diff --git a/Assembly.cpp b/Assembly.cpp index d8b6673..99bac20 100644 --- a/Assembly.cpp +++ b/Assembly.cpp @@ -1,2191 +1,2218 @@ -#include -#include -#include -#include -#include "Assembly.h" -#include "Process_Read.h" -#include "CommandLines.h" -#include "Hash_Table.h" -#include "POA.h" -#include "Correct.h" -#include "htab.h" -#include "kthread.h" -#include "rcut.h" -#include "kalloc.h" -#include "ecovlp.h" - -void ha_get_candidates_interface(ha_abuf_t *ab, int64_t rid, UC_Read *ucr, overlap_region_alloc *overlap_list, overlap_region_alloc *overlap_list_hp, Candidates_list *cl, double bw_thres, -int max_n_chain, int keep_whole_chain, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* chain_idx, ma_hit_t_alloc* paf, ma_hit_t_alloc* rev_paf, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp); -void ha_get_ug_candidates(ha_abuf_t *ab, int64_t rid, ma_utg_t *u, ma_utg_v *ua, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, int max_n_chain, int keep_whole_chain, kvec_t_u8_warp* k_flag, -kvec_t_u64_warp* chain_idx, void *ha_flt_tab, ha_pt_t *ha_idx, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, double chain_match_rate); -void ha_sort_list_by_anchor(overlap_region_alloc *overlap_list); - -All_reads R_INF; -Debug_reads R_INF_FLAG; -all_ul_t UL_INF, ULG_INF; -uint32_t *het_cnt = NULL; -// uint32_t debug_out = 0; - -void get_corrected_read_from_cigar(Cigar_record* cigar, char* pre_read, int pre_length, char* new_read, int* new_length) -{ - int i, j; - int pre_i, new_i; - int operation, operation_length; - pre_i = new_i = 0; - int diff_char_i = 0; - - - for (i = 0; i < (long long)cigar->length; i++) - { - operation = Get_Cigar_Type(cigar->record[i]); - operation_length = Get_Cigar_Length(cigar->record[i]); - - if (operation == 0) - { - memcpy(new_read + new_i, pre_read + pre_i, operation_length); - pre_i = pre_i + operation_length; - new_i = new_i + operation_length; - } - else if (operation == 1) - { - - for (j = 0; j < operation_length; j++) - { - new_read[new_i] = Get_MisMatch_Base(cigar->lost_base[diff_char_i]); - new_i++; - diff_char_i++; - } - pre_i = pre_i + operation_length; - } - else if (operation == 3) - { - pre_i = pre_i + operation_length; - diff_char_i = diff_char_i + operation_length; - } - else if (operation == 2) - { - memcpy(new_read + new_i, cigar->lost_base + diff_char_i, operation_length); - new_i = new_i + operation_length; - diff_char_i = diff_char_i + operation_length; - } - } - *new_length = new_i; -} - -void get_uncorrected_read_from_cigar(Cigar_record* cigar, char* new_read, int new_length, char* pre_read, int* pre_length) -{ - int i, j; - int pre_i, new_i; - int operation, operation_length; - pre_i = new_i = 0; - int diff_char_i = 0; - - - for (i = 0; i < (long long)cigar->length; i++) - { - operation = Get_Cigar_Type(cigar->record[i]); - operation_length = Get_Cigar_Length(cigar->record[i]); - - - if (operation == 0) - { - memcpy(pre_read + pre_i, new_read + new_i, operation_length); - pre_i = pre_i + operation_length; - new_i = new_i + operation_length; - } - else if (operation == 1) - { - - for (j = 0; j < operation_length; j++) - { - pre_read[pre_i] = Get_Match_Base(cigar->lost_base[diff_char_i]); - pre_i++; - diff_char_i++; - } - new_i = new_i + operation_length; - } - else if (operation == 3) - { - memcpy(pre_read + pre_i, cigar->lost_base + diff_char_i, operation_length); - pre_i = pre_i + operation_length; - diff_char_i = diff_char_i + operation_length; - } - else if (operation == 2) - { - new_i = new_i + operation_length; - diff_char_i = diff_char_i + operation_length; - } - } - - *pre_length = pre_i; -} - -inline int get_cigar_errors(Cigar_record* cigar) -{ - int i; - int total_errors = 0; - for (i = 0; i < (long long)cigar->length; i++) - { - if (Get_Cigar_Type(cigar->record[i]) > 0) - { - total_errors = total_errors + Get_Cigar_Length(cigar->record[i]); - } - } - return total_errors; -} - -int debug_cigar(Cigar_record* cigar, char* pre_read, int pre_length, char* new_read, int new_length, int correct_base) -{ - int i; - int total_errors = 0; - for (i = 0; i < (long long)cigar->length; i++) - { - if (Get_Cigar_Type(cigar->record[i]) > 0) - { - total_errors = total_errors + Get_Cigar_Length(cigar->record[i]); - } - } - - if(total_errors!=correct_base) - { - fprintf(stderr, "total_errors: %d, correct_base: %d\n", total_errors, correct_base); - } - - int pre_i, new_i; - int operation, operation_length; - pre_i = new_i = 0; - - for (i = 0; i < (long long)cigar->length; i++) - { - operation = Get_Cigar_Type(cigar->record[i]); - operation_length = Get_Cigar_Length(cigar->record[i]); - - if (operation == 0) - { - pre_i = pre_i + operation_length; - new_i = new_i + operation_length; - } - - if (operation == 1) - { - pre_i = pre_i + operation_length; - new_i = new_i + operation_length; - } - - if (operation == 3) - { - pre_i = pre_i + operation_length; - } - - if (operation == 2) - { - new_i = new_i + operation_length; - } - - } - - if (pre_i != pre_length) - { - fprintf(stderr, "pre_i: %d, pre_length: %d\n", pre_i, pre_length); - } - - - if(new_i != new_length) - { - fprintf(stderr, "new_i: %d, new_length: %d\n", new_i, new_length); - } - - return 1; - - char* tmp_seq = (char*)malloc(new_length + pre_length); - int tmp_length; - - get_corrected_read_from_cigar(cigar, pre_read, pre_length, tmp_seq, &tmp_length); - - if(tmp_length != new_length) - { - fprintf(stderr, "tmp_length: %d, new_length: %d\n", tmp_length, new_length); - } - - if(memcmp(new_read, tmp_seq, new_length)!=0) - { - fprintf(stderr, "error new string\n"); - } - - - get_uncorrected_read_from_cigar(cigar, new_read, new_length, tmp_seq, &tmp_length); - - - if(tmp_length != pre_length) - { - fprintf(stderr, "tmp_length: %d, pre_length: %d\n", tmp_length, pre_length); - } - - if(memcmp(pre_read, tmp_seq, pre_length)!=0) - { - fprintf(stderr, "error pre string\n"); - } - - - free(tmp_seq); - - if((int)cigar->new_read_length != new_length) - { - fprintf(stderr, "cigar->new_read_length: %d, new_length: %d\n", cigar->new_read_length, new_length); - } -} - - -inline void push_cigar(Compressed_Cigar_record* records, long long ID, Cigar_record* input) -{ - if (input->length > records[ID].size) - { - records[ID].size = input->length; - records[ID].record = (uint32_t*)realloc(records[ID].record, records[ID].size*sizeof(uint32_t)); - } - records[ID].length = input->length; - memcpy(records[ID].record, input->record, input->length*sizeof(uint32_t)); - - if (input->lost_base_length > records[ID].lost_base_size) - { - records[ID].lost_base_size = input->lost_base_length; - records[ID].lost_base = (char*)realloc(records[ID].lost_base, records[ID].lost_base_size); - } - records[ID].lost_base_length = input->lost_base_length; - memcpy(records[ID].lost_base, input->lost_base, input->lost_base_length); - - records[ID].new_length = input->new_read_length; -} - - -void push_overlaps(ma_hit_t_alloc* paf, overlap_region_alloc* overlap_list, int flag, All_reads* R_INF, int if_reverse) -{ - long long i = 0, xLen, yLen; - int32_t size = 0; - ma_hit_t tmp; - for (i = 0; i < (long long)overlap_list->length; ++i) - if (overlap_list->list[i].is_match == flag) - ++size; - resize_ma_hit_t_alloc(paf, size); - clear_ma_hit_t_alloc(paf); - for (i = 0; i < (long long)overlap_list->length; i++) - { - if (overlap_list->list[i].is_match == flag) - { - xLen = Get_READ_LENGTH((*R_INF), overlap_list->list[i].x_id); - yLen = Get_READ_LENGTH((*R_INF), overlap_list->list[i].y_id); - - tmp.qns = overlap_list->list[i].x_id; - tmp.qns = tmp.qns << 32; - tmp.tn = overlap_list->list[i].y_id; - - if(if_reverse != 0) - { - tmp.qns = tmp.qns | (uint64_t)(xLen - overlap_list->list[i].x_pos_s - 1); - tmp.qe = xLen - overlap_list->list[i].x_pos_e - 1; - tmp.ts = yLen - overlap_list->list[i].y_pos_s - 1; - tmp.te = yLen - overlap_list->list[i].y_pos_e - 1; - } - else - { - tmp.qns = tmp.qns | (uint64_t)(overlap_list->list[i].x_pos_s); - tmp.qe = overlap_list->list[i].x_pos_e; - tmp.ts = overlap_list->list[i].y_pos_s; - tmp.te = overlap_list->list[i].y_pos_e; - } - - ///for overlap_list, the x_strand of all overlaps are 0, so the tmp.rev is the same as the y_strand - tmp.rev = overlap_list->list[i].y_pos_strand; - - ///tmp.bl = R_INF.read_length[overlap_list->list[i].y_id]; - tmp.bl = Get_READ_LENGTH((*R_INF), overlap_list->list[i].y_id); - tmp.ml = overlap_list->list[i].strong; - tmp.no_l_indel = overlap_list->list[i].without_large_indel; - - add_ma_hit_t_alloc(paf, &tmp); - } - } -} - - -long long push_final_overlaps(ma_hit_t_alloc* paf, ma_hit_t_alloc* reverse_paf_list, overlap_region_alloc* overlap_list, int flag) -{ - long long i = 0; - long long available_overlaps = 0; - ma_hit_t tmp; - clear_ma_hit_t_alloc(paf); // paf has been preallocated, so we don't need preallocation - for (i = 0; i < (long long)overlap_list->length; i++) - { - if (overlap_list->list[i].is_match == flag) - { - available_overlaps++; - /**********************query***************************/ - //the interval of overlap is half-open [start, end) - tmp.qns = overlap_list->list[i].x_id; - tmp.qns = tmp.qns << 32; - tmp.qns = tmp.qns | (uint64_t)(overlap_list->list[i].x_pos_s); - ///the end pos is open - tmp.qe = overlap_list->list[i].x_pos_e + 1; - /**********************query***************************/ - - - - ///for overlap_list, the x_strand of all overlaps are 0, so the tmp.rev is the same as the y_strand - tmp.rev = overlap_list->list[i].y_pos_strand; - - - /**********************target***************************/ - tmp.tn = overlap_list->list[i].y_id; - if(tmp.rev == 1) - { - long long y_readLen = R_INF.read_length[overlap_list->list[i].y_id]; - tmp.ts = y_readLen - overlap_list->list[i].y_pos_e - 1; - tmp.te = y_readLen - overlap_list->list[i].y_pos_s - 1; - } - else - { - tmp.ts = overlap_list->list[i].y_pos_s; - tmp.te = overlap_list->list[i].y_pos_e; - } - ///the end pos is open - tmp.te++; - /**********************target***************************/ - - tmp.bl = R_INF.read_length[overlap_list->list[i].y_id]; - tmp.ml = overlap_list->list[i].strong; - tmp.no_l_indel = overlap_list->list[i].without_large_indel; - - tmp.el = overlap_list->list[i].shared_seed; - - add_ma_hit_t_alloc(paf, &tmp); - } - } - - return available_overlaps; -} - - - -long long push_final_overlaps_increment(ma_hit_t_alloc* paf, ma_hit_t_alloc* reverse_paf_list, overlap_region_alloc* overlap_list, int flag) -{ - long long i = 0; - long long available_overlaps = paf->length; - ma_hit_t tmp; - ///clear_ma_hit_t_alloc(paf); // paf has been preallocated, so we don't need preallocation - for (i = 0; i < (long long)overlap_list->length; i++) - { - if (overlap_list->list[i].is_match == flag) - { - available_overlaps++; - /**********************query***************************/ - //the interval of overlap is half-open [start, end) - tmp.qns = overlap_list->list[i].x_id; - tmp.qns = tmp.qns << 32; - tmp.qns = tmp.qns | (uint64_t)(overlap_list->list[i].x_pos_s); - ///the end pos is open - tmp.qe = overlap_list->list[i].x_pos_e + 1; - /**********************query***************************/ - - - - ///for overlap_list, the x_strand of all overlaps are 0, so the tmp.rev is the same as the y_strand - tmp.rev = overlap_list->list[i].y_pos_strand; - - - /**********************target***************************/ - tmp.tn = overlap_list->list[i].y_id; - if(tmp.rev == 1) - { - long long y_readLen = R_INF.read_length[overlap_list->list[i].y_id]; - tmp.ts = y_readLen - overlap_list->list[i].y_pos_e - 1; - tmp.te = y_readLen - overlap_list->list[i].y_pos_s - 1; - } - else - { - tmp.ts = overlap_list->list[i].y_pos_s; - tmp.te = overlap_list->list[i].y_pos_e; - } - ///the end pos is open - tmp.te++; - /**********************target***************************/ - - tmp.bl = R_INF.read_length[overlap_list->list[i].y_id]; - tmp.ml = overlap_list->list[i].strong; - tmp.no_l_indel = overlap_list->list[i].without_large_indel; - - tmp.el = overlap_list->list[i].shared_seed; - - add_ma_hit_t_alloc(paf, &tmp); - } - } - - return available_overlaps; -} - -ha_ovec_buf_t *ha_ovec_buf_init(void *km, int is_final, int save_ov, int is_ug) -{ - ha_ovec_buf_t *b; - KCALLOC(km, b, 1); - b->is_final = !!is_final, b->save_ov = !!save_ov; - init_UC_Read(&b->self_read);//set 0 - init_UC_Read(&b->ovlp_read);//set 0 - init_Candidates_list(&b->clist);//set 0 - memset(&b->olist, 0, sizeof(overlap_region_alloc)); - memset(&b->olist_hp, 0, sizeof(overlap_region_alloc)); - // init_overlap_region_alloc(&b->olist); - // init_overlap_region_alloc(&b->olist_hp); - init_fake_cigar(&(b->tmp_region.f_cigar));//set 0 - kv_init(b->b_buf.a);//set 0 - kv_init(b->r_buf.a);//set 0 - kv_init(b->k_flag.a);//set 0 - kv_init(b->sp);//set 0 - if(!is_ug) b->ab = ha_abuf_init_buf(km); - else b->abl = ha_abufl_init_buf(km); - if (!b->is_final) { - init_Cigar_record_buf(&b->cigar1, km); - // init_Graph(&b->POA_Graph); - // init_Graph(&b->DAGCon); - init_Correct_dumy_buf(&b->correct, km);//set 0 - InitHaplotypeEvdience_buf(&b->hap, km); - init_Round2_alignment_buf(&b->round2, km); - } - return b; -} - -ha_ovec_buf_t *ha_ovec_init(int is_final, int save_ov, int is_ug) -{ - ha_ovec_buf_t *b; - CALLOC(b, 1); - b->is_final = !!is_final, b->save_ov = !!save_ov; - init_UC_Read(&b->self_read); - init_UC_Read(&b->ovlp_read); - init_Candidates_list(&b->clist); - init_overlap_region_alloc(&b->olist); - init_overlap_region_alloc(&b->olist_hp); - init_fake_cigar(&(b->tmp_region.f_cigar)); - memset(&(b->tmp_region.w_list), 0, sizeof(b->tmp_region.w_list)); - CALLOC(b->tmp_region.w_list.a, 1); b->tmp_region.w_list.n = b->tmp_region.w_list.m = 1; - kv_init(b->b_buf.a); - kv_init(b->r_buf.a); - kv_init(b->k_flag.a); - kv_init(b->sp); - init_bit_extz_t(&(b->exz), 31); - if(!is_ug) b->ab = ha_abuf_init(); - else b->abl = ha_abufl_init(); - if (!b->is_final) { - init_Cigar_record(&b->cigar1); - init_Graph(&b->POA_Graph); - init_Graph(&b->DAGCon); - init_Correct_dumy(&b->correct); - InitHaplotypeEvdience(&b->hap); - init_Round2_alignment(&b->round2); - } - return b; -} - -void ha_ovec_destroy(ha_ovec_buf_t *b) -{ - destory_UC_Read(&b->self_read); - destory_UC_Read(&b->ovlp_read); - destory_Candidates_list(&b->clist); - destory_overlap_region_alloc(&b->olist); - destory_overlap_region_alloc(&b->olist_hp); - ha_abuf_destroy(b->ab); - ha_abufl_destroy(b->abl); - destory_fake_cigar(&(b->tmp_region.f_cigar)); - free(b->tmp_region.w_list.a); free(b->tmp_region.w_list.c.a); - kv_destroy(b->b_buf.a); - kv_destroy(b->r_buf.a); - kv_destroy(b->k_flag.a); - kv_destroy(b->sp); - destroy_bit_extz_t(&(b->exz)); - if (!b->is_final) { - destory_Cigar_record(&b->cigar1); - destory_Graph(&b->POA_Graph); - destory_Graph(&b->DAGCon); - destory_Correct_dumy(&b->correct); - destoryHaplotypeEvdience(&b->hap); - destory_Round2_alignment(&b->round2); - } - free(b); -} - -static int64_t ha_Graph_mem(const Graph *g) -{ - int64_t i, mem = 0; - mem = sizeof(Graph) + g->node_q.size * 8 + g->g_nodes.size * sizeof(Node); - for (i = 0; i < (int64_t)g->g_nodes.size; ++i) { - Node *n = &g->g_nodes.list[i]; - mem += n->mismatch_edges.size * sizeof(Edge); - mem += n->deletion_edges.size * sizeof(Edge); - mem += n->insertion_edges.size * sizeof(Edge); - } - mem += g->g_nodes.sort.size * 9; - return mem; -} - -int64_t ha_ovec_mem(const ha_ovec_buf_t *b, int64_t *mem_a) -{ - int64_t i, mem_ab = 0, mem_clist, mem_olist, mem_hap = 0, mem_aux = 0; - // mem_clist = b->clist.size * sizeof(k_mer_hit) + b->clist.chainDP.size * 7 * 4; - mem_clist = (b->clist.size * sizeof(k_mer_hit)) + ((sizeof((*b->clist.chainDP.score)) + sizeof((*b->clist.chainDP.pre)) - + sizeof((*b->clist.chainDP.indels)) + sizeof((*b->clist.chainDP.self_length)) - + sizeof((*b->clist.chainDP.occ)) + sizeof((*b->clist.chainDP.tmp))) * b->clist.chainDP.size); - mem_clist += sizeof(*(b->b_buf.a.a)) * b->b_buf.a.m; - mem_clist += sizeof(*(b->r_buf.a.a)) * b->r_buf.a.m; - mem_clist += sizeof(*(b->k_flag.a.a)) * b->k_flag.a.m; - mem_clist += sizeof(*(b->sp.a)) * b->sp.m; - mem_clist += sizeof(*(b->tmp_region.f_cigar.buffer)) * b->tmp_region.f_cigar.size; - mem_clist += sizeof(*(b->tmp_region.w_list.a)) * b->tmp_region.w_list.n; - mem_clist += sizeof(*(b->tmp_region.w_list.c.a)) * b->tmp_region.w_list.c.n; - - mem_olist = b->olist.size * sizeof(overlap_region); - for (i = 0; i < (int64_t)b->olist.size; ++i) { - const overlap_region *r = &b->olist.list[i]; - mem_olist += (r->w_list.n*sizeof(*(r->w_list.a))) + (r->w_list.c.n*sizeof(*(r->w_list.c.a))); - mem_olist += r->f_cigar.size * 8; - mem_olist += (r->boundary_cigars.n*sizeof(*(r->boundary_cigars.a))) - + (r->boundary_cigars.c.n*sizeof(*(r->boundary_cigars.c.a))); - } - - mem_olist += b->olist_hp.size * sizeof(overlap_region); - for (i = 0; i < (int64_t)b->olist_hp.size; ++i) { - const overlap_region *r = &b->olist_hp.list[i]; - mem_olist += (r->w_list.n*sizeof(*(r->w_list.a))) + (r->w_list.c.n*sizeof(*(r->w_list.c.a))); - mem_olist += r->f_cigar.size * 8; - mem_olist += (r->boundary_cigars.n*sizeof(*(r->boundary_cigars.a))) - + (r->boundary_cigars.c.n*sizeof(*(r->boundary_cigars.c.a))); - } - - if(b->ab) mem_ab += ha_abuf_mem(b->ab); - if(b->abl) mem_ab += ha_abufl_mem(b->abl); - - if (!b->is_final) { - mem_hap += sizeof(Cigar_record) + b->cigar1.lost_base_size + b->cigar1.size * 4; - mem_hap += sizeof(Correct_dumy) + b->correct.size * 8; - mem_hap += sizeof(Round2_alignment) + b->round2.cigar.size * 4 + b->round2.tmp_cigar.size * 4; - mem_hap += sizeof(haplotype_evdience_alloc) + b->hap.size * sizeof(haplotype_evdience) + b->hap.snp_matrix_size + b->hap.r_snp_size + b->hap.snp_stat.m * sizeof(SnpStats) + b->hap.snp_srt.m * sizeof(uint64_t); - mem_hap += ha_Graph_mem(&b->POA_Graph); - mem_hap += ha_Graph_mem(&b->DAGCon); - } - - - mem_aux += sizeof(*(b->self_read.seq)) * b->self_read.size; - mem_aux += sizeof(*(b->ovlp_read.seq)) * b->ovlp_read.size; - - if(mem_a) { - mem_a[0] = mem_ab; mem_a[1] = mem_clist; mem_a[2] = mem_olist; - mem_a[3] = mem_hap; mem_a[4] = mem_aux; - } - - return mem_ab + mem_clist + mem_olist + mem_hap + mem_aux; -} - -uint32_t get_het_cnt(haplotype_evdience_alloc *hap) -{ - uint32_t i, cnt; - for (i = cnt = 0; i < hap->snp_stat.n; i++) { - if(hap->snp_stat.a[i].score == 1 && (!(hap->snp_stat.a[i].occ_0 < 2 || hap->snp_stat.a[i].occ_1 < 2))) { - cnt++; - } - } - return cnt; -} - -static void worker_ovec(void *data, long i, int tid) -{ - ha_ovec_buf_t *b = ((ha_ovec_buf_t**)data)[tid]; - int fully_cov, abnormal; - // if(i != 12578) return; - // fprintf(stderr, "[M::%s-beg] rid->%ld\n", __func__, i); - // if (memcmp("7897e875-76e5-42c8-bc37-94b370c4cc8d", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { - // fprintf(stderr, "[M::%s-beg] rid->%ld\n", __func__, i); - // } else { - // return; - // } - - ha_get_candidates_interface(b->ab, i, &b->self_read, &b->olist, &b->olist_hp, &b->clist, - 0.02, asm_opt.max_n_chain, 1, NULL/**&(b->k_flag)**/, &b->r_buf, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), &(b->tmp_region), NULL, &(b->sp)); - - // prt_chain(&b->olist); - // return; - - clear_Cigar_record(&b->cigar1); - clear_Round2_alignment(&b->round2); - - correct_overlap(&b->olist, &R_INF, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, - &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 1, &fully_cov, &abnormal); - - b->num_read_base += b->self_read.length; - b->num_correct_base += b->correct.corrected_base; - b->num_recorrect_base += b->round2.dumy.corrected_base; - - push_cigar(R_INF.cigars, i, &b->cigar1); - push_cigar(R_INF.second_round_cigar, i, &b->round2.cigar); - - R_INF.paf[i].is_fully_corrected = 0; - if (fully_cov) { - if (get_cigar_errors(&b->cigar1) == 0 && get_cigar_errors(&b->round2.cigar) == 0) - R_INF.paf[i].is_fully_corrected = 1; - } - R_INF.paf[i].is_abnormal = abnormal; - - R_INF.trio_flag[i] = AMBIGU; - - ///need to be fixed in r305 - // if(ha_idx_hp == NULL) - // { - // R_INF.trio_flag[i] += collect_hp_regions(&b->olist, &R_INF, &(b->k_flag), RESEED_HP_RATE, Get_READ_LENGTH(R_INF, i), NULL); - // } - - if (R_INF.trio_flag[i] != AMBIGU || b->save_ov) { - int is_rev = (asm_opt.number_of_round % 2 == 0); - push_overlaps(&(R_INF.paf[i]), &b->olist, 1, &R_INF, is_rev); - push_overlaps(&(R_INF.reverse_paf[i]), &b->olist, 2, &R_INF, is_rev); - } - - if(het_cnt) het_cnt[i] = get_het_cnt(&b->hap); - // fprintf(stderr, "[M::%s-end] rid->%ld\n", __func__, i); -} - - -static void worker_ovec_cal0(void *data, long i, int tid) -{ - ha_ovec_buf_t *b = ((ha_ovec_buf_t**)data)[tid]; - int fully_cov, abnormal; - - ha_get_candidates_interface(b->ab, i, &b->self_read, &b->olist, &b->olist_hp, &b->clist, - 0.02, asm_opt.max_n_chain, 1, NULL/**&(b->k_flag)**/, &b->r_buf, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), &(b->tmp_region), NULL, &(b->sp)); - - clear_Cigar_record(&b->cigar1); - clear_Round2_alignment(&b->round2); - - correct_overlap(&b->olist, &R_INF, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, - &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 0/**1***/, &fully_cov, &abnormal); - - b->num_read_base += b->self_read.length; - b->num_correct_base += b->correct.corrected_base; - b->num_recorrect_base += b->round2.dumy.corrected_base; - - - // R_INF.paf[i].is_fully_corrected = 0; - // R_INF.paf[i].is_abnormal = abnormal; - R_INF.trio_flag[i] = AMBIGU; - - // R_INF.paf[i].is_fully_corrected = 0; - // if (fully_cov) { - // if (get_cigar_errors(&b->cigar1) == 0 && get_cigar_errors(&b->round2.cigar) == 0) - // R_INF.paf[i].is_fully_corrected = 1; - // } - // R_INF.paf[i].is_abnormal = abnormal; - // R_INF.trio_flag[i] = AMBIGU; - - push_final_overlaps(&(R_INF.paf[i]), R_INF.reverse_paf, &b->olist, 1); - push_final_overlaps(&(R_INF.reverse_paf[i]), R_INF.reverse_paf, &b->olist, 2); - - if(het_cnt) het_cnt[i] = get_het_cnt(&b->hap); -} - - -static void worker_ovec_related_reads(void *data, long i, int tid) -{ - ha_ovec_buf_t *b = ((ha_ovec_buf_t**)data)[tid]; - - uint64_t k, queryNameLen; - for (k = 0; k < R_INF_FLAG.query_num; k++) - { - queryNameLen = strlen(R_INF_FLAG.read_name[k]); - if (queryNameLen != Get_NAME_LENGTH((R_INF),i)) continue; - if (memcmp(R_INF_FLAG.read_name[k], Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) - { - break; - } - } - - if(k < R_INF_FLAG.query_num) - { - R_INF_FLAG.read_id[k] = i; - int fully_cov, abnormal, q_idx = k; - - ha_get_candidates_interface(b->ab, i, &b->self_read, &b->olist, &b->olist_hp, &b->clist, - 0.02, asm_opt.max_n_chain, 1, NULL/**&(b->k_flag)**/, &b->r_buf, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), &(b->tmp_region), &(R_INF_FLAG.candidate_count[q_idx]), &(b->sp)); - - clear_Cigar_record(&b->cigar1); - clear_Round2_alignment(&b->round2); - - correct_overlap(&b->olist, &R_INF, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, - &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 1, &fully_cov, &abnormal); - - b->num_read_base += b->self_read.length; - b->num_correct_base += b->correct.corrected_base; - b->num_recorrect_base += b->round2.dumy.corrected_base; - - push_cigar(R_INF.cigars, i, &b->cigar1); - push_cigar(R_INF.second_round_cigar, i, &b->round2.cigar); - - R_INF.paf[i].is_fully_corrected = 0; - if (fully_cov) { - if (get_cigar_errors(&b->cigar1) == 0 && get_cigar_errors(&b->round2.cigar) == 0) - R_INF.paf[i].is_fully_corrected = 1; - } - R_INF.paf[i].is_abnormal = abnormal; - - - - pthread_mutex_lock(&R_INF_FLAG.OutputMutex); - - fprintf(R_INF_FLAG.fp, "\n>%.*s, rid: %ld\n", (int)Get_NAME_LENGTH((R_INF), i), Get_NAME((R_INF), i), i); - fprintf(R_INF_FLAG.fp, "%d-th round, len: %lu, hom_cov: %d, max_n_chain: %d\n", - asm_opt.number_of_round, Get_READ_LENGTH(R_INF, i), asm_opt.hom_cov, asm_opt.max_n_chain); - - fprintf(R_INF_FLAG.fp, "***************************k-mer counts (%d)***************************\n", (int)(R_INF_FLAG.candidate_count[q_idx].a.n)); - - sort_kvec_t_u64_warp(&(R_INF_FLAG.candidate_count[q_idx]), 0); - for (k = 0; k < R_INF_FLAG.candidate_count[q_idx].a.n; k++) - { - fprintf(R_INF_FLAG.fp, "[%lu] Count(%u): %lu, filtered: %lu\n", k, - (uint32_t)R_INF_FLAG.candidate_count[q_idx].a.a[k], R_INF_FLAG.candidate_count[q_idx].a.a[k]>>33, - (R_INF_FLAG.candidate_count[q_idx].a.a[k]>>32)&(uint64_t)1); - } - - - fprintf(R_INF_FLAG.fp, "***************************forward ovlp***************************\n"); - for (k = 0; k < b->olist.length; k++) - { - if(b->olist.list[k].is_match != 1) continue; - fprintf(R_INF_FLAG.fp, "%.*s\n", (int)Get_NAME_LENGTH((R_INF), b->olist.list[k].y_id), Get_NAME((R_INF), b->olist.list[k].y_id)); - fprintf(R_INF_FLAG.fp, "qs: %u, qe: %u, ts: %u, te: %u, rev: %u, strong: %u, no_l_indel: %u, len: %lu\n", - b->olist.list[k].x_pos_s, b->olist.list[k].x_pos_e, b->olist.list[k].y_pos_s, b->olist.list[k].y_pos_e, - b->olist.list[k].y_pos_strand, b->olist.list[k].strong, b->olist.list[k].without_large_indel, - Get_READ_LENGTH(R_INF, b->olist.list[k].y_id)); - } - - fprintf(R_INF_FLAG.fp, "***************************reverse ovlp***************************\n"); - for (k = 0; k < b->olist.length; k++) - { - if(b->olist.list[k].is_match != 2) continue; - fprintf(R_INF_FLAG.fp, "%.*s\n", (int)Get_NAME_LENGTH((R_INF), b->olist.list[k].y_id), Get_NAME((R_INF), b->olist.list[k].y_id)); - fprintf(R_INF_FLAG.fp, "qs: %u, qe: %u, ts: %u, te: %u, rev: %u, strong: %u, no_l_indel: %u, len: %lu\n", - b->olist.list[k].x_pos_s, b->olist.list[k].x_pos_e, b->olist.list[k].y_pos_s, b->olist.list[k].y_pos_e, - b->olist.list[k].y_pos_strand, b->olist.list[k].strong, b->olist.list[k].without_large_indel, - Get_READ_LENGTH(R_INF, b->olist.list[k].y_id)); - } - - /** - fprintf(R_INF_FLAG.fp, "***************************unmatched ovlp***************************\n"); - for (k = 0; k < b->olist.length; k++) - { - if(b->olist.list[k].is_match == 1) continue; - if(b->olist.list[k].is_match == 2) continue; - fprintf(R_INF_FLAG.fp, "%.*s\n", (int)Get_NAME_LENGTH((R_INF), b->olist.list[k].y_id), Get_NAME((R_INF), b->olist.list[k].y_id)); - fprintf(R_INF_FLAG.fp, "qs: %u, qe: %u, ts: %u, te: %u, rev: %u, strong: %u, no_l_indel: %u, len: %lu\n", - b->olist.list[k].x_pos_s, b->olist.list[k].x_pos_e, b->olist.list[k].y_pos_s, b->olist.list[k].y_pos_e, - b->olist.list[k].y_pos_strand, b->olist.list[k].strong, b->olist.list[k].without_large_indel, - Get_READ_LENGTH(R_INF, b->olist.list[k].y_id)); - } - **/ - - R_INF.trio_flag[i] = AMBIGU; - - ///need to be fixed in r305 - // if(ha_idx_hp == NULL) - // { - // R_INF.trio_flag[i] += collect_hp_regions(&b->olist, &R_INF, &(b->k_flag), RESEED_HP_RATE, Get_READ_LENGTH(R_INF, i), R_INF_FLAG.fp); - // } - - fprintf(R_INF_FLAG.fp, "R_INF.trio_flag[%ld]: %u\n", i, R_INF.trio_flag[i]); - - - pthread_mutex_unlock(&R_INF_FLAG.OutputMutex); - } -} - - -static inline long long get_N_occ(char* seq, long long length) -{ - long long j, N_occ = 0; - for (j = 0; j < length; j++) - if(seq_nt6_table[(uint8_t)seq[j]] >= 4) - N_occ++; - return N_occ; -} - -typedef struct { - UC_Read g_read; - int first_round_read_size; - int second_round_read_size; - char *first_round_read; - char *second_round_read; -} ha_ecsave_buf_t; - -static void worker_ec_save(void *data, long i, int tid) -{ - ha_ecsave_buf_t *e = (ha_ecsave_buf_t*)data + tid; - - Cigar_record cigar; - int first_round_read_length; - int second_round_read_length; - uint64_t N_occ; - - char *new_read; - int new_read_length; - - recover_UC_Read(&e->g_read, &R_INF, i); - - // round 1 - if ((long long)R_INF.cigars[i].new_length > e->first_round_read_size) { - e->first_round_read_size = R_INF.cigars[i].new_length; - REALLOC(e->first_round_read, e->first_round_read_size); - } - - cigar.length = R_INF.cigars[i].length; - cigar.lost_base_length = R_INF.cigars[i].lost_base_length; - cigar.record = R_INF.cigars[i].record; - cigar.lost_base = R_INF.cigars[i].lost_base; - - get_corrected_read_from_cigar(&cigar, e->g_read.seq, e->g_read.length, e->first_round_read, &first_round_read_length); - - // round 2 - if ((long long)R_INF.second_round_cigar[i].new_length > e->second_round_read_size) { - e->second_round_read_size = R_INF.second_round_cigar[i].new_length; - REALLOC(e->second_round_read, e->second_round_read_size); - } - cigar.length = R_INF.second_round_cigar[i].length; - cigar.lost_base_length = R_INF.second_round_cigar[i].lost_base_length; - cigar.record = R_INF.second_round_cigar[i].record; - cigar.lost_base = R_INF.second_round_cigar[i].lost_base; - - get_corrected_read_from_cigar(&cigar, e->first_round_read, first_round_read_length, e->second_round_read, &second_round_read_length); - - new_read = e->second_round_read; - new_read_length = second_round_read_length; - - if (asm_opt.roundID != asm_opt.number_of_round - 1) - { - ///need modification - reverse_complement(new_read, new_read_length); - } - else if(asm_opt.number_of_round % 2 == 0) - { - ///need modification - reverse_complement(new_read, new_read_length); - } - - N_occ = get_N_occ(new_read, new_read_length); - - if ((long long)R_INF.read_size[i] < new_read_length) { - R_INF.read_size[i] = new_read_length; - REALLOC(R_INF.read_sperate[i], R_INF.read_size[i]/4+1); - } - R_INF.read_length[i] = new_read_length; - ha_compress_base(Get_READ(R_INF, i), new_read, new_read_length, &R_INF.N_site[i], N_occ); -} - -void Output_corrected_reads() -{ - long long i; - UC_Read g_read; - init_UC_Read(&g_read); - char* gfa_name = (char*)malloc(strlen(asm_opt.output_file_name)+35); - sprintf(gfa_name, "%s.ec.fa", asm_opt.output_file_name); - FILE* output_file = fopen(gfa_name, "w"); - free(gfa_name); - - for (i = 0; i < (long long)R_INF.total_reads; i++) - { - recover_UC_Read(&g_read, &R_INF, i); - fwrite(">", 1, 1, output_file); - fwrite(Get_NAME(R_INF, i), 1, Get_NAME_LENGTH(R_INF, i), output_file); - fwrite("\n", 1, 1, output_file); - fwrite(g_read.seq, 1, g_read.length, output_file); - fwrite("\n", 1, 1, output_file); - } - destory_UC_Read(&g_read); - fclose(output_file); -} - -void Output_corrected_fastq() -{ - long long i; uint64_t k; - UC_Read g_read; asg8_v dv; - init_UC_Read(&g_read); kv_init(dv); - char* gfa_name = (char*)malloc(strlen(asm_opt.output_file_name)+35); - sprintf(gfa_name, "%s.ec.fq", asm_opt.output_file_name); - FILE* fp = fopen(gfa_name, "w"); - free(gfa_name); - - for (i = 0; i < (long long)R_INF.total_reads; i++) { - recover_UC_Read(&g_read, &R_INF, i); - fprintf(fp, "@%.*s\n", (int32_t)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); - fprintf(fp, "%.*s\n", (int32_t)g_read.length, g_read.seq); - fprintf(fp, "+\n"); - retrive_bqual(&dv, NULL, i, -1, -1, 0, sc_bn); - for (k = 0; k < dv.n; k++) fprintf(fp, "%c", (char)(sc_tb[dv.a[k]] + 33 - 1)); - fprintf(fp, "\n"); - } - destory_UC_Read(&g_read); kv_destroy(dv); - fclose(fp); -} - -void debug_print_pob_regions() -{ - uint64_t i, total = 0; - for (i = 0; i < R_INF.total_reads; i++) - { - if(R_INF.trio_flag[i]!=AMBIGU) - { - total++; - fprintf(stderr, "(%lu) %.*s\n", i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); - } - } - fprintf(stderr, "total hp reads: %lu, R_INF.total_reads: %lu\n", total, R_INF.total_reads); - exit(1); -} - -void rescue_hp_reads(ha_ovec_buf_t **b) -{ - int hom_cov, het_cov; - ha_flt_tab_hp = ha_idx_hp = NULL; - if (!(asm_opt.flag & HA_F_NO_KMER_FLT)) { - ha_flt_tab_hp = ha_ft_gen(&asm_opt, &R_INF, &hom_cov, 1, 0); - } - ha_idx_hp = ha_pt_gen(&asm_opt, ha_flt_tab, 1, 1, &R_INF, &hom_cov, &het_cov); - - - if (asm_opt.required_read_name) - kt_for(asm_opt.thread_num, worker_ovec_related_reads, b, R_INF.total_reads); - else - kt_for(asm_opt.thread_num, worker_ovec, b, R_INF.total_reads); - - - - - ha_ft_destroy(ha_flt_tab_hp); ha_flt_tab_hp = NULL; - ha_pt_destroy(ha_idx_hp); ha_idx_hp = NULL; -} - - -void print_het_cnt_log(uint32_t *het_cnt) -{ - if(!het_cnt) return; - char* gfa_name = (char*)malloc(strlen(asm_opt.output_file_name)+35); - sprintf(gfa_name, "%s.het_cnt.log", asm_opt.output_file_name); - FILE* output_file = fopen(gfa_name, "w"); - fprintf(stderr, "[M::%s::] ==> print cnt of het sites to %s...\n", __func__, gfa_name); - free(gfa_name); - uint64_t i; - for (i = 0; i < R_INF.total_reads; i++){ - fprintf(output_file, ">%.*s\t%u\n", (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i), het_cnt[i]); - } - fclose(output_file); -} - -void prt_dbg_rs(FILE *fp, Debug_reads* x, uint64_t round) -{ - uint64_t k, id; UC_Read g_read; init_UC_Read(&g_read); - for (k = 0; k < R_INF_FLAG.query_num; k++) { - id = x->read_id[k]; - if(id == ((uint64_t)-1)) continue; - recover_UC_Read(&g_read, &R_INF, id); - fprintf(fp, ">%.*s_r%lu\n", (int)Get_NAME_LENGTH((R_INF), id), Get_NAME((R_INF), id), round); - fprintf(fp, "%.*s\n", (int)g_read.length, g_read.seq); - } - destory_UC_Read(&g_read); -} - -void ha_ec(int64_t round, int num_pround, int des_idx, uint64_t *tot_b, uint64_t *tot_e) -{ - int hom_cov, het_cov, r_out = 0; - ha_flt_tab_hp = ha_idx_hp = NULL; (*tot_b) = (*tot_e) = 0; - - if((ha_idx == NULL)&&(asm_opt.flag & HA_F_VERBOSE_GFA)&&(round == asm_opt.number_of_round - 1)) r_out = 1; - - if(asm_opt.required_read_name) init_Debug_reads(&R_INF_FLAG, asm_opt.required_read_name); // for debugging only - - if(ha_idx) hom_cov = asm_opt.hom_cov; - if(ha_idx == NULL) { - ha_idx = ha_pt_gen(&asm_opt, ha_flt_tab, round == 0? 0 : 1, 0, &R_INF, &hom_cov, &het_cov); // build the index - asm_opt.hom_cov = hom_cov; asm_opt.het_cov = het_cov; - } - ///debug_adapter(&asm_opt, &R_INF); - if (round == 0 && ha_flt_tab == 0) // then asm_opt.hom_cov hasn't been updated - ha_opt_update_cov(&asm_opt, hom_cov); - het_cnt = NULL; - if(round == asm_opt.number_of_round-1 && asm_opt.is_dbg_het_cnt) CALLOC(het_cnt, R_INF.total_reads); - - if (r_out) write_pt_index(ha_flt_tab, ha_idx, &R_INF, &asm_opt, asm_opt.output_file_name); - - // Output_corrected_fastq(); - - - cal_ec_r(asm_opt.thread_num, round, num_pround, R_INF.total_reads, (round == (asm_opt.number_of_round-1))?1:0, tot_b, tot_e); - - // exit(1); - - // if (r_out) write_pt_index(ha_flt_tab, ha_idx, &R_INF, &asm_opt, asm_opt.output_file_name); - if(des_idx) { - ha_pt_destroy(ha_idx); ha_idx = NULL; - } - - - if(het_cnt) { - print_het_cnt_log(het_cnt); free(het_cnt); het_cnt = NULL; - } - - // exit(1); - - - if (asm_opt.required_read_name) prt_dbg_rs(R_INF_FLAG.fp_r0, &R_INF_FLAG, 0); // for debugging only - - // save corrected reads to R_INF - // sl_ec_r(asm_opt.thread_num, R_INF.total_reads); - - if (asm_opt.required_read_name) prt_dbg_rs(R_INF_FLAG.fp_r1, &R_INF_FLAG, 1); // for debugging only - if (asm_opt.required_read_name) destory_Debug_reads(&R_INF_FLAG), exit(0); // for debugging only - ///debug_print_pob_regions(); - - // Output_corrected_reads(); - - // exit(1); -} - - -int ha_ec_dbg(void) -{ - int hom_cov, het_cov; - - ha_idx = ha_pt_gen(&asm_opt, 0, 0, 0, &R_INF, &hom_cov, &het_cov); // build the index - asm_opt.hom_cov = hom_cov; asm_opt.het_cov = het_cov; - ha_opt_update_cov(&asm_opt, hom_cov); - - cal_ec_r_dbg(asm_opt.thread_num, R_INF.total_reads); - - ha_pt_destroy(ha_idx); ha_idx = NULL; - - return 0; -} - -void ha_overlap_and_correct(int round) -{ - int i, hom_cov, het_cov, r_out = 0; - ha_ovec_buf_t **b; - ha_ecsave_buf_t *e; - ha_flt_tab_hp = ha_idx_hp = NULL; - - if((ha_idx == NULL)&&(asm_opt.flag & HA_F_VERBOSE_GFA)&&(round == asm_opt.number_of_round - 1)) - { - r_out = 1; - } - - if(asm_opt.required_read_name) init_Debug_reads(&R_INF_FLAG, asm_opt.required_read_name); // for debugging only - // overlap and correct reads - CALLOC(b, asm_opt.thread_num); - for (i = 0; i < asm_opt.thread_num; ++i) - b[i] = ha_ovec_init(0, (round == asm_opt.number_of_round - 1),0); - if(ha_idx) hom_cov = asm_opt.hom_cov; - if(ha_idx == NULL) ha_idx = ha_pt_gen(&asm_opt, ha_flt_tab, round == 0? 0 : 1, 0, &R_INF, &hom_cov, &het_cov); // build the index - ///debug_adapter(&asm_opt, &R_INF); - if (round == 0 && ha_flt_tab == 0) // then asm_opt.hom_cov hasn't been updated - ha_opt_update_cov(&asm_opt, hom_cov); - het_cnt = NULL; - if(round == asm_opt.number_of_round-1 && asm_opt.is_dbg_het_cnt) CALLOC(het_cnt, R_INF.total_reads); - // fprintf(stderr, "[M::%s-start]\n", __func__); - // double tt0 = yak_realtime_0(); - if (asm_opt.required_read_name) - kt_for(asm_opt.thread_num, worker_ovec_related_reads, b, R_INF.total_reads); - else - kt_for(asm_opt.thread_num, worker_ovec, b, R_INF.total_reads);///debug_for_fix - // fprintf(stderr, "[M::%s-end]\n", __func__); - // fprintf(stderr, "[M::%s::%.3f] ==> chaining\n", __func__, yak_realtime_0()-tt0); - // exit(1); - - if (r_out) write_pt_index(ha_flt_tab, ha_idx, &R_INF, &asm_opt, asm_opt.output_file_name); - ha_pt_destroy(ha_idx); - ha_idx = NULL; - - if(het_cnt) { - print_het_cnt_log(het_cnt); free(het_cnt); het_cnt = NULL; - } - - // collect statistics - for (i = 0; i < asm_opt.thread_num; ++i) { - asm_opt.num_bases += b[i]->num_read_base; - asm_opt.num_corrected_bases += b[i]->num_correct_base; - asm_opt.num_recorrected_bases += b[i]->num_recorrect_base; - asm_opt.mem_buf += ha_ovec_mem(b[i], NULL); - ha_ovec_destroy(b[i]); - } - free(b); - if (asm_opt.required_read_name) prt_dbg_rs(R_INF_FLAG.fp_r0, &R_INF_FLAG, 0); // for debugging only - - // save corrected reads to R_INF - CALLOC(e, asm_opt.thread_num); - for (i = 0; i < asm_opt.thread_num; ++i) { - init_UC_Read(&e[i].g_read); - e[i].first_round_read_size = e[i].second_round_read_size = 50000; - CALLOC(e[i].first_round_read, e[i].first_round_read_size); - CALLOC(e[i].second_round_read, e[i].second_round_read_size); - } - kt_for(asm_opt.thread_num, worker_ec_save, e, R_INF.total_reads); - for (i = 0; i < asm_opt.thread_num; ++i) { - destory_UC_Read(&e[i].g_read); - free(e[i].first_round_read); - free(e[i].second_round_read); - } - free(e); - - if (asm_opt.required_read_name) prt_dbg_rs(R_INF_FLAG.fp_r1, &R_INF_FLAG, 1); // for debugging only - if (asm_opt.required_read_name) destory_Debug_reads(&R_INF_FLAG), exit(0); // for debugging only - ///debug_print_pob_regions(); -} - -void ha_overlap_cal(int round, int read_from_store) -{ - int i, hom_cov, het_cov; - ha_ovec_buf_t **b; - ha_flt_tab_hp = ha_idx_hp = NULL; - - // overlap and correct reads - CALLOC(b, asm_opt.thread_num); - for (i = 0; i < asm_opt.thread_num; ++i) - b[i] = ha_ovec_init(0, (round == asm_opt.number_of_round - 1),0); - if(ha_idx) hom_cov = asm_opt.hom_cov; - if(ha_idx == NULL) ha_idx = ha_pt_gen(&asm_opt, ha_flt_tab, ((round == 0)&&(read_from_store == 0))?0:1, 0, &R_INF, &hom_cov, &het_cov); // build the index - ///debug_adapter(&asm_opt, &R_INF); - if (/**round == 0 &&**/ ha_flt_tab == 0) // then asm_opt.hom_cov hasn't been updated - ha_opt_update_cov(&asm_opt, hom_cov); - het_cnt = NULL; - if(round == asm_opt.number_of_round-1 && asm_opt.is_dbg_het_cnt) CALLOC(het_cnt, R_INF.total_reads); - // fprintf(stderr, "[M::%s-start]\n", __func__); - kt_for(asm_opt.thread_num, worker_ovec_cal0, b, R_INF.total_reads);///debug_for_fix - // fprintf(stderr, "[M::%s-end]\n", __func__); - - ha_pt_destroy(ha_idx); - ha_idx = NULL; - - if(het_cnt) { - print_het_cnt_log(het_cnt); free(het_cnt); het_cnt = NULL; - } - - // collect statistics - for (i = 0; i < asm_opt.thread_num; ++i) { - asm_opt.num_bases += b[i]->num_read_base; - asm_opt.num_corrected_bases += b[i]->num_correct_base; - asm_opt.num_recorrected_bases += b[i]->num_recorrect_base; - asm_opt.mem_buf += ha_ovec_mem(b[i], NULL); - ha_ovec_destroy(b[i]); - } - free(b); - asm_opt.hom_cov = hom_cov; - asm_opt.het_cov = het_cov; -} - - -void update_overlaps(overlap_region_alloc* overlap_list, ma_hit_t_alloc* paf, -UC_Read* g_read, UC_Read* overlap_read, int is_match, int is_exact) -{ - - uint64_t inner_j = 0; - uint64_t j = 0; - long long x_overlapLen, y_overlapLen; - while (j < overlap_list->length && inner_j < paf->length) - { - if(overlap_list->list[j].y_id < paf->buffer[inner_j].tn) - { - j++; - } - else if(overlap_list->list[j].y_id > paf->buffer[inner_j].tn) - { - inner_j++; - } - else - { - if(overlap_list->list[j].y_pos_strand == paf->buffer[inner_j].rev) - { - x_overlapLen = Get_qe(paf->buffer[inner_j]) - Get_qs(paf->buffer[inner_j]) + 1; - y_overlapLen = Get_te(paf->buffer[inner_j]) - Get_ts(paf->buffer[inner_j]) + 1; - if(x_overlapLen < y_overlapLen) x_overlapLen = y_overlapLen; - x_overlapLen = x_overlapLen * 0.1; - - // if( - // ((DIFF(overlap_list->list[j].x_pos_s, Get_qs(paf->buffer[inner_j])) < x_overlapLen) - // && (DIFF(overlap_list->list[j].x_pos_e, Get_qe(paf->buffer[inner_j])) < x_overlapLen)) - // || - // ((DIFF(overlap_list->list[j].y_pos_s, Get_ts(paf->buffer[inner_j])) < x_overlapLen) - // && (DIFF(overlap_list->list[j].y_pos_e, Get_te(paf->buffer[inner_j])) < x_overlapLen))) - if( - ((DIFF(overlap_list->list[j].x_pos_s, Get_qs(paf->buffer[inner_j])) < (uint64_t)x_overlapLen) - && (DIFF(overlap_list->list[j].x_pos_e, Get_qe(paf->buffer[inner_j])) < (uint64_t)x_overlapLen)) - || - ((DIFF(overlap_list->list[j].y_pos_s, Get_ts(paf->buffer[inner_j])) < (uint64_t)x_overlapLen) - && (DIFF(overlap_list->list[j].y_pos_e, Get_te(paf->buffer[inner_j])) < (uint64_t)x_overlapLen)) - ) - { - overlap_list->list[j].is_match = is_match; - overlap_list->list[j].strong = paf->buffer[inner_j].ml; - overlap_list->list[j].without_large_indel = paf->buffer[inner_j].no_l_indel; - if(is_exact == 1) - { - if(overlap_list->list[j].y_pos_strand == 0) - { - recover_UC_Read(overlap_read, &R_INF, overlap_list->list[j].y_id); - } - else - { - recover_UC_Read_RC(overlap_read, &R_INF, overlap_list->list[j].y_id); - } - if(if_exact_match(g_read->seq, g_read->length, overlap_read->seq, overlap_read->length, - overlap_list->list[j].x_pos_s, overlap_list->list[j].x_pos_e, - overlap_list->list[j].y_pos_s, overlap_list->list[j].y_pos_e)) - { - overlap_list->list[j].shared_seed = 1; - } - else - { - overlap_list->list[j].shared_seed = 0; - } - } - } - else - { - overlap_list->list[j].is_match = 3; - } - } - else - { - overlap_list->list[j].is_match = 3; - } - - j++; - inner_j++; - } - } -} - - -int check_chain_indels(Fake_Cigar* chain, long long xBeg, long long xEnd, float indel_rate) -{ - uint64_t i = 0; - long long indels = 0, xOffset; - if(chain->length != 0) - { - indels += abs(get_fake_gap_shift(chain, 0)); - xOffset = get_fake_gap_pos(chain, 0); - if(indels > (xOffset - xBeg + 1) * indel_rate) return 0; - - for (i = 1; i < chain->length; i++) - { - indels += abs((get_fake_gap_shift(chain, i) - get_fake_gap_shift(chain, i-1))); - xOffset = get_fake_gap_pos(chain, i); - if(indels > (xOffset - xBeg + 1) * indel_rate) return 0; - } - } - - if(indels > (xEnd - xBeg + 1) * indel_rate) return 0; - return 1; -} - -void update_overlaps_chain_width(overlap_region_alloc* overlap_list, ma_hit_t_alloc* paf, -UC_Read* g_read, UC_Read* overlap_read, int is_match, int is_exact, float indel_rate) -{ - - uint64_t inner_j = 0; - uint64_t j = 0; - long long x_overlapLen, y_overlapLen; - while (j < overlap_list->length && inner_j < paf->length) - { - if(overlap_list->list[j].y_id < paf->buffer[inner_j].tn) - { - j++; - } - else if(overlap_list->list[j].y_id > paf->buffer[inner_j].tn) - { - inner_j++; - } - else - { - if(check_chain_indels(&(overlap_list->list[j].f_cigar), overlap_list->list[j].x_pos_s, - overlap_list->list[j].x_pos_e, indel_rate) == 1) - { - if(overlap_list->list[j].y_pos_strand == paf->buffer[inner_j].rev) - { - x_overlapLen = Get_qe(paf->buffer[inner_j]) - Get_qs(paf->buffer[inner_j]) + 1; - y_overlapLen = Get_te(paf->buffer[inner_j]) - Get_ts(paf->buffer[inner_j]) + 1; - if(x_overlapLen < y_overlapLen) x_overlapLen = y_overlapLen; - x_overlapLen = x_overlapLen * 0.1; - - // if( - // ((DIFF(overlap_list->list[j].x_pos_s, Get_qs(paf->buffer[inner_j])) < x_overlapLen) - // && (DIFF(overlap_list->list[j].x_pos_e, Get_qe(paf->buffer[inner_j])) < x_overlapLen)) - // || - // ((DIFF(overlap_list->list[j].y_pos_s, Get_ts(paf->buffer[inner_j])) < x_overlapLen) - // && (DIFF(overlap_list->list[j].y_pos_e, Get_te(paf->buffer[inner_j])) < x_overlapLen))) - if( - ((DIFF(overlap_list->list[j].x_pos_s, Get_qs(paf->buffer[inner_j])) < (uint64_t)x_overlapLen) - && (DIFF(overlap_list->list[j].x_pos_e, Get_qe(paf->buffer[inner_j])) < (uint64_t)x_overlapLen)) - || - ((DIFF(overlap_list->list[j].y_pos_s, Get_ts(paf->buffer[inner_j])) < (uint64_t)x_overlapLen) - && (DIFF(overlap_list->list[j].y_pos_e, Get_te(paf->buffer[inner_j])) < (uint64_t)x_overlapLen)) - ) - { - overlap_list->list[j].is_match = is_match; - overlap_list->list[j].strong = paf->buffer[inner_j].ml; - overlap_list->list[j].without_large_indel = paf->buffer[inner_j].no_l_indel; - if(is_exact == 1) - { - if(overlap_list->list[j].y_pos_strand == 0) - { - recover_UC_Read(overlap_read, &R_INF, overlap_list->list[j].y_id); - } - else - { - recover_UC_Read_RC(overlap_read, &R_INF, overlap_list->list[j].y_id); - } - if(if_exact_match(g_read->seq, g_read->length, overlap_read->seq, overlap_read->length, - overlap_list->list[j].x_pos_s, overlap_list->list[j].x_pos_e, - overlap_list->list[j].y_pos_s, overlap_list->list[j].y_pos_e)) - { - overlap_list->list[j].shared_seed = 1; - } - else - { - overlap_list->list[j].shared_seed = 0; - } - } - } - else - { - overlap_list->list[j].is_match = 3; - } - } - else - { - overlap_list->list[j].is_match = 3; - } - } - - j++; - inner_j++; - } - } -} - - - -void update_exact_overlaps(overlap_region_alloc* overlap_list, UC_Read* g_read, UC_Read* overlap_read) -{ - uint64_t j; - for (j = 0; j < overlap_list->length; j++) - { - if (overlap_list->list[j].is_match != 1) - { - if((overlap_list->list[j].x_pos_e + 1 - overlap_list->list[j].x_pos_s) != - (overlap_list->list[j].y_pos_e + 1 - overlap_list->list[j].y_pos_s)) - { - continue; - } - - if(overlap_list->list[j].y_pos_strand == 0) - { - recover_UC_Read(overlap_read, &R_INF, overlap_list->list[j].y_id); - } - else - { - recover_UC_Read_RC(overlap_read, &R_INF, overlap_list->list[j].y_id); - } - - if(if_exact_match(g_read->seq, g_read->length, overlap_read->seq, overlap_read->length, - overlap_list->list[j].x_pos_s, overlap_list->list[j].x_pos_e, - overlap_list->list[j].y_pos_s, overlap_list->list[j].y_pos_e)) - { - overlap_list->list[j].is_match = 1; - overlap_list->list[j].strong = 0; - overlap_list->list[j].without_large_indel = 1; - overlap_list->list[j].shared_seed = 1; - } - } - } -} - -void ha_print_ovlp_stat(ma_hit_t_alloc* paf, ma_hit_t_alloc* rev_paf, long long readNum) -{ - long long forward, reverse, strong, weak, exact, no_l_indel; - long long i, j; - - no_l_indel = forward = reverse = exact = strong = weak = 0; - for (i = 0; i < readNum; i++) { - forward += paf[i].length; - reverse += rev_paf[i].length; - for (j = 0; j < paf[i].length; j++) { - if (paf[i].buffer[j].el == 1) exact++; - if (paf[i].buffer[j].ml == 1) strong++; - if (paf[i].buffer[j].ml == 0) weak++; - if (paf[i].buffer[j].no_l_indel == 1) no_l_indel++; - } - } - fprintf(stderr, "[M::%s] # overlaps: %lld\n", __func__, forward); - fprintf(stderr, "[M::%s] # strong overlaps: %lld\n", __func__, strong); - fprintf(stderr, "[M::%s] # weak overlaps: %lld\n", __func__, weak); - fprintf(stderr, "[M::%s] # exact overlaps: %lld\n", __func__, exact); // this seems not right - fprintf(stderr, "[M::%s] # inexact overlaps: %lld\n", __func__, forward - exact); - fprintf(stderr, "[M::%s] # overlaps without large indels: %lld\n", __func__, no_l_indel); - fprintf(stderr, "[M::%s] # reverse overlaps: %lld\n", __func__, reverse); -} - -void fill_chain(Fake_Cigar* chain, char* x_string, char* y_string, long long xBeg, long long yBeg, -long long x_readLen, long long y_readLen, Cigar_record* cigar, uint8_t* c2n) -{ - /** - long long i, xOffset, yOffset, xRegionLen, yRegionLen, maxXpos, maxYpos, mapGlobalScore, mapExtentScore, zdroped; - long long xBuoundaryScore, yBuoundaryScore; - ///float band_rate = 0.08; - int endbouns,mode; - if(chain->length <= 0) return; - - kvec_t(uint8_t) x_num; - kvec_t(uint8_t) y_num; - kv_init(x_num); - kv_init(y_num); - - ///deal with region 0 backward - i = 0; - endbouns = 0; - - xOffset = get_fake_gap_pos(chain, 0); - xOffset = xOffset - 1; - yOffset = (xOffset - xBeg) + yBeg + get_fake_gap_shift(chain, 0); - if(xOffset >= 0 && yOffset >= 0) - { - xRegionLen = xOffset + 1; - yRegionLen = yOffset + 1; - //note here cannot use DIFF(xRegionLen, yRegionLen) - // bandLen = (MIN(xRegionLen, yRegionLen))*band_rate; - // if(bandLen == 0) bandLen = MIN(xRegionLen, yRegionLen); - - ///do alignment backward - kv_resize(uint8_t, x_num, (uint64_t)xRegionLen); - kv_resize(uint8_t, y_num, (uint64_t)yRegionLen); - ///text is x, query is y - afine_gap_alignment(x_string, x_num.a, xRegionLen, y_string, y_num.a, yRegionLen, - c2n, BACKWARD_KSW, MATCH_SCORE_KSW, MISMATCH_SCORE_KSW, GAP_OPEN_KSW, GAP_EXT_KSW, - BAND_KSW, Z_DROP_KSW, endbouns, &maxXpos, &maxYpos, &mapGlobalScore, - &mapExtentScore, &xBuoundaryScore, &yBuoundaryScore, &zdroped); - - // fprintf(stderr, "* xOffset: %lld, yOffset: %lld, xRegionLen: %lld, yRegionLen: %lld, bandLen: %lld, maxXpos: %lld, maxYpos: %lld, zdroped: %lld\n", - // xOffset, yOffset, xRegionLen, yRegionLen, BAND_KSW, maxXpos, maxYpos, zdroped); - } - - ///align forward - for (i = 0; i < (long long)chain->length; i++) - { - // xOffset = get_fake_gap_pos(chain, i); - // yOffset = xOffset + get_fake_gap_shift(chain, i); - xOffset = get_fake_gap_pos(chain, i); - yOffset = (xOffset - xBeg) + yBeg + get_fake_gap_shift(chain, i); - ///last region - if(i == (long long)(chain->length - 1)) - { - endbouns = 0; - xRegionLen = x_readLen - xOffset; - yRegionLen = y_readLen - yOffset; - //note here cannot use DIFF(xRegionLen, yRegionLen) - // bandLen = (MIN(xRegionLen, yRegionLen))*band_rate; - // if(bandLen == 0) bandLen = MIN(xRegionLen, yRegionLen); - } - else - { - ///higher endbouns for middle regions - endbouns = MATCH_SCORE_KSW; - xRegionLen = get_fake_gap_pos(chain, i+1) - xOffset; - yRegionLen = (get_fake_gap_pos(chain, i+1) + get_fake_gap_shift(chain, i+1)) - - (get_fake_gap_pos(chain, i) + get_fake_gap_shift(chain, i)); - - // bandLen = MAX((MIN(xRegionLen, yRegionLen))*band_rate, DIFF(xRegionLen, yRegionLen)); - // if(bandLen == 0) bandLen = MIN(xRegionLen, yRegionLen); - } - - - ///do alignment forward - kv_resize(uint8_t, x_num, (uint64_t)xRegionLen); - kv_resize(uint8_t, y_num, (uint64_t)yRegionLen); - ///text is x, query is y - afine_gap_alignment(x_string+xOffset, x_num.a, xRegionLen, y_string+yOffset, y_num.a, yRegionLen, - c2n, FORWARD_KSW, MATCH_SCORE_KSW, MISMATCH_SCORE_KSW, GAP_OPEN_KSW, GAP_EXT_KSW, - BAND_KSW, Z_DROP_KSW, endbouns, &maxXpos, &maxYpos, &mapGlobalScore, - &mapExtentScore, &xBuoundaryScore, &yBuoundaryScore, &zdroped); - // fprintf(stderr, "# xOffset: %lld, yOffset: %lld, xRegionLen: %lld, yRegionLen: %lld, bandLen: %lld, maxXpos: %lld, maxYpos: %lld, zdroped: %lld\n", - // xOffset, yOffset, xRegionLen, yRegionLen, BAND_KSW, maxXpos, maxYpos, zdroped); - } - - - kv_destroy(x_num); - kv_destroy(y_num); - **/ -} -void Final_phasing(overlap_region_alloc* overlap_list, Cigar_record_alloc* cigarline, -UC_Read* g_read, UC_Read* overlap_read, uint8_t* c2n) -{ - uint64_t i, xLen, yStrand; - char* x_string; - char* y_string; - Cigar_record* cigar; - resize_Cigar_record_alloc(cigarline, overlap_list->length); - - - - for (i = 0; i < overlap_list->length; i++) - { - if(overlap_list->list[i].is_match == 1 || - overlap_list->list[i].is_match == 2 || - overlap_list->list[i].is_match == 3) - { - xLen = overlap_list->list[i].x_pos_e - overlap_list->list[i].x_pos_s + 1; - yStrand = overlap_list->list[i].y_pos_strand; - cigar = &(cigarline->buffer[i]); - ///has already been matched exactly - if(overlap_list->list[i].is_match == 1 && overlap_list->list[i].shared_seed == 1) - { - add_cigar_record(g_read->seq + overlap_list->list[i].x_pos_s, xLen, cigar, 0); - } - else - { - if(yStrand == 0) - { - recover_UC_Read(overlap_read, &R_INF, overlap_list->list[i].y_id); - } - else - { - recover_UC_Read_RC(overlap_read, &R_INF, overlap_list->list[i].y_id); - } - x_string = g_read->seq; - y_string = overlap_read->seq; - - fill_chain(&(overlap_list->list[i].f_cigar), x_string, y_string, - overlap_list->list[i].x_pos_s, overlap_list->list[i].y_pos_s, - Get_READ_LENGTH(R_INF, overlap_list->list[i].x_id), - Get_READ_LENGTH(R_INF, overlap_list->list[i].y_id), cigar, c2n); - } - - } - } - -} - -static void worker_ov_final(void *data, long i, int tid) -{ - ha_ovec_buf_t *b = ((ha_ovec_buf_t**)data)[tid]; - - //get_new_candidates(i, &g_read, &overlap_list, &array_list, &l, 0.001, 0); - ha_get_candidates_interface(b->ab, i, &b->self_read, &b->olist, &b->olist_hp, &b->clist, 0.001, - asm_opt.max_n_chain, 0, NULL/**&(b->k_flag)**/, &b->r_buf, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), &(b->tmp_region), NULL, &(b->sp)); - - overlap_region_sort_y_id(b->olist.list, b->olist.length); - ma_hit_sort_tn(R_INF.paf[i].buffer, R_INF.paf[i].length); - ma_hit_sort_tn(R_INF.reverse_paf[i].buffer, R_INF.reverse_paf[i].length); - - update_overlaps(&b->olist, &(R_INF.paf[i]), &b->self_read, &b->ovlp_read, 1, 1); - update_overlaps(&b->olist, &(R_INF.reverse_paf[i]), &b->self_read, &b->ovlp_read, 2, 0); - ///recover missing exact overlaps - update_exact_overlaps(&b->olist, &b->self_read, &b->ovlp_read); - - ///Final_phasing(&overlap_list, &cigarline, &g_read, &overlap_read, c2n); - push_final_overlaps(&(R_INF.paf[i]), R_INF.reverse_paf, &b->olist, 1); - push_final_overlaps(&(R_INF.reverse_paf[i]), R_INF.reverse_paf, &b->olist, 2); -} - - - - -void reset_final_overlaps(overlap_region_alloc *overlap_list) -{ - - uint64_t i; - for (i = 0; i < overlap_list->length; i++) - { - if (overlap_list->list[i].is_match == 1 || overlap_list->list[i].is_match == 2) - { - overlap_list->list[i].x_pos_s = overlap_list->list[i].x_pos_e = (uint32_t)-1; - overlap_list->list[i].y_pos_s = overlap_list->list[i].y_pos_e = (uint32_t)-1; - overlap_list->list[i].is_match = 0; - } - } - - ha_sort_list_by_anchor(overlap_list); -} - -void debug_affine_gap_alignment(overlap_region_alloc *overlap_list, UC_Read* g_read, UC_Read* overlap_read) -{ - uint64_t i; - kvec_t(uint8_t) x_num; - kvec_t(uint8_t) y_num; - kv_init(x_num); - kv_init(y_num); - for (i = 0; i < overlap_list->length; i++) - { - if (overlap_list->list[i].is_match == 1 && overlap_list->list[i].shared_seed == 1) - { - - kv_resize(uint8_t, x_num, (uint64_t)(Get_READ_LENGTH(R_INF, overlap_list->list[i].x_id))); - kv_resize(uint8_t, y_num, (uint64_t)(Get_READ_LENGTH(R_INF, overlap_list->list[i].y_id))); - - get_affine_gap_score(&(overlap_list->list[i]), g_read, overlap_read, x_num.a, y_num.a, - overlap_list->list[i].x_pos_e + 1 - overlap_list->list[i].x_pos_s, - overlap_list->list[i].y_pos_e + 1 - overlap_list->list[i].y_pos_s); - } - } - - kv_destroy(x_num); - kv_destroy(y_num); -} - -/** -static void worker_ov_final_high_het(void *data, long i, int tid) -{ - ha_ovec_buf_t *b = ((ha_ovec_buf_t**)data)[tid]; - - ha_get_candidates_interface(b->ab, i, &b->self_read, &b->olist, &b->olist_hp, &b->clist, HIGH_HET_ERROR_RATE, - asm_opt.max_n_chain, 1, NULL, &b->r_buf, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), &(b->tmp_region), NULL, &(b->sp)); - - overlap_region_sort_y_id(b->olist.list, b->olist.length); - ma_hit_sort_tn(R_INF.paf[i].buffer, R_INF.paf[i].length); - ma_hit_sort_tn(R_INF.reverse_paf[i].buffer, R_INF.reverse_paf[i].length); - - - ///update_overlaps(&b->olist, &(R_INF.paf[i]), &b->self_read, &b->ovlp_read, 1, 1); - update_overlaps_chain_width(&b->olist, &(R_INF.paf[i]), &b->self_read, &b->ovlp_read, 1, 1, 0.002); - update_overlaps(&b->olist, &(R_INF.reverse_paf[i]), &b->self_read, &b->ovlp_read, 2, 0); - ///recover missing exact overlaps - update_exact_overlaps(&b->olist, &b->self_read, &b->ovlp_read); - - - ///Final_phasing(&overlap_list, &cigarline, &g_read, &overlap_read, c2n); - push_final_overlaps(&(R_INF.paf[i]), R_INF.reverse_paf, &b->olist, 1); - push_final_overlaps(&(R_INF.reverse_paf[i]), R_INF.reverse_paf, &b->olist, 2); - - ///debug_affine_gap_alignment(&b->olist, &b->self_read, &b->ovlp_read); - - reset_final_overlaps(&b->olist); - correct_overlap_high_het(&b->olist, &R_INF, &b->self_read, &b->correct, &b->ovlp_read); - push_final_overlaps_increment(&(R_INF.reverse_paf[i]), R_INF.reverse_paf, &b->olist, 2); -} -**/ - -void Output_PAF() -{ - fprintf(stderr, "Writing PAF to disk ...... \n"); - char* paf_name = (char*)malloc(strlen(asm_opt.output_file_name)+50); - sprintf(paf_name, "%s.ovlp.paf", asm_opt.output_file_name); - FILE* output_file = fopen(paf_name, "w"); - uint64_t i, j; - ma_hit_t_alloc* sources = R_INF.paf; - - for (i = 0; i < R_INF.total_reads; i++) - { - for (j = 0; j < sources[i].length; j++) - { - fwrite(Get_NAME(R_INF, Get_qn(sources[i].buffer[j])), 1, - Get_NAME_LENGTH(R_INF, Get_qn(sources[i].buffer[j])), output_file); - fwrite("\t", 1, 1, output_file); - fprintf(output_file, "%lu\t", (unsigned long)Get_READ_LENGTH(R_INF, Get_qn(sources[i].buffer[j]))); - fprintf(output_file, "%d\t", Get_qs(sources[i].buffer[j])); - fprintf(output_file, "%d\t", Get_qe(sources[i].buffer[j])); - if(sources[i].buffer[j].rev) - { - fprintf(output_file, "-\t"); - } - else - { - fprintf(output_file, "+\t"); - } - fwrite(Get_NAME(R_INF, Get_tn(sources[i].buffer[j])), 1, - Get_NAME_LENGTH(R_INF, Get_tn(sources[i].buffer[j])), output_file); - fwrite("\t", 1, 1, output_file); - fprintf(output_file, "%lu\t", (unsigned long)Get_READ_LENGTH(R_INF, Get_tn(sources[i].buffer[j]))); - fprintf(output_file, "%d\t", Get_ts(sources[i].buffer[j])); - fprintf(output_file, "%d\t", Get_te(sources[i].buffer[j])); - fprintf(output_file, "%d\t", sources[i].buffer[j].ml); - fprintf(output_file, "%d\t", sources[i].buffer[j].bl); - fprintf(output_file, "255\n"); - - } - } - - free(paf_name); - fclose(output_file); - - fprintf(stderr, "PAF has been written.\n"); -} - - -void Output_PAF0(ma_hit_t_alloc* sources, const char *prefix) -{ - fprintf(stderr, "Writing PAF to disk ...... \n"); - char* paf_name = (char*)malloc(strlen(asm_opt.output_file_name)+strlen(prefix)+50); - sprintf(paf_name, "%s.%s.ovlp.paf", asm_opt.output_file_name, prefix); - FILE* output_file = fopen(paf_name, "w"); - uint64_t i, j; - - for (i = 0; i < R_INF.total_reads; i++) - { - for (j = 0; j < sources[i].length; j++) - { - fwrite(Get_NAME(R_INF, Get_qn(sources[i].buffer[j])), 1, - Get_NAME_LENGTH(R_INF, Get_qn(sources[i].buffer[j])), output_file); - fwrite("\t", 1, 1, output_file); - fprintf(output_file, "%lu\t", (unsigned long)Get_READ_LENGTH(R_INF, Get_qn(sources[i].buffer[j]))); - fprintf(output_file, "%d\t", Get_qs(sources[i].buffer[j])); - fprintf(output_file, "%d\t", Get_qe(sources[i].buffer[j])); - if(sources[i].buffer[j].rev) - { - fprintf(output_file, "-\t"); - } - else - { - fprintf(output_file, "+\t"); - } - fwrite(Get_NAME(R_INF, Get_tn(sources[i].buffer[j])), 1, - Get_NAME_LENGTH(R_INF, Get_tn(sources[i].buffer[j])), output_file); - fwrite("\t", 1, 1, output_file); - fprintf(output_file, "%lu\t", (unsigned long)Get_READ_LENGTH(R_INF, Get_tn(sources[i].buffer[j]))); - fprintf(output_file, "%d\t", Get_ts(sources[i].buffer[j])); - fprintf(output_file, "%d\t", Get_te(sources[i].buffer[j])); - fprintf(output_file, "%d\t", sources[i].buffer[j].ml); - fprintf(output_file, "%d\t", sources[i].buffer[j].bl); - fprintf(output_file, "255\n"); - - } - } - - free(paf_name); - fclose(output_file); - - fprintf(stderr, "PAF has been written.\n"); -} - -int check_cluster(uint64_t* list, long long listLen, ma_hit_t_alloc* paf, float threshold) -{ - long long i, k; - uint32_t qn, tn; - long long T_edges, A_edges; - T_edges = A_edges = 0; - for (i = 0; i < listLen; i++) - { - qn = (uint32_t)list[i]; - for (k = i + 1; k < listLen; k++) - { - tn = (uint32_t)list[k]; - if(get_specific_overlap(&(paf[qn]), qn, tn) != -1) - { - A_edges++; - } - - if(get_specific_overlap(&(paf[tn]), tn, qn) != -1) - { - A_edges++; - } - - T_edges = T_edges + 2; - } - - } - - if(A_edges >= (T_edges*threshold)) - { - return 1; - } - else - { - return 0; - } -} - - -void rescue_edges(ma_hit_t_alloc* paf, ma_hit_t_alloc* rev_paf, -long long readNum, long long rescue_threshold, float cluster_threshold) -{ - double startTime = Get_T(); - long long i, j, revises = 0; - uint32_t qn, tn; - - kvec_t(uint64_t) edge_vector; - kv_init(edge_vector); - kvec_t(uint64_t) edge_vector_index; - kv_init(edge_vector_index); - uint64_t flag; - int index; - - for (i = 0; i < readNum; i++) - { - edge_vector.n = 0; - edge_vector_index.n = 0; - for (j = 0; j < paf[i].length; j++) - { - qn = Get_qn(paf[i].buffer[j]); - tn = Get_tn(paf[i].buffer[j]); - index = get_specific_overlap(&(rev_paf[tn]), tn, qn); - if(index != -1) - { - flag = tn; - flag = flag << 32; - flag = flag | (uint64_t)(index); - kv_push(uint64_t, edge_vector, flag); - kv_push(uint64_t, edge_vector_index, j); - } - } - - ///the read itself has these overlaps, but all related reads do not have - ///we need to remove all overlaps from paf[i], and then add all overlaps to rev_paf[i] - if((long long)edge_vector.n >= rescue_threshold && - check_cluster(edge_vector.a, edge_vector.n, paf, cluster_threshold) == 1) - { - add_overlaps(&(paf[i]), &(rev_paf[i]), edge_vector_index.a, edge_vector_index.n); - remove_overlaps(&(paf[i]), edge_vector_index.a, edge_vector_index.n); - revises = revises + edge_vector.n; - } - - edge_vector.n = 0; - edge_vector_index.n = 0; - for (j = 0; j < rev_paf[i].length; j++) - { - qn = Get_qn(rev_paf[i].buffer[j]); - tn = Get_tn(rev_paf[i].buffer[j]); - index = get_specific_overlap(&(paf[tn]), tn, qn); - if(index != -1) - { - flag = tn; - flag = flag << 32; - flag = flag | (uint64_t)(index); - kv_push(uint64_t, edge_vector, flag); - kv_push(uint64_t, edge_vector_index, j); - } - } - - ///the read itself do not have these overlaps, but all related reads have - ///we need to remove all overlaps from rev_paf[i], and then add all overlaps to paf[i] - if((long long)edge_vector.n >= rescue_threshold && - check_cluster(edge_vector.a, edge_vector.n, paf, cluster_threshold) == 1) - { - remove_overlaps(&(rev_paf[i]), edge_vector_index.a, edge_vector_index.n); - add_overlaps_from_different_sources(paf, &(paf[i]), edge_vector.a, edge_vector.n); - revises = revises + edge_vector.n; - } - } - - - kv_destroy(edge_vector); - kv_destroy(edge_vector_index); - - fprintf(stderr, "[M::%s] took %0.2fs, revise edges #: %lld\n\n", __func__, Get_T()-startTime, revises); -} - -void hap_recalculate_peaks(char* output_file_name) -{ - destory_read_bin(&R_INF); - destory_ma_hit_t_alloc(R_INF.paf); - destory_ma_hit_t_alloc(R_INF.reverse_paf); - - char* gfa_name = (char*)malloc(strlen(output_file_name)+25); - sprintf(gfa_name, "%s.ec", output_file_name); - - int hom_cov, het_cov; - // construct hash table for high occurrence k-mers - if (!(asm_opt.flag & HA_F_NO_KMER_FLT)) { - ha_flt_tab = ha_ft_gen(&asm_opt, &R_INF, &hom_cov, 0, 0); - ha_opt_update_cov(&asm_opt, hom_cov); - } - free(R_INF.read_length); - free(R_INF.name_index); - - load_All_reads(&R_INF, gfa_name); - - ha_idx = ha_pt_gen(&asm_opt, ha_flt_tab, 1, 0, &R_INF, &hom_cov, &het_cov); // build the index - asm_opt.hom_cov = hom_cov; - asm_opt.het_cov = het_cov; - ha_pt_destroy(ha_idx); - ha_idx = 0; - - destory_read_bin(&R_INF); - free(gfa_name); - - load_all_data_from_disk(&R_INF.paf, &R_INF.reverse_paf, asm_opt.output_file_name); - fprintf(stderr, "M::%s has done.\n", __func__); -} - -void ha_overlap_final(void) -{ - int i, hom_cov, het_cov; - ha_ovec_buf_t **b; - ha_flt_tab_hp = ha_idx_hp = NULL; - - CALLOC(b, asm_opt.thread_num); - for (i = 0; i < asm_opt.thread_num; ++i) - b[i] = ha_ovec_init(asm_opt.flag & HA_F_HIGH_HET, 1,0);///b[i] = ha_ovec_init(1, 1); - ha_idx = ha_pt_gen(&asm_opt, ha_flt_tab, 1, 0, &R_INF, &hom_cov, &het_cov); // build the index - // if(asm_opt.flag & HA_F_HIGH_HET) - // { - // kt_for(asm_opt.thread_num, worker_ov_final_high_het, b, R_INF.total_reads); - // } - // else - { - kt_for(asm_opt.thread_num, worker_ov_final, b, R_INF.total_reads); - } - - ha_pt_destroy(ha_idx); - ha_idx = 0; - for (i = 0; i < asm_opt.thread_num; ++i) - ha_ovec_destroy(b[i]); - free(b); - asm_opt.hom_cov = hom_cov; - asm_opt.het_cov = het_cov; -} - -void ha_ec_ff(int renew_idx) -{ - int hom_cov, het_cov; - ha_flt_tab_hp = ha_idx_hp = NULL; - - if(ha_idx && renew_idx) { - ha_pt_destroy(ha_idx); ha_idx = NULL; - } - - if(!ha_idx) { - ha_idx = ha_pt_gen(&asm_opt, ha_flt_tab, 1, 0, &R_INF, &hom_cov, &het_cov); // build the index - asm_opt.hom_cov = hom_cov; asm_opt.het_cov = het_cov; - } - - cal_ov_r(asm_opt.thread_num, R_INF.total_reads, renew_idx); - - ha_pt_destroy(ha_idx); ha_idx = NULL; -} - -static void worker_ov_utg(void *data, long i, int tid) -{ - ha_ovec_buf_t *b = ((ha_ovec_buf_t**)data)[tid]; - if(b->ua->a[i].len == 0) return; - - ha_get_ug_candidates(b->ab, i, &(b->ua->a[i]), b->ua, &b->olist, &b->clist, - 0.3, asm_opt.polyploidy*5, 0, &(b->k_flag), &b->r_buf, ha_flt_tab, ha_idx, - &(b->tmp_region), NULL, /**0.3**/0); - - overlap_region_sort_y_id(b->olist.list, b->olist.length); - ma_hit_sort_tn(R_INF.paf[i].buffer, R_INF.paf[i].length); - ma_hit_sort_tn(R_INF.reverse_paf[i].buffer, R_INF.reverse_paf[i].length); - - update_overlaps(&b->olist, &(R_INF.paf[i]), &b->self_read, &b->ovlp_read, 1, 1); - update_overlaps(&b->olist, &(R_INF.reverse_paf[i]), &b->self_read, &b->ovlp_read, 2, 0); - ///recover missing exact overlaps - update_exact_overlaps(&b->olist, &b->self_read, &b->ovlp_read); - - ///Final_phasing(&overlap_list, &cigarline, &g_read, &overlap_read, c2n); - push_final_overlaps(&(R_INF.paf[i]), R_INF.reverse_paf, &b->olist, 1); - push_final_overlaps(&(R_INF.reverse_paf[i]), R_INF.reverse_paf, &b->olist, 2); -} - - -void ug_idx_build(ma_ug_t *ug, int hap_n) -{ - int flag = asm_opt.flag&HA_F_NO_HPC, i; - asm_opt.flag -= flag; - // ha_flt_tab = ha_ft_ug_gen(&asm_opt, &(ug->u), hap_n, hap_n); - // ha_idx = ha_pt_ug_gen(&asm_opt, ha_flt_tab, &(ug->u), hap_n); - - ha_ovec_buf_t **b = NULL; - // overlap and correct reads - CALLOC(b, asm_opt.thread_num); - for (i = 0; i < asm_opt.thread_num; ++i) - { - b[i] = ha_ovec_init(1, 1, 0); - b[i]->ua = &(ug->u); - } - - kt_for(asm_opt.thread_num, worker_ov_utg, b, R_INF.total_reads); - - for (i = 0; i < asm_opt.thread_num; ++i) - ha_ovec_destroy(b[i]); - free(b); - - ha_ft_destroy(ha_flt_tab); - ha_pt_destroy(ha_idx); - asm_opt.flag += flag; - exit(1); -} - -int ha_assemble_ovec(void) -{ - extern void ha_extract_print_list(const All_reads *rs, int n_rounds, const char *o); - int r = 0, hom_cov = -1; - - ha_flt_tab = ha_idx = NULL; - - // construct hash table for high occurrence k-mers - if (!(asm_opt.flag & HA_F_NO_KMER_FLT) && ha_flt_tab == NULL) { - ha_flt_tab = ha_ft_gen(&asm_opt, &R_INF, &hom_cov, 0, 0); - ha_opt_update_cov(&asm_opt, hom_cov); - } - // error correction - assert(asm_opt.number_of_round > 0); - ha_opt_reset_to_round(&asm_opt, r); // this update asm_opt.roundID and a few other fields - ha_overlap_cal(r, 0); - fprintf(stderr, "[M::%s] size of buffer: %.3fGB\n", __func__, asm_opt.mem_buf / 1073741824.0); - - - ha_print_ovlp_stat(R_INF.paf, R_INF.reverse_paf, R_INF.total_reads); - ha_ft_destroy(ha_flt_tab); - - Output_PAF0(R_INF.paf, "0"); - Output_PAF0(R_INF.reverse_paf, "1"); - if (asm_opt.flag & HA_F_WRITE_PAF) Output_PAF(); - - destory_All_reads(&R_INF); - return 0; -} - -int ha_assemble_ovec_cc(void) -{ - ha_idx = NULL; - - ha_opt_reset_to_round(&asm_opt, 0); // this update asm_opt.roundID and a few other fields - ha_ec_dbg(); - - // Output_PAF0(R_INF.paf, "0"); - destory_All_reads(&R_INF); - return 0; -} - -int ha_assemble(void) -{ - // debug_mc_g_t(MC_NAME); - // debug_mc_gg_t(MC_NAME, 0, 0); - // quick_debug_phasing(MC_NAME); - extern void ha_extract_print_list(const All_reads *rs, int n_rounds, const char *o); - int r, hom_cov = -1, ovlp_loaded = 0; uint64_t tot_b, tot_e; - if (asm_opt.load_index_from_disk && load_all_data_from_disk(&R_INF.paf, &R_INF.reverse_paf, asm_opt.output_file_name)) { - ovlp_loaded = 1; - fprintf(stderr, "[M::%s::%.3f*%.2f] ==> loaded corrected reads and overlaps from disk\n", __func__, yak_realtime(), yak_cpu_usage()); - if (asm_opt.extract_list) { - ha_extract_print_list(&R_INF, asm_opt.extract_iter, asm_opt.extract_list); - exit(0); - } - if (asm_opt.flag & HA_F_WRITE_EC) { - if(asm_opt.is_sc) Output_corrected_fastq(); - else Output_corrected_reads(); - } - if (asm_opt.flag & HA_F_WRITE_PAF) Output_PAF(); - if (asm_opt.het_cov == -1024) hap_recalculate_peaks(asm_opt.output_file_name), ovlp_loaded = 2; - } - if (!ovlp_loaded) { - ha_flt_tab = ha_idx = NULL; - if((asm_opt.flag & HA_F_VERBOSE_GFA)) load_pt_index(&ha_flt_tab, &ha_idx, &R_INF, &asm_opt, asm_opt.output_file_name), load_ct_index(&ha_ct_table, asm_opt.output_file_name); - - // construct hash table for high occurrence k-mers - if (!(asm_opt.flag & HA_F_NO_KMER_FLT) && ha_flt_tab == NULL) - { - ha_flt_tab = ha_ft_gen(&asm_opt, &R_INF, &hom_cov, 0, 0); - ha_opt_update_cov(&asm_opt, hom_cov); - } - // error correction - assert(asm_opt.number_of_round > 0); - for (r = ha_idx?asm_opt.number_of_round-1:0; r < asm_opt.number_of_round; ++r) { - ha_opt_reset_to_round(&asm_opt, r); // this update asm_opt.roundID and a few other fields - tot_b = tot_e = 0; - // ha_overlap_and_correct(r); - ha_ec(r, asm_opt.number_of_pround, (r corrected reads for round %d\n", __func__, yak_realtime(), - yak_cpu_usage(), yak_peakrss_in_gb(), r + 1); - fprintf(stderr, "[M::%s] # bases: %lu; # corrected bases: %lu\n", __func__, tot_b, tot_e); - // fprintf(stderr, "[M::%s] # bases: %lld; # corrected bases: %lld; # recorrected bases: %lld\n", __func__, - // asm_opt.num_bases, asm_opt.num_corrected_bases, asm_opt.num_recorrected_bases); - // fprintf(stderr, "[M::%s] size of buffer: %.3fGB\n", __func__, asm_opt.mem_buf / 1073741824.0); - } - if (asm_opt.flag & HA_F_WRITE_EC) { - if(asm_opt.is_sc) Output_corrected_fastq(); - else Output_corrected_reads(); - } - // overlap between corrected reads - ha_opt_reset_to_round(&asm_opt, asm_opt.number_of_round); - // ha_overlap_final(); - ha_ec_ff(1/**0**/); - fprintf(stderr, "[M::%s::%.3f*%.2f@%.3fGB] ==> found overlaps for the final round\n", __func__, yak_realtime(), yak_cpu_usage(), yak_peakrss_in_gb()); - // fprintf(stderr, "\n[M::%s::%.3f*%.2f@%.3fGB] ==> found overlaps for the final round\n", __func__, yak_realtime(), yak_cpu_usage(), yak_peakrss_in_gb()); - // ha_print_ovlp_stat(R_INF.paf, R_INF.reverse_paf, R_INF.total_reads); - ha_ft_destroy(ha_flt_tab); - if (asm_opt.flag & HA_F_WRITE_PAF) Output_PAF(); - ha_triobin(&asm_opt); - - // exit(1); - } - if(ovlp_loaded == 2) ovlp_loaded = 0; - ha_opt_update_cov_min(&asm_opt, asm_opt.hom_cov, MIN_N_CHAIN); - - build_string_graph_without_clean(asm_opt.min_overlap_coverage, R_INF.paf, R_INF.reverse_paf, - R_INF.total_reads, R_INF.read_length, asm_opt.min_overlap_Len, asm_opt.max_hang_Len, asm_opt.clean_round, - asm_opt.gap_fuzz, asm_opt.min_drop_rate, asm_opt.max_drop_rate, asm_opt.output_file_name, asm_opt.large_pop_bubble_size, 0, !ovlp_loaded); - destory_All_reads(&R_INF); - return 0; -} - - -int ha_assemble_pair(void) -{ - extern void ha_extract_print_list(const All_reads *rs, int n_rounds, const char *o); - int r = 0, hom_cov = -1, ovlp_loaded = 0; memset((&R_INF), 0, sizeof(R_INF)); - - if (asm_opt.load_index_from_disk && load_all_data_from_disk(&R_INF.paf, &R_INF.reverse_paf, asm_opt.output_file_name)) { - ovlp_loaded = 1; - fprintf(stderr, "[M::%s::%.3f*%.2f] ==> loaded corrected reads and overlaps from disk\n", __func__, yak_realtime(), yak_cpu_usage()); - if (asm_opt.extract_list) { - ha_extract_print_list(&R_INF, asm_opt.extract_iter, asm_opt.extract_list); - exit(0); - } - if (asm_opt.flag & HA_F_WRITE_EC) Output_corrected_reads(); - if (asm_opt.flag & HA_F_WRITE_PAF) Output_PAF(); - if (asm_opt.het_cov == -1024) hap_recalculate_peaks(asm_opt.output_file_name), ovlp_loaded = 2; - } - - - if (!ovlp_loaded) { - - if(!append_All_reads(&R_INF, asm_opt.output_file_name, 0)) { - fprintf(stderr, "[M::%s::] Cannot load %s.0\n", __func__, asm_opt.output_file_name); - exit(1); - } - - if(!append_All_reads(&R_INF, asm_opt.output_file_name, 1)) { - fprintf(stderr, "[M::%s::] Cannot load %s.1\n", __func__, asm_opt.output_file_name); - exit(1); - } - // Output_corrected_reads(); exit(0); - - ha_flt_tab = ha_idx = NULL; r = asm_opt.number_of_round - 1; - if((asm_opt.flag & HA_F_VERBOSE_GFA)) load_pt_index(&ha_flt_tab, &ha_idx, &R_INF, &asm_opt, asm_opt.output_file_name), load_ct_index(&ha_ct_table, asm_opt.output_file_name); - - // construct hash table for high occurrence k-mers - if (!(asm_opt.flag & HA_F_NO_KMER_FLT) && ha_flt_tab == NULL) { - ha_flt_tab = ha_ft_gen(&asm_opt, &R_INF, &hom_cov, 0, 1); - ha_opt_update_cov(&asm_opt, hom_cov); - } - // error correction - assert(asm_opt.number_of_round > 0); - ha_opt_reset_to_round(&asm_opt, r); // this update asm_opt.roundID and a few other fields - ha_overlap_cal(r, 1); - fprintf(stderr, "[M::%s] size of buffer: %.3fGB\n", __func__, asm_opt.mem_buf / 1073741824.0); - fprintf(stderr, "[M::%s::%.3f*%.2f@%.3fGB] ==> found overlaps for the final round\n", __func__, yak_realtime(), - yak_cpu_usage(), yak_peakrss_in_gb()); - - - if (asm_opt.flag & HA_F_WRITE_EC) Output_corrected_reads(); - ha_print_ovlp_stat(R_INF.paf, R_INF.reverse_paf, R_INF.total_reads); - ha_ft_destroy(ha_flt_tab); - if (asm_opt.flag & HA_F_WRITE_PAF) Output_PAF(); - ha_triobin(&asm_opt); - - } - if(ovlp_loaded == 2) ovlp_loaded = 0; - ha_opt_update_cov_min(&asm_opt, asm_opt.hom_cov, MIN_N_CHAIN); - - build_string_graph_without_clean(asm_opt.min_overlap_coverage, R_INF.paf, R_INF.reverse_paf, - R_INF.total_reads, R_INF.read_length, asm_opt.min_overlap_Len, asm_opt.max_hang_Len, asm_opt.clean_round, - asm_opt.gap_fuzz, asm_opt.min_drop_rate, asm_opt.max_drop_rate, asm_opt.output_file_name, asm_opt.large_pop_bubble_size, 0, !ovlp_loaded); - destory_All_reads(&R_INF); - return 0; +#include +#include +#include +#include +#include "Assembly.h" +#include "Process_Read.h" +#include "CommandLines.h" +#include "Hash_Table.h" +#include "POA.h" +#include "Correct.h" +#include "htab.h" +#include "kthread.h" +#include "rcut.h" +#include "kalloc.h" +#include "ecovlp.h" + +void ha_get_candidates_interface(ha_abuf_t *ab, int64_t rid, UC_Read *ucr, overlap_region_alloc *overlap_list, overlap_region_alloc *overlap_list_hp, Candidates_list *cl, double bw_thres, +int max_n_chain, int keep_whole_chain, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* chain_idx, ma_hit_t_alloc* paf, ma_hit_t_alloc* rev_paf, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp); +void ha_get_ug_candidates(ha_abuf_t *ab, int64_t rid, ma_utg_t *u, ma_utg_v *ua, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, int max_n_chain, int keep_whole_chain, kvec_t_u8_warp* k_flag, +kvec_t_u64_warp* chain_idx, void *ha_flt_tab, ha_pt_t *ha_idx, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, double chain_match_rate); +void ha_sort_list_by_anchor(overlap_region_alloc *overlap_list); + +All_reads R_INF; +Debug_reads R_INF_FLAG; +all_ul_t UL_INF, ULG_INF; +uint32_t *het_cnt = NULL; +// uint32_t debug_out = 0; + +void get_corrected_read_from_cigar(Cigar_record* cigar, char* pre_read, int pre_length, char* new_read, int* new_length) +{ + int i, j; + int pre_i, new_i; + int operation, operation_length; + pre_i = new_i = 0; + int diff_char_i = 0; + + + for (i = 0; i < (long long)cigar->length; i++) + { + operation = Get_Cigar_Type(cigar->record[i]); + operation_length = Get_Cigar_Length(cigar->record[i]); + + if (operation == 0) + { + memcpy(new_read + new_i, pre_read + pre_i, operation_length); + pre_i = pre_i + operation_length; + new_i = new_i + operation_length; + } + else if (operation == 1) + { + + for (j = 0; j < operation_length; j++) + { + new_read[new_i] = Get_MisMatch_Base(cigar->lost_base[diff_char_i]); + new_i++; + diff_char_i++; + } + pre_i = pre_i + operation_length; + } + else if (operation == 3) + { + pre_i = pre_i + operation_length; + diff_char_i = diff_char_i + operation_length; + } + else if (operation == 2) + { + memcpy(new_read + new_i, cigar->lost_base + diff_char_i, operation_length); + new_i = new_i + operation_length; + diff_char_i = diff_char_i + operation_length; + } + } + *new_length = new_i; +} + +void get_uncorrected_read_from_cigar(Cigar_record* cigar, char* new_read, int new_length, char* pre_read, int* pre_length) +{ + int i, j; + int pre_i, new_i; + int operation, operation_length; + pre_i = new_i = 0; + int diff_char_i = 0; + + + for (i = 0; i < (long long)cigar->length; i++) + { + operation = Get_Cigar_Type(cigar->record[i]); + operation_length = Get_Cigar_Length(cigar->record[i]); + + + if (operation == 0) + { + memcpy(pre_read + pre_i, new_read + new_i, operation_length); + pre_i = pre_i + operation_length; + new_i = new_i + operation_length; + } + else if (operation == 1) + { + + for (j = 0; j < operation_length; j++) + { + pre_read[pre_i] = Get_Match_Base(cigar->lost_base[diff_char_i]); + pre_i++; + diff_char_i++; + } + new_i = new_i + operation_length; + } + else if (operation == 3) + { + memcpy(pre_read + pre_i, cigar->lost_base + diff_char_i, operation_length); + pre_i = pre_i + operation_length; + diff_char_i = diff_char_i + operation_length; + } + else if (operation == 2) + { + new_i = new_i + operation_length; + diff_char_i = diff_char_i + operation_length; + } + } + + *pre_length = pre_i; +} + +inline int get_cigar_errors(Cigar_record* cigar) +{ + int i; + int total_errors = 0; + for (i = 0; i < (long long)cigar->length; i++) + { + if (Get_Cigar_Type(cigar->record[i]) > 0) + { + total_errors = total_errors + Get_Cigar_Length(cigar->record[i]); + } + } + return total_errors; +} + +int debug_cigar(Cigar_record* cigar, char* pre_read, int pre_length, char* new_read, int new_length, int correct_base) +{ + int i; + int total_errors = 0; + for (i = 0; i < (long long)cigar->length; i++) + { + if (Get_Cigar_Type(cigar->record[i]) > 0) + { + total_errors = total_errors + Get_Cigar_Length(cigar->record[i]); + } + } + + if(total_errors!=correct_base) + { + fprintf(stderr, "total_errors: %d, correct_base: %d\n", total_errors, correct_base); + } + + int pre_i, new_i; + int operation, operation_length; + pre_i = new_i = 0; + + for (i = 0; i < (long long)cigar->length; i++) + { + operation = Get_Cigar_Type(cigar->record[i]); + operation_length = Get_Cigar_Length(cigar->record[i]); + + if (operation == 0) + { + pre_i = pre_i + operation_length; + new_i = new_i + operation_length; + } + + if (operation == 1) + { + pre_i = pre_i + operation_length; + new_i = new_i + operation_length; + } + + if (operation == 3) + { + pre_i = pre_i + operation_length; + } + + if (operation == 2) + { + new_i = new_i + operation_length; + } + + } + + if (pre_i != pre_length) + { + fprintf(stderr, "pre_i: %d, pre_length: %d\n", pre_i, pre_length); + } + + + if(new_i != new_length) + { + fprintf(stderr, "new_i: %d, new_length: %d\n", new_i, new_length); + } + + return 1; + + char* tmp_seq = (char*)malloc(new_length + pre_length); + int tmp_length; + + get_corrected_read_from_cigar(cigar, pre_read, pre_length, tmp_seq, &tmp_length); + + if(tmp_length != new_length) + { + fprintf(stderr, "tmp_length: %d, new_length: %d\n", tmp_length, new_length); + } + + if(memcmp(new_read, tmp_seq, new_length)!=0) + { + fprintf(stderr, "error new string\n"); + } + + + get_uncorrected_read_from_cigar(cigar, new_read, new_length, tmp_seq, &tmp_length); + + + if(tmp_length != pre_length) + { + fprintf(stderr, "tmp_length: %d, pre_length: %d\n", tmp_length, pre_length); + } + + if(memcmp(pre_read, tmp_seq, pre_length)!=0) + { + fprintf(stderr, "error pre string\n"); + } + + + free(tmp_seq); + + if((int)cigar->new_read_length != new_length) + { + fprintf(stderr, "cigar->new_read_length: %d, new_length: %d\n", cigar->new_read_length, new_length); + } +} + + +inline void push_cigar(Compressed_Cigar_record* records, long long ID, Cigar_record* input) +{ + if (input->length > records[ID].size) + { + records[ID].size = input->length; + records[ID].record = (uint32_t*)realloc(records[ID].record, records[ID].size*sizeof(uint32_t)); + } + records[ID].length = input->length; + memcpy(records[ID].record, input->record, input->length*sizeof(uint32_t)); + + if (input->lost_base_length > records[ID].lost_base_size) + { + records[ID].lost_base_size = input->lost_base_length; + records[ID].lost_base = (char*)realloc(records[ID].lost_base, records[ID].lost_base_size); + } + records[ID].lost_base_length = input->lost_base_length; + memcpy(records[ID].lost_base, input->lost_base, input->lost_base_length); + + records[ID].new_length = input->new_read_length; +} + + +void push_overlaps(ma_hit_t_alloc* paf, overlap_region_alloc* overlap_list, int flag, All_reads* R_INF, int if_reverse) +{ + long long i = 0, xLen, yLen; + int32_t size = 0; + ma_hit_t tmp; + for (i = 0; i < (long long)overlap_list->length; ++i) + if (overlap_list->list[i].is_match == flag) + ++size; + resize_ma_hit_t_alloc(paf, size); + clear_ma_hit_t_alloc(paf); + for (i = 0; i < (long long)overlap_list->length; i++) + { + if (overlap_list->list[i].is_match == flag) + { + xLen = Get_READ_LENGTH((*R_INF), overlap_list->list[i].x_id); + yLen = Get_READ_LENGTH((*R_INF), overlap_list->list[i].y_id); + + tmp.qns = overlap_list->list[i].x_id; + tmp.qns = tmp.qns << 32; + tmp.tn = overlap_list->list[i].y_id; + + if(if_reverse != 0) + { + tmp.qns = tmp.qns | (uint64_t)(xLen - overlap_list->list[i].x_pos_s - 1); + tmp.qe = xLen - overlap_list->list[i].x_pos_e - 1; + tmp.ts = yLen - overlap_list->list[i].y_pos_s - 1; + tmp.te = yLen - overlap_list->list[i].y_pos_e - 1; + } + else + { + tmp.qns = tmp.qns | (uint64_t)(overlap_list->list[i].x_pos_s); + tmp.qe = overlap_list->list[i].x_pos_e; + tmp.ts = overlap_list->list[i].y_pos_s; + tmp.te = overlap_list->list[i].y_pos_e; + } + + ///for overlap_list, the x_strand of all overlaps are 0, so the tmp.rev is the same as the y_strand + tmp.rev = overlap_list->list[i].y_pos_strand; + + ///tmp.bl = R_INF.read_length[overlap_list->list[i].y_id]; + tmp.bl = Get_READ_LENGTH((*R_INF), overlap_list->list[i].y_id); + tmp.ml = overlap_list->list[i].strong; + tmp.no_l_indel = overlap_list->list[i].without_large_indel; + + add_ma_hit_t_alloc(paf, &tmp); + } + } +} + + +long long push_final_overlaps(ma_hit_t_alloc* paf, ma_hit_t_alloc* reverse_paf_list, overlap_region_alloc* overlap_list, int flag) +{ + long long i = 0; + long long available_overlaps = 0; + ma_hit_t tmp; + clear_ma_hit_t_alloc(paf); // paf has been preallocated, so we don't need preallocation + for (i = 0; i < (long long)overlap_list->length; i++) + { + if (overlap_list->list[i].is_match == flag) + { + available_overlaps++; + /**********************query***************************/ + //the interval of overlap is half-open [start, end) + tmp.qns = overlap_list->list[i].x_id; + tmp.qns = tmp.qns << 32; + tmp.qns = tmp.qns | (uint64_t)(overlap_list->list[i].x_pos_s); + ///the end pos is open + tmp.qe = overlap_list->list[i].x_pos_e + 1; + /**********************query***************************/ + + + + ///for overlap_list, the x_strand of all overlaps are 0, so the tmp.rev is the same as the y_strand + tmp.rev = overlap_list->list[i].y_pos_strand; + + + /**********************target***************************/ + tmp.tn = overlap_list->list[i].y_id; + if(tmp.rev == 1) + { + long long y_readLen = R_INF.read_length[overlap_list->list[i].y_id]; + tmp.ts = y_readLen - overlap_list->list[i].y_pos_e - 1; + tmp.te = y_readLen - overlap_list->list[i].y_pos_s - 1; + } + else + { + tmp.ts = overlap_list->list[i].y_pos_s; + tmp.te = overlap_list->list[i].y_pos_e; + } + ///the end pos is open + tmp.te++; + /**********************target***************************/ + + tmp.bl = R_INF.read_length[overlap_list->list[i].y_id]; + tmp.ml = overlap_list->list[i].strong; + tmp.no_l_indel = overlap_list->list[i].without_large_indel; + + tmp.el = overlap_list->list[i].shared_seed; + + add_ma_hit_t_alloc(paf, &tmp); + } + } + + return available_overlaps; +} + + + +long long push_final_overlaps_increment(ma_hit_t_alloc* paf, ma_hit_t_alloc* reverse_paf_list, overlap_region_alloc* overlap_list, int flag) +{ + long long i = 0; + long long available_overlaps = paf->length; + ma_hit_t tmp; + ///clear_ma_hit_t_alloc(paf); // paf has been preallocated, so we don't need preallocation + for (i = 0; i < (long long)overlap_list->length; i++) + { + if (overlap_list->list[i].is_match == flag) + { + available_overlaps++; + /**********************query***************************/ + //the interval of overlap is half-open [start, end) + tmp.qns = overlap_list->list[i].x_id; + tmp.qns = tmp.qns << 32; + tmp.qns = tmp.qns | (uint64_t)(overlap_list->list[i].x_pos_s); + ///the end pos is open + tmp.qe = overlap_list->list[i].x_pos_e + 1; + /**********************query***************************/ + + + + ///for overlap_list, the x_strand of all overlaps are 0, so the tmp.rev is the same as the y_strand + tmp.rev = overlap_list->list[i].y_pos_strand; + + + /**********************target***************************/ + tmp.tn = overlap_list->list[i].y_id; + if(tmp.rev == 1) + { + long long y_readLen = R_INF.read_length[overlap_list->list[i].y_id]; + tmp.ts = y_readLen - overlap_list->list[i].y_pos_e - 1; + tmp.te = y_readLen - overlap_list->list[i].y_pos_s - 1; + } + else + { + tmp.ts = overlap_list->list[i].y_pos_s; + tmp.te = overlap_list->list[i].y_pos_e; + } + ///the end pos is open + tmp.te++; + /**********************target***************************/ + + tmp.bl = R_INF.read_length[overlap_list->list[i].y_id]; + tmp.ml = overlap_list->list[i].strong; + tmp.no_l_indel = overlap_list->list[i].without_large_indel; + + tmp.el = overlap_list->list[i].shared_seed; + + add_ma_hit_t_alloc(paf, &tmp); + } + } + + return available_overlaps; +} + +ha_ovec_buf_t *ha_ovec_buf_init(void *km, int is_final, int save_ov, int is_ug) +{ + ha_ovec_buf_t *b; + KCALLOC(km, b, 1); + b->is_final = !!is_final, b->save_ov = !!save_ov; + init_UC_Read(&b->self_read);//set 0 + init_UC_Read(&b->ovlp_read);//set 0 + init_Candidates_list(&b->clist);//set 0 + memset(&b->olist, 0, sizeof(overlap_region_alloc)); + memset(&b->olist_hp, 0, sizeof(overlap_region_alloc)); + // init_overlap_region_alloc(&b->olist); + // init_overlap_region_alloc(&b->olist_hp); + init_fake_cigar(&(b->tmp_region.f_cigar));//set 0 + kv_init(b->b_buf.a);//set 0 + kv_init(b->r_buf.a);//set 0 + kv_init(b->k_flag.a);//set 0 + kv_init(b->sp);//set 0 + if(!is_ug) b->ab = ha_abuf_init_buf(km); + else b->abl = ha_abufl_init_buf(km); + if (!b->is_final) { + init_Cigar_record_buf(&b->cigar1, km); + // init_Graph(&b->POA_Graph); + // init_Graph(&b->DAGCon); + init_Correct_dumy_buf(&b->correct, km);//set 0 + InitHaplotypeEvdience_buf(&b->hap, km); + init_Round2_alignment_buf(&b->round2, km); + } + return b; +} + +ha_ovec_buf_t *ha_ovec_init(int is_final, int save_ov, int is_ug) +{ + ha_ovec_buf_t *b; + CALLOC(b, 1); + b->is_final = !!is_final, b->save_ov = !!save_ov; + init_UC_Read(&b->self_read); + init_UC_Read(&b->ovlp_read); + init_Candidates_list(&b->clist); + init_overlap_region_alloc(&b->olist); + init_overlap_region_alloc(&b->olist_hp); + init_fake_cigar(&(b->tmp_region.f_cigar)); + memset(&(b->tmp_region.w_list), 0, sizeof(b->tmp_region.w_list)); + CALLOC(b->tmp_region.w_list.a, 1); b->tmp_region.w_list.n = b->tmp_region.w_list.m = 1; + kv_init(b->b_buf.a); + kv_init(b->r_buf.a); + kv_init(b->k_flag.a); + kv_init(b->sp); + init_bit_extz_t(&(b->exz), 31); + if(!is_ug) b->ab = ha_abuf_init(); + else b->abl = ha_abufl_init(); + if (!b->is_final) { + init_Cigar_record(&b->cigar1); + init_Graph(&b->POA_Graph); + init_Graph(&b->DAGCon); + init_Correct_dumy(&b->correct); + InitHaplotypeEvdience(&b->hap); + init_Round2_alignment(&b->round2); + } + return b; +} + +void ha_ovec_destroy(ha_ovec_buf_t *b) +{ + destory_UC_Read(&b->self_read); + destory_UC_Read(&b->ovlp_read); + destory_Candidates_list(&b->clist); + destory_overlap_region_alloc(&b->olist); + destory_overlap_region_alloc(&b->olist_hp); + ha_abuf_destroy(b->ab); + ha_abufl_destroy(b->abl); + destory_fake_cigar(&(b->tmp_region.f_cigar)); + free(b->tmp_region.w_list.a); free(b->tmp_region.w_list.c.a); + kv_destroy(b->b_buf.a); + kv_destroy(b->r_buf.a); + kv_destroy(b->k_flag.a); + kv_destroy(b->sp); + destroy_bit_extz_t(&(b->exz)); + if (!b->is_final) { + destory_Cigar_record(&b->cigar1); + destory_Graph(&b->POA_Graph); + destory_Graph(&b->DAGCon); + destory_Correct_dumy(&b->correct); + destoryHaplotypeEvdience(&b->hap); + destory_Round2_alignment(&b->round2); + } + free(b); +} + +static int64_t ha_Graph_mem(const Graph *g) +{ + int64_t i, mem = 0; + mem = sizeof(Graph) + g->node_q.size * 8 + g->g_nodes.size * sizeof(Node); + for (i = 0; i < (int64_t)g->g_nodes.size; ++i) { + Node *n = &g->g_nodes.list[i]; + mem += n->mismatch_edges.size * sizeof(Edge); + mem += n->deletion_edges.size * sizeof(Edge); + mem += n->insertion_edges.size * sizeof(Edge); + } + mem += g->g_nodes.sort.size * 9; + return mem; +} + +int64_t ha_ovec_mem(const ha_ovec_buf_t *b, int64_t *mem_a) +{ + int64_t i, mem_ab = 0, mem_clist, mem_olist, mem_hap = 0, mem_aux = 0; + // mem_clist = b->clist.size * sizeof(k_mer_hit) + b->clist.chainDP.size * 7 * 4; + mem_clist = (b->clist.size * sizeof(k_mer_hit)) + ((sizeof((*b->clist.chainDP.score)) + sizeof((*b->clist.chainDP.pre)) + + sizeof((*b->clist.chainDP.indels)) + sizeof((*b->clist.chainDP.self_length)) + + sizeof((*b->clist.chainDP.occ)) + sizeof((*b->clist.chainDP.tmp))) * b->clist.chainDP.size); + mem_clist += sizeof(*(b->b_buf.a.a)) * b->b_buf.a.m; + mem_clist += sizeof(*(b->r_buf.a.a)) * b->r_buf.a.m; + mem_clist += sizeof(*(b->k_flag.a.a)) * b->k_flag.a.m; + mem_clist += sizeof(*(b->sp.a)) * b->sp.m; + mem_clist += sizeof(*(b->tmp_region.f_cigar.buffer)) * b->tmp_region.f_cigar.size; + mem_clist += sizeof(*(b->tmp_region.w_list.a)) * b->tmp_region.w_list.n; + mem_clist += sizeof(*(b->tmp_region.w_list.c.a)) * b->tmp_region.w_list.c.n; + + mem_olist = b->olist.size * sizeof(overlap_region); + for (i = 0; i < (int64_t)b->olist.size; ++i) { + const overlap_region *r = &b->olist.list[i]; + mem_olist += (r->w_list.n*sizeof(*(r->w_list.a))) + (r->w_list.c.n*sizeof(*(r->w_list.c.a))); + mem_olist += r->f_cigar.size * 8; + mem_olist += (r->boundary_cigars.n*sizeof(*(r->boundary_cigars.a))) + + (r->boundary_cigars.c.n*sizeof(*(r->boundary_cigars.c.a))); + } + + mem_olist += b->olist_hp.size * sizeof(overlap_region); + for (i = 0; i < (int64_t)b->olist_hp.size; ++i) { + const overlap_region *r = &b->olist_hp.list[i]; + mem_olist += (r->w_list.n*sizeof(*(r->w_list.a))) + (r->w_list.c.n*sizeof(*(r->w_list.c.a))); + mem_olist += r->f_cigar.size * 8; + mem_olist += (r->boundary_cigars.n*sizeof(*(r->boundary_cigars.a))) + + (r->boundary_cigars.c.n*sizeof(*(r->boundary_cigars.c.a))); + } + + if(b->ab) mem_ab += ha_abuf_mem(b->ab); + if(b->abl) mem_ab += ha_abufl_mem(b->abl); + + if (!b->is_final) { + mem_hap += sizeof(Cigar_record) + b->cigar1.lost_base_size + b->cigar1.size * 4; + mem_hap += sizeof(Correct_dumy) + b->correct.size * 8; + mem_hap += sizeof(Round2_alignment) + b->round2.cigar.size * 4 + b->round2.tmp_cigar.size * 4; + mem_hap += sizeof(haplotype_evdience_alloc) + b->hap.size * sizeof(haplotype_evdience) + b->hap.snp_matrix_size + b->hap.r_snp_size + b->hap.snp_stat.m * sizeof(SnpStats) + b->hap.snp_srt.m * sizeof(uint64_t); + mem_hap += ha_Graph_mem(&b->POA_Graph); + mem_hap += ha_Graph_mem(&b->DAGCon); + } + + + mem_aux += sizeof(*(b->self_read.seq)) * b->self_read.size; + mem_aux += sizeof(*(b->ovlp_read.seq)) * b->ovlp_read.size; + + if(mem_a) { + mem_a[0] = mem_ab; mem_a[1] = mem_clist; mem_a[2] = mem_olist; + mem_a[3] = mem_hap; mem_a[4] = mem_aux; + } + + return mem_ab + mem_clist + mem_olist + mem_hap + mem_aux; +} + +uint32_t get_het_cnt(haplotype_evdience_alloc *hap) +{ + uint32_t i, cnt; + for (i = cnt = 0; i < hap->snp_stat.n; i++) { + if(hap->snp_stat.a[i].score == 1 && (!(hap->snp_stat.a[i].occ_0 < 2 || hap->snp_stat.a[i].occ_1 < 2))) { + cnt++; + } + } + return cnt; +} + +static void worker_ovec(void *data, long i, int tid) +{ + ha_ovec_buf_t *b = ((ha_ovec_buf_t**)data)[tid]; + int fully_cov, abnormal; + // if(i != 12578) return; + // fprintf(stderr, "[M::%s-beg] rid->%ld\n", __func__, i); + // if (memcmp("7897e875-76e5-42c8-bc37-94b370c4cc8d", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + // fprintf(stderr, "[M::%s-beg] rid->%ld\n", __func__, i); + // } else { + // return; + // } + + ha_get_candidates_interface(b->ab, i, &b->self_read, &b->olist, &b->olist_hp, &b->clist, + 0.02, asm_opt.max_n_chain, 1, NULL/**&(b->k_flag)**/, &b->r_buf, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), &(b->tmp_region), NULL, &(b->sp)); + + // prt_chain(&b->olist); + // return; + + clear_Cigar_record(&b->cigar1); + clear_Round2_alignment(&b->round2); + + correct_overlap(&b->olist, &R_INF, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, + &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 1, &fully_cov, &abnormal); + + b->num_read_base += b->self_read.length; + b->num_correct_base += b->correct.corrected_base; + b->num_recorrect_base += b->round2.dumy.corrected_base; + + push_cigar(R_INF.cigars, i, &b->cigar1); + push_cigar(R_INF.second_round_cigar, i, &b->round2.cigar); + + R_INF.paf[i].is_fully_corrected = 0; + if (fully_cov) { + if (get_cigar_errors(&b->cigar1) == 0 && get_cigar_errors(&b->round2.cigar) == 0) + R_INF.paf[i].is_fully_corrected = 1; + } + R_INF.paf[i].is_abnormal = abnormal; + + R_INF.trio_flag[i] = AMBIGU; + + ///need to be fixed in r305 + // if(ha_idx_hp == NULL) + // { + // R_INF.trio_flag[i] += collect_hp_regions(&b->olist, &R_INF, &(b->k_flag), RESEED_HP_RATE, Get_READ_LENGTH(R_INF, i), NULL); + // } + + if (R_INF.trio_flag[i] != AMBIGU || b->save_ov) { + int is_rev = (asm_opt.number_of_round % 2 == 0); + push_overlaps(&(R_INF.paf[i]), &b->olist, 1, &R_INF, is_rev); + push_overlaps(&(R_INF.reverse_paf[i]), &b->olist, 2, &R_INF, is_rev); + } + + if(het_cnt) het_cnt[i] = get_het_cnt(&b->hap); + // fprintf(stderr, "[M::%s-end] rid->%ld\n", __func__, i); +} + + +static void worker_ovec_cal0(void *data, long i, int tid) +{ + ha_ovec_buf_t *b = ((ha_ovec_buf_t**)data)[tid]; + int fully_cov, abnormal; + + ha_get_candidates_interface(b->ab, i, &b->self_read, &b->olist, &b->olist_hp, &b->clist, + 0.02, asm_opt.max_n_chain, 1, NULL/**&(b->k_flag)**/, &b->r_buf, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), &(b->tmp_region), NULL, &(b->sp)); + + clear_Cigar_record(&b->cigar1); + clear_Round2_alignment(&b->round2); + + correct_overlap(&b->olist, &R_INF, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, + &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 0/**1***/, &fully_cov, &abnormal); + + b->num_read_base += b->self_read.length; + b->num_correct_base += b->correct.corrected_base; + b->num_recorrect_base += b->round2.dumy.corrected_base; + + + // R_INF.paf[i].is_fully_corrected = 0; + // R_INF.paf[i].is_abnormal = abnormal; + R_INF.trio_flag[i] = AMBIGU; + + // R_INF.paf[i].is_fully_corrected = 0; + // if (fully_cov) { + // if (get_cigar_errors(&b->cigar1) == 0 && get_cigar_errors(&b->round2.cigar) == 0) + // R_INF.paf[i].is_fully_corrected = 1; + // } + // R_INF.paf[i].is_abnormal = abnormal; + // R_INF.trio_flag[i] = AMBIGU; + + push_final_overlaps(&(R_INF.paf[i]), R_INF.reverse_paf, &b->olist, 1); + push_final_overlaps(&(R_INF.reverse_paf[i]), R_INF.reverse_paf, &b->olist, 2); + + if(het_cnt) het_cnt[i] = get_het_cnt(&b->hap); +} + + +static void worker_ovec_related_reads(void *data, long i, int tid) +{ + ha_ovec_buf_t *b = ((ha_ovec_buf_t**)data)[tid]; + + uint64_t k, queryNameLen; + for (k = 0; k < R_INF_FLAG.query_num; k++) + { + queryNameLen = strlen(R_INF_FLAG.read_name[k]); + if (queryNameLen != Get_NAME_LENGTH((R_INF),i)) continue; + if (memcmp(R_INF_FLAG.read_name[k], Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) + { + break; + } + } + + if(k < R_INF_FLAG.query_num) + { + R_INF_FLAG.read_id[k] = i; + int fully_cov, abnormal, q_idx = k; + + ha_get_candidates_interface(b->ab, i, &b->self_read, &b->olist, &b->olist_hp, &b->clist, + 0.02, asm_opt.max_n_chain, 1, NULL/**&(b->k_flag)**/, &b->r_buf, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), &(b->tmp_region), &(R_INF_FLAG.candidate_count[q_idx]), &(b->sp)); + + clear_Cigar_record(&b->cigar1); + clear_Round2_alignment(&b->round2); + + correct_overlap(&b->olist, &R_INF, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, + &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 1, &fully_cov, &abnormal); + + b->num_read_base += b->self_read.length; + b->num_correct_base += b->correct.corrected_base; + b->num_recorrect_base += b->round2.dumy.corrected_base; + + push_cigar(R_INF.cigars, i, &b->cigar1); + push_cigar(R_INF.second_round_cigar, i, &b->round2.cigar); + + R_INF.paf[i].is_fully_corrected = 0; + if (fully_cov) { + if (get_cigar_errors(&b->cigar1) == 0 && get_cigar_errors(&b->round2.cigar) == 0) + R_INF.paf[i].is_fully_corrected = 1; + } + R_INF.paf[i].is_abnormal = abnormal; + + + + pthread_mutex_lock(&R_INF_FLAG.OutputMutex); + + fprintf(R_INF_FLAG.fp, "\n>%.*s, rid: %ld\n", (int)Get_NAME_LENGTH((R_INF), i), Get_NAME((R_INF), i), i); + fprintf(R_INF_FLAG.fp, "%d-th round, len: %lu, hom_cov: %d, max_n_chain: %d\n", + asm_opt.number_of_round, Get_READ_LENGTH(R_INF, i), asm_opt.hom_cov, asm_opt.max_n_chain); + + fprintf(R_INF_FLAG.fp, "***************************k-mer counts (%d)***************************\n", (int)(R_INF_FLAG.candidate_count[q_idx].a.n)); + + sort_kvec_t_u64_warp(&(R_INF_FLAG.candidate_count[q_idx]), 0); + for (k = 0; k < R_INF_FLAG.candidate_count[q_idx].a.n; k++) + { + fprintf(R_INF_FLAG.fp, "[%lu] Count(%u): %lu, filtered: %lu\n", k, + (uint32_t)R_INF_FLAG.candidate_count[q_idx].a.a[k], R_INF_FLAG.candidate_count[q_idx].a.a[k]>>33, + (R_INF_FLAG.candidate_count[q_idx].a.a[k]>>32)&(uint64_t)1); + } + + + fprintf(R_INF_FLAG.fp, "***************************forward ovlp***************************\n"); + for (k = 0; k < b->olist.length; k++) + { + if(b->olist.list[k].is_match != 1) continue; + fprintf(R_INF_FLAG.fp, "%.*s\n", (int)Get_NAME_LENGTH((R_INF), b->olist.list[k].y_id), Get_NAME((R_INF), b->olist.list[k].y_id)); + fprintf(R_INF_FLAG.fp, "qs: %u, qe: %u, ts: %u, te: %u, rev: %u, strong: %u, no_l_indel: %u, len: %lu\n", + b->olist.list[k].x_pos_s, b->olist.list[k].x_pos_e, b->olist.list[k].y_pos_s, b->olist.list[k].y_pos_e, + b->olist.list[k].y_pos_strand, b->olist.list[k].strong, b->olist.list[k].without_large_indel, + Get_READ_LENGTH(R_INF, b->olist.list[k].y_id)); + } + + fprintf(R_INF_FLAG.fp, "***************************reverse ovlp***************************\n"); + for (k = 0; k < b->olist.length; k++) + { + if(b->olist.list[k].is_match != 2) continue; + fprintf(R_INF_FLAG.fp, "%.*s\n", (int)Get_NAME_LENGTH((R_INF), b->olist.list[k].y_id), Get_NAME((R_INF), b->olist.list[k].y_id)); + fprintf(R_INF_FLAG.fp, "qs: %u, qe: %u, ts: %u, te: %u, rev: %u, strong: %u, no_l_indel: %u, len: %lu\n", + b->olist.list[k].x_pos_s, b->olist.list[k].x_pos_e, b->olist.list[k].y_pos_s, b->olist.list[k].y_pos_e, + b->olist.list[k].y_pos_strand, b->olist.list[k].strong, b->olist.list[k].without_large_indel, + Get_READ_LENGTH(R_INF, b->olist.list[k].y_id)); + } + + /** + fprintf(R_INF_FLAG.fp, "***************************unmatched ovlp***************************\n"); + for (k = 0; k < b->olist.length; k++) + { + if(b->olist.list[k].is_match == 1) continue; + if(b->olist.list[k].is_match == 2) continue; + fprintf(R_INF_FLAG.fp, "%.*s\n", (int)Get_NAME_LENGTH((R_INF), b->olist.list[k].y_id), Get_NAME((R_INF), b->olist.list[k].y_id)); + fprintf(R_INF_FLAG.fp, "qs: %u, qe: %u, ts: %u, te: %u, rev: %u, strong: %u, no_l_indel: %u, len: %lu\n", + b->olist.list[k].x_pos_s, b->olist.list[k].x_pos_e, b->olist.list[k].y_pos_s, b->olist.list[k].y_pos_e, + b->olist.list[k].y_pos_strand, b->olist.list[k].strong, b->olist.list[k].without_large_indel, + Get_READ_LENGTH(R_INF, b->olist.list[k].y_id)); + } + **/ + + R_INF.trio_flag[i] = AMBIGU; + + ///need to be fixed in r305 + // if(ha_idx_hp == NULL) + // { + // R_INF.trio_flag[i] += collect_hp_regions(&b->olist, &R_INF, &(b->k_flag), RESEED_HP_RATE, Get_READ_LENGTH(R_INF, i), R_INF_FLAG.fp); + // } + + fprintf(R_INF_FLAG.fp, "R_INF.trio_flag[%ld]: %u\n", i, R_INF.trio_flag[i]); + + + pthread_mutex_unlock(&R_INF_FLAG.OutputMutex); + } +} + + +static inline long long get_N_occ(char* seq, long long length) +{ + long long j, N_occ = 0; + for (j = 0; j < length; j++) + if(seq_nt6_table[(uint8_t)seq[j]] >= 4) + N_occ++; + return N_occ; +} + +typedef struct { + UC_Read g_read; + int first_round_read_size; + int second_round_read_size; + char *first_round_read; + char *second_round_read; +} ha_ecsave_buf_t; + +static void worker_ec_save(void *data, long i, int tid) +{ + ha_ecsave_buf_t *e = (ha_ecsave_buf_t*)data + tid; + + Cigar_record cigar; + int first_round_read_length; + int second_round_read_length; + uint64_t N_occ; + + char *new_read; + int new_read_length; + + recover_UC_Read(&e->g_read, &R_INF, i); + + // round 1 + if ((long long)R_INF.cigars[i].new_length > e->first_round_read_size) { + e->first_round_read_size = R_INF.cigars[i].new_length; + REALLOC(e->first_round_read, e->first_round_read_size); + } + + cigar.length = R_INF.cigars[i].length; + cigar.lost_base_length = R_INF.cigars[i].lost_base_length; + cigar.record = R_INF.cigars[i].record; + cigar.lost_base = R_INF.cigars[i].lost_base; + + get_corrected_read_from_cigar(&cigar, e->g_read.seq, e->g_read.length, e->first_round_read, &first_round_read_length); + + // round 2 + if ((long long)R_INF.second_round_cigar[i].new_length > e->second_round_read_size) { + e->second_round_read_size = R_INF.second_round_cigar[i].new_length; + REALLOC(e->second_round_read, e->second_round_read_size); + } + cigar.length = R_INF.second_round_cigar[i].length; + cigar.lost_base_length = R_INF.second_round_cigar[i].lost_base_length; + cigar.record = R_INF.second_round_cigar[i].record; + cigar.lost_base = R_INF.second_round_cigar[i].lost_base; + + get_corrected_read_from_cigar(&cigar, e->first_round_read, first_round_read_length, e->second_round_read, &second_round_read_length); + + new_read = e->second_round_read; + new_read_length = second_round_read_length; + + if (asm_opt.roundID != asm_opt.number_of_round - 1) + { + ///need modification + reverse_complement(new_read, new_read_length); + } + else if(asm_opt.number_of_round % 2 == 0) + { + ///need modification + reverse_complement(new_read, new_read_length); + } + + N_occ = get_N_occ(new_read, new_read_length); + + if ((long long)R_INF.read_size[i] < new_read_length) { + R_INF.read_size[i] = new_read_length; + REALLOC(R_INF.read_sperate[i], R_INF.read_size[i]/4+1); + } + R_INF.read_length[i] = new_read_length; + ha_compress_base(Get_READ(R_INF, i), new_read, new_read_length, &R_INF.N_site[i], N_occ); +} + +void Output_corrected_reads() +{ + uint64_t i; UC_Read g_read; + init_UC_Read(&g_read); + char* gfa_name = (char*)malloc(strlen(asm_opt.output_file_name)+35); + sprintf(gfa_name, "%s.ec.fa", asm_opt.output_file_name); + FILE *output_file = fopen(gfa_name, "w"); + free(gfa_name); + + for (i = 0; i < R_INF.total_reads; i++) { + recover_UC_Read(&g_read, &R_INF, i); + fwrite(">", 1, 1, output_file); + fwrite(Get_NAME(R_INF, i), 1, Get_NAME_LENGTH(R_INF, i), output_file); + fwrite("\n", 1, 1, output_file); + fwrite(g_read.seq, 1, g_read.length, output_file); + fwrite("\n", 1, 1, output_file); + } + destory_UC_Read(&g_read); + fclose(output_file); +} + +void Output_corrected_fastq() +{ + uint64_t i, k; + UC_Read g_read; asg8_v dv; + init_UC_Read(&g_read); kv_init(dv); + char* gfa_name = (char*)malloc(strlen(asm_opt.output_file_name)+35); + sprintf(gfa_name, "%s.ec.fq", asm_opt.output_file_name); + FILE* fp = fopen(gfa_name, "w"); + free(gfa_name); + + for (i = 0; i < R_INF.tqn; i++) { + recover_UC_Read(&g_read, &R_INF, i); + fprintf(fp, "@%.*s\n", (int32_t)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); + fprintf(fp, "%.*s\n", (int32_t)g_read.length, g_read.seq); + fprintf(fp, "+\n"); + retrive_bqual(&dv, NULL, i, -1, -1, 0, sc_bn); + for (k = 0; k < dv.n; k++) fprintf(fp, "%c", (char)(sc_tb[dv.a[k]] + 33 - 1)); + fprintf(fp, "\n"); + } + + for (; i < R_INF.total_reads; i++) { + recover_UC_Read(&g_read, &R_INF, i); + fprintf(fp, "@%.*s\n", (int32_t)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); + fprintf(fp, "%.*s\n", (int32_t)g_read.length, g_read.seq); + fprintf(fp, "+\n"); + // retrive_bqual(&dv, NULL, i, -1, -1, 0, sc_bn); + // for (k = 0; k < dv.n; k++) fprintf(fp, "%c", (char)(sc_tb[dv.a[k]] + 33 - 1)); + for (k = 0; k < (uint64_t)g_read.length; k++) fprintf(fp, "%c", (char)(3 + 33 - 1)); + fprintf(fp, "\n"); + } + destory_UC_Read(&g_read); kv_destroy(dv); + fclose(fp); +} + +void debug_print_pob_regions() +{ + uint64_t i, total = 0; + for (i = 0; i < R_INF.total_reads; i++) + { + if(R_INF.trio_flag[i]!=AMBIGU) + { + total++; + fprintf(stderr, "(%lu) %.*s\n", i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); + } + } + fprintf(stderr, "total hp reads: %lu, R_INF.total_reads: %lu\n", total, R_INF.total_reads); + exit(1); +} + +void rescue_hp_reads(ha_ovec_buf_t **b) +{ + int hom_cov, het_cov; + ha_flt_tab_hp = ha_idx_hp = NULL; + if (!(asm_opt.flag & HA_F_NO_KMER_FLT)) { + ha_flt_tab_hp = ha_ft_gen(&asm_opt, &R_INF, &hom_cov, 1, 0); + } + ha_idx_hp = ha_pt_gen(&asm_opt, ha_flt_tab, 1, 1, &R_INF, &hom_cov, &het_cov); + + + if (asm_opt.required_read_name) + kt_for(asm_opt.thread_num, worker_ovec_related_reads, b, R_INF.total_reads); + else + kt_for(asm_opt.thread_num, worker_ovec, b, R_INF.total_reads); + + + + + ha_ft_destroy(ha_flt_tab_hp); ha_flt_tab_hp = NULL; + ha_pt_destroy(ha_idx_hp); ha_idx_hp = NULL; +} + + +void print_het_cnt_log(uint32_t *het_cnt) +{ + if(!het_cnt) return; + char* gfa_name = (char*)malloc(strlen(asm_opt.output_file_name)+35); + sprintf(gfa_name, "%s.het_cnt.log", asm_opt.output_file_name); + FILE* output_file = fopen(gfa_name, "w"); + fprintf(stderr, "[M::%s::] ==> print cnt of het sites to %s...\n", __func__, gfa_name); + free(gfa_name); + uint64_t i; + for (i = 0; i < R_INF.total_reads; i++){ + fprintf(output_file, ">%.*s\t%u\n", (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i), het_cnt[i]); + } + fclose(output_file); +} + +void prt_dbg_rs(FILE *fp, Debug_reads* x, uint64_t round) +{ + uint64_t k, id; UC_Read g_read; init_UC_Read(&g_read); + for (k = 0; k < R_INF_FLAG.query_num; k++) { + id = x->read_id[k]; + if(id == ((uint64_t)-1)) continue; + recover_UC_Read(&g_read, &R_INF, id); + fprintf(fp, ">%.*s_r%lu\n", (int)Get_NAME_LENGTH((R_INF), id), Get_NAME((R_INF), id), round); + fprintf(fp, "%.*s\n", (int)g_read.length, g_read.seq); + } + destory_UC_Read(&g_read); +} + +void ha_ec(int64_t round, int num_pround, int des_idx, uint64_t *tot_b, uint64_t *tot_e, uint64_t w_tmp) +{ + int hom_cov, het_cov, r_out = 0; + ha_flt_tab_hp = ha_idx_hp = NULL; (*tot_b) = (*tot_e) = 0; + + if((ha_idx == NULL)&&(asm_opt.flag & HA_F_VERBOSE_GFA)&&(round == asm_opt.number_of_round - 1)) r_out = 1; + + if(asm_opt.required_read_name) init_Debug_reads(&R_INF_FLAG, asm_opt.required_read_name); // for debugging only + + if(ha_idx) hom_cov = asm_opt.hom_cov; + if(ha_idx == NULL) { + ha_idx = ha_pt_gen(&asm_opt, ha_flt_tab, round == 0? 0 : 1, 0, &R_INF, &hom_cov, &het_cov); // build the index + asm_opt.hom_cov = hom_cov; asm_opt.het_cov = het_cov; + } + ///debug_adapter(&asm_opt, &R_INF); + if (round == 0 && ha_flt_tab == 0) // then asm_opt.hom_cov hasn't been updated + ha_opt_update_cov(&asm_opt, hom_cov); + het_cnt = NULL; + if(round == asm_opt.number_of_round-1 && asm_opt.is_dbg_het_cnt) CALLOC(het_cnt, R_INF.total_reads); + + if (r_out) { + write_pt_index(ha_flt_tab, ha_idx, &R_INF, &asm_opt, asm_opt.output_file_name); + if((asm_opt.flag & HA_F_VERBOSE_GFA) && (asm_opt.bin_only == 1)) exit(1);///just for debug + } + if (w_tmp) tmp_pt_pro(&ha_flt_tab, &ha_idx, &R_INF, &asm_opt, asm_opt.output_file_name, round, asm_opt.number_of_round, 0); + + // Output_corrected_fastq(); + + + cal_ec_r(asm_opt.thread_num, round, num_pround, R_INF.total_reads, (round == (asm_opt.number_of_round-1))?1:0, tot_b, tot_e); + + // exit(1); + + // if (r_out) write_pt_index(ha_flt_tab, ha_idx, &R_INF, &asm_opt, asm_opt.output_file_name); + if(des_idx) { + ha_pt_destroy(ha_idx); ha_idx = NULL; + } + + + if(het_cnt) { + print_het_cnt_log(het_cnt); free(het_cnt); het_cnt = NULL; + } + + // exit(1); + + + if (asm_opt.required_read_name) prt_dbg_rs(R_INF_FLAG.fp_r0, &R_INF_FLAG, 0); // for debugging only + + // save corrected reads to R_INF + // sl_ec_r(asm_opt.thread_num, R_INF.total_reads); + + if (asm_opt.required_read_name) prt_dbg_rs(R_INF_FLAG.fp_r1, &R_INF_FLAG, 1); // for debugging only + if (asm_opt.required_read_name) destory_Debug_reads(&R_INF_FLAG), exit(0); // for debugging only + ///debug_print_pob_regions(); + + // Output_corrected_reads(); + + // exit(1); +} + + +int ha_ec_dbg(void) +{ + int hom_cov, het_cov; + + ha_idx = ha_pt_gen(&asm_opt, 0, 0, 0, &R_INF, &hom_cov, &het_cov); // build the index + asm_opt.hom_cov = hom_cov; asm_opt.het_cov = het_cov; + ha_opt_update_cov(&asm_opt, hom_cov); + + cal_ec_r_dbg(asm_opt.thread_num, R_INF.total_reads); + + ha_pt_destroy(ha_idx); ha_idx = NULL; + + return 0; +} + +void ha_overlap_and_correct(int round) +{ + int i, hom_cov, het_cov, r_out = 0; + ha_ovec_buf_t **b; + ha_ecsave_buf_t *e; + ha_flt_tab_hp = ha_idx_hp = NULL; + + if((ha_idx == NULL)&&(asm_opt.flag & HA_F_VERBOSE_GFA)&&(round == asm_opt.number_of_round - 1)) + { + r_out = 1; + } + + if(asm_opt.required_read_name) init_Debug_reads(&R_INF_FLAG, asm_opt.required_read_name); // for debugging only + // overlap and correct reads + CALLOC(b, asm_opt.thread_num); + for (i = 0; i < asm_opt.thread_num; ++i) + b[i] = ha_ovec_init(0, (round == asm_opt.number_of_round - 1),0); + if(ha_idx) hom_cov = asm_opt.hom_cov; + if(ha_idx == NULL) ha_idx = ha_pt_gen(&asm_opt, ha_flt_tab, round == 0? 0 : 1, 0, &R_INF, &hom_cov, &het_cov); // build the index + ///debug_adapter(&asm_opt, &R_INF); + if (round == 0 && ha_flt_tab == 0) // then asm_opt.hom_cov hasn't been updated + ha_opt_update_cov(&asm_opt, hom_cov); + het_cnt = NULL; + if(round == asm_opt.number_of_round-1 && asm_opt.is_dbg_het_cnt) CALLOC(het_cnt, R_INF.total_reads); + // fprintf(stderr, "[M::%s-start]\n", __func__); + // double tt0 = yak_realtime_0(); + if (asm_opt.required_read_name) + kt_for(asm_opt.thread_num, worker_ovec_related_reads, b, R_INF.total_reads); + else + kt_for(asm_opt.thread_num, worker_ovec, b, R_INF.total_reads);///debug_for_fix + // fprintf(stderr, "[M::%s-end]\n", __func__); + // fprintf(stderr, "[M::%s::%.3f] ==> chaining\n", __func__, yak_realtime_0()-tt0); + // exit(1); + + if (r_out) write_pt_index(ha_flt_tab, ha_idx, &R_INF, &asm_opt, asm_opt.output_file_name); + ha_pt_destroy(ha_idx); + ha_idx = NULL; + + if(het_cnt) { + print_het_cnt_log(het_cnt); free(het_cnt); het_cnt = NULL; + } + + // collect statistics + for (i = 0; i < asm_opt.thread_num; ++i) { + asm_opt.num_bases += b[i]->num_read_base; + asm_opt.num_corrected_bases += b[i]->num_correct_base; + asm_opt.num_recorrected_bases += b[i]->num_recorrect_base; + asm_opt.mem_buf += ha_ovec_mem(b[i], NULL); + ha_ovec_destroy(b[i]); + } + free(b); + if (asm_opt.required_read_name) prt_dbg_rs(R_INF_FLAG.fp_r0, &R_INF_FLAG, 0); // for debugging only + + // save corrected reads to R_INF + CALLOC(e, asm_opt.thread_num); + for (i = 0; i < asm_opt.thread_num; ++i) { + init_UC_Read(&e[i].g_read); + e[i].first_round_read_size = e[i].second_round_read_size = 50000; + CALLOC(e[i].first_round_read, e[i].first_round_read_size); + CALLOC(e[i].second_round_read, e[i].second_round_read_size); + } + kt_for(asm_opt.thread_num, worker_ec_save, e, R_INF.total_reads); + for (i = 0; i < asm_opt.thread_num; ++i) { + destory_UC_Read(&e[i].g_read); + free(e[i].first_round_read); + free(e[i].second_round_read); + } + free(e); + + if (asm_opt.required_read_name) prt_dbg_rs(R_INF_FLAG.fp_r1, &R_INF_FLAG, 1); // for debugging only + if (asm_opt.required_read_name) destory_Debug_reads(&R_INF_FLAG), exit(0); // for debugging only + ///debug_print_pob_regions(); +} + +void ha_overlap_cal(int round, int read_from_store) +{ + int i, hom_cov, het_cov; + ha_ovec_buf_t **b; + ha_flt_tab_hp = ha_idx_hp = NULL; + + // overlap and correct reads + CALLOC(b, asm_opt.thread_num); + for (i = 0; i < asm_opt.thread_num; ++i) + b[i] = ha_ovec_init(0, (round == asm_opt.number_of_round - 1),0); + if(ha_idx) hom_cov = asm_opt.hom_cov; + if(ha_idx == NULL) ha_idx = ha_pt_gen(&asm_opt, ha_flt_tab, ((round == 0)&&(read_from_store == 0))?0:1, 0, &R_INF, &hom_cov, &het_cov); // build the index + ///debug_adapter(&asm_opt, &R_INF); + if (/**round == 0 &&**/ ha_flt_tab == 0) // then asm_opt.hom_cov hasn't been updated + ha_opt_update_cov(&asm_opt, hom_cov); + het_cnt = NULL; + if(round == asm_opt.number_of_round-1 && asm_opt.is_dbg_het_cnt) CALLOC(het_cnt, R_INF.total_reads); + // fprintf(stderr, "[M::%s-start]\n", __func__); + kt_for(asm_opt.thread_num, worker_ovec_cal0, b, R_INF.total_reads);///debug_for_fix + // fprintf(stderr, "[M::%s-end]\n", __func__); + + ha_pt_destroy(ha_idx); + ha_idx = NULL; + + if(het_cnt) { + print_het_cnt_log(het_cnt); free(het_cnt); het_cnt = NULL; + } + + // collect statistics + for (i = 0; i < asm_opt.thread_num; ++i) { + asm_opt.num_bases += b[i]->num_read_base; + asm_opt.num_corrected_bases += b[i]->num_correct_base; + asm_opt.num_recorrected_bases += b[i]->num_recorrect_base; + asm_opt.mem_buf += ha_ovec_mem(b[i], NULL); + ha_ovec_destroy(b[i]); + } + free(b); + asm_opt.hom_cov = hom_cov; + asm_opt.het_cov = het_cov; +} + + +void update_overlaps(overlap_region_alloc* overlap_list, ma_hit_t_alloc* paf, +UC_Read* g_read, UC_Read* overlap_read, int is_match, int is_exact) +{ + + uint64_t inner_j = 0; + uint64_t j = 0; + long long x_overlapLen, y_overlapLen; + while (j < overlap_list->length && inner_j < paf->length) + { + if(overlap_list->list[j].y_id < paf->buffer[inner_j].tn) + { + j++; + } + else if(overlap_list->list[j].y_id > paf->buffer[inner_j].tn) + { + inner_j++; + } + else + { + if(overlap_list->list[j].y_pos_strand == paf->buffer[inner_j].rev) + { + x_overlapLen = Get_qe(paf->buffer[inner_j]) - Get_qs(paf->buffer[inner_j]) + 1; + y_overlapLen = Get_te(paf->buffer[inner_j]) - Get_ts(paf->buffer[inner_j]) + 1; + if(x_overlapLen < y_overlapLen) x_overlapLen = y_overlapLen; + x_overlapLen = x_overlapLen * 0.1; + + // if( + // ((DIFF(overlap_list->list[j].x_pos_s, Get_qs(paf->buffer[inner_j])) < x_overlapLen) + // && (DIFF(overlap_list->list[j].x_pos_e, Get_qe(paf->buffer[inner_j])) < x_overlapLen)) + // || + // ((DIFF(overlap_list->list[j].y_pos_s, Get_ts(paf->buffer[inner_j])) < x_overlapLen) + // && (DIFF(overlap_list->list[j].y_pos_e, Get_te(paf->buffer[inner_j])) < x_overlapLen))) + if( + ((DIFF(overlap_list->list[j].x_pos_s, Get_qs(paf->buffer[inner_j])) < (uint64_t)x_overlapLen) + && (DIFF(overlap_list->list[j].x_pos_e, Get_qe(paf->buffer[inner_j])) < (uint64_t)x_overlapLen)) + || + ((DIFF(overlap_list->list[j].y_pos_s, Get_ts(paf->buffer[inner_j])) < (uint64_t)x_overlapLen) + && (DIFF(overlap_list->list[j].y_pos_e, Get_te(paf->buffer[inner_j])) < (uint64_t)x_overlapLen)) + ) + { + overlap_list->list[j].is_match = is_match; + overlap_list->list[j].strong = paf->buffer[inner_j].ml; + overlap_list->list[j].without_large_indel = paf->buffer[inner_j].no_l_indel; + if(is_exact == 1) + { + if(overlap_list->list[j].y_pos_strand == 0) + { + recover_UC_Read(overlap_read, &R_INF, overlap_list->list[j].y_id); + } + else + { + recover_UC_Read_RC(overlap_read, &R_INF, overlap_list->list[j].y_id); + } + if(if_exact_match(g_read->seq, g_read->length, overlap_read->seq, overlap_read->length, + overlap_list->list[j].x_pos_s, overlap_list->list[j].x_pos_e, + overlap_list->list[j].y_pos_s, overlap_list->list[j].y_pos_e)) + { + overlap_list->list[j].shared_seed = 1; + } + else + { + overlap_list->list[j].shared_seed = 0; + } + } + } + else + { + overlap_list->list[j].is_match = 3; + } + } + else + { + overlap_list->list[j].is_match = 3; + } + + j++; + inner_j++; + } + } +} + + +int check_chain_indels(Fake_Cigar* chain, long long xBeg, long long xEnd, float indel_rate) +{ + uint64_t i = 0; + long long indels = 0, xOffset; + if(chain->length != 0) + { + indels += abs(get_fake_gap_shift(chain, 0)); + xOffset = get_fake_gap_pos(chain, 0); + if(indels > (xOffset - xBeg + 1) * indel_rate) return 0; + + for (i = 1; i < chain->length; i++) + { + indels += abs((get_fake_gap_shift(chain, i) - get_fake_gap_shift(chain, i-1))); + xOffset = get_fake_gap_pos(chain, i); + if(indels > (xOffset - xBeg + 1) * indel_rate) return 0; + } + } + + if(indels > (xEnd - xBeg + 1) * indel_rate) return 0; + return 1; +} + +void update_overlaps_chain_width(overlap_region_alloc* overlap_list, ma_hit_t_alloc* paf, +UC_Read* g_read, UC_Read* overlap_read, int is_match, int is_exact, float indel_rate) +{ + + uint64_t inner_j = 0; + uint64_t j = 0; + long long x_overlapLen, y_overlapLen; + while (j < overlap_list->length && inner_j < paf->length) + { + if(overlap_list->list[j].y_id < paf->buffer[inner_j].tn) + { + j++; + } + else if(overlap_list->list[j].y_id > paf->buffer[inner_j].tn) + { + inner_j++; + } + else + { + if(check_chain_indels(&(overlap_list->list[j].f_cigar), overlap_list->list[j].x_pos_s, + overlap_list->list[j].x_pos_e, indel_rate) == 1) + { + if(overlap_list->list[j].y_pos_strand == paf->buffer[inner_j].rev) + { + x_overlapLen = Get_qe(paf->buffer[inner_j]) - Get_qs(paf->buffer[inner_j]) + 1; + y_overlapLen = Get_te(paf->buffer[inner_j]) - Get_ts(paf->buffer[inner_j]) + 1; + if(x_overlapLen < y_overlapLen) x_overlapLen = y_overlapLen; + x_overlapLen = x_overlapLen * 0.1; + + // if( + // ((DIFF(overlap_list->list[j].x_pos_s, Get_qs(paf->buffer[inner_j])) < x_overlapLen) + // && (DIFF(overlap_list->list[j].x_pos_e, Get_qe(paf->buffer[inner_j])) < x_overlapLen)) + // || + // ((DIFF(overlap_list->list[j].y_pos_s, Get_ts(paf->buffer[inner_j])) < x_overlapLen) + // && (DIFF(overlap_list->list[j].y_pos_e, Get_te(paf->buffer[inner_j])) < x_overlapLen))) + if( + ((DIFF(overlap_list->list[j].x_pos_s, Get_qs(paf->buffer[inner_j])) < (uint64_t)x_overlapLen) + && (DIFF(overlap_list->list[j].x_pos_e, Get_qe(paf->buffer[inner_j])) < (uint64_t)x_overlapLen)) + || + ((DIFF(overlap_list->list[j].y_pos_s, Get_ts(paf->buffer[inner_j])) < (uint64_t)x_overlapLen) + && (DIFF(overlap_list->list[j].y_pos_e, Get_te(paf->buffer[inner_j])) < (uint64_t)x_overlapLen)) + ) + { + overlap_list->list[j].is_match = is_match; + overlap_list->list[j].strong = paf->buffer[inner_j].ml; + overlap_list->list[j].without_large_indel = paf->buffer[inner_j].no_l_indel; + if(is_exact == 1) + { + if(overlap_list->list[j].y_pos_strand == 0) + { + recover_UC_Read(overlap_read, &R_INF, overlap_list->list[j].y_id); + } + else + { + recover_UC_Read_RC(overlap_read, &R_INF, overlap_list->list[j].y_id); + } + if(if_exact_match(g_read->seq, g_read->length, overlap_read->seq, overlap_read->length, + overlap_list->list[j].x_pos_s, overlap_list->list[j].x_pos_e, + overlap_list->list[j].y_pos_s, overlap_list->list[j].y_pos_e)) + { + overlap_list->list[j].shared_seed = 1; + } + else + { + overlap_list->list[j].shared_seed = 0; + } + } + } + else + { + overlap_list->list[j].is_match = 3; + } + } + else + { + overlap_list->list[j].is_match = 3; + } + } + + j++; + inner_j++; + } + } +} + + + +void update_exact_overlaps(overlap_region_alloc* overlap_list, UC_Read* g_read, UC_Read* overlap_read) +{ + uint64_t j; + for (j = 0; j < overlap_list->length; j++) + { + if (overlap_list->list[j].is_match != 1) + { + if((overlap_list->list[j].x_pos_e + 1 - overlap_list->list[j].x_pos_s) != + (overlap_list->list[j].y_pos_e + 1 - overlap_list->list[j].y_pos_s)) + { + continue; + } + + if(overlap_list->list[j].y_pos_strand == 0) + { + recover_UC_Read(overlap_read, &R_INF, overlap_list->list[j].y_id); + } + else + { + recover_UC_Read_RC(overlap_read, &R_INF, overlap_list->list[j].y_id); + } + + if(if_exact_match(g_read->seq, g_read->length, overlap_read->seq, overlap_read->length, + overlap_list->list[j].x_pos_s, overlap_list->list[j].x_pos_e, + overlap_list->list[j].y_pos_s, overlap_list->list[j].y_pos_e)) + { + overlap_list->list[j].is_match = 1; + overlap_list->list[j].strong = 0; + overlap_list->list[j].without_large_indel = 1; + overlap_list->list[j].shared_seed = 1; + } + } + } +} + +void ha_print_ovlp_stat(ma_hit_t_alloc* paf, ma_hit_t_alloc* rev_paf, long long readNum) +{ + long long forward, reverse, strong, weak, exact, no_l_indel; + long long i, j; + + no_l_indel = forward = reverse = exact = strong = weak = 0; + for (i = 0; i < readNum; i++) { + forward += paf[i].length; + reverse += rev_paf[i].length; + for (j = 0; j < paf[i].length; j++) { + if (paf[i].buffer[j].el == 1) exact++; + if (paf[i].buffer[j].ml == 1) strong++; + if (paf[i].buffer[j].ml == 0) weak++; + if (paf[i].buffer[j].no_l_indel == 1) no_l_indel++; + } + } + fprintf(stderr, "[M::%s] # overlaps: %lld\n", __func__, forward); + fprintf(stderr, "[M::%s] # strong overlaps: %lld\n", __func__, strong); + fprintf(stderr, "[M::%s] # weak overlaps: %lld\n", __func__, weak); + fprintf(stderr, "[M::%s] # exact overlaps: %lld\n", __func__, exact); // this seems not right + fprintf(stderr, "[M::%s] # inexact overlaps: %lld\n", __func__, forward - exact); + fprintf(stderr, "[M::%s] # overlaps without large indels: %lld\n", __func__, no_l_indel); + fprintf(stderr, "[M::%s] # reverse overlaps: %lld\n", __func__, reverse); +} + +void fill_chain(Fake_Cigar* chain, char* x_string, char* y_string, long long xBeg, long long yBeg, +long long x_readLen, long long y_readLen, Cigar_record* cigar, uint8_t* c2n) +{ + /** + long long i, xOffset, yOffset, xRegionLen, yRegionLen, maxXpos, maxYpos, mapGlobalScore, mapExtentScore, zdroped; + long long xBuoundaryScore, yBuoundaryScore; + ///float band_rate = 0.08; + int endbouns,mode; + if(chain->length <= 0) return; + + kvec_t(uint8_t) x_num; + kvec_t(uint8_t) y_num; + kv_init(x_num); + kv_init(y_num); + + ///deal with region 0 backward + i = 0; + endbouns = 0; + + xOffset = get_fake_gap_pos(chain, 0); + xOffset = xOffset - 1; + yOffset = (xOffset - xBeg) + yBeg + get_fake_gap_shift(chain, 0); + if(xOffset >= 0 && yOffset >= 0) + { + xRegionLen = xOffset + 1; + yRegionLen = yOffset + 1; + //note here cannot use DIFF(xRegionLen, yRegionLen) + // bandLen = (MIN(xRegionLen, yRegionLen))*band_rate; + // if(bandLen == 0) bandLen = MIN(xRegionLen, yRegionLen); + + ///do alignment backward + kv_resize(uint8_t, x_num, (uint64_t)xRegionLen); + kv_resize(uint8_t, y_num, (uint64_t)yRegionLen); + ///text is x, query is y + afine_gap_alignment(x_string, x_num.a, xRegionLen, y_string, y_num.a, yRegionLen, + c2n, BACKWARD_KSW, MATCH_SCORE_KSW, MISMATCH_SCORE_KSW, GAP_OPEN_KSW, GAP_EXT_KSW, + BAND_KSW, Z_DROP_KSW, endbouns, &maxXpos, &maxYpos, &mapGlobalScore, + &mapExtentScore, &xBuoundaryScore, &yBuoundaryScore, &zdroped); + + // fprintf(stderr, "* xOffset: %lld, yOffset: %lld, xRegionLen: %lld, yRegionLen: %lld, bandLen: %lld, maxXpos: %lld, maxYpos: %lld, zdroped: %lld\n", + // xOffset, yOffset, xRegionLen, yRegionLen, BAND_KSW, maxXpos, maxYpos, zdroped); + } + + ///align forward + for (i = 0; i < (long long)chain->length; i++) + { + // xOffset = get_fake_gap_pos(chain, i); + // yOffset = xOffset + get_fake_gap_shift(chain, i); + xOffset = get_fake_gap_pos(chain, i); + yOffset = (xOffset - xBeg) + yBeg + get_fake_gap_shift(chain, i); + ///last region + if(i == (long long)(chain->length - 1)) + { + endbouns = 0; + xRegionLen = x_readLen - xOffset; + yRegionLen = y_readLen - yOffset; + //note here cannot use DIFF(xRegionLen, yRegionLen) + // bandLen = (MIN(xRegionLen, yRegionLen))*band_rate; + // if(bandLen == 0) bandLen = MIN(xRegionLen, yRegionLen); + } + else + { + ///higher endbouns for middle regions + endbouns = MATCH_SCORE_KSW; + xRegionLen = get_fake_gap_pos(chain, i+1) - xOffset; + yRegionLen = (get_fake_gap_pos(chain, i+1) + get_fake_gap_shift(chain, i+1)) - + (get_fake_gap_pos(chain, i) + get_fake_gap_shift(chain, i)); + + // bandLen = MAX((MIN(xRegionLen, yRegionLen))*band_rate, DIFF(xRegionLen, yRegionLen)); + // if(bandLen == 0) bandLen = MIN(xRegionLen, yRegionLen); + } + + + ///do alignment forward + kv_resize(uint8_t, x_num, (uint64_t)xRegionLen); + kv_resize(uint8_t, y_num, (uint64_t)yRegionLen); + ///text is x, query is y + afine_gap_alignment(x_string+xOffset, x_num.a, xRegionLen, y_string+yOffset, y_num.a, yRegionLen, + c2n, FORWARD_KSW, MATCH_SCORE_KSW, MISMATCH_SCORE_KSW, GAP_OPEN_KSW, GAP_EXT_KSW, + BAND_KSW, Z_DROP_KSW, endbouns, &maxXpos, &maxYpos, &mapGlobalScore, + &mapExtentScore, &xBuoundaryScore, &yBuoundaryScore, &zdroped); + // fprintf(stderr, "# xOffset: %lld, yOffset: %lld, xRegionLen: %lld, yRegionLen: %lld, bandLen: %lld, maxXpos: %lld, maxYpos: %lld, zdroped: %lld\n", + // xOffset, yOffset, xRegionLen, yRegionLen, BAND_KSW, maxXpos, maxYpos, zdroped); + } + + + kv_destroy(x_num); + kv_destroy(y_num); + **/ +} +void Final_phasing(overlap_region_alloc* overlap_list, Cigar_record_alloc* cigarline, +UC_Read* g_read, UC_Read* overlap_read, uint8_t* c2n) +{ + uint64_t i, xLen, yStrand; + char* x_string; + char* y_string; + Cigar_record* cigar; + resize_Cigar_record_alloc(cigarline, overlap_list->length); + + + + for (i = 0; i < overlap_list->length; i++) + { + if(overlap_list->list[i].is_match == 1 || + overlap_list->list[i].is_match == 2 || + overlap_list->list[i].is_match == 3) + { + xLen = overlap_list->list[i].x_pos_e - overlap_list->list[i].x_pos_s + 1; + yStrand = overlap_list->list[i].y_pos_strand; + cigar = &(cigarline->buffer[i]); + ///has already been matched exactly + if(overlap_list->list[i].is_match == 1 && overlap_list->list[i].shared_seed == 1) + { + add_cigar_record(g_read->seq + overlap_list->list[i].x_pos_s, xLen, cigar, 0); + } + else + { + if(yStrand == 0) + { + recover_UC_Read(overlap_read, &R_INF, overlap_list->list[i].y_id); + } + else + { + recover_UC_Read_RC(overlap_read, &R_INF, overlap_list->list[i].y_id); + } + x_string = g_read->seq; + y_string = overlap_read->seq; + + fill_chain(&(overlap_list->list[i].f_cigar), x_string, y_string, + overlap_list->list[i].x_pos_s, overlap_list->list[i].y_pos_s, + Get_READ_LENGTH(R_INF, overlap_list->list[i].x_id), + Get_READ_LENGTH(R_INF, overlap_list->list[i].y_id), cigar, c2n); + } + + } + } + +} + +static void worker_ov_final(void *data, long i, int tid) +{ + ha_ovec_buf_t *b = ((ha_ovec_buf_t**)data)[tid]; + + //get_new_candidates(i, &g_read, &overlap_list, &array_list, &l, 0.001, 0); + ha_get_candidates_interface(b->ab, i, &b->self_read, &b->olist, &b->olist_hp, &b->clist, 0.001, + asm_opt.max_n_chain, 0, NULL/**&(b->k_flag)**/, &b->r_buf, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), &(b->tmp_region), NULL, &(b->sp)); + + overlap_region_sort_y_id(b->olist.list, b->olist.length); + ma_hit_sort_tn(R_INF.paf[i].buffer, R_INF.paf[i].length); + ma_hit_sort_tn(R_INF.reverse_paf[i].buffer, R_INF.reverse_paf[i].length); + + update_overlaps(&b->olist, &(R_INF.paf[i]), &b->self_read, &b->ovlp_read, 1, 1); + update_overlaps(&b->olist, &(R_INF.reverse_paf[i]), &b->self_read, &b->ovlp_read, 2, 0); + ///recover missing exact overlaps + update_exact_overlaps(&b->olist, &b->self_read, &b->ovlp_read); + + ///Final_phasing(&overlap_list, &cigarline, &g_read, &overlap_read, c2n); + push_final_overlaps(&(R_INF.paf[i]), R_INF.reverse_paf, &b->olist, 1); + push_final_overlaps(&(R_INF.reverse_paf[i]), R_INF.reverse_paf, &b->olist, 2); +} + + + + +void reset_final_overlaps(overlap_region_alloc *overlap_list) +{ + + uint64_t i; + for (i = 0; i < overlap_list->length; i++) + { + if (overlap_list->list[i].is_match == 1 || overlap_list->list[i].is_match == 2) + { + overlap_list->list[i].x_pos_s = overlap_list->list[i].x_pos_e = (uint32_t)-1; + overlap_list->list[i].y_pos_s = overlap_list->list[i].y_pos_e = (uint32_t)-1; + overlap_list->list[i].is_match = 0; + } + } + + ha_sort_list_by_anchor(overlap_list); +} + +void debug_affine_gap_alignment(overlap_region_alloc *overlap_list, UC_Read* g_read, UC_Read* overlap_read) +{ + uint64_t i; + kvec_t(uint8_t) x_num; + kvec_t(uint8_t) y_num; + kv_init(x_num); + kv_init(y_num); + for (i = 0; i < overlap_list->length; i++) + { + if (overlap_list->list[i].is_match == 1 && overlap_list->list[i].shared_seed == 1) + { + + kv_resize(uint8_t, x_num, (uint64_t)(Get_READ_LENGTH(R_INF, overlap_list->list[i].x_id))); + kv_resize(uint8_t, y_num, (uint64_t)(Get_READ_LENGTH(R_INF, overlap_list->list[i].y_id))); + + get_affine_gap_score(&(overlap_list->list[i]), g_read, overlap_read, x_num.a, y_num.a, + overlap_list->list[i].x_pos_e + 1 - overlap_list->list[i].x_pos_s, + overlap_list->list[i].y_pos_e + 1 - overlap_list->list[i].y_pos_s); + } + } + + kv_destroy(x_num); + kv_destroy(y_num); +} + +/** +static void worker_ov_final_high_het(void *data, long i, int tid) +{ + ha_ovec_buf_t *b = ((ha_ovec_buf_t**)data)[tid]; + + ha_get_candidates_interface(b->ab, i, &b->self_read, &b->olist, &b->olist_hp, &b->clist, HIGH_HET_ERROR_RATE, + asm_opt.max_n_chain, 1, NULL, &b->r_buf, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), &(b->tmp_region), NULL, &(b->sp)); + + overlap_region_sort_y_id(b->olist.list, b->olist.length); + ma_hit_sort_tn(R_INF.paf[i].buffer, R_INF.paf[i].length); + ma_hit_sort_tn(R_INF.reverse_paf[i].buffer, R_INF.reverse_paf[i].length); + + + ///update_overlaps(&b->olist, &(R_INF.paf[i]), &b->self_read, &b->ovlp_read, 1, 1); + update_overlaps_chain_width(&b->olist, &(R_INF.paf[i]), &b->self_read, &b->ovlp_read, 1, 1, 0.002); + update_overlaps(&b->olist, &(R_INF.reverse_paf[i]), &b->self_read, &b->ovlp_read, 2, 0); + ///recover missing exact overlaps + update_exact_overlaps(&b->olist, &b->self_read, &b->ovlp_read); + + + ///Final_phasing(&overlap_list, &cigarline, &g_read, &overlap_read, c2n); + push_final_overlaps(&(R_INF.paf[i]), R_INF.reverse_paf, &b->olist, 1); + push_final_overlaps(&(R_INF.reverse_paf[i]), R_INF.reverse_paf, &b->olist, 2); + + ///debug_affine_gap_alignment(&b->olist, &b->self_read, &b->ovlp_read); + + reset_final_overlaps(&b->olist); + correct_overlap_high_het(&b->olist, &R_INF, &b->self_read, &b->correct, &b->ovlp_read); + push_final_overlaps_increment(&(R_INF.reverse_paf[i]), R_INF.reverse_paf, &b->olist, 2); +} +**/ + +void Output_PAF() +{ + fprintf(stderr, "Writing PAF to disk ...... \n"); + char* paf_name = (char*)malloc(strlen(asm_opt.output_file_name)+50); + sprintf(paf_name, "%s.ovlp.paf", asm_opt.output_file_name); + FILE* output_file = fopen(paf_name, "w"); + uint64_t i, j; + ma_hit_t_alloc* sources = R_INF.paf; + + for (i = 0; i < R_INF.total_reads; i++) + { + for (j = 0; j < sources[i].length; j++) + { + fwrite(Get_NAME(R_INF, Get_qn(sources[i].buffer[j])), 1, + Get_NAME_LENGTH(R_INF, Get_qn(sources[i].buffer[j])), output_file); + fwrite("\t", 1, 1, output_file); + fprintf(output_file, "%lu\t", (unsigned long)Get_READ_LENGTH(R_INF, Get_qn(sources[i].buffer[j]))); + fprintf(output_file, "%d\t", Get_qs(sources[i].buffer[j])); + fprintf(output_file, "%d\t", Get_qe(sources[i].buffer[j])); + if(sources[i].buffer[j].rev) + { + fprintf(output_file, "-\t"); + } + else + { + fprintf(output_file, "+\t"); + } + fwrite(Get_NAME(R_INF, Get_tn(sources[i].buffer[j])), 1, + Get_NAME_LENGTH(R_INF, Get_tn(sources[i].buffer[j])), output_file); + fwrite("\t", 1, 1, output_file); + fprintf(output_file, "%lu\t", (unsigned long)Get_READ_LENGTH(R_INF, Get_tn(sources[i].buffer[j]))); + fprintf(output_file, "%d\t", Get_ts(sources[i].buffer[j])); + fprintf(output_file, "%d\t", Get_te(sources[i].buffer[j])); + fprintf(output_file, "%d\t", sources[i].buffer[j].ml); + fprintf(output_file, "%d\t", sources[i].buffer[j].bl); + fprintf(output_file, "255\n"); + + } + } + + free(paf_name); + fclose(output_file); + + fprintf(stderr, "PAF has been written.\n"); +} + + +void Output_PAF0(ma_hit_t_alloc* sources, const char *prefix) +{ + fprintf(stderr, "Writing PAF to disk ...... \n"); + char* paf_name = (char*)malloc(strlen(asm_opt.output_file_name)+strlen(prefix)+50); + sprintf(paf_name, "%s.%s.ovlp.paf", asm_opt.output_file_name, prefix); + FILE* output_file = fopen(paf_name, "w"); + uint64_t i, j; + + for (i = 0; i < R_INF.total_reads; i++) + { + for (j = 0; j < sources[i].length; j++) + { + fwrite(Get_NAME(R_INF, Get_qn(sources[i].buffer[j])), 1, + Get_NAME_LENGTH(R_INF, Get_qn(sources[i].buffer[j])), output_file); + fwrite("\t", 1, 1, output_file); + fprintf(output_file, "%lu\t", (unsigned long)Get_READ_LENGTH(R_INF, Get_qn(sources[i].buffer[j]))); + fprintf(output_file, "%d\t", Get_qs(sources[i].buffer[j])); + fprintf(output_file, "%d\t", Get_qe(sources[i].buffer[j])); + if(sources[i].buffer[j].rev) + { + fprintf(output_file, "-\t"); + } + else + { + fprintf(output_file, "+\t"); + } + fwrite(Get_NAME(R_INF, Get_tn(sources[i].buffer[j])), 1, + Get_NAME_LENGTH(R_INF, Get_tn(sources[i].buffer[j])), output_file); + fwrite("\t", 1, 1, output_file); + fprintf(output_file, "%lu\t", (unsigned long)Get_READ_LENGTH(R_INF, Get_tn(sources[i].buffer[j]))); + fprintf(output_file, "%d\t", Get_ts(sources[i].buffer[j])); + fprintf(output_file, "%d\t", Get_te(sources[i].buffer[j])); + fprintf(output_file, "%d\t", sources[i].buffer[j].ml); + fprintf(output_file, "%d\t", sources[i].buffer[j].bl); + fprintf(output_file, "255\n"); + + } + } + + free(paf_name); + fclose(output_file); + + fprintf(stderr, "PAF has been written.\n"); +} + +int check_cluster(uint64_t* list, long long listLen, ma_hit_t_alloc* paf, float threshold) +{ + long long i, k; + uint32_t qn, tn; + long long T_edges, A_edges; + T_edges = A_edges = 0; + for (i = 0; i < listLen; i++) + { + qn = (uint32_t)list[i]; + for (k = i + 1; k < listLen; k++) + { + tn = (uint32_t)list[k]; + if(get_specific_overlap(&(paf[qn]), qn, tn) != -1) + { + A_edges++; + } + + if(get_specific_overlap(&(paf[tn]), tn, qn) != -1) + { + A_edges++; + } + + T_edges = T_edges + 2; + } + + } + + if(A_edges >= (T_edges*threshold)) + { + return 1; + } + else + { + return 0; + } +} + + +void rescue_edges(ma_hit_t_alloc* paf, ma_hit_t_alloc* rev_paf, +long long readNum, long long rescue_threshold, float cluster_threshold) +{ + double startTime = Get_T(); + long long i, j, revises = 0; + uint32_t qn, tn; + + kvec_t(uint64_t) edge_vector; + kv_init(edge_vector); + kvec_t(uint64_t) edge_vector_index; + kv_init(edge_vector_index); + uint64_t flag; + int index; + + for (i = 0; i < readNum; i++) + { + edge_vector.n = 0; + edge_vector_index.n = 0; + for (j = 0; j < paf[i].length; j++) + { + qn = Get_qn(paf[i].buffer[j]); + tn = Get_tn(paf[i].buffer[j]); + index = get_specific_overlap(&(rev_paf[tn]), tn, qn); + if(index != -1) + { + flag = tn; + flag = flag << 32; + flag = flag | (uint64_t)(index); + kv_push(uint64_t, edge_vector, flag); + kv_push(uint64_t, edge_vector_index, j); + } + } + + ///the read itself has these overlaps, but all related reads do not have + ///we need to remove all overlaps from paf[i], and then add all overlaps to rev_paf[i] + if((long long)edge_vector.n >= rescue_threshold && + check_cluster(edge_vector.a, edge_vector.n, paf, cluster_threshold) == 1) + { + add_overlaps(&(paf[i]), &(rev_paf[i]), edge_vector_index.a, edge_vector_index.n); + remove_overlaps(&(paf[i]), edge_vector_index.a, edge_vector_index.n); + revises = revises + edge_vector.n; + } + + edge_vector.n = 0; + edge_vector_index.n = 0; + for (j = 0; j < rev_paf[i].length; j++) + { + qn = Get_qn(rev_paf[i].buffer[j]); + tn = Get_tn(rev_paf[i].buffer[j]); + index = get_specific_overlap(&(paf[tn]), tn, qn); + if(index != -1) + { + flag = tn; + flag = flag << 32; + flag = flag | (uint64_t)(index); + kv_push(uint64_t, edge_vector, flag); + kv_push(uint64_t, edge_vector_index, j); + } + } + + ///the read itself do not have these overlaps, but all related reads have + ///we need to remove all overlaps from rev_paf[i], and then add all overlaps to paf[i] + if((long long)edge_vector.n >= rescue_threshold && + check_cluster(edge_vector.a, edge_vector.n, paf, cluster_threshold) == 1) + { + remove_overlaps(&(rev_paf[i]), edge_vector_index.a, edge_vector_index.n); + add_overlaps_from_different_sources(paf, &(paf[i]), edge_vector.a, edge_vector.n); + revises = revises + edge_vector.n; + } + } + + + kv_destroy(edge_vector); + kv_destroy(edge_vector_index); + + fprintf(stderr, "[M::%s] took %0.2fs, revise edges #: %lld\n\n", __func__, Get_T()-startTime, revises); +} + +void hap_recalculate_peaks(char* output_file_name) +{ + destory_read_bin(&R_INF); + destory_ma_hit_t_alloc(R_INF.paf); + destory_ma_hit_t_alloc(R_INF.reverse_paf); + + char* gfa_name = (char*)malloc(strlen(output_file_name)+25); + sprintf(gfa_name, "%s.ec", output_file_name); + + int hom_cov, het_cov; + // construct hash table for high occurrence k-mers + if (!(asm_opt.flag & HA_F_NO_KMER_FLT)) { + ha_flt_tab = ha_ft_gen(&asm_opt, &R_INF, &hom_cov, 0, 0); + ha_opt_update_cov(&asm_opt, hom_cov); + } + free(R_INF.read_length); + free(R_INF.name_index); + + load_All_reads(&R_INF, gfa_name); + + ha_idx = ha_pt_gen(&asm_opt, ha_flt_tab, 1, 0, &R_INF, &hom_cov, &het_cov); // build the index + asm_opt.hom_cov = hom_cov; + asm_opt.het_cov = het_cov; + ha_pt_destroy(ha_idx); + ha_idx = 0; + + destory_read_bin(&R_INF); + free(gfa_name); + + load_all_data_from_disk(&R_INF.paf, &R_INF.reverse_paf, asm_opt.output_file_name); + fprintf(stderr, "M::%s has done.\n", __func__); +} + +void ha_overlap_final(void) +{ + int i, hom_cov, het_cov; + ha_ovec_buf_t **b; + ha_flt_tab_hp = ha_idx_hp = NULL; + + CALLOC(b, asm_opt.thread_num); + for (i = 0; i < asm_opt.thread_num; ++i) + b[i] = ha_ovec_init(asm_opt.flag & HA_F_HIGH_HET, 1,0);///b[i] = ha_ovec_init(1, 1); + ha_idx = ha_pt_gen(&asm_opt, ha_flt_tab, 1, 0, &R_INF, &hom_cov, &het_cov); // build the index + // if(asm_opt.flag & HA_F_HIGH_HET) + // { + // kt_for(asm_opt.thread_num, worker_ov_final_high_het, b, R_INF.total_reads); + // } + // else + { + kt_for(asm_opt.thread_num, worker_ov_final, b, R_INF.total_reads); + } + + ha_pt_destroy(ha_idx); + ha_idx = 0; + for (i = 0; i < asm_opt.thread_num; ++i) + ha_ovec_destroy(b[i]); + free(b); + asm_opt.hom_cov = hom_cov; + asm_opt.het_cov = het_cov; +} + +void ha_ec_ff(int renew_idx) +{ + int hom_cov, het_cov; + ha_flt_tab_hp = ha_idx_hp = NULL; + + if(ha_idx && renew_idx) { + ha_pt_destroy(ha_idx); ha_idx = NULL; + } + + if(!ha_idx) { + ha_idx = ha_pt_gen(&asm_opt, ha_flt_tab, 1, 0, &R_INF, &hom_cov, &het_cov); // build the index + asm_opt.hom_cov = hom_cov; asm_opt.het_cov = het_cov; + } + + cal_ov_r(asm_opt.thread_num, R_INF.total_reads, renew_idx); + + if(asm_opt.write_pos_idx) { + refresh_pt_idx(&ha_flt_tab, &ha_idx, NULL, &asm_opt, asm_opt.output_file_name, 1); + // write_pt_index(ha_flt_tab, ha_idx, NULL, &asm_opt, asm_opt.output_file_name); + } else { + ha_pt_destroy(ha_idx); ha_idx = NULL; + } +} + +static void worker_ov_utg(void *data, long i, int tid) +{ + ha_ovec_buf_t *b = ((ha_ovec_buf_t**)data)[tid]; + if(b->ua->a[i].len == 0) return; + + ha_get_ug_candidates(b->ab, i, &(b->ua->a[i]), b->ua, &b->olist, &b->clist, + 0.3, asm_opt.polyploidy*5, 0, &(b->k_flag), &b->r_buf, ha_flt_tab, ha_idx, + &(b->tmp_region), NULL, /**0.3**/0); + + overlap_region_sort_y_id(b->olist.list, b->olist.length); + ma_hit_sort_tn(R_INF.paf[i].buffer, R_INF.paf[i].length); + ma_hit_sort_tn(R_INF.reverse_paf[i].buffer, R_INF.reverse_paf[i].length); + + update_overlaps(&b->olist, &(R_INF.paf[i]), &b->self_read, &b->ovlp_read, 1, 1); + update_overlaps(&b->olist, &(R_INF.reverse_paf[i]), &b->self_read, &b->ovlp_read, 2, 0); + ///recover missing exact overlaps + update_exact_overlaps(&b->olist, &b->self_read, &b->ovlp_read); + + ///Final_phasing(&overlap_list, &cigarline, &g_read, &overlap_read, c2n); + push_final_overlaps(&(R_INF.paf[i]), R_INF.reverse_paf, &b->olist, 1); + push_final_overlaps(&(R_INF.reverse_paf[i]), R_INF.reverse_paf, &b->olist, 2); +} + + +void ug_idx_build(ma_ug_t *ug, int hap_n) +{ + int flag = asm_opt.flag&HA_F_NO_HPC, i; + asm_opt.flag -= flag; + // ha_flt_tab = ha_ft_ug_gen(&asm_opt, &(ug->u), hap_n, hap_n); + // ha_idx = ha_pt_ug_gen(&asm_opt, ha_flt_tab, &(ug->u), hap_n); + + ha_ovec_buf_t **b = NULL; + // overlap and correct reads + CALLOC(b, asm_opt.thread_num); + for (i = 0; i < asm_opt.thread_num; ++i) + { + b[i] = ha_ovec_init(1, 1, 0); + b[i]->ua = &(ug->u); + } + + kt_for(asm_opt.thread_num, worker_ov_utg, b, R_INF.total_reads); + + for (i = 0; i < asm_opt.thread_num; ++i) + ha_ovec_destroy(b[i]); + free(b); + + ha_ft_destroy(ha_flt_tab); + ha_pt_destroy(ha_idx); + asm_opt.flag += flag; + exit(1); +} + +int ha_assemble_ovec(void) +{ + extern void ha_extract_print_list(const All_reads *rs, int n_rounds, const char *o); + int r = 0, hom_cov = -1; + + ha_flt_tab = ha_idx = NULL; + + // construct hash table for high occurrence k-mers + if (!(asm_opt.flag & HA_F_NO_KMER_FLT) && ha_flt_tab == NULL) { + ha_flt_tab = ha_ft_gen(&asm_opt, &R_INF, &hom_cov, 0, 0); + ha_opt_update_cov(&asm_opt, hom_cov); + } + // error correction + assert(asm_opt.number_of_round > 0); + ha_opt_reset_to_round(&asm_opt, r); // this update asm_opt.roundID and a few other fields + ha_overlap_cal(r, 0); + fprintf(stderr, "[M::%s] size of buffer: %.3fGB\n", __func__, asm_opt.mem_buf / 1073741824.0); + + + ha_print_ovlp_stat(R_INF.paf, R_INF.reverse_paf, R_INF.total_reads); + ha_ft_destroy(ha_flt_tab); + + Output_PAF0(R_INF.paf, "0"); + Output_PAF0(R_INF.reverse_paf, "1"); + if (asm_opt.flag & HA_F_WRITE_PAF) Output_PAF(); + + destory_All_reads(&R_INF); + return 0; +} + +int ha_assemble_ovec_cc(void) +{ + ha_idx = NULL; + + ha_opt_reset_to_round(&asm_opt, 0); // this update asm_opt.roundID and a few other fields + ha_ec_dbg(); + + // Output_PAF0(R_INF.paf, "0"); + destory_All_reads(&R_INF); + return 0; +} + +int ha_assemble(void) +{ + // debug_mc_g_t(MC_NAME); + // debug_mc_gg_t(MC_NAME, 0, 0); + // quick_debug_phasing(MC_NAME); + extern void ha_extract_print_list(const All_reads *rs, int n_rounds, const char *o); + int r, r0 = -1, hom_cov = -1, ovlp_loaded = 0; uint64_t tot_b, tot_e; + if (asm_opt.load_index_from_disk && load_all_data_from_disk(&R_INF.paf, &R_INF.reverse_paf, asm_opt.output_file_name)) { + ovlp_loaded = 1; + fprintf(stderr, "[M::%s::%.3f*%.2f] ==> loaded corrected reads and overlaps from disk\n", __func__, yak_realtime(), yak_cpu_usage()); + if (asm_opt.extract_list) { + ha_extract_print_list(&R_INF, asm_opt.extract_iter, asm_opt.extract_list); + exit(0); + } + if (asm_opt.flag & HA_F_WRITE_EC) { + if(asm_opt.is_sc) Output_corrected_fastq(); + else Output_corrected_reads(); + } + if (asm_opt.flag & HA_F_WRITE_PAF) Output_PAF(); + if (asm_opt.het_cov == -1024) hap_recalculate_peaks(asm_opt.output_file_name), ovlp_loaded = 2; + } + if (!ovlp_loaded) { + ha_flt_tab = ha_idx = NULL; + if((asm_opt.flag & HA_F_VERBOSE_GFA)) load_pt_index(&ha_flt_tab, &ha_idx, &R_INF, &asm_opt, asm_opt.output_file_name), load_ct_index(&ha_ct_table, asm_opt.output_file_name); + r = ha_idx?asm_opt.number_of_round-1:0; + if((!ha_idx) && (asm_opt.restart)) { + for (r = asm_opt.number_of_round - 1; r >= 0; --r) { + if(tmp_pt_pro(&ha_flt_tab, &ha_idx, &R_INF, &asm_opt, asm_opt.output_file_name, r, asm_opt.number_of_round, 1)) { + load_ct_index(&ha_ct_table, asm_opt.output_file_name); r0 = r; + break; + } + } + if(r < 0) r = 0; + } + + // construct hash table for high occurrence k-mers + if (!(asm_opt.flag & HA_F_NO_KMER_FLT) && ha_flt_tab == NULL) { + ha_flt_tab = ha_ft_gen(&asm_opt, &R_INF, &hom_cov, 0, 0); + ha_opt_update_cov(&asm_opt, hom_cov); + } + // error correction + assert(asm_opt.number_of_round > 0); + for (; r < asm_opt.number_of_round; ++r) { + ha_opt_reset_to_round(&asm_opt, r); // this update asm_opt.roundID and a few other fields + tot_b = tot_e = 0; + // ha_overlap_and_correct(r); + ha_ec(r, asm_opt.number_of_pround, (r r0) && (asm_opt.restart))?1:0); + fprintf(stderr, "[M::%s::%.3f*%.2f@%.3fGB] ==> corrected reads for round %d\n", __func__, yak_realtime(), + yak_cpu_usage(), yak_peakrss_in_gb(), r + 1); + fprintf(stderr, "[M::%s] # bases: %lu; # corrected bases: %lu\n", __func__, tot_b, tot_e); + // fprintf(stderr, "[M::%s] # bases: %lld; # corrected bases: %lld; # recorrected bases: %lld\n", __func__, + // asm_opt.num_bases, asm_opt.num_corrected_bases, asm_opt.num_recorrected_bases); + // fprintf(stderr, "[M::%s] size of buffer: %.3fGB\n", __func__, asm_opt.mem_buf / 1073741824.0); + } + if (asm_opt.flag & HA_F_WRITE_EC) { + if(asm_opt.is_sc) Output_corrected_fastq(); + else Output_corrected_reads(); + } + // overlap between corrected reads + ha_opt_reset_to_round(&asm_opt, asm_opt.number_of_round); + // ha_overlap_final(); + ha_ec_ff(1/**0**/); + fprintf(stderr, "[M::%s::%.3f*%.2f@%.3fGB] ==> found overlaps for the final round\n", __func__, yak_realtime(), yak_cpu_usage(), yak_peakrss_in_gb()); + // fprintf(stderr, "\n[M::%s::%.3f*%.2f@%.3fGB] ==> found overlaps for the final round\n", __func__, yak_realtime(), yak_cpu_usage(), yak_peakrss_in_gb()); + // ha_print_ovlp_stat(R_INF.paf, R_INF.reverse_paf, R_INF.total_reads); + if(!(asm_opt.write_pos_idx)) ha_ft_destroy(ha_flt_tab); + if (asm_opt.flag & HA_F_WRITE_PAF) Output_PAF(); + ha_triobin(&asm_opt); + + // exit(1); + } + if(ovlp_loaded == 2) ovlp_loaded = 0; + ha_opt_update_cov_min(&asm_opt, asm_opt.hom_cov, MIN_N_CHAIN); + + build_string_graph_without_clean(asm_opt.min_overlap_coverage, R_INF.paf, R_INF.reverse_paf, + R_INF.total_reads, R_INF.read_length, asm_opt.min_overlap_Len, asm_opt.max_hang_Len, asm_opt.clean_round, + asm_opt.gap_fuzz, asm_opt.min_drop_rate, asm_opt.max_drop_rate, asm_opt.output_file_name, asm_opt.large_pop_bubble_size, 0, !ovlp_loaded); + destory_All_reads(&R_INF); + return 0; +} + + +int ha_assemble_pair(void) +{ + extern void ha_extract_print_list(const All_reads *rs, int n_rounds, const char *o); + int r = 0, hom_cov = -1, ovlp_loaded = 0; memset((&R_INF), 0, sizeof(R_INF)); + + if (asm_opt.load_index_from_disk && load_all_data_from_disk(&R_INF.paf, &R_INF.reverse_paf, asm_opt.output_file_name)) { + ovlp_loaded = 1; + fprintf(stderr, "[M::%s::%.3f*%.2f] ==> loaded corrected reads and overlaps from disk\n", __func__, yak_realtime(), yak_cpu_usage()); + if (asm_opt.extract_list) { + ha_extract_print_list(&R_INF, asm_opt.extract_iter, asm_opt.extract_list); + exit(0); + } + if (asm_opt.flag & HA_F_WRITE_EC) Output_corrected_reads(); + if (asm_opt.flag & HA_F_WRITE_PAF) Output_PAF(); + if (asm_opt.het_cov == -1024) hap_recalculate_peaks(asm_opt.output_file_name), ovlp_loaded = 2; + } + + + if (!ovlp_loaded) { + + if(!append_All_reads(&R_INF, asm_opt.output_file_name, 0)) { + fprintf(stderr, "[M::%s::] Cannot load %s.0\n", __func__, asm_opt.output_file_name); + exit(1); + } + + if(!append_All_reads(&R_INF, asm_opt.output_file_name, 1)) { + fprintf(stderr, "[M::%s::] Cannot load %s.1\n", __func__, asm_opt.output_file_name); + exit(1); + } + // Output_corrected_reads(); exit(0); + + ha_flt_tab = ha_idx = NULL; r = asm_opt.number_of_round - 1; + if((asm_opt.flag & HA_F_VERBOSE_GFA)) load_pt_index(&ha_flt_tab, &ha_idx, &R_INF, &asm_opt, asm_opt.output_file_name), load_ct_index(&ha_ct_table, asm_opt.output_file_name); + + // construct hash table for high occurrence k-mers + if (!(asm_opt.flag & HA_F_NO_KMER_FLT) && ha_flt_tab == NULL) { + ha_flt_tab = ha_ft_gen(&asm_opt, &R_INF, &hom_cov, 0, 1); + ha_opt_update_cov(&asm_opt, hom_cov); + } + // error correction + assert(asm_opt.number_of_round > 0); + ha_opt_reset_to_round(&asm_opt, r); // this update asm_opt.roundID and a few other fields + ha_overlap_cal(r, 1); + fprintf(stderr, "[M::%s] size of buffer: %.3fGB\n", __func__, asm_opt.mem_buf / 1073741824.0); + fprintf(stderr, "[M::%s::%.3f*%.2f@%.3fGB] ==> found overlaps for the final round\n", __func__, yak_realtime(), + yak_cpu_usage(), yak_peakrss_in_gb()); + + + if (asm_opt.flag & HA_F_WRITE_EC) Output_corrected_reads(); + ha_print_ovlp_stat(R_INF.paf, R_INF.reverse_paf, R_INF.total_reads); + ha_ft_destroy(ha_flt_tab); + if (asm_opt.flag & HA_F_WRITE_PAF) Output_PAF(); + ha_triobin(&asm_opt); + + } + if(ovlp_loaded == 2) ovlp_loaded = 0; + ha_opt_update_cov_min(&asm_opt, asm_opt.hom_cov, MIN_N_CHAIN); + + build_string_graph_without_clean(asm_opt.min_overlap_coverage, R_INF.paf, R_INF.reverse_paf, + R_INF.total_reads, R_INF.read_length, asm_opt.min_overlap_Len, asm_opt.max_hang_Len, asm_opt.clean_round, + asm_opt.gap_fuzz, asm_opt.min_drop_rate, asm_opt.max_drop_rate, asm_opt.output_file_name, asm_opt.large_pop_bubble_size, 0, !ovlp_loaded); + destory_All_reads(&R_INF); + return 0; } \ No newline at end of file diff --git a/Assembly.h b/Assembly.h index 08e3d45..eb6f2e3 100644 --- a/Assembly.h +++ b/Assembly.h @@ -1,56 +1,56 @@ -#ifndef __ASSEMBLY__ -#define __ASSEMBLY__ -#include "CommandLines.h" -#include "Overlaps.h" -#include "Process_Read.h" -#include "Hash_Table.h" -#include "Correct.h" - -#define FORWARD 0 -#define REVERSE_COMPLEMENT (0x8000000000000000) - -#define Get_Cigar_Type(RECORD) (RECORD&3) -#define Get_Cigar_Length(RECORD) (RECORD>>2) - -#define RESEED_DP 4 -#define RESEED_PEAK_RATE 0.15 -#define RESEED_LEN 2000 -#define RESEED_HP_RATE 0.9 - -typedef struct { - int is_final, save_ov; - // chaining and overlapping related buffers - UC_Read self_read, ovlp_read; - Candidates_list clist; - overlap_region_alloc olist; - overlap_region_alloc olist_hp; - ha_abuf_t *ab; - ha_abufl_t *abl; - // error correction related buffers - int64_t num_read_base, num_correct_base, num_recorrect_base; - Cigar_record cigar1; - Graph POA_Graph; - Graph DAGCon; - Correct_dumy correct; - haplotype_evdience_alloc hap; - Round2_alignment round2; - kvec_t_u32_warp b_buf; - kvec_t_u64_warp r_buf; - kvec_t_u8_warp k_flag; - overlap_region tmp_region; - ma_utg_v *ua; - st_mt_t sp; - bit_extz_t exz; -} ha_ovec_buf_t; - -int ha_assemble(void); -int ha_assemble_pair(void); -void ug_idx_build(ma_ug_t *ug, int hap_n); -ha_ovec_buf_t *ha_ovec_init(int is_final, int save_ov, int is_ug); -ha_ovec_buf_t *ha_ovec_buf_init(void *km, int is_final, int save_ov, int is_ug); -void ha_ovec_destroy(ha_ovec_buf_t *b); -int64_t ha_ovec_mem(const ha_ovec_buf_t *b, int64_t *mem_a); -int ha_assemble_ovec(void); -int ha_ec_dbg(void); - -#endif +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ +#include "CommandLines.h" +#include "Overlaps.h" +#include "Process_Read.h" +#include "Hash_Table.h" +#include "Correct.h" + +#define FORWARD 0 +#define REVERSE_COMPLEMENT (0x8000000000000000) + +#define Get_Cigar_Type(RECORD) (RECORD&3) +#define Get_Cigar_Length(RECORD) (RECORD>>2) + +#define RESEED_DP 4 +#define RESEED_PEAK_RATE 0.15 +#define RESEED_LEN 2000 +#define RESEED_HP_RATE 0.9 + +typedef struct { + int is_final, save_ov; + // chaining and overlapping related buffers + UC_Read self_read, ovlp_read; + Candidates_list clist; + overlap_region_alloc olist; + overlap_region_alloc olist_hp; + ha_abuf_t *ab; + ha_abufl_t *abl; + // error correction related buffers + int64_t num_read_base, num_correct_base, num_recorrect_base; + Cigar_record cigar1; + Graph POA_Graph; + Graph DAGCon; + Correct_dumy correct; + haplotype_evdience_alloc hap; + Round2_alignment round2; + kvec_t_u32_warp b_buf; + kvec_t_u64_warp r_buf; + kvec_t_u8_warp k_flag; + overlap_region tmp_region; + ma_utg_v *ua; + st_mt_t sp; + bit_extz_t exz; +} ha_ovec_buf_t; + +int ha_assemble(void); +int ha_assemble_pair(void); +void ug_idx_build(ma_ug_t *ug, int hap_n); +ha_ovec_buf_t *ha_ovec_init(int is_final, int save_ov, int is_ug); +ha_ovec_buf_t *ha_ovec_buf_init(void *km, int is_final, int save_ov, int is_ug); +void ha_ovec_destroy(ha_ovec_buf_t *b); +int64_t ha_ovec_mem(const ha_ovec_buf_t *b, int64_t *mem_a); +int ha_assemble_ovec(void); +int ha_ec_dbg(void); + +#endif diff --git a/CommandLines.cpp b/CommandLines.cpp index 256a35a..aa63f9b 100644 --- a/CommandLines.cpp +++ b/CommandLines.cpp @@ -1,1048 +1,1121 @@ -#define __STDC_LIMIT_MACROS -#include -#include -#include -#include -#include -#include -#include "CommandLines.h" -#include "ketopt.h" -#include "kseq.h" - -KSEQ_INIT(gzFile, gzread) - -#define DEFAULT_OUTPUT "hifiasm.asm" - -hifiasm_opt_t asm_opt; - -static ko_longopt_t long_options[] = { - { "version", ko_no_argument, 300 }, - { "dbg-gfa", ko_no_argument, 301 }, - { "write-paf", ko_no_argument, 302 }, - { "write-ec", ko_no_argument, 303 }, - { "skip-triobin", ko_no_argument, 304 }, - { "max-od-ec", ko_required_argument, 305 }, - { "max-od-final", ko_required_argument, 306 }, - { "ex-list", ko_required_argument, 307 }, - { "ex-iter", ko_required_argument, 308 }, - { "hom-cov", ko_required_argument, 309 }, - { "pri-range", ko_required_argument, 310 }, - { "lowQ", ko_required_argument, 312 }, - { "min-hist-cnt", ko_required_argument, 313 }, - { "h1", ko_required_argument, 314 }, - { "h2", ko_required_argument, 315 }, - { "enzyme", ko_required_argument, 316 }, - { "b-cov", ko_required_argument, 317 }, - { "h-cov", ko_required_argument, 318 }, - { "m-rate", ko_required_argument, 319 }, - { "primary", ko_no_argument, 320 }, - { "t-occ", ko_required_argument, 321 }, - { "seed", ko_required_argument, 322 }, - { "n-perturb", ko_required_argument, 323 }, - { "f-perturb", ko_required_argument, 324 }, - { "n-hap", ko_required_argument, 325 }, - { "n-weight", ko_required_argument, 326 }, - { "l-msjoin", ko_required_argument, 327 }, - { "purge-max", ko_required_argument, 328 }, - { "fast", ko_no_argument, 329 }, - { "dp-er", ko_required_argument, 330}, - { "max-kocc", ko_required_argument, 331}, - { "hg-size", ko_required_argument, 332}, - { "ul", ko_required_argument, 333}, - { "unskew", ko_no_argument, 334}, - { "kpt-rate", ko_required_argument, 335}, - { "ul-rate", ko_required_argument, 336}, - { "dbg-het-cnt", ko_no_argument, 337}, - { "ul-tip", ko_required_argument, 338}, - { "low-het", ko_no_argument, 339}, - { "s-base", ko_required_argument, 340}, - { "bin-only", ko_no_argument, 341}, - { "ul-round", ko_required_argument, 342}, - { "prt-raw", ko_no_argument, 343}, - { "integer-correct", ko_required_argument, 344}, - { "dbg-ovec", ko_no_argument, 345}, - { "path-max", ko_required_argument, 346}, - { "path-min", ko_required_argument, 347}, - { "trio-dual", ko_no_argument, 348}, - { "ul-cut", ko_required_argument, 349}, - { "dual-scaf", ko_no_argument, 350}, - { "scaf-gap", ko_required_argument, 351}, - { "sec-in", ko_required_argument, 352}, - { "somatic-cov", ko_required_argument, 353}, - { "telo-m", ko_required_argument, 354}, - { "telo-p", ko_required_argument, 355}, - { "telo-d", ko_required_argument, 356}, - { "telo-s", ko_required_argument, 357}, - { "ctg-n", ko_required_argument, 358}, - { "ont", ko_no_argument, 359}, - // { "sc-n", ko_no_argument, 360}, - { "chem-c", ko_required_argument, 361}, - { "chem-f", ko_required_argument, 362}, - { "ul-m", ko_required_argument, 363}, - { "rl-cut", ko_required_argument, 364}, - { "sc-cut", ko_required_argument, 365}, - // { "path-round", ko_required_argument, 348}, - { 0, 0, 0 } -}; - -double Get_T(void) -{ - struct timeval t; - gettimeofday(&t, NULL); - return t.tv_sec+t.tv_usec/1000000.0; -} - -void Print_H(hifiasm_opt_t* asm_opt) -{ - fprintf(stderr, "Usage: hifiasm [options] <...>\n"); - fprintf(stderr, "Options:\n"); - fprintf(stderr, " Input/Output:\n"); - fprintf(stderr, " -o STR prefix of output files [%s]\n", asm_opt->output_file_name); - fprintf(stderr, " -t INT number of threads [%d]\n", asm_opt->thread_num); - fprintf(stderr, " -h show help information\n"); - fprintf(stderr, " --version show version number\n"); - fprintf(stderr, " Preset options:\n"); - fprintf(stderr, " --ont assemble Oxford Nanopore reads\n"); - fprintf(stderr, " Overlap/Error correction:\n"); - fprintf(stderr, " -k INT k-mer length (must be <64) [%d]\n", asm_opt->k_mer_length); - fprintf(stderr, " -w INT minimizer window size [%d]\n", asm_opt->mz_win); - fprintf(stderr, " -f INT number of bits for bloom filter; 0 to disable [%d]\n", asm_opt->bf_shift); - fprintf(stderr, " -D FLOAT drop k-mers occurring >FLOAT*coverage times [%.1f]\n", asm_opt->high_factor); - fprintf(stderr, " -N INT consider up to max(-D*coverage,-N) overlaps for each oriented read [%d]\n", asm_opt->max_n_chain); - fprintf(stderr, " -r INT round of correction [%d]\n", asm_opt->number_of_round); - fprintf(stderr, " -z INT length of adapters that should be removed [%d]\n", asm_opt->adapterLen); - fprintf(stderr, " --max-kocc INT\n"); - fprintf(stderr, " employ k-mers occurring max_kmer_cnt); - fprintf(stderr, " --hg-size INT(k, m or g)\n"); - fprintf(stderr, " estimated haploid genome size used for inferring read coverage [auto]\n"); - fprintf(stderr, " Assembly:\n"); - fprintf(stderr, " -a INT round of assembly cleaning [%d]\n", asm_opt->clean_round); - fprintf(stderr, " -m INT pop bubbles of large_pop_bubble_size); - fprintf(stderr, " -p INT pop bubbles of small_pop_bubble_size); - fprintf(stderr, " -n INT remove tip unitigs composed of <=INT reads [%d]\n", asm_opt->max_short_tip); - fprintf(stderr, " -x FLOAT max overlap drop ratio [%.2g]\n", asm_opt->max_drop_rate); - fprintf(stderr, " -y FLOAT min overlap drop ratio [%.2g]\n", asm_opt->min_drop_rate); - fprintf(stderr, " -i ignore saved read correction and overlaps\n"); - fprintf(stderr, " -u post-join step for contigs which may improve N50; 0 to disable; 1 to enable\n"); - fprintf(stderr, " [%u] and [%u] in default for the UL+HiFi assembly and the HiFi assembly, respectively\n", - asm_opt->ul_pst_join, asm_opt->hifi_pst_join); - fprintf(stderr, " --hom-cov INT\n"); - fprintf(stderr, " homozygous read coverage [auto]\n"); - fprintf(stderr, " --lowQ INT\n"); - fprintf(stderr, " output contig regions with >=INT%% inconsistency in BED format; 0 to disable [%d]\n", asm_opt->bed_inconsist_rate); - fprintf(stderr, " --b-cov INT\n"); - fprintf(stderr, " break contigs at positions with b_low_cov); - fprintf(stderr, " --h-cov INT\n"); - fprintf(stderr, " break contigs at positions with >INT-fold coverage; work with '--m-rate'; -1 to disable [%d]\n", asm_opt->b_high_cov); - fprintf(stderr, " --m-rate FLOAT\n"); - fprintf(stderr, " break contigs at positions with <=FLOAT*coverage exact overlaps;\n"); - fprintf(stderr, " only work with '--b-cov' or '--h-cov'[%.2f]\n", asm_opt->m_rate); - fprintf(stderr, " --primary output a primary assembly and an alternate assembly\n"); - fprintf(stderr, " --ctg-n INT\n"); - fprintf(stderr, " remove tip contigs composed of <=INT reads [%d]\n", asm_opt->max_contig_tip); - - -// fprintf(stderr, " --pri-range INT1[,INT2]\n"); -// fprintf(stderr, " keep contigs with coverage in this range in p_ctg.gfa; -1 to disable [auto,inf]\n"); - - fprintf(stderr, " Trio-partition:\n"); - fprintf(stderr, " -1 FILE hap1/paternal k-mer dump generated by \"yak count\" []\n"); - fprintf(stderr, " -2 FILE hap2/maternal k-mer dump generated by \"yak count\" []\n"); - fprintf(stderr, " -3 FILE list of hap1/paternal read names []\n"); - fprintf(stderr, " -4 FILE list of hap2/maternal read names []\n"); - fprintf(stderr, " -c INT lower bound of the binned k-mer's frequency [%d]\n", asm_opt->min_cnt); - fprintf(stderr, " -d INT upper bound of the binned k-mer's frequency [%d]\n", asm_opt->mid_cnt); - fprintf(stderr, " --t-occ INT\n"); - fprintf(stderr, " forcedly remove unitigs with >INT unexpected haplotype-specific reads;\n"); - fprintf(stderr, " ignore graph topology; [%d]\n", asm_opt->trio_flag_occ_thres); - fprintf(stderr, " --trio-dual utilize homology information to correct trio phasing errors\n"); - - - fprintf(stderr, " Purge-dups:\n"); - fprintf(stderr, " -l INT purge level. 0: no purging; 1: light; 2/3: aggressive [0 for trio; 3 for unzip]\n"); - fprintf(stderr, " -s FLOAT similarity threshold for duplicate haplotigs in read-level [%g for -l1/-l2, %g for -l3]\n", - asm_opt->purge_simi_rate_l2, asm_opt->purge_simi_rate_l3); - fprintf(stderr, " -O INT min number of overlapped reads for duplicate haplotigs [%d]\n", - asm_opt->purge_overlap_len); - fprintf(stderr, " --purge-max INT\n"); - fprintf(stderr, " coverage upper bound of Purge-dups [auto]\n"); - fprintf(stderr, " --n-hap INT\n"); - fprintf(stderr, " number of haplotypes [%d]\n", asm_opt->polyploidy); - - // fprintf(stderr, " Hi-C-partition [experimental, not stable]:\n"); - fprintf(stderr, " Hi-C-partition:\n"); - fprintf(stderr, " --h1 FILEs file names of Hi-C R1 [r1_1.fq,r1_2.fq,...]\n"); - fprintf(stderr, " --h2 FILEs file names of Hi-C R2 [r2_1.fq,r2_2.fq,...]\n"); - fprintf(stderr, " --seed INT RNG seed [%lu]\n", asm_opt->seed); - fprintf(stderr, " --s-base FLOAT\n"); - fprintf(stderr, " similarity threshold for homology detection in base-level;\n"); - fprintf(stderr, " -1 to disable [%.3g]; -s for read-level (see )\n", asm_opt->trans_base_rate_sec); - - fprintf(stderr, " --n-weight INT\n"); - fprintf(stderr, " rounds of reweighting Hi-C links [%d]\n", asm_opt->n_weight); - fprintf(stderr, " --n-perturb INT\n"); - fprintf(stderr, " rounds of perturbation [%d]\n", asm_opt->n_perturb); - fprintf(stderr, " --f-perturb FLOAT\n"); - fprintf(stderr, " fraction to flip for perturbation [%.3g]\n", asm_opt->f_perturb); - fprintf(stderr, " --l-msjoin INT\n"); - fprintf(stderr, " detect misjoined unitigs of >=INT in size; 0 to disable [%lu]\n", asm_opt->misjoin_len); - - fprintf(stderr, " Ultra-Long-integration:\n"); - fprintf(stderr, " --ul FILEs file names of Ultra-Long reads [r1.fq,r2.fq,...]\n"); - ///pending for integration - /** - fprintf(stderr, " --ul-m INT\n"); - fprintf(stderr, " hybrid assembly mode. 0: fast and memory efficent; 1: may produce better assembly with ONT R10 [%d]\n", asm_opt->ul_mod); - **/ - fprintf(stderr, " --ul-rate FLOAT\n"); - fprintf(stderr, " error rate of Ultra-Long reads [%.3g]\n", asm_opt->ul_error_rate); - fprintf(stderr, " --ul-tip INT\n"); - fprintf(stderr, " remove tip unitigs composed of <=INT reads for the UL assembly [%d]\n", asm_opt->max_short_ul_tip); - fprintf(stderr, " --path-max FLOAT\n"); - fprintf(stderr, " max path drop ratio [%.2g]; higher number may make the assembly cleaner\n", asm_opt->max_path_drop_rate); - fprintf(stderr, " but may lead to more misassemblies\n"); - fprintf(stderr, " --path-min FLOAT\n"); - fprintf(stderr, " min path drop ratio [%.2g]; higher number may make the assembly cleaner\n", asm_opt->min_path_drop_rate); - fprintf(stderr, " but may lead to more misassemblies\n"); - fprintf(stderr, " --ul-cut INT\n"); - fprintf(stderr, " filter out ul_min_base); - // fprintf(stderr, " --low-het enable it for genomes with very low het heterozygosity rate (<0.0001%%)\n"); - - fprintf(stderr, " Dual-Scaffolding:\n"); - fprintf(stderr, " --dual-scaf output scaffolding\n"); - fprintf(stderr, " --scaf-gap INT\n"); - fprintf(stderr, " max gap size for scaffolding [%ld]\n", asm_opt->self_scaf_gap_max); - - fprintf(stderr, " Telomere-identification:\n"); - fprintf(stderr, " --telo-m STR\n"); - fprintf(stderr, " telomere motif at 5'-end; CCCTAA for human [%s]\n", ((asm_opt->telo_motif)?(asm_opt->telo_motif):("NULL")));///5'-end, check CCCTAA - fprintf(stderr, " --telo-p INT\n"); - fprintf(stderr, " non-telomeric penalty [%ld]\n", asm_opt->telo_pen); - fprintf(stderr, " --telo-d INT\n"); - fprintf(stderr, " max drop [%ld]\n", asm_opt->telo_drop); - fprintf(stderr, " --telo-s INT\n"); - fprintf(stderr, " min score for telomere reads [%ld]\n", asm_opt->telo_mic_sc); - - fprintf(stderr, " ONT simplex assembly (beta):\n"); - fprintf(stderr, " --ont assemble ONT simplex reads in fastq format\n"); - // fprintf(stderr, " --sc-n consider base qual value for assembly\n"); - fprintf(stderr, " --chem-c INT\n"); - fprintf(stderr, " detect chimeric reads with <=INT other reads support [%lu]\n", asm_opt->chemical_cov); - fprintf(stderr, " --chem-f INT\n"); - fprintf(stderr, " length of flanking regions for chimeric read detection [%lu]\n", asm_opt->chemical_flank); - fprintf(stderr, " --rl-cut INT\n"); - fprintf(stderr, " filter out ONT simplex reads shorter than for assembly [%ld]\n", asm_opt->rl_cut); - fprintf(stderr, " --sc-cut INT\n"); - fprintf(stderr, " filter out ONT simplex reads with a mean base quality score below [%ld]\n", asm_opt->sc_cut); - - - fprintf(stderr, "Example: ./hifiasm -o NA12878.asm -t 32 NA12878.fq.gz\n"); - fprintf(stderr, "See `https://hifiasm.readthedocs.io/en/latest/' or `man ./hifiasm.1' for complete documentation.\n"); -} - -void init_opt(hifiasm_opt_t* asm_opt) -{ - memset(asm_opt, 0, sizeof(hifiasm_opt_t)); - ///asm_opt->flag = 0; - asm_opt->flag = HA_F_PARTITION; - asm_opt->coverage = -1; - asm_opt->num_reads = 0; - asm_opt->read_file_names = NULL; - asm_opt->output_file_name = (char*)(DEFAULT_OUTPUT); - asm_opt->required_read_name = NULL; - asm_opt->hic_enzymes = NULL; - asm_opt->hic_reads[0] = NULL; - asm_opt->hic_reads[1] = NULL; - asm_opt->fn_bin_poy = NULL; - asm_opt->ar = NULL; - asm_opt->thread_num = 1; - asm_opt->k_mer_length = 51; - asm_opt->hic_mer_length = 31; - asm_opt->ul_mer_length = 19; - asm_opt->trans_mer_length = 31; - asm_opt->mz_win = 51; - asm_opt->ul_mz_win = 19; - asm_opt->trans_win = 31; - asm_opt->mz_rewin = 1000; - asm_opt->ul_mz_rewin = 360; - asm_opt->mz_sample_dist = 500; - asm_opt->bf_shift = 37; - asm_opt->max_kmer_cnt = 2000; - asm_opt->high_factor = 5.0; - asm_opt->max_ov_diff_ec = 0.04; - asm_opt->max_ov_diff_final = 0.03; - asm_opt->hom_cov = 20; - asm_opt->het_cov = -1024; - asm_opt->max_n_chain = MIN_N_CHAIN; - asm_opt->min_hist_kmer_cnt = 5; - asm_opt->load_index_from_disk = 1; - asm_opt->write_index_to_disk = 1; - asm_opt->number_of_round = 3; - asm_opt->number_of_pround = 0/**3**/; - asm_opt->adapterLen = 0; - asm_opt->clean_round = 4; - ///asm_opt->small_pop_bubble_size = 100000; - asm_opt->small_pop_bubble_size = 0; - asm_opt->large_pop_bubble_size = 10000000; - asm_opt->min_drop_rate = 0.2; - asm_opt->max_drop_rate = 0.8; - asm_opt->max_hang_Len = 1000; - asm_opt->max_hang_rate = 0.8; - asm_opt->gap_fuzz = 1000; - asm_opt->min_overlap_Len = 50; - asm_opt->min_overlap_coverage = 0; - asm_opt->max_short_tip = 3; - asm_opt->max_short_ul_tip = 6; - asm_opt->max_contig_tip = 3; - asm_opt->min_cnt = 2; - asm_opt->mid_cnt = 5; - asm_opt->purge_level_primary = 3; - asm_opt->purge_level_trio = 0; - asm_opt->purge_simi_rate_l2 = 0.75; - asm_opt->purge_simi_rate_l3 = 0.55; - asm_opt->trans_base_rate = 0.93; - asm_opt->trans_base_rate_sec = 0.5; - asm_opt->purge_overlap_len = 1; - ///asm_opt->purge_overlap_len_hic = 50; - asm_opt->recover_atg_cov_min = -1024; - asm_opt->recover_atg_cov_max = INT_MAX; - asm_opt->hom_global_coverage = -1; - asm_opt->hom_global_coverage_set = 0; - asm_opt->pur_global_coverage = -1; - asm_opt->bed_inconsist_rate = 70; - asm_opt->hic_inconsist_rate = 30; - ///asm_opt->bub_mer_length = 3; - asm_opt->bub_mer_length = 1000000; - asm_opt->b_low_cov = 0; - asm_opt->b_high_cov = -1; - asm_opt->m_rate = 0.75; - asm_opt->hap_occ = 1; - asm_opt->polyploidy = 2; - asm_opt->trio_flag_occ_thres = 60; - asm_opt->seed = 11; - asm_opt->n_perturb = 10000; - asm_opt->f_perturb = 0.1; - asm_opt->n_weight = 3; - asm_opt->is_alt = 0; - asm_opt->misjoin_len = 500000; - asm_opt->scffold = 0; - asm_opt->dp_min_len = 2000; - asm_opt->dp_e = 0.0025; - asm_opt->hg_size = -1; - asm_opt->kpt_rate = -1; - asm_opt->infor_cov = 3; - asm_opt->s_hap_cov = 3; - asm_opt->ul_error_rate = 0.2/**0.15**/; - asm_opt->ul_error_rate_low = 0.1; - asm_opt->ul_error_rate_hpc = 0.2; - asm_opt->ul_ec_round = 3; - asm_opt->is_dbg_het_cnt = 0; - asm_opt->is_low_het_ul = 0; - asm_opt->is_base_trans = 1; - asm_opt->is_read_trans = 1; - asm_opt->is_topo_trans = 1; - asm_opt->is_bub_trans = 1; - asm_opt->bin_only = 0; - asm_opt->ul_clean_round = 1; - asm_opt->prt_dbg_gfa = 0; - asm_opt->integer_correct_round = 0; - asm_opt->dbg_ovec_cal = 0; - asm_opt->min_path_drop_rate = 0.2; - asm_opt->max_path_drop_rate = 0.6; - asm_opt->hifi_pst_join = 1; - asm_opt->ul_pst_join = 1; - asm_opt->trio_cov_het_ovlp = -1; - asm_opt->ul_min_base = 0; - asm_opt->self_scaf = 0; - asm_opt->self_scaf_min = 250000; - asm_opt->self_scaf_reliable_min = 5000000; - asm_opt->self_scaf_gap_max = 3000000; - asm_opt->sec_in = NULL; - asm_opt->somatic_cov = -1; - - asm_opt->telo_motif = NULL; - asm_opt->telo_pen = 1; - asm_opt->telo_drop = 2000; - asm_opt->telo_mic_sc = 500; - - asm_opt->is_ont = 0; - asm_opt->is_sc = 0; - asm_opt->chemical_cov = 1; - asm_opt->chemical_flank = 256; - asm_opt->ul_mod = 0; - - asm_opt->rl_cut = 1000; - asm_opt->sc_cut = 10; -} - -void destory_enzyme(enzyme* f) -{ - int i; - if(f != NULL) - { - for (i = 0; i < f->n; i++) - { - free(f->a[i]); - } - free(f->a); - free(f->l); - free(f); - } -} - -void destory_opt(hifiasm_opt_t* asm_opt) -{ - if(asm_opt->read_file_names != NULL) free(asm_opt->read_file_names); - if(asm_opt->hic_enzymes != NULL) destory_enzyme(asm_opt->hic_enzymes); - if(asm_opt->hic_reads[0] != NULL) destory_enzyme(asm_opt->hic_reads[0]); - if(asm_opt->hic_reads[1] != NULL) destory_enzyme(asm_opt->hic_reads[1]); - if(asm_opt->ar != NULL) destory_enzyme(asm_opt->ar); -} - -void ha_opt_reset_to_round(hifiasm_opt_t* asm_opt, int round) -{ - asm_opt->num_bases = 0; - asm_opt->num_corrected_bases = 0; - asm_opt->num_recorrected_bases = 0; - asm_opt->mem_buf = 0; - asm_opt->roundID = round; -} - -void ha_opt_update_cov(hifiasm_opt_t *opt, int hom_cov) -{ - int max_n_chain = (int)(hom_cov * opt->high_factor + .499); - opt->hom_cov = hom_cov; - if (opt->max_n_chain < max_n_chain) - opt->max_n_chain = max_n_chain; - fprintf(stderr, "[M::%s] updated max_n_chain to %d\n", __func__, opt->max_n_chain); -} - -void ha_opt_update_cov_min(hifiasm_opt_t *opt, int hom_cov, int min_chain) -{ - int max_n_chain = (int)(hom_cov * opt->high_factor + .499); - opt->hom_cov = hom_cov; opt->max_n_chain = max_n_chain; - if(opt->max_n_chain < min_chain) opt->max_n_chain = min_chain; - fprintf(stderr, "[M::%s] updated max_n_chain to %d\n", __func__, opt->max_n_chain); -} - -static int check_file(char* name, const char* opt) -{ - if(!name) - { - fprintf(stderr, "[ERROR] file does not exist (-%s)\n", opt); - return 0; - } - FILE* is_exist = NULL; - is_exist = fopen(name,"r"); - if(!is_exist) - { - fprintf(stderr, "[ERROR] %s does not exist (-%s)\n", name, opt); - return 0; - } - - fclose(is_exist); - return 1; -} - -static int check_hic_reads(enzyme* f, const char* opt) -{ - int32_t i; - for (i = 0; i < f->n; i++) { - if(check_file(f->a[i], opt) == 0) return 0; - } - return 1; -} - -static int check_fq_files(enzyme* f, const char* opt, int32_t is_fq) -{ - int32_t i, ret; gzFile dfp; kseq_t *ks = NULL; - for (i = 0; i < f->n; i++) { - if(!(f->a[i])) { - fprintf(stderr, "[ERROR] input file does not exist (%s)\n", opt); - return 0; - } - - dfp = gzopen(f->a[i], "r"); - if (dfp == 0) { - fprintf(stderr, "[ERROR] Cannot find the input file: %s (%s)\n", f->a[i], opt); - return 0; - } else if(is_fq){ - ks = kseq_init(dfp); - while (((ret = kseq_read(ks)) >= 0)) { - if((ks->qual.l == 0) || (ks->qual.s == NULL)) { - fprintf(stderr, "[ERROR] %s is in fasta format rather than fastq format (%s)\n", f->a[i], opt); - fprintf(stderr, "[ERROR] set --ul-m 0 for fasta files\n"); - return 0; - } - break; - } - kseq_destroy(ks); ks = NULL; - } - gzclose(dfp); - } - return 1; -} - -int check_option(hifiasm_opt_t* asm_opt) -{ - if(asm_opt->read_file_names == NULL || asm_opt->num_reads == 0) - { - fprintf(stderr, "[ERROR] missing input: please specify a read file\n"); - return 0; - } - - if(asm_opt->output_file_name == NULL) - { - fprintf(stderr, "[ERROR] missing output: please specify the output name (-o)\n"); - return 0; - } - - if(asm_opt->thread_num < 1) - { - fprintf(stderr, "[ERROR] the number of threads must be > 0 (-t)\n"); - return 0; - } - - - if(asm_opt->number_of_round < 1) - { - fprintf(stderr, "[ERROR] the number of rounds for correction must be > 0 (-r)\n"); - return 0; - } - - if(asm_opt->clean_round < 1) - { - fprintf(stderr, "[ERROR] the number of rounds for assembly cleaning must be > 0 (-a)\n"); - return 0; - } - - if(asm_opt->adapterLen < 0) - { - fprintf(stderr, "[ERROR] the length of removed adapters must be >= 0 (-z)\n"); - return 0; - } - - - if(asm_opt->k_mer_length >= 64) - { - fprintf(stderr, "[ERROR] the length of k_mer must be < 64 (-k)\n"); - return 0; - } - - - if(asm_opt->max_drop_rate < 0 || asm_opt->max_drop_rate >= 1 ) - { - fprintf(stderr, "[ERROR] max overlap drop ratio must be [0.0, 1.0) (-x)\n"); - return 0; - } - - - if(asm_opt->min_drop_rate < 0 || asm_opt->min_drop_rate >= 1) - { - fprintf(stderr, "[ERROR] min overlap drop ratio must be [0.0, 1.0) (-y)\n"); - return 0; - } - - if(asm_opt->max_drop_rate <= asm_opt->min_drop_rate) - { - fprintf(stderr, "[ERROR] min overlap drop ratio must be less than max overlap drop ratio (-x/-y)\n"); - return 0; - } - - if(asm_opt->small_pop_bubble_size < 0) - { - fprintf(stderr, "[ERROR] the size of popped small bubbles must be >= 0 (-p)\n"); - return 0; - } - - if(asm_opt->large_pop_bubble_size < 0) - { - fprintf(stderr, "[ERROR] the size of popped large bubbles must be >= 0 (-m)\n"); - return 0; - } - - if(asm_opt->max_hang_Len < 0) - { - fprintf(stderr, "[ERROR] max_hang_Len must be >= 0\n"); - return 0; - } - - if(asm_opt->max_hang_rate < 0) - { - fprintf(stderr, "[ERROR] max_hang_rate must be >= 0\n"); - return 0; - } - - if(asm_opt->gap_fuzz < 0) - { - fprintf(stderr, "[ERROR] gap_fuzz must be >= 0\n"); - return 0; - } - - if(asm_opt->min_overlap_Len < 0) - { - fprintf(stderr, "[ERROR] min_overlap_Len must be >= 0\n"); - return 0; - } - - if(asm_opt->min_overlap_coverage < 0) - { - fprintf(stderr, "[ERROR] min_overlap_coverage must be >= 0\n"); - return 0; - } - - if (asm_opt->max_ov_diff_ec < asm_opt->max_ov_diff_final) { - fprintf(stderr, "[ERROR] max_ov_diff_ec shouldn't be smaller than max_ov_diff_final\n"); - return 0; - } - - if (asm_opt->max_ov_diff_ec < HA_MIN_OV_DIFF) { - fprintf(stderr, "[ERROR] max_ov_diff_ec shouldn't be smaller than %g\n", HA_MIN_OV_DIFF); - return 0; - } - - if(asm_opt->max_short_tip < 0) - { - fprintf(stderr, "[ERROR] the length of removal tips must be >= 0 (-n)\n"); - return 0; - } - - if(asm_opt->purge_level_primary < 0 || asm_opt->purge_level_primary > 3) - { - fprintf(stderr, "[ERROR] the level of purge-dup should be [0, 3] (-l)\n"); - return 0; - } - - if(ha_opt_triobin(asm_opt) && ((asm_opt->purge_level_trio < 0 || asm_opt->purge_level_trio > 1))) - { - fprintf(stderr, "[ERROR] the level of purge-dup for trio should be [0, 1] (-l)\n"); - return 0; - } - - if(asm_opt->hom_global_coverage < 0 && asm_opt->hom_global_coverage != -1) - { - fprintf(stderr, "[ERROR] homozygous read coverage should be >= 0 (--hom-cov)\n"); - return 0; - } - - if(asm_opt->pur_global_coverage < 0 && asm_opt->pur_global_coverage != -1) - { - fprintf(stderr, "[ERROR] purge duplication coverage threshold should be >= 0 (--purge-max)\n"); - return 0; - } - - if(asm_opt->bed_inconsist_rate < 0 || asm_opt->bed_inconsist_rate > 100) - { - fprintf(stderr, "[ERROR] inconsistency rate should be [0, 100] (--lowQ)\n"); - return 0; - } - - - if(asm_opt->fn_bin_yak[0] != NULL && check_file(asm_opt->fn_bin_yak[0], "YAK1") == 0) return 0; - if(asm_opt->fn_bin_yak[1] != NULL && check_file(asm_opt->fn_bin_yak[1], "YAK2") == 0) return 0; - if(asm_opt->fn_bin_list[0] != NULL && check_file(asm_opt->fn_bin_list[0], "LIST1") == 0) return 0; - if(asm_opt->fn_bin_list[1] != NULL && check_file(asm_opt->fn_bin_list[1], "LIST2") == 0) return 0; - if(asm_opt->required_read_name != NULL && check_file(asm_opt->required_read_name, "b") == 0) return 0; - - if(asm_opt->hic_reads[0] != NULL && check_hic_reads(asm_opt->hic_reads[0], "HIC1") == 0) return 0; - if(asm_opt->hic_reads[1] != NULL && check_hic_reads(asm_opt->hic_reads[1], "HIC2") == 0) return 0; - if(asm_opt->hic_reads[0] != NULL && asm_opt->hic_reads[1] == NULL) - { - fprintf(stderr, "[ERROR] lack r2 of HiC reads (--h2)\n"); - return 0; - } - if(asm_opt->hic_reads[1] != NULL && asm_opt->hic_reads[0] == NULL) - { - fprintf(stderr, "[ERROR] lack r1 of HiC reads (--h1)\n"); - return 0; - } - - if(asm_opt->hic_reads[0] != NULL && asm_opt->hic_reads[1] != NULL && - asm_opt->hic_reads[0]->n != asm_opt->hic_reads[1]->n) - { - fprintf(stderr, "[ERROR] wrong r1 and r2 of HiC reads (--h1 && --h2)\n"); - return 0; - } - - if(asm_opt->hic_enzymes != NULL && asm_opt->hic_enzymes->n == 0) - { - fprintf(stderr, "[ERROR] wrong HiC enzymes (--enzyme)\n"); - return 0; - } - - if(asm_opt->hic_reads[0] != NULL && asm_opt->hic_reads[0]->n == 0) - { - fprintf(stderr, "[ERROR] wrong r1 of HiC reads (--h1)\n"); - return 0; - } - - if(asm_opt->hic_reads[1] != NULL && asm_opt->hic_reads[1]->n == 0) - { - fprintf(stderr, "[ERROR] wrong r2 of HiC reads (--h2)\n"); - return 0; - } - - if(asm_opt->ar != NULL && check_fq_files(asm_opt->ar, "--ul", asm_opt->ul_mod) == 0) return 0; - if(asm_opt->ar != NULL && asm_opt->ar->n == 0) - { - fprintf(stderr, "[ERROR] wrong UL reads (--ul)\n"); - return 0; - } - - if(asm_opt->b_low_cov < 0) - { - fprintf(stderr, "[ERROR] must >= 0 (--b-cov)\n"); - return 0; - } - - if(asm_opt->b_high_cov != -1 && asm_opt->b_high_cov < 0) - { - fprintf(stderr, "[ERROR] must >= 0 (--h-cov)\n"); - return 0; - } - - if(asm_opt->m_rate < 0) - { - fprintf(stderr, "[ERROR] must >= 0 (--m-rate)\n"); - return 0; - } - - if(asm_opt->b_high_cov != -1 && asm_opt->b_high_cov <= asm_opt->b_low_cov) - { - fprintf(stderr, "[ERROR] [--h-cov] must >= [--b-cov]\n"); - return 0; - } - - if(asm_opt->purge_simi_thres < 0) - { - fprintf(stderr, "[ERROR] [-s] must >= 0\n"); - return 0; - } - - if(asm_opt->max_kmer_cnt < 0) - { - fprintf(stderr, "[ERROR] [--max-kocc] must >= 0\n"); - return 0; - } - - if(asm_opt->hg_size < -1) - { - fprintf(stderr, "[ERROR] [--hg-size] wrong genome size\n"); - return 0; - } - - if(asm_opt->ul_mod != 0 && asm_opt->ul_mod != 1) { - fprintf(stderr, "[ERROR] must be 0 or 1 (--ul-m)\n"); - return 0; - } - - if(asm_opt->telo_motif) { - uint64_t k, tlen = strlen((asm_opt->telo_motif)); char c; - if(tlen > 32) { - fprintf(stderr, "[ERROR] [--telo-m] must be no longer than 32\n"); - return 0; - } - for (k = 0; k < tlen; k++) { - c = asm_opt->telo_motif[k]; - if(c != 'A' && c != 'C' && c != 'G' && c != 'T' && - c != 'a' && c != 'c' && c != 'g' && c != 't') { - fprintf(stderr, "[ERROR] [--telo-m] must be A/C/G/T\n"); - return 0; - } - } - } - - return 1; -} - -void get_queries(int argc, char *argv[], ketopt_t* opt, hifiasm_opt_t* asm_opt) -{ - if(opt->ind == argc) { - return; - } - - asm_opt->num_reads = argc - opt->ind; - asm_opt->read_file_names = (char**)malloc(sizeof(char*)*asm_opt->num_reads); - - long long i; int ret; - gzFile dfp; kseq_t *ks = NULL; - for (i = 0; i < asm_opt->num_reads; i++) { - asm_opt->read_file_names[i] = argv[i + opt->ind]; - dfp = gzopen(asm_opt->read_file_names[i], "r"); - if (dfp == 0) { - fprintf(stderr, "[ERROR] Cannot find the input read file: %s\n", - asm_opt->read_file_names[i]); - exit(0); - } else if(asm_opt->is_sc){ - ks = kseq_init(dfp); - while (((ret = kseq_read(ks)) >= 0)) { - if((ks->qual.l == 0) || (ks->qual.s == NULL)) { - fprintf(stderr, "[ERROR] %s is in fasta format rather than fastq format\n", asm_opt->read_file_names[i]); - asm_opt->is_sc = 0; - exit(0); - } - break; - } - kseq_destroy(ks); ks = NULL; - } - gzclose(dfp); - } -} - -void get_hic_enzymes(char *argv, enzyme** x, int check_name) -{ - int i, k, pre_i, len = strlen(argv); - (*x) = (enzyme*)calloc(1, sizeof(enzyme)); - if(len == 0) - { - (*x)->n = 0; (*x)->l = NULL; (*x)->a = NULL; - return; - } - - - (*x)->n = 1; - for (i = pre_i = 0; i < len; i++) - { - if(argv[i] == ',') - { - (*x)->n++; - continue; - } - - if(check_name) - { - if(argv[i] != 'A' && argv[i] != 'C' && argv[i] != 'G' && argv[i] != 'T' && - argv[i] != 'a' && argv[i] != 'c' && argv[i] != 'g' && argv[i] != 't' && - argv[i] != 'N' && argv[i] != 'n') - { - (*x)->n = 0; - (*x)->l = NULL; - (*x)->a = NULL; - return; - } - } - - } - (*x)->l = (int*)calloc((*x)->n, sizeof(int)); - (*x)->a = (char**)calloc((*x)->n, sizeof(char*)); - - for (i = pre_i = k = 0; i < len; i++) - { - if(argv[i] == ',') - { - (*x)->l[k] = i - pre_i; - (*x)->a[k] = (char*)malloc(sizeof(char)*((*x)->l[k]+1)); - memcpy((*x)->a[k], argv + pre_i, (*x)->l[k]); - (*x)->a[k][(*x)->l[k]] = '\0'; - pre_i = i + 1; - k++; - } - } - - (*x)->l[k] = i - pre_i; - (*x)->a[k] = (char*)malloc(sizeof(char)*((*x)->l[k]+1)); - memcpy((*x)->a[k], argv + pre_i, (*x)->l[k]); - (*x)->a[k][(*x)->l[k]] = '\0'; -} - -int64_t inter_gsize(char *argv) -{ - int64_t len = strlen(argv); - double s; - if(len <= 1) return -2; - char t = argv[len-1]; - if(t != 'k' && t != 'K' && t != 'm' && t != 'M' && t != 'g' && t != 'G') return -2; - char *ss=(char*)malloc(len); - memcpy(ss, argv, len-1); ss[len-1] = '\0'; - s = atof(ss); - free(ss); - if(t == 'k' || t == 'K') return s*1000; - if(t == 'm' || t == 'M') return s*1000000; - if(t == 'g' || t == 'G') return s*1000000000; - return s; -} - -int CommandLine_process(int argc, char *argv[], hifiasm_opt_t* asm_opt) -{ - ketopt_t opt = KETOPT_INIT; - - int c; - - while ((c = ketopt(&opt, argc, argv, 1, "hvt:o:k:w:m:n:r:a:b:z:x:y:p:c:d:M:P:if:D:FN:1:2:3:4:5:l:s:O:eu:", long_options)) >= 0) { - if (c == 'h') - { - Print_H(asm_opt); - return 0; - } - else if (c == 'v' || c == 300) - { - puts(HA_VERSION); - return 0; - } - else if (c == 'f') asm_opt->bf_shift = atoi(opt.arg); - else if (c == 't') asm_opt->thread_num = atoi(opt.arg); - else if (c == 'o') asm_opt->output_file_name = opt.arg; - else if (c == 'r') asm_opt->number_of_round = atoi(opt.arg); - else if (c == 'k') asm_opt->k_mer_length = atoi(opt.arg); - else if (c == 'i') asm_opt->load_index_from_disk = 0; - else if (c == 'w') asm_opt->mz_win = atoi(opt.arg); - else if (c == 'D') asm_opt->high_factor = atof(opt.arg); - else if (c == 'F') asm_opt->flag |= HA_F_NO_KMER_FLT; - else if (c == 'N') asm_opt->max_n_chain = atoi(opt.arg); - else if (c == 'a') asm_opt->clean_round = atoi(opt.arg); - else if (c == 'z') asm_opt->adapterLen = atoi(opt.arg); - else if (c == 'b') asm_opt->required_read_name = opt.arg; - else if (c == 'c') asm_opt->min_cnt = atoi(opt.arg); - else if (c == 'd') asm_opt->mid_cnt = atoi(opt.arg); - else if (c == '1' || c == 'P') asm_opt->fn_bin_yak[0] = opt.arg; // -P/-M reserved for backward compatibility - else if (c == '2' || c == 'M') asm_opt->fn_bin_yak[1] = opt.arg; - else if (c == '3') asm_opt->fn_bin_list[0] = opt.arg; - else if (c == '4') asm_opt->fn_bin_list[1] = opt.arg; - else if (c == '5') asm_opt->fn_bin_poy = opt.arg; - else if (c == 'x') asm_opt->max_drop_rate = atof(opt.arg); - else if (c == 'y') asm_opt->min_drop_rate = atof(opt.arg); - else if (c == 'p') asm_opt->small_pop_bubble_size = atoll(opt.arg); - else if (c == 'm') asm_opt->large_pop_bubble_size = atoll(opt.arg); - else if (c == 'n') asm_opt->max_short_tip = atoll(opt.arg); - else if (c == 'e') asm_opt->flag |= HA_F_BAN_ASSEMBLY; - else if (c == 'u') { - if(atoll(opt.arg)) { - asm_opt->hifi_pst_join = asm_opt->ul_pst_join = 1; - } else { - asm_opt->hifi_pst_join = asm_opt->ul_pst_join = 0; - } - } - else if (c == 301) asm_opt->flag |= HA_F_VERBOSE_GFA; - else if (c == 302) asm_opt->flag |= HA_F_WRITE_PAF; - else if (c == 303) asm_opt->flag |= HA_F_WRITE_EC; - else if (c == 304) asm_opt->flag |= HA_F_SKIP_TRIOBIN; - else if (c == 305) asm_opt->max_ov_diff_ec = atof(opt.arg); - else if (c == 306) asm_opt->max_ov_diff_final = atof(opt.arg); - else if (c == 307) asm_opt->extract_list = opt.arg; - else if (c == 308) asm_opt->extract_iter = atoi(opt.arg); - else if (c == 309) - { - asm_opt->hom_global_coverage = atoi(opt.arg); - asm_opt->hom_global_coverage_set = 1; - } - else if (c == 310) - { - char* s = NULL; - asm_opt->recover_atg_cov_min = strtol(opt.arg, &s, 10); - if (*s == ',') asm_opt->recover_atg_cov_max = strtol(s + 1, &s, 10); - if(asm_opt->recover_atg_cov_min == -1 || asm_opt->recover_atg_cov_max == -1) - { - asm_opt->recover_atg_cov_min = asm_opt->recover_atg_cov_max = -1; - } - } - ///else if (c == 311) asm_opt->flag |= HA_F_HIGH_HET; - else if (c == 312) asm_opt->bed_inconsist_rate = atoi(opt.arg); - else if (c == 313) asm_opt->min_hist_kmer_cnt = atoi(opt.arg); - else if (c == 314) get_hic_enzymes(opt.arg, &(asm_opt->hic_reads[0]), 0); - else if (c == 315) get_hic_enzymes(opt.arg, &(asm_opt->hic_reads[1]), 0); - else if (c == 316) get_hic_enzymes(opt.arg, &(asm_opt->hic_enzymes), 1); - else if (c == 317) asm_opt->b_low_cov = atoi(opt.arg); - else if (c == 318) asm_opt->b_high_cov = atoi(opt.arg); - else if (c == 319) asm_opt->m_rate = atof(opt.arg); - else if (c == 320) asm_opt->flag -= HA_F_PARTITION, asm_opt->is_alt = 1; - else if (c == 321) asm_opt->trio_flag_occ_thres = atoi(opt.arg); - else if (c == 322) asm_opt->seed = atol(opt.arg); - else if (c == 323) asm_opt->n_perturb = atoi(opt.arg); - else if (c == 324) asm_opt->f_perturb = atof(opt.arg); - else if (c == 325) asm_opt->polyploidy = atoi(opt.arg); - else if (c == 326) asm_opt->n_weight = atoi(opt.arg); - else if (c == 327) asm_opt->misjoin_len = atol(opt.arg); - else if (c == 328) asm_opt->pur_global_coverage = atoi(opt.arg); - else if (c == 329) asm_opt->flag |= HA_F_FAST; - else if (c == 330) asm_opt->dp_e = atof(opt.arg); - else if (c == 331) asm_opt->max_kmer_cnt = atol(opt.arg); - else if (c == 332) asm_opt->hg_size = inter_gsize(opt.arg); - else if (c == 333) get_hic_enzymes(opt.arg, &(asm_opt->ar), 0); - else if (c == 334) asm_opt->flag |= HA_F_USKEW; - else if (c == 335) asm_opt->kpt_rate = atof(opt.arg); - else if (c == 336) asm_opt->ul_error_rate = atof(opt.arg); - else if (c == 337) asm_opt->is_dbg_het_cnt = 1; - else if (c == 338) asm_opt->max_short_ul_tip = atol(opt.arg); - else if (c == 339) asm_opt->is_low_het_ul = 1; - else if (c == 340) { - asm_opt->trans_base_rate_sec = atof(opt.arg); - if(asm_opt->trans_base_rate_sec < 0) asm_opt->is_base_trans = 0; - } - else if (c == 341) asm_opt->bin_only = 1; - else if (c == 342) asm_opt->ul_clean_round = atol(opt.arg); - else if (c == 343) asm_opt->prt_dbg_gfa = 1; - else if (c == 344) asm_opt->integer_correct_round = atol(opt.arg); - else if (c == 345) asm_opt->dbg_ovec_cal = 1; - else if (c == 346) asm_opt->max_path_drop_rate = atof(opt.arg); - else if (c == 347) asm_opt->min_path_drop_rate = atof(opt.arg); - else if (c == 348) asm_opt->trio_cov_het_ovlp = 1; - else if (c == 349) asm_opt->ul_min_base = atol(opt.arg); - else if (c == 350) asm_opt->self_scaf = 1; - else if (c == 351) asm_opt->self_scaf_gap_max = atol(opt.arg); - else if (c == 352) get_hic_enzymes(opt.arg, &(asm_opt->sec_in), 0); - else if (c == 353) asm_opt->somatic_cov = atol(opt.arg); - else if (c == 354) asm_opt->telo_motif = opt.arg; - else if (c == 355) asm_opt->telo_pen = atol(opt.arg); - else if (c == 356) asm_opt->telo_drop = atol(opt.arg); - else if (c == 357) asm_opt->telo_mic_sc = atol(opt.arg); - else if (c == 358) asm_opt->max_contig_tip = atol(opt.arg); - else if (c == 359) { - asm_opt->is_ont = 1; asm_opt->max_ov_diff_ec = 0.07; asm_opt->is_sc = 1; ///asm_opt->mz_win = 37; asm_opt->k_mer_length = 37; - } /**else if (c == 360) { - asm_opt->is_sc = 1; - }**/ else if (c == 361) { - asm_opt->chemical_cov = atol(opt.arg); - } else if (c == 362) { - asm_opt->chemical_flank = atol(opt.arg); - ///pending for integration - /** - } else if (c == 363) { - asm_opt->ul_mod = atol(opt.arg); - **/ - } else if (c == 364) { - asm_opt->rl_cut = atol(opt.arg); - } else if (c == 365) { - asm_opt->sc_cut = atol(opt.arg); - } else if (c == 'l') { ///0: disable purge_dup; 1: purge containment; 2: purge overlap - asm_opt->purge_level_primary = asm_opt->purge_level_trio = atoi(opt.arg); - } - else if (c == 's') asm_opt->purge_simi_rate_l2 = asm_opt->purge_simi_rate_l3 = atof(opt.arg); - else if (c == 'O') asm_opt->purge_overlap_len = atoll(opt.arg); - else if (c == ':') - { - fprintf(stderr, "[ERROR] missing option argument in \"%s\"\n", argv[opt.i - 1]); - return 1; - } - else if (c == '?') - { - fprintf(stderr, "[ERROR] unknown option in \"%s\"\n", argv[opt.i - 1]); - return 1; - } - } - - if(asm_opt->purge_level_primary > 2) asm_opt->purge_simi_thres = asm_opt->purge_simi_rate_l3; - else asm_opt->purge_simi_thres = asm_opt->purge_simi_rate_l2; - - if (argc == opt.ind) - { - Print_H(asm_opt); - return 0; - } - - get_queries(argc, argv, &opt, asm_opt); - - c = ((asm_opt->ar)?(asm_opt->ul_pst_join):(asm_opt->hifi_pst_join)); - if(c) { - if((asm_opt->flag&HA_F_BAN_POST_JOIN)) asm_opt->flag-=HA_F_BAN_POST_JOIN; - } else { - asm_opt->flag |= HA_F_BAN_POST_JOIN; - } - - // fprintf(stderr, "[M::%s::] post join::%u\n", __func__, (uint32_t)(!(asm_opt->flag & HA_F_BAN_POST_JOIN))); - // exit(1); - if(!(asm_opt->is_ont)) { - asm_opt->rl_cut = -1; asm_opt->sc_cut = 1; - } - - return check_option(asm_opt); -} +#define __STDC_LIMIT_MACROS +#include +#include +#include +#include +#include +#include +#include "CommandLines.h" +#include "ketopt.h" +#include "kseq.h" + +KSEQ_INIT(gzFile, gzread) + +#define DEFAULT_OUTPUT "hifiasm.asm" + +hifiasm_opt_t asm_opt; + +static ko_longopt_t long_options[] = { + { "version", ko_no_argument, 300 }, + { "dbg-gfa", ko_no_argument, 301 }, + { "write-paf", ko_no_argument, 302 }, + { "write-ec", ko_no_argument, 303 }, + { "skip-triobin", ko_no_argument, 304 }, + { "max-od-ec", ko_required_argument, 305 }, + { "max-od-final", ko_required_argument, 306 }, + { "ex-list", ko_required_argument, 307 }, + { "ex-iter", ko_required_argument, 308 }, + { "hom-cov", ko_required_argument, 309 }, + { "pri-range", ko_required_argument, 310 }, + { "lowQ", ko_required_argument, 312 }, + { "min-hist-cnt", ko_required_argument, 313 }, + { "h1", ko_required_argument, 314 }, + { "h2", ko_required_argument, 315 }, + { "enzyme", ko_required_argument, 316 }, + { "b-cov", ko_required_argument, 317 }, + { "h-cov", ko_required_argument, 318 }, + { "m-rate", ko_required_argument, 319 }, + { "primary", ko_no_argument, 320 }, + { "t-occ", ko_required_argument, 321 }, + { "seed", ko_required_argument, 322 }, + { "n-perturb", ko_required_argument, 323 }, + { "f-perturb", ko_required_argument, 324 }, + { "n-hap", ko_required_argument, 325 }, + { "n-weight", ko_required_argument, 326 }, + { "l-msjoin", ko_required_argument, 327 }, + { "purge-max", ko_required_argument, 328 }, + { "fast", ko_no_argument, 329 }, + { "dp-er", ko_required_argument, 330}, + { "max-kocc", ko_required_argument, 331}, + { "hg-size", ko_required_argument, 332}, + { "ul", ko_required_argument, 333}, + { "unskew", ko_no_argument, 334}, + { "kpt-rate", ko_required_argument, 335}, + { "ul-rate", ko_required_argument, 336}, + { "dbg-het-cnt", ko_no_argument, 337}, + { "ul-tip", ko_required_argument, 338}, + { "low-het", ko_no_argument, 339}, + { "s-base", ko_required_argument, 340}, + { "bin-only", ko_no_argument, 341}, + { "ul-round", ko_required_argument, 342}, + { "prt-raw", ko_no_argument, 343}, + { "integer-correct", ko_required_argument, 344}, + { "dbg-ovec", ko_no_argument, 345}, + { "path-max", ko_required_argument, 346}, + { "path-min", ko_required_argument, 347}, + { "trio-dual", ko_no_argument, 348}, + { "ul-cut", ko_required_argument, 349}, + { "dual-scaf", ko_no_argument, 350}, + { "scaf-gap", ko_required_argument, 351}, + { "sec-in", ko_required_argument, 352}, + { "somatic-cov", ko_required_argument, 353}, + { "telo-m", ko_required_argument, 354}, + { "telo-p", ko_required_argument, 355}, + { "telo-d", ko_required_argument, 356}, + { "telo-s", ko_required_argument, 357}, + { "ctg-n", ko_required_argument, 358}, + { "ont", ko_no_argument, 359}, + // { "sc-n", ko_no_argument, 360}, + { "chem-c", ko_required_argument, 361}, + { "chem-f", ko_required_argument, 362}, + { "ul-m", ko_required_argument, 363}, + { "rl-cut", ko_required_argument, 364}, + { "sc-cut", ko_required_argument, 365}, + { "hf", ko_required_argument, 366}, + { "cb", ko_required_argument, 367}, + { "gpath", ko_no_argument, 368}, + { "het-cov", ko_required_argument, 369}, + { "resume", ko_no_argument, 370}, + { "flt-kocc", ko_required_argument, 371}, + { "chn-occ", ko_required_argument, 372}, + // { "path-round", ko_required_argument, 348}, + { 0, 0, 0 } +}; + +double Get_T(void) +{ + struct timeval t; + gettimeofday(&t, NULL); + return t.tv_sec+t.tv_usec/1000000.0; +} + +void Print_H(hifiasm_opt_t* asm_opt) +{ + fprintf(stderr, "Usage: hifiasm [options] <...>\n"); + fprintf(stderr, "Options:\n"); + fprintf(stderr, " Input/Output:\n"); + fprintf(stderr, " -o STR prefix of output files [%s]\n", asm_opt->output_file_name); + fprintf(stderr, " -t INT number of threads [%d]\n", asm_opt->thread_num); + fprintf(stderr, " -h show help information\n"); + fprintf(stderr, " --version show version number\n"); + fprintf(stderr, " Preset options:\n"); + fprintf(stderr, " --ont assemble Oxford Nanopore reads\n"); + fprintf(stderr, " Overlap/Error correction:\n"); + fprintf(stderr, " -k INT k-mer length (must be <64) [%d]\n", asm_opt->k_mer_length); + fprintf(stderr, " -w INT minimizer window size [%d]\n", asm_opt->mz_win); + fprintf(stderr, " -f INT number of bits for bloom filter; 0 to disable [%d]\n", asm_opt->bf_shift); + fprintf(stderr, " -D FLOAT drop k-mers occurring >FLOAT*coverage times [%.1f]; work with --flt-kocc or -N\n", asm_opt->high_factor); + fprintf(stderr, " --flt-kocc INT\n"); + fprintf(stderr, " drop k-mers occurring >max(-D*coverage,--flt-kocc) times [%ld]\n", asm_opt->hf_cutoff); + fprintf(stderr, " -N INT consider up to max(-D*coverage,-N) overlaps for each oriented read [%d]\n", asm_opt->max_n_chain); + fprintf(stderr, " -r INT round of correction [%d]\n", asm_opt->number_of_round); + fprintf(stderr, " -z INT length of adapters that should be removed [%d]\n", asm_opt->adapterLen); + fprintf(stderr, " --max-kocc INT\n"); + fprintf(stderr, " employ k-mers occurring max_kmer_cnt); + fprintf(stderr, " --hg-size INT(k, m or g)\n"); + fprintf(stderr, " estimated haploid genome size used for inferring read coverage [auto]\n"); + fprintf(stderr, " --resume resume from the previously incomplete assembly [%ld]\n", asm_opt->restart); + fprintf(stderr, " --het-cov INT\n"); + fprintf(stderr, " heterozygous read coverage [auto]; used for error correction and assembly; manual value overrides auto\n"); + fprintf(stderr, " --hom-cov INT\n"); + fprintf(stderr, " homozygous read coverage [auto]; used for error correction and assembly; manual value overrides auto\n"); + fprintf(stderr, " --chn-occ INT\n"); + fprintf(stderr, " discard overlaps supported by chn_occ); + fprintf(stderr, " Assembly:\n"); + fprintf(stderr, " -a INT round of assembly cleaning [%d]\n", asm_opt->clean_round); + fprintf(stderr, " -m INT pop bubbles of large_pop_bubble_size); + fprintf(stderr, " -p INT pop bubbles of small_pop_bubble_size); + fprintf(stderr, " -n INT remove tip unitigs composed of <=INT reads [%d]\n", asm_opt->max_short_tip); + fprintf(stderr, " -x FLOAT max overlap drop ratio [%.2g]\n", asm_opt->max_drop_rate); + fprintf(stderr, " -y FLOAT min overlap drop ratio [%.2g]\n", asm_opt->min_drop_rate); + fprintf(stderr, " -i ignore saved read correction and overlaps\n"); + fprintf(stderr, " -u post-join step for contigs which may improve N50; 0 to disable; 1 to enable\n"); + fprintf(stderr, " [%u] and [%u] in default for the UL+HiFi assembly and the HiFi assembly, respectively\n", + asm_opt->ul_pst_join, asm_opt->hifi_pst_join); + fprintf(stderr, " --lowQ INT\n"); + fprintf(stderr, " output contig regions with >=INT%% inconsistency in BED format; 0 to disable [%d]\n", asm_opt->bed_inconsist_rate); + fprintf(stderr, " --b-cov INT\n"); + fprintf(stderr, " break contigs at positions with b_low_cov); + fprintf(stderr, " --h-cov INT\n"); + fprintf(stderr, " break contigs at positions with >INT-fold coverage; work with '--m-rate'; -1 to disable [%d]\n", asm_opt->b_high_cov); + fprintf(stderr, " --m-rate FLOAT\n"); + fprintf(stderr, " break contigs at positions with <=FLOAT*coverage exact overlaps;\n"); + fprintf(stderr, " only work with '--b-cov' or '--h-cov'[%.2f]\n", asm_opt->m_rate); + fprintf(stderr, " --primary output a primary assembly and an alternate assembly\n"); + fprintf(stderr, " --ctg-n INT\n"); + fprintf(stderr, " remove tip contigs composed of <=INT reads [%d]\n", asm_opt->max_contig_tip); + fprintf(stderr, " --gpath output the corresponding path of each contig (p_ctg) within the assembly graph (d_utg.noseq.gfa)\n"); + + +// fprintf(stderr, " --pri-range INT1[,INT2]\n"); +// fprintf(stderr, " keep contigs with coverage in this range in p_ctg.gfa; -1 to disable [auto,inf]\n"); + + fprintf(stderr, " Trio-partition:\n"); + fprintf(stderr, " -1 FILE hap1/paternal k-mer dump generated by \"yak count\" []\n"); + fprintf(stderr, " -2 FILE hap2/maternal k-mer dump generated by \"yak count\" []\n"); + fprintf(stderr, " -3 FILE list of hap1/paternal read names []\n"); + fprintf(stderr, " -4 FILE list of hap2/maternal read names []\n"); + fprintf(stderr, " -c INT lower bound of the binned k-mer's frequency [%d]\n", asm_opt->min_cnt); + fprintf(stderr, " -d INT upper bound of the binned k-mer's frequency [%d]\n", asm_opt->mid_cnt); + fprintf(stderr, " --t-occ INT\n"); + fprintf(stderr, " forcedly remove unitigs with >INT unexpected haplotype-specific reads;\n"); + fprintf(stderr, " ignore graph topology; [%d]\n", asm_opt->trio_flag_occ_thres); + fprintf(stderr, " --trio-dual utilize homology information to correct trio phasing errors\n"); + + + fprintf(stderr, " Purge-dups:\n"); + fprintf(stderr, " -l INT purge level. 0: no purging; 1: light; 2/3: aggressive [0 for trio; 3 for unzip]\n"); + fprintf(stderr, " -s FLOAT similarity threshold for duplicate haplotigs in read-level [%g for -l1/-l2, %g for -l3]\n", + asm_opt->purge_simi_rate_l2, asm_opt->purge_simi_rate_l3); + fprintf(stderr, " -O INT min number of overlapped reads for duplicate haplotigs [%d]\n", + asm_opt->purge_overlap_len); + fprintf(stderr, " --purge-max INT\n"); + fprintf(stderr, " coverage upper bound of Purge-dups [auto]\n"); + fprintf(stderr, " --n-hap INT\n"); + fprintf(stderr, " number of haplotypes [%d]\n", asm_opt->polyploidy); + + // fprintf(stderr, " Hi-C-partition [experimental, not stable]:\n"); + fprintf(stderr, " Hi-C-partition:\n"); + fprintf(stderr, " --h1 FILEs file names of Hi-C R1 [r1_1.fq,r1_2.fq,...]\n"); + fprintf(stderr, " --h2 FILEs file names of Hi-C R2 [r2_1.fq,r2_2.fq,...]\n"); + fprintf(stderr, " --seed INT RNG seed [%lu]\n", asm_opt->seed); + fprintf(stderr, " --s-base FLOAT\n"); + fprintf(stderr, " similarity threshold for homology detection in base-level;\n"); + fprintf(stderr, " -1 to disable [%.3g]; -s for read-level (see )\n", asm_opt->trans_base_rate_sec); + + fprintf(stderr, " --n-weight INT\n"); + fprintf(stderr, " rounds of reweighting Hi-C links [%d]\n", asm_opt->n_weight); + fprintf(stderr, " --n-perturb INT\n"); + fprintf(stderr, " rounds of perturbation [%d]\n", asm_opt->n_perturb); + fprintf(stderr, " --f-perturb FLOAT\n"); + fprintf(stderr, " fraction to flip for perturbation [%.3g]\n", asm_opt->f_perturb); + fprintf(stderr, " --l-msjoin INT\n"); + fprintf(stderr, " detect misjoined unitigs of >=INT in size; 0 to disable [%lu]\n", asm_opt->misjoin_len); + + fprintf(stderr, " Ultra-Long-integration:\n"); + fprintf(stderr, " --ul FILEs file names of Ultra-Long reads [r1.fq,r2.fq,...]\n"); + ///pending for integration + /** + fprintf(stderr, " --ul-m INT\n"); + fprintf(stderr, " hybrid assembly mode. 0: fast and memory efficent; 1: may produce better assembly with ONT R10 [%d]\n", asm_opt->ul_mod); + **/ + fprintf(stderr, " --ul-rate FLOAT\n"); + fprintf(stderr, " error rate of Ultra-Long reads [%.3g]\n", asm_opt->ul_error_rate); + fprintf(stderr, " --ul-tip INT\n"); + fprintf(stderr, " remove tip unitigs composed of <=INT reads for the UL assembly [%d]\n", asm_opt->max_short_ul_tip); + fprintf(stderr, " --path-max FLOAT\n"); + fprintf(stderr, " max path drop ratio [%.2g]; higher number may make the assembly cleaner\n", asm_opt->max_path_drop_rate); + fprintf(stderr, " but may lead to more misassemblies\n"); + fprintf(stderr, " --path-min FLOAT\n"); + fprintf(stderr, " min path drop ratio [%.2g]; higher number may make the assembly cleaner\n", asm_opt->min_path_drop_rate); + fprintf(stderr, " but may lead to more misassemblies\n"); + fprintf(stderr, " --ul-cut INT\n"); + fprintf(stderr, " filter out ul_min_base); + // fprintf(stderr, " --low-het enable it for genomes with very low het heterozygosity rate (<0.0001%%)\n"); + + fprintf(stderr, " Dual-Scaffolding:\n"); + fprintf(stderr, " --dual-scaf output scaffolding\n"); + fprintf(stderr, " --scaf-gap INT\n"); + fprintf(stderr, " max gap size for scaffolding [%ld]\n", asm_opt->self_scaf_gap_max); + + fprintf(stderr, " Telomere-identification:\n"); + fprintf(stderr, " --telo-m STR\n"); + fprintf(stderr, " telomere motif at 5'-end; CCCTAA for human [%s]\n", ((asm_opt->telo_motif)?(asm_opt->telo_motif):("NULL")));///5'-end, check CCCTAA + fprintf(stderr, " --telo-p INT\n"); + fprintf(stderr, " non-telomeric penalty [%ld]\n", asm_opt->telo_pen); + fprintf(stderr, " --telo-d INT\n"); + fprintf(stderr, " max drop [%ld]\n", asm_opt->telo_drop); + fprintf(stderr, " --telo-s INT\n"); + fprintf(stderr, " min score for telomere reads [%ld]\n", asm_opt->telo_mic_sc); + + fprintf(stderr, " ONT Simplex assembly (beta):\n"); + fprintf(stderr, " --ont assemble ONT Simplex reads in fastq format\n"); + // fprintf(stderr, " --sc-n consider base qual value for assembly\n"); + fprintf(stderr, " --chem-c INT\n"); + fprintf(stderr, " detect chimeric reads with <=INT other reads support [%lu]\n", asm_opt->chemical_cov); + fprintf(stderr, " --chem-f INT\n"); + fprintf(stderr, " length of flanking regions for chimeric read detection [%lu]\n", asm_opt->chemical_flank); + fprintf(stderr, " --rl-cut INT\n"); + fprintf(stderr, " filter out ONT Simplex reads shorter than for assembly [%ld]\n", asm_opt->rl_cut); + fprintf(stderr, " --sc-cut INT\n"); + fprintf(stderr, " filter out ONT Simplex reads with a mean base quality score below [%ld]\n", asm_opt->sc_cut); + fprintf(stderr, " --hf FILEs file names of HiFi reads\n"); + + + fprintf(stderr, "Example: ./hifiasm -o NA12878.asm -t 32 NA12878.fq.gz\n"); + fprintf(stderr, "See `https://hifiasm.readthedocs.io/en/latest/' or `man ./hifiasm.1' for complete documentation.\n"); +} + +void init_opt(hifiasm_opt_t* asm_opt) +{ + memset(asm_opt, 0, sizeof(hifiasm_opt_t)); + ///asm_opt->flag = 0; + asm_opt->flag = HA_F_PARTITION; + asm_opt->coverage = -1; + asm_opt->num_reads = 0; + asm_opt->read_file_names = NULL; + asm_opt->output_file_name = (char*)(DEFAULT_OUTPUT); + asm_opt->required_read_name = NULL; + asm_opt->hic_enzymes = NULL; + asm_opt->hic_reads[0] = NULL; + asm_opt->hic_reads[1] = NULL; + asm_opt->fn_bin_poy = NULL; + asm_opt->fn_chr_bin = NULL; + asm_opt->ar = NULL; + asm_opt->thread_num = 1; + asm_opt->k_mer_length = 51; + asm_opt->hic_mer_length = 31; + asm_opt->ul_mer_length = 19; + asm_opt->trans_mer_length = 31; + asm_opt->mz_win = 51; + asm_opt->ul_mz_win = 19; + asm_opt->trans_win = 31; + asm_opt->mz_rewin = 1000; + asm_opt->ul_mz_rewin = 360; + asm_opt->mz_sample_dist = 500; + asm_opt->bf_shift = 37; + asm_opt->max_kmer_cnt = 2000; + asm_opt->high_factor = 5.0; + asm_opt->max_ov_diff_ec = 0.04; + asm_opt->max_ov_diff_ec_sec = 0.04; + asm_opt->max_ov_diff_final = 0.03; + asm_opt->hom_cov = 20; + asm_opt->het_cov = -1024; + asm_opt->max_n_chain = MIN_N_CHAIN; + asm_opt->min_hist_kmer_cnt = 5; + asm_opt->load_index_from_disk = 1; + asm_opt->write_index_to_disk = 1; + asm_opt->number_of_round = 3; + asm_opt->number_of_pround = 0/**3**/; + asm_opt->adapterLen = 0; + asm_opt->clean_round = 4; + ///asm_opt->small_pop_bubble_size = 100000; + asm_opt->small_pop_bubble_size = 0; + asm_opt->large_pop_bubble_size = 10000000; + asm_opt->min_drop_rate = 0.2; + asm_opt->max_drop_rate = 0.8; + asm_opt->max_hang_Len = 1000; + asm_opt->max_hang_rate = 0.8; + asm_opt->gap_fuzz = 1000; + asm_opt->min_overlap_Len = 50; + asm_opt->min_overlap_coverage = 0; + asm_opt->max_short_tip = 3; + asm_opt->max_short_ul_tip = 6; + asm_opt->max_contig_tip = 3; + asm_opt->min_cnt = 2; + asm_opt->mid_cnt = 5; + asm_opt->purge_level_primary = 3; + asm_opt->purge_level_trio = 0; + asm_opt->purge_simi_rate_l2 = 0.75; + asm_opt->purge_simi_rate_l3 = 0.55; + asm_opt->trans_base_rate = 0.93; + asm_opt->trans_base_rate_sec = 0.5; + asm_opt->purge_overlap_len = 1; + ///asm_opt->purge_overlap_len_hic = 50; + asm_opt->recover_atg_cov_min = -1024; + asm_opt->recover_atg_cov_max = INT_MAX; + asm_opt->hom_global_coverage = -1; + asm_opt->hom_global_coverage_set = 0; + asm_opt->pur_global_coverage = -1; + asm_opt->bed_inconsist_rate = 70; + asm_opt->hic_inconsist_rate = 30; + ///asm_opt->bub_mer_length = 3; + asm_opt->bub_mer_length = 1000000; + asm_opt->b_low_cov = 0; + asm_opt->b_high_cov = -1; + asm_opt->m_rate = 0.75; + asm_opt->hap_occ = 1; + asm_opt->polyploidy = 2; + asm_opt->trio_flag_occ_thres = 60; + asm_opt->seed = 11; + asm_opt->n_perturb = 10000; + asm_opt->f_perturb = 0.1; + asm_opt->n_weight = 3; + asm_opt->is_alt = 0; + asm_opt->misjoin_len = 500000; + asm_opt->scffold = 0; + asm_opt->dp_min_len = 2000; + asm_opt->dp_e = 0.0025; + asm_opt->hg_size = -1; + asm_opt->kpt_rate = -1; + asm_opt->infor_cov = 3; + asm_opt->s_hap_cov = 3; + asm_opt->ul_error_rate = 0.2/**0.15**/; + asm_opt->ul_error_rate_low = 0.1; + asm_opt->ul_error_rate_hpc = 0.2; + asm_opt->ul_ec_round = 3; + asm_opt->is_dbg_het_cnt = 0; + asm_opt->is_low_het_ul = 0; + asm_opt->is_base_trans = 1; + asm_opt->is_read_trans = 1; + asm_opt->is_topo_trans = 1; + asm_opt->is_bub_trans = 1; + asm_opt->bin_only = 0; + asm_opt->ul_clean_round = 1; + asm_opt->prt_dbg_gfa = 0; + asm_opt->integer_correct_round = 0; + asm_opt->dbg_ovec_cal = 0; + asm_opt->min_path_drop_rate = 0.2; + asm_opt->max_path_drop_rate = 0.6; + asm_opt->hifi_pst_join = 1; + asm_opt->ul_pst_join = 1; + asm_opt->trio_cov_het_ovlp = -1; + asm_opt->ul_min_base = 0; + asm_opt->self_scaf = 0; + asm_opt->self_scaf_min = 250000; + asm_opt->self_scaf_reliable_min = 5000000; + asm_opt->self_scaf_gap_max = 3000000; + asm_opt->sec_in = NULL; + asm_opt->somatic_cov = -1; + + asm_opt->telo_motif = NULL; + asm_opt->telo_pen = 1; + asm_opt->telo_drop = 2000; + asm_opt->telo_mic_sc = 500; + + asm_opt->is_ont = 0; + asm_opt->is_sc = 0; + asm_opt->chemical_cov = 1; + asm_opt->chemical_flank = 256; + asm_opt->ul_mod = 0; + + asm_opt->rl_cut = 1000; + asm_opt->sc_cut = 10; + + asm_opt->hf = NULL; + + asm_opt->gpath = 0; + + asm_opt->hf_rate = 4; + asm_opt->ont_rate = 1;///must be 1 or 0 + asm_opt->hf_rate_max = 4; + + asm_opt->het_cov_set = -1; + asm_opt->restart = 0; + + asm_opt->hf_cutoff = -1; + + asm_opt->write_pos_idx = 1; + + asm_opt->hom_cov_0 = -1; + asm_opt->het_cov_0 = -1; + asm_opt->max_n_chain_0 = -1; + + + asm_opt->hmo_cov_ss = -1; + asm_opt->het_cov_ss = -1; + asm_opt->chn_occ = 2; +} + +void destory_enzyme(enzyme* f) +{ + int i; + if(f != NULL) + { + for (i = 0; i < f->n; i++) + { + free(f->a[i]); + } + free(f->a); + free(f->l); + free(f); + } +} + +void destory_opt(hifiasm_opt_t* asm_opt) +{ + if(asm_opt->read_file_names != NULL) free(asm_opt->read_file_names); + if(asm_opt->hic_enzymes != NULL) destory_enzyme(asm_opt->hic_enzymes); + if(asm_opt->hic_reads[0] != NULL) destory_enzyme(asm_opt->hic_reads[0]); + if(asm_opt->hic_reads[1] != NULL) destory_enzyme(asm_opt->hic_reads[1]); + if(asm_opt->ar != NULL) destory_enzyme(asm_opt->ar); +} + +void ha_opt_reset_to_round(hifiasm_opt_t* asm_opt, int round) +{ + asm_opt->num_bases = 0; + asm_opt->num_corrected_bases = 0; + asm_opt->num_recorrected_bases = 0; + asm_opt->mem_buf = 0; + asm_opt->roundID = round; +} + +void ha_opt_update_cov(hifiasm_opt_t *opt, int hom_cov) +{ + int max_n_chain = (int)(hom_cov * opt->high_factor + .499); + opt->hom_cov = hom_cov; + if (opt->max_n_chain < max_n_chain) + opt->max_n_chain = max_n_chain; + fprintf(stderr, "[M::%s] updated max_n_chain to %d\n", __func__, opt->max_n_chain); +} + +void ha_opt_update_cov_min(hifiasm_opt_t *opt, int hom_cov, int min_chain) +{ + int max_n_chain = (int)(hom_cov * opt->high_factor + .499); + opt->hom_cov = hom_cov; opt->max_n_chain = max_n_chain; + if(opt->max_n_chain < min_chain) opt->max_n_chain = min_chain; + fprintf(stderr, "[M::%s] updated max_n_chain to %d\n", __func__, opt->max_n_chain); +} + +static int check_file(char* name, const char* opt) +{ + if(!name) + { + fprintf(stderr, "[ERROR] file does not exist (-%s)\n", opt); + return 0; + } + FILE* is_exist = NULL; + is_exist = fopen(name,"r"); + if(!is_exist) + { + fprintf(stderr, "[ERROR] %s does not exist (-%s)\n", name, opt); + return 0; + } + + fclose(is_exist); + return 1; +} + +static int check_hic_reads(enzyme* f, const char* opt) +{ + int32_t i; + for (i = 0; i < f->n; i++) { + if(check_file(f->a[i], opt) == 0) return 0; + } + return 1; +} + +static int check_fq_files(enzyme* f, const char* opt, int32_t is_fq) +{ + int32_t i, ret; gzFile dfp; kseq_t *ks = NULL; + for (i = 0; i < f->n; i++) { + if(!(f->a[i])) { + fprintf(stderr, "[ERROR] input file does not exist (%s)\n", opt); + return 0; + } + + dfp = gzopen(f->a[i], "r"); + if (dfp == 0) { + fprintf(stderr, "[ERROR] Cannot find the input file: %s (%s)\n", f->a[i], opt); + return 0; + } else if(is_fq){ + ks = kseq_init(dfp); + while (((ret = kseq_read(ks)) >= 0)) { + if((ks->qual.l == 0) || (ks->qual.s == NULL)) { + fprintf(stderr, "[ERROR] %s is in fasta format rather than fastq format (%s)\n", f->a[i], opt); + fprintf(stderr, "[ERROR] set --ul-m 0 for fasta files\n"); + return 0; + } + break; + } + kseq_destroy(ks); ks = NULL; + } + gzclose(dfp); + } + return 1; +} + +int check_option(hifiasm_opt_t* asm_opt) +{ + if(asm_opt->read_file_names == NULL || asm_opt->num_reads == 0) + { + fprintf(stderr, "[ERROR] missing input: please specify a read file\n"); + return 0; + } + + if(asm_opt->output_file_name == NULL) + { + fprintf(stderr, "[ERROR] missing output: please specify the output name (-o)\n"); + return 0; + } + + if(asm_opt->thread_num < 1) + { + fprintf(stderr, "[ERROR] the number of threads must be > 0 (-t)\n"); + return 0; + } + + + if(asm_opt->number_of_round < 1) + { + fprintf(stderr, "[ERROR] the number of rounds for correction must be > 0 (-r)\n"); + return 0; + } + + if(asm_opt->clean_round < 1) + { + fprintf(stderr, "[ERROR] the number of rounds for assembly cleaning must be > 0 (-a)\n"); + return 0; + } + + if(asm_opt->adapterLen < 0) + { + fprintf(stderr, "[ERROR] the length of removed adapters must be >= 0 (-z)\n"); + return 0; + } + + + if(asm_opt->k_mer_length >= 64) + { + fprintf(stderr, "[ERROR] the length of k_mer must be < 64 (-k)\n"); + return 0; + } + + + if(asm_opt->max_drop_rate < 0 || asm_opt->max_drop_rate >= 1 ) + { + fprintf(stderr, "[ERROR] max overlap drop ratio must be [0.0, 1.0) (-x)\n"); + return 0; + } + + + if(asm_opt->min_drop_rate < 0 || asm_opt->min_drop_rate >= 1) + { + fprintf(stderr, "[ERROR] min overlap drop ratio must be [0.0, 1.0) (-y)\n"); + return 0; + } + + if(asm_opt->max_drop_rate <= asm_opt->min_drop_rate) + { + fprintf(stderr, "[ERROR] min overlap drop ratio must be less than max overlap drop ratio (-x/-y)\n"); + return 0; + } + + if(asm_opt->small_pop_bubble_size < 0) + { + fprintf(stderr, "[ERROR] the size of popped small bubbles must be >= 0 (-p)\n"); + return 0; + } + + if(asm_opt->large_pop_bubble_size < 0) + { + fprintf(stderr, "[ERROR] the size of popped large bubbles must be >= 0 (-m)\n"); + return 0; + } + + if(asm_opt->max_hang_Len < 0) + { + fprintf(stderr, "[ERROR] max_hang_Len must be >= 0\n"); + return 0; + } + + if(asm_opt->max_hang_rate < 0) + { + fprintf(stderr, "[ERROR] max_hang_rate must be >= 0\n"); + return 0; + } + + if(asm_opt->gap_fuzz < 0) + { + fprintf(stderr, "[ERROR] gap_fuzz must be >= 0\n"); + return 0; + } + + if(asm_opt->min_overlap_Len < 0) + { + fprintf(stderr, "[ERROR] min_overlap_Len must be >= 0\n"); + return 0; + } + + if(asm_opt->min_overlap_coverage < 0) + { + fprintf(stderr, "[ERROR] min_overlap_coverage must be >= 0\n"); + return 0; + } + + if (asm_opt->max_ov_diff_ec < asm_opt->max_ov_diff_final) { + fprintf(stderr, "[ERROR] max_ov_diff_ec shouldn't be smaller than max_ov_diff_final\n"); + return 0; + } + + if (asm_opt->max_ov_diff_ec < HA_MIN_OV_DIFF) { + fprintf(stderr, "[ERROR] max_ov_diff_ec shouldn't be smaller than %g\n", HA_MIN_OV_DIFF); + return 0; + } + + if(asm_opt->max_short_tip < 0) + { + fprintf(stderr, "[ERROR] the length of removal tips must be >= 0 (-n)\n"); + return 0; + } + + if(asm_opt->purge_level_primary < 0 || asm_opt->purge_level_primary > 3) + { + fprintf(stderr, "[ERROR] the level of purge-dup should be [0, 3] (-l)\n"); + return 0; + } + + if(ha_opt_triobin(asm_opt) && ((asm_opt->purge_level_trio < 0 || asm_opt->purge_level_trio > 1))) + { + fprintf(stderr, "[ERROR] the level of purge-dup for trio should be [0, 1] (-l)\n"); + return 0; + } + + if(asm_opt->hom_global_coverage < 0 && asm_opt->hom_global_coverage != -1) + { + fprintf(stderr, "[ERROR] homozygous read coverage should be >= 0 (--hom-cov)\n"); + return 0; + } + + if(asm_opt->pur_global_coverage < 0 && asm_opt->pur_global_coverage != -1) + { + fprintf(stderr, "[ERROR] purge duplication coverage threshold should be >= 0 (--purge-max)\n"); + return 0; + } + + if(asm_opt->bed_inconsist_rate < 0 || asm_opt->bed_inconsist_rate > 100) + { + fprintf(stderr, "[ERROR] inconsistency rate should be [0, 100] (--lowQ)\n"); + return 0; + } + + + if(asm_opt->fn_bin_yak[0] != NULL && check_file(asm_opt->fn_bin_yak[0], "YAK1") == 0) return 0; + if(asm_opt->fn_bin_yak[1] != NULL && check_file(asm_opt->fn_bin_yak[1], "YAK2") == 0) return 0; + if(asm_opt->fn_bin_list[0] != NULL && check_file(asm_opt->fn_bin_list[0], "LIST1") == 0) return 0; + if(asm_opt->fn_bin_list[1] != NULL && check_file(asm_opt->fn_bin_list[1], "LIST2") == 0) return 0; + if(asm_opt->required_read_name != NULL && check_file(asm_opt->required_read_name, "b") == 0) return 0; + + if(asm_opt->hic_reads[0] != NULL && check_hic_reads(asm_opt->hic_reads[0], "HIC1") == 0) return 0; + if(asm_opt->hic_reads[1] != NULL && check_hic_reads(asm_opt->hic_reads[1], "HIC2") == 0) return 0; + if(asm_opt->hic_reads[0] != NULL && asm_opt->hic_reads[1] == NULL) + { + fprintf(stderr, "[ERROR] lack r2 of HiC reads (--h2)\n"); + return 0; + } + if(asm_opt->hic_reads[1] != NULL && asm_opt->hic_reads[0] == NULL) + { + fprintf(stderr, "[ERROR] lack r1 of HiC reads (--h1)\n"); + return 0; + } + + if(asm_opt->hic_reads[0] != NULL && asm_opt->hic_reads[1] != NULL && + asm_opt->hic_reads[0]->n != asm_opt->hic_reads[1]->n) + { + fprintf(stderr, "[ERROR] wrong r1 and r2 of HiC reads (--h1 && --h2)\n"); + return 0; + } + + if(asm_opt->hic_enzymes != NULL && asm_opt->hic_enzymes->n == 0) + { + fprintf(stderr, "[ERROR] wrong HiC enzymes (--enzyme)\n"); + return 0; + } + + if(asm_opt->hic_reads[0] != NULL && asm_opt->hic_reads[0]->n == 0) + { + fprintf(stderr, "[ERROR] wrong r1 of HiC reads (--h1)\n"); + return 0; + } + + if(asm_opt->hic_reads[1] != NULL && asm_opt->hic_reads[1]->n == 0) + { + fprintf(stderr, "[ERROR] wrong r2 of HiC reads (--h2)\n"); + return 0; + } + + if(asm_opt->ar != NULL && check_fq_files(asm_opt->ar, "--ul", asm_opt->ul_mod) == 0) return 0; + if(asm_opt->ar != NULL && asm_opt->ar->n == 0) + { + fprintf(stderr, "[ERROR] wrong UL reads (--ul)\n"); + return 0; + } + + if(asm_opt->b_low_cov < 0) + { + fprintf(stderr, "[ERROR] must >= 0 (--b-cov)\n"); + return 0; + } + + if(asm_opt->b_high_cov != -1 && asm_opt->b_high_cov < 0) + { + fprintf(stderr, "[ERROR] must >= 0 (--h-cov)\n"); + return 0; + } + + if(asm_opt->m_rate < 0) + { + fprintf(stderr, "[ERROR] must >= 0 (--m-rate)\n"); + return 0; + } + + if(asm_opt->b_high_cov != -1 && asm_opt->b_high_cov <= asm_opt->b_low_cov) + { + fprintf(stderr, "[ERROR] [--h-cov] must >= [--b-cov]\n"); + return 0; + } + + if(asm_opt->purge_simi_thres < 0) + { + fprintf(stderr, "[ERROR] [-s] must >= 0\n"); + return 0; + } + + if(asm_opt->max_kmer_cnt < 0) + { + fprintf(stderr, "[ERROR] [--max-kocc] must >= 0\n"); + return 0; + } + + if(asm_opt->hg_size < -1) + { + fprintf(stderr, "[ERROR] [--hg-size] wrong genome size\n"); + return 0; + } + + if(asm_opt->ul_mod != 0 && asm_opt->ul_mod != 1) { + fprintf(stderr, "[ERROR] must be 0 or 1 (--ul-m)\n"); + return 0; + } + + if(asm_opt->telo_motif) { + uint64_t k, tlen = strlen((asm_opt->telo_motif)); char c; + if(tlen > 32) { + fprintf(stderr, "[ERROR] [--telo-m] must be no longer than 32\n"); + return 0; + } + for (k = 0; k < tlen; k++) { + c = asm_opt->telo_motif[k]; + if(c != 'A' && c != 'C' && c != 'G' && c != 'T' && + c != 'a' && c != 'c' && c != 'g' && c != 't') { + fprintf(stderr, "[ERROR] [--telo-m] must be A/C/G/T\n"); + return 0; + } + } + } + + + if((asm_opt->hf) && (!(asm_opt->is_ont))) { + fprintf(stderr, "[ERROR] [--hf] must work with [--ont]\n"); + return 0; + } + + return 1; +} + +void get_queries(int argc, char *argv[], ketopt_t* opt, hifiasm_opt_t* asm_opt) +{ + if(opt->ind == argc) { + return; + } + + asm_opt->num_reads = argc - opt->ind; + asm_opt->read_file_names = (char**)malloc(sizeof(char*)*asm_opt->num_reads); + + long long i; int ret; + gzFile dfp; kseq_t *ks = NULL; + for (i = 0; i < asm_opt->num_reads; i++) { + asm_opt->read_file_names[i] = argv[i + opt->ind]; + dfp = gzopen(asm_opt->read_file_names[i], "r"); + if (dfp == 0) { + fprintf(stderr, "[ERROR] Cannot find the input read file: %s\n", + asm_opt->read_file_names[i]); + exit(0); + } else if(asm_opt->is_sc){ + ks = kseq_init(dfp); + while (((ret = kseq_read(ks)) >= 0)) { + if((ks->qual.l == 0) || (ks->qual.s == NULL)) { + fprintf(stderr, "[ERROR] %s is in fasta format rather than fastq format\n", asm_opt->read_file_names[i]); + asm_opt->is_sc = 0; + exit(0); + } + break; + } + kseq_destroy(ks); ks = NULL; + } + gzclose(dfp); + } +} + +void get_hic_enzymes(char *argv, enzyme** x, int check_name) +{ + int i, k, pre_i, len = strlen(argv); + (*x) = (enzyme*)calloc(1, sizeof(enzyme)); + if(len == 0) + { + (*x)->n = 0; (*x)->l = NULL; (*x)->a = NULL; + return; + } + + + (*x)->n = 1; + for (i = pre_i = 0; i < len; i++) + { + if(argv[i] == ',') + { + (*x)->n++; + continue; + } + + if(check_name) + { + if(argv[i] != 'A' && argv[i] != 'C' && argv[i] != 'G' && argv[i] != 'T' && + argv[i] != 'a' && argv[i] != 'c' && argv[i] != 'g' && argv[i] != 't' && + argv[i] != 'N' && argv[i] != 'n') + { + (*x)->n = 0; + (*x)->l = NULL; + (*x)->a = NULL; + return; + } + } + + } + (*x)->l = (int*)calloc((*x)->n, sizeof(int)); + (*x)->a = (char**)calloc((*x)->n, sizeof(char*)); + + for (i = pre_i = k = 0; i < len; i++) + { + if(argv[i] == ',') + { + (*x)->l[k] = i - pre_i; + (*x)->a[k] = (char*)malloc(sizeof(char)*((*x)->l[k]+1)); + memcpy((*x)->a[k], argv + pre_i, (*x)->l[k]); + (*x)->a[k][(*x)->l[k]] = '\0'; + pre_i = i + 1; + k++; + } + } + + (*x)->l[k] = i - pre_i; + (*x)->a[k] = (char*)malloc(sizeof(char)*((*x)->l[k]+1)); + memcpy((*x)->a[k], argv + pre_i, (*x)->l[k]); + (*x)->a[k][(*x)->l[k]] = '\0'; +} + +int64_t inter_gsize(char *argv) +{ + int64_t len = strlen(argv); + double s; + if(len <= 1) return -2; + char t = argv[len-1]; + if(t != 'k' && t != 'K' && t != 'm' && t != 'M' && t != 'g' && t != 'G') return -2; + char *ss=(char*)malloc(len); + memcpy(ss, argv, len-1); ss[len-1] = '\0'; + s = atof(ss); + free(ss); + if(t == 'k' || t == 'K') return s*1000; + if(t == 'm' || t == 'M') return s*1000000; + if(t == 'g' || t == 'G') return s*1000000000; + return s; +} + +int CommandLine_process(int argc, char *argv[], hifiasm_opt_t* asm_opt) +{ + ketopt_t opt = KETOPT_INIT; + + int c; + + while ((c = ketopt(&opt, argc, argv, 1, "hvt:o:k:w:m:n:r:a:b:z:x:y:p:c:d:M:P:if:D:FN:1:2:3:4:5:l:s:O:eu:", long_options)) >= 0) { + if (c == 'h') + { + Print_H(asm_opt); + return 0; + } + else if (c == 'v' || c == 300) + { + puts(HA_VERSION); + return 0; + } + else if (c == 'f') asm_opt->bf_shift = atoi(opt.arg); + else if (c == 't') asm_opt->thread_num = atoi(opt.arg); + else if (c == 'o') asm_opt->output_file_name = opt.arg; + else if (c == 'r') asm_opt->number_of_round = atoi(opt.arg); + else if (c == 'k') asm_opt->k_mer_length = atoi(opt.arg); + else if (c == 'i') asm_opt->load_index_from_disk = 0; + else if (c == 'w') asm_opt->mz_win = atoi(opt.arg); + else if (c == 'D') asm_opt->high_factor = atof(opt.arg); + else if (c == 'F') asm_opt->flag |= HA_F_NO_KMER_FLT; + else if (c == 'N') asm_opt->max_n_chain = atoi(opt.arg); + else if (c == 'a') asm_opt->clean_round = atoi(opt.arg); + else if (c == 'z') asm_opt->adapterLen = atoi(opt.arg); + else if (c == 'b') asm_opt->required_read_name = opt.arg; + else if (c == 'c') asm_opt->min_cnt = atoi(opt.arg); + else if (c == 'd') asm_opt->mid_cnt = atoi(opt.arg); + else if (c == '1' || c == 'P') asm_opt->fn_bin_yak[0] = opt.arg; // -P/-M reserved for backward compatibility + else if (c == '2' || c == 'M') asm_opt->fn_bin_yak[1] = opt.arg; + else if (c == '3') asm_opt->fn_bin_list[0] = opt.arg; + else if (c == '4') asm_opt->fn_bin_list[1] = opt.arg; + else if (c == '5') asm_opt->fn_bin_poy = opt.arg; + else if (c == 'x') asm_opt->max_drop_rate = atof(opt.arg); + else if (c == 'y') asm_opt->min_drop_rate = atof(opt.arg); + else if (c == 'p') asm_opt->small_pop_bubble_size = atoll(opt.arg); + else if (c == 'm') asm_opt->large_pop_bubble_size = atoll(opt.arg); + else if (c == 'n') asm_opt->max_short_tip = atoll(opt.arg); + else if (c == 'e') asm_opt->flag |= HA_F_BAN_ASSEMBLY; + else if (c == 'u') { + if(atoll(opt.arg)) { + asm_opt->hifi_pst_join = asm_opt->ul_pst_join = 1; + } else { + asm_opt->hifi_pst_join = asm_opt->ul_pst_join = 0; + } + } + else if (c == 301) asm_opt->flag |= HA_F_VERBOSE_GFA; + else if (c == 302) asm_opt->flag |= HA_F_WRITE_PAF; + else if (c == 303) asm_opt->flag |= HA_F_WRITE_EC; + else if (c == 304) asm_opt->flag |= HA_F_SKIP_TRIOBIN; + else if (c == 305) asm_opt->max_ov_diff_ec = atof(opt.arg); + else if (c == 306) asm_opt->max_ov_diff_final = atof(opt.arg); + else if (c == 307) asm_opt->extract_list = opt.arg; + else if (c == 308) asm_opt->extract_iter = atoi(opt.arg); + else if (c == 309) { + asm_opt->hom_global_coverage = asm_opt->hmo_cov_ss = atoi(opt.arg); + asm_opt->hom_global_coverage_set = 1; + if(asm_opt->hmo_cov_ss <= 0) { + fprintf(stderr, "[ERROR] homozygous read coverage should be > 0 (--hom-cov)"); + return 1; + } + } else if (c == 310) + { + char* s = NULL; + asm_opt->recover_atg_cov_min = strtol(opt.arg, &s, 10); + if (*s == ',') asm_opt->recover_atg_cov_max = strtol(s + 1, &s, 10); + if(asm_opt->recover_atg_cov_min == -1 || asm_opt->recover_atg_cov_max == -1) + { + asm_opt->recover_atg_cov_min = asm_opt->recover_atg_cov_max = -1; + } + } + ///else if (c == 311) asm_opt->flag |= HA_F_HIGH_HET; + else if (c == 312) asm_opt->bed_inconsist_rate = atoi(opt.arg); + else if (c == 313) asm_opt->min_hist_kmer_cnt = atoi(opt.arg); + else if (c == 314) get_hic_enzymes(opt.arg, &(asm_opt->hic_reads[0]), 0); + else if (c == 315) get_hic_enzymes(opt.arg, &(asm_opt->hic_reads[1]), 0); + else if (c == 316) get_hic_enzymes(opt.arg, &(asm_opt->hic_enzymes), 1); + else if (c == 317) asm_opt->b_low_cov = atoi(opt.arg); + else if (c == 318) asm_opt->b_high_cov = atoi(opt.arg); + else if (c == 319) asm_opt->m_rate = atof(opt.arg); + else if (c == 320) asm_opt->flag -= HA_F_PARTITION, asm_opt->is_alt = 1; + else if (c == 321) asm_opt->trio_flag_occ_thres = atoi(opt.arg); + else if (c == 322) asm_opt->seed = atol(opt.arg); + else if (c == 323) asm_opt->n_perturb = atoi(opt.arg); + else if (c == 324) asm_opt->f_perturb = atof(opt.arg); + else if (c == 325) asm_opt->polyploidy = atoi(opt.arg); + else if (c == 326) asm_opt->n_weight = atoi(opt.arg); + else if (c == 327) asm_opt->misjoin_len = atol(opt.arg); + else if (c == 328) asm_opt->pur_global_coverage = atoi(opt.arg); + else if (c == 329) asm_opt->flag |= HA_F_FAST; + else if (c == 330) asm_opt->dp_e = atof(opt.arg); + else if (c == 331) asm_opt->max_kmer_cnt = atol(opt.arg); + else if (c == 332) asm_opt->hg_size = inter_gsize(opt.arg); + else if (c == 333) get_hic_enzymes(opt.arg, &(asm_opt->ar), 0); + else if (c == 334) asm_opt->flag |= HA_F_USKEW; + else if (c == 335) asm_opt->kpt_rate = atof(opt.arg); + else if (c == 336) asm_opt->ul_error_rate = atof(opt.arg); + else if (c == 337) asm_opt->is_dbg_het_cnt = 1; + else if (c == 338) asm_opt->max_short_ul_tip = atol(opt.arg); + else if (c == 339) asm_opt->is_low_het_ul = 1; + else if (c == 340) { + asm_opt->trans_base_rate_sec = atof(opt.arg); + if(asm_opt->trans_base_rate_sec < 0) asm_opt->is_base_trans = 0; + } + else if (c == 341) asm_opt->bin_only = 1; + else if (c == 342) asm_opt->ul_clean_round = atol(opt.arg); + else if (c == 343) asm_opt->prt_dbg_gfa = 1; + else if (c == 344) asm_opt->integer_correct_round = atol(opt.arg); + else if (c == 345) asm_opt->dbg_ovec_cal = 1; + else if (c == 346) asm_opt->max_path_drop_rate = atof(opt.arg); + else if (c == 347) asm_opt->min_path_drop_rate = atof(opt.arg); + else if (c == 348) asm_opt->trio_cov_het_ovlp = 1; + else if (c == 349) asm_opt->ul_min_base = atol(opt.arg); + else if (c == 350) asm_opt->self_scaf = 1; + else if (c == 351) asm_opt->self_scaf_gap_max = atol(opt.arg); + else if (c == 352) get_hic_enzymes(opt.arg, &(asm_opt->sec_in), 0); + else if (c == 353) asm_opt->somatic_cov = atol(opt.arg); + else if (c == 354) asm_opt->telo_motif = opt.arg; + else if (c == 355) asm_opt->telo_pen = atol(opt.arg); + else if (c == 356) asm_opt->telo_drop = atol(opt.arg); + else if (c == 357) asm_opt->telo_mic_sc = atol(opt.arg); + else if (c == 358) asm_opt->max_contig_tip = atol(opt.arg); + else if (c == 359) { + asm_opt->is_ont = 1; asm_opt->max_ov_diff_ec = 0.07; asm_opt->is_sc = 1; ///asm_opt->mz_win = 37; asm_opt->k_mer_length = 37; + } /**else if (c == 360) { + asm_opt->is_sc = 1; + }**/ else if (c == 361) { + asm_opt->chemical_cov = atol(opt.arg); + } else if (c == 362) { + asm_opt->chemical_flank = atol(opt.arg); + ///pending for integration + /** + } else if (c == 363) { + asm_opt->ul_mod = atol(opt.arg); + **/ + } else if (c == 364) { + asm_opt->rl_cut = atol(opt.arg); + } else if (c == 365) { + asm_opt->sc_cut = atol(opt.arg); + } else if (c == 366) { + get_hic_enzymes(opt.arg, &(asm_opt->hf), 0); + } else if (c == 367) { + asm_opt->fn_chr_bin = opt.arg; + } else if (c == 368) { + asm_opt->gpath = 1; + } else if (c == 369) { + asm_opt->het_cov_set = asm_opt->het_cov_ss = atoi(opt.arg); + if(asm_opt->het_cov_ss <= 0) { + fprintf(stderr, "[ERROR] heterozygous read coverage should be > 0 (--het-cov)"); + return 1; + } + } else if (c == 370) { + asm_opt->restart = 1; + } else if (c == 371) { + asm_opt->hf_cutoff = atoi(opt.arg); + } else if (c == 372) { + asm_opt->chn_occ = atoi(opt.arg); + if(asm_opt->chn_occ <= 0) { + fprintf(stderr, "[ERROR] chain cutoff should be > 0 (--chn-occ)"); + return 1; + } + } + else if (c == 'l') { ///0: disable purge_dup; 1: purge containment; 2: purge overlap + asm_opt->purge_level_primary = asm_opt->purge_level_trio = atoi(opt.arg); + } + else if (c == 's') asm_opt->purge_simi_rate_l2 = asm_opt->purge_simi_rate_l3 = atof(opt.arg); + else if (c == 'O') asm_opt->purge_overlap_len = atoll(opt.arg); + else if (c == ':') + { + fprintf(stderr, "[ERROR] missing option argument in \"%s\"\n", argv[opt.i - 1]); + return 1; + } + else if (c == '?') + { + fprintf(stderr, "[ERROR] unknown option in \"%s\"\n", argv[opt.i - 1]); + return 1; + } + } + + if(asm_opt->purge_level_primary > 2) asm_opt->purge_simi_thres = asm_opt->purge_simi_rate_l3; + else asm_opt->purge_simi_thres = asm_opt->purge_simi_rate_l2; + + if (argc == opt.ind) + { + Print_H(asm_opt); + return 0; + } + + get_queries(argc, argv, &opt, asm_opt); + + c = ((asm_opt->ar)?(asm_opt->ul_pst_join):(asm_opt->hifi_pst_join)); + if(c) { + if((asm_opt->flag&HA_F_BAN_POST_JOIN)) asm_opt->flag-=HA_F_BAN_POST_JOIN; + } else { + asm_opt->flag |= HA_F_BAN_POST_JOIN; + } + + // fprintf(stderr, "[M::%s::] post join::%u\n", __func__, (uint32_t)(!(asm_opt->flag & HA_F_BAN_POST_JOIN))); + // exit(1); + if(!(asm_opt->is_ont)) { + asm_opt->rl_cut = -1; asm_opt->sc_cut = 1; + } + + return check_option(asm_opt); +} diff --git a/CommandLines.h b/CommandLines.h index 3bebc87..eaf1dea 100644 --- a/CommandLines.h +++ b/CommandLines.h @@ -1,195 +1,217 @@ -#ifndef __COMMAND_LINE_PARSER__ -#define __COMMAND_LINE_PARSER__ - -#define __STDC_LIMIT_MACROS -#include -#include - -#define HA_VERSION "0.25.0-r726" - -#define VERBOSE 0 - -#define HA_F_NO_HPC 0x1 -#define HA_F_NO_KMER_FLT 0x2 -#define HA_F_VERBOSE_GFA 0x4 -#define HA_F_WRITE_EC 0x8 -#define HA_F_WRITE_PAF 0x10 -#define HA_F_SKIP_TRIOBIN 0x20 -#define HA_F_PURGE_CONTAIN 0x40 -#define HA_F_PURGE_JOIN 0x80 -#define HA_F_BAN_POST_JOIN 0x100 -#define HA_F_BAN_ASSEMBLY 0x200 -#define HA_F_HIGH_HET 0x400 -#define HA_F_PARTITION 0x800 -#define HA_F_FAST 0x1000 -#define HA_F_USKEW 0x2000 - -#define HA_MIN_OV_DIFF 0.02 // min sequence divergence in an overlap -#define MIN_N_CHAIN 100 - -typedef struct{ - int *l, n; - char **a; -}enzyme; - -typedef struct { - int flag; - int num_reads; - char** read_file_names; - char* output_file_name; - char* required_read_name; - char *fn_bin_yak[2]; - char *fn_bin_list[2]; - char *fn_bin_poy; - char *extract_list; - enzyme *hic_reads[2]; - enzyme *hic_enzymes; - enzyme *ar; - enzyme *sec_in; - int extract_iter; - int thread_num; - int k_mer_length; - int hic_mer_length; - int ul_mer_length; - int trans_mer_length; - int bub_mer_length; - int mz_win; - int ul_mz_win; - int trans_win; - int mz_rewin; - int ul_mz_rewin; - int mz_sample_dist; - int bf_shift; - int max_kmer_cnt; - double high_factor; // coverage cutoff set to high_factor*hom_cov - double max_ov_diff_ec; - double max_ov_diff_final; - int hom_cov; - int het_cov; - int b_low_cov; - int b_high_cov; - double m_rate; - int max_n_chain; // fall-back max number of chains to consider - int min_hist_kmer_cnt; - int load_index_from_disk; - int write_index_to_disk; - int number_of_round; - int number_of_pround; - int adapterLen; - int clean_round; - int roundID; - int max_hang_Len; - int gap_fuzz; - int min_overlap_Len; - int min_overlap_coverage; - int max_short_tip; - int max_short_ul_tip; - int max_contig_tip; - int min_cnt; - int mid_cnt; - int purge_level_primary; - int purge_level_trio; - int purge_overlap_len; - ///int purge_overlap_len_hic; - int recover_atg_cov_min; - int recover_atg_cov_max; - int hom_global_coverage; - int hom_global_coverage_set; - int pur_global_coverage; - int bed_inconsist_rate; - int hic_inconsist_rate; - - float max_hang_rate; - float min_drop_rate; - float max_drop_rate; - float purge_simi_rate_l2; - float purge_simi_rate_l3; - float purge_simi_thres; - float trans_base_rate; - float trans_base_rate_sec; - float min_path_drop_rate; - float max_path_drop_rate; - // uint64_t path_clean_round; - - ///float purge_simi_rate_hic; - - long long small_pop_bubble_size; - long long large_pop_bubble_size; - long long num_bases; - long long num_corrected_bases; - long long num_recorrected_bases; - long long mem_buf; - long long coverage; - int hap_occ; - int polyploidy; - int trio_flag_occ_thres; - uint64_t seed; - int32_t n_perturb; - double f_perturb; - int32_t n_weight; - uint32_t is_alt; - uint64_t misjoin_len; - uint64_t scffold; - int32_t dp_min_len; - float dp_e; - int64_t hg_size; - float kpt_rate; - int64_t infor_cov, s_hap_cov, trio_cov_het_ovlp; - double ul_error_rate, ul_error_rate_low, ul_error_rate_hpc; - int32_t ul_ec_round; - int32_t ul_mod; - uint8_t is_dbg_het_cnt; - uint8_t is_low_het_ul; - uint8_t is_base_trans; - uint8_t is_read_trans; - uint8_t is_topo_trans; - uint8_t is_bub_trans; - uint8_t bin_only; - int32_t ul_clean_round; - int32_t prt_dbg_gfa; - int32_t integer_correct_round; - uint8_t dbg_ovec_cal; - uint8_t hifi_pst_join, ul_pst_join; - uint32_t ul_min_base; - uint8_t self_scaf; - uint64_t self_scaf_min; - uint64_t self_scaf_reliable_min; - int64_t self_scaf_gap_max; - int64_t somatic_cov; - - char *telo_motif; - int64_t telo_pen; - int64_t telo_drop; - int64_t telo_mic_sc; - - uint64_t is_ont; - uint64_t is_sc; - uint64_t chemical_cov; - uint64_t chemical_flank; - - int64_t rl_cut; - int64_t sc_cut; - -} hifiasm_opt_t; - -extern hifiasm_opt_t asm_opt; - -void init_opt(hifiasm_opt_t* asm_opt); -void destory_opt(hifiasm_opt_t* asm_opt); -void ha_opt_reset_to_round(hifiasm_opt_t* asm_opt, int round); -void ha_opt_update_cov(hifiasm_opt_t *opt, int hom_cov); -void ha_opt_update_cov_min(hifiasm_opt_t *opt, int hom_cov, int min_chain); -int CommandLine_process(int argc, char *argv[], hifiasm_opt_t* asm_opt); -double Get_T(void); - -static inline int ha_opt_triobin(const hifiasm_opt_t *opt) -{ - return ((opt->fn_bin_yak[0] && opt->fn_bin_yak[1]) || (opt->fn_bin_list[0] && opt->fn_bin_list[1])); -} - -static inline int ha_opt_hic(const hifiasm_opt_t *opt) -{ - return ((opt->hic_reads[0] && opt->hic_reads[1])); -} - -#endif +#ifndef __COMMAND_LINE_PARSER__ +#define __COMMAND_LINE_PARSER__ + +#define __STDC_LIMIT_MACROS +#include +#include + +#define HA_VERSION "0.25.0-r852" + +#define VERBOSE 0 + +#define HA_F_NO_HPC 0x1 +#define HA_F_NO_KMER_FLT 0x2 +#define HA_F_VERBOSE_GFA 0x4 +#define HA_F_WRITE_EC 0x8 +#define HA_F_WRITE_PAF 0x10 +#define HA_F_SKIP_TRIOBIN 0x20 +#define HA_F_PURGE_CONTAIN 0x40 +#define HA_F_PURGE_JOIN 0x80 +#define HA_F_BAN_POST_JOIN 0x100 +#define HA_F_BAN_ASSEMBLY 0x200 +#define HA_F_HIGH_HET 0x400 +#define HA_F_PARTITION 0x800 +#define HA_F_FAST 0x1000 +#define HA_F_USKEW 0x2000 + +#define HA_MIN_OV_DIFF 0.02 // min sequence divergence in an overlap +#define MIN_N_CHAIN 100 + +typedef struct{ + int *l, n; + char **a; +}enzyme; + +typedef struct { + int flag; + int num_reads; + char** read_file_names; + char* output_file_name; + char* required_read_name; + char *fn_bin_yak[2]; + char *fn_bin_list[2]; + char *fn_bin_poy; + char *fn_chr_bin; + char *extract_list; + enzyme *hic_reads[2]; + enzyme *hic_enzymes; + enzyme *ar; + enzyme *hf; + enzyme *sec_in; + int extract_iter; + int thread_num; + int k_mer_length; + int hic_mer_length; + int ul_mer_length; + int trans_mer_length; + int bub_mer_length; + int mz_win; + int ul_mz_win; + int trans_win; + int mz_rewin; + int ul_mz_rewin; + int mz_sample_dist; + int bf_shift; + int max_kmer_cnt; + double high_factor; // coverage cutoff set to high_factor*hom_cov + double max_ov_diff_ec; + double max_ov_diff_ec_sec; + double max_ov_diff_final; + int hom_cov; + int het_cov; + int b_low_cov; + int b_high_cov; + double m_rate; + int max_n_chain; // fall-back max number of chains to consider + int min_hist_kmer_cnt; + int load_index_from_disk; + int write_index_to_disk; + int number_of_round; + int number_of_pround; + int adapterLen; + int clean_round; + int roundID; + int max_hang_Len; + int gap_fuzz; + int min_overlap_Len; + int min_overlap_coverage; + int max_short_tip; + int max_short_ul_tip; + int max_contig_tip; + int min_cnt; + int mid_cnt; + int purge_level_primary; + int purge_level_trio; + int purge_overlap_len; + ///int purge_overlap_len_hic; + int recover_atg_cov_min; + int recover_atg_cov_max; + int hom_global_coverage; + int hom_global_coverage_set; + int pur_global_coverage; + int bed_inconsist_rate; + int hic_inconsist_rate; + + float max_hang_rate; + float min_drop_rate; + float max_drop_rate; + float purge_simi_rate_l2; + float purge_simi_rate_l3; + float purge_simi_thres; + float trans_base_rate; + float trans_base_rate_sec; + float min_path_drop_rate; + float max_path_drop_rate; + // uint64_t path_clean_round; + + ///float purge_simi_rate_hic; + + long long small_pop_bubble_size; + long long large_pop_bubble_size; + long long num_bases; + long long num_corrected_bases; + long long num_recorrected_bases; + long long mem_buf; + long long coverage; + int hap_occ; + int polyploidy; + int trio_flag_occ_thres; + uint64_t seed; + int32_t n_perturb; + double f_perturb; + int32_t n_weight; + uint32_t is_alt; + uint64_t misjoin_len; + uint64_t scffold; + int32_t dp_min_len; + float dp_e; + int64_t hg_size; + float kpt_rate; + int64_t infor_cov, s_hap_cov, trio_cov_het_ovlp; + double ul_error_rate, ul_error_rate_low, ul_error_rate_hpc; + int32_t ul_ec_round; + int32_t ul_mod; + uint8_t is_dbg_het_cnt; + uint8_t is_low_het_ul; + uint8_t is_base_trans; + uint8_t is_read_trans; + uint8_t is_topo_trans; + uint8_t is_bub_trans; + uint8_t bin_only; + int32_t ul_clean_round; + int32_t prt_dbg_gfa; + int32_t integer_correct_round; + uint8_t dbg_ovec_cal; + uint8_t hifi_pst_join, ul_pst_join; + uint32_t ul_min_base; + uint8_t self_scaf; + uint64_t self_scaf_min; + uint64_t self_scaf_reliable_min; + int64_t self_scaf_gap_max; + int64_t somatic_cov; + + char *telo_motif; + int64_t telo_pen; + int64_t telo_drop; + int64_t telo_mic_sc; + + uint64_t is_ont; + uint64_t is_sc; + uint64_t chemical_cov; + uint64_t chemical_flank; + + int64_t rl_cut; + int64_t sc_cut; + uint8_t gpath; + + uint64_t hf_rate;///cannot be larger than 128? + uint64_t hf_rate_max;///cannot be larger than 128? + uint64_t ont_rate;///cannot be 0, should be 1 in anyway + + int64_t het_cov_set; + int64_t restart; + + int64_t hf_cutoff; + + uint8_t write_pos_idx; + + int hom_cov_0; + int het_cov_0; + int max_n_chain_0; // fall-back max number of chains to consider + + int64_t hmo_cov_ss; + int64_t het_cov_ss; + int64_t chn_occ; +} hifiasm_opt_t; + +extern hifiasm_opt_t asm_opt; + +void init_opt(hifiasm_opt_t* asm_opt); +void destory_opt(hifiasm_opt_t* asm_opt); +void ha_opt_reset_to_round(hifiasm_opt_t* asm_opt, int round); +void ha_opt_update_cov(hifiasm_opt_t *opt, int hom_cov); +void ha_opt_update_cov_min(hifiasm_opt_t *opt, int hom_cov, int min_chain); +int CommandLine_process(int argc, char *argv[], hifiasm_opt_t* asm_opt); +double Get_T(void); + +static inline int ha_opt_triobin(const hifiasm_opt_t *opt) +{ + return ((opt->fn_bin_yak[0] && opt->fn_bin_yak[1]) || (opt->fn_bin_list[0] && opt->fn_bin_list[1])); +} + +static inline int ha_opt_hic(const hifiasm_opt_t *opt) +{ + return ((opt->hic_reads[0] && opt->hic_reads[1])); +} + +#endif diff --git a/Correct.cpp b/Correct.cpp index 809e71a..3b09f5e 100644 --- a/Correct.cpp +++ b/Correct.cpp @@ -1,25962 +1,34308 @@ -#define __STDC_LIMIT_MACROS -#include -#include -#include -#include -#include -#include -#include -#include "Correct.h" -#include "Levenshtein_distance.h" -#include "Assembly.h" -#include "CommandLines.h" -// #include "ksw2.h" -#include "ksort.h" -#include "kalloc.h" -#include "htab.h" -#include "Overlaps.h" -#include "inter.h" -#include "Process_Read.h" -#define A_L 16 -#define ext_w 6 -#define r_simi_w 0.05 -#define rphase_thres 4 - -#define generic_key(x) (x) -KRADIX_SORT_INIT(b32, uint32_t, generic_key, 4) -KRADIX_SORT_INIT(bc64, uint64_t, generic_key, 8) - -#define haplotype_evdience_key(x) ((x).site) -KRADIX_SORT_INIT(haplotype_evdience_srt, haplotype_evdience, haplotype_evdience_key, member_size(haplotype_evdience, site)) - -#define haplotype_evdience_id_key(x) ((x).overlapID) -KRADIX_SORT_INIT(haplotype_evdience_id_srt, haplotype_evdience, haplotype_evdience_id_key, member_size(haplotype_evdience, overlapID)) - -#define haplotype_evdience_os_key(x) ((x).overlapSite) -KRADIX_SORT_INIT(haplotype_evdience_os_srt, haplotype_evdience, haplotype_evdience_os_key, member_size(haplotype_evdience, overlapSite)) - -#define overlap_region_dp_key(x) ((x).x_pos_e) -KRADIX_SORT_INIT(overlap_region_dp_srt, overlap_region, overlap_region_dp_key, member_size(overlap_region, x_pos_e)) - -#define window_list_xs_key(x) ((x).x_start) -KRADIX_SORT_INIT(window_list_xs_srt, window_list, window_list_xs_key, member_size(window_list, x_start)) - -#define uov_qs_key(p) ((p).qs) -KRADIX_SORT_INIT(uov_srt_qs, ul_ov_t, uov_qs_key, member_size(ul_ov_t, qs)) - -#define k_mer_hit_self_key(p) ((p).self_offset) -KRADIX_SORT_INIT(k_mer_hit_self, k_mer_hit, k_mer_hit_self_key, member_size(k_mer_hit, self_offset)) - -#define k_mer_hit_off_key(p) ((p).offset) -KRADIX_SORT_INIT(k_mer_hit_off, k_mer_hit, k_mer_hit_off_key, member_size(k_mer_hit, offset)) - -#define ul_ov_srt_qs1_key(p) ((p).qs) -KRADIX_SORT_INIT(ul_ov_srt_qs1, ul_ov_t, ul_ov_srt_qs1_key, member_size(ul_ov_t, qs)) - -#define ul_ov_srt_tn1_key(p) ((p).tn) -KRADIX_SORT_INIT(ul_ov_srt_tn1, ul_ov_t, ul_ov_srt_tn1_key, member_size(ul_ov_t, tn)) - -#define ul_ov_srt_qn1_key(p) ((p).qn) -KRADIX_SORT_INIT(ul_ov_srt_qn1, ul_ov_t, ul_ov_srt_qn1_key, member_size(ul_ov_t, qn)) - -#define ul_ov_srt_qe1_key(p) ((p).qe) -KRADIX_SORT_INIT(ul_ov_srt_qe1, ul_ov_t, ul_ov_srt_qe1_key, member_size(ul_ov_t, qe)) - -#define ul_ov_srt_ts1_key(p) ((p).ts) -KRADIX_SORT_INIT(ul_ov_srt_ts1, ul_ov_t, ul_ov_srt_ts1_key, member_size(ul_ov_t, ts)) - -#define MAX_SEC_ERR (0x3fffffffU) - - -int ha_ov_type(const overlap_region *r, uint32_t len); -void set_lchain_dp_op(uint32_t is_accurate, uint32_t mz_k, int64_t *max_skip, int64_t *max_iter, int64_t *max_dis, double *chn_pen_gap, double *chn_pen_skip, int64_t *quick_check); - -void clear_Round2_alignment(Round2_alignment* h) -{ - clear_Correct_dumy_pure(&(h->dumy)); - clear_Cigar_record(&(h->cigar)); - clear_Cigar_record(&(h->tmp_cigar)); - h->obtained_cigar_length = 0; -} - -void init_Round2_alignment(Round2_alignment* h) -{ - init_Correct_dumy(&(h->dumy)); - init_Cigar_record(&(h->cigar)); - init_Cigar_record(&(h->tmp_cigar)); - h->obtained_cigar_length = 0; -} - -void init_Round2_alignment_buf(Round2_alignment* h, void *km) -{ - init_Correct_dumy_buf(&(h->dumy), km); - init_Cigar_record_buf(&(h->cigar), km); - init_Cigar_record_buf(&(h->tmp_cigar), km); - h->obtained_cigar_length = 0; -} - -void destory_Round2_alignment(Round2_alignment* h) -{ - destory_Correct_dumy(&(h->dumy)); - destory_Cigar_record(&(h->cigar)); - destory_Cigar_record(&(h->tmp_cigar)); -} - - - -inline int get_interval(long long window_start, long long window_end, overlap_region_alloc* overlap_list, Correct_dumy* dumy, long long blockLen) -{ - uint64_t i, fud = 0; - long long Len; - if(window_start == 0) dumy->start_i = 0; - for (i = dumy->start_i; i < overlap_list->length; i++) - { - ///this interval is smaller than all overlaps - ///in this case, the next interval should start from 0 - if (window_end < (long long)overlap_list->list[i].x_pos_s) - { - dumy->start_i = 0; - dumy->length = 0; - dumy->lengthNT = 0; - return 0; - } - else ///if window_end >= overlap_list->list[i].x_pos_s,this overlap might be overlapped with current interval - { - dumy->start_i = i; - break; - } - } - - - ///this interval is larger than all overlaps, so we don't need to scan next overlap - if (i >= overlap_list->length) - { - dumy->start_i = overlap_list->length; - dumy->length = 0; - dumy->lengthNT = 0; - return -2; - } - - dumy->length = 0; - dumy->lengthNT = 0; - fud = 0; - - for (; i < overlap_list->length; i++) - { - if((Len = OVERLAP(window_start, window_end, (long long)overlap_list->list[i].x_pos_s, (long long)overlap_list->list[i].x_pos_e)) > 0) - { - ///sometimes the length of window > WINDOW, but overlap length == WINDOW - // if (Len == WINDOW && window_end - window_start + 1 == WINDOW) - if (Len == blockLen && window_end - window_start + 1 == blockLen) - { - dumy->overlapID[dumy->length] = i; - dumy->length++; - } - else - { - dumy->lengthNT++; - dumy->overlapID[dumy->size - dumy->lengthNT] = i; - } - if(fud == 0) fud = 1, dumy->start_i = i; - } - - if((long long)overlap_list->list[i].x_pos_s > window_end) - { - break; - } - } - - if ( dumy->length + dumy->lengthNT == 0) - { - return 0; - } - else - { - return 1; - } -} - - -inline int get_available_interval(long long window_start, long long window_end, overlap_region_alloc* overlap_list, Correct_dumy* dumy) -{ - uint64_t i, fud = 0; - long long Len; - if(window_start == 0) dumy->start_i = 0; - for (i = dumy->start_i; i < overlap_list->length; i++) - { - ///this interval is smaller than all overlaps - ///in this case, the next interval should start from 0 - if (window_end < (long long)overlap_list->list[i].x_pos_s) - { - dumy->start_i = 0; - dumy->length = 0; - dumy->lengthNT = 0; - return 0; - } - else ///if window_end >= overlap_list->list[i].x_pos_s,this overlap might be overlapped with current interval - { - dumy->start_i = i; - break; - } - } - - ///this interval is larger than all overlaps, so we don't need to scan next overlap - if (i >= overlap_list->length) - { - dumy->start_i = overlap_list->length; - dumy->length = 0; - dumy->lengthNT = 0; - return -2; - } - - dumy->length = 0; - dumy->lengthNT = 0; - fud = 0; - - - long long fake_length = 0; - - for (; i < overlap_list->length; i++) - { - ///check if the interval is overlapped with current overlap - if((Len = OVERLAP(window_start, window_end, (long long)overlap_list->list[i].x_pos_s, (long long)overlap_list->list[i].x_pos_e)) > 0) - { - ///number of overlaps - fake_length++; - - ///check if this overlap is available - if (overlap_list->list[i].is_match == 1) - { - dumy->overlapID[dumy->length] = i; - dumy->length++; - } - if(fud == 0) fud = 1, dumy->start_i = i; - } - - if((long long)overlap_list->list[i].x_pos_s > window_end) - { - break; - } - } - - ///fake_length is the number of overlaps, instead of the number of available overlaps - if (fake_length == 0) - { - return 0; - } - else - { - return 1; - } -} - -///Len = OVERLAP(window_start, window_end, overlap_list->list[i].x_pos_s, overlap_list->list[i].x_pos_e)) - -void print_string(char* s, int l) -{ - int i; - for (i = 0; i < l; i++) - { - fprintf(stderr, "%c", s[i]); - } - - fprintf(stderr, "\n"); - -} - - - - -void fill_subregion(char* r, long long start_pos, long long length, uint8_t strand, All_reads* R_INF, long long ID, -int extra_begin, int extra_end) -{ - - recover_UC_Read_sub_region(r+extra_begin, start_pos, length, strand, R_INF, ID); - memset(r, 'N', extra_begin); - memset(r+extra_begin+length, 'N', extra_end); -} - -void fill_subregion_ul(char* r, long long start_pos, long long length, uint8_t strand, const ul_idx_t *uref, long long ID, -int extra_begin, int extra_end) -{ - retrieve_u_seq(NULL, r+extra_begin, &(uref->ug->u.a[ID]), strand, start_pos, length, NULL); - memset(r, 'N', extra_begin); - memset(r+extra_begin+length, 'N', extra_end); -} - -int determine_overlap_region(int threshold, long long y_start, long long y_ID, long long Window_Len, /**All_reads* R_INF**/long long y_len, -int* r_extra_begin, int* r_extra_end, long long* r_y_start, long long* r_y_length) -{ - int extra_begin; - int extra_end; - long long currentIDLen; - long long o_len; - - ///the length of y - // currentIDLen = Get_READ_LENGTH((*R_INF), y_ID); - currentIDLen = y_len; - - ///since Window_Len == x_len + (threshold << 1) - if(y_start < 0 || currentIDLen <= y_start || - currentIDLen - y_start + 2 * threshold + THRESHOLD_MAX_SIZE < Window_Len) - { - return 0; - } - - extra_begin = extra_end = 0; - ///y maybe less than 0 - y_start = y_start - threshold; - o_len = MIN(Window_Len, currentIDLen - y_start); - extra_end = Window_Len - o_len; - - if (y_start < 0) - { - extra_begin = -y_start; - y_start = 0; - o_len = o_len - extra_begin; - } - - (*r_extra_begin) = extra_begin; - (*r_extra_end) = extra_end; - (*r_y_start) = y_start; - (*r_y_length) = o_len; - - return 1; -} - - -int verify_single_window(long long x_start, long long x_end, -long long overlap_x_s, long long overlap_y_s, int x_id, -int y_id, int x_strand, char* x_buffer, char* y_buffer, -All_reads* R_INF) -{ - char* x_string = NULL; - char* y_string = NULL; - int extra_begin, extra_end, x_len, threshold; - long long y_start; - long long Window_Len, o_len; - unsigned int error; - - - - x_len = x_end - x_start + 1; - threshold = x_len * asm_opt.max_ov_diff_ec; - /****************************may have bugs********************************/ - threshold = Adjust_Threshold(threshold, x_len); - /****************************may have bugs********************************/ - - y_start = (x_start - overlap_x_s) + overlap_y_s; - - Window_Len = x_len + (threshold << 1); - - if(!determine_overlap_region(threshold, y_start, y_id, Window_Len, Get_READ_LENGTH((*R_INF), y_id), - &extra_begin, &extra_end, &y_start, &o_len)) - { - return 0; - } - - ///use unusual direction here - /** - fill_subregion(y_buffer, y_start, o_len, y_strand, R_INF, y_id, extra_begin, extra_end); - ///x is always forward strand - recover_UC_Read_sub_region(x_buffer, x_start, x_len, 0, R_INF, x_id); - **/ - ///use unusual direction here, here y is always forward strand - fill_subregion(y_buffer, y_start, o_len, 0, R_INF, y_id, extra_begin, extra_end); - recover_UC_Read_sub_region(x_buffer, x_start, x_len, x_strand, R_INF, x_id); - - - x_string = x_buffer; - y_string = y_buffer; - - Reserve_Banded_BPM(y_string, Window_Len, x_string, x_len, threshold, &error); - - if (error!=(unsigned int)-1) - { - return 1; - } - - return 0; -} - -void verify_window(long long window_start, long long window_end, overlap_region_alloc* overlap_list,Correct_dumy* dumy, All_reads* R_INF, -char* r_string) -{ - long long i; - long long currentID; - long long x_start, y_start, o_len; - long long Window_Len = WINDOW + (THRESHOLD << 1); - char* x_string = NULL; - char* y_string = NULL; - long long x_end, x_len; - int end_site; - unsigned int error; - int groupLen = 0; - int return_sites[GROUP_SIZE]; - unsigned int return_sites_error[GROUP_SIZE]; - uint64_t overlapID[GROUP_SIZE]; - uint64_t y_startGroup[GROUP_SIZE]; - int y_extra_begin[GROUP_SIZE]; - int y_extra_end[GROUP_SIZE]; - int error_threshold[GROUP_SIZE]; - int extra_begin; - int extra_end; - - ///here are overlaps fully covered by WINDOW - for (i = 0; i < (long long)dumy->length; i++) - { - extra_begin = extra_end = 0; - ///if the window has been fully covered, the interval at x is [window_start, window_end] - x_len = WINDOW; - currentID = dumy->overlapID[i]; - x_start = window_start; - ///offset of y - y_start = (x_start - overlap_list->list[currentID].x_pos_s) + overlap_list->list[currentID].y_pos_s; - /****************************may have bugs********************************/ - y_start += y_start_offset(x_start, &(overlap_list->list[currentID].f_cigar)); - /****************************may have bugs********************************/ - - - if(!determine_overlap_region(THRESHOLD, y_start, overlap_list->list[currentID].y_id, Window_Len, Get_READ_LENGTH((*R_INF), overlap_list->list[currentID].y_id), - &extra_begin, &extra_end, &y_start, &o_len)) { - continue; - } - - fill_subregion(dumy->overlap_region_group[groupLen], y_start, o_len, overlap_list->list[currentID].y_pos_strand, - R_INF, overlap_list->list[currentID].y_id, extra_begin, extra_end); - - y_extra_begin[groupLen] = extra_begin; - y_extra_end[groupLen] = extra_end; - overlapID[groupLen] = currentID; - y_startGroup[groupLen] = y_start; - error_threshold[groupLen] = THRESHOLD; - x_string = r_string + x_start; - groupLen++; - - - if (groupLen == GROUP_SIZE) - { - Reserve_Banded_BPM_4_SSE_only(dumy->overlap_region_group[0], dumy->overlap_region_group[1], - dumy->overlap_region_group[2], dumy->overlap_region_group[3], Window_Len, x_string, WINDOW, - return_sites, return_sites_error, THRESHOLD, dumy->Peq_SSE); - groupLen = 0; - - - if (return_sites_error[0]!=(unsigned int)-1) { - overlap_list->list[overlapID[0]].align_length += x_len; - - append_window_list(&overlap_list->list[overlapID[0]], window_start, window_end, - y_startGroup[0], y_startGroup[0] + return_sites[0], (int)return_sites_error[0], - y_extra_begin[0], y_extra_end[0], error_threshold[0], WINDOW, NULL); - } - - - if (return_sites_error[1]!=(unsigned int)-1) { - overlap_list->list[overlapID[1]].align_length += x_len; - - append_window_list(&overlap_list->list[overlapID[1]], window_start, window_end, - y_startGroup[1], y_startGroup[1] + return_sites[1], (int)return_sites_error[1], - y_extra_begin[1], y_extra_end[1], error_threshold[1], WINDOW, NULL); - } - - - if (return_sites_error[2]!=(unsigned int)-1) { - overlap_list->list[overlapID[2]].align_length += x_len; - - append_window_list(&overlap_list->list[overlapID[2]], window_start, window_end, - y_startGroup[2], y_startGroup[2] + return_sites[2], (int)return_sites_error[2], - y_extra_begin[2], y_extra_end[2], error_threshold[2], WINDOW, NULL); - } - - - if (return_sites_error[3]!=(unsigned int)-1) { - overlap_list->list[overlapID[3]].align_length += x_len; - - append_window_list(&overlap_list->list[overlapID[3]], window_start, window_end, - y_startGroup[3], y_startGroup[3] + return_sites[3], (int)return_sites_error[3], - y_extra_begin[3], y_extra_end[3], error_threshold[3], WINDOW, NULL); - } - } - } - - if (groupLen == 1) - { - end_site = Reserve_Banded_BPM(dumy->overlap_region_group[0], Window_Len, x_string, WINDOW, THRESHOLD, &error); - - if (error!=(unsigned int)-1) { - overlap_list->list[overlapID[0]].align_length += x_len; - - append_window_list(&overlap_list->list[overlapID[0]], window_start, window_end, - y_startGroup[0], y_startGroup[0] + end_site, (int)error, - y_extra_begin[0], y_extra_end[0], error_threshold[0], WINDOW, NULL); - } - } - else if (groupLen > 1) - { - Reserve_Banded_BPM_4_SSE_only(dumy->overlap_region_group[0], dumy->overlap_region_group[1], - dumy->overlap_region_group[2], dumy->overlap_region_group[3], Window_Len, x_string, WINDOW, - return_sites, return_sites_error, THRESHOLD, dumy->Peq_SSE); - - for (i = 0; i < groupLen; i++) - { - if (return_sites_error[i]!=(unsigned int)-1) { - overlap_list->list[overlapID[i]].align_length += x_len; - append_window_list(&overlap_list->list[overlapID[i]], window_start, window_end, - y_startGroup[i], y_startGroup[i] + return_sites[i], (int)return_sites_error[i], - y_extra_begin[i], y_extra_end[i], error_threshold[i], WINDOW, NULL); - } - } - - groupLen = 0; - } - - long long reverse_i = dumy->size - 1; - int threshold; - - ///here are overlaps partially covered by WINDOW - for (i = 0; i < (long long)dumy->lengthNT; i++) - { - extra_begin = extra_end = 0; - currentID = dumy->overlapID[reverse_i--]; - x_start = MAX(window_start, (long long)overlap_list->list[currentID].x_pos_s); - x_end = MIN(window_end, (long long)overlap_list->list[currentID].x_pos_e); - - ///overlap length between [window_start, window_end] - x_len = x_end - x_start + 1; - threshold = x_len * asm_opt.max_ov_diff_ec; - /****************************may have bugs********************************/ - threshold = Adjust_Threshold(threshold, x_len); - if(threshold > THRESHOLD_MAX_SIZE) threshold = THRESHOLD_MAX_SIZE; - /****************************may have bugs********************************/ - - ///offset of y - y_start = (x_start - overlap_list->list[currentID].x_pos_s) + overlap_list->list[currentID].y_pos_s; - /****************************may have bugs********************************/ - y_start += y_start_offset(x_start, &(overlap_list->list[currentID].f_cigar)); - /****************************may have bugs********************************/ - - Window_Len = x_len + (threshold << 1); - - if(!determine_overlap_region(threshold, y_start, overlap_list->list[currentID].y_id, Window_Len, Get_READ_LENGTH((*R_INF), overlap_list->list[currentID].y_id), - &extra_begin, &extra_end, &y_start, &o_len)) { - continue; - } - - fill_subregion(dumy->overlap_region, y_start, o_len, overlap_list->list[currentID].y_pos_strand, - R_INF, overlap_list->list[currentID].y_id, extra_begin, extra_end); - - x_string = r_string + x_start; - y_string = dumy->overlap_region; - - end_site = Reserve_Banded_BPM(y_string, Window_Len, x_string, x_len, threshold, &error); - - if (error!=(unsigned int)-1) { - overlap_list->list[currentID].align_length += x_len; - append_window_list(&overlap_list->list[currentID], x_start, x_end, y_start, y_start + end_site, (int)error, - extra_begin, extra_end, threshold, WINDOW, NULL); - } - } -} - - -void verify_ul_window(long long window_start, long long window_end, overlap_region_alloc* overlap_list,Correct_dumy* dumy, const ul_idx_t *uref, -char* r_string, double max_ov_diff_ec, long long blockLen, long long max_error, void *km) -{ - long long i; - long long currentID; - long long x_start, y_start, o_len; - long long Window_Len = blockLen + (max_error << 1); - char* x_string = NULL; - char* y_string = NULL; - long long x_end, x_len; - int end_site; - unsigned int error; - int groupLen = 0; - int return_sites[GROUP_SIZE]; - unsigned int return_sites_error[GROUP_SIZE]; - uint64_t overlapID[GROUP_SIZE]; - uint64_t y_startGroup[GROUP_SIZE]; - int y_extra_begin[GROUP_SIZE]; - int y_extra_end[GROUP_SIZE]; - int error_threshold[GROUP_SIZE]; - int extra_begin; - int extra_end; - - ///here are overlaps fully covered by blockLen - for (i = 0; i < (long long)dumy->length; i++) - { - extra_begin = extra_end = 0; - ///if the window has been fully covered, the interval at x is [window_start, window_end] - x_len = blockLen; - currentID = dumy->overlapID[i]; - x_start = window_start; - ///offset of y - y_start = (x_start - overlap_list->list[currentID].x_pos_s) + overlap_list->list[currentID].y_pos_s; - /****************************may have bugs********************************/ - y_start += y_start_offset(x_start, &(overlap_list->list[currentID].f_cigar)); - /****************************may have bugs********************************/ - - - if(!determine_overlap_region(max_error, y_start, overlap_list->list[currentID].y_id, Window_Len, uref->ug->u.a[overlap_list->list[currentID].y_id].len, - &extra_begin, &extra_end, &y_start, &o_len)) { - continue; - } - - // if(overlap_list->list[currentID].y_id == 4) { - // fprintf(stderr, "[M::%s] q_s::%lld, t_s::%lld, t_pri_l::%lld, aux_beg::%d, aux_end::%d, aln_l::%lld\n", __func__, - // x_start, y_start, o_len, extra_begin, extra_end, Window_Len); - // } - - fill_subregion_ul(dumy->overlap_region_group[groupLen], y_start, o_len, overlap_list->list[currentID].y_pos_strand, - uref, overlap_list->list[currentID].y_id, extra_begin, extra_end); - - y_extra_begin[groupLen] = extra_begin; - y_extra_end[groupLen] = extra_end; - overlapID[groupLen] = currentID; - y_startGroup[groupLen] = y_start; - error_threshold[groupLen] = max_error; - x_string = r_string + x_start; - groupLen++; - - - if (groupLen == GROUP_SIZE) - { - // Reserve_Banded_BPM_4_SSE_only(dumy->overlap_region_group[0], dumy->overlap_region_group[1], - // dumy->overlap_region_group[2], dumy->overlap_region_group[3], Window_Len, x_string, blockLen, - // return_sites, return_sites_error, max_error, dumy->Peq_SSE); - return_sites[0] = - Reserve_Banded_BPM(dumy->overlap_region_group[0], Window_Len, x_string, blockLen, max_error, &return_sites_error[0]); - return_sites[1] = - Reserve_Banded_BPM(dumy->overlap_region_group[1], Window_Len, x_string, blockLen, max_error, &return_sites_error[1]); - return_sites[2] = - Reserve_Banded_BPM(dumy->overlap_region_group[2], Window_Len, x_string, blockLen, max_error, &return_sites_error[2]); - return_sites[3] = - Reserve_Banded_BPM(dumy->overlap_region_group[3], Window_Len, x_string, blockLen, max_error, &return_sites_error[3]); - - - - - - groupLen = 0; - - if (return_sites_error[0]!=(unsigned int)-1) { - overlap_list->list[overlapID[0]].align_length += x_len; - - append_window_list(&overlap_list->list[overlapID[0]], window_start, window_end, - y_startGroup[0], y_startGroup[0] + return_sites[0], (int)return_sites_error[0], - y_extra_begin[0], y_extra_end[0], error_threshold[0], blockLen, km); - } - - - if (return_sites_error[1]!=(unsigned int)-1) { - overlap_list->list[overlapID[1]].align_length += x_len; - append_window_list(&overlap_list->list[overlapID[1]], window_start, window_end, - y_startGroup[1], y_startGroup[1] + return_sites[1], (int)return_sites_error[1], - y_extra_begin[1], y_extra_end[1], error_threshold[1], blockLen, km); - } - - - if (return_sites_error[2]!=(unsigned int)-1) { - overlap_list->list[overlapID[2]].align_length += x_len; - - append_window_list(&overlap_list->list[overlapID[2]], window_start, window_end, - y_startGroup[2], y_startGroup[2] + return_sites[2], (int)return_sites_error[2], - y_extra_begin[2], y_extra_end[2], error_threshold[2], blockLen, km); - } - - - if (return_sites_error[3]!=(unsigned int)-1) { - overlap_list->list[overlapID[3]].align_length += x_len; - - append_window_list(&overlap_list->list[overlapID[3]], window_start, window_end, - y_startGroup[3], y_startGroup[3] + return_sites[3], (int)return_sites_error[3], - y_extra_begin[3], y_extra_end[3], error_threshold[3], blockLen, km); - } - } - } - - if (groupLen == 1) - { - end_site = Reserve_Banded_BPM(dumy->overlap_region_group[0], Window_Len, x_string, blockLen, max_error, &error); - - if (error!=(unsigned int)-1) { - overlap_list->list[overlapID[0]].align_length += x_len; - - append_window_list(&overlap_list->list[overlapID[0]], window_start, window_end, - y_startGroup[0], y_startGroup[0] + end_site, (int)error, - y_extra_begin[0], y_extra_end[0], error_threshold[0], blockLen, km); - } - } - else if (groupLen > 1) - { - // Reserve_Banded_BPM_4_SSE_only(dumy->overlap_region_group[0], dumy->overlap_region_group[1], - // dumy->overlap_region_group[2], dumy->overlap_region_group[3], Window_Len, x_string, blockLen, - // return_sites, return_sites_error, max_error, dumy->Peq_SSE); - - for (i = 0; i < groupLen; i++) - { - return_sites[i] = Reserve_Banded_BPM(dumy->overlap_region_group[i], Window_Len, x_string, blockLen, max_error, &return_sites_error[i]); - - if (return_sites_error[i]!=(unsigned int)-1) { - overlap_list->list[overlapID[i]].align_length += x_len; - append_window_list(&overlap_list->list[overlapID[i]], window_start, window_end, - y_startGroup[i], y_startGroup[i] + return_sites[i], (int)return_sites_error[i], - y_extra_begin[i], y_extra_end[i], error_threshold[i], blockLen, km); - } - } - - groupLen = 0; - } - - long long reverse_i = dumy->size - 1; - int threshold; - - ///here are overlaps partially covered by blockLen - for (i = 0; i < (long long)dumy->lengthNT; i++) - { - extra_begin = extra_end = 0; - currentID = dumy->overlapID[reverse_i--]; - x_start = MAX(window_start, (long long)overlap_list->list[currentID].x_pos_s); - x_end = MIN(window_end, (long long)overlap_list->list[currentID].x_pos_e); - - ///overlap length between [window_start, window_end] - x_len = x_end - x_start + 1; - threshold = x_len * max_ov_diff_ec; - /****************************may have bugs********************************/ - threshold = Adjust_Threshold(threshold, x_len); - if(threshold > THRESHOLD_MAX_SIZE) threshold = THRESHOLD_MAX_SIZE; - /****************************may have bugs********************************/ - - ///offset of y - y_start = (x_start - overlap_list->list[currentID].x_pos_s) + overlap_list->list[currentID].y_pos_s; - /****************************may have bugs********************************/ - y_start += y_start_offset(x_start, &(overlap_list->list[currentID].f_cigar)); - /****************************may have bugs********************************/ - - Window_Len = x_len + (threshold << 1); - - if(!determine_overlap_region(threshold, y_start, overlap_list->list[currentID].y_id, Window_Len, uref->ug->u.a[overlap_list->list[currentID].y_id].len, - &extra_begin, &extra_end, &y_start, &o_len)) { - continue; - } - - // if(overlap_list->list[currentID].y_id == 4) { - // fprintf(stderr, "[M::%s] q_s::%lld, t_s::%lld, t_pri_l::%lld, aux_beg::%d, aux_end::%d, aln_l::%lld\n", __func__, - // x_start, y_start, o_len, extra_begin, extra_end, Window_Len); - // } - - fill_subregion_ul(dumy->overlap_region, y_start, o_len, overlap_list->list[currentID].y_pos_strand, - uref, overlap_list->list[currentID].y_id, extra_begin, extra_end); - - x_string = r_string + x_start; - y_string = dumy->overlap_region; - - end_site = Reserve_Banded_BPM(y_string, Window_Len, x_string, x_len, threshold, &error); - - if (error!=(unsigned int)-1) { - overlap_list->list[currentID].align_length += x_len; - append_window_list(&overlap_list->list[currentID], x_start, x_end, y_start, y_start + end_site, (int)error, - extra_begin, extra_end, threshold, blockLen, km); - } - } -} - -int32_t init_waln(int64_t err, int64_t s, int64_t l, int64_t w_l, int64_t* aux_beg, int64_t* aux_end, int64_t* r_s, int64_t* r_l) -{ - (*aux_beg) = (*aux_end) = (*r_s) = (*r_l) = -1; - ///since w_l == x_len + (err << 1) - if((s < 0) || (s >= l) || ((l-s+(2*err)+THRESHOLD_MAX_SIZE) < w_l)) return 0; - (*aux_beg) = (*aux_end) = 0; - ///s might be less than 0 - (*r_s) = s - err; - (*r_l) = l-(*r_s); if((*r_l) > w_l) (*r_l) = w_l; - (*aux_end) = w_l - (*r_l); - - if ((*r_s) < 0) { - (*aux_beg) = -(*r_s); (*r_s) = 0; (*r_l) -= (*aux_beg); - } - return 1; -} - -///[s, e) -int64_t get_num_wins(int64_t s, int64_t e, int64_t block_s) -{ - int64_t nl = e - ((s/block_s)*block_s), nw; - nw = (nl/block_s); if((nl%block_s)>0) nw++; - return nw; -} - -void gen_str_seq(char *dst, int64_t s, int64_t pri_l, uint8_t rev, const ul_idx_t *uref, long long id, int64_t aux_beg, int64_t aux_end) -{ - // int64_t l = pri_l + aux_beg + aux_end; - memset(dst, 'N', aux_beg); - retrieve_u_seq(NULL, dst+aux_beg, &(uref->ug->u.a[id]), rev, s, pri_l, NULL); - memset(dst+aux_beg+pri_l, 'N', aux_end); -} - -void verify_ul_window_s(overlap_region *z, const ul_idx_t *uref, char* qstr, char *tstr, -double e_rate, int64_t w_l, int64_t e_max, void *km) -{ - int64_t q_s, q_e, nw, k, q_l; - int64_t aux_beg, aux_end, t_s, thre, aln_l, t_pri_l, t_end; - char *q_string, *t_string; unsigned int error; - z->w_list.n = 0; nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, w_l); - get_win_se_by_normalize_xs(z, (z->x_pos_s/w_l)*w_l, w_l, &q_s, &q_e); - // q_s = z->x_pos_s; get_win_id_by_s(z, q_s, w_l, &q_e); - for (k = 0; k < nw; k++) { - aux_beg = aux_end = 0; q_l = 1 + q_e - q_s; - thre = q_l*e_rate; thre = Adjust_Threshold(thre, q_l); - if(thre > THRESHOLD_MAX_SIZE) thre = THRESHOLD_MAX_SIZE; - ///offset of y - t_s = (q_s - z->x_pos_s) + z->y_pos_s; - t_s += y_start_offset(q_s, &(z->f_cigar)); - - aln_l = q_l + (thre<<1); - // if(z->y_id == 115) { - // fprintf(stderr, "+[M::] q_s::%ld, t_s::%ld, t_pri_l::%ld, aux_beg::%ld, aux_end::%ld, aln_l::%ld, t_end::%ld, error::%u\n", - // q_s, t_s, t_pri_l, aux_beg, aux_end, aln_l, t_end, error); - // } - if(init_waln(thre, t_s, uref->ug->u.a[z->y_id].len, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) { - gen_str_seq(tstr, t_s, t_pri_l, z->y_pos_strand, uref, z->y_id, aux_beg, aux_end); - q_string = qstr+q_s; t_string = tstr; - t_end = Reserve_Banded_BPM(t_string, aln_l, q_string, q_l, thre, &error); - // if(z->y_id == 115) { - // fprintf(stderr, "-[M::] q_s::%ld, t_s::%ld, t_pri_l::%ld, aux_beg::%ld, aux_end::%ld, aln_l::%ld, t_end::%ld, error::%u, thre::%ld\n", - // q_s, t_s, t_pri_l, aux_beg, aux_end, aln_l, t_end, error, thre); - // } - if (error!=((unsigned int)-1)) { - z->align_length += q_l; - ///t_s do not have aux_beg, while t_s + t_end (aka, te) has - append_window_list(z, q_s, q_e, t_s, t_s + t_end, error, aux_beg, aux_end, thre, w_l, km); - } - } - q_s = q_e + 1; q_e = q_s + w_l - 1; - if(q_e >= (int64_t)z->x_pos_e) q_e = z->x_pos_e; - } - - // if(q_e != (int64_t)z->x_pos_e) { - // fprintf(stderr, "[M::%s] q_e::%ld, z->x_pos_s::%u, z->x_pos_e::%u, w_l::%ld, nw::%ld\n", __func__, - // q_e, z->x_pos_s, z->x_pos_e, w_l, nw); - // } - assert(q_e == (int64_t)z->x_pos_e); -} - -///error_rate should be 30% -long long get_high_error(long long x_start, long long x_end, -long long y_start, long long y_end, long long y_id, long long y_strand, long long pre_threshold, -long long n_steps, float error_rate, All_reads* R_INF, Correct_dumy* dumy, -UC_Read* g_read) -{ - long long stepLen = (x_end - x_start + 1) / n_steps; - if((x_end - x_start + 1) % n_steps != 0) - { - stepLen++; - } - long long SubLen, SubWindowLen; - long long SubThreshold = THRESHOLD_MAX_SIZE; - int extra_begin, extra_end; - long long o_len; - long long T_error = 0; - y_start = y_start + pre_threshold; - - while (x_start <= x_end) - { - SubLen = x_end - x_start + 1; - if(SubLen > stepLen) - { - SubLen = stepLen; - } - - - SubThreshold = SubLen * error_rate; - if(SubThreshold > THRESHOLD_MAX_SIZE) - { - SubThreshold = THRESHOLD_MAX_SIZE; - } - - SubThreshold = Adjust_Threshold(SubThreshold, SubLen); - - - SubWindowLen = SubLen + (SubThreshold << 1); - if(determine_overlap_region(SubThreshold, y_start, y_id, SubWindowLen, Get_READ_LENGTH((*R_INF), y_id), - &extra_begin, &extra_end, &y_start, &o_len) == 0) - { - T_error = T_error + (x_end - x_start + 1) * error_rate * 1.5; - break; - } - - fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, R_INF, y_id, - extra_begin, extra_end); - - char* x_string = g_read->seq + x_start; - char* y_string = dumy->overlap_region; - int end_site; - unsigned int error; - - end_site = Reserve_Banded_BPM(y_string, SubWindowLen, x_string, SubLen, SubThreshold, &error); - - ///if error = -1, unmatched - if (error!=(unsigned int)-1) - { - T_error = T_error + error; - y_start = y_start + end_site - extra_begin + 1; - } - else - { - T_error = T_error + SubLen * error_rate * 1.5; - y_start = y_start + SubThreshold - extra_begin + SubLen; - } - - x_start = x_start + SubLen; - } - - - return T_error; -} - -inline int double_error_threshold(int pre_threshold, int x_len) -{ - - pre_threshold = Adjust_Threshold(pre_threshold, x_len); - int threshold = pre_threshold * 2; - ///may have some bugs - if(x_len >= 300 && threshold < THRESHOLD_MAX_SIZE) - { - threshold = THRESHOLD_MAX_SIZE; - } - - if(threshold > THRESHOLD_MAX_SIZE) - { - threshold = THRESHOLD_MAX_SIZE; - } - - return threshold; -} - -inline int double_ul_error_threshold(int pre_threshold, int x_len) -{ - - pre_threshold = Adjust_Threshold(pre_threshold, x_len); - int threshold = THRESHOLD_UL_MAX * x_len; - if(threshold < pre_threshold) threshold = pre_threshold; - if(threshold > THRESHOLD_MAX_SIZE) threshold = THRESHOLD_MAX_SIZE; - return threshold; -} - - -inline int verify_sub_window(All_reads* R_INF, Correct_dumy* dumy, UC_Read* g_read, -long long x_beg, long long xLen, long long y_beg, long long yLen, uint64_t y_id, -uint64_t y_pos_strand, int threshold, int alignment_strand, -unsigned int* get_error, int* get_y_end, int* get_x_end, int* get_aligned_xLen) -{ - (*get_aligned_xLen) = 0; - (*get_y_end) = -1; - (*get_x_end) = -1; - (*get_error) = (unsigned int)-1; - - int extra_begin, extra_end, r_x_end, r_y_end, aligned_xLen; - long long o_len; - unsigned int r_error; - if(!determine_overlap_region(threshold, y_beg, y_id, yLen, - Get_READ_LENGTH((*R_INF), y_id), &extra_begin, &extra_end, &y_beg, &o_len)) - { - return 0; - } - - fill_subregion(dumy->overlap_region, y_beg, o_len, y_pos_strand, R_INF, - y_id, extra_begin, extra_end); - - char* x_string = g_read->seq + x_beg; - char* y_string = dumy->overlap_region; - - aligned_xLen = 0; - - alignment_extension(y_string, yLen, x_string, xLen, threshold, - alignment_strand, &r_error, &r_y_end, &r_x_end, &aligned_xLen); - - (*get_error) = r_error; - (*get_y_end) = r_y_end; - (*get_x_end) = r_x_end; - (*get_aligned_xLen) = aligned_xLen; - - if(aligned_xLen == 0) - { - return 0; - } - else - { - return 1; - } -} - -inline int verify_ul_sub_window(const ul_idx_t *uref, Correct_dumy* dumy, UC_Read* g_read, -long long x_beg, long long xLen, long long y_beg, long long yLen, uint64_t y_id, -uint64_t y_pos_strand, int threshold, int alignment_strand, -unsigned int* get_error, int* get_y_end, int* get_x_end, int* get_aligned_xLen) -{ - (*get_aligned_xLen) = 0; - (*get_y_end) = -1; - (*get_x_end) = -1; - (*get_error) = (unsigned int)-1; - - int extra_begin, extra_end, r_x_end, r_y_end, aligned_xLen; - long long o_len; - unsigned int r_error; - if(!determine_overlap_region(threshold, y_beg, y_id, yLen, - uref->ug->u.a[y_id].len, &extra_begin, &extra_end, &y_beg, &o_len)) - { - return 0; - } - - fill_subregion_ul(dumy->overlap_region, y_beg, o_len, y_pos_strand, uref, - y_id, extra_begin, extra_end); - - // if(y_id == 6) { - // fprintf(stderr, "-[M::%s::aln_dir->%d] qs->%lld, ts->%lld, thres->%d, aux_beg->%d, aux_end->%d, t_pri_l->%lld\n", - // __func__, alignment_strand, x_beg, y_beg, threshold, extra_begin, extra_end, o_len); - // } - - char* x_string = g_read->seq + x_beg; - char* y_string = dumy->overlap_region; - - aligned_xLen = 0; - - alignment_extension(y_string, yLen, x_string, xLen, threshold, - alignment_strand, &r_error, &r_y_end, &r_x_end, &aligned_xLen); - - (*get_error) = r_error; - (*get_y_end) = r_y_end; - (*get_x_end) = r_x_end; - (*get_aligned_xLen) = aligned_xLen; - - if(aligned_xLen == 0) - { - return 0; - } - else - { - return 1; - } -} - -inline int64_t get_init_err_thres(int64_t len, double e_rate, int64_t block_s, int64_t block_err) -{ - if(len >= block_s) return block_err; - int64_t thres = len * e_rate; - thres = Adjust_Threshold(thres, len); - if(thres > THRESHOLD_MAX_SIZE) thres = THRESHOLD_MAX_SIZE; - return thres; -} - - -uint32_t get_init_paras(All_reads* rref, const ul_idx_t *uref, overlap_region *z, int64_t x_s, int64_t x_e, double e_rate, int64_t block_s, - int64_t *r_ys, int64_t *r_ex_beg, int64_t *r_ex_end, int64_t *r_err_thre) -{ - int e, ex_beg, ex_end; long long y_s, o_len, Window_Len; - e = get_init_err_thres(x_e+1-x_s, e_rate, block_s, rref?THRESHOLD:THRESHOLD_MAX_SIZE); - y_s = (x_s-z->x_pos_s) + z->y_pos_s; y_s += y_start_offset(x_s, &(z->f_cigar)); - Window_Len = (x_e+1-x_s) + (e<<1); - - if(!determine_overlap_region(e, y_s, z->y_id, Window_Len, (rref?(Get_READ_LENGTH((*rref), z->y_id)):(uref->ug->u.a[z->y_id].len)), - &ex_beg, &ex_end, &y_s, &o_len)) { - return 0; - } - (*r_ys) = y_s; (*r_ex_beg) = ex_beg; (*r_ex_end) = ex_end; (*r_err_thre) = e; - return 1; -} - -int64_t check_coverage_gap(uint64_t *v_idx, uint64_t w_s, uint64_t w_e, int64_t block_s) -{ - int64_t wid = w_s/block_s, a_n = (uint32_t)(v_idx[wid]), k; - uint64_t *a = v_idx + (v_idx[wid]>>32); - for (k = 0; k < a_n; k++) { - if(((a[k]>>32) == w_s) && (((uint32_t)(a[k])) == w_e)) return 1; - } - return 0; -} - -inline double non_trim_error_rate(overlap_region *z, All_reads* rref, const ul_idx_t *uref, const kvec_t_u64_warp* v_idx, Correct_dumy* dumy, UC_Read* g_read, double e_rate, int64_t block_s) -{ - int64_t nw, aw = z->w_list.n, k, m, w_id, wn_id, w_s, w_e, idx_e, tErr = 0, tLen = 0, y_s, ex_beg, ex_end, err_thre, p_err_thre; - int64_t x_len, Window_Len, y_beg_left, y_beg_right; - unsigned int r_error_left, r_error_right; int32_t r_x_end_left, r_y_end_left, aligned_xLen_left, r_x_end_right, r_y_end_right, aligned_xLen_right; - nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); - assert(nw >= aw && aw > 0); - - for (k = aw-1, idx_e = nw; k >= 0; k--) { - w_id = get_win_id_by_e(z, z->w_list.a[k].x_end, block_s, &w_s); - assert(w_s == z->w_list.a[k].x_start && w_id < idx_e && k <= w_id); - tLen += z->w_list.a[k].x_end + 1 - z->w_list.a[k].x_start; - tErr += z->w_list.a[k].error;///matched window - // if(z->y_id == 1) { - // fprintf(stderr, "+[M::%s] ws->%d, we->%d, tot_l->%ld, tot_e->%ld\n", - // __func__, z->w_list.a[k].x_start, z->w_list.a[k].x_end, tLen, tErr); - // } - // if(k != w_id) z->w_list.a[w_id] = z->w_list.a[k]; - ///from mapped window w_list.a[k] to the following unmapped windows - for (m = w_id+1, w_e = z->w_list.a[k].x_end; m < idx_e; m++) { - w_s = w_e + 1; - wn_id = get_win_id_by_s(z, w_s, block_s, &w_e); - assert(wn_id == m); x_len = w_e + 1 - w_s; tLen += x_len; - ///check if there are some windows that cannot be algined by any overlaps/unitigs - ///if no, it is likely that the UL read itself has issues - if(uref && v_idx && z->is_match == 4) { - if(check_coverage_gap(v_idx->a.a, w_s, w_e, block_s)) { - tErr += THRESHOLD_MAX_SIZE; - // if(z->y_id == 1) { - // fprintf(stderr, "-[M::%s] ws->%ld, we->%ld, tot_l->%ld, tot_e->%ld\n", __func__, w_s, w_e, tLen, tErr); - // } - continue; - } - } - if(!get_init_paras(rref, uref, z, w_s, w_e, e_rate, block_s, &y_s, &ex_beg, &ex_end, &err_thre)) { - tErr += x_len; - // if(z->y_id == 1) { - // fprintf(stderr, "-[M::%s] ws->%ld, we->%ld, tot_l->%ld, tot_e->%ld\n", __func__, w_s, w_e, tLen, tErr); - // } - continue; - } - p_err_thre = err_thre; - - if(rref) { - err_thre = double_error_threshold(err_thre, x_len); - } else { - err_thre = double_ul_error_threshold(err_thre, x_len); - } - Window_Len = x_len + (err_thre << 1); - r_error_left = r_error_right = 0; - aligned_xLen_left = aligned_xLen_right = 0; - y_beg_left = y_beg_right = -1; - - if(m == w_id+1) { ///if the previous window is mapped - y_beg_left = z->w_list.a[k].y_end + 1;///incorrect - } - - if(m+1 == idx_e && k+1 < aw) { ///if the next window is mapped - y_beg_right = z->w_list.a[k+1].y_start-x_len;///incorrect - } - - if(y_beg_left == -1 && y_beg_right == -1) { - y_beg_left = y_s; - if(ex_beg >= 0) y_beg_left = y_beg_left + p_err_thre - ex_beg; - y_beg_right = y_beg_left; - } - - if(y_beg_left == -1 && y_beg_right != -1) y_beg_left = y_beg_right; - if(y_beg_right == -1 && y_beg_left != -1) y_beg_right = y_beg_left; - - if(y_beg_left != -1) {///note: this function will change tstr/qstr - if(rref) { - verify_sub_window(rref, dumy, g_read, w_s, x_len, y_beg_left, Window_Len, - z->y_id, z->y_pos_strand, err_thre, 0, &r_error_left, &r_y_end_left, &r_x_end_left, &aligned_xLen_left); - } else { - verify_ul_sub_window(uref, dumy, g_read, w_s, x_len, y_beg_left, Window_Len, - z->y_id, z->y_pos_strand, err_thre, 0, &r_error_left, &r_y_end_left, &r_x_end_left, &aligned_xLen_left); - } - } - - if(y_beg_right != -1) { - if(rref) { - verify_sub_window(rref, dumy, g_read, w_s, x_len, y_beg_right, Window_Len, z->y_id, z->y_pos_strand, - err_thre, 1, &r_error_right, &r_y_end_right, &r_x_end_right, &aligned_xLen_right); - } else { - verify_ul_sub_window(uref, dumy, g_read, w_s, x_len, y_beg_right, Window_Len, z->y_id, z->y_pos_strand, - err_thre, 1, &r_error_right, &r_y_end_right, &r_x_end_right, &aligned_xLen_right); - } - } - - ///aligned in both directions - if(aligned_xLen_left != 0 && aligned_xLen_right != 0) { - if(aligned_xLen_left + aligned_xLen_right <= x_len) { - tErr += r_error_left + r_error_right + (x_len - aligned_xLen_left - aligned_xLen_right); - } else { - float E_rate = (float)(x_len)/(float)(aligned_xLen_left + aligned_xLen_right); - tErr += (r_error_left + r_error_right)*E_rate; - } - }///not aligned in both directions - else if(aligned_xLen_left == 0 && aligned_xLen_right == 0) { - tErr += x_len; - }///only aligned in left - else if(aligned_xLen_left != 0) { - tErr += r_error_left + (x_len - aligned_xLen_left); - }///only aligned in right - else if(aligned_xLen_right != 0) { - tErr += r_error_right + (x_len - aligned_xLen_right); - } - // if(z->y_id == 1) { - // fprintf(stderr, "*[M::%s] qs->%ld, ts->%ld, tb[0]->%ld, tb[1]->%ld, di[0]->%u, di[1]->%u, al[0]->%d, al[1]->%d, err_thre->%ld\n", __func__, - // w_s, y_s, y_beg_left, y_beg_right, r_error_left, r_error_right, aligned_xLen_left, aligned_xLen_right, err_thre); - // } - // if(z->y_id == 1) { - // fprintf(stderr, "-[M::%s] ws->%ld, we->%ld, tot_l->%ld, tot_e->%ld\n", __func__, w_s, w_e, tLen, tErr); - // } - } - idx_e = w_id; - } - - if(idx_e > 0) { - for (m = 0, w_e = (int64_t)z->x_pos_s-1; m < idx_e; m++) { - w_s = w_e + 1; - wn_id = get_win_id_by_s(z, w_s, block_s, &w_e); - assert(wn_id == m); x_len = w_e + 1 - w_s; tLen += x_len; - ///check if there are some windows that cannot be algined by any overlaps/unitigs - ///if no, it is likely that the UL read itself has issues - if(uref && v_idx && z->is_match == 4) { - if(check_coverage_gap(v_idx->a.a, w_s, w_e, block_s)) { - tErr += THRESHOLD_MAX_SIZE; - // if(z->y_id == 1) { - // fprintf(stderr, "-[M::%s] ws->%ld, we->%ld, tot_l->%ld, tot_e->%ld\n", __func__, w_s, w_e, tLen, tErr); - // } - continue; - } - // else { - // if(z->y_id == 575) { - // fprintf(stderr, "---[M::%s::] z::y_id->%u, w_s->%ld, w_e->%ld\n", __func__, z->y_id, w_s, w_e); - // } - // } - } - if(!get_init_paras(rref, uref, z, w_s, w_e, e_rate, block_s, &y_s, &ex_beg, &ex_end, &err_thre)) { - tErr += x_len; - // if(z->y_id == 1) { - // fprintf(stderr, "-[M::%s] ws->%ld, we->%ld, tot_l->%ld, tot_e->%ld\n", __func__, w_s, w_e, tLen, tErr); - // } - continue; - } - p_err_thre = err_thre; - if(rref) { - err_thre = double_error_threshold(err_thre, x_len); - } else { - err_thre = double_ul_error_threshold(err_thre, x_len); - } - Window_Len = x_len + (err_thre << 1); - r_error_left = r_error_right = 0; - aligned_xLen_left = aligned_xLen_right = 0; - y_beg_left = y_beg_right = -1; - - ///impossible that the previous window is mapped - // if(m == w_id+1) { ///if the previous window is mapped - // y_beg_left = z->w_list.a[k].y_end + 1; - // } - - if(m+1 == idx_e && k+1 < aw) { ///if the next window is mapped - y_beg_right = z->w_list.a[k+1].y_start-x_len; - } - - if(y_beg_left == -1 && y_beg_right == -1) { - y_beg_left = y_s; - if(ex_beg >= 0) y_beg_left = y_beg_left + p_err_thre - ex_beg; - y_beg_right = y_beg_left; - } - - if(y_beg_left == -1 && y_beg_right != -1) y_beg_left = y_beg_right; - if(y_beg_right == -1 && y_beg_left != -1) y_beg_right = y_beg_left; - - if(y_beg_left != -1) { - if(rref) { - verify_sub_window(rref, dumy, g_read, w_s, x_len, y_beg_left, Window_Len, - z->y_id, z->y_pos_strand, err_thre, 0, &r_error_left, &r_y_end_left, &r_x_end_left, &aligned_xLen_left); - } else { - verify_ul_sub_window(uref, dumy, g_read, w_s, x_len, y_beg_left, Window_Len, - z->y_id, z->y_pos_strand, err_thre, 0, &r_error_left, &r_y_end_left, &r_x_end_left, &aligned_xLen_left); - } - } - - if(y_beg_right != -1) { - if(rref) { - verify_sub_window(rref, dumy, g_read, w_s, x_len, y_beg_right, Window_Len, z->y_id, z->y_pos_strand, - err_thre, 1, &r_error_right, &r_y_end_right, &r_x_end_right, &aligned_xLen_right); - } else { - verify_ul_sub_window(uref, dumy, g_read, w_s, x_len, y_beg_right, Window_Len, z->y_id, z->y_pos_strand, - err_thre, 1, &r_error_right, &r_y_end_right, &r_x_end_right, &aligned_xLen_right); - } - } - - ///aligned in both directions - if(aligned_xLen_left != 0 && aligned_xLen_right != 0) { - if(aligned_xLen_left + aligned_xLen_right <= x_len) { - tErr += r_error_left + r_error_right + (x_len - aligned_xLen_left - aligned_xLen_right); - } else { - float E_rate = (float)(x_len)/(float)(aligned_xLen_left + aligned_xLen_right); - tErr += (r_error_left + r_error_right)*E_rate; - } - }///not aligned in both directions - else if(aligned_xLen_left == 0 && aligned_xLen_right == 0) { - tErr += x_len; - }///only aligned in left - else if(aligned_xLen_left != 0) { - tErr += r_error_left + (x_len - aligned_xLen_left); - }///only aligned in right - else if(aligned_xLen_right != 0) { - tErr += r_error_right + (x_len - aligned_xLen_right); - } - // if(z->y_id == 1) { - // fprintf(stderr, "-[M::%s] ws->%ld, we->%ld, tot_l->%ld, tot_e->%ld\n", __func__, w_s, w_e, tLen, tErr); - // } - } - } - - assert(tLen == z->x_pos_e + 1 - z->x_pos_s); - return (double)(tErr)/(double)(tLen); -} - -void append_unmatched_wins(overlap_region *z, int64_t block_s) -{ - int64_t nw, aw = z->w_list.n, k, m, w_id, wn_id, w_s, w_e, idx_e; - nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); - assert(nw >= aw && aw > 0); - if(nw == aw) return;///done - kv_resize(window_list, z->w_list, (uint64_t)nw); z->w_list.n = nw; - for (k = aw-1, idx_e = nw; k >= 0; k--) { - w_id = get_win_id_by_e(z, z->w_list.a[k].x_end, block_s, &w_s); - assert(w_s == z->w_list.a[k].x_start && w_id < idx_e && k <= w_id); - if(k != w_id) z->w_list.a[w_id] = z->w_list.a[k]; - for (m = w_id+1, w_e = z->w_list.a[k].x_end; m < idx_e; m++) { - z->w_list.a[m].cidx = z->w_list.a[m].clen = 0; - z->w_list.a[m].y_start = z->w_list.a[m].y_end = -1; - z->w_list.a[m].error = z->w_list.a[m].error_threshold = -1; - z->w_list.a[m].extra_begin = z->w_list.a[m].extra_end = 0; - z->w_list.a[m].x_start = w_e + 1; - wn_id = get_win_id_by_s(z, z->w_list.a[m].x_start, block_s, &w_e); - z->w_list.a[m].x_end = w_e; - assert(wn_id == m); - } - idx_e = w_id; - } - - if(idx_e > 0) { - for (m = 0, w_e = (int64_t)z->x_pos_s-1; m < idx_e; m++) { - z->w_list.a[m].cidx = z->w_list.a[m].clen = 0; - z->w_list.a[m].y_start = z->w_list.a[m].y_end = -1; - z->w_list.a[m].error = z->w_list.a[m].error_threshold = -1; - z->w_list.a[m].extra_begin = z->w_list.a[m].extra_end = 0; - z->w_list.a[m].x_start = w_e + 1; - wn_id = get_win_id_by_s(z, z->w_list.a[m].x_start, block_s, &w_e); - z->w_list.a[m].x_end = w_e; - assert(wn_id == m); - } - } -} - -/** -inline double non_trim_ul_error_rate(overlap_region_alloc* overlap_list, long long ID, -const ul_idx_t *uref, Correct_dumy* dumy, UC_Read* g_read) -{ - long long tLen, tError,i, subWinLen, subWinNum; - - tLen = 0; - tError = 0; - - subWinNum = overlap_list->list[ID].w_list_length; - - - for (i = 0; i < subWinNum; i++) - { - subWinLen = overlap_list->list[ID].w_list[i].x_end - overlap_list->list[ID].w_list[i].x_start + 1; - tLen += subWinLen; - - if(overlap_list->list[ID].w_list[i].y_end != -1) - { - tError += overlap_list->list[ID].w_list[i].error; - } - else - { - int x_len = subWinLen; - int threshold = double_ul_error_threshold(overlap_list->list[ID].w_list[i].error_threshold, x_len); - int Window_Len = x_len + (threshold << 1); - unsigned int r_error_left = 0; - int r_x_end_left, r_y_end_left, aligned_xLen_left; - unsigned int r_error_right = 0; - int r_x_end_right, r_y_end_right, aligned_xLen_right; - long long y_beg_left, y_beg_right; - - aligned_xLen_left = aligned_xLen_right = 0; - y_beg_left = y_beg_right = -1; - - if(overlap_list->list[ID].w_list[i].y_start == -1) - { - tError += x_len; - continue; - } - - ///if the previous window is mapped - if(i > 0 && overlap_list->list[ID].w_list[i - 1].y_end != -1) - { - y_beg_left = overlap_list->list[ID].w_list[i - 1].y_end + 1; - } - - ///if the next window is mapped - if(i < (long long)(overlap_list->list[ID].w_list_length - 1) && overlap_list->list[ID].w_list[i + 1].y_end != -1) - { - y_beg_right = 1 + overlap_list->list[ID].w_list[i + 1].y_start - 1 - x_len; - } - - - if(y_beg_left == -1 && y_beg_right == -1) - { - y_beg_left = overlap_list->list[ID].w_list[i].y_start; - if(overlap_list->list[ID].w_list[i].extra_begin >= 0) - { - y_beg_left = y_beg_left + overlap_list->list[ID].w_list[i].error_threshold - - overlap_list->list[ID].w_list[i].extra_begin; - } - y_beg_right = y_beg_left; - } - - if(y_beg_left == -1 && y_beg_right != -1) - { - y_beg_left = y_beg_right; - } - - if(y_beg_right == -1 && y_beg_left != -1) - { - y_beg_right = y_beg_left; - } - - - if(y_beg_left != -1) - { - verify_ul_sub_window(uref, dumy, g_read, overlap_list->list[ID].w_list[i].x_start, - x_len, y_beg_left, Window_Len, overlap_list->list[ID].y_id, overlap_list->list[ID].y_pos_strand, - threshold, 0, &r_error_left, &r_y_end_left, &r_x_end_left, &aligned_xLen_left); - } - - if(y_beg_right != -1) - { - verify_ul_sub_window(uref, dumy, g_read, overlap_list->list[ID].w_list[i].x_start, - x_len, y_beg_right, Window_Len, overlap_list->list[ID].y_id, overlap_list->list[ID].y_pos_strand, - threshold, 1, &r_error_right, &r_y_end_right, &r_x_end_right, &aligned_xLen_right); - } - - ///aligned in both direction - if(aligned_xLen_left != 0 && aligned_xLen_right != 0) - { - if(aligned_xLen_left + aligned_xLen_right <= x_len) - { - tError = tError + r_error_left + r_error_right + - (x_len - aligned_xLen_left - aligned_xLen_right); - } - else - { - float E_rate = (float)(x_len)/(float)(aligned_xLen_left + aligned_xLen_right); - tError = tError + (r_error_left + r_error_right)*E_rate; - } - }///not aligned in both direction - else if(aligned_xLen_left == 0 && aligned_xLen_right == 0) - { - tError += x_len; - }///only aligned in left - else if(aligned_xLen_left != 0) - { - tError = tError + r_error_left + (x_len - aligned_xLen_left); - }///only aligned in right - else if(aligned_xLen_right != 0) - { - tError = tError + r_error_right + (x_len - aligned_xLen_right); - } - } - } - - double error_rate = (double)(tError)/(double)(tLen); - - return error_rate; -} - -int calculate_hpm_errors(char* x, int x_len, char* y, int y_len, CIGAR* cigar, int error) -{ - int x_i, y_i, cigar_i; - x_i = 0; - y_i = 0; - cigar_i = 0; - int operation; - int operationLen; - int i; - int cigar_error = 0; - int hpm_error = 0; - - - while (cigar_i < cigar->length) - { - operation = cigar->C_C[cigar_i]; - operationLen = cigar->C_L[cigar_i]; - - if (operation == 0) - { - x_i = x_i + operationLen; - y_i = y_i + operationLen; - } - else if (operation == 1) - { - cigar_error += operationLen; - for (i = 0; i < operationLen; i++) - { - if(if_is_homopolymer_repeat(x_i, x, x_len) || if_is_homopolymer_repeat(y_i, y, y_len)) - { - hpm_error++; - } - - x_i++; - y_i++; - } - } - else if (operation == 2) - { - - if(if_is_homopolymer_repeat(x_i, x, x_len) || if_is_homopolymer_repeat(y_i, y, y_len)) - { - hpm_error++; - } - cigar_error += operationLen; - y_i += operationLen; - } - else if (operation == 3) - { - - if(if_is_homopolymer_repeat(x_i, x, x_len) || if_is_homopolymer_repeat(y_i, y, y_len)) - { - hpm_error++; - } - - cigar_error += operationLen; - x_i += operationLen; - } - - cigar_i++; - } - return hpm_error; -} - -int verify_cigar(char* x, int x_len, char* y, int y_len, CIGAR* cigar, int error) -{ - int x_i, y_i, cigar_i; - x_i = 0; - y_i = 0; - cigar_i = 0; - int operation; - int operationLen; - int i; - int cigar_error = 0; - int flag_error = 0; - - ///0 is match, 1 is mismatch, 2 is up, 3 is left - ///2 means there are more y, 3 means there are more x - while (cigar_i < cigar->length) - { - operation = cigar->C_C[cigar_i]; - operationLen = cigar->C_L[cigar_i]; - - if (operation == 0) - { - for (i = 0; i < operationLen; i++) - { - - if (x[x_i]!=y[y_i]) - { - ///fprintf(stderr, "error match\n"); - flag_error = 1; - } - x_i++; - y_i++; - } - } - else if (operation == 1) - { - cigar_error += operationLen; - for (i = 0; i < operationLen; i++) - { - - if (x[x_i]==y[y_i]) - { - ///fprintf(stderr, "error mismatch, cigar_i: %d, x_i: %d, y_i: %d\n",cigar_i, x_i, y_i); - flag_error = 1; - } - x_i++; - y_i++; - } - } - else if (operation == 2) - { - cigar_error += operationLen; - y_i += operationLen; - } - else if (operation == 3) - { - cigar_error += operationLen; - x_i += operationLen; - } - - cigar_i++; - } - - - if (cigar_error != error) - { - - // fprintf(stderr, "error cigar_error: cigar_error: %d, error: %d\n", cigar_error, error); - // for (i = 0; i < cigar->length; i++) - // { - // fprintf(stderr, "%u: %u\n", cigar->C_L[i], cigar->C_C[i]); - // } - - - flag_error = 1; - - } - - - if (flag_error == 1) - { - - // print_string(x, x_len); - // print_string(y, y_len); - // fprintf(stderr, "x_len: %d, y_len: %d, cigar_len: %d, error: %d\n", x_len, y_len, cigar->length, error); - // for (i = 0; i < cigar->length; i++) - // { - // fprintf(stderr, "%u: %u\n", cigar->C_L[i], cigar->C_C[i]); - // } - - - } - - - return flag_error; - -} -**/ - -int32_t scan_cigar(window_list *idx, window_list_alloc *cc, int64_t* get_error, int64_t scanXLen, int64_t direction) -{ - uint8_t c = (uint8_t)-1; uint32_t cl = (uint32_t)-1; - (*get_error) = -1; - if(idx->clen == 1) { - get_cigar_cell(idx, cc, 0, &c, &cl); - if(c == 0) { - (*get_error) = 0; - return 1; - } - } - int32_t x_i = 0, y_i = 0, c_i, c_n = idx->clen, c_err = 0; - uint32_t i; - - ///0 is match, 1 is mismatch, 2 is up, 3 is left - ///2: there are more bases at y, 3: there are more bases at x - if(direction == 0) { - for (c_i = 0; c_i < c_n; c_i++) { - get_cigar_cell(idx, cc, c_i, &c, &cl); - if (c == 0) { //match - x_i += cl; y_i += cl; - if(x_i >= scanXLen) { - (*get_error) = c_err; - return 1; - } - } - else if (c == 1) { - for (i = 0; i < cl; i++) { - x_i++; y_i++; c_err++; - if(x_i >= scanXLen) { - (*get_error) = c_err; - return 1; - } - } - } - else if (c == 2) {///y has more bases than x - c_err += cl; y_i += cl; - } - else if (c == 3) {///x has more bases than y - for (i = 0; i < cl; i++) { - x_i++; c_err++; - if(x_i >= scanXLen) { - (*get_error) = c_err; - return 1; - } - } - } - } - } else { - for (c_i = c_n-1; c_i >= 0; c_i--) { - get_cigar_cell(idx, cc, c_i, &c, &cl); - if (c == 0) { //match - x_i += cl; y_i += cl; - if(x_i >= scanXLen) { - (*get_error) = c_err; - return 1; - } - } else if (c == 1) { //mismatch - for (i = 0; i < cl; i++) { - x_i++; y_i++; c_err++; - if(x_i >= scanXLen) { - (*get_error) = c_err; - return 1; - } - } - } else if (c == 2) {///y has more bases than x - c_err += cl; y_i += cl; - } else if (c == 3) {///x has more bases than y - for (i = 0; i < cl; i++) { - x_i++; c_err++; - if(x_i >= scanXLen) { - (*get_error) = c_err; - return 1; - } - } - } - } - } - - (*get_error) = c_err; - return 0; -} - -///[scanXbeg, scanXend] -int scan_cigar_interval(window_list *idx, window_list_alloc *cc, int64_t* get_error, int64_t scanXbeg, int64_t scanXend) -{ - uint8_t c; uint32_t cl; - (*get_error) = -1; - if(idx->clen == 1) { - get_cigar_cell(idx, cc, 0, &c, &cl); - if(c == 0) { - (*get_error) = 0; - return 1; - } - } - - - - int32_t x_i = 0, y_i = 0, c_i, c_n = idx->clen, c_err = 0; - uint32_t i; - - - ///0 is match, 1 is mismatch, 2 is up, 3 is left - ///2: there are more bases at y, 3: there are more bases at x - for (c_i = 0; c_i < c_n; c_i++) { - get_cigar_cell(idx, cc, c_i, &c, &cl); - if (c == 0) {//match - for (i = 0; i < cl; i++) { - if(x_i == scanXbeg) c_err = 0; - x_i++; y_i++; - - if(x_i == scanXend + 1) { - (*get_error) = c_err; - return 1; - } - } - } else if (c == 1) {//mismatch - for (i = 0; i < cl; i++) { - if(x_i == scanXbeg) c_err = 0; - x_i++; y_i++; c_err++; - - if(x_i == scanXend + 1) { - (*get_error) = c_err; - return 1; - } - } - } else if (c == 2) {///y has more bases than x - c_err += cl; y_i += cl; - } - else if (c == 3) { - for (i = 0; i < cl; i++) { - if(x_i == scanXbeg) c_err = 0; - x_i++; c_err++; - - if(x_i == scanXend + 1) { - (*get_error) = c_err; - return 1; - } - } - } - } - - (*get_error) = c_err; - return 0; -} - -inline int move_gap_greedy(char* path, int path_i, int path_length, char* x, int x_i, char* y, int y_i, unsigned int* new_error) -{ - if(path[path_i] < 2) - { - return 0; - } - - /** - * - GGCG-TGTGCCTGT - * - GGCAATGTGCCTGT - * - 00013000000000 - **/ - - int flag = 0; - - char oper = path[path_i]; - - - if(oper == 3)///there are more x - { - path_i++; - y_i--; - for (; path_i < path_length && x_i >= 0 && y_i >= 0; path_i++, x_i--, y_i--) - { - if(path[path_i] == 2 || path[path_i] == 3 || (path[path_i] == 0 && x[x_i] != y[y_i])) - { - break; - } - else ///path[path_i] = 1 || path[path_i] = 0, exchange path[path_i] with path[path_i-1] - { - if(path[path_i] == 1 && x[x_i] == y[y_i]) - { - path[path_i - 1] = 0; - (*new_error)--; - } - else - { - path[path_i - 1] = path[path_i]; - } - - path[path_i] = oper; - - - flag = 1; - } - - } - } - else if(oper == 2)///there are more y - { - path_i++; - x_i--; - for (; path_i < path_length && x_i >= 0 && y_i >= 0; path_i++, x_i--, y_i--) - { - if(path[path_i] == 2 || path[path_i] == 3 || (path[path_i] == 0 && x[x_i] != y[y_i])) - { - break; - } - else - { - - if(path[path_i] == 1 && x[x_i] == y[y_i]) - { - path[path_i - 1] = 0; - (*new_error)--; - } - else - { - path[path_i - 1] = path[path_i]; - } - - - path[path_i] = oper; - flag = 1; - } - - } - } - - return flag; -} - -inline void generate_cigar(char* path, int path_length, window_list *idx, window_list_alloc *res, int* start, int* end, unsigned int* old_error, - char* x, int x_len, char* y) -{ - // uint8_t debug_c; uint32_t debug_c_len; - idx->cidx = res->c.n; - if ((*old_error) == 0) { - push_cigar_cell(res, 0, idx->x_end + 1 - idx->x_start); - idx->clen = res->c.n - idx->cidx; - // get_cigar_cell(idx, res, idx->clen-1, &debug_c, &debug_c_len); - // assert(debug_c==0 && debug_c_len==(idx->x_end + 1 - idx->x_start)); - return; - } - - ///0 is match, 1 is mismatch, 2 is up (more y), 3 is left (more x) - int32_t i = 0, pre_cl = 0, trem_p = -1; char pre_c = 5; - for (i = 0; i < path_length; i++) { - if(path[i] == 1) { - path[i] = 3;(*end)--; trem_p = i; - } else { - break; - } - } - - for (i = path_length - 1; i >= 0; i--) { - if(path[i] == 1) { - path[i] = 3; (*start)++; - } - else { - break; - } - } - - - // for (i = path_length - 1; i >= 0; i--) - // { - - // if (pre_ciga != path[i]) - // { - // if (pre_ciga_length != 0) - // { - // result->cigar.C_L[result->cigar.length] = pre_ciga_length; - // result->cigar.C_C[result->cigar.length] = pre_ciga; - // result->cigar.length++; - // } - - // pre_ciga = path[i]; - // pre_ciga_length = 1; - // } - // else - // { - // pre_ciga_length++; - // } - // } - - // if (pre_ciga_length != 0) - // { - // result->cigar.C_L[result->cigar.length] = pre_ciga_length; - // result->cigar.C_C[result->cigar.length] = pre_ciga; - // result->cigar.length++; - // } - - ///verify_cigar(x, x_len, y + (*start), (*end) - (*start) + 1, &(result->cigar), error); - - - y = y + (*start); - int32_t x_i = 0, y_i = 0; - ///terminate_site = -1 in default - for (i = path_length - 1; i > trem_p; i--) { - if(path[i] == 0) { - x_i++; y_i++; - } - else if(path[i] == 1) { - x_i++; y_i++; - } - else if(path[i] == 2) {///there are more y - move_gap_greedy(path, i, path_length, x, x_i, y, y_i, old_error); - y_i++; - } - else if(path[i] == 3) {///there are more x - move_gap_greedy(path, i, path_length, x, x_i, y, y_i, old_error); - x_i++; - } - } - - - - pre_c = 5; pre_cl = 0; - for (i = path_length - 1; i >= 0; i--) { - if (pre_c != path[i]) { - if (pre_cl != 0) { - push_cigar_cell(res, pre_c, pre_cl); - // get_cigar_cell(idx, res, res->c.n - idx->cidx - 1, &debug_c, &debug_c_len); - // assert(debug_c==pre_c && debug_c_len==pre_cl); - } - pre_c = path[i]; pre_cl = 1; - } - else { - pre_cl++; - } - } - - if (pre_cl != 0) { - push_cigar_cell(res, pre_c, pre_cl); - // get_cigar_cell(idx, res, res->c.n - idx->cidx -1, &debug_c, &debug_c_len); - // assert(debug_c==pre_c && debug_c_len==pre_cl); - } - - idx->clen = res->c.n - idx->cidx; - // if(verify_cigar(x, x_len, y, (*end) - (*start) + 1, &(result->cigar), *old_error)) - // { - // fprintf(stderr, "error\n"); - // } -} - -int verify_cigar_2(char* x, int x_len, char* y, int y_len, Cigar_record* cigar, int error) -{ - int x_i, y_i, cigar_i; - x_i = 0; - y_i = 0; - cigar_i = 0; - int operation; - int operationLen; - int i; - int cigar_error = 0; - int flag_error = 0; - int diff_i = 0; - - ///0 is match, 1 is mismatch, 2 is up, 3 is left - ///2 means there are more y, 3 means there are more x - while (cigar_i < (long long)cigar->length) - { - operation = Get_Cigar_Type(cigar->record[cigar_i]); - operationLen = Get_Cigar_Length(cigar->record[cigar_i]); - - if (operation == 0) - { - for (i = 0; i < operationLen; i++) - { - - if (x[x_i]!=y[y_i]) - { - ///fprintf(stderr, "error match\n"); - flag_error = 1; - } - x_i++; - y_i++; - } - } - else if (operation == 1) - { - cigar_error += operationLen; - for (i = 0; i < operationLen; i++) - { - - if (x[x_i]==y[y_i]) - { - ///fprintf(stderr, "error mismatch, cigar_i: %d, x_i: %d, y_i: %d\n",cigar_i, x_i, y_i); - flag_error = 1; - } - - if(Get_MisMatch_Base(cigar->lost_base[diff_i]) != y[y_i]) - { - // fprintf(stderr, "mismatch x: %c, y: %c, mis[%d]: %c\n", x[x_i],y[y_i],diff_i, - // Get_MisMatch_Base(cigar->lost_base[diff_i])); - } - - if(Get_Match_Base(cigar->lost_base[diff_i]) != x[x_i]) - { - // fprintf(stderr, "match x: %c, y: %c, deletion[%d]: %c\n", - // x[x_i],y[y_i],diff_i, - // Get_Match_Base(cigar->lost_base[diff_i])); - } - - - - - x_i++; - y_i++; - diff_i++; - } - } - else if (operation == 2) - { - cigar_error += operationLen; - for (i = 0; i < operationLen; i++) - { - if(cigar->lost_base[diff_i] != y[y_i]) - { - ///fprintf(stderr, "insertion x: %c, y: %c, insertion[%d]: %c\n", x[x_i],y[y_i],diff_i, - ///cigar->lost_base[diff_i]); - } - y_i++; - diff_i++; - } - } - else if (operation == 3) - { - cigar_error += operationLen; - - for (i = 0; i < operationLen; i++) - { - if(cigar->lost_base[diff_i] != x[x_i]) - { - ///fprintf(stderr, "deletion x: %c, y: %c, deletion[%d]: %c\n", x[x_i],y[y_i],diff_i, - ///cigar->lost_base[diff_i]); - } - x_i++; - diff_i++; - } - } - - cigar_i++; - } - - - ///return; - /** - if (cigar_error != error) - { - fprintf(stderr, "error cigar_error: cigar_error: %d, error: %d\n", cigar_error, error); - for (i = 0; i < cigar->length; i++) - { - operation = Get_Cigar_Type(cigar->record[i]); - operationLen = Get_Cigar_Length(cigar->record[i]); - fprintf(stderr, "%u: %u\n", operationLen, operation); - } - - } - **/ - - - if (flag_error == 1) - { - print_string(x, x_len); - print_string(y, y_len); - ///fprintf(stderr, "x_len: %d, y_len: %d, cigar_len: %d, error: %d\n", x_len, y_len, cigar->length, error); - for (i = 0; i < (long long)cigar->length; i++) - { - operation = Get_Cigar_Type(cigar->record[i]); - operationLen = Get_Cigar_Length(cigar->record[i]); - ///fprintf(stderr, "%u: %u\n", operationLen, operation); - } - } - - - return flag_error; - -} - -inline int fix_ul_boundary(char* x_string, long long x_len, int threshold, -long long total_y_start, long long local_y_start, long long local_y_end, -long long old_extra_begin, long long old_extra_end, -long long y_ID, long long Window_Len, const ul_idx_t *uref, -Correct_dumy* dumy, int y_strand, unsigned int old_error, -long long* r_total_y_start, int* r_start_site, int* r_end_site, -int* r_extra_begin, int* r_extra_end, unsigned int* r_error) -{ - - - int new_extra_begin, new_extra_end; - long long new_y_start, new_y_length; - int new_end_site, new_start_site; - unsigned int new_error; - char* y_string; - - - int path_length; - - ///if the start pos at the left boundary - if(local_y_start == 0) - { - total_y_start = total_y_start + local_y_start; - ///if local_y_start == 0 and old_extra_begin != 0 - ///this means total_y_start == 0, so shift to the left cannot get a new start pos - if(old_extra_begin != 0) - { - return 0; - } - - ///if the begining of alignment is 0, we should try to shift the window to find a better result - ///shift to the left by threshold-1 bases - if(!determine_overlap_region(threshold, total_y_start, y_ID, Window_Len, uref->ug->u.a[y_ID].len, - &new_extra_begin, &new_extra_end, &new_y_start, &new_y_length)) - { - return 0; - } - - ///if new_y_start is equal to total_y_start, recalculate makes no sense - if(new_y_start == total_y_start) - { - return 0; - } - - fill_subregion_ul(dumy->overlap_region_fix, new_y_start, new_y_length, y_strand, uref, y_ID, - new_extra_begin, new_extra_end); - - y_string = dumy->overlap_region_fix; - - new_end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &new_error, &new_start_site, - &path_length, dumy->matrix_bit, dumy->path_fix, -1, -1); - - if (new_error != (unsigned int)-1 && new_error < old_error) - { - (*r_total_y_start) = new_y_start; - (*r_start_site) = new_start_site; - (*r_end_site) = new_end_site; - (*r_extra_begin) = new_extra_begin; - (*r_extra_end) = new_extra_end; - (*r_error) = new_error; - - dumy->path_length = path_length; - memcpy(dumy->path, dumy->path_fix, path_length); - memcpy(dumy->overlap_region, dumy->overlap_region_fix, Window_Len); - return 1; - } - } - else if(local_y_end == Window_Len - 1) - { - ///if local_y_end == Window_Len - 1 and old_extra_end > 0 - ///this means local_y_end is the end of the y - ///so shit to the right makes no sense - if(old_extra_end != 0) - { - return 0; - } - long long total_y_end = total_y_start + local_y_end; - - total_y_start = total_y_end - x_len + 1; - - if(!determine_overlap_region(threshold, total_y_start, y_ID, Window_Len, uref->ug->u.a[y_ID].len, - &new_extra_begin, &new_extra_end, &new_y_start, &new_y_length)) - { - return 0; - } - - if(new_y_start == total_y_end - local_y_end) - { - return 0; - } - - fill_subregion_ul(dumy->overlap_region_fix, new_y_start, new_y_length, y_strand, uref, y_ID, - new_extra_begin, new_extra_end); - - y_string = dumy->overlap_region_fix; - - new_end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &new_error, &new_start_site, - &path_length, dumy->matrix_bit, dumy->path_fix, -1, -1); - - if (new_error != (unsigned int)-1 && new_error < old_error) - { - (*r_total_y_start) = new_y_start; - (*r_start_site) = new_start_site; - (*r_end_site) = new_end_site; - (*r_extra_begin) = new_extra_begin; - (*r_extra_end) = new_extra_end; - (*r_error) = new_error; - - dumy->path_length = path_length; - memcpy(dumy->path, dumy->path_fix, path_length); - memcpy(dumy->overlap_region, dumy->overlap_region_fix, Window_Len); - return 1; - } - - - } - return 0; -} - - -inline int fix_boundary(char* x_string, long long x_len, int threshold, -long long total_y_start, long long local_y_start, long long local_y_end, -long long old_extra_begin, long long old_extra_end, -long long y_ID, long long Window_Len, All_reads* R_INF, -Correct_dumy* dumy, int y_strand, unsigned int old_error, -long long* r_total_y_start, int* r_start_site, int* r_end_site, -int* r_extra_begin, int* r_extra_end, unsigned int* r_error) -{ - - - int new_extra_begin, new_extra_end; - long long new_y_start, new_y_length; - int new_end_site, new_start_site; - unsigned int new_error; - char* y_string; - - - int path_length; - - ///if the start pos at the left boundary - if(local_y_start == 0) - { - total_y_start = total_y_start + local_y_start; - ///if local_y_start == 0 and old_extra_begin != 0 - ///this means total_y_start == 0, so shift to the left cannot get a new start pos - if(old_extra_begin != 0) - { - return 0; - } - - ///if the begining of alignment is 0, we should try to shift the window to find a better result - ///shift to the left by threshold-1 bases - if(!determine_overlap_region(threshold, total_y_start, y_ID, Window_Len, Get_READ_LENGTH((*R_INF), y_ID), - &new_extra_begin, &new_extra_end, &new_y_start, &new_y_length)) - { - return 0; - } - - ///if new_y_start is equal to total_y_start, recalculate makes no sense - if(new_y_start == total_y_start) - { - return 0; - } - - fill_subregion(dumy->overlap_region_fix, new_y_start, new_y_length, y_strand, R_INF, y_ID, - new_extra_begin, new_extra_end); - - y_string = dumy->overlap_region_fix; - - new_end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &new_error, &new_start_site, - &path_length, dumy->matrix_bit, dumy->path_fix, -1, -1); - - if (new_error != (unsigned int)-1 && new_error < old_error) - { - (*r_total_y_start) = new_y_start; - (*r_start_site) = new_start_site; - (*r_end_site) = new_end_site; - (*r_extra_begin) = new_extra_begin; - (*r_extra_end) = new_extra_end; - (*r_error) = new_error; - - dumy->path_length = path_length; - memcpy(dumy->path, dumy->path_fix, path_length); - memcpy(dumy->overlap_region, dumy->overlap_region_fix, Window_Len); - return 1; - } - } - else if(local_y_end == Window_Len - 1) - { - ///if local_y_end == Window_Len - 1 and old_extra_end > 0 - ///this means local_y_end is the end of the y - ///so shit to the right makes no sense - if(old_extra_end != 0) - { - return 0; - } - long long total_y_end = total_y_start + local_y_end; - - total_y_start = total_y_end - x_len + 1; - - if(!determine_overlap_region(threshold, total_y_start, y_ID, Window_Len, Get_READ_LENGTH((*R_INF), y_ID), - &new_extra_begin, &new_extra_end, &new_y_start, &new_y_length)) - { - return 0; - } - - if(new_y_start == total_y_end - local_y_end) - { - return 0; - } - - fill_subregion(dumy->overlap_region_fix, new_y_start, new_y_length, y_strand, R_INF, y_ID, - new_extra_begin, new_extra_end); - - y_string = dumy->overlap_region_fix; - - new_end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &new_error, &new_start_site, - &path_length, dumy->matrix_bit, dumy->path_fix, -1, -1); - - if (new_error != (unsigned int)-1 && new_error < old_error) - { - (*r_total_y_start) = new_y_start; - (*r_start_site) = new_start_site; - (*r_end_site) = new_end_site; - (*r_extra_begin) = new_extra_begin; - (*r_extra_end) = new_extra_end; - (*r_error) = new_error; - - dumy->path_length = path_length; - memcpy(dumy->path, dumy->path_fix, path_length); - memcpy(dumy->overlap_region, dumy->overlap_region_fix, Window_Len); - return 1; - } - - - } - return 0; -} - -inline char *return_str_seq(char *buf, int64_t s, int64_t pri_l, uint8_t rev, hpc_t *hpc_g, const ul_idx_t *uref, int64_t id, int64_t aux_beg, int64_t aux_end) -{ - if(!hpc_g) { - memset(buf, 'N', aux_beg); - retrieve_u_seq(NULL, buf+aux_beg, &(uref->ug->u.a[id]), rev, s, pri_l, NULL); - memset(buf+aux_beg+pri_l, 'N', aux_end); - return buf; - } else { - char *z = hpc_str(*hpc_g, id, rev); - if((aux_beg == 0) && (aux_end == 0)) { - return z+s; - } else { - memset(buf, 'N', aux_beg); - memcpy(buf+aux_beg, z+s, pri_l); - memset(buf+aux_beg+pri_l, 'N', aux_end); - return buf; - } - } -} - -inline char *return_str_seq_exz(char *buf, int64_t s, int64_t pri_l, uint8_t rev, hpc_t *hpc_g, const ul_idx_t *uref, int64_t id) -{ - if(!hpc_g) { - retrieve_u_seq(NULL, buf, &(uref->ug->u.a[id]), rev, s, pri_l, NULL); - return buf; - } else { - return hpc_str(*hpc_g, id, rev) + s; - } -} - -///cannot use tstr in-place -inline int recal_boundary(char* qstr, char* tstr1, int64_t ql, int64_t thres, -int64_t global_ts0, int64_t local_ts0, int64_t local_te0, -int64_t aux_beg0, int64_t aux_end0, unsigned int err0, -int64_t tid, int64_t aln_l, uint32_t rev, -Correct_dumy* dumy, All_reads* rref, hpc_t *hpc_g, const ul_idx_t *uref, -int64_t* global_ts1, int* local_ts1, int* local_te1, -int64_t* aux_beg1, int64_t* aux_end1, unsigned int* err1) -{ - int64_t ts, t_tot_l, aux_beg, aux_end, t_pri_l, t_end; - char *q_string = qstr, *t_string; unsigned int error = (unsigned int)-1; - int r_ts = 0, path_length = 0; - if(hpc_g) t_tot_l = hpc_len(*hpc_g, tid); - else if(uref) t_tot_l = uref->ug->u.a[tid].len; - else t_tot_l = Get_READ_LENGTH((*rref), tid); - - if(local_ts0 == 0) {//left boundary - if(aux_beg0 > 0) return 0;///shift to the left cannot get a new start pos - ts = global_ts0; - } else if((local_te0 + 1) == aln_l) {//right boundary - if(aux_end0 > 0) return 0;///shift to the right cannot get a new start pos - ts = global_ts0 + local_te0 - ql + 1; - } else { - return 0; - } - if(!init_waln(thres, ts, t_tot_l, aln_l, &aux_beg, &aux_end, &ts, &t_pri_l)) return 0; - if(ts == global_ts0) return 0;//unchanged, make no sense - - if(rref) { - fill_subregion(tstr1, ts, t_pri_l, rev, rref, tid, aux_beg, aux_end); t_string = tstr1; - } else { - t_string = return_str_seq(tstr1, ts, t_pri_l, rev, hpc_g, uref, tid, aux_beg, aux_end); - } - - t_end = Reserve_Banded_BPM_PATH(t_string, aln_l, q_string, ql, thres, &error, &r_ts, - &path_length, dumy->matrix_bit, dumy->path_fix, -1, -1); - - if (error != (unsigned int)-1 && error < err0) { - (*global_ts1) = ts; - (*local_ts1) = r_ts; - (*local_te1) = t_end; - (*aux_beg1) = aux_beg; - (*aux_end1) = aux_end; - (*err1) = error; - - dumy->path_length = path_length; - memcpy(dumy->path, dumy->path_fix, path_length); - // memcpy(tstr0, t_string, aln_l); - return 1; - } - return 0; -} - -///cannot use tstr in-place -inline int recal_boundary_exz(char* qstr, char* tstr, int64_t ql0, int64_t tl0, int64_t thres, -int64_t toff, int64_t ts0, int64_t te0, int64_t err0, -int64_t tid, uint32_t rev, bit_extz_t *exz, -All_reads* rref, hpc_t *hpc_g, const ul_idx_t *uref, -int64_t *ts_r, int64_t *aux_beg_r, int64_t *aux_end_r) -{ - int64_t ts, tl, t_tot_l, aux_beg, aux_end, t_pri_l, aln_l = ql0 + (thres << 1); - char *q_string = qstr, *t_string; - if(hpc_g) t_tot_l = hpc_len(*hpc_g, tid); - else if(uref) t_tot_l = uref->ug->u.a[tid].len; - else t_tot_l = Get_READ_LENGTH((*rref), tid); - - if(ts0 == 0) {//left boundary - ts = toff; - } else if((te0 + 1) == tl0) {//right boundary - ts = toff + te0 - ql0 + 1; - } else { - return 0; - } - if(!init_waln(thres, ts, t_tot_l, aln_l, &aux_beg, &aux_end, &ts, &t_pri_l)) return 0; - if(ts == toff && tl0 == t_pri_l) return 0;//unchanged, make no sense - - tl = t_pri_l; - if(rref) { - recover_UC_Read_sub_region(tstr, ts, tl, rev, rref, tid); t_string = tstr; - } else { - t_string = return_str_seq_exz(tstr, ts, tl, rev, hpc_g, uref, tid); - } - - clear_align(*exz); - ed_band_cal_semi_64_w_absent_diag_trace(t_string, tl, q_string, ql0, thres, aux_beg, exz); - - if(is_align(*exz) && exz->err < err0) { - (*aux_beg_r) = aux_beg; - (*aux_end_r) = aux_end; - (*ts_r) = ts; - return 1; - } - return 0; -} - -///cannot use tstr in-place -inline int recal_boundary_non_retrieve_exz(char* qstr, char* tstr, int64_t t_tot_l, -int64_t ql0, int64_t tl0, int64_t thres, -int64_t toff, int64_t ts0, int64_t te0, int64_t err0, -int64_t tid, uint32_t rev, bit_extz_t *exz, -int64_t *ts_r, int64_t *aux_beg_r, int64_t *aux_end_r) -{ - int64_t ts, tl, aux_beg, aux_end, t_pri_l, aln_l = ql0 + (thres << 1); - char *q_string = qstr, *t_string; - - if(ts0 == 0) {//left boundary - ts = toff; - } else if((te0 + 1) == tl0) {//right boundary - ts = toff + te0 - ql0 + 1; - } else { - return 0; - } - if(!init_waln(thres, ts, t_tot_l, aln_l, &aux_beg, &aux_end, &ts, &t_pri_l)) return 0; - if(ts == toff && tl0 == t_pri_l) return 0;//unchanged, make no sense - - tl = t_pri_l; t_string = tstr + ts; - - clear_align(*exz); - ed_band_cal_semi_64_w_absent_diag_trace(t_string, tl, q_string, ql0, thres, aux_beg, exz); - - if(is_align(*exz) && exz->err < err0) { - (*aux_beg_r) = aux_beg; - (*aux_end_r) = aux_end; - (*ts_r) = ts; - return 1; - } - return 0; -} - -inline char *update_des_str(char *des, int64_t s, int64_t pri_l, uint8_t rev, All_reads *rref, hpc_t *hpc_g, - const ul_idx_t *uref, int64_t id, int64_t aux_beg, int64_t aux_end, char *src) -{ - if(src) { - // memcpy(des, src, (pri_l+aux_beg+aux_end)); - // return des; - return src; - } else { - if(rref) { - fill_subregion(des, s, pri_l, rev, rref, id, aux_beg, aux_end); - return des; - } else { - return return_str_seq(des, s, pri_l, rev, hpc_g, uref, id, aux_beg, aux_end); - } - } -} - -/** -void debug_scan_cigar(overlap_region* sub_list) -{ - long long i; - int f_err, b_err, fLen, xLen; - for (i = 0; i < (long long)sub_list->w_list_length; i++) - { - if(sub_list->w_list[i].y_end == -1 || sub_list->w_list[i].cigar.length == -1) - { - continue; - } - xLen = sub_list->w_list[i].x_end - sub_list->w_list[i].x_start + 1; - - scan_cigar(&(sub_list->w_list[i].cigar), &b_err, - xLen, 1); - scan_cigar(&(sub_list->w_list[i].cigar), &f_err, - xLen, 0); - - if(b_err != sub_list->w_list[i].error || f_err != sub_list->w_list[i].error) - { - fprintf(stderr, "error\n"); - } - - scan_cigar(&(sub_list->w_list[i].cigar), &b_err, - WINDOW, 1); - scan_cigar(&(sub_list->w_list[i].cigar), &f_err, - WINDOW, 0); - - if(b_err != sub_list->w_list[i].error || f_err != sub_list->w_list[i].error) - { - fprintf(stderr, "error\n"); - } - - scan_cigar_interval(&(sub_list->w_list[i].cigar), &b_err, 0, xLen-1); - if(b_err != sub_list->w_list[i].error) - { - fprintf(stderr, "error\n"); - } - - fLen = xLen / 3; - scan_cigar(&(sub_list->w_list[i].cigar), &f_err, fLen, 0); - scan_cigar_interval(&(sub_list->w_list[i].cigar), &b_err, 0, fLen-1); - if(f_err != b_err) - { - fprintf(stderr, "error\n"); - } - - fLen = xLen / 3; - scan_cigar(&(sub_list->w_list[i].cigar), &f_err, fLen, 1); - scan_cigar_interval(&(sub_list->w_list[i].cigar), &b_err, xLen-fLen, xLen-1); - if(f_err != b_err) - { - fprintf(stderr, "\nerror\n"); - fprintf(stderr, "b_err: %d, f_err: %d\n",b_err, f_err); - long long j; - for (j = 0; j < sub_list->w_list[i].cigar.length; j++) - { - fprintf(stderr, "len: %d, opera: %d\n", - sub_list->w_list[i].cigar.C_L[j], sub_list->w_list[i].cigar.C_C[j]); - } - } - - // bLen = xLen / 3; - // fLen = xLen - bLen; - - // scan_cigar(&(sub_list->w_list[i].cigar), &b_err, - // bLen, 1); - // scan_cigar(&(sub_list->w_list[i].cigar), &f_err, - // fLen, 0); - - // if(b_err + f_err != sub_list->w_list[i].error) - // { - // fprintf(stderr, "\nsub_list->w_list[i].error: %d, bLen: %d, b_err: %d, fLen: %d, f_err: %d\n", - // sub_list->w_list[i].error, bLen, b_err, fLen, f_err); - // long long j; - // for (j = 0; j < sub_list->w_list[i].cigar.length; j++) - // { - // fprintf(stderr, "len: %d, opera: %d\n", - // sub_list->w_list[i].cigar.C_L[j], sub_list->w_list[i].cigar.C_C[j]); - // } - - // } - } -} -**/ - -void calculate_boundary_cigars(overlap_region* z, All_reads* R_INF, Correct_dumy* dumy, UC_Read* g_read, double e_rate) -{ - assert(z->w_list.n > 0); - int64_t nw = z->w_list.n; - resize_window_list_alloc(&(z->boundary_cigars), nw - 1); - int64_t y_id = z->y_id, y_strand = z->y_pos_strand; - int64_t y_readLen = Get_READ_LENGTH((*R_INF), y_id); - int64_t i, y_distance, f_err = -1, b_err = -1, m_error; - int64_t scanLen = 10, boundaryLen = 200; - int64_t single_sideLen = boundaryLen/2; - int64_t force_useless_side = single_sideLen/2; - int64_t L_useless_side, R_useless_side, alpha = 1; - long long y_start, x_start, x_end, yLen, xLen, leftLen, rightLen, threshold, o_len; - char *x_string = NULL, *y_string = NULL; - int end_site, real_y_start, extra_begin, extra_end; - unsigned int error; - z->boundary_cigars.n = nw - 1; - ///the (i)-th boundary between the (i)-th window and the (i+1)-th window - ///that means it includes (the tail of (i)-th window) and (the header of (i+1)-th window) - ///note the (i)-th boundary is calculated at the (i)-th window - for (i = 0; i + 1 < nw; i++) { - ///if both of the two windows are not aligned - ///it is not necessary to calculate the boundary - if(z->w_list.a[i].y_end == -1 || z->w_list.a[i+1].y_end == -1) { - z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; - continue; - } - ///y_distance can be less than 0, or larger than 0 - y_distance = (int64_t)z->w_list.a[i+1].y_start - (int64_t)z->w_list.a[i].y_end - 1; - - ///if two windows are aligned - if(z->w_list.a[i].y_end != -1 && z->w_list.a[i+1].y_end != -1 && y_distance == 0) { - ///scan backward - scan_cigar(&(z->w_list.a[i]), &(z->w_list), &b_err, scanLen, 1); - ///scan forward - scan_cigar(&(z->w_list.a[i+1]), &(z->w_list), &f_err, scanLen, 0); - if(b_err == 0 && f_err == 0) { - z->boundary_cigars.a[i].error = -2; z->boundary_cigars.a[i].y_end = -1; - continue; - } - } - - - if(z->w_list.a[i].y_end != -1) { - y_start = z->w_list.a[i].y_end; x_start = z->w_list.a[i].x_end; - }///if the (i)-th window is not matched, have a look at the (i+1)-th window - else if(z->w_list.a[i+1].y_end != -1) { - y_start = z->w_list.a[i+1].y_start; x_start = z->w_list.a[i+1].x_start; - }///if both of these two windows are not matched, directly skip - else { - z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; - continue; - } - - ///it seems we don't need to record x_start and y_start - z->boundary_cigars.a[i].extra_begin = x_start; - z->boundary_cigars.a[i].extra_end = y_start; - - ///leftLen and rightLen are used for x - ///x should be at [sub_list->w_list[i].x_start, sub_list->w_list[i+1].x_end] - ///y shouldn't have limitation - ///note that the x_start and x_end should not be -1 in any case - ///up to now, x_start and y_start are not -1 - ///leftLen does not include x_start itself, rightLen does - ///gnerally speaking, rightLen should be always larger than leftLen - leftLen = MIN(MIN((x_start - (int64_t)z->w_list.a[i].x_start), y_start), single_sideLen); - rightLen = MIN(MIN(((int64_t)z->w_list.a[i+1].x_end + 1 - x_start), y_readLen - y_start), single_sideLen); - - ///xLen should be the sum length of two windows - xLen = leftLen + rightLen; - x_start = x_start - leftLen; - x_end = x_start + xLen - 1; - y_start = y_start - leftLen; - - ///if we don't have enough leftLen and rightLen - // if(leftLen <= useless_side || rightLen <= useless_side) - // { - // sub_list->boundary_cigars.buffer[i].error = -1; - // sub_list->boundary_cigars.buffer[i].y_end = -1; - // continue; - // } - - - threshold = xLen * e_rate/**asm_opt.max_ov_diff_ec**/; - threshold = Adjust_Threshold(threshold, xLen); - threshold = double_error_threshold(threshold, xLen); - - yLen = xLen + (threshold << 1); - if(!determine_overlap_region(threshold, y_start, y_id, yLen, Get_READ_LENGTH((*R_INF), y_id), - &extra_begin, &extra_end, &y_start, &o_len)) { - z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; - continue; - } - - if(o_len < xLen) { - z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; - continue; - } - - fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, R_INF, y_id, extra_begin, extra_end); - - x_string = g_read->seq + x_start; - y_string = dumy->overlap_region; - - end_site = Reserve_Banded_BPM_PATH(y_string, yLen, x_string, xLen, threshold, &error, - &real_y_start, &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); - - ///means this window is matched - if (error!=(unsigned int)-1) { - z->boundary_cigars.a[i].x_start = x_start; - z->boundary_cigars.a[i].x_end = x_end; - - generate_cigar(dumy->path, dumy->path_length, &(z->boundary_cigars.a[i]), &(z->boundary_cigars), - &real_y_start, &end_site, &error, x_string, xLen, y_string); - ///should not adjust cigar here, adjust cigar may cause problem - ///that is not what we want - - ///y_distance can be less than 0, or larger than 0 - ///please if one of the two windows is not matched, - ///y_distance may have potential problems - if(y_distance < 0) y_distance = y_distance * (-1); - ///leftLen, rightLen - // if(leftLen <= useless_side || rightLen <= useless_side) - // { - // sub_list->boundary_cigars.buffer[i].error = -1; - // sub_list->boundary_cigars.buffer[i].y_end = -1; - // continue; - // } - L_useless_side = R_useless_side = force_useless_side; - - ///first window - if((i == 0) && (x_start == (int64_t)z->w_list.a[0].x_start)) { - L_useless_side = 0; - } - ///last window - if((i == (int64_t)(z->w_list.n) - 2) && - (x_end == (long long)(z->w_list.a[(int64_t)(z->w_list.n)-1].x_end))) { - R_useless_side = 0; - } - - if(leftLen <= L_useless_side || rightLen <= R_useless_side) { - z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; - z->boundary_cigars.c.n = z->boundary_cigars.a[i].cidx; - continue; - } - - - - ///up to now, if we require (i)-th window and (i+1)-th window are matched - ///boundary_cigars.buffer[i].cigar, w_list[i].cigar and w_list[i+1].cigar are avaiable - ///get the error excluding the first and the last useless_side bases - scan_cigar_interval(&(z->boundary_cigars.a[i]), &(z->boundary_cigars), &m_error, L_useless_side, xLen-R_useless_side-1); - scan_cigar(&(z->w_list.a[i]), &(z->w_list), &b_err, leftLen-L_useless_side, 1); - scan_cigar(&(z->w_list.a[i+1]), &(z->w_list), &f_err, rightLen-R_useless_side, 0); - - if(f_err + b_err + y_distance + alpha < m_error) { - z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; - z->boundary_cigars.c.n = z->boundary_cigars.a[i].cidx; - continue; - } - - z->boundary_cigars.a[i].error = error; - z->boundary_cigars.a[i].y_start = y_start + real_y_start - extra_begin; - z->boundary_cigars.a[i].y_end = y_start + end_site - extra_begin; - - z->boundary_cigars.a[i].x_start = x_start; - z->boundary_cigars.a[i].x_end = x_end; - ///sub_list->boundary_cigars.buffer[i].error_threshold = useless_side; - z->boundary_cigars.a[i].extra_begin = L_useless_side; - z->boundary_cigars.a[i].extra_end = R_useless_side; - } - else { - z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; - continue; - } - } - -} - - -void calculate_ul_boundary_cigars(overlap_region* z, const ul_idx_t *uref, Correct_dumy* dumy, -UC_Read* g_read, double max_ov_diff_ec, long long blockLen) -{ - assert(z->w_list.n > 0); - int64_t nw = z->w_list.n; - resize_window_list_alloc(&(z->boundary_cigars), nw - 1); - int64_t y_id = z->y_id; - int64_t y_strand = z->y_pos_strand; - int64_t y_readLen = uref->ug->u.a[y_id].len; - int64_t i, y_distance; - int64_t f_err, b_err, m_error, scanLen = 10; - int64_t boundaryLen = WINDOW_UL_BOUND_RATE*blockLen; - boundaryLen >>= 2; boundaryLen <<= 2; - if(boundaryLen < WINDOW_UL_BOUND) boundaryLen = WINDOW_UL_BOUND; - int64_t single_sideLen = boundaryLen/2; - int64_t force_useless_side = single_sideLen/2; - int64_t L_useless_side, R_useless_side; - int64_t alpha = 1; - long long y_start, x_start, x_end, yLen, xLen, leftLen, rightLen, threshold, o_len; - int extra_begin, extra_end, end_site, real_y_start; - char* x_string; - char* y_string; - unsigned int error; - z->boundary_cigars.n = nw - 1; - ///the (i)-th boundary between the (i)-th window and the (i+1)-th window - ///that means it includes (the tail of (i)-th window) and (the header of (i+1)-th window) - ///note the (i)-th boundary is calculated at the (i)-th window - for (i = 0; i + 1 < nw; i++) { - ///if both of the two windows are not aligned - ///it is not necessary to calculate the boundary - ///if(sub_list->w_list[i].y_end == -1 && sub_list->w_list[i+1].y_end == -1) - if(z->w_list.a[i].y_end == -1 || z->w_list.a[i+1].y_end == -1) { - z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; - continue; - } - - ///note if w_list[i+1].y_start or sub_list->w_list[i].y_end is -1 - ///y_distance might have some problems at the last of this function - ///we need to deal with it carefully - y_distance = (int64_t)z->w_list.a[i+1].y_start - (int64_t)z->w_list.a[i].y_end - 1; - - ///if two windows are aligned - if(z->w_list.a[i].y_end != -1 && z->w_list.a[i+1].y_end != -1 && y_distance == 0) { - ///scan backward - scan_cigar(&(z->w_list.a[i]), &(z->w_list), &b_err, scanLen, 1); - ///scan forward - scan_cigar(&(z->w_list.a[i+1]), &(z->w_list), &f_err, scanLen, 0); - if(b_err == 0 && f_err == 0) { - z->boundary_cigars.a[i].error = -2; z->boundary_cigars.a[i].y_end = -1; - continue; - } - } - - - ///y_distance can be less than 0, or larger than 0 - if(z->w_list.a[i].y_end != -1) { - y_start = z->w_list.a[i].y_end; x_start = z->w_list.a[i].x_end; - }///if the (i)-th window is not matched, have a look at the (i+1)-th window - else if(z->w_list.a[i+1].y_end != -1) { - y_start = z->w_list.a[i+1].y_start; x_start = z->w_list.a[i+1].x_start; - }///if both of these two windows are not matched, directly skip - else { - z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; - continue; - } - - ///it seems we don't need to record x_start and y_start - z->boundary_cigars.a[i].extra_begin = x_start; - z->boundary_cigars.a[i].extra_end = y_start; - - ///leftLen and rightLen are used for x - ///x should be at [sub_list->w_list[i].x_start, sub_list->w_list[i+1].x_end] - ///y shouldn't have limitation - ///note that the x_start and x_end should not be -1 in any case - ///up to now, x_start and y_start are not -1 - ///leftLen does not include x_start itself, rightLen does - ///gnerally speaking, rightLen should be always larger than leftLen - leftLen = MIN(MIN((x_start - (long long)z->w_list.a[i].x_start), y_start), single_sideLen); - rightLen = MIN(MIN(((long long)z->w_list.a[i+1].x_end + 1 - x_start), y_readLen - y_start), single_sideLen); - - ///xLen should be the sum length of two windows - xLen = leftLen + rightLen; - x_start = x_start - leftLen; - x_end = x_start + xLen - 1; - y_start = y_start - leftLen; - - ///if we don't have enough leftLen and rightLen - // if(leftLen <= useless_side || rightLen <= useless_side) - // { - // sub_list->boundary_cigars.buffer[i].error = -1; - // sub_list->boundary_cigars.buffer[i].y_end = -1; - // continue; - // } - - - threshold = xLen * max_ov_diff_ec; - threshold = Adjust_Threshold(threshold, xLen); - threshold = double_ul_error_threshold(threshold, xLen); - - yLen = xLen + (threshold << 1); - if(!determine_overlap_region(threshold, y_start, y_id, yLen, uref->ug->u.a[y_id].len, - &extra_begin, &extra_end, &y_start, &o_len)) { - z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; - continue; - } - - if(o_len < xLen) { - z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; - continue; - } - - fill_subregion_ul(dumy->overlap_region, y_start, o_len, y_strand, - uref, y_id, extra_begin, extra_end); - - x_string = g_read->seq + x_start; - y_string = dumy->overlap_region; - - end_site = Reserve_Banded_BPM_PATH(y_string, yLen, x_string, xLen, threshold, &error, - &real_y_start, &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); - - ///means this window is matched - if (error!=(unsigned int)-1) { - z->boundary_cigars.a[i].x_start = x_start; z->boundary_cigars.a[i].x_end = x_end; - - generate_cigar(dumy->path, dumy->path_length, &(z->boundary_cigars.a[i]), &(z->boundary_cigars), - &real_y_start, &end_site, &error, x_string, xLen, y_string); - ///should not adjust cigar here, adjust cigar may cause problem - ///that is not what we want - - ///y_distance can be less than 0, or larger than 0 - ///please if one of the two windows is not matched, - ///y_distance may have potential problems - if(y_distance < 0) y_distance = y_distance * (-1); - ///leftLen, rightLen - // if(leftLen <= useless_side || rightLen <= useless_side) - // { - // sub_list->boundary_cigars.buffer[i].error = -1; - // sub_list->boundary_cigars.buffer[i].y_end = -1; - // continue; - // } - L_useless_side = R_useless_side = force_useless_side; - - ///first window - if((i == 0) && (x_start == (long long)z->w_list.a[0].x_start)) { - L_useless_side = 0; - } - ///last window - if((i == (int64_t)(z->w_list.n) - 2) && (x_end == (z->w_list.a[(int64_t)z->w_list.n - 1].x_end))) { - R_useless_side = 0; - } - - if(leftLen <= L_useless_side || rightLen <= R_useless_side) { - z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; - z->boundary_cigars.c.n = z->boundary_cigars.a[i].cidx; - continue; - } - - - - ///up to now, if we require (i)-th window and (i+1)-th window are matched - ///boundary_cigars.buffer[i].cigar, w_list[i].cigar and w_list[i+1].cigar are avaiable - ///get the error excluding the first and the last useless_side bases - scan_cigar_interval(&(z->boundary_cigars.a[i]), &(z->boundary_cigars), &m_error, - L_useless_side, xLen-R_useless_side-1); - scan_cigar(&(z->w_list.a[i]), &(z->w_list), &b_err, leftLen-L_useless_side, 1); - scan_cigar(&(z->w_list.a[i+1]), &(z->w_list), &f_err, rightLen-R_useless_side, 0); - - if(f_err + b_err + y_distance + alpha < m_error) { - z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; - z->boundary_cigars.c.n = z->boundary_cigars.a[i].cidx; - continue; - } - - z->boundary_cigars.a[i].error = error; - z->boundary_cigars.a[i].y_start = y_start + real_y_start - extra_begin; - z->boundary_cigars.a[i].y_end = y_start + end_site - extra_begin; - - z->boundary_cigars.a[i].x_start = x_start; - z->boundary_cigars.a[i].x_end = x_end; - ///sub_list->boundary_cigars.buffer[i].error_threshold = useless_side; - z->boundary_cigars.a[i].extra_begin = L_useless_side; - z->boundary_cigars.a[i].extra_end = R_useless_side; - } - else - { - z->boundary_cigars.a[i].error = -1; - z->boundary_cigars.a[i].y_end = -1; - continue; - } - - } - -} - - -/** -void debug_window_cigar(overlap_region_alloc* overlap_list, UC_Read* g_read, Correct_dumy* dumy, -All_reads* R_INF, int test_window, int test_boundary) -{ - uint64_t i, j, y_id, y_strand; - char* x_string; - char* y_string; - long long x_start; - long long x_end; - long long x_len; - long long y_start; - long long y_end; - long long y_len; - - for (j = 0; j < overlap_list->length; j++) - { - y_id = overlap_list->list[j].y_id; - y_strand = overlap_list->list[j].y_pos_strand; - if(overlap_list->list[j].is_match == 1) - { - - if(test_window == 1) - { - for (i = 0; i < overlap_list->list[j].w_list_length; i++) - { - if(overlap_list->list[j].w_list[i].y_end != -1) - { - ///there is no problem for x - x_start = overlap_list->list[j].w_list[i].x_start; - x_end = overlap_list->list[j].w_list[i].x_end; - x_len = x_end - x_start + 1; - - x_string = g_read->seq + x_start; - - y_start = overlap_list->list[j].w_list[i].y_start; - y_end = overlap_list->list[j].w_list[i].y_end; - y_len = y_end - y_start + 1; - - recover_UC_Read_sub_region(dumy->overlap_region, y_start, y_len, y_strand, R_INF, y_id); - y_string = dumy->overlap_region; - - - if(verify_cigar(x_string, x_len, y_string, y_len, &overlap_list->list[j].w_list[i].cigar, - overlap_list->list[j].w_list[i].error)) - { - fprintf(stderr, "error\n"); - } - } - } - } - - - - if(test_boundary == 1) - { - for (i = 0; i < (uint64_t)overlap_list->list[j].boundary_cigars.length; i++) - { - if(overlap_list->list[j].boundary_cigars.buffer[i].y_end != -1) - { - x_start = overlap_list->list[j].boundary_cigars.buffer[i].x_start; - x_end = overlap_list->list[j].boundary_cigars.buffer[i].x_end; - x_len = x_end - x_start + 1; - x_string = g_read->seq + x_start; - - y_start = overlap_list->list[j].boundary_cigars.buffer[i].y_start; - y_end = overlap_list->list[j].boundary_cigars.buffer[i].y_end; - y_len = y_end - y_start + 1; - - recover_UC_Read_sub_region(dumy->overlap_region, y_start, y_len, y_strand, - R_INF, y_id); - y_string = dumy->overlap_region; - - - if(verify_cigar(x_string, x_len, y_string, y_len, - &overlap_list->list[j].boundary_cigars.buffer[i].cigar, - overlap_list->list[j].boundary_cigars.buffer[i].error)) - { - fprintf(stderr, "error\n"); - } - } - } - } - - - if(test_window == 1 && test_boundary == 1) - { - if(overlap_list->list[j].w_list_length != - (uint64_t)(overlap_list->list[j].boundary_cigars.length + 1)) - { - fprintf(stderr, "error\n"); - } - } - - } - } -} -**/ -int64_t get_adjust_winid(overlap_region *z, int64_t win_beg, int64_t win_len) -{ - int64_t win_id, k; - win_id = (win_beg-((z->x_pos_s/win_len)*win_len))/win_len; - if((uint64_t)win_id < z->w_list.n && z->w_list.a[win_id].x_start == win_beg) return win_id; - if(z->w_list.n == 0) return -1; - // if(z->w_list.a[win_id].x_start <= win_beg) { - // fprintf(stderr, "z->w_list.n::%u, z->w_list.a[%ld].x_start::%d, win_beg::%ld\n", - // (uint32_t)z->w_list.n, win_id, z->w_list.a[win_id].x_start, win_beg); - // } - if((uint64_t)win_id > z->w_list.n) win_id = z->w_list.n; - // assert((z->w_list.a[win_id].x_start > win_beg); - for (k = win_id - 1; k >= 0; k--) { - // if(k < 0 || k >= (int64_t)z->w_list.n) fprintf(stderr, "win_id::%ld, k::%ld, z->w_list.n::%ld\n", win_id, k, (int64_t)z->w_list.n); - if(z->w_list.a[k].x_start == win_beg) return k; - if(z->w_list.a[k].x_start < win_beg) return -1; - } - return -1; -} - -void set_herror_win(overlap_region_alloc* ovlp, Correct_dumy* du, kvec_t_u64_warp* v_idx, double max_ov_diff_ec, int64_t rLen, int64_t blockLen) -{ - Window_Pool w_inf; int32_t flag = 0; uint64_t cID, mm, fc, fw, idx_n, idx_i; - init_Window_Pool(&w_inf, rLen, blockLen, (int)(1.0/max_ov_diff_ec)); - long long window_start, window_end; int64_t i, k, mLen, w_list_id, ws, we; - - idx_n = get_num_wins(0, rLen, blockLen); idx_i = 0; - kv_resize(uint64_t, v_idx->a, idx_n); v_idx->a.n = idx_n; - - while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) { - du->length = du->lengthNT = 0; - flag = get_interval(window_start, window_end, ovlp, du, w_inf.window_length); - switch (flag) { - case 1: ///no match here - break; - case 0: ///no match here - break; - case -2: ///if flag == -2, loop would be terminated - break; - } - - v_idx->a.a[idx_i++] = ((uint64_t)(v_idx->a.n))<<32; - for (i = 0; i < (int64_t)du->length; i++) { - cID = (uint32_t)du->overlapID[i]; - if(ovlp->list[cID].is_match!=3 && ovlp->list[cID].is_match!=4) continue; - w_list_id = get_adjust_winid(&(ovlp->list[cID]), window_start, w_inf.window_length); - if(w_list_id >= 0) break;///a matched window - } - if(i < (int64_t)du->length) continue;///if there is a matched window - - for (i = 0, mm = 0; i < (int64_t)du->length; i++) {///all windows are unmatched - cID = (uint32_t)du->overlapID[i]; - if(ovlp->list[cID].is_match!=3 && ovlp->list[cID].is_match!=4) continue; - ovlp->list[cID].is_match = 4; - ovlp->list[cID].align_length += window_end + 1 - window_start; - mm++; - } - if(mm > 0) { - kv_push(uint64_t, v_idx->a, (((uint64_t)window_start)<<32)|((uint64_t)window_end)); - v_idx->a.a[idx_i-1]++; - } - - - ///shorter than blockLen - for (i = du->size-du->lengthNT, mLen = du->size-du->lengthNT, fc = 0; i < (int64_t)du->size; i++) { - cID = (uint32_t)du->overlapID[i]; - if(ovlp->list[cID].is_match!=3 && ovlp->list[cID].is_match!=4) continue; - get_win_se_by_normalize_xs(&(ovlp->list[cID]), window_start, blockLen, &ws, &we); - w_list_id = get_adjust_winid(&(ovlp->list[cID]), ws, blockLen); - if (w_list_id >= 0) {///matched - cID = w_list_id; cID <<= 32; cID += (uint32_t)du->overlapID[i]; du->overlapID[i] = cID; - if(mLen != i) { - mm = du->overlapID[i]; du->overlapID[i] = du->overlapID[mLen]; du->overlapID[mLen] = mm; - } - mLen++; - } else {///unmatched - cID = (uint32_t)-1; cID <<= 32; cID += (uint32_t)du->overlapID[i]; du->overlapID[i] = cID; - fc++; - } - } - // if(mLen == (int64_t)du->size) continue;///if all windows shorter than blockLen are matched - if(fc == 0) continue;///no unmatched windows that are shorter than blockLen - for (i = mLen; i < (int64_t)du->size; i++){///check the remaining unmatched windows that are shorter than blockLen - cID = (uint32_t)du->overlapID[i]; - if(ovlp->list[cID].is_match!=3 && ovlp->list[cID].is_match!=4) continue; - assert((du->overlapID[i]>>32)==(uint32_t)-1); - get_win_se_by_normalize_xs(&(ovlp->list[cID]), window_start, blockLen, &ws, &we); - for (k = du->size-du->lengthNT; k < mLen; k++) {///all matched windows - fc = (uint32_t)du->overlapID[k]; fw = du->overlapID[k]>>32; - assert(fw!=(uint32_t)-1); assert(ovlp->list[fc].is_match == 3 || ovlp->list[fc].is_match == 4); - // if (ovlp->list[fc].w_list[fw].y_end == -1 || (ovlp->list[fc].is_match!=3 && ovlp->list[fc].is_match!=4)) fprintf(stderr, "ERROR\n"); - ///if there is one matched window can cover the unmatched window - if(ovlp->list[fc].w_list.a[fw].x_start<=ws && ovlp->list[fc].w_list.a[fw].x_end>=we) { - break; - } - } - - if(k >= mLen) {///no matched window can cover the unmatched window - ovlp->list[cID].is_match = 4; - ovlp->list[cID].align_length += we + 1 - ws; - kv_push(uint64_t, v_idx->a, (((uint64_t)ws)<<32)|((uint64_t)we)); - v_idx->a.a[idx_i-1]++; - } - } - } -} - - -inline void recalcate_window_advance(overlap_region_alloc* overlap_list, All_reads *rref, const ul_idx_t *uref, - UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, kvec_t_u64_warp* v_idx, int64_t block_s, double e_rate, double e_rate_final) -{ - long long j, k, i; - int threshold; - long long y_id; - int y_strand; - long long y_readLen; - long long x_start; - long long x_end; - long long x_len; - long long total_y_start; - long long total_y_end; - long long y_start; - long long Window_Len; - char* x_string; - char* y_string; - int end_site; - unsigned int error; - int real_y_start; - long long overlap_length; - int extra_begin, extra_end; - long long o_len; - int64_t nw, a_nw, w_id, w_s, w_e, is_srt; - double error_rate; - uint64_t *w_idx; - overlap_region *z; - window_list *p = NULL; - - - overlap_list->mapped_overlaps_length = 0; - for (j = 0; j < (long long)overlap_list->length; j++) { - z = &(overlap_list->list[j]); z->is_match = 0; is_srt = 1; - if(z->w_list.n == 0) continue;///no alignment - nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); a_nw = z->w_list.n; - kv_resize(uint64_t, v_idx->a, (uint64_t)nw); memset(v_idx->a.a, -1, sizeof((*v_idx->a.a))*nw); w_idx = v_idx->a.a; - for (i = 0; i < a_nw; i++) { - assert(z->w_list.a[i].y_end != -1); - w_id = get_win_id_by_s(z, z->w_list.a[i].x_start, block_s, NULL); - w_idx[w_id] = i; - } - // if(j == 248) { - // fprintf(stderr, "0-[M::%s] j::%lld, nw::%ld, a_nw::%ld, z->x_pos_s::%u, z->x_pos_e::%u, z->y_pos_s::%u, z->y_pos_e::%u, w_idx[0]::%lu\n", __func__, - // j, nw, a_nw, z->x_pos_s, z->x_pos_e, z->y_pos_s, z->y_pos_e, w_idx[0]); - // } - - y_id = z->y_id; y_strand = z->y_pos_strand; - y_readLen = (rref?(Get_READ_LENGTH((*rref), y_id)):(uref->ug->u.a[y_id].len)); - for (i = a_nw-1; i >= 0; i--) { //utilize the the end pos of pre-window in forward - w_id = get_win_id_by_s(z, z->w_list.a[i].x_start, block_s, &w_e); - // if(z->w_list.a[i].x_end != w_e) { - // fprintf(stderr, "[M::%s] block_s->%ld, w_id->%ld, z::x_pos_s->%u, z::x_pos_e->%u, x_start->%d, x_end->%d, w_e->%ld\n", __func__, block_s, w_id, z->x_pos_s, z->x_pos_e, - // z->w_list.a[i].x_start, z->w_list.a[i].x_end, w_e); - // } - assert(z->w_list.a[i].x_end == w_e); - total_y_start = z->w_list.a[i].y_end + 1 - z->w_list.a[i].extra_begin; - for (k = w_id + 1; k < nw; k++) { - if(w_idx[k] != (uint64_t)-1) break; - w_s = w_e + 1; - w_id = get_win_id_by_s(z, w_s, block_s, &w_e); - assert(w_id == k); - extra_begin = extra_end = 0; - if (total_y_start >= y_readLen) break; - ///there is no problem for x - x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; y_start = total_y_start; - ///there are two potiential reasons for unmatched window: - ///1. this window has a large number of differences - ///2. DP does not start from the right offset - if(rref) { - threshold = double_error_threshold(get_init_err_thres(x_len, e_rate, block_s, THRESHOLD), x_len); - } else { - threshold = double_ul_error_threshold(get_init_err_thres(x_len, e_rate, block_s, THRESHOLD_MAX_SIZE), x_len); - } - - Window_Len = x_len + (threshold << 1); - - if(!determine_overlap_region(threshold, y_start, y_id, Window_Len, (rref?(Get_READ_LENGTH((*rref), y_id)):(uref->ug->u.a[y_id].len)), - &extra_begin, &extra_end, &y_start, &o_len)) { - break; - } - if(o_len + threshold < x_len) break; - - if(rref) { - fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, rref, y_id, extra_begin, extra_end); - } else { - fill_subregion_ul(dumy->overlap_region, y_start, o_len, y_strand, uref, y_id, extra_begin, extra_end); - } - - x_string = g_read->seq + x_start; y_string = dumy->overlap_region; - ///note!!! need notification - end_site = Reserve_Banded_BPM(y_string, Window_Len, x_string, x_len, threshold, &error); - if (error!=(unsigned int)-1) {///unmatched - kv_pushp(window_list, z->w_list, &p); - p->x_start = x_start; - p->x_end = x_end; - p->y_start = y_start; - p->y_end = y_start + end_site; - p->error = error; - p->extra_begin = extra_begin; - p->extra_end = extra_end; - p->error_threshold = threshold; - p->cidx = p->clen = 0; - - z->align_length += x_len; w_idx[k] = z->w_list.n - 1; - - if(is_srt && z->w_list.n > 1 && p->x_start < z->w_list.a[z->w_list.n-2].x_start) is_srt = 0; - } - else { - break; - } - - total_y_start = y_start + end_site + 1 - extra_begin; - } - } - // if(j == 248) { - // fprintf(stderr, "1-[M::%s] j::%lld, nw::%ld, a_nw::%ld, z->x_pos_s::%u, z->x_pos_e::%u, z->y_pos_s::%u, z->y_pos_e::%u, w_idx[0]::%lu\n", __func__, - // j, nw, a_nw, z->x_pos_s, z->x_pos_e, z->y_pos_s, z->y_pos_e, w_idx[0]); - // } - for (i = 0; i < nw; i++) { //utilize the the start pos of next window in backward - ///find the first matched window, which should not be the first window - ///the pre-window of this matched window must be unmatched - if(i > 0 && w_idx[i] != (uint64_t)-1 && w_idx[i-1] == (uint64_t)-1) { - w_s = z->w_list.a[w_idx[i]].x_start; - ///check if the start pos of this matched window has been calculated - if(z->w_list.a[w_idx[i]].clen == 0) { - p = &(z->w_list.a[w_idx[i]]); - ///there is no problem for x - x_start = p->x_start; x_end = p->x_end; x_len = x_end + 1 - x_start; threshold = p->error_threshold; - /****************************may have bugs********************************/ - ///should not adjust threshold, since this window can be matched by the old threshold - ///threshold = Adjust_Threshold(threshold, x_len); - /****************************may have bugs********************************/ - Window_Len = x_len + (threshold << 1); - ///y_start is the real y_start - y_start = p->y_start; extra_begin = p->extra_begin; extra_end = p->extra_end; - o_len = Window_Len - extra_end - extra_begin; - if(rref) { - fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, rref, y_id, extra_begin, extra_end); - } else { - fill_subregion_ul(dumy->overlap_region, y_start, o_len, y_strand, uref, y_id, extra_begin, extra_end); - } - - x_string = g_read->seq + x_start; - y_string = dumy->overlap_region; - - end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, - &(dumy->path_length), dumy->matrix_bit, dumy->path, p->error, p->y_end - y_start); - assert(error != (unsigned int)-1); - - { - ///this condition is always wrong - ///in best case, real_y_start = threshold, end_site = Window_Len - threshold - 1 - if (end_site == Window_Len - 1 || real_y_start == 0) { - if(rref) { - if(fix_boundary(x_string, x_len, threshold, y_start, real_y_start, - end_site, extra_begin, extra_end, y_id, Window_Len, rref, dumy, - y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, - &extra_end, &error)) { - p->error = error; p->extra_begin = extra_begin; p->extra_end = extra_end; - } - } else { - if(fix_ul_boundary(x_string, x_len, threshold, y_start, real_y_start, - end_site, extra_begin, extra_end, y_id, Window_Len, uref, dumy, - y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, - &extra_end, &error)) { - p->error = error; p->extra_begin = extra_begin; p->extra_end = extra_end; - } - } - } - - generate_cigar(dumy->path, dumy->path_length, p, &(z->w_list), &real_y_start, &end_site, &error, x_string, x_len, y_string); - - ///note!!! need notification - real_y_start = y_start + real_y_start - extra_begin; - p->y_start = real_y_start; - ///I forget why don't reduce the extra_begin for y_end - ///it seems extra_begin will be reduced at the end of this function - p->y_end = y_start + end_site; - p->error = error; - } - } else { - real_y_start = p->y_start; - } - - ///the end pos for pre window is real_y_start - 1 - total_y_end = real_y_start - 1; - ///find the unmatched window on the left of current matched window - ///k starts from i - 1 - for (k = i - 1; k >= 0 && w_idx[k] == (uint64_t)-1; k--) { - w_e = w_s - 1; - w_id = get_win_id_by_e(z, w_e, block_s, &w_s); - assert(w_id == k); - ///there is no problem in x - x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; - ///there are two potiential reasons for unmatched window: - ///1. this window has a large number of differences - ///2. DP does not start from the right offset - if(rref) { - threshold = double_error_threshold(get_init_err_thres(x_len, e_rate, block_s, THRESHOLD), x_len); - } else { - threshold = double_ul_error_threshold(get_init_err_thres(x_len, e_rate, block_s, THRESHOLD_MAX_SIZE), x_len); - } - Window_Len = x_len + (threshold << 1); - if(total_y_end <= 0) break; - - ///y_start might be less than 0 - y_start = total_y_end - x_len + 1; - if(!determine_overlap_region(threshold, y_start, y_id, Window_Len, (rref?(Get_READ_LENGTH((*rref), y_id)):(uref->ug->u.a[y_id].len)), - &extra_begin, &extra_end, &y_start, &o_len)) { - break; - } - - if(o_len + threshold < x_len) break; - - if(rref) { - fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, rref, y_id, extra_begin, extra_end); - } else { - fill_subregion_ul(dumy->overlap_region, y_start, o_len, y_strand, uref, y_id, extra_begin, extra_end); - } - x_string = g_read->seq + x_start; - y_string = dumy->overlap_region; - - ///note!!! need notification - end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, - &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); - - if (error!=(unsigned int)-1) { - ///this condition is always wrong - ///in best case, real_y_start = threshold, end_site = Window_Len - threshold - 1 - if (end_site == Window_Len - 1 || real_y_start == 0) { - if(rref) { - fix_boundary(x_string, x_len, threshold, y_start, real_y_start, - end_site, extra_begin, extra_end, y_id, Window_Len, rref, dumy, - y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, - &extra_end, &error); - } else { - fix_ul_boundary(x_string, x_len, threshold, y_start, real_y_start, - end_site, extra_begin, extra_end, y_id, Window_Len, uref, dumy, - y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, - &extra_end, &error); - } - } - - kv_pushp(window_list, z->w_list, &p); - p->x_start = x_start; p->x_end = x_end;///must set x_start/x_end here - generate_cigar(dumy->path, dumy->path_length, p, &(z->w_list), &real_y_start, &end_site, &error, x_string, x_len, y_string); - - ///y_start has no shift, but y_end has shift - p->y_start = y_start + real_y_start - extra_begin; - p->y_end = y_start + end_site; - p->error = error; - p->extra_begin = extra_begin; - p->extra_end = extra_end; - p->error_threshold = threshold; - z->align_length += x_len; w_idx[k] = z->w_list.n - 1; - - if(is_srt && z->w_list.n > 1 && p->x_start < z->w_list.a[z->w_list.n-2].x_start) is_srt = 0; - } - else { - break; - } - - total_y_end = y_start + real_y_start - 1 - extra_begin; - } - } - } - - // if(j == 248) { - // fprintf(stderr, "2-[M::%s] j::%lld, nw::%ld, a_nw::%ld, z->x_pos_s::%u, z->x_pos_e::%u, z->y_pos_s::%u, z->y_pos_e::%u, w_idx[0]::%lu, w_idx[0]->cidx::%u, w_idx[0]->clen::%u, w_idx[0]->cigar[0]:%u\n", __func__, - // j, nw, a_nw, z->x_pos_s, z->x_pos_e, z->y_pos_s, z->y_pos_e, w_idx[0], z->w_list.a[w_idx[0]].cidx, z->w_list.a[w_idx[0]].clen, z->w_list.c.a[z->w_list.a[w_idx[0]].cidx]); - // } - - if(uref) { - z->is_match = 0; - if((((z->x_pos_e + 1 - z->x_pos_s)*MIN_UL_ALIN_RATE) <= z->align_length) && (z->align_length >= MIN_UL_ALIN_LEN)){ - z->is_match = 3; overlap_list->mapped_overlaps_length += z->align_length; - ///sort for set_herror_win - if(!is_srt) radix_sort_window_list_xs_srt(z->w_list.a, z->w_list.a + z->w_list.n); - } - } - } - - // fprintf(stderr, "+++[M::%s::idx->%d::y_id->%u] z::align_length->%u, e_threshold->%f\n", - // __func__, 27, overlap_list->list[27].y_id, overlap_list->list[27].align_length, e_rate); - - // fprintf(stderr, "+++[M::%s::idx->%d::y_id->%u] z::align_length->%u, e_threshold->%f\n", - // __func__, 45, overlap_list->list[45].y_id, overlap_list->list[45].align_length, e_rate); - - // fprintf(stderr, "+++[M::%s::idx->%d::y_id->%u] z::align_length->%u, e_threshold->%f\n", - // __func__, 277, overlap_list->list[277].y_id, overlap_list->list[277].align_length, e_rate); - - if(uref && overlap_list->mapped_overlaps_length > 0) { - set_herror_win(overlap_list, dumy, v_idx, e_rate, g_read->length, block_s); - } - - overlap_list->mapped_overlaps_length = 0; - for (j = 0; j < (long long)overlap_list->length; j++) { - z = &(overlap_list->list[j]); - y_id = z->y_id; y_strand = z->y_pos_strand; - y_readLen = (rref?(Get_READ_LENGTH((*rref), y_id)):(uref->ug->u.a[y_id].len)); - overlap_length = z->x_pos_e + 1 - z->x_pos_s; //z->is_match = 0; - // if(y_id == 0 || y_id == 1) { - // fprintf(stderr, "[M::%s::j->%lld] utg%.6dl(%c), align_length::%u, overlap_length::%lld\n", __func__, - // j, (int32_t)z->y_id + 1, "+-"[z->y_pos_strand], z->align_length, overlap_length); - // } - // if(y_id == 24128) { - // fprintf(stderr, "[M::%s::idx->%lld::] x::[%u, %u), y::[%u, %u), ovl->%lld, aln->%u\n", - // __func__, j, z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1, overlap_length, z->align_length); - // radix_sort_window_list_xs_srt(z->w_list.a, z->w_list.a + z->w_list.n); a_nw = z->w_list.n; - // int64_t ss, ee; - // for (i = 0, ss = ee = -2; i < a_nw; i++) { - // p = &(z->w_list.a[i]); - // if(p->x_start == ee) { - // ee = p->x_end + 1; - // } else { - // if(ee > 0) { - // fprintf(stderr, "[M::%s::] x::[%ld, %ld)\n", __func__, ss, ee); - // } - // ss = p->x_start; ee = p->x_end + 1; - // } - // } - // if(ee > 0) { - // fprintf(stderr, "[M::%s::] x::[%ld, %ld)\n", __func__, ss, ee); - // } - - // for (i = 0; i < a_nw; i++) { - // p = &(z->w_list.a[i]); if(p->y_end == -1) continue; - // fprintf(stderr, "[M::%s::] x::[%d, %d), y::[%d, %d), error::%d\n", __func__, p->x_start, p->x_end + 1, p->y_start, p->y_end + 1, p->error); - // } - // } - - ///debug_scan_cigar(&(overlap_list->list[j])); - ///only calculate cigar for high quality overlaps - if ((rref && (overlap_length*OVERLAP_THRESHOLD_HIFI_FILTER <= z->align_length)) || - (uref && (overlap_length*(1-e_rate) <= z->align_length))) { - a_nw = z->w_list.n; - // int64_t tt = 0; - for (i = 0, is_srt = 1; i < a_nw; i++) { - p = &(z->w_list.a[i]); - ///check if the cigar of this window has been got - if(p->clen == 0) { - ///there is no problem for x - x_start = p->x_start; x_end = p->x_end; x_len = x_end - x_start + 1; - /****************************may have bugs********************************/ - ///threshold = x_len * asm_opt.max_ov_diff_ec; - threshold = p->error_threshold; - /****************************may have bugs********************************/ - /****************************may have bugs********************************/ - ///should not adjust threshold, since this window can be matched by the old threshold - ///threshold = Adjust_Threshold(threshold, x_len); - /****************************may have bugs********************************/ - Window_Len = x_len + (threshold << 1); - - - ///y_start is the real y_start - ///for the window with cigar, y_start has already reduced extra_begin - y_start = p->y_start; extra_begin = p->extra_begin; extra_end = p->extra_end; - o_len = Window_Len - extra_end - extra_begin; - if(rref) { - fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, rref, y_id, extra_begin, extra_end); - } else { - fill_subregion_ul(dumy->overlap_region, y_start, o_len, y_strand, uref, y_id, extra_begin, extra_end); - } - x_string = g_read->seq + x_start; y_string = dumy->overlap_region; - - - ///note!!! need notification - end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, - &(dumy->path_length), dumy->matrix_bit, dumy->path, p->error, p->y_end - y_start); - // if(!(error != (unsigned int)-1)) { - // fprintf(stderr, "[M::%s::]\tqid::%u\tqlen::%lu\tq::[%d,\t%d)\ttid::%u\ttlen::%lu\tt::[%d,\t%d)\te_beg::%d\te_end::%d\terr::%d\n", __func__, - // overlap_list->list[j].x_id, Get_READ_LENGTH((*rref), overlap_list->list[j].x_id), - // p->x_start, p->x_end+1, - // overlap_list->list[j].y_id, Get_READ_LENGTH((*rref), overlap_list->list[j].y_id), - // p->y_start, p->y_end+1, - // p->extra_begin, p->extra_end, p->error); - // fprintf(stderr, "[M::%s::]\tqcal_len::%lld\ttcal_len::%lld\tthres::%d\n", __func__, - // x_len, Window_Len, threshold); - // fprintf(stderr, "qid::%u\nqname::%.*s\n\t%.*s\n", overlap_list->list[j].x_id, - // (int32_t)Get_NAME_LENGTH((*rref), overlap_list->list[j].x_id), - // Get_NAME((*rref), overlap_list->list[j].x_id), (int32_t)x_len, x_string); - - // fprintf(stderr, "tid::%u\ntname::%.*s\n\t%.*s\n", overlap_list->list[j].y_id, - // (int32_t)Get_NAME_LENGTH((*rref), overlap_list->list[j].y_id), - // Get_NAME((*rref), overlap_list->list[j].y_id), (int32_t)Window_Len, y_string); - - // } - assert(error != (unsigned int)-1); - - { - if (end_site == Window_Len - 1 || real_y_start == 0) { - if(rref) { - if(fix_boundary(x_string, x_len, threshold, y_start, real_y_start, end_site, - extra_begin, extra_end, y_id, Window_Len, rref, dumy, y_strand, error, - &y_start, &real_y_start, &end_site, &extra_begin, &extra_end, &error)) { - p->error = error; p->extra_begin = extra_begin; p->extra_end = extra_end; - } - } else { - if(fix_ul_boundary(x_string, x_len, threshold, y_start, real_y_start, - end_site, extra_begin, extra_end, y_id, Window_Len, uref, dumy, - y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, - &extra_end, &error)) { - p->error = error; p->extra_begin = extra_begin; p->extra_end = extra_end; - } - } - } - - generate_cigar(dumy->path, dumy->path_length, p, &(z->w_list), &real_y_start, &end_site, &error, x_string, x_len, y_string); - - ///note!!! need notification - real_y_start = y_start + real_y_start - extra_begin; - p->y_start = real_y_start; - p->y_end = y_start + end_site - extra_begin; - p->error = error; - } - - // if(y_id == 4) { - // fprintf(stderr, "+[M::idx->%lld::] y_start->%d, y_end->%d, error->%d\n", - // j, p->y_start, p->y_end, p->error); - // } - } - else { - p->y_end -= p->extra_begin; - // if(y_id == 4) { - // fprintf(stderr, "-[M::idx->%lld::] y_start->%d, y_end->%d, error->%d\n", - // j, p->y_start, p->y_end, p->error); - // } - } - // tt += p->error; - if(is_srt && i > 0 && p->x_start < z->w_list.a[i-1].x_start) is_srt = 0; - } - - if(!is_srt) radix_sort_window_list_xs_srt(z->w_list.a, z->w_list.a + z->w_list.n); - error_rate = non_trim_error_rate(z, rref, uref, v_idx, dumy, g_read, e_rate, block_s); - z->is_match = 0; - // if(y_id == 4) { - // fprintf(stderr, "[M::%s::idx->%lld::] z::x_pos_s->%u, z::x_pos_e->%u, ovl->%lld, aln->%u, error_rate->%f, e_rate_final->%f, tt->%ld\n", - // __func__, j, z->x_pos_s, z->x_pos_e, overlap_length, z->align_length, error_rate, e_rate_final, tt); - // } - - if (error_rate <= e_rate_final/**asm_opt.max_ov_diff_final**/) { - overlap_list->mapped_overlaps_length += overlap_length; - z->is_match = 1; append_unmatched_wins(z, block_s); - // if(j == 248) { - // fprintf(stderr, "3-[M::%s] j::%lld, nw::%ld, a_nw::%ld, z->x_pos_s::%u, z->x_pos_e::%u, z->y_pos_s::%u, z->y_pos_e::%u, w_idx[0]::%lu, w_idx[0]->cidx::%u, w_idx[0]->clen::%u, w_idx[0]->cigar[0]:%u\n", __func__, - // j, nw, a_nw, z->x_pos_s, z->x_pos_e, z->y_pos_s, z->y_pos_e, w_idx[0], z->w_list.a[w_idx[0]].cidx, z->w_list.a[w_idx[0]].clen, z->w_list.c.a[z->w_list.a[w_idx[0]].cidx]); - // } - if(rref) { - calculate_boundary_cigars(z, rref, dumy, g_read, e_rate); - } else { - calculate_ul_boundary_cigars(z, uref, dumy, g_read, e_rate, block_s); - } - // if(j == 248) { - // fprintf(stderr, "4-[M::%s] j::%lld, nw::%ld, a_nw::%ld, z->x_pos_s::%u, z->x_pos_e::%u, z->y_pos_s::%u, z->y_pos_e::%u, w_idx[0]::%lu, w_idx[0]->cidx::%u, w_idx[0]->clen::%u, w_idx[0]->cigar[0]:%u\n", __func__, - // j, nw, a_nw, z->x_pos_s, z->x_pos_e, z->y_pos_s, z->y_pos_e, w_idx[0], z->w_list.a[w_idx[0]].cidx, z->w_list.a[w_idx[0]].clen, z->w_list.c.a[z->w_list.a[w_idx[0]].cidx]); - // } - // if((int64_t)z->x_pos_s!=z->w_list.a[0].x_start || - // (int64_t)z->x_pos_e!=z->w_list.a[z->w_list.n-1].x_end) { - // fprintf(stderr, "[M::%s] z::x_pos_s->%u, z::x_pos_e->%u, (0)::x_start->%d, (wn-1)x_end->%d, z->w_list.n->%ld\n", __func__, - // z->x_pos_s, z->x_pos_e, z->w_list.a[0].x_start, z->w_list.a[z->w_list.n-1].x_end, (int64_t)z->w_list.n); - // } - - // assert(get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s)==(int64_t)z->w_list.n); - // assert((int64_t)z->x_pos_s==z->w_list.a[0].x_start && - // (int64_t)z->x_pos_e==z->w_list.a[z->w_list.n-1].x_end); - } else if (error_rate <= /**asm_opt.max_ov_diff_final**/e_rate_final * 1.5) { - z->is_match = 3; - } - // fprintf(stderr, "[M::%s::idx->%lld::is_match->%u] z::y_id->%u, z::x_pos_s->%u, z::x_pos_e->%u, error_rate->%f, e_threshold->%f\n", - // __func__, j, z->is_match, z->y_id, z->x_pos_s, z->x_pos_e, error_rate, e_rate); - } else {///it impossible to be matched - z->is_match = 0; - // fprintf(stderr, "[M::%s::idx->%ld::is_match->%u] z::x_pos_s->%u, z::x_pos_e->%u, error_rate->-1, e_threshold->%f\n", - // __func__, j, z->is_match, z->x_pos_s, z->x_pos_e, e_rate); - } - - - } - ///debug_window_cigar(overlap_list, g_read, dumy, rref, 1, 1); -} - -uint32_t inline simi_pass(int64_t ol, int64_t aln_ol, uint32_t second_ck, double o_rate, double *e_rate) -{ - if(aln_ol == 0 || ol == 0) return 0; - if((!second_ck) && (!e_rate)) { - // if((ol*OVERLAP_THRESHOLD_FILTER) <= aln_ol) return 1; - if((ol*o_rate) <= aln_ol) return 1; - } else if(e_rate) { - if((ol*((double)(((double)1.0)-(*e_rate)))) <= aln_ol) return 1; - } else if(second_ck) { - if(((ol*MIN_UL_ALIN_RATE) <= aln_ol) && (aln_ol >= MIN_UL_ALIN_LEN)) return 1; - } - - // if(rref) { - // if((ol*OVERLAP_THRESHOLD_FILTER) <= aln_ol) return 1; - // } else if(uref) { - // if(e_rate) { - // if((ol*((double)(((double)1.0)-(*e_rate)))) <= aln_ol) return 1; - // } else { - // if(((ol*MIN_UL_ALIN_RATE) <= aln_ol) && (aln_ol >= MIN_UL_ALIN_LEN)) return 1; - // } - // } - - return 0; -} - -inline uint32_t gen_backtrace(window_list *p, overlap_region *z, All_reads *rref, const ul_idx_t *uref, UC_Read* g_read, Correct_dumy* dumy, -int32_t y_strand, int32_t y_id) -{ - int64_t x_start, x_end, x_len, Window_Len, o_len; - int32_t threshold; long long y_start; - int real_y_start = 0, end_site, extra_begin, extra_end; - char *x_string, *y_string; unsigned int error; - ///there is no problem for x - x_start = p->x_start; x_end = p->x_end; x_len = x_end - x_start + 1; - threshold = p->error_threshold; Window_Len = x_len + (threshold << 1); - - - ///y_start is the real y_start - ///for the window with cigar, y_start has already reduced extra_begin - y_start = p->y_start; extra_begin = p->extra_begin; extra_end = p->extra_end; - o_len = Window_Len - extra_end - extra_begin; - if(rref) { - fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, rref, y_id, extra_begin, extra_end); - } else { - fill_subregion_ul(dumy->overlap_region, y_start, o_len, y_strand, uref, y_id, extra_begin, extra_end); - } - x_string = g_read->seq + x_start; y_string = dumy->overlap_region; - - - ///note!!! need notification - end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, - &(dumy->path_length), dumy->matrix_bit, dumy->path, p->error, p->y_end - y_start); - // assert(error != (unsigned int)-1); - if(error != (unsigned int)-1) { - ///this condition is always wrong - ///in best case, real_y_start = threshold, end_site = Window_Len - threshold - 1 - if (end_site == Window_Len - 1 || real_y_start == 0) { - if(rref) { - if(fix_boundary(x_string, x_len, threshold, y_start, real_y_start, end_site, - extra_begin, extra_end, y_id, Window_Len, rref, dumy, y_strand, error, - &y_start, &real_y_start, &end_site, &extra_begin, &extra_end, &error)) { - p->error = error; p->extra_begin = extra_begin; p->extra_end = extra_end; - } - } else { - if(fix_ul_boundary(x_string, x_len, threshold, y_start, real_y_start, - end_site, extra_begin, extra_end, y_id, Window_Len, uref, dumy, - y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, - &extra_end, &error)) { - p->error = error; p->extra_begin = extra_begin; p->extra_end = extra_end; - } - } - } - - generate_cigar(dumy->path, dumy->path_length, p, &(z->w_list), &real_y_start, &end_site, &error, x_string, x_len, y_string); - - ///note!!! need notification - real_y_start = y_start + real_y_start - extra_begin; - p->y_start = real_y_start; - p->y_end = y_start + end_site - extra_begin; - p->error = error; - return 1; - } - p->error = -1; - return 0; -} - -void gen_rev_str(char *in, char **out, uint32_t len) -{ - char *r; uint32_t k; MALLOC(r, len); (*out) = r; - for (k = 0; k < len; k++) r[k] = in[len-k-1]; -} - -inline uint32_t gen_backtrace_adv(window_list *p, overlap_region *z, All_reads *rref, hpc_t *hpc_g, const ul_idx_t *uref, -char *qstr, char *tstr, char *tstr1, Correct_dumy* dumy, uint32_t rev, uint32_t id) -{ - int64_t qs, qe, ql, aln_l, t_pri_l, thres, ts; - int r_ts = 0, t_end; int64_t aux_beg, aux_end; - char *q_string, *t_string; unsigned int error; - ///there is no problem for x - qs = p->x_start; qe = p->x_end; ql = qe + 1 - qs; - thres = p->error_threshold; aln_l = ql + (thres<<1); - - ///y_start is the real y_start - ///for the window with cigar, y_start has already reduced extra_begin - ts = p->y_start; aux_beg = p->extra_begin; aux_end = p->extra_end; - t_pri_l = aln_l - aux_beg - aux_end; - - q_string = qstr + qs; - if(rref) { - fill_subregion(tstr, ts, t_pri_l, rev, rref, id, aux_beg, aux_end); t_string = tstr; - } else { - t_string = return_str_seq(tstr, ts, t_pri_l, rev, hpc_g, uref, id, aux_beg, aux_end); - } - - t_end = Reserve_Banded_BPM_PATH(t_string, aln_l, q_string, ql, thres, &error, &r_ts, - &(dumy->path_length), dumy->matrix_bit, dumy->path, p->error, p->y_end - ts); - - // assert(error != (unsigned int)-1); - if(error != (unsigned int)-1) { - /** - bit_extz_t exz, exz64; init_bit_extz_t(&exz, thres); init_bit_extz_t(&exz64, thres); - // ed_band_cal_extension_64_0_w(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz64); - // ed_band_cal_extension_64_0_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz64); - // cigar_check(t_string+r_ts, q_string, &(exz64)); - // exz64.err = INT32_MAX; - // ed_band_cal_extension_64_0_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz64); - // cigar_check(t_string+r_ts, q_string, &(exz64)); - - // ed_band_cal_extension_infi_0_w(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, NULL, &exz); - // ed_band_cal_extension_infi_0_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, NULL, &exz); - // cigar_check(t_string+r_ts, q_string, &exz); - // exz.err = INT32_MAX; - // ed_band_cal_extension_infi_0_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, NULL, &exz); - // cigar_check(t_string+r_ts, q_string, &exz); - // assert(exz.err <= (int32_t)error && exz.err >= 0); - // assert(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); - - // ed_band_cal_extension_256_0_w(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz); - // ed_band_cal_extension_256_0_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz); - // cigar_check(t_string+r_ts, q_string, &exz); - // exz.err = INT32_MAX; - // ed_band_cal_extension_256_0_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz); - // cigar_check(t_string+r_ts, q_string, &exz); - // assert(exz.err <= (int32_t)error && exz.err >= 0); - // assert(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); - - // char *qr, *tr; - // gen_rev_str(q_string, &qr, ql); gen_rev_str(t_string+r_ts, &tr, t_end+1-r_ts); - - // ed_band_cal_extension_64_1_w(tr, t_end+1-r_ts, qr, ql, thres, &exz64); - // ed_band_cal_extension_64_1_w_trace(tr, t_end+1-r_ts, qr, ql, thres, &exz64); - // cigar_check(tr, qr, &exz64); - // exz64.err = INT32_MAX; - // ed_band_cal_extension_64_1_w_trace(tr, t_end+1-r_ts, qr, ql, thres, &exz64); - // cigar_check(tr, qr, &exz64); - // assert(exz.err == exz64.err && exz.ps == (exz64.pl-exz64.pe-1) && exz.pe == (exz64.pl-exz64.ps-1) && exz.ts == (exz64.tl-exz64.te-1) && exz.te == (exz64.tl-exz64.ts-1)); - - // ed_band_cal_extension_infi_1_w(tr, t_end+1-r_ts, qr, ql, thres, NULL, &exz); - // ed_band_cal_extension_infi_1_w_trace(tr, t_end+1-r_ts, qr, ql, thres, NULL, &exz); - // cigar_check(tr, qr, &exz); - // exz.err = INT32_MAX; - // ed_band_cal_extension_infi_1_w_trace(tr, t_end+1-r_ts, qr, ql, thres, NULL, &exz); - // cigar_check(tr, qr, &exz); - // assert(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); - - // ed_band_cal_extension_256_1_w(tr, t_end+1-r_ts, qr, ql, thres, &exz); - // ed_band_cal_extension_256_1_w_trace(tr, t_end+1-r_ts, qr, ql, thres, &exz); - // cigar_check(tr, qr, &exz); - // exz.err = INT32_MAX; - // ed_band_cal_extension_256_1_w_trace(tr, t_end+1-r_ts, qr, ql, thres, &exz); - // cigar_check(tr, qr, &exz); - // assert(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); - - // free(qr); free(tr); - - - // ed_band_cal_global_64_w(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz64); - // ed_band_cal_global_64_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz64); - // cigar_check(t_string+r_ts, q_string, &(exz64)); - // exz64.err = INT32_MAX; - // ed_band_cal_global_64_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz64); - // cigar_check(t_string+r_ts, q_string, &(exz64)); - - // ed_band_cal_global_infi_w(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, NULL, &exz); - // ed_band_cal_global_infi_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, NULL, &exz); - // cigar_check(t_string+r_ts, q_string, &exz); - // exz.err = INT32_MAX; - // ed_band_cal_global_infi_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, NULL, &exz); - // cigar_check(t_string+r_ts, q_string, &exz); - // assert(exz.err <= (int32_t)error && exz.err >= 0); - // assert(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); - - // ed_band_cal_global_256_w(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz); - // ed_band_cal_global_256_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz); - // cigar_check(t_string+r_ts, q_string, &exz); - // exz.err = INT32_MAX; - // ed_band_cal_global_256_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz); - // cigar_check(t_string+r_ts, q_string, &exz); - // assert(exz.err <= (int32_t)error && exz.err >= 0); - // assert(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); - - - // ed_band_cal_semi_64_w(t_string, aln_l, q_string, ql, thres, &exz64); - // ed_band_cal_semi_64_w_trace(t_string, aln_l, q_string, ql, thres, &exz64); - // cigar_check(t_string, q_string, &(exz64)); - // exz64.err = INT32_MAX; - // ed_band_cal_semi_64_w_trace(t_string, aln_l, q_string, ql, thres, &exz64); - // cigar_check(t_string, q_string, &(exz64)); - - // ed_band_cal_semi_infi_w(t_string, aln_l, q_string, ql, thres, NULL, &exz); - // ed_band_cal_semi_infi_w_trace(t_string, aln_l, q_string, ql, thres, NULL, &exz); - // cigar_check(t_string, q_string, &exz); - // exz.err = INT32_MAX; - // ed_band_cal_semi_infi_w_trace(t_string, aln_l, q_string, ql, thres, NULL, &exz); - // cigar_check(t_string, q_string, &exz); - // assert(exz.err <= (int32_t)error && exz.err >= 0); - // assert(exz.err == exz64.err && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); - - // ed_band_cal_semi_256_w(t_string, aln_l, q_string, ql, thres, &exz); - // ed_band_cal_semi_256_w_trace(t_string, aln_l, q_string, ql, thres, &exz); - // cigar_check(t_string, q_string, &exz); - // exz.err = INT32_MAX; - // ed_band_cal_semi_256_w_trace(t_string, aln_l, q_string, ql, thres, &exz); - // cigar_check(t_string, q_string, &exz); - // assert(exz.err <= (int32_t)error && exz.err >= 0); - // assert(exz.err == exz64.err && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); - - - - ed_band_cal_semi_64_w_absent_diag(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, - thres, aux_beg, &exz64); - // ed_band_cal_semi_64_w_absent_diag_trace(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, - // thres, aux_beg, &exz64); - // cigar_check(t_string+aux_beg, q_string, &(exz64)); - // exz64.err = INT32_MAX; - // ed_band_cal_semi_64_w_absent_diag_trace(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, - // thres, aux_beg, &exz64); - // cigar_check(t_string+aux_beg, q_string, &(exz64)); - - - - ed_band_cal_semi_infi_w_absent_diag(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, - thres, aux_beg, NULL, &exz); - ed_band_cal_semi_infi_w_absent_diag_trace(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, - thres, aux_beg, NULL, &exz); - cigar_check(t_string+aux_beg, q_string, &(exz)); - exz.err = INT32_MAX; - ed_band_cal_semi_infi_w_absent_diag_trace(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, - thres, aux_beg, NULL, &exz); - cigar_check(t_string+aux_beg, q_string, &(exz)); - assert(exz.err <= (int32_t)error && exz.err >= 0); - assert(exz.err == exz64.err && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); - exz64.err = exz.err; exz64.ps = exz.ps; exz64.pe = exz.pe; exz64.ts = exz.ts; exz64.te = exz.te; - - - ed_band_cal_semi_256_w_absent_diag(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, - thres, aux_beg, &exz); - ed_band_cal_semi_256_w_absent_diag_trace(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, - thres, aux_beg, &exz); - cigar_check(t_string+aux_beg, q_string, &(exz)); - exz.err = INT32_MAX; - ed_band_cal_semi_256_w_absent_diag_trace(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, - thres, aux_beg, &exz); - cigar_check(t_string+aux_beg, q_string, &(exz)); - assert(exz.err <= (int32_t)error && exz.err >= 0); - assert(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); - // if((!(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te)) || (exz.err != (int32_t)error)) { - // fprintf(stderr, "\n[M::%s::semi] error::%u, ql::%ld, thres::%ld, exz.err::%d, exz64.err::%d, exz.ps::%d, exz64.ps::%d, exz.pe::%d, exz64.pe::%d, exz.ts::%d, exz64.ts::%d, exz.te::%d, exz64.te::%d\n", __func__, - // error, ql, thres, exz.err, exz64.err, exz.ps, exz64.ps, exz.pe, exz64.pe, exz.ts, exz64.ts, exz.te, exz64.te); - // fprintf(stderr, "[tstr] %.*s\n", (int32_t)aln_l, t_string); - // fprintf(stderr, "[qstr] %.*s\n", (int32_t)ql, q_string); - // } - destroy_bit_extz_t(&exz); destroy_bit_extz_t(&exz64); - - // if(exz.err > (int32_t)error && ql == 1) { - // fprintf(stderr, "[M::%s::] error::%u, ed_extension::%d, ql::%ld, thres::%ld\n", - // __func__, error, exz.err, ql, thres); - // fprintf(stderr, "[tstr] %.*s\n", t_end+1-r_ts, t_string+r_ts); - // fprintf(stderr, "[qstr] %.*s\n", (int32_t)ql, q_string); - // } - - // assert(ed_band_cal_global(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres) == - // ed_band_cal_global_128bit(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres)); - **/ - - ///this condition is always wrong - ///in best case, r_ts = threshold, t_end = aln_l - thres - 1 - if (((t_end+1) == aln_l) || (r_ts == 0)) { - if(recal_boundary(q_string, tstr1, ql, thres, ts, r_ts, t_end, - aux_beg, aux_end, error, id, aln_l, rev, dumy, rref, hpc_g, uref, - &ts, &r_ts, &t_end, &aux_beg, &aux_end, &error)) { - p->error = error; p->extra_begin = aux_beg; p->extra_end = aux_end; - t_string = update_des_str(tstr, ts, aln_l-aux_beg-aux_end, rev, rref, hpc_g, uref, - id, aux_beg, aux_end, hpc_g?NULL:tstr1); - } - } - - generate_cigar(dumy->path, dumy->path_length, p, &(z->w_list), &r_ts, &t_end, &error, q_string, ql, t_string); - - p->y_start = ts + r_ts - aux_beg; - p->y_end = ts + t_end - aux_beg; - p->error = error; - return 1; - } - p->error = -1; - return 0; -} - -inline uint32_t aln_wlst_adv(overlap_region *z, All_reads *rref, hpc_t *hpc_g, -const ul_idx_t *uref, char *qstr, char *tstr, char *tstr1, Correct_dumy* dumy, -uint32_t rev, uint32_t id, int64_t qs, int64_t qe, int64_t t_s, int64_t block_s, -double e_rate, uint32_t is_cigar) -{ - int64_t ql, aln_l, t_tot_l; window_list *p = NULL; int r_ts = 0, t_end; - int64_t aux_beg, aux_end, t_pri_l; - int64_t thres; char *q_string, *t_string; unsigned int error; - ql = qe + 1 - qs; - ///there are two potiential reasons for unmatched window: - ///1. this window has a large number of differences - ///2. DP does not start from the right offset - if(rref) { - thres = double_error_threshold(get_init_err_thres(ql, e_rate, block_s, THRESHOLD), ql); - } else { - thres = double_ul_error_threshold(get_init_err_thres(ql, e_rate, block_s, THRESHOLD_MAX_SIZE), ql); - } - aln_l = ql + (thres << 1); - if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); - else if(uref) t_tot_l = uref->ug->u.a[id].len; - else t_tot_l = Get_READ_LENGTH((*rref), id); - - if(!init_waln(thres, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) return 0; - if(t_pri_l + thres < ql) return 0; - - q_string = qstr + qs; - if(rref) { - fill_subregion(tstr, t_s, t_pri_l, rev, rref, id, aux_beg, aux_end); t_string = tstr; - } else { - t_string = return_str_seq(tstr, t_s, t_pri_l, rev, hpc_g, uref, id, aux_beg, aux_end); - } - - if(is_cigar) { - ///note!!! need notification - t_end = Reserve_Banded_BPM_PATH(t_string, aln_l, q_string, ql, thres, &error, &r_ts, - &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); - } else { - ///note!!! need notification - t_end = Reserve_Banded_BPM(t_string, aln_l, q_string, ql, thres, &error); - } - if(error!=(unsigned int)-1) { - if(is_cigar) { - ///this condition is always wrong - ///in best case, r_ts = threshold, t_end = aln_l - thres - 1 - if (((t_end+1) == aln_l) || (r_ts == 0)) { - if(recal_boundary(q_string, tstr1, ql, thres, t_s, r_ts, t_end, - aux_beg, aux_end, error, id, aln_l, rev, dumy, rref, hpc_g, uref, - &t_s, &r_ts, &t_end, &aux_beg, &aux_end, &error)) { - t_string = update_des_str(tstr, t_s, aln_l-aux_beg-aux_end, rev, rref, hpc_g, uref, - id, aux_beg, aux_end, hpc_g?NULL:tstr1); - } - } - } - - kv_pushp(window_list, z->w_list, &p); - p->x_start = qs; p->x_end = qe; ///must set x_start/x_end here - if(is_cigar) { - generate_cigar(dumy->path, dumy->path_length, p, &(z->w_list), &r_ts, &t_end, &error, q_string, ql, t_string); - } else { - p->cidx = p->clen = 0; - } - p->y_start = t_s + r_ts;///difference - p->y_end = t_s + t_end; - p->error = error; - p->extra_begin = aux_beg; - p->extra_end = aux_end; - p->error_threshold = thres; - z->align_length += ql; - - return 1; - } - return 0; -} - -void push_wcigar(window_list *idx, window_list_alloc *res, bit_extz_t *exz) -{ - idx->cidx = res->c.n; idx->clen = exz->cigar.n; res->c.n += exz->cigar.n; - kv_resize(uint16_t, res->c, res->c.n); - memcpy(res->c.a+idx->cidx, exz->cigar.a, exz->cigar.n*sizeof(*(res->c.a))); -} - -inline uint32_t aln_wlst_adv_exz(overlap_region *z, All_reads *rref, hpc_t *hpc_g, -const ul_idx_t *uref, char *qstr, char *tstr, bit_extz_t *exz, uint32_t max_err, -uint32_t rev, uint32_t id, int64_t qs, int64_t qe, int64_t t_s, int64_t block_s, -double e_rate, uint32_t is_cigar) -{ - int64_t ql, tl, aln_l, t_tot_l; window_list *p = NULL; ///int r_ts = 0, t_end; - int64_t aux_beg, aux_end, t_pri_l; int64_t thres; char *q_string, *t_string; - ql = qe + 1 - qs; - ///there are two potiential reasons for unmatched window: - ///1. this window has a large number of differences - ///2. DP does not start from the right offset - if(rref) { - thres = double_error_threshold(get_init_err_thres(ql, e_rate, block_s, max_err), ql); - } else { - thres = double_ul_error_threshold(get_init_err_thres(ql, e_rate, block_s, max_err), ql); - } - aln_l = ql + (thres << 1); - if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); - else if(uref) t_tot_l = uref->ug->u.a[id].len; - else t_tot_l = Get_READ_LENGTH((*rref), id); - - if(!init_waln(thres, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) return 0; - if(t_pri_l + thres < ql) return 0; - - q_string = qstr + qs; - if(rref) { - recover_UC_Read_sub_region(tstr, t_s, t_pri_l, rev, rref, id); t_string = tstr; - } else { - t_string = return_str_seq_exz(tstr, t_s, t_pri_l, rev, hpc_g, uref, id); - } - tl = t_pri_l; - if(is_cigar) { - clear_align(*exz); - ed_band_cal_semi_64_w_absent_diag_trace(t_string, tl, q_string, ql, thres, aux_beg, exz); - } else { - ed_band_cal_semi_64_w_absent_diag(t_string, tl, q_string, ql, thres, aux_beg, exz); exz->ps = 0; - } - - // if(id == 40 && qs == 79670 && qe == 79824) { - // fprintf(stderr, "\n[M::%s::semi] exz->ps::%d, exz->pe::%d, exz->ts::%d, exz->te::%d, exz->err::%d, exz->cigar.n::%d\n", - // __func__, exz->ps, exz->pe, exz->ts, exz->te, exz->err, (int32_t)exz->cigar.n); - // } - - if(is_align(*exz)) { - kv_pushp(window_list, z->w_list, &p); - p->x_start = qs; p->x_end = qe; ///must set x_start/x_end here - p->y_start = t_s + exz->ps;///difference - p->y_end = t_s + exz->pe; - p->error = exz->err; - p->cidx = p->clen = 0; - if(is_cigar) { - push_wcigar(p, &(z->w_list), exz); - ///this condition is always wrong - ///in best case, r_ts = threshold, t_end = aln_l - thres - 1 - if ((((exz->pe+1) == tl) || (exz->ps == 0)) && (exz->err > 0)) { - if(recal_boundary_exz(q_string, tstr, ql, tl, thres, t_s, exz->ps, exz->pe, - exz->err, id, rev, exz, rref, hpc_g, uref, &t_s, &aux_beg, &aux_end)) { - //update cigar - z->w_list.c.n = p->cidx; push_wcigar(p, &(z->w_list), exz); - - p->y_start = t_s + exz->ps;///difference - p->y_end = t_s + exz->pe; - p->error = exz->err; - } - } - } - - p->extra_begin = aux_beg; - p->extra_end = aux_end; - p->error_threshold = thres; - z->align_length += ql; - return 1; - } - return 0; -} - -inline uint32_t aln_wlst_adv_non_retrieve_exz(overlap_region *z, char *qstr, char *tstr, int64_t t_tot_l, bit_extz_t *exz, uint32_t max_err, -uint32_t rev, uint32_t id, int64_t qs, int64_t qe, int64_t t_s, int64_t block_s, double e_rate, uint32_t is_cigar) -{ - int64_t ql, tl, aln_l; window_list *p = NULL; ///int r_ts = 0, t_end; - int64_t aux_beg, aux_end, t_pri_l; int64_t thres; char *q_string, *t_string; - ql = qe + 1 - qs; - ///there are two potiential reasons for unmatched window: - ///1. this window has a large number of differences - ///2. DP does not start from the right offset - thres = double_error_threshold(get_init_err_thres(ql, e_rate, block_s, max_err), ql); - - aln_l = ql + (thres << 1); - - if(!init_waln(thres, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) return 0; - if(t_pri_l + thres < ql) return 0; - - q_string = qstr + qs; t_string = tstr + t_s; - - tl = t_pri_l; - if(is_cigar) { - clear_align(*exz); - ed_band_cal_semi_64_w_absent_diag_trace(t_string, tl, q_string, ql, thres, aux_beg, exz); - } else { - ed_band_cal_semi_64_w_absent_diag(t_string, tl, q_string, ql, thres, aux_beg, exz); exz->ps = 0; - } - - // if(id == 40 && qs == 79670 && qe == 79824) { - // fprintf(stderr, "\n[M::%s::semi] exz->ps::%d, exz->pe::%d, exz->ts::%d, exz->te::%d, exz->err::%d, exz->cigar.n::%d\n", - // __func__, exz->ps, exz->pe, exz->ts, exz->te, exz->err, (int32_t)exz->cigar.n); - // } - - if(is_align(*exz)) { - kv_pushp(window_list, z->w_list, &p); - p->x_start = qs; p->x_end = qe; ///must set x_start/x_end here - p->y_start = t_s + exz->ps;///difference - p->y_end = t_s + exz->pe; - p->error = exz->err; - p->cidx = p->clen = 0; - if(is_cigar) { - push_wcigar(p, &(z->w_list), exz); - ///this condition is always wrong - ///in best case, r_ts = threshold, t_end = aln_l - thres - 1 - if ((((exz->pe+1) == tl) || (exz->ps == 0)) && (exz->err > 0)) { - if(recal_boundary_non_retrieve_exz(q_string, tstr, t_tot_l, ql, tl, thres, t_s, exz->ps, exz->pe, - exz->err, id, rev, exz, &t_s, &aux_beg, &aux_end)) { - //update cigar - z->w_list.c.n = p->cidx; push_wcigar(p, &(z->w_list), exz); - - p->y_start = t_s + exz->ps;///difference - p->y_end = t_s + exz->pe; - p->error = exz->err; - } - } - } - - p->extra_begin = aux_beg; - p->extra_end = aux_end; - p->error_threshold = thres; - z->align_length += ql; - return 1; - } - return 0; -} - -inline uint32_t aln_wlst(overlap_region *z, All_reads *rref, const ul_idx_t *uref, UC_Read* g_read, Correct_dumy* dumy, -int32_t y_strand, int32_t y_id, int64_t x_start, int64_t x_end, long long y_start, int64_t block_s, double e_rate, int32_t is_cigar) -{ - int64_t x_len, Window_Len; window_list *p = NULL; long long o_len; - int32_t threshold; int real_y_start = 0, end_site, extra_begin, extra_end; - char *x_string, *y_string; unsigned int error; - x_len = x_end + 1 - x_start; - ///there are two potiential reasons for unmatched window: - ///1. this window has a large number of differences - ///2. DP does not start from the right offset - if(rref) { - threshold = double_error_threshold(get_init_err_thres(x_len, e_rate, block_s, THRESHOLD), x_len); - } else { - threshold = double_ul_error_threshold(get_init_err_thres(x_len, e_rate, block_s, THRESHOLD_MAX_SIZE), x_len); - } - Window_Len = x_len + (threshold << 1); - ///y_start might be less than 0 - if(!determine_overlap_region(threshold, y_start, y_id, Window_Len, (rref?(Get_READ_LENGTH((*rref), y_id)):(uref->ug->u.a[y_id].len)), - &extra_begin, &extra_end, &y_start, &o_len)) { - return 0; - } - - if(o_len + threshold < x_len) return 0; - if(rref) { - fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, rref, y_id, extra_begin, extra_end); - } else { - fill_subregion_ul(dumy->overlap_region, y_start, o_len, y_strand, uref, y_id, extra_begin, extra_end); - } - x_string = g_read->seq + x_start; - y_string = dumy->overlap_region; - - if(is_cigar) { - ///note!!! need notification - end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, - &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); - } else { - ///note!!! need notification - end_site = Reserve_Banded_BPM(y_string, Window_Len, x_string, x_len, threshold, &error); - } - if(error!=(unsigned int)-1) { - if(is_cigar) { - ///this condition is always wrong - ///in best case, real_y_start = threshold, end_site = Window_Len - threshold - 1 - if (end_site == Window_Len - 1 || real_y_start == 0) { - if(rref) { - fix_boundary(x_string, x_len, threshold, y_start, real_y_start, - end_site, extra_begin, extra_end, y_id, Window_Len, rref, dumy, - y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, - &extra_end, &error); - } else { - fix_ul_boundary(x_string, x_len, threshold, y_start, real_y_start, - end_site, extra_begin, extra_end, y_id, Window_Len, uref, dumy, - y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, - &extra_end, &error); - } - } - } - - kv_pushp(window_list, z->w_list, &p); - p->x_start = x_start; p->x_end = x_end; ///must set x_start/x_end here - if(is_cigar) { - generate_cigar(dumy->path, dumy->path_length, p, &(z->w_list), &real_y_start, &end_site, &error, x_string, x_len, y_string); - } else { - p->cidx = p->clen = 0; - } - p->y_start = y_start + real_y_start;///difference - p->y_end = y_start + end_site; - p->error = error; - p->extra_begin = extra_begin; - p->extra_end = extra_end; - p->error_threshold = threshold; - z->align_length += x_len; - - return 1; - } - return 0; -} -uint64_t realign_ed(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, -char *tstr, char *tstr_1, Correct_dumy* dumy, kvec_t_u64_warp* v_idx, int64_t block_s, double e_rate, -double *e_rate_final, uint32_t sec_check, int64_t *is_sort); -inline void refine_ed_aln(overlap_region_alloc* overlap_list, All_reads *rref, const ul_idx_t *uref, - UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, kvec_t_u64_warp* v_idx, int64_t block_s, double e_rate, double e_rate_final) -{ - int64_t j, k, i, on, y_id, y_readLen, x_start, x_end, x_len, total_y_start, total_y_end; - int32_t y_strand, real_y_start; - int64_t nw, a_nw, w_id, w_s, w_e, is_srt, mm_we, mm_ws, mm_aln, ovl; - double error_rate; uint64_t *w_idx; overlap_region *z; window_list *p = NULL; - - overlap_list->mapped_overlaps_length = 0; on = overlap_list->length; - for (j = 0; j < on; ++j) { - // z = &(overlap_list->list[j]); ovl = z->x_pos_e+1-z->x_pos_s; - // if(!realign_ed(z, uref, NULL, rref, g_read->seq, - // dumy->overlap_region, dumy->overlap_region_fix, dumy, v_idx, block_s, e_rate, NULL, 1, &is_srt)) { - // continue; - // } - z = &(overlap_list->list[j]); z->is_match = 0; is_srt = 1; - if(z->w_list.n == 0) continue;///no alignment - nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); a_nw = z->w_list.n; - kv_resize(uint64_t, v_idx->a, (uint64_t)nw); - memset(v_idx->a.a, -1, sizeof((*v_idx->a.a))*nw); w_idx = v_idx->a.a; - for (i = 0; i < a_nw; i++) { ///w_idx[] == (uint64_t) if unmatched - assert(z->w_list.a[i].y_end != -1); - w_id = get_win_id_by_s(z, z->w_list.a[i].x_start, block_s, NULL); - w_idx[w_id] = i; - } - - y_id = z->y_id; y_strand = z->y_pos_strand; - ovl = z->x_pos_e+1-z->x_pos_s; mm_we = z->x_pos_s; mm_aln = 0; - y_readLen = (rref?(Get_READ_LENGTH((*rref), y_id)):(uref->ug->u.a[y_id].len)); - for (i = a_nw-1; i >= 0; i--) { //utilize the the end pos of pre-window in forward - w_id = get_win_id_by_s(z, z->w_list.a[i].x_start, block_s, &w_e); - assert(z->w_list.a[i].x_end == w_e); - if(w_e > mm_we) mm_we = w_e; - ///in most cases, extra_begin = 0 - total_y_start = z->w_list.a[i].y_end + 1 - z->w_list.a[i].extra_begin; - for (k = w_id + 1; k < nw && total_y_start < y_readLen; k++) { - if(w_idx[k] != (uint64_t)-1) break; - w_s = w_e + 1; - w_id = get_win_id_by_s(z, w_s, block_s, &w_e); - assert(w_id == k); - x_start = w_s; x_end = w_e; - if(aln_wlst(z, rref, uref, g_read, dumy, y_strand, y_id, x_start, x_end, - total_y_start, block_s, e_rate, 0)) { - p = &(z->w_list.a[z->w_list.n-1]); - w_idx[k] = z->w_list.n - 1; - if(x_end > mm_we) mm_we = x_end; - if(is_srt && z->w_list.n > 1 && p->x_start < z->w_list.a[z->w_list.n-2].x_start) is_srt = 0; - } else { - break; - } - total_y_start = p->y_end + 1 - p->extra_begin; - } - } - mm_ws = z->x_pos_s; mm_aln = mm_we+1-mm_ws; - if(!simi_pass(ovl, mm_aln, uref?1:0, OVERLAP_THRESHOLD_NOSI_FILTER, NULL)) continue; - if(nw > 0 && w_idx[0] != (uint64_t)-1) mm_ws = z->w_list.a[w_idx[0]].x_end+1; - - for (i = 1; i < nw; i++) { //utilize the the start pos of next window in backward - ///find the first matched window, which should not be the first window - ///the pre-window of this matched window must be unmatched - if(w_idx[i] != (uint64_t)-1 && w_idx[i-1] == (uint64_t)-1) { - w_s = z->w_list.a[w_idx[i]].x_start; mm_aln -= (w_s-mm_ws); - ///check if the start pos of this matched window has been calculated - if(z->w_list.a[w_idx[i]].clen == 0) { - p = &(z->w_list.a[w_idx[i]]); - gen_backtrace(p, z, rref, uref, g_read, dumy, y_strand, y_id); - assert(p->error != -1); - p->y_end += p->extra_begin; - } - real_y_start = p->y_start; - - ///the end pos for pre window is real_y_start - 1 - total_y_end = real_y_start - 1; - ///find the unmatched window on the left of current matched window - ///k starts from i - 1 - for (k = i - 1; k >= 0 && w_idx[k] == (uint64_t)-1 && total_y_end > 0; k--) { - w_e = w_s - 1; - w_id = get_win_id_by_e(z, w_e, block_s, &w_s); - assert(w_id == k); - x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; - if(aln_wlst(z, rref, uref, g_read, dumy, y_strand, y_id, x_start, x_end, total_y_end+1-x_len, block_s, e_rate, 1)) { - p = &(z->w_list.a[z->w_list.n-1]); - p->y_start -= p->extra_begin; ///y_start has no shift, but y_end has shift - w_idx[k] = z->w_list.n - 1; - mm_aln += x_len; - if(is_srt && z->w_list.n > 1 && p->x_start < z->w_list.a[z->w_list.n-2].x_start) is_srt = 0; - } else { - break; - } - total_y_end = p->y_start - 1; - } - if(!simi_pass(ovl, mm_aln, uref?1:0, OVERLAP_THRESHOLD_NOSI_FILTER, NULL)) break; - } - if(w_idx[i] != (uint64_t)-1) mm_ws = z->w_list.a[w_idx[i]].x_end+1; - } - - if(i < nw) continue; - if(uref && simi_pass(ovl, z->align_length, uref?1:0, OVERLAP_THRESHOLD_NOSI_FILTER, NULL)) { - z->is_match = 3; overlap_list->mapped_overlaps_length += z->align_length; - ///sort for set_herror_win - if(!is_srt) radix_sort_window_list_xs_srt(z->w_list.a, z->w_list.a + z->w_list.n); - } - } - - if(uref && overlap_list->mapped_overlaps_length > 0) { - set_herror_win(overlap_list, dumy, v_idx, e_rate, g_read->length, block_s); - } - - overlap_list->mapped_overlaps_length = 0; - for (j = 0; j < (long long)overlap_list->length; j++) { - z = &(overlap_list->list[j]); - y_id = z->y_id; y_strand = z->y_pos_strand; - y_readLen = (rref?(Get_READ_LENGTH((*rref), y_id)):(uref->ug->u.a[y_id].len)); - ovl = z->x_pos_e + 1 - z->x_pos_s; //z->is_match = 0; - // if(y_id == 4) { - // fprintf(stderr, "[M::%s::idx->%ld::] z::x_pos_s->%u, z::x_pos_e->%u, ovl->%ld, aln->%u\n", - // __func__, j, z->x_pos_s, z->x_pos_e, ovl, z->align_length); - // } - ///debug_scan_cigar(&(overlap_list->list[j])); - ///only calculate cigar for high quality overlaps - // int64_t tt = 0; - if(simi_pass(ovl, z->align_length, 0, OVERLAP_THRESHOLD_NOSI_FILTER, &e_rate)) { - a_nw = z->w_list.n; - for (i = 0, is_srt = 1; i < a_nw; i++) { - p = &(z->w_list.a[i]); - ///check if the cigar of this window has been got - if(p->clen == 0) { - gen_backtrace(p, z, rref, uref, g_read, dumy, y_strand, y_id); - assert(p->error != -1); - // if(y_id == 4) { - // fprintf(stderr, "+[M::idx->%ld::] y_start->%d, y_end->%d, error->%d\n", - // j, p->y_start, p->y_end, p->error); - // } - } - else { - p->y_end -= p->extra_begin; - // if(y_id == 4) { - // fprintf(stderr, "-[M::idx->%ld::] y_start->%d, y_end->%d, error->%d\n", - // j, p->y_start, p->y_end, p->error); - // } - } - // tt += p->error; - if(is_srt && i > 0 && p->x_start < z->w_list.a[i-1].x_start) is_srt = 0; - } - if(!is_srt) radix_sort_window_list_xs_srt(z->w_list.a, z->w_list.a + z->w_list.n); - error_rate = non_trim_error_rate(z, rref, uref, v_idx, dumy, g_read, e_rate, block_s); - z->is_match = 0;///must be here; - // if(y_id == 4) { - // fprintf(stderr, "[M::%s::idx->%ld::] block_s->%ld, z::x_pos_s->%u, z::x_pos_e->%u, ovl->%ld, aln->%u, error_rate->%f, e_rate_final->%f\n", - // __func__, j, block_s, z->x_pos_s, z->x_pos_e, ovl, z->align_length, error_rate, e_rate_final); - // exit(1); - // } - if (error_rate <= e_rate_final) { - overlap_list->mapped_overlaps_length += ovl; - z->is_match = 1; append_unmatched_wins(z, block_s); - if(rref) { - calculate_boundary_cigars(z, rref, dumy, g_read, e_rate); - } else { - calculate_ul_boundary_cigars(z, uref, dumy, g_read, e_rate, block_s); - } - // assert(get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s)==(int64_t)z->w_list.n); - // assert((int64_t)z->x_pos_s==z->w_list.a[0].x_start && - // (int64_t)z->x_pos_e==z->w_list.a[z->w_list.n-1].x_end); - } else if (error_rate <= e_rate_final * 1.5) { - z->is_match = 3; - } - } else {///it impossible to be matched - z->is_match = 0; - // fprintf(stderr, "[M::%s::idx->%ld::is_match->%u] z::x_pos_s->%u, z::x_pos_e->%u, error_rate->-1, e_threshold->%f\n", - // __func__, j, z->is_match, z->x_pos_s, z->x_pos_e, e_rate); - } - } -} - - -uint32_t align_ul_ed_post(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, char* qstr, char *tstr, char *tstr_1, -Correct_dumy* dumy, double e_rate, int64_t w_l, double ovlp_cut, void *km); -double gen_extend_err(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, -char *tstr, char *tstr_1, Correct_dumy* dumy, uint64_t *v_idx, int64_t block_s, double ovlp_cut, double e_rate, double e_max, int64_t *r_e); -inline void refine_ed_aln_test(overlap_region_alloc* overlap_list, All_reads *rref, const ul_idx_t *uref, - UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, kvec_t_u64_warp* v_idx, int64_t block_s, double e_rate, double e_rate_final) -{ - int64_t j, on, ovl; uint64_t k; double rr; overlap_region *z; - - overlap_list->mapped_overlaps_length = 0; on = overlap_list->length; - for (j = 0; j < on; ++j) { - z = &(overlap_list->list[j]); ovl = z->x_pos_e+1-z->x_pos_s; - if(!align_ul_ed_post(z, uref, NULL, g_read->seq, dumy->overlap_region, dumy->overlap_region_fix, - dumy, e_rate, block_s, OVERLAP_THRESHOLD_NOSI_FILTER, NULL)) { - continue; - } - if(uref && simi_pass(ovl, z->align_length, uref?1:0, OVERLAP_THRESHOLD_NOSI_FILTER, NULL)) { - z->is_match = 3; overlap_list->mapped_overlaps_length += z->align_length; - } - } - - if(uref && overlap_list->mapped_overlaps_length > 0) { - set_herror_win(overlap_list, dumy, v_idx, e_rate, g_read->length, block_s); - } - - double e_max = e_rate_final * 1.5; - overlap_list->mapped_overlaps_length = 0; on = overlap_list->length; - for (j = 0; j < on; j++) { - z = &(overlap_list->list[j]); ovl = z->x_pos_e + 1 - z->x_pos_s; - rr = gen_extend_err(z, uref, NULL, rref, g_read->seq, dumy->overlap_region, dumy->overlap_region_fix, - dumy, v_idx?v_idx->a.a:NULL, block_s, -1, e_rate, (e_max+0.000001), NULL); - z->is_match = 0;///must be here; - if (rr <= e_rate_final) { - for (k = 0; k < z->w_list.n; k++) { - if(z->w_list.a[k].clen) continue; - gen_backtrace_adv(&(z->w_list.a[k]), z, rref, NULL, uref, g_read->seq, dumy->overlap_region, dumy->overlap_region_fix, - dumy, z->y_pos_strand, z->y_id); - } - - overlap_list->mapped_overlaps_length += ovl; - z->is_match = 1; append_unmatched_wins(z, block_s); - if(rref) { - calculate_boundary_cigars(z, rref, dumy, g_read, e_rate); - } else { - calculate_ul_boundary_cigars(z, uref, dumy, g_read, e_rate, block_s); - } - } else if (rr <= e_max) { - z->is_match = 3; - } - } -} - - - -inline void add_base_to_correct_read_directly(Correct_dumy* dumy, char base) -{ - - if (dumy->corrected_read_length + 2 > dumy->corrected_read_size) - { - dumy->corrected_read_size = dumy->corrected_read_size * 2; - dumy->corrected_read = (char*)realloc(dumy->corrected_read, dumy->corrected_read_size); - } - - dumy->corrected_read[dumy->corrected_read_length] = base; - dumy->corrected_read_length++; - dumy->corrected_read[dumy->corrected_read_length] = '\0'; - -} - -inline void add_base_to_correct_read(Correct_dumy* dumy, char base, int is_error) -{ - ///don't need to deal with deletion - if (base != 'D') - { - if (dumy->corrected_read_length + 2 > dumy->corrected_read_size) - { - dumy->corrected_read_size = dumy->corrected_read_size * 2; - dumy->corrected_read = (char*)realloc(dumy->corrected_read, dumy->corrected_read_size); - } - - dumy->corrected_read[dumy->corrected_read_length] = base; - dumy->corrected_read_length++; - dumy->corrected_read[dumy->corrected_read_length] = '\0'; - } - - if (is_error) - { - dumy->corrected_base++; - } - -} - - -inline void add_segment_to_correct_read(Correct_dumy* dumy, char* segment, long long segment_length) -{ - - if (dumy->corrected_read_length + segment_length + 2 > dumy->corrected_read_size) - { - dumy->corrected_read_size = dumy->corrected_read_length + segment_length + 2; - dumy->corrected_read = (char*)realloc(dumy->corrected_read, dumy->corrected_read_size); - } - - memcpy(dumy->corrected_read + dumy->corrected_read_length, segment, segment_length); - dumy->corrected_read_length += segment_length; - dumy->corrected_read[dumy->corrected_read_length] = '\0'; -} - - - - -///return the ID of next node at backbone -long long inline add_path_to_correct_read(Graph* backbone, Correct_dumy* dumy, long long currentNodeID, -long long type, long long edgeID, Cigar_record* current_cigar, char* self_string) -{ - //long long i; - long long nodeID; - - ///Note: currentNodeID must be a backbone node - ///currentNodeID = 0 means a fake node - ///currentNodeID = i means self_string[i - 1] - ///include match/mismatch - if (type == MISMATCH) - { - ///match - if(backbone->g_nodes.list[currentNodeID].mismatch_edges.list[edgeID].length == 0) - { - nodeID = backbone->g_nodes.list[currentNodeID].mismatch_edges.list[edgeID].out_node; - add_base_to_correct_read_directly(dumy, backbone->g_nodes.list[nodeID].base); - ///nodeID = i means self_string[i - 1] - ///add_cigar_record(self_string+nodeID-1, 1, current_cigar, 0); - add_cigar_record(&(backbone->g_nodes.list[nodeID].base), 1, current_cigar, 0); - return nodeID; - } - else ///mismatch - { - nodeID = backbone->g_nodes.list[currentNodeID].mismatch_edges.list[edgeID].out_node; - add_base_to_correct_read_directly(dumy, backbone->g_nodes.list[nodeID].base); - dumy->corrected_base++; - char merge_base = 0; - merge_base = seq_nt6_table[(uint8_t)backbone->g_nodes.list[nodeID].base]; - merge_base = merge_base << 3; - nodeID = backbone->g_nodes.list[nodeID].mismatch_edges.list[0].out_node; - merge_base = merge_base | seq_nt6_table[(uint8_t)backbone->g_nodes.list[nodeID].base]; - add_cigar_record(&merge_base, 1, current_cigar, 1); - return nodeID; - } - } - else if (type == DELETION) - { - nodeID = backbone->g_nodes.list[currentNodeID].deletion_edges.list[edgeID].out_node; - dumy->corrected_base += nodeID - currentNodeID; - add_cigar_record(self_string + currentNodeID, nodeID - currentNodeID, current_cigar, DELETION); - return nodeID; - } - else if (type == INSERTION) - { - ///pay attention to this line - backbone->g_nodes.list[currentNodeID].num_insertions = 0; - - nodeID = backbone->g_nodes.list[currentNodeID].insertion_edges.list[edgeID].out_node; - long long step = backbone->g_nodes.list[currentNodeID].insertion_edges.list[edgeID].length; - long long i; - for (i = 0; i < step; i++) - { - add_base_to_correct_read_directly(dumy, backbone->g_nodes.list[nodeID].base); - add_cigar_record(&backbone->g_nodes.list[nodeID].base, 1, current_cigar, INSERTION); - nodeID = backbone->g_nodes.list[nodeID].insertion_edges.list[0].out_node; - } - dumy->corrected_base += step; - return nodeID; - } - else - { - fprintf(stderr, "error type\n"); - return -1; - } -} - - -///return the ID of next node at backbone -long long inline add_path_to_correct_read_new(Graph* backbone, Graph* DAGCon, Correct_dumy* dumy, long long currentNodeID, -long long type, long long edgeID, Cigar_record* current_cigar, char* self_string) -{ - //long long i; - long long nodeID; - - ///Note: currentNodeID must be a backbone node - ///currentNodeID = 0 means a fake node - ///currentNodeID = i means self_string[i - 1] - ///include match/mismatch - if (type == MISMATCH) - { - ///match - if(backbone->g_nodes.list[currentNodeID].mismatch_edges.list[edgeID].length == 0) - { - nodeID = backbone->g_nodes.list[currentNodeID].mismatch_edges.list[edgeID].out_node; - add_base_to_correct_read_directly(dumy, backbone->g_nodes.list[nodeID].base); - ///nodeID = i means self_string[i - 1] - ///add_cigar_record(self_string+nodeID-1, 1, current_cigar, 0); - add_cigar_record(&(backbone->g_nodes.list[nodeID].base), 1, current_cigar, 0); - return nodeID; - } - else ///mismatch - { - nodeID = backbone->g_nodes.list[currentNodeID].mismatch_edges.list[edgeID].out_node; - add_base_to_correct_read_directly(dumy, backbone->g_nodes.list[nodeID].base); - dumy->corrected_base++; - char merge_base = 0; - merge_base = seq_nt6_table[(uint8_t)backbone->g_nodes.list[nodeID].base]; - merge_base = merge_base << 3; - nodeID = backbone->g_nodes.list[nodeID].mismatch_edges.list[0].out_node; - merge_base = merge_base | seq_nt6_table[(uint8_t)backbone->g_nodes.list[nodeID].base]; - add_cigar_record(&merge_base, 1, current_cigar, 1); - return nodeID; - } - } - else if (type == DELETION) - { - nodeID = backbone->g_nodes.list[currentNodeID].deletion_edges.list[edgeID].out_node; - dumy->corrected_base += nodeID - currentNodeID; - add_cigar_record(self_string + currentNodeID, nodeID - currentNodeID, current_cigar, DELETION); - return nodeID; - } - else if (type == INSERTION) - { - ///pay attention to this line - backbone->g_nodes.list[currentNodeID].num_insertions = 0; - long long str; - char str_c; - while (pop_from_Queue(&(DAGCon->node_q), &str)) - { - str_c = (char)str; - add_base_to_correct_read_directly(dumy, str_c); - add_cigar_record(&str_c, 1, current_cigar, INSERTION); - dumy->corrected_base++; - } - - return currentNodeID; - } - else - { - fprintf(stderr, "error type\n"); - } - - return -1; -} - - -void Merge_Out_Nodes(Graph* DAGCon, Node* currentNode) -{ - ///if this node does not have any output, directly return - if(Real_Length(Output_Edges((*currentNode))) == 0) - { - return; - } - - RSet buf, out_buf; - char Bases[4] = {'A', 'C', 'G', 'T'}; - char base; - long long base_i, weight; - int flag = 0; - Node* get_node_1 = NULL; - Node* out_node_of_get_node_1 = NULL; - Node* consensus_node_1 = NULL; - Edge* e_forward_1 = NULL; - Edge* e_backward_1 = NULL; - - ///merge all base for each base - for (base_i = 0; base_i < 4; base_i++) - { - base = Bases[base_i]; - - clear_RSet(&buf); - flag = 0; - weight = 0; - ///should use getOutputEdges, instead of getOutputNodes - ///check all out-nodes of currentNode - while(getOutputNodes(&buf, DAGCon, currentNode, &get_node_1)) - { - ///check the corresponding node, this node must only have one in-node - ///note this is the Real_Length, instead of the Input_Edges.length - if((*get_node_1).base == base && Real_Length(Input_Edges(*get_node_1)) == 1) - { - if(flag == 0) - { - flag = 1; - ///add a new node to merge all out-node - consensus_node_1 = get_node_1; - ///link consensus_node to currentNode - ///set the new edge to be visited - if(get_bi_Edge(DAGCon, currentNode, consensus_node_1, &e_forward_1, &e_backward_1)) - { - Visit(*e_forward_1) = 1; - Visit(*e_backward_1) = 1; - } - else - { - fprintf(stderr, "error\n"); - } - - weight = (*e_forward_1).weight; - } - else - { - flag++; - ///add the weight of get_node->currentNode - if(get_bi_Edge(DAGCon, currentNode, get_node_1, &e_forward_1, &e_backward_1)) - { - weight = weight + (*e_forward_1).weight; - } - else - { - fprintf(stderr, "error\n"); - } - - ///process the out-nodes of get_node - clear_RSet(&out_buf); - while(getOutputNodes(&out_buf, DAGCon, get_node_1, &out_node_of_get_node_1)) - { - ///link consensus_node to the out-nodes of get_node - if(get_bi_Edge(DAGCon, consensus_node_1, out_node_of_get_node_1, &e_forward_1, &e_backward_1)) - { - Visit(*e_forward_1) = 1; - Visit(*e_backward_1) = 1; - (*e_forward_1).weight += get_Edge_Weight(DAGCon, get_node_1, out_node_of_get_node_1); - (*e_backward_1).weight = (*e_forward_1).weight; - } - else - { - add_bi_direction_edge(DAGCon, consensus_node_1, out_node_of_get_node_1, - get_Edge_Weight(DAGCon, get_node_1, out_node_of_get_node_1), 1); - } - } - - delete_Node_DAGCon(DAGCon, get_node_1); - } - } - } - - if(flag > 1) - { - get_bi_Edge(DAGCon, currentNode, consensus_node_1, &e_forward_1, &e_backward_1); - (*e_forward_1).weight = weight; - (*e_backward_1).weight = (*e_forward_1).weight; - } - - if(flag > 0) - { - Merge_Out_Nodes(DAGCon, consensus_node_1); - } - } -} - - -void Merge_In_Nodes(Graph* DAGCon, Node* currentNode) -{ - ///if this node does not have any input, directly return - if(Real_Length(Input_Edges((*currentNode))) == 0) - { - return; - } - - RSet buf, in_buf; - char Bases[4] = {'A', 'C', 'G', 'T'}; - char base; - long long base_i, weight; - int flag = 0; - Node* get_node = NULL; - Node* in_node_of_get_node = NULL; - Node* consensus_node = NULL; - Edge* e_forward = NULL; - Edge* e_backward = NULL; - - ///merge all base for each base - for (base_i = 0; base_i < 4; base_i++) - { - base = Bases[base_i]; - - clear_RSet(&buf); - flag = 0; - weight = 0; - ///should use getInputEdges, instead of getInputNodes - ///check all in-nodes of currentNode - while(getInputNodes(&buf, DAGCon, currentNode, &get_node)) - { - ///check the corresponding node, this node must only have one out-node - ///note this is the Real_Length, instead of the Output_Edges.length - if((*get_node).base == base && Real_Length(Output_Edges(*get_node)) == 1) - { - if(flag == 0) - { - flag = 1; - ///add a new node to merge all in-node - consensus_node = get_node; - ///link consensus_node to currentNode - ///set the new edge to be visited - if(get_bi_Edge(DAGCon, consensus_node, currentNode, &e_forward, &e_backward)) - { - Visit(*e_forward) = 1; - Visit(*e_backward) = 1; - } - else - { - fprintf(stderr, "error\n"); - } - - weight = (*e_forward).weight; - } - else - { - flag++; - ///add the weight of get_node->currentNode - if(get_bi_Edge(DAGCon, get_node, currentNode, &e_forward, &e_backward)) - { - weight = weight + (*e_forward).weight; - } - else - { - fprintf(stderr, "error\n"); - } - - ///process the in-nodes of get_node - clear_RSet(&in_buf); - while(getInputNodes(&in_buf, DAGCon, get_node, &in_node_of_get_node)) - { - ///link in-nodes of get_node to consensus_node - if(get_bi_Edge(DAGCon, in_node_of_get_node, consensus_node, &e_forward, &e_backward)) - { - Visit(*e_forward) = 1; - Visit(*e_backward) = 1; - (*e_forward).weight += get_Edge_Weight(DAGCon, in_node_of_get_node, get_node); - (*e_backward).weight = (*e_forward).weight; - } - else - { - add_bi_direction_edge(DAGCon, in_node_of_get_node, consensus_node, - get_Edge_Weight(DAGCon, in_node_of_get_node, get_node), 1); - } - } - - delete_Node_DAGCon(DAGCon, get_node); - } - } - } - - if(flag > 1) - { - get_bi_Edge(DAGCon, consensus_node, currentNode, &e_forward, &e_backward); - (*e_forward).weight = weight; - (*e_backward).weight = (*e_forward).weight; - } - - if(flag > 0) - { - Merge_In_Nodes(DAGCon, consensus_node); - } - } -} - -void print_graph(Graph* DAGCon) -{ - uint64_t i; - for (i = 0; i < DAGCon->g_nodes.length; i++) - { - Node* currentStartNode = &(G_Node(*DAGCon, i)); - RSet iter_out; - - if(If_Node_Exist(*currentStartNode)) - { - fprintf(stderr, "ID: %lu (%c) (w: %lu)\n", (unsigned long)(*currentStartNode).ID, (*currentStartNode).base, (unsigned long)(*currentStartNode).weight); - clear_RSet(&iter_out); - Edge* e; - fprintf(stderr, "****Out-node: "); - while(getOutputEdges(&iter_out, DAGCon, currentStartNode, &e)) - { - //fprintf(stderr, "%d[%c], ", G_Node(*DAGCon, e->out_node).ID, G_Node(*DAGCon, e->out_node).base); - fprintf(stderr, "%lu(w: %lu), ", (unsigned long)G_Node(*DAGCon, e->out_node).ID, (unsigned long)e->weight); - } - fprintf(stderr, "\n"); - - - // clear_RSet(&iter_out); - // fprintf(stderr, "In-node: "); - // while(getInputEdges(&iter_out, DAGCon, currentStartNode, &e)) - // { - // fprintf(stderr, "%d[%c], ", G_Node(*DAGCon, e->in_node).ID, G_Node(*DAGCon, e->in_node).base); - // } - } - } - - fprintf(stderr, "*******\n"); - -} - -void debug_DAGCon(Graph* DAGCon) -{ - uint64_t i = 0; - for (i = 0; i < DAGCon->g_nodes.length; i++) - { - Node* currentStartNode = &(G_Node(*DAGCon, i)); - RSet iter_out; - - if(If_Node_Exist(*currentStartNode)) - { - clear_RSet(&iter_out); - Edge* e_self; - Edge* e_reverse; - while(getOutputEdges(&iter_out, DAGCon, currentStartNode, &e_self)) - { - - get_bi_direction_edges(DAGCon, e_self, &e_self, &e_reverse); - - - if(Visit(*e_self) == 0) - { - fprintf(stderr, "Visit(*e_self): %lu, error visit flag: in_node: %lu, out_node: %lu\n", - (unsigned long)Visit(*e_self), (unsigned long)(*e_self).in_node, (unsigned long)(*e_self).out_node); - } - - - if(Visit(*e_reverse) == 0) - { - fprintf(stderr, "Visit(*e_reverse): %lu, error visit flag: in_node: %lu, out_node: %lu\n", - (unsigned long)Visit(*e_reverse), (unsigned long)(*e_reverse).in_node, (unsigned long)(*e_reverse).out_node); - } - - - if(e_self->in_node != e_reverse->in_node) - { - fprintf(stderr, "different in-node\n"); - } - if(e_self->out_node != e_reverse->out_node) - { - fprintf(stderr, "different out-node\n"); - } - if(e_self->weight != e_reverse->weight) - { - fprintf(stderr, "different weight\n"); - } - } - - clear_RSet(&iter_out); - while(getInputEdges(&iter_out, DAGCon, currentStartNode, &e_self)) - { - - get_bi_direction_edges(DAGCon, e_self, &e_self, &e_reverse); - - - if(Visit(*e_self) == 0) - { - fprintf(stderr, "Visit(*e_self): %lu, error visit flag: in_node: %lu, out_node: %lu\n", - (unsigned long)Visit(*e_self), (unsigned long)(*e_self).in_node, (unsigned long)(*e_self).out_node); - } - - - if(Visit(*e_reverse) == 0) - { - fprintf(stderr, "Visit(*e_reverse): %lu, error visit flag: in_node: %lu, out_node: %lu\n", - (unsigned long)Visit(*e_reverse), (unsigned long)(*e_reverse).in_node, (unsigned long)(*e_reverse).out_node); - } - - - if(e_self->in_node != e_reverse->in_node) - { - fprintf(stderr, "different in-node\n"); - } - if(e_self->out_node != e_reverse->out_node) - { - fprintf(stderr, "different out-node\n"); - } - if(e_self->weight != e_reverse->weight) - { - fprintf(stderr, "different weight\n"); - } - } - } - } -} - -void Merge_DAGCon(Graph* DAGCon) -{ - ///using the length of edge representing if it has been visited - ///in default, the length of edge is 0 - RSet iter_node, iter_edge; - long long flag; - - Node* currentNode; - Node* outNode; - Edge* edge; - Edge* e_forward; - Edge* e_backward; - - // int num_way = Real_Length(Output_Edges(G_Node(*DAGCon, DAGCon->s_start_nodeID))); - // if(num_way > 2) - // { - // print_graph(DAGCon); - // } - - - - ///at begining, only the start node has no in-node - currentNode = &(G_Node(*DAGCon, DAGCon->s_start_nodeID)); - Push_Node(DAGCon, ¤tNode); - - - - while (Pop_Node(DAGCon, ¤tNode)) - { - ///merge in-node - Merge_In_Nodes(DAGCon, currentNode); - ///merge out-node - Merge_Out_Nodes(DAGCon, currentNode); - - clear_RSet(&iter_edge); - ///for all out-edges of currentNode, set as visited - while (getOutputEdges(&iter_edge, DAGCon, currentNode, &edge)) - { - get_bi_direction_edges(DAGCon, edge, &e_forward, &e_backward); - Visit(*e_forward) = 1; - Visit(*e_backward) = 1; - } - - - - ///check all out-node of currentNode - clear_RSet(&iter_node); - while(getOutputNodes(&iter_node, DAGCon, currentNode, &outNode)) - { - - ///for each outNode, check if all in-edges have been visited - flag = 0; - clear_RSet(&iter_edge); - while (getInputEdges(&iter_edge, DAGCon, outNode, &edge)) - { - if(Visit(*edge) == 0) - { - flag = 1; - break; - } - } - //if all in-edges of Out_node have already been visited, push it to queue - if(flag == 0) - { - Push_Node(DAGCon, &outNode); - } - } - } - - - - // if(num_way > 2) - // { - // print_graph(DAGCon); - // fprintf(stderr, "****************************note*****************\n\n"); - // } - - - ///debug_DAGCon(DAGCon); -} - - -inline void generate_seq_from_path(Graph* DAGCon, Node* node, int direction) -{ - clear_Queue(&(DAGCon->node_q)); - RSet iter; - Edge* e = NULL; - uint64_t max; - Node* max_node = NULL; - - - if(direction == 0) - { - while (node->ID != DAGCon->s_end_nodeID) - { - push_to_Queue(&(DAGCon->node_q), node->base); - clear_RSet(&iter); - max = 0; - while(getOutputEdges(&iter, DAGCon, node, &e)) - { - if(e->weight > max) - { - max = e->weight; - max_node = &(G_Node(*DAGCon, e->out_node)); - } - } - node = max_node; - } - } - else - { - while (node->ID != DAGCon->s_start_nodeID) - { - push_to_Queue(&(DAGCon->node_q), node->base); - clear_RSet(&iter); - max = 0; - while(getInputEdges(&iter, DAGCon, node, &e)) - { - if(e->weight > max) - { - max = e->weight; - max_node = &(G_Node(*DAGCon, e->in_node)); - } - } - node = max_node; - } - - long long i, k; - long long length = (DAGCon->node_q.end - DAGCon->node_q.beg); - long long length_ex = length/2; - long long* array = DAGCon->node_q.buffer + DAGCon->node_q.beg; - for (i = 0; i < length_ex; i++) - { - k = array[i]; - array[i] = array[length - i - 1]; - array[length - i - 1] = k; - } - } -} - - -long long generate_best_seq_from_edges(Graph* DAGCon) -{ - long long max_start = 0, max_end = 0, max_start_edge = 0, max_end_edge = 0; - RSet iter; - Edge* e = NULL; - Node* newNode = NULL; - long long max_count = 0; - - - ///check the out-edges of start node - ///must to be 0 - max_start = 0; - newNode = &(G_Node(*DAGCon, DAGCon->s_start_nodeID)); - clear_RSet(&iter); - while(getOutputEdges(&iter, DAGCon, newNode, &e)) - { - if(e->weight > (uint64_t)max_start) - { - max_start = e->weight; - max_start_edge = iter.index - 1; - } - } - - ///check the in-edges of end node - ///must to be 0 - max_end = 0; - newNode = &(G_Node(*DAGCon, DAGCon->s_end_nodeID)); - clear_RSet(&iter); - while(getInputEdges(&iter, DAGCon, newNode, &e)) - { - if(e->weight > (uint64_t)max_end) - { - max_end = e->weight; - max_end_edge = iter.index - 1; - } - } - - if(max_start >= max_end) - { - max_count = max_start; - generate_seq_from_path(DAGCon, - &G_Node(*DAGCon, Output_Edges(G_Node(*DAGCon, DAGCon->s_start_nodeID)).list[max_start_edge].out_node), 0); - } - else - { - max_count = max_end; - generate_seq_from_path(DAGCon, - &G_Node(*DAGCon, Input_Edges(G_Node(*DAGCon, DAGCon->s_end_nodeID)).list[max_end_edge].in_node), 1); - } - - return max_count; -} - - -inline void generate_seq_from_node(Graph* DAGCon, Node* node, int direction) -{ - clear_Queue(&(DAGCon->node_q)); - RSet iter; - uint64_t max; - Node* max_node = NULL; - Node* getNodes = NULL; - - - if(direction == 0) - { - while (node->ID != DAGCon->s_end_nodeID) - { - push_to_Queue(&(DAGCon->node_q), node->base); - clear_RSet(&iter); - max = 0; - while(getOutputNodes(&iter, DAGCon, node, &getNodes)) - { - if(getNodes->weight > max) - { - max = getNodes->weight; - max_node = getNodes; - } - } - node = max_node; - } - } - else - { - while (node->ID != DAGCon->s_start_nodeID) - { - push_to_Queue(&(DAGCon->node_q), node->base); - clear_RSet(&iter); - max = 0; - while(getInputNodes(&iter, DAGCon, node, &getNodes)) - { - if(getNodes->weight > max) - { - max = getNodes->weight; - max_node = getNodes; - } - } - node = max_node; - } - - long long i, k; - long long length = (DAGCon->node_q.end - DAGCon->node_q.beg); - long long length_ex = length/2; - long long* array = DAGCon->node_q.buffer + DAGCon->node_q.beg; - for (i = 0; i < length_ex; i++) - { - k = array[i]; - array[i] = array[length - i - 1]; - array[length - i - 1] = k; - } - } -} - - -long long generate_best_seq_from_nodes(Graph* DAGCon) -{ - long long max_start = 0, max_end = 0; - RSet iter; - Edge* e = NULL; - Node* newNode = NULL; - Node* getNode = NULL; - Node* max_start_node = NULL; - Node* max_end_node = NULL; - long long max_count = 0; - uint64_t i; - - for (i = 0; i < DAGCon->g_nodes.length; i++) - { - newNode = &(G_Node(*DAGCon, i)); - if(If_Node_Exist(*newNode)) - { - newNode->weight = 0; - clear_RSet(&iter); - while(getOutputEdges(&iter, DAGCon, newNode, &e)) - { - newNode->weight += e->weight; - } - } - } - - newNode = &(G_Node(*DAGCon, DAGCon->s_start_nodeID)); - newNode->weight = 0; - clear_RSet(&iter); - while(getOutputEdges(&iter, DAGCon, newNode, &e)) - { - newNode->weight += e->weight; - } - - - newNode = &(G_Node(*DAGCon, DAGCon->s_end_nodeID)); - newNode->weight = 0; - clear_RSet(&iter); - while(getInputEdges(&iter, DAGCon, newNode, &e)) - { - newNode->weight += e->weight; - } - - - - - ///check the out-edges of start node - ///must to be 0 - max_start = 0; - newNode = &(G_Node(*DAGCon, DAGCon->s_start_nodeID)); - clear_RSet(&iter); - while(getOutputNodes(&iter, DAGCon, newNode, &getNode)) - { - if(getNode->weight > (uint64_t)max_start) - { - max_start = getNode->weight; - max_start_node = getNode; - } - } - - ///check the in-edges of end node - ///must to be 0 - max_end = 0; - newNode = &(G_Node(*DAGCon, DAGCon->s_end_nodeID)); - clear_RSet(&iter); - while(getInputNodes(&iter, DAGCon, newNode, &getNode)) - { - if(getNode->weight > (uint64_t)max_end) - { - max_end = getNode->weight; - max_end_node = getNode; - } - } - - if(max_start >= max_end) - { - max_count = max_start; - generate_seq_from_node(DAGCon, max_start_node, 0); - } - else - { - max_count = max_end; - generate_seq_from_node(DAGCon, max_end_node, 1); - } - - return max_count; -} - - -void build_DAGCon(Graph* DAGCon, Graph* backbone, long long currentNodeID, long long* max_count) -{ - long long i, j, path_weight, nodeID, step; - char base; - clear_Graph(DAGCon); - Node* newNode; - Node* lastNode; - - ///add the start node and the end node - newNode = add_Node_DAGCon(DAGCon, 'S'); - DAGCon->s_start_nodeID = newNode->ID; - - newNode = add_Node_DAGCon(DAGCon, 'E'); - DAGCon->s_end_nodeID = newNode->ID; - - - for (i = 0; i < (long long)G_Node(*backbone, currentNodeID).insertion_edges.length; i++) - { - path_weight = G_Node(*backbone, currentNodeID).insertion_edges.list[i].weight; - - lastNode = &(G_Node(*DAGCon, DAGCon->s_start_nodeID)); - - step = G_Node(*backbone, currentNodeID).insertion_edges.list[i].length; - if(step != 0) - { - nodeID = G_Node(*backbone, currentNodeID).insertion_edges.list[i].out_node; - - for (j = 0; j < step; j++) - { - base = G_Node(*backbone, nodeID).base; - newNode = add_Node_DAGCon(DAGCon, base); - add_bi_direction_edge(DAGCon, lastNode, newNode, path_weight, 0); - - nodeID = G_Node(*backbone, nodeID).insertion_edges.list[0].out_node; - - lastNode = newNode; - } - - if(lastNode->ID != DAGCon->s_start_nodeID) - { - add_bi_direction_edge(DAGCon, lastNode, &(G_Node(*DAGCon, DAGCon->s_end_nodeID)), path_weight, 0); - - } - } - - - - } - - - Merge_DAGCon(DAGCon); - - ///(*max_count) = generate_best_seq_from_edges(DAGCon); - (*max_count) = generate_best_seq_from_nodes(DAGCon); - - ///very important - backbone->g_nodes.list[currentNodeID].num_insertions = 0; - -} - -void debug_whole_graph(Graph* g) -{ - long long i, j, k; - for (i = 0; i < (long long)g->g_nodes.length; i++) - { - if(g->g_nodes.list[i].deletion_edges.length!= 0 && - g->g_nodes.list[i].deletion_edges.length!= 1) - { - fprintf(stderr, "g->g_nodes.list[i].deletion_edges.length: %lu\n", - (unsigned long)g->g_nodes.list[i].deletion_edges.length); - } - } - - for (i = g->s_start_nodeID; i < (long long)g->s_end_nodeID; i++) - { - if(g->g_nodes.list[i].mismatch_edges.length > 4 - || - g->g_nodes.list[i].mismatch_edges.length < 1) - { - fprintf(stderr, "g->s_end_nodeID: %lu, g->g_nodes.list[%lld].mismatch_edges.length: %lu\n", - (unsigned long)g->s_end_nodeID, i, (unsigned long)g->g_nodes.list[i].mismatch_edges.length); - } - } - - char current[1000]; - char compare[1000]; - long long total_weight = 0; - for (i = g->s_start_nodeID; i < (long long)g->s_end_nodeID; i++) - { - total_weight = 0; - for (j = 0; j < (long long)G_Node(*g, i).insertion_edges.length; j++) - { - - total_weight = total_weight + G_Node(*g, i).insertion_edges.list[j].weight; - - extract_path(g, i, j, current); - - for (k = j + 1; k < (long long)G_Node(*g, i).insertion_edges.length; k++) - { - extract_path(g, i, k, compare); - if(strcmp(current, compare)==0) - { - fprintf(stderr,"error\n"); - } - } - } - - if(total_weight != (long long)G_Node(*g, i).num_insertions) - { - fprintf(stderr,"error\n"); - } - } - - - -} - -void get_seq_from_Graph(Graph* backbone, Graph* DAGCon, Correct_dumy* dumy, Cigar_record* current_cigar, char* self_string, -char* r_string, long long r_string_length, long long r_string_site) -{ - ///debug_whole_graph(backbone); - long long currentNodeID; - long long i; - // There are several cases: - // 1. match 2. mismatch (A, C, G, T, N) 3. deletion 4. insertion (A, C, G, T) - // in fact, 1. the weight of node itself 2. weight of alignToNode 3. weight of insertion node - long long max_count; - int max_type; - long long max_edge; - long long total_count; - long long current_weight; - - long long max_insertion_count; - - currentNodeID = backbone->s_start_nodeID; - - while (currentNodeID != (long long)backbone->s_end_nodeID) - { - total_count = 0; - max_count = -1; - max_type = -1; - max_edge = -1; - - - ///if it is a backbone node, there are three types od out-edges - ///1. mismatch_edges 2. insertion_edges 3. deletion_edges - if (currentNodeID >= (long long)backbone->s_start_nodeID && currentNodeID <= (long long)backbone->s_end_nodeID) - { - ///mismatch_edges - for (i = 0; i < (long long)backbone->g_nodes.list[currentNodeID].mismatch_edges.length; i++) - { - if (backbone->g_nodes.list[currentNodeID].num_insertions != 0) - { - current_weight = backbone->g_nodes.list[currentNodeID].mismatch_edges.list[i].weight - - backbone->g_nodes.list[currentNodeID].mismatch_edges.list[i].num_insertions; - } - else - { - current_weight = backbone->g_nodes.list[currentNodeID].mismatch_edges.list[i].weight; - } - - - total_count = total_count + current_weight; - - ///for match, it needs to deal with both match and insertion - ///if there is a insertion, we need to check this node two times - ///1. num_insertions > 0, 2. num_insertions=0 - if (current_weight > max_count) - { - max_count = current_weight; - max_edge = i; - max_type = MISMATCH; - } - } - - ///insertion_edges - if (backbone->g_nodes.list[currentNodeID].num_insertions != 0) - { - ///this line must be prior than the next line - ///since build_DAGCon will set backbone->g_nodes.list[currentNodeID].num_insertions to be 0 - total_count = total_count + backbone->g_nodes.list[currentNodeID].num_insertions; - - build_DAGCon(DAGCon, backbone, currentNodeID, &max_insertion_count); - - if(max_insertion_count > max_count) - { - max_count = max_insertion_count; - max_type = INSERTION; - } - } - - ///deletion_edges - for (i = 0; i < (long long)backbone->g_nodes.list[currentNodeID].deletion_edges.length; i++) - { - total_count = total_count + backbone->g_nodes.list[currentNodeID].deletion_edges.list[i].weight; - - if ((long long)backbone->g_nodes.list[currentNodeID].deletion_edges.list[i].weight > max_count) - { - max_count = backbone->g_nodes.list[currentNodeID].deletion_edges.list[i].weight; - max_edge = i; - max_type = DELETION; - } - } - - ///do correction - if(max_count >= total_count*(CORRECT_THRESHOLD)) - { - currentNodeID = add_path_to_correct_read_new(backbone, DAGCon, dumy, currentNodeID, max_type, max_edge, current_cigar, - self_string); - } - else - { - ///NOTE: currentNodeID = 0 is a tmp node without any sense - if(currentNodeID > 0 && if_is_homopolymer_strict(r_string_site + currentNodeID - 1, r_string, r_string_length) - && max_count >= total_count*CORRECT_THRESHOLD_HOMOPOLYMER) - { - currentNodeID = add_path_to_correct_read_new(backbone, DAGCon, dumy, currentNodeID, max_type, max_edge, current_cigar, - self_string); - } - else///don't do correction, directly use the base of next backbone node - { - currentNodeID++; - add_base_to_correct_read_directly(dumy, backbone->g_nodes.list[currentNodeID].base); - - add_cigar_record(&(backbone->g_nodes.list[currentNodeID].base), 1, current_cigar, 0); - } - } - - } - else ///if there is a non-backbone node - { - fprintf(stderr, "error\n"); - } - - } - -} - - -void window_consensus(char* r_string, long long r_total_length, long long window_start, long long window_end, -overlap_region_alloc* overlap_list, Correct_dumy* dumy, All_reads* R_INF, Graph* g, Graph* DAGCon, Cigar_record* current_cigar) -{ - clear_Graph(g); - clear_Graph(DAGCon); - - long long x_start; - long long x_length; - char* x_string; - char* y_string; - char* backbone; - long long backbone_length; - uint64_t i; - long long y_start, y_length; - long long windowID; - long long startNodeID, endNodeID, currentNodeID; - overlap_region *z; - - - backbone = r_string + window_start; - backbone_length = window_end + 1 - window_start; - - addUnmatchedSeqToGraph(g, backbone, backbone_length, &startNodeID, &endNodeID); - - - long long correct_x_pos_s; - for (i = 0; i < dumy->length; i++) - { - // assert(dumy->overlapID[i]length); - ///this is the overlap ID - z = &(overlap_list->list[dumy->overlapID[i]]); - - correct_x_pos_s = (z->x_pos_s / WINDOW) * WINDOW; - windowID = (window_start - correct_x_pos_s) / WINDOW; - // assert(windowID<(int64_t)z->w_list.n); - - ///if this window is not matched - if (z->w_list.a[windowID].y_end == -1) continue; - - x_start = z->w_list.a[windowID].x_start; - x_length = z->w_list.a[windowID].x_end + 1 - z->w_list.a[windowID].x_start; - - - y_start = z->w_list.a[windowID].y_start; - y_length = z->w_list.a[windowID].y_end + 1 - z->w_list.a[windowID].y_start; - // assert(y_start>=0 && y_start<(int64_t)Get_READ_LENGTH((*R_INF), z->y_id)); - // assert((y_start+y_length)>=0 && (y_start+y_length)<=(int64_t)Get_READ_LENGTH((*R_INF), z->y_id)); - recover_UC_Read_sub_region(dumy->overlap_region, y_start, y_length, z->y_pos_strand, R_INF, z->y_id); - - x_string = r_string + x_start; - y_string = dumy->overlap_region; - ///here is the offset of the start base, also is the node ID - currentNodeID = x_start - window_start; - - // if(window_start == 4500) { - // fprintf(stderr, "[M::%s] window_start::%lld, ovlp_id::%lu, windowID::%lld, x_start::%lld, x_length::%lld, y_start::%lld, y_length::%lld, currentNodeID::%lld\n", __func__, - // window_start, dumy->overlapID[i], windowID, x_start, x_length, y_start, y_length, currentNodeID); - // } - - ///cigar: overlap_list->list[overlapID].w_list[windowID].cigar; - addmatchedSeqToGraph(g, currentNodeID, x_string, x_length, - y_string, y_length, &(z->w_list.a[windowID]), &(z->w_list), startNodeID, endNodeID); - } - - get_seq_from_Graph(g, DAGCon, dumy, current_cigar, backbone, r_string, r_total_length, window_start); -} - - -void add_cigar_to_cigar(Correct_dumy* backbone_dumy, Cigar_record* backbone_cigar, -Round2_alignment* second_round, -long long back_bone_start, long long back_bone_length, -long long new_start, long long new_length) -{ - Correct_dumy* new_dumy = &(second_round->dumy); - Cigar_record* new_cigar = &(second_round->tmp_cigar); - Cigar_record* result_cigar = &(second_round->cigar); - - char* x_string = backbone_dumy->corrected_read + back_bone_start; - char* y_string = new_dumy->corrected_read + new_start; - /** - if(verify_cigar_2(x_string, back_bone_length, y_string, new_length, new_cigar, -1)) - { - fprintf(stderr, "error\n"); - } - **/ - - - ///if type == 0, x_string here is not useful - ///output matches to cigar - add_cigar_record(x_string, back_bone_start - second_round->obtained_cigar_length, result_cigar, 0); - second_round->obtained_cigar_length = back_bone_start + back_bone_length; - - long long i, cigar_i, x_i, y_i; - int operation; - int operationLen; - x_i = y_i = 0; - char merge_base; - - for (i = 0; i < (long long)new_cigar->length; i++) - { - operation = Get_Cigar_Type(new_cigar->record[i]); - operationLen = Get_Cigar_Length(new_cigar->record[i]); - if (operation == 0) - { - ///if type == 0, x_string here is not useful - add_cigar_record(x_string, operationLen, result_cigar, 0); - x_i += operationLen; - y_i += operationLen; - } - else if (operation == 1) - { - for (cigar_i = 0; cigar_i < operationLen; cigar_i++) - { - merge_base = 0; - merge_base = seq_nt6_table[(uint8_t)y_string[y_i]]; - merge_base = merge_base << 3; - merge_base = merge_base | seq_nt6_table[(uint8_t)x_string[x_i]]; - - add_cigar_record(&merge_base, 1, result_cigar, 1); - x_i++; - y_i++; - } - } - else if (operation == INSERTION)///2是x缺字符(y多字符) - { - add_cigar_record(y_string+y_i, operationLen, result_cigar, INSERTION); - y_i += operationLen; - } - else if (operation == DELETION) - { - add_cigar_record(x_string+x_i, operationLen, result_cigar, DELETION); - x_i += operationLen; - } - } -} - -///correct bases of current_dumy->corrected_read in [start_base, end_base] -int merge_cigars(Correct_dumy* current_dumy, Cigar_record* current_cigar, -Round2_alignment* second_round, long long total_start_base, long long total_end_base, -long long total_window_start, long long total_window_end) -{ - Cigar_record* new_cigar = &(second_round->tmp_cigar); - - if(new_cigar->length == 1 && Get_Cigar_Type(new_cigar->record[0]) == 0) - { - return 1; - } - - - long long start_base = total_start_base - total_window_start; - long long end_base = total_end_base - total_window_start; - long long x_i, y_i, cigar_i, i; - x_i = 0; - y_i = 0; - int operation; - int operationLen; - - long long get_x_start, get_x_end, get_y_start, get_y_end; - get_x_start = get_x_end = get_y_start = get_y_end = -1; - - int start_cigar = -1; - int end_cigar = -1; - - ///0 is match, 1 is mismatch, 2 is up, 3 is left - ///obtained x_i may larger than start_base/end_base - ///when operation == 3 - ///so for operation == 3, we need deal with carefully - for (i = 0; i < (long long)new_cigar->length; i++) - { - operation = Get_Cigar_Type(new_cigar->record[i]); - operationLen = Get_Cigar_Length(new_cigar->record[i]); - if (operation == 0) - { - for (cigar_i = 0; cigar_i < operationLen; cigar_i++) - { - if(x_i >= start_base && get_x_start == -1) - { - get_x_start = x_i; - get_y_start = y_i; - start_cigar = i; - } - - - - if(x_i >= end_base && get_x_end == -1) - { - get_x_end = x_i; - get_y_end = y_i; - end_cigar = i; - break; - } - - - - x_i++; - y_i++; - } - } - else if (operation == 1) - { - for (cigar_i = 0; cigar_i < operationLen; cigar_i++) - { - if(x_i >= start_base && get_x_start == -1) - { - get_x_start = x_i; - get_y_start = y_i; - start_cigar = i; - } - - if(x_i >= end_base && get_x_end == -1) - { - get_x_end = x_i; - get_y_end = y_i; - end_cigar = i; - break; - } - - x_i++; - y_i++; - } - } - else if (operation == 2) - { - y_i += operationLen; - } - else if (operation == 3) - { - ///obtained x_i may larger than start_base/end_base - ///when operation == 3 - ///so for operation == 3, we need deal with carefully - x_i += operationLen; - } - } - - ///if there are some gap at the end of x, it very likely miscorrection - if(get_x_end == -1 || get_x_start == -1) - { - return 0; - } - - x_i = 0; - y_i = 0; - - uint32_t single_record = 0; - - for (i = 0; i < (long long)new_cigar->length; i++) - { - operation = Get_Cigar_Type(new_cigar->record[i]); - operationLen = Get_Cigar_Length(new_cigar->record[i]); - - if (i == start_cigar) - { - single_record = 0; - single_record = operationLen - (get_x_start - x_i); - single_record = single_record << 2; - single_record = single_record | operation; - new_cigar->record[i] = single_record; - - if(operation > 1) - { - fprintf(stderr, "error\n"); - } - - if (i == end_cigar) - { - x_i = get_x_start; - single_record = 0; - single_record = get_x_end - x_i + 1; - single_record = single_record << 2; - single_record = single_record | operation; - new_cigar->record[i] = single_record; - if(operation > 1) - { - fprintf(stderr, "error\n"); - } - break; - } - } - else if (i == end_cigar) - { - single_record = 0; - single_record = get_x_end - x_i + 1; - single_record = single_record << 2; - single_record = single_record | operation; - new_cigar->record[i] = single_record; - if(operation > 1) - { - fprintf(stderr, "error\n"); - } - break; - } - - - if (operation == 0 || operation == 1) - { - x_i += operationLen; - y_i += operationLen; - } - else if (operation == 2) - { - y_i += operationLen; - } - else if (operation == 3) - { - x_i += operationLen; - } - } - - new_cigar->length = end_cigar - start_cigar + 1; - ///should be improved - memmove(new_cigar->record, new_cigar->record + start_cigar, new_cigar->length*sizeof(uint32_t)); - - long long total_x_start = total_window_start + get_x_start; - long long x_length = get_x_end -get_x_start + 1; - long long total_y_start = get_y_start; - long long y_length = get_y_end -get_y_start + 1; - - add_cigar_to_cigar(current_dumy, current_cigar, second_round, - total_x_start, x_length, total_y_start, y_length); - - return 1; -} - -int process_boundary(overlap_region_alloc* overlap_list, All_reads* R_INF, Correct_dumy* dumy, Graph* g, Graph* DAGCon, -Cigar_record* current_cigar, long long uncorrected_window_start, Round2_alignment* second_round, window_list_alloc* win_ciagr_buf) -{ - char* r_string = dumy->corrected_read; - long long r_total_length = current_cigar->new_read_length; - long long corrected_window_start, corrected_window_end; - int extra_begin; - int extra_end; - - if(dumy->last_boundary_length == 0) - { - return 0; - } - - corrected_window_start = dumy->last_boundary_length - WINDOW_BOUNDARY/2; - corrected_window_end = dumy->last_boundary_length + WINDOW_BOUNDARY/2 - 1; - - if(corrected_window_start < 0) - { - corrected_window_start = 0; - } - - if (corrected_window_end >= current_cigar->new_read_length) - { - corrected_window_end = current_cigar->new_read_length - 1; - } - - clear_Graph(g); - clear_Graph(DAGCon); - - long long x_start, x_end; - long long x_length, x_len, o_len; - int threshold; - long long Window_Len; - char* x_string = NULL; - char* y_string = NULL; - char* backbone = NULL; - long long backbone_length; - long long i; - long long y_start, y_length; - long long overlapID, windowID; - long long startNodeID, endNodeID, currentNodeID; - int end_site; - unsigned int error; - int real_y_start; - long long total_error = 0; - - backbone = r_string + corrected_window_start; - backbone_length = corrected_window_end - corrected_window_start + 1; - addUnmatchedSeqToGraph(g, backbone, backbone_length, &startNodeID, &endNodeID); - - - long long correct_x_pos_s; - long long matched_coverage = 0; - for (i = 0; i < (long long)dumy->length; i++) - { - overlapID = dumy->overlapID[i]; - correct_x_pos_s = (overlap_list->list[overlapID].x_pos_s / WINDOW) * WINDOW; - windowID = (uncorrected_window_start - correct_x_pos_s) / WINDOW; - - ///skip if window is unmatched - if (overlap_list->list[overlapID].w_list.a[windowID].y_end == -1) - { - continue; - } - - x_start = overlap_list->list[overlapID].w_list.a[windowID].x_start; - y_start = overlap_list->list[overlapID].w_list.a[windowID].y_start; - - - - - /** - * There are total 3 cases: - * 1. this window of x is overlapped fully by y - * x: ------|------|--------- - * y: ------|------|--------- - * in this case, x_start == uncorrected_window_start, x_length == WINDOW - * 2. the suiffx of x's window is overlapped by the prefix of y - * x: ------|------|--------- - * y: |--|----------- - * in this case, x_start > uncorrected_window_start, x_length < WINDOW - * this overlap is useless - * 3. the prefix of x's window is overlapped by y (see last window) - * x: |------|------|-----|--- - * y: |--|-----|------ - * or - * x: |------|------|-----|---- - * y: --|------|------|-----|-- - * - * in this case, x_start == uncorrected_window_start, x_length < WINDOW - * - * case 1 and case 3 are useful, while case 2 is useless - * **/ - - ///case 1 and case 3 are useful - if(x_start == uncorrected_window_start) - { - extra_begin = extra_end = 0; - x_start = corrected_window_start; - x_end = corrected_window_end; - x_len = x_end - x_start + 1; - threshold = x_len * asm_opt.max_ov_diff_ec; - /****************************may have bugs********************************/ - threshold = Adjust_Threshold(threshold, x_len); - /****************************may have bugs********************************/ - ///y_start may less than 0 - y_start = y_start - WINDOW_BOUNDARY/2; - - ///in fact, we don't need this line, just worry for bug - if(y_start < 0) - { - continue; - } - - Window_Len = x_len + (threshold << 1); - - error =(unsigned int)-1; - if(determine_overlap_region(threshold, y_start, overlap_list->list[overlapID].y_id, Window_Len, Get_READ_LENGTH((*R_INF), overlap_list->list[overlapID].y_id), - &extra_begin, &extra_end, &y_start, &o_len)) - { - fill_subregion(dumy->overlap_region, y_start, o_len, overlap_list->list[overlapID].y_pos_strand, - R_INF, overlap_list->list[overlapID].y_id, extra_begin, extra_end); - - x_string = r_string + x_start; - y_string = dumy->overlap_region; - - ///both end site and real_y_start have extra_begin - ///should be improved, since most of overlaps are exact overlaps - ///we can do it quickly - end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, - &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); - } - - - - ///try to calculate using higher threshold - if(error==(unsigned int)-1) - { - extra_begin = extra_end = 0; - x_start = corrected_window_start; - x_end = corrected_window_end; - x_len = x_end - x_start + 1; - threshold = threshold * 2; - /****************************may have bugs********************************/ - threshold = Adjust_Threshold(threshold, x_len); - /****************************may have bugs********************************/ - if(x_len >= 300 && threshold < THRESHOLD_MAX_SIZE) - { - threshold = THRESHOLD_MAX_SIZE; - } - if(threshold > THRESHOLD_MAX_SIZE) - { - threshold = THRESHOLD_MAX_SIZE; - } - Window_Len = x_len + (threshold << 1); - y_start = overlap_list->list[overlapID].w_list.a[windowID].y_start - WINDOW_BOUNDARY/2; - - ///in fact, we don't need this line, just worry for bug - if(y_start < 0) - { - continue; - } - - error =(unsigned int)-1; - if(determine_overlap_region(threshold, y_start, overlap_list->list[overlapID].y_id, Window_Len, Get_READ_LENGTH((*R_INF), overlap_list->list[overlapID].y_id), - &extra_begin, &extra_end, &y_start, &o_len)) - { - fill_subregion(dumy->overlap_region, y_start, o_len, overlap_list->list[overlapID].y_pos_strand, - R_INF, overlap_list->list[overlapID].y_id, extra_begin, extra_end); - - x_string = r_string + x_start; - y_string = dumy->overlap_region; - - ///both end site and real_y_start have extra_begin - ///should be improved, since most of overlaps are exact overlaps - ///we can do it quickly - end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, - &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); - } - } - - if (error!=(unsigned int)-1) - { - - - - total_error = total_error + error; - matched_coverage++; - win_ciagr_buf->a[0].x_start = x_start; win_ciagr_buf->a[0].x_end = x_end; - win_ciagr_buf->c.n = 0; - generate_cigar(dumy->path, dumy->path_length, &(win_ciagr_buf->a[0]), win_ciagr_buf, &real_y_start, &end_site, &error, x_string, x_len, y_string); - ///both end site and real_y_start have extra_begin - real_y_start -= extra_begin; - end_site -= extra_begin; - - y_length = end_site - real_y_start + 1; - y_start = y_start + real_y_start; - - - x_start = corrected_window_start; - x_length = corrected_window_end - x_start + 1; - - ///here can be improved, make y_string = dumy->overlap_region + real_y_start + extra_begin - recover_UC_Read_sub_region(dumy->overlap_region, y_start, y_length, overlap_list->list[overlapID].y_pos_strand, - R_INF, overlap_list->list[overlapID].y_id); - - x_string = r_string + x_start; - y_string = dumy->overlap_region; - - currentNodeID = x_start - corrected_window_start; - - addmatchedSeqToGraph(g, currentNodeID, x_string, x_length, y_string, y_length, &(win_ciagr_buf->a[0]), win_ciagr_buf, startNodeID, endNodeID); - } - - }///case 2 is useless - else if(x_start != uncorrected_window_start) - { - continue; - } - } - - - if(matched_coverage >= MIN_COVERAGE_THRESHOLD) - { - ///if there are no error, we do not need correction - if(total_error == 0) - { - return 0; - } - - clear_Cigar_record(&(second_round->tmp_cigar)); - clear_Correct_dumy_pure(&(second_round->dumy)); - - ///correct bases in [start_base, end_base] - long long start_base = corrected_window_start + WINDOW_UNCORRECT_SINGLE_SIDE_BOUNDARY; - long long end_base = corrected_window_end - WINDOW_UNCORRECT_SINGLE_SIDE_BOUNDARY; - - if(end_base > start_base) - { - ///note there is an additional "S" node - ///and start from i-th node, we can correct (i+1)-th base - /// so the condition when traversing graph is - ///(node >= start_base - corrected_window_start && node <= end_base - corrected_window_start) - get_seq_from_Graph(g, DAGCon, &(second_round->dumy), &(second_round->tmp_cigar), backbone, - r_string, r_total_length, corrected_window_start); - - /** - if(verify_cigar_2(backbone, backbone_length, second_round->dumy.corrected_read, - second_round->dumy.corrected_read_length, &(second_round->tmp_cigar), -1)) - { - fprintf(stderr, "hahah\n"); - } - **/ - - merge_cigars(dumy, current_cigar, second_round, start_base, end_base, - corrected_window_start, corrected_window_end); - - - - } - - } - else - { - return 0; - } - - return 1; - - - -} - - -void generate_consensus(overlap_region_alloc* overlap_list, All_reads* R_INF, - UC_Read* g_read, Correct_dumy* dumy, Graph* g, Graph* DAGCon, Cigar_record* current_cigar, - Round2_alignment* second_round, window_list_alloc* win_ciagr_buf) -{ - clear_Cigar_record(current_cigar); - - long long window_start, window_end; - - long long num_availiable_win = 0; - - - - - Window_Pool w_inf; - init_Window_Pool(&w_inf, g_read->length, WINDOW, (int)(1.0/asm_opt.max_ov_diff_ec)); - - int flag = 0; - ///for last window - dumy->last_boundary_length = 0; - while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) - { - - - - dumy->length = 0; - dumy->lengthNT = 0; - - ///return overlaps that are overlaped with [window_start, window_end] - flag = get_available_interval(window_start, window_end, overlap_list, dumy); - switch (flag) - { - case 1: ///match - break; - case 0: ///unmatch - break; - case -2: ///unmatch, and cannot match for next window - break; - } - - num_availiable_win = num_availiable_win + dumy->length; - - // fprintf(stderr, "[M::%s] window_start::%lld, window_end::%lld, g_read->length::%lld, dumy->length::%lu\n", __func__, - // window_start, window_end, g_read->length, dumy->length); - - ///number of overlaps, also be the coverage - if(dumy->length >= MIN_COVERAGE_THRESHOLD) - { - window_consensus(g_read->seq, g_read->length, window_start, window_end, overlap_list, - dumy, R_INF, g, DAGCon, current_cigar); - - if(dumy->last_boundary_length != 0) - { - process_boundary(overlap_list, R_INF, dumy, g, DAGCon, current_cigar, - window_start, second_round, win_ciagr_buf); - } - - } - else - { - add_segment_to_correct_read(dumy, g_read->seq + window_start, window_end - window_start + 1); - add_cigar_record(g_read->seq + window_start, window_end - window_start + 1, current_cigar, 0); - } - - - dumy->last_boundary_length = current_cigar->new_read_length; - } - - if (window_start < g_read->length) - { - add_segment_to_correct_read(dumy, g_read->seq + window_start, g_read->length - window_start); - add_cigar_record(g_read->seq + window_start, g_read->length - window_start, current_cigar, 0); - } - - ///if type == 0, x_string here is not useful - ///output matches to cigar - if (current_cigar->new_read_length != second_round->obtained_cigar_length) - { - add_cigar_record(dumy->corrected_read, current_cigar->new_read_length - second_round->obtained_cigar_length, - &(second_round->cigar), 0); - } -} - - -inline int get_available_fully_covered_interval(long long window_start, long long window_end, -overlap_region_alloc* overlap_list, Correct_dumy* dumy, long long* real_length, long long* real_length_100) -{ - long long i, fud = 0; - long long Len; - long long overlap_length; - - if(window_start == 0) dumy->start_i = 0; - for (i = dumy->start_i; i < (long long)overlap_list->length; i++) - { - if (window_end < (long long)overlap_list->list[i].x_pos_s) - { - dumy->start_i = 0; - return 0; - } - else - { - dumy->start_i = i; - break; - } - } - - - if (i >= (long long)overlap_list->length) - { - dumy->start_i = overlap_list->length; - return -2; - } - - - - - - long long fake_length = 0; - overlap_length = window_end - window_start + 1; - (*real_length) = 0; fud = 0; - - for (; i < (long long)overlap_list->length; i++) - { - if((Len = OVERLAP(window_start, window_end, (long long)overlap_list->list[i].x_pos_s, (long long)overlap_list->list[i].x_pos_e)) > 0) - { - fake_length++; - - if (overlap_length == Len && overlap_list->list[i].is_match == 1) - { - (*real_length)++; - } - - if (overlap_length == Len && overlap_list->list[i].is_match == 100) - { - (*real_length_100)++; - } - if(fud == 0) fud = 1, dumy->start_i = i; - } - - if((long long)overlap_list->list[i].x_pos_s > window_end) - { - break; - } - } - - if (fake_length == 0) - { - return 0; - } - else - { - return 1; - } -} - -int check_if_fully_covered(overlap_region_alloc* overlap_list, -All_reads* R_INF, UC_Read* g_read, Correct_dumy* dumy, Graph* g, int* abnormal) -{ - long long window_start, window_end; - int return_flag = 1; - (*abnormal) = 0; - - Window_Pool w_inf; - init_Window_Pool(&w_inf, g_read->length, WINDOW, (int)(1.0/asm_opt.max_ov_diff_ec)); - - int flag = 0; - long long realLen = 0, tmpLen = 0; - while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) - { - dumy->length = 0; - dumy->lengthNT = 0; - - ///return overlaps that are overlaped with [window_start, window_end] - flag = get_available_fully_covered_interval(window_start, window_end, - overlap_list, dumy, &realLen, &tmpLen); - - - switch (flag) - { - case 1: ///match - break; - case 0: ///unmatch - break; - case -2: ///unmatch, and cannot match for next window - break; - } - - if(realLen < MIN_COVERAGE_THRESHOLD * 2) - { - return_flag = 0; - //return 0; - } - - if(realLen == 0) - { - ///that means this window is a middle window - if(window_start != 0 && window_end != g_read->length - 1) - { - (*abnormal) = 1; - } - else if((*abnormal)==0) - { - (*abnormal) = 2; - } - } - } - - return return_flag; -} - -///mark SNPs at [xBeg, xEnd], note we need to deal with flag_offset carefully -void markSNP_detail(window_list *cigar_idx, window_list_alloc *cigar_s, uint8_t* flag, -long long xBeg, long long xEnd, long long flag_offset, const ul_idx_t *uref, long long y_total_start, int y_strand, int yid) -{ - if(xBeg > xEnd) return; - - int64_t x_i, y_i, c_i, c_n = cigar_idx->clen, pi = 0, cc = 0; - uint32_t i, operLen = (uint32_t)-1; uint8_t oper = (uint8_t)-1; - i = c_i = x_i = y_i = 0; - for (c_i = 0; c_i < c_n; c_i++) { - get_cigar_cell(cigar_idx, cigar_s, c_i, &oper, &operLen); - if(x_i > xEnd) break; - - if (oper == 0) {///match - x_i += operLen; y_i += operLen; - } - else if(oper == 1) {///mismatch - for (i = 0; i < operLen; i++) { - /// note we need to deal with flag_offset carefully - ///if(flag[x_i - flag_offset] < 127 && x_i >= xBeg && x_i <= xEnd) - if(x_i >= xBeg && x_i <= xEnd && flag[x_i - flag_offset] < 127) {///Fix-attention - if(uref) { - cc = retrieve_u_cov(uref, yid, y_strand, y_total_start + y_i, y_strand, &pi); - cc += flag[x_i - flag_offset]; - flag[x_i - flag_offset] = (cc <= 127?cc:127); - // if(cc <= 127) flag[x_i - flag_offset] = cc; - } else { - flag[x_i - flag_offset]++; - } - } - x_i++; y_i++; - } - } else if (oper == 2) {///insertion, that means y has more bases than x - y_i += operLen; - } - else if (oper == 3) { - x_i += operLen; - } - } -} - - -///window_offset is still the x-based offset -///x_total_start and y_total_start are global positions, instead of local positions -void markSNP_advance( -long long window_offset, -long long x_total_start, long long x_length, -long long y_total_start, long long y_length, -window_list *current_cigar, window_list_alloc *current_cigar_s, -window_list *beg_cigar, window_list_alloc *beg_cigar_s, -window_list *end_cigar, window_list_alloc *end_cigar_s, -haplotype_evdience_alloc* hap, const ul_idx_t *uref, int strand, int yid) -{ - long long x_total_end = x_total_start + x_length - 1; - ///mismatches based on the offset of x - long long inner_offset = x_total_start - window_offset; - ///long long useless_side, xleftLen, xrightLen, x_interval_beg, x_interval_end; - long long L_useless_side, R_useless_side, xleftLen, xrightLen, x_interval_beg, x_interval_end; - long long current_cigar_beg, current_cigar_end; - - ///for current_cigar, [current_cigar_beg, current_cigar_end] - current_cigar_beg = 0; - current_cigar_end = x_length - 1; - ///if the beg_cigar is available - if(beg_cigar != NULL && beg_cigar->y_end!=-1) - { - ///useless_side = beg_cigar->error_threshold; - L_useless_side = beg_cigar->extra_begin; - R_useless_side = beg_cigar->extra_end; - ///again, xleftLen does not include x_total_start itself, but includes beg_cigar->x_start - xleftLen = x_total_start - beg_cigar->x_start; - ///xrightLen includes both x_total_start and beg_cigar->x_end - xrightLen = beg_cigar->x_end - x_total_start + 1; - ///actually xleftLen could be no larger than useless_side - ///but such window has already been filtered out at calculate_boundary_cigars - ///if(xleftLen > useless_side && xrightLen > useless_side) - if(xleftLen > L_useless_side && xrightLen > R_useless_side) - { - ///[x_interval_beg, x_interval_end] are the offsets to beg_cigar->x_start - ///they are local postions, instead of global positions - - x_interval_beg = xleftLen; - //x_interval_end = x_interval_beg + (xrightLen - useless_side) - 1; - x_interval_end = x_interval_beg + (xrightLen - R_useless_side) - 1; - ///current_cigar_beg is the offset of the current cigar - ///that is the beg of current_cigar_beg - ///current_cigar_beg = xrightLen - useless_side; - current_cigar_beg = xrightLen - R_useless_side; - - markSNP_detail(beg_cigar, beg_cigar_s, hap->flag + inner_offset, x_interval_beg, x_interval_end, - x_interval_beg, uref, beg_cigar->y_start, strand, yid); - } - } - - if(end_cigar!=NULL && end_cigar->y_end!=-1) - { - ///useless_side = end_cigar->error_threshold; - L_useless_side = end_cigar->extra_begin; - R_useless_side = end_cigar->extra_end; - ///again, xleftLen does not include x_total_end, but includes end_cigar->x_start - ///it seems to be not what we want - xleftLen = x_total_end - end_cigar->x_start; - ///xrightLen includes both x_total_end and end_cigar->x_end - ///it is also not what we want - xrightLen = end_cigar->x_end - x_total_end + 1; - ///we hope that x_total_end should be included in xleftLen, instead of xrightLen - ///that means xleftLen should + 1, while xrightLen should -1 - ///but it is fine here - - ///actually xrightLen could be no larger than useless_side - ///but such window has already been filtered out in calculate_boundary_cigars - ///if(xleftLen > useless_side && xrightLen > useless_side) - if(xleftLen > L_useless_side && xrightLen > R_useless_side) - { - ///[x_interval_beg, x_interval_end] are the offsets to beg_cigar->x_start - ///they are local postions, instead of global positions - x_interval_end = xleftLen; - ///the real left part length is (xleftLen + 1) - ///so the useful left part length is ((xleftLen + 1) - useless_side) - ///x_interval_beg = x_interval_end - ((xleftLen + 1) - useless_side) + 1; - x_interval_beg = x_interval_end - ((xleftLen + 1) - L_useless_side) + 1; - ///current_cigar_end = (x_length - 1) - ((xleftLen + 1) - useless_side); - current_cigar_end = (x_length - 1) - ((xleftLen + 1) - L_useless_side); - - markSNP_detail(end_cigar, end_cigar_s, hap->flag + end_cigar->x_start - window_offset, x_interval_beg, - x_interval_end, 0, uref, end_cigar->y_start, strand, yid); - } - } - - markSNP_detail(current_cigar, current_cigar_s, hap->flag + inner_offset, current_cigar_beg, - current_cigar_end, 0, uref, current_cigar->y_start, strand, yid); -} - - - -/** -void addSNPtohaplotype( -long long window_offset, int overlapID, -char* x_string, long long x_total_start, long long x_length, -char* y_string, long long y_total_start, long long y_length, -CIGAR* cigar, haplotype_evdience_alloc* hap, int snp_threshold) -{ - - int x_i, y_i, cigar_i; - x_i = 0; - y_i = 0; - cigar_i = 0; - int operation; - int operationLen; - int i; - long long inner_offset = x_total_start - window_offset; - haplotype_evdience ev; - - ///note that node 0 is the start node - ///0 is match, 1 is mismatch, 2 is up, 3 is left - ///2 represents thre are more bases at y - ///3 represents thre are more bases at x - while (cigar_i < cigar->length) - { - operation = cigar->C_C[cigar_i]; - operationLen = cigar->C_L[cigar_i]; - - ///matches - if (operation == 0) - { - for (i = 0; i < operationLen; i++) - { - ///should be at least 2 mismatches - if(hap->flag[inner_offset] > snp_threshold) - { - ev.misBase = y_string[y_i]; - ev.overlapID = overlapID; - ev.site = x_total_start + x_i; - ev.overlapSite = y_total_start + y_i; - ev.type = 0; - addHaplotypeEvdience(hap, &ev, NULL); - } - - - inner_offset++; - x_i++; - y_i++; - } - - } - else if(operation == 1) - { - for (i = 0; i < operationLen; i++) - { - - if(hap->flag[inner_offset] > snp_threshold) - { - ev.misBase = y_string[y_i]; - ev.overlapID = overlapID; - ev.site = x_total_start + x_i; - ev.overlapSite = y_total_start + y_i; - ev.type = 1; - addHaplotypeEvdience(hap, &ev, NULL); - } - - inner_offset++; - x_i++; - y_i++; - } - }///insertion - else if (operation == 2) - { - y_i += operationLen; - } - else if (operation == 3) - { - //may have bugs - for (i = 0; i < operationLen; i++) - { - if(hap->flag[inner_offset] > snp_threshold) - { - ev.misBase = 'N'; - ev.overlapID = overlapID; - ev.site = x_total_start + x_i; - ev.overlapSite = y_total_start + y_i; - ev.type = 2; - addHaplotypeEvdience(hap, &ev, NULL); - } - - inner_offset++; - x_i++; - } - //may have bugs - } - - cigar_i++; - } -} -**/ - - -///mark SNPs at [xBeg, xEnd], note we need to deal with flag_offset carefully -void addSNPtohaplotype_details(window_list *cigar_idx, window_list_alloc *cigar_s, uint8_t* flag, -char* x_string, char* y_string, long long x_total_start, long long y_total_start, -long long xBeg, long long xEnd, int overlapID, long long flag_offset, -haplotype_evdience_alloc* hap, long long snp_threshold, const ul_idx_t *uref, int y_strand, int yid, void *km) -{ - if(xBeg > xEnd) return; - int64_t x_i, y_i, c_i, pi = 0, c_n = cigar_idx->clen; - uint32_t i, operLen = (uint32_t)-1; uint8_t oper = (uint8_t)-1; i = c_i = x_i = y_i = 0; - haplotype_evdience ev; - - ///note that node 0 is the start node - ///0 is match, 1 is mismatch, 2 is up, 3 is left - ///2 represents thre are more bases at y - ///3 represents thre are more bases at x - for (c_i = 0; c_i < c_n; c_i++) { - get_cigar_cell(cigar_idx, cigar_s, c_i, &oper, &operLen); - if(x_i > xEnd) break; - - if (oper == 0) { ///matches - for (i = 0; i < operLen; i++) { - ///should be at least 2 mismatches - /// note we need to deal with flag_offset carefully - ///if(flag[x_i - flag_offset] > snp_threshold && x_i >= xBeg && x_i <= xEnd) - if(x_i >= xBeg && x_i <= xEnd && flag[x_i - flag_offset] > snp_threshold) { - ev.misBase = y_string[y_i]; - ev.overlapID = overlapID; - ev.site = x_total_start + x_i; - ev.overlapSite = y_total_start + y_i; - ev.type = 0; - ev.cov = uref?retrieve_u_cov(uref, yid, y_strand, y_total_start + y_i, y_strand, &pi):1; - addHaplotypeEvdience(hap, &ev, km); - } - ///inner_offset++; - x_i++; y_i++; - } - } - else if(oper == 1) { - for (i = 0; i < operLen; i++) { - /// should be at least 2 mismatches - /// note we need to deal with flag_offset carefully - ///if(flag[x_i - flag_offset] > snp_threshold && x_i >= xBeg && x_i <= xEnd) - if(x_i >= xBeg && x_i <= xEnd && flag[x_i - flag_offset] > snp_threshold) { - ev.misBase = y_string[y_i]; - ev.overlapID = overlapID; - ev.site = x_total_start + x_i; - ev.overlapSite = y_total_start + y_i; - ev.type = 1; - ev.cov = uref?retrieve_u_cov(uref, yid, y_strand, y_total_start + y_i, y_strand, &pi):1; - addHaplotypeEvdience(hap, &ev, km); - } - ///inner_offset++; - x_i++; y_i++; - } - }///insertion, 2 represents thre are more bases at y - else if (oper == 2) { - y_i += operLen; - }///3 represents thre are more bases at x - else if (oper == 3) { - /****************************may have bugs********************************/ - for (i = 0; i < operLen; i++) { - ///if(hap->flag[inner_offset] > snp_threshold) - /// should be at least 2 mismatches - /// note we need to deal with flag_offset carefully - ///if(flag[x_i - flag_offset] > snp_threshold && x_i >= xBeg && x_i <= xEnd) - if(x_i >= xBeg && x_i <= xEnd && flag[x_i - flag_offset] > snp_threshold) { - ev.misBase = 'N'; - ev.overlapID = overlapID; - ev.site = x_total_start + x_i; - ev.overlapSite = y_total_start + y_i; - ev.type = 2; - ev.cov = uref?retrieve_u_cov(uref, yid, y_strand, y_total_start + y_i, y_strand, &pi):1; - addHaplotypeEvdience(hap, &ev, km); - } - - ///inner_offset++; - x_i++; - } - /****************************may have bugs********************************/ - } - } -} - - -void addSNPtohaplotype_advance( -long long window_offset, int overlapID, -long long x_total_start, long long x_length, -long long y_total_start, long long y_length, -window_list* current_cigar, window_list_alloc *current_cigar_s, -window_list* beg_cigar, window_list_alloc *beg_cigar_s, -window_list* end_cigar, window_list_alloc *end_cigar_s, -haplotype_evdience_alloc* hap, int snp_threshold, char* x_T_string, char* y_T_string, const ul_idx_t *uref, int strand, int yid, void *km) -{ - long long x_total_end = x_total_start + x_length - 1; - long long inner_offset = x_total_start - window_offset; - ///long long useless_side, xleftLen, xrightLen, x_interval_beg, x_interval_end; - long long L_useless_side, R_useless_side, xleftLen, xrightLen, x_interval_beg, x_interval_end; - long long current_cigar_beg, current_cigar_end; - - ///for current_cigar, [current_cigar_beg, current_cigar_end] - current_cigar_beg = 0; - current_cigar_end = x_length - 1; - ///if the beg_cigar is available - if(beg_cigar != NULL && beg_cigar->y_end!=-1) - { - ///useless_side = beg_cigar->error_threshold; - L_useless_side = beg_cigar->extra_begin; - R_useless_side = beg_cigar->extra_end; - ///again, xleftLen does not include x_total_start itself, but includes beg_cigar->x_start - xleftLen = x_total_start - beg_cigar->x_start; - ///xrightLen includes both x_total_start and beg_cigar->x_end - xrightLen = beg_cigar->x_end - x_total_start + 1; - ///actually xleftLen could be no larger than useless_side - ///but such window has already been filtered out at calculate_boundary_cigars - ///if(xleftLen > useless_side && xrightLen > useless_side) - if(xleftLen > L_useless_side && xrightLen > R_useless_side) { - ///[x_interval_beg, x_interval_end] are the offsets to beg_cigar->x_start - ///they are local postions, instead of global positions - - x_interval_beg = xleftLen; - ///x_interval_end = x_interval_beg + (xrightLen - useless_side) - 1; - x_interval_end = x_interval_beg + (xrightLen - R_useless_side) - 1; - ///current_cigar_beg is the offset of the current cigar - ///that is the beg of current_cigar_beg - ///current_cigar_beg = xrightLen - useless_side; - current_cigar_beg = xrightLen - R_useless_side; - - // markSNP_detail(cigar_record, hap->flag + inner_offset, x_interval_beg, - // x_interval_end, x_interval_beg); - addSNPtohaplotype_details(beg_cigar, beg_cigar_s, hap->flag + inner_offset, - x_T_string + beg_cigar->x_start, y_T_string + beg_cigar->y_start, - beg_cigar->x_start, beg_cigar->y_start, x_interval_beg, x_interval_end, - overlapID, x_interval_beg, hap, snp_threshold, uref, strand, yid, km); - } - } - - - if(end_cigar!=NULL && end_cigar->y_end!=-1) - { - ///useless_side = end_cigar->error_threshold; - L_useless_side = end_cigar->extra_begin; - R_useless_side = end_cigar->extra_end; - ///again, xleftLen does not include x_total_end, but includes end_cigar->x_start - ///it seems to be not what we want - xleftLen = x_total_end - end_cigar->x_start; - ///xrightLen includes both x_total_end and end_cigar->x_end - ///it is also not what we want - xrightLen = end_cigar->x_end - x_total_end + 1; - ///we hope that x_total_end should be included in xleftLen, instead of xrightLen - ///that means xleftLen should + 1, while xrightLen should -1 - ///but it is fine here - - ///actually xrightLen could be no larger than useless_side - ///but such window has already been filtered out in calculate_boundary_cigars - ///if(xleftLen > useless_side && xrightLen > useless_side) - if(xleftLen > L_useless_side && xrightLen > R_useless_side) - { - ///[x_interval_beg, x_interval_end] are the offsets to beg_cigar->x_start - ///they are local postions, instead of global positions - x_interval_end = xleftLen; - ///the real left part length is (xleftLen + 1) - ///so the useful left part length is ((xleftLen + 1) - useless_side) - ///x_interval_beg = x_interval_end - ((xleftLen + 1) - useless_side) + 1; - x_interval_beg = x_interval_end - ((xleftLen + 1) - L_useless_side) + 1; - ///current_cigar_end = (x_length - 1) - ((xleftLen + 1) - useless_side); - current_cigar_end = (x_length - 1) - ((xleftLen + 1) - L_useless_side); - - // markSNP_detail(cigar_record, hap->flag + end_cigar->x_start - window_offset, - // x_interval_beg, x_interval_end, 0); - addSNPtohaplotype_details(end_cigar, end_cigar_s, hap->flag + end_cigar->x_start - window_offset, - x_T_string + end_cigar->x_start, y_T_string + end_cigar->y_start, - end_cigar->x_start, end_cigar->y_start, x_interval_beg, x_interval_end, - overlapID, 0, hap, snp_threshold, uref, strand, yid, km); - } - } - - // markSNP_detail(&(current_cigar->cigar), hap->flag + inner_offset, current_cigar_beg, - // current_cigar_end, 0); - addSNPtohaplotype_details(current_cigar, current_cigar_s, hap->flag + inner_offset, - x_T_string + current_cigar->x_start, y_T_string + current_cigar->y_start, - current_cigar->x_start, current_cigar->y_start, current_cigar_beg, - current_cigar_end, overlapID, 0, hap, snp_threshold, uref, strand, yid, km); -} - -/** -void cluster(char* r_string, long long window_start, long long window_end, -overlap_region_alloc* overlap_list, Correct_dumy* dumy, All_reads* R_INF, haplotype_evdience_alloc* hap) -{ - ///window_start, window_end, and useful_length correspond to x, instead of y - long long useful_length = window_end - window_start + 1; - long long x_start; - long long x_length; - char* x_string; - char* y_string; - long long i; - long long y_start, y_length; - long long overlapID, windowID; - - long long correct_x_pos_s; - int snp_threshold; - snp_threshold = 1; - - ///all overlaps related to the current window [window_start, window_end] - ///first mark all snp pos - for (i = 0; i < (long long)dumy->length; i++) - { - ///overlap id, instead of the window id or the y id - overlapID = dumy->overlapID[i]; - - ///overlap_list->list[overlapID].x_pos_s is the begining of the whole overlap - correct_x_pos_s = (overlap_list->list[overlapID].x_pos_s / WINDOW) * WINDOW; - ///window_start is the begining of this window in the whole x_read - windowID = (window_start - correct_x_pos_s) / WINDOW; - - ///skip if this window is not matched - if (overlap_list->list[overlapID].w_list[windowID].y_end == -1) - { - continue; - } - - ///both x_start and y_start are the offsets of the whole x_read and y_read - ///instead of the offsets of window - x_start = overlap_list->list[overlapID].w_list[windowID].x_start; - x_length = overlap_list->list[overlapID].w_list[windowID].x_end - - overlap_list->list[overlapID].w_list[windowID].x_start + 1; - - y_start = overlap_list->list[overlapID].w_list[windowID].y_start; - y_length = overlap_list->list[overlapID].w_list[windowID].y_end - - overlap_list->list[overlapID].w_list[windowID].y_start + 1; - - - markSNP(window_start, x_start, x_length, y_start, y_length, - &(overlap_list->list[overlapID].w_list[windowID].cigar), hap); - } - - - //may have bugs - long long last_snp = -1; - long long first_snp = -1; - for (i = 0; i < useful_length; i++) - { - if(hap->flag[i] != 0) - { - last_snp = i; - if(first_snp == -1) - { - first_snp = i; - } - } - ///for a real snp, the coverage should be at least 2 - if(hap->flag[i] > snp_threshold) - { - // hap->snp++; - hap->nn_snp++; - } - } - ///if there are any >0 elements, both first_snp and last_snp should be != -1 - if(first_snp == -1 || last_snp == -1) - { - first_snp = 0; - last_snp = -1; - } - //may have bugs - - - - ///add the information related to snp to haplotype_evdience_alloc - for (i = 0; i < (long long)dumy->length; i++) - { - ///overlap ID, instead of the window ID - overlapID = dumy->overlapID[i]; - - ///overlap_list->list[overlapID].x_pos_s is the begining of the whole overlap - correct_x_pos_s = (overlap_list->list[overlapID].x_pos_s / WINDOW) * WINDOW; - ///window_start is the begining of this window in the whole x_read - windowID = (window_start - correct_x_pos_s) / WINDOW; - - ///skip if this window is not matched - if (overlap_list->list[overlapID].w_list[windowID].y_end == -1) - { - continue; - } - - ///both x_start and y_start are the offsets of the whole x_read and y_read - ///instead of the offsets of window - x_start = overlap_list->list[overlapID].w_list[windowID].x_start; - x_length = overlap_list->list[overlapID].w_list[windowID].x_end - - overlap_list->list[overlapID].w_list[windowID].x_start + 1; - - y_start = overlap_list->list[overlapID].w_list[windowID].y_start; - y_length = overlap_list->list[overlapID].w_list[windowID].y_end - - overlap_list->list[overlapID].w_list[windowID].y_start + 1; - - - recover_UC_Read_sub_region(dumy->overlap_region, y_start, y_length, overlap_list->list[overlapID].y_pos_strand, - R_INF, overlap_list->list[overlapID].y_id); - - x_string = r_string + x_start; - y_string = dumy->overlap_region; - - - addSNPtohaplotype(window_start, overlapID, x_string, x_start, x_length, - y_string, y_start, y_length, &(overlap_list->list[overlapID].w_list[windowID].cigar), - hap, snp_threshold); - } - - RsetInitHaplotypeEvdienceFlag(hap, first_snp, last_snp + 1 - first_snp); -} -**/ - - -void get_related_cigars(window_list_alloc* boundary_cigars, long long id, window_list** beg_cigar, -window_list** end_cigar) -{ - (*beg_cigar) = &(boundary_cigars->a[id*2]); - (*end_cigar) = &(boundary_cigars->a[id*2+1]); -} - -int cmp_haplotype_evdience(const void * a, const void * b) -{ - if ((*(haplotype_evdience*)a).site != (*(haplotype_evdience*)b).site) - { - return (*(haplotype_evdience*)a).site > (*(haplotype_evdience*)b).site ? 1 : -1; - } - else - { - if ((*(haplotype_evdience*)a).type != (*(haplotype_evdience*)b).type) - { - return (*(haplotype_evdience*)a).type > (*(haplotype_evdience*)b).type ? 1 : -1; - } - else - { - if ((*(haplotype_evdience*)a).misBase != (*(haplotype_evdience*)b).misBase) - { - return (*(haplotype_evdience*)a).misBase > (*(haplotype_evdience*)b).misBase ? 1 : -1; - } - else - { - return 0; - } - - } - - } - - -} - -void cluster_advance(char* r_string, long long window_start, long long window_end, -overlap_region_alloc* overlap_list, Correct_dumy* dumy, All_reads* R_INF, -haplotype_evdience_alloc* hap, UC_Read* overlap_read, int snp_threshold) -{ - window_list* beg_cigar; - window_list* end_cigar; - ///window_start, window_end, and useful_length correspond to x, instead of y - long long useful_length = window_end - window_start + 1; - long long x_start, x_length, ll = hap->length, lr; - char* x_string; - char* y_string; - long long i; - long long y_start, y_length; - long long overlapID, windowID; - - long long correct_x_pos_s; - - - ///all overlaps related to the current window [window_start, window_end] - ///first mark all snp pos - for (i = 0; i < (long long)dumy->length; i++) - { - ///overlap id, instead of the window id or the y id - overlapID = dumy->overlapID[i]; - - ///overlap_list->list[overlapID].x_pos_s is the begining of the whole overlap - correct_x_pos_s = (overlap_list->list[overlapID].x_pos_s / WINDOW) * WINDOW; - ///window_start is the begining of this window in the whole x_read - windowID = (window_start - correct_x_pos_s) / WINDOW; - - ///skip if this window is not matched - if (overlap_list->list[overlapID].w_list.a[windowID].y_end == -1) - { - continue; - } - - ///both x_start and y_start are the offsets of the whole x_read and y_read - ///instead of the offsets of window - x_start = overlap_list->list[overlapID].w_list.a[windowID].x_start; - x_length = overlap_list->list[overlapID].w_list.a[windowID].x_end + 1 - - overlap_list->list[overlapID].w_list.a[windowID].x_start; - - y_start = overlap_list->list[overlapID].w_list.a[windowID].y_start; - y_length = overlap_list->list[overlapID].w_list.a[windowID].y_end + 1 - - overlap_list->list[overlapID].w_list.a[windowID].y_start; - - beg_cigar = end_cigar = NULL; - - if(windowID >= 1) - { - beg_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID-1]); - } - - if(windowID < (long long)(overlap_list->list[overlapID].w_list.n) - 1) - { - end_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID]); - } - - - markSNP_advance(window_start, x_start, x_length, y_start, y_length, - &(overlap_list->list[overlapID].w_list.a[windowID]), &(overlap_list->list[overlapID].w_list), - beg_cigar, &(overlap_list->list[overlapID].boundary_cigars), - end_cigar, &(overlap_list->list[overlapID].boundary_cigars), hap, NULL, - overlap_list->list[overlapID].y_pos_strand, overlap_list->list[overlapID].y_id); - } - - - /****************************may have bugs********************************/ - long long last_snp = -1; - long long first_snp = -1; - for (i = 0, lr = 0; i < useful_length; i++) - { - if(hap->flag[i] != 0) - { - last_snp = i; - if(first_snp == -1) - { - first_snp = i; - } - } - ///for a real snp, the coverage should be at least 2 - if(hap->flag[i] > snp_threshold) - { - // hap->snp++; - hap->nn_snp++; - lr++; - } - } - ///if there are any >0 elements, both first_snp and last_snp should be != -1 - if(first_snp == -1 || last_snp == -1) - { - first_snp = 0; - last_snp = -1; - } - /****************************may have bugs********************************/ - - - - ///add the information related to snp to haplotype_evdience_alloc - for (i = 0; i < (long long)dumy->length; i++) - { - ///overlap ID, instead of the window ID - overlapID = dumy->overlapID[i]; - - ///overlap_list->list[overlapID].x_pos_s is the begining of the whole overlap - correct_x_pos_s = (overlap_list->list[overlapID].x_pos_s / WINDOW) * WINDOW; - ///window_start is the begining of this window in the whole x_read - windowID = (window_start - correct_x_pos_s) / WINDOW; - - ///skip if this window is not matched - if (overlap_list->list[overlapID].w_list.a[windowID].y_end == -1) - { - continue; - } - - ///both x_start and y_start are the offsets of the whole x_read and y_read - ///instead of the offsets of window - x_start = overlap_list->list[overlapID].w_list.a[windowID].x_start; - x_length = overlap_list->list[overlapID].w_list.a[windowID].x_end - - overlap_list->list[overlapID].w_list.a[windowID].x_start + 1; - - y_start = overlap_list->list[overlapID].w_list.a[windowID].y_start; - y_length = overlap_list->list[overlapID].w_list.a[windowID].y_end - - overlap_list->list[overlapID].w_list.a[windowID].y_start + 1; - - - if(overlap_list->list[overlapID].y_pos_strand == 0) - { - recover_UC_Read(overlap_read, R_INF, overlap_list->list[overlapID].y_id); - } - else - { - recover_UC_Read_RC(overlap_read, R_INF, overlap_list->list[overlapID].y_id); - } - - x_string = r_string; - y_string = overlap_read->seq; - - - beg_cigar = end_cigar = NULL; - if(windowID >= 1) - { - beg_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID-1]); - } - if(windowID < (long long)(overlap_list->list[overlapID].w_list.n) - 1) - { - end_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID]); - } - - - addSNPtohaplotype_advance(window_start, overlapID, x_start, x_length, y_start, y_length, - &(overlap_list->list[overlapID].w_list.a[windowID]), &(overlap_list->list[overlapID].w_list), - beg_cigar, &(overlap_list->list[overlapID].boundary_cigars), - end_cigar, &(overlap_list->list[overlapID].boundary_cigars), - hap, snp_threshold, x_string, y_string, NULL, overlap_list->list[overlapID].y_pos_strand, - overlap_list->list[overlapID].y_id, NULL); - } - - RsetInitHaplotypeEvdienceFlag(hap, first_snp, last_snp + 1 - first_snp); - - if(hap->length - ll > 1 && lr > 1) radix_sort_haplotype_evdience_srt(hap->list+ll, hap->list + hap->length); -} - -void cluster_ul_advance(char* r_string, long long window_start, long long window_end, -overlap_region_alloc* overlap_list, Correct_dumy* dumy, const ul_idx_t *uref, -haplotype_evdience_alloc* hap, UC_Read* overlap_read, int snp_threshold, long long blockLen, void *km) -{ - window_list* beg_cigar; - window_list* end_cigar; - ///window_start, window_end, and useful_length correspond to x, instead of y - long long useful_length = window_end - window_start + 1; - long long x_start, x_length, ll = hap->length, lr; - char* x_string; - char* y_string; - long long i; - long long y_start, y_length; - long long overlapID, windowID; - - long long correct_x_pos_s; - - - ///all overlaps related to the current window [window_start, window_end] - ///first mark all snp pos - for (i = 0; i < (long long)dumy->length; i++) - { - ///overlap id, instead of the window id or the y id - overlapID = dumy->overlapID[i]; - - ///overlap_list->list[overlapID].x_pos_s is the begining of the whole overlap - correct_x_pos_s = (overlap_list->list[overlapID].x_pos_s / blockLen) * blockLen; - ///window_start is the begining of this window in the whole x_read - windowID = (window_start - correct_x_pos_s) / blockLen; - - ///skip if this window is not matched - if (overlap_list->list[overlapID].w_list.a[windowID].y_end == -1) - { - continue; - } - - ///both x_start and y_start are the offsets of the whole x_read and y_read - ///instead of the offsets of window - x_start = overlap_list->list[overlapID].w_list.a[windowID].x_start; - x_length = overlap_list->list[overlapID].w_list.a[windowID].x_end - - overlap_list->list[overlapID].w_list.a[windowID].x_start + 1; - - y_start = overlap_list->list[overlapID].w_list.a[windowID].y_start; - y_length = overlap_list->list[overlapID].w_list.a[windowID].y_end - - overlap_list->list[overlapID].w_list.a[windowID].y_start + 1; - - beg_cigar = end_cigar = NULL; - - if(windowID >= 1) - { - beg_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID-1]); - } - - if(windowID < (long long)(overlap_list->list[overlapID].w_list.n) - 1) - { - end_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID]); - } - - - markSNP_advance(window_start, x_start, x_length, y_start, y_length, - &(overlap_list->list[overlapID].w_list.a[windowID]), &(overlap_list->list[overlapID].w_list), - beg_cigar, &(overlap_list->list[overlapID].boundary_cigars), - end_cigar, &(overlap_list->list[overlapID].boundary_cigars), - hap, uref, overlap_list->list[overlapID].y_pos_strand, overlap_list->list[overlapID].y_id); - } - - - /****************************may have bugs********************************/ - long long last_snp = -1; - long long first_snp = -1; - for (i = 0, lr = 0; i < useful_length; i++) - { - if(hap->flag[i] != 0) - { - last_snp = i; - if(first_snp == -1) - { - first_snp = i; - } - } - ///for a real snp, the coverage should be at least 2 - if(hap->flag[i] > snp_threshold) - { - // hap->snp++; - hap->nn_snp++; - lr++; - } - } - ///if there are any >0 elements, both first_snp and last_snp should be != -1 - if(first_snp == -1 || last_snp == -1) - { - first_snp = 0; - last_snp = -1; - } - /****************************may have bugs********************************/ - - - - ///add the information related to snp to haplotype_evdience_alloc - for (i = 0; i < (long long)dumy->length; i++) - { - ///overlap ID, instead of the window ID - overlapID = dumy->overlapID[i]; - - ///overlap_list->list[overlapID].x_pos_s is the begining of the whole overlap - correct_x_pos_s = (overlap_list->list[overlapID].x_pos_s / blockLen) * blockLen; - ///window_start is the begining of this window in the whole x_read - windowID = (window_start - correct_x_pos_s) / blockLen; - - ///skip if this window is not matched - if (overlap_list->list[overlapID].w_list.a[windowID].y_end == -1) - { - continue; - } - - ///both x_start and y_start are the offsets of the whole x_read and y_read - ///instead of the offsets of window - x_start = overlap_list->list[overlapID].w_list.a[windowID].x_start; - x_length = overlap_list->list[overlapID].w_list.a[windowID].x_end - - overlap_list->list[overlapID].w_list.a[windowID].x_start + 1; - - y_start = overlap_list->list[overlapID].w_list.a[windowID].y_start; - y_length = overlap_list->list[overlapID].w_list.a[windowID].y_end - - overlap_list->list[overlapID].w_list.a[windowID].y_start + 1; - - retrieve_u_seq(overlap_read, NULL, &uref->ug->u.a[overlap_list->list[overlapID].y_id], - overlap_list->list[overlapID].y_pos_strand, 0, -1, km); - - - x_string = r_string; - y_string = overlap_read->seq; - - - beg_cigar = end_cigar = NULL; - if(windowID >= 1) - { - beg_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID-1]); - } - if(windowID < (long long)(overlap_list->list[overlapID].w_list.n) - 1) - { - end_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID]); - } - - - addSNPtohaplotype_advance(window_start, overlapID, x_start, x_length, y_start, y_length, - &(overlap_list->list[overlapID].w_list.a[windowID]), &(overlap_list->list[overlapID].w_list), - beg_cigar, &(overlap_list->list[overlapID].boundary_cigars), - end_cigar, &(overlap_list->list[overlapID].boundary_cigars), - hap, snp_threshold, x_string, y_string, uref, overlap_list->list[overlapID].y_pos_strand, overlap_list->list[overlapID].y_id, km); - } - - RsetInitHaplotypeEvdienceFlag(hap, first_snp, last_snp + 1 - first_snp); - - if(hap->length - ll > 1 && lr > 1) radix_sort_haplotype_evdience_srt(hap->list+ll, hap->list + hap->length); -} - - -int cmp_snp_stats(const void * a, const void * b) -{ - if ((*(SnpStats*)a).score != (*(SnpStats*)b).score) - { - return (*(SnpStats*)a).score < (*(SnpStats*)b).score ? 1 : -1; - } - else - { - if ((*(SnpStats*)a).occ_2 != (*(SnpStats*)b).occ_2) - { - return (*(SnpStats*)a).occ_2 > (*(SnpStats*)b).occ_2 ? 1 : -1; - } - else - { - return 0; - } - } -} - - -int cmp_max_DP(const void * a, const void * b) -{ - if(Get_Max_DP_Value((*(uint64_t*)a))!=Get_Max_DP_Value((*(uint64_t*)b))) - { - return Get_Max_DP_Value((*(uint64_t*)a)) < Get_Max_DP_Value((*(uint64_t*)b))? 1 : -1; - } - else - { - return 0; - } -} - - -int split_sub_list(haplotype_evdience_alloc* hap, -haplotype_evdience* sub_list, long long sub_length, -overlap_region_alloc* overlap_list, All_reads* R_INF, UC_Read* g_read) -{ - long long i = 0; - long long occ_0 = 0; - long long occ_1 = 0; - long long occ_1_array[5]; - memset(occ_1_array, 0, sizeof(long long) * 5); - long long occ_2 = 0; - - - for (i = 0; i < sub_length; i++) - { - if(sub_list[i].type == 0) - { - occ_0++; - } - else if(sub_list[i].type == 1) - { - occ_1_array[seq_nt6_table[(uint8_t)(sub_list[i].misBase)]]++; - occ_1++; - } - else if(sub_list[i].type == 2) - { - occ_2++; - } - } - - - - /** - 1. if occ_0 = 0, that means all overlaps are different with this read at this site - 2. it is not possible that occ_1 = 0, - 3. if occ_1 = 1, there are only one difference. It must be a sequencing error. - (for repeat, it maybe a snp at repeat. but ...) - **/ - ///if(occ_0 == 0 || occ_1 <= 1) - if(occ_0 == 0 || occ_1 == 0) - { - return 0; - } - - - - ///note: if the max value except type0 is type2 - ///that means this is no snp hapolyte - long long max = occ_2; - long long max_i = -1; - - for (i = 0; i < 5; i++) - { - if(occ_1_array[i] > max) - { - max = occ_1_array[i]; - max_i = i; - } - } - - - - if(max_i == -1) - { - return 0; - } - - if(max <= 1) - { - return 0; - } - - - ///if we have two max - for (i = 0; i < 5; i++) - { - if(occ_1_array[i] == max && i != max_i) - { - return 0; - } - } - - long long new_0 = occ_0 + 1; - long long new_total = sub_length + 1; - ///note: here occ_0++ since the read itself has a type0 - double available = new_0 + max; - double threshold = 0.95; - available = available/((double)(new_total)); - if(available < threshold)///Fix-attention: looks definitely wrong - { - return 0; - } - - ///new_total is the number of errors here - new_total = new_total - new_0; - ///available is the number of selected errors here - available = max; - threshold = 0.70; - available = available/((double)(new_total)); - if(available < threshold)///Fix-attention: looks definitely wrong - { - return 0; - } - - InsertSNPVector(hap, sub_list, sub_length, s_H[max_i], g_read); - - return 1; -} - - -int calculate_distance_snp_vector(int8_t *vector1, int8_t *vector2, int Len) -{ - int i; - for (i = 0; i < Len; i++) - { - if(vector1[i] != vector2[i]) - { - if ((vector1[i] == 0 || vector1[i] == 1) && (vector2[i] == 0 || vector2[i] == 1)) - { - return 1; - } - } - } - - return 0; -} - -void print_core_snp(haplotype_evdience_alloc* hap) -{ - uint64_t i, j; - for (i = 0; i < hap->core_snp; i++) - { - fprintf(stderr, "core(i): %lu, site: %u, occ_0: %u, occ_1: %u, occ_2: %u, score: %d\n", - (unsigned long)i, hap->snp_stat.a[i].site, hap->snp_stat.a[i].occ_0, hap->snp_stat.a[i].occ_1, - hap->snp_stat.a[i].occ_2, - hap->snp_stat.a[i].score); - - int vectorID = hap->snp_stat.a[i].id; - int8_t* vector = Get_SNP_Vector((*hap), vectorID); - - for (j = 0; j < hap->overlap; j++) - { - if(vector[j] == 0) - { - fprintf(stderr, "type: %d, ID: %lu\n", vector[j], (unsigned long)j); - } - } - - - for (j = 0; j < hap->overlap; j++) - { - if(vector[j] == 1) - { - fprintf(stderr, "type: %d, ID: %lu\n", vector[j], (unsigned long)j); - } - } - - - for (j = 0; j < hap->overlap; j++) - { - if(vector[j] == 2) - { - fprintf(stderr, "type: %d, ID: %lu\n", vector[j], (unsigned long)j); - } - } - - } -} - - - -void add_to_result_snp_vector(haplotype_evdience_alloc* hap, int8_t *new_vector, int Len) -{ - int8_t *r_vector = Get_Result_SNP_Vector((*hap)); - int j; - for (j = 0; j < Len; j++) - { - if(r_vector[j] == -1) - { - if(new_vector[j] == 0) - { - hap->result_stat.occ_0++; - r_vector[j] = new_vector[j]; - } - else if(new_vector[j] == 1) - { - hap->result_stat.occ_1++; - r_vector[j] = new_vector[j]; - } - } - ///can debug here - } - - hap->result_stat.overlap_num = hap->result_stat.occ_0 + hap->result_stat.occ_1; -} - - -int debug_add_to_result_snp_vector(haplotype_evdience_alloc* hap, int8_t *new_vector, int Len) -{ - int8_t *r_vector = Get_Result_SNP_Vector((*hap)); - int j; - for (j = 0; j < Len; j++) - { - if(r_vector[j] == -1) - { - if(new_vector[j] == 0) - { - hap->result_stat.occ_0++; - r_vector[j] = new_vector[j]; - } - else if(new_vector[j] == 1) - { - hap->result_stat.occ_1++; - r_vector[j] = new_vector[j]; - } - } - else ///can debug here - { - ///if((new_vector[j] != -1 && new_vector[j] != 2 && new_vector[j] != r_vector[j])) - if((new_vector[j] == 0 || new_vector[j] == 1) && new_vector[j] != r_vector[j]) - { - return j; - } - } - } - - return -1; - -} - - - -int merge_snp_vectors_and_test(haplotype_evdience_alloc* hap, int diff_vector_ID) -{ - int8_t *r_vector = Get_Result_SNP_Vector((*hap)); - int vectorLen = Get_SNP_Vector_Length((*hap)); - memset(r_vector, -1, vectorLen); - hap->result_stat.occ_0 = 0; - hap->result_stat.occ_1 = 0; - - int8_t* vector; - int vectorID; - int i, j; - - for (i = 0; i < (int)hap->core_snp; i++) - { - if(i == diff_vector_ID) - { - continue; - } - - vectorID = hap->snp_stat.a[i].id; - vector = Get_SNP_Vector((*hap), vectorID); - - for (j = 0; j < vectorLen; j++) - { - if(r_vector[j] == -1) - { - if(vector[j] == 0) - { - hap->result_stat.occ_0++; - r_vector[j] = vector[j]; - } - else if(vector[j] == 1) - { - hap->result_stat.occ_1++; - r_vector[j] = vector[j]; - } - } - else ///can debug here - { - ///has confilict - if(vector[j] != -1 && vector[j] != 2 && vector[j] != r_vector[j]) - { - return 0; - } - } - } - } - - hap->result_stat.overlap_num = hap->result_stat.occ_0 + hap->result_stat.occ_1; - - return 1; -} - -int generate_haplotypes(haplotype_evdience_alloc* hap) -{ - int j; - - int vectorID2; - int8_t *vector, *vector2; - - if(hap->core_snp == 0) - { - return 0; - } - - ///sort by weight - // qsort(hap->snp_stat, hap->available_snp, sizeof(SnpStats), cmp_snp_stats); - qsort(hap->snp_stat.a, hap->snp_stat.n, sizeof(SnpStats), cmp_snp_stats); - - - ///the hap->core_snp is used to find centriod - ///if there are <5 vectors in core_snp, we didn't allow different vector - if (hap->core_snp < 5) - { - if(merge_snp_vectors_and_test(hap, -1) == 0) - { - return 0; - } - } - else ///for vectors in core_snp, we allow at most one different vector when there are >= 5 vectors in core_snp - { - ///there are two condition: 1. vector 0 is the different one. 2. vector 0 is not the different one - ///first try to merge all vector together - if(merge_snp_vectors_and_test(hap, -1) == 0) - { - for (j = hap->core_snp - 1; j >= 0; j--) - { - if(merge_snp_vectors_and_test(hap, j) == 1) - { - break; - } - } - - if(j == -1) - { - return 0; - } - } - } - - - - - ///after merge, we get result vector - vector = Get_Result_SNP_Vector((*hap)); - ///and for each non-core snp vector, if it has no conflict with result vector - /// add it to result vector - for (j = hap->core_snp; j < (int)hap->snp_stat.n/**hap->available_snp**/; j++) - { - vectorID2 = hap->snp_stat.a[j].id; - vector2 = Get_SNP_Vector((*hap), vectorID2); - if(calculate_distance_snp_vector(vector, vector2, Get_SNP_Vector_Length((*hap))) == 0) - { - add_to_result_snp_vector(hap, vector2, Get_SNP_Vector_Length((*hap))); - } - } - - - ///for read only have 1 snp, we need a more strict condition - if (hap->core_snp == 1 && - filter_one_snp(hap->result_stat.occ_0 + 1, hap->result_stat.occ_1, - hap->result_stat.overlap_num + 1) == 0) - { - return 0; - } - - - return 1; - -} - -void Preorder_Merge(uint32_t snpID, haplotype_evdience_alloc* hap, int is_merge) -{ - int vectorID = hap->snp_stat.a[snpID].id; - int8_t* vector = Get_SNP_Vector((*hap), vectorID); - hap->dp.visit[snpID] = 1; - - - if(is_merge) - { - if(hap->snp_stat.a[snpID].is_homopolymer) - { - hap->result_stat.homopolymer_num++; - } - else - { - hap->result_stat.non_homopolymer_num++; - } - - hap->result_stat.score++; - int flag; - if((flag = debug_add_to_result_snp_vector(hap, vector, Get_SNP_Vector_Length((*hap))))!= -1) - { - fprintf(stderr, "incompatible snp vector....\n"); - exit(0); - } - } - - uint32_t* column; - int j; - - if(hap->dp.backtrack_length[snpID] != 0) - { - column = Get_DP_Backtrack_Column(hap->dp, snpID); - - if(is_merge) - { - int add_ID = 0; - for (j = 0; j < (int)hap->dp.backtrack_length[snpID]; j++) - { - if(hap->snp_stat.a[column[j]].is_homopolymer == 0) - { - add_ID = j; - } - } - - for (j = 0; j < (int)hap->dp.backtrack_length[snpID]; j++) - { - if(j == add_ID) - { - Preorder_Merge(column[j], hap, 1); - } - else - { - Preorder_Merge(column[j], hap, 0); - } - } - } - else - { - for (j = 0; j < (int)hap->dp.backtrack_length[snpID]; j++) - { - Preorder_Merge(column[j], hap, 0); - } - } - } -} - - -void Preorder_Merge_Advance_Repeat(uint32_t snpID, haplotype_evdience_alloc* hap, int pathLen) -{ - hap->dp.visit[snpID] = 1; - hap->dp.buffer[pathLen] = snpID; - pathLen++; - - if(hap->dp.backtrack_length[snpID] == 0) - { - insert_SNP_IDs_addition(&(hap->dp.SNP_IDs), hap->dp.buffer, pathLen); - return; - } - else - { - uint32_t* column; - int j; - - column = Get_DP_Backtrack_Column(hap->dp, snpID); - for (j = 0; j < (int)hap->dp.backtrack_length[snpID]; j++) - { - Preorder_Merge_Advance_Repeat(column[j], hap, pathLen); - } - } -} - -void generate_result_vector(haplotype_evdience_alloc* hap, int pathLen) -{ - if(pathLen != hap->dp.current_snp_num) - { - fprintf(stderr, "error\n"); - } - - - int8_t* vector = Get_Result_SNP_Vector((*hap)); - memset(vector, -1, Get_SNP_Vector_Length((*hap))); - hap->result_stat.occ_0 = 0; - hap->result_stat.occ_1 = 0; - hap->result_stat.occ_2 = 0; - hap->result_stat.score = pathLen; - hap->result_stat.homopolymer_num = 0; - hap->result_stat.non_homopolymer_num = 0; - - long long snpID1; - long long j = 0; - int flag, vectorID; - int current_score; - for (j = 0; j < pathLen; j++) - { - snpID1 = hap->dp.buffer[j]; - vectorID = hap->snp_stat.a[snpID1].id; - vector = Get_SNP_Vector((*hap), vectorID); - if(hap->snp_stat.a[snpID1].is_homopolymer) - { - hap->result_stat.homopolymer_num++; - } - else - { - hap->result_stat.non_homopolymer_num++; - } - - if((flag = debug_add_to_result_snp_vector(hap, vector, Get_SNP_Vector_Length((*hap))))!= -1) - { - fprintf(stderr, "incompatible snp vector....\n"); - exit(0); - } - } - hap->result_stat.overlap_num = hap->result_stat.occ_0 + hap->result_stat.occ_1; - - - - - ///check if this is a useful snp vector - if(hap->result_stat.overlap_num !=0 && filter_one_snp_advance_nearby(hap, hap->result_stat.occ_0 + 1, - hap->result_stat.occ_1, hap->result_stat.overlap_num + 1, - hap->result_stat.homopolymer_num, hap->result_stat.non_homopolymer_num, - hap->dp.buffer, pathLen)) - { - current_score = calculate_score(hap->result_stat.occ_0 + 1, hap->result_stat.occ_1); - ///first useful snp vector - if(hap->dp.max_snp_num < pathLen) - { - hap->dp.max_snp_num = pathLen; - hap->dp.max_score = current_score; - memcpy(hap->dp.max_buffer, hap->dp.buffer, sizeof(uint32_t) * pathLen); - }///if we have multiple single best snp vector, select the vector with max score - else if(hap->dp.max_snp_num == pathLen) - { - if(current_score > hap->dp.max_score) - { - hap->dp.max_score = current_score; - memcpy(hap->dp.max_buffer, hap->dp.buffer, sizeof(uint32_t) * pathLen); - } - } - } - -} - - -void Preorder_Merge_Advance(uint32_t snpID, haplotype_evdience_alloc* hap, int pathLen) -{ - hap->dp.visit[snpID] = 1; - hap->dp.buffer[pathLen] = snpID; - pathLen++; - - if(hap->dp.backtrack_length[snpID] == 0) - { - generate_result_vector(hap, pathLen); - return; - } - else - { - uint32_t* column; - int j; - - column = Get_DP_Backtrack_Column(hap->dp, snpID); - for (j = 0; j < (int)hap->dp.backtrack_length[snpID]; j++) - { - Preorder_Merge_Advance(column[j], hap, pathLen); - } - } -} - - - -int if_snp_vector_useful(haplotype_evdience_alloc* hap, -long long occ_0, long long occ_1, uint32_t* SNPs, long long SNPsLen) -{ - - double occ_1_coverage_low = (occ_0 + occ_1) * 0.3; - - if(occ_1 == 0 || occ_0 == 0) - { - return 0; - } - - ///Fix-attention - if(occ_1 >= occ_1_coverage_low && occ_0 >= occ_1_coverage_low) - { - return 1; - } - else if(occ_1 >= 5 && occ_0 >= 5) - { - return 1; - } - else if(occ_1 >= 3 && occ_0 >= 3 && SNPsLen >= 2) - { - int nearsnp; - int non_nearsnps; - count_nearby_snps(hap, SNPs, SNPsLen, &nearsnp, &non_nearsnps); - if(non_nearsnps > 0) - { - return 1; - } - } - - return 0; -} - - -void merge_SNP_Vectors(haplotype_evdience_alloc* hap, uint32_t* SNPs, long long SNPLen) -{ - - int8_t* vector = Get_Result_SNP_Vector((*hap)); - memset(vector, -1, Get_SNP_Vector_Length((*hap))); - hap->result_stat.occ_0 = 0; - hap->result_stat.occ_1 = 0; - hap->result_stat.occ_2 = 0; - hap->result_stat.score = SNPLen; - hap->result_stat.homopolymer_num = 0; - hap->result_stat.non_homopolymer_num = 0; - - long long snpID1; - long long j = 0; - int flag, vectorID; - for (j = 0; j < SNPLen; j++) - { - snpID1 = SNPs[j]; - vectorID = hap->snp_stat.a[snpID1].id; - vector = Get_SNP_Vector((*hap), vectorID); - if(hap->snp_stat.a[snpID1].is_homopolymer) - { - hap->result_stat.homopolymer_num++; - } - else - { - hap->result_stat.non_homopolymer_num++; - } - - if((flag = debug_add_to_result_snp_vector(hap, vector, Get_SNP_Vector_Length((*hap))))!= -1) - { - fprintf(stderr, "incompatible snp vector....\n"); - exit(0); - } - } - hap->result_stat.overlap_num = hap->result_stat.occ_0 + hap->result_stat.occ_1; -} - - -void remove_reads(haplotype_evdience_alloc* hap, uint32_t* SNPs, long long SNPsLen, overlap_region_alloc* overlap_list) -{ - long long i, j, snpID, vectorID, overlapLen; - int8_t *vector; - - for (i = 0; i < SNPsLen; i++) - { - snpID = SNPs[i]; - vectorID = hap->snp_stat.a[snpID].id; - vector = Get_SNP_Vector((*hap), vectorID); - ///hap->snp_stat[snpID].site; - - for (j = 0; j < Get_SNP_Vector_Length((*hap)); j++) - { - - if(vector[j] == 1 && overlap_list->list[j].is_match == 1) - { - //overlap_list->list[j].is_match = 0; - overlap_list->list[j].is_match = 2; - overlapLen = overlap_list->list[j].x_pos_e - overlap_list->list[j].x_pos_s + 1; - ///overlap_list->mapped_overlaps--; - overlap_list->mapped_overlaps_length -= overlapLen; - } - - /****************************may have bugs********************************/ - if( hap->snp_stat.a[snpID].site >= overlap_list->list[j].x_pos_s - && - hap->snp_stat.a[snpID].site <= overlap_list->list[j].x_pos_e) - { - overlap_list->list[j].strong = 1; - } - /****************************may have bugs********************************/ - - } - } -} - -void try_to_remove_reads(int8_t* vector, long long vectorLen, overlap_region_alloc* overlap_list, -uint32_t* SNPs, long long SNPLen, haplotype_evdience_alloc* hap) -{ - long long i, overlapLen; - long long removed_num = 0; - - for (i = 0; i < vectorLen; i++) - { - if(vector[i] == 1 && overlap_list->list[i].is_match == 1) - { - - ///overlap_list->list[i].is_match = 0; - overlap_list->list[i].is_match = 2; - overlapLen = overlap_list->list[i].x_pos_e - overlap_list->list[i].x_pos_s + 1; - ///overlap_list->mapped_overlaps--; - overlap_list->mapped_overlaps_length -= overlapLen; - removed_num++; - } - } - - - long long snpID, j; - for (i = 0; i < SNPLen; i++) - { - snpID = SNPs[i]; - ///check all overlaps - for (j = 0; j < Get_SNP_Vector_Length((*hap)); j++) - { - /****************************may have bugs********************************/ - if( hap->snp_stat.a[snpID].site >= overlap_list->list[j].x_pos_s - && - hap->snp_stat.a[snpID].site <= overlap_list->list[j].x_pos_e) - { - overlap_list->list[j].strong = 1; - } - /****************************may have bugs********************************/ - } - } -} - - -void process_repeat_snps(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list) -{ - int i; - uint32_t* snp_ids; - long long length; - - - - for (i = 0; i < hap->dp.SNP_IDs.IDs_length; i++) - { - snp_ids = hap->dp.SNP_IDs.buffer + hap->dp.SNP_IDs.IDs[i].beg; - length = hap->dp.SNP_IDs.IDs[i].end -hap->dp.SNP_IDs.IDs[i].beg + 1; - - merge_SNP_Vectors(hap, snp_ids, length); - - if(if_snp_vector_useful(hap, hap->result_stat.occ_0, hap->result_stat.occ_1, - snp_ids, length)) - { - try_to_remove_reads(Get_Result_SNP_Vector((*hap)), Get_SNP_Vector_Length((*hap)), - overlap_list, snp_ids, length, hap); - - hap->dp.SNP_IDs.IDs[i].is_remove = 1; - } - else - { - hap->dp.SNP_IDs.IDs[i].is_remove = 0; - } - } -} - - -void lable_large_indels(overlap_region_alloc* overlap_list, long long read_length, Correct_dumy* dumy, double max_ov_diff_ec) -{ - long long i, j, c_i, c_n; uint32_t operLen; uint8_t oper; - int is_delete = 0; window_list *c_idx; - for (i = 0; i < (long long)overlap_list->length; i++) - { - ///should has at least 3 windows for this overlap - if (overlap_list->list[i].is_match == 1 && overlap_list->list[i].w_list.n >= 3) - { - ///here w_list_length >= 3 - ///skip the first and last window - for (j = 1; j + 1 < (long long)(overlap_list->list[i].w_list.n); j++) - { - ///this window is not matched, it seems to have large difference - if(overlap_list->list[i].w_list.a[j].y_end == -1) - { - overlap_list->list[i].is_match = 100; - is_delete = 1; - goto end_rem; - } - - c_idx = &(overlap_list->list[i].w_list.a[j]); - c_n = c_idx->clen; - ///if there are <=2 cigar elements, skip it - if(c_n < 3) continue; - - ///skip the first and last cigar elements - for (c_i = 1; c_i + 1 < c_n; c_i++) - { - get_cigar_cell(c_idx, &(overlap_list->list[i].w_list), c_i, &oper, &operLen); - - - if(operLen <= 5) - { - continue; - } - ///>=6 bp deletion or insertion - if(oper == 2 || oper == 3) - { - overlap_list->list[i].is_match = 100; - is_delete = 1; - goto end_rem; - } - } - } - } - - end_rem:; - } - - - if(is_delete == 1) - { - long long window_start, window_end; - Window_Pool w_inf; - init_Window_Pool(&w_inf, read_length, WINDOW, (int)(1.0/max_ov_diff_ec)); - int flag = 0; - long long realLen = 0, realLen_100 = 0; - int to_recover = 0; - while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) - { - dumy->length = 0; - dumy->lengthNT = 0; - ///return overlaps that is overlaped with [window_start, window_end] - flag = get_available_fully_covered_interval(window_start, window_end, - overlap_list, dumy, &realLen, &realLen_100); - - - switch (flag) - { - case 1: ///match - break; - case 0: ///unmatch - break; - case -2: ///unmatch, and the next window also cannot match - break; - } - - ///it seems there is a long indel at the reference read itself - if(realLen == 0 && realLen_100 > 0) - { - to_recover = 1; - break; - } - } - - if(to_recover == 1) - { - for (i = 0; i < (long long)overlap_list->length; i++) - { - if (overlap_list->list[i].is_match == 100) - { - overlap_list->list[i].is_match = 1; - } - } - } - } - - - for (i = is_delete = 0; i < (long long)(overlap_list->length); i++) - { - if (overlap_list->list[i].is_match == 1) - { - overlap_list->list[i].without_large_indel = 1; - is_delete++; - } - - if (overlap_list->list[i].is_match == 100) - { - overlap_list->list[i].is_match = 1; - overlap_list->list[i].without_large_indel = 0; - is_delete++; - } - } - - // if(is_delete) radix_sort_overlap_region_dp_srt(overlap_list->list, overlap_list->list+overlap_list->length); -} - -int debug_print_snp_stat(char* name, haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, All_reads* R_INF) -{ - if(overlap_list->length > 0 && - memcmp(name, Get_NAME((*R_INF), overlap_list->list[0].x_id), - Get_NAME_LENGTH((*R_INF), overlap_list->list[0].x_id)) == 0) - { - fprintf(stderr, "\n%s, available_snp: %d\n", name, (int)hap->snp_stat.n); - int i; - for (i = 0; i < (int)hap->snp_stat.n; i++) - { - fprintf(stderr, "site: %d, occ_0: %d, occ_1: %d, occ_2: %d\n", - hap->snp_stat.a[i].site, hap->snp_stat.a[i].occ_0, - hap->snp_stat.a[i].occ_1, hap->snp_stat.a[i].occ_2); - } - } - - return 1; -} - -int generate_haplotypes_DP(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, All_reads* R_INF, long long rLen, -int force_repeat) -{ - int j, i; - int vectorID, vectorID2; - int8_t *vector, *vector2; - - - // if(hap->available_snp == 0) - if(hap->snp_stat.n == 0) - { - return 0; - } - - ///debug_print_snp_stat("m64013_190324_024932/23660629/ccs", hap, overlap_list, R_INF); - - - ///if hap->available_snp == 1, the following codes would have bugs - ///filter snps that are highly likly false - // if(hap->available_snp > 1) - if(hap->snp_stat.n > 1) - { - i = 0; - ///if a snp is very close to others, it should not be a real snp - for (j = 0; j < (int)hap->snp_stat.n/**hap->available_snp**/; j++) - { - if(j > 0 && j + 1 < (int)hap->snp_stat.n) - { - if(hap->snp_stat.a[j].site != hap->snp_stat.a[j - 1].site + 1 - && - hap->snp_stat.a[j].site + 1 != hap->snp_stat.a[j + 1].site) - { - hap->snp_stat.a[i] = hap->snp_stat.a[j]; - i++; - } - - } - else if(j == 0) - { - if(hap->snp_stat.a[j].site + 1 != hap->snp_stat.a[j + 1].site) - { - hap->snp_stat.a[i] = hap->snp_stat.a[j]; - i++; - } - } - else - { - if(hap->snp_stat.a[j].site != hap->snp_stat.a[j - 1].site + 1) - { - hap->snp_stat.a[i] = hap->snp_stat.a[j]; - i++; - } - } - } - // hap->available_snp = i; - hap->snp_stat.n = i; - } - - - - - - - int flag; - long long overlap_length, total_read, unuseful_read; - total_read = unuseful_read = 0; - ///check if any read may be conflict with others - for (i = 0; i < (long long)overlap_list->length; i++) - { - overlap_length = overlap_list->list[i].x_pos_e - overlap_list->list[i].x_pos_s + 1; - if (overlap_list->list[i].is_match == 1) - { - total_read++; - flag = -1; - for (j = 0; j < (int)hap->snp_stat.n; j++) - { - vectorID = hap->snp_stat.a[j].id; - vector = Get_SNP_Vector((*hap), vectorID); - - ///flag == -1 means there are no useful signals yet - if (flag == -1) - { - if((vector[i] == 0 || vector[i] == 1 )) - { - flag = 0; - } - }///flag == 0 means there is at least one useful signal yet - else if (flag == 0) - { - if(vector[i] != 0 && vector[i] != 1) - { - flag = 2; - } - }///flag == 0 means there is at least one useful signal first, and another unuseful signal after that - else if(flag == 2) - { - if((vector[i] == 0 || vector[i] == 1 )) - { - flag = 3; - break; - } - } - } - - - if(flag == 3) ///Fix-attention: definitely wrong - { - unuseful_read++; - for (j = 0; j < (int)hap->snp_stat.n; j++) - { - vectorID = hap->snp_stat.a[j].id; - vector = Get_SNP_Vector((*hap), vectorID); - - - - if(vector[i] == 0) - { - hap->snp_stat.a[j].occ_0--; - hap->snp_stat.a[j].occ_2++; - } - else if(vector[i] == 1) - { - hap->snp_stat.a[j].occ_1--; - hap->snp_stat.a[j].occ_2++; - } - else if(vector[i] != 2) - { - hap->snp_stat.a[j].occ_2++; - } - - - vector[i] = 2; - } - - ///this read may be unuseful - ///overlap_list->list[i].is_match = 0; - ///overlap_list->list[i].is_match = 2; - overlap_list->list[i].is_match = 4; - ///overlap_list->mapped_overlaps--; - overlap_list->mapped_overlaps_length -= overlap_length; - } - } - } - - - /*******************************DP********************************/ - init_DP_matrix(&(hap->dp), hap->snp_stat.n); - - long long equal_best = 0; - uint32_t* column; - - - - for (i = 0; i < (int)hap->snp_stat.n; i++) - { - ///vector of snp i - vectorID = hap->snp_stat.a[i].id; - vector = Get_SNP_Vector((*hap), vectorID); - hap->dp.visit[i] = 0; - hap->dp.max[i] = 1; - hap->dp.backtrack_length[i] = 0; - equal_best = 0; - column = Get_DP_Backtrack_Column(hap->dp, i); - - for (j = 0; j < i; j++) - { - ///vector of snp j - vectorID2 = hap->snp_stat.a[j].id; - vector2 = Get_SNP_Vector((*hap), vectorID2); - - ///vector is compatible with vector2 - if(calculate_distance_snp_vector(vector, vector2, Get_SNP_Vector_Length((*hap))) == 0) - { - - if(hap->dp.max[i] < hap->dp.max[j] + 1) - { - hap->dp.max[i] = hap->dp.max[j] + 1; - - column[0] = j; - equal_best = 1; - } - else if(hap->dp.max[i] == hap->dp.max[j] + 1) - { - column[equal_best] = j; - equal_best++; - } - - - } - } - - hap->dp.backtrack_length[i] = equal_best; - } - - /*******************************DP********************************/ - - uint64_t tmp_mode = 0; - - for (i = 0; i < (int)hap->snp_stat.n; i++) - { - tmp_mode = hap->dp.max[i]; - tmp_mode = tmp_mode << 32; - tmp_mode = tmp_mode | (uint64_t)(i); - hap->dp.max_for_sort[i] = tmp_mode; - } - - qsort(hap->dp.max_for_sort, hap->snp_stat.n, sizeof(uint64_t), cmp_max_DP); - - - int snpID; - ///the minmum snp_num is 1 - hap->dp.max_snp_num = 0; - hap->dp.max_score = -2; - - - for (i = 0; i < (int)hap->snp_stat.n; i++) - { - snpID = Get_Max_DP_ID(hap->dp.max_for_sort[i]); - if(hap->dp.visit[snpID] == 0) - { - hap->dp.current_snp_num = Get_Max_DP_Value(hap->dp.max_for_sort[i]); - Preorder_Merge_Advance_Repeat(snpID, hap, 0); - } - } - - ///debug_print_snp_stat("m64013_190324_024932/23660629/ccs", hap, overlap_list, R_INF); - - - //if(hap->dp.max_snp_num > 0) - if(hap->snp_stat.n > 0) - { - process_repeat_snps(hap, overlap_list); - return 1; - } - else - { - return 0; - } -} - - -inline int check_informative_site(haplotype_evdience_alloc* hap, SnpStats* snp) -{ - long long vectorID = snp->id; - int8_t *vector = Get_SNP_Vector((*hap), vectorID); - snp->occ_0 = 0; - snp->occ_1 = 0; - snp->occ_2 = 0; - long long i; - for (i = 0; i < Get_SNP_Vector_Length((*hap)); i++) - { - if(vector[i] == 0) - { - snp->occ_0++; - } - else if(vector[i] == 1) - { - snp->occ_1++; - } - else if(vector[i] == 2) - { - snp->occ_2++; - } - } - - if(snp->occ_0 >= 2 || snp->occ_1 >= 2) - { - return 1; - } - - return 0; -} - - -int generate_haplotypes_naive(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, All_reads* R_INF, long long rLen, -int force_repeat) -{ - int j, i; - - - if(hap->snp_stat.n == 0) - { - return 0; - } - - ///if hap->available_snp == 1, the following codes would have bugs - ///filter snps that are highly likly false - if(hap->snp_stat.n > 1) - { - i = 0; - ///if a snp is very close to others, it should not be a real snp - for (j = 0; j < (int)hap->snp_stat.n; j++) - { - - if(j > 0 && j + 1 < (int)hap->snp_stat.n) - { - if(hap->snp_stat.a[j].site != hap->snp_stat.a[j - 1].site + 1 - && - hap->snp_stat.a[j].site + 1 != hap->snp_stat.a[j + 1].site) - { - hap->snp_stat.a[i] = hap->snp_stat.a[j]; - i++; - } - - } - else if(j == 0) - { - if(hap->snp_stat.a[j].site + 1 != hap->snp_stat.a[j + 1].site) - { - hap->snp_stat.a[i] = hap->snp_stat.a[j]; - i++; - } - } - else - { - if(hap->snp_stat.a[j].site != hap->snp_stat.a[j - 1].site + 1) - { - hap->snp_stat.a[i] = hap->snp_stat.a[j]; - i++; - } - } - } - hap->snp_stat.n = i; - } - - - long long m; - if(hap->snp_stat.n > 0) - { - ///************************debug**************************/// - m = 0; - for (i = 0; i < (int)hap->snp_stat.n; i++) - { - if(check_informative_site(hap, &(hap->snp_stat.a[i]))) - { - hap->snp_stat.a[m] = hap->snp_stat.a[i]; - m++; - } - } - hap->snp_stat.n = m; - ///************************debug**************************/// - - - - init_DP_matrix(&(hap->dp), hap->snp_stat.n); - - for (i = 0; i < (int)hap->snp_stat.n; i++) - { - hap->dp.max_buffer[i] = i; - } - hap->dp.max_snp_num = hap->snp_stat.n; - remove_reads(hap, hap->dp.max_buffer, hap->dp.max_snp_num, overlap_list); - - return 1; - - } - else - { - return 0; - } - -} - - -void generate_haplotypes_naive_advance(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, void *km) -{ - if(hap->length == 0) return; - uint64_t k, l, i, o, *a, ii; - int64_t z; - SnpStats *s = NULL, *t = NULL; - hap->snp_srt.n = 0; - radix_sort_haplotype_evdience_id_srt(hap->list, hap->list + hap->length); - for (k = 1, l = 0; k <= hap->length; ++k) { - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - for (i = l, o = 0; i < k; i++) { - // if(hap->list[i].overlapSite == 55) { - // fprintf(stderr, "5555555555[M::%s::] utg%.6dl(%c), x_site::%u, x::[%u, %u), misBase::%c, occ_0::%u, occ_1::%u, occ_2::%u, snp_idx::%u\n", __func__, - // ((int32_t)(overlap_list->list[hap->list[i].overlapID].y_id)) + 1, - // "+-"[overlap_list->list[hap->list[i].overlapID].y_pos_strand], - // hap->list[i].site, overlap_list->list[hap->list[i].overlapID].x_pos_s, - // overlap_list->list[hap->list[i].overlapID].x_pos_e + 1, hap->list[i].misBase, - // s->occ_0, s->occ_1, s->occ_2, hap->list[i].overlapSite); - // } - if(hap->list[i].type!=1) continue;///mismatch - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - // if(hap->list[i].overlapID == 125 || hap->list[i].overlapID == 127) { - // fprintf(stderr, "[M::%s::] utg%.6dl(%c), x_site::%u, x::[%u, %u), misBase::%c, occ_0::%u, occ_1::%u, occ_2::%u, snp_idx::%u\n", __func__, - // ((int32_t)(overlap_list->list[hap->list[i].overlapID].y_id)) + 1, - // "+-"[overlap_list->list[hap->list[i].overlapID].y_pos_strand], - // hap->list[i].site, overlap_list->list[hap->list[i].overlapID].x_pos_s, - // overlap_list->list[hap->list[i].overlapID].x_pos_e + 1, hap->list[i].misBase, - // s->occ_0, s->occ_1, s->occ_2, hap->list[i].overlapSite); - // } - if(s->occ_0 < 2 || s->occ_1 < 2) continue; - if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) o++;///allels must be real - } - - // if(hap->list[l].overlapID == 125 || hap->list[l].overlapID == 127) { - // fprintf(stderr, "+++[M::%s::] utg%.6dl(%c), o::%lu\n", __func__, - // ((int32_t)(overlap_list->list[hap->list[l].overlapID].y_id)) + 1, - // "+-"[overlap_list->list[hap->list[l].overlapID].y_pos_strand], o); - // } - if(o > 0) { - o = ((uint32_t)-1) - o; - o <<= 32; o += l; - if(!km) kv_push(uint64_t, hap->snp_srt, o); - else kv_push_km(km, uint64_t, hap->snp_srt, o); - } - l = k; - } - } - // fprintf(stderr, "\nhap->snp_srt.n: %u, overlap_list->length: %lu, x_id: %u\n", - // (uint32_t)hap->snp_srt.n, overlap_list->length, overlap_list->list[0].x_id); - if (hap->snp_srt.n > 0) { - radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n);///sort by how many snps in one overlap - for (k = 0; k < hap->snp_srt.n; k++) { - o = 0; l = (uint32_t)hap->snp_srt.a[k]; - for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { - if(hap->list[i].type!=1) continue; - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->occ_0 < 2 || s->occ_1 < 2) continue; - if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) o++; - } - // if(hap->list[l].overlapID == 125 || hap->list[l].overlapID == 127) { - // fprintf(stderr, "sbsbsb[M::%s::] utg%.6dl(%c), o::%lu\n", __func__, - // ((int32_t)(overlap_list->list[hap->list[l].overlapID].y_id)) + 1, - // "+-"[overlap_list->list[hap->list[l].overlapID].y_pos_strand], o); - // } - if(o == 0) continue; - - ii = hap->list[l].overlapID; - if(overlap_list->list[ii].is_match == 1) overlap_list->list[ii].is_match = 2; - for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { - if(hap->list[i].type==1){ - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - s->score = 1; - } else if(hap->list[i].type==0) { - z = hap->list[i].overlapSite; s = &(hap->snp_stat.a[z]); - for (z = hap->list[i].overlapSite; z >= 0; z--) { - t = &(hap->snp_stat.a[z]); - if(s->site!=t->site) break; - t->occ_0 -= hap->list[i].cov; - assert(t->occ_0 >= 1);// if(t->occ_0 < 1) fprintf(stderr, "WRONG-CORRECTION\n"); - } - } - } - } - - for (k = 0; k < hap->snp_srt.n; k++) { - o = 0; l = (uint32_t)hap->snp_srt.a[k]; - for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { - if(hap->list[i].type!=1) continue; - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->occ_0 < 2 || s->occ_1 < 2) continue; - if(s->score == 1) { - o++; - // if(hap->list[i].overlapID == 125 || hap->list[i].overlapID == 127) { - // fprintf(stderr, "[M::%s::] utg%.6dl(%c), x_site::%u, x::[%u, %u), misBase::%c, occ_0::%u, occ_1::%u, occ_2::%u, snp_idx::%u\n", __func__, - // ((int32_t)(overlap_list->list[hap->list[i].overlapID].y_id)) + 1, - // "+-"[overlap_list->list[hap->list[i].overlapID].y_pos_strand], - // hap->list[i].site, overlap_list->list[hap->list[i].overlapID].x_pos_s, - // overlap_list->list[hap->list[i].overlapID].x_pos_e + 1, hap->list[i].misBase, - // s->occ_0, s->occ_1, s->occ_2, hap->list[i].overlapSite); - // } - } - } - ii = hap->list[l].overlapID; - // if(hap->list[l].overlapID == 125 || hap->list[l].overlapID == 127) { - // fprintf(stderr, ">>>[M::%s::] utg%.6dl(%c), o::%lu\n", __func__, - // ((int32_t)(overlap_list->list[hap->list[l].overlapID].y_id)) + 1, - // "+-"[overlap_list->list[hap->list[l].overlapID].y_pos_strand], o); - // } - if(overlap_list->list[ii].is_match == 2 && o == 0) { - overlap_list->list[ii].is_match = 1; - } - if(overlap_list->list[ii].is_match == 1 && o > 0) { - overlap_list->list[ii].is_match = 2; - } - } - } - - hap->snp_srt.n = 0; - for (k = 1, l = 0; k <= hap->length; ++k) { - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - if(overlap_list->list[hap->list[l].overlapID].is_match == 2) { - l = k; - continue; - } - for (i = l, o = 0; i < k; i++) { - if(hap->list[i].type!=1) continue; - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->occ_0 < 2 || s->occ_1 < 2) continue; - if(s->score == 1) continue; - o++; - if(!km) kv_push(uint64_t, hap->snp_srt, hap->list[i].overlapSite); - else kv_push_km(km, uint64_t, hap->snp_srt, hap->list[i].overlapSite); - } - // if(hap->list[l].overlapID == 125 || hap->list[l].overlapID == 127) { - // fprintf(stderr, "---[M::%s::] utg%.6dl(%c), o::%lu\n", __func__, - // ((int32_t)(overlap_list->list[hap->list[l].overlapID].y_id)) + 1, - // "+-"[overlap_list->list[hap->list[l].overlapID].y_pos_strand], o); - // } - hap->snp_srt.n -= o; - if(o >= 2) {///there are at least two variants at one read - radix_sort_bc64(hap->snp_srt.a + hap->snp_srt.n, hap->snp_srt.a + hap->snp_srt.n + o); - a = hap->snp_srt.a + hap->snp_srt.n; - for (i = z = 0; i < o; i++) { - if(i > 0) s = &(hap->snp_stat.a[a[i-1]]); - if(i + 1 < o) t = &(hap->snp_stat.a[a[i+1]]); - if(s && s->site + 32 > hap->snp_stat.a[a[i]].site) continue; - if(t && hap->snp_stat.a[a[i]].site + 32 > t->site) continue; - a[z] = a[i]; - z++; - } - if(z >= 2) hap->snp_srt.n += z; - } - l = k; - } - } - if (hap->snp_srt.n > 0) { - radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n); - for (k = 1, l = 0; k <= hap->snp_srt.n; ++k) { - if(k == hap->snp_srt.n || hap->snp_srt.a[k] != hap->snp_srt.a[l]) { - if(k - l >= 2) hap->snp_stat.a[hap->snp_srt.a[l]].score = 1; - } - l = k; - } - } - - for (k = 1, l = 0; k <= hap->length; ++k) { - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - ii = hap->list[l].overlapID; - if(overlap_list->list[ii].is_match==2) overlap_list->list[ii].is_match = 1; - if(overlap_list->list[ii].is_match==1) { - for (i = l; i < k; i++) { - if(hap->list[i].type==1 || hap->list[i].type==0) { - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->score == 1 && (!(s->occ_0 < 2 || s->occ_1 < 2))) { - overlap_list->list[ii].strong = 1; - if(hap->list[i].type==1) { - overlap_list->list[ii].is_match = 2; - overlap_list->mapped_overlaps_length -= - overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; - break; - } - } - } - - } - } - l = k; - } - } - - // for (i = k = 0; i < overlap_list->length; i++) { - // if(overlap_list->list[i].is_match == 2) k++; - // } - // for (i = l = 0; i < hap->snp_stat.n; i++) { - // s = &(hap->snp_stat.a[i]); - // if(s->score == 1 && (!(s->occ_0 < 2 || s->occ_1 < 2))) l++; - // } - // fprintf(stderr, "#trans ovlp: %lu, # snp:: %lu\n", k, l); - -} - -void prt_sub_read(char *str, uint64_t str_l, uint64_t site, uint64_t win) -{ - uint64_t k, s, e; - s = ((site >= win)?(site-win):(0)); - e = (((site+win+1) <= str_l)?(site+win+1):(str_l)); - fprintf(stderr, "[M::%s-site::%lu] [%lu, %lu)\n", __func__, site, s, e); - - for (k = s; k < site; k++) fprintf(stderr, "%c", str[k]); - fprintf(stderr, "[%c]", str[k++]); - for (; k < e; k++) fprintf(stderr, "%c", str[k]); - - fprintf(stderr, "\n"); -} - -void prt_sub_cigar(overlap_region* z, uint64_t str_l, uint64_t site, uint64_t win) -{ - uint64_t k, s, e, ci, xi, yi, ws, we, os, oe, ovlp; uint32_t cl; uint16_t c; bit_extz_t ez; char cm[4]; - cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; - s = ((site >= win)?(site-win):(0)); - e = (((site+win+1) <= str_l)?(site+win+1):(str_l)); - - fprintf(stderr, "[M::%s-site::%lu] [%lu, %lu)\n", __func__, site, s, e); - - for (k = 0; k < z->w_list.n; k++) { - set_bit_extz_t(ez, (*z), k); ci = 0; xi = ez.ts; yi = ez.ps; - while (ci < ez.cigar.n) { - ws = xi; - ci = pop_trace(&(ez.cigar), ci, &c, &cl); - if(c!=2) xi += cl; - if(c!=3) yi += cl; - we = xi; - - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - - if(c != 2) { - if(!ovlp) continue; - } else {///ws == we - if(ws < s || ws >= e) continue; - ovlp = cl; - } - - fprintf(stderr, "%lu%c[%lu,%lu)", ovlp, cm[c], os, oe); - } - fprintf(stderr, "\n"); - } -} - -#define is_st_bs(s, rr, mm) (((mm) != ((uint64_t)-1)) && (((s).overlap_num + mm) >= ((s).occ_0)) && ((((s).occ_0*(rr) + (s).overlap_num)) >= ((s).occ_0))) - -void generate_haplotypes_naive_HiFi(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, double up, UC_Read* g_read, uint64_t multi_check, double st_rate, uint64_t st_max) -{ - // fprintf(stderr, "[M::%s::] Done\n", __func__); - if(hap->length == 0) return; - uint64_t k, l, i, o, *a, ii, m_snp_stat, m_list, m_off; - int64_t z; - SnpStats *s = NULL, *t = NULL; - - for (k = 1, l = 0, i = m_snp_stat = m_list = 0; k <= hap->snp_stat.n; ++k) {///filter snps - if(k == hap->snp_stat.n || hap->snp_stat.a[k].site != hap->snp_stat.a[l].site) { - if((l > 0) && (hap->snp_stat.a[l].site == (hap->snp_stat.a[l-1].site + 1))) { - l = k; continue; - } - if((k < hap->snp_stat.n) && ((hap->snp_stat.a[l].site+1) == hap->snp_stat.a[k].site)) { - l = k; continue; - } - - for (; i < hap->length && hap->list[i].site != hap->snp_stat.a[l].site; i++); - assert(i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site); - m_off = l - m_snp_stat; - for (; i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site; i++) { - assert(hap->list[i].overlapSite>=l && hap->list[i].overlapSite < k); - // assert(hap->snp_stat.a[hap->list[i].overlapSite].site==hap->list[i].site); - hap->list[m_list] = hap->list[i]; hap->list[m_list++].overlapSite -= m_off; - } - - for (; l < k; l++) hap->snp_stat.a[m_snp_stat++] = hap->snp_stat.a[l]; - } - } - hap->snp_stat.n = m_snp_stat; hap->length = m_list; - if(hap->snp_stat.n == 0 || hap->length == 0) return; - - // for (k = 0; k < hap->snp_stat.n; k++) { - // s = &(hap->snp_stat.a[k]); if(s->site != 1502) continue; - // fprintf(stderr, "[M::%s] site::%u, occ_0::%u, occ_1::%u, occ_2::%u, is_homopolymer::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_2, s->is_homopolymer); - // prt_sub_read(g_read->seq, g_read->length, s->site, 25); - // for (i = 0; i < overlap_list->length; i++) { - // if(/**overlap_list->list[i].is_match == 1 &&**/ overlap_list->list[i].x_pos_s <= s->site && s->site <= overlap_list->list[i].x_pos_e) { - // fprintf(stderr, "%.*s\tis_match::%u\tid::%u\n", (int)Get_NAME_LENGTH(R_INF, overlap_list->list[i].y_id), Get_NAME(R_INF, overlap_list->list[i].y_id), overlap_list->list[i].is_match, overlap_list->list[i].y_id); - // } - // } - // } - - - hap->snp_srt.n = 0; - radix_sort_haplotype_evdience_id_srt(hap->list, hap->list + hap->length); - for (k = 1, l = 0; k <= hap->length; ++k) { - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - for (i = l, o = 0; i < k; i++) { - if(hh_tp(hap->list[i])!=1) continue;///mismatch - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - assert(s->site == hap->list[i].site); - if(s->occ_0 < 2 || s->occ_1 < 2) continue; - if(is_st_bs((*s), st_rate, st_max)) continue; - if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) o++;///allels must be real - } - - // if(overlap_list->list[hap->list[l].overlapID].y_id == 4378830 || overlap_list->list[hap->list[l].overlapID].y_id == 4378829 || overlap_list->list[hap->list[l].overlapID].y_id == 4378799) { - // fprintf(stderr, "[M::%s-id::%u] o->%lu(%c), l::%lu\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, o, "+-"[overlap_list->list[hap->list[l].overlapID].y_pos_strand], l); - // for (i = l; i < k; i++) { - // if(hh_tp(hap->list[i])!=1) continue;///mismatch - // s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - // assert(s->site == hap->list[i].site); - // if(s->occ_0 < 2 || s->occ_1 < 2) continue; - // if(is_st_bs((*s), st_rate, st_max)) continue; - // if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { - // fprintf(stderr, "[M::%s] site::%u, occ_0::%u, occ_1::%u, occ_2::%u, is_homopolymer::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_1, s->is_homopolymer); - // prt_sub_read(g_read->seq, g_read->length, s->site, 50); - // } - // } - // } - // else { - // for (i = l, o = 0; i < k; i++) { - // if(hh_tp(hap->list[i])!=0) continue;///mismatch - // s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - // assert(s->site == hap->list[i].site); - // if(s->occ_0 < 2 || s->occ_1 < 2) continue; - // if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { - // if(s->site == 7878 || s->site == 9682) { - - // fprintf(stderr, "***[M::%s] site::%u, rid::%u\t%.*s\n", __func__, s->site, overlap_list->list[hap->list[l].overlapID].y_id, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[hap->list[l].overlapID].y_id), - // Get_NAME(R_INF, overlap_list->list[hap->list[l].overlapID].y_id)); - // prt_sub_cigar(&(overlap_list->list[hap->list[l].overlapID]), g_read->length, s->site, 50); - // } - // // o++;///allels must be real - // // fprintf(stderr, "[M::%s] site::%u, occ_0::%u, occ_1::%u, occ_2::%u, is_homopolymer::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_1, s->is_homopolymer); - // // prt_sub_read(g_read->seq, g_read->length, s->site, 50); - // } - // } - // } - - // if(overlap_list->list[hap->list[l].overlapID].y_id == 20835) { - // fprintf(stderr, "***0***[M::%s-id::%u] o->%lu\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, o); - // } - - if(o > 0) { - o = ((uint32_t)-1) - o; - o <<= 32; o += l; - kv_push(uint64_t, hap->snp_srt, o); - } - l = k; - } - } - - // fprintf(stderr, "[M::%s] snp_srt.n->%lu\n", __func__, ((uint64_t)hap->snp_srt.n)); - - if (hap->snp_srt.n > 0) { - radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n);///sort by how many snps in one overlap - for (k = 0; k < hap->snp_srt.n; k++) { - o = 0; l = (uint32_t)hap->snp_srt.a[k]; - for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { - if(hh_tp(hap->list[i])!=1) continue; - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->occ_0 < 2 || s->occ_1 < 2) continue; - if(is_st_bs((*s), st_rate, st_max)) continue; - if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { - o++; - // if(overlap_list->list[hap->list[l].overlapID].y_id == 20835) { - // fprintf(stderr, "[M::%s-id::%u] occ_0->%u, occ_1->%u, occ_2->%u, site->%u\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, s->occ_0, s->occ_1, s->occ_2, s->site); - // } - } - } - // if(overlap_list->list[hap->list[l].overlapID].y_id == 4378830 || overlap_list->list[hap->list[l].overlapID].y_id == 4378829) { - // fprintf(stderr, "***1***[M::%s-id::%u] o->%lu, l->%lu\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, o, l); - // } - if(o == 0) continue; - - ii = hap->list[l].overlapID; - if(overlap_list->list[ii].is_match == 1) overlap_list->list[ii].is_match = 2; - for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { - if(hh_tp(hap->list[i])==1){ - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - s->score = 1; - } ///else if((hh_tp(hap->list[i])==0) && (o>=(overlap_list->list[ii].align_length*up))) { - else if(hh_tp(hap->list[i])==0) { - ///not real allels - z = hap->list[i].overlapSite; s = &(hap->snp_stat.a[z]); - for (z = hap->list[i].overlapSite; z >= 0; z--) { - t = &(hap->snp_stat.a[z]); - if(s->site!=t->site) break; - // if(t->site == 14217) { - // fprintf(stderr, "[M::%s]\tsite::%u\tn0::%u\tn1::%u\to::%lu\t%.*s\n", __func__, t->site, t->occ_0, t->occ_1, o, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id)); - // } - t->occ_0 -= hap->list[i].cov; - assert(t->occ_0 >= 1); - if((st_max != ((uint64_t)-1)) && (overlap_list->list[ii].y_pos_strand == 0)) { - t->overlap_num -= hap->list[i].cov; - assert(t->overlap_num >= 1); - } - } - } - } - } - - for (k = 0; k < hap->snp_srt.n; k++) {///sorted by how many allels in each overlap; more -> less - o = 0; l = (uint32_t)hap->snp_srt.a[k]; - for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { - if(hh_tp(hap->list[i])!=1) continue; - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->occ_0 < 2 || s->occ_1 < 2) continue; - if(is_st_bs((*s), st_rate, st_max)) continue; - if(s->score == 1) o++; - } - ii = hap->list[l].overlapID; - ///for HiFi, do not flip trans to cis - // if(overlap_list->list[ii].is_match == 2 && o == 0) { - // overlap_list->list[ii].is_match = 1; - // } - if(overlap_list->list[ii].is_match == 1 && o > 0) { - overlap_list->list[ii].is_match = 2; - } - } - - - for (k = 1, l = 0; k <= hap->length; ++k) { ///reset snp_stat - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - ii = hap->list[l].overlapID; - if(overlap_list->list[ii].is_match==1) { - for (i = l; i < k; i++) { - if(hh_tp(hap->list[i])==1) { - hap->snp_stat.a[hap->list[i].overlapSite].score = -1; - } - } - } - l = k; - } - } - } - - - if(multi_check) { - hap->snp_srt.n = 0; - for (k = 1, l = 0; k <= hap->length; ++k) { - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - if(overlap_list->list[hap->list[l].overlapID].is_match == 2) { - l = k; - continue; - } - for (i = l, o = 0; i < k; i++) { - if(hh_tp(hap->list[i])!=1) continue; - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->occ_0 < 2 || s->occ_1 < 2) continue; - if(is_st_bs((*s), st_rate, st_max)) continue; - if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) continue; - if(s->score == 1) continue; - o++; - kv_push(uint64_t, hap->snp_srt, hap->list[i].overlapSite); - } - // if(overlap_list->list[hap->list[l].overlapID].y_id == 317 || overlap_list->list[hap->list[l].overlapID].y_id == 287) { - // fprintf(stderr, "***2***[M::%s-id::%u] o->%lu\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, o); - // } - hap->snp_srt.n -= o; - ///there are at least two variants at one read - if(o>=(overlap_list->list[hap->list[l].overlapID].align_length*up)) { - radix_sort_bc64(hap->snp_srt.a + hap->snp_srt.n, hap->snp_srt.a + hap->snp_srt.n + o); - a = hap->snp_srt.a + hap->snp_srt.n; - for (i = z = 0; i < o; i++) { - if(i > 0) s = &(hap->snp_stat.a[a[i-1]]); - if(i + 1 < o) t = &(hap->snp_stat.a[a[i+1]]); - if(s && s->site + 32 > hap->snp_stat.a[a[i]].site) continue; - if(t && hap->snp_stat.a[a[i]].site + 32 > t->site) continue; - a[z] = a[i]; - z++; - } - if(z >= 2) hap->snp_srt.n += z; - } - l = k; - } - } - if (hap->snp_srt.n > 0) { - radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n); - for (k = 1, l = 0; k <= hap->snp_srt.n; ++k) { - if(k == hap->snp_srt.n || hap->snp_srt.a[k] != hap->snp_srt.a[l]) { - if(k - l >= 2) hap->snp_stat.a[hap->snp_srt.a[l]].score = 1; - } - l = k; - } - } - } - - for (k = 1, l = 0; k <= hap->length; ++k) { - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - ii = hap->list[l].overlapID; - if(overlap_list->list[ii].is_match==2) { - overlap_list->list[ii].strong = 1; - overlap_list->mapped_overlaps_length -= - overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; - } else if(overlap_list->list[ii].is_match==1) { - for (i = l; i < k; i++) { - if(hh_tp(hap->list[i])==1 || hh_tp(hap->list[i])==0) { - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->score == 1 && (!(s->occ_0 < 2 || s->occ_1 < 2)) && (!(is_st_bs((*s), st_rate, st_max)))) { - overlap_list->list[ii].strong = 1; - if(hh_tp(hap->list[i])==1) { - overlap_list->list[ii].is_match = 2; - overlap_list->mapped_overlaps_length -= - overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; - break; - } - } - } - - } - } - l = k; - } - } -} - - -void generate_haplotypes_sv(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, uint64_t rid) -{ - uint64_t k, l, i, o, ii; - int64_t z; SnpStats *s = NULL; - // fprintf(stderr, "[M::%s] hap->snp_stat.n::%u, hap->length::%u\n", __func__, (uint32_t)hap->snp_stat.n, (uint32_t)hap->length); - if(hap->snp_stat.n == 0 || hap->length == 0) return; - - hap->snp_srt.n = 0; - radix_sort_haplotype_evdience_id_srt(hap->list, hap->list + hap->length); - for (k = 1, l = 0; k <= hap->length; ++k) { - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - for (i = l, o = 0; i < k; i++) { - if(hh_tp(hap->list[i])!=1) continue;///mismatch - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - assert(s->site == hap->list[i].site); - if(s->occ_0 < 2 || s->occ_1 < 2) continue; - if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) o++;///allels must be real - } - - if(o > 0) { - o = ((uint32_t)-1) - o; - o <<= 32; o += l; - kv_push(uint64_t, hap->snp_srt, o); - } - l = k; - } - } - - - if (hap->snp_srt.n > 0) { - radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n);///sort by how many snps in one overlap - for (k = 0; k < hap->snp_srt.n; k++) { - o = 0; l = (uint32_t)hap->snp_srt.a[k]; - for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { - if(hh_tp(hap->list[i])!=1) continue; - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->occ_0 < 2 || s->occ_1 < 2) continue; - if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { - o++; - } - } - if(o == 0) continue; - - ii = hap->list[l].overlapID; - if(overlap_list->list[ii].is_match == 1) { - overlap_list->list[ii].is_match = 2; - // fprintf(stderr, "[M::%s] rid::%u\t%.*s\n", __func__, overlap_list->list[ii].y_id, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id)); - } - for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { - if(hh_tp(hap->list[i])==1){ - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - s->score = 1; - } else if(hh_tp(hap->list[i])==0) { - ///not real allels - z = hap->list[i].overlapSite; - s = &(hap->snp_stat.a[z]); - s->occ_0--; - // if(!(s->occ_0 >= 1)) { - // fprintf(stderr, "[M::%s] rid::%lu, ssite::%u, lsite::%u, i::%lu, idx::%u\n", __func__, rid, s->site, hap->list[i].site, i, hap->list[i].overlapSite); - // } - assert(s->occ_0 >= 1); - } - } - } - - for (k = 0; k < hap->snp_srt.n; k++) {///sorted by how many allels in each overlap; more -> less - o = 0; l = (uint32_t)hap->snp_srt.a[k]; - for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { - if(hh_tp(hap->list[i])!=1) continue; - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->occ_0 < 2 || s->occ_1 < 2) continue; - if(s->score == 1) o++; - } - ii = hap->list[l].overlapID; - if(overlap_list->list[ii].is_match == 1 && o > 0) { - overlap_list->list[ii].is_match = 2; - // fprintf(stderr, "[M::%s] rid::%u\t%.*s\n", __func__, overlap_list->list[ii].y_id, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id)); - } - } - - - for (k = 1, l = 0; k <= hap->length; ++k) { ///reset snp_stat - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - ii = hap->list[l].overlapID; - if(overlap_list->list[ii].is_match==1) { - for (i = l; i < k; i++) { - if(hh_tp(hap->list[i])==1) { - hap->snp_stat.a[hap->list[i].overlapSite].score = -1; - } - } - } - l = k; - } - } - } - - - - for (k = 1, l = 0; k <= hap->length; ++k) { - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - ii = hap->list[l].overlapID; - if(overlap_list->list[ii].is_match==2) { - overlap_list->list[ii].strong = 1; - overlap_list->mapped_overlaps_length -= - overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; - } else if(overlap_list->list[ii].is_match==1) { - for (i = l; i < k; i++) { - if(hh_tp(hap->list[i])==1 || hh_tp(hap->list[i])==0) { - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if((s->score == 1) && (!(s->occ_0 < 2 || s->occ_1 < 2))) { - overlap_list->list[ii].strong = 1; - if(hh_tp(hap->list[i])==1) { - overlap_list->list[ii].is_match = 2; - overlap_list->mapped_overlaps_length -= - overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; - // fprintf(stderr, "[M::%s] rid::%u\t%.*s\n", __func__, overlap_list->list[ii].y_id, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id)); - break; - } - } - } - - } - } - l = k; - } - } -} - - -inline int64_t comput_sc_rphase(SnpStats *ai, uint64_t id, SnpStats *aj, uint64_t jd, haplotype_evdience *za, uint64_t occ0_cut) -{ - if(ai->site == aj->site) return INT64_MIN; - // if(ai->occ_0 < occ0_cut || aj->occ_0 < occ0_cut) return INT64_MIN; - haplotype_evdience *iz = NULL, *jz = NULL; int64_t in, jn, ik, jk, nn[2]; uint8_t fi, fj; - iz = za + ai->non_homopolymer_num; in = ai->homopolymer_num - ai->non_homopolymer_num; - jz = za + aj->non_homopolymer_num; jn = aj->homopolymer_num - aj->non_homopolymer_num; - - for (ik = jk = nn[0] = nn[1] = 0; (ik < in) && (jk < jn); ik++) { - for (; (jk < jn) && (jz[jk].overlapID < iz[ik].overlapID); jk++); - if((jk < jn) && (jz[jk].overlapID == iz[ik].overlapID)) { - - fi = 2; - if(hh_tp(iz[ik]) == 0) { - fi = 0; - } else if(iz[ik].overlapSite == id){ - fi = 1; - } - - fj = 2; - if(hh_tp(jz[jk]) == 0) { - fj = 0; - } else if(jz[jk].overlapSite == jd){ - fj = 1; - } - - if((fi == 2) && (fj == 2) && (iz[ik].overlapSite != ((uint32_t)-1)) && (jz[jk].overlapSite != ((uint32_t)-1))) {///for rare cases - fi = fj = 0; - } - - if(fi == 2 || fj == 2) return INT64_MIN; - if(fi != fj) return INT64_MIN; - nn[fi]++; - } - } - - if(nn[0] > 0 && nn[1] > 0) return 1; - return INT64_MIN; -} - -///idx->a:: [0, ch_n) -> tree; -void gen_rphase_path(asg64_v *idx, int64_t *cn, int32_t *f, int64_t *p, uint64_t v0, asg64_v *res) -{ - uint64_t n0 = idx->n, pn = 0, v, w, ct, *ca, k, gi; - kv_push(uint64_t, *idx, v0); - while (idx->n > n0) { - v = idx->a[--idx->n]; - pn = v>>32; v = (uint32_t)v; - f[v] = 1; p[pn++] = v; - ct = ((v>0)?(cn[v]-cn[v-1]):(cn[v])); - ca = ((v>0)?(idx->a+cn[v-1]):(idx->a)); - if(ct) { - for (k = 0; k < ct; k++) { - w = ((pn<<32)|ca[k]); - kv_push(uint64_t, *idx, w); - } - } else { - gi = ((res->n)?((res->a[res->n-1]>>32)+1):(0)); - for (k = 0; k < pn; k++) { - w = (gi<<32)|((uint32_t)p[pn-k-1]); - kv_push(uint64_t, *res, w); - } - } - } -} - -void dbg_prt_rphase_vec(SnpStats *ai, uint64_t id, haplotype_evdience *za) -{ - haplotype_evdience *iz = NULL; int64_t in, ik; uint8_t fi; - iz = za + ai->non_homopolymer_num; in = ai->homopolymer_num - ai->non_homopolymer_num; - - for (ik = 0; ik < in; ik++) { - fi = 2; - if(hh_tp(iz[ik]) == 0) { - fi = 0; - } else if(iz[ik].overlapSite == id){ - fi = 1; - } - fprintf(stderr, "oid::%u(f::%u)\n", iz[ik].overlapID, fi); - } -} - -void gen_rphase_dp0_multiple_path(SnpStats *a, int64_t an, haplotype_evdience *za, Chain_Data *dp, asg64_v *idx, asg64_v *res) -{ - if(an <= 0) return; - int64_t *p, *t, i, k, j, max_f, sc, ch_n, plus = 0, rn; int32_t *f, *ii; uint64_t m; - resize_Chain_Data(dp, an, NULL); idx->n = res->n = 0; - t = dp->tmp; f = dp->score; p = dp->pre; ii = dp->occ; - - for (i = 0; i < an; ++i) { - max_f = 1; ch_n = idx->n; - for (j = i - 1; j >= 0; --j) { - sc = comput_sc_rphase(&a[i], i, &a[j], j, za, 0); - if (sc == INT64_MIN) continue; - sc += f[j]; - if (sc > max_f) { - max_f = sc; - idx->n = ch_n; kv_push(uint64_t, *idx, j); - } else if (sc == max_f) { - kv_push(uint64_t, *idx, j); - } - } - - f[i] = max_f; p[i] = idx->n; ii[i] = 0; - if(f[i] < plus) plus = f[i]; - } - ch_n = idx->n; - - for (i = 0; i < an; i++) { - f[i] -= plus; - m = f[i]; m = ((uint32_t)-1) - m; m <<= 32; m |= i; - kv_push(uint64_t, *idx, m); - } - radix_sort_bc64(idx->a + ch_n, idx->a + idx->n); - - for (i = 0; i < an; i++) {///idx->a:: [0, ch_n) -> tree; [ch_n, ch_n + an) -> sort; [ch_n + an, -1) -> path - k = (uint32_t)idx->a[ch_n + i]; - if(ii[k]) continue; - gen_rphase_path(idx, p, ii, t, k, res); - } - - rn = res->n; - for (k = 1, i = 0; k <= rn; k++) { - if(k == rn || (res->a[i]>>32) != (res->a[k]>>32)) { - if(k - i > 0) { - fprintf(stderr, "\n[M::%s]\tcnt::%lu\n", __func__, k - i); - for (j = i; j < k; j++) { - fprintf(stderr, "pos::%u\n", a[(uint32_t)res->a[j]].site); - // if(k - i == 2) { - // dbg_prt_rphase_vec(&(a[(uint32_t)res->a[j]]), (uint32_t)res->a[j], za); - // } - } - } - i = k; - } - } - -} - -int64_t is_hpc_vec(SnpStats *ai, uint64_t id, haplotype_evdience *za) -{ - haplotype_evdience *iz = NULL; int64_t in, ik, n0 = ai->occ_0, n1 = ai->occ_1, f = 0; - iz = za + ai->non_homopolymer_num; in = ai->homopolymer_num - ai->non_homopolymer_num; - - for (ik = 0; ik < in; ik++) { - if(!hh_hp(iz[ik])) continue; - if(hh_tp(iz[ik]) == 0) { - ai->occ_0 -= iz[ik].cov; - } else if(iz[ik].overlapSite == id){ - ai->occ_1 -= iz[ik].cov; - } - } - if((ai->occ_0 < 2 || ai->occ_1 < 2) || (!(ai->occ_0 >= asm_opt.s_hap_cov && ai->occ_1 >= asm_opt.infor_cov))) f = 1; - ai->occ_0 = n0; ai->occ_1 = n1; - // if((sec_check) && (((n0)<=((n0+n1)*0.333333)) || ((n1)<=((n0+n1)*0.333333)))) f = 1; - return f; -} - - -void prt_dbg_vec_comp() -{ - ; -} - -void get_hq_value(SnpStats *ai, uint64_t id, haplotype_evdience *za, int64_t *lq0, int64_t *hq0, int64_t *lq1, int64_t *hq1, uint8_t *ref_a) -{ - haplotype_evdience *z; int64_t n, k, occ0[2], occ1[2]; uint8_t fi; - z = za + ai->non_homopolymer_num; n = ai->homopolymer_num - ai->non_homopolymer_num; - occ0[0] = occ0[1] = occ1[0] = occ1[1] = 0; - for (k = 0; k < n; k++) { - if((hh_tp(z[k]) == 1) && (z[k].overlapSite != id)) continue; - fi = 0; - if((hh_bq(z[k]) > 1)) fi = 1; - - if(hh_tp(z[k]) == 0) occ0[fi]++; - else occ1[fi]++; - } - if(ref_a) { - if(ref_a[ai->site] > 1) occ0[1]++; - else occ0[0]++; - } - (*lq0) = occ0[0]; (*hq0) = occ0[1]; - (*lq1) = occ1[0]; (*hq1) = occ1[1]; -} - -void gen_rphase_dp0_single_path(SnpStats *a, int64_t an, haplotype_evdience *za, Chain_Data *dp, asg64_v *idx, int64_t het_cov, int64_t hom_cov, int64_t n_hap, double cut_rate, uint64_t cut_bd, asg64_v *res, uint8_t *qual_a) -{ - if(an <= 0) return; - int64_t *p, i, k, j, st, max_f, max_j, sc, ch_n, plus = 0, rn, rn0; int32_t *f, *ii; uint64_t m, cc = 0; - resize_Chain_Data(dp, an, NULL); idx->n = res->n = 0; - f = dp->score; p = dp->pre; ii = dp->occ; - cc = ((het_cov > 0)?(het_cov):(hom_cov/n_hap)); cc *= cut_rate; if(cc < cut_bd) cc = cut_bd; - - // fprintf(stderr, "\n\n\n[M::%s]\tcc::%lu\n\n\n", __func__, cc); - - for (i = 0; i < an; ++i) { - max_f = 1; max_j = -1; - st = 0; ///if(a[i].occ_0 < cc) st = i; - for (j = i - 1; j >= st; --j) { - sc = comput_sc_rphase(&a[i], i, &a[j], j, za, 0/**cc**/); - if (sc == INT64_MIN) continue; - sc += f[j]; - if (sc > max_f) { - max_f = sc; max_j = j; - } - } - - f[i] = max_f; p[i] = max_j; ii[i] = 0; - if(f[i] < plus) plus = f[i]; - } - - for (i = 0; i < an; i++) { - f[i] -= plus; - m = f[i]; m = ((uint32_t)-1) - m; m <<= 32; m |= i; - kv_push(uint64_t, *idx, m); - } - radix_sort_bc64(idx->a, idx->a + idx->n); - - kv_resize(uint64_t, *res, ((uint64_t)an)); - for (i = rn = 0; i < an; i++) {///idx->a:: [0, ch_n) -> tree; [ch_n, ch_n + an) -> sort; [ch_n + an, -1) -> path - rn0 = rn; - for(k = (uint32_t)idx->a[i]; (k >= 0) && (!ii[k]);) { - res->a[rn++] = k; ii[k] = 1; k = p[k]; - } - if(rn0 == rn) continue; - m = rn - rn0; m = ((uint32_t)-1) - m; m <<= 32; m |= rn0; - kv_push(uint64_t, *idx, m); - } - - radix_sort_bc64(idx->a + an, idx->a + idx->n); - ch_n = idx->n; - if(!qual_a) { - for (k = an; k < ch_n; k++) { - rn0 = ((uint32_t)idx->a[k]); - rn = ((uint32_t)-1) - (idx->a[k]>>32); - // break; - plus = -1; - if(rn > 1) { - // for (i = 0; (i < rn) && (is_hpc_vec(&(a[res->a[rn0+rn-i-1]]), res->a[rn0+rn-i-1], za)); i++); - // plus = ((i < rn)?(1):(-1)); - plus = 1; - - // for (i = 0; i < rn; i++) { - // a[res->a[rn0+rn-i-1]].score = plus; - // // fprintf(stderr, "pos::%u\tsc::%ld\tn0::%u\tn1::%u\tn2::%u\tk::%lu\n", a[res->a[rn0+rn-i-1]].site, plus, a[res->a[rn0+rn-i-1]].occ_0, a[res->a[rn0+rn-i-1]].occ_1, - // // 1 + a[res->a[rn0+rn-i-1]].homopolymer_num - a[res->a[rn0+rn-i-1]].non_homopolymer_num - a[res->a[rn0+rn-i-1]].occ_0 - a[res->a[rn0+rn-i-1]].occ_1, res->a[rn0+rn-i-1]); - // } - - } else { - if((!is_hpc_vec(&(a[res->a[rn0]]), res->a[rn0], za)) && (a[res->a[rn0]].occ_0 >= cc)) plus = 1; - ///a[res->a[rn0]].score = plus; - // fprintf(stderr, "pos::%u\tsc::%ld\tn0::%u\tn1::%u\tn2::%u\tk::%lu\n", a[res->a[rn0]].site, plus, a[res->a[rn0]].occ_0, a[res->a[rn0]].occ_1, - // 1 + a[res->a[rn0]].homopolymer_num - a[res->a[rn0]].non_homopolymer_num - a[res->a[rn0]].occ_0 - a[res->a[rn0]].occ_1, res->a[rn0]); - } - - // fprintf(stderr, "\n[M::%s]\tcnt::%lu\tplus::%ld\n", __func__, rn, plus); - // if(plus > 0) { - // for (i = 0; (i < rn) && (a[res->a[rn0 + i]].occ_0 < cc); i++); - // if(i < rn) { - // for (i = 0; i < rn; i++) a[res->a[rn0 + i]].score = plus; - // } - // } - for (i = 0; i < rn; i++) { - if(a[res->a[rn0 + i]].occ_0 >= cc) { - a[res->a[rn0 + i]].score = plus; - } else { - a[res->a[rn0 + i]].score = -1; - } - // fprintf(stderr, "pos::%u\tsc::%d\tn0::%u\tn1::%u\tn2::%u\tk::%lu\n", a[res->a[rn0 + i]].site, a[res->a[rn0 + i]].score, a[res->a[rn0 + i]].occ_0, a[res->a[rn0 + i]].occ_1, - // 1 + a[res->a[rn0 + i]].homopolymer_num - a[res->a[rn0 + i]].non_homopolymer_num - a[res->a[rn0 + i]].occ_0 - a[res->a[rn0 + i]].occ_1, res->a[rn0 + i]); - } - } - } else { - int64_t b0l, b0h, b1l, b1h, krn; - /** - for (k = an; k < ch_n; k++) { - rn0 = ((uint32_t)idx->a[k]); - rn = ((uint32_t)-1) - (idx->a[k]>>32); - // break; - fprintf(stderr, "\n[M::%s]\tcnt::%lu\n", __func__, rn); - if(rn > 1) { - for (i = 0; i < rn; i++) { - get_hq_value(&(a[res->a[rn0 + i]]), res->a[rn0 + i], za, &b0l, &b0h, &b1l, &b1h, qual_a); - if(b0h > b0l && b0h >= asm_opt.s_hap_cov && b1h > b1l && b1h >= asm_opt.infor_cov) { - a[res->a[rn0 + i]].score = 1; - } else { - a[res->a[rn0 + i]].score = -1; - } - fprintf(stderr, "pos::%u\tsc::%d\tn0::%u\tn1::%u\tn2::%u\tk::%lu\tb0l::%ld\tb0h::%ld\tb1l::%ld\tb1h::%ld\n", a[res->a[rn0 + i]].site, a[res->a[rn0 + i]].score, a[res->a[rn0 + i]].occ_0, a[res->a[rn0 + i]].occ_1, - 1 + a[res->a[rn0 + i]].homopolymer_num - a[res->a[rn0 + i]].non_homopolymer_num - a[res->a[rn0 + i]].occ_0 - a[res->a[rn0 + i]].occ_1, res->a[rn0 + i], b0l, b0h, b1l, b1h); - } - } else { - if((!is_hpc_vec(&(a[res->a[rn0]]), res->a[rn0], za))) { - get_hq_value(&(a[res->a[rn0]]), res->a[rn0], za, &b0l, &b0h, &b1l, &b1h, qual_a); - if(((b0h > b0l) && (b0h > ((b0h + b0l)*0.7)) && (b0h >= asm_opt.s_hap_cov) && (b0h >= (int64_t)cc)) && - ((b1h > b1l) && (b1h > ((b1h + b1l)*0.7)) && (b1h >= asm_opt.infor_cov) && (b1h >= (int64_t)cc))) { - a[res->a[rn0]].score = 1; - } else { - a[res->a[rn0]].score = -1; - } - } - } - } - **/ - for (k = an; k < ch_n; k++) { - rn0 = ((uint32_t)idx->a[k]); - rn = ((uint32_t)-1) - (idx->a[k]>>32); - krn = rn; - // break; - - for (i = 1; (i < rn) && ((a[res->a[rn0 + i]].site + 8) >= a[res->a[rn0 + i - 1]].site); i++); - if(i >= rn) krn = 1; - // fprintf(stderr, "\n[M::%s]\tcnt::%lu\tkrn::%ld\n", __func__, rn, krn); - - for (i = 0; i < rn; i++) { - get_hq_value(&(a[res->a[rn0 + i]]), res->a[rn0 + i], za, &b0l, &b0h, &b1l, &b1h, qual_a); - if(krn > 1) { - if(b0h > b0l && b0h >= asm_opt.s_hap_cov && b1h > b1l && b1h >= asm_opt.infor_cov) { - a[res->a[rn0 + i]].score = 1; - } else { - a[res->a[rn0 + i]].score = -1; - } - } else { - if(((b0h > b0l) && (b0h > ((b0h + b0l)*0.7)) && (b0h >= asm_opt.s_hap_cov) && (b0h >= (int64_t)cc)) && - ((b1h > b1l) && (b1h > ((b1h + b1l)*0.7)) && (b1h >= asm_opt.infor_cov) && (b1h >= (int64_t)cc))) { - a[res->a[rn0 + i]].score = 1; - } else { - a[res->a[rn0 + i]].score = -1; - } - } - - // fprintf(stderr, "pos::%u\tsc::%d\tn0::%u\tn1::%u\tn2::%u\tk::%lu\tb0l::%ld\tb0h::%ld\tb1l::%ld\tb1h::%ld\n", a[res->a[rn0 + i]].site, a[res->a[rn0 + i]].score, a[res->a[rn0 + i]].occ_0, a[res->a[rn0 + i]].occ_1, - // 1 + a[res->a[rn0 + i]].homopolymer_num - a[res->a[rn0 + i]].non_homopolymer_num - a[res->a[rn0 + i]].occ_0 - a[res->a[rn0 + i]].occ_1, res->a[rn0 + i], b0l, b0h, b1l, b1h); - } - - for (i = j = 0; i < rn; i = j) { - plus = a[res->a[rn0 + i]].score; - for (j = i + 1; (j < rn) && ((a[res->a[rn0 + i]].site-a[res->a[rn0 + j]].site) == (j-i)); j++) { - if(a[res->a[rn0 + j]].score == -1) plus = -1; - } - // fprintf(stderr, "[M::%s]\ti::%ld\tj::%ld\tplus::%ld\n", __func__, i, j, plus); - if(plus == -1) { - for (; i < j; i++) { - a[res->a[rn0 + i]].score = plus; - } - } - } - - } - } - -} - -inline void fill_incom(asg64_v *om, uint64_t oid, uint64_t pe, uint64_t *idx_a, int64_t idx_n, uint64_t qid) -{ - if(om->a[oid] == ((uint64_t)-1)) { - om->a[oid] = pe; - return; - } - - uint64_t ps = om->a[oid]; int64_t k; - for (k = idx_n - 1; idx_a[k] != ps; k--); - // if(!(k >= 0)) { - // fprintf(stderr, "qid::%lu, oid::%lu, pe::%lu, ps::%lu, idx_n::%ld\n", qid, oid, pe, ps, idx_n); - // } - assert(k >= 0); - for (k++; k < idx_n; k++) { - kv_push(uint64_t, *om, ((oid<<32)|(idx_a[k]))); - } - om->a[oid] = pe; -} - -void get_wqual(uint64_t zid, uint64_t zpos, uint64_t zrev, asg8_v *v, uint8_t *va, uint64_t scw, uint64_t *tqual, uint64_t *wqual) -{ - (*tqual) = (*wqual) = 0; - uint64_t s, e, k, wk, wsc, msc, l = Get_READ_LENGTH((R_INF), (zid)); uint8_t *a; - s = ((zpos + 1 >= scw)?(zpos + 1 - scw):(0)); - e = zpos + scw; if(e > l) e = l; - - if(v) { - retrive_bqual(v, NULL, zid, s, e, zrev, sc_bn); a = v->a; - } else { - a = va + s; - } - - (*tqual) = a[zpos - s]; - for (k = s, wk = wsc = 0; k < e && wk < scw; k++, wk++) { - wsc += a[k - s]; - } - msc = wsc; - - if(k < e) { - assert(wk == scw); - for (; k < e; k++) { - wsc -= a[k - scw - s]; - wsc += a[k - s]; - if(wsc < msc) msc = wsc; - } - } - - (*wqual) = round(((double)msc)/((double)wk)); - // fprintf(stderr, "[M::%s] s::%lu, e::%lu, wk::%lu, scw::%lu, msc/wk::%lu, wqual::%lu\n", __func__, s, e, wk, scw, msc/wk, (*wqual)); -} - -void gen_rphase_dp(haplotype_evdience_alloc* hl, overlap_region_alloc* ol, UC_Read* g_read, double st_rate, uint64_t st_max, Chain_Data *dp, asg64_v *idx, asg64_v *res, uint64_t rid, asg8_v *qv) -{ - if(hl->length <= 0) return; - - uint64_t k, l, i, i0, o, ii, m_snp_stat, m_snp_stat0, m_list /**m_off**/, m1, c0, c1, rev_n, tqual, wqual, hq_cut = 2; uint32_t hq[5], hp[4], is_st; SnpStats *s; haplotype_evdience ev; char mc; - retrive_bqual(qv, NULL, rid, -1, -1, 0, sc_bn); - - idx->n = 0; - kv_resize(uint64_t, *res, ol->length); memset(res->a, -1, sizeof((*(res->a)))*ol->length); res->n = ol->length; - for (k = 1, l = 0, i = m_snp_stat = m_list = 0; k <= hl->snp_stat.n; ++k) {///filter snps - if(k == hl->snp_stat.n || hl->snp_stat.a[k].site != hl->snp_stat.a[l].site) { - for (; i < hl->length && hl->list[i].site != hl->snp_stat.a[l].site; i++); - assert(i < hl->length && hl->list[i].site == hl->snp_stat.a[l].site); - for (o = l, m1 = 0; o < k; o++) { - s = &(hl->snp_stat.a[o]); - // fprintf(stderr, "+[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, s->site, s->occ_0, s->occ_1); - if((s->occ_0 < 2 || s->occ_1 < 2) || (is_st_bs((*s), st_rate, st_max)) || (!(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov))) { - continue; - } - // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, s->site, s->occ_0, s->occ_1); - m1++; - } - - if(m1) { - hq[0] = hq[1] = hq[2] = hq[3] = hq[4] = 0; hp[0] = hp[1] = hp[2] = hp[3] = ((uint32_t)-1); - for (i0 = i, c0 = rev_n = 0; i0 < hl->length && hl->list[i0].site == hl->snp_stat.a[l].site; i0++) { - hl->list[i0].site = ((uint32_t)-1); - if(hh_tp(hl->list[i0]) == 0) { - c0 += 1/**hl->list[i0].cov**/; - if((ol->list[hl->list[i0].overlapID].y_pos_strand == 0)) rev_n += 1/**hl->list[i0].cov**/; - } - if(qv) { - if(hh_tp(hl->list[i0]) == 0) { - if((hh_bq(hl->list[i0]) > 1) || (hh_wq(hl->list[i0]) > 1)) hq[4]++; - } else { - hp[seq_nt6_table[(uint8_t)(hl->list[i0].misBase)]] = hl->list[i0].overlapSite; - if((hh_bq(hl->list[i0]) > 1) || (hh_wq(hl->list[i0]) > 1)) { - hq[seq_nt6_table[(uint8_t)(hl->list[i0].misBase)]]++; - } - } - } - } - assert(i0 > i); - if(qv) { - if(hp[0] != ((uint32_t)-1) && hq[0] < hq_cut) { - // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, hl->snp_stat.a[hp[0]].site, hl->snp_stat.a[hp[0]].occ_0, hl->snp_stat.a[hp[0]].occ_1); - hl->snp_stat.a[hp[0]].occ_1 = 0; - } - - if(hp[1] != ((uint32_t)-1) && hq[1] < hq_cut) { - // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, hl->snp_stat.a[hp[1]].site, hl->snp_stat.a[hp[1]].occ_0, hl->snp_stat.a[hp[1]].occ_1); - hl->snp_stat.a[hp[1]].occ_1 = 0; - } - - if(hp[2] != ((uint32_t)-1) && hq[2] < hq_cut) { - // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, hl->snp_stat.a[hp[2]].site, hl->snp_stat.a[hp[2]].occ_0, hl->snp_stat.a[hp[2]].occ_1); - hl->snp_stat.a[hp[2]].occ_1 = 0; - } - - if(hp[3] != ((uint32_t)-1) && hq[3] < hq_cut) { - // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, hl->snp_stat.a[hp[3]].site, hl->snp_stat.a[hp[3]].occ_0, hl->snp_stat.a[hp[3]].occ_1); - hl->snp_stat.a[hp[3]].occ_1 = 0; - } - - get_wqual(rid, hl->snp_stat.a[l].site, 0, NULL, qv->a, sc_wn, &tqual, &wqual); - if(tqual > 1 || wqual > 1) hq[4]++; - // if(hq[4] == 0) { - // fprintf(stderr, "+[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, hl->snp_stat.a[l].site, hl->snp_stat.a[l].occ_0, hl->snp_stat.a[l].occ_1); - // } - } else { - hq[0] = hq[1] = hq[2] = hq[3] = hq[4] = ((uint32_t)-1); - } - - if((hq[4] >= hq_cut) && (hq[0] >= hq_cut || hq[1] >= hq_cut || hq[2] >= hq_cut || hq[3] >= hq_cut)) { - for (o = l, m_snp_stat0 = m_snp_stat; o < k; o++) { - s = &(hl->snp_stat.a[o]); - if((s->occ_0 < 2 || s->occ_1 < 2) || (is_st_bs((*s), st_rate, st_max)) || (!(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov))) { - continue; - } - - hl->snp_stat.a[m_snp_stat] = *s; - for (ii = i, c1 = 0; ii < i0; ii++) { - if(((hl->list[ii].overlapSite == o) && (hl->list[ii].site == ((uint32_t)-1))) || (hh_tp(hl->list[ii]) == 0)) { - hl->list[ii].overlapSite = m_snp_stat; - hl->list[ii].site = hl->snp_stat.a[o].site; - if(hh_tp(hl->list[ii]) == 1) c1 += 1/**hl->list[ii].cov**/;///not correct if we don't do read correction - } - } - // fprintf(stderr, "-0-[M::%s]\tsite::%u\tc0::%lu\tc1::%lu\n", __func__, s->site, c0, c1); - hl->snp_stat.a[m_snp_stat].occ_0 = c0 + 1; - hl->snp_stat.a[m_snp_stat].occ_1 = c1; - hl->snp_stat.a[m_snp_stat].overlap_num = rev_n + 1; - hl->snp_stat.a[m_snp_stat].non_homopolymer_num = m_list; - hl->snp_stat.a[m_snp_stat++].score = -1; - } - - for (ii = i, m1 = m_list; ii < i0; ii++) { - if((hl->list[ii].site == ((uint32_t)-1))) { - hl->list[ii].overlapSite = ((uint32_t)-1); - hl->list[ii].site = hl->snp_stat.a[l].site; - } - fill_incom(res, hl->list[ii].overlapID, hl->list[ii].site, idx->a, idx->n, ol->list[0].x_id); - hl->list[m_list++] = hl->list[ii]; - } - radix_sort_haplotype_evdience_id_srt(hl->list + m1, hl->list + m_list); - for (ii = m_snp_stat0; ii < m_snp_stat; ii++) { - hl->snp_stat.a[ii].homopolymer_num = m_list; - } - - i = i0; - - kv_push(uint64_t, *idx, hl->snp_stat.a[l].site); - } - } - - l = k; - } - } - hl->snp_stat.n = m_snp_stat; hl->length = m_list; - if(hl->snp_stat.n == 0 || hl->length == 0) return; - - - ///fill incomplete values - if(res->n > ol->length) { - // fprintf(stderr, "\n[M::%s]\tin_comp::%lu\n", __func__, ((uint64_t)res->n - ol->length)); - for (k = ol->length; k < res->n; k++) { - ev.misBase = 0; - ev.overlapID = res->a[k]>>32; - ev.site = ((uint32_t)res->a[k]); - ev.overlapSite = ((uint32_t)-1); - ev.type = 0; - ev.cov = 1; - addHaplotypeEvdience(hl, &ev, NULL); - // fprintf(stderr, "[M::%s]\toid::%u\tsite::%u\n", __func__, ev.overlapID, ev.site); - } - radix_sort_haplotype_evdience_srt(hl->list, hl->list + hl->length); - - for (k = 1, l = 0, i = 0; k <= hl->snp_stat.n; ++k) { - if(k == hl->snp_stat.n || hl->snp_stat.a[k].site != hl->snp_stat.a[l].site) { - for (; i < hl->length && hl->list[i].site != hl->snp_stat.a[l].site; i++); - assert(i < hl->length && hl->list[i].site == hl->snp_stat.a[l].site); - - m1 = ((uint32_t)-1); mc = 0; - for (i0 = i, c0 = rev_n = 0; i0 < hl->length && hl->list[i0].site == hl->snp_stat.a[l].site; i0++) { - if(hh_tp(hl->list[i0]) == 0) { - c0+=1/**hl->list[i0].cov**/; - if((ol->list[hl->list[i0].overlapID].y_pos_strand == 0)) rev_n += 1/**hl->list[i0].cov**/; - if(hl->list[i0].overlapSite != ((uint32_t)-1)) { - m1 = hl->list[i0].overlapSite; mc = hl->list[i0].misBase; - } - } - // if(hl->snp_stat.a[l].site == 6995) { - // fprintf(stderr, "[M::%s]\tsite::%u\tosite::%u\toid::%u\ttp::%u\n", __func__, hl->list[i0].site, hl->list[i0].overlapSite, hl->list[i0].overlapID, hh_tp(hl->list[i0])); - // } - } - assert(i0 > i); - assert(m1 != ((uint32_t)-1)); - assert(mc != 0); - - - for (ii = i, is_st = 1; ii < i0; ii++) { - if(hh_tp(hl->list[ii]) == 0) { - assert(hl->list[ii].overlapSite == ((uint32_t)-1) || hl->list[ii].overlapSite == m1); - hl->list[ii].overlapSite = m1; hl->list[ii].misBase = mc; - } - if((ii > i) && (hl->list[ii].overlapID <= hl->list[ii-1].overlapID)) { - is_st = 0; - // fprintf(stderr, "[M::%s]\tid::[%u,%u]\tsite::[%u,%u]\n", __func__, hl->list[ii].overlapID, hl->list[ii-1].overlapID, hl->list[ii].overlapSite, hl->list[ii-1].overlapSite); - } - } - if(is_st == 0) radix_sort_haplotype_evdience_id_srt(hl->list + i, hl->list + i0); - // assert(is_st == 1); - - - - for (o = l; o < k; o++) { - s = &(hl->snp_stat.a[o]); - for (ii = i, c1 = 0; ii < i0; ii++) { - if((hl->list[ii].overlapSite == o) && (hh_tp(hl->list[ii]) == 1)) c1 += 1/**hl->list[ii].cov**/;///not correct if we don't do read correction - } - // fprintf(stderr, "-1-[M::%s]\tsite::%u\tc0::%lu\tc1::%lu\n", __func__, s->site, c0, c1); - s->occ_0 = c0 + 1; - s->occ_1 = c1; - s->overlap_num = rev_n + 1; - s->non_homopolymer_num = i; - s->homopolymer_num = i0; - } - - i = i0; - l = k; - } - } - - } - - - - - - // gen_rphase_dp0_multiple_path(hl->snp_stat.a, hl->snp_stat.n, hl->list, dp, idx, res); - gen_rphase_dp0_single_path(hl->snp_stat.a, hl->snp_stat.n, hl->list, dp, idx, asm_opt.het_cov, asm_opt.hom_cov, asm_opt.polyploidy, 0.7, 6, res, qv->a); - - for (k = 1, l = 0, i = m_snp_stat = m_list = 0; k <= hl->snp_stat.n; ++k) {///filter snps - if(k == hl->snp_stat.n || hl->snp_stat.a[k].site != hl->snp_stat.a[l].site) { - for (; i < hl->length && hl->list[i].site != hl->snp_stat.a[l].site; i++); - assert(i < hl->length && hl->list[i].site == hl->snp_stat.a[l].site); - for (o = l, m1 = 0; o < k; o++) { - s = &(hl->snp_stat.a[o]); - if(s->score == -1) continue; - m1++; - } - - if(m1) { - for (i0 = i, c0 = rev_n = 0; i0 < hl->length && hl->list[i0].site == hl->snp_stat.a[l].site; i0++) { - hl->list[i0].site = ((uint32_t)-1); - if(hh_tp(hl->list[i0]) == 0) { - c0 += 1/**hl->list[i0].cov**/; - if((ol->list[hl->list[i0].overlapID].y_pos_strand == 0)) rev_n += 1/**hl->list[i0].cov**/; - } - } - assert(i0 > i); - - for (o = l, m_snp_stat0 = m_snp_stat; o < k; o++) { - s = &(hl->snp_stat.a[o]); - if(s->score == -1) continue; - - hl->snp_stat.a[m_snp_stat] = *s; - for (ii = i, c1 = 0; ii < i0; ii++) { - if(((hl->list[ii].overlapSite == o) && (hl->list[ii].site == ((uint32_t)-1))) || (hh_tp(hl->list[ii]) == 0)) { - hl->list[ii].overlapSite = m_snp_stat; - hl->list[ii].site = hl->snp_stat.a[o].site; - if(hh_tp(hl->list[ii]) == 1) c1 += 1/**hl->list[ii].cov**/;///not correct if we don't do read correction - } - } - - // if(hl->snp_stat.a[m_snp_stat].site == 4) { - // fprintf(stderr, "[M::%s] occ_0->%lu, occ_1->%lu, site->%u\n", __func__, c0 + 1, c1, hl->snp_stat.a[m_snp_stat].site); - // } - - hl->snp_stat.a[m_snp_stat].occ_0 = c0 + 1; - hl->snp_stat.a[m_snp_stat].occ_1 = c1; - hl->snp_stat.a[m_snp_stat].overlap_num = rev_n + 1; - hl->snp_stat.a[m_snp_stat].non_homopolymer_num = m_list; - hl->snp_stat.a[m_snp_stat++].score = -1; - } - - for (ii = i, m1 = m_list; ii < i0; ii++) { - if((hl->list[ii].site == ((uint32_t)-1))) continue; - hl->list[m_list++] = hl->list[ii]; - } - for (ii = m_snp_stat0; ii < m_snp_stat; ii++) { - hl->snp_stat.a[ii].homopolymer_num = m_list; - } - - i = i0; - } - - l = k; - } - } - hl->snp_stat.n = m_snp_stat; hl->length = m_list; - -} - -void generate_haplotypes_naive_UL(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, double up, void *km) -{ - if(hap->length == 0) return; - uint64_t k, l, i, o, *a, ii, m_snp_stat, m_list, m_off; - int64_t z; - SnpStats *s = NULL, *t = NULL; - - for (k = 1, l = 0, i = m_snp_stat = m_list = 0; k <= hap->snp_stat.n; ++k) {///filter snps - if(k == hap->snp_stat.n || hap->snp_stat.a[k].site != hap->snp_stat.a[l].site) { - if((l > 0) && (hap->snp_stat.a[l].site == (hap->snp_stat.a[l-1].site + 1))) { - l = k; continue; - } - if((k < hap->snp_stat.n) && ((hap->snp_stat.a[l].site+1) == hap->snp_stat.a[k].site)) { - l = k; continue; - } - - for (; i < hap->length && hap->list[i].site != hap->snp_stat.a[l].site; i++); - assert(i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site); - m_off = l - m_snp_stat; - for (; i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site; i++) { - assert(hap->list[i].overlapSite>=l && hap->list[i].overlapSite < k); - // assert(hap->snp_stat.a[hap->list[i].overlapSite].site==hap->list[i].site); - hap->list[m_list] = hap->list[i]; hap->list[m_list++].overlapSite -= m_off; - } - - for (; l < k; l++) hap->snp_stat.a[m_snp_stat++] = hap->snp_stat.a[l]; - } - } - hap->snp_stat.n = m_snp_stat; hap->length = m_list; - if(hap->snp_stat.n == 0 || hap->length == 0) return; - - hap->snp_srt.n = 0; - radix_sort_haplotype_evdience_id_srt(hap->list, hap->list + hap->length); - for (k = 1, l = 0; k <= hap->length; ++k) { - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - for (i = l, o = 0; i < k; i++) { - if(hap->list[i].type!=1) continue;///mismatch - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - assert(s->site == hap->list[i].site); - if(s->occ_0 < 2 || s->occ_1 < 2) continue; - if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) o++;///allels must be real - } - if(o > 0) { - o = ((uint32_t)-1) - o; - o <<= 32; o += l; - if(!km) kv_push(uint64_t, hap->snp_srt, o); - else kv_push_km(km, uint64_t, hap->snp_srt, o); - } - l = k; - } - } - - if (hap->snp_srt.n > 0) { - radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n);///sort by how many snps in one overlap - for (k = 0; k < hap->snp_srt.n; k++) { - o = 0; l = (uint32_t)hap->snp_srt.a[k]; - for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { - if(hap->list[i].type!=1) continue; - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->occ_0 < 2 || s->occ_1 < 2) continue; - if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) o++; - } - if(o == 0) continue; - - ii = hap->list[l].overlapID; - if(overlap_list->list[ii].is_match == 1) overlap_list->list[ii].is_match = 2; - for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { - if(hap->list[i].type==1){ - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - s->score = 1; - } ///else if((hap->list[i].type==0) && (o>=(overlap_list->list[ii].align_length*up))) { - else if(hap->list[i].type==0) { - ///not real allels - z = hap->list[i].overlapSite; s = &(hap->snp_stat.a[z]); - for (z = hap->list[i].overlapSite; z >= 0; z--) { - t = &(hap->snp_stat.a[z]); - if(s->site!=t->site) break; - t->occ_0 -= hap->list[i].cov; - assert(t->occ_0 >= 1); - } - } - } - } - - for (k = 0; k < hap->snp_srt.n; k++) {///sorted by how many allels in each overlap; more -> less - o = 0; l = (uint32_t)hap->snp_srt.a[k]; - for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { - if(hap->list[i].type!=1) continue; - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->occ_0 < 2 || s->occ_1 < 2) continue; - if(s->score == 1) o++; - } - ii = hap->list[l].overlapID; - ///for HiFi, do not flip trans to cis - // if(overlap_list->list[ii].is_match == 2 && o == 0) { - // overlap_list->list[ii].is_match = 1; - // } - if(overlap_list->list[ii].is_match == 1 && o > 0) { - overlap_list->list[ii].is_match = 2; - } - } - - - for (k = 1, l = 0; k <= hap->length; ++k) { ///reset snp_stat - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - ii = hap->list[l].overlapID; - if(overlap_list->list[ii].is_match==1) { - for (i = l; i < k; i++) { - if(hap->list[i].type==1) { - hap->snp_stat.a[hap->list[i].overlapSite].score = -1; - } - } - } - l = k; - } - } - } - - - - hap->snp_srt.n = 0; - for (k = 1, l = 0; k <= hap->length; ++k) { - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - if(overlap_list->list[hap->list[l].overlapID].is_match == 2) { - l = k; - continue; - } - for (i = l, o = 0; i < k; i++) { - if(hap->list[i].type!=1) continue; - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->occ_0 < 2 || s->occ_1 < 2) continue; - if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) continue; - if(s->score == 1) continue; - o++; - if(!km) kv_push(uint64_t, hap->snp_srt, hap->list[i].overlapSite); - else kv_push_km(km, uint64_t, hap->snp_srt, hap->list[i].overlapSite); - } - hap->snp_srt.n -= o; - ///there are at least two variants at one read - if(o>=(overlap_list->list[hap->list[l].overlapID].align_length*up)) { - radix_sort_bc64(hap->snp_srt.a + hap->snp_srt.n, hap->snp_srt.a + hap->snp_srt.n + o); - a = hap->snp_srt.a + hap->snp_srt.n; - for (i = z = 0; i < o; i++) { - if(i > 0) s = &(hap->snp_stat.a[a[i-1]]); - if(i + 1 < o) t = &(hap->snp_stat.a[a[i+1]]); - if(s && s->site + 32 > hap->snp_stat.a[a[i]].site) continue; - if(t && hap->snp_stat.a[a[i]].site + 32 > t->site) continue; - a[z] = a[i]; - z++; - } - if(z >= 2) hap->snp_srt.n += z; - } - l = k; - } - } - if (hap->snp_srt.n > 0) { - radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n); - for (k = 1, l = 0; k <= hap->snp_srt.n; ++k) { - if(k == hap->snp_srt.n || hap->snp_srt.a[k] != hap->snp_srt.a[l]) { - if(k - l >= 2) hap->snp_stat.a[hap->snp_srt.a[l]].score = 1; - } - l = k; - } - } - - for (k = 1, l = 0; k <= hap->length; ++k) { - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - ii = hap->list[l].overlapID; - if(overlap_list->list[ii].is_match==2) { - overlap_list->list[ii].strong = 1; - overlap_list->mapped_overlaps_length -= - overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; - } else if(overlap_list->list[ii].is_match==1) { - for (i = l; i < k; i++) { - if(hap->list[i].type==1 || hap->list[i].type==0) { - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->score == 1 && (!(s->occ_0 < 2 || s->occ_1 < 2))) { - overlap_list->list[ii].strong = 1; - if(hap->list[i].type==1) { - overlap_list->list[ii].is_match = 2; - overlap_list->mapped_overlaps_length -= - overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; - break; - } - } - } - - } - } - l = k; - } - } -} - -/** -void partition_overlaps(overlap_region_alloc* overlap_list, All_reads* R_INF, - UC_Read* g_read, Correct_dumy* dumy, haplotype_evdience_alloc* hap, - int force_repeat) -{ - ResizeInitHaplotypeEvdience(hap); - - long long i; - long long window_start, window_end; - - long long num_availiable_win = 0; - - Window_Pool w_inf; - init_Window_Pool(&w_inf, g_read->length, WINDOW, (int)(1.0/asm_opt.max_ov_diff_ec)); - - int flag = 0; - while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) - { - dumy->length = 0; - dumy->lengthNT = 0; - - ///return overlaps that is overlaped with [window_start, window_end] - flag = get_available_interval(window_start, window_end, overlap_list, dumy); - switch (flag) - { - case 1: ///found matched overlaps - break; - case 0: ///do not find any matched overlaps - break; - case -2: ///do not find any matched overlaps, and the next window also cannot match - break; - } - - num_availiable_win = num_availiable_win + dumy->length; - - cluster(g_read->seq, window_start, window_end, overlap_list, dumy, R_INF, hap); - } - - ///very time-consuming - qsort(hap->list, hap->length, sizeof(haplotype_evdience), cmp_haplotype_evdience); - - - - - ///debug_hap_information(overlap_list, R_INF, g_read, hap, dumy); - - SetSnpMatrix(hap, &(hap->nn_snp), &(overlap_list->length), 1, NULL); - - - uint64_t pre_site = (uint64_t)-1; - uint64_t num_of_snps = 0; - long long pre_i = -1; - long long sub_length; - haplotype_evdience* sub_list; - - ////split reads - for (i = 0; i < hap->length; i++) - { - if(pre_site != hap->list[i].site) - { - if(i != 0) - { - sub_list = hap->list + pre_i; - sub_length = i - pre_i; - split_sub_list(hap, sub_list, sub_length, overlap_list, R_INF, g_read); - } - num_of_snps++; - pre_site = hap->list[i].site; - pre_i = i; - } - } - - if(pre_i != -1) - { - sub_list = hap->list + pre_i; - sub_length = i - pre_i; - split_sub_list(hap, sub_list, sub_length, overlap_list, R_INF, g_read); - } - - ///debug_snp_matrix(hap); - generate_haplotypes_DP(hap, overlap_list, R_INF, g_read->length, force_repeat); - ///generate_haplotypes_naive(hap, overlap_list, R_INF, g_read->length, force_repeat); - - lable_large_indels(overlap_list, g_read->length, dumy, asm_opt.max_ov_diff_ec); - - - ///debug_snp_matrix(hap); -} -**/ - -void partition_overlaps_advance_back(overlap_region_alloc* overlap_list, All_reads* R_INF, - UC_Read* g_read, UC_Read* overlap_read, Correct_dumy* dumy, - haplotype_evdience_alloc* hap, int force_repeat) -{ - ResizeInitHaplotypeEvdience(hap); - - long long i; - long long window_start, window_end; - - long long num_availiable_win = 0; - - Window_Pool w_inf; - init_Window_Pool(&w_inf, g_read->length, WINDOW, (int)(1.0/asm_opt.max_ov_diff_ec)); - - int flag = 0; - while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) - { - dumy->length = 0; - dumy->lengthNT = 0; - ///return overlaps that is overlaped with [window_start, window_end] - flag = get_available_interval(window_start, window_end, overlap_list, dumy); - switch (flag) - { - case 1: ///found matched overlaps - break; - case 0: ///do not find any matched overlaps - break; - case -2: ///do not find any matched overlaps, and the next window also cannot match - break; - } - - num_availiable_win = num_availiable_win + dumy->length; - - ///need to deal with - cluster_advance(g_read->seq, window_start, window_end, overlap_list, - dumy, R_INF, hap, overlap_read, 1); - } - - - - ///very time-consuming - ///Fix-attention ---> able to be sorted locally - // qsort(hap->list, hap->length, sizeof(haplotype_evdience), cmp_haplotype_evdience); - SetSnpMatrix(hap, &(hap->nn_snp), &(overlap_list->length), 1, NULL); - - uint64_t pre_site = (uint64_t)-1; - uint64_t num_of_snps = 0; - long long pre_i = -1; - long long sub_length; - haplotype_evdience* sub_list; - - ////split reads - for (i = 0; i < hap->length; i++) - { - if(pre_site != hap->list[i].site) - { - if(i != 0) - { - sub_list = hap->list + pre_i; - sub_length = i - pre_i; - split_sub_list(hap, sub_list, sub_length, overlap_list, R_INF, g_read); - } - num_of_snps++; - pre_site = hap->list[i].site; - pre_i = i; - } - } - - if(pre_i != -1) - { - sub_list = hap->list + pre_i; - sub_length = i - pre_i; - split_sub_list(hap, sub_list, sub_length, overlap_list, R_INF, g_read); - } - - generate_haplotypes_DP(hap, overlap_list, R_INF, g_read->length, force_repeat); - ///generate_haplotypes_naive(hap, overlap_list, R_INF, g_read->length, force_repeat); - - lable_large_indels(overlap_list, g_read->length, dumy, asm_opt.max_ov_diff_ec); -} - -inline void insert_snp_vv(haplotype_evdience_alloc* h, haplotype_evdience* a, uint64_t a_n, char misBase, UC_Read* g_read, void *km) -{ - if(a_n == 0) return; - SnpStats *p = NULL; uint64_t /**nn = 0,**/ i; - if(!km) kv_pushp(SnpStats, h->snp_stat, &p); - else kv_pushp_km(km, SnpStats, h->snp_stat, &p); - p->id = h->snp_stat.n-1; - p->occ_0 = 1; - p->occ_1 = 0; - p->occ_2 = 0; - p->overlap_num = 0; - p->site = a[0].site; - p->is_homopolymer = if_is_homopolymer_strict(p->site, g_read->seq, g_read->length); - for (i = 0; i < a_n; i++) { - if(a[i].type == 0) { - a[i].overlapSite = p->id; - h->snp_stat.a[p->id].occ_0 += a[i].cov; - } - else if(a[i].type == 1 && a[i].misBase == misBase) { - a[i].overlapSite = p->id; - h->snp_stat.a[p->id].occ_1 += a[i].cov; - } - else { - h->snp_stat.a[p->id].occ_2 += a[i].cov; - } - h->snp_stat.a[p->id].overlap_num += a[i].cov; - } - h->snp_stat.a[p->id].score = -1; -} - - -int insert_snp_ee(haplotype_evdience_alloc* h, haplotype_evdience* a, uint64_t a_n, haplotype_evdience* u_a, UC_Read* g_read, void *km) -{ - uint64_t i, m, occ_0, occ_1[6], occ_2, diff; - occ_0 = occ_2 = diff = 0; memset(occ_1, 0, sizeof(uint64_t)*6); - - for (i = 0; i < a_n; i++) { - if(a[i].type == 0){ - occ_0 += a[i].cov; - }else if(a[i].type == 1){ - occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]] += a[i].cov; - diff += a[i].cov; - } - // else if(a[i].type == 2){ - // occ_2++; - // diff++; - // } - occ_2 += a[i].cov; - } - - /** - 1. if occ_0 = 0, that means all overlaps are different with this read at this site - 2. it is not possible that occ_1 = 0, - 3. if occ_1 = 1, there are only one difference. It must be a sequencing error. - (for repeat, it maybe a snp at repeat. but ...) - **/ - SnpStats *p = NULL; - uint32_t is_homopolymer = (uint32_t)-1; - if(occ_0 == 0 || diff <= 1) return 0; - for (i = m = 0; i < 4; i++) { - if(occ_1[i] >= 2){ - if(!km) kv_pushp(SnpStats, h->snp_stat, &p); - else kv_pushp_km(km, SnpStats, h->snp_stat, &p); - p->id = h->snp_stat.n-1; - p->occ_0 = 1 + occ_0; - p->occ_1 = occ_1[i]; - p->occ_2 = occ_2 - p->occ_0 - p->occ_1; - p->overlap_num = 0; - p->site = a[0].site; - p->score = -1; - p->overlap_num = occ_2; - if(is_homopolymer == (uint32_t)-1) { - is_homopolymer = if_is_homopolymer_strict(p->site, g_read->seq, g_read->length); - } - p->is_homopolymer = is_homopolymer; - occ_1[i] = p->id; - m++; - } else { - occ_1[i] = (uint64_t)-1; - } - } - occ_1[4] = occ_1[5] = (uint64_t)-1; - if(m == 0) return 0; - - for (i = m = 0; i < a_n; i++) { - // fprintf(stderr, "[M::%s] a[%lu].misBase->%c\n", __func__, i, a[i].misBase); - if(a[i].type == 0) { - a[i].overlapSite = h->snp_stat.n-1; - } else if(occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]]!=(uint64_t)-1){ - a[i].cov = a[i].overlapSite;///note: only renew cov here!!! - a[i].overlapSite = occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]]; - } else { - continue; - } - u_a[m++] = a[i]; - } - - /** - // if(c_snp && ovlp) { - // ; - // } - for (i = m = 0; i < 4; i++) { - if(occ_1[i] >= 2) { - insert_snp_vv(h, a, a_n, s_H[i], g_read, km); - m++; - } - } - if(m == 0) return 0; - - for (i = m = 0; i < a_n; i++) { - if(a[i].type == 0){ - u_a[m++] = a[i]; - }else if(a[i].type == 1){ - if(occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]] >= 2) u_a[m++] = a[i]; - } - } - **/ - - return m; -} - - -uint8_t hpc_mask_ff(char *sa, int64_t sn, int64_t p, int64_t hpc_flk, int64_t hpc_rr, uint8_t *f, int64_t fn, int64_t fsift, int64_t hpc_cutoff) -{ - int64_t s = ((p>=hpc_flk)?(p-hpc_flk):0), e = (((p+hpc_flk)<=sn)?(p+hpc_flk):(sn)), k, r, rc, zs, ze; - - for (r = 1; r <= hpc_rr; r++) { - rc = r * hpc_cutoff/**HPC_CC**/; - - ///inlcuding p - for (k = p + r; (k < e) && ((k-r) >= s) && (sa[k] == sa[k-r]); k++); ze = k; if(ze > e) ze = e; - for (k = p - 1; (k >= s) && ((k+r) < e) && (sa[k] == sa[k+r]); k--); zs = k + 1; if(zs < s) zs = s; - if(((ze - zs) > r) && ((ze - zs) >= rc)) { - // fprintf(stderr, "-0-[M::%s] p::%ld, hh::[%ld,%ld), f::%u, %.*s\n", __func__, p, zs, ze, f?1:0, (int32_t)(ze - zs), sa + zs); - if(f) { - for (k = MAX(p, zs); (k < ze) && (k - fsift < fn); k++) f[k - fsift] = 0; f[p - fsift] = 0; - } - return 1; - } - - ///do not inlcude p - for (k = p + r + 1; (k < e) && ((k-r) >= s) && (sa[k] == sa[k-r]); k++); - zs = p + 1; if(zs < s) zs = s; ze = k; if(ze > e) ze = e; - if(((ze - zs) > r) && ((ze - zs) >= rc)) { - // fprintf(stderr, "-1-[M::%s] p::%ld, hh::[%ld,%ld), f::%u, %.*s\n", __func__, p, zs, ze, f?1:0, (int32_t)(ze - zs), sa + zs); - if(f) { - for (k = MAX(p, zs); (k < ze) && (k - fsift < fn); k++) f[k - fsift] = 0; f[p - fsift] = 0; - } - return 1; - } - - ///inlcuding p - for (k = p - r; (k >= s) && ((k+r) < e) && (sa[k] == sa[k+r]); k--); zs = k + 1; if(zs < s) zs = s; - for (k = p + 1; (k < e) && ((k-r) >= s) && (sa[k] == sa[k-r]); k++); ze = k; if(ze > e) ze = e; - if(((ze - zs) > r) && ((ze - zs) >= rc)) { - // fprintf(stderr, "-2-[M::%s] p::%ld, hh::[%ld,%ld), f::%u, %.*s\n", __func__, p, zs, ze, f?1:0, (int32_t)(ze - zs), sa + zs); - if(f) { - for (k = MAX(p, zs); (k < ze) && (k - fsift < fn); k++) f[k - fsift] = 0; f[p - fsift] = 0; - } - return 1; - } - - ///do not inlcude p - for (k = p - r - 1; (k >= s) && ((k+r) < e) && (sa[k] == sa[k+r]); k--); - zs = k + 1; if(zs < s) zs = s; ze = p; if(ze > e) ze = e; - if(((ze - zs) > r) && ((ze - zs) >= rc)) { - // fprintf(stderr, "-3-[M::%s] p::%ld, hh::[%ld,%ld), f::%u, %.*s\n", __func__, p, zs, ze, f?1:0, (int32_t)(ze - zs), sa + zs); - if(f) { - for (k = MAX(p, zs); (k < ze) && (k - fsift < fn); k++) f[k - fsift] = 0; f[p - fsift] = 0; - } - return 1; - } - } - // fprintf(stderr, "-6-[M::%s] p::%ld, hh::[,), %.*s\n", __func__, p, (int32_t)(e - s), sa + s); - return 0; -} - -uint8_t hpc_mask_ff_region(char *sa, int64_t sn, int64_t s0, int64_t e0, int64_t hpc_flk, int64_t hpc_rr, int64_t hpc_cutoff, double hpc_rate) -{ - assert(e0>=s0); - int64_t s = ((s0>=hpc_flk)?(s0-hpc_flk):0), e = (((e0+hpc_flk)<=sn)?(e0+hpc_flk):(sn)), k, r, rc, zs, ze, os, oe, ovlp; - - for (r = 1; r <= hpc_rr; r++) { - rc = r * (MAX(hpc_cutoff, hpc_rr));///hpc_cutoff = 6; - - ///inlcuding p - for (k = ((e0>s0)?(e0-1):(e0))+r; (k < e) && ((k-r) >= s) && (sa[k] == sa[k-r]); k++); ze = k; if(ze > e) ze = e; - for (k = ((e0>s0)?(e0-1):(e0))-1; (k >= s) && ((k+r) < e) && (sa[k] == sa[k+r]); k--); zs = k + 1; if(zs < s) zs = s; - if(((ze - zs) > r) && ((ze - zs) >= rc)) { - os = MAX(zs, s0); oe = MIN(ze, e0); - ovlp = ((oe>os)? (oe-os):0); - if(e0 > s0) { - if(ovlp > 0 && (ovlp >= ((e0 - s0)*hpc_rate))) return 1;///hpc_rate = 0.51 - } else { - if(zs <= s0 && ze >= e0) return 1; - } - } - - ///do not inlcude p - if(e0 <= s0) { - for (k = e0 + r + 1; (k < e) && ((k-r) >= s) && (sa[k] == sa[k-r]); k++); - zs = e0 + 1; if(zs < s) zs = s; ze = k; if(ze > e) ze = e; - if(((ze - zs) > r) && ((ze - zs) >= rc)) { - // fprintf(stderr, "-1-[M::%s] p::%ld, hh::[%ld,%ld), f::%u, %.*s\n", __func__, p, zs, ze, f?1:0, (int32_t)(ze - zs), sa + zs); - return 1; - } - } - - ///inlcuding p - for (k = s0 - r; (k >= s) && ((k+r) < e) && (sa[k] == sa[k+r]); k--); zs = k + 1; if(zs < s) zs = s; - for (k = s0 + 1; (k < e) && ((k-r) >= s) && (sa[k] == sa[k-r]); k++); ze = k; if(ze > e) ze = e; - if(((ze - zs) > r) && ((ze - zs) >= rc)) { - os = MAX(zs, s0); oe = MIN(ze, e0); - ovlp = ((oe>os)? (oe-os):0); - if(e0 > s0) { - if(ovlp > 0 && (ovlp >= ((e0 - s0)*hpc_rate))) return 1; - } else { - if(zs <= s0 && ze >= e0) return 1; - } - } - - ///do not inlcude p - if(e0 <= s0) { - for (k = s0 - r - 1; (k >= s) && ((k+r) < e) && (sa[k] == sa[k+r]); k--); - zs = k + 1; if(zs < s) zs = s; ze = s0; if(ze > e) ze = e; - if(((ze - zs) > r) && ((ze - zs) >= rc)) { - return 1; - } - } - } - // fprintf(stderr, "-6-[M::%s] p::%ld, hh::[,), %.*s\n", __func__, p, (int32_t)(e - s), sa + s); - return 0; -} - -int push_info(haplotype_evdience_alloc* h, haplotype_evdience* a, uint64_t a_n, haplotype_evdience* u_a, overlap_region *oa, asg8_v *v8, uint64_t scw) -{ - uint64_t i, k, m, occ_0, occ_1[6], occ_2, diff, rev_n; uint8_t ihpc = 0; - occ_0 = occ_2 = diff = rev_n = 0; memset(occ_1, 0, sizeof(uint64_t)*6); - - radix_sort_haplotype_evdience_id_srt(a, a + a_n); - for (k = 1, m = i = 0; k <= a_n; k++) { - if((k == a_n) || (a[k].overlapID != a[m].overlapID)) { - a[i] = a[m]; - if(hh_tp(a[i]) == 0){ - occ_0 += a[i].cov; - if((oa) && (oa[a[i].overlapID].y_pos_strand == 0)) { - rev_n += a[i].cov; - } - if((!ihpc) && (hh_hp(a[i]))) ihpc = 1; - }else if(hh_tp(a[i]) == 1){ - occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]] += a[i].cov; - diff += a[i].cov; - } - occ_2 += a[i].cov; - - i++; m = k; - } - } - a_n = i; - - // for (i = 0; i < a_n; i++) { - // if(hh_tp(a[i]) == 0){ - // occ_0 += a[i].cov; - // if((oa) && (oa[a[i].overlapID].y_pos_strand == 0)) { - // rev_n += a[i].cov; - // } - // if((!ihpc) && (hh_hp(a[i]))) ihpc = 1; - // }else if(hh_tp(a[i]) == 1){ - // occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]] += a[i].cov; - // diff += a[i].cov; - // } - // occ_2 += a[i].cov; - // } - - - /** - 1. if occ_0 = 0, that means all overlaps are different with this read at this site - 2. it is not possible that occ_1 = 0, - 3. if occ_1 = 1, there are only one difference. It must be a sequencing error. - (for repeat, it maybe a snp at repeat. but ...) - **/ - SnpStats *p = NULL; - if(occ_0 == 0 || diff <= 1) return 0; - if((oa) && (rev_n == occ_0)) return 0; - if(!oa) { - rev_n = occ_2; - } else { - rev_n++; - } - - for (i = m = 0; i < 4; i++) { - if(occ_1[i] >= 2){ - kv_pushp(SnpStats, h->snp_stat, &p); - p->id = h->snp_stat.n-1; - p->occ_0 = 1 + occ_0; - p->occ_1 = occ_1[i]; - p->occ_2 = occ_2 - p->occ_0 - p->occ_1; - p->site = a[0].site; - p->score = -1; - p->overlap_num = rev_n; - p->is_homopolymer = ihpc; - occ_1[i] = p->id; - m++; - // fprintf(stderr, "[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, p->site, p->occ_0, p->occ_1); - } else { - occ_1[i] = (uint64_t)-1; - } - } - occ_1[4] = occ_1[5] = (uint64_t)-1; - if(m == 0) return 0; - - if(!v8) { - for (i = m = 0; i < a_n; i++) { - // fprintf(stderr, "[M::%s] a[%lu].misBase->%c\n", __func__, i, a[i].misBase); - if(hh_tp(a[i]) == 0) { - a[i].overlapSite = h->snp_stat.n-1; - } else if(occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]]!=(uint64_t)-1){ - a[i].cov = a[i].overlapSite;///note: only renew cov here!!! - a[i].overlapSite = occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]]; - } else { - continue; - } - u_a[m++] = a[i]; - } - } else { - uint64_t tpos, tqual, wqual; - for (i = m = 0; i < a_n; i++) { - tpos = a[i].overlapSite; - if(hh_tp(a[i]) == 0) { - a[i].overlapSite = h->snp_stat.n-1; - } else if(occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]]!=(uint64_t)-1){ - a[i].cov = a[i].overlapSite;///note: only renew cov here!!! - a[i].overlapSite = occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]]; - } else { - continue; - } - get_wqual(oa[a[i].overlapID].y_id, tpos, oa[a[i].overlapID].y_pos_strand, v8, NULL, scw, &tqual, &wqual); - a[i].type |= (tqual<<2); a[i].type |= (wqual<<(sc_bn+2)); - // assert(hh_bq(a[i]) == tqual); assert(hh_wq(a[i]) == wqual); - // fprintf(stderr, "[M::%s] site::%u, type::%u, occ0::%lu, occ2::%lu, tqual::%lu, wqual::%lu\n", __func__, a[i].site, hh_tp(a[i]), occ_0, occ_2, tqual, wqual); - u_a[m++] = a[i]; - } - } - - - return m; -} - - -void partition_overlaps_advance(overlap_region_alloc* overlap_list, All_reads* R_INF, - UC_Read* g_read, UC_Read* overlap_read, Correct_dumy* dumy, - haplotype_evdience_alloc* hap, int force_repeat) -{ - ResizeInitHaplotypeEvdience(hap); - - uint64_t k, l, m; - long long window_start, window_end; - long long num_availiable_win = 0; - - Window_Pool w_inf; - init_Window_Pool(&w_inf, g_read->length, WINDOW, (int)(1.0/asm_opt.max_ov_diff_ec)); - - int flag = 0; - while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) - { - dumy->length = 0; - dumy->lengthNT = 0; - ///return overlaps that is overlaped with [window_start, window_end] - flag = get_available_interval(window_start, window_end, overlap_list, dumy); - switch (flag) - { - case 1: ///found matched overlaps - break; - case 0: ///do not find any matched overlaps - break; - case -2: ///do not find any matched overlaps, and the next window also cannot match - break; - } - - num_availiable_win = num_availiable_win + dumy->length; - - ///need to deal with - cluster_advance(g_read->seq, window_start, window_end, overlap_list, dumy, R_INF, hap, overlap_read, 1); - } - - ///very time-consuming - ///Fix-attention ---> able to be sorted locally - // qsort(hap->list, hap->length, sizeof(haplotype_evdience), cmp_haplotype_evdience); - SetSnpMatrix(hap, &(hap->nn_snp), &(overlap_list->length), 0, NULL); - for (k = 1, l = m = 0; k <= hap->length; ++k) { - if (k == hap->length || hap->list[k].site != hap->list[l].site) { - m += insert_snp_ee(hap, hap->list+l, k-l, hap->list+m, g_read, NULL); - l = k; - } - } - hap->length = m; - - // generate_haplotypes_naive_advance(hap, overlap_list, NULL); - generate_haplotypes_naive_HiFi(hap, overlap_list, 0.04, g_read, 1, 0, ((uint64_t)-1)); - // generate_haplotypes_DP(hap, overlap_list, R_INF, g_read->length, force_repeat); - // generate_haplotypes_naive(hap, overlap_list, R_INF, g_read->length, force_repeat); - - lable_large_indels(overlap_list, g_read->length, dumy, asm_opt.max_ov_diff_ec); -} - - -void debug_phasing_snp_site_status(haplotype_evdience_alloc* h, haplotype_evdience* a, uint64_t a_n, overlap_region_alloc* olist) -{ - uint64_t i; - for (i = 0; i < a_n; i++) { - if(a[i].site == 76046) { - fprintf(stderr, "[M::utg%.6dl::]x_site->%u, y_site->%u, type->%u, cov->%u, misBase->%c\n", - (int)olist->list[a[i].overlapID].y_id+1, a[i].site, - a[i].overlapSite, a[i].type, a[i].cov, a[i].misBase); - } - } -} - - -void partition_ul_overlaps_advance(overlap_region_alloc* overlap_list, const ul_idx_t *uref, - UC_Read* g_read, UC_Read* overlap_read, Correct_dumy* dumy, haplotype_evdience_alloc* hap, - int force_repeat, double max_ov_diff_ec, long long blockLen, void *km) -{ - ResizeInitHaplotypeEvdience(hap); - - uint64_t k, l, m; - long long window_start, window_end; - long long num_availiable_win = 0; - - Window_Pool w_inf; - init_Window_Pool(&w_inf, g_read->length, blockLen, (int)(1.0/max_ov_diff_ec)); - - int flag = 0; - while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) - { - dumy->length = 0; - dumy->lengthNT = 0; - ///return overlaps that is overlaped with [window_start, window_end] - flag = get_available_interval(window_start, window_end, overlap_list, dumy); - switch (flag) - { - case 1: ///found matched overlaps - break; - case 0: ///do not find any matched overlaps - break; - case -2: ///do not find any matched overlaps, and the next window also cannot match - break; - } - - num_availiable_win = num_availiable_win + dumy->length; - - ///need to deal with - cluster_ul_advance(g_read->seq, window_start, window_end, overlap_list, dumy, uref, hap, overlap_read, 1, w_inf.window_length, km); - } - - - - ///very time-consuming - ///Fix-attention ---> able to be sorted locally - // qsort(hap->list, hap->length, sizeof(haplotype_evdience), cmp_haplotype_evdience); - SetSnpMatrix(hap, &(hap->nn_snp), &(overlap_list->length), 0, km); - for (k = 1, l = m = 0; k <= hap->length; ++k) { - if (k == hap->length || hap->list[k].site != hap->list[l].site) { - // debug_phasing_snp_site_status(hap, hap->list+l, k-l, overlap_list); - m += insert_snp_ee(hap, hap->list+l, k-l, hap->list+m, g_read, km); - l = k; - } - } - hap->length = m; - - generate_haplotypes_naive_advance(hap, overlap_list, km); - - // generate_haplotypes_DP(hap, overlap_list, R_INF, g_read->length, force_repeat); - // generate_haplotypes_naive(hap, overlap_list, R_INF, g_read->length, force_repeat); - - lable_large_indels(overlap_list, g_read->length, dumy, max_ov_diff_ec); -} - - -void collect_no_cov_regions(overlap_region_alloc* overlap_list, All_reads* R_INF, -kvec_t_u32_warp* b, kvec_t_u64_warp* r, int min_dp, int min_len) -{ - b->a.n = r->a.n = 0; - ///if(overlap_list->length == 0) return; - long long i = 0, xLen = Get_READ_LENGTH((*R_INF), overlap_list->list[0].x_id); - uint32_t qs, qe; - uint64_t tmp; - int dp, old_dp, s_start = 0, s_end = 0; - ///at least 1 - if(min_len < 1) min_len = 1; - - - for (i = 0; i < (long long)overlap_list->length; i++) - { - if (overlap_list->list[i].is_match != 1 && overlap_list->list[i].is_match != 2) continue; - - qs = overlap_list->list[i].x_pos_s; - qe = overlap_list->list[i].x_pos_e + 1; - kv_push(uint32_t, b->a, qs<<1); - kv_push(uint32_t, b->a, qe<<1|1); - } - - - ///we can identify the qs and qe by the 0-th bit - radix_sort_b32(b->a.a, b->a.a + b->a.n); - - for (i = 0, dp = 0; i < (long long)b->a.n; ++i) - { - old_dp = dp; - //if a[j] is qe - if (b->a.a[i]&1) --dp; - else ++dp; - /** - min_dp is the coverage drop threshold - there are two cases: - 1. old_dp = dp + 1 (b.a[j] is qe); 2. old_dp = dp - 1 (b.a[j] is qs); - **/ - if (old_dp < min_dp && dp >= min_dp) ///old_dp < dp, b.a[j] is qs - { - ///case 2, a[j] is qs - s_end = b->a.a[i]>>1; - ///at least 1 - if(s_end-s_start >= min_len) - { - tmp = s_start; tmp = tmp << 32; tmp = tmp | (uint64_t)(s_end-1); - kv_push(uint64_t, r->a, tmp); - } - } - else if (old_dp >= min_dp && dp < min_dp) ///old_dp > min_dp, b.a[j] is qe - { - s_start = b->a.a[i]>>1; - } - } - - - if(s_start < xLen && xLen-s_start >= min_len) - { - s_end = xLen; - tmp = s_start; tmp = tmp << 32; tmp = tmp | (uint64_t)(s_end-1); - kv_push(uint64_t, r->a, tmp); - } -} - -int collect_hp_regions_back(overlap_region_alloc* olist, All_reads* R_INF, kvec_t_u32_warp* b, kvec_t_u64_warp* r, kvec_t_u8_warp* k_flag, float hp_rate, FILE* fp) -{ - int i, k, qs, qe, ava_k_mer = 0, hp_k_mer = 0, min_dp; - // min_dp = RESEED_DP; - // if(asm_opt.hom_cov > 0) min_dp = asm_opt.hom_cov * RESEED_PEAK_RATE; - // if(min_dp > RESEED_DP) min_dp = RESEED_DP; - min_dp = RESEED_DP; - if(asm_opt.hom_cov > 0) min_dp = asm_opt.hom_cov * RESEED_PEAK_RATE; - if(asm_opt.het_cov > 0) min_dp = asm_opt.het_cov * RESEED_PEAK_RATE; - collect_no_cov_regions(olist, R_INF, b, r, min_dp, RESEED_LEN); - - for (i = 0; i < (int)r->a.n; i++) - { - ///[qs, qe] - qs = r->a.a[i]>>32; - qe = (r->a.a[i]<<32)>>32; - - for (k = qs; k <= qe; k++) - { - if(k_flag->a.a[k] > 1) ava_k_mer++; - if(k_flag->a.a[k] > 2) hp_k_mer++; - } - - if(fp) fprintf(fp, "qs: %d, qe: %d, ava_k_mer: %d, hp_k_mer: %d\n", qs, qe, ava_k_mer, hp_k_mer); - } - - if(fp) fprintf(fp, "ava_k_mer: %d, hp_k_mer: %d, hp_rate: %f, min_dp: %d, a.n: %d\n", ava_k_mer, hp_k_mer, hp_rate, min_dp, (int)r->a.n); - - // if(fp) - // { - // for (k = 0; k < (int)k_flag->a.n; k++) - // { - // if(k_flag->a.a[k] > 0) fprintf(fp, "(%d) %u\n", k, k_flag->a.a[k]); - // } - // } - - if(hp_k_mer > ava_k_mer*hp_rate) return 1; ///must use '>' instead of '>=' - r->a.n = 0; - return 0; -} - - -int collect_hp_regions(overlap_region_alloc* olist, All_reads* R_INF, kvec_t_u8_warp* k_flag, -float hp_rate, int rlen, FILE* fp) -{ - int i, ava_k_mer = 0, hp_k_mer = 0, vLen, min_dp; - int32_t w, n[4]; - n[0] = n[1] = n[2] = n[3] = 0; - min_dp = RESEED_DP; - if(asm_opt.hom_cov > 0) min_dp = asm_opt.hom_cov * RESEED_PEAK_RATE; - if(min_dp > RESEED_DP) min_dp = RESEED_DP; - overlap_region* ov = NULL; - - for (i = 0; i < (long long)olist->length; i++) - { - ov = &(olist->list[i]); - if (ov->is_match != 1 && ov->is_match != 2) continue; - - w = ha_ov_type(ov, rlen); - ++n[w]; - } - - if(fp) fprintf(fp, "n[0]: %d, n[1]: %d, n[2]: %d, n[3]: %d\n", n[0], n[1], n[2], n[3]); - - // n[0] += n[2]; - // n[1] += n[2]; - - if(n[0] < min_dp) - { - ava_k_mer = hp_k_mer = 0; - vLen = MIN(k_flag->a.n, RESEED_LEN); - for (i = 0; i < vLen; i++) - { - if(k_flag->a.a[i] > 1) ava_k_mer++; - if(k_flag->a.a[i] > 2) hp_k_mer++; - } - if(hp_k_mer > ava_k_mer*hp_rate) return 1; - } - - - if(n[1] < min_dp) - { - ava_k_mer = hp_k_mer = 0; - vLen = MIN(k_flag->a.n, RESEED_LEN); - for (i = k_flag->a.n - vLen; i < (int)k_flag->a.n; i++) - { - if(k_flag->a.a[i] > 1) ava_k_mer++; - if(k_flag->a.a[i] > 2) hp_k_mer++; - } - if(hp_k_mer > ava_k_mer*hp_rate) return 1; - } - - - if(fp) fprintf(fp, "ava_k_mer: %d, hp_k_mer: %d, hp_rate: %f, min_dp: %d\n", ava_k_mer, hp_k_mer, hp_rate, min_dp); - - // if(fp) - // { - // for (k = 0; k < (int)k_flag->a.n; k++) - // { - // if(k_flag->a.a[k] > 0) fprintf(fp, "(%d) %u\n", k, k_flag->a.a[k]); - // } - // } - - return 0; -} - -uint64_t ovlp_occ(overlap_region_alloc* overlap_list, uint8_t is_match) -{ - uint64_t occ = 0, k; - for (k = 0; k < overlap_list->length; k++) { - if(overlap_list->list[k].is_match == is_match) occ++; - } - return occ; -} - -void correct_overlap(overlap_region_alloc* overlap_list, All_reads* R_INF, - UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, - Graph* g, Graph* DAGCon, Cigar_record* current_cigar, - haplotype_evdience_alloc* hap, Round2_alignment* second_round, - kvec_t_u64_warp* v_idx, window_list_alloc* win_ciagr_buf, int force_repeat, int is_consensus, int* fully_cov, int* abnormal) -{ - clear_Correct_dumy(dumy, overlap_list, NULL); - - long long window_start, window_end; - - Window_Pool w_inf; - - init_Window_Pool(&w_inf, g_read->length, WINDOW, (int)(1.0/asm_opt.max_ov_diff_ec)); - - int flag = 0; - - while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) - { - dumy->length = 0; - dumy->lengthNT = 0; - flag = get_interval(window_start, window_end, overlap_list, dumy, w_inf.window_length); - - switch (flag) - { - case 1: ///no match here - break; - case 0: ///no match here - break; - case -2: ///if flag == -2, loop would be terminated - break; - } - - ///dumy->lengthNT represent how many overlaps that the length of them is not equal to WINDOW; may larger or less than WINDOW - ///dumy->length represent how many overlaps that the length of them is WINDOW - /****************************may improve**************************/ - ///now the windows which are larger than WINDOW are verified one-by-one, to improve it, we can do it group-bygroup - verify_window(window_start, window_end, overlap_list, dumy, R_INF, g_read->seq); - } - // fprintf(stderr, "###dumy->start_i:%lu, overlap_list->length:%lu\n\n", dumy->start_i, overlap_list->length); - - // recalcate_window(overlap_list, R_INF, g_read, dumy, overlap_read); - // partition_overlaps(overlap_list, R_INF, g_read, dumy, hap, force_repeat); - recalcate_window_advance(overlap_list, R_INF, NULL, g_read, dumy, overlap_read, v_idx, w_inf.window_length, asm_opt.max_ov_diff_ec, asm_opt.max_ov_diff_final); - // fprintf(stderr, "[M::%s-beg] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, - // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); - partition_overlaps_advance(overlap_list, R_INF, g_read, overlap_read, dumy, hap, force_repeat); - // fprintf(stderr, "[M::%s-after] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, - // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); - if(is_consensus) - { - generate_consensus(overlap_list, R_INF, g_read, dumy, g, DAGCon, current_cigar, second_round, win_ciagr_buf); - } - - (*fully_cov) = check_if_fully_covered(overlap_list, R_INF, g_read, dumy, g, abnormal); -} - -/** -void debug_phasing_status(overlap_region_alloc *olist, ma_ug_t *ug, uint64_t print_w_list, -haplotype_evdience_alloc* hap, UC_Read* g_read, int64_t flanking, uint64_t yid) -{ - uint64_t i, k, l, ii; - int64_t t; - SnpStats *s = NULL; - - for (i = 0; i < olist->length; i++) { - if(olist->list[i].y_id != yid) continue; - fprintf(stderr, "\n[M::utg%.6d%c::is_match->%u] rev->%u, x->[%u, %u), y->[%u, %u)\n", - (int)olist->list[i].y_id+1, "lc"[ug->u.a[olist->list[i].y_id].circ], olist->list[i].is_match, - olist->list[i].y_pos_strand, olist->list[i].x_pos_s, olist->list[i].x_pos_e+1, olist->list[i].y_pos_s, olist->list[i].y_pos_e+1); - if(print_w_list) { - for (k = 0; k < olist->list[i].w_list.n; k++) { - if(olist->list[i].w_list.a[k].y_end != -1) { - fprintf(stderr, "x->[%lu, %lu), y->[%d, %d), e->%d\n", - olist->list[i].w_list.a[k].x_start, olist->list[i].w_list.a[k].x_end+1, - olist->list[i].w_list.a[k].y_start, olist->list[i].w_list.a[k].y_end+1, - olist->list[i].w_list.a[k].error); - } else { - fprintf(stderr, "x->[-1, -1), y->[-1, -1), e->-1\n"); - } - } - } - } - - - for (k = 1, l = 0; k <= hap->length; ++k) { - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - ii = hap->list[l].overlapID; - if(olist->list[ii].y_id != yid) { - l = k; - continue; - } - for (i = l; i < k; i++) { - if(hap->list[i].type!=1) continue; - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->score == 1 && (!(s->occ_0 < 2 || s->occ_1 < 2))) { - fprintf(stderr, "s->site:%u, s->occ_0:%u, s->occ_1:%u, s->occ_2:%u\n", s->site, s->occ_0, s->occ_1, s->occ_2); - for (t = s->site>=flanking?s->site-flanking:0; tlength && t<=s->site+flanking; t++){ - if(t == s->site) fprintf(stderr,"["); - fprintf(stderr,"%c", g_read->seq[t]); - if(t == s->site) fprintf(stderr,"]"); - } - fprintf(stderr,"\n"); - } - } - l = k; - } - } -} -**/ - -void print_ovlp_occ_stat(overlap_region_alloc* overlap_list, uint32_t xlen, uint8_t is_match) -{ - uint64_t k; - for (k = 0; k < overlap_list->length; k++) { - if(overlap_list->list[k].is_match != is_match) continue; - fprintf(stderr, "[M::%s::xlen::%u] utg%.6dl(%c), is_match::%u, x::[%u, %u)\n", __func__, xlen, - (int32_t)overlap_list->list[k].y_id + 1, - "+-"[overlap_list->list[k].y_pos_strand], overlap_list->list[k].is_match, - overlap_list->list[k].x_pos_s, overlap_list->list[k].x_pos_e+1); - } -} -void align_ul_ed(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, char* qstr, char *tstr, double e_rate, int64_t w_l, void *km); -void correct_ul_overlap(overlap_region_alloc* overlap_list, const ul_idx_t *uref, - UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, - Graph* g, Graph* DAGCon, Cigar_record* current_cigar, - haplotype_evdience_alloc* hap, Round2_alignment* second_round, - kvec_t_u64_warp* v_idx, window_list_alloc* win_ciagr_buf, - int force_repeat, int is_consensus, int* fully_cov, int* abnormal, - double max_ov_diff_ec, long long winLen, void *km) -{ - - clear_Correct_dumy(dumy, overlap_list, km); - - Window_Pool w_inf; - init_Window_Pool(&w_inf, g_read->length, winLen, (int)(1.0/max_ov_diff_ec)); - /** - uint64_t i; - for (i = 0; i < overlap_list->length; i++) { - verify_ul_window_s(&(overlap_list->list[i]), uref, g_read->seq, dumy->overlap_region, max_ov_diff_ec, w_inf.window_length, THRESHOLD_MAX_SIZE, km); - // align_ul_ed(&(overlap_list->list[i]), uref, NULL, g_read->seq, dumy->overlap_region, max_ov_diff_ec, w_inf.window_length, km); - } - **/ - - - // recalcate_window(overlap_list, R_INF, g_read, dumy, overlap_read); - // partition_overlaps(overlap_list, R_INF, g_read, dumy, hap, force_repeat); - // recalcate_window_ul_advance(overlap_list, uref, g_read, dumy, overlap_read, max_ov_diff_ec, w_inf.window_length, km); - // recalcate_window_advance(overlap_list, NULL, uref, g_read, dumy, overlap_read, v_idx, w_inf.window_length, max_ov_diff_ec, max_ov_diff_ec); - /** - refine_ed_aln(overlap_list, NULL, uref, g_read, dumy, overlap_read, v_idx, w_inf.window_length, max_ov_diff_ec, max_ov_diff_ec); - **/ - refine_ed_aln_test(overlap_list, NULL, uref, g_read, dumy, overlap_read, v_idx, w_inf.window_length, max_ov_diff_ec, max_ov_diff_ec); - // fprintf(stderr, "[M::%s-beg] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, - // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); - ///after this function, overlap_list is sorted by x_pos_e; used for g_chain - partition_ul_overlaps_advance(overlap_list, uref, g_read, overlap_read, dumy, hap, force_repeat, max_ov_diff_ec, w_inf.window_length, km); - // print_ovlp_occ_stat(overlap_list, g_read->length, 1); - // print_ovlp_occ_stat(overlap_list, g_read->length, 2); - // fprintf(stderr, "[M::%s-end] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, - // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); - // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1176); - // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1167); - // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1170); - /** - - - if(is_consensus) - { - generate_consensus(overlap_list, R_INF, g_read, dumy, g, DAGCon, current_cigar, second_round); - } - - - (*fully_cov) = check_if_fully_covered(overlap_list, R_INF, g_read, dumy, g, abnormal); - **/ -} - - - - -void lchain_align(overlap_region_alloc* overlap_list, const ul_idx_t *uref, - UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, - Graph* g, Graph* DAGCon, Cigar_record* current_cigar, - haplotype_evdience_alloc* hap, Round2_alignment* second_round, - kvec_t_u64_warp* v_idx, window_list_alloc* win_ciagr_buf, - int force_repeat, int is_consensus, int* fully_cov, int* abnormal, - double max_ov_diff_ec, long long winLen, void *km) -{ - - clear_Correct_dumy(dumy, overlap_list, km); - - long long window_start, window_end; - - Window_Pool w_inf; - - init_Window_Pool(&w_inf, g_read->length, winLen, (int)(1.0/max_ov_diff_ec)); - int flag = 0; - - while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) { - dumy->length = 0; dumy->lengthNT = 0; - flag = get_interval(window_start, window_end, overlap_list, dumy, w_inf.window_length); - - switch (flag) { - case 1: ///no match here - break; - case 0: ///no match here - break; - case -2: ///if flag == -2, loop would be terminated - break; - } - - ///dumy->lengthNT represent how many overlaps that the length of them is not equal to WINDOW; may larger or less than WINDOW - ///dumy->length represent how many overlaps that the length of them is WINDOW - ///now the windows which are larger than WINDOW are verified one-by-one, to improve it, we can do it group-bygroup - verify_ul_window(window_start, window_end, overlap_list, dumy, uref, g_read->seq, max_ov_diff_ec, w_inf.window_length, /**THRESHOLD**/THRESHOLD_MAX_SIZE, km); - } - - // recalcate_window(overlap_list, R_INF, g_read, dumy, overlap_read); - // partition_overlaps(overlap_list, R_INF, g_read, dumy, hap, force_repeat); - // recalcate_window_ul_advance(overlap_list, uref, g_read, dumy, overlap_read, max_ov_diff_ec, w_inf.window_length, km); - refine_ed_aln(overlap_list, NULL, uref, g_read, dumy, overlap_read, v_idx, w_inf.window_length, max_ov_diff_ec, max_ov_diff_ec); - // fprintf(stderr, "[M::%s-beg] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, - // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); - ///after this function, overlap_list is sorted by x_pos_e; used for g_chain - partition_ul_overlaps_advance(overlap_list, uref, g_read, overlap_read, dumy, hap, force_repeat, max_ov_diff_ec, w_inf.window_length, km); - // print_ovlp_occ_stat(overlap_list, g_read->length, 1); - // print_ovlp_occ_stat(overlap_list, g_read->length, 2); - // fprintf(stderr, "[M::%s-end] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, - // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); - // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1176); - // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1167); - // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1170); - /** - - - if(is_consensus) - { - generate_consensus(overlap_list, R_INF, g_read, dumy, g, DAGCon, current_cigar, second_round); - } - - - (*fully_cov) = check_if_fully_covered(overlap_list, R_INF, g_read, dumy, g, abnormal); - **/ -} - -void init_Cigar_record(Cigar_record* dummy) -{ - dummy->length = 0; - dummy->size = 100; - dummy->record = (uint32_t*)malloc(sizeof(uint32_t)*dummy->size); - - - dummy->lost_base_length = 0; - dummy->lost_base_size = 100; - dummy->lost_base = (char*)malloc(sizeof(char)*dummy->lost_base_size); - - - - dummy->current_operation_length = 0; - dummy->current_operation = 127; -} - -void init_Cigar_record_buf(Cigar_record* dummy, void *km) -{ - memset(dummy, 0, sizeof(*dummy)); - dummy->current_operation = 127; -} - - -void destory_Cigar_record(Cigar_record* dummy) -{ - free(dummy->record); - free(dummy->lost_base); -} - -void clear_Cigar_record(Cigar_record* dummy) -{ - dummy->new_read_length = 0; - dummy->length = 0; - dummy->lost_base_length = 0; - - dummy->current_operation_length = 0; - dummy->current_operation = 127; -} - - -void init_Correct_dumy_buf(Correct_dumy* list, void *km) -{ - memset(list, 0, sizeof(Correct_dumy)); - int i; - for (i = 0; i < 256; i++){ - list->Peq_SSE[i] = _mm_setzero_si128(); - } -} - - -void init_Correct_dumy(Correct_dumy* list) -{ - list->size = 0; - list->length = 0; - list->lengthNT = 0; - list->start_i = 0; - list->overlapID = NULL; - int i; - for (i = 0; i < 256; i++) - { - list->Peq_SSE[i] = _mm_setzero_si128(); - } - - - list->corrected_read_size = 1000; - list->corrected_read_length = 0; - list->corrected_read = (char*)malloc(sizeof(char)*list->corrected_read_size); - list->corrected_base = 0; - -} - -void destory_Correct_dumy(Correct_dumy* list) -{ - free(list->overlapID); - free(list->corrected_read); -} - - -void clear_Correct_dumy(Correct_dumy* list, overlap_region_alloc* overlap_list, void *km) -{ - list->length = 0; - list->lengthNT = 0; - list->start_i = 0; - - if (list->size < overlap_list->length){ - list->size = overlap_list->length; - if(!km) REALLOC(list->overlapID, list->size); - else KREALLOC(km, list->overlapID, list->size); - } - - list->last_boundary_length = 0; - list->corrected_read_length = 0; - list->corrected_base = 0; - -} - -void clear_Correct_dumy_pure(Correct_dumy* list) -{ - list->length = 0; - list->lengthNT = 0; - list->start_i = 0; - list->last_boundary_length = 0; - list->corrected_read_length = 0; - list->corrected_base = 0; -} - - -void init_Cigar_record_alloc(Cigar_record_alloc* x) -{ - x->length = 0; - x->size = 0; - x->buffer = NULL; -} - -void resize_Cigar_record_alloc(Cigar_record_alloc* x, long long new_size) -{ - long long i; - if(new_size > x->size) - { - x->buffer = (Cigar_record*)realloc(x->buffer, new_size*sizeof(Cigar_record)); - for (i = 0; i < x->size; i++) - { - clear_Cigar_record(&(x->buffer[i])); - } - for (; i < new_size; i++) - { - init_Cigar_record(&(x->buffer[i])); - clear_Cigar_record(&(x->buffer[i])); - } - - x->size = new_size; - } - else - { - for (i = 0; i < new_size; i++) - { - clear_Cigar_record(&(x->buffer[i])); - } - } - - x->length = 0; -} -void destory_Cigar_record_alloc(Cigar_record_alloc* x) -{ - long long i; - for (i = 0; i < x->size; i++) - { - destory_Cigar_record(&(x->buffer[i])); - } - free(x->buffer); -} - - -void add_new_cell_to_cigar_record(Cigar_record* dummy, uint32_t len, uint32_t type) -{ - uint32_t tmp; - tmp = len; - tmp = tmp << 2; - tmp = tmp | type; - - dummy->length++; - - - if(dummy->length > dummy->size) - { - dummy->size = dummy->size * 2; - dummy->record = (uint32_t*)realloc(dummy->record, dummy->size*sizeof(uint32_t)); - } - - dummy->record[dummy->length - 1] = tmp; -} - -void add_existing_cell_to_cigar_record(Cigar_record* dummy, uint32_t len, uint32_t type) -{ - uint32_t tmp; - - tmp = dummy->record[dummy->length - 1] >> 2; - tmp = tmp + len; - tmp = tmp << 2; - tmp = tmp | type; - dummy->record[dummy->length - 1] = tmp; -} - - -void add_new_cell_to_cigar_record_with_different_base(Cigar_record* dummy, uint32_t len, uint32_t type, char* seq) -{ - uint32_t tmp; - tmp = len; - tmp = tmp << 2; - tmp = tmp | type; - - - dummy->length++; - - if(dummy->length > dummy->size) - { - dummy->size = dummy->size * 2; - dummy->record = (uint32_t*)realloc(dummy->record, dummy->size*sizeof(uint32_t)); - } - - dummy->record[dummy->length - 1] = tmp; - - - - if (dummy->lost_base_length + len> dummy->lost_base_size) - { - dummy->lost_base_size = (dummy->lost_base_length + len) * 2; - dummy->lost_base = (char*)realloc(dummy->lost_base, dummy->lost_base_size*sizeof(char)); - } - - uint32_t i = 0; - for (i = 0; i < len; i++, dummy->lost_base_length++) - { - dummy->lost_base[dummy->lost_base_length] = seq[i]; - } -} - -void add_existing_cell_to_cigar_record_with_different_base(Cigar_record* dummy, uint32_t len, uint32_t type, char* seq) -{ - uint32_t tmp; - - tmp = dummy->record[dummy->length - 1] >> 2; - tmp = tmp + len; - tmp = tmp << 2; - tmp = tmp | type; - dummy->record[dummy->length - 1] = tmp; - - if (dummy->lost_base_length + len> dummy->lost_base_size) - { - dummy->lost_base_size = (dummy->lost_base_length + len) * 2; - dummy->lost_base = (char*)realloc(dummy->lost_base, dummy->lost_base_size*sizeof(char)); - } - - uint32_t i = 0; - for (i = 0; i < len; i++, dummy->lost_base_length++) - { - dummy->lost_base[dummy->lost_base_length] = seq[i]; - } -} - -void afine_gap_alignment(const char *qseq, uint8_t* qnum, const int ql, -const char *tseq, uint8_t* tnum, const int tl, const uint8_t *c2n, const int strand, -int sc_mch, int sc_mis, int gapo, int gape, int bandLen, int zdrop, int end_bonus, -long long* max_q_pos, long long* max_t_pos, long long* global_score, -long long* extention_score, long long* q_boundary_score, long long* q_boundary_t_coordinate, -long long* t_boundary_score, long long* t_boundary_q_coordinate, -long long* droped, int mode) -{ - /** - // for ksw2 - (*max_t_pos) = (*max_q_pos) = -1; - int i, a = sc_mch, b = sc_mis < 0? sc_mis : -sc_mis; // a>0 and b<0 - - int8_t mat[25] = {(int8_t)a,(int8_t)b,(int8_t)b,(int8_t)b,0, - (int8_t)b,(int8_t)a,(int8_t)b,(int8_t)b,0, (int8_t)b,(int8_t)b,(int8_t)a,(int8_t)b,0, - (int8_t)b,(int8_t)b,(int8_t)b,(int8_t)a,0, 0,0,0,0,0}; - ksw_extz_t ez; - memset(&ez, 0, sizeof(ksw_extz_t)); - - if(strand == FORWARD_KSW) - { - for (i = 0; i < tl; ++i) tnum[i] = c2n[(uint8_t)tseq[i]]; // encode to 0/1/2/3 - for (i = 0; i < ql; ++i) qnum[i] = c2n[(uint8_t)qseq[i]]; - } - else if(strand == BACKWARD_KSW) - { - for (i = 0; i < tl; ++i) tnum[i] = c2n[(uint8_t)tseq[tl - i - 1]]; // encode to 0/1/2/3 - for (i = 0; i < ql; ++i) qnum[i] = c2n[(uint8_t)qseq[ql - i - 1]]; - } - ksw_extz2_sse(0, ql, qnum, tl, tnum, 5, mat, gapo, gape, bandLen, zdrop, end_bonus, - mode, &ez); - (*global_score) = ez.score; - (*extention_score) = ez.max; - (*q_boundary_score) = ez.mqe; - (*q_boundary_t_coordinate) = ez.mqe_t; - (*t_boundary_score) = ez.mte; - (*t_boundary_q_coordinate) = ez.mte_q; - (*max_t_pos) = ez.max_t; - (*max_q_pos) = ez.max_q; - (*droped) = ez.zdropped; - free(ez.cigar); - - - // for (i = 0; i < ez.n_cigar; ++i) // print CIGAR - // printf("%d%c", ez.cigar[i]>>4, "MID"[ez.cigar[i]&0xf]); - // putchar('\n'); - - // for ksw2 - **/ -} - -int fill_chain_by_affine_gap_debug(Fake_Cigar* chain, char* x_string, char* y_string, overlap_region* ovc, -long long x_readLen, long long y_readLen, Cigar_record* cigar, uint8_t* c2n, uint8_t* x_num, uint8_t* y_num, -long long* minus_score_thres, long long* final_scores) -{ - /** - long long i, xOffset, yOffset, xRegionLen, yRegionLen, maxXpos, maxYpos, zdroped; - long long mapGlobalScore, mapExtentScore; - long long xBuoundaryScore, xBuoundaryYcoordinate, yBuoundaryScore, yBuoundaryXcoordinate; - ///float band_rate = 0.08; - int endbouns, mode; - long long xBeg, yBeg; - xBeg = ovc->x_pos_s; - yBeg = ovc->y_pos_s; - if(chain->length <= 0) return 0; - // long long minus_score_thres = (EstimateOlen*HIGH_HET_ERROR_RATE*(MATCH_SCORE_KSW+(MAX(MISMATCH_SCORE_KSW,GAP_EXT_KSW)))); - // long long total_score_thres = EstimateOlen*MATCH_SCORE_KSW - minus_score_thres; - long long sum_score = 0, current_ovlp = 0, zdrop_occ = 0; - long long new_xBeg, new_yBeg, new_xEnd, new_yEnd; - new_xBeg = ovc->x_pos_s; - new_yBeg = ovc->y_pos_s; - new_xEnd = ovc->x_pos_e; - new_yEnd = ovc->y_pos_e; - ///long long sub_score_sum; - ///deal with region 0 backward - i = 0; - endbouns = 0; - - xOffset = get_fake_gap_pos(chain, 0); - xOffset = xOffset - 1; - yOffset = (xOffset - xBeg) + yBeg + get_fake_gap_shift(chain, 0); - if(xOffset >= 0 && yOffset >= 0) - { - xRegionLen = xOffset + 1; - yRegionLen = yOffset + 1; - //note here cannot use DIFF(xRegionLen, yRegionLen) - // bandLen = (MIN(xRegionLen, yRegionLen))*band_rate; - // if(bandLen == 0) bandLen = MIN(xRegionLen, yRegionLen); - - - ///do alignment backward - ///for beginning part and end part, must use exact mode - mode = KSW_EZ_SCORE_ONLY; - afine_gap_alignment(x_string, x_num, xRegionLen, y_string, y_num, yRegionLen, - c2n, BACKWARD_KSW, MATCH_SCORE_KSW, MISMATCH_SCORE_KSW, GAP_OPEN_KSW, GAP_EXT_KSW, - BAND_KSW, Z_DROP_KSW, endbouns, &maxXpos, &maxYpos, &mapGlobalScore, - &mapExtentScore, &xBuoundaryScore, &xBuoundaryYcoordinate, - &yBuoundaryScore, &yBuoundaryXcoordinate, &zdroped, mode); - - - - - if(!zdroped) - { - if(xRegionLen <= yRegionLen) - { - sum_score += xBuoundaryScore; - new_yBeg = yRegionLen - xBuoundaryYcoordinate - 1; - } - else - { - sum_score += yBuoundaryScore; - new_xBeg = xRegionLen - yBuoundaryXcoordinate - 1; - } - } - else - { ///return 0; - sum_score += mapExtentScore; - if(xRegionLen <= yRegionLen) - { - - sum_score -= (GAP_OPEN_KSW + (xRegionLen - maxXpos)*GAP_EXT_KSW); - } - else - { - sum_score -= (GAP_OPEN_KSW + (yRegionLen - maxYpos)*GAP_EXT_KSW); - } - } - } - - ///align forward - for (i = 0; i < (long long)chain->length; i++) - { - // xOffset = get_fake_gap_pos(chain, i); - // yOffset = xOffset + get_fake_gap_shift(chain, i); - xOffset = get_fake_gap_pos(chain, i); - yOffset = (xOffset - xBeg) + yBeg + get_fake_gap_shift(chain, i); - ///last region - if(i == (long long)(chain->length - 1)) - { - endbouns = 0; - xRegionLen = x_readLen - xOffset; - yRegionLen = y_readLen - yOffset; - ///for beginning part and end part, must use exact mode - mode = KSW_EZ_SCORE_ONLY; - //note here cannot use DIFF(xRegionLen, yRegionLen) - // bandLen = (MIN(xRegionLen, yRegionLen))*band_rate; - // if(bandLen == 0) bandLen = MIN(xRegionLen, yRegionLen); - } - else - { - ///higher endbouns for middle regions - endbouns = MATCH_SCORE_KSW; - xRegionLen = get_fake_gap_pos(chain, i+1) - xOffset; - yRegionLen = (get_fake_gap_pos(chain, i+1) + get_fake_gap_shift(chain, i+1)) - - (get_fake_gap_pos(chain, i) + get_fake_gap_shift(chain, i)); - mode = KSW_EZ_SCORE_ONLY | KSW_EZ_APPROX_MAX | KSW_EZ_APPROX_DROP; - // bandLen = MAX((MIN(xRegionLen, yRegionLen))*band_rate, DIFF(xRegionLen, yRegionLen)); - // if(bandLen == 0) bandLen = MIN(xRegionLen, yRegionLen); - } - - - if(minus_score_thres) - { - current_ovlp = MIN((xOffset + 1 - xBeg), (yOffset + 1 - yBeg)); - current_ovlp = current_ovlp*MATCH_SCORE_KSW; - if(current_ovlp - sum_score > (*minus_score_thres)) - { - return 0; - } - } - - if(xOffset < 0) xOffset = 0; - if(yOffset < 0) yOffset = 0; - if(xRegionLen < 0) xRegionLen = 0; - if(yRegionLen < 0) yRegionLen = 0; - - ///do alignment forward - ///text is x, query is y - afine_gap_alignment(x_string+xOffset, x_num, xRegionLen, y_string+yOffset, y_num, yRegionLen, - c2n, FORWARD_KSW, MATCH_SCORE_KSW, MISMATCH_SCORE_KSW, GAP_OPEN_KSW, GAP_EXT_KSW, - BAND_KSW, Z_DROP_KSW, endbouns, &maxXpos, &maxYpos, &mapGlobalScore, - &mapExtentScore, &xBuoundaryScore, &xBuoundaryYcoordinate, - &yBuoundaryScore, &yBuoundaryXcoordinate, &zdroped, mode); - // fprintf(stderr, "# xOffset: %lld, yOffset: %lld, xRegionLen: %lld, yRegionLen: %lld, bandLen: %lld, maxXpos: %lld, maxYpos: %lld, zdroped: %lld\n", - // xOffset, yOffset, xRegionLen, yRegionLen, BAND_KSW, maxXpos, maxYpos, zdroped); - - if(!zdroped) - { - if(i != (long long)(chain->length - 1)) - { - sum_score += mapGlobalScore; - } - else - { - if(xRegionLen <= yRegionLen) - { - sum_score += xBuoundaryScore; - new_yEnd = yOffset + xBuoundaryYcoordinate; - } - else - { - sum_score += yBuoundaryScore; - new_xEnd = xOffset + yBuoundaryXcoordinate; - // if(new_xEnd != (long long)ovc->x_pos_e) - // { - // fprintf(stderr, "\n******direction: %u, new_xBeg: %lld, new_xEnd: %lld, new_yBeg: %lld, new_yEnd: %lld, old_xBeg: %u, old_xEnd: %u, old_yBeg: %u, old_yEnd: %u\n", - // ovc->y_pos_strand, new_xBeg, new_xEnd, new_yBeg, new_yEnd, ovc->x_pos_s, ovc->x_pos_e, ovc->y_pos_s, ovc->y_pos_e); - // fprintf(stderr, "x_readLen: %lld, y_readLen: %lld\n", x_readLen, y_readLen); - // fprintf(stderr, "xID: %lld, yID: %lld\n", ovc->x_id, ovc->y_id); - // fprintf(stderr, "xRegionLen: %lld, yRegionLen: %lld\n", xRegionLen, yRegionLen); - // fprintf(stderr, "xOffset: %lld, yOffset: %lld\n", xOffset, yOffset); - // fprintf(stderr, "yBuoundaryXcoordinate: %lld\n", yBuoundaryXcoordinate); - // } - } - } - } - else - { - ///return 0; - if(i != (long long)(chain->length - 1)) zdrop_occ++; - if(zdrop_occ > 1) return 0; - sum_score += mapExtentScore; - if(xRegionLen <= yRegionLen) - { - sum_score -= (GAP_OPEN_KSW + (xRegionLen - maxXpos)*GAP_EXT_KSW); - } - else - { - sum_score -= (GAP_OPEN_KSW + (yRegionLen - maxYpos)*GAP_EXT_KSW); - } - } - } - - (*final_scores) = sum_score; - if(new_xBeg != (long long)ovc->x_pos_s || new_xEnd != (long long)ovc->x_pos_e || - new_yBeg != (long long)ovc->y_pos_s || new_yEnd != (long long)ovc->y_pos_e) - { - // fprintf(stderr, "\ntttdirection: %u, new_xBeg: %lld, new_xEnd: %lld, new_yBeg: %lld, new_yEnd: %lld, old_xBeg: %u, old_xEnd: %u, old_yBeg: %u, old_yEnd: %u\n", - // ovc->y_pos_strand, new_xBeg, new_xEnd, new_yBeg, new_yEnd, ovc->x_pos_s, ovc->x_pos_e, ovc->y_pos_s, ovc->y_pos_e); - // fprintf(stderr, "x_readLen: %lld, y_readLen: %lld\n", x_readLen, y_readLen); - // fprintf(stderr, "xID: %lld, yID: %lld\n", ovc->x_id, ovc->y_id); - // for (i = 0; i < (long long)chain->length; i++) - // { - // fprintf(stderr,"i: %lld, x_pos: %d, offset: %d\n", - // i, get_fake_gap_pos(chain, i), get_fake_gap_shift(chain, i)); - // } - } - else - { - // fprintf(stderr, "\nkkkdirection: %u, new_xBeg: %lld, new_xEnd: %lld, new_yBeg: %lld, new_yEnd: %lld, old_xBeg: %u, old_xEnd: %u, old_yBeg: %u, old_yEnd: %u\n", - // ovc->y_pos_strand, new_xBeg, new_xEnd, new_yBeg, new_yEnd, ovc->x_pos_s, ovc->x_pos_e, ovc->y_pos_s, ovc->y_pos_e); - // fprintf(stderr, "x_readLen: %lld, y_readLen: %lld\n", x_readLen, y_readLen); - // fprintf(stderr, "xID: %lld, yID: %lld\n", ovc->x_id, ovc->y_id); - // for (i = 0; i < (long long)chain->length; i++) - // { - // fprintf(stderr,"i: %lld, x_pos: %d, offset: %d\n", - // i, get_fake_gap_pos(chain, i), get_fake_gap_shift(chain, i)); - // } - } - **/ - - return 1; -} - - - -int fill_chain_by_affine_gap(Fake_Cigar* chain, char* x_string, char* y_string, overlap_region* ovc, -long long x_readLen, long long y_readLen, Cigar_record* cigar, uint8_t* c2n, uint8_t* x_num, uint8_t* y_num, -long long* minus_score_thres, long long* final_scores) -{ - /** - long long i, xOffset, yOffset, xRegionLen, yRegionLen, maxXpos, maxYpos, zdroped; - long long mapGlobalScore, mapExtentScore; - long long xBuoundaryScore, xBuoundaryYcoordinate, yBuoundaryScore, yBuoundaryXcoordinate; - ///float band_rate = 0.08; - int endbouns, mode; - long long xBeg, yBeg; - xBeg = ovc->x_pos_s; - yBeg = ovc->y_pos_s; - if(chain->length <= 0) return 0; - long long sum_score = 0, current_ovlp = 0, zdrop_occ = 0; - long long chain_num = (long long)chain->length - 1; - - ///align forward - for (i = 0; i < chain_num; i++) - { - xOffset = get_fake_gap_pos(chain, i); - yOffset = (xOffset - xBeg) + yBeg + get_fake_gap_shift(chain, i); - ///last region - - ///higher endbouns for middle regions - endbouns = MATCH_SCORE_KSW; - xRegionLen = get_fake_gap_pos(chain, i+1) - xOffset; - yRegionLen = (get_fake_gap_pos(chain, i+1) + get_fake_gap_shift(chain, i+1)) - - (get_fake_gap_pos(chain, i) + get_fake_gap_shift(chain, i)); - ///last region - if(i == chain_num - 1) - { - xRegionLen++; - yRegionLen++; - } - - mode = KSW_EZ_SCORE_ONLY | KSW_EZ_APPROX_MAX | KSW_EZ_APPROX_DROP; - - - if(minus_score_thres) - { - current_ovlp = MIN((xOffset - xBeg), (yOffset - yBeg)); - current_ovlp = current_ovlp*MATCH_SCORE_KSW; - if(current_ovlp - sum_score > (*minus_score_thres)) - { - return 0; - } - } - - if(xOffset < 0) xOffset = 0; - if(yOffset < 0) yOffset = 0; - if(xRegionLen < 0) xRegionLen = 0; - if(yRegionLen < 0) yRegionLen = 0; - - ///do alignment forward - ///text is x, query is y - afine_gap_alignment(x_string+xOffset, x_num, xRegionLen, y_string+yOffset, y_num, yRegionLen, - c2n, FORWARD_KSW, MATCH_SCORE_KSW, MISMATCH_SCORE_KSW, GAP_OPEN_KSW, GAP_EXT_KSW, - BAND_KSW, Z_DROP_KSW, endbouns, &maxXpos, &maxYpos, &mapGlobalScore, - &mapExtentScore, &xBuoundaryScore, &xBuoundaryYcoordinate, - &yBuoundaryScore, &yBuoundaryXcoordinate, &zdroped, mode); - - - if(!zdroped) - { - sum_score += mapGlobalScore; - } - else - { - ///return 0; - zdrop_occ++; - ///if(zdrop_occ > 1) return 0; - sum_score += mapExtentScore; - if(xRegionLen <= yRegionLen) - { - sum_score -= (GAP_OPEN_KSW + (xRegionLen - maxXpos)*GAP_EXT_KSW); - } - else - { - sum_score -= (GAP_OPEN_KSW + (yRegionLen - maxYpos)*GAP_EXT_KSW); - } - } - } - - (*final_scores) = sum_score; - **/ - return 1; -} - - - -long long get_affine_gap_score(overlap_region* ovc, UC_Read* g_read, UC_Read* overlap_read, uint8_t* x_num, -uint8_t* y_num, uint64_t EstimateXOlen, uint64_t EstimateYOlen) -{ - char* x_string; - char* y_string; - uint64_t yStrand; - long long minus_score_thres = (MAX(EstimateXOlen, EstimateYOlen)*HIGH_HET_ERROR_RATE*(MATCH_SCORE_KSW+(MAX(MISMATCH_SCORE_KSW,GAP_EXT_KSW)))); - long long total_score_thres = MAX(EstimateXOlen, EstimateYOlen)*MATCH_SCORE_KSW - minus_score_thres; - - yStrand = ovc->y_pos_strand; - - if(yStrand == 0) - { - recover_UC_Read(overlap_read, &R_INF, ovc->y_id); - } - else - { - recover_UC_Read_RC(overlap_read, &R_INF, ovc->y_id); - } - x_string = g_read->seq; - y_string = overlap_read->seq; - - long long sum = 0; - - if(fill_chain_by_affine_gap(&(ovc->f_cigar), x_string, y_string, ovc, Get_READ_LENGTH(R_INF, ovc->x_id), - Get_READ_LENGTH(R_INF, ovc->y_id), NULL, seq_nt6_table, x_num, y_num, &minus_score_thres, &sum) == 0) - { - return 0; - } - - if(sum >= total_score_thres) return 1; - return 0; -} - -/** -void recalcate_high_het_overlap(overlap_region_alloc* overlap_list, All_reads* R_INF, - UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read) -{ - long long j, k, i; - int threshold; - long long y_id; - int y_strand; - long long y_readLen; - long long x_start; - long long x_end; - long long x_len; - long long total_y_start; - long long total_y_end; - long long y_start; - long long Window_Len; - char* x_string; - char* y_string; - int end_site; - unsigned int error; - int real_y_start; - long long overlap_length; - int extra_begin, extra_end; - long long o_len; - kvec_t(uint8_t) x_num; - kvec_t(uint8_t) y_num; - kv_init(x_num); - kv_init(y_num); - - for (j = 0; j < (long long)overlap_list->length; j++) - { - - if(overlap_list->list[j].w_list_length == 0) continue; - y_id = overlap_list->list[j].y_id; - y_strand = overlap_list->list[j].y_pos_strand; - y_readLen = Get_READ_LENGTH((*R_INF), y_id); - - //i corresponding to each window of a overlap - //utilize the the end pos of pre-window in backwards - for (i = overlap_list->list[j].w_list_length - 1; i >= 0; i--) - { - ///the first matched window - if(overlap_list->list[j].w_list[i].y_end != -1) - { - ///note!!! need notification - ///this is the actual end postion in ystring - total_y_start = overlap_list->list[j].w_list[i].y_end - - overlap_list->list[j].w_list[i].extra_begin + 1; - - ///k corresponding to all unmatched windows at the right side of overlap_list->list[j].w_list[i] - ///so k starts from i + 1, and end to the first matched window - for (k = i + 1; k < (long long)overlap_list->list[j].w_list_length && overlap_list->list[j].w_list[k].y_end == -1; k++) - { - extra_begin = extra_end = 0; - - ///if y_start > y_readLen, direct terminate - if (total_y_start >= y_readLen) - { - break; - } - - ///there is no problem for x - x_start = overlap_list->list[j].w_list[k].x_start; - x_end = overlap_list->list[j].w_list[k].x_end; - x_len = x_end - x_start + 1; - ///there are two potiential reasons for unmatched window: - ///1. this window has a large number of differences - ///2. DP does not start from the right offset - threshold = double_error_threshold(overlap_list->list[j].w_list[k].error_threshold, x_len); - - y_start = total_y_start; - Window_Len = x_len + (threshold << 1); - - if(!determine_overlap_region(threshold, y_start, y_id, Window_Len, Get_READ_LENGTH((*R_INF), y_id), - &extra_begin, &extra_end, &y_start, &o_len)) - { - break; - } - - if(o_len + threshold < x_len) - { - break; - } - - fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, - R_INF, y_id, extra_begin, extra_end); - - x_string = g_read->seq + x_start; - y_string = dumy->overlap_region; - - ///note!!! need notification - end_site = Reserve_Banded_BPM(y_string, Window_Len, x_string, x_len, threshold, &error); - - ///if error==-1, unmatched - if (error!=(unsigned int)-1) - { - overlap_list->list[j].w_list[k].cigar.length = -1; - overlap_list->list[j].w_list[k].y_start = y_start; - overlap_list->list[j].w_list[k].y_end = y_start + end_site; - overlap_list->list[j].w_list[k].error = (int)error; - ///note!!! need notification - overlap_list->list[j].w_list[k].extra_begin = extra_begin; - overlap_list->list[j].w_list[k].extra_end = extra_end; - overlap_list->list[j].w_list[k].error_threshold = threshold; - - overlap_list->list[j].align_length += x_len; - } - else - { - break; - } - - ///note!!! need notification - total_y_start = y_start + end_site - extra_begin + 1; - } - - } - - } - - - - //i corresponding to each window of a overlap - //utilize the the start pos of next window in forward - for (i = 0; i < (long long)overlap_list->list[j].w_list_length; i++) - { - ///find the first matched window, which should not be the first window - ///the pre-window of this matched window must be unmatched - if(overlap_list->list[j].w_list[i].y_end != -1 && i != 0 && overlap_list->list[j].w_list[i - 1].y_end == -1) - { - ///check if the start pos of this matched window has been calculated - if(overlap_list->list[j].w_list[i].cigar.length == -1) - { - ///there is no problem for x - x_start = overlap_list->list[j].w_list[i].x_start; - x_end = overlap_list->list[j].w_list[i].x_end; - x_len = x_end - x_start + 1; - //may have bugs - threshold = overlap_list->list[j].w_list[i].error_threshold; - //may have bugs - //may have bugs - ///should not adjust threshold, since this window can be matched by the old threshold - ///threshold = Adjust_Threshold(threshold, x_len); - //may have bugs - Window_Len = x_len + (threshold << 1); - - - ///y_start is the real y_start - y_start = overlap_list->list[j].w_list[i].y_start; - extra_begin = overlap_list->list[j].w_list[i].extra_begin; - extra_end = overlap_list->list[j].w_list[i].extra_end; - o_len = Window_Len - extra_end - extra_begin; - fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, - R_INF, y_id, extra_begin, extra_end); - x_string = g_read->seq + x_start; - y_string = dumy->overlap_region; - - ///note!!! need notification - end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, - &(dumy->path_length), dumy->matrix_bit, dumy->path, - overlap_list->list[j].w_list[i].error, overlap_list->list[j].w_list[i].y_end - y_start); - - - ///y_start has already been calculated - if (error != (unsigned int)-1) - { - ///this condition is always wrong - ///in best case, real_y_start = threshold, end_site = Window_Len - threshold - 1 - if (end_site == Window_Len - 1 || real_y_start == 0) - { - if(fix_boundary(x_string, x_len, threshold, y_start, real_y_start, - end_site, extra_begin, extra_end, y_id, Window_Len, R_INF, dumy, - y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, - &extra_end, &error)) - { - overlap_list->list[j].w_list[i].error = error; - overlap_list->list[j].w_list[i].extra_begin = extra_begin; - overlap_list->list[j].w_list[i].extra_end = extra_end; - } - } - - generate_cigar(dumy->path, dumy->path_length, &(overlap_list->list[j].w_list[i]), - &real_y_start, &end_site, &error, x_string, x_len, y_string); - - ///note!!! need notification - real_y_start = y_start + real_y_start - extra_begin; - overlap_list->list[j].w_list[i].y_start = real_y_start; - ///I forget why don't reduce the extra_begin for y_end - ///it seems extra_begin will be reduced at the end of this function - overlap_list->list[j].w_list[i].y_end = y_start + end_site; - overlap_list->list[j].w_list[i].error = error; - } - else - { - fprintf(stderr, "error\n"); - } - } - else - { - real_y_start = overlap_list->list[j].w_list[i].y_start; - } - - - ///the end pos for pre window is real_y_start - 1 - total_y_end = real_y_start - 1; - ///find the unmatched window on the left of current matched window - ///k starts from i - 1 - for (k = i - 1; k >= 0 && overlap_list->list[j].w_list[k].y_end == -1; k--) - { - ///there is no problem in x - x_start = overlap_list->list[j].w_list[k].x_start; - x_end = overlap_list->list[j].w_list[k].x_end; - x_len = x_end - x_start + 1; - ///there are two potiential reasons for unmatched window: - ///1. this window has a large number of differences - ///2. DP does not start from the right offset - threshold = double_error_threshold(overlap_list->list[j].w_list[k].error_threshold, x_len); - - Window_Len = x_len + (threshold << 1); - - if(total_y_end <= 0) - { - break; - } - - ///y_start might be less than 0 - y_start = total_y_end - x_len + 1; - if(!determine_overlap_region(threshold, y_start, y_id, Window_Len, Get_READ_LENGTH((*R_INF), y_id), - &extra_begin, &extra_end, &y_start, &o_len)) - { - break; - } - - if(o_len + threshold < x_len) - { - break; - } - - fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, - R_INF, y_id, extra_begin, extra_end); - x_string = g_read->seq + x_start; - y_string = dumy->overlap_region; - - ///note!!! need notification - end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, - &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); - - if (error!=(unsigned int)-1) - { - ///this condition is always wrong - ///in best case, real_y_start = threshold, end_site = Window_Len - threshold - 1 - if (end_site == Window_Len - 1 || real_y_start == 0) - { - fix_boundary(x_string, x_len, threshold, y_start, real_y_start, end_site, - extra_begin, extra_end, y_id, Window_Len, R_INF, dumy, y_strand, error, - &y_start, &real_y_start, &end_site, - &extra_begin, &extra_end, &error); - } - - generate_cigar(dumy->path, dumy->path_length, &(overlap_list->list[j].w_list[k]), - &real_y_start, &end_site, &error, x_string, x_len, y_string); - - ///y_start has no shift, but y_end has shift - overlap_list->list[j].w_list[k].y_start = y_start + real_y_start - extra_begin; - overlap_list->list[j].w_list[k].y_end = y_start + end_site; - overlap_list->list[j].w_list[k].error = error; - overlap_list->list[j].align_length += x_len; - overlap_list->list[j].w_list[k].extra_begin = extra_begin; - overlap_list->list[j].w_list[k].extra_end = extra_end; - overlap_list->list[j].w_list[k].error_threshold = threshold; - } - else - { - break; - } - - total_y_end = y_start + real_y_start - 1 - extra_begin; - } - } - } - } - - - - overlap_list->mapped_overlaps_length = 0; - - double error_rate; - int is_update = 0; - for (j = 0; j < (long long)overlap_list->length; j++) - { - y_id = overlap_list->list[j].y_id; - y_strand = overlap_list->list[j].y_pos_strand; - y_readLen = Get_READ_LENGTH((*R_INF), y_id); - overlap_length = overlap_list->list[j].x_pos_e - overlap_list->list[j].x_pos_s + 1; - overlap_list->list[j].is_match = 0; - is_update = 0; - ///debug_scan_cigar(&(overlap_list->list[j])); - if(overlap_list->list[j].w_list_length == 0 || overlap_length == 0 || overlap_list->list[j].align_length == 0) continue; - ///only calculate cigar for high quality overlaps - if (overlap_length * OVERLAP_THRESHOLD_FILTER <= overlap_list->list[j].align_length) - { - - for (i = 0; i < (long long)overlap_list->list[j].w_list_length; i++) - { - ///first we need to check if this window is matched - if(overlap_list->list[j].w_list[i].y_end != -1) - { - ///second check if the cigar of this window has been got - if(overlap_list->list[j].w_list[i].cigar.length == -1) - { - ///there is no problem for x - x_start = overlap_list->list[j].w_list[i].x_start; - x_end = overlap_list->list[j].w_list[i].x_end; - x_len = x_end - x_start + 1; - //may have bugs - ///threshold = x_len * asm_opt.max_ov_diff_ec; - threshold = overlap_list->list[j].w_list[i].error_threshold; - //may have bugs - //may have bugs - ///should not adjust threshold, since this window can be matched by the old threshold - ///threshold = Adjust_Threshold(threshold, x_len); - //may have bugs - Window_Len = x_len + (threshold << 1); - - - ///y_start is the real y_start - ///for the window with cigar, y_start has already reduced extra_begin - y_start = overlap_list->list[j].w_list[i].y_start; - extra_begin = overlap_list->list[j].w_list[i].extra_begin; - extra_end = overlap_list->list[j].w_list[i].extra_end; - o_len = Window_Len - extra_end - extra_begin; - fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, - R_INF, y_id, extra_begin, extra_end); - x_string = g_read->seq + x_start; - y_string = dumy->overlap_region; - - - ///note!!! need notification - end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, - &(dumy->path_length), dumy->matrix_bit, dumy->path, - overlap_list->list[j].w_list[i].error, overlap_list->list[j].w_list[i].y_end - y_start); - - if (error != (unsigned int)-1) - { - if (end_site == Window_Len - 1 || real_y_start == 0) - { - - if(fix_boundary(x_string, x_len, threshold, y_start, real_y_start, end_site, - extra_begin, extra_end, y_id, Window_Len, R_INF, dumy, y_strand, error, - &y_start, &real_y_start, &end_site, - &extra_begin, &extra_end, &error)) - { - overlap_list->list[j].w_list[i].error = error; - overlap_list->list[j].w_list[i].extra_begin = extra_begin; - overlap_list->list[j].w_list[i].extra_end = extra_end; - } - - } - - generate_cigar(dumy->path, dumy->path_length, &(overlap_list->list[j].w_list[i]), - &real_y_start, &end_site, &error, x_string, x_len, y_string); - - ///note!!! need notification - real_y_start = y_start + real_y_start - extra_begin; - overlap_list->list[j].w_list[i].y_start = real_y_start; - overlap_list->list[j].w_list[i].y_end = y_start + end_site - extra_begin; - overlap_list->list[j].w_list[i].error = error; - } - else - { - fprintf(stderr, "error\n"); - } - } - else - { - overlap_list->list[j].w_list[i].y_end -= overlap_list->list[j].w_list[i].extra_begin; - } - - - } - } - - error_rate = non_trim_error_rate(overlap_list, j, R_INF, dumy, g_read); - - - if (error_rate <= HIGH_HET_ERROR_RATE) - { - is_update = 1; - } - } - - if((is_update == 0) && (overlap_list->list[j].align_length >= WINDOW) && - (overlap_length * HIGH_HET_OVERLAP_THRESHOLD_FILTER <= overlap_list->list[j].align_length)) - { - kv_resize(uint8_t, x_num, (uint64_t)(Get_READ_LENGTH((*R_INF), overlap_list->list[j].x_id))); - kv_resize(uint8_t, y_num, (uint64_t)(Get_READ_LENGTH((*R_INF), overlap_list->list[j].y_id))); - is_update = get_affine_gap_score(&(overlap_list->list[j]), g_read, overlap_read, x_num.a, y_num.a, - overlap_list->list[j].x_pos_e + 1 - overlap_list->list[j].x_pos_s, - overlap_list->list[j].y_pos_e + 1 - overlap_list->list[j].y_pos_s); - } - - if(is_update) - { - overlap_list->list[j].is_match = 2; - } - } - - kv_destroy(x_num); - kv_destroy(y_num); -} - - - -void correct_overlap_high_het(overlap_region_alloc* overlap_list, All_reads* R_INF, - UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read) -{ - clear_Correct_dumy(dumy, overlap_list, NULL); - - long long window_start, window_end; - - Window_Pool w_inf; - - init_Window_Pool(&w_inf, g_read->length, WINDOW, (int)(1.0/asm_opt.max_ov_diff_ec)); - - int flag = 0; - - while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) - { - dumy->length = 0; - dumy->lengthNT = 0; - flag = get_interval(window_start, window_end, overlap_list, dumy, w_inf.window_length); - - switch (flag) - { - case 1: ///no match here - break; - case 0: ///no match here - break; - case -2: ///if flag == -2, loop would be terminated - break; - } - - ///dumy->lengthNT represent how many overlaps that the length of them is not equal to WINDOW; may larger or less than WINDOW - ///dumy->length represent how many overlaps that the length of them is WINDOW - //may improve - ///now the windows which are larger than WINDOW are verified one-by-one, to improve it, we can do it group-bygroup - verify_window(window_start, window_end, overlap_list, dumy, R_INF, g_read->seq); - } - - recalcate_high_het_overlap(overlap_list, R_INF, g_read, dumy, overlap_read); -} -**/ - -uint64_t update_ov_track_0(Fake_Cigar* z, overlap_region *o, int64_t apend_be, int64_t xl, int64_t yl, -k_mer_hit* hit, int64_t n_hit) -{ - int64_t k, dq, dr, dd, pdd = INT32_MAX, xr, yr; - z->length = 0; - if(hit[0].readID != o->y_id || hit[0].strand != o->y_pos_strand) return 0; - ///update o->s - o->x_pos_s = hit[0].self_offset; o->y_pos_s = hit[0].offset; - if(o->x_pos_s <= o->y_pos_s) { - o->y_pos_s -= o->x_pos_s; o->x_pos_s = 0; - } else { - o->x_pos_s -= o->y_pos_s; o->y_pos_s = 0; - } - - if(apend_be == 1) add_fake_cigar(z, o->x_pos_s, 0, NULL); - for (k = 0; (k < n_hit) && (hit[k].readID == o->y_id) && (hit[k].strand == o->y_pos_strand); k++) { - dq = hit[k].self_offset - o->x_pos_s; - dr = hit[k].offset - o->y_pos_s; - dd = dr - dq; - if(dd != pdd) { - pdd = dd; - add_fake_cigar(z, hit[k].self_offset, pdd, NULL); - } - } - ///update o->s - o->x_pos_e = hit[k-1].self_offset; o->y_pos_e = hit[k-1].offset; - xr = xl-o->x_pos_e-1; yr = yl-o->y_pos_e-1; - if(xr <= yr) { - o->x_pos_e = xl-1; o->y_pos_e += xr; - } else { - o->y_pos_e = yl-1; o->x_pos_e += yr; - } - - if((apend_be == 1) && (get_fake_gap_pos(z, z->length-1)!=((int64_t)o->x_pos_e))) { - add_fake_cigar(z, o->x_pos_e, get_fake_gap_shift(z, z->length-1), NULL); - } - - return k; -} - -int64_t iter_hpc(uint8_t *m, int64_t mn, int64_t *mo, int64_t rev, int64_t *so, int64_t *ho, int64_t sc) -{ - if(sc == 0) return 0; - if(sc <= (*so)) return (*ho)-1; - if(!rev) { - while((*mo) < mn) { - for (; (*mo) < mn && m[(*mo)] == 255; (*mo)++) { - (*so) += m[(*mo)]; - } - (*so) += m[(*mo)]; (*mo)++; (*ho)++; - if(sc <= (*so)) return (*ho)-1; - } - } else { - while((*mo) < mn) { - (*so) += m[mn-(*mo)-1]; (*mo)++; (*ho)++; - for (; (*mo) < mn && m[mn-(*mo)-1] == 255; (*mo)++) { - (*so) += m[mn-(*mo)-1]; - } - if(sc <= (*so)) return (*ho)-1; - } - } - - return -1; -} - -uint64_t update_ov_track_hpc_0(Fake_Cigar* z, overlap_region *o, int64_t apend_be, int64_t xhl, -uint32_t *x_idx, int64_t y_idx_map_l, uint8_t *y_idx_map, hpc_t *hpc_g, k_mer_hit* hit, int64_t n_hit) -{ - int64_t k, dq, dr, dd, pdd = INT32_MAX, xr, yr, yhl, mo = 0, so = 0, ho = 0, x1, y1; - z->length = 0; - if(hit[0].readID != o->y_id || hit[0].strand != o->y_pos_strand) return 0; - yhl = hpc_len(*hpc_g, o->y_id); - - x1 = x_idx[hit[0].self_offset]; - y1 = iter_hpc(y_idx_map, y_idx_map_l, &mo, o->y_pos_strand, &so, &ho, hit[0].offset); - assert(y1 >= 0); - o->x_pos_s = x1; o->y_pos_s = y1; - - ///update o->s - if(o->x_pos_s <= o->y_pos_s) { - o->y_pos_s -= o->x_pos_s; o->x_pos_s = 0; - } else { - o->x_pos_s -= o->y_pos_s; o->y_pos_s = 0; - } - - - if(apend_be == 1) add_fake_cigar(z, o->x_pos_s, 0, NULL); - for (k = 0; (k < n_hit) && (hit[k].readID == o->y_id) && (hit[k].strand == o->y_pos_strand); k++) { - x1 = x_idx[hit[k].self_offset]; - y1 = iter_hpc(y_idx_map, y_idx_map_l, &mo, o->y_pos_strand, &so, &ho, hit[k].offset); - assert(y1 >= 0); - dq = x1 - o->x_pos_s; - dr = y1 - o->y_pos_s; - dd = dr - dq; - if(dd != pdd) { - pdd = dd; - add_fake_cigar(z, x1, pdd, NULL); - } - } - ///update o->s - x1 = x_idx[hit[k-1].self_offset]; - y1 = iter_hpc(y_idx_map, y_idx_map_l, &mo, o->y_pos_strand, &so, &ho, hit[k-1].offset); - assert(y1 >= 0); - o->x_pos_e = x1; o->y_pos_e = y1; - xr = xhl-o->x_pos_e-1; yr = yhl-o->y_pos_e-1; - if(xr <= yr) { - o->x_pos_e = xhl-1; o->y_pos_e += xr; - } else { - o->y_pos_e = yhl-1; o->x_pos_e += yr; - } - - if((apend_be == 1) && (get_fake_gap_pos(z, z->length-1)!=((int64_t)o->x_pos_e))) { - add_fake_cigar(z, o->x_pos_e, get_fake_gap_shift(z, z->length-1), NULL); - } - - return k; -} - -///(char *qstr, kvec_t_u64_warp* q_idx) -> only used for hpc -uint64_t update_ol_track(overlap_region_alloc* ol, Candidates_list *cl, hpc_t *hpc_g, const ul_idx_t *udb, uint32_t apend_be, uint64_t qlen, -char *qstr, kvec_t_u32_warp* q_idx) -{ - uint64_t cln = cl->length, i, k, l, m = 0; overlap_region *r; - if(hpc_g) { - if(ol->length) { - q_idx->a.n = 0; kv_resize(uint32_t, q_idx->a, qlen); m = 0; - for (l = 0, k = 1; k <= qlen; k++) { - if((k == qlen) || (qstr[k] != qstr[l]) || (seq_nt4_table[(uint8_t)qstr[l]] >= 4)) { - for (i = l; i < k; i++) q_idx->a.a[i] = m; - l = k; m++; - } - } - - for (i = k = 0; i < ol->length; ++i) { - r = &(ol->list[i]); k = r->non_homopolymer_errors; - update_ov_track_hpc_0(&(r->f_cigar), r, apend_be, m, q_idx->a.a, - (uint32_t)hpc_g->mm->idx[r->y_id], hpc_g->mm->a + (hpc_g->mm->idx[r->y_id]>>32), - hpc_g, cl->list+k, cln-k); - } - } - } else { - if(ol->length) { - for (i = k = 0; i < ol->length; ++i) { - r = &(ol->list[i]); k = r->non_homopolymer_errors; - update_ov_track_0(&(r->f_cigar), r, apend_be, qlen, udb->ug->u.a[r->y_id].len, cl->list+k, cln-k); - } - } - } - return m;///hpc length -} - -uint64_t gen_hpc_str(const char *in, uint32_t in_l, UC_Read *z, uint64_t *in_hl) -{ - uint64_t hl, k, l; - if(in_hl) { - hl = (*in_hl); - } else { - for (l = hl = 0, k = 1; k <= in_l; k++) { - if((k == in_l) || (in[k] != in[l]) || (seq_nt4_table[(uint8_t)in[l]] >= 4)) { - hl++; l = k; - } - } - } - resize_UC_Read(z, hl); z->length = 0; - for (l = 0, k = 1; k <= in_l; k++) { - if((k == in_l) || (in[k] != in[l]) || (seq_nt4_table[(uint8_t)in[l]] >= 4)) { - z->seq[z->length++] = in[l]; l = k; - } - } - return hl; -} - -///ts do not have aux_beg, while te has -uint32_t push_wlst(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, overlap_region* ol, - char* qstr, char *tstr, char *tstr_1, Correct_dumy* dumy, - int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t tl, - int64_t error, int64_t aux_beg, int64_t aux_end, int64_t thres, double e_rate, - int64_t block_s, uint32_t sec_check, double ovlp_cut, void *km) -{ - - window_list p, t, *a; int64_t w_e, w_s, ce = qs - 1, cs = ol->x_pos_s, toff, ovl, ualn, aln; - uint64_t a_n, k; - - p.x_start = qs; p.x_end = qe; p.y_start = ts; p.y_end = te; p.error = error; - p.extra_begin = aux_beg; p.extra_end = aux_end; - p.error_threshold = thres; p.cidx = p.clen = 0; - if(ol->w_list.n > 0) { //utilize the the end pos of pre-window in forward - w_e = ol->w_list.a[ol->w_list.n-1].x_end; - toff = ol->w_list.a[ol->w_list.n-1].y_end + 1 - ol->w_list.a[ol->w_list.n-1].extra_begin; - while ((w_e < ce) && (toff < tl)) { - w_s = w_e + 1; - get_win_id_by_s(ol, w_s, block_s, &w_e); - // x_start = w_s; x_end = w_e; - if(aln_wlst_adv(ol, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, - ol->y_pos_strand, ol->y_id, w_s, w_e, toff, block_s, e_rate, 0)) { - toff = ol->w_list.a[ol->w_list.n-1].y_end + 1 - ol->w_list.a[ol->w_list.n-1].extra_begin; - } else { - break; - } - } - cs = ol->w_list.a[ol->w_list.n-1].x_end + 1; - } - ///utilize the the start pos of next window in backward - a_n = ol->w_list.n; w_s = qs; - if(w_s > cs) { - gen_backtrace_adv(&p, ol, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, ol->y_pos_strand, ol->y_id); - p.y_end += p.extra_begin; - toff = p.y_start - 1; - while ((w_s > cs) && (toff > 0)) { - w_e = w_s - 1; - get_win_id_by_e(ol, w_e, block_s, &w_s); - // x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; - if(aln_wlst_adv(ol, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, - ol->y_pos_strand, ol->y_id, w_s, w_e, toff+1-(w_e+1-w_s), block_s, e_rate, 1)) { - ///y_start has no shift, but y_end has shift - ol->w_list.a[ol->w_list.n-1].y_start -= ol->w_list.a[ol->w_list.n-1].extra_begin; - toff = ol->w_list.a[ol->w_list.n-1].y_start - 1; - } else { - break; - } - } - } - - ol->align_length += qe + 1 - qs; - ovl = ol->x_pos_e+1-ol->x_pos_s; ualn = (qe + 1 - ol->x_pos_s) - ol->align_length; aln = ovl-ualn; - if((!simi_pass(ovl, aln, 0, ovlp_cut, &e_rate)) && (!simi_pass(ovl, aln, sec_check, ovlp_cut, NULL))) { - kv_push(window_list, ol->w_list, p); - return 0; - } - - if(ol->w_list.n > a_n) { - a = ol->w_list.a + a_n; a_n = ol->w_list.n - a_n; toff = a_n; a_n >>=1; - for (k = 0; k < a_n; k++) { - t = a[k]; a[k] = a[toff-1-k]; a[toff-1-k] = t; - } - } - kv_push(window_list, ol->w_list, p); - return 1; -} - -uint32_t align_ul_ed_post(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, char* qstr, char *tstr, char *tstr_1, -Correct_dumy* dumy, double e_rate, int64_t w_l, double ovlp_cut, void *km) -{ - int64_t q_s, q_e, nw, k, q_l, t_tot_l, sec_check = (uref&&(!hpc_g))?1:0; - int64_t aux_beg, aux_end, t_s, thre, aln_l, t_pri_l, t_end; - char *q_string, *t_string; unsigned int error; - z->w_list.n = 0; z->is_match = 0; z->align_length = 0; - nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, w_l); - get_win_se_by_normalize_xs(z, (z->x_pos_s/w_l)*w_l, w_l, &q_s, &q_e); - for (k = 0; k < nw; k++) { - aux_beg = aux_end = 0; q_l = 1 + q_e - q_s; - thre = q_l*e_rate; thre = Adjust_Threshold(thre, q_l); - if(thre > THRESHOLD_MAX_SIZE) thre = THRESHOLD_MAX_SIZE; - ///offset of y - t_s = (q_s - z->x_pos_s) + z->y_pos_s; - t_s += y_start_offset(q_s, &(z->f_cigar)); - - aln_l = q_l + (thre<<1); t_tot_l = hpc_g?hpc_len(*hpc_g, z->y_id):uref->ug->u.a[z->y_id].len; - if(init_waln(thre, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) { - q_string = qstr+q_s; - t_string = return_str_seq(tstr, t_s, t_pri_l, z->y_pos_strand, hpc_g, uref, z->y_id, aux_beg, aux_end); - - t_end = Reserve_Banded_BPM(t_string, aln_l, q_string, q_l, thre, &error); - // int32_t debug_t_end, debug_error; - // debug_t_end = ed_band_cal_semi(t_string, aln_l, q_string, q_l, thre, &debug_error); - // if((t_end != debug_t_end) || (t_end >= 0 && debug_t_end >= 0 && debug_error != (int32_t)error)) { - // fprintf(stderr, "[M::%s] debug_error->%d, error->%d\n", __func__, debug_error, error); - // } - - - if (error!=((unsigned int)-1)) { - ///t_s do not have aux_beg, while t_s + t_end (aka, te) has - if(!push_wlst(uref, hpc_g, NULL, z, qstr, tstr, tstr_1, dumy, q_s, q_e, t_s, t_s + t_end, - t_tot_l, error, aux_beg, aux_end, thre, e_rate, w_l, sec_check, ovlp_cut, km)) { - return 0; - } - // append_window_list(z, q_s, q_e, t_s, t_s + t_end, error, aux_beg, aux_end, thre, w_l, km); - } - } - q_s = q_e + 1; q_e = q_s + w_l - 1; - if(q_e >= (int64_t)z->x_pos_e) q_e = z->x_pos_e; - } - - if((!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, 0, ovlp_cut, &e_rate)) && - (!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, sec_check, ovlp_cut, NULL))) return 0; - return 1; -} - -void prt_cigar(uint16_t *ca, uint32_t cn) -{ - uint32_t k; - for (k = 0; k < cn; k++) { - fprintf(stderr, "%u%c", ca[k]&0x3fff, "EMDI"[ca[k]>>14]); - } - fprintf(stderr, "\n"); -} - - -inline uint32_t gen_backtrace_adv_exz(window_list *p, overlap_region *z, All_reads *rref, hpc_t *hpc_g, const ul_idx_t *uref, -char *qstr, char *tstr, bit_extz_t *exz, uint32_t rev, uint32_t id) -{ - if(p->error < 0 || p->y_end < 0) return 0; - int64_t qs, qe, ql, tl, aln_l, t_pri_l, thres, ts, t_tot_l; - int64_t aux_beg, aux_end; - char *q_string, *t_string; - ///there is no problem for x - qs = p->x_start; qe = p->x_end; ql = qe + 1 - qs; - thres = p->error_threshold; aln_l = ql + (thres<<1); - - ///y_start is the real y_start - ///for the window with cigar, y_start has already reduced extra_begin - ts = p->y_start; aux_beg = p->extra_begin; aux_end = p->extra_end; - if(aux_end >= 0) { - t_pri_l = aln_l - aux_beg - aux_end; - } else { - if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); - else if(uref) t_tot_l = uref->ug->u.a[id].len; - else t_tot_l = Get_READ_LENGTH((*rref), id); - - t_pri_l = ts + aln_l - aux_beg; if(t_pri_l > t_tot_l) t_pri_l = t_tot_l; - t_pri_l = t_pri_l - ts; - } - - q_string = qstr + qs; tl = t_pri_l; - if(rref) { - recover_UC_Read_sub_region(tstr, ts, t_pri_l, rev, rref, id); t_string = tstr; - } else { - t_string = return_str_seq_exz(tstr, ts, t_pri_l, rev, hpc_g, uref, id); - } - - exz->ts = 0; exz->te = p->x_end-p->x_start; exz->tl = ql; - exz->ps = -1; exz->pe = p->y_end-p->y_start; exz->pl = tl; - exz->err = p->error; exz->thre = p->error_threshold; - // clear_align(*exz); - ed_band_cal_semi_64_w_absent_diag_trace(t_string, tl, q_string, ql, thres, aux_beg, exz); - // if(id == 178 && p->x_start == 86800 && p->x_end == 86807) { - // fprintf(stderr, "\n[M::%s::semi] exz->ps::%d, exz->pe::%d, exz->ts::%d, exz->te::%d, exz->err::%d, exz->cigar.n::%d\n", - // __func__, exz->ps, exz->pe, exz->ts, exz->te, exz->err, (int32_t)exz->cigar.n); - // fprintf(stderr, "[M::%s::semi] p->y_start::%d, p->y_end::%d, p->x_start::%d, p->x_end::%d, p->error::%d\n", - // __func__, p->y_start, p->y_end, p->x_start, p->x_end, p->error); - // if(is_align(*exz)) { - // prt_cigar(exz->cigar.a, exz->cigar.n); - // fprintf(stderr, "[tstr] %.*s\n", exz->pe+1-exz->ps, t_string+exz->ps); - // fprintf(stderr, "[qstr] %.*s\n", exz->te+1-exz->ts, q_string+exz->ts); - // } - // } - // assert(is_align(*exz)); - // assert(cigar_check(t_string, q_string, exz)); - - - if(is_align(*exz)) { - p->y_start = ts + exz->ps;///difference - p->y_end = ts + exz->pe; - p->error = exz->err; - push_wcigar(p, &(z->w_list), exz); - ///this condition is always wrong - ///in best case, r_ts = threshold, t_end = aln_l - thres - 1 - if ((((exz->pe+1) == tl) || (exz->ps == 0)) && (exz->err > 0)) { - if(recal_boundary_exz(q_string, tstr, ql, tl, thres, ts, exz->ps, exz->pe, - exz->err, id, rev, exz, rref, hpc_g, uref, &ts, &aux_beg, &aux_end)) { - //update cigar - z->w_list.c.n = p->cidx; push_wcigar(p, &(z->w_list), exz); - - p->y_start = ts + exz->ps;///difference - p->y_end = ts + exz->pe; - p->error = exz->err; - } - } - p->extra_begin = aux_beg; - p->extra_end = aux_end; - return 1; - } - p->error = -1; - return 0; -} - -inline uint32_t gen_backtrace_non_retrieve_adv_exz(window_list *p, overlap_region *z, char *qstr, char *tstr, int64_t t_tot_l, bit_extz_t *exz, uint32_t rev, uint32_t id) -{ - if(p->error < 0 || p->y_end < 0) return 0; - int64_t qs, qe, ql, tl, aln_l, t_pri_l, thres, ts; - int64_t aux_beg, aux_end; - char *q_string, *t_string; - ///there is no problem for x - qs = p->x_start; qe = p->x_end; ql = qe + 1 - qs; - thres = p->error_threshold; aln_l = ql + (thres<<1); - - ///y_start is the real y_start - ///for the window with cigar, y_start has already reduced extra_begin - ts = p->y_start; aux_beg = p->extra_begin; aux_end = p->extra_end; - if(aux_end >= 0) { - t_pri_l = aln_l - aux_beg - aux_end; - } else { - t_pri_l = ts + aln_l - aux_beg; if(t_pri_l > t_tot_l) t_pri_l = t_tot_l; - t_pri_l = t_pri_l - ts; - } - - q_string = qstr + qs; t_string = tstr + ts; tl = t_pri_l; - - exz->ts = 0; exz->te = p->x_end-p->x_start; exz->tl = ql; - exz->ps = -1; exz->pe = p->y_end-p->y_start; exz->pl = tl; - exz->err = p->error; exz->thre = p->error_threshold; - // clear_align(*exz); - ed_band_cal_semi_64_w_absent_diag_trace(t_string, tl, q_string, ql, thres, aux_beg, exz); - // if(id == 178 && p->x_start == 86800 && p->x_end == 86807) { - // fprintf(stderr, "\n[M::%s::semi] exz->ps::%d, exz->pe::%d, exz->ts::%d, exz->te::%d, exz->err::%d, exz->cigar.n::%d\n", - // __func__, exz->ps, exz->pe, exz->ts, exz->te, exz->err, (int32_t)exz->cigar.n); - // fprintf(stderr, "[M::%s::semi] p->y_start::%d, p->y_end::%d, p->x_start::%d, p->x_end::%d, p->error::%d\n", - // __func__, p->y_start, p->y_end, p->x_start, p->x_end, p->error); - // if(is_align(*exz)) { - // prt_cigar(exz->cigar.a, exz->cigar.n); - // fprintf(stderr, "[tstr] %.*s\n", exz->pe+1-exz->ps, t_string+exz->ps); - // fprintf(stderr, "[qstr] %.*s\n", exz->te+1-exz->ts, q_string+exz->ts); - // } - // } - // assert(is_align(*exz)); - // assert(cigar_check(t_string, q_string, exz)); - - - if(is_align(*exz)) { - p->y_start = ts + exz->ps;///difference - p->y_end = ts + exz->pe; - p->error = exz->err; - push_wcigar(p, &(z->w_list), exz); - ///this condition is always wrong - ///in best case, r_ts = threshold, t_end = aln_l - thres - 1 - if ((((exz->pe+1) == tl) || (exz->ps == 0)) && (exz->err > 0)) { - if(recal_boundary_non_retrieve_exz(q_string, tstr, t_tot_l, ql, tl, thres, ts, exz->ps, exz->pe, - exz->err, id, rev, exz, &ts, &aux_beg, &aux_end)) { - //update cigar - z->w_list.c.n = p->cidx; push_wcigar(p, &(z->w_list), exz); - - p->y_start = ts + exz->ps;///difference - p->y_end = ts + exz->pe; - p->error = exz->err; - } - } - p->extra_begin = aux_beg; - p->extra_end = aux_end; - return 1; - } - p->error = -1; - return 0; -} - - -///ts do not have aux_beg, while te has -uint32_t push_wlst_exz(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, overlap_region* ol, - char* qstr, char *tstr, bit_extz_t *exz, uint32_t max_err, - int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t tl, - int64_t aux_beg, int64_t aux_end, double e_rate, int64_t block_s, uint32_t sec_check, double ovlp_cut, int64_t force_aln, void *km) -{ - - window_list p, t, *a; int64_t w_e, w_s, ce = qs - 1, cs = ol->x_pos_s, toff, ovl, ualn, aln, ys; - uint64_t a_n, k; - - p.x_start = qs; p.x_end = qe; p.y_start = ts; p.y_end = te; p.error = exz->err; - p.extra_begin = aux_beg; p.extra_end = aux_end; p.error_threshold = exz->thre; p.cidx = p.clen = 0; - if(ol->w_list.n > 0) { //utilize the the end pos of pre-window in forward - w_e = ol->w_list.a[ol->w_list.n-1].x_end; - toff = ol->w_list.a[ol->w_list.n-1].y_end + 1; - while ((w_e < ce) && (toff < tl)) { - w_s = w_e + 1; - get_win_id_by_s(ol, w_s, block_s, &w_e); - // x_start = w_s; x_end = w_e; - if(aln_wlst_adv_exz(ol, rref, hpc_g, uref, qstr, tstr, exz, max_err, - ol->y_pos_strand, ol->y_id, w_s, w_e, toff, block_s, e_rate, 0)) { - toff = ol->w_list.a[ol->w_list.n-1].y_end + 1; - } else { - break; - } - } - cs = ol->w_list.a[ol->w_list.n-1].x_end + 1; - } - ///utilize the the start pos of next window in backward - a_n = ol->w_list.n; w_s = qs; - if(w_s > cs) { - gen_backtrace_adv_exz(&p, ol, rref, hpc_g, uref, qstr, tstr, exz, ol->y_pos_strand, ol->y_id); - toff = p.y_start - 1; - while (w_s > cs) { - w_e = w_s - 1; - get_win_id_by_e(ol, w_e, block_s, &w_s); ys = toff+1-(w_e+1-w_s); - // x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; - if((ys >= 0) && aln_wlst_adv_exz(ol, rref, hpc_g, uref, qstr, tstr, exz, max_err, - ol->y_pos_strand, ol->y_id, w_s, w_e, ys, block_s, e_rate, 1)) { - toff = ol->w_list.a[ol->w_list.n-1].y_start - 1; - } else { - break; - } - } - } - - ol->align_length += qe + 1 - qs; - ovl = ol->x_pos_e+1-ol->x_pos_s; ualn = (qe + 1 - ol->x_pos_s) - ol->align_length; aln = ovl-ualn; - if((!force_aln) && (!simi_pass(ovl, aln, 0, ovlp_cut, &e_rate)) && (!simi_pass(ovl, aln, sec_check, ovlp_cut, NULL))) { - kv_push(window_list, ol->w_list, p); - return 0; - } - - if(ol->w_list.n > a_n) { - a = ol->w_list.a + a_n; a_n = ol->w_list.n - a_n; toff = a_n; a_n >>=1; - for (k = 0; k < a_n; k++) { - t = a[k]; a[k] = a[toff-1-k]; a[toff-1-k] = t; - } - } - kv_push(window_list, ol->w_list, p); - return 1; -} - -#define pass_qovlp(o, a, r) (((a)>0)&&((o)*(r)<=(a))) - -///ts do not have aux_beg, while te has -uint32_t push_hc_wlst_exz(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, overlap_region* ol, - char* qstr, char *tstr, bit_extz_t *exz, uint32_t max_err, - int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t tl, - int64_t aux_beg, int64_t aux_end, double e_rate, int64_t block_s, double ovlp_cut, int64_t force_aln, void *km) -{ - - window_list p, t, *a; int64_t w_e, w_s, ce = qs - 1, cs = ol->x_pos_s, toff, ovl, ualn, aln, ys; - uint64_t a_n, k; - p.x_start = qs; p.x_end = qe; p.y_start = ts; p.y_end = te; p.error = exz->err; - p.extra_begin = aux_beg; p.extra_end = aux_end; p.error_threshold = exz->thre; p.cidx = p.clen = 0; - if(ol->w_list.n > 0) { //utilize the the end pos of pre-window in forward - w_e = ol->w_list.a[ol->w_list.n-1].x_end; - toff = ol->w_list.a[ol->w_list.n-1].y_end + 1; - while ((w_e < ce) && (toff < tl)) { - w_s = w_e + 1; - get_win_id_by_s(ol, w_s, block_s, &w_e); - // x_start = w_s; x_end = w_e; - if(aln_wlst_adv_exz(ol, rref, hpc_g, uref, qstr, tstr, exz, max_err, - ol->y_pos_strand, ol->y_id, w_s, w_e, toff, block_s, e_rate, 0)) { - toff = ol->w_list.a[ol->w_list.n-1].y_end + 1; - } else { - break; - } - } - cs = ol->w_list.a[ol->w_list.n-1].x_end + 1; - } - ///utilize the the start pos of next window in backward - a_n = ol->w_list.n; w_s = qs; - if(w_s > cs) { - gen_backtrace_adv_exz(&p, ol, rref, hpc_g, uref, qstr, tstr, exz, ol->y_pos_strand, ol->y_id); - toff = p.y_start - 1; - while (w_s > cs) { - w_e = w_s - 1; - get_win_id_by_e(ol, w_e, block_s, &w_s); ys = toff+1-(w_e+1-w_s); - // x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; - if((ys >= 0) && aln_wlst_adv_exz(ol, rref, hpc_g, uref, qstr, tstr, exz, max_err, - ol->y_pos_strand, ol->y_id, w_s, w_e, ys, block_s, e_rate, 1)) { - toff = ol->w_list.a[ol->w_list.n-1].y_start - 1; - } else { - break; - } - } - } - - ol->align_length += qe + 1 - qs; - ovl = ol->x_pos_e+1-ol->x_pos_s; ualn = (qe + 1 - ol->x_pos_s) - ol->align_length; aln = ovl-ualn; - // if((!force_aln) && (!simi_pass(ovl, aln, 0, ovlp_cut, &e_rate)) && (!simi_pass(ovl, aln, sec_check, ovlp_cut, NULL))) { - if((!force_aln) && (!pass_qovlp(ovl, aln, ovlp_cut))) { - kv_push(window_list, ol->w_list, p); - return 0; - } - - if(ol->w_list.n > a_n) { - a = ol->w_list.a + a_n; a_n = ol->w_list.n - a_n; toff = a_n; a_n >>=1; - for (k = 0; k < a_n; k++) { - t = a[k]; a[k] = a[toff-1-k]; a[toff-1-k] = t; - } - } - kv_push(window_list, ol->w_list, p); - return 1; -} - - -///ts do not have aux_beg, while te has -uint32_t push_hc_wlst_non_retrieve_exz(overlap_region* ol, char* qa, int64_t ql, char *ta, int64_t tl, bit_extz_t *exz, uint32_t max_err, - int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t aux_beg, int64_t aux_end, double e_rate, int64_t block_s, double ovlp_cut, int64_t force_aln, void *km) -{ - - window_list p, t, *a; int64_t w_e, w_s, ce = qs - 1, cs = ol->x_pos_s, toff, ovl, ualn, aln, ys; - uint64_t a_n, k; - p.x_start = qs; p.x_end = qe; p.y_start = ts; p.y_end = te; p.error = exz->err; - p.extra_begin = aux_beg; p.extra_end = aux_end; p.error_threshold = exz->thre; p.cidx = p.clen = 0; - if(ol->w_list.n > 0) { //utilize the the end pos of pre-window in forward - w_e = ol->w_list.a[ol->w_list.n-1].x_end; - toff = ol->w_list.a[ol->w_list.n-1].y_end + 1; - while ((w_e < ce) && (toff < tl)) { - w_s = w_e + 1; - get_win_id_by_s(ol, w_s, block_s, &w_e); - // x_start = w_s; x_end = w_e; - if(aln_wlst_adv_non_retrieve_exz(ol, qa, ta, tl, exz, max_err, - ol->y_pos_strand, ol->y_id, w_s, w_e, toff, block_s, e_rate, 0)) { - toff = ol->w_list.a[ol->w_list.n-1].y_end + 1; - } else { - break; - } - } - cs = ol->w_list.a[ol->w_list.n-1].x_end + 1; - } - ///utilize the the start pos of next window in backward - a_n = ol->w_list.n; w_s = qs; - if(w_s > cs) { - gen_backtrace_non_retrieve_adv_exz(&p, ol, qa, ta, tl, exz, ol->y_pos_strand, ol->y_id); - toff = p.y_start - 1; - while (w_s > cs) { - w_e = w_s - 1; - get_win_id_by_e(ol, w_e, block_s, &w_s); ys = toff+1-(w_e+1-w_s); - // x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; - if((ys >= 0) && aln_wlst_adv_non_retrieve_exz(ol, qa, ta, tl, exz, max_err, - ol->y_pos_strand, ol->y_id, w_s, w_e, ys, block_s, e_rate, 1)) { - toff = ol->w_list.a[ol->w_list.n-1].y_start - 1; - } else { - break; - } - } - } - - ol->align_length += qe + 1 - qs; - ovl = ol->x_pos_e+1-ol->x_pos_s; ualn = (qe + 1 - ol->x_pos_s) - ol->align_length; aln = ovl-ualn; - // if((!force_aln) && (!simi_pass(ovl, aln, 0, ovlp_cut, &e_rate)) && (!simi_pass(ovl, aln, sec_check, ovlp_cut, NULL))) { - if((!force_aln) && (!pass_qovlp(ovl, aln, ovlp_cut))) { - kv_push(window_list, ol->w_list, p); - return 0; - } - - if(ol->w_list.n > a_n) { - a = ol->w_list.a + a_n; a_n = ol->w_list.n - a_n; toff = a_n; a_n >>=1; - for (k = 0; k < a_n; k++) { - t = a[k]; a[k] = a[toff-1-k]; a[toff-1-k] = t; - } - } - kv_push(window_list, ol->w_list, p); - return 1; -} - -uint32_t align_ul_ed_post_extz(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, char* qstr, char *tstr, bit_extz_t *exz, double e_rate, int64_t w_l, double ovlp_cut, int64_t force_aln, void *km) -{ - int64_t q_s, q_e, nw, k, q_l, t_l, t_tot_l, sec_check = (uref&&(!hpc_g))?1:0; - int64_t aux_beg, aux_end, t_s, thre, aln_l, t_pri_l; - char *q_string, *t_string; - z->w_list.n = 0; z->is_match = 0; z->align_length = 0; - nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, w_l); - get_win_se_by_normalize_xs(z, (z->x_pos_s/w_l)*w_l, w_l, &q_s, &q_e); - for (k = 0; k < nw; k++) { - aux_beg = aux_end = 0; q_l = 1 + q_e - q_s; - thre = q_l*e_rate; thre = Adjust_Threshold(thre, q_l); - if(thre > THRESHOLD_MAX_SIZE) thre = THRESHOLD_MAX_SIZE; - ///offset of y - t_s = (q_s - z->x_pos_s) + z->y_pos_s; - t_s += y_start_offset(q_s, &(z->f_cigar)); - - aln_l = q_l + (thre<<1); t_tot_l = hpc_g?hpc_len(*hpc_g, z->y_id):uref->ug->u.a[z->y_id].len; - if(init_waln(thre, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) { - q_string = qstr+q_s; - t_string = return_str_seq_exz(tstr, t_s, t_pri_l, z->y_pos_strand, hpc_g, uref, z->y_id); - t_l = t_pri_l; - // t_end = Reserve_Banded_BPM(t_string, aln_l, q_string, q_l, thre, &error); - ed_band_cal_semi_64_w_absent_diag(t_string, t_l, q_string, q_l, thre, aux_beg, exz); - // if(z->y_id == 178 && q_s == 86800 && q_e == 86807) { - // fprintf(stderr, "\n[M::%s::semi::t_s->%ld::t_pri_l->%ld::aux_beg->%ld::aux_end->%ld::thre->%ld] exz->ps::%d, exz->pe::%d, exz->ts::%d, exz->te::%d, exz->err::%d, exz->cigar.n::%d\n", - // __func__, t_s, t_pri_l, aux_beg, aux_end, thre, exz->ps, exz->pe, exz->ts, exz->te, exz->err, (int32_t)exz->cigar.n); - // fprintf(stderr, "[tstr::len->%ld] %.*s\n", t_l, (int32_t)t_l, t_string); - // fprintf(stderr, "[qstr::len->%ld] %.*s\n", q_l, (int32_t)q_l, q_string); - // } - if (is_align(*exz)) { - // ed_band_cal_semi_64_w(t_string, aln_l, q_string, q_l, thre, exz); - // assert(exz->err <= exz->thre); - // fprintf(stderr, "[M::%s] exz->err::%d\n", __func__, exz->err); - ///t_s do not have aux_beg, while t_s + t_end (aka, te) has - if(!push_wlst_exz(uref, hpc_g, NULL, z, qstr, tstr, exz, THRESHOLD_MAX_SIZE, q_s, q_e, t_s, t_s + exz->pe, - t_tot_l, aux_beg, aux_end, e_rate, w_l, sec_check, ovlp_cut, force_aln, km)) { - return 0; - } - // append_window_list(z, q_s, q_e, t_s, t_s + t_end, error, aux_beg, aux_end, thre, w_l, km); - } - } - q_s = q_e + 1; q_e = q_s + w_l - 1; - if(q_e >= (int64_t)z->x_pos_e) q_e = z->x_pos_e; - } - - if((!force_aln) && (!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, 0, ovlp_cut, &e_rate)) && - (!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, sec_check, ovlp_cut, NULL))) return 0; - return 1; -} - - -uint32_t align_hc_ed_post_extz(overlap_region *z, All_reads *rref, char* qstr, char *tstr, bit_extz_t *exz, double e_rate, int64_t w_l, double ovlp_cut, int64_t force_aln, void *km) -{ - int64_t q_s, q_e, nw, k, q_l, t_l, t_tot_l, aux_beg, aux_end, t_s, thre, aln_l, t_pri_l; - char *q_string, *t_string; - z->w_list.n = 0; z->is_match = 0; z->align_length = 0; - nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, w_l); - get_win_se_by_normalize_xs(z, (z->x_pos_s/w_l)*w_l, w_l, &q_s, &q_e); - // if(z->x_id == 19350 && z->y_id == 19324) { - // fprintf(stderr, "-z-[M::%s] tid::%u(%c)\tq::[%u,%u)\tt::[%u,%u)\n", __func__, z->y_id, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1); - // } - for (k = 0; k < nw; k++) { - aux_beg = aux_end = 0; q_l = 1 + q_e - q_s; - thre = q_l*e_rate; thre = Adjust_Threshold(thre, q_l); - if(thre > THRESHOLD_MAX_SIZE) thre = THRESHOLD_MAX_SIZE; - ///offset of y - t_s = (q_s - z->x_pos_s) + z->y_pos_s; - t_s += y_start_offset(q_s, &(z->f_cigar)); - - aln_l = q_l + (thre<<1); t_tot_l = Get_READ_LENGTH((*rref), z->y_id); - if(init_waln(thre, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) { - q_string = qstr+q_s; - recover_UC_Read_sub_region(tstr, t_s, t_pri_l, z->y_pos_strand, rref, z->y_id); t_string = tstr; - // t_string = return_str_seq_exz(tstr, t_s, t_pri_l, z->y_pos_strand, hpc_g, uref, z->y_id); - - t_l = t_pri_l; - // t_end = Reserve_Banded_BPM(t_string, aln_l, q_string, q_l, thre, &error); - ed_band_cal_semi_64_w_absent_diag(t_string, t_l, q_string, q_l, thre, aux_beg, exz); - - // if(z->x_id == 5569 && z->y_id == 5557 && q_s == 10075 && q_e == 10849) { - // fprintf(stderr, "\n[M::%s::semi::t_s->%ld::t_pri_l->%ld::aux_beg->%ld::aux_end->%ld::thre->%ld] exz->ps::%d, exz->pe::%d, exz->ts::%d, exz->te::%d, exz->err::%d, exz->cigar.n::%d, thre::%ld\n", - // __func__, t_s, t_pri_l, aux_beg, aux_end, thre, exz->ps, exz->pe, exz->ts, exz->te, exz->err, (int32_t)exz->cigar.n, thre); - // fprintf(stderr, "[tstr::len->%ld] %.*s\n", t_l, (int32_t)t_l, t_string); - // fprintf(stderr, "[qstr::len->%ld] %.*s\n", q_l, (int32_t)q_l, q_string); - // } - if (is_align(*exz)) { - // ed_band_cal_semi_64_w(t_string, aln_l, q_string, q_l, thre, exz); - // assert(exz->err <= exz->thre); - // if(z->x_id == 19350 && z->y_id == 19324) { - // fprintf(stderr, "+[M::%s]\tq::[%ld,%ld)\tt::[%ld,%ld)\texz->err::%d\n", __func__, q_s, q_e + 1, t_s, t_s + exz->pe + 1, exz->err); - // } - ///t_s do not have aux_beg, while t_s + t_end (aka, te) has - if(!push_hc_wlst_exz(NULL, NULL, rref, z, qstr, tstr, exz, THRESHOLD_MAX_SIZE, q_s, q_e, t_s, t_s + exz->pe, - t_tot_l, aux_beg, aux_end, e_rate, w_l, ovlp_cut, force_aln, km)) { - return 0; - } - // append_window_list(z, q_s, q_e, t_s, t_s + t_end, error, aux_beg, aux_end, thre, w_l, km); - } - // else { - // if(z->x_id == 19350 && z->y_id == 19324) { - // fprintf(stderr, "-[M::%s]\tq::[%ld,%ld)\tt::[%ld,%ld)\texz->err::%d\n", __func__, q_s, q_e + 1, t_s, t_s + exz->pe + 1, exz->err); - // } - // } - } - q_s = q_e + 1; q_e = q_s + w_l - 1; - if(q_e >= (int64_t)z->x_pos_e) q_e = z->x_pos_e; - } - - // if((!force_aln) && (!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, 0, ovlp_cut, &e_rate)) && - // (!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, sec_check, ovlp_cut, NULL))) return 0; - if((!force_aln) && (!pass_qovlp(z->x_pos_e+1-z->x_pos_s, z->align_length, ovlp_cut))) return 0; - return 1; -} - -uint32_t align_hc_ed_post_non_retrieve_extz(overlap_region *z, char* qstr, int64_t ql, char *tstr, int64_t tl, bit_extz_t *exz, double e_rate, int64_t w_l, double ovlp_cut, int64_t force_aln, void *km) -{ - int64_t q_s, q_e, nw, k, q_l, t_l, aux_beg, aux_end, t_s, thre, aln_l, t_pri_l; - char *q_string, *t_string; - z->w_list.n = 0; z->is_match = 0; z->align_length = 0; - nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, w_l); - get_win_se_by_normalize_xs(z, (z->x_pos_s/w_l)*w_l, w_l, &q_s, &q_e); - for (k = 0; k < nw; k++) { - aux_beg = aux_end = 0; q_l = 1 + q_e - q_s; - thre = q_l*e_rate; thre = Adjust_Threshold(thre, q_l); - if(thre > THRESHOLD_MAX_SIZE) thre = THRESHOLD_MAX_SIZE; - ///offset of y - t_s = (q_s - z->x_pos_s) + z->y_pos_s; - t_s += y_start_offset(q_s, &(z->f_cigar)); - - aln_l = q_l + (thre<<1); - if(init_waln(thre, t_s, tl, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) { - q_string = qstr+q_s; t_string = tstr+t_s; t_l = t_pri_l; - - ed_band_cal_semi_64_w_absent_diag(t_string, t_l, q_string, q_l, thre, aux_beg, exz); - - // if(z->x_id == 5569 && z->y_id == 5557 && q_s == 10075 && q_e == 10849) { - // fprintf(stderr, "\n[M::%s::semi::t_s->%ld::t_pri_l->%ld::aux_beg->%ld::aux_end->%ld::thre->%ld] exz->ps::%d, exz->pe::%d, exz->ts::%d, exz->te::%d, exz->err::%d, exz->cigar.n::%d, thre::%ld\n", - // __func__, t_s, t_pri_l, aux_beg, aux_end, thre, exz->ps, exz->pe, exz->ts, exz->te, exz->err, (int32_t)exz->cigar.n, thre); - // fprintf(stderr, "[tstr::len->%ld] %.*s\n", t_l, (int32_t)t_l, t_string); - // fprintf(stderr, "[qstr::len->%ld] %.*s\n", q_l, (int32_t)q_l, q_string); - // } - if (is_align(*exz)) { - // ed_band_cal_semi_64_w(t_string, aln_l, q_string, q_l, thre, exz); - // assert(exz->err <= exz->thre); - // fprintf(stderr, "[M::%s] exz->err::%d\n", __func__, exz->err); - ///t_s do not have aux_beg, while t_s + t_end (aka, te) has - if(!push_hc_wlst_non_retrieve_exz(z, qstr, ql, tstr, tl, exz, THRESHOLD_MAX_SIZE, q_s, q_e, t_s, t_s + exz->pe, - aux_beg, aux_end, e_rate, w_l, ovlp_cut, force_aln, km)) { - return 0; - } - // append_window_list(z, q_s, q_e, t_s, t_s + t_end, error, aux_beg, aux_end, thre, w_l, km); - } - } - q_s = q_e + 1; q_e = q_s + w_l - 1; - if(q_e >= (int64_t)z->x_pos_e) q_e = z->x_pos_e; - } - - // if((!force_aln) && (!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, 0, ovlp_cut, &e_rate)) && - // (!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, sec_check, ovlp_cut, NULL))) return 0; - if((!force_aln) && (!pass_qovlp(z->x_pos_e+1-z->x_pos_s, z->align_length, ovlp_cut))) return 0; - return 1; -} - -inline uint32_t ed_cut(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, -char *qstr, char *tstr, uint32_t rev, uint32_t id, -int64_t qs, int64_t qe, int64_t t_s, int64_t block_s, double e_rate, int64_t max_err, -uint32_t aln_dir, int64_t* r_err, int64_t* qoff, int64_t* toff, int64_t* aln_qlen) -{ - (*aln_qlen) = 0; (*r_err) = INT32_MAX; - if(qoff) (*qoff) = -1; if(toff) (*toff) = -1; - int64_t ql, aln_l, t_tot_l, aux_beg, aux_end, t_pri_l, thres; - char *q_string, *t_string; unsigned int error; int t_end, q_end; - - ql = qe + 1 - qs; - ///there are two potiential reasons for unmatched window: - ///1. this window has a large number of differences - ///2. DP does not start from the right offset - if(rref) { - thres = double_error_threshold(get_init_err_thres(ql, e_rate, block_s, max_err), ql); - } else { - thres = double_ul_error_threshold(get_init_err_thres(ql, e_rate, block_s, max_err), ql); - } - - aln_l = ql + (thres << 1); - if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); - else if(uref) t_tot_l = uref->ug->u.a[id].len; - else t_tot_l = Get_READ_LENGTH((*rref), id); - - if(!init_waln(thres, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) return 0; - // if(t_pri_l + thres < ql) return 0; - - q_string = qstr + qs; - if(rref) { - fill_subregion(tstr, t_s, t_pri_l, rev, rref, id, aux_beg, aux_end); t_string = tstr; - } else { - t_string = return_str_seq(tstr, t_s, t_pri_l, rev, hpc_g, uref, id, aux_beg, aux_end); - } - - // if(id == 6) { - // fprintf(stderr, "-[M::%s::aln_dir->%u] qs->%ld, ts->%ld, thres->%ld, aux_beg->%ld, aux_end->%ld, t_pri_l->%ld\n", - // __func__, aln_dir, qs, t_s, thres, aux_beg, aux_end, t_pri_l); - // } - if(aln_dir == 0) { - Reserve_Banded_BPM_Extension(t_string, aln_l, q_string, ql, thres, &error, &t_end, &q_end); - } else { - Reserve_Banded_BPM_Extension_REV(t_string, aln_l, q_string, ql, thres, &error, &t_end, &q_end); - } - - if(t_end != -1 && q_end != -1) (*aln_qlen) = (aln_dir?(ql-q_end):(q_end+1)); - if(qoff) (*qoff) = q_end; if(toff) (*toff) = t_end; (*r_err) = error; - - if((*aln_qlen) == 0) return 0; - return 1; -} - -inline uint32_t ed_non_retrieve_cut(char *qstr, char *tstr, int64_t t_tot_l, uint32_t rev, uint32_t id, -int64_t qs, int64_t qe, int64_t t_s, int64_t block_s, double e_rate, int64_t max_err, -uint32_t aln_dir, int64_t* r_err, int64_t* qoff, int64_t* toff, int64_t* aln_qlen) -{ - (*aln_qlen) = 0; (*r_err) = INT32_MAX; - if(qoff) (*qoff) = -1; if(toff) (*toff) = -1; - int64_t ql, aln_l, aux_beg, aux_end, t_pri_l, thres; - char *q_string, *t_string; unsigned int error; int t_end, q_end; - - ql = qe + 1 - qs; - ///there are two potiential reasons for unmatched window: - ///1. this window has a large number of differences - ///2. DP does not start from the right offset - thres = double_error_threshold(get_init_err_thres(ql, e_rate, block_s, max_err), ql); - - aln_l = ql + (thres << 1); - - if(!init_waln(thres, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) return 0; - // if(t_pri_l + thres < ql) return 0; - - q_string = qstr + qs; t_string = tstr + t_s; - - // if(id == 6) { - // fprintf(stderr, "-[M::%s::aln_dir->%u] qs->%ld, ts->%ld, thres->%ld, aux_beg->%ld, aux_end->%ld, t_pri_l->%ld\n", - // __func__, aln_dir, qs, t_s, thres, aux_beg, aux_end, t_pri_l); - // } - if(aln_dir == 0) { - Reserve_Banded_BPM_Extension(t_string, aln_l, q_string, ql, thres, &error, &t_end, &q_end); - } else { - Reserve_Banded_BPM_Extension_REV(t_string, aln_l, q_string, ql, thres, &error, &t_end, &q_end); - } - - if(t_end != -1 && q_end != -1) (*aln_qlen) = (aln_dir?(ql-q_end):(q_end+1)); - if(qoff) (*qoff) = q_end; if(toff) (*toff) = t_end; (*r_err) = error; - - if((*aln_qlen) == 0) return 0; - return 1; -} - -int64_t gen_extend_err_0(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, -char *tstr, char *tstr_1, Correct_dumy* dumy, uint64_t *v_idx, int64_t block_s, double e_rate, -int64_t qs, int64_t qe, int64_t pk) -{ - int64_t tot_e = 0, ts, di[2], al[2], tb[2], an = z->w_list.n; double rr; - int64_t id = z->y_id, rev = z->y_pos_strand, ql = qe + 1 - qs; - ///check if there are some windows that cannot be algined by any overlaps/unitigs - ///if no, it is likely that the UL read itself has issues - if(uref && v_idx && z->is_match == 4) { - if(check_coverage_gap(v_idx, qs, qe, block_s)) { - tot_e += THRESHOLD_MAX_SIZE; return tot_e; - } - } - ts = (qs - z->x_pos_s) + z->y_pos_s; ts += y_start_offset(qs, &(z->f_cigar)); - - di[0] = di[1] = al[0] = al[1] = 0; tb[0] = tb[1] = -1; - if((pk > 0) && (qs == (z->w_list.a[pk].x_end + 1))) { - if(z->w_list.a[pk].clen == 0) {///do not have cigar - gen_backtrace_adv(&(z->w_list.a[pk]), z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, rev, id); - } - tb[0] = z->w_list.a[pk].y_end + 1; - } - - if(((pk+1) < an) && ((qe+1) == (z->w_list.a[pk+1].x_start))) { - if(z->w_list.a[pk+1].clen == 0) {///do not have cigar - gen_backtrace_adv(&(z->w_list.a[pk+1]), z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, rev, id); - } - tb[1] = z->w_list.a[pk+1].y_start-ql; - } - - if(tb[0] == -1 && tb[1] == -1) tb[0] = tb[1] = ts; - else if(tb[0] == -1 && tb[1] != -1) tb[0] = tb[1]; - else if(tb[1] == -1 && tb[0] != -1) tb[1] = tb[0]; - - if(tb[0] != -1) { - if(!ed_cut(uref, hpc_g, rref, qstr, tstr, rev, id, qs, qe, tb[0], block_s, e_rate, ((rref)?THRESHOLD:THRESHOLD_MAX_SIZE), - 0, &(di[0]), NULL, NULL, &(al[0]))) { - di[0] = ql; al[0] = 0; - } - } - - if(tb[1] != -1) { - if(!ed_cut(uref, hpc_g, rref, qstr, tstr, rev, id, qs, qe, tb[1], block_s, e_rate, ((rref)?THRESHOLD:THRESHOLD_MAX_SIZE), - 1, &(di[1]), NULL, NULL, &(al[1]))) { - di[1] = ql; al[1] = 0; - } - } - - if(al[0] && al[1]) {///matched in both sides - if((al[0] + al[1]) <= ql) { - tot_e += di[0] + di[1] + ql - (al[0] + al[1]); - } else { - rr = ((double)ql)/((double)(al[0] + al[1])); - tot_e += (di[0] + di[1])*rr; - } - } else if((!al[0]) && (!al[1])) {//failed - tot_e += ql; - } else if(al[0]) { - tot_e += di[0] + (ql - al[0]); - }else if(al[1]) { - tot_e += di[1] + (ql - al[1]); - } - // if(z->y_id == 6) { - // fprintf(stderr, "-[M::%s] qs->%ld, ts->%ld, tb[0]->%ld, tb[1]->%ld, di[0]->%ld, di[1]->%ld, al[0]->%ld, al[1]->%ld, block_s->%ld, e_rate->%f\n", __func__, - // qs, ts, tb[0], tb[1], di[0], di[1], al[0], al[1], block_s, e_rate); - // } - return tot_e; -} - - -int64_t gen_extend_err_0_exz(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, -char *tstr, bit_extz_t *exz, uint64_t *v_idx, int64_t block_s, double e_rate, int64_t max_err, -int64_t qs, int64_t qe, int64_t pk) -{ - int64_t tot_e = 0, ts, di[2], al[2], tb[2], an = z->w_list.n; double rr; - int64_t id = z->y_id, rev = z->y_pos_strand, ql = qe + 1 - qs; - ///check if there are some windows that cannot be algined by any overlaps/unitigs - ///if no, it is likely that the UL read itself has issues - if(uref && v_idx && z->is_match == 4) { - if(check_coverage_gap(v_idx, qs, qe, block_s)) { - tot_e += THRESHOLD_MAX_SIZE; return tot_e; - } - } - ts = (qs - z->x_pos_s) + z->y_pos_s; ts += y_start_offset(qs, &(z->f_cigar)); - - di[0] = di[1] = al[0] = al[1] = 0; tb[0] = tb[1] = -1; - if((pk > 0) && (qs == (z->w_list.a[pk].x_end + 1))) { - if(z->w_list.a[pk].clen == 0) {///do not have cigar - gen_backtrace_adv_exz(&(z->w_list.a[pk]), z, rref, hpc_g, uref, qstr, tstr, exz, rev, id); - } - tb[0] = z->w_list.a[pk].y_end + 1; - } - - if(((pk+1) < an) && ((qe+1) == (z->w_list.a[pk+1].x_start))) { - if(z->w_list.a[pk+1].clen == 0) {///do not have cigar - gen_backtrace_adv_exz(&(z->w_list.a[pk+1]), z, rref, hpc_g, uref, qstr, tstr, exz, rev, id); - } - tb[1] = z->w_list.a[pk+1].y_start-ql; - } - - if(tb[0] == -1 && tb[1] == -1) tb[0] = tb[1] = ts; - else if(tb[0] == -1 && tb[1] != -1) tb[0] = tb[1]; - else if(tb[1] == -1 && tb[0] != -1) tb[1] = tb[0]; - - if(tb[0] != -1) { - if(!ed_cut(uref, hpc_g, rref, qstr, tstr, rev, id, qs, qe, tb[0], block_s, e_rate, max_err, - 0, &(di[0]), NULL, NULL, &(al[0]))) { - di[0] = ql; al[0] = 0; - } - } - - if(tb[1] != -1) { - if(!ed_cut(uref, hpc_g, rref, qstr, tstr, rev, id, qs, qe, tb[1], block_s, e_rate, max_err, - 1, &(di[1]), NULL, NULL, &(al[1]))) { - di[1] = ql; al[1] = 0; - } - } - - if(al[0] && al[1]) {///matched in both sides - if((al[0] + al[1]) <= ql) { - tot_e += di[0] + di[1] + ql - (al[0] + al[1]); - } else { - rr = ((double)ql)/((double)(al[0] + al[1])); - tot_e += (di[0] + di[1])*rr; - } - } else if((!al[0]) && (!al[1])) {//failed - tot_e += ql; - } else if(al[0]) { - tot_e += di[0] + (ql - al[0]); - }else if(al[1]) { - tot_e += di[1] + (ql - al[1]); - } - // if(z->y_id == 6) { - // fprintf(stderr, "-[M::%s] qs->%ld, ts->%ld, tb[0]->%ld, tb[1]->%ld, di[0]->%ld, di[1]->%ld, al[0]->%ld, al[1]->%ld, block_s->%ld, e_rate->%f\n", __func__, - // qs, ts, tb[0], tb[1], di[0], di[1], al[0], al[1], block_s, e_rate); - // } - return tot_e; -} - -int64_t gen_extend_err_0_non_retrieve_exz(overlap_region *z, char* qstr, char *tstr, int64_t tl, bit_extz_t *exz, uint64_t *v_idx, int64_t block_s, double e_rate, int64_t max_err, int64_t qs, int64_t qe, int64_t pk) -{ - int64_t tot_e = 0, ts, di[2], al[2], tb[2], an = z->w_list.n; double rr; - int64_t id = z->y_id, rev = z->y_pos_strand, ql = qe + 1 - qs; - ///check if there are some windows that cannot be algined by any overlaps/unitigs - ///if no, it is likely that the UL read itself has issues - - ts = (qs - z->x_pos_s) + z->y_pos_s; ts += y_start_offset(qs, &(z->f_cigar)); - - di[0] = di[1] = al[0] = al[1] = 0; tb[0] = tb[1] = -1; - if((pk > 0) && (qs == (z->w_list.a[pk].x_end + 1))) { - if(z->w_list.a[pk].clen == 0) {///do not have cigar - gen_backtrace_non_retrieve_adv_exz(&(z->w_list.a[pk]), z, qstr, tstr, tl, exz, rev, id); - } - tb[0] = z->w_list.a[pk].y_end + 1; - } - - if(((pk+1) < an) && ((qe+1) == (z->w_list.a[pk+1].x_start))) { - if(z->w_list.a[pk+1].clen == 0) {///do not have cigar - gen_backtrace_non_retrieve_adv_exz(&(z->w_list.a[pk+1]), z, qstr, tstr, tl, exz, rev, id); - } - tb[1] = z->w_list.a[pk+1].y_start-ql; - } - - if(tb[0] == -1 && tb[1] == -1) tb[0] = tb[1] = ts; - else if(tb[0] == -1 && tb[1] != -1) tb[0] = tb[1]; - else if(tb[1] == -1 && tb[0] != -1) tb[1] = tb[0]; - - if(tb[0] != -1) { - if(!ed_non_retrieve_cut(qstr, tstr, tl, rev, id, qs, qe, tb[0], block_s, e_rate, max_err, - 0, &(di[0]), NULL, NULL, &(al[0]))) { - di[0] = ql; al[0] = 0; - } - } - - if(tb[1] != -1) { - if(!ed_non_retrieve_cut(qstr, tstr, tl, rev, id, qs, qe, tb[1], block_s, e_rate, max_err, - 1, &(di[1]), NULL, NULL, &(al[1]))) { - di[1] = ql; al[1] = 0; - } - } - - if(al[0] && al[1]) {///matched in both sides - if((al[0] + al[1]) <= ql) { - tot_e += di[0] + di[1] + ql - (al[0] + al[1]); - } else { - rr = ((double)ql)/((double)(al[0] + al[1])); - tot_e += (di[0] + di[1])*rr; - } - } else if((!al[0]) && (!al[1])) {//failed - tot_e += ql; - } else if(al[0]) { - tot_e += di[0] + (ql - al[0]); - }else if(al[1]) { - tot_e += di[1] + (ql - al[1]); - } - // if(z->y_id == 6) { - // fprintf(stderr, "-[M::%s] qs->%ld, ts->%ld, tb[0]->%ld, tb[1]->%ld, di[0]->%ld, di[1]->%ld, al[0]->%ld, al[1]->%ld, block_s->%ld, e_rate->%f\n", __func__, - // qs, ts, tb[0], tb[1], di[0], di[1], al[0], al[1], block_s, e_rate); - // } - return tot_e; -} - -double gen_extend_err(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, -char *tstr, char *tstr_1, Correct_dumy* dumy, uint64_t *v_idx, int64_t block_s, double ovlp_cut, double e_rate, double e_max, int64_t *r_e) -{ - int64_t ovl, k, ce, an = z->w_list.n, tot_l, tot_e, ws, we, ql; - ovl = z->x_pos_e+1-z->x_pos_s; if(r_e) (*r_e) = INT64_MAX; - if(!simi_pass(ovl, z->align_length, 0, ovlp_cut, &e_rate)) return DBL_MAX; - // nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); - for (k = 0; k < an; k++) { - if(z->w_list.a[k].clen) z->w_list.a[k].y_end -= z->w_list.a[k].extra_begin; - } - - tot_l = tot_e = 0; - for (k = an-1, ce = z->x_pos_e; k >= 0; k--) { - // assert(k == 0 || z->w_list.a[k].x_end > z->w_list.a[k-1].x_start);//sorted - tot_l += z->w_list.a[k].x_end + 1 - z->w_list.a[k].x_start; - tot_e += z->w_list.a[k].error;///matched window - - we = z->w_list.a[k].x_end; - while (we < ce) { - ws = we+1; - get_win_id_by_s(z, ws, block_s, &we); - ql = we+1-ws; tot_l += ql; - tot_e += gen_extend_err_0(z, uref, hpc_g, rref, qstr, tstr, tstr_1, dumy, v_idx, block_s, e_rate, ws, we, k); - if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; - } - ce = z->w_list.a[k].x_start-1; - if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; - } - - if(ce >= ((int64_t)z->x_pos_s)) { - we = ((int64_t)z->x_pos_s)-1; - while (we < ce) { - ws = we+1; - get_win_id_by_s(z, ws, block_s, &we); - ql = we+1-ws; tot_l += ql; - tot_e += gen_extend_err_0(z, uref, hpc_g, rref, qstr, tstr, tstr_1, dumy, v_idx, block_s, e_rate, ws, we, k); - if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; - } - } - - assert(tot_l == ovl); if(r_e) (*r_e) = tot_e; - return (double)(tot_e)/(double)(tot_l); -} - -double gen_extend_err_exz(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, -char *tstr, bit_extz_t *exz, uint64_t *v_idx, int64_t block_s, double ovlp_cut, double e_rate, double e_max, int64_t max_err, int64_t sec_check, int64_t *r_e) -{ - int64_t ovl, k, ce, an = z->w_list.n, tot_l, tot_e, ws, we, ql; - ovl = z->x_pos_e+1-z->x_pos_s; if(r_e) (*r_e) = INT64_MAX; - if((sec_check) && (!simi_pass(ovl, z->align_length, 0, ovlp_cut, &e_rate))) return DBL_MAX; - // nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); - // for (k = 0; k < an; k++) { - // if(z->w_list.a[k].clen) z->w_list.a[k].y_end -= z->w_list.a[k].extra_begin; - // } - - tot_l = tot_e = 0; - for (k = an-1, ce = z->x_pos_e; k >= 0; k--) { - // assert(k == 0 || z->w_list.a[k].x_end > z->w_list.a[k-1].x_start);//sorted - tot_l += z->w_list.a[k].x_end + 1 - z->w_list.a[k].x_start; - tot_e += z->w_list.a[k].error;///matched window - - we = z->w_list.a[k].x_end; - while (we < ce) { - ws = we+1; - get_win_id_by_s(z, ws, block_s, &we); - ql = we+1-ws; tot_l += ql; - tot_e += gen_extend_err_0_exz(z, uref, hpc_g, rref, qstr, tstr, exz, v_idx, block_s, e_rate, max_err, ws, we, k); - if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; - } - ce = z->w_list.a[k].x_start-1; - if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; - } - - if(ce >= ((int64_t)z->x_pos_s)) { - we = ((int64_t)z->x_pos_s)-1; - while (we < ce) { - ws = we+1; - get_win_id_by_s(z, ws, block_s, &we); - ql = we+1-ws; tot_l += ql; - tot_e += gen_extend_err_0_exz(z, uref, hpc_g, rref, qstr, tstr, exz, v_idx, block_s, e_rate, max_err, ws, we, k); - if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; - } - } - - assert(tot_l == ovl); if(r_e) (*r_e) = tot_e; - return (double)(tot_e)/(double)(tot_l); -} - -double gen_extend_err_non_retrieve_exz(overlap_region *z, char* qstr, char *tstr, int64_t tl, bit_extz_t *exz, uint64_t *v_idx, int64_t block_s, double ovlp_cut, double e_rate, double e_max, int64_t max_err, int64_t sec_check, int64_t *r_e) -{ - int64_t ovl, k, ce, an = z->w_list.n, tot_l, tot_e, ws, we, ql; - ovl = z->x_pos_e+1-z->x_pos_s; if(r_e) (*r_e) = INT64_MAX; - if((sec_check) && (!simi_pass(ovl, z->align_length, 0, ovlp_cut, &e_rate))) return DBL_MAX; - // nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); - // for (k = 0; k < an; k++) { - // if(z->w_list.a[k].clen) z->w_list.a[k].y_end -= z->w_list.a[k].extra_begin; - // } - - tot_l = tot_e = 0; - for (k = an-1, ce = z->x_pos_e; k >= 0; k--) { - // assert(k == 0 || z->w_list.a[k].x_end > z->w_list.a[k-1].x_start);//sorted - tot_l += z->w_list.a[k].x_end + 1 - z->w_list.a[k].x_start; - tot_e += z->w_list.a[k].error;///matched window - - we = z->w_list.a[k].x_end; - while (we < ce) { - ws = we+1; - get_win_id_by_s(z, ws, block_s, &we); - ql = we+1-ws; tot_l += ql; - tot_e += gen_extend_err_0_non_retrieve_exz(z, qstr, tstr, tl, exz, v_idx, block_s, e_rate, max_err, ws, we, k); - if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; - } - ce = z->w_list.a[k].x_start-1; - if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; - } - - if(ce >= ((int64_t)z->x_pos_s)) { - we = ((int64_t)z->x_pos_s)-1; - while (we < ce) { - ws = we+1; - get_win_id_by_s(z, ws, block_s, &we); - ql = we+1-ws; tot_l += ql; - tot_e += gen_extend_err_0_non_retrieve_exz(z, qstr, tstr, tl, exz, v_idx, block_s, e_rate, max_err, ws, we, k); - if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; - } - } - - assert(tot_l == ovl); if(r_e) (*r_e) = tot_e; - return (double)(tot_e)/(double)(tot_l); -} - - -void push_anchors(window_list *z, window_list_alloc *zidx, asg64_v *anchor, uint64_t *qhp, int64_t qhp_l, int64_t *qhp_k, uint32_t mcl) -{ - int64_t xi = 0, yi = 0, ci, cn = z->clen; uint8_t c = (uint8_t)-1; uint32_t cl = (uint32_t)-1; - for (ci = 0; ci < cn; ci++) { - get_cigar_cell(z, zidx, ci, &c, &cl); - if (c == 0) { //match - if(cl >= mcl) { - ; - ; - ; - ; - } - xi += cl; yi += cl; - } else if (c == 1) { - xi += cl; yi += cl; - } else if (c == 2) {///y has more bases than x - yi += cl; - } else if (c == 3) {///x has more bases than y - xi += cl; - } - } -} - -#define gen_hpc_max_len(x) ((x)+((x)>>1)+1) -///[off_s, off_e) -uint64_t extract_mm_hpc(char *in, int64_t len, int64_t off_s, int64_t off_e, int64_t w, uint64_t rev) -{ - int64_t i, o, l, trim, k, tl; uint64_t m, sf; uint8_t c; - ///forward - for (k = 1, trim = 0; k <= w; k++) { - m = 0; o = gen_hpc_max_len(k); sf = k<<1; - if(!rev) { - ///[off_s, off_e) - for (i = ((off_s>=o)?(off_s-o):(0)), l = 0; i < off_e; i++) { - c = seq_nt4_table[(uint8_t)in[i]]; - if((c < 4) && (((l >= k) && (((m>>sf)&3) == c)) || (l < k))) { - if(l < k) m = (m<<2) + c; - else sf = (sf?(sf):(k<<1))-2; - l++; - } else { - if(i > off_s) { - tl = i-off_s; - if((l >= o) && (trim < tl)) trim = tl; - l = -1; - break; - } - l = 0; sf = k<<1; - } - } - tl = i-off_s; - if((l!=-1) && (i > off_s) && (l >= o) && (trim < tl)) { - trim = tl; - if(trim >= (off_e-off_s)) break; - } - } else { - ///[off_s, off_e) - for (i = (((len-off_e)>=o)?(off_e+o):(len))-1, l = 0; i >= off_s; i--) { - c = seq_nt4_table[(uint8_t)in[i]]; - if((c < 4) && (((l >= k) && (((m>>sf)&3) == c)) || (l < k))) { - if(l < k) m = (m<<2) + c; - else sf = (sf?(sf):(k<<1))-2; - l++; - } else { - if(i+1 < off_e) { - tl = off_e-i-1; - if((l >= o) && (trim < tl)) trim = tl; - l = -1; - break; - } - l = 0; sf = k<<1; - } - } - tl = off_e-i-1; - if((l!=-1) && (i+1 < off_e) && (l >= o) && (trim < tl)) { - trim = tl; - if(trim >= (off_e-off_s)) break; - } - } - } - return trim; -} - -uint64_t trim_hpc(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, char *tstr, int64_t hpc_max, -int64_t ql, int64_t tl, int64_t tid, int64_t trev, int64_t *rqs, int64_t *rqe, int64_t *rts, int64_t *rte) -{ - ///[qs, qe); [ts, te) - int64_t qs = *rqs, qe = *rqe, ts = *rts, te = *rte, trim[2], hl, aux_l, subl = qe-qs; char *ss; - if(hpc_max > 32) hpc_max = 32; trim[0] = trim[1] = 0; aux_l = gen_hpc_max_len(hpc_max); - - qs -= aux_l; if(qs < 0) qs = 0; - qe += aux_l; if(qe > ql) qe = ql; - ss = qstr + qs; - hl = extract_mm_hpc(ss, qe - qs, (*rqs)-qs, (*rqe)-qs, hpc_max, 0); - if(hl >= subl) return 0; trim[0] = hl; - hl = extract_mm_hpc(ss, qe - qs, (*rqs)-qs, (*rqe)-qs, hpc_max, 1); - if(hl >= subl) return 0; trim[1] = hl; - if(trim[0] + trim[1] >= subl) return 0; - - ts -= aux_l; if(ts < 0) ts = 0; - te += aux_l; if(te > tl) te = tl; - if(rref) { - fill_subregion(tstr, ts, te-ts, trev, rref, tid, 0, 0); ss = tstr; - } else { - ss = return_str_seq(tstr, ts, te-ts, trev, hpc_g, uref, tid, 0, 0); - } - hl = extract_mm_hpc(ss, te - ts, (*rts)-ts, (*rte)-ts, hpc_max, 0); - if(hl >= subl) return 0; if(hl > trim[0]) trim[0] = hl; - hl = extract_mm_hpc(ss, te - ts, (*rts)-ts, (*rte)-ts, hpc_max, 1); - if(hl >= subl) return 0; if(hl > trim[1]) trim[1] = hl; - if(trim[0] + trim[1] >= subl) return 0; - - (*rqs) += trim[0]; (*rts) += trim[0]; - (*rqe) -= trim[1]; (*rte) -= trim[1]; - return 1; -} - -#define cl_pushp(type, v, p) do { \ - if ((v).length == (v).size) { \ - (v).size = (v).size? (v).size<<1 : 2; \ - (v).list = (type*)realloc((v).list, sizeof(type) * (v).size); \ - } \ - *(p) = &(v).list[(v).length++]; \ - } while (0) - -///ai is the suffix of aj -int64_t inline traceback_sc(const k_mer_hit *ai, const k_mer_hit *aj) -{ - int64_t qsi = ai->self_offset-ai->cnt, qej = aj->self_offset; - int64_t tsi = ai->offset-ai->cnt, tej = aj->offset; - if(qsi >= qej && tsi >= tej) return ai->cnt; - return INT32_MIN; -} - -void split_long_anchors(Candidates_list *ac, int64_t block, int64_t block_n) -{ - int64_t i, m, an = ac->length; - if(block_n < 0) { - for (i = block_n = 0; i < an; i++) { - if(ac->list[i].cnt <= block) block_n++; - else block_n += (ac->list[i].cnt/block) + (((ac->list[i].cnt%block) > 0)?1:0); - } - } - if(block_n <= an) return; - if(block_n > ac->size) { - ac->size = block_n; REALLOC(ac->list, ac->size); - } - for (i = an-1, m = block_n-1; i >= 0; i--) { - if(ac->list[i].cnt <= block) { - ac->list[m--] = ac->list[i]; - } else { - while (ac->list[i].cnt > 0) { - ac->list[m] = ac->list[i]; - if(ac->list[i].cnt >= block) { - ac->list[m].cnt = block; - ac->list[i].cnt -= block; - ac->list[i].self_offset -= block; - ac->list[i].offset -= block; - } else { - ac->list[i].cnt = 0; - } - m--; - } - } - } - ac->length = block_n; assert(m == -1); -} - -int64_t gen_affine_traceback_dp(Candidates_list *ac, int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t block, int64_t block_n) -{ - if(ac->length < 1) return 0; - int64_t i, j, *p, *t, max_f, n_skip, max_j, end_j, st, max_ii, sc, max, tmp, msc_i, msc; - int32_t *f, cL; k_mer_hit* a = ac->list; int64_t a_n = ac->length; Chain_Data* dp; - - for (i = 1; i < a_n; ++i) { - sc = traceback_sc(&a[i], &a[i-1]); - if(sc == INT32_MIN) break; - } - if(i >= a_n) return a_n; - - split_long_anchors(ac, block, block_n); - a = ac->list; a_n = ac->length; dp = &(ac->chainDP); - - resize_Chain_Data(dp, a_n, NULL); t = dp->tmp; f = dp->score; p = dp->pre; - t[0] = 0; p[0] = -1; f[0] = a[0].cnt; - msc_i = msc = -1; i = 0; - - memset(t, 0, (a_n*sizeof((*t)))); - for (i = st = 0, max_ii = -1; i < a_n; ++i) { - max_f = a[i].cnt; n_skip = 0; max_j = end_j = -1; - if ((i-st) > max_iter) st = i-max_iter; - - for (j = i - 1; j >= st; --j) { - sc = traceback_sc(&a[i], &a[j]); - if(sc == INT32_MIN) break; - sc += f[j]; - if (sc > max_f) { - max_f = sc, max_j = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == (int32_t)i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - end_j = j; - - if (max_ii < 0 || ((int64_t)a[i].offset) - ((int64_t)a[max_ii].offset) > max_dis) { - max = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && ((((int64_t)a[i].offset)-((int64_t)a[j].offset))<=max_dis); --j) { - if (max < f[j]) { - max = f[j], max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - tmp = traceback_sc(&a[i], &a[max_ii]); - if (tmp != INT32_MIN && max_f < tmp + f[max_ii]) - max_f = tmp + f[max_ii], max_j = max_ii; - } - f[i] = max_f; p[i] = max_j; - if ((max_ii < 0) || (((((int64_t)a[i].offset)-((int64_t)a[max_ii].offset))<=max_dis) && (f[max_ii] msc) { - msc = f[i]; msc_i = i; - } - } - - cL = 0; i = msc_i; - while (i >= 0) { - t[cL++] = i; i = p[i]; - } - for (i = 0; i < cL; i++) a[i] = a[t[cL-i-1]]; - return cL; -} - -uint64_t gen_affine_traceback(overlap_region *o, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, char *tstr, uint64_t ql, -uint64_t *qhp, uint64_t qhp_l, Candidates_list *ac, uint32_t hpc_max, uint32_t min_ach, uint32_t block) -{ - if(o->w_list.n <= 0) return 0; - int64_t nw = o->w_list.n, snw, k, t, qi, ti, ci, p_qi, p_ti, cn, qs, qe, ts, te, tl; - window_list *z; uint8_t c; uint32_t cl, pcl, id = o->y_id, rev = o->y_pos_strand; k_mer_hit *p; - uint64_t hm, aocc = 0, bocc = 0; qi = ti = 0; p_qi = p_ti = INT32_MIN; pcl = 0; - clear_Candidates_list(ac); - if(o->w_list.n > (uint64_t)ac->size) { - ac->size = o->w_list.n; REALLOC(ac->list, ac->size); - } - - if(hpc_g) tl = hpc_len(*hpc_g, id); - else if(uref) tl = uref->ug->u.a[id].len; - else tl = Get_READ_LENGTH((*rref), id); - for (k = 0; k < nw; k++) { - z = &(o->w_list.a[k]); ci = 0; cn = z->clen; - qi = z->x_start; ti = z->y_start; - for (ci = 0; ci < cn; ci++) { - get_cigar_cell(z, &(o->w_list), ci, &c, &cl); - if (c == 0) { //match - if((p_qi == qi) && (p_ti == ti)) { - pcl += cl; - } else { - ///push - if(pcl > 0) { - hm = 0; qs = qi - pcl; qe = qi; ts = ti - pcl; te = ti; - if(pcl > min_ach) hm = trim_hpc(uref, hpc_g, rref, qstr, tstr, hpc_max, ql, tl, id, rev, &qs, &qe, &ts, &te); - if(hm) aocc++; - if(hm || aocc == 0) { - cl_pushp(k_mer_hit, *ac, &p); - p->readID = p->strand = !!hm; - p->cnt = qe - qs; p->self_offset = qe; p->offset = te; - if(p->cnt > min_ach) bocc++; - } - } - ///push - pcl = 0; - } - qi += cl; ti += cl; - p_qi = qi; p_ti = ti; - } else { - ///push - if(pcl > 0) { - hm = 0; qs = qi - pcl; qe = qi; ts = ti - pcl; te = ti; - if(pcl > min_ach) hm = trim_hpc(uref, hpc_g, rref, qstr, tstr, hpc_max, ql, tl, id, rev, &qs, &qe, &ts, &te); - if(hm) aocc++; - if(hm || aocc == 0) { - cl_pushp(k_mer_hit, *ac, &p); - p->readID = p->strand = !!hm; - p->cnt = qe - qs; p->self_offset = qe; p->offset = te; - if(p->cnt > min_ach) bocc++; - } - } - pcl = 0; - ///push - if (c == 1) { - qi += cl; ti += cl; - } if (c == 2) {///t has more bases than p - ti += cl; - } if (c == 3) {///p has more bases than t - qi += cl; - } - } - } - } - - ///push - if(pcl > 0) { - hm = 0; qs = qi - pcl; qe = qi; ts = ti - pcl; te = ti; - if(pcl > min_ach) hm = trim_hpc(uref, hpc_g, rref, qstr, tstr, hpc_max, ql, tl, id, rev, &qs, &qe, &ts, &te); - if(hm) aocc++; - if(hm || aocc == 0) { - cl_pushp(k_mer_hit, *ac, &p); - p->readID = p->strand = !!hm; - p->cnt = qe - qs; p->self_offset = qe; p->offset = te; - if(p->cnt > min_ach) bocc++; - } - } - ///push - - nw = ac->length; snw = -1; - if(aocc > 0) { - if(aocc < (uint64_t)ac->length) { - for (k = t = snw = 0; k < nw; k++) { - if(ac->list[k].readID) { - ac->list[t] = ac->list[k]; - if(ac->list[t].cnt <= block) snw++; - else snw += (ac->list[t].cnt/block) + (((ac->list[t].cnt%block) > 0)?1:0); - t++; - } - } - ac->length = t; - } - } else if (bocc > 0) { - if(bocc < (uint64_t)ac->length) { - for (k = t = snw = 0; k < nw; k++) { - if(ac->list[k].cnt > min_ach) { - ac->list[t] = ac->list[k]; - if(ac->list[t].cnt <= block) snw++; - else snw += (ac->list[t].cnt/block) + (((ac->list[t].cnt%block) > 0)?1:0); - t++; - } - } - ac->length = t; - } - } - nw = ac->length; - gen_affine_traceback_dp(ac, 25, 5000, 5000, block, snw); - return 1; -} - - -void align_ul_ed(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, char* qstr, char *tstr, double e_rate, int64_t w_l, void *km) -{ - int64_t q_s, q_e, nw, k, q_l, t_tot_l; - int64_t aux_beg, aux_end, t_s, thre, aln_l, t_pri_l, t_end; - char *q_string, *t_string; unsigned int error; - z->w_list.n = 0; z->is_match = 0; - nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, w_l); - get_win_se_by_normalize_xs(z, (z->x_pos_s/w_l)*w_l, w_l, &q_s, &q_e); - for (k = 0; k < nw; k++) { - aux_beg = aux_end = 0; q_l = 1 + q_e - q_s; - thre = q_l*e_rate; thre = Adjust_Threshold(thre, q_l); - if(thre > THRESHOLD_MAX_SIZE) thre = THRESHOLD_MAX_SIZE; - ///offset of y - t_s = (q_s - z->x_pos_s) + z->y_pos_s; - t_s += y_start_offset(q_s, &(z->f_cigar)); - - aln_l = q_l + (thre<<1); t_tot_l = hpc_g?hpc_len(*hpc_g, z->y_id):uref->ug->u.a[z->y_id].len; - if(init_waln(thre, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) { - q_string = qstr+q_s; - t_string = return_str_seq(tstr, t_s, t_pri_l, z->y_pos_strand, hpc_g, uref, z->y_id, aux_beg, aux_end); - - t_end = Reserve_Banded_BPM(t_string, aln_l, q_string, q_l, thre, &error); - if (error!=((unsigned int)-1)) { - z->align_length += q_l; - ///t_s do not have aux_beg, while t_s + t_end (aka, te) has - append_window_list(z, q_s, q_e, t_s, t_s + t_end, error, aux_beg, aux_end, thre, w_l, km); - } - } - q_s = q_e + 1; q_e = q_s + w_l - 1; - if(q_e >= (int64_t)z->x_pos_e) q_e = z->x_pos_e; - } - - assert(q_e == (int64_t)z->x_pos_e); -} - -uint64_t realign_ed(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, -char *tstr, char *tstr_1, Correct_dumy* dumy, kvec_t_u64_warp* v_idx, int64_t block_s, double e_rate, -double *e_rate_final, uint32_t sec_check, double ovlp_cut, int64_t *is_sort) -{ - int64_t i, k, nw, a_nw, w_id, y_id, y_strand, real_y_start, x_start, x_end, x_len, ce, cs; - int64_t w_s, w_e, mm_we, mm_ws, mm_aln, ovl, y_readLen, total_y_start, total_y_end; - uint64_t *w_idx = NULL, srt = 1; window_list *p = NULL; if(sec_check && (!uref)) sec_check = 0; - z->is_match = 0; if(is_sort) (*is_sort) = 1; - if(z->w_list.n == 0) return 0; - nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); a_nw = z->w_list.n; - y_id = z->y_id; y_strand = z->y_pos_strand; - ovl = z->x_pos_e+1-z->x_pos_s; mm_ws = mm_we = z->x_pos_s; mm_aln = 0; - - if(hpc_g) y_readLen = hpc_len(*hpc_g, y_id); - else if(uref) y_readLen = uref->ug->u.a[y_id].len; - else y_readLen = Get_READ_LENGTH((*rref), y_id); - - for (i = a_nw-1, ce = z->x_pos_e; i >= 0; i--) { //utilize the the end pos of pre-window in forward - w_e = mm_we = z->w_list.a[i].x_end; - total_y_start = z->w_list.a[i].y_end + 1 - z->w_list.a[i].extra_begin; - while ((w_e < ce) && (total_y_start < y_readLen)) { - w_s = w_e + 1; - w_id = get_win_id_by_s(z, w_s, block_s, &w_e); - x_start = w_s; x_end = w_e; - if(aln_wlst_adv(z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, - y_strand, y_id, x_start, x_end, total_y_start, block_s, e_rate, 0)) { - p = &(z->w_list.a[z->w_list.n-1]); - mm_we = x_end; - } else { - break; - } - total_y_start = p->y_end + 1 - p->extra_begin; - } - ce = z->w_list.a[i].x_start-1; - if(i == a_nw-1) {///only possiblity with the largest end pos - mm_aln = mm_we+1-mm_ws; - if(!simi_pass(ovl, mm_aln, sec_check, ovlp_cut, NULL)) break; - } - } - - if(z->w_list.a[a_nw-1].x_end > z->w_list.a[z->w_list.n-1].x_end) { - srt = 0; if(is_sort) (*is_sort) = 0; - } - if(i >= 0) return 0; - if((!srt) && (z->w_list.n <= (nw*0.2))) {///if very few windows are mapped - radix_sort_window_list_xs_srt(z->w_list.a, z->w_list.a + z->w_list.n); - srt = 1; if(is_sort) (*is_sort) = 1; - } - if(!srt) {///need sort - a_nw = z->w_list.n; - kv_resize(uint64_t, v_idx->a, (uint64_t)nw); w_idx = v_idx->a.a; - memset(v_idx->a.a, -1, sizeof((*v_idx->a.a))*nw); - for (i = 0; i < a_nw; i++) { ///w_idx[] == (uint64_t) if unmatched - assert(z->w_list.a[i].y_end != -1); - w_id = get_win_id_by_s(z, z->w_list.a[i].x_start, block_s, NULL); - w_idx[w_id] = i; - } - ///deal with first window - mm_ws = z->x_pos_s; - if(w_idx[0] != (uint64_t)-1) { - w_s = z->w_list.a[w_idx[0]].x_start; mm_aln -= (w_s-mm_ws); - mm_ws = z->w_list.a[w_idx[0]].x_end+1; - } - for (i = 1; i < nw; i++) { //utilize the the start pos of next window in backward - ///find the first matched window, which should not be the first window - ///the pre-window of this matched window must be unmatched - if(w_idx[i] != (uint64_t)-1 && w_idx[i-1] == (uint64_t)-1) { - w_s = z->w_list.a[w_idx[i]].x_start; mm_aln -= (w_s-mm_ws); - ///check if the start pos of this matched window has been calculated - if(z->w_list.a[w_idx[i]].clen == 0) { - p = &(z->w_list.a[w_idx[i]]); - gen_backtrace_adv(p, z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, y_strand, y_id); - assert(p->error != -1); - p->y_end += p->extra_begin; - } - real_y_start = p->y_start; - - ///the end pos for pre window is real_y_start - 1 - total_y_end = real_y_start - 1; - ///find the unmatched window on the left of current matched window - ///k starts from i - 1 - for (k = i - 1; k >= 0 && w_idx[k] == (uint64_t)-1 && total_y_end > 0; k--) { - w_e = w_s - 1; - w_id = get_win_id_by_e(z, w_e, block_s, &w_s); - assert(w_id == k); - x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; - if(aln_wlst_adv(z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, - y_strand, y_id, x_start, x_end, total_y_end+1-x_len, block_s, e_rate, 1)) { - p = &(z->w_list.a[z->w_list.n-1]); - p->y_start -= p->extra_begin; ///y_start has no shift, but y_end has shift - w_idx[k] = z->w_list.n - 1; - mm_aln += x_len; - // if(is_sort && (*is_sort) && z->w_list.n > 1 && p->x_start < z->w_list.a[z->w_list.n-2].x_start) (*is_sort) = 0; - } else { - break; - } - total_y_end = p->y_start - 1; - } - if(!simi_pass(ovl, mm_aln, sec_check, ovlp_cut, NULL)) break; - } - if(w_idx[i] != (uint64_t)-1) mm_ws = z->w_list.a[w_idx[i]].x_end+1; - } - if(i < nw) return 0; - } else {//sorted - a_nw = z->w_list.n; mm_ws = z->x_pos_s; - for (i = 0, cs = z->x_pos_s; i < a_nw; i++) { - p = &(z->w_list.a[i]); - w_s = p->x_start; mm_aln -= (w_s-mm_ws); - ///check if the start pos of this matched window has been calculated - if((w_s > cs) && (p->clen == 0)) { - gen_backtrace_adv(p, z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, y_strand, y_id); - assert(p->error != -1); - p->y_end += p->extra_begin; - } - real_y_start = p->y_start; - ///the end pos for pre window is real_y_start - 1 - total_y_end = real_y_start - 1; - while ((w_s > cs) && (total_y_end > 0)) { - w_e = w_s - 1; - w_id = get_win_id_by_e(z, w_e, block_s, &w_s); - x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; - if(aln_wlst_adv(z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, - y_strand, y_id, x_start, x_end, total_y_end+1-x_len, block_s, e_rate, 1)) { - p = &(z->w_list.a[z->w_list.n-1]); - p->y_start -= p->extra_begin; ///y_start has no shift, but y_end has shift - mm_aln += x_len; - // if(is_sort && (*is_sort) && z->w_list.n > 1 && p->x_start < z->w_list.a[z->w_list.n-2].x_start) (*is_sort) = 0; - } else { - break; - } - total_y_end = p->y_start - 1; - } - if(!simi_pass(ovl, mm_aln, sec_check, ovlp_cut, NULL)) break; - mm_ws = cs = z->w_list.a[i].x_end+1; - } - if(a_nw < (int64_t)z->w_list.n) { - srt = 0; if(is_sort) (*is_sort) = 0; - } - if(i < a_nw) return 0; - } - - if(e_rate_final) { - /** - if(simi_pass(ovl, z->align_length, 0, &e_rate)) { - a_nw = z->w_list.n; - for (i = 0; i < a_nw; i++) { - p = &(z->w_list.a[i]); - ///check if the cigar of this window has been got - if(p->clen == 0) { - gen_backtrace_adv(p, z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, y_strand, y_id); - assert(p->error != -1); - } else { - p->y_end -= p->extra_begin; - } - } - if(!srt) radix_sort_window_list_xs_srt(z->w_list.a, z->w_list.a + z->w_list.n); - ///note: this function will change tstr/qstr - error_rate = non_trim_error_rate(z, rref, uref, v_idx, dumy, g_read, e_rate, block_s); - z->is_match = 0;///must be here; - - if (error_rate <= e_rate_final) { - overlap_list->mapped_overlaps_length += ovl; - z->is_match = 1; append_unmatched_wins(z, block_s); - if(rref) { - calculate_boundary_cigars(z, rref, dumy, g_read, e_rate); - } else { - calculate_ul_boundary_cigars(z, uref, dumy, g_read, e_rate, block_s); - } - // assert(get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s)==(int64_t)z->w_list.n); - // assert((int64_t)z->x_pos_s==z->w_list.a[0].x_start && - // (int64_t)z->x_pos_e==z->w_list.a[z->w_list.n-1].x_end); - } else if (error_rate <= e_rate_final * 1.5) { - z->is_match = 3; - } - } - **/ - return 1; - } else { - return 1; - } - return 0; -} - -uint64_t col_errors(overlap_region *z) -{ - uint64_t i, e = 0; - for (i = 0; i < z->w_list.n; i++) e += z->w_list.a[i].error; - return e; -} - - -void ul_lalign_hpc(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, char *qstr, - uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, - haplotype_evdience_alloc* hap, kvec_t_u64_warp* v_idx, kvec_t_u32_warp* q_idx, - double e_rate, double eh_rate, int64_t wl, void *km) -{ - uint64_t i, qhl, bs, k, ovl, whl; Window_Pool w; double err; overlap_region t; overlap_region *z; - whl = MIN((((double)THRESHOLD_MAX_SIZE)/eh_rate), WINDOW); - ol->mapped_overlaps_length = 0; - if(ol->length <= 0) return; - - ///hpc alignment - ///init hpc seq - qhl = update_ol_track(ol, cl, uref->hpc_g, uref, 1, ql, qstr, q_idx); - gen_hpc_str(qstr, ql, qu, &qhl); - ///verify hpc seq - clear_Correct_dumy(dumy, ol, km); err = eh_rate; - init_Window_Pool(&w, qhl, whl, (int)(1.0/err)); - bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; - resize_UC_Read(tu, bs<<1); - for (i = k = 0; i < ol->length; i++) { - if(!align_ul_ed_post(&(ol->list[i]), uref, uref->hpc_g, qu->seq, tu->seq, tu->seq+bs, dumy, err, w.window_length, OVERLAP_THRESHOLD_FILTER_HPC, km)) { - continue; - } - // fprintf(stderr, "+++[M::%s] yid::%u, x::[%u, %u), y::[%u, %u), aln::%u, err::%lu\n", __func__, ol->list[i].y_id, - // ol->list[i].x_pos_s, ol->list[i].x_pos_e+1, ol->list[i].y_pos_s, ol->list[i].y_pos_e+1, - // ol->list[i].align_length, col_errors(&(ol->list[i]))); - if(k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - k++; - } - ol->length = k; - if(ol->length <= 0) return; - - - ///base alignment - update_ol_track(ol, cl, NULL, uref, 1, ql, NULL, NULL); - resize_UC_Read(qu, ql); qu->length = ql; memcpy(qu->seq, qstr, ql); - clear_Correct_dumy(dumy, ol, km); err = e_rate; - init_Window_Pool(&w, ql, wl, (int)(1.0/err)); - bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; - resize_UC_Read(tu, bs<<1); - for (i = 0; i < ol->length; i++) { - z = &(ol->list[i]); ovl = z->x_pos_e+1-z->x_pos_s; - if(!align_ul_ed_post(z, uref, NULL, qu->seq, tu->seq, tu->seq+bs, dumy, err, w.window_length, -1, km)) { - continue; - } - // fprintf(stderr, "---[M::%s] yid::%u, x::[%u, %u), y::[%u, %u), aln::%u, err::%lu\n", __func__, ol->list[i].y_id, - // ol->list[i].x_pos_s, ol->list[i].x_pos_e+1, ol->list[i].y_pos_s, ol->list[i].y_pos_e+1, - // ol->list[i].align_length, col_errors(&(ol->list[i]))); - if(uref && simi_pass(ovl, z->align_length, uref?1:0, -1, NULL)) { - z->is_match = 3; ol->mapped_overlaps_length += z->align_length; - } - } - - if(uref && ol->mapped_overlaps_length > 0) { - set_herror_win(ol, dumy, v_idx, err, ql, w.window_length); - } - - double e_max = err*1.5, rr; - for (i = k = 0; i < ol->length; i++) { - z = &(ol->list[i]); ovl = z->x_pos_e + 1 - z->x_pos_s; - rr = gen_extend_err(z, uref, NULL, NULL, qu->seq, tu->seq, tu->seq+bs, - dumy, v_idx?v_idx->a.a:NULL, w.window_length, -1, err, (e_max+0.000001), NULL); - z->is_match = 0;///must be here; - if (rr <= err) { - for (k = 0; k < z->w_list.n; k++) { - if(z->w_list.a[k].clen) continue; - gen_backtrace_adv(&(z->w_list.a[k]), z, NULL, NULL, uref, qu->seq, tu->seq, tu->seq+bs, - dumy, z->y_pos_strand, z->y_id); - } - - ol->mapped_overlaps_length += ovl; k++; - z->is_match = 1; append_unmatched_wins(z, w.window_length); - calculate_ul_boundary_cigars(z, uref, dumy, qu, err, w.window_length); - } else if (rr <= e_max) { - z->is_match = 3; - } - } - - partition_ul_overlaps_advance(ol, uref, qu, tu, dumy, hap, 1, err, w.window_length, km); - - // recalcate_window(overlap_list, R_INF, g_read, dumy, overlap_read); - // partition_overlaps(overlap_list, R_INF, g_read, dumy, hap, force_repeat); - // recalcate_window_ul_advance(overlap_list, uref, g_read, dumy, overlap_read, max_ov_diff_ec, w_inf.window_length, km); - // recalcate_window_advance(overlap_list, NULL, uref, g_read, dumy, overlap_read, v_idx, w_inf.window_length, max_ov_diff_ec, max_ov_diff_ec); - /** - refine_ed_aln(overlap_list, NULL, uref, g_read, dumy, overlap_read, v_idx, w_inf.window_length, max_ov_diff_ec, max_ov_diff_ec); - **/ - // fprintf(stderr, "[M::%s-beg] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, - // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); - ///after this function, overlap_list is sorted by x_pos_e; used for g_chain - /** - partition_ul_overlaps_advance(overlap_list, uref, g_read, overlap_read, dumy, hap, force_repeat, max_ov_diff_ec, w_inf.window_length, km); - **/ - // print_ovlp_occ_stat(overlap_list, g_read->length, 1); - // print_ovlp_occ_stat(overlap_list, g_read->length, 2); - // fprintf(stderr, "[M::%s-end] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, - // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); - // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1176); - // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1167); - // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1170); - /** - - - if(is_consensus) - { - generate_consensus(overlap_list, R_INF, g_read, dumy, g, DAGCon, current_cigar, second_round); - } - - - (*fully_cov) = check_if_fully_covered(overlap_list, R_INF, g_read, dumy, g, abnormal); - **/ -} - -// void ul_phase(overlap_region *oa, int64_t on, uint64_t *idx, uint64_t *buf) -// { -// int64_t i, oi; overlap_region *z; -// for (i = 0; i < on; i++) { -// oi = (uint32_t)idx[i]; z = &(oa[oi]); -// if(z->is_match != 1) continue; -// } -// } - -inline uint32_t cigar_check_dbg(char *pstr, char *tstr, bit_extz_t *ez) -{ - int32_t pi = ez->ps, ti = ez->ts, err = 0; uint32_t ci = 0, cl, k; uint16_t c; - while (ci < ez->cigar.n) { - ci = pop_trace(&(ez->cigar), ci, &c, &cl); - // fprintf(stderr, "# %u = %u, cigar_n::%u\n", c, cl, (uint32_t)ez->cigar.n); - if(c == 0) { - for (k=0;(kerr) { - fprintf(stderr, "ERROR-err, err::%d, ez->err::%d\n", err, ez->err); - return 0; - } - return 1; -} - -int64_t wcigar_check(window_list *p, window_list_alloc *z, char *qstr, char *tstr) -{ - bit_extz_t ez; - ez.cigar.a = z->c.a+p->cidx; ez.cigar.n = ez.cigar.m = p->clen; - ez.ps = p->y_start; ez.pe = p->y_end; - ez.ts = p->x_start; ez.te = p->x_end; - ez.err = p->error; - // prt_cigar(ez.cigar.a, ez.cigar.n); - return cigar_check_dbg(tstr, qstr, &ez); -} - -void verify_aln(int32_t sid, overlap_region *z, UC_Read* qu, UC_Read* tu, All_reads *rref, hpc_t *hpc_g, const ul_idx_t *uref) -{ - uint64_t tl, tid = z->y_id, rev = z->y_pos_strand, i; char *tstr, *qstr; window_list *p; - if(hpc_g) tl = hpc_len(*hpc_g, tid); - else if(uref) tl = uref->ug->u.a[tid].len; - else tl = Get_READ_LENGTH((*rref), tid); - - qstr = qu->seq; resize_UC_Read(tu, tl); - if(rref) { - recover_UC_Read_sub_region(tu->seq, 0, tl, rev, rref, tid); tstr = tu->seq; - } else { - tstr = return_str_seq_exz(tu->seq, 0, tl, rev, hpc_g, uref, tid); - } - - for (i = 0; i < z->w_list.n; i++) { - p = &(z->w_list.a[i]); - if(p->y_end == -1) continue; - if(!wcigar_check(p, &(z->w_list), qstr, tstr)) break; - } - if(i < z->w_list.n) { - fprintf(stderr, "sid::%d, tid::%lu, i::%lu, qs::%d, qe::%d, ts::%d, te::%d, err::%d\n", sid, tid, i, - p->x_start, p->x_end, p->y_start, p->y_end, p->error); - prt_cigar(z->w_list.c.a+p->cidx, p->clen); - fprintf(stderr, "[tstr::[%u, %u]] %.*s\n", z->y_pos_s, z->y_pos_e, p->y_end+1-p->y_start, tstr+p->y_start); - fprintf(stderr, "[qstr::[%u, %u]] %.*s\n", z->x_pos_s, z->x_pos_e, p->x_end+1-p->x_start, qstr+p->x_start); - exit(0); - } -} - - -void ul_lalign_old_ed(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, char *qstr, - uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, - haplotype_evdience_alloc* hap, kvec_t_u64_warp* v_idx, - double e_rate, int64_t wl, uint64_t is_base, void *km) -{ - uint64_t i, bs, k, ovl/**, on**/; Window_Pool w; double err; - /**int64_t sc;**/ overlap_region t; overlap_region *z; - ol->mapped_overlaps_length = 0; - if(ol->length <= 0) return; - - ///base alignment - clear_Correct_dumy(dumy, ol, km); err = e_rate; - init_Window_Pool(&w, ql, wl, (int)(1.0/err)); - bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; - resize_UC_Read(tu, bs<<1); - - if(is_base) { - resize_UC_Read(qu, ql); qu->length = ql; memcpy(qu->seq, qstr, ql); - for (i = 0; i < ol->length; i++) { - z = &(ol->list[i]); ovl = z->x_pos_e+1-z->x_pos_s; - if(!align_ul_ed_post(z, uref, NULL, qu->seq, tu->seq, tu->seq+bs, dumy, err, w.window_length, -1, km)) { - continue; - } - if(uref && simi_pass(ovl, z->align_length, uref?1:0, -1, NULL)) { - z->is_match = 3; ol->mapped_overlaps_length += z->align_length; - } - } - - if(uref && ol->mapped_overlaps_length > 0) { - set_herror_win(ol, dumy, v_idx, err, ql, w.window_length); - } - - double e_max = err*1.5, rr; int64_t re; - for (i = k = 0; i < ol->length; i++) { - z = &(ol->list[i]); ovl = z->x_pos_e + 1 - z->x_pos_s; - rr = gen_extend_err(z, uref, NULL, NULL, qu->seq, tu->seq, tu->seq+bs, - dumy, v_idx?v_idx->a.a:NULL, w.window_length, -1, err, (e_max+0.000001), &re); - z->is_match = 0;///must be here; - if (rr <= err) { - if(k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - ol->list[k].is_match = 1; ol->list[k].non_homopolymer_errors = re; - k++; - } - } - - ol->length = k; - // fprintf(stderr, "+[M::%s] on::%lu\n", __func__, ol->length); - if(ol->length <= 0) return; - } else { - // fprintf(stderr, "-[M::%s] on::%lu\n", __func__, ol->length); - if(ol->length <= 1) return; - // for (i = 0; (i < ol->length) && (ol->list[i].is_match == 1); i++); on = i; - // if(on <= 1) return; - // kv_resize(uint64_t, v_idx->a, (on<<1)); v_idx->a.n = on; - // for (i = 0; i < on; i++) { - // sc = ol->list[i].x_pos_e+1-ol->list[i].x_pos_s; - // sc -= ((int64_t)(ol->list[i].non_homopolymer_errors*ERROR_RATE)); - // if(sc < 0) sc = 0; - // v_idx->a.a[i] = sc; v_idx->a.a[i] <<= 32; v_idx->a.a[i] += i; - // } - // radix_sort_bc64(v_idx->a.a, v_idx->a.a+on); - // for (i = 0; i < on; i++) { - // ol->list[i].non_homopolymer_errors = 0; - // k = ((uint32_t)v_idx->a.a[i]); - // v_idx->a.a[k]<<=32; v_idx->a.a[k]>>=32; v_idx->a.a[k]|=i; - // } - // ul_phase(ol->list, on, v_idx->a.a, v_idx->a.a+on); - - - for (i = 0; i < ol->length; i++) { - z = &(ol->list[i]); ovl = z->x_pos_e+1-z->x_pos_s; z->is_match = 1; - for (k = 0; k < z->w_list.n; k++) { - if(z->w_list.a[k].clen) continue; - gen_backtrace_adv(&(z->w_list.a[k]), z, NULL, NULL, uref, qu->seq, tu->seq, tu->seq+bs, - dumy, z->y_pos_strand, z->y_id); - } - ol->mapped_overlaps_length += ovl; - append_unmatched_wins(z, w.window_length); - calculate_ul_boundary_cigars(z, uref, dumy, qu, err, w.window_length); - } - partition_ul_overlaps_advance(ol, uref, qu, tu, dumy, hap, 1, err, w.window_length, km); - } -} - -inline uint64_t scale_ed_thre(uint32_t err, uint32_t max_err) -{ - uint64_t bd = (err<<1)+1, w; - w = (bd>>bitw); w <<= bitw; if(w < bd) w += bitwbit; - err = (w-1)>>1; if(err > max_err) err = max_err; - return err; -} - - -///[qs, qe) -int64_t update_semi_coord(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, overlap_region *z, -int64_t qs, int64_t qe, int64_t thre, int64_t *ts, int64_t *te, int64_t *aux_beg) -{ - int64_t ql = qe - qs, aln_l, t_tot_l, id = z->y_id, aux_end, tl; - (*ts) = (qs - z->x_pos_s) + z->y_pos_s; - (*ts) += y_start_offset(qs, &(z->f_cigar)); - aln_l = ql + (thre<<1); - if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); - else if(uref) t_tot_l = uref->ug->u.a[id].len; - else t_tot_l = Get_READ_LENGTH((*rref), id); - if(!init_waln(thre, (*ts), t_tot_l, aln_l, aux_beg, &aux_end, ts, &tl)) { - (*ts) = (*te) = (*aux_beg) = -1; - return 0; - } - (*te) = (*ts) + tl; - return 1; -} - - -///[qs, qe) -int64_t update_semi_non_retrieve_coord(overlap_region *z, int64_t qs, int64_t qe, int64_t thre, int64_t t_tot_l, int64_t *ts, int64_t *te, int64_t *aux_beg) -{ - int64_t ql = qe - qs, aln_l, aux_end, tl; - (*ts) = (qs - z->x_pos_s) + z->y_pos_s; - (*ts) += y_start_offset(qs, &(z->f_cigar)); - aln_l = ql + (thre<<1); - - if(!init_waln(thre, (*ts), t_tot_l, aln_l, aux_beg, &aux_end, ts, &tl)) { - (*ts) = (*te) = (*aux_beg) = -1; - return 0; - } - (*te) = (*ts) + tl; - return 1; -} - - -void adjust_ext_offset(int64_t *qs, int64_t *qe, int64_t *ts, int64_t *te, int64_t ql, int64_t tl, int64_t thre, int64_t mode) -{ - int64_t qoff, toff; - if(mode == 1) {///forward extension - qoff = ql - (*qs); toff = tl - (*ts); - if(qoff <= toff) { - (*qe) = ql; (*te) = (*ts) + qoff + thre; - } else { - (*te) = tl; (*qe) = (*qs) + toff + thre; - } - } else if(mode == 2) {///backward extension - qoff = (*qe); toff = (*te); - if(qoff <= toff) { - (*qs) = 0; (*ts) = (*te) - qoff - thre; - } else { - (*ts) = 0; (*qs) = (*qe) - toff - thre; - } - } - if((*qs) < 0) (*qs) = 0; - if((*ts) < 0) (*ts) = 0; - if((*qe) > ql) (*qe) = ql; - if((*te) > tl) (*te) = tl; -} - -void adjust_specific_ext_offset(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, bit_extz_t *exz, char* qstr, UC_Read *tu, -int64_t *qs0, int64_t *qe0, int64_t *ts0, int64_t *te0, int64_t ql, int64_t tl, int64_t wl, int64_t *mode) -{ - ///[qs, qe) - if((*mode) != 1 && (*mode) != 2) return; - int64_t qs = *qs0, qe = *qe0, ts = *ts0, te = *te0, k, update, wid, we, ws, sl, gq, gt, gg, min_g = INT32_MAX, min_id = -1, gl; - adjust_ext_offset(&qs, &qe, &ts, &te, ql, tl, 0, *mode); - if((*mode) == 1) {///forward extension - //qs0 and ts0 are fixed; te0 = -1, qe0 is unreliable - if(qe > (*qe0)) { - we = (*qe0); we/=wl; we *= wl; we +=wl; we--; ///next window - for (k = 0; we < qe && k < ext_w; we+=wl) {//[ws, we]; [qs, qe) - wid = get_win_id_by_e(z, we, wl, NULL); - if(z->w_list.a[wid].y_end == -1) continue;//unmapped - if(z->w_list.a[wid].x_end < (*qs0)) continue; - if(z->w_list.a[wid].y_end < (*ts0)) continue; - sl = z->w_list.a[wid].x_end+1-z->w_list.a[wid].x_start; - if(z->w_list.a[wid].error > (sl/A_L)) continue; - gq = z->w_list.a[wid].x_end-(*qs0); - gt = z->w_list.a[wid].y_end-(*ts0); - gl = MIN(gq, gt); gl/=16; if(gl <= 0) gl = 1; - gg = (gq>=gt)?(gq-gt):(gt-gq); gg /= gl; - update = 0; - if(min_g>gg) { - update = 1; - } else if((min_g==gg)&&(z->w_list.a[min_id].error>z->w_list.a[wid].error)) { - update = 1; - } - if(update) { - min_g = gg; min_id = wid; - } - k++; - } - } - if(min_id >= 0) { - (*qe0) = z->w_list.a[min_id].x_end+1; - if(((*qe0)+wl) >= qe) { - (*qe0) = qe; (*te0) = te; ///still extension - return; - } - (*te0) = z->w_list.a[min_id].y_end+1; (*mode) = 0;///global - } else { - (*qe0) = qe; (*te0) = te; ///still extension - } - } else if((*mode) == 2) {///backward extension - //qe0 and te0 are fixed; ts0 = -1, qs0 is unreliable - if(qs < (*qs0)) { - ws = (*qs0)-1; ws/=wl; ws*=wl; - for (k = 0; ws >= qs && k < ext_w; ws-=wl) {//[ws, we]; [qs, qe) - wid = get_win_id_by_s(z, ws, wl, NULL); - if(z->w_list.a[wid].y_end == -1) continue;//unmapped - if(z->w_list.a[wid].x_start >= (*qe0)) continue; - if(z->w_list.a[wid].y_start >= (*te0)) continue; - sl = z->w_list.a[wid].x_end+1-z->w_list.a[wid].x_start; - if(z->w_list.a[wid].error > (sl/A_L)) continue; - gq = (*qe0) - z->w_list.a[wid].x_start; - gt = (*te0) - z->w_list.a[wid].y_start; - gl = MIN(gq, gt); gl/=16; if(gl <= 0) gl = 1; - gg = (gq>=gt)?(gq-gt):(gt-gq); gg /= gl; - update = 0; - if(min_g>gg) { - update = 1; - } else if((min_g==gg)&&(z->w_list.a[min_id].error>z->w_list.a[wid].error)) { - update = 1; - } - if(update) { - min_g = gg; min_id = wid; - } - k++; - } - } - if(min_id >= 0) { - (*qs0) = z->w_list.a[min_id].x_start; - if((qs+wl) >= (*qs0)) { - (*qs0) = qs; (*ts0) = ts; ///still extension - return; - } - (*ts0) = z->w_list.a[min_id].y_start; (*mode) = 0;///global - } else { - (*qs0) = qs; (*ts0) = ts; ///still extension - } - } -} - -int64_t cal_exz_infi(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, bit_extz_t *exz, char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t thre, int64_t q_tot_l, int64_t mode) -{ - clear_align(*exz); - int64_t aux_beg = 0, bd = (((thre)<<1)+1), ql, tl, t_tot_l = -1; int32_t nword = ((bd>>bitw)+(!!(bd&bitz))); - char *q_string, *t_string; int32_t rev = z->y_pos_strand, id = z->y_id; ql = qe - qs; - if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); - else if(uref) t_tot_l = uref->ug->u.a[id].len; - else t_tot_l = Get_READ_LENGTH((*rref), id); - - if(mode == 3) { - update_semi_coord(uref, hpc_g, rref, z, qs, qe, thre, &ts, &te, &aux_beg); - } else if(mode == 1 || mode == 2) { - adjust_ext_offset(&qs, &qe, &ts, &te, q_tot_l, t_tot_l, thre, mode); - } - - if((qe > qs) && (te > ts) && (ts != -1) && (te != -1)) { - ql = qe - qs; q_string = qstr + qs; - tl = te - ts; resize_UC_Read(tu, tl); - // fprintf(stderr, "q::[%ld, %ld), t::[%ld, %ld), thre::%ld, t_tot_l::%ld\n", qs, qe, ts, te, thre, t_tot_l); - if(rref) { - recover_UC_Read_sub_region(tu->seq, ts, tl, rev, rref, id); t_string = tu->seq; - } else { - t_string = return_str_seq_exz(tu->seq, ts, tl, rev, hpc_g, uref, id); - } - // fprintf(stderr, ", nword::%d", nword); - // if(ql < 0) fprintf(stderr, "qs::%ld, qe::%ld\n", qs, qe); - // return 0; - if(nword <= 1) { - if(mode == 0) { //global - ed_band_cal_global_64_w_trace(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 1) {///forward extension - // fprintf(stderr, "q::[%ld, %ld), t::[%ld, %ld), thre::%ld\n", qs, qe, ts, te, thre); - ed_band_cal_extension_64_0_w_trace(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 2) {///backward extension - ed_band_cal_extension_64_1_w_trace(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 3) {//semi-global - ed_band_cal_semi_64_w_absent_diag_trace(t_string, tl, q_string, ql, thre, aux_beg, exz); - } - } else if(nword == 2) { - if(mode == 0) { //global - ed_band_cal_global_128_w_trace(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 1) {///forward extension - ed_band_cal_extension_128_0_w_trace(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 2) {///backward extension - ed_band_cal_extension_128_1_w_trace(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 3) {//semi-global - ed_band_cal_semi_128_w_absent_diag_trace(t_string, tl, q_string, ql, thre, aux_beg, exz); - } - } else { - if(mode == 0) { //global - ed_band_cal_global_infi_w_trace(t_string, tl, q_string, ql, thre, &nword, exz); - } else if(mode == 1) {///forward extension - ed_band_cal_extension_infi_0_w_trace(t_string, tl, q_string, ql, thre, &nword, exz); - } else if(mode == 2) {///backward extension - ed_band_cal_extension_infi_1_w_trace(t_string, tl, q_string, ql, thre, &nword, exz); - } else if(mode == 3) {//semi-global - ed_band_cal_semi_infi_w_absent_diag_trace(t_string, tl, q_string, ql, thre, aux_beg, &nword, exz); - } - } - if(is_align(*exz)) { - - return 1; - } - return 0; - } - return 0; -} - -void hc_aln_exz(overlap_region *z, Candidates_list *cl, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, -char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t estimate_err, -int64_t mode, int64_t wl, bit_extz_t *exz, int64_t q_tot, double e_rate, int64_t maxl, int64_t maxe) -{ - clear_align(*exz); - int64_t thre, ql = qe - qs, thre0, t_tot, id = z->y_id; - if(((ts == -1) && (te == -1))) mode = 3;///set to semi-global - - if(mode == 1 || mode == 2) { - if(hpc_g) t_tot = hpc_len(*hpc_g, id); - else if(uref) t_tot = uref->ug->u.a[id].len; - else t_tot = Get_READ_LENGTH((*rref), id); - // fprintf(stderr, "\n+[M::%s::ql->%ld::tl->%ld::mode->%ld] q::[%ld, %ld), t::[%ld, %ld), zx[%d, %d), zy[%d, %d)\n", - // __func__, q_tot, t_tot, mode, qs, qe, ts, te, z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1); - ///find a aligned window >= qe to convert extension to global; or do extension directly - adjust_specific_ext_offset(z, uref, hpc_g, rref, exz, qstr, tu, &qs, &qe, &ts, &te, q_tot, t_tot, wl, &mode); - // fprintf(stderr, "-[M::%s::ql->%ld::tl->%ld::mode->%ld] q::[%ld, %ld), t::[%ld, %ld), zx[%d, %d), zy[%d, %d)\n", - // __func__, q_tot, t_tot, mode, qs, qe, ts, te, z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1); - } - - // fprintf(stderr, "[M::%s::ql::%ld] qs::%ld, qe::%ld, ts::%ld, te::%ld, mode::%ld, estimate_err::%ld, e_rate::%f", - // __func__, ql, qs, qe, ts, te, mode, estimate_err, e_rate); - - if(ql <= maxl && (estimate_err*1.2) <= maxe) { - thre = scale_ed_thre(estimate_err, maxe); if(thre > ql) thre = ql; - if(cal_exz_infi(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, thre, q_tot, mode)) { - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(+)\n", exz->err, exz->thre, thre); - return; - } - - thre0 = thre; thre = ql*e_rate; - thre = scale_ed_thre(thre, maxe); if(thre > ql) thre = ql; - if(thre > thre0) { - if(cal_exz_infi(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, thre, q_tot, mode)) { - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); - return; - } - } - - thre0 = thre; thre <<= 1; - thre = scale_ed_thre(thre, maxe); if(thre > ql) thre = ql; - if(thre > thre0) { - if(cal_exz_infi(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, thre, q_tot, mode)) { - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); - return; - } - } - - thre0 = thre; thre = ql*0.51; - thre = scale_ed_thre(thre, maxe); if(thre > ql) thre = ql; - if(thre > thre0) { - if(cal_exz_infi(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, thre, q_tot, mode)) { - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); - return; - } - } - } - // fprintf(stderr, ", err::%d, thre::%d\n", INT32_MAX, exz->thre); - // anchor_aln(z, cl, uref, hpc_g, rref, qstr, tu, qs, qe, ts, te, thre, mode, wl, exz, q_tot, A_L); - -} - -void sub_ciagar_gen(overlap_region *z, Candidates_list *cl, uint64_t s, uint64_t e, uint64_t wl, -const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, double e_rate, -int64_t ql, uint64_t rid) -{ - uint64_t qs, qe, sid, eid, k, l, m, tot_e, c_e; int64_t q[2], t[2], o[2], mode, kocc; - qs = (s/wl)*wl; if(qs < z->x_pos_s) qs = z->x_pos_s; if(qs > z->x_pos_e) return; - qe = (e/wl)*wl; if(qe < e) qe += wl; if(qe > z->x_pos_e+1) qe = z->x_pos_e+1; - if(qe <= 0) return; - sid = get_win_id_by_s(z, qs, wl, NULL); - eid = get_win_id_by_e(z, qe-1, wl, NULL) + 1;///must qe-1 instead of qe!!!!!! - if(sid >= eid) return; - // fprintf(stderr, "\n***[M::%s::rid->%lu] s::%lu, e::%lu, n_qs::%lu, n_qe::%lu, z::[%u, %u), sid::%lu, eid::%lu, w_list.n::%lu\n", - // __func__, rid, s, e, qs, qe, z->x_pos_s, z->x_pos_e+1, sid, eid, (uint64_t)z->w_list.n); - for (k = sid+1, l = sid; k <= eid; k++) {//[sid, eid) - if(k == eid || z->w_list.a[k].extra_end < 0) { - if(k - l > 1 || z->w_list.a[l].extra_end >= 0) { - q[0] = q[1] = t[0] = t[1] = -1; - o[0] = o[1] = -1; mode = -1; tot_e = 0; - if(z->w_list.a[l].extra_end < 0) { - q[0] = z->w_list.a[l].x_end+1; - if(z->w_list.a[l].y_end != -1) { - t[0] = z->w_list.a[l].y_end+1; - } - if(z->w_list.a[l].extra_end != INT16_MIN) { - o[0] = -z->w_list.a[l].extra_end; - } - } else {///first window - q[0] = qs; - if(z->w_list.a[l].y_end != -1) { - c_e = z->w_list.a[l].error; - } else { - c_e = z->w_list.a[l].x_end + 1 - z->w_list.a[l].x_start; - if(c_e > THRESHOLD_MAX_SIZE) c_e = THRESHOLD_MAX_SIZE; - } - tot_e += c_e; - } - - if(k > sid && k < eid && z->w_list.a[k].extra_end < 0) { - q[1] = z->w_list.a[k-1].x_end+1; - if(z->w_list.a[k].y_end != -1) { - // if(z->w_list.a[k-1].y_end == -1) { - // fprintf(stderr, "[M::%s::rid::%lu] k::%lu, sid::%lu, eid::%lu, k_y_end::%d, k-1_y_end::%d, xk[%d, %d)\n", - // __func__, rid, k, sid, eid, z->w_list.a[k].y_end, z->w_list.a[k-1].y_end, - // z->w_list.a[k].x_start, z->w_list.a[k].x_end+1); - // } - assert(z->w_list.a[k-1].y_end != -1); - t[1] = z->w_list.a[k-1].y_end+1; - } - if(z->w_list.a[k].extra_end != INT16_MIN) { - o[1] = -z->w_list.a[k].extra_end; - } - } else {///last window - q[1] = qe; - } - - if((t[0] != -1) && (t[1] != -1)) { - mode = 0;//global - } else if((t[0] != -1) && (t[1] == -1)) { - /**t[1] = z->y_pos_e+1;**/ mode = 1;///forward extension - } else if((t[0] == -1) && (t[1] != -1)) { - /**t[0] = z->y_pos_s;**/ mode = 2;///backward extension - } else { - mode = 3;//semi-global - } - - for (m = l+1; m < k; m++) { - if(z->w_list.a[m].y_end != -1) { - c_e = z->w_list.a[m].error; - } else { - c_e = z->w_list.a[m].x_end + 1 - z->w_list.a[m].x_start; - if(c_e > THRESHOLD_MAX_SIZE) c_e = THRESHOLD_MAX_SIZE; - } - tot_e += c_e; - } - // if(q[1] < q[0]) { - // fprintf(stderr, "[M::%s::ql::%lu] qs::%lu, qe::%lu, ts::%lu, te::%lu, mode::%ld, tot_e::%lu\n", - // __func__, q[1]-q[0], q[0], q[1], t[0], t[1], mode, tot_e); - // } - kocc = MAX(o[0], o[1]); if(kocc < 0) kocc = 1; - hc_aln_exz(z, cl, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], tot_e, mode, wl, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E); - - } - l = k; - } - } -} - - -uint64_t cigar_gen(overlap_region *z, Candidates_list *cl, ul_ov_t *ov, uint64_t on, uint64_t qn, uint64_t wl, -const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, double e_rate, -int64_t ql, uint64_t rid, ul_ov_t *des) -{ - if(on <= 0) return 0; - uint64_t i; - // des[0] = ov[0]; - // for (i = m = 1; i < on; i++) { - // fusion_merge(); - // } - - - for (i = 0; i < on; i++) { - assert((i<=0)||(ov[i].qs > ov[i-1].qe)); - sub_ciagar_gen(z, cl, ov[i].qs, ov[i].qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, rid); - } - return on; - // uint64_t i, qs = (uint64_t)-1, qe = (uint64_t)-1; - // for (i = 0; i < on && ov[i].qn == qn; i++) { - // assert((i<=0)||(ov[i].qs >= ov[i-1].qe)); - // if(ov[i].qs <= qe && qe != (uint64_t)-1) { - // qe = ov[i].qe; - // } else { - // if(qs != (uint64_t)-1) sub_ciagar_gen(z, cl, qs, qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, rid); - // qs = ov[i].qs; qe = ov[i].qe; - // } - // } - // if(qs != (uint64_t)-1) sub_ciagar_gen(z, cl, qs, qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, rid); -} - - - -int64_t push_adp_k_hits(Candidates_list *cl, int64_t cln, uint64_t qs, uint64_t qe, uint64_t ts, uint64_t te, uint64_t readID, int64_t ci, int64_t dbgid) -{ - int64_t k = ci, m = -1; k_mer_hit *p = NULL; - if(cl->length > cln) { - m = cl->length-1; assert(is_alnw(cl->list[m])); - } - for (; k < cln && cl->list[k].readID == readID && cl->list[k].self_offset < qs; k++) { - p = &(cl->list[k]); - // fprintf(stderr, "[M::%s::] p->q::%ld, p->t::%ld\n", __func__, p->self_offset, p->offset); - if(p->offset >= ts) continue; - if((m>=0) && ((cl->list[m].offset >= p->offset) || (cl->list[m].self_offset >= p->self_offset))) { - continue; - } - kv_pushp_cl(k_mer_hit, (*cl), &p); *p = cl->list[k]; p->readID = p->cnt; - // if(dbgid == 109111 || dbgid == 75436) { - // fprintf(stderr, "[M::%s::k->%ld] self_offset::%u, offset::%u, cl->length::%lld, cln::%ld, p->readID::%u\n", - // __func__, k, cl->list[k].self_offset, cl->list[k].offset, cl->length, cln, p->readID); - // } - } - if(qs == (uint64_t)-1 || qe == (uint64_t)-1) return k; - // if(!(k >= cln || cl->list[k].self_offset >= qe)) { - // fprintf(stderr, "[M::%s::] k::%ld, self_offset::%u, offset::%u\n", - // __func__, k, cl->list[k].self_offset, cl->list[k].offset); - // } - assert(k >= cln || cl->list[k].readID != readID || cl->list[k].self_offset >= qe); - ///push qs, ts - kv_pushp_cl(k_mer_hit, (*cl), &p); - p->readID = ((uint32_t)(0x7fffffff)); - p->cnt = (uint32_t)-1; p->strand = 0; - p->self_offset = qs; p->offset = ts; - - for (; k < cln && cl->list[k].readID == readID && cl->list[k].self_offset < qe; k++); - - ///push qe, te - kv_pushp_cl(k_mer_hit, (*cl), &p); - p->readID = ((uint32_t)(0x7fffffff)); - p->cnt = (uint32_t)-1; p->strand = 1; - p->self_offset = qe-1; p->offset = te-1; - return k; -} - -int64_t gen_weight_khits0(uint32_t qs, uint32_t qe, k_mer_hit *a, int64_t an, int64_t k, uint64_t dp)///[qs, qe) -{ - for (; k >= 0 && a[k].self_offset >= qs; k--); - for (k = ((k>=0)?k:0); k < an && a[k].self_offset < qe; k++) { - if((a[k].self_offset >= qs) && (a[k].self_offset < qe) && (!is_alnw(a[k]))) { - a[k].readID = dp; - } - } - return k; -} - -void gen_weight_khits(asg64_v* idx, k_mer_hit *a, int64_t an) -{ - int64_t i, idx_n = idx->n, dp, old_dp, beg, end, k; - // fprintf(stderr, "[M::%s::] idx->n::%ld\n", __func__, (int64_t)idx->n); - for (i = k = 0, dp = old_dp = 0, beg = 0, end = -1; i < idx_n; ++i) {///[beg, end) but coordinates in idx is [, ] - ///if idx->a.a[] is qe - old_dp = dp; - if ((idx->a[i]>>32)&1) { - --dp; end = (idx->a[i]>>33)+1; - }else { - //meet a new overlap; the overlaps are pushed by the x_pos_s - ++dp; end = (idx->a[i]>>33); - } - // fprintf(stderr, "[M::%s::] beg::%ld, end::%ld, old_dp::%ld\n", __func__, beg, end, old_dp); - if(end > beg) k = gen_weight_khits0(beg, end, a, an, k, old_dp); - beg = end; - } -} - -void prt_khit(Candidates_list *cl, overlap_region_alloc* ol, overlap_region *z, uint64_t utg_id, const char *cmd) -{ - uint64_t k, cid; int64_t i; - if(!z) { - for (k = 0; k < ol->length; k++) { - z = &(ol->list[k]); - if(z->y_id == utg_id) break; - } - } - if((z) || (z->y_id == utg_id)) { - fprintf(stderr, "[M::%s::cmd->%s] ******\n", __func__, (char *)cmd); - for (i = z->shared_seed, cid = cl->list[i].readID; i < cl->length && cl->list[i].readID == cid; i++) { - fprintf(stderr, "[M::%s::i->%lu] qoff::%u, toff::%u, cid::%lu, cl->length::%lld\n", __func__, i, - cl->list[i].self_offset, cl->list[i].offset, cid, cl->length); - } - } -} - -int64_t gen_cns_chain(overlap_region_alloc* ol, overlap_region *z, Candidates_list *cl, asg64_v* iidx, int64_t max_lgap, double sgap_rate, int64_t need_filter_khit) -{ - int64_t k, wn = z->w_list.n, aln_n, qs, qe, ts, te, ci, id, rcn = cl->length, kn; k_mer_hit *ka; - if(wn <= 0) return 0; - qs = qe = ts = te = -1; ci = z->shared_seed; id = cl->list[ci].readID; - for (k = aln_n = 0; k < wn; k++) { - if(z->w_list.a[k].extra_end < 0 && z->w_list.a[k].y_end != -1) {///anchor - if(qs == -1) { - qs = z->w_list.a[k].x_start; ts = z->w_list.a[k-1].y_end+1; - } - qe = z->w_list.a[k].x_end+1; te = z->w_list.a[k].y_end+1; - } else { - if(qs != -1) { - // if(z->y_id == 109111 || z->y_id == 75436) { - // fprintf(stderr, "\n[M::%s::] q::[%ld, %ld), t::[%ld, %ld), ci::%ld, cn::%lld\n", - // __func__, qs, qe, ts, te, ci, cl->length); - // } - ci = push_adp_k_hits(cl, rcn, qs, qe, ts, te, id, ci, z->y_id); - aln_n++;//[qs, qe); [ts, te) - } - qs = qe = ts = te = -1; - } - } - if(qs != -1) { - // if(z->y_id == 109111 || z->y_id == 75436) { - // fprintf(stderr, "\n[M::%s::] q::[%ld, %ld), t::[%ld, %ld), ci::%ld, cn::%lld\n", - // __func__, qs, qe, ts, te, ci, cl->length); - // } - ci = push_adp_k_hits(cl, rcn, qs, qe, ts, te, id, ci, z->y_id); - aln_n++;//[qs, qe); [ts, te) - } - // if(z->y_id == 109111 || z->y_id == 75436) { - // fprintf(stderr, "\n[M::%s::] q::[%ld, %ld), t::[%ld, %ld), ci::%ld, cn::%lld, rcn::%ld\n", - // __func__, qs, qe, ts, te, ci, cl->length, rcn); - // } - push_adp_k_hits(cl, rcn, (uint64_t)-1, (uint64_t)-1, (uint64_t)-1, (uint64_t)-1, id, ci, z->y_id); - - ka = cl->list+rcn; kn = cl->length-rcn; - // if(z->y_id == 66) { - // fprintf(stderr, "[M::%s::] kn::%ld, q_pos::%u, t_pos::%u\n", __func__, kn, ka[kn-1].self_offset, ka[kn-1].offset); - // } - // if(z->y_id == 109111 || z->y_id == 75436) { - // prt_khit(cl, ol, NULL, 109111, "sa"); - // } - if(iidx) gen_weight_khits(iidx, ka, kn); - // if(z->y_id == 109111 || z->y_id == 75436) { - // prt_khit(cl, ol, NULL, 109111, "sb"); - // } - if(need_filter_khit) { - kn = lchain_dp_trace(ka, kn, max_lgap, sgap_rate, SGAP); cl->length = rcn + kn; - } - cl->length = rcn; - return kn; -} - - -uint64_t cigar_gen_cns(overlap_region *z, Candidates_list *cl, ul_ov_t *ov, uint64_t on, uint64_t qn, uint64_t wl, -const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, double e_rate, -int64_t ql, uint64_t rid, asg64_v* iidx, ul_ov_t *des) -{ - if(on <= 0 || iidx->n <= 0) return 0; - uint64_t i; - for (i = 0; i < on; i++) { - assert((i<=0)||(ov[i].qs > ov[i-1].qe)); - sub_ciagar_gen(z, cl, ov[i].qs, ov[i].qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, rid); - } - return on; -} - -///[ys, ye) -uint64_t inline get_win_aln(overlap_region *z, uint64_t wid, int64_t *ys, int64_t *ye, int64_t *err) -{ - (*err) = -2; - if((wid > 0) && (z->w_list.a[wid].y_end != -1) && (z->w_list.a[wid-1].y_end != -1) && (z->w_list.a[wid].y_end > z->w_list.a[wid-1].y_end)) { - (*ys) = z->w_list.a[wid-1].y_end+1; - (*ye) = z->w_list.a[wid].y_end+1; - (*err) = z->w_list.a[wid].error; - return 1; - } - return 0; -} - -char* retrive_str_piece_exz(All_reads *rref, const ul_idx_t *uref, char *buf, int64_t s, int64_t l, int64_t rev, int64_t id) -{ - if(rref) recover_UC_Read_sub_region(buf, s, l, rev, rref, id); - else if(uref) retrieve_u_seq(NULL, buf, &(uref->ug->u.a[id]), rev, s, l, NULL); - else return NULL; - return buf; -} - -uint64_t k_hits_bcheck(All_reads *rref, const ul_idx_t *uref, overlap_region_alloc* ol, Candidates_list *cl, -uint64_t khit, uint64_t *a, uint64_t a_n, char* qstr, char *str0, char *str1) -{ - if(a_n < 2) return 1; - uint64_t k, e; char *ref0, *ref1; overlap_region *z; - - e = cl->list[(uint32_t)a[0]].offset; - if(e >= khit) e-=khit; - else return 0; - z = &(ol->list[cl->list[(uint32_t)a[0]].readID]); - ref0 = retrive_str_piece_exz(rref, uref, str0, e, khit, z->y_pos_strand, z->y_id); - // fprintf(stderr, "\n[M::%s::] qstr::%.*s\n", __func__, - // (int32_t)khit, qstr+cl->list[(uint32_t)a[0]].self_offset-khit); - // fprintf(stderr, "[M::%s::qoff->%u::toff->%u::%c] tstr0::%.*s\n", __func__, - // cl->list[(uint32_t)a[0]].self_offset, cl->list[(uint32_t)a[0]].offset, "+-"[z->y_pos_strand], (int32_t)khit, ref0); - - for (k = 1; k < a_n; k++) { - e = cl->list[(uint32_t)a[k]].offset; - if(e >= khit) e-=khit; - else return 0; - z = &(ol->list[cl->list[(uint32_t)a[k]].readID]); - ref1 = retrive_str_piece_exz(rref, uref, str1, e, khit, z->y_pos_strand, z->y_id); - // fprintf(stderr, "[M::%s::qoff->%u::toff->%u::%c] tstr1::%.*s\n", __func__, - // cl->list[(uint32_t)a[k]].self_offset, cl->list[(uint32_t)a[k]].offset, "+-"[z->y_pos_strand], (int32_t)khit, ref1); - if(memcmp(ref0, ref1, khit)) return 0; - } - return 1; -} - -inline int64_t khit_long_gap(k_mer_hit *a, k_mer_hit *b, double small_bw_rate, int64_t min_small_bw) -{ - int64_t dq, dr, dd, dm; - dq = b->self_offset-a->self_offset; - dr = b->offset-a->offset; - dd = dq>=dr? ((dq)-(dr)): ((dr)-(dq)); - - dm = dq>=dr?dr:dq; - if((dd > (dm*small_bw_rate)) && (dd > min_small_bw)) return 0; - return 1; -} - -int64_t filter_bad_khits(k_mer_hit *sk, k_mer_hit *ek, k_mer_hit* a, int64_t a_n, double small_bw_rate, int64_t min_small_bw) -{ - int64_t k = 0; k_mer_hit *z; double bw_r; int64_t bw, occ = 0; - bw_r = small_bw_rate; bw = min_small_bw; - if(sk) { - for (k = 0; k < a_n; k++) { - z = &(a[k]); - if((sk && (!khit_long_gap(sk, z, bw_r, bw))) || - (ek && (!khit_long_gap(z, ek, bw_r, bw)))) { - z->offset = z->self_offset = (uint32_t)-1; occ++; - } else { - break; - } - } - } - - if(ek && k < a_n) { - for (k = a_n-1; k >= 0; k--) { - z = &(a[k]); - if(z->cnt < z->readID) continue; - if((sk && (!khit_long_gap(sk, z, bw_r, bw))) || - (ek && (!khit_long_gap(z, ek, bw_r, bw)))) { - z->offset = z->self_offset = (uint32_t)-1; occ++; - } else { - break; - } - } - } - - if(occ) { - for (k = occ = 0; k < a_n; k++) { - if(a[k].offset == (uint32_t)-1) continue; - a[occ++] = a[k]; - } - a_n = occ; - } - return a_n; -} - -int64_t filter_adp_k_hits(k_mer_hit *ka, int64_t kn, Chain_Data *dp, uint64_t qs, uint64_t qe, uint64_t ts, uint64_t te, uint64_t readID, int64_t ci, int64_t *cmi, k_mer_hit *m, -double small_bw_rate, int64_t min_small_bw) -{ - int64_t k = ci, cmi0 = (*cmi); k_mer_hit *p = NULL, n; - for (; k < kn && ka[k].readID == readID && ka[k].self_offset < qs; k++) { - p = &(ka[k]); - // fprintf(stderr, "[M::%s::] p->q::%ld, p->t::%ld\n", __func__, p->self_offset, p->offset); - if(p->offset >= ts) continue; - if((m) && ((m->offset >= p->offset) || (m->self_offset >= p->self_offset))) continue; - ka[(*cmi)++] = *p; - } - n.self_offset = qs; n.offset = ts; p = &n; - if(qs == (uint64_t)-1 || qe == (uint64_t)-1) p = NULL; - // fprintf(stderr, "[M::%s::] cmi0::%ld, cmi::%ld\n", __func__, cmi0, (*cmi)); back = (*cmi); - if((*cmi) > cmi0) { - (*cmi) = cmi0 + filter_bad_khits(m, p, ka+cmi0, (*cmi)-cmi0, small_bw_rate, min_small_bw); - if((*cmi) > cmi0) { - (*cmi) = cmi0 + lchain_refine(ka+cmi0, (*cmi)-cmi0, ka+cmi0, dp, 50, 5000, 512, 16); - } - } - // if(back != (*cmi)) { - // fprintf(stderr, "sbsbsbsb[M::%s::] cmi0::%ld, cmi::%ld\n", __func__, cmi0, (*cmi)); - // } - - for (; k < kn && ka[k].readID == readID && ka[k].self_offset < qe; k++); - return k; -} - - -void refine_khits(overlap_region *z, Candidates_list *cl, Chain_Data *dp, double sgap_rate) -{ - int64_t k, wn = z->w_list.n, aln_n, qs, qe, ts, te, ci, cmi, id, mm_gap = 64; - k_mer_hit p; p.self_offset = (uint32_t)-1; p.offset = (uint32_t)-1; - if(wn <= 0) return; - qs = qe = ts = te = -1; ci = cmi = z->shared_seed; id = cl->list[ci].readID; - for (k = aln_n = 0; k < wn; k++) { - if(z->w_list.a[k].extra_end < 0 && z->w_list.a[k].y_end != -1) {///anchor - if(qs == -1) { - qs = z->w_list.a[k].x_start; ts = z->w_list.a[k-1].y_end+1; - } - qe = z->w_list.a[k].x_end+1; te = z->w_list.a[k].y_end+1; - } else { - if(qs != -1) { - // fprintf(stderr, "\n[M::%s::] q::[%ld, %ld), t::[%ld, %ld), ci::%ld\n", - // __func__, qs, qe, ts, te, ci); - ci = filter_adp_k_hits(cl->list, cl->length, dp, qs, qe, ts, te, id, ci, &cmi, - aln_n?&p:NULL, sgap_rate, mm_gap); - p.self_offset = qe - 1; p.offset = te -1; - aln_n++;//[qs, qe); [ts, te) - } - qs = qe = ts = te = -1; - } - } - if(qs != -1) { - // fprintf(stderr, "\n[M::%s::] q::[%ld, %ld), t::[%ld, %ld), ci::%ld\n", - // __func__, qs, qe, ts, te, ci); - ci = filter_adp_k_hits(cl->list, cl->length, dp, qs, qe, ts, te, id, ci, &cmi, - aln_n?&p:NULL, sgap_rate, mm_gap); - p.self_offset = qe - 1; p.offset = te -1; - aln_n++;//[qs, qe); [ts, te) - } - // fprintf(stderr, "\n[M::%s::] q::[%ld, %ld), t::[%ld, %ld), ci::%ld\n", - // __func__, qs, qe, ts, te, ci); - ci = filter_adp_k_hits(cl->list, cl->length, dp, (uint64_t)-1, (uint64_t)-1, (uint64_t)-1, (uint64_t)-1, id, ci, &cmi, - aln_n?&p:NULL, sgap_rate, mm_gap); - for (k = cmi; k < ci; k++) cl->list[k].readID = ((uint32_t)(0x7fffffff)); -} - - -void count_k_hits_filter(overlap_region_alloc* ol, Candidates_list *cl, asg64_v* ii, Chain_Data *dp) -{ - int64_t k, on = ol->length, m = 0, i, cn = cl->length, scn; k_mer_hit *ca; - overlap_region *z; uint64_t pid; - kv_resize(uint64_t, *ii, ol->length); - for (k = 0, ii->n = 0; k < on; k++, ii->n++) { - z = &(ol->list[k]); - ii->a[ii->n] = z->shared_seed; - ii->a[ii->n] <<= 32; ii->a[ii->n] |= k; - i = z->shared_seed; pid = cl->list[i].readID; - for (; i < cn && cl->list[i].readID == pid && cl->list[i].readID != ((uint32_t)(0x7fffffff)); i++); - scn = i - z->shared_seed; ca = cl->list+z->shared_seed; - i = lchain_refine(ca, scn, ca, dp, 50, 5000, 512, 16); - for (; i < scn; i++) ca[i].readID = ((uint32_t)(0x7fffffff)); - } - radix_sort_bc64(ii->a, ii->a+ii->n); - - for (k = m = 0; k < on; k++) { - z = &(ol->list[(uint32_t)ii->a[k]]); i = z->shared_seed; - pid = cl->list[i].readID; z->shared_seed = m; - for (; i < cn && cl->list[i].readID == pid && cl->list[i].readID != ((uint32_t)(0x7fffffff)); i++) { - cl->list[m] = cl->list[i]; - cl->list[m].readID = (uint32_t)ii->a[k]; - cl->list[m].cnt = 0; - m++; - } - } - cl->length = cn = m; -} - - - -void count_k_hits_adv(All_reads *rref, const ul_idx_t *uref, char* qstr, UC_Read *buf, -overlap_region_alloc* ol, Candidates_list *cl, asg64_v* ii, Chain_Data *dp, double sgap_rate, -uint64_t khit, uint64_t basec) -{ - int64_t k, l, on = ol->length, m = 0, i, cn = cl->length, srt_n; - overlap_region *z; uint64_t t, ff, pid, *srt; char *str0 = NULL, *str1 = NULL; - kv_resize(uint64_t, *ii, ol->length); - for (k = 0, ii->n = 0; k < on; k++, ii->n++) { - ii->a[ii->n] = ol->list[k].shared_seed; - ii->a[ii->n] <<= 32; ii->a[ii->n] |= k; - refine_khits(&(ol->list[k]), cl, dp, sgap_rate); - } - radix_sort_bc64(ii->a, ii->a+ii->n); - // prt_khit(cl, ol, NULL, 109111, "a"); - for (k = m = 0; k < on; k++) { - z = &(ol->list[(uint32_t)ii->a[k]]); i = z->shared_seed; - pid = cl->list[i].readID; z->shared_seed = m; - for (; i < cn && cl->list[i].readID == pid && cl->list[i].readID != ((uint32_t)(0x7fffffff)); i++) { - cl->list[m] = cl->list[i]; - cl->list[m].readID = (uint32_t)ii->a[k]; - cl->list[m].cnt = 0; - t = cl->list[m].self_offset; t <<= 32; t |= m; - kv_push(uint64_t, (*ii), t); - // if(z->y_id == 109111) { - // fprintf(stderr, "[M::%s::m->%ld] qoff::%u, toff::%u\n", __func__, m, - // cl->list[m].self_offset, cl->list[m].offset); - // } - m++; - } - } - cl->length = cn = m; srt = ii->a+on; srt_n = ii->n-on; - // prt_khit(cl, ol, NULL, 109111, "b"); - radix_sort_bc64(srt, srt+srt_n); - if(basec) { - resize_UC_Read(buf, (khit<<1)); str0 = buf->seq; str1 = buf->seq + khit; - } - // prt_khit(cl, ol, NULL, 109111, "c"); - for (k = 1, l = 0; k <= srt_n; k++) { - if(k == cn || (srt[l]>>32) != (srt[k]>>32)) { - ff = k - l; - if(basec && ff > 1) { - if(!k_hits_bcheck(rref, uref, ol, cl, khit, srt+l, k-l, qstr, str0, str1)) ff = 1; - } - for (i = l; i < k; i++) { - cl->list[(uint32_t)srt[i]].cnt = ff; - // fprintf(stderr, "[M::%s::] pos::%u, cnt::%lu\n", __func__, - // cl->list[(uint32_t)srt[i]].self_offset, ff); - } - - l = k; - } - } - // prt_khit(cl, ol, NULL, 109111, "d"); -} - - -void count_k_hits(All_reads *rref, const ul_idx_t *uref, char* qstr, UC_Read *buf, -overlap_region_alloc* ol, Candidates_list *cl, asg64_v* ii, uint64_t khit, uint64_t basec) -{ - int64_t k, l, on = ol->length, m = 0, i, cn = cl->length, srt_n; - overlap_region *z; uint64_t t, ff, pid, *srt; char *str0 = NULL, *str1 = NULL; - kv_resize(uint64_t, *ii, ol->length); - for (k = 0, ii->n = 0; k < on; k++, ii->n++) { - ii->a[ii->n] = ol->list[k].shared_seed; - ii->a[ii->n] <<= 32; ii->a[ii->n] |= k; - } - radix_sort_bc64(ii->a, ii->a+ii->n); - - for (k = m = 0; k < on; k++) { - z = &(ol->list[(uint32_t)ii->a[k]]); i = z->shared_seed; - pid = cl->list[i].readID; z->shared_seed = m; - for (; i < cn && cl->list[i].readID == pid; i++) { - cl->list[m] = cl->list[i]; - cl->list[m].readID = (uint32_t)ii->a[k]; - cl->list[m].cnt = 0; - t = cl->list[m].self_offset; t <<= 32; t |= m; - kv_push(uint64_t, (*ii), t); - m++; - } - } - cl->length = cn = m; srt = ii->a+on; srt_n = ii->n-on; - radix_sort_bc64(srt, srt+srt_n); - if(basec) { - resize_UC_Read(buf, (khit<<1)); str0 = buf->seq; str1 = buf->seq + khit; - } - - for (k = 1, l = 0; k <= srt_n; k++) { - if(k == cn || (srt[l]>>32) != (srt[k]>>32)) { - ff = k - l; - if(basec && ff > 1) { - if(!k_hits_bcheck(rref, uref, ol, cl, khit, srt+l, k-l, qstr, str0, str1)) ff = 1; - } - for (i = l; i < k; i++) { - cl->list[(uint32_t)srt[i]].cnt = ff; - // fprintf(stderr, "[M::%s::] pos::%u, cnt::%lu\n", __func__, - // cl->list[(uint32_t)srt[i]].self_offset, ff); - } - - l = k; - } - } - - -} - - -void tuning_ext_offset(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, int64_t ql, int64_t tl, int64_t wl, -int64_t fusion_k_len, int64_t fusion_win_occ, int64_t *ch_s0, int64_t *ch_e0, int64_t *qs0, int64_t *qe0, int64_t *ts0, int64_t *te0, int64_t *mode) -{ - ///[qs, qe) - if((*mode) != 1 && (*mode) != 2) return; - int64_t qs = *qs0, qe = *qe0, ts = *ts0, te = *te0, ch_s = *ch_s0, ch_e = *ch_e0; - int64_t ke, ks, p[3], we, ws, k, wid; - int64_t sl, gq, gt, gl, gg, update, min_g = INT32_MAX, min_id = -1; - adjust_ext_offset(&qs, &qe, &ts, &te, ql, tl, 0, *mode); p[0] = p[1] = p[2] = -1; - if((*mode) == 1) {///forward extension - //qs0 and ts0 are fixed; te0 = -1, qe0 is unreliable - if(qe > (*qe0)) { - ///find k-mer hit - ke = ch_a[ch_s].self_offset; - for (ch_e = ch_s; (ch_e < ch_n) && (ch_a[ch_e].self_offset < (*qe0)); ch_e++) { - ke = ch_a[ch_e].self_offset; - } - for (ke += fusion_k_len; (ch_e < ch_n) && (ch_a[ch_e].self_offset < ke); ch_e++) { - if(ch_a[ch_e].self_offset<(*qe0)) continue; - if((ch_a[ch_e].offset<=(*ts0))||(ch_a[ch_e].self_offset<=(*qs0))) continue;//not co-linear - if(is_pri_aln(ch_a[ch_e])) { - p[2] = ch_e; break; - } else if(ch_a[ch_e].cnt > 1 && p[1] == -1) { - p[1] = ch_e; - } else if(p[0] == -1) { - p[0] = ch_e; - } - } - if(p[2] != -1) p[0] = p[2]; - else if(p[1] != -1) p[0] = p[1]; - if(p[0] != -1) { - (*mode) = 0;///global - (*qe0) = ch_a[p[0]].self_offset; (*te0) = ch_a[p[0]].offset; (*ch_e0) = p[0]; - return; - } - - ///find aligned window - we = (*qe0); we/=wl; we *= wl; we +=wl; we--; ///next window - for (k = 0; we < qe && we <= z->x_pos_e && k < fusion_win_occ; we+=wl) {//[ws, we]; [qs, qe) - wid = get_win_id_by_e(z, we, wl, NULL); - if(z->w_list.a[wid].y_end == -1) continue;//unmapped - if(z->w_list.a[wid].x_end < (*qs0)) continue; - if(z->w_list.a[wid].y_end < (*ts0)) continue; - sl = z->w_list.a[wid].x_end+1-z->w_list.a[wid].x_start; - if(z->w_list.a[wid].error > (sl/A_L)) continue; - gq = z->w_list.a[wid].x_end-(*qs0); - gt = z->w_list.a[wid].y_end-(*ts0); - gl = MIN(gq, gt); gl/=16; if(gl <= 0) gl = 1; - gg = (gq>=gt)?(gq-gt):(gt-gq); gg /= gl; - update = 0; - if(min_g>gg) { - update = 1; - } else if((min_g==gg)&&(z->w_list.a[min_id].error>z->w_list.a[wid].error)) { - update = 1; - } - if(update) { - min_g = gg; min_id = wid; - } - k++; - } - } - - if(min_id != -1) { - (*qe0) = z->w_list.a[min_id].x_end+1; - (*te0) = z->w_list.a[min_id].y_end+1; - (*mode) = 0;///global - } else { - (*qe0) = qe; (*te0) = te;//extension - } - } else if((*mode) == 2) {///backward extension - //qe0 and te0 are fixed; ts0 = -1, qs0 is unreliable - if(qs < (*qs0)) { - ///find k-mer hit - ks = ch_a[ch_e].self_offset; - for (ch_s = ch_e; (ch_s >= 0) && (ch_a[ch_s].self_offset > (*qs0)); ch_s--) { - ks = ch_a[ch_s].self_offset; - } - for (ks -= fusion_k_len; (ch_s >= 0) && (ch_a[ch_s].self_offset > ks); ch_s--) { - if(ch_a[ch_s].self_offset>(*qs0)) continue; - if((ch_a[ch_s].offset>=(*te0))||(ch_a[ch_s].self_offset>=(*qe0))) continue;//not co-linear - if(is_pri_aln(ch_a[ch_s])) { - p[2] = ch_s; break; - } else if(ch_a[ch_s].cnt > 1 && p[1] == -1) { - p[1] = ch_s; - } else if(p[0] == -1) { - p[0] = ch_s; - } - } - // fprintf(stderr, "-[M::%s::] utg%.6dl(%c), p[0]::%ld, p[1]::%ld, p[2]::%ld\n", - // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], p[0], p[1], p[2]); - if(p[2] != -1) p[0] = p[2]; - else if(p[1] != -1) p[0] = p[1]; - if(p[0] != -1) { - (*mode) = 0;///global - (*qs0) = ch_a[p[0]].self_offset; (*ts0) = ch_a[p[0]].offset; (*ch_s0) = p[0]; - return; - } - - ///find aligned window - ws = (*qs0)-1; ws/=wl; ws*=wl; - for (k = 0; ws >= qs && ws >= z->x_pos_s && k < fusion_win_occ; ws-=wl) {//[ws, we]; [qs, qe) - wid = get_win_id_by_s(z, ws, wl, NULL); - if(z->w_list.a[wid].y_end == -1) continue;//unmapped - if(z->w_list.a[wid].x_start >= (*qe0)) continue; - if(z->w_list.a[wid].y_start >= (*te0)) continue; - sl = z->w_list.a[wid].x_end+1-z->w_list.a[wid].x_start; - if(z->w_list.a[wid].error > (sl/A_L)) continue; - gq = (*qe0) - z->w_list.a[wid].x_start; - gt = (*te0) - z->w_list.a[wid].y_start; - gl = MIN(gq, gt); gl/=16; if(gl <= 0) gl = 1; - gg = (gq>=gt)?(gq-gt):(gt-gq); gg /= gl; - update = 0; - if(min_g>gg) { - update = 1; - } else if((min_g==gg)&&(z->w_list.a[min_id].error>z->w_list.a[wid].error)) { - update = 1; - } - if(update) { - min_g = gg; min_id = wid; - } - k++; - } - } - - if(min_id != -1) { - (*qs0) = z->w_list.a[min_id].x_start; - (*ts0) = z->w_list.a[min_id].y_start; - (*mode) = 0;///global - } else { - (*qs0) = qs; (*ts0) = ts; ///still extension - } - } - - if((*ch_e0) == -1) { - for ((*ch_e0)=(*ch_s0);((*ch_e0)=(*qs0))&&(ch_a[(*ch_e0)].self_offset<=(*qe0)); (*ch_e0)++); - } - - if((*ch_s0) == -1) { - for ((*ch_s0)=(*ch_e0);((*ch_s0)>=0)&&(ch_a[(*ch_s0)].self_offset>=(*qs0))&&(ch_a[(*ch_s0)].self_offset<=(*qe0)); (*ch_s0)--); - (*ch_s0)++; - } - ///boundry - for (;((*ch_e0)=(*qs0))&&(ch_a[(*ch_e0)].self_offset<=(*qe0)); (*ch_e0)++); -} - -int64_t cal_estimate_err(overlap_region *z, int64_t wl, int64_t qs, int64_t qe, double e_rate) -{ - int64_t k, ws, we, wid, os, oe, ovlp, tot, cov_l, est = (qe-qs)*e_rate, wn = z->w_list.n; - if(!wn) return est; - if(qs < z->x_pos_s) qs = z->x_pos_s; - if(qe > z->x_pos_e+1) qe = z->x_pos_e+1; - ws = qs/wl; ws *= wl; wid = get_win_id_by_s(z, ws, wl, NULL); - if(wid>=wn) wid = wn-1; - for (k = wid;k < wn && qs > z->w_list.a[k].x_end; k++); if(k == wn) return est; - ///qs <= z->w_list.a[k].x_end - for (;k>=0 && qs < z->w_list.a[k].x_start; k--); if(k < 0) k = 0; - ///qs >= z->w_list.a[k].x_start - - for (tot = cov_l = 0; k < wn && z->w_list.a[k].x_start < qe; k++) { - if(z->w_list.a[k].y_end == -1) continue; - ws = z->w_list.a[k].x_start; we = z->w_list.a[k].x_end+1; - os = MAX(qs, ws); oe = MIN(qe, we); - ovlp = ((oe>os)? (oe-os):0); - if(!ovlp) continue; - cov_l += ovlp; - // if(!ovlp) { - // fprintf(stderr, "\n[M::%s::] utg%.6dl(%c), q::[%ld, %ld), w::[%ld, %ld), z::::[%d, %d)\n", - // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], qs, qe, ws, we, z->x_pos_s, z->x_pos_e+1); - // } - if(ovlp == (we-ws)) { - tot += z->w_list.a[k].error; - } else { - tot += ((double)z->w_list.a[k].error)*((double)ovlp)/((double)(we-ws)); - } - } - tot += ((qe-qs)-cov_l)*e_rate; - return tot; -} - -int64_t cal_estimate_err_hc(overlap_region *z, int64_t wl, int64_t qs, int64_t qe, int64_t ts, int64_t te, double e_rate, int64_t *exact) -{ - int64_t k, ws, we, wid, os, oe, ovlp, tot, cov_l, est = (qe-qs)*e_rate, wn = z->w_list.n, exa = 1, ots, ote, q[2], t[2]; - if(exact) (*exact) = 0; - if(!wn) return est; - if(qs < z->x_pos_s) qs = z->x_pos_s; - if(qe > z->x_pos_e+1) qe = z->x_pos_e+1; - ws = qs/wl; ws *= wl; wid = get_win_id_by_s(z, ws, wl, NULL); - if(wid>=wn) wid = wn-1; - for (k = wid;k < wn && qs > z->w_list.a[k].x_end; k++); if(k == wn) return est; - ///qs <= z->w_list.a[k].x_end - for (;k>=0 && qs < z->w_list.a[k].x_start; k--); if(k < 0) k = 0; - ///qs >= z->w_list.a[k].x_start - - for (tot = cov_l = 0, ots = ote = -1; k < wn && z->w_list.a[k].x_start < qe; k++) { - if(z->w_list.a[k].y_end == -1) continue; - ws = z->w_list.a[k].x_start; we = z->w_list.a[k].x_end+1; - os = MAX(qs, ws); oe = MIN(qe, we); - ovlp = ((oe>os)? (oe-os):0); - if(!ovlp) continue; - cov_l += ovlp; - - if(ovlp == (we-ws)) { - tot += z->w_list.a[k].error; - } else { - tot += ((double)z->w_list.a[k].error)*((double)ovlp)/((double)(we-ws)); - } - if(z->w_list.a[k].error > 0) exa = 0; - if(exa) { - q[0] = os - ws; q[1] = we - oe; - we = z->w_list.a[k].y_end+1; ws = we - (z->w_list.a[k].x_end+1-z->w_list.a[k].x_start); - os = MAX(ts, ws); oe = MIN(te, we); - ovlp = ((oe>os)? (oe-os):0); - t[0] = os - ws; t[1] = we - oe; - if((ovlp) && (q[0] == t[0]) && (t[0] == t[0])) { - if(ote == -1) { - ots = os; ote = oe; - } else if(ote == os) { - ote = oe; - } else { - exa = 0; - } - } else { - exa = 0; - } - } - } - tot += ((qe-qs)-cov_l)*e_rate; - if((exact) && exa && (((qe-qs) == cov_l))) { - if(((qe-qs) == (ote - ots)) && (ots == ts) && (ote == te)) (*exact) = 1; - } - return tot; -} - - -///[s, e); [ps, pe) -inline char *retrieve_str_seq_exz(UC_Read *tu, int64_t s, int64_t l, -int64_t ps, int64_t pl, uint8_t rev, const ul_idx_t *uref, hpc_t *hpc_g, -All_reads *rref, int64_t id) -{ - if(!hpc_g) { - char *str; int64_t ss = s, sl = l; tu->length = l; - UC_Read_resize(*tu, sl); str = tu->seq; - if(s == ps) { - if(l <= pl) return tu->seq; - str = tu->seq + pl; ss = ps + pl; sl = l - pl; - } - if(uref) { - retrieve_u_seq(NULL, str, &(uref->ug->u.a[id]), rev, ss, sl, NULL); - } else if(rref) { - recover_UC_Read_sub_region(str, ss, sl, rev, rref, id); - } - return tu->seq; - } else { - return hpc_str(*hpc_g, id, rev) + s; - } -} - -void cal_exz_global(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) -{ - int32_t bd, nword; - bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); - - if(nword <= 1) { - ed_band_cal_global_64_w_trace(pstr, pn, tstr, tn, thre, ez); - } else if(nword == 2) { - ed_band_cal_global_128_w_trace(pstr, pn, tstr, tn, thre, ez); - } else { - ed_band_cal_global_infi_w_trace(pstr, pn, tstr, tn, thre, &nword, ez); - } -} - -void cal_exz_global_simi(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) -{ - int32_t bd, nword; - bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); - - if(nword <= 1) { - ed_band_cal_global_64_w(pstr, pn, tstr, tn, thre, ez); - } else if(nword == 2) { - ed_band_cal_global_128_w(pstr, pn, tstr, tn, thre, ez); - } else { - ed_band_cal_global_infi_w(pstr, pn, tstr, tn, thre, &nword, ez); - } -} - -void cal_exz_extension_0(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) -{ - int32_t bd, nword; - bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); - - if(nword <= 1) { - ed_band_cal_extension_64_0_w_trace(pstr, pn, tstr, tn, thre, ez); - } else if(nword == 2) { - ed_band_cal_extension_128_0_w_trace(pstr, pn, tstr, tn, thre, ez); - } else { - ed_band_cal_extension_infi_0_w_trace(pstr, pn, tstr, tn, thre, &nword, ez); - } -} - -void cal_exz_extension_0_simi(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) -{ - int32_t bd, nword; - bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); - - if(nword <= 1) { - ed_band_cal_extension_64_0_w(pstr, pn, tstr, tn, thre, ez); - } else if(nword == 2) { - ed_band_cal_extension_128_0_w(pstr, pn, tstr, tn, thre, ez); - } else { - ed_band_cal_extension_infi_0_w(pstr, pn, tstr, tn, thre, &nword, ez); - } -} - -void cal_exz_extension_1(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) -{ - int32_t bd, nword; - bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); - - if(nword <= 1) { - ed_band_cal_extension_64_1_w_trace(pstr, pn, tstr, tn, thre, ez); - } else if(nword == 2) { - ed_band_cal_extension_128_1_w_trace(pstr, pn, tstr, tn, thre, ez); - } else { - ed_band_cal_extension_infi_1_w_trace(pstr, pn, tstr, tn, thre, &nword, ez); - } -} - -void cal_exz_extension_1_simi(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) -{ - int32_t bd, nword; - bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); - - if(nword <= 1) { - ed_band_cal_extension_64_1_w(pstr, pn, tstr, tn, thre, ez); - } else if(nword == 2) { - ed_band_cal_extension_128_1_w(pstr, pn, tstr, tn, thre, ez); - } else { - ed_band_cal_extension_infi_1_w(pstr, pn, tstr, tn, thre, &nword, ez); - } -} - -void cal_exz_semi(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t aux_beg, bit_extz_t *ez) -{ - int32_t bd, nword; - bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); - - if(nword <= 1) { - ed_band_cal_semi_64_w_absent_diag_trace(pstr, pn, tstr, tn, thre, aux_beg, ez); - } else if(nword == 2) { - ed_band_cal_semi_128_w_absent_diag_trace(pstr, pn, tstr, tn, thre, aux_beg, ez); - } else { - ed_band_cal_semi_infi_w_absent_diag_trace(pstr, pn, tstr, tn, thre, aux_beg, &nword, ez); - } -} - -void cal_exz_semi_simi(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t aux_beg, bit_extz_t *ez) -{ - int32_t bd, nword; - bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); - - if(nword <= 1) { - ed_band_cal_semi_64_w_absent_diag(pstr, pn, tstr, tn, thre, aux_beg, ez); - } else if(nword == 2) { - ed_band_cal_semi_128_w_absent_diag(pstr, pn, tstr, tn, thre, aux_beg, ez); - } else { - ed_band_cal_semi_infi_w_absent_diag(pstr, pn, tstr, tn, thre, aux_beg, &nword, ez); - } -} - -void ref_cigar_check(char* qstr, UC_Read *tu, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, int64_t id, int64_t rev, bit_extz_t *ez) -{ - int64_t pts = -1, pte = -1, tl = ez->pe-ez->ps+1, ql = ez->te-ez->ts+1, bps, bts, k; - char *q, *t; bps = ez->ps; bts = ez->ts; - - q = qstr + ez->ts; - t = retrieve_str_seq_exz(tu, ez->ps, tl, pts, pte-pts, rev, uref, hpc_g, rref, id); - ez->ps = ez->ts = 0; - if(!cigar_check(t, q, ez)){ - fprintf(stderr, "[M::%s::] cigar_n::%d\n", __func__, (int32_t)ez->cigar.n); - for (k = 0; k < (int32_t)ez->cigar.n; k++) { - fprintf(stderr, "[M::%s::%ld] cigar_len::%u, c::%u\n", __func__, k, - ez->cigar.a[k]&(0x3fff), (ez->cigar.a[k]>>14)); - } - - // fprintf(stderr, "[M::%s::l->%ld] s::%ld, pstr::%.*s\n", __func__, tl, bps, (int32_t)tl, t); - // fprintf(stderr, "[M::%s::l->%ld] s::%ld, tstr::%.*s\n", __func__, ql, bts, (int32_t)ql, q); - fprintf(stderr, "[M::%s::l->%ld] s::%ld\n", __func__, tl, bps); - fprintf(stderr, "[M::%s::l->%ld] s::%ld\n", __func__, ql, bts); - exit(1); - } - ez->ps = bps; ez->ts = bts; -} - -int64_t cal_exz_infi_adv(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, -bit_extz_t *exz, char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, -int64_t *pts, int64_t *pte, int64_t thre, int64_t *pthre, int64_t q_tot_l, int64_t mode) -{ - clear_align(*exz); - int64_t aux_beg = 0, ql, tl, t_tot_l = -1, dd; - char *q_string, *t_string; int32_t rev = z->y_pos_strand, id = z->y_id; - ql = qe - qs; tl = te - ts; dd = MAX(ql, tl); - if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); - else if(uref) t_tot_l = uref->ug->u.a[id].len; - else t_tot_l = Get_READ_LENGTH((*rref), id); - - if(mode == 3) { - update_semi_coord(uref, hpc_g, rref, z, qs, qe, ((thre>dd)?dd:thre), &ts, &te, &aux_beg); - } else if(mode == 1 || mode == 2) { - adjust_ext_offset(&qs, &qe, &ts, &te, q_tot_l, t_tot_l, ((thre>dd)?dd:thre), mode); - } - - if((qe > qs) && (te > ts) && (ts != -1) && (te != -1)) { - ql = qe - qs; tl = te - ts; - dd = MAX(ql, tl); - if(thre > dd) thre = dd; - if(thre <= (*pthre)) return 0; - (*pthre) = thre; - - q_string = qstr + qs; - t_string = retrieve_str_seq_exz(tu, ts, tl, (*pts), (*pte)-(*pts), rev, uref, hpc_g, rref, id); - (*pts) = ts; (*pte) = te; - - if(mode == 0) { //global - cal_exz_global(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 1) {///forward extension - cal_exz_extension_0(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 2) {///backward extension - cal_exz_extension_1(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 3) {//semi-global - cal_exz_semi(t_string, tl, q_string, ql, thre, aux_beg, exz); - } - - if(is_align(*exz)) { - // cigar_check(t_string, q_string, exz); - // if(mode == 1) { - // fprintf(stderr, "\n[M::%s::ql::%ld] qs::%ld, qe::%ld, ts::%ld, te::%ld, mode::%ld, err::%d, thre::%d, exz_q[%d, %d], exz_t[%d, %d]\n", - // __func__, ql, qs, qe, ts, te, mode, exz->err, exz->thre, exz->ts, exz->te, exz->ps, exz->pe); - // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tl, t_string); - // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)ql, q_string); - // fprintf(stderr, "[M::%s::] exz->cigar.n::%d\n", __func__, (int32_t)exz->cigar.n); - // } - exz->ps += ts; exz->pe += ts; - exz->ts += qs; exz->te += qs; - return 1; - } - return 0; - } - return 0; -} - - -int64_t cal_exz_infi_non_retrieve_adv(overlap_region *z, bit_extz_t *exz, char* qstr, char* tstr, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t thre, int64_t *pthre, int64_t q_tot_l, int64_t t_tot_l, int64_t mode) -{ - clear_align(*exz); - int64_t aux_beg = 0, ql, tl, dd; char *q_string, *t_string; - ql = qe - qs; tl = te - ts; dd = MAX(ql, tl); - - if(mode == 3) { - update_semi_non_retrieve_coord(z, qs, qe, ((thre>dd)?dd:thre), t_tot_l, &ts, &te, &aux_beg); - } else if(mode == 1 || mode == 2) { - adjust_ext_offset(&qs, &qe, &ts, &te, q_tot_l, t_tot_l, ((thre>dd)?dd:thre), mode); - } - - if((qe > qs) && (te > ts) && (ts != -1) && (te != -1)) { - ql = qe - qs; tl = te - ts; - dd = MAX(ql, tl); - if(thre > dd) thre = dd; - if(thre <= (*pthre)) return 0; - (*pthre) = thre; - - q_string = qstr + qs; t_string = tstr + ts; - - if(mode == 0) { //global - cal_exz_global(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 1) {///forward extension - cal_exz_extension_0(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 2) {///backward extension - cal_exz_extension_1(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 3) {//semi-global - cal_exz_semi(t_string, tl, q_string, ql, thre, aux_beg, exz); - } - - if(is_align(*exz)) { - // cigar_check(t_string, q_string, exz); - // if(mode == 1) { - // fprintf(stderr, "\n[M::%s::ql::%ld] qs::%ld, qe::%ld, ts::%ld, te::%ld, mode::%ld, err::%d, thre::%d, exz_q[%d, %d], exz_t[%d, %d]\n", - // __func__, ql, qs, qe, ts, te, mode, exz->err, exz->thre, exz->ts, exz->te, exz->ps, exz->pe); - // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tl, t_string); - // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)ql, q_string); - // fprintf(stderr, "[M::%s::] exz->cigar.n::%d\n", __func__, (int32_t)exz->cigar.n); - // } - exz->ps += ts; exz->pe += ts; - exz->ts += qs; exz->te += qs; - return 1; - } - return 0; - } - return 0; -} - - -int64_t cal_exact_exz(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, -bit_extz_t *exz, char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, -int64_t *pts, int64_t *pte, int64_t q_tot_l, int64_t mode) -{ - clear_align(*exz); exz->thre = 0; exz->cigar.n = 0; - int64_t ql, tl, t_tot_l = -1; - char *q_string, *t_string; int32_t rev = z->y_pos_strand, id = z->y_id; ql = qe - qs; - if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); - else if(uref) t_tot_l = uref->ug->u.a[id].len; - else t_tot_l = Get_READ_LENGTH((*rref), id); - - if(mode == 3) {//semi - ts = (qs - z->x_pos_s) + z->y_pos_s; ts += y_start_offset(qs, &(z->f_cigar)); - te = ts + ql; - } else if(mode == 1) {///forward extension - te = ts + ql; - } else if(mode == 2) {///backward extension - ts = te - ql; - } - if(ts < 0) ts = 0; - if(ts > t_tot_l) ts = t_tot_l; - if(te > t_tot_l) te = t_tot_l; - ql = qe - qs; tl = te - ts; - if(ql != tl) return 0; - - q_string = qstr + qs; - t_string = retrieve_str_seq_exz(tu, ts, tl, (*pts), (*pte)-(*pts), rev, uref, hpc_g, rref, id); - (*pts) = ts; (*pte) = te; - - if(memcmp(q_string, t_string, ql)) return 0; - exz->err = 0; push_trace(&(exz->cigar), 0, ql); - exz->pl = tl; exz->ps = 0; exz->pe = tl-1; - exz->tl = ql; exz->ts = 0; exz->te = ql-1; - // cigar_check(t_string, q_string, exz); - // if(!cigar_check(t_string, q_string, exz)) { - // fprintf(stderr, "[M::%s::] cigar_n::%d\n", __func__, (int32_t)exz->cigar.n); - // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tl, t_string); - // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)ql, q_string); - // } - exz->ps += ts; exz->pe += ts; - exz->ts += qs; exz->te += qs; - return 1; -} - -int64_t cal_exact_non_retrieve_exz(overlap_region *z, bit_extz_t *exz, char* qstr, char* tstr, int64_t qs, int64_t qe, int64_t ts, int64_t te, -int64_t q_tot_l, int64_t t_tot_l, int64_t mode) -{ - clear_align(*exz); exz->thre = 0; exz->cigar.n = 0; - int64_t ql, tl; - char *q_string, *t_string; ql = qe - qs; - // if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); - // else if(uref) t_tot_l = uref->ug->u.a[id].len; - // else t_tot_l = Get_READ_LENGTH((*rref), id); - - if(mode == 3) {//semi - ts = (qs - z->x_pos_s) + z->y_pos_s; ts += y_start_offset(qs, &(z->f_cigar)); - te = ts + ql; - } else if(mode == 1) {///forward extension - te = ts + ql; - } else if(mode == 2) {///backward extension - ts = te - ql; - } - if(ts < 0) ts = 0; - if(ts > t_tot_l) ts = t_tot_l; - if(te > t_tot_l) te = t_tot_l; - ql = qe - qs; tl = te - ts; - if(ql != tl) return 0; - - q_string = qstr + qs; t_string = tstr + ts; - - if(memcmp(q_string, t_string, ql)) return 0; - exz->err = 0; push_trace(&(exz->cigar), 0, ql); - exz->pl = tl; exz->ps = 0; exz->pe = tl-1; - exz->tl = ql; exz->ts = 0; exz->te = ql-1; - // cigar_check(t_string, q_string, exz); - // if(!cigar_check(t_string, q_string, exz)) { - // fprintf(stderr, "[M::%s::] cigar_n::%d\n", __func__, (int32_t)exz->cigar.n); - // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tl, t_string); - // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)ql, q_string); - // } - exz->ps += ts; exz->pe += ts; - exz->ts += qs; exz->te += qs; - return 1; -} - -//[qmin, qmax) && [tmin, tmax) -void adjust_ext_offset_fixed_t(int64_t *qs, int64_t *qe, int64_t *ts, int64_t *te, -int64_t qmin, int64_t qmax, int64_t tmin, int64_t tmax, int64_t thre, int64_t mode) -{ - int64_t qoff, toff; - if(mode == 1) {///forward extension - qoff = qmax - (*qs); toff = tmax - (*ts); - if(qoff <= toff) { - (*qe) = qmax; (*te) = (*ts) + qoff + thre; - } else { - (*te) = tmax; (*qe) = (*qs) + toff + thre; - } - } else if(mode == 2) {///backward extension - qoff = (*qe) - qmin; toff = (*te) - tmin; - if(qoff <= toff) { - (*qs) = qmin; (*ts) = (*te) - qoff - thre; - } else { - (*ts) = tmin; (*qs) = (*qe) - toff - thre; - } - } - if((*qs) < qmin) (*qs) = qmin; - if((*ts) < tmin) (*ts) = tmin; - if((*qe) > qmax) (*qe) = qmax; - if((*te) > tmax) (*te) = tmax; -} - - - -int64_t cal_exz_infi_simi_adv(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, -bit_extz_t *exz, char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, -int64_t *pts, int64_t *pte, int64_t thre, int64_t *pthre, int64_t qmin, int64_t qmax, -int64_t tmin, int64_t tmax, int32_t rev, int32_t id, int64_t mode, overlap_region *z, -int64_t gen_trace) -{ ///mode cannot be 3 - clear_align(*exz); - int64_t aux_beg = 0, ql, tl, dd; char *q_string, *t_string; - ql = qe - qs; tl = te - ts; dd = MAX(ql, tl); - if(mode == 3 && z) { - update_semi_coord(uref, hpc_g, rref, z, qs, qe, ((thre>dd)?dd:thre), &ts, &te, &aux_beg); - } else if(mode == 1 || mode == 2) { - adjust_ext_offset_fixed_t(&qs, &qe, &ts, &te, qmin, qmax, tmin, tmax, ((thre>dd)?dd:thre), mode); - } - - // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { - // fprintf(stderr, "[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), thre::%ld, pthre::%ld\n", - // __func__, mode, qs, qe, ts, te, thre, *pthre); - // } - - if((qe > qs) && (te > ts) && (ts != -1) && (te != -1)) { - ql = qe - qs; tl = te - ts; - dd = MAX(ql, tl); - if(thre > dd) thre = dd; - // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { - // fprintf(stderr, "[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), thre::%ld, pthre::%ld\n", - // __func__, mode, qs, qe, ts, te, thre, *pthre); - // } - if(thre <= (*pthre)) return 0; - (*pthre) = thre; - - q_string = qstr + qs; - t_string = retrieve_str_seq_exz(tu, ts, tl, (*pts), (*pte)-(*pts), rev, uref, hpc_g, rref, id); - (*pts) = ts; (*pte) = te; - - if(!gen_trace) { - if(mode == 0) { //global - cal_exz_global_simi(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 1) {///forward extension - cal_exz_extension_0_simi(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 2) {///backward extension - cal_exz_extension_1_simi(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 3) {//semi-global; mode cannot be 3 - cal_exz_semi_simi(t_string, tl, q_string, ql, thre, aux_beg, exz); - } - } else { - if(mode == 0) { //global - cal_exz_global(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 1) {///forward extension - cal_exz_extension_0(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 2) {///backward extension - cal_exz_extension_1(t_string, tl, q_string, ql, thre, exz); - } else if(mode == 3) {//semi-global - cal_exz_semi(t_string, tl, q_string, ql, thre, aux_beg, exz); - } - } - - - if(is_align(*exz)) { - exz->ps += ts; exz->pe += ts; - exz->ts += qs; exz->te += qs; - // if(exz->ps == 18327 && exz->pe + 1 == 18601 && exz->ts == 145990 && exz->te + 1 == 146191) { - // fprintf(stderr, "[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld)\n", - // __func__, mode, qs, qe, ts, te); - // fprintf(stderr, "[M::%s::] q_string::%.*s\n", __func__, (int32_t)ql, q_string); - // fprintf(stderr, "[M::%s::] t_string::%.*s\n", __func__, (int32_t)tl, t_string); - // } - return 1; - } - // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { - // fprintf(stderr, "[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld)\n", - // __func__, mode, qs, qe, ts, te); - // fprintf(stderr, "[M::%s::] q_string::%.*s\n", __func__, (int32_t)ql, q_string); - // fprintf(stderr, "[M::%s::] t_string::%.*s\n", __func__, (int32_t)tl, t_string); - // } - return 0; - } - return 0; -} - -int64_t cal_exact_simi_exz(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, -bit_extz_t *exz, char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, -int64_t *pts, int64_t *pte, int64_t q_tot_l, int64_t t_tot_l, int32_t rev, int32_t id, -int64_t mode, overlap_region *z) -{ - clear_align(*exz); exz->thre = 0; exz->cigar.n = 0; - int64_t ql, tl; char *q_string, *t_string; ql = qe - qs; - - if(mode == 3 && z) {//semi - ts = (qs - z->x_pos_s) + z->y_pos_s; ts += y_start_offset(qs, &(z->f_cigar)); - te = ts + ql; - } else if(mode == 1) {///forward extension - te = ts + ql; - } else if(mode == 2) {///backward extension - ts = te - ql; - } - if(ts < 0) ts = 0; - if(ts > t_tot_l) ts = t_tot_l; - if(te > t_tot_l) te = t_tot_l; - ql = qe - qs; tl = te - ts; - if(ql != tl) return 0; - - q_string = qstr + qs; - t_string = retrieve_str_seq_exz(tu, ts, tl, (*pts), (*pte)-(*pts), rev, uref, hpc_g, rref, id); - (*pts) = ts; (*pte) = te; - - if(memcmp(q_string, t_string, ql)) return 0; - exz->err = 0; push_trace(&(exz->cigar), 0, ql); - exz->pl = tl; exz->ps = 0; exz->pe = tl-1; - exz->tl = ql; exz->ts = 0; exz->te = ql-1; - - exz->ps += ts; exz->pe += ts; - exz->ts += qs; exz->te += qs; - return 1; -} - - -void append_wcigar(window_list *idx, window_list_alloc *res, bit_extz_t *exz) -{ - // fprintf(stderr, "[M::%s::] idx->cidx::%u, idx->clen::%u, res->c.n_0::%u, exz->cigar.n::%u, ", - // __func__, idx->cidx, idx->clen, (uint32_t)res->c.n, (uint32_t)exz->cigar.n); - if(idx->clen > 0) { - // if(!(idx->cidx+idx->clen == res->c.n)) { - // fprintf(stderr, "[M::%s::] idx->cidx::%u, idx->clen::%u, res->c.n::%u\n", - // __func__, idx->cidx, idx->clen, (uint32_t)res->c.n); - // } - assert(idx->cidx+idx->clen == res->c.n); - if(exz->cigar.n > 0) { - uint16_t c0, c; uint32_t l0, l, ci = 0, cn; - ///last item of old cigar - c0 = (res->c.a[res->c.n-1]>>14); l0 = (res->c.a[res->c.n-1]&(0x3fff)); - ///first item of new cigar - ci = pop_trace(&(exz->cigar), ci, &c, &l); - if(c0 == c) {l += l0; res->c.n--; idx->clen--;} - push_trace(((asg16_v *)(&(res->c))), c, l); - idx->clen = res->c.n-idx->cidx; - - cn = exz->cigar.n-ci; - if(cn > 0) { - kv_resize(uint16_t, res->c, (res->c.n+cn)); - memcpy(res->c.a+res->c.n, exz->cigar.a+ci, cn*sizeof(*(res->c.a))); - idx->clen += cn; res->c.n += cn; - } - } - } else { - push_wcigar(idx, res, exz);///if exz is the first item - } - // fprintf(stderr, "[M::%s::] res->c.n::%u\n", __func__, (uint32_t)res->c.n); -} - -void push_alnw(overlap_region *aux_o, bit_extz_t *exz) -{ - window_list *p = NULL; int64_t t; - if(aux_o->w_list.n > 0) { - p = &(aux_o->w_list.a[aux_o->w_list.n-1]); - // fprintf(stderr, "+[M::%s::wn->%d] px::[%d, %d], py::[%d, %d], pe::%d, exz->t::[%u, %u], exz->p::[%u, %u], exz->e::%d, clen::%u\n", - // __func__, (int32_t)(aux_o->w_list.n), p->x_start, p->x_end, p->y_start, p->y_end, p->error, - // exz->ts, exz->te, exz->ps, exz->pe, exz->err, p->clen); - // assert((p->x_endts)&&(p->y_endps)); - - if(p->clen > 0) { - t = ((int64_t)p->error) + ((int64_t)exz->err); - ///note: t cannot be equal to INT16_MAX; otherwise it is unable to distiguish unaligned regions - if(((p->x_end+1) == exz->ts) && ((p->y_end+1) == exz->ps) && (t < INT16_MAX)) { - p->x_end = exz->te; p->y_end = exz->pe; p->error += exz->err; - append_wcigar(p, &(aux_o->w_list), exz); - // fprintf(stderr, "-[M::%s::wn->%d] px::[%d, %d], py::[%d, %d], pe::%d, exz->t::[%u, %u], exz->p::[%u, %u], exz->e::%d, clen::%u\n", - // __func__, (int32_t)(aux_o->w_list.n), p->x_start, p->x_end, p->y_start, p->y_end, p->error, - // exz->ts, exz->te, exz->ps, exz->pe, exz->err, p->clen); - return; - } - } - } - // fprintf(stderr, "[M::%s::wn->%d] exz->t::[%u, %u], exz->p::[%u, %u], exz->e::%d\n", - // __func__, (int32_t)(aux_o->w_list.n), exz->ts, exz->te, exz->ps, exz->pe, exz->err); - kv_pushp(window_list, aux_o->w_list, &p); - p->x_start = exz->ts; p->x_end = exz->te; - p->y_start = exz->ps; p->y_end = exz->pe; - p->error_threshold = 0; p->error = exz->err;///single round of alignment cannot have INT16_MAX errors - push_wcigar(p, &(aux_o->w_list), exz); -} - -///[qs, qe] && [ts, te] -void push_unmap_alnw(overlap_region *aux_o, int32_t qs, int64_t qe, int64_t ts, int64_t te, int64_t mode) -{ - window_list *p = NULL; - kv_pushp(window_list, aux_o->w_list, &p); - p->x_start = qs; p->x_end = qe; - p->y_start = ts; p->y_end = te; - p->error_threshold = mode; p->error = INT16_MAX; - p->extra_begin = p->extra_end = -1; - p->cidx = p->clen = 0; -} - -///[qs, qe] && [ts, te] -void push_replace_alnw(overlap_region *aux_o, int32_t qs, int64_t qe, int64_t ts, int64_t te, int64_t mode) -{ - window_list *p = NULL; - kv_pushp(window_list, aux_o->w_list, &p); - p->x_start = qs; p->x_end = qe; - p->y_start = ts; p->y_end = te; - p->error_threshold = mode; p->error = 0; - p->extra_begin = p->extra_end = 0; - p->cidx = p->clen = 0; -} - -///[qs, qe] && [ts, te] -void push_replace_alnw_adv(overlap_region *z, int64_t wl, overlap_region *aux_o, int32_t qs, int64_t qe, int64_t ts, int64_t te, int64_t mode) -{ - int64_t k, wsk, wek, err, t; window_list *p = NULL; - wsk = get_win_id_by_s(z, qs, wl, NULL); assert(z->w_list.a[wsk].x_start == qs); - wek = get_win_id_by_s(z, qe+1, wl, NULL); assert(z->w_list.a[wek].x_end == (qe+1)); - kv_pushp(window_list, aux_o->w_list, &p); - p->x_start = p->x_end = qs; - p->y_start = p->y_end = ts; - p->error_threshold = mode; p->error = 0; - p->extra_begin = p->extra_end = 0; - p->cidx = p->clen = 0; err = 0; - - for (k = wsk; k <= wek; k++) { - assert(z->w_list.a[k].y_end != -1); - t = err + z->w_list.a[k].error; - if(t < INT16_MAX) {///note: t cannot be equal to INT16_MAX; otherwise it is unable to distiguish unaligned regions - err += z->w_list.a[k].error; - p->x_end = z->w_list.a[k].x_end; - p->y_end = z->w_list.a[k].y_end; - } else { - err = z->w_list.a[k].error; - kv_pushp(window_list, aux_o->w_list, &p); - p->x_start = z->w_list.a[k].x_start; - p->x_end = z->w_list.a[k].x_end; - p->y_start = z->w_list.a[k].y_start; - p->y_end = z->w_list.a[k].y_end; - p->error_threshold = mode; - p->extra_begin = p->extra_end = 0; - p->cidx = p->clen = 0; - } - p->error = err; - } - p->x_end = qe; p->y_end = te; -} - - - -int64_t hc_aln_exz_adv(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, -char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t mode, int64_t wl, -bit_extz_t *exz, int64_t q_tot, double e_rate, int64_t maxl, int64_t maxe, int64_t force_l, -int64_t estimate_err, overlap_region *aux_o) -{ - clear_align(*exz); exz->thre = 0; - if(((ts == -1) && (te == -1))) mode = 3;///set to semi-global - int64_t thre, ql = qe - qs, thre0, pts = -1, pte = -1, pthre = -1; - if(ql == 0 && (te-ts) == 0) return 1; - if((ql <= 0) || (te-ts) <= 0) return 0; - if(estimate_err < 0) { - if(ql > wl) estimate_err = cal_estimate_err(z, wl, qs, qe, e_rate); - else estimate_err = ql*e_rate; - } - - - // fprintf(stderr, "[M::%s::ql::%ld] qs::[%ld, %ld), ts::[%ld, %ld), mode::%ld, est_err::%ld, e_rate::%f, maxe::%ld", - // __func__, ql, qs, qe, ts, te, mode, estimate_err, e_rate, maxe); - if(ql <= 16) { - if(cal_exact_exz(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, q_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::0(+)\n", exz->err, exz->thre); - push_alnw(aux_o, exz); - return 1; - } - } - - if(ql <= maxl && (estimate_err>>1) <= maxe) { - thre = scale_ed_thre(estimate_err, maxe); - if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(+)\n", exz->err, exz->thre, thre); - push_alnw(aux_o, exz); - return 1; - } - - thre0 = thre; thre = ql*e_rate; thre = scale_ed_thre(thre, maxe); - if(thre > thre0) { - if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); - push_alnw(aux_o, exz); - return 1; - } - } - - thre0 = thre; thre <<= 1; thre = scale_ed_thre(thre, maxe); - if(thre > thre0) { - if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); - push_alnw(aux_o, exz); - return 1; - } - } - - thre0 = thre; thre = ql*0.51; thre = scale_ed_thre(thre, maxe); - if(thre > thre0) { - if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); - push_alnw(aux_o, exz); - return 1; - } - } - - if(ql <= force_l) { - thre = maxe; - if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); - push_alnw(aux_o, exz); - return 1; - } - } - } - // fprintf(stderr, ", err::%d, thre::%d\n", INT32_MAX, exz->thre); - // if(mode == 0) { - // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tu->length, tu->seq); - // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)(qe-qs), qstr+qs); - // } - return 0; - -} - -void set_exact_exz(bit_extz_t *exz, int64_t qs, int64_t qe, int64_t ts, int64_t te) -{ - clear_align(*exz); exz->thre = 0; exz->cigar.n = 0; - exz->err = 0; push_trace(&(exz->cigar), 0, qe - qs); - exz->pl = te - ts; exz->ps = 0; exz->pe = exz->pl-1; - exz->tl = qe - qs; exz->ts = 0; exz->te = exz->tl-1; - exz->ps += ts; exz->pe += ts; - exz->ts += qs; exz->te += qs; -} - - -int64_t hc_aln_exz_adv_hc(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, -char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t mode, int64_t wl, -bit_extz_t *exz, int64_t q_tot, double e_rate, int64_t maxl, int64_t maxe, int64_t force_l, -int64_t estimate_err, overlap_region *aux_o) -{ - clear_align(*exz); exz->thre = 0; - if(((ts == -1) && (te == -1))) mode = 3;///set to semi-global - int64_t thre, ql = qe - qs, thre0, pts = -1, pte = -1, pthre = -1, full = 0; - if(ql == 0 && (te-ts) == 0) return 1; - if((ql <= 0) || (te-ts) <= 0) return 0; - if(estimate_err < 0) estimate_err = cal_estimate_err_hc(z, wl, qs, qe, ts, te, e_rate, &full); - - - - // if(ql <= 16) { - if(estimate_err == 0) { - if(full) { - // if(!cal_exact_exz(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, q_tot, mode)) { - // fprintf(stderr, "[M::%s::ql::%ld::%c] xid::%d, yid::%d, qs::[%ld, %ld), ts::[%ld, %ld), mode::%ld, est_err::%ld, e_rate::%f, maxe::%ld\n", - // __func__, ql, "+-"[z->y_pos_strand], z->x_id, z->y_id, qs, qe, ts, te, mode, estimate_err, e_rate, maxe); - // exit(1); - // } - set_exact_exz(exz, qs, qe, ts, te); push_alnw(aux_o, exz); - return 1; - } else if(cal_exact_exz(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, q_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::0(+)\n", exz->err, exz->thre); - push_alnw(aux_o, exz); - return 1; - } - } - - if(ql <= maxl && (estimate_err>>1) <= maxe) { - thre = scale_ed_thre(estimate_err, maxe); - if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(+)\n", exz->err, exz->thre, thre); - push_alnw(aux_o, exz); - return 1; - } - - thre0 = thre; thre = ql*e_rate; thre = scale_ed_thre(thre, maxe); - if(thre > thre0) { - if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); - push_alnw(aux_o, exz); - return 1; - } - } - - thre0 = thre; thre <<= 1; thre = scale_ed_thre(thre, maxe); - if(thre > thre0) { - if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); - push_alnw(aux_o, exz); - return 1; - } - } - - thre0 = thre; thre = ql*0.51; thre = scale_ed_thre(thre, maxe); - if(thre > thre0) { - if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); - push_alnw(aux_o, exz); - return 1; - } - } - - if(ql <= force_l) { - thre = maxe; - if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); - push_alnw(aux_o, exz); - return 1; - } - } - } - // fprintf(stderr, ", err::%d, thre::%d\n", INT32_MAX, exz->thre); - // if(mode == 0) { - // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tu->length, tu->seq); - // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)(qe-qs), qstr+qs); - // } - return 0; - -} - -int64_t hc_aln_exz_non_retrieve_adv_hc(overlap_region *z, char* qstr, char* tstr, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t mode, int64_t wl, -bit_extz_t *exz, int64_t q_tot, int64_t t_tot, double e_rate, int64_t maxl, int64_t maxe, int64_t force_l, int64_t estimate_err, overlap_region *aux_o) -{ - clear_align(*exz); exz->thre = 0; - if(((ts == -1) && (te == -1))) mode = 3;///set to semi-global - int64_t thre, ql = qe - qs, thre0, pthre = -1, full = 0; - if(ql == 0 && (te-ts) == 0) return 1; - if((ql <= 0) || (te-ts) <= 0) return 0; - if(estimate_err < 0) estimate_err = cal_estimate_err_hc(z, wl, qs, qe, ts, te, e_rate, &full); - - - - // if(ql <= 16) { - if(estimate_err == 0) { - if(full) { - // if(!cal_exact_exz(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, q_tot, mode)) { - // fprintf(stderr, "[M::%s::ql::%ld::%c] xid::%d, yid::%d, qs::[%ld, %ld), ts::[%ld, %ld), mode::%ld, est_err::%ld, e_rate::%f, maxe::%ld\n", - // __func__, ql, "+-"[z->y_pos_strand], z->x_id, z->y_id, qs, qe, ts, te, mode, estimate_err, e_rate, maxe); - // exit(1); - // } - set_exact_exz(exz, qs, qe, ts, te); push_alnw(aux_o, exz); - return 1; - } else if(cal_exact_non_retrieve_exz(z, exz, qstr, tstr, qs, qe, ts, te, q_tot, t_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::0(+)\n", exz->err, exz->thre); - push_alnw(aux_o, exz); - return 1; - } - } - - if(ql <= maxl && (estimate_err>>1) <= maxe) { - thre = scale_ed_thre(estimate_err, maxe); - if(cal_exz_infi_non_retrieve_adv(z, exz, qstr, tstr, qs, qe, ts, te, thre, &pthre, q_tot, t_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(+)\n", exz->err, exz->thre, thre); - push_alnw(aux_o, exz); - return 1; - } - - thre0 = thre; thre = ql*e_rate; thre = scale_ed_thre(thre, maxe); - if(thre > thre0) { - if(cal_exz_infi_non_retrieve_adv(z, exz, qstr, tstr, qs, qe, ts, te, thre, &pthre, q_tot, t_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); - push_alnw(aux_o, exz); - return 1; - } - } - - thre0 = thre; thre <<= 1; thre = scale_ed_thre(thre, maxe); - if(thre > thre0) { - if(cal_exz_infi_non_retrieve_adv(z, exz, qstr, tstr, qs, qe, ts, te, thre, &pthre, q_tot, t_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); - push_alnw(aux_o, exz); - return 1; - } - } - - thre0 = thre; thre = ql*0.51; thre = scale_ed_thre(thre, maxe); - if(thre > thre0) { - if(cal_exz_infi_non_retrieve_adv(z, exz, qstr, tstr, qs, qe, ts, te, thre, &pthre, q_tot, t_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); - push_alnw(aux_o, exz); - return 1; - } - } - - if(ql <= force_l) { - thre = maxe; - if(cal_exz_infi_non_retrieve_adv(z, exz, qstr, tstr, qs, qe, ts, te, thre, &pthre, q_tot, t_tot, mode)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); - push_alnw(aux_o, exz); - return 1; - } - } - } - // fprintf(stderr, ", err::%d, thre::%d\n", INT32_MAX, exz->thre); - // if(mode == 0) { - // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tu->length, tu->seq); - // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)(qe-qs), qstr+qs); - // } - return 0; - -} - -void prt_k_mer_hit(k_mer_hit *ch_a, int64_t ch_n) -{ - int64_t k; - for (k = 0; k < ch_n; k++) { - fprintf(stderr, "[M::%s::k->%ld] q_pos::%u, t_pos::%u, cnt::%u, cov::%u\n", - __func__, k, ch_a[k].self_offset, ch_a[k].offset, ch_a[k].cnt, ch_a[k].readID); - } - -} - -void debug_iter_k_mer_hit(k_mer_hit *ch_a, int64_t ch_n, uint64_t s, uint64_t e, int64_t ibeg, int64_t iend) -{ - int64_t i, beg = -1, end = -1; - for (i = 0; i < ch_n; i++) { - if((ch_a[i].self_offset >= s) && (ch_a[i].self_offset < e)) { - if(beg == -1) beg = i; - end = i+1; - } - } - assert(ibeg==beg && iend==end); -} - -int64_t chain_aln(overlap_region *z, Chain_Data *dp, k_mer_hit *ch_a, int64_t ch_n, const ul_idx_t *uref, -hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, -int64_t te, int64_t mode, int64_t wl, bit_extz_t *exz, int64_t q_tot, double e_rate, -int64_t min_chain_aln, uint64_t rid) -{ - int64_t *m, mn = 0, k; int64_t q[2], t[2], is_chain_aln = 1; - if(mode == 0) { - ///wrong - // assert((ch_n >= 2) && (ch_a[0].self_offset == qs) && (ch_a[0].offset == ts) && - // (ch_a[ch_n-1].self_offset == qe) && (ch_a[ch_n-1].offset == te)); - //does not work with CNS alignment; it also could not work here - if(ch_n == 2 && ((qe-qs)+128) < min_chain_aln) is_chain_aln = 0; - } else if(mode == 1) { - // assert((ch_n >= 1) && (ch_a[0].self_offset == qs) && (ch_a[0].offset == ts)); - //does not work with CNS alignment; it also could not work here - if(ch_n == 1 && ((qe-qs)+128) < min_chain_aln) is_chain_aln = 0; - } else if(mode == 2) { - // assert((ch_n >= 1) && (ch_a[ch_n-1].self_offset == qe) && (ch_a[ch_n-1].offset == te)); - //does not work with CNS alignment; it also could not work here - if(ch_n == 1 && ((qe-qs)+128) < min_chain_aln) is_chain_aln = 0; - } - - if(is_chain_aln) { - mn = lchain_refine(ch_a, ch_n, NULL, dp, 50, 5000, 512, 16); m = dp->tmp; - q[0] = qs; t[0] = ts; - for (k = 0; k < mn; k++) { - q[1] = ch_a[m[k]].self_offset; t[1] = ch_a[m[k]].offset; - if(q[1] > q[0]) { - if((t[0] != -1) && (t[1] != -1)) { - mode = 0;//global - } else if((t[0] != -1) && (t[1] == -1)) { - mode = 1;///forward extension - } else if((t[0] == -1) && (t[1] != -1)) { - mode = 2;///backward extension - } else { - mode = 3;//semi-global - } - if(!hc_aln_exz_adv(z, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, q_tot, e_rate, MAX_SIN_L, MAX_SIN_E, FORCE_SIN_L, -1, NULL)) { - - } - } - q[0] = q[1]; t[0] = t[1]; - } - q[1] = qe; t[1] = te; - if(q[1] > q[0]) { - if((t[0] != -1) && (t[1] != -1)) { - mode = 0;//global - } else if((t[0] != -1) && (t[1] == -1)) { - mode = 1;///forward extension - } else if((t[0] == -1) && (t[1] != -1)) { - mode = 2;///backward extension - } else { - mode = 3;//semi-global - } - if(!hc_aln_exz_adv(z, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, q_tot, e_rate, MAX_SIN_L, MAX_SIN_E, FORCE_SIN_L, -1, NULL)) { - - } - } - - } else { - - } - - // { - // q[0] = qs; t[0] = ts; q[1] = qe; t[1] = te; - // if(q[1] > q[0]) { - // hc_aln_exz_adv(z, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, q_tot, e_rate, MAX_SIN_L, MAX_SIN_E); - // } - // } - return 0; -} - -int64_t sub_base_aln(overlap_region *z, Chain_Data *dp, k_mer_hit *ch_a, int64_t ch_n, uint64_t pre_e, -uint64_t s, uint64_t e, int64_t wl, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, -char* qstr, UC_Read *tu, bit_extz_t *exz, double e_rate, int64_t ql, int64_t tl, -int64_t ch_i, uint64_t rid) -{ - int64_t i = ch_i, l, ibeg, iend, mode, q[2], t[2], ch_s, ch_e; - for (; i >= 0 && ch_a[i].self_offset >= s; i--); - if(i<0) i = 0; ibeg=iend=-1; - for (; i < ch_n && ch_a[i].self_offset < e; i++) { - if((ch_a[i].self_offset >= s) && (ch_a[i].self_offset < e)) { - if(ibeg < 0) ibeg = i; - iend = i+1; - } - } - // debug_iter_k_mer_hit(ch_a, ch_n, s, e, ibeg, iend); - // fprintf(stderr, "***[M::%s::rid->%lu] utg%.6dl(%c), s::%lu, e::%lu, z::[%u, %u), ibeg::%ld, iend::%ld\n", - // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], s, e, z->x_pos_s, z->x_pos_e+1, ibeg, iend); - ch_i = i; - if(ibeg >= 0 && iend >= 0 && iend > ibeg) {///find some anchors[ibeg, iend) - for (i = l = ibeg; i <= iend; i++) { - // fprintf(stderr, "\n[M::%s::i->%ld] q::%u, t::%u, cnt::%u, readID::%u\n", __func__, - // i, ch_a[i].self_offset, ch_a[i].offset, ch_a[i].cnt, ch_a[i].readID); - if(i == iend || is_pri_aln(ch_a[i])) { - q[0] = q[1] = t[0] = t[1] = -1; mode = ch_s = ch_e = -1; - if(l < i && l < iend && is_pri_aln(ch_a[l])) { - q[0] = ch_a[l].self_offset; t[0] = ch_a[l].offset; ch_s = l; - } else { - q[0] = s; - } - - if(i < iend && is_pri_aln(ch_a[i])) { - q[1] = ch_a[i].self_offset; t[1] = ch_a[i].offset; ch_e = i; - } else { - q[1] = e; - } - - if((t[0] != -1) && (t[1] != -1)) { - mode = 0;//global - } else if((t[0] != -1) && (t[1] == -1)) { - mode = 1;///forward extension - } else if((t[0] == -1) && (t[1] != -1)) { - mode = 2;///backward extension - } else { - mode = 3;//semi-global - } - - if((mode == 0) && is_alnw(ch_a[l]) && is_alnw(ch_a[i]) - && (ch_a[l].strand == 0) && (ch_a[i].strand == 1)) { - ; - } else { - // fprintf(stderr, "+[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", - // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode); - - if(mode == 1 || mode == 2) { - tuning_ext_offset(z, ch_a, ch_n, ql, tl, wl, MAX_SIN_L, 4, &ch_s, &ch_e, &q[0], &q[1], &t[0], &t[1], &mode); - } else if(ch_e >= 0) {//global - ch_e++; - } - if(!hc_aln_exz_adv(z, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E, FORCE_CNS_L, -1, NULL)) { - if(ch_s < 0) ch_s = ibeg; if(ch_e < 0) ch_e = iend; - assert(ch_e > ch_s); - // chain_aln(z, dp, ch_a+ch_s, ch_e-ch_s, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, ql, e_rate, MAX_CNS_L, rid); - } - } - l = i; - } - } - } else {//totoally no anchor; probably semi-global - // fprintf(stderr, "\n***[M::%s::rid->%lu] utg%.6dl(%c), s::%lu, e::%lu, z::[%u, %u), ibeg::%ld, iend::%ld\n", - // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], s, e, z->x_pos_s, z->x_pos_e+1, ibeg, iend); - } - - return ch_i; -} - -void cigar_gen_by_chain(overlap_region *z, Chain_Data *dp, k_mer_hit *ch_a, int64_t ch_n, ul_ov_t *ov, int64_t on, uint64_t wl, -const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, double e_rate, -int64_t ql, uint64_t rid) -{ - if(on <= 0) return; - int64_t i, ch_i, tl, id = z->y_id; uint64_t pe = (uint64_t)-1; - if(hpc_g) tl = hpc_len(*hpc_g, id); - else if(uref) tl = uref->ug->u.a[id].len; - else tl = Get_READ_LENGTH((*rref), id); - // for (i = 0; i < wn; i++) z->w_list.a[i].clen = 0;///clean cigar - // if(on > 1) { - // fprintf(stderr, "[M::%s::] rid::%lu, on::%ld\n", __func__, rid, on); - // } - // if(z->y_id == 126) prt_k_mer_hit(ch_a, ch_n); - for (i = ch_i = 0; i < on; i++) { - assert((i<=0)||(ov[i].qs > ov[i-1].qe)); - ch_i = sub_base_aln(z, dp, ch_a, ch_n, pe, ov[i].qs, ov[i].qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, tl, ch_i, rid); - pe = ov[i].qe; - } -} - - -int64_t adjust_base_coordinates(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, -ul_ov_t *res, int64_t wl, int64_t ql, int64_t tl, int64_t ch_i) -{ - res->ts = res->te = (uint32_t)-1; - res->sec = 3; res->qn = res->tn = (uint32_t)-1; //semi-global - if(ch_n == 0) return ch_i; - int64_t i = ch_i, ibeg, iend; uint64_t s = res->qs, e = res->qe; - for (; i >= 0 && ch_a[i].self_offset >= s; i--); if(i < 0) i = 0; - for (; i < ch_n && ch_a[i].self_offset < s; i++); - if((i >= 0) && ((ch_a[i].self_offset > s) || (i >= ch_n))) i--; ibeg = i; ///if ch_a[i].self_offset == s, do nothing - for (i = (i>=0?i:0); i < ch_n && ch_a[i].self_offset < e; i++); iend = i; - ch_i = i;///ch_i must be here - ///ibeg might be < 0, iend might be == ch_n - ///1. [s, e) contain anchors - ///2. anchors contain [s, e) - // fprintf(stderr, "[M::%s::] ibeg::%ld, iend::%ld, ch_n::%ld\n", __func__, ibeg, iend, ch_n); - // if(ibeg >= 0) { - // fprintf(stderr, "[M::%s::] ch_a[ibeg].self_offset::%u, ch_a[ibeg].offset::%u\n", - // __func__, ch_a[ibeg].self_offset, ch_a[ibeg].offset); - // } - // if(ibeg+1 >= 0) { - // fprintf(stderr, "[M::%s::] ch_a[ibeg+1].self_offset::%u, ch_a[ibeg+1].offset::%u\n", - // __func__, ch_a[ibeg+1].self_offset, ch_a[ibeg+1].offset); - // } - - // if(iend < ch_n) { - // fprintf(stderr, "[M::%s::] ch_a[iend].self_offset::%u, ch_a[iend].offset::%u\n", - // __func__, ch_a[iend].self_offset, ch_a[iend].offset); - // } - // if(iend > 0) { - // fprintf(stderr, "[M::%s::] ch_a[iend-1].self_offset::%u, ch_a[iend-1].offset::%u\n", - // __func__, ch_a[iend-1].self_offset, ch_a[iend-1].offset); - // } - - // if(z->y_id == 109111) { - // int64_t di; - // fprintf(stderr, "[M::%s] ch_n::%ld, s::%lu, e::%lu, ibeg::%ld, iend::%ld\n", __func__, ch_n, s, e, ibeg, iend); - // for (di = 0; di < ch_n; di++) { - // fprintf(stderr, "[M::%s::di->%ld] qoff::%u, toff::%u\n", __func__, di, - // ch_a[di].self_offset, ch_a[di].offset); - // } - // } - - if(ibeg >= 0) { - res->qs = ch_a[ibeg].self_offset; - res->ts = ch_a[ibeg].offset; - res->qn = ibeg; - } else {//extension to left - res->qs = 0; res->qn = (uint32_t)-1; - } - - if(iend < ch_n) { - res->qe = ch_a[iend].self_offset; - res->te = ch_a[iend].offset; - res->tn = iend; - } else {//extension to right - res->qe = ql; res->tn = ch_n; - } - - return ch_i; -} - -inline int64_t translate_double_mode(uint64_t double_mode, uint64_t is_backward) -{ - if(double_mode == 0) return 0; - if(double_mode == 4) return 3; - if(double_mode == 1 || double_mode == 2) return double_mode; -} - -int64_t fusion_chain_ovlp(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, ul_ov_t *ov, int64_t on, uint64_t wl, int64_t ql, int64_t tl) -{ - int64_t i, srt, ch_i, m, os, oe, ovlp; ul_ov_t *p; - for (i = ch_i = 0, srt = 1; i < on; i++) { - // fprintf(stderr, "[M::%s::i->%ld] ovq::[%u, %u)\n", __func__, i, ov->qs, ov->qe); - ov[i].sec = 6;///do not know the aln type - ch_i = adjust_base_coordinates(z, ch_a, ch_n, &(ov[i]), wl, ql, tl, ch_i); - if(i > 0 && ov[i].qs < ov[i-1].qe) srt = 0; - } - if(on <= 1) return on; - - if(!srt) radix_sort_uov_srt_qs(ov, ov+on); - for (i = m = 1; i < on; i++) { - p = &(ov[m-1]); - os = MAX(p->qs, ov[i].qs); - oe = MIN(p->qe, ov[i].qe); - ovlp = oe - os; - if(ovlp >= 0) {//merge - p->qe = MAX(p->qe, ov[i].qe); - p->te = MAX(p->te, ov[i].te); - p->tn = MAX(p->tn, ov[i].tn); - } else {//new - ov[m++] = ov[i]; - } - } - - on = m; - return on; -} - -// void chain_win_aln(overlap_region *z, Chain_Data *dp, Candidates_list *cl, int64_t qs, int64_t qe, -// int64_t ts, int64_t te, int64_t ql, int64_t tl, int64_t wl, int64_t mode, bit_extz_t *exz) -// { - -// } - -int64_t ovlp_base_aln_all(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, -int64_t soff, int64_t eoff, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, -char* qstr, UC_Read *tu, ul_ov_t *ov, int64_t ql, int64_t tl, int64_t wl, bit_extz_t *exz, -overlap_region *aux_o, double e_rate) -{ - int64_t ibeg, iend, i, l, mode, q[2], t[2], is_done; - ibeg = soff; iend = eoff; - for (l = ibeg, i = ibeg + 1; i <= iend; i++) { - l = i - 1; - q[0] = q[1] = t[0] = t[1] = mode = -1; is_done = 0; - if(l >= 0) { - q[0] = ch_a[l].self_offset; t[0] = ch_a[l].offset; - } else { - q[0] = ov->qs; - } - - if(i < ch_n) { - q[1] = ch_a[i].self_offset; t[1] = ch_a[i].offset; - } else { - q[1] = ov->qe; - } - - if((t[0] != -1) && (t[1] != -1)) { - mode = 0;//global - } else if((t[0] != -1) && (t[1] == -1)) { - mode = 1;///forward extension - } else if((t[0] == -1) && (t[1] != -1)) { - mode = 2;///backward extension - } else { - mode = 3;///no primary hit within [ibeg, iend] - } - assert(mode != 3); - if(mode == 1 || mode == 2) adjust_ext_offset(&(q[0]), &(q[1]), &(t[0]), &(t[1]), ql, tl, 0, mode); - ///at cns chain, the base alignment fails; there is no anchor between soff and eoff - if((eoff-soff<=1) && (((q[1]-q[0])>>1) < MAX_CNS_E)) { - is_done = 0; - } else { - is_done = hc_aln_exz_adv(z, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, ql, e_rate, MAX_SIN_L, MAX_SIN_E, FORCE_SIN_L, -1, aux_o); - } - - if(!is_done) { - push_unmap_alnw(aux_o, q[0], q[1]-1, t[0], t[1]-1, mode); - // chain_win_aln(z, dp, cl, q[0], q[1], t[0], t[1], ql, tl, wl, exz); - } - // if(aux_o->y_id == 109111) { - // fprintf(stderr, "<[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld, is_done::%ld\n", - // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode, is_done); - // } - } - return 0; -} - -void ovlp_base_aln(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, -ul_ov_t *ov, int64_t wl, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, -bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, int64_t tl, uint64_t rid) -{ - int64_t ibeg, iend, i, l, mode, q[2], t[2], is_done; - if(ov->qn == ((uint32_t)-1)) ibeg = -1; - else ibeg = ov->qn; - iend = ov->tn; - assert(iend>=ibeg+1); - // fprintf(stderr, "\n***[M::%s::rid->%lu] utg%.6dl(%c), s::%u, e::%u, z::[%u, %u), ibeg::%ld, iend::%ld, ch_n::%ld\n", - // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], ov->qs, ov->qe, z->x_pos_s, z->x_pos_e+1, ibeg, iend, ch_n); - for (l = ibeg, i = ibeg + 1; i <= iend; i++) { - if(i == iend || is_pri_aln(ch_a[i])) { - q[0] = q[1] = t[0] = t[1] = mode = -1; is_done = 0; - if(l >= 0) { - q[0] = ch_a[l].self_offset; t[0] = ch_a[l].offset; - } else { - q[0] = ov->qs; - } - - if(i < ch_n) { - q[1] = ch_a[i].self_offset; t[1] = ch_a[i].offset; - } else { - q[1] = ov->qe; - } - - if((t[0] != -1) && (t[1] != -1)) { - mode = 0;//global - } else if((t[0] != -1) && (t[1] == -1)) { - mode = 1;///forward extension - } else if((t[0] == -1) && (t[1] != -1)) { - mode = 2;///backward extension - } else { - mode = 3;///no primary hit within [ibeg, iend] - } - - if((mode == 0) && is_alnw(ch_a[l]) && is_alnw(ch_a[i]) - && (ch_a[l].strand == 0) && (ch_a[i].strand == 1)) { - is_done = 1; - // if(aux_o->x_id == 29033 && aux_o->y_id == 21307){ - // fprintf(stderr, "*[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", - // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode); - // } - // push_replace_alnw(aux_o, q[0], q[1]-1, t[0], t[1]-1, mode);///no need this - push_replace_alnw_adv(z, wl, aux_o, q[0], q[1]-1, t[0], t[1]-1, mode); - } else if(mode != 3) { - if(mode == 1 || mode == 2) adjust_ext_offset(&(q[0]), &(q[1]), &(t[0]), &(t[1]), ql, tl, 0, mode); - // if(aux_o->x_id == 29033 && aux_o->y_id == 21307){ - // fprintf(stderr, "#[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", - // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode); - // } - is_done = hc_aln_exz_adv(z, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E, FORCE_CNS_L, -1, aux_o); - } - - if(!is_done) {///postprocess - // if(aux_o->x_id == 29033 && aux_o->y_id == 21307){ - // fprintf(stderr, ">[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", - // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode); - // } - is_done = ovlp_base_aln_all(z, ch_a, ch_n, l, i, uref, hpc_g, rref, qstr, tu, ov, ql, tl, wl, exz, aux_o, e_rate); - } - // if(aux_o->x_id == 29033 && aux_o->y_id == 21307){ - // fprintf(stderr, "-is_done::%ld[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld, l::%ld, i::%ld, ch_n::%ld\n", - // is_done, __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode, l, i, ch_n); - // } - // if(rid == (uint64_t)-1) { - // fprintf(stderr, "+is_done::%ld[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld, l::%ld, i::%ld, ch_n::%ld\n", - // is_done, __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode, l, i, ch_n); - // } - l = i; - } - } - -} - -inline void push_khit(Candidates_list *res, int32_t xs, int32_t ys, uint32_t len, uint32_t h_khit, uint32_t *ic) -{ - uint32_t p, c; k_mer_hit *z; - c = ((len >= h_khit)?1:2); if(ic) c = *ic; c <<= 8; - if(len > 0) { - while (len >= (0xffu)) { - p = (c + (0xffu)); - kv_pushp_cl(k_mer_hit, (*res), &z); - memset(z, 0, sizeof((*z))); - z->self_offset = xs; z->offset = ys; z->cnt = p; - len -= (0xffu); - } - if(len) { - p = (c + len); - kv_pushp_cl(k_mer_hit, (*res), &z); - memset(z, 0, sizeof((*z))); - z->self_offset = xs; z->offset = ys; z->cnt = p; - } - } else { - p = (c + len); - kv_pushp_cl(k_mer_hit, (*res), &z); - memset(z, 0, sizeof((*z))); - z->self_offset = xs; z->offset = ys; z->cnt = p; - } -} - -uint32_t extract_exact_cigar(asg16_v *ez, int32_t ps, int32_t ts, int32_t pmin, int32_t pmax, -int32_t tmin, int32_t tmax, Candidates_list *res, int32_t minl, int64_t min_w_l, int64_t h_khit) -{ - uint32_t ci = 0, cl, occ = 0; uint16_t c; - int32_t pi = ps, ti = ts, p[2], t[2], poff, toff, maxl; - int32_t pos, poe, tos, toe, l; poff = toff = maxl = -1; - while (ci < ez->n && pi < pmax && ti < tmax) { - ci = pop_trace(ez, ci, &c, &cl); - if(c == 0) { - p[0] = pi; p[1] = pi + cl; - t[0] = ti; t[1] = ti + cl; - pos = MAX(p[0], pmin); poe = MIN(p[1], pmax); - tos = MAX(t[0], tmin); toe = MIN(t[1], tmax); - if((poe > pos) && (toe > tos)) { - l = poe - pos; - if(l == (toe - tos)) { - poe--; toe--; - if(l > maxl) { - poff = poe; toff = toe; maxl = l; - } - if(l >= minl) { - push_khit(res, toe, poe, l, h_khit, NULL); occ++; - } - } - } - pi+=cl; ti+=cl; - } else if(c == 1) { - pi+=cl; ti+=cl; - } else if(c == 2) {///more p - pi+=cl; - } else if(c == 3) { - ti+=cl; - } - } - ///(ts >= tmin) && (ti >= (min_w_l + ts)): here is a whole window - if(maxl > 0 && maxl < minl && (ts >= tmin) && (ti >= (min_w_l + ts))) { - uint32_t w = 3; - push_khit(res, toff, poff, maxl, h_khit, &w); occ++; - } - return occ; -} - -int64_t debug_k_mer_hit_retrive(k_mer_hit *z, hpc_t *hpc_g, All_reads *rref, const ul_idx_t *uref, -char* qstr, UC_Read *tu, int64_t id, int64_t rev) -{ - int64_t qs, qe, ts, te; char *q_string, *t_string; - qe = z->self_offset+1; qs = qe - (z->cnt&(0xffu)); - te = z->offset+1; ts = te - (z->cnt&(0xffu)); - if(qe == qs) return 1; - q_string = qstr + qs; - t_string = retrieve_str_seq_exz(tu, ts, te-ts, -1, -1, rev, uref, hpc_g, rref, id); - fprintf(stderr, "[M::%s::] q_string::%.*s\n", __func__, (int32_t)(qe-qs), q_string); - fprintf(stderr, "[M::%s::] t_string::%.*s\n", __func__, (int32_t)(te-ts), t_string); - if(memcmp(q_string, t_string, qe-qs)) { - fprintf(stderr, "[M::%s::] qsite::%u, tsite::%u\n", __func__, z->self_offset, z->offset); - return 0; - } - return 1; -} - -int64_t gen_single_khit(Candidates_list *cl, int64_t ch_n, int64_t h_khit, int64_t mode, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t max_skip, int64_t max_iter, int64_t rid) -{ - // if(ch_n != 3 || mode != 0 || qs != 171728 || qe != 172258) return 0; - k_mer_hit *ch_a = cl->list + cl->length; int64_t k, i, j, occ, m, ncn, prefix, suffix, srt = 1; - prefix = suffix = 0; - if(mode == 0 || mode == 2) suffix = 1; - if(mode == 0 || mode == 1) prefix = 1; - // if(ch_n == 2 && mode == 2 && qe - qs == 2419 && te - ts == 2419) { - // fprintf(stderr, "[M::%s::mode->%ld] ch_n::%ld, q::[%ld, %ld), t::[%ld, %ld)\n", - // __func__, mode, ch_n, qs, qe, ts, te); - // } - - for (k = occ = m = 0; k < ch_n; k++) { - // if(ch_n == 2 && mode == 2 && qe - qs == 2419 && te - ts == 2419) { - // fprintf(stderr, "+i::%ld[M::%s::] x::[%u, %u), y::[%u, %u), cnt::%u\n", k, __func__, - // ch_a[k].self_offset+1-(ch_a[k].cnt&((uint32_t)(0xffu))), ch_a[k].self_offset+1, - // ch_a[k].offset+1-(ch_a[k].cnt&((uint32_t)(0xffu))), ch_a[k].offset+1, (ch_a[k].cnt&(0xffu))); - // } - if(!(ch_a[k].cnt&(0xffu))) continue; - occ++; - if((ch_a[k].cnt&(0xffu)) > 1) occ++; - ch_a[m++] = ch_a[k]; - } - ch_n = m; if(!ch_n) return ch_n; - occ += prefix + suffix; - // if(ch_n == 2 && mode == 2 && qe - qs == 2419 && te - ts == 2419) { - // fprintf(stderr, "+[M::%s::] occ::%ld\n", __func__, occ); - // } - - ncn = occ + cl->length; - if(cl->size < ncn) { - cl->size = ncn; - REALLOC(cl->list, cl->size); - // cl->list = (k_mer_hit*)realloc(cl->list, (sizeof((*(cl->list)))*cl->length)); - } - ch_a = cl->list + cl->length; assert((cl->length+occ)<= cl->size); - - k_mer_hit cht; - ///global or backward - if(suffix) { - cht.self_offset = qe; - cht.offset = te; - cht.cnt = 1; cht.readID = 1;//make it as primary chain - cht.strand = 0; - ch_a[--occ] = cht; - // fprintf(stderr, "occ::%ld[M::%s::] x::%u, y::%u, cnt::%u, cov::%u\n", occ, __func__, - // cht.self_offset, cht.offset, cht.cnt, cht.readID); - } - for (k = ch_n-1; k >= 0; k--) { - if(!(ch_a[k].cnt&(0xffu))) continue; - ///end - cht.self_offset = ch_a[k].self_offset+1; - cht.offset = ch_a[k].offset+1; - cht.strand = 0; - cht.cnt = cht.readID = (ch_a[k].cnt&(0xffu)); - //make it as non-primary chain - if((ch_a[k].cnt&(0xffu)) < h_khit) cht.readID = cht.cnt + 1; - ch_a[--occ] = cht; - // fprintf(stderr, "occ::%ld[M::%s::] x::%u, y::%u, cnt::%u, cov::%u\n", occ, __func__, - // cht.self_offset, cht.offset, cht.cnt, cht.readID); - - if((ch_a[k].cnt&(0xffu)) > 1) { - ///start - cht.self_offset = ch_a[k].self_offset+1-(ch_a[k].cnt&(0xffu)); - cht.offset = ch_a[k].offset+1-(ch_a[k].cnt&(0xffu)); - cht.strand = 0; - cht.cnt = cht.readID = (ch_a[k].cnt&(0xffu)); - //make it as non-primary chain - if((ch_a[k].cnt&(0xffu)) < h_khit) cht.readID = cht.cnt + 1; - ch_a[--occ] = cht; - // fprintf(stderr, "occ::%ld[M::%s::] x::%u, y::%u, cnt::%u, cov::%u\n", occ, __func__, - // cht.self_offset, cht.offset, cht.cnt, cht.readID); - } - } - - if(prefix) { ///global or forward - cht.self_offset = qs; - cht.offset = ts; - cht.cnt = 1; cht.readID = 1;//make it as primary chain - cht.strand = 0; - ch_a[--occ] = cht; - // fprintf(stderr, "occ::%ld[M::%s::] x::%u, y::%u, cnt::%u, cov::%u\n", occ, __func__, - // cht.self_offset, cht.offset, cht.cnt, cht.readID); - } - // if(ch_n == 2 && mode == 2 && qe - qs == 2419 && te - ts == 2419) { - // fprintf(stderr, "-[M::%s::] occ::%ld\n", __func__, occ); - // } - // if(!(occ == 0)) { - // fprintf(stderr, "[M::%s] rid::%ld, name::%.*s\n", __func__, rid, - // (int32_t)UL_INF.nid.a[rid].n, UL_INF.nid.a[rid].a); - // } - assert(occ == 0); - ch_n = occ = ncn - cl->length; - uint64_t q[2], t[2]; - q[0] = q[1] = t[0] = t[1] = (uint64_t)-1; - if(prefix) { - q[0] = qs; t[0] = ts; - } - if(suffix) { - q[1] = qe; t[1] = te; - } - - // for (k = 0; k < ch_n; k++) { - // fprintf(stderr, "0) && (ch_a[k].self_offset==q[0]) && (ch_a[k].offset=t[0])) continue; - if(((k+1)0) { - if((ch_a[k].self_offset>ch_a[m-1].self_offset) && (ch_a[k].offset>ch_a[m-1].offset)) { - occ++; - } - if(ch_a[k].self_offset<=ch_a[m-1].self_offset) srt = 0; - } else { - occ++; - } - ch_a[m++] = ch_a[k]; - } - ch_n = m; - if(occ == ch_n) return ch_n;///already colinear - if(!srt) { - radix_sort_k_mer_hit_self(ch_a, ch_a + ch_n); - for (i = 1, j = 0; i <= ch_n; i++) { - if (i == ch_n || ch_a[i].self_offset != ch_a[j].self_offset) { - if(i - j > 1) radix_sort_k_mer_hit_off(ch_a+j, ch_a+i); - j = i; - } - } - } - - // for (k = 0; k < ch_n; k++) { - // fprintf(stderr, ">i::%ld[M::%s::] x::%u, y::%u, cnt::%u, cov::%u\n", k, __func__, - // ch_a[k].self_offset, ch_a[k].offset, ch_a[k].cnt, ch_a[k].readID); - // } - occ = ch_n; - ch_n = lchain_simple(ch_a+prefix, ch_n-prefix-suffix, ch_a+prefix, &(cl->chainDP), max_skip, max_iter); - ch_n += prefix + suffix; if(suffix) ch_a[ch_n-1] = ch_a[occ-1]; - // for (k = 0; k < ch_n; k++) { - // fprintf(stderr, "-i::%ld[M::%s::] x::%u, y::%u, cnt::%u, cov::%u\n", k, __func__, - // ch_a[k].self_offset, ch_a[k].offset, ch_a[k].cnt, ch_a[k].readID); - // } - - return ch_n; -} - -///[qs, qe) && [ts, te) -int64_t gen_win_chain(overlap_region *z, Candidates_list *cl, int64_t qs, int64_t qe, int64_t ts, int64_t te, -int64_t wl, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, -int64_t ql, int64_t tl, double e_rate, int64_t h_khit, int64_t mode, int64_t rid, int64_t is_accurate) -{ - assert(mode < 3); - int64_t k, ws, we, os, oe, wsk, rcn = cl->length, ncn, occ = 0, ovlp, wn = z->w_list.n; asg16_v ez; uint32_t w = 1; - ws = qs; if(ws < z->x_pos_s) ws = z->x_pos_s; - we = qe-1; if(we > z->x_pos_e) we = z->x_pos_e; - wsk = get_win_id_by_s(z, ((ws/wl)*wl), wl, NULL); - // if(rid == 7) { - // fprintf(stderr, "[M::%s::]\tutg%.6u%c\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\tq::[%ld,%ld)\tw::[%ld,%ld]\twn::%ld\twsk::%ld\n", __func__, - // z->x_id+1, "lc"[uref->ug->u.a[z->x_id].circ], - // z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[uref->ug->u.a[z->y_id].circ], - // z->y_pos_s, z->y_pos_e+1, qs, qe, ws, we, wn, wsk); - // } - // assert((ws>=z->w_list.a[wsk].x_start) && (ws<=z->w_list.a[wsk].x_end)); - // wek = get_win_id_by_e(z, ((we/wl)*wl), wl, NULL); - // assert((we>=z->w_list.a[wek].x_start) && (we<=z->w_list.a[wek].x_end)); - for(wsk=((wskz->w_list.a[wsk].x_end; wsk++); - for(wsk=((wsk=0 && qsw_list.a[wsk].x_start; wsk--); - if(wsk < 0) wsk = 0; ///qs >= z->w_list.a[wsk].x_start && qs <= z->w_list.a[wsk].x_end - ///global or forward - if(mode == 0 || mode == 1) push_khit(cl, qs, ts, 0, 0, &w); - //[ws, we] && [wsk, wek]; [qs, qe) && [ts, te) - for (k = wsk; kw_list.a[k].x_startw_list.a[k].y_end == -1) continue; - ws = z->w_list.a[k].x_start; we = z->w_list.a[k].x_end+1; - os = MAX(qs, ws); oe = MIN(qe, we); ovlp = ((oe>os)? (oe-os):0); - if(!ovlp) continue; - if(!(z->w_list.a[k].clen)) { - gen_backtrace_adv_exz(&(z->w_list.a[k]), z, rref, hpc_g, uref, qstr, tu->seq, exz, z->y_pos_strand, z->y_id); - } - ez.a = z->w_list.c.a + z->w_list.a[k].cidx; - ez.n = ez.m = z->w_list.a[k].clen; - occ += extract_exact_cigar(&ez, z->w_list.a[k].y_start, z->w_list.a[k].x_start, ts, te, qs, qe, cl, 10, wl, h_khit); - } - ///global or backward - if(mode == 0 || mode == 2) push_khit(cl, qe-1, te-1, 0, 0, &w); - // fprintf(stderr, "[M::%s::] rcn::%ld, cl->length::%lld\n", __func__, rcn, cl->length); - if(!occ) { - cl->length = rcn; return 0; - } - ncn = cl->length; cl->length = rcn; - k_mer_hit *ch_a = cl->list + rcn; int64_t ch_n0 = ncn - rcn, ch_n; - int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; - set_lchain_dp_op(is_accurate, h_khit, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); - max_dis = MAX_SIN_L>>1; - // for (k = 0; k < ch_n0; k++) { - // assert(debug_k_mer_hit_retrive(&(ch_a[k]), hpc_g, rref, uref, qstr, tu, z->y_id, z->y_pos_strand)); - // } - ch_n = lchain_qdp_fix(ch_a, ch_n0, &(cl->chainDP), max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, - e_rate, ql, tl, 1, ((mode==0)||(mode==1))?1:0, ((mode==0)||(mode==2))?1:0); - for (k = occ = 0; k < ch_n; k++) { - ch_a[k] = ch_a[cl->chainDP.tmp[k]]; - if((ch_a[k].cnt&(0xffu))) occ++; - // assert(debug_k_mer_hit_retrive(&(ch_a[k]), hpc_g, rref, uref, qstr, tu, z->y_id, z->y_pos_strand)); - } - // fprintf(stderr, "[M::%s::] ch_n0::%ld, ch_n::%ld, mode::%ld, ql::%ld, tl::%ld, occ::%ld\n", - // __func__, ch_n0, ch_n, mode, qe-qs, te-ts, occ); - if(occ <= 0) return 0; - ch_n = gen_single_khit(cl, ch_n, h_khit, mode, qs, qe, ts, te, max_skip, max_iter, rid); - return ch_n; -} - - -///[qs, qe) && [ts, te) -int64_t gen_win_non_retrieve_chain(overlap_region *z, Candidates_list *cl, int64_t qs, int64_t qe, int64_t ts, int64_t te, -int64_t wl, char* qstr, char* tstr, bit_extz_t *exz, int64_t ql, int64_t tl, double e_rate, int64_t h_khit, int64_t mode, int64_t rid, int64_t is_accurate) -{ - assert(mode < 3); - int64_t k, ws, we, os, oe, wsk, rcn = cl->length, ncn, occ = 0, ovlp, wn = z->w_list.n; asg16_v ez; uint32_t w = 1; - ws = qs; if(ws < z->x_pos_s) ws = z->x_pos_s; - we = qe-1; if(we > z->x_pos_e) we = z->x_pos_e; - wsk = get_win_id_by_s(z, ((ws/wl)*wl), wl, NULL); - // if(rid == 7) { - // fprintf(stderr, "[M::%s::]\tutg%.6u%c\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\tq::[%ld,%ld)\tw::[%ld,%ld]\twn::%ld\twsk::%ld\n", __func__, - // z->x_id+1, "lc"[uref->ug->u.a[z->x_id].circ], - // z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[uref->ug->u.a[z->y_id].circ], - // z->y_pos_s, z->y_pos_e+1, qs, qe, ws, we, wn, wsk); - // } - // assert((ws>=z->w_list.a[wsk].x_start) && (ws<=z->w_list.a[wsk].x_end)); - // wek = get_win_id_by_e(z, ((we/wl)*wl), wl, NULL); - // assert((we>=z->w_list.a[wek].x_start) && (we<=z->w_list.a[wek].x_end)); - for(wsk=((wskz->w_list.a[wsk].x_end; wsk++); - for(wsk=((wsk=0 && qsw_list.a[wsk].x_start; wsk--); - if(wsk < 0) wsk = 0; ///qs >= z->w_list.a[wsk].x_start && qs <= z->w_list.a[wsk].x_end - ///global or forward - if(mode == 0 || mode == 1) push_khit(cl, qs, ts, 0, 0, &w); - //[ws, we] && [wsk, wek]; [qs, qe) && [ts, te) - for (k = wsk; kw_list.a[k].x_startw_list.a[k].y_end == -1) continue; - ws = z->w_list.a[k].x_start; we = z->w_list.a[k].x_end+1; - os = MAX(qs, ws); oe = MIN(qe, we); ovlp = ((oe>os)? (oe-os):0); - if(!ovlp) continue; - if(!(z->w_list.a[k].clen)) { - gen_backtrace_non_retrieve_adv_exz(&(z->w_list.a[k]), z, qstr, tstr, tl, exz, z->y_pos_strand, z->y_id); - } - ez.a = z->w_list.c.a + z->w_list.a[k].cidx; - ez.n = ez.m = z->w_list.a[k].clen; - occ += extract_exact_cigar(&ez, z->w_list.a[k].y_start, z->w_list.a[k].x_start, ts, te, qs, qe, cl, 10, wl, h_khit); - } - ///global or backward - if(mode == 0 || mode == 2) push_khit(cl, qe-1, te-1, 0, 0, &w); - // fprintf(stderr, "[M::%s::] rcn::%ld, cl->length::%lld\n", __func__, rcn, cl->length); - if(!occ) { - cl->length = rcn; return 0; - } - ncn = cl->length; cl->length = rcn; - k_mer_hit *ch_a = cl->list + rcn; int64_t ch_n0 = ncn - rcn, ch_n; - int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; - set_lchain_dp_op(is_accurate, h_khit, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); - max_dis = MAX_SIN_L>>1; - // for (k = 0; k < ch_n0; k++) { - // assert(debug_k_mer_hit_retrive(&(ch_a[k]), hpc_g, rref, uref, qstr, tu, z->y_id, z->y_pos_strand)); - // } - ch_n = lchain_qdp_fix(ch_a, ch_n0, &(cl->chainDP), max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, - e_rate, ql, tl, 1, ((mode==0)||(mode==1))?1:0, ((mode==0)||(mode==2))?1:0); - for (k = occ = 0; k < ch_n; k++) { - ch_a[k] = ch_a[cl->chainDP.tmp[k]]; - if((ch_a[k].cnt&(0xffu))) occ++; - // assert(debug_k_mer_hit_retrive(&(ch_a[k]), hpc_g, rref, uref, qstr, tu, z->y_id, z->y_pos_strand)); - } - // fprintf(stderr, "[M::%s::] ch_n0::%ld, ch_n::%ld, mode::%ld, ql::%ld, tl::%ld, occ::%ld\n", - // __func__, ch_n0, ch_n, mode, qe-qs, te-ts, occ); - if(occ <= 0) return 0; - ch_n = gen_single_khit(cl, ch_n, h_khit, mode, qs, qe, ts, te, max_skip, max_iter, rid); - return ch_n; -} - - - -void rechain_aln(overlap_region *z, Candidates_list *cl, overlap_region *aux_o, int64_t aux_i, int64_t wl, -const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, double e_rate, -int64_t ql, int64_t tl, int64_t h_khit, int64_t rid) -{ - int64_t rcn = cl->length, ch_n, qs, qe, ts, te, mode, an0, an, todo; - k_mer_hit *ch_a; ul_ov_t idx; uint8_t q[2], t[2]; - ///[qs, qe) && [ts, te) - qs = aux_o->w_list.a[aux_i].x_start; qe = aux_o->w_list.a[aux_i].x_end+1; - ts = aux_o->w_list.a[aux_i].y_start; te = aux_o->w_list.a[aux_i].y_end+1; - if(qe - qs < FORCE_SIN_L || te - ts < FORCE_SIN_L) return; - mode = aux_o->w_list.a[aux_i].error_threshold; - ch_n = gen_win_chain(z, cl, qs, qe, ts, te, wl, uref, hpc_g, rref, qstr, tu, exz, ql, tl, e_rate, h_khit, mode, rid, 0); - ch_a = cl->list + rcn; - if(ch_n) { - idx.ts = idx.te = (uint32_t)-1; idx.qs = 0; idx.qe = ql; todo = 1; - if(mode == 0) {//global - idx.qn = 0; idx.tn = ch_n - 1; - idx.qs = ch_a[idx.qn].self_offset; - idx.ts = ch_a[idx.qn].offset; - idx.qe = ch_a[idx.tn].self_offset; - idx.te = ch_a[idx.tn].offset; - assert(ch_a[0].self_offset == qs && ch_a[0].offset == ts); - assert(ch_a[ch_n-1].self_offset == qe && ch_a[ch_n-1].offset == te); - if(ch_n <= 2) todo = 0; - } else if(mode == 1) {//forward ext - idx.qn = 0; idx.tn = ch_n; - idx.qs = ch_a[idx.qn].self_offset; - idx.ts = ch_a[idx.qn].offset; - idx.qe = ql; - assert(ch_a[0].self_offset == qs && ch_a[0].offset == ts); - if(ch_n <= 1) todo = 0; - } else if(mode == 2) {///backward ext - idx.qn = (uint32_t)-1; idx.tn = ch_n-1; - idx.qs = 0; - idx.qe = ch_a[idx.tn].self_offset; - idx.te = ch_a[idx.tn].offset; - assert(ch_a[ch_n-1].self_offset == qe && ch_a[ch_n-1].offset == te); - if(ch_n <= 1) todo = 0; - } - if(todo) { - an0 = aux_o->w_list.n; - // if(z->x_id == 29033 && z->y_id == 21307) { - // fprintf(stderr, "[M::%s]\tan0::%ld\tq::[%u,\t%u)\tt::[%u,\t%u)\tlw::%u\trw::%u\n", __func__, an0, - // idx.qs, idx.qe, idx.ts, idx.te, idx.qn, idx.tn); - // } - ovlp_base_aln(z, ch_a, ch_n, &idx, wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, tl, (uint64_t)-1); - an = aux_o->w_list.n; q[0] = q[1] = t[0] = t[1] = 0; todo = 0; - // if(z->x_id == 29033 && z->y_id == 21307) { - // fprintf(stderr, "[M::%s]\tan::%ld\n", __func__, an); - // } - // fprintf(stderr, "[M::%s::] awn0::%ld, awn::%lu\n", __func__, an0, an); - ///old unaligned window could be replaced by the new aligned window - if((an == (an0 + 1)) && (!(is_ualn_win(aux_o->w_list.a[an-1])))) { - if(aux_o->w_list.a[aux_i].x_start == aux_o->w_list.a[an-1].x_start) q[0] = 1; - if(aux_o->w_list.a[aux_i].x_end == aux_o->w_list.a[an-1].x_end) q[1] = 1; - if(aux_o->w_list.a[aux_i].y_start == aux_o->w_list.a[an-1].y_start) t[0] = 1; - if(aux_o->w_list.a[aux_i].y_end == aux_o->w_list.a[an-1].y_end) t[1] = 1; - if((mode == 0) && q[0] && q[1] && t[0] && t[1]) todo = 1; - if((mode == 1) && q[0] && t[0]) todo = 1; - if((mode == 2) && q[1] && t[1]) todo = 1; - if(todo) { - aux_o->w_list.a[aux_i] = aux_o->w_list.a[an-1]; aux_o->w_list.n--; - } - } - // if(an > an0) {///should always > 0 as there are unmapped windows - // } - // aux_o->w_list.n = an0; - } - } - cl->length = rcn;///must reset!!!! -} - -void debug_overlap_region(overlap_region *au, char* qstr, UC_Read *tu, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref) -{ - int64_t wn = au->w_list.n, k; bit_extz_t ez; - for (k = 0; k < wn; k++) { - assert((k<=0)||((au->w_list.a[k].x_start>au->w_list.a[k-1].x_end) - &&(au->w_list.a[k].y_start>au->w_list.a[k-1].y_end))); - // if(!((k<=0)||((au->w_list.a[k].x_start>au->w_list.a[k-1].x_end) - // &&(au->w_list.a[k].y_start>au->w_list.a[k-1].y_end)))) { - // if(k > 0) { - // fprintf(stderr, "\n[M::%s::(k-1)->%ld] x::[%u, %u], y::[%u, %u]\n", - // __func__, k-1, au->w_list.a[k-1].x_start, au->w_list.a[k-1].x_end, au->w_list.a[k-1].y_start, au->w_list.a[k-1].y_end); - // fprintf(stderr, "[M::%s::(k**)->%ld] x::[%u, %u], y::[%u, %u]\n", - // __func__, k, au->w_list.a[k].x_start, au->w_list.a[k].x_end, au->w_list.a[k].y_start, au->w_list.a[k].y_end); - // } - - // } - assert(au->w_list.a[k].x_end>au->w_list.a[k].x_start); - // if(!(au->w_list.a[k].y_end>au->w_list.a[k].y_start)) { - // fprintf(stderr, "[M::%s::(k**)->%ld] x::[%u, %u], y::[%u, %u]\n", - // __func__, k, au->w_list.a[k].x_start, au->w_list.a[k].x_end, au->w_list.a[k].y_start, au->w_list.a[k].y_end); - // } - assert(au->w_list.a[k].y_end>au->w_list.a[k].y_start); - if(is_ualn_win(au->w_list.a[k]) || is_est_aln(au->w_list.a[k])) continue; - ez.cigar.a = au->w_list.c.a + au->w_list.a[k].cidx; - ez.cigar.n = ez.cigar.m = au->w_list.a[k].clen; - ez.ts = au->w_list.a[k].x_start; ez.te = au->w_list.a[k].x_end; - ez.ps = au->w_list.a[k].y_start; ez.pe = au->w_list.a[k].y_end; - ez.err = au->w_list.a[k].error; - ref_cigar_check(qstr, tu, uref, hpc_g, rref, au->y_id, au->y_pos_strand, &ez); - } -} - -void update_overlap_region(overlap_region *des, overlap_region *src, int64_t xl, int64_t yl) -{ - kv_resize(uint16_t, des->w_list.c, src->w_list.c.n); - des->w_list.c.n = src->w_list.c.n; - memcpy(des->w_list.c.a, src->w_list.c.a, src->w_list.c.n*(sizeof((*(src->w_list.c.a))))); - - kv_resize(window_list, des->w_list, src->w_list.n); - des->w_list.n = src->w_list.n; - memcpy(des->w_list.a, src->w_list.a, src->w_list.n*(sizeof((*(src->w_list.a))))); - - if(src->w_list.n) { - des->x_pos_s = src->w_list.a[0].x_start; des->x_pos_e = src->w_list.a[src->w_list.n-1].x_end; - des->y_pos_s = src->w_list.a[0].y_start; des->y_pos_e = src->w_list.a[src->w_list.n-1].y_end; - } - - int64_t xr, yr; - if(des->x_pos_s <= des->y_pos_s) { - des->y_pos_s -= des->x_pos_s; des->x_pos_s = 0; - } else { - des->x_pos_s -= des->y_pos_s; des->y_pos_s = 0; - } - - xr = xl-des->x_pos_e-1; yr = yl-des->y_pos_e-1; - if(xr <= yr) { - des->x_pos_e = xl-1; des->y_pos_e += xr; - } else { - des->y_pos_e = yl-1; des->x_pos_e += yr; - } -} - -void cigar_gen_by_chain_adv(overlap_region *z, Candidates_list *cl, int64_t ch_idx, int64_t ch_n, -ul_ov_t *ov, int64_t on, uint64_t wl, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, -UC_Read *tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, uint64_t rid, int64_t h_khit) -{ - if(on <= 0) return; - int64_t i, tl, id = z->y_id, m; - k_mer_hit *ch_a = cl->list + ch_idx; - if(hpc_g) tl = hpc_len(*hpc_g, id); - else if(uref) tl = uref->ug->u.a[id].len; - else tl = Get_READ_LENGTH((*rref), id); - // fprintf(stderr, "\n[M::%s::rid->%ld] utg%.6dl(%c), z::[%u, %u)\n", - // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e+1); - on = fusion_chain_ovlp(z, ch_a, ch_n, ov, on, wl, ql, tl); - aux_o->w_list.n = aux_o->w_list.c.n = 0; - aux_o->y_id = z->y_id; aux_o->y_pos_strand = z->y_pos_strand; - aux_o->x_pos_s = z->x_pos_s; aux_o->x_pos_e = z->x_pos_e; - aux_o->y_pos_s = z->y_pos_s; aux_o->y_pos_e = z->y_pos_e; - - - for (i = 0; i < on; i++) { - // if(aux_o->y_id == 109111) { - // fprintf(stderr, "[M::%s::i->%ld] ovq::[%u, %u), ovt::[%u, %u), hits::[%d, %d)\n", __func__, i, - // ov->qs, ov->qe, ov->ts, ov->te, - // (ov->qn!=((uint32_t)-1))?(int32_t)ov->qn:-1, (int32_t)ov->tn); - // } - assert((i<=0)||(ov[i].qs>ov[i-1].qe)); - ovlp_base_aln(z, ch_a, ch_n, &(ov[i]), wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, tl, rid); - } - - int64_t aux_n = aux_o->w_list.n; - ///for debug - // if(aux_o->y_id == 109111) { - // for (i = 0; i < ((int64_t)aux_o->w_list.n); i++) { - // fprintf(stderr, "-0-[aln::i->%ld::ql->%d] q::[%d, %d), t::[%d, %d), err::%d, clen::%u, extra_end::%d, mode::%d\n", i, - // aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start, - // aux_o->w_list.a[i].x_start, aux_o->w_list.a[i].x_end+1, - // aux_o->w_list.a[i].y_start, aux_o->w_list.a[i].y_end+1, - // aux_o->w_list.a[i].error, aux_o->w_list.a[i].clen, - // aux_o->w_list.a[i].extra_end, aux_o->w_list.a[i].error_threshold); - // } - // } - - for (i = 0; i < aux_n; i++) { - if(!(is_ualn_win(aux_o->w_list.a[i]))) continue; - //will overwrite ch_a; does not matter - rechain_aln(z, cl, aux_o, i, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, tl, h_khit, rid); - } - - ///for debug - // if(aux_o->y_id == 109111) { - // for (i = 0; i < ((int64_t)aux_o->w_list.n); i++) { - // fprintf(stderr, "-2-[aln::i->%ld::ql->%d] q::[%d, %d), t::[%d, %d), err::%d, clen::%u, mode::%d\n", i, - // aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start, - // aux_o->w_list.a[i].x_start, aux_o->w_list.a[i].x_end+1, - // aux_o->w_list.a[i].y_start, aux_o->w_list.a[i].y_end+1, - // aux_o->w_list.a[i].error, aux_o->w_list.a[i].clen, aux_o->w_list.a[i].error_threshold); - // } - // } - - if(((int64_t)aux_o->w_list.n) > aux_n) { - for (i = m = 0; i < ((int64_t)aux_o->w_list.n); i++) { - if((i < aux_n) && (is_ualn_win(aux_o->w_list.a[i]))) continue; - aux_o->w_list.a[m++] = aux_o->w_list.a[i]; - } - aux_o->w_list.n = m; - radix_sort_window_list_xs_srt(aux_o->w_list.a, aux_o->w_list.a+aux_o->w_list.n); - } - - ///update z by aux_o - update_overlap_region(z, aux_o, ql, tl); - - // debug_overlap_region(aux_o, qstr, tu, uref, hpc_g, rref); - - - // ch_a = cl->list + ch_idx; //update - // for (i = 0; i < wn; i++) z->w_list.a[i].clen = 0;///clean cigar - // if(on > 1) { - // fprintf(stderr, "[M::%s::] rid::%lu, on::%ld\n", __func__, rid, on); - // } - // if(z->y_id == 126) prt_k_mer_hit(ch_a, ch_n); - // for (i = ch_i = 0; i < on; i++) { - // assert((i<=0)||(ov[i].qs > ov[i-1].qe)); - // ov[i].sec = 16;///do not know the aln type - // ch_i = sub_base_aln(z, dp, ch_a, ch_n, pe, ov[i].qs, ov[i].qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, tl, ch_i, rid); - // pe = ov[i].qe; - // } -} - -void ovlp_base_direct(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, -ul_ov_t *ov, int64_t wl, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, -bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, int64_t tl, uint64_t rid) -{ - int64_t ibeg, iend, i, l, mode, q[2], t[2], is_done; - if(ov->qn == ((uint32_t)-1)) ibeg = -1; - else ibeg = ov->qn; - iend = ov->tn; - assert(iend>=ibeg+1); - // if(z->x_id == 57 && z->y_id == 2175) { - // fprintf(stderr, "\n***[M::%s::rid->%lu] utg%.6dl(%c), s::%u, e::%u, z::[%u, %u), ibeg::%ld, iend::%ld, ch_n::%ld\n", - // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], ov->qs, ov->qe, z->x_pos_s, z->x_pos_e+1, ibeg, iend, ch_n); - // } - for (l = ibeg, i = ibeg + 1; i <= iend; i++) { - q[0] = q[1] = t[0] = t[1] = mode = -1; is_done = 0; - if(l >= 0) { - q[0] = ch_a[l].self_offset; t[0] = ch_a[l].offset; - } else { - q[0] = ov->qs; - } - - if(i < ch_n) { - q[1] = ch_a[i].self_offset; t[1] = ch_a[i].offset; - } else { - q[1] = ov->qe; - } - - if((t[0] != -1) && (t[1] != -1)) { - mode = 0;//global - } else if((t[0] != -1) && (t[1] == -1)) { - mode = 1;///forward extension - } else if((t[0] == -1) && (t[1] != -1)) { - mode = 2;///backward extension - } else { - mode = 3;///no primary hit within [ibeg, iend] - } - - if(mode == 1 || mode == 2) adjust_ext_offset(&(q[0]), &(q[1]), &(t[0]), &(t[1]), ql, tl, 0, mode); - // if(z->x_id == 57 && z->y_id == 2175) { - // fprintf(stderr, "#[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", - // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode); - // } - is_done = hc_aln_exz_adv(z, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, ql, e_rate, - MAX_SIN_L, MAX_SIN_E, FORCE_SIN_L, -1, aux_o); - - // if(z->x_id == 57 && z->y_id == 2175) { - // fprintf(stderr, "-is_done::%ld[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", - // is_done, __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode); - // } - - if(!is_done) {///postprocess - push_unmap_alnw(aux_o, q[0], q[1]-1, t[0], t[1]-1, mode); - } - l = i; - } -} - - -void hc_ovlp_base_direct(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, int64_t wl, All_reads *rref, char* qstr, UC_Read *tu, -bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, int64_t tl, uint64_t rid, int64_t pre_mode) -{ - int64_t i, l, mode, q[2], t[2], qr, tr, is_done, zn, si, ei; - - if((pre_mode < 0) && (z->non_homopolymer_errors == 0) && (z->w_list.n)) { - zn = z->w_list.n; - for (i = 1; i < zn; i++) { - if((z->w_list.a[i].error == 0 && z->w_list.a[i-1].error == 0) && (z->w_list.a[i].x_start == z->w_list.a[i-1].x_end + 1) && - (z->w_list.a[i].y_end == (z->w_list.a[i-1].y_end + (z->w_list.a[i].x_end-z->w_list.a[i-1].x_end)))) { - continue; - } - break; - } - if(i >= zn) { - q[0] = z->w_list.a[0].x_start; q[1] = z->w_list.a[z->w_list.n-1].x_end; - t[1] = z->w_list.a[z->w_list.n-1].y_end; t[0] = z->w_list.a[0].y_end - (z->w_list.a[0].x_end-z->w_list.a[0].x_start); - - if(q[0] <= t[0]) { - t[0] -= q[0]; q[0] = 0; - } else { - q[0] -= t[0]; t[0] = 0; - } - - qr = ql-q[1]-1; tr = tl-t[1]-1; - if(qr <= tr) { - q[1] = ql-1; t[1] += qr; - } else { - t[1] = tl-1; q[1] += tr; - } - - if(q[0] == z->w_list.a[0].x_start && q[1] == z->w_list.a[z->w_list.n-1].x_end) { - // fprintf(stderr, "[M::%s::%u->%u::%c] ovlp::%u, w_list.n::%u\n", __func__, z->x_id, z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_e+1-z->x_pos_s, (uint32_t)z->w_list.n); - set_exact_exz(exz, q[0], q[1] + 1, t[0], t[1] + 1); push_alnw(aux_o, exz); - return; - } - } - } - - si = 0; ei = ch_n; - if(pre_mode == 0) { - si = 1; ei = ch_n - 1; - } else if(pre_mode == 1) { - si = 1; - } else if(pre_mode == 2) { - ei = ch_n - 1; - } - - for (l = si - 1, i = si; i <= ei; i++) { - q[0] = q[1] = t[0] = t[1] = mode = -1; is_done = 0; - if(l >= 0) { - q[0] = ch_a[l].self_offset; t[0] = ch_a[l].offset; - } else { - q[0] = 0; - } - - if(i < ch_n) { - q[1] = ch_a[i].self_offset; t[1] = ch_a[i].offset; - } else { - q[1] = ql; - } - - if((t[0] != -1) && (t[1] != -1)) { - mode = 0;//global - } else if((t[0] != -1) && (t[1] == -1)) { - mode = 1;///forward extension - } else if((t[0] == -1) && (t[1] != -1)) { - mode = 2;///backward extension - } else { - mode = 3;///no primary hit within [ibeg, iend] - } - - // if(z->x_id == 57 && z->y_id == 2175) { - if(mode == 1 || mode == 2) adjust_ext_offset(&(q[0]), &(q[1]), &(t[0]), &(t[1]), ql, tl, 0, mode); - // fprintf(stderr, "#[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", - // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode); - // } - is_done = hc_aln_exz_adv_hc(z, NULL, NULL, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, ql, e_rate, - MAX_SIN_L, MAX_SIN_E, FORCE_SIN_L, -1, aux_o); - - // if(z->x_id == 57 && z->y_id == 2175) { - // fprintf(stderr, "-is_done::%ld[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld, ch_n::%ld\n", - // is_done, __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode, ch_n); - // } - - if(!is_done) {///postprocess - push_unmap_alnw(aux_o, q[0], q[1]-1, t[0], t[1]-1, mode); - } - l = i; - } -} - -void hc_ovlp_base_non_retrieve_direct(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, int64_t wl, char* qstr, char* tstr, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, int64_t tl, uint64_t rid) -{ - int64_t i, l, mode, q[2], t[2], qr, tr, is_done, zn; - - if(z->non_homopolymer_errors == 0 && z->w_list.n) { - zn = z->w_list.n; - for (i = 1; i < zn; i++) { - if((z->w_list.a[i].error == 0 && z->w_list.a[i-1].error == 0) && (z->w_list.a[i].x_start == z->w_list.a[i-1].x_end + 1) && - (z->w_list.a[i].y_end == (z->w_list.a[i-1].y_end + (z->w_list.a[i].x_end-z->w_list.a[i-1].x_end)))) { - continue; - } - break; - } - if(i >= zn) { - q[0] = z->w_list.a[0].x_start; q[1] = z->w_list.a[z->w_list.n-1].x_end; - t[1] = z->w_list.a[z->w_list.n-1].y_end; t[0] = z->w_list.a[0].y_end - (z->w_list.a[0].x_end-z->w_list.a[0].x_start); - - if(q[0] <= t[0]) { - t[0] -= q[0]; q[0] = 0; - } else { - q[0] -= t[0]; t[0] = 0; - } - - qr = ql-q[1]-1; tr = tl-t[1]-1; - if(qr <= tr) { - q[1] = ql-1; t[1] += qr; - } else { - t[1] = tl-1; q[1] += tr; - } - - if(q[0] == z->w_list.a[0].x_start && q[1] == z->w_list.a[z->w_list.n-1].x_end) { - // fprintf(stderr, "[M::%s::%u->%u::%c] ovlp::%u, w_list.n::%u\n", __func__, z->x_id, z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_e+1-z->x_pos_s, (uint32_t)z->w_list.n); - set_exact_exz(exz, q[0], q[1] + 1, t[0], t[1] + 1); push_alnw(aux_o, exz); - return; - } - } - } - - for (l = -1, i = 0; i <= ch_n; i++) { - q[0] = q[1] = t[0] = t[1] = mode = -1; is_done = 0; - if(l >= 0) { - q[0] = ch_a[l].self_offset; t[0] = ch_a[l].offset; - } else { - q[0] = 0; - } - - if(i < ch_n) { - q[1] = ch_a[i].self_offset; t[1] = ch_a[i].offset; - } else { - q[1] = ql; - } - - if((t[0] != -1) && (t[1] != -1)) { - mode = 0;//global - } else if((t[0] != -1) && (t[1] == -1)) { - mode = 1;///forward extension - } else if((t[0] == -1) && (t[1] != -1)) { - mode = 2;///backward extension - } else { - mode = 3;///no primary hit within [ibeg, iend] - } - - // if(z->x_id == 57 && z->y_id == 2175) { - if(mode == 1 || mode == 2) adjust_ext_offset(&(q[0]), &(q[1]), &(t[0]), &(t[1]), ql, tl, 0, mode); - // fprintf(stderr, "#[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", - // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode); - // } - is_done = hc_aln_exz_non_retrieve_adv_hc(z, qstr, tstr, q[0], q[1], t[0], t[1], mode, wl, exz, ql, tl, e_rate, MAX_SIN_L, MAX_SIN_E, FORCE_SIN_L, -1, aux_o); - - // if(z->x_id == 57 && z->y_id == 2175) { - // fprintf(stderr, "-is_done::%ld[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld, ch_n::%ld\n", - // is_done, __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode, ch_n); - // } - - if(!is_done) {///postprocess - push_unmap_alnw(aux_o, q[0], q[1]-1, t[0], t[1]-1, mode); - } - l = i; - } -} - -void cigar_gen_by_chain_adv_local(overlap_region *z, Candidates_list *cl, ul_ov_t *ov, int64_t on, uint64_t wl, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, -UC_Read *tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, uint64_t rid, int64_t h_khit) -{ - if(on <= 0) return; - int64_t ch_idx = z->shared_seed, ch_n; - int64_t i, tl, id = z->y_id, m; - k_mer_hit *ch_a = cl->list + ch_idx; - if(hpc_g) tl = hpc_len(*hpc_g, id); - else if(uref) tl = uref->ug->u.a[id].len; - else tl = Get_READ_LENGTH((*rref), id); - for (i = ch_idx; i < cl->length && cl->list[i].readID == cl->list[ch_idx].readID; i++); ch_n = i-ch_idx; - - // fprintf(stderr, "[M::%s::rid->%ld] utg%.6dl(%c), z::[%u, %u)\n", - // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e+1); - on = fusion_chain_ovlp(z, ch_a, ch_n, ov, on, wl, ql, tl); - aux_o->w_list.n = aux_o->w_list.c.n = 0; - aux_o->y_id = z->y_id; aux_o->y_pos_strand = z->y_pos_strand; - aux_o->x_pos_s = z->x_pos_s; aux_o->x_pos_e = z->x_pos_e; - aux_o->y_pos_s = z->y_pos_s; aux_o->y_pos_e = z->y_pos_e; - - - for (i = 0; i < on; i++) { - // fprintf(stderr, "[M::%s::+i->%ld] ovq::[%u, %u), ovt::[%u, %u), hits::[%d, %d)\n", __func__, i, - // ov->qs, ov->qe, ov->ts, ov->te, - // (ov->qn!=((uint32_t)-1))?(int32_t)ov->qn:-1, (int32_t)ov->tn); - assert((i<=0)||(ov[i].qs>ov[i-1].qe)); - ovlp_base_direct(z, ch_a, ch_n, &(ov[i]), wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, tl, rid); - } - - int64_t aux_n = aux_o->w_list.n; - for (i = 0; i < aux_n; i++) { - if(!(is_ualn_win(aux_o->w_list.a[i]))) continue; - // if((aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start) <= FORCE_CNS_L) { - // fprintf(stderr, "[aln::-i->%ld::ql->%d] q::[%d, %d), t::[%d, %d), err::%d, clen::%u, mode::%d\n", i, - // aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start, - // aux_o->w_list.a[i].x_start, aux_o->w_list.a[i].x_end+1, - // aux_o->w_list.a[i].y_start, aux_o->w_list.a[i].y_end+1, - // aux_o->w_list.a[i].error, aux_o->w_list.a[i].clen, aux_o->w_list.a[i].error_threshold); - // } - //will overwrite ch_a; does not matter - rechain_aln(z, cl, aux_o, i, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, tl, h_khit, rid); - } - if(((int64_t)aux_o->w_list.n) > aux_n) { - for (i = m = 0; i < ((int64_t)aux_o->w_list.n); i++) { - if((i < aux_n) && (is_ualn_win(aux_o->w_list.a[i]))) continue; - aux_o->w_list.a[m++] = aux_o->w_list.a[i]; - } - aux_o->w_list.n = m; - radix_sort_window_list_xs_srt(aux_o->w_list.a, aux_o->w_list.a+aux_o->w_list.n); - } - - ///update z by aux_o - update_overlap_region(z, aux_o, ql, tl); - - // debug_overlap_region(aux_o, qstr, tu, uref, hpc_g, rref); - - - // ch_a = cl->list + ch_idx; //update - // for (i = 0; i < wn; i++) z->w_list.a[i].clen = 0;///clean cigar - // if(on > 1) { - // fprintf(stderr, "[M::%s::] rid::%lu, on::%ld\n", __func__, rid, on); - // } - // if(z->y_id == 126) prt_k_mer_hit(ch_a, ch_n); - // for (i = ch_i = 0; i < on; i++) { - // assert((i<=0)||(ov[i].qs > ov[i-1].qe)); - // ov[i].sec = 16;///do not know the aln type - // ch_i = sub_base_aln(z, dp, ch_a, ch_n, pe, ov[i].qs, ov[i].qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, tl, ch_i, rid); - // pe = ov[i].qe; - // } -} - -void rechain_aln_hc(overlap_region *z, Candidates_list *cl, overlap_region *aux_o, int64_t aux_i, int64_t wl, -All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, double e_rate, int64_t ql, int64_t tl, int64_t h_khit, int64_t rid) -{ - int64_t rcn = cl->length, ch_n, qs, qe, ts, te, mode, an0, an, todo; - k_mer_hit *ch_a; uint8_t q[2], t[2]; ///ul_ov_t idx; - ///[qs, qe) && [ts, te) - qs = aux_o->w_list.a[aux_i].x_start; qe = aux_o->w_list.a[aux_i].x_end+1; - ts = aux_o->w_list.a[aux_i].y_start; te = aux_o->w_list.a[aux_i].y_end+1; - if(qe - qs < FORCE_SIN_L || te - ts < FORCE_SIN_L) return; - mode = aux_o->w_list.a[aux_i].error_threshold; - ch_n = gen_win_chain(z, cl, qs, qe, ts, te, wl, NULL, NULL, rref, qstr, tu, exz, ql, tl, e_rate, h_khit, mode, rid, 1); - ch_a = cl->list + rcn; - if(ch_n) { - todo = 1; ///idx.ts = idx.te = (uint32_t)-1; idx.qs = 0; idx.qe = ql; - if(mode == 0) {//global - // idx.qn = 0; idx.tn = ch_n - 1; - // idx.qs = ch_a[idx.qn].self_offset; - // idx.ts = ch_a[idx.qn].offset; - // idx.qe = ch_a[idx.tn].self_offset; - // idx.te = ch_a[idx.tn].offset; - assert(ch_a[0].self_offset == qs && ch_a[0].offset == ts); - assert(ch_a[ch_n-1].self_offset == qe && ch_a[ch_n-1].offset == te); - if(ch_n <= 2) todo = 0; - } else if(mode == 1) {//forward ext - // idx.qn = 0; idx.tn = ch_n; - // idx.qs = ch_a[idx.qn].self_offset; - // idx.ts = ch_a[idx.qn].offset; - // idx.qe = ql; - assert(ch_a[0].self_offset == qs && ch_a[0].offset == ts); - if(ch_n <= 1) todo = 0; - } else if(mode == 2) {///backward ext - // idx.qn = (uint32_t)-1; idx.tn = ch_n-1; - // idx.qs = 0; - // idx.qe = ch_a[idx.tn].self_offset; - // idx.te = ch_a[idx.tn].offset; - assert(ch_a[ch_n-1].self_offset == qe && ch_a[ch_n-1].offset == te); - if(ch_n <= 1) todo = 0; - } - if(todo) { - an0 = aux_o->w_list.n; - // if(z->x_id == 29033 && z->y_id == 21307) { - // fprintf(stderr, "[M::%s]\tan0::%ld\tq::[%u,\t%u)\tt::[%u,\t%u)\tlw::%u\trw::%u\n", __func__, an0, - // idx.qs, idx.qe, idx.ts, idx.te, idx.qn, idx.tn); - // } - // ovlp_base_aln(z, ch_a, ch_n, &idx, wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, tl, (uint64_t)-1); - hc_ovlp_base_direct(z, ch_a, ch_n, wl, rref, qstr, tu, exz, aux_o, e_rate, ql, tl, (uint64_t)-1, mode); - an = aux_o->w_list.n; q[0] = q[1] = t[0] = t[1] = 0; todo = 0; - // if(z->x_id == 29033 && z->y_id == 21307) { - // fprintf(stderr, "[M::%s]\tan::%ld\n", __func__, an); - // } - // fprintf(stderr, "[M::%s::] awn0::%ld, awn::%lu\n", __func__, an0, an); - ///old unaligned window could be replaced by the new aligned window - if((an == (an0 + 1)) && (!(is_ualn_win(aux_o->w_list.a[an-1])))) { - if(aux_o->w_list.a[aux_i].x_start == aux_o->w_list.a[an-1].x_start) q[0] = 1; - if(aux_o->w_list.a[aux_i].x_end == aux_o->w_list.a[an-1].x_end) q[1] = 1; - if(aux_o->w_list.a[aux_i].y_start == aux_o->w_list.a[an-1].y_start) t[0] = 1; - if(aux_o->w_list.a[aux_i].y_end == aux_o->w_list.a[an-1].y_end) t[1] = 1; - if((mode == 0) && q[0] && q[1] && t[0] && t[1]) todo = 1; - if((mode == 1) && q[0] && t[0]) todo = 1; - if((mode == 2) && q[1] && t[1]) todo = 1; - if(todo) { - aux_o->w_list.a[aux_i] = aux_o->w_list.a[an-1]; aux_o->w_list.n--; - } - } - // if(an > an0) {///should always > 0 as there are unmapped windows - // } - // aux_o->w_list.n = an0; - } - } - cl->length = rcn;///must reset!!!! -} - -void rechain_aln_non_retrieve_hc(overlap_region *z, Candidates_list *cl, overlap_region *aux_o, int64_t aux_i, int64_t wl, -char* qstr, char* tstr, bit_extz_t *exz, double e_rate, int64_t ql, int64_t tl, int64_t h_khit, int64_t rid) -{ - int64_t rcn = cl->length, ch_n, qs, qe, ts, te, mode, an0, an, todo; - k_mer_hit *ch_a; uint8_t q[2], t[2]; ///ul_ov_t idx; - ///[qs, qe) && [ts, te) - qs = aux_o->w_list.a[aux_i].x_start; qe = aux_o->w_list.a[aux_i].x_end+1; - ts = aux_o->w_list.a[aux_i].y_start; te = aux_o->w_list.a[aux_i].y_end+1; - if(qe - qs < FORCE_SIN_L || te - ts < FORCE_SIN_L) return; - mode = aux_o->w_list.a[aux_i].error_threshold; - ch_n = gen_win_non_retrieve_chain(z, cl, qs, qe, ts, te, wl, qstr, tstr, exz, ql, tl, e_rate, h_khit, mode, rid, 1); - ch_a = cl->list + rcn; - if(ch_n) { - todo = 1; ///idx.ts = idx.te = (uint32_t)-1; idx.qs = 0; idx.qe = ql; - if(mode == 0) {//global - // idx.qn = 0; idx.tn = ch_n - 1; - // idx.qs = ch_a[idx.qn].self_offset; - // idx.ts = ch_a[idx.qn].offset; - // idx.qe = ch_a[idx.tn].self_offset; - // idx.te = ch_a[idx.tn].offset; - assert(ch_a[0].self_offset == qs && ch_a[0].offset == ts); - assert(ch_a[ch_n-1].self_offset == qe && ch_a[ch_n-1].offset == te); - if(ch_n <= 2) todo = 0; - } else if(mode == 1) {//forward ext - // idx.qn = 0; idx.tn = ch_n; - // idx.qs = ch_a[idx.qn].self_offset; - // idx.ts = ch_a[idx.qn].offset; - // idx.qe = ql; - assert(ch_a[0].self_offset == qs && ch_a[0].offset == ts); - if(ch_n <= 1) todo = 0; - } else if(mode == 2) {///backward ext - // idx.qn = (uint32_t)-1; idx.tn = ch_n-1; - // idx.qs = 0; - // idx.qe = ch_a[idx.tn].self_offset; - // idx.te = ch_a[idx.tn].offset; - assert(ch_a[ch_n-1].self_offset == qe && ch_a[ch_n-1].offset == te); - if(ch_n <= 1) todo = 0; - } - if(todo) { - an0 = aux_o->w_list.n; - // if(z->x_id == 29033 && z->y_id == 21307) { - // fprintf(stderr, "[M::%s]\tan0::%ld\tq::[%u,\t%u)\tt::[%u,\t%u)\tlw::%u\trw::%u\n", __func__, an0, - // idx.qs, idx.qe, idx.ts, idx.te, idx.qn, idx.tn); - // } - // ovlp_base_aln(z, ch_a, ch_n, &idx, wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, tl, (uint64_t)-1); - hc_ovlp_base_non_retrieve_direct(z, ch_a, ch_n, wl, qstr, tstr, exz, aux_o, e_rate, ql, tl, (uint64_t)-1); - an = aux_o->w_list.n; q[0] = q[1] = t[0] = t[1] = 0; todo = 0; - // if(z->x_id == 29033 && z->y_id == 21307) { - // fprintf(stderr, "[M::%s]\tan::%ld\n", __func__, an); - // } - // fprintf(stderr, "[M::%s::] awn0::%ld, awn::%lu\n", __func__, an0, an); - ///old unaligned window could be replaced by the new aligned window - if((an == (an0 + 1)) && (!(is_ualn_win(aux_o->w_list.a[an-1])))) { - if(aux_o->w_list.a[aux_i].x_start == aux_o->w_list.a[an-1].x_start) q[0] = 1; - if(aux_o->w_list.a[aux_i].x_end == aux_o->w_list.a[an-1].x_end) q[1] = 1; - if(aux_o->w_list.a[aux_i].y_start == aux_o->w_list.a[an-1].y_start) t[0] = 1; - if(aux_o->w_list.a[aux_i].y_end == aux_o->w_list.a[an-1].y_end) t[1] = 1; - if((mode == 0) && q[0] && q[1] && t[0] && t[1]) todo = 1; - if((mode == 1) && q[0] && t[0]) todo = 1; - if((mode == 2) && q[1] && t[1]) todo = 1; - if(todo) { - aux_o->w_list.a[aux_i] = aux_o->w_list.a[an-1]; aux_o->w_list.n--; - } - } - // if(an > an0) {///should always > 0 as there are unmapped windows - // } - // aux_o->w_list.n = an0; - } - } - cl->length = rcn;///must reset!!!! -} - -uint64_t gen_hc_fast_cigar0(overlap_region *z, Candidates_list *cl, uint64_t wl, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, uint64_t rid, int64_t h_khit, int64_t *re) -{ - int64_t ch_idx = z->shared_seed, ch_n; - int64_t i, tl, id = z->y_id, m, tot_e, aln, xe, ye; - k_mer_hit *ch_a = cl->list + ch_idx; - tl = Get_READ_LENGTH((*rref), id); - for (i = ch_idx; i < cl->length && cl->list[i].readID == cl->list[ch_idx].readID; i++); ch_n = i-ch_idx; - if(ch_n <= 0) return 0; - - ///debug for memory - // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); - - // fprintf(stderr, "[M::%s::rid->%ld] utg%.6dl(%c), z::[%u, %u)\n", - // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e+1); - aux_o->w_list.n = aux_o->w_list.c.n = 0; - aux_o->y_id = z->y_id; aux_o->y_pos_strand = z->y_pos_strand; - aux_o->x_pos_s = z->x_pos_s; aux_o->x_pos_e = z->x_pos_e; - aux_o->y_pos_s = z->y_pos_s; aux_o->y_pos_e = z->y_pos_e; - - hc_ovlp_base_direct(z, ch_a, ch_n, wl, rref, qstr, tu, exz, aux_o, e_rate, ql, tl, rid, -1); - - int64_t aux_n = aux_o->w_list.n; - for (i = 0; i < aux_n; i++) { - // if(z->y_id == 30129) { - // fprintf(stderr, "[aln::-i->%ld::ql->%d] q::[%d, %d), t::[%d, %d), err::%d, clen::%u, mode::%d\n", i, - // aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start, - // aux_o->w_list.a[i].x_start, aux_o->w_list.a[i].x_end+1, - // aux_o->w_list.a[i].y_start, aux_o->w_list.a[i].y_end+1, - // aux_o->w_list.a[i].error, aux_o->w_list.a[i].clen, aux_o->w_list.a[i].error_threshold); - // } - if(!(is_ualn_win(aux_o->w_list.a[i]))) continue; - // if((aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start) <= FORCE_CNS_L) { - // fprintf(stderr, "[aln::-i->%ld::ql->%d] q::[%d, %d), t::[%d, %d), err::%d, clen::%u, mode::%d\n", i, - // aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start, - // aux_o->w_list.a[i].x_start, aux_o->w_list.a[i].x_end+1, - // aux_o->w_list.a[i].y_start, aux_o->w_list.a[i].y_end+1, - // aux_o->w_list.a[i].error, aux_o->w_list.a[i].clen, aux_o->w_list.a[i].error_threshold); - // } - //will overwrite ch_a; does not matter - rechain_aln_hc(z, cl, aux_o, i, wl, rref, qstr, tu, exz, e_rate, ql, tl, h_khit, rid); - } - - if(((int64_t)aux_o->w_list.n) > aux_n) { - for (i = m = 0; i < ((int64_t)aux_o->w_list.n); i++) { - if((i < aux_n) && (is_ualn_win(aux_o->w_list.a[i]))) continue; - aux_o->w_list.a[m++] = aux_o->w_list.a[i]; - } - aux_o->w_list.n = m; - radix_sort_window_list_xs_srt(aux_o->w_list.a, aux_o->w_list.a+aux_o->w_list.n); - } - - ///update z by aux_o - update_overlap_region(z, aux_o, ql, tl); - - aux_n = z->w_list.n; - for (i = tot_e = aln = 0; i < aux_n; i++) { - if(is_ualn_win(z->w_list.a[i])) { - xe = z->w_list.a[i].x_end + 1 - z->w_list.a[i].x_start; - ye = z->w_list.a[i].y_end + 1 - z->w_list.a[i].y_start; - tot_e += ((xe >= ye)?(xe):(ye)); - } else { - tot_e += z->w_list.a[i].error; aln += z->w_list.a[i].x_end + 1 - z->w_list.a[i].x_start; - } - } - *re = tot_e; - // fprintf(stderr, "[M::%s::%u->%u::%c] ovlp::%u, aln::%ld, tot_e::%ld, w_list.n::%u, ch_n::%ld\n", - // __func__, z->x_id, z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_e+1-z->x_pos_s, aln, tot_e, (uint32_t)z->w_list.n, ch_n); - - // debug_overlap_region(aux_o, qstr, tu, NULL, NULL, rref); - - - // ch_a = cl->list + ch_idx; //update - // for (i = 0; i < wn; i++) z->w_list.a[i].clen = 0;///clean cigar - // if(on > 1) { - // fprintf(stderr, "[M::%s::] rid::%lu, on::%ld\n", __func__, rid, on); - // } - // if(z->y_id == 126) prt_k_mer_hit(ch_a, ch_n); - // for (i = ch_i = 0; i < on; i++) { - // assert((i<=0)||(ov[i].qs > ov[i-1].qe)); - // ov[i].sec = 16;///do not know the aln type - // ch_i = sub_base_aln(z, dp, ch_a, ch_n, pe, ov[i].qs, ov[i].qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, tl, ch_i, rid); - // pe = ov[i].qe; - // } - - return 1; -} - - -uint64_t gen_hc_fast_non_retrieve_cigar0(overlap_region *z, Candidates_list *cl, uint64_t wl, char* qstr, int64_t ql, char* tstr, int64_t tl, bit_extz_t *exz, overlap_region *aux_o, double e_rate, uint64_t rid, int64_t h_khit) -{ - int64_t ch_idx = z->shared_seed, ch_n; - int64_t i, m, tot_e, aln; - k_mer_hit *ch_a = cl->list + ch_idx; - for (i = ch_idx; i < cl->length && cl->list[i].readID == cl->list[ch_idx].readID; i++); ch_n = i-ch_idx; - if(ch_n <= 0) return 0; - - - // fprintf(stderr, "[M::%s::rid->%ld] utg%.6dl(%c), z::[%u, %u)\n", - // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e+1); - aux_o->w_list.n = aux_o->w_list.c.n = 0; - aux_o->y_id = z->y_id; aux_o->y_pos_strand = z->y_pos_strand; - aux_o->x_pos_s = z->x_pos_s; aux_o->x_pos_e = z->x_pos_e; - aux_o->y_pos_s = z->y_pos_s; aux_o->y_pos_e = z->y_pos_e; - - hc_ovlp_base_non_retrieve_direct(z, ch_a, ch_n, wl, qstr, tstr, exz, aux_o, e_rate, ql, tl, rid); - - - int64_t aux_n = aux_o->w_list.n; - for (i = 0; i < aux_n; i++) { - if(!(is_ualn_win(aux_o->w_list.a[i]))) continue; - // if((aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start) <= FORCE_CNS_L) { - // fprintf(stderr, "[aln::-i->%ld::ql->%d] q::[%d, %d), t::[%d, %d), err::%d, clen::%u, mode::%d\n", i, - // aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start, - // aux_o->w_list.a[i].x_start, aux_o->w_list.a[i].x_end+1, - // aux_o->w_list.a[i].y_start, aux_o->w_list.a[i].y_end+1, - // aux_o->w_list.a[i].error, aux_o->w_list.a[i].clen, aux_o->w_list.a[i].error_threshold); - // } - //will overwrite ch_a; does not matter - rechain_aln_non_retrieve_hc(z, cl, aux_o, i, wl, qstr, tstr, exz, e_rate, ql, tl, h_khit, rid); - } - - if(((int64_t)aux_o->w_list.n) > aux_n) { - for (i = m = 0; i < ((int64_t)aux_o->w_list.n); i++) { - if((i < aux_n) && (is_ualn_win(aux_o->w_list.a[i]))) continue; - aux_o->w_list.a[m++] = aux_o->w_list.a[i]; - } - aux_o->w_list.n = m; - radix_sort_window_list_xs_srt(aux_o->w_list.a, aux_o->w_list.a+aux_o->w_list.n); - } - - ///update z by aux_o - update_overlap_region(z, aux_o, ql, tl); - - aux_n = z->w_list.n; - for (i = tot_e = aln = 0; i < aux_n; i++) { - if(is_ualn_win(z->w_list.a[i])) { - tot_e += z->w_list.a[i].x_end + 1 - z->w_list.a[i].x_start; - } else { - tot_e += z->w_list.a[i].error; aln += z->w_list.a[i].x_end + 1 - z->w_list.a[i].x_start; - } - } - // fprintf(stderr, "[M::%s::%u->%u::%c] ovlp::%u, aln::%ld, tot_e::%ld, w_list.n::%u, ch_n::%ld\n", - // __func__, z->x_id, z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_e+1-z->x_pos_s, aln, tot_e, (uint32_t)z->w_list.n, ch_n); - - // debug_overlap_region(aux_o, qstr, tu, NULL, NULL, rref); - - - // ch_a = cl->list + ch_idx; //update - // for (i = 0; i < wn; i++) z->w_list.a[i].clen = 0;///clean cigar - // if(on > 1) { - // fprintf(stderr, "[M::%s::] rid::%lu, on::%ld\n", __func__, rid, on); - // } - // if(z->y_id == 126) prt_k_mer_hit(ch_a, ch_n); - // for (i = ch_i = 0; i < on; i++) { - // assert((i<=0)||(ov[i].qs > ov[i-1].qe)); - // ov[i].sec = 16;///do not know the aln type - // ch_i = sub_base_aln(z, dp, ch_a, ch_n, pe, ov[i].qs, ov[i].qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, tl, ch_i, rid); - // pe = ov[i].qe; - // } - - - return 1; -} - - -#define gen_err_unaligned(xl, yl) (((xl)<=FORCE_SIN_L)?(MAX((xl), (yl))):MAX((MIN((xl), (yl))), ((xl*0.51)+1))) - -int64_t retrieve_cigar_err_debug(bit_extz_t *ez, int64_t s, int64_t e) -{ - if(!ez->cigar.n) return 0; - int64_t err = 0, xk = ez->ts; int64_t ws, we, os, oe, ovlp; - uint32_t ck = 0, cl; uint16_t op; - - os = MAX(s, ez->ts); oe = MIN(e, ez->te+1); - ovlp = ((oe>os)? (oe-os):0); - if(!ovlp) { - fprintf(stderr, "[M::%s::] s::%ld, e::%ld, ez->ts::%u, ez->te::%u\n", - __func__, s, e, ez->ts, ez->te); - } - assert(ovlp); - - //some cigar will span s or e - while (ck < ez->cigar.n && xk < e) {//[s, e) - ws = xk; - ck = pop_trace(&(ez->cigar), ck, &op, &cl); - if(op!=2) xk += cl; - we = xk; - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - if((op==2) && (ws>=s) && (wsw_list.n, ws, we, os, oe, ovlp; - window_list *m; int64_t xl, yl, werr, err; bit_extz_t ez; - for (wk = err = 0; wk < wn; wk++) { - m = &(z->w_list.a[wk]); - ws = m->x_start; we = m->x_end+1; - if(ws >= e) break; - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - if(ovlp) { - xl = m->x_end+1-m->x_start; - yl = m->y_end+1-m->y_start; - if((is_ualn_win((*m))) || (is_est_aln((*m)))) { - if(is_ualn_win((*m))) { //unmapped - werr = gen_err_unaligned(xl, yl); - } else { - werr = m->error;//shared window - } - if(ovlp < xl) { - werr = (((double)ovlp)/((double)xl))*((double)werr); - } - //skip the whole window - err += werr; - } else { - if(ovlp == xl) { - //skip the whole window - err += m->error; - } else { - set_bit_extz_t(ez, (*z), wk); - err += retrieve_cigar_err_debug(&ez, os, oe); - } - } - } - } - return err; -} - -int64_t retrieve_cigar_err(bit_extz_t *ez, int64_t s, int64_t e, int64_t *xk, int64_t *ck) -{ - if(!ez->cigar.n) return 0; - int64_t cn = ez->cigar.n, op, err = 0; int64_t ws, we, os, oe, ovlp; - if(((*ck) < 0) || ((*ck) > cn)) {//(*ck) == cn is allowed - (*ck) = 0; (*xk) = ez->ts; - } - - while ((*ck) > 0 && (*xk) > s) { - --(*ck); - op = ez->cigar.a[(*ck)]>>14; - if(op!=2) (*xk) -= (ez->cigar.a[(*ck)]&(0x3fff)); - } - - //some cigar will span s or e - while ((*ck) < cn && (*xk) < e) {//[s, e) - ws = (*xk); - op = ez->cigar.a[(*ck)]>>14; - if(op!=2) (*xk) += (ez->cigar.a[(*ck)]&(0x3fff)); - we = (*xk); - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - if((op==2) && (ws>=s) && (wscigar.a[(*ck)]&(0x3fff)); - } - - // if(s == 22694 && e == 38018) { - // fprintf(stderr, "[M::%s]\tw::[%ld,\t%ld)\tc::%ld\top::%ld\terr::%ld\n", __func__, ws, we, (*ck), op, err + (op?ovlp:0)); - // } - (*ck)++; - if((!ovlp) || (!op)) continue; - err += ovlp; - } - - // int64_t debug_err = retrieve_cigar_err_debug(ez, s, e); - // if(!(err == debug_err)) { - // fprintf(stderr, "[M::%s::] err::%ld, debug_err::%ld, s::%ld, e::%ld, ez->ts::%u, ez->te::%u\n", - // __func__, err, debug_err, s, e, ez->ts, ez->te); - // } - // assert(err == debug_err); - return err; -} -///[s, e) -int64_t extract_sub_cigar_err(overlap_region *z, int64_t s, int64_t e, ul_ov_t *p) -{ - int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), ck = ovlp_cur_coff(*p); - int64_t min_w = ovlp_min_wid(*p), max_w = ovlp_max_wid(*p);//[min_w, max_w] - bit_extz_t ez; window_list *m; - int64_t ws, we, os, oe, ovlp, err = 0, xl, yl, werr, tot = e - s; - if(wk < min_w || wk > max_w) wk = min_w; - for (; wk >= min_w && z->w_list.a[wk].x_start > s; wk--); - if(wk < min_w || wk > max_w) return -1; - for (; wk <= max_w && z->w_list.a[wk].x_end < s; wk++); - if(wk < min_w || wk > max_w) return -1; - //s >= w_list.a[wk].x_start && s <= w_list.a[wk].x_end - if(wk != ovlp_cur_wid(*p)) {//xk is global, while ck is local - xk = z->w_list.a[wk].x_start; ck = 0; - } - // fprintf(stderr, "[M::%s] wk::%ld, ck::%ld, xk::%ld\n", __func__, wk, ck, xk); - // fprintf(stderr, "+[M::%s] wk::%ld, ck::%ld, xk::%ld, w::[%d, %d), bound::[%ld, %ld)\n", - // __func__, wk, ck, xk, z->w_list.a[wk].x_start, z->w_list.a[wk].x_end+1, s, e); - - while(wk <= max_w && z->w_list.a[wk].x_start < e) {///[s, e) - m = &(z->w_list.a[wk]); - ws = m->x_start; we = m->x_end+1; - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - // fprintf(stderr, "-[M::%s] ovlp::%ld, wk::%ld, ck::%ld, xk::%ld, w::[%ld, %ld), bound::[%ld, %ld)\n", - // __func__, ovlp, wk, ck, xk, ws, we, s, e); - if(ovlp) { - xl = m->x_end+1-m->x_start; - yl = m->y_end+1-m->y_start; - if((is_ualn_win((*m))) || (is_est_aln((*m)))) { - if(is_ualn_win((*m))) { //unmapped - werr = gen_err_unaligned(xl, yl); - } else { - werr = m->error;//shared window - } - if(ovlp < xl) { - werr = (((double)ovlp)/((double)xl))*((double)werr); - } - //skip the whole window - err += werr; xk = m->x_end+1; ck = m->clen; - } else { - if(ovlp == xl) { - //skip the whole window - err += m->error; xk = m->x_end+1; ck = m->clen; - } else { - // if(os == 22694 && oe == 38018) { - // fprintf(stderr, "\n-[M::%s]\tos::%ld\toe::%ld\n", __func__, os, oe); - // } - set_bit_extz_t(ez, (*z), wk); - err += retrieve_cigar_err(&ez, os, oe, &xk, &ck); - } - } - } - tot -= ovlp; - if(xk >= e) break;//[min_w, max_w] && [s, e) - wk++; if(wk > max_w) break; - xk = z->w_list.a[wk].x_start; ck = 0;//reset - } - assert(!tot); - ovlp_cur_wid(*p) = wk; ovlp_cur_xoff(*p) = xk; ovlp_cur_coff(*p) = ck; - return err; -} - -#define bst_ov(x) ((x).misBase) -#define ov_dif(x) ((x).cov) -#define ov_id(x) ((x).overlapID) -#define ov_xoff(x) ((x).site) -#define var_id(x) ((x).overlapSite) - -#define var_s(x) ((x).site) -#define var_l(x) ((x).overlap_num) -#define var_occ(x) ((x).occ_0) -#define var_min_dif(x) ((x).score) -#define var_min_ovid(x) ((x).id) -#define var_h_idx(x) ((x).occ_1) - - -uint64_t query_gen_gov_idx(asg64_v *ovidx, uint64_t v, uint64_t w) -{ - uint64_t m, s, e; - if(v > w) { - m = v; v = w; w = m; - } - s = ovidx->a[v]>>32; e = s + (uint32_t)ovidx->a[v]; - for (m = s; m < e; m++) { - if(ovidx->a[m] == w) return 1; - } - return 0; -} - -void push_sec_aln(overlap_region *z, int64_t s, int64_t e, int64_t sec_err) -{ - window_list *p; - if(z->align_length > 0) { - p = z->w_list.a + z->w_list.n + z->align_length - 1; - if((p->x_end == s) && ((!!(p->clen)) == (!!sec_err))) { - p->x_end = e; p->clen += sec_err; - return; - } - } - if((z->w_list.n+z->align_length)==z->w_list.m) { - z->w_list.m = z->w_list.m? z->w_list.m<<1 : 2; - z->w_list.a = (window_list*)realloc(z->w_list.a, sizeof(window_list)*z->w_list.m); - } - p = &(z->w_list.a[z->w_list.n+z->align_length]); z->align_length++; memset(p, 0, sizeof((*p))); - p->x_start = s; p->x_end = e; p->clen += sec_err; -} - -void push_sec_aln_robust(overlap_region *z, int64_t s, int64_t e, int64_t sec_err) -{ - window_list *p; - if(z->align_length > 0) { - p = z->w_list.a + z->w_list.n + z->align_length - 1; - if((p->x_end == s) && (p->clen == 0) && ((!!(p->clen)) == (!!sec_err))) { - p->x_end = e; p->clen += sec_err; - return; - } - } - if((z->w_list.n+z->align_length)==z->w_list.m) { - z->w_list.m = z->w_list.m? z->w_list.m<<1 : 2; - z->w_list.a = (window_list*)realloc(z->w_list.a, sizeof(window_list)*z->w_list.m); - } - p = &(z->w_list.a[z->w_list.n+z->align_length]); z->align_length++; memset(p, 0, sizeof((*p))); - p->x_start = s; p->x_end = e; p->clen += sec_err; -} - -// #define id_mm ((uint64_t)0x7fffffffffffffff) -#define id_set ((uint64_t)0x8000000000000000) -#define id_get(a) ((uint32_t)(a)) -#define err_get(a) (((a)&((uint64_t)0x7fffffffffffffff))>>32) - -void reassign_sec_err(overlap_region* ol, asg64_v *ovidx, asg64_v *buf, uint64_t bid0) -{ - uint64_t bn = buf->n, bid = bid0, oid, mid, m, s, e; - if(buf->a[bid]&id_set) return; - kv_push(uint64_t, *buf, bid); - while (buf->n > bn) { - bid = buf->a[--buf->n]; - if(buf->a[bid]&id_set) continue; - buf->a[bid]|=id_set; - - oid = id_get(buf->a[bid]); - s = ovidx->a[oid]>>32; e = (uint32_t)ovidx->a[oid]; - for (m = s; m < e; m++) { - mid = ol[(uint32_t)ovidx->a[m]].overlapLen; - if(mid == (uint32_t)-1) continue; - if(buf->a[mid]&id_set) continue; - kv_push(uint64_t, *buf, mid); - } - } -} -///[s, e) -uint64_t gen_region_phase(overlap_region* ol, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, uint64_t dp, ul_ov_t *c_idx, asg64_v *buf, asg64_v *ovidx) -{ - if(!id_n) return id_n; - uint64_t k, m, mn, q[2], buf_n, rm_n, oid; int64_t err, msc, msc_k, msc_n; - overlap_region *z; ul_ov_t *p; buf->n = 0; kv_resize(uint64_t, *buf, dp); - for (k = buf_n = rm_n = 0; k < id_n; k++) { - p = &(c_idx[id_a[k]]); - q[0] = ol[ovlp_id(*p)].w_list.a[ovlp_min_wid(*p)].x_start; - q[1] = ol[ovlp_id(*p)].w_list.a[ovlp_max_wid(*p)].x_end+1; - if(q[0]<=s && q[1]>=e) { - kv_push(uint64_t, *buf, id_a[k]); - // buf[buf_n++] = id_a[k]; - } - if(q[1] < e) rm_n++; - } - buf_n = buf->n; - assert(buf_n == dp);//not right - - if(buf_n > 0) { - for (k = 0, msc = INT32_MAX, msc_k = -1, msc_n = 0; k < buf_n; k++) { - p = &(c_idx[(uint32_t)buf->a[k]]); z = &(ol[ovlp_id(*p)]); - // fprintf(stderr, "+++[M::%s::utg%.6dl] wid::%u, xoff::%u, coff::%u\n", __func__, - // (int32_t)ol[ovlp_id(*p)].y_id+1, ovlp_cur_wid(*p), ovlp_cur_xoff(*p), ovlp_cur_coff(*p)); - err = extract_sub_cigar_err(z, s, e, p); - // int64_t debug_err = extract_sub_cigar_err_debug(z, s, e); - // assert(err == debug_err); - // fprintf(stderr, "[M::%s::] err::%ld, debug_err::%ld\n", __func__, err, debug_err); - - // fprintf(stderr, "---[M::%s::utg%.6dl] wid::%u, xoff::%u, coff::%u, err::%ld\n", __func__, - // (int32_t)ol[ovlp_id(*p)].y_id+1, ovlp_cur_wid(*p), ovlp_cur_xoff(*p), ovlp_cur_coff(*p), err); - fprintf(stderr, "---[M::%s::utg%.6dl] xoff::[%lu, %lu), err::%ld\n", __func__, - (int32_t)ol[ovlp_id(*p)].y_id+1, s, e, err); - assert(err >= 0); - if(err < msc) { - msc = err; msc_k = k; msc_n = 1; - } else if(err == msc) { - msc_n++; - } - buf->a[k] |= (((uint64_t)err)<<32); - } - - if(msc_n == 1) { - p = &(c_idx[(uint32_t)buf->a[msc_k]]); - z = &(ol[ovlp_id(*p)]); mn = 1; - if(msc_k != 0) { - m = buf->a[msc_k]; - buf->a[msc_k] = buf->a[0]; - buf->a[0] = m; - } - } else { - for (k = mn = 0; k < buf_n && (int64_t)mn < msc_n; k++) { - p = &(c_idx[(uint32_t)buf->a[k]]); - z = &(ol[ovlp_id(*p)]); - if((buf->a[k]>>32) == (uint64_t)msc) { - if(mn != k) { - m = buf->a[k]; - buf->a[k] = buf->a[mn]; - buf->a[mn] = m; - } - mn++; - } - } - } - // fprintf(stderr, "[M::%s] buf_n::%ld, msc_n::%ld, mn::%lu\n", __func__, buf_n, msc_n, mn); - for (k = 0; k < buf_n; k++) { - oid = ovlp_id((c_idx[(uint32_t)buf->a[k]])); - buf->a[k] >>= 32; buf->a[k] <<= 32; buf->a[k] |= oid; - ol[oid].overlapLen = k; - // if(s == 158482) fprintf(stderr, "k->%ld::oid->%ld[M::%s::utg%.6dl] pos::[%lu, %lu)\n", k, oid, __func__, - // (int32_t)ol[oid].y_id+1, s, e); - } - - for (k = 0; k < mn; k++) {///best alignment - z = &(ol[id_get(buf->a[k])]); - reassign_sec_err(ol, ovidx, buf, k); - push_sec_aln(z, s, e, 0); - } - - for (k = mn; k < buf_n; k++) { - z = &(ol[id_get(buf->a[k])]); - push_sec_aln(z, s, e, ((buf->a[k]&id_set)?(0):(err_get(buf->a[k])-msc))); - } - - for (k = 0; k < buf_n; k++) { - ol[id_get(buf->a[k])].overlapLen = (uint32_t)-1; - } - } - - - if(rm_n) { - for (k = m = 0; k < id_n; k++) { - p = &(c_idx[id_a[k]]); - q[1] = ol[ovlp_id(*p)].w_list.a[ovlp_max_wid(*p)].x_end+1; - if(q[1] < e) continue; - id_a[m++] = id_a[k]; - } - id_n = m; - } - return id_n; -} - - -///[s, e) -uint64_t gen_region_phase_robust(overlap_region* ol, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, uint64_t dp, ul_ov_t *c_idx, asg64_v *buf) -{ - if(!id_n) return id_n; - uint64_t k, m, mn, q[2], buf_n, rm_n, oid; int64_t err, msc, msc_k, msc_n; - overlap_region *z; ul_ov_t *p; buf->n = 0; kv_resize(uint64_t, *buf, dp); - for (k = buf_n = rm_n = 0; k < id_n; k++) { - p = &(c_idx[id_a[k]]); - q[0] = ol[ovlp_id(*p)].w_list.a[ovlp_min_wid(*p)].x_start; - q[1] = ol[ovlp_id(*p)].w_list.a[ovlp_max_wid(*p)].x_end+1; - if(q[0]<=s && q[1]>=e) { - kv_push(uint64_t, *buf, id_a[k]); - // buf[buf_n++] = id_a[k]; - } - if(q[1] < e) rm_n++; - } - buf_n = buf->n; - assert(buf_n == dp);//not right - - if(buf_n > 0) { - for (k = 0, msc = INT32_MAX, msc_k = -1, msc_n = 0; k < buf_n; k++) { - p = &(c_idx[(uint32_t)buf->a[k]]); z = &(ol[ovlp_id(*p)]); - // fprintf(stderr, "+++[M::%s::utg%.6dl] wid::%u, xoff::%u, coff::%u\n", __func__, - // (int32_t)ol[ovlp_id(*p)].y_id+1, ovlp_cur_wid(*p), ovlp_cur_xoff(*p), ovlp_cur_coff(*p)); - err = extract_sub_cigar_err(z, s, e, p); - // int64_t debug_err = extract_sub_cigar_err_debug(z, s, e); - // assert(err == debug_err); - // fprintf(stderr, "[M::%s::] err::%ld, debug_err::%ld\n", __func__, err, debug_err); - - // fprintf(stderr, "---[M::%s::utg%.6dl] wid::%u, xoff::%u, coff::%u, err::%ld\n", __func__, - // (int32_t)ol[ovlp_id(*p)].y_id+1, ovlp_cur_wid(*p), ovlp_cur_xoff(*p), ovlp_cur_coff(*p), err); - // fprintf(stderr, "---[M::%s::utg%.6dl] xoff::[%lu, %lu), err::%ld\n", __func__, - // (int32_t)ol[ovlp_id(*p)].y_id+1, s, e, err); - assert(err >= 0); - if(err < msc) { - msc = err; msc_k = k; msc_n = 1; - } else if(err == msc) { - msc_n++; - } - buf->a[k] |= (((uint64_t)err)<<32); - } - - if(msc_n == 1) { - p = &(c_idx[(uint32_t)buf->a[msc_k]]); - z = &(ol[ovlp_id(*p)]); mn = 1; - if(msc_k != 0) { - m = buf->a[msc_k]; - buf->a[msc_k] = buf->a[0]; - buf->a[0] = m; - } - } else { - for (k = mn = 0; k < buf_n && (int64_t)mn < msc_n; k++) { - p = &(c_idx[(uint32_t)buf->a[k]]); - z = &(ol[ovlp_id(*p)]); - if((buf->a[k]>>32) == (uint64_t)msc) { - if(mn != k) { - m = buf->a[k]; - buf->a[k] = buf->a[mn]; - buf->a[mn] = m; - } - mn++; - } - } - } - // fprintf(stderr, "[M::%s] buf_n::%ld, msc_n::%ld, mn::%lu\n", __func__, buf_n, msc_n, mn); - for (k = 0; k < buf_n; k++) { - oid = ovlp_id((c_idx[(uint32_t)buf->a[k]])); - buf->a[k] >>= 32; buf->a[k] <<= 32; buf->a[k] |= oid; - // ol[oid].overlapLen = k;//no need to set - // if(s == 158482) fprintf(stderr, "k->%ld::oid->%ld[M::%s::utg%.6dl] pos::[%lu, %lu)\n", k, oid, __func__, - // (int32_t)ol[oid].y_id+1, s, e); - } - - for (k = 0; k < mn; k++) {///best alignment - z = &(ol[id_get(buf->a[k])]); - // reassign_sec_err(ol, ovidx, buf, k); - // push_sec_aln(z, s, e, 0); - push_sec_aln_robust(z, s, e, 0); - } - - for (k = mn; k < buf_n; k++) { - z = &(ol[id_get(buf->a[k])]); - // push_sec_aln(z, s, e, ((buf->a[k]&id_set)?(0):(err_get(buf->a[k])-msc))); - push_sec_aln_robust(z, s, e, (err_get(buf->a[k])-msc)); - } - - // for (k = 0; k < buf_n; k++) { - // ol[id_get(buf->a[k])].overlapLen = (uint32_t)-1; - // } - } - - - if(rm_n) { - for (k = m = 0; k < id_n; k++) { - p = &(c_idx[id_a[k]]); - q[1] = ol[ovlp_id(*p)].w_list.a[ovlp_max_wid(*p)].x_end+1; - if(q[1] < e) continue; - id_a[m++] = id_a[k]; - } - id_n = m; - } - return id_n; -} - -///[s, e) -int64_t extract_sub_cigar_err_rr(overlap_region *z, int64_t s, int64_t e, ul_ov_t *p) -{ - int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), ck = ovlp_cur_coff(*p); - int64_t min_w = ovlp_min_wid(*p), max_w = ovlp_max_wid(*p);//[min_w, max_w] - bit_extz_t ez; window_list *m; int64_t bd = ovlp_bd(*p), s0, e0; - s0 = ((int64_t)(z->w_list.a[min_w].x_start)) + bd; - e0 = ((int64_t)(z->w_list.a[max_w].x_end))+1-bd; - if(s < s0) s = s0; if(e > e0) e = e0;///exclude boundary - if(s >= e) return -1; - - int64_t ws, we, os, oe, ovlp, err = 0, xl, yl, werr, tot = e - s; - if(wk < min_w || wk > max_w) wk = min_w; - for (; wk >= min_w && z->w_list.a[wk].x_start > s; wk--); - if(wk < min_w || wk > max_w) return -1; - for (; wk <= max_w && z->w_list.a[wk].x_end < s; wk++); - if(wk < min_w || wk > max_w) return -1; - //s >= w_list.a[wk].x_start && s <= w_list.a[wk].x_end - if(wk != ovlp_cur_wid(*p)) {//xk is global, while ck is local - xk = z->w_list.a[wk].x_start; ck = 0; - } - - while(wk <= max_w && z->w_list.a[wk].x_start < e) {///[s, e); [min_w, max_w] - m = &(z->w_list.a[wk]); - ws = m->x_start; we = m->x_end+1; - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - - if(ovlp) { - xl = m->x_end+1-m->x_start; - yl = m->y_end+1-m->y_start; - if((is_ualn_win((*m))) || (is_est_aln((*m)))) { - if(is_ualn_win((*m))) { //unmapped - werr = gen_err_unaligned(xl, yl); - } else { - werr = m->error;//shared window - } - if(ovlp < xl) { - werr = (((double)ovlp)/((double)xl))*((double)werr); - } - //skip the whole window - err += werr; xk = m->x_end+1; ck = m->clen; - } else { - if(ovlp == xl) { - //skip the whole window - err += m->error; xk = m->x_end+1; ck = m->clen; - } else { - set_bit_extz_t(ez, (*z), wk); - err += retrieve_cigar_err(&ez, os, oe, &xk, &ck); - } - } - } - tot -= ovlp; - if(xk >= e) break;//[min_w, max_w] && [s, e) - wk++; if(wk > max_w) break; - xk = z->w_list.a[wk].x_start; ck = 0;//reset - } - assert(!tot); - ovlp_cur_wid(*p) = wk; ovlp_cur_xoff(*p) = xk; ovlp_cur_coff(*p) = ck; - return err; -} - -///[s, e) -inline int64_t detect_near_cc_tlen(bit_extz_t *ez, int64_t ck0, int64_t xk0, int64_t yk0, uint8_t rev) -{ - int64_t ck = ck0, xk = xk0, yk = yk0, cn = ez->cigar.n, op; - if(!rev) { - if(ck >= cn) return yk; - while (ck < cn) { - op = ez->cigar.a[ck]>>14; - if(op == 0) return yk; - if(op!=2) xk += (ez->cigar.a[ck]&(0x3fff)); - if(op!=3) yk += (ez->cigar.a[ck]&(0x3fff)); - ck++; - } - } else { - if(ck <= 0) return yk; - while (ck > 0) { - --ck; - op = ez->cigar.a[ck]>>14; - if(op == 0) return yk; - if(op!=2) xk -= (ez->cigar.a[ck]&(0x3fff)); - if(op!=3) yk -= (ez->cigar.a[ck]&(0x3fff)); - } - } - - return yk; -} - -///[s, e) -int64_t extract_sub_cigar_hc(overlap_region *z, All_reads *rref, haplotype_evdience_alloc* hp, char *qstr, uint64_t ql, UC_Read* tu, int64_t s, int64_t e, ul_ov_t *p, int64_t set_f, uint8_t *f, uint8_t occ_thres, uint64_t hpc_len/**, uint8_t is_dbg**/) -{ - // fprintf(stderr, "\n[M::%s]\ts::%ld\te::%ld\tset_f::%ld\tovlp_id::%u\twid::%u\n", __func__, s, e, set_f, ovlp_id(*p), ovlp_cur_wid(*p)); - // if((!set_f) && (!ovlp_cur_ylen(*p))) return 1;///no potential informative site - int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), yk = ovlp_cur_yoff(*p), ck = ovlp_cur_coff(*p), os, oe, t; - bit_extz_t ez; int64_t bd = ovlp_bd(*p), s0, e0; char *ystr = NULL; - s0 = ((int64_t)(z->w_list.a[wk].x_start)) + bd; - e0 = ((int64_t)(z->w_list.a[wk].x_end)) + 1 - bd; - if(s < s0) s = s0; if(e > e0) e = e0;///exclude boundary - if(s >= e) return -1; - os = MAX(s, s0); oe = MIN(e, e0); - if(oe <= os) return -1; - - set_bit_extz_t(ez, (*z), wk); - if(!ez.cigar.n) return -1; - int64_t cn = ez.cigar.n, op; int64_t ws, we, ovlp, xk0, yk0, ck0, yk1 = -1, /**xk1 = -1, ck1 = -1,**/ yl; haplotype_evdience ev; uint8_t om; - xk0 = xk; yk0 = yk; ck0 = ck; ///for assertion - if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed - ck = 0; xk = ez.ts; yk = ez.ps; - } - - while (ck > 0 && xk > s) {///x -> t; y -> p - --ck; - op = ez.cigar.a[ck]>>14; - if(op!=2) xk -= (ez.cigar.a[ck]&(0x3fff)); - if(op!=3) yk -= (ez.cigar.a[ck]&(0x3fff)); - } - - if(set_f) { - ovlp_cur_ylen(*p) = 0; - xk0 = xk; yk0 = yk; ck0 = ck; - } else { - assert(xk0 == xk); assert(yk0 == yk); assert(ck0 == ck); - yk1 = yk0 + ovlp_cur_ylen(*p); yl = Get_READ_LENGTH((*rref), z->y_id); - - // UC_Read_resize(*tu, ovlp_cur_ylen(*p)); ystr = tu->seq; - // if(is_dbg) fprintf(stderr, "[M::%s] set_f::%ld, yk0::%ld, ovlp_cur_ylen::%u, ylen::%lu\n", __func__, set_f, yk0, ovlp_cur_ylen(*p), Get_READ_LENGTH((*rref), z->y_id)); - // recover_UC_Read_sub_region(ystr, yk0, ovlp_cur_ylen(*p), z->y_pos_strand, rref, z->y_id); - } - - // if(is_dbg) fprintf(stderr, "---0---[M::%s] set_f::%ld, yk::%ld\n", __func__, set_f, yk); - //some cigar will span s or e - while (ck < cn && xk < e) {//[s, e) - ws = xk; - op = ez.cigar.a[ck]>>14; - if(op!=2) xk += (ez.cigar.a[ck]&(0x3fff)); - if(op!=3) yk += (ez.cigar.a[ck]&(0x3fff)); - ck++; we = xk; - if(op != 0 && op != 1) continue;///only collect match/snp - - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - if(!ovlp) continue; - - if(set_f) { - if(op == 1) { - for (t = os; t < oe; t++) { - f[t-s] = ((f[t-s]<=126)?(f[t-s]+1):(127)); - } - // if(!hpc_len) { - // yk1 = oe-xk+yk; - // } else { - // yk1 = yk; xk1 = xk; ck1 = ck; - // } - yk1 = oe-xk+yk; - } - } else { - if(op == 0) { - for (t = os; t < oe; t++) { - if(f[t-s]) { - om = ((f[t-s]==3)?1:0); - ev.misBase = qstr[t]; - ev.overlapID = ovlp_id(*p); - ev.site = t; - ev.overlapSite = t-xk+yk; - ev.type = (om<<1); - ev.cov = 1; - addHaplotypeEvdience(hp, &ev, NULL); - } - } - } else if(op == 1) { - for (t = os; t < oe; t++) { - if(f[t-s]) { - if(!ystr) { - // yk0 = ((hpc_len)?(detect_near_cc_tlen(&ez, ck, xk, yk, 1)):(t-xk+yk)); - yk0 = t-xk+yk; - yk0 -= hpc_len; if(yk0 < 0) yk0 = 0; - UC_Read_resize(*tu, (yk1 - yk0)); ystr = tu->seq; - recover_UC_Read_sub_region(ystr, yk0, (yk1 - yk0), z->y_pos_strand, rref, z->y_id); - } - - om = ((f[t-s]==3)?1:0); - if((!om) && (hpc_len) && (hpc_mask_ff(ystr, yk1 - yk0, t-xk+yk-yk0, hpc_len, HPC_RR, NULL, -1, -1, HPC_CC))) om = 1; - - ev.misBase = ystr[t-xk+yk-yk0]; - ev.overlapID = ovlp_id(*p); - ev.site = t; - ev.overlapSite = t-xk+yk; - ev.type = (om<<1) + 1; - ev.cov = 1; - addHaplotypeEvdience(hp, &ev, NULL); - // if(ev.overlapID == 21 && ev.site == 17129) { - // fprintf(stderr, "[M::%s]\ts::%ld\te::%ld\tck::%ld\txk::%ld\tyk::%ld\tset_f::%ld\n", __func__, s, e, ck, xk, yk, set_f); - // } - } - - } - } - } - } - // if(is_dbg) fprintf(stderr, "---1---[M::%s] set_f::%ld, yk::%ld\n", __func__, set_f, yk); - - if(set_f) { - ovlp_cur_xoff(*p) = xk0; ovlp_cur_yoff(*p) = yk0; ovlp_cur_coff(*p) = ck0; - if(yk1 != -1) { - // if((xk1 != -1) && (yk1 != -1)) {///detect nearby differences - // yk1 = detect_near_cc_tlen(&ez, ck1, xk1, yk1, 0); - // } - yk1 += hpc_len; - yl = Get_READ_LENGTH((*rref), z->y_id); - if(yk1 > yl) yk1 = yl; - ovlp_cur_ylen(*p) = yk1 - yk0; - } else {///no potential informative site; no second round - ovlp_cur_ylen(*p) = 0; - } - } else { - ovlp_cur_xoff(*p) = xk; ovlp_cur_yoff(*p) = yk; ovlp_cur_coff(*p) = ck; ovlp_cur_ylen(*p) = 0; - } - - return 1; -} - -///[s, e) -int64_t extract_sub_err(overlap_region *z, int64_t s, int64_t e, int64_t os0, int64_t oe0, int64_t err0, double err_sec_rate, ul_ov_t *p) -{ - // fprintf(stderr, "\n[M::%s]\ts::%ld\te::%ld\tset_f::%ld\tovlp_id::%u\twid::%u\n", __func__, s, e, set_f, ovlp_id(*p), ovlp_cur_wid(*p)); - // if((!set_f) && (!ovlp_cur_ylen(*p))) return 1;///no potential informative site - int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), yk = ovlp_cur_yoff(*p), ck = ovlp_cur_coff(*p), os, oe, t, l[2], err; - bit_extz_t ez; int64_t bd = ovlp_bd(*p), s0, e0; - s0 = ((int64_t)(z->w_list.a[wk].x_start)) + bd; - e0 = ((int64_t)(z->w_list.a[wk].x_end)) + 1 - bd; - if(s < s0) s = s0; if(e > e0) e = e0;///exclude boundary - if(s >= e) return -1; - os = MAX(s, s0); oe = MIN(e, e0); - if(oe <= os) return -1; - - set_bit_extz_t(ez, (*z), wk); - if(!ez.cigar.n) return -1; - int64_t cn = ez.cigar.n, op, ol; int64_t ws, we, ovlp; - if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed - ck = 0; xk = ez.ts; yk = ez.ps; - } - - while (ck > 0 && xk >= s) {///x -> t; y -> p - --ck; - op = ez.cigar.a[ck]>>14; - if(op!=2) xk -= (ez.cigar.a[ck]&(0x3fff)); - if(op!=3) yk -= (ez.cigar.a[ck]&(0x3fff)); - } - - // if(is_dbg) fprintf(stderr, "---0---[M::%s] set_f::%ld, yk::%ld\n", __func__, set_f, yk); - //some cigar will span s or e - l[0] = l[1] = 0; - while (ck < cn && xk < e) {//[s, e) - ws = xk; - op = ez.cigar.a[ck]>>14; - ol = (ez.cigar.a[ck]&(0x3fff)); - if(op!=2) xk += ol; - if(op!=3) yk += ol; - ck++; we = xk; t= 0; - // if(op != 0 && op != 1) continue;///only collect match/snp - - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - if((op==2) && (ws == we) && ((ws>=s) && (ws<=e))) t = 1; - if(ovlp) t = 1; - if(!t) continue; - - if(op!=2) { - l[(!!op)] += ovlp; - } else { - l[1] += ol; - } - } - - while (ck < cn && xk <= e) {//[s, e) - ws = xk; - op = ez.cigar.a[ck]>>14; ol = (ez.cigar.a[ck]&(0x3fff)); - if(op != 2) break; - - for (ck++; (ck < cn) && (op == (ez.cigar.a[ck]>>14)); ck++) { - ol += (ez.cigar.a[ck]&(0x3fff)); - } - yk += ol; we = xk; - - if(ws >= s && ws <= e) l[1] += ol; - } - // if(is_dbg) fprintf(stderr, "---1---[M::%s] set_f::%ld, yk::%ld\n", __func__, set_f, yk); - - ovlp_cur_xoff(*p) = xk; ovlp_cur_yoff(*p) = yk; - ovlp_cur_coff(*p) = ck; ovlp_cur_ylen(*p) = 0; - - // fprintf(stderr, "[M::%s] cid::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\n", __func__, c_idx->a[zi].ts, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), c_idx->a[zi].qs, c_idx->a[zi].qe, c_idx->a[zi].qn); - - - - err = err0; - if((oe0 - os0) < (e - s)) { - err = (((double)(oe0 - os0))/((double)(e - s)))*err0; - } - err *= err_sec_rate; - // fprintf(stderr, "[M::%s]\t%.*s\tl[0]::%ld\tl[1]::%ld\tthres::%ld\n", __func__, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), l[0], l[1], err); - if(l[1] <= err) return l[1]; - return -1; -} - - -uint64_t iter_sub_cigar_sv(int64_t zid, ul_ov_t *cp, bit_extz_t *ez, int64_t *ck, int64_t *xk, int64_t *yk, char *qstr, int64_t ql, char *tstr, int64_t tl, int64_t ts, int64_t te, int64_t hpc_len, int64_t hpc_rr, int64_t *rys, int64_t *rye, int64_t exd_err_bd) -{ - int64_t err = 0, herr = 0, ex[2], ey[2], s, e, cn = ez->cigar.n, wx[2], wy[2], p; uint16_t op; uint32_t cl; - ex[0] = ex[1] = -1; ey[0] = ey[1] = -1; - (*rys) = (*rye) = -1; - // fprintf(stderr, "+[M::%s] rid::%u\t%.*s\tq::[%u,%u)\tql::%ld\tt::[%u,%u)\ttl::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), cp->qs, cp->qe, ql, cp->ts, cp->te, tl); - - s = cp->qs; e = cp->qe; - while ((*ck) > 0 && (*xk) >= s) {///x -> t; y -> p - --(*ck); - op = ez->cigar.a[*ck]>>14; - if(op!=2) (*xk) -= (ez->cigar.a[*ck]&(0x3fff)); - if(op!=3) (*yk) -= (ez->cigar.a[*ck]&(0x3fff)); - } - - while ((*ck) < cn && (*xk) < e) {//[s, e) - wx[0] = *xk; wy[0] = *yk; - (*ck) = pop_trace(&(ez->cigar), *ck, &op, &cl); - if(op!=2) (*xk) += cl; - if(op!=3) (*yk) += cl; - wx[1] = (*xk); wy[1] = (*yk); - if(op == 0) continue; - if(wx[0] >= s && wx[1] <= e) { - if(ex[0] < 0) ex[0] = wx[0]; - if(ey[0] < 0) ey[0] = wy[0]; - ex[1] = wx[1]; ey[1] = wy[1]; - err += cl; - if(hpc_len > 0) { - assert(wy[0] >= ts && wy[1] <= te); - if(hpc_mask_ff_region(qstr, ql, wx[0], wx[1], hpc_len, hpc_rr, 6, 0.51) || hpc_mask_ff_region(tstr, tl, wy[0] - ts, wy[1] - ts, hpc_len, hpc_rr, 6, 0.51)) { - herr += cl; - } - } - } - } - - while ((*ck) < cn && (*xk) <= e) {//[s, e) - wx[0] = *xk; wy[0] = *yk; - op = ez->cigar.a[*ck]>>14; - cl = (ez->cigar.a[*ck]&(0x3fff)); - if(op != 2) break; - (*yk) += (ez->cigar.a[*ck]&(0x3fff)); - (*ck)++; wx[1] = (*xk); wy[1] = (*yk); - if(wx[0] >= s && wx[1] <= e) { - if(ex[0] < 0) ex[0] = wx[0]; - if(ey[0] < 0) ey[0] = wy[0]; - ex[1] = wx[1]; ey[1] = wy[1]; - err += cl; - if(hpc_len > 0) { - assert(wy[0] >= ts && wy[1] <= te); - if(hpc_mask_ff_region(qstr, ql, wx[0], wx[1], hpc_len, hpc_rr, 6, 0.51) || hpc_mask_ff_region(tstr, tl, wy[0] - ts, wy[1] - ts, hpc_len, hpc_rr, 6, 0.51)) { - herr += cl; - } - } - } - } - - if(hpc_len > 0) { - // cp->qs = ex[0]; cp->qe = ex[1]; - // cp->ts = ey[0]; cp->te = ey[1]; - // cp->ts = s; cp->te = e; - assert(cp->qn == err); - cp->qs = s; cp->qe = e; - cp->ts = ex[0]; cp->te = ex[1]; - cp->tn = zid; cp->qn = err; - if((herr > 0) && (herr > (err*0.66))) cp->el = 0; - else cp->el = 1; - // (*rys) = ey[0]; (*rye) = ey[1]; - if(err <= exd_err_bd) { - p = (s + e)/2; p -= exd_err_bd; if(p < 0) p = 0; if(p < ((int64_t)cp->qs)) cp->qs = p; - p = (s + e)/2; p += exd_err_bd; if(p > ql) p = ql; if(p > ((int64_t)cp->qe)) cp->qe = p; - } - } - // else { - // assert(cp->qn == err); - // } - (*rys) = ey[0]; (*rye) = ey[1]; - - return err; -} - -int64_t extract_sub_cigar_sv(overlap_region *z, int64_t zid, int64_t wk, All_reads *rref, char *qstr, int64_t ql, UC_Read* tu, kv_ul_ov_t *rr, uint64_t min_err, int64_t hpc_len, int64_t hpc_rr) -{ - int64_t xk = z->w_list.a[wk].x_start, yk = z->w_list.a[wk].y_start; ul_ov_t *cp, *ra; bit_extz_t ez; - int64_t ck = 0, ex[2], ey[2], el0, tl = Get_READ_LENGTH((*rref), z->y_id), ox[2], oy[2], os, oe, ff, rn, rn1, k; uint32_t cl, rr_n0 = rr->n, is_srt = 1; - set_bit_extz_t(ez, (*z), wk); - if(!ez.cigar.n) return -1; - int64_t cn = ez.cigar.n, wx[2], wy[2]; uint16_t op, op0; - ex[0] = ex[1] = ey[0] = ey[1] = -1; - - while (ck < cn) {//[s, e) - wx[0] = xk; wy[0] = yk; el0 = 0; - op = (ez.cigar.a[ck]>>14); - cl = (ez.cigar.a[ck]&(0x3fff)); - if(op!=2) xk += cl; if(op!=3) yk += cl; - op0 = op; el0 += cl; - for (ck++; ck < cn; ck++) { - op = (ez.cigar.a[ck]>>14); - if((!!op) != (!!op0)) break; - cl = (ez.cigar.a[ck]&(0x3fff)); - if(op!=2) xk += cl; if(op!=3) yk += cl; - el0 += cl; - } - wx[1] = xk; wy[1] = yk; - if(op0 == 0) continue; - ff = 1; - - - ox[0] = ((wx[0]>=el0)?(wx[0]-el0):(0)); ox[1] = ((wx[1]+el0<=ql)?(wx[1]+el0):(ql)); - oy[0] = ((wy[0]>=el0)?(wy[0]-el0):(0)); oy[1] = ((wy[1]+el0<=tl)?(wy[1]+el0):(tl)); - - if(ex[0] < 0 || ex[1] < 0 || ey[0] < 0 || ey[1] < 0) ff = 0; - - if(ff) { - os = MAX(ox[0], ex[0]); oe = MIN(ox[1], ex[1]); - if(oe <= os) ff = 0; - - os = MAX(oy[0], ey[0]); oe = MIN(oy[1], ey[1]); - if(oe <= os) ff = 0; - } - - if(ff) {///extend - ex[0] = MIN(ox[0], ex[0]); ex[1] = MAX(ox[1], ex[1]); - ey[0] = MIN(oy[0], ey[0]); ey[1] = MAX(oy[1], ey[1]); - } else { - if(ex[0] >= 0 && ex[1] >= 0 && ey[0] >= 0 && ey[1] >= 0) { - kv_pushp(ul_ov_t, *rr, &cp); - cp->qs = ex[0]; cp->qe = ex[1]; - cp->ts = ey[0]; cp->te = ey[1]; - cp->sec = 0; cp->el = 0; cp->rev = 0; - if((rr->n > rr_n0 + 1) && (cp->qs < rr->a[rr->n-2].qs)) is_srt = 0; - } - ex[0] = ox[0]; ex[1] = ox[1]; - ey[0] = oy[0]; ey[1] = oy[1]; - } - } - - if(ex[0] >= 0 && ex[1] >= 0 && ey[0] >= 0 && ey[1] >= 0) { - kv_pushp(ul_ov_t, *rr, &cp); - cp->qs = ex[0]; cp->qe = ex[1]; - cp->ts = ey[0]; cp->te = ey[1]; - cp->sec = 0; cp->el = 0; cp->rev = 0; - if((rr->n > rr_n0 + 1) && (cp->qs < rr->a[rr->n-2].qs)) is_srt = 0; - } - - if(rr->n <= rr_n0) return 0; - if(!is_srt) radix_sort_ul_ov_srt_qs1(rr->a + rr_n0, rr->a + rr->n); - - ra = rr->a + rr_n0; rn = rr->n - rr_n0; - for (k = ck = 0; k < rn; k++) { - if(ck > 0 && ra[k].qs < ra[ck - 1].qe) { - if(ra[k].qe > ra[ck - 1].qe) ra[ck - 1].qe = ra[k].qe; - if(ra[k].ts < ra[ck - 1].ts) ra[ck - 1].ts = ra[k].ts; - if(ra[k].te > ra[ck - 1].te) ra[ck - 1].te = ra[k].te; - } else { - if((ck > 0) && (ra[ck - 1].qe - ra[ck - 1].qs < min_err) && (ra[ck - 1].te - ra[ck - 1].ts < min_err)) { - ck--; - } - ra[ck++] = ra[k]; - } - } - if((ck > 0) && (ra[ck - 1].qe - ra[ck - 1].qs < min_err) && (ra[ck - 1].te - ra[ck - 1].ts < min_err)) ck--; - if(ck == 0) { - rr->n = rr_n0; - return 0; - } - rn = ck; ck = 0; xk = z->w_list.a[wk].x_start; yk = z->w_list.a[wk].y_start; - for (k = ck = rn1 = 0; k < rn; k++) { - cp = &(ra[k]); - cp->qn = iter_sub_cigar_sv(zid, cp, &ez, &ck, &xk, &yk, NULL, -1, NULL, -1, -1, -1, -1, -1, &(ey[0]), &(ey[1]), -1); - if(cp->qn < min_err) continue; - assert(ey[0] >= 0 && ey[1] >= 0 && ey[1] >= ey[0]); - ey[0] -= hpc_len; if(ey[0] < 0) ey[0] = 0; - ey[1] += hpc_len; if(ey[1] > tl) ey[1] = tl; - - UC_Read_resize(*tu, (ey[1] - ey[0])); ///ystr = tu->seq; - recover_UC_Read_sub_region(tu->seq, ey[0], (ey[1] - ey[0]), z->y_pos_strand, rref, z->y_id); - iter_sub_cigar_sv(zid, cp, &ez, &ck, &xk, &yk, qstr, ql, tu->seq, tl, ey[0], ey[1], hpc_len, hpc_rr, &(ey[0]), &(ey[1]), (min_err<<1)); - - ra[rn1++] = *cp; - // fprintf(stderr, "-[M::%s] rid::%u\t%.*s\tq0::[%u,%u)\tql::%ld\tq1::[%u,%u)\t\terr::%u\tel::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), cp->qs, cp->qe, ql, cp->ts, cp->te, cp->qn, cp->el); - } - - // fprintf(stderr, "\n"); - - rr->n = rr_n0 + rn1; - if(rn1 > 0) return 1; - else return 0; -} - -uint64_t is_mask_ov(mask_ul_ov_t *mk, uint64_t *bes_id, uint64_t bes_n, uint64_t sec_id) -{ - uint64_t s = mk->idx.a[sec_id]>>32, e = (uint32_t)(mk->idx.a[sec_id]), bk, si; - bk = 0; si = s; - while (bk < bes_n && si < e) { - if (bes_id[bk] < mk->srt.a[si].tn) { - bk++; - } else if(mk->srt.a[si].tn < bes_id[bk]) { - si++; - } else {///bes_id[bk] == mk->srt.a[si].tn - if(!(mk->srt.a[si].qs)) return 1; - return 0; - } - } - return 0; -} - -///[s, e) -uint64_t gen_region_phase_robust_rr(overlap_region* ol, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, uint64_t dp, ul_ov_t *c_idx, asg64_v *buf, mask_ul_ov_t *mk) -{ - if(!id_n) return id_n; - uint64_t k, m, mn, q[2], buf_n, rm_n, oid; int64_t err, msc, msc_k, msc_n; - overlap_region *z; ul_ov_t *p; buf->n = 0; kv_resize(uint64_t, *buf, dp); - for (k = buf_n = rm_n = 0; k < id_n; k++) { - p = &(c_idx[id_a[k]]); - q[0] = ol[ovlp_id(*p)].w_list.a[ovlp_min_wid(*p)].x_start+ovlp_bd(*p); - q[1] = ol[ovlp_id(*p)].w_list.a[ovlp_max_wid(*p)].x_end+1-ovlp_bd(*p); - if(q[0]<=s && q[1]>=e) { - kv_push(uint64_t, *buf, id_a[k]); - } - if(q[1] < e) rm_n++; - } - buf_n = buf->n; - // fprintf(stderr, "[M::%s] buf_n::%lu, dp::%lu\n", __func__, buf_n, dp); - assert(buf_n == dp);//not right - - if(buf_n > 0) { - for (k = 0, msc = INT32_MAX, msc_k = -1, msc_n = 0; k < buf_n; k++) { - p = &(c_idx[(uint32_t)buf->a[k]]); z = &(ol[ovlp_id(*p)]); - err = extract_sub_cigar_err_rr(z, s, e, p); - assert(err >= 0); - if(err < msc) { - msc = err; msc_k = k; msc_n = 1; - } else if(err == msc) { - msc_n++; - } - buf->a[k] |= (((uint64_t)err)<<32); - } - - if(msc_n == 1) { - p = &(c_idx[(uint32_t)buf->a[msc_k]]); - z = &(ol[ovlp_id(*p)]); mn = 1; - if(msc_k != 0) { - m = buf->a[msc_k]; - buf->a[msc_k] = buf->a[0]; - buf->a[0] = m; - } - } else { - for (k = mn = 0; k < buf_n && (int64_t)mn < msc_n; k++) { - p = &(c_idx[(uint32_t)buf->a[k]]); - z = &(ol[ovlp_id(*p)]); - if((buf->a[k]>>32) == (uint64_t)msc) { - if(mn != k) { - m = buf->a[k]; - buf->a[k] = buf->a[mn]; - buf->a[mn] = m; - } - mn++; - } - } - } - // fprintf(stderr, "[M::%s] buf_n::%ld, msc_n::%ld, mn::%lu\n", __func__, buf_n, msc_n, mn); - for (k = 0; k < buf_n; k++) { - oid = ovlp_id((c_idx[(uint32_t)buf->a[k]])); - buf->a[k] >>= 32; buf->a[k] <<= 32; buf->a[k] |= oid; - // ol[oid].overlapLen = k;//no need to set - // if(s == 158482) fprintf(stderr, "k->%ld::oid->%ld[M::%s::utg%.6dl] pos::[%lu, %lu)\n", k, oid, __func__, - // (int32_t)ol[oid].y_id+1, s, e); - } - - for (k = 0; k < mn; k++) {///best alignment - z = &(ol[id_get(buf->a[k])]); - // reassign_sec_err(ol, ovidx, buf, k); - // push_sec_aln(z, s, e, 0); - push_sec_aln_robust(z, s, e, 0); - buf->a[k] = id_get(buf->a[k]);///all equally best overlap pieces - } - if(!mk) { - for (k = mn; k < buf_n; k++) { - err = err_get(buf->a[k])-msc; - z = &(ol[id_get(buf->a[k])]); - push_sec_aln_robust(z, s, e, err); - } - } else { - if(mn > 1) radix_sort_bc64(buf->a, buf->a + mn); - for (k = mn; k < buf_n; k++) { - err = err_get(buf->a[k])-msc; - if(is_mask_ov(mk, buf->a, mn, id_get(buf->a[k]))) err = 0; - z = &(ol[id_get(buf->a[k])]); - push_sec_aln_robust(z, s, e, err); - } - } - } - - - if(rm_n) { - for (k = m = 0; k < id_n; k++) { - p = &(c_idx[id_a[k]]); - q[1] = ol[ovlp_id(*p)].w_list.a[ovlp_max_wid(*p)].x_end+1-ovlp_bd(*p); - if(q[1] < e) continue; - id_a[m++] = id_a[k]; - } - id_n = m; - } - return id_n; -} - -uint64_t hc_phase_robust_rr(overlap_region* ol, All_reads *rref, haplotype_evdience_alloc* hp, char* qstr, uint64_t ql, UC_Read* tu, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, ul_ov_t *c_idx, int64_t set_f, uint8_t occ_thres, uint64_t hpc_len/**, uint8_t is_dbg**/) -{ - uint64_t k, q[2], rr = 0, os, oe; ul_ov_t *p; overlap_region *z; - for (k = 0; k < id_n; k++) { - p = &(c_idx[id_a[k]]); z = &(ol[ovlp_id(*p)]); - q[0] = z->w_list.a[ovlp_cur_wid(*p)].x_start+ovlp_bd(*p); - q[1] = z->w_list.a[ovlp_cur_wid(*p)].x_end+1-ovlp_bd(*p); - if(q[1] <= e) rr = 1; - os = MAX(q[0], s); oe = MIN(q[1], e); - if(oe > os) { - // if(is_dbg) fprintf(stderr, "[M::%s]\ttn::%u\t%c\to::[%lu,\t%lu)\n", __func__, z->y_id, "+-"[z->y_pos_strand], os, oe); - extract_sub_cigar_hc(z, rref, hp, qstr, ql, tu, os, oe, p, set_f, hp->flag + os - s, occ_thres, hpc_len/**, is_dbg**/); - } - } - return rr; -} - - -int64_t infer_rovlp(ul_ov_t *li, ul_ov_t *lj, uc_block_t *bi, uc_block_t *bj, All_reads *ridx, ma_ug_t *ug) -{ - int64_t in, is, ie, irev, iqs, iqe, jn, js, je, jrev, jqs, jqe, ir, jr, ts, te, max_s, min_e, s_shift, e_shift; - - if(li) { - in = ug?ug->u.a[li->tn].len:Get_READ_LENGTH(R_INF, li->tn); - is = li->ts; ie = li->te; irev = li->rev; iqs = li->qs; iqe = li->qe; - } else if(bi) { - in = ug?ug->u.a[bi->hid].len:Get_READ_LENGTH(R_INF, bi->hid); - is = bi->ts; ie = bi->te; irev = bi->rev; iqs = bi->qs; iqe = bi->qe; - } else { - return 0; - } - - if(lj) { - jn = ug?ug->u.a[lj->tn].len:Get_READ_LENGTH(R_INF, lj->tn); - js = lj->ts; je = lj->te; jrev = lj->rev; jqs = lj->qs; jqe = lj->qe; - } else if(bj) { - jn = ug?ug->u.a[bj->hid].len:Get_READ_LENGTH(R_INF, bj->hid); - js = bj->ts; je = bj->te; jrev = bj->rev; jqs = bj->qs; jqe = bj->qe; - } else { - return 0; - } - - max_s = MAX(iqs, jqs); min_e = MIN(iqe, jqe); - if(min_e <= max_s) return 0; - s_shift = get_offset_adjust(max_s - iqs, iqe-iqs, ie-is); - e_shift = get_offset_adjust(iqe - min_e, iqe-iqs, ie-is); - if(irev) { - ts = s_shift; s_shift = e_shift; e_shift = ts; - } - is += s_shift; ie-= e_shift; - - // if(li && lj && li->tn == 324 && lj->tn == 319 && li->qs == 63841) { - // fprintf(stderr, "+++in:%ld, is:%ld, ie:%ld, irev:%ld, jn:%ld, js:%ld, je:%ld, jrev:%ld\n", in, is, ie, irev, jn, js, je, jrev); - // } - - s_shift = get_offset_adjust(max_s - jqs, jqe-jqs, je-js); - e_shift = get_offset_adjust(jqe - min_e, jqe-jqs, je-js); - if(jrev) { - ts = s_shift; s_shift = e_shift; e_shift = ts; - } - js += s_shift; je-= e_shift; - - if(irev) { - ts = in - ie; te = in - is; - is = ts; ie = te; - } - - if(jrev) { - ts = jn - je; te = jn - js; - js = ts; je = te; - } - - // if(li && lj && li->tn == 324 && lj->tn == 319 && li->qs == 63841) { - // fprintf(stderr, "---in:%ld, is:%ld, ie:%ld, irev:%ld, jn:%ld, js:%ld, je:%ld, jrev:%ld\n", in, is, ie, irev, jn, js, je, jrev); - // } - - if(is <= js) { - js -= is; is = 0; - } else { - is -= js; js = 0; - } - - ir = in - ie; jr = jn - je; - - if(ir <= jr){ - ie = in; je += ir; - } - else { - je = jn; ie += jr; - } - - ir = ie - is; jr = je - js; - return MAX(ir, jr); -} - -void convert_ul_ov_t(ul_ov_t *des, overlap_region *src, ma_ug_t *ug) -{ - des->qn = (uint32_t)-1; des->qs = src->x_pos_s; des->qe = src->x_pos_e+1; - des->tn = src->y_id; des->el = 1; des->rev = src->y_pos_strand; - des->sec = src->non_homopolymer_errors; - if(des->rev) { - des->ts = ug->u.a[des->tn].len - (src->y_pos_e+1); - des->te = ug->u.a[des->tn].len - src->y_pos_s; - } else { - des->ts = src->y_pos_s; - des->te = src->y_pos_e+1; - } -} - -uint64_t check_connect_ug(const ul_idx_t *uref, uint32_t v, uint32_t w, int64_t bw, double diff_ec_ul, int64_t dq) -{ - const asg_t *g = uref?uref->ug->g:NULL; int64_t dt = -1; - uint32_t nv = asg_arc_n(g, v), i; asg_arc_t *av = asg_arc_a(g, v); - for (i = 0; i < nv; i++) { - if(av[i].del || av[i].v != w) continue; - dt = av[i].ol; - break; - } - if(dt < 0) return 0; - int64_t diff = (dq>dt? dq-dt:dt-dq), mm = MAX(dq, dt); - mm *= diff_ec_ul; if(mm < bw) mm = bw; - if(diff <= mm) return 1; - return 0; -} - -uint64_t check_connect_rg(const ul_idx_t *uref, const ug_opt_t *uopt, uint32_t uv, uint32_t uw, int64_t bw, double diff_ec_ul, int64_t dq) -{ - int64_t dt = -1; - if(uref->ug->u.a[uv>>1].circ || uref->ug->u.a[uw>>1].circ) return 0; - uint32_t rv = (uref->ug->u.a[uv>>1].a[(uv&1)?(0):(uref->ug->u.a[uv>>1].n-1)]>>32)^(uv&1); - uint32_t rw = (uref->ug->u.a[uw>>1].a[(uw&1)?(uref->ug->u.a[uw>>1].n-1):(0)]>>32)^(uw&1); - ma_hit_t_alloc* src = uopt->sources; - int64_t min_ovlp = uopt->min_ovlp; - int64_t max_hang = uopt->max_hang; - uint64_t z, qn, tn, x = rv>>1; int32_t r = 1; asg_arc_t e; - for (z = 0; z < src[x].length; z++) { - qn = Get_qn(src[x].buffer[z]); tn = Get_tn(src[x].buffer[z]); - if(tn != (rw>>1)) continue; - r = ma_hit2arc(&(src[x].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); - if(r < 0) continue; - if((e.ul>>32) != rv || e.v != rw) continue; - dt = e.ol; - break; - } - if(dt < 0) return 0; - int64_t diff = (dq>dt? dq-dt:dt-dq), mm = MAX(dq, dt); - mm *= diff_ec_ul; if(mm < bw) mm = bw; - if(diff <= mm) return 1; - return 0; -} - -uint32_t govlp_check(const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, ul_ov_t *li, ul_ov_t *lj) -{ - int64_t qo = infer_rovlp(li, lj, NULL, NULL, /**ridx**/NULL, uref->ug); ///overlap length in query (UL read) - - // fprintf(stderr, "+++[M::%s::utg%.6dl->utg%.6dl] qo::%ld\n", __func__, (int32_t)li->tn+1, (int32_t)lj->tn+1, qo); - if(check_connect_ug(uref, ((li->tn<<1)|li->rev)^1, ((lj->tn<<1)|lj->rev)^1, bw, diff_ec_ul, qo)) return 1; - // fprintf(stderr, "[M::%s::] check_connect_ug fail\n", __func__); - if(check_connect_rg(uref, uopt, ((li->tn<<1)|li->rev)^1, ((lj->tn<<1)|lj->rev)^1, bw, diff_ec_ul, qo)) return 1; - // fprintf(stderr, "[M::%s::] check_connect_rg fail\n", __func__); - return 0; -} - -void gen_gov_idx(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, asg64_v* idx) -{ - int64_t on = ol->length, k, i; uint64_t os, oe, ovlp; ul_ov_t p, q, *li, *lj; - kv_resize(uint64_t, *idx, (uint64_t)on); memset(idx->a, 0, sizeof(*(idx->a))*on); - for (k = 0, idx->n = on; k < on; k++) { - convert_ul_ov_t(&p, &(ol->list[k]), uref->ug); p.qn = k; - // idx->a[k] = idx->n; idx->a[k] <<= 32; - for (i = on - 1; i >= 0 && i > k && ol->list[i].x_pos_e >= ol->list[k].x_pos_s; i--) { - // if(k >= i) continue; - convert_ul_ov_t(&q, &(ol->list[i]), uref->ug); q.qn = i; - - if(p.qe > q.qe) li = &p, lj = &q; - else if(p.qe == q.qe && p.qs >= q.qs) li = &p, lj = &q; - else lj = &p, li = &q; - os = MAX(li->qs, lj->qs), oe = MIN(li->qe, lj->qe); - ovlp = ((oe > os)? (oe - os):0); - if(!ovlp) continue;//no overlap - - if(lj->qs <= li->qs+G_CHAIN_INDEL) { - if(govlp_check(uref, uopt, bw, diff_ec_ul, li, lj)) { - idx->a[k]++; idx->a[i]++; - kv_push(uint64_t, *idx, (((uint64_t)k)<<32)|((uint64_t)i)); - kv_push(uint64_t, *idx, (((uint64_t)i)<<32)|((uint64_t)k)); - } - } else if((lj->qe+G_CHAIN_INDEL>=li->qe) && (lj->qs+G_CHAIN_INDEL>=li->qs)) { - if(govlp_check(uref, uopt, bw, diff_ec_ul, lj, li)) { - idx->a[k]++; idx->a[i]++; - kv_push(uint64_t, *idx, (((uint64_t)k)<<32)|((uint64_t)i)); - kv_push(uint64_t, *idx, (((uint64_t)i)<<32)|((uint64_t)k)); - } - } - } - } - radix_sort_bc64(idx->a + on, idx->a + idx->n); - for (k = 0, os = oe = on; k < on; k++) { - oe = os + idx->a[k]; - idx->a[k] = (os<<32)|oe; - os = oe; - } - - // for (k = 0; k < on; k++) { - // int64_t s, e; - // s = idx->a[k]>>32; e = (uint32_t)idx->a[k]; - // for (i = s; i < e; i++) { - // assert((idx->a[i]>>32) == (uint32_t)k); - // fprintf(stderr, "k::%ld[M::%s::utg%.6dl] utg%.6dl\n", k, __func__, - // (int32_t)ol->list[k].y_id+1, (int32_t)ol->list[(uint32_t)idx->a[i]].y_id+1); - // } - // } -} - -void prt_overlap_region_stat(overlap_region *z, int64_t sid) -{ - uint64_t k = 0, aln = 0, ualn = 0, err = 0; - for (k = 0; k < z->w_list.n; k++) { - if(is_ualn_win(z->w_list.a[k])) { - ualn += z->w_list.a[k].x_end+1-z->w_list.a[k].x_start; - } else { - aln += z->w_list.a[k].x_end+1-z->w_list.a[k].x_start; - err += z->w_list.a[k].error; - } - } - fprintf(stderr, "[M::%s::utg%.6dl::%c] sid::%ld, q::[%d, %d), t::[%d, %d), aln::%lu, ualn::%lu, err::%lu\n", - __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], sid, z->x_pos_s, z->x_pos_e+1, - z->y_pos_s, z->y_pos_e+1, aln, ualn, err); - -} - - -void prt_overlap_region_phase_stat(overlap_region *z, int64_t sid) -{ - uint64_t k = 0; - fprintf(stderr, "[M::%s::utg%.6dl::%c] sid::%ld, q::[%d, %d), t::[%d, %d)\n", __func__, - (int32_t)z->y_id+1, "+-"[z->y_pos_strand], sid, z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1); - for (k = 0; k < z->w_list.n; k++) { - fprintf(stderr, "[k::%lu] sid::%ld, q::[%d, %d), sec::%u\n", k, sid, - z->w_list.a[k].x_start, z->w_list.a[k].x_end, z->w_list.a[k].clen); - } -} - -void region_phase(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, asg64_v* buf1, int64_t ulid) -{ - int64_t on = ol->length, k, i, zwn, q[2], t[2], w[2]; - uint64_t m; overlap_region *z; ul_ov_t *cp; - kv_resize(uint64_t, *idx, (ol->length<<1)); - kv_resize(ul_ov_t, *c_idx, ol->length); - for (k = idx->n = c_idx->n = 0; k < on; k++) { - z = &(ol->list[k]); zwn = z->w_list.n; - // prt_overlap_region_stat(z, ulid); - // if(/**ulid == 35437 &&**/ z->y_id == 15199 || z->y_id == 31315) { - // fprintf(stderr, "+0+[M::%s::utg%.6dl::%c] ulid::%ld, all::%u, non-best::%ld, best::%u\n", __func__, - // (int32_t)z->y_id+1, "+-"[z->y_pos_strand], ulid, z->overlapLen, zwn, z->align_length); - // prt_overlap_region_stat(&(ol->list[k]), ulid); - // // prt_overlap_region_phase_stat(&(ol->list[k]), ulid); - // } - // z->align_length = z->overlapLen = z->x_pos_e+1-z->x_pos_s; - z->align_length = 0; z->overlapLen = (uint32_t)-1; - z->non_homopolymer_errors = 0; - if(!zwn) continue; - q[0] = q[1] = t[0] = t[1] = w[0] = w[1] = INT32_MIN; - for (i = 0; i < zwn; i++) { - if((z->w_list.a[i].x_start==(q[1]+1)) && ((z->w_list.a[i].y_start==(t[1]+1)))) { - q[1] = z->w_list.a[i].x_end; - t[1] = z->w_list.a[i].y_end; - w[1] = i; - } else { - if(q[0] != INT32_MIN) { - m = ((uint64_t)q[0])<<1; m <<= 32; - m += c_idx->n; kv_push(uint64_t, *idx, m); - m = (((uint64_t)q[1])<<1)+1; m <<= 32; - m += c_idx->n; kv_push(uint64_t, *idx, m); - - kv_pushp(ul_ov_t, *c_idx, &cp); - ovlp_id(*cp) = k; ///ovlp id - ovlp_min_wid(*cp) = w[0]; ///beg id of windows - ovlp_max_wid(*cp) = w[1]; ///end id of windows - ovlp_cur_wid(*cp) = w[0]; ///cur id of windows - ovlp_cur_xoff(*cp) = z->w_list.a[w[0]].x_start; ///cur xpos - ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window - ovlp_bd(*cp) = 0; - } - - q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; - t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end; - w[0] = i; w[1] = i; - } - } - if(q[0] != INT32_MIN) { - m = ((uint64_t)q[0])<<1; m <<= 32; - m += c_idx->n; kv_push(uint64_t, *idx, m); - m = (((uint64_t)q[1])<<1)+1; m <<= 32; - m += c_idx->n; kv_push(uint64_t, *idx, m); - - kv_pushp(ul_ov_t, *c_idx, &cp); - ovlp_id(*cp) = k; ///ovlp id - ovlp_min_wid(*cp) = w[0]; ///beg id of windows - ovlp_max_wid(*cp) = w[1]; ///end id of windows - ovlp_cur_wid(*cp) = w[0]; ///cur id of windows - ovlp_cur_xoff(*cp) = z->w_list.a[w[0]].x_start; ///cur xpos - ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window - ovlp_bd(*cp) = 0; - } - // if(ulid == 35437 && z->y_id == 109111) { - // fprintf(stderr, "+1+[M::%s::utg%.6dl::%c] ulid::%ld, all::%u, non-best::%ld, best::%u\n", __func__, - // (int32_t)z->y_id+1, "+-"[z->y_pos_strand], ulid, z->overlapLen, zwn, z->align_length); - // prt_overlap_region_stat(&(ol->list[k])); - // prt_overlap_region_phase_stat(&(ol->list[k])); - // } - } - radix_sort_bc64(idx->a, idx->a+idx->n); - //this is used with gen_region_phase, now give up - //gen_gov_idx(ol, uref, uopt, G_CHAIN_BW, N_GCHAIN_RATE, buf1); - // for (m = 0; m < c_idx->n; m++) { - // fprintf(stderr, "+++[M::%s::utg%.6dl] q[%d, %d), t[%d, %d), wn::%d\n", __func__, - // (int32_t)ol->list[ovlp_id(c_idx->a[m])].y_id+1, - // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_min_wid(c_idx->a[m])].x_start, - // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_max_wid(c_idx->a[m])].x_end+1, - // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_min_wid(c_idx->a[m])].y_start, - // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_max_wid(c_idx->a[m])].y_end+1, - // ovlp_max_wid(c_idx->a[m])+1-ovlp_min_wid(c_idx->a[m])); - // } - - - int64_t srt_n = idx->n, dp, old_dp, beg, end; - for (i = k = 0, dp = old_dp = 0, beg = 0, end = -1; i < srt_n; ++i) {///[beg, end) but coordinates in idx is [, ] - ///if idx->a.a[] is qe - old_dp = dp; - if ((idx->a[i]>>32)&1) { - --dp; end = (idx->a[i]>>33)+1; - }else { - //meet a new overlap; the overlaps are pushed by the x_pos_s - ++dp; end = (idx->a[i]>>33); - kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); - } - // fprintf(stderr, "\n[M::%s::] beg::%ld, end::%ld, old_dp::%ld\n", __func__, beg, end, old_dp); - if((end > beg) && (old_dp >= 2)) { - // fprintf(stderr, "\n[M::%s::] beg::%ld, end::%ld, old_dp::%ld\n", __func__, beg, end, old_dp); - // kv_resize(uint64_t, *buf, ((uint32_t)old_dp)<<1); - // idx->n = srt_n + gen_region_phase(ol->list, idx->a+srt_n, idx->n-srt_n, beg, end, old_dp, c_idx->a, buf, buf1); - idx->n = srt_n + gen_region_phase_robust(ol->list, idx->a+srt_n, idx->n-srt_n, beg, end, old_dp, c_idx->a, buf); - } - beg = end; - } - ///hap->length - - for (k = 0; k < on; k++) { - z = &(ol->list[k]); - // if(ulid == 35437 && z->y_id == 109111) { - // fprintf(stderr, "+2+[M::%s::utg%.6dl::%c] ulid::%ld, all::%u, non-best::%ld, best::%u\n", __func__, - // (int32_t)z->y_id+1, "+-"[z->y_pos_strand], ulid, z->overlapLen, zwn, z->align_length); - // prt_overlap_region_stat(&(ol->list[k])); - // prt_overlap_region_phase_stat(&(ol->list[k])); - // } - - - - z->overlapLen = z->x_pos_e+1-z->x_pos_s; - z->non_homopolymer_errors = 0; zwn = 0; - for (i = m = 0; i < z->align_length; i++) { - z->w_list.a[m] = z->w_list.a[z->w_list.n+i]; - if(z->w_list.a[m].clen > 0) { - z->non_homopolymer_errors += z->w_list.a[m].clen; - zwn += z->w_list.a[m].x_end-z->w_list.a[m].x_start; - } - m++; - } - z->w_list.n = m; - // if(ulid == 35437 && z->y_id == 109111/**zwn > z->overlapLen**/) { - // fprintf(stderr, "+3+[M::%s::utg%.6dl::%c] ulid::%ld, all::%u, non-best::%ld, best::%u\n", __func__, - // (int32_t)z->y_id+1, "+-"[z->y_pos_strand], ulid, z->overlapLen, zwn, z->align_length); - // prt_overlap_region_stat(&(ol->list[k])); - // prt_overlap_region_phase_stat(&(ol->list[k])); - // } - assert(zwn <= z->overlapLen); - z->align_length = z->overlapLen - zwn; - // /**if(ulid == 35437 && z->y_id == 15199 || z->y_id == 31315)**/ { - // prt_overlap_region_phase_stat(z, ulid); - // fprintf(stderr, "[M::%s::utg%.6dl::%c] all::%u, non-best::%ld, best::%u\n\n", __func__, - // (int32_t)z->y_id+1, "+-"[z->y_pos_strand], z->overlapLen, zwn, z->align_length); - // } - // prt_overlap_region_phase_stat(&(ol->list[k])); - // z = &(ol->list[k]); - // if(z->align_length == z->overlapLen) {///prefer alignments without any trans hit - // z->align_length = z->overlapLen = z->x_pos_e+1-z->x_pos_s; - // } - } -} - - -void rphase_rr(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, int64_t ulid, int64_t bd, mask_ul_ov_t *mk) -{ - int64_t on = ol->length, k, i, zwn, q[2], t[2], w[2]; - uint64_t m; overlap_region *z; ul_ov_t *cp; - kv_resize(uint64_t, *idx, (ol->length<<1)); - kv_resize(ul_ov_t, *c_idx, ol->length); - for (k = idx->n = c_idx->n = 0; k < on; k++) { - z = &(ol->list[k]); zwn = z->w_list.n; - z->align_length = 0; z->overlapLen = (uint32_t)-1; - z->non_homopolymer_errors = 0; - if(!zwn) continue; - q[0] = q[1] = t[0] = t[1] = w[0] = w[1] = INT32_MIN; - for (i = 0; i < zwn; i++) { - if((z->w_list.a[i].x_start==(q[1]+1)) && ((z->w_list.a[i].y_start==(t[1]+1)))) { - q[1] = z->w_list.a[i].x_end; - t[1] = z->w_list.a[i].y_end; - w[1] = i; - } else { - if(q[0] != INT32_MIN) { - q[0] += bd; q[1] -= bd; - if(q[1] >= q[0]) { - m = ((uint64_t)q[0])<<1; m <<= 32; - m += c_idx->n; kv_push(uint64_t, *idx, m); - m = (((uint64_t)q[1])<<1)+1; m <<= 32; - m += c_idx->n; kv_push(uint64_t, *idx, m); - - kv_pushp(ul_ov_t, *c_idx, &cp); - ovlp_id(*cp) = k; ///ovlp id - ovlp_min_wid(*cp) = w[0]; ///beg id of windows - ovlp_max_wid(*cp) = w[1]; ///end id of windows - ovlp_cur_wid(*cp) = w[0]; ///cur id of windows - ovlp_cur_xoff(*cp) = z->w_list.a[w[0]].x_start; ///cur xpos - ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window - ovlp_bd(*cp) = bd; - } - } - - q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; - t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end; - w[0] = i; w[1] = i; - } - } - if(q[0] != INT32_MIN) { - q[0] += bd; q[1] -= bd; - if(q[1] >= q[0]) { - m = ((uint64_t)q[0])<<1; m <<= 32; - m += c_idx->n; kv_push(uint64_t, *idx, m); - m = (((uint64_t)q[1])<<1)+1; m <<= 32; - m += c_idx->n; kv_push(uint64_t, *idx, m); - - kv_pushp(ul_ov_t, *c_idx, &cp); - ovlp_id(*cp) = k; ///ovlp id - ovlp_min_wid(*cp) = w[0]; ///beg id of windows - ovlp_max_wid(*cp) = w[1]; ///end id of windows - ovlp_cur_wid(*cp) = w[0]; ///cur id of windows - ovlp_cur_xoff(*cp) = z->w_list.a[w[0]].x_start; ///cur xpos - ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window - ovlp_bd(*cp) = bd; - } - } - } - radix_sort_bc64(idx->a, idx->a+idx->n); - - int64_t srt_n = idx->n, dp, old_dp, beg, end; - for (i = k = 0, dp = old_dp = 0, beg = 0, end = -1; i < srt_n; ++i) {///[beg, end) but coordinates in idx is [, ] - ///if idx->a.a[] is qe - old_dp = dp; - if ((idx->a[i]>>32)&1) { - --dp; end = (idx->a[i]>>33)+1; - }else { - //meet a new overlap; the overlaps are pushed by the x_pos_s - ++dp; end = (idx->a[i]>>33); - kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); - } - if((end > beg) && (old_dp >= 2)) { - idx->n = srt_n + gen_region_phase_robust_rr(ol->list, idx->a+srt_n, idx->n-srt_n, beg, end, old_dp, c_idx->a, buf, mk); - } - beg = end; - } -} - -void debug_inter(overlap_region_alloc* ol, kv_ul_ov_t *c_idx, uint64_t *idx, int64_t idx_n, uint64_t *res, int64_t res_n, int64_t s, int64_t e) -{ - ul_ov_t *cp; int64_t q[2], a_n = 0, i, k = 0, os, oe; - for (i = 0; i < idx_n; i++) { - cp = &(c_idx->a[(uint32_t)idx[i]]); - q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); - q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); - os = MAX(q[0], s); oe = MIN(q[1], e); - if(oe > os) { - a_n++; assert(((uint32_t)idx[i]) == res[k++]); - } - } - // if(a_n != res_n) { - // fprintf(stderr, "[M::%s] a_n::%ld\tres_n::%ld\ts::%ld\te::%ld\n", __func__, a_n, res_n, s, e); - // } - assert(a_n == res_n); -} - -void debug_snp_site(overlap_region* ol, All_reads *rref, UC_Read *qu, haplotype_evdience *a, int64_t a_n) -{ - int64_t k; char ystr; - for (k = 0; k < a_n; k++) { - recover_UC_Read_sub_region(&ystr, a[k].overlapSite, 1, ol[a[k].overlapID].y_pos_strand, rref, ol[a[k].overlapID].y_id); - // if(a[k].misBase == ystr) fprintf(stderr, "[M::%s] misBase::%c\tystr::%c\n", __func__, a[k].misBase, ystr); - assert(a[k].misBase == ystr); - if(a[k].type == 0) { - assert(qu->seq[a[k].site] == ystr); - } else { - assert(qu->seq[a[k].site] != ystr); - } - } - -} - -void rphase_hc_back(overlap_region_alloc* ol, All_reads *rref, haplotype_evdience_alloc* hp, UC_Read* qu, UC_Read* tu, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, int64_t bd, int64_t wl, int64_t ql, uint8_t occ_thres/**, uint8_t is_dbg**/, uint64_t rid, uint64_t hpc_len, uint64_t std_bs) -{ - int64_t on = ol->length, k, i, zwn, q[2]; - uint64_t m, l0, wi, wl0, si, ei, fi; overlap_region *z; ul_ov_t *cp; - kv_resize(uint64_t, *idx, (ol->length)); - kv_resize(ul_ov_t, *c_idx, ol->length); - - for (k = idx->n = c_idx->n = 0; k < on; k++) { - z = &(ol->list[k]); zwn = z->w_list.n; - // z->align_length = 0; z->overlapLen = (uint32_t)-1; z->non_homopolymer_errors = 0; - if(!zwn) continue; - for (i = 0; i < zwn; i++) { - if(is_ualn_win(z->w_list.a[i])) continue; - q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; - q[0] += bd; q[1] -= bd; - if(q[1] >= q[0]) { - m = ((uint64_t)q[0]); m <<= 32; - m += c_idx->n; kv_push(uint64_t, *idx, m); - - kv_pushp(ul_ov_t, *c_idx, &cp); - ovlp_id(*cp) = k; ///ovlp id - // ovlp_min_wid(*cp) = i; ///beg id of windows - // ovlp_max_wid(*cp) = i; ///end id of windows - ovlp_cur_wid(*cp) = i; ///cur id of windows - ovlp_cur_xoff(*cp) = z->w_list.a[i].x_start; ///cur xpos - ovlp_cur_yoff(*cp) = z->w_list.a[i].y_start; ///cur xpos - ovlp_cur_ylen(*cp) = 0; - ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window - ovlp_bd(*cp) = bd; - } - // if(rid == 19350) { - // fprintf(stderr, "#########[M::%s] tid::%u\t%.*s\twid::%ld\tq::[%u, %u)\terr::%d\toerr::%u#########\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), - // i, z->w_list.a[i].x_start, z->w_list.a[i].x_end+1, z->w_list.a[i].error, z->non_homopolymer_errors); - // } - } - } - - int64_t srt_n = idx->n, s, e, t, os, oe, rm_n, rr; i = 0; - radix_sort_bc64(idx->a, idx->a+idx->n); - for (k = 1, i = 0; k < srt_n; k++) { - if (k == srt_n || (idx->a[k]>>32) != (idx->a[i]>>32)) { - if(k - i > 1) { - for (t = i; t < k; t++) { - cp = &(c_idx->a[(uint32_t)idx->a[t]]); - // s = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); - // assert(s == (int64_t)(idx->a[i]>>32)); - m = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); - m <<= 32; m += ((uint32_t)idx->a[t]); idx->a[t] = m; - // fprintf(stderr, "[M::%s] s::%ld\tsi::%lu\n", __func__, s, (idx->a[i]>>32)); - } - radix_sort_bc64(idx->a + i, idx->a + k); - } - i = k; - } - } - - ResizeInitHaplotypeEvdience(hp); - // if(is_dbg) fprintf(stderr, "[M::%s] ******\n", __func__); - // fprintf(stderr, "[M::%s] ig_hpc::%lu\n", __func__, ig_hpc); - i = 0; s = 0; e = wl; e = ((e<=ql)?e:ql); rr = 0; - for (; s < ql; ) { - // if(is_dbg) fprintf(stderr, "-0-[M::%s]\ts::%ld\te::%ld\n", __func__, s, e); - if(rr) { - // rr = 0; - for (m = rm_n = srt_n; m < idx->n; m++) { - cp = &(c_idx->a[idx->a[m]]); - q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); - q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); - os = MAX(q[0], s); oe = MIN(q[1], e); - if(oe > os) { - idx->a[rm_n++] = idx->a[m]; - // if(q[1] <= e) rr = 1; - } - } - idx->n = rm_n; - } - - for (; i < srt_n; ++i) { - cp = &(c_idx->a[(uint32_t)idx->a[i]]); - q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); - q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); - if(q[0] >= e) break; - os = MAX(q[0], s); oe = MIN(q[1], e); - if(oe > os) { - kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); - // if(q[1] <= e) rr = 1; - } - } - - // fprintf(stderr, "[M::%s] s::%ld, e::%ld, srt_n::%ld, idx->n::%ld\n", __func__, s, e, srt_n, (int64_t)idx->n); - // debug_inter(ol, c_idx, idx->a, srt_n, idx->a + srt_n, idx->n - srt_n, s, e); - l0 = hp->length; - // if(is_dbg) fprintf(stderr, "-1-[M::%s]\ts::%ld\te::%ld\n", __func__, s, e); - rr = hc_phase_robust_rr(ol->list, rref, hp, qu->seq, qu->length, tu, idx->a + srt_n, idx->n - srt_n, s, e, c_idx->a, 1, occ_thres, hpc_len/**, is_dbg**/); - /** - for (wi = fi = ei = 0, si = ((uint64_t)-1), wl0 = e - s; wi < wl0; wi++) { - if(hp->flag[wi] > 0) { - if((hp->flag[wi] > occ_thres) && ((!hpc_len) || (!hpc_mask_ff(qu->seq, qu->length, wi + s, hpc_len, HPC_RR, hp->flag, e - s, s, HPC_CC)))) { - fi = 1; hp->nn_snp++; - } - ei = wi + 1; if(si == ((uint64_t)-1)) si = wi; - } - } - **/ - for (wi = fi = ei = 0, si = ((uint64_t)-1), wl0 = e - s; wi < wl0; wi++) { - if(hp->flag[wi] > 0) { - if(hp->flag[wi] > occ_thres) { - fi = 1; hp->nn_snp++; hp->flag[wi] = 1; - if((hpc_len) && (hpc_mask_ff(qu->seq, qu->length, wi + s, hpc_len, HPC_RR, NULL, 0, 0, HPC_CC))) hp->flag[wi] = 3; - ei = wi + 1; if(si == ((uint64_t)-1)) si = wi; - } else { - hp->flag[wi] = 0; - } - } - } - - if(fi) { - // if(is_dbg) fprintf(stderr, "-2-[M::%s]\ts::%ld\te::%ld\n", __func__, s, e); - rr = hc_phase_robust_rr(ol->list, rref, hp, qu->seq, qu->length, tu, idx->a + srt_n, idx->n - srt_n, s, e, c_idx->a, 0, occ_thres, hpc_len/**, is_dbg**/); - if(hp->length > l0) radix_sort_haplotype_evdience_srt(hp->list + l0, hp->list + hp->length); - } - - if(ei > si) memset(hp->flag + si, 0, (ei-si)*sizeof((*(hp->flag)))); - // if(is_dbg) fprintf(stderr, "-3-[M::%s]\ts::%ld\te::%ld\n", __func__, s, e); - - s += wl; e += wl; e = ((e<=ql)?e:ql); - } - - // debug_snp_site(ol->list, rref, qu, hp->list, hp->length); - - - SetSnpMatrix(hp, &(hp->nn_snp), &(ol->length), 0, NULL); - srt_n = hp->length; z = ((std_bs)?(ol->list):(NULL)); - for (k = 1, i = t = 0; k <= srt_n; ++k) { - if (k == srt_n || hp->list[k].site != hp->list[i].site) { - t += push_info(hp, hp->list+i, k-i, hp->list+t, z, NULL, sc_wn); - i = k; - } - } - hp->length = t; - - // generate_haplotypes_naive_advance(hap, overlap_list, NULL); - generate_haplotypes_naive_HiFi(hp, ol, 0.04, qu, ((std_bs)?(0):(1)), ((std_bs)?(0.05):(0)), ((std_bs)?(2):((uint64_t)-1))); - // generate_haplotypes_DP(hap, overlap_list, R_INF, g_read->length, force_repeat); - // generate_haplotypes_naive(hap, overlap_list, R_INF, g_read->length, force_repeat); - - // lable_large_indels(overlap_list, g_read->length, dumy, asm_opt.max_ov_diff_ec); - - - // for (i = k = 0, dp = old_dp = 0, beg = 0, end = -1; i < srt_n; ++i) {///[beg, end) but coordinates in idx is [, ] - // ///if idx->a.a[] is qe - // old_dp = dp; - // if ((idx->a[i]>>32)&1) { - // --dp; end = (idx->a[i]>>33)+1; - // }else { - // //meet a new overlap; the overlaps are pushed by the x_pos_s - // ++dp; end = (idx->a[i]>>33); - // kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); - // } - // if((end > beg) && (old_dp >= 2)) { - // idx->n = srt_n + gen_region_phase_robust_rr(ol->list, idx->a+srt_n, idx->n-srt_n, beg, end, old_dp, c_idx->a, buf, mk); - // } - // beg = end; - // } -} - - - -double cal_lindel_dd(ul_ov_t *a, ul_ov_t *b, double ol_r, uint64_t ol_w, double err_dif, uint64_t c_sz) -{ - if(a->tn == b->tn) return -1; - uint64_t os, oe, ol; int64_t ea, eb, ed; - os = MAX(a->qs, b->qs); oe = MIN(a->qe, b->qe); - if(oe <= os + ol_w) return -1; - ol = oe - os; - // if((ol < ((a->qe - a->qs)*ol_r)) || (ol < ((b->qe - b->qs)*ol_r))) return -1; - if((ol < ((a->qe - a->qs)*ol_r)) && (ol < ((b->qe - b->qs)*ol_r))) return -1; - - ea = a->qn; eb = b->qn; - ed = ((ea >= eb)?(ea - eb):(eb - ea)); - if((ed > (ea * err_dif)) || (ed > (eb * err_dif))) return -1; - - double sc; - sc = ((double)(ea - ed + eb - ed))/((double)(ea + eb)); - sc += ((double)(ol + ol)) / ((double)(a->qe - a->qs + b->qe - b->qs)); - return sc; -} - -inline uint64_t set_cgid(ul_ov_t *z, uint64_t *ia, uint64_t *iak, uint64_t ian, uint64_t *ca, uint64_t ci, overlap_region *oa, int64_t *gni) -{ - assert(ca[z->tn] <= 1); - if(z->ts != ((uint32_t)-1)) return 0; - if(ca[z->tn] != 0) { - // fprintf(stderr, "+[M::%s] sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\tca[z->tn]::%lu\n", __func__, z->sec, oa[z->tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa[z->tn].y_id), Get_NAME(R_INF, oa[z->tn].y_id), z->qs, z->qe, z->qn, ca[z->tn]); - return 0; - } - - z->ts = ci; ca[z->tn]++; - ia[(*iak)++] = z->tn; - assert((*iak) <= ian); - (*gni)++; - // fprintf(stderr, "-[M::%s] sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\tca[z->tn]::%lu\n", __func__, z->sec, oa[z->tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa[z->tn].y_id), Get_NAME(R_INF, oa[z->tn].y_id), z->qs, z->qe, z->qn, ca[z->tn]); - - return 1; -} - -///need to print some examples for double check -uint64_t is_get_group(ul_ov_t *a/**, uint64_t an, uint64_t rid**/, uint64_t *ga, uint64_t *ia, uint64_t gi, uint64_t tn) -{ - // fprintf(stderr, "+[M::%s] gi::%lu\n", __func__, gi); - uint64_t k = ga[gi]>>32; - // while ((k != ((uint64_t)-1)) && (a[k].tn != tn)) { - // fprintf(stderr, "+[M::%s] k::%lu\n", __func__, k); - // k = ia[k]; - // fprintf(stderr, "-[M::%s] k::%lu\n", __func__, k); - // } - for (k = ga[gi]>>32; (k != ((uint64_t)-1)) && (a[k].tn != tn); k = ia[k]); - // if((k != ((uint32_t)-1)) && (k >= an)) { - // fprintf(stderr, "-[M::%s] rid::%lu, an::%lu, k::%lu\n", __func__, rid, an, k); - // } - if((k != ((uint64_t)-1)) && (a[k].tn == tn)) return 0; - return 1; -} - -int64_t rphase_lidel_cc(overlap_region_alloc* oa, ul_ov_t *a, int64_t an, double len_st, uint64_t len_w, double err_dif, uint64_t c_sz, uint64_t rid, asg64_v *buf, asg64_v *idx) -{ - int64_t k, z, mk, gni; uint64_t ol, ck, v, *ia, *ca, iak, ii, ian; double sw, msw = -1; - kv_resize(uint64_t, *idx, (oa->length<<1)); - ia = idx->a; ian = oa->length; iak = 0; - ca = idx->a + oa->length; memset(ca, 0, sizeof((*ca))*oa->length); - - for (k = 0; k < an; k++) { - ol = (a[k].qe - a[k].qs) * len_st; if(ol < len_w) ol = len_w; - if((a[k].qe - a[k].qs) < ol) continue; - for (z = k + 1; (z < an) && (a[z].qs < a[k].qe); z++) { - if(cal_lindel_dd(&(a[k]), &(a[z]), len_st, len_w, err_dif, c_sz) >= 0) { - a[k].sec++; a[z].sec++; - // fprintf(stderr, "(0)[M::%s] k(%ld)sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\n", __func__, k, a[k].sec, oa->list[a[k].tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa->list[a[k].tn].y_id), Get_NAME(R_INF, oa->list[a[k].tn].y_id), a[k].qs, a[k].qe, a[k].qn); - // fprintf(stderr, "(1)[M::%s] z(%ld)sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\n", __func__, z, a[z].sec, oa->list[a[z].tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa->list[a[z].tn].y_id), Get_NAME(R_INF, oa->list[a[z].tn].y_id), a[z].qs, a[z].qe, a[z].qn); - } - } - } - - for (k = z = 0; k < an; k++) { - if(a[k].sec == 0) { - // fprintf(stderr, "#[M::%s] z::%ld, sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\tel::%u\n", __func__, z, a[k].sec, oa->list[a[k].tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa->list[a[k].tn].y_id), Get_NAME(R_INF, oa->list[a[k].tn].y_id), a[k].qs, a[k].qe, a[k].qn, a[k].el); - continue; - } - a[k].ts = a[k].te = ((uint32_t)-1);///cluster - // fprintf(stderr, "[M::%s] z::%ld, tn::%u, sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\n", __func__, z, a[k].tn, a[k].sec, oa->list[a[k].tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa->list[a[k].tn].y_id), Get_NAME(R_INF, oa->list[a[k].tn].y_id), a[k].qs, a[k].qe, a[k].qn); - a[z++] = a[k]; - } - an = z; - if(an == 0) return 0; - - // fprintf(stderr, "*0*[M::%s] rid::%lu, an::%ld\n", __func__, rid, an); - for (k = ck = buf->n = gni = 0; k < an; k++) { - if((a[k].sec < c_sz) || (a[k].ts != ((uint32_t)-1))) continue; - // fprintf(stderr, "\n[M::%s] k::%ld\tsec::%u\tcc::%u\tck::%lu\ttn::%u\n", __func__, k, a[k].sec, a[k].ts, ck, a[k].tn); - - buf->n = 0; kv_push(uint64_t, *buf, k); iak = 0; - while (buf->n) { - v = buf->a[--buf->n]; - ol = (a[v].qe - a[v].qs) * len_st; if(ol < len_w) ol = len_w; - if((a[v].qe - a[v].qs) < ol) continue; - - // fprintf(stderr, "*0*[M::%s] v::%lu\n", __func__, v); - if((set_cgid(&(a[v]), ia, &iak, ian, ca, ck, oa->list, &gni)) || (a[v].ts == ck)) { - // fprintf(stderr, "*1*[M::%s] v::%lu\n", __func__, v); - for (z = 0; (z < an) && (a[z].qs < a[v].qe); z++) { - // fprintf(stderr, "*0*[M::%s] a[z].tn::%u, a[z].sec::%u, c_sz::%lu, a[z].ts:%u, v::%lu, z::%ld\n", __func__, a[z].tn, a[z].sec, c_sz, a[z].ts, v, z); - if((a[z].sec < c_sz) || (a[z].ts != ((uint32_t)-1)) || (((int64_t)v) == z)) continue; - // fprintf(stderr, "*1*[M::%s] a[z].tn::%u\n", __func__, a[z].tn); - if((cal_lindel_dd(&(a[v]), &(a[z]), len_st, len_w, err_dif, c_sz) >= 0) && (set_cgid(&(a[z]), ia, &iak, ian, ca, ck, oa->list, &gni))) { - kv_push(uint64_t, *buf, z); - // fprintf(stderr, "*2*[M::%s] z::%ld, a[z].tn::%u\n", __func__, z, a[z].tn); - } - } - } - } - - for (ii = 0; ii < iak; ii++) ia[ii] = 0; - ck++; - } - - // for (k = 0; k < an; k++) { - // fprintf(stderr, "*0*[M::%s] z::%ld, tn::%u, sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\tgid::%u\n", __func__, k, a[k].tn, a[k].sec, oa->list[a[k].tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa->list[a[k].tn].y_id), Get_NAME(R_INF, oa->list[a[k].tn].y_id), a[k].qs, a[k].qe, a[k].qn, a[k].ts); - // } - // fprintf(stderr, "*1*[M::%s] rid::%lu, an::%ld, ck::%lu\n", __func__, rid, an, ck); - if(ck <= 0 || gni <= 0) return 0; - - if(gni < an) { - ///build index for cluster - buf->n = an + ck; kv_resize(uint64_t, *buf, buf->n); - memset(buf->a, -1, sizeof((*(buf->a)))*buf->n); - ca = buf->a; ia = buf->a + ck; - for (k = 0; k < an; k++) { - if(a[k].ts == ((uint32_t)-1)) continue; - if(ca[a[k].ts] != ((uint64_t)-1)) { - ///set the previous one - assert(ia[((uint32_t)ca[a[k].ts])] == ((uint64_t)-1)); - ia[((uint32_t)ca[a[k].ts])] = k; - ca[a[k].ts] >>= 32; ca[a[k].ts] <<= 32; ca[a[k].ts] |= k; - } else { - ca[a[k].ts] = k; ca[a[k].ts] <<= 32; ca[a[k].ts] |= ((uint64_t)k); - } - } - - - for (k = ck = 0; k < an; k++) { - if(a[k].ts != ((uint32_t)-1)) { - ck++; continue; - } - ol = (a[k].qe - a[k].qs) * len_st; if(ol < len_w) ol = len_w; - if((a[k].qe - a[k].qs) < ol) continue; - mk = -1; msw = -1; - for (z = 0/**k + 1**/; (z < an) && (a[z].qs < a[k].qe); z++) { - if(a[z].sec < c_sz) continue; - if(a[z].ts == ((uint32_t)-1)) continue; - if(z == k) continue; - sw = cal_lindel_dd(&(a[k]), &(a[z]), len_st, len_w, err_dif, c_sz); - if(sw < 0) continue; - if((sw > msw) && (is_get_group(a, /**an, rid,**/ ca, ia, a[z].ts, a[k].tn))) { - mk = a[z].ts; msw = sw; - } - } - if(mk != -1) { - ck++; a[k].ts = mk; - ///set the previous one - assert(ia[((uint32_t)ca[a[k].ts])] == ((uint64_t)-1)); - ia[((uint32_t)ca[a[k].ts])] = k; - ca[a[k].ts] >>= 32; ca[a[k].ts] <<= 32; ca[a[k].ts] |= k; - } - } - } else { - ck = gni; - } - radix_sort_ul_ov_srt_ts1(a, a + an); - // for (k = 0; k < an; k++) { - // fprintf(stderr, "*1*[M::%s] z::%ld, tn::%u, sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\tgid::%u\n", __func__, k, a[k].tn, a[k].sec, oa->list[a[k].tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa->list[a[k].tn].y_id), Get_NAME(R_INF, oa->list[a[k].tn].y_id), a[k].qs, a[k].qe, a[k].qn, a[k].ts); - // } - return ck; -} - -void push_idel_info(haplotype_evdience_alloc *h, uint64_t s, uint64_t e, uint64_t err, ul_ov_t *a, uint64_t an, ul_ov_t *a1, uint64_t an1, overlap_region *oa, uint64_t *idx, uint64_t idx_n, uint64_t rid, int64_t het_cov, int64_t hom_cov, int64_t n_hap, double cut_rate, int64_t cut_bd) -{ - // fprintf(stderr, "\n"); - uint64_t k, q[2], os, oe, /**hn = h->length,**/ bl0 = h->length; int64_t cc, occ0, occ1, occ2; ul_ov_t *p; overlap_region *z; haplotype_evdience ev; int64_t ec; SnpStats *ps = NULL; - for (k = occ0 = occ1 = occ2 = 0; k < idx_n; k++) { - p = &(a[idx[k]]); z = &(oa[ovlp_id(*p)]); - if(z->is_match != 1) continue; - - q[0] = z->w_list.a[ovlp_cur_wid(*p)].x_start+ovlp_bd(*p); - q[1] = z->w_list.a[ovlp_cur_wid(*p)].x_end+1-ovlp_bd(*p); - os = MAX(q[0], s); oe = MIN(q[1], e); - if((oe > os) && ((oe - os) >= ((e - s) - (oe - os)))) { - // fprintf(stderr, "[M::%s]\ts::%lu\n", __func__, s); - ec = extract_sub_err(z, s, e, os, oe, err, 0.2, p); - if(ec >= 0) { - occ0++; - ev.misBase = 0; - ev.overlapID = ovlp_id(*p); - ev.site = s; - ev.overlapSite = h->snp_stat.n; - ev.type = 0; - ev.cov = ec;///error - // fprintf(stderr, "+0+[M::%s]\th->length::%u\tsite::%u\toverlapSite::%u\n", __func__, h->length, ev.site, ev.overlapSite); - addHaplotypeEvdience(h, &ev, NULL); - } else { - occ2++; - } - } - } - - ///add sv - for (k = 0, occ1 = an1; k < an1; k++) { - ev.misBase = 0; - ev.overlapID = a1[k].tn; - ev.site = s; - ev.overlapSite = h->snp_stat.n; - ev.type = 1; - ev.cov = a1[k].qn;///error - // fprintf(stderr, "+1+[M::%s]\th->length::%u\tsite::%u\toverlapSite::%u\n", __func__, h->length, ev.site, ev.overlapSite); - addHaplotypeEvdience(h, &ev, NULL); - } - - // for (k = hn; k < h->length; k++) { - // z = &(oa[h->list[k].overlapID]); - // fprintf(stderr, "[M::%s]\t%.*s\tq::[%u, %u)\terr::%u\ttype::%u\n", __func__, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), h->list[k].site, h->list[k].overlapSite, h->list[k].cov, h->list[k].type); - // } - - ///for debug indel - // if(occ0 < 2 || occ1 < 2) { - // h->length = bl0; - // return; - // } - occ0++; - cc = ((het_cov > 0)?(het_cov):(hom_cov/n_hap)); cc *= cut_rate; if(cc < cut_bd) cc = cut_bd; - if(occ0 < cc || occ1 < cc) { - h->length = bl0; - return; - } - - kv_pushp(SnpStats, h->snp_stat, &ps); - ps->id = h->snp_stat.n-1; - ps->occ_0 = occ0; - ps->occ_1 = occ1; - ps->occ_2 = occ2; - ps->site = s; - ps->score = -1; - ps->overlap_num = 0; - ps->is_homopolymer = 0; - // fprintf(stderr, "-[M::%s]\trid::%lu\t%.*s\tq::[%lu,%lu)\terr::%lu\tocc0::%lu\tocc1::%lu\tocc2::%lu\n", __func__, rid, (int)Get_NAME_LENGTH(R_INF, rid), Get_NAME(R_INF, rid), s, e, err, 1 + occ0, occ1, occ2); -} - -void gen_ov_lidel_variant(kv_ul_ov_t *cz, overlap_region_alloc *ol, asg64_v *idx, int64_t bd) -{ - uint64_t cbn = cz->n, k, i, t, zwn, m; int64_t q[2]; overlap_region *z; ul_ov_t *cp; - for (k = idx->n = 0; k < ol->length; k++) { - z = &(ol->list[k]); zwn = z->w_list.n; - if((!zwn) || (z->is_match != 1)) continue; - for (i = 0; i < zwn; i++) { - if(is_ualn_win(z->w_list.a[i])) continue; - q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; - q[0] += bd; q[1] -= bd; - if(q[1] >= q[0]) { - m = ((uint64_t)q[0]); m <<= 32; - m += (cz->n - cbn); kv_push(uint64_t, *idx, m); - - kv_pushp(ul_ov_t, *cz, &cp); - ovlp_id(*cp) = k; ///ovlp id - ovlp_cur_wid(*cp) = i; ///cur id of windows - ovlp_cur_xoff(*cp) = z->w_list.a[i].x_start; ///cur xpos - ovlp_cur_yoff(*cp) = z->w_list.a[i].y_start; ///cur xpos - ovlp_cur_ylen(*cp) = 0; - ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window - ovlp_bd(*cp) = bd; - } - } - } - - radix_sort_bc64(idx->a, idx->a + idx->n); - for (k = 1, i = 0; k <= idx->n; k++) { - if (k == idx->n || (idx->a[k]>>32) != (idx->a[i]>>32)) { - if(k - i > 1) { - for (t = i; t < k; t++) { - cp = &(cz->a[cbn + ((uint32_t)idx->a[t])]); - m = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); - m <<= 32; m += ((uint32_t)idx->a[t]); idx->a[t] = m; - } - radix_sort_bc64(idx->a + i, idx->a + k); - } - i = k; - } - } -} - - -uint64_t rcall_lidel_variant(kv_ul_ov_t *cz, overlap_region_alloc *ol, haplotype_evdience_alloc *hp, asg64_v *idx, asg64_v *idz, uint64_t rid) -{ - // fprintf(stderr, "-0-[M::%s] %.*s\tis_match::%u\n", __func__, (int)Get_NAME_LENGTH(R_INF, ol->list[48].y_id), Get_NAME(R_INF, ol->list[48].y_id), ol->list[48].is_match); - - uint64_t i, k, zi, zk, nec[2], p, pmm, pmn, bn0 = 0, *ia, in, sv_n = cz->n, svi_n = 0, ovn = 0, m, rm_n; /**overlap_region *z;**/ ul_ov_t ez, *cp; - hp->length = hp->snp_stat.n = idx->n = idz->n = 0; - ///for debug indel - // fprintf(stderr, "+[M::%s] sv_n::%lu\n", __func__, sv_n); - for (k = 1, i = 0; k <= sv_n; k++) { - // fprintf(stderr, "+[M::%s] i::%ld, k::%ld\n", __func__, i, k); - if (k == sv_n || (cz->a[k].ts) != (cz->a[i].ts)) { - ///calculate pos - for (zi = i, nec[0] = nec[1] = 0, idx->n = bn0, pmm = ((uint64_t)-1), pmn = 0; zi < k; zi++) { - // z = &(ol->list[cz->a[zi].tn]); - nec[cz->a[zi].el]++; - p = cz->a[zi].qs; p <<= 32; p |= ((uint64_t)cz->a[zi].qe); - kv_push(uint64_t, *idx, p); - if(pmm == ((uint64_t)-1)) pmm = p; - if(pmm == p) pmn++; - // fprintf(stderr, "[M::%s] cid::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\n", __func__, cz->a[zi].ts, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), cz->a[zi].qs, cz->a[zi].qe, cz->a[zi].qn); - } - if(nec[0] < nec[1]) { - ///calculate pos - if((pmn <= 0) || (pmn < (idx->n - bn0 - pmn))) { - ia = idx->a + bn0; in = idx->n - bn0; - if(k - i > 1) radix_sort_bc64(ia, ia + in); - for (zk = 1, zi = 0, pmm = ((uint64_t)-1), pmn = 0; zk <= in; zk++) { - if((zk == in) || (ia[zi] != ia[zk])) { - if((zk - zi) > pmn) { - pmn = zk - zi; pmm = ia[zi]; - } - zi = zk; - } - } - } - - ez.qs = pmm>>32; ez.qe = (uint32_t)pmm; ez.ts = i; ez.te = k; ez.qn = 0; ez.tn = cz->a[i].ts; - ///calculate error - for (zi = i, idx->n = bn0, pmm = ((uint64_t)-1), pmn = 0; zi < k; zi++) { - if((cz->a[zi].qs != ez.qs) || (cz->a[zi].qe != ez.qe)) continue; - kv_push(uint64_t, *idx, cz->a[zi].qn); - if(pmm == ((uint64_t)-1)) pmm = cz->a[zi].qn; - if(pmm == cz->a[zi].qn) pmn++; - } - if((pmn <= 0) || (pmn < (idx->n - bn0 - pmn))) { - ia = idx->a + bn0; in = idx->n - bn0; - if(k - i > 1) radix_sort_bc64(ia, ia + in); - for (zk = 1, zi = 0, pmm = ((uint64_t)-1), pmn = 0; zk <= in; zk++) { - if((zk == in) || (ia[zi] != ia[zk])) { - if((zk - zi) > pmn) { - pmn = zk - zi; pmm = ia[zi]; - } - zi = zk; - } - } - } - ez.qn = pmm; kv_push(ul_ov_t, *cz, ez); - - // fprintf(stderr, "-[M::%s] nec[0]::%ld, nec[1]::%ld, pa::[%u, %u), err::%u\n\n", __func__, nec[0], nec[1], ez.qs, ez.qe, ez.qn); - } - - i = k; - } - } - // fprintf(stderr, "-1-[M::%s] %.*s\tis_match::%u\n", __func__, (int)Get_NAME_LENGTH(R_INF, ol->list[48].y_id), Get_NAME(R_INF, ol->list[48].y_id), ol->list[48].is_match); - - svi_n = cz->n - sv_n; idx->n = 0; - gen_ov_lidel_variant(cz, ol, idx, 0); - ovn = cz->n - sv_n - svi_n; - // fprintf(stderr, "-2-[M::%s] %.*s\tis_match::%u\n", __func__, (int)Get_NAME_LENGTH(R_INF, ol->list[48].y_id), Get_NAME(R_INF, ol->list[48].y_id), ol->list[48].is_match); - // fprintf(stderr, "+[M::%s] sv_n::%lu, svi_n::%lu, ovn::%lu\n", __func__, sv_n, svi_n, ovn); - - ul_ov_t *sv = cz->a, *svi = cz->a + sv_n, *ov = cz->a + sv_n + svi_n; int64_t s, e, os, oe, q[2]; - radix_sort_ul_ov_srt_qs1(svi, svi + svi_n); - for (k = i = 0; k < svi_n; k++) { - // fprintf(stderr, "\n-3-[M::%s] %.*s\tis_match::%u\n", __func__, (int)Get_NAME_LENGTH(R_INF, ol->list[48].y_id), Get_NAME(R_INF, ol->list[48].y_id), ol->list[48].is_match); - ///label matched overlaps - s = svi[k].qs; e = svi[k].qe; - for (p = svi[k].ts; p < svi[k].te; p++) { - // z = &(ol->list[sv[p].tn]); - // fprintf(stderr, "+++[M::%s] cid::%lu\tccid::%lu\trid::%u\t%.*s\tq::[%ld,%ld)\terr::%u\n", __func__, k, p - svi[k].ts, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), s, e, sv[p].qn); - assert(sv[p].ts == svi[k].tn); - // if(!(ol->list[sv[p].tn].is_match == 1)) { - // fprintf(stderr, "+[M::%s] rid::%lu\toid::%u\tis_match::%u\n", __func__, rid, sv[p].tn, ol->list[sv[p].tn].is_match); - // fprintf(stderr, "[M::%s] cid::%lu\tccid::%lu\trid::%u\t%.*s\tq::[%ld,%ld)\terr::%u\n", __func__, k, p - svi[k].ts, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), s, e, sv[p].qn); - // } - assert(ol->list[sv[p].tn].is_match == 1); - ol->list[sv[p].tn].is_match = 2; - } - - ///filter out passed overlaps - for (m = rm_n = ovn; m < idx->n; m++) { - cp = &(ov[idx->a[m]]); - q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); - q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); - if(q[1] <= s) continue; - idx->a[rm_n++] = idx->a[m]; - } - idx->n = rm_n; - - ///push new overlaps - for (; i < ovn; ++i) { - cp = &(ov[(uint32_t)idx->a[i]]); - q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); - q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); - if(q[0] >= e) break; - os = MAX(q[0], s); oe = MIN(q[1], e); - if(oe > os) { - kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); - } - } - - push_idel_info(hp, s, e, svi[k].qn, ov, ovn, sv + svi[k].ts, svi[k].te - svi[k].ts, ol->list, idx->a + ovn, idx->n - ovn, rid, asm_opt.het_cov, asm_opt.hom_cov, asm_opt.polyploidy, 0.333333, 5); - - ///relabel matched overlaps - for (p = svi[k].ts; p < svi[k].te; p++) { - assert(ol->list[sv[p].tn].is_match == 2); - ol->list[sv[p].tn].is_match = 1; - } - // fprintf(stderr, "-4-[M::%s] %.*s\tis_match::%u\n", __func__, (int)Get_NAME_LENGTH(R_INF, ol->list[48].y_id), Get_NAME(R_INF, ol->list[48].y_id), ol->list[48].is_match); - } - - return hp->length; -} - -uint64_t rphase_lidel(overlap_region_alloc* ol, All_reads *rref, haplotype_evdience_alloc* hp, UC_Read *qu, UC_Read *tu, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, int64_t bd, int64_t wl, int64_t ql, uint8_t occ_thres, uint64_t rid, uint64_t hpc_len, uint64_t std_bs) -{ - hp->length = hp->snp_stat.n = 0; - int64_t on = ol->length, k, i, zwn, q[2], t[2]; - overlap_region *z; //ul_ov_t *cp; - for (k = idx->n = c_idx->n = 0; k < on; k++) { - z = &(ol->list[k]); zwn = z->w_list.n; - if((!zwn) || (z->is_match != 1)) continue; - for (i = 0; i < zwn; i++) { - if(is_ualn_win(z->w_list.a[i])) continue; - q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end + 1; - t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end + 1; - if(q[1] > q[0] && t[1] > t[0]) { - extract_sub_cigar_sv(z, k, i, rref, qu->seq, qu->length, tu, c_idx, 16, hpc_len, 2); - } - } - } - if(c_idx->n <= 0) return 0; - - idx->n = (c_idx->n<<1); - kv_resize(uint64_t, *idx, idx->n); on = c_idx->n; idx->n = 0; - radix_sort_ul_ov_srt_qs1(c_idx->a, c_idx->a + on); - for (k = 1, i = 0; k <= on; k++) { - if (k == on || (c_idx->a[k].qs) != (c_idx->a[i].qs)) { - if(k > i + k) radix_sort_ul_ov_srt_qe1(c_idx->a + i, c_idx->a + k); - i = k; - } - } - // fprintf(stderr, "-0-[M::%s]\n", __func__); - on = rphase_lidel_cc(ol, c_idx->a, on, 0.500001, 3, 0.25, 3, rid, buf, idx); - c_idx->n = on; - // fprintf(stderr, "-1-[M::%s]\n", __func__); - return rcall_lidel_variant(c_idx, ol, hp, idx, buf, rid); -} - - -void rphase_hc(overlap_region_alloc* ol, All_reads *rref, haplotype_evdience_alloc* hp, UC_Read* qu, UC_Read* tu, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, int64_t bd, int64_t wl, int64_t ql, uint8_t occ_thres/**, uint8_t is_dbg**/, uint64_t rid, uint64_t hpc_len, uint64_t std_bs, Chain_Data *dp, asg8_v *q8, asg8_v *t8, uint8_t lindel) -{ - int64_t on = ol->length, k, i, zwn, q[2]; - uint64_t m, l0, wi, wl0, si, ei, fi; overlap_region *z; ul_ov_t *cp; - kv_resize(uint64_t, *idx, (ol->length)); - kv_resize(ul_ov_t, *c_idx, ol->length); - - for (k = idx->n = c_idx->n = 0; k < on; k++) { - z = &(ol->list[k]); zwn = z->w_list.n; - if(!zwn) continue; - for (i = 0; i < zwn; i++) { - if(is_ualn_win(z->w_list.a[i])) continue; - q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; - q[0] += bd; q[1] -= bd; - if(q[1] >= q[0]) { - m = ((uint64_t)q[0]); m <<= 32; - m += c_idx->n; kv_push(uint64_t, *idx, m); - - kv_pushp(ul_ov_t, *c_idx, &cp); - ovlp_id(*cp) = k; ///ovlp id - ovlp_cur_wid(*cp) = i; ///cur id of windows - ovlp_cur_xoff(*cp) = z->w_list.a[i].x_start; ///cur xpos - ovlp_cur_yoff(*cp) = z->w_list.a[i].y_start; ///cur xpos - ovlp_cur_ylen(*cp) = 0; - ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window - ovlp_bd(*cp) = bd; - } - } - } - - int64_t srt_n = idx->n, s, e, t, os, oe, rm_n, rr; i = 0; - radix_sort_bc64(idx->a, idx->a+idx->n); - for (k = 1, i = 0; k <= srt_n; k++) { - if (k == srt_n || (idx->a[k]>>32) != (idx->a[i]>>32)) { - if(k - i > 1) { - for (t = i; t < k; t++) { - cp = &(c_idx->a[(uint32_t)idx->a[t]]); - // s = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); - // assert(s == (int64_t)(idx->a[i]>>32)); - m = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); - m <<= 32; m += ((uint32_t)idx->a[t]); idx->a[t] = m; - // fprintf(stderr, "[M::%s] s::%ld\tsi::%lu\n", __func__, s, (idx->a[i]>>32)); - } - radix_sort_bc64(idx->a + i, idx->a + k); - } - i = k; - } - } - - ResizeInitHaplotypeEvdience(hp); - i = 0; s = 0; e = wl; e = ((e<=ql)?e:ql); rr = 0; - for (; s < ql; ) { - if(rr) { - // rr = 0; - for (m = rm_n = srt_n; m < idx->n; m++) { - cp = &(c_idx->a[idx->a[m]]); - q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); - q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); - os = MAX(q[0], s); oe = MIN(q[1], e); - if(oe > os) { - idx->a[rm_n++] = idx->a[m]; - // if(q[1] <= e) rr = 1; - } - } - idx->n = rm_n; - } - - for (; i < srt_n; ++i) { - cp = &(c_idx->a[(uint32_t)idx->a[i]]); - q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); - q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); - if(q[0] >= e) break; - os = MAX(q[0], s); oe = MIN(q[1], e); - if(oe > os) { - kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); - // if(q[1] <= e) rr = 1; - } - } - - // fprintf(stderr, "[M::%s] s::%ld, e::%ld, srt_n::%ld, idx->n::%ld\n", __func__, s, e, srt_n, (int64_t)idx->n); - // debug_inter(ol, c_idx, idx->a, srt_n, idx->a + srt_n, idx->n - srt_n, s, e); - l0 = hp->length; - // if(is_dbg) fprintf(stderr, "-1-[M::%s]\ts::%ld\te::%ld\n", __func__, s, e); - rr = hc_phase_robust_rr(ol->list, rref, hp, qu->seq, qu->length, tu, idx->a + srt_n, idx->n - srt_n, s, e, c_idx->a, 1, occ_thres, hpc_len/**, is_dbg**/); - for (wi = fi = ei = 0, si = ((uint64_t)-1), wl0 = e - s; wi < wl0; wi++) { - if(hp->flag[wi] > 0) { - if(hp->flag[wi] > occ_thres) { - fi = 1; hp->nn_snp++; hp->flag[wi] = 1; - if((hpc_len) && (hpc_mask_ff(qu->seq, qu->length, wi + s, hpc_len, HPC_RR, NULL, 0, 0, HPC_CC))) hp->flag[wi] = 3; - ei = wi + 1; if(si == ((uint64_t)-1)) si = wi; - } else { - hp->flag[wi] = 0; - } - } - } - - if(fi) { - // if(is_dbg) fprintf(stderr, "-2-[M::%s]\ts::%ld\te::%ld\n", __func__, s, e); - rr = hc_phase_robust_rr(ol->list, rref, hp, qu->seq, qu->length, tu, idx->a + srt_n, idx->n - srt_n, s, e, c_idx->a, 0, occ_thres, hpc_len/**, is_dbg**/); - if(hp->length > l0) radix_sort_haplotype_evdience_srt(hp->list + l0, hp->list + hp->length); - } - - if(ei > si) memset(hp->flag + si, 0, (ei-si)*sizeof((*(hp->flag)))); - // if(is_dbg) fprintf(stderr, "-3-[M::%s]\ts::%ld\te::%ld\n", __func__, s, e); - - s += wl; e += wl; e = ((e<=ql)?e:ql); - } - - // debug_snp_site(ol->list, rref, qu, hp->list, hp->length); - - - SetSnpMatrix(hp, &(hp->nn_snp), &(ol->length), 0, NULL); - srt_n = hp->length; z = (((std_bs)||(t8))?(ol->list):(NULL)); - for (k = 1, i = t = 0; k <= srt_n; ++k) { - if (k == srt_n || hp->list[k].site != hp->list[i].site) { - t += push_info(hp, hp->list+i, k-i, hp->list+t, z, t8, sc_wn); - i = k; - } - } - hp->length = t; - - if(!dp) { - // generate_haplotypes_naive_advance(hap, overlap_list, NULL); - generate_haplotypes_naive_HiFi(hp, ol, 0.04, qu, ((std_bs)?(0):(1)), ((std_bs)?(0.05):(0)), ((std_bs)?(2):((uint64_t)-1))); - // generate_haplotypes_DP(hap, overlap_list, R_INF, g_read->length, force_repeat); - // generate_haplotypes_naive(hap, overlap_list, R_INF, g_read->length, force_repeat); - } else { - gen_rphase_dp(hp, ol, qu, ((std_bs)?(0.05):(0)), ((std_bs)?(2):((uint64_t)-1)), dp, idx, buf, rid, q8); - generate_haplotypes_naive_HiFi(hp, ol, 0.04, qu, ((std_bs)?(0):(1)), ((std_bs)?(0.05):(0)), ((std_bs)?(2):((uint64_t)-1))); - } - - if(lindel) { - if(rphase_lidel(ol, rref, hp, qu, tu, c_idx, idx, buf, bd, wl, ql, occ_thres, rid, hpc_len, std_bs)) { - generate_haplotypes_sv(hp, ol, rid); - } - } -} - -int64_t gen_aln_ul_ov_t(int64_t in_id, int64_t tl, overlap_region *in, ul_ov_t *ou) -{ - int64_t zwn; memset(ou, 0, sizeof((*ou))); - zwn = in->w_list.n; if(!zwn) return 0; - - ///in_id -> ovlp id - ou->qn = in_id; ou->tn = in->y_id; - ou->rev = in->y_pos_strand; - ou->qs = in->w_list.a[0].x_start; - ou->qe = in->w_list.a[zwn-1].x_end+1; - - if(!(ou->rev)) { - ou->ts = in->w_list.a[0].y_start; - ou->te = in->w_list.a[zwn-1].y_end+1; - } else { - ou->ts = tl-(in->w_list.a[zwn-1].y_end+1); - ou->te = tl-in->w_list.a[0].y_start; - } - return 1; -} - -uint32_t push_emask_flt(kv_emask_t *in, uint64_t *flt, uint64_t flt_n, uint64_t qn, kv_ul_ov_t *res) -{ - uint32_t k = 0, z = 0, tn, rn0 = res->n; ul_ov_t *p; - while (k < in->n && z < flt_n) { - if (in->a[k].tn < (flt[z]>>32)) { - k++; - } else if((flt[z]>>32) < in->a[k].tn) { - z++; - } else {///in->a[k].tn == (flt[z]>>32) - for (tn = in->a[k].tn; k < in->n && in->a[k].tn == tn; k++) { - kv_pushp(ul_ov_t, *res, &p); - p->qn = qn; p->qs = in->a[k].qs; p->qe = in->a[k].qe; - p->tn = in->a[k].tn; p->ts = in->a[k].ts; p->te = in->a[k].te; - p->rev = in->a[k].rev; p->el = in->a[k].full; p->sec = k; - } - for (; z < flt_n && (flt[z]>>32) == tn; z++); - } - } - return res->n-rn0; -} - -#define is_ul_ov_pe(z, zn, i, mm) ((((i)+1)<(zn))&&((z)[(i)+1].qn==(z)[(i)].qn)&&((z)[(i)+1].tn==(z)[(i)].tn)&&((z)[(i)+1].rev==(z)[(i)].rev)\ - &&((z)[(i)+1].sec==(z)[(i)].sec+1)&&(((z)[(i)].sec)<(mm).a[(z)[(i)].qn].n)&&(((z)[(i)+1].sec)<(mm).a[(z)[(i)+1].qn].n)\ - &&((mm).a[(z)[(i)].qn].a[((z)[(i)].sec)].pe)&&((mm).a[(z)[(i)+1].qn].a[((z)[(i)+1].sec)].pe)\ - &&((mm).a[(z)[(i)].qn].a[((z)[(i)].sec)].dir==0)&&((mm).a[(z)[(i)+1].qn].a[((z)[(i)+1].sec)].dir==1)) - -#define is_exact_ov(z, mm) (((((z).sec)<(mm).a[(z).qn].n))&&(!((mm).a[(z).qn].a[((z).sec)].pe))\ - &&((mm).a[(z).qn].a[((z).sec)].el==(uint32_t)-1)) - - -///ref_n <= 2 -uint64_t is_cover_ul_ov_t(ma_ug_t *ug, double diff, ul_ov_t *ref, uint64_t ref_n, ul_ov_t *in) -{ - if((!check_ul_ov_t_consist(in, &(ref[0]), ug->g->seq[in->qn].len, ug->g->seq[in->tn].len, diff))) return 0; - if((ref_n > 1) && (!check_ul_ov_t_consist(in, &(ref[ref_n-1]), ug->g->seq[in->qn].len, ug->g->seq[in->tn].len, 0.06))) return 0; - uint64_t i; int64_t sql, stl, os, oe, ovlp; - sql = in->qe - in->qs; stl = in->te - in->ts; - for (i = 0; i < ref_n && sql > 0 && stl > 0; i++) { - os = MAX(in->qs, ref[i].qs); oe = MIN(in->qe, ref[i].qe); - ovlp = ((oe>os)?(oe-os):(0)); sql -= ovlp; - - os = MAX(in->ts, ref[i].ts); oe = MIN(in->te, ref[i].te); - ovlp = ((oe>os)?(oe-os):(0)); stl -= ovlp; - } - if((sql > 256) && (sql > ((in->qe - in->qs)*0.06))) return 0; - if((sql <= 256) && (sql > ((in->qe - in->qs)*0.6))) return 0; - if((stl > 256) && (stl > ((in->te - in->ts)*0.06))) return 0; - if((stl <= 256) && (stl > ((in->te - in->ts)*0.6))) return 0; - return 1; -} - -uint64_t dedup_src_shared(ma_ug_t *ug, ul_ov_t *ta, uint64_t tn, ul_ov_t *qa, uint64_t qn, idx_emask_t *mm) -{ - uint32_t ti, qi, ts, te, id, k, l; - ti = qi = 0; - while (ti < tn && qi < qn) { - if (ta[ti].tn < qa[qi].tn) { - ti++; - } else if(qa[qi].tn < ta[ti].tn) { - qi++; - } else {///ta[ti].tn == qa[qi].tn - id = ta[ti].tn; - for (ts = ti; ti < tn && ta[ti].tn == id; ti++); te = ti; - for (; qi < qn && qa[qi].tn == id; qi++) { - for (k = ts; k < te; k++) { - l = 1; - if(is_ul_ov_pe(ta, te, k, (*mm))) { - l++; k++; - } - if(is_cover_ul_ov_t(ug, 0.06, ta+k+1-l, l, &(qa[qi]))) break; - } - if(k < te) qa[qi].qn = qa[qi].tn = (uint32_t)-1; - } - } - } - for (qi = l = 0; qi < qn; qi++) { - if(qa[qi].tn == (uint32_t)-1) continue; - qa[l++] = qa[qi]; - } - return l; -} - -void dedup_src_shared1(ma_ug_t *ug, kv_ul_ov_t *res, uint64_t tocc, uint64_t qocc, idx_emask_t *mm) -{ - if((!tocc) || (!qocc)) return; - uint32_t ti, qi, tn, qn, rn = res->n, id, ts, te, k, l, ff = 0; - // qi = res->n - qocc; fi = 0; m = qi; qocc = 0; - // while (qi < res->n && fi < flt_n) { - // if(res->a[qi].tn < (flt[fi]>>32)) { - // qi++; - // } else if((flt[fi]>>32) < res->a[qi].tn) { - // fi++; - // } else {///res->a[qi].tn == (flt[fi]>>32) - // res->a[m++] = res->a[qi]; qocc++; qi++; fi++; - // } - // } - // res->n = m; - // if((!tocc) || (!qocc)) return; - - rn = res->n; - ti = res->n - tocc - qocc; qi = res->n - qocc;//t first, and then q - tn = ti + tocc; qn = qi + qocc; kv_resize(ul_ov_t, *res, (rn+tn));///the buf size should be at least tn - while (ti < tn && qi < qn) { - if (res->a[ti].tn < res->a[qi].tn) { - kv_push(ul_ov_t, *res, res->a[ti]); ti++; - } else if(res->a[qi].tn < res->a[ti].tn) { - kv_push(ul_ov_t, *res, res->a[qi]); qi++; - } else {///ta[ti].tn == qa[qi].tn - id = res->a[ti].tn; ts = ti; - for (; ti < tn && res->a[ti].tn == id; ti++) { - kv_push(ul_ov_t, *res, res->a[ti]); - } - te = ti; - - for (; qi < qn && res->a[qi].tn == id; qi++) { - for (k = ts; k < te; k++) { - l = k; - if(is_ul_ov_pe(res->a, te, k, (*mm))) k++; - if(is_cover_ul_ov_t(ug, 0.06, res->a+l, k+1-l, &(res->a[qi]))) { - ff = 1; break; - } - } - if(k >= te) kv_push(ul_ov_t, *res, res->a[qi]); - } - } - } - while (ti < tn) { - kv_push(ul_ov_t, *res, res->a[ti]); ti++; - } - while (qi < qn) { - kv_push(ul_ov_t, *res, res->a[qi]); qi++; - } - - // fprintf(stderr, "[M::%s]\tff::%u\n", __func__, ff); - if(!ff) {///nothing has been removed as duplication - res->n = rn; - } else if(res->n > rn) { - l = res->n; res->n = rn - tocc - qocc; - for (k = rn; k < l; k++) res->a[res->n++] = res->a[k]; - } -} - -#define aln2ov(in, ou, tl) \ - {(ou).qn=(in).x_id;(ou).tn=(in).y_id;(ou).rev=(in).y_pos_strand;\ - (ou).qs=(in).x_pos_s;(ou).qe=(in).x_pos_e+1;\ - if((in).y_pos_strand){(ou).ts=(tl)-(in).y_pos_e-1;(ou).te=(tl)-(in).y_pos_s;}\ - else {(ou).ts=(in).y_pos_s;(ou).te=(in).y_pos_e+1;}} - -uint64_t cal_x_ul_ovlp(ma_ug_t *ug, overlap_region *q, overlap_region *t, ul_ov_t *res) -{ - ul_ov_t qo, to; uint32_t ql, tl, os, oe, rqs, rqe, rts, rte; - ql = ug->g->seq[q->y_id].len; tl = ug->g->seq[t->y_id].len; - aln2ov((*q), qo, ql); aln2ov((*t), to, tl); memset(res, 0, sizeof(*res)); - os = MAX(qo.qs, to.qs); oe = MIN(qo.qe, to.qe); - if(oe <= os) return 0; - if(infer_se(qo.qs, qo.qe, qo.ts, qo.te, qo.rev, os, oe, &rqs, &rqe) && - infer_se(to.qs, to.qe, to.ts, to.te, to.rev, os, oe, &rts, &rte)) { - if(rqe > rqs && rte > rts) { - res->qn = qo.tn; res->tn = to.tn; res->rev = ((qo.rev==to.rev)?0:1); - res->qs = rqs; res->qe = rqe; res->ts = rts; res->te = rte; - return 1; - } - } - return 0; -} - -uint64_t check_mask_exist(ma_ug_t *ug, overlap_region *q, overlap_region *t, kv_ul_ov_t *ov_db, idx_emask_t *mm, double len_diff, uint64_t *is_exact, uint64_t *ovdb_idx) -{ - ul_ov_t rr, *a; uint64_t k, eid, an, ss; (*is_exact) = 0; (*ovdb_idx) = (uint64_t)-1; - if(!cal_x_ul_ovlp(ug, q, t, &rr)) return 0; - ss = q->overlapLen; - if(q->x_pos_strand) {///if q does not have mask - eid = rr.tn; a = ov_db->a + ss; an = q->x_pos_strand; - for (k = 0; k < an && a[k].tn < eid; k++); - for (; k < an && a[k].tn == eid; k++) { - if((!check_ul_ov_t_consist(&rr, &(a[k]), ug->g->seq[rr.qn].len, ug->g->seq[rr.tn].len, len_diff))) continue; - if(is_ul_ov_pe(a, an, k, (*mm))) { - k++; if((!check_ul_ov_t_consist(&rr, &(a[k]), ug->g->seq[rr.qn].len, ug->g->seq[rr.tn].len, len_diff))) continue; - } - if(is_exact_ov(a[k],(*mm))) (*is_exact) = 1; - (*ovdb_idx) = ss + k; - return 1; - } - } - - k = rr.qn; rr.qn = rr.tn; rr.tn = k; - k = rr.qs; rr.qs = rr.ts; rr.ts = k; - k = rr.qe; rr.qe = rr.te; rr.te = k; - ss = t->overlapLen; - if(t->x_pos_strand) {///if t does not have mask - eid = rr.tn; a = ov_db->a + ss; an = t->x_pos_strand; - for (k = 0; k < an && a[k].tn < eid; k++); - for (; k < an && a[k].tn == eid; k++) { - if((!check_ul_ov_t_consist(&rr, &(a[k]), ug->g->seq[rr.qn].len, ug->g->seq[rr.tn].len, len_diff))) continue; - if(is_ul_ov_pe(a, an, k, (*mm))) { - k++; if((!check_ul_ov_t_consist(&rr, &(a[k]), ug->g->seq[rr.qn].len, ug->g->seq[rr.tn].len, len_diff))) continue; - } - if(is_exact_ov(a[k],(*mm))) (*is_exact) = 1; - (*ovdb_idx) = ss + k; - return 1; - } - } - return 0; -} - -void push_consist_ul_ovlps(ma_ug_t *ug, kv_ul_ov_t *ov_db, uint64_t s, uint64_t e, double len_diff, ul_ov_t *ref, idx_emask_t *mm, kv_ul_ov_t *out, uint64_t flip_res, uint64_t *is_exact) -{ - (*is_exact) = 0; - if(s >= e) return; - uint64_t k, z, ql = ug->g->seq[ref->qn].len, tl = ug->g->seq[ref->tn].len; ul_ov_t *p; - for (k = s; k < e && ov_db->a[k].tn < ref->tn; k++); - for (; k < e && ov_db->a[k].tn == ref->tn; k++) { - if((!check_ul_ov_t_consist(ref, &(ov_db->a[k]), ql, tl, len_diff))) continue; - z = k; - if(is_ul_ov_pe(ov_db->a, ov_db->n, k, (*mm))) { - k++; if((!check_ul_ov_t_consist(ref, &(ov_db->a[k]), ql, tl, len_diff))) continue; - } - if(is_exact_ov(ov_db->a[k], (*mm))) { - (*is_exact) = 1; return; - } - - for (; z <= k; z++) { - kv_pushp(ul_ov_t, *out, &p); - *p = ov_db->a[k]; - if(flip_res) { - p->qn = ov_db->a[k].tn; p->tn = ov_db->a[k].qn; - p->qs = ov_db->a[k].ts; p->qe = ov_db->a[k].te; - p->ts = ov_db->a[k].qs; p->te = ov_db->a[k].qe; - } - } - } -} - -uint64_t cal_no_bd_coor(ul_ov_t *in, ul_ov_t *ou, idx_emask_t *mm, int64_t bd) -{ - int64_t qs, qe, ts, te; emask_t *z; - qs = in->qs; qe = in->qe; ts = in->ts; te = in->te; - if(in->sec != ((uint32_t)(0x3fffffff))) {///might be an end mask; no need shrink - if((in->sec < mm->a[in->qn].n) && (in->tn == mm->a[in->qn].a[in->sec].tn) && (in->rev == mm->a[in->qn].a[in->sec].rev) && - (in->qs == mm->a[in->qn].a[in->sec].qs) && (in->qe == mm->a[in->qn].a[in->sec].qe) && - (in->ts == mm->a[in->qn].a[in->sec].ts) && (in->te == mm->a[in->qn].a[in->sec].te)) { - z = &(mm->a[in->qn].a[in->sec]); assert(z->el != ((uint32_t)-1)); - if(z->dir == 0) { - qe -= (z->el>>1); - if(in->rev) ts += (z->el>>1); - else te -= (z->el>>1); - } else { - qs += (z->el>>1); - if(in->rev) te -= (z->el>>1); - else ts += (z->el>>1); - } - // fprintf(stderr, "+[M::%s]\tz->dir::%u\tz->el::%u\tq::[%ld,\t%ld)\tt::[%ld,\t%ld)\n", __func__, z->dir, z->el, qs, qe, ts, te); - } else { - assert((in->sec < mm->a[in->tn].n) && (in->qn == mm->a[in->tn].a[in->sec].tn) && (in->rev == mm->a[in->tn].a[in->sec].rev) && - (in->qs == mm->a[in->tn].a[in->sec].ts) && (in->qe == mm->a[in->tn].a[in->sec].te) && - (in->ts == mm->a[in->tn].a[in->sec].qs) && (in->te == mm->a[in->tn].a[in->sec].qe)); - z = &(mm->a[in->tn].a[in->sec]); assert(z->el != ((uint32_t)-1)); - if(z->dir == 1) { - qe -= (z->el>>1); - if(in->rev) ts += (z->el>>1); - else te -= (z->el>>1); - } else { - qs += (z->el>>1); - if(in->rev) te -= (z->el>>1); - else ts += (z->el>>1); - } - // fprintf(stderr, "-[M::%s]\tz->dir::%u\tz->el::%u\tq::[%ld,\t%ld)\tt::[%ld,\t%ld)\n", __func__, z->dir, z->el, qs, qe, ts, te); - } - } else {///shrink anyway - qs += bd; qe -= bd; ts += bd; te -= bd; - } - if(qe > qs && te > ts) { - (*ou) = (*in); - ou->qs = qs; ou->qe = qe; ou->ts = ts; ou->te = te; - return 1; - } - return 0; -} - -typedef struct { - int64_t qi, qs, qe; - int64_t ti; - int64_t qis, qie, tis, tie; - int64_t wi, wn; - int64_t tot, lc, cql, ctl, ci, lerr; - overlap_region *z; -} pe_cigar_iter_t; - -#define citer_end(m) ((m).qi>=(m).qe) - -/** -inline void pop_citer(pe_cigar_iter_t *it) -{ - it->lc = it->lerr = -1; it->cql = it->ctl = 0; - it->qis = it->qie; it->tis = it->tie; - if(it->wi >= it->wn) return; - int64_t ws, we, os, oe, ovlp, ql, tl, werr; - window_list *m; bit_extz_t ez; - - while (it->wi < it->wn) { - m = &(it->z->w_list.a[it->wi]); - ws = m->x_start; we = m->x_end+1; - os = MAX(it->qs, ws); oe = MIN(it->qe, we); - ovlp = ((oe>os)? (oe-os):0); - - if(ovlp) { - ql = m->x_end+1-m->x_start; - tl = m->y_end+1-m->y_start; - if((is_ualn_win((*m))) || (is_est_aln((*m)))) { - it->lc = 4;//not an ordinary cigar - if(is_ualn_win((*m))) { //unmapped - werr = gen_err_unaligned(ql, tl); - } else { - werr = m->error;//shared window - if(!werr) it->lc = 0;///treat it as match - } - it->lerr = werr; - if(ovlp < ql) { - werr = (((double)ovlp)/((double)ql))*((double)werr); - } - //skip the whole window - it->tot += werr; - it->qis = it->qi; it->qi = it->qie = m->x_end+1; it->cql = it->qie - it->qis; - it->tis = it->ti; it->ti = it->tie = m->x_start; it->ctl = it->tie - it->tis; - it->ci = 0; it->wi++; - return; - } else { - if(it->qi < m->x_start || it->ti < m->y_start) { - it->qi = m->x_start; it->ti = m->y_start; it->ci = 0; - } - set_bit_extz_t(ez, (*(it->z)), it->wi); - // if(ovlp == ql) { - // //skip the whole window - // err += m->error; xk = m->x_end+1; ck = m->clen; - // } else { - // set_bit_extz_t(ez, (*z), wk); - // err += retrieve_cigar_err(&ez, os, oe, &xk, &ck); - // } - } - } - } -} -**/ - -int64_t get_pe_diff(overlap_region *q, uint64_t *qmask, uint64_t qmask_n, overlap_region *t, uint64_t *tmask, uint64_t tmask_n, int64_t bd) -{ - int64_t s, e; overlap_region *z; - pe_cigar_iter_t qi, ti; - z = q; if(!(z->w_list.n)) return 0; - s = z->w_list.a[0].x_start; e = z->w_list.a[z->w_list.n-1].x_end+1; - s += bd; e -= bd; if(s >= e) return 0; - memset(&qi, 0, sizeof(qi)); - qi.z = q; qi.qs = s; qi.qe = e; - qi.qi = q->w_list.a[0].x_start; - qi.ti = q->w_list.a[0].y_start; - qi.wi = 0; qi.wn = q->w_list.n; - qi.tot = 0; qi.ci = 0; qi.lc = -1; qi.cql = qi.ctl = 0; - qi.qis = qi.qie = qi.qi; - qi.tis = qi.tie = qi.ti; - qi.lerr = -1; - - z = t; if(!(z->w_list.n)) return 0; - s = z->w_list.a[0].x_start; e = z->w_list.a[z->w_list.n-1].x_end+1; - s += bd; e -= bd; if(s >= e) return 0; - memset(&ti, 0, sizeof(ti)); - ti.z = q; ti.qs = s; ti.qe = e; - ti.qi = t->w_list.a[0].x_start; - ti.ti = t->w_list.a[0].y_start; - ti.wi = 0; ti.wn = t->w_list.n; - ti.tot = 0; ti.ci = 0; ti.lc = -1; ti.cql = ti.ctl = 0; - ti.qis = ti.qie = ti.qi; - ti.tis = ti.tie = ti.ti; - ti.lerr = -1; - - while((!citer_end(qi)) && (!citer_end(ti))) { - if(qi.qi == ti.qi) {///check if it is been masked - - } else if((qi.lc == 0) && (ti.lc == 0)) {///check if it is been masked - - } - - if(qi.qi < ti.qi) { - - } if(ti.qi < qi.qi) { - - } else {//qi.qi == ti.qi - - } - } - return 0; -} - -void retrieve_cigar_xcoord(bit_extz_t *ez, int64_t is, int64_t ie, int64_t *yk, int64_t *xk, int64_t *ck, int64_t *rxs, int64_t *rxe) -{ - if(!ez->cigar.n) return; - int64_t cn = ez->cigar.n, op; int64_t ws, we, ws0, we0, os, oe; - if(((*ck) < 0) || ((*ck) > cn)) {//(*ck) == cn is allowed - (*ck) = 0; (*yk) = ez->ps; (*xk) = ez->ts; - } - - while ((*ck) > 0 && (*yk) > is) { - --(*ck); - op = ez->cigar.a[(*ck)]>>14; - if(op!=3) (*yk) -= (ez->cigar.a[(*ck)]&(0x3fff)); - if(op!=2) (*xk) -= (ez->cigar.a[(*ck)]&(0x3fff)); - } - - //some cigar will span s or e - while ((*ck) < cn && (*yk) < ie) {//[s, e) - ws = (*yk); ws0 = (*xk); - op = ez->cigar.a[(*ck)]>>14; - if(op!=3) (*yk) += (ez->cigar.a[(*ck)]&(0x3fff)); - if(op!=2) (*xk) += (ez->cigar.a[(*ck)]&(0x3fff)); - we = (*yk); we0 = (*xk); - if(ws >= is && we <= ie) {///the cigar is fully contained - if((*rxs) > ws0) (*rxs) = ws0; - if((*rxe) < we0) (*rxe) = we0; - } else if(op == 0 || op == 1) {///overlap, it is hard to handle indels - os = MAX(is, ws); oe = MIN(ie, we); - if(oe > os) { - ws0 += (os - ws); - we0 = ws0 + (oe - os); - if((*rxs) > ws0) (*rxs) = ws0; - if((*rxe) < we0) (*rxe) = we0; - } - } - (*ck)++; - } -} - -uint64_t extract_xcoordates0(overlap_region *z, int64_t ys, int64_t ye, int64_t *rxs, int64_t *rxe, ul_ov_t *p) -{ - int64_t wk = ovlp_cur_wid(*p), yk = ovlp_cur_xoff(*p), xk = ovlp_id(*p), ck = ovlp_cur_coff(*p); - int64_t min_w = ovlp_min_wid(*p), max_w = ovlp_max_wid(*p);//[min_w, max_w] - bit_extz_t ez; window_list *m; (*rxs) = INT32_MAX; (*rxe) = -1; - if(ys >= ye) return 0; - ///[ys, ye) but [z->w_list.a[wk].y_start, z->w_list.a[wk].y_end] - int64_t ws, we, os, oe, ovlp, yl, tot = ye - ys; - if(wk < min_w || wk > max_w) wk = min_w; - for (; wk >= min_w && z->w_list.a[wk].y_start > ys; wk--); - if(wk < min_w || wk > max_w) return 0; - for (; wk <= max_w && z->w_list.a[wk].y_end < ys; wk++); - if(wk < min_w || wk > max_w) return 0; - //s >= w_list.a[wk].x_start && s <= w_list.a[wk].x_end - if(wk != ovlp_cur_wid(*p)) {//xk is global, while ck is local - yk = z->w_list.a[wk].y_start; - xk = z->w_list.a[wk].x_start; - ck = 0; - } - - ///[ys, ye) but [z->w_list.a[wk].y_start, z->w_list.a[wk].y_end] - while(wk <= max_w && z->w_list.a[wk].y_start < ye) { - m = &(z->w_list.a[wk]); - ws = m->y_start; we = m->y_end+1; - os = MAX(ys, ws); oe = MIN(ye, we); - ovlp = ((oe>os)? (oe-os):0); - - if(ovlp) { - yl = m->y_end+1-m->y_start; - if((is_ualn_win((*m))) || (is_est_aln((*m)))) { - if(ovlp >= yl) { - if((*rxs) > m->x_start) (*rxs) = m->x_start; - if((*rxe) < (m->x_end+1)) (*rxe) = m->x_end+1; - } - //skip the whole window - yk = m->y_end+1; xk = m->x_end+1; ck = m->clen; - } else { - if(ovlp == yl) { - //skip the whole window - yk = m->y_end+1; xk = m->x_end+1; ck = m->clen; - if((*rxs) > m->x_start) (*rxs) = m->x_start; - if((*rxe) < (m->x_end+1)) (*rxe) = m->x_end+1; - } else { - set_bit_extz_t(ez, (*z), wk); - retrieve_cigar_xcoord(&ez, os, oe, &yk, &xk, &ck, rxs, rxe); - } - } - } - tot -= ovlp; - if(yk >= ye) break;//[min_w, max_w] && [ys, ye) - wk++; if(wk > max_w) break; - yk = z->w_list.a[wk].y_start; xk = z->w_list.a[wk].x_start; ck = 0;//reset - } - assert(!tot); - ovlp_cur_wid(*p) = wk; ovlp_cur_xoff(*p) = yk; ovlp_id(*p) = xk; ovlp_cur_coff(*p) = ck; - if((*rxe) > (*rxs)) return 1; - return 0; -} - -uint64_t extract_xcoordates(overlap_region *z, uint64_t *a, int64_t a_n, asg64_v *b) -{ - int64_t i, zwn, q[2], t[2], w[2], bn = b->n, a_i, a_z, as, ae, is, ie, os, oe, ovlp; - ul_ov_t m; int64_t qs, qe; - zwn = z->w_list.n; if(!zwn) return 0; - q[0] = q[1] = t[0] = t[1] = w[0] = w[1] = INT32_MIN; memset(&m, 0, sizeof(m)); - for (i = a_i = 0; i < zwn; i++) { - if((z->w_list.a[i].x_start==(q[1]+1)) && ((z->w_list.a[i].y_start==(t[1]+1)))) { - q[1] = z->w_list.a[i].x_end; - t[1] = z->w_list.a[i].y_end; - w[1] = i; - } else { - if(q[0] != INT32_MIN) { - ovlp_id(m) = z->w_list.a[w[0]].x_start; ///cur xpos - ovlp_min_wid(m) = w[0]; ///beg id of windows - ovlp_max_wid(m) = w[1]; ///end id of windows - ovlp_cur_wid(m) = w[0]; ///cur id of windows - ovlp_cur_xoff(m) = z->w_list.a[w[0]].y_start; ///cur ypos - ovlp_cur_coff(m) = 0; ///cur cigar off in cur window - - is = t[0]; ie = t[1]+1; ///[is, ie) - for (a_z = a_i; a_z >= 0; a_z--) { - as = a[a_z]>>32; ae = (uint32_t)a[a_z]; - if(ae <= is) break; - } - if(a_z < 0) a_z = 0; - for (; a_z < a_n; a_z++) { - as = a[a_z]>>32; ae = (uint32_t)a[a_z]; - os = MAX(is, as); oe = MIN(ie, ae); - ovlp = ((oe>os)? (oe-os):0); - if(ovlp) { - if(extract_xcoordates0(z, os, oe, &qs, &qe, &m)) { - kv_push(uint64_t, *b, (((uint64_t)qs)<<32)|((uint64_t)qe)); - } - } - if(as >= ie) break; - } - a_i = a_z; - } - q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; - t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end; - w[0] = i; w[1] = i; - } - } - - if(q[0] != INT32_MIN) { - ovlp_id(m) = z->w_list.a[w[0]].x_start; ///cur xpos - ovlp_min_wid(m) = w[0]; ///beg id of windows - ovlp_max_wid(m) = w[1]; ///end id of windows - ovlp_cur_wid(m) = w[0]; ///cur id of windows - ovlp_cur_xoff(m) = z->w_list.a[w[0]].y_start; ///cur ypos - ovlp_cur_coff(m) = 0; ///cur cigar off in cur window - - is = t[0]; ie = t[1]+1; - for (a_z = a_i; a_z >= 0; a_z--) { - as = a[a_z]>>32; ae = (uint32_t)a[a_z]; - if(ae <= is) break; - } - if(a_z < 0) a_z = 0; - for (; a_z < a_n; a_z++) { - as = a[a_z]>>32; ae = (uint32_t)a[a_z]; - os = MAX(is, as); oe = MIN(ie, ae); - ovlp = ((oe>os)? (oe-os):0); - if(ovlp) { - if(extract_xcoordates0(z, os, oe, &qs, &qe, &m)) { - kv_push(uint64_t, *b, (((uint64_t)qs)<<32)|((uint64_t)qe)); - } - } - if(as >= ie) break; - } - a_i = a_z; - } - return b->n - bn; -} - -int64_t cal_xerr(overlap_region *z, uint64_t *a, int64_t a_n) -{ - int64_t i, zwn, q[2], t[2], w[2], a_i, a_z, as, ae, is, ie, os, oe, ovlp, err = 0; ul_ov_t m; - zwn = z->w_list.n; if(!zwn) return 0; - q[0] = q[1] = t[0] = t[1] = w[0] = w[1] = INT32_MIN; memset(&m, 0, sizeof(m)); - for (i = a_i = 0; i < zwn; i++) { - // fprintf(stderr, "[M::%s]\tw::[%d,\t%d)\n", __func__, z->w_list.a[i].x_start, z->w_list.a[i].x_end+1); - if((z->w_list.a[i].x_start==(q[1]+1)) && ((z->w_list.a[i].y_start==(t[1]+1)))) { - q[1] = z->w_list.a[i].x_end; - t[1] = z->w_list.a[i].y_end; - w[1] = i; - } else { - if(q[0] != INT32_MIN) { - ovlp_id(m) = 0; ///ovlp id - ovlp_min_wid(m) = w[0]; ///beg id of windows - ovlp_max_wid(m) = w[1]; ///end id of windows - ovlp_cur_wid(m) = w[0]; ///cur id of windows - ovlp_cur_xoff(m) = z->w_list.a[w[0]].x_start; ///cur xpos - ovlp_cur_coff(m) = 0; ///cur cigar off in cur window - ovlp_bd(m) = 0; - - is = q[0]; ie = q[1]+1; ///[is, ie) - // fprintf(stderr, "+[M::%s]\tis::%ld\tie::%ld\n", __func__, is, ie); - for (a_z = a_i; a_z >= 0; a_z--) { - as = a[a_z]>>32; ae = (uint32_t)a[a_z]; - if(ae <= is) break; - } - if(a_z < 0) a_z = 0; - for (; a_z < a_n; a_z++) { - as = a[a_z]>>32; ae = (uint32_t)a[a_z]; - os = MAX(is, as); oe = MIN(ie, ae); - ovlp = ((oe>os)? (oe-os):0); - if(ovlp) { - // fprintf(stderr, "+[M::%s]\tos::%ld\toe::%ld\n", __func__, os, oe); - err = err + extract_sub_cigar_err(z, os, oe, &m); - } - if(as >= ie) break; - } - a_i = a_z; - } - q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; - t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end; - w[0] = i; w[1] = i; - } - } - - if(q[0] != INT32_MIN) { - ovlp_id(m) = 0; ///ovlp id - ovlp_min_wid(m) = w[0]; ///beg id of windows - ovlp_max_wid(m) = w[1]; ///end id of windows - ovlp_cur_wid(m) = w[0]; ///cur id of windows - ovlp_cur_xoff(m) = z->w_list.a[w[0]].x_start; ///cur xpos - ovlp_cur_coff(m) = 0; ///cur cigar off in cur window - ovlp_bd(m) = 0; - - is = q[0]; ie = q[1]+1; - // fprintf(stderr, "-[M::%s]\tis::%ld\tie::%ld\n", __func__, is, ie); - for (a_z = a_i; a_z >= 0; a_z--) { - as = a[a_z]>>32; ae = (uint32_t)a[a_z]; - if(ae <= is) break; - } - if(a_z < 0) a_z = 0; - for (; a_z < a_n; a_z++) { - as = a[a_z]>>32; ae = (uint32_t)a[a_z]; - os = MAX(is, as); oe = MIN(ie, ae); - ovlp = ((oe>os)? (oe-os):0); - if(ovlp) { - // if(os == 22758 && oe == 22764) { - // fprintf(stderr, "-[M::%s]\tos::%ld\toe::%ld\n", __func__, os, oe); - // } - err = err + extract_sub_cigar_err(z, os, oe, &m); - } - if(as >= ie) break; - } - a_i = a_z; - } - return err; -} - -void update_masks(asg64_v *in, overlap_region *qi, overlap_region *ti, int64_t bd) -{ - uint64_t in_n0 = in->n, in_n1, k, s, e; - int64_t zwn, i, q[2], t[2]; overlap_region *z; - for (k = 0; k < in_n0; k++) { - s = in->a[k]>>32; e = (uint32_t)in->a[k]; - // fprintf(stderr, "+[M::%s]\tk::%lu\tstr::[%lu,\t%lu)\n", __func__, k, s, e); - kv_push(uint64_t, *in, s<<1); - kv_push(uint64_t, *in, (((e-1)<<1)|1)); - } - in_n1 = in->n; - - uint64_t m, start, end; int64_t dp, old_dp, dp_mask, old_dp_mask; - radix_sort_bc64(in->a+in_n0, in->a+in_n1); - for (k = in_n0, dp = start = 0; k < in_n1; k++) { - old_dp = dp; - if (in->a[k]&1) --dp; - else ++dp; - - if (old_dp < 2 && dp >= 2) {///old_dp < dp, b.a[j] is qs - start = in->a[k]>>1; - } else if (old_dp >= 2 && dp < 2){ - end = in->a[k]>>1; - if(end >= start) { - kv_push(uint64_t, *in, ((start<<32)|end));///[start, end] - // fprintf(stderr, "-[M::%s]\tmsk::[%lu,\t%lu)\n", __func__, start, end+1); - } - } - } - - for (m = 0, k = in_n1; k < in->n; k++) in->a[m++] = in->a[k]; - in->n = in_n0 = m; ///in->a[0, in_n0) includes the masked regions - - z = qi; - zwn = z->w_list.n; - if(zwn > 0) { - q[0] = q[1] = t[0] = t[1] = INT32_MIN; - for (i = 0; i < zwn; i++) { - if((z->w_list.a[i].x_start==(q[1]+1)) && ((z->w_list.a[i].y_start==(t[1]+1)))) { - q[1] = z->w_list.a[i].x_end; - t[1] = z->w_list.a[i].y_end; - } else { - if(q[0] != INT32_MIN) { - q[0] += bd; q[1] -= bd; - if(q[1] >= q[0]) {///unmasked regions - m = ((uint64_t)q[0])<<1; m <<= 32; - kv_push(uint64_t, *in, m); - m = (((uint64_t)(q[1]))<<1)+1; m <<= 32; - kv_push(uint64_t, *in, m); - // fprintf(stderr, "[M::%s]\tqstr::[%ld,\t%ld)\n", __func__, q[0], q[1]+1); - } - } - q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; - t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end; - } - } - if(q[0] != INT32_MIN) { - q[0] += bd; q[1] -= bd; - if(q[1] >= q[0]) { - m = ((uint64_t)q[0])<<1; m <<= 32; - kv_push(uint64_t, *in, m); - m = (((uint64_t)(q[1]))<<1)+1; m <<= 32; - kv_push(uint64_t, *in, m); - // fprintf(stderr, "[M::%s]\tqstr::[%ld,\t%ld)\n", __func__, q[0], q[1]+1); - } - } - } - - z = ti; - zwn = z->w_list.n; - if(zwn > 0) { - q[0] = q[1] = t[0] = t[1] = INT32_MIN; - for (i = 0; i < zwn; i++) { - if((z->w_list.a[i].x_start==(q[1]+1)) && ((z->w_list.a[i].y_start==(t[1]+1)))) { - q[1] = z->w_list.a[i].x_end; - t[1] = z->w_list.a[i].y_end; - } else { - if(q[0] != INT32_MIN) { - q[0] += bd; q[1] -= bd; - if(q[1] >= q[0]) {///unmasked regions - m = ((uint64_t)q[0])<<1; m <<= 32; - kv_push(uint64_t, *in, m); - m = (((uint64_t)(q[1]))<<1)+1; m <<= 32; - kv_push(uint64_t, *in, m); - // fprintf(stderr, "[M::%s]\ttstr::[%ld,\t%ld)\n", __func__, q[0], q[1]+1); - } - } - q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; - t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end; - } - } - if(q[0] != INT32_MIN) { - q[0] += bd; q[1] -= bd; - if(q[1] >= q[0]) { - m = ((uint64_t)q[0])<<1; m <<= 32; - kv_push(uint64_t, *in, m); - m = (((uint64_t)(q[1]))<<1)+1; m <<= 32; - kv_push(uint64_t, *in, m); - // fprintf(stderr, "[M::%s]\ttstr::[%ld,\t%ld)\n", __func__, q[0], q[1]+1); - } - } - } - - - for (k = 0; k < in_n0; k++) { - start = in->a[k]>>32; end = (uint32_t)in->a[k]; - if(end >= start) { - q[0] = start; q[1] = end; - m = ((uint64_t)q[0])<<1; m <<= 32; m |= 1; - kv_push(uint64_t, *in, m); - m = (((uint64_t)(q[1]))<<1)+1; m <<= 32; m |= 1; - kv_push(uint64_t, *in, m); - } - } - in_n1 = in->n; - - radix_sort_bc64(in->a+in_n0, in->a+in_n1);///(uint32_t)in->a[]: 0-> original; 1-> mask - for (k = in_n0, dp = old_dp = dp_mask = old_dp_mask = 0, start = 0, end = -1; k < in_n1; ++k) {///[beg, end) but coordinates in idx is [, ] - ///if idx->a.a[] is qe - old_dp = dp; old_dp_mask = dp_mask; - if ((in->a[k]>>32)&1) { - --dp; end = (in->a[k]>>33)+1; if((uint32_t)in->a[k]) dp_mask--; - }else { - //meet a new overlap; the overlaps are pushed by the x_pos_s - ++dp; end = (in->a[k]>>33); if((uint32_t)in->a[k]) dp_mask++; - } - if((end > start) && (old_dp >= 2) && old_dp_mask <= 0) { - kv_push(uint64_t, *in, ((start<<32)|end));///[start, end) - if(qi->y_id == 4 && ti->y_id == 6) { - fprintf(stderr, "[M::%s]\tout::[%ld,\t%ld)\n", __func__, start, end); - } - } - start = end; - } - - for (m = 0, k = in_n1; k < in->n; k++) in->a[m++] = in->a[k]; - in->n = in_n0 = m; -} - -int64_t cal_paired_distance(ma_ug_t *ug, overlap_region *q, overlap_region *t, ul_ov_t *a, uint32_t a_n, -asg64_v *srt, asg64_v* buf1, idx_emask_t *mm, int64_t bd) -{ - uint64_t k, cn, *qa, *ta, *ca, m, qn, tn, rev, rev_n, tl, mt, qocc, tocc, s, e; - ul_ov_t ou; memset((&ou), 0, sizeof(ou)); int64_t eq, et; - srt->n = 0; kv_resize(uint64_t, *srt, (a_n<<1)); qa = srt->a; ta = qa + a_n; - - // if(q->y_id == 4 && t->y_id == 6) { - // fprintf(stderr, "\n\n\n[M::%s]\tutg%.6u%c\tutg%.6u%c\n", __func__, q->y_id+1, "lc"[ug->u.a[q->y_id].circ], - // t->y_id+1, "lc"[ug->u.a[t->y_id].circ]); - // } - - for (k = cn = 0; k < a_n; k++) { - // if(q->y_id == 4 && t->y_id == 6) { - // fprintf(stderr, "[M::%s]\tk::%lu\n", __func__, k); - // fprintf(stderr, "au\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\tfull::%u\tis_cal::%u\n", - // a[k].qn + 1, "lc"[ug->u.a[a[k].qn].circ], ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], - // a[k].tn + 1, "lc"[ug->u.a[a[k].tn].circ], ug->u.a[a[k].tn].len, a[k].ts, a[k].te, - // a[k].el, (a[k].sec!=((uint32_t)(0x3fffffff)))?1:0); - // } - if(!cal_no_bd_coor(&(a[k]), &ou, mm, bd)) continue; - qa[cn] = (((uint64_t)ou.qs)<<32)|((uint64_t)ou.qe); - ta[cn] = (((uint64_t)ou.ts)<<32)|((uint64_t)ou.te); - cn++; - // if(q->y_id == 4 && t->y_id == 6) { - // fprintf(stderr, "ou\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\n", - // ou.qn + 1, "lc"[ug->u.a[ou.qn].circ], ug->u.a[ou.qn].len, ou.qs, ou.qe, "+-"[ou.rev], - // ou.tn + 1, "lc"[ug->u.a[ou.tn].circ], ug->u.a[ou.tn].len, ou.ts, ou.te); - // } - } - radix_sort_bc64(qa, qa+cn); ca = qa; rev = q->y_pos_strand; tl = ug->g->seq[q->y_id].len; - for (k = m = 0; k < cn; k++) { - if(m <= 0 || (((uint32_t)ca[m-1])) < (ca[k]>>32)) { - ca[m++] = ca[k]; - } else if(((uint32_t)ca[m-1]) < ((uint32_t)ca[k])) { - ca[m-1] += ((uint32_t)ca[k])-((uint32_t)ca[m-1]); - } - } - if(rev) { - rev_n = m>>1; ///tl = (tl<<32) + tl; - for (k = 0; k < rev_n; k++) { - mt = ca[k]; ca[k] = ca[m-k-1]; ca[m-k-1] = mt; - - s = tl-((uint32_t)ca[k]); e = tl-(ca[k]>>32); - ca[k] = (s<<32)|e; - s = tl-((uint32_t)ca[m-k-1]); e = tl-(ca[m-k-1]>>32); - ca[m-k-1] = (s<<32)|e; - } - if(m&1) { - s = tl-((uint32_t)ca[k]); e = tl-(ca[k]>>32); - ca[k] = (s<<32)|e; - } - } - qn = m; - // if(q->y_id == 4 && t->y_id == 6) { - // fprintf(stderr, "[M::%s]\tqn::%lu\trev::%lu\n", __func__, qn, rev); - // for (k = 0; k < qn; k++) { - // s = qa[k]>>32; e = ((uint32_t)qa[k]); - // fprintf(stderr, "[M::%s]\tqstr::[%lu,\t%lu)\n", __func__, s, e); - // } - // } - - radix_sort_bc64(ta, ta+cn); ca = ta; rev = t->y_pos_strand; tl = ug->g->seq[t->y_id].len; - for (k = m = 0; k < cn; k++) { - if(m <= 0 || (((uint32_t)ca[m-1])) < (ca[k]>>32)) { - ca[m++] = ca[k]; - } else if(((uint32_t)ca[m-1]) < ((uint32_t)ca[k])) { - ca[m-1] += ((uint32_t)ca[k])-((uint32_t)ca[m-1]); - } - } - if(rev) { - rev_n = m>>1; ///tl = (tl<<32) + tl; - for (k = 0; k < rev_n; k++) { - mt = ca[k]; ca[k] = ca[m-k-1]; ca[m-k-1] = mt; - - s = tl-((uint32_t)ca[k]); e = tl-(ca[k]>>32); - ca[k] = (s<<32)|e; - s = tl-((uint32_t)ca[m-k-1]); e = tl-(ca[m-k-1]>>32); - ca[m-k-1] = (s<<32)|e; - } - if(m&1) { - s = tl-((uint32_t)ca[k]); e = tl-(ca[k]>>32); - ca[k] = (s<<32)|e; - } - } - tn = m; - // if(q->y_id == 4 && t->y_id == 6) { - // fprintf(stderr, "[M::%s]\ttn::%lu\trev::%lu\n", __func__, tn, rev); - // for (k = 0; k < tn; k++) { - // s = ta[k]>>32; e = ((uint32_t)ta[k]); - // fprintf(stderr, "[M::%s]\ttstr::[%lu,\t%lu)\n", __func__, s, e); - // } - // } - - buf1->n = 0; qocc = tocc = 0; srt->n = 0; - if(qn > 0 && tn > 0) { - qocc = extract_xcoordates(q, qa, qn, buf1); - tocc = extract_xcoordates(t, ta, tn, buf1); - // if(q->y_id == 4 && t->y_id == 6) { - // fprintf(stderr, "[M::%s]\tqocc::%lu\ttocc::%lu\n", __func__, qocc, tocc); - // } - if((!qocc) || (!tocc)) qocc = tocc = buf1->n = 0; - } - if(!(buf1->n)) return INT32_MIN; - update_masks(buf1, q, t, bd); - - eq = et = 0; - if(buf1->n) { - eq = cal_xerr(q, buf1->a, buf1->n); - et = cal_xerr(t, buf1->a, buf1->n); - } - // if(q->y_id == 4 && t->y_id == 6) { - // s = MAX(q->x_pos_s, t->x_pos_s); - // e = MIN(q->x_pos_e, t->x_pos_e) + 1; - // buf1->n = 0; - // kv_push(uint64_t, *buf1, ((s<<32)|e)); - // fprintf(stderr, "[M::%s]\teq::%ld\tet::%ld\tbuf1->n::%u\n", __func__, eq, et, (uint32_t)buf1->n); - // eq = cal_xerr(q, buf1->a, buf1->n); et = cal_xerr(t, buf1->a, buf1->n); - // fprintf(stderr, "[M::%s]\teq1::%ld\tet1::%ld\tbuf1->n::%u\ts::%lu\te::%lu\n", - // __func__, eq, et, (uint32_t)buf1->n, s, e); - // } - - return eq - et; - // return get_pe_diff(q, qa, qn, t, ta, tn, bd); -} - -void prt_masks(ma_ug_t *ug, ul_ov_t *a, uint64_t a_n) -{ - uint64_t k; - for (k = 0; k < a_n; k++) { - fprintf(stderr, "[M::%s]\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\tfull::%u\tis_cal::%u\n", - __func__, - a[k].qn + 1, "lc"[ug->u.a[a[k].qn].circ], ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], - a[k].tn + 1, "lc"[ug->u.a[a[k].tn].circ], ug->u.a[a[k].tn].len, a[k].ts, a[k].te, - a[k].el, (a[k].sec!=((uint32_t)(0x3fffffff)))?1:0); - } -} - -uint32_t gen_mask_ovlp0(ma_ug_t *ug, overlap_region *a, uint32_t qi, uint32_t ti, kv_ul_ov_t *ov_db, kv_ul_ov_t *buf, idx_emask_t *mm, double len_diff, int64_t rlen, uint64_t ovdb_idx, asg64_v *coor_srt, -asg64_v* buf1, int64_t bd, ul_ov_t *res) -{ - ul_ov_t *ref, r0, r1; uint32_t bn = buf->n, s, e; uint64_t is_exact = 0; - overlap_region *q = &(a[qi]), *t = &(a[ti]); int64_t dd = 0; - assert(q->y_id < t->y_id); - assert(ovdb_idx < ov_db->n);///quickly jump to the related qn-tn pair ov_db[] - cal_x_ul_ovlp(ug, q, t, &r0); - r1 = r0; - r1.qn = r0.tn; r1.tn = r0.qn; - r1.qs = r0.ts; r1.qe = r0.te; - r1.ts = r0.qs; r1.te = r0.qe; - - if((ov_db->a[ovdb_idx].qn==q->y_id) && (ov_db->a[ovdb_idx].tn==t->y_id)) { - ref = &(r0); s = ovdb_idx; e = q->overlapLen+q->x_pos_strand; - if((s!=((uint32_t)-1))&&(e > s)) push_consist_ul_ovlps(ug, ov_db, s, e, len_diff, ref, mm, buf, 0, &is_exact); - - if(!is_exact) { - ref = &(r1); s = t->overlapLen; e = t->overlapLen+t->x_pos_strand; - if((s!=((uint32_t)-1))&&(e > s)) push_consist_ul_ovlps(ug, ov_db, s, e, len_diff, ref, mm, buf, 1, &is_exact); - } - } else { - assert((ov_db->a[ovdb_idx].tn==q->y_id) && (ov_db->a[ovdb_idx].qn==t->y_id)); - ref = &(r1); s = ovdb_idx; e = t->overlapLen+t->x_pos_strand; - if((s!=((uint32_t)-1))&&(e > s)) push_consist_ul_ovlps(ug, ov_db, s, e, len_diff, ref, mm, buf, 1, &is_exact); - - if(!is_exact) { - ref = &(r0); s = q->overlapLen; e = q->overlapLen+q->x_pos_strand; - if((s!=((uint32_t)-1))&&(e > s)) push_consist_ul_ovlps(ug, ov_db, s, e, len_diff, ref, mm, buf, 0, &is_exact); - } - } - // prt_masks(ug, buf->a + bn, buf->n - bn); - ///p->qn/p->tn:: id within the ol->list - ///p->el:: if equally best - ///p->qs:: err(query)-err(target) - ///p->ts:: err(target)-err(query) - ref = &(r0); - res->qn = qi; res->tn = ti; - res->el = 1; res->qs = res->ts = 0; - if(!is_exact) { - assert(buf->n > bn); - dd = cal_paired_distance(ug, q, t, buf->a + bn, buf->n - bn, coor_srt, buf1, mm, bd); - if(dd != 0) { - res->el = 0; - if(dd > 0) {///q has more error than t - res->qs = dd; res->ts = 0; - } else { - res->qs = 0; res->ts = -dd; - } - } - } - buf->n = bn; - if(dd!=INT32_MIN) return 1; - return 0; -} - -uint64_t if_direct_mask(const ul_idx_t *uref, const ug_opt_t *uopt, ul_ov_t *p, ul_ov_t *q, uint64_t bw, double len_diff) -{ - ul_ov_t *li, *lj; uint64_t os, oe, ovlp; - if(p->qe > q->qe) li = p, lj = q; - else if(p->qe == q->qe && p->qs >= q->qs) li = p, lj = q; - else lj = p, li = q; - os = MAX(li->qs, lj->qs), oe = MIN(li->qe, lj->qe); - ovlp = ((oe > os)? (oe - os):0); - if(!ovlp) return 0;//no overlap - - if(lj->qs <= li->qs+G_CHAIN_INDEL) { - if(govlp_check(uref, uopt, bw, len_diff, li, lj)) return 1; - } else if((lj->qe+G_CHAIN_INDEL>=li->qe) && (lj->qs+G_CHAIN_INDEL>=li->qs)) { - if(govlp_check(uref, uopt, bw, len_diff, lj, li)) return 1; - } - return 0; -} - -uint64_t mask_ovlps(const ul_idx_t *uref, const ug_opt_t *uopt, ma_ug_t *ug, overlap_region_alloc* ol, mask_ul_ov_t *mk, kv_ul_ov_t *ov_db, asg64_v *coor_srt, asg64_v* buf1, idx_emask_t *mm, double len_diff, uint64_t rlen, int64_t bd) -{ - mk->srt.n = mk->idx.n = 0; - int64_t k, m, i, osrt_n, osrt_n1, on = ol->length; uint64_t wt, w[2], is_exact, sid, tot, tol, qi, ti; - overlap_region *z; ul_ov_t ou; kv_ul_ov_t *osrt = &(mk->srt); ul_ov_t p, q; - for (k = osrt->n = 0; k < on; k++) { - z = &(ol->list[k]); if(!(z->x_pos_strand)) continue;///x_pos_strand: how many masks - if(gen_aln_ul_ov_t(k, ug->g->seq[z->y_id].len, z, &ou)) { - kv_push(ul_ov_t, *osrt, ou); - } - } - if(!(osrt->n)) return 0; - - osrt_n = osrt->n; memset(&ou, 0, sizeof(ou)); - radix_sort_uov_srt_qs(osrt->a, osrt->a+osrt->n); ///sort by qs; for quick filtering between overlaps - for (k = tot = tol = 0; k < osrt_n; k++) { - tol += osrt->a[k].qe-osrt->a[k].qs; - convert_ul_ov_t(&p, &(ol->list[osrt->a[k].qn]), ug); p.qn = osrt->a[k].qn; - for (i = k+1; i < osrt_n && osrt->a[i].qs < osrt->a[k].qe; i++) { - ///for a pair of overlap, only need to calculate it in one side - if(ol->list[osrt->a[i].qn].y_id >= ol->list[osrt->a[k].qn].y_id) continue; - is_exact = 0; sid = (uint32_t)-1; - convert_ul_ov_t(&q, &(ol->list[osrt->a[i].qn]), ug); q.qn = osrt->a[i].qn; - if(if_direct_mask(uref, uopt, &p, &q, 16, len_diff)) is_exact = 1; - if((!is_exact) && (!check_mask_exist(ug, &(ol->list[osrt->a[i].qn]), &(ol->list[osrt->a[k].qn]), ov_db, mm, len_diff, &is_exact, &sid))) { - continue; - } - - if(is_exact) {///if two overlaps are exactly the same; no need to do anything - ou.qs = 0; ou.qe = sid; ou.ts = ou.te = 0; ou.el = 1; - } else { - w[0] = ol->list[osrt->a[k].qn].non_homopolymer_errors; - w[1] = ol->list[osrt->a[i].qn].non_homopolymer_errors; - wt = w[0] + w[1] + ((w[0]>=w[1])?(w[0]-w[1]):(w[1]-w[0])); - if(wt > (uint32_t)-1) wt = (uint32_t)-1; - //qs: weight; qe: idx with in ov_db; el: exact match? - ou.qs = wt; ou.qe = sid; ou.el = 0; - ou.ts = osrt->a[i].qe-osrt->a[i].qs; - ou.te = osrt->a[k].qe-osrt->a[k].qs; - } - ou.qn = osrt->a[i].qn; ou.tn = osrt->a[k].qn;///id of the ol->list, instead of real yid - tot += ou.ts + ou.te; - kv_push(ul_ov_t, *osrt, ou); - } - for (i = k-1; i >= 0; i--) { - ///for a pair of overlap, only need to calculate it in one side - if(ol->list[osrt->a[i].qn].y_id >= ol->list[osrt->a[k].qn].y_id) continue; - is_exact = 0; sid = (uint32_t)-1; - convert_ul_ov_t(&q, &(ol->list[osrt->a[i].qn]), ug); q.qn = osrt->a[i].qn; - if(if_direct_mask(uref, uopt, &p, &q, 16, len_diff)) is_exact = 1; - if((!is_exact) && (!check_mask_exist(ug, &(ol->list[osrt->a[i].qn]), &(ol->list[osrt->a[k].qn]), ov_db, mm, len_diff, &is_exact, &sid))) { - continue; - } - - if(is_exact) { - ou.qs = 0; ou.qe = sid; ou.ts = ou.te = 0; ou.el = 1; - } else { - w[0] = ol->list[osrt->a[k].qn].non_homopolymer_errors; - w[1] = ol->list[osrt->a[i].qn].non_homopolymer_errors; - wt = w[0] + w[1] + ((w[0]>=w[1])?(w[0]-w[1]):(w[1]-w[0])); - if(wt > (uint32_t)-1) wt = (uint32_t)-1; - ou.qs = wt; ou.qe = sid; ou.el = 0; - ou.ts = osrt->a[i].qe-osrt->a[i].qs; - ou.te = osrt->a[k].qe-osrt->a[k].qs; - } - ou.qn = osrt->a[i].qn; ou.tn = osrt->a[k].qn;///id of the ol->list, instead of real yid - tot += ou.ts + ou.te; - kv_push(ul_ov_t, *osrt, ou); - } - } - - // fprintf(stderr, "0[M::%s]\tosrt_n::%u\tosrt->n::%u\n", __func__, (uint32_t)osrt_n, (uint32_t)osrt->n); - - if((tot > (rlen*256)) && (tot > (tol*32))) { - tot = MAX((rlen*256), (tol*32)); osrt_n1 = osrt->n; - radix_sort_uov_srt_qs(osrt->a+osrt_n, osrt->a+osrt->n); ///sort by weight (qs) - for (k = osrt_n, wt = 0; k < osrt_n1 && wt <= tot; k++) { - if(osrt->a[k].el) continue;///exact match, no additional work - wt += (uint64_t)osrt->a[k].ts + (uint64_t)osrt->a[k].te; - } - osrt->n = k; - } - - memset(&ou, 0, sizeof(ou)); osrt_n1 = osrt->n; - ///note: osrt will be updated here, so do not use the address within osrt - for (k = osrt_n, m = 0; k < osrt_n1; k++) { - qi = osrt->a[k].qn; ti = osrt->a[k].tn; ///represent a pair of read ol->list[qi] <-> ol->list[ti] - sid = osrt->a[k].qe; wt = 1; - ///p->qn/p->tn:: id within the ol->list - ///p->el:: if equally best - ///p->qs:: err(query)-err(target) - ///p->ts:: err(target)-err(query) - if(osrt->a[k].el) {///exact match; no need base-check - ou.qn = qi; ou.tn = ti; ou.el = 1; ou.qs = ou.ts = 0; - } else {///do base-check - wt = gen_mask_ovlp0(ug, ol->list, qi, ti, ov_db, osrt, mm, len_diff, rlen, sid, coor_srt, buf1, bd, &(ou)); - } - if(wt) { - osrt->a[m++] = ou; - // fprintf(stderr, "[M::%s]\tutg%.6u%c\tqerr::%u\t\tutg%.6u%c\tterr::%u\tel::%u\n", - // __func__, ol->list[ou.qn].y_id+1, "lc"[ug->u.a[ol->list[ou.qn].y_id].circ], ou.qs, - // ol->list[ou.tn].y_id+1, "lc"[ug->u.a[ol->list[ou.tn].y_id].circ], ou.ts, ou.el); - } - } - osrt->n = m; - if(!(osrt->n)) return 0; - - ///double - ///p->qn/p->tn:: id within the ol->list - ///p->el:: if equally best - ///p->qs:: err(query)-err(target) - ///p->ts:: err(target)-err(query) - kv_resize(ul_ov_t, *osrt, (osrt->n<<1)); - memcpy(osrt->a+osrt->n, osrt->a, (sizeof((*(osrt->a)))*osrt->n)); - osrt_n = osrt->n; osrt->n <<= 1; osrt_n1 = osrt->n; - for (k = osrt_n; k < osrt_n1; k++) { - m = osrt->a[k].qn; osrt->a[k].qn = osrt->a[k].tn; osrt->a[k].tn = m; - m = osrt->a[k].qs; osrt->a[k].qs = osrt->a[k].ts; osrt->a[k].ts = m; - } - - ///osrt = &(mk->srt); - radix_sort_ul_ov_srt_qn1(osrt->a, osrt->a+osrt->n); - kv_resize(uint64_t, mk->idx, ol->length); mk->idx.n = ol->length; - memset(mk->idx.a, 0, sizeof((*(mk->idx.a)))*ol->length); - for (k = 1, i = 0; k <= osrt_n1; k++) { - if(k == osrt_n1 || osrt->a[i].qn != osrt->a[k].qn) { - if(k - i > 1) radix_sort_ul_ov_srt_tn1(osrt->a+i, osrt->a+k); - mk->idx.a[osrt->a[i].qn] = (((uint64_t)i)<<32)|((uint64_t)k); - i = k; - } - } - - return 1; -} - -void refine_rphase_back(overlap_region *za, uint64_t zid, ul_ov_t *a, uint64_t a_n, asg64_v *buf) -{ - uint64_t k, bn, qs, qe, err, zs, ze, zerr, m, zwn; overlap_region *z; window_list *p; - kv_resize(uint64_t, *buf, a_n); - for (k = buf->n = 0; k < a_n; k++) { - if(a[k].qs > 0) {//za[zid] has higher error rate - // buf->a[buf->n++] = (((uint64_t)za[a[k].tn].x_pos_s)<<32)|((uint64_t)a[k].tn); - buf->a[buf->n++] = (((uint64_t)za[a[k].tn].x_pos_s)<<32)|(k); - } - } - radix_sort_bc64(buf->a, buf->a+buf->n); - - bn = buf->n; - for (k = 0; k < bn; k++) { - qs = qe = err = 0; - if(buf->n > bn) { - qs = buf->a[buf->n-2]>>32; - qe = ((uint32_t)buf->a[buf->n-2]); - err = buf->a[buf->n-1]; - } - zs = MIN(za[a[((uint64_t)buf->a[k])].tn].x_pos_s, za[zid].x_pos_s); - ze = MAX(za[a[((uint64_t)buf->a[k])].tn].x_pos_e, za[zid].x_pos_e) + 1; - if(ze <= zs) continue; - zerr = a[((uint64_t)buf->a[k])].qs; - if(qe <= zs) { - kv_push(uint64_t, *buf, ((zs<<32)|ze)); - kv_push(uint64_t, *buf, zerr); - } else { - if(ze > qe) qe = ze; - if(zerr > err) err = zerr; - buf->a[buf->n-2] = ((qs<<32)|(qe)); - buf->a[buf->n-1] = err; - } - } - - for (k = bn, m = 0; k < buf->n; k++) buf->a[m++] = buf->a[k]; - buf->n = m; - if(!(buf->n)) return; - - z = &(za[zid]); - for (k = 0; k < z->align_length; k++) { - p = &(z->w_list.a[z->w_list.n+k]); - if(p->clen <= 0) continue; - zs = p->x_start; ze = p->x_end; ///note here is [p->x_start, p->x_end) - zerr = p->clen; - - kv_push(uint64_t, *buf, ((zs<<32)|ze)); - kv_push(uint64_t, *buf, zerr); - } - - bn = buf->n; kv_resize(uint64_t, *buf, (bn + (bn>>1))); - for (k = 0; k < bn; k+=2) { - zs = buf->a[k]>>32; zs <<= 32; zs |= k; - kv_push(uint64_t, *buf, zs); - } - - uint64_t *wa = buf->a + bn, wan = buf->n - bn; - radix_sort_bc64(wa, wa + wan); - z->x_pos_strand = (uint32_t)-1; - z->w_list.n = 0; - - for (k = 0; k < wan; k++) { - qs = qe = z->x_pos_s; err = 0; - if(z->w_list.n) { - qs = z->w_list.a[z->w_list.n-1].x_start; - qe = z->w_list.a[z->w_list.n-1].x_end; - err = z->w_list.a[z->w_list.n-1].clen; - } - - zs = buf->a[((uint64_t)wa[k])]>>32; - ze = (uint32_t)(buf->a[((uint64_t)wa[k])]); - zerr = buf->a[((uint64_t)wa[k])+1]; - - if(qe <= zs) { - if(qe < zs) { - kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); - p->clen = 0; p->x_start = qe; p->x_end = zs; - } - kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); - p->clen = zerr; p->x_start = zs; p->x_end = ze; - } else { - if(ze > qe) qe = ze; - if(zerr > err) err = zerr; - p = &(z->w_list.a[z->w_list.n-1]); - p->clen = err; - p->x_start = qs; - p->x_end = qe; - } - } - - - qs = qe = z->x_pos_s; zs = z->x_pos_e + 1; - if(z->w_list.n) { - qs = z->w_list.a[z->w_list.n-1].x_start; - qe = z->w_list.a[z->w_list.n-1].x_end; - } - if(qe < zs) { - kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); - p->clen = 0; p->x_start = qe; p->x_end = zs; - } - - z->x_pos_strand = (uint32_t)-1; - z->overlapLen = z->x_pos_e+1-z->x_pos_s; - z->non_homopolymer_errors = 0; zwn = 0; - for (k = 0; k < z->w_list.n; k++) { - if(z->w_list.a[k].clen > 0) { - z->non_homopolymer_errors += z->w_list.a[k].clen; - zwn += z->w_list.a[k].x_end-z->w_list.a[k].x_start; - } - } - assert(zwn <= z->overlapLen);///zwn is the length with secondary-best alignment - z->align_length = z->overlapLen - zwn; -} - -inline void push_rphase(overlap_region *z, uint64_t zs, uint64_t ze, uint64_t zerr, uint64_t is_pri) -{ - uint64_t pe, p_pri; window_list *p; - pe = z->x_pos_s; p_pri = 0; - if(z->w_list.n) { - pe = z->w_list.a[z->w_list.n-1].x_end; - p_pri = z->w_list.a[z->w_list.n-1].cidx; - } - - // fprintf(stderr, "+[M::%s] zs::%lu, ze::%lu, zerr::%lu, pe::%lu, is_pri::%lu, p_pri::%lu, wn::%u\n", - // __func__, zs, ze, zerr, pe, is_pri, p_pri, (uint32_t)z->w_list.n); - - if(pe <= zs) {///not overlap with [zs, ze) - if(pe < zs) { - kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); - p->clen = 0; p->x_start = pe; p->x_end = zs; p->cidx = 0; - } - kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); - p->clen = zerr; p->x_start = zs; p->x_end = ze; p->cidx = is_pri; - } else { - if(pe <= ze) {///prefix-suffix overlap - if(is_pri) { - if(p_pri) { - kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); - p->clen = zerr; p->cidx = is_pri; - p->x_start = zs; p->x_end = ze; - z->w_list.a[z->w_list.n-2].x_end = zs;///trim the previous primary window - } else { - p = &(z->w_list.a[z->w_list.n-1]); - p->clen = zerr; p->cidx = is_pri; - p->x_end = ze; - } - } else {///if current is not primary - p = &(z->w_list.a[z->w_list.n-1]); - p->x_end = ze; - } - } else {//pe > ze; [zs, ze) is contained within [ps, pe) - if(is_pri) {///is_pri == 0, no need to do anything - if(!p_pri) { - p = &(z->w_list.a[z->w_list.n-1]); - p->clen = zerr; p->cidx = is_pri; - } else { - kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); - p->clen = zerr; p->cidx = is_pri; - p->x_start = zs; p->x_end = z->w_list.a[z->w_list.n-2].x_end; - z->w_list.a[z->w_list.n-2].x_end = zs;///trim the previous primary window - } - } - } - } - // fprintf(stderr, "-[M::%s] zs::%lu, ze::%lu, zerr::%lu, pe::%lu, is_pri::%lu, p_pri::%lu, wn::%u, x::[%d, %d), sec::%u\n", - // __func__, zs, ze, zerr, pe, is_pri, p_pri, (uint32_t)z->w_list.n, - // z->w_list.a[z->w_list.n-1].x_start, z->w_list.a[z->w_list.n-1].x_end, z->w_list.a[z->w_list.n-1].clen); -} - -void refine_rphase(ma_ug_t *ug, int64_t rlen, overlap_region *za, uint64_t zan, uint64_t zid, ul_ov_t *a, uint64_t a_n, asg64_v *buf) -{ - // fprintf(stderr, "\n[M::%s] zid::%lu, x::[%u, %u), zan::%lu, a_n::%lu\n", - // __func__, zid, za[zid].x_pos_s, za[zid].x_pos_e+1, zan, a_n); - uint64_t k, bn, qs, qe, err, zs, ze, zerr, m, zwn; overlap_region *z; window_list *p; - kv_resize(uint64_t, *buf, a_n); - for (k = buf->n = 0; k < a_n; k++) { - if(a[k].qs > 0) {//za[zid] has higher error rate - // buf->a[buf->n++] = (((uint64_t)za[a[k].tn].x_pos_s)<<32)|((uint64_t)a[k].tn); - // fprintf(stderr, "+[M::%s] k::%lu, err::%u, x::[%u, %u)\n", __func__, k, a[k].qs, za[a[k].tn].x_pos_s, za[a[k].tn].x_pos_e+1); - buf->a[buf->n++] = (((uint64_t)za[a[k].tn].x_pos_s)<<32)|(k); - } - } - radix_sort_bc64(buf->a, buf->a+buf->n); - - bn = buf->n; - for (k = 0; k < bn; k++) { - qs = qe = err = 0; - if(buf->n > bn) { - qs = buf->a[buf->n-2]>>32; - qe = ((uint32_t)buf->a[buf->n-2]); - err = buf->a[buf->n-1]; - } - zs = MAX(za[a[((uint32_t)buf->a[k])].tn].x_pos_s, za[zid].x_pos_s); - ze = MIN(za[a[((uint32_t)buf->a[k])].tn].x_pos_e, za[zid].x_pos_e) + 1; - if(ze <= zs) continue; - zerr = a[((uint32_t)buf->a[k])].qs; - // fprintf(stderr, "-[M::%s] k::%lu, z::[%u, %u), zerr::%lu\n", __func__, k, zs, ze, zerr); - if(qe <= zs) { - kv_push(uint64_t, *buf, ((zs<<32)|ze)); - kv_push(uint64_t, *buf, zerr); - } else { - if(ze > qe) qe = ze; - if(zerr > err) err = zerr; - buf->a[buf->n-2] = ((qs<<32)|(qe)); - buf->a[buf->n-1] = err; - } - } - - for (k = bn, m = 0; k < buf->n; k++) buf->a[m++] = buf->a[k]; - buf->n = m; - if(!(buf->n)) return; - - z = &(za[zid]); - for (k = 0; k < z->align_length; k++) { - p = &(z->w_list.a[z->w_list.n+k]); - if(p->clen <= 0) continue; - zs = p->x_start; ze = p->x_end; ///note here is [p->x_start, p->x_end) - zerr = p->clen; - // fprintf(stderr, ">[M::%s] k::%lu, z::[%u, %u), zerr::%lu\n", __func__, k, zs, ze, zerr); - kv_push(uint64_t, *buf, ((zs<<32)|ze)); - kv_push(uint64_t, *buf, zerr); - } - - uint64_t *ref, ref_n, ref_i, *qry, qry_n, qry_i; - ref = buf->a; ref_n = m; - qry = ref + ref_n; qry_n = buf->n - ref_n; - ref_i = qry_i = z->w_list.n = 0; - // fprintf(stderr, "[M::%s] ref_n::%lu, qry_n::%lu\n", __func__, ref_n, qry_n); - ///all ref and qry are regions with at least one error - while (ref_i < ref_n && qry_i < qry_n) { - if((ref[ref_i]>>32) < (qry[qry_i]>>32)) { - push_rphase(z, ref[ref_i]>>32, (uint32_t)ref[ref_i], ref[ref_i+1], 0); - ref_i += 2; - } else if((qry[qry_i]>>32) < (ref[ref_i]>>32)) { - push_rphase(z, qry[qry_i]>>32, (uint32_t)qry[qry_i], qry[qry_i+1], 1); - qry_i += 2; - } else { - push_rphase(z, qry[qry_i]>>32, (uint32_t)qry[qry_i], qry[qry_i+1], 1); - qry_i += 2; - } - } - - while(qry_i < qry_n) { - push_rphase(z, qry[qry_i]>>32, (uint32_t)qry[qry_i], qry[qry_i+1], 1); - qry_i += 2; - } - - while(ref_i < ref_n) { - push_rphase(z, ref[ref_i]>>32, (uint32_t)ref[ref_i], ref[ref_i+1], 0); - ref_i += 2; - } - - ///push remaining bases as the last window - qs = qe = z->x_pos_s; zs = z->x_pos_e + 1; - if(z->w_list.n) { - qs = z->w_list.a[z->w_list.n-1].x_start; - qe = z->w_list.a[z->w_list.n-1].x_end; - } - if(qe < zs) { - kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); - p->clen = 0; p->x_start = qe; p->x_end = zs; - } - - - z->x_pos_strand = (uint32_t)-1; - z->overlapLen = z->x_pos_e+1-z->x_pos_s; - z->non_homopolymer_errors = 0; zwn = 0; - for (k = m = 0; k < z->w_list.n; k++) { - if(z->w_list.a[k].clen > 0) { - z->non_homopolymer_errors += z->w_list.a[k].clen; - zwn += z->w_list.a[k].x_end-z->w_list.a[k].x_start; - } - z->w_list.a[k].cidx = 0; m += z->w_list.a[k].x_end-z->w_list.a[k].x_start; - } - // fprintf(stderr, "[M::%s] m:%lu, z->overlapLen:%lu\n", __func__, m, z->overlapLen); - assert(m == z->overlapLen); - // assert(zwn <= z->overlapLen);///zwn is the length with secondary-best alignment - z->align_length = z->overlapLen - zwn; - - // fprintf(stderr, ">[M::%s]\tutg%.6u%c\txl::%ld\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\tsec_len::%lu\n", - // __func__, z->y_id + 1, "lc"[ug->u.a[z->y_id].circ], - // rlen, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - // ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors, zwn); -} - -void rphase_hl(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, asg64_v* buf1, int64_t ulid, int64_t bd, -int64_t rlen, mask_ul_ov_t *mk, idx_emask_t *mm, double len_diff) -{ - uint64_t on0 = ol->length, k, i, l, m0, m1, sec, zwn, m, mmov; - overlap_region *z, h; ma_ug_t *ug = uref->ug; - - for (k = i = 0; k < ol->length; k++) { - z = &(ol->list[k]); - z->align_length = 0; - z->non_homopolymer_errors = 0; - z->overlapLen = (uint32_t)-1; - z->x_pos_strand = 0; - // fprintf(stderr, "i[M::%s]\tutg%.6u%c\txl::%ld\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\n", - // __func__, z->y_id + 1, "lc"[ug->u.a[z->y_id].circ], - // rlen, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - // ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors); - if(!(z->w_list.n)) continue;///no base-level; cis - if(k != i) { - h = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = h; - } - i++; - } - ol->length = i; ///[ol->length, on0) keeps cis overlaps without the base-level alignment - - rphase_rr(ol, uref, uopt, c_idx, idx, buf, ulid, bd, NULL); - ///could use idx && buf here - for (k = idx->n = buf->n = 0; k < ol->length; k++) { - z = &(ol->list[k]); - ///sort overlaps by sec error - for (i = sec = 0; i < z->align_length; i++) { - sec += z->w_list.a[z->w_list.n+i].clen; - } - z->non_homopolymer_errors = sec; sec = sec - (sec&3);///normalize by 4 - kv_push(uint64_t, *buf, (((uint64_t)sec)<<32)|((uint64_t)k)); - - ///sort overlaps by yid for filtering - kv_push(uint64_t, *idx, (((uint64_t)z->y_id)<<32)|((uint64_t)k)); - - // fprintf(stderr, "+[M::%s]\tutg%.6u%c\txl::%ld\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\tn_sec::%lu\n", - // __func__, z->y_id + 1, "lc"[ug->u.a[z->y_id].circ], - // rlen, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - // ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors, sec); - } - radix_sort_bc64(idx->a, idx->a+idx->n); ///for filtering - - radix_sort_bc64(buf->a, buf->a+buf->n);///sort by error; smaller error first - for (l = 0, k = 1; k <= buf->n; k++) { - if(k == buf->n || (buf->a[l]>>32) == (buf->a[k]>>32)) {///with equal number of normalized errors - if(((k - l) > 1) && (k < buf->n)) { - for (i = l; i < k; i++) { - // fprintf(stderr, "[M::%s]\tl::%lu\tk::%lu\tbuf->a[i]>>32::%lu\n", __func__, l, k, buf->a[i]>>32); - z = &(ol->list[(uint32_t)buf->a[i]]); - m0 = z->x_pos_e+1-z->x_pos_s; - m1 = z->y_pos_e+1-z->y_pos_s; - sec = MIN(m0, m1); sec = ((uint32_t)-1)-((uint32_t)sec); - buf->a[i] = (((uint64_t)sec)<<32)|((uint32_t)buf->a[i]); - } - radix_sort_bc64(buf->a+l, buf->a+k);///sort by lenght; longer first - } - l = k; - } - } - - mk->idx.n = mk->srt.n = 0; c_idx->n = 0; - mmov = 1000000; if(mmov > (ol->length*32)) mmov = (ol->length*32); - for (k = 0; k < buf->n && c_idx->n <= mmov; k++) {///need to add overlap that directly connected in the graph - z = &(ol->list[(uint32_t)buf->a[k]]); z->overlapLen = c_idx->n; - - // fprintf(stderr, "\n-[M::%s]\tutg%.6u%c\txl::%ld\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\n", - // __func__, z->y_id + 1, "lc"[ug->u.a[z->y_id].circ], - // rlen, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - // ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors); - - m0 = push_emask_flt(&(mm->a[z->y_id]), idx->a, idx->n, z->y_id, c_idx); - - - // fprintf(stderr, "-[M::%s]\tm0::%lu\n", __func__, m0); - // prt_masks(ug, c_idx->a+c_idx->n-m0, m0); - - - m1 = gen_src_shared_interval_simple(z->y_id, ug, idx->a, idx->n, c_idx); - - - // fprintf(stderr, "-[M::%s]\tm1::%lu\n", __func__, m1); - // prt_masks(ug, c_idx->a+c_idx->n-m1, m1); - - - dedup_src_shared1(ug, c_idx, m0, m1, mm); - z->x_pos_strand = c_idx->n - z->overlapLen; - if(!(z->x_pos_strand)) z->overlapLen = (uint32_t)-1; - - // fprintf(stderr, "-[M::%s]\tutg%.6u%c\txl::%ld\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\tm0::%lu\tm1::%lu\tcan_n::%u\n", - // __func__, z->y_id + 1, "lc"[ug->u.a[z->y_id].circ], - // rlen, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - // ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors, m0, m1, z->x_pos_strand); - // fprintf(stderr, "-[M::%s]\tcan_n::%u\n", __func__, z->x_pos_strand); - // if(z->x_pos_strand) prt_masks(ug, c_idx->a+z->overlapLen, z->x_pos_strand); - } - - ///if no mask overlaps, some overlaps may be still masked using the overlap within the graph - if(((c_idx->n) || (ol->length > 1)) && mask_ovlps(uref, uopt, ug, ol, mk, c_idx, idx, buf1, mm, len_diff, rlen, bd)) { - // for (k = 0; k < mk->srt.n; k++) { - // fprintf(stderr, "*[M::%s]\tutg%.6u%c\txl::%u\tqerr::%u\t%c\tutg%.6u%c\tyl::%u\tterr::%u\tel::%u\n", - // __func__, - // ol->list[mk->srt.a[k].qn].y_id + 1, "lc"[ug->u.a[ol->list[mk->srt.a[k].qn].y_id].circ], - // ug->u.a[ol->list[mk->srt.a[k].qn].y_id].len, mk->srt.a[k].qs, - // "+-"[mk->srt.a[k].rev], - // ol->list[mk->srt.a[k].tn].y_id + 1, "lc"[ug->u.a[ol->list[mk->srt.a[k].tn].y_id].circ], - // ug->u.a[ol->list[mk->srt.a[k].tn].y_id].len, mk->srt.a[k].ts, - // mk->srt.a[k].el); - // } - - - - rphase_rr(ol, uref, uopt, c_idx, idx, buf, ulid, bd, mk); - for (k = 0; k < ol->length; k++) { - if(((uint32_t)mk->idx.a[k]) > (mk->idx.a[k]>>32)) {///it has masks - refine_rphase(ug, rlen, ol->list, ol->length, k, mk->srt.a+(mk->idx.a[k]>>32), ((uint32_t)mk->idx.a[k])-(mk->idx.a[k]>>32), idx); - } - } - } - // assert(on0 <= ol->length); - ol->length = on0; - - for (k = 0; k < ol->length; k++) { - z = &(ol->list[k]); - if(z->x_pos_strand == (uint32_t)-1) { - // fprintf(stderr, ">[M::%s]\tutg%.6u%c\txl::%ld\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\n", - // __func__, z->y_id + 1, "lc"[ug->u.a[z->y_id].circ], - // rlen, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - // ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors); - - z->x_pos_strand = 0; continue; - } - z->overlapLen = z->x_pos_e+1-z->x_pos_s; - z->non_homopolymer_errors = 0; zwn = 0; - for (i = m = 0; i < z->align_length; i++) { - z->w_list.a[m] = z->w_list.a[z->w_list.n+i]; - if(z->w_list.a[m].clen > 0) { - z->non_homopolymer_errors += z->w_list.a[m].clen; - zwn += z->w_list.a[m].x_end-z->w_list.a[m].x_start; - } - m++; - } - z->w_list.n = m; z->x_pos_strand = 0; - assert(zwn <= z->overlapLen);///zwn is the length with secondary-best alignment - z->align_length = z->overlapLen - zwn; - - // fprintf(stderr, ">[M::%s]\tutg%.6u%c\txl::%ld\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\tsec_len::%lu\n", - // __func__, z->y_id + 1, "lc"[ug->u.a[z->y_id].circ], - // rlen, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - // ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors, zwn); - } -} - -uint64_t rphase_detect0(overlap_region_alloc* ol, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, asg64_v* suf) -{ - uint64_t srt_n = idx->n, i, k, h, qs, qe, ts, te, rr = 0, ovlp; overlap_region *z, *p; - int64_t dp, old_dp, beg, end; - for (i = k = 0, dp = old_dp = 0, beg = 0, end = -1; i < srt_n; ++i) {///[beg, end) but coordinates in idx is [, ] - ///if idx->a.a[] is qe - old_dp = dp; - if ((idx->a[i]>>32)&1) { - --dp; end = (idx->a[i]>>33)+1; - }else { - //meet a new overlap; the overlaps are pushed by the x_pos_s - ++dp; end = (idx->a[i]>>33); - kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); - } - // fprintf(stderr, "\n[M::%s::] beg::%ld, end::%ld, old_dp::%ld\n", __func__, beg, end, old_dp); - if((end > beg) && (old_dp >= 2)) { - // fprintf(stderr, "\n[M::%s::] beg::%ld, end::%ld, old_dp::%ld\n", __func__, beg, end, old_dp); - // kv_resize(uint64_t, *buf, ((uint32_t)old_dp)<<1); - // idx->n = srt_n + gen_region_phase(ol->list, idx->a+srt_n, idx->n-srt_n, beg, end, old_dp, c_idx->a, buf, buf1); - idx->n = srt_n + gen_region_phase_robust(ol->list, idx->a+srt_n, idx->n-srt_n, beg, end, old_dp, c_idx->a, buf); - } - beg = end; - } - idx->n = srt_n; - - suf->n = 0; kv_resize(uint64_t, *suf, (ol->length<<1)); - uint64_t *sep = suf->a, *sid = suf->a + ol->length, sid_n; - for (k = h = sid_n = 0; k < ol->length; k++) { - z = &(ol->list[k]); - z->overlapLen = (uint32_t)-1; z->non_homopolymer_errors = 0; - for (i = 0; i < z->align_length; i++) { - z->non_homopolymer_errors += z->w_list.a[z->w_list.n+i].clen; - } - for (; h < c_idx->n && ovlp_id(c_idx->a[h]) < k; h++); - if(h < c_idx->n && ovlp_id(c_idx->a[h]) == k) { - qs = z->w_list.a[ovlp_min_wid(c_idx->a[h])].x_start; - qe = z->w_list.a[ovlp_max_wid(c_idx->a[h])].x_end+1; - for (; h < c_idx->n && ovlp_id(c_idx->a[h]) == k; h++) { - qe = z->w_list.a[ovlp_max_wid(c_idx->a[h])].x_end+1; - } - sid[sid_n] = ((qs<<32)|sid_n); - sep[sid_n] = ((k<<32)|qe); - sid_n++; - // kv_push(uint64_t, *suf, ((qs<<32)|h)); - } - } - radix_sort_bc64(sid, sid+sid_n); - for (k = 0; k < sid_n; k++) { - qs = sid[k]>>32; qe = ((uint32_t)sep[(uint32_t)sid[k]]); - z = &(ol->list[sep[(uint32_t)sid[k]]>>32]); - if(z->non_homopolymer_errors == 0) continue; - for (i = rr = 0; i < sid_n; i++) { - ts = sid[i]>>32; te = ((uint32_t)sep[(uint32_t)sid[i]]); - p = &(ol->list[sep[(uint32_t)sid[i]]>>32]); - if(ts >= qe) break; - if(te <= qs) continue; - ovlp = ((MIN(qe, te) > MAX(qs, ts))? (MIN(qe, te) - MAX(qs, ts)):0); - if(ovlp < 512) continue; - if(z->non_homopolymer_errors > p->non_homopolymer_errors + rphase_thres) continue; - rr = 1; break; - } - if(rr) z->overlapLen = 1; - } - return rr; -} - -void reacal_phase(overlap_region_alloc* ol, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, asg64_v* suf) -{ - uint64_t srt_n = idx->n, i, k, h, qs, qe, ts, te, rr = 0; overlap_region *z, *p; - int64_t dp, old_dp, beg, end; - for (i = k = 0, dp = old_dp = 0, beg = 0, end = -1; i < srt_n; ++i) {///[beg, end) but coordinates in idx is [, ] - ///if idx->a.a[] is qe - old_dp = dp; - if ((idx->a[i]>>32)&1) { - --dp; end = (idx->a[i]>>33)+1; - }else { - //meet a new overlap; the overlaps are pushed by the x_pos_s - ++dp; end = (idx->a[i]>>33); - kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); - } - // fprintf(stderr, "\n[M::%s::] beg::%ld, end::%ld, old_dp::%ld\n", __func__, beg, end, old_dp); - if((end > beg) && (old_dp >= 2)) { - // fprintf(stderr, "\n[M::%s::] beg::%ld, end::%ld, old_dp::%ld\n", __func__, beg, end, old_dp); - // kv_resize(uint64_t, *buf, ((uint32_t)old_dp)<<1); - // idx->n = srt_n + gen_region_phase(ol->list, idx->a+srt_n, idx->n-srt_n, beg, end, old_dp, c_idx->a, buf, buf1); - idx->n = srt_n + gen_region_phase_robust(ol->list, idx->a+srt_n, idx->n-srt_n, beg, end, old_dp, c_idx->a, buf); - } - beg = end; - } - idx->n = srt_n; - - suf->n = 0; kv_resize(uint64_t, *suf, (ol->length<<1)); - uint64_t *sep = suf->a, *sid = suf->a + ol->length, sid_n; - for (k = h = sid_n = 0; k < ol->length; k++) { - z = &(ol->list[k]); - z->overlapLen = (uint32_t)-1; z->non_homopolymer_errors = 0; - for (i = 0; i < z->align_length; i++) { - z->non_homopolymer_errors += z->w_list.a[z->w_list.n+i].clen; - } - for (; h < c_idx->n && ovlp_id(c_idx->a[h]) < k; h++); - if(h < c_idx->n && ovlp_id(c_idx->a[h]) == k) { - qs = z->w_list.a[ovlp_min_wid(c_idx->a[h])].x_start; - qe = z->w_list.a[ovlp_max_wid(c_idx->a[h])].x_end+1; - for (; h < c_idx->n && ovlp_id(c_idx->a[h]) == k; h++) { - qe = z->w_list.a[ovlp_max_wid(c_idx->a[h])].x_end+1; - } - sid[sid_n] = ((qs<<32)|sid_n); - sep[sid_n] = ((k<<32)|qe); - sid_n++; - // kv_push(uint64_t, *suf, ((qs<<32)|h)); - } - } - radix_sort_bc64(sid, sid+sid_n); - for (k = rr = 0; k < sid_n; k++) { - qs = sid[k]>>32; qe = ((uint32_t)sep[(uint32_t)sid[k]]); - z = &(ol->list[sep[(uint32_t)sid[k]]>>32]); - if(z->non_homopolymer_errors == 0) continue; - for (i = 0; i < sid_n; i++) { - ts = sid[i]>>32; te = ((uint32_t)sep[(uint32_t)sid[i]]); - p = &(ol->list[sep[(uint32_t)sid[i]]>>32]); - if(ts >= qe) break; - if(te <= qs) continue; - if(p->non_homopolymer_errors > z->non_homopolymer_errors) continue; - if(z->non_homopolymer_errors - p->non_homopolymer_errors <= rphase_thres) { - z->overlapLen = p->overlapLen = 1; rr++; - } - } - } -} - -void region_phase_adv(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, asg64_v* buf1, int64_t ulid) -{ - int64_t on = ol->length, k, i, zwn, q[2], t[2], w[2]; - uint64_t m; overlap_region *z; ul_ov_t *cp; - kv_resize(uint64_t, *idx, (ol->length<<1)); - kv_resize(ul_ov_t, *c_idx, ol->length); - for (k = idx->n = c_idx->n = 0; k < on; k++) { - z = &(ol->list[k]); zwn = z->w_list.n; - z->align_length = 0; z->overlapLen = (uint32_t)-1; - z->non_homopolymer_errors = 0; - if(!zwn) continue; - q[0] = q[1] = t[0] = t[1] = w[0] = w[1] = INT32_MIN; - for (i = 0; i < zwn; i++) { - if((z->w_list.a[i].x_start==(q[1]+1)) && ((z->w_list.a[i].y_start==(t[1]+1)))) { - q[1] = z->w_list.a[i].x_end; - t[1] = z->w_list.a[i].y_end; - w[1] = i; - } else { - if(q[0] != INT32_MIN) { - m = ((uint64_t)q[0])<<1; m <<= 32; - m += c_idx->n; kv_push(uint64_t, *idx, m); - m = (((uint64_t)q[1])<<1)+1; m <<= 32; - m += c_idx->n; kv_push(uint64_t, *idx, m); - - kv_pushp(ul_ov_t, *c_idx, &cp); - ovlp_id(*cp) = k; ///ovlp id - ovlp_min_wid(*cp) = w[0]; ///beg id of windows - ovlp_max_wid(*cp) = w[1]; ///end id of windows - ovlp_cur_wid(*cp) = w[0]; ///cur id of windows - ovlp_cur_xoff(*cp) = z->w_list.a[w[0]].x_start; ///cur xpos - ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window - } - - q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; - t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end; - w[0] = i; w[1] = i; - } - } - if(q[0] != INT32_MIN) { - m = ((uint64_t)q[0])<<1; m <<= 32; - m += c_idx->n; kv_push(uint64_t, *idx, m); - m = (((uint64_t)q[1])<<1)+1; m <<= 32; - m += c_idx->n; kv_push(uint64_t, *idx, m); - - kv_pushp(ul_ov_t, *c_idx, &cp); - ovlp_id(*cp) = k; ///ovlp id - ovlp_min_wid(*cp) = w[0]; ///beg id of windows - ovlp_max_wid(*cp) = w[1]; ///end id of windows - ovlp_cur_wid(*cp) = w[0]; ///cur id of windows - ovlp_cur_xoff(*cp) = z->w_list.a[w[0]].x_start; ///cur xpos - ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window - } - } - radix_sort_bc64(idx->a, idx->a+idx->n); - //this is used with gen_region_phase, now give up - //gen_gov_idx(ol, uref, uopt, G_CHAIN_BW, N_GCHAIN_RATE, buf1); - // for (m = 0; m < c_idx->n; m++) { - // fprintf(stderr, "+++[M::%s::utg%.6dl] q[%d, %d), t[%d, %d), wn::%d\n", __func__, - // (int32_t)ol->list[ovlp_id(c_idx->a[m])].y_id+1, - // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_min_wid(c_idx->a[m])].x_start, - // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_max_wid(c_idx->a[m])].x_end+1, - // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_min_wid(c_idx->a[m])].y_start, - // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_max_wid(c_idx->a[m])].y_end+1, - // ovlp_max_wid(c_idx->a[m])+1-ovlp_min_wid(c_idx->a[m])); - // } - - if(rphase_detect0(ol, c_idx, idx, buf, buf1)) {//refine phasing - reacal_phase(ol, c_idx, idx, buf, buf1); - } - - for (k = 0; k < on; k++) { - z = &(ol->list[k]); - z->overlapLen = z->x_pos_e+1-z->x_pos_s; - z->non_homopolymer_errors = 0; zwn = 0; - for (i = m = 0; i < z->align_length; i++) { - z->w_list.a[m] = z->w_list.a[z->w_list.n+i]; - if(z->w_list.a[m].clen > 0) { - z->non_homopolymer_errors += z->w_list.a[m].clen; - zwn += z->w_list.a[m].x_end-z->w_list.a[m].x_start; - } - m++; - } - z->w_list.n = m; - assert(zwn <= z->overlapLen); - z->align_length = z->overlapLen - zwn; - } -} - -void ul_gap_filling_adv(overlap_region_alloc* ol, Candidates_list *cl, kv_ul_ov_t *aln, uint64_t wl, -const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, overlap_region *aux_o, -asg64_v* buf, asg64_v* iidx, double e_rate, int64_t ql, uint64_t rid, int64_t khit, int64_t base_chekc_k_hit, -int64_t max_lgap) -{ - int64_t k, l, ch_n, a_n = aln->n; uint64_t pqn, pk; overlap_region *z; //k_mer_hit *ch_a; - // count_k_hits(rref, uref, qstr, tu, ol, cl, buf, khit, base_chekc_k_hit); - count_k_hits_adv(rref, uref, qstr, tu, ol, cl, buf, &(cl->chainDP), e_rate, khit, base_chekc_k_hit); - // prt_khit(cl, ol, NULL, 109111, "e"); - for (k = 1, l = 0, pqn = 0; k <= a_n; k++) { - if(k == a_n || aln->a[l].qn != aln->a[k].qn) { - z = &(ol->list[aln->a[l].qn]); assert(z->align_length == l); - // fprintf(stderr, "[M::%s::] oid::[%lu, %u)\n", __func__, pqn, aln->a[l].qn); - for (pk = pqn; pk < aln->a[l].qn; pk++) ol->list[pk].w_list.n = 0; - pqn = aln->a[l].qn+1; - // fprintf(stderr, "[M::%s::utg%.6dl::%c]\n", __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand]); - // prt_khit(cl, ol, NULL, 109111, "f"); - ch_n = gen_cns_chain(ol, z, cl, iidx, max_lgap, e_rate, 0); - // prt_khit(cl, ol, NULL, 109111, "g"); - if(ch_n) { - cigar_gen_by_chain_adv(z, cl, cl->length, ch_n, aln->a+l, k-l, wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, rid, khit); - } - l = k; - } - } - for (pk = pqn; pk < ol->length; pk++) ol->list[pk].w_list.n = 0; -} - -void ul_gap_filling_local(overlap_region_alloc* ol, Candidates_list *cl, kv_ul_ov_t *aln, uint64_t wl, -const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, overlap_region *aux_o, -asg64_v* buf, asg64_v* iidx, double e_rate, int64_t ql, uint64_t rid, int64_t khit, int64_t base_chekc_k_hit, -int64_t max_lgap) -{ - int64_t k, l, a_n = aln->n; uint64_t pqn, pk; overlap_region *z; //k_mer_hit *ch_a; - count_k_hits_filter(ol, cl, buf, &(cl->chainDP)); - for (k = 1, l = 0, pqn = 0; k <= a_n; k++) { - if(k == a_n || aln->a[l].qn != aln->a[k].qn) { - z = &(ol->list[aln->a[l].qn]); assert(z->align_length == l); - for (pk = pqn; pk < aln->a[l].qn; pk++) ol->list[pk].w_list.n = 0; - pqn = aln->a[l].qn+1; - cigar_gen_by_chain_adv_local(z, cl, aln->a+l, k-l, wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, rid, khit); - // ch_n = gen_cns_chain(z, cl, iidx, max_lgap, e_rate, 0); - // if(ch_n) { - // cigar_gen_by_chain_adv(z, cl, cl->length, ch_n, aln->a+l, k-l, wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, rid, khit); - // } - l = k; - } - } - for (pk = pqn; pk < ol->length; pk++) ol->list[pk].w_list.n = 0; -} - -inline uint32_t ovlp_win_check(overlap_region *z, uint32_t id0, uint32_t id1, int64_t max_lgap, double small_bw_rate, int64_t min_small_bw) -{ - if(id0 == (uint32_t)-1 || id1 == (uint32_t)-1) return 1; - int64_t qs0, qe0, ts0, te0, qs1, qe1, ts1, te1, err, dd, dm, dq, dr; - if(!get_win_aln(z, id0, &ts0, &te0, &err)) return 1; - qs0 = z->w_list.a[id0].x_start; qe0 = z->w_list.a[id0].x_end+1; - if(!get_win_aln(z, id1, &ts1, &te1, &err)) return 1; - qs1 = z->w_list.a[id1].x_start; qe1 = z->w_list.a[id1].x_end+1; - - if(qs1 < qs0 || qe1 < qe0) return 0; - if(ts1 < ts0 || te1 < te0) return 0; - dq = qe1 - qs0; dr = te1 - ts0; dd = dq>=dr? ((dq)-(dr)): ((dr)-(dq)); - if((ts1 < te0) && (qe0 == qs1)) {//has overlap in y - dm = dq>=dr?dr:dq; - if((dd > (dm*small_bw_rate)) && (dd > min_small_bw)) return 0; - } else { - if(dd > max_lgap) return 0; - } - return 1; -} - -uint64_t dp_commen_sketch(kv_ul_ov_t *aln, overlap_region_alloc* ol, uint64_t *id_a, int64_t id_n, -uint64_t *win_a, int64_t win_n, uint64_t *dp, int64_t n_skip, int64_t wl, int64_t cov, int64_t max_lgap, -double sgap_rate, int64_t sgap) -{ - if(!win_n) return 0; - int64_t k, ws, ws0, i, m, wid, wid0, sc, max_sc, p, long_sc, long_idx; overlap_region *z; - // fprintf(stderr, "\n[M::%s::] n_skip::%ld, win_n::%ld\n", __func__, n_skip, win_n); - // for (k = 0; k < win_n; k++) { - // fprintf(stderr, "[M::%s::] win_a[%ld]::%lu\n", __func__, k, win_a[k]); - // } - if(n_skip < win_n) { - long_sc = long_idx = -1; - for (k = 0; k < n_skip; k++) { - dp[k] = ((k>0)?(k-1):((uint32_t)-1)); dp[k] <<= 32; dp[k] |= k+1; max_sc = k+1; - if(long_sc < max_sc) { - long_sc = max_sc; long_idx = k; - } - } - - for (; k < win_n; k++) { - ws = win_a[k]; sc = 1; p = -1; max_sc = sc; - for (m = k-1; m >= 0; m--) { - ws0 = win_a[m]; - for (i = 0; i < id_n; i++) { - z = &(ol->list[aln->a[(uint32_t)id_a[i]].qn]); - wid = get_win_id_by_s(z, ws, wl, NULL); - wid0 = get_win_id_by_s(z, ws0, wl, NULL); - if(!ovlp_win_check(z, wid0, wid, max_lgap, sgap_rate, sgap)) break; - } - if((i >= id_n) && ((sc + ((uint32_t)dp[m])) > max_sc)) { - max_sc = (sc + ((uint32_t)dp[m])); p = m; - } - } - dp[k] = ((p>=0)?(p):((uint32_t)-1)); dp[k] <<= 32; dp[k] |= max_sc; - if(long_sc < max_sc) { - long_sc = max_sc; long_idx = k; - } - } - // fprintf(stderr, "[M::%s::] long_idx::%lu, long_sc::%lu\n", __func__, long_idx, long_sc); - k = long_idx; - while (k >= 0) { - win_a[k] |= ((uint64_t)0x8000000000000000); - k = ((dp[k]>>32)!=((uint32_t)-1))?(dp[k]>>32):(-1); - } - - for (k = 0, m = 0; k < win_n; k++) { - if(!(win_a[k]&((uint64_t)0x8000000000000000))) continue; - win_a[m++] = (win_a[k]<<1)>>1; - } - win_n = m; - // fprintf(stderr, "[M::%s::] win_n::%lu\n", __func__, win_n); - } - - for (k = 0, cov = -cov; k < win_n; k++) { - ws = win_a[k]; - for (i = 0; i < id_n; i++) { - z = &(ol->list[aln->a[(uint32_t)id_a[i]].qn]); - wid = get_win_id_by_s(z, ws, wl, NULL); - // if(wid >= z->w_list.n) { - // fprintf(stderr, "[M::%s::] ws::%ld, wl::%ld, wid::%ld, wn::%ld\n", - // __func__, ws, wl, wid, ((int64_t)z->w_list.n)); - // } - if(cov > INT16_MIN) z->w_list.a[wid].extra_end = cov; - else z->w_list.a[wid].extra_end = INT16_MIN; - z->align_length = wid;///for conliner - } - } - return win_n; -} - - -uint64_t gen_commen_sketch(All_reads *rref, const ul_idx_t *uref, overlap_region_alloc* ol, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, uint64_t ql, uint64_t wl, -uint64_t *buf, uint64_t dp, char *str0, char *str1, kv_ul_ov_t *aln, asg64_v *trace, -int64_t max_lgap, double sgap_rate, int64_t sgap)///[s, e) -{ - if(!id_n) return id_n; - uint64_t i, m, k, rm_n = 0, buf_n = 0, qs, qe, wid, co, occ; char *qstring, *tstring; - overlap_region *z; uint64_t ws, we; int64_t r_y[2], r_err, p_y[2], p_err, rxl, ryl, pxl; - ///shrink [qs, qe) - qs = (s/wl)*wl; if(qs < s) qs += wl; if(qs >= ql) return id_n; - qe = (e/wl)*wl; if(qe >= ql) qe = ql; - if(qs >= qe) return id_n; - //idx_a[] is sorted by aln[].qs - for (k = 0; k < id_n; k++) { - if(aln->a[id_a[k]].qs<=qs && aln->a[id_a[k]].qe>=qe) { - buf[buf_n] = ol->list[aln->a[id_a[k]].qn].align_length; buf[buf_n] <<= 32; buf[buf_n] |= id_a[k]; - buf_n++; - } - if(aln->a[id_a[k]].qe < e) rm_n++; - } - assert(buf_n == dp && buf_n > 1); - - if(buf_n > 0) { - ///fs = fe = (uint64_t)-1; - co = 1; trace->n = occ = 0; - for (k = qs; k < qe; k += wl) { - ws = k; we = ws + wl; if(we > qe) we = qe;//[ws, we) - ///first overlap - z = &(ol->list[aln->a[(uint32_t)buf[0]].qn]); - wid = get_win_id_by_s(z, ws, wl, NULL); - if(!get_win_aln(z, wid, &(r_y[0]), &(r_y[1]), &r_err)) continue; - if(!ovlp_win_check(z, z->align_length, wid, max_lgap, sgap_rate, sgap)) continue;///not co-linear - rxl = z->w_list.a[wid].x_end+1-z->w_list.a[wid].x_start; - ryl = r_y[1]-r_y[0]; - // fprintf(stderr, "+[M::%s::] buf_n::%lu, q::[%lu, %lu), w::[%lu, %lu), rxl::%ld, ryl::%ld, x::[%d, %d), y::[%ld, %ld)\n", - // __func__, buf_n, qs, qe, ws, we, rxl, ryl, z->w_list.a[wid].x_start, z->w_list.a[wid].x_end+1, r_y[0], r_y[1]); - if(rxl > 1 && ryl > 1) continue;///length of window should be longer than 1 - // if(rxl <= 1 || ryl <= 1) continue;///length of window should be longer than 1 - // fprintf(stderr, "-[M::%s::] buf_n::%lu, q::[%lu, %lu), w::[%lu, %lu), rxl::%ld, ryl::%ld, x::[%d, %d), y::[%ld, %ld)\n", - // __func__, buf_n, qs, qe, ws, we, rxl, ryl, z->w_list.a[wid].x_start, z->w_list.a[wid].x_end+1, r_y[0], r_y[1]); - qstring = tstring = NULL; - for (i = 1; i < buf_n; i++) { - z = &(ol->list[aln->a[(uint32_t)buf[i]].qn]); - wid = get_win_id_by_s(z, ws, wl, NULL); - if(!get_win_aln(z, wid, &(p_y[0]), &(p_y[1]), &p_err)) break; - if(!ovlp_win_check(z, z->align_length, wid, max_lgap, sgap_rate, sgap)) break;///not co-linear - pxl = z->w_list.a[wid].x_end+1-z->w_list.a[wid].x_start; - if(pxl != rxl) break; - if(((r_y[1]-r_y[0]) != (p_y[1]-p_y[0])) || (r_err != p_err)) break; - if(r_err == 0) continue; - if(!qstring) { - qstring = retrive_str_piece_exz(rref, uref, str0, r_y[0], r_y[1]-r_y[0], - ol->list[aln->a[(uint32_t)buf[0]].qn].y_pos_strand, ol->list[aln->a[(uint32_t)buf[0]].qn].y_id); - } - tstring = retrive_str_piece_exz(rref, uref, str1, p_y[0], p_y[1]-p_y[0], z->y_pos_strand, z->y_id); - if(memcmp(qstring, tstring, (p_y[1]-p_y[0]))) { - // fprintf(stderr, "[M::%s::] qs::%ld, qe::%lu, ts::%ld, te::%lu, err::%ld, rts::%ld, rte::%lu, err::%ld\n", - // __func__, ws, we, p_y[0], p_y[1], r_err, r_y[0], r_y[1], p_err); - // fprintf(stderr, "str0::%.*s\n", (int32_t)(r_y[1]-r_y[0]), str0); - // fprintf(stderr, "str1::%.*s\n", (int32_t)(p_y[1]-p_y[0]), str1); - break; - } - } - if(i < buf_n) continue; - if(co) { - for (i = 0; i < buf_n; i++) { - z = &(ol->list[aln->a[(uint32_t)buf[i]].qn]); - wid = get_win_id_by_s(z, ws, wl, NULL); - co = ovlp_win_check(z, buf[i]>>32, wid, max_lgap, sgap_rate, sgap); - m = wid; m <<= 32; m |= (uint32_t)buf[i]; buf[i] = m; - } - if(co) occ++; - } - kv_push(uint64_t, *trace, ws); - } - - if(trace->n) { - if(!co) kv_resize(uint64_t, *trace, trace->n<<1); - trace->n = dp_commen_sketch(aln, ol, buf, buf_n, trace->a, trace->n, trace->a + trace->n, occ, wl, dp, max_lgap, sgap_rate, sgap); - } - } - if(rm_n) { - for (i = m = 0; i < id_n; i++) { - if(aln->a[id_a[i]].qe < e) continue; - id_a[m++] = id_a[i]; - } - id_n = m; - } - return id_n; -} - -void update_sketch_trace(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, -All_reads *rref, UC_Read* tu, asg64_v* idx, asg64_v *b0, asg64_v *b1, int64_t ql, int64_t wl, -kv_ul_ov_t *aln, uint64_t rid, int64_t max_lgap, double sgap_rate) -{ - idx->n = 0; - if(!aln->n) return; - uint64_t i, k, own, srt_n; int64_t dp, old_dp, beg, end; overlap_region *z; - for (i = 0; i < ol->length; i++) { - z = &(ol->list[i]); append_unmatched_wins(z, wl); - own = z->w_list.n; z->align_length = (uint32_t)-1; - for (k = 0; k < own; k++) { - if(z->w_list.a[k].extra_end < 0) z->w_list.a[k].extra_end = 0; - } - } - - kv_resize(uint64_t, *idx, (aln->n<<1)); kv_resize(uint64_t, *b0, aln->n); - for (i = srt_n = 0; i < aln->n; i++) { - // if(i == 0 || aln->a[i].qn != aln->a[i-1].qn) ol->list[aln->a[i].qn].align_length = i; - ol->list[aln->a[i].qn].align_length = (uint32_t)-1;///for co-linear - idx->a[srt_n] = aln->a[i].qs<<1; idx->a[srt_n] <<= 32; idx->a[srt_n] += i; srt_n++; - idx->a[srt_n] = ((aln->a[i].qe-1)<<1)+1; idx->a[srt_n] <<= 32; idx->a[srt_n] += i; srt_n++; - aln->a[i].el = 1; - } - - radix_sort_bc64(idx->a, idx->a+srt_n); idx->n = srt_n; resize_UC_Read(tu, (wl<<1)); - for (i = 0, dp = 0, beg = 0, end = -1; i < srt_n; ++i) {///[beg, end), but the idx saves [qs, qe] - old_dp = dp; - ///if idx->a.a[] is qe - if ((idx->a[i]>>32)&1) { - --dp; end = (idx->a[i]>>33)+1; - }else { - //meet a new overlap; the overlaps are pushed by the x_pos_s - ++dp; end = (idx->a[i]>>33); - kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); - } - - if((end > beg) && (end - beg > wl) && (old_dp >= 2) ) { - // fprintf(stderr, "+++[M::%s::] beg::%ld, end::%ld\n", __func__, beg, end); - idx->n = srt_n + - gen_commen_sketch(rref, uref, ol, idx->a+srt_n, idx->n-srt_n, beg, end, ql, wl, b0->a, - old_dp, tu->seq, tu->seq+wl, aln, b1, max_lgap, sgap_rate, SGAP); - } - beg = end; - } - - for (i = 0; i < aln->n; i++) { - if(i == 0 || aln->a[i].qn != aln->a[i-1].qn) ol->list[aln->a[i].qn].align_length = i; - } - idx->n = srt_n; - // fprintf(stderr, "+++[M::%s::] idx->n::%ld\n", __func__, idx->n); - return; -} - - - -void ul_lalign(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, const ug_opt_t *uopt, - char *qstr, uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, bit_extz_t *exz, haplotype_evdience_alloc* hap, - kvec_t_u64_warp* v_idx, overlap_region *aux_o, double e_rate, int64_t wl, kv_ul_ov_t *aln, int64_t sid, uint64_t khit, - st_mt_t *stb, idx_emask_t *mm, mask_ul_ov_t *mk, void *km) -{ - uint64_t i, bs, k, ovl/**, on**/; Window_Pool w; double err; - /**int64_t sc;**/ overlap_region t; overlap_region *z; asg64_v iidx, buf, buf1; - ol->mapped_overlaps_length = 0; - if(ol->length <= 0) return; - - ///base alignment - clear_Correct_dumy(dumy, ol, km); err = e_rate; - init_Window_Pool(&w, ql, wl, (int)(1.0/err)); - bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; - resize_UC_Read(tu, bs<<1); - - if(!aln) { - resize_UC_Read(qu, ql); qu->length = ql; memcpy(qu->seq, qstr, ql); - for (i = 0; i < ol->length; i++) { - z = &(ol->list[i]); ovl = z->x_pos_e+1-z->x_pos_s; - z->shared_seed = z->non_homopolymer_errors;///for index - if(!align_ul_ed_post_extz(z, uref, NULL, qu->seq, tu->seq, exz, err, w.window_length, -1, 0, km)) { - continue; - } - if(uref && simi_pass(ovl, z->align_length, uref?1:0, -1, NULL)) { - z->is_match = 3; ol->mapped_overlaps_length += z->align_length; - } - } - - if(uref && ol->mapped_overlaps_length > 0) { - set_herror_win(ol, dumy, v_idx, err, ql, w.window_length); - } - - double e_max = err*1.5, rr; int64_t re; - for (i = k = 0; i < ol->length; i++) { - z = &(ol->list[i]); ovl = z->x_pos_e + 1 - z->x_pos_s; - rr = gen_extend_err_exz(z, uref, NULL, NULL, qu->seq, tu->seq, exz, v_idx?v_idx->a.a:NULL, w.window_length, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 1, &re); - z->is_match = 0;///must be here; - - - // fprintf(stderr, "[M::%s::utg%.6dl::%c] sid::%ld, q::[%d, %d), t::[%d, %d), err::%ld\n", - // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], sid, z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1, - // re); - - if (rr <= err) { - if(k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - ol->list[k].is_match = 1; ol->list[k].non_homopolymer_errors = re; - // fprintf(stderr, "+[M::%s] on::%lu\n", __func__, ol->length); - /****for debug****/ - // z = &(ol->list[k]); - // fprintf(stderr, "[M::%s::utg%.6dl::%c] sid::%ld, q::[%d, %d), t::[%d, %d), err::%u\n", - // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], sid, z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1, - // z->non_homopolymer_errors); - /****for debug****/ - k++; - } - } - - ol->length = k; - // fprintf(stderr, "+[M::%s] on::%lu\n", __func__, ol->length); - if(ol->length <= 0) return; - } else { - // fprintf(stderr, "-[M::%s] on::%lu\n", __func__, ol->length); - if(ol->length <= 1) { - if(ol->length == 1) { - window_list *p; - z = &(ol->list[0]); z->w_list.n = 0; - kv_pushp(window_list, z->w_list, &p); - memset(p, 0, sizeof((*p))); - p->x_start = z->x_pos_s; p->x_end = z->x_pos_e+1; p->clen = 0; - z->align_length = z->overlapLen = z->x_pos_e+1-z->x_pos_s; - z->non_homopolymer_errors = 0; - } - return; - } - ///coordinates for all intervals with cov > 1 - copy_asg_arr(iidx, hap->snp_srt); copy_asg_arr(buf, v_idx->a); copy_asg_arr(buf1, (*stb)); - // fprintf(stderr, "\n[M::%s] iidx_n::%ld\n", __func__, (int64_t)iidx.n); - ul_gap_filling_adv(ol, cl, aln, wl, uref, NULL, NULL, qu->seq, tu, exz, aux_o, &buf, &iidx, err, ql, sid, khit, 1, MAX_LGAP(ql)); - copy_asg_arr(hap->snp_srt, iidx); copy_asg_arr(v_idx->a, buf); copy_asg_arr((*stb), buf1); - - copy_asg_arr(iidx, hap->snp_srt); copy_asg_arr(buf, v_idx->a); copy_asg_arr(buf1, (*stb)); - // region_phase(ol, uref, uopt, aln, &iidx, &buf, &buf1, sid); - rphase_hl(ol, uref, uopt, aln, &iidx, &buf, &buf1, sid, 64, ql, mk, mm, err); - copy_asg_arr(hap->snp_srt, iidx); copy_asg_arr(v_idx->a, buf); copy_asg_arr((*stb), buf1); - } -} - - -int64_t get_chain_x_by_y(overlap_region* ot, int64_t q) -{ - int64_t x, y, off, i, lx = -1, ly = -1; Fake_Cigar* o = &(ot->f_cigar); - x = get_fake_gap_pos(o, o->length - 1); - off = get_fake_gap_shift(o, o->length - 1); - y = x - ot->x_pos_s + ot->y_pos_s + off; - if(y == q) return x; - - for (i = 0; i < (int64_t)o->length; i++){ - x = get_fake_gap_pos(o, i); off = get_fake_gap_shift(o, i); - y = x - ot->x_pos_s + ot->y_pos_s + off; - if(q < y) { - lx = x; ly = y; - break; - } - } - - assert((i!=0)&&(i!=(int64_t)o->length)); - x = get_fake_gap_pos(o, i-1); off = get_fake_gap_shift(o, i-1); - y = x - ot->x_pos_s + ot->y_pos_s + off; - y = (((double)(q - y))/((double)(ly - y)))*((double)(lx -x)) + x; - if(y < ot->x_pos_s) y = ot->x_pos_s; - if(y > ot->x_pos_e) y = ot->x_pos_e; - return y; -} - -int64_t gen_contain_ov(const ul_idx_t *uref, utg_ct_t *p, overlap_region* o, kv_ul_ov_t *res) -{ - int64_t y_s, y_e, y_bs, y_be, x_s, x_e, q_s, q_e; - if(o->y_pos_strand) { - y_s = uref->ug->u.a[o->y_id].len - p->e; - y_e = uref->ug->u.a[o->y_id].len - p->s - 1; - } else { - y_s = p->s; y_e = p->e - 1; - } - - y_s = MAX(y_s, (int64_t)o->y_pos_s); y_e = MIN(y_e, (int64_t)o->y_pos_e); - if(y_s > y_e) return 0; - x_s = get_chain_x_by_y(o, y_s); x_e = get_chain_x_by_y(o, y_e) + 1; - assert(x_s < x_e); - // if(x_s >= x_e) fprintf(stderr, "+++y_s->%ld, y_e->%ld, x_s->%ld, x_e->%ld\n", y_s, y_e, x_s, x_e); - if(o->y_pos_strand) { - y_bs = uref->ug->u.a[o->y_id].len - (y_e+1); - y_be = uref->ug->u.a[o->y_id].len - y_s; - } else { - y_bs = y_s; y_be = y_e + 1; - } - - q_s = 0; q_e = p->e - p->s; - if(p->x&1) { - q_s += (p->e - y_be); - q_e -= (y_bs - p->s); - } else { - q_s += (y_bs - p->s); - q_e -= (p->e - y_be); - } - - ul_ov_t *x = NULL; - kv_pushp(ul_ov_t, *res, &x); - x->qn = o->x_id; x->qs = x_s; x->qe = x_e; - x->tn = (uint32_t)(0x80000000); x->tn |= (p->x>>1); - x->ts = q_s; x->te = q_e; x->el = 1;x->sec = 0; x->rev = ((o->y_pos_strand == (p->x&1))?0:1); - return 1; -} - - -uint64_t gen_sub_ov(const ul_idx_t *udb, overlap_region* o, kv_ul_ov_t *res, uint64_t xs, uint64_t xe) -{ - uint64_t ts, te, i, l, rn = res->n, rev = o->y_pos_strand; ul_ov_t *z; - utg_ct_t p; ma_utg_t *u = &(udb->ug->u.a[o->y_id]); - if(!rev){ - ts = o->y_pos_s; te = o->y_pos_e + 1; - } else { - ts = u->len - (o->y_pos_e+1); te = u->len - o->y_pos_s; - } - - for (i = l = 0; i < u->n; i++) { - p.x = u->a[i]>>32; p.s = l; p.e = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); - l += (uint32_t)u->a[i]; - if(p.e <= ts) continue; - if(p.s >= te) break; - if(gen_contain_ov(udb, &p, o, res)) { - z = &(res->a[res->n-1]); - if(z->qs >= xe) break; - if(z->qe <= xs) res->n--; - } - } - return res->n-rn; -} - -uint64_t gen_conta_ov(const ul_idx_t *udb, overlap_region* o, utg_ct_t *ct_a, int64_t ct_n, kv_ul_ov_t *res, uint64_t xs, uint64_t xe) -{ - int64_t i; uint64_t ys, ye, rn = res->n; ma_utg_t *u = &(udb->ug->u.a[o->y_id]); - ul_ov_t *z; utg_ct_t *p; - - if(o->y_pos_strand == 0){ - ys = o->y_pos_s; ye = o->y_pos_e + 1; - } else { - ys = u->len - (o->y_pos_e+1); ye = u->len - o->y_pos_s; - } - - for (i = 0; i < ct_n; i++) { - p = &(ct_a[i]); - if(p->e <= ys) continue; - if(p->s >= ye) break; - if(gen_contain_ov(udb, p, o, res)) { - z = &(res->a[res->n-1]); - if(z->qs >= xe) break; - if(z->qe <= xs) res->n--; - } - } - return res->n-rn; -} - - -uint64_t gen_r_aln(const ul_idx_t *udb, overlap_region *z, uint64_t zid, asg64_v *idx, double o_rate, kv_ul_ov_t *aln, uint64_t min_ovlp) -{ - uint64_t ol = z->x_pos_e+1-z->x_pos_s, aln_ol = z->align_length, k, cn, is_srt; - ul_ov_t *p; ul_contain *ct = udb->ct; utg_ct_t *ca; uint64_t os, oe, ovlp, salnl, sol, raln = aln->n; - int64_t sk, ek, wn, s, e, ws, we, minw, maxw; - if((aln_ol < min_ovlp) || (!(z->w_list.n))) return 0; - if((ol*o_rate) <= aln_ol) { - kv_pushp(ul_ov_t, *aln, &p); - p->qn = zid; p->tn = z->y_id; p->el = 1; p->rev = z->y_pos_strand; p->sec = 0; - p->qs = z->x_pos_s; p->qe = z->x_pos_e+1; //[qs, qe) - p->ts = 0; p->te = z->w_list.n; //[ts, te) - } else { - cn = ((uint32_t)(ct->idx.a[z->y_id])); - ca = ct->rids.a + ((ct->idx.a[z->y_id])>>32); - wn = z->w_list.n; - ws = z->w_list.a[0].x_start; - we = z->w_list.a[z->w_list.n-1].x_end+1; - - gen_sub_ov(udb, z, aln, ws, we); gen_conta_ov(udb, z, ca, cn, aln, ws, we); - - idx->n = aln->n-raln; kv_resize(uint64_t, *idx, idx->n); - for (k = raln, idx->n = 0, is_srt = 1; k < aln->n; k++) { - if(k > raln && aln->a[k].qs < aln->a[k-1].qs) is_srt = 0; - idx->a[idx->n++] = (((uint64_t)(aln->a[k].qs))<<32)|((uint64_t)(aln->a[k].qe)); - } - if(!is_srt) radix_sort_bc64(idx->a, idx->a+idx->n); - aln->n = raln; - - for (k = sk = ek = 0; k < idx->n; k++) {///idx->a is sorted by s, not by e - s = idx->a[k]>>32; e = (uint32_t)idx->a[k]; - salnl = 0; sol = e - s; minw = INT32_MAX; maxw = 0; - for (sk = ((sk z->w_list.a[sk].x_end; sk++); - for (sk = ((sk= 0 && s < z->w_list.a[sk].x_start; sk--); - if(k < 0) k = 0; ///s >= z->w_list.a[sk].x_start && s <= z->w_list.a[sk].x_end - for (ek = sk; ek < wn; ek++) { - ws = z->w_list.a[ek].x_start; - we = z->w_list.a[ek].x_end + 1; - if(ws >= e) break; - if(z->w_list.a[ek].y_end == -1) continue; - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - if(!ovlp) continue; - salnl += ovlp; - if(ek < minw) minw = ek; - if(ek > maxw) maxw = ek; - } - p = NULL; - if(((sol*o_rate)<=salnl) && (maxw >= minw)) { - ws = z->w_list.a[minw].x_start; we = z->w_list.a[maxw].x_end + 1; maxw++; - if(aln->n > raln) { - p = &(aln->a[aln->n-1]); - os = MAX(s, p->qs); oe = MIN(e, p->qe); - if(oe>os) { - if(s < p->qs) p->qs = s; - if(e > p->qe) p->qe = e; - if(minw < p->ts) p->ts = minw; - if(maxw > p->te) p->te = maxw; - } else { - p = NULL; - } - } - if(!p) { - kv_pushp(ul_ov_t, *aln, &p); - p->qn = zid; p->tn = z->y_id; p->el = 0; - p->rev = z->y_pos_strand; p->sec = 0; - p->qs = s; p->qe = e; ///[qs, qe) - p->ts = minw; p->te = maxw; ///[ts, te) - } - } - } - } - - return aln->n - raln; -} - -///q[2], t[2] -int64_t get_win_yoff(overlap_region *o, int64_t toff, int64_t k, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t *q, int64_t *t, -int64_t *rq, int64_t *rt) -{ - int64_t wn = o->w_list.n<<1, s, qdis, tdis, dis; - if(k<0) k = 0; if(k>=wn) k = wn-1; - for (; k < wn; k++) { - s = ((k&1)?(o->w_list.a[k>>1].x_end):(o->w_list.a[k>>1].x_start)); - if(s >= toff) break; - } - for (k=(k>=wn?(wn-1):(k)); k >= 0; k--) { - s = ((k&1)?(o->w_list.a[k>>1].x_end):(o->w_list.a[k>>1].x_start)); - if(s <= toff) break; - } - - q[0] = qs; q[1] = qe; t[0] = ts; t[1] = te; - if(k < 0) {//toff <= t[1] - q[1] = o->w_list.a[0].x_start; - t[1] = o->w_list.a[0].y_start; - tdis = t[1] - toff; qdis = q[1] - q[0]; dis = MIN(qdis, tdis); - (*rq) = q[1] - dis; (*rt) = t[1] - dis; - } else if(k == wn-1) {//toff >= t[0] - q[0] = o->w_list.a[k>>1].x_end; - t[0] = o->w_list.a[k>>1].y_end; - tdis = toff - t[0]; qdis = q[1] - q[0]; dis = MIN(qdis, tdis); - (*rq) = q[0] + dis; (*rt) = t[0] + dis; - } else {//toff >= t[0] && toff <= t[1] - q[0] = ((k&1)?(o->w_list.a[k>>1].x_end):(o->w_list.a[k>>1].x_start)); - t[0] = ((k&1)?(o->w_list.a[k>>1].y_end):(o->w_list.a[k>>1].y_start)); - k++; - q[1] = ((k&1)?(o->w_list.a[k>>1].x_end):(o->w_list.a[k>>1].x_start)); - t[1] = ((k&1)?(o->w_list.a[k>>1].y_end):(o->w_list.a[k>>1].y_start)); - k--; - (*rt) = toff; - (*rq) = q[0] + get_offset_adjust(toff-t[0], t[1]-t[0], q[1]-q[0]); - } - return k; -} - -int64_t get_win_off(int64_t ql, utg_ct_t *p, overlap_region* o, double o_rate, ul_ov_t *res) -{ - if(!o->w_list.n) return 0; - int64_t q[2], t[2], wk[2], wq[2], wt[2], k, tot_l, qs, qe, ts, te, os, oe, ovlp, aln_l; - qs = 0; qe = ql-1; ts = p->s; te = p->e-1; //[qs, qe] && [ps, pe] - - k = 0; memset(res, 0, sizeof((*res))); - k = get_win_yoff(o, ts, k, qs, qe, ts, te, q, t, &(wq[0]), &(wt[0])); wk[0] = k; - k = get_win_yoff(o, te, k, qs, qe, ts, te, q, t, &(wq[1]), &(wt[1])); wk[1] = k; - res->ts = ts; res->te = te + 1;///offset of t - res->qs = wk[0]<0?(uint32_t)-1:wk[0]; res->qe = wk[1] + 1;///id of window - - wk[0] = ((wk[0]>=0)?(wk[0]>>1):0); - wk[1] = ((wk[1]>=0)?(wk[1]>>1):0)+1; - tot_l = wq[1]+1-wq[0]; aln_l = 0; - for (k = wk[0]; k < wk[1]; k++) { - if(is_ualn_win(o->w_list.a[k])) continue; - os = MAX(wq[0], o->w_list.a[k].x_start); - oe = MIN(wq[1], o->w_list.a[k].x_end) + 1; - ovlp = ((oe>os)? (oe-os):0); aln_l += ovlp; - } - if((aln_l < (tot_l*o_rate)) || (aln_l == 0)) return 0; - return 1; -} - -uint64_t gen_sub_ov_cigar(const ul_idx_t *udb, uint64_t ql, overlap_region* o, double o_rate, kv_ul_ov_t *res) -{ - uint64_t ts, te, i, l, tl, id = o->y_id, rn = res->n, s, e, rev = o->y_pos_strand; utg_ct_t p; - ma_utg_t *u = &(udb->ug->u.a[id]); ul_ov_t rr; int64_t wn, k; - - wn = o->w_list.n; tl = u->len; - for (k = 0; (k < wn) && (is_ualn_win(o->w_list.a[k])); k++); - if(k >= wn) return 0; - if(!rev) { - ts = o->w_list.a[k].x_start; - } else { - te = tl-o->w_list.a[k].x_start; - } - for (k = wn-1; (k >= 0) && (is_ualn_win(o->w_list.a[k])); k--); - if(k < 0) return 0; - if(!rev) { - te = o->w_list.a[k].x_end+1; - } else { - ts = tl-o->w_list.a[k].x_end-1; - } - if(ts >= te) return 0;///[ts, te) - - - for (i = l = 0; i < u->n; i++) { - p.x = u->a[i]>>32; s = l; e = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); - l += (uint32_t)u->a[i]; - if(e <= ts) continue; if(s >= te) break; - if(!rev) { - p.s = s; p.e = e; - } - else { - p.s = tl - e; p.e = tl - s; - } - - if(get_win_off(ql, &p, o, o_rate, &rr)) { - rr.el = 0; kv_push(ul_ov_t, *res, rr); - } - } - return res->n-rn; -} - - -uint64_t gen_conta_ov_cigar(const ul_idx_t *udb, uint64_t ql, overlap_region* o, utg_ct_t *ct_a, uint64_t ct_n, double o_rate, kv_ul_ov_t *res) -{ - uint64_t ts, te, i, tl, id = o->y_id, rn = res->n, rev = o->y_pos_strand; utg_ct_t p, *z; - ma_utg_t *u = &(udb->ug->u.a[id]); ul_ov_t rr; int64_t wn, k; - - wn = o->w_list.n; tl = u->len; - for (k = 0; (k < wn) && (is_ualn_win(o->w_list.a[k])); k++); - if(k >= wn) return 0; - if(!rev) { - ts = o->w_list.a[k].x_start; - } else { - te = tl-o->w_list.a[k].x_start; - } - for (k = wn-1; (k >= 0) && (is_ualn_win(o->w_list.a[k])); k--); - if(k < 0) return 0; - if(!rev) { - te = o->w_list.a[k].x_end+1; - } else { - ts = tl-o->w_list.a[k].x_end-1; - } - if(ts >= te) return 0;///[ts, te) - - - for (i = 0; i < ct_n; i++) { - z = &(ct_a[i]); - if(z->e <= ts) continue; - if(z->s >= te) break; - p = *z; - if(!rev) { - p.s = z->s; p.e = z->e; - } else { - p.s = tl - z->e; p.e = tl - z->s; - } - - if(get_win_off(ql, &p, o, o_rate, &rr)) { - rr.el = 1; kv_push(ul_ov_t, *res, rr); - } - } - return res->n-rn; -} - - - /** -void cal_simi_ul_ov_t(overlap_region *z, ul_ov_t *o, kv_ul_ov_t *res, int64_t ql) -{ - int64_t beg_q[2], beg_t[2], end_q[2], end_t[2], wk[2], wq[2], wt[2], kbeg, kend; - int64_t k, tot_l, qs, qe, ts, te, os, oe, ovlp, aln_l, wts, wte, wtl, wn; ul_ov_t *p; - qs = 0; qe = ql-1; ts = o->ts; te = o->te-1; //[qs, qe] && [ps, pe] - k = (o->qs==(uint32_t)-1)?(-1):(o->qs); - k = get_win_yoff(z, ts, k, qs, qe, ts, te, beg_q, beg_t, &(wq[0]), &(wt[0])); wk[0] = k; - k = o->qe; - k = get_win_yoff(z, te, k, qs, qe, ts, te, end_q, end_t, &(wq[1]), &(wt[1])); wk[1] = k; - o->sec = 0; - kbeg = ((wk[0]>=0)?(wk[0]>>1):(0)); kend = ((wk[1]>=0)?(wk[1]>>1):(0)); aln_l = 0; - for (k = kbeg; k <= kend; k++) { - wts = z->w_list.a[k].y_start; wte = z->w_list.a[k].y_end; wtl = wte + 1 - wts; - os = MAX(wts, ts); oe = MIN(wte, te) + 1; - ovlp = ((oe>os)? (oe-os):0); aln_l += ovlp; - assert(ovlp > 0); - if(ovlp == wtl) { - - } else { - - } - } - if(aln_l < te+1-ts) { - wn = z->w_list.n; - assert(wk[0] == -1 || wk[1] == wn-1); - } - - if(wk[0] == wk[1]) {///one window cover the whole [ts, te] - kv_pushp(ul_ov_t, *res, &p); p->ts = ts; p->te = te; - } - if(wk[0] < 0) { - - } -} -**/ - -///[ts, te) -> this is the reverse coordinates of t, not the original coordinates of t -int64_t extract_subov(int64_t ts, int64_t te, overlap_region *o, double o_rate, int64_t *in_k, ul_ov_t *res) -{ - int64_t rev = o->y_pos_strand, qs, qe, k = 0, wn = o->w_list.n, ws, we, os, oe, ovlp, salnl; - if(ts < ((int64_t)o->y_pos_s)) ts = o->y_pos_s; - if(te > ((int64_t)o->y_pos_e+1)) te = o->y_pos_e+1; - if(ts >= te) return 0; - qs = get_chain_x_by_y(o, ts); - qe = get_chain_x_by_y(o, te-1) + 1; - assert(qs < qe); - memset(res, 0, sizeof(*res)); res->rev = rev; - res->qs = qs; res->qe = qe; res->ts = ts; res->te = te; - - if(o_rate >= 0) { - if(wn <= 0) return 0; - if(in_k) k = *in_k; - - if(k < 0) k = 0; if(k >= wn) k = wn-1; - for(; k < wn && qs > o->w_list.a[k].x_end; k++); - if(k < 0) k = 0; if(k >= wn) k = wn-1; - for(; k >= 0 && qs < o->w_list.a[k].x_start; k--); - ///qs <= o->w_list.a[k].x_end && qs >= o->w_list.a[k].x_start - if(k < 0) k = 0; - if(in_k) *in_k = k; - - for (salnl = 0; k < wn; k++) { - ws = o->w_list.a[k].x_start; - we = o->w_list.a[k].x_end + 1; - if(ws >= qe) break; - if((o->w_list.a[k].y_end == -1) || (is_ualn_win(o->w_list.a[k]))) continue; - os = MAX(qs, ws); oe = MIN(qe, we); - ovlp = ((oe>os)? (oe-os):0); - if(!ovlp) continue; - salnl += ovlp; - } - // if(o->y_id == 700) { - // fprintf(stderr, "[M::%s] raw_t::[%ld, %ld), raw_q::[%ld, %ld), salnl::%ld\n", __func__, ts, te, qs, qe, salnl); - // } - if((((qe-qs)*o_rate)<=salnl) && (salnl > 0)) return 1; - else return 0; - } - return 1; -} - - -uint64_t gen_sub_ov_adv(const ul_idx_t *udb, overlap_region* o, double o_rate, utg_ct_t *ct_a, uint64_t ct_n, kv_ul_ov_t *res) -{ - uint64_t ts, te, i, l, rn = res->n, rev = o->y_pos_strand, s, e, rid, t[2]; ul_ov_t z; - ma_utg_t *u = &(udb->ug->u.a[o->y_id]); int64_t k; - if(!rev){ - ts = o->y_pos_s; te = o->y_pos_e + 1; k = 0; - } else { - ts = u->len - (o->y_pos_e+1); te = u->len - o->y_pos_s; - k = ((int64_t)o->w_list.n)-1; if(k < 0) k = 0; - } - - if(!ct_a) { - for (i = l = 0; i < u->n; i++) { - rid = u->a[i]>>33; - s = l; e = l + Get_READ_LENGTH(R_INF, rid); - l += (uint32_t)u->a[i]; - if(e <= ts) continue; - if(s >= te) break; - t[0] = (rev?(u->len-e):(s)); t[1] = (rev?(u->len-s):(e)); - if(extract_subov(t[0], t[1], o, o_rate, &k, &z)) { - ///[ts, te) -> whole interval rid at the unitig adjusted by the reverse - // z.ts = t[0]; z.te = t[1]; - ///the strand of rid at the unitig - z.rev = rev; - ///non-contained read at the unitg - z.el = 0; - ///rid - z.tn = rid; - ///i-th read at the unitig - z.qn = i; - kv_push(ul_ov_t, *res, z); - } - } - } else { - for (i = 0; i < ct_n; i++) { - rid = ct_a[i].x>>1; s = ct_a[i].s; e = ct_a[i].e; - if(e <= ts) continue; - if(s >= te) break; - t[0] = (rev?(u->len-e):(s)); t[1] = (rev?(u->len-s):(e)); - if(extract_subov(t[0], t[1], o, o_rate, &k, &z)) { - ///[ts, te) -> whole interval rid at the unitig adjusted by the reverse - // z.ts = t[0]; z.te = t[1]; - ///the strand of rid at the unitig - z.rev = rev; - ///contained read at the unitg - z.el = 1; - ///rid - z.tn = rid; - ///i-th read at the unitig - z.qn = i; - kv_push(ul_ov_t, *res, z); - } - } - } - return res->n-rn; -} - -int64_t return_t_chain(overlap_region *z, Candidates_list *cl) -{ - int64_t i, cn = cl->length, scn; uint64_t pid; k_mer_hit *ca; - - // if(z->y_id == 30129) { - // fprintf(stderr, "\n-0-[M::%s]\tutg%.6ul\tx::[%u,\t%u)\t%c\tutg%.6ul\ty::[%u,\t%u)\n", - // __func__, z->x_id+1, z->x_pos_s, z->x_pos_e+1, - // "+-"[z->y_pos_strand], z->y_id+1, z->y_pos_s, z->y_pos_e+1); - // i = z->shared_seed; pid = cl->list[i].readID; - // for (; i < cn && cl->list[i].readID == pid && cl->list[i].readID != ((uint32_t)(0x7fffffff)); i++) { - // fprintf(stderr, "i::%ld[M::%s]\treadID::%u\tself_offset::%u\toffset::%u\t%c\n", - // i, __func__, cl->list[i].readID, cl->list[i].self_offset, cl->list[i].offset, - // "+-"[cl->list[i].strand]); - // } - // } - - - - i = z->shared_seed; pid = cl->list[i].readID; - for (; i < cn && cl->list[i].readID == pid && cl->list[i].readID != ((uint32_t)(0x7fffffff)); i++); - scn = i - z->shared_seed; ca = cl->list+z->shared_seed; - i = lchain_refine(ca, scn, ca, &(cl->chainDP), 50, 5000, 512, 16); cn = i; - for (; i < scn; i++) ca[i].readID = ((uint32_t)(0x7fffffff)); - // if(z->y_id == 30129) fprintf(stderr, "\n-a-[M::%s]\tcn::%ld\n", __func__, cn); - - - // if(z->y_id == 30129) { - // fprintf(stderr, "\n-1-[M::%s]\tutg%.6ul\tx::[%u,\t%u)\t%c\tutg%.6ul\ty::[%u,\t%u)\n", - // __func__, z->x_id+1, z->x_pos_s, z->x_pos_e+1, - // "+-"[z->y_pos_strand], z->y_id+1, z->y_pos_s, z->y_pos_e+1); - // i = z->shared_seed; pid = cl->list[i].readID; cn = cl->length; - // for (; i < cn && cl->list[i].readID == pid && cl->list[i].readID != ((uint32_t)(0x7fffffff)); i++) { - // fprintf(stderr, "i::%ld[M::%s]\treadID::%u\tself_offset::%u\toffset::%u\t%c\n", - // i, __func__, cl->list[i].readID, cl->list[i].self_offset, cl->list[i].offset, - // "+-"[cl->list[i].strand]); - // } - // } - return cn; -} - -// int64_t gen_mix_tchain(Candidates_list *cl, int64_t kidx, int64_t kn, ul_ov_t *oa, int64_t on) -// { -// int64_t rcn = cl->length, kk, ok; -// kv_resize_cl(k_mer_hit, *cl, rcn+kn); -// kk = ok = 0; -// while(kk < kn && ok < on) { -// if(cl->list[kidx+kk].offset) -// } -// } - - -uint64_t gen_woff_idx(overlap_region *z, asg64_v *oidx) -{ - uint64_t mm, k, aln = 0; - kv_resize(uint64_t, *oidx, (z->w_list.n<<1)+2); - mm = z->x_pos_s; mm <<= 32; mm += z->y_pos_s; kv_push(uint64_t, *oidx, mm); - for (k = oidx->n = 0; k < z->w_list.n; k++) { - mm = z->w_list.a[k].x_start; mm <<= 32; mm += z->w_list.a[k].y_start; - if((oidx->n == 0) && (mm != oidx->a[oidx->n-1])) { - kv_push(uint64_t, *oidx, mm); - } - - mm = z->w_list.a[k].x_end; mm <<= 32; mm += z->w_list.a[k].y_end; - if((oidx->n == 0) && (mm != oidx->a[oidx->n-1])) { - kv_push(uint64_t, *oidx, mm); - } - if(!(is_ualn_win(z->w_list.a[k]))) aln += z->w_list.a[k].x_end - z->w_list.a[k].x_start; - } - mm = z->x_pos_e; mm <<= 32; mm += z->y_pos_e; - if((oidx->n == 0) && (mm != oidx->a[oidx->n-1])) { - kv_push(uint64_t, *oidx, mm); - } - return aln; -} - -//return [rq, rt] -void win_boundary_offset(window_list *a, int64_t w_n, int64_t wi, int64_t toff, int64_t ql, int64_t *rq, int64_t *rt) -{ - int64_t q[2], t[2], qdis, tdis, dis; q[0] = q[1] = t[0] = t[1] = -1; - ///[q[0], q[1]] && [t[0], t[1]] - if(toff >= a[wi].y_start && toff <= a[wi].y_end) {///within the window - q[0] = a[wi].x_start; q[1] = a[wi].x_end; - t[0] = a[wi].y_start; t[1] = a[wi].y_end; - } else if(toff < a[wi].y_start) {///before the window - if(wi > 0) { - q[0] = a[wi-1].x_end+1; q[1] = a[wi].x_start-1; - t[0] = a[wi-1].y_end+1; t[1] = a[wi].y_start-1; - } else { - qdis = a[wi].x_start; - tdis = a[wi].y_start - toff; - dis = MIN(qdis, tdis); - (*rq) = a[wi].x_start - dis; - (*rt) = a[wi].y_start - dis; - } - } else if(toff > a[wi].y_end) {//after the window - if(wi < w_n - 1) { - q[0] = a[wi].x_end+1; q[1] = a[wi+1].x_start-1; - t[0] = a[wi].y_end+1; t[1] = a[wi+1].y_start-1; - } else { - qdis = ql-1-a[wi].x_end; - tdis = toff-a[wi].y_end; - dis = MIN(qdis, tdis); - (*rq) = a[wi].x_end + dis; - (*rt) = a[wi].y_end + dis; - } - } - - if(q[0] >= 0 && q[1] >= 0 && t[0] >= 0 && t[1] >= 0) { - (*rt) = toff; - (*rq) = q[0] + get_offset_adjust(toff-t[0], t[1]-t[0], q[1]-q[0]); - } -} - -int64_t hc_aln_exz_simi_adv(int64_t id, int64_t rev, const ul_idx_t *uref, hpc_t *hpc_g, -All_reads *rref, char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, -int64_t qmin, int64_t qmax, int64_t tmin, int64_t tmax, int64_t mode, bit_extz_t *exz, int64_t q_tot, -double e_rate, int64_t maxl, int64_t maxe, int64_t force_l, int64_t estimate_err, overlap_region *z, -int64_t gen_trace) -{ - clear_align(*exz); exz->thre = 0; ///mode cannot be 3 - int64_t thre, ql = qe - qs, thre0, pts = -1, pte = -1, pthre = -1, t_tot; - if(estimate_err < 0) estimate_err = ql*e_rate; - if(ql <= 0) return 0; - if(hpc_g) t_tot = hpc_len(*hpc_g, id); - else if(uref) t_tot = uref->ug->u.a[id].len; - else t_tot = Get_READ_LENGTH((*rref), id); - - // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { - // fprintf(stderr, "-0-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld)\n", - // __func__, mode, qs, qe, ts, te); - // } - - if(ql <= 16) { - if(cal_exact_simi_exz(uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, q_tot, - t_tot, rev, id, mode, z)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::0(+)\n", exz->err, exz->thre); - return 1; - } - } - - // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { - // fprintf(stderr, "-a-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), ql::%ld, maxl::%ld, estimate_err::%ld, maxe::%ld\n", - // __func__, mode, qs, qe, ts, te, ql, maxl, estimate_err, maxe); - // } - - if(ql <= maxl && (estimate_err>>1) <= maxe) { - thre = scale_ed_thre(estimate_err, maxe); - // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { - // fprintf(stderr, "-1-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), thre::%ld\n", - // __func__, mode, qs, qe, ts, te, thre); - // } - if(cal_exz_infi_simi_adv(uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, - qmin, qmax, tmin, tmax, rev, id, mode, z, gen_trace)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(+)\n", exz->err, exz->thre, thre); - // push_alnw(aux_o, exz); - return 1; - } - - thre0 = thre; thre = ql*e_rate; thre = scale_ed_thre(thre, maxe); - // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { - // fprintf(stderr, "-2-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), thre::%ld\n", - // __func__, mode, qs, qe, ts, te, thre); - // } - if(thre > thre0) { - if(cal_exz_infi_simi_adv(uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, - qmin, qmax, tmin, tmax, rev, id, mode, z, gen_trace)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); - // push_alnw(aux_o, exz); - return 1; - } - } - - thre0 = thre; thre <<= 1; thre = scale_ed_thre(thre, maxe); - // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { - // fprintf(stderr, "-3-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), thre::%ld\n", - // __func__, mode, qs, qe, ts, te, thre); - // } - if(thre > thre0) { - if(cal_exz_infi_simi_adv(uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, - qmin, qmax, tmin, tmax, rev, id, mode, z, gen_trace)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); - // push_alnw(aux_o, exz); - return 1; - } - } - - thre0 = thre; thre = ql*0.51; thre = scale_ed_thre(thre, maxe); - // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { - // fprintf(stderr, "-4-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), thre::%ld\n", - // __func__, mode, qs, qe, ts, te, thre); - // } - if(thre > thre0) { - if(cal_exz_infi_simi_adv(uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, - qmin, qmax, tmin, tmax, rev, id, mode, z, gen_trace)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); - // push_alnw(aux_o, exz); - return 1; - } - } - - if(ql <= force_l) { - thre = maxe; - // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { - // fprintf(stderr, "-5-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), thre::%ld\n", - // __func__, mode, qs, qe, ts, te, thre); - // } - if(cal_exz_infi_simi_adv(uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, - qmin, qmax, tmin, tmax, rev, id, mode, z, gen_trace)) { - // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); - // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); - // push_alnw(aux_o, exz); - return 1; - } - } - } - - // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { - // fprintf(stderr, "-b-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld)\n", - // __func__, mode, qs, qe, ts, te); - // } - // fprintf(stderr, ", err::%d, thre::%d\n", INT32_MAX, exz->thre); - // if(mode == 0) { - // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tu->length, tu->seq); - // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)(qe-qs), qstr+qs); - // } - return 0; - -} - -#define update_ul_ov_t_coor(z, qbeg, qend, tbeg, tend) do {\ - if(((int64_t)(z).qs) > (qbeg)) (z).qs = (qbeg);\ - if(((int64_t)(z).qe) < (qend)) (z).qe = (qend);\ - if(((int64_t)(z).ts) > (tbeg)) (z).ts = (tbeg);\ - if(((int64_t)(z).te) < (tend)) (z).te = (tend);\ - } while (0) - -///[ps, pe) && [ts, te]) -int64_t hc_aln_exz_by_exist_cigar_with_p(bit_extz_t *ez, int64_t mode, int64_t ps, int64_t pe, -int64_t *ts, int64_t *te, int64_t *cis, int64_t *cie, int64_t *cps, int64_t *cpe, int64_t *cts, int64_t *cte) -{ - int64_t ts0 = (*ts), te0 = (*te), ts1, te1; - assert(ez->ps <= ps && ez->pe+1 >= pe && mode > 0); - if(mode == 1) (*te) = -1; - else if(mode == 2) (*ts) = -1; - else (*ts) = (*te) = -1; - (*cis) = (*cie) = (*cps) = (*cpe) = (*cts) = (*cte) = -1; - - int32_t pi = ez->ps, ti = ez->ts, pi0, ti0, err[2], tot_err, ws, we; - uint32_t ci = 0, cl; uint16_t c, sset = 0, eset = 0; - err[0] = err[1] = tot_err = 0; - while (ci < ez->cigar.n) { - ci = pop_trace(&(ez->cigar), ci, &c, &cl); - ws = pi; pi0 = pi; ti0 = ti; - if(c <= 1) { - pi+=cl; ti+=cl; - } else if(c == 2) {///more p - pi+=cl; - } else if(c == 3) { - ti+=cl; - } - we = pi; - // if((ps == 5139) && (pe == 21733)) { - // fprintf(stderr, "[M::%s::ci->%u] wp::[%d, %d), pi::%d, ti::%d, c::%u, cl::%u, tot_err::%d, p::[%ld, %ld), t::[%ld, %ld)\n", - // __func__, ci, ws, we, pi, ti, c, cl, tot_err, ps, pe, (*ts), (*te)); - // } - if(we < ps) {///not we <= ps - if(c != 0) tot_err += cl; - continue; - } - if(ws > pe) {///not ws >= pe - if(c != 0) tot_err += cl; - break; - } - - if(!sset) { - if((ps>=ws) && (ps%u] c::%u, cl::%u\n", __func__, ci, c, cl); - // } - if(c <= 1) { - ts1 = ti - (we - ps); - if((ts1 == ts0) || (mode != 1)) { - if(c == 1) err[0] = tot_err + (ps - ws); - else err[0] = tot_err; - sset = 1; (*ts) = ts1; - (*cis) = ci-1; (*cps) = pi0; (*cts) = ti0; - } - } else if(c == 2) {///more p - // ts1 = ti - (we - ps); - ts1 = ti; - if((ts1 == ts0) || (mode != 1)) { - err[0] = tot_err + (ps - ws); - sset = 1; (*ts) = ts1; - (*cis) = ci-1; (*cps) = pi0; (*cts) = ti0; - } - } else if(c == 3) { - ts1 = ti; - if((ts1 == ts0) || (mode != 1)) { - err[0] = tot_err + cl; - sset = 1; (*ts) = ts1; - (*cis) = ci-1; (*cps) = pi0; (*cts) = ti0; - } - } - } - - if((c == 3) && (ps>=ws) && (ps<=we)) { - // if((ps == 5139) && (pe == 21733)) { - // fprintf(stderr, "-[M::%s::ci->%u] c::%u, cl::%u\n", __func__, ci, c, cl); - // } - ts1 = ti - cl; - if(ts1 == ts0) { - err[0] = tot_err; sset = 1; (*ts) = ts1; - (*cis) = ci-1; (*cps) = pi0; (*cts) = ti0; - } - } - } - - if(!eset) { - if((pe>ws) && (pe<=we)) { - if(c <= 1) { - te1 = ti - (we - pe); - if((te1 == te0) || (mode != 2)) { - if(c == 1) err[1] = tot_err + (pe - ws); - else err[1] = tot_err; - eset = 1; (*te) = te1; - (*cie) = ci; (*cpe) = pi; (*cte) = ti; - } - } else if(c == 2) {///more p - // te1 = ti - (we - pe); - te1 = ti; - if((te1 == te0) || (mode != 2)) { - err[1] = tot_err + (pe - ws); - eset = 1; (*te) = te1; - (*cie) = ci; (*cpe) = pi; (*cte) = ti; - } - } else if(c == 3) { - te1 = ti-cl; - if((te1 == te0) || (mode != 2)) { - err[1] = tot_err; - eset = 1; (*te) = te1; - (*cie) = ci; (*cpe) = pi; (*cte) = ti; - } - } - } - if((c == 3) && (pe>=ws) && (pe<=we)) { - te1 = ti; - if(te1 == te0) { - err[1] = tot_err + cl; - eset = 1; (*te) = te1; - (*cie) = ci; (*cpe) = pi; (*cte) = ti; - } - } - if(eset) break; - } - - if(c != 0) tot_err += cl; - } - - // if(!(((mode == 1)&&((*ts) == ts0))||((mode == 2)&&((*te) == te0))||(mode == 3))) { - // fprintf(stderr, "+[M::%s::mode->%ld] t0::[%ld, %ld), t::[%ld, %ld), err::%d\n", - // __func__, mode, ts0, te0, (*ts), (*te), err[1] - err[0]); - // } - assert(((mode == 1)&&((*ts) == ts0))||((mode == 2)&&((*te) == te0))||(mode == 3)); - return err[1] - err[0]; -} - - -inline void update_trace_idx(rtrace_t *tc, int64_t wid, int64_t wid_s, int64_t wid_e, -int64_t qs, int64_t qe, int64_t ts, int64_t te) -{ - if(qs < tc->c_qs || ts < tc->c_ts) { - tc->c_qs = qs; - tc->c_ts = ts; - tc->c_wsid = wid; - tc->c_wsii = wid_s; - } - - if(qe > tc->c_qe || te > tc->c_te) { - tc->c_qe = qe; - tc->c_te = te; - tc->c_weid = wid; - tc->c_weii = wid_e; - } -} - -int64_t scan_single_wcigar(bit_extz_t *ez, int64_t csi, int64_t cei, int64_t cps, int64_t cpe, int64_t cts, int64_t cte, -int64_t tar_ps, int64_t tar_pe, int64_t tar_ts, int64_t tar_te) -{ - int64_t ci = csi, pi = cps, ti = cts, ws, we; - int64_t tot_err[2] = {0}, err[2] = {0}, ts1, te1; uint32_t cl; - uint16_t c, sset = 0, eset = 0; - while (ci < cei) { - ci = pop_trace(&(ez->cigar), ci, &c, &cl); - ws = pi; - if(c <= 1) { - pi+=cl; ti+=cl; - } else if(c == 2) {///more p - pi+=cl; - } else if(c == 3) { - ti+=cl; - } - we = pi; - // if(cps == 4489 && cpe == 16192) { - // fprintf(stderr, "[M::%s::ci->%ld] wp::[%ld, %ld), pi::%ld, ti::%ld, c::%u, cl::%u, tot_err::%ld\n", - // __func__, ci, ws, we, pi, ti, c, cl, tot_err[0]); - // } - if(we < tar_ps) {///not we <= ps - if(c != 0) tot_err[0] += cl; - continue; - } - if(ws > tar_pe) {///not ws >= pe - if(c != 0) tot_err[0] += cl; - break; - } - - if(!sset) { - if((tar_ps>=ws) && (tar_ps=ws) && (tar_ps<=we)) { - ts1 = ti - cl; - if(ts1 == tar_ts) { - err[0] = tot_err[0]; sset = 1; - } - } - } - - if(!eset) { - if((tar_pe>ws) && (tar_pe<=we)) { - if(c <= 1) { - te1 = ti - (we - tar_pe); - if(te1 == tar_te) { - if(c == 1) err[1] = tot_err[0] + (tar_pe - ws); - else err[1] = tot_err[0]; - eset = 1; - } - } else if(c == 2) {///more p - // te1 = ti - (we - tar_pe); - te1 = ti; - if(te1 == tar_te) { - err[1] = tot_err[0] + (tar_pe - ws); - eset = 1; - } - } else if(c == 3) { - te1 = ti-cl; - if(te1 == tar_te) { - err[1] = tot_err[0]; - eset = 1; - } - } - } - if((c == 3) && (tar_pe>=ws) && (tar_pe<=we)) { - te1 = ti; - if(te1 == tar_te) { - err[1] = tot_err[0] + cl; - eset = 1; - } - } - if(eset) break; - } - - if(c != 0) tot_err[0] += cl; - // fprintf(stderr, "[M::%s::ci->%ld] tot_err::%ld, c::%u\n", __func__, ci, tot_err[0], c); - } - return err[1] - err[0]; -} - - -int64_t scan_single_wcigar_toff_backward_backup(bit_extz_t *ez, int64_t csi, int64_t cei, int64_t cps, int64_t cpe, int64_t cts, int64_t cte, -int64_t tar_ps, int64_t tar_pe, int64_t tar_ts, int64_t tar_te) -{ - int64_t ci = cei-1, pi = cpe, ti = cte, wts, wte; - int64_t tot_err = 0, err[2] = {0}, ps1, pe1; - uint16_t c, sset = 0, eset = 0; uint32_t cl; - while (ci >= csi) { - ci = pop_trace_back(&(ez->cigar), ci, &c, &cl); - wte = ti; - if(c <= 1) { - pi-=cl; ti-=cl; - } else if(c == 2) {///more p - pi-=cl; - } else if(c == 3) { - ti-=cl; - } - wts = ti; - // if(tar_ts == 0 && tar_te == 14233 && cts == 0 && cte == 14233) { - // fprintf(stderr, "[M::%s::ci->%ld] wt::[%ld, %ld), pi::%ld, ti::%ld, c::%u, cl::%u, tot_err::%ld, err[0]::%ld, err[1]::%ld\n", - // __func__, ci, wts, wte, pi, ti, c, cl, tot_err[0], err[0], err[1]); - // } - if(wte < tar_ts) {///not we <= ps - if(c != 0) tot_err += cl; - break; - } - if(wts > tar_te) {///not ws >= pe - if(c != 0) tot_err += cl; - continue; - } - - if(!sset) { - // if(tar_ts == 19030 && tar_te == 31898 && cts == 19030 && cte == 31983) { - // fprintf(stderr, "+[M::%s::ci->%ld] wt::[%ld, %ld), tar_t::[%ld, %ld)\n", - // __func__, ci, wts, wte, tar_ts, tar_te); - // } - if((tar_ts>=wts) && (tar_ts=wts) && (tar_ts<=wte)) {///more p - // ps1 = pi; - // if(ps1 == tar_ps) { - // err[0] = tot_err[0] + cl; sset = 1; - // } - if(tar_ps >= pi && tar_ps < pi + cl) { - err[0] = tot_err + (pi + cl - tar_ps); - sset = 1; - } - } - if(sset) break; - } - - if(!eset) { - if((tar_te>wts) && (tar_te<=wte)) { - assert(c != 2); - if(c <= 1) { - pe1 = pi + (tar_te - wts); - // if(tar_ts == 19030 && tar_te == 31898 && cts == 19030 && cte == 31983) { - // fprintf(stderr, "-[M::%s::ci->%ld] wt::[%ld, %ld), tar_t::[%ld, %ld), pe1::%ld, tar_pe::%ld\n", - // __func__, ci, wts, wte, tar_ts, tar_te, pe1, tar_pe); - // } - if(pe1 == tar_pe) { - if(c == 1) err[1] = tot_err + (wte - tar_te); - else err[1] = tot_err; - eset = 1; - } - } else if(c == 3) {///more t - pe1 = pi; - if(pe1 == tar_pe) { - err[1] = tot_err + (wte - tar_te); - eset = 1; - } - } - } - - if((c == 2) && (tar_te>=wts) && (tar_te<=wte)) {///more p - // pe1 = pi; - // if(pe1 == tar_pe) { - // err[1] = tot_err[0] + cl; eset = 1; - // } - if(tar_pe >= pi && tar_pe < pi + cl) { - err[1] = tot_err + (pi + cl - tar_pe); - eset = 1; - } - } - } - - if(c != 0) tot_err += cl; - // fprintf(stderr, "[M::%s::ci->%ld] tot_err::%ld, c::%u\n", __func__, ci, tot_err[0], c); - } - return err[0] - err[1]; -} - - -int64_t scan_single_wcigar_toff_backward(bit_extz_t *ez, int64_t csi, int64_t cei, int64_t cps, int64_t cpe, int64_t cts, int64_t cte, -int64_t tar_ps, int64_t tar_pe, int64_t tar_ts, int64_t tar_te) -{ - int64_t ci = cei-1, pi = cpe, ti = cte, wts, wte; - int64_t e = 0, ps1, pe1; - uint16_t c, sset = 0, eset = 0, ff[2]; uint32_t cl; - while (ci >= csi) { - ci = pop_trace_back(&(ez->cigar), ci, &c, &cl); - wte = ti; - if(c <= 1) { - pi-=cl; ti-=cl; - } else if(c == 2) {///more p - pi-=cl; - } else if(c == 3) { - ti-=cl; - } - wts = ti; ff[0] = ff[1] = 0; - // if(tar_ts == 0 && tar_te == 14233 && cts == 0 && cte == 14233) { - // fprintf(stderr, "[M::%s::ci->%ld] wt::[%ld, %ld), pi::%ld, ti::%ld, c::%u, cl::%u, tot_err::%ld, err[0]::%ld, err[1]::%ld\n", - // __func__, ci, wts, wte, pi, ti, c, cl, tot_err[0], err[0], err[1]); - // } - if(wte < tar_ts) {///not we <= ps - if(c != 0) e += cl; - break; - } - if(wts > tar_te) {///not ws >= pe - if(c != 0) e += cl; - continue; - } - - if(!eset) { - if((tar_te>wts) && (tar_te<=wte)) { - assert(c != 2); - if(c <= 1) { - pe1 = pi + (tar_te - wts); - if(pe1 == tar_pe) { - if(c == 1) e = tar_te - wts; - else e = 0; - eset = 1; - } - } else if(c == 3) {///more t - pe1 = pi; - if(pe1 == tar_pe) { - e = tar_te - wts; - eset = 1; - } - } - } - - if((c == 2) && (tar_te==wts) && (tar_te==wte)) {///more p - if(tar_pe >= pi && tar_pe < pi + cl) { - e = tar_pe - pi; - eset = 1; - } - } - // if(eset) continue; - if(eset) ff[0] = 1; - } - - - if(!sset) { - // if(tar_ts == 19030 && tar_te == 31898 && cts == 19030 && cte == 31983) { - // fprintf(stderr, "+[M::%s::ci->%ld] wt::[%ld, %ld), tar_t::[%ld, %ld)\n", - // __func__, ci, wts, wte, tar_ts, tar_te); - // } - if((tar_ts>=wts) && (tar_ts= pi && tar_ps < pi + cl) { - e += (pi + cl - tar_ps); - sset = 1; - } - } - // if(sset) break; - if(sset) ff[1] = 1; - } - - if(ff[1]) break; - if(ff[0]) continue; - if(c!=0) e += cl; - // fprintf(stderr, "[M::%s::ci->%ld] tot_err::%ld, c::%u\n", __func__, ci, tot_err[0], c); - } - return e; -} - - -int64_t debug_aln_err(overlap_region *o, int64_t qs, int64_t qe, int64_t ts, int64_t te, double e_rate, -int64_t estz_err, const ul_idx_t *uref, char* qstr, UC_Read *tu, bit_extz_t *exz) -{ - int64_t ql = qe - qs, tl = te - ts, id = o->y_id, rev = o->y_pos_strand; - if((!ql) && (!tl)) return 0; - if((!ql) && (tl)) return tl; - if((ql) && (!tl)) return ql; - if(estz_err < 0) estz_err = -1; - if(hc_aln_exz_simi_adv(id, rev, uref, NULL, NULL, qstr, tu, qs, qe, ts, te, - qs, qe, ts, te, 0, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E, FORCE_CNS_L, estz_err, NULL, 0)) { - return exz->err; - } else { - return gen_err_unaligned(ql, tl); - } -} - -int64_t get_sub_cigar_err(ul_ov_t *aln, rtrace_t *tc, const ul_idx_t *uref, char* qstr, UC_Read *tu, overlap_region *o, bit_extz_t *exz, double e_rate, int64_t is_rev) -{ - int64_t k, q[2], t[2], cq[2], ct[2], ci[2], err, qwl, twl; - window_list *wa = o->w_list.a; bit_extz_t aux; - if(!is_rev) { - err = 0; q[0] = aln->qs; t[0] = aln->ts; - for (k = tc->c_wsid; k <= tc->c_weid; k++) { - q[1] = wa[k].x_start; t[1] = wa[k].y_start; - if(q[0] <= q[1] && t[0] <= t[1]) { - err += debug_aln_err(o, q[0], q[1], t[0], t[1], e_rate, k==tc->c_wsid?tc->pfx_e:-1, uref, qstr, tu, exz); - // fprintf(stderr, "-0-[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), err::%ld\n", - // __func__, k, q[0], q[1], t[0], t[1], err); - } - - cq[0] = q[0] = wa[k].x_start; cq[1] = q[1] = wa[k].x_end+1; - ct[0] = t[0] = wa[k].y_start; ct[1] = t[1] = wa[k].y_end+1; - ci[0] = 0; ci[1] = wa[k].clen; qwl = q[1] - q[0]; twl = t[1] - t[0]; - if(is_ualn_win(wa[k])) { - err += gen_err_unaligned(qwl, twl); - // fprintf(stderr, "-1-[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), err::%ld\n", - // __func__, k, q[0], q[1], t[0], t[1], err); - } else { - set_bit_extz_t(aux, (*o), k); - if(k == tc->c_wsid) { - cq[0] = tc->c_qs; ct[0] = tc->c_ts; ci[0] = tc->c_wsii; - q[0] = MAX((int32_t)aln->qs, tc->c_qs); - t[0] = MAX((int32_t)aln->ts, tc->c_ts); - } - if(k == tc->c_weid) { - cq[1] = tc->c_qe; ct[1] = tc->c_te; ci[1] = tc->c_weii; - q[1] = MIN((int32_t)aln->qe, tc->c_qe); - t[1] = MIN((int32_t)aln->te, tc->c_te); - } - // err += scan_single_wcigar(&aux, ci[0], ci[1], ct[0], ct[1], cq[0], cq[1], - // t[0], t[1], q[0], q[1]); - err += scan_single_wcigar_toff_backward(&aux, ci[0], ci[1], ct[0], ct[1], cq[0], cq[1], - t[0], t[1], q[0], q[1]); - // fprintf(stderr, "-2-[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), err::%ld, cq::[%ld, %ld), ct::[%ld, %ld)\n", - // __func__, k, q[0], q[1], t[0], t[1], err, cq[0], cq[1], ct[0], ct[1]); - } - q[0] = q[1]; t[0] = t[1]; - } - - q[1] = aln->qe; t[1] = aln->te; - if(q[0] <= q[1] && t[0] <= t[1]) { - err += debug_aln_err(o, q[0], q[1], t[0], t[1], e_rate, tc->sfx_e, uref, qstr, tu, exz); - // fprintf(stderr, "-3-[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), err::%ld\n", - // __func__, k, q[0], q[1], t[0], t[1], err); - } - } else { - err = 0; q[1] = aln->qe; t[1] = aln->te; - for (k = tc->c_weid; k >= tc->c_wsid; k--) { - q[0] = wa[k].x_end+1; t[0] = wa[k].y_end+1; - if(q[0] <= q[1] && t[0] <= t[1]) { - err += debug_aln_err(o, q[0], q[1], t[0], t[1], e_rate, k==tc->c_weid?tc->sfx_e:-1, uref, qstr, tu, exz); - } - - cq[0] = q[0] = wa[k].x_start; cq[1] = q[1] = wa[k].x_end+1; - ct[0] = t[0] = wa[k].y_start; ct[1] = t[1] = wa[k].y_end+1; - ci[0] = 0; ci[1] = wa[k].clen; qwl = q[1] - q[0]; twl = t[1] - t[0]; - if(is_ualn_win(wa[k])) { - err += gen_err_unaligned(qwl, twl); - } else { - set_bit_extz_t(aux, (*o), k); - if(k == tc->c_wsid) { - cq[0] = tc->c_qs; ct[0] = tc->c_ts; ci[0] = tc->c_wsii; - q[0] = MAX((int32_t)aln->qs, tc->c_qs); - t[0] = MAX((int32_t)aln->ts, tc->c_ts); - } - if(k == tc->c_weid) { - cq[1] = tc->c_qe; ct[1] = tc->c_te; ci[1] = tc->c_weii; - q[1] = MIN((int32_t)aln->qe, tc->c_qe); - t[1] = MIN((int32_t)aln->te, tc->c_te); - } - // err += scan_single_wcigar(&aux, ci[0], ci[1], ct[0], ct[1], cq[0], cq[1], - // t[0], t[1], q[0], q[1]); - err += scan_single_wcigar_toff_backward(&aux, ci[0], ci[1], ct[0], ct[1], cq[0], cq[1], - t[0], t[1], q[0], q[1]); - } - q[1] = q[0]; t[1] = t[0]; - } - - q[0] = aln->qs; t[0] = aln->ts; - if(q[0] <= q[1] && t[0] <= t[1]) { - err += debug_aln_err(o, q[0], q[1], t[0], t[1], e_rate, tc->pfx_e, uref, qstr, tu, exz); - } - } - // fprintf(stderr, "[M::%s::] err::%ld, aln_err::%u\n", __func__, err, aln->sec); - return err; -} - - -void gen_clip_win_err(overlap_region *o, int64_t qs, int64_t qe, int64_t ts, int64_t te, double e_rate, -int64_t estz_err, const ul_idx_t *uref, char* qstr, UC_Read *tu, bit_extz_t *exz) -{ - int64_t ql = qe - qs, tl = te - ts, id = o->y_id, rev = o->y_pos_strand; - exz->ts = qs; exz->te = qe-1; exz->ps = ts; exz->pe = te-1; - exz->cigar.n = 0; exz->thre = exz->err = INT32_MAX; - if((!ql) && (!tl)) { - exz->err = 0; return; - } - if((!ql) && (tl)) { - exz->err = tl; return; - } - if((ql) && (!tl)) { - exz->err = ql; return; - } - if(estz_err < 0) estz_err = -1; - if(hc_aln_exz_simi_adv(id, rev, uref, NULL, NULL, qstr, tu, qs, qe, ts, te, - qs, qe, ts, te, 0, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E, FORCE_CNS_L, estz_err, NULL, 1)) { - return; - } else { - exz->ts = qs; exz->te = qe-1; exz->ps = ts; exz->pe = te-1; - exz->cigar.n = 0; exz->thre = INT32_MAX; - exz->err = gen_err_unaligned(ql, tl); - return; - } -} - - -int64_t extract_sub_werr(bit_extz_t *ez, int64_t csi, int64_t cei, int64_t cps, int64_t cpe, int64_t cts, int64_t cte, -int64_t tar_ps, int64_t tar_pe, int64_t tar_ts, int64_t tar_te, int64_t spec_toff, rtrace_iter *idx) -{ - if(idx->toff >= tar_pe && idx->qoff >= tar_te) { - idx->coff = cei-1; - idx->toff = cpe; - idx->qoff = cte; - idx->cerr = 0; - } - if(!(is_align(*ez))) return INT32_MAX; - if(!(ez->cigar.n)) return (((double)(tar_te-spec_toff))/((double)(tar_te-tar_ts)))*ez->err; - - int64_t ci = idx->coff, pi = idx->toff, ti = idx->qoff, err = idx->cerr; - int64_t t[2], ci0, pi0, ti0, err0, re = INT32_MAX, wts, wte, ps1, pe1; - uint16_t c, sset = 0, eset = 0, ff[2]; uint32_t cl; - while (ci >= csi) { - ci0 = ci; pi0 = pi; ti0 = ti; err0 = err; - ci = pop_trace_back(&(ez->cigar), ci, &c, &cl); - wte = ti; - if(c <= 1) { - pi-=cl; ti-=cl; - } else if(c == 2) {///more p - pi-=cl; - } else if(c == 3) { - ti-=cl; - } - wts = ti; ff[0] = ff[1] = 0; - t[0] = wts; t[1] = wte; - // if(spec_toff == 118374) { - // fprintf(stderr, "+[M::%s::ci->%ld::cl->%u::c->%u] spec_toff::%ld, t::[%ld, %ld), p::[%ld, %ld), err0::%ld\n", - // __func__, ci, cl, c, spec_toff, ti, ti0, pi, pi0, err0); - // } - - if(wte < tar_ts) {///not we <= ps - if(c != 0) err += cl; - break; - } - if(wts > tar_te) {///not ws >= pe - if(c != 0) err += cl; - continue; - } - - if(!eset) { - if((tar_te>wts) && (tar_te<=wte)) { - assert(c != 2); - if(c <= 1) { - pe1 = pi + (tar_te - wts); - if(pe1 == tar_pe) { - if(c == 1) err = tar_te - wts; - else err = 0; - eset = 1; - } - } else if(c == 3) {///more t - pe1 = pi; - if(pe1 == tar_pe) { - err = tar_te - wts; - eset = 1; - } - } - } - - if((c == 2) && (tar_te>=wts) && (tar_te<=wte)) {///more p - if(tar_pe >= pi && tar_pe < pi + cl) { - err = tar_pe - pi; - eset = 1; - } - } - if(eset) { - ff[0] = 1; t[1] = tar_te; - } - } - - - if(!sset) { - if((tar_ts>=wts) && (tar_ts=wts) && (tar_ts<=wte)) {///more p - if(tar_ps >= pi && tar_ps < pi + cl) { - err += (pi + cl - tar_ps); - sset = 1; - } - } - if(sset) { - ff[1] = 1; t[0] = tar_ts; - } - } - - // if(spec_toff == 118374) { - // fprintf(stderr, "-[M::%s::ci->%ld::cl->%u::c->%u] spec_toff::%ld, t::[%ld, %ld), p::[%ld, %ld), err0::%ld\n", - // __func__, ci, cl, c, spec_toff, ti, ti0, pi, pi0, err0); - // } - if(spec_toff > t[1]) break; - - if((spec_toff >= t[0] && spec_toff < t[1]) || (spec_toff == t[0] && spec_toff == t[1])) { - re = err + (((!ff[1]) && (!ff[0]) && (c!=0))?cl:0); - if(c == 1 || c == 3) re -= (spec_toff - t[0]); - idx->coff = ci0; - idx->toff = pi0; - idx->qoff = ti0; - idx->cerr = err0; - // return re; - } - if(ff[1]) break; - if(ff[0]) continue; - if(c!=0) err += cl; - } - return re; -} - -//get error within [qe, ql) -int64_t get_rid_backward_cigar_err_back(rtrace_iter *it, ul_ov_t *aln, kv_rtrace_t *trace, rtrace_t *tc, -const ul_idx_t *uref, char* qstr, UC_Read *tu, overlap_region_alloc *ol, overlap_region *o, -bit_extz_t *exz, double e_rate, int64_t qs) -{ - if(qs == aln->qe) return 0; - if(!tc) tc = &(trace->a[aln->qn]); - if(!o) o = &(ol->list[tc->oid]); - - if(it->k == INT32_MAX) { - it->k = tc->c_weid; - it->q[1] = aln->qe; - it->t[1] = aln->te; - it->werr = it->cerr = 0; - it->qoff = aln->qe; - it->toff = aln->te; - it->coff = INT32_MAX; - clear_align(*exz); - exz->ps = exz->pe = exz->ts = exz->te = INT32_MAX; - } - window_list *wa = o->w_list.a; int64_t qwl, twl, sub_err; bit_extz_t aux; - assert(qs <= it->qoff); - - for (; it->k >= tc->c_wsid; it->k--) { - it->q[0] = wa[it->k].x_end+1; - it->t[0] = wa[it->k].y_end+1; - // if(qs == 166327) { - // fprintf(stderr, "-0-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld\n", - // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs); - // } - - if(it->qoff > it->q[0]) {///[it->qoff, ql) has been calculated - if(it->q[0] <= it->q[1] && it->t[0] <= it->t[1]) { - if((exz->ps != it->t[0]) || (exz->pe != it->t[1]) || (exz->ts != it->q[0]) || (exz->te == it->q[1])) { - ///calculate on-the-fly - gen_clip_win_err(o, it->q[0], it->q[1], it->t[0], it->t[1], e_rate, it->k==tc->c_weid?tc->sfx_e:-1, uref, qstr, tu, exz); - } - // fprintf(stderr, "-1-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld\n", - // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs); - if(qs >= it->q[0] && qs < it->q[1]) { - ///phrase cigar - sub_err = extract_sub_werr(exz, 0, exz->cigar.n, exz->ps, exz->pe+1, exz->ts, exz->te+1, - exz->ps, exz->pe+1, exz->ts, exz->te+1, qs, it); - if(qs == it->q[0]) { - it->werr += sub_err; sub_err = 0; - it->qoff = it->q[0]; it->toff = it->t[0]; - } - return it->werr+sub_err; - } - it->qoff = it->q[0]; - it->toff = it->t[0]; - it->werr += exz->err; - } - } - if(qs == it->qoff) return it->werr; - - it->cq[0] = it->q[0] = wa[it->k].x_start; it->cq[1] = it->q[1] = wa[it->k].x_end+1; - it->ct[0] = it->t[0] = wa[it->k].y_start; it->ct[1] = it->t[1] = wa[it->k].y_end+1; - it->ci[0] = 0; it->ci[1] = wa[it->k].clen; qwl = it->q[1] - it->q[0]; twl = it->t[1] - it->t[0]; - if(is_ualn_win(wa[it->k])) { - if(it->qoff > it->q[0]) { - // fprintf(stderr, "-2-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld\n", - // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs); - if(qs /**>=**/> it->q[0] && qs < it->q[1]) { - sub_err = ((((double)(it->q[1]-qs))/((double)(it->q[1]-it->q[0])))* - (gen_err_unaligned(qwl, twl))); - // if(qs == it->q[0]) { - // it->werr += sub_err; sub_err = 0; - // it->qoff = it->q[0]; it->toff = it->t[0]; - // } - return it->werr+sub_err; - } - it->qoff = it->q[0]; - it->toff = it->t[0]; - it->werr += gen_err_unaligned(qwl, twl); - } - } else { - set_bit_extz_t(aux, (*o), it->k); - if(it->k == tc->c_wsid) { - it->cq[0] = tc->c_qs; it->ct[0] = tc->c_ts; it->ci[0] = tc->c_wsii; - it->q[0] = MAX((int32_t)aln->qs, tc->c_qs); - it->t[0] = MAX((int32_t)aln->ts, tc->c_ts); - } - if(it->k == tc->c_weid) { - it->cq[1] = tc->c_qe; it->ct[1] = tc->c_te; it->ci[1] = tc->c_weii; - it->q[1] = MIN((int32_t)aln->qe, tc->c_qe); - it->t[1] = MIN((int32_t)aln->te, tc->c_te); - } - // fprintf(stderr, "-3-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld\n", - // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs); - if(it->qoff > it->q[0]) { - if(qs /**>=**/> it->q[0] && qs < it->q[1]) { - sub_err = extract_sub_werr(&aux, it->ci[0], it->ci[1], it->ct[0], it->ct[1], - it->cq[0], it->cq[1], it->t[0], it->t[1], it->q[0], it->q[1], qs, it); - // if(qs == it->q[0]) { - // it->werr += sub_err; sub_err = 0; - // it->qoff = it->q[0]; it->toff = it->t[0]; - // } - return it->werr + sub_err; - } - it->werr += extract_sub_werr(&aux, it->ci[0], it->ci[1], it->ct[0], it->ct[1], - it->cq[0], it->cq[1], it->t[0], it->t[1], it->q[0], it->q[1], it->q[0], it); - it->qoff = it->q[0]; - it->toff = it->t[0]; - } - } - - // if(qs == 166327) { - // fprintf(stderr, "-1-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld\n", - // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs); - // } - it->q[1] = it->q[0]; it->t[1] = it->t[0]; - if((qs == it->qoff)) { - if(it->k > tc->c_wsid) { - it->q[0] = wa[it->k-1].x_end+1; - it->t[0] = wa[it->k-1].y_end+1; - } else { - it->q[0] = aln->qs; - it->t[0] = aln->ts; - } - - // if(qs == 166327) { - // fprintf(stderr, "-2-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld\n", - // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs); - // fprintf(stderr, "-2-[M::%s::k->%ld] pre_inner_q::[%d, %d), pre_inner_t::[%d, %d)\n", - // __func__, it->k, wa[it->k-1].x_start, wa[it->k-1].x_end+1, wa[it->k-1].y_start, wa[it->k-1].y_end+1); - // } - ///otherwise there should be an indel at t - if(it->q[0] == it->q[1] && it->t[0] < it->t[1]) { - it->werr += it->t[1] - it->t[0]; continue; - } else { - return it->werr; - } - } - } - - it->q[0] = aln->qs; it->t[0] = aln->ts; - if(it->qoff > it->q[0]) { - if(it->q[0] <= it->q[1] && it->t[0] <= it->t[1]) { - if((exz->ps != it->t[0]) || (exz->pe != it->t[1]) || (exz->ts != it->q[0]) || (exz->te == it->q[1])) { - ///calculate on-the-fly - gen_clip_win_err(o, it->q[0], it->q[1], it->t[0], it->t[1], e_rate, tc->pfx_e, uref, qstr, tu, exz); - } - // fprintf(stderr, "-4-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld\n", - // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs); - if(qs >= it->q[0] && qs < it->q[1]) { - ///phrase cigar - sub_err = extract_sub_werr(exz, 0, exz->cigar.n, exz->ps, exz->pe+1, exz->ts, exz->te+1, - exz->ps, exz->pe+1, exz->ts, exz->te+1, qs, it); - if(qs == it->q[0]) { - it->werr += sub_err; sub_err = 0; - it->qoff = it->q[0]; it->toff = it->t[0]; - } - return it->werr+sub_err; - } - - it->qoff = it->q[0]; - it->toff = it->t[0]; - it->werr += exz->err; - } - } - if(it->k < tc->c_wsid) it->werr = aln->sec; - return it->werr; -} - - -//get error within [qe, ql) -int64_t get_rid_backward_cigar_err(rtrace_iter *it, ul_ov_t *aln, kv_rtrace_t *trace, rtrace_t *tc, -const ul_idx_t *uref, char* qstr, UC_Read *tu, overlap_region_alloc *ol, overlap_region *o, -bit_extz_t *exz, double e_rate, int64_t qs) -{ - //this is not right - // if(qs == aln->qe) return 0; - if(!tc) tc = &(trace->a[aln->qn]); - if(!o) o = &(ol->list[tc->oid]); - if(it->k < tc->c_wsid && qs > ((int64_t)aln->qs)) it->k = INT32_MAX; - - if(it->k == INT32_MAX) { - it->k = tc->c_weid; - it->q[1] = MAX(tc->c_qe, ((int64_t)aln->qe)); - it->t[1] = MAX(tc->c_te, ((int64_t)aln->te)); - it->qoff = MAX(tc->c_qe, ((int64_t)aln->qe)); - it->toff = MAX(tc->c_te, ((int64_t)aln->te)); - it->cur_qoff = MAX(tc->c_qe, ((int64_t)aln->qe)); - - it->werr = it->werr0 = it->cerr = 0; - it->f = 0; - it->coff = INT32_MAX; - clear_align(*exz); - exz->ps = exz->pe = exz->ts = exz->te = INT32_MAX; - } - // if(qs == 45766) { - // fprintf(stderr, "\n[M::%s::] q::[%u, %u), t::[%u, %u), tot_e::%u, cid::[%d, %d], cq::[%u, %u), ct::[%u, %u), pfx_e::%d, sfx_e::%d, mid_e::%d\n", - // __func__, aln->qs, aln->qe, aln->ts, aln->te, aln->sec, tc->c_wsid, tc->c_weid, - // tc->c_qs, tc->c_qe, tc->c_ts, tc->c_te, tc->pfx_e, tc->sfx_e, tc->mid_e); - // } - - window_list *wa = o->w_list.a; int64_t qwl, twl, sub_err; bit_extz_t aux; - assert(qs <= it->qoff); - if(qs == it->cur_qoff) return it->werr0; - - // if(qs == 166327) { - // fprintf(stderr, "\n-*-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld, cur_qoff::%ld, werr0::%ld\n", - // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs, - // it->cur_qoff, it->werr0); - // } - - for (; it->k >= tc->c_wsid; it->k--) { - it->q[0] = wa[it->k].x_end+1; - it->t[0] = wa[it->k].y_end+1; - // if(qs == 166327) { - // fprintf(stderr, "-0-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld, cur_qoff::%ld, werr0::%ld, f::%ld\n", - // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs, - // it->cur_qoff, it->werr0, it->f); - // } - ///now qs >= it->qoff -> qs >= q[0] - if(it->f == 0) { - if(it->qoff >= it->q[0]) {///[it->qoff, ql) has been calculated - if(it->q[0] <= it->q[1] && it->t[0] <= it->t[1]) { - if((exz->ps != it->t[0]) || (exz->pe != it->t[1]) || (exz->ts != it->q[0]) || (exz->te == it->q[1])) { - ///calculate on-the-fly - gen_clip_win_err(o, it->q[0], it->q[1], it->t[0], it->t[1], e_rate, it->k==tc->c_weid?tc->sfx_e:-1, uref, qstr, tu, exz); - } - sub_err = INT32_MAX; - ///if there are indels at either ends of t, qs == it->q[0] || qs == it->q[1] - if(qs >= it->q[0] && qs <= it->q[1]) { - ///phrase cigar - sub_err = extract_sub_werr(exz, 0, exz->cigar.n, exz->ps, exz->pe+1, exz->ts, exz->te+1, - exz->ps, exz->pe+1, exz->ts, exz->te+1, qs, it); - if(sub_err != INT32_MAX) {///find the coordinate for qs - if((it->cur_qoff != qs) || ((it->werr+sub_err) > it->werr0)) { - it->werr0 = it->werr+sub_err; - } - it->cur_qoff = qs; - if(qs > it->q[0] && qs <= it->q[1]) return it->werr0; - } else {///happen when qs == it->q[1] and no indels at the right end - it->qoff = it->q[1]; - it->toff = it->t[1]; - // assert(it->cur_qoff == qs); - it->cur_qoff = qs; - return it->werr0; - } - } - - if(qs <= it->q[0]) { - it->qoff = it->q[0]; - it->toff = it->t[0]; - it->werr += exz->err; - it->f = 1; - if((it->cur_qoff != it->q[0]) || (it->werr > it->werr0)) { - it->werr0 = it->werr; - } - it->cur_qoff = it->q[0]; - } - } else { - it->f = 1; - } - } else { - it->f = 1; - } - } - - it->cq[0] = it->q[0] = wa[it->k].x_start; it->cq[1] = it->q[1] = wa[it->k].x_end+1; - it->ct[0] = it->t[0] = wa[it->k].y_start; it->ct[1] = it->t[1] = wa[it->k].y_end+1; - it->ci[0] = 0; it->ci[1] = wa[it->k].clen; qwl = it->q[1] - it->q[0]; twl = it->t[1] - it->t[0]; - // if(qs == 166327) { - // fprintf(stderr, "-1-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld, cur_qoff::%ld, werr0::%ld, f::%ld\n", - // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], - // it->werr, qs, it->cur_qoff, it->werr0, it->f); - // } - if(is_ualn_win(wa[it->k])) { - if(it->qoff >= it->q[0] && it->f == 1) { - ///ignore indels of t at both ends; so ignore qs == it->q[0] and qs == it->q[1] - if(qs == it->q[1]) { - // assert(it->cur_qoff == qs); - it->cur_qoff = qs; - return it->werr0; - } - if(qs > it->q[0] && qs < it->q[1]) { - sub_err = ((((double)(it->q[1]-qs))/((double)(it->q[1]-it->q[0])))* - (gen_err_unaligned(qwl, twl))); - return it->werr+sub_err; - } - ///qs <= it->q[0] - it->qoff = it->q[0]; - it->toff = it->t[0]; - it->werr += gen_err_unaligned(qwl, twl); - it->f = 0; - if((it->cur_qoff != it->q[0]) || (it->werr > it->werr0)) { - it->werr0 = it->werr; - } - it->cur_qoff = it->q[0]; - } - } else { - set_bit_extz_t(aux, (*o), it->k); - if(it->k == tc->c_wsid) { - it->cq[0] = tc->c_qs; it->ct[0] = tc->c_ts; it->ci[0] = tc->c_wsii; - it->q[0] = MAX((int32_t)aln->qs, tc->c_qs); - it->t[0] = MAX((int32_t)aln->ts, tc->c_ts); - } - if(it->k == tc->c_weid) { - it->cq[1] = tc->c_qe; it->ct[1] = tc->c_te; it->ci[1] = tc->c_weii; - it->q[1] = MIN((int32_t)aln->qe, tc->c_qe); - it->t[1] = MIN((int32_t)aln->te, tc->c_te); - } - - if(it->qoff >= it->q[0] && it->f == 1) { - sub_err = INT32_MAX; - ///if there are indels at either ends of t, qs == it->q[0] || qs == it->q[1] - if(qs >= it->q[0] && qs <= it->q[1]) { - sub_err = extract_sub_werr(&aux, it->ci[0], it->ci[1], it->ct[0], it->ct[1], - it->cq[0], it->cq[1], it->t[0], it->t[1], it->q[0], it->q[1], qs, it); - // if(qs == 166327) { - // fprintf(stderr, "-3-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld, cur_qoff::%ld, werr0::%ld, f::%ld, sub_err::%ld\n", - // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs, - // it->cur_qoff, it->werr0, it->f, sub_err); - // } - if(sub_err != INT32_MAX) {///find the coordinate for qs - if((it->cur_qoff != qs) || ((it->werr+sub_err) > it->werr0)) { - it->werr0 = it->werr+sub_err; - } - it->cur_qoff = qs; - if(qs > it->q[0] && qs <= it->q[1]) return it->werr0; - } else {///happen when qs == it->q[1] and no indels at the right end - it->qoff = it->q[1]; - it->toff = it->t[1]; - // if(!(it->cur_qoff == qs)) { - // fprintf(stderr, "\n[M::%s::] q::[%u, %u), t::[%u, %u), tot_e::%u, cid::[%d, %d], cq::[%u, %u), ct::[%u, %u), pfx_e::%d, sfx_e::%d, mid_e::%d\n", - // __func__, aln->qs, aln->qe, aln->ts, aln->te, aln->sec, tc->c_wsid, tc->c_weid, - // tc->c_qs, tc->c_qe, tc->c_ts, tc->c_te, tc->pfx_e, tc->sfx_e, tc->mid_e); - // } - // assert(it->cur_qoff == qs); - it->cur_qoff = qs; - return it->werr0; - } - } - // if(qs == 166327) { - // fprintf(stderr, "-4-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld, cur_qoff::%ld, werr0::%ld, f::%ld, sub_err::%ld\n", - // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs, - // it->cur_qoff, it->werr0, it->f, sub_err); - // } - ///qs <= it->q[0] - if(qs <= it->q[0]) { - it->werr += ((qs==it->q[0])?(sub_err):(extract_sub_werr(&aux, it->ci[0], it->ci[1], it->ct[0], it->ct[1], - it->cq[0], it->cq[1], it->t[0], it->t[1], it->q[0], it->q[1], it->q[0], it))); - it->qoff = it->q[0]; - it->toff = it->t[0]; - it->f = 0; - if((it->cur_qoff != it->q[0]) || (it->werr > it->werr0)) { - it->werr0 = it->werr; - } - it->cur_qoff = it->q[0]; - } - } - } - it->q[1] = it->q[0]; it->t[1] = it->t[0]; - // if(qs == 166327) { - // fprintf(stderr, "-#-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld, cur_qoff::%ld, werr0::%ld, f::%ld\n", - // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs, - // it->cur_qoff, it->werr0, it->f); - // } - } - - it->q[0] = aln->qs; it->t[0] = aln->ts; - if(it->qoff >= it->q[0] && it->f == 0) { - if(it->q[0] <= it->q[1] && it->t[0] <= it->t[1]) { - if((exz->ps != it->t[0]) || (exz->pe != it->t[1]) || (exz->ts != it->q[0]) || (exz->te == it->q[1])) { - ///calculate on-the-fly - gen_clip_win_err(o, it->q[0], it->q[1], it->t[0], it->t[1], e_rate, tc->pfx_e, uref, qstr, tu, exz); - } - sub_err = INT32_MAX; - ///if there are indels at either ends of t, qs == it->q[0] || qs == it->q[1] - if(qs >= it->q[0] && qs <= it->q[1]) { - ///phrase cigar - sub_err = extract_sub_werr(exz, 0, exz->cigar.n, exz->ps, exz->pe+1, exz->ts, exz->te+1, - exz->ps, exz->pe+1, exz->ts, exz->te+1, qs, it); - if(sub_err != INT32_MAX) {///find the coordinate for qs - if((it->cur_qoff != qs) || ((it->werr+sub_err) > it->werr0)) { - it->werr0 = it->werr+sub_err; - } - it->cur_qoff = qs; - if(qs > it->q[0] && qs <= it->q[1]) return it->werr0; - } else {///happen when qs == it->q[1] and no indels at the right end - it->qoff = it->q[1]; - it->toff = it->t[1]; - // assert(it->cur_qoff == qs); - it->cur_qoff = qs; - return it->werr0; - } - } - - if(qs <= it->q[0]) { - it->qoff = it->q[0]; - it->toff = it->t[0]; - it->werr += exz->err; - it->f = 1; - if((it->cur_qoff != it->q[0]) || (it->werr > it->werr0)) { - it->werr0 = it->werr; - } - it->cur_qoff = it->q[0]; - } - } - } - // if(it->k < tc->c_wsid) it->werr = aln->sec; - return it->werr; -} - -void debug_backtrace_step_err(uint64_t rid, ul_ov_t *aln, rtrace_t *tc, const ul_idx_t *uref, char* qstr, UC_Read *tu, overlap_region *o, bit_extz_t *exz, double e_rate) -{ - // if(aln->qs == 0 && aln->qe == 3013 && aln->ts == 28965 && aln->te == 31993) { - // fprintf(stderr, "\n[M::%s::] q::[%u, %u), t::[%u, %u), tot_e::%u, cid::[%d, %d], cq::[%u, %u), ct::[%u, %u), pfx_e::%d, sfx_e::%d, mid_e::%d\n", - // __func__, aln->qs, aln->qe, aln->ts, aln->te, aln->sec, tc->c_wsid, tc->c_weid, - // tc->c_qs, tc->c_qe, tc->c_ts, tc->c_te, tc->pfx_e, tc->sfx_e, tc->mid_e); - int64_t k, err, qs = aln->qs, qe = aln->qe, err0; rtrace_iter it; - k = qe; it.k = INT32_MAX; - err0 = get_rid_backward_cigar_err(&it, aln, NULL, tc, uref, qstr, tu, NULL, o, exz, e_rate, k); - err = get_rid_backward_cigar_err(&it, aln, NULL, tc, uref, qstr, tu, NULL, o, exz, e_rate, k); - assert(err == err0); - for (k = qe, it.k = INT32_MAX, err0 = 0; k >= qs; k-=8) { - err = get_rid_backward_cigar_err(&it, aln, NULL, tc, uref, qstr, tu, NULL, o, exz, e_rate, k); - // if(!(err >= 0 && err >= err0)) { - // fprintf(stderr, "[M::%s::rid->%lu] q::[%u, %u), t::[%u, %u), tot_e::%u, cid::[%d, %d], cq::[%u, %u), ct::[%u, %u)\n", - // __func__, rid, aln->qs, aln->qe, aln->ts, aln->te, aln->sec, tc->c_wsid, tc->c_weid, - // tc->c_qs, tc->c_qe, tc->c_ts, tc->c_te); - // fprintf(stderr, "[M::%s::] q::[%ld, %ld), err::%ld, err0::%ld\n", __func__, k, qe, err, err0); - // } - // fprintf(stderr, "[M::%s::] q::[%ld, %ld), err::%ld\n", __func__, k, qe, err); - assert(err >= 0 && err >= err0); - err0 = err; - } - k = qs; - err = get_rid_backward_cigar_err(&it, aln, NULL, tc, uref, qstr, tu, NULL, o, exz, e_rate, k); - // if(!(err >= 0 && err >= err0)) { - // fprintf(stderr, "[M::%s::rid->%lu] q::[%u, %u), t::[%u, %u), tot_e::%u, cid::[%d, %d], cq::[%u, %u), ct::[%u, %u)\n", - // __func__, rid, aln->qs, aln->qe, aln->ts, aln->te, aln->sec, tc->c_wsid, tc->c_weid, - // tc->c_qs, tc->c_qe, tc->c_ts, tc->c_te); - // fprintf(stderr, "[M::%s::] q::[%ld, %ld), err::%ld, err0::%ld\n", __func__, k, qe, err, err0); - // } - // fprintf(stderr, "[M::%s::] q::[%ld, %ld), err::%ld, exz->err::%d, exz->cigar.n::%d\n", - // __func__, qs, qe, err, exz->err, (int32_t)exz->cigar.n); - assert(err >= 0 && err >= err0); - if(!(err == (int64_t)aln->sec)) { - fprintf(stderr, "[M::%s::rid->%lu] q::[%u, %u), t::[%u, %u), tot_e::%u, cid::[%d, %d], cq::[%u, %u), ct::[%u, %u)\n", - __func__, rid, aln->qs, aln->qe, aln->ts, aln->te, aln->sec, tc->c_wsid, tc->c_weid, - tc->c_qs, tc->c_qe, tc->c_ts, tc->c_te); - fprintf(stderr, "[M::%s::] aln->sec::%u, err::%ld\n", __func__, aln->sec, err); - } - assert(err == (int64_t)aln->sec); - // } -} - -///[wsid, weid) && [ts, te) -void gen_raln(const ul_idx_t *uref, char* qstr, UC_Read *tu, overlap_region *o, bit_extz_t *exz, -int64_t wsid, int64_t weid, int64_t ts, int64_t te, int64_t ql, int64_t id, int64_t rev, double e_rate, -uint64_t rid, rtrace_t *tc, ul_ov_t *res) -{ - // fprintf(stderr, "\n[M::%s::] ii::[%ld, %ld), t::[%ld, %ld), ql::%ld, id::%ld\n", - // __func__, wsid, weid, ts, te, ql, id); - int64_t k, q[2], t[2], c[2], ct[2], cq[2], mode, qwl, twl, aln_e = 0, cur_e, is_aln; - bit_extz_t aux; window_list *wa = o->w_list.a; - memset(res, 0, sizeof((*res))); - res->qs = res->ts = UINT32_MAX; res->qe = res->te = 0; - memset(tc, 0, sizeof((*tc))); - tc->c_qs = tc->c_ts = INT32_MAX; tc->c_qe = tc->c_te = -1; - tc->pfx_e = tc->mid_e = tc->sfx_e = 0; - - q[0] = q[1] = -1; t[0] = ts; t[1] = te;///[q[0], q[1]) && [t[0], t[1]) - for (k = wsid; k < weid; k++) { - q[1] = wa[k].x_start; t[1] = wa[k].y_start; - mode = - 1; cur_e = 0; is_aln = 1; - // if(rid == 53 && id == 6) { - // fprintf(stderr, "0-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld)\n", __func__, k, q[0], q[1], t[0], t[1]); - // } - //before window; there are gaps before the window that need to be filled - if(t[0] < t[1] && q[0] < q[1]) { - if(q[0] < 0) { ///backward extension - mode = 2; - adjust_ext_offset_fixed_t(&(q[0]), &(q[1]), &(t[0]), &(t[1]), 0, q[1], t[0], t[1], 0, mode); - } else { - mode = 0; - } - // if(rid == 53 && id == 6) { - // fprintf(stderr, "1-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", - // __func__, k, q[0], q[1], t[0], t[1], mode); - // } - qwl = q[1] - q[0]; twl = t[1] - t[0]; - if(qwl || twl) { - if(qwl == 0 && twl > 0) { - cur_e = twl; - // tot_e += twl; - } else if(twl == 0 && qwl > 0) { - cur_e = qwl; - // tot_e += qwl; - } else { - if(hc_aln_exz_simi_adv(id, rev, uref, NULL, NULL, qstr, tu, q[0], q[1], t[0], t[1], - 0, ql, ts, te, mode, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E, FORCE_CNS_L, -1, NULL, 0)) { - cur_e = exz->err; - // tot_e += exz->err; - q[0] = exz->ts; q[1] = exz->te + 1; t[0] = exz->ps; t[1] = exz->pe + 1; - // if(rid == 53 && id == 6) { - // fprintf(stderr, "2-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), mode::%ld, cur_e::%ld\n", - // __func__, k, q[0], q[1], t[0], t[1], mode, cur_e); - // } - } else { - cur_e = gen_err_unaligned(qwl, twl); is_aln = 0; - // tot_e += gen_err_unaligned(qwl, twl); - // if(rid == 53 && id == 6) { - // fprintf(stderr, "2-b[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), mode::%ld, cur_e::%ld\n", - // __func__, k, q[0], q[1], t[0], t[1], mode, cur_e); - // } - } - } - aln_e += cur_e; - update_ul_ov_t_coor((*res), q[0], q[1], t[0], t[1]); - if(k == wsid) tc->pfx_e = cur_e*(is_aln?1:-1); - } - } - - ///within window - q[0] = wa[k].x_start; t[0] = wa[k].y_start; - q[1] = wa[k].x_end+1; t[1] = wa[k].y_end+1; - qwl = q[1] - q[0]; twl = t[1] - t[0]; cur_e = 0; is_aln = 1; - // if(rid == 53 && id == 6) { - // fprintf(stderr, "3-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld)\n", - // __func__, k, q[0], q[1], t[0], t[1]); - // } - if((ts <= t[0]) && (te >= t[1])) {///cover the whole window - if(!is_ualn_win(wa[k])) cur_e = wa[k].error; - else cur_e = gen_err_unaligned(qwl, twl); - update_trace_idx(tc, k, 0, wa[k].clen, q[0], q[1], t[0], t[1]); - // if(rid == 53 && id == 6) { - // fprintf(stderr, "4-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld\n", - // __func__, k, q[0], q[1], t[0], t[1], cur_e); - // } - } else {///te < t[1]->cover a part of window - if(ts > t[0]) { - t[0] = ts; q[0] = -1; - } - if(te < t[1]) { - t[1] = te; q[1] = -1; - } - - if((q[0] != -1) && (q[1] != -1)) { - mode = 0;//global - } else if((q[0] != -1) && (q[1] == -1)) { - mode = 1;///forward extension - } else if((q[0] == -1) && (q[1] != -1)) { - mode = 2;///backward extension - } else { - mode = 3;///no primary hit within [ibeg, iend] - } - // if(rid == 53 && id == 6) { - // fprintf(stderr, "5-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", - // __func__, k, q[0], q[1], t[0], t[1], mode); - // } - if(!is_ualn_win(wa[k])) {///scan cigar by the coordinates of y/t - set_bit_extz_t(aux, (*o), k); - cur_e = hc_aln_exz_by_exist_cigar_with_p(&aux, mode, t[0], t[1], &(q[0]), &(q[1]), - &(c[0]), &(c[1]), &(ct[0]), &(ct[1]), &(cq[0]), &(cq[1])); - update_trace_idx(tc, k, c[0], c[1], cq[0], cq[1], ct[0], ct[1]); - // if(rid == 53 && id == 6) { - // fprintf(stderr, "6-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld, c_q::[%ld, %ld), c_t::[%ld, %ld)\n", - // __func__, k, q[0], q[1], t[0], t[1], cur_e, cq[0], cq[1], ct[0], ct[1]); - // } - } else { - assert(mode == 1 || mode == 2); - adjust_ext_offset_fixed_t(&(q[0]), &(q[1]), &(t[0]), &(t[1]), q[0], q[1], t[0], t[1], 0, mode); - qwl = q[1] - q[0]; twl = t[1] - t[0]; - // if(rid == 53 && id == 6) { - // fprintf(stderr, "7-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld\n", - // __func__, k, q[0], q[1], t[0], t[1], cur_e); - // } - if(qwl || twl) { - if(qwl == 0 && twl > 0) { - cur_e = twl; - } else if(twl == 0 && qwl > 0) { - cur_e = qwl; - } else { - if(hc_aln_exz_simi_adv(id, rev, uref, NULL, NULL, qstr, tu, q[0], q[1], t[0], t[1], - 0, ql, ts, te, mode, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E, FORCE_CNS_L, -1, NULL, 0)) { - cur_e = exz->err; - q[0] = exz->ts; q[1] = exz->te + 1; t[0] = exz->ps; t[1] = exz->pe + 1; - // if(rid == 53 && id == 6) { - // fprintf(stderr, "7-b[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld\n", - // __func__, k, q[0], q[1], t[0], t[1], cur_e); - // } - } else { - cur_e = gen_err_unaligned(qwl, twl); is_aln = 0; - // if(rid == 53 && id == 6) { - // fprintf(stderr, "7-c[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld\n", - // __func__, k, q[0], q[1], t[0], t[1], cur_e); - // } - } - } - tc->sfx_e = cur_e*(is_aln?1:-1); - } - } - } - aln_e += cur_e; - update_ul_ov_t_coor((*res), q[0], q[1], t[0], t[1]); - - q[0] = q[1]; t[0] = t[1]; - } - // if(ts == 8087 && te == 28530 && ql == 127662) { - // fprintf(stderr, "8-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld, ql::%ld\n", - // __func__, k, q[0], q[1], t[0], t[1], cur_e, ql); - // } - if(q[0] >= 0 && q[0] < ql) {///forward extension - q[1] = ql; t[1] = te; cur_e = 0; mode = 1;///forward extension - adjust_ext_offset_fixed_t(&(q[0]), &(q[1]), &(t[0]), &(t[1]), q[0], q[1], t[0], t[1], 0, mode); - qwl = q[1] - q[0]; twl = t[1] - t[0]; is_aln = 1; - // if(rid == 53 && id == 6) { - // fprintf(stderr, "9-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld\n", - // __func__, k, q[0], q[1], t[0], t[1], cur_e); - // } - if(qwl || twl) { - if(qwl == 0 && twl > 0) { - cur_e = twl; - } else if(twl == 0 && qwl > 0) { - cur_e = qwl; - } else { - if(hc_aln_exz_simi_adv(id, rev, uref, NULL, NULL, qstr, tu, q[0], q[1], t[0], t[1], - 0, ql, ts, te, mode, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E, FORCE_CNS_L, -1, NULL, 0)) { - cur_e = exz->err; - q[0] = exz->ts; q[1] = exz->te + 1; t[0] = exz->ps; t[1] = exz->pe + 1; - // if(rid == 53 && id == 6) { - // fprintf(stderr, "9-b[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld, thre::%d\n", - // __func__, k, q[0], q[1], t[0], t[1], cur_e, exz->thre); - // } - } else { - cur_e = gen_err_unaligned(qwl, twl); is_aln = 0; - // if(rid == 53 && id == 6) { - // fprintf(stderr, "9-c[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld\n", - // __func__, k, q[0], q[1], t[0], t[1], cur_e); - // } - } - } - update_ul_ov_t_coor((*res), q[0], q[1], t[0], t[1]); - tc->sfx_e = cur_e*(is_aln?1:-1); - } - aln_e += cur_e; - } - tc->mid_e = aln_e - abs(tc->pfx_e) - abs(tc->sfx_e); - if(aln_e <= MAX_SEC_ERR) res->sec = aln_e; - else res->sec = MAX_SEC_ERR; - // fprintf(stderr, "10-a[M::%s::k->%ld] q::[%u, %u), t::[%u, %u), tot_e::%u\n\n", - // __func__, k, res->qs, res->qe, res->ts, res->te, res->sec); - - - // aln_e = get_sub_cigar_err(res, tc, uref, qstr, tu, o, exz, e_rate); - // if(aln_e != (int64_t)res->sec) { - // fprintf(stderr, "[M::%s::rid->%lu] tot_e::%u, aln_e::%ld, id::%ld\n", - // __func__, rid, res->sec, aln_e, id); - // exit(1); - // } - - // assert(aln_e == get_sub_cigar_err(res, tc, uref, qstr, tu, o, exz, e_rate, 0)); - // assert(aln_e == get_sub_cigar_err(res, tc, uref, qstr, tu, o, exz, e_rate, 1)); - // debug_backtrace_step_err(rid, res, tc, uref, qstr, tu, o, exz, e_rate); - // if(rid == 42 && res->sec == 706 && res->qs == 63686 && res->qe == 75773 - // && res->ts == 9404 && res->te == 21663) { - // debug_backtrace_step_err(rid, res, tc, uref, qstr, tu, o, exz, e_rate); - // } -} - -void prt_aln_w(overlap_region *o) -{ - uint64_t k; - for (k = 0; k < o->w_list.n; k++) { - fprintf(stderr, "[M::%s::aln->%u] q::[%d, %d), t::[%d, %d), err::%d\n", - __func__, ((o->w_list.a[k].y_end != -1) && (!(is_ualn_win(o->w_list.a[k])))), - o->w_list.a[k].x_start, o->w_list.a[k].x_end+1, - o->w_list.a[k].y_start, o->w_list.a[k].y_end+1, o->w_list.a[k].error); - } -} - -///[ts, te) -> this is the reverse coordinates of t, not the original coordinates of t -int64_t extract_subov_cigar(const ul_idx_t *uref, char* qstr, UC_Read *tu, bit_extz_t *exz, -int64_t ts0, int64_t te0, overlap_region *o, double o_rate, int64_t *in_k, int64_t ql, -double e_rate, uint64_t rid, uint64_t dbg_id, rtrace_t *trace, ul_ov_t *res) -{ - int64_t rev = o->y_pos_strand, t[2], q[2], k = 0, wts, wte, ii[2]; - int64_t wn = o->w_list.n, os, oe, ovlp, salnl = 0; - t[0] = ts0; t[1] = te0; if(wn <= 0) return 0; - - if(in_k) k = *in_k; - if(k < 0) k = 0; if(k >= wn) k = wn-1; - for(; k < wn && t[0] > o->w_list.a[k].y_end; k++); - if(k < 0) k = 0; if(k >= wn) k = wn-1; - for(; k >= 0 && t[0] < o->w_list.a[k].y_start; k--); - ///qs <= o->w_list.a[k].x_end && qs >= o->w_list.a[k].x_start - if(k < 0) k = 0; - if(in_k) *in_k = k; - - for (ii[0] = INT32_MAX, ii[1] = -1; k < wn; k++) { - wts = o->w_list.a[k].y_start; - wte = o->w_list.a[k].y_end + 1; - if(wts >= t[1]) break; - if((o->w_list.a[k].y_end == -1) || (is_ualn_win(o->w_list.a[k]))) continue; - os = MAX(t[0], wts); oe = MIN(t[1], wte); - ovlp = ((oe>os)? (oe-os):0); - if(!ovlp) continue; - if(k < ii[0]) ii[0] = k; - if(k > ii[1]) ii[1] = k; - salnl += ovlp; - } - // if(dbg_id == 5525) { - // prt_aln_w(o); - // fprintf(stderr, "[M::%s::aln->%ld] ii::[%ld, %ld), q_aln0::[%d, %d), t0::[%ld, %ld)\n", - // __func__, salnl, ii[0], ii[1]+1, o->w_list.a[ii[0]].x_start, o->w_list.a[ii[0]].x_end+1, - // ts0, te0); - // } - if((!salnl) || (ii[0] == INT32_MAX) || (ii[1] < 0)) return 0; - if((ii[0] == ii[1]) && (is_ualn_win(o->w_list.a[ii[0]]))) return 0; - //[ii[0], ii[1]] - win_boundary_offset(o->w_list.a, o->w_list.n, ii[0], ts0, ql, &(q[0]), &(t[0])); - win_boundary_offset(o->w_list.a, o->w_list.n, ii[1], te0-1, ql, &(q[1]), &(t[1])); - q[1]++; t[1]++; - // if(dbg_id == 5525) { - // fprintf(stderr, "[M::%s::aln->%ld] ii::[%ld, %ld), q::[%ld, %ld), t::[%ld, %ld)\n", - // __func__, salnl, ii[0], ii[1]+1, q[0], q[1], t[0], t[1]); - // } - if(salnl < ((t[1]-t[0])*o_rate)) return 0; - - gen_raln(uref, qstr, tu, o, exz, ii[0], ii[1]+1, ts0, te0, ql, o->y_id, rev, e_rate, rid, trace, res); - assert(res->ts >= ts0 && res->te <= te0 && res->qs >= 0 && res->qe <= ql); - double simi_thre = e_rate + MIN(r_simi_w, (e_rate/2)); - if((res->sec <= ((res->qe-res->qs)*simi_thre)) && (res->sec <= ((res->te-res->ts)*simi_thre))) { - return 1; - } else { - return 0; - } -} - - -uint64_t gen_sub_ov_adv_cigar(const ul_idx_t *udb, overlap_region* o, char* qstr, UC_Read *tu, -bit_extz_t *exz, int64_t ql, double o_rate, double e_rate, utg_ct_t *ct_a, uint64_t ct_n, -uint64_t sid, uint64_t oid, kv_rtrace_t *trace, kv_ul_ov_t *res) -{ - uint64_t ts, te, i, l, rn = res->n, rev = o->y_pos_strand, s, e, rid, t[2]; - ma_utg_t *u = &(udb->ug->u.a[o->y_id]); ul_ov_t z; rtrace_t tz; int64_t k; - if(!rev){ - ts = o->y_pos_s; te = o->y_pos_e + 1; k = 0; - } else { - ts = u->len - (o->y_pos_e+1); te = u->len - o->y_pos_s; - k = ((int64_t)o->w_list.n)-1; if(k < 0) k = 0; - } - - if(!ct_a) { - for (i = l = 0; i < u->n; i++) { - rid = u->a[i]>>33; - s = l; e = l + Get_READ_LENGTH(R_INF, rid);///note: [s, e) are pos of t - l += (uint32_t)u->a[i]; - if(e <= ts) continue; - if(s >= te) break; - t[0] = (rev?(u->len-e):(s)); t[1] = (rev?(u->len-s):(e)); - if(extract_subov_cigar(udb, qstr, tu, exz, t[0], t[1], o, o_rate, &k, ql, e_rate, sid, rid, &tz, &z)) { - tz.oid = oid; - z.ts -= t[0]; z.te -= t[0]; - z.rev = ((o->y_pos_strand == ((u->a[i]>>32)&1))?0:1); - if(z.rev) { - t[0] = z.ts; t[1] = z.te; - z.ts = Get_READ_LENGTH(R_INF, rid) - t[1]; - z.te = Get_READ_LENGTH(R_INF, rid) - t[0]; - } - ///non-contained read at the unitg - z.el = 1; - ///rid - z.tn = rid; - ///i-th read at the unitig - z.qn = trace->n; - kv_push(ul_ov_t, *res, z); - kv_push(rtrace_t, *trace, tz); - // fprintf(stderr, "+[M::%s::rid->%lu::rev->%lu] utg_t::[%ld, %ld), ql::%ld\n", - // __func__, rid, rev, t[0], t[1], ql); - // fprintf(stderr, "+[M::%s::%.*s::%c] q::[%u, %u), ql::%ld, t::[%u, %u), tl::%lu, err::%u\n", - // __func__, (int)Get_NAME_LENGTH(R_INF, z.tn), Get_NAME(R_INF, z.tn), - // "+-"[z.rev], z.qs, z.qe, ql, z.ts, z.te, Get_READ_LENGTH(R_INF, z.tn), z.sec); - } - } - } else { - for (i = 0; i < ct_n; i++) { - rid = ct_a[i].x>>1; s = ct_a[i].s; e = ct_a[i].e; - if(e <= ts) continue; - if(s >= te) break; - t[0] = (rev?(u->len-e):(s)); t[1] = (rev?(u->len-s):(e)); - if(extract_subov_cigar(udb, qstr, tu, exz, t[0], t[1], o, o_rate, &k, ql, e_rate, sid, rid, &tz, &z)) { - tz.oid = oid; - z.ts -= t[0]; z.te -= t[0]; - z.rev = ((o->y_pos_strand == (ct_a[i].x&1))?0:1); - if(z.rev) { - t[0] = z.ts; t[1] = z.te; - z.ts = Get_READ_LENGTH(R_INF, rid) - t[1]; - z.te = Get_READ_LENGTH(R_INF, rid) - t[0]; - } - ///contained read at the unitg - z.el = 0; - ///rid - z.tn = rid; - ///i-th read at the unitig - z.qn = trace->n; - kv_push(ul_ov_t, *res, z); - kv_push(rtrace_t, *trace, tz); - // fprintf(stderr, "-[M::%s::rid->%lu::rev->%lu] utg_t::[%ld, %ld), ql::%ld\n", - // __func__, rid, rev, t[0], t[1], ql); - // fprintf(stderr, "-[M::%s::%.*s::%c] q::[%u, %u), ql::%ld, t::[%u, %u), tl::%lu, err::%u\n", - // __func__, (int)Get_NAME_LENGTH(R_INF, z.tn), Get_NAME(R_INF, z.tn), - // "+-"[z.rev], z.qs, z.qe, ql, z.ts, z.te, Get_READ_LENGTH(R_INF, z.tn), z.sec); - } - } - } - return res->n-rn; -} - -uint64_t win_cluster_fliter(window_list *wa, uint64_t wn, uint64_t min_ovlp, double o_rate) -{ - uint64_t k, ws = (uint64_t)-1, we = (uint64_t)-1, aln_ol, sk; - for (k = 0; k < wn && wa[k].y_end == -1; k++); - if(k >= wn) return 0; ws = wa[k].x_start; - - for (aln_ol = 0, sk = k; k < wn; k++) { - we = wa[k].x_end+1; - if(wa[k].y_end != -1) { - aln_ol += wa[k].x_end+1-wa[k].x_start; - } - if(we >= ws + min_ovlp) break; - } - // fprintf(stderr, "[M::%s::] aln_ol::%lu, w::[%lu, %lu), min_ovlp::%lu, o_rate::%f\n", - // __func__, aln_ol, ws, we, min_ovlp, o_rate); - if((aln_ol >= (we-ws)*o_rate) && (we-ws >= min_ovlp)) return 1; - - for (k++; k < wn; k++) { - we = wa[k].x_end+1; - if(wa[k].y_end != -1) { - aln_ol += wa[k].x_end+1-wa[k].x_start; - } - for (; sk < wn && wa[sk].x_start + min_ovlp < we; sk++) { - if(wa[sk].y_end != -1) aln_ol -= wa[sk].x_end+1-wa[sk].x_start; - } - ws = wa[sk].x_start; - // fprintf(stderr, "+[M::%s::] aln_ol::%lu, w::[%lu, %lu), min_ovlp::%lu, o_rate::%f, k::[%lu, %lu)\n", - // __func__, aln_ol, ws, we, min_ovlp, o_rate, sk, k); - if((aln_ol >= (we-ws)*o_rate) && (we-ws >= min_ovlp)) return 1; - if((sk > 0) && (we-ws < min_ovlp)) { - sk--; if(wa[sk].y_end != -1) aln_ol += wa[sk].x_end+1-wa[sk].x_start; - ws = wa[sk].x_start; - // fprintf(stderr, "-[M::%s::] aln_ol::%lu, w::[%lu, %lu), min_ovlp::%lu, o_rate::%f, k::[%lu, %lu)\n", - // __func__, aln_ol, ws, we, min_ovlp, o_rate, sk, k); - if((aln_ol >= (we-ws)*o_rate) && (we-ws >= min_ovlp)) return 1; - } - } - return 0; -} - - -void print_aln_windows(overlap_region *z) -{ - uint64_t k; - for (k = 0; k < z->w_list.n; k++) { - fprintf(stderr, "[M::%s::] q::[%u, %u), t::[%u, %u), err::%d\n", __func__, - z->w_list.a[k].x_start, z->w_list.a[k].x_end+1, - z->w_list.a[k].y_start, z->w_list.a[k].y_end+1, - z->w_list.a[k].error); - } -} - -uint64_t ul_local_aln(overlap_region *z, Candidates_list *cl, const ul_idx_t *udb, char* qstr, UC_Read *tu, -bit_extz_t *exz, double e_rate, int64_t w_l, uint64_t min_ovlp, double o_rate, kv_ul_ov_t *rln, kv_ul_ov_t *cln, -kv_rtrace_t *trace, uint64_t ql, uint64_t rid, uint64_t oid, uint64_t khit, overlap_region *aux_o) -{ - uint64_t ol, aln_ol, cn, k, mm, rln_0; ul_contain *ct = udb->ct; utg_ct_t *ca; ul_ov_t *p; - if(!aux_o) { - align_ul_ed_post_extz(z, udb, NULL, qstr, tu->seq, exz, e_rate, w_l, -1, 1, NULL); - ol = z->x_pos_e+1-z->x_pos_s, aln_ol = z->align_length; - if(aln_ol >= (ol*o_rate)) return 1; - if(aln_ol <= min_ovlp) return 0; - // fprintf(stderr, "***[M::%s::aln_ol->%lu] utg%.6dl(%c), align::%u, q::[%u, %u), t::[%u, %u)\n", __func__, aln_ol, - // (int32_t)z->y_id + 1, "+-"[z->y_pos_strand], z->align_length, - // z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1); - mm = win_cluster_fliter(z->w_list.a, z->w_list.n, min_ovlp, o_rate/2); - // print_aln_windows(z); - // fprintf(stderr, "***[M::%s::] mm::%lu\n", __func__, mm); - return mm; - } else { - ol = z->x_pos_e+1-z->x_pos_s; aln_ol = z->align_length; - if(aln_ol <= min_ovlp) return 0; - // if(z->y_id == 700) { - // fprintf(stderr, "+[M::%s::aln_ol->%lu::o_rate->%f] utg%.6dl(%c), align::%u, q::[%u, %u), t::[%u, %u), ql::%lu\n", - // __func__, aln_ol, o_rate, - // (int32_t)z->y_id + 1, "+-"[z->y_pos_strand], z->align_length, - // z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1, ql); - // print_aln_windows(z); - // } - rln_0 = rln->n; - if((ol*o_rate) <= aln_ol) { - kv_pushp(ul_ov_t, *rln, &p); memset(p, 0, sizeof(*p)); - ///[ts, te) -> whole interval rid at the unitig adjusted by the reverse - p->ts = z->y_pos_s; p->te = z->y_pos_e+1; - p->qs = z->x_pos_s; p->qe = z->x_pos_e+1; - p->rev = z->y_pos_strand; p->el = 0; p->tn = p->qn = (uint32_t)-1; - } else { - cn = ((uint32_t)(ct->idx.a[z->y_id])); - ca = ct->rids.a + ((ct->idx.a[z->y_id])>>32); - gen_sub_ov_adv(udb, z, o_rate, NULL, 0, rln); - gen_sub_ov_adv(udb, z, o_rate, ca, cn, rln); - } - - if(rln->n <= rln_0) return 0; - radix_sort_ul_ov_srt_qs1(rln->a+rln_0, rln->a+rln->n); - // if(z->y_id == 700) { - // for (k = 0; k < rln->n; k++) { - // p = &(rln->a[k]); - // fprintf(stderr, "+[M::%s::k->%lu] candidate_q::[%u, %u)\n", __func__, k, p->qs, p->qe); - // } - // } - - for (k = mm = rln_0, p = NULL; k < rln->n; k++) { - if((!p) || (rln->a[k].qs >= p->qe)) p = NULL; - if(p) { - if((rln->a[k].qsqe)&&(rln->a[k].qe>p->qe)) { - p->qe = rln->a[k].qe; - } - } else { - p = &(rln->a[mm++]); *p = rln->a[k]; - } - } - rln->n = mm; - // if(z->y_id == 700) { - // for (k = 0; k < rln->n; k++) { - // p = &(rln->a[k]); - // fprintf(stderr, "-[M::%s::k->%lu] candidate_q::[%u, %u)\n", __func__, k, p->qs, p->qe); - // } - // } - - return_t_chain(z, cl); - cigar_gen_by_chain_adv_local(z, cl, rln->a+rln_0, rln->n-rln_0, w_l, udb, NULL, NULL, qstr, tu, exz, aux_o, e_rate, ql, rid, khit); - - // fprintf(stderr, "-[M::%s::aln_ol->%lu] utg%.6dl(%c), align::%u, q::[%u, %u), t::[%u, %u)\n", __func__, aln_ol, - // (int32_t)z->y_id + 1, "+-"[z->y_pos_strand], z->align_length, - // z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1); - // print_aln_windows(z); - - - rln->n = rln_0; - cn = ((uint32_t)(ct->idx.a[z->y_id])); - ca = ct->rids.a + ((ct->idx.a[z->y_id])>>32); - gen_sub_ov_adv_cigar(udb, z, qstr, tu, exz, ql, o_rate, e_rate, NULL, 0, rid, oid, trace, rln); - gen_sub_ov_adv_cigar(udb, z, qstr, tu, exz, ql, o_rate, e_rate, ca, cn, rid, oid, trace, cln); - return 1; - } -} - - -int64_t ul_raw_aln(overlap_region *z, Candidates_list *cl, const ul_idx_t *udb, char* qstr, UC_Read *tu, -bit_extz_t *exz, double e_rate, int64_t w_l, uint64_t ql, uint64_t rid, uint64_t khit, overlap_region *aux_o) -{ - return_t_chain(z, cl); - int64_t ch_idx = z->shared_seed, ch_n; - int64_t i, tl, id = z->y_id, m; ul_ov_t ov; - k_mer_hit *ch_a = cl->list + ch_idx; - tl = udb->ug->u.a[id].len; - for (i = ch_idx; i < cl->length && cl->list[i].readID == cl->list[ch_idx].readID; i++); ch_n = i-ch_idx; - - // if(z->x_id == 57 && z->y_id == 2175) { - // fprintf(stderr, "\n-*-[M::%s]\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\tch_idx::%ld\tch_n::%ld\n", - // __func__, - // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], udb->ug->u.a[z->x_id].len, z->x_pos_s, z->x_pos_e+1, - // "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], udb->ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, - // ch_idx, ch_n); - // for (i = ch_idx; i < cl->length && cl->list[i].readID == cl->list[ch_idx].readID; i++) { - // fprintf(stderr, "i::%ld[M::%s]\treadID::%u\tself_offset::%u\toffset::%u\t%c\n", - // i, __func__, cl->list[i].readID, cl->list[i].self_offset, cl->list[i].offset, - // "+-"[cl->list[i].strand]); - // } - // } - - // on = fusion_chain_ovlp(z, ch_a, ch_n, ov, on, wl, ql, tl); - aux_o->w_list.n = aux_o->w_list.c.n = 0; - aux_o->y_id = z->y_id; aux_o->y_pos_strand = z->y_pos_strand; - aux_o->x_pos_s = z->x_pos_s; aux_o->x_pos_e = z->x_pos_e; - aux_o->y_pos_s = z->y_pos_s; aux_o->y_pos_e = z->y_pos_e; - - memset(&ov, 0, sizeof(ov)); ov.sec = 3; - ov.ts = ov.te = (uint32_t)-1; - ov.qs = 0; ov.qn = (uint32_t)-1; //extension to left - ov.qe = ql; ov.tn = ch_n; //extension to right - - ovlp_base_direct(z, ch_a, ch_n, &ov, w_l, udb, NULL, NULL, qstr, tu, exz, aux_o, e_rate, ql, tl, rid); - - int64_t aux_n = aux_o->w_list.n; - - - // if(z->x_id == 57 && z->y_id == 2175) { - // fprintf(stderr, "\n-0-[M::%s]\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\n", - // __func__, - // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], udb->ug->u.a[z->x_id].len, z->x_pos_s, z->x_pos_e+1, - // "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], udb->ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1); - // for (i = 0; i < aux_n; i++) { - // window_list *m = &(aux_o->w_list.a[i]); - // fprintf(stderr, "i::%ld[M::%s]\tutg%.6u%c\twx::[%u,\t%u)\t%c\tutg%.6u%c\twy::[%u,\t%u)\terr::%d\tualn::%u\test::%u\n", i, __func__, - // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], m->x_start, m->x_end+1, - // "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], m->y_start, m->y_end+1, m->error, - // (is_ualn_win((*m))), (is_est_aln((*m)))); - // } - // fprintf(stderr, "\n"); - // } - - - for (i = 0; i < aux_n; i++) { - if(!(is_ualn_win(aux_o->w_list.a[i]))) continue; - //will overwrite ch_a; does not matter - rechain_aln(z, cl, aux_o, i, w_l, udb, NULL, NULL, qstr, tu, exz, e_rate, ql, tl, khit, rid); - } - - // if(z->x_id == 57 && z->y_id == 2175) { - // fprintf(stderr, "\n-1-[M::%s]\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\n", - // __func__, - // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], udb->ug->u.a[z->x_id].len, z->x_pos_s, z->x_pos_e+1, - // "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], udb->ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1); - // for (i = 0; i < ((int64_t)aux_o->w_list.n); i++) { - // window_list *m = &(aux_o->w_list.a[i]); - // fprintf(stderr, "i::%ld[M::%s]\tutg%.6u%c\twx::[%u,\t%u)\t%c\tutg%.6u%c\twy::[%u,\t%u)\terr::%d\tualn::%u\test::%u\n", i, __func__, - // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], m->x_start, m->x_end+1, - // "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], m->y_start, m->y_end+1, m->error, - // (is_ualn_win((*m))), (is_est_aln((*m)))); - // } - // fprintf(stderr, "\n"); - // } - - if(((int64_t)aux_o->w_list.n) > aux_n) { - for (i = m = 0; i < ((int64_t)aux_o->w_list.n); i++) { - if((i < aux_n) && (is_ualn_win(aux_o->w_list.a[i]))) continue; - aux_o->w_list.a[m++] = aux_o->w_list.a[i]; - } - aux_o->w_list.n = m; - radix_sort_window_list_xs_srt(aux_o->w_list.a, aux_o->w_list.a+aux_o->w_list.n); - } - - ///update z by aux_o - update_overlap_region(z, aux_o, ql, tl); - assert((z->x_pos_e>=z->x_pos_s) && (z->y_pos_e>=z->y_pos_s)); - - int64_t zwn = z->w_list.n, zerr = 0, zlen = z->x_pos_e+1-z->x_pos_s; - for (i = 0; i < zwn; i++) { - if(is_ualn_win(z->w_list.a[i])) { - zerr += MAX((z->w_list.a[i].x_end+1-z->w_list.a[i].x_start), - (z->w_list.a[i].y_end+1-z->w_list.a[i].y_start)); - } else { - zerr += z->w_list.a[i].error; - } - } - z->non_homopolymer_errors = zerr; - - // if(z->x_id == 57 && z->y_id == 2175) { - // fprintf(stderr, "\n-2-[M::%s]\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\n", - // __func__, - // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], udb->ug->u.a[z->x_id].len, z->x_pos_s, z->x_pos_e+1, - // "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], udb->ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1); - // for (i = 0; i < zwn; i++) { - // window_list *m = &(z->w_list.a[i]); - // fprintf(stderr, "i::%ld[M::%s]\tutg%.6u%c\twx::[%u,\t%u)\t%c\tutg%.6u%c\twy::[%u,\t%u)\terr::%d\tualn::%u\test::%u\n", i, __func__, - // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], m->x_start, m->x_end+1, - // "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], m->y_start, m->y_end+1, m->error, - // (is_ualn_win((*m))), (is_est_aln((*m)))); - // } - // fprintf(stderr, "\n"); - // } - - // if(z->x_id == 57 && z->y_id == 2175) { - // fprintf(stderr, "\n-3-[M::%s]\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\tzerr::%ld\tzlen::%ld\te_rate::%f\n", - // __func__, - // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], udb->ug->u.a[z->x_id].len, z->x_pos_s, z->x_pos_e+1, - // "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], udb->ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, - // zerr, zlen, e_rate); - // } - - if(zerr >= zlen) return 0; - if(zerr <= 0 && zlen > 0) return 1; - if(zerr > (zlen*e_rate)) return 0; - return 1; -} - -void dedup_ul_ov_t(kv_ul_ov_t *in) -{ - ul_ov_t *a = in->a; int64_t k, l, m, z, r, a_n = in->n; uint64_t qo, to; double rr = 0.95; - for (k = 0; k < a_n; k++) a[k].tn = ((uint32_t)(a[k].tn<<1))|((uint32_t)(a[k].rev)); - radix_sort_ul_ov_srt_tn1(a, a + a_n); - for (k = 1, l = m = 0; k <= a_n; k++) { - if(k == a_n || a[k].tn != a[l].tn) { - for (z = l; z < k; z++) { - for (r=m-1; (r>=0) && (a[r].tn==(a[z].tn>>1)) && (a[r].rev==a[z].rev); r--) { - qo = ((MIN(a[z].qe, a[r].qe) > MAX(a[z].qs, a[r].qs))? - MIN(a[z].qe, a[r].qe) - MAX(a[z].qs, a[r].qs):0); - to = ((MIN(a[z].te, a[r].te) > MAX(a[z].ts, a[r].ts))? - MIN(a[z].te, a[r].te) - MAX(a[z].ts, a[r].ts):0); - if(qo >= ((a[r].qe - a[r].qs)*rr) && qo >= ((a[z].qe - a[z].qs)*rr) && - to >= ((a[r].te - a[r].ts)*rr) && to >= ((a[z].te - a[z].ts)*rr)) { - break; - } - } - if(r >= 0 && (a[r].tn==(a[z].tn>>1)) && (a[r].rev==a[z].rev)) { - if(a[z].sec < a[r].sec) { - a[r] = a[z]; a[r].tn >>= 1; - } - continue; - } - a[m] = a[z]; a[m].tn >>= 1; m++; - } - l = k; - } - } - // fprintf(stderr, "[M::%s::] in->n0::%ld, in->n::%ld\n", __func__, (int64_t)in->n, m); - in->n = m; -} - -void ul_rid_lalign_adv(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, const ug_opt_t *uopt, - char *qstr, uint64_t ql, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, - int64_t wl, kv_ul_ov_t *aln, kv_ul_ov_t *cln, kv_rtrace_t *trace, int64_t sid, uint64_t khit, void *km) -{ - uint64_t i, bs, k; Window_Pool w; double err; - overlap_region t; overlap_region *z; //asg64_v iidx, buf, buf1; - ol->mapped_overlaps_length = 0; - if(ol->length <= 0) return; - - ///base alignment - err = e_rate; - init_Window_Pool(&w, ql, wl, (int)(1.0/err)); - bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; - resize_UC_Read(tu, bs<<1); - - if(!aux_o) { - resize_UC_Read(qu, ql); qu->length = ql; memcpy(qu->seq, qstr, ql); - for (i = k = 0; i < ol->length; i++) { - z = &(ol->list[i]); z->shared_seed = z->non_homopolymer_errors;///for index - if(!ul_local_aln(z, cl, uref, qu->seq, tu, exz, err, w.window_length, - 1000, OVERLAP_THRESHOLD_NOSI_FILTER, NULL, NULL, NULL, ql, sid, i, khit, NULL)) { - continue; - } - if(k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - z = &(ol->list[k++]); z->is_match = 1; - } - ol->length = k; - if(ol->length <= 0) return; - } else { - for (i = cln->n = trace->n = 0; i < ol->length; i++) { - z = &(ol->list[i]); z->shared_seed = z->non_homopolymer_errors;///for index - // fprintf(stderr, "\n[M::%s::utg%.6dl(%c)] i::%lu, aln_l::%u, q::[%u, %u), ql::%u\n", __func__, - // (int32_t)z->y_id + 1, "+-"[z->y_pos_strand], i, z->align_length, - // z->x_pos_s, z->x_pos_e+1, z->x_pos_e+1-z->x_pos_s); - ul_local_aln(z, cl, uref, qu->seq, tu, exz, err, w.window_length, 1000, - OVERLAP_THRESHOLD_NOSI_FILTER, aln, cln, trace, ql, sid, i, khit, aux_o); - } - - ///contained reads - if(cln->n) dedup_ul_ov_t(cln); - if(cln->n) { - kv_resize(ul_ov_t, *aln, aln->n+cln->n); - memcpy(aln->a+aln->n, cln->a, cln->n*sizeof(*(aln->a))); - aln->n += cln->n; - } - - } -} - - -uint64_t gen_hc_fast_cigar(overlap_region *z, Candidates_list *cl, All_reads *rref, int64_t wl, char *qstr, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, int64_t rid, int64_t khit, int64_t *re) -{ - return_t_chain(z, cl); - gen_hc_fast_cigar0(z, cl, wl, rref, qstr, tu, exz, aux_o, e_rate, ql, rid, khit, re); - return 1; -} - -uint64_t gen_hc_fast_non_retrieve_cigar(overlap_region *z, Candidates_list *cl, int64_t wl, char *qstr, int64_t ql, char *tstr, int64_t tl, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t rid, int64_t khit) -{ - return_t_chain(z, cl); - gen_hc_fast_non_retrieve_cigar0(z, cl, wl, qstr, ql, tstr, tl, exz, aux_o, e_rate, rid, khit); - return 1; -} - -void append_cigar(window_list *idx, window_list_alloc *res, uint16_t c, uint32_t l) -{ - if(l <= 0) return; - uint16_t c0 = (uint16_t)-1; uint32_t l0 = 0; - ///last item of old cigar - if(idx->clen > 0) { - c0 = (res->c.a[res->c.n-1]>>14); - l0 = (res->c.a[res->c.n-1]&(0x3fff)); - } - ///first item of new cigar - if(c0 == c) {l += l0; res->c.n--; idx->clen--;} - - push_trace(((asg16_v *)(&(res->c))), c, l); - idx->clen = res->c.n-idx->cidx; -} - -uint16_t adjust_gap(window_list *idx, window_list_alloc *res, char *pstr, char *tstr, int64_t pi, int64_t ti, uint16_t op0, asg16_v* buf, int64_t *rd_err) -{ - (*rd_err) = 0; - - if(idx->clen == 0) { - append_cigar(idx, res, op0, 1); - return 0;///no move - } - if(op0 != 2 && op0 != 3) return 0;///no move - if(op0 == 2) {///more p -> y - ti--; - } else if(op0 == 3) {///more t -> x - pi--; - } - - // if(z->y_id == 3199 && z->x_id == 3196) { - // fprintf(stderr, "\n[M::%s]\tqi::%ld\tti::%ld\n", __func__, ti, pi); - // } - - uint16_t *ca = res->c.a+idx->cidx; - int64_t ci = idx->clen; int64_t op, cl, k, l[2]; uint16_t p, ff; - for (ci--, buf->n = ff = 0; ci >= 0; ci--) { - op = ca[ci]>>14; cl = (ca[ci]&(0x3fff)); - // if(z->y_id == 3199 && z->x_id == 3196) { - // fprintf(stderr, "[M::%s]\tqi::%ld\tti::%ld\tci::%ld\tcl::%ld\top::%ld\n", __func__, ti, pi, ci, cl, op); - // } - if(op == 2 || op == 3) { - p = op0; p <<= 14; p += 1; kv_push(uint16_t, *buf, p); - l[0] = cl; - p = op; p <<= 14; p += l[0]; kv_push(uint16_t, *buf, p); - break; - } else if(op == 0) { - for (k = cl-1, l[0] = l[1] = 0; k >= 0; k--, pi--, ti--) { - if(pstr[pi] != (tstr[ti])) break; - // if(op == 1) { - // if(!(pstr[pi] != (tstr[ti]))) { - // fprintf(stderr, "[M::%s] xid::%u, yid::%u, qi::%ld, ti::%ld\n", __func__, z->x_id, z->y_id, ti, pi); - // } - // assert(pstr[pi] != (tstr[ti])); - // } - } - l[1] = cl - k - 1; l[0] = k + 1; - if(l[1] > 0) { - p = op; p <<= 14; p += l[1]; kv_push(uint16_t, *buf, p); ff = 1; - } - - if(l[0] > 0) { - p = op0; p <<= 14; p += 1; kv_push(uint16_t, *buf, p); - } - - if(l[0] > 0) { - p = op; p <<= 14; p += l[0]; kv_push(uint16_t, *buf, p); - } - } else {///op == 1; it is possible since cigar is not optimal - for (k = cl-1, l[0] = cl, l[1] = 0; k >= 0; k--, pi--, ti--) { - if(pstr[pi] == (tstr[ti])) { - l[1] = l[0] - k - 1; - l[0] = k; - - if(l[1] > 0) { - p = op; p <<= 14; p += l[1]; kv_push(uint16_t, *buf, p); ff = 1;///push unmatch - } - p = 0; p <<= 14; p += 1; kv_push(uint16_t, *buf, p);///push match - (*rd_err)++; - } - } - - if(l[0] > 0) { - p = op; p <<= 14; p += l[0]; kv_push(uint16_t, *buf, p); - } - l[0] = 0; - } - - // fprintf(stderr, "[M::%s] ci::%ld, l[0]::%ld, l[1]::%ld\n", __func__, ci, l[0], l[1]); - - if(l[0] > 0) break; - } - - // fprintf(stderr, "[M::%s] ff::%u, ci::%ld, buf->n::%lu\n", __func__, ff, ci, (uint64_t)buf->n); - - if(!ff) {///no move - append_cigar(idx, res, op0, 1); - return 0;///no move - } else if(ci >= 0) { - // if(!(idx->cidx + idx->clen == res->c.n)) { - // fprintf(stderr, "[M::%s] idx->cidx::%lu, idx->clen::%lu, res->c.n::%lu\n", __func__, (uint64_t)idx->cidx, (uint64_t)idx->clen, (uint64_t)res->c.n); - // } - assert(idx->cidx + idx->clen == res->c.n); - idx->clen = ci; res->c.n = idx->cidx + idx->clen; - for (k = ((int64_t)buf->n)-1; k >= 0; k--) { - op = buf->a[k]>>14; cl = (buf->a[k]&(0x3fff)); - append_cigar(idx, res, op, cl); - } - } else { - idx->clen = 0; res->c.n = idx->cidx + idx->clen; - append_cigar(idx, res, op0, 1); - for (k = ((int64_t)buf->n)-1; k >= 0; k--) { - op = buf->a[k]>>14; cl = (buf->a[k]&(0x3fff)); - append_cigar(idx, res, op, cl); - } - } - return 1;///no move -} - -uint16_t ajust_end_cigar(window_list *idx, window_list_alloc *res) -{ - uint16_t *ca = res->c.a+idx->cidx, p, rr = 0; int64_t ci, cn = idx->clen, op, cl; - if(cn <= 0) return rr; - for (ci = 0; ci < cn; ci++) { - op = ca[ci]>>14; cl = (ca[ci]&(0x3fff)); - if(op != 1) break; - p = 3; p <<= 14; p += cl; ca[ci] = p; idx->y_start += cl; rr = 1; - } - - for (ci = cn-1; ci >= 0; ci--) { - op = ca[ci]>>14; cl = (ca[ci]&(0x3fff)); - if(op != 1) break; - p = 3; p <<= 14; p += cl; ca[ci] = p; idx->y_end -= cl; rr = 1; - } - - // if(rr) fprintf(stderr, "[M::%s] rr::%u\n", __func__, rr); - - return rr; -} - -uint16_t move_wins(overlap_region *z, uint32_t wid, overlap_region *aux, All_reads *rref, char *tstr, char *pstr, UC_Read *pu, asg16_v* buf, int64_t *tot_re) -{ - // if(z->y_id == 3199 && z->x_id == 3196) { - // fprintf(stderr, "\n[M::%s] x_id::%u, y_id::%u, x::[%u, %u), y::[%u, %u)\n", __func__, z->x_id, z->y_id, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); - // fprintf(stderr, "[M::%s] wid::%u, x::[%d, %d), y::[%d, %d), err::%d\n", __func__, wid, z->w_list.a[wid].x_start, z->w_list.a[wid].x_end + 1, z->w_list.a[wid].y_start, z->w_list.a[wid].y_end + 1, z->w_list.a[wid].error); - // } - if(is_ualn_win((z->w_list.a[wid]))) { - kv_push(window_list, aux->w_list, (z->w_list.a[wid])); - return 0;///no move - } - - window_list *p = NULL; char *tseq = tstr, *pseq = pstr; - bit_extz_t ez; set_bit_extz_t(ez, (*z), wid); - kv_pushp(window_list, aux->w_list, &p); - p->x_start = ez.ts; p->x_end = ez.te; - p->y_start = ez.ps; p->y_end = ez.pe; - p->error_threshold = 0; p->error = ez.err;///single round of alignment cannot have INT16_MAX errors - p->cidx = aux->w_list.c.n; p->clen = 0; ///aux->w_list.c.n += ez.cigar.n; - - if(ez.err == 0) { - push_wcigar(p, &(aux->w_list), &ez); - return 0;///no move - } - - int64_t pi = ez.ps, ti = ez.ts/**, err = 0**/, cl, op, k, rr = 0, re; uint64_t ci = 0, mm = 0; - // char cm[4]; cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; - // if(z->y_id == 3199 && z->x_id == 3196) { - // fprintf(stderr, "******\n"); - // for (ci = 0; ci < ez.cigar.n; ci++) { - // op = ez.cigar.a[ci]>>14; cl = (ez.cigar.a[ci]&(0x3fff)); - // fprintf(stderr, "%ld%c(q::[%ld,%ld))(t::[%ld,%ld))(ck::%ld)\n", cl, cm[op], ti, ti + (((op<2)||(op==3))?(cl):(0)), pi, pi + (((op<2)||(op==2))?(cl):(0)), ci); - - // if(op < 2) { - // pi+=cl; ti+=cl; - // } else { - // if(op == 2) {///more p -> y - // pi+=cl; - // } else if(op == 3) {///more t -> x - // ti+=cl; - // } - // } - // } - // pi = ez.ps; ti = ez.ts; - // fprintf(stderr, "******\n"); - // } - - for (ci = mm = 0; ci < ez.cigar.n; ci++) { - op = ez.cigar.a[ci]>>14; ///cl = (ez.cigar.a[ci]&(0x3fff)); - if(op < 2) { - mm = 1; - } else if(mm) { - break; - } - // if(op == 2 || op == 3) break; - } - if(ci >= ez.cigar.n) { - push_wcigar(p, &(aux->w_list), &ez); - if(ajust_end_cigar(p, &(aux->w_list))) rr = 1; - return rr; - } - - if(!pseq) { - if(z->y_pos_strand) { - recover_UC_Read_RC(pu, rref, aux->y_id); - } else { - recover_UC_Read(pu, rref, aux->y_id); - } - pseq = pu->seq; - } - - kv_resize(uint16_t, aux->w_list.c, (aux->w_list.c.n + ez.cigar.n)); - - for (ci = mm = 0; ci < ez.cigar.n; ci++) { - op = ez.cigar.a[ci]>>14; cl = (ez.cigar.a[ci]&(0x3fff)); - // if(z->y_id == 24 && z->x_id == 25) { - // fprintf(stderr, "[M::%s] op::%ld, cl::%ld, pi::%ld, ti::%ld\n", __func__, op, cl, pi, ti); - // fprintf(stderr, "[M::%s] p->cidx::%lu, p->clen::%lu, cc->n::%lu\n", __func__, (uint64_t)p->cidx, (uint64_t)p->clen, (uint64_t)aux->w_list.c.n); - // } - // if(z->y_id == 3199 && z->x_id == 3196) { - // fprintf(stderr, "%ld%c(q::[%ld,%ld))(t::[%ld,%ld))(ck::%ld)\tmm::%lu\n", cl, cm[op], ti, ti + (((op<2)||(op==3))?(cl):(0)), pi, pi + (((op<2)||(op==2))?(cl):(0)), ci, mm); - // } - - if(op < 2) { - append_cigar(p, &(aux->w_list), op, cl); - pi+=cl; ti+=cl; mm = 1; - } else { - if(mm == 0) { - append_cigar(p, &(aux->w_list), op, cl); - if(op == 2) {///more p -> y - pi+=cl; - } else if(op == 3) {///more t -> x - ti+=cl; - } - } else { - for (k = 0; k < cl; k++) { - // if(z->y_id == 3199 && z->x_id == 3196) { - // fprintf(stderr, "+++k::%ld\tqi::%ld\tti::%ld\n", k, ti, pi); - // } - if(adjust_gap(p, &(aux->w_list), pseq, tseq, pi, ti, op, buf, &re)) { - rr = 1; p->error -= re; (*tot_re) += re; - } - if(op == 2) {///more p -> y - pi++; - } else if(op == 3) {///more t -> x - ti++; - } - } - } - } - } - - // if(rr) fprintf(stderr, "[M::%s] rr::%ld\n", __func__, rr); - - if(ajust_end_cigar(p, &(aux->w_list))) rr = 1; - return rr; -} - -void reassign_gaps(overlap_region *z, overlap_region *aux, char* qstr, int64_t ql, char* tstr, int64_t tl, All_reads *rref, UC_Read* tu, asg16_v* buf) -{ - // if(z->y_id != 24 || z->x_id != 25) return; - if(z->non_homopolymer_errors == 0) return; - aux->w_list.n = aux->w_list.c.n = 0; - aux->y_id = z->y_id; aux->y_pos_strand = z->y_pos_strand; - aux->x_pos_s = z->x_pos_s; aux->x_pos_e = z->x_pos_e; - aux->y_pos_s = z->y_pos_s; aux->y_pos_e = z->y_pos_e; - - int64_t k, z_n = z->w_list.n, rr = 0, re = 0; - for (k = 0; k < z_n; k++) { - if(move_wins(z, k, aux, rref, qstr, tstr, tu, buf, &re)) rr = 1; - } - ///update z by aux_o - if(rr) update_overlap_region(z, aux, ql, ((rref)?(Get_READ_LENGTH((*rref), z->y_id)):(tl))); - z->non_homopolymer_errors -= re; - - // if(z->y_id == 1) { - // fprintf(stderr, "[M::%s] rr::%ld\tx_id::%u\ty_id::%u\tx::[%u, %u)\ty::[%u, %u)\tz_n::%ld\n", - // __func__, rr, z->x_id, z->y_id, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, z_n); - // fprintf(stderr, "qstr(%lld)::%.*s\n", qu->length, (int32_t)(qu->length), qu->seq); - // fprintf(stderr, "tstr(%lld)::%.*s\n", tu->length, (int32_t)(tu->length), tu->seq); - // ///debug - - // if(z->y_pos_strand) { - // recover_UC_Read_RC(tu, rref, z->y_id); - // } else { - // recover_UC_Read(tu, rref, z->y_id); - // } - // if(tstr) { - // bit_extz_t ez; - // for (k = 0; k < z_n; k++) { - // if(is_ualn_win((z->w_list.a[k]))) continue; - // set_bit_extz_t(ez, (*z), k); - // if(!cigar_check(tstr, qstr, &ez)) { - // fprintf(stderr, "\n[M::%s] x_id::%u, y_id::%u, x::[%u, %u), y::[%u, %u)\n", __func__, z->x_id, z->y_id, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); - // exit(1); - // } - // } - // } - - // } -} - -uint32_t is_ovlp_debug(int64_t s, int64_t e, int64_t ws, int64_t we, int64_t op) -{ - int64_t os, oe, ovlp; - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - if(op != 2) { - return (!!ovlp); - } else { - if(ws >= s && we <= e) return 1; - } - return 0; -} - -uint32_t inline ff_tend(overlap_region *z, int64_t wn, int64_t dn, double dr, double er, int64_t min_err) -{ - int64_t k, zwn = z->w_list.n, err, mm, qi, ci, cn, ql, ws, we, zs, ze, s, e, os, oe, ovlp; bit_extz_t ez; uint32_t cl; uint16_t c; - zs = z->x_pos_s; ze = z->x_pos_e + 1; ql = ze - zs; - if(ql < wn) return 0; if(dn > (ql*dr)) dn = ql*dr; if(dn < wn) return 0; if(ql < dn) return 0; - - s = zs; e = zs + dn; - // if(z->y_id == 27) fprintf(stderr, "-a-[M::%s] tid::%u\t%.*s\tz::[%ld,%ld)\ti::[%ld,%ld)\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), zs, ze, s, e); - for (k = err = mm = 0, qi = zs; (k < zwn) && (z->w_list.a[k].x_start < e); k++) { - // if(z->y_id == 27) fprintf(stderr, "-a-[M::%s] tid::%u\t%.*s\tw::[%d,%d)\terr::%d\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), z->w_list.a[k].x_start, z->w_list.a[k].x_end + 1, z->w_list.a[k].error); - if(!(is_ualn_win(z->w_list.a[k]))) { - set_bit_extz_t(ez, (*z), k); - ci = 0; cn = ez.cigar.n; qi = ez.ts; //ti = ez.ps; - while (ci < cn && qi < e) { - ws = qi; - ci = pop_trace(&(ez.cigar), ci, &c, &cl); - if(c!=2) qi += cl; - // if(c!=3) ti += cl; - we = qi; - - if(c == 0) { - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); mm += ovlp; - } else { - err += cl; - } - // assert(is_ovlp_debug(s, e, ws, we, c)); - - if((err > min_err) && ((mm + err) > wn) && (err > ((mm + err)*er))) { - // fprintf(stderr, "-0-[M::%s] tid::%u\t%.*s\tmm::%ld\terr::%ld\tdn::%ld\twn::%ld\tdif::%f\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), mm, err, dn, wn, er); - return 1; - } - } - } else { - ws = z->w_list.a[k].x_start; we = z->w_list.a[k].x_end + 1; - err += we - ws; - - // assert(is_ovlp_debug(s, e, ws, we, -1)); - - if((err > min_err) && ((mm + err) > wn) && (err > ((mm + err)*er))) { - // fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\tmm::%ld\terr::%ld\tdn::%ld\twn::%ld\tdif::%f\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), mm, err, dn, wn, er); - return 1; - } - } - } - - s = ze - dn; e = ze; - for (k = zwn - 1, err = mm = 0, qi = ze; (k >= 0) && ((z->w_list.a[k].x_end + 1) > s); k--) { - if(!(is_ualn_win(z->w_list.a[k]))) { - set_bit_extz_t(ez, (*z), k); - ci = ((int64_t)ez.cigar.n) - 1; qi = ez.te + 1; //ti = ez.pe + 1; - while (ci >= 0 && qi > s) { - we = qi; - ci = pop_trace_back(&(ez.cigar), ci, &c, &cl); - if(c!=2) qi -= cl; - // if(c!=3) ti += cl; - ws = qi; - - if(c == 0) { - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); mm += ovlp; - } else { - err += cl; - } - - // assert(is_ovlp_debug(s, e, ws, we, c)); - - if((err > min_err) && ((mm + err) > wn) && (err > ((mm + err)*er))) { - // fprintf(stderr, "-2-[M::%s] tid::%u\t%.*s\tmm::%ld\terr::%ld\tdn::%ld\twn::%ld\tdif::%f\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), mm, err, dn, wn, er); - return 1; - } - } - } else { - ws = z->w_list.a[k].x_start; we = z->w_list.a[k].x_end + 1; - err += we - ws; - - // assert(is_ovlp_debug(s, e, ws, we, -1)); - - if((err > min_err) && ((mm + err) > wn) && (err > ((mm + err)*er))) { - // fprintf(stderr, "-3-[M::%s] tid::%u\t%.*s\tmm::%ld\terr::%ld\tdn::%ld\twn::%ld\tdif::%f\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), mm, err, dn, wn, er); - return 1; - } - } - } - - return 0; -} - -uint32_t inline ff_lunalign(overlap_region *z, double erate, double gap_rate, int64_t max_gap) -{ - if((z->w_list.n == 1) && (!(is_ualn_win(z->w_list.a[0]))) - && (z->w_list.a[0].x_start == ((int64_t)z->x_pos_s)) && (z->w_list.a[0].x_end == ((int64_t)z->x_pos_e)) - && (z->w_list.a[0].y_start == ((int64_t)z->y_pos_s)) && (z->w_list.a[0].y_end == ((int64_t)z->y_pos_e))) { - return 1; - } - - int64_t k, zwn = z->w_list.n, zq, zt, wq, wt, tot_e, tot_g, ql, tl; - - // fprintf(stderr, "[M::%s]\n", __func__); - - zq = z->x_pos_s; zt = z->y_pos_s; tot_e = tot_g = 0; - for (k = 0; k < zwn; k++) { - // fprintf(stderr, "[M::%s]\twk::%ld\tq::[%d, %d)\tt::[%d, %d)\terr::%d\n", __func__, - // k, z->w_list.a[k].x_start, z->w_list.a[k].x_end + 1, z->w_list.a[k].y_start, z->w_list.a[k].y_end + 1, z->w_list.a[k].error); - if(is_ualn_win(z->w_list.a[k])) continue; - wq = z->w_list.a[k].x_start; - wt = z->w_list.a[k].y_start; - - if(wq != zq) tot_g += ((wq>=zq)?(wq-zq):(zq-wq)); - if(wt != zt) tot_g += ((wt>=zt)?(wt-zt):(zt-wt)); - - zq = z->w_list.a[k].x_end + 1; - zt = z->w_list.a[k].y_end + 1; - tot_e += z->w_list.a[k].error; - - // fprintf(stderr, "[M::%s]\twk::%ld\tq::[%d, %d)\tt::[%d, %d)\terr::%d\n", __func__, - // k, z->w_list.a[k].x_start, z->w_list.a[k].x_end + 1, z->w_list.a[k].y_start, z->w_list.a[k].y_end + 1, z->w_list.a[k].error); - } - - wq = z->x_pos_e + 1; - wt = z->y_pos_e + 1; - if(wq != zq) tot_g += ((wq>=zq)?(wq-zq):(zq-wq)); - if(wt != zt) tot_g += ((wt>=zt)?(wt-zt):(zt-wt)); - - // fprintf(stderr, "[M::%s]\t%.*s(id::%u)\tq::[%u, %u)\t%.*s(id::%u)\tt::[%u, %u)\tre::%ld\trg::%ld\n", __func__, (int)Get_NAME_LENGTH(R_INF, z->x_id), Get_NAME(R_INF, z->x_id), z->x_id, z->x_pos_s, z->x_pos_e + 1, - // (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), z->y_id, z->y_pos_s, z->y_pos_e + 1, tot_e, tot_g); - - if(!tot_g) return 1; - - // fprintf(stderr, "-0-[M::%s]\n", __func__); - - if(tot_g > max_gap) return 0; - - // fprintf(stderr, "-1-[M::%s]\n", __func__); - - ql = z->x_pos_e + 1 - z->x_pos_s; - tl = z->y_pos_e + 1 - z->y_pos_s; - - if((tot_g > (ql*gap_rate)) || (tot_g > (tl*gap_rate))) return 0; - - // fprintf(stderr, "-2-[M::%s]\n", __func__); - - tot_e += tot_g; - - if((tot_e > (ql*erate)) || (tot_e > (tl*erate))) return 0; - - // fprintf(stderr, "-3-[M::%s]\n", __func__); - - return 1; -} - -void gen_hc_r_alin(overlap_region_alloc* ol, Candidates_list *cl, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t wl, int64_t rid, int64_t khit, int64_t move_gap, asg16_v* buf, uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max) -{ - uint64_t i, bs, k, ql = qu->length; Window_Pool w; double err, e_max, rr; int64_t re; - overlap_region t; overlap_region *z; //asg64_v iidx, buf, buf1; - ol->mapped_overlaps_length = 0; - if(ol->length <= 0) return; - // if(ol->length && ol->list[0].x_id == 19350) e_rate = 0.1; - - ///base alignment - err = e_rate; e_max = err * 1.5; - init_Window_Pool(&w, ql, wl, (int)(1.0/err)); - bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; - resize_UC_Read(tu, bs<<1); - // fprintf(stderr, "[M::%s] window_length::%lld, err::%f\n", __func__, w.window_length, err); - - for (i = k = 0; i < ol->length; i++) { - z = &(ol->list[i]); z->shared_seed = z->non_homopolymer_errors;///for index - - // if(z->x_id == 19350 && z->y_id == 19324) fprintf(stderr, "-z-[M::%s] tid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); - - if(!align_hc_ed_post_extz(z, rref, qu->seq, tu->seq, exz, err, w.window_length, OVERLAP_THRESHOLD_HIFI_FILTER, 0, NULL)) continue; - - // if(z->x_id == 19350 && z->y_id == 19324) fprintf(stderr, "-m-[M::%s] tid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); - - rr = gen_extend_err_exz(z, NULL, NULL, rref, qu->seq, tu->seq, exz, NULL, w.window_length, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 0, &re); - z->is_match = 0; - - // if(z->x_id == 19350 && z->y_id == 19324) fprintf(stderr, "-0-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); - - if (rr > err) continue; - z->non_homopolymer_errors = re; - - if(!gen_hc_fast_cigar(z, cl, rref, w.window_length, qu->seq, tu, exz, aux_o, e_rate, ql, rid, khit, &re)) continue; - - if((align_gap_max >= 0) && (!ff_lunalign(z, err, align_gap_rate, align_gap_max))) continue; - - if(chem_drop && ff_tend(z, 384, 2000, 0.1, (((e_rate*10)<0.36)?(e_rate*10):(0.36)), 128)) continue; - - - // if(z->x_id == 3196 && z->y_id == 3199) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); - - reassign_gaps(z, aux_o, qu->seq, ql, NULL, -1, rref, tu, buf); - - // fprintf(stderr, "-2-[M::%s] tid::%u\t%.*s\trr::%f\tre::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); - - // if(z->x_id == 19350) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\terr::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); - - if(k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - z = &(ol->list[k++]); z->is_match = 1; ///z->non_homopolymer_errors = re; - z->strong = z->without_large_indel = 0; - } - ol->length = k; - if(ol->length <= 0) return; -} - - -void gen_hc_r_alin_nec(overlap_region_alloc* ol, Candidates_list *cl, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t wl, int64_t rid, int64_t khit, int64_t move_gap, asg16_v* buf, uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max) -{ - uint64_t i, bs, k, ql = qu->length; Window_Pool w; double err, e_max, rr; int64_t re; - overlap_region t; overlap_region *z; //asg64_v iidx, buf, buf1; - ol->mapped_overlaps_length = 0; - if(ol->length <= 0) return; - // if(ol->length && ol->list[0].x_id == 19350) e_rate = 0.1; - - ///base alignment - err = e_rate; e_max = err * 1.5; - init_Window_Pool(&w, ql, wl, (int)(1.0/err)); - bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; - resize_UC_Read(tu, bs<<1); - // fprintf(stderr, "[M::%s] window_length::%lld\n", __func__, w.window_length); - - ///debug for memory - // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); - - for (i = k = 0; i < ol->length; i++) { - z = &(ol->list[i]); - if(z->is_match != 1) { - z->shared_seed = z->non_homopolymer_errors;///for index - - // if(z->x_id == 19350 && z->y_id == 19324) fprintf(stderr, "-z-[M::%s] tid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); - - if(!align_hc_ed_post_extz(z, rref, qu->seq, tu->seq, exz, err, w.window_length, OVERLAP_THRESHOLD_HIFI_FILTER, 0, NULL)) continue; - - // if(z->x_id == 19350 && z->y_id == 19324) fprintf(stderr, "-m-[M::%s] tid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); - - rr = gen_extend_err_exz(z, NULL, NULL, rref, qu->seq, tu->seq, exz, NULL, w.window_length, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 0, &re); - z->is_match = 0; - - // if(z->x_id == 19350 && z->y_id == 19324) fprintf(stderr, "-0-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); - - if (rr > err) continue; - z->non_homopolymer_errors = re; - - ///debug for memory - // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); - - if(!gen_hc_fast_cigar(z, cl, rref, w.window_length, qu->seq, tu, exz, aux_o, e_rate, ql, rid, khit, &re)) continue; - - if((align_gap_max >= 0) && (!ff_lunalign(z, err, align_gap_rate, align_gap_max))) continue; - - if(chem_drop && ff_tend(z, 384, 2000, 0.1, (((e_rate*10)<0.36)?(e_rate*10):(0.36)), 128)) continue; - - // if(z->x_id == 3196 && z->y_id == 3199) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); - ///debug for memory - // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); - - reassign_gaps(z, aux_o, qu->seq, ql, NULL, -1, rref, tu, buf); - - ///debug for memory - // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); - } - - // if(z->x_id == 3196 && z->y_id == 3199) fprintf(stderr, "-2-[M::%s] tid::%u\t%.*s\trr::%f\tre::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); - - // if(z->x_id == 19350) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\terr::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); - - if(k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - z = &(ol->list[k++]); z->is_match = 1; ///z->non_homopolymer_errors = re; - z->strong = z->without_large_indel = 0; - } - ol->length = k; - if(ol->length <= 0) return; -} - - -uint64_t gen_hc_r_alin_re(overlap_region* z, Candidates_list *cl, char* qstr, uint64_t ql, char* tstr, uint64_t tl, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t wl, int64_t rid, int64_t khit, int64_t move_gap, asg16_v* buf) -{ - double err, e_max, rr; int64_t re; - - err = e_rate; e_max = err * 1.5; - - z->shared_seed = z->non_homopolymer_errors;///for index - - if(!align_hc_ed_post_non_retrieve_extz(z, qstr, ql, tstr, tl, exz, err, wl, OVERLAP_THRESHOLD_HIFI_FILTER, 0, NULL)) return 0; - - rr = gen_extend_err_non_retrieve_exz(z, qstr, tstr, tl, exz, NULL, wl, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 0, &re); - z->is_match = 0; - - if (rr > err) return 0; - z->non_homopolymer_errors = re; - - // if(z->x_id == 3196 && z->y_id == 3199) fprintf(stderr, "-0-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); - - if(!gen_hc_fast_non_retrieve_cigar(z, cl, wl, qstr, ql, tstr, tl, exz, aux_o, e_rate, rid, khit)) return 0; - - // if(z->x_id == 3196 && z->y_id == 3199) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); - - reassign_gaps(z, aux_o, qstr, ql, tstr, tl, NULL, NULL, buf); - - // if(z->x_id == 3196 && z->y_id == 3199) fprintf(stderr, "-2-[M::%s] tid::%u\t%.*s\trr::%f\tre::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); - - z->is_match = 1; ///z->non_homopolymer_errors = re; - z->strong = z->without_large_indel = 0; - - return 1; -} - -/** -void ul_raw_lalign_adv(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, All_reads *rdb, const ug_opt_t *uopt, - char *qstr, uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, bit_extz_t *exz, haplotype_evdience_alloc* hap, - kvec_t_u64_warp* v_idx, overlap_region *aux_o, double e_rate, int64_t wl, kv_ul_ov_t *aln, kv_ul_ov_t *aln1, - int64_t sid, uint64_t khit, st_mt_t *stb, void *km) -{ - uint64_t i, bs, k, aln_occ; Window_Pool w; double err; - overlap_region t; overlap_region *z; asg64_v iidx, buf, buf1; - ol->mapped_overlaps_length = 0; - if(ol->length <= 0) return; - - ///base alignment - clear_Correct_dumy(dumy, ol, km); err = e_rate; - init_Window_Pool(&w, ql, wl, (int)(1.0/err)); - bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; - resize_UC_Read(tu, bs<<1); - - if(!aux_o) { - resize_UC_Read(qu, ql); qu->length = ql; memcpy(qu->seq, qstr, ql); - copy_asg_arr(iidx, hap->snp_srt); - for (i = k = 0, aln->n = 0; i < ol->length; i++) { - z = &(ol->list[i]); z->shared_seed = z->non_homopolymer_errors;///for index - align_ul_ed_post_extz(z, uref, NULL, qu->seq, tu->seq, exz, err, w.window_length, -1, 1, km); - aln_occ = gen_r_aln(uref, z, k, &iidx, OVERLAP_THRESHOLD_FILTER, aln, 1000); - if(!aln_occ) continue; - if(k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - z = &(ol->list[k++]); z->is_match = 1; - } - copy_asg_arr(hap->snp_srt, iidx); - ol->length = k; - if(ol->length <= 0) return; - } else { - copy_asg_arr(iidx, hap->snp_srt); copy_asg_arr(buf, v_idx->a); copy_asg_arr(buf1, (*stb)); - ul_gap_filling_local(ol, cl, aln, wl, uref, NULL, NULL, qu->seq, tu, exz, aux_o, &buf, &iidx, err, ql, sid, khit, 1, MAX_LGAP(ql)); - copy_asg_arr(hap->snp_srt, iidx); copy_asg_arr(v_idx->a, buf); copy_asg_arr((*stb), buf1); - - copy_asg_arr(iidx, hap->snp_srt); - gen_aln_local(ol, aln, aln1, &iidx, uref, qu->seq, tu, exz, aux_o, err, ql, OVERLAP_THRESHOLD_FILTER); - copy_asg_arr(hap->snp_srt, iidx); - } - // } else { - // // fprintf(stderr, "-[M::%s] on::%lu\n", __func__, ol->length); - // if(ol->length <= 1) return; - // ///coordinates for all intervals with cov > 1 - // copy_asg_arr(iidx, hap->snp_srt); copy_asg_arr(buf, v_idx->a); copy_asg_arr(buf1, (*stb)); - // // fprintf(stderr, "\n[M::%s] iidx_n::%ld\n", __func__, (int64_t)iidx.n); - // ul_gap_filling_adv(ol, cl, aln, wl, uref, NULL, NULL, qu->seq, tu, exz, aux_o, &buf, &iidx, err, ql, sid, khit, 1, MAX_LGAP(ql)); - // copy_asg_arr(hap->snp_srt, iidx); copy_asg_arr(v_idx->a, buf); copy_asg_arr((*stb), buf1); - - // copy_asg_arr(iidx, hap->snp_srt); copy_asg_arr(buf, v_idx->a); copy_asg_arr(buf1, (*stb)); - // region_phase(ol, uref, uopt, aln, &iidx, &buf, &buf1); - // copy_asg_arr(hap->snp_srt, iidx); copy_asg_arr(v_idx->a, buf); copy_asg_arr((*stb), buf1); - // } -} -**/ - -uint64_t gen_nkhits(Candidates_list *cl, overlap_region *z) -{ - uint64_t pid, kn; int64_t k; - pid = cl->list[z->shared_seed].readID;kn = 0; - for (k = z->shared_seed; k < cl->length && cl->list[k].readID == pid; k++) kn++; - return kn; -} - -void ug_lalign(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, const ug_opt_t *uopt, - char *qstr, uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, bit_extz_t *exz, - overlap_region *aux_o, double e_rate, int64_t wl, int64_t sid, uint64_t khit, - uint64_t chain_cut, void *km) -{ - uint64_t i, bs, k, ovl, pid, kl, kn; Window_Pool w; double err; - overlap_region t; overlap_region *z; char *in = qstr; - ol->mapped_overlaps_length = 0; - if(ol->length <= 0) return; - - ///base alignment - clear_Correct_dumy(dumy, ol, km); err = e_rate; - init_Window_Pool(&w, ql, wl, (int)(1.0/err)); - bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; - resize_UC_Read(tu, bs<<1); - - if(!aux_o) { - if(qu) { - resize_UC_Read(qu, ql); qu->length = ql; memcpy(qu->seq, qstr, ql); in = qu->seq; - } - for (i = 0; i < ol->length; i++) { - z = &(ol->list[i]); ovl = z->x_pos_e+1-z->x_pos_s; - z->shared_seed = z->non_homopolymer_errors;///for index - pid = cl->list[z->shared_seed].readID; kl = cl->length; kn = 0; - for (k = z->shared_seed; k < kl && cl->list[k].readID == pid && kn < chain_cut; k++) kn++; - if(kn < chain_cut) continue; - - if(!align_ul_ed_post_extz(z, uref, NULL, in/**qu->seq**/, tu->seq, exz, err, w.window_length, -1, 0, km)) { - continue; - } - if(uref && simi_pass(ovl, z->align_length, uref?1:0, -1, NULL)) { - z->is_match = 3; ol->mapped_overlaps_length += z->align_length; - } - } - - // if(uref && ol->mapped_overlaps_length > 0) { - // set_herror_win(ol, dumy, v_idx, err, ql, w.window_length); - // } - - double e_max = err*1.5, rr; int64_t re; - for (i = k = 0; i < ol->length; i++) { - z = &(ol->list[i]); ovl = z->x_pos_e + 1 - z->x_pos_s; - rr = gen_extend_err_exz(z, uref, NULL, NULL, in/**qu->seq**/, tu->seq, exz, NULL/**v_idx?v_idx->a.a:NULL**/, w.window_length, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 1, &re); - z->is_match = 0;///must be here; - - // if(z->x_id == 57 && z->y_id == 2175) { - // fprintf(stderr, "+utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\talign_length::%u\terr::%f\trr::%f\twn::%u\tk::%lu\ti::%lu\n", - // z->x_id+1, "lc"[uref->ug->u.a[z->x_id].circ], uref->ug->u.a[z->x_id].len, - // z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[uref->ug->u.a[z->y_id].circ], uref->ug->u.a[z->y_id].len, - // z->y_pos_s, z->y_pos_e+1, z->align_length, err, rr, (uint32_t)z->w_list.n/**gen_nkhits(cl, z)**/, - // k, i); - // } - if (rr <= err) { - if(k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - ol->list[k].is_match = 1; ol->list[k].non_homopolymer_errors = re; - k++; - } - } - - ol->length = k; - // if(sid == 57) { - // fprintf(stderr, "+utg%.6ld%c\tol->length::%lu\n", sid+1, "lc"[uref->ug->u.a[sid].circ], ol->length); - // } - if(ol->length <= 0) return; - } else { - // if(ol->length <= 1) return; - if(ol->length <= 0) return; - if(qu) { - resize_UC_Read(qu, ql); qu->length = ql; memcpy(qu->seq, qstr, ql); in = qu->seq; - } - for (i = k = 0; i < ol->length; i++) { - z = &(ol->list[i]); - // if(z->x_id == 57 && z->y_id == 2175) { - // fprintf(stderr, "-1-utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\talign_length::%u\terr::%f\twn::%u\tk::%lu\ti::%lu\n", - // z->x_id+1, "lc"[uref->ug->u.a[z->x_id].circ], uref->ug->u.a[z->x_id].len, - // z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[uref->ug->u.a[z->y_id].circ], uref->ug->u.a[z->y_id].len, - // z->y_pos_s, z->y_pos_e+1, z->align_length, err, (uint32_t)z->w_list.n/**gen_nkhits(cl, z)**/, - // k, i); - // } - if(!ul_raw_aln(z, cl, uref, in/**qu->seq**/, tu, exz, err, wl, ql, sid, khit, aux_o)) { - z->is_match = 0; - continue; - } - - // if(z->x_id == 57 && z->y_id == 2175) { - // fprintf(stderr, "-2-utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\talign_length::%u\terr::%f\twn::%u\tk::%lu\ti::%lu\n", - // z->x_id+1, "lc"[uref->ug->u.a[z->x_id].circ], uref->ug->u.a[z->x_id].len, - // z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[uref->ug->u.a[z->y_id].circ], uref->ug->u.a[z->y_id].len, - // z->y_pos_s, z->y_pos_e+1, z->align_length, err, (uint32_t)z->w_list.n/**gen_nkhits(cl, z)**/, - // k, i); - // } - if(k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - ol->list[k].is_match = 1; - k++; - } - ol->length = k; - - // if(sid == 57) { - // fprintf(stderr, "-utg%.6ld%c\tol->length::%lu\n", sid+1, "lc"[uref->ug->u.a[sid].circ], ol->length); - // } - } +#define __STDC_LIMIT_MACROS +#include +#include +#include +#include +#include +#include +#include +#include "Correct.h" +#include "Levenshtein_distance.h" +#include "Assembly.h" +#include "CommandLines.h" +// #include "ksw2.h" +#include "ksort.h" +#include "kalloc.h" +#include "htab.h" +#include "Overlaps.h" +#include "inter.h" +#include "Process_Read.h" +#define A_L 16 +#define ext_w 6 +#define r_simi_w 0.05 +#define rphase_thres 4 +#define HF_W_P 4 +#define OT_W_P 1 +#define h0_w_p 1 + +#define generic_key(x) (x) +KRADIX_SORT_INIT(b32, uint32_t, generic_key, 4) +KRADIX_SORT_INIT(bc64, uint64_t, generic_key, 8) + +#define haplotype_evdience_key(x) ((x).site) +KRADIX_SORT_INIT(haplotype_evdience_srt, haplotype_evdience, haplotype_evdience_key, member_size(haplotype_evdience, site)) + +#define haplotype_evdience_id_key(x) ((x).overlapID) +KRADIX_SORT_INIT(haplotype_evdience_id_srt, haplotype_evdience, haplotype_evdience_id_key, member_size(haplotype_evdience, overlapID)) + +#define haplotype_evdience_os_key(x) ((x).overlapSite) +KRADIX_SORT_INIT(haplotype_evdience_os_srt, haplotype_evdience, haplotype_evdience_os_key, member_size(haplotype_evdience, overlapSite)) + +#define overlap_region_dp_key(x) ((x).x_pos_e) +KRADIX_SORT_INIT(overlap_region_dp_srt, overlap_region, overlap_region_dp_key, member_size(overlap_region, x_pos_e)) + +#define window_list_xs_key(x) ((x).x_start) +KRADIX_SORT_INIT(window_list_xs_srt, window_list, window_list_xs_key, member_size(window_list, x_start)) + +#define uov_qs_key(p) ((p).qs) +KRADIX_SORT_INIT(uov_srt_qs, ul_ov_t, uov_qs_key, member_size(ul_ov_t, qs)) + +#define k_mer_hit_self_key(p) ((p).self_offset) +KRADIX_SORT_INIT(k_mer_hit_self, k_mer_hit, k_mer_hit_self_key, member_size(k_mer_hit, self_offset)) + +#define k_mer_hit_off_key(p) ((p).offset) +KRADIX_SORT_INIT(k_mer_hit_off, k_mer_hit, k_mer_hit_off_key, member_size(k_mer_hit, offset)) + +#define ul_ov_srt_qs1_key(p) ((p).qs) +KRADIX_SORT_INIT(ul_ov_srt_qs1, ul_ov_t, ul_ov_srt_qs1_key, member_size(ul_ov_t, qs)) + +#define ul_ov_srt_tn1_key(p) ((p).tn) +KRADIX_SORT_INIT(ul_ov_srt_tn1, ul_ov_t, ul_ov_srt_tn1_key, member_size(ul_ov_t, tn)) + +#define ul_ov_srt_qn1_key(p) ((p).qn) +KRADIX_SORT_INIT(ul_ov_srt_qn1, ul_ov_t, ul_ov_srt_qn1_key, member_size(ul_ov_t, qn)) + +#define ul_ov_srt_qe1_key(p) ((p).qe) +KRADIX_SORT_INIT(ul_ov_srt_qe1, ul_ov_t, ul_ov_srt_qe1_key, member_size(ul_ov_t, qe)) + +#define ul_ov_srt_ts1_key(p) ((p).ts) +KRADIX_SORT_INIT(ul_ov_srt_ts1, ul_ov_t, ul_ov_srt_ts1_key, member_size(ul_ov_t, ts)) + +#define MAX_SEC_ERR (0x3fffffffU) + + +int ha_ov_type(const overlap_region *r, uint32_t len); +void set_lchain_dp_op(uint32_t is_accurate, uint32_t mz_k, int64_t *max_skip, int64_t *max_iter, int64_t *max_dis, double *chn_pen_gap, double *chn_pen_skip, int64_t *quick_check); + +void clear_Round2_alignment(Round2_alignment* h) +{ + clear_Correct_dumy_pure(&(h->dumy)); + clear_Cigar_record(&(h->cigar)); + clear_Cigar_record(&(h->tmp_cigar)); + h->obtained_cigar_length = 0; +} + +void init_Round2_alignment(Round2_alignment* h) +{ + init_Correct_dumy(&(h->dumy)); + init_Cigar_record(&(h->cigar)); + init_Cigar_record(&(h->tmp_cigar)); + h->obtained_cigar_length = 0; +} + +void init_Round2_alignment_buf(Round2_alignment* h, void *km) +{ + init_Correct_dumy_buf(&(h->dumy), km); + init_Cigar_record_buf(&(h->cigar), km); + init_Cigar_record_buf(&(h->tmp_cigar), km); + h->obtained_cigar_length = 0; +} + +void destory_Round2_alignment(Round2_alignment* h) +{ + destory_Correct_dumy(&(h->dumy)); + destory_Cigar_record(&(h->cigar)); + destory_Cigar_record(&(h->tmp_cigar)); +} + + + +inline int get_interval(long long window_start, long long window_end, overlap_region_alloc* overlap_list, Correct_dumy* dumy, long long blockLen) +{ + uint64_t i, fud = 0; + long long Len; + if(window_start == 0) dumy->start_i = 0; + for (i = dumy->start_i; i < overlap_list->length; i++) + { + ///this interval is smaller than all overlaps + ///in this case, the next interval should start from 0 + if (window_end < (long long)overlap_list->list[i].x_pos_s) + { + dumy->start_i = 0; + dumy->length = 0; + dumy->lengthNT = 0; + return 0; + } + else ///if window_end >= overlap_list->list[i].x_pos_s,this overlap might be overlapped with current interval + { + dumy->start_i = i; + break; + } + } + + + ///this interval is larger than all overlaps, so we don't need to scan next overlap + if (i >= overlap_list->length) + { + dumy->start_i = overlap_list->length; + dumy->length = 0; + dumy->lengthNT = 0; + return -2; + } + + dumy->length = 0; + dumy->lengthNT = 0; + fud = 0; + + for (; i < overlap_list->length; i++) + { + if((Len = OVERLAP(window_start, window_end, (long long)overlap_list->list[i].x_pos_s, (long long)overlap_list->list[i].x_pos_e)) > 0) + { + ///sometimes the length of window > WINDOW, but overlap length == WINDOW + // if (Len == WINDOW && window_end - window_start + 1 == WINDOW) + if (Len == blockLen && window_end - window_start + 1 == blockLen) + { + dumy->overlapID[dumy->length] = i; + dumy->length++; + } + else + { + dumy->lengthNT++; + dumy->overlapID[dumy->size - dumy->lengthNT] = i; + } + if(fud == 0) fud = 1, dumy->start_i = i; + } + + if((long long)overlap_list->list[i].x_pos_s > window_end) + { + break; + } + } + + if ( dumy->length + dumy->lengthNT == 0) + { + return 0; + } + else + { + return 1; + } +} + + +inline int get_available_interval(long long window_start, long long window_end, overlap_region_alloc* overlap_list, Correct_dumy* dumy) +{ + uint64_t i, fud = 0; + long long Len; + if(window_start == 0) dumy->start_i = 0; + for (i = dumy->start_i; i < overlap_list->length; i++) + { + ///this interval is smaller than all overlaps + ///in this case, the next interval should start from 0 + if (window_end < (long long)overlap_list->list[i].x_pos_s) + { + dumy->start_i = 0; + dumy->length = 0; + dumy->lengthNT = 0; + return 0; + } + else ///if window_end >= overlap_list->list[i].x_pos_s,this overlap might be overlapped with current interval + { + dumy->start_i = i; + break; + } + } + + ///this interval is larger than all overlaps, so we don't need to scan next overlap + if (i >= overlap_list->length) + { + dumy->start_i = overlap_list->length; + dumy->length = 0; + dumy->lengthNT = 0; + return -2; + } + + dumy->length = 0; + dumy->lengthNT = 0; + fud = 0; + + + long long fake_length = 0; + + for (; i < overlap_list->length; i++) + { + ///check if the interval is overlapped with current overlap + if((Len = OVERLAP(window_start, window_end, (long long)overlap_list->list[i].x_pos_s, (long long)overlap_list->list[i].x_pos_e)) > 0) + { + ///number of overlaps + fake_length++; + + ///check if this overlap is available + if (overlap_list->list[i].is_match == 1) + { + dumy->overlapID[dumy->length] = i; + dumy->length++; + } + if(fud == 0) fud = 1, dumy->start_i = i; + } + + if((long long)overlap_list->list[i].x_pos_s > window_end) + { + break; + } + } + + ///fake_length is the number of overlaps, instead of the number of available overlaps + if (fake_length == 0) + { + return 0; + } + else + { + return 1; + } +} + +///Len = OVERLAP(window_start, window_end, overlap_list->list[i].x_pos_s, overlap_list->list[i].x_pos_e)) + +void print_string(char* s, int l) +{ + int i; + for (i = 0; i < l; i++) + { + fprintf(stderr, "%c", s[i]); + } + + fprintf(stderr, "\n"); + +} + + + + +void fill_subregion(char* r, long long start_pos, long long length, uint8_t strand, All_reads* R_INF, long long ID, +int extra_begin, int extra_end) +{ + + recover_UC_Read_sub_region(r+extra_begin, start_pos, length, strand, R_INF, ID); + memset(r, 'N', extra_begin); + memset(r+extra_begin+length, 'N', extra_end); +} + +void fill_subregion_ul(char* r, long long start_pos, long long length, uint8_t strand, const ul_idx_t *uref, long long ID, +int extra_begin, int extra_end) +{ + retrieve_u_seq(NULL, r+extra_begin, &(uref->ug->u.a[ID]), strand, start_pos, length, NULL); + memset(r, 'N', extra_begin); + memset(r+extra_begin+length, 'N', extra_end); +} + +int determine_overlap_region(int threshold, long long y_start, long long y_ID, long long Window_Len, /**All_reads* R_INF**/long long y_len, +int* r_extra_begin, int* r_extra_end, long long* r_y_start, long long* r_y_length) +{ + int extra_begin; + int extra_end; + long long currentIDLen; + long long o_len; + + ///the length of y + // currentIDLen = Get_READ_LENGTH((*R_INF), y_ID); + currentIDLen = y_len; + + ///since Window_Len == x_len + (threshold << 1) + if(y_start < 0 || currentIDLen <= y_start || + currentIDLen - y_start + 2 * threshold + THRESHOLD_MAX_SIZE < Window_Len) + { + return 0; + } + + extra_begin = extra_end = 0; + ///y maybe less than 0 + y_start = y_start - threshold; + o_len = MIN(Window_Len, currentIDLen - y_start); + extra_end = Window_Len - o_len; + + if (y_start < 0) + { + extra_begin = -y_start; + y_start = 0; + o_len = o_len - extra_begin; + } + + (*r_extra_begin) = extra_begin; + (*r_extra_end) = extra_end; + (*r_y_start) = y_start; + (*r_y_length) = o_len; + + return 1; +} + + +int verify_single_window(long long x_start, long long x_end, +long long overlap_x_s, long long overlap_y_s, int x_id, +int y_id, int x_strand, char* x_buffer, char* y_buffer, +All_reads* R_INF) +{ + char* x_string = NULL; + char* y_string = NULL; + int extra_begin, extra_end, x_len, threshold; + long long y_start; + long long Window_Len, o_len; + unsigned int error; + + + + x_len = x_end - x_start + 1; + threshold = x_len * asm_opt.max_ov_diff_ec; + /****************************may have bugs********************************/ + threshold = Adjust_Threshold(threshold, x_len); + /****************************may have bugs********************************/ + + y_start = (x_start - overlap_x_s) + overlap_y_s; + + Window_Len = x_len + (threshold << 1); + + if(!determine_overlap_region(threshold, y_start, y_id, Window_Len, Get_READ_LENGTH((*R_INF), y_id), + &extra_begin, &extra_end, &y_start, &o_len)) + { + return 0; + } + + ///use unusual direction here + /** + fill_subregion(y_buffer, y_start, o_len, y_strand, R_INF, y_id, extra_begin, extra_end); + ///x is always forward strand + recover_UC_Read_sub_region(x_buffer, x_start, x_len, 0, R_INF, x_id); + **/ + ///use unusual direction here, here y is always forward strand + fill_subregion(y_buffer, y_start, o_len, 0, R_INF, y_id, extra_begin, extra_end); + recover_UC_Read_sub_region(x_buffer, x_start, x_len, x_strand, R_INF, x_id); + + + x_string = x_buffer; + y_string = y_buffer; + + Reserve_Banded_BPM(y_string, Window_Len, x_string, x_len, threshold, &error); + + if (error!=(unsigned int)-1) + { + return 1; + } + + return 0; +} + +void verify_window(long long window_start, long long window_end, overlap_region_alloc* overlap_list,Correct_dumy* dumy, All_reads* R_INF, +char* r_string) +{ + long long i; + long long currentID; + long long x_start, y_start, o_len; + long long Window_Len = WINDOW + (THRESHOLD << 1); + char* x_string = NULL; + char* y_string = NULL; + long long x_end, x_len; + int end_site; + unsigned int error; + int groupLen = 0; + int return_sites[GROUP_SIZE]; + unsigned int return_sites_error[GROUP_SIZE]; + uint64_t overlapID[GROUP_SIZE]; + uint64_t y_startGroup[GROUP_SIZE]; + int y_extra_begin[GROUP_SIZE]; + int y_extra_end[GROUP_SIZE]; + int error_threshold[GROUP_SIZE]; + int extra_begin; + int extra_end; + + ///here are overlaps fully covered by WINDOW + for (i = 0; i < (long long)dumy->length; i++) + { + extra_begin = extra_end = 0; + ///if the window has been fully covered, the interval at x is [window_start, window_end] + x_len = WINDOW; + currentID = dumy->overlapID[i]; + x_start = window_start; + ///offset of y + y_start = (x_start - overlap_list->list[currentID].x_pos_s) + overlap_list->list[currentID].y_pos_s; + /****************************may have bugs********************************/ + y_start += y_start_offset(x_start, &(overlap_list->list[currentID].f_cigar)); + /****************************may have bugs********************************/ + + + if(!determine_overlap_region(THRESHOLD, y_start, overlap_list->list[currentID].y_id, Window_Len, Get_READ_LENGTH((*R_INF), overlap_list->list[currentID].y_id), + &extra_begin, &extra_end, &y_start, &o_len)) { + continue; + } + + fill_subregion(dumy->overlap_region_group[groupLen], y_start, o_len, overlap_list->list[currentID].y_pos_strand, + R_INF, overlap_list->list[currentID].y_id, extra_begin, extra_end); + + y_extra_begin[groupLen] = extra_begin; + y_extra_end[groupLen] = extra_end; + overlapID[groupLen] = currentID; + y_startGroup[groupLen] = y_start; + error_threshold[groupLen] = THRESHOLD; + x_string = r_string + x_start; + groupLen++; + + + if (groupLen == GROUP_SIZE) + { + Reserve_Banded_BPM_4_SSE_only(dumy->overlap_region_group[0], dumy->overlap_region_group[1], + dumy->overlap_region_group[2], dumy->overlap_region_group[3], Window_Len, x_string, WINDOW, + return_sites, return_sites_error, THRESHOLD, dumy->Peq_SSE); + groupLen = 0; + + + if (return_sites_error[0]!=(unsigned int)-1) { + overlap_list->list[overlapID[0]].align_length += x_len; + + append_window_list(&overlap_list->list[overlapID[0]], window_start, window_end, + y_startGroup[0], y_startGroup[0] + return_sites[0], (int)return_sites_error[0], + y_extra_begin[0], y_extra_end[0], error_threshold[0], WINDOW, NULL); + } + + + if (return_sites_error[1]!=(unsigned int)-1) { + overlap_list->list[overlapID[1]].align_length += x_len; + + append_window_list(&overlap_list->list[overlapID[1]], window_start, window_end, + y_startGroup[1], y_startGroup[1] + return_sites[1], (int)return_sites_error[1], + y_extra_begin[1], y_extra_end[1], error_threshold[1], WINDOW, NULL); + } + + + if (return_sites_error[2]!=(unsigned int)-1) { + overlap_list->list[overlapID[2]].align_length += x_len; + + append_window_list(&overlap_list->list[overlapID[2]], window_start, window_end, + y_startGroup[2], y_startGroup[2] + return_sites[2], (int)return_sites_error[2], + y_extra_begin[2], y_extra_end[2], error_threshold[2], WINDOW, NULL); + } + + + if (return_sites_error[3]!=(unsigned int)-1) { + overlap_list->list[overlapID[3]].align_length += x_len; + + append_window_list(&overlap_list->list[overlapID[3]], window_start, window_end, + y_startGroup[3], y_startGroup[3] + return_sites[3], (int)return_sites_error[3], + y_extra_begin[3], y_extra_end[3], error_threshold[3], WINDOW, NULL); + } + } + } + + if (groupLen == 1) + { + end_site = Reserve_Banded_BPM(dumy->overlap_region_group[0], Window_Len, x_string, WINDOW, THRESHOLD, &error); + + if (error!=(unsigned int)-1) { + overlap_list->list[overlapID[0]].align_length += x_len; + + append_window_list(&overlap_list->list[overlapID[0]], window_start, window_end, + y_startGroup[0], y_startGroup[0] + end_site, (int)error, + y_extra_begin[0], y_extra_end[0], error_threshold[0], WINDOW, NULL); + } + } + else if (groupLen > 1) + { + Reserve_Banded_BPM_4_SSE_only(dumy->overlap_region_group[0], dumy->overlap_region_group[1], + dumy->overlap_region_group[2], dumy->overlap_region_group[3], Window_Len, x_string, WINDOW, + return_sites, return_sites_error, THRESHOLD, dumy->Peq_SSE); + + for (i = 0; i < groupLen; i++) + { + if (return_sites_error[i]!=(unsigned int)-1) { + overlap_list->list[overlapID[i]].align_length += x_len; + append_window_list(&overlap_list->list[overlapID[i]], window_start, window_end, + y_startGroup[i], y_startGroup[i] + return_sites[i], (int)return_sites_error[i], + y_extra_begin[i], y_extra_end[i], error_threshold[i], WINDOW, NULL); + } + } + + groupLen = 0; + } + + long long reverse_i = dumy->size - 1; + int threshold; + + ///here are overlaps partially covered by WINDOW + for (i = 0; i < (long long)dumy->lengthNT; i++) + { + extra_begin = extra_end = 0; + currentID = dumy->overlapID[reverse_i--]; + x_start = MAX(window_start, (long long)overlap_list->list[currentID].x_pos_s); + x_end = MIN(window_end, (long long)overlap_list->list[currentID].x_pos_e); + + ///overlap length between [window_start, window_end] + x_len = x_end - x_start + 1; + threshold = x_len * asm_opt.max_ov_diff_ec; + /****************************may have bugs********************************/ + threshold = Adjust_Threshold(threshold, x_len); + if(threshold > THRESHOLD_MAX_SIZE) threshold = THRESHOLD_MAX_SIZE; + /****************************may have bugs********************************/ + + ///offset of y + y_start = (x_start - overlap_list->list[currentID].x_pos_s) + overlap_list->list[currentID].y_pos_s; + /****************************may have bugs********************************/ + y_start += y_start_offset(x_start, &(overlap_list->list[currentID].f_cigar)); + /****************************may have bugs********************************/ + + Window_Len = x_len + (threshold << 1); + + if(!determine_overlap_region(threshold, y_start, overlap_list->list[currentID].y_id, Window_Len, Get_READ_LENGTH((*R_INF), overlap_list->list[currentID].y_id), + &extra_begin, &extra_end, &y_start, &o_len)) { + continue; + } + + fill_subregion(dumy->overlap_region, y_start, o_len, overlap_list->list[currentID].y_pos_strand, + R_INF, overlap_list->list[currentID].y_id, extra_begin, extra_end); + + x_string = r_string + x_start; + y_string = dumy->overlap_region; + + end_site = Reserve_Banded_BPM(y_string, Window_Len, x_string, x_len, threshold, &error); + + if (error!=(unsigned int)-1) { + overlap_list->list[currentID].align_length += x_len; + append_window_list(&overlap_list->list[currentID], x_start, x_end, y_start, y_start + end_site, (int)error, + extra_begin, extra_end, threshold, WINDOW, NULL); + } + } +} + + +void verify_ul_window(long long window_start, long long window_end, overlap_region_alloc* overlap_list,Correct_dumy* dumy, const ul_idx_t *uref, +char* r_string, double max_ov_diff_ec, long long blockLen, long long max_error, void *km) +{ + long long i; + long long currentID; + long long x_start, y_start, o_len; + long long Window_Len = blockLen + (max_error << 1); + char* x_string = NULL; + char* y_string = NULL; + long long x_end, x_len; + int end_site; + unsigned int error; + int groupLen = 0; + int return_sites[GROUP_SIZE]; + unsigned int return_sites_error[GROUP_SIZE]; + uint64_t overlapID[GROUP_SIZE]; + uint64_t y_startGroup[GROUP_SIZE]; + int y_extra_begin[GROUP_SIZE]; + int y_extra_end[GROUP_SIZE]; + int error_threshold[GROUP_SIZE]; + int extra_begin; + int extra_end; + + ///here are overlaps fully covered by blockLen + for (i = 0; i < (long long)dumy->length; i++) + { + extra_begin = extra_end = 0; + ///if the window has been fully covered, the interval at x is [window_start, window_end] + x_len = blockLen; + currentID = dumy->overlapID[i]; + x_start = window_start; + ///offset of y + y_start = (x_start - overlap_list->list[currentID].x_pos_s) + overlap_list->list[currentID].y_pos_s; + /****************************may have bugs********************************/ + y_start += y_start_offset(x_start, &(overlap_list->list[currentID].f_cigar)); + /****************************may have bugs********************************/ + + + if(!determine_overlap_region(max_error, y_start, overlap_list->list[currentID].y_id, Window_Len, uref->ug->u.a[overlap_list->list[currentID].y_id].len, + &extra_begin, &extra_end, &y_start, &o_len)) { + continue; + } + + // if(overlap_list->list[currentID].y_id == 4) { + // fprintf(stderr, "[M::%s] q_s::%lld, t_s::%lld, t_pri_l::%lld, aux_beg::%d, aux_end::%d, aln_l::%lld\n", __func__, + // x_start, y_start, o_len, extra_begin, extra_end, Window_Len); + // } + + fill_subregion_ul(dumy->overlap_region_group[groupLen], y_start, o_len, overlap_list->list[currentID].y_pos_strand, + uref, overlap_list->list[currentID].y_id, extra_begin, extra_end); + + y_extra_begin[groupLen] = extra_begin; + y_extra_end[groupLen] = extra_end; + overlapID[groupLen] = currentID; + y_startGroup[groupLen] = y_start; + error_threshold[groupLen] = max_error; + x_string = r_string + x_start; + groupLen++; + + + if (groupLen == GROUP_SIZE) + { + // Reserve_Banded_BPM_4_SSE_only(dumy->overlap_region_group[0], dumy->overlap_region_group[1], + // dumy->overlap_region_group[2], dumy->overlap_region_group[3], Window_Len, x_string, blockLen, + // return_sites, return_sites_error, max_error, dumy->Peq_SSE); + return_sites[0] = + Reserve_Banded_BPM(dumy->overlap_region_group[0], Window_Len, x_string, blockLen, max_error, &return_sites_error[0]); + return_sites[1] = + Reserve_Banded_BPM(dumy->overlap_region_group[1], Window_Len, x_string, blockLen, max_error, &return_sites_error[1]); + return_sites[2] = + Reserve_Banded_BPM(dumy->overlap_region_group[2], Window_Len, x_string, blockLen, max_error, &return_sites_error[2]); + return_sites[3] = + Reserve_Banded_BPM(dumy->overlap_region_group[3], Window_Len, x_string, blockLen, max_error, &return_sites_error[3]); + + + + + + groupLen = 0; + + if (return_sites_error[0]!=(unsigned int)-1) { + overlap_list->list[overlapID[0]].align_length += x_len; + + append_window_list(&overlap_list->list[overlapID[0]], window_start, window_end, + y_startGroup[0], y_startGroup[0] + return_sites[0], (int)return_sites_error[0], + y_extra_begin[0], y_extra_end[0], error_threshold[0], blockLen, km); + } + + + if (return_sites_error[1]!=(unsigned int)-1) { + overlap_list->list[overlapID[1]].align_length += x_len; + append_window_list(&overlap_list->list[overlapID[1]], window_start, window_end, + y_startGroup[1], y_startGroup[1] + return_sites[1], (int)return_sites_error[1], + y_extra_begin[1], y_extra_end[1], error_threshold[1], blockLen, km); + } + + + if (return_sites_error[2]!=(unsigned int)-1) { + overlap_list->list[overlapID[2]].align_length += x_len; + + append_window_list(&overlap_list->list[overlapID[2]], window_start, window_end, + y_startGroup[2], y_startGroup[2] + return_sites[2], (int)return_sites_error[2], + y_extra_begin[2], y_extra_end[2], error_threshold[2], blockLen, km); + } + + + if (return_sites_error[3]!=(unsigned int)-1) { + overlap_list->list[overlapID[3]].align_length += x_len; + + append_window_list(&overlap_list->list[overlapID[3]], window_start, window_end, + y_startGroup[3], y_startGroup[3] + return_sites[3], (int)return_sites_error[3], + y_extra_begin[3], y_extra_end[3], error_threshold[3], blockLen, km); + } + } + } + + if (groupLen == 1) + { + end_site = Reserve_Banded_BPM(dumy->overlap_region_group[0], Window_Len, x_string, blockLen, max_error, &error); + + if (error!=(unsigned int)-1) { + overlap_list->list[overlapID[0]].align_length += x_len; + + append_window_list(&overlap_list->list[overlapID[0]], window_start, window_end, + y_startGroup[0], y_startGroup[0] + end_site, (int)error, + y_extra_begin[0], y_extra_end[0], error_threshold[0], blockLen, km); + } + } + else if (groupLen > 1) + { + // Reserve_Banded_BPM_4_SSE_only(dumy->overlap_region_group[0], dumy->overlap_region_group[1], + // dumy->overlap_region_group[2], dumy->overlap_region_group[3], Window_Len, x_string, blockLen, + // return_sites, return_sites_error, max_error, dumy->Peq_SSE); + + for (i = 0; i < groupLen; i++) + { + return_sites[i] = Reserve_Banded_BPM(dumy->overlap_region_group[i], Window_Len, x_string, blockLen, max_error, &return_sites_error[i]); + + if (return_sites_error[i]!=(unsigned int)-1) { + overlap_list->list[overlapID[i]].align_length += x_len; + append_window_list(&overlap_list->list[overlapID[i]], window_start, window_end, + y_startGroup[i], y_startGroup[i] + return_sites[i], (int)return_sites_error[i], + y_extra_begin[i], y_extra_end[i], error_threshold[i], blockLen, km); + } + } + + groupLen = 0; + } + + long long reverse_i = dumy->size - 1; + int threshold; + + ///here are overlaps partially covered by blockLen + for (i = 0; i < (long long)dumy->lengthNT; i++) + { + extra_begin = extra_end = 0; + currentID = dumy->overlapID[reverse_i--]; + x_start = MAX(window_start, (long long)overlap_list->list[currentID].x_pos_s); + x_end = MIN(window_end, (long long)overlap_list->list[currentID].x_pos_e); + + ///overlap length between [window_start, window_end] + x_len = x_end - x_start + 1; + threshold = x_len * max_ov_diff_ec; + /****************************may have bugs********************************/ + threshold = Adjust_Threshold(threshold, x_len); + if(threshold > THRESHOLD_MAX_SIZE) threshold = THRESHOLD_MAX_SIZE; + /****************************may have bugs********************************/ + + ///offset of y + y_start = (x_start - overlap_list->list[currentID].x_pos_s) + overlap_list->list[currentID].y_pos_s; + /****************************may have bugs********************************/ + y_start += y_start_offset(x_start, &(overlap_list->list[currentID].f_cigar)); + /****************************may have bugs********************************/ + + Window_Len = x_len + (threshold << 1); + + if(!determine_overlap_region(threshold, y_start, overlap_list->list[currentID].y_id, Window_Len, uref->ug->u.a[overlap_list->list[currentID].y_id].len, + &extra_begin, &extra_end, &y_start, &o_len)) { + continue; + } + + // if(overlap_list->list[currentID].y_id == 4) { + // fprintf(stderr, "[M::%s] q_s::%lld, t_s::%lld, t_pri_l::%lld, aux_beg::%d, aux_end::%d, aln_l::%lld\n", __func__, + // x_start, y_start, o_len, extra_begin, extra_end, Window_Len); + // } + + fill_subregion_ul(dumy->overlap_region, y_start, o_len, overlap_list->list[currentID].y_pos_strand, + uref, overlap_list->list[currentID].y_id, extra_begin, extra_end); + + x_string = r_string + x_start; + y_string = dumy->overlap_region; + + end_site = Reserve_Banded_BPM(y_string, Window_Len, x_string, x_len, threshold, &error); + + if (error!=(unsigned int)-1) { + overlap_list->list[currentID].align_length += x_len; + append_window_list(&overlap_list->list[currentID], x_start, x_end, y_start, y_start + end_site, (int)error, + extra_begin, extra_end, threshold, blockLen, km); + } + } +} + +int32_t init_waln(int64_t err, int64_t s, int64_t l, int64_t w_l, int64_t* aux_beg, int64_t* aux_end, int64_t* r_s, int64_t* r_l) +{ + (*aux_beg) = (*aux_end) = (*r_s) = (*r_l) = -1; + ///since w_l == x_len + (err << 1) + if((s < 0) || (s >= l) || ((l-s+(2*err)+THRESHOLD_MAX_SIZE) < w_l)) return 0; + (*aux_beg) = (*aux_end) = 0; + ///s might be less than 0 + (*r_s) = s - err; + (*r_l) = l-(*r_s); if((*r_l) > w_l) (*r_l) = w_l; + (*aux_end) = w_l - (*r_l); + + if ((*r_s) < 0) { + (*aux_beg) = -(*r_s); (*r_s) = 0; (*r_l) -= (*aux_beg); + } + return 1; +} + +///[s, e) +int64_t get_num_wins(int64_t s, int64_t e, int64_t block_s) +{ + int64_t nl = e - ((s/block_s)*block_s), nw; + nw = (nl/block_s); if((nl%block_s)>0) nw++; + return nw; +} + +void gen_str_seq(char *dst, int64_t s, int64_t pri_l, uint8_t rev, const ul_idx_t *uref, long long id, int64_t aux_beg, int64_t aux_end) +{ + // int64_t l = pri_l + aux_beg + aux_end; + memset(dst, 'N', aux_beg); + retrieve_u_seq(NULL, dst+aux_beg, &(uref->ug->u.a[id]), rev, s, pri_l, NULL); + memset(dst+aux_beg+pri_l, 'N', aux_end); +} + +void verify_ul_window_s(overlap_region *z, const ul_idx_t *uref, char* qstr, char *tstr, +double e_rate, int64_t w_l, int64_t e_max, void *km) +{ + int64_t q_s, q_e, nw, k, q_l; + int64_t aux_beg, aux_end, t_s, thre, aln_l, t_pri_l, t_end; + char *q_string, *t_string; unsigned int error; + z->w_list.n = 0; nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, w_l); + get_win_se_by_normalize_xs(z, (z->x_pos_s/w_l)*w_l, w_l, &q_s, &q_e); + // q_s = z->x_pos_s; get_win_id_by_s(z, q_s, w_l, &q_e); + for (k = 0; k < nw; k++) { + aux_beg = aux_end = 0; q_l = 1 + q_e - q_s; + thre = q_l*e_rate; thre = Adjust_Threshold(thre, q_l); + if(thre > THRESHOLD_MAX_SIZE) thre = THRESHOLD_MAX_SIZE; + ///offset of y + t_s = (q_s - z->x_pos_s) + z->y_pos_s; + t_s += y_start_offset(q_s, &(z->f_cigar)); + + aln_l = q_l + (thre<<1); + // if(z->y_id == 115) { + // fprintf(stderr, "+[M::] q_s::%ld, t_s::%ld, t_pri_l::%ld, aux_beg::%ld, aux_end::%ld, aln_l::%ld, t_end::%ld, error::%u\n", + // q_s, t_s, t_pri_l, aux_beg, aux_end, aln_l, t_end, error); + // } + if(init_waln(thre, t_s, uref->ug->u.a[z->y_id].len, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) { + gen_str_seq(tstr, t_s, t_pri_l, z->y_pos_strand, uref, z->y_id, aux_beg, aux_end); + q_string = qstr+q_s; t_string = tstr; + t_end = Reserve_Banded_BPM(t_string, aln_l, q_string, q_l, thre, &error); + // if(z->y_id == 115) { + // fprintf(stderr, "-[M::] q_s::%ld, t_s::%ld, t_pri_l::%ld, aux_beg::%ld, aux_end::%ld, aln_l::%ld, t_end::%ld, error::%u, thre::%ld\n", + // q_s, t_s, t_pri_l, aux_beg, aux_end, aln_l, t_end, error, thre); + // } + if (error!=((unsigned int)-1)) { + z->align_length += q_l; + ///t_s do not have aux_beg, while t_s + t_end (aka, te) has + append_window_list(z, q_s, q_e, t_s, t_s + t_end, error, aux_beg, aux_end, thre, w_l, km); + } + } + q_s = q_e + 1; q_e = q_s + w_l - 1; + if(q_e >= (int64_t)z->x_pos_e) q_e = z->x_pos_e; + } + + // if(q_e != (int64_t)z->x_pos_e) { + // fprintf(stderr, "[M::%s] q_e::%ld, z->x_pos_s::%u, z->x_pos_e::%u, w_l::%ld, nw::%ld\n", __func__, + // q_e, z->x_pos_s, z->x_pos_e, w_l, nw); + // } + assert(q_e == (int64_t)z->x_pos_e); +} + +///error_rate should be 30% +long long get_high_error(long long x_start, long long x_end, +long long y_start, long long y_end, long long y_id, long long y_strand, long long pre_threshold, +long long n_steps, float error_rate, All_reads* R_INF, Correct_dumy* dumy, +UC_Read* g_read) +{ + long long stepLen = (x_end - x_start + 1) / n_steps; + if((x_end - x_start + 1) % n_steps != 0) + { + stepLen++; + } + long long SubLen, SubWindowLen; + long long SubThreshold = THRESHOLD_MAX_SIZE; + int extra_begin, extra_end; + long long o_len; + long long T_error = 0; + y_start = y_start + pre_threshold; + + while (x_start <= x_end) + { + SubLen = x_end - x_start + 1; + if(SubLen > stepLen) + { + SubLen = stepLen; + } + + + SubThreshold = SubLen * error_rate; + if(SubThreshold > THRESHOLD_MAX_SIZE) + { + SubThreshold = THRESHOLD_MAX_SIZE; + } + + SubThreshold = Adjust_Threshold(SubThreshold, SubLen); + + + SubWindowLen = SubLen + (SubThreshold << 1); + if(determine_overlap_region(SubThreshold, y_start, y_id, SubWindowLen, Get_READ_LENGTH((*R_INF), y_id), + &extra_begin, &extra_end, &y_start, &o_len) == 0) + { + T_error = T_error + (x_end - x_start + 1) * error_rate * 1.5; + break; + } + + fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, R_INF, y_id, + extra_begin, extra_end); + + char* x_string = g_read->seq + x_start; + char* y_string = dumy->overlap_region; + int end_site; + unsigned int error; + + end_site = Reserve_Banded_BPM(y_string, SubWindowLen, x_string, SubLen, SubThreshold, &error); + + ///if error = -1, unmatched + if (error!=(unsigned int)-1) + { + T_error = T_error + error; + y_start = y_start + end_site - extra_begin + 1; + } + else + { + T_error = T_error + SubLen * error_rate * 1.5; + y_start = y_start + SubThreshold - extra_begin + SubLen; + } + + x_start = x_start + SubLen; + } + + + return T_error; +} + +inline int double_error_threshold(int pre_threshold, int x_len) +{ + + pre_threshold = Adjust_Threshold(pre_threshold, x_len); + int threshold = pre_threshold * 2; + ///may have some bugs + if(x_len >= 300 && threshold < THRESHOLD_MAX_SIZE) + { + threshold = THRESHOLD_MAX_SIZE; + } + + if(threshold > THRESHOLD_MAX_SIZE) + { + threshold = THRESHOLD_MAX_SIZE; + } + + return threshold; +} + +inline int double_ul_error_threshold(int pre_threshold, int x_len) +{ + + pre_threshold = Adjust_Threshold(pre_threshold, x_len); + int threshold = THRESHOLD_UL_MAX * x_len; + if(threshold < pre_threshold) threshold = pre_threshold; + if(threshold > THRESHOLD_MAX_SIZE) threshold = THRESHOLD_MAX_SIZE; + return threshold; +} + + +inline int verify_sub_window(All_reads* R_INF, Correct_dumy* dumy, UC_Read* g_read, +long long x_beg, long long xLen, long long y_beg, long long yLen, uint64_t y_id, +uint64_t y_pos_strand, int threshold, int alignment_strand, +unsigned int* get_error, int* get_y_end, int* get_x_end, int* get_aligned_xLen) +{ + (*get_aligned_xLen) = 0; + (*get_y_end) = -1; + (*get_x_end) = -1; + (*get_error) = (unsigned int)-1; + + int extra_begin, extra_end, r_x_end, r_y_end, aligned_xLen; + long long o_len; + unsigned int r_error; + if(!determine_overlap_region(threshold, y_beg, y_id, yLen, + Get_READ_LENGTH((*R_INF), y_id), &extra_begin, &extra_end, &y_beg, &o_len)) + { + return 0; + } + + fill_subregion(dumy->overlap_region, y_beg, o_len, y_pos_strand, R_INF, + y_id, extra_begin, extra_end); + + char* x_string = g_read->seq + x_beg; + char* y_string = dumy->overlap_region; + + aligned_xLen = 0; + + alignment_extension(y_string, yLen, x_string, xLen, threshold, + alignment_strand, &r_error, &r_y_end, &r_x_end, &aligned_xLen); + + (*get_error) = r_error; + (*get_y_end) = r_y_end; + (*get_x_end) = r_x_end; + (*get_aligned_xLen) = aligned_xLen; + + if(aligned_xLen == 0) + { + return 0; + } + else + { + return 1; + } +} + +inline int verify_ul_sub_window(const ul_idx_t *uref, Correct_dumy* dumy, UC_Read* g_read, +long long x_beg, long long xLen, long long y_beg, long long yLen, uint64_t y_id, +uint64_t y_pos_strand, int threshold, int alignment_strand, +unsigned int* get_error, int* get_y_end, int* get_x_end, int* get_aligned_xLen) +{ + (*get_aligned_xLen) = 0; + (*get_y_end) = -1; + (*get_x_end) = -1; + (*get_error) = (unsigned int)-1; + + int extra_begin, extra_end, r_x_end, r_y_end, aligned_xLen; + long long o_len; + unsigned int r_error; + if(!determine_overlap_region(threshold, y_beg, y_id, yLen, + uref->ug->u.a[y_id].len, &extra_begin, &extra_end, &y_beg, &o_len)) + { + return 0; + } + + fill_subregion_ul(dumy->overlap_region, y_beg, o_len, y_pos_strand, uref, + y_id, extra_begin, extra_end); + + // if(y_id == 6) { + // fprintf(stderr, "-[M::%s::aln_dir->%d] qs->%lld, ts->%lld, thres->%d, aux_beg->%d, aux_end->%d, t_pri_l->%lld\n", + // __func__, alignment_strand, x_beg, y_beg, threshold, extra_begin, extra_end, o_len); + // } + + char* x_string = g_read->seq + x_beg; + char* y_string = dumy->overlap_region; + + aligned_xLen = 0; + + alignment_extension(y_string, yLen, x_string, xLen, threshold, + alignment_strand, &r_error, &r_y_end, &r_x_end, &aligned_xLen); + + (*get_error) = r_error; + (*get_y_end) = r_y_end; + (*get_x_end) = r_x_end; + (*get_aligned_xLen) = aligned_xLen; + + if(aligned_xLen == 0) + { + return 0; + } + else + { + return 1; + } +} + +inline int64_t get_init_err_thres(int64_t len, double e_rate, int64_t block_s, int64_t block_err) +{ + if(len >= block_s) return block_err; + int64_t thres = len * e_rate; + thres = Adjust_Threshold(thres, len); + if(thres > THRESHOLD_MAX_SIZE) thres = THRESHOLD_MAX_SIZE; + return thres; +} + + +uint32_t get_init_paras(All_reads* rref, const ul_idx_t *uref, overlap_region *z, int64_t x_s, int64_t x_e, double e_rate, int64_t block_s, + int64_t *r_ys, int64_t *r_ex_beg, int64_t *r_ex_end, int64_t *r_err_thre) +{ + int e, ex_beg, ex_end; long long y_s, o_len, Window_Len; + e = get_init_err_thres(x_e+1-x_s, e_rate, block_s, rref?THRESHOLD:THRESHOLD_MAX_SIZE); + y_s = (x_s-z->x_pos_s) + z->y_pos_s; y_s += y_start_offset(x_s, &(z->f_cigar)); + Window_Len = (x_e+1-x_s) + (e<<1); + + if(!determine_overlap_region(e, y_s, z->y_id, Window_Len, (rref?(Get_READ_LENGTH((*rref), z->y_id)):(uref->ug->u.a[z->y_id].len)), + &ex_beg, &ex_end, &y_s, &o_len)) { + return 0; + } + (*r_ys) = y_s; (*r_ex_beg) = ex_beg; (*r_ex_end) = ex_end; (*r_err_thre) = e; + return 1; +} + +int64_t check_coverage_gap(uint64_t *v_idx, uint64_t w_s, uint64_t w_e, int64_t block_s) +{ + int64_t wid = w_s/block_s, a_n = (uint32_t)(v_idx[wid]), k; + uint64_t *a = v_idx + (v_idx[wid]>>32); + for (k = 0; k < a_n; k++) { + if(((a[k]>>32) == w_s) && (((uint32_t)(a[k])) == w_e)) return 1; + } + return 0; +} + +inline double non_trim_error_rate(overlap_region *z, All_reads* rref, const ul_idx_t *uref, const kvec_t_u64_warp* v_idx, Correct_dumy* dumy, UC_Read* g_read, double e_rate, int64_t block_s) +{ + int64_t nw, aw = z->w_list.n, k, m, w_id, wn_id, w_s, w_e, idx_e, tErr = 0, tLen = 0, y_s, ex_beg, ex_end, err_thre, p_err_thre; + int64_t x_len, Window_Len, y_beg_left, y_beg_right; + unsigned int r_error_left, r_error_right; int32_t r_x_end_left, r_y_end_left, aligned_xLen_left, r_x_end_right, r_y_end_right, aligned_xLen_right; + nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); + assert(nw >= aw && aw > 0); + + for (k = aw-1, idx_e = nw; k >= 0; k--) { + w_id = get_win_id_by_e(z, z->w_list.a[k].x_end, block_s, &w_s); + assert(w_s == z->w_list.a[k].x_start && w_id < idx_e && k <= w_id); + tLen += z->w_list.a[k].x_end + 1 - z->w_list.a[k].x_start; + tErr += z->w_list.a[k].error;///matched window + // if(z->y_id == 1) { + // fprintf(stderr, "+[M::%s] ws->%d, we->%d, tot_l->%ld, tot_e->%ld\n", + // __func__, z->w_list.a[k].x_start, z->w_list.a[k].x_end, tLen, tErr); + // } + // if(k != w_id) z->w_list.a[w_id] = z->w_list.a[k]; + ///from mapped window w_list.a[k] to the following unmapped windows + for (m = w_id+1, w_e = z->w_list.a[k].x_end; m < idx_e; m++) { + w_s = w_e + 1; + wn_id = get_win_id_by_s(z, w_s, block_s, &w_e); + assert(wn_id == m); x_len = w_e + 1 - w_s; tLen += x_len; + ///check if there are some windows that cannot be algined by any overlaps/unitigs + ///if no, it is likely that the UL read itself has issues + if(uref && v_idx && z->is_match == 4) { + if(check_coverage_gap(v_idx->a.a, w_s, w_e, block_s)) { + tErr += THRESHOLD_MAX_SIZE; + // if(z->y_id == 1) { + // fprintf(stderr, "-[M::%s] ws->%ld, we->%ld, tot_l->%ld, tot_e->%ld\n", __func__, w_s, w_e, tLen, tErr); + // } + continue; + } + } + if(!get_init_paras(rref, uref, z, w_s, w_e, e_rate, block_s, &y_s, &ex_beg, &ex_end, &err_thre)) { + tErr += x_len; + // if(z->y_id == 1) { + // fprintf(stderr, "-[M::%s] ws->%ld, we->%ld, tot_l->%ld, tot_e->%ld\n", __func__, w_s, w_e, tLen, tErr); + // } + continue; + } + p_err_thre = err_thre; + + if(rref) { + err_thre = double_error_threshold(err_thre, x_len); + } else { + err_thre = double_ul_error_threshold(err_thre, x_len); + } + Window_Len = x_len + (err_thre << 1); + r_error_left = r_error_right = 0; + aligned_xLen_left = aligned_xLen_right = 0; + y_beg_left = y_beg_right = -1; + + if(m == w_id+1) { ///if the previous window is mapped + y_beg_left = z->w_list.a[k].y_end + 1;///incorrect + } + + if(m+1 == idx_e && k+1 < aw) { ///if the next window is mapped + y_beg_right = z->w_list.a[k+1].y_start-x_len;///incorrect + } + + if(y_beg_left == -1 && y_beg_right == -1) { + y_beg_left = y_s; + if(ex_beg >= 0) y_beg_left = y_beg_left + p_err_thre - ex_beg; + y_beg_right = y_beg_left; + } + + if(y_beg_left == -1 && y_beg_right != -1) y_beg_left = y_beg_right; + if(y_beg_right == -1 && y_beg_left != -1) y_beg_right = y_beg_left; + + if(y_beg_left != -1) {///note: this function will change tstr/qstr + if(rref) { + verify_sub_window(rref, dumy, g_read, w_s, x_len, y_beg_left, Window_Len, + z->y_id, z->y_pos_strand, err_thre, 0, &r_error_left, &r_y_end_left, &r_x_end_left, &aligned_xLen_left); + } else { + verify_ul_sub_window(uref, dumy, g_read, w_s, x_len, y_beg_left, Window_Len, + z->y_id, z->y_pos_strand, err_thre, 0, &r_error_left, &r_y_end_left, &r_x_end_left, &aligned_xLen_left); + } + } + + if(y_beg_right != -1) { + if(rref) { + verify_sub_window(rref, dumy, g_read, w_s, x_len, y_beg_right, Window_Len, z->y_id, z->y_pos_strand, + err_thre, 1, &r_error_right, &r_y_end_right, &r_x_end_right, &aligned_xLen_right); + } else { + verify_ul_sub_window(uref, dumy, g_read, w_s, x_len, y_beg_right, Window_Len, z->y_id, z->y_pos_strand, + err_thre, 1, &r_error_right, &r_y_end_right, &r_x_end_right, &aligned_xLen_right); + } + } + + ///aligned in both directions + if(aligned_xLen_left != 0 && aligned_xLen_right != 0) { + if(aligned_xLen_left + aligned_xLen_right <= x_len) { + tErr += r_error_left + r_error_right + (x_len - aligned_xLen_left - aligned_xLen_right); + } else { + float E_rate = (float)(x_len)/(float)(aligned_xLen_left + aligned_xLen_right); + tErr += (r_error_left + r_error_right)*E_rate; + } + }///not aligned in both directions + else if(aligned_xLen_left == 0 && aligned_xLen_right == 0) { + tErr += x_len; + }///only aligned in left + else if(aligned_xLen_left != 0) { + tErr += r_error_left + (x_len - aligned_xLen_left); + }///only aligned in right + else if(aligned_xLen_right != 0) { + tErr += r_error_right + (x_len - aligned_xLen_right); + } + // if(z->y_id == 1) { + // fprintf(stderr, "*[M::%s] qs->%ld, ts->%ld, tb[0]->%ld, tb[1]->%ld, di[0]->%u, di[1]->%u, al[0]->%d, al[1]->%d, err_thre->%ld\n", __func__, + // w_s, y_s, y_beg_left, y_beg_right, r_error_left, r_error_right, aligned_xLen_left, aligned_xLen_right, err_thre); + // } + // if(z->y_id == 1) { + // fprintf(stderr, "-[M::%s] ws->%ld, we->%ld, tot_l->%ld, tot_e->%ld\n", __func__, w_s, w_e, tLen, tErr); + // } + } + idx_e = w_id; + } + + if(idx_e > 0) { + for (m = 0, w_e = (int64_t)z->x_pos_s-1; m < idx_e; m++) { + w_s = w_e + 1; + wn_id = get_win_id_by_s(z, w_s, block_s, &w_e); + assert(wn_id == m); x_len = w_e + 1 - w_s; tLen += x_len; + ///check if there are some windows that cannot be algined by any overlaps/unitigs + ///if no, it is likely that the UL read itself has issues + if(uref && v_idx && z->is_match == 4) { + if(check_coverage_gap(v_idx->a.a, w_s, w_e, block_s)) { + tErr += THRESHOLD_MAX_SIZE; + // if(z->y_id == 1) { + // fprintf(stderr, "-[M::%s] ws->%ld, we->%ld, tot_l->%ld, tot_e->%ld\n", __func__, w_s, w_e, tLen, tErr); + // } + continue; + } + // else { + // if(z->y_id == 575) { + // fprintf(stderr, "---[M::%s::] z::y_id->%u, w_s->%ld, w_e->%ld\n", __func__, z->y_id, w_s, w_e); + // } + // } + } + if(!get_init_paras(rref, uref, z, w_s, w_e, e_rate, block_s, &y_s, &ex_beg, &ex_end, &err_thre)) { + tErr += x_len; + // if(z->y_id == 1) { + // fprintf(stderr, "-[M::%s] ws->%ld, we->%ld, tot_l->%ld, tot_e->%ld\n", __func__, w_s, w_e, tLen, tErr); + // } + continue; + } + p_err_thre = err_thre; + if(rref) { + err_thre = double_error_threshold(err_thre, x_len); + } else { + err_thre = double_ul_error_threshold(err_thre, x_len); + } + Window_Len = x_len + (err_thre << 1); + r_error_left = r_error_right = 0; + aligned_xLen_left = aligned_xLen_right = 0; + y_beg_left = y_beg_right = -1; + + ///impossible that the previous window is mapped + // if(m == w_id+1) { ///if the previous window is mapped + // y_beg_left = z->w_list.a[k].y_end + 1; + // } + + if(m+1 == idx_e && k+1 < aw) { ///if the next window is mapped + y_beg_right = z->w_list.a[k+1].y_start-x_len; + } + + if(y_beg_left == -1 && y_beg_right == -1) { + y_beg_left = y_s; + if(ex_beg >= 0) y_beg_left = y_beg_left + p_err_thre - ex_beg; + y_beg_right = y_beg_left; + } + + if(y_beg_left == -1 && y_beg_right != -1) y_beg_left = y_beg_right; + if(y_beg_right == -1 && y_beg_left != -1) y_beg_right = y_beg_left; + + if(y_beg_left != -1) { + if(rref) { + verify_sub_window(rref, dumy, g_read, w_s, x_len, y_beg_left, Window_Len, + z->y_id, z->y_pos_strand, err_thre, 0, &r_error_left, &r_y_end_left, &r_x_end_left, &aligned_xLen_left); + } else { + verify_ul_sub_window(uref, dumy, g_read, w_s, x_len, y_beg_left, Window_Len, + z->y_id, z->y_pos_strand, err_thre, 0, &r_error_left, &r_y_end_left, &r_x_end_left, &aligned_xLen_left); + } + } + + if(y_beg_right != -1) { + if(rref) { + verify_sub_window(rref, dumy, g_read, w_s, x_len, y_beg_right, Window_Len, z->y_id, z->y_pos_strand, + err_thre, 1, &r_error_right, &r_y_end_right, &r_x_end_right, &aligned_xLen_right); + } else { + verify_ul_sub_window(uref, dumy, g_read, w_s, x_len, y_beg_right, Window_Len, z->y_id, z->y_pos_strand, + err_thre, 1, &r_error_right, &r_y_end_right, &r_x_end_right, &aligned_xLen_right); + } + } + + ///aligned in both directions + if(aligned_xLen_left != 0 && aligned_xLen_right != 0) { + if(aligned_xLen_left + aligned_xLen_right <= x_len) { + tErr += r_error_left + r_error_right + (x_len - aligned_xLen_left - aligned_xLen_right); + } else { + float E_rate = (float)(x_len)/(float)(aligned_xLen_left + aligned_xLen_right); + tErr += (r_error_left + r_error_right)*E_rate; + } + }///not aligned in both directions + else if(aligned_xLen_left == 0 && aligned_xLen_right == 0) { + tErr += x_len; + }///only aligned in left + else if(aligned_xLen_left != 0) { + tErr += r_error_left + (x_len - aligned_xLen_left); + }///only aligned in right + else if(aligned_xLen_right != 0) { + tErr += r_error_right + (x_len - aligned_xLen_right); + } + // if(z->y_id == 1) { + // fprintf(stderr, "-[M::%s] ws->%ld, we->%ld, tot_l->%ld, tot_e->%ld\n", __func__, w_s, w_e, tLen, tErr); + // } + } + } + + assert(tLen == z->x_pos_e + 1 - z->x_pos_s); + return (double)(tErr)/(double)(tLen); +} + +void append_unmatched_wins(overlap_region *z, int64_t block_s) +{ + int64_t nw, aw = z->w_list.n, k, m, w_id, wn_id, w_s, w_e, idx_e; + nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); + assert(nw >= aw && aw > 0); + if(nw == aw) return;///done + kv_resize(window_list, z->w_list, (uint64_t)nw); z->w_list.n = nw; + for (k = aw-1, idx_e = nw; k >= 0; k--) { + w_id = get_win_id_by_e(z, z->w_list.a[k].x_end, block_s, &w_s); + assert(w_s == z->w_list.a[k].x_start && w_id < idx_e && k <= w_id); + if(k != w_id) z->w_list.a[w_id] = z->w_list.a[k]; + for (m = w_id+1, w_e = z->w_list.a[k].x_end; m < idx_e; m++) { + z->w_list.a[m].cidx = z->w_list.a[m].clen = 0; + z->w_list.a[m].y_start = z->w_list.a[m].y_end = -1; + z->w_list.a[m].error = z->w_list.a[m].error_threshold = -1; + z->w_list.a[m].extra_begin = z->w_list.a[m].extra_end = 0; + z->w_list.a[m].x_start = w_e + 1; + wn_id = get_win_id_by_s(z, z->w_list.a[m].x_start, block_s, &w_e); + z->w_list.a[m].x_end = w_e; + assert(wn_id == m); + } + idx_e = w_id; + } + + if(idx_e > 0) { + for (m = 0, w_e = (int64_t)z->x_pos_s-1; m < idx_e; m++) { + z->w_list.a[m].cidx = z->w_list.a[m].clen = 0; + z->w_list.a[m].y_start = z->w_list.a[m].y_end = -1; + z->w_list.a[m].error = z->w_list.a[m].error_threshold = -1; + z->w_list.a[m].extra_begin = z->w_list.a[m].extra_end = 0; + z->w_list.a[m].x_start = w_e + 1; + wn_id = get_win_id_by_s(z, z->w_list.a[m].x_start, block_s, &w_e); + z->w_list.a[m].x_end = w_e; + assert(wn_id == m); + } + } +} + +/** +inline double non_trim_ul_error_rate(overlap_region_alloc* overlap_list, long long ID, +const ul_idx_t *uref, Correct_dumy* dumy, UC_Read* g_read) +{ + long long tLen, tError,i, subWinLen, subWinNum; + + tLen = 0; + tError = 0; + + subWinNum = overlap_list->list[ID].w_list_length; + + + for (i = 0; i < subWinNum; i++) + { + subWinLen = overlap_list->list[ID].w_list[i].x_end - overlap_list->list[ID].w_list[i].x_start + 1; + tLen += subWinLen; + + if(overlap_list->list[ID].w_list[i].y_end != -1) + { + tError += overlap_list->list[ID].w_list[i].error; + } + else + { + int x_len = subWinLen; + int threshold = double_ul_error_threshold(overlap_list->list[ID].w_list[i].error_threshold, x_len); + int Window_Len = x_len + (threshold << 1); + unsigned int r_error_left = 0; + int r_x_end_left, r_y_end_left, aligned_xLen_left; + unsigned int r_error_right = 0; + int r_x_end_right, r_y_end_right, aligned_xLen_right; + long long y_beg_left, y_beg_right; + + aligned_xLen_left = aligned_xLen_right = 0; + y_beg_left = y_beg_right = -1; + + if(overlap_list->list[ID].w_list[i].y_start == -1) + { + tError += x_len; + continue; + } + + ///if the previous window is mapped + if(i > 0 && overlap_list->list[ID].w_list[i - 1].y_end != -1) + { + y_beg_left = overlap_list->list[ID].w_list[i - 1].y_end + 1; + } + + ///if the next window is mapped + if(i < (long long)(overlap_list->list[ID].w_list_length - 1) && overlap_list->list[ID].w_list[i + 1].y_end != -1) + { + y_beg_right = 1 + overlap_list->list[ID].w_list[i + 1].y_start - 1 - x_len; + } + + + if(y_beg_left == -1 && y_beg_right == -1) + { + y_beg_left = overlap_list->list[ID].w_list[i].y_start; + if(overlap_list->list[ID].w_list[i].extra_begin >= 0) + { + y_beg_left = y_beg_left + overlap_list->list[ID].w_list[i].error_threshold - + overlap_list->list[ID].w_list[i].extra_begin; + } + y_beg_right = y_beg_left; + } + + if(y_beg_left == -1 && y_beg_right != -1) + { + y_beg_left = y_beg_right; + } + + if(y_beg_right == -1 && y_beg_left != -1) + { + y_beg_right = y_beg_left; + } + + + if(y_beg_left != -1) + { + verify_ul_sub_window(uref, dumy, g_read, overlap_list->list[ID].w_list[i].x_start, + x_len, y_beg_left, Window_Len, overlap_list->list[ID].y_id, overlap_list->list[ID].y_pos_strand, + threshold, 0, &r_error_left, &r_y_end_left, &r_x_end_left, &aligned_xLen_left); + } + + if(y_beg_right != -1) + { + verify_ul_sub_window(uref, dumy, g_read, overlap_list->list[ID].w_list[i].x_start, + x_len, y_beg_right, Window_Len, overlap_list->list[ID].y_id, overlap_list->list[ID].y_pos_strand, + threshold, 1, &r_error_right, &r_y_end_right, &r_x_end_right, &aligned_xLen_right); + } + + ///aligned in both direction + if(aligned_xLen_left != 0 && aligned_xLen_right != 0) + { + if(aligned_xLen_left + aligned_xLen_right <= x_len) + { + tError = tError + r_error_left + r_error_right + + (x_len - aligned_xLen_left - aligned_xLen_right); + } + else + { + float E_rate = (float)(x_len)/(float)(aligned_xLen_left + aligned_xLen_right); + tError = tError + (r_error_left + r_error_right)*E_rate; + } + }///not aligned in both direction + else if(aligned_xLen_left == 0 && aligned_xLen_right == 0) + { + tError += x_len; + }///only aligned in left + else if(aligned_xLen_left != 0) + { + tError = tError + r_error_left + (x_len - aligned_xLen_left); + }///only aligned in right + else if(aligned_xLen_right != 0) + { + tError = tError + r_error_right + (x_len - aligned_xLen_right); + } + } + } + + double error_rate = (double)(tError)/(double)(tLen); + + return error_rate; +} + +int calculate_hpm_errors(char* x, int x_len, char* y, int y_len, CIGAR* cigar, int error) +{ + int x_i, y_i, cigar_i; + x_i = 0; + y_i = 0; + cigar_i = 0; + int operation; + int operationLen; + int i; + int cigar_error = 0; + int hpm_error = 0; + + + while (cigar_i < cigar->length) + { + operation = cigar->C_C[cigar_i]; + operationLen = cigar->C_L[cigar_i]; + + if (operation == 0) + { + x_i = x_i + operationLen; + y_i = y_i + operationLen; + } + else if (operation == 1) + { + cigar_error += operationLen; + for (i = 0; i < operationLen; i++) + { + if(if_is_homopolymer_repeat(x_i, x, x_len) || if_is_homopolymer_repeat(y_i, y, y_len)) + { + hpm_error++; + } + + x_i++; + y_i++; + } + } + else if (operation == 2) + { + + if(if_is_homopolymer_repeat(x_i, x, x_len) || if_is_homopolymer_repeat(y_i, y, y_len)) + { + hpm_error++; + } + cigar_error += operationLen; + y_i += operationLen; + } + else if (operation == 3) + { + + if(if_is_homopolymer_repeat(x_i, x, x_len) || if_is_homopolymer_repeat(y_i, y, y_len)) + { + hpm_error++; + } + + cigar_error += operationLen; + x_i += operationLen; + } + + cigar_i++; + } + return hpm_error; +} + +int verify_cigar(char* x, int x_len, char* y, int y_len, CIGAR* cigar, int error) +{ + int x_i, y_i, cigar_i; + x_i = 0; + y_i = 0; + cigar_i = 0; + int operation; + int operationLen; + int i; + int cigar_error = 0; + int flag_error = 0; + + ///0 is match, 1 is mismatch, 2 is up, 3 is left + ///2 means there are more y, 3 means there are more x + while (cigar_i < cigar->length) + { + operation = cigar->C_C[cigar_i]; + operationLen = cigar->C_L[cigar_i]; + + if (operation == 0) + { + for (i = 0; i < operationLen; i++) + { + + if (x[x_i]!=y[y_i]) + { + ///fprintf(stderr, "error match\n"); + flag_error = 1; + } + x_i++; + y_i++; + } + } + else if (operation == 1) + { + cigar_error += operationLen; + for (i = 0; i < operationLen; i++) + { + + if (x[x_i]==y[y_i]) + { + ///fprintf(stderr, "error mismatch, cigar_i: %d, x_i: %d, y_i: %d\n",cigar_i, x_i, y_i); + flag_error = 1; + } + x_i++; + y_i++; + } + } + else if (operation == 2) + { + cigar_error += operationLen; + y_i += operationLen; + } + else if (operation == 3) + { + cigar_error += operationLen; + x_i += operationLen; + } + + cigar_i++; + } + + + if (cigar_error != error) + { + + // fprintf(stderr, "error cigar_error: cigar_error: %d, error: %d\n", cigar_error, error); + // for (i = 0; i < cigar->length; i++) + // { + // fprintf(stderr, "%u: %u\n", cigar->C_L[i], cigar->C_C[i]); + // } + + + flag_error = 1; + + } + + + if (flag_error == 1) + { + + // print_string(x, x_len); + // print_string(y, y_len); + // fprintf(stderr, "x_len: %d, y_len: %d, cigar_len: %d, error: %d\n", x_len, y_len, cigar->length, error); + // for (i = 0; i < cigar->length; i++) + // { + // fprintf(stderr, "%u: %u\n", cigar->C_L[i], cigar->C_C[i]); + // } + + + } + + + return flag_error; + +} +**/ + +int32_t scan_cigar(window_list *idx, window_list_alloc *cc, int64_t* get_error, int64_t scanXLen, int64_t direction) +{ + uint8_t c = (uint8_t)-1; uint32_t cl = (uint32_t)-1; + (*get_error) = -1; + if(idx->clen == 1) { + get_cigar_cell(idx, cc, 0, &c, &cl); + if(c == 0) { + (*get_error) = 0; + return 1; + } + } + int32_t x_i = 0, y_i = 0, c_i, c_n = idx->clen, c_err = 0; + uint32_t i; + + ///0 is match, 1 is mismatch, 2 is up, 3 is left + ///2: there are more bases at y, 3: there are more bases at x + if(direction == 0) { + for (c_i = 0; c_i < c_n; c_i++) { + get_cigar_cell(idx, cc, c_i, &c, &cl); + if (c == 0) { //match + x_i += cl; y_i += cl; + if(x_i >= scanXLen) { + (*get_error) = c_err; + return 1; + } + } + else if (c == 1) { + for (i = 0; i < cl; i++) { + x_i++; y_i++; c_err++; + if(x_i >= scanXLen) { + (*get_error) = c_err; + return 1; + } + } + } + else if (c == 2) {///y has more bases than x + c_err += cl; y_i += cl; + } + else if (c == 3) {///x has more bases than y + for (i = 0; i < cl; i++) { + x_i++; c_err++; + if(x_i >= scanXLen) { + (*get_error) = c_err; + return 1; + } + } + } + } + } else { + for (c_i = c_n-1; c_i >= 0; c_i--) { + get_cigar_cell(idx, cc, c_i, &c, &cl); + if (c == 0) { //match + x_i += cl; y_i += cl; + if(x_i >= scanXLen) { + (*get_error) = c_err; + return 1; + } + } else if (c == 1) { //mismatch + for (i = 0; i < cl; i++) { + x_i++; y_i++; c_err++; + if(x_i >= scanXLen) { + (*get_error) = c_err; + return 1; + } + } + } else if (c == 2) {///y has more bases than x + c_err += cl; y_i += cl; + } else if (c == 3) {///x has more bases than y + for (i = 0; i < cl; i++) { + x_i++; c_err++; + if(x_i >= scanXLen) { + (*get_error) = c_err; + return 1; + } + } + } + } + } + + (*get_error) = c_err; + return 0; +} + +///[scanXbeg, scanXend] +int scan_cigar_interval(window_list *idx, window_list_alloc *cc, int64_t* get_error, int64_t scanXbeg, int64_t scanXend) +{ + uint8_t c; uint32_t cl; + (*get_error) = -1; + if(idx->clen == 1) { + get_cigar_cell(idx, cc, 0, &c, &cl); + if(c == 0) { + (*get_error) = 0; + return 1; + } + } + + + + int32_t x_i = 0, y_i = 0, c_i, c_n = idx->clen, c_err = 0; + uint32_t i; + + + ///0 is match, 1 is mismatch, 2 is up, 3 is left + ///2: there are more bases at y, 3: there are more bases at x + for (c_i = 0; c_i < c_n; c_i++) { + get_cigar_cell(idx, cc, c_i, &c, &cl); + if (c == 0) {//match + for (i = 0; i < cl; i++) { + if(x_i == scanXbeg) c_err = 0; + x_i++; y_i++; + + if(x_i == scanXend + 1) { + (*get_error) = c_err; + return 1; + } + } + } else if (c == 1) {//mismatch + for (i = 0; i < cl; i++) { + if(x_i == scanXbeg) c_err = 0; + x_i++; y_i++; c_err++; + + if(x_i == scanXend + 1) { + (*get_error) = c_err; + return 1; + } + } + } else if (c == 2) {///y has more bases than x + c_err += cl; y_i += cl; + } + else if (c == 3) { + for (i = 0; i < cl; i++) { + if(x_i == scanXbeg) c_err = 0; + x_i++; c_err++; + + if(x_i == scanXend + 1) { + (*get_error) = c_err; + return 1; + } + } + } + } + + (*get_error) = c_err; + return 0; +} + +inline int move_gap_greedy(char* path, int path_i, int path_length, char* x, int x_i, char* y, int y_i, unsigned int* new_error) +{ + if(path[path_i] < 2) + { + return 0; + } + + /** + * + GGCG-TGTGCCTGT + * + GGCAATGTGCCTGT + * + 00013000000000 + **/ + + int flag = 0; + + char oper = path[path_i]; + + + if(oper == 3)///there are more x + { + path_i++; + y_i--; + for (; path_i < path_length && x_i >= 0 && y_i >= 0; path_i++, x_i--, y_i--) + { + if(path[path_i] == 2 || path[path_i] == 3 || (path[path_i] == 0 && x[x_i] != y[y_i])) + { + break; + } + else ///path[path_i] = 1 || path[path_i] = 0, exchange path[path_i] with path[path_i-1] + { + if(path[path_i] == 1 && x[x_i] == y[y_i]) + { + path[path_i - 1] = 0; + (*new_error)--; + } + else + { + path[path_i - 1] = path[path_i]; + } + + path[path_i] = oper; + + + flag = 1; + } + + } + } + else if(oper == 2)///there are more y + { + path_i++; + x_i--; + for (; path_i < path_length && x_i >= 0 && y_i >= 0; path_i++, x_i--, y_i--) + { + if(path[path_i] == 2 || path[path_i] == 3 || (path[path_i] == 0 && x[x_i] != y[y_i])) + { + break; + } + else + { + + if(path[path_i] == 1 && x[x_i] == y[y_i]) + { + path[path_i - 1] = 0; + (*new_error)--; + } + else + { + path[path_i - 1] = path[path_i]; + } + + + path[path_i] = oper; + flag = 1; + } + + } + } + + return flag; +} + +inline void generate_cigar(char* path, int path_length, window_list *idx, window_list_alloc *res, int* start, int* end, unsigned int* old_error, + char* x, int x_len, char* y) +{ + // uint8_t debug_c; uint32_t debug_c_len; + idx->cidx = res->c.n; + if ((*old_error) == 0) { + push_cigar_cell(res, 0, idx->x_end + 1 - idx->x_start); + idx->clen = res->c.n - idx->cidx; + // get_cigar_cell(idx, res, idx->clen-1, &debug_c, &debug_c_len); + // assert(debug_c==0 && debug_c_len==(idx->x_end + 1 - idx->x_start)); + return; + } + + ///0 is match, 1 is mismatch, 2 is up (more y), 3 is left (more x) + int32_t i = 0, pre_cl = 0, trem_p = -1; char pre_c = 5; + for (i = 0; i < path_length; i++) { + if(path[i] == 1) { + path[i] = 3;(*end)--; trem_p = i; + } else { + break; + } + } + + for (i = path_length - 1; i >= 0; i--) { + if(path[i] == 1) { + path[i] = 3; (*start)++; + } + else { + break; + } + } + + + // for (i = path_length - 1; i >= 0; i--) + // { + + // if (pre_ciga != path[i]) + // { + // if (pre_ciga_length != 0) + // { + // result->cigar.C_L[result->cigar.length] = pre_ciga_length; + // result->cigar.C_C[result->cigar.length] = pre_ciga; + // result->cigar.length++; + // } + + // pre_ciga = path[i]; + // pre_ciga_length = 1; + // } + // else + // { + // pre_ciga_length++; + // } + // } + + // if (pre_ciga_length != 0) + // { + // result->cigar.C_L[result->cigar.length] = pre_ciga_length; + // result->cigar.C_C[result->cigar.length] = pre_ciga; + // result->cigar.length++; + // } + + ///verify_cigar(x, x_len, y + (*start), (*end) - (*start) + 1, &(result->cigar), error); + + + y = y + (*start); + int32_t x_i = 0, y_i = 0; + ///terminate_site = -1 in default + for (i = path_length - 1; i > trem_p; i--) { + if(path[i] == 0) { + x_i++; y_i++; + } + else if(path[i] == 1) { + x_i++; y_i++; + } + else if(path[i] == 2) {///there are more y + move_gap_greedy(path, i, path_length, x, x_i, y, y_i, old_error); + y_i++; + } + else if(path[i] == 3) {///there are more x + move_gap_greedy(path, i, path_length, x, x_i, y, y_i, old_error); + x_i++; + } + } + + + + pre_c = 5; pre_cl = 0; + for (i = path_length - 1; i >= 0; i--) { + if (pre_c != path[i]) { + if (pre_cl != 0) { + push_cigar_cell(res, pre_c, pre_cl); + // get_cigar_cell(idx, res, res->c.n - idx->cidx - 1, &debug_c, &debug_c_len); + // assert(debug_c==pre_c && debug_c_len==pre_cl); + } + pre_c = path[i]; pre_cl = 1; + } + else { + pre_cl++; + } + } + + if (pre_cl != 0) { + push_cigar_cell(res, pre_c, pre_cl); + // get_cigar_cell(idx, res, res->c.n - idx->cidx -1, &debug_c, &debug_c_len); + // assert(debug_c==pre_c && debug_c_len==pre_cl); + } + + idx->clen = res->c.n - idx->cidx; + // if(verify_cigar(x, x_len, y, (*end) - (*start) + 1, &(result->cigar), *old_error)) + // { + // fprintf(stderr, "error\n"); + // } +} + +int verify_cigar_2(char* x, int x_len, char* y, int y_len, Cigar_record* cigar, int error) +{ + int x_i, y_i, cigar_i; + x_i = 0; + y_i = 0; + cigar_i = 0; + int operation; + int operationLen; + int i; + int cigar_error = 0; + int flag_error = 0; + int diff_i = 0; + + ///0 is match, 1 is mismatch, 2 is up, 3 is left + ///2 means there are more y, 3 means there are more x + while (cigar_i < (long long)cigar->length) + { + operation = Get_Cigar_Type(cigar->record[cigar_i]); + operationLen = Get_Cigar_Length(cigar->record[cigar_i]); + + if (operation == 0) + { + for (i = 0; i < operationLen; i++) + { + + if (x[x_i]!=y[y_i]) + { + ///fprintf(stderr, "error match\n"); + flag_error = 1; + } + x_i++; + y_i++; + } + } + else if (operation == 1) + { + cigar_error += operationLen; + for (i = 0; i < operationLen; i++) + { + + if (x[x_i]==y[y_i]) + { + ///fprintf(stderr, "error mismatch, cigar_i: %d, x_i: %d, y_i: %d\n",cigar_i, x_i, y_i); + flag_error = 1; + } + + if(Get_MisMatch_Base(cigar->lost_base[diff_i]) != y[y_i]) + { + // fprintf(stderr, "mismatch x: %c, y: %c, mis[%d]: %c\n", x[x_i],y[y_i],diff_i, + // Get_MisMatch_Base(cigar->lost_base[diff_i])); + } + + if(Get_Match_Base(cigar->lost_base[diff_i]) != x[x_i]) + { + // fprintf(stderr, "match x: %c, y: %c, deletion[%d]: %c\n", + // x[x_i],y[y_i],diff_i, + // Get_Match_Base(cigar->lost_base[diff_i])); + } + + + + + x_i++; + y_i++; + diff_i++; + } + } + else if (operation == 2) + { + cigar_error += operationLen; + for (i = 0; i < operationLen; i++) + { + if(cigar->lost_base[diff_i] != y[y_i]) + { + ///fprintf(stderr, "insertion x: %c, y: %c, insertion[%d]: %c\n", x[x_i],y[y_i],diff_i, + ///cigar->lost_base[diff_i]); + } + y_i++; + diff_i++; + } + } + else if (operation == 3) + { + cigar_error += operationLen; + + for (i = 0; i < operationLen; i++) + { + if(cigar->lost_base[diff_i] != x[x_i]) + { + ///fprintf(stderr, "deletion x: %c, y: %c, deletion[%d]: %c\n", x[x_i],y[y_i],diff_i, + ///cigar->lost_base[diff_i]); + } + x_i++; + diff_i++; + } + } + + cigar_i++; + } + + + ///return; + /** + if (cigar_error != error) + { + fprintf(stderr, "error cigar_error: cigar_error: %d, error: %d\n", cigar_error, error); + for (i = 0; i < cigar->length; i++) + { + operation = Get_Cigar_Type(cigar->record[i]); + operationLen = Get_Cigar_Length(cigar->record[i]); + fprintf(stderr, "%u: %u\n", operationLen, operation); + } + + } + **/ + + + if (flag_error == 1) + { + print_string(x, x_len); + print_string(y, y_len); + ///fprintf(stderr, "x_len: %d, y_len: %d, cigar_len: %d, error: %d\n", x_len, y_len, cigar->length, error); + for (i = 0; i < (long long)cigar->length; i++) + { + operation = Get_Cigar_Type(cigar->record[i]); + operationLen = Get_Cigar_Length(cigar->record[i]); + ///fprintf(stderr, "%u: %u\n", operationLen, operation); + } + } + + + return flag_error; + +} + +inline int fix_ul_boundary(char* x_string, long long x_len, int threshold, +long long total_y_start, long long local_y_start, long long local_y_end, +long long old_extra_begin, long long old_extra_end, +long long y_ID, long long Window_Len, const ul_idx_t *uref, +Correct_dumy* dumy, int y_strand, unsigned int old_error, +long long* r_total_y_start, int* r_start_site, int* r_end_site, +int* r_extra_begin, int* r_extra_end, unsigned int* r_error) +{ + + + int new_extra_begin, new_extra_end; + long long new_y_start, new_y_length; + int new_end_site, new_start_site; + unsigned int new_error; + char* y_string; + + + int path_length; + + ///if the start pos at the left boundary + if(local_y_start == 0) + { + total_y_start = total_y_start + local_y_start; + ///if local_y_start == 0 and old_extra_begin != 0 + ///this means total_y_start == 0, so shift to the left cannot get a new start pos + if(old_extra_begin != 0) + { + return 0; + } + + ///if the begining of alignment is 0, we should try to shift the window to find a better result + ///shift to the left by threshold-1 bases + if(!determine_overlap_region(threshold, total_y_start, y_ID, Window_Len, uref->ug->u.a[y_ID].len, + &new_extra_begin, &new_extra_end, &new_y_start, &new_y_length)) + { + return 0; + } + + ///if new_y_start is equal to total_y_start, recalculate makes no sense + if(new_y_start == total_y_start) + { + return 0; + } + + fill_subregion_ul(dumy->overlap_region_fix, new_y_start, new_y_length, y_strand, uref, y_ID, + new_extra_begin, new_extra_end); + + y_string = dumy->overlap_region_fix; + + new_end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &new_error, &new_start_site, + &path_length, dumy->matrix_bit, dumy->path_fix, -1, -1); + + if (new_error != (unsigned int)-1 && new_error < old_error) + { + (*r_total_y_start) = new_y_start; + (*r_start_site) = new_start_site; + (*r_end_site) = new_end_site; + (*r_extra_begin) = new_extra_begin; + (*r_extra_end) = new_extra_end; + (*r_error) = new_error; + + dumy->path_length = path_length; + memcpy(dumy->path, dumy->path_fix, path_length); + memcpy(dumy->overlap_region, dumy->overlap_region_fix, Window_Len); + return 1; + } + } + else if(local_y_end == Window_Len - 1) + { + ///if local_y_end == Window_Len - 1 and old_extra_end > 0 + ///this means local_y_end is the end of the y + ///so shit to the right makes no sense + if(old_extra_end != 0) + { + return 0; + } + long long total_y_end = total_y_start + local_y_end; + + total_y_start = total_y_end - x_len + 1; + + if(!determine_overlap_region(threshold, total_y_start, y_ID, Window_Len, uref->ug->u.a[y_ID].len, + &new_extra_begin, &new_extra_end, &new_y_start, &new_y_length)) + { + return 0; + } + + if(new_y_start == total_y_end - local_y_end) + { + return 0; + } + + fill_subregion_ul(dumy->overlap_region_fix, new_y_start, new_y_length, y_strand, uref, y_ID, + new_extra_begin, new_extra_end); + + y_string = dumy->overlap_region_fix; + + new_end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &new_error, &new_start_site, + &path_length, dumy->matrix_bit, dumy->path_fix, -1, -1); + + if (new_error != (unsigned int)-1 && new_error < old_error) + { + (*r_total_y_start) = new_y_start; + (*r_start_site) = new_start_site; + (*r_end_site) = new_end_site; + (*r_extra_begin) = new_extra_begin; + (*r_extra_end) = new_extra_end; + (*r_error) = new_error; + + dumy->path_length = path_length; + memcpy(dumy->path, dumy->path_fix, path_length); + memcpy(dumy->overlap_region, dumy->overlap_region_fix, Window_Len); + return 1; + } + + + } + return 0; +} + + +inline int fix_boundary(char* x_string, long long x_len, int threshold, +long long total_y_start, long long local_y_start, long long local_y_end, +long long old_extra_begin, long long old_extra_end, +long long y_ID, long long Window_Len, All_reads* R_INF, +Correct_dumy* dumy, int y_strand, unsigned int old_error, +long long* r_total_y_start, int* r_start_site, int* r_end_site, +int* r_extra_begin, int* r_extra_end, unsigned int* r_error) +{ + + + int new_extra_begin, new_extra_end; + long long new_y_start, new_y_length; + int new_end_site, new_start_site; + unsigned int new_error; + char* y_string; + + + int path_length; + + ///if the start pos at the left boundary + if(local_y_start == 0) + { + total_y_start = total_y_start + local_y_start; + ///if local_y_start == 0 and old_extra_begin != 0 + ///this means total_y_start == 0, so shift to the left cannot get a new start pos + if(old_extra_begin != 0) + { + return 0; + } + + ///if the begining of alignment is 0, we should try to shift the window to find a better result + ///shift to the left by threshold-1 bases + if(!determine_overlap_region(threshold, total_y_start, y_ID, Window_Len, Get_READ_LENGTH((*R_INF), y_ID), + &new_extra_begin, &new_extra_end, &new_y_start, &new_y_length)) + { + return 0; + } + + ///if new_y_start is equal to total_y_start, recalculate makes no sense + if(new_y_start == total_y_start) + { + return 0; + } + + fill_subregion(dumy->overlap_region_fix, new_y_start, new_y_length, y_strand, R_INF, y_ID, + new_extra_begin, new_extra_end); + + y_string = dumy->overlap_region_fix; + + new_end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &new_error, &new_start_site, + &path_length, dumy->matrix_bit, dumy->path_fix, -1, -1); + + if (new_error != (unsigned int)-1 && new_error < old_error) + { + (*r_total_y_start) = new_y_start; + (*r_start_site) = new_start_site; + (*r_end_site) = new_end_site; + (*r_extra_begin) = new_extra_begin; + (*r_extra_end) = new_extra_end; + (*r_error) = new_error; + + dumy->path_length = path_length; + memcpy(dumy->path, dumy->path_fix, path_length); + memcpy(dumy->overlap_region, dumy->overlap_region_fix, Window_Len); + return 1; + } + } + else if(local_y_end == Window_Len - 1) + { + ///if local_y_end == Window_Len - 1 and old_extra_end > 0 + ///this means local_y_end is the end of the y + ///so shit to the right makes no sense + if(old_extra_end != 0) + { + return 0; + } + long long total_y_end = total_y_start + local_y_end; + + total_y_start = total_y_end - x_len + 1; + + if(!determine_overlap_region(threshold, total_y_start, y_ID, Window_Len, Get_READ_LENGTH((*R_INF), y_ID), + &new_extra_begin, &new_extra_end, &new_y_start, &new_y_length)) + { + return 0; + } + + if(new_y_start == total_y_end - local_y_end) + { + return 0; + } + + fill_subregion(dumy->overlap_region_fix, new_y_start, new_y_length, y_strand, R_INF, y_ID, + new_extra_begin, new_extra_end); + + y_string = dumy->overlap_region_fix; + + new_end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &new_error, &new_start_site, + &path_length, dumy->matrix_bit, dumy->path_fix, -1, -1); + + if (new_error != (unsigned int)-1 && new_error < old_error) + { + (*r_total_y_start) = new_y_start; + (*r_start_site) = new_start_site; + (*r_end_site) = new_end_site; + (*r_extra_begin) = new_extra_begin; + (*r_extra_end) = new_extra_end; + (*r_error) = new_error; + + dumy->path_length = path_length; + memcpy(dumy->path, dumy->path_fix, path_length); + memcpy(dumy->overlap_region, dumy->overlap_region_fix, Window_Len); + return 1; + } + + + } + return 0; +} + +inline char *return_str_seq(char *buf, int64_t s, int64_t pri_l, uint8_t rev, hpc_t *hpc_g, const ul_idx_t *uref, int64_t id, int64_t aux_beg, int64_t aux_end) +{ + if(!hpc_g) { + memset(buf, 'N', aux_beg); + retrieve_u_seq(NULL, buf+aux_beg, &(uref->ug->u.a[id]), rev, s, pri_l, NULL); + memset(buf+aux_beg+pri_l, 'N', aux_end); + return buf; + } else { + char *z = hpc_str(*hpc_g, id, rev); + if((aux_beg == 0) && (aux_end == 0)) { + return z+s; + } else { + memset(buf, 'N', aux_beg); + memcpy(buf+aux_beg, z+s, pri_l); + memset(buf+aux_beg+pri_l, 'N', aux_end); + return buf; + } + } +} + +inline char *return_str_seq_exz(char *buf, int64_t s, int64_t pri_l, uint8_t rev, hpc_t *hpc_g, const ul_idx_t *uref, int64_t id) +{ + if(!hpc_g) { + retrieve_u_seq(NULL, buf, &(uref->ug->u.a[id]), rev, s, pri_l, NULL); + return buf; + } else { + return hpc_str(*hpc_g, id, rev) + s; + } +} + +///cannot use tstr in-place +inline int recal_boundary(char* qstr, char* tstr1, int64_t ql, int64_t thres, +int64_t global_ts0, int64_t local_ts0, int64_t local_te0, +int64_t aux_beg0, int64_t aux_end0, unsigned int err0, +int64_t tid, int64_t aln_l, uint32_t rev, +Correct_dumy* dumy, All_reads* rref, hpc_t *hpc_g, const ul_idx_t *uref, +int64_t* global_ts1, int* local_ts1, int* local_te1, +int64_t* aux_beg1, int64_t* aux_end1, unsigned int* err1) +{ + int64_t ts, t_tot_l, aux_beg, aux_end, t_pri_l, t_end; + char *q_string = qstr, *t_string; unsigned int error = (unsigned int)-1; + int r_ts = 0, path_length = 0; + if(hpc_g) t_tot_l = hpc_len(*hpc_g, tid); + else if(uref) t_tot_l = uref->ug->u.a[tid].len; + else t_tot_l = Get_READ_LENGTH((*rref), tid); + + if(local_ts0 == 0) {//left boundary + if(aux_beg0 > 0) return 0;///shift to the left cannot get a new start pos + ts = global_ts0; + } else if((local_te0 + 1) == aln_l) {//right boundary + if(aux_end0 > 0) return 0;///shift to the right cannot get a new start pos + ts = global_ts0 + local_te0 - ql + 1; + } else { + return 0; + } + if(!init_waln(thres, ts, t_tot_l, aln_l, &aux_beg, &aux_end, &ts, &t_pri_l)) return 0; + if(ts == global_ts0) return 0;//unchanged, make no sense + + if(rref) { + fill_subregion(tstr1, ts, t_pri_l, rev, rref, tid, aux_beg, aux_end); t_string = tstr1; + } else { + t_string = return_str_seq(tstr1, ts, t_pri_l, rev, hpc_g, uref, tid, aux_beg, aux_end); + } + + t_end = Reserve_Banded_BPM_PATH(t_string, aln_l, q_string, ql, thres, &error, &r_ts, + &path_length, dumy->matrix_bit, dumy->path_fix, -1, -1); + + if (error != (unsigned int)-1 && error < err0) { + (*global_ts1) = ts; + (*local_ts1) = r_ts; + (*local_te1) = t_end; + (*aux_beg1) = aux_beg; + (*aux_end1) = aux_end; + (*err1) = error; + + dumy->path_length = path_length; + memcpy(dumy->path, dumy->path_fix, path_length); + // memcpy(tstr0, t_string, aln_l); + return 1; + } + return 0; +} + +///cannot use tstr in-place +inline int recal_boundary_exz(char* qstr, char* tstr, int64_t ql0, int64_t tl0, int64_t thres, +int64_t toff, int64_t ts0, int64_t te0, int64_t err0, +int64_t tid, uint32_t rev, bit_extz_t *exz, +All_reads* rref, hpc_t *hpc_g, const ul_idx_t *uref, +int64_t *ts_r, int64_t *aux_beg_r, int64_t *aux_end_r) +{ + int64_t ts, tl, t_tot_l, aux_beg, aux_end, t_pri_l, aln_l = ql0 + (thres << 1); + char *q_string = qstr, *t_string; + if(hpc_g) t_tot_l = hpc_len(*hpc_g, tid); + else if(uref) t_tot_l = uref->ug->u.a[tid].len; + else t_tot_l = Get_READ_LENGTH((*rref), tid); + + if(ts0 == 0) {//left boundary + ts = toff; + } else if((te0 + 1) == tl0) {//right boundary + ts = toff + te0 - ql0 + 1; + } else { + return 0; + } + if(!init_waln(thres, ts, t_tot_l, aln_l, &aux_beg, &aux_end, &ts, &t_pri_l)) return 0; + if(ts == toff && tl0 == t_pri_l) return 0;//unchanged, make no sense + + tl = t_pri_l; + if(rref) { + recover_UC_Read_sub_region(tstr, ts, tl, rev, rref, tid); t_string = tstr; + } else { + t_string = return_str_seq_exz(tstr, ts, tl, rev, hpc_g, uref, tid); + } + + clear_align(*exz); + ed_band_cal_semi_64_w_absent_diag_trace(t_string, tl, q_string, ql0, thres, aux_beg, exz); + + if(is_align(*exz) && exz->err < err0) { + (*aux_beg_r) = aux_beg; + (*aux_end_r) = aux_end; + (*ts_r) = ts; + return 1; + } + return 0; +} + +///cannot use tstr in-place +inline int recal_boundary_non_retrieve_exz(char* qstr, char* tstr, int64_t t_tot_l, +int64_t ql0, int64_t tl0, int64_t thres, +int64_t toff, int64_t ts0, int64_t te0, int64_t err0, +int64_t tid, uint32_t rev, bit_extz_t *exz, +int64_t *ts_r, int64_t *aux_beg_r, int64_t *aux_end_r) +{ + int64_t ts, tl, aux_beg, aux_end, t_pri_l, aln_l = ql0 + (thres << 1); + char *q_string = qstr, *t_string; + + if(ts0 == 0) {//left boundary + ts = toff; + } else if((te0 + 1) == tl0) {//right boundary + ts = toff + te0 - ql0 + 1; + } else { + return 0; + } + if(!init_waln(thres, ts, t_tot_l, aln_l, &aux_beg, &aux_end, &ts, &t_pri_l)) return 0; + if(ts == toff && tl0 == t_pri_l) return 0;//unchanged, make no sense + + tl = t_pri_l; t_string = tstr + ts; + + clear_align(*exz); + ed_band_cal_semi_64_w_absent_diag_trace(t_string, tl, q_string, ql0, thres, aux_beg, exz); + + if(is_align(*exz) && exz->err < err0) { + (*aux_beg_r) = aux_beg; + (*aux_end_r) = aux_end; + (*ts_r) = ts; + return 1; + } + return 0; +} + +inline char *update_des_str(char *des, int64_t s, int64_t pri_l, uint8_t rev, All_reads *rref, hpc_t *hpc_g, + const ul_idx_t *uref, int64_t id, int64_t aux_beg, int64_t aux_end, char *src) +{ + if(src) { + // memcpy(des, src, (pri_l+aux_beg+aux_end)); + // return des; + return src; + } else { + if(rref) { + fill_subregion(des, s, pri_l, rev, rref, id, aux_beg, aux_end); + return des; + } else { + return return_str_seq(des, s, pri_l, rev, hpc_g, uref, id, aux_beg, aux_end); + } + } +} + +/** +void debug_scan_cigar(overlap_region* sub_list) +{ + long long i; + int f_err, b_err, fLen, xLen; + for (i = 0; i < (long long)sub_list->w_list_length; i++) + { + if(sub_list->w_list[i].y_end == -1 || sub_list->w_list[i].cigar.length == -1) + { + continue; + } + xLen = sub_list->w_list[i].x_end - sub_list->w_list[i].x_start + 1; + + scan_cigar(&(sub_list->w_list[i].cigar), &b_err, + xLen, 1); + scan_cigar(&(sub_list->w_list[i].cigar), &f_err, + xLen, 0); + + if(b_err != sub_list->w_list[i].error || f_err != sub_list->w_list[i].error) + { + fprintf(stderr, "error\n"); + } + + scan_cigar(&(sub_list->w_list[i].cigar), &b_err, + WINDOW, 1); + scan_cigar(&(sub_list->w_list[i].cigar), &f_err, + WINDOW, 0); + + if(b_err != sub_list->w_list[i].error || f_err != sub_list->w_list[i].error) + { + fprintf(stderr, "error\n"); + } + + scan_cigar_interval(&(sub_list->w_list[i].cigar), &b_err, 0, xLen-1); + if(b_err != sub_list->w_list[i].error) + { + fprintf(stderr, "error\n"); + } + + fLen = xLen / 3; + scan_cigar(&(sub_list->w_list[i].cigar), &f_err, fLen, 0); + scan_cigar_interval(&(sub_list->w_list[i].cigar), &b_err, 0, fLen-1); + if(f_err != b_err) + { + fprintf(stderr, "error\n"); + } + + fLen = xLen / 3; + scan_cigar(&(sub_list->w_list[i].cigar), &f_err, fLen, 1); + scan_cigar_interval(&(sub_list->w_list[i].cigar), &b_err, xLen-fLen, xLen-1); + if(f_err != b_err) + { + fprintf(stderr, "\nerror\n"); + fprintf(stderr, "b_err: %d, f_err: %d\n",b_err, f_err); + long long j; + for (j = 0; j < sub_list->w_list[i].cigar.length; j++) + { + fprintf(stderr, "len: %d, opera: %d\n", + sub_list->w_list[i].cigar.C_L[j], sub_list->w_list[i].cigar.C_C[j]); + } + } + + // bLen = xLen / 3; + // fLen = xLen - bLen; + + // scan_cigar(&(sub_list->w_list[i].cigar), &b_err, + // bLen, 1); + // scan_cigar(&(sub_list->w_list[i].cigar), &f_err, + // fLen, 0); + + // if(b_err + f_err != sub_list->w_list[i].error) + // { + // fprintf(stderr, "\nsub_list->w_list[i].error: %d, bLen: %d, b_err: %d, fLen: %d, f_err: %d\n", + // sub_list->w_list[i].error, bLen, b_err, fLen, f_err); + // long long j; + // for (j = 0; j < sub_list->w_list[i].cigar.length; j++) + // { + // fprintf(stderr, "len: %d, opera: %d\n", + // sub_list->w_list[i].cigar.C_L[j], sub_list->w_list[i].cigar.C_C[j]); + // } + + // } + } +} +**/ + +void calculate_boundary_cigars(overlap_region* z, All_reads* R_INF, Correct_dumy* dumy, UC_Read* g_read, double e_rate) +{ + assert(z->w_list.n > 0); + int64_t nw = z->w_list.n; + resize_window_list_alloc(&(z->boundary_cigars), nw - 1); + int64_t y_id = z->y_id, y_strand = z->y_pos_strand; + int64_t y_readLen = Get_READ_LENGTH((*R_INF), y_id); + int64_t i, y_distance, f_err = -1, b_err = -1, m_error; + int64_t scanLen = 10, boundaryLen = 200; + int64_t single_sideLen = boundaryLen/2; + int64_t force_useless_side = single_sideLen/2; + int64_t L_useless_side, R_useless_side, alpha = 1; + long long y_start, x_start, x_end, yLen, xLen, leftLen, rightLen, threshold, o_len; + char *x_string = NULL, *y_string = NULL; + int end_site, real_y_start, extra_begin, extra_end; + unsigned int error; + z->boundary_cigars.n = nw - 1; + ///the (i)-th boundary between the (i)-th window and the (i+1)-th window + ///that means it includes (the tail of (i)-th window) and (the header of (i+1)-th window) + ///note the (i)-th boundary is calculated at the (i)-th window + for (i = 0; i + 1 < nw; i++) { + ///if both of the two windows are not aligned + ///it is not necessary to calculate the boundary + if(z->w_list.a[i].y_end == -1 || z->w_list.a[i+1].y_end == -1) { + z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; + continue; + } + ///y_distance can be less than 0, or larger than 0 + y_distance = (int64_t)z->w_list.a[i+1].y_start - (int64_t)z->w_list.a[i].y_end - 1; + + ///if two windows are aligned + if(z->w_list.a[i].y_end != -1 && z->w_list.a[i+1].y_end != -1 && y_distance == 0) { + ///scan backward + scan_cigar(&(z->w_list.a[i]), &(z->w_list), &b_err, scanLen, 1); + ///scan forward + scan_cigar(&(z->w_list.a[i+1]), &(z->w_list), &f_err, scanLen, 0); + if(b_err == 0 && f_err == 0) { + z->boundary_cigars.a[i].error = -2; z->boundary_cigars.a[i].y_end = -1; + continue; + } + } + + + if(z->w_list.a[i].y_end != -1) { + y_start = z->w_list.a[i].y_end; x_start = z->w_list.a[i].x_end; + }///if the (i)-th window is not matched, have a look at the (i+1)-th window + else if(z->w_list.a[i+1].y_end != -1) { + y_start = z->w_list.a[i+1].y_start; x_start = z->w_list.a[i+1].x_start; + }///if both of these two windows are not matched, directly skip + else { + z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; + continue; + } + + ///it seems we don't need to record x_start and y_start + z->boundary_cigars.a[i].extra_begin = x_start; + z->boundary_cigars.a[i].extra_end = y_start; + + ///leftLen and rightLen are used for x + ///x should be at [sub_list->w_list[i].x_start, sub_list->w_list[i+1].x_end] + ///y shouldn't have limitation + ///note that the x_start and x_end should not be -1 in any case + ///up to now, x_start and y_start are not -1 + ///leftLen does not include x_start itself, rightLen does + ///gnerally speaking, rightLen should be always larger than leftLen + leftLen = MIN(MIN((x_start - (int64_t)z->w_list.a[i].x_start), y_start), single_sideLen); + rightLen = MIN(MIN(((int64_t)z->w_list.a[i+1].x_end + 1 - x_start), y_readLen - y_start), single_sideLen); + + ///xLen should be the sum length of two windows + xLen = leftLen + rightLen; + x_start = x_start - leftLen; + x_end = x_start + xLen - 1; + y_start = y_start - leftLen; + + ///if we don't have enough leftLen and rightLen + // if(leftLen <= useless_side || rightLen <= useless_side) + // { + // sub_list->boundary_cigars.buffer[i].error = -1; + // sub_list->boundary_cigars.buffer[i].y_end = -1; + // continue; + // } + + + threshold = xLen * e_rate/**asm_opt.max_ov_diff_ec**/; + threshold = Adjust_Threshold(threshold, xLen); + threshold = double_error_threshold(threshold, xLen); + + yLen = xLen + (threshold << 1); + if(!determine_overlap_region(threshold, y_start, y_id, yLen, Get_READ_LENGTH((*R_INF), y_id), + &extra_begin, &extra_end, &y_start, &o_len)) { + z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; + continue; + } + + if(o_len < xLen) { + z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; + continue; + } + + fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, R_INF, y_id, extra_begin, extra_end); + + x_string = g_read->seq + x_start; + y_string = dumy->overlap_region; + + end_site = Reserve_Banded_BPM_PATH(y_string, yLen, x_string, xLen, threshold, &error, + &real_y_start, &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); + + ///means this window is matched + if (error!=(unsigned int)-1) { + z->boundary_cigars.a[i].x_start = x_start; + z->boundary_cigars.a[i].x_end = x_end; + + generate_cigar(dumy->path, dumy->path_length, &(z->boundary_cigars.a[i]), &(z->boundary_cigars), + &real_y_start, &end_site, &error, x_string, xLen, y_string); + ///should not adjust cigar here, adjust cigar may cause problem + ///that is not what we want + + ///y_distance can be less than 0, or larger than 0 + ///please if one of the two windows is not matched, + ///y_distance may have potential problems + if(y_distance < 0) y_distance = y_distance * (-1); + ///leftLen, rightLen + // if(leftLen <= useless_side || rightLen <= useless_side) + // { + // sub_list->boundary_cigars.buffer[i].error = -1; + // sub_list->boundary_cigars.buffer[i].y_end = -1; + // continue; + // } + L_useless_side = R_useless_side = force_useless_side; + + ///first window + if((i == 0) && (x_start == (int64_t)z->w_list.a[0].x_start)) { + L_useless_side = 0; + } + ///last window + if((i == (int64_t)(z->w_list.n) - 2) && + (x_end == (long long)(z->w_list.a[(int64_t)(z->w_list.n)-1].x_end))) { + R_useless_side = 0; + } + + if(leftLen <= L_useless_side || rightLen <= R_useless_side) { + z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; + z->boundary_cigars.c.n = z->boundary_cigars.a[i].cidx; + continue; + } + + + + ///up to now, if we require (i)-th window and (i+1)-th window are matched + ///boundary_cigars.buffer[i].cigar, w_list[i].cigar and w_list[i+1].cigar are avaiable + ///get the error excluding the first and the last useless_side bases + scan_cigar_interval(&(z->boundary_cigars.a[i]), &(z->boundary_cigars), &m_error, L_useless_side, xLen-R_useless_side-1); + scan_cigar(&(z->w_list.a[i]), &(z->w_list), &b_err, leftLen-L_useless_side, 1); + scan_cigar(&(z->w_list.a[i+1]), &(z->w_list), &f_err, rightLen-R_useless_side, 0); + + if(f_err + b_err + y_distance + alpha < m_error) { + z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; + z->boundary_cigars.c.n = z->boundary_cigars.a[i].cidx; + continue; + } + + z->boundary_cigars.a[i].error = error; + z->boundary_cigars.a[i].y_start = y_start + real_y_start - extra_begin; + z->boundary_cigars.a[i].y_end = y_start + end_site - extra_begin; + + z->boundary_cigars.a[i].x_start = x_start; + z->boundary_cigars.a[i].x_end = x_end; + ///sub_list->boundary_cigars.buffer[i].error_threshold = useless_side; + z->boundary_cigars.a[i].extra_begin = L_useless_side; + z->boundary_cigars.a[i].extra_end = R_useless_side; + } + else { + z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; + continue; + } + } + +} + + +void calculate_ul_boundary_cigars(overlap_region* z, const ul_idx_t *uref, Correct_dumy* dumy, +UC_Read* g_read, double max_ov_diff_ec, long long blockLen) +{ + assert(z->w_list.n > 0); + int64_t nw = z->w_list.n; + resize_window_list_alloc(&(z->boundary_cigars), nw - 1); + int64_t y_id = z->y_id; + int64_t y_strand = z->y_pos_strand; + int64_t y_readLen = uref->ug->u.a[y_id].len; + int64_t i, y_distance; + int64_t f_err, b_err, m_error, scanLen = 10; + int64_t boundaryLen = WINDOW_UL_BOUND_RATE*blockLen; + boundaryLen >>= 2; boundaryLen <<= 2; + if(boundaryLen < WINDOW_UL_BOUND) boundaryLen = WINDOW_UL_BOUND; + int64_t single_sideLen = boundaryLen/2; + int64_t force_useless_side = single_sideLen/2; + int64_t L_useless_side, R_useless_side; + int64_t alpha = 1; + long long y_start, x_start, x_end, yLen, xLen, leftLen, rightLen, threshold, o_len; + int extra_begin, extra_end, end_site, real_y_start; + char* x_string; + char* y_string; + unsigned int error; + z->boundary_cigars.n = nw - 1; + ///the (i)-th boundary between the (i)-th window and the (i+1)-th window + ///that means it includes (the tail of (i)-th window) and (the header of (i+1)-th window) + ///note the (i)-th boundary is calculated at the (i)-th window + for (i = 0; i + 1 < nw; i++) { + ///if both of the two windows are not aligned + ///it is not necessary to calculate the boundary + ///if(sub_list->w_list[i].y_end == -1 && sub_list->w_list[i+1].y_end == -1) + if(z->w_list.a[i].y_end == -1 || z->w_list.a[i+1].y_end == -1) { + z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; + continue; + } + + ///note if w_list[i+1].y_start or sub_list->w_list[i].y_end is -1 + ///y_distance might have some problems at the last of this function + ///we need to deal with it carefully + y_distance = (int64_t)z->w_list.a[i+1].y_start - (int64_t)z->w_list.a[i].y_end - 1; + + ///if two windows are aligned + if(z->w_list.a[i].y_end != -1 && z->w_list.a[i+1].y_end != -1 && y_distance == 0) { + ///scan backward + scan_cigar(&(z->w_list.a[i]), &(z->w_list), &b_err, scanLen, 1); + ///scan forward + scan_cigar(&(z->w_list.a[i+1]), &(z->w_list), &f_err, scanLen, 0); + if(b_err == 0 && f_err == 0) { + z->boundary_cigars.a[i].error = -2; z->boundary_cigars.a[i].y_end = -1; + continue; + } + } + + + ///y_distance can be less than 0, or larger than 0 + if(z->w_list.a[i].y_end != -1) { + y_start = z->w_list.a[i].y_end; x_start = z->w_list.a[i].x_end; + }///if the (i)-th window is not matched, have a look at the (i+1)-th window + else if(z->w_list.a[i+1].y_end != -1) { + y_start = z->w_list.a[i+1].y_start; x_start = z->w_list.a[i+1].x_start; + }///if both of these two windows are not matched, directly skip + else { + z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; + continue; + } + + ///it seems we don't need to record x_start and y_start + z->boundary_cigars.a[i].extra_begin = x_start; + z->boundary_cigars.a[i].extra_end = y_start; + + ///leftLen and rightLen are used for x + ///x should be at [sub_list->w_list[i].x_start, sub_list->w_list[i+1].x_end] + ///y shouldn't have limitation + ///note that the x_start and x_end should not be -1 in any case + ///up to now, x_start and y_start are not -1 + ///leftLen does not include x_start itself, rightLen does + ///gnerally speaking, rightLen should be always larger than leftLen + leftLen = MIN(MIN((x_start - (long long)z->w_list.a[i].x_start), y_start), single_sideLen); + rightLen = MIN(MIN(((long long)z->w_list.a[i+1].x_end + 1 - x_start), y_readLen - y_start), single_sideLen); + + ///xLen should be the sum length of two windows + xLen = leftLen + rightLen; + x_start = x_start - leftLen; + x_end = x_start + xLen - 1; + y_start = y_start - leftLen; + + ///if we don't have enough leftLen and rightLen + // if(leftLen <= useless_side || rightLen <= useless_side) + // { + // sub_list->boundary_cigars.buffer[i].error = -1; + // sub_list->boundary_cigars.buffer[i].y_end = -1; + // continue; + // } + + + threshold = xLen * max_ov_diff_ec; + threshold = Adjust_Threshold(threshold, xLen); + threshold = double_ul_error_threshold(threshold, xLen); + + yLen = xLen + (threshold << 1); + if(!determine_overlap_region(threshold, y_start, y_id, yLen, uref->ug->u.a[y_id].len, + &extra_begin, &extra_end, &y_start, &o_len)) { + z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; + continue; + } + + if(o_len < xLen) { + z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; + continue; + } + + fill_subregion_ul(dumy->overlap_region, y_start, o_len, y_strand, + uref, y_id, extra_begin, extra_end); + + x_string = g_read->seq + x_start; + y_string = dumy->overlap_region; + + end_site = Reserve_Banded_BPM_PATH(y_string, yLen, x_string, xLen, threshold, &error, + &real_y_start, &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); + + ///means this window is matched + if (error!=(unsigned int)-1) { + z->boundary_cigars.a[i].x_start = x_start; z->boundary_cigars.a[i].x_end = x_end; + + generate_cigar(dumy->path, dumy->path_length, &(z->boundary_cigars.a[i]), &(z->boundary_cigars), + &real_y_start, &end_site, &error, x_string, xLen, y_string); + ///should not adjust cigar here, adjust cigar may cause problem + ///that is not what we want + + ///y_distance can be less than 0, or larger than 0 + ///please if one of the two windows is not matched, + ///y_distance may have potential problems + if(y_distance < 0) y_distance = y_distance * (-1); + ///leftLen, rightLen + // if(leftLen <= useless_side || rightLen <= useless_side) + // { + // sub_list->boundary_cigars.buffer[i].error = -1; + // sub_list->boundary_cigars.buffer[i].y_end = -1; + // continue; + // } + L_useless_side = R_useless_side = force_useless_side; + + ///first window + if((i == 0) && (x_start == (long long)z->w_list.a[0].x_start)) { + L_useless_side = 0; + } + ///last window + if((i == (int64_t)(z->w_list.n) - 2) && (x_end == (z->w_list.a[(int64_t)z->w_list.n - 1].x_end))) { + R_useless_side = 0; + } + + if(leftLen <= L_useless_side || rightLen <= R_useless_side) { + z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; + z->boundary_cigars.c.n = z->boundary_cigars.a[i].cidx; + continue; + } + + + + ///up to now, if we require (i)-th window and (i+1)-th window are matched + ///boundary_cigars.buffer[i].cigar, w_list[i].cigar and w_list[i+1].cigar are avaiable + ///get the error excluding the first and the last useless_side bases + scan_cigar_interval(&(z->boundary_cigars.a[i]), &(z->boundary_cigars), &m_error, + L_useless_side, xLen-R_useless_side-1); + scan_cigar(&(z->w_list.a[i]), &(z->w_list), &b_err, leftLen-L_useless_side, 1); + scan_cigar(&(z->w_list.a[i+1]), &(z->w_list), &f_err, rightLen-R_useless_side, 0); + + if(f_err + b_err + y_distance + alpha < m_error) { + z->boundary_cigars.a[i].error = -1; z->boundary_cigars.a[i].y_end = -1; + z->boundary_cigars.c.n = z->boundary_cigars.a[i].cidx; + continue; + } + + z->boundary_cigars.a[i].error = error; + z->boundary_cigars.a[i].y_start = y_start + real_y_start - extra_begin; + z->boundary_cigars.a[i].y_end = y_start + end_site - extra_begin; + + z->boundary_cigars.a[i].x_start = x_start; + z->boundary_cigars.a[i].x_end = x_end; + ///sub_list->boundary_cigars.buffer[i].error_threshold = useless_side; + z->boundary_cigars.a[i].extra_begin = L_useless_side; + z->boundary_cigars.a[i].extra_end = R_useless_side; + } + else + { + z->boundary_cigars.a[i].error = -1; + z->boundary_cigars.a[i].y_end = -1; + continue; + } + + } + +} + + +/** +void debug_window_cigar(overlap_region_alloc* overlap_list, UC_Read* g_read, Correct_dumy* dumy, +All_reads* R_INF, int test_window, int test_boundary) +{ + uint64_t i, j, y_id, y_strand; + char* x_string; + char* y_string; + long long x_start; + long long x_end; + long long x_len; + long long y_start; + long long y_end; + long long y_len; + + for (j = 0; j < overlap_list->length; j++) + { + y_id = overlap_list->list[j].y_id; + y_strand = overlap_list->list[j].y_pos_strand; + if(overlap_list->list[j].is_match == 1) + { + + if(test_window == 1) + { + for (i = 0; i < overlap_list->list[j].w_list_length; i++) + { + if(overlap_list->list[j].w_list[i].y_end != -1) + { + ///there is no problem for x + x_start = overlap_list->list[j].w_list[i].x_start; + x_end = overlap_list->list[j].w_list[i].x_end; + x_len = x_end - x_start + 1; + + x_string = g_read->seq + x_start; + + y_start = overlap_list->list[j].w_list[i].y_start; + y_end = overlap_list->list[j].w_list[i].y_end; + y_len = y_end - y_start + 1; + + recover_UC_Read_sub_region(dumy->overlap_region, y_start, y_len, y_strand, R_INF, y_id); + y_string = dumy->overlap_region; + + + if(verify_cigar(x_string, x_len, y_string, y_len, &overlap_list->list[j].w_list[i].cigar, + overlap_list->list[j].w_list[i].error)) + { + fprintf(stderr, "error\n"); + } + } + } + } + + + + if(test_boundary == 1) + { + for (i = 0; i < (uint64_t)overlap_list->list[j].boundary_cigars.length; i++) + { + if(overlap_list->list[j].boundary_cigars.buffer[i].y_end != -1) + { + x_start = overlap_list->list[j].boundary_cigars.buffer[i].x_start; + x_end = overlap_list->list[j].boundary_cigars.buffer[i].x_end; + x_len = x_end - x_start + 1; + x_string = g_read->seq + x_start; + + y_start = overlap_list->list[j].boundary_cigars.buffer[i].y_start; + y_end = overlap_list->list[j].boundary_cigars.buffer[i].y_end; + y_len = y_end - y_start + 1; + + recover_UC_Read_sub_region(dumy->overlap_region, y_start, y_len, y_strand, + R_INF, y_id); + y_string = dumy->overlap_region; + + + if(verify_cigar(x_string, x_len, y_string, y_len, + &overlap_list->list[j].boundary_cigars.buffer[i].cigar, + overlap_list->list[j].boundary_cigars.buffer[i].error)) + { + fprintf(stderr, "error\n"); + } + } + } + } + + + if(test_window == 1 && test_boundary == 1) + { + if(overlap_list->list[j].w_list_length != + (uint64_t)(overlap_list->list[j].boundary_cigars.length + 1)) + { + fprintf(stderr, "error\n"); + } + } + + } + } +} +**/ +int64_t get_adjust_winid(overlap_region *z, int64_t win_beg, int64_t win_len) +{ + int64_t win_id, k; + win_id = (win_beg-((z->x_pos_s/win_len)*win_len))/win_len; + if((uint64_t)win_id < z->w_list.n && z->w_list.a[win_id].x_start == win_beg) return win_id; + if(z->w_list.n == 0) return -1; + // if(z->w_list.a[win_id].x_start <= win_beg) { + // fprintf(stderr, "z->w_list.n::%u, z->w_list.a[%ld].x_start::%d, win_beg::%ld\n", + // (uint32_t)z->w_list.n, win_id, z->w_list.a[win_id].x_start, win_beg); + // } + if((uint64_t)win_id > z->w_list.n) win_id = z->w_list.n; + // assert((z->w_list.a[win_id].x_start > win_beg); + for (k = win_id - 1; k >= 0; k--) { + // if(k < 0 || k >= (int64_t)z->w_list.n) fprintf(stderr, "win_id::%ld, k::%ld, z->w_list.n::%ld\n", win_id, k, (int64_t)z->w_list.n); + if(z->w_list.a[k].x_start == win_beg) return k; + if(z->w_list.a[k].x_start < win_beg) return -1; + } + return -1; +} + +void set_herror_win(overlap_region_alloc* ovlp, Correct_dumy* du, kvec_t_u64_warp* v_idx, double max_ov_diff_ec, int64_t rLen, int64_t blockLen) +{ + Window_Pool w_inf; int32_t flag = 0; uint64_t cID, mm, fc, fw, idx_n, idx_i; + init_Window_Pool(&w_inf, rLen, blockLen, (int)(1.0/max_ov_diff_ec)); + long long window_start, window_end; int64_t i, k, mLen, w_list_id, ws, we; + + idx_n = get_num_wins(0, rLen, blockLen); idx_i = 0; + kv_resize(uint64_t, v_idx->a, idx_n); v_idx->a.n = idx_n; + + while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) { + du->length = du->lengthNT = 0; + flag = get_interval(window_start, window_end, ovlp, du, w_inf.window_length); + switch (flag) { + case 1: ///no match here + break; + case 0: ///no match here + break; + case -2: ///if flag == -2, loop would be terminated + break; + } + + v_idx->a.a[idx_i++] = ((uint64_t)(v_idx->a.n))<<32; + for (i = 0; i < (int64_t)du->length; i++) { + cID = (uint32_t)du->overlapID[i]; + if(ovlp->list[cID].is_match!=3 && ovlp->list[cID].is_match!=4) continue; + w_list_id = get_adjust_winid(&(ovlp->list[cID]), window_start, w_inf.window_length); + if(w_list_id >= 0) break;///a matched window + } + if(i < (int64_t)du->length) continue;///if there is a matched window + + for (i = 0, mm = 0; i < (int64_t)du->length; i++) {///all windows are unmatched + cID = (uint32_t)du->overlapID[i]; + if(ovlp->list[cID].is_match!=3 && ovlp->list[cID].is_match!=4) continue; + ovlp->list[cID].is_match = 4; + ovlp->list[cID].align_length += window_end + 1 - window_start; + mm++; + } + if(mm > 0) { + kv_push(uint64_t, v_idx->a, (((uint64_t)window_start)<<32)|((uint64_t)window_end)); + v_idx->a.a[idx_i-1]++; + } + + + ///shorter than blockLen + for (i = du->size-du->lengthNT, mLen = du->size-du->lengthNT, fc = 0; i < (int64_t)du->size; i++) { + cID = (uint32_t)du->overlapID[i]; + if(ovlp->list[cID].is_match!=3 && ovlp->list[cID].is_match!=4) continue; + get_win_se_by_normalize_xs(&(ovlp->list[cID]), window_start, blockLen, &ws, &we); + w_list_id = get_adjust_winid(&(ovlp->list[cID]), ws, blockLen); + if (w_list_id >= 0) {///matched + cID = w_list_id; cID <<= 32; cID += (uint32_t)du->overlapID[i]; du->overlapID[i] = cID; + if(mLen != i) { + mm = du->overlapID[i]; du->overlapID[i] = du->overlapID[mLen]; du->overlapID[mLen] = mm; + } + mLen++; + } else {///unmatched + cID = (uint32_t)-1; cID <<= 32; cID += (uint32_t)du->overlapID[i]; du->overlapID[i] = cID; + fc++; + } + } + // if(mLen == (int64_t)du->size) continue;///if all windows shorter than blockLen are matched + if(fc == 0) continue;///no unmatched windows that are shorter than blockLen + for (i = mLen; i < (int64_t)du->size; i++){///check the remaining unmatched windows that are shorter than blockLen + cID = (uint32_t)du->overlapID[i]; + if(ovlp->list[cID].is_match!=3 && ovlp->list[cID].is_match!=4) continue; + assert((du->overlapID[i]>>32)==(uint32_t)-1); + get_win_se_by_normalize_xs(&(ovlp->list[cID]), window_start, blockLen, &ws, &we); + for (k = du->size-du->lengthNT; k < mLen; k++) {///all matched windows + fc = (uint32_t)du->overlapID[k]; fw = du->overlapID[k]>>32; + assert(fw!=(uint32_t)-1); assert(ovlp->list[fc].is_match == 3 || ovlp->list[fc].is_match == 4); + // if (ovlp->list[fc].w_list[fw].y_end == -1 || (ovlp->list[fc].is_match!=3 && ovlp->list[fc].is_match!=4)) fprintf(stderr, "ERROR\n"); + ///if there is one matched window can cover the unmatched window + if(ovlp->list[fc].w_list.a[fw].x_start<=ws && ovlp->list[fc].w_list.a[fw].x_end>=we) { + break; + } + } + + if(k >= mLen) {///no matched window can cover the unmatched window + ovlp->list[cID].is_match = 4; + ovlp->list[cID].align_length += we + 1 - ws; + kv_push(uint64_t, v_idx->a, (((uint64_t)ws)<<32)|((uint64_t)we)); + v_idx->a.a[idx_i-1]++; + } + } + } +} + + +inline void recalcate_window_advance(overlap_region_alloc* overlap_list, All_reads *rref, const ul_idx_t *uref, + UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, kvec_t_u64_warp* v_idx, int64_t block_s, double e_rate, double e_rate_final) +{ + long long j, k, i; + int threshold; + long long y_id; + int y_strand; + long long y_readLen; + long long x_start; + long long x_end; + long long x_len; + long long total_y_start; + long long total_y_end; + long long y_start; + long long Window_Len; + char* x_string; + char* y_string; + int end_site; + unsigned int error; + int real_y_start; + long long overlap_length; + int extra_begin, extra_end; + long long o_len; + int64_t nw, a_nw, w_id, w_s, w_e, is_srt; + double error_rate; + uint64_t *w_idx; + overlap_region *z; + window_list *p = NULL; + + + overlap_list->mapped_overlaps_length = 0; + for (j = 0; j < (long long)overlap_list->length; j++) { + z = &(overlap_list->list[j]); z->is_match = 0; is_srt = 1; + if(z->w_list.n == 0) continue;///no alignment + nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); a_nw = z->w_list.n; + kv_resize(uint64_t, v_idx->a, (uint64_t)nw); memset(v_idx->a.a, -1, sizeof((*v_idx->a.a))*nw); w_idx = v_idx->a.a; + for (i = 0; i < a_nw; i++) { + assert(z->w_list.a[i].y_end != -1); + w_id = get_win_id_by_s(z, z->w_list.a[i].x_start, block_s, NULL); + w_idx[w_id] = i; + } + // if(j == 248) { + // fprintf(stderr, "0-[M::%s] j::%lld, nw::%ld, a_nw::%ld, z->x_pos_s::%u, z->x_pos_e::%u, z->y_pos_s::%u, z->y_pos_e::%u, w_idx[0]::%lu\n", __func__, + // j, nw, a_nw, z->x_pos_s, z->x_pos_e, z->y_pos_s, z->y_pos_e, w_idx[0]); + // } + + y_id = z->y_id; y_strand = z->y_pos_strand; + y_readLen = (rref?(Get_READ_LENGTH((*rref), y_id)):(uref->ug->u.a[y_id].len)); + for (i = a_nw-1; i >= 0; i--) { //utilize the the end pos of pre-window in forward + w_id = get_win_id_by_s(z, z->w_list.a[i].x_start, block_s, &w_e); + // if(z->w_list.a[i].x_end != w_e) { + // fprintf(stderr, "[M::%s] block_s->%ld, w_id->%ld, z::x_pos_s->%u, z::x_pos_e->%u, x_start->%d, x_end->%d, w_e->%ld\n", __func__, block_s, w_id, z->x_pos_s, z->x_pos_e, + // z->w_list.a[i].x_start, z->w_list.a[i].x_end, w_e); + // } + assert(z->w_list.a[i].x_end == w_e); + total_y_start = z->w_list.a[i].y_end + 1 - z->w_list.a[i].extra_begin; + for (k = w_id + 1; k < nw; k++) { + if(w_idx[k] != (uint64_t)-1) break; + w_s = w_e + 1; + w_id = get_win_id_by_s(z, w_s, block_s, &w_e); + assert(w_id == k); + extra_begin = extra_end = 0; + if (total_y_start >= y_readLen) break; + ///there is no problem for x + x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; y_start = total_y_start; + ///there are two potiential reasons for unmatched window: + ///1. this window has a large number of differences + ///2. DP does not start from the right offset + if(rref) { + threshold = double_error_threshold(get_init_err_thres(x_len, e_rate, block_s, THRESHOLD), x_len); + } else { + threshold = double_ul_error_threshold(get_init_err_thres(x_len, e_rate, block_s, THRESHOLD_MAX_SIZE), x_len); + } + + Window_Len = x_len + (threshold << 1); + + if(!determine_overlap_region(threshold, y_start, y_id, Window_Len, (rref?(Get_READ_LENGTH((*rref), y_id)):(uref->ug->u.a[y_id].len)), + &extra_begin, &extra_end, &y_start, &o_len)) { + break; + } + if(o_len + threshold < x_len) break; + + if(rref) { + fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, rref, y_id, extra_begin, extra_end); + } else { + fill_subregion_ul(dumy->overlap_region, y_start, o_len, y_strand, uref, y_id, extra_begin, extra_end); + } + + x_string = g_read->seq + x_start; y_string = dumy->overlap_region; + ///note!!! need notification + end_site = Reserve_Banded_BPM(y_string, Window_Len, x_string, x_len, threshold, &error); + if (error!=(unsigned int)-1) {///unmatched + kv_pushp(window_list, z->w_list, &p); + p->x_start = x_start; + p->x_end = x_end; + p->y_start = y_start; + p->y_end = y_start + end_site; + p->error = error; + p->extra_begin = extra_begin; + p->extra_end = extra_end; + p->error_threshold = threshold; + p->cidx = p->clen = 0; + + z->align_length += x_len; w_idx[k] = z->w_list.n - 1; + + if(is_srt && z->w_list.n > 1 && p->x_start < z->w_list.a[z->w_list.n-2].x_start) is_srt = 0; + } + else { + break; + } + + total_y_start = y_start + end_site + 1 - extra_begin; + } + } + // if(j == 248) { + // fprintf(stderr, "1-[M::%s] j::%lld, nw::%ld, a_nw::%ld, z->x_pos_s::%u, z->x_pos_e::%u, z->y_pos_s::%u, z->y_pos_e::%u, w_idx[0]::%lu\n", __func__, + // j, nw, a_nw, z->x_pos_s, z->x_pos_e, z->y_pos_s, z->y_pos_e, w_idx[0]); + // } + for (i = 0; i < nw; i++) { //utilize the the start pos of next window in backward + ///find the first matched window, which should not be the first window + ///the pre-window of this matched window must be unmatched + if(i > 0 && w_idx[i] != (uint64_t)-1 && w_idx[i-1] == (uint64_t)-1) { + w_s = z->w_list.a[w_idx[i]].x_start; + ///check if the start pos of this matched window has been calculated + if(z->w_list.a[w_idx[i]].clen == 0) { + p = &(z->w_list.a[w_idx[i]]); + ///there is no problem for x + x_start = p->x_start; x_end = p->x_end; x_len = x_end + 1 - x_start; threshold = p->error_threshold; + /****************************may have bugs********************************/ + ///should not adjust threshold, since this window can be matched by the old threshold + ///threshold = Adjust_Threshold(threshold, x_len); + /****************************may have bugs********************************/ + Window_Len = x_len + (threshold << 1); + ///y_start is the real y_start + y_start = p->y_start; extra_begin = p->extra_begin; extra_end = p->extra_end; + o_len = Window_Len - extra_end - extra_begin; + if(rref) { + fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, rref, y_id, extra_begin, extra_end); + } else { + fill_subregion_ul(dumy->overlap_region, y_start, o_len, y_strand, uref, y_id, extra_begin, extra_end); + } + + x_string = g_read->seq + x_start; + y_string = dumy->overlap_region; + + end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, + &(dumy->path_length), dumy->matrix_bit, dumy->path, p->error, p->y_end - y_start); + assert(error != (unsigned int)-1); + + { + ///this condition is always wrong + ///in best case, real_y_start = threshold, end_site = Window_Len - threshold - 1 + if (end_site == Window_Len - 1 || real_y_start == 0) { + if(rref) { + if(fix_boundary(x_string, x_len, threshold, y_start, real_y_start, + end_site, extra_begin, extra_end, y_id, Window_Len, rref, dumy, + y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, + &extra_end, &error)) { + p->error = error; p->extra_begin = extra_begin; p->extra_end = extra_end; + } + } else { + if(fix_ul_boundary(x_string, x_len, threshold, y_start, real_y_start, + end_site, extra_begin, extra_end, y_id, Window_Len, uref, dumy, + y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, + &extra_end, &error)) { + p->error = error; p->extra_begin = extra_begin; p->extra_end = extra_end; + } + } + } + + generate_cigar(dumy->path, dumy->path_length, p, &(z->w_list), &real_y_start, &end_site, &error, x_string, x_len, y_string); + + ///note!!! need notification + real_y_start = y_start + real_y_start - extra_begin; + p->y_start = real_y_start; + ///I forget why don't reduce the extra_begin for y_end + ///it seems extra_begin will be reduced at the end of this function + p->y_end = y_start + end_site; + p->error = error; + } + } else { + real_y_start = p->y_start; + } + + ///the end pos for pre window is real_y_start - 1 + total_y_end = real_y_start - 1; + ///find the unmatched window on the left of current matched window + ///k starts from i - 1 + for (k = i - 1; k >= 0 && w_idx[k] == (uint64_t)-1; k--) { + w_e = w_s - 1; + w_id = get_win_id_by_e(z, w_e, block_s, &w_s); + assert(w_id == k); + ///there is no problem in x + x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; + ///there are two potiential reasons for unmatched window: + ///1. this window has a large number of differences + ///2. DP does not start from the right offset + if(rref) { + threshold = double_error_threshold(get_init_err_thres(x_len, e_rate, block_s, THRESHOLD), x_len); + } else { + threshold = double_ul_error_threshold(get_init_err_thres(x_len, e_rate, block_s, THRESHOLD_MAX_SIZE), x_len); + } + Window_Len = x_len + (threshold << 1); + if(total_y_end <= 0) break; + + ///y_start might be less than 0 + y_start = total_y_end - x_len + 1; + if(!determine_overlap_region(threshold, y_start, y_id, Window_Len, (rref?(Get_READ_LENGTH((*rref), y_id)):(uref->ug->u.a[y_id].len)), + &extra_begin, &extra_end, &y_start, &o_len)) { + break; + } + + if(o_len + threshold < x_len) break; + + if(rref) { + fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, rref, y_id, extra_begin, extra_end); + } else { + fill_subregion_ul(dumy->overlap_region, y_start, o_len, y_strand, uref, y_id, extra_begin, extra_end); + } + x_string = g_read->seq + x_start; + y_string = dumy->overlap_region; + + ///note!!! need notification + end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, + &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); + + if (error!=(unsigned int)-1) { + ///this condition is always wrong + ///in best case, real_y_start = threshold, end_site = Window_Len - threshold - 1 + if (end_site == Window_Len - 1 || real_y_start == 0) { + if(rref) { + fix_boundary(x_string, x_len, threshold, y_start, real_y_start, + end_site, extra_begin, extra_end, y_id, Window_Len, rref, dumy, + y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, + &extra_end, &error); + } else { + fix_ul_boundary(x_string, x_len, threshold, y_start, real_y_start, + end_site, extra_begin, extra_end, y_id, Window_Len, uref, dumy, + y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, + &extra_end, &error); + } + } + + kv_pushp(window_list, z->w_list, &p); + p->x_start = x_start; p->x_end = x_end;///must set x_start/x_end here + generate_cigar(dumy->path, dumy->path_length, p, &(z->w_list), &real_y_start, &end_site, &error, x_string, x_len, y_string); + + ///y_start has no shift, but y_end has shift + p->y_start = y_start + real_y_start - extra_begin; + p->y_end = y_start + end_site; + p->error = error; + p->extra_begin = extra_begin; + p->extra_end = extra_end; + p->error_threshold = threshold; + z->align_length += x_len; w_idx[k] = z->w_list.n - 1; + + if(is_srt && z->w_list.n > 1 && p->x_start < z->w_list.a[z->w_list.n-2].x_start) is_srt = 0; + } + else { + break; + } + + total_y_end = y_start + real_y_start - 1 - extra_begin; + } + } + } + + // if(j == 248) { + // fprintf(stderr, "2-[M::%s] j::%lld, nw::%ld, a_nw::%ld, z->x_pos_s::%u, z->x_pos_e::%u, z->y_pos_s::%u, z->y_pos_e::%u, w_idx[0]::%lu, w_idx[0]->cidx::%u, w_idx[0]->clen::%u, w_idx[0]->cigar[0]:%u\n", __func__, + // j, nw, a_nw, z->x_pos_s, z->x_pos_e, z->y_pos_s, z->y_pos_e, w_idx[0], z->w_list.a[w_idx[0]].cidx, z->w_list.a[w_idx[0]].clen, z->w_list.c.a[z->w_list.a[w_idx[0]].cidx]); + // } + + if(uref) { + z->is_match = 0; + if((((z->x_pos_e + 1 - z->x_pos_s)*MIN_UL_ALIN_RATE) <= z->align_length) && (z->align_length >= MIN_UL_ALIN_LEN)){ + z->is_match = 3; overlap_list->mapped_overlaps_length += z->align_length; + ///sort for set_herror_win + if(!is_srt) radix_sort_window_list_xs_srt(z->w_list.a, z->w_list.a + z->w_list.n); + } + } + } + + // fprintf(stderr, "+++[M::%s::idx->%d::y_id->%u] z::align_length->%u, e_threshold->%f\n", + // __func__, 27, overlap_list->list[27].y_id, overlap_list->list[27].align_length, e_rate); + + // fprintf(stderr, "+++[M::%s::idx->%d::y_id->%u] z::align_length->%u, e_threshold->%f\n", + // __func__, 45, overlap_list->list[45].y_id, overlap_list->list[45].align_length, e_rate); + + // fprintf(stderr, "+++[M::%s::idx->%d::y_id->%u] z::align_length->%u, e_threshold->%f\n", + // __func__, 277, overlap_list->list[277].y_id, overlap_list->list[277].align_length, e_rate); + + if(uref && overlap_list->mapped_overlaps_length > 0) { + set_herror_win(overlap_list, dumy, v_idx, e_rate, g_read->length, block_s); + } + + overlap_list->mapped_overlaps_length = 0; + for (j = 0; j < (long long)overlap_list->length; j++) { + z = &(overlap_list->list[j]); + y_id = z->y_id; y_strand = z->y_pos_strand; + y_readLen = (rref?(Get_READ_LENGTH((*rref), y_id)):(uref->ug->u.a[y_id].len)); + overlap_length = z->x_pos_e + 1 - z->x_pos_s; //z->is_match = 0; + // if(y_id == 0 || y_id == 1) { + // fprintf(stderr, "[M::%s::j->%lld] utg%.6dl(%c), align_length::%u, overlap_length::%lld\n", __func__, + // j, (int32_t)z->y_id + 1, "+-"[z->y_pos_strand], z->align_length, overlap_length); + // } + // if(y_id == 24128) { + // fprintf(stderr, "[M::%s::idx->%lld::] x::[%u, %u), y::[%u, %u), ovl->%lld, aln->%u\n", + // __func__, j, z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1, overlap_length, z->align_length); + // radix_sort_window_list_xs_srt(z->w_list.a, z->w_list.a + z->w_list.n); a_nw = z->w_list.n; + // int64_t ss, ee; + // for (i = 0, ss = ee = -2; i < a_nw; i++) { + // p = &(z->w_list.a[i]); + // if(p->x_start == ee) { + // ee = p->x_end + 1; + // } else { + // if(ee > 0) { + // fprintf(stderr, "[M::%s::] x::[%ld, %ld)\n", __func__, ss, ee); + // } + // ss = p->x_start; ee = p->x_end + 1; + // } + // } + // if(ee > 0) { + // fprintf(stderr, "[M::%s::] x::[%ld, %ld)\n", __func__, ss, ee); + // } + + // for (i = 0; i < a_nw; i++) { + // p = &(z->w_list.a[i]); if(p->y_end == -1) continue; + // fprintf(stderr, "[M::%s::] x::[%d, %d), y::[%d, %d), error::%d\n", __func__, p->x_start, p->x_end + 1, p->y_start, p->y_end + 1, p->error); + // } + // } + + ///debug_scan_cigar(&(overlap_list->list[j])); + ///only calculate cigar for high quality overlaps + if ((rref && (overlap_length*OVERLAP_THRESHOLD_HIFI_FILTER <= z->align_length)) || + (uref && (overlap_length*(1-e_rate) <= z->align_length))) { + a_nw = z->w_list.n; + // int64_t tt = 0; + for (i = 0, is_srt = 1; i < a_nw; i++) { + p = &(z->w_list.a[i]); + ///check if the cigar of this window has been got + if(p->clen == 0) { + ///there is no problem for x + x_start = p->x_start; x_end = p->x_end; x_len = x_end - x_start + 1; + /****************************may have bugs********************************/ + ///threshold = x_len * asm_opt.max_ov_diff_ec; + threshold = p->error_threshold; + /****************************may have bugs********************************/ + /****************************may have bugs********************************/ + ///should not adjust threshold, since this window can be matched by the old threshold + ///threshold = Adjust_Threshold(threshold, x_len); + /****************************may have bugs********************************/ + Window_Len = x_len + (threshold << 1); + + + ///y_start is the real y_start + ///for the window with cigar, y_start has already reduced extra_begin + y_start = p->y_start; extra_begin = p->extra_begin; extra_end = p->extra_end; + o_len = Window_Len - extra_end - extra_begin; + if(rref) { + fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, rref, y_id, extra_begin, extra_end); + } else { + fill_subregion_ul(dumy->overlap_region, y_start, o_len, y_strand, uref, y_id, extra_begin, extra_end); + } + x_string = g_read->seq + x_start; y_string = dumy->overlap_region; + + + ///note!!! need notification + end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, + &(dumy->path_length), dumy->matrix_bit, dumy->path, p->error, p->y_end - y_start); + // if(!(error != (unsigned int)-1)) { + // fprintf(stderr, "[M::%s::]\tqid::%u\tqlen::%lu\tq::[%d,\t%d)\ttid::%u\ttlen::%lu\tt::[%d,\t%d)\te_beg::%d\te_end::%d\terr::%d\n", __func__, + // overlap_list->list[j].x_id, Get_READ_LENGTH((*rref), overlap_list->list[j].x_id), + // p->x_start, p->x_end+1, + // overlap_list->list[j].y_id, Get_READ_LENGTH((*rref), overlap_list->list[j].y_id), + // p->y_start, p->y_end+1, + // p->extra_begin, p->extra_end, p->error); + // fprintf(stderr, "[M::%s::]\tqcal_len::%lld\ttcal_len::%lld\tthres::%d\n", __func__, + // x_len, Window_Len, threshold); + // fprintf(stderr, "qid::%u\nqname::%.*s\n\t%.*s\n", overlap_list->list[j].x_id, + // (int32_t)Get_NAME_LENGTH((*rref), overlap_list->list[j].x_id), + // Get_NAME((*rref), overlap_list->list[j].x_id), (int32_t)x_len, x_string); + + // fprintf(stderr, "tid::%u\ntname::%.*s\n\t%.*s\n", overlap_list->list[j].y_id, + // (int32_t)Get_NAME_LENGTH((*rref), overlap_list->list[j].y_id), + // Get_NAME((*rref), overlap_list->list[j].y_id), (int32_t)Window_Len, y_string); + + // } + assert(error != (unsigned int)-1); + + { + if (end_site == Window_Len - 1 || real_y_start == 0) { + if(rref) { + if(fix_boundary(x_string, x_len, threshold, y_start, real_y_start, end_site, + extra_begin, extra_end, y_id, Window_Len, rref, dumy, y_strand, error, + &y_start, &real_y_start, &end_site, &extra_begin, &extra_end, &error)) { + p->error = error; p->extra_begin = extra_begin; p->extra_end = extra_end; + } + } else { + if(fix_ul_boundary(x_string, x_len, threshold, y_start, real_y_start, + end_site, extra_begin, extra_end, y_id, Window_Len, uref, dumy, + y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, + &extra_end, &error)) { + p->error = error; p->extra_begin = extra_begin; p->extra_end = extra_end; + } + } + } + + generate_cigar(dumy->path, dumy->path_length, p, &(z->w_list), &real_y_start, &end_site, &error, x_string, x_len, y_string); + + ///note!!! need notification + real_y_start = y_start + real_y_start - extra_begin; + p->y_start = real_y_start; + p->y_end = y_start + end_site - extra_begin; + p->error = error; + } + + // if(y_id == 4) { + // fprintf(stderr, "+[M::idx->%lld::] y_start->%d, y_end->%d, error->%d\n", + // j, p->y_start, p->y_end, p->error); + // } + } + else { + p->y_end -= p->extra_begin; + // if(y_id == 4) { + // fprintf(stderr, "-[M::idx->%lld::] y_start->%d, y_end->%d, error->%d\n", + // j, p->y_start, p->y_end, p->error); + // } + } + // tt += p->error; + if(is_srt && i > 0 && p->x_start < z->w_list.a[i-1].x_start) is_srt = 0; + } + + if(!is_srt) radix_sort_window_list_xs_srt(z->w_list.a, z->w_list.a + z->w_list.n); + error_rate = non_trim_error_rate(z, rref, uref, v_idx, dumy, g_read, e_rate, block_s); + z->is_match = 0; + // if(y_id == 4) { + // fprintf(stderr, "[M::%s::idx->%lld::] z::x_pos_s->%u, z::x_pos_e->%u, ovl->%lld, aln->%u, error_rate->%f, e_rate_final->%f, tt->%ld\n", + // __func__, j, z->x_pos_s, z->x_pos_e, overlap_length, z->align_length, error_rate, e_rate_final, tt); + // } + + if (error_rate <= e_rate_final/**asm_opt.max_ov_diff_final**/) { + overlap_list->mapped_overlaps_length += overlap_length; + z->is_match = 1; append_unmatched_wins(z, block_s); + // if(j == 248) { + // fprintf(stderr, "3-[M::%s] j::%lld, nw::%ld, a_nw::%ld, z->x_pos_s::%u, z->x_pos_e::%u, z->y_pos_s::%u, z->y_pos_e::%u, w_idx[0]::%lu, w_idx[0]->cidx::%u, w_idx[0]->clen::%u, w_idx[0]->cigar[0]:%u\n", __func__, + // j, nw, a_nw, z->x_pos_s, z->x_pos_e, z->y_pos_s, z->y_pos_e, w_idx[0], z->w_list.a[w_idx[0]].cidx, z->w_list.a[w_idx[0]].clen, z->w_list.c.a[z->w_list.a[w_idx[0]].cidx]); + // } + if(rref) { + calculate_boundary_cigars(z, rref, dumy, g_read, e_rate); + } else { + calculate_ul_boundary_cigars(z, uref, dumy, g_read, e_rate, block_s); + } + // if(j == 248) { + // fprintf(stderr, "4-[M::%s] j::%lld, nw::%ld, a_nw::%ld, z->x_pos_s::%u, z->x_pos_e::%u, z->y_pos_s::%u, z->y_pos_e::%u, w_idx[0]::%lu, w_idx[0]->cidx::%u, w_idx[0]->clen::%u, w_idx[0]->cigar[0]:%u\n", __func__, + // j, nw, a_nw, z->x_pos_s, z->x_pos_e, z->y_pos_s, z->y_pos_e, w_idx[0], z->w_list.a[w_idx[0]].cidx, z->w_list.a[w_idx[0]].clen, z->w_list.c.a[z->w_list.a[w_idx[0]].cidx]); + // } + // if((int64_t)z->x_pos_s!=z->w_list.a[0].x_start || + // (int64_t)z->x_pos_e!=z->w_list.a[z->w_list.n-1].x_end) { + // fprintf(stderr, "[M::%s] z::x_pos_s->%u, z::x_pos_e->%u, (0)::x_start->%d, (wn-1)x_end->%d, z->w_list.n->%ld\n", __func__, + // z->x_pos_s, z->x_pos_e, z->w_list.a[0].x_start, z->w_list.a[z->w_list.n-1].x_end, (int64_t)z->w_list.n); + // } + + // assert(get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s)==(int64_t)z->w_list.n); + // assert((int64_t)z->x_pos_s==z->w_list.a[0].x_start && + // (int64_t)z->x_pos_e==z->w_list.a[z->w_list.n-1].x_end); + } else if (error_rate <= /**asm_opt.max_ov_diff_final**/e_rate_final * 1.5) { + z->is_match = 3; + } + // fprintf(stderr, "[M::%s::idx->%lld::is_match->%u] z::y_id->%u, z::x_pos_s->%u, z::x_pos_e->%u, error_rate->%f, e_threshold->%f\n", + // __func__, j, z->is_match, z->y_id, z->x_pos_s, z->x_pos_e, error_rate, e_rate); + } else {///it impossible to be matched + z->is_match = 0; + // fprintf(stderr, "[M::%s::idx->%ld::is_match->%u] z::x_pos_s->%u, z::x_pos_e->%u, error_rate->-1, e_threshold->%f\n", + // __func__, j, z->is_match, z->x_pos_s, z->x_pos_e, e_rate); + } + + + } + ///debug_window_cigar(overlap_list, g_read, dumy, rref, 1, 1); +} + +uint32_t inline simi_pass(int64_t ol, int64_t aln_ol, uint32_t second_ck, double o_rate, double *e_rate) +{ + if(aln_ol == 0 || ol == 0) return 0; + if((!second_ck) && (!e_rate)) { + // if((ol*OVERLAP_THRESHOLD_FILTER) <= aln_ol) return 1; + if((ol*o_rate) <= aln_ol) return 1; + } else if(e_rate) { + if((ol*((double)(((double)1.0)-(*e_rate)))) <= aln_ol) return 1; + } else if(second_ck) { + if(((ol*MIN_UL_ALIN_RATE) <= aln_ol) && (aln_ol >= MIN_UL_ALIN_LEN)) return 1; + } + + // if(rref) { + // if((ol*OVERLAP_THRESHOLD_FILTER) <= aln_ol) return 1; + // } else if(uref) { + // if(e_rate) { + // if((ol*((double)(((double)1.0)-(*e_rate)))) <= aln_ol) return 1; + // } else { + // if(((ol*MIN_UL_ALIN_RATE) <= aln_ol) && (aln_ol >= MIN_UL_ALIN_LEN)) return 1; + // } + // } + + return 0; +} + +inline uint32_t gen_backtrace(window_list *p, overlap_region *z, All_reads *rref, const ul_idx_t *uref, UC_Read* g_read, Correct_dumy* dumy, +int32_t y_strand, int32_t y_id) +{ + int64_t x_start, x_end, x_len, Window_Len, o_len; + int32_t threshold; long long y_start; + int real_y_start = 0, end_site, extra_begin, extra_end; + char *x_string, *y_string; unsigned int error; + ///there is no problem for x + x_start = p->x_start; x_end = p->x_end; x_len = x_end - x_start + 1; + threshold = p->error_threshold; Window_Len = x_len + (threshold << 1); + + + ///y_start is the real y_start + ///for the window with cigar, y_start has already reduced extra_begin + y_start = p->y_start; extra_begin = p->extra_begin; extra_end = p->extra_end; + o_len = Window_Len - extra_end - extra_begin; + if(rref) { + fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, rref, y_id, extra_begin, extra_end); + } else { + fill_subregion_ul(dumy->overlap_region, y_start, o_len, y_strand, uref, y_id, extra_begin, extra_end); + } + x_string = g_read->seq + x_start; y_string = dumy->overlap_region; + + + ///note!!! need notification + end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, + &(dumy->path_length), dumy->matrix_bit, dumy->path, p->error, p->y_end - y_start); + // assert(error != (unsigned int)-1); + if(error != (unsigned int)-1) { + ///this condition is always wrong + ///in best case, real_y_start = threshold, end_site = Window_Len - threshold - 1 + if (end_site == Window_Len - 1 || real_y_start == 0) { + if(rref) { + if(fix_boundary(x_string, x_len, threshold, y_start, real_y_start, end_site, + extra_begin, extra_end, y_id, Window_Len, rref, dumy, y_strand, error, + &y_start, &real_y_start, &end_site, &extra_begin, &extra_end, &error)) { + p->error = error; p->extra_begin = extra_begin; p->extra_end = extra_end; + } + } else { + if(fix_ul_boundary(x_string, x_len, threshold, y_start, real_y_start, + end_site, extra_begin, extra_end, y_id, Window_Len, uref, dumy, + y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, + &extra_end, &error)) { + p->error = error; p->extra_begin = extra_begin; p->extra_end = extra_end; + } + } + } + + generate_cigar(dumy->path, dumy->path_length, p, &(z->w_list), &real_y_start, &end_site, &error, x_string, x_len, y_string); + + ///note!!! need notification + real_y_start = y_start + real_y_start - extra_begin; + p->y_start = real_y_start; + p->y_end = y_start + end_site - extra_begin; + p->error = error; + return 1; + } + p->error = -1; + return 0; +} + +void gen_rev_str(char *in, char **out, uint32_t len) +{ + char *r; uint32_t k; MALLOC(r, len); (*out) = r; + for (k = 0; k < len; k++) r[k] = in[len-k-1]; +} + +inline uint32_t gen_backtrace_adv(window_list *p, overlap_region *z, All_reads *rref, hpc_t *hpc_g, const ul_idx_t *uref, +char *qstr, char *tstr, char *tstr1, Correct_dumy* dumy, uint32_t rev, uint32_t id) +{ + int64_t qs, qe, ql, aln_l, t_pri_l, thres, ts; + int r_ts = 0, t_end; int64_t aux_beg, aux_end; + char *q_string, *t_string; unsigned int error; + ///there is no problem for x + qs = p->x_start; qe = p->x_end; ql = qe + 1 - qs; + thres = p->error_threshold; aln_l = ql + (thres<<1); + + ///y_start is the real y_start + ///for the window with cigar, y_start has already reduced extra_begin + ts = p->y_start; aux_beg = p->extra_begin; aux_end = p->extra_end; + t_pri_l = aln_l - aux_beg - aux_end; + + q_string = qstr + qs; + if(rref) { + fill_subregion(tstr, ts, t_pri_l, rev, rref, id, aux_beg, aux_end); t_string = tstr; + } else { + t_string = return_str_seq(tstr, ts, t_pri_l, rev, hpc_g, uref, id, aux_beg, aux_end); + } + + t_end = Reserve_Banded_BPM_PATH(t_string, aln_l, q_string, ql, thres, &error, &r_ts, + &(dumy->path_length), dumy->matrix_bit, dumy->path, p->error, p->y_end - ts); + + // assert(error != (unsigned int)-1); + if(error != (unsigned int)-1) { + /** + bit_extz_t exz, exz64; init_bit_extz_t(&exz, thres); init_bit_extz_t(&exz64, thres); + // ed_band_cal_extension_64_0_w(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz64); + // ed_band_cal_extension_64_0_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz64); + // cigar_check(t_string+r_ts, q_string, &(exz64)); + // exz64.err = INT32_MAX; + // ed_band_cal_extension_64_0_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz64); + // cigar_check(t_string+r_ts, q_string, &(exz64)); + + // ed_band_cal_extension_infi_0_w(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, NULL, &exz); + // ed_band_cal_extension_infi_0_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, NULL, &exz); + // cigar_check(t_string+r_ts, q_string, &exz); + // exz.err = INT32_MAX; + // ed_band_cal_extension_infi_0_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, NULL, &exz); + // cigar_check(t_string+r_ts, q_string, &exz); + // assert(exz.err <= (int32_t)error && exz.err >= 0); + // assert(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); + + // ed_band_cal_extension_256_0_w(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz); + // ed_band_cal_extension_256_0_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz); + // cigar_check(t_string+r_ts, q_string, &exz); + // exz.err = INT32_MAX; + // ed_band_cal_extension_256_0_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz); + // cigar_check(t_string+r_ts, q_string, &exz); + // assert(exz.err <= (int32_t)error && exz.err >= 0); + // assert(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); + + // char *qr, *tr; + // gen_rev_str(q_string, &qr, ql); gen_rev_str(t_string+r_ts, &tr, t_end+1-r_ts); + + // ed_band_cal_extension_64_1_w(tr, t_end+1-r_ts, qr, ql, thres, &exz64); + // ed_band_cal_extension_64_1_w_trace(tr, t_end+1-r_ts, qr, ql, thres, &exz64); + // cigar_check(tr, qr, &exz64); + // exz64.err = INT32_MAX; + // ed_band_cal_extension_64_1_w_trace(tr, t_end+1-r_ts, qr, ql, thres, &exz64); + // cigar_check(tr, qr, &exz64); + // assert(exz.err == exz64.err && exz.ps == (exz64.pl-exz64.pe-1) && exz.pe == (exz64.pl-exz64.ps-1) && exz.ts == (exz64.tl-exz64.te-1) && exz.te == (exz64.tl-exz64.ts-1)); + + // ed_band_cal_extension_infi_1_w(tr, t_end+1-r_ts, qr, ql, thres, NULL, &exz); + // ed_band_cal_extension_infi_1_w_trace(tr, t_end+1-r_ts, qr, ql, thres, NULL, &exz); + // cigar_check(tr, qr, &exz); + // exz.err = INT32_MAX; + // ed_band_cal_extension_infi_1_w_trace(tr, t_end+1-r_ts, qr, ql, thres, NULL, &exz); + // cigar_check(tr, qr, &exz); + // assert(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); + + // ed_band_cal_extension_256_1_w(tr, t_end+1-r_ts, qr, ql, thres, &exz); + // ed_band_cal_extension_256_1_w_trace(tr, t_end+1-r_ts, qr, ql, thres, &exz); + // cigar_check(tr, qr, &exz); + // exz.err = INT32_MAX; + // ed_band_cal_extension_256_1_w_trace(tr, t_end+1-r_ts, qr, ql, thres, &exz); + // cigar_check(tr, qr, &exz); + // assert(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); + + // free(qr); free(tr); + + + // ed_band_cal_global_64_w(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz64); + // ed_band_cal_global_64_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz64); + // cigar_check(t_string+r_ts, q_string, &(exz64)); + // exz64.err = INT32_MAX; + // ed_band_cal_global_64_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz64); + // cigar_check(t_string+r_ts, q_string, &(exz64)); + + // ed_band_cal_global_infi_w(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, NULL, &exz); + // ed_band_cal_global_infi_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, NULL, &exz); + // cigar_check(t_string+r_ts, q_string, &exz); + // exz.err = INT32_MAX; + // ed_band_cal_global_infi_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, NULL, &exz); + // cigar_check(t_string+r_ts, q_string, &exz); + // assert(exz.err <= (int32_t)error && exz.err >= 0); + // assert(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); + + // ed_band_cal_global_256_w(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz); + // ed_band_cal_global_256_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz); + // cigar_check(t_string+r_ts, q_string, &exz); + // exz.err = INT32_MAX; + // ed_band_cal_global_256_w_trace(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz); + // cigar_check(t_string+r_ts, q_string, &exz); + // assert(exz.err <= (int32_t)error && exz.err >= 0); + // assert(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); + + + // ed_band_cal_semi_64_w(t_string, aln_l, q_string, ql, thres, &exz64); + // ed_band_cal_semi_64_w_trace(t_string, aln_l, q_string, ql, thres, &exz64); + // cigar_check(t_string, q_string, &(exz64)); + // exz64.err = INT32_MAX; + // ed_band_cal_semi_64_w_trace(t_string, aln_l, q_string, ql, thres, &exz64); + // cigar_check(t_string, q_string, &(exz64)); + + // ed_band_cal_semi_infi_w(t_string, aln_l, q_string, ql, thres, NULL, &exz); + // ed_band_cal_semi_infi_w_trace(t_string, aln_l, q_string, ql, thres, NULL, &exz); + // cigar_check(t_string, q_string, &exz); + // exz.err = INT32_MAX; + // ed_band_cal_semi_infi_w_trace(t_string, aln_l, q_string, ql, thres, NULL, &exz); + // cigar_check(t_string, q_string, &exz); + // assert(exz.err <= (int32_t)error && exz.err >= 0); + // assert(exz.err == exz64.err && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); + + // ed_band_cal_semi_256_w(t_string, aln_l, q_string, ql, thres, &exz); + // ed_band_cal_semi_256_w_trace(t_string, aln_l, q_string, ql, thres, &exz); + // cigar_check(t_string, q_string, &exz); + // exz.err = INT32_MAX; + // ed_band_cal_semi_256_w_trace(t_string, aln_l, q_string, ql, thres, &exz); + // cigar_check(t_string, q_string, &exz); + // assert(exz.err <= (int32_t)error && exz.err >= 0); + // assert(exz.err == exz64.err && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); + + + + ed_band_cal_semi_64_w_absent_diag(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, + thres, aux_beg, &exz64); + // ed_band_cal_semi_64_w_absent_diag_trace(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, + // thres, aux_beg, &exz64); + // cigar_check(t_string+aux_beg, q_string, &(exz64)); + // exz64.err = INT32_MAX; + // ed_band_cal_semi_64_w_absent_diag_trace(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, + // thres, aux_beg, &exz64); + // cigar_check(t_string+aux_beg, q_string, &(exz64)); + + + + ed_band_cal_semi_infi_w_absent_diag(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, + thres, aux_beg, NULL, &exz); + ed_band_cal_semi_infi_w_absent_diag_trace(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, + thres, aux_beg, NULL, &exz); + cigar_check(t_string+aux_beg, q_string, &(exz)); + exz.err = INT32_MAX; + ed_band_cal_semi_infi_w_absent_diag_trace(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, + thres, aux_beg, NULL, &exz); + cigar_check(t_string+aux_beg, q_string, &(exz)); + assert(exz.err <= (int32_t)error && exz.err >= 0); + assert(exz.err == exz64.err && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); + exz64.err = exz.err; exz64.ps = exz.ps; exz64.pe = exz.pe; exz64.ts = exz.ts; exz64.te = exz.te; + + + ed_band_cal_semi_256_w_absent_diag(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, + thres, aux_beg, &exz); + ed_band_cal_semi_256_w_absent_diag_trace(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, + thres, aux_beg, &exz); + cigar_check(t_string+aux_beg, q_string, &(exz)); + exz.err = INT32_MAX; + ed_band_cal_semi_256_w_absent_diag_trace(t_string+aux_beg, aln_l-aux_beg-aux_end, q_string, ql, + thres, aux_beg, &exz); + cigar_check(t_string+aux_beg, q_string, &(exz)); + assert(exz.err <= (int32_t)error && exz.err >= 0); + assert(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te); + // if((!(exz.err == exz64.err && exz.ps == exz64.ps && exz.pe == exz64.pe && exz.ts == exz64.ts && exz.te == exz64.te)) || (exz.err != (int32_t)error)) { + // fprintf(stderr, "\n[M::%s::semi] error::%u, ql::%ld, thres::%ld, exz.err::%d, exz64.err::%d, exz.ps::%d, exz64.ps::%d, exz.pe::%d, exz64.pe::%d, exz.ts::%d, exz64.ts::%d, exz.te::%d, exz64.te::%d\n", __func__, + // error, ql, thres, exz.err, exz64.err, exz.ps, exz64.ps, exz.pe, exz64.pe, exz.ts, exz64.ts, exz.te, exz64.te); + // fprintf(stderr, "[tstr] %.*s\n", (int32_t)aln_l, t_string); + // fprintf(stderr, "[qstr] %.*s\n", (int32_t)ql, q_string); + // } + destroy_bit_extz_t(&exz); destroy_bit_extz_t(&exz64); + + // if(exz.err > (int32_t)error && ql == 1) { + // fprintf(stderr, "[M::%s::] error::%u, ed_extension::%d, ql::%ld, thres::%ld\n", + // __func__, error, exz.err, ql, thres); + // fprintf(stderr, "[tstr] %.*s\n", t_end+1-r_ts, t_string+r_ts); + // fprintf(stderr, "[qstr] %.*s\n", (int32_t)ql, q_string); + // } + + // assert(ed_band_cal_global(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres) == + // ed_band_cal_global_128bit(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres)); + **/ + + ///this condition is always wrong + ///in best case, r_ts = threshold, t_end = aln_l - thres - 1 + if (((t_end+1) == aln_l) || (r_ts == 0)) { + if(recal_boundary(q_string, tstr1, ql, thres, ts, r_ts, t_end, + aux_beg, aux_end, error, id, aln_l, rev, dumy, rref, hpc_g, uref, + &ts, &r_ts, &t_end, &aux_beg, &aux_end, &error)) { + p->error = error; p->extra_begin = aux_beg; p->extra_end = aux_end; + t_string = update_des_str(tstr, ts, aln_l-aux_beg-aux_end, rev, rref, hpc_g, uref, + id, aux_beg, aux_end, hpc_g?NULL:tstr1); + } + } + + generate_cigar(dumy->path, dumy->path_length, p, &(z->w_list), &r_ts, &t_end, &error, q_string, ql, t_string); + + p->y_start = ts + r_ts - aux_beg; + p->y_end = ts + t_end - aux_beg; + p->error = error; + return 1; + } + p->error = -1; + return 0; +} + +inline uint32_t aln_wlst_adv(overlap_region *z, All_reads *rref, hpc_t *hpc_g, +const ul_idx_t *uref, char *qstr, char *tstr, char *tstr1, Correct_dumy* dumy, +uint32_t rev, uint32_t id, int64_t qs, int64_t qe, int64_t t_s, int64_t block_s, +double e_rate, uint32_t is_cigar) +{ + int64_t ql, aln_l, t_tot_l; window_list *p = NULL; int r_ts = 0, t_end; + int64_t aux_beg, aux_end, t_pri_l; + int64_t thres; char *q_string, *t_string; unsigned int error; + ql = qe + 1 - qs; + ///there are two potiential reasons for unmatched window: + ///1. this window has a large number of differences + ///2. DP does not start from the right offset + if(rref) { + thres = double_error_threshold(get_init_err_thres(ql, e_rate, block_s, THRESHOLD), ql); + } else { + thres = double_ul_error_threshold(get_init_err_thres(ql, e_rate, block_s, THRESHOLD_MAX_SIZE), ql); + } + aln_l = ql + (thres << 1); + if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); + else if(uref) t_tot_l = uref->ug->u.a[id].len; + else t_tot_l = Get_READ_LENGTH((*rref), id); + + if(!init_waln(thres, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) return 0; + if(t_pri_l + thres < ql) return 0; + + q_string = qstr + qs; + if(rref) { + fill_subregion(tstr, t_s, t_pri_l, rev, rref, id, aux_beg, aux_end); t_string = tstr; + } else { + t_string = return_str_seq(tstr, t_s, t_pri_l, rev, hpc_g, uref, id, aux_beg, aux_end); + } + + if(is_cigar) { + ///note!!! need notification + t_end = Reserve_Banded_BPM_PATH(t_string, aln_l, q_string, ql, thres, &error, &r_ts, + &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); + } else { + ///note!!! need notification + t_end = Reserve_Banded_BPM(t_string, aln_l, q_string, ql, thres, &error); + } + if(error!=(unsigned int)-1) { + if(is_cigar) { + ///this condition is always wrong + ///in best case, r_ts = threshold, t_end = aln_l - thres - 1 + if (((t_end+1) == aln_l) || (r_ts == 0)) { + if(recal_boundary(q_string, tstr1, ql, thres, t_s, r_ts, t_end, + aux_beg, aux_end, error, id, aln_l, rev, dumy, rref, hpc_g, uref, + &t_s, &r_ts, &t_end, &aux_beg, &aux_end, &error)) { + t_string = update_des_str(tstr, t_s, aln_l-aux_beg-aux_end, rev, rref, hpc_g, uref, + id, aux_beg, aux_end, hpc_g?NULL:tstr1); + } + } + } + + kv_pushp(window_list, z->w_list, &p); + p->x_start = qs; p->x_end = qe; ///must set x_start/x_end here + if(is_cigar) { + generate_cigar(dumy->path, dumy->path_length, p, &(z->w_list), &r_ts, &t_end, &error, q_string, ql, t_string); + } else { + p->cidx = p->clen = 0; + } + p->y_start = t_s + r_ts;///difference + p->y_end = t_s + t_end; + p->error = error; + p->extra_begin = aux_beg; + p->extra_end = aux_end; + p->error_threshold = thres; + z->align_length += ql; + + return 1; + } + return 0; +} + +void push_wcigar(window_list *idx, window_list_alloc *res, bit_extz_t *exz) +{ + idx->cidx = res->c.n; idx->clen = exz->cigar.n; res->c.n += exz->cigar.n; + kv_resize(uint16_t, res->c, res->c.n); + memcpy(res->c.a+idx->cidx, exz->cigar.a, exz->cigar.n*sizeof(*(res->c.a))); +} + +inline uint32_t aln_wlst_adv_exz(overlap_region *z, All_reads *rref, hpc_t *hpc_g, +const ul_idx_t *uref, char *qstr, char *tstr, bit_extz_t *exz, uint32_t max_err, +uint32_t rev, uint32_t id, int64_t qs, int64_t qe, int64_t t_s, int64_t block_s, +double e_rate, uint32_t is_cigar) +{ + int64_t ql, tl, aln_l, t_tot_l; window_list *p = NULL; ///int r_ts = 0, t_end; + int64_t aux_beg, aux_end, t_pri_l; int64_t thres; char *q_string, *t_string; + ql = qe + 1 - qs; + ///there are two potiential reasons for unmatched window: + ///1. this window has a large number of differences + ///2. DP does not start from the right offset + if(rref) { + thres = double_error_threshold(get_init_err_thres(ql, e_rate, block_s, max_err), ql); + } else { + thres = double_ul_error_threshold(get_init_err_thres(ql, e_rate, block_s, max_err), ql); + } + aln_l = ql + (thres << 1); + if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); + else if(uref) t_tot_l = uref->ug->u.a[id].len; + else t_tot_l = Get_READ_LENGTH((*rref), id); + + if(!init_waln(thres, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) return 0; + if(t_pri_l + thres < ql) return 0; + + q_string = qstr + qs; + if(rref) { + recover_UC_Read_sub_region(tstr, t_s, t_pri_l, rev, rref, id); t_string = tstr; + } else { + t_string = return_str_seq_exz(tstr, t_s, t_pri_l, rev, hpc_g, uref, id); + } + tl = t_pri_l; + if(is_cigar) { + clear_align(*exz); + ed_band_cal_semi_64_w_absent_diag_trace(t_string, tl, q_string, ql, thres, aux_beg, exz); + } else { + ed_band_cal_semi_64_w_absent_diag(t_string, tl, q_string, ql, thres, aux_beg, exz); exz->ps = 0; + } + + // if(id == 40 && qs == 79670 && qe == 79824) { + // fprintf(stderr, "\n[M::%s::semi] exz->ps::%d, exz->pe::%d, exz->ts::%d, exz->te::%d, exz->err::%d, exz->cigar.n::%d\n", + // __func__, exz->ps, exz->pe, exz->ts, exz->te, exz->err, (int32_t)exz->cigar.n); + // } + + if(is_align(*exz)) { + kv_pushp(window_list, z->w_list, &p); + p->x_start = qs; p->x_end = qe; ///must set x_start/x_end here + p->y_start = t_s + exz->ps;///difference + p->y_end = t_s + exz->pe; + p->error = exz->err; + p->cidx = p->clen = 0; + if(is_cigar) { + push_wcigar(p, &(z->w_list), exz); + ///this condition is always wrong + ///in best case, r_ts = threshold, t_end = aln_l - thres - 1 + if ((((exz->pe+1) == tl) || (exz->ps == 0)) && (exz->err > 0)) { + if(recal_boundary_exz(q_string, tstr, ql, tl, thres, t_s, exz->ps, exz->pe, + exz->err, id, rev, exz, rref, hpc_g, uref, &t_s, &aux_beg, &aux_end)) { + //update cigar + z->w_list.c.n = p->cidx; push_wcigar(p, &(z->w_list), exz); + + p->y_start = t_s + exz->ps;///difference + p->y_end = t_s + exz->pe; + p->error = exz->err; + } + } + } + + p->extra_begin = aux_beg; + p->extra_end = aux_end; + p->error_threshold = thres; + z->align_length += ql; + return 1; + } + return 0; +} + +inline uint32_t aln_wlst_adv_non_retrieve_exz(overlap_region *z, char *qstr, char *tstr, int64_t t_tot_l, bit_extz_t *exz, uint32_t max_err, +uint32_t rev, uint32_t id, int64_t qs, int64_t qe, int64_t t_s, int64_t block_s, double e_rate, uint32_t is_cigar) +{ + int64_t ql, tl, aln_l; window_list *p = NULL; ///int r_ts = 0, t_end; + int64_t aux_beg, aux_end, t_pri_l; int64_t thres; char *q_string, *t_string; + ql = qe + 1 - qs; + ///there are two potiential reasons for unmatched window: + ///1. this window has a large number of differences + ///2. DP does not start from the right offset + thres = double_error_threshold(get_init_err_thres(ql, e_rate, block_s, max_err), ql); + + aln_l = ql + (thres << 1); + + if(!init_waln(thres, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) return 0; + if(t_pri_l + thres < ql) return 0; + + q_string = qstr + qs; t_string = tstr + t_s; + + tl = t_pri_l; + if(is_cigar) { + clear_align(*exz); + ed_band_cal_semi_64_w_absent_diag_trace(t_string, tl, q_string, ql, thres, aux_beg, exz); + } else { + ed_band_cal_semi_64_w_absent_diag(t_string, tl, q_string, ql, thres, aux_beg, exz); exz->ps = 0; + } + + // if(id == 40 && qs == 79670 && qe == 79824) { + // fprintf(stderr, "\n[M::%s::semi] exz->ps::%d, exz->pe::%d, exz->ts::%d, exz->te::%d, exz->err::%d, exz->cigar.n::%d\n", + // __func__, exz->ps, exz->pe, exz->ts, exz->te, exz->err, (int32_t)exz->cigar.n); + // } + + if(is_align(*exz)) { + kv_pushp(window_list, z->w_list, &p); + p->x_start = qs; p->x_end = qe; ///must set x_start/x_end here + p->y_start = t_s + exz->ps;///difference + p->y_end = t_s + exz->pe; + p->error = exz->err; + p->cidx = p->clen = 0; + if(is_cigar) { + push_wcigar(p, &(z->w_list), exz); + ///this condition is always wrong + ///in best case, r_ts = threshold, t_end = aln_l - thres - 1 + if ((((exz->pe+1) == tl) || (exz->ps == 0)) && (exz->err > 0)) { + if(recal_boundary_non_retrieve_exz(q_string, tstr, t_tot_l, ql, tl, thres, t_s, exz->ps, exz->pe, + exz->err, id, rev, exz, &t_s, &aux_beg, &aux_end)) { + //update cigar + z->w_list.c.n = p->cidx; push_wcigar(p, &(z->w_list), exz); + + p->y_start = t_s + exz->ps;///difference + p->y_end = t_s + exz->pe; + p->error = exz->err; + } + } + } + + p->extra_begin = aux_beg; + p->extra_end = aux_end; + p->error_threshold = thres; + z->align_length += ql; + return 1; + } + return 0; +} + +inline uint32_t aln_wlst(overlap_region *z, All_reads *rref, const ul_idx_t *uref, UC_Read* g_read, Correct_dumy* dumy, +int32_t y_strand, int32_t y_id, int64_t x_start, int64_t x_end, long long y_start, int64_t block_s, double e_rate, int32_t is_cigar) +{ + int64_t x_len, Window_Len; window_list *p = NULL; long long o_len; + int32_t threshold; int real_y_start = 0, end_site, extra_begin, extra_end; + char *x_string, *y_string; unsigned int error; + x_len = x_end + 1 - x_start; + ///there are two potiential reasons for unmatched window: + ///1. this window has a large number of differences + ///2. DP does not start from the right offset + if(rref) { + threshold = double_error_threshold(get_init_err_thres(x_len, e_rate, block_s, THRESHOLD), x_len); + } else { + threshold = double_ul_error_threshold(get_init_err_thres(x_len, e_rate, block_s, THRESHOLD_MAX_SIZE), x_len); + } + Window_Len = x_len + (threshold << 1); + ///y_start might be less than 0 + if(!determine_overlap_region(threshold, y_start, y_id, Window_Len, (rref?(Get_READ_LENGTH((*rref), y_id)):(uref->ug->u.a[y_id].len)), + &extra_begin, &extra_end, &y_start, &o_len)) { + return 0; + } + + if(o_len + threshold < x_len) return 0; + if(rref) { + fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, rref, y_id, extra_begin, extra_end); + } else { + fill_subregion_ul(dumy->overlap_region, y_start, o_len, y_strand, uref, y_id, extra_begin, extra_end); + } + x_string = g_read->seq + x_start; + y_string = dumy->overlap_region; + + if(is_cigar) { + ///note!!! need notification + end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, + &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); + } else { + ///note!!! need notification + end_site = Reserve_Banded_BPM(y_string, Window_Len, x_string, x_len, threshold, &error); + } + if(error!=(unsigned int)-1) { + if(is_cigar) { + ///this condition is always wrong + ///in best case, real_y_start = threshold, end_site = Window_Len - threshold - 1 + if (end_site == Window_Len - 1 || real_y_start == 0) { + if(rref) { + fix_boundary(x_string, x_len, threshold, y_start, real_y_start, + end_site, extra_begin, extra_end, y_id, Window_Len, rref, dumy, + y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, + &extra_end, &error); + } else { + fix_ul_boundary(x_string, x_len, threshold, y_start, real_y_start, + end_site, extra_begin, extra_end, y_id, Window_Len, uref, dumy, + y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, + &extra_end, &error); + } + } + } + + kv_pushp(window_list, z->w_list, &p); + p->x_start = x_start; p->x_end = x_end; ///must set x_start/x_end here + if(is_cigar) { + generate_cigar(dumy->path, dumy->path_length, p, &(z->w_list), &real_y_start, &end_site, &error, x_string, x_len, y_string); + } else { + p->cidx = p->clen = 0; + } + p->y_start = y_start + real_y_start;///difference + p->y_end = y_start + end_site; + p->error = error; + p->extra_begin = extra_begin; + p->extra_end = extra_end; + p->error_threshold = threshold; + z->align_length += x_len; + + return 1; + } + return 0; +} +uint64_t realign_ed(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, +char *tstr, char *tstr_1, Correct_dumy* dumy, kvec_t_u64_warp* v_idx, int64_t block_s, double e_rate, +double *e_rate_final, uint32_t sec_check, int64_t *is_sort); +inline void refine_ed_aln(overlap_region_alloc* overlap_list, All_reads *rref, const ul_idx_t *uref, + UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, kvec_t_u64_warp* v_idx, int64_t block_s, double e_rate, double e_rate_final) +{ + int64_t j, k, i, on, y_id, y_readLen, x_start, x_end, x_len, total_y_start, total_y_end; + int32_t y_strand, real_y_start; + int64_t nw, a_nw, w_id, w_s, w_e, is_srt, mm_we, mm_ws, mm_aln, ovl; + double error_rate; uint64_t *w_idx; overlap_region *z; window_list *p = NULL; + + overlap_list->mapped_overlaps_length = 0; on = overlap_list->length; + for (j = 0; j < on; ++j) { + // z = &(overlap_list->list[j]); ovl = z->x_pos_e+1-z->x_pos_s; + // if(!realign_ed(z, uref, NULL, rref, g_read->seq, + // dumy->overlap_region, dumy->overlap_region_fix, dumy, v_idx, block_s, e_rate, NULL, 1, &is_srt)) { + // continue; + // } + z = &(overlap_list->list[j]); z->is_match = 0; is_srt = 1; + if(z->w_list.n == 0) continue;///no alignment + nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); a_nw = z->w_list.n; + kv_resize(uint64_t, v_idx->a, (uint64_t)nw); + memset(v_idx->a.a, -1, sizeof((*v_idx->a.a))*nw); w_idx = v_idx->a.a; + for (i = 0; i < a_nw; i++) { ///w_idx[] == (uint64_t) if unmatched + assert(z->w_list.a[i].y_end != -1); + w_id = get_win_id_by_s(z, z->w_list.a[i].x_start, block_s, NULL); + w_idx[w_id] = i; + } + + y_id = z->y_id; y_strand = z->y_pos_strand; + ovl = z->x_pos_e+1-z->x_pos_s; mm_we = z->x_pos_s; mm_aln = 0; + y_readLen = (rref?(Get_READ_LENGTH((*rref), y_id)):(uref->ug->u.a[y_id].len)); + for (i = a_nw-1; i >= 0; i--) { //utilize the the end pos of pre-window in forward + w_id = get_win_id_by_s(z, z->w_list.a[i].x_start, block_s, &w_e); + assert(z->w_list.a[i].x_end == w_e); + if(w_e > mm_we) mm_we = w_e; + ///in most cases, extra_begin = 0 + total_y_start = z->w_list.a[i].y_end + 1 - z->w_list.a[i].extra_begin; + for (k = w_id + 1; k < nw && total_y_start < y_readLen; k++) { + if(w_idx[k] != (uint64_t)-1) break; + w_s = w_e + 1; + w_id = get_win_id_by_s(z, w_s, block_s, &w_e); + assert(w_id == k); + x_start = w_s; x_end = w_e; + if(aln_wlst(z, rref, uref, g_read, dumy, y_strand, y_id, x_start, x_end, + total_y_start, block_s, e_rate, 0)) { + p = &(z->w_list.a[z->w_list.n-1]); + w_idx[k] = z->w_list.n - 1; + if(x_end > mm_we) mm_we = x_end; + if(is_srt && z->w_list.n > 1 && p->x_start < z->w_list.a[z->w_list.n-2].x_start) is_srt = 0; + } else { + break; + } + total_y_start = p->y_end + 1 - p->extra_begin; + } + } + mm_ws = z->x_pos_s; mm_aln = mm_we+1-mm_ws; + if(!simi_pass(ovl, mm_aln, uref?1:0, OVERLAP_THRESHOLD_NOSI_FILTER, NULL)) continue; + if(nw > 0 && w_idx[0] != (uint64_t)-1) mm_ws = z->w_list.a[w_idx[0]].x_end+1; + + for (i = 1; i < nw; i++) { //utilize the the start pos of next window in backward + ///find the first matched window, which should not be the first window + ///the pre-window of this matched window must be unmatched + if(w_idx[i] != (uint64_t)-1 && w_idx[i-1] == (uint64_t)-1) { + w_s = z->w_list.a[w_idx[i]].x_start; mm_aln -= (w_s-mm_ws); + ///check if the start pos of this matched window has been calculated + if(z->w_list.a[w_idx[i]].clen == 0) { + p = &(z->w_list.a[w_idx[i]]); + gen_backtrace(p, z, rref, uref, g_read, dumy, y_strand, y_id); + assert(p->error != -1); + p->y_end += p->extra_begin; + } + real_y_start = p->y_start; + + ///the end pos for pre window is real_y_start - 1 + total_y_end = real_y_start - 1; + ///find the unmatched window on the left of current matched window + ///k starts from i - 1 + for (k = i - 1; k >= 0 && w_idx[k] == (uint64_t)-1 && total_y_end > 0; k--) { + w_e = w_s - 1; + w_id = get_win_id_by_e(z, w_e, block_s, &w_s); + assert(w_id == k); + x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; + if(aln_wlst(z, rref, uref, g_read, dumy, y_strand, y_id, x_start, x_end, total_y_end+1-x_len, block_s, e_rate, 1)) { + p = &(z->w_list.a[z->w_list.n-1]); + p->y_start -= p->extra_begin; ///y_start has no shift, but y_end has shift + w_idx[k] = z->w_list.n - 1; + mm_aln += x_len; + if(is_srt && z->w_list.n > 1 && p->x_start < z->w_list.a[z->w_list.n-2].x_start) is_srt = 0; + } else { + break; + } + total_y_end = p->y_start - 1; + } + if(!simi_pass(ovl, mm_aln, uref?1:0, OVERLAP_THRESHOLD_NOSI_FILTER, NULL)) break; + } + if(w_idx[i] != (uint64_t)-1) mm_ws = z->w_list.a[w_idx[i]].x_end+1; + } + + if(i < nw) continue; + if(uref && simi_pass(ovl, z->align_length, uref?1:0, OVERLAP_THRESHOLD_NOSI_FILTER, NULL)) { + z->is_match = 3; overlap_list->mapped_overlaps_length += z->align_length; + ///sort for set_herror_win + if(!is_srt) radix_sort_window_list_xs_srt(z->w_list.a, z->w_list.a + z->w_list.n); + } + } + + if(uref && overlap_list->mapped_overlaps_length > 0) { + set_herror_win(overlap_list, dumy, v_idx, e_rate, g_read->length, block_s); + } + + overlap_list->mapped_overlaps_length = 0; + for (j = 0; j < (long long)overlap_list->length; j++) { + z = &(overlap_list->list[j]); + y_id = z->y_id; y_strand = z->y_pos_strand; + y_readLen = (rref?(Get_READ_LENGTH((*rref), y_id)):(uref->ug->u.a[y_id].len)); + ovl = z->x_pos_e + 1 - z->x_pos_s; //z->is_match = 0; + // if(y_id == 4) { + // fprintf(stderr, "[M::%s::idx->%ld::] z::x_pos_s->%u, z::x_pos_e->%u, ovl->%ld, aln->%u\n", + // __func__, j, z->x_pos_s, z->x_pos_e, ovl, z->align_length); + // } + ///debug_scan_cigar(&(overlap_list->list[j])); + ///only calculate cigar for high quality overlaps + // int64_t tt = 0; + if(simi_pass(ovl, z->align_length, 0, OVERLAP_THRESHOLD_NOSI_FILTER, &e_rate)) { + a_nw = z->w_list.n; + for (i = 0, is_srt = 1; i < a_nw; i++) { + p = &(z->w_list.a[i]); + ///check if the cigar of this window has been got + if(p->clen == 0) { + gen_backtrace(p, z, rref, uref, g_read, dumy, y_strand, y_id); + assert(p->error != -1); + // if(y_id == 4) { + // fprintf(stderr, "+[M::idx->%ld::] y_start->%d, y_end->%d, error->%d\n", + // j, p->y_start, p->y_end, p->error); + // } + } + else { + p->y_end -= p->extra_begin; + // if(y_id == 4) { + // fprintf(stderr, "-[M::idx->%ld::] y_start->%d, y_end->%d, error->%d\n", + // j, p->y_start, p->y_end, p->error); + // } + } + // tt += p->error; + if(is_srt && i > 0 && p->x_start < z->w_list.a[i-1].x_start) is_srt = 0; + } + if(!is_srt) radix_sort_window_list_xs_srt(z->w_list.a, z->w_list.a + z->w_list.n); + error_rate = non_trim_error_rate(z, rref, uref, v_idx, dumy, g_read, e_rate, block_s); + z->is_match = 0;///must be here; + // if(y_id == 4) { + // fprintf(stderr, "[M::%s::idx->%ld::] block_s->%ld, z::x_pos_s->%u, z::x_pos_e->%u, ovl->%ld, aln->%u, error_rate->%f, e_rate_final->%f\n", + // __func__, j, block_s, z->x_pos_s, z->x_pos_e, ovl, z->align_length, error_rate, e_rate_final); + // exit(1); + // } + if (error_rate <= e_rate_final) { + overlap_list->mapped_overlaps_length += ovl; + z->is_match = 1; append_unmatched_wins(z, block_s); + if(rref) { + calculate_boundary_cigars(z, rref, dumy, g_read, e_rate); + } else { + calculate_ul_boundary_cigars(z, uref, dumy, g_read, e_rate, block_s); + } + // assert(get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s)==(int64_t)z->w_list.n); + // assert((int64_t)z->x_pos_s==z->w_list.a[0].x_start && + // (int64_t)z->x_pos_e==z->w_list.a[z->w_list.n-1].x_end); + } else if (error_rate <= e_rate_final * 1.5) { + z->is_match = 3; + } + } else {///it impossible to be matched + z->is_match = 0; + // fprintf(stderr, "[M::%s::idx->%ld::is_match->%u] z::x_pos_s->%u, z::x_pos_e->%u, error_rate->-1, e_threshold->%f\n", + // __func__, j, z->is_match, z->x_pos_s, z->x_pos_e, e_rate); + } + } +} + + +uint32_t align_ul_ed_post(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, char* qstr, char *tstr, char *tstr_1, +Correct_dumy* dumy, double e_rate, int64_t w_l, double ovlp_cut, void *km); +double gen_extend_err(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, +char *tstr, char *tstr_1, Correct_dumy* dumy, uint64_t *v_idx, int64_t block_s, double ovlp_cut, double e_rate, double e_max, int64_t *r_e); +inline void refine_ed_aln_test(overlap_region_alloc* overlap_list, All_reads *rref, const ul_idx_t *uref, + UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, kvec_t_u64_warp* v_idx, int64_t block_s, double e_rate, double e_rate_final) +{ + int64_t j, on, ovl; uint64_t k; double rr; overlap_region *z; + + overlap_list->mapped_overlaps_length = 0; on = overlap_list->length; + for (j = 0; j < on; ++j) { + z = &(overlap_list->list[j]); ovl = z->x_pos_e+1-z->x_pos_s; + if(!align_ul_ed_post(z, uref, NULL, g_read->seq, dumy->overlap_region, dumy->overlap_region_fix, + dumy, e_rate, block_s, OVERLAP_THRESHOLD_NOSI_FILTER, NULL)) { + continue; + } + if(uref && simi_pass(ovl, z->align_length, uref?1:0, OVERLAP_THRESHOLD_NOSI_FILTER, NULL)) { + z->is_match = 3; overlap_list->mapped_overlaps_length += z->align_length; + } + } + + if(uref && overlap_list->mapped_overlaps_length > 0) { + set_herror_win(overlap_list, dumy, v_idx, e_rate, g_read->length, block_s); + } + + double e_max = e_rate_final * 1.5; + overlap_list->mapped_overlaps_length = 0; on = overlap_list->length; + for (j = 0; j < on; j++) { + z = &(overlap_list->list[j]); ovl = z->x_pos_e + 1 - z->x_pos_s; + rr = gen_extend_err(z, uref, NULL, rref, g_read->seq, dumy->overlap_region, dumy->overlap_region_fix, + dumy, v_idx?v_idx->a.a:NULL, block_s, -1, e_rate, (e_max+0.000001), NULL); + z->is_match = 0;///must be here; + if (rr <= e_rate_final) { + for (k = 0; k < z->w_list.n; k++) { + if(z->w_list.a[k].clen) continue; + gen_backtrace_adv(&(z->w_list.a[k]), z, rref, NULL, uref, g_read->seq, dumy->overlap_region, dumy->overlap_region_fix, + dumy, z->y_pos_strand, z->y_id); + } + + overlap_list->mapped_overlaps_length += ovl; + z->is_match = 1; append_unmatched_wins(z, block_s); + if(rref) { + calculate_boundary_cigars(z, rref, dumy, g_read, e_rate); + } else { + calculate_ul_boundary_cigars(z, uref, dumy, g_read, e_rate, block_s); + } + } else if (rr <= e_max) { + z->is_match = 3; + } + } +} + + + +inline void add_base_to_correct_read_directly(Correct_dumy* dumy, char base) +{ + + if (dumy->corrected_read_length + 2 > dumy->corrected_read_size) + { + dumy->corrected_read_size = dumy->corrected_read_size * 2; + dumy->corrected_read = (char*)realloc(dumy->corrected_read, dumy->corrected_read_size); + } + + dumy->corrected_read[dumy->corrected_read_length] = base; + dumy->corrected_read_length++; + dumy->corrected_read[dumy->corrected_read_length] = '\0'; + +} + +inline void add_base_to_correct_read(Correct_dumy* dumy, char base, int is_error) +{ + ///don't need to deal with deletion + if (base != 'D') + { + if (dumy->corrected_read_length + 2 > dumy->corrected_read_size) + { + dumy->corrected_read_size = dumy->corrected_read_size * 2; + dumy->corrected_read = (char*)realloc(dumy->corrected_read, dumy->corrected_read_size); + } + + dumy->corrected_read[dumy->corrected_read_length] = base; + dumy->corrected_read_length++; + dumy->corrected_read[dumy->corrected_read_length] = '\0'; + } + + if (is_error) + { + dumy->corrected_base++; + } + +} + + +inline void add_segment_to_correct_read(Correct_dumy* dumy, char* segment, long long segment_length) +{ + + if (dumy->corrected_read_length + segment_length + 2 > dumy->corrected_read_size) + { + dumy->corrected_read_size = dumy->corrected_read_length + segment_length + 2; + dumy->corrected_read = (char*)realloc(dumy->corrected_read, dumy->corrected_read_size); + } + + memcpy(dumy->corrected_read + dumy->corrected_read_length, segment, segment_length); + dumy->corrected_read_length += segment_length; + dumy->corrected_read[dumy->corrected_read_length] = '\0'; +} + + + + +///return the ID of next node at backbone +long long inline add_path_to_correct_read(Graph* backbone, Correct_dumy* dumy, long long currentNodeID, +long long type, long long edgeID, Cigar_record* current_cigar, char* self_string) +{ + //long long i; + long long nodeID; + + ///Note: currentNodeID must be a backbone node + ///currentNodeID = 0 means a fake node + ///currentNodeID = i means self_string[i - 1] + ///include match/mismatch + if (type == MISMATCH) + { + ///match + if(backbone->g_nodes.list[currentNodeID].mismatch_edges.list[edgeID].length == 0) + { + nodeID = backbone->g_nodes.list[currentNodeID].mismatch_edges.list[edgeID].out_node; + add_base_to_correct_read_directly(dumy, backbone->g_nodes.list[nodeID].base); + ///nodeID = i means self_string[i - 1] + ///add_cigar_record(self_string+nodeID-1, 1, current_cigar, 0); + add_cigar_record(&(backbone->g_nodes.list[nodeID].base), 1, current_cigar, 0); + return nodeID; + } + else ///mismatch + { + nodeID = backbone->g_nodes.list[currentNodeID].mismatch_edges.list[edgeID].out_node; + add_base_to_correct_read_directly(dumy, backbone->g_nodes.list[nodeID].base); + dumy->corrected_base++; + char merge_base = 0; + merge_base = seq_nt6_table[(uint8_t)backbone->g_nodes.list[nodeID].base]; + merge_base = merge_base << 3; + nodeID = backbone->g_nodes.list[nodeID].mismatch_edges.list[0].out_node; + merge_base = merge_base | seq_nt6_table[(uint8_t)backbone->g_nodes.list[nodeID].base]; + add_cigar_record(&merge_base, 1, current_cigar, 1); + return nodeID; + } + } + else if (type == DELETION) + { + nodeID = backbone->g_nodes.list[currentNodeID].deletion_edges.list[edgeID].out_node; + dumy->corrected_base += nodeID - currentNodeID; + add_cigar_record(self_string + currentNodeID, nodeID - currentNodeID, current_cigar, DELETION); + return nodeID; + } + else if (type == INSERTION) + { + ///pay attention to this line + backbone->g_nodes.list[currentNodeID].num_insertions = 0; + + nodeID = backbone->g_nodes.list[currentNodeID].insertion_edges.list[edgeID].out_node; + long long step = backbone->g_nodes.list[currentNodeID].insertion_edges.list[edgeID].length; + long long i; + for (i = 0; i < step; i++) + { + add_base_to_correct_read_directly(dumy, backbone->g_nodes.list[nodeID].base); + add_cigar_record(&backbone->g_nodes.list[nodeID].base, 1, current_cigar, INSERTION); + nodeID = backbone->g_nodes.list[nodeID].insertion_edges.list[0].out_node; + } + dumy->corrected_base += step; + return nodeID; + } + else + { + fprintf(stderr, "error type\n"); + return -1; + } +} + + +///return the ID of next node at backbone +long long inline add_path_to_correct_read_new(Graph* backbone, Graph* DAGCon, Correct_dumy* dumy, long long currentNodeID, +long long type, long long edgeID, Cigar_record* current_cigar, char* self_string) +{ + //long long i; + long long nodeID; + + ///Note: currentNodeID must be a backbone node + ///currentNodeID = 0 means a fake node + ///currentNodeID = i means self_string[i - 1] + ///include match/mismatch + if (type == MISMATCH) + { + ///match + if(backbone->g_nodes.list[currentNodeID].mismatch_edges.list[edgeID].length == 0) + { + nodeID = backbone->g_nodes.list[currentNodeID].mismatch_edges.list[edgeID].out_node; + add_base_to_correct_read_directly(dumy, backbone->g_nodes.list[nodeID].base); + ///nodeID = i means self_string[i - 1] + ///add_cigar_record(self_string+nodeID-1, 1, current_cigar, 0); + add_cigar_record(&(backbone->g_nodes.list[nodeID].base), 1, current_cigar, 0); + return nodeID; + } + else ///mismatch + { + nodeID = backbone->g_nodes.list[currentNodeID].mismatch_edges.list[edgeID].out_node; + add_base_to_correct_read_directly(dumy, backbone->g_nodes.list[nodeID].base); + dumy->corrected_base++; + char merge_base = 0; + merge_base = seq_nt6_table[(uint8_t)backbone->g_nodes.list[nodeID].base]; + merge_base = merge_base << 3; + nodeID = backbone->g_nodes.list[nodeID].mismatch_edges.list[0].out_node; + merge_base = merge_base | seq_nt6_table[(uint8_t)backbone->g_nodes.list[nodeID].base]; + add_cigar_record(&merge_base, 1, current_cigar, 1); + return nodeID; + } + } + else if (type == DELETION) + { + nodeID = backbone->g_nodes.list[currentNodeID].deletion_edges.list[edgeID].out_node; + dumy->corrected_base += nodeID - currentNodeID; + add_cigar_record(self_string + currentNodeID, nodeID - currentNodeID, current_cigar, DELETION); + return nodeID; + } + else if (type == INSERTION) + { + ///pay attention to this line + backbone->g_nodes.list[currentNodeID].num_insertions = 0; + long long str; + char str_c; + while (pop_from_Queue(&(DAGCon->node_q), &str)) + { + str_c = (char)str; + add_base_to_correct_read_directly(dumy, str_c); + add_cigar_record(&str_c, 1, current_cigar, INSERTION); + dumy->corrected_base++; + } + + return currentNodeID; + } + else + { + fprintf(stderr, "error type\n"); + } + + return -1; +} + + +void Merge_Out_Nodes(Graph* DAGCon, Node* currentNode) +{ + ///if this node does not have any output, directly return + if(Real_Length(Output_Edges((*currentNode))) == 0) + { + return; + } + + RSet buf, out_buf; + char Bases[4] = {'A', 'C', 'G', 'T'}; + char base; + long long base_i, weight; + int flag = 0; + Node* get_node_1 = NULL; + Node* out_node_of_get_node_1 = NULL; + Node* consensus_node_1 = NULL; + Edge* e_forward_1 = NULL; + Edge* e_backward_1 = NULL; + + ///merge all base for each base + for (base_i = 0; base_i < 4; base_i++) + { + base = Bases[base_i]; + + clear_RSet(&buf); + flag = 0; + weight = 0; + ///should use getOutputEdges, instead of getOutputNodes + ///check all out-nodes of currentNode + while(getOutputNodes(&buf, DAGCon, currentNode, &get_node_1)) + { + ///check the corresponding node, this node must only have one in-node + ///note this is the Real_Length, instead of the Input_Edges.length + if((*get_node_1).base == base && Real_Length(Input_Edges(*get_node_1)) == 1) + { + if(flag == 0) + { + flag = 1; + ///add a new node to merge all out-node + consensus_node_1 = get_node_1; + ///link consensus_node to currentNode + ///set the new edge to be visited + if(get_bi_Edge(DAGCon, currentNode, consensus_node_1, &e_forward_1, &e_backward_1)) + { + Visit(*e_forward_1) = 1; + Visit(*e_backward_1) = 1; + } + else + { + fprintf(stderr, "error\n"); + } + + weight = (*e_forward_1).weight; + } + else + { + flag++; + ///add the weight of get_node->currentNode + if(get_bi_Edge(DAGCon, currentNode, get_node_1, &e_forward_1, &e_backward_1)) + { + weight = weight + (*e_forward_1).weight; + } + else + { + fprintf(stderr, "error\n"); + } + + ///process the out-nodes of get_node + clear_RSet(&out_buf); + while(getOutputNodes(&out_buf, DAGCon, get_node_1, &out_node_of_get_node_1)) + { + ///link consensus_node to the out-nodes of get_node + if(get_bi_Edge(DAGCon, consensus_node_1, out_node_of_get_node_1, &e_forward_1, &e_backward_1)) + { + Visit(*e_forward_1) = 1; + Visit(*e_backward_1) = 1; + (*e_forward_1).weight += get_Edge_Weight(DAGCon, get_node_1, out_node_of_get_node_1); + (*e_backward_1).weight = (*e_forward_1).weight; + } + else + { + add_bi_direction_edge(DAGCon, consensus_node_1, out_node_of_get_node_1, + get_Edge_Weight(DAGCon, get_node_1, out_node_of_get_node_1), 1); + } + } + + delete_Node_DAGCon(DAGCon, get_node_1); + } + } + } + + if(flag > 1) + { + get_bi_Edge(DAGCon, currentNode, consensus_node_1, &e_forward_1, &e_backward_1); + (*e_forward_1).weight = weight; + (*e_backward_1).weight = (*e_forward_1).weight; + } + + if(flag > 0) + { + Merge_Out_Nodes(DAGCon, consensus_node_1); + } + } +} + + +void Merge_In_Nodes(Graph* DAGCon, Node* currentNode) +{ + ///if this node does not have any input, directly return + if(Real_Length(Input_Edges((*currentNode))) == 0) + { + return; + } + + RSet buf, in_buf; + char Bases[4] = {'A', 'C', 'G', 'T'}; + char base; + long long base_i, weight; + int flag = 0; + Node* get_node = NULL; + Node* in_node_of_get_node = NULL; + Node* consensus_node = NULL; + Edge* e_forward = NULL; + Edge* e_backward = NULL; + + ///merge all base for each base + for (base_i = 0; base_i < 4; base_i++) + { + base = Bases[base_i]; + + clear_RSet(&buf); + flag = 0; + weight = 0; + ///should use getInputEdges, instead of getInputNodes + ///check all in-nodes of currentNode + while(getInputNodes(&buf, DAGCon, currentNode, &get_node)) + { + ///check the corresponding node, this node must only have one out-node + ///note this is the Real_Length, instead of the Output_Edges.length + if((*get_node).base == base && Real_Length(Output_Edges(*get_node)) == 1) + { + if(flag == 0) + { + flag = 1; + ///add a new node to merge all in-node + consensus_node = get_node; + ///link consensus_node to currentNode + ///set the new edge to be visited + if(get_bi_Edge(DAGCon, consensus_node, currentNode, &e_forward, &e_backward)) + { + Visit(*e_forward) = 1; + Visit(*e_backward) = 1; + } + else + { + fprintf(stderr, "error\n"); + } + + weight = (*e_forward).weight; + } + else + { + flag++; + ///add the weight of get_node->currentNode + if(get_bi_Edge(DAGCon, get_node, currentNode, &e_forward, &e_backward)) + { + weight = weight + (*e_forward).weight; + } + else + { + fprintf(stderr, "error\n"); + } + + ///process the in-nodes of get_node + clear_RSet(&in_buf); + while(getInputNodes(&in_buf, DAGCon, get_node, &in_node_of_get_node)) + { + ///link in-nodes of get_node to consensus_node + if(get_bi_Edge(DAGCon, in_node_of_get_node, consensus_node, &e_forward, &e_backward)) + { + Visit(*e_forward) = 1; + Visit(*e_backward) = 1; + (*e_forward).weight += get_Edge_Weight(DAGCon, in_node_of_get_node, get_node); + (*e_backward).weight = (*e_forward).weight; + } + else + { + add_bi_direction_edge(DAGCon, in_node_of_get_node, consensus_node, + get_Edge_Weight(DAGCon, in_node_of_get_node, get_node), 1); + } + } + + delete_Node_DAGCon(DAGCon, get_node); + } + } + } + + if(flag > 1) + { + get_bi_Edge(DAGCon, consensus_node, currentNode, &e_forward, &e_backward); + (*e_forward).weight = weight; + (*e_backward).weight = (*e_forward).weight; + } + + if(flag > 0) + { + Merge_In_Nodes(DAGCon, consensus_node); + } + } +} + +void print_graph(Graph* DAGCon) +{ + uint64_t i; + for (i = 0; i < DAGCon->g_nodes.length; i++) + { + Node* currentStartNode = &(G_Node(*DAGCon, i)); + RSet iter_out; + + if(If_Node_Exist(*currentStartNode)) + { + fprintf(stderr, "ID: %lu (%c) (w: %lu)\n", (unsigned long)(*currentStartNode).ID, (*currentStartNode).base, (unsigned long)(*currentStartNode).weight); + clear_RSet(&iter_out); + Edge* e; + fprintf(stderr, "****Out-node: "); + while(getOutputEdges(&iter_out, DAGCon, currentStartNode, &e)) + { + //fprintf(stderr, "%d[%c], ", G_Node(*DAGCon, e->out_node).ID, G_Node(*DAGCon, e->out_node).base); + fprintf(stderr, "%lu(w: %lu), ", (unsigned long)G_Node(*DAGCon, e->out_node).ID, (unsigned long)e->weight); + } + fprintf(stderr, "\n"); + + + // clear_RSet(&iter_out); + // fprintf(stderr, "In-node: "); + // while(getInputEdges(&iter_out, DAGCon, currentStartNode, &e)) + // { + // fprintf(stderr, "%d[%c], ", G_Node(*DAGCon, e->in_node).ID, G_Node(*DAGCon, e->in_node).base); + // } + } + } + + fprintf(stderr, "*******\n"); + +} + +void debug_DAGCon(Graph* DAGCon) +{ + uint64_t i = 0; + for (i = 0; i < DAGCon->g_nodes.length; i++) + { + Node* currentStartNode = &(G_Node(*DAGCon, i)); + RSet iter_out; + + if(If_Node_Exist(*currentStartNode)) + { + clear_RSet(&iter_out); + Edge* e_self; + Edge* e_reverse; + while(getOutputEdges(&iter_out, DAGCon, currentStartNode, &e_self)) + { + + get_bi_direction_edges(DAGCon, e_self, &e_self, &e_reverse); + + + if(Visit(*e_self) == 0) + { + fprintf(stderr, "Visit(*e_self): %lu, error visit flag: in_node: %lu, out_node: %lu\n", + (unsigned long)Visit(*e_self), (unsigned long)(*e_self).in_node, (unsigned long)(*e_self).out_node); + } + + + if(Visit(*e_reverse) == 0) + { + fprintf(stderr, "Visit(*e_reverse): %lu, error visit flag: in_node: %lu, out_node: %lu\n", + (unsigned long)Visit(*e_reverse), (unsigned long)(*e_reverse).in_node, (unsigned long)(*e_reverse).out_node); + } + + + if(e_self->in_node != e_reverse->in_node) + { + fprintf(stderr, "different in-node\n"); + } + if(e_self->out_node != e_reverse->out_node) + { + fprintf(stderr, "different out-node\n"); + } + if(e_self->weight != e_reverse->weight) + { + fprintf(stderr, "different weight\n"); + } + } + + clear_RSet(&iter_out); + while(getInputEdges(&iter_out, DAGCon, currentStartNode, &e_self)) + { + + get_bi_direction_edges(DAGCon, e_self, &e_self, &e_reverse); + + + if(Visit(*e_self) == 0) + { + fprintf(stderr, "Visit(*e_self): %lu, error visit flag: in_node: %lu, out_node: %lu\n", + (unsigned long)Visit(*e_self), (unsigned long)(*e_self).in_node, (unsigned long)(*e_self).out_node); + } + + + if(Visit(*e_reverse) == 0) + { + fprintf(stderr, "Visit(*e_reverse): %lu, error visit flag: in_node: %lu, out_node: %lu\n", + (unsigned long)Visit(*e_reverse), (unsigned long)(*e_reverse).in_node, (unsigned long)(*e_reverse).out_node); + } + + + if(e_self->in_node != e_reverse->in_node) + { + fprintf(stderr, "different in-node\n"); + } + if(e_self->out_node != e_reverse->out_node) + { + fprintf(stderr, "different out-node\n"); + } + if(e_self->weight != e_reverse->weight) + { + fprintf(stderr, "different weight\n"); + } + } + } + } +} + +void Merge_DAGCon(Graph* DAGCon) +{ + ///using the length of edge representing if it has been visited + ///in default, the length of edge is 0 + RSet iter_node, iter_edge; + long long flag; + + Node* currentNode; + Node* outNode; + Edge* edge; + Edge* e_forward; + Edge* e_backward; + + // int num_way = Real_Length(Output_Edges(G_Node(*DAGCon, DAGCon->s_start_nodeID))); + // if(num_way > 2) + // { + // print_graph(DAGCon); + // } + + + + ///at begining, only the start node has no in-node + currentNode = &(G_Node(*DAGCon, DAGCon->s_start_nodeID)); + Push_Node(DAGCon, ¤tNode); + + + + while (Pop_Node(DAGCon, ¤tNode)) + { + ///merge in-node + Merge_In_Nodes(DAGCon, currentNode); + ///merge out-node + Merge_Out_Nodes(DAGCon, currentNode); + + clear_RSet(&iter_edge); + ///for all out-edges of currentNode, set as visited + while (getOutputEdges(&iter_edge, DAGCon, currentNode, &edge)) + { + get_bi_direction_edges(DAGCon, edge, &e_forward, &e_backward); + Visit(*e_forward) = 1; + Visit(*e_backward) = 1; + } + + + + ///check all out-node of currentNode + clear_RSet(&iter_node); + while(getOutputNodes(&iter_node, DAGCon, currentNode, &outNode)) + { + + ///for each outNode, check if all in-edges have been visited + flag = 0; + clear_RSet(&iter_edge); + while (getInputEdges(&iter_edge, DAGCon, outNode, &edge)) + { + if(Visit(*edge) == 0) + { + flag = 1; + break; + } + } + //if all in-edges of Out_node have already been visited, push it to queue + if(flag == 0) + { + Push_Node(DAGCon, &outNode); + } + } + } + + + + // if(num_way > 2) + // { + // print_graph(DAGCon); + // fprintf(stderr, "****************************note*****************\n\n"); + // } + + + ///debug_DAGCon(DAGCon); +} + + +inline void generate_seq_from_path(Graph* DAGCon, Node* node, int direction) +{ + clear_Queue(&(DAGCon->node_q)); + RSet iter; + Edge* e = NULL; + uint64_t max; + Node* max_node = NULL; + + + if(direction == 0) + { + while (node->ID != DAGCon->s_end_nodeID) + { + push_to_Queue(&(DAGCon->node_q), node->base); + clear_RSet(&iter); + max = 0; + while(getOutputEdges(&iter, DAGCon, node, &e)) + { + if(e->weight > max) + { + max = e->weight; + max_node = &(G_Node(*DAGCon, e->out_node)); + } + } + node = max_node; + } + } + else + { + while (node->ID != DAGCon->s_start_nodeID) + { + push_to_Queue(&(DAGCon->node_q), node->base); + clear_RSet(&iter); + max = 0; + while(getInputEdges(&iter, DAGCon, node, &e)) + { + if(e->weight > max) + { + max = e->weight; + max_node = &(G_Node(*DAGCon, e->in_node)); + } + } + node = max_node; + } + + long long i, k; + long long length = (DAGCon->node_q.end - DAGCon->node_q.beg); + long long length_ex = length/2; + long long* array = DAGCon->node_q.buffer + DAGCon->node_q.beg; + for (i = 0; i < length_ex; i++) + { + k = array[i]; + array[i] = array[length - i - 1]; + array[length - i - 1] = k; + } + } +} + + +long long generate_best_seq_from_edges(Graph* DAGCon) +{ + long long max_start = 0, max_end = 0, max_start_edge = 0, max_end_edge = 0; + RSet iter; + Edge* e = NULL; + Node* newNode = NULL; + long long max_count = 0; + + + ///check the out-edges of start node + ///must to be 0 + max_start = 0; + newNode = &(G_Node(*DAGCon, DAGCon->s_start_nodeID)); + clear_RSet(&iter); + while(getOutputEdges(&iter, DAGCon, newNode, &e)) + { + if(e->weight > (uint64_t)max_start) + { + max_start = e->weight; + max_start_edge = iter.index - 1; + } + } + + ///check the in-edges of end node + ///must to be 0 + max_end = 0; + newNode = &(G_Node(*DAGCon, DAGCon->s_end_nodeID)); + clear_RSet(&iter); + while(getInputEdges(&iter, DAGCon, newNode, &e)) + { + if(e->weight > (uint64_t)max_end) + { + max_end = e->weight; + max_end_edge = iter.index - 1; + } + } + + if(max_start >= max_end) + { + max_count = max_start; + generate_seq_from_path(DAGCon, + &G_Node(*DAGCon, Output_Edges(G_Node(*DAGCon, DAGCon->s_start_nodeID)).list[max_start_edge].out_node), 0); + } + else + { + max_count = max_end; + generate_seq_from_path(DAGCon, + &G_Node(*DAGCon, Input_Edges(G_Node(*DAGCon, DAGCon->s_end_nodeID)).list[max_end_edge].in_node), 1); + } + + return max_count; +} + + +inline void generate_seq_from_node(Graph* DAGCon, Node* node, int direction) +{ + clear_Queue(&(DAGCon->node_q)); + RSet iter; + uint64_t max; + Node* max_node = NULL; + Node* getNodes = NULL; + + + if(direction == 0) + { + while (node->ID != DAGCon->s_end_nodeID) + { + push_to_Queue(&(DAGCon->node_q), node->base); + clear_RSet(&iter); + max = 0; + while(getOutputNodes(&iter, DAGCon, node, &getNodes)) + { + if(getNodes->weight > max) + { + max = getNodes->weight; + max_node = getNodes; + } + } + node = max_node; + } + } + else + { + while (node->ID != DAGCon->s_start_nodeID) + { + push_to_Queue(&(DAGCon->node_q), node->base); + clear_RSet(&iter); + max = 0; + while(getInputNodes(&iter, DAGCon, node, &getNodes)) + { + if(getNodes->weight > max) + { + max = getNodes->weight; + max_node = getNodes; + } + } + node = max_node; + } + + long long i, k; + long long length = (DAGCon->node_q.end - DAGCon->node_q.beg); + long long length_ex = length/2; + long long* array = DAGCon->node_q.buffer + DAGCon->node_q.beg; + for (i = 0; i < length_ex; i++) + { + k = array[i]; + array[i] = array[length - i - 1]; + array[length - i - 1] = k; + } + } +} + + +long long generate_best_seq_from_nodes(Graph* DAGCon) +{ + long long max_start = 0, max_end = 0; + RSet iter; + Edge* e = NULL; + Node* newNode = NULL; + Node* getNode = NULL; + Node* max_start_node = NULL; + Node* max_end_node = NULL; + long long max_count = 0; + uint64_t i; + + for (i = 0; i < DAGCon->g_nodes.length; i++) + { + newNode = &(G_Node(*DAGCon, i)); + if(If_Node_Exist(*newNode)) + { + newNode->weight = 0; + clear_RSet(&iter); + while(getOutputEdges(&iter, DAGCon, newNode, &e)) + { + newNode->weight += e->weight; + } + } + } + + newNode = &(G_Node(*DAGCon, DAGCon->s_start_nodeID)); + newNode->weight = 0; + clear_RSet(&iter); + while(getOutputEdges(&iter, DAGCon, newNode, &e)) + { + newNode->weight += e->weight; + } + + + newNode = &(G_Node(*DAGCon, DAGCon->s_end_nodeID)); + newNode->weight = 0; + clear_RSet(&iter); + while(getInputEdges(&iter, DAGCon, newNode, &e)) + { + newNode->weight += e->weight; + } + + + + + ///check the out-edges of start node + ///must to be 0 + max_start = 0; + newNode = &(G_Node(*DAGCon, DAGCon->s_start_nodeID)); + clear_RSet(&iter); + while(getOutputNodes(&iter, DAGCon, newNode, &getNode)) + { + if(getNode->weight > (uint64_t)max_start) + { + max_start = getNode->weight; + max_start_node = getNode; + } + } + + ///check the in-edges of end node + ///must to be 0 + max_end = 0; + newNode = &(G_Node(*DAGCon, DAGCon->s_end_nodeID)); + clear_RSet(&iter); + while(getInputNodes(&iter, DAGCon, newNode, &getNode)) + { + if(getNode->weight > (uint64_t)max_end) + { + max_end = getNode->weight; + max_end_node = getNode; + } + } + + if(max_start >= max_end) + { + max_count = max_start; + generate_seq_from_node(DAGCon, max_start_node, 0); + } + else + { + max_count = max_end; + generate_seq_from_node(DAGCon, max_end_node, 1); + } + + return max_count; +} + + +void build_DAGCon(Graph* DAGCon, Graph* backbone, long long currentNodeID, long long* max_count) +{ + long long i, j, path_weight, nodeID, step; + char base; + clear_Graph(DAGCon); + Node* newNode; + Node* lastNode; + + ///add the start node and the end node + newNode = add_Node_DAGCon(DAGCon, 'S'); + DAGCon->s_start_nodeID = newNode->ID; + + newNode = add_Node_DAGCon(DAGCon, 'E'); + DAGCon->s_end_nodeID = newNode->ID; + + + for (i = 0; i < (long long)G_Node(*backbone, currentNodeID).insertion_edges.length; i++) + { + path_weight = G_Node(*backbone, currentNodeID).insertion_edges.list[i].weight; + + lastNode = &(G_Node(*DAGCon, DAGCon->s_start_nodeID)); + + step = G_Node(*backbone, currentNodeID).insertion_edges.list[i].length; + if(step != 0) + { + nodeID = G_Node(*backbone, currentNodeID).insertion_edges.list[i].out_node; + + for (j = 0; j < step; j++) + { + base = G_Node(*backbone, nodeID).base; + newNode = add_Node_DAGCon(DAGCon, base); + add_bi_direction_edge(DAGCon, lastNode, newNode, path_weight, 0); + + nodeID = G_Node(*backbone, nodeID).insertion_edges.list[0].out_node; + + lastNode = newNode; + } + + if(lastNode->ID != DAGCon->s_start_nodeID) + { + add_bi_direction_edge(DAGCon, lastNode, &(G_Node(*DAGCon, DAGCon->s_end_nodeID)), path_weight, 0); + + } + } + + + + } + + + Merge_DAGCon(DAGCon); + + ///(*max_count) = generate_best_seq_from_edges(DAGCon); + (*max_count) = generate_best_seq_from_nodes(DAGCon); + + ///very important + backbone->g_nodes.list[currentNodeID].num_insertions = 0; + +} + +void debug_whole_graph(Graph* g) +{ + long long i, j, k; + for (i = 0; i < (long long)g->g_nodes.length; i++) + { + if(g->g_nodes.list[i].deletion_edges.length!= 0 && + g->g_nodes.list[i].deletion_edges.length!= 1) + { + fprintf(stderr, "g->g_nodes.list[i].deletion_edges.length: %lu\n", + (unsigned long)g->g_nodes.list[i].deletion_edges.length); + } + } + + for (i = g->s_start_nodeID; i < (long long)g->s_end_nodeID; i++) + { + if(g->g_nodes.list[i].mismatch_edges.length > 4 + || + g->g_nodes.list[i].mismatch_edges.length < 1) + { + fprintf(stderr, "g->s_end_nodeID: %lu, g->g_nodes.list[%lld].mismatch_edges.length: %lu\n", + (unsigned long)g->s_end_nodeID, i, (unsigned long)g->g_nodes.list[i].mismatch_edges.length); + } + } + + char current[1000]; + char compare[1000]; + long long total_weight = 0; + for (i = g->s_start_nodeID; i < (long long)g->s_end_nodeID; i++) + { + total_weight = 0; + for (j = 0; j < (long long)G_Node(*g, i).insertion_edges.length; j++) + { + + total_weight = total_weight + G_Node(*g, i).insertion_edges.list[j].weight; + + extract_path(g, i, j, current); + + for (k = j + 1; k < (long long)G_Node(*g, i).insertion_edges.length; k++) + { + extract_path(g, i, k, compare); + if(strcmp(current, compare)==0) + { + fprintf(stderr,"error\n"); + } + } + } + + if(total_weight != (long long)G_Node(*g, i).num_insertions) + { + fprintf(stderr,"error\n"); + } + } + + + +} + +void get_seq_from_Graph(Graph* backbone, Graph* DAGCon, Correct_dumy* dumy, Cigar_record* current_cigar, char* self_string, +char* r_string, long long r_string_length, long long r_string_site) +{ + ///debug_whole_graph(backbone); + long long currentNodeID; + long long i; + // There are several cases: + // 1. match 2. mismatch (A, C, G, T, N) 3. deletion 4. insertion (A, C, G, T) + // in fact, 1. the weight of node itself 2. weight of alignToNode 3. weight of insertion node + long long max_count; + int max_type; + long long max_edge; + long long total_count; + long long current_weight; + + long long max_insertion_count; + + currentNodeID = backbone->s_start_nodeID; + + while (currentNodeID != (long long)backbone->s_end_nodeID) + { + total_count = 0; + max_count = -1; + max_type = -1; + max_edge = -1; + + + ///if it is a backbone node, there are three types od out-edges + ///1. mismatch_edges 2. insertion_edges 3. deletion_edges + if (currentNodeID >= (long long)backbone->s_start_nodeID && currentNodeID <= (long long)backbone->s_end_nodeID) + { + ///mismatch_edges + for (i = 0; i < (long long)backbone->g_nodes.list[currentNodeID].mismatch_edges.length; i++) + { + if (backbone->g_nodes.list[currentNodeID].num_insertions != 0) + { + current_weight = backbone->g_nodes.list[currentNodeID].mismatch_edges.list[i].weight - + backbone->g_nodes.list[currentNodeID].mismatch_edges.list[i].num_insertions; + } + else + { + current_weight = backbone->g_nodes.list[currentNodeID].mismatch_edges.list[i].weight; + } + + + total_count = total_count + current_weight; + + ///for match, it needs to deal with both match and insertion + ///if there is a insertion, we need to check this node two times + ///1. num_insertions > 0, 2. num_insertions=0 + if (current_weight > max_count) + { + max_count = current_weight; + max_edge = i; + max_type = MISMATCH; + } + } + + ///insertion_edges + if (backbone->g_nodes.list[currentNodeID].num_insertions != 0) + { + ///this line must be prior than the next line + ///since build_DAGCon will set backbone->g_nodes.list[currentNodeID].num_insertions to be 0 + total_count = total_count + backbone->g_nodes.list[currentNodeID].num_insertions; + + build_DAGCon(DAGCon, backbone, currentNodeID, &max_insertion_count); + + if(max_insertion_count > max_count) + { + max_count = max_insertion_count; + max_type = INSERTION; + } + } + + ///deletion_edges + for (i = 0; i < (long long)backbone->g_nodes.list[currentNodeID].deletion_edges.length; i++) + { + total_count = total_count + backbone->g_nodes.list[currentNodeID].deletion_edges.list[i].weight; + + if ((long long)backbone->g_nodes.list[currentNodeID].deletion_edges.list[i].weight > max_count) + { + max_count = backbone->g_nodes.list[currentNodeID].deletion_edges.list[i].weight; + max_edge = i; + max_type = DELETION; + } + } + + ///do correction + if(max_count >= total_count*(CORRECT_THRESHOLD)) + { + currentNodeID = add_path_to_correct_read_new(backbone, DAGCon, dumy, currentNodeID, max_type, max_edge, current_cigar, + self_string); + } + else + { + ///NOTE: currentNodeID = 0 is a tmp node without any sense + if(currentNodeID > 0 && if_is_homopolymer_strict(r_string_site + currentNodeID - 1, r_string, r_string_length) + && max_count >= total_count*CORRECT_THRESHOLD_HOMOPOLYMER) + { + currentNodeID = add_path_to_correct_read_new(backbone, DAGCon, dumy, currentNodeID, max_type, max_edge, current_cigar, + self_string); + } + else///don't do correction, directly use the base of next backbone node + { + currentNodeID++; + add_base_to_correct_read_directly(dumy, backbone->g_nodes.list[currentNodeID].base); + + add_cigar_record(&(backbone->g_nodes.list[currentNodeID].base), 1, current_cigar, 0); + } + } + + } + else ///if there is a non-backbone node + { + fprintf(stderr, "error\n"); + } + + } + +} + + +void window_consensus(char* r_string, long long r_total_length, long long window_start, long long window_end, +overlap_region_alloc* overlap_list, Correct_dumy* dumy, All_reads* R_INF, Graph* g, Graph* DAGCon, Cigar_record* current_cigar) +{ + clear_Graph(g); + clear_Graph(DAGCon); + + long long x_start; + long long x_length; + char* x_string; + char* y_string; + char* backbone; + long long backbone_length; + uint64_t i; + long long y_start, y_length; + long long windowID; + long long startNodeID, endNodeID, currentNodeID; + overlap_region *z; + + + backbone = r_string + window_start; + backbone_length = window_end + 1 - window_start; + + addUnmatchedSeqToGraph(g, backbone, backbone_length, &startNodeID, &endNodeID); + + + long long correct_x_pos_s; + for (i = 0; i < dumy->length; i++) + { + // assert(dumy->overlapID[i]length); + ///this is the overlap ID + z = &(overlap_list->list[dumy->overlapID[i]]); + + correct_x_pos_s = (z->x_pos_s / WINDOW) * WINDOW; + windowID = (window_start - correct_x_pos_s) / WINDOW; + // assert(windowID<(int64_t)z->w_list.n); + + ///if this window is not matched + if (z->w_list.a[windowID].y_end == -1) continue; + + x_start = z->w_list.a[windowID].x_start; + x_length = z->w_list.a[windowID].x_end + 1 - z->w_list.a[windowID].x_start; + + + y_start = z->w_list.a[windowID].y_start; + y_length = z->w_list.a[windowID].y_end + 1 - z->w_list.a[windowID].y_start; + // assert(y_start>=0 && y_start<(int64_t)Get_READ_LENGTH((*R_INF), z->y_id)); + // assert((y_start+y_length)>=0 && (y_start+y_length)<=(int64_t)Get_READ_LENGTH((*R_INF), z->y_id)); + recover_UC_Read_sub_region(dumy->overlap_region, y_start, y_length, z->y_pos_strand, R_INF, z->y_id); + + x_string = r_string + x_start; + y_string = dumy->overlap_region; + ///here is the offset of the start base, also is the node ID + currentNodeID = x_start - window_start; + + // if(window_start == 4500) { + // fprintf(stderr, "[M::%s] window_start::%lld, ovlp_id::%lu, windowID::%lld, x_start::%lld, x_length::%lld, y_start::%lld, y_length::%lld, currentNodeID::%lld\n", __func__, + // window_start, dumy->overlapID[i], windowID, x_start, x_length, y_start, y_length, currentNodeID); + // } + + ///cigar: overlap_list->list[overlapID].w_list[windowID].cigar; + addmatchedSeqToGraph(g, currentNodeID, x_string, x_length, + y_string, y_length, &(z->w_list.a[windowID]), &(z->w_list), startNodeID, endNodeID); + } + + get_seq_from_Graph(g, DAGCon, dumy, current_cigar, backbone, r_string, r_total_length, window_start); +} + + +void add_cigar_to_cigar(Correct_dumy* backbone_dumy, Cigar_record* backbone_cigar, +Round2_alignment* second_round, +long long back_bone_start, long long back_bone_length, +long long new_start, long long new_length) +{ + Correct_dumy* new_dumy = &(second_round->dumy); + Cigar_record* new_cigar = &(second_round->tmp_cigar); + Cigar_record* result_cigar = &(second_round->cigar); + + char* x_string = backbone_dumy->corrected_read + back_bone_start; + char* y_string = new_dumy->corrected_read + new_start; + /** + if(verify_cigar_2(x_string, back_bone_length, y_string, new_length, new_cigar, -1)) + { + fprintf(stderr, "error\n"); + } + **/ + + + ///if type == 0, x_string here is not useful + ///output matches to cigar + add_cigar_record(x_string, back_bone_start - second_round->obtained_cigar_length, result_cigar, 0); + second_round->obtained_cigar_length = back_bone_start + back_bone_length; + + long long i, cigar_i, x_i, y_i; + int operation; + int operationLen; + x_i = y_i = 0; + char merge_base; + + for (i = 0; i < (long long)new_cigar->length; i++) + { + operation = Get_Cigar_Type(new_cigar->record[i]); + operationLen = Get_Cigar_Length(new_cigar->record[i]); + if (operation == 0) + { + ///if type == 0, x_string here is not useful + add_cigar_record(x_string, operationLen, result_cigar, 0); + x_i += operationLen; + y_i += operationLen; + } + else if (operation == 1) + { + for (cigar_i = 0; cigar_i < operationLen; cigar_i++) + { + merge_base = 0; + merge_base = seq_nt6_table[(uint8_t)y_string[y_i]]; + merge_base = merge_base << 3; + merge_base = merge_base | seq_nt6_table[(uint8_t)x_string[x_i]]; + + add_cigar_record(&merge_base, 1, result_cigar, 1); + x_i++; + y_i++; + } + } + else if (operation == INSERTION)///2是x缺字符(y多字符) + { + add_cigar_record(y_string+y_i, operationLen, result_cigar, INSERTION); + y_i += operationLen; + } + else if (operation == DELETION) + { + add_cigar_record(x_string+x_i, operationLen, result_cigar, DELETION); + x_i += operationLen; + } + } +} + +///correct bases of current_dumy->corrected_read in [start_base, end_base] +int merge_cigars(Correct_dumy* current_dumy, Cigar_record* current_cigar, +Round2_alignment* second_round, long long total_start_base, long long total_end_base, +long long total_window_start, long long total_window_end) +{ + Cigar_record* new_cigar = &(second_round->tmp_cigar); + + if(new_cigar->length == 1 && Get_Cigar_Type(new_cigar->record[0]) == 0) + { + return 1; + } + + + long long start_base = total_start_base - total_window_start; + long long end_base = total_end_base - total_window_start; + long long x_i, y_i, cigar_i, i; + x_i = 0; + y_i = 0; + int operation; + int operationLen; + + long long get_x_start, get_x_end, get_y_start, get_y_end; + get_x_start = get_x_end = get_y_start = get_y_end = -1; + + int start_cigar = -1; + int end_cigar = -1; + + ///0 is match, 1 is mismatch, 2 is up, 3 is left + ///obtained x_i may larger than start_base/end_base + ///when operation == 3 + ///so for operation == 3, we need deal with carefully + for (i = 0; i < (long long)new_cigar->length; i++) + { + operation = Get_Cigar_Type(new_cigar->record[i]); + operationLen = Get_Cigar_Length(new_cigar->record[i]); + if (operation == 0) + { + for (cigar_i = 0; cigar_i < operationLen; cigar_i++) + { + if(x_i >= start_base && get_x_start == -1) + { + get_x_start = x_i; + get_y_start = y_i; + start_cigar = i; + } + + + + if(x_i >= end_base && get_x_end == -1) + { + get_x_end = x_i; + get_y_end = y_i; + end_cigar = i; + break; + } + + + + x_i++; + y_i++; + } + } + else if (operation == 1) + { + for (cigar_i = 0; cigar_i < operationLen; cigar_i++) + { + if(x_i >= start_base && get_x_start == -1) + { + get_x_start = x_i; + get_y_start = y_i; + start_cigar = i; + } + + if(x_i >= end_base && get_x_end == -1) + { + get_x_end = x_i; + get_y_end = y_i; + end_cigar = i; + break; + } + + x_i++; + y_i++; + } + } + else if (operation == 2) + { + y_i += operationLen; + } + else if (operation == 3) + { + ///obtained x_i may larger than start_base/end_base + ///when operation == 3 + ///so for operation == 3, we need deal with carefully + x_i += operationLen; + } + } + + ///if there are some gap at the end of x, it very likely miscorrection + if(get_x_end == -1 || get_x_start == -1) + { + return 0; + } + + x_i = 0; + y_i = 0; + + uint32_t single_record = 0; + + for (i = 0; i < (long long)new_cigar->length; i++) + { + operation = Get_Cigar_Type(new_cigar->record[i]); + operationLen = Get_Cigar_Length(new_cigar->record[i]); + + if (i == start_cigar) + { + single_record = 0; + single_record = operationLen - (get_x_start - x_i); + single_record = single_record << 2; + single_record = single_record | operation; + new_cigar->record[i] = single_record; + + if(operation > 1) + { + fprintf(stderr, "error\n"); + } + + if (i == end_cigar) + { + x_i = get_x_start; + single_record = 0; + single_record = get_x_end - x_i + 1; + single_record = single_record << 2; + single_record = single_record | operation; + new_cigar->record[i] = single_record; + if(operation > 1) + { + fprintf(stderr, "error\n"); + } + break; + } + } + else if (i == end_cigar) + { + single_record = 0; + single_record = get_x_end - x_i + 1; + single_record = single_record << 2; + single_record = single_record | operation; + new_cigar->record[i] = single_record; + if(operation > 1) + { + fprintf(stderr, "error\n"); + } + break; + } + + + if (operation == 0 || operation == 1) + { + x_i += operationLen; + y_i += operationLen; + } + else if (operation == 2) + { + y_i += operationLen; + } + else if (operation == 3) + { + x_i += operationLen; + } + } + + new_cigar->length = end_cigar - start_cigar + 1; + ///should be improved + memmove(new_cigar->record, new_cigar->record + start_cigar, new_cigar->length*sizeof(uint32_t)); + + long long total_x_start = total_window_start + get_x_start; + long long x_length = get_x_end -get_x_start + 1; + long long total_y_start = get_y_start; + long long y_length = get_y_end -get_y_start + 1; + + add_cigar_to_cigar(current_dumy, current_cigar, second_round, + total_x_start, x_length, total_y_start, y_length); + + return 1; +} + +int process_boundary(overlap_region_alloc* overlap_list, All_reads* R_INF, Correct_dumy* dumy, Graph* g, Graph* DAGCon, +Cigar_record* current_cigar, long long uncorrected_window_start, Round2_alignment* second_round, window_list_alloc* win_ciagr_buf) +{ + char* r_string = dumy->corrected_read; + long long r_total_length = current_cigar->new_read_length; + long long corrected_window_start, corrected_window_end; + int extra_begin; + int extra_end; + + if(dumy->last_boundary_length == 0) + { + return 0; + } + + corrected_window_start = dumy->last_boundary_length - WINDOW_BOUNDARY/2; + corrected_window_end = dumy->last_boundary_length + WINDOW_BOUNDARY/2 - 1; + + if(corrected_window_start < 0) + { + corrected_window_start = 0; + } + + if (corrected_window_end >= current_cigar->new_read_length) + { + corrected_window_end = current_cigar->new_read_length - 1; + } + + clear_Graph(g); + clear_Graph(DAGCon); + + long long x_start, x_end; + long long x_length, x_len, o_len; + int threshold; + long long Window_Len; + char* x_string = NULL; + char* y_string = NULL; + char* backbone = NULL; + long long backbone_length; + long long i; + long long y_start, y_length; + long long overlapID, windowID; + long long startNodeID, endNodeID, currentNodeID; + int end_site; + unsigned int error; + int real_y_start; + long long total_error = 0; + + backbone = r_string + corrected_window_start; + backbone_length = corrected_window_end - corrected_window_start + 1; + addUnmatchedSeqToGraph(g, backbone, backbone_length, &startNodeID, &endNodeID); + + + long long correct_x_pos_s; + long long matched_coverage = 0; + for (i = 0; i < (long long)dumy->length; i++) + { + overlapID = dumy->overlapID[i]; + correct_x_pos_s = (overlap_list->list[overlapID].x_pos_s / WINDOW) * WINDOW; + windowID = (uncorrected_window_start - correct_x_pos_s) / WINDOW; + + ///skip if window is unmatched + if (overlap_list->list[overlapID].w_list.a[windowID].y_end == -1) + { + continue; + } + + x_start = overlap_list->list[overlapID].w_list.a[windowID].x_start; + y_start = overlap_list->list[overlapID].w_list.a[windowID].y_start; + + + + + /** + * There are total 3 cases: + * 1. this window of x is overlapped fully by y + * x: ------|------|--------- + * y: ------|------|--------- + * in this case, x_start == uncorrected_window_start, x_length == WINDOW + * 2. the suiffx of x's window is overlapped by the prefix of y + * x: ------|------|--------- + * y: |--|----------- + * in this case, x_start > uncorrected_window_start, x_length < WINDOW + * this overlap is useless + * 3. the prefix of x's window is overlapped by y (see last window) + * x: |------|------|-----|--- + * y: |--|-----|------ + * or + * x: |------|------|-----|---- + * y: --|------|------|-----|-- + * + * in this case, x_start == uncorrected_window_start, x_length < WINDOW + * + * case 1 and case 3 are useful, while case 2 is useless + * **/ + + ///case 1 and case 3 are useful + if(x_start == uncorrected_window_start) + { + extra_begin = extra_end = 0; + x_start = corrected_window_start; + x_end = corrected_window_end; + x_len = x_end - x_start + 1; + threshold = x_len * asm_opt.max_ov_diff_ec; + /****************************may have bugs********************************/ + threshold = Adjust_Threshold(threshold, x_len); + /****************************may have bugs********************************/ + ///y_start may less than 0 + y_start = y_start - WINDOW_BOUNDARY/2; + + ///in fact, we don't need this line, just worry for bug + if(y_start < 0) + { + continue; + } + + Window_Len = x_len + (threshold << 1); + + error =(unsigned int)-1; + if(determine_overlap_region(threshold, y_start, overlap_list->list[overlapID].y_id, Window_Len, Get_READ_LENGTH((*R_INF), overlap_list->list[overlapID].y_id), + &extra_begin, &extra_end, &y_start, &o_len)) + { + fill_subregion(dumy->overlap_region, y_start, o_len, overlap_list->list[overlapID].y_pos_strand, + R_INF, overlap_list->list[overlapID].y_id, extra_begin, extra_end); + + x_string = r_string + x_start; + y_string = dumy->overlap_region; + + ///both end site and real_y_start have extra_begin + ///should be improved, since most of overlaps are exact overlaps + ///we can do it quickly + end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, + &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); + } + + + + ///try to calculate using higher threshold + if(error==(unsigned int)-1) + { + extra_begin = extra_end = 0; + x_start = corrected_window_start; + x_end = corrected_window_end; + x_len = x_end - x_start + 1; + threshold = threshold * 2; + /****************************may have bugs********************************/ + threshold = Adjust_Threshold(threshold, x_len); + /****************************may have bugs********************************/ + if(x_len >= 300 && threshold < THRESHOLD_MAX_SIZE) + { + threshold = THRESHOLD_MAX_SIZE; + } + if(threshold > THRESHOLD_MAX_SIZE) + { + threshold = THRESHOLD_MAX_SIZE; + } + Window_Len = x_len + (threshold << 1); + y_start = overlap_list->list[overlapID].w_list.a[windowID].y_start - WINDOW_BOUNDARY/2; + + ///in fact, we don't need this line, just worry for bug + if(y_start < 0) + { + continue; + } + + error =(unsigned int)-1; + if(determine_overlap_region(threshold, y_start, overlap_list->list[overlapID].y_id, Window_Len, Get_READ_LENGTH((*R_INF), overlap_list->list[overlapID].y_id), + &extra_begin, &extra_end, &y_start, &o_len)) + { + fill_subregion(dumy->overlap_region, y_start, o_len, overlap_list->list[overlapID].y_pos_strand, + R_INF, overlap_list->list[overlapID].y_id, extra_begin, extra_end); + + x_string = r_string + x_start; + y_string = dumy->overlap_region; + + ///both end site and real_y_start have extra_begin + ///should be improved, since most of overlaps are exact overlaps + ///we can do it quickly + end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, + &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); + } + } + + if (error!=(unsigned int)-1) + { + + + + total_error = total_error + error; + matched_coverage++; + win_ciagr_buf->a[0].x_start = x_start; win_ciagr_buf->a[0].x_end = x_end; + win_ciagr_buf->c.n = 0; + generate_cigar(dumy->path, dumy->path_length, &(win_ciagr_buf->a[0]), win_ciagr_buf, &real_y_start, &end_site, &error, x_string, x_len, y_string); + ///both end site and real_y_start have extra_begin + real_y_start -= extra_begin; + end_site -= extra_begin; + + y_length = end_site - real_y_start + 1; + y_start = y_start + real_y_start; + + + x_start = corrected_window_start; + x_length = corrected_window_end - x_start + 1; + + ///here can be improved, make y_string = dumy->overlap_region + real_y_start + extra_begin + recover_UC_Read_sub_region(dumy->overlap_region, y_start, y_length, overlap_list->list[overlapID].y_pos_strand, + R_INF, overlap_list->list[overlapID].y_id); + + x_string = r_string + x_start; + y_string = dumy->overlap_region; + + currentNodeID = x_start - corrected_window_start; + + addmatchedSeqToGraph(g, currentNodeID, x_string, x_length, y_string, y_length, &(win_ciagr_buf->a[0]), win_ciagr_buf, startNodeID, endNodeID); + } + + }///case 2 is useless + else if(x_start != uncorrected_window_start) + { + continue; + } + } + + + if(matched_coverage >= MIN_COVERAGE_THRESHOLD) + { + ///if there are no error, we do not need correction + if(total_error == 0) + { + return 0; + } + + clear_Cigar_record(&(second_round->tmp_cigar)); + clear_Correct_dumy_pure(&(second_round->dumy)); + + ///correct bases in [start_base, end_base] + long long start_base = corrected_window_start + WINDOW_UNCORRECT_SINGLE_SIDE_BOUNDARY; + long long end_base = corrected_window_end - WINDOW_UNCORRECT_SINGLE_SIDE_BOUNDARY; + + if(end_base > start_base) + { + ///note there is an additional "S" node + ///and start from i-th node, we can correct (i+1)-th base + /// so the condition when traversing graph is + ///(node >= start_base - corrected_window_start && node <= end_base - corrected_window_start) + get_seq_from_Graph(g, DAGCon, &(second_round->dumy), &(second_round->tmp_cigar), backbone, + r_string, r_total_length, corrected_window_start); + + /** + if(verify_cigar_2(backbone, backbone_length, second_round->dumy.corrected_read, + second_round->dumy.corrected_read_length, &(second_round->tmp_cigar), -1)) + { + fprintf(stderr, "hahah\n"); + } + **/ + + merge_cigars(dumy, current_cigar, second_round, start_base, end_base, + corrected_window_start, corrected_window_end); + + + + } + + } + else + { + return 0; + } + + return 1; + + + +} + + +void generate_consensus(overlap_region_alloc* overlap_list, All_reads* R_INF, + UC_Read* g_read, Correct_dumy* dumy, Graph* g, Graph* DAGCon, Cigar_record* current_cigar, + Round2_alignment* second_round, window_list_alloc* win_ciagr_buf) +{ + clear_Cigar_record(current_cigar); + + long long window_start, window_end; + + long long num_availiable_win = 0; + + + + + Window_Pool w_inf; + init_Window_Pool(&w_inf, g_read->length, WINDOW, (int)(1.0/asm_opt.max_ov_diff_ec)); + + int flag = 0; + ///for last window + dumy->last_boundary_length = 0; + while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) + { + + + + dumy->length = 0; + dumy->lengthNT = 0; + + ///return overlaps that are overlaped with [window_start, window_end] + flag = get_available_interval(window_start, window_end, overlap_list, dumy); + switch (flag) + { + case 1: ///match + break; + case 0: ///unmatch + break; + case -2: ///unmatch, and cannot match for next window + break; + } + + num_availiable_win = num_availiable_win + dumy->length; + + // fprintf(stderr, "[M::%s] window_start::%lld, window_end::%lld, g_read->length::%lld, dumy->length::%lu\n", __func__, + // window_start, window_end, g_read->length, dumy->length); + + ///number of overlaps, also be the coverage + if(dumy->length >= MIN_COVERAGE_THRESHOLD) + { + window_consensus(g_read->seq, g_read->length, window_start, window_end, overlap_list, + dumy, R_INF, g, DAGCon, current_cigar); + + if(dumy->last_boundary_length != 0) + { + process_boundary(overlap_list, R_INF, dumy, g, DAGCon, current_cigar, + window_start, second_round, win_ciagr_buf); + } + + } + else + { + add_segment_to_correct_read(dumy, g_read->seq + window_start, window_end - window_start + 1); + add_cigar_record(g_read->seq + window_start, window_end - window_start + 1, current_cigar, 0); + } + + + dumy->last_boundary_length = current_cigar->new_read_length; + } + + if (window_start < g_read->length) + { + add_segment_to_correct_read(dumy, g_read->seq + window_start, g_read->length - window_start); + add_cigar_record(g_read->seq + window_start, g_read->length - window_start, current_cigar, 0); + } + + ///if type == 0, x_string here is not useful + ///output matches to cigar + if (current_cigar->new_read_length != second_round->obtained_cigar_length) + { + add_cigar_record(dumy->corrected_read, current_cigar->new_read_length - second_round->obtained_cigar_length, + &(second_round->cigar), 0); + } +} + + +inline int get_available_fully_covered_interval(long long window_start, long long window_end, +overlap_region_alloc* overlap_list, Correct_dumy* dumy, long long* real_length, long long* real_length_100) +{ + long long i, fud = 0; + long long Len; + long long overlap_length; + + if(window_start == 0) dumy->start_i = 0; + for (i = dumy->start_i; i < (long long)overlap_list->length; i++) + { + if (window_end < (long long)overlap_list->list[i].x_pos_s) + { + dumy->start_i = 0; + return 0; + } + else + { + dumy->start_i = i; + break; + } + } + + + if (i >= (long long)overlap_list->length) + { + dumy->start_i = overlap_list->length; + return -2; + } + + + + + + long long fake_length = 0; + overlap_length = window_end - window_start + 1; + (*real_length) = 0; fud = 0; + + for (; i < (long long)overlap_list->length; i++) + { + if((Len = OVERLAP(window_start, window_end, (long long)overlap_list->list[i].x_pos_s, (long long)overlap_list->list[i].x_pos_e)) > 0) + { + fake_length++; + + if (overlap_length == Len && overlap_list->list[i].is_match == 1) + { + (*real_length)++; + } + + if (overlap_length == Len && overlap_list->list[i].is_match == 100) + { + (*real_length_100)++; + } + if(fud == 0) fud = 1, dumy->start_i = i; + } + + if((long long)overlap_list->list[i].x_pos_s > window_end) + { + break; + } + } + + if (fake_length == 0) + { + return 0; + } + else + { + return 1; + } +} + +int check_if_fully_covered(overlap_region_alloc* overlap_list, +All_reads* R_INF, UC_Read* g_read, Correct_dumy* dumy, Graph* g, int* abnormal) +{ + long long window_start, window_end; + int return_flag = 1; + (*abnormal) = 0; + + Window_Pool w_inf; + init_Window_Pool(&w_inf, g_read->length, WINDOW, (int)(1.0/asm_opt.max_ov_diff_ec)); + + int flag = 0; + long long realLen = 0, tmpLen = 0; + while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) + { + dumy->length = 0; + dumy->lengthNT = 0; + + ///return overlaps that are overlaped with [window_start, window_end] + flag = get_available_fully_covered_interval(window_start, window_end, + overlap_list, dumy, &realLen, &tmpLen); + + + switch (flag) + { + case 1: ///match + break; + case 0: ///unmatch + break; + case -2: ///unmatch, and cannot match for next window + break; + } + + if(realLen < MIN_COVERAGE_THRESHOLD * 2) + { + return_flag = 0; + //return 0; + } + + if(realLen == 0) + { + ///that means this window is a middle window + if(window_start != 0 && window_end != g_read->length - 1) + { + (*abnormal) = 1; + } + else if((*abnormal)==0) + { + (*abnormal) = 2; + } + } + } + + return return_flag; +} + +///mark SNPs at [xBeg, xEnd], note we need to deal with flag_offset carefully +void markSNP_detail(window_list *cigar_idx, window_list_alloc *cigar_s, uint8_t* flag, +long long xBeg, long long xEnd, long long flag_offset, const ul_idx_t *uref, long long y_total_start, int y_strand, int yid) +{ + if(xBeg > xEnd) return; + + int64_t x_i, y_i, c_i, c_n = cigar_idx->clen, pi = 0, cc = 0; + uint32_t i, operLen = (uint32_t)-1; uint8_t oper = (uint8_t)-1; + i = c_i = x_i = y_i = 0; + for (c_i = 0; c_i < c_n; c_i++) { + get_cigar_cell(cigar_idx, cigar_s, c_i, &oper, &operLen); + if(x_i > xEnd) break; + + if (oper == 0) {///match + x_i += operLen; y_i += operLen; + } + else if(oper == 1) {///mismatch + for (i = 0; i < operLen; i++) { + /// note we need to deal with flag_offset carefully + ///if(flag[x_i - flag_offset] < 127 && x_i >= xBeg && x_i <= xEnd) + if(x_i >= xBeg && x_i <= xEnd && flag[x_i - flag_offset] < 127) {///Fix-attention + if(uref) { + cc = retrieve_u_cov(uref, yid, y_strand, y_total_start + y_i, y_strand, &pi); + cc += flag[x_i - flag_offset]; + flag[x_i - flag_offset] = (cc <= 127?cc:127); + // if(cc <= 127) flag[x_i - flag_offset] = cc; + } else { + flag[x_i - flag_offset]++; + } + } + x_i++; y_i++; + } + } else if (oper == 2) {///insertion, that means y has more bases than x + y_i += operLen; + } + else if (oper == 3) { + x_i += operLen; + } + } +} + + +///window_offset is still the x-based offset +///x_total_start and y_total_start are global positions, instead of local positions +void markSNP_advance( +long long window_offset, +long long x_total_start, long long x_length, +long long y_total_start, long long y_length, +window_list *current_cigar, window_list_alloc *current_cigar_s, +window_list *beg_cigar, window_list_alloc *beg_cigar_s, +window_list *end_cigar, window_list_alloc *end_cigar_s, +haplotype_evdience_alloc* hap, const ul_idx_t *uref, int strand, int yid) +{ + long long x_total_end = x_total_start + x_length - 1; + ///mismatches based on the offset of x + long long inner_offset = x_total_start - window_offset; + ///long long useless_side, xleftLen, xrightLen, x_interval_beg, x_interval_end; + long long L_useless_side, R_useless_side, xleftLen, xrightLen, x_interval_beg, x_interval_end; + long long current_cigar_beg, current_cigar_end; + + ///for current_cigar, [current_cigar_beg, current_cigar_end] + current_cigar_beg = 0; + current_cigar_end = x_length - 1; + ///if the beg_cigar is available + if(beg_cigar != NULL && beg_cigar->y_end!=-1) + { + ///useless_side = beg_cigar->error_threshold; + L_useless_side = beg_cigar->extra_begin; + R_useless_side = beg_cigar->extra_end; + ///again, xleftLen does not include x_total_start itself, but includes beg_cigar->x_start + xleftLen = x_total_start - beg_cigar->x_start; + ///xrightLen includes both x_total_start and beg_cigar->x_end + xrightLen = beg_cigar->x_end - x_total_start + 1; + ///actually xleftLen could be no larger than useless_side + ///but such window has already been filtered out at calculate_boundary_cigars + ///if(xleftLen > useless_side && xrightLen > useless_side) + if(xleftLen > L_useless_side && xrightLen > R_useless_side) + { + ///[x_interval_beg, x_interval_end] are the offsets to beg_cigar->x_start + ///they are local postions, instead of global positions + + x_interval_beg = xleftLen; + //x_interval_end = x_interval_beg + (xrightLen - useless_side) - 1; + x_interval_end = x_interval_beg + (xrightLen - R_useless_side) - 1; + ///current_cigar_beg is the offset of the current cigar + ///that is the beg of current_cigar_beg + ///current_cigar_beg = xrightLen - useless_side; + current_cigar_beg = xrightLen - R_useless_side; + + markSNP_detail(beg_cigar, beg_cigar_s, hap->flag + inner_offset, x_interval_beg, x_interval_end, + x_interval_beg, uref, beg_cigar->y_start, strand, yid); + } + } + + if(end_cigar!=NULL && end_cigar->y_end!=-1) + { + ///useless_side = end_cigar->error_threshold; + L_useless_side = end_cigar->extra_begin; + R_useless_side = end_cigar->extra_end; + ///again, xleftLen does not include x_total_end, but includes end_cigar->x_start + ///it seems to be not what we want + xleftLen = x_total_end - end_cigar->x_start; + ///xrightLen includes both x_total_end and end_cigar->x_end + ///it is also not what we want + xrightLen = end_cigar->x_end - x_total_end + 1; + ///we hope that x_total_end should be included in xleftLen, instead of xrightLen + ///that means xleftLen should + 1, while xrightLen should -1 + ///but it is fine here + + ///actually xrightLen could be no larger than useless_side + ///but such window has already been filtered out in calculate_boundary_cigars + ///if(xleftLen > useless_side && xrightLen > useless_side) + if(xleftLen > L_useless_side && xrightLen > R_useless_side) + { + ///[x_interval_beg, x_interval_end] are the offsets to beg_cigar->x_start + ///they are local postions, instead of global positions + x_interval_end = xleftLen; + ///the real left part length is (xleftLen + 1) + ///so the useful left part length is ((xleftLen + 1) - useless_side) + ///x_interval_beg = x_interval_end - ((xleftLen + 1) - useless_side) + 1; + x_interval_beg = x_interval_end - ((xleftLen + 1) - L_useless_side) + 1; + ///current_cigar_end = (x_length - 1) - ((xleftLen + 1) - useless_side); + current_cigar_end = (x_length - 1) - ((xleftLen + 1) - L_useless_side); + + markSNP_detail(end_cigar, end_cigar_s, hap->flag + end_cigar->x_start - window_offset, x_interval_beg, + x_interval_end, 0, uref, end_cigar->y_start, strand, yid); + } + } + + markSNP_detail(current_cigar, current_cigar_s, hap->flag + inner_offset, current_cigar_beg, + current_cigar_end, 0, uref, current_cigar->y_start, strand, yid); +} + + + +/** +void addSNPtohaplotype( +long long window_offset, int overlapID, +char* x_string, long long x_total_start, long long x_length, +char* y_string, long long y_total_start, long long y_length, +CIGAR* cigar, haplotype_evdience_alloc* hap, int snp_threshold) +{ + + int x_i, y_i, cigar_i; + x_i = 0; + y_i = 0; + cigar_i = 0; + int operation; + int operationLen; + int i; + long long inner_offset = x_total_start - window_offset; + haplotype_evdience ev; + + ///note that node 0 is the start node + ///0 is match, 1 is mismatch, 2 is up, 3 is left + ///2 represents thre are more bases at y + ///3 represents thre are more bases at x + while (cigar_i < cigar->length) + { + operation = cigar->C_C[cigar_i]; + operationLen = cigar->C_L[cigar_i]; + + ///matches + if (operation == 0) + { + for (i = 0; i < operationLen; i++) + { + ///should be at least 2 mismatches + if(hap->flag[inner_offset] > snp_threshold) + { + ev.misBase = y_string[y_i]; + ev.overlapID = overlapID; + ev.site = x_total_start + x_i; + ev.overlapSite = y_total_start + y_i; + ev.type = 0; + addHaplotypeEvdience(hap, &ev, NULL); + } + + + inner_offset++; + x_i++; + y_i++; + } + + } + else if(operation == 1) + { + for (i = 0; i < operationLen; i++) + { + + if(hap->flag[inner_offset] > snp_threshold) + { + ev.misBase = y_string[y_i]; + ev.overlapID = overlapID; + ev.site = x_total_start + x_i; + ev.overlapSite = y_total_start + y_i; + ev.type = 1; + addHaplotypeEvdience(hap, &ev, NULL); + } + + inner_offset++; + x_i++; + y_i++; + } + }///insertion + else if (operation == 2) + { + y_i += operationLen; + } + else if (operation == 3) + { + //may have bugs + for (i = 0; i < operationLen; i++) + { + if(hap->flag[inner_offset] > snp_threshold) + { + ev.misBase = 'N'; + ev.overlapID = overlapID; + ev.site = x_total_start + x_i; + ev.overlapSite = y_total_start + y_i; + ev.type = 2; + addHaplotypeEvdience(hap, &ev, NULL); + } + + inner_offset++; + x_i++; + } + //may have bugs + } + + cigar_i++; + } +} +**/ + + +///mark SNPs at [xBeg, xEnd], note we need to deal with flag_offset carefully +void addSNPtohaplotype_details(window_list *cigar_idx, window_list_alloc *cigar_s, uint8_t* flag, +char* x_string, char* y_string, long long x_total_start, long long y_total_start, +long long xBeg, long long xEnd, int overlapID, long long flag_offset, +haplotype_evdience_alloc* hap, long long snp_threshold, const ul_idx_t *uref, int y_strand, int yid, void *km) +{ + if(xBeg > xEnd) return; + int64_t x_i, y_i, c_i, pi = 0, c_n = cigar_idx->clen; + uint32_t i, operLen = (uint32_t)-1; uint8_t oper = (uint8_t)-1; i = c_i = x_i = y_i = 0; + haplotype_evdience ev; + + ///note that node 0 is the start node + ///0 is match, 1 is mismatch, 2 is up, 3 is left + ///2 represents thre are more bases at y + ///3 represents thre are more bases at x + for (c_i = 0; c_i < c_n; c_i++) { + get_cigar_cell(cigar_idx, cigar_s, c_i, &oper, &operLen); + if(x_i > xEnd) break; + + if (oper == 0) { ///matches + for (i = 0; i < operLen; i++) { + ///should be at least 2 mismatches + /// note we need to deal with flag_offset carefully + ///if(flag[x_i - flag_offset] > snp_threshold && x_i >= xBeg && x_i <= xEnd) + if(x_i >= xBeg && x_i <= xEnd && flag[x_i - flag_offset] > snp_threshold) { + ev.misBase = y_string[y_i]; + ev.overlapID = overlapID; + ev.site = x_total_start + x_i; + ev.overlapSite = y_total_start + y_i; + ev.type = 0; + ev.cov = uref?retrieve_u_cov(uref, yid, y_strand, y_total_start + y_i, y_strand, &pi):1; + addHaplotypeEvdience(hap, &ev, km); + } + ///inner_offset++; + x_i++; y_i++; + } + } + else if(oper == 1) { + for (i = 0; i < operLen; i++) { + /// should be at least 2 mismatches + /// note we need to deal with flag_offset carefully + ///if(flag[x_i - flag_offset] > snp_threshold && x_i >= xBeg && x_i <= xEnd) + if(x_i >= xBeg && x_i <= xEnd && flag[x_i - flag_offset] > snp_threshold) { + ev.misBase = y_string[y_i]; + ev.overlapID = overlapID; + ev.site = x_total_start + x_i; + ev.overlapSite = y_total_start + y_i; + ev.type = 1; + ev.cov = uref?retrieve_u_cov(uref, yid, y_strand, y_total_start + y_i, y_strand, &pi):1; + addHaplotypeEvdience(hap, &ev, km); + } + ///inner_offset++; + x_i++; y_i++; + } + }///insertion, 2 represents thre are more bases at y + else if (oper == 2) { + y_i += operLen; + }///3 represents thre are more bases at x + else if (oper == 3) { + /****************************may have bugs********************************/ + for (i = 0; i < operLen; i++) { + ///if(hap->flag[inner_offset] > snp_threshold) + /// should be at least 2 mismatches + /// note we need to deal with flag_offset carefully + ///if(flag[x_i - flag_offset] > snp_threshold && x_i >= xBeg && x_i <= xEnd) + if(x_i >= xBeg && x_i <= xEnd && flag[x_i - flag_offset] > snp_threshold) { + ev.misBase = 'N'; + ev.overlapID = overlapID; + ev.site = x_total_start + x_i; + ev.overlapSite = y_total_start + y_i; + ev.type = 2; + ev.cov = uref?retrieve_u_cov(uref, yid, y_strand, y_total_start + y_i, y_strand, &pi):1; + addHaplotypeEvdience(hap, &ev, km); + } + + ///inner_offset++; + x_i++; + } + /****************************may have bugs********************************/ + } + } +} + + +void addSNPtohaplotype_advance( +long long window_offset, int overlapID, +long long x_total_start, long long x_length, +long long y_total_start, long long y_length, +window_list* current_cigar, window_list_alloc *current_cigar_s, +window_list* beg_cigar, window_list_alloc *beg_cigar_s, +window_list* end_cigar, window_list_alloc *end_cigar_s, +haplotype_evdience_alloc* hap, int snp_threshold, char* x_T_string, char* y_T_string, const ul_idx_t *uref, int strand, int yid, void *km) +{ + long long x_total_end = x_total_start + x_length - 1; + long long inner_offset = x_total_start - window_offset; + ///long long useless_side, xleftLen, xrightLen, x_interval_beg, x_interval_end; + long long L_useless_side, R_useless_side, xleftLen, xrightLen, x_interval_beg, x_interval_end; + long long current_cigar_beg, current_cigar_end; + + ///for current_cigar, [current_cigar_beg, current_cigar_end] + current_cigar_beg = 0; + current_cigar_end = x_length - 1; + ///if the beg_cigar is available + if(beg_cigar != NULL && beg_cigar->y_end!=-1) + { + ///useless_side = beg_cigar->error_threshold; + L_useless_side = beg_cigar->extra_begin; + R_useless_side = beg_cigar->extra_end; + ///again, xleftLen does not include x_total_start itself, but includes beg_cigar->x_start + xleftLen = x_total_start - beg_cigar->x_start; + ///xrightLen includes both x_total_start and beg_cigar->x_end + xrightLen = beg_cigar->x_end - x_total_start + 1; + ///actually xleftLen could be no larger than useless_side + ///but such window has already been filtered out at calculate_boundary_cigars + ///if(xleftLen > useless_side && xrightLen > useless_side) + if(xleftLen > L_useless_side && xrightLen > R_useless_side) { + ///[x_interval_beg, x_interval_end] are the offsets to beg_cigar->x_start + ///they are local postions, instead of global positions + + x_interval_beg = xleftLen; + ///x_interval_end = x_interval_beg + (xrightLen - useless_side) - 1; + x_interval_end = x_interval_beg + (xrightLen - R_useless_side) - 1; + ///current_cigar_beg is the offset of the current cigar + ///that is the beg of current_cigar_beg + ///current_cigar_beg = xrightLen - useless_side; + current_cigar_beg = xrightLen - R_useless_side; + + // markSNP_detail(cigar_record, hap->flag + inner_offset, x_interval_beg, + // x_interval_end, x_interval_beg); + addSNPtohaplotype_details(beg_cigar, beg_cigar_s, hap->flag + inner_offset, + x_T_string + beg_cigar->x_start, y_T_string + beg_cigar->y_start, + beg_cigar->x_start, beg_cigar->y_start, x_interval_beg, x_interval_end, + overlapID, x_interval_beg, hap, snp_threshold, uref, strand, yid, km); + } + } + + + if(end_cigar!=NULL && end_cigar->y_end!=-1) + { + ///useless_side = end_cigar->error_threshold; + L_useless_side = end_cigar->extra_begin; + R_useless_side = end_cigar->extra_end; + ///again, xleftLen does not include x_total_end, but includes end_cigar->x_start + ///it seems to be not what we want + xleftLen = x_total_end - end_cigar->x_start; + ///xrightLen includes both x_total_end and end_cigar->x_end + ///it is also not what we want + xrightLen = end_cigar->x_end - x_total_end + 1; + ///we hope that x_total_end should be included in xleftLen, instead of xrightLen + ///that means xleftLen should + 1, while xrightLen should -1 + ///but it is fine here + + ///actually xrightLen could be no larger than useless_side + ///but such window has already been filtered out in calculate_boundary_cigars + ///if(xleftLen > useless_side && xrightLen > useless_side) + if(xleftLen > L_useless_side && xrightLen > R_useless_side) + { + ///[x_interval_beg, x_interval_end] are the offsets to beg_cigar->x_start + ///they are local postions, instead of global positions + x_interval_end = xleftLen; + ///the real left part length is (xleftLen + 1) + ///so the useful left part length is ((xleftLen + 1) - useless_side) + ///x_interval_beg = x_interval_end - ((xleftLen + 1) - useless_side) + 1; + x_interval_beg = x_interval_end - ((xleftLen + 1) - L_useless_side) + 1; + ///current_cigar_end = (x_length - 1) - ((xleftLen + 1) - useless_side); + current_cigar_end = (x_length - 1) - ((xleftLen + 1) - L_useless_side); + + // markSNP_detail(cigar_record, hap->flag + end_cigar->x_start - window_offset, + // x_interval_beg, x_interval_end, 0); + addSNPtohaplotype_details(end_cigar, end_cigar_s, hap->flag + end_cigar->x_start - window_offset, + x_T_string + end_cigar->x_start, y_T_string + end_cigar->y_start, + end_cigar->x_start, end_cigar->y_start, x_interval_beg, x_interval_end, + overlapID, 0, hap, snp_threshold, uref, strand, yid, km); + } + } + + // markSNP_detail(&(current_cigar->cigar), hap->flag + inner_offset, current_cigar_beg, + // current_cigar_end, 0); + addSNPtohaplotype_details(current_cigar, current_cigar_s, hap->flag + inner_offset, + x_T_string + current_cigar->x_start, y_T_string + current_cigar->y_start, + current_cigar->x_start, current_cigar->y_start, current_cigar_beg, + current_cigar_end, overlapID, 0, hap, snp_threshold, uref, strand, yid, km); +} + +/** +void cluster(char* r_string, long long window_start, long long window_end, +overlap_region_alloc* overlap_list, Correct_dumy* dumy, All_reads* R_INF, haplotype_evdience_alloc* hap) +{ + ///window_start, window_end, and useful_length correspond to x, instead of y + long long useful_length = window_end - window_start + 1; + long long x_start; + long long x_length; + char* x_string; + char* y_string; + long long i; + long long y_start, y_length; + long long overlapID, windowID; + + long long correct_x_pos_s; + int snp_threshold; + snp_threshold = 1; + + ///all overlaps related to the current window [window_start, window_end] + ///first mark all snp pos + for (i = 0; i < (long long)dumy->length; i++) + { + ///overlap id, instead of the window id or the y id + overlapID = dumy->overlapID[i]; + + ///overlap_list->list[overlapID].x_pos_s is the begining of the whole overlap + correct_x_pos_s = (overlap_list->list[overlapID].x_pos_s / WINDOW) * WINDOW; + ///window_start is the begining of this window in the whole x_read + windowID = (window_start - correct_x_pos_s) / WINDOW; + + ///skip if this window is not matched + if (overlap_list->list[overlapID].w_list[windowID].y_end == -1) + { + continue; + } + + ///both x_start and y_start are the offsets of the whole x_read and y_read + ///instead of the offsets of window + x_start = overlap_list->list[overlapID].w_list[windowID].x_start; + x_length = overlap_list->list[overlapID].w_list[windowID].x_end + - overlap_list->list[overlapID].w_list[windowID].x_start + 1; + + y_start = overlap_list->list[overlapID].w_list[windowID].y_start; + y_length = overlap_list->list[overlapID].w_list[windowID].y_end + - overlap_list->list[overlapID].w_list[windowID].y_start + 1; + + + markSNP(window_start, x_start, x_length, y_start, y_length, + &(overlap_list->list[overlapID].w_list[windowID].cigar), hap); + } + + + //may have bugs + long long last_snp = -1; + long long first_snp = -1; + for (i = 0; i < useful_length; i++) + { + if(hap->flag[i] != 0) + { + last_snp = i; + if(first_snp == -1) + { + first_snp = i; + } + } + ///for a real snp, the coverage should be at least 2 + if(hap->flag[i] > snp_threshold) + { + // hap->snp++; + hap->nn_snp++; + } + } + ///if there are any >0 elements, both first_snp and last_snp should be != -1 + if(first_snp == -1 || last_snp == -1) + { + first_snp = 0; + last_snp = -1; + } + //may have bugs + + + + ///add the information related to snp to haplotype_evdience_alloc + for (i = 0; i < (long long)dumy->length; i++) + { + ///overlap ID, instead of the window ID + overlapID = dumy->overlapID[i]; + + ///overlap_list->list[overlapID].x_pos_s is the begining of the whole overlap + correct_x_pos_s = (overlap_list->list[overlapID].x_pos_s / WINDOW) * WINDOW; + ///window_start is the begining of this window in the whole x_read + windowID = (window_start - correct_x_pos_s) / WINDOW; + + ///skip if this window is not matched + if (overlap_list->list[overlapID].w_list[windowID].y_end == -1) + { + continue; + } + + ///both x_start and y_start are the offsets of the whole x_read and y_read + ///instead of the offsets of window + x_start = overlap_list->list[overlapID].w_list[windowID].x_start; + x_length = overlap_list->list[overlapID].w_list[windowID].x_end + - overlap_list->list[overlapID].w_list[windowID].x_start + 1; + + y_start = overlap_list->list[overlapID].w_list[windowID].y_start; + y_length = overlap_list->list[overlapID].w_list[windowID].y_end + - overlap_list->list[overlapID].w_list[windowID].y_start + 1; + + + recover_UC_Read_sub_region(dumy->overlap_region, y_start, y_length, overlap_list->list[overlapID].y_pos_strand, + R_INF, overlap_list->list[overlapID].y_id); + + x_string = r_string + x_start; + y_string = dumy->overlap_region; + + + addSNPtohaplotype(window_start, overlapID, x_string, x_start, x_length, + y_string, y_start, y_length, &(overlap_list->list[overlapID].w_list[windowID].cigar), + hap, snp_threshold); + } + + RsetInitHaplotypeEvdienceFlag(hap, first_snp, last_snp + 1 - first_snp); +} +**/ + + +void get_related_cigars(window_list_alloc* boundary_cigars, long long id, window_list** beg_cigar, +window_list** end_cigar) +{ + (*beg_cigar) = &(boundary_cigars->a[id*2]); + (*end_cigar) = &(boundary_cigars->a[id*2+1]); +} + +int cmp_haplotype_evdience(const void * a, const void * b) +{ + if ((*(haplotype_evdience*)a).site != (*(haplotype_evdience*)b).site) + { + return (*(haplotype_evdience*)a).site > (*(haplotype_evdience*)b).site ? 1 : -1; + } + else + { + if ((*(haplotype_evdience*)a).type != (*(haplotype_evdience*)b).type) + { + return (*(haplotype_evdience*)a).type > (*(haplotype_evdience*)b).type ? 1 : -1; + } + else + { + if ((*(haplotype_evdience*)a).misBase != (*(haplotype_evdience*)b).misBase) + { + return (*(haplotype_evdience*)a).misBase > (*(haplotype_evdience*)b).misBase ? 1 : -1; + } + else + { + return 0; + } + + } + + } + + +} + +void cluster_advance(char* r_string, long long window_start, long long window_end, +overlap_region_alloc* overlap_list, Correct_dumy* dumy, All_reads* R_INF, +haplotype_evdience_alloc* hap, UC_Read* overlap_read, int snp_threshold) +{ + window_list* beg_cigar; + window_list* end_cigar; + ///window_start, window_end, and useful_length correspond to x, instead of y + long long useful_length = window_end - window_start + 1; + long long x_start, x_length, ll = hap->length, lr; + char* x_string; + char* y_string; + long long i; + long long y_start, y_length; + long long overlapID, windowID; + + long long correct_x_pos_s; + + + ///all overlaps related to the current window [window_start, window_end] + ///first mark all snp pos + for (i = 0; i < (long long)dumy->length; i++) + { + ///overlap id, instead of the window id or the y id + overlapID = dumy->overlapID[i]; + + ///overlap_list->list[overlapID].x_pos_s is the begining of the whole overlap + correct_x_pos_s = (overlap_list->list[overlapID].x_pos_s / WINDOW) * WINDOW; + ///window_start is the begining of this window in the whole x_read + windowID = (window_start - correct_x_pos_s) / WINDOW; + + ///skip if this window is not matched + if (overlap_list->list[overlapID].w_list.a[windowID].y_end == -1) + { + continue; + } + + ///both x_start and y_start are the offsets of the whole x_read and y_read + ///instead of the offsets of window + x_start = overlap_list->list[overlapID].w_list.a[windowID].x_start; + x_length = overlap_list->list[overlapID].w_list.a[windowID].x_end + 1 + - overlap_list->list[overlapID].w_list.a[windowID].x_start; + + y_start = overlap_list->list[overlapID].w_list.a[windowID].y_start; + y_length = overlap_list->list[overlapID].w_list.a[windowID].y_end + 1 + - overlap_list->list[overlapID].w_list.a[windowID].y_start; + + beg_cigar = end_cigar = NULL; + + if(windowID >= 1) + { + beg_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID-1]); + } + + if(windowID < (long long)(overlap_list->list[overlapID].w_list.n) - 1) + { + end_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID]); + } + + + markSNP_advance(window_start, x_start, x_length, y_start, y_length, + &(overlap_list->list[overlapID].w_list.a[windowID]), &(overlap_list->list[overlapID].w_list), + beg_cigar, &(overlap_list->list[overlapID].boundary_cigars), + end_cigar, &(overlap_list->list[overlapID].boundary_cigars), hap, NULL, + overlap_list->list[overlapID].y_pos_strand, overlap_list->list[overlapID].y_id); + } + + + /****************************may have bugs********************************/ + long long last_snp = -1; + long long first_snp = -1; + for (i = 0, lr = 0; i < useful_length; i++) + { + if(hap->flag[i] != 0) + { + last_snp = i; + if(first_snp == -1) + { + first_snp = i; + } + } + ///for a real snp, the coverage should be at least 2 + if(hap->flag[i] > snp_threshold) + { + // hap->snp++; + hap->nn_snp++; + lr++; + } + } + ///if there are any >0 elements, both first_snp and last_snp should be != -1 + if(first_snp == -1 || last_snp == -1) + { + first_snp = 0; + last_snp = -1; + } + /****************************may have bugs********************************/ + + + + ///add the information related to snp to haplotype_evdience_alloc + for (i = 0; i < (long long)dumy->length; i++) + { + ///overlap ID, instead of the window ID + overlapID = dumy->overlapID[i]; + + ///overlap_list->list[overlapID].x_pos_s is the begining of the whole overlap + correct_x_pos_s = (overlap_list->list[overlapID].x_pos_s / WINDOW) * WINDOW; + ///window_start is the begining of this window in the whole x_read + windowID = (window_start - correct_x_pos_s) / WINDOW; + + ///skip if this window is not matched + if (overlap_list->list[overlapID].w_list.a[windowID].y_end == -1) + { + continue; + } + + ///both x_start and y_start are the offsets of the whole x_read and y_read + ///instead of the offsets of window + x_start = overlap_list->list[overlapID].w_list.a[windowID].x_start; + x_length = overlap_list->list[overlapID].w_list.a[windowID].x_end + - overlap_list->list[overlapID].w_list.a[windowID].x_start + 1; + + y_start = overlap_list->list[overlapID].w_list.a[windowID].y_start; + y_length = overlap_list->list[overlapID].w_list.a[windowID].y_end + - overlap_list->list[overlapID].w_list.a[windowID].y_start + 1; + + + if(overlap_list->list[overlapID].y_pos_strand == 0) + { + recover_UC_Read(overlap_read, R_INF, overlap_list->list[overlapID].y_id); + } + else + { + recover_UC_Read_RC(overlap_read, R_INF, overlap_list->list[overlapID].y_id); + } + + x_string = r_string; + y_string = overlap_read->seq; + + + beg_cigar = end_cigar = NULL; + if(windowID >= 1) + { + beg_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID-1]); + } + if(windowID < (long long)(overlap_list->list[overlapID].w_list.n) - 1) + { + end_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID]); + } + + + addSNPtohaplotype_advance(window_start, overlapID, x_start, x_length, y_start, y_length, + &(overlap_list->list[overlapID].w_list.a[windowID]), &(overlap_list->list[overlapID].w_list), + beg_cigar, &(overlap_list->list[overlapID].boundary_cigars), + end_cigar, &(overlap_list->list[overlapID].boundary_cigars), + hap, snp_threshold, x_string, y_string, NULL, overlap_list->list[overlapID].y_pos_strand, + overlap_list->list[overlapID].y_id, NULL); + } + + RsetInitHaplotypeEvdienceFlag(hap, first_snp, last_snp + 1 - first_snp); + + if(hap->length - ll > 1 && lr > 1) radix_sort_haplotype_evdience_srt(hap->list+ll, hap->list + hap->length); +} + +void cluster_ul_advance(char* r_string, long long window_start, long long window_end, +overlap_region_alloc* overlap_list, Correct_dumy* dumy, const ul_idx_t *uref, +haplotype_evdience_alloc* hap, UC_Read* overlap_read, int snp_threshold, long long blockLen, void *km) +{ + window_list* beg_cigar; + window_list* end_cigar; + ///window_start, window_end, and useful_length correspond to x, instead of y + long long useful_length = window_end - window_start + 1; + long long x_start, x_length, ll = hap->length, lr; + char* x_string; + char* y_string; + long long i; + long long y_start, y_length; + long long overlapID, windowID; + + long long correct_x_pos_s; + + + ///all overlaps related to the current window [window_start, window_end] + ///first mark all snp pos + for (i = 0; i < (long long)dumy->length; i++) + { + ///overlap id, instead of the window id or the y id + overlapID = dumy->overlapID[i]; + + ///overlap_list->list[overlapID].x_pos_s is the begining of the whole overlap + correct_x_pos_s = (overlap_list->list[overlapID].x_pos_s / blockLen) * blockLen; + ///window_start is the begining of this window in the whole x_read + windowID = (window_start - correct_x_pos_s) / blockLen; + + ///skip if this window is not matched + if (overlap_list->list[overlapID].w_list.a[windowID].y_end == -1) + { + continue; + } + + ///both x_start and y_start are the offsets of the whole x_read and y_read + ///instead of the offsets of window + x_start = overlap_list->list[overlapID].w_list.a[windowID].x_start; + x_length = overlap_list->list[overlapID].w_list.a[windowID].x_end + - overlap_list->list[overlapID].w_list.a[windowID].x_start + 1; + + y_start = overlap_list->list[overlapID].w_list.a[windowID].y_start; + y_length = overlap_list->list[overlapID].w_list.a[windowID].y_end + - overlap_list->list[overlapID].w_list.a[windowID].y_start + 1; + + beg_cigar = end_cigar = NULL; + + if(windowID >= 1) + { + beg_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID-1]); + } + + if(windowID < (long long)(overlap_list->list[overlapID].w_list.n) - 1) + { + end_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID]); + } + + + markSNP_advance(window_start, x_start, x_length, y_start, y_length, + &(overlap_list->list[overlapID].w_list.a[windowID]), &(overlap_list->list[overlapID].w_list), + beg_cigar, &(overlap_list->list[overlapID].boundary_cigars), + end_cigar, &(overlap_list->list[overlapID].boundary_cigars), + hap, uref, overlap_list->list[overlapID].y_pos_strand, overlap_list->list[overlapID].y_id); + } + + + /****************************may have bugs********************************/ + long long last_snp = -1; + long long first_snp = -1; + for (i = 0, lr = 0; i < useful_length; i++) + { + if(hap->flag[i] != 0) + { + last_snp = i; + if(first_snp == -1) + { + first_snp = i; + } + } + ///for a real snp, the coverage should be at least 2 + if(hap->flag[i] > snp_threshold) + { + // hap->snp++; + hap->nn_snp++; + lr++; + } + } + ///if there are any >0 elements, both first_snp and last_snp should be != -1 + if(first_snp == -1 || last_snp == -1) + { + first_snp = 0; + last_snp = -1; + } + /****************************may have bugs********************************/ + + + + ///add the information related to snp to haplotype_evdience_alloc + for (i = 0; i < (long long)dumy->length; i++) + { + ///overlap ID, instead of the window ID + overlapID = dumy->overlapID[i]; + + ///overlap_list->list[overlapID].x_pos_s is the begining of the whole overlap + correct_x_pos_s = (overlap_list->list[overlapID].x_pos_s / blockLen) * blockLen; + ///window_start is the begining of this window in the whole x_read + windowID = (window_start - correct_x_pos_s) / blockLen; + + ///skip if this window is not matched + if (overlap_list->list[overlapID].w_list.a[windowID].y_end == -1) + { + continue; + } + + ///both x_start and y_start are the offsets of the whole x_read and y_read + ///instead of the offsets of window + x_start = overlap_list->list[overlapID].w_list.a[windowID].x_start; + x_length = overlap_list->list[overlapID].w_list.a[windowID].x_end + - overlap_list->list[overlapID].w_list.a[windowID].x_start + 1; + + y_start = overlap_list->list[overlapID].w_list.a[windowID].y_start; + y_length = overlap_list->list[overlapID].w_list.a[windowID].y_end + - overlap_list->list[overlapID].w_list.a[windowID].y_start + 1; + + retrieve_u_seq(overlap_read, NULL, &uref->ug->u.a[overlap_list->list[overlapID].y_id], + overlap_list->list[overlapID].y_pos_strand, 0, -1, km); + + + x_string = r_string; + y_string = overlap_read->seq; + + + beg_cigar = end_cigar = NULL; + if(windowID >= 1) + { + beg_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID-1]); + } + if(windowID < (long long)(overlap_list->list[overlapID].w_list.n) - 1) + { + end_cigar = &(overlap_list->list[overlapID].boundary_cigars.a[windowID]); + } + + + addSNPtohaplotype_advance(window_start, overlapID, x_start, x_length, y_start, y_length, + &(overlap_list->list[overlapID].w_list.a[windowID]), &(overlap_list->list[overlapID].w_list), + beg_cigar, &(overlap_list->list[overlapID].boundary_cigars), + end_cigar, &(overlap_list->list[overlapID].boundary_cigars), + hap, snp_threshold, x_string, y_string, uref, overlap_list->list[overlapID].y_pos_strand, overlap_list->list[overlapID].y_id, km); + } + + RsetInitHaplotypeEvdienceFlag(hap, first_snp, last_snp + 1 - first_snp); + + if(hap->length - ll > 1 && lr > 1) radix_sort_haplotype_evdience_srt(hap->list+ll, hap->list + hap->length); +} + + +int cmp_snp_stats(const void * a, const void * b) +{ + if ((*(SnpStats*)a).score != (*(SnpStats*)b).score) + { + return (*(SnpStats*)a).score < (*(SnpStats*)b).score ? 1 : -1; + } + else + { + if ((*(SnpStats*)a).occ_2 != (*(SnpStats*)b).occ_2) + { + return (*(SnpStats*)a).occ_2 > (*(SnpStats*)b).occ_2 ? 1 : -1; + } + else + { + return 0; + } + } +} + + +int cmp_max_DP(const void * a, const void * b) +{ + if(Get_Max_DP_Value((*(uint64_t*)a))!=Get_Max_DP_Value((*(uint64_t*)b))) + { + return Get_Max_DP_Value((*(uint64_t*)a)) < Get_Max_DP_Value((*(uint64_t*)b))? 1 : -1; + } + else + { + return 0; + } +} + + +int split_sub_list(haplotype_evdience_alloc* hap, +haplotype_evdience* sub_list, long long sub_length, +overlap_region_alloc* overlap_list, All_reads* R_INF, UC_Read* g_read) +{ + long long i = 0; + long long occ_0 = 0; + long long occ_1 = 0; + long long occ_1_array[5]; + memset(occ_1_array, 0, sizeof(long long) * 5); + long long occ_2 = 0; + + + for (i = 0; i < sub_length; i++) + { + if(sub_list[i].type == 0) + { + occ_0++; + } + else if(sub_list[i].type == 1) + { + occ_1_array[seq_nt6_table[(uint8_t)(sub_list[i].misBase)]]++; + occ_1++; + } + else if(sub_list[i].type == 2) + { + occ_2++; + } + } + + + + /** + 1. if occ_0 = 0, that means all overlaps are different with this read at this site + 2. it is not possible that occ_1 = 0, + 3. if occ_1 = 1, there are only one difference. It must be a sequencing error. + (for repeat, it maybe a snp at repeat. but ...) + **/ + ///if(occ_0 == 0 || occ_1 <= 1) + if(occ_0 == 0 || occ_1 == 0) + { + return 0; + } + + + + ///note: if the max value except type0 is type2 + ///that means this is no snp hapolyte + long long max = occ_2; + long long max_i = -1; + + for (i = 0; i < 5; i++) + { + if(occ_1_array[i] > max) + { + max = occ_1_array[i]; + max_i = i; + } + } + + + + if(max_i == -1) + { + return 0; + } + + if(max <= 1) + { + return 0; + } + + + ///if we have two max + for (i = 0; i < 5; i++) + { + if(occ_1_array[i] == max && i != max_i) + { + return 0; + } + } + + long long new_0 = occ_0 + 1; + long long new_total = sub_length + 1; + ///note: here occ_0++ since the read itself has a type0 + double available = new_0 + max; + double threshold = 0.95; + available = available/((double)(new_total)); + if(available < threshold)///Fix-attention: looks definitely wrong + { + return 0; + } + + ///new_total is the number of errors here + new_total = new_total - new_0; + ///available is the number of selected errors here + available = max; + threshold = 0.70; + available = available/((double)(new_total)); + if(available < threshold)///Fix-attention: looks definitely wrong + { + return 0; + } + + InsertSNPVector(hap, sub_list, sub_length, s_H[max_i], g_read); + + return 1; +} + + +int calculate_distance_snp_vector(int8_t *vector1, int8_t *vector2, int Len) +{ + int i; + for (i = 0; i < Len; i++) + { + if(vector1[i] != vector2[i]) + { + if ((vector1[i] == 0 || vector1[i] == 1) && (vector2[i] == 0 || vector2[i] == 1)) + { + return 1; + } + } + } + + return 0; +} + +void print_core_snp(haplotype_evdience_alloc* hap) +{ + uint64_t i, j; + for (i = 0; i < hap->core_snp; i++) + { + fprintf(stderr, "core(i): %lu, site: %u, occ_0: %u, occ_1: %u, occ_2: %u, score: %d\n", + (unsigned long)i, hap->snp_stat.a[i].site, hap->snp_stat.a[i].occ_0, hap->snp_stat.a[i].occ_1, + hap->snp_stat.a[i].occ_2, + hap->snp_stat.a[i].score); + + int vectorID = hap->snp_stat.a[i].id; + int8_t* vector = Get_SNP_Vector((*hap), vectorID); + + for (j = 0; j < hap->overlap; j++) + { + if(vector[j] == 0) + { + fprintf(stderr, "type: %d, ID: %lu\n", vector[j], (unsigned long)j); + } + } + + + for (j = 0; j < hap->overlap; j++) + { + if(vector[j] == 1) + { + fprintf(stderr, "type: %d, ID: %lu\n", vector[j], (unsigned long)j); + } + } + + + for (j = 0; j < hap->overlap; j++) + { + if(vector[j] == 2) + { + fprintf(stderr, "type: %d, ID: %lu\n", vector[j], (unsigned long)j); + } + } + + } +} + + + +void add_to_result_snp_vector(haplotype_evdience_alloc* hap, int8_t *new_vector, int Len) +{ + int8_t *r_vector = Get_Result_SNP_Vector((*hap)); + int j; + for (j = 0; j < Len; j++) + { + if(r_vector[j] == -1) + { + if(new_vector[j] == 0) + { + hap->result_stat.occ_0++; + r_vector[j] = new_vector[j]; + } + else if(new_vector[j] == 1) + { + hap->result_stat.occ_1++; + r_vector[j] = new_vector[j]; + } + } + ///can debug here + } + + hap->result_stat.overlap_num = hap->result_stat.occ_0 + hap->result_stat.occ_1; +} + + +int debug_add_to_result_snp_vector(haplotype_evdience_alloc* hap, int8_t *new_vector, int Len) +{ + int8_t *r_vector = Get_Result_SNP_Vector((*hap)); + int j; + for (j = 0; j < Len; j++) + { + if(r_vector[j] == -1) + { + if(new_vector[j] == 0) + { + hap->result_stat.occ_0++; + r_vector[j] = new_vector[j]; + } + else if(new_vector[j] == 1) + { + hap->result_stat.occ_1++; + r_vector[j] = new_vector[j]; + } + } + else ///can debug here + { + ///if((new_vector[j] != -1 && new_vector[j] != 2 && new_vector[j] != r_vector[j])) + if((new_vector[j] == 0 || new_vector[j] == 1) && new_vector[j] != r_vector[j]) + { + return j; + } + } + } + + return -1; + +} + + + +int merge_snp_vectors_and_test(haplotype_evdience_alloc* hap, int diff_vector_ID) +{ + int8_t *r_vector = Get_Result_SNP_Vector((*hap)); + int vectorLen = Get_SNP_Vector_Length((*hap)); + memset(r_vector, -1, vectorLen); + hap->result_stat.occ_0 = 0; + hap->result_stat.occ_1 = 0; + + int8_t* vector; + int vectorID; + int i, j; + + for (i = 0; i < (int)hap->core_snp; i++) + { + if(i == diff_vector_ID) + { + continue; + } + + vectorID = hap->snp_stat.a[i].id; + vector = Get_SNP_Vector((*hap), vectorID); + + for (j = 0; j < vectorLen; j++) + { + if(r_vector[j] == -1) + { + if(vector[j] == 0) + { + hap->result_stat.occ_0++; + r_vector[j] = vector[j]; + } + else if(vector[j] == 1) + { + hap->result_stat.occ_1++; + r_vector[j] = vector[j]; + } + } + else ///can debug here + { + ///has confilict + if(vector[j] != -1 && vector[j] != 2 && vector[j] != r_vector[j]) + { + return 0; + } + } + } + } + + hap->result_stat.overlap_num = hap->result_stat.occ_0 + hap->result_stat.occ_1; + + return 1; +} + +int generate_haplotypes(haplotype_evdience_alloc* hap) +{ + int j; + + int vectorID2; + int8_t *vector, *vector2; + + if(hap->core_snp == 0) + { + return 0; + } + + ///sort by weight + // qsort(hap->snp_stat, hap->available_snp, sizeof(SnpStats), cmp_snp_stats); + qsort(hap->snp_stat.a, hap->snp_stat.n, sizeof(SnpStats), cmp_snp_stats); + + + ///the hap->core_snp is used to find centriod + ///if there are <5 vectors in core_snp, we didn't allow different vector + if (hap->core_snp < 5) + { + if(merge_snp_vectors_and_test(hap, -1) == 0) + { + return 0; + } + } + else ///for vectors in core_snp, we allow at most one different vector when there are >= 5 vectors in core_snp + { + ///there are two condition: 1. vector 0 is the different one. 2. vector 0 is not the different one + ///first try to merge all vector together + if(merge_snp_vectors_and_test(hap, -1) == 0) + { + for (j = hap->core_snp - 1; j >= 0; j--) + { + if(merge_snp_vectors_and_test(hap, j) == 1) + { + break; + } + } + + if(j == -1) + { + return 0; + } + } + } + + + + + ///after merge, we get result vector + vector = Get_Result_SNP_Vector((*hap)); + ///and for each non-core snp vector, if it has no conflict with result vector + /// add it to result vector + for (j = hap->core_snp; j < (int)hap->snp_stat.n/**hap->available_snp**/; j++) + { + vectorID2 = hap->snp_stat.a[j].id; + vector2 = Get_SNP_Vector((*hap), vectorID2); + if(calculate_distance_snp_vector(vector, vector2, Get_SNP_Vector_Length((*hap))) == 0) + { + add_to_result_snp_vector(hap, vector2, Get_SNP_Vector_Length((*hap))); + } + } + + + ///for read only have 1 snp, we need a more strict condition + if (hap->core_snp == 1 && + filter_one_snp(hap->result_stat.occ_0 + 1, hap->result_stat.occ_1, + hap->result_stat.overlap_num + 1) == 0) + { + return 0; + } + + + return 1; + +} + +void Preorder_Merge(uint32_t snpID, haplotype_evdience_alloc* hap, int is_merge) +{ + int vectorID = hap->snp_stat.a[snpID].id; + int8_t* vector = Get_SNP_Vector((*hap), vectorID); + hap->dp.visit[snpID] = 1; + + + if(is_merge) + { + if(hap->snp_stat.a[snpID].is_homopolymer) + { + hap->result_stat.homopolymer_num++; + } + else + { + hap->result_stat.non_homopolymer_num++; + } + + hap->result_stat.score++; + int flag; + if((flag = debug_add_to_result_snp_vector(hap, vector, Get_SNP_Vector_Length((*hap))))!= -1) + { + fprintf(stderr, "incompatible snp vector....\n"); + exit(0); + } + } + + uint32_t* column; + int j; + + if(hap->dp.backtrack_length[snpID] != 0) + { + column = Get_DP_Backtrack_Column(hap->dp, snpID); + + if(is_merge) + { + int add_ID = 0; + for (j = 0; j < (int)hap->dp.backtrack_length[snpID]; j++) + { + if(hap->snp_stat.a[column[j]].is_homopolymer == 0) + { + add_ID = j; + } + } + + for (j = 0; j < (int)hap->dp.backtrack_length[snpID]; j++) + { + if(j == add_ID) + { + Preorder_Merge(column[j], hap, 1); + } + else + { + Preorder_Merge(column[j], hap, 0); + } + } + } + else + { + for (j = 0; j < (int)hap->dp.backtrack_length[snpID]; j++) + { + Preorder_Merge(column[j], hap, 0); + } + } + } +} + + +void Preorder_Merge_Advance_Repeat(uint32_t snpID, haplotype_evdience_alloc* hap, int pathLen) +{ + hap->dp.visit[snpID] = 1; + hap->dp.buffer[pathLen] = snpID; + pathLen++; + + if(hap->dp.backtrack_length[snpID] == 0) + { + insert_SNP_IDs_addition(&(hap->dp.SNP_IDs), hap->dp.buffer, pathLen); + return; + } + else + { + uint32_t* column; + int j; + + column = Get_DP_Backtrack_Column(hap->dp, snpID); + for (j = 0; j < (int)hap->dp.backtrack_length[snpID]; j++) + { + Preorder_Merge_Advance_Repeat(column[j], hap, pathLen); + } + } +} + +void generate_result_vector(haplotype_evdience_alloc* hap, int pathLen) +{ + if(pathLen != hap->dp.current_snp_num) + { + fprintf(stderr, "error\n"); + } + + + int8_t* vector = Get_Result_SNP_Vector((*hap)); + memset(vector, -1, Get_SNP_Vector_Length((*hap))); + hap->result_stat.occ_0 = 0; + hap->result_stat.occ_1 = 0; + hap->result_stat.occ_2 = 0; + hap->result_stat.score = pathLen; + hap->result_stat.homopolymer_num = 0; + hap->result_stat.non_homopolymer_num = 0; + + long long snpID1; + long long j = 0; + int flag, vectorID; + int current_score; + for (j = 0; j < pathLen; j++) + { + snpID1 = hap->dp.buffer[j]; + vectorID = hap->snp_stat.a[snpID1].id; + vector = Get_SNP_Vector((*hap), vectorID); + if(hap->snp_stat.a[snpID1].is_homopolymer) + { + hap->result_stat.homopolymer_num++; + } + else + { + hap->result_stat.non_homopolymer_num++; + } + + if((flag = debug_add_to_result_snp_vector(hap, vector, Get_SNP_Vector_Length((*hap))))!= -1) + { + fprintf(stderr, "incompatible snp vector....\n"); + exit(0); + } + } + hap->result_stat.overlap_num = hap->result_stat.occ_0 + hap->result_stat.occ_1; + + + + + ///check if this is a useful snp vector + if(hap->result_stat.overlap_num !=0 && filter_one_snp_advance_nearby(hap, hap->result_stat.occ_0 + 1, + hap->result_stat.occ_1, hap->result_stat.overlap_num + 1, + hap->result_stat.homopolymer_num, hap->result_stat.non_homopolymer_num, + hap->dp.buffer, pathLen)) + { + current_score = calculate_score(hap->result_stat.occ_0 + 1, hap->result_stat.occ_1); + ///first useful snp vector + if(hap->dp.max_snp_num < pathLen) + { + hap->dp.max_snp_num = pathLen; + hap->dp.max_score = current_score; + memcpy(hap->dp.max_buffer, hap->dp.buffer, sizeof(uint32_t) * pathLen); + }///if we have multiple single best snp vector, select the vector with max score + else if(hap->dp.max_snp_num == pathLen) + { + if(current_score > hap->dp.max_score) + { + hap->dp.max_score = current_score; + memcpy(hap->dp.max_buffer, hap->dp.buffer, sizeof(uint32_t) * pathLen); + } + } + } + +} + + +void Preorder_Merge_Advance(uint32_t snpID, haplotype_evdience_alloc* hap, int pathLen) +{ + hap->dp.visit[snpID] = 1; + hap->dp.buffer[pathLen] = snpID; + pathLen++; + + if(hap->dp.backtrack_length[snpID] == 0) + { + generate_result_vector(hap, pathLen); + return; + } + else + { + uint32_t* column; + int j; + + column = Get_DP_Backtrack_Column(hap->dp, snpID); + for (j = 0; j < (int)hap->dp.backtrack_length[snpID]; j++) + { + Preorder_Merge_Advance(column[j], hap, pathLen); + } + } +} + + + +int if_snp_vector_useful(haplotype_evdience_alloc* hap, +long long occ_0, long long occ_1, uint32_t* SNPs, long long SNPsLen) +{ + + double occ_1_coverage_low = (occ_0 + occ_1) * 0.3; + + if(occ_1 == 0 || occ_0 == 0) + { + return 0; + } + + ///Fix-attention + if(occ_1 >= occ_1_coverage_low && occ_0 >= occ_1_coverage_low) + { + return 1; + } + else if(occ_1 >= 5 && occ_0 >= 5) + { + return 1; + } + else if(occ_1 >= 3 && occ_0 >= 3 && SNPsLen >= 2) + { + int nearsnp; + int non_nearsnps; + count_nearby_snps(hap, SNPs, SNPsLen, &nearsnp, &non_nearsnps); + if(non_nearsnps > 0) + { + return 1; + } + } + + return 0; +} + + +void merge_SNP_Vectors(haplotype_evdience_alloc* hap, uint32_t* SNPs, long long SNPLen) +{ + + int8_t* vector = Get_Result_SNP_Vector((*hap)); + memset(vector, -1, Get_SNP_Vector_Length((*hap))); + hap->result_stat.occ_0 = 0; + hap->result_stat.occ_1 = 0; + hap->result_stat.occ_2 = 0; + hap->result_stat.score = SNPLen; + hap->result_stat.homopolymer_num = 0; + hap->result_stat.non_homopolymer_num = 0; + + long long snpID1; + long long j = 0; + int flag, vectorID; + for (j = 0; j < SNPLen; j++) + { + snpID1 = SNPs[j]; + vectorID = hap->snp_stat.a[snpID1].id; + vector = Get_SNP_Vector((*hap), vectorID); + if(hap->snp_stat.a[snpID1].is_homopolymer) + { + hap->result_stat.homopolymer_num++; + } + else + { + hap->result_stat.non_homopolymer_num++; + } + + if((flag = debug_add_to_result_snp_vector(hap, vector, Get_SNP_Vector_Length((*hap))))!= -1) + { + fprintf(stderr, "incompatible snp vector....\n"); + exit(0); + } + } + hap->result_stat.overlap_num = hap->result_stat.occ_0 + hap->result_stat.occ_1; +} + + +void remove_reads(haplotype_evdience_alloc* hap, uint32_t* SNPs, long long SNPsLen, overlap_region_alloc* overlap_list) +{ + long long i, j, snpID, vectorID, overlapLen; + int8_t *vector; + + for (i = 0; i < SNPsLen; i++) + { + snpID = SNPs[i]; + vectorID = hap->snp_stat.a[snpID].id; + vector = Get_SNP_Vector((*hap), vectorID); + ///hap->snp_stat[snpID].site; + + for (j = 0; j < Get_SNP_Vector_Length((*hap)); j++) + { + + if(vector[j] == 1 && overlap_list->list[j].is_match == 1) + { + //overlap_list->list[j].is_match = 0; + overlap_list->list[j].is_match = 2; + overlapLen = overlap_list->list[j].x_pos_e - overlap_list->list[j].x_pos_s + 1; + ///overlap_list->mapped_overlaps--; + overlap_list->mapped_overlaps_length -= overlapLen; + } + + /****************************may have bugs********************************/ + if( hap->snp_stat.a[snpID].site >= overlap_list->list[j].x_pos_s + && + hap->snp_stat.a[snpID].site <= overlap_list->list[j].x_pos_e) + { + overlap_list->list[j].strong = 1; + } + /****************************may have bugs********************************/ + + } + } +} + +void try_to_remove_reads(int8_t* vector, long long vectorLen, overlap_region_alloc* overlap_list, +uint32_t* SNPs, long long SNPLen, haplotype_evdience_alloc* hap) +{ + long long i, overlapLen; + long long removed_num = 0; + + for (i = 0; i < vectorLen; i++) + { + if(vector[i] == 1 && overlap_list->list[i].is_match == 1) + { + + ///overlap_list->list[i].is_match = 0; + overlap_list->list[i].is_match = 2; + overlapLen = overlap_list->list[i].x_pos_e - overlap_list->list[i].x_pos_s + 1; + ///overlap_list->mapped_overlaps--; + overlap_list->mapped_overlaps_length -= overlapLen; + removed_num++; + } + } + + + long long snpID, j; + for (i = 0; i < SNPLen; i++) + { + snpID = SNPs[i]; + ///check all overlaps + for (j = 0; j < Get_SNP_Vector_Length((*hap)); j++) + { + /****************************may have bugs********************************/ + if( hap->snp_stat.a[snpID].site >= overlap_list->list[j].x_pos_s + && + hap->snp_stat.a[snpID].site <= overlap_list->list[j].x_pos_e) + { + overlap_list->list[j].strong = 1; + } + /****************************may have bugs********************************/ + } + } +} + + +void process_repeat_snps(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list) +{ + int i; + uint32_t* snp_ids; + long long length; + + + + for (i = 0; i < hap->dp.SNP_IDs.IDs_length; i++) + { + snp_ids = hap->dp.SNP_IDs.buffer + hap->dp.SNP_IDs.IDs[i].beg; + length = hap->dp.SNP_IDs.IDs[i].end -hap->dp.SNP_IDs.IDs[i].beg + 1; + + merge_SNP_Vectors(hap, snp_ids, length); + + if(if_snp_vector_useful(hap, hap->result_stat.occ_0, hap->result_stat.occ_1, + snp_ids, length)) + { + try_to_remove_reads(Get_Result_SNP_Vector((*hap)), Get_SNP_Vector_Length((*hap)), + overlap_list, snp_ids, length, hap); + + hap->dp.SNP_IDs.IDs[i].is_remove = 1; + } + else + { + hap->dp.SNP_IDs.IDs[i].is_remove = 0; + } + } +} + + +void lable_large_indels(overlap_region_alloc* overlap_list, long long read_length, Correct_dumy* dumy, double max_ov_diff_ec) +{ + long long i, j, c_i, c_n; uint32_t operLen; uint8_t oper; + int is_delete = 0; window_list *c_idx; + for (i = 0; i < (long long)overlap_list->length; i++) + { + ///should has at least 3 windows for this overlap + if (overlap_list->list[i].is_match == 1 && overlap_list->list[i].w_list.n >= 3) + { + ///here w_list_length >= 3 + ///skip the first and last window + for (j = 1; j + 1 < (long long)(overlap_list->list[i].w_list.n); j++) + { + ///this window is not matched, it seems to have large difference + if(overlap_list->list[i].w_list.a[j].y_end == -1) + { + overlap_list->list[i].is_match = 100; + is_delete = 1; + goto end_rem; + } + + c_idx = &(overlap_list->list[i].w_list.a[j]); + c_n = c_idx->clen; + ///if there are <=2 cigar elements, skip it + if(c_n < 3) continue; + + ///skip the first and last cigar elements + for (c_i = 1; c_i + 1 < c_n; c_i++) + { + get_cigar_cell(c_idx, &(overlap_list->list[i].w_list), c_i, &oper, &operLen); + + + if(operLen <= 5) + { + continue; + } + ///>=6 bp deletion or insertion + if(oper == 2 || oper == 3) + { + overlap_list->list[i].is_match = 100; + is_delete = 1; + goto end_rem; + } + } + } + } + + end_rem:; + } + + + if(is_delete == 1) + { + long long window_start, window_end; + Window_Pool w_inf; + init_Window_Pool(&w_inf, read_length, WINDOW, (int)(1.0/max_ov_diff_ec)); + int flag = 0; + long long realLen = 0, realLen_100 = 0; + int to_recover = 0; + while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) + { + dumy->length = 0; + dumy->lengthNT = 0; + ///return overlaps that is overlaped with [window_start, window_end] + flag = get_available_fully_covered_interval(window_start, window_end, + overlap_list, dumy, &realLen, &realLen_100); + + + switch (flag) + { + case 1: ///match + break; + case 0: ///unmatch + break; + case -2: ///unmatch, and the next window also cannot match + break; + } + + ///it seems there is a long indel at the reference read itself + if(realLen == 0 && realLen_100 > 0) + { + to_recover = 1; + break; + } + } + + if(to_recover == 1) + { + for (i = 0; i < (long long)overlap_list->length; i++) + { + if (overlap_list->list[i].is_match == 100) + { + overlap_list->list[i].is_match = 1; + } + } + } + } + + + for (i = is_delete = 0; i < (long long)(overlap_list->length); i++) + { + if (overlap_list->list[i].is_match == 1) + { + overlap_list->list[i].without_large_indel = 1; + is_delete++; + } + + if (overlap_list->list[i].is_match == 100) + { + overlap_list->list[i].is_match = 1; + overlap_list->list[i].without_large_indel = 0; + is_delete++; + } + } + + // if(is_delete) radix_sort_overlap_region_dp_srt(overlap_list->list, overlap_list->list+overlap_list->length); +} + +int debug_print_snp_stat(char* name, haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, All_reads* R_INF) +{ + if(overlap_list->length > 0 && + memcmp(name, Get_NAME((*R_INF), overlap_list->list[0].x_id), + Get_NAME_LENGTH((*R_INF), overlap_list->list[0].x_id)) == 0) + { + fprintf(stderr, "\n%s, available_snp: %d\n", name, (int)hap->snp_stat.n); + int i; + for (i = 0; i < (int)hap->snp_stat.n; i++) + { + fprintf(stderr, "site: %d, occ_0: %d, occ_1: %d, occ_2: %d\n", + hap->snp_stat.a[i].site, hap->snp_stat.a[i].occ_0, + hap->snp_stat.a[i].occ_1, hap->snp_stat.a[i].occ_2); + } + } + + return 1; +} + +int generate_haplotypes_DP(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, All_reads* R_INF, long long rLen, +int force_repeat) +{ + int j, i; + int vectorID, vectorID2; + int8_t *vector, *vector2; + + + // if(hap->available_snp == 0) + if(hap->snp_stat.n == 0) + { + return 0; + } + + ///debug_print_snp_stat("m64013_190324_024932/23660629/ccs", hap, overlap_list, R_INF); + + + ///if hap->available_snp == 1, the following codes would have bugs + ///filter snps that are highly likly false + // if(hap->available_snp > 1) + if(hap->snp_stat.n > 1) + { + i = 0; + ///if a snp is very close to others, it should not be a real snp + for (j = 0; j < (int)hap->snp_stat.n/**hap->available_snp**/; j++) + { + if(j > 0 && j + 1 < (int)hap->snp_stat.n) + { + if(hap->snp_stat.a[j].site != hap->snp_stat.a[j - 1].site + 1 + && + hap->snp_stat.a[j].site + 1 != hap->snp_stat.a[j + 1].site) + { + hap->snp_stat.a[i] = hap->snp_stat.a[j]; + i++; + } + + } + else if(j == 0) + { + if(hap->snp_stat.a[j].site + 1 != hap->snp_stat.a[j + 1].site) + { + hap->snp_stat.a[i] = hap->snp_stat.a[j]; + i++; + } + } + else + { + if(hap->snp_stat.a[j].site != hap->snp_stat.a[j - 1].site + 1) + { + hap->snp_stat.a[i] = hap->snp_stat.a[j]; + i++; + } + } + } + // hap->available_snp = i; + hap->snp_stat.n = i; + } + + + + + + + int flag; + long long overlap_length, total_read, unuseful_read; + total_read = unuseful_read = 0; + ///check if any read may be conflict with others + for (i = 0; i < (long long)overlap_list->length; i++) + { + overlap_length = overlap_list->list[i].x_pos_e - overlap_list->list[i].x_pos_s + 1; + if (overlap_list->list[i].is_match == 1) + { + total_read++; + flag = -1; + for (j = 0; j < (int)hap->snp_stat.n; j++) + { + vectorID = hap->snp_stat.a[j].id; + vector = Get_SNP_Vector((*hap), vectorID); + + ///flag == -1 means there are no useful signals yet + if (flag == -1) + { + if((vector[i] == 0 || vector[i] == 1 )) + { + flag = 0; + } + }///flag == 0 means there is at least one useful signal yet + else if (flag == 0) + { + if(vector[i] != 0 && vector[i] != 1) + { + flag = 2; + } + }///flag == 0 means there is at least one useful signal first, and another unuseful signal after that + else if(flag == 2) + { + if((vector[i] == 0 || vector[i] == 1 )) + { + flag = 3; + break; + } + } + } + + + if(flag == 3) ///Fix-attention: definitely wrong + { + unuseful_read++; + for (j = 0; j < (int)hap->snp_stat.n; j++) + { + vectorID = hap->snp_stat.a[j].id; + vector = Get_SNP_Vector((*hap), vectorID); + + + + if(vector[i] == 0) + { + hap->snp_stat.a[j].occ_0--; + hap->snp_stat.a[j].occ_2++; + } + else if(vector[i] == 1) + { + hap->snp_stat.a[j].occ_1--; + hap->snp_stat.a[j].occ_2++; + } + else if(vector[i] != 2) + { + hap->snp_stat.a[j].occ_2++; + } + + + vector[i] = 2; + } + + ///this read may be unuseful + ///overlap_list->list[i].is_match = 0; + ///overlap_list->list[i].is_match = 2; + overlap_list->list[i].is_match = 4; + ///overlap_list->mapped_overlaps--; + overlap_list->mapped_overlaps_length -= overlap_length; + } + } + } + + + /*******************************DP********************************/ + init_DP_matrix(&(hap->dp), hap->snp_stat.n); + + long long equal_best = 0; + uint32_t* column; + + + + for (i = 0; i < (int)hap->snp_stat.n; i++) + { + ///vector of snp i + vectorID = hap->snp_stat.a[i].id; + vector = Get_SNP_Vector((*hap), vectorID); + hap->dp.visit[i] = 0; + hap->dp.max[i] = 1; + hap->dp.backtrack_length[i] = 0; + equal_best = 0; + column = Get_DP_Backtrack_Column(hap->dp, i); + + for (j = 0; j < i; j++) + { + ///vector of snp j + vectorID2 = hap->snp_stat.a[j].id; + vector2 = Get_SNP_Vector((*hap), vectorID2); + + ///vector is compatible with vector2 + if(calculate_distance_snp_vector(vector, vector2, Get_SNP_Vector_Length((*hap))) == 0) + { + + if(hap->dp.max[i] < hap->dp.max[j] + 1) + { + hap->dp.max[i] = hap->dp.max[j] + 1; + + column[0] = j; + equal_best = 1; + } + else if(hap->dp.max[i] == hap->dp.max[j] + 1) + { + column[equal_best] = j; + equal_best++; + } + + + } + } + + hap->dp.backtrack_length[i] = equal_best; + } + + /*******************************DP********************************/ + + uint64_t tmp_mode = 0; + + for (i = 0; i < (int)hap->snp_stat.n; i++) + { + tmp_mode = hap->dp.max[i]; + tmp_mode = tmp_mode << 32; + tmp_mode = tmp_mode | (uint64_t)(i); + hap->dp.max_for_sort[i] = tmp_mode; + } + + qsort(hap->dp.max_for_sort, hap->snp_stat.n, sizeof(uint64_t), cmp_max_DP); + + + int snpID; + ///the minmum snp_num is 1 + hap->dp.max_snp_num = 0; + hap->dp.max_score = -2; + + + for (i = 0; i < (int)hap->snp_stat.n; i++) + { + snpID = Get_Max_DP_ID(hap->dp.max_for_sort[i]); + if(hap->dp.visit[snpID] == 0) + { + hap->dp.current_snp_num = Get_Max_DP_Value(hap->dp.max_for_sort[i]); + Preorder_Merge_Advance_Repeat(snpID, hap, 0); + } + } + + ///debug_print_snp_stat("m64013_190324_024932/23660629/ccs", hap, overlap_list, R_INF); + + + //if(hap->dp.max_snp_num > 0) + if(hap->snp_stat.n > 0) + { + process_repeat_snps(hap, overlap_list); + return 1; + } + else + { + return 0; + } +} + + +inline int check_informative_site(haplotype_evdience_alloc* hap, SnpStats* snp) +{ + long long vectorID = snp->id; + int8_t *vector = Get_SNP_Vector((*hap), vectorID); + snp->occ_0 = 0; + snp->occ_1 = 0; + snp->occ_2 = 0; + long long i; + for (i = 0; i < Get_SNP_Vector_Length((*hap)); i++) + { + if(vector[i] == 0) + { + snp->occ_0++; + } + else if(vector[i] == 1) + { + snp->occ_1++; + } + else if(vector[i] == 2) + { + snp->occ_2++; + } + } + + if(snp->occ_0 >= 2 || snp->occ_1 >= 2) + { + return 1; + } + + return 0; +} + + +int generate_haplotypes_naive(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, All_reads* R_INF, long long rLen, +int force_repeat) +{ + int j, i; + + + if(hap->snp_stat.n == 0) + { + return 0; + } + + ///if hap->available_snp == 1, the following codes would have bugs + ///filter snps that are highly likly false + if(hap->snp_stat.n > 1) + { + i = 0; + ///if a snp is very close to others, it should not be a real snp + for (j = 0; j < (int)hap->snp_stat.n; j++) + { + + if(j > 0 && j + 1 < (int)hap->snp_stat.n) + { + if(hap->snp_stat.a[j].site != hap->snp_stat.a[j - 1].site + 1 + && + hap->snp_stat.a[j].site + 1 != hap->snp_stat.a[j + 1].site) + { + hap->snp_stat.a[i] = hap->snp_stat.a[j]; + i++; + } + + } + else if(j == 0) + { + if(hap->snp_stat.a[j].site + 1 != hap->snp_stat.a[j + 1].site) + { + hap->snp_stat.a[i] = hap->snp_stat.a[j]; + i++; + } + } + else + { + if(hap->snp_stat.a[j].site != hap->snp_stat.a[j - 1].site + 1) + { + hap->snp_stat.a[i] = hap->snp_stat.a[j]; + i++; + } + } + } + hap->snp_stat.n = i; + } + + + long long m; + if(hap->snp_stat.n > 0) + { + ///************************debug**************************/// + m = 0; + for (i = 0; i < (int)hap->snp_stat.n; i++) + { + if(check_informative_site(hap, &(hap->snp_stat.a[i]))) + { + hap->snp_stat.a[m] = hap->snp_stat.a[i]; + m++; + } + } + hap->snp_stat.n = m; + ///************************debug**************************/// + + + + init_DP_matrix(&(hap->dp), hap->snp_stat.n); + + for (i = 0; i < (int)hap->snp_stat.n; i++) + { + hap->dp.max_buffer[i] = i; + } + hap->dp.max_snp_num = hap->snp_stat.n; + remove_reads(hap, hap->dp.max_buffer, hap->dp.max_snp_num, overlap_list); + + return 1; + + } + else + { + return 0; + } + +} + + +void generate_haplotypes_naive_advance(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, void *km) +{ + if(hap->length == 0) return; + uint64_t k, l, i, o, *a, ii; + int64_t z; + SnpStats *s = NULL, *t = NULL; + hap->snp_srt.n = 0; + radix_sort_haplotype_evdience_id_srt(hap->list, hap->list + hap->length); + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + for (i = l, o = 0; i < k; i++) { + // if(hap->list[i].overlapSite == 55) { + // fprintf(stderr, "5555555555[M::%s::] utg%.6dl(%c), x_site::%u, x::[%u, %u), misBase::%c, occ_0::%u, occ_1::%u, occ_2::%u, snp_idx::%u\n", __func__, + // ((int32_t)(overlap_list->list[hap->list[i].overlapID].y_id)) + 1, + // "+-"[overlap_list->list[hap->list[i].overlapID].y_pos_strand], + // hap->list[i].site, overlap_list->list[hap->list[i].overlapID].x_pos_s, + // overlap_list->list[hap->list[i].overlapID].x_pos_e + 1, hap->list[i].misBase, + // s->occ_0, s->occ_1, s->occ_2, hap->list[i].overlapSite); + // } + if(hap->list[i].type!=1) continue;///mismatch + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + // if(hap->list[i].overlapID == 125 || hap->list[i].overlapID == 127) { + // fprintf(stderr, "[M::%s::] utg%.6dl(%c), x_site::%u, x::[%u, %u), misBase::%c, occ_0::%u, occ_1::%u, occ_2::%u, snp_idx::%u\n", __func__, + // ((int32_t)(overlap_list->list[hap->list[i].overlapID].y_id)) + 1, + // "+-"[overlap_list->list[hap->list[i].overlapID].y_pos_strand], + // hap->list[i].site, overlap_list->list[hap->list[i].overlapID].x_pos_s, + // overlap_list->list[hap->list[i].overlapID].x_pos_e + 1, hap->list[i].misBase, + // s->occ_0, s->occ_1, s->occ_2, hap->list[i].overlapSite); + // } + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) o++;///allels must be real + } + + // if(hap->list[l].overlapID == 125 || hap->list[l].overlapID == 127) { + // fprintf(stderr, "+++[M::%s::] utg%.6dl(%c), o::%lu\n", __func__, + // ((int32_t)(overlap_list->list[hap->list[l].overlapID].y_id)) + 1, + // "+-"[overlap_list->list[hap->list[l].overlapID].y_pos_strand], o); + // } + if(o > 0) { + o = ((uint32_t)-1) - o; + o <<= 32; o += l; + if(!km) kv_push(uint64_t, hap->snp_srt, o); + else kv_push_km(km, uint64_t, hap->snp_srt, o); + } + l = k; + } + } + // fprintf(stderr, "\nhap->snp_srt.n: %u, overlap_list->length: %lu, x_id: %u\n", + // (uint32_t)hap->snp_srt.n, overlap_list->length, overlap_list->list[0].x_id); + if (hap->snp_srt.n > 0) { + radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n);///sort by how many snps in one overlap + for (k = 0; k < hap->snp_srt.n; k++) { + o = 0; l = (uint32_t)hap->snp_srt.a[k]; + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hap->list[i].type!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) o++; + } + // if(hap->list[l].overlapID == 125 || hap->list[l].overlapID == 127) { + // fprintf(stderr, "sbsbsb[M::%s::] utg%.6dl(%c), o::%lu\n", __func__, + // ((int32_t)(overlap_list->list[hap->list[l].overlapID].y_id)) + 1, + // "+-"[overlap_list->list[hap->list[l].overlapID].y_pos_strand], o); + // } + if(o == 0) continue; + + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match == 1) overlap_list->list[ii].is_match = 2; + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hap->list[i].type==1){ + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + s->score = 1; + } else if(hap->list[i].type==0) { + z = hap->list[i].overlapSite; s = &(hap->snp_stat.a[z]); + for (z = hap->list[i].overlapSite; z >= 0; z--) { + t = &(hap->snp_stat.a[z]); + if(s->site!=t->site) break; + t->occ_0 -= hap->list[i].cov; + assert(t->occ_0 >= 1);// if(t->occ_0 < 1) fprintf(stderr, "WRONG-CORRECTION\n"); + } + } + } + } + + for (k = 0; k < hap->snp_srt.n; k++) { + o = 0; l = (uint32_t)hap->snp_srt.a[k]; + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hap->list[i].type!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(s->score == 1) { + o++; + // if(hap->list[i].overlapID == 125 || hap->list[i].overlapID == 127) { + // fprintf(stderr, "[M::%s::] utg%.6dl(%c), x_site::%u, x::[%u, %u), misBase::%c, occ_0::%u, occ_1::%u, occ_2::%u, snp_idx::%u\n", __func__, + // ((int32_t)(overlap_list->list[hap->list[i].overlapID].y_id)) + 1, + // "+-"[overlap_list->list[hap->list[i].overlapID].y_pos_strand], + // hap->list[i].site, overlap_list->list[hap->list[i].overlapID].x_pos_s, + // overlap_list->list[hap->list[i].overlapID].x_pos_e + 1, hap->list[i].misBase, + // s->occ_0, s->occ_1, s->occ_2, hap->list[i].overlapSite); + // } + } + } + ii = hap->list[l].overlapID; + // if(hap->list[l].overlapID == 125 || hap->list[l].overlapID == 127) { + // fprintf(stderr, ">>>[M::%s::] utg%.6dl(%c), o::%lu\n", __func__, + // ((int32_t)(overlap_list->list[hap->list[l].overlapID].y_id)) + 1, + // "+-"[overlap_list->list[hap->list[l].overlapID].y_pos_strand], o); + // } + if(overlap_list->list[ii].is_match == 2 && o == 0) { + overlap_list->list[ii].is_match = 1; + } + if(overlap_list->list[ii].is_match == 1 && o > 0) { + overlap_list->list[ii].is_match = 2; + } + } + } + + hap->snp_srt.n = 0; + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + if(overlap_list->list[hap->list[l].overlapID].is_match == 2) { + l = k; + continue; + } + for (i = l, o = 0; i < k; i++) { + if(hap->list[i].type!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(s->score == 1) continue; + o++; + if(!km) kv_push(uint64_t, hap->snp_srt, hap->list[i].overlapSite); + else kv_push_km(km, uint64_t, hap->snp_srt, hap->list[i].overlapSite); + } + // if(hap->list[l].overlapID == 125 || hap->list[l].overlapID == 127) { + // fprintf(stderr, "---[M::%s::] utg%.6dl(%c), o::%lu\n", __func__, + // ((int32_t)(overlap_list->list[hap->list[l].overlapID].y_id)) + 1, + // "+-"[overlap_list->list[hap->list[l].overlapID].y_pos_strand], o); + // } + hap->snp_srt.n -= o; + if(o >= 2) {///there are at least two variants at one read + radix_sort_bc64(hap->snp_srt.a + hap->snp_srt.n, hap->snp_srt.a + hap->snp_srt.n + o); + a = hap->snp_srt.a + hap->snp_srt.n; + for (i = z = 0; i < o; i++) { + if(i > 0) s = &(hap->snp_stat.a[a[i-1]]); + if(i + 1 < o) t = &(hap->snp_stat.a[a[i+1]]); + if(s && s->site + 32 > hap->snp_stat.a[a[i]].site) continue; + if(t && hap->snp_stat.a[a[i]].site + 32 > t->site) continue; + a[z] = a[i]; + z++; + } + if(z >= 2) hap->snp_srt.n += z; + } + l = k; + } + } + if (hap->snp_srt.n > 0) { + radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n); + for (k = 1, l = 0; k <= hap->snp_srt.n; ++k) { + if(k == hap->snp_srt.n || hap->snp_srt.a[k] != hap->snp_srt.a[l]) { + if(k - l >= 2) hap->snp_stat.a[hap->snp_srt.a[l]].score = 1; + } + l = k; + } + } + + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match==2) overlap_list->list[ii].is_match = 1; + if(overlap_list->list[ii].is_match==1) { + for (i = l; i < k; i++) { + if(hap->list[i].type==1 || hap->list[i].type==0) { + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->score == 1 && (!(s->occ_0 < 2 || s->occ_1 < 2))) { + overlap_list->list[ii].strong = 1; + if(hap->list[i].type==1) { + overlap_list->list[ii].is_match = 2; + overlap_list->mapped_overlaps_length -= + overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; + break; + } + } + } + + } + } + l = k; + } + } + + // for (i = k = 0; i < overlap_list->length; i++) { + // if(overlap_list->list[i].is_match == 2) k++; + // } + // for (i = l = 0; i < hap->snp_stat.n; i++) { + // s = &(hap->snp_stat.a[i]); + // if(s->score == 1 && (!(s->occ_0 < 2 || s->occ_1 < 2))) l++; + // } + // fprintf(stderr, "#trans ovlp: %lu, # snp:: %lu\n", k, l); + +} + +void prt_sub_read(char *str, uint64_t str_l, uint64_t site, uint64_t win) +{ + uint64_t k, s, e; + s = ((site >= win)?(site-win):(0)); + e = (((site+win+1) <= str_l)?(site+win+1):(str_l)); + fprintf(stderr, "[M::%s-site::%lu] [%lu, %lu)\n", __func__, site, s, e); + + for (k = s; k < site; k++) fprintf(stderr, "%c", str[k]); + fprintf(stderr, "[%c]", str[k++]); + for (; k < e; k++) fprintf(stderr, "%c", str[k]); + + fprintf(stderr, "\n"); +} + +void prt_sub_cigar(overlap_region* z, uint64_t str_l, uint64_t site, uint64_t win) +{ + uint64_t k, s, e, ci, xi, yi, ws, we, os, oe, ovlp; uint32_t cl; uint16_t c; bit_extz_t ez; char cm[4]; + cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; + s = ((site >= win)?(site-win):(0)); + e = (((site+win+1) <= str_l)?(site+win+1):(str_l)); + + fprintf(stderr, "[M::%s-site::%lu] [%lu, %lu)\n", __func__, site, s, e); + + for (k = 0; k < z->w_list.n; k++) { + set_bit_extz_t(ez, (*z), k); ci = 0; xi = ez.ts; yi = ez.ps; + while (ci < ez.cigar.n) { + ws = xi; + ci = pop_trace(&(ez.cigar), ci, &c, &cl); + if(c!=2) xi += cl; + if(c!=3) yi += cl; + we = xi; + + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + + if(c != 2) { + if(!ovlp) continue; + } else {///ws == we + if(ws < s || ws >= e) continue; + ovlp = cl; + } + + fprintf(stderr, "%lu%c[%lu,%lu)", ovlp, cm[c], os, oe); + } + fprintf(stderr, "\n"); + } +} + +#define is_st_bs(s, rr, mm) (((mm) != ((uint64_t)-1)) && (((s).overlap_num + mm) >= ((s).occ_0)) && ((((s).occ_0*(rr) + (s).overlap_num)) >= ((s).occ_0))) + +void generate_haplotypes_naive_HiFi(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, double up, UC_Read* g_read, uint64_t multi_check, double st_rate, uint64_t st_max) +{ + // fprintf(stderr, "[M::%s::] Done\n", __func__); + if(hap->length == 0) return; + uint64_t k, l, i, o, *a, ii, m_snp_stat, m_list, m_off; + int64_t z; + SnpStats *s = NULL, *t = NULL; + + for (k = 1, l = 0, i = m_snp_stat = m_list = 0; k <= hap->snp_stat.n; ++k) {///filter snps + if(k == hap->snp_stat.n || hap->snp_stat.a[k].site != hap->snp_stat.a[l].site) { + if((l > 0) && (hap->snp_stat.a[l].site == (hap->snp_stat.a[l-1].site + 1))) { + l = k; continue; + } + if((k < hap->snp_stat.n) && ((hap->snp_stat.a[l].site+1) == hap->snp_stat.a[k].site)) { + l = k; continue; + } + + for (; i < hap->length && hap->list[i].site != hap->snp_stat.a[l].site; i++); + assert(i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site); + m_off = l - m_snp_stat; + for (; i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site; i++) { + assert(hap->list[i].overlapSite>=l && hap->list[i].overlapSite < k); + // assert(hap->snp_stat.a[hap->list[i].overlapSite].site==hap->list[i].site); + hap->list[m_list] = hap->list[i]; hap->list[m_list++].overlapSite -= m_off; + } + + for (; l < k; l++) hap->snp_stat.a[m_snp_stat++] = hap->snp_stat.a[l]; + } + } + hap->snp_stat.n = m_snp_stat; hap->length = m_list; + if(hap->snp_stat.n == 0 || hap->length == 0) return; + + // for (k = 0; k < hap->snp_stat.n; k++) { + // s = &(hap->snp_stat.a[k]); if(s->site != 1502) continue; + // fprintf(stderr, "[M::%s] site::%u, occ_0::%u, occ_1::%u, occ_2::%u, is_homopolymer::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_2, s->is_homopolymer); + // prt_sub_read(g_read->seq, g_read->length, s->site, 25); + // for (i = 0; i < overlap_list->length; i++) { + // if(/**overlap_list->list[i].is_match == 1 &&**/ overlap_list->list[i].x_pos_s <= s->site && s->site <= overlap_list->list[i].x_pos_e) { + // fprintf(stderr, "%.*s\tis_match::%u\tid::%u\n", (int)Get_NAME_LENGTH(R_INF, overlap_list->list[i].y_id), Get_NAME(R_INF, overlap_list->list[i].y_id), overlap_list->list[i].is_match, overlap_list->list[i].y_id); + // } + // } + // } + + + hap->snp_srt.n = 0; + radix_sort_haplotype_evdience_id_srt(hap->list, hap->list + hap->length); + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + for (i = l, o = 0; i < k; i++) { + if(hh_tp(hap->list[i])!=1) continue;///mismatch + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + assert(s->site == hap->list[i].site); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(is_st_bs((*s), st_rate, st_max)) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { + // fprintf(stderr, "[M::%s] site::%u, occ_0::%u, occ_1::%u, occ_2::%u, is_homopolymer::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_1, s->is_homopolymer); + o++;///allels must be real + } + } + + // if(overlap_list->list[hap->list[l].overlapID].y_id == 1740) { + // fprintf(stderr, "str1074[M::%s-id::%u] o->%lu(%c), l::%lu\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, o, "+-"[overlap_list->list[hap->list[l].overlapID].y_pos_strand], l); + // for (i = l; i < k; i++) { + // if(hh_tp(hap->list[i])!=1) continue;///mismatch + // s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + // assert(s->site == hap->list[i].site); + // if(s->occ_0 < 2 || s->occ_1 < 2) continue; + // if(is_st_bs((*s), st_rate, st_max)) continue; + // if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { + // fprintf(stderr, "[M::%s] site::%u, occ_0::%u, occ_1::%u, occ_2::%u, is_homopolymer::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_1, s->is_homopolymer); + // // prt_sub_read(g_read->seq, g_read->length, s->site, 50); + // } + // } + // } + // else { + // fprintf(stderr, "[M::%s-id::%u] o->%lu(%c), l::%lu\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, o, "+-"[overlap_list->list[hap->list[l].overlapID].y_pos_strand], l); + // } + // else { + // for (i = l, o = 0; i < k; i++) { + // if(hh_tp(hap->list[i])!=0) continue;///mismatch + // s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + // assert(s->site == hap->list[i].site); + // if(s->occ_0 < 2 || s->occ_1 < 2) continue; + // if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { + // if(s->site == 7878 || s->site == 9682) { + + // fprintf(stderr, "***[M::%s] site::%u, rid::%u\t%.*s\n", __func__, s->site, overlap_list->list[hap->list[l].overlapID].y_id, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[hap->list[l].overlapID].y_id), + // Get_NAME(R_INF, overlap_list->list[hap->list[l].overlapID].y_id)); + // prt_sub_cigar(&(overlap_list->list[hap->list[l].overlapID]), g_read->length, s->site, 50); + // } + // // o++;///allels must be real + // // fprintf(stderr, "[M::%s] site::%u, occ_0::%u, occ_1::%u, occ_2::%u, is_homopolymer::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_1, s->is_homopolymer); + // // prt_sub_read(g_read->seq, g_read->length, s->site, 50); + // } + // } + // } + + // if(overlap_list->list[hap->list[l].overlapID].y_id == 3626) { + // fprintf(stderr, "***0***[M::%s-id::%u] o->%lu\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, o); + // } + + if(o > 0) { + o = ((uint32_t)-1) - o; + o <<= 32; o += l; + kv_push(uint64_t, hap->snp_srt, o); + } + l = k; + } + } + + // fprintf(stderr, "[M::%s] snp_srt.n->%lu\n", __func__, ((uint64_t)hap->snp_srt.n)); + + if (hap->snp_srt.n > 0) { + radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n);///sort by how many snps in one overlap + for (k = 0; k < hap->snp_srt.n; k++) { + o = 0; l = (uint32_t)hap->snp_srt.a[k]; + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hh_tp(hap->list[i])!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(is_st_bs((*s), st_rate, st_max)) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { + o++; + // if(overlap_list->list[hap->list[l].overlapID].y_id == 20835) { + // fprintf(stderr, "[M::%s-id::%u] occ_0->%u, occ_1->%u, occ_2->%u, site->%u\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, s->occ_0, s->occ_1, s->occ_2, s->site); + // } + } + } + // if(overlap_list->list[hap->list[l].overlapID].y_id == 1740) { + // fprintf(stderr, "srt[M::%s-id::%u] o->%lu, l->%lu\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, o, l); + // } + if(o == 0) continue; + + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match == 1) overlap_list->list[ii].is_match = 2; + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hh_tp(hap->list[i])==1){ + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + s->score = 1; + } ///else if((hh_tp(hap->list[i])==0) && (o>=(overlap_list->list[ii].align_length*up))) { + else if(hh_tp(hap->list[i])==0) { + ///not real allels + z = hap->list[i].overlapSite; s = &(hap->snp_stat.a[z]); + for (z = hap->list[i].overlapSite; z >= 0; z--) { + t = &(hap->snp_stat.a[z]); + if(s->site!=t->site) break; + // if(t->site == 14217) { + // fprintf(stderr, "[M::%s]\tsite::%u\tn0::%u\tn1::%u\to::%lu\t%.*s\n", __func__, t->site, t->occ_0, t->occ_1, o, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id)); + // } + t->occ_0 -= hap->list[i].cov; + assert(t->occ_0 >= 1); + if((st_max != ((uint64_t)-1)) && (overlap_list->list[ii].y_pos_strand == 0)) { + t->overlap_num -= hap->list[i].cov; + assert(t->overlap_num >= 1); + } + } + } + } + } + + for (k = 0; k < hap->snp_srt.n; k++) {///sorted by how many allels in each overlap; more -> less + o = 0; l = (uint32_t)hap->snp_srt.a[k]; + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hh_tp(hap->list[i])!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(is_st_bs((*s), st_rate, st_max)) continue; + if(s->score == 1) o++; + } + ii = hap->list[l].overlapID; + ///for HiFi, do not flip trans to cis + // if(overlap_list->list[ii].is_match == 2 && o == 0) { + // overlap_list->list[ii].is_match = 1; + // } + if(overlap_list->list[ii].is_match == 1 && o > 0) { + overlap_list->list[ii].is_match = 2; + } + } + + + for (k = 1, l = 0; k <= hap->length; ++k) { ///reset snp_stat + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match==1) { + for (i = l; i < k; i++) { + if(hh_tp(hap->list[i])==1) { + hap->snp_stat.a[hap->list[i].overlapSite].score = -1; + } + } + } + l = k; + } + } + } + + + if(multi_check) { + hap->snp_srt.n = 0; + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + if(overlap_list->list[hap->list[l].overlapID].is_match == 2) { + l = k; + continue; + } + for (i = l, o = 0; i < k; i++) { + if(hh_tp(hap->list[i])!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(is_st_bs((*s), st_rate, st_max)) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) continue; + if(s->score == 1) continue; + o++; + kv_push(uint64_t, hap->snp_srt, hap->list[i].overlapSite); + } + // if(overlap_list->list[hap->list[l].overlapID].y_id == 317 || overlap_list->list[hap->list[l].overlapID].y_id == 287) { + // fprintf(stderr, "***2***[M::%s-id::%u] o->%lu\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, o); + // } + hap->snp_srt.n -= o; + ///there are at least two variants at one read + if(o>=(overlap_list->list[hap->list[l].overlapID].align_length*up)) { + radix_sort_bc64(hap->snp_srt.a + hap->snp_srt.n, hap->snp_srt.a + hap->snp_srt.n + o); + a = hap->snp_srt.a + hap->snp_srt.n; + for (i = z = 0; i < o; i++) { + if(i > 0) s = &(hap->snp_stat.a[a[i-1]]); + if(i + 1 < o) t = &(hap->snp_stat.a[a[i+1]]); + if(s && s->site + 32 > hap->snp_stat.a[a[i]].site) continue; + if(t && hap->snp_stat.a[a[i]].site + 32 > t->site) continue; + a[z] = a[i]; + z++; + } + if(z >= 2) hap->snp_srt.n += z; + } + l = k; + } + } + if (hap->snp_srt.n > 0) { + radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n); + for (k = 1, l = 0; k <= hap->snp_srt.n; ++k) { + if(k == hap->snp_srt.n || hap->snp_srt.a[k] != hap->snp_srt.a[l]) { + if(k - l >= 2) hap->snp_stat.a[hap->snp_srt.a[l]].score = 1; + } + l = k; + } + } + } + + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match==2) { + overlap_list->list[ii].strong = 1; + overlap_list->mapped_overlaps_length -= + overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; + } else if(overlap_list->list[ii].is_match==1) { + for (i = l; i < k; i++) { + if(hh_tp(hap->list[i])==1 || hh_tp(hap->list[i])==0) { + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->site == 267) { + fprintf(stderr, "[M::%s::]\tsite::%u\tocc0::%u\tocc1::%u\tocc2::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_2); + } + if(s->score == 1 && (!(s->occ_0 < 2 || s->occ_1 < 2)) && (!(is_st_bs((*s), st_rate, st_max)))) { + overlap_list->list[ii].strong = 1; + if(hh_tp(hap->list[i])==1) { + overlap_list->list[ii].is_match = 2; + overlap_list->mapped_overlaps_length -= + overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; + break; + } + } + } + + } + } + l = k; + } + } +} + +typedef struct { + uint64_t *ack; + uint64_t ack_w64n;///how many words(64) required + uint64_t ack_w64m;///mask and max value + uint64_t ack_w64_sft;///how many bits each cell + uint64_t ack_w64_sft_w;///how many cells in each word(64) +} srt_on_ck_t; + +typedef struct { + uint64_t an, kan; + uint64_t *awk; + uint64_t *ap; + srt_on_ck_t ack; + + uint64_t kn; + uint64_t *ik; + uint64_t ma, mk; + uint64_t mk_srt; + + // uint32_t *sn; + // uint32_t *sa; + uint64_t sa_tot; + uint64_t sn_tot; + asg32_v *b32; +} srt_on_t; + +#define g_nxt_az(za, zi) ((uint32_t)((za).ap[(zi)])) +#define g_pre_az(za, zi) (((za).ap[(zi)])>>32) +#define g_is_pre_kid_az(za, zi) ((g_pre_az((za), (zi)) >= (za).an) && (g_pre_az((za), (zi)) != ((uint32_t)-1))) +#define g_pre_kid_az(za, zi) (g_pre_az((za), (zi)) - (za).an) + + +#define g_w_az(za, zi) ((uint32_t)((za).awk[(zi)])) +#define g_hid_az(za, zi) (((za).awk[(zi)]>>32)&((uint64_t)(0x7fffffffu))) +#define g_of_az(za, zi) (((za).awk[(zi)]>>63)) + +#define s_nxt_az(za, zi, nid) do {\ + (za).ap[(zi)] >>= 32;\ + (za).ap[(zi)] <<= 32;\ + (za).ap[(zi)] |= (nid);\ +} while (0) + +#define s_pre_az(za, zi, pid, kid) do {\ + (za).ap[(zi)] <<= 32;\ + (za).ap[(zi)] >>= 32;\ + if((pid) < (za).an) {\ + (za).ap[(zi)] |= (((uint64_t)(pid))<<32);\ + } else {\ + (za).ap[(zi)] |= (((uint64_t)(kid+(za).an))<<32);\ + }\ +} while (0) + +#define s_of_az(za, zi, zf) do {\ + (za).awk[(zi)] <<= 1;\ + (za).awk[(zi)] >>= 1;\ + (za).awk[(zi)] |= (((uint64_t)(zf))<<63);\ +} while (0) + +/** +#define s_uuse_az(za, zi) do {\ + (za).ap[(zi)] = ((za).an<<32)|((uint64_t)(0xffffffff));\ +} while (0) + +#define is_uuse_az(za, zi) ((za).ap[(zi)] == ((uint64_t)(0xffffffff))) +**/ + +#define s_pop_az(za, zi) do {\ + (za).ap[(zi)] = ((uint64_t)-1);\ +} while (0) + +#define is_pop_az(za, zi) ((za).ap[(zi)] == ((uint64_t)-1)) + +void init_srt_on_ck_t(srt_on_ck_t *zc, uint64_t m0, uint64_t tot_n) +{ + uint64_t k, m1; + for (m1 = m0, k = 0; m1; m1 >>= 1, k++); + if(k <= 0) k = 1; + if(k > 64) k = 64; + zc->ack_w64m = (((uint64_t)1)<ack_w64_sft = k; + zc->ack_w64_sft_w = 64/k; + zc->ack = NULL; + zc->ack_w64n = (tot_n/zc->ack_w64_sft_w) + ((tot_n%zc->ack_w64_sft_w)?(1):(0)); + + // fprintf(stderr, "+0+[M::%s] ack_w64m::%lu, ack_w64_sft::%lu, ack_w64_sft_w::%lu, ack_w64n::%lu\n", __func__, zc->ack_w64m, zc->ack_w64_sft, zc->ack_w64_sft_w, zc->ack_w64n); +} + +inline void set_srt_on_ck_t(srt_on_ck_t *zc, uint64_t oid, uint64_t w) +{ + uint64_t k = oid/zc->ack_w64_sft_w; + uint64_t m = (zc->ack_w64m << (64 - (((oid%zc->ack_w64_sft_w) + 1)*zc->ack_w64_sft))); + uint64_t mw = (w << (64 - (((oid%zc->ack_w64_sft_w) + 1)*zc->ack_w64_sft))); + zc->ack[k] &= (~m); zc->ack[k] |= mw; +} + +inline uint64_t get_srt_on_ck_t(srt_on_ck_t *zc, uint64_t oid) +{ + return ((zc->ack[oid/zc->ack_w64_sft_w] >> (64 - (((oid%zc->ack_w64_sft_w) + 1)*zc->ack_w64_sft))) & zc->ack_w64m); +} + +/// init_srt_on_t(&buf, 64, overlap_list->length, &bs); +void init_srt_on_t(asg64_v *in, uint64_t max_k, uint64_t an, srt_on_t *z) +{ + uint64_t tot = 0, k; + z->an = an; z->kn = max_k + 1; z->mk = max_k; z->ma = 0; z->kan = 0; z->mk_srt = 1; in->n = 0; + + // fprintf(stderr, "+0+[M::%s] max_k::%lu, an::%lu\n", __func__, max_k, an); + + // uint64_t ack_w64n; + // uint64_t ack_w64m; + // uint64_t ack_w64_sft; + init_srt_on_ck_t(&(z->ack), z->kn, z->an); + + // fprintf(stderr, "+1+[M::%s] max_k::%lu, an::%lu\n", __func__, max_k, an); + + tot = z->an + z->an + z->kn + z->ack.ack_w64n; + kv_resize(uint64_t, *in, tot); + + z->ap = in->a; + z->awk = in->a + z->an; + z->ik = in->a + z->an + z->an; + z->ack.ack = in->a + z->an + z->an + z->kn; + + // if(!add_set) memset(z->ap, -1, sizeof((*(z->ap)))*z->an); + memset(z->ap, -1, sizeof((*(z->ap)))*z->an); + + // fprintf(stderr, "+2+[M::%s] max_k::%lu, an::%lu\n", __func__, max_k, an); + memset(z->ack.ack, -1, sizeof((*(z->ack.ack)))*z->ack.ack_w64n); + // fprintf(stderr, "+3+[M::%s] max_k::%lu, an::%lu\n", __func__, max_k, an); + for (k = 0; k < z->an; k++) { + ///[63, 64)::set + ///[32, 63)::index + ///[0,32)::weight + z->awk[k] = 0x7fffffffu; z->awk[k] <<= 32; + // if(add_set) s_uuse_az(*z, k); ///z->ap[k] = ((an<<32)|((uint64_t)((uint32_t)-1))); + } + // fprintf(stderr, "+4+[M::%s] max_k::%lu, an::%lu\n", __func__, max_k, an); + + for (k = 0; k < z->kn; k++) z->ik[k] = (uint32_t)-1; + + // fprintf(stderr, "+5+[M::%s] max_k::%lu, an::%lu\n", __func__, max_k, an); +} + +void push_srt_k(srt_on_t *z, uint64_t oid, uint64_t w, uint8_t kp_srt) +{ + uint64_t kz = w, nxt, k; + if(w >= z->mk) kz = z->mk;///normalization + if(z->ik[kz] == ((uint32_t)-1)) {///empty k-lst + z->ik[kz] = oid; ///first oid in this list + s_pre_az(*z, oid, ((uint32_t)-1), kz); + // z->ap[oid] = (uint64_t)-1; + } else { + if((kz < z->mk) || (kp_srt == 0)) { + nxt = z->ik[kz];///0-th ovlp within the k-lst + z->ik[kz] = oid; + + s_nxt_az((*z), oid, nxt); + s_pre_az((*z), nxt, oid, ((uint32_t)-1)); + s_pre_az(*z, oid, ((uint32_t)-1), kz); + } else { + for (k = z->ik[kz], nxt = ((uint32_t)-1); (k != ((uint32_t)-1)) && (w < g_w_az((*z), k)); k = g_nxt_az((*z), k)) { + nxt = k; + } + if((k != ((uint32_t)-1))) { + assert((g_w_az((*z), k) <= w)); + nxt = g_pre_az((*z), k); + assert((nxt >= z->an) || (g_nxt_az((*z), nxt) == k));///point to a k-lst or another overlap + + if(nxt < z->an) { + s_nxt_az((*z), nxt, oid); + } else { + z->ik[kz] = oid; + } + s_pre_az((*z), oid, nxt, kz); + s_nxt_az((*z), oid, k); + s_pre_az((*z), k, oid, ((uint32_t)-1)); + } else {//tail + if(nxt != ((uint32_t)-1)) { + s_nxt_az((*z), nxt, oid); + } else { + z->ik[kz] = oid; + } + s_pre_az((*z), oid, nxt, kz); + } + } + } + set_srt_on_ck_t(&(z->ack), oid, kz); + if(w > z->ma) z->ma = w; + + // fprintf(stderr, "+3+[M::%s] kz::%lu, gkz::%lu\n", __func__, kz, get_srt_on_ck_t(&(z->ack), oid)); +} + +void delete_srt_on_t(srt_on_t *z, uint64_t oid) +{ + uint64_t na, nb, kp; + na = g_pre_az((*z), oid); + nb = g_nxt_az((*z), oid); + kp = g_pre_kid_az((*z), oid); + if(is_pop_az((*z), (oid))) return; + z->kan--; + s_pop_az((*z), (oid)); + // if(oid == 249) { + // fprintf(stderr, "-0-[M::%s] oid::%lu, w::%u, na::%lu, nb::%lu, kp::%lu\n", + // __func__, oid, g_w_az((*z), oid), na, nb, kp); + // } + if((na < z->an) && (nb < z->an)) { + s_nxt_az((*z), na, nb); + s_pre_az((*z), nb, na, ((uint32_t)-1)); + // if(oid == 249) { + // fprintf(stderr, "-1-[M::%s] oid::%lu, w::%u, na::%lu, nb::%lu, kp::%lu\n", + // __func__, oid, g_w_az((*z), oid), na, nb, kp); + // } + return; + } + + if(na < z->an) {///nb == ((uint32_t)-1) + s_nxt_az((*z), na, nb); + kp = ((uint32_t)-1); + // if(oid == 249) { + // fprintf(stderr, "-2-[M::%s] oid::%lu, w::%u, na::%lu, nb::%lu, kp::%lu\n", + // __func__, oid, g_w_az((*z), oid), na, nb, kp); + // } + } else {///na point to a klst + z->ik[kp] = nb; + na = ((uint32_t)-1); + // if(oid == 249) { + // fprintf(stderr, "-3-[M::%s] oid::%lu, w::%u, na::%lu, nb::%lu, kp::%lu\n", + // __func__, oid, g_w_az((*z), oid), na, nb, kp); + // } + // s_pre_az((*z), nb, ((uint32_t)-1), kp); + // w = g_w_az((*z), oid); + // if(w >= z->mk) w = z->mk; + + // fprintf(stderr, "[M::%s] oid::%lu, w::%lu, z->ik[%lu]::%lu, z->mk::%lu, nb::%lu, na::%lu, w[%lu]::%u\n", __func__, oid, w, w, z->ik[w], z->mk, nb, na, + // nb, (uint32_t)((nb != ((uint32_t)-1)?g_w_az((*z), nb):0))); + // assert(z->ik[w] == oid); + // z->ik[w] = nb; + } + + if(nb != ((uint32_t)-1)) {///na == ((uint32_t)-1) + s_pre_az((*z), nb, na, kp); + // if(oid == 249) { + // fprintf(stderr, "-4-[M::%s] oid::%lu, w::%u, na::%lu, nb::%lu, kp::%lu\n", + // __func__, oid, g_w_az((*z), oid), na, nb, kp); + // } + } +} + +uint64_t pop_srt_k(srt_on_t *z, uint64_t* oid, uint64_t* hid, uint64_t* w) +{ + (*oid) = (*hid) = (*w) = (uint64_t)-1; + if(!(z->kan)) return 0;///all overlaps have been pop + uint64_t k, mw = z->ma, nid = ((uint32_t)-1), w0, wk0, wp, srt; + if(mw >= z->mk) mw = z->mk; + for (; (mw > 0) && (z->ik[mw] == ((uint32_t)-1)); --mw); + if(!mw) { + z->ma = mw; + return 0; + } + + // fprintf(stderr, "[M::%s] mw::%lu, z->mk::%lu, z->mk_srt::%lu, z->ma::%lu\n", __func__, mw, z->mk, z->mk_srt, z->ma); + + ///z->ik[mw] != ((uint32_t)-1)) + if((mw < z->mk) || (z->mk_srt)) { + nid = z->ik[mw]; + delete_srt_on_t(z, nid); + } else { + ///unsorted by weight + for (k = z->ik[mw], w0 = 0, wp = wk0 = ((uint32_t)-1), srt = 1; k != ((uint32_t)-1); k = g_nxt_az((*z), k)) { + if(w0 < (g_w_az((*z), k))) { + w0 = g_w_az((*z), k); wk0 = k; + } + + if((srt) && (wp < g_w_az((*z), k))) srt = 0; + wp = g_w_az((*z), k); + + if(w0 == z->ma) { + k = g_nxt_az((*z), k);///for srt + break; + } + } + if(k != ((uint32_t)-1)) srt = 0; + assert(wk0 != ((uint32_t)-1)); + nid = wk0; + delete_srt_on_t(z, nid); + if(z->mk_srt == 0) z->mk_srt = srt; + } + z->ma = g_w_az((*z), nid); + + (*oid) = nid; + (*hid) = g_hid_az((*z), nid); + (*w) = g_w_az((*z), nid); + return 1; +} + +///insert_srt_on_t(&bs, hap->list[l].overlapID, o, l); +void insert_srt_on_t(srt_on_t *z, uint64_t oid, uint64_t w, uint64_t hid) +{ + z->awk[oid] = (hid&((uint64_t)(0x7fffffffu))); z->awk[oid] <<= 32; z->awk[oid] |= w; + push_srt_k(z, oid, w, 1); z->kan++; + if(z->ma < w) z->ma = w; +} + +void adjust_srt_on_t(srt_on_t *z, uint64_t oid) +{ + uint64_t w = g_w_az((*z), oid), nw, k; + if(w >= z->mk) {///nothing to delete + if(z->mk_srt) { + for (k = g_nxt_az((*z), oid); k != ((uint32_t)-1); k = g_nxt_az((*z), k)) { + nw = g_w_az((*z), k); + if(nw >= z->mk) { + if(nw > w) z->mk_srt = 0; + break; + } + } + } + + if(z->mk_srt) { + for (k = g_pre_az((*z), oid); k < z->an; k = g_pre_az((*z), k)) { + nw = g_w_az((*z), k); + if(nw >= z->mk) { + if(nw < w) z->mk_srt = 0; + break; + } + } + } + return; + } + + delete_srt_on_t(z, oid); z->kan++; + push_srt_k(z, oid, w, 1); +} + +void adjust_srt_on_t_obs(srt_on_t *z, uint64_t oid) +{ + uint64_t w = g_w_az((*z), oid), nw, k, wk0 = get_srt_on_ck_t(&(z->ack), oid); + if(w > z->ma) z->ma = w; + if((w < z->mk) && (w == wk0)) return;///no change + if((w >= z->mk) && (wk0 == z->mk)) {///just move within z->mk-th-list + if(z->mk_srt) { + for (k = g_nxt_az((*z), oid); k != ((uint32_t)-1); k = g_nxt_az((*z), k)) { + nw = g_w_az((*z), k); + if(nw >= z->mk) { + if(nw > w) z->mk_srt = 0; + break; + } + } + } + + if(z->mk_srt) { + for (k = g_pre_az((*z), oid); k < z->an; k = g_pre_az((*z), k)) { + nw = g_w_az((*z), k); + if(nw >= z->mk) { + if(nw < w) z->mk_srt = 0; + break; + } + } + } + + return; + } + + delete_srt_on_t(z, oid); z->kan++; + push_srt_k(z, oid, w, 0); + if((w >= z->mk) && (z->mk_srt)) { + k = g_nxt_az((*z), oid); + if(k != ((uint32_t)-1)) { + nw = g_w_az((*z), k); + if(nw > w) z->mk_srt = 0; + } + } +} + +#define g_sn_az(za, zi) (((za).b32->a[(zi)+1]-(za).b32->a[(zi)])) +#define g_sa_az(za, zi) (((za).b32->a+(za).sn_tot)+(za).b32->a[(zi)]) + +inline int8_t is_plus_sc_obs(SnpStats *s, double st_rate, uint64_t st_max) +{ + ///if(s->score < 0) return 0; + if(s->occ_0 < 2 || s->occ_1 < 2 || s->occ_0 < asm_opt.s_hap_cov || s->occ_1 < asm_opt.infor_cov) return -1; + if(is_st_bs((*s), st_rate, st_max)) return 0; + return 1; +} + +inline uint8_t is_plus_sc(SnpStats *s, double st_rate, uint64_t st_max) +{ + ///if(s->score < 0) return 0; + if(s->occ_0 < 2 || s->occ_1 < 2 || s->occ_0 < asm_opt.s_hap_cov || s->occ_1 < asm_opt.infor_cov) return 0; + if(is_st_bs((*s), st_rate, st_max)) return 0; + return 1; +} + +///sn_tot: how many snps in total +inline void insert_srt_on_t_i32(srt_on_t *z, haplotype_evdience *a, uint64_t an, asg32_v *bu, SnpStats *sn_a, uint64_t sn_tot, double st_rate, uint64_t st_max) +{ + uint64_t k, oid, sid, sa_tot0, ss; + uint32_t *snp_a, snp_n, snp_k; + uint32_t *sn = NULL; + z->sn_tot = sn_tot + 1; ///how many snps in total + z->sa_tot = 0; ///how many overlaps covered by these snps + + kv_resize(uint32_t, *bu, z->sn_tot); + sn = bu->a; z->b32 = bu; + memset(sn, 0, sizeof((*(sn)))*z->sn_tot); + + for (k = 0; k < an; k++) { + if(hh_tp(a[k]) != 1) continue; + oid = a[k].overlapID; + if(g_w_az((*z), oid) == 0) continue; + + sid = a[k].overlapSite; + if(!is_plus_sc(&sn_a[sid], st_rate, st_max)) continue; + + sn[sid]++; z->sa_tot++; + } + + kv_resize(uint32_t, *bu, (z->sn_tot + z->sa_tot)); + sn = bu->a; ///z->sa = bu->a + z->sn_tot; + for (k = sa_tot0 = 0; k < z->sn_tot; k++) { + ss = sn[k]; + sn[k] = sa_tot0; sa_tot0 += ss; + if(ss > 0) { + // fprintf(stderr, "[M::%s] ss::%lu, sa_tot0::%lu, z->sa_tot::%lu, k::%lu, z->sn_tot::%lu, idx::%lu\n", __func__, ss, sa_tot0, z->sa_tot, k, z->sn_tot, + // ((*z).sn_tot)+(*z).b32->a[(k)]); + + g_sa_az(*z, k)[ss-1] = 0;//iter + } + } + assert(sa_tot0 == z->sa_tot); + + + for (k = sa_tot0 = 0; k < an; k++) { + if(hh_tp(a[k]) != 1) continue; + oid = a[k].overlapID; + if(g_w_az((*z), oid) == 0) continue; + sid = a[k].overlapSite; + if(!is_plus_sc(&sn_a[sid], st_rate, st_max)) continue; + + sa_tot0++; + snp_a = g_sa_az(*z, sid); + snp_n = g_sn_az(*z, sid); + assert(snp_n); + snp_k = snp_a[snp_n-1]; + snp_a[snp_k] = oid; snp_k++; + if(snp_k != snp_n) snp_a[snp_n-1]++; + } + z->b32 = bu; z->b32->n = z->sa_tot + z->sn_tot; + assert(sa_tot0 == z->sa_tot); +} + +///sn_tot: how many snps in total +inline void insert_srt_on_t_i32_obs(srt_on_t *z, haplotype_evdience *a, uint64_t an, asg32_v *bu, SnpStats *sn_a, uint64_t sn_tot, double st_rate, uint64_t st_max) +{ + uint64_t k, oid, sid, sa_tot0, ss; + uint32_t *snp_a, snp_n, snp_k; + uint32_t *sn = NULL; int8_t zf; + z->sn_tot = sn_tot + 1; ///how many snps in total + z->sa_tot = 0; ///how many overlaps covered by these snps + + kv_resize(uint32_t, *bu, z->sn_tot); + sn = bu->a; z->b32 = bu; + memset(sn, 0, sizeof((*(sn)))*z->sn_tot); + + for (k = 0; k < an; k++) { + if(hh_tp(a[k]) != 1) continue; + oid = a[k].overlapID; + // if(g_w_az((*z), oid) == 0) continue; + sid = a[k].overlapSite; + zf = is_plus_sc_obs(&sn_a[sid], st_rate, st_max); + if(zf < 0) continue; + + sn[sid]++; z->sa_tot++; + } + + kv_resize(uint32_t, *bu, (z->sn_tot + z->sa_tot)); + sn = bu->a; ///z->sa = bu->a + z->sn_tot; + for (k = sa_tot0 = 0; k < z->sn_tot; k++) { + ss = sn[k]; + sn[k] = sa_tot0; sa_tot0 += ss; + if(ss > 0) { + // fprintf(stderr, "[M::%s] ss::%lu, sa_tot0::%lu, z->sa_tot::%lu, k::%lu, z->sn_tot::%lu, idx::%lu\n", __func__, ss, sa_tot0, z->sa_tot, k, z->sn_tot, + // ((*z).sn_tot)+(*z).b32->a[(k)]); + + g_sa_az(*z, k)[ss-1] = 0;//iter + } + } + assert(sa_tot0 == z->sa_tot); + + + for (k = sa_tot0 = 0; k < an; k++) { + if(hh_tp(a[k]) != 1) continue; + oid = a[k].overlapID; + // if(g_w_az((*z), oid) == 0) continue; + sid = a[k].overlapSite; + zf = is_plus_sc_obs(&sn_a[sid], st_rate, st_max); + if(zf < 0) continue; + + sa_tot0++; + snp_a = g_sa_az(*z, sid); + snp_n = g_sn_az(*z, sid); + assert(snp_n); + snp_k = snp_a[snp_n-1]; + snp_a[snp_k] = oid; snp_k++; + if(snp_k != snp_n) snp_a[snp_n-1]++; + } + z->b32 = bu; z->b32->n = z->sa_tot + z->sn_tot; + assert(sa_tot0 == z->sa_tot); +} + + +///sn_tot: how many snps in total +inline void insert_srt_on_t_i32_hc(srt_on_t *z, haplotype_evdience *a, uint64_t an, asg32_v *bu, SnpStats *sn_a, uint64_t sn_tot, double st_rate, uint64_t st_max) +{ + uint64_t k, oid, sid, sa_tot0, ss; + uint32_t *snp_a, snp_n, snp_k; + uint32_t *sn = NULL; + z->sn_tot = sn_tot + 1; ///how mant snps in total + z->sa_tot = 0; ///how many overlaps covered by these snps + + kv_resize(uint32_t, *bu, z->sn_tot); + sn = bu->a; z->b32 = bu; + memset(sn, 0, sizeof((*(sn)))*z->sn_tot); + + for (k = 0; k < an; k++) { + if(hh_tp(a[k]) != 1) continue; + oid = a[k].overlapID; + // if(g_w_az((*z), oid) == 0) continue; + + sid = a[k].overlapSite; + // if(!is_plus_sc(&sn_a[sid], st_rate, st_max)) continue; + + sn[sid]++; z->sa_tot++; + } + + kv_resize(uint32_t, *bu, (z->sn_tot + z->sa_tot)); + sn = bu->a; ///z->sa = bu->a + z->sn_tot; + for (k = sa_tot0 = 0; k < z->sn_tot; k++) { + ss = sn[k]; + sn[k] = sa_tot0; sa_tot0 += ss; + if(ss > 0) { + // fprintf(stderr, "[M::%s] ss::%lu, sa_tot0::%lu, z->sa_tot::%lu, k::%lu, z->sn_tot::%lu, idx::%lu\n", __func__, ss, sa_tot0, z->sa_tot, k, z->sn_tot, + // ((*z).sn_tot)+(*z).b32->a[(k)]); + + g_sa_az(*z, k)[ss-1] = 0;//iter + } + } + assert(sa_tot0 == z->sa_tot); + + + for (k = sa_tot0 = 0; k < an; k++) { + if(hh_tp(a[k]) != 1) continue; + oid = a[k].overlapID; + // if(g_w_az((*z), oid) == 0) continue; + sid = a[k].overlapSite; + // if(!is_plus_sc(&sn_a[sid], st_rate, st_max)) continue; + + sa_tot0++; + snp_a = g_sa_az(*z, sid); + snp_n = g_sn_az(*z, sid); + assert(snp_n); + snp_k = snp_a[snp_n-1]; + snp_a[snp_k] = oid; snp_k++; + if(snp_k != snp_n) snp_a[snp_n-1]++; + } + z->b32 = bu; z->b32->n = z->sa_tot + z->sn_tot; + assert(sa_tot0 == z->sa_tot); +} + + +void mark_srt_on_t_oid(srt_on_t *z, uint64_t sid, SnpStats *st, uint64_t rid) +{ + uint32_t *snp_a = g_sa_az(*z, sid), snp_n = g_sn_az(*z, sid), k, oi; + for (k = 0; k < snp_n; k++) { + oi = snp_a[k]; + // if(!(g_w_az(*z, oi) > 0) || oi == 32) { + // fprintf(stderr, "\n-a-[M::%s]\trid::%lu\toid::%u\tssite::%u\n", __func__, rid, oi, st->site); + // } + + assert(g_w_az(*z, oi) > 0); + if((*z).ap[(oi)] == ((uint64_t)-1)) continue; + (*z).awk[(oi)]--; + if(g_of_az(*z, oi)) continue; + s_of_az(*z, oi, 1); + kv_push(uint32_t, (*(z->b32)), oi); + } + // z->sn = z->b32->a; z->sa = z->b32->a + z->sn_tot; +} + +void mark_srt_on_t_oid_obs(srt_on_t *z, uint64_t sid, SnpStats *st, uint64_t rid, int64_t plus) +{ + uint32_t *snp_a = g_sa_az(*z, sid), snp_n = g_sn_az(*z, sid), k, oi; + // fprintf(stderr, "\n+0+[M::%s] sid::%lu, snp_n::%u, idx::%lu, tot_m::%u\n", __func__, sid, snp_n, (*z).sn_tot+(*z).b32->a[(sid)], (uint32_t)z->b32->m); + for (k = 0; k < snp_n; k++) { + // fprintf(stderr, "+0+[M::%s] sid::%lu, snp_n::%u, k::%u\n", __func__, sid, snp_n, k); + oi = snp_a[k]; + assert((g_w_az(*z, oi) > 0) || (plus > 0)); + if(is_pop_az((*z), (oi))) continue;///has been poped + if(plus > 0) (*z).awk[(oi)]++; + else if(plus < 0) (*z).awk[(oi)]--; + if(g_of_az(*z, oi)) continue; + s_of_az(*z, oi, 1); + kv_push(uint32_t, (*(z->b32)), oi); + snp_a = g_sa_az(*z, sid); + } + // z->sn = z->b32->a; z->sa = z->b32->a + z->sn_tot; +} + + + +void update_srt_on_t_oid(srt_on_t *z) +{ + uint32_t k, oi; + for (k = z->sa_tot + z->sn_tot; k < z->b32->n; k++) { + oi = z->b32->a[k]; + if((*z).ap[(oi)] == ((uint64_t)-1)) continue; + s_of_az(*z, oi, 0); + if(g_w_az(*z, oi) == 0) { + delete_srt_on_t(z, oi); + } else { + adjust_srt_on_t(z, oi); + } + } + z->b32->n = z->sa_tot + z->sn_tot; +} + +void update_srt_on_t_oid_obs(srt_on_t *z) +{ + uint32_t k, oi; + for (k = z->sa_tot + z->sn_tot; k < z->b32->n; k++) { + oi = z->b32->a[k]; + assert(!is_pop_az((*z), (oi)));///has not been pop + // if((*z).ap[(oi)] == ((uint64_t)-1)) continue; + s_of_az(*z, oi, 0); + adjust_srt_on_t_obs(z, oi); + } + z->b32->n = z->sa_tot + z->sn_tot; +} + + + +void dbg_srt_ont(srt_on_t *z, haplotype_evdience_alloc* hap, double st_rate, uint64_t st_max, uint64_t oid0, uint64_t w0, uint64_t rid) +{ + uint64_t k, l, i, oi, oim = (uint64_t)-1, om = 0, o; SnpStats *s = NULL; + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + oi = hap->list[l].overlapID; + if(((*z).ap[(oi)] == ((uint64_t)-1)) && (oi != oid0)) { + l = k; + continue; + } + + for (i = l, o = 0; i < k; i++) { + if(hh_tp(hap->list[i])!=1) continue;///mismatch + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + assert(s->site == hap->list[i].site); + if(!is_plus_sc(s, st_rate, st_max)) continue; + o++;///allels must be real + // fprintf(stderr, "[M::%s] s->site::%u, s->occ_0::%u, s->occ_1::%u, s->overlap_num::%u, oi::%lu\n", __func__, s->site, s->occ_0, s->occ_1, s->overlap_num, oi); + } + + if(o > 0) { + // fprintf(stderr, "[M::%s::] oi::%lu, o::%lu\n", __func__, oi, o); + if((o > om) || (o == om && oi == oid0)) { + om = o; oim = oi; + } + } + l = k; + } + } + + + if(!(om == w0 && oim == oid0)) { + fprintf(stderr, "sss[M::%s::] oim::%lu, om::%lu, oid0::%lu, w0::%lu, rid::%lu\n", __func__, oim, om, oid0, w0, rid); + } + + assert(om == w0 && oim == oid0); +} + +void print_srt_ont_maxk(srt_on_t *z) +{ + uint64_t k, mw = z->mk, wp; + for (k = z->ik[mw]; k != ((uint32_t)-1); k = g_nxt_az((*z), k)) { + wp = g_w_az((*z), k); + fprintf(stderr, "[M::%s::] oid::%lu, wp::%lu\n", __func__, k, wp); + } +} + +void dbg_srt_ont_maxk(srt_on_t *z, const char *cmd) +{ + uint64_t k, mw = z->mk, wp, srt; + for (k = z->ik[mw], wp = ((uint32_t)-1), srt = 1; (k != ((uint32_t)-1)) && (srt); k = g_nxt_az((*z), k)) { + if(wp < g_w_az((*z), k)) { + srt = 0; + break; + } + wp = g_w_az((*z), k); + } + + if(srt != z->mk_srt) { + fprintf(stderr, "\n%s[M::%s::] srt::%lu, mk_srt::%lu, ma::%lu\n", __func__, cmd, srt, z->mk_srt, z->ma); + print_srt_ont_maxk(z); + } +} + +void generate_haplotypes_naive_HiFi_adv(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, double up, UC_Read* g_read, double st_rate, uint64_t st_max, asg32_v *b32, uint64_t rid) +{ + if(hap->length == 0) return; + uint64_t k, l, i, o, ii, m_snp_stat, m_list, m_off; + int64_t z; SnpStats *s = NULL, *t = NULL; + + for (k = 1, l = 0, i = m_snp_stat = m_list = 0; k <= hap->snp_stat.n; ++k) {///filter snps + if(k == hap->snp_stat.n || hap->snp_stat.a[k].site != hap->snp_stat.a[l].site) { + if((l > 0) && (hap->snp_stat.a[l].site == (hap->snp_stat.a[l-1].site + 1))) { + l = k; continue; + } + if((k < hap->snp_stat.n) && ((hap->snp_stat.a[l].site+1) == hap->snp_stat.a[k].site)) { + l = k; continue; + } + + for (; i < hap->length && hap->list[i].site != hap->snp_stat.a[l].site; i++); + assert(i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site); + m_off = l - m_snp_stat; + for (; i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site; i++) { + assert(hap->list[i].overlapSite>=l && hap->list[i].overlapSite < k); + // assert(hap->snp_stat.a[hap->list[i].overlapSite].site==hap->list[i].site); + hap->list[m_list] = hap->list[i]; hap->list[m_list++].overlapSite -= m_off; + } + + for (; l < k; l++) hap->snp_stat.a[m_snp_stat++] = hap->snp_stat.a[l]; + } + } + hap->snp_stat.n = m_snp_stat; hap->length = m_list; + if(hap->snp_stat.n == 0 || hap->length == 0) return; + + asg64_v buf; srt_on_t bs; + copy_asg_arr(buf, hap->snp_srt); + init_srt_on_t(&buf, 64, overlap_list->length, &bs); + + // for (k = 0; k < hap->snp_stat.n; ++k) { + // s = &(hap->snp_stat.a[k]); + // fprintf(stderr, "sss[M::%s::]\tsite::%u\tocc0::%u\tocc1::%u\tocc2::%u\tsc::%d\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_2, s->score); + // } + + radix_sort_haplotype_evdience_id_srt(hap->list, hap->list + hap->length); + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + for (i = l, o = 0; i < k; i++) { + if(hh_tp(hap->list[i])!=1) continue;///mismatch + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + assert(s->site == hap->list[i].site); + if(!is_plus_sc(s, st_rate, st_max)) continue; + // if(hap->list[l].overlapID == 35) { + // fprintf(stderr, "[M::%s] site::%u, occ_0::%u, occ_1::%u, occ_2::%u, is_homopolymer::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_1, s->is_homopolymer); + // } + + o++;///allels must be real + } + + if(o > 0) { + insert_srt_on_t(&bs, hap->list[l].overlapID, o, l);///insert a overlap + // ii = hap->list[l].overlapID; + // fprintf(stderr, "-z-[M::%s]\t%.*s\to::%lu\toid::%lu\n", __func__, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id), o, ii); + } + + + l = k; + } + } + + // fprintf(stderr, "\n[M::%s] snp_srt.n->%lu\n\n", __func__, ((uint64_t)hap->snp_srt.n)); + + if (bs.kan) { + // fprintf(stderr, "\n-a-[M::%s]\n\n", __func__); + ///insert SNP -> overlap id + insert_srt_on_t_i32(&bs, hap->list, hap->length, b32, hap->snp_stat.a, hap->snp_stat.n, st_rate, st_max); + // fprintf(stderr, "\n-b-[M::%s]\n\n", __func__); + + while (pop_srt_k(&bs, &ii, &l, &o)) {///pop one read/overlap + if(o == 0) break; + + // fprintf(stderr, "-ssb-[M::%s]\t%.*s(id::%u)\toid::%lu\to::%lu\tq::[%u,%u)\tt::[%u,%u)\tbs.an::%lu\n", + // __func__, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id), overlap_list->list[ii].y_id, ii, o, + // overlap_list->list[ii].x_pos_s, overlap_list->list[ii].x_pos_e + 1, overlap_list->list[ii].y_pos_s, overlap_list->list[ii].y_pos_e + 1, bs.an); + + + // fprintf(stderr, "-0-[M::%s]\tg_w_az(bs, 35)::%u\n", __func__, g_w_az(bs, 35)); + + // dbg_srt_ont(&bs, hap, st_rate, st_max, ii, o, rid); + + + + + if(overlap_list->list[ii].is_match == 1) { + overlap_list->list[ii].is_match = 2; + } + + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hh_tp(hap->list[i]) == 0) { + ///not real allels + z = hap->list[i].overlapSite; s = &(hap->snp_stat.a[z]); + for (z = hap->list[i].overlapSite; z >= 0; z--) { + t = &(hap->snp_stat.a[z]); + if(s->site!=t->site) break; + t->occ_0 -= hap->list[i].cov; + assert(t->occ_0 >= 1); + if((st_max != ((uint64_t)-1)) && (overlap_list->list[ii].y_pos_strand == 0)) { + + // if(ii == 249) { + // fprintf(stderr, "\nsasasa[M::%s]\tt->site::%u\tt->overlap_num::%u\thap->list[i].cov::%u\t%.*s\n\n", __func__, t->site, t->overlap_num, hap->list[i].cov, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id)); + // } + + t->overlap_num -= hap->list[i].cov; + assert(t->overlap_num >= 1); + } + + if((t->score > 0) && (!is_plus_sc(t, st_rate, st_max))) { + t->score = -1; + ///mark read that need to be updated + // fprintf(stderr, "-1-[M::%s]\tg_w_az(bs, 35)::%u\tt->site::%u\n", __func__, g_w_az(bs, 35), t->site); + mark_srt_on_t_oid(&bs, z, t, rid); + // fprintf(stderr, "-2-[M::%s]\tg_w_az(bs, 35)::%u\tt->site::%u\n", __func__, g_w_az(bs, 35), t->site); + } + } + } + } + + // fprintf(stderr, "-3-[M::%s]\tg_w_az(bs, 35)::%u\n", __func__, g_w_az(bs, 35)); + + update_srt_on_t_oid(&bs); + + // fprintf(stderr, "-4-[M::%s]\tg_w_az(bs, 35)::%u\n", __func__, g_w_az(bs, 35)); + + + } + } + + // for (k = 0; k < hap->snp_stat.n; ++k) { + // s = &(hap->snp_stat.a[k]); + // if(s->score <= 0) continue; + // fprintf(stderr, "sss[M::%s::]\tsite::%u\tocc0::%u\tocc1::%u\tocc2::%u\tsc::%d\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_2, s->score); + // } + + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match==2) { + overlap_list->list[ii].strong = 1; + overlap_list->mapped_overlaps_length -= + overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; + } else if(overlap_list->list[ii].is_match==1) { + for (i = l; i < k; i++) { + if(hh_tp(hap->list[i])==1 || hh_tp(hap->list[i])==0) { + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->score > 0 && (!(s->occ_0 < 2 || s->occ_1 < 2)) && (!(is_st_bs((*s), st_rate, st_max)))) { + overlap_list->list[ii].strong = 1; + if(hh_tp(hap->list[i])==1) { + // fprintf(stderr, "-2-[M::%s]\t%.*s\n", __func__, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id)); + overlap_list->list[ii].is_match = 2; + overlap_list->mapped_overlaps_length -= + overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; + break; + } + } + } + + } + } + l = k; + } + } + + copy_asg_arr(hap->snp_srt, buf); +} + + + +void generate_haplotypes_naive_HiFi_adv_hc(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, double up, UC_Read* g_read, double st_rate, uint64_t st_max, asg32_v *b32, uint64_t rid) +{ + if(hap->length == 0) return; + uint64_t k, l, i, o, obs, ii, m_snp_stat, m_list, m_off; + int64_t z; SnpStats *s = NULL, *t = NULL; int8_t zf; + + // fprintf(stderr, "+0+[M::%s] rid::%lu\n", __func__, rid); + + for (k = 1, l = 0, i = m_snp_stat = m_list = 0; k <= hap->snp_stat.n; ++k) {///filter snps + if(k == hap->snp_stat.n || hap->snp_stat.a[k].site != hap->snp_stat.a[l].site) { + if((l > 0) && (hap->snp_stat.a[l].site == (hap->snp_stat.a[l-1].site + 1))) { + l = k; continue; + } + if((k < hap->snp_stat.n) && ((hap->snp_stat.a[l].site+1) == hap->snp_stat.a[k].site)) { + l = k; continue; + } + + for (; i < hap->length && hap->list[i].site != hap->snp_stat.a[l].site; i++); + assert(i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site); + m_off = l - m_snp_stat; + for (; i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site; i++) { + assert(hap->list[i].overlapSite>=l && hap->list[i].overlapSite < k); + // assert(hap->snp_stat.a[hap->list[i].overlapSite].site==hap->list[i].site); + hap->list[m_list] = hap->list[i]; hap->list[m_list++].overlapSite -= m_off; + } + + for (; l < k; l++) { + s = &(hap->snp_stat.a[l]); assert(s->score > 0); + zf = is_plus_sc_obs(s, st_rate, st_max); + if(zf <= 0) s->score = -s->score; + + hap->snp_stat.a[m_snp_stat++] = hap->snp_stat.a[l]; + } + } + } + hap->snp_stat.n = m_snp_stat; hap->length = m_list; + if(hap->snp_stat.n == 0 || hap->length == 0) return; + + // fprintf(stderr, "+1+[M::%s] rid::%lu\n", __func__, rid); + + asg64_v buf; srt_on_t bs; + copy_asg_arr(buf, hap->snp_srt); + init_srt_on_t(&buf, 64, overlap_list->length, &bs); + + // for (k = 0; k < hap->snp_stat.n; ++k) { + // s = &(hap->snp_stat.a[k]); + // fprintf(stderr, "sss[M::%s::]\tsite::%u\tocc0::%u\tocc1::%u\tocc2::%u\tsc::%d\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_2, s->score); + // } + + // fprintf(stderr, "\n+2+[M::%s] rid::%lu\n", __func__, rid); + radix_sort_haplotype_evdience_id_srt(hap->list, hap->list + hap->length); + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + for (i = l, o = obs = 0; i < k; i++) { + if(hh_tp(hap->list[i])!=1) continue;///mismatch + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + assert(s->site == hap->list[i].site); + zf = is_plus_sc_obs(s, st_rate, st_max); + // if(s->site == 11114) { + // fprintf(stderr, "[M::%s] s->site::%u, s->occ_0::%u, s->occ_1::%u, s->overlap_num::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->overlap_num); + // } + if(zf > 0) o++; + else if(zf == 0) obs++; + } + + // fprintf(stderr, "[M::%s] obs::%lu, o::%lu, s->site::%u, s->occ_0::%u, s->occ_1::%u, s->overlap_num::%u\n", __func__, obs, o, s->site, s->occ_0, s->occ_1, s->overlap_num); + + if(obs || o) { + ///o might be 0 + insert_srt_on_t(&bs, hap->list[l].overlapID, o, l);///insert a overlap + // ii = hap->list[l].overlapID; + // fprintf(stderr, "-z-[M::%s]\t%.*s\to::%lu\tobs::%lu\toid::%lu\tow::%u\n", + // __func__, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id), o, obs, ii, g_w_az((bs), hap->list[l].overlapID)); + } + + + l = k; + } + } + + // fprintf(stderr, "\n[M::%s] snp_srt.n->%lu\n\n", __func__, ((uint64_t)hap->snp_srt.n)); + + // fprintf(stderr, "+3+[M::%s] rid::%lu, ma::%lu\n", __func__, rid, bs.ma); + + // print_srt_ont_maxk(&bs); + + if (bs.kan) { + // fprintf(stderr, "\n-a-[M::%s]\n\n", __func__); + ///insert SNP -> overlap id + insert_srt_on_t_i32_obs(&bs, hap->list, hap->length, b32, hap->snp_stat.a, hap->snp_stat.n, st_rate, st_max); + // fprintf(stderr, "\n-b-[M::%s]\n\n", __func__); + + // fprintf(stderr, "+4+[M::%s] rid::%lu\n", __func__, rid); + + while (pop_srt_k(&bs, &ii, &l, &o)) {///pop one read/overlap + if(o == 0) break; + + // fprintf(stderr, "-ssb-[M::%s]\t%.*s(id::%u)\toid::%lu\to::%lu\tq::[%u,%u)\tt::[%u,%u)\tbs.an::%lu\n", + // __func__, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id), overlap_list->list[ii].y_id, ii, o, + // overlap_list->list[ii].x_pos_s, overlap_list->list[ii].x_pos_e + 1, overlap_list->list[ii].y_pos_s, overlap_list->list[ii].y_pos_e + 1, bs.an); + + + // fprintf(stderr, "-0-[M::%s]\to::%lu\toid::%lu\n", __func__, o, ii); + + // dbg_srt_ont_maxk(&bs, "*1*"); + + // dbg_srt_ont(&bs, hap, st_rate, st_max, ii, o, rid); + + + + + if(overlap_list->list[ii].is_match == 1) { + overlap_list->list[ii].is_match = 2; + } + + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hh_tp(hap->list[i]) == 0) { + ///not real allels + z = hap->list[i].overlapSite; s = &(hap->snp_stat.a[z]); + for (z = hap->list[i].overlapSite; z >= 0; z--) { + t = &(hap->snp_stat.a[z]); + if(s->site!=t->site) break; + t->occ_0 -= hap->list[i].cov; + assert(t->occ_0 >= 1); + if((st_max != ((uint64_t)-1)) && (overlap_list->list[ii].y_pos_strand == 0)) { + + // if(ii == 249) { + // fprintf(stderr, "\nsasasa[M::%s]\tt->site::%u\tt->overlap_num::%u\thap->list[i].cov::%u\t%.*s\n\n", __func__, t->site, t->overlap_num, hap->list[i].cov, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id)); + // } + + t->overlap_num -= hap->list[i].cov; + assert(t->overlap_num >= 1); + } + + zf = is_plus_sc(t, st_rate, st_max); + // if(s->site == 11114) { + // fprintf(stderr, "[M::%s] s->site::%u, s->occ_0::%u, s->occ_1::%u, s->overlap_num::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->overlap_num); + // fprintf(stderr, "[M::%s]\tzf::%d\tt->score::%d\n", __func__, zf, t->score); + // } + + if((t->score > 0) && (zf == 0)) { + t->score = -t->score; + ///mark read that need to be updated + // fprintf(stderr, "-1-[M::%s]\ttoid::%lu\tt->site::%u\n", __func__, ii, t->site); + mark_srt_on_t_oid_obs(&bs, z, t, rid, ((t->score>0)?1:-1)); + // fprintf(stderr, "-2-[M::%s]\tg_w_az(bs, 35)::%u\tt->site::%u\n", __func__, g_w_az(bs, 35), t->site); + } else if((t->score < 0) && (zf > 0)) { + t->score = -t->score; + ///mark read that need to be updated + // fprintf(stderr, "-2-[M::%s]\ttoid::%lu\tt->site::%u\n", __func__, ii, t->site); + mark_srt_on_t_oid_obs(&bs, z, t, rid, ((t->score>0)?1:-1)); + // fprintf(stderr, "-2-[M::%s]\tg_w_az(bs, 35)::%u\tt->site::%u\n", __func__, g_w_az(bs, 35), t->site); + } + } + } + } + + // fprintf(stderr, "-3-[M::%s]\tg_w_az(bs, 35)::%u\n", __func__, g_w_az(bs, 39)); + + // dbg_srt_ont_maxk(&bs, "*2*"); + + update_srt_on_t_oid_obs(&bs); + + // fprintf(stderr, "-4-[M::%s]\tg_w_az(bs, 35)::%u\n", __func__, g_w_az(bs, 39)); + + // dbg_srt_ont_maxk(&bs, "*3*"); + // print_srt_ont_maxk(&bs); + + + } + } + + // for (k = 0; k < hap->snp_stat.n; ++k) { + // s = &(hap->snp_stat.a[k]); + // if(s->score <= 0) continue; + // fprintf(stderr, "sss[M::%s::]\tsite::%u\tocc0::%u\tocc1::%u\tocc2::%u\tsc::%d\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_2, s->score); + // } + + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match==2) { + overlap_list->list[ii].strong = 1; + overlap_list->mapped_overlaps_length -= + overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; + } else if(overlap_list->list[ii].is_match==1) { + for (i = l; i < k; i++) { + if(hh_tp(hap->list[i])==1 || hh_tp(hap->list[i])==0) { + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->score > 0 && (!(s->occ_0 < 2 || s->occ_1 < 2)) && (!(is_st_bs((*s), st_rate, st_max)))) { + overlap_list->list[ii].strong = 1; + if(hh_tp(hap->list[i])==1) { + // fprintf(stderr, "-2-[M::%s]\t%.*s\n", __func__, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id)); + overlap_list->list[ii].is_match = 2; + overlap_list->mapped_overlaps_length -= + overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; + break; + } + } + } + + } + } + l = k; + } + } + + copy_asg_arr(hap->snp_srt, buf); +} + + + +void generate_haplotypes_naive_HiFi_adv_back(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, double up, UC_Read* g_read, double st_rate, uint64_t st_max/**, kv_ul_ov_t *bu**/) +{ + if(hap->length == 0) return; + uint64_t k, l, i, o, ii, m_snp_stat, m_list, m_off; + int64_t z; + SnpStats *s = NULL, *t = NULL; + + for (k = 1, l = 0, i = m_snp_stat = m_list = 0; k <= hap->snp_stat.n; ++k) {///filter snps + if(k == hap->snp_stat.n || hap->snp_stat.a[k].site != hap->snp_stat.a[l].site) { + if((l > 0) && (hap->snp_stat.a[l].site == (hap->snp_stat.a[l-1].site + 1))) { + l = k; continue; + } + if((k < hap->snp_stat.n) && ((hap->snp_stat.a[l].site+1) == hap->snp_stat.a[k].site)) { + l = k; continue; + } + + for (; i < hap->length && hap->list[i].site != hap->snp_stat.a[l].site; i++); + assert(i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site); + m_off = l - m_snp_stat; + for (; i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site; i++) { + assert(hap->list[i].overlapSite>=l && hap->list[i].overlapSite < k); + // assert(hap->snp_stat.a[hap->list[i].overlapSite].site==hap->list[i].site); + hap->list[m_list] = hap->list[i]; hap->list[m_list++].overlapSite -= m_off; + } + + for (; l < k; l++) hap->snp_stat.a[m_snp_stat++] = hap->snp_stat.a[l]; + } + } + hap->snp_stat.n = m_snp_stat; hap->length = m_list; + if(hap->snp_stat.n == 0 || hap->length == 0) return; + + for (k = 0; k < hap->snp_stat.n; ++k) { + s = &(hap->snp_stat.a[k]); + fprintf(stderr, "sss[M::%s::]\tsite::%u\tocc0::%u\tocc1::%u\tocc2::%u\tsc::%d\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_2, s->score); + } + + hap->snp_srt.n = 0; + radix_sort_haplotype_evdience_id_srt(hap->list, hap->list + hap->length); + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + for (i = l, o = 0; i < k; i++) { + if(hh_tp(hap->list[i])!=1) continue;///mismatch + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + assert(s->site == hap->list[i].site); + if(s->occ_0 < 2 || s->occ_1 < 2 || s->score < 0) continue; + if(is_st_bs((*s), st_rate, st_max)) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { + // fprintf(stderr, "[M::%s] site::%u, occ_0::%u, occ_1::%u, occ_2::%u, is_homopolymer::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_1, s->is_homopolymer); + o++;///allels must be real + } + } + + if(o > 0) { + ii = hap->list[l].overlapID; + fprintf(stderr, "-z-[M::%s]\t%.*s\to::%lu\n", __func__, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id), o); + o = ((uint32_t)-1) - o; + o <<= 32; o += l; + kv_push(uint64_t, hap->snp_srt, o); + } + l = k; + } + } + + fprintf(stderr, "\n[M::%s] snp_srt.n->%lu\n", __func__, ((uint64_t)hap->snp_srt.n)); + + if (hap->snp_srt.n > 0) { + radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n);///sort by how many snps in one overlap + for (k = 0; k < hap->snp_srt.n; k++) { + o = 0; l = (uint32_t)hap->snp_srt.a[k]; + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hh_tp(hap->list[i])!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2 || s->score < 0) continue; + if(is_st_bs((*s), st_rate, st_max)) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { + /**if(overlap_list->list[hap->list[l].overlapID].y_id == 1461140)**/ { + fprintf(stderr, "bbb[M::%s::]\tsite::%u\tocc0::%u\tocc1::%u\tocc2::%u\tsc::%d\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_2, s->score); + } + o++; + } + } + if(o == 0) continue; + + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match == 1) { + overlap_list->list[ii].is_match = 2; + fprintf(stderr, "-0-[M::%s]\t%.*s(id::%u)\to::%lu\tq::[%u,%u)\tt::[%u,%u)\n", + __func__, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id), overlap_list->list[ii].y_id, o, + overlap_list->list[ii].x_pos_s, overlap_list->list[ii].x_pos_e + 1, overlap_list->list[ii].y_pos_s, overlap_list->list[ii].y_pos_e + 1); + } + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hh_tp(hap->list[i])==1){///r831: I guess this should be disabled, especially within repeats + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->score < 0) s->score = 1; + } else if(hh_tp(hap->list[i])==0) { + ///not real allels + z = hap->list[i].overlapSite; s = &(hap->snp_stat.a[z]); + for (z = hap->list[i].overlapSite; z >= 0; z--) { + t = &(hap->snp_stat.a[z]); + if(s->site!=t->site) break; + t->occ_0 -= hap->list[i].cov; + assert(t->occ_0 >= 1); + if((st_max != ((uint64_t)-1)) && (overlap_list->list[ii].y_pos_strand == 0)) { + t->overlap_num -= hap->list[i].cov; + assert(t->overlap_num >= 1); + } + } + } + } + } + + for (k = 0; k < hap->snp_srt.n; k++) {///sorted by how many allels in each overlap; more -> less + o = 0; l = (uint32_t)hap->snp_srt.a[k]; + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hh_tp(hap->list[i])!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(is_st_bs((*s), st_rate, st_max)) continue; + if(s->score > 0) o++; + } + ii = hap->list[l].overlapID; + ///for HiFi, do not flip trans to cis + // if(overlap_list->list[ii].is_match == 2 && o == 0) { + // overlap_list->list[ii].is_match = 1; + // } + if(overlap_list->list[ii].is_match == 1 && o > 0) { + fprintf(stderr, "-1-[M::%s]\t%.*s\to::%lu\n", __func__, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id), o); + overlap_list->list[ii].is_match = 2; + } + } + + + for (k = 1, l = 0; k <= hap->length; ++k) { ///reset snp_stat + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match==1) { + for (i = l; i < k; i++) { + if(hh_tp(hap->list[i])==1) { + hap->snp_stat.a[hap->list[i].overlapSite].score = -1; + } + } + } + l = k; + } + } + } + + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match==2) { + overlap_list->list[ii].strong = 1; + overlap_list->mapped_overlaps_length -= + overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; + } else if(overlap_list->list[ii].is_match==1) { + for (i = l; i < k; i++) { + if(hh_tp(hap->list[i])==1 || hh_tp(hap->list[i])==0) { + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + // if(s->site == 267) { + // fprintf(stderr, "[M::%s::]\tsite::%u\tocc0::%u\tocc1::%u\tocc2::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_2); + // } + if(s->score > 0 && (!(s->occ_0 < 2 || s->occ_1 < 2)) && (!(is_st_bs((*s), st_rate, st_max)))) { + overlap_list->list[ii].strong = 1; + if(hh_tp(hap->list[i])==1) { + fprintf(stderr, "-2-[M::%s]\t%.*s\n", __func__, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id)); + overlap_list->list[ii].is_match = 2; + overlap_list->mapped_overlaps_length -= + overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; + break; + } + } + } + + } + } + l = k; + } + } +} + + +void generate_haplotypes_weight(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, double up, UC_Read* g_read, uint64_t multi_check, double st_rate, uint64_t st_max, uint64_t snp_dis, int64_t snp_cut) +{ + // fprintf(stderr, "-0-[M::%s::] Done\n", __func__); + if(hap->length == 0) return; + uint64_t k, l, i, o, *a, ii, m_snp_stat, m_list, m_off, ps, obit, omax, lmax; + int64_t z; + SnpStats *s = NULL, *t = NULL; + + ///update weight + for (k = 0; k < hap->snp_stat.n; ) { + l = k; ps = hap->snp_stat.a[l].site; + for (; k < hap->snp_stat.n && ps == hap->snp_stat.a[k].site; k++); + for (; k < hap->snp_stat.n && (ps + snp_dis) >= hap->snp_stat.a[k].site; k++) { + ps = hap->snp_stat.a[k].site; + } + if(ps > hap->snp_stat.a[l].site) { + for (i = l; i < k; i++) { + hap->snp_stat.a[i].score = hap->snp_stat.a[i].score/snp_cut; + if(hap->snp_stat.a[i].score < 1) hap->snp_stat.a[i].score = 1; + } + } + assert(k > l); + } + // fprintf(stderr, "[M::%s::] hap->snp_stat.n::%u\n", __func__, (uint32_t)hap->snp_stat.n); + + ///discard sites + for (k = 1, l = 0, i = m_snp_stat = m_list = 0; k <= hap->snp_stat.n; ++k) {///filter snps + if(k == hap->snp_stat.n || hap->snp_stat.a[k].site != hap->snp_stat.a[l].site) { + if((l > 0) && (hap->snp_stat.a[l].site == (hap->snp_stat.a[l-1].site + 1))) { + l = k; continue; + } + if((k < hap->snp_stat.n) && ((hap->snp_stat.a[l].site+1) == hap->snp_stat.a[k].site)) { + l = k; continue; + } + + for (; i < hap->length && hap->list[i].site != hap->snp_stat.a[l].site; i++); + assert(i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site); + m_off = l - m_snp_stat; + for (; i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site; i++) { + assert(hap->list[i].overlapSite>=l && hap->list[i].overlapSite < k); + // assert(hap->snp_stat.a[hap->list[i].overlapSite].site==hap->list[i].site); + hap->list[m_list] = hap->list[i]; hap->list[m_list++].overlapSite -= m_off; + } + + for (; l < k; l++) hap->snp_stat.a[m_snp_stat++] = hap->snp_stat.a[l]; + } + } + // fprintf(stderr, "[M::%s::] hap->snp_stat.n::%u, m_snp_stat::%lu, m_list::%lu\n", __func__, (uint32_t)hap->snp_stat.n, m_snp_stat, m_list); + hap->snp_stat.n = m_snp_stat; hap->length = m_list; + if(hap->snp_stat.n == 0 || hap->length == 0) return; + + // fprintf(stderr, "-1-[M::%s::] Done\n", __func__); + + // for (k = 0; k < hap->snp_stat.n; k++) { + // s = &(hap->snp_stat.a[k]); if(s->site != 1502) continue; + // fprintf(stderr, "[M::%s] site::%u, occ_0::%u, occ_1::%u, occ_2::%u, is_homopolymer::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_2, s->is_homopolymer); + // prt_sub_read(g_read->seq, g_read->length, s->site, 25); + // for (i = 0; i < overlap_list->length; i++) { + // if(/**overlap_list->list[i].is_match == 1 &&**/ overlap_list->list[i].x_pos_s <= s->site && s->site <= overlap_list->list[i].x_pos_e) { + // fprintf(stderr, "%.*s\tis_match::%u\tid::%u\n", (int)Get_NAME_LENGTH(R_INF, overlap_list->list[i].y_id), Get_NAME(R_INF, overlap_list->list[i].y_id), overlap_list->list[i].is_match, overlap_list->list[i].y_id); + // } + // } + // } + + o = hap->length; obit = 0; + while (o > 0) { + obit++; o >>= 1; + } + obit = 64 - obit; omax = (((uint64_t)1)<snp_srt.n = 0; + radix_sort_haplotype_evdience_id_srt(hap->list, hap->list + hap->length); + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + for (i = l, o = 0; i < k; i++) { + if(hh_tp(hap->list[i])!=1) continue;///mismatch + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + assert(s->site == hap->list[i].site); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(is_st_bs((*s), st_rate, st_max)) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { + assert(s->score > 0); + o += s->score;// o++;///allels must be real + // if(overlap_list->list[hap->list[l].overlapID].y_id == 1740) { + // fprintf(stderr, "sra[M::%s-id::%u] o->%lu, l->%lu, occ_0::%u, occ_1::%u\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, o, l, s->occ_0, s->occ_1); + // } + } + } + if(o > omax) o = omax; + + // if(overlap_list->list[hap->list[l].overlapID].y_id == 1740) { + // fprintf(stderr, "str1074[M::%s-id::%u] o->%lu(%c), l::%lu\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, o, "+-"[overlap_list->list[hap->list[l].overlapID].y_pos_strand], l); + // for (i = l; i < k; i++) { + // if(hh_tp(hap->list[i])!=1) continue;///mismatch + // s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + // assert(s->site == hap->list[i].site); + // if(s->occ_0 < 2 || s->occ_1 < 2) continue; + // if(is_st_bs((*s), st_rate, st_max)) continue; + // if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { + // fprintf(stderr, "[M::%s] site::%u, occ_0::%u, occ_1::%u, occ_2::%u, is_homopolymer::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_1, s->is_homopolymer); + // // prt_sub_read(g_read->seq, g_read->length, s->site, 50); + // } + // } + // } + // else { + // fprintf(stderr, "[M::%s-id::%u] o->%lu(%c), l::%lu\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, o, "+-"[overlap_list->list[hap->list[l].overlapID].y_pos_strand], l); + // } + // else { + // for (i = l, o = 0; i < k; i++) { + // if(hh_tp(hap->list[i])!=0) continue;///mismatch + // s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + // assert(s->site == hap->list[i].site); + // if(s->occ_0 < 2 || s->occ_1 < 2) continue; + // if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { + // if(s->site == 7878 || s->site == 9682) { + + // fprintf(stderr, "***[M::%s] site::%u, rid::%u\t%.*s\n", __func__, s->site, overlap_list->list[hap->list[l].overlapID].y_id, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[hap->list[l].overlapID].y_id), + // Get_NAME(R_INF, overlap_list->list[hap->list[l].overlapID].y_id)); + // prt_sub_cigar(&(overlap_list->list[hap->list[l].overlapID]), g_read->length, s->site, 50); + // } + // // o++;///allels must be real + // // fprintf(stderr, "[M::%s] site::%u, occ_0::%u, occ_1::%u, occ_2::%u, is_homopolymer::%u\n", __func__, s->site, s->occ_0, s->occ_1, s->occ_1, s->is_homopolymer); + // // prt_sub_read(g_read->seq, g_read->length, s->site, 50); + // } + // } + // } + + // if(overlap_list->list[hap->list[l].overlapID].y_id == 3626) { + // fprintf(stderr, "***0***[M::%s-id::%u] o->%lu\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, o); + // } + + if(o > 0) { + o = omax - o; + o <<= obit; o += l; assert((o&lmax) == l); + kv_push(uint64_t, hap->snp_srt, o); + } + l = k; + } + } + + // fprintf(stderr, "[M::%s] snp_srt.n->%lu\n", __func__, ((uint64_t)hap->snp_srt.n)); + + if (hap->snp_srt.n > 0) { + radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n);///sort by how many snps in one overlap + for (k = 0; k < hap->snp_srt.n; k++) { + o = 0; l = hap->snp_srt.a[k]&lmax; + // fprintf(stderr, "[M::%s] rid::%u\t%.*s\tweight::%lu\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, + // (int)Get_NAME_LENGTH(R_INF, overlap_list->list[hap->list[l].overlapID].y_id), Get_NAME(R_INF, overlap_list->list[hap->list[l].overlapID].y_id), omax - (hap->snp_srt.a[k]>>obit)); + + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hh_tp(hap->list[i])!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(is_st_bs((*s), st_rate, st_max)) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { + o++; + // if(overlap_list->list[hap->list[l].overlapID].y_id == 1740) { + // fprintf(stderr, "srt[M::%s] site->%u, occ_0::%u, occ_1::%u\n", __func__, s->site, s->occ_0, s->occ_1); + // } + } + } + // if(overlap_list->list[hap->list[l].overlapID].y_id == 1740) { + // fprintf(stderr, "srt[M::%s-id::%u] o->%lu, l->%lu\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, o, l); + // } + if(o == 0) continue; + + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match == 1) overlap_list->list[ii].is_match = 2; + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hh_tp(hap->list[i])==1) { + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(is_st_bs((*s), st_rate, st_max)) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { + s->id = UINT32_MAX; ///s->score = 1; + // fprintf(stderr, "set[M::%s-site::%u] occ_0::%u, occ_1::%u\n", __func__, s->site, s->occ_0, s->occ_1); + } + } else if(hh_tp(hap->list[i])==0) { + ///not real allels + z = hap->list[i].overlapSite; s = &(hap->snp_stat.a[z]); + for (z = hap->list[i].overlapSite; z >= 0; z--) { + t = &(hap->snp_stat.a[z]); + if(s->site!=t->site) break; + t->occ_0 -= hap->list[i].cov; + assert(t->occ_0 >= 1); + if((st_max != ((uint64_t)-1)) && (overlap_list->list[ii].y_pos_strand == 0)) { + t->overlap_num -= hap->list[i].cov; + assert(t->overlap_num >= 1); + } + } + } + } + } + + for (k = 0; k < hap->snp_srt.n; k++) {///sorted by how many allels in each overlap; more -> less + o = 0; l = hap->snp_srt.a[k] & lmax; + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hh_tp(hap->list[i])!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(is_st_bs((*s), st_rate, st_max)) continue; + if(s->id == UINT32_MAX) o++; // if(s->score == 1) o++; + } + ii = hap->list[l].overlapID; + ///for HiFi, do not flip trans to cis + // if(overlap_list->list[ii].is_match == 2 && o == 0) { + // overlap_list->list[ii].is_match = 1; + // } + if(overlap_list->list[ii].is_match == 1 && o > 0) { + overlap_list->list[ii].is_match = 2; + } + } + + + for (k = 1, l = 0; k <= hap->length; ++k) { ///reset snp_stat + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match == 1) { + for (i = l; i < k; i++) { + if(hh_tp(hap->list[i])==1) { + hap->snp_stat.a[hap->list[i].overlapSite].id = 0;// hap->snp_stat.a[hap->list[i].overlapSite].score = -1; + } + } + } + l = k; + } + } + } + + + if(multi_check) { + hap->snp_srt.n = 0; + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + if(overlap_list->list[hap->list[l].overlapID].is_match == 2) { + l = k; continue; + } + for (i = l, o = 0; i < k; i++) { + if(hh_tp(hap->list[i])!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(is_st_bs((*s), st_rate, st_max)) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) continue; + if(s->id == UINT32_MAX) continue; //if(s->score == 1) continue; + o++; + kv_push(uint64_t, hap->snp_srt, hap->list[i].overlapSite); + } + // if(overlap_list->list[hap->list[l].overlapID].y_id == 317 || overlap_list->list[hap->list[l].overlapID].y_id == 287) { + // fprintf(stderr, "***2***[M::%s-id::%u] o->%lu\n", __func__, overlap_list->list[hap->list[l].overlapID].y_id, o); + // } + hap->snp_srt.n -= o; + ///there are at least two variants at one read + if(o>=(overlap_list->list[hap->list[l].overlapID].align_length*up)) { + radix_sort_bc64(hap->snp_srt.a + hap->snp_srt.n, hap->snp_srt.a + hap->snp_srt.n + o); + a = hap->snp_srt.a + hap->snp_srt.n; + for (i = z = 0; i < o; i++) { + if(i > 0) s = &(hap->snp_stat.a[a[i-1]]); + if(i + 1 < o) t = &(hap->snp_stat.a[a[i+1]]); + if(s && s->site + 32 > hap->snp_stat.a[a[i]].site) continue; + if(t && hap->snp_stat.a[a[i]].site + 32 > t->site) continue; + a[z] = a[i]; + z++; + } + if(z >= 2) hap->snp_srt.n += z; + } + l = k; + } + } + if (hap->snp_srt.n > 0) { + radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n); + for (k = 1, l = 0; k <= hap->snp_srt.n; ++k) { + if(k == hap->snp_srt.n || hap->snp_srt.a[k] != hap->snp_srt.a[l]) { + if(k - l >= 2) hap->snp_stat.a[hap->snp_srt.a[l]].id = UINT32_MAX; ///hap->snp_stat.a[hap->snp_srt.a[l]].score = 1; + } + l = k; + } + } + } + + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match==2) { + overlap_list->list[ii].strong = 1; + overlap_list->mapped_overlaps_length -= + overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; + } else if(overlap_list->list[ii].is_match==1) { + for (i = l; i < k; i++) { + if(hh_tp(hap->list[i])==1 || hh_tp(hap->list[i])==0) { + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if((s->id == UINT32_MAX/**s->score == 1**/) && (!(s->occ_0 < 2 || s->occ_1 < 2)) && (!(is_st_bs((*s), st_rate, st_max)))) { + overlap_list->list[ii].strong = 1; + if(hh_tp(hap->list[i])==1) { + overlap_list->list[ii].is_match = 2; + overlap_list->mapped_overlaps_length -= + overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; + break; + } + } + } + + } + } + l = k; + } + } + + for (k = 0; k < hap->snp_stat.n; k++) { + if(hap->snp_stat.a[k].id == UINT32_MAX) { + hap->snp_stat.a[k].score = 1; + // fprintf(stderr, "true[M::%s-site::%u] occ_0::%u, occ_1::%u\n", __func__, hap->snp_stat.a[k].site, hap->snp_stat.a[k].occ_0, hap->snp_stat.a[k].occ_1); + } else { + hap->snp_stat.a[k].score = -1; + // fprintf(stderr, "fase[M::%s-site::%u] occ_0::%u, occ_1::%u\n", __func__, hap->snp_stat.a[k].site, hap->snp_stat.a[k].occ_0, hap->snp_stat.a[k].occ_1); + } + } +} + + + + +void generate_haplotypes_sv(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, uint64_t rid) +{ + uint64_t k, l, i, o, ii; + int64_t z; SnpStats *s = NULL; + // fprintf(stderr, "[M::%s] hap->snp_stat.n::%u, hap->length::%u\n", __func__, (uint32_t)hap->snp_stat.n, (uint32_t)hap->length); + if(hap->snp_stat.n == 0 || hap->length == 0) return; + + hap->snp_srt.n = 0; + radix_sort_haplotype_evdience_id_srt(hap->list, hap->list + hap->length); + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + for (i = l, o = 0; i < k; i++) { + if(hh_tp(hap->list[i])!=1) continue;///mismatch + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + assert(s->site == hap->list[i].site); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) o++;///allels must be real + } + + if(o > 0) { + o = ((uint32_t)-1) - o; + o <<= 32; o += l; + kv_push(uint64_t, hap->snp_srt, o); + } + l = k; + } + } + + + if (hap->snp_srt.n > 0) { + radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n);///sort by how many snps in one overlap + for (k = 0; k < hap->snp_srt.n; k++) { + o = 0; l = (uint32_t)hap->snp_srt.a[k]; + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hh_tp(hap->list[i])!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) { + o++; + } + } + if(o == 0) continue; + + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match == 1) { + overlap_list->list[ii].is_match = 2; + // fprintf(stderr, "[M::%s] rid::%u\t%.*s\n", __func__, overlap_list->list[ii].y_id, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id)); + } + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hh_tp(hap->list[i])==1){ + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + s->score = 1; + } else if(hh_tp(hap->list[i])==0) { + ///not real allels + z = hap->list[i].overlapSite; + s = &(hap->snp_stat.a[z]); + s->occ_0--; + // if(!(s->occ_0 >= 1)) { + // fprintf(stderr, "[M::%s] rid::%lu, ssite::%u, lsite::%u, i::%lu, idx::%u\n", __func__, rid, s->site, hap->list[i].site, i, hap->list[i].overlapSite); + // } + assert(s->occ_0 >= 1); + } + } + } + + for (k = 0; k < hap->snp_srt.n; k++) {///sorted by how many allels in each overlap; more -> less + o = 0; l = (uint32_t)hap->snp_srt.a[k]; + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hh_tp(hap->list[i])!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(s->score == 1) o++; + } + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match == 1 && o > 0) { + overlap_list->list[ii].is_match = 2; + // fprintf(stderr, "[M::%s] rid::%u\t%.*s\n", __func__, overlap_list->list[ii].y_id, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id)); + } + } + + + for (k = 1, l = 0; k <= hap->length; ++k) { ///reset snp_stat + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match==1) { + for (i = l; i < k; i++) { + if(hh_tp(hap->list[i])==1) { + hap->snp_stat.a[hap->list[i].overlapSite].score = -1; + } + } + } + l = k; + } + } + } + + + + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match==2) { + overlap_list->list[ii].strong = 1; + overlap_list->mapped_overlaps_length -= + overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; + } else if(overlap_list->list[ii].is_match==1) { + for (i = l; i < k; i++) { + if(hh_tp(hap->list[i])==1 || hh_tp(hap->list[i])==0) { + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if((s->score == 1) && (!(s->occ_0 < 2 || s->occ_1 < 2))) { + overlap_list->list[ii].strong = 1; + if(hh_tp(hap->list[i])==1) { + overlap_list->list[ii].is_match = 2; + overlap_list->mapped_overlaps_length -= + overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; + // fprintf(stderr, "[M::%s] rid::%u\t%.*s\n", __func__, overlap_list->list[ii].y_id, (int)Get_NAME_LENGTH(R_INF, overlap_list->list[ii].y_id), Get_NAME(R_INF, overlap_list->list[ii].y_id)); + break; + } + } + } + + } + } + l = k; + } + } +} + + +inline int64_t comput_sc_rphase(SnpStats *ai, uint64_t id, SnpStats *aj, uint64_t jd, haplotype_evdience *za, uint64_t occ0_cut) +{ + if(ai->site == aj->site) return INT64_MIN; + // if(ai->occ_0 < occ0_cut || aj->occ_0 < occ0_cut) return INT64_MIN; + haplotype_evdience *iz = NULL, *jz = NULL; int64_t in, jn, ik, jk, nn[2]; uint8_t fi, fj; + iz = za + ai->non_homopolymer_num; in = ai->homopolymer_num - ai->non_homopolymer_num; + jz = za + aj->non_homopolymer_num; jn = aj->homopolymer_num - aj->non_homopolymer_num; + + for (ik = jk = nn[0] = nn[1] = 0; (ik < in) && (jk < jn); ik++) { + for (; (jk < jn) && (jz[jk].overlapID < iz[ik].overlapID); jk++); + if((jk < jn) && (jz[jk].overlapID == iz[ik].overlapID)) { + + fi = 2; + if(hh_tp(iz[ik]) == 0) { + fi = 0; + } else if(iz[ik].overlapSite == id){ + fi = 1; + } + + fj = 2; + if(hh_tp(jz[jk]) == 0) { + fj = 0; + } else if(jz[jk].overlapSite == jd){ + fj = 1; + } + + if((fi == 2) && (fj == 2) && (iz[ik].overlapSite != ((uint32_t)-1)) && (jz[jk].overlapSite != ((uint32_t)-1))) {///for rare cases + fi = fj = 0; + } + + if(fi == 2 || fj == 2) return INT64_MIN; + if(fi != fj) return INT64_MIN; + nn[fi]++; + } + } + + if(nn[0] > 0 && nn[1] > 0) return 1; + return INT64_MIN; +} + + +inline void comput_sc_rphase_hybrid(SnpStats *ai, uint64_t id, SnpStats *aj, uint64_t jd, haplotype_evdience *za, uint64_t occ0_cut, overlap_region_alloc *ol, uint64_t tcut, int64_t *sca, int64_t *sch) +{ + (*sca) = (*sch) = INT64_MIN; + if(ai->site == aj->site) return; + // if(ai->occ_0 < occ0_cut || aj->occ_0 < occ0_cut) return INT64_MIN; + haplotype_evdience *iz = NULL, *jz = NULL; int64_t in, jn, ik, jk, na[2], nh[2]; uint8_t fi, fj, ra = 0, rh = 0; + iz = za + ai->non_homopolymer_num; in = ai->homopolymer_num - ai->non_homopolymer_num; + jz = za + aj->non_homopolymer_num; jn = aj->homopolymer_num - aj->non_homopolymer_num; + + for (ik = jk = na[0] = na[1] = nh[0] = nh[1] = 0; (ik < in) && (jk < jn); ik++) { + for (; (jk < jn) && (jz[jk].overlapID < iz[ik].overlapID); jk++); + if((jk < jn) && (jz[jk].overlapID == iz[ik].overlapID)) { + + fi = 2; + if(hh_tp(iz[ik]) == 0) { + fi = 0; + } else if(iz[ik].overlapSite == id){ + fi = 1; + } + + fj = 2; + if(hh_tp(jz[jk]) == 0) { + fj = 0; + } else if(jz[jk].overlapSite == jd){ + fj = 1; + } + + if((fi == 2) && (fj == 2) && (iz[ik].overlapSite != ((uint32_t)-1)) && (jz[jk].overlapSite != ((uint32_t)-1))) {///for rare cases + fi = fj = 0; + } + + if((fi != fj) || (fi == 2) || (fj == 2)) { + ra = 1; + if(ol->list[iz[ik].overlapID].y_id >= tcut) rh = 1;///HiFi + } + if(ra && rh) return; + if(!ra) na[fi]++; + if((!rh) && (ol->list[iz[ik].overlapID].y_id >= tcut)) nh[fi]++; + } + } + + if((!ra) && (na[0] > 0) && (na[1] > 0)) (*sca) = 1; + if((!rh) && (nh[0] > 0) && (nh[1] > 0)) (*sch) = 1; + + // fprintf(stderr, "[M::%s]\tna[0]::%ld\tna[1]::%ld\tnh[0]::%ld\tnh[1]::%ld", __func__, na[0], na[1], nh[0], nh[1]); +} + + +///idx->a:: [0, ch_n) -> tree; +void gen_rphase_path(asg64_v *idx, int64_t *cn, int32_t *f, int64_t *p, uint64_t v0, asg64_v *res) +{ + uint64_t n0 = idx->n, pn = 0, v, w, ct, *ca, k, gi; + kv_push(uint64_t, *idx, v0); + while (idx->n > n0) { + v = idx->a[--idx->n]; + pn = v>>32; v = (uint32_t)v; + f[v] = 1; p[pn++] = v; + ct = ((v>0)?(cn[v]-cn[v-1]):(cn[v])); + ca = ((v>0)?(idx->a+cn[v-1]):(idx->a)); + if(ct) { + for (k = 0; k < ct; k++) { + w = ((pn<<32)|ca[k]); + kv_push(uint64_t, *idx, w); + } + } else { + gi = ((res->n)?((res->a[res->n-1]>>32)+1):(0)); + for (k = 0; k < pn; k++) { + w = (gi<<32)|((uint32_t)p[pn-k-1]); + kv_push(uint64_t, *res, w); + } + } + } +} + +void dbg_prt_rphase_vec(SnpStats *ai, uint64_t id, haplotype_evdience *za) +{ + haplotype_evdience *iz = NULL; int64_t in, ik; uint8_t fi; + iz = za + ai->non_homopolymer_num; in = ai->homopolymer_num - ai->non_homopolymer_num; + + for (ik = 0; ik < in; ik++) { + fi = 2; + if(hh_tp(iz[ik]) == 0) { + fi = 0; + } else if(iz[ik].overlapSite == id){ + fi = 1; + } + fprintf(stderr, "oid::%u(f::%u)\n", iz[ik].overlapID, fi); + } +} + +void gen_rphase_dp0_multiple_path(SnpStats *a, int64_t an, haplotype_evdience *za, Chain_Data *dp, asg64_v *idx, asg64_v *res) +{ + if(an <= 0) return; + int64_t *p, *t, i, k, j, max_f, sc, ch_n, plus = 0, rn; int32_t *f, *ii; uint64_t m; + resize_Chain_Data(dp, an, NULL); idx->n = res->n = 0; + t = dp->tmp; f = dp->score; p = dp->pre; ii = dp->occ; + + for (i = 0; i < an; ++i) { + max_f = 1; ch_n = idx->n; + for (j = i - 1; j >= 0; --j) { + sc = comput_sc_rphase(&a[i], i, &a[j], j, za, 0); + if (sc == INT64_MIN) continue; + sc += f[j]; + if (sc > max_f) { + max_f = sc; + idx->n = ch_n; kv_push(uint64_t, *idx, j); + } else if (sc == max_f) { + kv_push(uint64_t, *idx, j); + } + } + + f[i] = max_f; p[i] = idx->n; ii[i] = 0; + if(f[i] < plus) plus = f[i]; + } + ch_n = idx->n; + + for (i = 0; i < an; i++) { + f[i] -= plus; + m = f[i]; m = ((uint32_t)-1) - m; m <<= 32; m |= i; + kv_push(uint64_t, *idx, m); + } + radix_sort_bc64(idx->a + ch_n, idx->a + idx->n); + + for (i = 0; i < an; i++) {///idx->a:: [0, ch_n) -> tree; [ch_n, ch_n + an) -> sort; [ch_n + an, -1) -> path + k = (uint32_t)idx->a[ch_n + i]; + if(ii[k]) continue; + gen_rphase_path(idx, p, ii, t, k, res); + } + + rn = res->n; + for (k = 1, i = 0; k <= rn; k++) { + if(k == rn || (res->a[i]>>32) != (res->a[k]>>32)) { + if(k - i > 0) { + fprintf(stderr, "\n[M::%s]\tcnt::%lu\n", __func__, k - i); + for (j = i; j < k; j++) { + fprintf(stderr, "pos::%u\n", a[(uint32_t)res->a[j]].site); + // if(k - i == 2) { + // dbg_prt_rphase_vec(&(a[(uint32_t)res->a[j]]), (uint32_t)res->a[j], za); + // } + } + } + i = k; + } + } + +} + +int64_t is_hpc_vec(SnpStats *ai, uint64_t id, haplotype_evdience *za) +{ + haplotype_evdience *iz = NULL; int64_t in, ik, n0 = ai->occ_0, n1 = ai->occ_1, f = 0; + iz = za + ai->non_homopolymer_num; in = ai->homopolymer_num - ai->non_homopolymer_num; + + for (ik = 0; ik < in; ik++) { + if(!hh_hp(iz[ik])) continue; + if(hh_tp(iz[ik]) == 0) { + ai->occ_0 -= iz[ik].cov; + } else if(iz[ik].overlapSite == id){ + ai->occ_1 -= iz[ik].cov; + } + } + if((ai->occ_0 < 2 || ai->occ_1 < 2) || (!(ai->occ_0 >= asm_opt.s_hap_cov && ai->occ_1 >= asm_opt.infor_cov))) f = 1; + ai->occ_0 = n0; ai->occ_1 = n1; + // if((sec_check) && (((n0)<=((n0+n1)*0.333333)) || ((n1)<=((n0+n1)*0.333333)))) f = 1; + return f; +} + + +int32_t get_hq_value(SnpStats *ai, uint64_t id, haplotype_evdience *za, int64_t *lq0, int64_t *hq0, int64_t *lq1, int64_t *hq1, uint8_t *ref_a, overlap_region_alloc *ol, uint64_t rid, uint64_t tcut, + uint8_t hf_only, int64_t b_min, int64_t b_idl, int64_t sc_max) +{ + haplotype_evdience *z; int64_t n, k, occ0[2], occ1[2], nn[2], d[2], d_min, sc_w; double br = 0; uint8_t fi, hi; + z = za + ai->non_homopolymer_num; n = ai->homopolymer_num - ai->non_homopolymer_num; + occ0[0] = occ0[1] = occ1[0] = occ1[1] = 0; + nn[0] = 1; nn[1] = 0; + for (k = 0; k < n; k++) { + if((hh_tp(z[k]) == 1) && (z[k].overlapSite != id)) continue; + + nn[hh_tp(z[k])]++; + if ((ol) && (ol->list[z[k].overlapID].y_id < tcut)) hi = 0; + else hi = 1; + if(hf_only && (!hi)) continue; + + + fi = 0; + if((hh_bq(z[k]) > 1)) fi = 1; + + if(hh_tp(z[k]) == 0) occ0[fi]++; + else occ1[fi]++; + } + if(ref_a) { + if((ref_a[ai->site] > 1) || ((rid != ((uint64_t)-1)) && (rid >= tcut))) occ0[1]++; + else occ0[0]++; + } + + (*lq0) = occ0[0]; (*hq0) = occ0[1]; + (*lq1) = occ1[0]; (*hq1) = occ1[1]; + + ///calculate the score of this site + if(nn[0] && nn[0] >= b_min && nn[1] && nn[1] >= b_min) { + return sc_max; + } else { + d[0] = ((nn[0] >= b_idl)?(nn[0] - b_idl):(b_idl - nn[0])); + d[1] = ((nn[1] >= b_idl)?(nn[1] - b_idl):(b_idl - nn[1])); + d_min = MIN(d[0], d[1]); if(d_min > b_idl) d_min = b_idl; + br = 1.0 - ((double)d_min)/((double)b_idl); + sc_w = sc_max * br; if(sc_w < 1) sc_w = 1; + return sc_w; + } +} + +void gen_rphase_dp0_single_path(SnpStats *a, int64_t an, haplotype_evdience *za, Chain_Data *dp, asg64_v *idx, int64_t het_cov, int64_t hom_cov, int64_t n_hap, double cut_rate, uint64_t cut_bd, asg64_v *res, uint8_t *qual_a, uint8_t site_sc) +{ + if(an <= 0) return; + int64_t *p, i, k, j, st, max_f, max_j, sc, ch_n, plus = 0, rn, rn0; int32_t *f, *ii; uint64_t m, cc0, cc = 0, cci, cc_min; int64_t b0l, b0h, b1l, b1h, krn; + resize_Chain_Data(dp, an, NULL); idx->n = res->n = 0; + f = dp->score; p = dp->pre; ii = dp->occ; + cc = ((het_cov > 0)?(het_cov):(hom_cov/n_hap)); cc *= cut_rate; if(cc < cut_bd) cc = cut_bd; cc0 = cc; + cci = ((het_cov > 0)?(het_cov):(hom_cov/n_hap)); cc_min = cci * 0.75; + + // fprintf(stderr, "\n\n\n[M::%s]\tcc::%lu\n\n\n", __func__, cc); + // fprintf(stderr, "\n[M::%s]\tan::%ld\n", __func__, an); + + for (i = 0; i < an; ++i) { + // fprintf(stderr, "[M::%s::i->%ld]\tsite::%u\tocc0::%u\tocc1::%u\tocc2::%u\n", __func__, i, a[i].site, a[i].occ_0, a[i].occ_1, a[i].occ_2); + max_f = 1; max_j = -1; + st = 0; ///if(a[i].occ_0 < cc) st = i; + for (j = i - 1; j >= st; --j) { + sc = comput_sc_rphase(&a[i], i, &a[j], j, za, 0/**cc**/); + if (sc == INT64_MIN) continue; + sc += f[j]; + if (sc > max_f) { + max_f = sc; max_j = j; + } + } + + f[i] = max_f; p[i] = max_j; ii[i] = 0; + if(f[i] < plus) plus = f[i]; + } + + for (i = 0; i < an; i++) { + f[i] -= plus; + m = f[i]; m = ((uint32_t)-1) - m; m <<= 32; m |= i; + kv_push(uint64_t, *idx, m); + } + radix_sort_bc64(idx->a, idx->a + idx->n); + + kv_resize(uint64_t, *res, ((uint64_t)an)); + for (i = rn = 0; i < an; i++) {///idx->a:: [0, ch_n) -> tree; [ch_n, ch_n + an) -> sort; [ch_n + an, -1) -> path + rn0 = rn; + for(k = (uint32_t)idx->a[i]; (k >= 0) && (!ii[k]);) { + res->a[rn++] = k; ii[k] = 1; k = p[k]; + } + // fprintf(stderr, "[M::%s::k0->%u]\trn0::%ld\trn::%ld\n", __func__, (uint32_t)idx->a[i], rn0, rn); + if(rn0 == rn) continue; + m = rn - rn0; m = ((uint32_t)-1) - m; m <<= 32; m |= rn0; + kv_push(uint64_t, *idx, m); + } + + radix_sort_bc64(idx->a + an, idx->a + idx->n); + ch_n = idx->n; + if(!qual_a) { + for (k = an; k < ch_n; k++) { + rn0 = ((uint32_t)idx->a[k]); + rn = ((uint32_t)-1) - (idx->a[k]>>32); + ///r789 + cc = a[res->a[rn0]].occ_2 + a[res->a[rn0]].occ_1 + a[res->a[rn0]].occ_0; cc /= n_hap; + cc *= cut_rate; if(cc < cut_bd) cc = cut_bd; + if(cc > cc0) cc = cc0; + // break; + plus = -1; + if(rn > 1) { + plus = 1; + } else { + if((!is_hpc_vec(&(a[res->a[rn0]]), res->a[rn0], za)) && (a[res->a[rn0]].occ_0 >= cc)) plus = 1; + } + + for (i = 0; i < rn; i++) { + if(a[res->a[rn0 + i]].occ_0 >= cc) { + if(plus > 0 && site_sc) plus = get_hq_value(&(a[res->a[rn0 + i]]), res->a[rn0 + i], za, &b0l, &b0h, &b1l, &b1h, qual_a, NULL, ((uint64_t)-1), ((uint64_t)-1), 0, cc_min, cci, 16); + a[res->a[rn0 + i]].score = plus; + } else { + a[res->a[rn0 + i]].score = -1; + } + } + } + } else { + /** + for (k = an; k < ch_n; k++) { + rn0 = ((uint32_t)idx->a[k]); + rn = ((uint32_t)-1) - (idx->a[k]>>32); + // break; + fprintf(stderr, "\n[M::%s]\tcnt::%lu\n", __func__, rn); + if(rn > 1) { + for (i = 0; i < rn; i++) { + get_hq_value(&(a[res->a[rn0 + i]]), res->a[rn0 + i], za, &b0l, &b0h, &b1l, &b1h, qual_a); + if(b0h > b0l && b0h >= asm_opt.s_hap_cov && b1h > b1l && b1h >= asm_opt.infor_cov) { + a[res->a[rn0 + i]].score = 1; + } else { + a[res->a[rn0 + i]].score = -1; + } + fprintf(stderr, "pos::%u\tsc::%d\tn0::%u\tn1::%u\tn2::%u\tk::%lu\tb0l::%ld\tb0h::%ld\tb1l::%ld\tb1h::%ld\n", a[res->a[rn0 + i]].site, a[res->a[rn0 + i]].score, a[res->a[rn0 + i]].occ_0, a[res->a[rn0 + i]].occ_1, + 1 + a[res->a[rn0 + i]].homopolymer_num - a[res->a[rn0 + i]].non_homopolymer_num - a[res->a[rn0 + i]].occ_0 - a[res->a[rn0 + i]].occ_1, res->a[rn0 + i], b0l, b0h, b1l, b1h); + } + } else { + if((!is_hpc_vec(&(a[res->a[rn0]]), res->a[rn0], za))) { + get_hq_value(&(a[res->a[rn0]]), res->a[rn0], za, &b0l, &b0h, &b1l, &b1h, qual_a); + if(((b0h > b0l) && (b0h > ((b0h + b0l)*0.7)) && (b0h >= asm_opt.s_hap_cov) && (b0h >= (int64_t)cc)) && + ((b1h > b1l) && (b1h > ((b1h + b1l)*0.7)) && (b1h >= asm_opt.infor_cov) && (b1h >= (int64_t)cc))) { + a[res->a[rn0]].score = 1; + } else { + a[res->a[rn0]].score = -1; + } + } + } + } + **/ + for (k = an; k < ch_n; k++) { + rn0 = ((uint32_t)idx->a[k]); + rn = ((uint32_t)-1) - (idx->a[k]>>32); + krn = rn; + // break; + + for (i = 1; (i < rn) && ((a[res->a[rn0 + i]].site + 8) >= a[res->a[rn0 + i - 1]].site); i++); + if(i >= rn) krn = 1; + // fprintf(stderr, "\n\n[M::%s]\tcnt::%lu\tkrn::%ld\n", __func__, rn, krn); + + for (i = 0; i < rn; i++) { + plus = get_hq_value(&(a[res->a[rn0 + i]]), res->a[rn0 + i], za, &b0l, &b0h, &b1l, &b1h, qual_a, NULL, ((uint64_t)-1), ((uint64_t)-1), 0, cc_min, cci, 16); + if(!site_sc) plus = 1; + ///r789 + cc = a[res->a[rn0 + i]].occ_2 + a[res->a[rn0 + i]].occ_1 + a[res->a[rn0 + i]].occ_0; + cc /= n_hap; cc *= cut_rate; if(cc < cut_bd) cc = cut_bd; + if(cc > cc0) cc = cc0; + + if(krn > 1) { + if(b0h > b0l && b0h >= asm_opt.s_hap_cov && b1h > b1l && b1h >= asm_opt.infor_cov) { + a[res->a[rn0 + i]].score = plus; + } else { + a[res->a[rn0 + i]].score = -1; + } + } else { + if(((b0h > b0l) && (b0h > ((b0h + b0l)*0.7)) && (b0h >= asm_opt.s_hap_cov) && (b0h >= (int64_t)cc)) && + ((b1h > b1l) && (b1h > ((b1h + b1l)*0.7)) && (b1h >= asm_opt.infor_cov) && (b1h >= (int64_t)cc))) { + a[res->a[rn0 + i]].score = plus; + } else { + a[res->a[rn0 + i]].score = -1; + } + } + + // fprintf(stderr, "pos::%u\tsc::%d\tn0::%u\tn1::%u\tn2::%u\tk::%lu\tb0l::%ld\tb0h::%ld\tb1l::%ld\tb1h::%ld\tcc::%lu\thet_cov::%ld\thom_cov::%ld\tcc::%lu\n", a[res->a[rn0 + i]].site, a[res->a[rn0 + i]].score, a[res->a[rn0 + i]].occ_0, a[res->a[rn0 + i]].occ_1, + // 1 + a[res->a[rn0 + i]].homopolymer_num - a[res->a[rn0 + i]].non_homopolymer_num - a[res->a[rn0 + i]].occ_0 - a[res->a[rn0 + i]].occ_1, res->a[rn0 + i], b0l, b0h, b1l, b1h, cc, het_cov, hom_cov, cc); + } + + for (i = j = 0; i < rn; i = j) { + plus = a[res->a[rn0 + i]].score; + for (j = i + 1; (j < rn) && ((a[res->a[rn0 + i]].site-a[res->a[rn0 + j]].site) == (j-i)); j++) { + if(a[res->a[rn0 + j]].score == -1) plus = -1; + } + // fprintf(stderr, "[M::%s]\ti::%ld\tj::%ld\tplus::%ld\n", __func__, i, j, plus); + if(plus == -1) { + for (; i < j; i++) { + a[res->a[rn0 + i]].score = plus; + } + } + } + + } + } + +} + + +inline uint64_t get_occ0(SnpStats *ai, uint64_t id, haplotype_evdience *za, overlap_region_alloc *ol, uint64_t rid, uint64_t tcut) +{ + if(tcut == ((uint64_t)-1)) return ai->occ_0; + haplotype_evdience *iz = NULL; uint64_t in, ik, f = 0; + iz = za + ai->non_homopolymer_num; in = ai->homopolymer_num - ai->non_homopolymer_num; + + for (ik = 0; ik < in; ik++) { + if((hh_tp(iz[ik]) == 0) && (ol->list[iz[ik].overlapID].y_id >= tcut)) f++; + } + if(rid >= tcut) f++; + return f; +} + +void gen_rphase_dp0_single_path_hybrid_0(SnpStats *a, int64_t an, haplotype_evdience *za, int32_t *f, int64_t *p, int32_t *ii, uint8_t *qual_a, uint64_t *ra, asg64_v *idx, int64_t plus, uint64_t cc, uint64_t cci, uint64_t cc_min, + double h_rate, overlap_region_alloc *ol, uint64_t rid, uint64_t tcut, uint64_t hf_only, int64_t n_hap, double cut_rate, uint64_t cut_bd, uint64_t site_sc) +{ + int64_t i, j, k, rn, rn0, ch_n; uint64_t m, cc0 = cc; idx->n = 0; int64_t b0l, b0h, b1l, b1h, krn; + for (i = 0; i < an; i++) { + f[i] -= plus; + m = f[i]; m = ((uint32_t)-1) - m; m <<= 32; m |= i; + kv_push(uint64_t, *idx, m); + ii[i] = 0; + } + radix_sort_bc64(idx->a, idx->a + idx->n); + + for (i = rn = 0; i < an; i++) {///idx->a:: [0, ch_n) -> tree; [ch_n, ch_n + an) -> sort; [ch_n + an, -1) -> path + rn0 = rn; + for(k = (uint32_t)idx->a[i]; (k >= 0) && (!ii[k]);) { + ra[rn++] = k; ii[k] = 1; k = p[k]; + } + if(rn0 == rn) continue; + m = rn - rn0; m = ((uint32_t)-1) - m; m <<= 32; m |= rn0; + kv_push(uint64_t, *idx, m); + } + + radix_sort_bc64(idx->a + an, idx->a + idx->n); + ch_n = idx->n; + if(!qual_a) { + for (k = an; k < ch_n; k++) { + rn0 = ((uint32_t)idx->a[k]); + rn = ((uint32_t)-1) - (idx->a[k]>>32); + + ///r789 + cc = a[ra[rn0]].occ_2 + a[ra[rn0]].occ_1 + a[ra[rn0]].occ_0; cc /= n_hap; + cc *= cut_rate; if(cc < cut_bd) cc = cut_bd; + if(cc > cc0) cc = cc0; + + // break; + plus = -1; + if(rn > 1) { + plus = 1; + } else { + // if((!is_hpc_vec(&(a[ra[rn0]]), ra[rn0], za)) && (a[ra[rn0]].occ_0 >= cc)) plus = 1; + if((!is_hpc_vec(&(a[ra[rn0]]), ra[rn0], za)) && (get_occ0((&a[ra[rn0]]), ra[rn0], za, ol, rid, tcut) >= cc)) plus = 1; + } + + if(hf_only && plus == -1) continue; + for (i = 0; i < rn; i++) { + // if(a[ra[rn0 + i]].occ_0 >= cc) { + if(hf_only && a[ra[rn0 + i]].score > 0) continue; + if(get_occ0((&a[ra[rn0 + i]]), ra[rn0 + i], za, ol, rid, tcut) >= cc) { + if(plus > 0 && site_sc) plus = get_hq_value(&(a[ra[rn0 + i]]), ra[rn0 + i], za, &b0l, &b0h, &b1l, &b1h, qual_a, ol, rid, tcut, hf_only, cc_min, cci, 16); + a[ra[rn0 + i]].score = plus; + } else if(!hf_only) { + a[ra[rn0 + i]].score = -1; + } + } + } + } else { + + for (k = an; k < ch_n; k++) { + rn0 = ((uint32_t)idx->a[k]); + rn = ((uint32_t)-1) - (idx->a[k]>>32); + krn = rn; + // break; + + for (i = 1; (i < rn) && ((a[ra[rn0 + i]].site + 8) >= a[ra[rn0 + i - 1]].site); i++); + if(i >= rn) krn = 1; + + fprintf(stderr, "\n\n[M::%s]\tcnt::%lu\tkrn::%ld\n", __func__, rn, krn); + + for (i = 0; i < rn; i++) { + if(hf_only && a[ra[rn0 + i]].score > 0) continue; + plus = get_hq_value(&(a[ra[rn0 + i]]), ra[rn0 + i], za, &b0l, &b0h, &b1l, &b1h, qual_a, ol, rid, tcut, hf_only, cc_min, cci, 16); + if(!site_sc) plus = 1; + ///r789 + cc = a[ra[rn0 + i]].occ_2 + a[ra[rn0 + i]].occ_1 + a[ra[rn0 + i]].occ_0; + cc /= n_hap; cc *= cut_rate; if(cc < cut_bd) cc = cut_bd; + if(cc > cc0) cc = cc0; + + if(krn > 1) { + if(b0h > b0l && b0h >= asm_opt.s_hap_cov && b1h > b1l && b1h >= asm_opt.infor_cov) { + a[ra[rn0 + i]].score = plus; + } else { + a[ra[rn0 + i]].score = -1; + } + } else { + if(((b0h > b0l) && (b0h > ((b0h + b0l)*0.7)) && (b0h >= asm_opt.s_hap_cov) && (b0h >= (int64_t)cc)) && + ((b1h > b1l) && (b1h > ((b1h + b1l)*0.7)) && (b1h >= asm_opt.infor_cov) && (b1h >= (int64_t)cc))) { + a[ra[rn0 + i]].score = plus; + } else { + a[ra[rn0 + i]].score = -1; + } + } + + fprintf(stderr, "+[M::%s]\tsite::%u\tsc::%d\tn0::%u\tn1::%u\n", __func__, a[ra[rn0 + i]].site, a[ra[rn0 + i]].score, a[ra[rn0 + i]].occ_0, a[ra[rn0 + i]].occ_1); + + // if(hf_only) { + // fprintf(stderr, "pos::%u\tsc::%d\tn0::%u\tn1::%u\tn2::%u\tk::%lu\tb0l::%ld\tb0h::%ld\tb1l::%ld\tb1h::%ld\n", a[ra[rn0 + i]].site, a[ra[rn0 + i]].score, a[ra[rn0 + i]].occ_0, a[ra[rn0 + i]].occ_1, + // 1 + a[ra[rn0 + i]].homopolymer_num - a[ra[rn0 + i]].non_homopolymer_num - a[ra[rn0 + i]].occ_0 - a[ra[rn0 + i]].occ_1, ra[rn0 + i], b0l, b0h, b1l, b1h); + // } + + } + + for (i = j = 0; i < rn; i = j) { + plus = a[ra[rn0 + i]].score; + for (j = i + 1; (j < rn) && ((a[ra[rn0 + i]].site-a[ra[rn0 + j]].site) == (j-i)); j++) { + if(a[ra[rn0 + j]].score == -1) plus = -1; + } + // fprintf(stderr, "[M::%s]\ti::%ld\tj::%ld\tplus::%ld\n", __func__, i, j, plus); + if(plus == -1) { + for (; i < j; i++) { + a[ra[rn0 + i]].score = plus; + } + } + } + + } + } +} + + +void gen_rphase_dp0_single_path_hybrid_0_multi(SnpStats *a, int64_t an, haplotype_evdience *za, int32_t *f, int64_t *p, int32_t *ii, uint8_t *qual_a, uint64_t *rz, asg64_v *idx, int64_t plus, uint64_t cc, uint64_t cci, uint64_t cc_min, + overlap_region_alloc *ol, uint64_t rid, uint64_t tcut, uint64_t hf_only, int64_t n_hap, double cut_rate, uint64_t cut_bd, uint64_t site_sc) +{ + int64_t ri, rj, rk, rn; uint64_t m, cc0 = cc, occ0; idx->n = 0; int64_t b0l, b0h, b1l, b1h, krn; + for (ri = 0; ri < an; ri++) { + f[ri] -= plus; + m = f[ri]; m = ((uint32_t)-1) - m; m <<= 32; m |= ri; + kv_push(uint64_t, *idx, m); + ii[ri] = 0; + } + radix_sort_bc64(idx->a, idx->a + idx->n); + + for (ri = 0; ri < an; ri++) { + rk = (uint32_t)idx->a[ri]; + if(ii[rk]) continue; + for(rn = 0; (rk >= 0);) {///r826 + rz[rn++] = rk; /**ii[rk] = 1;**/ rk = p[rk];///r826 + } + // assert(rn > 0); + + if(qual_a) { + krn = rn; + for (rk = 1; (rk < rn) && ((a[rz[rk]].site + 8) >= a[rz[rk - 1]].site); rk++); + if(rk >= rn) krn = 1; + + for (rk = 0; rk < rn; rk++) { + if(a[rz[rk]].score > 0) { + if(ii[rz[rk]]) continue;///has been set + ii[rz[rk]] = 1; + if(hf_only) continue; + } + ii[rz[rk]] = 1; + + plus = get_hq_value(&(a[rz[rk]]), rz[rk], za, &b0l, &b0h, &b1l, &b1h, qual_a, ol, rid, tcut, hf_only, cc_min, cci, 16); + if(!site_sc) plus = krn;//plus = 1; + ///r789 + cc = a[rz[rk]].occ_2 + a[rz[rk]].occ_1 + a[rz[rk]].occ_0; + cc /= n_hap; cc *= cut_rate; if(cc < cut_bd) cc = cut_bd; + if(cc > cc0) cc = cc0; + + if(krn > 1) { + if(b0h > b0l && b0h >= asm_opt.s_hap_cov && b1h > b1l && b1h >= asm_opt.infor_cov) { + a[rz[rk]].score = plus; + } else { + a[rz[rk]].score = -1; + } + } else { + if(((b0h > b0l) && (b0h > ((b0h + b0l)*0.7)) && (b0h >= asm_opt.s_hap_cov) && (b0h >= (int64_t)cc)) && + ((b1h > b1l) && (b1h > ((b1h + b1l)*0.7)) && (b1h >= asm_opt.infor_cov) && (b1h >= (int64_t)cc))) { + a[rz[rk]].score = plus; + } else { + a[rz[rk]].score = -1; + } + } + + // fprintf(stderr, "+[M::%s]\tsite::%u\tsc::%d\tn0::%u\tn1::%u\trn::%ld\tkrn::%ld\n", __func__, a[rz[rk]].site, a[rz[rk]].score, a[rz[rk]].occ_0, a[rz[rk]].occ_1, rn, krn); + + // if(hf_only) { + // fprintf(stderr, "pos::%u\tsc::%d\tn0::%u\tn1::%u\tn2::%u\tk::%lu\tb0l::%ld\tb0h::%ld\tb1l::%ld\tb1h::%ld\n", a[ra[rn0 + i]].site, a[ra[rn0 + i]].score, a[ra[rn0 + i]].occ_0, a[ra[rn0 + i]].occ_1, + // 1 + a[ra[rn0 + i]].homopolymer_num - a[ra[rn0 + i]].non_homopolymer_num - a[ra[rn0 + i]].occ_0 - a[ra[rn0 + i]].occ_1, ra[rn0 + i], b0l, b0h, b1l, b1h); + // } + } + + for (rk = rj = 0; rk < rn; rk = rj) { + plus = a[rz[rk]].score; + for (rj = rk + 1; (rj < rn) && ((a[rz[rk]].site-a[rz[rj]].site) == (rj-rk)); rj++) { + if(a[rz[rj]].score == -1) plus = -1; + } + // fprintf(stderr, "[M::%s]\ti::%ld\tj::%ld\tplus::%ld\n", __func__, i, j, plus); + if(plus == -1) { + for (; rk < rj; rk++) { + a[rz[rk]].score = plus; + } + } + } + } else { + krn = rn; + for (rk = 0; rk < rn; rk++) { + if(a[rz[rk]].score > 0) { + if(ii[rz[rk]]) continue;///has been set + ii[rz[rk]] = 1; + if(hf_only) continue; + } + ii[rz[rk]] = 1; + + ///r789 + cc = a[rz[rk]].occ_2 + a[rz[rk]].occ_1 + a[rz[rk]].occ_0; cc /= n_hap; + cc *= cut_rate; if(cc < cut_bd) cc = cut_bd; + if(cc > cc0) cc = cc0; + + // break; + plus = -1; occ0 = (uint64_t)-1; + if(rn > 1) { + plus = krn/**1**/; + } else { + if(!is_hpc_vec(&(a[rz[rk]]), rz[rk], za)) { + occ0 = get_occ0((&a[rz[rk]]), rz[rk], za, ol, rid, tcut); + if(occ0 >= cc) plus = krn/**1**/; + } + } + if(hf_only && plus == -1) continue; + + if(occ0 == (uint64_t)-1) occ0 = get_occ0((&a[rz[rk]]), rz[rk], za, ol, rid, tcut); + if(occ0 >= cc) { + if(plus > 0 && site_sc) plus = get_hq_value(&(a[rz[rk]]), rz[rk], za, &b0l, &b0h, &b1l, &b1h, qual_a, ol, rid, tcut, hf_only, cc_min, cci, 16); + a[rz[rk]].score = plus; + } else if(!hf_only) { + a[rz[rk]].score = -1; + } + } + } + } +} + +void gen_rphase_dp0_single_path_multi(SnpStats *a, int64_t an, haplotype_evdience *za, Chain_Data *dp, asg64_v *idx, int64_t het_cov, int64_t hom_cov, int64_t n_hap, double cut_rate, uint64_t cut_bd, asg64_v *res, uint8_t *qual_a, uint8_t site_sc) +{ + if(an <= 0) return; + int64_t *p, ri, rj, st, max_f, max_j, sc, plus = 0; int32_t *f, *ii; uint64_t cc = 0, cci, cc_min; + resize_Chain_Data(dp, an, NULL); idx->n = res->n = 0; + f = dp->score; p = dp->pre; ii = dp->occ; + cc = ((het_cov > 0)?(het_cov):(hom_cov/n_hap)); cc *= cut_rate; if(cc < cut_bd) cc = cut_bd; + cci = ((het_cov > 0)?(het_cov):(hom_cov/n_hap)); cc_min = cci * 0.75; + + // fprintf(stderr, "\n\n\n[M::%s]\tcc::%lu\n\n\n", __func__, cc); + // fprintf(stderr, "[M::%s]\tan::%ld\n", __func__, an); + + for (ri = 0; ri < an; ++ri) { + // fprintf(stderr, "[M::%s::i->%ld]\tsite::%u\tocc0::%u\tocc1::%u\tocc2::%u\n", __func__, ri, a[ri].site, a[ri].occ_0, a[ri].occ_1, a[ri].occ_2); + max_f = 1; max_j = -1; + st = 0; ///if(a[i].occ_0 < cc) st = i; + for (rj = ri - 1; rj >= st; --rj) { + sc = comput_sc_rphase(&a[ri], ri, &a[rj], rj, za, 0/**cc**/); + if (sc == INT64_MIN) continue; + sc += f[rj]; + if (sc > max_f) { + max_f = sc; max_j = rj; + } + } + + f[ri] = max_f; p[ri] = max_j; ii[ri] = 0; + if(f[ri] < plus) plus = f[ri]; + } + + kv_resize(uint64_t, *res, ((uint64_t)an)); + gen_rphase_dp0_single_path_hybrid_0_multi(a, an, za, f, p, ii, qual_a, res->a, idx, plus, cc, cci, cc_min, NULL, ((uint64_t)-1), ((uint64_t)-1), 0, n_hap, cut_rate, cut_bd, site_sc); +} + +void gen_rphase_dp0_single_path_hybrid(SnpStats *a, int64_t an, haplotype_evdience *za, Chain_Data *dp, asg64_v *idx, int64_t het_cov, int64_t hom_cov, int64_t n_hap, double cut_rate, double cut_rate_hf, uint64_t cut_bd, asg64_v *res, uint8_t *qual_a, overlap_region_alloc *ol, uint64_t rid, uint64_t tcut, uint64_t site_sc) +{ + if(an <= 0) return; + int64_t *p_h, *p_a, i, j, st, max_f_h, max_f_a, max_j_h, max_j_a, sc_h, sc_a, plus_h = 0, plus_a = 0; int32_t *f_h, *f_a, *ii_h, *ii_a; uint64_t cc = 0, cc0 = 0, cci, cc_min; + resize_Chain_Data(dp, (an<<1), NULL); idx->n = res->n = 0; + f_h = dp->score; f_a = dp->score + an; + p_h = dp->pre; p_a = dp->pre + an; + ii_h = dp->occ; ii_a = dp->occ + an; + cc = ((het_cov > 0)?(het_cov):(hom_cov/n_hap)); cc *= cut_rate; if(cc < cut_bd) cc = cut_bd; + cci = ((het_cov > 0)?(het_cov):(hom_cov/n_hap)); cc_min = cci * 0.75; + + for (i = 0; i < an; ++i) { + // fprintf(stderr, "+[M::%s::i->%ld]\tsite::%u\tn0::%u\tn1::%u\n", __func__, i, a[i].site, a[i].occ_0, a[i].occ_1); + max_f_h = max_f_a = 1; max_j_h = max_j_a = -1; + st = 0; ///if(a[i].occ_0 < cc) st = i; + for (j = i - 1; j >= st; --j) { + // fprintf(stderr, "j::%ld\t", j); + comput_sc_rphase_hybrid(&a[i], i, &a[j], j, za, 0, ol, tcut, &sc_a, &sc_h); + // fprintf(stderr, "\n"); + if (sc_a != INT64_MIN) { + sc_a += f_a[j]; + if (sc_a > max_f_a) { + max_f_a = sc_a; max_j_a = j; + } + } + if(sc_h != INT64_MIN) { + sc_h += f_h[j]; + if (sc_h > max_f_h) { + max_f_h = sc_h; max_j_h = j; + } + } + } + + f_a[i] = max_f_a; p_a[i] = max_j_a; ii_a[i] = 0; + f_h[i] = max_f_h; p_h[i] = max_j_h; ii_h[i] = 0; + if(f_a[i] < plus_a) plus_a = f_a[i]; + if(f_h[i] < plus_h) plus_h = f_h[i]; + // fprintf(stderr, "-[M::%s]\tf_a::%d\tp_a::%ld\n", __func__, f_a[i], p_a[i]); + // fprintf(stderr, "-[M::%s]\tf_h::%d\tp_h::%ld\n", __func__, f_h[i], p_h[i]); + } + + // if(rid == 1784) { + // fprintf(stderr, "[M::%s-id::%lu] tcut::%lu, cc::%lu\n", __func__, rid, tcut, cc); + // } + + + kv_resize(uint64_t, *res, ((uint64_t)an)); + gen_rphase_dp0_single_path_hybrid_0_multi(a, an, za, f_a, p_a, ii_a, qual_a, res->a, idx, plus_a, cc, cci, cc_min, ol, rid, (uint64_t)-1, 0, n_hap, cut_rate, cut_bd, site_sc); + + cc0 = cc; cc = ((het_cov > 0)?(het_cov):(hom_cov/n_hap)); cc *= (((double)R_INF.tr[1])/((double)(R_INF.tr[0] + R_INF.tr[1]))); cc *= cut_rate_hf; + if(cc < ((uint64_t)(MAX(asm_opt.s_hap_cov, asm_opt.infor_cov) + 1))) cc = MAX(asm_opt.s_hap_cov, asm_opt.infor_cov) + 1; + if(cc <= 0) cc = 1; + if(cc < cc0) cc = cc0; + /**if(rid >= tcut)**/ gen_rphase_dp0_single_path_hybrid_0_multi(a, an, za, f_h, p_h, ii_h, qual_a, res->a, idx, plus_h, cc, cci, cc_min, ol, rid, tcut, 1, n_hap, cut_rate, cut_bd, site_sc);///additional SNPs +} + +inline void fill_incom(asg64_v *om, uint64_t oid, uint64_t pe, uint64_t *idx_a, int64_t idx_n, uint64_t qid) +{ + if(om->a[oid] == ((uint64_t)-1)) { + om->a[oid] = pe; + return; + } + + uint64_t ps = om->a[oid]; int64_t k; + for (k = idx_n - 1; idx_a[k] != ps; k--); + // if(!(k >= 0)) { + // fprintf(stderr, "qid::%lu, oid::%lu, pe::%lu, ps::%lu, idx_n::%ld\n", qid, oid, pe, ps, idx_n); + // } + assert(k >= 0); + for (k++; k < idx_n; k++) { + kv_push(uint64_t, *om, ((oid<<32)|(idx_a[k]))); + } + om->a[oid] = pe; +} + +void get_wqual(uint64_t zid, uint64_t zpos, uint64_t zrev, asg8_v *v, uint8_t *va, uint64_t scw, uint64_t *tqual, uint64_t *wqual) +{ + (*tqual) = (*wqual) = 0; + uint64_t s, e, k, wk, wsc, msc, l = Get_READ_LENGTH((R_INF), (zid)); uint8_t *a; + s = ((zpos + 1 >= scw)?(zpos + 1 - scw):(0)); + e = zpos + scw; if(e > l) e = l; + + if(v) { + retrive_bqual(v, NULL, zid, s, e, zrev, sc_bn); a = v->a; + } else { + a = va + s; + } + + (*tqual) = a[zpos - s]; + for (k = s, wk = wsc = 0; k < e && wk < scw; k++, wk++) { + wsc += a[k - s]; + } + msc = wsc; + + if(k < e) { + assert(wk == scw); + for (; k < e; k++) { + wsc -= a[k - scw - s]; + wsc += a[k - s]; + if(wsc < msc) msc = wsc; + } + } + + (*wqual) = round(((double)msc)/((double)wk)); + // fprintf(stderr, "[M::%s] s::%lu, e::%lu, wk::%lu, scw::%lu, msc/wk::%lu, wqual::%lu\n", __func__, s, e, wk, scw, msc/wk, (*wqual)); +} + +void call_rphase_sc(haplotype_evdience_alloc *hl, overlap_region_alloc *ol, double st_rate, uint64_t st_max, asg64_v *idx, asg64_v *res, uint64_t rid, uint8_t *qa, uint64_t tcut) +{ + if(hl->length <= 0) return; + + uint64_t k, l, i, i0, o, ii, m_snp_stat, m_snp_stat0, m_list, m1, c0, c1, rev_n, tqual, wqual, hq_cut = 2; uint32_t hq[5], hp[4], is_st; SnpStats *s; haplotype_evdience ev; char mc; + uint16_t fl = ((res && idx)?(1):(0)); + + + if(fl) { + kv_resize(uint64_t, *res, ol->length); memset(res->a, -1, sizeof((*(res->a)))*ol->length); res->n = ol->length; + idx->n = 0; + } + for (k = 1, l = 0, i = m_snp_stat = m_list = 0; k <= hl->snp_stat.n; ++k) {///filter snps + if(k == hl->snp_stat.n || hl->snp_stat.a[k].site != hl->snp_stat.a[l].site) { + for (; i < hl->length && hl->list[i].site != hl->snp_stat.a[l].site; i++); + assert(i < hl->length && hl->list[i].site == hl->snp_stat.a[l].site); + for (o = l, m1 = 0; o < k; o++) { + s = &(hl->snp_stat.a[o]); + // fprintf(stderr, "+[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, s->site, s->occ_0, s->occ_1); + if((s->occ_0 < 2 || s->occ_1 < 2) || (is_st_bs((*s), st_rate, st_max)) || (!(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov))) { + continue; + } + // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, s->site, s->occ_0, s->occ_1); + m1++; + } + + if(m1) { + hq[0] = hq[1] = hq[2] = hq[3] = hq[4] = 0; hp[0] = hp[1] = hp[2] = hp[3] = ((uint32_t)-1); + for (i0 = i, c0 = rev_n = 0; i0 < hl->length && hl->list[i0].site == hl->snp_stat.a[l].site; i0++) { + hl->list[i0].site = ((uint32_t)-1); + if(hh_tp(hl->list[i0]) == 0) { + c0 += 1/**hl->list[i0].cov**/; + if((ol->list[hl->list[i0].overlapID].y_pos_strand == 0)) rev_n += 1/**hl->list[i0].cov**/; + } + if(qa) { + if(hh_tp(hl->list[i0]) == 0) { + if((hh_bq(hl->list[i0]) > 1) || (hh_wq(hl->list[i0]) > 1)) hq[4]++; + } else { + hp[seq_nt6_table[(uint8_t)(hl->list[i0].misBase)]] = hl->list[i0].overlapSite; + if((hh_bq(hl->list[i0]) > 1) || (hh_wq(hl->list[i0]) > 1)) { + hq[seq_nt6_table[(uint8_t)(hl->list[i0].misBase)]]++; + } + } + } + } + assert(i0 > i); + if(qa) { + if(hp[0] != ((uint32_t)-1) && hq[0] < hq_cut) { + // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, hl->snp_stat.a[hp[0]].site, hl->snp_stat.a[hp[0]].occ_0, hl->snp_stat.a[hp[0]].occ_1); + hl->snp_stat.a[hp[0]].occ_1 = 0; + } + + if(hp[1] != ((uint32_t)-1) && hq[1] < hq_cut) { + // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, hl->snp_stat.a[hp[1]].site, hl->snp_stat.a[hp[1]].occ_0, hl->snp_stat.a[hp[1]].occ_1); + hl->snp_stat.a[hp[1]].occ_1 = 0; + } + + if(hp[2] != ((uint32_t)-1) && hq[2] < hq_cut) { + // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, hl->snp_stat.a[hp[2]].site, hl->snp_stat.a[hp[2]].occ_0, hl->snp_stat.a[hp[2]].occ_1); + hl->snp_stat.a[hp[2]].occ_1 = 0; + } + + if(hp[3] != ((uint32_t)-1) && hq[3] < hq_cut) { + // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, hl->snp_stat.a[hp[3]].site, hl->snp_stat.a[hp[3]].occ_0, hl->snp_stat.a[hp[3]].occ_1); + hl->snp_stat.a[hp[3]].occ_1 = 0; + } + + tqual = wqual = 3; + if(rid < tcut) get_wqual(rid, hl->snp_stat.a[l].site, 0, NULL, qa, sc_wn, &tqual, &wqual); + if(tqual > 1 || wqual > 1) hq[4]++; + // if(hq[4] == 0) { + // fprintf(stderr, "+[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, hl->snp_stat.a[l].site, hl->snp_stat.a[l].occ_0, hl->snp_stat.a[l].occ_1); + // } + } else { + hq[0] = hq[1] = hq[2] = hq[3] = hq[4] = ((uint32_t)-1); + } + + // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\thq[0]::%u\thq[1]::%u\thq[2]::%u\thq[3]::%u\thq[4]::%u\thq_cut::%lu\n", __func__, s->site, s->occ_0, s->occ_1, hq[0], hq[1], hq[2], hq[3], hq[4], hq_cut); + + if((hq[4] >= hq_cut) && (hq[0] >= hq_cut || hq[1] >= hq_cut || hq[2] >= hq_cut || hq[3] >= hq_cut)) { + for (o = l, m_snp_stat0 = m_snp_stat; o < k; o++) { + s = &(hl->snp_stat.a[o]); + if((s->occ_0 < 2 || s->occ_1 < 2) || (is_st_bs((*s), st_rate, st_max)) || (!(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov))) { + continue; + } + + hl->snp_stat.a[m_snp_stat] = *s; + for (ii = i, c1 = 0; ii < i0; ii++) { + if(((hl->list[ii].overlapSite == o) && (hl->list[ii].site == ((uint32_t)-1))) || (hh_tp(hl->list[ii]) == 0)) { + hl->list[ii].overlapSite = m_snp_stat; + hl->list[ii].site = hl->snp_stat.a[o].site; + if(hh_tp(hl->list[ii]) == 1) c1 += 1/**hl->list[ii].cov**/;///not correct if we don't do read correction + } + } + // fprintf(stderr, "-0-[M::%s]\tsite::%u\tc0::%lu\tc1::%lu\tm_snp_stat::%lu\n", __func__, s->site, c0, c1, m_snp_stat); + hl->snp_stat.a[m_snp_stat].occ_0 = c0 + 1; + hl->snp_stat.a[m_snp_stat].occ_1 = c1; + hl->snp_stat.a[m_snp_stat].overlap_num = rev_n + 1; + hl->snp_stat.a[m_snp_stat].non_homopolymer_num = m_list; + hl->snp_stat.a[m_snp_stat++].score = -1; + } + + for (ii = i, m1 = m_list; ii < i0; ii++) { + if((hl->list[ii].site == ((uint32_t)-1))) { + hl->list[ii].overlapSite = ((uint32_t)-1); + hl->list[ii].site = hl->snp_stat.a[l].site; + } + if(fl) fill_incom(res, hl->list[ii].overlapID, hl->list[ii].site, idx->a, idx->n, ol->list[0].x_id); + hl->list[m_list++] = hl->list[ii]; + } + radix_sort_haplotype_evdience_id_srt(hl->list + m1, hl->list + m_list); + for (ii = m_snp_stat0; ii < m_snp_stat; ii++) { + hl->snp_stat.a[ii].homopolymer_num = m_list; + } + + i = i0; + + if(fl) kv_push(uint64_t, *idx, hl->snp_stat.a[l].site); + } + } + + l = k; + } + } + hl->snp_stat.n = m_snp_stat; hl->length = m_list; + if(hl->snp_stat.n == 0 || hl->length == 0) return; + + + // fprintf(stderr, "+[M::%s]\tres->n::%lu\tol->length::%lu\tsnp_stat.n::%lu\n", __func__, (uint64_t)res->n, ol->length, (uint64_t)hl->snp_stat.n); + ///fill incomplete values + if((fl) && (res->n > ol->length)) { + // fprintf(stderr, "\n[M::%s]\tin_comp::%lu\n", __func__, ((uint64_t)res->n - ol->length)); + for (k = ol->length; k < res->n; k++) { + ev.misBase = 0; + ev.overlapID = res->a[k]>>32; + ev.site = ((uint32_t)res->a[k]); + ev.overlapSite = ((uint32_t)-1); + ev.type = 0; + ev.cov = 1; + addHaplotypeEvdience(hl, &ev, NULL); + // fprintf(stderr, "[M::%s]\toid::%u\tsite::%u\n", __func__, ev.overlapID, ev.site); + } + radix_sort_haplotype_evdience_srt(hl->list, hl->list + hl->length); + + for (k = 1, l = 0, i = 0; k <= hl->snp_stat.n; ++k) { + if(k == hl->snp_stat.n || hl->snp_stat.a[k].site != hl->snp_stat.a[l].site) { + for (; i < hl->length && hl->list[i].site != hl->snp_stat.a[l].site; i++); + assert(i < hl->length && hl->list[i].site == hl->snp_stat.a[l].site); + + m1 = ((uint32_t)-1); mc = 0; + for (i0 = i, c0 = rev_n = 0; i0 < hl->length && hl->list[i0].site == hl->snp_stat.a[l].site; i0++) { + if(hh_tp(hl->list[i0]) == 0) { + c0+=1/**hl->list[i0].cov**/; + if((ol->list[hl->list[i0].overlapID].y_pos_strand == 0)) rev_n += 1/**hl->list[i0].cov**/; + if(hl->list[i0].overlapSite != ((uint32_t)-1)) { + m1 = hl->list[i0].overlapSite; mc = hl->list[i0].misBase; + } + } + // if(hl->snp_stat.a[l].site == 6995) { + // fprintf(stderr, "[M::%s]\tsite::%u\tosite::%u\toid::%u\ttp::%u\n", __func__, hl->list[i0].site, hl->list[i0].overlapSite, hl->list[i0].overlapID, hh_tp(hl->list[i0])); + // } + } + assert(i0 > i); + assert(m1 != ((uint32_t)-1)); + assert(mc != 0); + + + for (ii = i, is_st = 1; ii < i0; ii++) { + if(hh_tp(hl->list[ii]) == 0) { + assert(hl->list[ii].overlapSite == ((uint32_t)-1) || hl->list[ii].overlapSite == m1); + hl->list[ii].overlapSite = m1; hl->list[ii].misBase = mc; + } + if((ii > i) && (hl->list[ii].overlapID <= hl->list[ii-1].overlapID)) { + is_st = 0; + // fprintf(stderr, "[M::%s]\tid::[%u,%u]\tsite::[%u,%u]\n", __func__, hl->list[ii].overlapID, hl->list[ii-1].overlapID, hl->list[ii].overlapSite, hl->list[ii-1].overlapSite); + } + } + if(is_st == 0) radix_sort_haplotype_evdience_id_srt(hl->list + i, hl->list + i0); + // assert(is_st == 1); + + + + for (o = l; o < k; o++) { + s = &(hl->snp_stat.a[o]); + for (ii = i, c1 = 0; ii < i0; ii++) { + if((hl->list[ii].overlapSite == o) && (hh_tp(hl->list[ii]) == 1)) c1 += 1/**hl->list[ii].cov**/;///not correct if we don't do read correction + } + // fprintf(stderr, "-1-[M::%s]\tsite::%u\tc0::%lu\tc1::%lu\n", __func__, s->site, c0, c1); + s->occ_0 = c0 + 1; + s->occ_1 = c1; + s->overlap_num = rev_n + 1; + s->non_homopolymer_num = i; + s->homopolymer_num = i0; + } + + i = i0; + l = k; + } + } + } +} + +/** + * //r829 +void recal_rphase0(overlap_region *z, SnpStats *sa, int64_t sn, haplotype_evdience_alloc *hl, int64_t hn, uint64_t *idx, int64_t idx_n) +{ + int64_t k, z_n = z->w_list.n; + for (k = 0; k < z_n; k++) { + ; + } + +} + +//r829 +void recal_rphase(All_reads *rref, haplotype_evdience_alloc *hl, overlap_region_alloc *ol, UC_Read* g_read, double st_rate, uint64_t st_max, Chain_Data *dp, asg64_v *idx, + asg64_v *res, asg32_v* b32, uint64_t rid, uint8_t *qa, uint64_t tcut, uint64_t site_sc) +{ + if(hl->length <= 0) return; + + call_rphase_sc(hl, ol, st_rate, st_max, NULL, NULL, rid, qa, tcut); + + if(hl->snp_stat.n == 0 || hl->length == 0) return; + + int64_t k, l, i, sn = hl->snp_stat.n, hn = hl->length, os, oe, on = ol->length; + + + kv_resize(uint64_t, *idx, (hl->snp_stat.n<<1)); + uint64_t *srt = idx->a, *crt = idx->a + sn; + + for (k = idx->n = 0; k < sn; ++k) { + srt[idx->n] = UINT32_MAX; + srt[idx->n] -= ((uint64_t)hl->snp_stat.a[k].occ_1); + srt[idx->n] <<= 32; srt[idx->n] |= k; + crt[idx->n] = k; + idx->n++; + } + radix_sort_bc64(srt, srt + idx->n); + + ///cluster nearby snps; when merging a and b, check if a and b occur at same reads + for (k = 0; k < sn; ++k) { + l = ((uint32_t)srt[k]); + if(crt[l] != l) continue; + i = l + 1; + i = l - 1; + + } + + + idx->n = 0; kv_resize(uint64_t, *idx, hl->snp_stat.n); + ///hl->list could be resued + for (k = 1, l = i = 0; k <= sn; ++k) { + if(k == sn || hl->snp_stat.a[k].site != hl->snp_stat.a[l].site) { + for (; i < hn && hl->list[i].site != hl->snp_stat.a[l].site; i++); + assert(i < hn && hl->list[i].site == hl->snp_stat.a[l].site); + os = oe = i; + for (; (i < hn) && (hl->list[i].site == hl->snp_stat.a[l].site); i++) { + hl->list[i].overlapSite = ((uint32_t)-1); + } + oe = i; + + idx->a[idx->n] = os; idx->a[idx->n] <<= 32; idx->a[idx->n] |= ((uint64_t)oe); + idx->n++; + + l = k; + } + } + + for (k = 0; k < on; k++) { + recal_rphase0(&(ol->list[k]), hl->snp_stat.a, sn, hl, hn, idx->a, idx->n); + } +} +**/ + +void gen_rphase_dp_adv(haplotype_evdience_alloc *hl, overlap_region_alloc *ol, UC_Read* g_read, double st_rate, uint64_t st_max, Chain_Data *dp, asg64_v *idx, asg64_v *res, uint64_t rid, uint8_t *qa, uint64_t tcut, uint64_t site_sc) +{ + if(hl->length <= 0) return; + uint64_t k, l, i, i0, o, ii, m_snp_stat, m_snp_stat0, m_list /**m_off**/, m1, c0, c1, rev_n; SnpStats *s; + int64_t het_a, hom_a; + + call_rphase_sc(hl, ol, st_rate, st_max, idx, res, rid, qa, tcut); + + het_a = asm_opt.het_cov; hom_a = asm_opt.hom_cov; + if(asm_opt.het_cov_set >= 0) het_a = asm_opt.het_cov_set; + if(het_a < 0) { + het_a = hom_a/asm_opt.polyploidy; + } else if(het_a > (hom_a/asm_opt.polyploidy)) { + het_a = hom_a/asm_opt.polyploidy; + } + if(tcut == ((uint64_t)-1)) { + // gen_rphase_dp0_single_path(hl->snp_stat.a, hl->snp_stat.n, hl->list, dp, idx, het_a, hom_a, asm_opt.polyploidy, 0.7, 6, res, qv->a, site_sc); + gen_rphase_dp0_single_path_multi(hl->snp_stat.a, hl->snp_stat.n, hl->list, dp, idx, het_a, hom_a, asm_opt.polyploidy, 0.6/**0.7**/, 6, res, qa, site_sc); + } else { + gen_rphase_dp0_single_path_hybrid(hl->snp_stat.a, hl->snp_stat.n, hl->list, dp, idx, het_a, hom_a, asm_opt.polyploidy, 0.6/**0.7**/, 0.4, 6, res, qa, ol, rid, tcut, site_sc); + } + + for (k = 1, l = 0, i = m_snp_stat = m_list = 0; k <= hl->snp_stat.n; ++k) {///filter snps + if(k == hl->snp_stat.n || hl->snp_stat.a[k].site != hl->snp_stat.a[l].site) { + for (; i < hl->length && hl->list[i].site != hl->snp_stat.a[l].site; i++); + assert(i < hl->length && hl->list[i].site == hl->snp_stat.a[l].site); + for (o = l, m1 = 0; o < k; o++) { + s = &(hl->snp_stat.a[o]); + if(s->score == -1) continue; + m1++; + } + + if(m1) { + for (i0 = i, c0 = rev_n = 0; i0 < hl->length && hl->list[i0].site == hl->snp_stat.a[l].site; i0++) { + hl->list[i0].site = ((uint32_t)-1); + if(hh_tp(hl->list[i0]) == 0) { + c0 += 1/**hl->list[i0].cov**/; + if((ol->list[hl->list[i0].overlapID].y_pos_strand == 0)) rev_n += 1/**hl->list[i0].cov**/; + } + } + assert(i0 > i); + + for (o = l, m_snp_stat0 = m_snp_stat; o < k; o++) { + s = &(hl->snp_stat.a[o]); + if(s->score == -1) continue; + + hl->snp_stat.a[m_snp_stat] = *s; + for (ii = i, c1 = 0; ii < i0; ii++) { + if(((hl->list[ii].overlapSite == o) && (hl->list[ii].site == ((uint32_t)-1))) || (hh_tp(hl->list[ii]) == 0)) { + hl->list[ii].overlapSite = m_snp_stat; + hl->list[ii].site = hl->snp_stat.a[o].site; + if(hh_tp(hl->list[ii]) == 1) c1 += 1/**hl->list[ii].cov**/;///not correct if we don't do read correction + } + } + + // if(hl->snp_stat.a[m_snp_stat].site == 4) { + // fprintf(stderr, "[M::%s] occ_0->%lu, occ_1->%lu, site->%u\n", __func__, c0 + 1, c1, hl->snp_stat.a[m_snp_stat].site); + // } + + hl->snp_stat.a[m_snp_stat].occ_0 = c0 + 1; + hl->snp_stat.a[m_snp_stat].occ_1 = c1; + hl->snp_stat.a[m_snp_stat].overlap_num = rev_n + 1; + hl->snp_stat.a[m_snp_stat].non_homopolymer_num = m_list; + ///keep the score//r831 + // if(!site_sc) hl->snp_stat.a[m_snp_stat++].score = -1; + // else m_snp_stat++; + m_snp_stat++; + } + + for (ii = i, m1 = m_list; ii < i0; ii++) { + if((hl->list[ii].site == ((uint32_t)-1))) continue; + hl->list[m_list++] = hl->list[ii]; + } + for (ii = m_snp_stat0; ii < m_snp_stat; ii++) { + hl->snp_stat.a[ii].homopolymer_num = m_list; + } + + i = i0; + } + + l = k; + } + } + hl->snp_stat.n = m_snp_stat; hl->length = m_list; + // fprintf(stderr, "[M::%s] m_snp_stat->%lu\n", __func__, m_snp_stat); +} + +void gen_rphase_dp(haplotype_evdience_alloc *hl, overlap_region_alloc *ol, UC_Read* g_read, double st_rate, uint64_t st_max, Chain_Data *dp, asg64_v *idx, asg64_v *res, uint64_t rid, asg8_v *qv, uint64_t tcut, uint64_t site_sc) +{ + if(hl->length <= 0) return; + + uint64_t k, l, i, i0, o, ii, m_snp_stat, m_snp_stat0, m_list /**m_off**/, m1, c0, c1, rev_n, tqual, wqual, hq_cut = 2; uint32_t hq[5], hp[4], is_st; SnpStats *s; haplotype_evdience ev; char mc; + int64_t het_a, hom_a; + if(rid < tcut) { + retrive_bqual(qv, NULL, rid, -1, -1, 0, sc_bn); + } else { + kv_resize(uint8_t, *qv, (Get_READ_LENGTH(R_INF, rid))); + memset(qv->a, 3, ((Get_READ_LENGTH(R_INF, rid))*sizeof((*(qv->a))))); + } + + + idx->n = 0; + kv_resize(uint64_t, *res, ol->length); memset(res->a, -1, sizeof((*(res->a)))*ol->length); res->n = ol->length; + for (k = 1, l = 0, i = m_snp_stat = m_list = 0; k <= hl->snp_stat.n; ++k) {///filter snps + if(k == hl->snp_stat.n || hl->snp_stat.a[k].site != hl->snp_stat.a[l].site) { + for (; i < hl->length && hl->list[i].site != hl->snp_stat.a[l].site; i++); + assert(i < hl->length && hl->list[i].site == hl->snp_stat.a[l].site); + for (o = l, m1 = 0; o < k; o++) { + s = &(hl->snp_stat.a[o]); + // fprintf(stderr, "+[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, s->site, s->occ_0, s->occ_1); + if((s->occ_0 < 2 || s->occ_1 < 2) || (is_st_bs((*s), st_rate, st_max)) || (!(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov))) { + continue; + } + // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, s->site, s->occ_0, s->occ_1); + m1++; + } + + if(m1) { + hq[0] = hq[1] = hq[2] = hq[3] = hq[4] = 0; hp[0] = hp[1] = hp[2] = hp[3] = ((uint32_t)-1); + for (i0 = i, c0 = rev_n = 0; i0 < hl->length && hl->list[i0].site == hl->snp_stat.a[l].site; i0++) { + hl->list[i0].site = ((uint32_t)-1); + if(hh_tp(hl->list[i0]) == 0) { + c0 += 1/**hl->list[i0].cov**/; + if((ol->list[hl->list[i0].overlapID].y_pos_strand == 0)) rev_n += 1/**hl->list[i0].cov**/; + } + if(qv) { + if(hh_tp(hl->list[i0]) == 0) { + if((hh_bq(hl->list[i0]) > 1) || (hh_wq(hl->list[i0]) > 1)) hq[4]++; + } else { + hp[seq_nt6_table[(uint8_t)(hl->list[i0].misBase)]] = hl->list[i0].overlapSite; + if((hh_bq(hl->list[i0]) > 1) || (hh_wq(hl->list[i0]) > 1)) { + hq[seq_nt6_table[(uint8_t)(hl->list[i0].misBase)]]++; + } + } + } + } + assert(i0 > i); + if(qv) { + if(hp[0] != ((uint32_t)-1) && hq[0] < hq_cut) { + // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, hl->snp_stat.a[hp[0]].site, hl->snp_stat.a[hp[0]].occ_0, hl->snp_stat.a[hp[0]].occ_1); + hl->snp_stat.a[hp[0]].occ_1 = 0; + } + + if(hp[1] != ((uint32_t)-1) && hq[1] < hq_cut) { + // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, hl->snp_stat.a[hp[1]].site, hl->snp_stat.a[hp[1]].occ_0, hl->snp_stat.a[hp[1]].occ_1); + hl->snp_stat.a[hp[1]].occ_1 = 0; + } + + if(hp[2] != ((uint32_t)-1) && hq[2] < hq_cut) { + // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, hl->snp_stat.a[hp[2]].site, hl->snp_stat.a[hp[2]].occ_0, hl->snp_stat.a[hp[2]].occ_1); + hl->snp_stat.a[hp[2]].occ_1 = 0; + } + + if(hp[3] != ((uint32_t)-1) && hq[3] < hq_cut) { + // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, hl->snp_stat.a[hp[3]].site, hl->snp_stat.a[hp[3]].occ_0, hl->snp_stat.a[hp[3]].occ_1); + hl->snp_stat.a[hp[3]].occ_1 = 0; + } + + tqual = wqual = 3; + if(rid < tcut) get_wqual(rid, hl->snp_stat.a[l].site, 0, NULL, qv->a, sc_wn, &tqual, &wqual); + if(tqual > 1 || wqual > 1) hq[4]++; + // if(hq[4] == 0) { + // fprintf(stderr, "+[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, hl->snp_stat.a[l].site, hl->snp_stat.a[l].occ_0, hl->snp_stat.a[l].occ_1); + // } + } else { + hq[0] = hq[1] = hq[2] = hq[3] = hq[4] = ((uint32_t)-1); + } + + // fprintf(stderr, "-[M::%s]\tsite::%u\tn0::%u\tn1::%u\thq[0]::%u\thq[1]::%u\thq[2]::%u\thq[3]::%u\thq[4]::%u\thq_cut::%lu\n", __func__, s->site, s->occ_0, s->occ_1, hq[0], hq[1], hq[2], hq[3], hq[4], hq_cut); + + if((hq[4] >= hq_cut) && (hq[0] >= hq_cut || hq[1] >= hq_cut || hq[2] >= hq_cut || hq[3] >= hq_cut)) { + for (o = l, m_snp_stat0 = m_snp_stat; o < k; o++) { + s = &(hl->snp_stat.a[o]); + if((s->occ_0 < 2 || s->occ_1 < 2) || (is_st_bs((*s), st_rate, st_max)) || (!(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov))) { + continue; + } + + hl->snp_stat.a[m_snp_stat] = *s; + for (ii = i, c1 = 0; ii < i0; ii++) { + if(((hl->list[ii].overlapSite == o) && (hl->list[ii].site == ((uint32_t)-1))) || (hh_tp(hl->list[ii]) == 0)) { + hl->list[ii].overlapSite = m_snp_stat; + hl->list[ii].site = hl->snp_stat.a[o].site; + if(hh_tp(hl->list[ii]) == 1) c1 += 1/**hl->list[ii].cov**/;///not correct if we don't do read correction + } + } + // fprintf(stderr, "-0-[M::%s]\tsite::%u\tc0::%lu\tc1::%lu\tm_snp_stat::%lu\n", __func__, s->site, c0, c1, m_snp_stat); + hl->snp_stat.a[m_snp_stat].occ_0 = c0 + 1; + hl->snp_stat.a[m_snp_stat].occ_1 = c1; + hl->snp_stat.a[m_snp_stat].overlap_num = rev_n + 1; + hl->snp_stat.a[m_snp_stat].non_homopolymer_num = m_list; + hl->snp_stat.a[m_snp_stat++].score = -1; + } + + for (ii = i, m1 = m_list; ii < i0; ii++) { + if((hl->list[ii].site == ((uint32_t)-1))) { + hl->list[ii].overlapSite = ((uint32_t)-1); + hl->list[ii].site = hl->snp_stat.a[l].site; + } + fill_incom(res, hl->list[ii].overlapID, hl->list[ii].site, idx->a, idx->n, ol->list[0].x_id); + hl->list[m_list++] = hl->list[ii]; + } + radix_sort_haplotype_evdience_id_srt(hl->list + m1, hl->list + m_list); + for (ii = m_snp_stat0; ii < m_snp_stat; ii++) { + hl->snp_stat.a[ii].homopolymer_num = m_list; + } + + i = i0; + + kv_push(uint64_t, *idx, hl->snp_stat.a[l].site); + } + } + + l = k; + } + } + hl->snp_stat.n = m_snp_stat; hl->length = m_list; + if(hl->snp_stat.n == 0 || hl->length == 0) return; + + // fprintf(stderr, "+[M::%s]\tres->n::%lu\tol->length::%lu\tsnp_stat.n::%lu\n", __func__, (uint64_t)res->n, ol->length, (uint64_t)hl->snp_stat.n); + ///fill incomplete values + if(res->n > ol->length) { + // fprintf(stderr, "\n[M::%s]\tin_comp::%lu\n", __func__, ((uint64_t)res->n - ol->length)); + for (k = ol->length; k < res->n; k++) { + ev.misBase = 0; + ev.overlapID = res->a[k]>>32; + ev.site = ((uint32_t)res->a[k]); + ev.overlapSite = ((uint32_t)-1); + ev.type = 0; + ev.cov = 1; + addHaplotypeEvdience(hl, &ev, NULL); + // fprintf(stderr, "[M::%s]\toid::%u\tsite::%u\n", __func__, ev.overlapID, ev.site); + } + radix_sort_haplotype_evdience_srt(hl->list, hl->list + hl->length); + + for (k = 1, l = 0, i = 0; k <= hl->snp_stat.n; ++k) { + if(k == hl->snp_stat.n || hl->snp_stat.a[k].site != hl->snp_stat.a[l].site) { + for (; i < hl->length && hl->list[i].site != hl->snp_stat.a[l].site; i++); + assert(i < hl->length && hl->list[i].site == hl->snp_stat.a[l].site); + + m1 = ((uint32_t)-1); mc = 0; + for (i0 = i, c0 = rev_n = 0; i0 < hl->length && hl->list[i0].site == hl->snp_stat.a[l].site; i0++) { + if(hh_tp(hl->list[i0]) == 0) { + c0+=1/**hl->list[i0].cov**/; + if((ol->list[hl->list[i0].overlapID].y_pos_strand == 0)) rev_n += 1/**hl->list[i0].cov**/; + if(hl->list[i0].overlapSite != ((uint32_t)-1)) { + m1 = hl->list[i0].overlapSite; mc = hl->list[i0].misBase; + } + } + // if(hl->snp_stat.a[l].site == 6995) { + // fprintf(stderr, "[M::%s]\tsite::%u\tosite::%u\toid::%u\ttp::%u\n", __func__, hl->list[i0].site, hl->list[i0].overlapSite, hl->list[i0].overlapID, hh_tp(hl->list[i0])); + // } + } + assert(i0 > i); + assert(m1 != ((uint32_t)-1)); + assert(mc != 0); + + + for (ii = i, is_st = 1; ii < i0; ii++) { + if(hh_tp(hl->list[ii]) == 0) { + assert(hl->list[ii].overlapSite == ((uint32_t)-1) || hl->list[ii].overlapSite == m1); + hl->list[ii].overlapSite = m1; hl->list[ii].misBase = mc; + } + if((ii > i) && (hl->list[ii].overlapID <= hl->list[ii-1].overlapID)) { + is_st = 0; + // fprintf(stderr, "[M::%s]\tid::[%u,%u]\tsite::[%u,%u]\n", __func__, hl->list[ii].overlapID, hl->list[ii-1].overlapID, hl->list[ii].overlapSite, hl->list[ii-1].overlapSite); + } + } + if(is_st == 0) radix_sort_haplotype_evdience_id_srt(hl->list + i, hl->list + i0); + // assert(is_st == 1); + + + + for (o = l; o < k; o++) { + s = &(hl->snp_stat.a[o]); + for (ii = i, c1 = 0; ii < i0; ii++) { + if((hl->list[ii].overlapSite == o) && (hh_tp(hl->list[ii]) == 1)) c1 += 1/**hl->list[ii].cov**/;///not correct if we don't do read correction + } + // fprintf(stderr, "-1-[M::%s]\tsite::%u\tc0::%lu\tc1::%lu\n", __func__, s->site, c0, c1); + s->occ_0 = c0 + 1; + s->occ_1 = c1; + s->overlap_num = rev_n + 1; + s->non_homopolymer_num = i; + s->homopolymer_num = i0; + } + + i = i0; + l = k; + } + } + + } + // fprintf(stderr, "-[M::%s]\tres->n::%lu\tol->length::%lu\tsnp_stat.n::%lu\n", __func__, (uint64_t)res->n, ol->length, (uint64_t)hl->snp_stat.n); + // gen_rphase_dp0_multiple_path(hl->snp_stat.a, hl->snp_stat.n, hl->list, dp, idx, res); + het_a = asm_opt.het_cov; hom_a = asm_opt.hom_cov; + if(asm_opt.het_cov_set >= 0) het_a = asm_opt.het_cov_set; + if(het_a < 0) { + het_a = hom_a/asm_opt.polyploidy; + } else if(het_a > (hom_a/asm_opt.polyploidy)) { + het_a = hom_a/asm_opt.polyploidy; + } + if(tcut == ((uint64_t)-1)) { + // gen_rphase_dp0_single_path(hl->snp_stat.a, hl->snp_stat.n, hl->list, dp, idx, het_a, hom_a, asm_opt.polyploidy, 0.7, 6, res, qv->a, site_sc); + gen_rphase_dp0_single_path_multi(hl->snp_stat.a, hl->snp_stat.n, hl->list, dp, idx, het_a, hom_a, asm_opt.polyploidy, 0.7, 6, res, qv->a, site_sc); + } else { + gen_rphase_dp0_single_path_hybrid(hl->snp_stat.a, hl->snp_stat.n, hl->list, dp, idx, het_a, hom_a, asm_opt.polyploidy, 0.7, 0.4, 6, res, qv->a, ol, rid, tcut, site_sc); + } + + + for (k = 1, l = 0, i = m_snp_stat = m_list = 0; k <= hl->snp_stat.n; ++k) {///filter snps + if(k == hl->snp_stat.n || hl->snp_stat.a[k].site != hl->snp_stat.a[l].site) { + for (; i < hl->length && hl->list[i].site != hl->snp_stat.a[l].site; i++); + assert(i < hl->length && hl->list[i].site == hl->snp_stat.a[l].site); + for (o = l, m1 = 0; o < k; o++) { + s = &(hl->snp_stat.a[o]); + if(s->score == -1) continue; + m1++; + } + + if(m1) { + for (i0 = i, c0 = rev_n = 0; i0 < hl->length && hl->list[i0].site == hl->snp_stat.a[l].site; i0++) { + hl->list[i0].site = ((uint32_t)-1); + if(hh_tp(hl->list[i0]) == 0) { + c0 += 1/**hl->list[i0].cov**/; + if((ol->list[hl->list[i0].overlapID].y_pos_strand == 0)) rev_n += 1/**hl->list[i0].cov**/; + } + } + assert(i0 > i); + + for (o = l, m_snp_stat0 = m_snp_stat; o < k; o++) { + s = &(hl->snp_stat.a[o]); + if(s->score == -1) continue; + + hl->snp_stat.a[m_snp_stat] = *s; + for (ii = i, c1 = 0; ii < i0; ii++) { + if(((hl->list[ii].overlapSite == o) && (hl->list[ii].site == ((uint32_t)-1))) || (hh_tp(hl->list[ii]) == 0)) { + hl->list[ii].overlapSite = m_snp_stat; + hl->list[ii].site = hl->snp_stat.a[o].site; + if(hh_tp(hl->list[ii]) == 1) c1 += 1/**hl->list[ii].cov**/;///not correct if we don't do read correction + } + } + + // if(hl->snp_stat.a[m_snp_stat].site == 4) { + // fprintf(stderr, "[M::%s] occ_0->%lu, occ_1->%lu, site->%u\n", __func__, c0 + 1, c1, hl->snp_stat.a[m_snp_stat].site); + // } + + hl->snp_stat.a[m_snp_stat].occ_0 = c0 + 1; + hl->snp_stat.a[m_snp_stat].occ_1 = c1; + hl->snp_stat.a[m_snp_stat].overlap_num = rev_n + 1; + hl->snp_stat.a[m_snp_stat].non_homopolymer_num = m_list; + ///keep the score + if(!site_sc) hl->snp_stat.a[m_snp_stat++].score = -1; + else m_snp_stat++; + } + + for (ii = i, m1 = m_list; ii < i0; ii++) { + if((hl->list[ii].site == ((uint32_t)-1))) continue; + hl->list[m_list++] = hl->list[ii]; + } + for (ii = m_snp_stat0; ii < m_snp_stat; ii++) { + hl->snp_stat.a[ii].homopolymer_num = m_list; + } + + i = i0; + } + + l = k; + } + } + hl->snp_stat.n = m_snp_stat; hl->length = m_list; + // fprintf(stderr, "[M::%s] m_snp_stat->%lu\n", __func__, m_snp_stat); + +} + +void generate_haplotypes_naive_UL(haplotype_evdience_alloc* hap, overlap_region_alloc* overlap_list, double up, void *km) +{ + if(hap->length == 0) return; + uint64_t k, l, i, o, *a, ii, m_snp_stat, m_list, m_off; + int64_t z; + SnpStats *s = NULL, *t = NULL; + + for (k = 1, l = 0, i = m_snp_stat = m_list = 0; k <= hap->snp_stat.n; ++k) {///filter snps + if(k == hap->snp_stat.n || hap->snp_stat.a[k].site != hap->snp_stat.a[l].site) { + if((l > 0) && (hap->snp_stat.a[l].site == (hap->snp_stat.a[l-1].site + 1))) { + l = k; continue; + } + if((k < hap->snp_stat.n) && ((hap->snp_stat.a[l].site+1) == hap->snp_stat.a[k].site)) { + l = k; continue; + } + + for (; i < hap->length && hap->list[i].site != hap->snp_stat.a[l].site; i++); + assert(i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site); + m_off = l - m_snp_stat; + for (; i < hap->length && hap->list[i].site == hap->snp_stat.a[l].site; i++) { + assert(hap->list[i].overlapSite>=l && hap->list[i].overlapSite < k); + // assert(hap->snp_stat.a[hap->list[i].overlapSite].site==hap->list[i].site); + hap->list[m_list] = hap->list[i]; hap->list[m_list++].overlapSite -= m_off; + } + + for (; l < k; l++) hap->snp_stat.a[m_snp_stat++] = hap->snp_stat.a[l]; + } + } + hap->snp_stat.n = m_snp_stat; hap->length = m_list; + if(hap->snp_stat.n == 0 || hap->length == 0) return; + + hap->snp_srt.n = 0; + radix_sort_haplotype_evdience_id_srt(hap->list, hap->list + hap->length); + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + for (i = l, o = 0; i < k; i++) { + if(hap->list[i].type!=1) continue;///mismatch + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + assert(s->site == hap->list[i].site); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) o++;///allels must be real + } + if(o > 0) { + o = ((uint32_t)-1) - o; + o <<= 32; o += l; + if(!km) kv_push(uint64_t, hap->snp_srt, o); + else kv_push_km(km, uint64_t, hap->snp_srt, o); + } + l = k; + } + } + + if (hap->snp_srt.n > 0) { + radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n);///sort by how many snps in one overlap + for (k = 0; k < hap->snp_srt.n; k++) { + o = 0; l = (uint32_t)hap->snp_srt.a[k]; + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hap->list[i].type!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) o++; + } + if(o == 0) continue; + + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match == 1) overlap_list->list[ii].is_match = 2; + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hap->list[i].type==1){ + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + s->score = 1; + } ///else if((hap->list[i].type==0) && (o>=(overlap_list->list[ii].align_length*up))) { + else if(hap->list[i].type==0) { + ///not real allels + z = hap->list[i].overlapSite; s = &(hap->snp_stat.a[z]); + for (z = hap->list[i].overlapSite; z >= 0; z--) { + t = &(hap->snp_stat.a[z]); + if(s->site!=t->site) break; + t->occ_0 -= hap->list[i].cov; + assert(t->occ_0 >= 1); + } + } + } + } + + for (k = 0; k < hap->snp_srt.n; k++) {///sorted by how many allels in each overlap; more -> less + o = 0; l = (uint32_t)hap->snp_srt.a[k]; + for (i = l; i < hap->length && hap->list[i].overlapID == hap->list[l].overlapID; i++) { + if(hap->list[i].type!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(s->score == 1) o++; + } + ii = hap->list[l].overlapID; + ///for HiFi, do not flip trans to cis + // if(overlap_list->list[ii].is_match == 2 && o == 0) { + // overlap_list->list[ii].is_match = 1; + // } + if(overlap_list->list[ii].is_match == 1 && o > 0) { + overlap_list->list[ii].is_match = 2; + } + } + + + for (k = 1, l = 0; k <= hap->length; ++k) { ///reset snp_stat + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match==1) { + for (i = l; i < k; i++) { + if(hap->list[i].type==1) { + hap->snp_stat.a[hap->list[i].overlapSite].score = -1; + } + } + } + l = k; + } + } + } + + + + hap->snp_srt.n = 0; + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + if(overlap_list->list[hap->list[l].overlapID].is_match == 2) { + l = k; + continue; + } + for (i = l, o = 0; i < k; i++) { + if(hap->list[i].type!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->occ_0 < 2 || s->occ_1 < 2) continue; + if(s->occ_0 >= asm_opt.s_hap_cov && s->occ_1 >= asm_opt.infor_cov) continue; + if(s->score == 1) continue; + o++; + if(!km) kv_push(uint64_t, hap->snp_srt, hap->list[i].overlapSite); + else kv_push_km(km, uint64_t, hap->snp_srt, hap->list[i].overlapSite); + } + hap->snp_srt.n -= o; + ///there are at least two variants at one read + if(o>=(overlap_list->list[hap->list[l].overlapID].align_length*up)) { + radix_sort_bc64(hap->snp_srt.a + hap->snp_srt.n, hap->snp_srt.a + hap->snp_srt.n + o); + a = hap->snp_srt.a + hap->snp_srt.n; + for (i = z = 0; i < o; i++) { + if(i > 0) s = &(hap->snp_stat.a[a[i-1]]); + if(i + 1 < o) t = &(hap->snp_stat.a[a[i+1]]); + if(s && s->site + 32 > hap->snp_stat.a[a[i]].site) continue; + if(t && hap->snp_stat.a[a[i]].site + 32 > t->site) continue; + a[z] = a[i]; + z++; + } + if(z >= 2) hap->snp_srt.n += z; + } + l = k; + } + } + if (hap->snp_srt.n > 0) { + radix_sort_bc64(hap->snp_srt.a, hap->snp_srt.a + hap->snp_srt.n); + for (k = 1, l = 0; k <= hap->snp_srt.n; ++k) { + if(k == hap->snp_srt.n || hap->snp_srt.a[k] != hap->snp_srt.a[l]) { + if(k - l >= 2) hap->snp_stat.a[hap->snp_srt.a[l]].score = 1; + } + l = k; + } + } + + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + ii = hap->list[l].overlapID; + if(overlap_list->list[ii].is_match==2) { + overlap_list->list[ii].strong = 1; + overlap_list->mapped_overlaps_length -= + overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; + } else if(overlap_list->list[ii].is_match==1) { + for (i = l; i < k; i++) { + if(hap->list[i].type==1 || hap->list[i].type==0) { + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->score == 1 && (!(s->occ_0 < 2 || s->occ_1 < 2))) { + overlap_list->list[ii].strong = 1; + if(hap->list[i].type==1) { + overlap_list->list[ii].is_match = 2; + overlap_list->mapped_overlaps_length -= + overlap_list->list[ii].x_pos_e + 1 - overlap_list->list[ii].x_pos_s; + break; + } + } + } + + } + } + l = k; + } + } +} + +/** +void partition_overlaps(overlap_region_alloc* overlap_list, All_reads* R_INF, + UC_Read* g_read, Correct_dumy* dumy, haplotype_evdience_alloc* hap, + int force_repeat) +{ + ResizeInitHaplotypeEvdience(hap); + + long long i; + long long window_start, window_end; + + long long num_availiable_win = 0; + + Window_Pool w_inf; + init_Window_Pool(&w_inf, g_read->length, WINDOW, (int)(1.0/asm_opt.max_ov_diff_ec)); + + int flag = 0; + while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) + { + dumy->length = 0; + dumy->lengthNT = 0; + + ///return overlaps that is overlaped with [window_start, window_end] + flag = get_available_interval(window_start, window_end, overlap_list, dumy); + switch (flag) + { + case 1: ///found matched overlaps + break; + case 0: ///do not find any matched overlaps + break; + case -2: ///do not find any matched overlaps, and the next window also cannot match + break; + } + + num_availiable_win = num_availiable_win + dumy->length; + + cluster(g_read->seq, window_start, window_end, overlap_list, dumy, R_INF, hap); + } + + ///very time-consuming + qsort(hap->list, hap->length, sizeof(haplotype_evdience), cmp_haplotype_evdience); + + + + + ///debug_hap_information(overlap_list, R_INF, g_read, hap, dumy); + + SetSnpMatrix(hap, &(hap->nn_snp), &(overlap_list->length), 1, NULL); + + + uint64_t pre_site = (uint64_t)-1; + uint64_t num_of_snps = 0; + long long pre_i = -1; + long long sub_length; + haplotype_evdience* sub_list; + + ////split reads + for (i = 0; i < hap->length; i++) + { + if(pre_site != hap->list[i].site) + { + if(i != 0) + { + sub_list = hap->list + pre_i; + sub_length = i - pre_i; + split_sub_list(hap, sub_list, sub_length, overlap_list, R_INF, g_read); + } + num_of_snps++; + pre_site = hap->list[i].site; + pre_i = i; + } + } + + if(pre_i != -1) + { + sub_list = hap->list + pre_i; + sub_length = i - pre_i; + split_sub_list(hap, sub_list, sub_length, overlap_list, R_INF, g_read); + } + + ///debug_snp_matrix(hap); + generate_haplotypes_DP(hap, overlap_list, R_INF, g_read->length, force_repeat); + ///generate_haplotypes_naive(hap, overlap_list, R_INF, g_read->length, force_repeat); + + lable_large_indels(overlap_list, g_read->length, dumy, asm_opt.max_ov_diff_ec); + + + ///debug_snp_matrix(hap); +} +**/ + +void partition_overlaps_advance_back(overlap_region_alloc* overlap_list, All_reads* R_INF, + UC_Read* g_read, UC_Read* overlap_read, Correct_dumy* dumy, + haplotype_evdience_alloc* hap, int force_repeat) +{ + ResizeInitHaplotypeEvdience(hap); + + long long i; + long long window_start, window_end; + + long long num_availiable_win = 0; + + Window_Pool w_inf; + init_Window_Pool(&w_inf, g_read->length, WINDOW, (int)(1.0/asm_opt.max_ov_diff_ec)); + + int flag = 0; + while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) + { + dumy->length = 0; + dumy->lengthNT = 0; + ///return overlaps that is overlaped with [window_start, window_end] + flag = get_available_interval(window_start, window_end, overlap_list, dumy); + switch (flag) + { + case 1: ///found matched overlaps + break; + case 0: ///do not find any matched overlaps + break; + case -2: ///do not find any matched overlaps, and the next window also cannot match + break; + } + + num_availiable_win = num_availiable_win + dumy->length; + + ///need to deal with + cluster_advance(g_read->seq, window_start, window_end, overlap_list, + dumy, R_INF, hap, overlap_read, 1); + } + + + + ///very time-consuming + ///Fix-attention ---> able to be sorted locally + // qsort(hap->list, hap->length, sizeof(haplotype_evdience), cmp_haplotype_evdience); + SetSnpMatrix(hap, &(hap->nn_snp), &(overlap_list->length), 1, NULL); + + uint64_t pre_site = (uint64_t)-1; + uint64_t num_of_snps = 0; + long long pre_i = -1; + long long sub_length; + haplotype_evdience* sub_list; + + ////split reads + for (i = 0; i < hap->length; i++) + { + if(pre_site != hap->list[i].site) + { + if(i != 0) + { + sub_list = hap->list + pre_i; + sub_length = i - pre_i; + split_sub_list(hap, sub_list, sub_length, overlap_list, R_INF, g_read); + } + num_of_snps++; + pre_site = hap->list[i].site; + pre_i = i; + } + } + + if(pre_i != -1) + { + sub_list = hap->list + pre_i; + sub_length = i - pre_i; + split_sub_list(hap, sub_list, sub_length, overlap_list, R_INF, g_read); + } + + generate_haplotypes_DP(hap, overlap_list, R_INF, g_read->length, force_repeat); + ///generate_haplotypes_naive(hap, overlap_list, R_INF, g_read->length, force_repeat); + + lable_large_indels(overlap_list, g_read->length, dumy, asm_opt.max_ov_diff_ec); +} + +inline void insert_snp_vv(haplotype_evdience_alloc* h, haplotype_evdience* a, uint64_t a_n, char misBase, UC_Read* g_read, void *km) +{ + if(a_n == 0) return; + SnpStats *p = NULL; uint64_t /**nn = 0,**/ i; + if(!km) kv_pushp(SnpStats, h->snp_stat, &p); + else kv_pushp_km(km, SnpStats, h->snp_stat, &p); + p->id = h->snp_stat.n-1; + p->occ_0 = 1; + p->occ_1 = 0; + p->occ_2 = 0; + p->overlap_num = 0; + p->site = a[0].site; + p->is_homopolymer = if_is_homopolymer_strict(p->site, g_read->seq, g_read->length); + for (i = 0; i < a_n; i++) { + if(a[i].type == 0) { + a[i].overlapSite = p->id; + h->snp_stat.a[p->id].occ_0 += a[i].cov; + } + else if(a[i].type == 1 && a[i].misBase == misBase) { + a[i].overlapSite = p->id; + h->snp_stat.a[p->id].occ_1 += a[i].cov; + } + else { + h->snp_stat.a[p->id].occ_2 += a[i].cov; + } + h->snp_stat.a[p->id].overlap_num += a[i].cov; + } + h->snp_stat.a[p->id].score = -1; +} + + +int insert_snp_ee(haplotype_evdience_alloc* h, haplotype_evdience* a, uint64_t a_n, haplotype_evdience* u_a, UC_Read* g_read, void *km) +{ + uint64_t i, m, occ_0, occ_1[6], occ_2, diff; + occ_0 = occ_2 = diff = 0; memset(occ_1, 0, sizeof(uint64_t)*6); + + for (i = 0; i < a_n; i++) { + if(a[i].type == 0){ + occ_0 += a[i].cov; + }else if(a[i].type == 1){ + occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]] += a[i].cov; + diff += a[i].cov; + } + // else if(a[i].type == 2){ + // occ_2++; + // diff++; + // } + occ_2 += a[i].cov; + } + + /** + 1. if occ_0 = 0, that means all overlaps are different with this read at this site + 2. it is not possible that occ_1 = 0, + 3. if occ_1 = 1, there are only one difference. It must be a sequencing error. + (for repeat, it maybe a snp at repeat. but ...) + **/ + SnpStats *p = NULL; + uint32_t is_homopolymer = (uint32_t)-1; + if(occ_0 == 0 || diff <= 1) return 0; + for (i = m = 0; i < 4; i++) { + if(occ_1[i] >= 2){ + if(!km) kv_pushp(SnpStats, h->snp_stat, &p); + else kv_pushp_km(km, SnpStats, h->snp_stat, &p); + p->id = h->snp_stat.n-1; + p->occ_0 = 1 + occ_0; + p->occ_1 = occ_1[i]; + p->occ_2 = occ_2 - p->occ_0 - p->occ_1; + p->overlap_num = 0; + p->site = a[0].site; + p->score = -1; + p->overlap_num = occ_2; + if(is_homopolymer == (uint32_t)-1) { + is_homopolymer = if_is_homopolymer_strict(p->site, g_read->seq, g_read->length); + } + p->is_homopolymer = is_homopolymer; + occ_1[i] = p->id; + m++; + } else { + occ_1[i] = (uint64_t)-1; + } + } + occ_1[4] = occ_1[5] = (uint64_t)-1; + if(m == 0) return 0; + + for (i = m = 0; i < a_n; i++) { + // fprintf(stderr, "[M::%s] a[%lu].misBase->%c\n", __func__, i, a[i].misBase); + if(a[i].type == 0) { + a[i].overlapSite = h->snp_stat.n-1; + } else if(occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]]!=(uint64_t)-1){ + a[i].cov = a[i].overlapSite;///note: only renew cov here!!! + a[i].overlapSite = occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]]; + } else { + continue; + } + u_a[m++] = a[i]; + } + + /** + // if(c_snp && ovlp) { + // ; + // } + for (i = m = 0; i < 4; i++) { + if(occ_1[i] >= 2) { + insert_snp_vv(h, a, a_n, s_H[i], g_read, km); + m++; + } + } + if(m == 0) return 0; + + for (i = m = 0; i < a_n; i++) { + if(a[i].type == 0){ + u_a[m++] = a[i]; + }else if(a[i].type == 1){ + if(occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]] >= 2) u_a[m++] = a[i]; + } + } + **/ + + return m; +} + + +uint8_t hpc_mask_ff(char *sa, int64_t sn, int64_t p, int64_t hpc_flk, int64_t hpc_rr, uint8_t *f, int64_t fn, int64_t fsift, int64_t hpc_cutoff, int64_t *hpc_s, int64_t *hpc_e) +{ + int64_t s = ((p>=hpc_flk)?(p-hpc_flk):0), e = (((p+hpc_flk)<=sn)?(p+hpc_flk):(sn)), k, r, rc, zs, ze; + + for (r = 1; r <= hpc_rr; r++) { + rc = r * hpc_cutoff/**HPC_CC**/; + + ///inlcuding p + for (k = p + r; (k < e) && ((k-r) >= s) && (sa[k] == sa[k-r]); k++){;} ze = k; if(ze > e) {ze = e;} + for (k = p - 1; (k >= s) && ((k+r) < e) && (sa[k] == sa[k+r]); k--){;} zs = k + 1; if(zs < s) {zs = s;} + if(((ze - zs) > r) && ((ze - zs) >= rc)) { + // fprintf(stderr, "-0-[M::%s] p::%ld, hh::[%ld,%ld), f::%u, %.*s\n", __func__, p, zs, ze, f?1:0, (int32_t)(ze - zs), sa + zs); + if(f) { + for (k = MAX(p, zs); (k < ze) && (k - fsift < fn); k++) {f[k - fsift] = 0;} f[p - fsift] = 0; + } + if(hpc_s) (*hpc_s) = zs; + if(hpc_e) (*hpc_e) = ze; + return 1; + } + + ///do not inlcude p + for (k = p + r + 1; (k < e) && ((k-r) >= s) && (sa[k] == sa[k-r]); k++); + zs = p + 1; if(zs < s) zs = s; ze = k; if(ze > e) ze = e; + if(((ze - zs) > r) && ((ze - zs) >= rc)) { + // fprintf(stderr, "-1-[M::%s] p::%ld, hh::[%ld,%ld), f::%u, %.*s\n", __func__, p, zs, ze, f?1:0, (int32_t)(ze - zs), sa + zs); + if(f) { + for (k = MAX(p, zs); (k < ze) && (k - fsift < fn); k++) {f[k - fsift] = 0;} f[p - fsift] = 0; + } + if(hpc_s) (*hpc_s) = zs; + if(hpc_e) (*hpc_e) = ze; + return 1; + } + + ///inlcuding p + for (k = p - r; (k >= s) && ((k+r) < e) && (sa[k] == sa[k+r]); k--){;} zs = k + 1; if(zs < s) {zs = s;} + for (k = p + 1; (k < e) && ((k-r) >= s) && (sa[k] == sa[k-r]); k++){;} ze = k; if(ze > e) {ze = e;} + if(((ze - zs) > r) && ((ze - zs) >= rc)) { + // fprintf(stderr, "-2-[M::%s] p::%ld, hh::[%ld,%ld), f::%u, %.*s\n", __func__, p, zs, ze, f?1:0, (int32_t)(ze - zs), sa + zs); + if(f) { + for (k = MAX(p, zs); (k < ze) && (k - fsift < fn); k++) {f[k - fsift] = 0;} f[p - fsift] = 0; + } + if(hpc_s) (*hpc_s) = zs; + if(hpc_e) (*hpc_e) = ze; + return 1; + } + + ///do not inlcude p + for (k = p - r - 1; (k >= s) && ((k+r) < e) && (sa[k] == sa[k+r]); k--); + zs = k + 1; if(zs < s) zs = s; ze = p; if(ze > e) ze = e; + if(((ze - zs) > r) && ((ze - zs) >= rc)) { + // fprintf(stderr, "-3-[M::%s] p::%ld, hh::[%ld,%ld), f::%u, %.*s\n", __func__, p, zs, ze, f?1:0, (int32_t)(ze - zs), sa + zs); + if(f) { + for (k = MAX(p, zs); (k < ze) && (k - fsift < fn); k++) {f[k - fsift] = 0;} f[p - fsift] = 0; + } + if(hpc_s) (*hpc_s) = zs; + if(hpc_e) (*hpc_e) = ze; + return 1; + } + } + // fprintf(stderr, "-6-[M::%s] p::%ld, hh::[,), %.*s\n", __func__, p, (int32_t)(e - s), sa + s); + return 0; +} + +uint8_t hpc_mask_ff_region(char *sa, int64_t sn, int64_t s0, int64_t e0, int64_t hpc_flk, int64_t hpc_rr, int64_t hpc_cutoff, double hpc_rate) +{ + assert(e0>=s0); + int64_t s = ((s0>=hpc_flk)?(s0-hpc_flk):0), e = (((e0+hpc_flk)<=sn)?(e0+hpc_flk):(sn)), k, r, rc, zs, ze, os, oe, ovlp; + + for (r = 1; r <= hpc_rr; r++) { + rc = r * (MAX(hpc_cutoff, hpc_rr));///hpc_cutoff = 6; + + ///inlcuding p + for (k = ((e0>s0)?(e0-1):(e0))+r; (k < e) && ((k-r) >= s) && (sa[k] == sa[k-r]); k++){;} ze = k; if(ze > e) {ze = e;} + for (k = ((e0>s0)?(e0-1):(e0))-1; (k >= s) && ((k+r) < e) && (sa[k] == sa[k+r]); k--){;} zs = k + 1; if(zs < s) {zs = s;} + if(((ze - zs) > r) && ((ze - zs) >= rc)) { + os = MAX(zs, s0); oe = MIN(ze, e0); + ovlp = ((oe>os)? (oe-os):0); + if(e0 > s0) { + if(ovlp > 0 && (ovlp >= ((e0 - s0)*hpc_rate))) return 1;///hpc_rate = 0.51 + } else { + if(zs <= s0 && ze >= e0) return 1; + } + } + + ///do not inlcude p + if(e0 <= s0) { + for (k = e0 + r + 1; (k < e) && ((k-r) >= s) && (sa[k] == sa[k-r]); k++); + zs = e0 + 1; if(zs < s) zs = s; ze = k; if(ze > e) ze = e; + if(((ze - zs) > r) && ((ze - zs) >= rc)) { + // fprintf(stderr, "-1-[M::%s] p::%ld, hh::[%ld,%ld), f::%u, %.*s\n", __func__, p, zs, ze, f?1:0, (int32_t)(ze - zs), sa + zs); + return 1; + } + } + + ///inlcuding p + for (k = s0 - r; (k >= s) && ((k+r) < e) && (sa[k] == sa[k+r]); k--){;} zs = k + 1; if(zs < s) {zs = s;} + for (k = s0 + 1; (k < e) && ((k-r) >= s) && (sa[k] == sa[k-r]); k++){;} ze = k; if(ze > e) {ze = e;} + if(((ze - zs) > r) && ((ze - zs) >= rc)) { + os = MAX(zs, s0); oe = MIN(ze, e0); + ovlp = ((oe>os)? (oe-os):0); + if(e0 > s0) { + if(ovlp > 0 && (ovlp >= ((e0 - s0)*hpc_rate))) return 1; + } else { + if(zs <= s0 && ze >= e0) return 1; + } + } + + ///do not inlcude p + if(e0 <= s0) { + for (k = s0 - r - 1; (k >= s) && ((k+r) < e) && (sa[k] == sa[k+r]); k--); + zs = k + 1; if(zs < s) zs = s; ze = s0; if(ze > e) ze = e; + if(((ze - zs) > r) && ((ze - zs) >= rc)) { + return 1; + } + } + } + // fprintf(stderr, "-6-[M::%s] p::%ld, hh::[,), %.*s\n", __func__, p, (int32_t)(e - s), sa + s); + return 0; +} + +int push_info(haplotype_evdience_alloc* h, haplotype_evdience* a, uint64_t a_n, haplotype_evdience* u_a, overlap_region *oa, asg8_v *v8, uint64_t tot_cov, uint64_t scw, uint64_t tcut) +{ + uint64_t i, k, m, occ_0, occ_1[6], occ_2, diff, rev_n; uint8_t ihpc = 0; + occ_0 = occ_2 = diff = rev_n = 0; memset(occ_1, 0, sizeof(uint64_t)*6); + + + radix_sort_haplotype_evdience_id_srt(a, a + a_n); + for (k = 1, m = i = 0; k <= a_n; k++) { + if((k == a_n) || (a[k].overlapID != a[m].overlapID)) { + a[i] = a[m]; + // /**if(a[0].site == 3504)**/ { + // fprintf(stderr, "-%u-[M::%s-beg]\trid::%u\t%.*s\thh_tp::%u\n", a[0].site, __func__, + // oa[a[i].overlapID].y_id, (int)Get_NAME_LENGTH(R_INF, oa[a[i].overlapID].y_id), Get_NAME(R_INF, oa[a[i].overlapID].y_id), hh_tp(a[i])); + // } + if(hh_tp(a[i]) == 0){ + occ_0 += a[i].cov; + if((oa) && (oa[a[i].overlapID].y_pos_strand == 0)) { + rev_n += a[i].cov; + } + if((!ihpc) && (hh_hp(a[i]))) ihpc = 1; + }else if(hh_tp(a[i]) == 1){ + occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]] += a[i].cov; + diff += a[i].cov; + } + occ_2 += a[i].cov; + + i++; m = k; + } + } + a_n = i; + + // for (i = 0; i < a_n; i++) { + // if(hh_tp(a[i]) == 0){ + // occ_0 += a[i].cov; + // if((oa) && (oa[a[i].overlapID].y_pos_strand == 0)) { + // rev_n += a[i].cov; + // } + // if((!ihpc) && (hh_hp(a[i]))) ihpc = 1; + // }else if(hh_tp(a[i]) == 1){ + // occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]] += a[i].cov; + // diff += a[i].cov; + // } + // occ_2 += a[i].cov; + // } + + + /** + 1. if occ_0 = 0, that means all overlaps are different with this read at this site + 2. it is not possible that occ_1 = 0, + 3. if occ_1 = 1, there are only one difference. It must be a sequencing error. + (for repeat, it maybe a snp at repeat. but ...) + **/ + SnpStats *p = NULL; + if(occ_0 == 0 || diff <= 1) return 0; + if((oa) && (rev_n == occ_0)) return 0; + if(!oa) { + rev_n = occ_2; + } else { + rev_n++; + } + + for (i = m = 0; i < 4; i++) { + if(occ_1[i] >= 2){ + kv_pushp(SnpStats, h->snp_stat, &p); + p->id = h->snp_stat.n-1; + p->occ_0 = 1 + occ_0; + p->occ_1 = occ_1[i]; + if((tot_cov > 0) && (tot_cov >= (p->occ_0 + p->occ_1))) { + p->occ_2 = tot_cov - p->occ_0 - p->occ_1; + } else { + p->occ_2 = occ_2 + 1 - p->occ_0 - p->occ_1; + } + // fprintf(stderr, "[M::%s]\ttot_cov::%lu\tocc_2::%lu\n", __func__, tot_cov, occ_2); + p->site = a[0].site; + p->score = -1; + p->overlap_num = rev_n; + p->is_homopolymer = ihpc; + occ_1[i] = p->id; + m++; + // fprintf(stderr, "[M::%s]\tsite::%u\tn0::%u\tn1::%u\n", __func__, p->site, p->occ_0, p->occ_1); + } else { + occ_1[i] = (uint64_t)-1; + } + } + occ_1[4] = occ_1[5] = (uint64_t)-1; + if(m == 0) return 0; + + if(!v8) { + for (i = m = 0; i < a_n; i++) { + // fprintf(stderr, "[M::%s] a[%lu].misBase->%c\n", __func__, i, a[i].misBase); + if(hh_tp(a[i]) == 0) { + a[i].overlapSite = h->snp_stat.n-1; + } else if(occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]]!=(uint64_t)-1){ + a[i].cov = a[i].overlapSite;///note: only renew cov here!!! + a[i].overlapSite = occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]]; + } else { + continue; + } + u_a[m++] = a[i]; + } + } else { + uint64_t tpos, tqual, wqual; + for (i = m = 0; i < a_n; i++) { + tpos = a[i].overlapSite; + if(hh_tp(a[i]) == 0) { + a[i].overlapSite = h->snp_stat.n-1; + } else if(occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]]!=(uint64_t)-1){ + a[i].cov = a[i].overlapSite;///note: only renew cov here!!! + a[i].overlapSite = occ_1[seq_nt6_table[(uint8_t)(a[i].misBase)]]; + } else { + continue; + } + tqual = wqual = 3; + if(oa[a[i].overlapID].y_id < tcut) get_wqual(oa[a[i].overlapID].y_id, tpos, oa[a[i].overlapID].y_pos_strand, v8, NULL, scw, &tqual, &wqual); + a[i].type |= (tqual<<2); a[i].type |= (wqual<<(sc_bn+2)); + // assert(hh_bq(a[i]) == tqual); assert(hh_wq(a[i]) == wqual); + // fprintf(stderr, "[M::%s] site::%u, type::%u, occ0::%lu, occ2::%lu, tqual::%lu, wqual::%lu\n", __func__, a[i].site, hh_tp(a[i]), occ_0, occ_2, tqual, wqual); + u_a[m++] = a[i]; + } + } + + + return m; +} + + +void partition_overlaps_advance(overlap_region_alloc* overlap_list, All_reads* R_INF, + UC_Read* g_read, UC_Read* overlap_read, Correct_dumy* dumy, + haplotype_evdience_alloc* hap, int force_repeat) +{ + ResizeInitHaplotypeEvdience(hap); + + uint64_t k, l, m; + long long window_start, window_end; + long long num_availiable_win = 0; + + Window_Pool w_inf; + init_Window_Pool(&w_inf, g_read->length, WINDOW, (int)(1.0/asm_opt.max_ov_diff_ec)); + + int flag = 0; + while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) + { + dumy->length = 0; + dumy->lengthNT = 0; + ///return overlaps that is overlaped with [window_start, window_end] + flag = get_available_interval(window_start, window_end, overlap_list, dumy); + switch (flag) + { + case 1: ///found matched overlaps + break; + case 0: ///do not find any matched overlaps + break; + case -2: ///do not find any matched overlaps, and the next window also cannot match + break; + } + + num_availiable_win = num_availiable_win + dumy->length; + + ///need to deal with + cluster_advance(g_read->seq, window_start, window_end, overlap_list, dumy, R_INF, hap, overlap_read, 1); + } + + ///very time-consuming + ///Fix-attention ---> able to be sorted locally + // qsort(hap->list, hap->length, sizeof(haplotype_evdience), cmp_haplotype_evdience); + SetSnpMatrix(hap, &(hap->nn_snp), &(overlap_list->length), 0, NULL); + for (k = 1, l = m = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].site != hap->list[l].site) { + m += insert_snp_ee(hap, hap->list+l, k-l, hap->list+m, g_read, NULL); + l = k; + } + } + hap->length = m; + + // generate_haplotypes_naive_advance(hap, overlap_list, NULL); + generate_haplotypes_naive_HiFi(hap, overlap_list, 0.04, g_read, 1, 0, ((uint64_t)-1)); + // generate_haplotypes_DP(hap, overlap_list, R_INF, g_read->length, force_repeat); + // generate_haplotypes_naive(hap, overlap_list, R_INF, g_read->length, force_repeat); + + lable_large_indels(overlap_list, g_read->length, dumy, asm_opt.max_ov_diff_ec); +} + + +void debug_phasing_snp_site_status(haplotype_evdience_alloc* h, haplotype_evdience* a, uint64_t a_n, overlap_region_alloc* olist) +{ + uint64_t i; + for (i = 0; i < a_n; i++) { + if(a[i].site == 76046) { + fprintf(stderr, "[M::utg%.6dl::]x_site->%u, y_site->%u, type->%u, cov->%u, misBase->%c\n", + (int)olist->list[a[i].overlapID].y_id+1, a[i].site, + a[i].overlapSite, a[i].type, a[i].cov, a[i].misBase); + } + } +} + + +void partition_ul_overlaps_advance(overlap_region_alloc* overlap_list, const ul_idx_t *uref, + UC_Read* g_read, UC_Read* overlap_read, Correct_dumy* dumy, haplotype_evdience_alloc* hap, + int force_repeat, double max_ov_diff_ec, long long blockLen, void *km) +{ + ResizeInitHaplotypeEvdience(hap); + + uint64_t k, l, m; + long long window_start, window_end; + long long num_availiable_win = 0; + + Window_Pool w_inf; + init_Window_Pool(&w_inf, g_read->length, blockLen, (int)(1.0/max_ov_diff_ec)); + + int flag = 0; + while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) + { + dumy->length = 0; + dumy->lengthNT = 0; + ///return overlaps that is overlaped with [window_start, window_end] + flag = get_available_interval(window_start, window_end, overlap_list, dumy); + switch (flag) + { + case 1: ///found matched overlaps + break; + case 0: ///do not find any matched overlaps + break; + case -2: ///do not find any matched overlaps, and the next window also cannot match + break; + } + + num_availiable_win = num_availiable_win + dumy->length; + + ///need to deal with + cluster_ul_advance(g_read->seq, window_start, window_end, overlap_list, dumy, uref, hap, overlap_read, 1, w_inf.window_length, km); + } + + + + ///very time-consuming + ///Fix-attention ---> able to be sorted locally + // qsort(hap->list, hap->length, sizeof(haplotype_evdience), cmp_haplotype_evdience); + SetSnpMatrix(hap, &(hap->nn_snp), &(overlap_list->length), 0, km); + for (k = 1, l = m = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].site != hap->list[l].site) { + // debug_phasing_snp_site_status(hap, hap->list+l, k-l, overlap_list); + m += insert_snp_ee(hap, hap->list+l, k-l, hap->list+m, g_read, km); + l = k; + } + } + hap->length = m; + + generate_haplotypes_naive_advance(hap, overlap_list, km); + + // generate_haplotypes_DP(hap, overlap_list, R_INF, g_read->length, force_repeat); + // generate_haplotypes_naive(hap, overlap_list, R_INF, g_read->length, force_repeat); + + lable_large_indels(overlap_list, g_read->length, dumy, max_ov_diff_ec); +} + + +void collect_no_cov_regions(overlap_region_alloc* overlap_list, All_reads* R_INF, +kvec_t_u32_warp* b, kvec_t_u64_warp* r, int min_dp, int min_len) +{ + b->a.n = r->a.n = 0; + ///if(overlap_list->length == 0) return; + long long i = 0, xLen = Get_READ_LENGTH((*R_INF), overlap_list->list[0].x_id); + uint32_t qs, qe; + uint64_t tmp; + int dp, old_dp, s_start = 0, s_end = 0; + ///at least 1 + if(min_len < 1) min_len = 1; + + + for (i = 0; i < (long long)overlap_list->length; i++) + { + if (overlap_list->list[i].is_match != 1 && overlap_list->list[i].is_match != 2) continue; + + qs = overlap_list->list[i].x_pos_s; + qe = overlap_list->list[i].x_pos_e + 1; + kv_push(uint32_t, b->a, qs<<1); + kv_push(uint32_t, b->a, qe<<1|1); + } + + + ///we can identify the qs and qe by the 0-th bit + radix_sort_b32(b->a.a, b->a.a + b->a.n); + + for (i = 0, dp = 0; i < (long long)b->a.n; ++i) + { + old_dp = dp; + //if a[j] is qe + if (b->a.a[i]&1) --dp; + else ++dp; + /** + min_dp is the coverage drop threshold + there are two cases: + 1. old_dp = dp + 1 (b.a[j] is qe); 2. old_dp = dp - 1 (b.a[j] is qs); + **/ + if (old_dp < min_dp && dp >= min_dp) ///old_dp < dp, b.a[j] is qs + { + ///case 2, a[j] is qs + s_end = b->a.a[i]>>1; + ///at least 1 + if(s_end-s_start >= min_len) + { + tmp = s_start; tmp = tmp << 32; tmp = tmp | (uint64_t)(s_end-1); + kv_push(uint64_t, r->a, tmp); + } + } + else if (old_dp >= min_dp && dp < min_dp) ///old_dp > min_dp, b.a[j] is qe + { + s_start = b->a.a[i]>>1; + } + } + + + if(s_start < xLen && xLen-s_start >= min_len) + { + s_end = xLen; + tmp = s_start; tmp = tmp << 32; tmp = tmp | (uint64_t)(s_end-1); + kv_push(uint64_t, r->a, tmp); + } +} + +int collect_hp_regions_back(overlap_region_alloc* olist, All_reads* R_INF, kvec_t_u32_warp* b, kvec_t_u64_warp* r, kvec_t_u8_warp* k_flag, float hp_rate, FILE* fp) +{ + int i, k, qs, qe, ava_k_mer = 0, hp_k_mer = 0, min_dp; + // min_dp = RESEED_DP; + // if(asm_opt.hom_cov > 0) min_dp = asm_opt.hom_cov * RESEED_PEAK_RATE; + // if(min_dp > RESEED_DP) min_dp = RESEED_DP; + min_dp = RESEED_DP; + if(asm_opt.hom_cov > 0) min_dp = asm_opt.hom_cov * RESEED_PEAK_RATE; + if(asm_opt.het_cov > 0) min_dp = asm_opt.het_cov * RESEED_PEAK_RATE; + collect_no_cov_regions(olist, R_INF, b, r, min_dp, RESEED_LEN); + + for (i = 0; i < (int)r->a.n; i++) + { + ///[qs, qe] + qs = r->a.a[i]>>32; + qe = (r->a.a[i]<<32)>>32; + + for (k = qs; k <= qe; k++) + { + if(k_flag->a.a[k] > 1) ava_k_mer++; + if(k_flag->a.a[k] > 2) hp_k_mer++; + } + + if(fp) fprintf(fp, "qs: %d, qe: %d, ava_k_mer: %d, hp_k_mer: %d\n", qs, qe, ava_k_mer, hp_k_mer); + } + + if(fp) fprintf(fp, "ava_k_mer: %d, hp_k_mer: %d, hp_rate: %f, min_dp: %d, a.n: %d\n", ava_k_mer, hp_k_mer, hp_rate, min_dp, (int)r->a.n); + + // if(fp) + // { + // for (k = 0; k < (int)k_flag->a.n; k++) + // { + // if(k_flag->a.a[k] > 0) fprintf(fp, "(%d) %u\n", k, k_flag->a.a[k]); + // } + // } + + if(hp_k_mer > ava_k_mer*hp_rate) return 1; ///must use '>' instead of '>=' + r->a.n = 0; + return 0; +} + + +int collect_hp_regions(overlap_region_alloc* olist, All_reads* R_INF, kvec_t_u8_warp* k_flag, +float hp_rate, int rlen, FILE* fp) +{ + int i, ava_k_mer = 0, hp_k_mer = 0, vLen, min_dp; + int32_t w, n[4]; + n[0] = n[1] = n[2] = n[3] = 0; + min_dp = RESEED_DP; + if(asm_opt.hom_cov > 0) min_dp = asm_opt.hom_cov * RESEED_PEAK_RATE; + if(min_dp > RESEED_DP) min_dp = RESEED_DP; + overlap_region* ov = NULL; + + for (i = 0; i < (long long)olist->length; i++) + { + ov = &(olist->list[i]); + if (ov->is_match != 1 && ov->is_match != 2) continue; + + w = ha_ov_type(ov, rlen); + ++n[w]; + } + + if(fp) fprintf(fp, "n[0]: %d, n[1]: %d, n[2]: %d, n[3]: %d\n", n[0], n[1], n[2], n[3]); + + // n[0] += n[2]; + // n[1] += n[2]; + + if(n[0] < min_dp) + { + ava_k_mer = hp_k_mer = 0; + vLen = MIN(k_flag->a.n, RESEED_LEN); + for (i = 0; i < vLen; i++) + { + if(k_flag->a.a[i] > 1) ava_k_mer++; + if(k_flag->a.a[i] > 2) hp_k_mer++; + } + if(hp_k_mer > ava_k_mer*hp_rate) return 1; + } + + + if(n[1] < min_dp) + { + ava_k_mer = hp_k_mer = 0; + vLen = MIN(k_flag->a.n, RESEED_LEN); + for (i = k_flag->a.n - vLen; i < (int)k_flag->a.n; i++) + { + if(k_flag->a.a[i] > 1) ava_k_mer++; + if(k_flag->a.a[i] > 2) hp_k_mer++; + } + if(hp_k_mer > ava_k_mer*hp_rate) return 1; + } + + + if(fp) fprintf(fp, "ava_k_mer: %d, hp_k_mer: %d, hp_rate: %f, min_dp: %d\n", ava_k_mer, hp_k_mer, hp_rate, min_dp); + + // if(fp) + // { + // for (k = 0; k < (int)k_flag->a.n; k++) + // { + // if(k_flag->a.a[k] > 0) fprintf(fp, "(%d) %u\n", k, k_flag->a.a[k]); + // } + // } + + return 0; +} + +uint64_t ovlp_occ(overlap_region_alloc* overlap_list, uint8_t is_match) +{ + uint64_t occ = 0, k; + for (k = 0; k < overlap_list->length; k++) { + if(overlap_list->list[k].is_match == is_match) occ++; + } + return occ; +} + +void correct_overlap(overlap_region_alloc* overlap_list, All_reads* R_INF, + UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, + Graph* g, Graph* DAGCon, Cigar_record* current_cigar, + haplotype_evdience_alloc* hap, Round2_alignment* second_round, + kvec_t_u64_warp* v_idx, window_list_alloc* win_ciagr_buf, int force_repeat, int is_consensus, int* fully_cov, int* abnormal) +{ + clear_Correct_dumy(dumy, overlap_list, NULL); + + long long window_start, window_end; + + Window_Pool w_inf; + + init_Window_Pool(&w_inf, g_read->length, WINDOW, (int)(1.0/asm_opt.max_ov_diff_ec)); + + int flag = 0; + + while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) + { + dumy->length = 0; + dumy->lengthNT = 0; + flag = get_interval(window_start, window_end, overlap_list, dumy, w_inf.window_length); + + switch (flag) + { + case 1: ///no match here + break; + case 0: ///no match here + break; + case -2: ///if flag == -2, loop would be terminated + break; + } + + ///dumy->lengthNT represent how many overlaps that the length of them is not equal to WINDOW; may larger or less than WINDOW + ///dumy->length represent how many overlaps that the length of them is WINDOW + /****************************may improve**************************/ + ///now the windows which are larger than WINDOW are verified one-by-one, to improve it, we can do it group-bygroup + verify_window(window_start, window_end, overlap_list, dumy, R_INF, g_read->seq); + } + // fprintf(stderr, "###dumy->start_i:%lu, overlap_list->length:%lu\n\n", dumy->start_i, overlap_list->length); + + // recalcate_window(overlap_list, R_INF, g_read, dumy, overlap_read); + // partition_overlaps(overlap_list, R_INF, g_read, dumy, hap, force_repeat); + recalcate_window_advance(overlap_list, R_INF, NULL, g_read, dumy, overlap_read, v_idx, w_inf.window_length, asm_opt.max_ov_diff_ec, asm_opt.max_ov_diff_final); + // fprintf(stderr, "[M::%s-beg] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, + // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); + partition_overlaps_advance(overlap_list, R_INF, g_read, overlap_read, dumy, hap, force_repeat); + // fprintf(stderr, "[M::%s-after] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, + // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); + if(is_consensus) + { + generate_consensus(overlap_list, R_INF, g_read, dumy, g, DAGCon, current_cigar, second_round, win_ciagr_buf); + } + + (*fully_cov) = check_if_fully_covered(overlap_list, R_INF, g_read, dumy, g, abnormal); +} + +/** +void debug_phasing_status(overlap_region_alloc *olist, ma_ug_t *ug, uint64_t print_w_list, +haplotype_evdience_alloc* hap, UC_Read* g_read, int64_t flanking, uint64_t yid) +{ + uint64_t i, k, l, ii; + int64_t t; + SnpStats *s = NULL; + + for (i = 0; i < olist->length; i++) { + if(olist->list[i].y_id != yid) continue; + fprintf(stderr, "\n[M::utg%.6d%c::is_match->%u] rev->%u, x->[%u, %u), y->[%u, %u)\n", + (int)olist->list[i].y_id+1, "lc"[ug->u.a[olist->list[i].y_id].circ], olist->list[i].is_match, + olist->list[i].y_pos_strand, olist->list[i].x_pos_s, olist->list[i].x_pos_e+1, olist->list[i].y_pos_s, olist->list[i].y_pos_e+1); + if(print_w_list) { + for (k = 0; k < olist->list[i].w_list.n; k++) { + if(olist->list[i].w_list.a[k].y_end != -1) { + fprintf(stderr, "x->[%lu, %lu), y->[%d, %d), e->%d\n", + olist->list[i].w_list.a[k].x_start, olist->list[i].w_list.a[k].x_end+1, + olist->list[i].w_list.a[k].y_start, olist->list[i].w_list.a[k].y_end+1, + olist->list[i].w_list.a[k].error); + } else { + fprintf(stderr, "x->[-1, -1), y->[-1, -1), e->-1\n"); + } + } + } + } + + + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + ii = hap->list[l].overlapID; + if(olist->list[ii].y_id != yid) { + l = k; + continue; + } + for (i = l; i < k; i++) { + if(hap->list[i].type!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->score == 1 && (!(s->occ_0 < 2 || s->occ_1 < 2))) { + fprintf(stderr, "s->site:%u, s->occ_0:%u, s->occ_1:%u, s->occ_2:%u\n", s->site, s->occ_0, s->occ_1, s->occ_2); + for (t = s->site>=flanking?s->site-flanking:0; tlength && t<=s->site+flanking; t++){ + if(t == s->site) fprintf(stderr,"["); + fprintf(stderr,"%c", g_read->seq[t]); + if(t == s->site) fprintf(stderr,"]"); + } + fprintf(stderr,"\n"); + } + } + l = k; + } + } +} +**/ + +void print_ovlp_occ_stat(overlap_region_alloc* overlap_list, uint32_t xlen, uint8_t is_match) +{ + uint64_t k; + for (k = 0; k < overlap_list->length; k++) { + if(overlap_list->list[k].is_match != is_match) continue; + fprintf(stderr, "[M::%s::xlen::%u] utg%.6dl(%c), is_match::%u, x::[%u, %u)\n", __func__, xlen, + (int32_t)overlap_list->list[k].y_id + 1, + "+-"[overlap_list->list[k].y_pos_strand], overlap_list->list[k].is_match, + overlap_list->list[k].x_pos_s, overlap_list->list[k].x_pos_e+1); + } +} +void align_ul_ed(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, char* qstr, char *tstr, double e_rate, int64_t w_l, void *km); +void correct_ul_overlap(overlap_region_alloc* overlap_list, const ul_idx_t *uref, + UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, + Graph* g, Graph* DAGCon, Cigar_record* current_cigar, + haplotype_evdience_alloc* hap, Round2_alignment* second_round, + kvec_t_u64_warp* v_idx, window_list_alloc* win_ciagr_buf, + int force_repeat, int is_consensus, int* fully_cov, int* abnormal, + double max_ov_diff_ec, long long winLen, void *km) +{ + + clear_Correct_dumy(dumy, overlap_list, km); + + Window_Pool w_inf; + init_Window_Pool(&w_inf, g_read->length, winLen, (int)(1.0/max_ov_diff_ec)); + /** + uint64_t i; + for (i = 0; i < overlap_list->length; i++) { + verify_ul_window_s(&(overlap_list->list[i]), uref, g_read->seq, dumy->overlap_region, max_ov_diff_ec, w_inf.window_length, THRESHOLD_MAX_SIZE, km); + // align_ul_ed(&(overlap_list->list[i]), uref, NULL, g_read->seq, dumy->overlap_region, max_ov_diff_ec, w_inf.window_length, km); + } + **/ + + + // recalcate_window(overlap_list, R_INF, g_read, dumy, overlap_read); + // partition_overlaps(overlap_list, R_INF, g_read, dumy, hap, force_repeat); + // recalcate_window_ul_advance(overlap_list, uref, g_read, dumy, overlap_read, max_ov_diff_ec, w_inf.window_length, km); + // recalcate_window_advance(overlap_list, NULL, uref, g_read, dumy, overlap_read, v_idx, w_inf.window_length, max_ov_diff_ec, max_ov_diff_ec); + /** + refine_ed_aln(overlap_list, NULL, uref, g_read, dumy, overlap_read, v_idx, w_inf.window_length, max_ov_diff_ec, max_ov_diff_ec); + **/ + refine_ed_aln_test(overlap_list, NULL, uref, g_read, dumy, overlap_read, v_idx, w_inf.window_length, max_ov_diff_ec, max_ov_diff_ec); + // fprintf(stderr, "[M::%s-beg] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, + // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); + ///after this function, overlap_list is sorted by x_pos_e; used for g_chain + partition_ul_overlaps_advance(overlap_list, uref, g_read, overlap_read, dumy, hap, force_repeat, max_ov_diff_ec, w_inf.window_length, km); + // print_ovlp_occ_stat(overlap_list, g_read->length, 1); + // print_ovlp_occ_stat(overlap_list, g_read->length, 2); + // fprintf(stderr, "[M::%s-end] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, + // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); + // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1176); + // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1167); + // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1170); + /** + + + if(is_consensus) + { + generate_consensus(overlap_list, R_INF, g_read, dumy, g, DAGCon, current_cigar, second_round); + } + + + (*fully_cov) = check_if_fully_covered(overlap_list, R_INF, g_read, dumy, g, abnormal); + **/ +} + + + + +void lchain_align(overlap_region_alloc* overlap_list, const ul_idx_t *uref, + UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, + Graph* g, Graph* DAGCon, Cigar_record* current_cigar, + haplotype_evdience_alloc* hap, Round2_alignment* second_round, + kvec_t_u64_warp* v_idx, window_list_alloc* win_ciagr_buf, + int force_repeat, int is_consensus, int* fully_cov, int* abnormal, + double max_ov_diff_ec, long long winLen, void *km) +{ + + clear_Correct_dumy(dumy, overlap_list, km); + + long long window_start, window_end; + + Window_Pool w_inf; + + init_Window_Pool(&w_inf, g_read->length, winLen, (int)(1.0/max_ov_diff_ec)); + int flag = 0; + + while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) { + dumy->length = 0; dumy->lengthNT = 0; + flag = get_interval(window_start, window_end, overlap_list, dumy, w_inf.window_length); + + switch (flag) { + case 1: ///no match here + break; + case 0: ///no match here + break; + case -2: ///if flag == -2, loop would be terminated + break; + } + + ///dumy->lengthNT represent how many overlaps that the length of them is not equal to WINDOW; may larger or less than WINDOW + ///dumy->length represent how many overlaps that the length of them is WINDOW + ///now the windows which are larger than WINDOW are verified one-by-one, to improve it, we can do it group-bygroup + verify_ul_window(window_start, window_end, overlap_list, dumy, uref, g_read->seq, max_ov_diff_ec, w_inf.window_length, /**THRESHOLD**/THRESHOLD_MAX_SIZE, km); + } + + // recalcate_window(overlap_list, R_INF, g_read, dumy, overlap_read); + // partition_overlaps(overlap_list, R_INF, g_read, dumy, hap, force_repeat); + // recalcate_window_ul_advance(overlap_list, uref, g_read, dumy, overlap_read, max_ov_diff_ec, w_inf.window_length, km); + refine_ed_aln(overlap_list, NULL, uref, g_read, dumy, overlap_read, v_idx, w_inf.window_length, max_ov_diff_ec, max_ov_diff_ec); + // fprintf(stderr, "[M::%s-beg] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, + // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); + ///after this function, overlap_list is sorted by x_pos_e; used for g_chain + partition_ul_overlaps_advance(overlap_list, uref, g_read, overlap_read, dumy, hap, force_repeat, max_ov_diff_ec, w_inf.window_length, km); + // print_ovlp_occ_stat(overlap_list, g_read->length, 1); + // print_ovlp_occ_stat(overlap_list, g_read->length, 2); + // fprintf(stderr, "[M::%s-end] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, + // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); + // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1176); + // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1167); + // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1170); + /** + + + if(is_consensus) + { + generate_consensus(overlap_list, R_INF, g_read, dumy, g, DAGCon, current_cigar, second_round); + } + + + (*fully_cov) = check_if_fully_covered(overlap_list, R_INF, g_read, dumy, g, abnormal); + **/ +} + +void init_Cigar_record(Cigar_record* dummy) +{ + dummy->length = 0; + dummy->size = 100; + dummy->record = (uint32_t*)malloc(sizeof(uint32_t)*dummy->size); + + + dummy->lost_base_length = 0; + dummy->lost_base_size = 100; + dummy->lost_base = (char*)malloc(sizeof(char)*dummy->lost_base_size); + + + + dummy->current_operation_length = 0; + dummy->current_operation = 127; +} + +void init_Cigar_record_buf(Cigar_record* dummy, void *km) +{ + memset(dummy, 0, sizeof(*dummy)); + dummy->current_operation = 127; +} + + +void destory_Cigar_record(Cigar_record* dummy) +{ + free(dummy->record); + free(dummy->lost_base); +} + +void clear_Cigar_record(Cigar_record* dummy) +{ + dummy->new_read_length = 0; + dummy->length = 0; + dummy->lost_base_length = 0; + + dummy->current_operation_length = 0; + dummy->current_operation = 127; +} + + +void init_Correct_dumy_buf(Correct_dumy* list, void *km) +{ + memset(list, 0, sizeof(Correct_dumy)); + int i; + for (i = 0; i < 256; i++){ + list->Peq_SSE[i] = _mm_setzero_si128(); + } +} + + +void init_Correct_dumy(Correct_dumy* list) +{ + list->size = 0; + list->length = 0; + list->lengthNT = 0; + list->start_i = 0; + list->overlapID = NULL; + int i; + for (i = 0; i < 256; i++) + { + list->Peq_SSE[i] = _mm_setzero_si128(); + } + + + list->corrected_read_size = 1000; + list->corrected_read_length = 0; + list->corrected_read = (char*)malloc(sizeof(char)*list->corrected_read_size); + list->corrected_base = 0; + +} + +void destory_Correct_dumy(Correct_dumy* list) +{ + free(list->overlapID); + free(list->corrected_read); +} + + +void clear_Correct_dumy(Correct_dumy* list, overlap_region_alloc* overlap_list, void *km) +{ + list->length = 0; + list->lengthNT = 0; + list->start_i = 0; + + if (list->size < overlap_list->length){ + list->size = overlap_list->length; + if(!km) REALLOC(list->overlapID, list->size); + else KREALLOC(km, list->overlapID, list->size); + } + + list->last_boundary_length = 0; + list->corrected_read_length = 0; + list->corrected_base = 0; + +} + +void clear_Correct_dumy_pure(Correct_dumy* list) +{ + list->length = 0; + list->lengthNT = 0; + list->start_i = 0; + list->last_boundary_length = 0; + list->corrected_read_length = 0; + list->corrected_base = 0; +} + + +void init_Cigar_record_alloc(Cigar_record_alloc* x) +{ + x->length = 0; + x->size = 0; + x->buffer = NULL; +} + +void resize_Cigar_record_alloc(Cigar_record_alloc* x, long long new_size) +{ + long long i; + if(new_size > x->size) + { + x->buffer = (Cigar_record*)realloc(x->buffer, new_size*sizeof(Cigar_record)); + for (i = 0; i < x->size; i++) + { + clear_Cigar_record(&(x->buffer[i])); + } + for (; i < new_size; i++) + { + init_Cigar_record(&(x->buffer[i])); + clear_Cigar_record(&(x->buffer[i])); + } + + x->size = new_size; + } + else + { + for (i = 0; i < new_size; i++) + { + clear_Cigar_record(&(x->buffer[i])); + } + } + + x->length = 0; +} +void destory_Cigar_record_alloc(Cigar_record_alloc* x) +{ + long long i; + for (i = 0; i < x->size; i++) + { + destory_Cigar_record(&(x->buffer[i])); + } + free(x->buffer); +} + + +void add_new_cell_to_cigar_record(Cigar_record* dummy, uint32_t len, uint32_t type) +{ + uint32_t tmp; + tmp = len; + tmp = tmp << 2; + tmp = tmp | type; + + dummy->length++; + + + if(dummy->length > dummy->size) + { + dummy->size = dummy->size * 2; + dummy->record = (uint32_t*)realloc(dummy->record, dummy->size*sizeof(uint32_t)); + } + + dummy->record[dummy->length - 1] = tmp; +} + +void add_existing_cell_to_cigar_record(Cigar_record* dummy, uint32_t len, uint32_t type) +{ + uint32_t tmp; + + tmp = dummy->record[dummy->length - 1] >> 2; + tmp = tmp + len; + tmp = tmp << 2; + tmp = tmp | type; + dummy->record[dummy->length - 1] = tmp; +} + + +void add_new_cell_to_cigar_record_with_different_base(Cigar_record* dummy, uint32_t len, uint32_t type, char* seq) +{ + uint32_t tmp; + tmp = len; + tmp = tmp << 2; + tmp = tmp | type; + + + dummy->length++; + + if(dummy->length > dummy->size) + { + dummy->size = dummy->size * 2; + dummy->record = (uint32_t*)realloc(dummy->record, dummy->size*sizeof(uint32_t)); + } + + dummy->record[dummy->length - 1] = tmp; + + + + if (dummy->lost_base_length + len> dummy->lost_base_size) + { + dummy->lost_base_size = (dummy->lost_base_length + len) * 2; + dummy->lost_base = (char*)realloc(dummy->lost_base, dummy->lost_base_size*sizeof(char)); + } + + uint32_t i = 0; + for (i = 0; i < len; i++, dummy->lost_base_length++) + { + dummy->lost_base[dummy->lost_base_length] = seq[i]; + } +} + +void add_existing_cell_to_cigar_record_with_different_base(Cigar_record* dummy, uint32_t len, uint32_t type, char* seq) +{ + uint32_t tmp; + + tmp = dummy->record[dummy->length - 1] >> 2; + tmp = tmp + len; + tmp = tmp << 2; + tmp = tmp | type; + dummy->record[dummy->length - 1] = tmp; + + if (dummy->lost_base_length + len> dummy->lost_base_size) + { + dummy->lost_base_size = (dummy->lost_base_length + len) * 2; + dummy->lost_base = (char*)realloc(dummy->lost_base, dummy->lost_base_size*sizeof(char)); + } + + uint32_t i = 0; + for (i = 0; i < len; i++, dummy->lost_base_length++) + { + dummy->lost_base[dummy->lost_base_length] = seq[i]; + } +} + +void afine_gap_alignment(const char *qseq, uint8_t* qnum, const int ql, +const char *tseq, uint8_t* tnum, const int tl, const uint8_t *c2n, const int strand, +int sc_mch, int sc_mis, int gapo, int gape, int bandLen, int zdrop, int end_bonus, +long long* max_q_pos, long long* max_t_pos, long long* global_score, +long long* extention_score, long long* q_boundary_score, long long* q_boundary_t_coordinate, +long long* t_boundary_score, long long* t_boundary_q_coordinate, +long long* droped, int mode) +{ + /** + // for ksw2 + (*max_t_pos) = (*max_q_pos) = -1; + int i, a = sc_mch, b = sc_mis < 0? sc_mis : -sc_mis; // a>0 and b<0 + + int8_t mat[25] = {(int8_t)a,(int8_t)b,(int8_t)b,(int8_t)b,0, + (int8_t)b,(int8_t)a,(int8_t)b,(int8_t)b,0, (int8_t)b,(int8_t)b,(int8_t)a,(int8_t)b,0, + (int8_t)b,(int8_t)b,(int8_t)b,(int8_t)a,0, 0,0,0,0,0}; + ksw_extz_t ez; + memset(&ez, 0, sizeof(ksw_extz_t)); + + if(strand == FORWARD_KSW) + { + for (i = 0; i < tl; ++i) tnum[i] = c2n[(uint8_t)tseq[i]]; // encode to 0/1/2/3 + for (i = 0; i < ql; ++i) qnum[i] = c2n[(uint8_t)qseq[i]]; + } + else if(strand == BACKWARD_KSW) + { + for (i = 0; i < tl; ++i) tnum[i] = c2n[(uint8_t)tseq[tl - i - 1]]; // encode to 0/1/2/3 + for (i = 0; i < ql; ++i) qnum[i] = c2n[(uint8_t)qseq[ql - i - 1]]; + } + ksw_extz2_sse(0, ql, qnum, tl, tnum, 5, mat, gapo, gape, bandLen, zdrop, end_bonus, + mode, &ez); + (*global_score) = ez.score; + (*extention_score) = ez.max; + (*q_boundary_score) = ez.mqe; + (*q_boundary_t_coordinate) = ez.mqe_t; + (*t_boundary_score) = ez.mte; + (*t_boundary_q_coordinate) = ez.mte_q; + (*max_t_pos) = ez.max_t; + (*max_q_pos) = ez.max_q; + (*droped) = ez.zdropped; + free(ez.cigar); + + + // for (i = 0; i < ez.n_cigar; ++i) // print CIGAR + // printf("%d%c", ez.cigar[i]>>4, "MID"[ez.cigar[i]&0xf]); + // putchar('\n'); + + // for ksw2 + **/ +} + +int fill_chain_by_affine_gap_debug(Fake_Cigar* chain, char* x_string, char* y_string, overlap_region* ovc, +long long x_readLen, long long y_readLen, Cigar_record* cigar, uint8_t* c2n, uint8_t* x_num, uint8_t* y_num, +long long* minus_score_thres, long long* final_scores) +{ + /** + long long i, xOffset, yOffset, xRegionLen, yRegionLen, maxXpos, maxYpos, zdroped; + long long mapGlobalScore, mapExtentScore; + long long xBuoundaryScore, xBuoundaryYcoordinate, yBuoundaryScore, yBuoundaryXcoordinate; + ///float band_rate = 0.08; + int endbouns, mode; + long long xBeg, yBeg; + xBeg = ovc->x_pos_s; + yBeg = ovc->y_pos_s; + if(chain->length <= 0) return 0; + // long long minus_score_thres = (EstimateOlen*HIGH_HET_ERROR_RATE*(MATCH_SCORE_KSW+(MAX(MISMATCH_SCORE_KSW,GAP_EXT_KSW)))); + // long long total_score_thres = EstimateOlen*MATCH_SCORE_KSW - minus_score_thres; + long long sum_score = 0, current_ovlp = 0, zdrop_occ = 0; + long long new_xBeg, new_yBeg, new_xEnd, new_yEnd; + new_xBeg = ovc->x_pos_s; + new_yBeg = ovc->y_pos_s; + new_xEnd = ovc->x_pos_e; + new_yEnd = ovc->y_pos_e; + ///long long sub_score_sum; + ///deal with region 0 backward + i = 0; + endbouns = 0; + + xOffset = get_fake_gap_pos(chain, 0); + xOffset = xOffset - 1; + yOffset = (xOffset - xBeg) + yBeg + get_fake_gap_shift(chain, 0); + if(xOffset >= 0 && yOffset >= 0) + { + xRegionLen = xOffset + 1; + yRegionLen = yOffset + 1; + //note here cannot use DIFF(xRegionLen, yRegionLen) + // bandLen = (MIN(xRegionLen, yRegionLen))*band_rate; + // if(bandLen == 0) bandLen = MIN(xRegionLen, yRegionLen); + + + ///do alignment backward + ///for beginning part and end part, must use exact mode + mode = KSW_EZ_SCORE_ONLY; + afine_gap_alignment(x_string, x_num, xRegionLen, y_string, y_num, yRegionLen, + c2n, BACKWARD_KSW, MATCH_SCORE_KSW, MISMATCH_SCORE_KSW, GAP_OPEN_KSW, GAP_EXT_KSW, + BAND_KSW, Z_DROP_KSW, endbouns, &maxXpos, &maxYpos, &mapGlobalScore, + &mapExtentScore, &xBuoundaryScore, &xBuoundaryYcoordinate, + &yBuoundaryScore, &yBuoundaryXcoordinate, &zdroped, mode); + + + + + if(!zdroped) + { + if(xRegionLen <= yRegionLen) + { + sum_score += xBuoundaryScore; + new_yBeg = yRegionLen - xBuoundaryYcoordinate - 1; + } + else + { + sum_score += yBuoundaryScore; + new_xBeg = xRegionLen - yBuoundaryXcoordinate - 1; + } + } + else + { ///return 0; + sum_score += mapExtentScore; + if(xRegionLen <= yRegionLen) + { + + sum_score -= (GAP_OPEN_KSW + (xRegionLen - maxXpos)*GAP_EXT_KSW); + } + else + { + sum_score -= (GAP_OPEN_KSW + (yRegionLen - maxYpos)*GAP_EXT_KSW); + } + } + } + + ///align forward + for (i = 0; i < (long long)chain->length; i++) + { + // xOffset = get_fake_gap_pos(chain, i); + // yOffset = xOffset + get_fake_gap_shift(chain, i); + xOffset = get_fake_gap_pos(chain, i); + yOffset = (xOffset - xBeg) + yBeg + get_fake_gap_shift(chain, i); + ///last region + if(i == (long long)(chain->length - 1)) + { + endbouns = 0; + xRegionLen = x_readLen - xOffset; + yRegionLen = y_readLen - yOffset; + ///for beginning part and end part, must use exact mode + mode = KSW_EZ_SCORE_ONLY; + //note here cannot use DIFF(xRegionLen, yRegionLen) + // bandLen = (MIN(xRegionLen, yRegionLen))*band_rate; + // if(bandLen == 0) bandLen = MIN(xRegionLen, yRegionLen); + } + else + { + ///higher endbouns for middle regions + endbouns = MATCH_SCORE_KSW; + xRegionLen = get_fake_gap_pos(chain, i+1) - xOffset; + yRegionLen = (get_fake_gap_pos(chain, i+1) + get_fake_gap_shift(chain, i+1)) - + (get_fake_gap_pos(chain, i) + get_fake_gap_shift(chain, i)); + mode = KSW_EZ_SCORE_ONLY | KSW_EZ_APPROX_MAX | KSW_EZ_APPROX_DROP; + // bandLen = MAX((MIN(xRegionLen, yRegionLen))*band_rate, DIFF(xRegionLen, yRegionLen)); + // if(bandLen == 0) bandLen = MIN(xRegionLen, yRegionLen); + } + + + if(minus_score_thres) + { + current_ovlp = MIN((xOffset + 1 - xBeg), (yOffset + 1 - yBeg)); + current_ovlp = current_ovlp*MATCH_SCORE_KSW; + if(current_ovlp - sum_score > (*minus_score_thres)) + { + return 0; + } + } + + if(xOffset < 0) xOffset = 0; + if(yOffset < 0) yOffset = 0; + if(xRegionLen < 0) xRegionLen = 0; + if(yRegionLen < 0) yRegionLen = 0; + + ///do alignment forward + ///text is x, query is y + afine_gap_alignment(x_string+xOffset, x_num, xRegionLen, y_string+yOffset, y_num, yRegionLen, + c2n, FORWARD_KSW, MATCH_SCORE_KSW, MISMATCH_SCORE_KSW, GAP_OPEN_KSW, GAP_EXT_KSW, + BAND_KSW, Z_DROP_KSW, endbouns, &maxXpos, &maxYpos, &mapGlobalScore, + &mapExtentScore, &xBuoundaryScore, &xBuoundaryYcoordinate, + &yBuoundaryScore, &yBuoundaryXcoordinate, &zdroped, mode); + // fprintf(stderr, "# xOffset: %lld, yOffset: %lld, xRegionLen: %lld, yRegionLen: %lld, bandLen: %lld, maxXpos: %lld, maxYpos: %lld, zdroped: %lld\n", + // xOffset, yOffset, xRegionLen, yRegionLen, BAND_KSW, maxXpos, maxYpos, zdroped); + + if(!zdroped) + { + if(i != (long long)(chain->length - 1)) + { + sum_score += mapGlobalScore; + } + else + { + if(xRegionLen <= yRegionLen) + { + sum_score += xBuoundaryScore; + new_yEnd = yOffset + xBuoundaryYcoordinate; + } + else + { + sum_score += yBuoundaryScore; + new_xEnd = xOffset + yBuoundaryXcoordinate; + // if(new_xEnd != (long long)ovc->x_pos_e) + // { + // fprintf(stderr, "\n******direction: %u, new_xBeg: %lld, new_xEnd: %lld, new_yBeg: %lld, new_yEnd: %lld, old_xBeg: %u, old_xEnd: %u, old_yBeg: %u, old_yEnd: %u\n", + // ovc->y_pos_strand, new_xBeg, new_xEnd, new_yBeg, new_yEnd, ovc->x_pos_s, ovc->x_pos_e, ovc->y_pos_s, ovc->y_pos_e); + // fprintf(stderr, "x_readLen: %lld, y_readLen: %lld\n", x_readLen, y_readLen); + // fprintf(stderr, "xID: %lld, yID: %lld\n", ovc->x_id, ovc->y_id); + // fprintf(stderr, "xRegionLen: %lld, yRegionLen: %lld\n", xRegionLen, yRegionLen); + // fprintf(stderr, "xOffset: %lld, yOffset: %lld\n", xOffset, yOffset); + // fprintf(stderr, "yBuoundaryXcoordinate: %lld\n", yBuoundaryXcoordinate); + // } + } + } + } + else + { + ///return 0; + if(i != (long long)(chain->length - 1)) zdrop_occ++; + if(zdrop_occ > 1) return 0; + sum_score += mapExtentScore; + if(xRegionLen <= yRegionLen) + { + sum_score -= (GAP_OPEN_KSW + (xRegionLen - maxXpos)*GAP_EXT_KSW); + } + else + { + sum_score -= (GAP_OPEN_KSW + (yRegionLen - maxYpos)*GAP_EXT_KSW); + } + } + } + + (*final_scores) = sum_score; + if(new_xBeg != (long long)ovc->x_pos_s || new_xEnd != (long long)ovc->x_pos_e || + new_yBeg != (long long)ovc->y_pos_s || new_yEnd != (long long)ovc->y_pos_e) + { + // fprintf(stderr, "\ntttdirection: %u, new_xBeg: %lld, new_xEnd: %lld, new_yBeg: %lld, new_yEnd: %lld, old_xBeg: %u, old_xEnd: %u, old_yBeg: %u, old_yEnd: %u\n", + // ovc->y_pos_strand, new_xBeg, new_xEnd, new_yBeg, new_yEnd, ovc->x_pos_s, ovc->x_pos_e, ovc->y_pos_s, ovc->y_pos_e); + // fprintf(stderr, "x_readLen: %lld, y_readLen: %lld\n", x_readLen, y_readLen); + // fprintf(stderr, "xID: %lld, yID: %lld\n", ovc->x_id, ovc->y_id); + // for (i = 0; i < (long long)chain->length; i++) + // { + // fprintf(stderr,"i: %lld, x_pos: %d, offset: %d\n", + // i, get_fake_gap_pos(chain, i), get_fake_gap_shift(chain, i)); + // } + } + else + { + // fprintf(stderr, "\nkkkdirection: %u, new_xBeg: %lld, new_xEnd: %lld, new_yBeg: %lld, new_yEnd: %lld, old_xBeg: %u, old_xEnd: %u, old_yBeg: %u, old_yEnd: %u\n", + // ovc->y_pos_strand, new_xBeg, new_xEnd, new_yBeg, new_yEnd, ovc->x_pos_s, ovc->x_pos_e, ovc->y_pos_s, ovc->y_pos_e); + // fprintf(stderr, "x_readLen: %lld, y_readLen: %lld\n", x_readLen, y_readLen); + // fprintf(stderr, "xID: %lld, yID: %lld\n", ovc->x_id, ovc->y_id); + // for (i = 0; i < (long long)chain->length; i++) + // { + // fprintf(stderr,"i: %lld, x_pos: %d, offset: %d\n", + // i, get_fake_gap_pos(chain, i), get_fake_gap_shift(chain, i)); + // } + } + **/ + + return 1; +} + + + +int fill_chain_by_affine_gap(Fake_Cigar* chain, char* x_string, char* y_string, overlap_region* ovc, +long long x_readLen, long long y_readLen, Cigar_record* cigar, uint8_t* c2n, uint8_t* x_num, uint8_t* y_num, +long long* minus_score_thres, long long* final_scores) +{ + /** + long long i, xOffset, yOffset, xRegionLen, yRegionLen, maxXpos, maxYpos, zdroped; + long long mapGlobalScore, mapExtentScore; + long long xBuoundaryScore, xBuoundaryYcoordinate, yBuoundaryScore, yBuoundaryXcoordinate; + ///float band_rate = 0.08; + int endbouns, mode; + long long xBeg, yBeg; + xBeg = ovc->x_pos_s; + yBeg = ovc->y_pos_s; + if(chain->length <= 0) return 0; + long long sum_score = 0, current_ovlp = 0, zdrop_occ = 0; + long long chain_num = (long long)chain->length - 1; + + ///align forward + for (i = 0; i < chain_num; i++) + { + xOffset = get_fake_gap_pos(chain, i); + yOffset = (xOffset - xBeg) + yBeg + get_fake_gap_shift(chain, i); + ///last region + + ///higher endbouns for middle regions + endbouns = MATCH_SCORE_KSW; + xRegionLen = get_fake_gap_pos(chain, i+1) - xOffset; + yRegionLen = (get_fake_gap_pos(chain, i+1) + get_fake_gap_shift(chain, i+1)) - + (get_fake_gap_pos(chain, i) + get_fake_gap_shift(chain, i)); + ///last region + if(i == chain_num - 1) + { + xRegionLen++; + yRegionLen++; + } + + mode = KSW_EZ_SCORE_ONLY | KSW_EZ_APPROX_MAX | KSW_EZ_APPROX_DROP; + + + if(minus_score_thres) + { + current_ovlp = MIN((xOffset - xBeg), (yOffset - yBeg)); + current_ovlp = current_ovlp*MATCH_SCORE_KSW; + if(current_ovlp - sum_score > (*minus_score_thres)) + { + return 0; + } + } + + if(xOffset < 0) xOffset = 0; + if(yOffset < 0) yOffset = 0; + if(xRegionLen < 0) xRegionLen = 0; + if(yRegionLen < 0) yRegionLen = 0; + + ///do alignment forward + ///text is x, query is y + afine_gap_alignment(x_string+xOffset, x_num, xRegionLen, y_string+yOffset, y_num, yRegionLen, + c2n, FORWARD_KSW, MATCH_SCORE_KSW, MISMATCH_SCORE_KSW, GAP_OPEN_KSW, GAP_EXT_KSW, + BAND_KSW, Z_DROP_KSW, endbouns, &maxXpos, &maxYpos, &mapGlobalScore, + &mapExtentScore, &xBuoundaryScore, &xBuoundaryYcoordinate, + &yBuoundaryScore, &yBuoundaryXcoordinate, &zdroped, mode); + + + if(!zdroped) + { + sum_score += mapGlobalScore; + } + else + { + ///return 0; + zdrop_occ++; + ///if(zdrop_occ > 1) return 0; + sum_score += mapExtentScore; + if(xRegionLen <= yRegionLen) + { + sum_score -= (GAP_OPEN_KSW + (xRegionLen - maxXpos)*GAP_EXT_KSW); + } + else + { + sum_score -= (GAP_OPEN_KSW + (yRegionLen - maxYpos)*GAP_EXT_KSW); + } + } + } + + (*final_scores) = sum_score; + **/ + return 1; +} + + + +long long get_affine_gap_score(overlap_region* ovc, UC_Read* g_read, UC_Read* overlap_read, uint8_t* x_num, +uint8_t* y_num, uint64_t EstimateXOlen, uint64_t EstimateYOlen) +{ + char* x_string; + char* y_string; + uint64_t yStrand; + long long minus_score_thres = (MAX(EstimateXOlen, EstimateYOlen)*HIGH_HET_ERROR_RATE*(MATCH_SCORE_KSW+(MAX(MISMATCH_SCORE_KSW,GAP_EXT_KSW)))); + long long total_score_thres = MAX(EstimateXOlen, EstimateYOlen)*MATCH_SCORE_KSW - minus_score_thres; + + yStrand = ovc->y_pos_strand; + + if(yStrand == 0) + { + recover_UC_Read(overlap_read, &R_INF, ovc->y_id); + } + else + { + recover_UC_Read_RC(overlap_read, &R_INF, ovc->y_id); + } + x_string = g_read->seq; + y_string = overlap_read->seq; + + long long sum = 0; + + if(fill_chain_by_affine_gap(&(ovc->f_cigar), x_string, y_string, ovc, Get_READ_LENGTH(R_INF, ovc->x_id), + Get_READ_LENGTH(R_INF, ovc->y_id), NULL, seq_nt6_table, x_num, y_num, &minus_score_thres, &sum) == 0) + { + return 0; + } + + if(sum >= total_score_thres) return 1; + return 0; +} + +/** +void recalcate_high_het_overlap(overlap_region_alloc* overlap_list, All_reads* R_INF, + UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read) +{ + long long j, k, i; + int threshold; + long long y_id; + int y_strand; + long long y_readLen; + long long x_start; + long long x_end; + long long x_len; + long long total_y_start; + long long total_y_end; + long long y_start; + long long Window_Len; + char* x_string; + char* y_string; + int end_site; + unsigned int error; + int real_y_start; + long long overlap_length; + int extra_begin, extra_end; + long long o_len; + kvec_t(uint8_t) x_num; + kvec_t(uint8_t) y_num; + kv_init(x_num); + kv_init(y_num); + + for (j = 0; j < (long long)overlap_list->length; j++) + { + + if(overlap_list->list[j].w_list_length == 0) continue; + y_id = overlap_list->list[j].y_id; + y_strand = overlap_list->list[j].y_pos_strand; + y_readLen = Get_READ_LENGTH((*R_INF), y_id); + + //i corresponding to each window of a overlap + //utilize the the end pos of pre-window in backwards + for (i = overlap_list->list[j].w_list_length - 1; i >= 0; i--) + { + ///the first matched window + if(overlap_list->list[j].w_list[i].y_end != -1) + { + ///note!!! need notification + ///this is the actual end postion in ystring + total_y_start = overlap_list->list[j].w_list[i].y_end + - overlap_list->list[j].w_list[i].extra_begin + 1; + + ///k corresponding to all unmatched windows at the right side of overlap_list->list[j].w_list[i] + ///so k starts from i + 1, and end to the first matched window + for (k = i + 1; k < (long long)overlap_list->list[j].w_list_length && overlap_list->list[j].w_list[k].y_end == -1; k++) + { + extra_begin = extra_end = 0; + + ///if y_start > y_readLen, direct terminate + if (total_y_start >= y_readLen) + { + break; + } + + ///there is no problem for x + x_start = overlap_list->list[j].w_list[k].x_start; + x_end = overlap_list->list[j].w_list[k].x_end; + x_len = x_end - x_start + 1; + ///there are two potiential reasons for unmatched window: + ///1. this window has a large number of differences + ///2. DP does not start from the right offset + threshold = double_error_threshold(overlap_list->list[j].w_list[k].error_threshold, x_len); + + y_start = total_y_start; + Window_Len = x_len + (threshold << 1); + + if(!determine_overlap_region(threshold, y_start, y_id, Window_Len, Get_READ_LENGTH((*R_INF), y_id), + &extra_begin, &extra_end, &y_start, &o_len)) + { + break; + } + + if(o_len + threshold < x_len) + { + break; + } + + fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, + R_INF, y_id, extra_begin, extra_end); + + x_string = g_read->seq + x_start; + y_string = dumy->overlap_region; + + ///note!!! need notification + end_site = Reserve_Banded_BPM(y_string, Window_Len, x_string, x_len, threshold, &error); + + ///if error==-1, unmatched + if (error!=(unsigned int)-1) + { + overlap_list->list[j].w_list[k].cigar.length = -1; + overlap_list->list[j].w_list[k].y_start = y_start; + overlap_list->list[j].w_list[k].y_end = y_start + end_site; + overlap_list->list[j].w_list[k].error = (int)error; + ///note!!! need notification + overlap_list->list[j].w_list[k].extra_begin = extra_begin; + overlap_list->list[j].w_list[k].extra_end = extra_end; + overlap_list->list[j].w_list[k].error_threshold = threshold; + + overlap_list->list[j].align_length += x_len; + } + else + { + break; + } + + ///note!!! need notification + total_y_start = y_start + end_site - extra_begin + 1; + } + + } + + } + + + + //i corresponding to each window of a overlap + //utilize the the start pos of next window in forward + for (i = 0; i < (long long)overlap_list->list[j].w_list_length; i++) + { + ///find the first matched window, which should not be the first window + ///the pre-window of this matched window must be unmatched + if(overlap_list->list[j].w_list[i].y_end != -1 && i != 0 && overlap_list->list[j].w_list[i - 1].y_end == -1) + { + ///check if the start pos of this matched window has been calculated + if(overlap_list->list[j].w_list[i].cigar.length == -1) + { + ///there is no problem for x + x_start = overlap_list->list[j].w_list[i].x_start; + x_end = overlap_list->list[j].w_list[i].x_end; + x_len = x_end - x_start + 1; + //may have bugs + threshold = overlap_list->list[j].w_list[i].error_threshold; + //may have bugs + //may have bugs + ///should not adjust threshold, since this window can be matched by the old threshold + ///threshold = Adjust_Threshold(threshold, x_len); + //may have bugs + Window_Len = x_len + (threshold << 1); + + + ///y_start is the real y_start + y_start = overlap_list->list[j].w_list[i].y_start; + extra_begin = overlap_list->list[j].w_list[i].extra_begin; + extra_end = overlap_list->list[j].w_list[i].extra_end; + o_len = Window_Len - extra_end - extra_begin; + fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, + R_INF, y_id, extra_begin, extra_end); + x_string = g_read->seq + x_start; + y_string = dumy->overlap_region; + + ///note!!! need notification + end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, + &(dumy->path_length), dumy->matrix_bit, dumy->path, + overlap_list->list[j].w_list[i].error, overlap_list->list[j].w_list[i].y_end - y_start); + + + ///y_start has already been calculated + if (error != (unsigned int)-1) + { + ///this condition is always wrong + ///in best case, real_y_start = threshold, end_site = Window_Len - threshold - 1 + if (end_site == Window_Len - 1 || real_y_start == 0) + { + if(fix_boundary(x_string, x_len, threshold, y_start, real_y_start, + end_site, extra_begin, extra_end, y_id, Window_Len, R_INF, dumy, + y_strand, error, &y_start, &real_y_start, &end_site, &extra_begin, + &extra_end, &error)) + { + overlap_list->list[j].w_list[i].error = error; + overlap_list->list[j].w_list[i].extra_begin = extra_begin; + overlap_list->list[j].w_list[i].extra_end = extra_end; + } + } + + generate_cigar(dumy->path, dumy->path_length, &(overlap_list->list[j].w_list[i]), + &real_y_start, &end_site, &error, x_string, x_len, y_string); + + ///note!!! need notification + real_y_start = y_start + real_y_start - extra_begin; + overlap_list->list[j].w_list[i].y_start = real_y_start; + ///I forget why don't reduce the extra_begin for y_end + ///it seems extra_begin will be reduced at the end of this function + overlap_list->list[j].w_list[i].y_end = y_start + end_site; + overlap_list->list[j].w_list[i].error = error; + } + else + { + fprintf(stderr, "error\n"); + } + } + else + { + real_y_start = overlap_list->list[j].w_list[i].y_start; + } + + + ///the end pos for pre window is real_y_start - 1 + total_y_end = real_y_start - 1; + ///find the unmatched window on the left of current matched window + ///k starts from i - 1 + for (k = i - 1; k >= 0 && overlap_list->list[j].w_list[k].y_end == -1; k--) + { + ///there is no problem in x + x_start = overlap_list->list[j].w_list[k].x_start; + x_end = overlap_list->list[j].w_list[k].x_end; + x_len = x_end - x_start + 1; + ///there are two potiential reasons for unmatched window: + ///1. this window has a large number of differences + ///2. DP does not start from the right offset + threshold = double_error_threshold(overlap_list->list[j].w_list[k].error_threshold, x_len); + + Window_Len = x_len + (threshold << 1); + + if(total_y_end <= 0) + { + break; + } + + ///y_start might be less than 0 + y_start = total_y_end - x_len + 1; + if(!determine_overlap_region(threshold, y_start, y_id, Window_Len, Get_READ_LENGTH((*R_INF), y_id), + &extra_begin, &extra_end, &y_start, &o_len)) + { + break; + } + + if(o_len + threshold < x_len) + { + break; + } + + fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, + R_INF, y_id, extra_begin, extra_end); + x_string = g_read->seq + x_start; + y_string = dumy->overlap_region; + + ///note!!! need notification + end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, + &(dumy->path_length), dumy->matrix_bit, dumy->path, -1, -1); + + if (error!=(unsigned int)-1) + { + ///this condition is always wrong + ///in best case, real_y_start = threshold, end_site = Window_Len - threshold - 1 + if (end_site == Window_Len - 1 || real_y_start == 0) + { + fix_boundary(x_string, x_len, threshold, y_start, real_y_start, end_site, + extra_begin, extra_end, y_id, Window_Len, R_INF, dumy, y_strand, error, + &y_start, &real_y_start, &end_site, + &extra_begin, &extra_end, &error); + } + + generate_cigar(dumy->path, dumy->path_length, &(overlap_list->list[j].w_list[k]), + &real_y_start, &end_site, &error, x_string, x_len, y_string); + + ///y_start has no shift, but y_end has shift + overlap_list->list[j].w_list[k].y_start = y_start + real_y_start - extra_begin; + overlap_list->list[j].w_list[k].y_end = y_start + end_site; + overlap_list->list[j].w_list[k].error = error; + overlap_list->list[j].align_length += x_len; + overlap_list->list[j].w_list[k].extra_begin = extra_begin; + overlap_list->list[j].w_list[k].extra_end = extra_end; + overlap_list->list[j].w_list[k].error_threshold = threshold; + } + else + { + break; + } + + total_y_end = y_start + real_y_start - 1 - extra_begin; + } + } + } + } + + + + overlap_list->mapped_overlaps_length = 0; + + double error_rate; + int is_update = 0; + for (j = 0; j < (long long)overlap_list->length; j++) + { + y_id = overlap_list->list[j].y_id; + y_strand = overlap_list->list[j].y_pos_strand; + y_readLen = Get_READ_LENGTH((*R_INF), y_id); + overlap_length = overlap_list->list[j].x_pos_e - overlap_list->list[j].x_pos_s + 1; + overlap_list->list[j].is_match = 0; + is_update = 0; + ///debug_scan_cigar(&(overlap_list->list[j])); + if(overlap_list->list[j].w_list_length == 0 || overlap_length == 0 || overlap_list->list[j].align_length == 0) continue; + ///only calculate cigar for high quality overlaps + if (overlap_length * OVERLAP_THRESHOLD_FILTER <= overlap_list->list[j].align_length) + { + + for (i = 0; i < (long long)overlap_list->list[j].w_list_length; i++) + { + ///first we need to check if this window is matched + if(overlap_list->list[j].w_list[i].y_end != -1) + { + ///second check if the cigar of this window has been got + if(overlap_list->list[j].w_list[i].cigar.length == -1) + { + ///there is no problem for x + x_start = overlap_list->list[j].w_list[i].x_start; + x_end = overlap_list->list[j].w_list[i].x_end; + x_len = x_end - x_start + 1; + //may have bugs + ///threshold = x_len * asm_opt.max_ov_diff_ec; + threshold = overlap_list->list[j].w_list[i].error_threshold; + //may have bugs + //may have bugs + ///should not adjust threshold, since this window can be matched by the old threshold + ///threshold = Adjust_Threshold(threshold, x_len); + //may have bugs + Window_Len = x_len + (threshold << 1); + + + ///y_start is the real y_start + ///for the window with cigar, y_start has already reduced extra_begin + y_start = overlap_list->list[j].w_list[i].y_start; + extra_begin = overlap_list->list[j].w_list[i].extra_begin; + extra_end = overlap_list->list[j].w_list[i].extra_end; + o_len = Window_Len - extra_end - extra_begin; + fill_subregion(dumy->overlap_region, y_start, o_len, y_strand, + R_INF, y_id, extra_begin, extra_end); + x_string = g_read->seq + x_start; + y_string = dumy->overlap_region; + + + ///note!!! need notification + end_site = Reserve_Banded_BPM_PATH(y_string, Window_Len, x_string, x_len, threshold, &error, &real_y_start, + &(dumy->path_length), dumy->matrix_bit, dumy->path, + overlap_list->list[j].w_list[i].error, overlap_list->list[j].w_list[i].y_end - y_start); + + if (error != (unsigned int)-1) + { + if (end_site == Window_Len - 1 || real_y_start == 0) + { + + if(fix_boundary(x_string, x_len, threshold, y_start, real_y_start, end_site, + extra_begin, extra_end, y_id, Window_Len, R_INF, dumy, y_strand, error, + &y_start, &real_y_start, &end_site, + &extra_begin, &extra_end, &error)) + { + overlap_list->list[j].w_list[i].error = error; + overlap_list->list[j].w_list[i].extra_begin = extra_begin; + overlap_list->list[j].w_list[i].extra_end = extra_end; + } + + } + + generate_cigar(dumy->path, dumy->path_length, &(overlap_list->list[j].w_list[i]), + &real_y_start, &end_site, &error, x_string, x_len, y_string); + + ///note!!! need notification + real_y_start = y_start + real_y_start - extra_begin; + overlap_list->list[j].w_list[i].y_start = real_y_start; + overlap_list->list[j].w_list[i].y_end = y_start + end_site - extra_begin; + overlap_list->list[j].w_list[i].error = error; + } + else + { + fprintf(stderr, "error\n"); + } + } + else + { + overlap_list->list[j].w_list[i].y_end -= overlap_list->list[j].w_list[i].extra_begin; + } + + + } + } + + error_rate = non_trim_error_rate(overlap_list, j, R_INF, dumy, g_read); + + + if (error_rate <= HIGH_HET_ERROR_RATE) + { + is_update = 1; + } + } + + if((is_update == 0) && (overlap_list->list[j].align_length >= WINDOW) && + (overlap_length * HIGH_HET_OVERLAP_THRESHOLD_FILTER <= overlap_list->list[j].align_length)) + { + kv_resize(uint8_t, x_num, (uint64_t)(Get_READ_LENGTH((*R_INF), overlap_list->list[j].x_id))); + kv_resize(uint8_t, y_num, (uint64_t)(Get_READ_LENGTH((*R_INF), overlap_list->list[j].y_id))); + is_update = get_affine_gap_score(&(overlap_list->list[j]), g_read, overlap_read, x_num.a, y_num.a, + overlap_list->list[j].x_pos_e + 1 - overlap_list->list[j].x_pos_s, + overlap_list->list[j].y_pos_e + 1 - overlap_list->list[j].y_pos_s); + } + + if(is_update) + { + overlap_list->list[j].is_match = 2; + } + } + + kv_destroy(x_num); + kv_destroy(y_num); +} + + + +void correct_overlap_high_het(overlap_region_alloc* overlap_list, All_reads* R_INF, + UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read) +{ + clear_Correct_dumy(dumy, overlap_list, NULL); + + long long window_start, window_end; + + Window_Pool w_inf; + + init_Window_Pool(&w_inf, g_read->length, WINDOW, (int)(1.0/asm_opt.max_ov_diff_ec)); + + int flag = 0; + + while(get_Window(&w_inf, &window_start, &window_end) && flag != -2) + { + dumy->length = 0; + dumy->lengthNT = 0; + flag = get_interval(window_start, window_end, overlap_list, dumy, w_inf.window_length); + + switch (flag) + { + case 1: ///no match here + break; + case 0: ///no match here + break; + case -2: ///if flag == -2, loop would be terminated + break; + } + + ///dumy->lengthNT represent how many overlaps that the length of them is not equal to WINDOW; may larger or less than WINDOW + ///dumy->length represent how many overlaps that the length of them is WINDOW + //may improve + ///now the windows which are larger than WINDOW are verified one-by-one, to improve it, we can do it group-bygroup + verify_window(window_start, window_end, overlap_list, dumy, R_INF, g_read->seq); + } + + recalcate_high_het_overlap(overlap_list, R_INF, g_read, dumy, overlap_read); +} +**/ + +uint64_t update_ov_track_0(Fake_Cigar* z, overlap_region *o, int64_t apend_be, int64_t xl, int64_t yl, +k_mer_hit* hit, int64_t n_hit) +{ + int64_t k, dq, dr, dd, pdd = INT32_MAX, xr, yr; + z->length = 0; + if(hit[0].readID != o->y_id || hit[0].strand != o->y_pos_strand) return 0; + ///update o->s + o->x_pos_s = hit[0].self_offset; o->y_pos_s = hit[0].offset; + if(o->x_pos_s <= o->y_pos_s) { + o->y_pos_s -= o->x_pos_s; o->x_pos_s = 0; + } else { + o->x_pos_s -= o->y_pos_s; o->y_pos_s = 0; + } + + if(apend_be == 1) add_fake_cigar(z, o->x_pos_s, 0, NULL); + for (k = 0; (k < n_hit) && (hit[k].readID == o->y_id) && (hit[k].strand == o->y_pos_strand); k++) { + dq = hit[k].self_offset - o->x_pos_s; + dr = hit[k].offset - o->y_pos_s; + dd = dr - dq; + if(dd != pdd) { + pdd = dd; + add_fake_cigar(z, hit[k].self_offset, pdd, NULL); + } + } + ///update o->s + o->x_pos_e = hit[k-1].self_offset; o->y_pos_e = hit[k-1].offset; + xr = xl-o->x_pos_e-1; yr = yl-o->y_pos_e-1; + if(xr <= yr) { + o->x_pos_e = xl-1; o->y_pos_e += xr; + } else { + o->y_pos_e = yl-1; o->x_pos_e += yr; + } + + if((apend_be == 1) && (get_fake_gap_pos(z, z->length-1)!=((int64_t)o->x_pos_e))) { + add_fake_cigar(z, o->x_pos_e, get_fake_gap_shift(z, z->length-1), NULL); + } + + return k; +} + +int64_t iter_hpc(uint8_t *m, int64_t mn, int64_t *mo, int64_t rev, int64_t *so, int64_t *ho, int64_t sc) +{ + if(sc == 0) return 0; + if(sc <= (*so)) return (*ho)-1; + if(!rev) { + while((*mo) < mn) { + for (; (*mo) < mn && m[(*mo)] == 255; (*mo)++) { + (*so) += m[(*mo)]; + } + (*so) += m[(*mo)]; (*mo)++; (*ho)++; + if(sc <= (*so)) return (*ho)-1; + } + } else { + while((*mo) < mn) { + (*so) += m[mn-(*mo)-1]; (*mo)++; (*ho)++; + for (; (*mo) < mn && m[mn-(*mo)-1] == 255; (*mo)++) { + (*so) += m[mn-(*mo)-1]; + } + if(sc <= (*so)) return (*ho)-1; + } + } + + return -1; +} + +uint64_t update_ov_track_hpc_0(Fake_Cigar* z, overlap_region *o, int64_t apend_be, int64_t xhl, +uint32_t *x_idx, int64_t y_idx_map_l, uint8_t *y_idx_map, hpc_t *hpc_g, k_mer_hit* hit, int64_t n_hit) +{ + int64_t k, dq, dr, dd, pdd = INT32_MAX, xr, yr, yhl, mo = 0, so = 0, ho = 0, x1, y1; + z->length = 0; + if(hit[0].readID != o->y_id || hit[0].strand != o->y_pos_strand) return 0; + yhl = hpc_len(*hpc_g, o->y_id); + + x1 = x_idx[hit[0].self_offset]; + y1 = iter_hpc(y_idx_map, y_idx_map_l, &mo, o->y_pos_strand, &so, &ho, hit[0].offset); + assert(y1 >= 0); + o->x_pos_s = x1; o->y_pos_s = y1; + + ///update o->s + if(o->x_pos_s <= o->y_pos_s) { + o->y_pos_s -= o->x_pos_s; o->x_pos_s = 0; + } else { + o->x_pos_s -= o->y_pos_s; o->y_pos_s = 0; + } + + + if(apend_be == 1) add_fake_cigar(z, o->x_pos_s, 0, NULL); + for (k = 0; (k < n_hit) && (hit[k].readID == o->y_id) && (hit[k].strand == o->y_pos_strand); k++) { + x1 = x_idx[hit[k].self_offset]; + y1 = iter_hpc(y_idx_map, y_idx_map_l, &mo, o->y_pos_strand, &so, &ho, hit[k].offset); + assert(y1 >= 0); + dq = x1 - o->x_pos_s; + dr = y1 - o->y_pos_s; + dd = dr - dq; + if(dd != pdd) { + pdd = dd; + add_fake_cigar(z, x1, pdd, NULL); + } + } + ///update o->s + x1 = x_idx[hit[k-1].self_offset]; + y1 = iter_hpc(y_idx_map, y_idx_map_l, &mo, o->y_pos_strand, &so, &ho, hit[k-1].offset); + assert(y1 >= 0); + o->x_pos_e = x1; o->y_pos_e = y1; + xr = xhl-o->x_pos_e-1; yr = yhl-o->y_pos_e-1; + if(xr <= yr) { + o->x_pos_e = xhl-1; o->y_pos_e += xr; + } else { + o->y_pos_e = yhl-1; o->x_pos_e += yr; + } + + if((apend_be == 1) && (get_fake_gap_pos(z, z->length-1)!=((int64_t)o->x_pos_e))) { + add_fake_cigar(z, o->x_pos_e, get_fake_gap_shift(z, z->length-1), NULL); + } + + return k; +} + +///(char *qstr, kvec_t_u64_warp* q_idx) -> only used for hpc +uint64_t update_ol_track(overlap_region_alloc* ol, Candidates_list *cl, hpc_t *hpc_g, const ul_idx_t *udb, uint32_t apend_be, uint64_t qlen, +char *qstr, kvec_t_u32_warp* q_idx) +{ + uint64_t cln = cl->length, i, k, l, m = 0; overlap_region *r; + if(hpc_g) { + if(ol->length) { + q_idx->a.n = 0; kv_resize(uint32_t, q_idx->a, qlen); m = 0; + for (l = 0, k = 1; k <= qlen; k++) { + if((k == qlen) || (qstr[k] != qstr[l]) || (seq_nt4_table[(uint8_t)qstr[l]] >= 4)) { + for (i = l; i < k; i++) q_idx->a.a[i] = m; + l = k; m++; + } + } + + for (i = k = 0; i < ol->length; ++i) { + r = &(ol->list[i]); k = r->non_homopolymer_errors; + update_ov_track_hpc_0(&(r->f_cigar), r, apend_be, m, q_idx->a.a, + (uint32_t)hpc_g->mm->idx[r->y_id], hpc_g->mm->a + (hpc_g->mm->idx[r->y_id]>>32), + hpc_g, cl->list+k, cln-k); + } + } + } else { + if(ol->length) { + for (i = k = 0; i < ol->length; ++i) { + r = &(ol->list[i]); k = r->non_homopolymer_errors; + update_ov_track_0(&(r->f_cigar), r, apend_be, qlen, udb->ug->u.a[r->y_id].len, cl->list+k, cln-k); + } + } + } + return m;///hpc length +} + +uint64_t gen_hpc_str(const char *in, uint32_t in_l, UC_Read *z, uint64_t *in_hl) +{ + uint64_t hl, k, l; + if(in_hl) { + hl = (*in_hl); + } else { + for (l = hl = 0, k = 1; k <= in_l; k++) { + if((k == in_l) || (in[k] != in[l]) || (seq_nt4_table[(uint8_t)in[l]] >= 4)) { + hl++; l = k; + } + } + } + resize_UC_Read(z, hl); z->length = 0; + for (l = 0, k = 1; k <= in_l; k++) { + if((k == in_l) || (in[k] != in[l]) || (seq_nt4_table[(uint8_t)in[l]] >= 4)) { + z->seq[z->length++] = in[l]; l = k; + } + } + return hl; +} + +///ts do not have aux_beg, while te has +uint32_t push_wlst(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, overlap_region* ol, + char* qstr, char *tstr, char *tstr_1, Correct_dumy* dumy, + int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t tl, + int64_t error, int64_t aux_beg, int64_t aux_end, int64_t thres, double e_rate, + int64_t block_s, uint32_t sec_check, double ovlp_cut, void *km) +{ + + window_list p, t, *a; int64_t w_e, w_s, ce = qs - 1, cs = ol->x_pos_s, toff, ovl, ualn, aln; + uint64_t a_n, k; + + p.x_start = qs; p.x_end = qe; p.y_start = ts; p.y_end = te; p.error = error; + p.extra_begin = aux_beg; p.extra_end = aux_end; + p.error_threshold = thres; p.cidx = p.clen = 0; + if(ol->w_list.n > 0) { //utilize the the end pos of pre-window in forward + w_e = ol->w_list.a[ol->w_list.n-1].x_end; + toff = ol->w_list.a[ol->w_list.n-1].y_end + 1 - ol->w_list.a[ol->w_list.n-1].extra_begin; + while ((w_e < ce) && (toff < tl)) { + w_s = w_e + 1; + get_win_id_by_s(ol, w_s, block_s, &w_e); + // x_start = w_s; x_end = w_e; + if(aln_wlst_adv(ol, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, + ol->y_pos_strand, ol->y_id, w_s, w_e, toff, block_s, e_rate, 0)) { + toff = ol->w_list.a[ol->w_list.n-1].y_end + 1 - ol->w_list.a[ol->w_list.n-1].extra_begin; + } else { + break; + } + } + cs = ol->w_list.a[ol->w_list.n-1].x_end + 1; + } + ///utilize the the start pos of next window in backward + a_n = ol->w_list.n; w_s = qs; + if(w_s > cs) { + gen_backtrace_adv(&p, ol, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, ol->y_pos_strand, ol->y_id); + p.y_end += p.extra_begin; + toff = p.y_start - 1; + while ((w_s > cs) && (toff > 0)) { + w_e = w_s - 1; + get_win_id_by_e(ol, w_e, block_s, &w_s); + // x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; + if(aln_wlst_adv(ol, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, + ol->y_pos_strand, ol->y_id, w_s, w_e, toff+1-(w_e+1-w_s), block_s, e_rate, 1)) { + ///y_start has no shift, but y_end has shift + ol->w_list.a[ol->w_list.n-1].y_start -= ol->w_list.a[ol->w_list.n-1].extra_begin; + toff = ol->w_list.a[ol->w_list.n-1].y_start - 1; + } else { + break; + } + } + } + + ol->align_length += qe + 1 - qs; + ovl = ol->x_pos_e+1-ol->x_pos_s; ualn = (qe + 1 - ol->x_pos_s) - ol->align_length; aln = ovl-ualn; + if((!simi_pass(ovl, aln, 0, ovlp_cut, &e_rate)) && (!simi_pass(ovl, aln, sec_check, ovlp_cut, NULL))) { + kv_push(window_list, ol->w_list, p); + return 0; + } + + if(ol->w_list.n > a_n) { + a = ol->w_list.a + a_n; a_n = ol->w_list.n - a_n; toff = a_n; a_n >>=1; + for (k = 0; k < a_n; k++) { + t = a[k]; a[k] = a[toff-1-k]; a[toff-1-k] = t; + } + } + kv_push(window_list, ol->w_list, p); + return 1; +} + +uint32_t align_ul_ed_post(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, char* qstr, char *tstr, char *tstr_1, +Correct_dumy* dumy, double e_rate, int64_t w_l, double ovlp_cut, void *km) +{ + int64_t q_s, q_e, nw, k, q_l, t_tot_l, sec_check = (uref&&(!hpc_g))?1:0; + int64_t aux_beg, aux_end, t_s, thre, aln_l, t_pri_l, t_end; + char *q_string, *t_string; unsigned int error; + z->w_list.n = 0; z->is_match = 0; z->align_length = 0; + nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, w_l); + get_win_se_by_normalize_xs(z, (z->x_pos_s/w_l)*w_l, w_l, &q_s, &q_e); + for (k = 0; k < nw; k++) { + aux_beg = aux_end = 0; q_l = 1 + q_e - q_s; + thre = q_l*e_rate; thre = Adjust_Threshold(thre, q_l); + if(thre > THRESHOLD_MAX_SIZE) thre = THRESHOLD_MAX_SIZE; + ///offset of y + t_s = (q_s - z->x_pos_s) + z->y_pos_s; + t_s += y_start_offset(q_s, &(z->f_cigar)); + + aln_l = q_l + (thre<<1); t_tot_l = hpc_g?hpc_len(*hpc_g, z->y_id):uref->ug->u.a[z->y_id].len; + if(init_waln(thre, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) { + q_string = qstr+q_s; + t_string = return_str_seq(tstr, t_s, t_pri_l, z->y_pos_strand, hpc_g, uref, z->y_id, aux_beg, aux_end); + + t_end = Reserve_Banded_BPM(t_string, aln_l, q_string, q_l, thre, &error); + // int32_t debug_t_end, debug_error; + // debug_t_end = ed_band_cal_semi(t_string, aln_l, q_string, q_l, thre, &debug_error); + // if((t_end != debug_t_end) || (t_end >= 0 && debug_t_end >= 0 && debug_error != (int32_t)error)) { + // fprintf(stderr, "[M::%s] debug_error->%d, error->%d\n", __func__, debug_error, error); + // } + + + if (error!=((unsigned int)-1)) { + ///t_s do not have aux_beg, while t_s + t_end (aka, te) has + if(!push_wlst(uref, hpc_g, NULL, z, qstr, tstr, tstr_1, dumy, q_s, q_e, t_s, t_s + t_end, + t_tot_l, error, aux_beg, aux_end, thre, e_rate, w_l, sec_check, ovlp_cut, km)) { + return 0; + } + // append_window_list(z, q_s, q_e, t_s, t_s + t_end, error, aux_beg, aux_end, thre, w_l, km); + } + } + q_s = q_e + 1; q_e = q_s + w_l - 1; + if(q_e >= (int64_t)z->x_pos_e) q_e = z->x_pos_e; + } + + if((!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, 0, ovlp_cut, &e_rate)) && + (!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, sec_check, ovlp_cut, NULL))) return 0; + return 1; +} + +void prt_cigar(uint16_t *ca, uint32_t cn) +{ + uint32_t k; + for (k = 0; k < cn; k++) { + fprintf(stderr, "%u%c", ca[k]&0x3fff, "EMDI"[ca[k]>>14]); + } + fprintf(stderr, "\n"); +} + +void prt_cigar_smp(uint16_t *ca, uint32_t cn) +{ + uint32_t k; + for (k = 0; k < cn; k++) { + fprintf(stderr, "%u%c", ca[k]&0x3fff, "MSID"[ca[k]>>14]); + } + fprintf(stderr, "\n"); +} + + +inline uint32_t gen_backtrace_adv_exz(window_list *p, overlap_region *z, All_reads *rref, hpc_t *hpc_g, const ul_idx_t *uref, +char *qstr, char *tstr, bit_extz_t *exz, uint32_t rev, uint32_t id) +{ + if(p->error < 0 || p->y_end < 0) return 0; + int64_t qs, qe, ql, tl, aln_l, t_pri_l, thres, ts, t_tot_l; + int64_t aux_beg, aux_end; + char *q_string, *t_string; + ///there is no problem for x + qs = p->x_start; qe = p->x_end; ql = qe + 1 - qs; + thres = p->error_threshold; aln_l = ql + (thres<<1); + + ///y_start is the real y_start + ///for the window with cigar, y_start has already reduced extra_begin + ts = p->y_start; aux_beg = p->extra_begin; aux_end = p->extra_end; + if(aux_end >= 0) { + t_pri_l = aln_l - aux_beg - aux_end; + } else { + if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); + else if(uref) t_tot_l = uref->ug->u.a[id].len; + else t_tot_l = Get_READ_LENGTH((*rref), id); + + t_pri_l = ts + aln_l - aux_beg; if(t_pri_l > t_tot_l) t_pri_l = t_tot_l; + t_pri_l = t_pri_l - ts; + } + + q_string = qstr + qs; tl = t_pri_l; + if(rref) { + recover_UC_Read_sub_region(tstr, ts, t_pri_l, rev, rref, id); t_string = tstr; + } else { + t_string = return_str_seq_exz(tstr, ts, t_pri_l, rev, hpc_g, uref, id); + } + + exz->ts = 0; exz->te = p->x_end-p->x_start; exz->tl = ql; + exz->ps = -1; exz->pe = p->y_end-p->y_start; exz->pl = tl; + exz->err = p->error; exz->thre = p->error_threshold; + // clear_align(*exz); + ed_band_cal_semi_64_w_absent_diag_trace(t_string, tl, q_string, ql, thres, aux_beg, exz); + // if(id == 178 && p->x_start == 86800 && p->x_end == 86807) { + // fprintf(stderr, "\n[M::%s::semi] exz->ps::%d, exz->pe::%d, exz->ts::%d, exz->te::%d, exz->err::%d, exz->cigar.n::%d\n", + // __func__, exz->ps, exz->pe, exz->ts, exz->te, exz->err, (int32_t)exz->cigar.n); + // fprintf(stderr, "[M::%s::semi] p->y_start::%d, p->y_end::%d, p->x_start::%d, p->x_end::%d, p->error::%d\n", + // __func__, p->y_start, p->y_end, p->x_start, p->x_end, p->error); + // if(is_align(*exz)) { + // prt_cigar(exz->cigar.a, exz->cigar.n); + // fprintf(stderr, "[tstr] %.*s\n", exz->pe+1-exz->ps, t_string+exz->ps); + // fprintf(stderr, "[qstr] %.*s\n", exz->te+1-exz->ts, q_string+exz->ts); + // } + // } + // assert(is_align(*exz)); + // assert(cigar_check(t_string, q_string, exz)); + + + if(is_align(*exz)) { + p->y_start = ts + exz->ps;///difference + p->y_end = ts + exz->pe; + p->error = exz->err; + push_wcigar(p, &(z->w_list), exz); + ///this condition is always wrong + ///in best case, r_ts = threshold, t_end = aln_l - thres - 1 + if ((((exz->pe+1) == tl) || (exz->ps == 0)) && (exz->err > 0)) { + if(recal_boundary_exz(q_string, tstr, ql, tl, thres, ts, exz->ps, exz->pe, + exz->err, id, rev, exz, rref, hpc_g, uref, &ts, &aux_beg, &aux_end)) { + //update cigar + z->w_list.c.n = p->cidx; push_wcigar(p, &(z->w_list), exz); + + p->y_start = ts + exz->ps;///difference + p->y_end = ts + exz->pe; + p->error = exz->err; + } + } + p->extra_begin = aux_beg; + p->extra_end = aux_end; + return 1; + } + p->error = -1; + return 0; +} + +inline uint32_t gen_backtrace_non_retrieve_adv_exz(window_list *p, overlap_region *z, char *qstr, char *tstr, int64_t t_tot_l, bit_extz_t *exz, uint32_t rev, uint32_t id) +{ + if(p->error < 0 || p->y_end < 0) return 0; + int64_t qs, qe, ql, tl, aln_l, t_pri_l, thres, ts; + int64_t aux_beg, aux_end; + char *q_string, *t_string; + ///there is no problem for x + qs = p->x_start; qe = p->x_end; ql = qe + 1 - qs; + thres = p->error_threshold; aln_l = ql + (thres<<1); + + ///y_start is the real y_start + ///for the window with cigar, y_start has already reduced extra_begin + ts = p->y_start; aux_beg = p->extra_begin; aux_end = p->extra_end; + if(aux_end >= 0) { + t_pri_l = aln_l - aux_beg - aux_end; + } else { + t_pri_l = ts + aln_l - aux_beg; if(t_pri_l > t_tot_l) t_pri_l = t_tot_l; + t_pri_l = t_pri_l - ts; + } + + q_string = qstr + qs; t_string = tstr + ts; tl = t_pri_l; + + exz->ts = 0; exz->te = p->x_end-p->x_start; exz->tl = ql; + exz->ps = -1; exz->pe = p->y_end-p->y_start; exz->pl = tl; + exz->err = p->error; exz->thre = p->error_threshold; + // clear_align(*exz); + ed_band_cal_semi_64_w_absent_diag_trace(t_string, tl, q_string, ql, thres, aux_beg, exz); + // if(id == 178 && p->x_start == 86800 && p->x_end == 86807) { + // fprintf(stderr, "\n[M::%s::semi] exz->ps::%d, exz->pe::%d, exz->ts::%d, exz->te::%d, exz->err::%d, exz->cigar.n::%d\n", + // __func__, exz->ps, exz->pe, exz->ts, exz->te, exz->err, (int32_t)exz->cigar.n); + // fprintf(stderr, "[M::%s::semi] p->y_start::%d, p->y_end::%d, p->x_start::%d, p->x_end::%d, p->error::%d\n", + // __func__, p->y_start, p->y_end, p->x_start, p->x_end, p->error); + // if(is_align(*exz)) { + // prt_cigar(exz->cigar.a, exz->cigar.n); + // fprintf(stderr, "[tstr] %.*s\n", exz->pe+1-exz->ps, t_string+exz->ps); + // fprintf(stderr, "[qstr] %.*s\n", exz->te+1-exz->ts, q_string+exz->ts); + // } + // } + // assert(is_align(*exz)); + // assert(cigar_check(t_string, q_string, exz)); + + + if(is_align(*exz)) { + p->y_start = ts + exz->ps;///difference + p->y_end = ts + exz->pe; + p->error = exz->err; + push_wcigar(p, &(z->w_list), exz); + ///this condition is always wrong + ///in best case, r_ts = threshold, t_end = aln_l - thres - 1 + if ((((exz->pe+1) == tl) || (exz->ps == 0)) && (exz->err > 0)) { + if(recal_boundary_non_retrieve_exz(q_string, tstr, t_tot_l, ql, tl, thres, ts, exz->ps, exz->pe, + exz->err, id, rev, exz, &ts, &aux_beg, &aux_end)) { + //update cigar + z->w_list.c.n = p->cidx; push_wcigar(p, &(z->w_list), exz); + + p->y_start = ts + exz->ps;///difference + p->y_end = ts + exz->pe; + p->error = exz->err; + } + } + p->extra_begin = aux_beg; + p->extra_end = aux_end; + return 1; + } + p->error = -1; + return 0; +} + + +///ts do not have aux_beg, while te has +uint32_t push_wlst_exz(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, overlap_region* ol, + char* qstr, char *tstr, bit_extz_t *exz, uint32_t max_err, + int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t tl, + int64_t aux_beg, int64_t aux_end, double e_rate, int64_t block_s, uint32_t sec_check, double ovlp_cut, int64_t force_aln, void *km) +{ + + window_list p, t, *a; int64_t w_e, w_s, ce = qs - 1, cs = ol->x_pos_s, toff, ovl, ualn, aln, ys; + uint64_t a_n, k; + + p.x_start = qs; p.x_end = qe; p.y_start = ts; p.y_end = te; p.error = exz->err; + p.extra_begin = aux_beg; p.extra_end = aux_end; p.error_threshold = exz->thre; p.cidx = p.clen = 0; + if(ol->w_list.n > 0) { //utilize the the end pos of pre-window in forward + w_e = ol->w_list.a[ol->w_list.n-1].x_end; + toff = ol->w_list.a[ol->w_list.n-1].y_end + 1; + while ((w_e < ce) && (toff < tl)) { + w_s = w_e + 1; + get_win_id_by_s(ol, w_s, block_s, &w_e); + // x_start = w_s; x_end = w_e; + if(aln_wlst_adv_exz(ol, rref, hpc_g, uref, qstr, tstr, exz, max_err, + ol->y_pos_strand, ol->y_id, w_s, w_e, toff, block_s, e_rate, 0)) { + toff = ol->w_list.a[ol->w_list.n-1].y_end + 1; + } else { + break; + } + } + cs = ol->w_list.a[ol->w_list.n-1].x_end + 1; + } + ///utilize the the start pos of next window in backward + a_n = ol->w_list.n; w_s = qs; + if(w_s > cs) { + gen_backtrace_adv_exz(&p, ol, rref, hpc_g, uref, qstr, tstr, exz, ol->y_pos_strand, ol->y_id); + toff = p.y_start - 1; + while (w_s > cs) { + w_e = w_s - 1; + get_win_id_by_e(ol, w_e, block_s, &w_s); ys = toff+1-(w_e+1-w_s); + // x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; + if((ys >= 0) && aln_wlst_adv_exz(ol, rref, hpc_g, uref, qstr, tstr, exz, max_err, + ol->y_pos_strand, ol->y_id, w_s, w_e, ys, block_s, e_rate, 1)) { + toff = ol->w_list.a[ol->w_list.n-1].y_start - 1; + } else { + break; + } + } + } + + ol->align_length += qe + 1 - qs; + ovl = ol->x_pos_e+1-ol->x_pos_s; ualn = (qe + 1 - ol->x_pos_s) - ol->align_length; aln = ovl-ualn; + if((!force_aln) && (!simi_pass(ovl, aln, 0, ovlp_cut, &e_rate)) && (!simi_pass(ovl, aln, sec_check, ovlp_cut, NULL))) { + kv_push(window_list, ol->w_list, p); + return 0; + } + + if(ol->w_list.n > a_n) { + a = ol->w_list.a + a_n; a_n = ol->w_list.n - a_n; toff = a_n; a_n >>=1; + for (k = 0; k < a_n; k++) { + t = a[k]; a[k] = a[toff-1-k]; a[toff-1-k] = t; + } + } + kv_push(window_list, ol->w_list, p); + return 1; +} + +#define pass_qovlp(o, a, r) (((a)>0)&&((o)*(r)<=(a))) + +///ts do not have aux_beg, while te has +uint32_t push_hc_wlst_exz(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, overlap_region* ol, + char* qstr, char *tstr, bit_extz_t *exz, uint32_t max_err, + int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t tl, + int64_t aux_beg, int64_t aux_end, double e_rate, int64_t block_s, double ovlp_cut, int64_t force_aln, uint64_t *tot_b, uint8_t is_srt) +{ + + window_list p, t, *a; int64_t w_e, w_s, ce = qs - 1, cs = ol->x_pos_s, toff, ovl, ualn, aln, ys; + uint64_t a_n, k; uint8_t rf = 1; + p.x_start = qs; p.x_end = qe; p.y_start = ts; p.y_end = te; p.error = exz->err; + p.extra_begin = aux_beg; p.extra_end = aux_end; p.error_threshold = exz->thre; p.cidx = p.clen = 0; + if(ol->w_list.n > 0) { //utilize the the end pos of pre-window in forward + w_e = ol->w_list.a[ol->w_list.n-1].x_end; + toff = ol->w_list.a[ol->w_list.n-1].y_end + 1; + while ((w_e < ce) && (toff < tl)) { + w_s = w_e + 1; + get_win_id_by_s(ol, w_s, block_s, &w_e); + // x_start = w_s; x_end = w_e; + if(aln_wlst_adv_exz(ol, rref, hpc_g, uref, qstr, tstr, exz, max_err, + ol->y_pos_strand, ol->y_id, w_s, w_e, toff, block_s, e_rate, 0)) { + // if(ol->y_id == 3621213) { + // fprintf(stderr, "-a-[M::%s]\ttid::%u\twq::[%ld,%ld)\n", __func__, ol->y_id, w_s, w_e + 1); + // } + toff = ol->w_list.a[ol->w_list.n-1].y_end + 1; + if(tot_b) (*tot_b) += w_e + 1 - w_s; + } else { + break; + } + } + cs = ol->w_list.a[ol->w_list.n-1].x_end + 1; + } + ///utilize the the start pos of next window in backward + a_n = ol->w_list.n; w_s = qs; + if(w_s > cs) { + gen_backtrace_adv_exz(&p, ol, rref, hpc_g, uref, qstr, tstr, exz, ol->y_pos_strand, ol->y_id); + toff = p.y_start - 1; + while (w_s > cs) { + w_e = w_s - 1; + get_win_id_by_e(ol, w_e, block_s, &w_s); ys = toff+1-(w_e+1-w_s); + // x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; + if((ys >= 0) && aln_wlst_adv_exz(ol, rref, hpc_g, uref, qstr, tstr, exz, max_err, + ol->y_pos_strand, ol->y_id, w_s, w_e, ys, block_s, e_rate, 1)) { + // if(ol->y_id == 3621213) { + // fprintf(stderr, "-b-[M::%s]\ttid::%u\twq::[%ld,%ld)\n", __func__, ol->y_id, w_s, w_e + 1); + // } + toff = ol->w_list.a[ol->w_list.n-1].y_start - 1; + if(tot_b) (*tot_b) += w_e + 1 - w_s; + } else { + break; + } + } + } + + ol->align_length += qe + 1 - qs; + ovl = ol->x_pos_e+1-ol->x_pos_s; ualn = (qe + 1 - ol->x_pos_s) - ol->align_length; aln = ovl-ualn; + // if((!force_aln) && (!simi_pass(ovl, aln, 0, ovlp_cut, &e_rate)) && (!simi_pass(ovl, aln, sec_check, ovlp_cut, NULL))) { + if((!force_aln) && (!pass_qovlp(ovl, aln, ovlp_cut))) { + rf = 0; + if(!is_srt) { + kv_push(window_list, ol->w_list, p); + return 0; + } + } + + if(ol->w_list.n > a_n) { + a = ol->w_list.a + a_n; a_n = ol->w_list.n - a_n; toff = a_n; a_n >>=1; + for (k = 0; k < a_n; k++) { + t = a[k]; a[k] = a[toff-1-k]; a[toff-1-k] = t; + } + } + kv_push(window_list, ol->w_list, p); + // return 1; + return rf; +} + +uint32_t jp_cc_hit(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, overlap_region* ol, + char* qstr, char *tstr, bit_extz_t *exz, uint32_t max_err, + int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t tl, + int64_t aux_beg, int64_t aux_end, double e_rate, int64_t block_s, double ovlp_cut, int64_t force_aln, uint64_t *tot_b) +{ + return 1; +} + + +///ts do not have aux_beg, while te has +uint32_t push_hc_wlst_non_retrieve_exz(overlap_region* ol, char* qa, int64_t ql, char *ta, int64_t tl, bit_extz_t *exz, uint32_t max_err, + int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t aux_beg, int64_t aux_end, double e_rate, int64_t block_s, double ovlp_cut, int64_t force_aln, void *km) +{ + + window_list p, t, *a; int64_t w_e, w_s, ce = qs - 1, cs = ol->x_pos_s, toff, ovl, ualn, aln, ys; + uint64_t a_n, k; + p.x_start = qs; p.x_end = qe; p.y_start = ts; p.y_end = te; p.error = exz->err; + p.extra_begin = aux_beg; p.extra_end = aux_end; p.error_threshold = exz->thre; p.cidx = p.clen = 0; + if(ol->w_list.n > 0) { //utilize the the end pos of pre-window in forward + w_e = ol->w_list.a[ol->w_list.n-1].x_end; + toff = ol->w_list.a[ol->w_list.n-1].y_end + 1; + while ((w_e < ce) && (toff < tl)) { + w_s = w_e + 1; + get_win_id_by_s(ol, w_s, block_s, &w_e); + // x_start = w_s; x_end = w_e; + if(aln_wlst_adv_non_retrieve_exz(ol, qa, ta, tl, exz, max_err, + ol->y_pos_strand, ol->y_id, w_s, w_e, toff, block_s, e_rate, 0)) { + toff = ol->w_list.a[ol->w_list.n-1].y_end + 1; + } else { + break; + } + } + cs = ol->w_list.a[ol->w_list.n-1].x_end + 1; + } + ///utilize the the start pos of next window in backward + a_n = ol->w_list.n; w_s = qs; + if(w_s > cs) { + gen_backtrace_non_retrieve_adv_exz(&p, ol, qa, ta, tl, exz, ol->y_pos_strand, ol->y_id); + toff = p.y_start - 1; + while (w_s > cs) { + w_e = w_s - 1; + get_win_id_by_e(ol, w_e, block_s, &w_s); ys = toff+1-(w_e+1-w_s); + // x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; + if((ys >= 0) && aln_wlst_adv_non_retrieve_exz(ol, qa, ta, tl, exz, max_err, + ol->y_pos_strand, ol->y_id, w_s, w_e, ys, block_s, e_rate, 1)) { + toff = ol->w_list.a[ol->w_list.n-1].y_start - 1; + } else { + break; + } + } + } + + ol->align_length += qe + 1 - qs; + ovl = ol->x_pos_e+1-ol->x_pos_s; ualn = (qe + 1 - ol->x_pos_s) - ol->align_length; aln = ovl-ualn; + // if((!force_aln) && (!simi_pass(ovl, aln, 0, ovlp_cut, &e_rate)) && (!simi_pass(ovl, aln, sec_check, ovlp_cut, NULL))) { + if((!force_aln) && (!pass_qovlp(ovl, aln, ovlp_cut))) { + kv_push(window_list, ol->w_list, p); + return 0; + } + + if(ol->w_list.n > a_n) { + a = ol->w_list.a + a_n; a_n = ol->w_list.n - a_n; toff = a_n; a_n >>=1; + for (k = 0; k < a_n; k++) { + t = a[k]; a[k] = a[toff-1-k]; a[toff-1-k] = t; + } + } + kv_push(window_list, ol->w_list, p); + return 1; +} + +uint32_t align_ul_ed_post_extz(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, char* qstr, char *tstr, bit_extz_t *exz, double e_rate, int64_t w_l, double ovlp_cut, int64_t force_aln, void *km) +{ + int64_t q_s, q_e, nw, k, q_l, t_l, t_tot_l, sec_check = (uref&&(!hpc_g))?1:0; + int64_t aux_beg, aux_end, t_s, thre, aln_l, t_pri_l; + char *q_string, *t_string; + z->w_list.n = 0; z->is_match = 0; z->align_length = 0; + nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, w_l); + get_win_se_by_normalize_xs(z, (z->x_pos_s/w_l)*w_l, w_l, &q_s, &q_e); + for (k = 0; k < nw; k++) { + aux_beg = aux_end = 0; q_l = 1 + q_e - q_s; + thre = q_l*e_rate; thre = Adjust_Threshold(thre, q_l); + if(thre > THRESHOLD_MAX_SIZE) thre = THRESHOLD_MAX_SIZE; + ///offset of y + t_s = (q_s - z->x_pos_s) + z->y_pos_s; + t_s += y_start_offset(q_s, &(z->f_cigar)); + + aln_l = q_l + (thre<<1); t_tot_l = hpc_g?hpc_len(*hpc_g, z->y_id):uref->ug->u.a[z->y_id].len; + if(init_waln(thre, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) { + q_string = qstr+q_s; + t_string = return_str_seq_exz(tstr, t_s, t_pri_l, z->y_pos_strand, hpc_g, uref, z->y_id); + t_l = t_pri_l; + // t_end = Reserve_Banded_BPM(t_string, aln_l, q_string, q_l, thre, &error); + ed_band_cal_semi_64_w_absent_diag(t_string, t_l, q_string, q_l, thre, aux_beg, exz); + // if(z->y_id == 178 && q_s == 86800 && q_e == 86807) { + // fprintf(stderr, "\n[M::%s::semi::t_s->%ld::t_pri_l->%ld::aux_beg->%ld::aux_end->%ld::thre->%ld] exz->ps::%d, exz->pe::%d, exz->ts::%d, exz->te::%d, exz->err::%d, exz->cigar.n::%d\n", + // __func__, t_s, t_pri_l, aux_beg, aux_end, thre, exz->ps, exz->pe, exz->ts, exz->te, exz->err, (int32_t)exz->cigar.n); + // fprintf(stderr, "[tstr::len->%ld] %.*s\n", t_l, (int32_t)t_l, t_string); + // fprintf(stderr, "[qstr::len->%ld] %.*s\n", q_l, (int32_t)q_l, q_string); + // } + if (is_align(*exz)) { + // ed_band_cal_semi_64_w(t_string, aln_l, q_string, q_l, thre, exz); + // assert(exz->err <= exz->thre); + // fprintf(stderr, "[M::%s] exz->err::%d\n", __func__, exz->err); + ///t_s do not have aux_beg, while t_s + t_end (aka, te) has + if(!push_wlst_exz(uref, hpc_g, NULL, z, qstr, tstr, exz, THRESHOLD_MAX_SIZE, q_s, q_e, t_s, t_s + exz->pe, + t_tot_l, aux_beg, aux_end, e_rate, w_l, sec_check, ovlp_cut, force_aln, km)) { + return 0; + } + // append_window_list(z, q_s, q_e, t_s, t_s + t_end, error, aux_beg, aux_end, thre, w_l, km); + } + } + q_s = q_e + 1; q_e = q_s + w_l - 1; + if(q_e >= (int64_t)z->x_pos_e) q_e = z->x_pos_e; + } + + if((!force_aln) && (!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, 0, ovlp_cut, &e_rate)) && + (!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, sec_check, ovlp_cut, NULL))) return 0; + return 1; +} + + +uint32_t align_hc_ed_post_extz(overlap_region *z, All_reads *rref, char* qstr, char *tstr, bit_extz_t *exz, double e_rate, int64_t w_l, double ovlp_cut, int64_t force_aln, uint64_t *tot_b) +{ + int64_t q_s, q_e, nw, k, q_l, t_l, t_tot_l, aux_beg, aux_end, t_s, thre, aln_l, t_pri_l; + char *q_string, *t_string; + z->w_list.n = 0; z->is_match = 0; z->align_length = 0; + nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, w_l); + get_win_se_by_normalize_xs(z, (z->x_pos_s/w_l)*w_l, w_l, &q_s, &q_e); + // if(z->x_id == 19350 && z->y_id == 19324) { + // fprintf(stderr, "-z-[M::%s] tid::%u(%c)\tq::[%u,%u)\tt::[%u,%u)\n", __func__, z->y_id, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1); + // } + // if(z->y_id == 234) { + // fprintf(stderr, "-a-[M::%s] tid::%u(%c)\tq::[%u,%u)\tt::[%u,%u)\n", __func__, z->y_id, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1); + // } + + for (k = 0; k < nw; k++) { + aux_beg = aux_end = 0; q_l = 1 + q_e - q_s; + thre = q_l*e_rate; thre = Adjust_Threshold(thre, q_l); + if(thre > THRESHOLD_MAX_SIZE) thre = THRESHOLD_MAX_SIZE; + ///offset of y + t_s = (q_s - z->x_pos_s) + z->y_pos_s; + // if(z->y_id == 234) { + // fprintf(stderr, "-1-[M::%s] tid::%u\tk::%ld\tnw::%ld\tq_s::%ld\n", __func__, z->y_id, k, nw, q_s); + // } + t_s += y_start_offset(q_s, &(z->f_cigar)); + // if(z->y_id == 234) { + // fprintf(stderr, "-2-[M::%s] tid::%u\tk::%ld\tnw::%ld\tq_s::%ld\n", __func__, z->y_id, k, nw, q_s); + // } + + aln_l = q_l + (thre<<1); t_tot_l = Get_READ_LENGTH((*rref), z->y_id); + if(init_waln(thre, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) { + q_string = qstr+q_s; + recover_UC_Read_sub_region(tstr, t_s, t_pri_l, z->y_pos_strand, rref, z->y_id); t_string = tstr; + // t_string = return_str_seq_exz(tstr, t_s, t_pri_l, z->y_pos_strand, hpc_g, uref, z->y_id); + + t_l = t_pri_l; + // t_end = Reserve_Banded_BPM(t_string, aln_l, q_string, q_l, thre, &error); + ed_band_cal_semi_64_w_absent_diag(t_string, t_l, q_string, q_l, thre, aux_beg, exz); + + if(tot_b) (*tot_b) += q_l; + + // if(z->x_id == 5569 && z->y_id == 5557 && q_s == 10075 && q_e == 10849) { + // fprintf(stderr, "\n[M::%s::semi::t_s->%ld::t_pri_l->%ld::aux_beg->%ld::aux_end->%ld::thre->%ld] exz->ps::%d, exz->pe::%d, exz->ts::%d, exz->te::%d, exz->err::%d, exz->cigar.n::%d, thre::%ld\n", + // __func__, t_s, t_pri_l, aux_beg, aux_end, thre, exz->ps, exz->pe, exz->ts, exz->te, exz->err, (int32_t)exz->cigar.n, thre); + // fprintf(stderr, "[tstr::len->%ld] %.*s\n", t_l, (int32_t)t_l, t_string); + // fprintf(stderr, "[qstr::len->%ld] %.*s\n", q_l, (int32_t)q_l, q_string); + // } + if (is_align(*exz)) { + // ed_band_cal_semi_64_w(t_string, aln_l, q_string, q_l, thre, exz); + // assert(exz->err <= exz->thre); + // if(z->x_id == 19350 && z->y_id == 19324) { + // fprintf(stderr, "+[M::%s]\tq::[%ld,%ld)\tt::[%ld,%ld)\texz->err::%d\n", __func__, q_s, q_e + 1, t_s, t_s + exz->pe + 1, exz->err); + // } + ///t_s do not have aux_beg, while t_s + t_end (aka, te) has + if(!push_hc_wlst_exz(NULL, NULL, rref, z, qstr, tstr, exz, THRESHOLD_MAX_SIZE, q_s, q_e, t_s, t_s + exz->pe, + t_tot_l, aux_beg, aux_end, e_rate, w_l, ovlp_cut, force_aln, tot_b, 0)) { + // if(z->y_id == 234) fprintf(stderr, "-b-[M::%s] tid::%u(%c)\tq::[%u,%u)\tt::[%u,%u)\n", __func__, z->y_id, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1); + return 0; + } + // append_window_list(z, q_s, q_e, t_s, t_s + t_end, error, aux_beg, aux_end, thre, w_l, km); + } + // else { + // if(z->x_id == 19350 && z->y_id == 19324) { + // fprintf(stderr, "-[M::%s]\tq::[%ld,%ld)\tt::[%ld,%ld)\texz->err::%d\n", __func__, q_s, q_e + 1, t_s, t_s + exz->pe + 1, exz->err); + // } + // } + } + q_s = q_e + 1; q_e = q_s + w_l - 1; + if(q_e >= (int64_t)z->x_pos_e) q_e = z->x_pos_e; + } + + // if((!force_aln) && (!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, 0, ovlp_cut, &e_rate)) && + // (!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, sec_check, ovlp_cut, NULL))) return 0; + // if(z->y_id == 234) fprintf(stderr, "-c-[M::%s] tid::%u(%c)\tq::[%u,%u)\tt::[%u,%u)\n", __func__, z->y_id, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1); + if((!force_aln) && (!pass_qovlp(z->x_pos_e+1-z->x_pos_s, z->align_length, ovlp_cut))) return 0; + return 1; +} + +uint32_t align_hc_ed_post_extz_cut(overlap_region *z, overlap_region *zr, /**overlap_region *zuf,**/ All_reads *rref, char* qstr, char *tstr, bit_extz_t *exz, double e_rate, int64_t w_l, double ovlp_cut, int64_t force_aln, uint32_t *e_win, double nhit_cut, uint64_t *tot_b) +{ + int64_t q_s, q_e, nw, k, kr = 0, nr = 0, /**nuf = 0, fqs = -1, fqe = -1,**/ q_l, t_l, t_tot_l, aux_beg, aux_end, t_s, thre, aln_l, t_pri_l, zol = z->x_pos_e+1-z->x_pos_s, zal, rual = 0; + char *q_string, *t_string; window_list *p = NULL; if(e_win) *e_win = z->x_pos_e + 1; + z->w_list.n = 0; z->is_match = 0; z->align_length = 0; + nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, w_l); + get_win_se_by_normalize_xs(z, (z->x_pos_s/w_l)*w_l, w_l, &q_s, &q_e); + if(zr) { + nr = zr->w_list.n; kr = 0; + rual = ((zr->overlapLen > zr->align_length)?(zr->overlapLen-zr->align_length):(0)); + // if(z->y_id == 3621881) { + // fprintf(stderr, "+zr[M::%s::]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\trual::%ld\tnr::%ld\n", __func__, + // zr->y_id, (int)Get_NAME_LENGTH(R_INF, zr->y_id), Get_NAME(R_INF, zr->y_id), + // zr->x_pos_s, zr->x_pos_e + 1, zr->y_pos_s, zr->y_pos_e + 1, rual, nr); + // for (; kr < nr; kr++) { + // fprintf(stderr, "+zr[M::%s::]\terr::%d\tthre::%d\tq::[%d,%d)\n", __func__, + // zr->w_list.a[kr].error, zr->w_list.a[kr].error_threshold, zr->w_list.a[kr].x_start, zr->w_list.a[kr].x_end + 1); + + // } + // kr = 0; + // } + } + /** + if(zuf && zuf->w_list.n) { + nuf = zuf->w_list.n; + fqs = zuf->w_list.a[nuf-1].x_start; + fqe = zuf->w_list.a[nuf-1].x_end; + } + **/ + + // if(z->y_id == 3621141) { + // fprintf(stderr, "-a-[M::%s]\ttid::%u\t%.*s\tq::[%u,%u)\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), z->x_pos_s, z->x_pos_e + 1); + // } + + for (k = 0; k < nw; k++) { + aux_beg = aux_end = 0; q_l = 1 + q_e - q_s; + thre = q_l*e_rate; thre = Adjust_Threshold(thre, q_l); + if(thre > THRESHOLD_MAX_SIZE) thre = THRESHOLD_MAX_SIZE; + aln_l = q_l + (thre<<1); t_tot_l = Get_READ_LENGTH((*rref), z->y_id); + + p = NULL; + if(zr) { + for (; kr < nr && zr->w_list.a[kr].x_start < q_s; kr++); + if((kr < nr) && (zr->w_list.a[kr].x_start == q_s)) p = &(zr->w_list.a[kr]); + } + + exz->err = INT32_MAX; exz->thre = -1;///init exz + if(p) { + // if(z->y_id == 3620095 || z->y_id == 3624181) { + // fprintf(stderr, "-p[M::%s::]\ttid::%u\terr::%d\tthre::%d\tp_q::[%d,%d)\tz_q::[%ld,%ld)\n", __func__, + // z->y_id, p->error, p->error_threshold, p->x_start, p->x_end + 1, q_s, q_e + 1); + // } + t_s = p->y_start; thre = p->error_threshold; + aux_beg = p->extra_begin; + aux_end = p->extra_end; + + exz->thre = thre; exz->err = INT32_MAX; + exz->pl = INT32_MAX; exz->tl = q_l; + exz->done_cigar = exz->done_path = exz->cigar_n = exz->path_n = 0; + exz->ps = exz->pe = -1; exz->ts = 0; exz->te = q_l-1; + + if(p->error <= p->error_threshold) { + exz->pe = p->y_end - p->y_start; exz->err = p->error; + } else { + // if(!(rual >= q_l)) { + // fprintf(stderr, "[M::%s::]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\trual::%ld\tq_l::%ld\tw::[%ld,%ld]\n", __func__, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, rual, q_l, q_s, q_e); + // } + assert(rual >= q_l); + rual -= q_l; + } + } else { + ///offset of y + t_s = (q_s - z->x_pos_s) + z->y_pos_s; + t_s += y_start_offset(q_s, &(z->f_cigar)); + + if(init_waln(thre, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) { + q_string = qstr+q_s; + recover_UC_Read_sub_region(tstr, t_s, t_pri_l, z->y_pos_strand, rref, z->y_id); t_string = tstr; + + t_l = t_pri_l; + ed_band_cal_semi_64_w_absent_diag(t_string, t_l, q_string, q_l, thre, aux_beg, exz); + (*tot_b) += q_l; + } + } + + // if(z->y_id == 3620095 || z->y_id == 3624181) { + // fprintf(stderr, "[M::%s::]\ttid::%u\terr::%d\tthre::%d\tz_q::[%ld,%ld)\n", __func__, z->y_id, exz->err, exz->thre, q_s, q_e + 1); + // } + // if(z->y_id == 3621141) { + // if(is_align(*exz)) { + // fprintf(stderr, "-b-[M::%s]\ttid::%u\t%.*s\tq::[%ld,%ld)\taln::%u\tqe::%ld\tte::%ld\terr::%d\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), q_s, q_e + 1, is_align(*exz)?1:0, + // q_e + 1, t_s + exz->pe + 1, exz->err); + // } else { + // fprintf(stderr, "-b-[M::%s]\ttid::%u\t%.*s\tq::[%ld,%ld)\taln::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), q_s, q_e + 1, is_align(*exz)?1:0); + // } + // } + + if(is_align(*exz)) { + ///t_s do not have aux_beg, while t_s + t_end (aka, te) has + if(!push_hc_wlst_exz(NULL, NULL, rref, z, qstr, tstr, exz, THRESHOLD_MAX_SIZE, q_s, q_e, t_s, t_s + exz->pe, + t_tot_l, aux_beg, aux_end, e_rate, w_l, ovlp_cut, force_aln, tot_b, 1)) { + if(e_win) *e_win = q_e + 1; + return 0; + } + } /**else if((!p) && (nuf) && (q_e > fqe)) {///just append; do not change existing unmatched windows + p = &(zuf->w_list.a[zuf->w_list.n-1]); + if(q_e > p->x_end) { + if(q_s <= p->x_end + 1) {///because [os, oe] and [p->x_start, p->x_end] + p->x_end = q_e; ///no need to update x_x_start as this is window-based + } else { + kv_pushp(window_list, zuf->w_list, &p); + p->x_start = q_s; p->x_end = q_e; + p->y_start = p->y_end = -1; + p->error_threshold = -1; p->error = INT16_MAX; + p->extra_begin = p->extra_end = -1; + p->cidx = p->clen = 0; + } + } + } + **/ + + if(nhit_cut > 0) { + zal = z->align_length + z->x_pos_e - q_e - rual; + if((!force_aln) && (!pass_qovlp(zol, zal, nhit_cut))) { + if(e_win) *e_win = q_e + 1; + // jp_cc_hit(); + return 0; + } + } + + + q_s = q_e + 1; q_e = q_s + w_l - 1; + if(q_e >= (int64_t)z->x_pos_e) q_e = z->x_pos_e; + } + + if((!force_aln) && (!pass_qovlp(z->x_pos_e+1-z->x_pos_s, z->align_length, ovlp_cut))) return 0; + + /** + if(zuf && zuf->w_list.n) {///reset if match + zuf->w_list.n = nuf; + zuf->w_list.a[nuf-1].x_start = fqs; + zuf->w_list.a[nuf-1].x_end = fqe; + } + **/ + return 1; +} + + +uint32_t align_hc_ed_post_extz_cut_check(overlap_region *z, Fake_Cigar* zf, overlap_region *msk, All_reads *rref, char* qstr, char *tstr, bit_extz_t *exz, double e_rate, int64_t w_l, double ovlp_cut, uint64_t *tot_b) +{ + int64_t q_s, q_e, r_s, r_e, z_s, z_e, os, oe, nwr, kr, q_l, t_l, t_tot_l, aux_beg, aux_end, t_s, thre, aln_l, t_pri_l, zol = z->x_pos_e+1-z->x_pos_s, zcut, zual; + char *q_string, *t_string; window_list *p = NULL; + z->w_list.n = 0; z->is_match = 0; z->align_length = z->overlapLen = 0; + if(msk->w_list.n == 0) return 1;///ok, worth for in-depth cal + nwr = msk->w_list.n; + + // if(z->y_id == 3621213) { + // fprintf(stderr, "-a-[M::%s]\ttid::%u\t%.*s\tq::[%u,%u)\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), z->x_pos_s, z->x_pos_e + 1); + // for (kr = 0; kr < nwr; kr++) { + // fprintf(stderr, "-b-[M::%s]\ttid::%u\t%.*s\tmsk::[%d,%d)\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), msk->w_list.a[kr].x_start, msk->w_list.a[kr].x_end + 1); + // } + // } + + q_s = z->x_pos_s; q_e = z->x_pos_e + 1; + for (kr = 0; kr < nwr; kr++) { + r_s = msk->w_list.a[kr].x_start; + r_e = msk->w_list.a[kr].x_end + 1; + + os = MAX(q_s, r_s); oe = MIN(q_e, r_e); + if(oe > os) break; + } + + if(kr >= nwr) return 1;///ok, worth for in-depth cal + + z_s = z->x_pos_s; z_e = z->x_pos_e + 1; + ///(os >= z->x_pos_s) && (os <= z->x_pos_e) + q_s = (os/w_l)*w_l; + if(q_s < z_s) q_s = z_s; + get_win_id_by_s(z, q_s, w_l, &q_e); q_e++; + zcut = zol * ovlp_cut; zcut = zol - zcut; zual = 0; + + while ((q_s < z_e) && (kr < nwr)) { + for (; kr < nwr; kr++) { + r_s = msk->w_list.a[kr].x_start; + r_e = msk->w_list.a[kr].x_end + 1; + if(r_s >= q_e) break; + os = MAX(q_s, r_s); oe = MIN(q_e, r_e); + // if(z->y_id == 3621213) { + // fprintf(stderr, "-c-[M::%s]\ttid::%u\t%.*s\tq::[%ld,%ld)\tr::[%ld,%ld)\to::[%ld,%ld)\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), q_s, q_e, r_s, r_e, os, oe); + // } + if(oe > os) {///base-level + + aux_beg = aux_end = 0; q_l = q_e - q_s; + thre = q_l*e_rate; thre = Adjust_Threshold(thre, q_l); + if(thre > THRESHOLD_MAX_SIZE) thre = THRESHOLD_MAX_SIZE; + ///offset of y + t_s = (q_s - z->x_pos_s) + z->y_pos_s; + t_s += y_start_offset(q_s, zf); + aln_l = q_l + (thre<<1); t_tot_l = Get_READ_LENGTH((*rref), z->y_id); + + exz->err = INT32_MAX; exz->thre = -1; + if(init_waln(thre, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) { + q_string = qstr+q_s; + recover_UC_Read_sub_region(tstr, t_s, t_pri_l, z->y_pos_strand, rref, z->y_id); t_string = tstr; + + t_l = t_pri_l; + ed_band_cal_semi_64_w_absent_diag(t_string, t_l, q_string, q_l, thre, aux_beg, exz); + (*tot_b) += q_l; + } + + kv_pushp(window_list, z->w_list, &p); z->overlapLen += q_e - q_s; + if (is_align(*exz)) { + // if(z->y_id == 3621213) { + // fprintf(stderr, "-e-[M::%s]\ttid::%u\t%.*s\taln::%u\tqe::%ld\tte::%ld\terr::%d\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // is_align(*exz)?1:0, q_e, t_s + exz->pe + 1, exz->err); + // } + ///t_s do not have aux_beg, while t_s + t_end (aka, te) has + p->x_start = q_s; p->x_end = q_e - 1; + p->y_start = t_s; p->y_end = t_s + exz->pe; + p->error = exz->err; + p->extra_begin = aux_beg; p->extra_end = aux_end; + p->error_threshold = exz->thre; p->cidx = p->clen = 0; + z->align_length += q_e - q_s; + // if((q_e > q_s) && ((q_e - q_s) >= (w_l>>1))) return 1;///ok, worth for in-depth cal + } else { + // if(z->y_id == 3621213) { + // fprintf(stderr, "-e-[M::%s]\ttid::%u\t%.*s\taln::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // is_align(*exz)?1:0); + // } + p->x_start = q_s; p->x_end = q_e - 1; + p->y_start = t_s; p->y_end = -1; + p->error_threshold = thre; p->error = INT16_MAX; + p->extra_begin = aux_beg; p->extra_end = aux_end; + p->cidx = p->clen = 0; + zual += q_e - q_s; + if((zual) && (zual > zcut)) return 0; + } + break; + } + } + q_s = q_e; q_e = q_s + w_l; + if(q_e > z_e) q_e = z_e; + } + + return 1; +} + + + +uint32_t align_hc_ed_post_non_retrieve_extz(overlap_region *z, char* qstr, int64_t ql, char *tstr, int64_t tl, bit_extz_t *exz, double e_rate, int64_t w_l, double ovlp_cut, int64_t force_aln, void *km) +{ + int64_t q_s, q_e, nw, k, q_l, t_l, aux_beg, aux_end, t_s, thre, aln_l, t_pri_l; + char *q_string, *t_string; + z->w_list.n = 0; z->is_match = 0; z->align_length = 0; + nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, w_l); + get_win_se_by_normalize_xs(z, (z->x_pos_s/w_l)*w_l, w_l, &q_s, &q_e); + for (k = 0; k < nw; k++) { + aux_beg = aux_end = 0; q_l = 1 + q_e - q_s; + thre = q_l*e_rate; thre = Adjust_Threshold(thre, q_l); + if(thre > THRESHOLD_MAX_SIZE) thre = THRESHOLD_MAX_SIZE; + ///offset of y + t_s = (q_s - z->x_pos_s) + z->y_pos_s; + t_s += y_start_offset(q_s, &(z->f_cigar)); + + aln_l = q_l + (thre<<1); + if(init_waln(thre, t_s, tl, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) { + q_string = qstr+q_s; t_string = tstr+t_s; t_l = t_pri_l; + + ed_band_cal_semi_64_w_absent_diag(t_string, t_l, q_string, q_l, thre, aux_beg, exz); + + // if(z->x_id == 5569 && z->y_id == 5557 && q_s == 10075 && q_e == 10849) { + // fprintf(stderr, "\n[M::%s::semi::t_s->%ld::t_pri_l->%ld::aux_beg->%ld::aux_end->%ld::thre->%ld] exz->ps::%d, exz->pe::%d, exz->ts::%d, exz->te::%d, exz->err::%d, exz->cigar.n::%d, thre::%ld\n", + // __func__, t_s, t_pri_l, aux_beg, aux_end, thre, exz->ps, exz->pe, exz->ts, exz->te, exz->err, (int32_t)exz->cigar.n, thre); + // fprintf(stderr, "[tstr::len->%ld] %.*s\n", t_l, (int32_t)t_l, t_string); + // fprintf(stderr, "[qstr::len->%ld] %.*s\n", q_l, (int32_t)q_l, q_string); + // } + if (is_align(*exz)) { + // ed_band_cal_semi_64_w(t_string, aln_l, q_string, q_l, thre, exz); + // assert(exz->err <= exz->thre); + // fprintf(stderr, "[M::%s] exz->err::%d\n", __func__, exz->err); + ///t_s do not have aux_beg, while t_s + t_end (aka, te) has + if(!push_hc_wlst_non_retrieve_exz(z, qstr, ql, tstr, tl, exz, THRESHOLD_MAX_SIZE, q_s, q_e, t_s, t_s + exz->pe, + aux_beg, aux_end, e_rate, w_l, ovlp_cut, force_aln, km)) { + return 0; + } + // append_window_list(z, q_s, q_e, t_s, t_s + t_end, error, aux_beg, aux_end, thre, w_l, km); + } + } + q_s = q_e + 1; q_e = q_s + w_l - 1; + if(q_e >= (int64_t)z->x_pos_e) q_e = z->x_pos_e; + } + + // if((!force_aln) && (!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, 0, ovlp_cut, &e_rate)) && + // (!simi_pass(z->x_pos_e+1-z->x_pos_s, z->align_length, sec_check, ovlp_cut, NULL))) return 0; + if((!force_aln) && (!pass_qovlp(z->x_pos_e+1-z->x_pos_s, z->align_length, ovlp_cut))) return 0; + return 1; +} + +inline uint32_t ed_cut(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, +char *qstr, char *tstr, uint32_t rev, uint32_t id, +int64_t qs, int64_t qe, int64_t t_s, int64_t block_s, double e_rate, int64_t max_err, +uint32_t aln_dir, int64_t* r_err, int64_t* qoff, int64_t* toff, int64_t* aln_qlen) +{ + (*aln_qlen) = 0; (*r_err) = INT32_MAX; + if(qoff) {(*qoff) = -1;} if(toff) {(*toff) = -1;} + int64_t ql, aln_l, t_tot_l, aux_beg, aux_end, t_pri_l, thres; + char *q_string, *t_string; unsigned int error; int t_end, q_end; + + ql = qe + 1 - qs; + ///there are two potiential reasons for unmatched window: + ///1. this window has a large number of differences + ///2. DP does not start from the right offset + if(rref) { + thres = double_error_threshold(get_init_err_thres(ql, e_rate, block_s, max_err), ql); + } else { + thres = double_ul_error_threshold(get_init_err_thres(ql, e_rate, block_s, max_err), ql); + } + + aln_l = ql + (thres << 1); + if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); + else if(uref) t_tot_l = uref->ug->u.a[id].len; + else t_tot_l = Get_READ_LENGTH((*rref), id); + + if(!init_waln(thres, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) return 0; + // if(t_pri_l + thres < ql) return 0; + + q_string = qstr + qs; + if(rref) { + fill_subregion(tstr, t_s, t_pri_l, rev, rref, id, aux_beg, aux_end); t_string = tstr; + } else { + t_string = return_str_seq(tstr, t_s, t_pri_l, rev, hpc_g, uref, id, aux_beg, aux_end); + } + + // if(id == 6) { + // fprintf(stderr, "-[M::%s::aln_dir->%u] qs->%ld, ts->%ld, thres->%ld, aux_beg->%ld, aux_end->%ld, t_pri_l->%ld\n", + // __func__, aln_dir, qs, t_s, thres, aux_beg, aux_end, t_pri_l); + // } + if(aln_dir == 0) { + Reserve_Banded_BPM_Extension(t_string, aln_l, q_string, ql, thres, &error, &t_end, &q_end); + } else { + Reserve_Banded_BPM_Extension_REV(t_string, aln_l, q_string, ql, thres, &error, &t_end, &q_end); + } + + if(t_end != -1 && q_end != -1) (*aln_qlen) = (aln_dir?(ql-q_end):(q_end+1)); + if(qoff) {(*qoff) = q_end;} if(toff) {(*toff) = t_end;} (*r_err) = error; + + if((*aln_qlen) == 0) return 0; + return 1; +} + +inline uint32_t ed_non_retrieve_cut(char *qstr, char *tstr, int64_t t_tot_l, uint32_t rev, uint32_t id, +int64_t qs, int64_t qe, int64_t t_s, int64_t block_s, double e_rate, int64_t max_err, +uint32_t aln_dir, int64_t* r_err, int64_t* qoff, int64_t* toff, int64_t* aln_qlen) +{ + (*aln_qlen) = 0; (*r_err) = INT32_MAX; + if(qoff) {(*qoff) = -1;} if(toff) {(*toff) = -1;} + int64_t ql, aln_l, aux_beg, aux_end, t_pri_l, thres; + char *q_string, *t_string; unsigned int error; int t_end, q_end; + + ql = qe + 1 - qs; + ///there are two potiential reasons for unmatched window: + ///1. this window has a large number of differences + ///2. DP does not start from the right offset + thres = double_error_threshold(get_init_err_thres(ql, e_rate, block_s, max_err), ql); + + aln_l = ql + (thres << 1); + + if(!init_waln(thres, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) return 0; + // if(t_pri_l + thres < ql) return 0; + + q_string = qstr + qs; t_string = tstr + t_s; + + // if(id == 6) { + // fprintf(stderr, "-[M::%s::aln_dir->%u] qs->%ld, ts->%ld, thres->%ld, aux_beg->%ld, aux_end->%ld, t_pri_l->%ld\n", + // __func__, aln_dir, qs, t_s, thres, aux_beg, aux_end, t_pri_l); + // } + if(aln_dir == 0) { + Reserve_Banded_BPM_Extension(t_string, aln_l, q_string, ql, thres, &error, &t_end, &q_end); + } else { + Reserve_Banded_BPM_Extension_REV(t_string, aln_l, q_string, ql, thres, &error, &t_end, &q_end); + } + + if(t_end != -1 && q_end != -1) (*aln_qlen) = (aln_dir?(ql-q_end):(q_end+1)); + if(qoff) {(*qoff) = q_end;} if(toff) {(*toff) = t_end;} (*r_err) = error; + + if((*aln_qlen) == 0) return 0; + return 1; +} + +int64_t gen_extend_err_0(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, +char *tstr, char *tstr_1, Correct_dumy* dumy, uint64_t *v_idx, int64_t block_s, double e_rate, +int64_t qs, int64_t qe, int64_t pk) +{ + int64_t tot_e = 0, ts, di[2], al[2], tb[2], an = z->w_list.n; double rr; + int64_t id = z->y_id, rev = z->y_pos_strand, ql = qe + 1 - qs; + ///check if there are some windows that cannot be algined by any overlaps/unitigs + ///if no, it is likely that the UL read itself has issues + if(uref && v_idx && z->is_match == 4) { + if(check_coverage_gap(v_idx, qs, qe, block_s)) { + tot_e += THRESHOLD_MAX_SIZE; return tot_e; + } + } + ts = (qs - z->x_pos_s) + z->y_pos_s; ts += y_start_offset(qs, &(z->f_cigar)); + + di[0] = di[1] = al[0] = al[1] = 0; tb[0] = tb[1] = -1; + if((pk > 0) && (qs == (z->w_list.a[pk].x_end + 1))) { + if(z->w_list.a[pk].clen == 0) {///do not have cigar + gen_backtrace_adv(&(z->w_list.a[pk]), z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, rev, id); + } + tb[0] = z->w_list.a[pk].y_end + 1; + } + + if(((pk+1) < an) && ((qe+1) == (z->w_list.a[pk+1].x_start))) { + if(z->w_list.a[pk+1].clen == 0) {///do not have cigar + gen_backtrace_adv(&(z->w_list.a[pk+1]), z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, rev, id); + } + tb[1] = z->w_list.a[pk+1].y_start-ql; + } + + if(tb[0] == -1 && tb[1] == -1) tb[0] = tb[1] = ts; + else if(tb[0] == -1 && tb[1] != -1) tb[0] = tb[1]; + else if(tb[1] == -1 && tb[0] != -1) tb[1] = tb[0]; + + if(tb[0] != -1) { + if(!ed_cut(uref, hpc_g, rref, qstr, tstr, rev, id, qs, qe, tb[0], block_s, e_rate, ((rref)?THRESHOLD:THRESHOLD_MAX_SIZE), + 0, &(di[0]), NULL, NULL, &(al[0]))) { + di[0] = ql; al[0] = 0; + } + } + + if(tb[1] != -1) { + if(!ed_cut(uref, hpc_g, rref, qstr, tstr, rev, id, qs, qe, tb[1], block_s, e_rate, ((rref)?THRESHOLD:THRESHOLD_MAX_SIZE), + 1, &(di[1]), NULL, NULL, &(al[1]))) { + di[1] = ql; al[1] = 0; + } + } + + if(al[0] && al[1]) {///matched in both sides + if((al[0] + al[1]) <= ql) { + tot_e += di[0] + di[1] + ql - (al[0] + al[1]); + } else { + rr = ((double)ql)/((double)(al[0] + al[1])); + tot_e += (di[0] + di[1])*rr; + } + } else if((!al[0]) && (!al[1])) {//failed + tot_e += ql; + } else if(al[0]) { + tot_e += di[0] + (ql - al[0]); + }else if(al[1]) { + tot_e += di[1] + (ql - al[1]); + } + // if(z->y_id == 6) { + // fprintf(stderr, "-[M::%s] qs->%ld, ts->%ld, tb[0]->%ld, tb[1]->%ld, di[0]->%ld, di[1]->%ld, al[0]->%ld, al[1]->%ld, block_s->%ld, e_rate->%f\n", __func__, + // qs, ts, tb[0], tb[1], di[0], di[1], al[0], al[1], block_s, e_rate); + // } + return tot_e; +} + + +int64_t gen_extend_err_0_exz(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, +char *tstr, bit_extz_t *exz, uint64_t *v_idx, int64_t block_s, double e_rate, int64_t max_err, +int64_t qs, int64_t qe, int64_t pk) +{ + int64_t tot_e = 0, ts, di[2], al[2], tb[2], an = z->w_list.n; double rr; + int64_t id = z->y_id, rev = z->y_pos_strand, ql = qe + 1 - qs; + ///check if there are some windows that cannot be algined by any overlaps/unitigs + ///if no, it is likely that the UL read itself has issues + if(uref && v_idx && z->is_match == 4) { + if(check_coverage_gap(v_idx, qs, qe, block_s)) { + tot_e += THRESHOLD_MAX_SIZE; return tot_e; + } + } + ts = (qs - z->x_pos_s) + z->y_pos_s; ts += y_start_offset(qs, &(z->f_cigar)); + + di[0] = di[1] = al[0] = al[1] = 0; tb[0] = tb[1] = -1; + if((pk > 0) && (qs == (z->w_list.a[pk].x_end + 1))) { + if(z->w_list.a[pk].clen == 0) {///do not have cigar + gen_backtrace_adv_exz(&(z->w_list.a[pk]), z, rref, hpc_g, uref, qstr, tstr, exz, rev, id); + } + tb[0] = z->w_list.a[pk].y_end + 1; + } + + if(((pk+1) < an) && ((qe+1) == (z->w_list.a[pk+1].x_start))) { + if(z->w_list.a[pk+1].clen == 0) {///do not have cigar + gen_backtrace_adv_exz(&(z->w_list.a[pk+1]), z, rref, hpc_g, uref, qstr, tstr, exz, rev, id); + } + tb[1] = z->w_list.a[pk+1].y_start-ql; + } + + if(tb[0] == -1 && tb[1] == -1) tb[0] = tb[1] = ts; + else if(tb[0] == -1 && tb[1] != -1) tb[0] = tb[1]; + else if(tb[1] == -1 && tb[0] != -1) tb[1] = tb[0]; + + if(tb[0] != -1) { + if(!ed_cut(uref, hpc_g, rref, qstr, tstr, rev, id, qs, qe, tb[0], block_s, e_rate, max_err, + 0, &(di[0]), NULL, NULL, &(al[0]))) { + di[0] = ql; al[0] = 0; + } + } + + if(tb[1] != -1) { + if(!ed_cut(uref, hpc_g, rref, qstr, tstr, rev, id, qs, qe, tb[1], block_s, e_rate, max_err, + 1, &(di[1]), NULL, NULL, &(al[1]))) { + di[1] = ql; al[1] = 0; + } + } + + if(al[0] && al[1]) {///matched in both sides + if((al[0] + al[1]) <= ql) { + tot_e += di[0] + di[1] + ql - (al[0] + al[1]); + } else { + rr = ((double)ql)/((double)(al[0] + al[1])); + tot_e += (di[0] + di[1])*rr; + } + } else if((!al[0]) && (!al[1])) {//failed + tot_e += ql; + } else if(al[0]) { + tot_e += di[0] + (ql - al[0]); + }else if(al[1]) { + tot_e += di[1] + (ql - al[1]); + } + // if(z->y_id == 6) { + // fprintf(stderr, "-[M::%s] qs->%ld, ts->%ld, tb[0]->%ld, tb[1]->%ld, di[0]->%ld, di[1]->%ld, al[0]->%ld, al[1]->%ld, block_s->%ld, e_rate->%f\n", __func__, + // qs, ts, tb[0], tb[1], di[0], di[1], al[0], al[1], block_s, e_rate); + // } + return tot_e; +} + +int64_t gen_extend_err_0_non_retrieve_exz(overlap_region *z, char* qstr, char *tstr, int64_t tl, bit_extz_t *exz, uint64_t *v_idx, int64_t block_s, double e_rate, int64_t max_err, int64_t qs, int64_t qe, int64_t pk) +{ + int64_t tot_e = 0, ts, di[2], al[2], tb[2], an = z->w_list.n; double rr; + int64_t id = z->y_id, rev = z->y_pos_strand, ql = qe + 1 - qs; + ///check if there are some windows that cannot be algined by any overlaps/unitigs + ///if no, it is likely that the UL read itself has issues + + ts = (qs - z->x_pos_s) + z->y_pos_s; ts += y_start_offset(qs, &(z->f_cigar)); + + di[0] = di[1] = al[0] = al[1] = 0; tb[0] = tb[1] = -1; + if((pk > 0) && (qs == (z->w_list.a[pk].x_end + 1))) { + if(z->w_list.a[pk].clen == 0) {///do not have cigar + gen_backtrace_non_retrieve_adv_exz(&(z->w_list.a[pk]), z, qstr, tstr, tl, exz, rev, id); + } + tb[0] = z->w_list.a[pk].y_end + 1; + } + + if(((pk+1) < an) && ((qe+1) == (z->w_list.a[pk+1].x_start))) { + if(z->w_list.a[pk+1].clen == 0) {///do not have cigar + gen_backtrace_non_retrieve_adv_exz(&(z->w_list.a[pk+1]), z, qstr, tstr, tl, exz, rev, id); + } + tb[1] = z->w_list.a[pk+1].y_start-ql; + } + + if(tb[0] == -1 && tb[1] == -1) tb[0] = tb[1] = ts; + else if(tb[0] == -1 && tb[1] != -1) tb[0] = tb[1]; + else if(tb[1] == -1 && tb[0] != -1) tb[1] = tb[0]; + + if(tb[0] != -1) { + if(!ed_non_retrieve_cut(qstr, tstr, tl, rev, id, qs, qe, tb[0], block_s, e_rate, max_err, + 0, &(di[0]), NULL, NULL, &(al[0]))) { + di[0] = ql; al[0] = 0; + } + } + + if(tb[1] != -1) { + if(!ed_non_retrieve_cut(qstr, tstr, tl, rev, id, qs, qe, tb[1], block_s, e_rate, max_err, + 1, &(di[1]), NULL, NULL, &(al[1]))) { + di[1] = ql; al[1] = 0; + } + } + + if(al[0] && al[1]) {///matched in both sides + if((al[0] + al[1]) <= ql) { + tot_e += di[0] + di[1] + ql - (al[0] + al[1]); + } else { + rr = ((double)ql)/((double)(al[0] + al[1])); + tot_e += (di[0] + di[1])*rr; + } + } else if((!al[0]) && (!al[1])) {//failed + tot_e += ql; + } else if(al[0]) { + tot_e += di[0] + (ql - al[0]); + }else if(al[1]) { + tot_e += di[1] + (ql - al[1]); + } + // if(z->y_id == 6) { + // fprintf(stderr, "-[M::%s] qs->%ld, ts->%ld, tb[0]->%ld, tb[1]->%ld, di[0]->%ld, di[1]->%ld, al[0]->%ld, al[1]->%ld, block_s->%ld, e_rate->%f\n", __func__, + // qs, ts, tb[0], tb[1], di[0], di[1], al[0], al[1], block_s, e_rate); + // } + return tot_e; +} + +double gen_extend_err(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, +char *tstr, char *tstr_1, Correct_dumy* dumy, uint64_t *v_idx, int64_t block_s, double ovlp_cut, double e_rate, double e_max, int64_t *r_e) +{ + int64_t ovl, k, ce, an = z->w_list.n, tot_l, tot_e, ws, we, ql; + ovl = z->x_pos_e+1-z->x_pos_s; if(r_e) (*r_e) = INT64_MAX; + if(!simi_pass(ovl, z->align_length, 0, ovlp_cut, &e_rate)) return DBL_MAX; + // nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); + for (k = 0; k < an; k++) { + if(z->w_list.a[k].clen) z->w_list.a[k].y_end -= z->w_list.a[k].extra_begin; + } + + tot_l = tot_e = 0; + for (k = an-1, ce = z->x_pos_e; k >= 0; k--) { + // assert(k == 0 || z->w_list.a[k].x_end > z->w_list.a[k-1].x_start);//sorted + tot_l += z->w_list.a[k].x_end + 1 - z->w_list.a[k].x_start; + tot_e += z->w_list.a[k].error;///matched window + + we = z->w_list.a[k].x_end; + while (we < ce) { + ws = we+1; + get_win_id_by_s(z, ws, block_s, &we); + ql = we+1-ws; tot_l += ql; + tot_e += gen_extend_err_0(z, uref, hpc_g, rref, qstr, tstr, tstr_1, dumy, v_idx, block_s, e_rate, ws, we, k); + if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; + } + ce = z->w_list.a[k].x_start-1; + if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; + } + + if(ce >= ((int64_t)z->x_pos_s)) { + we = ((int64_t)z->x_pos_s)-1; + while (we < ce) { + ws = we+1; + get_win_id_by_s(z, ws, block_s, &we); + ql = we+1-ws; tot_l += ql; + tot_e += gen_extend_err_0(z, uref, hpc_g, rref, qstr, tstr, tstr_1, dumy, v_idx, block_s, e_rate, ws, we, k); + if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; + } + } + + assert(tot_l == ovl); if(r_e) (*r_e) = tot_e; + return (double)(tot_e)/(double)(tot_l); +} + +double gen_extend_err_exz(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, +char *tstr, bit_extz_t *exz, uint64_t *v_idx, int64_t block_s, double ovlp_cut, double e_rate, double e_max, int64_t max_err, int64_t sec_check, int64_t *r_e) +{ + int64_t ovl, k, ce, an = z->w_list.n, tot_l, tot_e, ws, we, ql; + ovl = z->x_pos_e+1-z->x_pos_s; if(r_e) (*r_e) = INT64_MAX; + if((sec_check) && (!simi_pass(ovl, z->align_length, 0, ovlp_cut, &e_rate))) return DBL_MAX; + // nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); + // for (k = 0; k < an; k++) { + // if(z->w_list.a[k].clen) z->w_list.a[k].y_end -= z->w_list.a[k].extra_begin; + // } + + tot_l = tot_e = 0; + for (k = an-1, ce = z->x_pos_e; k >= 0; k--) { + // assert(k == 0 || z->w_list.a[k].x_end > z->w_list.a[k-1].x_start);//sorted + tot_l += z->w_list.a[k].x_end + 1 - z->w_list.a[k].x_start; + tot_e += z->w_list.a[k].error;///matched window + + we = z->w_list.a[k].x_end; + while (we < ce) { + ws = we+1; + get_win_id_by_s(z, ws, block_s, &we); + ql = we+1-ws; tot_l += ql; + tot_e += gen_extend_err_0_exz(z, uref, hpc_g, rref, qstr, tstr, exz, v_idx, block_s, e_rate, max_err, ws, we, k); + if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; + } + ce = z->w_list.a[k].x_start-1; + if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; + } + + if(ce >= ((int64_t)z->x_pos_s)) { + we = ((int64_t)z->x_pos_s)-1; + while (we < ce) { + ws = we+1; + get_win_id_by_s(z, ws, block_s, &we); + ql = we+1-ws; tot_l += ql; + tot_e += gen_extend_err_0_exz(z, uref, hpc_g, rref, qstr, tstr, exz, v_idx, block_s, e_rate, max_err, ws, we, k); + if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; + } + } + + assert(tot_l == ovl); if(r_e) (*r_e) = tot_e; + return (double)(tot_e)/(double)(tot_l); +} + +double gen_extend_err_non_retrieve_exz(overlap_region *z, char* qstr, char *tstr, int64_t tl, bit_extz_t *exz, uint64_t *v_idx, int64_t block_s, double ovlp_cut, double e_rate, double e_max, int64_t max_err, int64_t sec_check, int64_t *r_e) +{ + int64_t ovl, k, ce, an = z->w_list.n, tot_l, tot_e, ws, we, ql; + ovl = z->x_pos_e+1-z->x_pos_s; if(r_e) (*r_e) = INT64_MAX; + if((sec_check) && (!simi_pass(ovl, z->align_length, 0, ovlp_cut, &e_rate))) return DBL_MAX; + // nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); + // for (k = 0; k < an; k++) { + // if(z->w_list.a[k].clen) z->w_list.a[k].y_end -= z->w_list.a[k].extra_begin; + // } + + tot_l = tot_e = 0; + for (k = an-1, ce = z->x_pos_e; k >= 0; k--) { + // assert(k == 0 || z->w_list.a[k].x_end > z->w_list.a[k-1].x_start);//sorted + tot_l += z->w_list.a[k].x_end + 1 - z->w_list.a[k].x_start; + tot_e += z->w_list.a[k].error;///matched window + + we = z->w_list.a[k].x_end; + while (we < ce) { + ws = we+1; + get_win_id_by_s(z, ws, block_s, &we); + ql = we+1-ws; tot_l += ql; + tot_e += gen_extend_err_0_non_retrieve_exz(z, qstr, tstr, tl, exz, v_idx, block_s, e_rate, max_err, ws, we, k); + if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; + } + ce = z->w_list.a[k].x_start-1; + if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; + } + + if(ce >= ((int64_t)z->x_pos_s)) { + we = ((int64_t)z->x_pos_s)-1; + while (we < ce) { + ws = we+1; + get_win_id_by_s(z, ws, block_s, &we); + ql = we+1-ws; tot_l += ql; + tot_e += gen_extend_err_0_non_retrieve_exz(z, qstr, tstr, tl, exz, v_idx, block_s, e_rate, max_err, ws, we, k); + if((e_max > 0) && (tot_e > (ovl*e_max))) return DBL_MAX; + } + } + + assert(tot_l == ovl); if(r_e) (*r_e) = tot_e; + return (double)(tot_e)/(double)(tot_l); +} + + +void push_anchors(window_list *z, window_list_alloc *zidx, asg64_v *anchor, uint64_t *qhp, int64_t qhp_l, int64_t *qhp_k, uint32_t mcl) +{ + int64_t xi = 0, yi = 0, ci, cn = z->clen; uint8_t c = (uint8_t)-1; uint32_t cl = (uint32_t)-1; + for (ci = 0; ci < cn; ci++) { + get_cigar_cell(z, zidx, ci, &c, &cl); + if (c == 0) { //match + if(cl >= mcl) { + ; + ; + ; + ; + } + xi += cl; yi += cl; + } else if (c == 1) { + xi += cl; yi += cl; + } else if (c == 2) {///y has more bases than x + yi += cl; + } else if (c == 3) {///x has more bases than y + xi += cl; + } + } +} + +#define gen_hpc_max_len(x) ((x)+((x)>>1)+1) +///[off_s, off_e) +uint64_t extract_mm_hpc(char *in, int64_t len, int64_t off_s, int64_t off_e, int64_t w, uint64_t rev) +{ + int64_t i, o, l, trim, k, tl; uint64_t m, sf; uint8_t c; + ///forward + for (k = 1, trim = 0; k <= w; k++) { + m = 0; o = gen_hpc_max_len(k); sf = k<<1; + if(!rev) { + ///[off_s, off_e) + for (i = ((off_s>=o)?(off_s-o):(0)), l = 0; i < off_e; i++) { + c = seq_nt4_table[(uint8_t)in[i]]; + if((c < 4) && (((l >= k) && (((m>>sf)&3) == c)) || (l < k))) { + if(l < k) m = (m<<2) + c; + else sf = (sf?(sf):(k<<1))-2; + l++; + } else { + if(i > off_s) { + tl = i-off_s; + if((l >= o) && (trim < tl)) trim = tl; + l = -1; + break; + } + l = 0; sf = k<<1; + } + } + tl = i-off_s; + if((l!=-1) && (i > off_s) && (l >= o) && (trim < tl)) { + trim = tl; + if(trim >= (off_e-off_s)) break; + } + } else { + ///[off_s, off_e) + for (i = (((len-off_e)>=o)?(off_e+o):(len))-1, l = 0; i >= off_s; i--) { + c = seq_nt4_table[(uint8_t)in[i]]; + if((c < 4) && (((l >= k) && (((m>>sf)&3) == c)) || (l < k))) { + if(l < k) m = (m<<2) + c; + else sf = (sf?(sf):(k<<1))-2; + l++; + } else { + if(i+1 < off_e) { + tl = off_e-i-1; + if((l >= o) && (trim < tl)) trim = tl; + l = -1; + break; + } + l = 0; sf = k<<1; + } + } + tl = off_e-i-1; + if((l!=-1) && (i+1 < off_e) && (l >= o) && (trim < tl)) { + trim = tl; + if(trim >= (off_e-off_s)) break; + } + } + } + return trim; +} + +uint64_t trim_hpc(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, char *tstr, int64_t hpc_max, +int64_t ql, int64_t tl, int64_t tid, int64_t trev, int64_t *rqs, int64_t *rqe, int64_t *rts, int64_t *rte) +{ + ///[qs, qe); [ts, te) + int64_t qs = *rqs, qe = *rqe, ts = *rts, te = *rte, trim[2], hl, aux_l, subl = qe-qs; char *ss; + if(hpc_max > 32) {hpc_max = 32;} trim[0] = trim[1] = 0; aux_l = gen_hpc_max_len(hpc_max); + + qs -= aux_l; if(qs < 0) qs = 0; + qe += aux_l; if(qe > ql) qe = ql; + ss = qstr + qs; + hl = extract_mm_hpc(ss, qe - qs, (*rqs)-qs, (*rqe)-qs, hpc_max, 0); + if(hl >= subl) {return 0;} trim[0] = hl; + hl = extract_mm_hpc(ss, qe - qs, (*rqs)-qs, (*rqe)-qs, hpc_max, 1); + if(hl >= subl) {return 0;} trim[1] = hl; + if(trim[0] + trim[1] >= subl) return 0; + + ts -= aux_l; if(ts < 0) ts = 0; + te += aux_l; if(te > tl) te = tl; + if(rref) { + fill_subregion(tstr, ts, te-ts, trev, rref, tid, 0, 0); ss = tstr; + } else { + ss = return_str_seq(tstr, ts, te-ts, trev, hpc_g, uref, tid, 0, 0); + } + hl = extract_mm_hpc(ss, te - ts, (*rts)-ts, (*rte)-ts, hpc_max, 0); + if(hl >= subl) {return 0;} if(hl > trim[0]) {trim[0] = hl;} + hl = extract_mm_hpc(ss, te - ts, (*rts)-ts, (*rte)-ts, hpc_max, 1); + if(hl >= subl) {return 0;} if(hl > trim[1]) {trim[1] = hl;} + if(trim[0] + trim[1] >= subl) return 0; + + (*rqs) += trim[0]; (*rts) += trim[0]; + (*rqe) -= trim[1]; (*rte) -= trim[1]; + return 1; +} + +#define cl_pushp(type, v, p) do { \ + if ((v).length == (v).size) { \ + (v).size = (v).size? (v).size<<1 : 2; \ + (v).list = (type*)realloc((v).list, sizeof(type) * (v).size); \ + } \ + *(p) = &(v).list[(v).length++]; \ + } while (0) + +///ai is the suffix of aj +int64_t inline traceback_sc(const k_mer_hit *ai, const k_mer_hit *aj) +{ + int64_t qsi = ai->self_offset-ai->cnt, qej = aj->self_offset; + int64_t tsi = ai->offset-ai->cnt, tej = aj->offset; + if(qsi >= qej && tsi >= tej) return ai->cnt; + return INT32_MIN; +} + +void split_long_anchors(Candidates_list *ac, int64_t block, int64_t block_n) +{ + int64_t i, m, an = ac->length; + if(block_n < 0) { + for (i = block_n = 0; i < an; i++) { + if(ac->list[i].cnt <= block) block_n++; + else block_n += (ac->list[i].cnt/block) + (((ac->list[i].cnt%block) > 0)?1:0); + } + } + if(block_n <= an) return; + if(block_n > ac->size) { + ac->size = block_n; REALLOC(ac->list, ac->size); + } + for (i = an-1, m = block_n-1; i >= 0; i--) { + if(ac->list[i].cnt <= block) { + ac->list[m--] = ac->list[i]; + } else { + while (ac->list[i].cnt > 0) { + ac->list[m] = ac->list[i]; + if(ac->list[i].cnt >= block) { + ac->list[m].cnt = block; + ac->list[i].cnt -= block; + ac->list[i].self_offset -= block; + ac->list[i].offset -= block; + } else { + ac->list[i].cnt = 0; + } + m--; + } + } + } + ac->length = block_n; assert(m == -1); +} + +int64_t gen_affine_traceback_dp(Candidates_list *ac, int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t block, int64_t block_n) +{ + if(ac->length < 1) return 0; + int64_t i, j, *p, *t, max_f, n_skip, max_j, end_j, st, max_ii, sc, max, tmp, msc_i, msc; + int32_t *f, cL; k_mer_hit* a = ac->list; int64_t a_n = ac->length; Chain_Data* dp; + + for (i = 1; i < a_n; ++i) { + sc = traceback_sc(&a[i], &a[i-1]); + if(sc == INT32_MIN) break; + } + if(i >= a_n) return a_n; + + split_long_anchors(ac, block, block_n); + a = ac->list; a_n = ac->length; dp = &(ac->chainDP); + + resize_Chain_Data(dp, a_n, NULL); t = dp->tmp; f = dp->score; p = dp->pre; + t[0] = 0; p[0] = -1; f[0] = a[0].cnt; + msc_i = msc = -1; i = 0; + + memset(t, 0, (a_n*sizeof((*t)))); + for (i = st = 0, max_ii = -1; i < a_n; ++i) { + max_f = a[i].cnt; n_skip = 0; max_j = end_j = -1; + if ((i-st) > max_iter) st = i-max_iter; + + for (j = i - 1; j >= st; --j) { + sc = traceback_sc(&a[i], &a[j]); + if(sc == INT32_MIN) break; + sc += f[j]; + if (sc > max_f) { + max_f = sc, max_j = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == (int32_t)i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + end_j = j; + + if (max_ii < 0 || ((int64_t)a[i].offset) - ((int64_t)a[max_ii].offset) > max_dis) { + max = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && ((((int64_t)a[i].offset)-((int64_t)a[j].offset))<=max_dis); --j) { + if (max < f[j]) { + max = f[j], max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + tmp = traceback_sc(&a[i], &a[max_ii]); + if (tmp != INT32_MIN && max_f < tmp + f[max_ii]) + max_f = tmp + f[max_ii], max_j = max_ii; + } + f[i] = max_f; p[i] = max_j; + if ((max_ii < 0) || (((((int64_t)a[i].offset)-((int64_t)a[max_ii].offset))<=max_dis) && (f[max_ii] msc) { + msc = f[i]; msc_i = i; + } + } + + cL = 0; i = msc_i; + while (i >= 0) { + t[cL++] = i; i = p[i]; + } + for (i = 0; i < cL; i++) a[i] = a[t[cL-i-1]]; + return cL; +} + +uint64_t gen_affine_traceback(overlap_region *o, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, char *tstr, uint64_t ql, +uint64_t *qhp, uint64_t qhp_l, Candidates_list *ac, uint32_t hpc_max, uint32_t min_ach, uint32_t block) +{ + if(o->w_list.n <= 0) return 0; + int64_t nw = o->w_list.n, snw, k, t, qi, ti, ci, p_qi, p_ti, cn, qs, qe, ts, te, tl; + window_list *z; uint8_t c; uint32_t cl, pcl, id = o->y_id, rev = o->y_pos_strand; k_mer_hit *p; + uint64_t hm, aocc = 0, bocc = 0; qi = ti = 0; p_qi = p_ti = INT32_MIN; pcl = 0; + clear_Candidates_list(ac); + if(o->w_list.n > (uint64_t)ac->size) { + ac->size = o->w_list.n; REALLOC(ac->list, ac->size); + } + + if(hpc_g) tl = hpc_len(*hpc_g, id); + else if(uref) tl = uref->ug->u.a[id].len; + else tl = Get_READ_LENGTH((*rref), id); + for (k = 0; k < nw; k++) { + z = &(o->w_list.a[k]); ci = 0; cn = z->clen; + qi = z->x_start; ti = z->y_start; + for (ci = 0; ci < cn; ci++) { + get_cigar_cell(z, &(o->w_list), ci, &c, &cl); + if (c == 0) { //match + if((p_qi == qi) && (p_ti == ti)) { + pcl += cl; + } else { + ///push + if(pcl > 0) { + hm = 0; qs = qi - pcl; qe = qi; ts = ti - pcl; te = ti; + if(pcl > min_ach) hm = trim_hpc(uref, hpc_g, rref, qstr, tstr, hpc_max, ql, tl, id, rev, &qs, &qe, &ts, &te); + if(hm) aocc++; + if(hm || aocc == 0) { + cl_pushp(k_mer_hit, *ac, &p); + p->readID = p->strand = !!hm; + p->cnt = qe - qs; p->self_offset = qe; p->offset = te; + if(p->cnt > min_ach) bocc++; + } + } + ///push + pcl = 0; + } + qi += cl; ti += cl; + p_qi = qi; p_ti = ti; + } else { + ///push + if(pcl > 0) { + hm = 0; qs = qi - pcl; qe = qi; ts = ti - pcl; te = ti; + if(pcl > min_ach) hm = trim_hpc(uref, hpc_g, rref, qstr, tstr, hpc_max, ql, tl, id, rev, &qs, &qe, &ts, &te); + if(hm) aocc++; + if(hm || aocc == 0) { + cl_pushp(k_mer_hit, *ac, &p); + p->readID = p->strand = !!hm; + p->cnt = qe - qs; p->self_offset = qe; p->offset = te; + if(p->cnt > min_ach) bocc++; + } + } + pcl = 0; + ///push + if (c == 1) { + qi += cl; ti += cl; + } if (c == 2) {///t has more bases than p + ti += cl; + } if (c == 3) {///p has more bases than t + qi += cl; + } + } + } + } + + ///push + if(pcl > 0) { + hm = 0; qs = qi - pcl; qe = qi; ts = ti - pcl; te = ti; + if(pcl > min_ach) hm = trim_hpc(uref, hpc_g, rref, qstr, tstr, hpc_max, ql, tl, id, rev, &qs, &qe, &ts, &te); + if(hm) aocc++; + if(hm || aocc == 0) { + cl_pushp(k_mer_hit, *ac, &p); + p->readID = p->strand = !!hm; + p->cnt = qe - qs; p->self_offset = qe; p->offset = te; + if(p->cnt > min_ach) bocc++; + } + } + ///push + + nw = ac->length; snw = -1; + if(aocc > 0) { + if(aocc < (uint64_t)ac->length) { + for (k = t = snw = 0; k < nw; k++) { + if(ac->list[k].readID) { + ac->list[t] = ac->list[k]; + if(ac->list[t].cnt <= block) snw++; + else snw += (ac->list[t].cnt/block) + (((ac->list[t].cnt%block) > 0)?1:0); + t++; + } + } + ac->length = t; + } + } else if (bocc > 0) { + if(bocc < (uint64_t)ac->length) { + for (k = t = snw = 0; k < nw; k++) { + if(ac->list[k].cnt > min_ach) { + ac->list[t] = ac->list[k]; + if(ac->list[t].cnt <= block) snw++; + else snw += (ac->list[t].cnt/block) + (((ac->list[t].cnt%block) > 0)?1:0); + t++; + } + } + ac->length = t; + } + } + nw = ac->length; + gen_affine_traceback_dp(ac, 25, 5000, 5000, block, snw); + return 1; +} + + +void align_ul_ed(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, char* qstr, char *tstr, double e_rate, int64_t w_l, void *km) +{ + int64_t q_s, q_e, nw, k, q_l, t_tot_l; + int64_t aux_beg, aux_end, t_s, thre, aln_l, t_pri_l, t_end; + char *q_string, *t_string; unsigned int error; + z->w_list.n = 0; z->is_match = 0; + nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, w_l); + get_win_se_by_normalize_xs(z, (z->x_pos_s/w_l)*w_l, w_l, &q_s, &q_e); + for (k = 0; k < nw; k++) { + aux_beg = aux_end = 0; q_l = 1 + q_e - q_s; + thre = q_l*e_rate; thre = Adjust_Threshold(thre, q_l); + if(thre > THRESHOLD_MAX_SIZE) thre = THRESHOLD_MAX_SIZE; + ///offset of y + t_s = (q_s - z->x_pos_s) + z->y_pos_s; + t_s += y_start_offset(q_s, &(z->f_cigar)); + + aln_l = q_l + (thre<<1); t_tot_l = hpc_g?hpc_len(*hpc_g, z->y_id):uref->ug->u.a[z->y_id].len; + if(init_waln(thre, t_s, t_tot_l, aln_l, &aux_beg, &aux_end, &t_s, &t_pri_l)) { + q_string = qstr+q_s; + t_string = return_str_seq(tstr, t_s, t_pri_l, z->y_pos_strand, hpc_g, uref, z->y_id, aux_beg, aux_end); + + t_end = Reserve_Banded_BPM(t_string, aln_l, q_string, q_l, thre, &error); + if (error!=((unsigned int)-1)) { + z->align_length += q_l; + ///t_s do not have aux_beg, while t_s + t_end (aka, te) has + append_window_list(z, q_s, q_e, t_s, t_s + t_end, error, aux_beg, aux_end, thre, w_l, km); + } + } + q_s = q_e + 1; q_e = q_s + w_l - 1; + if(q_e >= (int64_t)z->x_pos_e) q_e = z->x_pos_e; + } + + assert(q_e == (int64_t)z->x_pos_e); +} + +uint64_t realign_ed(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, +char *tstr, char *tstr_1, Correct_dumy* dumy, kvec_t_u64_warp* v_idx, int64_t block_s, double e_rate, +double *e_rate_final, uint32_t sec_check, double ovlp_cut, int64_t *is_sort) +{ + int64_t i, k, nw, a_nw, w_id, y_id, y_strand, real_y_start, x_start, x_end, x_len, ce, cs; + int64_t w_s, w_e, mm_we, mm_ws, mm_aln, ovl, y_readLen, total_y_start, total_y_end; + uint64_t *w_idx = NULL, srt = 1; window_list *p = NULL; if(sec_check && (!uref)) sec_check = 0; + z->is_match = 0; if(is_sort) (*is_sort) = 1; + if(z->w_list.n == 0) return 0; + nw = get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s); a_nw = z->w_list.n; + y_id = z->y_id; y_strand = z->y_pos_strand; + ovl = z->x_pos_e+1-z->x_pos_s; mm_ws = mm_we = z->x_pos_s; mm_aln = 0; + + if(hpc_g) y_readLen = hpc_len(*hpc_g, y_id); + else if(uref) y_readLen = uref->ug->u.a[y_id].len; + else y_readLen = Get_READ_LENGTH((*rref), y_id); + + for (i = a_nw-1, ce = z->x_pos_e; i >= 0; i--) { //utilize the the end pos of pre-window in forward + w_e = mm_we = z->w_list.a[i].x_end; + total_y_start = z->w_list.a[i].y_end + 1 - z->w_list.a[i].extra_begin; + while ((w_e < ce) && (total_y_start < y_readLen)) { + w_s = w_e + 1; + w_id = get_win_id_by_s(z, w_s, block_s, &w_e); + x_start = w_s; x_end = w_e; + if(aln_wlst_adv(z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, + y_strand, y_id, x_start, x_end, total_y_start, block_s, e_rate, 0)) { + p = &(z->w_list.a[z->w_list.n-1]); + mm_we = x_end; + } else { + break; + } + total_y_start = p->y_end + 1 - p->extra_begin; + } + ce = z->w_list.a[i].x_start-1; + if(i == a_nw-1) {///only possiblity with the largest end pos + mm_aln = mm_we+1-mm_ws; + if(!simi_pass(ovl, mm_aln, sec_check, ovlp_cut, NULL)) break; + } + } + + if(z->w_list.a[a_nw-1].x_end > z->w_list.a[z->w_list.n-1].x_end) { + srt = 0; if(is_sort) (*is_sort) = 0; + } + if(i >= 0) return 0; + if((!srt) && (z->w_list.n <= (nw*0.2))) {///if very few windows are mapped + radix_sort_window_list_xs_srt(z->w_list.a, z->w_list.a + z->w_list.n); + srt = 1; if(is_sort) (*is_sort) = 1; + } + if(!srt) {///need sort + a_nw = z->w_list.n; + kv_resize(uint64_t, v_idx->a, (uint64_t)nw); w_idx = v_idx->a.a; + memset(v_idx->a.a, -1, sizeof((*v_idx->a.a))*nw); + for (i = 0; i < a_nw; i++) { ///w_idx[] == (uint64_t) if unmatched + assert(z->w_list.a[i].y_end != -1); + w_id = get_win_id_by_s(z, z->w_list.a[i].x_start, block_s, NULL); + w_idx[w_id] = i; + } + ///deal with first window + mm_ws = z->x_pos_s; + if(w_idx[0] != (uint64_t)-1) { + w_s = z->w_list.a[w_idx[0]].x_start; mm_aln -= (w_s-mm_ws); + mm_ws = z->w_list.a[w_idx[0]].x_end+1; + } + for (i = 1; i < nw; i++) { //utilize the the start pos of next window in backward + ///find the first matched window, which should not be the first window + ///the pre-window of this matched window must be unmatched + if(w_idx[i] != (uint64_t)-1 && w_idx[i-1] == (uint64_t)-1) { + w_s = z->w_list.a[w_idx[i]].x_start; mm_aln -= (w_s-mm_ws); + ///check if the start pos of this matched window has been calculated + if(z->w_list.a[w_idx[i]].clen == 0) { + p = &(z->w_list.a[w_idx[i]]); + gen_backtrace_adv(p, z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, y_strand, y_id); + assert(p->error != -1); + p->y_end += p->extra_begin; + } + real_y_start = p->y_start; + + ///the end pos for pre window is real_y_start - 1 + total_y_end = real_y_start - 1; + ///find the unmatched window on the left of current matched window + ///k starts from i - 1 + for (k = i - 1; k >= 0 && w_idx[k] == (uint64_t)-1 && total_y_end > 0; k--) { + w_e = w_s - 1; + w_id = get_win_id_by_e(z, w_e, block_s, &w_s); + assert(w_id == k); + x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; + if(aln_wlst_adv(z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, + y_strand, y_id, x_start, x_end, total_y_end+1-x_len, block_s, e_rate, 1)) { + p = &(z->w_list.a[z->w_list.n-1]); + p->y_start -= p->extra_begin; ///y_start has no shift, but y_end has shift + w_idx[k] = z->w_list.n - 1; + mm_aln += x_len; + // if(is_sort && (*is_sort) && z->w_list.n > 1 && p->x_start < z->w_list.a[z->w_list.n-2].x_start) (*is_sort) = 0; + } else { + break; + } + total_y_end = p->y_start - 1; + } + if(!simi_pass(ovl, mm_aln, sec_check, ovlp_cut, NULL)) break; + } + if(w_idx[i] != (uint64_t)-1) mm_ws = z->w_list.a[w_idx[i]].x_end+1; + } + if(i < nw) return 0; + } else {//sorted + a_nw = z->w_list.n; mm_ws = z->x_pos_s; + for (i = 0, cs = z->x_pos_s; i < a_nw; i++) { + p = &(z->w_list.a[i]); + w_s = p->x_start; mm_aln -= (w_s-mm_ws); + ///check if the start pos of this matched window has been calculated + if((w_s > cs) && (p->clen == 0)) { + gen_backtrace_adv(p, z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, y_strand, y_id); + assert(p->error != -1); + p->y_end += p->extra_begin; + } + real_y_start = p->y_start; + ///the end pos for pre window is real_y_start - 1 + total_y_end = real_y_start - 1; + while ((w_s > cs) && (total_y_end > 0)) { + w_e = w_s - 1; + w_id = get_win_id_by_e(z, w_e, block_s, &w_s); + x_start = w_s; x_end = w_e; x_len = x_end + 1 - x_start; + if(aln_wlst_adv(z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, + y_strand, y_id, x_start, x_end, total_y_end+1-x_len, block_s, e_rate, 1)) { + p = &(z->w_list.a[z->w_list.n-1]); + p->y_start -= p->extra_begin; ///y_start has no shift, but y_end has shift + mm_aln += x_len; + // if(is_sort && (*is_sort) && z->w_list.n > 1 && p->x_start < z->w_list.a[z->w_list.n-2].x_start) (*is_sort) = 0; + } else { + break; + } + total_y_end = p->y_start - 1; + } + if(!simi_pass(ovl, mm_aln, sec_check, ovlp_cut, NULL)) break; + mm_ws = cs = z->w_list.a[i].x_end+1; + } + if(a_nw < (int64_t)z->w_list.n) { + srt = 0; if(is_sort) (*is_sort) = 0; + } + if(i < a_nw) return 0; + } + + if(e_rate_final) { + /** + if(simi_pass(ovl, z->align_length, 0, &e_rate)) { + a_nw = z->w_list.n; + for (i = 0; i < a_nw; i++) { + p = &(z->w_list.a[i]); + ///check if the cigar of this window has been got + if(p->clen == 0) { + gen_backtrace_adv(p, z, rref, hpc_g, uref, qstr, tstr, tstr_1, dumy, y_strand, y_id); + assert(p->error != -1); + } else { + p->y_end -= p->extra_begin; + } + } + if(!srt) radix_sort_window_list_xs_srt(z->w_list.a, z->w_list.a + z->w_list.n); + ///note: this function will change tstr/qstr + error_rate = non_trim_error_rate(z, rref, uref, v_idx, dumy, g_read, e_rate, block_s); + z->is_match = 0;///must be here; + + if (error_rate <= e_rate_final) { + overlap_list->mapped_overlaps_length += ovl; + z->is_match = 1; append_unmatched_wins(z, block_s); + if(rref) { + calculate_boundary_cigars(z, rref, dumy, g_read, e_rate); + } else { + calculate_ul_boundary_cigars(z, uref, dumy, g_read, e_rate, block_s); + } + // assert(get_num_wins(z->x_pos_s, z->x_pos_e+1, block_s)==(int64_t)z->w_list.n); + // assert((int64_t)z->x_pos_s==z->w_list.a[0].x_start && + // (int64_t)z->x_pos_e==z->w_list.a[z->w_list.n-1].x_end); + } else if (error_rate <= e_rate_final * 1.5) { + z->is_match = 3; + } + } + **/ + return 1; + } else { + return 1; + } + return 0; +} + +uint64_t col_errors(overlap_region *z) +{ + uint64_t i, e = 0; + for (i = 0; i < z->w_list.n; i++) e += z->w_list.a[i].error; + return e; +} + + +void ul_lalign_hpc(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, char *qstr, + uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, + haplotype_evdience_alloc* hap, kvec_t_u64_warp* v_idx, kvec_t_u32_warp* q_idx, + double e_rate, double eh_rate, int64_t wl, void *km) +{ + uint64_t i, qhl, bs, k, ovl, whl; Window_Pool w; double err; overlap_region t; overlap_region *z; + whl = MIN((((double)THRESHOLD_MAX_SIZE)/eh_rate), WINDOW); + ol->mapped_overlaps_length = 0; + if(ol->length <= 0) return; + + ///hpc alignment + ///init hpc seq + qhl = update_ol_track(ol, cl, uref->hpc_g, uref, 1, ql, qstr, q_idx); + gen_hpc_str(qstr, ql, qu, &qhl); + ///verify hpc seq + clear_Correct_dumy(dumy, ol, km); err = eh_rate; + init_Window_Pool(&w, qhl, whl, (int)(1.0/err)); + bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(tu, bs<<1); + for (i = k = 0; i < ol->length; i++) { + if(!align_ul_ed_post(&(ol->list[i]), uref, uref->hpc_g, qu->seq, tu->seq, tu->seq+bs, dumy, err, w.window_length, OVERLAP_THRESHOLD_FILTER_HPC, km)) { + continue; + } + // fprintf(stderr, "+++[M::%s] yid::%u, x::[%u, %u), y::[%u, %u), aln::%u, err::%lu\n", __func__, ol->list[i].y_id, + // ol->list[i].x_pos_s, ol->list[i].x_pos_e+1, ol->list[i].y_pos_s, ol->list[i].y_pos_e+1, + // ol->list[i].align_length, col_errors(&(ol->list[i]))); + if(k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + k++; + } + ol->length = k; + if(ol->length <= 0) return; + + + ///base alignment + update_ol_track(ol, cl, NULL, uref, 1, ql, NULL, NULL); + resize_UC_Read(qu, ql); qu->length = ql; memcpy(qu->seq, qstr, ql); + clear_Correct_dumy(dumy, ol, km); err = e_rate; + init_Window_Pool(&w, ql, wl, (int)(1.0/err)); + bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(tu, bs<<1); + for (i = 0; i < ol->length; i++) { + z = &(ol->list[i]); ovl = z->x_pos_e+1-z->x_pos_s; + if(!align_ul_ed_post(z, uref, NULL, qu->seq, tu->seq, tu->seq+bs, dumy, err, w.window_length, -1, km)) { + continue; + } + // fprintf(stderr, "---[M::%s] yid::%u, x::[%u, %u), y::[%u, %u), aln::%u, err::%lu\n", __func__, ol->list[i].y_id, + // ol->list[i].x_pos_s, ol->list[i].x_pos_e+1, ol->list[i].y_pos_s, ol->list[i].y_pos_e+1, + // ol->list[i].align_length, col_errors(&(ol->list[i]))); + if(uref && simi_pass(ovl, z->align_length, uref?1:0, -1, NULL)) { + z->is_match = 3; ol->mapped_overlaps_length += z->align_length; + } + } + + if(uref && ol->mapped_overlaps_length > 0) { + set_herror_win(ol, dumy, v_idx, err, ql, w.window_length); + } + + double e_max = err*1.5, rr; + for (i = k = 0; i < ol->length; i++) { + z = &(ol->list[i]); ovl = z->x_pos_e + 1 - z->x_pos_s; + rr = gen_extend_err(z, uref, NULL, NULL, qu->seq, tu->seq, tu->seq+bs, + dumy, v_idx?v_idx->a.a:NULL, w.window_length, -1, err, (e_max+0.000001), NULL); + z->is_match = 0;///must be here; + if (rr <= err) { + for (k = 0; k < z->w_list.n; k++) { + if(z->w_list.a[k].clen) continue; + gen_backtrace_adv(&(z->w_list.a[k]), z, NULL, NULL, uref, qu->seq, tu->seq, tu->seq+bs, + dumy, z->y_pos_strand, z->y_id); + } + + ol->mapped_overlaps_length += ovl; k++; + z->is_match = 1; append_unmatched_wins(z, w.window_length); + calculate_ul_boundary_cigars(z, uref, dumy, qu, err, w.window_length); + } else if (rr <= e_max) { + z->is_match = 3; + } + } + + partition_ul_overlaps_advance(ol, uref, qu, tu, dumy, hap, 1, err, w.window_length, km); + + // recalcate_window(overlap_list, R_INF, g_read, dumy, overlap_read); + // partition_overlaps(overlap_list, R_INF, g_read, dumy, hap, force_repeat); + // recalcate_window_ul_advance(overlap_list, uref, g_read, dumy, overlap_read, max_ov_diff_ec, w_inf.window_length, km); + // recalcate_window_advance(overlap_list, NULL, uref, g_read, dumy, overlap_read, v_idx, w_inf.window_length, max_ov_diff_ec, max_ov_diff_ec); + /** + refine_ed_aln(overlap_list, NULL, uref, g_read, dumy, overlap_read, v_idx, w_inf.window_length, max_ov_diff_ec, max_ov_diff_ec); + **/ + // fprintf(stderr, "[M::%s-beg] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, + // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); + ///after this function, overlap_list is sorted by x_pos_e; used for g_chain + /** + partition_ul_overlaps_advance(overlap_list, uref, g_read, overlap_read, dumy, hap, force_repeat, max_ov_diff_ec, w_inf.window_length, km); + **/ + // print_ovlp_occ_stat(overlap_list, g_read->length, 1); + // print_ovlp_occ_stat(overlap_list, g_read->length, 2); + // fprintf(stderr, "[M::%s-end] occ[0]->%lu, occ[1]->%lu, occ[2]->%lu, occ[3]->%lu\n", __func__, + // ovlp_occ(overlap_list, 0), ovlp_occ(overlap_list, 1), ovlp_occ(overlap_list, 2), ovlp_occ(overlap_list, 3)); + // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1176); + // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1167); + // debug_phasing_status(overlap_list, uref->ug, 0, hap, g_read, 20, 1170); + /** + + + if(is_consensus) + { + generate_consensus(overlap_list, R_INF, g_read, dumy, g, DAGCon, current_cigar, second_round); + } + + + (*fully_cov) = check_if_fully_covered(overlap_list, R_INF, g_read, dumy, g, abnormal); + **/ +} + +// void ul_phase(overlap_region *oa, int64_t on, uint64_t *idx, uint64_t *buf) +// { +// int64_t i, oi; overlap_region *z; +// for (i = 0; i < on; i++) { +// oi = (uint32_t)idx[i]; z = &(oa[oi]); +// if(z->is_match != 1) continue; +// } +// } + +inline uint32_t cigar_check_dbg(char *pstr, char *tstr, bit_extz_t *ez) +{ + int32_t pi = ez->ps, ti = ez->ts, err = 0; uint32_t ci = 0, cl, k; uint16_t c; + while (ci < ez->cigar.n) { + ci = pop_trace(&(ez->cigar), ci, &c, &cl); + // fprintf(stderr, "# %u = %u, cigar_n::%u\n", c, cl, (uint32_t)ez->cigar.n); + if(c == 0) { + for (k=0;(kerr) { + fprintf(stderr, "ERROR-err, err::%d, ez->err::%d\n", err, ez->err); + return 0; + } + return 1; +} + +int64_t wcigar_check(window_list *p, window_list_alloc *z, char *qstr, char *tstr) +{ + bit_extz_t ez; + ez.cigar.a = z->c.a+p->cidx; ez.cigar.n = ez.cigar.m = p->clen; + ez.ps = p->y_start; ez.pe = p->y_end; + ez.ts = p->x_start; ez.te = p->x_end; + ez.err = p->error; + // prt_cigar(ez.cigar.a, ez.cigar.n); + return cigar_check_dbg(tstr, qstr, &ez); +} + +void verify_aln(int32_t sid, overlap_region *z, UC_Read* qu, UC_Read* tu, All_reads *rref, hpc_t *hpc_g, const ul_idx_t *uref) +{ + uint64_t tl, tid = z->y_id, rev = z->y_pos_strand, i; char *tstr, *qstr; window_list *p; + if(hpc_g) tl = hpc_len(*hpc_g, tid); + else if(uref) tl = uref->ug->u.a[tid].len; + else tl = Get_READ_LENGTH((*rref), tid); + + qstr = qu->seq; resize_UC_Read(tu, tl); + if(rref) { + recover_UC_Read_sub_region(tu->seq, 0, tl, rev, rref, tid); tstr = tu->seq; + } else { + tstr = return_str_seq_exz(tu->seq, 0, tl, rev, hpc_g, uref, tid); + } + + for (i = 0; i < z->w_list.n; i++) { + p = &(z->w_list.a[i]); + if(p->y_end == -1) continue; + if(!wcigar_check(p, &(z->w_list), qstr, tstr)) break; + } + if(i < z->w_list.n) { + fprintf(stderr, "sid::%d, tid::%lu, i::%lu, qs::%d, qe::%d, ts::%d, te::%d, err::%d\n", sid, tid, i, + p->x_start, p->x_end, p->y_start, p->y_end, p->error); + prt_cigar(z->w_list.c.a+p->cidx, p->clen); + fprintf(stderr, "[tstr::[%u, %u]] %.*s\n", z->y_pos_s, z->y_pos_e, p->y_end+1-p->y_start, tstr+p->y_start); + fprintf(stderr, "[qstr::[%u, %u]] %.*s\n", z->x_pos_s, z->x_pos_e, p->x_end+1-p->x_start, qstr+p->x_start); + exit(0); + } +} + + +void ul_lalign_old_ed(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, char *qstr, + uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, + haplotype_evdience_alloc* hap, kvec_t_u64_warp* v_idx, + double e_rate, int64_t wl, uint64_t is_base, void *km) +{ + uint64_t i, bs, k, ovl/**, on**/; Window_Pool w; double err; + /**int64_t sc;**/ overlap_region t; overlap_region *z; + ol->mapped_overlaps_length = 0; + if(ol->length <= 0) return; + + ///base alignment + clear_Correct_dumy(dumy, ol, km); err = e_rate; + init_Window_Pool(&w, ql, wl, (int)(1.0/err)); + bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(tu, bs<<1); + + if(is_base) { + resize_UC_Read(qu, ql); qu->length = ql; memcpy(qu->seq, qstr, ql); + for (i = 0; i < ol->length; i++) { + z = &(ol->list[i]); ovl = z->x_pos_e+1-z->x_pos_s; + if(!align_ul_ed_post(z, uref, NULL, qu->seq, tu->seq, tu->seq+bs, dumy, err, w.window_length, -1, km)) { + continue; + } + if(uref && simi_pass(ovl, z->align_length, uref?1:0, -1, NULL)) { + z->is_match = 3; ol->mapped_overlaps_length += z->align_length; + } + } + + if(uref && ol->mapped_overlaps_length > 0) { + set_herror_win(ol, dumy, v_idx, err, ql, w.window_length); + } + + double e_max = err*1.5, rr; int64_t re; + for (i = k = 0; i < ol->length; i++) { + z = &(ol->list[i]); ovl = z->x_pos_e + 1 - z->x_pos_s; + rr = gen_extend_err(z, uref, NULL, NULL, qu->seq, tu->seq, tu->seq+bs, + dumy, v_idx?v_idx->a.a:NULL, w.window_length, -1, err, (e_max+0.000001), &re); + z->is_match = 0;///must be here; + if (rr <= err) { + if(k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + ol->list[k].is_match = 1; ol->list[k].non_homopolymer_errors = re; + k++; + } + } + + ol->length = k; + // fprintf(stderr, "+[M::%s] on::%lu\n", __func__, ol->length); + if(ol->length <= 0) return; + } else { + // fprintf(stderr, "-[M::%s] on::%lu\n", __func__, ol->length); + if(ol->length <= 1) return; + // for (i = 0; (i < ol->length) && (ol->list[i].is_match == 1); i++); on = i; + // if(on <= 1) return; + // kv_resize(uint64_t, v_idx->a, (on<<1)); v_idx->a.n = on; + // for (i = 0; i < on; i++) { + // sc = ol->list[i].x_pos_e+1-ol->list[i].x_pos_s; + // sc -= ((int64_t)(ol->list[i].non_homopolymer_errors*ERROR_RATE)); + // if(sc < 0) sc = 0; + // v_idx->a.a[i] = sc; v_idx->a.a[i] <<= 32; v_idx->a.a[i] += i; + // } + // radix_sort_bc64(v_idx->a.a, v_idx->a.a+on); + // for (i = 0; i < on; i++) { + // ol->list[i].non_homopolymer_errors = 0; + // k = ((uint32_t)v_idx->a.a[i]); + // v_idx->a.a[k]<<=32; v_idx->a.a[k]>>=32; v_idx->a.a[k]|=i; + // } + // ul_phase(ol->list, on, v_idx->a.a, v_idx->a.a+on); + + + for (i = 0; i < ol->length; i++) { + z = &(ol->list[i]); ovl = z->x_pos_e+1-z->x_pos_s; z->is_match = 1; + for (k = 0; k < z->w_list.n; k++) { + if(z->w_list.a[k].clen) continue; + gen_backtrace_adv(&(z->w_list.a[k]), z, NULL, NULL, uref, qu->seq, tu->seq, tu->seq+bs, + dumy, z->y_pos_strand, z->y_id); + } + ol->mapped_overlaps_length += ovl; + append_unmatched_wins(z, w.window_length); + calculate_ul_boundary_cigars(z, uref, dumy, qu, err, w.window_length); + } + partition_ul_overlaps_advance(ol, uref, qu, tu, dumy, hap, 1, err, w.window_length, km); + } +} + +inline uint64_t scale_ed_thre(uint32_t err, uint32_t max_err) +{ + uint64_t bd = (err<<1)+1, w; + w = (bd>>bitw); w <<= bitw; if(w < bd) w += bitwbit; + err = (w-1)>>1; if(err > max_err) err = max_err; + return err; +} + + +///[qs, qe) +int64_t update_semi_coord(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, overlap_region *z, +int64_t qs, int64_t qe, int64_t thre, int64_t *ts, int64_t *te, int64_t *aux_beg) +{ + int64_t ql = qe - qs, aln_l, t_tot_l, id = z->y_id, aux_end, tl; + (*ts) = (qs - z->x_pos_s) + z->y_pos_s; + (*ts) += y_start_offset(qs, &(z->f_cigar)); + aln_l = ql + (thre<<1); + if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); + else if(uref) t_tot_l = uref->ug->u.a[id].len; + else t_tot_l = Get_READ_LENGTH((*rref), id); + if(!init_waln(thre, (*ts), t_tot_l, aln_l, aux_beg, &aux_end, ts, &tl)) { + (*ts) = (*te) = (*aux_beg) = -1; + return 0; + } + (*te) = (*ts) + tl; + return 1; +} + + +///[qs, qe) +int64_t update_semi_non_retrieve_coord(overlap_region *z, int64_t qs, int64_t qe, int64_t thre, int64_t t_tot_l, int64_t *ts, int64_t *te, int64_t *aux_beg) +{ + int64_t ql = qe - qs, aln_l, aux_end, tl; + (*ts) = (qs - z->x_pos_s) + z->y_pos_s; + (*ts) += y_start_offset(qs, &(z->f_cigar)); + aln_l = ql + (thre<<1); + + if(!init_waln(thre, (*ts), t_tot_l, aln_l, aux_beg, &aux_end, ts, &tl)) { + (*ts) = (*te) = (*aux_beg) = -1; + return 0; + } + (*te) = (*ts) + tl; + return 1; +} + + +void adjust_ext_offset(int64_t *qs, int64_t *qe, int64_t *ts, int64_t *te, int64_t ql, int64_t tl, int64_t thre, int64_t mode) +{ + int64_t qoff, toff; + if(mode == 1) {///forward extension + qoff = ql - (*qs); toff = tl - (*ts); + if(qoff <= toff) { + (*qe) = ql; (*te) = (*ts) + qoff + thre; + } else { + (*te) = tl; (*qe) = (*qs) + toff + thre; + } + } else if(mode == 2) {///backward extension + qoff = (*qe); toff = (*te); + if(qoff <= toff) { + (*qs) = 0; (*ts) = (*te) - qoff - thre; + } else { + (*ts) = 0; (*qs) = (*qe) - toff - thre; + } + } + if((*qs) < 0) (*qs) = 0; + if((*ts) < 0) (*ts) = 0; + if((*qe) > ql) (*qe) = ql; + if((*te) > tl) (*te) = tl; +} + +void adjust_specific_ext_offset(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, bit_extz_t *exz, char* qstr, UC_Read *tu, +int64_t *qs0, int64_t *qe0, int64_t *ts0, int64_t *te0, int64_t ql, int64_t tl, int64_t wl, int64_t *mode) +{ + ///[qs, qe) + if((*mode) != 1 && (*mode) != 2) return; + int64_t qs = *qs0, qe = *qe0, ts = *ts0, te = *te0, k, update, wid, we, ws, sl, gq, gt, gg, min_g = INT32_MAX, min_id = -1, gl; + adjust_ext_offset(&qs, &qe, &ts, &te, ql, tl, 0, *mode); + if((*mode) == 1) {///forward extension + //qs0 and ts0 are fixed; te0 = -1, qe0 is unreliable + if(qe > (*qe0)) { + we = (*qe0); we/=wl; we *= wl; we +=wl; we--; ///next window + for (k = 0; we < qe && k < ext_w; we+=wl) {//[ws, we]; [qs, qe) + wid = get_win_id_by_e(z, we, wl, NULL); + if(z->w_list.a[wid].y_end == -1) continue;//unmapped + if(z->w_list.a[wid].x_end < (*qs0)) continue; + if(z->w_list.a[wid].y_end < (*ts0)) continue; + sl = z->w_list.a[wid].x_end+1-z->w_list.a[wid].x_start; + if(z->w_list.a[wid].error > (sl/A_L)) continue; + gq = z->w_list.a[wid].x_end-(*qs0); + gt = z->w_list.a[wid].y_end-(*ts0); + gl = MIN(gq, gt); gl/=16; if(gl <= 0) gl = 1; + gg = (gq>=gt)?(gq-gt):(gt-gq); gg /= gl; + update = 0; + if(min_g>gg) { + update = 1; + } else if((min_g==gg)&&(z->w_list.a[min_id].error>z->w_list.a[wid].error)) { + update = 1; + } + if(update) { + min_g = gg; min_id = wid; + } + k++; + } + } + if(min_id >= 0) { + (*qe0) = z->w_list.a[min_id].x_end+1; + if(((*qe0)+wl) >= qe) { + (*qe0) = qe; (*te0) = te; ///still extension + return; + } + (*te0) = z->w_list.a[min_id].y_end+1; (*mode) = 0;///global + } else { + (*qe0) = qe; (*te0) = te; ///still extension + } + } else if((*mode) == 2) {///backward extension + //qe0 and te0 are fixed; ts0 = -1, qs0 is unreliable + if(qs < (*qs0)) { + ws = (*qs0)-1; ws/=wl; ws*=wl; + for (k = 0; ws >= qs && k < ext_w; ws-=wl) {//[ws, we]; [qs, qe) + wid = get_win_id_by_s(z, ws, wl, NULL); + if(z->w_list.a[wid].y_end == -1) continue;//unmapped + if(z->w_list.a[wid].x_start >= (*qe0)) continue; + if(z->w_list.a[wid].y_start >= (*te0)) continue; + sl = z->w_list.a[wid].x_end+1-z->w_list.a[wid].x_start; + if(z->w_list.a[wid].error > (sl/A_L)) continue; + gq = (*qe0) - z->w_list.a[wid].x_start; + gt = (*te0) - z->w_list.a[wid].y_start; + gl = MIN(gq, gt); gl/=16; if(gl <= 0) gl = 1; + gg = (gq>=gt)?(gq-gt):(gt-gq); gg /= gl; + update = 0; + if(min_g>gg) { + update = 1; + } else if((min_g==gg)&&(z->w_list.a[min_id].error>z->w_list.a[wid].error)) { + update = 1; + } + if(update) { + min_g = gg; min_id = wid; + } + k++; + } + } + if(min_id >= 0) { + (*qs0) = z->w_list.a[min_id].x_start; + if((qs+wl) >= (*qs0)) { + (*qs0) = qs; (*ts0) = ts; ///still extension + return; + } + (*ts0) = z->w_list.a[min_id].y_start; (*mode) = 0;///global + } else { + (*qs0) = qs; (*ts0) = ts; ///still extension + } + } +} + +int64_t cal_exz_infi(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, bit_extz_t *exz, char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t thre, int64_t q_tot_l, int64_t mode) +{ + clear_align(*exz); + int64_t aux_beg = 0, bd = (((thre)<<1)+1), ql, tl, t_tot_l = -1; int32_t nword = ((bd>>bitw)+(!!(bd&bitz))); + char *q_string, *t_string; int32_t rev = z->y_pos_strand, id = z->y_id; ql = qe - qs; + if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); + else if(uref) t_tot_l = uref->ug->u.a[id].len; + else t_tot_l = Get_READ_LENGTH((*rref), id); + + if(mode == 3) { + update_semi_coord(uref, hpc_g, rref, z, qs, qe, thre, &ts, &te, &aux_beg); + } else if(mode == 1 || mode == 2) { + adjust_ext_offset(&qs, &qe, &ts, &te, q_tot_l, t_tot_l, thre, mode); + } + + if((qe > qs) && (te > ts) && (ts != -1) && (te != -1)) { + ql = qe - qs; q_string = qstr + qs; + tl = te - ts; resize_UC_Read(tu, tl); + // fprintf(stderr, "q::[%ld, %ld), t::[%ld, %ld), thre::%ld, t_tot_l::%ld\n", qs, qe, ts, te, thre, t_tot_l); + if(rref) { + recover_UC_Read_sub_region(tu->seq, ts, tl, rev, rref, id); t_string = tu->seq; + } else { + t_string = return_str_seq_exz(tu->seq, ts, tl, rev, hpc_g, uref, id); + } + // fprintf(stderr, ", nword::%d", nword); + // if(ql < 0) fprintf(stderr, "qs::%ld, qe::%ld\n", qs, qe); + // return 0; + if(nword <= 1) { + if(mode == 0) { //global + ed_band_cal_global_64_w_trace(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 1) {///forward extension + // fprintf(stderr, "q::[%ld, %ld), t::[%ld, %ld), thre::%ld\n", qs, qe, ts, te, thre); + ed_band_cal_extension_64_0_w_trace(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 2) {///backward extension + ed_band_cal_extension_64_1_w_trace(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 3) {//semi-global + ed_band_cal_semi_64_w_absent_diag_trace(t_string, tl, q_string, ql, thre, aux_beg, exz); + } + } else if(nword == 2) { + if(mode == 0) { //global + ed_band_cal_global_128_w_trace(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 1) {///forward extension + ed_band_cal_extension_128_0_w_trace(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 2) {///backward extension + ed_band_cal_extension_128_1_w_trace(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 3) {//semi-global + ed_band_cal_semi_128_w_absent_diag_trace(t_string, tl, q_string, ql, thre, aux_beg, exz); + } + } else { + if(mode == 0) { //global + ed_band_cal_global_infi_w_trace(t_string, tl, q_string, ql, thre, &nword, exz); + } else if(mode == 1) {///forward extension + ed_band_cal_extension_infi_0_w_trace(t_string, tl, q_string, ql, thre, &nword, exz); + } else if(mode == 2) {///backward extension + ed_band_cal_extension_infi_1_w_trace(t_string, tl, q_string, ql, thre, &nword, exz); + } else if(mode == 3) {//semi-global + ed_band_cal_semi_infi_w_absent_diag_trace(t_string, tl, q_string, ql, thre, aux_beg, &nword, exz); + } + } + if(is_align(*exz)) { + + return 1; + } + return 0; + } + return 0; +} + +void hc_aln_exz(overlap_region *z, Candidates_list *cl, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, +char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t estimate_err, +int64_t mode, int64_t wl, bit_extz_t *exz, int64_t q_tot, double e_rate, int64_t maxl, int64_t maxe) +{ + clear_align(*exz); + int64_t thre, ql = qe - qs, thre0, t_tot, id = z->y_id; + if(((ts == -1) && (te == -1))) mode = 3;///set to semi-global + + if(mode == 1 || mode == 2) { + if(hpc_g) t_tot = hpc_len(*hpc_g, id); + else if(uref) t_tot = uref->ug->u.a[id].len; + else t_tot = Get_READ_LENGTH((*rref), id); + // fprintf(stderr, "\n+[M::%s::ql->%ld::tl->%ld::mode->%ld] q::[%ld, %ld), t::[%ld, %ld), zx[%d, %d), zy[%d, %d)\n", + // __func__, q_tot, t_tot, mode, qs, qe, ts, te, z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1); + ///find a aligned window >= qe to convert extension to global; or do extension directly + adjust_specific_ext_offset(z, uref, hpc_g, rref, exz, qstr, tu, &qs, &qe, &ts, &te, q_tot, t_tot, wl, &mode); + // fprintf(stderr, "-[M::%s::ql->%ld::tl->%ld::mode->%ld] q::[%ld, %ld), t::[%ld, %ld), zx[%d, %d), zy[%d, %d)\n", + // __func__, q_tot, t_tot, mode, qs, qe, ts, te, z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1); + } + + // fprintf(stderr, "[M::%s::ql::%ld] qs::%ld, qe::%ld, ts::%ld, te::%ld, mode::%ld, estimate_err::%ld, e_rate::%f", + // __func__, ql, qs, qe, ts, te, mode, estimate_err, e_rate); + + if(ql <= maxl && (estimate_err*1.2) <= maxe) { + thre = scale_ed_thre(estimate_err, maxe); if(thre > ql) thre = ql; + if(cal_exz_infi(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, thre, q_tot, mode)) { + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(+)\n", exz->err, exz->thre, thre); + return; + } + + thre0 = thre; thre = ql*e_rate; + thre = scale_ed_thre(thre, maxe); if(thre > ql) thre = ql; + if(thre > thre0) { + if(cal_exz_infi(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, thre, q_tot, mode)) { + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); + return; + } + } + + thre0 = thre; thre <<= 1; + thre = scale_ed_thre(thre, maxe); if(thre > ql) thre = ql; + if(thre > thre0) { + if(cal_exz_infi(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, thre, q_tot, mode)) { + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); + return; + } + } + + thre0 = thre; thre = ql*0.51; + thre = scale_ed_thre(thre, maxe); if(thre > ql) thre = ql; + if(thre > thre0) { + if(cal_exz_infi(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, thre, q_tot, mode)) { + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); + return; + } + } + } + // fprintf(stderr, ", err::%d, thre::%d\n", INT32_MAX, exz->thre); + // anchor_aln(z, cl, uref, hpc_g, rref, qstr, tu, qs, qe, ts, te, thre, mode, wl, exz, q_tot, A_L); + +} + +void sub_ciagar_gen(overlap_region *z, Candidates_list *cl, uint64_t s, uint64_t e, uint64_t wl, +const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, double e_rate, +int64_t ql, uint64_t rid) +{ + uint64_t qs, qe, sid, eid, k, l, m, tot_e, c_e; int64_t q[2], t[2], o[2], mode, kocc; + qs = (s/wl)*wl; if(qs < z->x_pos_s) qs = z->x_pos_s; if(qs > z->x_pos_e) return; + qe = (e/wl)*wl; if(qe < e) qe += wl; if(qe > z->x_pos_e+1) qe = z->x_pos_e+1; + if(qe <= 0) return; + sid = get_win_id_by_s(z, qs, wl, NULL); + eid = get_win_id_by_e(z, qe-1, wl, NULL) + 1;///must qe-1 instead of qe!!!!!! + if(sid >= eid) return; + // fprintf(stderr, "\n***[M::%s::rid->%lu] s::%lu, e::%lu, n_qs::%lu, n_qe::%lu, z::[%u, %u), sid::%lu, eid::%lu, w_list.n::%lu\n", + // __func__, rid, s, e, qs, qe, z->x_pos_s, z->x_pos_e+1, sid, eid, (uint64_t)z->w_list.n); + for (k = sid+1, l = sid; k <= eid; k++) {//[sid, eid) + if(k == eid || z->w_list.a[k].extra_end < 0) { + if(k - l > 1 || z->w_list.a[l].extra_end >= 0) { + q[0] = q[1] = t[0] = t[1] = -1; + o[0] = o[1] = -1; mode = -1; tot_e = 0; + if(z->w_list.a[l].extra_end < 0) { + q[0] = z->w_list.a[l].x_end+1; + if(z->w_list.a[l].y_end != -1) { + t[0] = z->w_list.a[l].y_end+1; + } + if(z->w_list.a[l].extra_end != INT16_MIN) { + o[0] = -z->w_list.a[l].extra_end; + } + } else {///first window + q[0] = qs; + if(z->w_list.a[l].y_end != -1) { + c_e = z->w_list.a[l].error; + } else { + c_e = z->w_list.a[l].x_end + 1 - z->w_list.a[l].x_start; + if(c_e > THRESHOLD_MAX_SIZE) c_e = THRESHOLD_MAX_SIZE; + } + tot_e += c_e; + } + + if(k > sid && k < eid && z->w_list.a[k].extra_end < 0) { + q[1] = z->w_list.a[k-1].x_end+1; + if(z->w_list.a[k].y_end != -1) { + // if(z->w_list.a[k-1].y_end == -1) { + // fprintf(stderr, "[M::%s::rid::%lu] k::%lu, sid::%lu, eid::%lu, k_y_end::%d, k-1_y_end::%d, xk[%d, %d)\n", + // __func__, rid, k, sid, eid, z->w_list.a[k].y_end, z->w_list.a[k-1].y_end, + // z->w_list.a[k].x_start, z->w_list.a[k].x_end+1); + // } + assert(z->w_list.a[k-1].y_end != -1); + t[1] = z->w_list.a[k-1].y_end+1; + } + if(z->w_list.a[k].extra_end != INT16_MIN) { + o[1] = -z->w_list.a[k].extra_end; + } + } else {///last window + q[1] = qe; + } + + if((t[0] != -1) && (t[1] != -1)) { + mode = 0;//global + } else if((t[0] != -1) && (t[1] == -1)) { + /**t[1] = z->y_pos_e+1;**/ mode = 1;///forward extension + } else if((t[0] == -1) && (t[1] != -1)) { + /**t[0] = z->y_pos_s;**/ mode = 2;///backward extension + } else { + mode = 3;//semi-global + } + + for (m = l+1; m < k; m++) { + if(z->w_list.a[m].y_end != -1) { + c_e = z->w_list.a[m].error; + } else { + c_e = z->w_list.a[m].x_end + 1 - z->w_list.a[m].x_start; + if(c_e > THRESHOLD_MAX_SIZE) c_e = THRESHOLD_MAX_SIZE; + } + tot_e += c_e; + } + // if(q[1] < q[0]) { + // fprintf(stderr, "[M::%s::ql::%lu] qs::%lu, qe::%lu, ts::%lu, te::%lu, mode::%ld, tot_e::%lu\n", + // __func__, q[1]-q[0], q[0], q[1], t[0], t[1], mode, tot_e); + // } + kocc = MAX(o[0], o[1]); if(kocc < 0) kocc = 1; + hc_aln_exz(z, cl, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], tot_e, mode, wl, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E); + + } + l = k; + } + } +} + + +uint64_t cigar_gen(overlap_region *z, Candidates_list *cl, ul_ov_t *ov, uint64_t on, uint64_t qn, uint64_t wl, +const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, double e_rate, +int64_t ql, uint64_t rid, ul_ov_t *des) +{ + if(on <= 0) return 0; + uint64_t i; + // des[0] = ov[0]; + // for (i = m = 1; i < on; i++) { + // fusion_merge(); + // } + + + for (i = 0; i < on; i++) { + assert((i<=0)||(ov[i].qs > ov[i-1].qe)); + sub_ciagar_gen(z, cl, ov[i].qs, ov[i].qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, rid); + } + return on; + // uint64_t i, qs = (uint64_t)-1, qe = (uint64_t)-1; + // for (i = 0; i < on && ov[i].qn == qn; i++) { + // assert((i<=0)||(ov[i].qs >= ov[i-1].qe)); + // if(ov[i].qs <= qe && qe != (uint64_t)-1) { + // qe = ov[i].qe; + // } else { + // if(qs != (uint64_t)-1) sub_ciagar_gen(z, cl, qs, qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, rid); + // qs = ov[i].qs; qe = ov[i].qe; + // } + // } + // if(qs != (uint64_t)-1) sub_ciagar_gen(z, cl, qs, qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, rid); +} + + + +int64_t push_adp_k_hits(Candidates_list *cl, int64_t cln, uint64_t qs, uint64_t qe, uint64_t ts, uint64_t te, uint64_t readID, int64_t ci, int64_t dbgid) +{ + int64_t k = ci, m = -1; k_mer_hit *p = NULL; + if(cl->length > cln) { + m = cl->length-1; assert(is_alnw(cl->list[m])); + } + for (; k < cln && cl->list[k].readID == readID && cl->list[k].self_offset < qs; k++) { + p = &(cl->list[k]); + // fprintf(stderr, "[M::%s::] p->q::%ld, p->t::%ld\n", __func__, p->self_offset, p->offset); + if(p->offset >= ts) continue; + if((m>=0) && ((cl->list[m].offset >= p->offset) || (cl->list[m].self_offset >= p->self_offset))) { + continue; + } + kv_pushp_cl(k_mer_hit, (*cl), &p); *p = cl->list[k]; p->readID = p->cnt; + // if(dbgid == 109111 || dbgid == 75436) { + // fprintf(stderr, "[M::%s::k->%ld] self_offset::%u, offset::%u, cl->length::%lld, cln::%ld, p->readID::%u\n", + // __func__, k, cl->list[k].self_offset, cl->list[k].offset, cl->length, cln, p->readID); + // } + } + if(qs == (uint64_t)-1 || qe == (uint64_t)-1) return k; + // if(!(k >= cln || cl->list[k].self_offset >= qe)) { + // fprintf(stderr, "[M::%s::] k::%ld, self_offset::%u, offset::%u\n", + // __func__, k, cl->list[k].self_offset, cl->list[k].offset); + // } + assert(k >= cln || cl->list[k].readID != readID || cl->list[k].self_offset >= qe); + ///push qs, ts + kv_pushp_cl(k_mer_hit, (*cl), &p); + p->readID = ((uint32_t)(0x7fffffff)); + p->cnt = (uint32_t)-1; p->strand = 0; + p->self_offset = qs; p->offset = ts; + + for (; k < cln && cl->list[k].readID == readID && cl->list[k].self_offset < qe; k++); + + ///push qe, te + kv_pushp_cl(k_mer_hit, (*cl), &p); + p->readID = ((uint32_t)(0x7fffffff)); + p->cnt = (uint32_t)-1; p->strand = 1; + p->self_offset = qe-1; p->offset = te-1; + return k; +} + +int64_t gen_weight_khits0(uint32_t qs, uint32_t qe, k_mer_hit *a, int64_t an, int64_t k, uint64_t dp)///[qs, qe) +{ + for (; k >= 0 && a[k].self_offset >= qs; k--); + for (k = ((k>=0)?k:0); k < an && a[k].self_offset < qe; k++) { + if((a[k].self_offset >= qs) && (a[k].self_offset < qe) && (!is_alnw(a[k]))) { + a[k].readID = dp; + } + } + return k; +} + +void gen_weight_khits(asg64_v* idx, k_mer_hit *a, int64_t an) +{ + int64_t i, idx_n = idx->n, dp, old_dp, beg, end, k; + // fprintf(stderr, "[M::%s::] idx->n::%ld\n", __func__, (int64_t)idx->n); + for (i = k = 0, dp = old_dp = 0, beg = 0, end = -1; i < idx_n; ++i) {///[beg, end) but coordinates in idx is [, ] + ///if idx->a.a[] is qe + old_dp = dp; + if ((idx->a[i]>>32)&1) { + --dp; end = (idx->a[i]>>33)+1; + }else { + //meet a new overlap; the overlaps are pushed by the x_pos_s + ++dp; end = (idx->a[i]>>33); + } + // fprintf(stderr, "[M::%s::] beg::%ld, end::%ld, old_dp::%ld\n", __func__, beg, end, old_dp); + if(end > beg) k = gen_weight_khits0(beg, end, a, an, k, old_dp); + beg = end; + } +} + +void prt_khit(Candidates_list *cl, overlap_region_alloc* ol, overlap_region *z, uint64_t utg_id, const char *cmd) +{ + uint64_t k, cid; int64_t i; + if(!z) { + for (k = 0; k < ol->length; k++) { + z = &(ol->list[k]); + if(z->y_id == utg_id) break; + } + } + if((z) || (z->y_id == utg_id)) { + fprintf(stderr, "[M::%s::cmd->%s] ******\n", __func__, (char *)cmd); + for (i = z->shared_seed, cid = cl->list[i].readID; i < cl->length && cl->list[i].readID == cid; i++) { + fprintf(stderr, "[M::%s::i->%lu] qoff::%u, toff::%u, cid::%lu, cl->length::%lld\n", __func__, i, + cl->list[i].self_offset, cl->list[i].offset, cid, cl->length); + } + } +} + +int64_t gen_cns_chain(overlap_region_alloc* ol, overlap_region *z, Candidates_list *cl, asg64_v* iidx, int64_t max_lgap, double sgap_rate, int64_t need_filter_khit) +{ + int64_t k, wn = z->w_list.n, aln_n, qs, qe, ts, te, ci, id, rcn = cl->length, kn; k_mer_hit *ka; + if(wn <= 0) return 0; + qs = qe = ts = te = -1; ci = z->shared_seed; id = cl->list[ci].readID; + for (k = aln_n = 0; k < wn; k++) { + if(z->w_list.a[k].extra_end < 0 && z->w_list.a[k].y_end != -1) {///anchor + if(qs == -1) { + qs = z->w_list.a[k].x_start; ts = z->w_list.a[k-1].y_end+1; + } + qe = z->w_list.a[k].x_end+1; te = z->w_list.a[k].y_end+1; + } else { + if(qs != -1) { + // if(z->y_id == 109111 || z->y_id == 75436) { + // fprintf(stderr, "\n[M::%s::] q::[%ld, %ld), t::[%ld, %ld), ci::%ld, cn::%lld\n", + // __func__, qs, qe, ts, te, ci, cl->length); + // } + ci = push_adp_k_hits(cl, rcn, qs, qe, ts, te, id, ci, z->y_id); + aln_n++;//[qs, qe); [ts, te) + } + qs = qe = ts = te = -1; + } + } + if(qs != -1) { + // if(z->y_id == 109111 || z->y_id == 75436) { + // fprintf(stderr, "\n[M::%s::] q::[%ld, %ld), t::[%ld, %ld), ci::%ld, cn::%lld\n", + // __func__, qs, qe, ts, te, ci, cl->length); + // } + ci = push_adp_k_hits(cl, rcn, qs, qe, ts, te, id, ci, z->y_id); + aln_n++;//[qs, qe); [ts, te) + } + // if(z->y_id == 109111 || z->y_id == 75436) { + // fprintf(stderr, "\n[M::%s::] q::[%ld, %ld), t::[%ld, %ld), ci::%ld, cn::%lld, rcn::%ld\n", + // __func__, qs, qe, ts, te, ci, cl->length, rcn); + // } + push_adp_k_hits(cl, rcn, (uint64_t)-1, (uint64_t)-1, (uint64_t)-1, (uint64_t)-1, id, ci, z->y_id); + + ka = cl->list+rcn; kn = cl->length-rcn; + // if(z->y_id == 66) { + // fprintf(stderr, "[M::%s::] kn::%ld, q_pos::%u, t_pos::%u\n", __func__, kn, ka[kn-1].self_offset, ka[kn-1].offset); + // } + // if(z->y_id == 109111 || z->y_id == 75436) { + // prt_khit(cl, ol, NULL, 109111, "sa"); + // } + if(iidx) gen_weight_khits(iidx, ka, kn); + // if(z->y_id == 109111 || z->y_id == 75436) { + // prt_khit(cl, ol, NULL, 109111, "sb"); + // } + if(need_filter_khit) { + kn = lchain_dp_trace(ka, kn, max_lgap, sgap_rate, SGAP); cl->length = rcn + kn; + } + cl->length = rcn; + return kn; +} + + +uint64_t cigar_gen_cns(overlap_region *z, Candidates_list *cl, ul_ov_t *ov, uint64_t on, uint64_t qn, uint64_t wl, +const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, double e_rate, +int64_t ql, uint64_t rid, asg64_v* iidx, ul_ov_t *des) +{ + if(on <= 0 || iidx->n <= 0) return 0; + uint64_t i; + for (i = 0; i < on; i++) { + assert((i<=0)||(ov[i].qs > ov[i-1].qe)); + sub_ciagar_gen(z, cl, ov[i].qs, ov[i].qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, rid); + } + return on; +} + +///[ys, ye) +uint64_t inline get_win_aln(overlap_region *z, uint64_t wid, int64_t *ys, int64_t *ye, int64_t *err) +{ + (*err) = -2; + if((wid > 0) && (z->w_list.a[wid].y_end != -1) && (z->w_list.a[wid-1].y_end != -1) && (z->w_list.a[wid].y_end > z->w_list.a[wid-1].y_end)) { + (*ys) = z->w_list.a[wid-1].y_end+1; + (*ye) = z->w_list.a[wid].y_end+1; + (*err) = z->w_list.a[wid].error; + return 1; + } + return 0; +} + +char* retrive_str_piece_exz(All_reads *rref, const ul_idx_t *uref, char *buf, int64_t s, int64_t l, int64_t rev, int64_t id) +{ + if(rref) recover_UC_Read_sub_region(buf, s, l, rev, rref, id); + else if(uref) retrieve_u_seq(NULL, buf, &(uref->ug->u.a[id]), rev, s, l, NULL); + else return NULL; + return buf; +} + +uint64_t k_hits_bcheck(All_reads *rref, const ul_idx_t *uref, overlap_region_alloc* ol, Candidates_list *cl, +uint64_t khit, uint64_t *a, uint64_t a_n, char* qstr, char *str0, char *str1) +{ + if(a_n < 2) return 1; + uint64_t k, e; char *ref0, *ref1; overlap_region *z; + + e = cl->list[(uint32_t)a[0]].offset; + if(e >= khit) e-=khit; + else return 0; + z = &(ol->list[cl->list[(uint32_t)a[0]].readID]); + ref0 = retrive_str_piece_exz(rref, uref, str0, e, khit, z->y_pos_strand, z->y_id); + // fprintf(stderr, "\n[M::%s::] qstr::%.*s\n", __func__, + // (int32_t)khit, qstr+cl->list[(uint32_t)a[0]].self_offset-khit); + // fprintf(stderr, "[M::%s::qoff->%u::toff->%u::%c] tstr0::%.*s\n", __func__, + // cl->list[(uint32_t)a[0]].self_offset, cl->list[(uint32_t)a[0]].offset, "+-"[z->y_pos_strand], (int32_t)khit, ref0); + + for (k = 1; k < a_n; k++) { + e = cl->list[(uint32_t)a[k]].offset; + if(e >= khit) e-=khit; + else return 0; + z = &(ol->list[cl->list[(uint32_t)a[k]].readID]); + ref1 = retrive_str_piece_exz(rref, uref, str1, e, khit, z->y_pos_strand, z->y_id); + // fprintf(stderr, "[M::%s::qoff->%u::toff->%u::%c] tstr1::%.*s\n", __func__, + // cl->list[(uint32_t)a[k]].self_offset, cl->list[(uint32_t)a[k]].offset, "+-"[z->y_pos_strand], (int32_t)khit, ref1); + if(memcmp(ref0, ref1, khit)) return 0; + } + return 1; +} + +inline int64_t khit_long_gap(k_mer_hit *a, k_mer_hit *b, double small_bw_rate, int64_t min_small_bw) +{ + int64_t dq, dr, dd, dm; + dq = b->self_offset-a->self_offset; + dr = b->offset-a->offset; + dd = dq>=dr? ((dq)-(dr)): ((dr)-(dq)); + + dm = dq>=dr?dr:dq; + if((dd > (dm*small_bw_rate)) && (dd > min_small_bw)) return 0; + return 1; +} + +int64_t filter_bad_khits(k_mer_hit *sk, k_mer_hit *ek, k_mer_hit* a, int64_t a_n, double small_bw_rate, int64_t min_small_bw) +{ + int64_t k = 0; k_mer_hit *z; double bw_r; int64_t bw, occ = 0; + bw_r = small_bw_rate; bw = min_small_bw; + if(sk) { + for (k = 0; k < a_n; k++) { + z = &(a[k]); + if((sk && (!khit_long_gap(sk, z, bw_r, bw))) || + (ek && (!khit_long_gap(z, ek, bw_r, bw)))) { + z->offset = z->self_offset = (uint32_t)-1; occ++; + } else { + break; + } + } + } + + if(ek && k < a_n) { + for (k = a_n-1; k >= 0; k--) { + z = &(a[k]); + if(z->cnt < z->readID) continue; + if((sk && (!khit_long_gap(sk, z, bw_r, bw))) || + (ek && (!khit_long_gap(z, ek, bw_r, bw)))) { + z->offset = z->self_offset = (uint32_t)-1; occ++; + } else { + break; + } + } + } + + if(occ) { + for (k = occ = 0; k < a_n; k++) { + if(a[k].offset == (uint32_t)-1) continue; + a[occ++] = a[k]; + } + a_n = occ; + } + return a_n; +} + +int64_t filter_adp_k_hits(k_mer_hit *ka, int64_t kn, Chain_Data *dp, uint64_t qs, uint64_t qe, uint64_t ts, uint64_t te, uint64_t readID, int64_t ci, int64_t *cmi, k_mer_hit *m, +double small_bw_rate, int64_t min_small_bw) +{ + int64_t k = ci, cmi0 = (*cmi); k_mer_hit *p = NULL, n; + for (; k < kn && ka[k].readID == readID && ka[k].self_offset < qs; k++) { + p = &(ka[k]); + // fprintf(stderr, "[M::%s::] p->q::%ld, p->t::%ld\n", __func__, p->self_offset, p->offset); + if(p->offset >= ts) continue; + if((m) && ((m->offset >= p->offset) || (m->self_offset >= p->self_offset))) continue; + ka[(*cmi)++] = *p; + } + n.self_offset = qs; n.offset = ts; p = &n; + if(qs == (uint64_t)-1 || qe == (uint64_t)-1) p = NULL; + // fprintf(stderr, "[M::%s::] cmi0::%ld, cmi::%ld\n", __func__, cmi0, (*cmi)); back = (*cmi); + if((*cmi) > cmi0) { + (*cmi) = cmi0 + filter_bad_khits(m, p, ka+cmi0, (*cmi)-cmi0, small_bw_rate, min_small_bw); + if((*cmi) > cmi0) { + (*cmi) = cmi0 + lchain_refine(ka+cmi0, (*cmi)-cmi0, ka+cmi0, dp, 50, 5000, 512, 16); + } + } + // if(back != (*cmi)) { + // fprintf(stderr, "sbsbsbsb[M::%s::] cmi0::%ld, cmi::%ld\n", __func__, cmi0, (*cmi)); + // } + + for (; k < kn && ka[k].readID == readID && ka[k].self_offset < qe; k++); + return k; +} + + +void refine_khits(overlap_region *z, Candidates_list *cl, Chain_Data *dp, double sgap_rate) +{ + int64_t k, wn = z->w_list.n, aln_n, qs, qe, ts, te, ci, cmi, id, mm_gap = 64; + k_mer_hit p; p.self_offset = (uint32_t)-1; p.offset = (uint32_t)-1; + if(wn <= 0) return; + qs = qe = ts = te = -1; ci = cmi = z->shared_seed; id = cl->list[ci].readID; + for (k = aln_n = 0; k < wn; k++) { + if(z->w_list.a[k].extra_end < 0 && z->w_list.a[k].y_end != -1) {///anchor + if(qs == -1) { + qs = z->w_list.a[k].x_start; ts = z->w_list.a[k-1].y_end+1; + } + qe = z->w_list.a[k].x_end+1; te = z->w_list.a[k].y_end+1; + } else { + if(qs != -1) { + // fprintf(stderr, "\n[M::%s::] q::[%ld, %ld), t::[%ld, %ld), ci::%ld\n", + // __func__, qs, qe, ts, te, ci); + ci = filter_adp_k_hits(cl->list, cl->length, dp, qs, qe, ts, te, id, ci, &cmi, + aln_n?&p:NULL, sgap_rate, mm_gap); + p.self_offset = qe - 1; p.offset = te -1; + aln_n++;//[qs, qe); [ts, te) + } + qs = qe = ts = te = -1; + } + } + if(qs != -1) { + // fprintf(stderr, "\n[M::%s::] q::[%ld, %ld), t::[%ld, %ld), ci::%ld\n", + // __func__, qs, qe, ts, te, ci); + ci = filter_adp_k_hits(cl->list, cl->length, dp, qs, qe, ts, te, id, ci, &cmi, + aln_n?&p:NULL, sgap_rate, mm_gap); + p.self_offset = qe - 1; p.offset = te -1; + aln_n++;//[qs, qe); [ts, te) + } + // fprintf(stderr, "\n[M::%s::] q::[%ld, %ld), t::[%ld, %ld), ci::%ld\n", + // __func__, qs, qe, ts, te, ci); + ci = filter_adp_k_hits(cl->list, cl->length, dp, (uint64_t)-1, (uint64_t)-1, (uint64_t)-1, (uint64_t)-1, id, ci, &cmi, + aln_n?&p:NULL, sgap_rate, mm_gap); + for (k = cmi; k < ci; k++) cl->list[k].readID = ((uint32_t)(0x7fffffff)); +} + + +void count_k_hits_filter(overlap_region_alloc* ol, Candidates_list *cl, asg64_v* ii, Chain_Data *dp) +{ + int64_t k, on = ol->length, m = 0, i, cn = cl->length, scn; k_mer_hit *ca; + overlap_region *z; uint64_t pid; + kv_resize(uint64_t, *ii, ol->length); + for (k = 0, ii->n = 0; k < on; k++, ii->n++) { + z = &(ol->list[k]); + ii->a[ii->n] = z->shared_seed; + ii->a[ii->n] <<= 32; ii->a[ii->n] |= k; + i = z->shared_seed; pid = cl->list[i].readID; + for (; i < cn && cl->list[i].readID == pid && cl->list[i].readID != ((uint32_t)(0x7fffffff)); i++); + scn = i - z->shared_seed; ca = cl->list+z->shared_seed; + i = lchain_refine(ca, scn, ca, dp, 50, 5000, 512, 16); + for (; i < scn; i++) ca[i].readID = ((uint32_t)(0x7fffffff)); + } + radix_sort_bc64(ii->a, ii->a+ii->n); + + for (k = m = 0; k < on; k++) { + z = &(ol->list[(uint32_t)ii->a[k]]); i = z->shared_seed; + pid = cl->list[i].readID; z->shared_seed = m; + for (; i < cn && cl->list[i].readID == pid && cl->list[i].readID != ((uint32_t)(0x7fffffff)); i++) { + cl->list[m] = cl->list[i]; + cl->list[m].readID = (uint32_t)ii->a[k]; + cl->list[m].cnt = 0; + m++; + } + } + cl->length = cn = m; +} + + + +void count_k_hits_adv(All_reads *rref, const ul_idx_t *uref, char* qstr, UC_Read *buf, +overlap_region_alloc* ol, Candidates_list *cl, asg64_v* ii, Chain_Data *dp, double sgap_rate, +uint64_t khit, uint64_t basec) +{ + int64_t k, l, on = ol->length, m = 0, i, cn = cl->length, srt_n; + overlap_region *z; uint64_t t, ff, pid, *srt; char *str0 = NULL, *str1 = NULL; + kv_resize(uint64_t, *ii, ol->length); + for (k = 0, ii->n = 0; k < on; k++, ii->n++) { + ii->a[ii->n] = ol->list[k].shared_seed; + ii->a[ii->n] <<= 32; ii->a[ii->n] |= k; + refine_khits(&(ol->list[k]), cl, dp, sgap_rate); + } + radix_sort_bc64(ii->a, ii->a+ii->n); + // prt_khit(cl, ol, NULL, 109111, "a"); + for (k = m = 0; k < on; k++) { + z = &(ol->list[(uint32_t)ii->a[k]]); i = z->shared_seed; + pid = cl->list[i].readID; z->shared_seed = m; + for (; i < cn && cl->list[i].readID == pid && cl->list[i].readID != ((uint32_t)(0x7fffffff)); i++) { + cl->list[m] = cl->list[i]; + cl->list[m].readID = (uint32_t)ii->a[k]; + cl->list[m].cnt = 0; + t = cl->list[m].self_offset; t <<= 32; t |= m; + kv_push(uint64_t, (*ii), t); + // if(z->y_id == 109111) { + // fprintf(stderr, "[M::%s::m->%ld] qoff::%u, toff::%u\n", __func__, m, + // cl->list[m].self_offset, cl->list[m].offset); + // } + m++; + } + } + cl->length = cn = m; srt = ii->a+on; srt_n = ii->n-on; + // prt_khit(cl, ol, NULL, 109111, "b"); + radix_sort_bc64(srt, srt+srt_n); + if(basec) { + resize_UC_Read(buf, (khit<<1)); str0 = buf->seq; str1 = buf->seq + khit; + } + // prt_khit(cl, ol, NULL, 109111, "c"); + for (k = 1, l = 0; k <= srt_n; k++) { + if(k == cn || (srt[l]>>32) != (srt[k]>>32)) { + ff = k - l; + if(basec && ff > 1) { + if(!k_hits_bcheck(rref, uref, ol, cl, khit, srt+l, k-l, qstr, str0, str1)) ff = 1; + } + for (i = l; i < k; i++) { + cl->list[(uint32_t)srt[i]].cnt = ff; + // fprintf(stderr, "[M::%s::] pos::%u, cnt::%lu\n", __func__, + // cl->list[(uint32_t)srt[i]].self_offset, ff); + } + + l = k; + } + } + // prt_khit(cl, ol, NULL, 109111, "d"); +} + + +void count_k_hits(All_reads *rref, const ul_idx_t *uref, char* qstr, UC_Read *buf, +overlap_region_alloc* ol, Candidates_list *cl, asg64_v* ii, uint64_t khit, uint64_t basec) +{ + int64_t k, l, on = ol->length, m = 0, i, cn = cl->length, srt_n; + overlap_region *z; uint64_t t, ff, pid, *srt; char *str0 = NULL, *str1 = NULL; + kv_resize(uint64_t, *ii, ol->length); + for (k = 0, ii->n = 0; k < on; k++, ii->n++) { + ii->a[ii->n] = ol->list[k].shared_seed; + ii->a[ii->n] <<= 32; ii->a[ii->n] |= k; + } + radix_sort_bc64(ii->a, ii->a+ii->n); + + for (k = m = 0; k < on; k++) { + z = &(ol->list[(uint32_t)ii->a[k]]); i = z->shared_seed; + pid = cl->list[i].readID; z->shared_seed = m; + for (; i < cn && cl->list[i].readID == pid; i++) { + cl->list[m] = cl->list[i]; + cl->list[m].readID = (uint32_t)ii->a[k]; + cl->list[m].cnt = 0; + t = cl->list[m].self_offset; t <<= 32; t |= m; + kv_push(uint64_t, (*ii), t); + m++; + } + } + cl->length = cn = m; srt = ii->a+on; srt_n = ii->n-on; + radix_sort_bc64(srt, srt+srt_n); + if(basec) { + resize_UC_Read(buf, (khit<<1)); str0 = buf->seq; str1 = buf->seq + khit; + } + + for (k = 1, l = 0; k <= srt_n; k++) { + if(k == cn || (srt[l]>>32) != (srt[k]>>32)) { + ff = k - l; + if(basec && ff > 1) { + if(!k_hits_bcheck(rref, uref, ol, cl, khit, srt+l, k-l, qstr, str0, str1)) ff = 1; + } + for (i = l; i < k; i++) { + cl->list[(uint32_t)srt[i]].cnt = ff; + // fprintf(stderr, "[M::%s::] pos::%u, cnt::%lu\n", __func__, + // cl->list[(uint32_t)srt[i]].self_offset, ff); + } + + l = k; + } + } + + +} + + +void tuning_ext_offset(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, int64_t ql, int64_t tl, int64_t wl, +int64_t fusion_k_len, int64_t fusion_win_occ, int64_t *ch_s0, int64_t *ch_e0, int64_t *qs0, int64_t *qe0, int64_t *ts0, int64_t *te0, int64_t *mode) +{ + ///[qs, qe) + if((*mode) != 1 && (*mode) != 2) return; + int64_t qs = *qs0, qe = *qe0, ts = *ts0, te = *te0, ch_s = *ch_s0, ch_e = *ch_e0; + int64_t ke, ks, p[3], we, ws, k, wid; + int64_t sl, gq, gt, gl, gg, update, min_g = INT32_MAX, min_id = -1; + adjust_ext_offset(&qs, &qe, &ts, &te, ql, tl, 0, *mode); p[0] = p[1] = p[2] = -1; + if((*mode) == 1) {///forward extension + //qs0 and ts0 are fixed; te0 = -1, qe0 is unreliable + if(qe > (*qe0)) { + ///find k-mer hit + ke = ch_a[ch_s].self_offset; + for (ch_e = ch_s; (ch_e < ch_n) && (ch_a[ch_e].self_offset < (*qe0)); ch_e++) { + ke = ch_a[ch_e].self_offset; + } + for (ke += fusion_k_len; (ch_e < ch_n) && (ch_a[ch_e].self_offset < ke); ch_e++) { + if(ch_a[ch_e].self_offset<(*qe0)) continue; + if((ch_a[ch_e].offset<=(*ts0))||(ch_a[ch_e].self_offset<=(*qs0))) continue;//not co-linear + if(is_pri_aln(ch_a[ch_e])) { + p[2] = ch_e; break; + } else if(ch_a[ch_e].cnt > 1 && p[1] == -1) { + p[1] = ch_e; + } else if(p[0] == -1) { + p[0] = ch_e; + } + } + if(p[2] != -1) p[0] = p[2]; + else if(p[1] != -1) p[0] = p[1]; + if(p[0] != -1) { + (*mode) = 0;///global + (*qe0) = ch_a[p[0]].self_offset; (*te0) = ch_a[p[0]].offset; (*ch_e0) = p[0]; + return; + } + + ///find aligned window + we = (*qe0); we/=wl; we *= wl; we +=wl; we--; ///next window + for (k = 0; we < qe && we <= z->x_pos_e && k < fusion_win_occ; we+=wl) {//[ws, we]; [qs, qe) + wid = get_win_id_by_e(z, we, wl, NULL); + if(z->w_list.a[wid].y_end == -1) continue;//unmapped + if(z->w_list.a[wid].x_end < (*qs0)) continue; + if(z->w_list.a[wid].y_end < (*ts0)) continue; + sl = z->w_list.a[wid].x_end+1-z->w_list.a[wid].x_start; + if(z->w_list.a[wid].error > (sl/A_L)) continue; + gq = z->w_list.a[wid].x_end-(*qs0); + gt = z->w_list.a[wid].y_end-(*ts0); + gl = MIN(gq, gt); gl/=16; if(gl <= 0) gl = 1; + gg = (gq>=gt)?(gq-gt):(gt-gq); gg /= gl; + update = 0; + if(min_g>gg) { + update = 1; + } else if((min_g==gg)&&(z->w_list.a[min_id].error>z->w_list.a[wid].error)) { + update = 1; + } + if(update) { + min_g = gg; min_id = wid; + } + k++; + } + } + + if(min_id != -1) { + (*qe0) = z->w_list.a[min_id].x_end+1; + (*te0) = z->w_list.a[min_id].y_end+1; + (*mode) = 0;///global + } else { + (*qe0) = qe; (*te0) = te;//extension + } + } else if((*mode) == 2) {///backward extension + //qe0 and te0 are fixed; ts0 = -1, qs0 is unreliable + if(qs < (*qs0)) { + ///find k-mer hit + ks = ch_a[ch_e].self_offset; + for (ch_s = ch_e; (ch_s >= 0) && (ch_a[ch_s].self_offset > (*qs0)); ch_s--) { + ks = ch_a[ch_s].self_offset; + } + for (ks -= fusion_k_len; (ch_s >= 0) && (ch_a[ch_s].self_offset > ks); ch_s--) { + if(ch_a[ch_s].self_offset>(*qs0)) continue; + if((ch_a[ch_s].offset>=(*te0))||(ch_a[ch_s].self_offset>=(*qe0))) continue;//not co-linear + if(is_pri_aln(ch_a[ch_s])) { + p[2] = ch_s; break; + } else if(ch_a[ch_s].cnt > 1 && p[1] == -1) { + p[1] = ch_s; + } else if(p[0] == -1) { + p[0] = ch_s; + } + } + // fprintf(stderr, "-[M::%s::] utg%.6dl(%c), p[0]::%ld, p[1]::%ld, p[2]::%ld\n", + // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], p[0], p[1], p[2]); + if(p[2] != -1) p[0] = p[2]; + else if(p[1] != -1) p[0] = p[1]; + if(p[0] != -1) { + (*mode) = 0;///global + (*qs0) = ch_a[p[0]].self_offset; (*ts0) = ch_a[p[0]].offset; (*ch_s0) = p[0]; + return; + } + + ///find aligned window + ws = (*qs0)-1; ws/=wl; ws*=wl; + for (k = 0; ws >= qs && ws >= z->x_pos_s && k < fusion_win_occ; ws-=wl) {//[ws, we]; [qs, qe) + wid = get_win_id_by_s(z, ws, wl, NULL); + if(z->w_list.a[wid].y_end == -1) continue;//unmapped + if(z->w_list.a[wid].x_start >= (*qe0)) continue; + if(z->w_list.a[wid].y_start >= (*te0)) continue; + sl = z->w_list.a[wid].x_end+1-z->w_list.a[wid].x_start; + if(z->w_list.a[wid].error > (sl/A_L)) continue; + gq = (*qe0) - z->w_list.a[wid].x_start; + gt = (*te0) - z->w_list.a[wid].y_start; + gl = MIN(gq, gt); gl/=16; if(gl <= 0) gl = 1; + gg = (gq>=gt)?(gq-gt):(gt-gq); gg /= gl; + update = 0; + if(min_g>gg) { + update = 1; + } else if((min_g==gg)&&(z->w_list.a[min_id].error>z->w_list.a[wid].error)) { + update = 1; + } + if(update) { + min_g = gg; min_id = wid; + } + k++; + } + } + + if(min_id != -1) { + (*qs0) = z->w_list.a[min_id].x_start; + (*ts0) = z->w_list.a[min_id].y_start; + (*mode) = 0;///global + } else { + (*qs0) = qs; (*ts0) = ts; ///still extension + } + } + + if((*ch_e0) == -1) { + for ((*ch_e0)=(*ch_s0);((*ch_e0)=(*qs0))&&(ch_a[(*ch_e0)].self_offset<=(*qe0)); (*ch_e0)++); + } + + if((*ch_s0) == -1) { + for ((*ch_s0)=(*ch_e0);((*ch_s0)>=0)&&(ch_a[(*ch_s0)].self_offset>=(*qs0))&&(ch_a[(*ch_s0)].self_offset<=(*qe0)); (*ch_s0)--); + (*ch_s0)++; + } + ///boundry + for (;((*ch_e0)=(*qs0))&&(ch_a[(*ch_e0)].self_offset<=(*qe0)); (*ch_e0)++); +} + +int64_t cal_estimate_err(overlap_region *z, int64_t wl, int64_t qs, int64_t qe, double e_rate) +{ + int64_t k, ws, we, wid, os, oe, ovlp, tot, cov_l, est = (qe-qs)*e_rate, wn = z->w_list.n; + if(!wn) return est; + if(qs < z->x_pos_s) qs = z->x_pos_s; + if(qe > z->x_pos_e+1) qe = z->x_pos_e+1; + ws = qs/wl; ws *= wl; wid = get_win_id_by_s(z, ws, wl, NULL); + if(wid>=wn) wid = wn-1; + for (k = wid;k < wn && qs > z->w_list.a[k].x_end; k++){;} if(k == wn) {return est;} + ///qs <= z->w_list.a[k].x_end + for (;k>=0 && qs < z->w_list.a[k].x_start; k--){;} if(k < 0) {k = 0;} + ///qs >= z->w_list.a[k].x_start + + for (tot = cov_l = 0; k < wn && z->w_list.a[k].x_start < qe; k++) { + if(z->w_list.a[k].y_end == -1) continue; + ws = z->w_list.a[k].x_start; we = z->w_list.a[k].x_end+1; + os = MAX(qs, ws); oe = MIN(qe, we); + ovlp = ((oe>os)? (oe-os):0); + if(!ovlp) continue; + cov_l += ovlp; + // if(!ovlp) { + // fprintf(stderr, "\n[M::%s::] utg%.6dl(%c), q::[%ld, %ld), w::[%ld, %ld), z::::[%d, %d)\n", + // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], qs, qe, ws, we, z->x_pos_s, z->x_pos_e+1); + // } + if(ovlp == (we-ws)) { + tot += z->w_list.a[k].error; + } else { + tot += ((double)z->w_list.a[k].error)*((double)ovlp)/((double)(we-ws)); + } + } + tot += ((qe-qs)-cov_l)*e_rate; + return tot; +} + +int64_t cal_estimate_err_hc(overlap_region *z, int64_t wl, int64_t qs, int64_t qe, int64_t ts, int64_t te, double e_rate, int64_t *exact) +{ + int64_t k, ws, we, wid, os, oe, ovlp, tot, cov_l, est = (qe-qs)*e_rate, wn = z->w_list.n, exa = 1, ots, ote, q[2], t[2]; + if(exact) (*exact) = 0; + if(!wn) return est; + if(qs < z->x_pos_s) qs = z->x_pos_s; + if(qe > z->x_pos_e+1) qe = z->x_pos_e+1; + ws = qs/wl; ws *= wl; wid = get_win_id_by_s(z, ws, wl, NULL); + if(wid>=wn) wid = wn-1; + for (k = wid;k < wn && qs > z->w_list.a[k].x_end; k++){;} if(k == wn) {return est;} + ///qs <= z->w_list.a[k].x_end + for (;k>=0 && qs < z->w_list.a[k].x_start; k--){;} if(k < 0) {k = 0;} + ///qs >= z->w_list.a[k].x_start + + for (tot = cov_l = 0, ots = ote = -1; k < wn && z->w_list.a[k].x_start < qe; k++) { + if(z->w_list.a[k].y_end == -1) continue; + ws = z->w_list.a[k].x_start; we = z->w_list.a[k].x_end+1; + os = MAX(qs, ws); oe = MIN(qe, we); + ovlp = ((oe>os)? (oe-os):0); + if(!ovlp) continue; + cov_l += ovlp; + + if(ovlp == (we-ws)) { + tot += z->w_list.a[k].error; + } else { + tot += ((double)z->w_list.a[k].error)*((double)ovlp)/((double)(we-ws)); + } + if(z->w_list.a[k].error > 0) exa = 0; + if(exa) { + q[0] = os - ws; q[1] = we - oe; + we = z->w_list.a[k].y_end+1; ws = we - (z->w_list.a[k].x_end+1-z->w_list.a[k].x_start); + os = MAX(ts, ws); oe = MIN(te, we); + ovlp = ((oe>os)? (oe-os):0); + t[0] = os - ws; t[1] = we - oe; + if((ovlp) && (q[0] == t[0]) && (t[0] == t[0])) { + if(ote == -1) { + ots = os; ote = oe; + } else if(ote == os) { + ote = oe; + } else { + exa = 0; + } + } else { + exa = 0; + } + } + } + tot += ((qe-qs)-cov_l)*e_rate; + if((exact) && exa && (((qe-qs) == cov_l))) { + if(((qe-qs) == (ote - ots)) && (ots == ts) && (ote == te)) (*exact) = 1; + } + return tot; +} + + +///[s, e); [ps, pe) +inline char *retrieve_str_seq_exz(UC_Read *tu, int64_t s, int64_t l, +int64_t ps, int64_t pl, uint8_t rev, const ul_idx_t *uref, hpc_t *hpc_g, +All_reads *rref, int64_t id) +{ + if(!hpc_g) { + char *str; int64_t ss = s, sl = l; tu->length = l; + UC_Read_resize(*tu, sl); str = tu->seq; + if(s == ps) { + if(l <= pl) return tu->seq; + str = tu->seq + pl; ss = ps + pl; sl = l - pl; + } + if(uref) { + retrieve_u_seq(NULL, str, &(uref->ug->u.a[id]), rev, ss, sl, NULL); + } else if(rref) { + recover_UC_Read_sub_region(str, ss, sl, rev, rref, id); + } + return tu->seq; + } else { + return hpc_str(*hpc_g, id, rev) + s; + } +} + +void cal_exz_global(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) +{ + int32_t bd, nword; + bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); + + if(nword <= 1) { + ed_band_cal_global_64_w_trace(pstr, pn, tstr, tn, thre, ez); + } else if(nword == 2) { + ed_band_cal_global_128_w_trace(pstr, pn, tstr, tn, thre, ez); + } else { + ed_band_cal_global_infi_w_trace(pstr, pn, tstr, tn, thre, &nword, ez); + } +} + +void cal_exz_global_simi(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) +{ + int32_t bd, nword; + bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); + + if(nword <= 1) { + ed_band_cal_global_64_w(pstr, pn, tstr, tn, thre, ez); + } else if(nword == 2) { + ed_band_cal_global_128_w(pstr, pn, tstr, tn, thre, ez); + } else { + ed_band_cal_global_infi_w(pstr, pn, tstr, tn, thre, &nword, ez); + } +} + +void cal_exz_extension_0(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) +{ + int32_t bd, nword; + bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); + + if(nword <= 1) { + ed_band_cal_extension_64_0_w_trace(pstr, pn, tstr, tn, thre, ez); + } else if(nword == 2) { + ed_band_cal_extension_128_0_w_trace(pstr, pn, tstr, tn, thre, ez); + } else { + ed_band_cal_extension_infi_0_w_trace(pstr, pn, tstr, tn, thre, &nword, ez); + } +} + +void cal_exz_extension_0_simi(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) +{ + int32_t bd, nword; + bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); + + if(nword <= 1) { + ed_band_cal_extension_64_0_w(pstr, pn, tstr, tn, thre, ez); + } else if(nword == 2) { + ed_band_cal_extension_128_0_w(pstr, pn, tstr, tn, thre, ez); + } else { + ed_band_cal_extension_infi_0_w(pstr, pn, tstr, tn, thre, &nword, ez); + } +} + +void cal_exz_extension_1(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) +{ + int32_t bd, nword; + bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); + + if(nword <= 1) { + ed_band_cal_extension_64_1_w_trace(pstr, pn, tstr, tn, thre, ez); + } else if(nword == 2) { + ed_band_cal_extension_128_1_w_trace(pstr, pn, tstr, tn, thre, ez); + } else { + ed_band_cal_extension_infi_1_w_trace(pstr, pn, tstr, tn, thre, &nword, ez); + } +} + +void cal_exz_extension_1_simi(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) +{ + int32_t bd, nword; + bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); + + if(nword <= 1) { + ed_band_cal_extension_64_1_w(pstr, pn, tstr, tn, thre, ez); + } else if(nword == 2) { + ed_band_cal_extension_128_1_w(pstr, pn, tstr, tn, thre, ez); + } else { + ed_band_cal_extension_infi_1_w(pstr, pn, tstr, tn, thre, &nword, ez); + } +} + +void cal_exz_semi(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t aux_beg, bit_extz_t *ez) +{ + int32_t bd, nword; + bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); + + if(nword <= 1) { + ed_band_cal_semi_64_w_absent_diag_trace(pstr, pn, tstr, tn, thre, aux_beg, ez); + } else if(nword == 2) { + ed_band_cal_semi_128_w_absent_diag_trace(pstr, pn, tstr, tn, thre, aux_beg, ez); + } else { + ed_band_cal_semi_infi_w_absent_diag_trace(pstr, pn, tstr, tn, thre, aux_beg, &nword, ez); + } +} + +void cal_exz_semi_simi(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t aux_beg, bit_extz_t *ez) +{ + int32_t bd, nword; + bd = (((thre)<<1)+1); nword = ((bd>>bitw)+(!!(bd&bitz))); + + if(nword <= 1) { + ed_band_cal_semi_64_w_absent_diag(pstr, pn, tstr, tn, thre, aux_beg, ez); + } else if(nword == 2) { + ed_band_cal_semi_128_w_absent_diag(pstr, pn, tstr, tn, thre, aux_beg, ez); + } else { + ed_band_cal_semi_infi_w_absent_diag(pstr, pn, tstr, tn, thre, aux_beg, &nword, ez); + } +} + +void ref_cigar_check(char* qstr, UC_Read *tu, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, int64_t id, int64_t rev, bit_extz_t *ez) +{ + int64_t pts = -1, pte = -1, tl = ez->pe-ez->ps+1, ql = ez->te-ez->ts+1, bps, bts, k; + char *q, *t; bps = ez->ps; bts = ez->ts; + + q = qstr + ez->ts; + t = retrieve_str_seq_exz(tu, ez->ps, tl, pts, pte-pts, rev, uref, hpc_g, rref, id); + ez->ps = ez->ts = 0; + if(!cigar_check(t, q, ez)){ + fprintf(stderr, "[M::%s::] cigar_n::%d\n", __func__, (int32_t)ez->cigar.n); + for (k = 0; k < (int32_t)ez->cigar.n; k++) { + fprintf(stderr, "[M::%s::%ld] cigar_len::%u, c::%u\n", __func__, k, + ez->cigar.a[k]&(0x3fff), (ez->cigar.a[k]>>14)); + } + + // fprintf(stderr, "[M::%s::l->%ld] s::%ld, pstr::%.*s\n", __func__, tl, bps, (int32_t)tl, t); + // fprintf(stderr, "[M::%s::l->%ld] s::%ld, tstr::%.*s\n", __func__, ql, bts, (int32_t)ql, q); + fprintf(stderr, "[M::%s::l->%ld] s::%ld\n", __func__, tl, bps); + fprintf(stderr, "[M::%s::l->%ld] s::%ld\n", __func__, ql, bts); + exit(1); + } + ez->ps = bps; ez->ts = bts; +} + +int64_t cal_exz_infi_adv(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, +bit_extz_t *exz, char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, +int64_t *pts, int64_t *pte, int64_t thre, int64_t *pthre, int64_t q_tot_l, int64_t mode) +{ + clear_align(*exz); + int64_t aux_beg = 0, ql, tl, t_tot_l = -1, dd; + char *q_string, *t_string; int32_t rev = z->y_pos_strand, id = z->y_id; + ql = qe - qs; tl = te - ts; dd = MAX(ql, tl); + if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); + else if(uref) t_tot_l = uref->ug->u.a[id].len; + else t_tot_l = Get_READ_LENGTH((*rref), id); + + if(mode == 3) { + update_semi_coord(uref, hpc_g, rref, z, qs, qe, ((thre>dd)?dd:thre), &ts, &te, &aux_beg); + } else if(mode == 1 || mode == 2) { + adjust_ext_offset(&qs, &qe, &ts, &te, q_tot_l, t_tot_l, ((thre>dd)?dd:thre), mode); + } + + if((qe > qs) && (te > ts) && (ts != -1) && (te != -1)) { + ql = qe - qs; tl = te - ts; + dd = MAX(ql, tl); + if(thre > dd) thre = dd; + if(thre <= (*pthre)) return 0; + (*pthre) = thre; + + q_string = qstr + qs; + t_string = retrieve_str_seq_exz(tu, ts, tl, (*pts), (*pte)-(*pts), rev, uref, hpc_g, rref, id); + (*pts) = ts; (*pte) = te; + + if(mode == 0) { //global + cal_exz_global(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 1) {///forward extension + cal_exz_extension_0(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 2) {///backward extension + cal_exz_extension_1(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 3) {//semi-global + cal_exz_semi(t_string, tl, q_string, ql, thre, aux_beg, exz); + } + + if(is_align(*exz)) { + // cigar_check(t_string, q_string, exz); + // if(mode == 1) { + // fprintf(stderr, "\n[M::%s::ql::%ld] qs::%ld, qe::%ld, ts::%ld, te::%ld, mode::%ld, err::%d, thre::%d, exz_q[%d, %d], exz_t[%d, %d]\n", + // __func__, ql, qs, qe, ts, te, mode, exz->err, exz->thre, exz->ts, exz->te, exz->ps, exz->pe); + // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tl, t_string); + // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)ql, q_string); + // fprintf(stderr, "[M::%s::] exz->cigar.n::%d\n", __func__, (int32_t)exz->cigar.n); + // } + exz->ps += ts; exz->pe += ts; + exz->ts += qs; exz->te += qs; + return 1; + } + return 0; + } + return 0; +} + + +int64_t cal_exz_infi_non_retrieve_adv(overlap_region *z, bit_extz_t *exz, char* qstr, char* tstr, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t thre, int64_t *pthre, int64_t q_tot_l, int64_t t_tot_l, int64_t mode) +{ + clear_align(*exz); + int64_t aux_beg = 0, ql, tl, dd; char *q_string, *t_string; + ql = qe - qs; tl = te - ts; dd = MAX(ql, tl); + + if((mode == 3) && (z)) { + update_semi_non_retrieve_coord(z, qs, qe, ((thre>dd)?dd:thre), t_tot_l, &ts, &te, &aux_beg); + } else if(mode == 1 || mode == 2) { + adjust_ext_offset(&qs, &qe, &ts, &te, q_tot_l, t_tot_l, ((thre>dd)?dd:thre), mode); + } + + if((qe > qs) && (te > ts) && (ts != -1) && (te != -1)) { + ql = qe - qs; tl = te - ts; + dd = MAX(ql, tl); + if(thre > dd) thre = dd; + if(thre <= (*pthre)) return 0; + (*pthre) = thre; + + q_string = qstr + qs; t_string = tstr + ts; + + if(mode == 0) { //global + cal_exz_global(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 1) {///forward extension + cal_exz_extension_0(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 2) {///backward extension + cal_exz_extension_1(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 3) {//semi-global + cal_exz_semi(t_string, tl, q_string, ql, thre, aux_beg, exz); + } + + if(is_align(*exz)) { + // cigar_check(t_string, q_string, exz); + // if(mode == 1) { + // fprintf(stderr, "\n[M::%s::ql::%ld] qs::%ld, qe::%ld, ts::%ld, te::%ld, mode::%ld, err::%d, thre::%d, exz_q[%d, %d], exz_t[%d, %d]\n", + // __func__, ql, qs, qe, ts, te, mode, exz->err, exz->thre, exz->ts, exz->te, exz->ps, exz->pe); + // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tl, t_string); + // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)ql, q_string); + // fprintf(stderr, "[M::%s::] exz->cigar.n::%d\n", __func__, (int32_t)exz->cigar.n); + // } + exz->ps += ts; exz->pe += ts; + exz->ts += qs; exz->te += qs; + return 1; + } + return 0; + } + return 0; +} + + +int64_t cal_exact_exz(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, +bit_extz_t *exz, char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, +int64_t *pts, int64_t *pte, int64_t q_tot_l, int64_t mode) +{ + clear_align(*exz); exz->thre = 0; exz->cigar.n = 0; + int64_t ql, tl, t_tot_l = -1; + char *q_string, *t_string; int32_t rev = z->y_pos_strand, id = z->y_id; ql = qe - qs; + if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); + else if(uref) t_tot_l = uref->ug->u.a[id].len; + else t_tot_l = Get_READ_LENGTH((*rref), id); + + if(mode == 3) {//semi + ts = (qs - z->x_pos_s) + z->y_pos_s; ts += y_start_offset(qs, &(z->f_cigar)); + te = ts + ql; + } else if(mode == 1) {///forward extension + te = ts + ql; + } else if(mode == 2) {///backward extension + ts = te - ql; + } + if(ts < 0) ts = 0; + if(ts > t_tot_l) ts = t_tot_l; + if(te > t_tot_l) te = t_tot_l; + ql = qe - qs; tl = te - ts; + if(ql != tl) return 0; + + q_string = qstr + qs; + t_string = retrieve_str_seq_exz(tu, ts, tl, (*pts), (*pte)-(*pts), rev, uref, hpc_g, rref, id); + (*pts) = ts; (*pte) = te; + + if(memcmp(q_string, t_string, ql)) return 0; + exz->err = 0; push_trace(&(exz->cigar), 0, ql); + exz->pl = tl; exz->ps = 0; exz->pe = tl-1; + exz->tl = ql; exz->ts = 0; exz->te = ql-1; + // cigar_check(t_string, q_string, exz); + // if(!cigar_check(t_string, q_string, exz)) { + // fprintf(stderr, "[M::%s::] cigar_n::%d\n", __func__, (int32_t)exz->cigar.n); + // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tl, t_string); + // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)ql, q_string); + // } + exz->ps += ts; exz->pe += ts; + exz->ts += qs; exz->te += qs; + return 1; +} + +int64_t cal_exact_non_retrieve_exz(overlap_region *z, bit_extz_t *exz, char* qstr, char* tstr, int64_t qs, int64_t qe, int64_t ts, int64_t te, +int64_t q_tot_l, int64_t t_tot_l, int64_t mode) +{ + clear_align(*exz); exz->thre = 0; exz->cigar.n = 0; + int64_t ql, tl; + char *q_string, *t_string; ql = qe - qs; + // if(hpc_g) t_tot_l = hpc_len(*hpc_g, id); + // else if(uref) t_tot_l = uref->ug->u.a[id].len; + // else t_tot_l = Get_READ_LENGTH((*rref), id); + + if((mode == 3) && (z)) {//semi + ts = (qs - z->x_pos_s) + z->y_pos_s; ts += y_start_offset(qs, &(z->f_cigar)); + te = ts + ql; + } else if(mode == 1) {///forward extension + te = ts + ql; + } else if(mode == 2) {///backward extension + ts = te - ql; + } + if(ts < 0) ts = 0; + if(ts > t_tot_l) ts = t_tot_l; + if(te > t_tot_l) te = t_tot_l; + ql = qe - qs; tl = te - ts; + if(ql != tl) return 0; + + q_string = qstr + qs; t_string = tstr + ts; + + if(memcmp(q_string, t_string, ql)) return 0; + exz->err = 0; push_trace(&(exz->cigar), 0, ql); + exz->pl = tl; exz->ps = 0; exz->pe = tl-1; + exz->tl = ql; exz->ts = 0; exz->te = ql-1; + // cigar_check(t_string, q_string, exz); + // if(!cigar_check(t_string, q_string, exz)) { + // fprintf(stderr, "[M::%s::] cigar_n::%d\n", __func__, (int32_t)exz->cigar.n); + // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tl, t_string); + // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)ql, q_string); + // } + exz->ps += ts; exz->pe += ts; + exz->ts += qs; exz->te += qs; + return 1; +} + +//[qmin, qmax) && [tmin, tmax) +void adjust_ext_offset_fixed_t(int64_t *qs, int64_t *qe, int64_t *ts, int64_t *te, +int64_t qmin, int64_t qmax, int64_t tmin, int64_t tmax, int64_t thre, int64_t mode) +{ + int64_t qoff, toff; + if(mode == 1) {///forward extension + qoff = qmax - (*qs); toff = tmax - (*ts); + if(qoff <= toff) { + (*qe) = qmax; (*te) = (*ts) + qoff + thre; + } else { + (*te) = tmax; (*qe) = (*qs) + toff + thre; + } + } else if(mode == 2) {///backward extension + qoff = (*qe) - qmin; toff = (*te) - tmin; + if(qoff <= toff) { + (*qs) = qmin; (*ts) = (*te) - qoff - thre; + } else { + (*ts) = tmin; (*qs) = (*qe) - toff - thre; + } + } + if((*qs) < qmin) (*qs) = qmin; + if((*ts) < tmin) (*ts) = tmin; + if((*qe) > qmax) (*qe) = qmax; + if((*te) > tmax) (*te) = tmax; +} + + + +int64_t cal_exz_infi_simi_adv(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, +bit_extz_t *exz, char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, +int64_t *pts, int64_t *pte, int64_t thre, int64_t *pthre, int64_t qmin, int64_t qmax, +int64_t tmin, int64_t tmax, int32_t rev, int32_t id, int64_t mode, overlap_region *z, +int64_t gen_trace) +{ ///mode cannot be 3 + clear_align(*exz); + int64_t aux_beg = 0, ql, tl, dd; char *q_string, *t_string; + ql = qe - qs; tl = te - ts; dd = MAX(ql, tl); + if(mode == 3 && z) { + update_semi_coord(uref, hpc_g, rref, z, qs, qe, ((thre>dd)?dd:thre), &ts, &te, &aux_beg); + } else if(mode == 1 || mode == 2) { + adjust_ext_offset_fixed_t(&qs, &qe, &ts, &te, qmin, qmax, tmin, tmax, ((thre>dd)?dd:thre), mode); + } + + // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { + // fprintf(stderr, "[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), thre::%ld, pthre::%ld\n", + // __func__, mode, qs, qe, ts, te, thre, *pthre); + // } + + if((qe > qs) && (te > ts) && (ts != -1) && (te != -1)) { + ql = qe - qs; tl = te - ts; + dd = MAX(ql, tl); + if(thre > dd) thre = dd; + // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { + // fprintf(stderr, "[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), thre::%ld, pthre::%ld\n", + // __func__, mode, qs, qe, ts, te, thre, *pthre); + // } + if(thre <= (*pthre)) return 0; + (*pthre) = thre; + + q_string = qstr + qs; + t_string = retrieve_str_seq_exz(tu, ts, tl, (*pts), (*pte)-(*pts), rev, uref, hpc_g, rref, id); + (*pts) = ts; (*pte) = te; + + if(!gen_trace) { + if(mode == 0) { //global + cal_exz_global_simi(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 1) {///forward extension + cal_exz_extension_0_simi(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 2) {///backward extension + cal_exz_extension_1_simi(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 3) {//semi-global; mode cannot be 3 + cal_exz_semi_simi(t_string, tl, q_string, ql, thre, aux_beg, exz); + } + } else { + if(mode == 0) { //global + cal_exz_global(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 1) {///forward extension + cal_exz_extension_0(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 2) {///backward extension + cal_exz_extension_1(t_string, tl, q_string, ql, thre, exz); + } else if(mode == 3) {//semi-global + cal_exz_semi(t_string, tl, q_string, ql, thre, aux_beg, exz); + } + } + + + if(is_align(*exz)) { + exz->ps += ts; exz->pe += ts; + exz->ts += qs; exz->te += qs; + // if(exz->ps == 18327 && exz->pe + 1 == 18601 && exz->ts == 145990 && exz->te + 1 == 146191) { + // fprintf(stderr, "[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld)\n", + // __func__, mode, qs, qe, ts, te); + // fprintf(stderr, "[M::%s::] q_string::%.*s\n", __func__, (int32_t)ql, q_string); + // fprintf(stderr, "[M::%s::] t_string::%.*s\n", __func__, (int32_t)tl, t_string); + // } + return 1; + } + // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { + // fprintf(stderr, "[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld)\n", + // __func__, mode, qs, qe, ts, te); + // fprintf(stderr, "[M::%s::] q_string::%.*s\n", __func__, (int32_t)ql, q_string); + // fprintf(stderr, "[M::%s::] t_string::%.*s\n", __func__, (int32_t)tl, t_string); + // } + return 0; + } + return 0; +} + +int64_t cal_exact_simi_exz(const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, +bit_extz_t *exz, char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, +int64_t *pts, int64_t *pte, int64_t q_tot_l, int64_t t_tot_l, int32_t rev, int32_t id, +int64_t mode, overlap_region *z) +{ + clear_align(*exz); exz->thre = 0; exz->cigar.n = 0; + int64_t ql, tl; char *q_string, *t_string; ql = qe - qs; + + if(mode == 3 && z) {//semi + ts = (qs - z->x_pos_s) + z->y_pos_s; ts += y_start_offset(qs, &(z->f_cigar)); + te = ts + ql; + } else if(mode == 1) {///forward extension + te = ts + ql; + } else if(mode == 2) {///backward extension + ts = te - ql; + } + if(ts < 0) ts = 0; + if(ts > t_tot_l) ts = t_tot_l; + if(te > t_tot_l) te = t_tot_l; + ql = qe - qs; tl = te - ts; + if(ql != tl) return 0; + + q_string = qstr + qs; + t_string = retrieve_str_seq_exz(tu, ts, tl, (*pts), (*pte)-(*pts), rev, uref, hpc_g, rref, id); + (*pts) = ts; (*pte) = te; + + if(memcmp(q_string, t_string, ql)) return 0; + exz->err = 0; push_trace(&(exz->cigar), 0, ql); + exz->pl = tl; exz->ps = 0; exz->pe = tl-1; + exz->tl = ql; exz->ts = 0; exz->te = ql-1; + + exz->ps += ts; exz->pe += ts; + exz->ts += qs; exz->te += qs; + return 1; +} + + +void append_wcigar(window_list *idx, window_list_alloc *res, bit_extz_t *exz) +{ + // fprintf(stderr, "[M::%s::] idx->cidx::%u, idx->clen::%u, res->c.n_0::%u, exz->cigar.n::%u, ", + // __func__, idx->cidx, idx->clen, (uint32_t)res->c.n, (uint32_t)exz->cigar.n); + if(idx->clen > 0) { + // if(!(idx->cidx+idx->clen == res->c.n)) { + // fprintf(stderr, "[M::%s::] idx->cidx::%u, idx->clen::%u, res->c.n::%u\n", + // __func__, idx->cidx, idx->clen, (uint32_t)res->c.n); + // } + assert(idx->cidx+idx->clen == res->c.n); + if(exz->cigar.n > 0) { + uint16_t c0, c; uint32_t l0, l, ci = 0, cn; + ///last item of old cigar + c0 = (res->c.a[res->c.n-1]>>14); l0 = (res->c.a[res->c.n-1]&(0x3fff)); + ///first item of new cigar + ci = pop_trace(&(exz->cigar), ci, &c, &l); + if(c0 == c) {l += l0; res->c.n--; idx->clen--;} + push_trace(((asg16_v *)(&(res->c))), c, l); + idx->clen = res->c.n-idx->cidx; + + cn = exz->cigar.n-ci; + if(cn > 0) { + kv_resize(uint16_t, res->c, (res->c.n+cn)); + memcpy(res->c.a+res->c.n, exz->cigar.a+ci, cn*sizeof(*(res->c.a))); + idx->clen += cn; res->c.n += cn; + } + } + } else { + push_wcigar(idx, res, exz);///if exz is the first item + } + // fprintf(stderr, "[M::%s::] res->c.n::%u\n", __func__, (uint32_t)res->c.n); +} + +void push_alnw(overlap_region *aux_o, bit_extz_t *exz) +{ + window_list *p = NULL; int64_t t; + if(aux_o->w_list.n > 0) { + p = &(aux_o->w_list.a[aux_o->w_list.n-1]); + // fprintf(stderr, "+[M::%s::wn->%d] px::[%d, %d], py::[%d, %d], pe::%d, exz->t::[%u, %u], exz->p::[%u, %u], exz->e::%d, clen::%u\n", + // __func__, (int32_t)(aux_o->w_list.n), p->x_start, p->x_end, p->y_start, p->y_end, p->error, + // exz->ts, exz->te, exz->ps, exz->pe, exz->err, p->clen); + // assert((p->x_endts)&&(p->y_endps)); + + if(p->clen > 0) { + t = ((int64_t)p->error) + ((int64_t)exz->err); + ///note: t cannot be equal to INT16_MAX; otherwise it is unable to distiguish unaligned regions + if(((p->x_end+1) == exz->ts) && ((p->y_end+1) == exz->ps) && (t < INT16_MAX)) { + p->x_end = exz->te; p->y_end = exz->pe; p->error += exz->err; + append_wcigar(p, &(aux_o->w_list), exz); + // fprintf(stderr, "-[M::%s::wn->%d] px::[%d, %d], py::[%d, %d], pe::%d, exz->t::[%u, %u], exz->p::[%u, %u], exz->e::%d, clen::%u\n", + // __func__, (int32_t)(aux_o->w_list.n), p->x_start, p->x_end, p->y_start, p->y_end, p->error, + // exz->ts, exz->te, exz->ps, exz->pe, exz->err, p->clen); + return; + } + } + } + // fprintf(stderr, "[M::%s::wn->%d] exz->t::[%u, %u], exz->p::[%u, %u], exz->e::%d\n", + // __func__, (int32_t)(aux_o->w_list.n), exz->ts, exz->te, exz->ps, exz->pe, exz->err); + kv_pushp(window_list, aux_o->w_list, &p); + p->x_start = exz->ts; p->x_end = exz->te; + p->y_start = exz->ps; p->y_end = exz->pe; + p->error_threshold = 0; p->error = exz->err;///single round of alignment cannot have INT16_MAX errors + push_wcigar(p, &(aux_o->w_list), exz); +} + +///[qs, qe] && [ts, te] +void push_unmap_alnw(overlap_region *aux_o, int32_t qs, int64_t qe, int64_t ts, int64_t te, int64_t mode) +{ + window_list *p = NULL; + kv_pushp(window_list, aux_o->w_list, &p); + p->x_start = qs; p->x_end = qe; + p->y_start = ts; p->y_end = te; + p->error_threshold = mode; p->error = INT16_MAX; + p->extra_begin = p->extra_end = -1; + p->cidx = p->clen = 0; +} + +///[qs, qe] && [ts, te] +void push_replace_alnw(overlap_region *aux_o, int32_t qs, int64_t qe, int64_t ts, int64_t te, int64_t mode) +{ + window_list *p = NULL; + kv_pushp(window_list, aux_o->w_list, &p); + p->x_start = qs; p->x_end = qe; + p->y_start = ts; p->y_end = te; + p->error_threshold = mode; p->error = 0; + p->extra_begin = p->extra_end = 0; + p->cidx = p->clen = 0; +} + +///[qs, qe] && [ts, te] +void push_replace_alnw_adv(overlap_region *z, int64_t wl, overlap_region *aux_o, int32_t qs, int64_t qe, int64_t ts, int64_t te, int64_t mode) +{ + int64_t k, wsk, wek, err, t; window_list *p = NULL; + wsk = get_win_id_by_s(z, qs, wl, NULL); assert(z->w_list.a[wsk].x_start == qs); + wek = get_win_id_by_s(z, qe+1, wl, NULL); assert(z->w_list.a[wek].x_end == (qe+1)); + kv_pushp(window_list, aux_o->w_list, &p); + p->x_start = p->x_end = qs; + p->y_start = p->y_end = ts; + p->error_threshold = mode; p->error = 0; + p->extra_begin = p->extra_end = 0; + p->cidx = p->clen = 0; err = 0; + + for (k = wsk; k <= wek; k++) { + assert(z->w_list.a[k].y_end != -1); + t = err + z->w_list.a[k].error; + if(t < INT16_MAX) {///note: t cannot be equal to INT16_MAX; otherwise it is unable to distiguish unaligned regions + err += z->w_list.a[k].error; + p->x_end = z->w_list.a[k].x_end; + p->y_end = z->w_list.a[k].y_end; + } else { + err = z->w_list.a[k].error; + kv_pushp(window_list, aux_o->w_list, &p); + p->x_start = z->w_list.a[k].x_start; + p->x_end = z->w_list.a[k].x_end; + p->y_start = z->w_list.a[k].y_start; + p->y_end = z->w_list.a[k].y_end; + p->error_threshold = mode; + p->extra_begin = p->extra_end = 0; + p->cidx = p->clen = 0; + } + p->error = err; + } + p->x_end = qe; p->y_end = te; +} + + + +int64_t hc_aln_exz_adv(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, +char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t mode, int64_t wl, +bit_extz_t *exz, int64_t q_tot, double e_rate, int64_t maxl, int64_t maxe, int64_t force_l, +int64_t estimate_err, overlap_region *aux_o) +{ + clear_align(*exz); exz->thre = 0; + if(((ts == -1) && (te == -1))) mode = 3;///set to semi-global + int64_t thre, ql = qe - qs, thre0, pts = -1, pte = -1, pthre = -1; + if(ql == 0 && (te-ts) == 0) return 1; + if((ql <= 0) || (te-ts) <= 0) return 0; + if(estimate_err < 0) { + if(ql > wl) estimate_err = cal_estimate_err(z, wl, qs, qe, e_rate); + else estimate_err = ql*e_rate; + } + + + // fprintf(stderr, "[M::%s::ql::%ld] qs::[%ld, %ld), ts::[%ld, %ld), mode::%ld, est_err::%ld, e_rate::%f, maxe::%ld", + // __func__, ql, qs, qe, ts, te, mode, estimate_err, e_rate, maxe); + if(ql <= 16) { + if(cal_exact_exz(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, q_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::0(+)\n", exz->err, exz->thre); + push_alnw(aux_o, exz); + return 1; + } + } + + if(ql <= maxl && (estimate_err>>1) <= maxe) { + thre = scale_ed_thre(estimate_err, maxe); + if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(+)\n", exz->err, exz->thre, thre); + push_alnw(aux_o, exz); + return 1; + } + + thre0 = thre; thre = ql*e_rate; thre = scale_ed_thre(thre, maxe); + if(thre > thre0) { + if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); + push_alnw(aux_o, exz); + return 1; + } + } + + thre0 = thre; thre <<= 1; thre = scale_ed_thre(thre, maxe); + if(thre > thre0) { + if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); + push_alnw(aux_o, exz); + return 1; + } + } + + thre0 = thre; thre = ql*0.51; thre = scale_ed_thre(thre, maxe); + if(thre > thre0) { + if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); + push_alnw(aux_o, exz); + return 1; + } + } + + if(ql <= force_l) { + thre = maxe; + if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); + push_alnw(aux_o, exz); + return 1; + } + } + } + // fprintf(stderr, ", err::%d, thre::%d\n", INT32_MAX, exz->thre); + // if(mode == 0) { + // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tu->length, tu->seq); + // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)(qe-qs), qstr+qs); + // } + return 0; + +} + +void set_exact_exz(bit_extz_t *exz, int64_t qs, int64_t qe, int64_t ts, int64_t te) +{ + clear_align(*exz); exz->thre = 0; exz->cigar.n = 0; + exz->err = 0; push_trace(&(exz->cigar), 0, qe - qs); + exz->pl = te - ts; exz->ps = 0; exz->pe = exz->pl-1; + exz->tl = qe - qs; exz->ts = 0; exz->te = exz->tl-1; + exz->ps += ts; exz->pe += ts; + exz->ts += qs; exz->te += qs; +} + + +int64_t hc_aln_exz_adv_hc(overlap_region *z, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, +char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t mode, int64_t wl, +bit_extz_t *exz, int64_t q_tot, double e_rate, int64_t maxl, int64_t maxe, int64_t force_l, +int64_t estimate_err, overlap_region *aux_o) +{ + clear_align(*exz); exz->thre = 0; + if(((ts == -1) && (te == -1))) mode = 3;///set to semi-global + int64_t thre, ql = qe - qs, thre0, pts = -1, pte = -1, pthre = -1, full = 0; + if(ql == 0 && (te-ts) == 0) return 1; + if((ql <= 0) || (te-ts) <= 0) return 0; + if(estimate_err < 0) estimate_err = cal_estimate_err_hc(z, wl, qs, qe, ts, te, e_rate, &full); + + + + // if(ql <= 16) { + if(estimate_err == 0) { + if(full) { + // if(!cal_exact_exz(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, q_tot, mode)) { + // fprintf(stderr, "[M::%s::ql::%ld::%c] xid::%d, yid::%d, qs::[%ld, %ld), ts::[%ld, %ld), mode::%ld, est_err::%ld, e_rate::%f, maxe::%ld\n", + // __func__, ql, "+-"[z->y_pos_strand], z->x_id, z->y_id, qs, qe, ts, te, mode, estimate_err, e_rate, maxe); + // exit(1); + // } + set_exact_exz(exz, qs, qe, ts, te); push_alnw(aux_o, exz); + return 1; + } else if(cal_exact_exz(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, q_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::0(+)\n", exz->err, exz->thre); + push_alnw(aux_o, exz); + return 1; + } + } + + if(ql <= maxl && (estimate_err>>1) <= maxe) { + thre = scale_ed_thre(estimate_err, maxe); + if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(+)\n", exz->err, exz->thre, thre); + push_alnw(aux_o, exz); + return 1; + } + + thre0 = thre; thre = ql*e_rate; thre = scale_ed_thre(thre, maxe); + if(thre > thre0) { + if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); + push_alnw(aux_o, exz); + return 1; + } + } + + thre0 = thre; thre <<= 1; thre = scale_ed_thre(thre, maxe); + if(thre > thre0) { + if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); + push_alnw(aux_o, exz); + return 1; + } + } + + thre0 = thre; thre = ql*0.51; thre = scale_ed_thre(thre, maxe); + if(thre > thre0) { + if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); + push_alnw(aux_o, exz); + return 1; + } + } + + if(ql <= force_l) { + thre = maxe; + if(cal_exz_infi_adv(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, q_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); + push_alnw(aux_o, exz); + return 1; + } + } + } + // fprintf(stderr, ", err::%d, thre::%d\n", INT32_MAX, exz->thre); + // if(mode == 0) { + // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tu->length, tu->seq); + // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)(qe-qs), qstr+qs); + // } + return 0; + +} + +int64_t hc_aln_exz_non_retrieve_adv_hc(overlap_region *z, char* qstr, char* tstr, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t mode, int64_t wl, +bit_extz_t *exz, int64_t q_tot, int64_t t_tot, double e_rate, int64_t maxl, int64_t maxe, int64_t force_l, int64_t estimate_err, overlap_region *aux_o) +{ + clear_align(*exz); exz->thre = 0; + if(((ts == -1) && (te == -1))) mode = 3;///set to semi-global + int64_t thre, ql = qe - qs, thre0, pthre = -1, full = 0; + if(ql == 0 && (te-ts) == 0) return 1; + if((ql <= 0) || (te-ts) <= 0) return 0; + if(estimate_err < 0) estimate_err = cal_estimate_err_hc(z, wl, qs, qe, ts, te, e_rate, &full); + + + + // if(ql <= 16) { + if(estimate_err == 0) { + if(full) { + // if(!cal_exact_exz(z, uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, q_tot, mode)) { + // fprintf(stderr, "[M::%s::ql::%ld::%c] xid::%d, yid::%d, qs::[%ld, %ld), ts::[%ld, %ld), mode::%ld, est_err::%ld, e_rate::%f, maxe::%ld\n", + // __func__, ql, "+-"[z->y_pos_strand], z->x_id, z->y_id, qs, qe, ts, te, mode, estimate_err, e_rate, maxe); + // exit(1); + // } + set_exact_exz(exz, qs, qe, ts, te); push_alnw(aux_o, exz); + return 1; + } else if(cal_exact_non_retrieve_exz(z, exz, qstr, tstr, qs, qe, ts, te, q_tot, t_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::0(+)\n", exz->err, exz->thre); + push_alnw(aux_o, exz); + return 1; + } + } + + if(ql <= maxl && (estimate_err>>1) <= maxe) { + thre = scale_ed_thre(estimate_err, maxe); + if(cal_exz_infi_non_retrieve_adv(z, exz, qstr, tstr, qs, qe, ts, te, thre, &pthre, q_tot, t_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(+)\n", exz->err, exz->thre, thre); + push_alnw(aux_o, exz); + return 1; + } + + thre0 = thre; thre = ql*e_rate; thre = scale_ed_thre(thre, maxe); + if(thre > thre0) { + if(cal_exz_infi_non_retrieve_adv(z, exz, qstr, tstr, qs, qe, ts, te, thre, &pthre, q_tot, t_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); + push_alnw(aux_o, exz); + return 1; + } + } + + thre0 = thre; thre <<= 1; thre = scale_ed_thre(thre, maxe); + if(thre > thre0) { + if(cal_exz_infi_non_retrieve_adv(z, exz, qstr, tstr, qs, qe, ts, te, thre, &pthre, q_tot, t_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); + push_alnw(aux_o, exz); + return 1; + } + } + + thre0 = thre; thre = ql*0.51; thre = scale_ed_thre(thre, maxe); + if(thre > thre0) { + if(cal_exz_infi_non_retrieve_adv(z, exz, qstr, tstr, qs, qe, ts, te, thre, &pthre, q_tot, t_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); + push_alnw(aux_o, exz); + return 1; + } + } + + if(ql <= force_l) { + thre = maxe; + if(cal_exz_infi_non_retrieve_adv(z, exz, qstr, tstr, qs, qe, ts, te, thre, &pthre, q_tot, t_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); + push_alnw(aux_o, exz); + return 1; + } + } + } + // fprintf(stderr, ", err::%d, thre::%d\n", INT32_MAX, exz->thre); + // if(mode == 0) { + // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tu->length, tu->seq); + // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)(qe-qs), qstr+qs); + // } + return 0; + +} + +int64_t hc_aln_exz_non_retrieve_direct(char* qstr, char* tstr, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t mode, + bit_extz_t *exz, int64_t q_tot, int64_t t_tot, double e_rate, int64_t maxl, int64_t maxe, int64_t force_l, int64_t estimate_err) +{ + clear_align(*exz); exz->thre = 0; + int64_t thre, ql = qe - qs, tl = te-ts, thre0, pthre = -1; + if((ql < 0) || (tl < 0)) return 0; + + if((ql == 0) || (tl == 0)) { + if((ql > INT32_MAX) || (tl > INT32_MAX)) return 0; + exz->err = MAX(ql, tl); exz->cigar.n = 0; + exz->pl = tl; exz->ps = 0; exz->pe = tl-1; + exz->tl = ql; exz->ts = 0; exz->te = ql-1; + exz->ps += ts; exz->pe += ts; + exz->ts += qs; exz->te += qs; + + if(ql) { + push_trace(&(exz->cigar), 3, ql); + } else if(tl) { + push_trace(&(exz->cigar), 2, tl); + } + + return 1; + } + + // if((ql == 0) && (tl == 0)) return 1; + + if(estimate_err < 0) { + estimate_err = MAX(ql, tl); estimate_err *= e_rate; + thre0 = ((ql >= tl)?(ql - tl):(tl - ql)); + if(estimate_err < thre0) estimate_err = thre0; + } + + if(estimate_err == 0) { + if(cal_exact_non_retrieve_exz(NULL, exz, qstr, tstr, qs, qe, ts, te, q_tot, t_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::0(+)\n", exz->err, exz->thre); + // push_alnw(aux_o, exz); + return 1; + } + } + + if(ql <= maxl && (estimate_err>>1) <= maxe) { + thre = scale_ed_thre(estimate_err, maxe); + if(cal_exz_infi_non_retrieve_adv(NULL, exz, qstr, tstr, qs, qe, ts, te, thre, &pthre, q_tot, t_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(+)\n", exz->err, exz->thre, thre); + // push_alnw(aux_o, exz); + return 1; + } + + thre0 = thre; thre = ql*e_rate; thre = scale_ed_thre(thre, maxe); + if(thre > thre0) { + if(cal_exz_infi_non_retrieve_adv(NULL, exz, qstr, tstr, qs, qe, ts, te, thre, &pthre, q_tot, t_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); + // push_alnw(aux_o, exz); + return 1; + } + } + + thre0 = thre; thre <<= 1; thre = scale_ed_thre(thre, maxe); + if(thre > thre0) { + if(cal_exz_infi_non_retrieve_adv(NULL, exz, qstr, tstr, qs, qe, ts, te, thre, &pthre, q_tot, t_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); + // push_alnw(aux_o, exz); + return 1; + } + } + + thre0 = thre; thre = ql*0.51; thre = scale_ed_thre(thre, maxe); + if(thre > thre0) { + if(cal_exz_infi_non_retrieve_adv(NULL, exz, qstr, tstr, qs, qe, ts, te, thre, &pthre, q_tot, t_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); + // push_alnw(aux_o, exz); + return 1; + } + } + + if(ql <= force_l) { + thre = maxe; + if(cal_exz_infi_non_retrieve_adv(NULL, exz, qstr, tstr, qs, qe, ts, te, thre, &pthre, q_tot, t_tot, mode)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); + // push_alnw(aux_o, exz); + return 1; + } + } + } + + return 0; +} + +void prt_k_mer_hit(k_mer_hit *ch_a, int64_t ch_n) +{ + int64_t k; + for (k = 0; k < ch_n; k++) { + fprintf(stderr, "[M::%s::k->%ld] q_pos::%u, t_pos::%u, cnt::%u, cov::%u\n", + __func__, k, ch_a[k].self_offset, ch_a[k].offset, ch_a[k].cnt, ch_a[k].readID); + } + +} + +void debug_iter_k_mer_hit(k_mer_hit *ch_a, int64_t ch_n, uint64_t s, uint64_t e, int64_t ibeg, int64_t iend) +{ + int64_t i, beg = -1, end = -1; + for (i = 0; i < ch_n; i++) { + if((ch_a[i].self_offset >= s) && (ch_a[i].self_offset < e)) { + if(beg == -1) beg = i; + end = i+1; + } + } + assert(ibeg==beg && iend==end); +} + +int64_t chain_aln(overlap_region *z, Chain_Data *dp, k_mer_hit *ch_a, int64_t ch_n, const ul_idx_t *uref, +hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, +int64_t te, int64_t mode, int64_t wl, bit_extz_t *exz, int64_t q_tot, double e_rate, +int64_t min_chain_aln, uint64_t rid) +{ + int64_t *m, mn = 0, k; int64_t q[2], t[2], is_chain_aln = 1; + if(mode == 0) { + ///wrong + // assert((ch_n >= 2) && (ch_a[0].self_offset == qs) && (ch_a[0].offset == ts) && + // (ch_a[ch_n-1].self_offset == qe) && (ch_a[ch_n-1].offset == te)); + //does not work with CNS alignment; it also could not work here + if(ch_n == 2 && ((qe-qs)+128) < min_chain_aln) is_chain_aln = 0; + } else if(mode == 1) { + // assert((ch_n >= 1) && (ch_a[0].self_offset == qs) && (ch_a[0].offset == ts)); + //does not work with CNS alignment; it also could not work here + if(ch_n == 1 && ((qe-qs)+128) < min_chain_aln) is_chain_aln = 0; + } else if(mode == 2) { + // assert((ch_n >= 1) && (ch_a[ch_n-1].self_offset == qe) && (ch_a[ch_n-1].offset == te)); + //does not work with CNS alignment; it also could not work here + if(ch_n == 1 && ((qe-qs)+128) < min_chain_aln) is_chain_aln = 0; + } + + if(is_chain_aln) { + mn = lchain_refine(ch_a, ch_n, NULL, dp, 50, 5000, 512, 16); m = dp->tmp; + q[0] = qs; t[0] = ts; + for (k = 0; k < mn; k++) { + q[1] = ch_a[m[k]].self_offset; t[1] = ch_a[m[k]].offset; + if(q[1] > q[0]) { + if((t[0] != -1) && (t[1] != -1)) { + mode = 0;//global + } else if((t[0] != -1) && (t[1] == -1)) { + mode = 1;///forward extension + } else if((t[0] == -1) && (t[1] != -1)) { + mode = 2;///backward extension + } else { + mode = 3;//semi-global + } + if(!hc_aln_exz_adv(z, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, q_tot, e_rate, MAX_SIN_L, MAX_SIN_E, FORCE_SIN_L, -1, NULL)) { + + } + } + q[0] = q[1]; t[0] = t[1]; + } + q[1] = qe; t[1] = te; + if(q[1] > q[0]) { + if((t[0] != -1) && (t[1] != -1)) { + mode = 0;//global + } else if((t[0] != -1) && (t[1] == -1)) { + mode = 1;///forward extension + } else if((t[0] == -1) && (t[1] != -1)) { + mode = 2;///backward extension + } else { + mode = 3;//semi-global + } + if(!hc_aln_exz_adv(z, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, q_tot, e_rate, MAX_SIN_L, MAX_SIN_E, FORCE_SIN_L, -1, NULL)) { + + } + } + + } else { + + } + + // { + // q[0] = qs; t[0] = ts; q[1] = qe; t[1] = te; + // if(q[1] > q[0]) { + // hc_aln_exz_adv(z, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, q_tot, e_rate, MAX_SIN_L, MAX_SIN_E); + // } + // } + return 0; +} + +int64_t sub_base_aln(overlap_region *z, Chain_Data *dp, k_mer_hit *ch_a, int64_t ch_n, uint64_t pre_e, +uint64_t s, uint64_t e, int64_t wl, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, +char* qstr, UC_Read *tu, bit_extz_t *exz, double e_rate, int64_t ql, int64_t tl, +int64_t ch_i, uint64_t rid) +{ + int64_t i = ch_i, l, ibeg, iend, mode, q[2], t[2], ch_s, ch_e; + for (; i >= 0 && ch_a[i].self_offset >= s; i--); + if(i<0) {i = 0;} ibeg=iend=-1; + for (; i < ch_n && ch_a[i].self_offset < e; i++) { + if((ch_a[i].self_offset >= s) && (ch_a[i].self_offset < e)) { + if(ibeg < 0) ibeg = i; + iend = i+1; + } + } + // debug_iter_k_mer_hit(ch_a, ch_n, s, e, ibeg, iend); + // fprintf(stderr, "***[M::%s::rid->%lu] utg%.6dl(%c), s::%lu, e::%lu, z::[%u, %u), ibeg::%ld, iend::%ld\n", + // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], s, e, z->x_pos_s, z->x_pos_e+1, ibeg, iend); + ch_i = i; + if(ibeg >= 0 && iend >= 0 && iend > ibeg) {///find some anchors[ibeg, iend) + for (i = l = ibeg; i <= iend; i++) { + // fprintf(stderr, "\n[M::%s::i->%ld] q::%u, t::%u, cnt::%u, readID::%u\n", __func__, + // i, ch_a[i].self_offset, ch_a[i].offset, ch_a[i].cnt, ch_a[i].readID); + if(i == iend || is_pri_aln(ch_a[i])) { + q[0] = q[1] = t[0] = t[1] = -1; mode = ch_s = ch_e = -1; + if(l < i && l < iend && is_pri_aln(ch_a[l])) { + q[0] = ch_a[l].self_offset; t[0] = ch_a[l].offset; ch_s = l; + } else { + q[0] = s; + } + + if(i < iend && is_pri_aln(ch_a[i])) { + q[1] = ch_a[i].self_offset; t[1] = ch_a[i].offset; ch_e = i; + } else { + q[1] = e; + } + + if((t[0] != -1) && (t[1] != -1)) { + mode = 0;//global + } else if((t[0] != -1) && (t[1] == -1)) { + mode = 1;///forward extension + } else if((t[0] == -1) && (t[1] != -1)) { + mode = 2;///backward extension + } else { + mode = 3;//semi-global + } + + if((mode == 0) && is_alnw(ch_a[l]) && is_alnw(ch_a[i]) + && (ch_a[l].strand == 0) && (ch_a[i].strand == 1)) { + ; + } else { + // fprintf(stderr, "+[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", + // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode); + + if(mode == 1 || mode == 2) { + tuning_ext_offset(z, ch_a, ch_n, ql, tl, wl, MAX_SIN_L, 4, &ch_s, &ch_e, &q[0], &q[1], &t[0], &t[1], &mode); + } else if(ch_e >= 0) {//global + ch_e++; + } + if(!hc_aln_exz_adv(z, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E, FORCE_CNS_L, -1, NULL)) { + if(ch_s < 0) {ch_s = ibeg;} if(ch_e < 0) {ch_e = iend;} + assert(ch_e > ch_s); + // chain_aln(z, dp, ch_a+ch_s, ch_e-ch_s, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, ql, e_rate, MAX_CNS_L, rid); + } + } + l = i; + } + } + } else {//totoally no anchor; probably semi-global + // fprintf(stderr, "\n***[M::%s::rid->%lu] utg%.6dl(%c), s::%lu, e::%lu, z::[%u, %u), ibeg::%ld, iend::%ld\n", + // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], s, e, z->x_pos_s, z->x_pos_e+1, ibeg, iend); + } + + return ch_i; +} + +void cigar_gen_by_chain(overlap_region *z, Chain_Data *dp, k_mer_hit *ch_a, int64_t ch_n, ul_ov_t *ov, int64_t on, uint64_t wl, +const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, double e_rate, +int64_t ql, uint64_t rid) +{ + if(on <= 0) return; + int64_t i, ch_i, tl, id = z->y_id; uint64_t pe = (uint64_t)-1; + if(hpc_g) tl = hpc_len(*hpc_g, id); + else if(uref) tl = uref->ug->u.a[id].len; + else tl = Get_READ_LENGTH((*rref), id); + // for (i = 0; i < wn; i++) z->w_list.a[i].clen = 0;///clean cigar + // if(on > 1) { + // fprintf(stderr, "[M::%s::] rid::%lu, on::%ld\n", __func__, rid, on); + // } + // if(z->y_id == 126) prt_k_mer_hit(ch_a, ch_n); + for (i = ch_i = 0; i < on; i++) { + assert((i<=0)||(ov[i].qs > ov[i-1].qe)); + ch_i = sub_base_aln(z, dp, ch_a, ch_n, pe, ov[i].qs, ov[i].qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, tl, ch_i, rid); + pe = ov[i].qe; + } +} + + +int64_t adjust_base_coordinates(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, +ul_ov_t *res, int64_t wl, int64_t ql, int64_t tl, int64_t ch_i) +{ + res->ts = res->te = (uint32_t)-1; + res->sec = 3; res->qn = res->tn = (uint32_t)-1; //semi-global + if(ch_n == 0) return ch_i; + int64_t i = ch_i, ibeg, iend; uint64_t s = res->qs, e = res->qe; + for (; i >= 0 && ch_a[i].self_offset >= s; i--){;} if(i < 0) {i = 0;} + for (; i < ch_n && ch_a[i].self_offset < s; i++){;} + if((i >= 0) && ((ch_a[i].self_offset > s) || (i >= ch_n))) {i--;} ibeg = i; ///if ch_a[i].self_offset == s, do nothing + for (i = (i>=0?i:0); i < ch_n && ch_a[i].self_offset < e; i++){;} iend = i; + ch_i = i;///ch_i must be here + ///ibeg might be < 0, iend might be == ch_n + ///1. [s, e) contain anchors + ///2. anchors contain [s, e) + // fprintf(stderr, "[M::%s::] ibeg::%ld, iend::%ld, ch_n::%ld\n", __func__, ibeg, iend, ch_n); + // if(ibeg >= 0) { + // fprintf(stderr, "[M::%s::] ch_a[ibeg].self_offset::%u, ch_a[ibeg].offset::%u\n", + // __func__, ch_a[ibeg].self_offset, ch_a[ibeg].offset); + // } + // if(ibeg+1 >= 0) { + // fprintf(stderr, "[M::%s::] ch_a[ibeg+1].self_offset::%u, ch_a[ibeg+1].offset::%u\n", + // __func__, ch_a[ibeg+1].self_offset, ch_a[ibeg+1].offset); + // } + + // if(iend < ch_n) { + // fprintf(stderr, "[M::%s::] ch_a[iend].self_offset::%u, ch_a[iend].offset::%u\n", + // __func__, ch_a[iend].self_offset, ch_a[iend].offset); + // } + // if(iend > 0) { + // fprintf(stderr, "[M::%s::] ch_a[iend-1].self_offset::%u, ch_a[iend-1].offset::%u\n", + // __func__, ch_a[iend-1].self_offset, ch_a[iend-1].offset); + // } + + // if(z->y_id == 109111) { + // int64_t di; + // fprintf(stderr, "[M::%s] ch_n::%ld, s::%lu, e::%lu, ibeg::%ld, iend::%ld\n", __func__, ch_n, s, e, ibeg, iend); + // for (di = 0; di < ch_n; di++) { + // fprintf(stderr, "[M::%s::di->%ld] qoff::%u, toff::%u\n", __func__, di, + // ch_a[di].self_offset, ch_a[di].offset); + // } + // } + + if(ibeg >= 0) { + res->qs = ch_a[ibeg].self_offset; + res->ts = ch_a[ibeg].offset; + res->qn = ibeg; + } else {//extension to left + res->qs = 0; res->qn = (uint32_t)-1; + } + + if(iend < ch_n) { + res->qe = ch_a[iend].self_offset; + res->te = ch_a[iend].offset; + res->tn = iend; + } else {//extension to right + res->qe = ql; res->tn = ch_n; + } + + return ch_i; +} + +inline int64_t translate_double_mode(uint64_t double_mode, uint64_t is_backward) +{ + if(double_mode == 0) return 0; + if(double_mode == 4) return 3; + if(double_mode == 1 || double_mode == 2) return double_mode; +} + +int64_t fusion_chain_ovlp(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, ul_ov_t *ov, int64_t on, uint64_t wl, int64_t ql, int64_t tl) +{ + int64_t i, srt, ch_i, m, os, oe, ovlp; ul_ov_t *p; + for (i = ch_i = 0, srt = 1; i < on; i++) { + // fprintf(stderr, "[M::%s::i->%ld] ovq::[%u, %u)\n", __func__, i, ov->qs, ov->qe); + ov[i].sec = 6;///do not know the aln type + ch_i = adjust_base_coordinates(z, ch_a, ch_n, &(ov[i]), wl, ql, tl, ch_i); + if(i > 0 && ov[i].qs < ov[i-1].qe) srt = 0; + } + if(on <= 1) return on; + + if(!srt) radix_sort_uov_srt_qs(ov, ov+on); + for (i = m = 1; i < on; i++) { + p = &(ov[m-1]); + os = MAX(p->qs, ov[i].qs); + oe = MIN(p->qe, ov[i].qe); + ovlp = oe - os; + if(ovlp >= 0) {//merge + p->qe = MAX(p->qe, ov[i].qe); + p->te = MAX(p->te, ov[i].te); + p->tn = MAX(p->tn, ov[i].tn); + } else {//new + ov[m++] = ov[i]; + } + } + + on = m; + return on; +} + +// void chain_win_aln(overlap_region *z, Chain_Data *dp, Candidates_list *cl, int64_t qs, int64_t qe, +// int64_t ts, int64_t te, int64_t ql, int64_t tl, int64_t wl, int64_t mode, bit_extz_t *exz) +// { + +// } + +int64_t ovlp_base_aln_all(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, +int64_t soff, int64_t eoff, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, +char* qstr, UC_Read *tu, ul_ov_t *ov, int64_t ql, int64_t tl, int64_t wl, bit_extz_t *exz, +overlap_region *aux_o, double e_rate) +{ + int64_t ibeg, iend, i, l, mode, q[2], t[2], is_done; + ibeg = soff; iend = eoff; + for (l = ibeg, i = ibeg + 1; i <= iend; i++) { + l = i - 1; + q[0] = q[1] = t[0] = t[1] = mode = -1; is_done = 0; + if(l >= 0) { + q[0] = ch_a[l].self_offset; t[0] = ch_a[l].offset; + } else { + q[0] = ov->qs; + } + + if(i < ch_n) { + q[1] = ch_a[i].self_offset; t[1] = ch_a[i].offset; + } else { + q[1] = ov->qe; + } + + if((t[0] != -1) && (t[1] != -1)) { + mode = 0;//global + } else if((t[0] != -1) && (t[1] == -1)) { + mode = 1;///forward extension + } else if((t[0] == -1) && (t[1] != -1)) { + mode = 2;///backward extension + } else { + mode = 3;///no primary hit within [ibeg, iend] + } + assert(mode != 3); + if(mode == 1 || mode == 2) adjust_ext_offset(&(q[0]), &(q[1]), &(t[0]), &(t[1]), ql, tl, 0, mode); + ///at cns chain, the base alignment fails; there is no anchor between soff and eoff + if((eoff-soff<=1) && (((q[1]-q[0])>>1) < MAX_CNS_E)) { + is_done = 0; + } else { + is_done = hc_aln_exz_adv(z, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, ql, e_rate, MAX_SIN_L, MAX_SIN_E, FORCE_SIN_L, -1, aux_o); + } + + if(!is_done) { + push_unmap_alnw(aux_o, q[0], q[1]-1, t[0], t[1]-1, mode); + // chain_win_aln(z, dp, cl, q[0], q[1], t[0], t[1], ql, tl, wl, exz); + } + // if(aux_o->y_id == 109111) { + // fprintf(stderr, "<[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld, is_done::%ld\n", + // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode, is_done); + // } + } + return 0; +} + +void ovlp_base_aln(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, +ul_ov_t *ov, int64_t wl, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, +bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, int64_t tl, uint64_t rid) +{ + int64_t ibeg, iend, i, l, mode, q[2], t[2], is_done; + if(ov->qn == ((uint32_t)-1)) ibeg = -1; + else ibeg = ov->qn; + iend = ov->tn; + assert(iend>=ibeg+1); + // fprintf(stderr, "\n***[M::%s::rid->%lu] utg%.6dl(%c), s::%u, e::%u, z::[%u, %u), ibeg::%ld, iend::%ld, ch_n::%ld\n", + // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], ov->qs, ov->qe, z->x_pos_s, z->x_pos_e+1, ibeg, iend, ch_n); + for (l = ibeg, i = ibeg + 1; i <= iend; i++) { + if(i == iend || is_pri_aln(ch_a[i])) { + q[0] = q[1] = t[0] = t[1] = mode = -1; is_done = 0; + if(l >= 0) { + q[0] = ch_a[l].self_offset; t[0] = ch_a[l].offset; + } else { + q[0] = ov->qs; + } + + if(i < ch_n) { + q[1] = ch_a[i].self_offset; t[1] = ch_a[i].offset; + } else { + q[1] = ov->qe; + } + + if((t[0] != -1) && (t[1] != -1)) { + mode = 0;//global + } else if((t[0] != -1) && (t[1] == -1)) { + mode = 1;///forward extension + } else if((t[0] == -1) && (t[1] != -1)) { + mode = 2;///backward extension + } else { + mode = 3;///no primary hit within [ibeg, iend] + } + + if((mode == 0) && is_alnw(ch_a[l]) && is_alnw(ch_a[i]) + && (ch_a[l].strand == 0) && (ch_a[i].strand == 1)) { + is_done = 1; + // if(aux_o->x_id == 29033 && aux_o->y_id == 21307){ + // fprintf(stderr, "*[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", + // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode); + // } + // push_replace_alnw(aux_o, q[0], q[1]-1, t[0], t[1]-1, mode);///no need this + push_replace_alnw_adv(z, wl, aux_o, q[0], q[1]-1, t[0], t[1]-1, mode); + } else if(mode != 3) { + if(mode == 1 || mode == 2) adjust_ext_offset(&(q[0]), &(q[1]), &(t[0]), &(t[1]), ql, tl, 0, mode); + // if(aux_o->x_id == 29033 && aux_o->y_id == 21307){ + // fprintf(stderr, "#[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", + // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode); + // } + is_done = hc_aln_exz_adv(z, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E, FORCE_CNS_L, -1, aux_o); + } + + if(!is_done) {///postprocess + // if(aux_o->x_id == 29033 && aux_o->y_id == 21307){ + // fprintf(stderr, ">[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", + // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode); + // } + is_done = ovlp_base_aln_all(z, ch_a, ch_n, l, i, uref, hpc_g, rref, qstr, tu, ov, ql, tl, wl, exz, aux_o, e_rate); + } + // if(aux_o->x_id == 29033 && aux_o->y_id == 21307){ + // fprintf(stderr, "-is_done::%ld[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld, l::%ld, i::%ld, ch_n::%ld\n", + // is_done, __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode, l, i, ch_n); + // } + // if(rid == (uint64_t)-1) { + // fprintf(stderr, "+is_done::%ld[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld, l::%ld, i::%ld, ch_n::%ld\n", + // is_done, __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode, l, i, ch_n); + // } + l = i; + } + } + +} + +inline void push_khit(Candidates_list *res, int32_t xs, int32_t ys, uint32_t len, uint32_t h_khit, uint32_t *ic) +{ + uint32_t p, c; k_mer_hit *z; + c = ((len >= h_khit)?1:2); if(ic) c = *ic; c <<= 8; + if(len > 0) { + while (len >= (0xffu)) { + p = (c + (0xffu)); + kv_pushp_cl(k_mer_hit, (*res), &z); + memset(z, 0, sizeof((*z))); + z->self_offset = xs; z->offset = ys; z->cnt = p; + len -= (0xffu); + } + if(len) { + p = (c + len); + kv_pushp_cl(k_mer_hit, (*res), &z); + memset(z, 0, sizeof((*z))); + z->self_offset = xs; z->offset = ys; z->cnt = p; + } + } else { + p = (c + len); + kv_pushp_cl(k_mer_hit, (*res), &z); + memset(z, 0, sizeof((*z))); + z->self_offset = xs; z->offset = ys; z->cnt = p; + } +} + +uint32_t extract_exact_cigar(asg16_v *ez, int32_t ps, int32_t ts, int32_t pmin, int32_t pmax, +int32_t tmin, int32_t tmax, Candidates_list *res, int32_t minl, int64_t min_w_l, int64_t h_khit) +{ + uint32_t ci = 0, cl, occ = 0; uint16_t c; + int32_t pi = ps, ti = ts, p[2], t[2], poff, toff, maxl; + int32_t pos, poe, tos, toe, l; poff = toff = maxl = -1; + while (ci < ez->n && pi < pmax && ti < tmax) { + ci = pop_trace(ez, ci, &c, &cl); + if(c == 0) { + p[0] = pi; p[1] = pi + cl; + t[0] = ti; t[1] = ti + cl; + pos = MAX(p[0], pmin); poe = MIN(p[1], pmax); + tos = MAX(t[0], tmin); toe = MIN(t[1], tmax); + if((poe > pos) && (toe > tos)) { + l = poe - pos; + if(l == (toe - tos)) { + poe--; toe--; + if(l > maxl) { + poff = poe; toff = toe; maxl = l; + } + if(l >= minl) { + push_khit(res, toe, poe, l, h_khit, NULL); occ++; + } + } + } + pi+=cl; ti+=cl; + } else if(c == 1) { + pi+=cl; ti+=cl; + } else if(c == 2) {///more p + pi+=cl; + } else if(c == 3) { + ti+=cl; + } + } + ///(ts >= tmin) && (ti >= (min_w_l + ts)): here is a whole window + if(maxl > 0 && maxl < minl && (ts >= tmin) && (ti >= (min_w_l + ts))) { + uint32_t w = 3; + push_khit(res, toff, poff, maxl, h_khit, &w); occ++; + } + return occ; +} + +int64_t debug_k_mer_hit_retrive(k_mer_hit *z, hpc_t *hpc_g, All_reads *rref, const ul_idx_t *uref, +char* qstr, UC_Read *tu, int64_t id, int64_t rev) +{ + int64_t qs, qe, ts, te; char *q_string, *t_string; + qe = z->self_offset+1; qs = qe - (z->cnt&(0xffu)); + te = z->offset+1; ts = te - (z->cnt&(0xffu)); + if(qe == qs) return 1; + q_string = qstr + qs; + t_string = retrieve_str_seq_exz(tu, ts, te-ts, -1, -1, rev, uref, hpc_g, rref, id); + fprintf(stderr, "[M::%s::] q_string::%.*s\n", __func__, (int32_t)(qe-qs), q_string); + fprintf(stderr, "[M::%s::] t_string::%.*s\n", __func__, (int32_t)(te-ts), t_string); + if(memcmp(q_string, t_string, qe-qs)) { + fprintf(stderr, "[M::%s::] qsite::%u, tsite::%u\n", __func__, z->self_offset, z->offset); + return 0; + } + return 1; +} + +int64_t gen_single_khit(Candidates_list *cl, int64_t ch_n, int64_t h_khit, int64_t mode, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t max_skip, int64_t max_iter, int64_t rid) +{ + // if(ch_n != 3 || mode != 0 || qs != 171728 || qe != 172258) return 0; + k_mer_hit *ch_a = cl->list + cl->length; int64_t k, i, j, occ, m, ncn, prefix, suffix, srt = 1; + prefix = suffix = 0; + if(mode == 0 || mode == 2) suffix = 1; + if(mode == 0 || mode == 1) prefix = 1; + // if(ch_n == 2 && mode == 2 && qe - qs == 2419 && te - ts == 2419) { + // fprintf(stderr, "[M::%s::mode->%ld] ch_n::%ld, q::[%ld, %ld), t::[%ld, %ld)\n", + // __func__, mode, ch_n, qs, qe, ts, te); + // } + + for (k = occ = m = 0; k < ch_n; k++) { + // if(ch_n == 2 && mode == 2 && qe - qs == 2419 && te - ts == 2419) { + // fprintf(stderr, "+i::%ld[M::%s::] x::[%u, %u), y::[%u, %u), cnt::%u\n", k, __func__, + // ch_a[k].self_offset+1-(ch_a[k].cnt&((uint32_t)(0xffu))), ch_a[k].self_offset+1, + // ch_a[k].offset+1-(ch_a[k].cnt&((uint32_t)(0xffu))), ch_a[k].offset+1, (ch_a[k].cnt&(0xffu))); + // } + if(!(ch_a[k].cnt&(0xffu))) continue; + occ++; + if((ch_a[k].cnt&(0xffu)) > 1) occ++; + ch_a[m++] = ch_a[k]; + } + ch_n = m; if(!ch_n) return ch_n; + occ += prefix + suffix; + // if(ch_n == 2 && mode == 2 && qe - qs == 2419 && te - ts == 2419) { + // fprintf(stderr, "+[M::%s::] occ::%ld\n", __func__, occ); + // } + + ncn = occ + cl->length; + if(cl->size < ncn) { + cl->size = ncn; + REALLOC(cl->list, cl->size); + // cl->list = (k_mer_hit*)realloc(cl->list, (sizeof((*(cl->list)))*cl->length)); + } + ch_a = cl->list + cl->length; assert((cl->length+occ)<= cl->size); + + k_mer_hit cht; + ///global or backward + if(suffix) { + cht.self_offset = qe; + cht.offset = te; + cht.cnt = 1; cht.readID = 1;//make it as primary chain + cht.strand = 0; + ch_a[--occ] = cht; + // fprintf(stderr, "occ::%ld[M::%s::] x::%u, y::%u, cnt::%u, cov::%u\n", occ, __func__, + // cht.self_offset, cht.offset, cht.cnt, cht.readID); + } + for (k = ch_n-1; k >= 0; k--) { + if(!(ch_a[k].cnt&(0xffu))) continue; + ///end + cht.self_offset = ch_a[k].self_offset+1; + cht.offset = ch_a[k].offset+1; + cht.strand = 0; + cht.cnt = cht.readID = (ch_a[k].cnt&(0xffu)); + //make it as non-primary chain + if((ch_a[k].cnt&(0xffu)) < h_khit) cht.readID = cht.cnt + 1; + ch_a[--occ] = cht; + // fprintf(stderr, "occ::%ld[M::%s::] x::%u, y::%u, cnt::%u, cov::%u\n", occ, __func__, + // cht.self_offset, cht.offset, cht.cnt, cht.readID); + + if((ch_a[k].cnt&(0xffu)) > 1) { + ///start + cht.self_offset = ch_a[k].self_offset+1-(ch_a[k].cnt&(0xffu)); + cht.offset = ch_a[k].offset+1-(ch_a[k].cnt&(0xffu)); + cht.strand = 0; + cht.cnt = cht.readID = (ch_a[k].cnt&(0xffu)); + //make it as non-primary chain + if((ch_a[k].cnt&(0xffu)) < h_khit) cht.readID = cht.cnt + 1; + ch_a[--occ] = cht; + // fprintf(stderr, "occ::%ld[M::%s::] x::%u, y::%u, cnt::%u, cov::%u\n", occ, __func__, + // cht.self_offset, cht.offset, cht.cnt, cht.readID); + } + } + + if(prefix) { ///global or forward + cht.self_offset = qs; + cht.offset = ts; + cht.cnt = 1; cht.readID = 1;//make it as primary chain + cht.strand = 0; + ch_a[--occ] = cht; + // fprintf(stderr, "occ::%ld[M::%s::] x::%u, y::%u, cnt::%u, cov::%u\n", occ, __func__, + // cht.self_offset, cht.offset, cht.cnt, cht.readID); + } + // if(ch_n == 2 && mode == 2 && qe - qs == 2419 && te - ts == 2419) { + // fprintf(stderr, "-[M::%s::] occ::%ld\n", __func__, occ); + // } + // if(!(occ == 0)) { + // fprintf(stderr, "[M::%s] rid::%ld, name::%.*s\n", __func__, rid, + // (int32_t)UL_INF.nid.a[rid].n, UL_INF.nid.a[rid].a); + // } + assert(occ == 0); + ch_n = occ = ncn - cl->length; + uint64_t q[2], t[2]; + q[0] = q[1] = t[0] = t[1] = (uint64_t)-1; + if(prefix) { + q[0] = qs; t[0] = ts; + } + if(suffix) { + q[1] = qe; t[1] = te; + } + + // for (k = 0; k < ch_n; k++) { + // fprintf(stderr, "0) && (ch_a[k].self_offset==q[0]) && (ch_a[k].offset=t[0])) continue; + if(((k+1)0) { + if((ch_a[k].self_offset>ch_a[m-1].self_offset) && (ch_a[k].offset>ch_a[m-1].offset)) { + occ++; + } + if(ch_a[k].self_offset<=ch_a[m-1].self_offset) srt = 0; + } else { + occ++; + } + ch_a[m++] = ch_a[k]; + } + ch_n = m; + if(occ == ch_n) return ch_n;///already colinear + if(!srt) { + radix_sort_k_mer_hit_self(ch_a, ch_a + ch_n); + for (i = 1, j = 0; i <= ch_n; i++) { + if (i == ch_n || ch_a[i].self_offset != ch_a[j].self_offset) { + if(i - j > 1) radix_sort_k_mer_hit_off(ch_a+j, ch_a+i); + j = i; + } + } + } + + // for (k = 0; k < ch_n; k++) { + // fprintf(stderr, ">i::%ld[M::%s::] x::%u, y::%u, cnt::%u, cov::%u\n", k, __func__, + // ch_a[k].self_offset, ch_a[k].offset, ch_a[k].cnt, ch_a[k].readID); + // } + occ = ch_n; + ch_n = lchain_simple(ch_a+prefix, ch_n-prefix-suffix, ch_a+prefix, &(cl->chainDP), max_skip, max_iter); + ch_n += prefix + suffix; if(suffix) ch_a[ch_n-1] = ch_a[occ-1]; + // for (k = 0; k < ch_n; k++) { + // fprintf(stderr, "-i::%ld[M::%s::] x::%u, y::%u, cnt::%u, cov::%u\n", k, __func__, + // ch_a[k].self_offset, ch_a[k].offset, ch_a[k].cnt, ch_a[k].readID); + // } + + return ch_n; +} + +///[qs, qe) && [ts, te) +int64_t gen_win_chain(overlap_region *z, Candidates_list *cl, int64_t qs, int64_t qe, int64_t ts, int64_t te, +int64_t wl, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, +int64_t ql, int64_t tl, double e_rate, int64_t h_khit, int64_t mode, int64_t rid, int64_t is_accurate) +{ + assert(mode < 3); + int64_t k, ws, we, os, oe, wsk, rcn = cl->length, ncn, occ = 0, ovlp, wn = z->w_list.n; asg16_v ez; uint32_t w = 1; + ws = qs; if(ws < z->x_pos_s) ws = z->x_pos_s; + we = qe-1; if(we > z->x_pos_e) we = z->x_pos_e; + wsk = get_win_id_by_s(z, ((ws/wl)*wl), wl, NULL); + // if(rid == 7) { + // fprintf(stderr, "[M::%s::]\tutg%.6u%c\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\tq::[%ld,%ld)\tw::[%ld,%ld]\twn::%ld\twsk::%ld\n", __func__, + // z->x_id+1, "lc"[uref->ug->u.a[z->x_id].circ], + // z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[uref->ug->u.a[z->y_id].circ], + // z->y_pos_s, z->y_pos_e+1, qs, qe, ws, we, wn, wsk); + // } + // assert((ws>=z->w_list.a[wsk].x_start) && (ws<=z->w_list.a[wsk].x_end)); + // wek = get_win_id_by_e(z, ((we/wl)*wl), wl, NULL); + // assert((we>=z->w_list.a[wek].x_start) && (we<=z->w_list.a[wek].x_end)); + for(wsk=((wskz->w_list.a[wsk].x_end; wsk++); + for(wsk=((wsk=0 && qsw_list.a[wsk].x_start; wsk--); + if(wsk < 0) wsk = 0; ///qs >= z->w_list.a[wsk].x_start && qs <= z->w_list.a[wsk].x_end + ///global or forward + if(mode == 0 || mode == 1) push_khit(cl, qs, ts, 0, 0, &w); + //[ws, we] && [wsk, wek]; [qs, qe) && [ts, te) + for (k = wsk; kw_list.a[k].x_startw_list.a[k].y_end == -1) continue; + ws = z->w_list.a[k].x_start; we = z->w_list.a[k].x_end+1; + os = MAX(qs, ws); oe = MIN(qe, we); ovlp = ((oe>os)? (oe-os):0); + if(!ovlp) continue; + if(!(z->w_list.a[k].clen)) { + gen_backtrace_adv_exz(&(z->w_list.a[k]), z, rref, hpc_g, uref, qstr, tu->seq, exz, z->y_pos_strand, z->y_id); + } + ez.a = z->w_list.c.a + z->w_list.a[k].cidx; + ez.n = ez.m = z->w_list.a[k].clen; + occ += extract_exact_cigar(&ez, z->w_list.a[k].y_start, z->w_list.a[k].x_start, ts, te, qs, qe, cl, 10, wl, h_khit); + } + ///global or backward + if(mode == 0 || mode == 2) push_khit(cl, qe-1, te-1, 0, 0, &w); + // fprintf(stderr, "[M::%s::] rcn::%ld, cl->length::%lld\n", __func__, rcn, cl->length); + if(!occ) { + cl->length = rcn; return 0; + } + ncn = cl->length; cl->length = rcn; + k_mer_hit *ch_a = cl->list + rcn; int64_t ch_n0 = ncn - rcn, ch_n; + int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; + set_lchain_dp_op(is_accurate, h_khit, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); + max_dis = MAX_SIN_L>>1; + // for (k = 0; k < ch_n0; k++) { + // assert(debug_k_mer_hit_retrive(&(ch_a[k]), hpc_g, rref, uref, qstr, tu, z->y_id, z->y_pos_strand)); + // } + ch_n = lchain_qdp_fix(ch_a, ch_n0, &(cl->chainDP), max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, + e_rate, ql, tl, 1, ((mode==0)||(mode==1))?1:0, ((mode==0)||(mode==2))?1:0); + for (k = occ = 0; k < ch_n; k++) { + ch_a[k] = ch_a[cl->chainDP.tmp[k]]; + if((ch_a[k].cnt&(0xffu))) occ++; + // assert(debug_k_mer_hit_retrive(&(ch_a[k]), hpc_g, rref, uref, qstr, tu, z->y_id, z->y_pos_strand)); + } + // fprintf(stderr, "[M::%s::] ch_n0::%ld, ch_n::%ld, mode::%ld, ql::%ld, tl::%ld, occ::%ld\n", + // __func__, ch_n0, ch_n, mode, qe-qs, te-ts, occ); + if(occ <= 0) return 0; + ch_n = gen_single_khit(cl, ch_n, h_khit, mode, qs, qe, ts, te, max_skip, max_iter, rid); + return ch_n; +} + + +///[qs, qe) && [ts, te) +int64_t gen_win_non_retrieve_chain(overlap_region *z, Candidates_list *cl, int64_t qs, int64_t qe, int64_t ts, int64_t te, +int64_t wl, char* qstr, char* tstr, bit_extz_t *exz, int64_t ql, int64_t tl, double e_rate, int64_t h_khit, int64_t mode, int64_t rid, int64_t is_accurate) +{ + assert(mode < 3); + int64_t k, ws, we, os, oe, wsk, rcn = cl->length, ncn, occ = 0, ovlp, wn = z->w_list.n; asg16_v ez; uint32_t w = 1; + ws = qs; if(ws < z->x_pos_s) ws = z->x_pos_s; + we = qe-1; if(we > z->x_pos_e) we = z->x_pos_e; + wsk = get_win_id_by_s(z, ((ws/wl)*wl), wl, NULL); + // if(rid == 7) { + // fprintf(stderr, "[M::%s::]\tutg%.6u%c\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\tq::[%ld,%ld)\tw::[%ld,%ld]\twn::%ld\twsk::%ld\n", __func__, + // z->x_id+1, "lc"[uref->ug->u.a[z->x_id].circ], + // z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[uref->ug->u.a[z->y_id].circ], + // z->y_pos_s, z->y_pos_e+1, qs, qe, ws, we, wn, wsk); + // } + // assert((ws>=z->w_list.a[wsk].x_start) && (ws<=z->w_list.a[wsk].x_end)); + // wek = get_win_id_by_e(z, ((we/wl)*wl), wl, NULL); + // assert((we>=z->w_list.a[wek].x_start) && (we<=z->w_list.a[wek].x_end)); + for(wsk=((wskz->w_list.a[wsk].x_end; wsk++); + for(wsk=((wsk=0 && qsw_list.a[wsk].x_start; wsk--); + if(wsk < 0) wsk = 0; ///qs >= z->w_list.a[wsk].x_start && qs <= z->w_list.a[wsk].x_end + ///global or forward + if(mode == 0 || mode == 1) push_khit(cl, qs, ts, 0, 0, &w); + //[ws, we] && [wsk, wek]; [qs, qe) && [ts, te) + for (k = wsk; kw_list.a[k].x_startw_list.a[k].y_end == -1) continue; + ws = z->w_list.a[k].x_start; we = z->w_list.a[k].x_end+1; + os = MAX(qs, ws); oe = MIN(qe, we); ovlp = ((oe>os)? (oe-os):0); + if(!ovlp) continue; + if(!(z->w_list.a[k].clen)) { + gen_backtrace_non_retrieve_adv_exz(&(z->w_list.a[k]), z, qstr, tstr, tl, exz, z->y_pos_strand, z->y_id); + } + ez.a = z->w_list.c.a + z->w_list.a[k].cidx; + ez.n = ez.m = z->w_list.a[k].clen; + occ += extract_exact_cigar(&ez, z->w_list.a[k].y_start, z->w_list.a[k].x_start, ts, te, qs, qe, cl, 10, wl, h_khit); + } + ///global or backward + if(mode == 0 || mode == 2) push_khit(cl, qe-1, te-1, 0, 0, &w); + // fprintf(stderr, "[M::%s::] rcn::%ld, cl->length::%lld\n", __func__, rcn, cl->length); + if(!occ) { + cl->length = rcn; return 0; + } + ncn = cl->length; cl->length = rcn; + k_mer_hit *ch_a = cl->list + rcn; int64_t ch_n0 = ncn - rcn, ch_n; + int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; + set_lchain_dp_op(is_accurate, h_khit, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); + max_dis = MAX_SIN_L>>1; + // for (k = 0; k < ch_n0; k++) { + // assert(debug_k_mer_hit_retrive(&(ch_a[k]), hpc_g, rref, uref, qstr, tu, z->y_id, z->y_pos_strand)); + // } + ch_n = lchain_qdp_fix(ch_a, ch_n0, &(cl->chainDP), max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, + e_rate, ql, tl, 1, ((mode==0)||(mode==1))?1:0, ((mode==0)||(mode==2))?1:0); + for (k = occ = 0; k < ch_n; k++) { + ch_a[k] = ch_a[cl->chainDP.tmp[k]]; + if((ch_a[k].cnt&(0xffu))) occ++; + // assert(debug_k_mer_hit_retrive(&(ch_a[k]), hpc_g, rref, uref, qstr, tu, z->y_id, z->y_pos_strand)); + } + // fprintf(stderr, "[M::%s::] ch_n0::%ld, ch_n::%ld, mode::%ld, ql::%ld, tl::%ld, occ::%ld\n", + // __func__, ch_n0, ch_n, mode, qe-qs, te-ts, occ); + if(occ <= 0) return 0; + ch_n = gen_single_khit(cl, ch_n, h_khit, mode, qs, qe, ts, te, max_skip, max_iter, rid); + return ch_n; +} + + + +void rechain_aln(overlap_region *z, Candidates_list *cl, overlap_region *aux_o, int64_t aux_i, int64_t wl, +const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, double e_rate, +int64_t ql, int64_t tl, int64_t h_khit, int64_t rid) +{ + int64_t rcn = cl->length, ch_n, qs, qe, ts, te, mode, an0, an, todo; + k_mer_hit *ch_a; ul_ov_t idx; uint8_t q[2], t[2]; + ///[qs, qe) && [ts, te) + qs = aux_o->w_list.a[aux_i].x_start; qe = aux_o->w_list.a[aux_i].x_end+1; + ts = aux_o->w_list.a[aux_i].y_start; te = aux_o->w_list.a[aux_i].y_end+1; + if(qe - qs < FORCE_SIN_L || te - ts < FORCE_SIN_L) return; + mode = aux_o->w_list.a[aux_i].error_threshold; + ch_n = gen_win_chain(z, cl, qs, qe, ts, te, wl, uref, hpc_g, rref, qstr, tu, exz, ql, tl, e_rate, h_khit, mode, rid, 0); + ch_a = cl->list + rcn; + if(ch_n) { + idx.ts = idx.te = (uint32_t)-1; idx.qs = 0; idx.qe = ql; todo = 1; + if(mode == 0) {//global + idx.qn = 0; idx.tn = ch_n - 1; + idx.qs = ch_a[idx.qn].self_offset; + idx.ts = ch_a[idx.qn].offset; + idx.qe = ch_a[idx.tn].self_offset; + idx.te = ch_a[idx.tn].offset; + assert(ch_a[0].self_offset == qs && ch_a[0].offset == ts); + assert(ch_a[ch_n-1].self_offset == qe && ch_a[ch_n-1].offset == te); + if(ch_n <= 2) todo = 0; + } else if(mode == 1) {//forward ext + idx.qn = 0; idx.tn = ch_n; + idx.qs = ch_a[idx.qn].self_offset; + idx.ts = ch_a[idx.qn].offset; + idx.qe = ql; + assert(ch_a[0].self_offset == qs && ch_a[0].offset == ts); + if(ch_n <= 1) todo = 0; + } else if(mode == 2) {///backward ext + idx.qn = (uint32_t)-1; idx.tn = ch_n-1; + idx.qs = 0; + idx.qe = ch_a[idx.tn].self_offset; + idx.te = ch_a[idx.tn].offset; + assert(ch_a[ch_n-1].self_offset == qe && ch_a[ch_n-1].offset == te); + if(ch_n <= 1) todo = 0; + } + if(todo) { + an0 = aux_o->w_list.n; + // if(z->x_id == 29033 && z->y_id == 21307) { + // fprintf(stderr, "[M::%s]\tan0::%ld\tq::[%u,\t%u)\tt::[%u,\t%u)\tlw::%u\trw::%u\n", __func__, an0, + // idx.qs, idx.qe, idx.ts, idx.te, idx.qn, idx.tn); + // } + ovlp_base_aln(z, ch_a, ch_n, &idx, wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, tl, (uint64_t)-1); + an = aux_o->w_list.n; q[0] = q[1] = t[0] = t[1] = 0; todo = 0; + // if(z->x_id == 29033 && z->y_id == 21307) { + // fprintf(stderr, "[M::%s]\tan::%ld\n", __func__, an); + // } + // fprintf(stderr, "[M::%s::] awn0::%ld, awn::%lu\n", __func__, an0, an); + ///old unaligned window could be replaced by the new aligned window + if((an == (an0 + 1)) && (!(is_ualn_win(aux_o->w_list.a[an-1])))) { + if(aux_o->w_list.a[aux_i].x_start == aux_o->w_list.a[an-1].x_start) q[0] = 1; + if(aux_o->w_list.a[aux_i].x_end == aux_o->w_list.a[an-1].x_end) q[1] = 1; + if(aux_o->w_list.a[aux_i].y_start == aux_o->w_list.a[an-1].y_start) t[0] = 1; + if(aux_o->w_list.a[aux_i].y_end == aux_o->w_list.a[an-1].y_end) t[1] = 1; + if((mode == 0) && q[0] && q[1] && t[0] && t[1]) todo = 1; + if((mode == 1) && q[0] && t[0]) todo = 1; + if((mode == 2) && q[1] && t[1]) todo = 1; + if(todo) { + aux_o->w_list.a[aux_i] = aux_o->w_list.a[an-1]; aux_o->w_list.n--; + } + } + // if(an > an0) {///should always > 0 as there are unmapped windows + // } + // aux_o->w_list.n = an0; + } + } + cl->length = rcn;///must reset!!!! +} + +void debug_overlap_region(overlap_region *au, char* qstr, UC_Read *tu, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref) +{ + int64_t wn = au->w_list.n, k; bit_extz_t ez; + for (k = 0; k < wn; k++) { + assert((k<=0)||((au->w_list.a[k].x_start>au->w_list.a[k-1].x_end) + &&(au->w_list.a[k].y_start>au->w_list.a[k-1].y_end))); + // if(!((k<=0)||((au->w_list.a[k].x_start>au->w_list.a[k-1].x_end) + // &&(au->w_list.a[k].y_start>au->w_list.a[k-1].y_end)))) { + // if(k > 0) { + // fprintf(stderr, "\n[M::%s::(k-1)->%ld] x::[%u, %u], y::[%u, %u]\n", + // __func__, k-1, au->w_list.a[k-1].x_start, au->w_list.a[k-1].x_end, au->w_list.a[k-1].y_start, au->w_list.a[k-1].y_end); + // fprintf(stderr, "[M::%s::(k**)->%ld] x::[%u, %u], y::[%u, %u]\n", + // __func__, k, au->w_list.a[k].x_start, au->w_list.a[k].x_end, au->w_list.a[k].y_start, au->w_list.a[k].y_end); + // } + + // } + assert(au->w_list.a[k].x_end>au->w_list.a[k].x_start); + // if(!(au->w_list.a[k].y_end>au->w_list.a[k].y_start)) { + // fprintf(stderr, "[M::%s::(k**)->%ld] x::[%u, %u], y::[%u, %u]\n", + // __func__, k, au->w_list.a[k].x_start, au->w_list.a[k].x_end, au->w_list.a[k].y_start, au->w_list.a[k].y_end); + // } + assert(au->w_list.a[k].y_end>au->w_list.a[k].y_start); + if(is_ualn_win(au->w_list.a[k]) || is_est_aln(au->w_list.a[k])) continue; + ez.cigar.a = au->w_list.c.a + au->w_list.a[k].cidx; + ez.cigar.n = ez.cigar.m = au->w_list.a[k].clen; + ez.ts = au->w_list.a[k].x_start; ez.te = au->w_list.a[k].x_end; + ez.ps = au->w_list.a[k].y_start; ez.pe = au->w_list.a[k].y_end; + ez.err = au->w_list.a[k].error; + ref_cigar_check(qstr, tu, uref, hpc_g, rref, au->y_id, au->y_pos_strand, &ez); + } +} + + +void merge_hc_fast_cigar0(overlap_region *des, overlap_region *src) +{ + int64_t k = 0, i, wn = src->w_list.n, ck_s, ck_e, zk, e0, e, e_tot = 0, mz; + uint32_t op0 = (uint16_t)-1, ol0, op, ol, xs, ys, xk, yk, xe, ye; asg16_v b16; window_list *p; + copy_asg_arr(b16, des->w_list.c); b16.n = 0; des->w_list.n = 0; + + // fprintf(stderr, "\n[M::%s::aln::-xid->%u]\n", __func__, src->x_id); + + // /**if(z->y_id == 310315)**/ { + // for (i = 0; i < wn; i++) { + // fprintf(stderr, "[aln::-i->%ld::ql->%d] q::[%d, %d), t::[%d, %d), err::%d, cidx::%u, clen::%u, mode::%d\n", i, + // src->w_list.a[i].x_end+1-src->w_list.a[i].x_start, + // src->w_list.a[i].x_start, src->w_list.a[i].x_end+1, + // src->w_list.a[i].y_start, src->w_list.a[i].y_end+1, + // src->w_list.a[i].error, src->w_list.a[i].cidx, src->w_list.a[i].clen, src->w_list.a[i].error_threshold); + // } + // } + + while (k < wn) { + if((!(is_ualn_win(src->w_list.a[k])))) { + for (i = k + 1, e_tot = src->w_list.a[k].error; (i < wn) && (!(is_ualn_win(src->w_list.a[i]))); i++) { + if(((src->w_list.a[i].x_start) != (src->w_list.a[i-1].x_end + 1)) || ((src->w_list.a[i].y_start) != (src->w_list.a[i-1].y_end + 1))) { + break; + } + e_tot += src->w_list.a[i].error; + } + ///z->w_list.a[k, i) + // ck_s = z->w_list.a[k].cidx; ck_e = z->w_list.a[i-1].cidx + z->w_list.a[i-1].clen; + + if(i - k > 1) { + xk = src->w_list.a[k].x_start; yk = src->w_list.a[k].y_start; + xe = src->w_list.a[i-1].x_end + 1; ye = src->w_list.a[i-1].y_end + 1; + p = &(des->w_list.a[des->w_list.n++]); + + p->x_start = src->w_list.a[k].x_start; + p->x_end = src->w_list.a[k].x_start - 1; + p->y_start = src->w_list.a[k].y_start; + p->y_end = src->w_list.a[k].y_start - 1; + p->cidx = b16.n; + p->clen = 0; + p->error = 0; + p->error_threshold = 0; + + for (mz = k, e0 = e = 0; mz < i; mz++) { + ck_s = src->w_list.a[mz].cidx; + ck_e = src->w_list.a[mz].cidx + src->w_list.a[mz].clen; + + for (zk = ck_s; zk < ck_e; zk++) { + e0 = e; + op = (src->w_list.c.a[zk]>>14); + ol = (src->w_list.c.a[zk]&(0x3fff)); + xs = xk; ys = yk; + if(op!=2) xk += ol; + if(op!=3) yk += ol; + if(op != 0) e = e0 + ol; + if(e >= INT16_MAX) {///a new win + assert(e0 < INT16_MAX); + e_tot -= p->error; + p = &(des->w_list.a[des->w_list.n++]); + e = e - e0; + + p->x_start = xs; + p->y_start = ys; + p->x_end = xk - 1; + p->y_end = yk - 1; + p->cidx = b16.n; + p->error = e; + p->error_threshold = 0; + push_trace(&b16, op, ol); + p->clen = b16.n - p->cidx; + } else { + op0 = ((uint16_t)-1); ol0 = 0; + if(b16.n > p->cidx) { + op0 = (b16.a[b16.n-1]>>14); + ol0 = (b16.a[b16.n-1]&(0x3fff)); + } + if(op0 == op) {ol += ol0; b16.n--;} + push_trace(&b16, op, ol); + p->clen = b16.n - p->cidx; + p->x_end = xk - 1; + p->y_end = yk - 1; + p->error = e; + } + } + } + e_tot -= p->error; + // /**if(!(xe == xk && ye == yk && e_tot == 0))**/ { + // fprintf(stderr, "[M::%s::rid->%u] xk->%u, yk->%u, xe->%u, ye->%u, e_tot->%ld, wid::[%ld, %ld)\n", + // __func__, src->y_id, xk, yk, xe, ye, e_tot, k, i); + // } + assert(xe == xk && ye == yk && e_tot == 0); + } else { + des->w_list.a[des->w_list.n] = src->w_list.a[k]; + des->w_list.a[des->w_list.n].cidx = b16.n; + kv_resize(uint16_t, b16, (b16.n + src->w_list.a[k].clen)); + memcpy(b16.a + des->w_list.a[des->w_list.n].cidx, src->w_list.c.a + src->w_list.a[k].cidx, src->w_list.a[k].clen*(sizeof((*(src->w_list.c.a))))); + des->w_list.n++; b16.n += src->w_list.a[k].clen; p = NULL; + } + k = i; + } else { + des->w_list.a[des->w_list.n++] = src->w_list.a[k]; p = NULL; + k++; + } + } + + copy_asg_arr(des->w_list.c, b16); +} + + +void update_overlap_region(overlap_region *des, overlap_region *src, int64_t xl, int64_t yl) +{ + /** + kv_resize(uint16_t, des->w_list.c, src->w_list.c.n); + des->w_list.c.n = src->w_list.c.n; + memcpy(des->w_list.c.a, src->w_list.c.a, src->w_list.c.n*(sizeof((*(src->w_list.c.a))))); + + kv_resize(window_list, des->w_list, src->w_list.n); + des->w_list.n = src->w_list.n; + memcpy(des->w_list.a, src->w_list.a, src->w_list.n*(sizeof((*(src->w_list.a))))); + **/ + merge_hc_fast_cigar0(des, src); + + if(src->w_list.n) { + des->x_pos_s = src->w_list.a[0].x_start; des->x_pos_e = src->w_list.a[src->w_list.n-1].x_end; + des->y_pos_s = src->w_list.a[0].y_start; des->y_pos_e = src->w_list.a[src->w_list.n-1].y_end; + } + + int64_t xr, yr; + if(des->x_pos_s <= des->y_pos_s) { + des->y_pos_s -= des->x_pos_s; des->x_pos_s = 0; + } else { + des->x_pos_s -= des->y_pos_s; des->y_pos_s = 0; + } + + xr = xl-des->x_pos_e-1; yr = yl-des->y_pos_e-1; + if(xr <= yr) { + des->x_pos_e = xl-1; des->y_pos_e += xr; + } else { + des->y_pos_e = yl-1; des->x_pos_e += yr; + } +} + +void cigar_gen_by_chain_adv(overlap_region *z, Candidates_list *cl, int64_t ch_idx, int64_t ch_n, +ul_ov_t *ov, int64_t on, uint64_t wl, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, +UC_Read *tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, uint64_t rid, int64_t h_khit) +{ + if(on <= 0) return; + int64_t i, tl, id = z->y_id, m; + k_mer_hit *ch_a = cl->list + ch_idx; + if(hpc_g) tl = hpc_len(*hpc_g, id); + else if(uref) tl = uref->ug->u.a[id].len; + else tl = Get_READ_LENGTH((*rref), id); + // fprintf(stderr, "\n[M::%s::rid->%ld] utg%.6dl(%c), z::[%u, %u)\n", + // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e+1); + on = fusion_chain_ovlp(z, ch_a, ch_n, ov, on, wl, ql, tl); + aux_o->w_list.n = aux_o->w_list.c.n = 0; + aux_o->y_id = z->y_id; aux_o->y_pos_strand = z->y_pos_strand; + aux_o->x_pos_s = z->x_pos_s; aux_o->x_pos_e = z->x_pos_e; + aux_o->y_pos_s = z->y_pos_s; aux_o->y_pos_e = z->y_pos_e; + + + for (i = 0; i < on; i++) { + // if(aux_o->y_id == 109111) { + // fprintf(stderr, "[M::%s::i->%ld] ovq::[%u, %u), ovt::[%u, %u), hits::[%d, %d)\n", __func__, i, + // ov->qs, ov->qe, ov->ts, ov->te, + // (ov->qn!=((uint32_t)-1))?(int32_t)ov->qn:-1, (int32_t)ov->tn); + // } + assert((i<=0)||(ov[i].qs>ov[i-1].qe)); + ovlp_base_aln(z, ch_a, ch_n, &(ov[i]), wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, tl, rid); + } + + int64_t aux_n = aux_o->w_list.n; + ///for debug + // if(aux_o->y_id == 109111) { + // for (i = 0; i < ((int64_t)aux_o->w_list.n); i++) { + // fprintf(stderr, "-0-[aln::i->%ld::ql->%d] q::[%d, %d), t::[%d, %d), err::%d, clen::%u, extra_end::%d, mode::%d\n", i, + // aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start, + // aux_o->w_list.a[i].x_start, aux_o->w_list.a[i].x_end+1, + // aux_o->w_list.a[i].y_start, aux_o->w_list.a[i].y_end+1, + // aux_o->w_list.a[i].error, aux_o->w_list.a[i].clen, + // aux_o->w_list.a[i].extra_end, aux_o->w_list.a[i].error_threshold); + // } + // } + + for (i = 0; i < aux_n; i++) { + if(!(is_ualn_win(aux_o->w_list.a[i]))) continue; + //will overwrite ch_a; does not matter + rechain_aln(z, cl, aux_o, i, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, tl, h_khit, rid); + } + + ///for debug + // if(aux_o->y_id == 109111) { + // for (i = 0; i < ((int64_t)aux_o->w_list.n); i++) { + // fprintf(stderr, "-2-[aln::i->%ld::ql->%d] q::[%d, %d), t::[%d, %d), err::%d, clen::%u, mode::%d\n", i, + // aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start, + // aux_o->w_list.a[i].x_start, aux_o->w_list.a[i].x_end+1, + // aux_o->w_list.a[i].y_start, aux_o->w_list.a[i].y_end+1, + // aux_o->w_list.a[i].error, aux_o->w_list.a[i].clen, aux_o->w_list.a[i].error_threshold); + // } + // } + + if(((int64_t)aux_o->w_list.n) > aux_n) { + for (i = m = 0; i < ((int64_t)aux_o->w_list.n); i++) { + if((i < aux_n) && (is_ualn_win(aux_o->w_list.a[i]))) continue; + aux_o->w_list.a[m++] = aux_o->w_list.a[i]; + } + aux_o->w_list.n = m; + radix_sort_window_list_xs_srt(aux_o->w_list.a, aux_o->w_list.a+aux_o->w_list.n); + } + + ///update z by aux_o + update_overlap_region(z, aux_o, ql, tl); + + // debug_overlap_region(aux_o, qstr, tu, uref, hpc_g, rref); + + + // ch_a = cl->list + ch_idx; //update + // for (i = 0; i < wn; i++) z->w_list.a[i].clen = 0;///clean cigar + // if(on > 1) { + // fprintf(stderr, "[M::%s::] rid::%lu, on::%ld\n", __func__, rid, on); + // } + // if(z->y_id == 126) prt_k_mer_hit(ch_a, ch_n); + // for (i = ch_i = 0; i < on; i++) { + // assert((i<=0)||(ov[i].qs > ov[i-1].qe)); + // ov[i].sec = 16;///do not know the aln type + // ch_i = sub_base_aln(z, dp, ch_a, ch_n, pe, ov[i].qs, ov[i].qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, tl, ch_i, rid); + // pe = ov[i].qe; + // } +} + +void ovlp_base_direct(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, +ul_ov_t *ov, int64_t wl, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, +bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, int64_t tl, uint64_t rid) +{ + int64_t ibeg, iend, i, l, mode, q[2], t[2], is_done; + if(ov->qn == ((uint32_t)-1)) ibeg = -1; + else ibeg = ov->qn; + iend = ov->tn; + assert(iend>=ibeg+1); + // if(z->x_id == 57 && z->y_id == 2175) { + // fprintf(stderr, "\n***[M::%s::rid->%lu] utg%.6dl(%c), s::%u, e::%u, z::[%u, %u), ibeg::%ld, iend::%ld, ch_n::%ld\n", + // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], ov->qs, ov->qe, z->x_pos_s, z->x_pos_e+1, ibeg, iend, ch_n); + // } + for (l = ibeg, i = ibeg + 1; i <= iend; i++) { + q[0] = q[1] = t[0] = t[1] = mode = -1; is_done = 0; + if(l >= 0) { + q[0] = ch_a[l].self_offset; t[0] = ch_a[l].offset; + } else { + q[0] = ov->qs; + } + + if(i < ch_n) { + q[1] = ch_a[i].self_offset; t[1] = ch_a[i].offset; + } else { + q[1] = ov->qe; + } + + if((t[0] != -1) && (t[1] != -1)) { + mode = 0;//global + } else if((t[0] != -1) && (t[1] == -1)) { + mode = 1;///forward extension + } else if((t[0] == -1) && (t[1] != -1)) { + mode = 2;///backward extension + } else { + mode = 3;///no primary hit within [ibeg, iend] + } + + if(mode == 1 || mode == 2) adjust_ext_offset(&(q[0]), &(q[1]), &(t[0]), &(t[1]), ql, tl, 0, mode); + // if(z->x_id == 57 && z->y_id == 2175) { + // fprintf(stderr, "#[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", + // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode); + // } + is_done = hc_aln_exz_adv(z, uref, hpc_g, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, ql, e_rate, + MAX_SIN_L, MAX_SIN_E, FORCE_SIN_L, -1, aux_o); + + // if(z->x_id == 57 && z->y_id == 2175) { + // fprintf(stderr, "-is_done::%ld[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", + // is_done, __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode); + // } + + if(!is_done) {///postprocess + push_unmap_alnw(aux_o, q[0], q[1]-1, t[0], t[1]-1, mode); + } + l = i; + } +} + + +void hc_ovlp_base_direct(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, int64_t wl, All_reads *rref, char* qstr, UC_Read *tu, +bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, int64_t tl, uint64_t rid, int64_t pre_mode) +{ + int64_t i, l, mode, q[2], t[2], qr, tr, is_done, zn, si, ei; + + if((pre_mode < 0) && (z->non_homopolymer_errors == 0) && (z->w_list.n)) { + zn = z->w_list.n; + for (i = 1; i < zn; i++) { + if((z->w_list.a[i].error == 0 && z->w_list.a[i-1].error == 0) && (z->w_list.a[i].x_start == z->w_list.a[i-1].x_end + 1) && + (z->w_list.a[i].y_end == (z->w_list.a[i-1].y_end + (z->w_list.a[i].x_end-z->w_list.a[i-1].x_end)))) { + continue; + } + break; + } + if(i >= zn) { + q[0] = z->w_list.a[0].x_start; q[1] = z->w_list.a[z->w_list.n-1].x_end; + t[1] = z->w_list.a[z->w_list.n-1].y_end; t[0] = z->w_list.a[0].y_end - (z->w_list.a[0].x_end-z->w_list.a[0].x_start); + + if(q[0] <= t[0]) { + t[0] -= q[0]; q[0] = 0; + } else { + q[0] -= t[0]; t[0] = 0; + } + + qr = ql-q[1]-1; tr = tl-t[1]-1; + if(qr <= tr) { + q[1] = ql-1; t[1] += qr; + } else { + t[1] = tl-1; q[1] += tr; + } + + if(q[0] == z->w_list.a[0].x_start && q[1] == z->w_list.a[z->w_list.n-1].x_end) { + // fprintf(stderr, "[M::%s::%u->%u::%c] ovlp::%u, w_list.n::%u\n", __func__, z->x_id, z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_e+1-z->x_pos_s, (uint32_t)z->w_list.n); + set_exact_exz(exz, q[0], q[1] + 1, t[0], t[1] + 1); push_alnw(aux_o, exz); + return; + } + } + } + + si = 0; ei = ch_n; + if(pre_mode == 0) { + si = 1; ei = ch_n - 1; + } else if(pre_mode == 1) { + si = 1; + } else if(pre_mode == 2) { + ei = ch_n - 1; + } + + for (l = si - 1, i = si; i <= ei; i++) { + q[0] = q[1] = t[0] = t[1] = mode = -1; is_done = 0; + if(l >= 0) { + q[0] = ch_a[l].self_offset; t[0] = ch_a[l].offset; + } else { + q[0] = 0; + } + + if(i < ch_n) { + q[1] = ch_a[i].self_offset; t[1] = ch_a[i].offset; + } else { + q[1] = ql; + } + + if((t[0] != -1) && (t[1] != -1)) { + mode = 0;//global + } else if((t[0] != -1) && (t[1] == -1)) { + mode = 1;///forward extension + } else if((t[0] == -1) && (t[1] != -1)) { + mode = 2;///backward extension + } else { + mode = 3;///no primary hit within [ibeg, iend] + } + + + if(mode == 1 || mode == 2) adjust_ext_offset(&(q[0]), &(q[1]), &(t[0]), &(t[1]), ql, tl, 0, mode); + is_done = hc_aln_exz_adv_hc(z, NULL, NULL, rref, qstr, tu, q[0], q[1], t[0], t[1], mode, wl, exz, ql, e_rate, + MAX_SIN_L, MAX_SIN_E, FORCE_SIN_L, -1, aux_o); + + if(!is_done) {///postprocess + push_unmap_alnw(aux_o, q[0], q[1]-1, t[0], t[1]-1, mode); + } + l = i; + } +} + +void hc_ovlp_base_non_retrieve_direct(overlap_region *z, k_mer_hit *ch_a, int64_t ch_n, int64_t wl, char* qstr, char* tstr, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, int64_t tl, uint64_t rid) +{ + int64_t i, l, mode, q[2], t[2], qr, tr, is_done, zn; + + if(z->non_homopolymer_errors == 0 && z->w_list.n) { + zn = z->w_list.n; + for (i = 1; i < zn; i++) { + if((z->w_list.a[i].error == 0 && z->w_list.a[i-1].error == 0) && (z->w_list.a[i].x_start == z->w_list.a[i-1].x_end + 1) && + (z->w_list.a[i].y_end == (z->w_list.a[i-1].y_end + (z->w_list.a[i].x_end-z->w_list.a[i-1].x_end)))) { + continue; + } + break; + } + if(i >= zn) { + q[0] = z->w_list.a[0].x_start; q[1] = z->w_list.a[z->w_list.n-1].x_end; + t[1] = z->w_list.a[z->w_list.n-1].y_end; t[0] = z->w_list.a[0].y_end - (z->w_list.a[0].x_end-z->w_list.a[0].x_start); + + if(q[0] <= t[0]) { + t[0] -= q[0]; q[0] = 0; + } else { + q[0] -= t[0]; t[0] = 0; + } + + qr = ql-q[1]-1; tr = tl-t[1]-1; + if(qr <= tr) { + q[1] = ql-1; t[1] += qr; + } else { + t[1] = tl-1; q[1] += tr; + } + + if(q[0] == z->w_list.a[0].x_start && q[1] == z->w_list.a[z->w_list.n-1].x_end) { + // fprintf(stderr, "[M::%s::%u->%u::%c] ovlp::%u, w_list.n::%u\n", __func__, z->x_id, z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_e+1-z->x_pos_s, (uint32_t)z->w_list.n); + set_exact_exz(exz, q[0], q[1] + 1, t[0], t[1] + 1); push_alnw(aux_o, exz); + return; + } + } + } + + for (l = -1, i = 0; i <= ch_n; i++) { + q[0] = q[1] = t[0] = t[1] = mode = -1; is_done = 0; + if(l >= 0) { + q[0] = ch_a[l].self_offset; t[0] = ch_a[l].offset; + } else { + q[0] = 0; + } + + if(i < ch_n) { + q[1] = ch_a[i].self_offset; t[1] = ch_a[i].offset; + } else { + q[1] = ql; + } + + if((t[0] != -1) && (t[1] != -1)) { + mode = 0;//global + } else if((t[0] != -1) && (t[1] == -1)) { + mode = 1;///forward extension + } else if((t[0] == -1) && (t[1] != -1)) { + mode = 2;///backward extension + } else { + mode = 3;///no primary hit within [ibeg, iend] + } + + // if(z->x_id == 57 && z->y_id == 2175) { + if(mode == 1 || mode == 2) adjust_ext_offset(&(q[0]), &(q[1]), &(t[0]), &(t[1]), ql, tl, 0, mode); + // fprintf(stderr, "#[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", + // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode); + // } + is_done = hc_aln_exz_non_retrieve_adv_hc(z, qstr, tstr, q[0], q[1], t[0], t[1], mode, wl, exz, ql, tl, e_rate, MAX_SIN_L, MAX_SIN_E, FORCE_SIN_L, -1, aux_o); + + // if(z->x_id == 57 && z->y_id == 2175) { + // fprintf(stderr, "-is_done::%ld[M::%s::] utg%.6dl(%c), q::[%ld, %ld), t::[%ld, %ld), mode::%ld, ch_n::%ld\n", + // is_done, __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], q[0], q[1], t[0], t[1], mode, ch_n); + // } + + if(!is_done) {///postprocess + push_unmap_alnw(aux_o, q[0], q[1]-1, t[0], t[1]-1, mode); + } + l = i; + } +} + +void cigar_gen_by_chain_adv_local(overlap_region *z, Candidates_list *cl, ul_ov_t *ov, int64_t on, uint64_t wl, const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, +UC_Read *tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, uint64_t rid, int64_t h_khit) +{ + if(on <= 0) return; + int64_t ch_idx = z->shared_seed, ch_n; + int64_t i, tl, id = z->y_id, m; + k_mer_hit *ch_a = cl->list + ch_idx; + if(hpc_g) tl = hpc_len(*hpc_g, id); + else if(uref) tl = uref->ug->u.a[id].len; + else tl = Get_READ_LENGTH((*rref), id); + for (i = ch_idx; i < cl->length && cl->list[i].readID == cl->list[ch_idx].readID; i++){;} ch_n = i-ch_idx; + + // fprintf(stderr, "[M::%s::rid->%ld] utg%.6dl(%c), z::[%u, %u)\n", + // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e+1); + on = fusion_chain_ovlp(z, ch_a, ch_n, ov, on, wl, ql, tl); + aux_o->w_list.n = aux_o->w_list.c.n = 0; + aux_o->y_id = z->y_id; aux_o->y_pos_strand = z->y_pos_strand; + aux_o->x_pos_s = z->x_pos_s; aux_o->x_pos_e = z->x_pos_e; + aux_o->y_pos_s = z->y_pos_s; aux_o->y_pos_e = z->y_pos_e; + + + for (i = 0; i < on; i++) { + // fprintf(stderr, "[M::%s::+i->%ld] ovq::[%u, %u), ovt::[%u, %u), hits::[%d, %d)\n", __func__, i, + // ov->qs, ov->qe, ov->ts, ov->te, + // (ov->qn!=((uint32_t)-1))?(int32_t)ov->qn:-1, (int32_t)ov->tn); + assert((i<=0)||(ov[i].qs>ov[i-1].qe)); + ovlp_base_direct(z, ch_a, ch_n, &(ov[i]), wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, tl, rid); + } + + int64_t aux_n = aux_o->w_list.n; + for (i = 0; i < aux_n; i++) { + if(!(is_ualn_win(aux_o->w_list.a[i]))) continue; + // if((aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start) <= FORCE_CNS_L) { + // fprintf(stderr, "[aln::-i->%ld::ql->%d] q::[%d, %d), t::[%d, %d), err::%d, clen::%u, mode::%d\n", i, + // aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start, + // aux_o->w_list.a[i].x_start, aux_o->w_list.a[i].x_end+1, + // aux_o->w_list.a[i].y_start, aux_o->w_list.a[i].y_end+1, + // aux_o->w_list.a[i].error, aux_o->w_list.a[i].clen, aux_o->w_list.a[i].error_threshold); + // } + //will overwrite ch_a; does not matter + rechain_aln(z, cl, aux_o, i, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, tl, h_khit, rid); + } + if(((int64_t)aux_o->w_list.n) > aux_n) { + for (i = m = 0; i < ((int64_t)aux_o->w_list.n); i++) { + if((i < aux_n) && (is_ualn_win(aux_o->w_list.a[i]))) continue; + aux_o->w_list.a[m++] = aux_o->w_list.a[i]; + } + aux_o->w_list.n = m; + radix_sort_window_list_xs_srt(aux_o->w_list.a, aux_o->w_list.a+aux_o->w_list.n); + } + + ///update z by aux_o + update_overlap_region(z, aux_o, ql, tl); + + // debug_overlap_region(aux_o, qstr, tu, uref, hpc_g, rref); + + + // ch_a = cl->list + ch_idx; //update + // for (i = 0; i < wn; i++) z->w_list.a[i].clen = 0;///clean cigar + // if(on > 1) { + // fprintf(stderr, "[M::%s::] rid::%lu, on::%ld\n", __func__, rid, on); + // } + // if(z->y_id == 126) prt_k_mer_hit(ch_a, ch_n); + // for (i = ch_i = 0; i < on; i++) { + // assert((i<=0)||(ov[i].qs > ov[i-1].qe)); + // ov[i].sec = 16;///do not know the aln type + // ch_i = sub_base_aln(z, dp, ch_a, ch_n, pe, ov[i].qs, ov[i].qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, tl, ch_i, rid); + // pe = ov[i].qe; + // } +} + +void rechain_aln_hc(overlap_region *z, Candidates_list *cl, overlap_region *aux_o, int64_t aux_i, int64_t wl, +All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, double e_rate, int64_t ql, int64_t tl, int64_t h_khit, int64_t rid) +{ + int64_t rcn = cl->length, ch_n, qs, qe, ts, te, mode, an0, an, todo; + k_mer_hit *ch_a; uint8_t q[2], t[2]; ///ul_ov_t idx; + ///[qs, qe) && [ts, te) + qs = aux_o->w_list.a[aux_i].x_start; qe = aux_o->w_list.a[aux_i].x_end+1; + ts = aux_o->w_list.a[aux_i].y_start; te = aux_o->w_list.a[aux_i].y_end+1; + if(qe - qs < FORCE_SIN_L || te - ts < FORCE_SIN_L) return; + mode = aux_o->w_list.a[aux_i].error_threshold; + ch_n = gen_win_chain(z, cl, qs, qe, ts, te, wl, NULL, NULL, rref, qstr, tu, exz, ql, tl, e_rate, h_khit, mode, rid, 1); + ch_a = cl->list + rcn; + if(ch_n) { + todo = 1; ///idx.ts = idx.te = (uint32_t)-1; idx.qs = 0; idx.qe = ql; + if(mode == 0) {//global + // idx.qn = 0; idx.tn = ch_n - 1; + // idx.qs = ch_a[idx.qn].self_offset; + // idx.ts = ch_a[idx.qn].offset; + // idx.qe = ch_a[idx.tn].self_offset; + // idx.te = ch_a[idx.tn].offset; + assert(ch_a[0].self_offset == qs && ch_a[0].offset == ts); + assert(ch_a[ch_n-1].self_offset == qe && ch_a[ch_n-1].offset == te); + if(ch_n <= 2) todo = 0; + } else if(mode == 1) {//forward ext + // idx.qn = 0; idx.tn = ch_n; + // idx.qs = ch_a[idx.qn].self_offset; + // idx.ts = ch_a[idx.qn].offset; + // idx.qe = ql; + assert(ch_a[0].self_offset == qs && ch_a[0].offset == ts); + if(ch_n <= 1) todo = 0; + } else if(mode == 2) {///backward ext + // idx.qn = (uint32_t)-1; idx.tn = ch_n-1; + // idx.qs = 0; + // idx.qe = ch_a[idx.tn].self_offset; + // idx.te = ch_a[idx.tn].offset; + assert(ch_a[ch_n-1].self_offset == qe && ch_a[ch_n-1].offset == te); + if(ch_n <= 1) todo = 0; + } + if(todo) { + an0 = aux_o->w_list.n; + // if(z->x_id == 29033 && z->y_id == 21307) { + // fprintf(stderr, "[M::%s]\tan0::%ld\tq::[%u,\t%u)\tt::[%u,\t%u)\tlw::%u\trw::%u\n", __func__, an0, + // idx.qs, idx.qe, idx.ts, idx.te, idx.qn, idx.tn); + // } + // ovlp_base_aln(z, ch_a, ch_n, &idx, wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, tl, (uint64_t)-1); + hc_ovlp_base_direct(z, ch_a, ch_n, wl, rref, qstr, tu, exz, aux_o, e_rate, ql, tl, (uint64_t)-1, mode); + an = aux_o->w_list.n; q[0] = q[1] = t[0] = t[1] = 0; todo = 0; + // if(z->x_id == 29033 && z->y_id == 21307) { + // fprintf(stderr, "[M::%s]\tan::%ld\n", __func__, an); + // } + // fprintf(stderr, "[M::%s::] awn0::%ld, awn::%lu\n", __func__, an0, an); + ///old unaligned window could be replaced by the new aligned window + if((an == (an0 + 1)) && (!(is_ualn_win(aux_o->w_list.a[an-1])))) { + if(aux_o->w_list.a[aux_i].x_start == aux_o->w_list.a[an-1].x_start) q[0] = 1; + if(aux_o->w_list.a[aux_i].x_end == aux_o->w_list.a[an-1].x_end) q[1] = 1; + if(aux_o->w_list.a[aux_i].y_start == aux_o->w_list.a[an-1].y_start) t[0] = 1; + if(aux_o->w_list.a[aux_i].y_end == aux_o->w_list.a[an-1].y_end) t[1] = 1; + if((mode == 0) && q[0] && q[1] && t[0] && t[1]) todo = 1; + if((mode == 1) && q[0] && t[0]) todo = 1; + if((mode == 2) && q[1] && t[1]) todo = 1; + if(todo) { + aux_o->w_list.a[aux_i] = aux_o->w_list.a[an-1]; aux_o->w_list.n--; + } + } + // if(an > an0) {///should always > 0 as there are unmapped windows + // } + // aux_o->w_list.n = an0; + } + } + cl->length = rcn;///must reset!!!! +} + +void rechain_aln_non_retrieve_hc(overlap_region *z, Candidates_list *cl, overlap_region *aux_o, int64_t aux_i, int64_t wl, +char* qstr, char* tstr, bit_extz_t *exz, double e_rate, int64_t ql, int64_t tl, int64_t h_khit, int64_t rid) +{ + int64_t rcn = cl->length, ch_n, qs, qe, ts, te, mode, an0, an, todo; + k_mer_hit *ch_a; uint8_t q[2], t[2]; ///ul_ov_t idx; + ///[qs, qe) && [ts, te) + qs = aux_o->w_list.a[aux_i].x_start; qe = aux_o->w_list.a[aux_i].x_end+1; + ts = aux_o->w_list.a[aux_i].y_start; te = aux_o->w_list.a[aux_i].y_end+1; + if(qe - qs < FORCE_SIN_L || te - ts < FORCE_SIN_L) return; + mode = aux_o->w_list.a[aux_i].error_threshold; + ch_n = gen_win_non_retrieve_chain(z, cl, qs, qe, ts, te, wl, qstr, tstr, exz, ql, tl, e_rate, h_khit, mode, rid, 1); + ch_a = cl->list + rcn; + if(ch_n) { + todo = 1; ///idx.ts = idx.te = (uint32_t)-1; idx.qs = 0; idx.qe = ql; + if(mode == 0) {//global + // idx.qn = 0; idx.tn = ch_n - 1; + // idx.qs = ch_a[idx.qn].self_offset; + // idx.ts = ch_a[idx.qn].offset; + // idx.qe = ch_a[idx.tn].self_offset; + // idx.te = ch_a[idx.tn].offset; + assert(ch_a[0].self_offset == qs && ch_a[0].offset == ts); + assert(ch_a[ch_n-1].self_offset == qe && ch_a[ch_n-1].offset == te); + if(ch_n <= 2) todo = 0; + } else if(mode == 1) {//forward ext + // idx.qn = 0; idx.tn = ch_n; + // idx.qs = ch_a[idx.qn].self_offset; + // idx.ts = ch_a[idx.qn].offset; + // idx.qe = ql; + assert(ch_a[0].self_offset == qs && ch_a[0].offset == ts); + if(ch_n <= 1) todo = 0; + } else if(mode == 2) {///backward ext + // idx.qn = (uint32_t)-1; idx.tn = ch_n-1; + // idx.qs = 0; + // idx.qe = ch_a[idx.tn].self_offset; + // idx.te = ch_a[idx.tn].offset; + assert(ch_a[ch_n-1].self_offset == qe && ch_a[ch_n-1].offset == te); + if(ch_n <= 1) todo = 0; + } + if(todo) { + an0 = aux_o->w_list.n; + // if(z->x_id == 29033 && z->y_id == 21307) { + // fprintf(stderr, "[M::%s]\tan0::%ld\tq::[%u,\t%u)\tt::[%u,\t%u)\tlw::%u\trw::%u\n", __func__, an0, + // idx.qs, idx.qe, idx.ts, idx.te, idx.qn, idx.tn); + // } + // ovlp_base_aln(z, ch_a, ch_n, &idx, wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, tl, (uint64_t)-1); + hc_ovlp_base_non_retrieve_direct(z, ch_a, ch_n, wl, qstr, tstr, exz, aux_o, e_rate, ql, tl, (uint64_t)-1); + an = aux_o->w_list.n; q[0] = q[1] = t[0] = t[1] = 0; todo = 0; + // if(z->x_id == 29033 && z->y_id == 21307) { + // fprintf(stderr, "[M::%s]\tan::%ld\n", __func__, an); + // } + // fprintf(stderr, "[M::%s::] awn0::%ld, awn::%lu\n", __func__, an0, an); + ///old unaligned window could be replaced by the new aligned window + if((an == (an0 + 1)) && (!(is_ualn_win(aux_o->w_list.a[an-1])))) { + if(aux_o->w_list.a[aux_i].x_start == aux_o->w_list.a[an-1].x_start) q[0] = 1; + if(aux_o->w_list.a[aux_i].x_end == aux_o->w_list.a[an-1].x_end) q[1] = 1; + if(aux_o->w_list.a[aux_i].y_start == aux_o->w_list.a[an-1].y_start) t[0] = 1; + if(aux_o->w_list.a[aux_i].y_end == aux_o->w_list.a[an-1].y_end) t[1] = 1; + if((mode == 0) && q[0] && q[1] && t[0] && t[1]) todo = 1; + if((mode == 1) && q[0] && t[0]) todo = 1; + if((mode == 2) && q[1] && t[1]) todo = 1; + if(todo) { + aux_o->w_list.a[aux_i] = aux_o->w_list.a[an-1]; aux_o->w_list.n--; + } + } + // if(an > an0) {///should always > 0 as there are unmapped windows + // } + // aux_o->w_list.n = an0; + } + } + cl->length = rcn;///must reset!!!! +} + +/** +void push_trace_iter(asg16_v *exz, uint16_t c, uint32_t l) +{ + if(l <= 0) return; + uint16_t c0 = (uint16_t)-1; uint32_t l0 = 0; + ///last item of old cigar + if(exz->n > 0) { + c0 = (exz->a[exz->n-1]>>14); + l0 = (exz->a[exz->n-1]&(0x3fff)); + } + ///first item of new cigar + if(c0 == c) {l += l0; exz->n--;} + + push_trace(exz, c, l); +} +**/ + +uint64_t gen_hc_fast_cigar0(overlap_region *z, Candidates_list *cl, uint64_t wl, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, uint64_t rid, int64_t h_khit, int64_t *re) +{ + int64_t ch_idx = z->shared_seed, ch_n; + int64_t i, tl, id = z->y_id, m, tot_e, aln, xe, ye; + k_mer_hit *ch_a = cl->list + ch_idx; *re = INT64_MAX; + tl = Get_READ_LENGTH((*rref), id); + for (i = ch_idx; i < cl->length && cl->list[i].readID == cl->list[ch_idx].readID; i++){;} ch_n = i-ch_idx; + if(ch_n <= 0) return 0; + + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + + // fprintf(stderr, "[M::%s::rid->%ld] utg%.6dl(%c), z::[%u, %u)\n", + // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e+1); + aux_o->w_list.n = aux_o->w_list.c.n = 0; + aux_o->y_id = z->y_id; aux_o->y_pos_strand = z->y_pos_strand; + aux_o->x_pos_s = z->x_pos_s; aux_o->x_pos_e = z->x_pos_e; + aux_o->y_pos_s = z->y_pos_s; aux_o->y_pos_e = z->y_pos_e; + + hc_ovlp_base_direct(z, ch_a, ch_n, wl, rref, qstr, tu, exz, aux_o, e_rate, ql, tl, rid, -1); + + int64_t aux_n = aux_o->w_list.n; + if(z->w_list.n == 0) aux_n = 0; + for (i = 0; i < aux_n; i++) { + // if(z->y_id == 310315) { + // fprintf(stderr, "[aln::-i->%ld::ql->%d] q::[%d, %d), t::[%d, %d), err::%d, clen::%u, mode::%d\n", i, + // aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start, + // aux_o->w_list.a[i].x_start, aux_o->w_list.a[i].x_end+1, + // aux_o->w_list.a[i].y_start, aux_o->w_list.a[i].y_end+1, + // aux_o->w_list.a[i].error, aux_o->w_list.a[i].clen, aux_o->w_list.a[i].error_threshold); + // } + if(!(is_ualn_win(aux_o->w_list.a[i]))) continue; + // if((aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start) <= FORCE_CNS_L) { + // fprintf(stderr, "[aln::-i->%ld::ql->%d] q::[%d, %d), t::[%d, %d), err::%d, clen::%u, mode::%d\n", i, + // aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start, + // aux_o->w_list.a[i].x_start, aux_o->w_list.a[i].x_end+1, + // aux_o->w_list.a[i].y_start, aux_o->w_list.a[i].y_end+1, + // aux_o->w_list.a[i].error, aux_o->w_list.a[i].clen, aux_o->w_list.a[i].error_threshold); + // } + //will overwrite ch_a; does not matter + rechain_aln_hc(z, cl, aux_o, i, wl, rref, qstr, tu, exz, e_rate, ql, tl, h_khit, rid); + } + + if(((int64_t)aux_o->w_list.n) > aux_n) { + for (i = m = 0; i < ((int64_t)aux_o->w_list.n); i++) { + if((i < aux_n) && (is_ualn_win(aux_o->w_list.a[i]))) continue; + aux_o->w_list.a[m++] = aux_o->w_list.a[i]; + } + aux_o->w_list.n = m; + radix_sort_window_list_xs_srt(aux_o->w_list.a, aux_o->w_list.a+aux_o->w_list.n); + } + + ///update z by aux_o + update_overlap_region(z, aux_o, ql, tl); + + aux_n = z->w_list.n; + for (i = tot_e = aln = 0; i < aux_n; i++) { + if(is_ualn_win(z->w_list.a[i])) { + xe = z->w_list.a[i].x_end + 1 - z->w_list.a[i].x_start; + ye = z->w_list.a[i].y_end + 1 - z->w_list.a[i].y_start; + tot_e += ((xe >= ye)?(xe):(ye)); + } else { + tot_e += z->w_list.a[i].error; aln += z->w_list.a[i].x_end + 1 - z->w_list.a[i].x_start; + } + } + *re = tot_e; + // fprintf(stderr, "[M::%s::%u->%u::%c] ovlp::%u, aln::%ld, tot_e::%ld, w_list.n::%u, ch_n::%ld\n", + // __func__, z->x_id, z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_e+1-z->x_pos_s, aln, tot_e, (uint32_t)z->w_list.n, ch_n); + + // debug_overlap_region(aux_o, qstr, tu, NULL, NULL, rref); + + + // ch_a = cl->list + ch_idx; //update + // for (i = 0; i < wn; i++) z->w_list.a[i].clen = 0;///clean cigar + // if(on > 1) { + // fprintf(stderr, "[M::%s::] rid::%lu, on::%ld\n", __func__, rid, on); + // } + // if(z->y_id == 126) prt_k_mer_hit(ch_a, ch_n); + // for (i = ch_i = 0; i < on; i++) { + // assert((i<=0)||(ov[i].qs > ov[i-1].qe)); + // ov[i].sec = 16;///do not know the aln type + // ch_i = sub_base_aln(z, dp, ch_a, ch_n, pe, ov[i].qs, ov[i].qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, tl, ch_i, rid); + // pe = ov[i].qe; + // } + + return 1; +} + + +uint64_t gen_hc_fast_non_retrieve_cigar0(overlap_region *z, Candidates_list *cl, uint64_t wl, char* qstr, int64_t ql, char* tstr, int64_t tl, bit_extz_t *exz, overlap_region *aux_o, double e_rate, uint64_t rid, int64_t h_khit) +{ + int64_t ch_idx = z->shared_seed, ch_n; + int64_t i, m, tot_e, aln; + k_mer_hit *ch_a = cl->list + ch_idx; + for (i = ch_idx; i < cl->length && cl->list[i].readID == cl->list[ch_idx].readID; i++){;} ch_n = i-ch_idx; + if(ch_n <= 0) return 0; + + + // fprintf(stderr, "[M::%s::rid->%ld] utg%.6dl(%c), z::[%u, %u)\n", + // __func__, rid, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e+1); + aux_o->w_list.n = aux_o->w_list.c.n = 0; + aux_o->y_id = z->y_id; aux_o->y_pos_strand = z->y_pos_strand; + aux_o->x_pos_s = z->x_pos_s; aux_o->x_pos_e = z->x_pos_e; + aux_o->y_pos_s = z->y_pos_s; aux_o->y_pos_e = z->y_pos_e; + + hc_ovlp_base_non_retrieve_direct(z, ch_a, ch_n, wl, qstr, tstr, exz, aux_o, e_rate, ql, tl, rid); + + + int64_t aux_n = aux_o->w_list.n; + if(z->w_list.n == 0) aux_n = 0; + for (i = 0; i < aux_n; i++) { + if(!(is_ualn_win(aux_o->w_list.a[i]))) continue; + // if((aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start) <= FORCE_CNS_L) { + // fprintf(stderr, "[aln::-i->%ld::ql->%d] q::[%d, %d), t::[%d, %d), err::%d, clen::%u, mode::%d\n", i, + // aux_o->w_list.a[i].x_end+1-aux_o->w_list.a[i].x_start, + // aux_o->w_list.a[i].x_start, aux_o->w_list.a[i].x_end+1, + // aux_o->w_list.a[i].y_start, aux_o->w_list.a[i].y_end+1, + // aux_o->w_list.a[i].error, aux_o->w_list.a[i].clen, aux_o->w_list.a[i].error_threshold); + // } + //will overwrite ch_a; does not matter + rechain_aln_non_retrieve_hc(z, cl, aux_o, i, wl, qstr, tstr, exz, e_rate, ql, tl, h_khit, rid); + } + + if(((int64_t)aux_o->w_list.n) > aux_n) { + for (i = m = 0; i < ((int64_t)aux_o->w_list.n); i++) { + if((i < aux_n) && (is_ualn_win(aux_o->w_list.a[i]))) continue; + aux_o->w_list.a[m++] = aux_o->w_list.a[i]; + } + aux_o->w_list.n = m; + radix_sort_window_list_xs_srt(aux_o->w_list.a, aux_o->w_list.a+aux_o->w_list.n); + } + + ///update z by aux_o + update_overlap_region(z, aux_o, ql, tl); + + aux_n = z->w_list.n; + for (i = tot_e = aln = 0; i < aux_n; i++) { + if(is_ualn_win(z->w_list.a[i])) { + tot_e += z->w_list.a[i].x_end + 1 - z->w_list.a[i].x_start; + } else { + tot_e += z->w_list.a[i].error; aln += z->w_list.a[i].x_end + 1 - z->w_list.a[i].x_start; + } + } + // fprintf(stderr, "[M::%s::%u->%u::%c] ovlp::%u, aln::%ld, tot_e::%ld, w_list.n::%u, ch_n::%ld\n", + // __func__, z->x_id, z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_e+1-z->x_pos_s, aln, tot_e, (uint32_t)z->w_list.n, ch_n); + + // debug_overlap_region(aux_o, qstr, tu, NULL, NULL, rref); + + + // ch_a = cl->list + ch_idx; //update + // for (i = 0; i < wn; i++) z->w_list.a[i].clen = 0;///clean cigar + // if(on > 1) { + // fprintf(stderr, "[M::%s::] rid::%lu, on::%ld\n", __func__, rid, on); + // } + // if(z->y_id == 126) prt_k_mer_hit(ch_a, ch_n); + // for (i = ch_i = 0; i < on; i++) { + // assert((i<=0)||(ov[i].qs > ov[i-1].qe)); + // ov[i].sec = 16;///do not know the aln type + // ch_i = sub_base_aln(z, dp, ch_a, ch_n, pe, ov[i].qs, ov[i].qe, wl, uref, hpc_g, rref, qstr, tu, exz, e_rate, ql, tl, ch_i, rid); + // pe = ov[i].qe; + // } + + + return 1; +} + + +#define gen_err_unaligned(xl, yl) (((xl)<=FORCE_SIN_L)?(MAX((xl), (yl))):MAX((MIN((xl), (yl))), ((xl*0.51)+1))) + +int64_t retrieve_cigar_err_debug(bit_extz_t *ez, int64_t s, int64_t e) +{ + if(!ez->cigar.n) return 0; + int64_t err = 0, xk = ez->ts; int64_t ws, we, os, oe, ovlp; + uint32_t ck = 0, cl; uint16_t op; + + os = MAX(s, ez->ts); oe = MIN(e, ez->te+1); + ovlp = ((oe>os)? (oe-os):0); + if(!ovlp) { + fprintf(stderr, "[M::%s::] s::%ld, e::%ld, ez->ts::%u, ez->te::%u\n", + __func__, s, e, ez->ts, ez->te); + } + assert(ovlp); + + //some cigar will span s or e + while (ck < ez->cigar.n && xk < e) {//[s, e) + ws = xk; + ck = pop_trace(&(ez->cigar), ck, &op, &cl); + if(op!=2) xk += cl; + we = xk; + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + if((op==2) && (ws>=s) && (wsw_list.n, ws, we, os, oe, ovlp; + window_list *m; int64_t xl, yl, werr, err; bit_extz_t ez; + for (wk = err = 0; wk < wn; wk++) { + m = &(z->w_list.a[wk]); + ws = m->x_start; we = m->x_end+1; + if(ws >= e) break; + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + if(ovlp) { + xl = m->x_end+1-m->x_start; + yl = m->y_end+1-m->y_start; + if((is_ualn_win((*m))) || (is_est_aln((*m)))) { + if(is_ualn_win((*m))) { //unmapped + werr = gen_err_unaligned(xl, yl); + } else { + werr = m->error;//shared window + } + if(ovlp < xl) { + werr = (((double)ovlp)/((double)xl))*((double)werr); + } + //skip the whole window + err += werr; + } else { + if(ovlp == xl) { + //skip the whole window + err += m->error; + } else { + set_bit_extz_t(ez, (*z), wk); + err += retrieve_cigar_err_debug(&ez, os, oe); + } + } + } + } + return err; +} + +int64_t retrieve_cigar_err(bit_extz_t *ez, int64_t s, int64_t e, int64_t *xk, int64_t *ck) +{ + if(!ez->cigar.n) return 0; + int64_t cn = ez->cigar.n, op, err = 0; int64_t ws, we, os, oe, ovlp; + if(((*ck) < 0) || ((*ck) > cn)) {//(*ck) == cn is allowed + (*ck) = 0; (*xk) = ez->ts; + } + + while ((*ck) > 0 && (*xk) > s) { + --(*ck); + op = ez->cigar.a[(*ck)]>>14; + if(op!=2) (*xk) -= (ez->cigar.a[(*ck)]&(0x3fff)); + } + + //some cigar will span s or e + while ((*ck) < cn && (*xk) < e) {//[s, e) + ws = (*xk); + op = ez->cigar.a[(*ck)]>>14; + if(op!=2) (*xk) += (ez->cigar.a[(*ck)]&(0x3fff)); + we = (*xk); + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + if((op==2) && (ws>=s) && (wscigar.a[(*ck)]&(0x3fff)); + } + + // if(s == 22694 && e == 38018) { + // fprintf(stderr, "[M::%s]\tw::[%ld,\t%ld)\tc::%ld\top::%ld\terr::%ld\n", __func__, ws, we, (*ck), op, err + (op?ovlp:0)); + // } + (*ck)++; + if((!ovlp) || (!op)) continue; + err += ovlp; + } + + // int64_t debug_err = retrieve_cigar_err_debug(ez, s, e); + // if(!(err == debug_err)) { + // fprintf(stderr, "[M::%s::] err::%ld, debug_err::%ld, s::%ld, e::%ld, ez->ts::%u, ez->te::%u\n", + // __func__, err, debug_err, s, e, ez->ts, ez->te); + // } + // assert(err == debug_err); + return err; +} +///[s, e) +int64_t extract_sub_cigar_err(overlap_region *z, int64_t s, int64_t e, ul_ov_t *p) +{ + int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), ck = ovlp_cur_coff(*p); + int64_t min_w = ovlp_min_wid(*p), max_w = ovlp_max_wid(*p);//[min_w, max_w] + bit_extz_t ez; window_list *m; + int64_t ws, we, os, oe, ovlp, err = 0, xl, yl, werr, tot = e - s; + if(wk < min_w || wk > max_w) wk = min_w; + for (; wk >= min_w && z->w_list.a[wk].x_start > s; wk--); + if(wk < min_w || wk > max_w) return -1; + for (; wk <= max_w && z->w_list.a[wk].x_end < s; wk++); + if(wk < min_w || wk > max_w) return -1; + //s >= w_list.a[wk].x_start && s <= w_list.a[wk].x_end + if(wk != ovlp_cur_wid(*p)) {//xk is global, while ck is local + xk = z->w_list.a[wk].x_start; ck = 0; + } + // fprintf(stderr, "[M::%s] wk::%ld, ck::%ld, xk::%ld\n", __func__, wk, ck, xk); + // fprintf(stderr, "+[M::%s] wk::%ld, ck::%ld, xk::%ld, w::[%d, %d), bound::[%ld, %ld)\n", + // __func__, wk, ck, xk, z->w_list.a[wk].x_start, z->w_list.a[wk].x_end+1, s, e); + + while(wk <= max_w && z->w_list.a[wk].x_start < e) {///[s, e) + m = &(z->w_list.a[wk]); + ws = m->x_start; we = m->x_end+1; + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + // fprintf(stderr, "-[M::%s] ovlp::%ld, wk::%ld, ck::%ld, xk::%ld, w::[%ld, %ld), bound::[%ld, %ld)\n", + // __func__, ovlp, wk, ck, xk, ws, we, s, e); + if(ovlp) { + xl = m->x_end+1-m->x_start; + yl = m->y_end+1-m->y_start; + if((is_ualn_win((*m))) || (is_est_aln((*m)))) { + if(is_ualn_win((*m))) { //unmapped + werr = gen_err_unaligned(xl, yl); + } else { + werr = m->error;//shared window + } + if(ovlp < xl) { + werr = (((double)ovlp)/((double)xl))*((double)werr); + } + //skip the whole window + err += werr; xk = m->x_end+1; ck = m->clen; + } else { + if(ovlp == xl) { + //skip the whole window + err += m->error; xk = m->x_end+1; ck = m->clen; + } else { + // if(os == 22694 && oe == 38018) { + // fprintf(stderr, "\n-[M::%s]\tos::%ld\toe::%ld\n", __func__, os, oe); + // } + set_bit_extz_t(ez, (*z), wk); + err += retrieve_cigar_err(&ez, os, oe, &xk, &ck); + } + } + } + tot -= ovlp; + if(xk >= e) break;//[min_w, max_w] && [s, e) + wk++; if(wk > max_w) break; + xk = z->w_list.a[wk].x_start; ck = 0;//reset + } + assert(!tot); + ovlp_cur_wid(*p) = wk; ovlp_cur_xoff(*p) = xk; ovlp_cur_coff(*p) = ck; + return err; +} + +#define bst_ov(x) ((x).misBase) +#define ov_dif(x) ((x).cov) +#define ov_id(x) ((x).overlapID) +#define ov_xoff(x) ((x).site) +#define var_id(x) ((x).overlapSite) + +#define var_s(x) ((x).site) +#define var_l(x) ((x).overlap_num) +#define var_occ(x) ((x).occ_0) +#define var_min_dif(x) ((x).score) +#define var_min_ovid(x) ((x).id) +#define var_h_idx(x) ((x).occ_1) + + +uint64_t query_gen_gov_idx(asg64_v *ovidx, uint64_t v, uint64_t w) +{ + uint64_t m, s, e; + if(v > w) { + m = v; v = w; w = m; + } + s = ovidx->a[v]>>32; e = s + (uint32_t)ovidx->a[v]; + for (m = s; m < e; m++) { + if(ovidx->a[m] == w) return 1; + } + return 0; +} + +void push_sec_aln(overlap_region *z, int64_t s, int64_t e, int64_t sec_err) +{ + window_list *p; + if(z->align_length > 0) { + p = z->w_list.a + z->w_list.n + z->align_length - 1; + if((p->x_end == s) && ((!!(p->clen)) == (!!sec_err))) { + p->x_end = e; p->clen += sec_err; + return; + } + } + if((z->w_list.n+z->align_length)==z->w_list.m) { + z->w_list.m = z->w_list.m? z->w_list.m<<1 : 2; + z->w_list.a = (window_list*)realloc(z->w_list.a, sizeof(window_list)*z->w_list.m); + } + p = &(z->w_list.a[z->w_list.n+z->align_length]); z->align_length++; memset(p, 0, sizeof((*p))); + p->x_start = s; p->x_end = e; p->clen += sec_err; +} + +void push_sec_aln_robust(overlap_region *z, int64_t s, int64_t e, int64_t sec_err) +{ + window_list *p; + if(z->align_length > 0) { + p = z->w_list.a + z->w_list.n + z->align_length - 1; + if((p->x_end == s) && (p->clen == 0) && ((!!(p->clen)) == (!!sec_err))) { + p->x_end = e; p->clen += sec_err; + return; + } + } + if((z->w_list.n+z->align_length)==z->w_list.m) { + z->w_list.m = z->w_list.m? z->w_list.m<<1 : 2; + z->w_list.a = (window_list*)realloc(z->w_list.a, sizeof(window_list)*z->w_list.m); + } + p = &(z->w_list.a[z->w_list.n+z->align_length]); z->align_length++; memset(p, 0, sizeof((*p))); + p->x_start = s; p->x_end = e; p->clen += sec_err; +} + +// #define id_mm ((uint64_t)0x7fffffffffffffff) +#define id_set ((uint64_t)0x8000000000000000) +#define id_get(a) ((uint32_t)(a)) +#define err_get(a) (((a)&((uint64_t)0x7fffffffffffffff))>>32) + +void reassign_sec_err(overlap_region* ol, asg64_v *ovidx, asg64_v *buf, uint64_t bid0) +{ + uint64_t bn = buf->n, bid = bid0, oid, mid, m, s, e; + if(buf->a[bid]&id_set) return; + kv_push(uint64_t, *buf, bid); + while (buf->n > bn) { + bid = buf->a[--buf->n]; + if(buf->a[bid]&id_set) continue; + buf->a[bid]|=id_set; + + oid = id_get(buf->a[bid]); + s = ovidx->a[oid]>>32; e = (uint32_t)ovidx->a[oid]; + for (m = s; m < e; m++) { + mid = ol[(uint32_t)ovidx->a[m]].overlapLen; + if(mid == (uint32_t)-1) continue; + if(buf->a[mid]&id_set) continue; + kv_push(uint64_t, *buf, mid); + } + } +} +///[s, e) +uint64_t gen_region_phase(overlap_region* ol, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, uint64_t dp, ul_ov_t *c_idx, asg64_v *buf, asg64_v *ovidx) +{ + if(!id_n) return id_n; + uint64_t k, m, mn, q[2], buf_n, rm_n, oid; int64_t err, msc, msc_k, msc_n; + overlap_region *z; ul_ov_t *p; buf->n = 0; kv_resize(uint64_t, *buf, dp); + for (k = buf_n = rm_n = 0; k < id_n; k++) { + p = &(c_idx[id_a[k]]); + q[0] = ol[ovlp_id(*p)].w_list.a[ovlp_min_wid(*p)].x_start; + q[1] = ol[ovlp_id(*p)].w_list.a[ovlp_max_wid(*p)].x_end+1; + if(q[0]<=s && q[1]>=e) { + kv_push(uint64_t, *buf, id_a[k]); + // buf[buf_n++] = id_a[k]; + } + if(q[1] < e) rm_n++; + } + buf_n = buf->n; + assert(buf_n == dp);//not right + + if(buf_n > 0) { + for (k = 0, msc = INT32_MAX, msc_k = -1, msc_n = 0; k < buf_n; k++) { + p = &(c_idx[(uint32_t)buf->a[k]]); z = &(ol[ovlp_id(*p)]); + // fprintf(stderr, "+++[M::%s::utg%.6dl] wid::%u, xoff::%u, coff::%u\n", __func__, + // (int32_t)ol[ovlp_id(*p)].y_id+1, ovlp_cur_wid(*p), ovlp_cur_xoff(*p), ovlp_cur_coff(*p)); + err = extract_sub_cigar_err(z, s, e, p); + // int64_t debug_err = extract_sub_cigar_err_debug(z, s, e); + // assert(err == debug_err); + // fprintf(stderr, "[M::%s::] err::%ld, debug_err::%ld\n", __func__, err, debug_err); + + // fprintf(stderr, "---[M::%s::utg%.6dl] wid::%u, xoff::%u, coff::%u, err::%ld\n", __func__, + // (int32_t)ol[ovlp_id(*p)].y_id+1, ovlp_cur_wid(*p), ovlp_cur_xoff(*p), ovlp_cur_coff(*p), err); + fprintf(stderr, "---[M::%s::utg%.6dl] xoff::[%lu, %lu), err::%ld\n", __func__, + (int32_t)ol[ovlp_id(*p)].y_id+1, s, e, err); + assert(err >= 0); + if(err < msc) { + msc = err; msc_k = k; msc_n = 1; + } else if(err == msc) { + msc_n++; + } + buf->a[k] |= (((uint64_t)err)<<32); + } + + if(msc_n == 1) { + p = &(c_idx[(uint32_t)buf->a[msc_k]]); + z = &(ol[ovlp_id(*p)]); mn = 1; + if(msc_k != 0) { + m = buf->a[msc_k]; + buf->a[msc_k] = buf->a[0]; + buf->a[0] = m; + } + } else { + for (k = mn = 0; k < buf_n && (int64_t)mn < msc_n; k++) { + p = &(c_idx[(uint32_t)buf->a[k]]); + z = &(ol[ovlp_id(*p)]); + if((buf->a[k]>>32) == (uint64_t)msc) { + if(mn != k) { + m = buf->a[k]; + buf->a[k] = buf->a[mn]; + buf->a[mn] = m; + } + mn++; + } + } + } + // fprintf(stderr, "[M::%s] buf_n::%ld, msc_n::%ld, mn::%lu\n", __func__, buf_n, msc_n, mn); + for (k = 0; k < buf_n; k++) { + oid = ovlp_id((c_idx[(uint32_t)buf->a[k]])); + buf->a[k] >>= 32; buf->a[k] <<= 32; buf->a[k] |= oid; + ol[oid].overlapLen = k; + // if(s == 158482) fprintf(stderr, "k->%ld::oid->%ld[M::%s::utg%.6dl] pos::[%lu, %lu)\n", k, oid, __func__, + // (int32_t)ol[oid].y_id+1, s, e); + } + + for (k = 0; k < mn; k++) {///best alignment + z = &(ol[id_get(buf->a[k])]); + reassign_sec_err(ol, ovidx, buf, k); + push_sec_aln(z, s, e, 0); + } + + for (k = mn; k < buf_n; k++) { + z = &(ol[id_get(buf->a[k])]); + push_sec_aln(z, s, e, ((buf->a[k]&id_set)?(0):(err_get(buf->a[k])-msc))); + } + + for (k = 0; k < buf_n; k++) { + ol[id_get(buf->a[k])].overlapLen = (uint32_t)-1; + } + } + + + if(rm_n) { + for (k = m = 0; k < id_n; k++) { + p = &(c_idx[id_a[k]]); + q[1] = ol[ovlp_id(*p)].w_list.a[ovlp_max_wid(*p)].x_end+1; + if(q[1] < e) continue; + id_a[m++] = id_a[k]; + } + id_n = m; + } + return id_n; +} + + +///[s, e) +uint64_t gen_region_phase_robust(overlap_region* ol, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, uint64_t dp, ul_ov_t *c_idx, asg64_v *buf) +{ + if(!id_n) return id_n; + uint64_t k, m, mn, q[2], buf_n, rm_n, oid; int64_t err, msc, msc_k, msc_n; + overlap_region *z; ul_ov_t *p; buf->n = 0; kv_resize(uint64_t, *buf, dp); + for (k = buf_n = rm_n = 0; k < id_n; k++) { + p = &(c_idx[id_a[k]]); + q[0] = ol[ovlp_id(*p)].w_list.a[ovlp_min_wid(*p)].x_start; + q[1] = ol[ovlp_id(*p)].w_list.a[ovlp_max_wid(*p)].x_end+1; + if(q[0]<=s && q[1]>=e) { + kv_push(uint64_t, *buf, id_a[k]); + // buf[buf_n++] = id_a[k]; + } + if(q[1] < e) rm_n++; + } + buf_n = buf->n; + assert(buf_n == dp);//not right + + if(buf_n > 0) { + for (k = 0, msc = INT32_MAX, msc_k = -1, msc_n = 0; k < buf_n; k++) { + p = &(c_idx[(uint32_t)buf->a[k]]); z = &(ol[ovlp_id(*p)]); + // fprintf(stderr, "+++[M::%s::utg%.6dl] wid::%u, xoff::%u, coff::%u\n", __func__, + // (int32_t)ol[ovlp_id(*p)].y_id+1, ovlp_cur_wid(*p), ovlp_cur_xoff(*p), ovlp_cur_coff(*p)); + err = extract_sub_cigar_err(z, s, e, p); + // int64_t debug_err = extract_sub_cigar_err_debug(z, s, e); + // assert(err == debug_err); + // fprintf(stderr, "[M::%s::] err::%ld, debug_err::%ld\n", __func__, err, debug_err); + + // fprintf(stderr, "---[M::%s::utg%.6dl] wid::%u, xoff::%u, coff::%u, err::%ld\n", __func__, + // (int32_t)ol[ovlp_id(*p)].y_id+1, ovlp_cur_wid(*p), ovlp_cur_xoff(*p), ovlp_cur_coff(*p), err); + // fprintf(stderr, "---[M::%s::utg%.6dl] xoff::[%lu, %lu), err::%ld\n", __func__, + // (int32_t)ol[ovlp_id(*p)].y_id+1, s, e, err); + assert(err >= 0); + if(err < msc) { + msc = err; msc_k = k; msc_n = 1; + } else if(err == msc) { + msc_n++; + } + buf->a[k] |= (((uint64_t)err)<<32); + } + + if(msc_n == 1) { + p = &(c_idx[(uint32_t)buf->a[msc_k]]); + z = &(ol[ovlp_id(*p)]); mn = 1; + if(msc_k != 0) { + m = buf->a[msc_k]; + buf->a[msc_k] = buf->a[0]; + buf->a[0] = m; + } + } else { + for (k = mn = 0; k < buf_n && (int64_t)mn < msc_n; k++) { + p = &(c_idx[(uint32_t)buf->a[k]]); + z = &(ol[ovlp_id(*p)]); + if((buf->a[k]>>32) == (uint64_t)msc) { + if(mn != k) { + m = buf->a[k]; + buf->a[k] = buf->a[mn]; + buf->a[mn] = m; + } + mn++; + } + } + } + // fprintf(stderr, "[M::%s] buf_n::%ld, msc_n::%ld, mn::%lu\n", __func__, buf_n, msc_n, mn); + for (k = 0; k < buf_n; k++) { + oid = ovlp_id((c_idx[(uint32_t)buf->a[k]])); + buf->a[k] >>= 32; buf->a[k] <<= 32; buf->a[k] |= oid; + // ol[oid].overlapLen = k;//no need to set + // if(s == 158482) fprintf(stderr, "k->%ld::oid->%ld[M::%s::utg%.6dl] pos::[%lu, %lu)\n", k, oid, __func__, + // (int32_t)ol[oid].y_id+1, s, e); + } + + for (k = 0; k < mn; k++) {///best alignment + z = &(ol[id_get(buf->a[k])]); + // reassign_sec_err(ol, ovidx, buf, k); + // push_sec_aln(z, s, e, 0); + push_sec_aln_robust(z, s, e, 0); + } + + for (k = mn; k < buf_n; k++) { + z = &(ol[id_get(buf->a[k])]); + // push_sec_aln(z, s, e, ((buf->a[k]&id_set)?(0):(err_get(buf->a[k])-msc))); + push_sec_aln_robust(z, s, e, (err_get(buf->a[k])-msc)); + } + + // for (k = 0; k < buf_n; k++) { + // ol[id_get(buf->a[k])].overlapLen = (uint32_t)-1; + // } + } + + + if(rm_n) { + for (k = m = 0; k < id_n; k++) { + p = &(c_idx[id_a[k]]); + q[1] = ol[ovlp_id(*p)].w_list.a[ovlp_max_wid(*p)].x_end+1; + if(q[1] < e) continue; + id_a[m++] = id_a[k]; + } + id_n = m; + } + return id_n; +} + +///[s, e) +int64_t extract_sub_cigar_err_rr(overlap_region *z, int64_t s, int64_t e, ul_ov_t *p) +{ + int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), ck = ovlp_cur_coff(*p); + int64_t min_w = ovlp_min_wid(*p), max_w = ovlp_max_wid(*p);//[min_w, max_w] + bit_extz_t ez; window_list *m; int64_t bd = ovlp_bd(*p), s0, e0; + s0 = ((int64_t)(z->w_list.a[min_w].x_start)) + bd; + e0 = ((int64_t)(z->w_list.a[max_w].x_end))+1-bd; + if(s < s0) {s = s0;} if(e > e0) {e = e0;}///exclude boundary + if(s >= e) return -1; + + int64_t ws, we, os, oe, ovlp, err = 0, xl, yl, werr, tot = e - s; + if(wk < min_w || wk > max_w) wk = min_w; + for (; wk >= min_w && z->w_list.a[wk].x_start > s; wk--); + if(wk < min_w || wk > max_w) return -1; + for (; wk <= max_w && z->w_list.a[wk].x_end < s; wk++); + if(wk < min_w || wk > max_w) return -1; + //s >= w_list.a[wk].x_start && s <= w_list.a[wk].x_end + if(wk != ovlp_cur_wid(*p)) {//xk is global, while ck is local + xk = z->w_list.a[wk].x_start; ck = 0; + } + + while(wk <= max_w && z->w_list.a[wk].x_start < e) {///[s, e); [min_w, max_w] + m = &(z->w_list.a[wk]); + ws = m->x_start; we = m->x_end+1; + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + + if(ovlp) { + xl = m->x_end+1-m->x_start; + yl = m->y_end+1-m->y_start; + if((is_ualn_win((*m))) || (is_est_aln((*m)))) { + if(is_ualn_win((*m))) { //unmapped + werr = gen_err_unaligned(xl, yl); + } else { + werr = m->error;//shared window + } + if(ovlp < xl) { + werr = (((double)ovlp)/((double)xl))*((double)werr); + } + //skip the whole window + err += werr; xk = m->x_end+1; ck = m->clen; + } else { + if(ovlp == xl) { + //skip the whole window + err += m->error; xk = m->x_end+1; ck = m->clen; + } else { + set_bit_extz_t(ez, (*z), wk); + err += retrieve_cigar_err(&ez, os, oe, &xk, &ck); + } + } + } + tot -= ovlp; + if(xk >= e) break;//[min_w, max_w] && [s, e) + wk++; if(wk > max_w) break; + xk = z->w_list.a[wk].x_start; ck = 0;//reset + } + assert(!tot); + ovlp_cur_wid(*p) = wk; ovlp_cur_xoff(*p) = xk; ovlp_cur_coff(*p) = ck; + return err; +} + +///[s, e) +inline int64_t detect_near_cc_tlen(bit_extz_t *ez, int64_t ck0, int64_t xk0, int64_t yk0, uint8_t rev) +{ + int64_t ck = ck0, xk = xk0, yk = yk0, cn = ez->cigar.n, op; + if(!rev) { + if(ck >= cn) return yk; + while (ck < cn) { + op = ez->cigar.a[ck]>>14; + if(op == 0) return yk; + if(op!=2) xk += (ez->cigar.a[ck]&(0x3fff)); + if(op!=3) yk += (ez->cigar.a[ck]&(0x3fff)); + ck++; + } + } else { + if(ck <= 0) return yk; + while (ck > 0) { + --ck; + op = ez->cigar.a[ck]>>14; + if(op == 0) return yk; + if(op!=2) xk -= (ez->cigar.a[ck]&(0x3fff)); + if(op!=3) yk -= (ez->cigar.a[ck]&(0x3fff)); + } + } + + return yk; +} + +inline int64_t cal0_ew(bit_extz_t *ez, int64_t ck, int64_t xk, int64_t s, int64_t e, int64_t max_e) +{ + int64_t cn = ez->cigar.n, err = 0, op, ol, ws, we, os, oe, ovlp; + while (ck > 0 && xk > s) { + --ck; + if((ez->cigar.a[ck]>>14)!=2) xk -= (ez->cigar.a[ck]&(0x3fff)); + } + + while (ck < cn && xk < e && err <= max_e) {//[s, e) + ws = xk; + op = ez->cigar.a[ck]>>14; ol = (ez->cigar.a[ck]&(0x3fff)); + if(op!=2) xk += ol; + ck++; we = xk; + if(!op) continue; + + if(op == 2) { + if(ws > s && ws < e) err += ol; + continue; + } + + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + err += ovlp; + } + + return err; +} + +///[s, e) +int64_t extract_sub_cigar_hc(overlap_region *z, All_reads *rref, haplotype_evdience_alloc* hp, char *qstr, uint64_t ql, UC_Read* tu, int64_t s, int64_t e, ul_ov_t *p, int64_t set_f, uint8_t *f, uint8_t occ_thres, uint64_t hpc_len, uint64_t h0_w) +{ + // fprintf(stderr, "\n[M::%s]\ts::%ld\te::%ld\tset_f::%ld\tovlp_id::%u\twid::%u\n", __func__, s, e, set_f, ovlp_id(*p), ovlp_cur_wid(*p)); + // if((!set_f) && (!ovlp_cur_ylen(*p))) return 1;///no potential informative site + int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), yk = ovlp_cur_yoff(*p), ck = ovlp_cur_coff(*p), os, oe, sa0, ea0, t; + bit_extz_t ez; int64_t bd = ovlp_bd(*p), s0, e0; char *ystr = NULL; + s0 = ((int64_t)(z->w_list.a[wk].x_start)) + bd; + e0 = ((int64_t)(z->w_list.a[wk].x_end)) + 1 - bd; + if(s < s0) {s = s0;} if(e > e0) {e = e0;}///exclude boundary + if(s >= e) return -1; + os = MAX(s, s0); oe = MIN(e, e0); + if(oe <= os) return -1; + + set_bit_extz_t(ez, (*z), wk); + if(!ez.cigar.n) return -1; + int64_t cn = ez.cigar.n, op; int64_t ws, we, ovlp, xk0, yk0, ck0, yk1 = -1, /**xk1 = -1, ck1 = -1,**/ yl; haplotype_evdience ev; uint8_t om; + xk0 = xk; yk0 = yk; ck0 = ck; ///for assertion + if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed + ck = 0; xk = ez.ts; yk = ez.ps; + } + + while (ck > 0 && xk > s) {///x -> t; y -> p + --ck; + op = ez.cigar.a[ck]>>14; + if(op!=2) xk -= (ez.cigar.a[ck]&(0x3fff)); + if(op!=3) yk -= (ez.cigar.a[ck]&(0x3fff)); + } + + if(set_f) { + ovlp_cur_ylen(*p) = 0; + xk0 = xk; yk0 = yk; ck0 = ck; + } else { + assert(xk0 == xk); assert(yk0 == yk); assert(ck0 == ck); + yk1 = yk0 + ovlp_cur_ylen(*p); yl = Get_READ_LENGTH((*rref), z->y_id); + + // UC_Read_resize(*tu, ovlp_cur_ylen(*p)); ystr = tu->seq; + // if(is_dbg) fprintf(stderr, "[M::%s] set_f::%ld, yk0::%ld, ovlp_cur_ylen::%u, ylen::%lu\n", __func__, set_f, yk0, ovlp_cur_ylen(*p), Get_READ_LENGTH((*rref), z->y_id)); + // recover_UC_Read_sub_region(ystr, yk0, ovlp_cur_ylen(*p), z->y_pos_strand, rref, z->y_id); + } + + // if(is_dbg) fprintf(stderr, "---0---[M::%s] set_f::%ld, yk::%ld\n", __func__, set_f, yk); + //some cigar will span s or e + while (ck < cn && xk < e) {//[s, e) + ws = xk; + op = ez.cigar.a[ck]>>14; + if(op!=2) xk += (ez.cigar.a[ck]&(0x3fff)); + if(op!=3) yk += (ez.cigar.a[ck]&(0x3fff)); + ck++; we = xk; + if(op != 0 && op != 1) continue;///only collect match/snp + + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + if(!ovlp) continue; + + if(set_f) { + if(op == 1) { + for (t = os; t < oe; t++) { + f[t-s] = ((f[t-s]<=126)?(f[t-s]+1):(127)); + } + // if(!hpc_len) { + // yk1 = oe-xk+yk; + // } else { + // yk1 = yk; xk1 = xk; ck1 = ck; + // } + yk1 = oe-xk+yk; + } + } else { + if(op == 0) { + for (t = os; t < oe; t++) { + if(f[t-s]) { + sa0 = t - h0_w; ea0 = t + h0_w; + ///r789 + if(((sa0 >= ws) && (ea0 <= we)) || (cal0_ew(&ez, ck, xk, sa0, ea0, h0_w_p) <= h0_w_p)) { + om = ((f[t-s]==3)?1:0); + ev.misBase = qstr[t]; + ev.overlapID = ovlp_id(*p); + ev.site = t; + ev.overlapSite = t-xk+yk; + ev.type = (om<<1); + ev.cov = 1; + addHaplotypeEvdience(hp, &ev, NULL); + } + } + } + } else if(op == 1) { + for (t = os; t < oe; t++) { + if(f[t-s]) { + if(!ystr) { + // yk0 = ((hpc_len)?(detect_near_cc_tlen(&ez, ck, xk, yk, 1)):(t-xk+yk)); + yk0 = t-xk+yk; + yk0 -= hpc_len; if(yk0 < 0) yk0 = 0; + UC_Read_resize(*tu, (yk1 - yk0)); ystr = tu->seq; + recover_UC_Read_sub_region(ystr, yk0, (yk1 - yk0), z->y_pos_strand, rref, z->y_id); + } + + om = ((f[t-s]==3)?1:0); + if((!om) && (hpc_len) && (hpc_mask_ff(ystr, yk1 - yk0, t-xk+yk-yk0, hpc_len, HPC_RR, NULL, -1, -1, HPC_CC, NULL, NULL))) om = 1; + + ev.misBase = ystr[t-xk+yk-yk0]; + ev.overlapID = ovlp_id(*p); + ev.site = t; + ev.overlapSite = t-xk+yk; + ev.type = (om<<1) + 1; + ev.cov = 1; + addHaplotypeEvdience(hp, &ev, NULL); + // if(ev.overlapID == 21 && ev.site == 17129) { + // fprintf(stderr, "[M::%s]\ts::%ld\te::%ld\tck::%ld\txk::%ld\tyk::%ld\tset_f::%ld\n", __func__, s, e, ck, xk, yk, set_f); + // } + } + + } + } + } + } + // if(is_dbg) fprintf(stderr, "---1---[M::%s] set_f::%ld, yk::%ld\n", __func__, set_f, yk); + + if(set_f) { + ovlp_cur_xoff(*p) = xk0; ovlp_cur_yoff(*p) = yk0; ovlp_cur_coff(*p) = ck0; + if(yk1 != -1) { + // if((xk1 != -1) && (yk1 != -1)) {///detect nearby differences + // yk1 = detect_near_cc_tlen(&ez, ck1, xk1, yk1, 0); + // } + yk1 += hpc_len; + yl = Get_READ_LENGTH((*rref), z->y_id); + if(yk1 > yl) yk1 = yl; + ovlp_cur_ylen(*p) = yk1 - yk0; + } else {///no potential informative site; no second round + ovlp_cur_ylen(*p) = 0; + } + } else { + ovlp_cur_xoff(*p) = xk; ovlp_cur_yoff(*p) = yk; ovlp_cur_coff(*p) = ck; ovlp_cur_ylen(*p) = 0; + } + + return 1; +} + +inline char* cal_hpc_len(All_reads *rref, uint8_t rev, uint32_t id, int64_t s0, int64_t e0, int64_t cs, int64_t ce, int64_t *rs, int64_t *re, UC_Read *z) +{ + int64_t os, oe, ol, cl; (*rs) = (*re) = -1; + os = MAX(s0, cs); oe = MIN(e0, ce); + if(os >= s0 && oe <= e0) { + (*rs) = s0; (*re) = e0; + return z->seq; + } + ol = oe - os; cl = ce - cs; (*rs) = cs; (*re) = ce; + UC_Read_resize(*z, cl); + + if((ol >= 16) || ((ol) && (ol > (cl * 0.75)))) {///reuse + memmove(z->seq + os - cs, z->seq + os - s0, ol); + if(os > cs) recover_UC_Read_sub_region(z->seq, cs, os - cs, rev, rref, id); + if(ce > oe) recover_UC_Read_sub_region(z->seq + oe - cs, oe, ce - oe, rev, rref, id); + } else { + recover_UC_Read_sub_region(z->seq, cs, cl, rev, rref, id); + } + return z->seq; +} + +/** +///[s, e) +int64_t extract_sub_cigar_hc_hpc(overlap_region *z, All_reads *rref, haplotype_evdience_alloc* hp, char *qstr, uint64_t ql, UC_Read *tu, int64_t s, int64_t e, ul_ov_t *p, int64_t set_f, uint8_t *f, uint8_t occ_thres, int64_t hpc_len, uint64_t h0_w) +{ + // fprintf(stderr, "\n[M::%s]\ts::%ld\te::%ld\tset_f::%ld\tovlp_id::%u\twid::%u\n", __func__, s, e, set_f, ovlp_id(*p), ovlp_cur_wid(*p)); + // if((!set_f) && (!ovlp_cur_ylen(*p))) return 1;///no potential informative site + int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), yk = ovlp_cur_yoff(*p), ck = ovlp_cur_coff(*p), os, oe, sa0, ea0, t; + bit_extz_t ez; int64_t bd = ovlp_bd(*p), s0, e0; char *ystr = NULL; + s0 = ((int64_t)(z->w_list.a[wk].x_start)) + bd; + e0 = ((int64_t)(z->w_list.a[wk].x_end)) + 1 - bd; + if(s < s0) {s = s0;} if(e > e0) {e = e0;}///exclude boundary + if(s >= e) return -1; + os = MAX(s, s0); oe = MIN(e, e0); + if(oe <= os) return -1; + + set_bit_extz_t(ez, (*z), wk); + if(!ez.cigar.n) return -1; + int64_t cn = ez.cigar.n, op; int64_t ws, we, ovlp, xk0, yk0 = -1, ck0, yk1 = -1, yl; haplotype_evdience ev; uint8_t om; + xk0 = xk; ck0 = ck; ///for assertion + if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed + ck = 0; xk = ez.ts; yk = ez.ps; + } + + while (ck > 0 && xk > s) {///x -> t; y -> p + --ck; + op = ez.cigar.a[ck]>>14; + if(op!=2) xk -= (ez.cigar.a[ck]&(0x3fff)); + if(op!=3) yk -= (ez.cigar.a[ck]&(0x3fff)); + } + + if(set_f) { + ovlp_cur_ylen(*p) = 0; + xk0 = xk; ck0 = ck; + } else { + assert(xk0 == xk); assert(ck0 == ck); yl = Get_READ_LENGTH((*rref), z->y_id); + // UC_Read_resize(*tu, ovlp_cur_ylen(*p)); ystr = tu->seq; + // if(is_dbg) fprintf(stderr, "[M::%s] set_f::%ld, yk0::%ld, ovlp_cur_ylen::%u, ylen::%lu\n", __func__, set_f, yk0, ovlp_cur_ylen(*p), Get_READ_LENGTH((*rref), z->y_id)); + // recover_UC_Read_sub_region(ystr, yk0, ovlp_cur_ylen(*p), z->y_pos_strand, rref, z->y_id); + } + + // if(is_dbg) fprintf(stderr, "---0---[M::%s] set_f::%ld, yk::%ld\n", __func__, set_f, yk); + //some cigar will span s or e + while (ck < cn && xk < e) {//[s, e) + ws = xk; + op = ez.cigar.a[ck]>>14; + if(op!=2) xk += (ez.cigar.a[ck]&(0x3fff)); + if(op!=3) yk += (ez.cigar.a[ck]&(0x3fff)); + ck++; we = xk; + if(op != 0 && op != 1) continue;///only collect match/snp + + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + if(!ovlp) continue; + + if(set_f) { + if(op == 1) { + for (t = os; t < oe; t++) { + f[t-s] = ((f[t-s]<=126)?(f[t-s]+1):(127)); + } + yk1 = oe-xk+yk; + } + } else { + if(op == 0) { + for (t = os; t < oe; t++) { + if(f[t-s]) { + sa0 = t - h0_w; ea0 = t + h0_w; + ///r789 + if(((sa0 >= ws) && (ea0 <= we)) || (cal0_ew(&ez, ck, xk, sa0, ea0, h0_w_p) <= h0_w_p)) { + om = ((f[t-s]==3)?1:0); + ev.misBase = qstr[t]; + ev.overlapID = ovlp_id(*p); + ev.site = t; + ev.overlapSite = t-xk+yk; + ev.type = (om<<1); + ev.cov = 1; + addHaplotypeEvdience(hp, &ev, NULL); + } + } + } + } else if(op == 1) { + // ystr = cal_hpc_len(rref, z->y_pos_strand, z->y_id, yk0, yk1, ((os>=hpc_len)?(os-hpc_len):(0)), ((oe+hpc_len<=yl)?(oe+hpc_len):(yl)), &yk0, &yk1, tu); + for (t = os; t < oe; t++) { + if(f[t-s]) { + + om = ((f[t-s]==3)?1:0); + // if((!om) && (hpc_len) && (hpc_mask_ff(ystr, yk1 - yk0, t-xk+yk-yk0, hpc_len, HPC_RR, NULL, -1, -1, HPC_CC, NULL, NULL))) om = 1; + + ev.misBase = ystr[t-xk+yk-yk0]; + ev.overlapID = ovlp_id(*p); + ev.site = t; + ev.overlapSite = t-xk+yk; + ev.type = (om<<1) + 1; + ev.cov = 1; + addHaplotypeEvdience(hp, &ev, NULL); + // if(ev.overlapID == 21 && ev.site == 17129) { + // fprintf(stderr, "[M::%s]\ts::%ld\te::%ld\tck::%ld\txk::%ld\tyk::%ld\tset_f::%ld\n", __func__, s, e, ck, xk, yk, set_f); + // } + } + + } + } else if(hpc_len) {///op == 3, more x + for (t = os; (t < oe) && (f[t-s] != 3); t++); + if(t < oe) { + ystr = cal_hpc_len(rref, z->y_pos_strand, z->y_id, yk0, yk1, ((yk>=hpc_len)?(yk-hpc_len):(0)), ((yk+hpc_len<=yl)?(yk+hpc_len):(yl)), &yk0, &yk1, tu); + for (; t < oe; t++) { + if(f[t-s] == 3) { + ; + } + } + } + } + } + } + // if(is_dbg) fprintf(stderr, "---1---[M::%s] set_f::%ld, yk::%ld\n", __func__, set_f, yk); + + if(set_f) { + ovlp_cur_xoff(*p) = xk0; ovlp_cur_yoff(*p) = yk0; ovlp_cur_coff(*p) = ck0; + } else { + ovlp_cur_xoff(*p) = xk; ovlp_cur_yoff(*p) = yk; ovlp_cur_coff(*p) = ck; + } + + return 1; +} +**/ + +///[s, e) +void extract_sub_kmer(overlap_region *z, int64_t s, int64_t e, int64_t al, int64_t kl, ul_ov_t *p, uint64_t *cnt) +{ + // fprintf(stderr, "\n[M::%s]\ts::%ld\te::%ld\tset_f::%ld\tovlp_id::%u\twid::%u\n", __func__, s, e, set_f, ovlp_id(*p), ovlp_cur_wid(*p)); + // if((!set_f) && (!ovlp_cur_ylen(*p))) return 1;///no potential informative site + int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), yk = ovlp_cur_yoff(*p), ck = ovlp_cur_coff(*p), os, oe; + bit_extz_t ez; int64_t bd = ovlp_bd(*p), s0, e0, sk = s; s = s + 1 - kl; if (s < 0) s = 0; + s0 = ((int64_t)(z->w_list.a[wk].x_start)) + bd; + e0 = ((int64_t)(z->w_list.a[wk].x_end)) + 1 - bd; + if(s < s0) {s = s0;} if(e > e0) {e = e0;}///exclude boundary + if(s >= e) return; + os = MAX(s, s0); oe = MIN(e, e0); + if(oe <= os) return; + + set_bit_extz_t(ez, (*z), wk); + if(!ez.cigar.n) return; + int64_t cn = ez.cigar.n, op, ol; int64_t ws, we, ovlp; + if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed + ck = 0; xk = ez.ts; yk = ez.ps; + } + + while (ck > 0 && xk >= s) {///x -> t; y -> p + --ck; + op = ez.cigar.a[ck]>>14; + if(op!=2) xk -= (ez.cigar.a[ck]&(0x3fff)); + if(op!=3) yk -= (ez.cigar.a[ck]&(0x3fff)); + } + + // if(is_dbg) fprintf(stderr, "---0---[M::%s] set_f::%ld, yk::%ld\n", __func__, set_f, yk); + //some cigar will span s or e + while (ck < cn && xk < e) {//[s, e) + ws = xk; + op = ez.cigar.a[ck]>>14; + ol = (ez.cigar.a[ck]&(0x3fff)); + if(op!=2) xk += ol; + if(op!=3) yk += ol; + ck++; we = xk; + if(op) continue; + + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + if(ovlp < kl) continue; + + for (wk = os + kl - 1; wk < oe; wk++) cnt[wk - sk]++; + } + + // if(is_dbg) fprintf(stderr, "---1---[M::%s] set_f::%ld, yk::%ld\n", __func__, set_f, yk); + + ovlp_cur_xoff(*p) = xk; ovlp_cur_yoff(*p) = yk; + ovlp_cur_coff(*p) = ck; ovlp_cur_ylen(*p) = 0; + + return; +} + +///[s, e) +int64_t extract_sub_err(overlap_region *z, int64_t s, int64_t e, int64_t os0, int64_t oe0, int64_t err0, double err_sec_rate, ul_ov_t *p) +{ + // fprintf(stderr, "\n[M::%s]\ts::%ld\te::%ld\tset_f::%ld\tovlp_id::%u\twid::%u\n", __func__, s, e, set_f, ovlp_id(*p), ovlp_cur_wid(*p)); + // if((!set_f) && (!ovlp_cur_ylen(*p))) return 1;///no potential informative site + int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), yk = ovlp_cur_yoff(*p), ck = ovlp_cur_coff(*p), os, oe, t, l[2], err; + bit_extz_t ez; int64_t bd = ovlp_bd(*p), s0, e0; + s0 = ((int64_t)(z->w_list.a[wk].x_start)) + bd; + e0 = ((int64_t)(z->w_list.a[wk].x_end)) + 1 - bd; + if(s < s0) {s = s0;} if(e > e0) {e = e0;}///exclude boundary + if(s >= e) return -1; + os = MAX(s, s0); oe = MIN(e, e0); + if(oe <= os) return -1; + + set_bit_extz_t(ez, (*z), wk); + if(!ez.cigar.n) return -1; + int64_t cn = ez.cigar.n, op, ol; int64_t ws, we, ovlp; + if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed + ck = 0; xk = ez.ts; yk = ez.ps; + } + + while (ck > 0 && xk >= s) {///x -> t; y -> p + --ck; + op = ez.cigar.a[ck]>>14; + if(op!=2) xk -= (ez.cigar.a[ck]&(0x3fff)); + if(op!=3) yk -= (ez.cigar.a[ck]&(0x3fff)); + } + + // if(is_dbg) fprintf(stderr, "---0---[M::%s] set_f::%ld, yk::%ld\n", __func__, set_f, yk); + //some cigar will span s or e + l[0] = l[1] = 0; + while (ck < cn && xk < e) {//[s, e) + ws = xk; + op = ez.cigar.a[ck]>>14; + ol = (ez.cigar.a[ck]&(0x3fff)); + if(op!=2) xk += ol; + if(op!=3) yk += ol; + ck++; we = xk; t= 0; + // if(op != 0 && op != 1) continue;///only collect match/snp + + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + if((op==2) && (ws == we) && ((ws>=s) && (ws<=e))) t = 1; + if(ovlp) t = 1; + if(!t) continue; + + if(op!=2) { + l[(!!op)] += ovlp; + } else { + l[1] += ol; + } + } + + while (ck < cn && xk <= e) {//[s, e) + ws = xk; + op = ez.cigar.a[ck]>>14; ol = (ez.cigar.a[ck]&(0x3fff)); + if(op != 2) break; + + for (ck++; (ck < cn) && (op == (ez.cigar.a[ck]>>14)); ck++) { + ol += (ez.cigar.a[ck]&(0x3fff)); + } + yk += ol; we = xk; + + if(ws >= s && ws <= e) l[1] += ol; + } + // if(is_dbg) fprintf(stderr, "---1---[M::%s] set_f::%ld, yk::%ld\n", __func__, set_f, yk); + + ovlp_cur_xoff(*p) = xk; ovlp_cur_yoff(*p) = yk; + ovlp_cur_coff(*p) = ck; ovlp_cur_ylen(*p) = 0; + + // fprintf(stderr, "[M::%s] cid::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\n", __func__, c_idx->a[zi].ts, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), c_idx->a[zi].qs, c_idx->a[zi].qe, c_idx->a[zi].qn); + + + + err = err0; + if((oe0 - os0) < (e - s)) { + err = (((double)(oe0 - os0))/((double)(e - s)))*err0; + } + err *= err_sec_rate; + // fprintf(stderr, "[M::%s]\t%.*s\tl[0]::%ld\tl[1]::%ld\tthres::%ld\n", __func__, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), l[0], l[1], err); + if(l[1] <= err) return l[1]; + return -1; +} + + +uint64_t iter_sub_cigar_sv(int64_t zid, ul_ov_t *cp, bit_extz_t *ez, int64_t *ck, int64_t *xk, int64_t *yk, char *qstr, int64_t ql, char *tstr, int64_t tl, int64_t ts, int64_t te, int64_t hpc_len, int64_t hpc_rr, int64_t *rys, int64_t *rye, int64_t exd_err_bd) +{ + int64_t err = 0, herr = 0, ex[2], ey[2], s, e, cn = ez->cigar.n, wx[2], wy[2], p; uint16_t op; uint32_t cl; + ex[0] = ex[1] = -1; ey[0] = ey[1] = -1; + (*rys) = (*rye) = -1; + // fprintf(stderr, "+[M::%s] rid::%u\t%.*s\tq::[%u,%u)\tql::%ld\tt::[%u,%u)\ttl::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), cp->qs, cp->qe, ql, cp->ts, cp->te, tl); + + s = cp->qs; e = cp->qe; + while ((*ck) > 0 && (*xk) >= s) {///x -> t; y -> p + --(*ck); + op = ez->cigar.a[*ck]>>14; + if(op!=2) (*xk) -= (ez->cigar.a[*ck]&(0x3fff)); + if(op!=3) (*yk) -= (ez->cigar.a[*ck]&(0x3fff)); + } + + while ((*ck) < cn && (*xk) < e) {//[s, e) + wx[0] = *xk; wy[0] = *yk; + (*ck) = pop_trace(&(ez->cigar), *ck, &op, &cl); + if(op!=2) (*xk) += cl; + if(op!=3) (*yk) += cl; + wx[1] = (*xk); wy[1] = (*yk); + if(op == 0) continue; + if(wx[0] >= s && wx[1] <= e) { + if(ex[0] < 0) ex[0] = wx[0]; + if(ey[0] < 0) ey[0] = wy[0]; + ex[1] = wx[1]; ey[1] = wy[1]; + err += cl; + if(hpc_len > 0) { + assert(wy[0] >= ts && wy[1] <= te); + if(hpc_mask_ff_region(qstr, ql, wx[0], wx[1], hpc_len, hpc_rr, 6, 0.51) || hpc_mask_ff_region(tstr, tl, wy[0] - ts, wy[1] - ts, hpc_len, hpc_rr, 6, 0.51)) { + herr += cl; + } + } + } + } + + while ((*ck) < cn && (*xk) <= e) {//[s, e) + wx[0] = *xk; wy[0] = *yk; + op = ez->cigar.a[*ck]>>14; + cl = (ez->cigar.a[*ck]&(0x3fff)); + if(op != 2) break; + (*yk) += (ez->cigar.a[*ck]&(0x3fff)); + (*ck)++; wx[1] = (*xk); wy[1] = (*yk); + if(wx[0] >= s && wx[1] <= e) { + if(ex[0] < 0) ex[0] = wx[0]; + if(ey[0] < 0) ey[0] = wy[0]; + ex[1] = wx[1]; ey[1] = wy[1]; + err += cl; + if(hpc_len > 0) { + assert(wy[0] >= ts && wy[1] <= te); + if(hpc_mask_ff_region(qstr, ql, wx[0], wx[1], hpc_len, hpc_rr, 6, 0.51) || hpc_mask_ff_region(tstr, tl, wy[0] - ts, wy[1] - ts, hpc_len, hpc_rr, 6, 0.51)) { + herr += cl; + } + } + } + } + + if(hpc_len > 0) { + // cp->qs = ex[0]; cp->qe = ex[1]; + // cp->ts = ey[0]; cp->te = ey[1]; + // cp->ts = s; cp->te = e; + assert(cp->qn == err); + cp->qs = s; cp->qe = e; + cp->ts = ex[0]; cp->te = ex[1]; + cp->tn = zid; cp->qn = err; + if((herr > 0) && (herr > (err*0.66))) cp->el = 0; + else cp->el = 1; + // (*rys) = ey[0]; (*rye) = ey[1]; + if(err <= exd_err_bd) { + p = (s + e)/2; p -= exd_err_bd; if(p < 0) p = 0; if(p < ((int64_t)cp->qs)) cp->qs = p; + p = (s + e)/2; p += exd_err_bd; if(p > ql) p = ql; if(p > ((int64_t)cp->qe)) cp->qe = p; + } + } + // else { + // assert(cp->qn == err); + // } + (*rys) = ey[0]; (*rye) = ey[1]; + + return err; +} + +int64_t extract_sub_cigar_sv(overlap_region *z, int64_t zid, int64_t wk, All_reads *rref, char *qstr, int64_t ql, UC_Read* tu, kv_ul_ov_t *rr, uint64_t min_err, int64_t hpc_len, int64_t hpc_rr) +{ + int64_t xk = z->w_list.a[wk].x_start, yk = z->w_list.a[wk].y_start; ul_ov_t *cp, *ra; bit_extz_t ez; + int64_t ck = 0, ex[2], ey[2], el0, tl = Get_READ_LENGTH((*rref), z->y_id), ox[2], oy[2], os, oe, ff, rn, rn1, k; uint32_t cl, rr_n0 = rr->n, is_srt = 1; + set_bit_extz_t(ez, (*z), wk); + if(!ez.cigar.n) return -1; + int64_t cn = ez.cigar.n, wx[2], wy[2]; uint16_t op, op0; + ex[0] = ex[1] = ey[0] = ey[1] = -1; + + while (ck < cn) {//[s, e) + wx[0] = xk; wy[0] = yk; el0 = 0; + op = (ez.cigar.a[ck]>>14); + cl = (ez.cigar.a[ck]&(0x3fff)); + if(op!=2) {xk += cl;} if(op!=3) {yk += cl;} + op0 = op; el0 += cl; + for (ck++; ck < cn; ck++) { + op = (ez.cigar.a[ck]>>14); + if((!!op) != (!!op0)) break; + cl = (ez.cigar.a[ck]&(0x3fff)); + if(op!=2) {xk += cl;} if(op!=3) {yk += cl;} + el0 += cl; + } + wx[1] = xk; wy[1] = yk; + if(op0 == 0) continue; + ff = 1; + + + ox[0] = ((wx[0]>=el0)?(wx[0]-el0):(0)); ox[1] = ((wx[1]+el0<=ql)?(wx[1]+el0):(ql)); + oy[0] = ((wy[0]>=el0)?(wy[0]-el0):(0)); oy[1] = ((wy[1]+el0<=tl)?(wy[1]+el0):(tl)); + + if(ex[0] < 0 || ex[1] < 0 || ey[0] < 0 || ey[1] < 0) ff = 0; + + if(ff) { + os = MAX(ox[0], ex[0]); oe = MIN(ox[1], ex[1]); + if(oe <= os) ff = 0; + + os = MAX(oy[0], ey[0]); oe = MIN(oy[1], ey[1]); + if(oe <= os) ff = 0; + } + + if(ff) {///extend + ex[0] = MIN(ox[0], ex[0]); ex[1] = MAX(ox[1], ex[1]); + ey[0] = MIN(oy[0], ey[0]); ey[1] = MAX(oy[1], ey[1]); + } else { + if(ex[0] >= 0 && ex[1] >= 0 && ey[0] >= 0 && ey[1] >= 0) { + kv_pushp(ul_ov_t, *rr, &cp); + cp->qs = ex[0]; cp->qe = ex[1]; + cp->ts = ey[0]; cp->te = ey[1]; + cp->sec = 0; cp->el = 0; cp->rev = 0; + if((rr->n > rr_n0 + 1) && (cp->qs < rr->a[rr->n-2].qs)) is_srt = 0; + // if(z->y_id == 2857440) { + // fprintf(stderr, "0[M::%s] rid::%u\t%.*s\tq0::[%u,%u)\tql::%ld\tq1::[%u,%u)\teq::%u\tet::%u\n", __func__, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), cp->qs, cp->qe, ql, cp->ts, cp->te, cp->qe - cp->qs, cp->te - cp->ts); + // } + } + ex[0] = ox[0]; ex[1] = ox[1]; + ey[0] = oy[0]; ey[1] = oy[1]; + } + } + + if(ex[0] >= 0 && ex[1] >= 0 && ey[0] >= 0 && ey[1] >= 0) { + kv_pushp(ul_ov_t, *rr, &cp); + cp->qs = ex[0]; cp->qe = ex[1]; + cp->ts = ey[0]; cp->te = ey[1]; + cp->sec = 0; cp->el = 0; cp->rev = 0; + if((rr->n > rr_n0 + 1) && (cp->qs < rr->a[rr->n-2].qs)) is_srt = 0; + // if(z->y_id == 2857440) { + // fprintf(stderr, "0[M::%s] rid::%u\t%.*s\tq0::[%u,%u)\tql::%ld\tq1::[%u,%u)\n", __func__, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), cp->qs, cp->qe, ql, cp->ts, cp->te); + // } + } + + if(rr->n <= rr_n0) return 0; + if(!is_srt) radix_sort_ul_ov_srt_qs1(rr->a + rr_n0, rr->a + rr->n); + + ra = rr->a + rr_n0; rn = rr->n - rr_n0; + for (k = ck = 0; k < rn; k++) { + if(ck > 0 && ra[k].qs < ra[ck - 1].qe) { + if(ra[k].qe > ra[ck - 1].qe) ra[ck - 1].qe = ra[k].qe; + if(ra[k].ts < ra[ck - 1].ts) ra[ck - 1].ts = ra[k].ts; + if(ra[k].te > ra[ck - 1].te) ra[ck - 1].te = ra[k].te; + } else { + if((ck > 0) && (ra[ck - 1].qe - ra[ck - 1].qs < min_err) && (ra[ck - 1].te - ra[ck - 1].ts < min_err)) { + ck--; + } + ra[ck++] = ra[k]; + } + } + if((ck > 0) && (ra[ck - 1].qe - ra[ck - 1].qs < min_err) && (ra[ck - 1].te - ra[ck - 1].ts < min_err)) ck--; + if(ck == 0) { + rr->n = rr_n0; + return 0; + } + rn = ck; ck = 0; xk = z->w_list.a[wk].x_start; yk = z->w_list.a[wk].y_start; + for (k = ck = rn1 = 0; k < rn; k++) { + cp = &(ra[k]); + cp->qn = iter_sub_cigar_sv(zid, cp, &ez, &ck, &xk, &yk, NULL, -1, NULL, -1, -1, -1, -1, -1, &(ey[0]), &(ey[1]), -1); + if(cp->qn < min_err) continue; + assert(ey[0] >= 0 && ey[1] >= 0 && ey[1] >= ey[0]); + ey[0] -= hpc_len; if(ey[0] < 0) ey[0] = 0; + ey[1] += hpc_len; if(ey[1] > tl) ey[1] = tl; + + UC_Read_resize(*tu, (ey[1] - ey[0])); ///ystr = tu->seq; + recover_UC_Read_sub_region(tu->seq, ey[0], (ey[1] - ey[0]), z->y_pos_strand, rref, z->y_id); + iter_sub_cigar_sv(zid, cp, &ez, &ck, &xk, &yk, qstr, ql, tu->seq, tl, ey[0], ey[1], hpc_len, hpc_rr, &(ey[0]), &(ey[1]), (min_err<<1)); + + ra[rn1++] = *cp; + // if(z->y_id == 2857440) { + // fprintf(stderr, "-[M::%s] rid::%u\t%.*s\tq0::[%u,%u)\tql::%ld\tq1::[%u,%u)\t\terr::%u\tel::%u\n", __func__, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), cp->qs, cp->qe, ql, cp->ts, cp->te, cp->qn, cp->el); + // } + } + + // fprintf(stderr, "\n"); + + rr->n = rr_n0 + rn1; + if(rn1 > 0) return 1; + else return 0; +} + +uint64_t is_mask_ov(mask_ul_ov_t *mk, uint64_t *bes_id, uint64_t bes_n, uint64_t sec_id) +{ + uint64_t s = mk->idx.a[sec_id]>>32, e = (uint32_t)(mk->idx.a[sec_id]), bk, si; + bk = 0; si = s; + while (bk < bes_n && si < e) { + if (bes_id[bk] < mk->srt.a[si].tn) { + bk++; + } else if(mk->srt.a[si].tn < bes_id[bk]) { + si++; + } else {///bes_id[bk] == mk->srt.a[si].tn + if(!(mk->srt.a[si].qs)) return 1; + return 0; + } + } + return 0; +} + +///[s, e) +uint64_t gen_region_phase_robust_rr(overlap_region* ol, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, uint64_t dp, ul_ov_t *c_idx, asg64_v *buf, mask_ul_ov_t *mk) +{ + if(!id_n) return id_n; + uint64_t k, m, mn, q[2], buf_n, rm_n, oid; int64_t err, msc, msc_k, msc_n; + overlap_region *z; ul_ov_t *p; buf->n = 0; kv_resize(uint64_t, *buf, dp); + for (k = buf_n = rm_n = 0; k < id_n; k++) { + p = &(c_idx[id_a[k]]); + q[0] = ol[ovlp_id(*p)].w_list.a[ovlp_min_wid(*p)].x_start+ovlp_bd(*p); + q[1] = ol[ovlp_id(*p)].w_list.a[ovlp_max_wid(*p)].x_end+1-ovlp_bd(*p); + if(q[0]<=s && q[1]>=e) { + kv_push(uint64_t, *buf, id_a[k]); + } + if(q[1] < e) rm_n++; + } + buf_n = buf->n; + // fprintf(stderr, "[M::%s] buf_n::%lu, dp::%lu\n", __func__, buf_n, dp); + assert(buf_n == dp);//not right + + if(buf_n > 0) { + for (k = 0, msc = INT32_MAX, msc_k = -1, msc_n = 0; k < buf_n; k++) { + p = &(c_idx[(uint32_t)buf->a[k]]); z = &(ol[ovlp_id(*p)]); + err = extract_sub_cigar_err_rr(z, s, e, p); + assert(err >= 0); + if(err < msc) { + msc = err; msc_k = k; msc_n = 1; + } else if(err == msc) { + msc_n++; + } + buf->a[k] |= (((uint64_t)err)<<32); + } + + if(msc_n == 1) { + p = &(c_idx[(uint32_t)buf->a[msc_k]]); + z = &(ol[ovlp_id(*p)]); mn = 1; + if(msc_k != 0) { + m = buf->a[msc_k]; + buf->a[msc_k] = buf->a[0]; + buf->a[0] = m; + } + } else { + for (k = mn = 0; k < buf_n && (int64_t)mn < msc_n; k++) { + p = &(c_idx[(uint32_t)buf->a[k]]); + z = &(ol[ovlp_id(*p)]); + if((buf->a[k]>>32) == (uint64_t)msc) { + if(mn != k) { + m = buf->a[k]; + buf->a[k] = buf->a[mn]; + buf->a[mn] = m; + } + mn++; + } + } + } + // fprintf(stderr, "[M::%s] buf_n::%ld, msc_n::%ld, mn::%lu\n", __func__, buf_n, msc_n, mn); + for (k = 0; k < buf_n; k++) { + oid = ovlp_id((c_idx[(uint32_t)buf->a[k]])); + buf->a[k] >>= 32; buf->a[k] <<= 32; buf->a[k] |= oid; + // ol[oid].overlapLen = k;//no need to set + // if(s == 158482) fprintf(stderr, "k->%ld::oid->%ld[M::%s::utg%.6dl] pos::[%lu, %lu)\n", k, oid, __func__, + // (int32_t)ol[oid].y_id+1, s, e); + } + + for (k = 0; k < mn; k++) {///best alignment + z = &(ol[id_get(buf->a[k])]); + // reassign_sec_err(ol, ovidx, buf, k); + // push_sec_aln(z, s, e, 0); + push_sec_aln_robust(z, s, e, 0); + buf->a[k] = id_get(buf->a[k]);///all equally best overlap pieces + } + if(!mk) { + for (k = mn; k < buf_n; k++) { + err = err_get(buf->a[k])-msc; + z = &(ol[id_get(buf->a[k])]); + push_sec_aln_robust(z, s, e, err); + } + } else { + if(mn > 1) radix_sort_bc64(buf->a, buf->a + mn); + for (k = mn; k < buf_n; k++) { + err = err_get(buf->a[k])-msc; + if(is_mask_ov(mk, buf->a, mn, id_get(buf->a[k]))) err = 0; + z = &(ol[id_get(buf->a[k])]); + push_sec_aln_robust(z, s, e, err); + } + } + } + + + if(rm_n) { + for (k = m = 0; k < id_n; k++) { + p = &(c_idx[id_a[k]]); + q[1] = ol[ovlp_id(*p)].w_list.a[ovlp_max_wid(*p)].x_end+1-ovlp_bd(*p); + if(q[1] < e) continue; + id_a[m++] = id_a[k]; + } + id_n = m; + } + return id_n; +} + +uint64_t hc_phase_robust_rr(overlap_region* ol, All_reads *rref, haplotype_evdience_alloc* hp, char* qstr, uint64_t ql, UC_Read* tu, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, ul_ov_t *c_idx, int64_t set_f, uint8_t occ_thres, uint64_t hpc_len, uint64_t h0_w) +{ + uint64_t k, q[2], rr = 0, os, oe; ul_ov_t *p; overlap_region *z; + for (k = 0; k < id_n; k++) { + p = &(c_idx[id_a[k]]); z = &(ol[ovlp_id(*p)]); + q[0] = z->w_list.a[ovlp_cur_wid(*p)].x_start+ovlp_bd(*p); + q[1] = z->w_list.a[ovlp_cur_wid(*p)].x_end+1-ovlp_bd(*p); + if(q[1] <= e) rr = 1; + os = MAX(q[0], s); oe = MIN(q[1], e); + if(oe > os) { + // if(is_dbg) fprintf(stderr, "[M::%s]\ttn::%u\t%c\to::[%lu,\t%lu)\n", __func__, z->y_id, "+-"[z->y_pos_strand], os, oe); + extract_sub_cigar_hc(z, rref, hp, qstr, ql, tu, os, oe, p, set_f, hp->flag + os - s, occ_thres, hpc_len, h0_w); + // extract_sub_cigar_hc_hpc(z, rref, hp, qstr, ql, tu, os, oe, p, set_f, hp->flag + os - s, occ_thres, hpc_len, h0_w); + } + } + return rr; +} + + +int64_t infer_rovlp(ul_ov_t *li, ul_ov_t *lj, uc_block_t *bi, uc_block_t *bj, All_reads *ridx, ma_ug_t *ug) +{ + int64_t in, is, ie, irev, iqs, iqe, jn, js, je, jrev, jqs, jqe, ir, jr, ts, te, max_s, min_e, s_shift, e_shift; + + if(li) { + in = ug?ug->u.a[li->tn].len:Get_READ_LENGTH(R_INF, li->tn); + is = li->ts; ie = li->te; irev = li->rev; iqs = li->qs; iqe = li->qe; + } else if(bi) { + in = ug?ug->u.a[bi->hid].len:Get_READ_LENGTH(R_INF, bi->hid); + is = bi->ts; ie = bi->te; irev = bi->rev; iqs = bi->qs; iqe = bi->qe; + } else { + return 0; + } + + if(lj) { + jn = ug?ug->u.a[lj->tn].len:Get_READ_LENGTH(R_INF, lj->tn); + js = lj->ts; je = lj->te; jrev = lj->rev; jqs = lj->qs; jqe = lj->qe; + } else if(bj) { + jn = ug?ug->u.a[bj->hid].len:Get_READ_LENGTH(R_INF, bj->hid); + js = bj->ts; je = bj->te; jrev = bj->rev; jqs = bj->qs; jqe = bj->qe; + } else { + return 0; + } + + max_s = MAX(iqs, jqs); min_e = MIN(iqe, jqe); + if(min_e <= max_s) return 0; + s_shift = get_offset_adjust(max_s - iqs, iqe-iqs, ie-is); + e_shift = get_offset_adjust(iqe - min_e, iqe-iqs, ie-is); + if(irev) { + ts = s_shift; s_shift = e_shift; e_shift = ts; + } + is += s_shift; ie-= e_shift; + + // if(li && lj && li->tn == 324 && lj->tn == 319 && li->qs == 63841) { + // fprintf(stderr, "+++in:%ld, is:%ld, ie:%ld, irev:%ld, jn:%ld, js:%ld, je:%ld, jrev:%ld\n", in, is, ie, irev, jn, js, je, jrev); + // } + + s_shift = get_offset_adjust(max_s - jqs, jqe-jqs, je-js); + e_shift = get_offset_adjust(jqe - min_e, jqe-jqs, je-js); + if(jrev) { + ts = s_shift; s_shift = e_shift; e_shift = ts; + } + js += s_shift; je-= e_shift; + + if(irev) { + ts = in - ie; te = in - is; + is = ts; ie = te; + } + + if(jrev) { + ts = jn - je; te = jn - js; + js = ts; je = te; + } + + // if(li && lj && li->tn == 324 && lj->tn == 319 && li->qs == 63841) { + // fprintf(stderr, "---in:%ld, is:%ld, ie:%ld, irev:%ld, jn:%ld, js:%ld, je:%ld, jrev:%ld\n", in, is, ie, irev, jn, js, je, jrev); + // } + + if(is <= js) { + js -= is; is = 0; + } else { + is -= js; js = 0; + } + + ir = in - ie; jr = jn - je; + + if(ir <= jr){ + ie = in; je += ir; + } + else { + je = jn; ie += jr; + } + + ir = ie - is; jr = je - js; + return MAX(ir, jr); +} + +void convert_ul_ov_t(ul_ov_t *des, overlap_region *src, ma_ug_t *ug) +{ + des->qn = (uint32_t)-1; des->qs = src->x_pos_s; des->qe = src->x_pos_e+1; + des->tn = src->y_id; des->el = 1; des->rev = src->y_pos_strand; + des->sec = src->non_homopolymer_errors; + if(des->rev) { + des->ts = ug->u.a[des->tn].len - (src->y_pos_e+1); + des->te = ug->u.a[des->tn].len - src->y_pos_s; + } else { + des->ts = src->y_pos_s; + des->te = src->y_pos_e+1; + } +} + +uint64_t check_connect_ug(const ul_idx_t *uref, uint32_t v, uint32_t w, int64_t bw, double diff_ec_ul, int64_t dq) +{ + const asg_t *g = uref?uref->ug->g:NULL; int64_t dt = -1; + uint32_t nv = asg_arc_n(g, v), i; asg_arc_t *av = asg_arc_a(g, v); + for (i = 0; i < nv; i++) { + if(av[i].del || av[i].v != w) continue; + dt = av[i].ol; + break; + } + if(dt < 0) return 0; + int64_t diff = (dq>dt? dq-dt:dt-dq), mm = MAX(dq, dt); + mm *= diff_ec_ul; if(mm < bw) mm = bw; + if(diff <= mm) return 1; + return 0; +} + +uint64_t check_connect_rg(const ul_idx_t *uref, const ug_opt_t *uopt, uint32_t uv, uint32_t uw, int64_t bw, double diff_ec_ul, int64_t dq) +{ + int64_t dt = -1; + if(uref->ug->u.a[uv>>1].circ || uref->ug->u.a[uw>>1].circ) return 0; + uint32_t rv = (uref->ug->u.a[uv>>1].a[(uv&1)?(0):(uref->ug->u.a[uv>>1].n-1)]>>32)^(uv&1); + uint32_t rw = (uref->ug->u.a[uw>>1].a[(uw&1)?(uref->ug->u.a[uw>>1].n-1):(0)]>>32)^(uw&1); + ma_hit_t_alloc* src = uopt->sources; + int64_t min_ovlp = uopt->min_ovlp; + int64_t max_hang = uopt->max_hang; + uint64_t z, qn, tn, x = rv>>1; int32_t r = 1; asg_arc_t e; + for (z = 0; z < src[x].length; z++) { + qn = Get_qn(src[x].buffer[z]); tn = Get_tn(src[x].buffer[z]); + if(tn != (rw>>1)) continue; + r = ma_hit2arc(&(src[x].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); + if(r < 0) continue; + if((e.ul>>32) != rv || e.v != rw) continue; + dt = e.ol; + break; + } + if(dt < 0) return 0; + int64_t diff = (dq>dt? dq-dt:dt-dq), mm = MAX(dq, dt); + mm *= diff_ec_ul; if(mm < bw) mm = bw; + if(diff <= mm) return 1; + return 0; +} + +uint32_t govlp_check(const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, ul_ov_t *li, ul_ov_t *lj) +{ + int64_t qo = infer_rovlp(li, lj, NULL, NULL, /**ridx**/NULL, uref->ug); ///overlap length in query (UL read) + + // fprintf(stderr, "+++[M::%s::utg%.6dl->utg%.6dl] qo::%ld\n", __func__, (int32_t)li->tn+1, (int32_t)lj->tn+1, qo); + if(check_connect_ug(uref, ((li->tn<<1)|li->rev)^1, ((lj->tn<<1)|lj->rev)^1, bw, diff_ec_ul, qo)) return 1; + // fprintf(stderr, "[M::%s::] check_connect_ug fail\n", __func__); + if(check_connect_rg(uref, uopt, ((li->tn<<1)|li->rev)^1, ((lj->tn<<1)|lj->rev)^1, bw, diff_ec_ul, qo)) return 1; + // fprintf(stderr, "[M::%s::] check_connect_rg fail\n", __func__); + return 0; +} + +void gen_gov_idx(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, asg64_v* idx) +{ + int64_t on = ol->length, k, i; uint64_t os, oe, ovlp; ul_ov_t p, q, *li, *lj; + kv_resize(uint64_t, *idx, (uint64_t)on); memset(idx->a, 0, sizeof(*(idx->a))*on); + for (k = 0, idx->n = on; k < on; k++) { + convert_ul_ov_t(&p, &(ol->list[k]), uref->ug); p.qn = k; + // idx->a[k] = idx->n; idx->a[k] <<= 32; + for (i = on - 1; i >= 0 && i > k && ol->list[i].x_pos_e >= ol->list[k].x_pos_s; i--) { + // if(k >= i) continue; + convert_ul_ov_t(&q, &(ol->list[i]), uref->ug); q.qn = i; + + if(p.qe > q.qe) li = &p, lj = &q; + else if(p.qe == q.qe && p.qs >= q.qs) li = &p, lj = &q; + else lj = &p, li = &q; + os = MAX(li->qs, lj->qs), oe = MIN(li->qe, lj->qe); + ovlp = ((oe > os)? (oe - os):0); + if(!ovlp) continue;//no overlap + + if(lj->qs <= li->qs+G_CHAIN_INDEL) { + if(govlp_check(uref, uopt, bw, diff_ec_ul, li, lj)) { + idx->a[k]++; idx->a[i]++; + kv_push(uint64_t, *idx, (((uint64_t)k)<<32)|((uint64_t)i)); + kv_push(uint64_t, *idx, (((uint64_t)i)<<32)|((uint64_t)k)); + } + } else if((lj->qe+G_CHAIN_INDEL>=li->qe) && (lj->qs+G_CHAIN_INDEL>=li->qs)) { + if(govlp_check(uref, uopt, bw, diff_ec_ul, lj, li)) { + idx->a[k]++; idx->a[i]++; + kv_push(uint64_t, *idx, (((uint64_t)k)<<32)|((uint64_t)i)); + kv_push(uint64_t, *idx, (((uint64_t)i)<<32)|((uint64_t)k)); + } + } + } + } + radix_sort_bc64(idx->a + on, idx->a + idx->n); + for (k = 0, os = oe = on; k < on; k++) { + oe = os + idx->a[k]; + idx->a[k] = (os<<32)|oe; + os = oe; + } + + // for (k = 0; k < on; k++) { + // int64_t s, e; + // s = idx->a[k]>>32; e = (uint32_t)idx->a[k]; + // for (i = s; i < e; i++) { + // assert((idx->a[i]>>32) == (uint32_t)k); + // fprintf(stderr, "k::%ld[M::%s::utg%.6dl] utg%.6dl\n", k, __func__, + // (int32_t)ol->list[k].y_id+1, (int32_t)ol->list[(uint32_t)idx->a[i]].y_id+1); + // } + // } +} + +void prt_overlap_region_stat(overlap_region *z, int64_t sid) +{ + uint64_t k = 0, aln = 0, ualn = 0, err = 0; + for (k = 0; k < z->w_list.n; k++) { + if(is_ualn_win(z->w_list.a[k])) { + ualn += z->w_list.a[k].x_end+1-z->w_list.a[k].x_start; + } else { + aln += z->w_list.a[k].x_end+1-z->w_list.a[k].x_start; + err += z->w_list.a[k].error; + } + } + fprintf(stderr, "[M::%s::utg%.6dl::%c] sid::%ld, q::[%d, %d), t::[%d, %d), aln::%lu, ualn::%lu, err::%lu\n", + __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], sid, z->x_pos_s, z->x_pos_e+1, + z->y_pos_s, z->y_pos_e+1, aln, ualn, err); + +} + + +void prt_overlap_region_phase_stat(overlap_region *z, int64_t sid) +{ + uint64_t k = 0; + fprintf(stderr, "[M::%s::utg%.6dl::%c] sid::%ld, q::[%d, %d), t::[%d, %d)\n", __func__, + (int32_t)z->y_id+1, "+-"[z->y_pos_strand], sid, z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1); + for (k = 0; k < z->w_list.n; k++) { + fprintf(stderr, "[k::%lu] sid::%ld, q::[%d, %d), sec::%u\n", k, sid, + z->w_list.a[k].x_start, z->w_list.a[k].x_end, z->w_list.a[k].clen); + } +} + +void region_phase(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, asg64_v* buf1, int64_t ulid) +{ + int64_t on = ol->length, k, i, zwn, q[2], t[2], w[2]; + uint64_t m; overlap_region *z; ul_ov_t *cp; + kv_resize(uint64_t, *idx, (ol->length<<1)); + kv_resize(ul_ov_t, *c_idx, ol->length); + for (k = idx->n = c_idx->n = 0; k < on; k++) { + z = &(ol->list[k]); zwn = z->w_list.n; + // prt_overlap_region_stat(z, ulid); + // if(/**ulid == 35437 &&**/ z->y_id == 15199 || z->y_id == 31315) { + // fprintf(stderr, "+0+[M::%s::utg%.6dl::%c] ulid::%ld, all::%u, non-best::%ld, best::%u\n", __func__, + // (int32_t)z->y_id+1, "+-"[z->y_pos_strand], ulid, z->overlapLen, zwn, z->align_length); + // prt_overlap_region_stat(&(ol->list[k]), ulid); + // // prt_overlap_region_phase_stat(&(ol->list[k]), ulid); + // } + // z->align_length = z->overlapLen = z->x_pos_e+1-z->x_pos_s; + z->align_length = 0; z->overlapLen = (uint32_t)-1; + z->non_homopolymer_errors = 0; + if(!zwn) continue; + q[0] = q[1] = t[0] = t[1] = w[0] = w[1] = INT32_MIN; + for (i = 0; i < zwn; i++) { + if((z->w_list.a[i].x_start==(q[1]+1)) && ((z->w_list.a[i].y_start==(t[1]+1)))) { + q[1] = z->w_list.a[i].x_end; + t[1] = z->w_list.a[i].y_end; + w[1] = i; + } else { + if(q[0] != INT32_MIN) { + m = ((uint64_t)q[0])<<1; m <<= 32; + m += c_idx->n; kv_push(uint64_t, *idx, m); + m = (((uint64_t)q[1])<<1)+1; m <<= 32; + m += c_idx->n; kv_push(uint64_t, *idx, m); + + kv_pushp(ul_ov_t, *c_idx, &cp); + ovlp_id(*cp) = k; ///ovlp id + ovlp_min_wid(*cp) = w[0]; ///beg id of windows + ovlp_max_wid(*cp) = w[1]; ///end id of windows + ovlp_cur_wid(*cp) = w[0]; ///cur id of windows + ovlp_cur_xoff(*cp) = z->w_list.a[w[0]].x_start; ///cur xpos + ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window + ovlp_bd(*cp) = 0; + } + + q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; + t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end; + w[0] = i; w[1] = i; + } + } + if(q[0] != INT32_MIN) { + m = ((uint64_t)q[0])<<1; m <<= 32; + m += c_idx->n; kv_push(uint64_t, *idx, m); + m = (((uint64_t)q[1])<<1)+1; m <<= 32; + m += c_idx->n; kv_push(uint64_t, *idx, m); + + kv_pushp(ul_ov_t, *c_idx, &cp); + ovlp_id(*cp) = k; ///ovlp id + ovlp_min_wid(*cp) = w[0]; ///beg id of windows + ovlp_max_wid(*cp) = w[1]; ///end id of windows + ovlp_cur_wid(*cp) = w[0]; ///cur id of windows + ovlp_cur_xoff(*cp) = z->w_list.a[w[0]].x_start; ///cur xpos + ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window + ovlp_bd(*cp) = 0; + } + // if(ulid == 35437 && z->y_id == 109111) { + // fprintf(stderr, "+1+[M::%s::utg%.6dl::%c] ulid::%ld, all::%u, non-best::%ld, best::%u\n", __func__, + // (int32_t)z->y_id+1, "+-"[z->y_pos_strand], ulid, z->overlapLen, zwn, z->align_length); + // prt_overlap_region_stat(&(ol->list[k])); + // prt_overlap_region_phase_stat(&(ol->list[k])); + // } + } + radix_sort_bc64(idx->a, idx->a+idx->n); + //this is used with gen_region_phase, now give up + //gen_gov_idx(ol, uref, uopt, G_CHAIN_BW, N_GCHAIN_RATE, buf1); + // for (m = 0; m < c_idx->n; m++) { + // fprintf(stderr, "+++[M::%s::utg%.6dl] q[%d, %d), t[%d, %d), wn::%d\n", __func__, + // (int32_t)ol->list[ovlp_id(c_idx->a[m])].y_id+1, + // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_min_wid(c_idx->a[m])].x_start, + // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_max_wid(c_idx->a[m])].x_end+1, + // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_min_wid(c_idx->a[m])].y_start, + // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_max_wid(c_idx->a[m])].y_end+1, + // ovlp_max_wid(c_idx->a[m])+1-ovlp_min_wid(c_idx->a[m])); + // } + + + int64_t srt_n = idx->n, dp, old_dp, beg, end; + for (i = k = 0, dp = old_dp = 0, beg = 0, end = -1; i < srt_n; ++i) {///[beg, end) but coordinates in idx is [, ] + ///if idx->a.a[] is qe + old_dp = dp; + if ((idx->a[i]>>32)&1) { + --dp; end = (idx->a[i]>>33)+1; + }else { + //meet a new overlap; the overlaps are pushed by the x_pos_s + ++dp; end = (idx->a[i]>>33); + kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); + } + // fprintf(stderr, "\n[M::%s::] beg::%ld, end::%ld, old_dp::%ld\n", __func__, beg, end, old_dp); + if((end > beg) && (old_dp >= 2)) { + // fprintf(stderr, "\n[M::%s::] beg::%ld, end::%ld, old_dp::%ld\n", __func__, beg, end, old_dp); + // kv_resize(uint64_t, *buf, ((uint32_t)old_dp)<<1); + // idx->n = srt_n + gen_region_phase(ol->list, idx->a+srt_n, idx->n-srt_n, beg, end, old_dp, c_idx->a, buf, buf1); + idx->n = srt_n + gen_region_phase_robust(ol->list, idx->a+srt_n, idx->n-srt_n, beg, end, old_dp, c_idx->a, buf); + } + beg = end; + } + ///hap->length + + for (k = 0; k < on; k++) { + z = &(ol->list[k]); + // if(ulid == 35437 && z->y_id == 109111) { + // fprintf(stderr, "+2+[M::%s::utg%.6dl::%c] ulid::%ld, all::%u, non-best::%ld, best::%u\n", __func__, + // (int32_t)z->y_id+1, "+-"[z->y_pos_strand], ulid, z->overlapLen, zwn, z->align_length); + // prt_overlap_region_stat(&(ol->list[k])); + // prt_overlap_region_phase_stat(&(ol->list[k])); + // } + + + + z->overlapLen = z->x_pos_e+1-z->x_pos_s; + z->non_homopolymer_errors = 0; zwn = 0; + for (i = m = 0; i < z->align_length; i++) { + z->w_list.a[m] = z->w_list.a[z->w_list.n+i]; + if(z->w_list.a[m].clen > 0) { + z->non_homopolymer_errors += z->w_list.a[m].clen; + zwn += z->w_list.a[m].x_end-z->w_list.a[m].x_start; + } + m++; + } + z->w_list.n = m; + // if(ulid == 35437 && z->y_id == 109111/**zwn > z->overlapLen**/) { + // fprintf(stderr, "+3+[M::%s::utg%.6dl::%c] ulid::%ld, all::%u, non-best::%ld, best::%u\n", __func__, + // (int32_t)z->y_id+1, "+-"[z->y_pos_strand], ulid, z->overlapLen, zwn, z->align_length); + // prt_overlap_region_stat(&(ol->list[k])); + // prt_overlap_region_phase_stat(&(ol->list[k])); + // } + assert(zwn <= z->overlapLen); + z->align_length = z->overlapLen - zwn; + // /**if(ulid == 35437 && z->y_id == 15199 || z->y_id == 31315)**/ { + // prt_overlap_region_phase_stat(z, ulid); + // fprintf(stderr, "[M::%s::utg%.6dl::%c] all::%u, non-best::%ld, best::%u\n\n", __func__, + // (int32_t)z->y_id+1, "+-"[z->y_pos_strand], z->overlapLen, zwn, z->align_length); + // } + // prt_overlap_region_phase_stat(&(ol->list[k])); + // z = &(ol->list[k]); + // if(z->align_length == z->overlapLen) {///prefer alignments without any trans hit + // z->align_length = z->overlapLen = z->x_pos_e+1-z->x_pos_s; + // } + } +} + + +void rphase_rr(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, int64_t ulid, int64_t bd, mask_ul_ov_t *mk) +{ + int64_t on = ol->length, k, i, zwn, q[2], t[2], w[2]; + uint64_t m; overlap_region *z; ul_ov_t *cp; + kv_resize(uint64_t, *idx, (ol->length<<1)); + kv_resize(ul_ov_t, *c_idx, ol->length); + for (k = idx->n = c_idx->n = 0; k < on; k++) { + z = &(ol->list[k]); zwn = z->w_list.n; + z->align_length = 0; z->overlapLen = (uint32_t)-1; + z->non_homopolymer_errors = 0; + if(!zwn) continue; + q[0] = q[1] = t[0] = t[1] = w[0] = w[1] = INT32_MIN; + for (i = 0; i < zwn; i++) { + if((z->w_list.a[i].x_start==(q[1]+1)) && ((z->w_list.a[i].y_start==(t[1]+1)))) { + q[1] = z->w_list.a[i].x_end; + t[1] = z->w_list.a[i].y_end; + w[1] = i; + } else { + if(q[0] != INT32_MIN) { + q[0] += bd; q[1] -= bd; + if(q[1] >= q[0]) { + m = ((uint64_t)q[0])<<1; m <<= 32; + m += c_idx->n; kv_push(uint64_t, *idx, m); + m = (((uint64_t)q[1])<<1)+1; m <<= 32; + m += c_idx->n; kv_push(uint64_t, *idx, m); + + kv_pushp(ul_ov_t, *c_idx, &cp); + ovlp_id(*cp) = k; ///ovlp id + ovlp_min_wid(*cp) = w[0]; ///beg id of windows + ovlp_max_wid(*cp) = w[1]; ///end id of windows + ovlp_cur_wid(*cp) = w[0]; ///cur id of windows + ovlp_cur_xoff(*cp) = z->w_list.a[w[0]].x_start; ///cur xpos + ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window + ovlp_bd(*cp) = bd; + } + } + + q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; + t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end; + w[0] = i; w[1] = i; + } + } + if(q[0] != INT32_MIN) { + q[0] += bd; q[1] -= bd; + if(q[1] >= q[0]) { + m = ((uint64_t)q[0])<<1; m <<= 32; + m += c_idx->n; kv_push(uint64_t, *idx, m); + m = (((uint64_t)q[1])<<1)+1; m <<= 32; + m += c_idx->n; kv_push(uint64_t, *idx, m); + + kv_pushp(ul_ov_t, *c_idx, &cp); + ovlp_id(*cp) = k; ///ovlp id + ovlp_min_wid(*cp) = w[0]; ///beg id of windows + ovlp_max_wid(*cp) = w[1]; ///end id of windows + ovlp_cur_wid(*cp) = w[0]; ///cur id of windows + ovlp_cur_xoff(*cp) = z->w_list.a[w[0]].x_start; ///cur xpos + ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window + ovlp_bd(*cp) = bd; + } + } + } + radix_sort_bc64(idx->a, idx->a+idx->n); + + int64_t srt_n = idx->n, dp, old_dp, beg, end; + for (i = k = 0, dp = old_dp = 0, beg = 0, end = -1; i < srt_n; ++i) {///[beg, end) but coordinates in idx is [, ] + ///if idx->a.a[] is qe + old_dp = dp; + if ((idx->a[i]>>32)&1) { + --dp; end = (idx->a[i]>>33)+1; + }else { + //meet a new overlap; the overlaps are pushed by the x_pos_s + ++dp; end = (idx->a[i]>>33); + kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); + } + if((end > beg) && (old_dp >= 2)) { + idx->n = srt_n + gen_region_phase_robust_rr(ol->list, idx->a+srt_n, idx->n-srt_n, beg, end, old_dp, c_idx->a, buf, mk); + } + beg = end; + } +} + +void debug_inter(overlap_region_alloc* ol, kv_ul_ov_t *c_idx, uint64_t *idx, int64_t idx_n, uint64_t *res, int64_t res_n, int64_t s, int64_t e) +{ + ul_ov_t *cp; int64_t q[2], a_n = 0, i, k = 0, os, oe; + for (i = 0; i < idx_n; i++) { + cp = &(c_idx->a[(uint32_t)idx[i]]); + q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); + q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + os = MAX(q[0], s); oe = MIN(q[1], e); + if(oe > os) { + a_n++; assert(((uint32_t)idx[i]) == res[k++]); + } + } + // if(a_n != res_n) { + // fprintf(stderr, "[M::%s] a_n::%ld\tres_n::%ld\ts::%ld\te::%ld\n", __func__, a_n, res_n, s, e); + // } + assert(a_n == res_n); +} + +void debug_snp_site(overlap_region* ol, All_reads *rref, UC_Read *qu, haplotype_evdience *a, int64_t a_n) +{ + int64_t k; char ystr; + for (k = 0; k < a_n; k++) { + recover_UC_Read_sub_region(&ystr, a[k].overlapSite, 1, ol[a[k].overlapID].y_pos_strand, rref, ol[a[k].overlapID].y_id); + // if(a[k].misBase == ystr) fprintf(stderr, "[M::%s] misBase::%c\tystr::%c\n", __func__, a[k].misBase, ystr); + assert(a[k].misBase == ystr); + if(a[k].type == 0) { + assert(qu->seq[a[k].site] == ystr); + } else { + assert(qu->seq[a[k].site] != ystr); + } + } + +} + +///ol_r = 0.500001; ol_w = 3; err_dif = 0.25; c_sz = 3 +double cal_lindel_dd(ul_ov_t *a, ul_ov_t *b, double ol_r, uint64_t ol_w, double err_dif, uint64_t c_sz) +{ + if(a->tn == b->tn) return -1; + uint64_t os, oe, ol; int64_t ea, eb, ed; + os = MAX(a->qs, b->qs); oe = MIN(a->qe, b->qe); + if(oe <= os + ol_w) return -1; + ol = oe - os; + // if((ol < ((a->qe - a->qs)*ol_r)) || (ol < ((b->qe - b->qs)*ol_r))) return -1; + if((ol < ((a->qe - a->qs)*ol_r)) && (ol < ((b->qe - b->qs)*ol_r))) return -1; + + ea = a->qn; eb = b->qn; + ed = ((ea >= eb)?(ea - eb):(eb - ea)); + if((ed > (ea * err_dif)) || (ed > (eb * err_dif))) return -1; + + double sc; + sc = ((double)(ea - ed + eb - ed))/((double)(ea + eb)); + sc += ((double)(ol + ol)) / ((double)(a->qe - a->qs + b->qe - b->qs)); + return sc; +} + +inline uint64_t set_cgid(ul_ov_t *z, uint64_t *ia, uint64_t *iak, uint64_t ian, uint64_t *ca, uint64_t ci, overlap_region *oa, int64_t *gni) +{ + assert(ca[z->tn] <= 1); + if(z->ts != ((uint32_t)-1)) return 0; + if(ca[z->tn] != 0) { + // fprintf(stderr, "+[M::%s] sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\tca[z->tn]::%lu\n", __func__, z->sec, oa[z->tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa[z->tn].y_id), Get_NAME(R_INF, oa[z->tn].y_id), z->qs, z->qe, z->qn, ca[z->tn]); + return 0; + } + + z->ts = ci; ca[z->tn]++; + ia[(*iak)++] = z->tn; + assert((*iak) <= ian); + (*gni)++; + // fprintf(stderr, "-[M::%s] sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\tca[z->tn]::%lu\n", __func__, z->sec, oa[z->tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa[z->tn].y_id), Get_NAME(R_INF, oa[z->tn].y_id), z->qs, z->qe, z->qn, ca[z->tn]); + + return 1; +} + +///need to print some examples for double check +uint64_t is_get_group(ul_ov_t *a/**, uint64_t an, uint64_t rid**/, uint64_t *ga, uint64_t *ia, uint64_t gi, uint64_t tn) +{ + // fprintf(stderr, "+[M::%s] gi::%lu\n", __func__, gi); + uint64_t k = ga[gi]>>32; + // while ((k != ((uint64_t)-1)) && (a[k].tn != tn)) { + // fprintf(stderr, "+[M::%s] k::%lu\n", __func__, k); + // k = ia[k]; + // fprintf(stderr, "-[M::%s] k::%lu\n", __func__, k); + // } + for (k = ga[gi]>>32; (k != ((uint64_t)-1)) && (a[k].tn != tn); k = ia[k]); + // if((k != ((uint32_t)-1)) && (k >= an)) { + // fprintf(stderr, "-[M::%s] rid::%lu, an::%lu, k::%lu\n", __func__, rid, an, k); + // } + if((k != ((uint64_t)-1)) && (a[k].tn == tn)) return 0; + return 1; +} + +///len_st = 0.500001; len_w = 3; err_dif = 0.25; c_sz = 3 +int64_t rphase_lidel_cc(overlap_region_alloc* oa, ul_ov_t *a, int64_t an, double len_st, uint64_t len_w, double err_dif, uint64_t c_sz, uint64_t rid, asg64_v *buf, asg64_v *idx) +{ + int64_t k, z, mk, gni; uint64_t ol, ck, v, *ia, *ca, iak, ii, ian; double sw, msw = -1; + kv_resize(uint64_t, *idx, (oa->length<<1)); + ia = idx->a; ian = oa->length; iak = 0; + ca = idx->a + oa->length; memset(ca, 0, sizeof((*ca))*oa->length); + + for (k = 0; k < an; k++) { + ol = (a[k].qe - a[k].qs) * len_st; if(ol < len_w) ol = len_w; + if((a[k].qe - a[k].qs) < ol) continue; + for (z = k + 1; (z < an) && (a[z].qs < a[k].qe); z++) { + if(cal_lindel_dd(&(a[k]), &(a[z]), len_st, len_w, err_dif, c_sz) >= 0) { + a[k].sec++; a[z].sec++; + // fprintf(stderr, "(0)[M::%s] k(%ld)sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\n", __func__, k, a[k].sec, oa->list[a[k].tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa->list[a[k].tn].y_id), Get_NAME(R_INF, oa->list[a[k].tn].y_id), a[k].qs, a[k].qe, a[k].qn); + // fprintf(stderr, "(1)[M::%s] z(%ld)sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\n", __func__, z, a[z].sec, oa->list[a[z].tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa->list[a[z].tn].y_id), Get_NAME(R_INF, oa->list[a[z].tn].y_id), a[z].qs, a[z].qe, a[z].qn); + } + } + } + + for (k = z = 0; k < an; k++) { + if(a[k].sec == 0) { + // fprintf(stderr, "#[M::%s] z::%ld, sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\tel::%u\n", __func__, z, a[k].sec, oa->list[a[k].tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa->list[a[k].tn].y_id), Get_NAME(R_INF, oa->list[a[k].tn].y_id), a[k].qs, a[k].qe, a[k].qn, a[k].el); + continue; + } + a[k].ts = a[k].te = ((uint32_t)-1);///cluster + // fprintf(stderr, "[M::%s] z::%ld, tn::%u, sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\n", __func__, z, a[k].tn, a[k].sec, oa->list[a[k].tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa->list[a[k].tn].y_id), Get_NAME(R_INF, oa->list[a[k].tn].y_id), a[k].qs, a[k].qe, a[k].qn); + a[z++] = a[k]; + } + an = z; + if(an == 0) return 0; + + // fprintf(stderr, "*0*[M::%s] rid::%lu, an::%ld\n", __func__, rid, an); + for (k = ck = buf->n = gni = 0; k < an; k++) { + if((a[k].sec < c_sz) || (a[k].ts != ((uint32_t)-1))) continue; + // fprintf(stderr, "\n[M::%s] k::%ld\tsec::%u\tcc::%u\tck::%lu\ttn::%u\n", __func__, k, a[k].sec, a[k].ts, ck, a[k].tn); + + buf->n = 0; kv_push(uint64_t, *buf, k); iak = 0; + while (buf->n) { + v = buf->a[--buf->n]; + ol = (a[v].qe - a[v].qs) * len_st; if(ol < len_w) ol = len_w; + if((a[v].qe - a[v].qs) < ol) continue; + + // fprintf(stderr, "*0*[M::%s] v::%lu\n", __func__, v); + if((set_cgid(&(a[v]), ia, &iak, ian, ca, ck, oa->list, &gni)) || (a[v].ts == ck)) { + // fprintf(stderr, "*1*[M::%s] v::%lu\n", __func__, v); + for (z = 0; (z < an) && (a[z].qs < a[v].qe); z++) { + // fprintf(stderr, "*0*[M::%s] a[z].tn::%u, a[z].sec::%u, c_sz::%lu, a[z].ts:%u, v::%lu, z::%ld\n", __func__, a[z].tn, a[z].sec, c_sz, a[z].ts, v, z); + if((a[z].sec < c_sz) || (a[z].ts != ((uint32_t)-1)) || (((int64_t)v) == z)) continue; + // fprintf(stderr, "*1*[M::%s] a[z].tn::%u\n", __func__, a[z].tn); + if((cal_lindel_dd(&(a[v]), &(a[z]), len_st, len_w, err_dif, c_sz) >= 0) && (set_cgid(&(a[z]), ia, &iak, ian, ca, ck, oa->list, &gni))) { + kv_push(uint64_t, *buf, z); + // fprintf(stderr, "*2*[M::%s] z::%ld, a[z].tn::%u\n", __func__, z, a[z].tn); + } + } + } + } + + for (ii = 0; ii < iak; ii++) ia[ii] = 0; + ck++; + } + + // for (k = 0; k < an; k++) { + // fprintf(stderr, "*0*[M::%s] z::%ld, tn::%u, sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\tgid::%u\n", __func__, k, a[k].tn, a[k].sec, oa->list[a[k].tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa->list[a[k].tn].y_id), Get_NAME(R_INF, oa->list[a[k].tn].y_id), a[k].qs, a[k].qe, a[k].qn, a[k].ts); + // } + // fprintf(stderr, "*1*[M::%s] rid::%lu, an::%ld, ck::%lu\n", __func__, rid, an, ck); + if(ck <= 0 || gni <= 0) return 0; + + if(gni < an) { + ///build index for cluster + buf->n = an + ck; kv_resize(uint64_t, *buf, buf->n); + memset(buf->a, -1, sizeof((*(buf->a)))*buf->n); + ca = buf->a; ia = buf->a + ck; + for (k = 0; k < an; k++) { + if(a[k].ts == ((uint32_t)-1)) continue; + if(ca[a[k].ts] != ((uint64_t)-1)) { + ///set the previous one + assert(ia[((uint32_t)ca[a[k].ts])] == ((uint64_t)-1)); + ia[((uint32_t)ca[a[k].ts])] = k; + ca[a[k].ts] >>= 32; ca[a[k].ts] <<= 32; ca[a[k].ts] |= k; + } else { + ca[a[k].ts] = k; ca[a[k].ts] <<= 32; ca[a[k].ts] |= ((uint64_t)k); + } + } + + + for (k = ck = 0; k < an; k++) { + if(a[k].ts != ((uint32_t)-1)) { + ck++; continue; + } + ol = (a[k].qe - a[k].qs) * len_st; if(ol < len_w) ol = len_w; + if((a[k].qe - a[k].qs) < ol) continue; + mk = -1; msw = -1; + for (z = 0/**k + 1**/; (z < an) && (a[z].qs < a[k].qe); z++) { + if(a[z].sec < c_sz) continue; + if(a[z].ts == ((uint32_t)-1)) continue; + if(z == k) continue; + sw = cal_lindel_dd(&(a[k]), &(a[z]), len_st, len_w, err_dif, c_sz); + if(sw < 0) continue; + if((sw > msw) && (is_get_group(a, /**an, rid,**/ ca, ia, a[z].ts, a[k].tn))) { + mk = a[z].ts; msw = sw; + } + } + if(mk != -1) { + ck++; a[k].ts = mk; + ///set the previous one + assert(ia[((uint32_t)ca[a[k].ts])] == ((uint64_t)-1)); + ia[((uint32_t)ca[a[k].ts])] = k; + ca[a[k].ts] >>= 32; ca[a[k].ts] <<= 32; ca[a[k].ts] |= k; + } + } + } else { + ck = gni; + } + radix_sort_ul_ov_srt_ts1(a, a + an); + // for (k = 0; k < an; k++) { + // fprintf(stderr, "*1*[M::%s] z::%ld, tn::%u, sec::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\tgid::%u\n", __func__, k, a[k].tn, a[k].sec, oa->list[a[k].tn].y_id, (int)Get_NAME_LENGTH(R_INF, oa->list[a[k].tn].y_id), Get_NAME(R_INF, oa->list[a[k].tn].y_id), a[k].qs, a[k].qe, a[k].qn, a[k].ts); + // } + return ck; +} + +void push_idel_info(haplotype_evdience_alloc *h, uint64_t s, uint64_t e, uint64_t err, ul_ov_t *a, uint64_t an, ul_ov_t *a1, uint64_t an1, overlap_region *oa, uint64_t *idx, uint64_t idx_n, uint64_t rid, int64_t het_cov, int64_t hom_cov, int64_t n_hap, double cut_rate, int64_t cut_bd) +{ + // fprintf(stderr, "\n"); + uint64_t k, q[2], os, oe, /**hn = h->length,**/ bl0 = h->length; int64_t cc, occ0, occ1, occ2; ul_ov_t *p; overlap_region *z; haplotype_evdience ev; int64_t ec; SnpStats *ps = NULL; + for (k = occ0 = occ1 = occ2 = 0; k < idx_n; k++) { + p = &(a[idx[k]]); z = &(oa[ovlp_id(*p)]); + if(z->is_match != 1) continue; + + q[0] = z->w_list.a[ovlp_cur_wid(*p)].x_start+ovlp_bd(*p); + q[1] = z->w_list.a[ovlp_cur_wid(*p)].x_end+1-ovlp_bd(*p); + os = MAX(q[0], s); oe = MIN(q[1], e); + if((oe > os) && ((oe - os) >= ((e - s) - (oe - os)))) { + // fprintf(stderr, "[M::%s]\ts::%lu\n", __func__, s); + ec = extract_sub_err(z, s, e, os, oe, err, 0.2, p); + if(ec >= 0) { + occ0++; + ev.misBase = 0; + ev.overlapID = ovlp_id(*p); + ev.site = s; + ev.overlapSite = h->snp_stat.n; + ev.type = 0; + ev.cov = ec;///error + // fprintf(stderr, "+0+[M::%s]\th->length::%u\tsite::%u\toverlapSite::%u\n", __func__, h->length, ev.site, ev.overlapSite); + addHaplotypeEvdience(h, &ev, NULL); + } else { + occ2++; + } + } + } + + ///add sv + for (k = 0, occ1 = an1; k < an1; k++) { + ev.misBase = 0; + ev.overlapID = a1[k].tn; + ev.site = s; + ev.overlapSite = h->snp_stat.n; + ev.type = 1; + ev.cov = a1[k].qn;///error + // fprintf(stderr, "+1+[M::%s]\th->length::%u\tsite::%u\toverlapSite::%u\n", __func__, h->length, ev.site, ev.overlapSite); + addHaplotypeEvdience(h, &ev, NULL); + } + + // for (k = hn; k < h->length; k++) { + // z = &(oa[h->list[k].overlapID]); + // fprintf(stderr, "[M::%s]\t%.*s\tq::[%u, %u)\terr::%u\ttype::%u\n", __func__, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), h->list[k].site, h->list[k].overlapSite, h->list[k].cov, h->list[k].type); + // } + + ///for debug indel + // if(occ0 < 2 || occ1 < 2) { + // h->length = bl0; + // return; + // } + occ0++; + cc = ((het_cov > 0)?(het_cov):(hom_cov/n_hap)); cc *= cut_rate; if(cc < cut_bd) cc = cut_bd; + if(occ0 < cc || occ1 < cc) { + h->length = bl0; + return; + } + + kv_pushp(SnpStats, h->snp_stat, &ps); + ps->id = h->snp_stat.n-1; + ps->occ_0 = occ0; + ps->occ_1 = occ1; + ps->occ_2 = occ2; + ps->site = s; + ps->score = -1; + ps->overlap_num = 0; + ps->is_homopolymer = 0; + // fprintf(stderr, "-[M::%s]\trid::%lu\t%.*s\tq::[%lu,%lu)\terr::%lu\tocc0::%lu\tocc1::%lu\tocc2::%lu\n", __func__, rid, (int)Get_NAME_LENGTH(R_INF, rid), Get_NAME(R_INF, rid), s, e, err, 1 + occ0, occ1, occ2); +} + +void gen_ov_lidel_variant(kv_ul_ov_t *cz, overlap_region_alloc *ol, asg64_v *idx, int64_t bd) +{ + uint64_t cbn = cz->n, k, i, t, zwn, m; int64_t q[2]; overlap_region *z; ul_ov_t *cp; + for (k = idx->n = 0; k < ol->length; k++) { + z = &(ol->list[k]); zwn = z->w_list.n; + if((!zwn) || (z->is_match != 1)) continue; + for (i = 0; i < zwn; i++) { + if(is_ualn_win(z->w_list.a[i])) continue; + q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; + q[0] += bd; q[1] -= bd; + if(q[1] >= q[0]) { + m = ((uint64_t)q[0]); m <<= 32; + m += (cz->n - cbn); kv_push(uint64_t, *idx, m); + + kv_pushp(ul_ov_t, *cz, &cp); + ovlp_id(*cp) = k; ///ovlp id + ovlp_cur_wid(*cp) = i; ///cur id of windows + ovlp_cur_xoff(*cp) = z->w_list.a[i].x_start; ///cur xpos + ovlp_cur_yoff(*cp) = z->w_list.a[i].y_start; ///cur xpos + ovlp_cur_ylen(*cp) = 0; + ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window + ovlp_bd(*cp) = bd; + } + } + } + + radix_sort_bc64(idx->a, idx->a + idx->n); + for (k = 1, i = 0; k <= idx->n; k++) { + if (k == idx->n || (idx->a[k]>>32) != (idx->a[i]>>32)) { + if(k - i > 1) { + for (t = i; t < k; t++) { + cp = &(cz->a[cbn + ((uint32_t)idx->a[t])]); + m = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + m <<= 32; m += ((uint32_t)idx->a[t]); idx->a[t] = m; + } + radix_sort_bc64(idx->a + i, idx->a + k); + } + i = k; + } + } +} + + +uint64_t rcall_lidel_variant(kv_ul_ov_t *cz, overlap_region_alloc *ol, haplotype_evdience_alloc *hp, asg64_v *idx, asg64_v *idz, uint64_t rid) +{ + // fprintf(stderr, "-0-[M::%s] %.*s\tis_match::%u\n", __func__, (int)Get_NAME_LENGTH(R_INF, ol->list[48].y_id), Get_NAME(R_INF, ol->list[48].y_id), ol->list[48].is_match); + + uint64_t i, k, zi, zk, nec[2], p, pmm, pmn, bn0 = 0, *ia, in, sv_n = cz->n, svi_n = 0, ovn = 0, m, rm_n; /**overlap_region *z;**/ ul_ov_t ez, *cp; + hp->length = hp->snp_stat.n = idx->n = idz->n = 0; + ///for debug indel + // fprintf(stderr, "+[M::%s] sv_n::%lu\n", __func__, sv_n); + for (k = 1, i = 0; k <= sv_n; k++) { + // fprintf(stderr, "+[M::%s] i::%ld, k::%ld\n", __func__, i, k); + if (k == sv_n || (cz->a[k].ts) != (cz->a[i].ts)) { + ///calculate pos + for (zi = i, nec[0] = nec[1] = 0, idx->n = bn0, pmm = ((uint64_t)-1), pmn = 0; zi < k; zi++) { + // z = &(ol->list[cz->a[zi].tn]); + nec[cz->a[zi].el]++; + p = cz->a[zi].qs; p <<= 32; p |= ((uint64_t)cz->a[zi].qe); + kv_push(uint64_t, *idx, p); + if(pmm == ((uint64_t)-1)) pmm = p; + if(pmm == p) pmn++; + // fprintf(stderr, "[M::%s] cid::%u\trid::%u\t%.*s\tq::[%u,%u)\terr::%u\n", __func__, cz->a[zi].ts, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), cz->a[zi].qs, cz->a[zi].qe, cz->a[zi].qn); + } + if(nec[0] < nec[1]) { + ///calculate pos + if((pmn <= 0) || (pmn < (idx->n - bn0 - pmn))) { + ia = idx->a + bn0; in = idx->n - bn0; + if(k - i > 1) radix_sort_bc64(ia, ia + in); + for (zk = 1, zi = 0, pmm = ((uint64_t)-1), pmn = 0; zk <= in; zk++) { + if((zk == in) || (ia[zi] != ia[zk])) { + if((zk - zi) > pmn) { + pmn = zk - zi; pmm = ia[zi]; + } + zi = zk; + } + } + } + + ez.qs = pmm>>32; ez.qe = (uint32_t)pmm; ez.ts = i; ez.te = k; ez.qn = 0; ez.tn = cz->a[i].ts; + ///calculate error + for (zi = i, idx->n = bn0, pmm = ((uint64_t)-1), pmn = 0; zi < k; zi++) { + if((cz->a[zi].qs != ez.qs) || (cz->a[zi].qe != ez.qe)) continue; + kv_push(uint64_t, *idx, cz->a[zi].qn); + if(pmm == ((uint64_t)-1)) pmm = cz->a[zi].qn; + if(pmm == cz->a[zi].qn) pmn++; + } + if((pmn <= 0) || (pmn < (idx->n - bn0 - pmn))) { + ia = idx->a + bn0; in = idx->n - bn0; + if(k - i > 1) radix_sort_bc64(ia, ia + in); + for (zk = 1, zi = 0, pmm = ((uint64_t)-1), pmn = 0; zk <= in; zk++) { + if((zk == in) || (ia[zi] != ia[zk])) { + if((zk - zi) > pmn) { + pmn = zk - zi; pmm = ia[zi]; + } + zi = zk; + } + } + } + ez.qn = pmm; kv_push(ul_ov_t, *cz, ez); + + // fprintf(stderr, "-[M::%s] nec[0]::%ld, nec[1]::%ld, pa::[%u, %u), err::%u\n\n", __func__, nec[0], nec[1], ez.qs, ez.qe, ez.qn); + } + + i = k; + } + } + // fprintf(stderr, "-1-[M::%s] %.*s\tis_match::%u\n", __func__, (int)Get_NAME_LENGTH(R_INF, ol->list[48].y_id), Get_NAME(R_INF, ol->list[48].y_id), ol->list[48].is_match); + + svi_n = cz->n - sv_n; idx->n = 0; + gen_ov_lidel_variant(cz, ol, idx, 0); + ovn = cz->n - sv_n - svi_n; + // fprintf(stderr, "-2-[M::%s] %.*s\tis_match::%u\n", __func__, (int)Get_NAME_LENGTH(R_INF, ol->list[48].y_id), Get_NAME(R_INF, ol->list[48].y_id), ol->list[48].is_match); + // fprintf(stderr, "+[M::%s] sv_n::%lu, svi_n::%lu, ovn::%lu\n", __func__, sv_n, svi_n, ovn); + + ul_ov_t *sv = cz->a, *svi = cz->a + sv_n, *ov = cz->a + sv_n + svi_n; int64_t s, e, os, oe, q[2]; + radix_sort_ul_ov_srt_qs1(svi, svi + svi_n); + for (k = i = 0; k < svi_n; k++) { + // fprintf(stderr, "\n-3-[M::%s] %.*s\tis_match::%u\n", __func__, (int)Get_NAME_LENGTH(R_INF, ol->list[48].y_id), Get_NAME(R_INF, ol->list[48].y_id), ol->list[48].is_match); + ///label matched overlaps + s = svi[k].qs; e = svi[k].qe; + for (p = svi[k].ts; p < svi[k].te; p++) { + // z = &(ol->list[sv[p].tn]); + // fprintf(stderr, "+++[M::%s] cid::%lu\tccid::%lu\trid::%u\t%.*s\tq::[%ld,%ld)\terr::%u\n", __func__, k, p - svi[k].ts, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), s, e, sv[p].qn); + assert(sv[p].ts == svi[k].tn); + // if(!(ol->list[sv[p].tn].is_match == 1)) { + // fprintf(stderr, "+[M::%s] rid::%lu\toid::%u\tis_match::%u\n", __func__, rid, sv[p].tn, ol->list[sv[p].tn].is_match); + // fprintf(stderr, "[M::%s] cid::%lu\tccid::%lu\trid::%u\t%.*s\tq::[%ld,%ld)\terr::%u\n", __func__, k, p - svi[k].ts, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), s, e, sv[p].qn); + // } + assert(ol->list[sv[p].tn].is_match == 1); + ol->list[sv[p].tn].is_match = 2; + } + + ///filter out passed overlaps + for (m = rm_n = ovn; m < idx->n; m++) { + cp = &(ov[idx->a[m]]); + q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); + q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + if(q[1] <= s) continue; + idx->a[rm_n++] = idx->a[m]; + } + idx->n = rm_n; + + ///push new overlaps + for (; i < ovn; ++i) { + cp = &(ov[(uint32_t)idx->a[i]]); + q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); + q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + if(q[0] >= e) break; + os = MAX(q[0], s); oe = MIN(q[1], e); + if(oe > os) { + kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); + } + } + + push_idel_info(hp, s, e, svi[k].qn, ov, ovn, sv + svi[k].ts, svi[k].te - svi[k].ts, ol->list, idx->a + ovn, idx->n - ovn, rid, asm_opt.het_cov, asm_opt.hom_cov, asm_opt.polyploidy, 0.333333, 5); + + ///relabel matched overlaps + for (p = svi[k].ts; p < svi[k].te; p++) { + assert(ol->list[sv[p].tn].is_match == 2); + ol->list[sv[p].tn].is_match = 1; + } + // fprintf(stderr, "-4-[M::%s] %.*s\tis_match::%u\n", __func__, (int)Get_NAME_LENGTH(R_INF, ol->list[48].y_id), Get_NAME(R_INF, ol->list[48].y_id), ol->list[48].is_match); + } + + return hp->length; +} + +uint64_t rphase_lidel(overlap_region_alloc* ol, All_reads *rref, haplotype_evdience_alloc* hp, UC_Read *qu, UC_Read *tu, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, int64_t bd, int64_t wl, int64_t ql, uint8_t occ_thres, uint64_t rid, uint64_t hpc_len, uint64_t std_bs) +{ + hp->length = hp->snp_stat.n = 0; + int64_t on = ol->length, k, i, zwn, q[2], t[2]; + overlap_region *z; //ul_ov_t *cp; + for (k = idx->n = c_idx->n = 0; k < on; k++) { + z = &(ol->list[k]); zwn = z->w_list.n; + if((!zwn) || (z->is_match != 1)) continue; + for (i = 0; i < zwn; i++) { + if(is_ualn_win(z->w_list.a[i])) continue; + q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end + 1; + t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end + 1; + if(q[1] > q[0] && t[1] > t[0]) { + extract_sub_cigar_sv(z, k, i, rref, qu->seq, qu->length, tu, c_idx, 16, hpc_len, 2); + } + } + } + if(c_idx->n <= 0) return 0; + + idx->n = (c_idx->n<<1); + kv_resize(uint64_t, *idx, idx->n); on = c_idx->n; idx->n = 0; + radix_sort_ul_ov_srt_qs1(c_idx->a, c_idx->a + on); + for (k = 1, i = 0; k <= on; k++) { + if (k == on || (c_idx->a[k].qs) != (c_idx->a[i].qs)) { + if(k > i + k) radix_sort_ul_ov_srt_qe1(c_idx->a + i, c_idx->a + k); + i = k; + } + } + // fprintf(stderr, "-0-[M::%s]\n", __func__); + on = rphase_lidel_cc(ol, c_idx->a, on, 0.500001, 3, 0.25, 3, rid, buf, idx); + c_idx->n = on; + // fprintf(stderr, "-1-[M::%s]\n", __func__); + return rcall_lidel_variant(c_idx, ol, hp, idx, buf, rid); +} + +void dbg_cp_cov(overlap_region_alloc* ol, kv_ul_ov_t *c_idx, int64_t ps, int64_t ic) +{ + int64_t q[2], k, cn = c_idx->n, cov = 0; ul_ov_t *cp; + for (k = 0; k < cn; k++) { + cp = &(c_idx->a[k]); + q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); + q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + if(ps >= q[0] && ps < q[1]) cov++; + } + + if(ic != cov) { + fprintf(stderr, "[M::%s] ic::%ld\tcov::%ld\n", __func__, ic, cov); + } +} + +void gen_qvec_hvec(All_reads *rref, asg8_v *t, uint8_t **hf, uint8_t **qual, uint64_t rid, uint64_t tcut) +{ + uint64_t rl = Get_READ_LENGTH((*rref), rid); (*hf) = NULL; + if(qual) { + (*qual) = NULL; + // fprintf(stderr, "[M::%s] rl::%lu, t->n::%lu\n", __func__, rl, (uint64_t)t->n); + if(rl != t->n) { + t->n = 0; + kv_resize(uint8_t, *t, rl); (*qual) = t->a; + } else { + kv_resize(uint8_t, *t, (rl<<1)); + (*hf) = t->a; (*qual) = t->a + rl; + } + + if(rid < tcut) { + retrive_bqual(NULL, (*qual), rid, -1, -1, 0, sc_bn); + } else { + memset((*qual), 3, ((Get_READ_LENGTH(R_INF, rid))*sizeof((**qual)))); + } + } else { + if(rl == t->n) (*hf) = t->a; + } +} + + +void rphase_hc(overlap_region_alloc* ol, All_reads *rref, haplotype_evdience_alloc* hp, UC_Read* qu, UC_Read* tu, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, int64_t bd, int64_t wl, int64_t ql, uint8_t occ_thres/**, uint8_t is_dbg**/, uint64_t rid, uint64_t hpc_len, uint64_t std_bs, Chain_Data *dp, asg8_v *q8, asg8_v *t8, uint8_t lindel, uint64_t tcut, uint64_t site_sc, int64_t h0_w, asg32_v *b32) +{ + int64_t on = ol->length, k, i, zwn, q[2]/**, ndp, odp, ms, me, hfs, hfe, hfi**/; + uint64_t m, l0, wi, wl0, si, ei, fi; overlap_region *z; ul_ov_t *cp; uint8_t *qhf = NULL, *qual = NULL; + kv_resize(uint64_t, *idx, (ol->length)); + kv_resize(ul_ov_t, *c_idx, ol->length); + + for (k = idx->n = c_idx->n = 0; k < on; k++) { + z = &(ol->list[k]); zwn = z->w_list.n; + if(!zwn) continue; + for (i = 0; i < zwn; i++) { + if(is_ualn_win(z->w_list.a[i])) continue; + q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; + q[0] += bd; q[1] -= bd; + if(q[1] >= q[0]) { + m = ((uint64_t)q[0]); m <<= 32; + m += c_idx->n; kv_push(uint64_t, *idx, m); + + kv_pushp(ul_ov_t, *c_idx, &cp); + ovlp_id(*cp) = k; ///ovlp id + ovlp_cur_wid(*cp) = i; ///cur id of windows + ovlp_cur_xoff(*cp) = z->w_list.a[i].x_start; ///cur xpos + ovlp_cur_yoff(*cp) = z->w_list.a[i].y_start; ///cur xpos + ovlp_cur_ylen(*cp) = 0; + ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window + ovlp_bd(*cp) = bd; + } + } + } + + int64_t srt_n = idx->n, s, e, t, os, oe, rm_n, rr; i = 0; + radix_sort_bc64(idx->a, idx->a+idx->n); + for (k = 1, i = 0; k <= srt_n; k++) { + if (k == srt_n || (idx->a[k]>>32) != (idx->a[i]>>32)) { + if(k - i > 1) { + for (t = i; t < k; t++) { + cp = &(c_idx->a[(uint32_t)idx->a[t]]); + // s = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); + // assert(s == (int64_t)(idx->a[i]>>32)); + m = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + m <<= 32; m += ((uint32_t)idx->a[t]); idx->a[t] = m; + // fprintf(stderr, "[M::%s] s::%ld\tsi::%lu\n", __func__, s, (idx->a[i]>>32)); + } + radix_sort_bc64(idx->a + i, idx->a + k); + } + i = k; + } + } + + ResizeInitHaplotypeEvdience(hp); + i = 0; s = 0; e = wl; e = ((e<=ql)?e:ql); rr = 0; + for (; s < ql; ) { + if(rr) { + // rr = 0; + for (m = rm_n = srt_n; m < idx->n; m++) { + cp = &(c_idx->a[idx->a[m]]); + q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); + q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + os = MAX(q[0], s); oe = MIN(q[1], e); + if(oe > os) { + idx->a[rm_n++] = idx->a[m]; + // if(q[1] <= e) rr = 1; + } + } + idx->n = rm_n; + } + + for (; i < srt_n; ++i) { + cp = &(c_idx->a[(uint32_t)idx->a[i]]); + q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); + q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + if(q[0] >= e) break; + os = MAX(q[0], s); oe = MIN(q[1], e); + if(oe > os) { + kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); + // if(q[1] <= e) rr = 1; + } + } + + // fprintf(stderr, "[M::%s] s::%ld, e::%ld, srt_n::%ld, idx->n::%ld\n", __func__, s, e, srt_n, (int64_t)idx->n); + // debug_inter(ol, c_idx, idx->a, srt_n, idx->a + srt_n, idx->n - srt_n, s, e); + l0 = hp->length; + // if(is_dbg) fprintf(stderr, "-1-[M::%s]\ts::%ld\te::%ld\n", __func__, s, e); + rr = hc_phase_robust_rr(ol->list, rref, hp, qu->seq, qu->length, tu, idx->a + srt_n, idx->n - srt_n, s, e, c_idx->a, 1, occ_thres, hpc_len, h0_w); + for (wi = fi = ei = 0, si = ((uint64_t)-1), wl0 = e - s; wi < wl0; wi++) { + if(hp->flag[wi] > 0) { + if(hp->flag[wi] > occ_thres) { + fi = 1; hp->nn_snp++; hp->flag[wi] = 1; + if((hpc_len) && (hpc_mask_ff(qu->seq, qu->length, wi + s, hpc_len, HPC_RR, NULL, 0, 0, HPC_CC, NULL, NULL))) hp->flag[wi] = 3; + ei = wi + 1; if(si == ((uint64_t)-1)) si = wi; + } else { + hp->flag[wi] = 0; + } + } + } + + if(fi) { + // if(is_dbg) fprintf(stderr, "-2-[M::%s]\ts::%ld\te::%ld\n", __func__, s, e); + /** + wi = s; wl0 = ((hpc_len)?(e):(s)); + while (wi < wl0) { + if((hp->flag[wi-s]) && (hpc_mask_ff(qu->seq, qu->length, wi + s, hpc_len, HPC_RR, NULL, 0, 0, HPC_CC, &hfs, &hfe))) { + if(hfs < s) {hfs = s;} if(hfe > e) {hfe = e;} + for (hfi = hfs; hfi < hfe; hfi++) { + if(hp->flag[hfi-s]) hp->flag[hfi-s] |= 2; + } + hp->flag[wi-s] |= 2; wi++; + if(hfe > wi) wi = hfe; + } else { + wi++; + } + } + **/ + + rr = hc_phase_robust_rr(ol->list, rref, hp, qu->seq, qu->length, tu, idx->a + srt_n, idx->n - srt_n, s, e, c_idx->a, 0, occ_thres, hpc_len, h0_w); + if(hp->length > l0) radix_sort_haplotype_evdience_srt(hp->list + l0, hp->list + hp->length); + } + + if(ei > si) memset(hp->flag + si, 0, (ei-si)*sizeof((*(hp->flag)))); + // if(is_dbg) fprintf(stderr, "-3-[M::%s]\ts::%ld\te::%ld\n", __func__, s, e); + + s += wl; e += wl; e = ((e<=ql)?e:ql); + } + + // debug_snp_site(ol->list, rref, qu, hp->list, hp->length); + + /** + for (m = idx->n = 0; m < c_idx->n; m++) { + cp = &(c_idx->a[m]); + q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); + q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + kv_push(uint64_t, *idx, (((uint64_t)q[0])<<1)); + kv_push(uint64_t, *idx, ((((uint64_t)q[1])<<1)|1)); + } + radix_sort_bc64(idx->a, idx->a+idx->n); zwn = idx->n; + + for (i = 0, ndp = 0; i < zwn; ++i) { + odp = ndp; + if (idx->a[i]&1) --ndp; + else ++ndp; + + m = ((odp >= 0)?odp:0);///impossible to have odp < 0, just in case + idx->a[i]>>=1; idx->a[i]<<=32; idx->a[i] |= m; + } + **/ + + SetSnpMatrix(hp, &(hp->nn_snp), &(ol->length), 0, NULL); + srt_n = hp->length; z = (((std_bs)||(t8))?(ol->list):(NULL)); + for (k = 1, m = /**ms =**/ i = t = 0; k <= srt_n; ++k) { + if (k == srt_n || hp->list[k].site != hp->list[i].site) { + /** + for (odp = 0; m < idx->n; m++) { + me = idx->a[m]>>32; odp = (uint32_t)idx->a[m]; + if(hp->list[i].site >= ms && hp->list[i].site < me) break; + else if(hp->list[i].site < ms) break; + ms = me; + } + **/ + // if(m >= idx->n) then the region will be [ms, ql), odp = 0; + // dbg_cp_cov(ol, c_idx, hp->list[i].site, odp); + t += push_info(hp, hp->list+i, k-i, hp->list+t, z, t8, 0/**odp**/, sc_wn, tcut); + i = k; + } + } + hp->length = t; + + if(q8) gen_qvec_hvec(rref, q8, &qhf, ((dp)?(&qual):(NULL)), rid, tcut); + + //r829 + // if(qhf) recal_rphase(rref, hp, ol, qu, ((std_bs)?(0.05):(0)), ((std_bs)?(2):((uint64_t)-1)), dp, idx, buf, b32, rid, qual, tcut, site_sc); + + + if(!dp) { + // generate_haplotypes_naive_advance(hap, overlap_list, NULL); + generate_haplotypes_naive_HiFi(hp, ol, 0.04, qu, ((std_bs)?(0):(1)), ((std_bs)?(0.05):(0)), ((std_bs)?(2):((uint64_t)-1))); + // generate_haplotypes_DP(hap, overlap_list, R_INF, g_read->length, force_repeat); + // generate_haplotypes_naive(hap, overlap_list, R_INF, g_read->length, force_repeat); + } else { + // gen_rphase_dp(hp, ol, qu, ((std_bs)?(0.05):(0)), ((std_bs)?(2):((uint64_t)-1)), dp, idx, buf, rid, q8, tcut, site_sc); + gen_rphase_dp_adv(hp, ol, qu, ((std_bs)?(0.05):(0)), ((std_bs)?(2):((uint64_t)-1)), dp, idx, buf, rid, qual, tcut, site_sc); + // if(!site_sc) generate_haplotypes_naive_HiFi_adv(hp, ol, 0.04, qu, ((std_bs)?(0.05):(0)), ((std_bs)?(2):((uint64_t)-1)), b32, rid);//r835 + if(!site_sc) generate_haplotypes_naive_HiFi_adv_hc(hp, ol, 0.04, qu, ((std_bs)?(0.05):(0)), ((std_bs)?(2):((uint64_t)-1)), b32, rid);///r835 + else generate_haplotypes_weight(hp, ol, 0.04, qu, ((std_bs)?(0):(1)), ((std_bs)?(0.05):(0)), ((std_bs)?(2):((uint64_t)-1)), 32, 2); + } + + if(lindel) { + if(rphase_lidel(ol, rref, hp, qu, tu, c_idx, idx, buf, bd, wl, ql, occ_thres, rid, hpc_len, std_bs)) { + generate_haplotypes_sv(hp, ol, rid); + } + } +} + + +///ca[0, cn + 1); ca[cn] = 0; +void freq_ha_sketch(uint64_t *ca, int32_t cn, int32_t w, int32_t k, asg64_v *p) +{ + // uint64_t shift1 = k - 1, mask = (1ULL<n = 0; + memset(buf, 0xff, w * sizeof((*buf))); + ///memset(&tq, 0, sizeof(tiny_queue_t)); + ///len/w is the evaluated minimizer numbers + // kv_resize(uint64_t, *p, p->n + len/w); + // kv_resize_km(km, uint64_t, *mt, (int64_t)p->m); mt->n = p->n; + for (i = l = tl = buf_pos = max_pos = 0; i < cn; ++i) { + info = UINT32_MAX; + if(ca[i] > 0) { + ++l; tl++; info = ca[i]; info <<= 32; info |= ((uint64_t)i); + } else { + l = 0; ///tq.count = tq.front = 0; + } + buf[buf_pos] = info; ///need to do this here as appropriate buf_pos and buf[buf_pos] are needed below + // buf_p[buf_pos] = l; + // if (l == w + k - 1 && min.x != UINT64_MAX) { /**special case for the first window - because identical k-mers are not stored yet**/ + ///I have no idea if we should give l == w or l == w + 1 + if ((l == w) && (max != UINT32_MAX) && ((max>>32) >= (info>>32))) { /**special case for the first window - because identical k-mers are not stored yet**/ + for (j = buf_pos + 1; j < w; ++j){ + // if (sf##_mzcmp(&min, &buf[j]) == 0 && buf[j].pos != min.pos){ + if(((buf[j]>>32) == (max>>32)) && (((uint32_t)buf[j]) != ((uint32_t)max))) { + kv_push(uint64_t, *p, buf[j]); + } + } + for (j = 0; j < buf_pos; ++j){ + // if (sf##_mzcmp(&min, &buf[j]) == 0 && buf[j].pos != min.pos){ + if(((buf[j]>>32) == (max>>32)) && (((uint32_t)buf[j]) != ((uint32_t)max))) { + kv_push(uint64_t, *p, buf[j]); + } + } + } + + + /** + * There are three cases: + * 1. info.x <= min.x, means info is a new minimizer + * 2. info.x > min.x, info is not a new minimizer + * (1) buf_pos != min_pos, do nothing + * (2) buf_pos == min_pos, means current minimizer has moved outside the window + * **/ + if (((info>>32)) >= (max>>32)) { /**a new minimum; then write the old min**/ + // if (l >= w + k && min.x != UINT64_MAX){ + if ((l > w) && (max != UINT32_MAX)) { + kv_push(uint64_t, *p, max); + } + max = info, max_pos = buf_pos; ///max_s = buf_p[buf_pos]; + } else if (buf_pos == max_pos) { /**old min has moved outside the window**/ + // if (l >= w + k - 1 && min.x != UINT64_MAX){ + if((l >= w) && (max != UINT32_MAX)) { + kv_push(uint64_t, *p, max); + } + /**buf_pos == min_pos, means current minimizer has moved outside the window + so for now we need to find a new minimizer at the current window (w k-mers)**/ + for (j = buf_pos + 1, max = UINT32_MAX; j < w; ++j) {/**the two loops are necessary when there are identical k-mers**/ + if (((buf[j]>>32)) >= (max>>32)) { + max = buf[j], max_pos = j; ///max_s = buf_p[j]; /** >= is important s.t. min is always the closest k-mer**/ + } + } + for (j = 0; j <= buf_pos; ++j) { + if (((buf[j]>>32)) >= (max>>32)) { + max = buf[j], max_pos = j; ///max_s = buf_p[j]; + } + } + // if (l >= w + k - 1 && min.x != UINT64_MAX) { /**write identical k-mers**/ + if((l >= w) && (max != UINT32_MAX)) { /**write identical k-mers**/ + for (j = buf_pos + 1; j < w; ++j) {/**these two loops make sure the output is sorted**/ + if(((buf[j]>>32) == (max>>32)) && (((uint32_t)buf[j]) != ((uint32_t)max))) { + kv_push(uint64_t, *p, buf[j]); + } + } + for (j = 0; j <= buf_pos; ++j) { + if(((buf[j]>>32) == (max>>32)) && (((uint32_t)buf[j]) != ((uint32_t)max))) { + kv_push(uint64_t, *p, buf[j]); + } + } + } + if ((++buf_pos) == w) buf_pos = 0; + } + } + + if(max != UINT32_MAX) { + kv_push(uint64_t, *p, max); + } +} + + + +uint64_t hc_reseed_rr(overlap_region* ol, uint64_t ql, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, ul_ov_t *c_idx, int64_t kl, int64_t w, + int32_t *l, int32_t *tl, int32_t *buf_pos, int32_t *max_pos, uint64_t *buf, uint64_t *max, uint64_t *cnt, asg64_v *rs) +{ + uint64_t k, q[2], rr = 0, os, oe; ul_ov_t *p; overlap_region *z; + memset(cnt, 0, sizeof((*cnt))*(e-s)); + for (k = 0; k < id_n; k++) { + p = &(c_idx[id_a[k]]); z = &(ol[ovlp_id(*p)]); + q[0] = z->w_list.a[ovlp_cur_wid(*p)].x_start+ovlp_bd(*p); + q[1] = z->w_list.a[ovlp_cur_wid(*p)].x_end+1-ovlp_bd(*p); + if(q[1] <= e) rr = 1; + os = MAX(q[0], s); oe = MIN(q[1], e); + if(oe > os) { + // if(is_dbg) fprintf(stderr, "[M::%s]\ttn::%u\t%c\to::[%lu,\t%lu)\n", __func__, z->y_id, "+-"[z->y_pos_strand], os, oe); + // extract_sub_cigar_hc(z, rref, hp, qstr, ql, tu, os, oe, p, set_f, hp->flag + os - s, occ_thres, hpc_len); + extract_sub_kmer(z, os, oe, ql, kl, p, cnt + os - s); + } + } + + + + int32_t j; uint64_t info = UINT32_MAX, ki; + for (ki = s; ki < e; ki++) { + info = UINT32_MAX; + if(cnt[(ki)-s] > 0) { + ++(*l); (*tl)++; info = cnt[(ki)-s]; info <<= 32; info |= ((uint64_t)(ki)); + } else { + (*l) = 0; ///tq.count = tq.front = 0; + } + buf[(*buf_pos)] = info; ///need to do this here as appropriate buf_pos and buf[buf_pos] are needed below + // buf_p[buf_pos] = l; + // if (l == w + k - 1 && min.x != UINT64_MAX) { /**special case for the first window - because identical k-mers are not stored yet**/ + ///I have no idea if we should give l == w or l == w + 1 + if (((*l) == (w + kl - 1)) && ((*max) != UINT32_MAX) && (((*max)>>32) >= (info>>32))) { /**special case for the first window - because identical k-mers are not stored yet**/ + for (j = (*buf_pos) + 1; j < w; ++j){ + // if (sf##_mzcmp(&min, &buf[j]) == 0 && buf[j].pos != min.pos){ + if(((buf[j]>>32) == ((*max)>>32)) && (((uint32_t)buf[j]) != ((uint32_t)(*max)))) { + kv_push(uint64_t, *rs, buf[j]); + } + } + for (j = 0; j < (*buf_pos); ++j){ + // if (sf##_mzcmp(&min, &buf[j]) == 0 && buf[j].pos != min.pos){ + if(((buf[j]>>32) == ((*max)>>32)) && (((uint32_t)buf[j]) != ((uint32_t)(*max)))) { + kv_push(uint64_t, *rs, buf[j]); + } + } + } + + // fprintf(stderr, "[M::%s]\tcnt[%lu]::%lu\ts::%lu\te::%lu\tinfo::%lu\tmax::%lu\tl::%d\tbuf_pos::%d\tmax_pos::%d\n", __func__, ki, cnt[(ki)-s], s, e, info>>32, (*max)>>32, (*l), (*buf_pos), (*max_pos)); + /** + * There are three cases: + * 1. info.x <= min.x, means info is a new minimizer + * 2. info.x > min.x, info is not a new minimizer + * (1) buf_pos != min_pos, do nothing + * (2) buf_pos == min_pos, means current minimizer has moved outside the window + * **/ + if (((info>>32)) >= ((*max)>>32)) { /**a new minimum; then write the old min**/ + // if (l >= w + k && min.x != UINT64_MAX){ + if (((*l) >= (w + kl)) && ((*max) != UINT32_MAX)) { + kv_push(uint64_t, *rs, (*max)); + } + (*max) = info, (*max_pos) = (*buf_pos); ///max_s = buf_p[buf_pos]; + } else if ((*buf_pos) == (*max_pos)) { /**old min has moved outside the window**/ + // if (l >= w + k - 1 && min.x != UINT64_MAX){ + if(((*l) >= (w + kl - 1)) && ((*max) != UINT32_MAX)) { + kv_push(uint64_t, *rs, (*max)); + } + /**buf_pos == min_pos, means current minimizer has moved outside the window + so for now we need to find a new minimizer at the current window (w k-mers)**/ + for (j = (*buf_pos) + 1, (*max) = UINT32_MAX; j < w; ++j) {/**the two loops are necessary when there are identical k-mers**/ + if (((buf[j]>>32)) >= ((*max)>>32)) { + (*max) = buf[j], (*max_pos) = j; ///max_s = buf_p[j]; /** >= is important s.t. min is always the closest k-mer**/ + } + } + for (j = 0; j <= (*buf_pos); ++j) { + if (((buf[j]>>32)) >= ((*max)>>32)) { + (*max) = buf[j], (*max_pos) = j; ///max_s = buf_p[j]; + } + } + // if (l >= w + k - 1 && min.x != UINT64_MAX) { /**write identical k-mers**/ + if(((*l) >= (w + kl - 1)) && ((*max) != UINT32_MAX)) { /**write identical k-mers**/ + for (j = (*buf_pos) + 1; j < w; ++j) {/**these two loops make sure the output is sorted**/ + if(((buf[j]>>32) == ((*max)>>32)) && (((uint32_t)buf[j]) != ((uint32_t)(*max)))) { + kv_push(uint64_t, *rs, buf[j]); + } + } + for (j = 0; j <= (*buf_pos); ++j) { + if(((buf[j]>>32) == ((*max)>>32)) && (((uint32_t)buf[j]) != ((uint32_t)(*max)))) { + kv_push(uint64_t, *rs, buf[j]); + } + } + } + } + if ((++(*buf_pos)) == w) (*buf_pos) = 0; + } + + + return rr; +} + + +///[s, e) +void extract_sub_anchor(overlap_region *z, bit_extz_t *ez, int64_t kl, uint64_t *km_a, int64_t km_n, asg64_v *res/**, char *qstr, char *tstr**/) +{ + // fprintf(stderr, "\n[M::%s]\ts::%ld\te::%ld\tset_f::%ld\tovlp_id::%u\twid::%u\n", __func__, s, e, set_f, ovlp_id(*p), ovlp_cur_wid(*p)); + // if((!set_f) && (!ovlp_cur_ylen(*p))) return 1;///no potential informative site + if(!(ez->cigar.n)) return; + int64_t xk = ez->ts, yk = ez->ps, ck = 0, os, oe, cn = ez->cigar.n, op, ol, ws, we, ks, ke, ovlp, k; uint64_t m; + for (k = 0; k < km_n; k++) { + ke = ((uint32_t)km_a[k]) + 1; ks = ke - kl; ///[ks, ke) + while (ck > 0 && xk > ks) {///x -> t; y -> p + --ck; + op = ez->cigar.a[ck]>>14; + if(op!=2) xk -= (ez->cigar.a[ck]&(0x3fff)); + if(op!=3) yk -= (ez->cigar.a[ck]&(0x3fff)); + } + + while (ck < cn && xk < ke) {//[s, e) + ws = xk; + op = ez->cigar.a[ck]>>14; + ol = (ez->cigar.a[ck]&(0x3fff)); + if(op!=2) xk += ol; + if(op!=3) yk += ol; + ck++; we = xk; + if(op) continue; + + os = MAX(ks, ws); oe = MIN(ke, we); + ovlp = ((oe>os)? (oe-os):0); + if(ovlp < kl) continue; + // fprintf(stderr, "[M::%s]\tq::[%ld,\t%ld)\tt::[%ld,\t%ld)\tk::[%ld,\t%ld)\n", __func__, ws, we, yk - (we - ws), yk, ks, ke); + m = oe - kl; m <<= 32; m |= ((uint64_t)(yk - (xk - oe) - kl)); + kv_push(uint64_t, *res, m); kv_push(uint64_t, *res, km_a[k]>>32); + } + } + + ///debug error + // xk = ez->ts, yk = ez->ps, ck = 0; + // while (ck < cn) {//[s, e) + // op = ez->cigar.a[ck]>>14; + // ol = (ez->cigar.a[ck]&(0x3fff)); + // if(op!=2) xk += ol; + // if(op!=3) yk += ol; + // ck++; + // if(op) continue; + // if(memcmp(qstr + xk - ol, tstr + yk - ol, ol)) { + // fprintf(stderr, "[M::%s::inexacta]\tq::[%ld,\t%ld)\tt::[%ld,\t%ld)\n", __func__, xk - ol, xk, yk - ol, yk); + // } else { + // fprintf(stderr, "[M::%s::exacta]\tq::[%ld,\t%ld)\tt::[%ld,\t%ld)\n", __func__, xk - ol, xk, yk - ol, yk); + // } + // } +} + +void debug_anchors(All_reads *rref, overlap_region *z, Candidates_list *cl, char* qstr, int64_t ql, UC_Read *tu, int64_t kl) +{ + int64_t ch_idx = z->shared_seed, ch_n, i, id = z->y_id; + k_mer_hit *ch_a = cl->list + ch_idx; + for (i = ch_idx; i < cl->length && cl->list[i].readID == cl->list[ch_idx].readID; i++){;} ch_n = i-ch_idx; + if(!ch_n) return; + + if(z->y_pos_strand == 0) { + recover_UC_Read(tu, rref, id); + } else { + recover_UC_Read_RC(tu, rref, id); + } + for (i = 0; i < ch_n; i++) { + if(memcmp(qstr + ch_a[i].self_offset + 1 - kl, tu->seq + ch_a[i].offset + 1 - kl, kl)) { + fprintf(stderr, "[M::%s::inexact]\tqs::[%lu,\t%lu)\tts::[%lu,\t%lu)\n", __func__, (uint64_t)(ch_a[i].self_offset + 1 - kl), (uint64_t)(ch_a[i].self_offset + 1), + (uint64_t)(ch_a[i].offset + 1 - kl), (uint64_t)(ch_a[i].offset + 1)); + } + /** + else { + fprintf(stderr, "[M::%s::exact]\tqs::[%lu,\t%lu)\tts::[%lu,\t%lu)\n", __func__, (uint64_t)(ch_a[i].self_offset + 1 - kl), (uint64_t)(ch_a[i].self_offset + 1), + (uint64_t)(ch_a[i].offset + 1 - kl), (uint64_t)(ch_a[i].offset + 1)); + } + **/ + } +} +void reassign_gaps(overlap_region *z, overlap_region *aux, char* qstr, int64_t ql, uint8_t* hpf, char* tstr, int64_t tl, All_reads *rref, UC_Read* tu, asg16_v* buf, bit_extz_t *exz); + +void cmp_cigar(overlap_region *za, overlap_region *zb) +{ + uint64_t mm = 0, k; + if(za->w_list.n != zb->w_list.n) mm = 1; + if(!mm) { + bit_extz_t eza, ezb; + for (k = 0; k < za->w_list.n; k++) { + if(is_ualn_win(za->w_list.a[k]) || is_ualn_win(zb->w_list.a[k])) { + if(is_ualn_win(za->w_list.a[k]) && is_ualn_win(zb->w_list.a[k]) && (za->w_list.a[k].x_start == zb->w_list.a[k].x_start) && (za->w_list.a[k].x_end == zb->w_list.a[k].x_end)) { + continue; + } + mm = 1; + break; + } + set_bit_extz_t(eza, (*za), k); set_bit_extz_t(ezb, (*zb), k); + if(eza.cigar.n != ezb.cigar.n) { + mm = 1; + break; + } + if(memcmp(eza.cigar.a, ezb.cigar.a, (eza.cigar.n * sizeof((*(eza.cigar.a)))))) { + mm = 1; + break; + } + } + } + + if(mm) { + fprintf(stderr, "[M::%s::inexact]\t%.*s\n", __func__, (int)Get_NAME_LENGTH(R_INF, za->y_id), Get_NAME(R_INF, za->y_id)); + } +} + +void gen_cz_chain(All_reads *rref, Candidates_list *cl, overlap_region *z, bit_extz_t *exz, overlap_region *aux_o, overlap_region *rse_o, uint64_t kl, uint64_t *sa, uint64_t sn, asg64_v *res, char* qstr, uint64_t ql, uint64_t tl, double err, int64_t rid, UC_Read *tu, asg16_v *b16, uint8_t *hpf) +{ + if(!(z->w_list.n)) return; + if((z->w_list.n == 1) && (z->w_list.a[0].error == 0)) return; + + // fprintf(stderr, "\n[M::%s] rid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + // if(z->y_pos_strand == 0) { + // recover_UC_Read(tu, rref, z->y_id); + // } else { + // recover_UC_Read_RC(tu, rref, z->y_id); + // } + + bit_extz_t ez; uint64_t k, i, t, cl0 = cl->length, srt = 0, m, *idx = NULL, idx_n, *czi = NULL, czi_n, cl1; k_mer_hit *p; int64_t re, rl; + for (k = res->n = 0; k < z->w_list.n; k++) { + if(is_ualn_win(z->w_list.a[k])) continue; + set_bit_extz_t(ez, (*z), k); + if(!ez.cigar.n) return; + extract_sub_anchor(z, &ez, kl, sa, sn, res/**, qstr, tu->seq**/); + } + + + czi_n = res->n; + for (k = 0; k < czi_n; k += 2) { + m = res->a[k]>>32; m <<= 32; m |= k; + kv_push(uint64_t, *res, m); + if((k > 0) && (((res->a[k]>>32) <= (res->a[k-2]>>32)) || (((uint32_t)res->a[k]) <= ((uint32_t)res->a[k-2])))) { + srt = 1; + } + // fprintf(stderr, "[M::%s]\tqs::[%lu,\t%lu)\tts::[%lu,\t%lu)\tcnt::%lu\n", __func__, res->a[k]>>32, (res->a[k]>>32) + kl, + // (uint64_t)(((uint32_t)res->a[k])), (uint64_t)(((uint32_t)res->a[k]) + kl), res->a[k + 1]); + } + czi = res->a; idx = res->a + czi_n; idx_n = res->n - czi_n; + assert((idx_n<<1) == czi_n); + + if(srt) { + radix_sort_bc64(idx, idx + idx_n); + for (k = 1, i = 0; k <= idx_n; k++) { + if (k == idx_n || (idx[k]>>32) != (idx[i]>>32)) { + if(k - i > 1) { + for (t = i; t < k; t++) { + m = (uint32_t)czi[(uint32_t)idx[t]]; m <<= 32; + m += ((uint32_t)idx[t]); idx[t] = m; + } + radix_sort_bc64(idx + i, idx + k); + } + i = k; + } + } + } + + // ze0 = z->non_homopolymer_errors; z->non_homopolymer_errors = cl->length; + kv_resize_cl(k_mer_hit, (*cl), ((int64_t)(idx_n + cl->length))); + for (k = 0, cl1 = cl->length; k < idx_n; k++) { + p = &cl->list[cl1++]; + p->readID = z->y_id; + p->strand = z->y_pos_strand; + p->self_offset = (czi[(uint32_t)idx[k]]>>32) + kl - 1; + p->offset = ((uint32_t)czi[(uint32_t)idx[k]]) + kl - 1; + p->cnt = czi[((uint32_t)idx[k]) + 1]; + } + cl1 = lchain_simple0(cl->list + cl0, cl1 - cl0, cl->list + cl0, &(cl->chainDP), 25, 5000) + cl0; + if(cl1 == cl0) return; + cl->length = cl1; + + + // zq0[0] = z->x_pos_s; zq0[1] = z->x_pos_e; + // zt0[0] = z->y_pos_s; zt0[1] = z->y_pos_e; + // zal0 = z->align_length; zst0 = z->strong; zol0 = z->overlapLen; + // ze0 = z->non_homopolymer_errors; zse0 = z->shared_seed; zmat0 = z->is_match; + rse_o->f_cigar.length = 0; rse_o->w_list.n = rse_o->w_list.c.n = 0; + rse_o->boundary_cigars.n = rse_o->boundary_cigars.c.n = 0; + push_ovlp_chain_qgen(rse_o, z->x_id, ql, tl, z->shared_seed, &(cl->list[cl0]), &(cl->list[cl1 - 1])); + + rse_o->shared_seed = cl0; + for (k = cl0; k < cl1; k++) { + cl->list[k].readID = ((uint32_t)(0x7ffffffe)); //not ((uint32_t)(0x7fffffff)) + } + gen_fake_cigar(&(rse_o->f_cigar), rse_o, 1, cl->list + cl0, cl1 - cl0); + + ///this must be 0; not necssary here since we already set it to 0 + rse_o->w_list.n = 0; + + ///debug error + // debug_anchors(rref, rse_o, cl, qstr, ql, tu, kl); + + re = INT64_MAX; + gen_hc_fast_cigar0(rse_o, cl, 0, rref, qstr, tu, exz, aux_o, err, ql, rid, 0, &re); + rse_o->non_homopolymer_errors = re; + + reassign_gaps(rse_o, aux_o, qstr, ql, hpf, NULL, -1, rref, tu, b16, exz); + + // cmp_cigar(rse_o, z); + + + // fprintf(stderr, "[M::%s]\terr_0::%u\terr_1::%ld\terr_2::%u\n", __func__, z->non_homopolymer_errors, re, rse_o->non_homopolymer_errors); + + re = rse_o->non_homopolymer_errors; rl = rse_o->x_pos_e + 1 - rse_o->x_pos_s; + if(re <= (rl * err * 1.5)) { + update_overlap_region(z, rse_o, ql, tl); + } + + cl->length = cl0; +} + + +void gen_reseed_re(overlap_region_alloc *ol, Candidates_list *cl, overlap_region *aux_o, overlap_region *rse_o, All_reads *rref, UC_Read *qu, UC_Read *tu, bit_extz_t *exz, kv_ul_ov_t *c_idx, asg64_v *idx, asg64_v *res, int64_t bd, int64_t mzw, int64_t kl, int64_t rid, double err_h, double err_l, asg16_v *b16, uint64_t tqn, uint8_t *hpf) +{ + int64_t on = ol->length, k, i, zwn, q[2], ql = qu->length; + uint64_t m; overlap_region *z; ul_ov_t *cp; + kv_resize(uint64_t, *idx, (ol->length)); + kv_resize(ul_ov_t, *c_idx, ol->length); + + for (k = idx->n = c_idx->n = 0; k < on; k++) { + z = &(ol->list[k]); zwn = z->w_list.n; + if(!zwn) continue; + for (i = 0; i < zwn; i++) { + if(is_ualn_win(z->w_list.a[i])) continue; + q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; + q[0] += bd; q[1] -= bd; + if(q[1] >= q[0]) { + m = ((uint64_t)q[0]); m <<= 32; + m += c_idx->n; kv_push(uint64_t, *idx, m); + + kv_pushp(ul_ov_t, *c_idx, &cp); + ovlp_id(*cp) = k; ///ovlp id + ovlp_cur_wid(*cp) = i; ///cur id of windows + ovlp_cur_xoff(*cp) = z->w_list.a[i].x_start; ///cur xpos + ovlp_cur_yoff(*cp) = z->w_list.a[i].y_start; ///cur xpos + ovlp_cur_ylen(*cp) = 0; + ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window + ovlp_bd(*cp) = bd; + } + } + } + + int64_t srt_n = idx->n, s, e, t, os, oe, rm_n, rr; i = 0; + radix_sort_bc64(idx->a, idx->a+idx->n); + for (k = 1, i = 0; k <= srt_n; k++) { + if (k == srt_n || (idx->a[k]>>32) != (idx->a[i]>>32)) { + if(k - i > 1) { + for (t = i; t < k; t++) { + cp = &(c_idx->a[(uint32_t)idx->a[t]]); + // s = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); + // assert(s == (int64_t)(idx->a[i]>>32)); + m = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + m <<= 32; m += ((uint32_t)idx->a[t]); idx->a[t] = m; + // fprintf(stderr, "[M::%s] s::%ld\tsi::%lu\n", __func__, s, (idx->a[i]>>32)); + } + radix_sort_bc64(idx->a + i, idx->a + k); + } + i = k; + } + } + + + int32_t rl, rtl = 0, rbuf_pos, rmax_pos; + uint64_t rbuf[256], rmax = UINT32_MAX; + res->n = 0; rl = rtl = rbuf_pos = rmax_pos = 0; + memset(rbuf, 0xff, mzw * sizeof((*rbuf))); + + i = 0; s = 0; e = mzw; e = ((e<=ql)?e:ql); rr = 0; + for (; s < ql; ) { + if(rr) { + // rr = 0; + for (m = rm_n = srt_n; m < idx->n; m++) { + cp = &(c_idx->a[idx->a[m]]); + q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); + q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + os = MAX(q[0], s); oe = MIN(q[1], e); + if(oe > os) { + idx->a[rm_n++] = idx->a[m]; + // if(q[1] <= e) rr = 1; + } + } + idx->n = rm_n; + } + + for (; i < srt_n; ++i) { + cp = &(c_idx->a[(uint32_t)idx->a[i]]); + q[0] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); + q[1] = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + if(q[0] >= e) break; + os = MAX(q[0], s); oe = MIN(q[1], e); + if(oe > os) { + kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); + // if(q[1] <= e) rr = 1; + } + } + kv_resize(uint64_t, *idx, (idx->n + mzw)); + rr = hc_reseed_rr(ol->list, ql, idx->a + srt_n, idx->n - srt_n, s, e, c_idx->a, kl, mzw, + &rl, &rtl, &rbuf_pos, &rmax_pos, rbuf, &rmax, idx->a + idx->n, res); + + + s += mzw; e += mzw; e = ((e<=ql)?e:ql); + } + + if(rmax != UINT32_MAX) { + kv_push(uint64_t, *res, rmax); + } + + // zwn = res->n; + // for (i = 0; i < zwn; i++) { + // fprintf(stderr, "[M::%s]\tcnt::%lu\tk_s::[%lu,\t%lu]\n", __func__, res->a[i]>>32, (uint64_t)((uint32_t)res->a[i] + 1 - kl), (uint64_t)((uint32_t)res->a[i])); + // } + + for (k = 0; k < on; k++) { + gen_cz_chain(rref, cl, &(ol->list[k]), exz, aux_o, rse_o, kl, res->a, res->n, idx, qu->seq, ql, Get_READ_LENGTH(R_INF, ol->list[k].y_id), ((ol->list[k].y_idw_list.n; if(!zwn) return 0; + + ///in_id -> ovlp id + ou->qn = in_id; ou->tn = in->y_id; + ou->rev = in->y_pos_strand; + ou->qs = in->w_list.a[0].x_start; + ou->qe = in->w_list.a[zwn-1].x_end+1; + + if(!(ou->rev)) { + ou->ts = in->w_list.a[0].y_start; + ou->te = in->w_list.a[zwn-1].y_end+1; + } else { + ou->ts = tl-(in->w_list.a[zwn-1].y_end+1); + ou->te = tl-in->w_list.a[0].y_start; + } + return 1; +} + +uint32_t push_emask_flt(kv_emask_t *in, uint64_t *flt, uint64_t flt_n, uint64_t qn, kv_ul_ov_t *res) +{ + uint32_t k = 0, z = 0, tn, rn0 = res->n; ul_ov_t *p; + while (k < in->n && z < flt_n) { + if (in->a[k].tn < (flt[z]>>32)) { + k++; + } else if((flt[z]>>32) < in->a[k].tn) { + z++; + } else {///in->a[k].tn == (flt[z]>>32) + for (tn = in->a[k].tn; k < in->n && in->a[k].tn == tn; k++) { + kv_pushp(ul_ov_t, *res, &p); + p->qn = qn; p->qs = in->a[k].qs; p->qe = in->a[k].qe; + p->tn = in->a[k].tn; p->ts = in->a[k].ts; p->te = in->a[k].te; + p->rev = in->a[k].rev; p->el = in->a[k].full; p->sec = k; + } + for (; z < flt_n && (flt[z]>>32) == tn; z++); + } + } + return res->n-rn0; +} + +#define is_ul_ov_pe(z, zn, i, mm) ((((i)+1)<(zn))&&((z)[(i)+1].qn==(z)[(i)].qn)&&((z)[(i)+1].tn==(z)[(i)].tn)&&((z)[(i)+1].rev==(z)[(i)].rev)\ + &&((z)[(i)+1].sec==(z)[(i)].sec+1)&&(((z)[(i)].sec)<(mm).a[(z)[(i)].qn].n)&&(((z)[(i)+1].sec)<(mm).a[(z)[(i)+1].qn].n)\ + &&((mm).a[(z)[(i)].qn].a[((z)[(i)].sec)].pe)&&((mm).a[(z)[(i)+1].qn].a[((z)[(i)+1].sec)].pe)\ + &&((mm).a[(z)[(i)].qn].a[((z)[(i)].sec)].dir==0)&&((mm).a[(z)[(i)+1].qn].a[((z)[(i)+1].sec)].dir==1)) + +#define is_exact_ov(z, mm) (((((z).sec)<(mm).a[(z).qn].n))&&(!((mm).a[(z).qn].a[((z).sec)].pe))\ + &&((mm).a[(z).qn].a[((z).sec)].el==(uint32_t)-1)) + + +///ref_n <= 2 +uint64_t is_cover_ul_ov_t(ma_ug_t *ug, double diff, ul_ov_t *ref, uint64_t ref_n, ul_ov_t *in) +{ + if((!check_ul_ov_t_consist(in, &(ref[0]), ug->g->seq[in->qn].len, ug->g->seq[in->tn].len, diff))) return 0; + if((ref_n > 1) && (!check_ul_ov_t_consist(in, &(ref[ref_n-1]), ug->g->seq[in->qn].len, ug->g->seq[in->tn].len, 0.06))) return 0; + uint64_t i; int64_t sql, stl, os, oe, ovlp; + sql = in->qe - in->qs; stl = in->te - in->ts; + for (i = 0; i < ref_n && sql > 0 && stl > 0; i++) { + os = MAX(in->qs, ref[i].qs); oe = MIN(in->qe, ref[i].qe); + ovlp = ((oe>os)?(oe-os):(0)); sql -= ovlp; + + os = MAX(in->ts, ref[i].ts); oe = MIN(in->te, ref[i].te); + ovlp = ((oe>os)?(oe-os):(0)); stl -= ovlp; + } + if((sql > 256) && (sql > ((in->qe - in->qs)*0.06))) return 0; + if((sql <= 256) && (sql > ((in->qe - in->qs)*0.6))) return 0; + if((stl > 256) && (stl > ((in->te - in->ts)*0.06))) return 0; + if((stl <= 256) && (stl > ((in->te - in->ts)*0.6))) return 0; + return 1; +} + +uint64_t dedup_src_shared(ma_ug_t *ug, ul_ov_t *ta, uint64_t tn, ul_ov_t *qa, uint64_t qn, idx_emask_t *mm) +{ + uint32_t ti, qi, ts, te, id, k, l; + ti = qi = 0; + while (ti < tn && qi < qn) { + if (ta[ti].tn < qa[qi].tn) { + ti++; + } else if(qa[qi].tn < ta[ti].tn) { + qi++; + } else {///ta[ti].tn == qa[qi].tn + id = ta[ti].tn; + for (ts = ti; ti < tn && ta[ti].tn == id; ti++){;} te = ti; + for (; qi < qn && qa[qi].tn == id; qi++) { + for (k = ts; k < te; k++) { + l = 1; + if(is_ul_ov_pe(ta, te, k, (*mm))) { + l++; k++; + } + if(is_cover_ul_ov_t(ug, 0.06, ta+k+1-l, l, &(qa[qi]))) break; + } + if(k < te) qa[qi].qn = qa[qi].tn = (uint32_t)-1; + } + } + } + for (qi = l = 0; qi < qn; qi++) { + if(qa[qi].tn == (uint32_t)-1) continue; + qa[l++] = qa[qi]; + } + return l; +} + +void dedup_src_shared1(ma_ug_t *ug, kv_ul_ov_t *res, uint64_t tocc, uint64_t qocc, idx_emask_t *mm) +{ + if((!tocc) || (!qocc)) return; + uint32_t ti, qi, tn, qn, rn = res->n, id, ts, te, k, l, ff = 0; + // qi = res->n - qocc; fi = 0; m = qi; qocc = 0; + // while (qi < res->n && fi < flt_n) { + // if(res->a[qi].tn < (flt[fi]>>32)) { + // qi++; + // } else if((flt[fi]>>32) < res->a[qi].tn) { + // fi++; + // } else {///res->a[qi].tn == (flt[fi]>>32) + // res->a[m++] = res->a[qi]; qocc++; qi++; fi++; + // } + // } + // res->n = m; + // if((!tocc) || (!qocc)) return; + + rn = res->n; + ti = res->n - tocc - qocc; qi = res->n - qocc;//t first, and then q + tn = ti + tocc; qn = qi + qocc; kv_resize(ul_ov_t, *res, (rn+tn));///the buf size should be at least tn + while (ti < tn && qi < qn) { + if (res->a[ti].tn < res->a[qi].tn) { + kv_push(ul_ov_t, *res, res->a[ti]); ti++; + } else if(res->a[qi].tn < res->a[ti].tn) { + kv_push(ul_ov_t, *res, res->a[qi]); qi++; + } else {///ta[ti].tn == qa[qi].tn + id = res->a[ti].tn; ts = ti; + for (; ti < tn && res->a[ti].tn == id; ti++) { + kv_push(ul_ov_t, *res, res->a[ti]); + } + te = ti; + + for (; qi < qn && res->a[qi].tn == id; qi++) { + for (k = ts; k < te; k++) { + l = k; + if(is_ul_ov_pe(res->a, te, k, (*mm))) k++; + if(is_cover_ul_ov_t(ug, 0.06, res->a+l, k+1-l, &(res->a[qi]))) { + ff = 1; break; + } + } + if(k >= te) kv_push(ul_ov_t, *res, res->a[qi]); + } + } + } + while (ti < tn) { + kv_push(ul_ov_t, *res, res->a[ti]); ti++; + } + while (qi < qn) { + kv_push(ul_ov_t, *res, res->a[qi]); qi++; + } + + // fprintf(stderr, "[M::%s]\tff::%u\n", __func__, ff); + if(!ff) {///nothing has been removed as duplication + res->n = rn; + } else if(res->n > rn) { + l = res->n; res->n = rn - tocc - qocc; + for (k = rn; k < l; k++) res->a[res->n++] = res->a[k]; + } +} + +#define aln2ov(in, ou, tl) \ + {(ou).qn=(in).x_id;(ou).tn=(in).y_id;(ou).rev=(in).y_pos_strand;\ + (ou).qs=(in).x_pos_s;(ou).qe=(in).x_pos_e+1;\ + if((in).y_pos_strand){(ou).ts=(tl)-(in).y_pos_e-1;(ou).te=(tl)-(in).y_pos_s;}\ + else {(ou).ts=(in).y_pos_s;(ou).te=(in).y_pos_e+1;}} + +uint64_t cal_x_ul_ovlp(ma_ug_t *ug, overlap_region *q, overlap_region *t, ul_ov_t *res) +{ + ul_ov_t qo, to; uint32_t ql, tl, os, oe, rqs, rqe, rts, rte; + ql = ug->g->seq[q->y_id].len; tl = ug->g->seq[t->y_id].len; + aln2ov((*q), qo, ql); aln2ov((*t), to, tl); memset(res, 0, sizeof(*res)); + os = MAX(qo.qs, to.qs); oe = MIN(qo.qe, to.qe); + if(oe <= os) return 0; + if(infer_se(qo.qs, qo.qe, qo.ts, qo.te, qo.rev, os, oe, &rqs, &rqe) && + infer_se(to.qs, to.qe, to.ts, to.te, to.rev, os, oe, &rts, &rte)) { + if(rqe > rqs && rte > rts) { + res->qn = qo.tn; res->tn = to.tn; res->rev = ((qo.rev==to.rev)?0:1); + res->qs = rqs; res->qe = rqe; res->ts = rts; res->te = rte; + return 1; + } + } + return 0; +} + +uint64_t check_mask_exist(ma_ug_t *ug, overlap_region *q, overlap_region *t, kv_ul_ov_t *ov_db, idx_emask_t *mm, double len_diff, uint64_t *is_exact, uint64_t *ovdb_idx) +{ + ul_ov_t rr, *a; uint64_t k, eid, an, ss; (*is_exact) = 0; (*ovdb_idx) = (uint64_t)-1; + if(!cal_x_ul_ovlp(ug, q, t, &rr)) return 0; + ss = q->overlapLen; + if(q->x_pos_strand) {///if q does not have mask + eid = rr.tn; a = ov_db->a + ss; an = q->x_pos_strand; + for (k = 0; k < an && a[k].tn < eid; k++); + for (; k < an && a[k].tn == eid; k++) { + if((!check_ul_ov_t_consist(&rr, &(a[k]), ug->g->seq[rr.qn].len, ug->g->seq[rr.tn].len, len_diff))) continue; + if(is_ul_ov_pe(a, an, k, (*mm))) { + k++; if((!check_ul_ov_t_consist(&rr, &(a[k]), ug->g->seq[rr.qn].len, ug->g->seq[rr.tn].len, len_diff))) continue; + } + if(is_exact_ov(a[k],(*mm))) (*is_exact) = 1; + (*ovdb_idx) = ss + k; + return 1; + } + } + + k = rr.qn; rr.qn = rr.tn; rr.tn = k; + k = rr.qs; rr.qs = rr.ts; rr.ts = k; + k = rr.qe; rr.qe = rr.te; rr.te = k; + ss = t->overlapLen; + if(t->x_pos_strand) {///if t does not have mask + eid = rr.tn; a = ov_db->a + ss; an = t->x_pos_strand; + for (k = 0; k < an && a[k].tn < eid; k++); + for (; k < an && a[k].tn == eid; k++) { + if((!check_ul_ov_t_consist(&rr, &(a[k]), ug->g->seq[rr.qn].len, ug->g->seq[rr.tn].len, len_diff))) continue; + if(is_ul_ov_pe(a, an, k, (*mm))) { + k++; if((!check_ul_ov_t_consist(&rr, &(a[k]), ug->g->seq[rr.qn].len, ug->g->seq[rr.tn].len, len_diff))) continue; + } + if(is_exact_ov(a[k],(*mm))) (*is_exact) = 1; + (*ovdb_idx) = ss + k; + return 1; + } + } + return 0; +} + +void push_consist_ul_ovlps(ma_ug_t *ug, kv_ul_ov_t *ov_db, uint64_t s, uint64_t e, double len_diff, ul_ov_t *ref, idx_emask_t *mm, kv_ul_ov_t *out, uint64_t flip_res, uint64_t *is_exact) +{ + (*is_exact) = 0; + if(s >= e) return; + uint64_t k, z, ql = ug->g->seq[ref->qn].len, tl = ug->g->seq[ref->tn].len; ul_ov_t *p; + for (k = s; k < e && ov_db->a[k].tn < ref->tn; k++); + for (; k < e && ov_db->a[k].tn == ref->tn; k++) { + if((!check_ul_ov_t_consist(ref, &(ov_db->a[k]), ql, tl, len_diff))) continue; + z = k; + if(is_ul_ov_pe(ov_db->a, ov_db->n, k, (*mm))) { + k++; if((!check_ul_ov_t_consist(ref, &(ov_db->a[k]), ql, tl, len_diff))) continue; + } + if(is_exact_ov(ov_db->a[k], (*mm))) { + (*is_exact) = 1; return; + } + + for (; z <= k; z++) { + kv_pushp(ul_ov_t, *out, &p); + *p = ov_db->a[k]; + if(flip_res) { + p->qn = ov_db->a[k].tn; p->tn = ov_db->a[k].qn; + p->qs = ov_db->a[k].ts; p->qe = ov_db->a[k].te; + p->ts = ov_db->a[k].qs; p->te = ov_db->a[k].qe; + } + } + } +} + +uint64_t cal_no_bd_coor(ul_ov_t *in, ul_ov_t *ou, idx_emask_t *mm, int64_t bd) +{ + int64_t qs, qe, ts, te; emask_t *z; + qs = in->qs; qe = in->qe; ts = in->ts; te = in->te; + if(in->sec != ((uint32_t)(0x3fffffff))) {///might be an end mask; no need shrink + if((in->sec < mm->a[in->qn].n) && (in->tn == mm->a[in->qn].a[in->sec].tn) && (in->rev == mm->a[in->qn].a[in->sec].rev) && + (in->qs == mm->a[in->qn].a[in->sec].qs) && (in->qe == mm->a[in->qn].a[in->sec].qe) && + (in->ts == mm->a[in->qn].a[in->sec].ts) && (in->te == mm->a[in->qn].a[in->sec].te)) { + z = &(mm->a[in->qn].a[in->sec]); assert(z->el != ((uint32_t)-1)); + if(z->dir == 0) { + qe -= (z->el>>1); + if(in->rev) ts += (z->el>>1); + else te -= (z->el>>1); + } else { + qs += (z->el>>1); + if(in->rev) te -= (z->el>>1); + else ts += (z->el>>1); + } + // fprintf(stderr, "+[M::%s]\tz->dir::%u\tz->el::%u\tq::[%ld,\t%ld)\tt::[%ld,\t%ld)\n", __func__, z->dir, z->el, qs, qe, ts, te); + } else { + assert((in->sec < mm->a[in->tn].n) && (in->qn == mm->a[in->tn].a[in->sec].tn) && (in->rev == mm->a[in->tn].a[in->sec].rev) && + (in->qs == mm->a[in->tn].a[in->sec].ts) && (in->qe == mm->a[in->tn].a[in->sec].te) && + (in->ts == mm->a[in->tn].a[in->sec].qs) && (in->te == mm->a[in->tn].a[in->sec].qe)); + z = &(mm->a[in->tn].a[in->sec]); assert(z->el != ((uint32_t)-1)); + if(z->dir == 1) { + qe -= (z->el>>1); + if(in->rev) ts += (z->el>>1); + else te -= (z->el>>1); + } else { + qs += (z->el>>1); + if(in->rev) te -= (z->el>>1); + else ts += (z->el>>1); + } + // fprintf(stderr, "-[M::%s]\tz->dir::%u\tz->el::%u\tq::[%ld,\t%ld)\tt::[%ld,\t%ld)\n", __func__, z->dir, z->el, qs, qe, ts, te); + } + } else {///shrink anyway + qs += bd; qe -= bd; ts += bd; te -= bd; + } + if(qe > qs && te > ts) { + (*ou) = (*in); + ou->qs = qs; ou->qe = qe; ou->ts = ts; ou->te = te; + return 1; + } + return 0; +} + +typedef struct { + int64_t qi, qs, qe; + int64_t ti; + int64_t qis, qie, tis, tie; + int64_t wi, wn; + int64_t tot, lc, cql, ctl, ci, lerr; + overlap_region *z; +} pe_cigar_iter_t; + +#define citer_end(m) ((m).qi>=(m).qe) + +/** +inline void pop_citer(pe_cigar_iter_t *it) +{ + it->lc = it->lerr = -1; it->cql = it->ctl = 0; + it->qis = it->qie; it->tis = it->tie; + if(it->wi >= it->wn) return; + int64_t ws, we, os, oe, ovlp, ql, tl, werr; + window_list *m; bit_extz_t ez; + + while (it->wi < it->wn) { + m = &(it->z->w_list.a[it->wi]); + ws = m->x_start; we = m->x_end+1; + os = MAX(it->qs, ws); oe = MIN(it->qe, we); + ovlp = ((oe>os)? (oe-os):0); + + if(ovlp) { + ql = m->x_end+1-m->x_start; + tl = m->y_end+1-m->y_start; + if((is_ualn_win((*m))) || (is_est_aln((*m)))) { + it->lc = 4;//not an ordinary cigar + if(is_ualn_win((*m))) { //unmapped + werr = gen_err_unaligned(ql, tl); + } else { + werr = m->error;//shared window + if(!werr) it->lc = 0;///treat it as match + } + it->lerr = werr; + if(ovlp < ql) { + werr = (((double)ovlp)/((double)ql))*((double)werr); + } + //skip the whole window + it->tot += werr; + it->qis = it->qi; it->qi = it->qie = m->x_end+1; it->cql = it->qie - it->qis; + it->tis = it->ti; it->ti = it->tie = m->x_start; it->ctl = it->tie - it->tis; + it->ci = 0; it->wi++; + return; + } else { + if(it->qi < m->x_start || it->ti < m->y_start) { + it->qi = m->x_start; it->ti = m->y_start; it->ci = 0; + } + set_bit_extz_t(ez, (*(it->z)), it->wi); + // if(ovlp == ql) { + // //skip the whole window + // err += m->error; xk = m->x_end+1; ck = m->clen; + // } else { + // set_bit_extz_t(ez, (*z), wk); + // err += retrieve_cigar_err(&ez, os, oe, &xk, &ck); + // } + } + } + } +} +**/ + +int64_t get_pe_diff(overlap_region *q, uint64_t *qmask, uint64_t qmask_n, overlap_region *t, uint64_t *tmask, uint64_t tmask_n, int64_t bd) +{ + int64_t s, e; overlap_region *z; + pe_cigar_iter_t qi, ti; + z = q; if(!(z->w_list.n)) return 0; + s = z->w_list.a[0].x_start; e = z->w_list.a[z->w_list.n-1].x_end+1; + s += bd; e -= bd; if(s >= e) return 0; + memset(&qi, 0, sizeof(qi)); + qi.z = q; qi.qs = s; qi.qe = e; + qi.qi = q->w_list.a[0].x_start; + qi.ti = q->w_list.a[0].y_start; + qi.wi = 0; qi.wn = q->w_list.n; + qi.tot = 0; qi.ci = 0; qi.lc = -1; qi.cql = qi.ctl = 0; + qi.qis = qi.qie = qi.qi; + qi.tis = qi.tie = qi.ti; + qi.lerr = -1; + + z = t; if(!(z->w_list.n)) return 0; + s = z->w_list.a[0].x_start; e = z->w_list.a[z->w_list.n-1].x_end+1; + s += bd; e -= bd; if(s >= e) return 0; + memset(&ti, 0, sizeof(ti)); + ti.z = q; ti.qs = s; ti.qe = e; + ti.qi = t->w_list.a[0].x_start; + ti.ti = t->w_list.a[0].y_start; + ti.wi = 0; ti.wn = t->w_list.n; + ti.tot = 0; ti.ci = 0; ti.lc = -1; ti.cql = ti.ctl = 0; + ti.qis = ti.qie = ti.qi; + ti.tis = ti.tie = ti.ti; + ti.lerr = -1; + + while((!citer_end(qi)) && (!citer_end(ti))) { + if(qi.qi == ti.qi) {///check if it is been masked + + } else if((qi.lc == 0) && (ti.lc == 0)) {///check if it is been masked + + } + + if(qi.qi < ti.qi) { + + } if(ti.qi < qi.qi) { + + } else {//qi.qi == ti.qi + + } + } + return 0; +} + +void retrieve_cigar_xcoord(bit_extz_t *ez, int64_t is, int64_t ie, int64_t *yk, int64_t *xk, int64_t *ck, int64_t *rxs, int64_t *rxe) +{ + if(!ez->cigar.n) return; + int64_t cn = ez->cigar.n, op; int64_t ws, we, ws0, we0, os, oe; + if(((*ck) < 0) || ((*ck) > cn)) {//(*ck) == cn is allowed + (*ck) = 0; (*yk) = ez->ps; (*xk) = ez->ts; + } + + while ((*ck) > 0 && (*yk) > is) { + --(*ck); + op = ez->cigar.a[(*ck)]>>14; + if(op!=3) (*yk) -= (ez->cigar.a[(*ck)]&(0x3fff)); + if(op!=2) (*xk) -= (ez->cigar.a[(*ck)]&(0x3fff)); + } + + //some cigar will span s or e + while ((*ck) < cn && (*yk) < ie) {//[s, e) + ws = (*yk); ws0 = (*xk); + op = ez->cigar.a[(*ck)]>>14; + if(op!=3) (*yk) += (ez->cigar.a[(*ck)]&(0x3fff)); + if(op!=2) (*xk) += (ez->cigar.a[(*ck)]&(0x3fff)); + we = (*yk); we0 = (*xk); + if(ws >= is && we <= ie) {///the cigar is fully contained + if((*rxs) > ws0) (*rxs) = ws0; + if((*rxe) < we0) (*rxe) = we0; + } else if(op == 0 || op == 1) {///overlap, it is hard to handle indels + os = MAX(is, ws); oe = MIN(ie, we); + if(oe > os) { + ws0 += (os - ws); + we0 = ws0 + (oe - os); + if((*rxs) > ws0) (*rxs) = ws0; + if((*rxe) < we0) (*rxe) = we0; + } + } + (*ck)++; + } +} + +uint64_t extract_xcoordates0(overlap_region *z, int64_t ys, int64_t ye, int64_t *rxs, int64_t *rxe, ul_ov_t *p) +{ + int64_t wk = ovlp_cur_wid(*p), yk = ovlp_cur_xoff(*p), xk = ovlp_id(*p), ck = ovlp_cur_coff(*p); + int64_t min_w = ovlp_min_wid(*p), max_w = ovlp_max_wid(*p);//[min_w, max_w] + bit_extz_t ez; window_list *m; (*rxs) = INT32_MAX; (*rxe) = -1; + if(ys >= ye) return 0; + ///[ys, ye) but [z->w_list.a[wk].y_start, z->w_list.a[wk].y_end] + int64_t ws, we, os, oe, ovlp, yl, tot = ye - ys; + if(wk < min_w || wk > max_w) wk = min_w; + for (; wk >= min_w && z->w_list.a[wk].y_start > ys; wk--); + if(wk < min_w || wk > max_w) return 0; + for (; wk <= max_w && z->w_list.a[wk].y_end < ys; wk++); + if(wk < min_w || wk > max_w) return 0; + //s >= w_list.a[wk].x_start && s <= w_list.a[wk].x_end + if(wk != ovlp_cur_wid(*p)) {//xk is global, while ck is local + yk = z->w_list.a[wk].y_start; + xk = z->w_list.a[wk].x_start; + ck = 0; + } + + ///[ys, ye) but [z->w_list.a[wk].y_start, z->w_list.a[wk].y_end] + while(wk <= max_w && z->w_list.a[wk].y_start < ye) { + m = &(z->w_list.a[wk]); + ws = m->y_start; we = m->y_end+1; + os = MAX(ys, ws); oe = MIN(ye, we); + ovlp = ((oe>os)? (oe-os):0); + + if(ovlp) { + yl = m->y_end+1-m->y_start; + if((is_ualn_win((*m))) || (is_est_aln((*m)))) { + if(ovlp >= yl) { + if((*rxs) > m->x_start) (*rxs) = m->x_start; + if((*rxe) < (m->x_end+1)) (*rxe) = m->x_end+1; + } + //skip the whole window + yk = m->y_end+1; xk = m->x_end+1; ck = m->clen; + } else { + if(ovlp == yl) { + //skip the whole window + yk = m->y_end+1; xk = m->x_end+1; ck = m->clen; + if((*rxs) > m->x_start) (*rxs) = m->x_start; + if((*rxe) < (m->x_end+1)) (*rxe) = m->x_end+1; + } else { + set_bit_extz_t(ez, (*z), wk); + retrieve_cigar_xcoord(&ez, os, oe, &yk, &xk, &ck, rxs, rxe); + } + } + } + tot -= ovlp; + if(yk >= ye) break;//[min_w, max_w] && [ys, ye) + wk++; if(wk > max_w) break; + yk = z->w_list.a[wk].y_start; xk = z->w_list.a[wk].x_start; ck = 0;//reset + } + assert(!tot); + ovlp_cur_wid(*p) = wk; ovlp_cur_xoff(*p) = yk; ovlp_id(*p) = xk; ovlp_cur_coff(*p) = ck; + if((*rxe) > (*rxs)) return 1; + return 0; +} + +uint64_t extract_xcoordates(overlap_region *z, uint64_t *a, int64_t a_n, asg64_v *b) +{ + int64_t i, zwn, q[2], t[2], w[2], bn = b->n, a_i, a_z, as, ae, is, ie, os, oe, ovlp; + ul_ov_t m; int64_t qs, qe; + zwn = z->w_list.n; if(!zwn) return 0; + q[0] = q[1] = t[0] = t[1] = w[0] = w[1] = INT32_MIN; memset(&m, 0, sizeof(m)); + for (i = a_i = 0; i < zwn; i++) { + if((z->w_list.a[i].x_start==(q[1]+1)) && ((z->w_list.a[i].y_start==(t[1]+1)))) { + q[1] = z->w_list.a[i].x_end; + t[1] = z->w_list.a[i].y_end; + w[1] = i; + } else { + if(q[0] != INT32_MIN) { + ovlp_id(m) = z->w_list.a[w[0]].x_start; ///cur xpos + ovlp_min_wid(m) = w[0]; ///beg id of windows + ovlp_max_wid(m) = w[1]; ///end id of windows + ovlp_cur_wid(m) = w[0]; ///cur id of windows + ovlp_cur_xoff(m) = z->w_list.a[w[0]].y_start; ///cur ypos + ovlp_cur_coff(m) = 0; ///cur cigar off in cur window + + is = t[0]; ie = t[1]+1; ///[is, ie) + for (a_z = a_i; a_z >= 0; a_z--) { + as = a[a_z]>>32; ae = (uint32_t)a[a_z]; + if(ae <= is) break; + } + if(a_z < 0) a_z = 0; + for (; a_z < a_n; a_z++) { + as = a[a_z]>>32; ae = (uint32_t)a[a_z]; + os = MAX(is, as); oe = MIN(ie, ae); + ovlp = ((oe>os)? (oe-os):0); + if(ovlp) { + if(extract_xcoordates0(z, os, oe, &qs, &qe, &m)) { + kv_push(uint64_t, *b, (((uint64_t)qs)<<32)|((uint64_t)qe)); + } + } + if(as >= ie) break; + } + a_i = a_z; + } + q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; + t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end; + w[0] = i; w[1] = i; + } + } + + if(q[0] != INT32_MIN) { + ovlp_id(m) = z->w_list.a[w[0]].x_start; ///cur xpos + ovlp_min_wid(m) = w[0]; ///beg id of windows + ovlp_max_wid(m) = w[1]; ///end id of windows + ovlp_cur_wid(m) = w[0]; ///cur id of windows + ovlp_cur_xoff(m) = z->w_list.a[w[0]].y_start; ///cur ypos + ovlp_cur_coff(m) = 0; ///cur cigar off in cur window + + is = t[0]; ie = t[1]+1; + for (a_z = a_i; a_z >= 0; a_z--) { + as = a[a_z]>>32; ae = (uint32_t)a[a_z]; + if(ae <= is) break; + } + if(a_z < 0) a_z = 0; + for (; a_z < a_n; a_z++) { + as = a[a_z]>>32; ae = (uint32_t)a[a_z]; + os = MAX(is, as); oe = MIN(ie, ae); + ovlp = ((oe>os)? (oe-os):0); + if(ovlp) { + if(extract_xcoordates0(z, os, oe, &qs, &qe, &m)) { + kv_push(uint64_t, *b, (((uint64_t)qs)<<32)|((uint64_t)qe)); + } + } + if(as >= ie) break; + } + a_i = a_z; + } + return b->n - bn; +} + +int64_t cal_xerr(overlap_region *z, uint64_t *a, int64_t a_n) +{ + int64_t i, zwn, q[2], t[2], w[2], a_i, a_z, as, ae, is, ie, os, oe, ovlp, err = 0; ul_ov_t m; + zwn = z->w_list.n; if(!zwn) return 0; + q[0] = q[1] = t[0] = t[1] = w[0] = w[1] = INT32_MIN; memset(&m, 0, sizeof(m)); + for (i = a_i = 0; i < zwn; i++) { + // fprintf(stderr, "[M::%s]\tw::[%d,\t%d)\n", __func__, z->w_list.a[i].x_start, z->w_list.a[i].x_end+1); + if((z->w_list.a[i].x_start==(q[1]+1)) && ((z->w_list.a[i].y_start==(t[1]+1)))) { + q[1] = z->w_list.a[i].x_end; + t[1] = z->w_list.a[i].y_end; + w[1] = i; + } else { + if(q[0] != INT32_MIN) { + ovlp_id(m) = 0; ///ovlp id + ovlp_min_wid(m) = w[0]; ///beg id of windows + ovlp_max_wid(m) = w[1]; ///end id of windows + ovlp_cur_wid(m) = w[0]; ///cur id of windows + ovlp_cur_xoff(m) = z->w_list.a[w[0]].x_start; ///cur xpos + ovlp_cur_coff(m) = 0; ///cur cigar off in cur window + ovlp_bd(m) = 0; + + is = q[0]; ie = q[1]+1; ///[is, ie) + // fprintf(stderr, "+[M::%s]\tis::%ld\tie::%ld\n", __func__, is, ie); + for (a_z = a_i; a_z >= 0; a_z--) { + as = a[a_z]>>32; ae = (uint32_t)a[a_z]; + if(ae <= is) break; + } + if(a_z < 0) a_z = 0; + for (; a_z < a_n; a_z++) { + as = a[a_z]>>32; ae = (uint32_t)a[a_z]; + os = MAX(is, as); oe = MIN(ie, ae); + ovlp = ((oe>os)? (oe-os):0); + if(ovlp) { + // fprintf(stderr, "+[M::%s]\tos::%ld\toe::%ld\n", __func__, os, oe); + err = err + extract_sub_cigar_err(z, os, oe, &m); + } + if(as >= ie) break; + } + a_i = a_z; + } + q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; + t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end; + w[0] = i; w[1] = i; + } + } + + if(q[0] != INT32_MIN) { + ovlp_id(m) = 0; ///ovlp id + ovlp_min_wid(m) = w[0]; ///beg id of windows + ovlp_max_wid(m) = w[1]; ///end id of windows + ovlp_cur_wid(m) = w[0]; ///cur id of windows + ovlp_cur_xoff(m) = z->w_list.a[w[0]].x_start; ///cur xpos + ovlp_cur_coff(m) = 0; ///cur cigar off in cur window + ovlp_bd(m) = 0; + + is = q[0]; ie = q[1]+1; + // fprintf(stderr, "-[M::%s]\tis::%ld\tie::%ld\n", __func__, is, ie); + for (a_z = a_i; a_z >= 0; a_z--) { + as = a[a_z]>>32; ae = (uint32_t)a[a_z]; + if(ae <= is) break; + } + if(a_z < 0) a_z = 0; + for (; a_z < a_n; a_z++) { + as = a[a_z]>>32; ae = (uint32_t)a[a_z]; + os = MAX(is, as); oe = MIN(ie, ae); + ovlp = ((oe>os)? (oe-os):0); + if(ovlp) { + // if(os == 22758 && oe == 22764) { + // fprintf(stderr, "-[M::%s]\tos::%ld\toe::%ld\n", __func__, os, oe); + // } + err = err + extract_sub_cigar_err(z, os, oe, &m); + } + if(as >= ie) break; + } + a_i = a_z; + } + return err; +} + +void update_masks(asg64_v *in, overlap_region *qi, overlap_region *ti, int64_t bd) +{ + uint64_t in_n0 = in->n, in_n1, k, s, e; + int64_t zwn, i, q[2], t[2]; overlap_region *z; + for (k = 0; k < in_n0; k++) { + s = in->a[k]>>32; e = (uint32_t)in->a[k]; + // fprintf(stderr, "+[M::%s]\tk::%lu\tstr::[%lu,\t%lu)\n", __func__, k, s, e); + kv_push(uint64_t, *in, s<<1); + kv_push(uint64_t, *in, (((e-1)<<1)|1)); + } + in_n1 = in->n; + + uint64_t m, start, end; int64_t dp, old_dp, dp_mask, old_dp_mask; + radix_sort_bc64(in->a+in_n0, in->a+in_n1); + for (k = in_n0, dp = start = 0; k < in_n1; k++) { + old_dp = dp; + if (in->a[k]&1) --dp; + else ++dp; + + if (old_dp < 2 && dp >= 2) {///old_dp < dp, b.a[j] is qs + start = in->a[k]>>1; + } else if (old_dp >= 2 && dp < 2){ + end = in->a[k]>>1; + if(end >= start) { + kv_push(uint64_t, *in, ((start<<32)|end));///[start, end] + // fprintf(stderr, "-[M::%s]\tmsk::[%lu,\t%lu)\n", __func__, start, end+1); + } + } + } + + for (m = 0, k = in_n1; k < in->n; k++) in->a[m++] = in->a[k]; + in->n = in_n0 = m; ///in->a[0, in_n0) includes the masked regions + + z = qi; + zwn = z->w_list.n; + if(zwn > 0) { + q[0] = q[1] = t[0] = t[1] = INT32_MIN; + for (i = 0; i < zwn; i++) { + if((z->w_list.a[i].x_start==(q[1]+1)) && ((z->w_list.a[i].y_start==(t[1]+1)))) { + q[1] = z->w_list.a[i].x_end; + t[1] = z->w_list.a[i].y_end; + } else { + if(q[0] != INT32_MIN) { + q[0] += bd; q[1] -= bd; + if(q[1] >= q[0]) {///unmasked regions + m = ((uint64_t)q[0])<<1; m <<= 32; + kv_push(uint64_t, *in, m); + m = (((uint64_t)(q[1]))<<1)+1; m <<= 32; + kv_push(uint64_t, *in, m); + // fprintf(stderr, "[M::%s]\tqstr::[%ld,\t%ld)\n", __func__, q[0], q[1]+1); + } + } + q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; + t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end; + } + } + if(q[0] != INT32_MIN) { + q[0] += bd; q[1] -= bd; + if(q[1] >= q[0]) { + m = ((uint64_t)q[0])<<1; m <<= 32; + kv_push(uint64_t, *in, m); + m = (((uint64_t)(q[1]))<<1)+1; m <<= 32; + kv_push(uint64_t, *in, m); + // fprintf(stderr, "[M::%s]\tqstr::[%ld,\t%ld)\n", __func__, q[0], q[1]+1); + } + } + } + + z = ti; + zwn = z->w_list.n; + if(zwn > 0) { + q[0] = q[1] = t[0] = t[1] = INT32_MIN; + for (i = 0; i < zwn; i++) { + if((z->w_list.a[i].x_start==(q[1]+1)) && ((z->w_list.a[i].y_start==(t[1]+1)))) { + q[1] = z->w_list.a[i].x_end; + t[1] = z->w_list.a[i].y_end; + } else { + if(q[0] != INT32_MIN) { + q[0] += bd; q[1] -= bd; + if(q[1] >= q[0]) {///unmasked regions + m = ((uint64_t)q[0])<<1; m <<= 32; + kv_push(uint64_t, *in, m); + m = (((uint64_t)(q[1]))<<1)+1; m <<= 32; + kv_push(uint64_t, *in, m); + // fprintf(stderr, "[M::%s]\ttstr::[%ld,\t%ld)\n", __func__, q[0], q[1]+1); + } + } + q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; + t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end; + } + } + if(q[0] != INT32_MIN) { + q[0] += bd; q[1] -= bd; + if(q[1] >= q[0]) { + m = ((uint64_t)q[0])<<1; m <<= 32; + kv_push(uint64_t, *in, m); + m = (((uint64_t)(q[1]))<<1)+1; m <<= 32; + kv_push(uint64_t, *in, m); + // fprintf(stderr, "[M::%s]\ttstr::[%ld,\t%ld)\n", __func__, q[0], q[1]+1); + } + } + } + + + for (k = 0; k < in_n0; k++) { + start = in->a[k]>>32; end = (uint32_t)in->a[k]; + if(end >= start) { + q[0] = start; q[1] = end; + m = ((uint64_t)q[0])<<1; m <<= 32; m |= 1; + kv_push(uint64_t, *in, m); + m = (((uint64_t)(q[1]))<<1)+1; m <<= 32; m |= 1; + kv_push(uint64_t, *in, m); + } + } + in_n1 = in->n; + + radix_sort_bc64(in->a+in_n0, in->a+in_n1);///(uint32_t)in->a[]: 0-> original; 1-> mask + for (k = in_n0, dp = old_dp = dp_mask = old_dp_mask = 0, start = 0, end = -1; k < in_n1; ++k) {///[beg, end) but coordinates in idx is [, ] + ///if idx->a.a[] is qe + old_dp = dp; old_dp_mask = dp_mask; + if ((in->a[k]>>32)&1) { + --dp; end = (in->a[k]>>33)+1; if((uint32_t)in->a[k]) dp_mask--; + }else { + //meet a new overlap; the overlaps are pushed by the x_pos_s + ++dp; end = (in->a[k]>>33); if((uint32_t)in->a[k]) dp_mask++; + } + if((end > start) && (old_dp >= 2) && old_dp_mask <= 0) { + kv_push(uint64_t, *in, ((start<<32)|end));///[start, end) + if(qi->y_id == 4 && ti->y_id == 6) { + fprintf(stderr, "[M::%s]\tout::[%ld,\t%ld)\n", __func__, start, end); + } + } + start = end; + } + + for (m = 0, k = in_n1; k < in->n; k++) in->a[m++] = in->a[k]; + in->n = in_n0 = m; +} + +int64_t cal_paired_distance(ma_ug_t *ug, overlap_region *q, overlap_region *t, ul_ov_t *a, uint32_t a_n, +asg64_v *srt, asg64_v* buf1, idx_emask_t *mm, int64_t bd) +{ + uint64_t k, cn, *qa, *ta, *ca, m, qn, tn, rev, rev_n, tl, mt, qocc, tocc, s, e; + ul_ov_t ou; memset((&ou), 0, sizeof(ou)); int64_t eq, et; + srt->n = 0; kv_resize(uint64_t, *srt, (a_n<<1)); qa = srt->a; ta = qa + a_n; + + // if(q->y_id == 4 && t->y_id == 6) { + // fprintf(stderr, "\n\n\n[M::%s]\tutg%.6u%c\tutg%.6u%c\n", __func__, q->y_id+1, "lc"[ug->u.a[q->y_id].circ], + // t->y_id+1, "lc"[ug->u.a[t->y_id].circ]); + // } + + for (k = cn = 0; k < a_n; k++) { + // if(q->y_id == 4 && t->y_id == 6) { + // fprintf(stderr, "[M::%s]\tk::%lu\n", __func__, k); + // fprintf(stderr, "au\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\tfull::%u\tis_cal::%u\n", + // a[k].qn + 1, "lc"[ug->u.a[a[k].qn].circ], ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], + // a[k].tn + 1, "lc"[ug->u.a[a[k].tn].circ], ug->u.a[a[k].tn].len, a[k].ts, a[k].te, + // a[k].el, (a[k].sec!=((uint32_t)(0x3fffffff)))?1:0); + // } + if(!cal_no_bd_coor(&(a[k]), &ou, mm, bd)) continue; + qa[cn] = (((uint64_t)ou.qs)<<32)|((uint64_t)ou.qe); + ta[cn] = (((uint64_t)ou.ts)<<32)|((uint64_t)ou.te); + cn++; + // if(q->y_id == 4 && t->y_id == 6) { + // fprintf(stderr, "ou\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\n", + // ou.qn + 1, "lc"[ug->u.a[ou.qn].circ], ug->u.a[ou.qn].len, ou.qs, ou.qe, "+-"[ou.rev], + // ou.tn + 1, "lc"[ug->u.a[ou.tn].circ], ug->u.a[ou.tn].len, ou.ts, ou.te); + // } + } + radix_sort_bc64(qa, qa+cn); ca = qa; rev = q->y_pos_strand; tl = ug->g->seq[q->y_id].len; + for (k = m = 0; k < cn; k++) { + if(m <= 0 || (((uint32_t)ca[m-1])) < (ca[k]>>32)) { + ca[m++] = ca[k]; + } else if(((uint32_t)ca[m-1]) < ((uint32_t)ca[k])) { + ca[m-1] += ((uint32_t)ca[k])-((uint32_t)ca[m-1]); + } + } + if(rev) { + rev_n = m>>1; ///tl = (tl<<32) + tl; + for (k = 0; k < rev_n; k++) { + mt = ca[k]; ca[k] = ca[m-k-1]; ca[m-k-1] = mt; + + s = tl-((uint32_t)ca[k]); e = tl-(ca[k]>>32); + ca[k] = (s<<32)|e; + s = tl-((uint32_t)ca[m-k-1]); e = tl-(ca[m-k-1]>>32); + ca[m-k-1] = (s<<32)|e; + } + if(m&1) { + s = tl-((uint32_t)ca[k]); e = tl-(ca[k]>>32); + ca[k] = (s<<32)|e; + } + } + qn = m; + // if(q->y_id == 4 && t->y_id == 6) { + // fprintf(stderr, "[M::%s]\tqn::%lu\trev::%lu\n", __func__, qn, rev); + // for (k = 0; k < qn; k++) { + // s = qa[k]>>32; e = ((uint32_t)qa[k]); + // fprintf(stderr, "[M::%s]\tqstr::[%lu,\t%lu)\n", __func__, s, e); + // } + // } + + radix_sort_bc64(ta, ta+cn); ca = ta; rev = t->y_pos_strand; tl = ug->g->seq[t->y_id].len; + for (k = m = 0; k < cn; k++) { + if(m <= 0 || (((uint32_t)ca[m-1])) < (ca[k]>>32)) { + ca[m++] = ca[k]; + } else if(((uint32_t)ca[m-1]) < ((uint32_t)ca[k])) { + ca[m-1] += ((uint32_t)ca[k])-((uint32_t)ca[m-1]); + } + } + if(rev) { + rev_n = m>>1; ///tl = (tl<<32) + tl; + for (k = 0; k < rev_n; k++) { + mt = ca[k]; ca[k] = ca[m-k-1]; ca[m-k-1] = mt; + + s = tl-((uint32_t)ca[k]); e = tl-(ca[k]>>32); + ca[k] = (s<<32)|e; + s = tl-((uint32_t)ca[m-k-1]); e = tl-(ca[m-k-1]>>32); + ca[m-k-1] = (s<<32)|e; + } + if(m&1) { + s = tl-((uint32_t)ca[k]); e = tl-(ca[k]>>32); + ca[k] = (s<<32)|e; + } + } + tn = m; + // if(q->y_id == 4 && t->y_id == 6) { + // fprintf(stderr, "[M::%s]\ttn::%lu\trev::%lu\n", __func__, tn, rev); + // for (k = 0; k < tn; k++) { + // s = ta[k]>>32; e = ((uint32_t)ta[k]); + // fprintf(stderr, "[M::%s]\ttstr::[%lu,\t%lu)\n", __func__, s, e); + // } + // } + + buf1->n = 0; qocc = tocc = 0; srt->n = 0; + if(qn > 0 && tn > 0) { + qocc = extract_xcoordates(q, qa, qn, buf1); + tocc = extract_xcoordates(t, ta, tn, buf1); + // if(q->y_id == 4 && t->y_id == 6) { + // fprintf(stderr, "[M::%s]\tqocc::%lu\ttocc::%lu\n", __func__, qocc, tocc); + // } + if((!qocc) || (!tocc)) qocc = tocc = buf1->n = 0; + } + if(!(buf1->n)) return INT32_MIN; + update_masks(buf1, q, t, bd); + + eq = et = 0; + if(buf1->n) { + eq = cal_xerr(q, buf1->a, buf1->n); + et = cal_xerr(t, buf1->a, buf1->n); + } + // if(q->y_id == 4 && t->y_id == 6) { + // s = MAX(q->x_pos_s, t->x_pos_s); + // e = MIN(q->x_pos_e, t->x_pos_e) + 1; + // buf1->n = 0; + // kv_push(uint64_t, *buf1, ((s<<32)|e)); + // fprintf(stderr, "[M::%s]\teq::%ld\tet::%ld\tbuf1->n::%u\n", __func__, eq, et, (uint32_t)buf1->n); + // eq = cal_xerr(q, buf1->a, buf1->n); et = cal_xerr(t, buf1->a, buf1->n); + // fprintf(stderr, "[M::%s]\teq1::%ld\tet1::%ld\tbuf1->n::%u\ts::%lu\te::%lu\n", + // __func__, eq, et, (uint32_t)buf1->n, s, e); + // } + + return eq - et; + // return get_pe_diff(q, qa, qn, t, ta, tn, bd); +} + +void prt_masks(ma_ug_t *ug, ul_ov_t *a, uint64_t a_n) +{ + uint64_t k; + for (k = 0; k < a_n; k++) { + fprintf(stderr, "[M::%s]\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\tfull::%u\tis_cal::%u\n", + __func__, + a[k].qn + 1, "lc"[ug->u.a[a[k].qn].circ], ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], + a[k].tn + 1, "lc"[ug->u.a[a[k].tn].circ], ug->u.a[a[k].tn].len, a[k].ts, a[k].te, + a[k].el, (a[k].sec!=((uint32_t)(0x3fffffff)))?1:0); + } +} + +uint32_t gen_mask_ovlp0(ma_ug_t *ug, overlap_region *a, uint32_t qi, uint32_t ti, kv_ul_ov_t *ov_db, kv_ul_ov_t *buf, idx_emask_t *mm, double len_diff, int64_t rlen, uint64_t ovdb_idx, asg64_v *coor_srt, +asg64_v* buf1, int64_t bd, ul_ov_t *res) +{ + ul_ov_t *ref, r0, r1; uint32_t bn = buf->n, s, e; uint64_t is_exact = 0; + overlap_region *q = &(a[qi]), *t = &(a[ti]); int64_t dd = 0; + assert(q->y_id < t->y_id); + assert(ovdb_idx < ov_db->n);///quickly jump to the related qn-tn pair ov_db[] + cal_x_ul_ovlp(ug, q, t, &r0); + r1 = r0; + r1.qn = r0.tn; r1.tn = r0.qn; + r1.qs = r0.ts; r1.qe = r0.te; + r1.ts = r0.qs; r1.te = r0.qe; + + if((ov_db->a[ovdb_idx].qn==q->y_id) && (ov_db->a[ovdb_idx].tn==t->y_id)) { + ref = &(r0); s = ovdb_idx; e = q->overlapLen+q->x_pos_strand; + if((s!=((uint32_t)-1))&&(e > s)) push_consist_ul_ovlps(ug, ov_db, s, e, len_diff, ref, mm, buf, 0, &is_exact); + + if(!is_exact) { + ref = &(r1); s = t->overlapLen; e = t->overlapLen+t->x_pos_strand; + if((s!=((uint32_t)-1))&&(e > s)) push_consist_ul_ovlps(ug, ov_db, s, e, len_diff, ref, mm, buf, 1, &is_exact); + } + } else { + assert((ov_db->a[ovdb_idx].tn==q->y_id) && (ov_db->a[ovdb_idx].qn==t->y_id)); + ref = &(r1); s = ovdb_idx; e = t->overlapLen+t->x_pos_strand; + if((s!=((uint32_t)-1))&&(e > s)) push_consist_ul_ovlps(ug, ov_db, s, e, len_diff, ref, mm, buf, 1, &is_exact); + + if(!is_exact) { + ref = &(r0); s = q->overlapLen; e = q->overlapLen+q->x_pos_strand; + if((s!=((uint32_t)-1))&&(e > s)) push_consist_ul_ovlps(ug, ov_db, s, e, len_diff, ref, mm, buf, 0, &is_exact); + } + } + // prt_masks(ug, buf->a + bn, buf->n - bn); + ///p->qn/p->tn:: id within the ol->list + ///p->el:: if equally best + ///p->qs:: err(query)-err(target) + ///p->ts:: err(target)-err(query) + ref = &(r0); + res->qn = qi; res->tn = ti; + res->el = 1; res->qs = res->ts = 0; + if(!is_exact) { + assert(buf->n > bn); + dd = cal_paired_distance(ug, q, t, buf->a + bn, buf->n - bn, coor_srt, buf1, mm, bd); + if(dd != 0) { + res->el = 0; + if(dd > 0) {///q has more error than t + res->qs = dd; res->ts = 0; + } else { + res->qs = 0; res->ts = -dd; + } + } + } + buf->n = bn; + if(dd!=INT32_MIN) return 1; + return 0; +} + +uint64_t if_direct_mask(const ul_idx_t *uref, const ug_opt_t *uopt, ul_ov_t *p, ul_ov_t *q, uint64_t bw, double len_diff) +{ + ul_ov_t *li, *lj; uint64_t os, oe, ovlp; + if(p->qe > q->qe) li = p, lj = q; + else if(p->qe == q->qe && p->qs >= q->qs) li = p, lj = q; + else lj = p, li = q; + os = MAX(li->qs, lj->qs), oe = MIN(li->qe, lj->qe); + ovlp = ((oe > os)? (oe - os):0); + if(!ovlp) return 0;//no overlap + + if(lj->qs <= li->qs+G_CHAIN_INDEL) { + if(govlp_check(uref, uopt, bw, len_diff, li, lj)) return 1; + } else if((lj->qe+G_CHAIN_INDEL>=li->qe) && (lj->qs+G_CHAIN_INDEL>=li->qs)) { + if(govlp_check(uref, uopt, bw, len_diff, lj, li)) return 1; + } + return 0; +} + +uint64_t mask_ovlps(const ul_idx_t *uref, const ug_opt_t *uopt, ma_ug_t *ug, overlap_region_alloc* ol, mask_ul_ov_t *mk, kv_ul_ov_t *ov_db, asg64_v *coor_srt, asg64_v* buf1, idx_emask_t *mm, double len_diff, uint64_t rlen, int64_t bd) +{ + mk->srt.n = mk->idx.n = 0; + int64_t k, m, i, osrt_n, osrt_n1, on = ol->length; uint64_t wt, w[2], is_exact, sid, tot, tol, qi, ti; + overlap_region *z; ul_ov_t ou; kv_ul_ov_t *osrt = &(mk->srt); ul_ov_t p, q; + for (k = osrt->n = 0; k < on; k++) { + z = &(ol->list[k]); if(!(z->x_pos_strand)) continue;///x_pos_strand: how many masks + if(gen_aln_ul_ov_t(k, ug->g->seq[z->y_id].len, z, &ou)) { + kv_push(ul_ov_t, *osrt, ou); + } + } + if(!(osrt->n)) return 0; + + osrt_n = osrt->n; memset(&ou, 0, sizeof(ou)); + radix_sort_uov_srt_qs(osrt->a, osrt->a+osrt->n); ///sort by qs; for quick filtering between overlaps + for (k = tot = tol = 0; k < osrt_n; k++) { + tol += osrt->a[k].qe-osrt->a[k].qs; + convert_ul_ov_t(&p, &(ol->list[osrt->a[k].qn]), ug); p.qn = osrt->a[k].qn; + for (i = k+1; i < osrt_n && osrt->a[i].qs < osrt->a[k].qe; i++) { + ///for a pair of overlap, only need to calculate it in one side + if(ol->list[osrt->a[i].qn].y_id >= ol->list[osrt->a[k].qn].y_id) continue; + is_exact = 0; sid = (uint32_t)-1; + convert_ul_ov_t(&q, &(ol->list[osrt->a[i].qn]), ug); q.qn = osrt->a[i].qn; + if(if_direct_mask(uref, uopt, &p, &q, 16, len_diff)) is_exact = 1; + if((!is_exact) && (!check_mask_exist(ug, &(ol->list[osrt->a[i].qn]), &(ol->list[osrt->a[k].qn]), ov_db, mm, len_diff, &is_exact, &sid))) { + continue; + } + + if(is_exact) {///if two overlaps are exactly the same; no need to do anything + ou.qs = 0; ou.qe = sid; ou.ts = ou.te = 0; ou.el = 1; + } else { + w[0] = ol->list[osrt->a[k].qn].non_homopolymer_errors; + w[1] = ol->list[osrt->a[i].qn].non_homopolymer_errors; + wt = w[0] + w[1] + ((w[0]>=w[1])?(w[0]-w[1]):(w[1]-w[0])); + if(wt > (uint32_t)-1) wt = (uint32_t)-1; + //qs: weight; qe: idx with in ov_db; el: exact match? + ou.qs = wt; ou.qe = sid; ou.el = 0; + ou.ts = osrt->a[i].qe-osrt->a[i].qs; + ou.te = osrt->a[k].qe-osrt->a[k].qs; + } + ou.qn = osrt->a[i].qn; ou.tn = osrt->a[k].qn;///id of the ol->list, instead of real yid + tot += ou.ts + ou.te; + kv_push(ul_ov_t, *osrt, ou); + } + for (i = k-1; i >= 0; i--) { + ///for a pair of overlap, only need to calculate it in one side + if(ol->list[osrt->a[i].qn].y_id >= ol->list[osrt->a[k].qn].y_id) continue; + is_exact = 0; sid = (uint32_t)-1; + convert_ul_ov_t(&q, &(ol->list[osrt->a[i].qn]), ug); q.qn = osrt->a[i].qn; + if(if_direct_mask(uref, uopt, &p, &q, 16, len_diff)) is_exact = 1; + if((!is_exact) && (!check_mask_exist(ug, &(ol->list[osrt->a[i].qn]), &(ol->list[osrt->a[k].qn]), ov_db, mm, len_diff, &is_exact, &sid))) { + continue; + } + + if(is_exact) { + ou.qs = 0; ou.qe = sid; ou.ts = ou.te = 0; ou.el = 1; + } else { + w[0] = ol->list[osrt->a[k].qn].non_homopolymer_errors; + w[1] = ol->list[osrt->a[i].qn].non_homopolymer_errors; + wt = w[0] + w[1] + ((w[0]>=w[1])?(w[0]-w[1]):(w[1]-w[0])); + if(wt > (uint32_t)-1) wt = (uint32_t)-1; + ou.qs = wt; ou.qe = sid; ou.el = 0; + ou.ts = osrt->a[i].qe-osrt->a[i].qs; + ou.te = osrt->a[k].qe-osrt->a[k].qs; + } + ou.qn = osrt->a[i].qn; ou.tn = osrt->a[k].qn;///id of the ol->list, instead of real yid + tot += ou.ts + ou.te; + kv_push(ul_ov_t, *osrt, ou); + } + } + + // fprintf(stderr, "0[M::%s]\tosrt_n::%u\tosrt->n::%u\n", __func__, (uint32_t)osrt_n, (uint32_t)osrt->n); + + if((tot > (rlen*256)) && (tot > (tol*32))) { + tot = MAX((rlen*256), (tol*32)); osrt_n1 = osrt->n; + radix_sort_uov_srt_qs(osrt->a+osrt_n, osrt->a+osrt->n); ///sort by weight (qs) + for (k = osrt_n, wt = 0; k < osrt_n1 && wt <= tot; k++) { + if(osrt->a[k].el) continue;///exact match, no additional work + wt += (uint64_t)osrt->a[k].ts + (uint64_t)osrt->a[k].te; + } + osrt->n = k; + } + + memset(&ou, 0, sizeof(ou)); osrt_n1 = osrt->n; + ///note: osrt will be updated here, so do not use the address within osrt + for (k = osrt_n, m = 0; k < osrt_n1; k++) { + qi = osrt->a[k].qn; ti = osrt->a[k].tn; ///represent a pair of read ol->list[qi] <-> ol->list[ti] + sid = osrt->a[k].qe; wt = 1; + ///p->qn/p->tn:: id within the ol->list + ///p->el:: if equally best + ///p->qs:: err(query)-err(target) + ///p->ts:: err(target)-err(query) + if(osrt->a[k].el) {///exact match; no need base-check + ou.qn = qi; ou.tn = ti; ou.el = 1; ou.qs = ou.ts = 0; + } else {///do base-check + wt = gen_mask_ovlp0(ug, ol->list, qi, ti, ov_db, osrt, mm, len_diff, rlen, sid, coor_srt, buf1, bd, &(ou)); + } + if(wt) { + osrt->a[m++] = ou; + // fprintf(stderr, "[M::%s]\tutg%.6u%c\tqerr::%u\t\tutg%.6u%c\tterr::%u\tel::%u\n", + // __func__, ol->list[ou.qn].y_id+1, "lc"[ug->u.a[ol->list[ou.qn].y_id].circ], ou.qs, + // ol->list[ou.tn].y_id+1, "lc"[ug->u.a[ol->list[ou.tn].y_id].circ], ou.ts, ou.el); + } + } + osrt->n = m; + if(!(osrt->n)) return 0; + + ///double + ///p->qn/p->tn:: id within the ol->list + ///p->el:: if equally best + ///p->qs:: err(query)-err(target) + ///p->ts:: err(target)-err(query) + kv_resize(ul_ov_t, *osrt, (osrt->n<<1)); + memcpy(osrt->a+osrt->n, osrt->a, (sizeof((*(osrt->a)))*osrt->n)); + osrt_n = osrt->n; osrt->n <<= 1; osrt_n1 = osrt->n; + for (k = osrt_n; k < osrt_n1; k++) { + m = osrt->a[k].qn; osrt->a[k].qn = osrt->a[k].tn; osrt->a[k].tn = m; + m = osrt->a[k].qs; osrt->a[k].qs = osrt->a[k].ts; osrt->a[k].ts = m; + } + + ///osrt = &(mk->srt); + radix_sort_ul_ov_srt_qn1(osrt->a, osrt->a+osrt->n); + kv_resize(uint64_t, mk->idx, ol->length); mk->idx.n = ol->length; + memset(mk->idx.a, 0, sizeof((*(mk->idx.a)))*ol->length); + for (k = 1, i = 0; k <= osrt_n1; k++) { + if(k == osrt_n1 || osrt->a[i].qn != osrt->a[k].qn) { + if(k - i > 1) radix_sort_ul_ov_srt_tn1(osrt->a+i, osrt->a+k); + mk->idx.a[osrt->a[i].qn] = (((uint64_t)i)<<32)|((uint64_t)k); + i = k; + } + } + + return 1; +} + +void refine_rphase_back(overlap_region *za, uint64_t zid, ul_ov_t *a, uint64_t a_n, asg64_v *buf) +{ + uint64_t k, bn, qs, qe, err, zs, ze, zerr, m, zwn; overlap_region *z; window_list *p; + kv_resize(uint64_t, *buf, a_n); + for (k = buf->n = 0; k < a_n; k++) { + if(a[k].qs > 0) {//za[zid] has higher error rate + // buf->a[buf->n++] = (((uint64_t)za[a[k].tn].x_pos_s)<<32)|((uint64_t)a[k].tn); + buf->a[buf->n++] = (((uint64_t)za[a[k].tn].x_pos_s)<<32)|(k); + } + } + radix_sort_bc64(buf->a, buf->a+buf->n); + + bn = buf->n; + for (k = 0; k < bn; k++) { + qs = qe = err = 0; + if(buf->n > bn) { + qs = buf->a[buf->n-2]>>32; + qe = ((uint32_t)buf->a[buf->n-2]); + err = buf->a[buf->n-1]; + } + zs = MIN(za[a[((uint64_t)buf->a[k])].tn].x_pos_s, za[zid].x_pos_s); + ze = MAX(za[a[((uint64_t)buf->a[k])].tn].x_pos_e, za[zid].x_pos_e) + 1; + if(ze <= zs) continue; + zerr = a[((uint64_t)buf->a[k])].qs; + if(qe <= zs) { + kv_push(uint64_t, *buf, ((zs<<32)|ze)); + kv_push(uint64_t, *buf, zerr); + } else { + if(ze > qe) qe = ze; + if(zerr > err) err = zerr; + buf->a[buf->n-2] = ((qs<<32)|(qe)); + buf->a[buf->n-1] = err; + } + } + + for (k = bn, m = 0; k < buf->n; k++) buf->a[m++] = buf->a[k]; + buf->n = m; + if(!(buf->n)) return; + + z = &(za[zid]); + for (k = 0; k < z->align_length; k++) { + p = &(z->w_list.a[z->w_list.n+k]); + if(p->clen <= 0) continue; + zs = p->x_start; ze = p->x_end; ///note here is [p->x_start, p->x_end) + zerr = p->clen; + + kv_push(uint64_t, *buf, ((zs<<32)|ze)); + kv_push(uint64_t, *buf, zerr); + } + + bn = buf->n; kv_resize(uint64_t, *buf, (bn + (bn>>1))); + for (k = 0; k < bn; k+=2) { + zs = buf->a[k]>>32; zs <<= 32; zs |= k; + kv_push(uint64_t, *buf, zs); + } + + uint64_t *wa = buf->a + bn, wan = buf->n - bn; + radix_sort_bc64(wa, wa + wan); + z->x_pos_strand = (uint32_t)-1; + z->w_list.n = 0; + + for (k = 0; k < wan; k++) { + qs = qe = z->x_pos_s; err = 0; + if(z->w_list.n) { + qs = z->w_list.a[z->w_list.n-1].x_start; + qe = z->w_list.a[z->w_list.n-1].x_end; + err = z->w_list.a[z->w_list.n-1].clen; + } + + zs = buf->a[((uint64_t)wa[k])]>>32; + ze = (uint32_t)(buf->a[((uint64_t)wa[k])]); + zerr = buf->a[((uint64_t)wa[k])+1]; + + if(qe <= zs) { + if(qe < zs) { + kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); + p->clen = 0; p->x_start = qe; p->x_end = zs; + } + kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); + p->clen = zerr; p->x_start = zs; p->x_end = ze; + } else { + if(ze > qe) qe = ze; + if(zerr > err) err = zerr; + p = &(z->w_list.a[z->w_list.n-1]); + p->clen = err; + p->x_start = qs; + p->x_end = qe; + } + } + + + qs = qe = z->x_pos_s; zs = z->x_pos_e + 1; + if(z->w_list.n) { + qs = z->w_list.a[z->w_list.n-1].x_start; + qe = z->w_list.a[z->w_list.n-1].x_end; + } + if(qe < zs) { + kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); + p->clen = 0; p->x_start = qe; p->x_end = zs; + } + + z->x_pos_strand = (uint32_t)-1; + z->overlapLen = z->x_pos_e+1-z->x_pos_s; + z->non_homopolymer_errors = 0; zwn = 0; + for (k = 0; k < z->w_list.n; k++) { + if(z->w_list.a[k].clen > 0) { + z->non_homopolymer_errors += z->w_list.a[k].clen; + zwn += z->w_list.a[k].x_end-z->w_list.a[k].x_start; + } + } + assert(zwn <= z->overlapLen);///zwn is the length with secondary-best alignment + z->align_length = z->overlapLen - zwn; +} + +inline void push_rphase(overlap_region *z, uint64_t zs, uint64_t ze, uint64_t zerr, uint64_t is_pri) +{ + uint64_t pe, p_pri; window_list *p; + pe = z->x_pos_s; p_pri = 0; + if(z->w_list.n) { + pe = z->w_list.a[z->w_list.n-1].x_end; + p_pri = z->w_list.a[z->w_list.n-1].cidx; + } + + // fprintf(stderr, "+[M::%s] zs::%lu, ze::%lu, zerr::%lu, pe::%lu, is_pri::%lu, p_pri::%lu, wn::%u\n", + // __func__, zs, ze, zerr, pe, is_pri, p_pri, (uint32_t)z->w_list.n); + + if(pe <= zs) {///not overlap with [zs, ze) + if(pe < zs) { + kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); + p->clen = 0; p->x_start = pe; p->x_end = zs; p->cidx = 0; + } + kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); + p->clen = zerr; p->x_start = zs; p->x_end = ze; p->cidx = is_pri; + } else { + if(pe <= ze) {///prefix-suffix overlap + if(is_pri) { + if(p_pri) { + kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); + p->clen = zerr; p->cidx = is_pri; + p->x_start = zs; p->x_end = ze; + z->w_list.a[z->w_list.n-2].x_end = zs;///trim the previous primary window + } else { + p = &(z->w_list.a[z->w_list.n-1]); + p->clen = zerr; p->cidx = is_pri; + p->x_end = ze; + } + } else {///if current is not primary + p = &(z->w_list.a[z->w_list.n-1]); + p->x_end = ze; + } + } else {//pe > ze; [zs, ze) is contained within [ps, pe) + if(is_pri) {///is_pri == 0, no need to do anything + if(!p_pri) { + p = &(z->w_list.a[z->w_list.n-1]); + p->clen = zerr; p->cidx = is_pri; + } else { + kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); + p->clen = zerr; p->cidx = is_pri; + p->x_start = zs; p->x_end = z->w_list.a[z->w_list.n-2].x_end; + z->w_list.a[z->w_list.n-2].x_end = zs;///trim the previous primary window + } + } + } + } + // fprintf(stderr, "-[M::%s] zs::%lu, ze::%lu, zerr::%lu, pe::%lu, is_pri::%lu, p_pri::%lu, wn::%u, x::[%d, %d), sec::%u\n", + // __func__, zs, ze, zerr, pe, is_pri, p_pri, (uint32_t)z->w_list.n, + // z->w_list.a[z->w_list.n-1].x_start, z->w_list.a[z->w_list.n-1].x_end, z->w_list.a[z->w_list.n-1].clen); +} + +void refine_rphase(ma_ug_t *ug, int64_t rlen, overlap_region *za, uint64_t zan, uint64_t zid, ul_ov_t *a, uint64_t a_n, asg64_v *buf) +{ + // fprintf(stderr, "\n[M::%s] zid::%lu, x::[%u, %u), zan::%lu, a_n::%lu\n", + // __func__, zid, za[zid].x_pos_s, za[zid].x_pos_e+1, zan, a_n); + uint64_t k, bn, qs, qe, err, zs, ze, zerr, m, zwn; overlap_region *z; window_list *p; + kv_resize(uint64_t, *buf, a_n); + for (k = buf->n = 0; k < a_n; k++) { + if(a[k].qs > 0) {//za[zid] has higher error rate + // buf->a[buf->n++] = (((uint64_t)za[a[k].tn].x_pos_s)<<32)|((uint64_t)a[k].tn); + // fprintf(stderr, "+[M::%s] k::%lu, err::%u, x::[%u, %u)\n", __func__, k, a[k].qs, za[a[k].tn].x_pos_s, za[a[k].tn].x_pos_e+1); + buf->a[buf->n++] = (((uint64_t)za[a[k].tn].x_pos_s)<<32)|(k); + } + } + radix_sort_bc64(buf->a, buf->a+buf->n); + + bn = buf->n; + for (k = 0; k < bn; k++) { + qs = qe = err = 0; + if(buf->n > bn) { + qs = buf->a[buf->n-2]>>32; + qe = ((uint32_t)buf->a[buf->n-2]); + err = buf->a[buf->n-1]; + } + zs = MAX(za[a[((uint32_t)buf->a[k])].tn].x_pos_s, za[zid].x_pos_s); + ze = MIN(za[a[((uint32_t)buf->a[k])].tn].x_pos_e, za[zid].x_pos_e) + 1; + if(ze <= zs) continue; + zerr = a[((uint32_t)buf->a[k])].qs; + // fprintf(stderr, "-[M::%s] k::%lu, z::[%u, %u), zerr::%lu\n", __func__, k, zs, ze, zerr); + if(qe <= zs) { + kv_push(uint64_t, *buf, ((zs<<32)|ze)); + kv_push(uint64_t, *buf, zerr); + } else { + if(ze > qe) qe = ze; + if(zerr > err) err = zerr; + buf->a[buf->n-2] = ((qs<<32)|(qe)); + buf->a[buf->n-1] = err; + } + } + + for (k = bn, m = 0; k < buf->n; k++) buf->a[m++] = buf->a[k]; + buf->n = m; + if(!(buf->n)) return; + + z = &(za[zid]); + for (k = 0; k < z->align_length; k++) { + p = &(z->w_list.a[z->w_list.n+k]); + if(p->clen <= 0) continue; + zs = p->x_start; ze = p->x_end; ///note here is [p->x_start, p->x_end) + zerr = p->clen; + // fprintf(stderr, ">[M::%s] k::%lu, z::[%u, %u), zerr::%lu\n", __func__, k, zs, ze, zerr); + kv_push(uint64_t, *buf, ((zs<<32)|ze)); + kv_push(uint64_t, *buf, zerr); + } + + uint64_t *ref, ref_n, ref_i, *qry, qry_n, qry_i; + ref = buf->a; ref_n = m; + qry = ref + ref_n; qry_n = buf->n - ref_n; + ref_i = qry_i = z->w_list.n = 0; + // fprintf(stderr, "[M::%s] ref_n::%lu, qry_n::%lu\n", __func__, ref_n, qry_n); + ///all ref and qry are regions with at least one error + while (ref_i < ref_n && qry_i < qry_n) { + if((ref[ref_i]>>32) < (qry[qry_i]>>32)) { + push_rphase(z, ref[ref_i]>>32, (uint32_t)ref[ref_i], ref[ref_i+1], 0); + ref_i += 2; + } else if((qry[qry_i]>>32) < (ref[ref_i]>>32)) { + push_rphase(z, qry[qry_i]>>32, (uint32_t)qry[qry_i], qry[qry_i+1], 1); + qry_i += 2; + } else { + push_rphase(z, qry[qry_i]>>32, (uint32_t)qry[qry_i], qry[qry_i+1], 1); + qry_i += 2; + } + } + + while(qry_i < qry_n) { + push_rphase(z, qry[qry_i]>>32, (uint32_t)qry[qry_i], qry[qry_i+1], 1); + qry_i += 2; + } + + while(ref_i < ref_n) { + push_rphase(z, ref[ref_i]>>32, (uint32_t)ref[ref_i], ref[ref_i+1], 0); + ref_i += 2; + } + + ///push remaining bases as the last window + qs = qe = z->x_pos_s; zs = z->x_pos_e + 1; + if(z->w_list.n) { + qs = z->w_list.a[z->w_list.n-1].x_start; + qe = z->w_list.a[z->w_list.n-1].x_end; + } + if(qe < zs) { + kv_pushp(window_list, z->w_list, &p); memset(p, 0, sizeof((*p))); + p->clen = 0; p->x_start = qe; p->x_end = zs; + } + + + z->x_pos_strand = (uint32_t)-1; + z->overlapLen = z->x_pos_e+1-z->x_pos_s; + z->non_homopolymer_errors = 0; zwn = 0; + for (k = m = 0; k < z->w_list.n; k++) { + if(z->w_list.a[k].clen > 0) { + z->non_homopolymer_errors += z->w_list.a[k].clen; + zwn += z->w_list.a[k].x_end-z->w_list.a[k].x_start; + } + z->w_list.a[k].cidx = 0; m += z->w_list.a[k].x_end-z->w_list.a[k].x_start; + } + // fprintf(stderr, "[M::%s] m:%lu, z->overlapLen:%lu\n", __func__, m, z->overlapLen); + assert(m == z->overlapLen); + // assert(zwn <= z->overlapLen);///zwn is the length with secondary-best alignment + z->align_length = z->overlapLen - zwn; + + // fprintf(stderr, ">[M::%s]\tutg%.6u%c\txl::%ld\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\tsec_len::%lu\n", + // __func__, z->y_id + 1, "lc"[ug->u.a[z->y_id].circ], + // rlen, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + // ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors, zwn); +} + +void rphase_hl(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, asg64_v* buf1, int64_t ulid, int64_t bd, +int64_t rlen, mask_ul_ov_t *mk, idx_emask_t *mm, double len_diff) +{ + uint64_t on0 = ol->length, k, i, l, m0, m1, sec, zwn, m, mmov; + overlap_region *z, h; ma_ug_t *ug = uref->ug; + + for (k = i = 0; k < ol->length; k++) { + z = &(ol->list[k]); + z->align_length = 0; + z->non_homopolymer_errors = 0; + z->overlapLen = (uint32_t)-1; + z->x_pos_strand = 0; + // fprintf(stderr, "i[M::%s]\tutg%.6u%c\txl::%ld\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\n", + // __func__, z->y_id + 1, "lc"[ug->u.a[z->y_id].circ], + // rlen, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + // ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors); + if(!(z->w_list.n)) continue;///no base-level; cis + if(k != i) { + h = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = h; + } + i++; + } + ol->length = i; ///[ol->length, on0) keeps cis overlaps without the base-level alignment + + rphase_rr(ol, uref, uopt, c_idx, idx, buf, ulid, bd, NULL); + ///could use idx && buf here + for (k = idx->n = buf->n = 0; k < ol->length; k++) { + z = &(ol->list[k]); + ///sort overlaps by sec error + for (i = sec = 0; i < z->align_length; i++) { + sec += z->w_list.a[z->w_list.n+i].clen; + } + z->non_homopolymer_errors = sec; sec = sec - (sec&3);///normalize by 4 + kv_push(uint64_t, *buf, (((uint64_t)sec)<<32)|((uint64_t)k)); + + ///sort overlaps by yid for filtering + kv_push(uint64_t, *idx, (((uint64_t)z->y_id)<<32)|((uint64_t)k)); + + // fprintf(stderr, "+[M::%s]\tutg%.6u%c\txl::%ld\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\tn_sec::%lu\n", + // __func__, z->y_id + 1, "lc"[ug->u.a[z->y_id].circ], + // rlen, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + // ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors, sec); + } + radix_sort_bc64(idx->a, idx->a+idx->n); ///for filtering + + radix_sort_bc64(buf->a, buf->a+buf->n);///sort by error; smaller error first + for (l = 0, k = 1; k <= buf->n; k++) { + if(k == buf->n || (buf->a[l]>>32) == (buf->a[k]>>32)) {///with equal number of normalized errors + if(((k - l) > 1) && (k < buf->n)) { + for (i = l; i < k; i++) { + // fprintf(stderr, "[M::%s]\tl::%lu\tk::%lu\tbuf->a[i]>>32::%lu\n", __func__, l, k, buf->a[i]>>32); + z = &(ol->list[(uint32_t)buf->a[i]]); + m0 = z->x_pos_e+1-z->x_pos_s; + m1 = z->y_pos_e+1-z->y_pos_s; + sec = MIN(m0, m1); sec = ((uint32_t)-1)-((uint32_t)sec); + buf->a[i] = (((uint64_t)sec)<<32)|((uint32_t)buf->a[i]); + } + radix_sort_bc64(buf->a+l, buf->a+k);///sort by lenght; longer first + } + l = k; + } + } + + mk->idx.n = mk->srt.n = 0; c_idx->n = 0; + mmov = 1000000; if(mmov > (ol->length*32)) mmov = (ol->length*32); + for (k = 0; k < buf->n && c_idx->n <= mmov; k++) {///need to add overlap that directly connected in the graph + z = &(ol->list[(uint32_t)buf->a[k]]); z->overlapLen = c_idx->n; + + // fprintf(stderr, "\n-[M::%s]\tutg%.6u%c\txl::%ld\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\n", + // __func__, z->y_id + 1, "lc"[ug->u.a[z->y_id].circ], + // rlen, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + // ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors); + + m0 = push_emask_flt(&(mm->a[z->y_id]), idx->a, idx->n, z->y_id, c_idx); + + + // fprintf(stderr, "-[M::%s]\tm0::%lu\n", __func__, m0); + // prt_masks(ug, c_idx->a+c_idx->n-m0, m0); + + + m1 = gen_src_shared_interval_simple(z->y_id, ug, idx->a, idx->n, c_idx); + + + // fprintf(stderr, "-[M::%s]\tm1::%lu\n", __func__, m1); + // prt_masks(ug, c_idx->a+c_idx->n-m1, m1); + + + dedup_src_shared1(ug, c_idx, m0, m1, mm); + z->x_pos_strand = c_idx->n - z->overlapLen; + if(!(z->x_pos_strand)) z->overlapLen = (uint32_t)-1; + + // fprintf(stderr, "-[M::%s]\tutg%.6u%c\txl::%ld\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\tm0::%lu\tm1::%lu\tcan_n::%u\n", + // __func__, z->y_id + 1, "lc"[ug->u.a[z->y_id].circ], + // rlen, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + // ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors, m0, m1, z->x_pos_strand); + // fprintf(stderr, "-[M::%s]\tcan_n::%u\n", __func__, z->x_pos_strand); + // if(z->x_pos_strand) prt_masks(ug, c_idx->a+z->overlapLen, z->x_pos_strand); + } + + ///if no mask overlaps, some overlaps may be still masked using the overlap within the graph + if(((c_idx->n) || (ol->length > 1)) && mask_ovlps(uref, uopt, ug, ol, mk, c_idx, idx, buf1, mm, len_diff, rlen, bd)) { + // for (k = 0; k < mk->srt.n; k++) { + // fprintf(stderr, "*[M::%s]\tutg%.6u%c\txl::%u\tqerr::%u\t%c\tutg%.6u%c\tyl::%u\tterr::%u\tel::%u\n", + // __func__, + // ol->list[mk->srt.a[k].qn].y_id + 1, "lc"[ug->u.a[ol->list[mk->srt.a[k].qn].y_id].circ], + // ug->u.a[ol->list[mk->srt.a[k].qn].y_id].len, mk->srt.a[k].qs, + // "+-"[mk->srt.a[k].rev], + // ol->list[mk->srt.a[k].tn].y_id + 1, "lc"[ug->u.a[ol->list[mk->srt.a[k].tn].y_id].circ], + // ug->u.a[ol->list[mk->srt.a[k].tn].y_id].len, mk->srt.a[k].ts, + // mk->srt.a[k].el); + // } + + + + rphase_rr(ol, uref, uopt, c_idx, idx, buf, ulid, bd, mk); + for (k = 0; k < ol->length; k++) { + if(((uint32_t)mk->idx.a[k]) > (mk->idx.a[k]>>32)) {///it has masks + refine_rphase(ug, rlen, ol->list, ol->length, k, mk->srt.a+(mk->idx.a[k]>>32), ((uint32_t)mk->idx.a[k])-(mk->idx.a[k]>>32), idx); + } + } + } + // assert(on0 <= ol->length); + ol->length = on0; + + for (k = 0; k < ol->length; k++) { + z = &(ol->list[k]); + if(z->x_pos_strand == (uint32_t)-1) { + // fprintf(stderr, ">[M::%s]\tutg%.6u%c\txl::%ld\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\n", + // __func__, z->y_id + 1, "lc"[ug->u.a[z->y_id].circ], + // rlen, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + // ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors); + + z->x_pos_strand = 0; continue; + } + z->overlapLen = z->x_pos_e+1-z->x_pos_s; + z->non_homopolymer_errors = 0; zwn = 0; + for (i = m = 0; i < z->align_length; i++) { + z->w_list.a[m] = z->w_list.a[z->w_list.n+i]; + if(z->w_list.a[m].clen > 0) { + z->non_homopolymer_errors += z->w_list.a[m].clen; + zwn += z->w_list.a[m].x_end-z->w_list.a[m].x_start; + } + m++; + } + z->w_list.n = m; z->x_pos_strand = 0; + assert(zwn <= z->overlapLen);///zwn is the length with secondary-best alignment + z->align_length = z->overlapLen - zwn; + + // fprintf(stderr, ">[M::%s]\tutg%.6u%c\txl::%ld\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\tsec_len::%lu\n", + // __func__, z->y_id + 1, "lc"[ug->u.a[z->y_id].circ], + // rlen, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + // ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors, zwn); + } +} + +uint64_t rphase_detect0(overlap_region_alloc* ol, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, asg64_v* suf) +{ + uint64_t srt_n = idx->n, i, k, h, qs, qe, ts, te, rr = 0, ovlp; overlap_region *z, *p; + int64_t dp, old_dp, beg, end; + for (i = k = 0, dp = old_dp = 0, beg = 0, end = -1; i < srt_n; ++i) {///[beg, end) but coordinates in idx is [, ] + ///if idx->a.a[] is qe + old_dp = dp; + if ((idx->a[i]>>32)&1) { + --dp; end = (idx->a[i]>>33)+1; + }else { + //meet a new overlap; the overlaps are pushed by the x_pos_s + ++dp; end = (idx->a[i]>>33); + kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); + } + // fprintf(stderr, "\n[M::%s::] beg::%ld, end::%ld, old_dp::%ld\n", __func__, beg, end, old_dp); + if((end > beg) && (old_dp >= 2)) { + // fprintf(stderr, "\n[M::%s::] beg::%ld, end::%ld, old_dp::%ld\n", __func__, beg, end, old_dp); + // kv_resize(uint64_t, *buf, ((uint32_t)old_dp)<<1); + // idx->n = srt_n + gen_region_phase(ol->list, idx->a+srt_n, idx->n-srt_n, beg, end, old_dp, c_idx->a, buf, buf1); + idx->n = srt_n + gen_region_phase_robust(ol->list, idx->a+srt_n, idx->n-srt_n, beg, end, old_dp, c_idx->a, buf); + } + beg = end; + } + idx->n = srt_n; + + suf->n = 0; kv_resize(uint64_t, *suf, (ol->length<<1)); + uint64_t *sep = suf->a, *sid = suf->a + ol->length, sid_n; + for (k = h = sid_n = 0; k < ol->length; k++) { + z = &(ol->list[k]); + z->overlapLen = (uint32_t)-1; z->non_homopolymer_errors = 0; + for (i = 0; i < z->align_length; i++) { + z->non_homopolymer_errors += z->w_list.a[z->w_list.n+i].clen; + } + for (; h < c_idx->n && ovlp_id(c_idx->a[h]) < k; h++); + if(h < c_idx->n && ovlp_id(c_idx->a[h]) == k) { + qs = z->w_list.a[ovlp_min_wid(c_idx->a[h])].x_start; + qe = z->w_list.a[ovlp_max_wid(c_idx->a[h])].x_end+1; + for (; h < c_idx->n && ovlp_id(c_idx->a[h]) == k; h++) { + qe = z->w_list.a[ovlp_max_wid(c_idx->a[h])].x_end+1; + } + sid[sid_n] = ((qs<<32)|sid_n); + sep[sid_n] = ((k<<32)|qe); + sid_n++; + // kv_push(uint64_t, *suf, ((qs<<32)|h)); + } + } + radix_sort_bc64(sid, sid+sid_n); + for (k = 0; k < sid_n; k++) { + qs = sid[k]>>32; qe = ((uint32_t)sep[(uint32_t)sid[k]]); + z = &(ol->list[sep[(uint32_t)sid[k]]>>32]); + if(z->non_homopolymer_errors == 0) continue; + for (i = rr = 0; i < sid_n; i++) { + ts = sid[i]>>32; te = ((uint32_t)sep[(uint32_t)sid[i]]); + p = &(ol->list[sep[(uint32_t)sid[i]]>>32]); + if(ts >= qe) break; + if(te <= qs) continue; + ovlp = ((MIN(qe, te) > MAX(qs, ts))? (MIN(qe, te) - MAX(qs, ts)):0); + if(ovlp < 512) continue; + if(z->non_homopolymer_errors > p->non_homopolymer_errors + rphase_thres) continue; + rr = 1; break; + } + if(rr) z->overlapLen = 1; + } + return rr; +} + +void reacal_phase(overlap_region_alloc* ol, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, asg64_v* suf) +{ + uint64_t srt_n = idx->n, i, k, h, qs, qe, ts, te, rr = 0; overlap_region *z, *p; + int64_t dp, old_dp, beg, end; + for (i = k = 0, dp = old_dp = 0, beg = 0, end = -1; i < srt_n; ++i) {///[beg, end) but coordinates in idx is [, ] + ///if idx->a.a[] is qe + old_dp = dp; + if ((idx->a[i]>>32)&1) { + --dp; end = (idx->a[i]>>33)+1; + }else { + //meet a new overlap; the overlaps are pushed by the x_pos_s + ++dp; end = (idx->a[i]>>33); + kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); + } + // fprintf(stderr, "\n[M::%s::] beg::%ld, end::%ld, old_dp::%ld\n", __func__, beg, end, old_dp); + if((end > beg) && (old_dp >= 2)) { + // fprintf(stderr, "\n[M::%s::] beg::%ld, end::%ld, old_dp::%ld\n", __func__, beg, end, old_dp); + // kv_resize(uint64_t, *buf, ((uint32_t)old_dp)<<1); + // idx->n = srt_n + gen_region_phase(ol->list, idx->a+srt_n, idx->n-srt_n, beg, end, old_dp, c_idx->a, buf, buf1); + idx->n = srt_n + gen_region_phase_robust(ol->list, idx->a+srt_n, idx->n-srt_n, beg, end, old_dp, c_idx->a, buf); + } + beg = end; + } + idx->n = srt_n; + + suf->n = 0; kv_resize(uint64_t, *suf, (ol->length<<1)); + uint64_t *sep = suf->a, *sid = suf->a + ol->length, sid_n; + for (k = h = sid_n = 0; k < ol->length; k++) { + z = &(ol->list[k]); + z->overlapLen = (uint32_t)-1; z->non_homopolymer_errors = 0; + for (i = 0; i < z->align_length; i++) { + z->non_homopolymer_errors += z->w_list.a[z->w_list.n+i].clen; + } + for (; h < c_idx->n && ovlp_id(c_idx->a[h]) < k; h++); + if(h < c_idx->n && ovlp_id(c_idx->a[h]) == k) { + qs = z->w_list.a[ovlp_min_wid(c_idx->a[h])].x_start; + qe = z->w_list.a[ovlp_max_wid(c_idx->a[h])].x_end+1; + for (; h < c_idx->n && ovlp_id(c_idx->a[h]) == k; h++) { + qe = z->w_list.a[ovlp_max_wid(c_idx->a[h])].x_end+1; + } + sid[sid_n] = ((qs<<32)|sid_n); + sep[sid_n] = ((k<<32)|qe); + sid_n++; + // kv_push(uint64_t, *suf, ((qs<<32)|h)); + } + } + radix_sort_bc64(sid, sid+sid_n); + for (k = rr = 0; k < sid_n; k++) { + qs = sid[k]>>32; qe = ((uint32_t)sep[(uint32_t)sid[k]]); + z = &(ol->list[sep[(uint32_t)sid[k]]>>32]); + if(z->non_homopolymer_errors == 0) continue; + for (i = 0; i < sid_n; i++) { + ts = sid[i]>>32; te = ((uint32_t)sep[(uint32_t)sid[i]]); + p = &(ol->list[sep[(uint32_t)sid[i]]>>32]); + if(ts >= qe) break; + if(te <= qs) continue; + if(p->non_homopolymer_errors > z->non_homopolymer_errors) continue; + if(z->non_homopolymer_errors - p->non_homopolymer_errors <= rphase_thres) { + z->overlapLen = p->overlapLen = 1; rr++; + } + } + } +} + +void region_phase_adv(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, asg64_v* buf1, int64_t ulid) +{ + int64_t on = ol->length, k, i, zwn, q[2], t[2], w[2]; + uint64_t m; overlap_region *z; ul_ov_t *cp; + kv_resize(uint64_t, *idx, (ol->length<<1)); + kv_resize(ul_ov_t, *c_idx, ol->length); + for (k = idx->n = c_idx->n = 0; k < on; k++) { + z = &(ol->list[k]); zwn = z->w_list.n; + z->align_length = 0; z->overlapLen = (uint32_t)-1; + z->non_homopolymer_errors = 0; + if(!zwn) continue; + q[0] = q[1] = t[0] = t[1] = w[0] = w[1] = INT32_MIN; + for (i = 0; i < zwn; i++) { + if((z->w_list.a[i].x_start==(q[1]+1)) && ((z->w_list.a[i].y_start==(t[1]+1)))) { + q[1] = z->w_list.a[i].x_end; + t[1] = z->w_list.a[i].y_end; + w[1] = i; + } else { + if(q[0] != INT32_MIN) { + m = ((uint64_t)q[0])<<1; m <<= 32; + m += c_idx->n; kv_push(uint64_t, *idx, m); + m = (((uint64_t)q[1])<<1)+1; m <<= 32; + m += c_idx->n; kv_push(uint64_t, *idx, m); + + kv_pushp(ul_ov_t, *c_idx, &cp); + ovlp_id(*cp) = k; ///ovlp id + ovlp_min_wid(*cp) = w[0]; ///beg id of windows + ovlp_max_wid(*cp) = w[1]; ///end id of windows + ovlp_cur_wid(*cp) = w[0]; ///cur id of windows + ovlp_cur_xoff(*cp) = z->w_list.a[w[0]].x_start; ///cur xpos + ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window + } + + q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; + t[0] = z->w_list.a[i].y_start; t[1] = z->w_list.a[i].y_end; + w[0] = i; w[1] = i; + } + } + if(q[0] != INT32_MIN) { + m = ((uint64_t)q[0])<<1; m <<= 32; + m += c_idx->n; kv_push(uint64_t, *idx, m); + m = (((uint64_t)q[1])<<1)+1; m <<= 32; + m += c_idx->n; kv_push(uint64_t, *idx, m); + + kv_pushp(ul_ov_t, *c_idx, &cp); + ovlp_id(*cp) = k; ///ovlp id + ovlp_min_wid(*cp) = w[0]; ///beg id of windows + ovlp_max_wid(*cp) = w[1]; ///end id of windows + ovlp_cur_wid(*cp) = w[0]; ///cur id of windows + ovlp_cur_xoff(*cp) = z->w_list.a[w[0]].x_start; ///cur xpos + ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window + } + } + radix_sort_bc64(idx->a, idx->a+idx->n); + //this is used with gen_region_phase, now give up + //gen_gov_idx(ol, uref, uopt, G_CHAIN_BW, N_GCHAIN_RATE, buf1); + // for (m = 0; m < c_idx->n; m++) { + // fprintf(stderr, "+++[M::%s::utg%.6dl] q[%d, %d), t[%d, %d), wn::%d\n", __func__, + // (int32_t)ol->list[ovlp_id(c_idx->a[m])].y_id+1, + // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_min_wid(c_idx->a[m])].x_start, + // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_max_wid(c_idx->a[m])].x_end+1, + // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_min_wid(c_idx->a[m])].y_start, + // ol->list[ovlp_id(c_idx->a[m])].w_list.a[ovlp_max_wid(c_idx->a[m])].y_end+1, + // ovlp_max_wid(c_idx->a[m])+1-ovlp_min_wid(c_idx->a[m])); + // } + + if(rphase_detect0(ol, c_idx, idx, buf, buf1)) {//refine phasing + reacal_phase(ol, c_idx, idx, buf, buf1); + } + + for (k = 0; k < on; k++) { + z = &(ol->list[k]); + z->overlapLen = z->x_pos_e+1-z->x_pos_s; + z->non_homopolymer_errors = 0; zwn = 0; + for (i = m = 0; i < z->align_length; i++) { + z->w_list.a[m] = z->w_list.a[z->w_list.n+i]; + if(z->w_list.a[m].clen > 0) { + z->non_homopolymer_errors += z->w_list.a[m].clen; + zwn += z->w_list.a[m].x_end-z->w_list.a[m].x_start; + } + m++; + } + z->w_list.n = m; + assert(zwn <= z->overlapLen); + z->align_length = z->overlapLen - zwn; + } +} + +void ul_gap_filling_adv(overlap_region_alloc* ol, Candidates_list *cl, kv_ul_ov_t *aln, uint64_t wl, +const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, overlap_region *aux_o, +asg64_v* buf, asg64_v* iidx, double e_rate, int64_t ql, uint64_t rid, int64_t khit, int64_t base_chekc_k_hit, +int64_t max_lgap) +{ + int64_t k, l, ch_n, a_n = aln->n; uint64_t pqn, pk; overlap_region *z; //k_mer_hit *ch_a; + // count_k_hits(rref, uref, qstr, tu, ol, cl, buf, khit, base_chekc_k_hit); + count_k_hits_adv(rref, uref, qstr, tu, ol, cl, buf, &(cl->chainDP), e_rate, khit, base_chekc_k_hit); + // prt_khit(cl, ol, NULL, 109111, "e"); + for (k = 1, l = 0, pqn = 0; k <= a_n; k++) { + if(k == a_n || aln->a[l].qn != aln->a[k].qn) { + z = &(ol->list[aln->a[l].qn]); assert(z->align_length == l); + // fprintf(stderr, "[M::%s::] oid::[%lu, %u)\n", __func__, pqn, aln->a[l].qn); + for (pk = pqn; pk < aln->a[l].qn; pk++) ol->list[pk].w_list.n = 0; + pqn = aln->a[l].qn+1; + // fprintf(stderr, "[M::%s::utg%.6dl::%c]\n", __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand]); + // prt_khit(cl, ol, NULL, 109111, "f"); + ch_n = gen_cns_chain(ol, z, cl, iidx, max_lgap, e_rate, 0); + // prt_khit(cl, ol, NULL, 109111, "g"); + if(ch_n) { + cigar_gen_by_chain_adv(z, cl, cl->length, ch_n, aln->a+l, k-l, wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, rid, khit); + } + l = k; + } + } + for (pk = pqn; pk < ol->length; pk++) ol->list[pk].w_list.n = 0; +} + +void ul_gap_filling_local(overlap_region_alloc* ol, Candidates_list *cl, kv_ul_ov_t *aln, uint64_t wl, +const ul_idx_t *uref, hpc_t *hpc_g, All_reads *rref, char* qstr, UC_Read *tu, bit_extz_t *exz, overlap_region *aux_o, +asg64_v* buf, asg64_v* iidx, double e_rate, int64_t ql, uint64_t rid, int64_t khit, int64_t base_chekc_k_hit, +int64_t max_lgap) +{ + int64_t k, l, a_n = aln->n; uint64_t pqn, pk; overlap_region *z; //k_mer_hit *ch_a; + count_k_hits_filter(ol, cl, buf, &(cl->chainDP)); + for (k = 1, l = 0, pqn = 0; k <= a_n; k++) { + if(k == a_n || aln->a[l].qn != aln->a[k].qn) { + z = &(ol->list[aln->a[l].qn]); assert(z->align_length == l); + for (pk = pqn; pk < aln->a[l].qn; pk++) ol->list[pk].w_list.n = 0; + pqn = aln->a[l].qn+1; + cigar_gen_by_chain_adv_local(z, cl, aln->a+l, k-l, wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, rid, khit); + // ch_n = gen_cns_chain(z, cl, iidx, max_lgap, e_rate, 0); + // if(ch_n) { + // cigar_gen_by_chain_adv(z, cl, cl->length, ch_n, aln->a+l, k-l, wl, uref, hpc_g, rref, qstr, tu, exz, aux_o, e_rate, ql, rid, khit); + // } + l = k; + } + } + for (pk = pqn; pk < ol->length; pk++) ol->list[pk].w_list.n = 0; +} + +inline uint32_t ovlp_win_check(overlap_region *z, uint32_t id0, uint32_t id1, int64_t max_lgap, double small_bw_rate, int64_t min_small_bw) +{ + if(id0 == (uint32_t)-1 || id1 == (uint32_t)-1) return 1; + int64_t qs0, qe0, ts0, te0, qs1, qe1, ts1, te1, err, dd, dm, dq, dr; + if(!get_win_aln(z, id0, &ts0, &te0, &err)) return 1; + qs0 = z->w_list.a[id0].x_start; qe0 = z->w_list.a[id0].x_end+1; + if(!get_win_aln(z, id1, &ts1, &te1, &err)) return 1; + qs1 = z->w_list.a[id1].x_start; qe1 = z->w_list.a[id1].x_end+1; + + if(qs1 < qs0 || qe1 < qe0) return 0; + if(ts1 < ts0 || te1 < te0) return 0; + dq = qe1 - qs0; dr = te1 - ts0; dd = dq>=dr? ((dq)-(dr)): ((dr)-(dq)); + if((ts1 < te0) && (qe0 == qs1)) {//has overlap in y + dm = dq>=dr?dr:dq; + if((dd > (dm*small_bw_rate)) && (dd > min_small_bw)) return 0; + } else { + if(dd > max_lgap) return 0; + } + return 1; +} + +uint64_t dp_commen_sketch(kv_ul_ov_t *aln, overlap_region_alloc* ol, uint64_t *id_a, int64_t id_n, +uint64_t *win_a, int64_t win_n, uint64_t *dp, int64_t n_skip, int64_t wl, int64_t cov, int64_t max_lgap, +double sgap_rate, int64_t sgap) +{ + if(!win_n) return 0; + int64_t k, ws, ws0, i, m, wid, wid0, sc, max_sc, p, long_sc, long_idx; overlap_region *z; + // fprintf(stderr, "\n[M::%s::] n_skip::%ld, win_n::%ld\n", __func__, n_skip, win_n); + // for (k = 0; k < win_n; k++) { + // fprintf(stderr, "[M::%s::] win_a[%ld]::%lu\n", __func__, k, win_a[k]); + // } + if(n_skip < win_n) { + long_sc = long_idx = -1; + for (k = 0; k < n_skip; k++) { + dp[k] = ((k>0)?(k-1):((uint32_t)-1)); dp[k] <<= 32; dp[k] |= k+1; max_sc = k+1; + if(long_sc < max_sc) { + long_sc = max_sc; long_idx = k; + } + } + + for (; k < win_n; k++) { + ws = win_a[k]; sc = 1; p = -1; max_sc = sc; + for (m = k-1; m >= 0; m--) { + ws0 = win_a[m]; + for (i = 0; i < id_n; i++) { + z = &(ol->list[aln->a[(uint32_t)id_a[i]].qn]); + wid = get_win_id_by_s(z, ws, wl, NULL); + wid0 = get_win_id_by_s(z, ws0, wl, NULL); + if(!ovlp_win_check(z, wid0, wid, max_lgap, sgap_rate, sgap)) break; + } + if((i >= id_n) && ((sc + ((uint32_t)dp[m])) > max_sc)) { + max_sc = (sc + ((uint32_t)dp[m])); p = m; + } + } + dp[k] = ((p>=0)?(p):((uint32_t)-1)); dp[k] <<= 32; dp[k] |= max_sc; + if(long_sc < max_sc) { + long_sc = max_sc; long_idx = k; + } + } + // fprintf(stderr, "[M::%s::] long_idx::%lu, long_sc::%lu\n", __func__, long_idx, long_sc); + k = long_idx; + while (k >= 0) { + win_a[k] |= ((uint64_t)0x8000000000000000); + k = ((dp[k]>>32)!=((uint32_t)-1))?(dp[k]>>32):(-1); + } + + for (k = 0, m = 0; k < win_n; k++) { + if(!(win_a[k]&((uint64_t)0x8000000000000000))) continue; + win_a[m++] = (win_a[k]<<1)>>1; + } + win_n = m; + // fprintf(stderr, "[M::%s::] win_n::%lu\n", __func__, win_n); + } + + for (k = 0, cov = -cov; k < win_n; k++) { + ws = win_a[k]; + for (i = 0; i < id_n; i++) { + z = &(ol->list[aln->a[(uint32_t)id_a[i]].qn]); + wid = get_win_id_by_s(z, ws, wl, NULL); + // if(wid >= z->w_list.n) { + // fprintf(stderr, "[M::%s::] ws::%ld, wl::%ld, wid::%ld, wn::%ld\n", + // __func__, ws, wl, wid, ((int64_t)z->w_list.n)); + // } + if(cov > INT16_MIN) z->w_list.a[wid].extra_end = cov; + else z->w_list.a[wid].extra_end = INT16_MIN; + z->align_length = wid;///for conliner + } + } + return win_n; +} + + +uint64_t gen_commen_sketch(All_reads *rref, const ul_idx_t *uref, overlap_region_alloc* ol, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, uint64_t ql, uint64_t wl, +uint64_t *buf, uint64_t dp, char *str0, char *str1, kv_ul_ov_t *aln, asg64_v *trace, +int64_t max_lgap, double sgap_rate, int64_t sgap)///[s, e) +{ + if(!id_n) return id_n; + uint64_t i, m, k, rm_n = 0, buf_n = 0, qs, qe, wid, co, occ; char *qstring, *tstring; + overlap_region *z; uint64_t ws, we; int64_t r_y[2], r_err, p_y[2], p_err, rxl, ryl, pxl; + ///shrink [qs, qe) + qs = (s/wl)*wl; if(qs < s) qs += wl; if(qs >= ql) return id_n; + qe = (e/wl)*wl; if(qe >= ql) qe = ql; + if(qs >= qe) return id_n; + //idx_a[] is sorted by aln[].qs + for (k = 0; k < id_n; k++) { + if(aln->a[id_a[k]].qs<=qs && aln->a[id_a[k]].qe>=qe) { + buf[buf_n] = ol->list[aln->a[id_a[k]].qn].align_length; buf[buf_n] <<= 32; buf[buf_n] |= id_a[k]; + buf_n++; + } + if(aln->a[id_a[k]].qe < e) rm_n++; + } + assert(buf_n == dp && buf_n > 1); + + if(buf_n > 0) { + ///fs = fe = (uint64_t)-1; + co = 1; trace->n = occ = 0; + for (k = qs; k < qe; k += wl) { + ws = k; we = ws + wl; if(we > qe) we = qe;//[ws, we) + ///first overlap + z = &(ol->list[aln->a[(uint32_t)buf[0]].qn]); + wid = get_win_id_by_s(z, ws, wl, NULL); + if(!get_win_aln(z, wid, &(r_y[0]), &(r_y[1]), &r_err)) continue; + if(!ovlp_win_check(z, z->align_length, wid, max_lgap, sgap_rate, sgap)) continue;///not co-linear + rxl = z->w_list.a[wid].x_end+1-z->w_list.a[wid].x_start; + ryl = r_y[1]-r_y[0]; + // fprintf(stderr, "+[M::%s::] buf_n::%lu, q::[%lu, %lu), w::[%lu, %lu), rxl::%ld, ryl::%ld, x::[%d, %d), y::[%ld, %ld)\n", + // __func__, buf_n, qs, qe, ws, we, rxl, ryl, z->w_list.a[wid].x_start, z->w_list.a[wid].x_end+1, r_y[0], r_y[1]); + if(rxl > 1 && ryl > 1) continue;///length of window should be longer than 1 + // if(rxl <= 1 || ryl <= 1) continue;///length of window should be longer than 1 + // fprintf(stderr, "-[M::%s::] buf_n::%lu, q::[%lu, %lu), w::[%lu, %lu), rxl::%ld, ryl::%ld, x::[%d, %d), y::[%ld, %ld)\n", + // __func__, buf_n, qs, qe, ws, we, rxl, ryl, z->w_list.a[wid].x_start, z->w_list.a[wid].x_end+1, r_y[0], r_y[1]); + qstring = tstring = NULL; + for (i = 1; i < buf_n; i++) { + z = &(ol->list[aln->a[(uint32_t)buf[i]].qn]); + wid = get_win_id_by_s(z, ws, wl, NULL); + if(!get_win_aln(z, wid, &(p_y[0]), &(p_y[1]), &p_err)) break; + if(!ovlp_win_check(z, z->align_length, wid, max_lgap, sgap_rate, sgap)) break;///not co-linear + pxl = z->w_list.a[wid].x_end+1-z->w_list.a[wid].x_start; + if(pxl != rxl) break; + if(((r_y[1]-r_y[0]) != (p_y[1]-p_y[0])) || (r_err != p_err)) break; + if(r_err == 0) continue; + if(!qstring) { + qstring = retrive_str_piece_exz(rref, uref, str0, r_y[0], r_y[1]-r_y[0], + ol->list[aln->a[(uint32_t)buf[0]].qn].y_pos_strand, ol->list[aln->a[(uint32_t)buf[0]].qn].y_id); + } + tstring = retrive_str_piece_exz(rref, uref, str1, p_y[0], p_y[1]-p_y[0], z->y_pos_strand, z->y_id); + if(memcmp(qstring, tstring, (p_y[1]-p_y[0]))) { + // fprintf(stderr, "[M::%s::] qs::%ld, qe::%lu, ts::%ld, te::%lu, err::%ld, rts::%ld, rte::%lu, err::%ld\n", + // __func__, ws, we, p_y[0], p_y[1], r_err, r_y[0], r_y[1], p_err); + // fprintf(stderr, "str0::%.*s\n", (int32_t)(r_y[1]-r_y[0]), str0); + // fprintf(stderr, "str1::%.*s\n", (int32_t)(p_y[1]-p_y[0]), str1); + break; + } + } + if(i < buf_n) continue; + if(co) { + for (i = 0; i < buf_n; i++) { + z = &(ol->list[aln->a[(uint32_t)buf[i]].qn]); + wid = get_win_id_by_s(z, ws, wl, NULL); + co = ovlp_win_check(z, buf[i]>>32, wid, max_lgap, sgap_rate, sgap); + m = wid; m <<= 32; m |= (uint32_t)buf[i]; buf[i] = m; + } + if(co) occ++; + } + kv_push(uint64_t, *trace, ws); + } + + if(trace->n) { + if(!co) kv_resize(uint64_t, *trace, trace->n<<1); + trace->n = dp_commen_sketch(aln, ol, buf, buf_n, trace->a, trace->n, trace->a + trace->n, occ, wl, dp, max_lgap, sgap_rate, sgap); + } + } + if(rm_n) { + for (i = m = 0; i < id_n; i++) { + if(aln->a[id_a[i]].qe < e) continue; + id_a[m++] = id_a[i]; + } + id_n = m; + } + return id_n; +} + +void update_sketch_trace(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, +All_reads *rref, UC_Read* tu, asg64_v* idx, asg64_v *b0, asg64_v *b1, int64_t ql, int64_t wl, +kv_ul_ov_t *aln, uint64_t rid, int64_t max_lgap, double sgap_rate) +{ + idx->n = 0; + if(!aln->n) return; + uint64_t i, k, own, srt_n; int64_t dp, old_dp, beg, end; overlap_region *z; + for (i = 0; i < ol->length; i++) { + z = &(ol->list[i]); append_unmatched_wins(z, wl); + own = z->w_list.n; z->align_length = (uint32_t)-1; + for (k = 0; k < own; k++) { + if(z->w_list.a[k].extra_end < 0) z->w_list.a[k].extra_end = 0; + } + } + + kv_resize(uint64_t, *idx, (aln->n<<1)); kv_resize(uint64_t, *b0, aln->n); + for (i = srt_n = 0; i < aln->n; i++) { + // if(i == 0 || aln->a[i].qn != aln->a[i-1].qn) ol->list[aln->a[i].qn].align_length = i; + ol->list[aln->a[i].qn].align_length = (uint32_t)-1;///for co-linear + idx->a[srt_n] = aln->a[i].qs<<1; idx->a[srt_n] <<= 32; idx->a[srt_n] += i; srt_n++; + idx->a[srt_n] = ((aln->a[i].qe-1)<<1)+1; idx->a[srt_n] <<= 32; idx->a[srt_n] += i; srt_n++; + aln->a[i].el = 1; + } + + radix_sort_bc64(idx->a, idx->a+srt_n); idx->n = srt_n; resize_UC_Read(tu, (wl<<1)); + for (i = 0, dp = 0, beg = 0, end = -1; i < srt_n; ++i) {///[beg, end), but the idx saves [qs, qe] + old_dp = dp; + ///if idx->a.a[] is qe + if ((idx->a[i]>>32)&1) { + --dp; end = (idx->a[i]>>33)+1; + }else { + //meet a new overlap; the overlaps are pushed by the x_pos_s + ++dp; end = (idx->a[i]>>33); + kv_push(uint64_t, *idx, ((uint32_t)idx->a[i])); + } + + if((end > beg) && (end - beg > wl) && (old_dp >= 2) ) { + // fprintf(stderr, "+++[M::%s::] beg::%ld, end::%ld\n", __func__, beg, end); + idx->n = srt_n + + gen_commen_sketch(rref, uref, ol, idx->a+srt_n, idx->n-srt_n, beg, end, ql, wl, b0->a, + old_dp, tu->seq, tu->seq+wl, aln, b1, max_lgap, sgap_rate, SGAP); + } + beg = end; + } + + for (i = 0; i < aln->n; i++) { + if(i == 0 || aln->a[i].qn != aln->a[i-1].qn) ol->list[aln->a[i].qn].align_length = i; + } + idx->n = srt_n; + // fprintf(stderr, "+++[M::%s::] idx->n::%ld\n", __func__, idx->n); + return; +} + + + +void ul_lalign(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, const ug_opt_t *uopt, + char *qstr, uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, bit_extz_t *exz, haplotype_evdience_alloc* hap, + kvec_t_u64_warp* v_idx, overlap_region *aux_o, double e_rate, int64_t wl, kv_ul_ov_t *aln, int64_t sid, uint64_t khit, + st_mt_t *stb, idx_emask_t *mm, mask_ul_ov_t *mk, void *km) +{ + uint64_t i, bs, k, ovl/**, on**/; Window_Pool w; double err; + /**int64_t sc;**/ overlap_region t; overlap_region *z; asg64_v iidx, buf, buf1; + ol->mapped_overlaps_length = 0; + if(ol->length <= 0) return; + + ///base alignment + clear_Correct_dumy(dumy, ol, km); err = e_rate; + init_Window_Pool(&w, ql, wl, (int)(1.0/err)); + bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(tu, bs<<1); + + if(!aln) { + resize_UC_Read(qu, ql); qu->length = ql; memcpy(qu->seq, qstr, ql); + for (i = 0; i < ol->length; i++) { + z = &(ol->list[i]); ovl = z->x_pos_e+1-z->x_pos_s; + z->shared_seed = z->non_homopolymer_errors;///for index + if(!align_ul_ed_post_extz(z, uref, NULL, qu->seq, tu->seq, exz, err, w.window_length, -1, 0, km)) { + continue; + } + if(uref && simi_pass(ovl, z->align_length, uref?1:0, -1, NULL)) { + z->is_match = 3; ol->mapped_overlaps_length += z->align_length; + } + } + + if(uref && ol->mapped_overlaps_length > 0) { + set_herror_win(ol, dumy, v_idx, err, ql, w.window_length); + } + + double e_max = err*1.5, rr; int64_t re; + for (i = k = 0; i < ol->length; i++) { + z = &(ol->list[i]); ovl = z->x_pos_e + 1 - z->x_pos_s; + rr = gen_extend_err_exz(z, uref, NULL, NULL, qu->seq, tu->seq, exz, v_idx?v_idx->a.a:NULL, w.window_length, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 1, &re); + z->is_match = 0;///must be here; + + + // fprintf(stderr, "[M::%s::utg%.6dl::%c] sid::%ld, q::[%d, %d), t::[%d, %d), err::%ld\n", + // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], sid, z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1, + // re); + + if (rr <= err) { + if(k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + ol->list[k].is_match = 1; ol->list[k].non_homopolymer_errors = re; + // fprintf(stderr, "+[M::%s] on::%lu\n", __func__, ol->length); + /****for debug****/ + // z = &(ol->list[k]); + // fprintf(stderr, "[M::%s::utg%.6dl::%c] sid::%ld, q::[%d, %d), t::[%d, %d), err::%u\n", + // __func__, (int32_t)z->y_id+1, "+-"[z->y_pos_strand], sid, z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1, + // z->non_homopolymer_errors); + /****for debug****/ + k++; + } + } + + ol->length = k; + // fprintf(stderr, "+[M::%s] on::%lu\n", __func__, ol->length); + if(ol->length <= 0) return; + } else { + // fprintf(stderr, "-[M::%s] on::%lu\n", __func__, ol->length); + if(ol->length <= 1) { + if(ol->length == 1) { + window_list *p; + z = &(ol->list[0]); z->w_list.n = 0; + kv_pushp(window_list, z->w_list, &p); + memset(p, 0, sizeof((*p))); + p->x_start = z->x_pos_s; p->x_end = z->x_pos_e+1; p->clen = 0; + z->align_length = z->overlapLen = z->x_pos_e+1-z->x_pos_s; + z->non_homopolymer_errors = 0; + } + return; + } + ///coordinates for all intervals with cov > 1 + copy_asg_arr(iidx, hap->snp_srt); copy_asg_arr(buf, v_idx->a); copy_asg_arr(buf1, (*stb)); + // fprintf(stderr, "\n[M::%s] iidx_n::%ld\n", __func__, (int64_t)iidx.n); + ul_gap_filling_adv(ol, cl, aln, wl, uref, NULL, NULL, qu->seq, tu, exz, aux_o, &buf, &iidx, err, ql, sid, khit, 1, MAX_LGAP(ql)); + copy_asg_arr(hap->snp_srt, iidx); copy_asg_arr(v_idx->a, buf); copy_asg_arr((*stb), buf1); + + copy_asg_arr(iidx, hap->snp_srt); copy_asg_arr(buf, v_idx->a); copy_asg_arr(buf1, (*stb)); + // region_phase(ol, uref, uopt, aln, &iidx, &buf, &buf1, sid); + rphase_hl(ol, uref, uopt, aln, &iidx, &buf, &buf1, sid, 64, ql, mk, mm, err); + copy_asg_arr(hap->snp_srt, iidx); copy_asg_arr(v_idx->a, buf); copy_asg_arr((*stb), buf1); + } +} + + +int64_t get_chain_x_by_y(overlap_region* ot, int64_t q) +{ + int64_t x, y, off, i, lx = -1, ly = -1; Fake_Cigar* o = &(ot->f_cigar); + x = get_fake_gap_pos(o, o->length - 1); + off = get_fake_gap_shift(o, o->length - 1); + y = x - ot->x_pos_s + ot->y_pos_s + off; + if(y == q) return x; + + for (i = 0; i < (int64_t)o->length; i++){ + x = get_fake_gap_pos(o, i); off = get_fake_gap_shift(o, i); + y = x - ot->x_pos_s + ot->y_pos_s + off; + if(q < y) { + lx = x; ly = y; + break; + } + } + + assert((i!=0)&&(i!=(int64_t)o->length)); + x = get_fake_gap_pos(o, i-1); off = get_fake_gap_shift(o, i-1); + y = x - ot->x_pos_s + ot->y_pos_s + off; + y = (((double)(q - y))/((double)(ly - y)))*((double)(lx -x)) + x; + if(y < ot->x_pos_s) y = ot->x_pos_s; + if(y > ot->x_pos_e) y = ot->x_pos_e; + return y; +} + +int64_t gen_contain_ov(const ul_idx_t *uref, utg_ct_t *p, overlap_region* o, kv_ul_ov_t *res) +{ + int64_t y_s, y_e, y_bs, y_be, x_s, x_e, q_s, q_e; + if(o->y_pos_strand) { + y_s = uref->ug->u.a[o->y_id].len - p->e; + y_e = uref->ug->u.a[o->y_id].len - p->s - 1; + } else { + y_s = p->s; y_e = p->e - 1; + } + + y_s = MAX(y_s, (int64_t)o->y_pos_s); y_e = MIN(y_e, (int64_t)o->y_pos_e); + if(y_s > y_e) return 0; + x_s = get_chain_x_by_y(o, y_s); x_e = get_chain_x_by_y(o, y_e) + 1; + assert(x_s < x_e); + // if(x_s >= x_e) fprintf(stderr, "+++y_s->%ld, y_e->%ld, x_s->%ld, x_e->%ld\n", y_s, y_e, x_s, x_e); + if(o->y_pos_strand) { + y_bs = uref->ug->u.a[o->y_id].len - (y_e+1); + y_be = uref->ug->u.a[o->y_id].len - y_s; + } else { + y_bs = y_s; y_be = y_e + 1; + } + + q_s = 0; q_e = p->e - p->s; + if(p->x&1) { + q_s += (p->e - y_be); + q_e -= (y_bs - p->s); + } else { + q_s += (y_bs - p->s); + q_e -= (p->e - y_be); + } + + ul_ov_t *x = NULL; + kv_pushp(ul_ov_t, *res, &x); + x->qn = o->x_id; x->qs = x_s; x->qe = x_e; + x->tn = (uint32_t)(0x80000000); x->tn |= (p->x>>1); + x->ts = q_s; x->te = q_e; x->el = 1;x->sec = 0; x->rev = ((o->y_pos_strand == (p->x&1))?0:1); + return 1; +} + + +uint64_t gen_sub_ov(const ul_idx_t *udb, overlap_region* o, kv_ul_ov_t *res, uint64_t xs, uint64_t xe) +{ + uint64_t ts, te, i, l, rn = res->n, rev = o->y_pos_strand; ul_ov_t *z; + utg_ct_t p; ma_utg_t *u = &(udb->ug->u.a[o->y_id]); + if(!rev){ + ts = o->y_pos_s; te = o->y_pos_e + 1; + } else { + ts = u->len - (o->y_pos_e+1); te = u->len - o->y_pos_s; + } + + for (i = l = 0; i < u->n; i++) { + p.x = u->a[i]>>32; p.s = l; p.e = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); + l += (uint32_t)u->a[i]; + if(p.e <= ts) continue; + if(p.s >= te) break; + if(gen_contain_ov(udb, &p, o, res)) { + z = &(res->a[res->n-1]); + if(z->qs >= xe) break; + if(z->qe <= xs) res->n--; + } + } + return res->n-rn; +} + +uint64_t gen_conta_ov(const ul_idx_t *udb, overlap_region* o, utg_ct_t *ct_a, int64_t ct_n, kv_ul_ov_t *res, uint64_t xs, uint64_t xe) +{ + int64_t i; uint64_t ys, ye, rn = res->n; ma_utg_t *u = &(udb->ug->u.a[o->y_id]); + ul_ov_t *z; utg_ct_t *p; + + if(o->y_pos_strand == 0){ + ys = o->y_pos_s; ye = o->y_pos_e + 1; + } else { + ys = u->len - (o->y_pos_e+1); ye = u->len - o->y_pos_s; + } + + for (i = 0; i < ct_n; i++) { + p = &(ct_a[i]); + if(p->e <= ys) continue; + if(p->s >= ye) break; + if(gen_contain_ov(udb, p, o, res)) { + z = &(res->a[res->n-1]); + if(z->qs >= xe) break; + if(z->qe <= xs) res->n--; + } + } + return res->n-rn; +} + + +uint64_t gen_r_aln(const ul_idx_t *udb, overlap_region *z, uint64_t zid, asg64_v *idx, double o_rate, kv_ul_ov_t *aln, uint64_t min_ovlp) +{ + uint64_t ol = z->x_pos_e+1-z->x_pos_s, aln_ol = z->align_length, k, cn, is_srt; + ul_ov_t *p; ul_contain *ct = udb->ct; utg_ct_t *ca; uint64_t os, oe, ovlp, salnl, sol, raln = aln->n; + int64_t sk, ek, wn, s, e, ws, we, minw, maxw; + if((aln_ol < min_ovlp) || (!(z->w_list.n))) return 0; + if((ol*o_rate) <= aln_ol) { + kv_pushp(ul_ov_t, *aln, &p); + p->qn = zid; p->tn = z->y_id; p->el = 1; p->rev = z->y_pos_strand; p->sec = 0; + p->qs = z->x_pos_s; p->qe = z->x_pos_e+1; //[qs, qe) + p->ts = 0; p->te = z->w_list.n; //[ts, te) + } else { + cn = ((uint32_t)(ct->idx.a[z->y_id])); + ca = ct->rids.a + ((ct->idx.a[z->y_id])>>32); + wn = z->w_list.n; + ws = z->w_list.a[0].x_start; + we = z->w_list.a[z->w_list.n-1].x_end+1; + + gen_sub_ov(udb, z, aln, ws, we); gen_conta_ov(udb, z, ca, cn, aln, ws, we); + + idx->n = aln->n-raln; kv_resize(uint64_t, *idx, idx->n); + for (k = raln, idx->n = 0, is_srt = 1; k < aln->n; k++) { + if(k > raln && aln->a[k].qs < aln->a[k-1].qs) is_srt = 0; + idx->a[idx->n++] = (((uint64_t)(aln->a[k].qs))<<32)|((uint64_t)(aln->a[k].qe)); + } + if(!is_srt) radix_sort_bc64(idx->a, idx->a+idx->n); + aln->n = raln; + + for (k = sk = ek = 0; k < idx->n; k++) {///idx->a is sorted by s, not by e + s = idx->a[k]>>32; e = (uint32_t)idx->a[k]; + salnl = 0; sol = e - s; minw = INT32_MAX; maxw = 0; + for (sk = ((sk z->w_list.a[sk].x_end; sk++); + for (sk = ((sk= 0 && s < z->w_list.a[sk].x_start; sk--); + if(k < 0) k = 0; ///s >= z->w_list.a[sk].x_start && s <= z->w_list.a[sk].x_end + for (ek = sk; ek < wn; ek++) { + ws = z->w_list.a[ek].x_start; + we = z->w_list.a[ek].x_end + 1; + if(ws >= e) break; + if(z->w_list.a[ek].y_end == -1) continue; + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + if(!ovlp) continue; + salnl += ovlp; + if(ek < minw) minw = ek; + if(ek > maxw) maxw = ek; + } + p = NULL; + if(((sol*o_rate)<=salnl) && (maxw >= minw)) { + ws = z->w_list.a[minw].x_start; we = z->w_list.a[maxw].x_end + 1; maxw++; + if(aln->n > raln) { + p = &(aln->a[aln->n-1]); + os = MAX(s, p->qs); oe = MIN(e, p->qe); + if(oe>os) { + if(s < p->qs) p->qs = s; + if(e > p->qe) p->qe = e; + if(minw < p->ts) p->ts = minw; + if(maxw > p->te) p->te = maxw; + } else { + p = NULL; + } + } + if(!p) { + kv_pushp(ul_ov_t, *aln, &p); + p->qn = zid; p->tn = z->y_id; p->el = 0; + p->rev = z->y_pos_strand; p->sec = 0; + p->qs = s; p->qe = e; ///[qs, qe) + p->ts = minw; p->te = maxw; ///[ts, te) + } + } + } + } + + return aln->n - raln; +} + +///q[2], t[2] +int64_t get_win_yoff(overlap_region *o, int64_t toff, int64_t k, int64_t qs, int64_t qe, int64_t ts, int64_t te, int64_t *q, int64_t *t, +int64_t *rq, int64_t *rt) +{ + int64_t wn = o->w_list.n<<1, s, qdis, tdis, dis; + if(k<0) {k = 0;} if(k>=wn) {k = wn-1;} + for (; k < wn; k++) { + s = ((k&1)?(o->w_list.a[k>>1].x_end):(o->w_list.a[k>>1].x_start)); + if(s >= toff) break; + } + for (k=(k>=wn?(wn-1):(k)); k >= 0; k--) { + s = ((k&1)?(o->w_list.a[k>>1].x_end):(o->w_list.a[k>>1].x_start)); + if(s <= toff) break; + } + + q[0] = qs; q[1] = qe; t[0] = ts; t[1] = te; + if(k < 0) {//toff <= t[1] + q[1] = o->w_list.a[0].x_start; + t[1] = o->w_list.a[0].y_start; + tdis = t[1] - toff; qdis = q[1] - q[0]; dis = MIN(qdis, tdis); + (*rq) = q[1] - dis; (*rt) = t[1] - dis; + } else if(k == wn-1) {//toff >= t[0] + q[0] = o->w_list.a[k>>1].x_end; + t[0] = o->w_list.a[k>>1].y_end; + tdis = toff - t[0]; qdis = q[1] - q[0]; dis = MIN(qdis, tdis); + (*rq) = q[0] + dis; (*rt) = t[0] + dis; + } else {//toff >= t[0] && toff <= t[1] + q[0] = ((k&1)?(o->w_list.a[k>>1].x_end):(o->w_list.a[k>>1].x_start)); + t[0] = ((k&1)?(o->w_list.a[k>>1].y_end):(o->w_list.a[k>>1].y_start)); + k++; + q[1] = ((k&1)?(o->w_list.a[k>>1].x_end):(o->w_list.a[k>>1].x_start)); + t[1] = ((k&1)?(o->w_list.a[k>>1].y_end):(o->w_list.a[k>>1].y_start)); + k--; + (*rt) = toff; + (*rq) = q[0] + get_offset_adjust(toff-t[0], t[1]-t[0], q[1]-q[0]); + } + return k; +} + +int64_t get_win_off(int64_t ql, utg_ct_t *p, overlap_region* o, double o_rate, ul_ov_t *res) +{ + if(!o->w_list.n) return 0; + int64_t q[2], t[2], wk[2], wq[2], wt[2], k, tot_l, qs, qe, ts, te, os, oe, ovlp, aln_l; + qs = 0; qe = ql-1; ts = p->s; te = p->e-1; //[qs, qe] && [ps, pe] + + k = 0; memset(res, 0, sizeof((*res))); + k = get_win_yoff(o, ts, k, qs, qe, ts, te, q, t, &(wq[0]), &(wt[0])); wk[0] = k; + k = get_win_yoff(o, te, k, qs, qe, ts, te, q, t, &(wq[1]), &(wt[1])); wk[1] = k; + res->ts = ts; res->te = te + 1;///offset of t + res->qs = wk[0]<0?(uint32_t)-1:wk[0]; res->qe = wk[1] + 1;///id of window + + wk[0] = ((wk[0]>=0)?(wk[0]>>1):0); + wk[1] = ((wk[1]>=0)?(wk[1]>>1):0)+1; + tot_l = wq[1]+1-wq[0]; aln_l = 0; + for (k = wk[0]; k < wk[1]; k++) { + if(is_ualn_win(o->w_list.a[k])) continue; + os = MAX(wq[0], o->w_list.a[k].x_start); + oe = MIN(wq[1], o->w_list.a[k].x_end) + 1; + ovlp = ((oe>os)? (oe-os):0); aln_l += ovlp; + } + if((aln_l < (tot_l*o_rate)) || (aln_l == 0)) return 0; + return 1; +} + +uint64_t gen_sub_ov_cigar(const ul_idx_t *udb, uint64_t ql, overlap_region* o, double o_rate, kv_ul_ov_t *res) +{ + uint64_t ts, te, i, l, tl, id = o->y_id, rn = res->n, s, e, rev = o->y_pos_strand; utg_ct_t p; + ma_utg_t *u = &(udb->ug->u.a[id]); ul_ov_t rr; int64_t wn, k; + + wn = o->w_list.n; tl = u->len; + for (k = 0; (k < wn) && (is_ualn_win(o->w_list.a[k])); k++); + if(k >= wn) return 0; + if(!rev) { + ts = o->w_list.a[k].x_start; + } else { + te = tl-o->w_list.a[k].x_start; + } + for (k = wn-1; (k >= 0) && (is_ualn_win(o->w_list.a[k])); k--); + if(k < 0) return 0; + if(!rev) { + te = o->w_list.a[k].x_end+1; + } else { + ts = tl-o->w_list.a[k].x_end-1; + } + if(ts >= te) return 0;///[ts, te) + + + for (i = l = 0; i < u->n; i++) { + p.x = u->a[i]>>32; s = l; e = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); + l += (uint32_t)u->a[i]; + if(e <= ts) {continue;} if(s >= te) {break;} + if(!rev) { + p.s = s; p.e = e; + } + else { + p.s = tl - e; p.e = tl - s; + } + + if(get_win_off(ql, &p, o, o_rate, &rr)) { + rr.el = 0; kv_push(ul_ov_t, *res, rr); + } + } + return res->n-rn; +} + + +uint64_t gen_conta_ov_cigar(const ul_idx_t *udb, uint64_t ql, overlap_region* o, utg_ct_t *ct_a, uint64_t ct_n, double o_rate, kv_ul_ov_t *res) +{ + uint64_t ts, te, i, tl, id = o->y_id, rn = res->n, rev = o->y_pos_strand; utg_ct_t p, *z; + ma_utg_t *u = &(udb->ug->u.a[id]); ul_ov_t rr; int64_t wn, k; + + wn = o->w_list.n; tl = u->len; + for (k = 0; (k < wn) && (is_ualn_win(o->w_list.a[k])); k++); + if(k >= wn) return 0; + if(!rev) { + ts = o->w_list.a[k].x_start; + } else { + te = tl-o->w_list.a[k].x_start; + } + for (k = wn-1; (k >= 0) && (is_ualn_win(o->w_list.a[k])); k--); + if(k < 0) return 0; + if(!rev) { + te = o->w_list.a[k].x_end+1; + } else { + ts = tl-o->w_list.a[k].x_end-1; + } + if(ts >= te) return 0;///[ts, te) + + + for (i = 0; i < ct_n; i++) { + z = &(ct_a[i]); + if(z->e <= ts) continue; + if(z->s >= te) break; + p = *z; + if(!rev) { + p.s = z->s; p.e = z->e; + } else { + p.s = tl - z->e; p.e = tl - z->s; + } + + if(get_win_off(ql, &p, o, o_rate, &rr)) { + rr.el = 1; kv_push(ul_ov_t, *res, rr); + } + } + return res->n-rn; +} + + + /** +void cal_simi_ul_ov_t(overlap_region *z, ul_ov_t *o, kv_ul_ov_t *res, int64_t ql) +{ + int64_t beg_q[2], beg_t[2], end_q[2], end_t[2], wk[2], wq[2], wt[2], kbeg, kend; + int64_t k, tot_l, qs, qe, ts, te, os, oe, ovlp, aln_l, wts, wte, wtl, wn; ul_ov_t *p; + qs = 0; qe = ql-1; ts = o->ts; te = o->te-1; //[qs, qe] && [ps, pe] + k = (o->qs==(uint32_t)-1)?(-1):(o->qs); + k = get_win_yoff(z, ts, k, qs, qe, ts, te, beg_q, beg_t, &(wq[0]), &(wt[0])); wk[0] = k; + k = o->qe; + k = get_win_yoff(z, te, k, qs, qe, ts, te, end_q, end_t, &(wq[1]), &(wt[1])); wk[1] = k; + o->sec = 0; + kbeg = ((wk[0]>=0)?(wk[0]>>1):(0)); kend = ((wk[1]>=0)?(wk[1]>>1):(0)); aln_l = 0; + for (k = kbeg; k <= kend; k++) { + wts = z->w_list.a[k].y_start; wte = z->w_list.a[k].y_end; wtl = wte + 1 - wts; + os = MAX(wts, ts); oe = MIN(wte, te) + 1; + ovlp = ((oe>os)? (oe-os):0); aln_l += ovlp; + assert(ovlp > 0); + if(ovlp == wtl) { + + } else { + + } + } + if(aln_l < te+1-ts) { + wn = z->w_list.n; + assert(wk[0] == -1 || wk[1] == wn-1); + } + + if(wk[0] == wk[1]) {///one window cover the whole [ts, te] + kv_pushp(ul_ov_t, *res, &p); p->ts = ts; p->te = te; + } + if(wk[0] < 0) { + + } +} +**/ + +///[ts, te) -> this is the reverse coordinates of t, not the original coordinates of t +int64_t extract_subov(int64_t ts, int64_t te, overlap_region *o, double o_rate, int64_t *in_k, ul_ov_t *res) +{ + int64_t rev = o->y_pos_strand, qs, qe, k = 0, wn = o->w_list.n, ws, we, os, oe, ovlp, salnl; + if(ts < ((int64_t)o->y_pos_s)) ts = o->y_pos_s; + if(te > ((int64_t)o->y_pos_e+1)) te = o->y_pos_e+1; + if(ts >= te) return 0; + qs = get_chain_x_by_y(o, ts); + qe = get_chain_x_by_y(o, te-1) + 1; + assert(qs < qe); + memset(res, 0, sizeof(*res)); res->rev = rev; + res->qs = qs; res->qe = qe; res->ts = ts; res->te = te; + + if(o_rate >= 0) { + if(wn <= 0) return 0; + if(in_k) k = *in_k; + + if(k < 0) {k = 0;} if(k >= wn) {k = wn-1;} + for(; k < wn && qs > o->w_list.a[k].x_end; k++); + if(k < 0) {k = 0;} if(k >= wn) {k = wn-1;} + for(; k >= 0 && qs < o->w_list.a[k].x_start; k--); + ///qs <= o->w_list.a[k].x_end && qs >= o->w_list.a[k].x_start + if(k < 0) k = 0; + if(in_k) *in_k = k; + + for (salnl = 0; k < wn; k++) { + ws = o->w_list.a[k].x_start; + we = o->w_list.a[k].x_end + 1; + if(ws >= qe) break; + if((o->w_list.a[k].y_end == -1) || (is_ualn_win(o->w_list.a[k]))) continue; + os = MAX(qs, ws); oe = MIN(qe, we); + ovlp = ((oe>os)? (oe-os):0); + if(!ovlp) continue; + salnl += ovlp; + } + // if(o->y_id == 700) { + // fprintf(stderr, "[M::%s] raw_t::[%ld, %ld), raw_q::[%ld, %ld), salnl::%ld\n", __func__, ts, te, qs, qe, salnl); + // } + if((((qe-qs)*o_rate)<=salnl) && (salnl > 0)) return 1; + else return 0; + } + return 1; +} + + +uint64_t gen_sub_ov_adv(const ul_idx_t *udb, overlap_region* o, double o_rate, utg_ct_t *ct_a, uint64_t ct_n, kv_ul_ov_t *res) +{ + uint64_t ts, te, i, l, rn = res->n, rev = o->y_pos_strand, s, e, rid, t[2]; ul_ov_t z; + ma_utg_t *u = &(udb->ug->u.a[o->y_id]); int64_t k; + if(!rev){ + ts = o->y_pos_s; te = o->y_pos_e + 1; k = 0; + } else { + ts = u->len - (o->y_pos_e+1); te = u->len - o->y_pos_s; + k = ((int64_t)o->w_list.n)-1; if(k < 0) k = 0; + } + + if(!ct_a) { + for (i = l = 0; i < u->n; i++) { + rid = u->a[i]>>33; + s = l; e = l + Get_READ_LENGTH(R_INF, rid); + l += (uint32_t)u->a[i]; + if(e <= ts) continue; + if(s >= te) break; + t[0] = (rev?(u->len-e):(s)); t[1] = (rev?(u->len-s):(e)); + if(extract_subov(t[0], t[1], o, o_rate, &k, &z)) { + ///[ts, te) -> whole interval rid at the unitig adjusted by the reverse + // z.ts = t[0]; z.te = t[1]; + ///the strand of rid at the unitig + z.rev = rev; + ///non-contained read at the unitg + z.el = 0; + ///rid + z.tn = rid; + ///i-th read at the unitig + z.qn = i; + kv_push(ul_ov_t, *res, z); + } + } + } else { + for (i = 0; i < ct_n; i++) { + rid = ct_a[i].x>>1; s = ct_a[i].s; e = ct_a[i].e; + if(e <= ts) continue; + if(s >= te) break; + t[0] = (rev?(u->len-e):(s)); t[1] = (rev?(u->len-s):(e)); + if(extract_subov(t[0], t[1], o, o_rate, &k, &z)) { + ///[ts, te) -> whole interval rid at the unitig adjusted by the reverse + // z.ts = t[0]; z.te = t[1]; + ///the strand of rid at the unitig + z.rev = rev; + ///contained read at the unitg + z.el = 1; + ///rid + z.tn = rid; + ///i-th read at the unitig + z.qn = i; + kv_push(ul_ov_t, *res, z); + } + } + } + return res->n-rn; +} + +int64_t return_t_chain(overlap_region *z, Candidates_list *cl) +{ + int64_t i, cn = cl->length, scn; uint64_t pid; k_mer_hit *ca; + + // if(z->y_id == 30129) { + // fprintf(stderr, "\n-0-[M::%s]\tutg%.6ul\tx::[%u,\t%u)\t%c\tutg%.6ul\ty::[%u,\t%u)\n", + // __func__, z->x_id+1, z->x_pos_s, z->x_pos_e+1, + // "+-"[z->y_pos_strand], z->y_id+1, z->y_pos_s, z->y_pos_e+1); + // i = z->shared_seed; pid = cl->list[i].readID; + // for (; i < cn && cl->list[i].readID == pid && cl->list[i].readID != ((uint32_t)(0x7fffffff)); i++) { + // fprintf(stderr, "i::%ld[M::%s]\treadID::%u\tself_offset::%u\toffset::%u\t%c\n", + // i, __func__, cl->list[i].readID, cl->list[i].self_offset, cl->list[i].offset, + // "+-"[cl->list[i].strand]); + // } + // } + + + + i = z->shared_seed; pid = cl->list[i].readID; + for (; i < cn && cl->list[i].readID == pid && cl->list[i].readID != ((uint32_t)(0x7fffffff)); i++); + scn = i - z->shared_seed; ca = cl->list+z->shared_seed; + i = lchain_refine(ca, scn, ca, &(cl->chainDP), 50, 5000, 512, 16); cn = i; + for (; i < scn; i++) ca[i].readID = ((uint32_t)(0x7fffffff)); + // if(z->y_id == 30129) fprintf(stderr, "\n-a-[M::%s]\tcn::%ld\n", __func__, cn); + + + // if(z->y_id == 30129) { + // fprintf(stderr, "\n-1-[M::%s]\tutg%.6ul\tx::[%u,\t%u)\t%c\tutg%.6ul\ty::[%u,\t%u)\n", + // __func__, z->x_id+1, z->x_pos_s, z->x_pos_e+1, + // "+-"[z->y_pos_strand], z->y_id+1, z->y_pos_s, z->y_pos_e+1); + // i = z->shared_seed; pid = cl->list[i].readID; cn = cl->length; + // for (; i < cn && cl->list[i].readID == pid && cl->list[i].readID != ((uint32_t)(0x7fffffff)); i++) { + // fprintf(stderr, "i::%ld[M::%s]\treadID::%u\tself_offset::%u\toffset::%u\t%c\n", + // i, __func__, cl->list[i].readID, cl->list[i].self_offset, cl->list[i].offset, + // "+-"[cl->list[i].strand]); + // } + // } + return cn; +} + +// int64_t gen_mix_tchain(Candidates_list *cl, int64_t kidx, int64_t kn, ul_ov_t *oa, int64_t on) +// { +// int64_t rcn = cl->length, kk, ok; +// kv_resize_cl(k_mer_hit, *cl, rcn+kn); +// kk = ok = 0; +// while(kk < kn && ok < on) { +// if(cl->list[kidx+kk].offset) +// } +// } + + +uint64_t gen_woff_idx(overlap_region *z, asg64_v *oidx) +{ + uint64_t mm, k, aln = 0; + kv_resize(uint64_t, *oidx, (z->w_list.n<<1)+2); + mm = z->x_pos_s; mm <<= 32; mm += z->y_pos_s; kv_push(uint64_t, *oidx, mm); + for (k = oidx->n = 0; k < z->w_list.n; k++) { + mm = z->w_list.a[k].x_start; mm <<= 32; mm += z->w_list.a[k].y_start; + if((oidx->n == 0) && (mm != oidx->a[oidx->n-1])) { + kv_push(uint64_t, *oidx, mm); + } + + mm = z->w_list.a[k].x_end; mm <<= 32; mm += z->w_list.a[k].y_end; + if((oidx->n == 0) && (mm != oidx->a[oidx->n-1])) { + kv_push(uint64_t, *oidx, mm); + } + if(!(is_ualn_win(z->w_list.a[k]))) aln += z->w_list.a[k].x_end - z->w_list.a[k].x_start; + } + mm = z->x_pos_e; mm <<= 32; mm += z->y_pos_e; + if((oidx->n == 0) && (mm != oidx->a[oidx->n-1])) { + kv_push(uint64_t, *oidx, mm); + } + return aln; +} + +//return [rq, rt] +void win_boundary_offset(window_list *a, int64_t w_n, int64_t wi, int64_t toff, int64_t ql, int64_t *rq, int64_t *rt) +{ + int64_t q[2], t[2], qdis, tdis, dis; q[0] = q[1] = t[0] = t[1] = -1; + ///[q[0], q[1]] && [t[0], t[1]] + if(toff >= a[wi].y_start && toff <= a[wi].y_end) {///within the window + q[0] = a[wi].x_start; q[1] = a[wi].x_end; + t[0] = a[wi].y_start; t[1] = a[wi].y_end; + } else if(toff < a[wi].y_start) {///before the window + if(wi > 0) { + q[0] = a[wi-1].x_end+1; q[1] = a[wi].x_start-1; + t[0] = a[wi-1].y_end+1; t[1] = a[wi].y_start-1; + } else { + qdis = a[wi].x_start; + tdis = a[wi].y_start - toff; + dis = MIN(qdis, tdis); + (*rq) = a[wi].x_start - dis; + (*rt) = a[wi].y_start - dis; + } + } else if(toff > a[wi].y_end) {//after the window + if(wi < w_n - 1) { + q[0] = a[wi].x_end+1; q[1] = a[wi+1].x_start-1; + t[0] = a[wi].y_end+1; t[1] = a[wi+1].y_start-1; + } else { + qdis = ql-1-a[wi].x_end; + tdis = toff-a[wi].y_end; + dis = MIN(qdis, tdis); + (*rq) = a[wi].x_end + dis; + (*rt) = a[wi].y_end + dis; + } + } + + if(q[0] >= 0 && q[1] >= 0 && t[0] >= 0 && t[1] >= 0) { + (*rt) = toff; + (*rq) = q[0] + get_offset_adjust(toff-t[0], t[1]-t[0], q[1]-q[0]); + } +} + +int64_t hc_aln_exz_simi_adv(int64_t id, int64_t rev, const ul_idx_t *uref, hpc_t *hpc_g, +All_reads *rref, char* qstr, UC_Read *tu, int64_t qs, int64_t qe, int64_t ts, int64_t te, +int64_t qmin, int64_t qmax, int64_t tmin, int64_t tmax, int64_t mode, bit_extz_t *exz, int64_t q_tot, +double e_rate, int64_t maxl, int64_t maxe, int64_t force_l, int64_t estimate_err, overlap_region *z, +int64_t gen_trace) +{ + clear_align(*exz); exz->thre = 0; ///mode cannot be 3 + int64_t thre, ql = qe - qs, thre0, pts = -1, pte = -1, pthre = -1, t_tot; + if(estimate_err < 0) estimate_err = ql*e_rate; + if(ql <= 0) return 0; + if(hpc_g) t_tot = hpc_len(*hpc_g, id); + else if(uref) t_tot = uref->ug->u.a[id].len; + else t_tot = Get_READ_LENGTH((*rref), id); + + // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { + // fprintf(stderr, "-0-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld)\n", + // __func__, mode, qs, qe, ts, te); + // } + + if(ql <= 16) { + if(cal_exact_simi_exz(uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, q_tot, + t_tot, rev, id, mode, z)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::0(+)\n", exz->err, exz->thre); + return 1; + } + } + + // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { + // fprintf(stderr, "-a-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), ql::%ld, maxl::%ld, estimate_err::%ld, maxe::%ld\n", + // __func__, mode, qs, qe, ts, te, ql, maxl, estimate_err, maxe); + // } + + if(ql <= maxl && (estimate_err>>1) <= maxe) { + thre = scale_ed_thre(estimate_err, maxe); + // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { + // fprintf(stderr, "-1-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), thre::%ld\n", + // __func__, mode, qs, qe, ts, te, thre); + // } + if(cal_exz_infi_simi_adv(uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, + qmin, qmax, tmin, tmax, rev, id, mode, z, gen_trace)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(+)\n", exz->err, exz->thre, thre); + // push_alnw(aux_o, exz); + return 1; + } + + thre0 = thre; thre = ql*e_rate; thre = scale_ed_thre(thre, maxe); + // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { + // fprintf(stderr, "-2-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), thre::%ld\n", + // __func__, mode, qs, qe, ts, te, thre); + // } + if(thre > thre0) { + if(cal_exz_infi_simi_adv(uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, + qmin, qmax, tmin, tmax, rev, id, mode, z, gen_trace)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); + // push_alnw(aux_o, exz); + return 1; + } + } + + thre0 = thre; thre <<= 1; thre = scale_ed_thre(thre, maxe); + // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { + // fprintf(stderr, "-3-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), thre::%ld\n", + // __func__, mode, qs, qe, ts, te, thre); + // } + if(thre > thre0) { + if(cal_exz_infi_simi_adv(uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, + qmin, qmax, tmin, tmax, rev, id, mode, z, gen_trace)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(-)\n", exz->err, exz->thre, thre); + // push_alnw(aux_o, exz); + return 1; + } + } + + thre0 = thre; thre = ql*0.51; thre = scale_ed_thre(thre, maxe); + // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { + // fprintf(stderr, "-4-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), thre::%ld\n", + // __func__, mode, qs, qe, ts, te, thre); + // } + if(thre > thre0) { + if(cal_exz_infi_simi_adv(uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, + qmin, qmax, tmin, tmax, rev, id, mode, z, gen_trace)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); + // push_alnw(aux_o, exz); + return 1; + } + } + + if(ql <= force_l) { + thre = maxe; + // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { + // fprintf(stderr, "-5-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld), thre::%ld\n", + // __func__, mode, qs, qe, ts, te, thre); + // } + if(cal_exz_infi_simi_adv(uref, hpc_g, rref, exz, qstr, tu, qs, qe, ts, te, &pts, &pte, thre, &pthre, + qmin, qmax, tmin, tmax, rev, id, mode, z, gen_trace)) { + // ref_cigar_check(qstr, tu, uref, hpc_g, rref, z->y_id, z->y_pos_strand, exz); + // fprintf(stderr, ", err::%d, thre::%d, scale::%ld(*)\n", exz->err, exz->thre, thre); + // push_alnw(aux_o, exz); + return 1; + } + } + } + + // if(ts == 18327 && te == 18601 && qs == 145990 && qe == 146191) { + // fprintf(stderr, "-b-[M::%s::] mode::%ld, q::[%ld, %ld), t::[%ld, %ld)\n", + // __func__, mode, qs, qe, ts, te); + // } + // fprintf(stderr, ", err::%d, thre::%d\n", INT32_MAX, exz->thre); + // if(mode == 0) { + // fprintf(stderr, "[M::%s::] pstr::%.*s\n", __func__, (int32_t)tu->length, tu->seq); + // fprintf(stderr, "[M::%s::] tstr::%.*s\n", __func__, (int32_t)(qe-qs), qstr+qs); + // } + return 0; + +} + +#define update_ul_ov_t_coor(z, qbeg, qend, tbeg, tend) do {\ + if(((int64_t)(z).qs) > (qbeg)) (z).qs = (qbeg);\ + if(((int64_t)(z).qe) < (qend)) (z).qe = (qend);\ + if(((int64_t)(z).ts) > (tbeg)) (z).ts = (tbeg);\ + if(((int64_t)(z).te) < (tend)) (z).te = (tend);\ + } while (0) + +///[ps, pe) && [ts, te]) +int64_t hc_aln_exz_by_exist_cigar_with_p(bit_extz_t *ez, int64_t mode, int64_t ps, int64_t pe, +int64_t *ts, int64_t *te, int64_t *cis, int64_t *cie, int64_t *cps, int64_t *cpe, int64_t *cts, int64_t *cte) +{ + int64_t ts0 = (*ts), te0 = (*te), ts1, te1; + assert(ez->ps <= ps && ez->pe+1 >= pe && mode > 0); + if(mode == 1) (*te) = -1; + else if(mode == 2) (*ts) = -1; + else (*ts) = (*te) = -1; + (*cis) = (*cie) = (*cps) = (*cpe) = (*cts) = (*cte) = -1; + + int32_t pi = ez->ps, ti = ez->ts, pi0, ti0, err[2], tot_err, ws, we; + uint32_t ci = 0, cl; uint16_t c, sset = 0, eset = 0; + err[0] = err[1] = tot_err = 0; + while (ci < ez->cigar.n) { + ci = pop_trace(&(ez->cigar), ci, &c, &cl); + ws = pi; pi0 = pi; ti0 = ti; + if(c <= 1) { + pi+=cl; ti+=cl; + } else if(c == 2) {///more p + pi+=cl; + } else if(c == 3) { + ti+=cl; + } + we = pi; + // if((ps == 5139) && (pe == 21733)) { + // fprintf(stderr, "[M::%s::ci->%u] wp::[%d, %d), pi::%d, ti::%d, c::%u, cl::%u, tot_err::%d, p::[%ld, %ld), t::[%ld, %ld)\n", + // __func__, ci, ws, we, pi, ti, c, cl, tot_err, ps, pe, (*ts), (*te)); + // } + if(we < ps) {///not we <= ps + if(c != 0) tot_err += cl; + continue; + } + if(ws > pe) {///not ws >= pe + if(c != 0) tot_err += cl; + break; + } + + if(!sset) { + if((ps>=ws) && (ps%u] c::%u, cl::%u\n", __func__, ci, c, cl); + // } + if(c <= 1) { + ts1 = ti - (we - ps); + if((ts1 == ts0) || (mode != 1)) { + if(c == 1) err[0] = tot_err + (ps - ws); + else err[0] = tot_err; + sset = 1; (*ts) = ts1; + (*cis) = ci-1; (*cps) = pi0; (*cts) = ti0; + } + } else if(c == 2) {///more p + // ts1 = ti - (we - ps); + ts1 = ti; + if((ts1 == ts0) || (mode != 1)) { + err[0] = tot_err + (ps - ws); + sset = 1; (*ts) = ts1; + (*cis) = ci-1; (*cps) = pi0; (*cts) = ti0; + } + } else if(c == 3) { + ts1 = ti; + if((ts1 == ts0) || (mode != 1)) { + err[0] = tot_err + cl; + sset = 1; (*ts) = ts1; + (*cis) = ci-1; (*cps) = pi0; (*cts) = ti0; + } + } + } + + if((c == 3) && (ps>=ws) && (ps<=we)) { + // if((ps == 5139) && (pe == 21733)) { + // fprintf(stderr, "-[M::%s::ci->%u] c::%u, cl::%u\n", __func__, ci, c, cl); + // } + ts1 = ti - cl; + if(ts1 == ts0) { + err[0] = tot_err; sset = 1; (*ts) = ts1; + (*cis) = ci-1; (*cps) = pi0; (*cts) = ti0; + } + } + } + + if(!eset) { + if((pe>ws) && (pe<=we)) { + if(c <= 1) { + te1 = ti - (we - pe); + if((te1 == te0) || (mode != 2)) { + if(c == 1) err[1] = tot_err + (pe - ws); + else err[1] = tot_err; + eset = 1; (*te) = te1; + (*cie) = ci; (*cpe) = pi; (*cte) = ti; + } + } else if(c == 2) {///more p + // te1 = ti - (we - pe); + te1 = ti; + if((te1 == te0) || (mode != 2)) { + err[1] = tot_err + (pe - ws); + eset = 1; (*te) = te1; + (*cie) = ci; (*cpe) = pi; (*cte) = ti; + } + } else if(c == 3) { + te1 = ti-cl; + if((te1 == te0) || (mode != 2)) { + err[1] = tot_err; + eset = 1; (*te) = te1; + (*cie) = ci; (*cpe) = pi; (*cte) = ti; + } + } + } + if((c == 3) && (pe>=ws) && (pe<=we)) { + te1 = ti; + if(te1 == te0) { + err[1] = tot_err + cl; + eset = 1; (*te) = te1; + (*cie) = ci; (*cpe) = pi; (*cte) = ti; + } + } + if(eset) break; + } + + if(c != 0) tot_err += cl; + } + + // if(!(((mode == 1)&&((*ts) == ts0))||((mode == 2)&&((*te) == te0))||(mode == 3))) { + // fprintf(stderr, "+[M::%s::mode->%ld] t0::[%ld, %ld), t::[%ld, %ld), err::%d\n", + // __func__, mode, ts0, te0, (*ts), (*te), err[1] - err[0]); + // } + assert(((mode == 1)&&((*ts) == ts0))||((mode == 2)&&((*te) == te0))||(mode == 3)); + return err[1] - err[0]; +} + + +inline void update_trace_idx(rtrace_t *tc, int64_t wid, int64_t wid_s, int64_t wid_e, +int64_t qs, int64_t qe, int64_t ts, int64_t te) +{ + if(qs < tc->c_qs || ts < tc->c_ts) { + tc->c_qs = qs; + tc->c_ts = ts; + tc->c_wsid = wid; + tc->c_wsii = wid_s; + } + + if(qe > tc->c_qe || te > tc->c_te) { + tc->c_qe = qe; + tc->c_te = te; + tc->c_weid = wid; + tc->c_weii = wid_e; + } +} + +int64_t scan_single_wcigar(bit_extz_t *ez, int64_t csi, int64_t cei, int64_t cps, int64_t cpe, int64_t cts, int64_t cte, +int64_t tar_ps, int64_t tar_pe, int64_t tar_ts, int64_t tar_te) +{ + int64_t ci = csi, pi = cps, ti = cts, ws, we; + int64_t tot_err[2] = {0}, err[2] = {0}, ts1, te1; uint32_t cl; + uint16_t c, sset = 0, eset = 0; + while (ci < cei) { + ci = pop_trace(&(ez->cigar), ci, &c, &cl); + ws = pi; + if(c <= 1) { + pi+=cl; ti+=cl; + } else if(c == 2) {///more p + pi+=cl; + } else if(c == 3) { + ti+=cl; + } + we = pi; + // if(cps == 4489 && cpe == 16192) { + // fprintf(stderr, "[M::%s::ci->%ld] wp::[%ld, %ld), pi::%ld, ti::%ld, c::%u, cl::%u, tot_err::%ld\n", + // __func__, ci, ws, we, pi, ti, c, cl, tot_err[0]); + // } + if(we < tar_ps) {///not we <= ps + if(c != 0) tot_err[0] += cl; + continue; + } + if(ws > tar_pe) {///not ws >= pe + if(c != 0) tot_err[0] += cl; + break; + } + + if(!sset) { + if((tar_ps>=ws) && (tar_ps=ws) && (tar_ps<=we)) { + ts1 = ti - cl; + if(ts1 == tar_ts) { + err[0] = tot_err[0]; sset = 1; + } + } + } + + if(!eset) { + if((tar_pe>ws) && (tar_pe<=we)) { + if(c <= 1) { + te1 = ti - (we - tar_pe); + if(te1 == tar_te) { + if(c == 1) err[1] = tot_err[0] + (tar_pe - ws); + else err[1] = tot_err[0]; + eset = 1; + } + } else if(c == 2) {///more p + // te1 = ti - (we - tar_pe); + te1 = ti; + if(te1 == tar_te) { + err[1] = tot_err[0] + (tar_pe - ws); + eset = 1; + } + } else if(c == 3) { + te1 = ti-cl; + if(te1 == tar_te) { + err[1] = tot_err[0]; + eset = 1; + } + } + } + if((c == 3) && (tar_pe>=ws) && (tar_pe<=we)) { + te1 = ti; + if(te1 == tar_te) { + err[1] = tot_err[0] + cl; + eset = 1; + } + } + if(eset) break; + } + + if(c != 0) tot_err[0] += cl; + // fprintf(stderr, "[M::%s::ci->%ld] tot_err::%ld, c::%u\n", __func__, ci, tot_err[0], c); + } + return err[1] - err[0]; +} + + +int64_t scan_single_wcigar_toff_backward_backup(bit_extz_t *ez, int64_t csi, int64_t cei, int64_t cps, int64_t cpe, int64_t cts, int64_t cte, +int64_t tar_ps, int64_t tar_pe, int64_t tar_ts, int64_t tar_te) +{ + int64_t ci = cei-1, pi = cpe, ti = cte, wts, wte; + int64_t tot_err = 0, err[2] = {0}, ps1, pe1; + uint16_t c, sset = 0, eset = 0; uint32_t cl; + while (ci >= csi) { + ci = pop_trace_back(&(ez->cigar), ci, &c, &cl); + wte = ti; + if(c <= 1) { + pi-=cl; ti-=cl; + } else if(c == 2) {///more p + pi-=cl; + } else if(c == 3) { + ti-=cl; + } + wts = ti; + // if(tar_ts == 0 && tar_te == 14233 && cts == 0 && cte == 14233) { + // fprintf(stderr, "[M::%s::ci->%ld] wt::[%ld, %ld), pi::%ld, ti::%ld, c::%u, cl::%u, tot_err::%ld, err[0]::%ld, err[1]::%ld\n", + // __func__, ci, wts, wte, pi, ti, c, cl, tot_err[0], err[0], err[1]); + // } + if(wte < tar_ts) {///not we <= ps + if(c != 0) tot_err += cl; + break; + } + if(wts > tar_te) {///not ws >= pe + if(c != 0) tot_err += cl; + continue; + } + + if(!sset) { + // if(tar_ts == 19030 && tar_te == 31898 && cts == 19030 && cte == 31983) { + // fprintf(stderr, "+[M::%s::ci->%ld] wt::[%ld, %ld), tar_t::[%ld, %ld)\n", + // __func__, ci, wts, wte, tar_ts, tar_te); + // } + if((tar_ts>=wts) && (tar_ts=wts) && (tar_ts<=wte)) {///more p + // ps1 = pi; + // if(ps1 == tar_ps) { + // err[0] = tot_err[0] + cl; sset = 1; + // } + if(tar_ps >= pi && tar_ps < pi + cl) { + err[0] = tot_err + (pi + cl - tar_ps); + sset = 1; + } + } + if(sset) break; + } + + if(!eset) { + if((tar_te>wts) && (tar_te<=wte)) { + assert(c != 2); + if(c <= 1) { + pe1 = pi + (tar_te - wts); + // if(tar_ts == 19030 && tar_te == 31898 && cts == 19030 && cte == 31983) { + // fprintf(stderr, "-[M::%s::ci->%ld] wt::[%ld, %ld), tar_t::[%ld, %ld), pe1::%ld, tar_pe::%ld\n", + // __func__, ci, wts, wte, tar_ts, tar_te, pe1, tar_pe); + // } + if(pe1 == tar_pe) { + if(c == 1) err[1] = tot_err + (wte - tar_te); + else err[1] = tot_err; + eset = 1; + } + } else if(c == 3) {///more t + pe1 = pi; + if(pe1 == tar_pe) { + err[1] = tot_err + (wte - tar_te); + eset = 1; + } + } + } + + if((c == 2) && (tar_te>=wts) && (tar_te<=wte)) {///more p + // pe1 = pi; + // if(pe1 == tar_pe) { + // err[1] = tot_err[0] + cl; eset = 1; + // } + if(tar_pe >= pi && tar_pe < pi + cl) { + err[1] = tot_err + (pi + cl - tar_pe); + eset = 1; + } + } + } + + if(c != 0) tot_err += cl; + // fprintf(stderr, "[M::%s::ci->%ld] tot_err::%ld, c::%u\n", __func__, ci, tot_err[0], c); + } + return err[0] - err[1]; +} + + +int64_t scan_single_wcigar_toff_backward(bit_extz_t *ez, int64_t csi, int64_t cei, int64_t cps, int64_t cpe, int64_t cts, int64_t cte, +int64_t tar_ps, int64_t tar_pe, int64_t tar_ts, int64_t tar_te) +{ + int64_t ci = cei-1, pi = cpe, ti = cte, wts, wte; + int64_t e = 0, ps1, pe1; + uint16_t c, sset = 0, eset = 0, ff[2]; uint32_t cl; + while (ci >= csi) { + ci = pop_trace_back(&(ez->cigar), ci, &c, &cl); + wte = ti; + if(c <= 1) { + pi-=cl; ti-=cl; + } else if(c == 2) {///more p + pi-=cl; + } else if(c == 3) { + ti-=cl; + } + wts = ti; ff[0] = ff[1] = 0; + // if(tar_ts == 0 && tar_te == 14233 && cts == 0 && cte == 14233) { + // fprintf(stderr, "[M::%s::ci->%ld] wt::[%ld, %ld), pi::%ld, ti::%ld, c::%u, cl::%u, tot_err::%ld, err[0]::%ld, err[1]::%ld\n", + // __func__, ci, wts, wte, pi, ti, c, cl, tot_err[0], err[0], err[1]); + // } + if(wte < tar_ts) {///not we <= ps + if(c != 0) e += cl; + break; + } + if(wts > tar_te) {///not ws >= pe + if(c != 0) e += cl; + continue; + } + + if(!eset) { + if((tar_te>wts) && (tar_te<=wte)) { + assert(c != 2); + if(c <= 1) { + pe1 = pi + (tar_te - wts); + if(pe1 == tar_pe) { + if(c == 1) e = tar_te - wts; + else e = 0; + eset = 1; + } + } else if(c == 3) {///more t + pe1 = pi; + if(pe1 == tar_pe) { + e = tar_te - wts; + eset = 1; + } + } + } + + if((c == 2) && (tar_te==wts) && (tar_te==wte)) {///more p + if(tar_pe >= pi && tar_pe < pi + cl) { + e = tar_pe - pi; + eset = 1; + } + } + // if(eset) continue; + if(eset) ff[0] = 1; + } + + + if(!sset) { + // if(tar_ts == 19030 && tar_te == 31898 && cts == 19030 && cte == 31983) { + // fprintf(stderr, "+[M::%s::ci->%ld] wt::[%ld, %ld), tar_t::[%ld, %ld)\n", + // __func__, ci, wts, wte, tar_ts, tar_te); + // } + if((tar_ts>=wts) && (tar_ts= pi && tar_ps < pi + cl) { + e += (pi + cl - tar_ps); + sset = 1; + } + } + // if(sset) break; + if(sset) ff[1] = 1; + } + + if(ff[1]) break; + if(ff[0]) continue; + if(c!=0) e += cl; + // fprintf(stderr, "[M::%s::ci->%ld] tot_err::%ld, c::%u\n", __func__, ci, tot_err[0], c); + } + return e; +} + + +int64_t debug_aln_err(overlap_region *o, int64_t qs, int64_t qe, int64_t ts, int64_t te, double e_rate, +int64_t estz_err, const ul_idx_t *uref, char* qstr, UC_Read *tu, bit_extz_t *exz) +{ + int64_t ql = qe - qs, tl = te - ts, id = o->y_id, rev = o->y_pos_strand; + if((!ql) && (!tl)) return 0; + if((!ql) && (tl)) return tl; + if((ql) && (!tl)) return ql; + if(estz_err < 0) estz_err = -1; + if(hc_aln_exz_simi_adv(id, rev, uref, NULL, NULL, qstr, tu, qs, qe, ts, te, + qs, qe, ts, te, 0, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E, FORCE_CNS_L, estz_err, NULL, 0)) { + return exz->err; + } else { + return gen_err_unaligned(ql, tl); + } +} + +int64_t get_sub_cigar_err(ul_ov_t *aln, rtrace_t *tc, const ul_idx_t *uref, char* qstr, UC_Read *tu, overlap_region *o, bit_extz_t *exz, double e_rate, int64_t is_rev) +{ + int64_t k, q[2], t[2], cq[2], ct[2], ci[2], err, qwl, twl; + window_list *wa = o->w_list.a; bit_extz_t aux; + if(!is_rev) { + err = 0; q[0] = aln->qs; t[0] = aln->ts; + for (k = tc->c_wsid; k <= tc->c_weid; k++) { + q[1] = wa[k].x_start; t[1] = wa[k].y_start; + if(q[0] <= q[1] && t[0] <= t[1]) { + err += debug_aln_err(o, q[0], q[1], t[0], t[1], e_rate, k==tc->c_wsid?tc->pfx_e:-1, uref, qstr, tu, exz); + // fprintf(stderr, "-0-[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), err::%ld\n", + // __func__, k, q[0], q[1], t[0], t[1], err); + } + + cq[0] = q[0] = wa[k].x_start; cq[1] = q[1] = wa[k].x_end+1; + ct[0] = t[0] = wa[k].y_start; ct[1] = t[1] = wa[k].y_end+1; + ci[0] = 0; ci[1] = wa[k].clen; qwl = q[1] - q[0]; twl = t[1] - t[0]; + if(is_ualn_win(wa[k])) { + err += gen_err_unaligned(qwl, twl); + // fprintf(stderr, "-1-[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), err::%ld\n", + // __func__, k, q[0], q[1], t[0], t[1], err); + } else { + set_bit_extz_t(aux, (*o), k); + if(k == tc->c_wsid) { + cq[0] = tc->c_qs; ct[0] = tc->c_ts; ci[0] = tc->c_wsii; + q[0] = MAX((int32_t)aln->qs, tc->c_qs); + t[0] = MAX((int32_t)aln->ts, tc->c_ts); + } + if(k == tc->c_weid) { + cq[1] = tc->c_qe; ct[1] = tc->c_te; ci[1] = tc->c_weii; + q[1] = MIN((int32_t)aln->qe, tc->c_qe); + t[1] = MIN((int32_t)aln->te, tc->c_te); + } + // err += scan_single_wcigar(&aux, ci[0], ci[1], ct[0], ct[1], cq[0], cq[1], + // t[0], t[1], q[0], q[1]); + err += scan_single_wcigar_toff_backward(&aux, ci[0], ci[1], ct[0], ct[1], cq[0], cq[1], + t[0], t[1], q[0], q[1]); + // fprintf(stderr, "-2-[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), err::%ld, cq::[%ld, %ld), ct::[%ld, %ld)\n", + // __func__, k, q[0], q[1], t[0], t[1], err, cq[0], cq[1], ct[0], ct[1]); + } + q[0] = q[1]; t[0] = t[1]; + } + + q[1] = aln->qe; t[1] = aln->te; + if(q[0] <= q[1] && t[0] <= t[1]) { + err += debug_aln_err(o, q[0], q[1], t[0], t[1], e_rate, tc->sfx_e, uref, qstr, tu, exz); + // fprintf(stderr, "-3-[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), err::%ld\n", + // __func__, k, q[0], q[1], t[0], t[1], err); + } + } else { + err = 0; q[1] = aln->qe; t[1] = aln->te; + for (k = tc->c_weid; k >= tc->c_wsid; k--) { + q[0] = wa[k].x_end+1; t[0] = wa[k].y_end+1; + if(q[0] <= q[1] && t[0] <= t[1]) { + err += debug_aln_err(o, q[0], q[1], t[0], t[1], e_rate, k==tc->c_weid?tc->sfx_e:-1, uref, qstr, tu, exz); + } + + cq[0] = q[0] = wa[k].x_start; cq[1] = q[1] = wa[k].x_end+1; + ct[0] = t[0] = wa[k].y_start; ct[1] = t[1] = wa[k].y_end+1; + ci[0] = 0; ci[1] = wa[k].clen; qwl = q[1] - q[0]; twl = t[1] - t[0]; + if(is_ualn_win(wa[k])) { + err += gen_err_unaligned(qwl, twl); + } else { + set_bit_extz_t(aux, (*o), k); + if(k == tc->c_wsid) { + cq[0] = tc->c_qs; ct[0] = tc->c_ts; ci[0] = tc->c_wsii; + q[0] = MAX((int32_t)aln->qs, tc->c_qs); + t[0] = MAX((int32_t)aln->ts, tc->c_ts); + } + if(k == tc->c_weid) { + cq[1] = tc->c_qe; ct[1] = tc->c_te; ci[1] = tc->c_weii; + q[1] = MIN((int32_t)aln->qe, tc->c_qe); + t[1] = MIN((int32_t)aln->te, tc->c_te); + } + // err += scan_single_wcigar(&aux, ci[0], ci[1], ct[0], ct[1], cq[0], cq[1], + // t[0], t[1], q[0], q[1]); + err += scan_single_wcigar_toff_backward(&aux, ci[0], ci[1], ct[0], ct[1], cq[0], cq[1], + t[0], t[1], q[0], q[1]); + } + q[1] = q[0]; t[1] = t[0]; + } + + q[0] = aln->qs; t[0] = aln->ts; + if(q[0] <= q[1] && t[0] <= t[1]) { + err += debug_aln_err(o, q[0], q[1], t[0], t[1], e_rate, tc->pfx_e, uref, qstr, tu, exz); + } + } + // fprintf(stderr, "[M::%s::] err::%ld, aln_err::%u\n", __func__, err, aln->sec); + return err; +} + + +void gen_clip_win_err(overlap_region *o, int64_t qs, int64_t qe, int64_t ts, int64_t te, double e_rate, +int64_t estz_err, const ul_idx_t *uref, char* qstr, UC_Read *tu, bit_extz_t *exz) +{ + int64_t ql = qe - qs, tl = te - ts, id = o->y_id, rev = o->y_pos_strand; + exz->ts = qs; exz->te = qe-1; exz->ps = ts; exz->pe = te-1; + exz->cigar.n = 0; exz->thre = exz->err = INT32_MAX; + if((!ql) && (!tl)) { + exz->err = 0; return; + } + if((!ql) && (tl)) { + exz->err = tl; return; + } + if((ql) && (!tl)) { + exz->err = ql; return; + } + if(estz_err < 0) estz_err = -1; + if(hc_aln_exz_simi_adv(id, rev, uref, NULL, NULL, qstr, tu, qs, qe, ts, te, + qs, qe, ts, te, 0, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E, FORCE_CNS_L, estz_err, NULL, 1)) { + return; + } else { + exz->ts = qs; exz->te = qe-1; exz->ps = ts; exz->pe = te-1; + exz->cigar.n = 0; exz->thre = INT32_MAX; + exz->err = gen_err_unaligned(ql, tl); + return; + } +} + + +int64_t extract_sub_werr(bit_extz_t *ez, int64_t csi, int64_t cei, int64_t cps, int64_t cpe, int64_t cts, int64_t cte, +int64_t tar_ps, int64_t tar_pe, int64_t tar_ts, int64_t tar_te, int64_t spec_toff, rtrace_iter *idx) +{ + if(idx->toff >= tar_pe && idx->qoff >= tar_te) { + idx->coff = cei-1; + idx->toff = cpe; + idx->qoff = cte; + idx->cerr = 0; + } + if(!(is_align(*ez))) return INT32_MAX; + if(!(ez->cigar.n)) return (((double)(tar_te-spec_toff))/((double)(tar_te-tar_ts)))*ez->err; + + int64_t ci = idx->coff, pi = idx->toff, ti = idx->qoff, err = idx->cerr; + int64_t t[2], ci0, pi0, ti0, err0, re = INT32_MAX, wts, wte, ps1, pe1; + uint16_t c, sset = 0, eset = 0, ff[2]; uint32_t cl; + while (ci >= csi) { + ci0 = ci; pi0 = pi; ti0 = ti; err0 = err; + ci = pop_trace_back(&(ez->cigar), ci, &c, &cl); + wte = ti; + if(c <= 1) { + pi-=cl; ti-=cl; + } else if(c == 2) {///more p + pi-=cl; + } else if(c == 3) { + ti-=cl; + } + wts = ti; ff[0] = ff[1] = 0; + t[0] = wts; t[1] = wte; + // if(spec_toff == 118374) { + // fprintf(stderr, "+[M::%s::ci->%ld::cl->%u::c->%u] spec_toff::%ld, t::[%ld, %ld), p::[%ld, %ld), err0::%ld\n", + // __func__, ci, cl, c, spec_toff, ti, ti0, pi, pi0, err0); + // } + + if(wte < tar_ts) {///not we <= ps + if(c != 0) err += cl; + break; + } + if(wts > tar_te) {///not ws >= pe + if(c != 0) err += cl; + continue; + } + + if(!eset) { + if((tar_te>wts) && (tar_te<=wte)) { + assert(c != 2); + if(c <= 1) { + pe1 = pi + (tar_te - wts); + if(pe1 == tar_pe) { + if(c == 1) err = tar_te - wts; + else err = 0; + eset = 1; + } + } else if(c == 3) {///more t + pe1 = pi; + if(pe1 == tar_pe) { + err = tar_te - wts; + eset = 1; + } + } + } + + if((c == 2) && (tar_te>=wts) && (tar_te<=wte)) {///more p + if(tar_pe >= pi && tar_pe < pi + cl) { + err = tar_pe - pi; + eset = 1; + } + } + if(eset) { + ff[0] = 1; t[1] = tar_te; + } + } + + + if(!sset) { + if((tar_ts>=wts) && (tar_ts=wts) && (tar_ts<=wte)) {///more p + if(tar_ps >= pi && tar_ps < pi + cl) { + err += (pi + cl - tar_ps); + sset = 1; + } + } + if(sset) { + ff[1] = 1; t[0] = tar_ts; + } + } + + // if(spec_toff == 118374) { + // fprintf(stderr, "-[M::%s::ci->%ld::cl->%u::c->%u] spec_toff::%ld, t::[%ld, %ld), p::[%ld, %ld), err0::%ld\n", + // __func__, ci, cl, c, spec_toff, ti, ti0, pi, pi0, err0); + // } + if(spec_toff > t[1]) break; + + if((spec_toff >= t[0] && spec_toff < t[1]) || (spec_toff == t[0] && spec_toff == t[1])) { + re = err + (((!ff[1]) && (!ff[0]) && (c!=0))?cl:0); + if(c == 1 || c == 3) re -= (spec_toff - t[0]); + idx->coff = ci0; + idx->toff = pi0; + idx->qoff = ti0; + idx->cerr = err0; + // return re; + } + if(ff[1]) break; + if(ff[0]) continue; + if(c!=0) err += cl; + } + return re; +} + +//get error within [qe, ql) +int64_t get_rid_backward_cigar_err_back(rtrace_iter *it, ul_ov_t *aln, kv_rtrace_t *trace, rtrace_t *tc, +const ul_idx_t *uref, char* qstr, UC_Read *tu, overlap_region_alloc *ol, overlap_region *o, +bit_extz_t *exz, double e_rate, int64_t qs) +{ + if(qs == aln->qe) return 0; + if(!tc) tc = &(trace->a[aln->qn]); + if(!o) o = &(ol->list[tc->oid]); + + if(it->k == INT32_MAX) { + it->k = tc->c_weid; + it->q[1] = aln->qe; + it->t[1] = aln->te; + it->werr = it->cerr = 0; + it->qoff = aln->qe; + it->toff = aln->te; + it->coff = INT32_MAX; + clear_align(*exz); + exz->ps = exz->pe = exz->ts = exz->te = INT32_MAX; + } + window_list *wa = o->w_list.a; int64_t qwl, twl, sub_err; bit_extz_t aux; + assert(qs <= it->qoff); + + for (; it->k >= tc->c_wsid; it->k--) { + it->q[0] = wa[it->k].x_end+1; + it->t[0] = wa[it->k].y_end+1; + // if(qs == 166327) { + // fprintf(stderr, "-0-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld\n", + // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs); + // } + + if(it->qoff > it->q[0]) {///[it->qoff, ql) has been calculated + if(it->q[0] <= it->q[1] && it->t[0] <= it->t[1]) { + if((exz->ps != it->t[0]) || (exz->pe != it->t[1]) || (exz->ts != it->q[0]) || (exz->te == it->q[1])) { + ///calculate on-the-fly + gen_clip_win_err(o, it->q[0], it->q[1], it->t[0], it->t[1], e_rate, it->k==tc->c_weid?tc->sfx_e:-1, uref, qstr, tu, exz); + } + // fprintf(stderr, "-1-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld\n", + // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs); + if(qs >= it->q[0] && qs < it->q[1]) { + ///phrase cigar + sub_err = extract_sub_werr(exz, 0, exz->cigar.n, exz->ps, exz->pe+1, exz->ts, exz->te+1, + exz->ps, exz->pe+1, exz->ts, exz->te+1, qs, it); + if(qs == it->q[0]) { + it->werr += sub_err; sub_err = 0; + it->qoff = it->q[0]; it->toff = it->t[0]; + } + return it->werr+sub_err; + } + it->qoff = it->q[0]; + it->toff = it->t[0]; + it->werr += exz->err; + } + } + if(qs == it->qoff) return it->werr; + + it->cq[0] = it->q[0] = wa[it->k].x_start; it->cq[1] = it->q[1] = wa[it->k].x_end+1; + it->ct[0] = it->t[0] = wa[it->k].y_start; it->ct[1] = it->t[1] = wa[it->k].y_end+1; + it->ci[0] = 0; it->ci[1] = wa[it->k].clen; qwl = it->q[1] - it->q[0]; twl = it->t[1] - it->t[0]; + if(is_ualn_win(wa[it->k])) { + if(it->qoff > it->q[0]) { + // fprintf(stderr, "-2-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld\n", + // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs); + if(qs /**>=**/> it->q[0] && qs < it->q[1]) { + sub_err = ((((double)(it->q[1]-qs))/((double)(it->q[1]-it->q[0])))* + (gen_err_unaligned(qwl, twl))); + // if(qs == it->q[0]) { + // it->werr += sub_err; sub_err = 0; + // it->qoff = it->q[0]; it->toff = it->t[0]; + // } + return it->werr+sub_err; + } + it->qoff = it->q[0]; + it->toff = it->t[0]; + it->werr += gen_err_unaligned(qwl, twl); + } + } else { + set_bit_extz_t(aux, (*o), it->k); + if(it->k == tc->c_wsid) { + it->cq[0] = tc->c_qs; it->ct[0] = tc->c_ts; it->ci[0] = tc->c_wsii; + it->q[0] = MAX((int32_t)aln->qs, tc->c_qs); + it->t[0] = MAX((int32_t)aln->ts, tc->c_ts); + } + if(it->k == tc->c_weid) { + it->cq[1] = tc->c_qe; it->ct[1] = tc->c_te; it->ci[1] = tc->c_weii; + it->q[1] = MIN((int32_t)aln->qe, tc->c_qe); + it->t[1] = MIN((int32_t)aln->te, tc->c_te); + } + // fprintf(stderr, "-3-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld\n", + // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs); + if(it->qoff > it->q[0]) { + if(qs /**>=**/> it->q[0] && qs < it->q[1]) { + sub_err = extract_sub_werr(&aux, it->ci[0], it->ci[1], it->ct[0], it->ct[1], + it->cq[0], it->cq[1], it->t[0], it->t[1], it->q[0], it->q[1], qs, it); + // if(qs == it->q[0]) { + // it->werr += sub_err; sub_err = 0; + // it->qoff = it->q[0]; it->toff = it->t[0]; + // } + return it->werr + sub_err; + } + it->werr += extract_sub_werr(&aux, it->ci[0], it->ci[1], it->ct[0], it->ct[1], + it->cq[0], it->cq[1], it->t[0], it->t[1], it->q[0], it->q[1], it->q[0], it); + it->qoff = it->q[0]; + it->toff = it->t[0]; + } + } + + // if(qs == 166327) { + // fprintf(stderr, "-1-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld\n", + // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs); + // } + it->q[1] = it->q[0]; it->t[1] = it->t[0]; + if((qs == it->qoff)) { + if(it->k > tc->c_wsid) { + it->q[0] = wa[it->k-1].x_end+1; + it->t[0] = wa[it->k-1].y_end+1; + } else { + it->q[0] = aln->qs; + it->t[0] = aln->ts; + } + + // if(qs == 166327) { + // fprintf(stderr, "-2-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld\n", + // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs); + // fprintf(stderr, "-2-[M::%s::k->%ld] pre_inner_q::[%d, %d), pre_inner_t::[%d, %d)\n", + // __func__, it->k, wa[it->k-1].x_start, wa[it->k-1].x_end+1, wa[it->k-1].y_start, wa[it->k-1].y_end+1); + // } + ///otherwise there should be an indel at t + if(it->q[0] == it->q[1] && it->t[0] < it->t[1]) { + it->werr += it->t[1] - it->t[0]; continue; + } else { + return it->werr; + } + } + } + + it->q[0] = aln->qs; it->t[0] = aln->ts; + if(it->qoff > it->q[0]) { + if(it->q[0] <= it->q[1] && it->t[0] <= it->t[1]) { + if((exz->ps != it->t[0]) || (exz->pe != it->t[1]) || (exz->ts != it->q[0]) || (exz->te == it->q[1])) { + ///calculate on-the-fly + gen_clip_win_err(o, it->q[0], it->q[1], it->t[0], it->t[1], e_rate, tc->pfx_e, uref, qstr, tu, exz); + } + // fprintf(stderr, "-4-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld\n", + // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs); + if(qs >= it->q[0] && qs < it->q[1]) { + ///phrase cigar + sub_err = extract_sub_werr(exz, 0, exz->cigar.n, exz->ps, exz->pe+1, exz->ts, exz->te+1, + exz->ps, exz->pe+1, exz->ts, exz->te+1, qs, it); + if(qs == it->q[0]) { + it->werr += sub_err; sub_err = 0; + it->qoff = it->q[0]; it->toff = it->t[0]; + } + return it->werr+sub_err; + } + + it->qoff = it->q[0]; + it->toff = it->t[0]; + it->werr += exz->err; + } + } + if(it->k < tc->c_wsid) it->werr = aln->sec; + return it->werr; +} + + +//get error within [qe, ql) +int64_t get_rid_backward_cigar_err(rtrace_iter *it, ul_ov_t *aln, kv_rtrace_t *trace, rtrace_t *tc, +const ul_idx_t *uref, char* qstr, UC_Read *tu, overlap_region_alloc *ol, overlap_region *o, +bit_extz_t *exz, double e_rate, int64_t qs) +{ + //this is not right + // if(qs == aln->qe) return 0; + if(!tc) tc = &(trace->a[aln->qn]); + if(!o) o = &(ol->list[tc->oid]); + if(it->k < tc->c_wsid && qs > ((int64_t)aln->qs)) it->k = INT32_MAX; + + if(it->k == INT32_MAX) { + it->k = tc->c_weid; + it->q[1] = MAX(tc->c_qe, ((int64_t)aln->qe)); + it->t[1] = MAX(tc->c_te, ((int64_t)aln->te)); + it->qoff = MAX(tc->c_qe, ((int64_t)aln->qe)); + it->toff = MAX(tc->c_te, ((int64_t)aln->te)); + it->cur_qoff = MAX(tc->c_qe, ((int64_t)aln->qe)); + + it->werr = it->werr0 = it->cerr = 0; + it->f = 0; + it->coff = INT32_MAX; + clear_align(*exz); + exz->ps = exz->pe = exz->ts = exz->te = INT32_MAX; + } + // if(qs == 45766) { + // fprintf(stderr, "\n[M::%s::] q::[%u, %u), t::[%u, %u), tot_e::%u, cid::[%d, %d], cq::[%u, %u), ct::[%u, %u), pfx_e::%d, sfx_e::%d, mid_e::%d\n", + // __func__, aln->qs, aln->qe, aln->ts, aln->te, aln->sec, tc->c_wsid, tc->c_weid, + // tc->c_qs, tc->c_qe, tc->c_ts, tc->c_te, tc->pfx_e, tc->sfx_e, tc->mid_e); + // } + + window_list *wa = o->w_list.a; int64_t qwl, twl, sub_err; bit_extz_t aux; + assert(qs <= it->qoff); + if(qs == it->cur_qoff) return it->werr0; + + // if(qs == 166327) { + // fprintf(stderr, "\n-*-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld, cur_qoff::%ld, werr0::%ld\n", + // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs, + // it->cur_qoff, it->werr0); + // } + + for (; it->k >= tc->c_wsid; it->k--) { + it->q[0] = wa[it->k].x_end+1; + it->t[0] = wa[it->k].y_end+1; + // if(qs == 166327) { + // fprintf(stderr, "-0-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld, cur_qoff::%ld, werr0::%ld, f::%ld\n", + // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs, + // it->cur_qoff, it->werr0, it->f); + // } + ///now qs >= it->qoff -> qs >= q[0] + if(it->f == 0) { + if(it->qoff >= it->q[0]) {///[it->qoff, ql) has been calculated + if(it->q[0] <= it->q[1] && it->t[0] <= it->t[1]) { + if((exz->ps != it->t[0]) || (exz->pe != it->t[1]) || (exz->ts != it->q[0]) || (exz->te == it->q[1])) { + ///calculate on-the-fly + gen_clip_win_err(o, it->q[0], it->q[1], it->t[0], it->t[1], e_rate, it->k==tc->c_weid?tc->sfx_e:-1, uref, qstr, tu, exz); + } + sub_err = INT32_MAX; + ///if there are indels at either ends of t, qs == it->q[0] || qs == it->q[1] + if(qs >= it->q[0] && qs <= it->q[1]) { + ///phrase cigar + sub_err = extract_sub_werr(exz, 0, exz->cigar.n, exz->ps, exz->pe+1, exz->ts, exz->te+1, + exz->ps, exz->pe+1, exz->ts, exz->te+1, qs, it); + if(sub_err != INT32_MAX) {///find the coordinate for qs + if((it->cur_qoff != qs) || ((it->werr+sub_err) > it->werr0)) { + it->werr0 = it->werr+sub_err; + } + it->cur_qoff = qs; + if(qs > it->q[0] && qs <= it->q[1]) return it->werr0; + } else {///happen when qs == it->q[1] and no indels at the right end + it->qoff = it->q[1]; + it->toff = it->t[1]; + // assert(it->cur_qoff == qs); + it->cur_qoff = qs; + return it->werr0; + } + } + + if(qs <= it->q[0]) { + it->qoff = it->q[0]; + it->toff = it->t[0]; + it->werr += exz->err; + it->f = 1; + if((it->cur_qoff != it->q[0]) || (it->werr > it->werr0)) { + it->werr0 = it->werr; + } + it->cur_qoff = it->q[0]; + } + } else { + it->f = 1; + } + } else { + it->f = 1; + } + } + + it->cq[0] = it->q[0] = wa[it->k].x_start; it->cq[1] = it->q[1] = wa[it->k].x_end+1; + it->ct[0] = it->t[0] = wa[it->k].y_start; it->ct[1] = it->t[1] = wa[it->k].y_end+1; + it->ci[0] = 0; it->ci[1] = wa[it->k].clen; qwl = it->q[1] - it->q[0]; twl = it->t[1] - it->t[0]; + // if(qs == 166327) { + // fprintf(stderr, "-1-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld, cur_qoff::%ld, werr0::%ld, f::%ld\n", + // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], + // it->werr, qs, it->cur_qoff, it->werr0, it->f); + // } + if(is_ualn_win(wa[it->k])) { + if(it->qoff >= it->q[0] && it->f == 1) { + ///ignore indels of t at both ends; so ignore qs == it->q[0] and qs == it->q[1] + if(qs == it->q[1]) { + // assert(it->cur_qoff == qs); + it->cur_qoff = qs; + return it->werr0; + } + if(qs > it->q[0] && qs < it->q[1]) { + sub_err = ((((double)(it->q[1]-qs))/((double)(it->q[1]-it->q[0])))* + (gen_err_unaligned(qwl, twl))); + return it->werr+sub_err; + } + ///qs <= it->q[0] + it->qoff = it->q[0]; + it->toff = it->t[0]; + it->werr += gen_err_unaligned(qwl, twl); + it->f = 0; + if((it->cur_qoff != it->q[0]) || (it->werr > it->werr0)) { + it->werr0 = it->werr; + } + it->cur_qoff = it->q[0]; + } + } else { + set_bit_extz_t(aux, (*o), it->k); + if(it->k == tc->c_wsid) { + it->cq[0] = tc->c_qs; it->ct[0] = tc->c_ts; it->ci[0] = tc->c_wsii; + it->q[0] = MAX((int32_t)aln->qs, tc->c_qs); + it->t[0] = MAX((int32_t)aln->ts, tc->c_ts); + } + if(it->k == tc->c_weid) { + it->cq[1] = tc->c_qe; it->ct[1] = tc->c_te; it->ci[1] = tc->c_weii; + it->q[1] = MIN((int32_t)aln->qe, tc->c_qe); + it->t[1] = MIN((int32_t)aln->te, tc->c_te); + } + + if(it->qoff >= it->q[0] && it->f == 1) { + sub_err = INT32_MAX; + ///if there are indels at either ends of t, qs == it->q[0] || qs == it->q[1] + if(qs >= it->q[0] && qs <= it->q[1]) { + sub_err = extract_sub_werr(&aux, it->ci[0], it->ci[1], it->ct[0], it->ct[1], + it->cq[0], it->cq[1], it->t[0], it->t[1], it->q[0], it->q[1], qs, it); + // if(qs == 166327) { + // fprintf(stderr, "-3-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld, cur_qoff::%ld, werr0::%ld, f::%ld, sub_err::%ld\n", + // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs, + // it->cur_qoff, it->werr0, it->f, sub_err); + // } + if(sub_err != INT32_MAX) {///find the coordinate for qs + if((it->cur_qoff != qs) || ((it->werr+sub_err) > it->werr0)) { + it->werr0 = it->werr+sub_err; + } + it->cur_qoff = qs; + if(qs > it->q[0] && qs <= it->q[1]) return it->werr0; + } else {///happen when qs == it->q[1] and no indels at the right end + it->qoff = it->q[1]; + it->toff = it->t[1]; + // if(!(it->cur_qoff == qs)) { + // fprintf(stderr, "\n[M::%s::] q::[%u, %u), t::[%u, %u), tot_e::%u, cid::[%d, %d], cq::[%u, %u), ct::[%u, %u), pfx_e::%d, sfx_e::%d, mid_e::%d\n", + // __func__, aln->qs, aln->qe, aln->ts, aln->te, aln->sec, tc->c_wsid, tc->c_weid, + // tc->c_qs, tc->c_qe, tc->c_ts, tc->c_te, tc->pfx_e, tc->sfx_e, tc->mid_e); + // } + // assert(it->cur_qoff == qs); + it->cur_qoff = qs; + return it->werr0; + } + } + // if(qs == 166327) { + // fprintf(stderr, "-4-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld, cur_qoff::%ld, werr0::%ld, f::%ld, sub_err::%ld\n", + // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs, + // it->cur_qoff, it->werr0, it->f, sub_err); + // } + ///qs <= it->q[0] + if(qs <= it->q[0]) { + it->werr += ((qs==it->q[0])?(sub_err):(extract_sub_werr(&aux, it->ci[0], it->ci[1], it->ct[0], it->ct[1], + it->cq[0], it->cq[1], it->t[0], it->t[1], it->q[0], it->q[1], it->q[0], it))); + it->qoff = it->q[0]; + it->toff = it->t[0]; + it->f = 0; + if((it->cur_qoff != it->q[0]) || (it->werr > it->werr0)) { + it->werr0 = it->werr; + } + it->cur_qoff = it->q[0]; + } + } + } + it->q[1] = it->q[0]; it->t[1] = it->t[0]; + // if(qs == 166327) { + // fprintf(stderr, "-#-[M::%s::k->%ld] qoff::%ld, toff::%ld, coff::%ld, inner_q::[%ld, %ld), inner_t::[%ld, %ld), werr::%ld, qs::%ld, cur_qoff::%ld, werr0::%ld, f::%ld\n", + // __func__, it->k, it->qoff, it->toff, it->coff, it->q[0], it->q[1], it->t[0], it->t[1], it->werr, qs, + // it->cur_qoff, it->werr0, it->f); + // } + } + + it->q[0] = aln->qs; it->t[0] = aln->ts; + if(it->qoff >= it->q[0] && it->f == 0) { + if(it->q[0] <= it->q[1] && it->t[0] <= it->t[1]) { + if((exz->ps != it->t[0]) || (exz->pe != it->t[1]) || (exz->ts != it->q[0]) || (exz->te == it->q[1])) { + ///calculate on-the-fly + gen_clip_win_err(o, it->q[0], it->q[1], it->t[0], it->t[1], e_rate, tc->pfx_e, uref, qstr, tu, exz); + } + sub_err = INT32_MAX; + ///if there are indels at either ends of t, qs == it->q[0] || qs == it->q[1] + if(qs >= it->q[0] && qs <= it->q[1]) { + ///phrase cigar + sub_err = extract_sub_werr(exz, 0, exz->cigar.n, exz->ps, exz->pe+1, exz->ts, exz->te+1, + exz->ps, exz->pe+1, exz->ts, exz->te+1, qs, it); + if(sub_err != INT32_MAX) {///find the coordinate for qs + if((it->cur_qoff != qs) || ((it->werr+sub_err) > it->werr0)) { + it->werr0 = it->werr+sub_err; + } + it->cur_qoff = qs; + if(qs > it->q[0] && qs <= it->q[1]) return it->werr0; + } else {///happen when qs == it->q[1] and no indels at the right end + it->qoff = it->q[1]; + it->toff = it->t[1]; + // assert(it->cur_qoff == qs); + it->cur_qoff = qs; + return it->werr0; + } + } + + if(qs <= it->q[0]) { + it->qoff = it->q[0]; + it->toff = it->t[0]; + it->werr += exz->err; + it->f = 1; + if((it->cur_qoff != it->q[0]) || (it->werr > it->werr0)) { + it->werr0 = it->werr; + } + it->cur_qoff = it->q[0]; + } + } + } + // if(it->k < tc->c_wsid) it->werr = aln->sec; + return it->werr; +} + +void debug_backtrace_step_err(uint64_t rid, ul_ov_t *aln, rtrace_t *tc, const ul_idx_t *uref, char* qstr, UC_Read *tu, overlap_region *o, bit_extz_t *exz, double e_rate) +{ + // if(aln->qs == 0 && aln->qe == 3013 && aln->ts == 28965 && aln->te == 31993) { + // fprintf(stderr, "\n[M::%s::] q::[%u, %u), t::[%u, %u), tot_e::%u, cid::[%d, %d], cq::[%u, %u), ct::[%u, %u), pfx_e::%d, sfx_e::%d, mid_e::%d\n", + // __func__, aln->qs, aln->qe, aln->ts, aln->te, aln->sec, tc->c_wsid, tc->c_weid, + // tc->c_qs, tc->c_qe, tc->c_ts, tc->c_te, tc->pfx_e, tc->sfx_e, tc->mid_e); + int64_t k, err, qs = aln->qs, qe = aln->qe, err0; rtrace_iter it; + k = qe; it.k = INT32_MAX; + err0 = get_rid_backward_cigar_err(&it, aln, NULL, tc, uref, qstr, tu, NULL, o, exz, e_rate, k); + err = get_rid_backward_cigar_err(&it, aln, NULL, tc, uref, qstr, tu, NULL, o, exz, e_rate, k); + assert(err == err0); + for (k = qe, it.k = INT32_MAX, err0 = 0; k >= qs; k-=8) { + err = get_rid_backward_cigar_err(&it, aln, NULL, tc, uref, qstr, tu, NULL, o, exz, e_rate, k); + // if(!(err >= 0 && err >= err0)) { + // fprintf(stderr, "[M::%s::rid->%lu] q::[%u, %u), t::[%u, %u), tot_e::%u, cid::[%d, %d], cq::[%u, %u), ct::[%u, %u)\n", + // __func__, rid, aln->qs, aln->qe, aln->ts, aln->te, aln->sec, tc->c_wsid, tc->c_weid, + // tc->c_qs, tc->c_qe, tc->c_ts, tc->c_te); + // fprintf(stderr, "[M::%s::] q::[%ld, %ld), err::%ld, err0::%ld\n", __func__, k, qe, err, err0); + // } + // fprintf(stderr, "[M::%s::] q::[%ld, %ld), err::%ld\n", __func__, k, qe, err); + assert(err >= 0 && err >= err0); + err0 = err; + } + k = qs; + err = get_rid_backward_cigar_err(&it, aln, NULL, tc, uref, qstr, tu, NULL, o, exz, e_rate, k); + // if(!(err >= 0 && err >= err0)) { + // fprintf(stderr, "[M::%s::rid->%lu] q::[%u, %u), t::[%u, %u), tot_e::%u, cid::[%d, %d], cq::[%u, %u), ct::[%u, %u)\n", + // __func__, rid, aln->qs, aln->qe, aln->ts, aln->te, aln->sec, tc->c_wsid, tc->c_weid, + // tc->c_qs, tc->c_qe, tc->c_ts, tc->c_te); + // fprintf(stderr, "[M::%s::] q::[%ld, %ld), err::%ld, err0::%ld\n", __func__, k, qe, err, err0); + // } + // fprintf(stderr, "[M::%s::] q::[%ld, %ld), err::%ld, exz->err::%d, exz->cigar.n::%d\n", + // __func__, qs, qe, err, exz->err, (int32_t)exz->cigar.n); + assert(err >= 0 && err >= err0); + if(!(err == (int64_t)aln->sec)) { + fprintf(stderr, "[M::%s::rid->%lu] q::[%u, %u), t::[%u, %u), tot_e::%u, cid::[%d, %d], cq::[%u, %u), ct::[%u, %u)\n", + __func__, rid, aln->qs, aln->qe, aln->ts, aln->te, aln->sec, tc->c_wsid, tc->c_weid, + tc->c_qs, tc->c_qe, tc->c_ts, tc->c_te); + fprintf(stderr, "[M::%s::] aln->sec::%u, err::%ld\n", __func__, aln->sec, err); + } + assert(err == (int64_t)aln->sec); + // } +} + +///[wsid, weid) && [ts, te) +void gen_raln(const ul_idx_t *uref, char* qstr, UC_Read *tu, overlap_region *o, bit_extz_t *exz, +int64_t wsid, int64_t weid, int64_t ts, int64_t te, int64_t ql, int64_t id, int64_t rev, double e_rate, +uint64_t rid, rtrace_t *tc, ul_ov_t *res) +{ + // fprintf(stderr, "\n[M::%s::] ii::[%ld, %ld), t::[%ld, %ld), ql::%ld, id::%ld\n", + // __func__, wsid, weid, ts, te, ql, id); + int64_t k, q[2], t[2], c[2], ct[2], cq[2], mode, qwl, twl, aln_e = 0, cur_e, is_aln; + bit_extz_t aux; window_list *wa = o->w_list.a; + memset(res, 0, sizeof((*res))); + res->qs = res->ts = UINT32_MAX; res->qe = res->te = 0; + memset(tc, 0, sizeof((*tc))); + tc->c_qs = tc->c_ts = INT32_MAX; tc->c_qe = tc->c_te = -1; + tc->pfx_e = tc->mid_e = tc->sfx_e = 0; + + q[0] = q[1] = -1; t[0] = ts; t[1] = te;///[q[0], q[1]) && [t[0], t[1]) + for (k = wsid; k < weid; k++) { + q[1] = wa[k].x_start; t[1] = wa[k].y_start; + mode = - 1; cur_e = 0; is_aln = 1; + // if(rid == 53 && id == 6) { + // fprintf(stderr, "0-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld)\n", __func__, k, q[0], q[1], t[0], t[1]); + // } + //before window; there are gaps before the window that need to be filled + if(t[0] < t[1] && q[0] < q[1]) { + if(q[0] < 0) { ///backward extension + mode = 2; + adjust_ext_offset_fixed_t(&(q[0]), &(q[1]), &(t[0]), &(t[1]), 0, q[1], t[0], t[1], 0, mode); + } else { + mode = 0; + } + // if(rid == 53 && id == 6) { + // fprintf(stderr, "1-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", + // __func__, k, q[0], q[1], t[0], t[1], mode); + // } + qwl = q[1] - q[0]; twl = t[1] - t[0]; + if(qwl || twl) { + if(qwl == 0 && twl > 0) { + cur_e = twl; + // tot_e += twl; + } else if(twl == 0 && qwl > 0) { + cur_e = qwl; + // tot_e += qwl; + } else { + if(hc_aln_exz_simi_adv(id, rev, uref, NULL, NULL, qstr, tu, q[0], q[1], t[0], t[1], + 0, ql, ts, te, mode, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E, FORCE_CNS_L, -1, NULL, 0)) { + cur_e = exz->err; + // tot_e += exz->err; + q[0] = exz->ts; q[1] = exz->te + 1; t[0] = exz->ps; t[1] = exz->pe + 1; + // if(rid == 53 && id == 6) { + // fprintf(stderr, "2-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), mode::%ld, cur_e::%ld\n", + // __func__, k, q[0], q[1], t[0], t[1], mode, cur_e); + // } + } else { + cur_e = gen_err_unaligned(qwl, twl); is_aln = 0; + // tot_e += gen_err_unaligned(qwl, twl); + // if(rid == 53 && id == 6) { + // fprintf(stderr, "2-b[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), mode::%ld, cur_e::%ld\n", + // __func__, k, q[0], q[1], t[0], t[1], mode, cur_e); + // } + } + } + aln_e += cur_e; + update_ul_ov_t_coor((*res), q[0], q[1], t[0], t[1]); + if(k == wsid) tc->pfx_e = cur_e*(is_aln?1:-1); + } + } + + ///within window + q[0] = wa[k].x_start; t[0] = wa[k].y_start; + q[1] = wa[k].x_end+1; t[1] = wa[k].y_end+1; + qwl = q[1] - q[0]; twl = t[1] - t[0]; cur_e = 0; is_aln = 1; + // if(rid == 53 && id == 6) { + // fprintf(stderr, "3-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld)\n", + // __func__, k, q[0], q[1], t[0], t[1]); + // } + if((ts <= t[0]) && (te >= t[1])) {///cover the whole window + if(!is_ualn_win(wa[k])) cur_e = wa[k].error; + else cur_e = gen_err_unaligned(qwl, twl); + update_trace_idx(tc, k, 0, wa[k].clen, q[0], q[1], t[0], t[1]); + // if(rid == 53 && id == 6) { + // fprintf(stderr, "4-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld\n", + // __func__, k, q[0], q[1], t[0], t[1], cur_e); + // } + } else {///te < t[1]->cover a part of window + if(ts > t[0]) { + t[0] = ts; q[0] = -1; + } + if(te < t[1]) { + t[1] = te; q[1] = -1; + } + + if((q[0] != -1) && (q[1] != -1)) { + mode = 0;//global + } else if((q[0] != -1) && (q[1] == -1)) { + mode = 1;///forward extension + } else if((q[0] == -1) && (q[1] != -1)) { + mode = 2;///backward extension + } else { + mode = 3;///no primary hit within [ibeg, iend] + } + // if(rid == 53 && id == 6) { + // fprintf(stderr, "5-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), mode::%ld\n", + // __func__, k, q[0], q[1], t[0], t[1], mode); + // } + if(!is_ualn_win(wa[k])) {///scan cigar by the coordinates of y/t + set_bit_extz_t(aux, (*o), k); + cur_e = hc_aln_exz_by_exist_cigar_with_p(&aux, mode, t[0], t[1], &(q[0]), &(q[1]), + &(c[0]), &(c[1]), &(ct[0]), &(ct[1]), &(cq[0]), &(cq[1])); + update_trace_idx(tc, k, c[0], c[1], cq[0], cq[1], ct[0], ct[1]); + // if(rid == 53 && id == 6) { + // fprintf(stderr, "6-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld, c_q::[%ld, %ld), c_t::[%ld, %ld)\n", + // __func__, k, q[0], q[1], t[0], t[1], cur_e, cq[0], cq[1], ct[0], ct[1]); + // } + } else { + assert(mode == 1 || mode == 2); + adjust_ext_offset_fixed_t(&(q[0]), &(q[1]), &(t[0]), &(t[1]), q[0], q[1], t[0], t[1], 0, mode); + qwl = q[1] - q[0]; twl = t[1] - t[0]; + // if(rid == 53 && id == 6) { + // fprintf(stderr, "7-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld\n", + // __func__, k, q[0], q[1], t[0], t[1], cur_e); + // } + if(qwl || twl) { + if(qwl == 0 && twl > 0) { + cur_e = twl; + } else if(twl == 0 && qwl > 0) { + cur_e = qwl; + } else { + if(hc_aln_exz_simi_adv(id, rev, uref, NULL, NULL, qstr, tu, q[0], q[1], t[0], t[1], + 0, ql, ts, te, mode, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E, FORCE_CNS_L, -1, NULL, 0)) { + cur_e = exz->err; + q[0] = exz->ts; q[1] = exz->te + 1; t[0] = exz->ps; t[1] = exz->pe + 1; + // if(rid == 53 && id == 6) { + // fprintf(stderr, "7-b[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld\n", + // __func__, k, q[0], q[1], t[0], t[1], cur_e); + // } + } else { + cur_e = gen_err_unaligned(qwl, twl); is_aln = 0; + // if(rid == 53 && id == 6) { + // fprintf(stderr, "7-c[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld\n", + // __func__, k, q[0], q[1], t[0], t[1], cur_e); + // } + } + } + tc->sfx_e = cur_e*(is_aln?1:-1); + } + } + } + aln_e += cur_e; + update_ul_ov_t_coor((*res), q[0], q[1], t[0], t[1]); + + q[0] = q[1]; t[0] = t[1]; + } + // if(ts == 8087 && te == 28530 && ql == 127662) { + // fprintf(stderr, "8-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld, ql::%ld\n", + // __func__, k, q[0], q[1], t[0], t[1], cur_e, ql); + // } + if(q[0] >= 0 && q[0] < ql) {///forward extension + q[1] = ql; t[1] = te; cur_e = 0; mode = 1;///forward extension + adjust_ext_offset_fixed_t(&(q[0]), &(q[1]), &(t[0]), &(t[1]), q[0], q[1], t[0], t[1], 0, mode); + qwl = q[1] - q[0]; twl = t[1] - t[0]; is_aln = 1; + // if(rid == 53 && id == 6) { + // fprintf(stderr, "9-a[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld\n", + // __func__, k, q[0], q[1], t[0], t[1], cur_e); + // } + if(qwl || twl) { + if(qwl == 0 && twl > 0) { + cur_e = twl; + } else if(twl == 0 && qwl > 0) { + cur_e = qwl; + } else { + if(hc_aln_exz_simi_adv(id, rev, uref, NULL, NULL, qstr, tu, q[0], q[1], t[0], t[1], + 0, ql, ts, te, mode, exz, ql, e_rate, MAX_CNS_L, MAX_CNS_E, FORCE_CNS_L, -1, NULL, 0)) { + cur_e = exz->err; + q[0] = exz->ts; q[1] = exz->te + 1; t[0] = exz->ps; t[1] = exz->pe + 1; + // if(rid == 53 && id == 6) { + // fprintf(stderr, "9-b[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld, thre::%d\n", + // __func__, k, q[0], q[1], t[0], t[1], cur_e, exz->thre); + // } + } else { + cur_e = gen_err_unaligned(qwl, twl); is_aln = 0; + // if(rid == 53 && id == 6) { + // fprintf(stderr, "9-c[M::%s::k->%ld] q::[%ld, %ld), t::[%ld, %ld), cur_e::%ld\n", + // __func__, k, q[0], q[1], t[0], t[1], cur_e); + // } + } + } + update_ul_ov_t_coor((*res), q[0], q[1], t[0], t[1]); + tc->sfx_e = cur_e*(is_aln?1:-1); + } + aln_e += cur_e; + } + tc->mid_e = aln_e - abs(tc->pfx_e) - abs(tc->sfx_e); + if(aln_e <= MAX_SEC_ERR) res->sec = aln_e; + else res->sec = MAX_SEC_ERR; + // fprintf(stderr, "10-a[M::%s::k->%ld] q::[%u, %u), t::[%u, %u), tot_e::%u\n\n", + // __func__, k, res->qs, res->qe, res->ts, res->te, res->sec); + + + // aln_e = get_sub_cigar_err(res, tc, uref, qstr, tu, o, exz, e_rate); + // if(aln_e != (int64_t)res->sec) { + // fprintf(stderr, "[M::%s::rid->%lu] tot_e::%u, aln_e::%ld, id::%ld\n", + // __func__, rid, res->sec, aln_e, id); + // exit(1); + // } + + // assert(aln_e == get_sub_cigar_err(res, tc, uref, qstr, tu, o, exz, e_rate, 0)); + // assert(aln_e == get_sub_cigar_err(res, tc, uref, qstr, tu, o, exz, e_rate, 1)); + // debug_backtrace_step_err(rid, res, tc, uref, qstr, tu, o, exz, e_rate); + // if(rid == 42 && res->sec == 706 && res->qs == 63686 && res->qe == 75773 + // && res->ts == 9404 && res->te == 21663) { + // debug_backtrace_step_err(rid, res, tc, uref, qstr, tu, o, exz, e_rate); + // } +} + +void prt_aln_w(overlap_region *o) +{ + uint64_t k; + for (k = 0; k < o->w_list.n; k++) { + fprintf(stderr, "[M::%s::aln->%u] q::[%d, %d), t::[%d, %d), err::%d\n", + __func__, ((o->w_list.a[k].y_end != -1) && (!(is_ualn_win(o->w_list.a[k])))), + o->w_list.a[k].x_start, o->w_list.a[k].x_end+1, + o->w_list.a[k].y_start, o->w_list.a[k].y_end+1, o->w_list.a[k].error); + } +} + +///[ts, te) -> this is the reverse coordinates of t, not the original coordinates of t +int64_t extract_subov_cigar(const ul_idx_t *uref, char* qstr, UC_Read *tu, bit_extz_t *exz, +int64_t ts0, int64_t te0, overlap_region *o, double o_rate, int64_t *in_k, int64_t ql, +double e_rate, uint64_t rid, uint64_t dbg_id, rtrace_t *trace, ul_ov_t *res) +{ + int64_t rev = o->y_pos_strand, t[2], q[2], k = 0, wts, wte, ii[2]; + int64_t wn = o->w_list.n, os, oe, ovlp, salnl = 0; + t[0] = ts0; t[1] = te0; if(wn <= 0) return 0; + + if(in_k) k = *in_k; + if(k < 0) {k = 0;} if(k >= wn) {k = wn-1;} + for(; k < wn && t[0] > o->w_list.a[k].y_end; k++); + if(k < 0) {k = 0;} if(k >= wn) {k = wn-1;} + for(; k >= 0 && t[0] < o->w_list.a[k].y_start; k--); + ///qs <= o->w_list.a[k].x_end && qs >= o->w_list.a[k].x_start + if(k < 0) k = 0; + if(in_k) *in_k = k; + + for (ii[0] = INT32_MAX, ii[1] = -1; k < wn; k++) { + wts = o->w_list.a[k].y_start; + wte = o->w_list.a[k].y_end + 1; + if(wts >= t[1]) break; + if((o->w_list.a[k].y_end == -1) || (is_ualn_win(o->w_list.a[k]))) continue; + os = MAX(t[0], wts); oe = MIN(t[1], wte); + ovlp = ((oe>os)? (oe-os):0); + if(!ovlp) continue; + if(k < ii[0]) ii[0] = k; + if(k > ii[1]) ii[1] = k; + salnl += ovlp; + } + // if(dbg_id == 5525) { + // prt_aln_w(o); + // fprintf(stderr, "[M::%s::aln->%ld] ii::[%ld, %ld), q_aln0::[%d, %d), t0::[%ld, %ld)\n", + // __func__, salnl, ii[0], ii[1]+1, o->w_list.a[ii[0]].x_start, o->w_list.a[ii[0]].x_end+1, + // ts0, te0); + // } + if((!salnl) || (ii[0] == INT32_MAX) || (ii[1] < 0)) return 0; + if((ii[0] == ii[1]) && (is_ualn_win(o->w_list.a[ii[0]]))) return 0; + //[ii[0], ii[1]] + win_boundary_offset(o->w_list.a, o->w_list.n, ii[0], ts0, ql, &(q[0]), &(t[0])); + win_boundary_offset(o->w_list.a, o->w_list.n, ii[1], te0-1, ql, &(q[1]), &(t[1])); + q[1]++; t[1]++; + // if(dbg_id == 5525) { + // fprintf(stderr, "[M::%s::aln->%ld] ii::[%ld, %ld), q::[%ld, %ld), t::[%ld, %ld)\n", + // __func__, salnl, ii[0], ii[1]+1, q[0], q[1], t[0], t[1]); + // } + if(salnl < ((t[1]-t[0])*o_rate)) return 0; + + gen_raln(uref, qstr, tu, o, exz, ii[0], ii[1]+1, ts0, te0, ql, o->y_id, rev, e_rate, rid, trace, res); + assert(res->ts >= ts0 && res->te <= te0 && res->qs >= 0 && res->qe <= ql); + double simi_thre = e_rate + MIN(r_simi_w, (e_rate/2)); + if((res->sec <= ((res->qe-res->qs)*simi_thre)) && (res->sec <= ((res->te-res->ts)*simi_thre))) { + return 1; + } else { + return 0; + } +} + + +uint64_t gen_sub_ov_adv_cigar(const ul_idx_t *udb, overlap_region* o, char* qstr, UC_Read *tu, +bit_extz_t *exz, int64_t ql, double o_rate, double e_rate, utg_ct_t *ct_a, uint64_t ct_n, +uint64_t sid, uint64_t oid, kv_rtrace_t *trace, kv_ul_ov_t *res) +{ + uint64_t ts, te, i, l, rn = res->n, rev = o->y_pos_strand, s, e, rid, t[2]; + ma_utg_t *u = &(udb->ug->u.a[o->y_id]); ul_ov_t z; rtrace_t tz; int64_t k; + if(!rev){ + ts = o->y_pos_s; te = o->y_pos_e + 1; k = 0; + } else { + ts = u->len - (o->y_pos_e+1); te = u->len - o->y_pos_s; + k = ((int64_t)o->w_list.n)-1; if(k < 0) k = 0; + } + + if(!ct_a) { + for (i = l = 0; i < u->n; i++) { + rid = u->a[i]>>33; + s = l; e = l + Get_READ_LENGTH(R_INF, rid);///note: [s, e) are pos of t + l += (uint32_t)u->a[i]; + if(e <= ts) continue; + if(s >= te) break; + t[0] = (rev?(u->len-e):(s)); t[1] = (rev?(u->len-s):(e)); + if(extract_subov_cigar(udb, qstr, tu, exz, t[0], t[1], o, o_rate, &k, ql, e_rate, sid, rid, &tz, &z)) { + tz.oid = oid; + z.ts -= t[0]; z.te -= t[0]; + z.rev = ((o->y_pos_strand == ((u->a[i]>>32)&1))?0:1); + if(z.rev) { + t[0] = z.ts; t[1] = z.te; + z.ts = Get_READ_LENGTH(R_INF, rid) - t[1]; + z.te = Get_READ_LENGTH(R_INF, rid) - t[0]; + } + ///non-contained read at the unitg + z.el = 1; + ///rid + z.tn = rid; + ///i-th read at the unitig + z.qn = trace->n; + kv_push(ul_ov_t, *res, z); + kv_push(rtrace_t, *trace, tz); + // fprintf(stderr, "+[M::%s::rid->%lu::rev->%lu] utg_t::[%ld, %ld), ql::%ld\n", + // __func__, rid, rev, t[0], t[1], ql); + // fprintf(stderr, "+[M::%s::%.*s::%c] q::[%u, %u), ql::%ld, t::[%u, %u), tl::%lu, err::%u\n", + // __func__, (int)Get_NAME_LENGTH(R_INF, z.tn), Get_NAME(R_INF, z.tn), + // "+-"[z.rev], z.qs, z.qe, ql, z.ts, z.te, Get_READ_LENGTH(R_INF, z.tn), z.sec); + } + } + } else { + for (i = 0; i < ct_n; i++) { + rid = ct_a[i].x>>1; s = ct_a[i].s; e = ct_a[i].e; + if(e <= ts) continue; + if(s >= te) break; + t[0] = (rev?(u->len-e):(s)); t[1] = (rev?(u->len-s):(e)); + if(extract_subov_cigar(udb, qstr, tu, exz, t[0], t[1], o, o_rate, &k, ql, e_rate, sid, rid, &tz, &z)) { + tz.oid = oid; + z.ts -= t[0]; z.te -= t[0]; + z.rev = ((o->y_pos_strand == (ct_a[i].x&1))?0:1); + if(z.rev) { + t[0] = z.ts; t[1] = z.te; + z.ts = Get_READ_LENGTH(R_INF, rid) - t[1]; + z.te = Get_READ_LENGTH(R_INF, rid) - t[0]; + } + ///contained read at the unitg + z.el = 0; + ///rid + z.tn = rid; + ///i-th read at the unitig + z.qn = trace->n; + kv_push(ul_ov_t, *res, z); + kv_push(rtrace_t, *trace, tz); + // fprintf(stderr, "-[M::%s::rid->%lu::rev->%lu] utg_t::[%ld, %ld), ql::%ld\n", + // __func__, rid, rev, t[0], t[1], ql); + // fprintf(stderr, "-[M::%s::%.*s::%c] q::[%u, %u), ql::%ld, t::[%u, %u), tl::%lu, err::%u\n", + // __func__, (int)Get_NAME_LENGTH(R_INF, z.tn), Get_NAME(R_INF, z.tn), + // "+-"[z.rev], z.qs, z.qe, ql, z.ts, z.te, Get_READ_LENGTH(R_INF, z.tn), z.sec); + } + } + } + return res->n-rn; +} + +uint64_t win_cluster_fliter(window_list *wa, uint64_t wn, uint64_t min_ovlp, double o_rate) +{ + uint64_t k, ws = (uint64_t)-1, we = (uint64_t)-1, aln_ol, sk; + for (k = 0; k < wn && wa[k].y_end == -1; k++); + if(k >= wn) {return 0;} ws = wa[k].x_start; + + for (aln_ol = 0, sk = k; k < wn; k++) { + we = wa[k].x_end+1; + if(wa[k].y_end != -1) { + aln_ol += wa[k].x_end+1-wa[k].x_start; + } + if(we >= ws + min_ovlp) break; + } + // fprintf(stderr, "[M::%s::] aln_ol::%lu, w::[%lu, %lu), min_ovlp::%lu, o_rate::%f\n", + // __func__, aln_ol, ws, we, min_ovlp, o_rate); + if((aln_ol >= (we-ws)*o_rate) && (we-ws >= min_ovlp)) return 1; + + for (k++; k < wn; k++) { + we = wa[k].x_end+1; + if(wa[k].y_end != -1) { + aln_ol += wa[k].x_end+1-wa[k].x_start; + } + for (; sk < wn && wa[sk].x_start + min_ovlp < we; sk++) { + if(wa[sk].y_end != -1) aln_ol -= wa[sk].x_end+1-wa[sk].x_start; + } + ws = wa[sk].x_start; + // fprintf(stderr, "+[M::%s::] aln_ol::%lu, w::[%lu, %lu), min_ovlp::%lu, o_rate::%f, k::[%lu, %lu)\n", + // __func__, aln_ol, ws, we, min_ovlp, o_rate, sk, k); + if((aln_ol >= (we-ws)*o_rate) && (we-ws >= min_ovlp)) return 1; + if((sk > 0) && (we-ws < min_ovlp)) { + sk--; if(wa[sk].y_end != -1) aln_ol += wa[sk].x_end+1-wa[sk].x_start; + ws = wa[sk].x_start; + // fprintf(stderr, "-[M::%s::] aln_ol::%lu, w::[%lu, %lu), min_ovlp::%lu, o_rate::%f, k::[%lu, %lu)\n", + // __func__, aln_ol, ws, we, min_ovlp, o_rate, sk, k); + if((aln_ol >= (we-ws)*o_rate) && (we-ws >= min_ovlp)) return 1; + } + } + return 0; +} + + +void print_aln_windows(overlap_region *z) +{ + uint64_t k; + for (k = 0; k < z->w_list.n; k++) { + fprintf(stderr, "[M::%s::] q::[%u, %u), t::[%u, %u), err::%d\n", __func__, + z->w_list.a[k].x_start, z->w_list.a[k].x_end+1, + z->w_list.a[k].y_start, z->w_list.a[k].y_end+1, + z->w_list.a[k].error); + } +} + +uint64_t ul_local_aln(overlap_region *z, Candidates_list *cl, const ul_idx_t *udb, char* qstr, UC_Read *tu, +bit_extz_t *exz, double e_rate, int64_t w_l, uint64_t min_ovlp, double o_rate, kv_ul_ov_t *rln, kv_ul_ov_t *cln, +kv_rtrace_t *trace, uint64_t ql, uint64_t rid, uint64_t oid, uint64_t khit, overlap_region *aux_o) +{ + uint64_t ol, aln_ol, cn, k, mm, rln_0; ul_contain *ct = udb->ct; utg_ct_t *ca; ul_ov_t *p; + if(!aux_o) { + align_ul_ed_post_extz(z, udb, NULL, qstr, tu->seq, exz, e_rate, w_l, -1, 1, NULL); + ol = z->x_pos_e+1-z->x_pos_s, aln_ol = z->align_length; + if(aln_ol >= (ol*o_rate)) return 1; + if(aln_ol <= min_ovlp) return 0; + // fprintf(stderr, "***[M::%s::aln_ol->%lu] utg%.6dl(%c), align::%u, q::[%u, %u), t::[%u, %u)\n", __func__, aln_ol, + // (int32_t)z->y_id + 1, "+-"[z->y_pos_strand], z->align_length, + // z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1); + mm = win_cluster_fliter(z->w_list.a, z->w_list.n, min_ovlp, o_rate/2); + // print_aln_windows(z); + // fprintf(stderr, "***[M::%s::] mm::%lu\n", __func__, mm); + return mm; + } else { + ol = z->x_pos_e+1-z->x_pos_s; aln_ol = z->align_length; + if(aln_ol <= min_ovlp) return 0; + // if(z->y_id == 700) { + // fprintf(stderr, "+[M::%s::aln_ol->%lu::o_rate->%f] utg%.6dl(%c), align::%u, q::[%u, %u), t::[%u, %u), ql::%lu\n", + // __func__, aln_ol, o_rate, + // (int32_t)z->y_id + 1, "+-"[z->y_pos_strand], z->align_length, + // z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1, ql); + // print_aln_windows(z); + // } + rln_0 = rln->n; + if((ol*o_rate) <= aln_ol) { + kv_pushp(ul_ov_t, *rln, &p); memset(p, 0, sizeof(*p)); + ///[ts, te) -> whole interval rid at the unitig adjusted by the reverse + p->ts = z->y_pos_s; p->te = z->y_pos_e+1; + p->qs = z->x_pos_s; p->qe = z->x_pos_e+1; + p->rev = z->y_pos_strand; p->el = 0; p->tn = p->qn = (uint32_t)-1; + } else { + cn = ((uint32_t)(ct->idx.a[z->y_id])); + ca = ct->rids.a + ((ct->idx.a[z->y_id])>>32); + gen_sub_ov_adv(udb, z, o_rate, NULL, 0, rln); + gen_sub_ov_adv(udb, z, o_rate, ca, cn, rln); + } + + if(rln->n <= rln_0) return 0; + radix_sort_ul_ov_srt_qs1(rln->a+rln_0, rln->a+rln->n); + // if(z->y_id == 700) { + // for (k = 0; k < rln->n; k++) { + // p = &(rln->a[k]); + // fprintf(stderr, "+[M::%s::k->%lu] candidate_q::[%u, %u)\n", __func__, k, p->qs, p->qe); + // } + // } + + for (k = mm = rln_0, p = NULL; k < rln->n; k++) { + if((!p) || (rln->a[k].qs >= p->qe)) p = NULL; + if(p) { + if((rln->a[k].qsqe)&&(rln->a[k].qe>p->qe)) { + p->qe = rln->a[k].qe; + } + } else { + p = &(rln->a[mm++]); *p = rln->a[k]; + } + } + rln->n = mm; + // if(z->y_id == 700) { + // for (k = 0; k < rln->n; k++) { + // p = &(rln->a[k]); + // fprintf(stderr, "-[M::%s::k->%lu] candidate_q::[%u, %u)\n", __func__, k, p->qs, p->qe); + // } + // } + + return_t_chain(z, cl); + cigar_gen_by_chain_adv_local(z, cl, rln->a+rln_0, rln->n-rln_0, w_l, udb, NULL, NULL, qstr, tu, exz, aux_o, e_rate, ql, rid, khit); + + // fprintf(stderr, "-[M::%s::aln_ol->%lu] utg%.6dl(%c), align::%u, q::[%u, %u), t::[%u, %u)\n", __func__, aln_ol, + // (int32_t)z->y_id + 1, "+-"[z->y_pos_strand], z->align_length, + // z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1); + // print_aln_windows(z); + + + rln->n = rln_0; + cn = ((uint32_t)(ct->idx.a[z->y_id])); + ca = ct->rids.a + ((ct->idx.a[z->y_id])>>32); + gen_sub_ov_adv_cigar(udb, z, qstr, tu, exz, ql, o_rate, e_rate, NULL, 0, rid, oid, trace, rln); + gen_sub_ov_adv_cigar(udb, z, qstr, tu, exz, ql, o_rate, e_rate, ca, cn, rid, oid, trace, cln); + return 1; + } +} + + +int64_t ul_raw_aln(overlap_region *z, Candidates_list *cl, const ul_idx_t *udb, char* qstr, UC_Read *tu, +bit_extz_t *exz, double e_rate, int64_t w_l, uint64_t ql, uint64_t rid, uint64_t khit, overlap_region *aux_o) +{ + return_t_chain(z, cl); + int64_t ch_idx = z->shared_seed, ch_n; + int64_t i, tl, id = z->y_id, m; ul_ov_t ov; + k_mer_hit *ch_a = cl->list + ch_idx; + tl = udb->ug->u.a[id].len; + for (i = ch_idx; i < cl->length && cl->list[i].readID == cl->list[ch_idx].readID; i++){;} ch_n = i-ch_idx; + + // if(z->x_id == 57 && z->y_id == 2175) { + // fprintf(stderr, "\n-*-[M::%s]\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\tch_idx::%ld\tch_n::%ld\n", + // __func__, + // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], udb->ug->u.a[z->x_id].len, z->x_pos_s, z->x_pos_e+1, + // "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], udb->ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, + // ch_idx, ch_n); + // for (i = ch_idx; i < cl->length && cl->list[i].readID == cl->list[ch_idx].readID; i++) { + // fprintf(stderr, "i::%ld[M::%s]\treadID::%u\tself_offset::%u\toffset::%u\t%c\n", + // i, __func__, cl->list[i].readID, cl->list[i].self_offset, cl->list[i].offset, + // "+-"[cl->list[i].strand]); + // } + // } + + // on = fusion_chain_ovlp(z, ch_a, ch_n, ov, on, wl, ql, tl); + aux_o->w_list.n = aux_o->w_list.c.n = 0; + aux_o->y_id = z->y_id; aux_o->y_pos_strand = z->y_pos_strand; + aux_o->x_pos_s = z->x_pos_s; aux_o->x_pos_e = z->x_pos_e; + aux_o->y_pos_s = z->y_pos_s; aux_o->y_pos_e = z->y_pos_e; + + memset(&ov, 0, sizeof(ov)); ov.sec = 3; + ov.ts = ov.te = (uint32_t)-1; + ov.qs = 0; ov.qn = (uint32_t)-1; //extension to left + ov.qe = ql; ov.tn = ch_n; //extension to right + + ovlp_base_direct(z, ch_a, ch_n, &ov, w_l, udb, NULL, NULL, qstr, tu, exz, aux_o, e_rate, ql, tl, rid); + + int64_t aux_n = aux_o->w_list.n; + + + // if(z->x_id == 57 && z->y_id == 2175) { + // fprintf(stderr, "\n-0-[M::%s]\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\n", + // __func__, + // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], udb->ug->u.a[z->x_id].len, z->x_pos_s, z->x_pos_e+1, + // "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], udb->ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1); + // for (i = 0; i < aux_n; i++) { + // window_list *m = &(aux_o->w_list.a[i]); + // fprintf(stderr, "i::%ld[M::%s]\tutg%.6u%c\twx::[%u,\t%u)\t%c\tutg%.6u%c\twy::[%u,\t%u)\terr::%d\tualn::%u\test::%u\n", i, __func__, + // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], m->x_start, m->x_end+1, + // "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], m->y_start, m->y_end+1, m->error, + // (is_ualn_win((*m))), (is_est_aln((*m)))); + // } + // fprintf(stderr, "\n"); + // } + + + for (i = 0; i < aux_n; i++) { + if(!(is_ualn_win(aux_o->w_list.a[i]))) continue; + //will overwrite ch_a; does not matter + rechain_aln(z, cl, aux_o, i, w_l, udb, NULL, NULL, qstr, tu, exz, e_rate, ql, tl, khit, rid); + } + + // if(z->x_id == 57 && z->y_id == 2175) { + // fprintf(stderr, "\n-1-[M::%s]\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\n", + // __func__, + // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], udb->ug->u.a[z->x_id].len, z->x_pos_s, z->x_pos_e+1, + // "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], udb->ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1); + // for (i = 0; i < ((int64_t)aux_o->w_list.n); i++) { + // window_list *m = &(aux_o->w_list.a[i]); + // fprintf(stderr, "i::%ld[M::%s]\tutg%.6u%c\twx::[%u,\t%u)\t%c\tutg%.6u%c\twy::[%u,\t%u)\terr::%d\tualn::%u\test::%u\n", i, __func__, + // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], m->x_start, m->x_end+1, + // "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], m->y_start, m->y_end+1, m->error, + // (is_ualn_win((*m))), (is_est_aln((*m)))); + // } + // fprintf(stderr, "\n"); + // } + + if(((int64_t)aux_o->w_list.n) > aux_n) { + for (i = m = 0; i < ((int64_t)aux_o->w_list.n); i++) { + if((i < aux_n) && (is_ualn_win(aux_o->w_list.a[i]))) continue; + aux_o->w_list.a[m++] = aux_o->w_list.a[i]; + } + aux_o->w_list.n = m; + radix_sort_window_list_xs_srt(aux_o->w_list.a, aux_o->w_list.a+aux_o->w_list.n); + } + + ///update z by aux_o + update_overlap_region(z, aux_o, ql, tl); + assert((z->x_pos_e>=z->x_pos_s) && (z->y_pos_e>=z->y_pos_s)); + + int64_t zwn = z->w_list.n, zerr = 0, zlen = z->x_pos_e+1-z->x_pos_s; + for (i = 0; i < zwn; i++) { + if(is_ualn_win(z->w_list.a[i])) { + zerr += MAX((z->w_list.a[i].x_end+1-z->w_list.a[i].x_start), + (z->w_list.a[i].y_end+1-z->w_list.a[i].y_start)); + } else { + zerr += z->w_list.a[i].error; + } + } + z->non_homopolymer_errors = zerr; + + // if(z->x_id == 57 && z->y_id == 2175) { + // fprintf(stderr, "\n-2-[M::%s]\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\n", + // __func__, + // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], udb->ug->u.a[z->x_id].len, z->x_pos_s, z->x_pos_e+1, + // "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], udb->ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1); + // for (i = 0; i < zwn; i++) { + // window_list *m = &(z->w_list.a[i]); + // fprintf(stderr, "i::%ld[M::%s]\tutg%.6u%c\twx::[%u,\t%u)\t%c\tutg%.6u%c\twy::[%u,\t%u)\terr::%d\tualn::%u\test::%u\n", i, __func__, + // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], m->x_start, m->x_end+1, + // "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], m->y_start, m->y_end+1, m->error, + // (is_ualn_win((*m))), (is_est_aln((*m)))); + // } + // fprintf(stderr, "\n"); + // } + + // if(z->x_id == 57 && z->y_id == 2175) { + // fprintf(stderr, "\n-3-[M::%s]\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\tzerr::%ld\tzlen::%ld\te_rate::%f\n", + // __func__, + // z->x_id+1, "lc"[udb->ug->u.a[z->x_id].circ], udb->ug->u.a[z->x_id].len, z->x_pos_s, z->x_pos_e+1, + // "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[udb->ug->u.a[z->y_id].circ], udb->ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, + // zerr, zlen, e_rate); + // } + + if(zerr >= zlen) return 0; + if(zerr <= 0 && zlen > 0) return 1; + if(zerr > (zlen*e_rate)) return 0; + return 1; +} + +void dedup_ul_ov_t(kv_ul_ov_t *in) +{ + ul_ov_t *a = in->a; int64_t k, l, m, z, r, a_n = in->n; uint64_t qo, to; double rr = 0.95; + for (k = 0; k < a_n; k++) a[k].tn = ((uint32_t)(a[k].tn<<1))|((uint32_t)(a[k].rev)); + radix_sort_ul_ov_srt_tn1(a, a + a_n); + for (k = 1, l = m = 0; k <= a_n; k++) { + if(k == a_n || a[k].tn != a[l].tn) { + for (z = l; z < k; z++) { + for (r=m-1; (r>=0) && (a[r].tn==(a[z].tn>>1)) && (a[r].rev==a[z].rev); r--) { + qo = ((MIN(a[z].qe, a[r].qe) > MAX(a[z].qs, a[r].qs))? + MIN(a[z].qe, a[r].qe) - MAX(a[z].qs, a[r].qs):0); + to = ((MIN(a[z].te, a[r].te) > MAX(a[z].ts, a[r].ts))? + MIN(a[z].te, a[r].te) - MAX(a[z].ts, a[r].ts):0); + if(qo >= ((a[r].qe - a[r].qs)*rr) && qo >= ((a[z].qe - a[z].qs)*rr) && + to >= ((a[r].te - a[r].ts)*rr) && to >= ((a[z].te - a[z].ts)*rr)) { + break; + } + } + if(r >= 0 && (a[r].tn==(a[z].tn>>1)) && (a[r].rev==a[z].rev)) { + if(a[z].sec < a[r].sec) { + a[r] = a[z]; a[r].tn >>= 1; + } + continue; + } + a[m] = a[z]; a[m].tn >>= 1; m++; + } + l = k; + } + } + // fprintf(stderr, "[M::%s::] in->n0::%ld, in->n::%ld\n", __func__, (int64_t)in->n, m); + in->n = m; +} + +void ul_rid_lalign_adv(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, const ug_opt_t *uopt, + char *qstr, uint64_t ql, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, + int64_t wl, kv_ul_ov_t *aln, kv_ul_ov_t *cln, kv_rtrace_t *trace, int64_t sid, uint64_t khit, void *km) +{ + uint64_t i, bs, k; Window_Pool w; double err; + overlap_region t; overlap_region *z; //asg64_v iidx, buf, buf1; + ol->mapped_overlaps_length = 0; + if(ol->length <= 0) return; + + ///base alignment + err = e_rate; + init_Window_Pool(&w, ql, wl, (int)(1.0/err)); + bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(tu, bs<<1); + + if(!aux_o) { + resize_UC_Read(qu, ql); qu->length = ql; memcpy(qu->seq, qstr, ql); + for (i = k = 0; i < ol->length; i++) { + z = &(ol->list[i]); z->shared_seed = z->non_homopolymer_errors;///for index + if(!ul_local_aln(z, cl, uref, qu->seq, tu, exz, err, w.window_length, + 1000, OVERLAP_THRESHOLD_NOSI_FILTER, NULL, NULL, NULL, ql, sid, i, khit, NULL)) { + continue; + } + if(k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + z = &(ol->list[k++]); z->is_match = 1; + } + ol->length = k; + if(ol->length <= 0) return; + } else { + for (i = cln->n = trace->n = 0; i < ol->length; i++) { + z = &(ol->list[i]); z->shared_seed = z->non_homopolymer_errors;///for index + // fprintf(stderr, "\n[M::%s::utg%.6dl(%c)] i::%lu, aln_l::%u, q::[%u, %u), ql::%u\n", __func__, + // (int32_t)z->y_id + 1, "+-"[z->y_pos_strand], i, z->align_length, + // z->x_pos_s, z->x_pos_e+1, z->x_pos_e+1-z->x_pos_s); + ul_local_aln(z, cl, uref, qu->seq, tu, exz, err, w.window_length, 1000, + OVERLAP_THRESHOLD_NOSI_FILTER, aln, cln, trace, ql, sid, i, khit, aux_o); + } + + ///contained reads + if(cln->n) dedup_ul_ov_t(cln); + if(cln->n) { + kv_resize(ul_ov_t, *aln, aln->n+cln->n); + memcpy(aln->a+aln->n, cln->a, cln->n*sizeof(*(aln->a))); + aln->n += cln->n; + } + + } +} + + +uint64_t gen_hc_fast_cigar(overlap_region *z, Candidates_list *cl, All_reads *rref, int64_t wl, char *qstr, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ql, int64_t rid, int64_t khit, int64_t *re) +{ + return_t_chain(z, cl); + gen_hc_fast_cigar0(z, cl, wl, rref, qstr, tu, exz, aux_o, e_rate, ql, rid, khit, re); + return 1; +} + +uint64_t gen_hc_fast_non_retrieve_cigar(overlap_region *z, Candidates_list *cl, int64_t wl, char *qstr, int64_t ql, char *tstr, int64_t tl, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t rid, int64_t khit) +{ + return_t_chain(z, cl); + gen_hc_fast_non_retrieve_cigar0(z, cl, wl, qstr, ql, tstr, tl, exz, aux_o, e_rate, rid, khit); + return 1; +} + +void append_cigar(window_list *idx, window_list_alloc *res, uint16_t c, uint32_t l) +{ + if(l <= 0) return; + uint16_t c0 = (uint16_t)-1; uint32_t l0 = 0; + ///last item of old cigar + if(idx->clen > 0) { + c0 = (res->c.a[res->c.n-1]>>14); + l0 = (res->c.a[res->c.n-1]&(0x3fff)); + } + ///first item of new cigar + if(c0 == c) {l += l0; res->c.n--; idx->clen--;} + + push_trace(((asg16_v *)(&(res->c))), c, l); + idx->clen = res->c.n-idx->cidx; +} + +uint16_t adjust_gap(window_list *idx, window_list_alloc *res, char *pstr, char *tstr, int64_t pi, int64_t ti, uint16_t op0, asg16_v* buf, int64_t *rd_err) +{ + (*rd_err) = 0; + + if(idx->clen == 0) { + append_cigar(idx, res, op0, 1); + return 0;///no move + } + if(op0 != 2 && op0 != 3) return 0;///no move + if(op0 == 2) {///more p -> y + ti--; + } else if(op0 == 3) {///more t -> x + pi--; + } + + // if(z->y_id == 3199 && z->x_id == 3196) { + // fprintf(stderr, "\n[M::%s]\tqi::%ld\tti::%ld\n", __func__, ti, pi); + // } + + uint16_t *ca = res->c.a+idx->cidx; + int64_t ci = idx->clen; int64_t op, cl, k, l[2]; uint16_t p, ff; + for (ci--, buf->n = ff = 0; ci >= 0; ci--) { + op = ca[ci]>>14; cl = (ca[ci]&(0x3fff)); + // if(z->y_id == 3199 && z->x_id == 3196) { + // fprintf(stderr, "[M::%s]\tqi::%ld\tti::%ld\tci::%ld\tcl::%ld\top::%ld\n", __func__, ti, pi, ci, cl, op); + // } + if(op == 2 || op == 3) { + p = op0; p <<= 14; p += 1; kv_push(uint16_t, *buf, p); + l[0] = cl; + p = op; p <<= 14; p += l[0]; kv_push(uint16_t, *buf, p); + break; + } else if(op == 0) { + for (k = cl-1, l[0] = l[1] = 0; k >= 0; k--, pi--, ti--) { + if(pstr[pi] != (tstr[ti])) break; + // if(op == 1) { + // if(!(pstr[pi] != (tstr[ti]))) { + // fprintf(stderr, "[M::%s] xid::%u, yid::%u, qi::%ld, ti::%ld\n", __func__, z->x_id, z->y_id, ti, pi); + // } + // assert(pstr[pi] != (tstr[ti])); + // } + } + l[1] = cl - k - 1; l[0] = k + 1; + if(l[1] > 0) { + p = op; p <<= 14; p += l[1]; kv_push(uint16_t, *buf, p); ff = 1; + } + + if(l[0] > 0) { + p = op0; p <<= 14; p += 1; kv_push(uint16_t, *buf, p); + } + + if(l[0] > 0) { + p = op; p <<= 14; p += l[0]; kv_push(uint16_t, *buf, p); + } + } else {///op == 1; it is possible since cigar is not optimal + for (k = cl-1, l[0] = cl, l[1] = 0; k >= 0; k--, pi--, ti--) { + if(pstr[pi] == (tstr[ti])) { + l[1] = l[0] - k - 1; + l[0] = k; + + if(l[1] > 0) { + p = op; p <<= 14; p += l[1]; kv_push(uint16_t, *buf, p); ff = 1;///push unmatch + } + p = 0; p <<= 14; p += 1; kv_push(uint16_t, *buf, p);///push match + (*rd_err)++; + } + } + + if(l[0] > 0) { + p = op; p <<= 14; p += l[0]; kv_push(uint16_t, *buf, p); + } + l[0] = 0; + } + + // fprintf(stderr, "[M::%s] ci::%ld, l[0]::%ld, l[1]::%ld\n", __func__, ci, l[0], l[1]); + + if(l[0] > 0) break; + } + + // fprintf(stderr, "[M::%s] ff::%u, ci::%ld, buf->n::%lu\n", __func__, ff, ci, (uint64_t)buf->n); + + if(!ff) {///no move + append_cigar(idx, res, op0, 1); + return 0;///no move + } else if(ci >= 0) { + // if(!(idx->cidx + idx->clen == res->c.n)) { + // fprintf(stderr, "[M::%s] idx->cidx::%lu, idx->clen::%lu, res->c.n::%lu\n", __func__, (uint64_t)idx->cidx, (uint64_t)idx->clen, (uint64_t)res->c.n); + // } + assert(idx->cidx + idx->clen == res->c.n); + idx->clen = ci; res->c.n = idx->cidx + idx->clen; + for (k = ((int64_t)buf->n)-1; k >= 0; k--) { + op = buf->a[k]>>14; cl = (buf->a[k]&(0x3fff)); + append_cigar(idx, res, op, cl); + } + } else { + idx->clen = 0; res->c.n = idx->cidx + idx->clen; + append_cigar(idx, res, op0, 1); + for (k = ((int64_t)buf->n)-1; k >= 0; k--) { + op = buf->a[k]>>14; cl = (buf->a[k]&(0x3fff)); + append_cigar(idx, res, op, cl); + } + } + return 1;///no move +} + +uint16_t ajust_end_cigar(window_list *idx, window_list_alloc *res) +{ + uint16_t *ca = res->c.a+idx->cidx, p, rr = 0; int64_t ci, cn = idx->clen, op, cl; + if(cn <= 0) return rr; + for (ci = 0; ci < cn; ci++) { + op = ca[ci]>>14; cl = (ca[ci]&(0x3fff)); + if(op != 1) break; + p = 3; p <<= 14; p += cl; ca[ci] = p; idx->y_start += cl; rr = 1; + } + + for (ci = cn-1; ci >= 0; ci--) { + op = ca[ci]>>14; cl = (ca[ci]&(0x3fff)); + if(op != 1) break; + p = 3; p <<= 14; p += cl; ca[ci] = p; idx->y_end -= cl; rr = 1; + } + + // if(rr) fprintf(stderr, "[M::%s] rr::%u\n", __func__, rr); + + return rr; +} + +uint16_t move_wins(overlap_region *z, uint32_t wid, overlap_region *aux, All_reads *rref, char *tstr, char *pstr, UC_Read *pu, asg16_v* buf, int64_t *tot_re) +{ + // if(z->y_id == 46133) { + // fprintf(stderr, "\n[M::%s] x_id::%u, y_id::%u, x::[%u, %u), y::[%u, %u)\n", __func__, z->x_id, z->y_id, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); + // fprintf(stderr, "[M::%s] wid::%u, x::[%d, %d), y::[%d, %d), err::%d\n", __func__, wid, z->w_list.a[wid].x_start, z->w_list.a[wid].x_end + 1, z->w_list.a[wid].y_start, z->w_list.a[wid].y_end + 1, z->w_list.a[wid].error); + // } + if(is_ualn_win((z->w_list.a[wid]))) { + kv_push(window_list, aux->w_list, (z->w_list.a[wid])); + return 0;///no move + } + + window_list *p = NULL; char *tseq = tstr, *pseq = pstr; + bit_extz_t ez; set_bit_extz_t(ez, (*z), wid); + kv_pushp(window_list, aux->w_list, &p); + p->x_start = ez.ts; p->x_end = ez.te; + p->y_start = ez.ps; p->y_end = ez.pe; + p->error_threshold = 0; p->error = ez.err;///single round of alignment cannot have INT16_MAX errors + p->cidx = aux->w_list.c.n; p->clen = 0; ///aux->w_list.c.n += ez.cigar.n; + + if(ez.err == 0) { + push_wcigar(p, &(aux->w_list), &ez); + return 0;///no move + } + + int64_t pi = ez.ps, ti = ez.ts/**, err = 0**/, cl, op, k, rr = 0, re; uint64_t ci = 0, mm = 0; + // char cm[4]; cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; + // if(z->y_id == 3199 && z->x_id == 3196) { + // fprintf(stderr, "******\n"); + // for (ci = 0; ci < ez.cigar.n; ci++) { + // op = ez.cigar.a[ci]>>14; cl = (ez.cigar.a[ci]&(0x3fff)); + // fprintf(stderr, "%ld%c(q::[%ld,%ld))(t::[%ld,%ld))(ck::%ld)\n", cl, cm[op], ti, ti + (((op<2)||(op==3))?(cl):(0)), pi, pi + (((op<2)||(op==2))?(cl):(0)), ci); + + // if(op < 2) { + // pi+=cl; ti+=cl; + // } else { + // if(op == 2) {///more p -> y + // pi+=cl; + // } else if(op == 3) {///more t -> x + // ti+=cl; + // } + // } + // } + // pi = ez.ps; ti = ez.ts; + // fprintf(stderr, "******\n"); + // } + + for (ci = mm = 0; ci < ez.cigar.n; ci++) { + op = ez.cigar.a[ci]>>14; ///cl = (ez.cigar.a[ci]&(0x3fff)); + if(op < 2) { + mm = 1; + } else if(mm) { + break; + } + // if(op == 2 || op == 3) break; + } + if(ci >= ez.cigar.n) { + push_wcigar(p, &(aux->w_list), &ez); + if(ajust_end_cigar(p, &(aux->w_list))) rr = 1; + return rr; + } + + if(!pseq) { + if(z->y_pos_strand) { + recover_UC_Read_RC(pu, rref, aux->y_id); + } else { + recover_UC_Read(pu, rref, aux->y_id); + } + pseq = pu->seq; + } + + kv_resize(uint16_t, aux->w_list.c, (aux->w_list.c.n + ez.cigar.n)); + + for (ci = mm = 0; ci < ez.cigar.n; ci++) { + op = ez.cigar.a[ci]>>14; cl = (ez.cigar.a[ci]&(0x3fff)); + // if(z->x_id == 21102 && z->y_id == 21139) { + // fprintf(stderr, "[M::%s] ci::%lu, op::%ld, cl::%ld, yi::%ld, xi::%ld, cn::%u, rr::%ld\n", __func__, ci, op, cl, pi, ti, p->clen, rr); + // // fprintf(stderr, "[M::%s] p->cidx::%lu, p->clen::%lu, cc->n::%lu\n", __func__, (uint64_t)p->cidx, (uint64_t)p->clen, (uint64_t)aux->w_list.c.n); + // } + // if(z->y_id == 3199 && z->x_id == 3196) { + // fprintf(stderr, "%ld%c(q::[%ld,%ld))(t::[%ld,%ld))(ck::%ld)\tmm::%lu\n", cl, cm[op], ti, ti + (((op<2)||(op==3))?(cl):(0)), pi, pi + (((op<2)||(op==2))?(cl):(0)), ci, mm); + // } + + if(op < 2) { + append_cigar(p, &(aux->w_list), op, cl); + pi+=cl; ti+=cl; mm = 1; + } else { + if(mm == 0) { + append_cigar(p, &(aux->w_list), op, cl); + if(op == 2) {///more p -> y + pi+=cl; + } else if(op == 3) {///more t -> x + ti+=cl; + } + } else { + for (k = 0; k < cl; k++) { + // if(z->y_id == 46133) { + // fprintf(stderr, "+++k::%ld\tqi::%ld\tti::%ld\n", k, ti, pi); + // } + if(adjust_gap(p, &(aux->w_list), pseq, tseq, pi, ti, op, buf, &re)) { + rr = 1; p->error -= re; (*tot_re) += re; + } + if(op == 2) {///more p -> y + pi++; + } else if(op == 3) {///more t -> x + ti++; + } + } + } + } + } + + // if(z->x_id == 21102 && z->y_id == 21139) { + // fprintf(stderr, "[M::%s] ci::%lu, cn::%u, rr::%ld\n", __func__, ci, p->clen, rr); + // } + + // if(rr) fprintf(stderr, "[M::%s] rr::%ld\n", __func__, rr); + + if(ajust_end_cigar(p, &(aux->w_list))) rr = 1; + return rr; +} + +inline uint16_t trim_extz(bit_extz_t *ez, uint16_t trim_left, uint16_t trim_right) +{ + int64_t ck, cn = ez->cigar.n; uint16_t m, op, ol, rr = 0; + if(trim_left) { + for (ck = 0; ck < cn; ck++) { + op = ez->cigar.a[ck]>>14; + ol = ez->cigar.a[ck]&(0x3fff); + if(op!=1) break; + m = 3; m <<= 14; m += ol; ez->cigar.a[ck] = m; + ez->ps += ol; rr = 1;///ez->ps == y_start + } + } + + if(trim_right) { + for (ck = cn-1; ck >= 0; ck--) { + op = ez->cigar.a[ck]>>14; + ol = ez->cigar.a[ck]&(0x3fff); + if(op!=1) break; + m = 3; m <<= 14; m += ol; ez->cigar.a[ck] = m; + ez->pe -= ol; rr = 1;///ez->pe == y_end + } + } + + + return rr; +} + +void push_trace_iter(asg16_v *exz, uint16_t c, uint32_t l) +{ + if(l <= 0) return; + uint16_t c0 = (uint16_t)-1; uint32_t l0 = 0; + ///last item of old cigar + if(exz->n > 0) { + c0 = (exz->a[exz->n-1]>>14); + l0 = (exz->a[exz->n-1]&(0x3fff)); + } + ///first item of new cigar + if(c0 == c) {l += l0; exz->n--;} + + push_trace(exz, c, l); +} + +uint16_t adjust_gap_0(bit_extz_t *rs, char *xz, int64_t xk, char *yz, int64_t yk, uint16_t op0, int64_t *rd_err) +{ + (*rd_err) = 0; + + if(rs->cigar.n == 0) { + push_trace_iter(&(rs->cigar), op0, 1); + return 0;///no move + } + if(op0 != 2 && op0 != 3) return 0;///no move + if(op0 == 2) {///more y + xk--;///ti-- + } else if(op0 == 3) {///more x + yk--; + } + + int64_t ck, cn = rs->cigar.n, n_cn = 0; int64_t op, cl, k, l[2]; uint16_t p, ff; + for (ck = cn -1, ff = 0; ck >= 0; ck--) { + op = rs->cigar.a[ck]>>14; + cl = (rs->cigar.a[ck]&(0x3fff)); + + if(op == 2 || op == 3) { + p = op0; p <<= 14; p += 1; kv_push(uint16_t, rs->cigar, p); + l[0] = cl; + p = op; p <<= 14; p += l[0]; kv_push(uint16_t, rs->cigar, p); ///(1:op0)|(l[0]:op) + break; + } else if(op == 0) { + for (k = cl-1, l[0] = l[1] = 0; (k >= 0) && (xz[xk] == yz[yk]); k--, xk--, yk--); + + ///(l[1]:op)|(1:op0)|(l[0]:op) + l[1] = cl - k - 1; l[0] = k + 1; + if(l[1] > 0) { + p = op; p <<= 14; p += l[1]; kv_push(uint16_t, rs->cigar, p); ff = 1; + } + if(l[0] > 0) { + p = op0; p <<= 14; p += 1; kv_push(uint16_t, rs->cigar, p); + } + if(l[0] > 0) { + p = op; p <<= 14; p += l[0]; kv_push(uint16_t, rs->cigar, p); + } + } else {///op == 1; it is possible since cigar is not optimal + for (k = cl-1, l[0] = cl, l[1] = 0; k >= 0; k--, xk--, yk--) { + if(xz[xk] == (yz[yk])) { + l[1] = l[0] - k - 1; + l[0] = k; + + if(l[1] > 0) { + p = op; p <<= 14; p += l[1]; kv_push(uint16_t, rs->cigar, p); ff = 1;///push unmatch + } + p = 0; p <<= 14; p += 1; kv_push(uint16_t, rs->cigar, p);///push match + (*rd_err)++; + } + } + + if(l[0] > 0) { + p = op; p <<= 14; p += l[0]; kv_push(uint16_t, rs->cigar, p); + } + l[0] = 0; + } + + if(l[0] > 0) break; + } + + // fprintf(stderr, "[M::%s] ff::%u, ci::%ld, buf->n::%lu\n", __func__, ff, ci, (uint64_t)buf->n); + n_cn = rs->cigar.n - cn; + if(!ff) {///no move + rs->cigar.n = cn;///not necessary + push_trace_iter(&(rs->cigar), op0, 1); + return 0;///no move + } else { + assert(n_cn); + cl = n_cn >> 1; + for (k = 0; k < cl; k++) { + p = rs->cigar.a[k + cn]; + rs->cigar.a[k + cn] = rs->cigar.a[cn + n_cn - k - 1]; + rs->cigar.a[cn + n_cn - k - 1] = p; + } + rs->cigar.n = ((ck >= 0)?(ck):(0)); + if(ck < 0) push_trace_iter(&(rs->cigar), op0, 1); + for (k = 0; k < n_cn; k++) { + p = rs->cigar.a[k + cn]; + op = p>>14; cl = (p&(0x3fff)); + push_trace_iter(&(rs->cigar), op, cl); + } + } + return 1;///no move +} + +uint16_t adjust_gap_0_adv_gradu(bit_extz_t *rs, char *xz, int64_t xk0, char *yz, int64_t yk0, uint16_t op0, int64_t op0_l, int64_t *rd_err, int64_t *skip_indel/**, uint8_t dbg**/) +{ + (*rd_err) = (*skip_indel) = 0; + if(op0_l <= 0) return 0;///no move + + + (*skip_indel) = 1; + if(rs->cigar.n == 0) { + push_trace_iter(&(rs->cigar), op0, op0_l); + (*skip_indel) = op0_l; + return 1;///no move + } + + if(op0 != 2 && op0 != 3) return 0;///no move + + int64_t ck, cn = rs->cigar.n, cn1, n_cn = 0, ol; int64_t op, cl, k, l[2], xk, yk; uint16_t p, ff; + + // if(dbg) { + // for (ck = 0; ck < cn; ck++) { + // op = rs->cigar.a[ck]>>14; + // ol = rs->cigar.a[ck]&(0x3fff); + // fprintf(stderr, "%ld%c", ol, "MSID"[op]); + // } + // fprintf(stderr, "\n"); + // } + + + // for (ol = 1; ol <= op0_l; ol++) { + for (ol = op0_l; ol >= 1; ol--) { + // if(dbg) { + // fprintf(stderr, "-0-ol::%ld\n", ol); + // } + + xk = xk0; yk = yk0; + if(op0 == 2) {///more y + xk -= ol;///ti-- + } else if(op0 == 3) {///more x + yk -= ol; + } + + xk = xk + ol - 1; + yk = yk + ol - 1; + cn = rs->cigar.n; + ck = cn - 1; + ff = 0; + + if(xk >= 0 && yk >= 0) { + for (; ck >= 0; ck--) { + op = rs->cigar.a[ck]>>14; + cl = (rs->cigar.a[ck]&(0x3fff)); + + // if(dbg) { + // fprintf(stderr, "-1-ol::%ld, cl::%ld, op::%ld\n", ol, cl, op); + // } + + if(op == 2 || op == 3) { + // if(dbg) { + // fprintf(stderr, "-2-op::%ld\n", op); + // } + p = op0; p <<= 14; p += ((uint64_t)ol); kv_push(uint16_t, rs->cigar, p); + l[0] = cl; + p = op; p <<= 14; p += l[0]; kv_push(uint16_t, rs->cigar, p); ///(1:op0)|(l[0]:op) + break; + } else if(op == 0) { + /** + for (k = cl - ol, l[0] = l[1] = 0; (k >= 0) && (xk >= 0) && (yk >= 0); k -= ol, xk -= ol, yk -= ol) { + for (zk = 0; (zk < ol) && (xz[xk - zk] == yz[yk - zk]); zk++); + if(zk < ol) break; + } + ///(l[1]:op)|(1:op0)|(l[0]:op) + l[0] = k + ol; l[1] = cl - l[0]; + **/ + for (k = cl - 1, l[0] = l[1] = 0; (k >= 0) && (xk >= 0) && (yk >= 0); k--, xk--, yk--){ + // if(dbg) { + // fprintf(stderr, "-###-op::%ld, xz[%ld]::%c, yz[%ld]::%c\n", op, xk, xz[xk], yk, yz[yk]); + // } + if(xz[xk] != yz[yk]) break; + } + ///(l[1]:op)|(1:op0)|(l[0]:op) + l[1] = cl - k - 1; l[0] = k + 1; + + + if(l[1] > 0) { + p = op; p <<= 14; p += l[1]; kv_push(uint16_t, rs->cigar, p); ff = 1; + } + if(l[0] > 0) { + p = op0; p <<= 14; p += ((uint64_t)ol); kv_push(uint16_t, rs->cigar, p); + } + if(l[0] > 0) { + p = op; p <<= 14; p += l[0]; kv_push(uint16_t, rs->cigar, p); + } + // if(dbg) { + // fprintf(stderr, "-2-op::%ld, l[0]::%ld, l[1]::%ld, ff::%u, xk::%ld, yk::%ld\n", op, l[0], l[1], ff, xk, yk); + // } + } else {///op == 1; it is possible since cigar is not optimal + for (k = cl-1, l[0] = cl, l[1] = 0; k >= 0; k--, xk--, yk--) { + // if(dbg) { + // fprintf(stderr, "-***-op::%ld, xz[%ld]::%c, yz[%ld]::%c\n", op, xk, xz[xk], yk, yz[yk]); + // } + if(xz[xk] == (yz[yk])) { + l[1] = l[0] - k - 1; + l[0] = k; + + if(l[1] > 0) { + p = op; p <<= 14; p += l[1]; kv_push(uint16_t, rs->cigar, p); ff = 1;///push unmatch + } + p = 0; p <<= 14; p += 1; kv_push(uint16_t, rs->cigar, p);///push match + (*rd_err)++; + } + } + + + if(l[0] > 0) { + p = op; p <<= 14; p += l[0]; kv_push(uint16_t, rs->cigar, p); + ff = 1;///mismatch and indel have been switched///r826 + } + // if(dbg) { + // fprintf(stderr, "-2-op::%ld, l[0]::%ld, l[1]::%ld, ff::%u, xk::%ld, yk::%ld\n", op, l[0], l[1], ff, xk, yk); + // } + l[0] = 0; + } + + if(l[0] > 0) break; + } + } + cn1 = ck; + + + // fprintf(stderr, "[M::%s] ff::%u, ci::%ld, buf->n::%lu\n", __func__, ff, ci, (uint64_t)buf->n); + n_cn = rs->cigar.n - cn; + // if(dbg) { + // fprintf(stderr, "-3-ol::%ld, ff::%u, op0_l::%ld, cn1::%ld\n", ol, ff, op0_l, cn1); + // for (ck = 0; ck < cn; ck++) { + // op = rs->cigar.a[ck]>>14; + // cl = rs->cigar.a[ck]&(0x3fff); + // fprintf(stderr, "%ld%c", cl, "MSID"[op]); + // } + // fprintf(stderr, "\n"); + // } + if(!ff) {///no move + rs->cigar.n = cn;///not necessary + if(ol == op0_l) { + push_trace_iter(&(rs->cigar), op0, ol); + (*skip_indel) = op0_l; + // if(dbg) { + // for (ck = 0; ck < cn; ck++) { + // op = rs->cigar.a[ck]>>14; + // ol = rs->cigar.a[ck]&(0x3fff); + // fprintf(stderr, "%ld%c", ol, "MSID"[op]); + // } + // fprintf(stderr, "\n"); + // } + return 0;///no move + } + } else { + assert(n_cn); + cl = n_cn >> 1; + for (k = 0; k < cl; k++) { + p = rs->cigar.a[k + cn]; + rs->cigar.a[k + cn] = rs->cigar.a[cn + n_cn - k - 1]; + rs->cigar.a[cn + n_cn - k - 1] = p; + } + rs->cigar.n = ((cn1 >= 0)?(cn1):(0)); + if(cn1 < 0) push_trace_iter(&(rs->cigar), op0, ol); + for (k = 0; k < n_cn; k++) { + p = rs->cigar.a[k + cn]; + op = p>>14; cl = (p&(0x3fff)); + push_trace_iter(&(rs->cigar), op, cl); + } + (*skip_indel) = ol; + + // if(dbg) { + // cn = rs->cigar.n; + // fprintf(stderr, "-5-ol::%ld, ff::%u, op0_l::%ld\n", ol, ff, op0_l); + // for (ck = 0; ck < cn; ck++) { + // op = rs->cigar.a[ck]>>14; + // cl = rs->cigar.a[ck]&(0x3fff); + // fprintf(stderr, "%ld%c", cl, "MSID"[op]); + // } + // fprintf(stderr, "\n"); + // } + return 1; + } + } + + return 0;///no move +} + +uint16_t move_wins_adv0(bit_extz_t *ez, char *xin, char *yin, UC_Read *yu, uint64_t yid, uint16_t rev, All_reads *rref, uint16_t trim_left, uint16_t trim_right, bit_extz_t *rs, int64_t* tot_re) +{ + int64_t yk = ez->ps, xk = ez->ts, ol, k, rr = 0, re, ck = 0, cn = ez->cigar.n, ski; uint16_t op, mm = 0; + rs->cigar.n = 0; + rs->err = ez->err; rs->thre = ez->thre; + rs->ts = ez->ts; rs->te = ez->te; + rs->ps = ez->ps; rs->pe = ez->pe; + + for (ck = mm = 0; ck < cn; ck++) { + op = ez->cigar.a[ck]>>14; + if(op < 2) {mm = 1;} + else if(mm) {break;} + } + if(ck >= cn) { + kv_resize(uint16_t, rs->cigar, ez->cigar.n); rs->cigar.n = ez->cigar.n; + memcpy(rs->cigar.a, ez->cigar.a, ez->cigar.n*sizeof(*(ez->cigar.a))); + if((trim_left || trim_right) && (trim_extz(rs, trim_left, trim_right))) rr = 1; + return rr; + } + + char *xz = xin, *yz = yin; + if(!yz) { + if(rev) recover_UC_Read_RC(yu, rref, yid); + else recover_UC_Read(yu, rref, yid); + yz = yu->seq; + } + + ck = mm = 0; + while (ck < cn) { + op = ez->cigar.a[ck]>>14; + ol = (ez->cigar.a[ck]&(0x3fff)); + // if(op!=2) xk += ol; + // if(op!=3) yk += ol; + + // if(ez->ts == 8581 && ez->te == 8582 && ez->ps == 5114 && ez->pe == 5114) { + // fprintf(stderr, "[M::%s] ci::%ld, op::%u, cl::%ld, yi::%ld, xi::%ld, cn::%u, rr::%ld\n", __func__, ck, op, ol, yk, xk, (uint32_t)rs->cigar.n, rr); + // } + + + if(op < 2) { + push_trace_iter(&(rs->cigar), op, ol); mm = 1; + // if(!cigar_check(yz, xz, rs)) { + // fprintf(stderr, "-0-[M::%s] y_id::%lu, xk::%ld, yk::%ld, ol::%ld, op::%c\n", __func__, yid, xk, yk, ol, "MSID"[op]); + // exit(1); + // } + + + xk += ol; yk += ol; + } else { + if(!mm) { + push_trace_iter(&(rs->cigar), op, ol); + // if(!cigar_check(yz, xz, rs)) { + // fprintf(stderr, "-1-[M::%s] y_id::%lu, xk::%ld, yk::%ld, ol::%ld, op::%c\n", __func__, yid, xk, yk, ol, "MSID"[op]); + // exit(1); + // } + + if(op!=2) xk += ol; + if(op!=3) yk += ol; + } else { + // for (k = 0; k < ol; k++) { + // if(adjust_gap_0(rs, xz, xk, yz, yk, op, &re)) { + // rr = 1; rs->err -= re; (*tot_re) += re; + // } + // if(op!=2) xk++; + // if(op!=3) yk++; + // } + + k = 0; + while (k < ol) { + // fprintf(stderr, "[M::%s] k::%ld, ol::%ld\n", __func__, k, ol); + ski = 0; + if(adjust_gap_0_adv_gradu(rs, xz, xk, yz, yk, op, ol - k, &re, &ski /**, (ez->ts == 8581 && ez->te == 8582 && ez->ps == 5114 && ez->pe == 5114)?1:0)**/)) { + // if(ski > 1) { + // fprintf(stderr, "-ski-tid::%lu\t%.*s\tski::%ld\txk::%ld\tyk::%ld\n", yid, (int)Get_NAME_LENGTH(R_INF, yid), Get_NAME(R_INF, yid), ski, xk, yk); + // } + rr = 1; rs->err -= re; (*tot_re) += re; + } + // if(!cigar_check(yz, xz, rs)) { + // fprintf(stderr, "-*-[M::%s] y_id::%lu, xk::%ld, yk::%ld, ol::%ld, k::%ld, ski::%ld, op::%c\n", __func__, yid, xk, yk, ol, k, ski, "MSID"[op]); + // exit(1); + // } + // fprintf(stderr, "[M::%s] k::%ld, ski::%ld\n", __func__, k, ski); + + if(op!=2) xk += ski; + if(op!=3) yk += ski; + k += ski; + } + } + } + + ck++; + } + + // if(yid == 21139) { + // fprintf(stderr, "[M::%s] ci::%ld, cn::%u, rr::%ld\n", __func__, ck, (uint32_t)rs->cigar.n, rr); + // } + + if((trim_left || trim_right) && (trim_extz(rs, trim_left, trim_right))) rr = 1; + return rr; +} + +///t->x; p->y +uint16_t move_wins_adv(overlap_region *z, uint32_t wid, overlap_region *aux, All_reads *rref, char *xstr, char *ystr, UC_Read *yu, asg16_v* buf, int64_t *tot_re) +{ + if(is_ualn_win((z->w_list.a[wid]))) { + kv_push(window_list, aux->w_list, (z->w_list.a[wid])); + return 0;///no move + } + + window_list *p = NULL; bit_extz_t ez; set_bit_extz_t(ez, (*z), wid); + kv_pushp(window_list, aux->w_list, &p); + p->x_start = ez.ts; p->x_end = ez.te; + p->y_start = ez.ps; p->y_end = ez.pe; + p->error_threshold = 0; p->error = ez.err;///single round of alignment cannot have INT16_MAX errors + p->cidx = aux->w_list.c.n; p->clen = 0; ///aux->w_list.c.n += ez.cigar.n; + + if(ez.err == 0) { + push_wcigar(p, &(aux->w_list), &ez); + return 0;///no move + } + + bit_extz_t rs; memset(&rs, 0, sizeof(rs)); int64_t rr = 0; + rs.cigar.a = buf->a; rs.cigar.n = buf->n; rs.cigar.m = buf->m; + + rr = move_wins_adv0(&ez, xstr, ystr, yu, z->y_id, z->y_pos_strand, rref, 1, 1, &rs, tot_re); + p->x_start = rs.ts; p->x_end = rs.te; p->y_start = rs.ps; p->y_end = rs.pe; p->error = rs.err; + push_wcigar(p, &(aux->w_list), &rs); + + buf->a = rs.cigar.a; buf->n = rs.cigar.n; buf->m = rs.cigar.m; + return rr; +} + + + + +uint64_t hpc_flat_dir0(int64_t xp, char *xstr, int64_t xlen, int64_t yp, char *ystr, int64_t ylen, uint8_t* xhpf, int64_t hpc_rr, int64_t hpc_cutoff, ul_ov_t *rr) +{ + int64_t p, k, r, an, rc, zs, ze, zx[2], zy[2], kl/**, km**/; char *a; uint64_t m, cm, cmk, xm, xmk, ym, ymk, msk, f, rf = 0; + rr->qs = rr->qe = rr->ts = rr->te = UINT32_MAX; + if((xp >= xlen)||(yp >= ylen)) return 0; + if((xp < 0)||(yp < 0)) return 0; + if(!xhpf[xp]) return 0; + xm = ym = xmk = ymk = (uint64_t)-1; zx[0] = zx[1] = zy[0] = zy[1] = -1; + + for (r = 1; r <= hpc_rr; r++) { + // if(xp == 18767) { + // fprintf(stderr, "[M::%s]\trr[%ld]::%u\n", __func__, xp, ((xhpf[xp]>>(r-1))&1)); + // } + if(!((xhpf[xp]>>(r-1))&1)) continue;///r + 1 + rc = r * hpc_cutoff;///HPC_CC; + msk = (((uint64_t)1)<<(r+r))-1; ///km = r + r - 1; + + ///inlcuding p + p = xp; an = xlen; a = xstr; + + m = cm = msk; zs = ze = -1; f = 0; cmk = (uint64_t)-1; + for (k = p + r; (k < an) && ((k-r) >= 0) && (a[k] == a[k-r]); k++){;} ze = k; if(ze > an) {ze = an;} + for (k = p - 1; (k >= 0) && ((k+r) < an) && (a[k] == a[k+r]); k--){;} zs = k + 1; if(zs < 0) {zs = 0;} + if(((ze - zs) > r) && ((ze - zs) >= rc)) { + for (k = zs, f = 1, kl = 0; k < ze; k++) { + m <<= 2; m |= seq_nt4_table[(uint8_t)a[k]]; m &= msk; kl++; + + // if(zs == 39582 && ze == 39589) { + // fprintf(stderr, "+[M::%s] a[%ld]::%c, zs::%ld, ze::%ld, m::%lu, cm::%lu, kl::%ld, r::%ld\n", __func__, k, a[k], zs, ze, m, cm, kl, r); + // } + + if(kl >= r && m <= cm) { + cm = m; cmk = k; + } + } + } else { + ///inlcuding p + for (k = p - r; (k >= 0) && ((k+r) < an) && (a[k] == a[k+r]); k--){;} zs = k + 1; if(zs < 0) {zs = 0;} + for (k = p + 1; (k < an) && ((k-r) >= 0) && (a[k] == a[k-r]); k++){;} ze = k; if(ze > an) {ze = an;} + if(((ze - zs) > r) && ((ze - zs) >= rc)) { + for (k = zs, f = 1, kl = 0; k < ze; k++) { + m <<= 2; m |= seq_nt4_table[(uint8_t)a[k]]; m &= msk; kl++; + + // if(zs == 39582 && ze == 39589) { + // fprintf(stderr, "-[M::%s] a[%ld]::%c, zs::%ld, ze::%ld, m::%lu, cm::%lu, kl::%ld, r::%ld\n", __func__, k, a[k], zs, ze, m, cm, kl, r); + // } + + if(kl >= r && m <= cm) { + cm = m; cmk = k; + } + } + } + } + if(!f) continue; + + xm = cm; xmk = cmk; zx[0] = zs; zx[1] = ze; + + + + ///inlcuding p + p = yp; an = ylen; a = ystr; + + m = cm = msk; zs = ze = -1; f = 0; + for (k = p + r; (k < an) && ((k-r) >= 0) && (a[k] == a[k-r]); k++){;} ze = k; if(ze > an) {ze = an;} + for (k = p - 1; (k >= 0) && ((k+r) < an) && (a[k] == a[k+r]); k--){;} zs = k + 1; if(zs < 0) {zs = 0;} + if(((ze - zs) > r) && ((ze - zs) >= rc)) { + for (k = zs, f = 1, kl = 0; k < ze; k++) { + m <<= 2; m |= seq_nt4_table[(uint8_t)a[k]]; m &= msk; kl++; + + // if(zs == 889 && ze == 895) { + // fprintf(stderr, "+[M::%s] a[%ld]::%c, zs::%ld, ze::%ld, m::%lu, cm::%lu, kl::%ld, r::%ld\n", __func__, k, a[k], zs, ze, m, cm, kl, r); + // } + + + if(kl >= r && m <= cm) { + cm = m; cmk = k; + } + } + } else { + ///inlcuding p + for (k = p - r; (k >= 0) && ((k+r) < an) && (a[k] == a[k+r]); k--){;} zs = k + 1; if(zs < 0) {zs = 0;} + for (k = p + 1; (k < an) && ((k-r) >= 0) && (a[k] == a[k-r]); k++){;} ze = k; if(ze > an) {ze = an;} + if(((ze - zs) > r) && ((ze - zs) >= rc)) { + for (k = zs, f = 1, kl = 0; k < ze; k++) { + m <<= 2; m |= seq_nt4_table[(uint8_t)a[k]]; m &= msk; kl++; + + // if(zs == 889 && ze == 895) { + // fprintf(stderr, "-[M::%s] a[%ld]::%c, zs::%ld, ze::%ld, m::%lu, cm::%lu, kl::%ld, r::%ld\n", __func__, k, a[k], zs, ze, m, cm, kl, r); + // } + + if(kl >= r && m <= cm) { + cm = m; cmk = k; + } + } + } + } + if(!f) continue; + + ym = cm; ymk = cmk; zy[0] = zs; zy[1] = ze; + + if(xm == ym) { + // if(zx[0] == 39582 && zx[1] == 39589 && zy[0] == 889 && zy[1] == 895) { + // fprintf(stderr, "[M::%s] xm::%lu, ym::%lu, r::%ld\n", __func__, xm, ym, r); + // } + rf = 1; break; + } + } + + if(rf) { + an = zx[1] - xmk; + if(an > (zy[1] - ((int64_t)ymk))) an = zy[1] - ymk; + assert(xstr[xmk] == ystr[ymk]); + for (k = 0; (k < an) && (xstr[xmk + k] == ystr[ymk + k]); k++); + + // fprintf(stderr, "[M::%s] zx[1]::%ld, xmk::%lu, zy[1]::%ld, ymk::%lu, k::%ld\n", __func__, zx[1], xmk, zy[1], ymk, k); + + rr->qs = zx[0]; rr->qe = zx[1]; rr->qn = xmk + k; + rr->ts = zy[0]; rr->te = zy[1]; rr->tn = ymk + k; + return r; + } + + return 0; +} + +inline int64_t hpc_imp_score(int64_t rr, int64_t xs, int64_t xe, int64_t ys, int64_t ye) +{ + if((xe - xs < rr) || (ye - ys < rr)) return -1; + return ((xe - xs - rr + 1) + (ye - ys - rr + 1))/rr; +} + +#define extz_xs(z) ((z).ts) +#define extz_xe(z) ((z).te) +#define extz_ys(z) ((z).ps) +#define extz_ye(z) ((z).pe) +#define extz_xf(z) ((z).tl) +#define extz_yf(z) ((z).pl) + +void push_bit_extz0(int64_t qid, int64_t tid, bit_extz_t *des, bit_extz_t *src, int64_t xk1, int64_t yk1, int64_t ck1, int64_t xk2, int64_t yk2/**, int64_t dbg**/) +{ + int64_t xk = xk1, yk = yk1, ck = ck1, op = -1, ol = -1; + int64_t xk0, yk0; + if(des->cigar.n) { + xk0 = extz_xe(*des) + 1; yk0 = extz_ye(*des) + 1; + } else { + xk0 = extz_xs(*des); yk0 = extz_ys(*des); + } + // if(dbg) { + // fprintf(stderr, "******[M::%s] xk0::%ld, yk0::%ld, xk1::%ld, yk1::%ld, ck1::%ld, xk2::%ld, yk2::%ld\n", __func__, xk0 + 1, yk0 + 1, xk1 + 1, yk1 + 1, ck1, xk2 + 1, yk2 + 1); + // } + + while ((ck > 0) && ((xk > xk0) || (yk > yk0))) { + --ck; + op = src->cigar.a[ck]>>14; + ol = src->cigar.a[ck]&(0x3fff); + if(op!=2) xk -= ol; + if(op!=3) yk -= ol; + } + // if(dbg) { + // fprintf(stderr, "[M::%s] xk::%ld, yk::%ld, ck::%ld\n", __func__, xk + 1, yk + 1, ck); + // } + + // fprintf(stderr, "[M::%s] ck::%ld, xk0::%ld, yk0::%ld, xk::%ld, yk::%ld\n", __func__, ck, xk0 + 1, yk0 + 1, xk + 1, yk + 1); + assert(ck >= 0); + if((xk == xk0) && (yk == yk0)) { + for (; ck + 1 < ck1; ck++) { + op = src->cigar.a[ck]>>14; ol = src->cigar.a[ck]&(0x3fff); + push_trace_iter(&(des->cigar), op, ol); + if(op) des->err += ol; + } + } else { + // if(!((xk < xk0) && (yk < yk0) && (op == 0) && (ol > 0))) { + // fprintf(stderr, "\nqid::%ld\t%.*s\ttid::%ld\t%.*s\n", qid, (int)Get_NAME_LENGTH(R_INF, qid), Get_NAME(R_INF, qid), tid, (int)Get_NAME_LENGTH(R_INF, tid), Get_NAME(R_INF, tid)); + // fprintf(stderr, "[M::%s] ck1::%ld, ck::%ld, xk0::%ld, yk0::%ld, xk::%ld, yk::%ld, op::%ld, ol::%ld\n", __func__, ck1, ck, xk0 + 1, yk0 + 1, xk + 1, yk + 1, op, ol); + // fprintf(stderr, "[M::%s] xk1::%ld, yk1::%ld, xk2::%ld, yk2::%ld\n", __func__, xk1 + 1, yk1 + 1, xk2 + 1, yk2 + 1); + // } + assert((xk < xk0) && (yk < yk0) && (op == 0) && (ol > 0)); + assert((xk + ol - xk0) == (yk + ol - yk0)); + push_trace_iter(&(des->cigar), op, (xk + ol - xk0)); + if(op) des->err += (xk + ol - xk0); + for (ck++; ck + 1 < ck1; ck++) { + op = src->cigar.a[ck]>>14; ol = src->cigar.a[ck]&(0x3fff); + push_trace_iter(&(des->cigar), op, ol); + if(op) des->err += ol; + } + } + // if(dbg) { + // fprintf(stderr, "[M::%s] ck::%ld\n", __func__, ck); + // } + + if(ck < ck1) { + if(xk1 == xk2 && yk1 == yk2) { + op = src->cigar.a[ck]>>14; ol = src->cigar.a[ck]&(0x3fff); + push_trace_iter(&(des->cigar), op, ol); + if(op) des->err += ol; + } else { + assert((src->cigar.a[ck]>>14) == 0); + op = src->cigar.a[ck]>>14; ol = ((src->cigar.a[ck]&(0x3fff)) - (xk1 - xk2)); + push_trace_iter(&(des->cigar), op, ol); + if(op) des->err += ol; + } + } + // assert((ck >= 0) && (xk == xk0) && (yk == yk0)); + + extz_xe(*des) = xk2 - 1; extz_ye(*des) = yk2 - 1; +} + +void move_flat_hpc_cc(bit_extz_t *ez, bit_extz_t *tmp_in, bit_extz_t *tmp_ou, uint8_t trim_left, uint8_t trim_right, char *qstr, char *tstr) +{ + if(ez->err == INT32_MAX) return; + int64_t tre = 0, ck, cn = ez->cigar.n; uint16_t op, mm; + for (ck = mm = 0; ck < cn; ck++) { + op = ez->cigar.a[ck]>>14; + if(op < 2) {mm = 1;} + else if(mm) {break;} + } + if(ck >= cn) return; + + tmp_ou->ps = ez->ps; tmp_ou->pe = ez->pe; tmp_ou->pl = ez->pl; + tmp_ou->ts = ez->ts; tmp_ou->te = ez->te; tmp_ou->tl = ez->tl; + tmp_ou->err = ez->err; tmp_ou->thre = ez->thre; + + kv_resize(uint16_t, tmp_in->cigar, (tmp_in->cigar.n + ez->cigar.n)); + tmp_ou->cigar.a = tmp_in->cigar.a + tmp_in->cigar.n; + tmp_ou->cigar.n = tmp_ou->cigar.m = ez->cigar.n; + memcpy(tmp_ou->cigar.a, ez->cigar.a, ez->cigar.n*sizeof(*(ez->cigar.a))); + + tre = 0; + move_wins_adv0(tmp_ou, qstr, tstr, NULL, -1, -1, NULL, trim_left, trim_right, ez, &tre); + assert(tre == 0); + ez->err -= tre; +} + +///note: [bit_extz_t.ts, bit_extz_t.te] but [ul_ov_t.ts, ul_ov_t.te) and [bit_extz_t.ts, extz_xf(z)) +inline int64_t flat_hpc_cc(int64_t qid, int64_t tid, char *qstr, int64_t qlen, char *tstr, int64_t tlen, double e_rate, bit_extz_t *rs, bit_extz_t *ez, bit_extz_t *exz, ul_ov_t *hpc, uint8_t* xhpf, int64_t xk0, int64_t yk0, int64_t ck0, int64_t le, int64_t re, int64_t *xk1, int64_t *yk1, int64_t *ck1, uint8_t *rr_end, int64_t max_recal/**, uint8_t dbg**/) +{ + ///rxk, ryk, and rck are the (rs) results within (ez) + int64_t rxf, ryf, op, ol, wx[2], wy[2], wc[2], xk, yk, ck, ff = 0, ffx, ffy, ffc, ffx2, ffy2, xrl, yrl; bit_extz_t tmp_ou; memset(&tmp_ou, 0, sizeof(tmp_ou)); + int64_t xs = hpc->qs, xe = hpc->qe, ys = hpc->ts, ye = hpc->te, fz[2], cn = ez->cigar.n, clk, xlk, ylk, crk, xrk, yrk, axk[2], ayk[2], lef_glob, rht_glob, lef_xs = -1, lef_ys = -1; + int64_t rht_xe = -1, rht_ye = -1, rht_ck = 1; + + if(rs->cigar.n) { + rxf = extz_xe(*rs) + 1; ryf = extz_ye(*rs) + 1; + } else { + rxf = extz_xs(*rs); ryf = extz_ys(*rs); + } + + if((xs >= xe) || (ys >= ye)) return 0; + if((xs < rxf) || (ys < ryf)) return 0;///conflict with existing one + xk = xk0; yk = yk0; ck = ck0; wx[0] = wx[1] = wy[0] = wy[1] = wc[0] = wc[1] = -1; lef_glob = rht_glob = -1; + clk = xlk = ylk = crk = xrk = yrk = axk[0] = axk[1] = ayk[0] = ayk[1] = -1; fz[0] = fz[1] = 0; + xrl = xe - xs; yrl = ye - ys; + + if(ck < 0) { + ck = 0; xk = extz_xs(*ez); yk = extz_ys(*ez); + } + + ///scan in ez + while ((ck < cn) && ((xk < xs) || (yk < ys) || (xk < rxf) || (yk < ryf))) { + op = ez->cigar.a[ck]>>14; + ol = ez->cigar.a[ck]&(0x3fff); + if(op!=2) xk += ol; + if(op!=3) yk += ol; + ++ck; + } + + if(ck > cn) { + ck = cn; xk = extz_xe(*ez) + 1; yk = extz_ye(*ez) + 1; + } + + if((xk < xs) || (yk < ys) || (xk < rxf) || (yk < ryf)) return 0; + + // if(dbg) { + // fprintf(stderr, "\n[M::%s] xs::%ld, xe::%ld, ys::%ld, ye::%ld, rxk::%ld, ryk::%ld\n", __func__, xs + 1, xe + 1, ys + 1, ye + 1, rxf + 1, ryf + 1); + // fprintf(stderr, "[M::%s] xk::%ld, yk::%ld, ck::%ld, rs_cn::%ld\n", __func__, xk + 1, yk + 1, ck, (int64_t)rs->cigar.n); + + // fprintf(stderr, "-1-[M::%s]\n", __func__); + // } + + ///[rxk, xk0) & [ryk, yk0): go through ez + ///[-, rxk) & [-, ryk): go through rs + ///do not need to consider extz_xf(*rs) and extz_yf(*rs) here as extz_xf(*rs) <= rxk and extz_yf(*rs) <= ryk + while ((ck > 0) && (xk >= rxf) && (yk >= ryf)) { + wx[1] = xk; wy[1] = yk; wc[1] = ck; + --ck; + op = ez->cigar.a[ck]>>14; + ol = ez->cigar.a[ck]&(0x3fff); + if(op!=2) xk -= ol; + if(op!=3) yk -= ol; + wx[0] = xk; wy[0] = yk; wc[0] = ck; + // if(tid == 46195) fprintf(stderr, "+[M::%s] xk::%ld, yk::%ld, ck::%ld, op::%ld, ol::%ld\n", __func__, xk + 1, yk + 1, ck, op, ol); + // if(tid == 46195) fprintf(stderr, "+[M::%s]\twx::[%ld,\t%ld)\twy::[%ld,\t%ld)\n", __func__, wx[0] + 1, wx[1] + 1, wy[0] + 1, wy[1] + 1); + + ////fully covered by an exact match + if((op == 0) && (xrl == yrl) && (hpc->qe == hpc->qn) && (hpc->te == hpc->tn) && (wx[0] <= xs) && (wx[1] >= xe) && (wy[0] <= ys) && (wy[1] >= ye)) { + push_bit_extz0(qid, tid, rs, ez, wx[1], wy[1], wc[1], xe, ye/**, dbg**/); fz[0] = 1; + // if(dbg) prt_cigar_smp(rs->cigar.a, rs->cigar.n); + (*xk1) = wx[1]; (*yk1) = wy[1]; (*ck1) = wc[1]; + + return 1; + } + + if(op) { + if((wx[0] == rxf) && (wy[0] == ryf)) { + ///we allow the (wx[0] == xs || wy[0] == ys) + ///as this is the direct sucessor of the previous pushed cigar + if((wx[0] <= xs) && (wy[0] <= ys)) { + clk = ck; xlk = xk; ylk = yk; lef_glob = 1; + axk[0] = xk; ayk[0] = yk; + if((ck == 0) && (le)) lef_glob = 0; + fz[0] = 3; + break; + } + } + continue; + } + + ///we only allow: + ///1. (wx[0] >= rxf && wx[1] >= rxf) and (wy[0] >= ryf && wy[1] >= ryf) + ///2. (wx[0] < rxf && wx[1] > rxf) and (wx[0] < ryf && wx[1] > ryf) + if((wx[0] < rxf) || (wy[0] < ryf)) { + if((wx[0] >= rxf) || (wy[0] >= ryf)) break;///cannot be smaller than wx[0], wy[0] + if((wx[1] <= rxf) || (wy[1] <= ryf)) break;///must be at least 1bp match after rxf, ryf + } + // fprintf(stderr, "-[M::%s] xk::%ld, yk::%ld, ck::%ld, op::%ld, ol::%ld\n", __func__, xk + 1, yk + 1, ck, op, ol); + + ///do not use (wx[0] <= xs) && (wy[0] <= ys) + ///as we want to at least 1bp match as seed + if((wx[0] < xs) && (wy[0] < ys)) { + clk = ck; xlk = xk; ylk = yk; lef_glob = 1; + axk[0] = MIN(wx[1], xs); ayk[0] = MIN(wy[1], ys); + + ol = axk[0] - xlk; + if(ol > (ayk[0] - ylk)) ol = ayk[0] - ylk; + + axk[0] = xlk + ol; ayk[0] = ylk + ol; + + fz[0] = 2; + + ///we only allow: + ///1. (wx[0] >= rxf && wx[1] >= rxf) and (wy[0] >= ryf && wy[1] >= ryf) + ///2. (wx[0] < rxf && wx[1] >= rxf0) and (wx[0] < rxf && wx[1] >= rxf0) + // if(wx[0] < rxf && wx[1] >= rxf) { + // assert((wx[1] - rxf) == (wy[1] - ryf)); + // ffm = wx[1] - wx[0]; + // } + break; + } + + if((wx[0] == rxf) && (wy[0] == ryf)) { + ///we allow the (wx[0] == xs || wy[0] == ys) + ///as this is the direct sucessor of the previous pushed cigar + if((wx[0] <= xs) && (wy[0] <= ys)) { + clk = ck; xlk = xk; ylk = yk; lef_glob = 1; + axk[0] = xk; ayk[0] = yk; + if((ck == 0) && (le)) lef_glob = 0; + fz[0] = 3; + break; + } + } + } + + + if((fz[0] == 0) && (rs->cigar.n == 0) && (le)) { + lef_glob = 0; fz[0] = 3; + } + + // if(dbg) { + // fprintf(stderr, "-2-[M::%s]\n", __func__); + // fprintf(stderr, "+[M::%s] xlk::%ld, ylk::%ld, clk::%ld\n", __func__, xlk + 1, ylk + 1, clk); + // fprintf(stderr, "+[M::%s] axk[0]::%ld, ayk[0]::%ld, fz[0]::%ld, lef_glob::%ld\n", __func__, axk[0] + 1, ayk[0] + 1, fz[0], lef_glob); + // } + + assert(ck >= 0); + ff = 0; ffx = ffy = ffx2 = ffy2 = ffc = -1; + if(ff == 0 && xk >= xe && yk >= ye) { + ff = 1; ffx = ffx2 = xk; ffy = ffy2 = yk; ffc = ck; + + if((ck > 0) && ((ez->cigar.a[ck-1]>>14) == 0)) { + ol = ez->cigar.a[ck-1]&(0x3fff); + wx[0] = xk - ol; wy[0] = yk - ol; + wx[1] = xk; wy[1] = yk; + + if((xe >= wx[0]) && (xe < wx[1]) && (ye >= wy[0]) && (ye < wy[1])) { + ol = wx[1] - xe; + if(ol > (wy[1] - ye)) ol = wy[1] - ye; + ffx2 = wx[1] - ol; ffy2 = wy[1] - ol; + } + } + } + while (ck < cn) { + wx[0] = xk; wy[0] = yk; wc[0] = ck; + op = ez->cigar.a[ck]>>14; + ol = ez->cigar.a[ck]&(0x3fff); + if(op!=2) xk += ol; + if(op!=3) yk += ol; + wx[1] = xk; wy[1] = yk; wc[1] = (++ck); + if(ff == 0 && xk >= xe && yk >= ye) { + ff = 1; ffx = ffx2 = xk; ffy = ffy2 = yk; ffc = ck; + if(op == 0) { + if((xe >= wx[0]) && (xe < wx[1]) && (ye >= wy[0]) && (ye < wy[1])) { + ol = wx[1] - xe; + if(ol > (wy[1] - ye)) ol = wy[1] - ye; + ffx2 = wx[1] - ol; ffy2 = wy[1] - ol; + } + } + } + // fprintf(stderr, "+[M::%s] xk::%ld, yk::%ld, ck::%ld, op::%ld, ol::%ld\n", __func__, xk + 1, yk + 1, ck, op, ol); + if(op) continue; + // fprintf(stderr, "-[M::%s] xk::%ld, yk::%ld, ck::%ld, op::%ld, ol::%ld\n", __func__, xk + 1, yk + 1, ck, op, ol); + + if((xrl == yrl) && (hpc->qe == hpc->qn) && (hpc->te == hpc->tn) && (wx[0] <= xs) && (wx[1] >= xe) && (wy[0] <= ys) && (wy[1] >= ye)) { + push_bit_extz0(qid, tid, rs, ez, wx[1], wy[1], wc[1], xe, ye/**, dbg**/); fz[1] = 1; + // if(dbg) prt_cigar_smp(rs->cigar.a, rs->cigar.n); + (*xk1) = wx[1]; (*yk1) = wy[1]; (*ck1) = wc[1]; + return 1; + } + ///at least 1bp match after xe, ye + if((wx[1] > xe) && (wy[1] > ye)) { + crk = ck; xrk = xk; yrk = yk; rht_glob = 1; + axk[1] = MAX(wx[0], xe); ayk[1] = MAX(wy[0], ye); + + + ol = xrk - axk[1]; + if(ol > (yrk - ayk[1])) ol = yrk - ayk[1]; + + axk[1] = xrk - ol; ayk[1] = yrk - ol; + + fz[1] = 2; + break; + } + } + + if(fz[1] == 0) { + if(re) { + rht_glob = 0; fz[1] = 3; + } else { + if(ff) {///no match before end + crk = ck; rht_glob = 1; + axk[1] = xrk = xk; + ayk[1] = yrk = yk; + fz[1] = 3; + } else {///hpc is outside of the whole window + ff = 1; ffx = ffx2 = xk; ffy = ffy2 = yk; ffc = ck; + } + } + } + // if((fz[1] == 0) && (re)) { + // rht_glob = 0; fz[1] = 3; + // } + + // if(dbg) { + // fprintf(stderr, "-2a-[M::%s]\n", __func__); + // } + + if((!fz[0]) || (!fz[1]) || (lef_glob < 0) || (rht_glob < 0)) { + // if(!(ffx >= 0 && ffy >= 0 && ffx2 >= 0 && ffy2 >= 0 && ffc >= 0)) { + // fprintf(stderr, "\nqid::%ld\t%.*s\n", qid, (int)Get_NAME_LENGTH(R_INF, qid), Get_NAME(R_INF, qid)); + // fprintf(stderr, "tid::%ld\t%.*s\n", tid, (int)Get_NAME_LENGTH(R_INF, tid), Get_NAME(R_INF, tid)); + // fprintf(stderr, "[M::%s] xs::%ld, xe::%ld, ys::%ld, ye::%ld, rxk::%ld, ryk::%ld\n", __func__, xs + 1, xe + 1, ys + 1, ye + 1, rxf + 1, ryf + 1); + // fprintf(stderr, "[M::%s] fz[0]::%ld, fz[1]::%ld, lef_glob::%ld, rht_glob::%ld, ffx::%ld, ffy::%ld, ffx2::%ld, ffy2::%ld, ffc::%ld\n", __func__, + // fz[0], fz[1], lef_glob, rht_glob, ffx, ffy, ffx2, ffy2, ffc); + // } + + // assert(ffx >= 0 && ffy >= 0 && ffx2 >= 0 && ffy2 >= 0 && ffc >= 0);//r829 + if(ffx < 0 || ffy < 0 || ffx2 < 0 || ffy2 < 0 || ffc < 0) {//r829 + ///qid::30572 474a40fe-c569-44a2-97a2-e83344eaf8fd tid::30573 0a1a9fa4-9c4a-4079-86c3-fc2a1a29bf5a + // fprintf(stderr, "\nqid::%ld\t%.*s\ttid::%ld\t%.*s\n", qid, (int)Get_NAME_LENGTH(R_INF, qid), Get_NAME(R_INF, qid), tid, (int)Get_NAME_LENGTH(R_INF, tid), Get_NAME(R_INF, tid)); + // exit(1); + + ffc = ez->cigar.n; + ffx = ffx2 = extz_xe((*ez)) + 1; + ffy = ffy2 = extz_ye((*ez)) + 1; + + // extz_xs(*rs) = extz_xe(*rs) = extz_xf(*rs) = extz_xs(*ez); + // extz_ys(*rs) = extz_ye(*rs) = extz_yf(*rs) = extz_ys(*ez); + // rs->cigar.n = 0; rs->err = 0; + } + push_bit_extz0(qid, tid, rs, ez, ffx, ffy, ffc, ffx2, ffy2/**, dbg**/); + // if(dbg) prt_cigar_smp(rs->cigar.a, rs->cigar.n); + (*xk1) = ffx; (*yk1) = ffy; (*ck1) = ffc; + return 0; + } + + // if(dbg) { + // fprintf(stderr, "-3-[M::%s]\tfz[0]::%ld\tfz[1]::%ld\n", __func__, fz[0], fz[1]); + // fprintf(stderr, "+[M::%s] xrk::%ld, yrk::%ld, crk::%ld\n", __func__, xrk + 1, yrk + 1, crk); + // fprintf(stderr, "+[M::%s] axk[1]::%ld, ayk[1]::%ld, fz[1]::%ld, rht_glob::%ld\n", __func__, axk[1] + 1, ayk[1] + 1, fz[1], rht_glob); + // } + + if(lef_glob == 0) { + xlk = axk[0] = extz_xs(*ez); + ylk = ayk[0] = extz_ys(*ez); + clk = 0; + } + if(rht_glob == 0) { + xrk = axk[1] = extz_xe(*ez) + 1; + yrk = ayk[1] = extz_ye(*ez) + 1; + crk = ez->cigar.n; + } + + // hc_aln_exz_non_retrieve_direct(qstr, tstr, axk[0], xs, ayk[0], ys, ((lef_glob)?(0):(2)), exz, qlen, tlen, e_rate, FORCE_SIN_L, FORCE_SIN_L, FORCE_SIN_L, err[0]) + // hc_aln_exz_non_retrieve_direct(qstr, tstr, xe, axk[1], ye, ayk[1], ((rht_glob)?(0):(1)), exz, qlen, tlen, e_rate, FORCE_SIN_L, FORCE_SIN_L, FORCE_SIN_L, err[1]) + if(((xs - axk[0]) > max_recal) || ((ys - ayk[0]) > max_recal) || ((axk[1] - xe) > max_recal) || ((ayk[1] - ye) > max_recal)) return 0;///too long + + for (xk = axk[0]; (xk < xs) && (!xhpf[xk]); xk++); + if(xk < xs) return 0; + for (xk = xe; (xk < axk[1]) && (!xhpf[xk]); xk++); + if(xk < axk[1]) return 0; + + + + + + + + int64_t tot_e = 0, err[2], tot_n = 0; uint64_t cn0; err[0] = err[1] = 0; + + cn = crk; ck = clk; xk = xlk; yk = ylk; + for (; ck < cn; ck++) { + wx[0] = xk; wy[0] = yk; + op = ez->cigar.a[ck]>>14; + ol = ez->cigar.a[ck]&(0x3fff); + if(op!=2) xk += ol; + if(op!=3) yk += ol; + wx[1] = xk; wy[1] = yk; + if(op == 0) continue; + tot_e += ol; + + // /**if((tid == 46192) && (hpc->qs == 18575) && (hpc->qe == 18580) && (hpc->ts == 9614) && (hpc->te == 9618))**/ { + // fprintf(stderr, "-2a-[M::%s]\twx::[%ld,\t%ld)\twy::[%ld,\t%ld)\top::%ld\tol::%ld\tck::%ld\ttot_e::%ld\n", __func__, wx[0], wx[1], wy[0], wy[1], op, ol, ck, tot_e); + // } + + if((xk <= xs) && (yk <= ys)) err[0] += ol; + if((xk >= xe) && (yk >= ye)) err[1] += ol; + } + assert(xrk == xk); + assert(yrk == yk); + + // if(tid == 21134) fprintf(stderr, "-3a-[M::%s] tot_n::%ld, tot_e::%ld\n", __func__, tot_n, tot_e); + + // if(tid == 21073) { + // fprintf(stderr, "\n[M::%s] xs::%ld, xe::%ld, ys::%ld, ye::%ld, rxk::%ld, ryk::%ld\n", __func__, xs + 1, xe + 1, ys + 1, ye + 1, rxf + 1, ryf + 1); + // fprintf(stderr, "[M::%s] xk::%ld, yk::%ld, ck::%ld, rs_cn::%ld\n", __func__, xk + 1, yk + 1, ck, (int64_t)rs->cigar.n); + + // fprintf(stderr, "-1-[M::%s]\n", __func__); + // } + + int64_t xos, xoe, yos, yoe; + tot_n = 0; cn0 = rs->cigar.n; + + xoe = hpc->qn; yoe = hpc->tn; + xrl = xoe - xs; yrl = yoe - ys; + ol = MIN(xrl, yrl); + xos = xoe - ol; yos = yoe - ol; + + xrl = xos - xs; yrl = yos - ys; assert(xrl == 0 || yrl == 0); + tot_n += MAX(xrl, yrl); + + xrl = xe - xoe; yrl = ye - yoe; + // if(!(xrl == 0 || yrl == 0)) { + // fprintf(stderr, "\nqid::%ld\t%.*s\n", qid, (int)Get_NAME_LENGTH(R_INF, qid), Get_NAME(R_INF, qid)); + // fprintf(stderr, "tid::%ld\t%.*s\n", tid, (int)Get_NAME_LENGTH(R_INF, tid), Get_NAME(R_INF, tid)); + // fprintf(stderr, "[M::%s] xs::%ld, xe::%ld, ys::%ld, ye::%ld, rxk::%ld, ryk::%ld\n", __func__, xs + 1, xe + 1, ys + 1, ye + 1, rxf + 1, ryf + 1); + // int64_t ssk; + // fprintf(stderr, "qstr::"); + // for (ssk = xs; ssk < xe; ssk++) fprintf(stderr, "%c", qstr[ssk]); + // fprintf(stderr, "\n"); + // fprintf(stderr, "tstr::"); + // for (ssk = ys; ssk < ye; ssk++) fprintf(stderr, "%c", tstr[ssk]); + // fprintf(stderr, "\n"); + + // } + assert(xrl == 0 || yrl == 0); + tot_n += MAX(xrl, yrl); + + + assert((xlk <= axk[0]) && (ylk <= ayk[0])); + assert((xrk >= axk[1]) && (yrk >= ayk[1])); + + // if(dbg) { + // fprintf(stderr, "-3b-[M::%s] tot_n::%ld, tot_e::%ld\n", __func__, tot_n, tot_e); + // } + + // if((hpc->qs == 1116) && (hpc->qe == 1120) && (hpc->ts == 14080) && (hpc->te == 14083)) { + // fprintf(stderr, "-a-[M::%s::sw]\tq::[%ld,\t%ld)\tt::[%ld,\t%ld)\n", __func__, xlk + 1, xrk + 1, ylk + 1, yrk + 1); + // fprintf(stderr, "-a-[M::%s::si]\tq::[%ld,\t%ld)\tt::[%ld,\t%ld)\n", __func__, axk[0] + 1, axk[1] + 1, ayk[0] + 1, ayk[1] + 1); + // } + int64_t os, oe, ovlp_x, ovlp_y; + if((tot_n <= tot_e) && (lef_glob == 1)) {///push anything within [rxf, axk[0]) && [ryf, ayk[0]) + ck = clk; xk = xlk; yk = ylk; cn = ez->cigar.n; + while ((ck > 0) && (xk >= rxf) && (yk >= ryf)) { + wx[1] = xk; wy[1] = yk; wc[1] = ck; + --ck; + op = ez->cigar.a[ck]>>14; + ol = ez->cigar.a[ck]&(0x3fff); + if(op!=2) xk -= ol; + if(op!=3) yk -= ol; + wx[0] = xk; wy[0] = yk; wc[0] = ck; + } + + + wx[0] = xk; wy[0] = yk; + while ((ck < cn) && ((wx[0] < axk[0]) || (wy[0] < ayk[0]))) { + wx[0] = xk; wy[0] = yk; + op = ez->cigar.a[ck]>>14; + ol = ez->cigar.a[ck]&(0x3fff); + if(op!=2) xk += ol; + if(op!=3) yk += ol; + ck++; + wx[1] = xk; wy[1] = yk; + + if((wx[0] > axk[0]) || (wy[0] > ayk[0])) continue; + + ///[rxf, axk[0]) && [ryf, ayk[0]) + os = MAX(rxf, wx[0]); oe = MIN(axk[0], wx[1]); + ovlp_x = ((oe>os)? (oe-os):0); + + os = MAX(ryf, wy[0]); oe = MIN(ayk[0], wy[1]); + ovlp_y = ((oe>os)? (oe-os):0); + + if(ovlp_x <= 0 && ovlp_y <= 0) continue; + + + // if(dbg) { + // fprintf(stderr, "-3a-[M::%s]\twx::[%ld,\t%ld)\twy::[%ld,\t%ld)\top::%ld\tol::%ld\tck::%ld\n", __func__, wx[0], wx[1], wy[0], wy[1], op, ol, ck); + // fprintf(stderr, "-3a-[M::%s]\trxf::%ld\tryf::%ld\taxk[0]::%ld\tayk[0]::%ld\n", __func__, rxf, ryf, axk[0], ayk[0]); + // } + + if(op > 1) { + assert(ovlp_x == ol || ovlp_y == ol); + push_trace(&(rs->cigar), op, ol); + } else if(op == 1) { + assert(ovlp_x == ol && ovlp_y == ol); + push_trace(&(rs->cigar), op, ol); + } else { + // if(ovlp_x < ol) { + // if(!(ck == clk + 1 || ck == crk)) { + // fprintf(stderr, "******[M::%s] tid::%ld, xs::%ld, xe::%ld, ys::%ld, ye::%ld, rxk::%ld, ryk::%ld, clk::%ld, crk::%ld\n", __func__, tid, xs + 1, xe + 1, ys + 1, ye + 1, rxf + 1, ryf + 1, clk, crk); + // fprintf(stderr, "-3a-[M::%s]\twx::[%ld,\t%ld)\twy::[%ld,\t%ld)\top::%ld\tol::%ld\tck::%ld\n", __func__, wx[0] + 1, wx[1] + 1, wy[0] + 1, wy[1] + 1, op, ol, ck); + // fprintf(stderr, "-3a-[M::%s]\trxf::%ld\tryf::%ld\taxk[0]::%ld\tayk[0]::%ld\n", __func__, rxf + 1, ryf + 1, axk[0] + 1, ayk[0] + 1); + // } + // assert((ck == clk + 1 || ck == crk)); + // } + assert(ovlp_x == ovlp_y); + push_trace(&(rs->cigar), op, ovlp_x); + } + } + } + + // if(dbg) fprintf(stderr, "-3c-[M::%s] tot_n::%ld, tot_e::%ld\n", __func__, tot_n, tot_e); + + ///push cigar within [axk[0], xs) && [ayk[0], ys) + if((tot_n <= tot_e) && (hc_aln_exz_non_retrieve_direct(qstr, tstr, axk[0], xs, ayk[0], ys, ((lef_glob)?(0):(2)), exz, qlen, tlen, e_rate, FORCE_SIN_L, FORCE_SIN_L, FORCE_SIN_L, err[0]))) { + // if(dbg) { + // fprintf(stderr, "-3c-0-[M::%s] exz->ts::%d, exz->te::%d, exz->ps::%d, exz->pe::%d, exz->cigar.n::%u\n", __func__, exz->ts, exz->te, exz->ps, exz->pe, (uint32_t)exz->cigar.n); + // } + move_flat_hpc_cc(exz, rs, &tmp_ou, ((lef_glob)?(0):(1)), 0, qstr, tstr); + tot_n += exz->err; + lef_xs = extz_xs(*exz); + lef_ys = extz_ys(*exz); + + cn = rs->cigar.n; rs->cigar.n += exz->cigar.n; + kv_resize(uint16_t, rs->cigar, rs->cigar.n); + memcpy(rs->cigar.a+cn, exz->cigar.a, exz->cigar.n*sizeof(*(rs->cigar.a))); + } else { + tot_n = INT64_MAX; + } + + // if(dbg) fprintf(stderr, "-3d-[M::%s] tot_n::%ld, tot_e::%ld\n", __func__, tot_n, tot_e); + + + ///push cigar within [xs, xe) and [ys, ye) + assert(xoe > xos); + assert(yoe > yos); + assert((xoe - xos) == (yoe - yos)); + + if(tot_n <= tot_e) { + xrl = xos - xs; yrl = yos - ys; + assert(xrl == 0 || yrl == 0); + if(xrl) { + push_trace(&(rs->cigar), 3, xrl); + } else if(yrl) { + push_trace(&(rs->cigar), 2, yrl); + } + + ///xoe - xos == yoe - yos + push_trace(&(rs->cigar), 0, xoe - xos); + + xrl = xe - xoe; yrl = ye - yoe; + assert(xrl == 0 || yrl == 0); + if(xrl) { + push_trace(&(rs->cigar), 3, xrl); + } else if(yrl) { + push_trace(&(rs->cigar), 2, yrl); + } + } + + // if(dbg) fprintf(stderr, "-3e-[M::%s] tot_n::%ld, tot_e::%ld\n", __func__, tot_n, tot_e); + + ///need to update rs.qs/qe/ts/te + ///push cigar within [xe, axk[1]) and [ye, ayk[1]) + if((tot_n <= tot_e) && (hc_aln_exz_non_retrieve_direct(qstr, tstr, xe, axk[1], ye, ayk[1], ((rht_glob)?(0):(1)), exz, qlen, tlen, e_rate, FORCE_SIN_L, FORCE_SIN_L, FORCE_SIN_L, err[1]))) { + move_flat_hpc_cc(exz, rs, &tmp_ou, 0, ((rht_glob)?(0):(1)), qstr, tstr); + tot_n += exz->err; + rht_xe = xrk; + rht_ye = yrk; + rht_ck = crk; + + cn = rs->cigar.n; rs->cigar.n += exz->cigar.n; + kv_resize(uint16_t, rs->cigar, rs->cigar.n); + memcpy(rs->cigar.a+cn, exz->cigar.a, exz->cigar.n*sizeof(*(rs->cigar.a))); + } else { + tot_n = INT64_MAX; + } + + // if(dbg) fprintf(stderr, "-3f-[M::%s] tot_n::%ld, tot_e::%ld\n", __func__, tot_n, tot_e); + + ///no cigar need to be pushed within [axk[1], xrk) and [ye, ayk[1]) + if((tot_n <= tot_e) && ((xrk > axk[1]) || (yrk > ayk[1]))) { + assert((xrk - axk[1]) == (yrk - ayk[1])); + assert((crk > 0) && ((ez->cigar.a[crk - 1]>>14) == 0)); + // push_trace(&(rs->cigar), 0, xrk - axk[1]); + assert(rht_glob == 1); + } + + // if(dbg) fprintf(stderr, "-4-[M::%s] tot_n::%ld, tot_e::%ld\n", __func__, tot_n, tot_e); + + + if((tot_n == INT64_MAX) || (tot_n > tot_e)) { + rs->cigar.n = cn0; + // if(dbg) fprintf(stderr, "-5-[M::%s]\n", __func__); + return 0; + } else { + // if(dbg) fprintf(stderr, "-6-[M::%s]\n", __func__); + ///debug + // fprintf(stderr, "-l-\thrr::%lu\tx::[%u, %u)\ty::[%u, %u)\tmmx::%u\tmmy::%u\n", fl, zl.qs + 1, zl.qe + 1, zl.ts + 1, zl.te + 1, zl.qn + 1, zl.tn + 1); + /** + if(dbg) { + fprintf(stderr, "\ntid::%ld\t%.*s\n", tid, (int)Get_NAME_LENGTH(R_INF, tid), Get_NAME(R_INF, tid)); + fprintf(stderr, "-z-[M::%s::hpc]\tq::[%u,\t%u)\tt::[%u,\t%u)\ttot_e::%ld\ttot_n::%ld\n", __func__, hpc->qs + 1, hpc->qe + 1, hpc->ts + 1, hpc->te + 1, tot_e, tot_n); + fprintf(stderr, "-0-x::[%ld,\t%ld)\ty::[%ld,\t%ld)\tcc::", axk[0] + 1, axk[1] + 1, ayk[0] + 1, ayk[1] + 1); + + cn = crk; ck = clk; xk = xlk; yk = ylk; + for (; ck < cn; ck++) { + wx[0] = xk; wy[0] = yk; + ffx = xk; ffy = yk; + op = ez->cigar.a[ck]>>14; + ol = ez->cigar.a[ck]&(0x3fff); + if(op!=2) xk += ol; + if(op!=3) yk += ol; + wx[1] = xk; wy[1] = yk; + + os = MAX(axk[0], wx[0]); oe = MIN(axk[1], wx[1]); + ovlp_x = ((oe>os)? (oe-os):0); + + os = MAX(ayk[0], wy[0]); oe = MIN(ayk[1], wy[1]); + ovlp_y = ((oe>os)? (oe-os):0); + + if(ovlp_x == 0 && ovlp_y == 0) continue; + + if(op == 0) ol = ovlp_x; + + fprintf(stderr, "%ld%c", ol, "MSID"[op]); + } + fprintf(stderr, "\n"); + + int64_t dbg_xk[2], dbg_yk[2]; + + dbg_xk[0] = lef_glob?(axk[0]+1):(lef_xs+1); + dbg_xk[1] = rht_glob?(axk[1]+1):(extz_xe(*exz)+1+1); + + dbg_yk[0] = lef_glob?(ayk[0]+1):(lef_ys+1); + dbg_yk[1] = rht_glob?(ayk[1]+1):(extz_ye(*exz)+1+1); + + + fprintf(stderr, "-1-lef_glob::%ld\trht_glob::%ld\tx::[%ld,\t%ld)\ty::[%ld,\t%ld)\tcc::", lef_glob, rht_glob, dbg_xk[0], dbg_xk[1], dbg_yk[0], dbg_yk[1]); + cn = rs->cigar.n; xk = ((lef_glob)?(rxf):(lef_xs)); yk = lef_glob?(ryf):(lef_ys); + dbg_xk[0]--; dbg_xk[1]--; dbg_yk[0]--; dbg_yk[1]--; + for (ck = cn0; ck < cn; ck++) { + wx[0] = xk; wy[0] = yk; + op = rs->cigar.a[ck]>>14; + ol = rs->cigar.a[ck]&(0x3fff); + if(op!=2) xk += ol; + if(op!=3) yk += ol; + wx[1] = xk; wy[1] = yk; + + os = MAX(dbg_xk[0], wx[0]); oe = MIN(dbg_xk[1], wx[1]); + ovlp_x = ((oe>os)? (oe-os):0); + + os = MAX(dbg_yk[0], wy[0]); oe = MIN(dbg_yk[1], wy[1]); + ovlp_y = ((oe>os)? (oe-os):0); + + if(ovlp_x == 0 && ovlp_y == 0) continue; + + if(op == 0) ol = ovlp_x; + + fprintf(stderr, "%ld%c", ol, "MSID"[op]); + } + fprintf(stderr, "\n"); + + // xk = ((lef_glob)?(rxf):(lef_xs)); yk = lef_glob?(ryf):(lef_ys); + // for (ck = cn0; ck < cn; ck++) { + // wx[0] = xk; wy[0] = yk; + // op = rs->cigar.a[ck]>>14; + // ol = rs->cigar.a[ck]&(0x3fff); + // if(op!=2) xk += ol; + // if(op!=3) yk += ol; + // wx[1] = xk; wy[1] = yk; + + // os = MAX(dbg_xk[0], wx[0]); oe = MIN(dbg_xk[1], wx[1]); + // ovlp_x = ((oe>os)? (oe-os):0); + + // os = MAX(dbg_yk[0], wy[0]); oe = MIN(dbg_yk[1], wy[1]); + // ovlp_y = ((oe>os)? (oe-os):0); + + // fprintf(stderr, "###wx[0]::%ld, wx[1]::%ld, wy[0]::%ld, wy[1]::%ld, ck::%ld, cn0::%ld, cn::%ld\n", wx[0] + 1, wx[1] + 1, wy[0] + 1, wy[1] + 1, ck, cn0, cn); + // fprintf(stderr, "%ld%c(%u), ovlp_x::%ld, ovlp_y::%ld,\n", ol, "MSID"[op], rs->cigar.a[ck]&(0x3fff), ovlp_x, ovlp_y); + + + // if(ovlp_x == 0 && ovlp_y == 0) continue; + + // if(op == 0) ol = ovlp_x; + // } + } + **/ + + + + + + + cn = rs->cigar.n; rs->cigar.n = cn0; + for (ck = cn0; ck < cn; ck++) { + op = rs->cigar.a[ck]>>14; + ol = rs->cigar.a[ck]&(0x3fff); + push_trace_iter(&(rs->cigar), op, ol); + if(op) rs->err += ol; + } + (*xk1) = rht_xe; (*yk1) = rht_ye; (*ck1) = rht_ck; + // extz_xe(*rs) = wx[1] - 1; extz_ye(*rs) = wy[1] - 1; + + ///we only need to update extz_xs(*rs), extz_ys(*rs) when lglb = 0; update extz_xe(*rs), extz_ye(*rs) when rglb = 0; + ///so no need to worry these updated number will conflict with previous or after windows; just update it in anyway + if(lef_glob == 0) { + extz_xs(*rs) = lef_xs; extz_ys(*rs) = lef_ys; + } + + if(rht_glob == 0) { + extz_xe(*rs) = extz_xe(*exz); extz_ye(*rs) = extz_ye(*exz); (*rr_end) = 1; + } else { + extz_xe(*rs) = axk[1] - 1; extz_ye(*rs) = ayk[1] - 1; + } + + + // if(dbg) prt_cigar_smp(rs->cigar.a, rs->cigar.n); + + return 1; + } +} + +///note: [bit_extz_t.ts, bit_extz_t.te] but [ul_ov_t.ts, ul_ov_t.te) and [bit_extz_t.ts, extz_xf(z)) +inline int64_t flat_hpc_cc_back(int64_t qid, int64_t tid, char *qstr, int64_t qlen, char *tstr, int64_t tlen, double e_rate, bit_extz_t *rs, bit_extz_t *ez, bit_extz_t *exz, ul_ov_t *hpc, uint8_t* xhpf, int64_t xk0, int64_t yk0, int64_t ck0, int64_t le, int64_t re, int64_t *xk1, int64_t *yk1, int64_t *ck1) +{ + ///rxk, ryk, and rck are the (rs) results within (ez) + int64_t rxk = extz_xe(*rs) + 1, ryk = extz_ye(*rs) + 1, op, ol, wx[2], wy[2], wc[2], xk, yk, ck, ff = 0, ffx, ffy, ffc, xrl, yrl; + int64_t xs = hpc->qs, xe = hpc->qe, ys = hpc->ts, ye = hpc->te, fz[2], cn = ez->cigar.n, clk, xlk, ylk, crk, xrk, yrk, axk[2], ayk[2], lef_glob, rht_glob, lef_xs = -1, lef_ys = -1; + if((xs >= xe) || (ys >= ye)) return 0; + if((xs < rxk) || (ys < ryk)) return 0;///conflict with existing one + xk = xk0; yk = yk0; ck = ck0; wx[0] = wx[1] = wy[0] = wy[1] = wc[0] = wc[1] = -1; lef_glob = rht_glob = -1; + clk = xlk = ylk = crk = xrk = yrk = axk[0] = axk[1] = ayk[0] = ayk[1] = -1; fz[0] = fz[1] = 0; + xrl = xe - xs; yrl = ye - ys; + + if(ck < 0) { + ck = 0; xk = extz_xs(*ez); yk = extz_ys(*ez); + } + + ///scan in ez + while ((ck < cn) && ((xk < xs) || (yk < ys) || (xk < rxk) || (yk < ryk))) { + op = ez->cigar.a[ck]>>14; + ol = ez->cigar.a[ck]&(0x3fff); + if(op!=2) xk += ol; + if(op!=3) yk += ol; + ++ck; + } + + if(ck > cn) { + ck = cn; xk = extz_xe(*ez) + 1; yk = extz_ye(*ez) + 1; + } + + // if(tid == 21080) { + // fprintf(stderr, "\n[M::%s] xs::%ld, xe::%ld, ys::%ld, ye::%ld, rxk::%ld, ryk::%ld\n", __func__, xs + 1, xe + 1, ys + 1, ye + 1, rxk + 1, ryk + 1); + // fprintf(stderr, "[M::%s] xk::%ld, yk::%ld, ck::%ld\n", __func__, xk + 1, yk + 1, ck); + + // fprintf(stderr, "-1-[M::%s]\n", __func__); + // } + + ///[rxk, xk0) & [ryk, yk0): go through ez + ///[-, rxk) & [-, ryk): go through rs + ///do not need to consider extz_xf(*rs) and extz_yf(*rs) here as extz_xf(*rs) <= rxk and extz_yf(*rs) <= ryk + while ((ck > 0) && (xk >= rxk) && (yk >= ryk)) { + wx[1] = xk; wy[1] = yk; wc[1] = ck; + --ck; + op = ez->cigar.a[ck]>>14; + ol = ez->cigar.a[ck]&(0x3fff); + if(op!=2) xk -= ol; + if(op!=3) yk -= ol; + wx[0] = xk; wy[0] = yk; wc[0] = ck; + // fprintf(stderr, "+[M::%s] xk::%ld, yk::%ld, ck::%ld, op::%ld, ol::%ld\n", __func__, xk + 1, yk + 1, ck, op, ol); + if(op) continue; + if((wx[0] < rxk) || (wy[0] < ryk)) break;///cannot be smaller than wx[0], wy[0] + // fprintf(stderr, "-[M::%s] xk::%ld, yk::%ld, ck::%ld, op::%ld, ol::%ld\n", __func__, xk + 1, yk + 1, ck, op, ol); + + + if((xrl == yrl) && (hpc->qe == hpc->qn) && (hpc->te == hpc->tn) && (wx[0] <= xs) && (wx[1] >= xe) && (wy[0] <= ys) && (wy[1] >= ye)) { + push_bit_extz0(qid, tid, rs, ez, wx[1], wy[1], wc[1], wx[1], wy[1]/**, 0**/); fz[0] = 1; + (*xk1) = wx[1]; (*yk1) = wy[1]; (*ck1) = wc[1]; + return 1; + } + if((wx[0] < xs) && (wy[0] < ys)) { + clk = ck; xlk = xk; ylk = yk; lef_glob = 1; + axk[0] = MIN(wx[1], xs); ayk[0] = MIN(wy[1], ys); + + ol = axk[0] - xlk; + if(ol > (ayk[0] - ylk)) ol = ayk[0] - ylk; + + axk[0] = xlk + ol; ayk[0] = ylk + ol; + + fz[0] = 2; + break; + } + } + + if(tid == 21080) fprintf(stderr, "-2-[M::%s]\n", __func__); + + if(fz[0] == 0) { + if((xk == rxk) && (yk == ryk)) { + clk = ck; xlk = xk; ylk = yk; lef_glob = 1; + axk[0] = xk; ayk[0] = yk; + if((ck == 0) && (le)) lef_glob = 0; + fz[0] = 3; + } else if((rs->cigar.n == 0) && (le)) {/// + lef_glob = 0; fz[0] = 3; + } + } + + assert(ck >= 0); + ff = 0; ffx = ffy = ffc = -1; + if(ff == 0 && xk >= xe && yk >= ye) { + ff = 1; ffx = xk; ffy = yk; ffc = ck; + } + while (ck < cn) { + wx[0] = xk; wy[0] = yk; wc[0] = ck; + op = ez->cigar.a[ck]>>14; + ol = ez->cigar.a[ck]&(0x3fff); + if(op!=2) xk += ol; + if(op!=3) yk += ol; + wx[1] = xk; wy[1] = yk; wc[1] = (++ck); + if(ff == 0 && xk >= xe && yk >= ye) { + ff = 1; ffx = xk; ffy = yk; ffc = ck; + } + // fprintf(stderr, "+[M::%s] xk::%ld, yk::%ld, ck::%ld, op::%ld, ol::%ld\n", __func__, xk + 1, yk + 1, ck, op, ol); + if(op) continue; + // fprintf(stderr, "-[M::%s] xk::%ld, yk::%ld, ck::%ld, op::%ld, ol::%ld\n", __func__, xk + 1, yk + 1, ck, op, ol); + + if((xrl == yrl) && (hpc->qe == hpc->qn) && (hpc->te == hpc->tn) && (wx[0] <= xs) && (wx[1] >= xe) && (wy[0] <= ys) && (wy[1] >= ye)) { + push_bit_extz0(qid, tid, rs, ez, wx[1], wy[1], wc[1], wx[1], wy[1]/**, 0**/); fz[1] = 1; + (*xk1) = wx[1]; (*yk1) = wy[1]; (*ck1) = wc[1]; + return 1; + } + if((wx[1] > xe) && (wy[1] > ye)) { + crk = ck; xrk = xk; yrk = yk; rht_glob = 1; + axk[1] = MAX(wx[0], xe); ayk[1] = MAX(wy[0], ye); + + + ol = xrk - axk[1]; + if(ol > (yrk - ayk[1])) ol = yrk - ayk[1]; + + axk[1] = xrk - ol; ayk[1] = yrk - ol; + + fz[1] = 2; + break; + } + } + if((fz[1] == 0) && (re)) { + rht_glob = 0; fz[1] = 3; + } + + if(tid == 21080) fprintf(stderr, "-3-[M::%s]\tfz[0]::%ld\tfz[1]::%ld\n", __func__, fz[0], fz[1]); + + if((!fz[0]) || (!fz[1]) || (lef_glob < 0) || (rht_glob < 0)) { + push_bit_extz0(qid, tid, rs, ez, ffx, ffy, ffc, ffx, ffy/**, 0**/); + (*xk1) = ffx; (*yk1) = ffy; (*ck1) = ffc; + return 0; + } + + if(lef_glob == 0) { + xlk = axk[0] = extz_xs(*ez); + ylk = ayk[0] = extz_ys(*ez); + clk = 0; + } + if(rht_glob == 0) { + xrk = axk[1] = extz_xe(*ez) + 1; + yrk = ayk[1] = extz_ye(*ez) + 1; + crk = ez->cigar.n; + } + + int64_t tot_e = 0, err[2], tot_n = 0; uint64_t cn0; err[0] = err[1] = 0; + + cn = crk; ck = clk; xk = xlk; yk = ylk; + for (; ck < cn; ck++) { + op = ez->cigar.a[ck]>>14; + ol = ez->cigar.a[ck]&(0x3fff); + if(op!=2) xk += ol; + if(op!=3) yk += ol; + if(op) continue; + tot_e += ol; + + if((xk <= xs) && (yk <= ys)) err[0] += ol; + if((xk >= xe) && (yk >= ye)) err[1] += ol; + } + assert(xrk == xk); + assert(yrk == yk); + + int64_t xos, xoe, yos, yoe; + tot_n = 0; cn0 = rs->cigar.n; + + xoe = hpc->qn; yoe = hpc->tn; + xrl = xoe - xs; yrl = yoe - ys; + ol = MIN(xrl, yrl); + xos = xoe - ol; yos = yoe - ol; + + xrl = xos - xs; yrl = yos - ys; assert(xrl == 0 || yrl == 0); + tot_n += MAX(xrl, yrl); + xrl = xe - xoe; yrl = ye - yoe; assert(xrl == 0 || yrl == 0); + tot_n += MAX(xrl, yrl); + + + assert((xlk <= axk[0]) && (ylk <= ayk[0])); + assert((xrk >= axk[1]) && (yrk >= ayk[1])); + + // if((hpc->qs == 1116) && (hpc->qe == 1120) && (hpc->ts == 14080) && (hpc->te == 14083)) { + // fprintf(stderr, "-a-[M::%s::sw]\tq::[%ld,\t%ld)\tt::[%ld,\t%ld)\n", __func__, xlk + 1, xrk + 1, ylk + 1, yrk + 1); + // fprintf(stderr, "-a-[M::%s::si]\tq::[%ld,\t%ld)\tt::[%ld,\t%ld)\n", __func__, axk[0] + 1, axk[1] + 1, ayk[0] + 1, ayk[1] + 1); + // } + + + if((tot_n <= tot_e) && ((xlk < axk[0]) || (ylk < ayk[0]))) { + assert((axk[0] - xlk) == (ayk[0] - ylk)); + push_trace(&(rs->cigar), 0, axk[0] - xlk); + assert(lef_glob == 1); + } + + + if((tot_n <= tot_e) && (hc_aln_exz_non_retrieve_direct(qstr, tstr, axk[0], xs, ayk[0], ys, ((lef_glob)?(0):(2)), exz, qlen, tlen, e_rate, FORCE_SIN_L, FORCE_SIN_L, FORCE_SIN_L, err[0]))) { + tot_n += exz->err; + lef_xs = extz_xs(*exz); + lef_ys = extz_ys(*exz); + + cn = rs->cigar.n; rs->cigar.n += exz->cigar.n; + kv_resize(uint16_t, rs->cigar, rs->cigar.n); + memcpy(rs->cigar.a+cn, exz->cigar.a, exz->cigar.n*sizeof(*(rs->cigar.a))); + } else { + tot_n = INT64_MAX; + } + + + ///push (xs, xe] and (ys, ye] + assert(xoe > xos); + assert(yoe > yos); + assert((xoe - xos) == (yoe - yos)); + + if(tot_n <= tot_e) { + xrl = xos - xs; yrl = yos - ys; + assert(xrl == 0 || yrl == 0); + if(xrl) { + push_trace(&(rs->cigar), 3, xrl); + } else if(yrl) { + push_trace(&(rs->cigar), 2, yrl); + } + + ///xoe - xos == yoe - yos + push_trace(&(rs->cigar), 0, xoe - xos); + + xrl = xe - xoe; yrl = ye - yoe; + assert(xrl == 0 || yrl == 0); + if(xrl) { + push_trace(&(rs->cigar), 3, xrl); + } else if(yrl) { + push_trace(&(rs->cigar), 2, yrl); + } + } + + ///need to update rs.qs/qe/ts/te + + if((tot_n <= tot_e) && (hc_aln_exz_non_retrieve_direct(qstr, tstr, xe, axk[1], ye, ayk[1], ((rht_glob)?(0):(1)), exz, qlen, tlen, e_rate, FORCE_SIN_L, FORCE_SIN_L, FORCE_SIN_L, err[1]))) { + tot_n += exz->err; + + cn = rs->cigar.n; rs->cigar.n += exz->cigar.n; + kv_resize(uint16_t, rs->cigar, rs->cigar.n); + memcpy(rs->cigar.a+cn, exz->cigar.a, exz->cigar.n*sizeof(*(rs->cigar.a))); + } else { + tot_n = INT64_MAX; + } + + + if((tot_n <= tot_e) && ((xrk > axk[1]) || (yrk > ayk[1]))) { + assert((xrk - axk[1]) == (yrk - ayk[1])); + push_trace(&(rs->cigar), 0, xrk - axk[1]); + assert(rht_glob == 1); + } + + if(tid == 21080) fprintf(stderr, "-4-[M::%s]\n", __func__); + + + if((tot_n == INT64_MAX) || (tot_n > tot_e)) { + rs->cigar.n = cn0; + if(tid == 21080) fprintf(stderr, "-5-[M::%s]\n", __func__); + return 0; + } else { + if(tid == 21080) fprintf(stderr, "-6-[M::%s]\n", __func__); + ///debug + // fprintf(stderr, "-l-\thrr::%lu\tx::[%u, %u)\ty::[%u, %u)\tmmx::%u\tmmy::%u\n", fl, zl.qs + 1, zl.qe + 1, zl.ts + 1, zl.te + 1, zl.qn + 1, zl.tn + 1); + + fprintf(stderr, "-z-[M::%s::hpc]\tq::[%u,\t%u)\tt::[%u,\t%u)\n", __func__, hpc->qs + 1, hpc->qe + 1, hpc->ts + 1, hpc->te + 1); + fprintf(stderr, "-0-x::[%ld,\t%ld)\ty::[%ld,\t%ld)\tcc::", xlk + 1, xrk + 1, ylk + 1, yrk + 1); + + cn = crk; ck = clk; xk = xlk; yk = ylk; + for (; ck < cn; ck++) { + ffx = xk; ffy = yk; + op = ez->cigar.a[ck]>>14; + ol = ez->cigar.a[ck]&(0x3fff); + if(op!=2) xk += ol; + if(op!=3) yk += ol; + fprintf(stderr, "%ld%c", ol, "MSID"[op]); + } + fprintf(stderr, "\n"); + + + if(!lef_glob) { + xlk = lef_xs; ylk = lef_ys; + } + if(!rht_glob) { + xrk = extz_xe(*exz) + 1; yrk = extz_ye(*exz) + 1; + } + fprintf(stderr, "-1-x::[%ld,\t%ld)\ty::[%ld,\t%ld)\tcc::", xlk + 1, xrk + 1, ylk + 1, yrk + 1); + cn = rs->cigar.n; + for (ck = cn0; ck < cn; ck++) { + op = rs->cigar.a[ck]>>14; + ol = rs->cigar.a[ck]&(0x3fff); + fprintf(stderr, "%ld%c", ol, "MSID"[op]); + } + fprintf(stderr, "\n"); + + + + + + + cn = rs->cigar.n; rs->cigar.n = cn0; + for (ck = cn0; ck < cn; ck++) { + op = rs->cigar.a[ck]>>14; + ol = rs->cigar.a[ck]&(0x3fff); + push_trace_iter(&(rs->cigar), op, ol); + if(op) rs->err += ol; + } + (*xk1) = wx[1]; (*yk1) = wy[1]; (*ck1) = wc[1]; + // extz_xe(*rs) = wx[1] - 1; extz_ye(*rs) = wy[1] - 1; + + ///we only need to update extz_xs(*rs), extz_ys(*rs) when lglb = 0; update extz_xe(*rs), extz_ye(*rs) when rglb = 0; + ///so no need to worry these updated number will conflict with previous or after windows; just update it in anyway + if(lef_glob == 0) { + extz_xs(*rs) = lef_xs; extz_ys(*rs) = lef_ys; + } + + if(rht_glob == 0) { + extz_xe(*rs) = extz_xe(*exz); extz_ye(*rs) = extz_ye(*exz); + } else { + extz_xe(*rs) = wx[1] - 1; extz_ye(*rs) = wy[1] - 1; + } + + return 1; + } +} + +uint16_t flat_hpc_wins(overlap_region *z, uint32_t wid, overlap_region *aux, All_reads *rref, char *xstr, int64_t xlen, char *ystr, int64_t ylen, asg16_v* buf, bit_extz_t *exz, uint8_t* xhpf, int64_t hpc_rr, int64_t hpc_cutoff, int64_t *re, int64_t max_recal/**, uint8_t dbg**/) +{ + if(is_ualn_win((z->w_list.a[wid]))) { + kv_push(window_list, aux->w_list, (z->w_list.a[wid])); + return 0;///no move + } + + window_list *p = NULL; bit_extz_t ez; set_bit_extz_t(ez, (*z), wid); + kv_pushp(window_list, aux->w_list, &p); + p->x_start = ez.ts; p->x_end = ez.te; + p->y_start = ez.ps; p->y_end = ez.pe; + p->error_threshold = 0; p->error = ez.err;///single round of alignment cannot have INT16_MAX errors + p->cidx = aux->w_list.c.n; p->clen = 0; ///aux->w_list.c.n += ez.cigar.n; + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-a-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tis_match::%u\terr::%u\tez.err::%d\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // z->is_match, z->non_homopolymer_errors, ez.err); + // } + + + if(ez.err == 0) { + push_wcigar(p, &(aux->w_list), &ez); + return 0;///no move + } + + int64_t is_left_end = 0, is_right_end = 0; + if(wid == 0) is_left_end = 1; + if((wid + 1) == ((int64_t)z->w_list.n)) is_right_end = 1; + + uint64_t fl, fr; int64_t ck, cn, wx[2], wy[2], /**wc[2],**/ op, ol, xk, yk, os, oe, ox, oy, lsc, rsc; uint8_t rr_end = 0; + + bit_extz_t rs; memset(&rs, 0, sizeof(rs)); + rs.cigar.a = buf->a; rs.cigar.n = buf->n; rs.cigar.m = buf->m; rs.cigar.n = 0; + extz_xs(rs) = extz_xe(rs) = extz_xf(rs) = extz_xs(ez); + extz_ys(rs) = extz_ye(rs) = extz_yf(rs) = extz_ys(ez); + ul_ov_t zl, zr; memset(&zl, 0, sizeof(zl)); memset(&zr, 0, sizeof(zr)); + ck = 0; xk = ez.ts; yk = ez.ps; cn = ez.cigar.n; + + // if(z->y_id == 310315) { + // fprintf(stderr, "\nqid::%u\t%.*s\n", z->x_id, (int)Get_NAME_LENGTH(R_INF, z->x_id), Get_NAME(R_INF, z->x_id)); + // fprintf(stderr, "tid::%u\t%.*s\t%c\n", z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), "+-"[z->y_pos_strand]); + // fprintf(stderr, "x::[%d,%d)\ty::[%d,%d)\tez.cigar.n::%u\n", ez.ts + 1, ez.te + 1, ez.ps + 1, ez.pe + 1, (uint32_t)ez.cigar.n); + // } + + + while (ck < cn) { + wx[0] = xk; wy[0] = yk; /**wc[0] = ck;**/ + op = ez.cigar.a[ck]>>14; + ol = (ez.cigar.a[ck]&(0x3fff)); + if(op!=2) xk += ol; + if(op!=3) yk += ol; + ck++; + if(!op) continue; + + for (; ck < cn; ck++) { + op = ez.cigar.a[ck]>>14; + if(!op) break; + ol = (ez.cigar.a[ck]&(0x3fff)); + if(op!=2) xk += ol; + if(op!=3) yk += ol; + } + wx[1] = xk; wy[1] = yk; /**wc[1] = ck;**/ + + zl.qs = zl.qe = zl.ts = zl.te = UINT32_MAX; + fl = hpc_flat_dir0(wx[0] - 1, xstr, xlen, wy[0] - 1, ystr, ylen, xhpf, hpc_rr, hpc_cutoff, &zl); + + zr.qs = zr.qe = zr.ts = zr.te = UINT32_MAX; + fr = hpc_flat_dir0(wx[1], xstr, xlen, wy[1], ystr, ylen, xhpf, hpc_rr, hpc_cutoff, &zr); + + if(fl <= 0 && fr <= 0) continue; + ///xk0 and yk0 are the ciagr boundary that has already been pushed into the rs + + // if(z->y_id == 3494) { + // fprintf(stderr, "-0-[M::%s]\twx::[%ld,\t%ld)\twy::[%ld,\t%ld)\n", __func__, wx[0] + 1, wx[1] + 1, wy[0] + 1, wy[1] + 1); + + // if(fl) { + // fprintf(stderr, "-l-\thrr::%lu\tx::[%u, %u)\ty::[%u, %u)\tmmx::%u\tmmy::%u\n", fl, zl.qs + 1, zl.qe + 1, zl.ts + 1, zl.te + 1, zl.qn + 1, zl.tn + 1); + // } + // if(fr) { + // fprintf(stderr, "-r-\thrr::%lu\tx::[%u, %u)\ty::[%u, %u)\tmmx::%u\tmmy::%u\n", fr, zr.qs + 1, zr.qe + 1, zr.ts + 1, zr.te + 1, zr.qn + 1, zr.tn + 1); + // } + // } + + ox = oy = 0; + + if(fl && fr) {///check if two hpc is overlapped + os = MAX(zl.qs, zr.qs); oe = MIN(zl.qe, zr.qe); + if(oe > os) ox = 1; + + os = MAX(zl.ts, zr.ts); oe = MIN(zl.te, zr.te); + if(oe > os) oy = 1; + + if(ox || oy) { + ///errors within the middle of a HPC regions; just move to the left, no ed required + if((ox) && (oe) && (zl.qs == zr.qs) && (zl.qe == zr.qe) && (zl.ts == zr.ts) && (zl.te == zr.te)) { + fr = 0;///keep left + } else { + lsc = hpc_imp_score(fl, zl.qs, zl.qe, zl.ts, zl.te); rsc = hpc_imp_score(fr, zr.qs, zr.qe, zr.ts, zr.te); + if(lsc > rsc) { + fr = 0;///keep left + } else if(lsc < rsc) { + fl = 0;///keep right + } else {///lsc == rsc + if(fl >= fr) { + fr = 0;///keep left + } else { + fl = 0;///keep right + } + } + } + } + } + + if(fl <= 0) {zl.qe = wx[0], zl.te = wy[0];} + if(fr <= 0) {zr.qs = wx[1], zr.ts = wy[1];} + + // if(z->y_id == 30573) { + // fprintf(stderr, "-1-[M::%s]\twx::[%ld,\t%ld)\twy::[%ld,\t%ld)\n", __func__, wx[0] + 1, wx[1] + 1, wy[0] + 1, wy[1] + 1); + + // if(fl) { + // fprintf(stderr, "-l-\thrr::%lu\tx::[%u, %u)\ty::[%u, %u)\tmmx::%u\tmmy::%u\n", fl, zl.qs + 1, zl.qe + 1, zl.ts + 1, zl.te + 1, zl.qn + 1, zl.tn + 1); + // } + // if(fr) { + // fprintf(stderr, "-r-\thrr::%lu\tx::[%u, %u)\ty::[%u, %u)\tmmx::%u\tmmy::%u\n", fr, zr.qs + 1, zr.qe + 1, zr.ts + 1, zr.te + 1, zr.qn + 1, zr.tn + 1); + // } + // } + + if(fl) {///handle left HPC + // assert(zl.qe >= rs.te && zl.te >= rs.pe); + flat_hpc_cc(z->x_id, z->y_id, xstr, xlen, ystr, ylen, 0.5, &rs, &ez, exz, &zl, xhpf, xk, yk, ck, is_left_end, is_right_end, &xk, &yk, &ck, &rr_end, max_recal/**, (z->y_id == 310315)?1:0**/); + } + + if(fr) { + flat_hpc_cc(z->x_id, z->y_id, xstr, xlen, ystr, ylen, 0.5, &rs, &ez, exz, &zr, xhpf, xk, yk, ck, is_left_end, is_right_end, &xk, &yk, &ck, &rr_end, max_recal/**, (z->y_id == 30573)?1:0**/); + } + + + ///adjust indels within [lxs, lxe) + + // if((lxe == wx[0]) && (lye == wy[0]) && (rxs == wx[1]) && (rys == wy[1])) continue; + } + + // if(z->y_id == 310315) fprintf(stderr, "+[M::%s]\tyid::%u\trr_end::%u\n", __func__, z->y_id, rr_end); + if(!rr_end) { + push_bit_extz0(z->x_id, z->y_id, &rs, &ez, extz_xe(ez) + 1, extz_ye(ez) + 1, ez.cigar.n, extz_xe(ez) + 1, extz_ye(ez) + 1/**, dbg**/); + // if(dbg) prt_cigar_smp(rs.cigar.a, rs.cigar.n); + } + // if(z->y_id == 310315) fprintf(stderr, "-[M::%s]\tyid::%u\trr_end::%u\n", __func__, z->y_id, rr_end); + + p->x_start = rs.ts; p->x_end = rs.te; p->y_start = rs.ps; p->y_end = rs.pe; p->error = rs.err; + push_wcigar(p, &(aux->w_list), &rs); + + buf->a = rs.cigar.a; buf->n = rs.cigar.n; buf->m = rs.cigar.m; + + (*re) += ez.err - rs.err; + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-b-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tis_match::%u\terr::%u\tez.err::%d\trs.err::%d\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // z->is_match, z->non_homopolymer_errors, ez.err, rs.err); + // } + + return 1; +} + + +void prt_cigar_z(overlap_region *z, const char *cmd) +{ + bit_extz_t ez; int64_t k, z_n = z->w_list.n, ck, cn, op, ol; + + fprintf(stderr, "\n[M::%s::%s]tid::%u\t%.*s\tq::[%u,\t%u)\tt::[%u,\t%u)\terr::%u\n", __func__, cmd, + z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, z->non_homopolymer_errors); + + for (k = 0; k < z_n; k++) { + if(is_ualn_win((z->w_list.a[k]))) continue; + fprintf(stderr, "x::[%d,\t%d)\ty::[%d,\t%d)\terr::%d\tcc::", z->w_list.a[k].x_start, z->w_list.a[k].x_end + 1, z->w_list.a[k].y_start, z->w_list.a[k].y_end + 1, z->w_list.a[k].error); + set_bit_extz_t(ez, (*z), k); + ck = 0; cn = ez.cigar.n; + for (; ck < cn; ck++) { + op = ez.cigar.a[ck]>>14; + ol = ez.cigar.a[ck]&(0x3fff); + fprintf(stderr, "%ld%c", ol, "MSID"[op]); + } + fprintf(stderr, "\n"); + } +} + + +void reassign_gaps(overlap_region *z, overlap_region *aux, char* qstr, int64_t ql, uint8_t* qhpf, char* tstr, int64_t tl, All_reads *rref, UC_Read* tu, asg16_v* buf, bit_extz_t *exz) +{ + // if(z->y_id != 310315) return; + + // if(z->y_id != 24 || z->x_id != 25) return; + if(z->non_homopolymer_errors == 0) return; + aux->w_list.n = aux->w_list.c.n = 0; + aux->y_id = z->y_id; aux->y_pos_strand = z->y_pos_strand; + aux->x_pos_s = z->x_pos_s; aux->x_pos_e = z->x_pos_e; + aux->y_pos_s = z->y_pos_s; aux->y_pos_e = z->y_pos_e; + + int64_t k, z_n = z->w_list.n, rr = 0, re = 0; + + // if(z->y_id == 310315) prt_cigar_z(z, "a-0"); + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-a-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tis_match::%u\terr::%u\trr::%ld\tre::%ld\tw_err::%d\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // z->is_match, z->non_homopolymer_errors, rr, re, z->w_list.a[0].error); + // } + + + // fprintf(stderr, "\n-0-tid::%u\t%.*s\n", z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + for (k = 0; k < z_n; k++) { + // if(move_wins(z, k, aux, rref, qstr, tstr, tu, buf, &re)) rr = 1; + if(move_wins_adv(z, k, aux, rref, qstr, tstr, tu, buf, &re)) rr = 1; + } + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-b-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tis_match::%u\terr::%u\trr::%ld\tre::%ld\tw_err::%d\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // z->is_match, z->non_homopolymer_errors, rr, re, z->w_list.a[0].error); + // } + // fprintf(stderr, "-1-tid::%u\t%.*s\n", z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + ///update z by aux_o + if(rr) update_overlap_region(z, aux, ql, ((rref)?(Get_READ_LENGTH((*rref), z->y_id)):(tl))); + z->non_homopolymer_errors -= re; + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-c-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tis_match::%u\terr::%u\trr::%ld\tre::%ld\tw_err::%d\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // z->is_match, z->non_homopolymer_errors, rr, re, z->w_list.a[0].error); + // } + + aux->w_list.n = aux->w_list.c.n = 0; + aux->y_id = z->y_id; aux->y_pos_strand = z->y_pos_strand; + aux->x_pos_s = z->x_pos_s; aux->x_pos_e = z->x_pos_e; + aux->y_pos_s = z->y_pos_s; aux->y_pos_e = z->y_pos_e; + z_n = z->w_list.n; rr = 0; re = 0; + if(!tstr) { + if(z->y_pos_strand) { + recover_UC_Read_RC(tu, rref, z->y_id); + } else { + recover_UC_Read(tu, rref, z->y_id); + } + } + // fprintf(stderr, "[M::%s]\n", __func__); + // int64_t p, r; + // for (k = 1, p = 0; k <= ql; k++) { + // if((k == ql) || ((!!qhpf[p]) != (!!qhpf[k]))) { + // if(qhpf[p]) fprintf(stderr, "[M::%s]\t[%ld,\t%ld)\tql::%ld\n", __func__, p + 1, k + 1, ql); + // p = k; + // } + // } + // for (k = 0; k < ql; k++) { + // if(qhpf[k] == 0) continue; + // fprintf(stderr, "p::%ld\t", k + 1); + // for (r = 0; r < 8; r++) { + // if((qhpf[k]>>r)&1) fprintf(stderr, "r::%ld\t", r + 1); + // } + // fprintf(stderr, "\n"); + // } + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-d-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tis_match::%u\terr::%u\trr::%ld\tre::%ld\tw_err::%d\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // z->is_match, z->non_homopolymer_errors, rr, re, z->w_list.a[0].error); + // } + + + + // if(z->y_id == 310315) prt_cigar_z(z, "a-2"); + + for (k = re = 0; k < z_n; k++) { + if(flat_hpc_wins(z, k, aux, rref, qstr, ql, tstr?tstr:tu->seq, tstr?tl:tu->length, buf, exz, qhpf, HPC_RR_Q, HPC_CC_Q, &re, 256)) rr = 1; + } + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-e-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tis_match::%u\terr::%u\trr::%ld\tre::%ld\tz_n::%ld\tw_err::%d\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // z->is_match, z->non_homopolymer_errors, rr, re, z_n, z->w_list.a[0].error); + // } + ///update z by aux_o + if(rr) update_overlap_region(z, aux, ql, ((rref)?(Get_READ_LENGTH((*rref), z->y_id)):(tl))); + z->non_homopolymer_errors -= re; + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-f-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tis_match::%u\terr::%u\trr::%ld\tre::%ld\tw_err::%d\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // z->is_match, z->non_homopolymer_errors, rr, re, z->w_list.a[0].error); + // } + + // prt_cigar_z(z, "b"); + + /** + // if(z->x_id == 21102 && z->y_id == 21139) { + // fprintf(stderr, "\n-1-[M::%s] rr::%ld\tx_id::%u\ty_id::%u\tx::[%u, %u)\ty::[%u, %u)\tz_n::%ld\n", + // __func__, rr, z->x_id, z->y_id, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, z_n); + // fprintf(stderr, "qid::%u\t%.*s\n", z->x_id, (int)Get_NAME_LENGTH(R_INF, z->x_id), Get_NAME(R_INF, z->x_id)); + // fprintf(stderr, "tid::%u\t%.*s\n", z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + // // fprintf(stderr, "qstr(%lld)::%.*s\n", qu->length, (int32_t)(qu->length), qu->seq); + // // fprintf(stderr, "tstr(%lld)::%.*s\n", tu->length, (int32_t)(tu->length), tu->seq); + // ///debug + + + if(z->y_pos_strand) { + recover_UC_Read_RC(tu, rref, z->y_id); + } else { + recover_UC_Read(tu, rref, z->y_id); + } + + bit_extz_t ez; + for (k = 0; k < z_n; k++) { + if(is_ualn_win((z->w_list.a[k]))) continue; + set_bit_extz_t(ez, (*z), k); + if(!cigar_check(tstr?tstr:tu->seq, qstr, &ez)) { + fprintf(stderr, "\n[M::%s] x_id::%u, y_id::%u, x::[%u, %u), y::[%u, %u)\n", __func__, z->x_id, z->y_id, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); + exit(1); + } + } + // } + + // } + **/ + + + +} + +uint32_t is_ovlp_debug(int64_t s, int64_t e, int64_t ws, int64_t we, int64_t op) +{ + int64_t os, oe, ovlp; + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + if(op != 2) { + return (!!ovlp); + } else { + if(ws >= s && we <= e) return 1; + } + return 0; +} + +uint32_t inline ff_tend(overlap_region *z, int64_t wn, int64_t dn, double dr, double er, int64_t min_err) +{ + int64_t k, zwn = z->w_list.n, err, mm, qi, ci, cn, ql, ws, we, zs, ze, s, e, os, oe, ovlp; bit_extz_t ez; uint32_t cl; uint16_t c; + zs = z->x_pos_s; ze = z->x_pos_e + 1; ql = ze - zs; + if(ql < wn) {return 0;} if(dn > (ql*dr)) {dn = ql*dr;} if(dn < wn) {return 0;} if(ql < dn) {return 0;} + + s = zs; e = zs + dn; + // if(z->y_id == 27) fprintf(stderr, "-a-[M::%s] tid::%u\t%.*s\tz::[%ld,%ld)\ti::[%ld,%ld)\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), zs, ze, s, e); + for (k = err = mm = 0, qi = zs; (k < zwn) && (z->w_list.a[k].x_start < e); k++) { + // if(z->y_id == 27) fprintf(stderr, "-a-[M::%s] tid::%u\t%.*s\tw::[%d,%d)\terr::%d\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), z->w_list.a[k].x_start, z->w_list.a[k].x_end + 1, z->w_list.a[k].error); + if(!(is_ualn_win(z->w_list.a[k]))) { + set_bit_extz_t(ez, (*z), k); + ci = 0; cn = ez.cigar.n; qi = ez.ts; //ti = ez.ps; + while (ci < cn && qi < e) { + ws = qi; + ci = pop_trace(&(ez.cigar), ci, &c, &cl); + if(c!=2) qi += cl; + // if(c!=3) ti += cl; + we = qi; + + if(c == 0) { + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); mm += ovlp; + } else { + err += cl; + } + // assert(is_ovlp_debug(s, e, ws, we, c)); + + if((err > min_err) && ((mm + err) > wn) && (err > ((mm + err)*er))) { + // fprintf(stderr, "-0-[M::%s] tid::%u\t%.*s\tmm::%ld\terr::%ld\tdn::%ld\twn::%ld\tdif::%f\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), mm, err, dn, wn, er); + return 1; + } + } + } else { + ws = z->w_list.a[k].x_start; we = z->w_list.a[k].x_end + 1; + err += we - ws; + + // assert(is_ovlp_debug(s, e, ws, we, -1)); + + if((err > min_err) && ((mm + err) > wn) && (err > ((mm + err)*er))) { + // fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\tmm::%ld\terr::%ld\tdn::%ld\twn::%ld\tdif::%f\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), mm, err, dn, wn, er); + return 1; + } + } + } + + s = ze - dn; e = ze; + for (k = zwn - 1, err = mm = 0, qi = ze; (k >= 0) && ((z->w_list.a[k].x_end + 1) > s); k--) { + if(!(is_ualn_win(z->w_list.a[k]))) { + set_bit_extz_t(ez, (*z), k); + ci = ((int64_t)ez.cigar.n) - 1; qi = ez.te + 1; //ti = ez.pe + 1; + while (ci >= 0 && qi > s) { + we = qi; + ci = pop_trace_back(&(ez.cigar), ci, &c, &cl); + if(c!=2) qi -= cl; + // if(c!=3) ti += cl; + ws = qi; + + if(c == 0) { + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); mm += ovlp; + } else { + err += cl; + } + + // assert(is_ovlp_debug(s, e, ws, we, c)); + + if((err > min_err) && ((mm + err) > wn) && (err > ((mm + err)*er))) { + // fprintf(stderr, "-2-[M::%s] tid::%u\t%.*s\tmm::%ld\terr::%ld\tdn::%ld\twn::%ld\tdif::%f\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), mm, err, dn, wn, er); + return 1; + } + } + } else { + ws = z->w_list.a[k].x_start; we = z->w_list.a[k].x_end + 1; + err += we - ws; + + // assert(is_ovlp_debug(s, e, ws, we, -1)); + + if((err > min_err) && ((mm + err) > wn) && (err > ((mm + err)*er))) { + // fprintf(stderr, "-3-[M::%s] tid::%u\t%.*s\tmm::%ld\terr::%ld\tdn::%ld\twn::%ld\tdif::%f\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), mm, err, dn, wn, er); + return 1; + } + } + } + + return 0; +} + +uint32_t inline ff_lunalign(overlap_region *z, double erate, double gap_rate, int64_t max_gap) +{ + if((z->w_list.n == 1) && (!(is_ualn_win(z->w_list.a[0]))) + && (z->w_list.a[0].x_start == ((int64_t)z->x_pos_s)) && (z->w_list.a[0].x_end == ((int64_t)z->x_pos_e)) + && (z->w_list.a[0].y_start == ((int64_t)z->y_pos_s)) && (z->w_list.a[0].y_end == ((int64_t)z->y_pos_e))) { + return 1; + } + + int64_t k, zwn = z->w_list.n, zq, zt, wq, wt, tot_e, tot_g, ql, tl; + + // fprintf(stderr, "[M::%s]\n", __func__); + + zq = z->x_pos_s; zt = z->y_pos_s; tot_e = tot_g = 0; + for (k = 0; k < zwn; k++) { + // fprintf(stderr, "[M::%s]\twk::%ld\tq::[%d, %d)\tt::[%d, %d)\terr::%d\n", __func__, + // k, z->w_list.a[k].x_start, z->w_list.a[k].x_end + 1, z->w_list.a[k].y_start, z->w_list.a[k].y_end + 1, z->w_list.a[k].error); + if(is_ualn_win(z->w_list.a[k])) continue; + wq = z->w_list.a[k].x_start; + wt = z->w_list.a[k].y_start; + + if(wq != zq) tot_g += ((wq>=zq)?(wq-zq):(zq-wq)); + if(wt != zt) tot_g += ((wt>=zt)?(wt-zt):(zt-wt)); + + zq = z->w_list.a[k].x_end + 1; + zt = z->w_list.a[k].y_end + 1; + tot_e += z->w_list.a[k].error; + + // fprintf(stderr, "[M::%s]\twk::%ld\tq::[%d, %d)\tt::[%d, %d)\terr::%d\n", __func__, + // k, z->w_list.a[k].x_start, z->w_list.a[k].x_end + 1, z->w_list.a[k].y_start, z->w_list.a[k].y_end + 1, z->w_list.a[k].error); + } + + wq = z->x_pos_e + 1; + wt = z->y_pos_e + 1; + if(wq != zq) tot_g += ((wq>=zq)?(wq-zq):(zq-wq)); + if(wt != zt) tot_g += ((wt>=zt)?(wt-zt):(zt-wt)); + + // fprintf(stderr, "[M::%s]\t%.*s(id::%u)\tq::[%u, %u)\t%.*s(id::%u)\tt::[%u, %u)\tre::%ld\trg::%ld\n", __func__, (int)Get_NAME_LENGTH(R_INF, z->x_id), Get_NAME(R_INF, z->x_id), z->x_id, z->x_pos_s, z->x_pos_e + 1, + // (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), z->y_id, z->y_pos_s, z->y_pos_e + 1, tot_e, tot_g); + + if(!tot_g) return 1; + + // fprintf(stderr, "-0-[M::%s]\n", __func__); + + if(tot_g > max_gap) return 0; + + // fprintf(stderr, "-1-[M::%s]\n", __func__); + + ql = z->x_pos_e + 1 - z->x_pos_s; + tl = z->y_pos_e + 1 - z->y_pos_s; + + if((tot_g > (ql*gap_rate)) || (tot_g > (tl*gap_rate))) return 0; + + // fprintf(stderr, "-2-[M::%s]\n", __func__); + + tot_e += tot_g; + + if((tot_e > (ql*erate)) || (tot_e > (tl*erate))) return 0; + + // fprintf(stderr, "-3-[M::%s]\n", __func__); + + return 1; +} + +uint64_t qick_realign(Candidates_list *cl, overlap_region *a, uint64_t n_a, uint64_t n_b, int64_t min_dp, uint64_t ql, uint64_t swl, asg64_v *srt, + All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t ewl, int64_t rid, int64_t khit, int64_t move_gap, asg16_v* buf, uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max, uint8_t *hpf) +{ + uint64_t k = 0, bs, k0, s, e, ws, we, os, oe, tot, p, i; + Window_Pool w; double err, e_max, rr; int64_t re; overlap_region t; srt->n = 0; + + for (k = 0; k < n_a; k++) { + s = a[k].x_pos_s; e = a[k].x_pos_e; + kv_push(uint64_t, *srt, s<<1); + kv_push(uint64_t, *srt, ((e<<1)|1)); + } + radix_sort_bc64(srt->a, srt->a + srt->n); + + uint64_t start, end; int64_t dp, old_dp; + for (k = k0 = tot = 0, dp = start = 0; k < srt->n; k++) { + old_dp = dp; + if (srt->a[k]&1) --dp; + else ++dp; + + if (old_dp < min_dp && dp >= min_dp) {///old_dp < dp, b.a[j] is qs + start = srt->a[k]>>1; + } else if (old_dp >= min_dp && dp < min_dp){ + end = srt->a[k]>>1; + if(end >= start) { + srt->a[k0++] = ((start<<32)|(end+1)); tot += (end+1) - start; + } + } + } + if(tot + swl >= ql) return n_a; + + srt->n = k0; tot = 0; + for (k = k0 = p = 0; k < srt->n; k++) { + s = srt->a[k]>>32; e = (uint32_t)srt->a[k]; + if(s > p) { + srt->a[k0++] = (p<<32)|(s); + if(s - p >= swl) tot = 1; + p = e; + } + } + + s = ql; srt->n = k0; + if(s > p) { + kv_push(uint64_t, *srt, (p<<32)|(s)); + if(s - p >= swl) tot = 1; + } + if(!tot) return n_a; + + // for (k = 0; k < srt->n; k++) { + // fprintf(stderr, "[M::%s] qlsrt::[%lu, %u)\n", __func__, srt->a[k]>>32, (uint32_t)srt->a[k]); + // } + ///base alignment + err = e_rate; e_max = err * 1.5; + init_Window_Pool(&w, ql, ewl, (int)(1.0/err)); + bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(tu, bs<<1); + + overlap_region *z = NULL; + for (i = k = n_a; i < n_b; i++) { + z = &(a[i]); s = z->x_pos_s; e = z->x_pos_e + 1; tot = 0; + if(z->non_homopolymer_errors != ((uint32_t)-1)) continue; + for (k0 = 0; k0 < srt->n; k0++) { + ws = srt->a[k0]>>32; we = (uint32_t)srt->a[k0]; + if(ws >= e) break; + os = MAX(s, ws); oe = MIN(e, we); + tot += ((oe>os)? (oe-os):0); + } + // if(z->y_id == 27752) fprintf(stderr, "-s-[M::%s] tid::%u\t%.*s\ttot::%lu\ts::%lu\te::%lu\terr::%f\te_max::%f\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), tot, s, e, err, e_max); + + if((tot) && (tot < ((e - s)*0.15))) continue; + + // fprintf(stderr, "\n-z-[M::%s] tid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + + if(!align_hc_ed_post_extz(z, rref, qu->seq, tu->seq, exz, err, w.window_length, OVERLAP_THRESHOLD_NOSI_FILTER, 0, NULL)) continue; + + // fprintf(stderr, "-m-[M::%s] tid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + + rr = gen_extend_err_exz(z, NULL, NULL, rref, qu->seq, tu->seq, exz, NULL, w.window_length, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 0, &re); + z->is_match = 0; + + // fprintf(stderr, "-0-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + if (rr > err) continue; + z->non_homopolymer_errors = re; + + if(!gen_hc_fast_cigar(z, cl, rref, w.window_length, qu->seq, tu, exz, aux_o, e_rate, ql, rid, khit, &re)) continue; + + if((align_gap_max >= 0) && (!ff_lunalign(z, err, align_gap_rate, align_gap_max))) continue; + + if(chem_drop && ff_tend(z, 384, 2000, 0.1, (((e_rate*10)<0.36)?(e_rate*10):(0.36)), 128)) continue; + + + // if(z->y_id == 27752) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + reassign_gaps(z, aux_o, qu->seq, ql, hpf, NULL, -1, rref, tu, buf, exz); + + // fprintf(stderr, "-2-[M::%s] tid::%u\t%.*s\trr::%f\tre::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); + + // if(z->y_id == 27752) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\terr::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); + + if(k != i) { + t = a[k]; a[k] = a[i]; a[i] = t; + } + + z = &(a[k++]); z->is_match = 1; ///z->non_homopolymer_errors = re; + z->strong = z->without_large_indel = 0; + } + + return k; +} + +void gen_hc_r_alin(overlap_region_alloc* ol, Candidates_list *cl, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t wl, int64_t rid, int64_t khit, int64_t move_gap, asg16_v* buf, uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max, uint64_t sec_aln_win, uint64_t sec_aln_cov, double sec_aln_err_rate, double sec_aln_max, asg64_v *kp, uint8_t *hpf) +{ + uint64_t i, bs, k, ql = qu->length, ks = 0, ke = sec_aln_win, kcnt = sec_aln_cov; Window_Pool w; double err, e_max, rr; int64_t re, kk; + overlap_region t; overlap_region *z; //asg64_v iidx, buf, buf1; + ol->mapped_overlaps_length = 0; + if(ol->length <= 0) return; + // if(ol->length && ol->list[0].x_id == 19350) e_rate = 0.1; + + ///base alignment + err = e_rate; e_max = err * 1.5; + init_Window_Pool(&w, ql, wl, (int)(1.0/err)); + bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(tu, bs<<1); + // fprintf(stderr, "+[M::%s] window_length::%lld, err::%f\n", __func__, w.window_length, err); + // if(kp) kp->n = 0; + + for (i = k = 0; i < ol->length; i++) { + z = &(ol->list[i]); z->shared_seed = z->non_homopolymer_errors; z->non_homopolymer_errors = (uint32_t)-1;///for index + + // if(z->y_id == 234) fprintf(stderr, "-z-[M::%s] tid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + + if(!align_hc_ed_post_extz(z, rref, qu->seq, tu->seq, exz, err, w.window_length, OVERLAP_THRESHOLD_HIFI_FILTER, 0, NULL)) continue; + + // if(z->y_id == 234) fprintf(stderr, "-m-[M::%s] tid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + + rr = gen_extend_err_exz(z, NULL, NULL, rref, qu->seq, tu->seq, exz, NULL, w.window_length, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 0, &re); + z->is_match = 0; + + // if(z->y_id == 234) fprintf(stderr, "-0-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + if (rr > err) continue; + z->non_homopolymer_errors = re; + + // if(z->y_id == 234) fprintf(stderr, "-c-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + if(!gen_hc_fast_cigar(z, cl, rref, w.window_length, qu->seq, tu, exz, aux_o, e_rate, ql, rid, khit, &re)) continue; + + // if(z->y_id == 234) fprintf(stderr, "-d-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + if((align_gap_max >= 0) && (!ff_lunalign(z, err, align_gap_rate, align_gap_max))) continue; + + // if(z->y_id == 234) fprintf(stderr, "-e-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + if(chem_drop && ff_tend(z, 384, 2000, 0.1, (((e_rate*10)<0.36)?(e_rate*10):(0.36)), 128)) continue; + + // if(z->y_id == 234) fprintf(stderr, "-g-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + + // if(z->y_id == 27752) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + reassign_gaps(z, aux_o, qu->seq, ql, hpf, NULL, -1, rref, tu, buf, exz); + + // fprintf(stderr, "-2-[M::%s] tid::%u\t%.*s\trr::%f\tre::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); + + // if(z->y_id == 27752) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\terr::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); + + if(k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + z = &(ol->list[k++]); z->is_match = 1; ///z->non_homopolymer_errors = re; + z->strong = z->without_large_indel = 0; + + if((kp) && (kcnt >= sec_aln_cov) && (z->x_pos_s >= ke) && (z->x_pos_s >= sec_aln_win)) { + ks = ke - sec_aln_win;///[ks, ke) + for (kk = k - 1, kcnt = 0; kk >= 0 && kcnt < sec_aln_cov; kk--) { + if((ol->list[kk].x_pos_s <= ks) && ((ol->list[kk].x_pos_e + 1) >= ke)) kcnt++; + } + ke += sec_aln_win; + } + } + + // fprintf(stderr, "-[M::%s] window_length::%lld, err::%f\n", __func__, w.window_length, err); + + if((kp) && (kcnt < sec_aln_cov)) { + k = qick_realign(cl, ol->list, k, ol->length, sec_aln_cov, ql, sec_aln_win, kp, + rref, qu, tu, exz, aux_o, (((e_rate*sec_aln_err_rate)>sec_aln_max)?(sec_aln_max):(e_rate*sec_aln_err_rate)), wl, rid, khit, move_gap, buf, chem_drop, align_gap_rate, align_gap_max, hpf); + } + + // fprintf(stderr, "--[M::%s] window_length::%lld, err::%f\n", __func__, w.window_length, err); + + ol->length = k; + if(ol->length <= 0) return; +} + + +uint64_t* infer_chn_bar(overlap_region_alloc* ol, uint64_t max_n_chain, uint64_t rl, uint64_t ocv_w, int32_t *s, asg64_v *sp, uint64_t *cwn) +{ + uint64_t n[4], k, *cc = NULL; uint16_t w; (*cwn) = 0; + n[0] = n[1] = n[2] = n[3] = 0; + s[0] = s[1] = s[2] = s[3] = 0; + + for (k = 0; k < ol->length; ++k) { + w = ha_ov_type(&(ol->list[k]), rl); + ++n[w]; + if (n[w] == max_n_chain) { + s[w] = ol->list[k].shared_seed; + } + } + + + if((((uint64_t)n[3]) >= max_n_chain) && (rl >= ocv_w)) { + uint64_t sn0 = sp->n, cws, cwe; + (*cwn) = (rl/ocv_w) + ((rl%ocv_w)?(1):(0)); + sp->n += (*cwn); + kv_resize(uint64_t, (*sp), sp->n); + + cc = sp->a + sn0; + for (k = cws = cwe = 0; k < (*cwn); k++) { + cwe = cws + ocv_w; if(cwe > rl) cwe = rl; + assert(cwe > cws); + cc[k] = (cwe - cws)*(max_n_chain>>1); ////need to figure out: this cutoff looks so large for me actually? Do we need to have hurdurds of fold coverage? + // fprintf(stderr, "[M::%s::] cw::[%lu, %lu), cc::%lu\n", __func__, cws, cwe, cc[i]); + if(cc[k] > UINT32_MAX) {cc[k] = UINT32_MAX;} cc[k] <<= 32; + cws += ocv_w; + } + } + + return cc; +} + +///update_mm_wins(&(ol->list[k]), cc, (*cwn), ocv_w, rl, 0, 0.15, 16, 1, 0); +///update_mm_wins(&(ol->list[k]), cc, (*cwn), ocv_w, rl, 1, 0.15, 16, max_n_chain>>1, 0); +inline uint8_t update_mm_wins(overlap_region *z, uint64_t *wcut, uint64_t wcut_n, uint64_t ocw, uint64_t rl, uint8_t check_first, double cut_rate, uint64_t cut_bd, uint64_t cut_thr_0, uint64_t cut_thr_1) +{ + uint64_t m = (z->x_pos_s/ocw), ms, me, cws, cwe, os, oe, ol, ql = z->x_pos_e + 1 - z->x_pos_s, nql = 0; + ms = z->x_pos_s; me = z->x_pos_e + 1; + + if(cut_thr_0 > 0) {///for all overlaps + if(check_first) { + m = (z->x_pos_s/ocw); + for (cws = m*ocw, nql = 0; m < wcut_n; m++) { + cwe = cws + ocw; if(cwe > rl) cwe = rl; + os = ((ms >= cws)?ms:cws); + oe = ((me <= cwe)?me:cwe); + if(oe <= os) break; + ol = oe - os; + if(((uint32_t)wcut[m]) + ol > (cut_thr_0*(cwe-cws))) { + nql += ol; + if((nql > cut_bd) && (nql > (ql*cut_rate))) return 0; + } + cws += ocw; + } + } + + m = (z->x_pos_s/ocw); + for (cws = m*ocw; m < wcut_n; m++) { + cwe = cws + ocw; if(cwe > rl) cwe = rl; + os = ((ms >= cws)?ms:cws); + oe = ((me <= cwe)?me:cwe); + if(oe <= os) break; + ol = oe - os; + if(((uint32_t)wcut[m]) + ol < UINT32_MAX) { + wcut[m] += ol; + } else { + wcut[m] >>= 32; wcut[m] <<= 32; wcut[m] |= UINT32_MAX; + } + // if(cws == 0 && cwe == 512) { + // fprintf(stderr, "[M::%s::]\ttid::%u\t%.*s\tol::%lu\tcov::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), ol, ((uint32_t)wcut[m])); + // } + + cws += ocw; + } + } + + if(cut_thr_1 > 0) {///for aligned overlaps + m = (z->x_pos_s/ocw); + for (cws = m*ocw; m < wcut_n; m++) { + cwe = cws + ocw; if(cwe > rl) cwe = rl; + os = ((ms >= cws)?ms:cws); + oe = ((me <= cwe)?me:cwe); + if(oe <= os) break; + ol = oe - os; + if((wcut[m]>>32) + ol < UINT32_MAX) { + wcut[m] += (ol<<32); + } else { + ol = UINT32_MAX; ol <<= 32; + wcut[m] <<= 32; wcut[m] >>= 32; wcut[m] |= ol; + } + cws += ocw; + } + } + + return 1; +} + +inline void print_mm_wins(overlap_region *z, uint64_t *wcut, uint64_t wcut_n, uint64_t ocw, uint64_t rl, uint64_t thres) +{ + uint64_t k, ms, me, qs = z->x_pos_s, qe = z->x_pos_e + 1, os, oe; + for (k = ms = me = 0; k < wcut_n; k++, ms += ocw) { + me = ms + ocw; if(me > rl) me = rl; + os = ((ms >= qs)?ms:qs); + oe = ((me <= qe)?me:qe); + if(oe <= os) continue; + fprintf(stderr, "[M::%s::] mm::[%lu, %lu), cc::%u(%lu), o::[%lu, %lu), uc::%lu(%lu), thres::%lu\n", __func__, ms, me, ((uint32_t)wcut[k]), ((uint32_t)wcut[k])/(me-ms), + os, oe, ((uint32_t)wcut[k]) + oe - os, (((uint32_t)wcut[k]) + oe - os)/(me-ms), thres*(me-ms)); + } +} + +inline void print_mm_wins_all(uint64_t *wcut, uint64_t wcut_n, uint64_t ocw, uint64_t rl, uint64_t is_aln) +{ + uint64_t k, ms, me; + if(!is_aln) { + for (k = ms = me = 0; k < wcut_n; k++, ms += ocw) { + me = ms + ocw; if(me > rl) me = rl; + fprintf(stderr, "[M::%s::] mm::[%lu, %lu), cc::%u(%lu)\n", __func__, ms, me, ((uint32_t)wcut[k]), ((uint32_t)wcut[k])/(me-ms)); + } + } else { + for (k = ms = me = 0; k < wcut_n; k++, ms += ocw) { + me = ms + ocw; if(me > rl) me = rl; + fprintf(stderr, "[M::%s::] mm::[%lu, %lu), cc::%lu(%lu)\n", __func__, ms, me, (wcut[k]>>32), (wcut[k]>>32)/(me-ms)); + } + } + +} + + +inline uint64_t cal_mm_wins_cov(uint64_t *wcut, uint64_t wcut_n, uint64_t ocw, uint64_t rl, uint64_t cut_thres) +{ + uint64_t k, ms, me, cc, tot = 0; + + for (k = ms = me = 0; k < wcut_n; k++, ms += ocw) { + me = ms + ocw; if(me > rl) me = rl; + cc = (me - ms)*cut_thres; + if(((uint32_t)wcut[k]) < cc) { + tot += cc - ((uint32_t)wcut[k]); + } + } + + return tot; +} + + +uint64_t* infer_chn_bar_0(overlap_region_alloc* ol, uint64_t max_n_chain, uint32_t *ocn, uint32_t *osc, uint64_t rl, uint64_t ocv_w, int32_t *s, asg64_v *sp, uint64_t *cwn, uint64_t *fcov) +{ + uint64_t n[4], k, *cc = NULL, sn0 = sp->n; uint16_t w; (*cwn) = (*fcov) = 0; + + (*cwn) = (rl/ocv_w) + ((rl%ocv_w)?(1):(0)); + sp->n += (*cwn); kv_resize(uint64_t, (*sp), sp->n); + cc = sp->a + sn0; memset(cc, 0, sizeof((*cc))*(*cwn)); + + n[0] = n[1] = n[2] = n[3] = 0; + s[0] = s[1] = s[2] = s[3] = 0; + + for (k = 0; k < ol->length; ++k) { + w = ha_ov_type(&(ol->list[k]), rl); + ++n[w]; + if (n[w] == max_n_chain) { + s[w] = osc[k]; ///ol->list[k].shared_seed; + } + + if((n[w] <= max_n_chain) || ((n[w] <= (max_n_chain<<1)) && (((int64_t)osc[k]) == s[w]))) { + (*fcov) += ol->list[k].x_pos_e + 1 - ol->list[k].x_pos_s; + update_mm_wins(&(ol->list[k]), cc, (*cwn), ocv_w, rl, 0, 0.15, 16, 1, 0); + } else if(w == 3) { + if(update_mm_wins(&(ol->list[k]), cc, (*cwn), ocv_w, rl, 1, 0.15, 16, max_n_chain>>1, 0)) { + (*fcov) += ol->list[k].x_pos_e + 1 - ol->list[k].x_pos_s; + } + } + // if((int64_t)osc[k] >= s[w]) { + // dbg[w]++; + // } + } + /** + for (k = 0; k < ol->length; ++k) { + w = ha_ov_type(&(ol->list[k]), rl); + ++n[w]; + if (n[w] == max_n_chain) { + s[w] = osc[k]; ///ol->list[k].shared_seed; + } + + if((ocn[k] >= chain_cutoff) && ((n[w] <= max_n_chain) || ((n[w] <= (max_n_chain<<1)) && (((int64_t)osc[k]) == s[w])))) { + (*fcov) += ol->list[k].x_pos_e + 1 - ol->list[k].x_pos_s; + update_mm_wins(&(ol->list[k]), cc, (*cwn), ocv_w, rl, 0, 0.15, 16, 1, 0); + dbg[w]++; + } + } + fprintf(stderr, "[M::%s] dbg[0]::%lu, dbg[1]::%lu, dbg[2]::%lu, dbg[3]::%lu, s[0]::%d, s[1]::%d, s[2]::%d, s[3]::%d\n", __func__, dbg[0], dbg[1], dbg[2], dbg[3], s[0], s[1], s[2], s[3]); + print_mm_wins_all(cc, (*cwn), ocv_w, rl); + + n[0] = n[1] = n[2] = n[3] = 0; + for (k = 0; k < ol->length; ++k) { + w = ha_ov_type(&(ol->list[k]), rl); + ++n[w]; + + if((ocn[k] >= chain_cutoff) && (w == 3) && (((n[w] > max_n_chain) && ((n[w] > (max_n_chain<<1)) || (((int64_t)osc[k]) < s[w]))))) { + if(update_mm_wins(&(ol->list[k]), cc, (*cwn), ocv_w, rl, 1, 0.15, 16, max_n_chain>>1, 0)) { + (*fcov) += ol->list[k].x_pos_e + 1 - ol->list[k].x_pos_s; + dbg[w]++; + } + } + } + + //[M::infer_chn_bar_0] dbg[0]::223, dbg[1]::215, dbg[2]::245, dbg[3]::236 + fprintf(stderr, "[M::%s] dbg[0]::%lu, dbg[1]::%lu, dbg[2]::%lu, dbg[3]::%lu\n", __func__, dbg[0], dbg[1], dbg[2], dbg[3]); + print_mm_wins_all(cc, (*cwn), ocv_w, rl); + **/ + + memset(cc, 0, sizeof((*cc))*(*cwn)); + return cc; +} + +///[src_s, src_e) +///in src, each window might be either aligned or unaligned; uncovered regions must be unaligned +inline uint32_t ccp_w_list_n(overlap_region *des, overlap_region *src, int64_t src_s, int64_t src_e, uint8_t gap_fill) +{ + if(src->y_id == 3620529) { + fprintf(stderr, "-a-[M::%s]\ttid::%u\t%.*s\tw_list_n::%u\tsrc_s::%ld\tsrc_e::%ld\tgap_fill::%u\n", __func__, src->y_id, (int)Get_NAME_LENGTH(R_INF, src->y_id), Get_NAME(R_INF, src->y_id), (uint32_t)src->w_list.n, + src_s, src_e, gap_fill); + } + assert((src_e > src_s) || (src_s == -1 && src_e == -1)); + window_list *p = NULL; uint32_t k = 0, dn0 = des->w_list.n; int64_t ks, ke; window_list *d = NULL, *s = NULL; + if(src->w_list.n <= 0) { + ks = src_s; ke = src_e-1; + if((gap_fill) && (ks <= ke)) { + kv_pushp(window_list, des->w_list, &p); + p->x_start = ks; p->x_end = ke; + p->y_start = p->y_end = -1; + p->error_threshold = INT16_MIN; p->error = INT16_MAX; + p->extra_begin = INT16_MIN; p->extra_end = INT16_MIN; + p->cidx = p->clen = 0; + } + return des->w_list.n - dn0; + } + + if(src->y_id == 3620529) { + fprintf(stderr, "-b-[M::%s]\ttid::%u\t%.*s\n", __func__, src->y_id, (int)Get_NAME_LENGTH(R_INF, src->y_id), Get_NAME(R_INF, src->y_id)); + for (k = 0; k < src->w_list.n; k++){ + s = &(src->w_list.a[k]); + fprintf(stderr, "[M::%s]\tq::[%d,%d]\tmatch::%u\n", __func__, s->x_start, s->x_end, s->error<=s->error_threshold?1:0); + } + } + + kv_pushp(window_list, des->w_list, &p); s = &(src->w_list.a[0]); + ks = ((src_s>=0)?(src_s):(s->x_start)); ke = s->x_start - 1; + if((gap_fill) && (ks <= ke)) { + p->x_start = ks; p->x_end = ke; + p->y_start = p->y_end = -1; + p->error_threshold = INT16_MIN; p->error = INT16_MAX; + p->extra_begin = INT16_MIN; p->extra_end = INT16_MIN; + p->cidx = p->clen = 0;///remove cigar + k = 0; + } else { + *p = *s; + p->cidx = p->clen = 0;///remove cigar + k = 1; + } + + if(gap_fill) { + for (; k < src->w_list.n; k++){ + s = &(src->w_list.a[k]); d = &(des->w_list.a[des->w_list.n - 1]); + ks = d->x_end+1; ke = s->x_start - 1; + if(ks <= ke) { + if(d->error <= d->error_threshold) {///aligned d + kv_pushp(window_list, des->w_list, &p); + p->x_start = ks; p->x_end = ke; + p->y_start = p->y_end = -1; + p->error_threshold = INT16_MIN; p->error = INT16_MAX; + p->extra_begin = INT16_MIN; p->extra_end = INT16_MIN; + p->cidx = p->clen = 0;///remove cigar + d = &(des->w_list.a[des->w_list.n - 1]); + } else {///unaligned d + d->x_end = ke; d->y_end = -1; + } + } + // if(!(d->x_end+1 == s->x_start)) { + // fprintf(stderr, "-b-[M::%s]\ttid::%u\t%.*s\n", __func__, src->y_id, (int)Get_NAME_LENGTH(R_INF, src->y_id), Get_NAME(R_INF, src->y_id)); + // } + assert(d->x_end+1 == s->x_start); + if((s->error > s->error_threshold) && (d->error > d->error_threshold)) {////unaligned d && unaligned s + d->x_end = s->x_end; d->y_end = s->y_end; + } else { + kv_pushp(window_list, des->w_list, &p); + *p = *s; p->cidx = p->clen = 0; + } + } + } else { + for (; k < src->w_list.n; k++){ + s = &(src->w_list.a[k]); d = &(des->w_list.a[des->w_list.n - 1]); + if((s->error > s->error_threshold) && (d->error > d->error_threshold) && (d->x_end+1 == s->x_start)) {////unaligned d && unaligned s + d->x_end = s->x_end; d->y_end = s->y_end; + } else { + kv_pushp(window_list, des->w_list, &p); + *p = *s; p->cidx = p->clen = 0; + } + } + } + + + d = &(des->w_list.a[des->w_list.n - 1]); + ks = d->x_end+1; ke = src_e-1; + if((gap_fill) && (ks <= ke)) { + if(d->error <= d->error_threshold) {///aligned d + kv_pushp(window_list, des->w_list, &p); + p->x_start = ks; p->x_end = ke; + p->y_start = p->y_end = -1; + p->error_threshold = INT16_MIN; p->error = INT16_MAX; + p->extra_begin = INT16_MIN; p->extra_end = INT16_MIN; + p->cidx = p->clen = 0; + d = &(des->w_list.a[des->w_list.n - 1]); + } else {///unaligned d + d->x_end = ke; d->y_end = -1; + } + } + + return des->w_list.n - dn0; +} + +///[src_s, src_e) +///in src, each window might be either aligned or unaligned; uncovered regions must be unaligned +inline uint32_t ccp_w_list_n_adv(overlap_region *des, overlap_region *src, int64_t src_s, int64_t src_e, uint8_t gap_fill) +{ + // if(src->y_id == 3621213) { + // fprintf(stderr, "-a-[M::%s]\ttid::%u\t%.*s\tw_list_n::%u\tsrc_s::%ld\tsrc_e::%ld\tgap_fill::%u\n", __func__, src->y_id, (int)Get_NAME_LENGTH(R_INF, src->y_id), Get_NAME(R_INF, src->y_id), (uint32_t)src->w_list.n, + // src_s, src_e, gap_fill); + // } + assert((src_e > src_s) || (src_s == -1 && src_e == -1)); + window_list *p = NULL; uint32_t k = 0, dn0 = des->w_list.n; int64_t ks, ke, tot_e, tot_thre; window_list *d = NULL, *s = NULL; + if(src->w_list.n <= 0) { + ks = src_s; ke = src_e-1; + if((gap_fill) && (ks <= ke)) { + kv_pushp(window_list, des->w_list, &p); + p->x_start = ks; p->x_end = ke; + p->y_start = p->y_end = -1; + p->error_threshold = INT16_MIN; p->error = INT16_MAX; + p->extra_begin = INT16_MIN; p->extra_end = INT16_MIN; + p->cidx = p->clen = 0; + } + return des->w_list.n - dn0; + } + + // if(src->y_id == 3621213) { + // fprintf(stderr, "-b-[M::%s]\ttid::%u\t%.*s\n", __func__, src->y_id, (int)Get_NAME_LENGTH(R_INF, src->y_id), Get_NAME(R_INF, src->y_id)); + // for (k = 0; k < src->w_list.n; k++){ + // s = &(src->w_list.a[k]); + // fprintf(stderr, "[M::%s]\tq::[%d,%d]\tmatch::%u\n", __func__, s->x_start, s->x_end, s->error<=s->error_threshold?1:0); + // } + // } + + kv_pushp(window_list, des->w_list, &p); s = &(src->w_list.a[0]); + ks = ((src_s>=0)?(src_s):(s->x_start)); ke = s->x_start - 1; + if((gap_fill) && (ks <= ke)) { + p->x_start = ks; p->x_end = ke; + p->y_start = p->y_end = -1; + p->error_threshold = INT16_MIN; p->error = INT16_MAX; + p->extra_begin = INT16_MIN; p->extra_end = INT16_MIN; + p->cidx = p->clen = 0;///remove cigar + k = 0; + } else { + *p = *s; + p->cidx = p->clen = 0;///remove cigar + k = 1; + } + + if(gap_fill) { + for (; k < src->w_list.n; k++){ + s = &(src->w_list.a[k]); d = &(des->w_list.a[des->w_list.n - 1]); + ks = d->x_end+1; ke = s->x_start - 1; + if(ks <= ke) { + if(d->error <= d->error_threshold) {///aligned d + kv_pushp(window_list, des->w_list, &p); + p->x_start = ks; p->x_end = ke; + p->y_start = p->y_end = -1; + p->error_threshold = INT16_MIN; p->error = INT16_MAX; + p->extra_begin = INT16_MIN; p->extra_end = INT16_MIN; + p->cidx = p->clen = 0;///remove cigar + d = &(des->w_list.a[des->w_list.n - 1]); + } else {///unaligned d + d->x_end = ke; d->y_end = -1; + } + } + // if(!(d->x_end+1 == s->x_start)) { + // fprintf(stderr, "-b-[M::%s]\ttid::%u\t%.*s\n", __func__, src->y_id, (int)Get_NAME_LENGTH(R_INF, src->y_id), Get_NAME(R_INF, src->y_id)); + // } + assert(d->x_end+1 == s->x_start); + if((s->error > s->error_threshold) && (d->error > d->error_threshold)) {////unaligned d && unaligned s + d->x_end = s->x_end; d->y_end = s->y_end; + } else if((s->error <= s->error_threshold) && (d->error <= d->error_threshold)) {////aligned d && aligned s + d->x_end = s->x_end; d->y_end = s->y_end; + + tot_e = (int16_t)d->error + (int16_t)s->error; + if(tot_e > INT16_MAX) tot_e = INT16_MAX; + d->error = tot_e; + + tot_thre = (int16_t)d->error_threshold + (int16_t)s->error_threshold; + if(tot_thre > INT16_MAX) tot_thre = INT16_MAX; + d->error_threshold = tot_thre; + } else { + kv_pushp(window_list, des->w_list, &p); + *p = *s; p->cidx = p->clen = 0; + } + } + } else { + for (; k < src->w_list.n; k++){ + s = &(src->w_list.a[k]); d = &(des->w_list.a[des->w_list.n - 1]); + if(d->x_end+1 == s->x_start) { + if((s->error > s->error_threshold) && (d->error > d->error_threshold)) {////unaligned d && unaligned s + d->x_end = s->x_end; d->y_end = s->y_end; + } else if((s->error <= s->error_threshold) && (d->error <= d->error_threshold)) {////aligned d && aligned s + d->x_end = s->x_end; d->y_end = s->y_end; + + tot_e = (int16_t)d->error + (int16_t)s->error; + if(tot_e > INT16_MAX) tot_e = INT16_MAX; + d->error = tot_e; + + tot_thre = (int16_t)d->error_threshold + (int16_t)s->error_threshold; + if(tot_thre > INT16_MAX) tot_thre = INT16_MAX; + d->error_threshold = tot_thre; + } else { + kv_pushp(window_list, des->w_list, &p); + *p = *s; p->cidx = p->clen = 0; + } + } else { + kv_pushp(window_list, des->w_list, &p); + *p = *s; p->cidx = p->clen = 0; + } + // if((s->error > s->error_threshold) && (d->error > d->error_threshold) && (d->x_end+1 == s->x_start)) {////unaligned d && unaligned s + // d->x_end = s->x_end; d->y_end = s->y_end; + // } else { + // kv_pushp(window_list, des->w_list, &p); + // *p = *s; p->cidx = p->clen = 0; + // } + } + } + + + d = &(des->w_list.a[des->w_list.n - 1]); + ks = d->x_end+1; ke = src_e-1; + if((gap_fill) && (ks <= ke)) { + if(d->error <= d->error_threshold) {///aligned d + kv_pushp(window_list, des->w_list, &p); + p->x_start = ks; p->x_end = ke; + p->y_start = p->y_end = -1; + p->error_threshold = INT16_MIN; p->error = INT16_MAX; + p->extra_begin = INT16_MIN; p->extra_end = INT16_MIN; + p->cidx = p->clen = 0; + d = &(des->w_list.a[des->w_list.n - 1]); + } else {///unaligned d + d->x_end = ke; d->y_end = -1; + } + } + + return des->w_list.n - dn0; +} + + +void refresh_w_list_n(overlap_region *z, uint32_t qe1) +{ + uint32_t k, l, qs, qs0, qe; window_list *p = NULL; + for (k = l = 0, qs = z->x_pos_s; k < z->w_list.n; k++) { + qe = z->w_list.a[k].x_start; qs0 = z->w_list.a[k].x_end + 1; + if(qe > qs) { + p = &(z->w_list.a[l++]); + p->x_start = qs; p->x_end = qe - 1; + p->y_start = p->y_end = -1; + p->error_threshold = -1; p->error = INT16_MAX; + p->extra_begin = p->extra_end = -1; + p->cidx = p->clen = 0; + } + qs = qs0; + } + z->w_list.n = l; qe = qe1; + if(qe > qs) { + kv_pushp(window_list, z->w_list, &p); + p->x_start = qs; p->x_end = qe - 1; + p->y_start = p->y_end = -1; + p->error_threshold = -1; p->error = INT16_MAX; + p->extra_begin = p->extra_end = -1; + p->cidx = p->clen = 0; + } +} + +uint8_t gen_hc_r_alin_flt0(overlap_region *z, overlap_region *zr, overlap_region *aux_o, overlap_region *bz, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, + double err, uint32_t wl, uint8_t set_um_ref, double match_rate_0, uint64_t *tot_b) +{ + uint32_t qe1 = 0; uint8_t ff = 1; double match_rate = match_rate_0; + z->is_match = 0; if(bz) bz->w_list.n = 0; + + // if(z->y_id == 3621213) { + // fprintf(stderr, "-a-[M::%s]\ttid::%u\t%.*s\tzr::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), zr?1:0); + // } + + if(zr == NULL) { + ff = align_hc_ed_post_extz_cut(z, NULL, /**NULL,**/ rref, qu->seq, tu->seq, exz, err, wl, OVERLAP_THRESHOLD_HIFI_FILTER, 0, &qe1, match_rate, tot_b); + if(z->y_id == 3620529) { + fprintf(stderr, "-b-[M::%s]\ttid::%u\t%.*s\tzr::%u\tff::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), zr?1:0, ff); + } + if(bz) ccp_w_list_n_adv(bz, z, z->x_pos_s, qe1, 1); + if((!ff) && (set_um_ref)) { + refresh_w_list_n(z, qe1); + return ff; + } + } else {///zr->is_match == 0 + + aux_o->w_list.n = aux_o->w_list.c.n = 0; + aux_o->y_id = z->y_id; aux_o->y_pos_strand = z->y_pos_strand; + aux_o->x_pos_s = z->x_pos_s; aux_o->x_pos_e = z->x_pos_e; + aux_o->y_pos_s = z->y_pos_s; aux_o->y_pos_e = z->y_pos_e; + + // if(z->y_id == 3621213) { + // fprintf(stderr, "-b-[M::%s]\ttid::%u\t%.*s\tzr::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), zr?1:0); + // } + + ff = align_hc_ed_post_extz_cut_check(aux_o, &(z->f_cigar), zr, rref, qu->seq, tu->seq, exz, err, wl, OVERLAP_THRESHOLD_HIFI_FILTER, tot_b); + if((!ff) && (bz)) ccp_w_list_n_adv(bz, aux_o, -1, -1, 0); + + if(ff) { + // if(z->y_id == 3621213) { + // fprintf(stderr, "-c-[M::%s]\ttid::%u\t%.*s\tzr::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), zr?1:0); + // } + + if((aux_o->align_length > 0) && (aux_o->align_length >= (aux_o->overlapLen*0.8))) { + match_rate = OVERLAP_THRESHOLD_HIFI_FF_DE_FILTER; + } + + // if(z->y_id == 3620095 || z->y_id == 3624181) { + // fprintf(stderr, "[M::%s::]\ttid::%u\talign_length::%u\toverlapLen::%u\n", __func__, z->y_id, aux_o->align_length, aux_o->overlapLen); + // } + + ff = align_hc_ed_post_extz_cut(z, aux_o, /**zr,**/ rref, qu->seq, tu->seq, exz, err, wl, OVERLAP_THRESHOLD_HIFI_FILTER, 0, &qe1, match_rate, tot_b); + if(bz) ccp_w_list_n_adv(bz, z, z->x_pos_s, qe1, 1); + + // if(z->y_id == 3621213) { + // fprintf(stderr, "-d-[M::%s]\ttid::%u\t%.*s\tzr::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), zr?1:0); + // } + } + } + + if(!ff) { + z->w_list.n = z->w_list.c.n = 0; + } + return ff; +} + + + +void stderr_phase_ovlp_0(overlap_region *z) +{ + uint64_t qry_n = Get_NAME_LENGTH(R_INF, z->y_id), rid = z->x_id, ref_n = Get_NAME_LENGTH(R_INF, z->x_id), qid = z->y_id; + + fprintf(stderr, "%.*s(qid::%lu)\tql::%lu\tq::[%u,\t%u)\t%c\t%.*s(tid::%lu)\ttl::%lu\tt::[%u,\t%u)\ttrans::%u\terr::%u\n", + (int32_t)Get_NAME_LENGTH(R_INF, rid), Get_NAME(R_INF, rid), rid, ref_n, z->x_pos_s, z->x_pos_e + 1, "+-"[z->y_pos_strand], + (int32_t)Get_NAME_LENGTH(R_INF, qid), Get_NAME(R_INF, qid), qid, qry_n, z->y_pos_s, z->y_pos_e + 1, ((z->is_match==1)?(0):(1)), z->non_homopolymer_errors); +} + +uint8_t cmp_chain_al_correct(overlap_region *a, overlap_region *b, k_mer_hit *ca, uint64_t cn) +{ + ///rr = cl->list[mi].readID; + uint64_t ak, am[2], bk, bm[2]; + am[0] = a->non_homopolymer_errors; bm[0] = b->non_homopolymer_errors; + + for (am[1] = am[0]; (am[1] < cn) && (ca[am[1]].readID == ca[am[0]].readID); am[1]++){;} + for (bm[1] = bm[0]; (bm[1] < cn) && (ca[bm[1]].readID == ca[bm[0]].readID); bm[1]++){;} + + for (ak = am[0], bk = bm[0]; (ak < am[1]) && (bk < bm[1]) && (ca[ak].self_offset == ca[bk].self_offset); ak++, bk++){;} + + if((ak < am[1]) || (bk < bm[1])) return 0; + return 1; +} + +#define is_aln_wst(a) (((a).error) <= ((a).error_threshold)) + +void prt_chain_cluster(overlap_region_alloc* ol, Candidates_list *cl, uint32_t *a_cu, uint32_t *a_ci, uint32_t *ocn, uint32_t *osc, uint64_t *idx_cu, uint64_t n_cu, uint8_t prt_sc, uint64_t *zfea) +{ + uint64_t k, i, s, on = ol->length, oid, rr, ql = 0, cs, ce; int64_t mi; overlap_region *z, *f; + if(ol->length) ql = Get_READ_LENGTH(R_INF, ol->list[0].x_id); + if(!prt_sc) { + for (k = 0; k < n_cu; k++) {///print + cs = (uint32_t)idx_cu[k]; ce = (uint32_t)idx_cu[k + 1]; + fprintf(stderr, "\n[M::%s]\t0st->n_clu::%lu\n", __func__, ce - cs); + for (i = cs; i < ce; i++) { + oid = a_cu[i]; z = &(ol->list[oid]); + fprintf(stderr, "[M::%s::oid->%lu]\ttid::%u\t%.*s\tsc::%u\tcn::%u\n", __func__, oid, + z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), osc[oid], ocn[oid]); + mi = z->non_homopolymer_errors; rr = cl->list[mi].readID; + for (; mi < cl->length && cl->list[mi].readID == rr; mi++) { + fprintf(stderr, "%u\t", cl->list[mi].self_offset); + } + fprintf(stderr, "\n"); + + } + } + + for (k = 0; k < n_cu; k++) {///double check + cs = (uint32_t)idx_cu[k]; ce = (uint32_t)idx_cu[k + 1]; + f = &(ol->list[a_cu[cs]]); + for (i = cs; i < ce; i++) { + z = &(ol->list[a_cu[i]]); + if(cmp_chain_al_correct(f, z, cl->list, cl->length) == 0) { + fprintf(stderr, "[M::%s]\terror1\tof(%u)->ok(%u)\n", __func__, a_cu[cs], a_cu[i]); + } + } + + for (i = 0; i < on; i++) { + z = &(ol->list[i]); + if(cmp_chain_al_correct(f, z, cl->list, cl->length)) { + if(a_ci[a_cu[cs]] != a_ci[i]) { + fprintf(stderr, "[M::%s]\terror2\tof(rid<%u>::cid<%u>)->ok(rid<%lu>::cid<%u>)\n", __func__, a_cu[cs], a_ci[a_cu[cs]], i, a_ci[i]); + } + } + } + } + /** + for (k = 1, l = 0; k <= on; k++) { + if(k == on || ci[cu[k]] != ci[cu[l]]) { + fprintf(stderr, "\n[M::%s]\tn_clu::%lu\n", __func__, k - l); + for (i = l; i < k; i++) { + oid = cu[i]; z = &(ol->list[oid]); + fprintf(stderr, "[M::%s::oid->%lu]\ttid::%u\t%.*s\tsc::%u\tcn::%u\n", __func__, oid, + z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), osc[oid], ocn[oid]); + mi = z->non_homopolymer_errors; rr = cl->list[mi].readID; + for (; mi < cl->length && cl->list[mi].readID == rr; mi++) { + fprintf(stderr, "%u\t", cl->list[mi].self_offset); + } + fprintf(stderr, "\n"); + + } + l = k; + } + } + + + for (k = 1, l = 0; k <= on; k++) { + if(k == on || ci[cu[k]] != ci[cu[l]]) { + f = &(ol->list[cu[l]]); + for (i = l; i < k; i++) { + z = &(ol->list[cu[i]]); + if(cmp_chain_al_correct(f, z, cl->list) == 0) { + fprintf(stderr, "[M::%s]\terror1\n", __func__); + } + } + + for (i = 0; i < on; i++) { + z = &(ol->list[i]); + if(cmp_chain_al_correct(f, z, cl->list)) { + if(ci[cu[l]] != ci[i]) { + fprintf(stderr, "[M::%s]\terror2\n", __func__); + } + } + } + + l = k; + } + } + **/ + } else { + for (k = 0; k < n_cu; k++) {///print + cs = (uint32_t)idx_cu[k]; ce = (uint32_t)idx_cu[k + 1]; + fprintf(stderr, "\n[M::%s]\t1st->n_clu::%lu\n", __func__, ce - cs); + for (i = cs; i < ce; i++) { + oid = a_cu[i]; z = &(ol->list[oid]); + fprintf(stderr, "[M::%s::oid->%lu]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\ttype::%d\n", __func__, oid, + z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + osc[oid], ocn[oid], z->is_match, z->non_homopolymer_errors, ha_ov_type(z, ql)); + if(zfea) { + window_list *wa = z->w_list.a + (zfea[oid]>>32); + uint32_t wn = (uint32_t)zfea[oid]; + for (s = 0; s < wn; s++) { + fprintf(stderr, "q::[%d,%d](m::%u),", wa[s].x_start, wa[s].x_end, is_aln_wst(wa[s])); + } + fprintf(stderr, "\n"); + } + } + } + /** + for (k = 1, l = 0; k <= on; k++) { + if(k == on || ci[cu[k]] != ci[cu[l]]) { + fprintf(stderr, "\n[M::%s]\tn_clu::%lu\n", __func__, k - l); + for (i = l; i < k; i++) { + oid = cu[i]; z = &(ol->list[oid]); + fprintf(stderr, "[M::%s::oid->%lu]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\ttype::%d\n", __func__, oid, + z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + osc[oid], ocn[oid], z->is_match, z->non_homopolymer_errors, ha_ov_type(z, ql)); + // mi = z->non_homopolymer_errors; rr = cl->list[mi].readID; + // for (; mi < cl->length && cl->list[mi].readID == rr; mi++) { + // fprintf(stderr, "%u\t", cl->list[mi].self_offset); + // } + // fprintf(stderr, "\n"); + + } + l = k; + } + } + **/ + } +} + +inline void prt_umatched_wins(overlap_region *z) +{ + if(!z) return; + uint64_t k = 0; + for (k = 0; k < z->w_list.n; k++) { + fprintf(stderr, "zc::[M::%s]\tq::[%d,%d)\n", __func__, z->w_list.a[k].x_start, z->w_list.a[k].x_end + 1); + } + +} + +void refill_hc_r_alin_flt(overlap_region_alloc* ol, uint64_t *wsrt, uint64_t wsrt_n) +{ + +} + +/** +void chain_ss_0(overlap_region_alloc* ol, asg64_v *kp, uint32_t *osc) +{ + uint64_t k, l, t, on = ol->length; + kp->n = on; kv_resize(uint64_t, *kp, on); + + for (k = 0; k < on; k++) { + kp->a[k] = ol->list[k].x_pos_s; + kp->a[k] <<= 32; kp->a[k] |= k; + } + radix_sort_bc64(kp->a, kp->a + on);///sort by how many snps in one overlap + + for (k = 1, l = 0; k <= on; k++) { + if (k == on || (kp->a[k]>>32) != (kp->a[l]>>32)) { + if (k - l > 1) { + for (t = l; t < k; t++) { + kp->a[t] <<= 32; kp->a[t] >>= 32; + kp->a[t] |= ((uint64_t)(ol->list[k].x_pos_e + 1))<<32; + } + radix_sort_bc64(kp->a + l, kp->a + k); + } + l = k; + } + } +} +**/ + + +inline void iter_fa_is_aln(const window_list *fa, uint32_t fn, uint32_t *idx, uint8_t match) +{ + if(match == 0) { + while (((*idx) < fn) && (is_aln_wst(fa[(*idx)]))) (*idx)++; + } else { + while (((*idx) < fn) && (!is_aln_wst(fa[(*idx)]))) (*idx)++; + } +} + +// Append [s,e] (inclusive) with is_aln=0 into out, coalescing if overlap/contiguous. +// Assumes out has enough capacity. +static inline void push0_coalesce(window_list_alloc *ou, int64_t s, int64_t e) +{ + if (s > e) return; + window_list *z = NULL; + if (ou->n > 0) { + z = &ou->a[ou->n - 1]; + if ((z->x_end + 1) >= s) { // overlap or contiguous + if (e > z->x_end) z->x_end = e; + return; + } + } + + kv_pushp(window_list, *ou, &z); + z->x_start = s; + z->x_end = e; + z->y_start = z->y_end = -1; + z->error_threshold = -1; + z->error = INT16_MAX; + z->extra_begin = z->extra_end = -1; + z->cidx = z->clen = 0; +} + +// Emit (union0_interval \ fa1) into out, with coalescing. +// fa1 index *k is advanced as needed (monotonic). +static inline void emit_zero_minus_one(int64_t cs, int64_t ce, const window_list *fa, uint32_t fn, uint32_t *k, window_list_alloc *ou) +{ + // advance blockers that end before cs + while (*k < fn) { + iter_fa_is_aln(fa, fn, k, 1); + if (*k >= fn) break; + if (fa[*k].x_end >= cs) break; + (*k)++; + } + + int64_t cur = cs, b0, b1; + while (*k < fn) { + iter_fa_is_aln(fa, fn, k, 1); + if (*k >= fn) break; + + ///i_1[b0, b1] + b0 = fa[*k].x_start; b1 = fa[*k].x_end; + + if (b0 > ce) break; // no more overlap + if (b1 < cur) { // no overlap; blocker behind cursor + (*k)++; continue; + } + + ///b0 >= cur && b0 <= ce; b1 >= cur; now we have overlap + push0_coalesce(ou, cur, b0 - 1); + + cur = b1 + 1; + if (cur > ce) break; + (*k)++; + } + + if (cur <= ce) { + push0_coalesce(ou, cur, ce); + } +} + +void ss_aln_msk(window_list *za, uint32_t zn, window_list *fa, uint32_t fn, window_list_alloc *ou) +{ + uint32_t zi_0 = 0, fi_0 = 0, fi_1 = 0, ff = 0; ou->n = 0; + int64_t s, e, cs = 0, ce = -1; window_list *w; + + iter_fa_is_aln(fa, fn, &fi_0, 0); iter_fa_is_aln(fa, fn, &fi_1, 1); + if((zi_0 < zn) || (fi_0 < fn)) { + w = NULL; + if(fi_0 >= fn) { + w = &za[zi_0++]; + } else if(zi_0 >= zn) { + w = &fa[fi_0++]; + iter_fa_is_aln(fa, fn, &fi_0, 0); + } else { + if (za[zi_0].x_start <= fa[fi_0].x_start) { + w = &za[zi_0++]; + } else { + w = &fa[fi_0++]; + iter_fa_is_aln(fa, fn, &fi_0, 0); + } + } + + s = w->x_start; e = w->x_end; + if (!ff) { + cs = s; ce = e; ff = 1; + } else if (s <= ce + 1) { + if (e > ce) ce = e; // extend [cs, ce] + } else {///new one, so push [cs, ce] + // finalize current interbal [cs,ce], subtract fa1 and emit + emit_zero_minus_one(cs, ce, fa, fn, &fi_1, ou); + cs = s; ce = e; + } + } + + if (ff) { + emit_zero_minus_one(cs, ce, fa, fn, &fi_1, ou); + } +} + + +void update_aln_msk(overlap_region *zm, uint64_t *zm_feature, window_list *fa, uint64_t fn, uint8_t clear_zm, overlap_region *tmp) +{ + uint64_t zmfk = (*zm_feature)>>32, zmfn = (uint32_t)(*zm_feature); + assert((zmfn) && ((zmfk + zmfn) <= zm->w_list.m) && (zmfk >= zm->w_list.n)); + if(clear_zm) zm->w_list.n = 0; + if(zm->w_list.n == 0) return; + ss_aln_msk(zm->w_list.a, zm->w_list.n, fa, fn, &(tmp->w_list)); + zm->w_list.n = tmp->w_list.n; + if(zm->w_list.n > zmfk) {///we need to move + uint64_t k, ze0 = zmfk + zmfn - 1, ze1 = zm->w_list.n + zmfn - 1, zn1 = zm->w_list.n + zmfn; + if(zn1 > zm->w_list.m) kv_resize(window_list, zm->w_list, zn1); + for (k = 0; k < zmfn; k++) { + zm->w_list.a[ze1--] = zm->w_list.a[ze0--]; + } + ///update zm_feature + zmfk = zm->w_list.n; (*zm_feature) <<= 32; (*zm_feature) >>= 32; (*zm_feature) |= (zmfk<<32); + } + + if(zm->w_list.n) { + memcpy(zm->w_list.a, tmp->w_list.a, zm->w_list.n*sizeof((*(zm->w_list.a)))); + } +} + +void push_zm_feature_wins(overlap_region *z, uint64_t *zm_feature, overlap_region *bz) +{ + uint64_t zn = z->w_list.n + bz->w_list.n; + (*zm_feature) = z->w_list.n; (*zm_feature) <<= 32; (*zm_feature) |= (uint64_t)bz->w_list.n; + kv_resize(window_list, z->w_list, zn); + if(bz->w_list.n) { + memcpy(z->w_list.a + z->w_list.n, bz->w_list.a, bz->w_list.n*sizeof((*(bz->w_list.a)))); + } +} + +uint8_t inline gen_hc_r_alin_flt_0(overlap_region *oa, uint64_t zi, uint32_t *a_cu, uint32_t *a_ci, uint64_t *idx_cu, + Candidates_list *cl, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, overlap_region *bz, double err, double e_max, double e_rate, int64_t wsl, int64_t ql, int64_t rid, int64_t khit, + uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max, uint8_t *hpf, asg16_v* buf, uint64_t *o_feature, uint64_t *tot_b) +{ + uint64_t cz, czs, cze, pi, tz, bs, f = 1, zci = ((uint64_t)-1); uint8_t mcu = 0, rset_f = 1; overlap_region *z = NULL, *zc = NULL; double nhit = OVERLAP_THRESHOLD_HIFI_FF_FILTER, rr; int64_t re; + + z = &(oa[zi]); z->non_homopolymer_errors = UINT32_MAX - 1;///primary chain that needs to be verfied + + cz = a_ci[zi]; + pi = a_cu[(uint32_t)idx_cu[cz]]; + czs = (uint32_t)idx_cu[cz]; cze = (uint32_t)idx_cu[cz+1]; + // fprintf(stderr, "-1-[M::%s]\ti::%lu\tpi::%lu\n", __func__, i, pi); + + if(pi != zi) { + zc = &(oa[pi]); + // fprintf(stderr, "-1a-[M::%s]\tis_match::%u\twn::%u\n", __func__, zc->is_match, (uint32_t)zc->w_list.n); + if(zc->is_match == 1) {///this group could be aligned; so nothing to filter + zc = NULL; nhit = -1.0; + } else {///is_match = 0 + if(zc->w_list.n > 0) {///this group could not be aligned; will be used for filtering + nhit = OVERLAP_THRESHOLD_HIFI_FILTER; + // nhit = OVERLAP_THRESHOLD_HIFI_FF_FILTER; + } else { + if(zc->non_homopolymer_errors == UINT32_MAX) {///switch overlaps + for (tz = czs; (tz < cze) && (a_cu[tz] != zi); tz++); + assert((a_cu[tz] == zi) && (tz > czs)); + bs = a_cu[(uint32_t)idx_cu[cz]]; + a_cu[(uint32_t)idx_cu[cz]] = a_cu[tz]; + a_cu[tz] = bs; + pi = zi; + } + zc = NULL; nhit = -1.0;///this group could be aligned + } + + } + } + + if((pi == zi) && (cze > czs + 1)) {///top chain + multipe chains cluster; zc must be null + mcu = 1; + } + + // fprintf(stderr, "-2-[M::%s]\tpi::%lu\tmcu::%lu\n", __func__, pi, mcu); + + // prt_umatched_wins(zc); + ///just for debugging + // zc = NULL; mcu = 0; nhit = -1.0; + + if(z->y_id == 3620529) { + fprintf(stderr, "-0-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + } + + if(zc) zci = pi; + + f = gen_hc_r_alin_flt0(z, zc, aux_o, bz, rref, qu, tu, exz, err, wsl, mcu, nhit, tot_b); + + if(zc && bz) update_aln_msk(zc, &o_feature[zci], bz->w_list.a, bz->w_list.n, f, aux_o); + + if(!f) rset_f = 0; + + if(f) { + if(z->y_id == 3620529) { + fprintf(stderr, "-1-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + } + rr = gen_extend_err_exz(z, NULL, NULL, rref, qu->seq, tu->seq, exz, NULL, wsl, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 0, &re); + z->is_match = 0; + if (rr > err) f = 0; + } + + if(f) { + z->non_homopolymer_errors = re; + + if(z->y_id == 3620529) { + fprintf(stderr, "-2-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + } + + if(!gen_hc_fast_cigar(z, cl, rref, wsl, qu->seq, tu, exz, aux_o, e_rate, ql, rid, khit, &re)) f = 0; + } + + + + if(f) { + if(z->y_id == 3620529) { + fprintf(stderr, "-3-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + } + + + if((align_gap_max >= 0) && (!ff_lunalign(z, err, align_gap_rate, align_gap_max))) f = 0; + } + + + if(f) { + if(z->y_id == 3620529) { + fprintf(stderr, "-4-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + } + + if(chem_drop && ff_tend(z, 384, 2000, 0.1, (((e_rate*10)<0.36)?(e_rate*10):(0.36)), 128)) f = 0; + } + + if(f) { + reassign_gaps(z, aux_o, qu->seq, ql, hpf, NULL, -1, rref, tu, buf, exz); + + // fprintf(stderr, "-2-[M::%s] tid::%u\t%.*s\trr::%f\tre::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); + fprintf(stderr, "-5-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + } + + if((!f) && (rset_f)) { + z->w_list.n = z->w_list.c.n = 0; + } + + if(bz) { + push_zm_feature_wins(z, &o_feature[zi], bz); + } + + return f; + + // z->is_match = 1; z->strong = z->without_large_indel = 0; + // if(fc) update_mm_wins(z, wcut, wcut_n, ocw, ql, 0, 0.15, 16, 0, 1); +} + +uint8_t inline gen_hc_r_alin_flt_1(overlap_region *oa, uint64_t zi, Candidates_list *cl, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, overlap_region *bz, + double err, double e_max, double e_rate, int64_t wsl, int64_t ql, int64_t rid, int64_t khit, uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max, uint8_t *hpf, asg16_v* buf, uint64_t *o_feature, uint64_t *tot_b) +{ + uint8_t f = 1; overlap_region *z = NULL; double rr; int64_t re; uint32_t qe1 = -1; + + z = &(oa[zi]); z->non_homopolymer_errors = UINT32_MAX - 1;///primary chain that needs to be verfied + + // fprintf(stderr, "-2-[M::%s]\tpi::%lu\tmcu::%lu\n", __func__, pi, mcu); + + // prt_umatched_wins(zc); + ///just for debugging + // zc = NULL; mcu = 0; nhit = -1.0; + + // if(z->y_id == 3621141) { + // fprintf(stderr, "-0-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + // } + + f = align_hc_ed_post_extz_cut(z, NULL, rref, qu->seq, tu->seq, exz, err, wsl, OVERLAP_THRESHOLD_HIFI_FILTER, 0, &qe1, -1, tot_b); + if(bz) { + bz->w_list.n = 0; + ccp_w_list_n_adv(bz, z, z->x_pos_s, qe1, 1); + } + + if(f) { + // if(z->y_id == 3621141) { + // fprintf(stderr, "-1-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + // } + rr = gen_extend_err_exz(z, NULL, NULL, rref, qu->seq, tu->seq, exz, NULL, wsl, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 0, &re); + z->is_match = 0; + if (rr > err) f = 0; + } + + if(f) { + z->non_homopolymer_errors = re; + // if(z->y_id == 3621141) { + // fprintf(stderr, "-2-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + // } + if(!gen_hc_fast_cigar(z, cl, rref, wsl, qu->seq, tu, exz, aux_o, e_rate, ql, rid, khit, &re)) f = 0; + } + + + + if(f) { + // if(z->y_id == 3621141) { + // fprintf(stderr, "-3-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + // } + if((align_gap_max >= 0) && (!ff_lunalign(z, err, align_gap_rate, align_gap_max))) f = 0; + } + + + if(f) { + // if(z->y_id == 3621141) { + // fprintf(stderr, "-4-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + // } + if(chem_drop && ff_tend(z, 384, 2000, 0.1, (((e_rate*10)<0.36)?(e_rate*10):(0.36)), 128)) f = 0; + } + + if(f) { + reassign_gaps(z, aux_o, qu->seq, ql, hpf, NULL, -1, rref, tu, buf, exz); + // if(z->y_id == 3621141) { + // fprintf(stderr, "-2-[M::%s] tid::%u\t%.*s\trr::%f\tre::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); + // fprintf(stderr, "-5-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + // } + } + + if((!f)) { + z->w_list.n = z->w_list.c.n = 0; + } + + if(bz) { + push_zm_feature_wins(z, &o_feature[zi], bz); + } + + return f; + + // z->is_match = 1; z->strong = z->without_large_indel = 0; + // if(fc) update_mm_wins(z, wcut, wcut_n, ocw, ql, 0, 0.15, 16, 0, 1); +} + + + +uint8_t inline gen_hc_r_alin_flt_1_smp(overlap_region *z, Candidates_list *cl, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, + double err, double e_max, double e_rate, int64_t wsl, int64_t ql, int64_t rid, int64_t khit, uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max, uint8_t *hpf, asg16_v* buf, uint64_t *tot_b) +{ + uint8_t f = 1; double rr; int64_t re; + + z->non_homopolymer_errors = UINT32_MAX - 1;///primary chain that needs to be verfied + + // fprintf(stderr, "-2-[M::%s]\tpi::%lu\tmcu::%lu\n", __func__, pi, mcu); + // prt_umatched_wins(zc); + // if(z->y_id == 3621141) { + // fprintf(stderr, "-0-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + // } + + f = align_hc_ed_post_extz(z, rref, qu->seq, tu->seq, exz, err, wsl, OVERLAP_THRESHOLD_NOSI_FILTER, 0, tot_b); + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-a-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // z->is_match, z->non_homopolymer_errors); + // } + + if(f) { + // if(z->y_id == 3621141) { + // fprintf(stderr, "-1-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + // } + rr = gen_extend_err_exz(z, NULL, NULL, rref, qu->seq, tu->seq, exz, NULL, wsl, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 0, &re); + z->is_match = 0; + if (rr > err) f = 0; + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-b-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tis_match::%u\terr::%u\trr::%f\terr::%f\tre::%ld\tf::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // z->is_match, z->non_homopolymer_errors, rr, err, re, f); + // } + } + + if(f) { + z->non_homopolymer_errors = re; + // if(z->y_id == 3621141) { + // fprintf(stderr, "-2-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + // } + if(!gen_hc_fast_cigar(z, cl, rref, wsl, qu->seq, tu, exz, aux_o, e_rate, ql, rid, khit, &re)) { + f = 0; + } else { + z->non_homopolymer_errors = re; + } + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-c-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tis_match::%u\terr::%u\trr::%f\terr::%f\tre::%ld\tf::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // z->is_match, z->non_homopolymer_errors, rr, err, re, f); + // } + } + + + + if(f) { + // if(z->y_id == 3621141) { + // fprintf(stderr, "-3-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + // } + if((align_gap_max >= 0) && (!ff_lunalign(z, err, align_gap_rate, align_gap_max))) f = 0; + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-d-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tis_match::%u\terr::%u\trr::%f\terr::%f\tre::%ld\tf::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // z->is_match, z->non_homopolymer_errors, rr, err, re, f); + // } + } + + + if(f) { + // if(z->y_id == 3621141) { + // fprintf(stderr, "-4-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + // } + if(chem_drop && ff_tend(z, 384, 2000, 0.1, (((e_rate*10)<0.36)?(e_rate*10):(0.36)), 128)) f = 0; + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-e-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tis_match::%u\terr::%u\trr::%f\terr::%f\tre::%ld\tf::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // z->is_match, z->non_homopolymer_errors, rr, err, re, f); + // } + } + + if(f) { + reassign_gaps(z, aux_o, qu->seq, ql, hpf, NULL, -1, rref, tu, buf, exz); + // if(z->y_id == 3621141) { + // fprintf(stderr, "-2-[M::%s] tid::%u\t%.*s\trr::%f\tre::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); + // fprintf(stderr, "-5-[M::%s]\ttid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + // } + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-g-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tis_match::%u\terr::%u\trr::%f\terr::%f\tre::%ld\tf::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // z->is_match, z->non_homopolymer_errors, rr, err, re, f); + // } + } + + if((!f)) { + z->w_list.n = z->w_list.c.n = 0; + } + + return f; + + // z->is_match = 1; z->strong = z->without_large_indel = 0; + // if(fc) update_mm_wins(z, wcut, wcut_n, ocw, ql, 0, 0.15, 16, 0, 1); +} + + + +///need to consider coverage, this information is missing right now (currently only use numbers) +void gen_hc_r_alin_flt(overlap_region_alloc* ol, Candidates_list *cl, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, overlap_region *aux_b, double e_rate, int64_t wl, int64_t rid, int64_t khit, int64_t move_gap, asg16_v* buf, uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max, uint64_t sec_aln_win, uint64_t sec_aln_cov, double sec_aln_err_rate, double sec_aln_max, + asg64_v *kp, asg64_v *sp, uint64_t ocw, uint8_t *hpf, uint32_t *a_cu, uint32_t *a_ci, uint32_t *ocn, uint32_t *osc, uint64_t *idx_cu, uint64_t n_cu, asg64_v *bp, uint64_t max_n_chain, uint64_t max_n_chain_f, uint64_t chain_cutoff, uint64_t ave_cov_min) +{ + uint64_t i, bs, /**k = 0,**/ ql = qu->length/**, ks = 0, ke = sec_aln_win, kcnt = sec_aln_cov**/, *wcut = NULL, wcut_n = 0, *wsrt = NULL, wsrt_n = 0, wsrt_n0, *o_feature = NULL, spn0 = 0, tz, tot_b = 0, t_cov0, z_cov, focv = 0, fcov_0 = 0, tot_b_cut = 0; Window_Pool w; double err, e_max; + overlap_region /**t,**/ *z, *bz = NULL; uint8_t fc = ((ol->length > max_n_chain)?(1):(0)), wf, ff; int32_t s[4]; s[0] = s[1] = s[2] = s[3] = 0; uint32_t scn[4], sca[4]; + scn[0] = scn[1] = scn[2] = scn[3] = sca[0] = sca[1] = sca[2] = sca[3] = 0; + + ol->mapped_overlaps_length = 0; + if(ol->length <= 0 || ql <= 0) return; + + prt_chain_cluster(ol, cl, a_cu, a_ci, ocn, osc, idx_cu, n_cu, 0, NULL); + + ///base alignment + err = e_rate; e_max = err * 1.5; + init_Window_Pool(&w, ql, wl, (int)(1.0/err)); + bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(tu, bs<<1); + + spn0 = sp->n; sp->n += ol->length + ol->length; + kv_resize(uint64_t, (*sp), sp->n); + wsrt = sp->a + spn0; o_feature = sp->a + spn0 + ol->length; + if(fc) { + wcut = infer_chn_bar_0(ol, max_n_chain, /**chain_cutoff,**/ ocn, osc, ql, ocw, s, sp, &wcut_n, &focv); + if ((s[0] <= 0) && (s[1] <= 0) && (s[2] <= 0) && (s[3] <= 0)) fc = 0; + wsrt = sp->a + spn0; o_feature = sp->a + spn0 + ol->length; + + focv = focv/ql; if(focv < 0) focv = 1; focv *= 1.05; + if(focv < ave_cov_min) focv = ave_cov_min; + // if(focv > ave_cov_max) focv = ave_cov_max; + // fcov_0 = max_n_chain>>1; if(fcov_0 > focv) fcov_0 = focv; + fcov_0 = max_n_chain>>1; + + tot_b_cut = max_n_chain>>1; tot_b_cut *= ql; + + bz = aux_b; + } + + fprintf(stderr, "-0-[M::%s] focv::%lu, ave_cov_min::%lu, fcov_0::%lu, max_n_chain::%lu, wcut_n::%lu, ql::%lu\n", __func__, focv, ave_cov_min, fcov_0, max_n_chain, wcut_n, ql); + + ////this is very important!!! main issues coming from uneven read length, some short reads may have too many chains need to be calculated? + ///a-0, more important) use the best alignment overlap, to estimate the chain cuttoff and which minimizer may have higher weights + ///a) if the chain score is equal to s[wf] and it is not in a large cluster, avoid to perform alignment + ///b) after the first round of alignment, calculate how many chains are aligned/unaligned as the weight to valludate the reamining chains with not high scores + ///c) if wcut[h] and wcut[l] have already collected enough aligned chains, we can discard a cluster together, if one or a part (10%?) of them are unaligned, or with very high difference rate + ///d) need to record overlaps in each round, and then use them for next round, avoiding missing real overlaps + s[0] = s[1] = s[2] = s[3] = 0;///reset it + for (i = wsrt_n = 0; i < ol->length; i++) {///primary chain + z = &(ol->list[i]); z->is_match = 0; + z->shared_seed = z->non_homopolymer_errors; + z->non_homopolymer_errors = UINT32_MAX;///for index + + wf = ha_ov_type(z, ql); ff = 1; o_feature[i] = 0; + + // fprintf(stderr, "\n-0-[M::%s::i->%lu]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\ttype::%u\tsc::%u(%d)\tcn::%u(%lu)\tpi::%u\n", __func__, i, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, wf, osc[i], s[wf], ocn[i], chain_cutoff, cu[ci[i]]); + + // if(z->y_id == 3623173) { + // fprintf(stderr, "-sss-0-sss-[M::%s::i->%lu]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\ttype::%u\tsc::%u(%d)\tcn::%u(%lu)\tscn[wf]::%u\tmax_n_chain::%lu\n", __func__, i, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, wf, osc[i], s[wf], ocn[i], chain_cutoff, scn[wf], max_n_chain); + // } + + + if((ocn[i] >= chain_cutoff) && ((scn[wf] <= max_n_chain) || ((scn[wf] <= (max_n_chain<<1)) && (((int64_t)osc[i]) == s[wf])))) { + // if(z->y_id == 3623173) { + // fprintf(stderr, "-sss-1-sss-[M::%s::i->%lu]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\ttype::%u\tsc::%u(%d)\tcn::%u(%lu)\tscn[wf]::%u\tmax_n_chain::%lu\tmax_n_chain_f::%lu\n", __func__, i, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, wf, osc[i], s[wf], ocn[i], chain_cutoff, scn[wf], max_n_chain, max_n_chain_f); + // } + if(fc) { + ff = update_mm_wins(z, wcut, wcut_n, ocw, ql, (scn[wf]>max_n_chain_f)?1:0, 0.15, 16, focv, 0); + /** + if(scn[wf]>max_n_chain_f) { + fprintf(stderr, "-ssssss-[M::%s::i->%lu]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\ttype::%u\tsc::%u(%d)\tcn::%u(%lu)\tff%u\n", __func__, i, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, wf, osc[i], s[wf], ocn[i], chain_cutoff, ff); + ///-0-[M::gen_hc_r_alin_flt] focv::505, ave_cov_min::29, fcov_0::107, max_n_chain::215, wcut_n::51, ql::25729 + print_mm_wins(z, wcut, wcut_n, ocw, ql, focv); + } + **/ + /** + if(ff == 0) { + fprintf(stderr, "-ssssss-[M::%s::i->%lu]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\ttype::%u\tsc::%u(%d)\tcn::%u(%lu)\n", __func__, i, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, wf, osc[i], s[wf], ocn[i], chain_cutoff); + ///-0-[M::gen_hc_r_alin_flt] focv::505, ave_cov_min::29, fcov_0::107, max_n_chain::215, wcut_n::51, ql::25729 + print_mm_wins(z, wcut, wcut_n, ocw, ql, focv); + } + **/ + } + } else { + ff = 0; + } + + if(!ff) { + if(ocn[i] >= chain_cutoff) { + wsrt[wsrt_n++] = (((uint64_t)osc[i])<<32)|(i); + } + continue; + } + + scn[wf]++; + if (scn[wf] == max_n_chain) { + s[wf] = osc[i]; + } + + sca[wf]++; + + + if(!gen_hc_r_alin_flt_0(ol->list, i, a_cu, a_ci, idx_cu, cl, rref, qu, tu, exz, aux_o, bz, err, e_max, e_rate, w.window_length, ql, rid, khit, chem_drop, align_gap_rate, align_gap_max, hpf, buf, o_feature, &tot_b)) { + continue; + } + + z->is_match = 1; z->strong = z->without_large_indel = 0; + if(fc) update_mm_wins(z, wcut, wcut_n, ocw, ql, 0, 0.15, 16, 0, 1); + } + + if(fc && wsrt_n) { + t_cov0 = cal_mm_wins_cov(wcut, wcut_n, ocw, ql, fcov_0); + wsrt_n0 = wsrt_n; wsrt_n = 0; + for (tz = z_cov = 0; (tz < wsrt_n0) && (z_cov <= t_cov0); tz++) { + i = (uint32_t)wsrt[tz]; z = &(ol->list[i]); + assert(z->non_homopolymer_errors == UINT32_MAX); + assert(z->is_match == 0); + if(update_mm_wins(z, wcut, wcut_n, ocw, ql, 1, 0.15, 16, fcov_0, 0) == 0) { + wsrt[wsrt_n++] = (((uint64_t)osc[i])<<32)|(i); + continue; + } + + if(!gen_hc_r_alin_flt_0(ol->list, i, a_cu, a_ci, idx_cu, cl, rref, qu, tu, exz, aux_o, bz, err, e_max, e_rate, w.window_length, ql, rid, khit, chem_drop, align_gap_rate, align_gap_max, hpf, buf, o_feature, &z_cov)) { + continue; + } + + z->is_match = 1; z->strong = z->without_large_indel = 0; + if(fc) update_mm_wins(z, wcut, wcut_n, ocw, ql, 0, 0.15, 16, 0, 1); + } + fprintf(stderr, "-1-[M::%s] tot_b::%lu, z_cov::%lu, t_cov0::%lu, wsrt_n0::%lu, sca[0]::%u, sca[1]::%u, sca[2]::%u, sca[3]::%u, s[0]::%d, s[1]::%d, s[2]::%d, s[3]::%d\n", __func__, tot_b, z_cov, t_cov0, wsrt_n0, sca[0], sca[1], sca[2], sca[3], + s[0], s[1], s[2], s[3]); + tot_b += z_cov; + + } + + print_mm_wins_all(wcut, wcut_n, ocw, ql, 0); + print_mm_wins_all(wcut, wcut_n, ocw, ql, 1); + + if(wsrt_n && fc) { + refill_hc_r_alin_flt(ol, wsrt, wsrt_n); + } + /** + if((kp) && (kcnt < sec_aln_cov)) { + k = qick_realign(cl, ol->list, k, ol->length, sec_aln_cov, ql, sec_aln_win, kp, + rref, qu, tu, exz, aux_o, (((e_rate*sec_aln_err_rate)>sec_aln_max)?(sec_aln_max):(e_rate*sec_aln_err_rate)), wl, rid, khit, move_gap, buf, chem_drop, align_gap_rate, align_gap_max, hpf); + } + + // fprintf(stderr, "--[M::%s] window_length::%lld, err::%f\n", __func__, w.window_length, err); + + ol->length = k; + **/ + prt_chain_cluster(ol, cl, a_cu, a_ci, ocn, osc, idx_cu, n_cu, 1, o_feature); + fprintf(stderr, "-[M::%s]\tend\ttot_b::%lu\tql::%lu\tmax_n_chain::%lu\n", __func__, tot_b, ql, max_n_chain); + exit(1); + sp->n = spn0; + if(ol->length <= 0) return; +} + +uint8_t ww_match0(window_list *qwa, uint64_t qwn, uint32_t *tidx, uint32_t tn, overlap_region *oa, uint64_t *o_feature, uint32_t min_cut) +{ + if(!qwn) return 0; + uint32_t k, ti, qi, qs, qe, ts, te, twn, os, oe, qaln, taln, aln_n = 0; window_list *twa; + for (k = 0; k < tn; k++) { + twa = oa[tidx[k]].w_list.a + (o_feature[tidx[k]]>>32); + twn = ((uint32_t)o_feature[tidx[k]]); + if(!twn) continue; + qi = ti = aln_n = 0; + while (qi < qwn && ti < twn) { + for (; (qi < qwn) && (qwa[qi].x_end < twa[ti].x_start); qi++); + for (; (ti < twn) && (twa[ti].x_end < qwa[qi].x_start); ti++); + if((qi < qwn) && (ti < twn)) { + qs = qwa[qi].x_start; qe = qwa[qi].x_end + 1; + ts = twa[ti].x_start; te = twa[ti].x_end + 1; + ///must be overlapped + os = MAX(qs, ts); oe = MIN(qe, te); + + if((oe > os) && ((oe - os) >= min_cut)) { + qaln = is_aln_wst(qwa[qi]); + taln = is_aln_wst(twa[ti]); + if(qaln != taln) { + aln_n = 0; + break; + } + + if((qaln == taln) && (qaln == 1)) { + aln_n++; + } + } + } + } + + if(aln_n > 0) return 1; + } + return 0; +} + +/** +void hc_r_alin_refil(overlap_region_alloc* ol, Candidates_list *cl, uint32_t *a_cu, uint32_t *a_ci, uint32_t *ocn, uint32_t *osc, uint64_t *idx_cu, uint64_t n_cu, uint64_t *o_feature, uint64_t *srt_a, uint32_t wl) +{ + uint64_t k, i, wk, cs, ce, ws, we, oid, an[4], f; uint32_t *ixa = NULL, ixn, ixn1, m, qid, tid; uint32_t* ia[3]; + for (k = srt_n = 0; k < n_cu; k++) {///print + cs = (uint32_t)idx_cu[k]; ce = (uint32_t)idx_cu[k + 1]; + if(ce <= (cs + 1)) continue;///cluster of size 1 + // fprintf(stderr, "\n[M::%s]\t0st->n_clu::%lu\n", __func__, ce - cs); + ixa = a_cu + cs; ixn = ce - cs; + for (i = an[0] = an[1] = an[2] = an[3] = 0; i < ixn; i++) { + + if(ol->list[ixa[i]].is_match) { + if(an[0] != i) { + m = ixa[i]; ixa[i] = ixa[an[0]]; ixa[an[0]] = m; + } + an[0]++; + } + + if(ol->list[ixa[i]].is_match == 0) { + if((ol->list[ixa[i]].non_homopolymer_errors == UINT32_MAX-1)) {///failed in alignment, does not pass window alignment + ws = o_feature[oid]>>32; we = ws + ((uint32_t)o_feature[oid]); + for (wk = ws; (wk < we) && (!is_aln_wst(ol->list[ixa[i]].w_list.a[wk])); wk++); + if((we > ws) && (wk < we)) {///worth to rescue + if(an[1] != i) { + m = ixa[i]; ixa[i] = ixa[an[1]]; ixa[an[1]] = m; + } + an[1]++; + } + } + } + + if(ol->list[ixa[i]].is_match == 0) { + if(ol->list[ixa[i]].non_homopolymer_errors == UINT32_MAX) {///skipped, worth to rescue + if((an[2]) != i) { + m = ixa[i]; ixa[i] = ixa[an[2]]; ixa[an[2]] = m; + } + an[2]++; + } + } + + } + + ws = we = 0; an[3] = ixn; + we = an[0]; an[0] = an[0] - ws; ws = we; + we = an[1]; an[1] = an[1] - ws; ws = we; + we = an[2]; an[2] = an[2] - ws; ws = we; + we = an[3]; an[3] = an[3] - ws; ws = we; + if((an[0] <= 0) || ((an[1] <= 0) && (an[2] <= 0))) continue; + + ia[0] = ixa; ia[1] = ixa + an[0]; ia[2] = ixa + an[0] + an[1]; + if(an[1]) { + for (i = wk = 0; i < an[1]; i++) { + if(!ww_match0(ol->list[ia[1][i]].w_list.a + (o_feature[ia[1][i]]>>32), ((uint32_t)o_feature[ia[1][i]]), ia[0], an[0], ol->list, o_feature, MAX(16, wl))) continue; + if(wk != i) { + m = ia[1][i]; ia[1][i] = ia[1][wk]; ia[1][wk] = m; + } + wk++; + } + an[1] = wk; + } + + + + + // srt_a[srt_n]; + } +} +**/ + +///need to consider coverage, this information is missing right now (currently only use numbers) +void gen_hc_r_alin_adp(overlap_region_alloc* ol, Candidates_list *cl, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, overlap_region *aux_b, double e_rate, int64_t wl, int64_t rid, int64_t khit, int64_t move_gap, asg16_v* buf, uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max, uint64_t sec_aln_win, uint64_t sec_aln_cov, double sec_aln_err_rate, double sec_aln_max, + asg64_v *kp, asg64_v *sp, uint64_t ocw, uint8_t *hpf, uint32_t *a_cu, uint32_t *a_ci, uint32_t *ocn, uint32_t *osc, uint64_t *idx_cu, uint64_t n_cu, asg64_v *bp, uint64_t max_n_chain, uint64_t max_n_chain_f, uint64_t chain_cutoff, uint64_t ave_cov_min) +{ + uint64_t i, bs, /**k = 0,**/ ql = qu->length/**, ks = 0, ke = sec_aln_win, kcnt = sec_aln_cov**/, *wcut = NULL, wcut_n = 0, *wsrt = NULL, wsrt_n = 0, wsrt_n0, *o_feature = NULL, spn0 = 0, tz, tot_b = 0, t_cov0, z_cov, focv = 0, fcov_0 = 0, tot_b_cut = 0; Window_Pool w; double err, e_max; + overlap_region /**t,**/ *z, *bz = NULL; uint8_t fc = ((ol->length > max_n_chain)?(1):(0)), wf, ff; int32_t s[4]; s[0] = s[1] = s[2] = s[3] = 0; uint32_t scn[4], sca[4]; + scn[0] = scn[1] = scn[2] = scn[3] = sca[0] = sca[1] = sca[2] = sca[3] = 0; + + ol->mapped_overlaps_length = 0; + if(ol->length <= 0 || ql <= 0) return; + + // prt_chain_cluster(ol, cl, a_cu, a_ci, ocn, osc, idx_cu, n_cu, 0, NULL); + + ///base alignment + err = e_rate; e_max = err * 1.5; + init_Window_Pool(&w, ql, wl, (int)(1.0/err)); + bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(tu, bs<<1); + + spn0 = sp->n; sp->n += ol->length + ol->length; + kv_resize(uint64_t, (*sp), sp->n); + wsrt = sp->a + spn0; o_feature = sp->a + spn0 + ol->length; + if(fc) { + wcut = infer_chn_bar_0(ol, max_n_chain, /**chain_cutoff,**/ ocn, osc, ql, ocw, s, sp, &wcut_n, &focv); + if ((s[0] <= 0) && (s[1] <= 0) && (s[2] <= 0) && (s[3] <= 0)) fc = 0; + wsrt = sp->a + spn0; o_feature = sp->a + spn0 + ol->length; + + focv = focv/ql; if(focv < 0) focv = 1; focv *= 1.05; + if(focv < ave_cov_min) focv = ave_cov_min; + // if(focv > ave_cov_max) focv = ave_cov_max; + // fcov_0 = max_n_chain>>1; if(fcov_0 > focv) fcov_0 = focv; + fcov_0 = max_n_chain>>1; + + tot_b_cut = max_n_chain>>1; tot_b_cut *= ql; + + bz = aux_b; + } + + fprintf(stderr, "-0-[M::%s] focv::%lu, ave_cov_min::%lu, fcov_0::%lu, max_n_chain::%lu, wcut_n::%lu, ql::%lu\n", __func__, focv, ave_cov_min, fcov_0, max_n_chain, wcut_n, ql); + + ////this is very important!!! main issues coming from uneven read length, some short reads may have too many chains need to be calculated? + ///a-0, more important) use the best alignment overlap, to estimate the chain cuttoff and which minimizer may have higher weights + ///a) if the chain score is equal to s[wf] and it is not in a large cluster, avoid to perform alignment + ///b) after the first round of alignment, calculate how many chains are aligned/unaligned as the weight to valludate the reamining chains with not high scores + ///c) if wcut[h] and wcut[l] have already collected enough aligned chains, we can discard a cluster together, if one or a part (10%?) of them are unaligned, or with very high difference rate + ///d) need to record overlaps in each round, and then use them for next round, avoiding missing real overlaps + s[0] = s[1] = s[2] = s[3] = 0;///reset it + for (i = wsrt_n = 0; i < ol->length; i++) {///primary chain + z = &(ol->list[i]); z->is_match = 0; + z->shared_seed = z->non_homopolymer_errors; + z->non_homopolymer_errors = UINT32_MAX;///for index + + wf = ha_ov_type(z, ql); ff = 1; o_feature[i] = 0; + + if((ocn[i] >= chain_cutoff) && ((scn[wf] <= max_n_chain) || ((scn[wf] <= (max_n_chain<<1)) && (((int64_t)osc[i]) == s[wf])))) { + if(fc) { + ff = update_mm_wins(z, wcut, wcut_n, ocw, ql, (scn[wf]>max_n_chain_f)?1:0, 0.15, 16, focv, 0); + } + } else { + ff = 0; + } + + if(!ff) { + if(ocn[i] >= chain_cutoff) { + wsrt[wsrt_n++] = (((uint64_t)osc[i])<<32)|(i); + } + continue; + } + + scn[wf]++; + if (scn[wf] == max_n_chain) { + s[wf] = osc[i]; + } + + sca[wf]++; + + + if(!gen_hc_r_alin_flt_1(ol->list, i, cl, rref, qu, tu, exz, aux_o, bz, err, e_max, e_rate, w.window_length, ql, rid, khit, chem_drop, align_gap_rate, align_gap_max, hpf, buf, o_feature, &tot_b)) { + continue; + } + + z->is_match = 1; z->strong = z->without_large_indel = 0; + if(fc) update_mm_wins(z, wcut, wcut_n, ocw, ql, 0, 0.15, 16, 0, 1); + } + + if(fc && wsrt_n) { + t_cov0 = cal_mm_wins_cov(wcut, wcut_n, ocw, ql, fcov_0); + wsrt_n0 = wsrt_n; wsrt_n = 0; + for (tz = z_cov = 0; (tz < wsrt_n0) && (z_cov <= t_cov0); tz++) { + i = (uint32_t)wsrt[tz]; z = &(ol->list[i]); + assert(z->non_homopolymer_errors == UINT32_MAX); + assert(z->is_match == 0); + if(update_mm_wins(z, wcut, wcut_n, ocw, ql, 1, 0.15, 16, fcov_0, 0) == 0) { + wsrt[wsrt_n++] = (((uint64_t)osc[i])<<32)|(i); + continue; + } + + if(!gen_hc_r_alin_flt_1(ol->list, i, cl, rref, qu, tu, exz, aux_o, bz, err, e_max, e_rate, w.window_length, ql, rid, khit, chem_drop, align_gap_rate, align_gap_max, hpf, buf, o_feature, &z_cov)) { + continue; + } + + z->is_match = 1; z->strong = z->without_large_indel = 0; + if(fc) update_mm_wins(z, wcut, wcut_n, ocw, ql, 0, 0.15, 16, 0, 1); + } + fprintf(stderr, "-1-[M::%s] tot_b::%lu, z_cov::%lu, t_cov0::%lu, wsrt_n0::%lu, sca[0]::%u, sca[1]::%u, sca[2]::%u, sca[3]::%u, s[0]::%d, s[1]::%d, s[2]::%d, s[3]::%d\n", __func__, tot_b, z_cov, t_cov0, wsrt_n0, sca[0], sca[1], sca[2], sca[3], + s[0], s[1], s[2], s[3]); + tot_b += z_cov; + + } + + if(fc) { + // hc_r_alin_refil(ol, cl, a_cu, a_ci, ocn, osc, idx_cu, n_cu, o_feature, wsrt, wl); + } + + // print_mm_wins_all(wcut, wcut_n, ocw, ql, 0); + // print_mm_wins_all(wcut, wcut_n, ocw, ql, 1); + + if(wsrt_n && fc) { + // refill_hc_r_alin_flt(ol, wsrt, wsrt_n); + } + /** + if((kp) && (kcnt < sec_aln_cov)) { + k = qick_realign(cl, ol->list, k, ol->length, sec_aln_cov, ql, sec_aln_win, kp, + rref, qu, tu, exz, aux_o, (((e_rate*sec_aln_err_rate)>sec_aln_max)?(sec_aln_max):(e_rate*sec_aln_err_rate)), wl, rid, khit, move_gap, buf, chem_drop, align_gap_rate, align_gap_max, hpf); + } + + // fprintf(stderr, "--[M::%s] window_length::%lld, err::%f\n", __func__, w.window_length, err); + + ol->length = k; + **/ + // prt_chain_cluster(ol, cl, a_cu, a_ci, ocn, osc, idx_cu, n_cu, 1, o_feature); + fprintf(stderr, "-[M::%s]\tend\ttot_b::%lu\tql::%lu\tmax_n_chain::%lu\n", __func__, tot_b, ql, max_n_chain); + exit(1); + sp->n = spn0; + if(ol->length <= 0) return; +} + + +void gen_hc_aln_small_chn_smp(overlap_region_alloc* ol, Candidates_list *cl, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, + double err, double e_max, double e_rate, int64_t wsl, int64_t ql, int64_t rid, int64_t khit, uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max, uint8_t *hpf, asg16_v *buf, uint64_t *tot_b, + uint64_t *wcut, uint64_t wcut_n, uint64_t ocw, uint64_t *srt_a, uint64_t i_srt_n, uint32_t *ocn, uint32_t *osc, uint64_t chain_cutoff, uint64_t ch_occ, uint64_t ch_sc) +{ + // if(!((i_srt_n > 0) && (i_srt_n <= ol->length))) { + // fprintf(stderr, "-1-[M::%s] (*i_srt_n)::%lu, ol->length::%lu\n", __func__, + // i_srt_n, ol->length); + // } + + assert((i_srt_n > 0) && (i_srt_n <= ol->length)); + // uint64_t ch_occ = 4, ch_sc = 16; + uint64_t k, m, s, e, ak, *srt_b = srt_a + i_srt_n, srt_ba = 0, bk, ncut = chain_cutoff*ch_occ; + for (k = s = bk = ak = 0; k < i_srt_n; k++) { + e = (uint32_t)srt_a[k]; + assert(s <= e); + for (m = s; m < e; m++){ + // if(!(ol->list[m].non_homopolymer_errors != UINT32_MAX)) { + // fprintf(stderr, "[M::%s::oid->%lu]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, m, ol->list[m].x_id, + // ol->list[m].y_id, (int)Get_NAME_LENGTH(R_INF, ol->list[m].y_id), Get_NAME(R_INF, ol->list[m].y_id), + // ol->list[m].x_pos_s, ol->list[m].x_pos_e + 1, ol->list[m].y_pos_s, ol->list[m].y_pos_e + 1, + // osc[m], ocn[m], ol->list[m].is_match, ol->list[m].non_homopolymer_errors); + // } + assert(ol->list[m].non_homopolymer_errors != UINT32_MAX); + if(ocn[m] < ncut) continue; + srt_b[bk] = ol->list[m].x_pos_s; + srt_b[bk] <<= 32; srt_b[bk] |= m; bk++; + } + srt_ba += e - s; + s = e + 1; + if((srt_a[k]>>32) == ((uint32_t)-1)) { + m = e; + srt_a[ak] = ol->list[m].x_pos_s; + srt_a[ak] <<= 32; srt_a[ak] |= m; ak++; + } + } + + e = ol->length; + assert(s <= e); + for (m = s; m < e; m++){ + // if(!(ol->list[m].non_homopolymer_errors != UINT32_MAX)) { + // fprintf(stderr, "[M::%s::oid->%lu]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, m, ol->list[m].x_id, + // ol->list[m].y_id, (int)Get_NAME_LENGTH(R_INF, ol->list[m].y_id), Get_NAME(R_INF, ol->list[m].y_id), + // ol->list[m].x_pos_s, ol->list[m].x_pos_e + 1, ol->list[m].y_pos_s, ol->list[m].y_pos_e + 1, + // osc[m], ocn[m], ol->list[m].is_match, ol->list[m].non_homopolymer_errors); + // } + assert(ol->list[m].non_homopolymer_errors != UINT32_MAX); + if(ocn[m] < ncut) continue; + srt_b[bk] = ol->list[m].x_pos_s; + srt_b[bk] <<= 32; srt_b[bk] |= m; bk++; + } + srt_ba += e - s; + + assert(srt_ba + i_srt_n == ol->length); + assert(ak > 0); + + radix_sort_bc64(srt_a, srt_a+ak); + radix_sort_bc64(srt_b, srt_b+bk); + + // fprintf(stderr, "-1-[M::%s] srt_ba::%lu, (*i_srt_n)::%lu, ol->length::%lu, ak::%lu, bk::%lu, ncut::%lu\n", __func__, + // srt_ba, i_srt_n, ol->length, ak, bk, ncut); + + uint64_t zs, ze, ob, zsc, zcn, rs, re, os, oe, oi, rr, kn, cs, ce, cn = cl->length; uint8_t f; overlap_region *zm, *rm; + for (m = 0; m < ak; m++) { + zm = &(ol->list[(uint32_t)srt_a[m]]); + zs = zm->x_pos_s; ze = zm->x_pos_e + 1; + ob = (ze - zs)*0.95; if(ob < 16) ob = 16; + zsc = osc[(uint32_t)srt_a[m]]*ch_sc; + zcn = ocn[(uint32_t)srt_a[m]]*ch_occ; + + // fprintf(stderr, "\n[M::%s::zm::oid->%u]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, (uint32_t)srt_a[m], + // zm->y_id, (int)Get_NAME_LENGTH(R_INF, zm->y_id), Get_NAME(R_INF, zm->y_id), + // zm->x_pos_s, zm->x_pos_e + 1, zm->y_pos_s, zm->y_pos_e + 1, + // osc[(uint32_t)srt_a[m]], ocn[(uint32_t)srt_a[m]], zm->is_match, zm->non_homopolymer_errors); + + for (k = f = 0; (k < bk) && (ze > ol->list[(uint32_t)srt_b[k]].x_pos_s); k++) { + rm = &(ol->list[(uint32_t)srt_b[k]]); + // fprintf(stderr, "[M::%s::rm::oid->%u]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, (uint32_t)srt_b[k], + // rm->y_id, (int)Get_NAME_LENGTH(R_INF, rm->y_id), Get_NAME(R_INF, rm->y_id), + // rm->x_pos_s, rm->x_pos_e + 1, rm->y_pos_s, rm->y_pos_e + 1, + // osc[(uint32_t)srt_b[k]], ocn[(uint32_t)srt_b[k]], rm->is_match, rm->non_homopolymer_errors); + if(osc[(uint32_t)srt_b[k]] < zsc) continue; + if(ocn[(uint32_t)srt_b[k]] < zcn) continue; + rs = rm->x_pos_s; re = rm->x_pos_e + 1; + os = ((rs>=zs)?rs:zs); oe = ((re<=ze)?re:ze); + if((oe > os) && (oe - os) >= ob) { + oi = rm->shared_seed; rr = cl->list[oi].readID; kn = 0; + for (; (oi < cn) && (cl->list[oi].readID == rr) && (kn < zcn); oi++) { + ce = cl->list[oi].self_offset; cs = ce - (cl->list[oi].cnt&(0xffu)); + if((cs >= os) && (ce <= oe)) kn++; + // fprintf(stderr, "[M::%s::rm::oid->%u]\tcs::%lu\tce::%lu\tos::%lu\toe::%lu\tkn::%lu\n", __func__, (uint32_t)srt_b[k], cs, ce, os, oe, kn); + } + if(kn >= zcn) { + f = 1; break; + } + } + } + // fprintf(stderr, "[M::%s::zm::oid->%u]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\tf::%u\n", __func__, (uint32_t)srt_a[m], + // zm->y_id, (int)Get_NAME_LENGTH(R_INF, zm->y_id), Get_NAME(R_INF, zm->y_id), + // zm->x_pos_s, zm->x_pos_e + 1, zm->y_pos_s, zm->y_pos_e + 1, + // osc[(uint32_t)srt_a[m]], ocn[(uint32_t)srt_a[m]], zm->is_match, zm->non_homopolymer_errors, f); + if(f) continue; + + if(!gen_hc_r_alin_flt_1_smp(zm, cl, rref, qu, tu, exz, aux_o, err, e_max, e_rate, wsl, ql, rid, khit, chem_drop, align_gap_rate, align_gap_max, hpf, buf, tot_b)) { + continue; + } + + zm->is_match = 1; zm->strong = zm->without_large_indel = 0; + if(wcut) update_mm_wins(zm, wcut, wcut_n, ocw, ql, 0, 0.15, 16, 0, 1); + } + +} + + +void gen_hc_aln_small_chn_smp_adv(gen_hc_aln_t *ez, uint64_t ql, uint32_t *a_cu, uint32_t *a_ci, uint32_t *ocn, uint32_t *osc, uint64_t *idx_cu, uint64_t n_cu, + uint64_t *wcut, uint64_t wcut_n, uint64_t *tot_b, uint64_t *srt_a, uint64_t i_srt_n, uint64_t ch_occ, uint64_t ch_sc) +{ + // if(!((i_srt_n > 0) && (i_srt_n <= ol->length))) { + // fprintf(stderr, "-1-[M::%s] (*i_srt_n)::%lu, ol->length::%lu\n", __func__, + // i_srt_n, ol->length); + // } + + assert((i_srt_n > 0) && (i_srt_n <= ez->ol->length)); + // uint64_t ch_occ = 4, ch_sc = 16; + uint64_t k, m, s, e, ak, *srt_b = srt_a + i_srt_n, srt_ba = 0, bk, ncut = ez->chain_cutoff*ch_occ; + for (k = s = bk = ak = 0; k < i_srt_n; k++) { + e = (uint32_t)srt_a[k]; + assert(s <= e); + // fprintf(stderr, "[M::%s::]\ts::%lu\te::%lu\tk::%lu\n", __func__, s, e, k); + + for (m = s; m < e; m++){ + // if(!(ez->ol->list[m].non_homopolymer_errors != UINT32_MAX)) { + // fprintf(stderr, "[M::%s::oid->%lu]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\ts::%lu\te::%lu\tk::%lu\n", __func__, m, ez->ol->list[m].x_id, + // ez->ol->list[m].y_id, (int)Get_NAME_LENGTH(R_INF, ez->ol->list[m].y_id), Get_NAME(R_INF, ez->ol->list[m].y_id), + // ez->ol->list[m].x_pos_s, ez->ol->list[m].x_pos_e + 1, ez->ol->list[m].y_pos_s, ez->ol->list[m].y_pos_e + 1, + // osc[m], ocn[m], ez->ol->list[m].is_match, ez->ol->list[m].non_homopolymer_errors, s, e, k); + // } + assert(ez->ol->list[m].non_homopolymer_errors != UINT32_MAX); + if(ocn[m] < ncut) continue; + srt_b[bk] = ez->ol->list[m].x_pos_s; + srt_b[bk] <<= 32; srt_b[bk] |= m; bk++; + } + srt_ba += e - s; + s = e + 1; + if((srt_a[k]>>32) == ((uint32_t)-1)) { + m = e; + srt_a[ak] = ez->ol->list[m].x_pos_s; + srt_a[ak] <<= 32; srt_a[ak] |= m; ak++; + } + } + + e = ez->ol->length; + assert(s <= e); + for (m = s; m < e; m++){ + assert(ez->ol->list[m].non_homopolymer_errors != UINT32_MAX); + if(ocn[m] < ncut) continue; + srt_b[bk] = ez->ol->list[m].x_pos_s; + srt_b[bk] <<= 32; srt_b[bk] |= m; bk++; + } + srt_ba += e - s; + + assert(srt_ba + i_srt_n == ez->ol->length); + assert(ak > 0); + + radix_sort_bc64(srt_a, srt_a+ak); + radix_sort_bc64(srt_b, srt_b+bk); + + // fprintf(stderr, "-1-[M::%s] srt_ba::%lu, (*i_srt_n)::%lu, ol->length::%lu, ak::%lu, bk::%lu, ncut::%lu\n", __func__, + // srt_ba, i_srt_n, ol->length, ak, bk, ncut); + + uint64_t zs, ze, ob, zsc, zcn, rs, re, os, oe, oi, rr, kn, cs, ce, cn = ez->cl->length, w; uint8_t f; overlap_region *zm, *rm; + double err, e_max, align_gap_max, align_gap_rate, chem_drop; + for (m = 0; m < ak; m++) { + zm = &(ez->ol->list[(uint32_t)srt_a[m]]); + zs = zm->x_pos_s; ze = zm->x_pos_e + 1; + ob = (ze - zs)*0.95; if(ob < 16) ob = 16; + zsc = osc[(uint32_t)srt_a[m]]*ch_sc; + zcn = ocn[(uint32_t)srt_a[m]]*ch_occ; + + // fprintf(stderr, "\n[M::%s::zm::oid->%u]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, (uint32_t)srt_a[m], + // zm->y_id, (int)Get_NAME_LENGTH(R_INF, zm->y_id), Get_NAME(R_INF, zm->y_id), + // zm->x_pos_s, zm->x_pos_e + 1, zm->y_pos_s, zm->y_pos_e + 1, + // osc[(uint32_t)srt_a[m]], ocn[(uint32_t)srt_a[m]], zm->is_match, zm->non_homopolymer_errors); + + for (k = f = 0; (k < bk) && (ze > ez->ol->list[(uint32_t)srt_b[k]].x_pos_s); k++) { + rm = &(ez->ol->list[(uint32_t)srt_b[k]]); + // fprintf(stderr, "[M::%s::rm::oid->%u]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, (uint32_t)srt_b[k], + // rm->y_id, (int)Get_NAME_LENGTH(R_INF, rm->y_id), Get_NAME(R_INF, rm->y_id), + // rm->x_pos_s, rm->x_pos_e + 1, rm->y_pos_s, rm->y_pos_e + 1, + // osc[(uint32_t)srt_b[k]], ocn[(uint32_t)srt_b[k]], rm->is_match, rm->non_homopolymer_errors); + if(osc[(uint32_t)srt_b[k]] < zsc) continue; + if(ocn[(uint32_t)srt_b[k]] < zcn) continue; + rs = rm->x_pos_s; re = rm->x_pos_e + 1; + os = ((rs>=zs)?rs:zs); oe = ((re<=ze)?re:ze); + if((oe > os) && (oe - os) >= ob) { + oi = rm->shared_seed; rr = ez->cl->list[oi].readID; kn = 0; + for (; (oi < cn) && (ez->cl->list[oi].readID == rr) && (kn < zcn); oi++) { + ce = ez->cl->list[oi].self_offset; cs = ce - (ez->cl->list[oi].cnt&(0xffu)); + if((cs >= os) && (ce <= oe)) kn++; + // fprintf(stderr, "[M::%s::rm::oid->%u]\tcs::%lu\tce::%lu\tos::%lu\toe::%lu\tkn::%lu\n", __func__, (uint32_t)srt_b[k], cs, ce, os, oe, kn); + } + if(kn >= zcn) { + f = 1; break; + } + } + } + // fprintf(stderr, "[M::%s::zm::oid->%u]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\tf::%u\n", __func__, (uint32_t)srt_a[m], + // zm->y_id, (int)Get_NAME_LENGTH(R_INF, zm->y_id), Get_NAME(R_INF, zm->y_id), + // zm->x_pos_s, zm->x_pos_e + 1, zm->y_pos_s, zm->y_pos_e + 1, + // osc[(uint32_t)srt_a[m]], ocn[(uint32_t)srt_a[m]], zm->is_match, zm->non_homopolymer_errors, f); + if(f) continue; + + if(zm->y_id < ez->t_cut) { + err = ez->e_rate[1]; w = ez->wl[1]; align_gap_max = ez->align_gap_max[1]; align_gap_rate = ez->align_gap_rate[1]; chem_drop = ez->chem_drop[1]; + } else { + err = ez->e_rate[0]; w = ez->wl[0]; align_gap_max = ez->align_gap_max[0]; align_gap_rate = ez->align_gap_rate[0]; chem_drop = ez->chem_drop[0]; + } + e_max = err * 1.5; + + if(!gen_hc_r_alin_flt_1_smp(zm, ez->cl, ez->rref, ez->qu, ez->tu, ez->exz, ez->aux_o, err, e_max, err, w, ql, ez->rid, ez->khit, chem_drop, align_gap_rate, align_gap_max, ez->hpz->a, ez->buf, tot_b)) { + continue; + } + + zm->is_match = 1; zm->strong = zm->without_large_indel = 0; + if(wcut) update_mm_wins(zm, wcut, wcut_n, ez->ocw, ql, 0, 0.15, 16, 0, 1); + } + +} + + +uint64_t rescue_cu_aln(overlap_region_alloc* ol, Candidates_list *cl, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, + double err, double e_max, double e_rate, int64_t wsl, int64_t ql, int64_t rid, int64_t khit, uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max, uint8_t *hpf, asg16_v *buf, + uint64_t *wcut, uint64_t wcut_n, uint64_t ocw, uint64_t *srt_a, uint32_t *a_cu, uint32_t *a_ci, uint64_t *idx_cu, uint64_t n_cu, uint64_t tot_b_cut) +{ + uint64_t k, cs, ce, i, oid, an[2], tn = 0, zcov = 0; overlap_region *z; + for (k = 0; k < n_cu; k++) {///print + cs = (uint32_t)idx_cu[k]; ce = (uint32_t)idx_cu[k + 1]; + an[0] = an[1] = 0; + for (i = cs; i < ce; i++) { + oid = a_cu[i]; z = &(ol->list[oid]); + if(z->is_match == 1) { + an[0]++; + } else if(z->non_homopolymer_errors == UINT32_MAX) { + an[1]++; + } + } + if(an[1] == 0 || an[0] == 0) continue; + + for (i = cs; i < ce; i++) { + oid = a_cu[i]; z = &(ol->list[oid]); + if((z->is_match == 0) && (z->non_homopolymer_errors == UINT32_MAX)) { + // fprintf(stderr, "\ncid::%lu[M::%s::zm::oid->%lu]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tan[0]::%lu\tan[1]::%lu\tis_match::%u\terr::%u\n", k, __func__, oid, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // an[0], an[1], z->is_match, z->non_homopolymer_errors); + srt_a[tn] = ((uint32_t)-1) - an[0]; srt_a[tn] <<= 32; srt_a[tn] |= oid; tn++; + } + } + } + if(tn <= 0) return zcov; + + radix_sort_bc64(srt_a, srt_a + tn); + for (k = zcov = 0; (k < tn) && (zcov <= tot_b_cut); k++) { + oid = ((uint32_t)srt_a[k]); + z = &(ol->list[oid]); + + // fprintf(stderr, "\n-1-[M::%s::zm::oid->%lu]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tan[0]::%lu\tis_match::%u\terr::%u\tzcov::%lu\ttot_b_cut::%lu\n", __func__, oid, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // ((uint32_t)-1) - (srt_a[k]>>32), z->is_match, z->non_homopolymer_errors, zcov, tot_b_cut); + + if(!gen_hc_r_alin_flt_1_smp(z, cl, rref, qu, tu, exz, aux_o, err, e_max, e_rate, wsl, ql, rid, khit, chem_drop, align_gap_rate, align_gap_max, hpf, buf, &zcov)) { + continue; + } + + z->is_match = 1; z->strong = z->without_large_indel = 0; + if(wcut) update_mm_wins(z, wcut, wcut_n, ocw, ql, 0, 0.15, 16, 0, 1); + } + + return zcov; +} + + +void rescue_cu_aln_adv(gen_hc_aln_t *ez, int64_t ql, uint64_t *wcut, uint64_t wcut_n, uint64_t *srt_a, uint32_t *a_cu, uint32_t *a_ci, uint64_t *idx_cu, uint64_t n_cu, uint64_t tot_b_cut) +{ + uint64_t k, cs, ce, i, oid, an[2], tn = 0, zcov = 0, w; overlap_region *z; double err, e_max, align_gap_max, align_gap_rate, chem_drop; + for (k = 0; k < n_cu; k++) {///print + cs = (uint32_t)idx_cu[k]; ce = (uint32_t)idx_cu[k + 1]; + an[0] = an[1] = 0; + for (i = cs; i < ce; i++) { + oid = a_cu[i]; z = &(ez->ol->list[oid]); + if(z->is_match == 1) { + an[0]++; + } else if(z->non_homopolymer_errors == UINT32_MAX) { + an[1]++; + } + } + if(an[1] == 0 || an[0] == 0) continue; + + for (i = cs; i < ce; i++) { + oid = a_cu[i]; z = &(ez->ol->list[oid]); + if((z->is_match == 0) && (z->non_homopolymer_errors == UINT32_MAX)) { + // fprintf(stderr, "\ncid::%lu[M::%s::zm::oid->%lu]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tan[0]::%lu\tan[1]::%lu\tis_match::%u\terr::%u\n", k, __func__, oid, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // an[0], an[1], z->is_match, z->non_homopolymer_errors); + srt_a[tn] = ((uint32_t)-1) - an[0]; srt_a[tn] <<= 32; srt_a[tn] |= oid; tn++; + } + } + } + if(tn <= 0) return; + + radix_sort_bc64(srt_a, srt_a + tn); + for (k = zcov = 0; (k < tn) && (zcov <= tot_b_cut); k++) { + oid = ((uint32_t)srt_a[k]); + z = &(ez->ol->list[oid]); + + // fprintf(stderr, "\n-1-[M::%s::zm::oid->%lu]\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tan[0]::%lu\tis_match::%u\terr::%u\tzcov::%lu\ttot_b_cut::%lu\n", __func__, oid, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // ((uint32_t)-1) - (srt_a[k]>>32), z->is_match, z->non_homopolymer_errors, zcov, tot_b_cut); + + if(z->y_id < ez->t_cut) { + err = ez->e_rate[1]; w = ez->wl[1]; align_gap_max = ez->align_gap_max[1]; align_gap_rate = ez->align_gap_rate[1]; chem_drop = ez->chem_drop[1]; + } else { + err = ez->e_rate[0]; w = ez->wl[0]; align_gap_max = ez->align_gap_max[0]; align_gap_rate = ez->align_gap_rate[0]; chem_drop = ez->chem_drop[0]; + } + e_max = err * 1.5; + + if(!gen_hc_r_alin_flt_1_smp(z, ez->cl, ez->rref, ez->qu, ez->tu, ez->exz, ez->aux_o, err, e_max, err, w, ql, ez->rid, ez->khit, chem_drop, align_gap_rate, align_gap_max, ez->hpz->a, ez->buf, &zcov)) { + continue; + } + + z->is_match = 1; z->strong = z->without_large_indel = 0; + if(wcut) update_mm_wins(z, wcut, wcut_n, ez->ocw, ql, 0, 0.15, 16, 0, 1); + } +} + + + +///need to consider coverage, this information is missing right now (currently only use numbers) +void gen_hc_r_alin_adp_smp(overlap_region_alloc* ol, Candidates_list *cl, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t wl, int64_t rid, int64_t khit, int64_t move_gap, asg16_v* buf, uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max, uint64_t sec_aln_win, uint64_t sec_aln_cov, double sec_aln_err_rate, double sec_aln_max, + asg64_v *sp, uint64_t ocw, uint8_t *hpf, uint32_t *a_cu, uint32_t *a_ci, uint32_t *ocn, uint32_t *osc, uint64_t *idx_cu, uint64_t n_cu, asg64_v *bp, uint64_t max_n_chain, uint64_t max_n_chain_f, uint64_t chain_cutoff, uint64_t ave_cov_min, uint8_t set_match) +{ + uint64_t i, k, bs, ql = qu->length, *wcut = NULL, wcut_n = 0, *wsrt = NULL, wsrt_n = 0, lch = 0, wsrt_n0, spn0 = 0, tz, tot_b = 0, t_cov0, z_cov, focv = 0, fcov_0 = 0, rescue_b_cut = 0; Window_Pool w; double err, e_max; + overlap_region *z, t; uint8_t fc = (((ol->length > max_n_chain) && (n_cu > 0))?(1):(0)), wf, ff; int32_t s[4]; s[0] = s[1] = s[2] = s[3] = 0; uint32_t scn[4]; + scn[0] = scn[1] = scn[2] = scn[3] = 0; + + ol->mapped_overlaps_length = 0; + if(ol->length <= 0 || ql <= 0) return; + + // prt_chain_cluster(ol, cl, a_cu, a_ci, ocn, osc, idx_cu, n_cu, 0, NULL); + + ///base alignment + err = e_rate; e_max = err * 1.5; + init_Window_Pool(&w, ql, wl, (int)(1.0/err)); + bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(tu, bs<<1); + + spn0 = sp->n; sp->n += ol->length + ol->length; + kv_resize(uint64_t, (*sp), sp->n); + wsrt = sp->a + spn0; + if(fc) { + wcut = infer_chn_bar_0(ol, max_n_chain, ocn, osc, ql, ocw, s, sp, &wcut_n, &focv); + if ((s[0] <= 0) && (s[1] <= 0) && (s[2] <= 0) && (s[3] <= 0)) fc = 0; + wsrt = sp->a + spn0; + + focv = focv/ql; if(focv < 0) focv = 1; focv *= 1.05; + if(focv < ave_cov_min) focv = ave_cov_min; + if(focv > (max_n_chain<<1)) focv = max_n_chain<<1; + // if(focv > ave_cov_max) focv = ave_cov_max; + // fcov_0 = max_n_chain>>1; if(fcov_0 > focv) fcov_0 = focv; + fcov_0 = max_n_chain>>1; + + // rescue_b_cut = (fcov_0>>1)*ql; + rescue_b_cut = (fcov_0*0.75)*ql; + } + + + // fprintf(stderr, "-0-[M::%s] focv::%lu, ave_cov_min::%lu, fcov_0::%lu, max_n_chain::%lu, wcut_n::%lu, ql::%lu, chain_cutoff::%lu\n", __func__, focv, ave_cov_min, fcov_0, max_n_chain, wcut_n, ql, chain_cutoff); + + ////this is very important!!! main issues coming from uneven read length, some short reads may have too many chains need to be calculated? + ///a-0, more important) use the best alignment overlap, to estimate the chain cuttoff and which minimizer may have higher weights + ///a) if the chain score is equal to s[wf] and it is not in a large cluster, avoid to perform alignment + ///b) after the first round of alignment, calculate how many chains are aligned/unaligned as the weight to valludate the reamining chains with not high scores + ///c) if wcut[h] and wcut[l] have already collected enough aligned chains, we can discard a cluster together, if one or a part (10%?) of them are unaligned, or with very high difference rate + ///d) need to record overlaps in each round, and then use them for next round, avoiding missing real overlaps + s[0] = s[1] = s[2] = s[3] = 0;///reset it + for (i = wsrt_n = 0; i < ol->length; i++) {///primary chain + z = &(ol->list[i]); + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-0-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + // } + if(set_match) { + z->is_match = 0; + } + + if(z->is_match == 0) { + z->shared_seed = z->non_homopolymer_errors; + z->non_homopolymer_errors = UINT32_MAX;///for index + } + + wf = ha_ov_type(z, ql); ff = 1; + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-1-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + // } + + if(fc) { + if(((scn[wf] <= max_n_chain) || ((scn[wf] <= (max_n_chain<<1)) && (((int64_t)osc[i]) == s[wf])) || (z->is_match == 1))) { + ff = update_mm_wins(z, wcut, wcut_n, ocw, ql, ((scn[wf]>max_n_chain_f) && (z->is_match == 0))?1:0, 0.15, 16, focv, 0); + } else { + ff = 0; + } + } + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-2-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + // } + + + if((!ff) && (z->is_match == 0)) {///fitered out due to coverage + wsrt[wsrt_n++] = (((uint64_t)osc[i])<<32)|(i); + continue; + } + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-3-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\tff::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors, ff); + // } + + scn[wf]++; + if (scn[wf] == max_n_chain) { + s[wf] = osc[i]; + } + + if((ocn[i] < chain_cutoff) && (z->is_match == 0)) {///fitered out due to no enough minimizers + lch = 1; + wsrt[wsrt_n++] = (((uint64_t)-1)<<32)|(i); + continue; + } + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-4-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + // } + + + if((z->is_match == 0) && (!gen_hc_r_alin_flt_1_smp(&(ol->list[i]), cl, rref, qu, tu, exz, aux_o, err, e_max, e_rate, w.window_length, ql, rid, khit, chem_drop, align_gap_rate, align_gap_max, hpf, buf, &tot_b))) { + continue; + } + + // if(z->x_id == 142 && z->y_id == 207) { + // fprintf(stderr, "-5-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + // } + + z->is_match = 1; z->strong = z->without_large_indel = 0; + if(fc) update_mm_wins(z, wcut, wcut_n, ocw, ql, 0, 0.15, 16, 0, 1); + } + + // fprintf(stderr, "[M::%s] wsrt_n::%lu, fc::%u, ez->ol->length::%lu, ez->max_n_chain::%lu, n_cu::%lu\n", __func__, wsrt_n, fc, ol->length, max_n_chain, n_cu); + // for (i = 0; i < wsrt_n; i++) { + // z = &(ol->list[(uint32_t)wsrt[i]]); + // fprintf(stderr, "[M::%s::i->%lu]\tqid::%u\ttid::%u\t%.*s\toid::%u\tsc::%lu\n", __func__, i, + // z->x_id, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // (uint32_t)wsrt[i], wsrt[i]>>32); + // } + + if(fc && wsrt_n) { + t_cov0 = cal_mm_wins_cov(wcut, wcut_n, ocw, ql, fcov_0); + + wsrt_n0 = wsrt_n; wsrt_n = 0; lch = 0; + for (tz = z_cov = 0; (tz < wsrt_n0) && (z_cov <= t_cov0); tz++) { + i = (uint32_t)wsrt[tz]; z = &(ol->list[i]); + assert(z->non_homopolymer_errors == UINT32_MAX); + assert(z->is_match == 0); + + // fprintf(stderr, "-a-[M::%s::tz->%lu::i->%lu]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, tz, i, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + + if((wsrt[tz]>>32) == ((uint32_t)-1)) {///fitered out due to no enough minimizers + lch = 1; wsrt[wsrt_n++] = (((uint64_t)-1)<<32)|(i); + continue; + } + + // fprintf(stderr, "-b-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + + if(update_mm_wins(z, wcut, wcut_n, ocw, ql, 1, 0.15, 16, fcov_0, 0) == 0) { + wsrt[wsrt_n++] = (((uint64_t)osc[i])<<32)|(i); + continue; + } + + // fprintf(stderr, "-c-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + + if(ocn[i] < chain_cutoff) {///fitered out due to no enough minimizers + lch = 1; wsrt[wsrt_n++] = (((uint64_t)-1)<<32)|(i); + continue; + } + + // fprintf(stderr, "-d-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + + if(!gen_hc_r_alin_flt_1_smp(&(ol->list[i]), cl, rref, qu, tu, exz, aux_o, err, e_max, e_rate, w.window_length, ql, rid, khit, chem_drop, align_gap_rate, align_gap_max, hpf, buf, &z_cov)) { + continue; + } + + z->is_match = 1; z->strong = z->without_large_indel = 0; + if(fc) update_mm_wins(z, wcut, wcut_n, ocw, ql, 0, 0.15, 16, 0, 1); + + // fprintf(stderr, "-e-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + } + + for (; tz < wsrt_n0; tz++) { + i = (uint32_t)wsrt[tz]; z = &(ol->list[i]); + assert(z->non_homopolymer_errors == UINT32_MAX); + assert(z->is_match == 0); + + if((wsrt[tz]>>32) == ((uint32_t)-1)) {///fitered out due to no enough minimizers + lch = 1; wsrt[wsrt_n++] = (((uint64_t)-1)<<32)|(i); + continue; + } + wsrt[wsrt_n++] = (((uint64_t)osc[i])<<32)|(i); + } + + + // fprintf(stderr, "-1-[M::%s] tot_b::%lu, z_cov::%lu, t_cov0::%lu, wsrt_n0::%lu, wsrt_n::%lu, s[0]::%d, s[1]::%d, s[2]::%d, s[3]::%d\n", __func__, + // tot_b, z_cov, t_cov0, wsrt_n0, wsrt_n, s[0], s[1], s[2], s[3]); + tot_b += z_cov; + } + + if(lch) { + gen_hc_aln_small_chn_smp(ol, cl, rref, qu, tu, exz, aux_o, err, e_max, e_rate, w.window_length, ql, rid, khit, chem_drop, align_gap_rate, align_gap_max, hpf, buf, &tot_b, + wcut, wcut_n, ocw, wsrt, wsrt_n, ocn, osc, chain_cutoff, /**3, 3**/16, 16); + } + + if(rescue_b_cut > 0 && n_cu > 0) { + tot_b += rescue_cu_aln(ol, cl, rref, qu, tu, exz, aux_o, err, e_max, e_rate, w.window_length, ql, rid, khit, chem_drop, align_gap_rate, align_gap_max, hpf, buf, + wcut, wcut_n, ocw, wsrt, a_cu, a_ci, idx_cu, n_cu, rescue_b_cut); + } + + + for (i = k = 0; i < ol->length; i++) {///primary chain + z = &(ol->list[i]); + if(z->is_match == 0) continue; + if(k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + k++; + } + // print_mm_wins_all(wcut, wcut_n, ocw, ql, 0); + // print_mm_wins_all(wcut, wcut_n, ocw, ql, 1); + + + /** + if((kp) && (kcnt < sec_aln_cov)) { + k = qick_realign(cl, ol->list, k, ol->length, sec_aln_cov, ql, sec_aln_win, kp, + rref, qu, tu, exz, aux_o, (((e_rate*sec_aln_err_rate)>sec_aln_max)?(sec_aln_max):(e_rate*sec_aln_err_rate)), wl, rid, khit, move_gap, buf, chem_drop, align_gap_rate, align_gap_max, hpf); + } + + // fprintf(stderr, "--[M::%s] window_length::%lld, err::%f\n", __func__, w.window_length, err); + **/ + + ol->length = k; + // prt_chain_cluster(ol, cl, a_cu, a_ci, ocn, osc, idx_cu, n_cu, 1, NULL); + // fprintf(stderr, "-[M::%s]\trid::%ld\ttot_b::%lu\tql::%lu\tmax_n_chain::%ld\ttot_b_cov:::%ld\n", __func__, rid, tot_b, ql, max_n_chain, tot_b/ql); + // exit(1); + sp->n = spn0; + if(ol->length <= 0) return; +} + + + +void gen_hc_r_alin_adv(gen_hc_aln_t *ez) +{ + uint64_t i, bs, k, w, ql = ez->qu->length, ks = 0, ke = ez->sec_aln_win, kcnt = ez->sec_aln_cov; double err, e_max, rr, align_gap_max, align_gap_rate, chem_drop; + int64_t re, kk; overlap_region t; overlap_region *z; //asg64_v iidx, buf, buf1; + ez->ol->mapped_overlaps_length = 0; + if(ez->ol->length <= 0) return; + // if(ol->length && ol->list[0].x_id == 19350) e_rate = 0.1; + + ///base alignment + // err = e_rate; e_max = err * 1.5; + // init_Window_Pool(&w, ql, wl, (int)(1.0/err)); + bs = (MAX(ez->wl[0], ez->wl[1]))+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(ez->tu, bs<<1); + + for (i = k = 0; i < ez->ol->length; i++) { + z = &(ez->ol->list[i]); z->shared_seed = z->non_homopolymer_errors; z->non_homopolymer_errors = (uint32_t)-1;///for index + + // if(z->y_id == 234) fprintf(stderr, "-z-[M::%s] tid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + if(z->y_id < ez->t_cut) { + err = ez->e_rate[1]; w = ez->wl[1]; align_gap_max = ez->align_gap_max[1]; align_gap_rate = ez->align_gap_rate[1]; chem_drop = ez->chem_drop[1]; + } else { + err = ez->e_rate[0]; w = ez->wl[0]; align_gap_max = ez->align_gap_max[0]; align_gap_rate = ez->align_gap_rate[0]; chem_drop = ez->chem_drop[0]; + } + e_max = err * 1.5; + + if(!align_hc_ed_post_extz(z, ez->rref, ez->qu->seq, ez->tu->seq, ez->exz, err, w, OVERLAP_THRESHOLD_HIFI_FILTER, 0, NULL)) continue; + + // if(z->y_id == 234) fprintf(stderr, "-m-[M::%s] tid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + + rr = gen_extend_err_exz(z, NULL, NULL, ez->rref, ez->qu->seq, ez->tu->seq, ez->exz, NULL, w, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 0, &re); + z->is_match = 0; + + // if(z->y_id == 234) fprintf(stderr, "-0-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + if (rr > err) continue; + z->non_homopolymer_errors = re; + + // if(z->y_id == 234) fprintf(stderr, "-c-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + if(!gen_hc_fast_cigar(z, ez->cl, ez->rref, w, ez->qu->seq, ez->tu, ez->exz, ez->aux_o, err, ql, ez->rid, ez->khit, &re)) continue; + + // if(z->y_id == 234) fprintf(stderr, "-d-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + if((align_gap_max >= 0) && (!ff_lunalign(z, err, align_gap_rate, align_gap_max))) continue; + + // if(z->y_id == 234) fprintf(stderr, "-e-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + if(chem_drop && ff_tend(z, 384, 2000, 0.1, (((err*10)<0.36)?(err*10):(0.36)), 128)) continue; + + // if(z->y_id == 234) fprintf(stderr, "-g-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + + // if(z->y_id == 27752) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + reassign_gaps(z, ez->aux_o, ez->qu->seq, ql, ez->hpz->a, NULL, -1, ez->rref, ez->tu, ez->buf, ez->exz); + + // fprintf(stderr, "-2-[M::%s] tid::%u\t%.*s\trr::%f\tre::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); + + // if(z->y_id == 27752) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\terr::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); + + if(k != i) { + t = ez->ol->list[k]; + ez->ol->list[k] = ez->ol->list[i]; + ez->ol->list[i] = t; + } + z = &(ez->ol->list[k++]); z->is_match = 1; ///z->non_homopolymer_errors = re; + z->strong = z->without_large_indel = 0; + + if((ez->kp) && (kcnt >= ez->sec_aln_cov) && (z->x_pos_s >= ke) && (z->x_pos_s >= ez->sec_aln_win)) { + ks = ke - ez->sec_aln_win;///[ks, ke) + for (kk = k - 1, kcnt = 0; kk >= 0 && kcnt < ez->sec_aln_cov; kk--) { + if((ez->ol->list[kk].x_pos_s <= ks) && ((ez->ol->list[kk].x_pos_e + 1) >= ke)) kcnt++; + } + ke += ez->sec_aln_win; + } + } + + // fprintf(stderr, "-[M::%s] window_length::%lld, err::%f\n", __func__, w.window_length, err); + + if((ez->kp) && (kcnt < ez->sec_aln_cov)) { + k = qick_realign(ez->cl, ez->ol->list, k, ez->ol->length, ez->sec_aln_cov, ql, ez->sec_aln_win, ez->kp, + ez->rref, ez->qu, ez->tu, ez->exz, ez->aux_o, (((ez->e_rate[1]*ez->sec_aln_err_rate)>ez->sec_aln_max)?(ez->sec_aln_max):(ez->e_rate[1]*ez->sec_aln_err_rate)), + ez->wl[1], ez->rid, ez->khit, ez->move_gap, ez->buf, ez->chem_drop[1], ez->align_gap_rate[1], ez->align_gap_max[1], ez->hpz->a); + } + + // fprintf(stderr, "--[M::%s] window_length::%lld, err::%f\n", __func__, w.window_length, err); + + ez->ol->length = k; + if(ez->ol->length <= 0) return; +} + + +void pp_chn_a(overlap_region *z, Candidates_list *cl, uint8_t is_raw) +{ + int64_t mi; uint64_t rr; + fprintf(stderr, "[M::%s::]\ttid::%u\t%.*s\n", __func__, + z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + mi = is_raw?z->non_homopolymer_errors:z->shared_seed; rr = cl->list[mi].readID; + for (; mi < cl->length && cl->list[mi].readID == rr; mi++) { + fprintf(stderr, "%u\t", cl->list[mi].self_offset); + } + fprintf(stderr, "\n"); +} + +void gen_hc_r_alin_adv_adp_smp(gen_hc_aln_t *ez, uint32_t *a_cu, uint32_t *a_ci, uint32_t *ocn, uint32_t *osc, uint64_t *idx_cu, uint64_t n_cu, uint8_t set_match) +{ + uint64_t i, bs, k, w, ql = ez->qu->length, *wcut = NULL, wcut_n = 0, *wsrt = NULL, wsrt_n = 0, lch = 0, wsrt_n0, spn0 = 0, tz, tot_b = 0, t_cov0, z_cov, focv = 0, fcov_0 = 0, rescue_b_cut = 0; + double err, e_max, align_gap_max, align_gap_rate, chem_drop; overlap_region t, *z; asg64_v *sp = ez->srt; + uint8_t fc = (((ez->ol->length > ez->max_n_chain) && (n_cu > 0))?(1):(0)), wf, ff; int32_t s[4]; s[0] = s[1] = s[2] = s[3] = 0; uint32_t scn[4]; scn[0] = scn[1] = scn[2] = scn[3] = 0; + ez->ol->mapped_overlaps_length = 0; + if(ez->ol->length <= 0) return; + + ///base alignment + bs = (MAX(ez->wl[0], ez->wl[1]))+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(ez->tu, bs<<1); + + spn0 = sp->n; sp->n += ez->ol->length + ez->ol->length; + kv_resize(uint64_t, (*sp), sp->n); + wsrt = sp->a + spn0; + if(fc) { + wcut = infer_chn_bar_0(ez->ol, ez->max_n_chain, ocn, osc, ql, ez->ocw, s, sp, &wcut_n, &focv); + if ((s[0] <= 0) && (s[1] <= 0) && (s[2] <= 0) && (s[3] <= 0)) fc = 0; + wsrt = sp->a + spn0; + + focv = focv/ql; if(focv < 0) focv = 1; focv *= 1.05; + if(focv < ez->ave_cov_min) focv = ez->ave_cov_min; + if(focv > (ez->max_n_chain<<1)) focv = ez->max_n_chain<<1; + // if(focv > ave_cov_max) focv = ave_cov_max; + // fcov_0 = max_n_chain>>1; if(fcov_0 > focv) fcov_0 = focv; + fcov_0 = ez->max_n_chain>>1; + + // rescue_b_cut = (fcov_0>>1)*ql; + rescue_b_cut = (fcov_0*0.75)*ql; + } + // fprintf(stderr, "[M::%s] wsrt_n::%lu, fc::%u, ez->ol->length::%lu, ez->max_n_chain::%lu, n_cu::%lu\n", __func__, wsrt_n, fc, ez->ol->length, ez->max_n_chain, n_cu); + // fprintf(stderr, "-0-[M::%s] focv::%lu, ave_cov_min::%lu, fcov_0::%lu, max_n_chain::%lu, wcut_n::%lu, ql::%lu, chain_cutoff::%lu\n", __func__, focv, ez->ave_cov_min, fcov_0, ez->max_n_chain, wcut_n, ql, ez->chain_cutoff); + + + s[0] = s[1] = s[2] = s[3] = 0;///reset it + for (i = wsrt_n = 0; i < ez->ol->length; i++) {///primary chain + z = &(ez->ol->list[i]); + if(set_match) { + z->is_match = 0; + } + + if(z->is_match == 0) { + z->shared_seed = z->non_homopolymer_errors; + z->non_homopolymer_errors = UINT32_MAX;///for index + } + + wf = ha_ov_type(z, ql); ff = 1; + + if(fc) { + if(((scn[wf] <= ez->max_n_chain) || ((scn[wf] <= (ez->max_n_chain<<1)) && (((int64_t)osc[i]) == s[wf])) || (z->is_match == 1))) { + ff = update_mm_wins(z, wcut, wcut_n, ez->ocw, ql, ((scn[wf]>ez->max_n_chain_f) && (z->is_match == 0))?1:0, 0.15, 16, focv, 0); + } else { + ff = 0; + } + } + + // if(z->y_id == 5931) pp_chn_a(z, ez->cl, 0); + + + // fprintf(stderr, "-0-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + + + if((!ff) && (z->is_match == 0)) {///fitered out due to coverage + wsrt[wsrt_n++] = (((uint64_t)osc[i])<<32)|(i); + continue; + } + + // fprintf(stderr, "-1-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + + scn[wf]++; + if (scn[wf] == ez->max_n_chain) { + s[wf] = osc[i]; + } + + if((ocn[i] < ez->chain_cutoff) && (z->is_match == 0)) {///fitered out due to no enough minimizers + lch = 1; + wsrt[wsrt_n++] = (((uint64_t)-1)<<32)|(i); + continue; + } + + // fprintf(stderr, "-2-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + + if(z->y_id < ez->t_cut) { + err = ez->e_rate[1]; w = ez->wl[1]; align_gap_max = ez->align_gap_max[1]; align_gap_rate = ez->align_gap_rate[1]; chem_drop = ez->chem_drop[1]; + } else { + err = ez->e_rate[0]; w = ez->wl[0]; align_gap_max = ez->align_gap_max[0]; align_gap_rate = ez->align_gap_rate[0]; chem_drop = ez->chem_drop[0]; + } + e_max = err * 1.5; + + // fprintf(stderr, "-3-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + + + if((z->is_match == 0) && (!gen_hc_r_alin_flt_1_smp(z, ez->cl, ez->rref, ez->qu, ez->tu, ez->exz, ez->aux_o, err, e_max, err, w, ql, ez->rid, ez->khit, chem_drop, align_gap_rate, align_gap_max, ez->hpz->a, ez->buf, &tot_b))) { + continue; + } + + // fprintf(stderr, "-4-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + + z->is_match = 1; z->strong = z->without_large_indel = 0; + if(fc) update_mm_wins(z, wcut, wcut_n, ez->ocw, ql, 0, 0.15, 16, 0, 1); + + // fprintf(stderr, "-5-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + } + + + // fprintf(stderr, "[M::%s] wsrt_n::%lu, fc::%u, ez->ol->length::%lu, ez->max_n_chain::%lu, n_cu::%lu\n", __func__, wsrt_n, fc, ez->ol->length, ez->max_n_chain, n_cu); + // for (i = 0; i < wsrt_n; i++) { + // z = &(ez->ol->list[(uint32_t)wsrt[i]]); + // fprintf(stderr, "[M::%s::i->%lu]\tqid::%u\ttid::%u\t%.*s\toid::%u\tsc::%lu\n", __func__, i, + // z->x_id, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // (uint32_t)wsrt[i], wsrt[i]>>32); + // } + + + + if(fc && wsrt_n) { + t_cov0 = cal_mm_wins_cov(wcut, wcut_n, ez->ocw, ql, fcov_0); + + wsrt_n0 = wsrt_n; wsrt_n = 0; lch = 0; + for (tz = z_cov = 0; (tz < wsrt_n0) && (z_cov <= t_cov0); tz++) { + i = (uint32_t)wsrt[tz]; z = &(ez->ol->list[i]); + assert(z->non_homopolymer_errors == UINT32_MAX); + assert(z->is_match == 0); + + // fprintf(stderr, "-a-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + + if((wsrt[tz]>>32) == ((uint32_t)-1)) {///fitered out due to no enough minimizers + lch = 1; wsrt[wsrt_n++] = (((uint64_t)-1)<<32)|(i); + continue; + } + + + // fprintf(stderr, "-b-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + + if(update_mm_wins(z, wcut, wcut_n, ez->ocw, ql, 1, 0.15, 16, fcov_0, 0) == 0) { + wsrt[wsrt_n++] = (((uint64_t)osc[i])<<32)|(i); + continue; + } + + // fprintf(stderr, "-c-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + + if(ocn[i] < ez->chain_cutoff) {///fitered out due to no enough minimizers + lch = 1; wsrt[wsrt_n++] = (((uint64_t)-1)<<32)|(i); + continue; + } + + // fprintf(stderr, "-d-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + + if(z->y_id < ez->t_cut) { + err = ez->e_rate[1]; w = ez->wl[1]; align_gap_max = ez->align_gap_max[1]; align_gap_rate = ez->align_gap_rate[1]; chem_drop = ez->chem_drop[1]; + } else { + err = ez->e_rate[0]; w = ez->wl[0]; align_gap_max = ez->align_gap_max[0]; align_gap_rate = ez->align_gap_rate[0]; chem_drop = ez->chem_drop[0]; + } + e_max = err * 1.5; + + // fprintf(stderr, "-e-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + + if(!gen_hc_r_alin_flt_1_smp(z, ez->cl, ez->rref, ez->qu, ez->tu, ez->exz, ez->aux_o, err, e_max, err, w, ql, ez->rid, ez->khit, chem_drop, align_gap_rate, align_gap_max, ez->hpz->a, ez->buf, &tot_b)) { + continue; + } + + // fprintf(stderr, "-f-[M::%s::]\tqid::%u\ttid::%u\t%.*s\tq::[%u,%u)\tt::[%u,%u)\tsc::%u\tcn::%u\tis_match::%u\terr::%u\n", __func__, z->x_id, + // z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), + // z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, + // osc[i], ocn[i], z->is_match, z->non_homopolymer_errors); + + z->is_match = 1; z->strong = z->without_large_indel = 0; + if(fc) update_mm_wins(z, wcut, wcut_n, ez->ocw, ql, 0, 0.15, 16, 0, 1); + } + + for (; tz < wsrt_n0; tz++) { + i = (uint32_t)wsrt[tz]; z = &(ez->ol->list[i]); + assert(z->non_homopolymer_errors == UINT32_MAX); + assert(z->is_match == 0); + + if((wsrt[tz]>>32) == ((uint32_t)-1)) {///fitered out due to no enough minimizers + lch = 1; wsrt[wsrt_n++] = (((uint64_t)-1)<<32)|(i); + continue; + } + wsrt[wsrt_n++] = (((uint64_t)osc[i])<<32)|(i); + } + + // fprintf(stderr, "-1-[M::%s] tot_b::%lu, z_cov::%lu, t_cov0::%lu, wsrt_n0::%lu, wsrt_n::%lu, s[0]::%d, s[1]::%d, s[2]::%d, s[3]::%d\n", __func__, tot_b, z_cov, t_cov0, wsrt_n0, wsrt_n, s[0], s[1], s[2], s[3]); + + tot_b += z_cov; + } + + + if(lch) { + gen_hc_aln_small_chn_smp_adv(ez, ql, a_cu, a_ci, ocn, osc, idx_cu, n_cu, wcut, wcut_n, &tot_b, wsrt, wsrt_n, 16, 16); + } + + + if(rescue_b_cut > 0 && n_cu > 0) { + rescue_cu_aln_adv(ez, ql, wcut, wcut_n, wsrt, a_cu, a_ci, idx_cu, n_cu, rescue_b_cut); + } + + + for (i = k = 0; i < ez->ol->length; i++) {///primary chain + z = &(ez->ol->list[i]); + if(z->is_match == 0) continue; + if(k != i) { + t = ez->ol->list[k]; + ez->ol->list[k] = ez->ol->list[i]; + ez->ol->list[i] = t; + } + k++; + } + + ez->ol->length = k; sp->n = spn0; + if(ez->ol->length <= 0) return; +} + + + + +void gen_hc_r_alin_nec(overlap_region_alloc* ol, Candidates_list *cl, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t wl, int64_t rid, int64_t khit, int64_t move_gap, asg16_v* buf, uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max, uint64_t sec_aln_win, uint64_t sec_aln_cov, double sec_aln_err_rate, double sec_aln_max, asg64_v *kp, uint8_t *hpf) +{ + uint64_t i, bs, k, ql = qu->length, ks = 0, ke = sec_aln_win, kcnt = sec_aln_cov; Window_Pool w; double err, e_max, rr; int64_t re, kk; + overlap_region t; overlap_region *z; //asg64_v iidx, buf, buf1; + ol->mapped_overlaps_length = 0; + if(ol->length <= 0) return; + // if(ol->length && ol->list[0].x_id == 19350) e_rate = 0.1; + + ///base alignment + err = e_rate; e_max = err * 1.5; + init_Window_Pool(&w, ql, wl, (int)(1.0/err)); + bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(tu, bs<<1); + // fprintf(stderr, "[M::%s] window_length::%lld\n", __func__, w.window_length); + + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + + for (i = k = 0; i < ol->length; i++) { + z = &(ol->list[i]); + if(z->is_match != 1) { + z->shared_seed = z->non_homopolymer_errors; z->non_homopolymer_errors = (uint32_t)-1;///for index + + // if(z->x_id == 19350 && z->y_id == 19324) fprintf(stderr, "-z-[M::%s] tid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + + if(!align_hc_ed_post_extz(z, rref, qu->seq, tu->seq, exz, err, w.window_length, OVERLAP_THRESHOLD_HIFI_FILTER, 0, NULL)) continue; + + // if(z->x_id == 19350 && z->y_id == 19324) fprintf(stderr, "-m-[M::%s] tid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + + rr = gen_extend_err_exz(z, NULL, NULL, rref, qu->seq, tu->seq, exz, NULL, w.window_length, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 0, &re); + z->is_match = 0; + + // if(z->x_id == 19350 && z->y_id == 19324) fprintf(stderr, "-0-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + if (rr > err) continue; + z->non_homopolymer_errors = re; + + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + + if(!gen_hc_fast_cigar(z, cl, rref, w.window_length, qu->seq, tu, exz, aux_o, e_rate, ql, rid, khit, &re)) continue; + + if((align_gap_max >= 0) && (!ff_lunalign(z, err, align_gap_rate, align_gap_max))) continue; + + if(chem_drop && ff_tend(z, 384, 2000, 0.1, (((e_rate*10)<0.36)?(e_rate*10):(0.36)), 128)) continue; + + // if(z->x_id == 3196 && z->y_id == 3199) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + + reassign_gaps(z, aux_o, qu->seq, ql, hpf, NULL, -1, rref, tu, buf, exz); + + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + } + + // if(z->x_id == 3196 && z->y_id == 3199) fprintf(stderr, "-2-[M::%s] tid::%u\t%.*s\trr::%f\tre::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); + + // if(z->x_id == 19350) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\terr::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); + + if(k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + z = &(ol->list[k++]); z->is_match = 1; ///z->non_homopolymer_errors = re; + z->strong = z->without_large_indel = 0; + + + if((kp) && (kcnt >= sec_aln_cov) && (z->x_pos_s >= ke) && (z->x_pos_s >= sec_aln_win)) { + ks = ke - sec_aln_win;///[ks, ke) + for (kk = k - 1, kcnt = 0; kk >= 0 && kcnt < sec_aln_cov; kk--) { + if((ol->list[kk].x_pos_s <= ks) && ((ol->list[kk].x_pos_e + 1) >= ke)) kcnt++; + } + ke += sec_aln_win; + } + } + + if((kp) && (kcnt < sec_aln_cov)) { + k = qick_realign(cl, ol->list, k, ol->length, sec_aln_cov, ql, sec_aln_win, kp, + rref, qu, tu, exz, aux_o, (((e_rate*sec_aln_err_rate)>sec_aln_max)?(sec_aln_max):(e_rate*sec_aln_err_rate)), wl, rid, khit, move_gap, buf, chem_drop, align_gap_rate, align_gap_max, hpf); + } + + + ol->length = k; + if(ol->length <= 0) return; +} + +void gen_hc_r_alin_nec_adv(gen_hc_aln_t *ez) +{ + uint64_t i, w, bs, k, ql = ez->qu->length, ks = 0, ke = ez->sec_aln_win, kcnt = ez->sec_aln_cov; double err, e_max, rr, align_gap_max, align_gap_rate, chem_drop; int64_t re, kk; + overlap_region t; overlap_region *z; //asg64_v iidx, buf, buf1; + ez->ol->mapped_overlaps_length = 0; + if(ez->ol->length <= 0) return; + // if(ol->length && ol->list[0].x_id == 19350) e_rate = 0.1; + + ///base alignment + // err = e_rate; e_max = err * 1.5; + // init_Window_Pool(&w, ql, wl, (int)(1.0/err)); + bs = (MAX(ez->wl[0], ez->wl[1]))+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(ez->tu, bs<<1); + // fprintf(stderr, "[M::%s] window_length::%lld\n", __func__, w.window_length); + + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + + for (i = k = 0; i < ez->ol->length; i++) { + z = &(ez->ol->list[i]); + if(z->is_match != 1) { + z->shared_seed = z->non_homopolymer_errors; z->non_homopolymer_errors = (uint32_t)-1;///for index + + if(z->y_id < ez->t_cut) { + err = ez->e_rate[1]; w = ez->wl[1]; align_gap_max = ez->align_gap_max[1]; align_gap_rate = ez->align_gap_rate[1]; chem_drop = ez->chem_drop[1]; + } else { + err = ez->e_rate[0]; w = ez->wl[0]; align_gap_max = ez->align_gap_max[0]; align_gap_rate = ez->align_gap_rate[0]; chem_drop = ez->chem_drop[0]; + } + e_max = err * 1.5; + + // if(z->x_id == 19350 && z->y_id == 19324) fprintf(stderr, "-z-[M::%s] tid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + + if(!align_hc_ed_post_extz(z, ez->rref, ez->qu->seq, ez->tu->seq, ez->exz, err, w, OVERLAP_THRESHOLD_HIFI_FILTER, 0, NULL)) continue; + + // if(z->x_id == 19350 && z->y_id == 19324) fprintf(stderr, "-m-[M::%s] tid::%u\t%.*s\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id)); + + rr = gen_extend_err_exz(z, NULL, NULL, ez->rref, ez->qu->seq, ez->tu->seq, ez->exz, NULL, w, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 0, &re); + z->is_match = 0; + + // if(z->x_id == 19350 && z->y_id == 19324) fprintf(stderr, "-0-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + if (rr > err) continue; + z->non_homopolymer_errors = re; + + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + + if(!gen_hc_fast_cigar(z, ez->cl, ez->rref, w, ez->qu->seq, ez->tu, ez->exz, ez->aux_o, err, ql, ez->rid, ez->khit, &re)) continue; + + if((align_gap_max >= 0) && (!ff_lunalign(z, err, align_gap_rate, align_gap_max))) continue; + + if(chem_drop && ff_tend(z, 384, 2000, 0.1, (((err*10)<0.36)?(err*10):(0.36)), 128)) continue; + + // if(z->x_id == 3196 && z->y_id == 3199) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + + reassign_gaps(z, ez->aux_o, ez->qu->seq, ql, ez->hpz->a, NULL, -1, ez->rref, ez->tu, ez->buf, ez->exz); + + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + } + + // if(z->x_id == 3196 && z->y_id == 3199) fprintf(stderr, "-2-[M::%s] tid::%u\t%.*s\trr::%f\tre::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); + + // if(z->x_id == 19350) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\terr::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); + + if(k != i) { + t = ez->ol->list[k]; + ez->ol->list[k] = ez->ol->list[i]; + ez->ol->list[i] = t; + } + z = &(ez->ol->list[k++]); z->is_match = 1; ///z->non_homopolymer_errors = re; + z->strong = z->without_large_indel = 0; + + + if((ez->kp) && (kcnt >= ez->sec_aln_cov) && (z->x_pos_s >= ke) && (z->x_pos_s >= ez->sec_aln_win)) { + ks = ke - ez->sec_aln_win;///[ks, ke) + for (kk = k - 1, kcnt = 0; kk >= 0 && kcnt < ez->sec_aln_cov; kk--) { + if((ez->ol->list[kk].x_pos_s <= ks) && ((ez->ol->list[kk].x_pos_e + 1) >= ke)) kcnt++; + } + ke += ez->sec_aln_win; + } + } + + if((ez->kp) && (kcnt < ez->sec_aln_cov)) { + k = qick_realign(ez->cl, ez->ol->list, k, ez->ol->length, ez->sec_aln_cov, ql, ez->sec_aln_win, ez->kp, ez->rref, ez->qu, ez->tu, ez->exz, ez->aux_o, + (((ez->e_rate[1]*ez->sec_aln_err_rate)>ez->sec_aln_max)?(ez->sec_aln_max):(ez->e_rate[1]*ez->sec_aln_err_rate)), ez->wl[1], ez->rid, ez->khit, ez->move_gap, + ez->buf, ez->chem_drop[1], ez->align_gap_rate[1], ez->align_gap_max[1], ez->hpz->a); + } + + + ez->ol->length = k; + if(ez->ol->length <= 0) return; +} + + +uint64_t gen_hc_r_alin_re(overlap_region* z, Candidates_list *cl, char* qstr, uint64_t ql, char* tstr, uint64_t tl, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t wl, int64_t rid, int64_t khit, int64_t move_gap, asg16_v* buf) +{ + double err, e_max, rr; int64_t re; + + err = e_rate; e_max = err * 1.5; + + z->shared_seed = z->non_homopolymer_errors;///for index + + if(!align_hc_ed_post_non_retrieve_extz(z, qstr, ql, tstr, tl, exz, err, wl, OVERLAP_THRESHOLD_HIFI_FILTER, 0, NULL)) return 0; + + rr = gen_extend_err_non_retrieve_exz(z, qstr, tstr, tl, exz, NULL, wl, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 0, &re); + z->is_match = 0; + + if (rr > err) return 0; + z->non_homopolymer_errors = re; + + // if(z->x_id == 3196 && z->y_id == 3199) fprintf(stderr, "-0-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + if(!gen_hc_fast_non_retrieve_cigar(z, cl, wl, qstr, ql, tstr, tl, exz, aux_o, e_rate, rid, khit)) return 0; + + // if(z->x_id == 3196 && z->y_id == 3199) fprintf(stderr, "-1-[M::%s] tid::%u\t%.*s\trr::%f\tre::%ld\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, re); + + reassign_gaps(z, aux_o, qstr, ql, NULL, tstr, tl, NULL, NULL, buf, exz); + + // if(z->x_id == 3196 && z->y_id == 3199) fprintf(stderr, "-2-[M::%s] tid::%u\t%.*s\trr::%f\tre::%u\n", __func__, z->y_id, (int)Get_NAME_LENGTH(R_INF, z->y_id), Get_NAME(R_INF, z->y_id), rr, z->non_homopolymer_errors); + + z->is_match = 1; ///z->non_homopolymer_errors = re; + z->strong = z->without_large_indel = 0; + + return 1; +} + +/** +void ul_raw_lalign_adv(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, All_reads *rdb, const ug_opt_t *uopt, + char *qstr, uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, bit_extz_t *exz, haplotype_evdience_alloc* hap, + kvec_t_u64_warp* v_idx, overlap_region *aux_o, double e_rate, int64_t wl, kv_ul_ov_t *aln, kv_ul_ov_t *aln1, + int64_t sid, uint64_t khit, st_mt_t *stb, void *km) +{ + uint64_t i, bs, k, aln_occ; Window_Pool w; double err; + overlap_region t; overlap_region *z; asg64_v iidx, buf, buf1; + ol->mapped_overlaps_length = 0; + if(ol->length <= 0) return; + + ///base alignment + clear_Correct_dumy(dumy, ol, km); err = e_rate; + init_Window_Pool(&w, ql, wl, (int)(1.0/err)); + bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(tu, bs<<1); + + if(!aux_o) { + resize_UC_Read(qu, ql); qu->length = ql; memcpy(qu->seq, qstr, ql); + copy_asg_arr(iidx, hap->snp_srt); + for (i = k = 0, aln->n = 0; i < ol->length; i++) { + z = &(ol->list[i]); z->shared_seed = z->non_homopolymer_errors;///for index + align_ul_ed_post_extz(z, uref, NULL, qu->seq, tu->seq, exz, err, w.window_length, -1, 1, km); + aln_occ = gen_r_aln(uref, z, k, &iidx, OVERLAP_THRESHOLD_FILTER, aln, 1000); + if(!aln_occ) continue; + if(k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + z = &(ol->list[k++]); z->is_match = 1; + } + copy_asg_arr(hap->snp_srt, iidx); + ol->length = k; + if(ol->length <= 0) return; + } else { + copy_asg_arr(iidx, hap->snp_srt); copy_asg_arr(buf, v_idx->a); copy_asg_arr(buf1, (*stb)); + ul_gap_filling_local(ol, cl, aln, wl, uref, NULL, NULL, qu->seq, tu, exz, aux_o, &buf, &iidx, err, ql, sid, khit, 1, MAX_LGAP(ql)); + copy_asg_arr(hap->snp_srt, iidx); copy_asg_arr(v_idx->a, buf); copy_asg_arr((*stb), buf1); + + copy_asg_arr(iidx, hap->snp_srt); + gen_aln_local(ol, aln, aln1, &iidx, uref, qu->seq, tu, exz, aux_o, err, ql, OVERLAP_THRESHOLD_FILTER); + copy_asg_arr(hap->snp_srt, iidx); + } + // } else { + // // fprintf(stderr, "-[M::%s] on::%lu\n", __func__, ol->length); + // if(ol->length <= 1) return; + // ///coordinates for all intervals with cov > 1 + // copy_asg_arr(iidx, hap->snp_srt); copy_asg_arr(buf, v_idx->a); copy_asg_arr(buf1, (*stb)); + // // fprintf(stderr, "\n[M::%s] iidx_n::%ld\n", __func__, (int64_t)iidx.n); + // ul_gap_filling_adv(ol, cl, aln, wl, uref, NULL, NULL, qu->seq, tu, exz, aux_o, &buf, &iidx, err, ql, sid, khit, 1, MAX_LGAP(ql)); + // copy_asg_arr(hap->snp_srt, iidx); copy_asg_arr(v_idx->a, buf); copy_asg_arr((*stb), buf1); + + // copy_asg_arr(iidx, hap->snp_srt); copy_asg_arr(buf, v_idx->a); copy_asg_arr(buf1, (*stb)); + // region_phase(ol, uref, uopt, aln, &iidx, &buf, &buf1); + // copy_asg_arr(hap->snp_srt, iidx); copy_asg_arr(v_idx->a, buf); copy_asg_arr((*stb), buf1); + // } +} +**/ + +uint64_t gen_nkhits(Candidates_list *cl, overlap_region *z) +{ + uint64_t pid, kn; int64_t k; + pid = cl->list[z->shared_seed].readID;kn = 0; + for (k = z->shared_seed; k < cl->length && cl->list[k].readID == pid; k++) kn++; + return kn; +} + +void ug_lalign(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, const ug_opt_t *uopt, + char *qstr, uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, bit_extz_t *exz, + overlap_region *aux_o, double e_rate, int64_t wl, int64_t sid, uint64_t khit, + uint64_t chain_cut, void *km) +{ + uint64_t i, bs, k, ovl, pid, kl, kn; Window_Pool w; double err; + overlap_region t; overlap_region *z; char *in = qstr; + ol->mapped_overlaps_length = 0; + if(ol->length <= 0) return; + + ///base alignment + clear_Correct_dumy(dumy, ol, km); err = e_rate; + init_Window_Pool(&w, ql, wl, (int)(1.0/err)); + bs = (w.window_length)+(THRESHOLD_MAX_SIZE<<1)+1; + resize_UC_Read(tu, bs<<1); + + if(!aux_o) { + if(qu) { + resize_UC_Read(qu, ql); qu->length = ql; memcpy(qu->seq, qstr, ql); in = qu->seq; + } + for (i = 0; i < ol->length; i++) { + z = &(ol->list[i]); ovl = z->x_pos_e+1-z->x_pos_s; + z->shared_seed = z->non_homopolymer_errors;///for index + pid = cl->list[z->shared_seed].readID; kl = cl->length; kn = 0; + for (k = z->shared_seed; k < kl && cl->list[k].readID == pid && kn < chain_cut; k++) kn++; + if(kn < chain_cut) continue; + + if(!align_ul_ed_post_extz(z, uref, NULL, in/**qu->seq**/, tu->seq, exz, err, w.window_length, -1, 0, km)) { + continue; + } + if(uref && simi_pass(ovl, z->align_length, uref?1:0, -1, NULL)) { + z->is_match = 3; ol->mapped_overlaps_length += z->align_length; + } + } + + // if(uref && ol->mapped_overlaps_length > 0) { + // set_herror_win(ol, dumy, v_idx, err, ql, w.window_length); + // } + + double e_max = err*1.5, rr; int64_t re; + for (i = k = 0; i < ol->length; i++) { + z = &(ol->list[i]); ovl = z->x_pos_e + 1 - z->x_pos_s; + rr = gen_extend_err_exz(z, uref, NULL, NULL, in/**qu->seq**/, tu->seq, exz, NULL/**v_idx?v_idx->a.a:NULL**/, w.window_length, -1, err, (e_max+0.000001), THRESHOLD_MAX_SIZE, 1, &re); + z->is_match = 0;///must be here; + + // if(z->x_id == 57 && z->y_id == 2175) { + // fprintf(stderr, "+utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\talign_length::%u\terr::%f\trr::%f\twn::%u\tk::%lu\ti::%lu\n", + // z->x_id+1, "lc"[uref->ug->u.a[z->x_id].circ], uref->ug->u.a[z->x_id].len, + // z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[uref->ug->u.a[z->y_id].circ], uref->ug->u.a[z->y_id].len, + // z->y_pos_s, z->y_pos_e+1, z->align_length, err, rr, (uint32_t)z->w_list.n/**gen_nkhits(cl, z)**/, + // k, i); + // } + if (rr <= err) { + if(k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + ol->list[k].is_match = 1; ol->list[k].non_homopolymer_errors = re; + k++; + } + } + + ol->length = k; + // if(sid == 57) { + // fprintf(stderr, "+utg%.6ld%c\tol->length::%lu\n", sid+1, "lc"[uref->ug->u.a[sid].circ], ol->length); + // } + if(ol->length <= 0) return; + } else { + // if(ol->length <= 1) return; + if(ol->length <= 0) return; + if(qu) { + resize_UC_Read(qu, ql); qu->length = ql; memcpy(qu->seq, qstr, ql); in = qu->seq; + } + for (i = k = 0; i < ol->length; i++) { + z = &(ol->list[i]); + // if(z->x_id == 57 && z->y_id == 2175) { + // fprintf(stderr, "-1-utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\talign_length::%u\terr::%f\twn::%u\tk::%lu\ti::%lu\n", + // z->x_id+1, "lc"[uref->ug->u.a[z->x_id].circ], uref->ug->u.a[z->x_id].len, + // z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[uref->ug->u.a[z->y_id].circ], uref->ug->u.a[z->y_id].len, + // z->y_pos_s, z->y_pos_e+1, z->align_length, err, (uint32_t)z->w_list.n/**gen_nkhits(cl, z)**/, + // k, i); + // } + if(!ul_raw_aln(z, cl, uref, in/**qu->seq**/, tu, exz, err, wl, ql, sid, khit, aux_o)) { + z->is_match = 0; + continue; + } + + // if(z->x_id == 57 && z->y_id == 2175) { + // fprintf(stderr, "-2-utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\talign_length::%u\terr::%f\twn::%u\tk::%lu\ti::%lu\n", + // z->x_id+1, "lc"[uref->ug->u.a[z->x_id].circ], uref->ug->u.a[z->x_id].len, + // z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[uref->ug->u.a[z->y_id].circ], uref->ug->u.a[z->y_id].len, + // z->y_pos_s, z->y_pos_e+1, z->align_length, err, (uint32_t)z->w_list.n/**gen_nkhits(cl, z)**/, + // k, i); + // } + if(k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + ol->list[k].is_match = 1; + k++; + } + ol->length = k; + + // if(sid == 57) { + // fprintf(stderr, "-utg%.6ld%c\tol->length::%lu\n", sid+1, "lc"[uref->ug->u.a[sid].circ], ol->length); + // } + } } \ No newline at end of file diff --git a/Correct.h b/Correct.h index 2839e60..933c59c 100644 --- a/Correct.h +++ b/Correct.h @@ -1,1420 +1,1486 @@ -#ifndef __CORRECT__ -#define __CORRECT__ - -#define __STDC_LIMIT_MACROS -#include -#include "Hash_Table.h" -#include "Levenshtein_distance.h" -#include "POA.h" -#include "Process_Read.h" -#include "Correct.h" -#include "kalloc.h" - -//#define CORRECT_THRESHOLD 0.70 -#define CORRECT_THRESHOLD 0.60 -///#define CORRECT_THRESHOLD_SECOND 0.55 -#define CORRECT_THRESHOLD_HOMOPOLYMER 0.515 -#define MIN_COVERAGE_THRESHOLD 3 -#define CORRECT_INDEL_LENGTH 2 -#define MISMATCH 1 -#define INSERTION 2 -#define DELETION 3 -#define ERROR_RATE 1.5 -#define UL_TOPN 50 -#define SGAP 16 -#define MAX_LGAP(ql) ((((ql)*0.2)<256)?((ql)*0.2):256) - -#define WINDOW_MAX_SIZE (WINDOW + (int)(1.0 / HA_MIN_OV_DIFF) + 3) // TODO: why 1/max_ov_diff? - -///#define FLAG_THRE 0 - -#define MAX(x, y) (((x) >= (y))?(x):(y)) -#define MIN(x, y) (((x) <= (y))?(x):(y)) -#define DIFF(x, y) ((MAX((x), (y))) - (MIN((x), (y)))) -#define OVERLAP(x_start, x_end, y_start, y_end) (MIN(x_end, y_end) - MAX(x_start, y_start) + 1) -///#define OVERLAP(x_start, x_end, y_start, y_end) MIN(x_end, y_end) - MAX(x_start, y_start) + 1 - -#define Get_MisMatch_Base(RECORD) (s_H[(RECORD>>3)]) -#define Get_Match_Base(RECORD) (s_H[(RECORD&7)]) -#define Coverage_Threshold(coverage, r_len) (coverage*r_len*1.1) - - - -#define Get_Max_DP_Value(RECORD) (RECORD>>32) -#define Get_Max_DP_ID(RECORD) (RECORD&(uint64_t)0xffffffff) - -#define Adjust_Threshold(threshold, x_len) ((threshold == 0 && x_len >= 4)? 1: threshold) - -typedef struct -{ - long long read_length; - long long window_length; - long long window_num; - long long window_start; - long long window_end; - long long tail_length; - int terminal; -}Window_Pool; - -inline void init_Window_Pool(Window_Pool* dumy, long long read_length, long long window_length, long long tail_length) -{ - dumy->terminal = 0; - dumy->read_length = read_length; - dumy->window_length = window_length; - dumy->tail_length = tail_length; - - dumy->window_start = 0; - dumy->window_end = dumy->window_length - 1; - if (dumy->window_end >= dumy->read_length) - { - dumy->window_end = dumy->read_length - 1; - } - - dumy->window_num = (dumy->read_length + dumy->window_length - 1) / dumy->window_length; -} - -inline int get_Window(Window_Pool* dumy, long long* w_beg, long long* w_end) -{ - (*w_beg) = dumy->window_start; - (*w_end) = dumy->window_end; - - if(dumy->window_end == dumy->read_length - 1) - { - if(dumy->terminal == 1 || dumy->read_length == 0) - { - return 0; - } - else if(dumy->terminal == 0) - { - dumy->terminal = 1; - } - } - - - dumy->window_start = dumy->window_start + dumy->window_length; - dumy->window_end = dumy->window_end + dumy->window_length; - if (dumy->window_end >= dumy->read_length) - { - dumy->window_end = dumy->read_length - 1; - } - return 1; -} - - -typedef struct -{ - /**[0-1] bits are type:**/ - /**[2-31] bits are length**/ - char current_operation; - int current_operation_length; - uint32_t* record; - uint64_t size; - uint64_t length; - uint32_t new_read_length; - - - char* lost_base; - uint64_t lost_base_size; - uint64_t lost_base_length; - - -}Cigar_record; - - -typedef struct -{ - long long length; - long long size; - Cigar_record* buffer; -}Cigar_record_alloc; - - -typedef struct -{ - ////the position of snp in read itself - uint32_t site; - ////the overlapID - uint32_t overlapID; - ////the position of snp in that overlap - uint32_t overlapSite; - ///there are several types: 0: equal to read 1: not equal to read, but it is a mismatch 2: is a gap - uint8_t type; - uint32_t cov; - ///misbase - char misBase; -}haplotype_evdience; - -#define hh_tp(z) (((z).type&1)) -#define hh_hp(z) ((((z).type>>1)&1)) -#define hh_bq(z) ((((z).type>>2))&sc_bm) -#define hh_wq(z) ((((z).type>>(sc_bn+2)))&sc_bm) - -typedef struct -{ - ///the id of this snp - uint32_t id; - uint32_t overlap_num; - uint32_t occ_0; - uint32_t occ_1; - uint32_t occ_2; - uint32_t homopolymer_num; - uint32_t non_homopolymer_num; - int score; - ////the position of snp in read itself - uint32_t site; - uint8_t is_homopolymer; -} -SnpStats; - - - -typedef struct -{ - uint32_t beg; - uint32_t end; - uint32_t occ_0; - uint32_t occ_1; - uint32_t homopolymer_num; - uint32_t non_homopolymer_num; - uint32_t is_remove; -} -Snp_ID_Vector; - - -typedef struct -{ - long long IDs_size; - long long IDs_length; - long long max_snp_id; - Snp_ID_Vector* IDs; - - long long buffer_size; - long long buffer_length; - uint32_t* buffer; -} -Snp_ID_Vector_Alloc; - -#define Get_DP_Backtrack_Column(matrix, i) (matrix.backtrack + matrix.snp_num * i) -#define Get_DP_Backtrack_Column_Length(matrix, i) (matrix.snp_num) - - -typedef struct -{ - // uint32_t snp_size; - // uint32_t snp_num; - // uint32_t* max; - // uint32_t* colum_len; - // uint32_t* colum; - // uint32_t matrix_size; - - uint32_t snp_num; - - uint8_t* visit; - uint32_t* max; - uint64_t* max_for_sort; - - - - uint32_t snp_size; - - uint32_t* backtrack_length; - uint32_t* backtrack; - uint32_t backtrack_size; - - - uint32_t* buffer; - uint32_t* max_buffer; - - - int max_snp_num; - ///int max_snp_ID; - int max_score; - int current_snp_num; - - - Snp_ID_Vector_Alloc SNP_IDs; -} -DP_matrix; - - -#define Get_SNP_Martix_Size(matrix) (matrix.snp * matrix.overlap) -#define Get_SNP_Vector(matrix, i) (matrix.snp_matrix + matrix.overlap * i) -#define Get_SNP_Vector_Length(matrix) (matrix.overlap) -// #define Get_Result_SNP_Vector(matrix) (matrix.snp_matrix + matrix.overlap*matrix.snp) -#define Get_Result_SNP_Vector(matrix) (matrix.r_snp) - -typedef struct -{ - SnpStats* a; - size_t n,m; -}kv_SnpStats_t; - -typedef struct -{ - haplotype_evdience* list; - uint32_t sub_list_start; - uint32_t sub_list_length; - uint32_t length; - uint32_t size; - - /****************************may have bugs********************************/ - uint8_t flag[WINDOW_MAX_SIZE]; - /****************************may have bugs********************************/ - - - uint32_t core_snp; - uint32_t overlap; - int8_t *snp_matrix; - uint32_t snp_matrix_size; - int8_t *r_snp; - uint32_t r_snp_size; - SnpStats result_stat; - - kv_SnpStats_t snp_stat; - uint32_t nn_snp; - kvec_t(uint64_t) snp_srt; - // SnpStats* snp_stat; - // uint32_t snp; - // uint32_t snp_stat_size; - // uint32_t available_snp; - - DP_matrix dp; -} -haplotype_evdience_alloc; - -inline int filter_snp(int x, int y, int total) -{ - double available; - - if(x <= y) - { - available = x; - } - else - { - available = y; - } - double threshold = 0.30; - available = available/((double)(total)); - if(available <= threshold && available < 6) - { - return 0; - } - return 1; -} - - -inline int filter_one_snp(int occ_0, int occ_1, int total) -{ - - - double available; - - if(occ_0 <= occ_1) - { - available = occ_0; - } - else - { - available = occ_1; - } - double threshold = 0.35; - available = available/((double)(total)); - - - - if(available < threshold || occ_0 < MIN_COVERAGE_THRESHOLD + 1 || total < 10) - ///if(available < threshold || total < 10) - { - return 0; - } - return 1; -} - -inline void count_nearby_snps(haplotype_evdience_alloc* hap, uint32_t* SNPs, int SNPsLen, int* nearsnp, int* non_nearsnps) -{ - long long i, current_id, large_id, small_id; - long long distance = 10; - - - - if(SNPsLen == 1) - { - (*non_nearsnps) = 1; - (*nearsnp) = 0; - return; - } - - if(SNPsLen == 0) - { - (*nearsnp) = 0; - (*non_nearsnps) = 0; - return; - } - - (*nearsnp) = 0; - (*non_nearsnps) = 0; - - for (i = 0; i < SNPsLen; i++) - { - if(i > 0 && i < SNPsLen - 1) - { - current_id= SNPs[i]; - - ///since SNPs[i - 1].site is larger than SNPs[i] - large_id = SNPs[i - 1]; - small_id = SNPs[i + 1]; - - - if(hap->snp_stat.a[large_id].site - hap->snp_stat.a[current_id].site < distance - || - hap->snp_stat.a[current_id].site - hap->snp_stat.a[small_id].site < distance) - { - (*nearsnp)++; - } - else - { - (*non_nearsnps)++; - } - - if(hap->snp_stat.a[current_id].site > hap->snp_stat.a[large_id].site || - hap->snp_stat.a[current_id].site < hap->snp_stat.a[small_id].site) - { - fprintf(stderr, "error\n"); - } - } - else if(i == 0) - { - current_id= SNPs[i]; - small_id = SNPs[i + 1]; - if(hap->snp_stat.a[current_id].site - hap->snp_stat.a[small_id].site < distance) - { - (*nearsnp)++; - } - else - { - (*non_nearsnps)++; - } - - if(hap->snp_stat.a[current_id].site < hap->snp_stat.a[small_id].site) - { - fprintf(stderr, "error\n"); - } - } - else - { - large_id = SNPs[i - 1]; - current_id= SNPs[i]; - if(hap->snp_stat.a[large_id].site - hap->snp_stat.a[current_id].site < distance) - { - (*nearsnp)++; - } - else - { - (*non_nearsnps)++; - } - - if(hap->snp_stat.a[current_id].site > hap->snp_stat.a[large_id].site) - { - fprintf(stderr, "error\n"); - } - - } - - } - - if((*nearsnp) + (*non_nearsnps) != SNPsLen) - { - fprintf(stderr, "(*nearsnp): %d, (*non_nearsnps): %d, SNPsLen: %d\n", (*nearsnp), (*non_nearsnps), SNPsLen); - } -} - -inline int filter_one_snp_advance_nearby(haplotype_evdience_alloc* hap, int occ_0, int occ_1, int total, -long long homopolymer_num, long long non_homopolymer_num, -uint32_t* SNPs, int SNPsLen) -{ - - - double available; - - if(occ_0 <= occ_1) - { - available = occ_0; - } - else - { - available = occ_1; - } - int min = available; - - double threshold1 = 0.35; - double threshold2 = 0.24; - available = available/((double)(total)); - - - - ///if((non_homopolymer_num > 0 && min >= 5) || (min >= 6)) - if(min >= 5) - { - if(available < threshold2 || total < 10) - { - return 0; - } - } - else if(available < threshold1 || occ_0 < MIN_COVERAGE_THRESHOLD + 1 || total < 10) - { - return 0; - } - return 1; -} - - -inline int if_is_homopolymer_strict(long long site, char* read, long long read_length) -{ - long long beg, end, i; - long long threshold = 3; - - beg = site - threshold; - if(beg < 0) - { - beg = 0; - } - - end = site + threshold; - - if(end >= read_length) - { - end = read_length - 1; - } - - char f_homopolymer_ch = 0; - long long f_homopolymer_len = 0; - - for (i = site + 1; i <= end; i++) - { - if(f_homopolymer_ch == 0) - { - f_homopolymer_ch = read[i]; - f_homopolymer_len = 1; - } - else - { - if(read[i] != f_homopolymer_ch) - { - break; - } - else - { - f_homopolymer_len++; - } - } - } - - char b_homopolymer_ch = 0; - long long b_homopolymer_len = 0; - - for (i = site - 1; i >= beg; i--) - { - if(b_homopolymer_ch == 0) - { - b_homopolymer_ch = read[i]; - b_homopolymer_len = 1; - } - else - { - if(read[i] != b_homopolymer_ch) - { - break; - } - else - { - b_homopolymer_len++; - } - } - } - - if(f_homopolymer_ch == read[site]) - { - f_homopolymer_len++; - } - else if(b_homopolymer_ch == read[site]) - { - b_homopolymer_len++; - } - - if(f_homopolymer_len >= threshold || b_homopolymer_len >= threshold) - { - return 1; - } - - if (read[site] == f_homopolymer_ch - && - b_homopolymer_ch == f_homopolymer_ch - && - (f_homopolymer_len + b_homopolymer_len >= threshold)) - { - return 1; - } - - - return 0; -} - - -inline int if_is_homopolymer_repeat(long long site, char* read, long long read_length) -{ - long long beg, end, i; - long long threshold = 3; - - beg = site - threshold; - if(beg < 0) - { - beg = 0; - } - - end = site + threshold; - - if(end >= read_length) - { - end = read_length - 1; - } - - char f_homopolymer_ch = 0; - long long f_homopolymer_len = 0; - - for (i = site + 1; i <= end; i++) - { - if(f_homopolymer_ch == 0) - { - f_homopolymer_ch = read[i]; - f_homopolymer_len = 1; - } - else - { - if(read[i] != f_homopolymer_ch) - { - break; - } - else - { - f_homopolymer_len++; - } - } - } - - char b_homopolymer_ch = 0; - long long b_homopolymer_len = 0; - - for (i = site - 1; i >= beg; i--) - { - if(b_homopolymer_ch == 0) - { - b_homopolymer_ch = read[i]; - b_homopolymer_len = 1; - } - else - { - if(read[i] != b_homopolymer_ch) - { - break; - } - else - { - b_homopolymer_len++; - } - } - } - - if(f_homopolymer_ch == read[site]) - { - f_homopolymer_len++; - } - else if(b_homopolymer_ch == read[site]) - { - b_homopolymer_len++; - } - - if(f_homopolymer_len >= threshold || b_homopolymer_len >= threshold) - { - return 1; - } - - if (read[site] == f_homopolymer_ch - && - b_homopolymer_ch == f_homopolymer_ch - && - (f_homopolymer_len + b_homopolymer_len >= threshold)) - { - return 1; - } - - - return 0; -} - -inline void InsertSNPVector(haplotype_evdience_alloc* h, haplotype_evdience* sub_list, long long sub_length, char misBase, -UC_Read* g_read) -{ - if(sub_length <= 0) - return; - long long i = 0; SnpStats *p = NULL; - kv_pushp(SnpStats, h->snp_stat, &p); - - // h->snp_stat[h->available_snp].id = h->available_snp; - // h->snp_stat[h->available_snp].occ_0 = 0; - // h->snp_stat[h->available_snp].occ_1 = 0; - // h->snp_stat[h->available_snp].occ_2 = 0; - // h->snp_stat[h->available_snp].overlap_num = 0; - // h->snp_stat[h->available_snp].site = sub_list[0].site; - // h->snp_stat[h->available_snp].is_homopolymer = - // if_is_homopolymer_strict(h->snp_stat[h->available_snp].site, g_read->seq, g_read->length); - // int8_t* vector = Get_SNP_Vector((*h), h->available_snp); - - p->id = h->snp_stat.n-1; - p->occ_0 = 0; - p->occ_1 = 0; - p->occ_2 = 0; - p->overlap_num = 0; - p->site = sub_list[0].site; - p->is_homopolymer = if_is_homopolymer_strict(p->site, g_read->seq, g_read->length); - int8_t* vector = Get_SNP_Vector((*h), p->id); - for (i = 0; i < sub_length; i++) - { - if(sub_list[i].type == 0) - { - vector[sub_list[i].overlapID] = 0; - // h->snp_stat[h->available_snp].occ_0++; - h->snp_stat.a[p->id].occ_0++; - } - else if(sub_list[i].type == 1 && sub_list[i].misBase == misBase) - { - vector[sub_list[i].overlapID] = 1; - // h->snp_stat[h->available_snp].occ_1++; - h->snp_stat.a[p->id].occ_1++; - } - else - { - vector[sub_list[i].overlapID] = 2; - // h->snp_stat[h->available_snp].occ_2++; - h->snp_stat.a[p->id].occ_2++; - } - // h->snp_stat[h->available_snp].overlap_num++; - h->snp_stat.a[p->id].overlap_num++; - } - - - // int new_occ_0 = h->snp_stat[h->available_snp].occ_0 + 1; - // int new_occ_1 = h->snp_stat[h->available_snp].occ_1; - int new_occ_0 = h->snp_stat.a[p->id].occ_0 + 1; - int new_occ_1 = h->snp_stat.a[p->id].occ_1; - - if(filter_snp(new_occ_0, new_occ_1, new_occ_0 + new_occ_1) == 0) ///Fix-attention:definitely wrong - { - // h->snp_stat[h->available_snp].score = -1; - h->snp_stat.a[p->id].score = -1; - } - else - { - h->core_snp++; - - - double consensus = new_occ_0 + new_occ_1 - abs(new_occ_0 - new_occ_1); - - consensus = consensus /((double)(new_occ_0 + new_occ_1)); - - ///50% vs 50%///Fix-attention:definitely wrong - if(new_occ_0 == new_occ_1) - { - consensus = consensus + 0.25; - } - else if(consensus >= 0.8) - { - consensus = consensus + 0.2; - } - else if(consensus >= 0.6) - { - consensus = consensus + 0.15; - } - else if(consensus >= 0.4) - { - consensus = consensus + 0.1; - } - else if(consensus >= 0.2) - { - consensus = consensus + 0.05; - } - - - consensus= consensus*((double)(new_occ_0 + new_occ_1)); - - // h->snp_stat[h->available_snp].score = consensus; - h->snp_stat.a[p->id].score = consensus; - } - - - - // h->available_snp++; -} - - -inline int calculate_score(int new_occ_0, int new_occ_1) -{ - if(new_occ_0 + new_occ_1 == 0) - { - return -1; - } - - if(filter_snp(new_occ_0, new_occ_1, new_occ_0 + new_occ_1) == 0) - { - return -1; - } - - double consensus = new_occ_0 + new_occ_1 - abs(new_occ_0 - new_occ_1); - - consensus = consensus /((double)(new_occ_0 + new_occ_1)); - - ///50% vs 50% - if(new_occ_0 == new_occ_1) - { - consensus = consensus + 0.25; - } - else if(consensus >= 0.8) - { - consensus = consensus + 0.2; - } - else if(consensus >= 0.6) - { - consensus = consensus + 0.15; - } - else if(consensus >= 0.4) - { - consensus = consensus + 0.1; - } - else if(consensus >= 0.2) - { - consensus = consensus + 0.05; - } - - - consensus= consensus*((double)(new_occ_0 + new_occ_1)); - - return consensus; -} - -inline void SetSnpMatrix(haplotype_evdience_alloc* h, uint32_t *nn_snp, uint64_t *overlap_num, int32_t set_matrix, void *km) -{ - if(nn_snp && overlap_num) { - if(!km) kv_resize(SnpStats, h->snp_stat, *nn_snp); - else kv_resize_km(km, SnpStats, h->snp_stat, *nn_snp); - h->snp_stat.n = 0; h->overlap = *overlap_num; h->core_snp = 0; - } - - if(set_matrix) { - uint64_t n_snp = nn_snp? *nn_snp:h->snp_stat.n; - uint64_t n_ovlp = overlap_num? *overlap_num:h->overlap; - uint64_t new_size = n_snp* n_ovlp; - if(h->snp_matrix_size < new_size) { - h->snp_matrix_size = new_size; - if(!km) REALLOC(h->snp_matrix, h->snp_matrix_size); - else KREALLOC(km, h->snp_matrix, h->snp_matrix_size); - } - memset(h->snp_matrix, -1, n_snp * n_ovlp); - - if(h->r_snp_size < n_ovlp) { - h->r_snp_size = n_ovlp; - if(!km) REALLOC(h->r_snp, h->r_snp_size); - else KREALLOC(km, h->r_snp, h->r_snp_size); - } - } -} - - -inline void init_SNP_IDs(Snp_ID_Vector_Alloc* SNP_IDs) -{ - SNP_IDs->max_snp_id = -1; - SNP_IDs->buffer_length = 0; - SNP_IDs->buffer_size = 1000; - SNP_IDs->buffer = (uint32_t*)malloc(sizeof(uint32_t) * SNP_IDs->buffer_size); - - SNP_IDs->IDs_length = 0; - SNP_IDs->IDs_size = 10; - SNP_IDs->IDs = (Snp_ID_Vector*)calloc(SNP_IDs->IDs_size, sizeof(Snp_ID_Vector)); - -} - -inline void clear_SNP_IDs(Snp_ID_Vector_Alloc* SNP_IDs) -{ - SNP_IDs->IDs_length = 0; - SNP_IDs->buffer_length = 0; - SNP_IDs->max_snp_id = -1; -} - -inline void destory_SNP_IDs(Snp_ID_Vector_Alloc* SNP_IDs) -{ - free(SNP_IDs->buffer); - free(SNP_IDs->IDs); -} - -inline void insert_SNP_IDs_addition(Snp_ID_Vector_Alloc* SNP_IDs, uint32_t* IDs_vec, int IDs_vec_length, - uint32_t occ_0, uint32_t occ_1, uint32_t homopolymer_num, uint32_t non_homopolymer_num) -{ - if(SNP_IDs->IDs_length + 1 > SNP_IDs->IDs_size) - { - SNP_IDs->IDs_size = SNP_IDs->IDs_size * 2; - SNP_IDs->IDs = (Snp_ID_Vector*)realloc(SNP_IDs->IDs, SNP_IDs->IDs_size * sizeof(Snp_ID_Vector)); - } - SNP_IDs->IDs[SNP_IDs->IDs_length].beg = SNP_IDs->buffer_length; - SNP_IDs->IDs[SNP_IDs->IDs_length].end = SNP_IDs->buffer_length + IDs_vec_length - 1; - - SNP_IDs->IDs[SNP_IDs->IDs_length].occ_0 = occ_0; - SNP_IDs->IDs[SNP_IDs->IDs_length].occ_1 = occ_1; - SNP_IDs->IDs[SNP_IDs->IDs_length].homopolymer_num = homopolymer_num; - SNP_IDs->IDs[SNP_IDs->IDs_length].non_homopolymer_num = non_homopolymer_num; - - - - if(SNP_IDs->buffer_length + IDs_vec_length > SNP_IDs->buffer_size) - { - SNP_IDs->buffer_size = (SNP_IDs->buffer_length + IDs_vec_length) * 2; - SNP_IDs->buffer = (uint32_t*)realloc(SNP_IDs->buffer, SNP_IDs->buffer_size * sizeof(uint32_t)); - } - memcpy(SNP_IDs->buffer + SNP_IDs->buffer_length, IDs_vec, IDs_vec_length*sizeof(uint32_t)); - - - SNP_IDs->IDs_length++; - SNP_IDs->buffer_length += IDs_vec_length; -} - - -inline void insert_SNP_IDs_addition(Snp_ID_Vector_Alloc* SNP_IDs, uint32_t* IDs_vec, int IDs_vec_length) -{ - if(SNP_IDs->IDs_length + 1 > SNP_IDs->IDs_size) - { - SNP_IDs->IDs_size = SNP_IDs->IDs_size * 2; - SNP_IDs->IDs = (Snp_ID_Vector*)realloc(SNP_IDs->IDs, SNP_IDs->IDs_size * sizeof(Snp_ID_Vector)); - } - SNP_IDs->IDs[SNP_IDs->IDs_length].beg = SNP_IDs->buffer_length; - SNP_IDs->IDs[SNP_IDs->IDs_length].end = SNP_IDs->buffer_length + IDs_vec_length - 1; - - - if(SNP_IDs->buffer_length + IDs_vec_length > SNP_IDs->buffer_size) - { - SNP_IDs->buffer_size = (SNP_IDs->buffer_length + IDs_vec_length) * 2; - SNP_IDs->buffer = (uint32_t*)realloc(SNP_IDs->buffer, SNP_IDs->buffer_size * sizeof(uint32_t)); - } - memcpy(SNP_IDs->buffer + SNP_IDs->buffer_length, IDs_vec, IDs_vec_length*sizeof(uint32_t)); - - - SNP_IDs->IDs_length++; - SNP_IDs->buffer_length += IDs_vec_length; -} - - -inline void init_DP_matrix(DP_matrix* dp, uint32_t snp_num) -{ - - if(snp_num > dp->snp_size) - { - dp->snp_size = snp_num; - dp->max = (uint32_t*)realloc(dp->max, dp->snp_size * sizeof(uint32_t)); - dp->max_for_sort = (uint64_t*)realloc(dp->max_for_sort, dp->snp_size * sizeof(uint64_t)); - dp->visit = (uint8_t*)realloc(dp->visit, dp->snp_size * sizeof(uint8_t)); - dp->buffer = (uint32_t*)realloc(dp->buffer, dp->snp_size * sizeof(uint32_t)); - dp->max_buffer = (uint32_t*)realloc(dp->max_buffer, dp->snp_size * sizeof(uint32_t)); - - - - dp->backtrack_length = (uint32_t*)realloc(dp->backtrack_length, dp->snp_size * sizeof(uint32_t)); - - dp->backtrack_size = snp_num*snp_num; - dp->backtrack = (uint32_t*)realloc(dp->backtrack, dp->backtrack_size * sizeof(uint32_t)); - } - - dp->snp_num = snp_num; - - clear_SNP_IDs(&(dp->SNP_IDs)); - - -} - -inline void InitHaplotypeEvdience_buf(haplotype_evdience_alloc* h, void *km) -{ - memset(h, 0, sizeof(haplotype_evdience_alloc)); - /****************************may have bugs********************************/ - memset(h->flag, 0, WINDOW_MAX_SIZE * sizeof(uint8_t)); - /****************************may have bugs********************************/ - // init_SNP_IDs(&(h->dp.SNP_IDs)); - memset(&(h->dp.SNP_IDs), 0, sizeof(h->dp.SNP_IDs)); - h->dp.SNP_IDs.max_snp_id = -1; -} - - -inline void InitHaplotypeEvdience(haplotype_evdience_alloc* h) -{ - - h->overlap = 0; - h->snp_matrix_size = 0; - h->snp_matrix = NULL; - h->r_snp_size = 0; - h->r_snp = NULL; - kv_init(h->snp_stat); - kv_init(h->snp_srt); - h->nn_snp = 0; - // h->snp_stat = NULL; - // h->snp = 0; - // h->snp_stat_size = 0; - // h->available_snp = 0; - - - h->sub_list_start = 0; - h->sub_list_length = 0; - h->length = 0; - h->size = 100; - h->list = (haplotype_evdience*)calloc(h->size, sizeof(haplotype_evdience)); - - /****************************may have bugs********************************/ - memset(h->flag, 0, WINDOW_MAX_SIZE * sizeof(uint8_t)); - /****************************may have bugs********************************/ - - - // h->dp.max = NULL; - // h->dp.colum = NULL; - // h->dp.colum_len = NULL; - // h->dp.matrix_size = 0; - // h->dp.snp_num = 0; - // h->dp.snp_size = 0; - h->dp.snp_num = 0; - h->dp.max = NULL; - h->dp.max_for_sort = NULL; - h->dp.visit = NULL; - h->dp.snp_size = 0; - h->dp.backtrack = NULL; - h->dp.backtrack_size = 0; - h->dp.backtrack_length = NULL; - h->dp.buffer = NULL; - h->dp.max_buffer = NULL; - - init_SNP_IDs(&(h->dp.SNP_IDs)); -} - -inline void StarSubListHaplotypeEvdience(haplotype_evdience_alloc* h) -{ - h->sub_list_start = h->length; -} - -inline void EndSubListHaplotypeEvdience(haplotype_evdience_alloc* h) -{ - h->sub_list_length = h->length - h->sub_list_start; -} - - -inline void destoryHaplotypeEvdience(haplotype_evdience_alloc* h) -{ - free(h->list); - // free(h->snp_stat); - kv_destroy(h->snp_stat); - kv_destroy(h->snp_srt); - free(h->snp_matrix); - free(h->r_snp); - free(h->dp.backtrack); - free(h->dp.max); - free(h->dp.max_for_sort); - free(h->dp.visit); - free(h->dp.backtrack_length); - free(h->dp.buffer); - free(h->dp.max_buffer); - destory_SNP_IDs(&(h->dp.SNP_IDs)); -} - - -inline void ResizeInitHaplotypeEvdience(haplotype_evdience_alloc* h) -{ - // h->snp = 0; - h->nn_snp = 0; - h->snp_stat.n = 0; - h->length = 0; - h->sub_list_start = 0; - h->sub_list_length = 0; - /****************************may have bugs********************************/ - memset(h->flag, 0, WINDOW_MAX_SIZE * sizeof(uint8_t)); - /****************************may have bugs********************************/ -} - -inline void RsetInitHaplotypeEvdienceFlag(haplotype_evdience_alloc* h, long long beg, long long useful_length) -{ - /****************************may have bugs********************************/ - memset(h->flag + beg, 0, useful_length * sizeof(uint8_t)); - /****************************may have bugs********************************/ -} - -inline void addHaplotypeEvdience(haplotype_evdience_alloc* h, haplotype_evdience* ev, void *km) -{ - if(h->length + 1 > h->size){ - h->size = h->length + 1; - kroundup32(h->size); - if(!km) REALLOC(h->list, h->size); - else KREALLOC(km, h->list, h->size); - // h->list = (haplotype_evdience*)realloc(h->list, sizeof(haplotype_evdience)*h->size); - } - - h->list[h->length] = (*ev); - h->length++; -} - -typedef struct -{ - char* corrected_read; - long long corrected_read_length; - long long last_boundary_length; - long long corrected_read_size; - long long corrected_base; - - uint64_t* overlapID; - uint64_t length; - uint64_t lengthNT; - uint64_t size; - uint64_t start_i; - - /****************************may have bugs********************************/ - // char overlap_region[WINDOW + THRESHOLD*2 + 10]; - // char overlap_region_group[GROUP_SIZE][WINDOW + THRESHOLD*2 + 10]; - // char path[WINDOW + THRESHOLD*2 + 10]; - // Word matrix_bit[((WINDOW + 10)<<3)]; - - char overlap_region[WINDOW_MAX_SIZE + THRESHOLD_MAX_SIZE*2 + 10]; - char overlap_region_group[GROUP_SIZE][WINDOW_MAX_SIZE + THRESHOLD_MAX_SIZE*2 + 10]; - char path[WINDOW_MAX_SIZE + THRESHOLD_MAX_SIZE*2 + 10]; - - char path_fix[WINDOW_MAX_SIZE + THRESHOLD_MAX_SIZE*2 + 10]; - char overlap_region_fix[WINDOW_MAX_SIZE + THRESHOLD_MAX_SIZE*2 + 10]; - Word matrix_bit[((WINDOW_MAX_SIZE + 10)<<3)]; - /****************************may have bugs********************************/ - - int path_length; - __m128i Peq_SSE[256]; -} Correct_dumy; - -typedef struct -{ - Correct_dumy dumy; - Cigar_record cigar; - Cigar_record tmp_cigar; - long long obtained_cigar_length; -} -Round2_alignment; - -void init_Round2_alignment_buf(Round2_alignment* h, void *km); -void init_Round2_alignment(Round2_alignment* h); -void destory_Round2_alignment(Round2_alignment* h); -void clear_Round2_alignment(Round2_alignment* h); - -typedef struct { - int32_t c_qs, c_qe, c_ts, c_te; //[c_qs, c_qe) && [c_ts, c_te) - int32_t c_wsid, c_weid, c_wsii, c_weii;//[c_wsid, c_weid] && [c_wsii, c_weii) - int32_t rev, sfx_e, pfx_e, mid_e, oid; -} rtrace_t; - -typedef struct { - rtrace_t *a; - size_t n, m; -} kv_rtrace_t; - -void correct_overlap(overlap_region_alloc* overlap_list, All_reads* R_INF, - UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, Graph* g, Graph* DAGCon, - Cigar_record* current_cigar, haplotype_evdience_alloc* hap, - Round2_alignment* second_round, kvec_t_u64_warp* v_idx, window_list_alloc* win_ciagr_buf, - int force_repeat, int is_consensus, int* fully_cov, int* abnormal); -void init_Correct_dumy_buf(Correct_dumy* list, void *km); -void init_Correct_dumy(Correct_dumy* list); -void destory_Correct_dumy(Correct_dumy* list); -void clear_Correct_dumy(Correct_dumy* list, overlap_region_alloc* overlap_list, void *km); -void clear_Correct_dumy_pure(Correct_dumy* list); -void get_seq_from_Graph(Graph* backbone, Graph* DAGCon, Correct_dumy* dumy, Cigar_record* current_cigar, char* self_string, -char* r_string, long long r_string_length, long long r_string_site); -void init_Cigar_record(Cigar_record* dummy); -void init_Cigar_record_buf(Cigar_record* dummy, void *km); -void destory_Cigar_record(Cigar_record* dummy); -void clear_Cigar_record(Cigar_record* dummy); -void add_new_cell_to_cigar_record(Cigar_record* dummy, uint32_t len, uint32_t type); -void add_existing_cell_to_cigar_record(Cigar_record* dummy, uint32_t len, uint32_t type); -void add_new_cell_to_cigar_record_with_different_base(Cigar_record* dummy, uint32_t len, uint32_t type, char* seq); -void add_existing_cell_to_cigar_record_with_different_base(Cigar_record* dummy, uint32_t len, uint32_t type, char* seq); - - -void correct_ul_overlap(overlap_region_alloc* overlap_list, const ul_idx_t *uref, - UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, - Graph* g, Graph* DAGCon, Cigar_record* current_cigar, - haplotype_evdience_alloc* hap, Round2_alignment* second_round, - kvec_t_u64_warp* v_idx, window_list_alloc* win_ciagr_buf, - int force_repeat, int is_consensus, int* fully_cov, int* abnormal, - double max_ov_diff_ec, long long winLen, void *km); -void ul_lalign(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, const ug_opt_t *uopt, char *qstr, - uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, bit_extz_t *exz, - haplotype_evdience_alloc* hap, kvec_t_u64_warp* v_idx, overlap_region *aux_o, - double e_rate, int64_t wl, kv_ul_ov_t *aln, int64_t sid, uint64_t hpc_k, st_mt_t *stb, idx_emask_t *mm, mask_ul_ov_t *mk, void *km); - -void ul_lalign_old_ed(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, char *qstr, - uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, - haplotype_evdience_alloc* hap, kvec_t_u64_warp* v_idx, - double e_rate, int64_t wl, uint64_t is_base, void *km); - -void lchain_align(overlap_region_alloc* overlap_list, const ul_idx_t *uref, - UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, - Graph* g, Graph* DAGCon, Cigar_record* current_cigar, - haplotype_evdience_alloc* hap, Round2_alignment* second_round, - kvec_t_u64_warp* v_idx, window_list_alloc* win_ciagr_buf, - int force_repeat, int is_consensus, int* fully_cov, int* abnormal, - double max_ov_diff_ec, long long winLen, void *km); - -void ug_lalign(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, const ug_opt_t *uopt, - char *qstr, uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, bit_extz_t *exz, - overlap_region *aux_o, double e_rate, int64_t wl, int64_t sid, uint64_t khit, uint64_t chain_cut, - void *km); -/*** - type: - 0. match - 1. mismatch - 2. insertion - 3. deletion - ***/ -inline void add_cigar_record(char* seq, uint32_t len, Cigar_record* dummy, uint32_t type) -{ - if(type == 0)///match - { - ///add to existing cell, just increase length - if((uint32_t)dummy->current_operation == type) - { - add_existing_cell_to_cigar_record(dummy, len, type); - } - else ///add to new cell - { - add_new_cell_to_cigar_record(dummy, len, type); - } - - dummy->new_read_length += len; - } - else if(type == 1)///mismatch - { - ///add to existing cell, just increase length - ///and add different bases - if((uint32_t)dummy->current_operation == type) - { - add_existing_cell_to_cigar_record_with_different_base(dummy, len, type, seq); - } - else - { - add_new_cell_to_cigar_record_with_different_base(dummy, len, type, seq); - } - - dummy->new_read_length += len; - } - else if(type == 3)///deletion, the bases in previous read will be removed - { - ///add to existing cell, just increase length - ///and add different bases - if((uint32_t)dummy->current_operation == type) - { - add_existing_cell_to_cigar_record_with_different_base(dummy, len, type, seq); - } - else - { - add_new_cell_to_cigar_record_with_different_base(dummy, len, type, seq); - } - } - else if(type == 2)///insertion - { - /** - ///add to existing cell, just increase length - if(dummy->current_operation == type) - { - add_existing_cell_to_cigar_record(dummy, len, type); - } - else ///add to new cell - { - add_new_cell_to_cigar_record(dummy, len, type); - } - **/ - ///add to existing cell, just increase length - ///and add different bases - if((uint32_t)dummy->current_operation == type) - { - add_existing_cell_to_cigar_record_with_different_base(dummy, len, type, seq); - } - else - { - add_new_cell_to_cigar_record_with_different_base(dummy, len, type, seq); - } - - dummy->new_read_length += len; - } - - dummy->current_operation = type; -} - -int verify_cigar_2(char* x, int x_len, char* y, int y_len, Cigar_record* cigar, int error); - - -int verify_single_window(long long x_start, long long x_end, -long long overlap_x_s, long long overlap_y_s, int x_id, -int y_id, int y_strand, char* x_buffer, char* y_buffer, -All_reads* R_INF); - -void init_Cigar_record_alloc(Cigar_record_alloc* x); -void resize_Cigar_record_alloc(Cigar_record_alloc* x, long long new_size); -void destory_Cigar_record_alloc(Cigar_record_alloc* x); - -void afine_gap_alignment(const char *qseq, uint8_t* qnum, const int ql, -const char *tseq, uint8_t* tnum, const int tl, const uint8_t *c2n, const int strand, -int sc_mch, int sc_mis, int gapo, int gape, int bandLen, int zdrop, int end_bonus, -long long* max_q_pos, long long* max_t_pos, long long* global_score, -long long* extention_score, long long* q_boundary_score, long long* q_boundary_t_coordinate, -long long* t_boundary_score, long long* t_boundary_q_coordinate, -long long* droped, int mode); -// void correct_overlap_high_het(overlap_region_alloc* overlap_list, All_reads* R_INF, -// UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read); -long long get_affine_gap_score(overlap_region* ovc, UC_Read* g_read, UC_Read* overlap_read, uint8_t* x_num, -uint8_t* y_num, uint64_t EstimateXOlen, uint64_t EstimateYOlen); -int collect_hp_regions(overlap_region_alloc* olist, All_reads* R_INF, kvec_t_u8_warp* k_flag, float hp_rate, int rlen, FILE* fp); - -inline int if_exact_match(char* x, long long xLen, char* y, long long yLen, long long xBeg, long long xEnd, long long yBeg, long long yEnd) -{ - long long overlapLen = xEnd - xBeg + 1; - - if(yEnd - yBeg + 1 == overlapLen) - { - if(memcmp(x+xBeg, y+yBeg, overlapLen)==0) return 1; - } - - return 0; -} - -inline void get_cigar_cell(window_list *idx, window_list_alloc *cc, uint32_t i, uint8_t *c, uint32_t *len) -{ - uint16_t p = cc->c.a[idx->cidx+i]; - (*c) = (uint8_t)(p>>14); (*len) = (p&((uint16_t)0x3fff)); -} - -inline void push_cigar_cell(window_list_alloc *res, uint8_t c, uint32_t len) -{ - uint16_t p = c; p <<= 14; p += (uint16_t)len; - kv_push(uint16_t, res->c, p); -} -int64_t get_num_wins(int64_t s, int64_t e, int64_t block_s); -void append_unmatched_wins(overlap_region *z, int64_t block_s); - -///[w_s, w_e] -inline int64_t get_win_id_by_s(overlap_region *z, int64_t w_s, int64_t block_s, int64_t *w_e) -{ - int64_t n_s = ((z->x_pos_s/block_s)*block_s), wid = (w_s-n_s)/block_s; - if(w_e) { - (*w_e) = n_s + (wid+1)*block_s - 1; - if((*w_e) > z->x_pos_e) (*w_e) = z->x_pos_e; - } - return wid; -} - -///[w_s, w_e] -inline int64_t get_win_id_by_e(overlap_region *z, int64_t w_e, int64_t block_s, int64_t *w_s) -{ - int64_t n_s = ((z->x_pos_s/block_s)*block_s), wid = (w_e-n_s)/block_s; - if(w_s) { - (*w_s) = n_s + wid*block_s; - if((*w_s) < z->x_pos_s) (*w_s) = z->x_pos_s; - } - return wid; -} - -///[w_s, w_e] -inline void get_win_se_by_normalize_xs(overlap_region *z, int64_t norm_w_s, int64_t block_s, int64_t *w_s, int64_t *w_e) -{ - int64_t n_s = ((z->x_pos_s/block_s)*block_s), wid = (norm_w_s-n_s)/block_s; - if(w_s) { - (*w_s) = n_s + wid*block_s; - if((*w_s) < z->x_pos_s) (*w_s) = z->x_pos_s; - } - if(w_e) { - (*w_e) = n_s + (wid+1)*block_s - 1; - if((*w_e) > z->x_pos_e) (*w_e) = z->x_pos_e; - } -} - -void inline resize_UC_Read(UC_Read *z, int64_t s) -{ - if(z->size < s) { - REALLOC(z->seq, s); z->size = s; - } -} - -void update_sketch_trace(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, -All_reads *rref, UC_Read* tu, asg64_v* idx, asg64_v *b0, asg64_v *b1, int64_t ql, int64_t wl, -kv_ul_ov_t *aln, uint64_t rid, int64_t max_lgap, double sgap_rate); - -int64_t infer_rovlp(ul_ov_t *li, ul_ov_t *lj, uc_block_t *bi, uc_block_t *bj, All_reads *ridx, ma_ug_t *ug); -void convert_ul_ov_t(ul_ov_t *des, overlap_region *src, ma_ug_t *ug); -uint64_t check_connect_ug(const ul_idx_t *uref, uint32_t v, uint32_t w, int64_t bw, double diff_ec_ul, int64_t dq); -uint64_t check_connect_rg(const ul_idx_t *uref, const ug_opt_t *uopt, uint32_t uv, uint32_t uw, int64_t bw, double diff_ec_ul, int64_t dq); -uint32_t govlp_check(const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, ul_ov_t *li, ul_ov_t *lj); -void ul_rid_lalign_adv(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, const ug_opt_t *uopt, - char *qstr, uint64_t ql, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, - int64_t wl, kv_ul_ov_t *aln, kv_ul_ov_t *cln, kv_rtrace_t *trace, int64_t sid, uint64_t khit, void *km); - -#define copy_asg_arr(des, src) ((des).a = (src).a, (des).n = (src).n, (des).m = (src).m) -#define is_ualn_win(a) (((a).error==INT16_MAX)&&((a).clen==0)&&((a).extra_end<0)) -#define is_exact_aln(a) (((a).error0)) -#define is_est_aln(a) (((a).error +#include "Hash_Table.h" +#include "Levenshtein_distance.h" +#include "POA.h" +#include "Process_Read.h" +#include "Correct.h" +#include "kalloc.h" + +//#define CORRECT_THRESHOLD 0.70 +#define CORRECT_THRESHOLD 0.60 +///#define CORRECT_THRESHOLD_SECOND 0.55 +#define CORRECT_THRESHOLD_HOMOPOLYMER 0.515 +#define MIN_COVERAGE_THRESHOLD 3 +#define CORRECT_INDEL_LENGTH 2 +#define MISMATCH 1 +#define INSERTION 2 +#define DELETION 3 +#define ERROR_RATE 1.5 +#define UL_TOPN 50 +#define SGAP 16 +#define MAX_LGAP(ql) ((((ql)*0.2)<256)?((ql)*0.2):256) + +#define WINDOW_MAX_SIZE (WINDOW + (int)(1.0 / HA_MIN_OV_DIFF) + 3) // TODO: why 1/max_ov_diff? + +///#define FLAG_THRE 0 + +#define MAX(x, y) (((x) >= (y))?(x):(y)) +#define MIN(x, y) (((x) <= (y))?(x):(y)) +#define DIFF(x, y) ((MAX((x), (y))) - (MIN((x), (y)))) +#define OVERLAP(x_start, x_end, y_start, y_end) (MIN(x_end, y_end) - MAX(x_start, y_start) + 1) +///#define OVERLAP(x_start, x_end, y_start, y_end) MIN(x_end, y_end) - MAX(x_start, y_start) + 1 + +#define Get_MisMatch_Base(RECORD) (s_H[(RECORD>>3)]) +#define Get_Match_Base(RECORD) (s_H[(RECORD&7)]) +#define Coverage_Threshold(coverage, r_len) (coverage*r_len*1.1) + + + +#define Get_Max_DP_Value(RECORD) (RECORD>>32) +#define Get_Max_DP_ID(RECORD) (RECORD&(uint64_t)0xffffffff) + +#define Adjust_Threshold(threshold, x_len) ((threshold == 0 && x_len >= 4)? 1: threshold) + +typedef struct +{ + long long read_length; + long long window_length; + long long window_num; + long long window_start; + long long window_end; + long long tail_length; + int terminal; +}Window_Pool; + +inline void init_Window_Pool(Window_Pool* dumy, long long read_length, long long window_length, long long tail_length) +{ + dumy->terminal = 0; + dumy->read_length = read_length; + dumy->window_length = window_length; + dumy->tail_length = tail_length; + + dumy->window_start = 0; + dumy->window_end = dumy->window_length - 1; + if (dumy->window_end >= dumy->read_length) + { + dumy->window_end = dumy->read_length - 1; + } + + dumy->window_num = (dumy->read_length + dumy->window_length - 1) / dumy->window_length; +} + +inline int get_Window(Window_Pool* dumy, long long* w_beg, long long* w_end) +{ + (*w_beg) = dumy->window_start; + (*w_end) = dumy->window_end; + + if(dumy->window_end == dumy->read_length - 1) + { + if(dumy->terminal == 1 || dumy->read_length == 0) + { + return 0; + } + else if(dumy->terminal == 0) + { + dumy->terminal = 1; + } + } + + + dumy->window_start = dumy->window_start + dumy->window_length; + dumy->window_end = dumy->window_end + dumy->window_length; + if (dumy->window_end >= dumy->read_length) + { + dumy->window_end = dumy->read_length - 1; + } + return 1; +} + + +typedef struct +{ + /**[0-1] bits are type:**/ + /**[2-31] bits are length**/ + char current_operation; + int current_operation_length; + uint32_t* record; + uint64_t size; + uint64_t length; + uint32_t new_read_length; + + + char* lost_base; + uint64_t lost_base_size; + uint64_t lost_base_length; + + +}Cigar_record; + + +typedef struct +{ + long long length; + long long size; + Cigar_record* buffer; +}Cigar_record_alloc; + + +typedef struct +{ + ////the position of snp in read itself + uint32_t site; + ////the overlapID + uint32_t overlapID; + ////the position of snp in that overlap + uint32_t overlapSite; + ///there are several types: 0: equal to read 1: not equal to read, but it is a mismatch 2: is a gap + uint8_t type; + uint32_t cov; + ///misbase + char misBase; +}haplotype_evdience; + +#define hh_tp(z) (((z).type&1)) +#define hh_hp(z) ((((z).type>>1)&1)) +#define hh_bq(z) ((((z).type>>2))&sc_bm) +#define hh_wq(z) ((((z).type>>(sc_bn+2)))&sc_bm) + +typedef struct +{ + ///the id of this snp + uint32_t id; + uint32_t overlap_num; + uint32_t occ_0; + uint32_t occ_1; + uint32_t occ_2; + uint32_t homopolymer_num; + uint32_t non_homopolymer_num; + int score; + ////the position of snp in read itself + uint32_t site; + uint8_t is_homopolymer; +} +SnpStats; + + + +typedef struct +{ + uint32_t beg; + uint32_t end; + uint32_t occ_0; + uint32_t occ_1; + uint32_t homopolymer_num; + uint32_t non_homopolymer_num; + uint32_t is_remove; +} +Snp_ID_Vector; + + +typedef struct +{ + long long IDs_size; + long long IDs_length; + long long max_snp_id; + Snp_ID_Vector* IDs; + + long long buffer_size; + long long buffer_length; + uint32_t* buffer; +} +Snp_ID_Vector_Alloc; + +#define Get_DP_Backtrack_Column(matrix, i) (matrix.backtrack + matrix.snp_num * i) +#define Get_DP_Backtrack_Column_Length(matrix, i) (matrix.snp_num) + + +typedef struct +{ + // uint32_t snp_size; + // uint32_t snp_num; + // uint32_t* max; + // uint32_t* colum_len; + // uint32_t* colum; + // uint32_t matrix_size; + + uint32_t snp_num; + + uint8_t* visit; + uint32_t* max; + uint64_t* max_for_sort; + + + + uint32_t snp_size; + + uint32_t* backtrack_length; + uint32_t* backtrack; + uint32_t backtrack_size; + + + uint32_t* buffer; + uint32_t* max_buffer; + + + int max_snp_num; + ///int max_snp_ID; + int max_score; + int current_snp_num; + + + Snp_ID_Vector_Alloc SNP_IDs; +} +DP_matrix; + + +#define Get_SNP_Martix_Size(matrix) (matrix.snp * matrix.overlap) +#define Get_SNP_Vector(matrix, i) (matrix.snp_matrix + matrix.overlap * i) +#define Get_SNP_Vector_Length(matrix) (matrix.overlap) +// #define Get_Result_SNP_Vector(matrix) (matrix.snp_matrix + matrix.overlap*matrix.snp) +#define Get_Result_SNP_Vector(matrix) (matrix.r_snp) + +typedef struct +{ + SnpStats* a; + size_t n,m; +}kv_SnpStats_t; + +typedef struct +{ + haplotype_evdience* list; + uint32_t sub_list_start; + uint32_t sub_list_length; + uint32_t length; + uint32_t size; + + /****************************may have bugs********************************/ + uint8_t flag[WINDOW_MAX_SIZE]; + /****************************may have bugs********************************/ + + + uint32_t core_snp; + uint32_t overlap; + int8_t *snp_matrix; + uint32_t snp_matrix_size; + int8_t *r_snp; + uint32_t r_snp_size; + SnpStats result_stat; + + kv_SnpStats_t snp_stat; + uint32_t nn_snp; + kvec_t(uint64_t) snp_srt; + // SnpStats* snp_stat; + // uint32_t snp; + // uint32_t snp_stat_size; + // uint32_t available_snp; + + DP_matrix dp; +} +haplotype_evdience_alloc; + +inline int filter_snp(int x, int y, int total) +{ + double available; + + if(x <= y) + { + available = x; + } + else + { + available = y; + } + double threshold = 0.30; + available = available/((double)(total)); + if(available <= threshold && available < 6) + { + return 0; + } + return 1; +} + + +inline int filter_one_snp(int occ_0, int occ_1, int total) +{ + + + double available; + + if(occ_0 <= occ_1) + { + available = occ_0; + } + else + { + available = occ_1; + } + double threshold = 0.35; + available = available/((double)(total)); + + + + if(available < threshold || occ_0 < MIN_COVERAGE_THRESHOLD + 1 || total < 10) + ///if(available < threshold || total < 10) + { + return 0; + } + return 1; +} + +inline void count_nearby_snps(haplotype_evdience_alloc* hap, uint32_t* SNPs, int SNPsLen, int* nearsnp, int* non_nearsnps) +{ + long long i, current_id, large_id, small_id; + long long distance = 10; + + + + if(SNPsLen == 1) + { + (*non_nearsnps) = 1; + (*nearsnp) = 0; + return; + } + + if(SNPsLen == 0) + { + (*nearsnp) = 0; + (*non_nearsnps) = 0; + return; + } + + (*nearsnp) = 0; + (*non_nearsnps) = 0; + + for (i = 0; i < SNPsLen; i++) + { + if(i > 0 && i < SNPsLen - 1) + { + current_id= SNPs[i]; + + ///since SNPs[i - 1].site is larger than SNPs[i] + large_id = SNPs[i - 1]; + small_id = SNPs[i + 1]; + + + if(hap->snp_stat.a[large_id].site - hap->snp_stat.a[current_id].site < distance + || + hap->snp_stat.a[current_id].site - hap->snp_stat.a[small_id].site < distance) + { + (*nearsnp)++; + } + else + { + (*non_nearsnps)++; + } + + if(hap->snp_stat.a[current_id].site > hap->snp_stat.a[large_id].site || + hap->snp_stat.a[current_id].site < hap->snp_stat.a[small_id].site) + { + fprintf(stderr, "error\n"); + } + } + else if(i == 0) + { + current_id= SNPs[i]; + small_id = SNPs[i + 1]; + if(hap->snp_stat.a[current_id].site - hap->snp_stat.a[small_id].site < distance) + { + (*nearsnp)++; + } + else + { + (*non_nearsnps)++; + } + + if(hap->snp_stat.a[current_id].site < hap->snp_stat.a[small_id].site) + { + fprintf(stderr, "error\n"); + } + } + else + { + large_id = SNPs[i - 1]; + current_id= SNPs[i]; + if(hap->snp_stat.a[large_id].site - hap->snp_stat.a[current_id].site < distance) + { + (*nearsnp)++; + } + else + { + (*non_nearsnps)++; + } + + if(hap->snp_stat.a[current_id].site > hap->snp_stat.a[large_id].site) + { + fprintf(stderr, "error\n"); + } + + } + + } + + if((*nearsnp) + (*non_nearsnps) != SNPsLen) + { + fprintf(stderr, "(*nearsnp): %d, (*non_nearsnps): %d, SNPsLen: %d\n", (*nearsnp), (*non_nearsnps), SNPsLen); + } +} + +inline int filter_one_snp_advance_nearby(haplotype_evdience_alloc* hap, int occ_0, int occ_1, int total, +long long homopolymer_num, long long non_homopolymer_num, +uint32_t* SNPs, int SNPsLen) +{ + + + double available; + + if(occ_0 <= occ_1) + { + available = occ_0; + } + else + { + available = occ_1; + } + int min = available; + + double threshold1 = 0.35; + double threshold2 = 0.24; + available = available/((double)(total)); + + + + ///if((non_homopolymer_num > 0 && min >= 5) || (min >= 6)) + if(min >= 5) + { + if(available < threshold2 || total < 10) + { + return 0; + } + } + else if(available < threshold1 || occ_0 < MIN_COVERAGE_THRESHOLD + 1 || total < 10) + { + return 0; + } + return 1; +} + + +inline int if_is_homopolymer_strict(long long site, char* read, long long read_length) +{ + long long beg, end, i; + long long threshold = 3; + + beg = site - threshold; + if(beg < 0) + { + beg = 0; + } + + end = site + threshold; + + if(end >= read_length) + { + end = read_length - 1; + } + + char f_homopolymer_ch = 0; + long long f_homopolymer_len = 0; + + for (i = site + 1; i <= end; i++) + { + if(f_homopolymer_ch == 0) + { + f_homopolymer_ch = read[i]; + f_homopolymer_len = 1; + } + else + { + if(read[i] != f_homopolymer_ch) + { + break; + } + else + { + f_homopolymer_len++; + } + } + } + + char b_homopolymer_ch = 0; + long long b_homopolymer_len = 0; + + for (i = site - 1; i >= beg; i--) + { + if(b_homopolymer_ch == 0) + { + b_homopolymer_ch = read[i]; + b_homopolymer_len = 1; + } + else + { + if(read[i] != b_homopolymer_ch) + { + break; + } + else + { + b_homopolymer_len++; + } + } + } + + if(f_homopolymer_ch == read[site]) + { + f_homopolymer_len++; + } + else if(b_homopolymer_ch == read[site]) + { + b_homopolymer_len++; + } + + if(f_homopolymer_len >= threshold || b_homopolymer_len >= threshold) + { + return 1; + } + + if (read[site] == f_homopolymer_ch + && + b_homopolymer_ch == f_homopolymer_ch + && + (f_homopolymer_len + b_homopolymer_len >= threshold)) + { + return 1; + } + + + return 0; +} + + +inline int if_is_homopolymer_repeat(long long site, char* read, long long read_length) +{ + long long beg, end, i; + long long threshold = 3; + + beg = site - threshold; + if(beg < 0) + { + beg = 0; + } + + end = site + threshold; + + if(end >= read_length) + { + end = read_length - 1; + } + + char f_homopolymer_ch = 0; + long long f_homopolymer_len = 0; + + for (i = site + 1; i <= end; i++) + { + if(f_homopolymer_ch == 0) + { + f_homopolymer_ch = read[i]; + f_homopolymer_len = 1; + } + else + { + if(read[i] != f_homopolymer_ch) + { + break; + } + else + { + f_homopolymer_len++; + } + } + } + + char b_homopolymer_ch = 0; + long long b_homopolymer_len = 0; + + for (i = site - 1; i >= beg; i--) + { + if(b_homopolymer_ch == 0) + { + b_homopolymer_ch = read[i]; + b_homopolymer_len = 1; + } + else + { + if(read[i] != b_homopolymer_ch) + { + break; + } + else + { + b_homopolymer_len++; + } + } + } + + if(f_homopolymer_ch == read[site]) + { + f_homopolymer_len++; + } + else if(b_homopolymer_ch == read[site]) + { + b_homopolymer_len++; + } + + if(f_homopolymer_len >= threshold || b_homopolymer_len >= threshold) + { + return 1; + } + + if (read[site] == f_homopolymer_ch + && + b_homopolymer_ch == f_homopolymer_ch + && + (f_homopolymer_len + b_homopolymer_len >= threshold)) + { + return 1; + } + + + return 0; +} + +inline void InsertSNPVector(haplotype_evdience_alloc* h, haplotype_evdience* sub_list, long long sub_length, char misBase, +UC_Read* g_read) +{ + if(sub_length <= 0) + return; + long long i = 0; SnpStats *p = NULL; + kv_pushp(SnpStats, h->snp_stat, &p); + + // h->snp_stat[h->available_snp].id = h->available_snp; + // h->snp_stat[h->available_snp].occ_0 = 0; + // h->snp_stat[h->available_snp].occ_1 = 0; + // h->snp_stat[h->available_snp].occ_2 = 0; + // h->snp_stat[h->available_snp].overlap_num = 0; + // h->snp_stat[h->available_snp].site = sub_list[0].site; + // h->snp_stat[h->available_snp].is_homopolymer = + // if_is_homopolymer_strict(h->snp_stat[h->available_snp].site, g_read->seq, g_read->length); + // int8_t* vector = Get_SNP_Vector((*h), h->available_snp); + + p->id = h->snp_stat.n-1; + p->occ_0 = 0; + p->occ_1 = 0; + p->occ_2 = 0; + p->overlap_num = 0; + p->site = sub_list[0].site; + p->is_homopolymer = if_is_homopolymer_strict(p->site, g_read->seq, g_read->length); + int8_t* vector = Get_SNP_Vector((*h), p->id); + for (i = 0; i < sub_length; i++) + { + if(sub_list[i].type == 0) + { + vector[sub_list[i].overlapID] = 0; + // h->snp_stat[h->available_snp].occ_0++; + h->snp_stat.a[p->id].occ_0++; + } + else if(sub_list[i].type == 1 && sub_list[i].misBase == misBase) + { + vector[sub_list[i].overlapID] = 1; + // h->snp_stat[h->available_snp].occ_1++; + h->snp_stat.a[p->id].occ_1++; + } + else + { + vector[sub_list[i].overlapID] = 2; + // h->snp_stat[h->available_snp].occ_2++; + h->snp_stat.a[p->id].occ_2++; + } + // h->snp_stat[h->available_snp].overlap_num++; + h->snp_stat.a[p->id].overlap_num++; + } + + + // int new_occ_0 = h->snp_stat[h->available_snp].occ_0 + 1; + // int new_occ_1 = h->snp_stat[h->available_snp].occ_1; + int new_occ_0 = h->snp_stat.a[p->id].occ_0 + 1; + int new_occ_1 = h->snp_stat.a[p->id].occ_1; + + if(filter_snp(new_occ_0, new_occ_1, new_occ_0 + new_occ_1) == 0) ///Fix-attention:definitely wrong + { + // h->snp_stat[h->available_snp].score = -1; + h->snp_stat.a[p->id].score = -1; + } + else + { + h->core_snp++; + + + double consensus = new_occ_0 + new_occ_1 - abs(new_occ_0 - new_occ_1); + + consensus = consensus /((double)(new_occ_0 + new_occ_1)); + + ///50% vs 50%///Fix-attention:definitely wrong + if(new_occ_0 == new_occ_1) + { + consensus = consensus + 0.25; + } + else if(consensus >= 0.8) + { + consensus = consensus + 0.2; + } + else if(consensus >= 0.6) + { + consensus = consensus + 0.15; + } + else if(consensus >= 0.4) + { + consensus = consensus + 0.1; + } + else if(consensus >= 0.2) + { + consensus = consensus + 0.05; + } + + + consensus= consensus*((double)(new_occ_0 + new_occ_1)); + + // h->snp_stat[h->available_snp].score = consensus; + h->snp_stat.a[p->id].score = consensus; + } + + + + // h->available_snp++; +} + + +inline int calculate_score(int new_occ_0, int new_occ_1) +{ + if(new_occ_0 + new_occ_1 == 0) + { + return -1; + } + + if(filter_snp(new_occ_0, new_occ_1, new_occ_0 + new_occ_1) == 0) + { + return -1; + } + + double consensus = new_occ_0 + new_occ_1 - abs(new_occ_0 - new_occ_1); + + consensus = consensus /((double)(new_occ_0 + new_occ_1)); + + ///50% vs 50% + if(new_occ_0 == new_occ_1) + { + consensus = consensus + 0.25; + } + else if(consensus >= 0.8) + { + consensus = consensus + 0.2; + } + else if(consensus >= 0.6) + { + consensus = consensus + 0.15; + } + else if(consensus >= 0.4) + { + consensus = consensus + 0.1; + } + else if(consensus >= 0.2) + { + consensus = consensus + 0.05; + } + + + consensus= consensus*((double)(new_occ_0 + new_occ_1)); + + return consensus; +} + +inline void SetSnpMatrix(haplotype_evdience_alloc* h, uint32_t *nn_snp, uint64_t *overlap_num, int32_t set_matrix, void *km) +{ + if(nn_snp && overlap_num) { + if(!km) kv_resize(SnpStats, h->snp_stat, *nn_snp); + else kv_resize_km(km, SnpStats, h->snp_stat, *nn_snp); + h->snp_stat.n = 0; h->overlap = *overlap_num; h->core_snp = 0; + } + + if(set_matrix) { + uint64_t n_snp = nn_snp? *nn_snp:h->snp_stat.n; + uint64_t n_ovlp = overlap_num? *overlap_num:h->overlap; + uint64_t new_size = n_snp* n_ovlp; + if(h->snp_matrix_size < new_size) { + h->snp_matrix_size = new_size; + if(!km) REALLOC(h->snp_matrix, h->snp_matrix_size); + else KREALLOC(km, h->snp_matrix, h->snp_matrix_size); + } + memset(h->snp_matrix, -1, n_snp * n_ovlp); + + if(h->r_snp_size < n_ovlp) { + h->r_snp_size = n_ovlp; + if(!km) REALLOC(h->r_snp, h->r_snp_size); + else KREALLOC(km, h->r_snp, h->r_snp_size); + } + } +} + + +inline void init_SNP_IDs(Snp_ID_Vector_Alloc* SNP_IDs) +{ + SNP_IDs->max_snp_id = -1; + SNP_IDs->buffer_length = 0; + SNP_IDs->buffer_size = 1000; + SNP_IDs->buffer = (uint32_t*)malloc(sizeof(uint32_t) * SNP_IDs->buffer_size); + + SNP_IDs->IDs_length = 0; + SNP_IDs->IDs_size = 10; + SNP_IDs->IDs = (Snp_ID_Vector*)calloc(SNP_IDs->IDs_size, sizeof(Snp_ID_Vector)); + +} + +inline void clear_SNP_IDs(Snp_ID_Vector_Alloc* SNP_IDs) +{ + SNP_IDs->IDs_length = 0; + SNP_IDs->buffer_length = 0; + SNP_IDs->max_snp_id = -1; +} + +inline void destory_SNP_IDs(Snp_ID_Vector_Alloc* SNP_IDs) +{ + free(SNP_IDs->buffer); + free(SNP_IDs->IDs); +} + +inline void insert_SNP_IDs_addition(Snp_ID_Vector_Alloc* SNP_IDs, uint32_t* IDs_vec, int IDs_vec_length, + uint32_t occ_0, uint32_t occ_1, uint32_t homopolymer_num, uint32_t non_homopolymer_num) +{ + if(SNP_IDs->IDs_length + 1 > SNP_IDs->IDs_size) + { + SNP_IDs->IDs_size = SNP_IDs->IDs_size * 2; + SNP_IDs->IDs = (Snp_ID_Vector*)realloc(SNP_IDs->IDs, SNP_IDs->IDs_size * sizeof(Snp_ID_Vector)); + } + SNP_IDs->IDs[SNP_IDs->IDs_length].beg = SNP_IDs->buffer_length; + SNP_IDs->IDs[SNP_IDs->IDs_length].end = SNP_IDs->buffer_length + IDs_vec_length - 1; + + SNP_IDs->IDs[SNP_IDs->IDs_length].occ_0 = occ_0; + SNP_IDs->IDs[SNP_IDs->IDs_length].occ_1 = occ_1; + SNP_IDs->IDs[SNP_IDs->IDs_length].homopolymer_num = homopolymer_num; + SNP_IDs->IDs[SNP_IDs->IDs_length].non_homopolymer_num = non_homopolymer_num; + + + + if(SNP_IDs->buffer_length + IDs_vec_length > SNP_IDs->buffer_size) + { + SNP_IDs->buffer_size = (SNP_IDs->buffer_length + IDs_vec_length) * 2; + SNP_IDs->buffer = (uint32_t*)realloc(SNP_IDs->buffer, SNP_IDs->buffer_size * sizeof(uint32_t)); + } + memcpy(SNP_IDs->buffer + SNP_IDs->buffer_length, IDs_vec, IDs_vec_length*sizeof(uint32_t)); + + + SNP_IDs->IDs_length++; + SNP_IDs->buffer_length += IDs_vec_length; +} + + +inline void insert_SNP_IDs_addition(Snp_ID_Vector_Alloc* SNP_IDs, uint32_t* IDs_vec, int IDs_vec_length) +{ + if(SNP_IDs->IDs_length + 1 > SNP_IDs->IDs_size) + { + SNP_IDs->IDs_size = SNP_IDs->IDs_size * 2; + SNP_IDs->IDs = (Snp_ID_Vector*)realloc(SNP_IDs->IDs, SNP_IDs->IDs_size * sizeof(Snp_ID_Vector)); + } + SNP_IDs->IDs[SNP_IDs->IDs_length].beg = SNP_IDs->buffer_length; + SNP_IDs->IDs[SNP_IDs->IDs_length].end = SNP_IDs->buffer_length + IDs_vec_length - 1; + + + if(SNP_IDs->buffer_length + IDs_vec_length > SNP_IDs->buffer_size) + { + SNP_IDs->buffer_size = (SNP_IDs->buffer_length + IDs_vec_length) * 2; + SNP_IDs->buffer = (uint32_t*)realloc(SNP_IDs->buffer, SNP_IDs->buffer_size * sizeof(uint32_t)); + } + memcpy(SNP_IDs->buffer + SNP_IDs->buffer_length, IDs_vec, IDs_vec_length*sizeof(uint32_t)); + + + SNP_IDs->IDs_length++; + SNP_IDs->buffer_length += IDs_vec_length; +} + + +inline void init_DP_matrix(DP_matrix* dp, uint32_t snp_num) +{ + + if(snp_num > dp->snp_size) + { + dp->snp_size = snp_num; + dp->max = (uint32_t*)realloc(dp->max, dp->snp_size * sizeof(uint32_t)); + dp->max_for_sort = (uint64_t*)realloc(dp->max_for_sort, dp->snp_size * sizeof(uint64_t)); + dp->visit = (uint8_t*)realloc(dp->visit, dp->snp_size * sizeof(uint8_t)); + dp->buffer = (uint32_t*)realloc(dp->buffer, dp->snp_size * sizeof(uint32_t)); + dp->max_buffer = (uint32_t*)realloc(dp->max_buffer, dp->snp_size * sizeof(uint32_t)); + + + + dp->backtrack_length = (uint32_t*)realloc(dp->backtrack_length, dp->snp_size * sizeof(uint32_t)); + + dp->backtrack_size = snp_num*snp_num; + dp->backtrack = (uint32_t*)realloc(dp->backtrack, dp->backtrack_size * sizeof(uint32_t)); + } + + dp->snp_num = snp_num; + + clear_SNP_IDs(&(dp->SNP_IDs)); + + +} + +inline void InitHaplotypeEvdience_buf(haplotype_evdience_alloc* h, void *km) +{ + memset(h, 0, sizeof(haplotype_evdience_alloc)); + /****************************may have bugs********************************/ + memset(h->flag, 0, WINDOW_MAX_SIZE * sizeof(uint8_t)); + /****************************may have bugs********************************/ + // init_SNP_IDs(&(h->dp.SNP_IDs)); + memset(&(h->dp.SNP_IDs), 0, sizeof(h->dp.SNP_IDs)); + h->dp.SNP_IDs.max_snp_id = -1; +} + + +inline void InitHaplotypeEvdience(haplotype_evdience_alloc* h) +{ + + h->overlap = 0; + h->snp_matrix_size = 0; + h->snp_matrix = NULL; + h->r_snp_size = 0; + h->r_snp = NULL; + kv_init(h->snp_stat); + kv_init(h->snp_srt); + h->nn_snp = 0; + // h->snp_stat = NULL; + // h->snp = 0; + // h->snp_stat_size = 0; + // h->available_snp = 0; + + + h->sub_list_start = 0; + h->sub_list_length = 0; + h->length = 0; + h->size = 100; + h->list = (haplotype_evdience*)calloc(h->size, sizeof(haplotype_evdience)); + + /****************************may have bugs********************************/ + memset(h->flag, 0, WINDOW_MAX_SIZE * sizeof(uint8_t)); + /****************************may have bugs********************************/ + + + // h->dp.max = NULL; + // h->dp.colum = NULL; + // h->dp.colum_len = NULL; + // h->dp.matrix_size = 0; + // h->dp.snp_num = 0; + // h->dp.snp_size = 0; + h->dp.snp_num = 0; + h->dp.max = NULL; + h->dp.max_for_sort = NULL; + h->dp.visit = NULL; + h->dp.snp_size = 0; + h->dp.backtrack = NULL; + h->dp.backtrack_size = 0; + h->dp.backtrack_length = NULL; + h->dp.buffer = NULL; + h->dp.max_buffer = NULL; + + init_SNP_IDs(&(h->dp.SNP_IDs)); +} + +inline void StarSubListHaplotypeEvdience(haplotype_evdience_alloc* h) +{ + h->sub_list_start = h->length; +} + +inline void EndSubListHaplotypeEvdience(haplotype_evdience_alloc* h) +{ + h->sub_list_length = h->length - h->sub_list_start; +} + + +inline void destoryHaplotypeEvdience(haplotype_evdience_alloc* h) +{ + free(h->list); + // free(h->snp_stat); + kv_destroy(h->snp_stat); + kv_destroy(h->snp_srt); + free(h->snp_matrix); + free(h->r_snp); + free(h->dp.backtrack); + free(h->dp.max); + free(h->dp.max_for_sort); + free(h->dp.visit); + free(h->dp.backtrack_length); + free(h->dp.buffer); + free(h->dp.max_buffer); + destory_SNP_IDs(&(h->dp.SNP_IDs)); +} + + +inline void ResizeInitHaplotypeEvdience(haplotype_evdience_alloc* h) +{ + // h->snp = 0; + h->nn_snp = 0; + h->snp_stat.n = 0; + h->length = 0; + h->sub_list_start = 0; + h->sub_list_length = 0; + /****************************may have bugs********************************/ + memset(h->flag, 0, WINDOW_MAX_SIZE * sizeof(uint8_t)); + /****************************may have bugs********************************/ +} + +inline void RsetInitHaplotypeEvdienceFlag(haplotype_evdience_alloc* h, long long beg, long long useful_length) +{ + /****************************may have bugs********************************/ + memset(h->flag + beg, 0, useful_length * sizeof(uint8_t)); + /****************************may have bugs********************************/ +} + +inline void addHaplotypeEvdience(haplotype_evdience_alloc* h, haplotype_evdience* ev, void *km) +{ + if(h->length + 1 > h->size){ + h->size = h->length + 1; + kroundup32(h->size); + if(!km) REALLOC(h->list, h->size); + else KREALLOC(km, h->list, h->size); + // h->list = (haplotype_evdience*)realloc(h->list, sizeof(haplotype_evdience)*h->size); + } + + h->list[h->length] = (*ev); + h->length++; +} + +typedef struct +{ + char* corrected_read; + long long corrected_read_length; + long long last_boundary_length; + long long corrected_read_size; + long long corrected_base; + + uint64_t* overlapID; + uint64_t length; + uint64_t lengthNT; + uint64_t size; + uint64_t start_i; + + /****************************may have bugs********************************/ + // char overlap_region[WINDOW + THRESHOLD*2 + 10]; + // char overlap_region_group[GROUP_SIZE][WINDOW + THRESHOLD*2 + 10]; + // char path[WINDOW + THRESHOLD*2 + 10]; + // Word matrix_bit[((WINDOW + 10)<<3)]; + + char overlap_region[WINDOW_MAX_SIZE + THRESHOLD_MAX_SIZE*2 + 10]; + char overlap_region_group[GROUP_SIZE][WINDOW_MAX_SIZE + THRESHOLD_MAX_SIZE*2 + 10]; + char path[WINDOW_MAX_SIZE + THRESHOLD_MAX_SIZE*2 + 10]; + + char path_fix[WINDOW_MAX_SIZE + THRESHOLD_MAX_SIZE*2 + 10]; + char overlap_region_fix[WINDOW_MAX_SIZE + THRESHOLD_MAX_SIZE*2 + 10]; + Word matrix_bit[((WINDOW_MAX_SIZE + 10)<<3)]; + /****************************may have bugs********************************/ + + int path_length; + __m128i Peq_SSE[256]; +} Correct_dumy; + +typedef struct +{ + Correct_dumy dumy; + Cigar_record cigar; + Cigar_record tmp_cigar; + long long obtained_cigar_length; +} +Round2_alignment; + +void init_Round2_alignment_buf(Round2_alignment* h, void *km); +void init_Round2_alignment(Round2_alignment* h); +void destory_Round2_alignment(Round2_alignment* h); +void clear_Round2_alignment(Round2_alignment* h); + +typedef struct { + int32_t c_qs, c_qe, c_ts, c_te; //[c_qs, c_qe) && [c_ts, c_te) + int32_t c_wsid, c_weid, c_wsii, c_weii;//[c_wsid, c_weid] && [c_wsii, c_weii) + int32_t rev, sfx_e, pfx_e, mid_e, oid; +} rtrace_t; + +typedef struct { + rtrace_t *a; + size_t n, m; +} kv_rtrace_t; + +void correct_overlap(overlap_region_alloc* overlap_list, All_reads* R_INF, + UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, Graph* g, Graph* DAGCon, + Cigar_record* current_cigar, haplotype_evdience_alloc* hap, + Round2_alignment* second_round, kvec_t_u64_warp* v_idx, window_list_alloc* win_ciagr_buf, + int force_repeat, int is_consensus, int* fully_cov, int* abnormal); +void init_Correct_dumy_buf(Correct_dumy* list, void *km); +void init_Correct_dumy(Correct_dumy* list); +void destory_Correct_dumy(Correct_dumy* list); +void clear_Correct_dumy(Correct_dumy* list, overlap_region_alloc* overlap_list, void *km); +void clear_Correct_dumy_pure(Correct_dumy* list); +void get_seq_from_Graph(Graph* backbone, Graph* DAGCon, Correct_dumy* dumy, Cigar_record* current_cigar, char* self_string, +char* r_string, long long r_string_length, long long r_string_site); +void init_Cigar_record(Cigar_record* dummy); +void init_Cigar_record_buf(Cigar_record* dummy, void *km); +void destory_Cigar_record(Cigar_record* dummy); +void clear_Cigar_record(Cigar_record* dummy); +void add_new_cell_to_cigar_record(Cigar_record* dummy, uint32_t len, uint32_t type); +void add_existing_cell_to_cigar_record(Cigar_record* dummy, uint32_t len, uint32_t type); +void add_new_cell_to_cigar_record_with_different_base(Cigar_record* dummy, uint32_t len, uint32_t type, char* seq); +void add_existing_cell_to_cigar_record_with_different_base(Cigar_record* dummy, uint32_t len, uint32_t type, char* seq); + + +void correct_ul_overlap(overlap_region_alloc* overlap_list, const ul_idx_t *uref, + UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, + Graph* g, Graph* DAGCon, Cigar_record* current_cigar, + haplotype_evdience_alloc* hap, Round2_alignment* second_round, + kvec_t_u64_warp* v_idx, window_list_alloc* win_ciagr_buf, + int force_repeat, int is_consensus, int* fully_cov, int* abnormal, + double max_ov_diff_ec, long long winLen, void *km); +void ul_lalign(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, const ug_opt_t *uopt, char *qstr, + uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, bit_extz_t *exz, + haplotype_evdience_alloc* hap, kvec_t_u64_warp* v_idx, overlap_region *aux_o, + double e_rate, int64_t wl, kv_ul_ov_t *aln, int64_t sid, uint64_t hpc_k, st_mt_t *stb, idx_emask_t *mm, mask_ul_ov_t *mk, void *km); + +void ul_lalign_old_ed(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, char *qstr, + uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, + haplotype_evdience_alloc* hap, kvec_t_u64_warp* v_idx, + double e_rate, int64_t wl, uint64_t is_base, void *km); + +void lchain_align(overlap_region_alloc* overlap_list, const ul_idx_t *uref, + UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read, + Graph* g, Graph* DAGCon, Cigar_record* current_cigar, + haplotype_evdience_alloc* hap, Round2_alignment* second_round, + kvec_t_u64_warp* v_idx, window_list_alloc* win_ciagr_buf, + int force_repeat, int is_consensus, int* fully_cov, int* abnormal, + double max_ov_diff_ec, long long winLen, void *km); + +void ug_lalign(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, const ug_opt_t *uopt, + char *qstr, uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, bit_extz_t *exz, + overlap_region *aux_o, double e_rate, int64_t wl, int64_t sid, uint64_t khit, uint64_t chain_cut, + void *km); +/*** + type: + 0. match + 1. mismatch + 2. insertion + 3. deletion + ***/ +inline void add_cigar_record(char* seq, uint32_t len, Cigar_record* dummy, uint32_t type) +{ + if(type == 0)///match + { + ///add to existing cell, just increase length + if((uint32_t)dummy->current_operation == type) + { + add_existing_cell_to_cigar_record(dummy, len, type); + } + else ///add to new cell + { + add_new_cell_to_cigar_record(dummy, len, type); + } + + dummy->new_read_length += len; + } + else if(type == 1)///mismatch + { + ///add to existing cell, just increase length + ///and add different bases + if((uint32_t)dummy->current_operation == type) + { + add_existing_cell_to_cigar_record_with_different_base(dummy, len, type, seq); + } + else + { + add_new_cell_to_cigar_record_with_different_base(dummy, len, type, seq); + } + + dummy->new_read_length += len; + } + else if(type == 3)///deletion, the bases in previous read will be removed + { + ///add to existing cell, just increase length + ///and add different bases + if((uint32_t)dummy->current_operation == type) + { + add_existing_cell_to_cigar_record_with_different_base(dummy, len, type, seq); + } + else + { + add_new_cell_to_cigar_record_with_different_base(dummy, len, type, seq); + } + } + else if(type == 2)///insertion + { + /** + ///add to existing cell, just increase length + if(dummy->current_operation == type) + { + add_existing_cell_to_cigar_record(dummy, len, type); + } + else ///add to new cell + { + add_new_cell_to_cigar_record(dummy, len, type); + } + **/ + ///add to existing cell, just increase length + ///and add different bases + if((uint32_t)dummy->current_operation == type) + { + add_existing_cell_to_cigar_record_with_different_base(dummy, len, type, seq); + } + else + { + add_new_cell_to_cigar_record_with_different_base(dummy, len, type, seq); + } + + dummy->new_read_length += len; + } + + dummy->current_operation = type; +} + +int verify_cigar_2(char* x, int x_len, char* y, int y_len, Cigar_record* cigar, int error); + + +int verify_single_window(long long x_start, long long x_end, +long long overlap_x_s, long long overlap_y_s, int x_id, +int y_id, int y_strand, char* x_buffer, char* y_buffer, +All_reads* R_INF); + +void init_Cigar_record_alloc(Cigar_record_alloc* x); +void resize_Cigar_record_alloc(Cigar_record_alloc* x, long long new_size); +void destory_Cigar_record_alloc(Cigar_record_alloc* x); + +void afine_gap_alignment(const char *qseq, uint8_t* qnum, const int ql, +const char *tseq, uint8_t* tnum, const int tl, const uint8_t *c2n, const int strand, +int sc_mch, int sc_mis, int gapo, int gape, int bandLen, int zdrop, int end_bonus, +long long* max_q_pos, long long* max_t_pos, long long* global_score, +long long* extention_score, long long* q_boundary_score, long long* q_boundary_t_coordinate, +long long* t_boundary_score, long long* t_boundary_q_coordinate, +long long* droped, int mode); +// void correct_overlap_high_het(overlap_region_alloc* overlap_list, All_reads* R_INF, +// UC_Read* g_read, Correct_dumy* dumy, UC_Read* overlap_read); +long long get_affine_gap_score(overlap_region* ovc, UC_Read* g_read, UC_Read* overlap_read, uint8_t* x_num, +uint8_t* y_num, uint64_t EstimateXOlen, uint64_t EstimateYOlen); +int collect_hp_regions(overlap_region_alloc* olist, All_reads* R_INF, kvec_t_u8_warp* k_flag, float hp_rate, int rlen, FILE* fp); + +inline int if_exact_match(char* x, long long xLen, char* y, long long yLen, long long xBeg, long long xEnd, long long yBeg, long long yEnd) +{ + long long overlapLen = xEnd - xBeg + 1; + + if(yEnd - yBeg + 1 == overlapLen) + { + if(memcmp(x+xBeg, y+yBeg, overlapLen)==0) return 1; + } + + return 0; +} + +inline void get_cigar_cell(window_list *idx, window_list_alloc *cc, uint32_t i, uint8_t *c, uint32_t *len) +{ + uint16_t p = cc->c.a[idx->cidx+i]; + (*c) = (uint8_t)(p>>14); (*len) = (p&((uint16_t)0x3fff)); +} + +inline void push_cigar_cell(window_list_alloc *res, uint8_t c, uint32_t len) +{ + uint16_t p = c; p <<= 14; p += (uint16_t)len; + kv_push(uint16_t, res->c, p); +} +int64_t get_num_wins(int64_t s, int64_t e, int64_t block_s); +void append_unmatched_wins(overlap_region *z, int64_t block_s); + +///[w_s, w_e] +inline int64_t get_win_id_by_s(overlap_region *z, int64_t w_s, int64_t block_s, int64_t *w_e) +{ + int64_t n_s = ((z->x_pos_s/block_s)*block_s), wid = (w_s-n_s)/block_s; + if(w_e) { + (*w_e) = n_s + (wid+1)*block_s - 1; + if((*w_e) > z->x_pos_e) (*w_e) = z->x_pos_e; + } + return wid; +} + +///[w_s, w_e] +inline int64_t get_win_id_by_e(overlap_region *z, int64_t w_e, int64_t block_s, int64_t *w_s) +{ + int64_t n_s = ((z->x_pos_s/block_s)*block_s), wid = (w_e-n_s)/block_s; + if(w_s) { + (*w_s) = n_s + wid*block_s; + if((*w_s) < z->x_pos_s) (*w_s) = z->x_pos_s; + } + return wid; +} + +///[w_s, w_e] +inline void get_win_se_by_normalize_xs(overlap_region *z, int64_t norm_w_s, int64_t block_s, int64_t *w_s, int64_t *w_e) +{ + int64_t n_s = ((z->x_pos_s/block_s)*block_s), wid = (norm_w_s-n_s)/block_s; + if(w_s) { + (*w_s) = n_s + wid*block_s; + if((*w_s) < z->x_pos_s) (*w_s) = z->x_pos_s; + } + if(w_e) { + (*w_e) = n_s + (wid+1)*block_s - 1; + if((*w_e) > z->x_pos_e) (*w_e) = z->x_pos_e; + } +} + +void inline resize_UC_Read(UC_Read *z, int64_t s) +{ + if(z->size < s) { + REALLOC(z->seq, s); z->size = s; + } +} + +void update_sketch_trace(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, +All_reads *rref, UC_Read* tu, asg64_v* idx, asg64_v *b0, asg64_v *b1, int64_t ql, int64_t wl, +kv_ul_ov_t *aln, uint64_t rid, int64_t max_lgap, double sgap_rate); + +int64_t infer_rovlp(ul_ov_t *li, ul_ov_t *lj, uc_block_t *bi, uc_block_t *bj, All_reads *ridx, ma_ug_t *ug); +void convert_ul_ov_t(ul_ov_t *des, overlap_region *src, ma_ug_t *ug); +uint64_t check_connect_ug(const ul_idx_t *uref, uint32_t v, uint32_t w, int64_t bw, double diff_ec_ul, int64_t dq); +uint64_t check_connect_rg(const ul_idx_t *uref, const ug_opt_t *uopt, uint32_t uv, uint32_t uw, int64_t bw, double diff_ec_ul, int64_t dq); +uint32_t govlp_check(const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, ul_ov_t *li, ul_ov_t *lj); +void ul_rid_lalign_adv(overlap_region_alloc* ol, Candidates_list *cl, const ul_idx_t *uref, const ug_opt_t *uopt, + char *qstr, uint64_t ql, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, + int64_t wl, kv_ul_ov_t *aln, kv_ul_ov_t *cln, kv_rtrace_t *trace, int64_t sid, uint64_t khit, void *km); + +#define copy_asg_arr(des, src) ((des).a = (src).a, (des).n = (src).n, (des).m = (src).m) +#define is_ualn_win(a) (((a).error==INT16_MAX)&&((a).clen==0)&&((a).extra_end<0)) +#define is_exact_aln(a) (((a).error0)) +#define is_est_aln(a) (((a).error -#include -#include -#include -#include "Hash_Table.h" -#include "ksort.h" -#include "kalloc.h" -pthread_mutex_t output_mutex; - -#define overlap_region_key(a) ((a).y_id) -KRADIX_SORT_INIT(overlap_region_sort, overlap_region, overlap_region_key, member_size(overlap_region, y_id)) - -#define generic_key(x) (x) -KRADIX_SORT_INIT(hc64i, int64_t, generic_key, 8) - -#define oreg_sss_lt(a, b) ((a).shared_seed > (b).shared_seed) // in the decending order -KSORT_INIT(or_sss, overlap_region, oreg_sss_lt) - -#define normal_w(x, y) ((x)>=(y)?(x)/(y):1) - -void overlap_region_sort_y_id(overlap_region *a, long long n) -{ - radix_sort_overlap_region_sort(a, a + n); -} - -void init_overlap_region_alloc(overlap_region_alloc* list) -{ - list->size = 1000; - list->length = 0; - ///list->list = (overlap_region*)malloc(sizeof(overlap_region)*list->size); - list->list = (overlap_region*)calloc(list->size, sizeof(overlap_region)); - uint64_t i; - for (i = 0; i < list->size; i++) { - init_fake_cigar(&(list->list[i].f_cigar)); - init_window_list_alloc(&(list->list[i].w_list)); - init_window_list_alloc(&(list->list[i].boundary_cigars)); - } -} - -void clear_overlap_region_alloc(overlap_region_alloc* list) -{ - list->length = 0; - list->mapped_overlaps_length = 0; - uint64_t i = 0; - for (i = 0; i < list->size; i++) { - clear_fake_cigar(&(list->list[i].f_cigar)); - clear_window_list_alloc(&(list->list[i].w_list)); - clear_window_list_alloc(&(list->list[i].boundary_cigars)); - } -} - -void destory_overlap_region_alloc(overlap_region_alloc* list) -{ - uint64_t i = 0; - for (i = 0; i < list->size; i++) { - destory_fake_cigar(&(list->list[i].f_cigar)); - destory_window_list_alloc(&(list->list[i].w_list)); - destory_window_list_alloc(&(list->list[i].boundary_cigars)); - } - free(list->list); -} - -int get_fake_gap_pos(Fake_Cigar* x, int index) -{ - return (x->buffer[index]>>32); -} - -int get_fake_gap_shift(Fake_Cigar* x, int index) -{ - uint32_t tmp = ((uint32_t)(x->buffer[index])); - int result; - if(tmp & ((uint32_t)1)) - { - tmp = tmp >> 1; - result = tmp; - result = result * -1; - } - else - { - tmp = tmp >> 1; - result = tmp; - } - - return result; -} - -void gen_fake_cigar(Fake_Cigar* z, overlap_region *o, int64_t apend_be, k_mer_hit* hit, int64_t n_hit) -{ - int64_t k, dq, dr, dd, pdd; z->length = 0; - if(apend_be == 1) add_fake_cigar(z, o->x_pos_s, 0, NULL); - for (k = 0, pdd = INT32_MAX; k < n_hit; k++) { - dq = hit[k].self_offset - o->x_pos_s; - dr = hit[k].offset - o->y_pos_s; - dd = dr - dq; - // if(print) { - // fprintf(stderr, "[M::k->%lu] x::%u, y::%u, cnt::%u, dd::%ld, pdd::%ld, z->n::%u\n", - // k, hit[k].self_offset, hit[k].offset, hit[k].cnt&(0xffu), dd, pdd, z->length); - // } - if(dd != pdd) { - pdd = dd; - add_fake_cigar(z, hit[k].self_offset, pdd, NULL); - } - } - - if((apend_be == 1) && (get_fake_gap_pos(z, z->length-1)!=((int64_t)o->x_pos_e))) { - add_fake_cigar(z, o->x_pos_e, get_fake_gap_shift(z, z->length-1), NULL); - } -} - -void debug_cigar(Fake_Cigar* z, overlap_region *o, int64_t apend_be, k_mer_hit* hit, uint64_t n_hit) -{ - gen_fake_cigar(z, o, apend_be, hit, n_hit); - if(!((z->length==o->f_cigar.length) && - (!memcmp(z->buffer, o->f_cigar.buffer, sizeof((*(o->f_cigar.buffer)))*o->f_cigar.length)))) { - uint64_t k; - fprintf(stderr, "\n[M::%s] z->n::%u, o->n::%u, rev::%u\n", __func__, z->length, o->f_cigar.length, o->y_pos_strand); - for (k = 0; k < z->length; k++) { - fprintf(stderr, "[z::k->%lu] pos::%d, off::%d\n", k, - get_fake_gap_pos(z, k), get_fake_gap_shift(z, k)); - } - for (k = 0; k < o->f_cigar.length; k++) { - fprintf(stderr, "[o::k->%lu] pos::%d, off::%d\n", k, - get_fake_gap_pos(&(o->f_cigar), k), get_fake_gap_shift(&(o->f_cigar), k)); - } - // gen_fake_cigar(z, o, apend_be, hit, n_hit, 1); - // for (k = 0; k < o->f_cigar.length; k++) { - // fprintf(stderr, "[M::k->%lu] x::%u, y::%u, cnt::%u\n", - // k, hit[k].self_offset, hit[k].offset, hit[k].cnt&(0xffu)); - // } - - } -} - -///for backup -int ovlp_chain_gen(overlap_region_alloc* ol, overlap_region* t, int64_t xl, int64_t yl, int64_t apend_be, k_mer_hit* hit, int64_t n_hit) -{ - if (ol->length + 1 > ol->size) { - uint64_t sl = ol->size; - ol->size = ol->length + 1; - kroundup64(ol->size); - REALLOC(ol->list, ol->size); - /// need to set new space to be 0 - memset(ol->list + sl, 0, sizeof(overlap_region)*(ol->size - sl)); - } - - if ((ol->length!=0) && (ol->list[ol->length-1].y_id==t->y_id)) { - if((ol->list[ol->length-1].shared_seed > t->shared_seed) || - ((ol->list[ol->length-1].shared_seed == t->shared_seed) && - (ol->list[ol->length-1].overlapLen <= t->overlapLen))) { - return 0; - } else { - ol->length--; - } - } - - int64_t xr, yr; - if(t->x_pos_s <= t->y_pos_s) { - t->y_pos_s -= t->x_pos_s; t->x_pos_s = 0; - } else { - t->x_pos_s -= t->y_pos_s; t->y_pos_s = 0; - } - - xr = xl-t->x_pos_e-1; yr = yl-t->y_pos_e-1; - if(xr <= yr) { - t->x_pos_e = xl-1; t->y_pos_e += xr; - } else { - t->y_pos_e = yl-1; t->x_pos_e += yr; - } - - overlap_region *o = &(ol->list[ol->length++]); - o->shared_seed = t->shared_seed; - o->align_length = 0; - o->is_match = 0; - o->non_homopolymer_errors = 0; - o->strong = 0; - o->x_id = t->x_id; - o->y_id = t->y_id; - o->x_pos_strand = 0;///always 0 - o->y_pos_strand = t->x_pos_strand; - - if (t->x_pos_strand == 1) { - o->x_pos_e = xl-t->x_pos_s-1; o->x_pos_s = xl-t->x_pos_e-1; - o->y_pos_e = yl-t->y_pos_s-1; o->y_pos_s = yl-t->y_pos_e-1; - } else { - o->x_pos_e = t->x_pos_e; o->x_pos_s = t->x_pos_s; - o->y_pos_e = t->y_pos_e; o->y_pos_s = t->y_pos_s; - } - ///debug - // debug_cigar(&(t->f_cigar), o, apend_be, hit, n_hit); - - return 1; -} - -int ovlp_chain_qgen(overlap_region_alloc* ol, overlap_region* t, int64_t xl, int64_t yl, int64_t apend_be, k_mer_hit* hit, int64_t n_hit) -{ - if (ol->length + 1 > ol->size) { - uint64_t sl = ol->size; - ol->size = ol->length + 1; - kroundup64(ol->size); - REALLOC(ol->list, ol->size); - /// need to set new space to be 0 - memset(ol->list + sl, 0, sizeof(overlap_region)*(ol->size - sl)); - } - - if ((ol->length!=0) && (ol->list[ol->length-1].y_id==t->y_id)) { - if((ol->list[ol->length-1].shared_seed > t->shared_seed) || - ((ol->list[ol->length-1].shared_seed == t->shared_seed) && - (ol->list[ol->length-1].overlapLen <= t->overlapLen))) { - return 0; - } else { - ol->length--; - } - } - - int64_t xr, yr; - if(t->x_pos_s <= t->y_pos_s) { - t->y_pos_s -= t->x_pos_s; t->x_pos_s = 0; - } else { - t->x_pos_s -= t->y_pos_s; t->y_pos_s = 0; - } - - xr = xl-t->x_pos_e-1; yr = yl-t->y_pos_e-1; - if(xr <= yr) { - t->x_pos_e = xl-1; t->y_pos_e += xr; - } else { - t->y_pos_e = yl-1; t->x_pos_e += yr; - } - - overlap_region *o = &(ol->list[ol->length++]); - o->shared_seed = t->shared_seed; - o->align_length = 0; - o->is_match = 0; - o->non_homopolymer_errors = 0; - o->strong = 0; - o->x_id = t->x_id; - o->y_id = t->y_id; - o->x_pos_strand = 0;///always 0 - o->y_pos_strand = t->x_pos_strand; - - o->x_pos_e = t->x_pos_e; o->x_pos_s = t->x_pos_s; - o->y_pos_e = t->y_pos_e; o->y_pos_s = t->y_pos_s; - ///debug - // debug_cigar(&(t->f_cigar), o, apend_be, hit, n_hit); - - return 1; -} - -int ovlp_chain_gen_fcigar(overlap_region_alloc* ol, overlap_region* t, int64_t xl, int64_t yl, int64_t apend_be, k_mer_hit* hit, int64_t n_hit) -{ - if (ol->length + 1 > ol->size) { - uint64_t sl = ol->size; - ol->size = ol->length + 1; - kroundup64(ol->size); - REALLOC(ol->list, ol->size); - /// need to set new space to be 0 - memset(ol->list + sl, 0, sizeof(overlap_region)*(ol->size - sl)); - } - - if ((ol->length!=0) && (ol->list[ol->length-1].y_id==t->y_id)) { - if((ol->list[ol->length-1].shared_seed > t->shared_seed) || - ((ol->list[ol->length-1].shared_seed == t->shared_seed) && - (ol->list[ol->length-1].overlapLen <= t->overlapLen))) { - return 0; - } else { - ol->length--; - } - } - - int64_t xr, yr, dd, pdd, dq, dr, id, i, fn; - if(t->x_pos_s <= t->y_pos_s) { - t->y_pos_s -= t->x_pos_s; t->x_pos_s = 0; - } else { - t->x_pos_s -= t->y_pos_s; t->y_pos_s = 0; - } - - xr = xl-t->x_pos_e-1; yr = yl-t->y_pos_e-1; - if(xr <= yr) { - t->x_pos_e = xl-1; t->y_pos_e += xr; - } else { - t->y_pos_e = yl-1; t->x_pos_e += yr; - } - - overlap_region *o = &(ol->list[ol->length++]); - o->shared_seed = t->shared_seed; - o->align_length = 0; - o->is_match = 0; - o->non_homopolymer_errors = 0; - o->strong = 0; - o->x_id = t->x_id; - o->y_id = t->y_id; - o->x_pos_strand = 0;///always 0 - o->y_pos_strand = t->x_pos_strand; - - resize_fake_cigar(&(o->f_cigar), (t->f_cigar.length + 2), NULL); - if(apend_be == 1) { - add_fake_cigar(&(o->f_cigar), ((t->x_pos_strand)?(xl-t->x_pos_e-1):(t->x_pos_s)), 0, NULL); - } - - if (t->x_pos_strand == 1) { - o->x_pos_e = xl-t->x_pos_s-1; o->x_pos_s = xl-t->x_pos_e-1; - o->y_pos_e = yl-t->y_pos_s-1; o->y_pos_s = yl-t->y_pos_e-1; - - pdd = INT32_MAX; fn = t->f_cigar.length; - for (i = 0; i < fn; i++) { - dd = get_fake_gap_shift(&(t->f_cigar), i); - if(dd != pdd) { - pdd = dd; - add_fake_cigar(&(o->f_cigar), xl-get_fake_gap_pos(&(t->f_cigar), i)-1, pdd, NULL); - } - } - } else { - o->x_pos_e = t->x_pos_e; o->x_pos_s = t->x_pos_s; - o->y_pos_e = t->y_pos_e; o->y_pos_s = t->y_pos_s; - - dq = t->x_pos_e - t->x_pos_s; - dr = t->y_pos_e - t->y_pos_s; - id = dr - dq;///indel size from left - - pdd = INT32_MAX; fn = t->f_cigar.length; - for (i = fn-1; i >= 0; i--) { - dd = get_fake_gap_shift(&(t->f_cigar), i); - if(dd != pdd) { - pdd = dd; - add_fake_cigar(&(o->f_cigar), get_fake_gap_pos(&(t->f_cigar), i), id - pdd, NULL); - } - } - } - - if((apend_be == 1) && (get_fake_gap_pos(&(o->f_cigar), o->f_cigar.length-1) != ((int64_t)o->x_pos_e))) { - add_fake_cigar(&(o->f_cigar), o->x_pos_e, get_fake_gap_shift(&(o->f_cigar), o->f_cigar.length-1), NULL); - } - - ///debug - debug_cigar(&(t->f_cigar), o, apend_be, hit, n_hit); - - return 1; -} - -int append_inexact_overlap_region_alloc(overlap_region_alloc* list, overlap_region* tmp, - long long xLen, long long yLen, int add_beg_end, void *km) -{ - - if (list->length + 1 > list->size) - { - uint64_t sl = list->size; - list->size = list->length + 1; - kroundup64(list->size); - if(!km) { - REALLOC(list->list, list->size); - } else { - KREALLOC(km, list->list, list->size); - } - /// need to set new space to be 0 - memset(list->list + sl, 0, sizeof(overlap_region)*(list->size - sl)); - } - - if (list->length!=0 && list->list[list->length - 1].y_id==tmp->y_id) - { - ///if(list->list[list->length - 1].shared_seed >= tmp->shared_seed) - if((list->list[list->length - 1].shared_seed > tmp->shared_seed) - || - ((list->list[list->length - 1].shared_seed == tmp->shared_seed) && - (list->list[list->length - 1].overlapLen <= tmp->overlapLen))) - { - return 0; - } - else - { - list->length--; - } - } - - if(tmp->x_pos_s <= tmp->y_pos_s) - { - tmp->y_pos_s = tmp->y_pos_s - tmp->x_pos_s; - tmp->x_pos_s = 0; - } - else - { - tmp->x_pos_s = tmp->x_pos_s - tmp->y_pos_s; - tmp->y_pos_s = 0; - } - - - long long x_right_length = xLen - tmp->x_pos_e - 1; - long long y_right_length = yLen - tmp->y_pos_e - 1; - - if(x_right_length <= y_right_length) - { - tmp->x_pos_e = xLen - 1; - tmp->y_pos_e = tmp->y_pos_e + x_right_length; - } - else - { - tmp->x_pos_e = tmp->x_pos_e + y_right_length; - tmp->y_pos_e = yLen - 1; - } - - if (tmp->x_pos_strand == 1) - { - list->list[list->length].x_id = tmp->x_id; - list->list[list->length].x_pos_e = xLen - tmp->x_pos_s - 1; - list->list[list->length].x_pos_s = xLen - tmp->x_pos_e - 1; - list->list[list->length].x_pos_strand = 0; - - list->list[list->length].y_id = tmp->y_id; - list->list[list->length].y_pos_e = yLen - tmp->y_pos_s - 1; - list->list[list->length].y_pos_s = yLen - tmp->y_pos_e - 1; - list->list[list->length].y_pos_strand = 1; - - resize_fake_cigar(&(list->list[list->length].f_cigar), (tmp->f_cigar.length + 2), km); - if(add_beg_end == 1) - { - add_fake_cigar(&(list->list[list->length].f_cigar), list->list[list->length].x_pos_s, 0, km); - } - - long long distance_gap; - /****************************may have bugs********************************/ - ///long long pre_distance_gap = 0; - long long pre_distance_gap = 0xfffffffffffffff; - /****************************may have bugs********************************/ - long long i = 0; - for (i = 0; i < (long long)tmp->f_cigar.length; i++) - { - distance_gap = get_fake_gap_shift(&(tmp->f_cigar), i); - if(distance_gap != pre_distance_gap) - { - pre_distance_gap = distance_gap; - add_fake_cigar(&(list->list[list->length].f_cigar), xLen - get_fake_gap_pos(&(tmp->f_cigar), i) - 1, - pre_distance_gap, km); - } - } - - if(add_beg_end == 1 && get_fake_gap_pos(&(list->list[list->length].f_cigar), - list->list[list->length].f_cigar.length - 1) != (long long)list->list[list->length].x_pos_e) - { - add_fake_cigar(&(list->list[list->length].f_cigar), - list->list[list->length].x_pos_e, - get_fake_gap_shift(&(list->list[list->length].f_cigar), - list->list[list->length].f_cigar.length - 1), km); - } - } - else - { - list->list[list->length].x_id = tmp->x_id; - list->list[list->length].x_pos_e = tmp->x_pos_e; - list->list[list->length].x_pos_s = tmp->x_pos_s; - list->list[list->length].x_pos_strand = tmp->x_pos_strand; - - list->list[list->length].y_id = tmp->y_id; - list->list[list->length].y_pos_e = tmp->y_pos_e; - list->list[list->length].y_pos_s = tmp->y_pos_s; - list->list[list->length].y_pos_strand = tmp->y_pos_strand; - - - - resize_fake_cigar(&(list->list[list->length].f_cigar), (tmp->f_cigar.length + 2), km); - if(add_beg_end == 1) - { - add_fake_cigar(&(list->list[list->length].f_cigar), list->list[list->length].x_pos_s, 0, km); - } - - long long distance_self_pos = tmp->x_pos_e - tmp->x_pos_s; - long long distance_pos = tmp->y_pos_e - tmp->y_pos_s; - long long init_distance_gap = distance_pos - distance_self_pos; - /****************************may have bugs********************************/ - ///long long pre_distance_gap = init_distance_gap; - long long pre_distance_gap = 0xfffffffffffffff; - /****************************may have bugs********************************/ - long long distance_gap; - long long i = 0; - for (i = tmp->f_cigar.length - 1; i >= 0; i--) - { - distance_gap = get_fake_gap_shift(&(tmp->f_cigar), i); - if(distance_gap != pre_distance_gap) - { - pre_distance_gap = distance_gap; - - add_fake_cigar(&(list->list[list->length].f_cigar), - get_fake_gap_pos(&(tmp->f_cigar), i), init_distance_gap - pre_distance_gap, km); - } - } - - if(add_beg_end == 1 && get_fake_gap_pos(&(list->list[list->length].f_cigar), - list->list[list->length].f_cigar.length - 1) != (long long)list->list[list->length].x_pos_e) - { - add_fake_cigar(&(list->list[list->length].f_cigar), - list->list[list->length].x_pos_e, - get_fake_gap_shift(&(list->list[list->length].f_cigar), - list->list[list->length].f_cigar.length - 1), km); - } - } - - list->list[list->length].shared_seed = tmp->shared_seed; - list->list[list->length].align_length = 0; - list->list[list->length].is_match = 0; - list->list[list->length].non_homopolymer_errors = 0; - list->list[list->length].strong = 0; - - list->length++; - - return 1; -} - - -int append_utg_inexact_overlap_region_alloc(overlap_region_alloc* list, overlap_region* tmp, - ma_utg_v *ua, int add_beg_end, void *km) -{ - if (list->length + 1 > list->size) - { - uint64_t sl = list->size; - list->size = list->length + 1; - kroundup64(list->size); - if(!km) { - REALLOC(list->list, list->size); - } else { - KREALLOC(km, list->list, list->size); - } - /// need to set new space to be 0 - memset(list->list + sl, 0, sizeof(overlap_region)*(list->size - sl)); - } - - if (list->length!=0 && list->list[list->length - 1].y_id==tmp->y_id) - { - ///if(list->list[list->length - 1].shared_seed >= tmp->shared_seed) - if((list->list[list->length - 1].shared_seed > tmp->shared_seed) - || - ((list->list[list->length - 1].shared_seed == tmp->shared_seed) && - (list->list[list->length - 1].overlapLen <= tmp->overlapLen))) - { - return 0; - } - else - { - list->length--; - } - } - - if(tmp->x_pos_s <= tmp->y_pos_s) - { - tmp->y_pos_s = tmp->y_pos_s - tmp->x_pos_s; - tmp->x_pos_s = 0; - } - else - { - tmp->x_pos_s = tmp->x_pos_s - tmp->y_pos_s; - tmp->y_pos_s = 0; - } - - - long long x_right_length = ua->a[tmp->x_id].len - tmp->x_pos_e - 1; - long long y_right_length = ua->a[tmp->y_id].len - tmp->y_pos_e - 1; - - if(x_right_length <= y_right_length) - { - tmp->x_pos_e = ua->a[tmp->x_id].len - 1; - tmp->y_pos_e = tmp->y_pos_e + x_right_length; - } - else - { - tmp->x_pos_e = tmp->x_pos_e + y_right_length; - tmp->y_pos_e = ua->a[tmp->y_id].len - 1; - } - - if (tmp->x_pos_strand == 1) - { - list->list[list->length].x_id = tmp->x_id; - list->list[list->length].x_pos_e = ua->a[tmp->x_id].len - tmp->x_pos_s - 1; - list->list[list->length].x_pos_s = ua->a[tmp->x_id].len - tmp->x_pos_e - 1; - list->list[list->length].x_pos_strand = 0; - - list->list[list->length].y_id = tmp->y_id; - list->list[list->length].y_pos_e = ua->a[tmp->y_id].len - tmp->y_pos_s - 1; - list->list[list->length].y_pos_s = ua->a[tmp->y_id].len - tmp->y_pos_e - 1; - list->list[list->length].y_pos_strand = 1; - - resize_fake_cigar(&(list->list[list->length].f_cigar), (tmp->f_cigar.length + 2), km); - if(add_beg_end == 1) - { - add_fake_cigar(&(list->list[list->length].f_cigar), list->list[list->length].x_pos_s, 0, km); - } - - long long distance_gap; - /****************************may have bugs********************************/ - ///long long pre_distance_gap = 0; - long long pre_distance_gap = 0xfffffffffffffff; - /****************************may have bugs********************************/ - long long i = 0; - for (i = 0; i < (long long)tmp->f_cigar.length; i++) - { - distance_gap = get_fake_gap_shift(&(tmp->f_cigar), i); - if(distance_gap != pre_distance_gap) - { - pre_distance_gap = distance_gap; - add_fake_cigar(&(list->list[list->length].f_cigar), - ua->a[tmp->x_id].len - get_fake_gap_pos(&(tmp->f_cigar), i) - 1, - pre_distance_gap, km); - } - } - - if(add_beg_end == 1 && get_fake_gap_pos(&(list->list[list->length].f_cigar), - list->list[list->length].f_cigar.length - 1) != (long long)list->list[list->length].x_pos_e) - { - add_fake_cigar(&(list->list[list->length].f_cigar), - list->list[list->length].x_pos_e, - get_fake_gap_shift(&(list->list[list->length].f_cigar), - list->list[list->length].f_cigar.length - 1), km); - } - } - else - { - list->list[list->length].x_id = tmp->x_id; - list->list[list->length].x_pos_e = tmp->x_pos_e; - list->list[list->length].x_pos_s = tmp->x_pos_s; - list->list[list->length].x_pos_strand = tmp->x_pos_strand; - - list->list[list->length].y_id = tmp->y_id; - list->list[list->length].y_pos_e = tmp->y_pos_e; - list->list[list->length].y_pos_s = tmp->y_pos_s; - list->list[list->length].y_pos_strand = tmp->y_pos_strand; - - - - resize_fake_cigar(&(list->list[list->length].f_cigar), (tmp->f_cigar.length + 2), km); - if(add_beg_end == 1) - { - add_fake_cigar(&(list->list[list->length].f_cigar), list->list[list->length].x_pos_s, 0, km); - } - - long long distance_self_pos = tmp->x_pos_e - tmp->x_pos_s; - long long distance_pos = tmp->y_pos_e - tmp->y_pos_s; - long long init_distance_gap = distance_pos - distance_self_pos; - /****************************may have bugs********************************/ - ///long long pre_distance_gap = init_distance_gap; - long long pre_distance_gap = 0xfffffffffffffff; - /****************************may have bugs********************************/ - long long distance_gap; - long long i = 0; - for (i = tmp->f_cigar.length - 1; i >= 0; i--) - { - distance_gap = get_fake_gap_shift(&(tmp->f_cigar), i); - if(distance_gap != pre_distance_gap) - { - pre_distance_gap = distance_gap; - - add_fake_cigar(&(list->list[list->length].f_cigar), - get_fake_gap_pos(&(tmp->f_cigar), i), init_distance_gap - pre_distance_gap, km); - } - } - - if(add_beg_end == 1 && get_fake_gap_pos(&(list->list[list->length].f_cigar), - list->list[list->length].f_cigar.length - 1) != (long long)list->list[list->length].x_pos_e) - { - add_fake_cigar(&(list->list[list->length].f_cigar), - list->list[list->length].x_pos_e, - get_fake_gap_shift(&(list->list[list->length].f_cigar), - list->list[list->length].f_cigar.length - 1), km); - } - } - - list->list[list->length].shared_seed = tmp->shared_seed; - list->list[list->length].align_length = 0; - list->list[list->length].is_match = 0; - list->list[list->length].non_homopolymer_errors = 0; - list->list[list->length].strong = 0; - - list->length++; - - return 1; -} - -void append_overlap_region_alloc_debug(overlap_region_alloc* list, overlap_region* tmp) -{ - - if (list->length + 1 > list->size) - { - list->size = list->size * 2; - list->list = (overlap_region*)realloc(list->list, sizeof(overlap_region)*list->size); - } - - - list->list[list->length].x_id = tmp->x_id; - list->list[list->length].x_pos_e = tmp->x_pos_e; - list->list[list->length].x_pos_s = tmp->x_pos_s; - list->list[list->length].x_pos_strand = tmp->x_pos_strand; - - list->list[list->length].y_id = tmp->y_id; - list->list[list->length].y_pos_e = tmp->y_pos_e; - list->list[list->length].y_pos_s = tmp->y_pos_s; - list->list[list->length].y_pos_strand = tmp->y_pos_strand; - - list->list[list->length].shared_seed = tmp->shared_seed; - - list->length++; -} - -void debug_chain(k_mer_hit* a, long long a_n, Chain_Data* dp) -{ - long long i, j, current_j; - long long selfLen, indels; - long long distance_self_pos, distance_pos, distance_gap; - for (i = 0; i < a_n; ++i) - { - selfLen = indels = 0; - j = i; - while (j >= 0) - { - current_j = j; - - j = dp->pre[j]; - - if(j != -1) - { - distance_self_pos = a[current_j].self_offset - a[j].self_offset; - distance_pos = a[current_j].offset - a[j].offset; - distance_gap = distance_pos > distance_self_pos? distance_pos - distance_self_pos : distance_self_pos - distance_pos; - - indels += distance_gap; - selfLen += distance_self_pos; - } - } - - if(indels != dp->indels[i]) - { - fprintf(stderr, "indels: %lld, dp->indels[i]: %ld\n", indels, (long)dp->indels[i]); - } - - if(selfLen != dp->self_length[i]) - { - fprintf(stderr, "selfLen: %lld, dp->self_length[i]: %ld\n", selfLen, (long)dp->self_length[i]); - } - - } -} - -void print_chain(k_mer_hit* a, long long a_n, Chain_Data* dp, long long topN) -{ - fprintf(stderr, "topN: %lld\n", topN); - long long max_score = -1, max_i = -1, max_n = 0;; - long long ss, i, j, current_j; - kvec_t(long long) si; kv_init(si); - for (ss = 0; ss < topN && ss < a_n; ss++){ - for (i = 0, max_i = -1, max_score = -1; i < a_n; ++i) { - for (j = 0; j < (long long)si.n; j++){ - if(i == si.a[j]) break; - } - if(j < (long long)si.n) continue; - if(dp->score[i] > max_score) max_score = dp->score[i], max_i = i; - } - if(max_i < 0) continue; - j = max_i; max_n = 0; - while (j >= 0) - { - current_j = j; - if(current_j == -1) continue; - j = dp->pre[j]; - max_n++; - } - - fprintf(stderr, "\nmax_i: %lld, max_score: %lld, max_n: %lld\n", max_i, max_score, max_n); - - j = max_i; - while (j >= 0) - { - current_j = j; - if(current_j == -1) continue; - - kv_push(long long, si, current_j); - j = dp->pre[j]; - fprintf(stderr, "self_offset: %u, offset: %u, cnt: %u, score: %d\n", - a[current_j].self_offset, a[current_j].offset, a[current_j].cnt, dp->score[current_j]); - } - } - kv_destroy(si); -} - - -long long get_chainLen(long long x_beg, long long x_end, long long xLen, - long long y_beg, long long y_end, long long yLen) -{ - if(x_beg <= y_beg) - { - y_beg = y_beg - x_beg; - x_beg = 0; - } - else - { - x_beg = x_beg - y_beg; - y_beg = 0; - } - - long long x_right_length = xLen - x_end - 1; - long long y_right_length = yLen - y_end - 1; - - - if(x_right_length <= y_right_length) - { - x_end = xLen - 1; - y_end = y_end + x_right_length; - } - else - { - x_end = x_end + y_right_length; - y_end = yLen - 1; - } - - return x_end - x_beg + 1; -} - - -void debug_chain_single_site(k_mer_hit* a, long long a_n, Chain_Data* dp, int x_readLen, int y_readLen, int s_index) -{ - long long j, current_j = s_index; - long long selfLen = 0, indels = 0; - long long distance_self_pos, distance_pos, distance_gap; - - j = s_index; - while (j >= 0) - { - current_j = j; - - j = dp->pre[j]; - - if(j != -1) - { - distance_self_pos = a[current_j].self_offset - a[j].self_offset; - distance_pos = a[current_j].offset - a[j].offset; - distance_gap = distance_pos > distance_self_pos? distance_pos - distance_self_pos : distance_self_pos - distance_pos; - - indels += distance_gap; - selfLen += distance_self_pos; - } - fprintf(stderr, "j: %lld, score: %lld, occ: %d, pre_j: %lld\n", - current_j, (long long)dp->score[current_j], dp->occ[current_j], j); - } - - fprintf(stderr, "s_self_offset: %u, s_offset: %u, e_self_offset: %u, e_offset: %u, ovlp length: %lld, x_readLen: %d, y_readLen: %d\n", - a[s_index].self_offset, a[s_index].offset, a[current_j].self_offset, a[current_j].offset, - get_chainLen(a[s_index].self_offset, a[current_j].self_offset, x_readLen, - a[s_index].offset, a[current_j].offset, y_readLen), x_readLen, y_readLen); - - if(indels != dp->indels[s_index]) - { - fprintf(stderr, "indels: %lld, dp->indels[i]: %ld\n", indels, (long)dp->indels[s_index]); - } - - if(selfLen != dp->self_length[s_index]) - { - fprintf(stderr, "selfLen: %lld, dp->self_length[i]: %ld\n", selfLen, (long)dp->self_length[s_index]); - } - fprintf(stderr,"\n"); -} - -int32_t ha_chain_check(k_mer_hit *a, int32_t n_a, Chain_Data *dp, int32_t min_sc, double bw_thres) -{ - int32_t i, tot_indel = 0, tot_len = 0; - double bw_pen; - if (n_a == 0) return -1; - for (i = 1; i < n_a; ++i) - if (a[i-1].self_offset >= a[i].self_offset) - break; - if (i < n_a) return -1; - bw_pen = 1.0 / bw_thres; - // dp->score[0] = a[0].good? min_sc : min_sc>>1; - dp->score[0] = normal_w(min_sc, (int64_t)a[0].cnt); - dp->pre[0] = -1, dp->indels[0] = 0, dp->self_length[0] = 0, dp->occ[0] = 1; - for (i = 1; i < n_a; ++i) { - int32_t score, dg; - int32_t dx = (int32_t)a[i].offset - (int32_t)a[i-1].offset; - int32_t dy = (int32_t)a[i].self_offset - (int32_t)a[i-1].self_offset; - int32_t dd = dx > dy? dx - dy : dy - dx; - double gap_rate; - tot_indel += dd; - tot_len += dy; - if (tot_indel > tot_len * bw_thres) break; - dg = dx < dy? dx : dy; - if (dd > THRESHOLD_MAX_SIZE && dd > dg * bw_thres) break; - score = dg < min_sc? dg : min_sc; - score = normal_w(score, (int64_t)a[i].cnt); - gap_rate = (double)tot_indel / tot_len; - score -= (int)(gap_rate * score * bw_pen); - dp->score[i] = dp->score[i-1] + score; - dp->pre[i] = i - 1; - dp->indels[i] = tot_indel; - dp->self_length[i] = tot_len; - dp->occ[i] = i + 1; - } - if (i < n_a) return -1; - return n_a; -} - -///double band_width_threshold = 0.05; -long long chain_DP(k_mer_hit* a, long long a_n, Chain_Data* dp, overlap_region* result, - double band_width_threshold, int max_skip, int x_readLen, int y_readLen, void *km) -{ - long long i, j; - long long self_pos, pos, max_j, max_i, max_score, score; - long long distance_pos, distance_self_pos, distance_gap, distance_min; - ///double band_width_threshold = 0.05; - double band_width_penalty = 1 / band_width_threshold; - long long min_score = asm_opt.k_mer_length; - long long max_indels, max_self_length; - double gap_rate; - long long total_indels, total_self_length; - int32_t ret; - - resize_Chain_Data(dp, a_n, km); - - ret = ha_chain_check(a, a_n, dp, min_score, band_width_threshold); - if (ret > 0) { - a_n = ret; - goto skip_dp; - } - - // fill the score and backtrack arrays - for (i = 0; i < a_n; ++i) dp->tmp[i] = -1; - for (i = 0; i < a_n; ++i) - { - int n_chn_skip = 0; - int n_max_skip = 0; - - pos = a[i].offset; - self_pos = a[i].self_offset; - max_j = -1; - max_score = normal_w(min_score, (int64_t)a[i].cnt); - max_indels = 0; - max_self_length = 0; - - ///may have a pre-cut condition for j - for (j = i - 1; j >= 0; --j) - { - distance_pos = pos - a[j].offset; - distance_self_pos = self_pos - a[j].self_offset; - ///a has been sorted by a[].offset - ///note for a, we do not have any two elements that have both equal offsets and self_offsets - ///but there maybe two elements that have equal offsets or equal self_offsets - if(distance_pos == 0 || distance_self_pos <= 0) - { - continue; - } - - distance_gap = distance_pos > distance_self_pos? distance_pos - distance_self_pos : distance_self_pos - distance_pos; - - total_indels = dp->indels[j] + distance_gap; - total_self_length = dp->self_length[j] + distance_self_pos; - if(total_indels > band_width_threshold * total_self_length) - { - continue; - } - - ///min distance - distance_min = distance_pos < distance_self_pos? distance_pos:distance_self_pos; - score = distance_min < min_score? distance_min : min_score; - ///need to be fixed in r305 - ///if (!a[j].good) score = (score >> 1) + (score & 1); - score = normal_w(score, (int64_t)a[j].cnt); - - gap_rate = (double)((double)(total_indels)/(double)(total_self_length)); - ///if the gap rate > 0.06, score will be negative - score -= (long long)(gap_rate * score * band_width_penalty); - - score += dp->score[j]; - - ///find a new max score - if (score > max_score) {///must use > instead of >= - max_score = score; - max_j = j; - max_indels = total_indels; - max_self_length = total_self_length; - n_max_skip = 0; - if (n_chn_skip > 0) --n_chn_skip; - } else { - if (++n_max_skip > max_skip) - break; - if (dp->tmp[j] == i) { - if (++n_chn_skip > max_skip) - break; - } - } - if (dp->pre[j] >= 0) dp->tmp[dp->pre[j]] = i; - } - - dp->score[i] = max_score; - dp->pre[i] = max_j; - dp->indels[i] = max_indels; - dp->self_length[i] = max_self_length; - dp->occ[i] = 1; - if(max_j != -1) dp->occ[i] = dp->occ[max_j] + 1; - } - - ///debug_chain(a, a_n, dp); - // if((*result).x_id == 2162668 && (*result).y_id == 182804) print_chain(a, a_n, dp, 10); - -skip_dp: - - max_score = -1; - max_i = -1; - long long mini_xLen = x_readLen * 2 + 2, tmp_xLen; - for (i = 0; i < a_n; ++i) - { - if(dp->score[i] > max_score) - { - max_score = dp->score[i]; - max_i = i; - mini_xLen = get_chainLen(a[i].self_offset, a[i].self_offset, x_readLen, - a[i].offset, a[i].offset, y_readLen); - } - else if(dp->score[i] == max_score) - { - tmp_xLen = get_chainLen(a[i].self_offset, a[i].self_offset, x_readLen, - a[i].offset, a[i].offset, y_readLen); - - if(tmp_xLen < mini_xLen) - { - max_score = dp->score[i]; - max_i = i; - - mini_xLen = tmp_xLen; - } - } - - } - - clear_fake_cigar(&(result->f_cigar)); - ///note a has been sorted by offset, that means has been sorted by query offset - i = max_i; - result->x_pos_e = a[i].self_offset; - result->y_pos_e = a[i].offset; - result->shared_seed = max_score; - result->overlapLen = mini_xLen; - - distance_self_pos = result->x_pos_e - a[i].self_offset; - distance_pos = result->y_pos_e - a[i].offset; - long long pre_distance_gap = distance_pos - distance_self_pos; - ///record first site - ///the length of f_cigar should be at least 1 - ///record the offset of reference - add_fake_cigar(&(result->f_cigar), a[i].self_offset, pre_distance_gap, km); - long long chainLen = 0; - if(result->x_pos_strand == 1) - { - while (i >= 0) - { - distance_self_pos = result->x_pos_e - a[i].self_offset; - distance_pos = result->y_pos_e - a[i].offset; - distance_gap = distance_pos - distance_self_pos; - if(distance_gap != pre_distance_gap) - { - pre_distance_gap = distance_gap; - ///record this site - add_fake_cigar(&(result->f_cigar), a[i].self_offset, pre_distance_gap, km); - } - - chainLen++; - result->x_pos_s = a[i].self_offset; - result->y_pos_s = a[i].offset; - i = dp->pre[i]; - } - } - else - { - while (i >= 0) - { - distance_self_pos = result->x_pos_e - a[i].self_offset; - distance_pos = result->y_pos_e - a[i].offset; - distance_gap = distance_pos - distance_self_pos; - if(distance_gap == pre_distance_gap) - { - result->f_cigar.length--; - add_fake_cigar(&(result->f_cigar), a[i].self_offset, pre_distance_gap, km); - } - else - { - pre_distance_gap = distance_gap; - add_fake_cigar(&(result->f_cigar), a[i].self_offset, pre_distance_gap, km); - } - - chainLen++; - result->x_pos_s = a[i].self_offset; - result->y_pos_s = a[i].offset; - i = dp->pre[i]; - } - } - return chainLen; -} - - - -void calculate_overlap_region_by_chaining(Candidates_list* candidates, overlap_region_alloc* overlap_list, kvec_t_u64_warp* chain_idx, - uint64_t readID, uint64_t readLength, All_reads* R_INF, const ul_idx_t *uref, double band_width_threshold, int add_beg_end, overlap_region* f_cigar, void *km) -{ - long long i = 0; - uint64_t current_ID; - uint64_t current_stand; - - if (candidates->length == 0) return; - - long long sub_region_beg; - long long sub_region_end; - - clear_fake_cigar(&((*f_cigar).f_cigar)); - - i = 0; - while (i < candidates->length) - { - chain_idx->a.n = 0; - current_ID = candidates->list[i].readID; - current_stand = candidates->list[i].strand; - - ///reference read - (*f_cigar).x_id = readID; - (*f_cigar).x_pos_strand = current_stand; - ///query read - (*f_cigar).y_id = current_ID; - ///here the strand of query is always 0 - (*f_cigar).y_pos_strand = 0; - - sub_region_beg = i; - sub_region_end = i; - i++; - - while (i < candidates->length - && - current_ID == candidates->list[i].readID - && - current_stand == candidates->list[i].strand) - { - sub_region_end = i; - i++; - } - - if ((*f_cigar).x_id == (*f_cigar).y_id) - { - continue; - } - - chain_DP(candidates->list + sub_region_beg, - sub_region_end - sub_region_beg + 1, &(candidates->chainDP), f_cigar, band_width_threshold, - 25, /**Get_READ_LENGTH((*R_INF), (*f_cigar).x_id)**/readLength, - R_INF?Get_READ_LENGTH((*R_INF), (*f_cigar).y_id):uref->ug->u.a[(*f_cigar).y_id].len, km); - - ///if (tmp_region.x_id != tmp_region.y_id && tmp_region.shared_seed > 1) - if ((*f_cigar).x_id != (*f_cigar).y_id) - { - append_inexact_overlap_region_alloc(overlap_list, f_cigar, readLength, R_INF?Get_READ_LENGTH((*R_INF), (*f_cigar).y_id):uref->ug->u.a[(*f_cigar).y_id].len, add_beg_end, km); - } - } -} - - -void append_window_list(overlap_region* region, uint64_t x_start, uint64_t x_end, int y_start, int y_end, int error, - int extra_begin, int extra_end, int error_threshold, int blockLen, void *km) -{ - window_list *p = NULL; - kv_pushp(window_list, region->w_list, &p); - - p->x_start = x_start; - p->x_end = x_end; - p->y_start = y_start; - p->y_end = y_end; - p->error = error; - p->extra_begin = extra_begin; - p->extra_end = extra_end; - p->error_threshold = error_threshold; - p->cidx = p->clen = 0; -} - -void test_single_list(Candidates_list* candidates, k_mer_pos* n_list, uint64_t n_lengh, uint64_t end_pos, uint64_t strand) -{ - uint64_t i; - long long j = 0; - for (i = 0; i < n_lengh; i++) - { - - for (; j < candidates->length; j++) - { - if ( - n_list[i].offset == (uint64_t)candidates->list[j].offset - && - n_list[i].readID == candidates->list[j].readID - && - end_pos == (uint64_t)candidates->list[j].self_offset - && - strand == candidates->list[j].strand - ) - { - break; - } - } - - if (j == candidates->length) - { - fprintf(stderr, "ERROR 4\n"); - } - } -} - - -void init_Chain_Data(Chain_Data* x) -{ - memset(x, 0, sizeof(Chain_Data)); -} - -void clear_Chain_Data(Chain_Data* x) -{ - x->length = 0; -} - -void destory_Chain_Data(Chain_Data* x) -{ - free(x->score); - free(x->pre); - free(x->indels); - free(x->self_length); - free(x->occ); - free(x->tmp); -} - -void resize_Chain_Data(Chain_Data* x, long long size, void *km) -{ - if (size + 1 > x->size) { - x->size = size + 1; - kroundup64(x->size); - if(!km) { - REALLOC(x->score, x->size); - REALLOC(x->pre, x->size); - REALLOC(x->indels, x->size); - REALLOC(x->self_length, x->size); - REALLOC(x->occ, x->size); - REALLOC(x->tmp, x->size); - } else { - KREALLOC(km, x->score, x->size); - KREALLOC(km, x->pre, x->size); - KREALLOC(km, x->indels, x->size); - KREALLOC(km, x->self_length, x->size); - KREALLOC(km, x->occ, x->size); - KREALLOC(km, x->tmp, x->size); - } - } -} - -void init_Candidates_list(Candidates_list* l) -{ - l->length = 0; - l->size = 0; - l->list = NULL; - init_Chain_Data(&(l->chainDP)); -} - -void clear_Candidates_list(Candidates_list* l) -{ - l->length = 0; - clear_Chain_Data(&(l->chainDP)); -} - -void destory_Candidates_list(Candidates_list* l) -{ - free(l->list); - destory_Chain_Data(&(l->chainDP)); -} - -void destory_Candidates_list_buf(void *km, Candidates_list* l, int is_z) -{ - kfree(km, l->list); - kfree(km, l->chainDP.score); - kfree(km, l->chainDP.pre); - kfree(km, l->chainDP.indels); - kfree(km, l->chainDP.self_length); - kfree(km, l->chainDP.occ); - kfree(km, l->chainDP.tmp); - if(is_z) memset(l, 0, sizeof(*l)); -} - -void init_fake_cigar(Fake_Cigar* x) -{ - x->buffer = NULL; - x->length = 0; - x->size = 0; -} - -void destory_fake_cigar(Fake_Cigar* x) -{ - if(x->size > 0) - { - free(x->buffer); - } -} - -void clear_fake_cigar(Fake_Cigar* x) -{ - x->length = 0; -} - -void add_fake_cigar(Fake_Cigar* x, uint32_t gap_site, int32_t gap_shift, void *km) -{ - if(x->length + 1 > x->size) - { - x->size = x->length + 1; - kroundup32(x->size); - if(!km) { - REALLOC(x->buffer, x->size); - } else { - KREALLOC(km, x->buffer, x->size); - } - // x->buffer = (uint64_t*)realloc(x->buffer, sizeof(uint64_t) * x->size); - } - - x->buffer[x->length] = gap_site; - x->buffer[x->length] = x->buffer[x->length] << 32; - - if(gap_shift < 0) - { - gap_shift = gap_shift * -1; - gap_site = gap_shift; - gap_site = gap_site << 1; - gap_site = gap_site | ((uint32_t)1); - } - else - { - gap_site = gap_shift; - gap_site = gap_site << 1; - } - - x->buffer[x->length] = x->buffer[x->length] | ((uint32_t)gap_site); - - x->length++; -} - - -void resize_fake_cigar(Fake_Cigar* x, uint64_t size, void *km) -{ - if (size > x->size) { - x->size = size; - if(!km) { - REALLOC(x->buffer, x->size); - } - else { - KREALLOC(km, x->buffer, x->size); - } - - } - x->length = 0; -} - - -void init_window_list_alloc(window_list_alloc* x) -{ - memset(x, 0, sizeof((*x))); -} - -void clear_window_list_alloc(window_list_alloc* x) -{ - x->n = x->c.n = 0; -} - -void destory_window_list_alloc(window_list_alloc* x) -{ - free(x->a); free(x->c.a); -} - -void resize_window_list_alloc(window_list_alloc* x, uint64_t size) -{ - kv_resize(window_list, *x, size); x->n = x->c.n = 0; - uint64_t k; - for (k = 0; k < x->m; k++) x->a[k].error = -1; - x->c.n = 0; -} - -#define normal_cw(x) (((x)&(0xffu))>=((x)>>8)?(((x)&(0xffu))/((x)>>8)):1) - -int32_t lchain_check(k_mer_hit *a, int32_t n_a, Chain_Data *dp, double bw_thres) -{ - int32_t i, tot_g = 0, sc, dg, dq, dr, dd, span; - double bw_pen; - if (n_a == 0) return -1; - if (n_a > 1) { - if ((a[0].self_offset >= a[n_a-1].self_offset)||(a[0].offset == a[n_a-1].offset)) return -1; - dq = (int32_t)a[n_a-1].self_offset - (int32_t)a[0].self_offset; - dr = (int32_t)a[n_a-1].offset - (int32_t)a[0].offset; - dd = ((dq>=dr)? (dq-dr): (dr-dq));//gap - dg = ((dq>=dr)? (dr): (dq));///len - if (dg == 0 || dd > (dg*bw_thres)) return -1; - } - - for (i = 1; i < n_a; ++i) {///a[] is sorted by offset, instead of self_offset; but offset might be equal - if(a[i-1].self_offset >= a[i].self_offset) break; - if(a[i-1].offset == a[i].offset) break; - } - if (i < n_a) return -1; - - bw_pen = 1.0 / bw_thres; - dp->score[0] = normal_w((a[0].cnt&(0xffu)), (a[0].cnt>>8)); dp->pre[0] = -1; - for (i = 1; i < n_a; ++i) { - dq = (int32_t)a[i].self_offset - (int32_t)a[i-1].self_offset; - dr = (int32_t)a[i].offset - (int32_t)a[i-1].offset; - dd = ((dq>=dr)? (dq-dr): (dr-dq));//gap - dg = ((dq>=dr)? (dr): (dq));///len - if(dg == 0) break; - - tot_g += dd; - if (dd > THRESHOLD_MAX_SIZE && dd > (dg*bw_thres)) break; - span = a[i].cnt&(0xffu); - sc = dg < span? dg : span; - sc = normal_w(sc, ((int32_t)(a[i].cnt>>8))); - sc -= (int32_t)((((double)dd)/((double)dg))*bw_pen*((double)sc));///bw_pen is 20 for HiFi - - dp->score[i] = dp->score[i-1] + sc; - dp->pre[i] = i - 1; - } - if (i < n_a) return -1; - - if(n_a > 1) { - dq = (int32_t)a[n_a-1].self_offset - (int32_t)a[0].self_offset; - dr = (int32_t)a[n_a-1].offset - (int32_t)a[0].offset; - dg = ((dq>=dr)? (dr): (dq));///len - dd = tot_g;///gap - if (dd > (dg*bw_thres)) return -1; - } - return n_a; -} - - -int32_t lchain_qcheck(k_mer_hit *a, int32_t n_a, Chain_Data *dp, double bw_thres) -{ - int32_t i, tot_g = 0, sc, dg, dq, dr, dd, span; - double bw_pen; - if (n_a == 0) return -1; - if (n_a > 1) { - if ((a[0].self_offset >= a[n_a-1].self_offset)||(a[0].offset >= a[n_a-1].offset)) return -1; - dq = (int32_t)a[n_a-1].self_offset - (int32_t)a[0].self_offset; - dr = (int32_t)a[n_a-1].offset - (int32_t)a[0].offset; - dd = ((dq>=dr)? (dq-dr): (dr-dq));//gap - dg = ((dq>=dr)? (dr): (dq));///len - if (dg == 0 || dd > (dg*bw_thres)) return -1; - } - - for (i = 1; i < n_a; ++i) {///a[] is sorted by self_offset - if(a[i-1].self_offset >= a[i].self_offset) break; - if(a[i-1].offset >= a[i].offset) break; - } - if (i < n_a) return -1; - - bw_pen = 1.0 / bw_thres; - dp->score[0] = normal_w((a[0].cnt&(0xffu)), (a[0].cnt>>8)); dp->pre[0] = -1; - for (i = 1; i < n_a; ++i) { - dq = (int32_t)a[i].self_offset - (int32_t)a[i-1].self_offset; - dr = (int32_t)a[i].offset - (int32_t)a[i-1].offset; - dd = ((dq>=dr)? (dq-dr): (dr-dq));//gap - dg = ((dq>=dr)? (dr): (dq));///len - if(dg == 0) break; - - tot_g += dd; - if (dd > THRESHOLD_MAX_SIZE && dd > (dg*bw_thres)) break; - span = a[i].cnt&(0xffu); - sc = dg < span? dg : span; - sc = normal_w(sc, ((int32_t)(a[i].cnt>>8))); - sc -= (int32_t)((((double)dd)/((double)dg))*bw_pen*((double)sc));///bw_pen is 20 for HiFi - - dp->score[i] = dp->score[i-1] + sc; - dp->pre[i] = i - 1; - } - if (i < n_a) return -1; - - if(n_a > 1) { - dq = (int32_t)a[n_a-1].self_offset - (int32_t)a[0].self_offset; - dr = (int32_t)a[n_a-1].offset - (int32_t)a[0].offset; - dg = ((dq>=dr)? (dr): (dq));///len - dd = tot_g;///gap - if (dd > (dg*bw_thres)) return -1; - } - return n_a; -} - -inline int32_t cal_bw(const k_mer_hit *ai, const k_mer_hit *aj, double bw_rate, int64_t sf_l, int64_t ot_l) -{ - ///ai is the suffix of aj - int64_t sf_s = aj->self_offset, sf_e = ai->self_offset + 1; - int64_t ot_s = aj->offset, ot_e = ai->offset + 1; - int64_t sf_r = sf_l - sf_e, ot_r = ot_l - ot_e; - if(sf_s <= ot_s) sf_s = 0; - else sf_s -= ot_s; - - if(sf_r <= ot_r) sf_e = sf_l; - else sf_e += ot_r; - - return (sf_e - sf_s)*bw_rate; -} - -inline int32_t comput_sc_ch(const k_mer_hit *ai, const k_mer_hit *aj, double bw_rate, double chn_pen_gap, double chn_pen_skip, int64_t sl, int64_t ol) -{ - ///ai is the suffix of aj - int32_t dq, dr, dd, dg, q_span, sc; - dq = (int64_t)(ai->self_offset) - (int64_t)(aj->self_offset); - if(dq <= 0) return INT32_MIN; - dr = (int64_t)(ai->offset) - (int64_t)(aj->offset); - if(dr <= 0) return INT32_MIN; - dd = dr > dq? dr - dq : dq - dr;//gap - if((dd > 16) && (dd > cal_bw(ai, aj, bw_rate, sl, ol))) return INT32_MIN; - dg = dr < dq? dr : dq;//len - q_span = ai->cnt&(0xffu); - sc = q_span < dg? q_span : dg; - sc = normal_w(sc, ((int32_t)(ai->cnt>>8))); - if (dd || (dg > q_span && dg > 0)) { - double lin_pen, a_pen; - lin_pen = (chn_pen_gap*(double)dd); - a_pen = ((double)(sc))*((((double)dd)/((double)dg))/bw_rate); - if(lin_pen > a_pen) lin_pen = a_pen; - lin_pen += (chn_pen_skip*(double)dg); - sc -= (int32_t)lin_pen; - } - return sc; -} - -inline int32_t comput_sc_ch_ec(const k_mer_hit *ai, const k_mer_hit *aj, double bw_rate, double chn_pen_gap, double chn_pen_skip, int64_t sl, int64_t ol) -{ - ///ai is the suffix of aj - int32_t dq, dr, dd, dg, q_span, sc; - dq = (int64_t)(ai->self_offset) - (int64_t)(aj->self_offset); - if(dq <= 0) return INT32_MIN; - dr = (int64_t)(ai->offset) - (int64_t)(aj->offset); - if(dr <= 0) return INT32_MIN; - dd = dr > dq? dr - dq : dq - dr;//gap - if((dd > 16) && (dd > cal_bw(ai, aj, bw_rate, sl, ol))) return INT32_MIN; - dg = dr < dq? dr : dq;//len - q_span = ai->cnt&(0xffu); - sc = q_span < dg? q_span : dg; - sc = normal_w(sc, ((int32_t)(ai->cnt>>8))); - if (dd || (dg > q_span && dg > 0)) { - double lin_pen, a_pen; - lin_pen = (chn_pen_gap*(double)dd); - a_pen = ((double)(sc))*((((double)dd)/((double)dg))/bw_rate); - ///for long gap - // if(lin_pen > a_pen) lin_pen = a_pen; - if(dd < 4) lin_pen = ((lin_pen > a_pen)?(a_pen):(lin_pen)); - else lin_pen = ((lin_pen < a_pen)?(a_pen):(lin_pen)); - lin_pen += (chn_pen_skip*(double)dg); - sc -= (int32_t)lin_pen; - } - return sc; -} - -inline int32_t comput_sc_ff(const k_mer_hit *ai, const k_mer_hit *aj, double bw_rate, double chn_pen_gap, double chn_pen_skip, int64_t sl, int64_t ol) -{ - ///ai is the suffix of aj - int32_t dq, dr, dd, dg, q_span, sc; - dq = (int64_t)(ai->self_offset) - (int64_t)(aj->self_offset); - if(dq < 0) return INT32_MIN; - dr = (int64_t)(ai->offset) - (int64_t)(aj->offset); - if(dr < 0) return INT32_MIN; - dd = dr > dq? dr - dq : dq - dr;//gap - // if((dd > 16) && (dd > cal_bw(ai, aj, bw_rate, sl, ol))) return INT32_MIN; - dg = dr < dq? dr : dq;//len - q_span = ai->cnt&(0xffu); - sc = q_span < dg? q_span : dg; - sc = normal_w(sc, ((int32_t)(ai->cnt>>8))); - if (dd || (dg > q_span && dg > 0)) { - double lin_pen, a_pen; - lin_pen = (chn_pen_gap*(double)dd); - a_pen = ((double)(sc))*((((double)dd)/((double)dg))/bw_rate); - if(lin_pen > a_pen) lin_pen = a_pen; - lin_pen += (chn_pen_skip*(double)dg); - sc -= (int32_t)lin_pen; - } - return sc; -} - -uint64_t lchain_dp(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, overlap_region* res, - int64_t max_skip, int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, - int64_t xl, int64_t yl, int64_t quick_check) -{ - int64_t *p, *t, max_f, n_skip, st, max_j, end_j, sc, msc, msc_i, bw, max_ii, ovl, movl; - int32_t *f, max, tmp; int64_t i, j, ret, cL = 0; - resize_Chain_Data(dp, a_n, NULL); - t = dp->tmp; f = dp->score; p = dp->pre; - bw = ((xl < yl)?xl:yl); bw *= bw_rate; - msc = msc_i = -1; movl = INT32_MAX; - - if(quick_check) { - ret = lchain_check(a, a_n, dp, bw_rate); - if (ret > 0) { - a_n = ret; msc_i = a_n-1; msc = f[msc_i]; - goto skip_ldp; - } - } - - memset(t, 0, (a_n*sizeof((*t)))); - for (i = st = 0, max_ii = -1; i < a_n; ++i) { - max_f = a[i].cnt&(0xffu); - n_skip = 0; max_j = end_j = -1; - if ((i-st) > max_iter) st = i-max_iter; - - for (j = i - 1; j >= st; --j) { - sc = comput_sc_ch(&a[i], &a[j], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); - if (sc == INT32_MIN) continue; - sc += f[j]; - if (sc > max_f) { - max_f = sc, max_j = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == (int32_t)i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - end_j = j; - - if (max_ii < 0 || ((int64_t)a[i].offset) - ((int64_t)a[max_ii].offset) > max_dis) { - max = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && ((((int64_t)a[i].offset)-((int64_t)a[j].offset))<=max_dis); --j) { - if (max < f[j]) { - max = f[j], max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - tmp = comput_sc_ch(&a[i], &a[max_ii], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); - if (tmp != INT32_MIN && max_f < tmp + f[max_ii]) - max_f = tmp + f[max_ii], max_j = max_ii; - } - f[i] = max_f; p[i] = max_j; - if ((max_ii < 0) || (((((int64_t)a[i].offset)-((int64_t)a[max_ii].offset))<=max_dis) && (f[max_ii]= msc) { - ovl = get_chainLen(a[i].self_offset, a[i].self_offset, xl, a[i].offset, a[i].offset, yl); - if(f[i] > msc || ovl < movl) { - msc = f[i]; msc_i = i; movl = ovl; - } - } - } - - skip_ldp: - ///a[] has been sorted by offset - i = msc_i; - res->x_pos_s = res->x_pos_e = a[i].self_offset; - res->y_pos_s = res->y_pos_e = a[i].offset; - res->shared_seed = msc; - - cL = 0; - while (i >= 0) { - t[cL++] = i; msc_i = i; i = p[i]; - } - - res->x_pos_s = a[t[cL-1]].self_offset; - res->y_pos_s = a[t[cL-1]].offset; - res->overlapLen = get_chainLen(res->x_pos_s, res->x_pos_e, xl, res->y_pos_s, res->y_pos_e, yl); - for (i = 0; i < cL; i++) des[i] = a[t[cL-i-1]]; - return cL; -} - -uint64_t lchain_qdp(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, overlap_region* res, - int64_t max_skip, int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, - int64_t xl, int64_t yl, int64_t quick_check) -{ - int64_t *p, *t, max_f, n_skip, st, max_j, end_j, sc, msc, msc_i, bw, max_ii, ovl, movl; - int32_t *f, max, tmp; int64_t i, j, ret, cL = 0; - resize_Chain_Data(dp, a_n, NULL); - t = dp->tmp; f = dp->score; p = dp->pre; - bw = ((xl < yl)?xl:yl); bw *= bw_rate; - msc = msc_i = -1; movl = INT32_MAX; - // if(a_n && a[0].readID == 0) { - // fprintf(stderr, "---[M::%s::utg%.6dl::%c]\n", - // __func__, (int32_t)a[0].readID+1, "+-"[a[0].strand]); - // } - if(quick_check) { - ret = lchain_qcheck(a, a_n, dp, bw_rate); - if (ret > 0) { - a_n = ret; msc_i = a_n-1; msc = f[msc_i]; - goto skip_ldp; - } - } - - memset(t, 0, (a_n*sizeof((*t)))); - for (i = st = 0, max_ii = -1; i < a_n; ++i) { - max_f = a[i].cnt&(0xffu); - n_skip = 0; max_j = end_j = -1; - if ((i-st) > max_iter) st = i-max_iter; - - for (j = i - 1; j >= st; --j) { - sc = comput_sc_ch(&a[i], &a[j], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); - if (sc == INT32_MIN) continue; - sc += f[j]; - if (sc > max_f) { - max_f = sc, max_j = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == (int32_t)i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - end_j = j; - - if (max_ii < 0 || ((int64_t)a[i].self_offset) - ((int64_t)a[max_ii].self_offset) > max_dis) { - max = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && ((((int64_t)a[i].self_offset)-((int64_t)a[j].self_offset))<=max_dis); --j) { - if (max < f[j]) { - max = f[j], max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - tmp = comput_sc_ch(&a[i], &a[max_ii], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); - if (tmp != INT32_MIN && max_f < tmp + f[max_ii]) - max_f = tmp + f[max_ii], max_j = max_ii; - } - f[i] = max_f; p[i] = max_j; - if ((max_ii < 0) || (((((int64_t)a[i].self_offset)-((int64_t)a[max_ii].self_offset))<=max_dis) && (f[max_ii]= msc) { - ovl = get_chainLen(a[i].self_offset, a[i].self_offset, xl, a[i].offset, a[i].offset, yl); - if(f[i] > msc || ovl < movl) { - msc = f[i]; msc_i = i; movl = ovl; - } - } - // if(a_n && a[0].readID == 0) { - // fprintf(stderr, "i::%ld[M::%s::utg%.6dl::%c] x::%u, y::%u, st::%ld, max_ii::%ld, f[i]::%d, p[i]::%ld, msc_i::%ld, msc::%ld, movl::%ld\n", - // i, __func__, (int32_t)a[i].readID+1, "+-"[a[i].strand], - // a[i].self_offset, a[i].offset, st, max_ii, f[i], p[i], msc_i, msc, movl); - // } - } - - skip_ldp: - ///a[] has been sorted by self_offset - i = msc_i; - res->x_pos_s = res->x_pos_e = a[i].self_offset; - res->y_pos_s = res->y_pos_e = a[i].offset; - res->shared_seed = msc; - - cL = 0; - while (i >= 0) { - t[cL++] = i; msc_i = i; i = p[i]; - } - - res->x_pos_s = a[t[cL-1]].self_offset; - res->y_pos_s = a[t[cL-1]].offset; - res->overlapLen = get_chainLen(res->x_pos_s, res->x_pos_e, xl, res->y_pos_s, res->y_pos_e, yl); - for (i = 0; i < cL; i++) { - des[i] = a[t[cL-i-1]]; - // if(a_n && a[0].readID == 0) { - // fprintf(stderr, "i::%ld[M::%s::utg%.6dl::%c] x::%u, y::%u, cL::%ld\n", - // i, __func__, (int32_t)des[i].readID+1, "+-"[des[i].strand], des[i].self_offset, des[i].offset, cL); - // } - } - return cL; -} - -void push_ovlp_chain_qgen(overlap_region* o, uint32_t xid, int64_t xl, int64_t yl, int64_t sc, -k_mer_hit *beg, k_mer_hit *end) -{ - int64_t xr, yr; - o->x_id = xid; o->y_id = beg->readID; - o->x_pos_strand = 0; o->y_pos_strand = beg->strand; - o->x_pos_s = beg->self_offset; o->y_pos_s = beg->offset; - o->x_pos_e = end->self_offset; o->y_pos_e = end->offset; - - if(o->x_pos_s <= o->y_pos_s) { - o->y_pos_s -= o->x_pos_s; o->x_pos_s = 0; - } else { - o->x_pos_s -= o->y_pos_s; o->y_pos_s = 0; - } - - xr = xl-o->x_pos_e-1; yr = yl-o->y_pos_e-1; - if(xr <= yr) { - o->x_pos_e = xl-1; o->y_pos_e += xr; - } else { - o->y_pos_e = yl-1; o->x_pos_e += yr; - } - - o->shared_seed = sc; - o->align_length = 0; - o->is_match = 0; - o->non_homopolymer_errors = 0; - o->strong = 0; - o->overlapLen = 0; -} - -int64_t filter_non_ovlp_chains(overlap_region *a, int64_t a_n, int64_t *n_v) -{ - int64_t k, i, n_mchain, omx, omy, opx, opy, ovx, ovy, os, oe; overlap_region *m, *p, t; - for (k = n_mchain = (*n_v) = 0; k < a_n; k++) { - m = &(a[k]); - omx = m->x_pos_e + 1 - m->x_pos_s; - omy = m->y_pos_e + 1 - m->y_pos_s; - for (i = 0; i < n_mchain; i++) { - p = &(a[i]); - opx = p->x_pos_e + 1 - p->x_pos_s; - opy = p->y_pos_e + 1 - p->y_pos_s; - - os = ((m->x_pos_s>=p->x_pos_s)? m->x_pos_s:p->x_pos_s); - oe = ((m->x_pos_e<=p->x_pos_e)? m->x_pos_e:p->x_pos_e) + 1; - ovx = oe>os?oe-os:0; - if((ovx > omx*0.1) || (ovx > opx*0.1)) break; - - os = ((m->y_pos_s>=p->y_pos_s)? m->y_pos_s:p->y_pos_s); - oe = ((m->y_pos_e<=p->y_pos_e)? m->y_pos_e:p->y_pos_e) + 1; - ovy = oe>os?oe-os:0; - if((ovy > omy*0.1) || (ovy > opy*0.1)) break; - } - if(i < n_mchain) continue; - - if (n_mchain != k) { - t = a[k]; a[k] = a[n_mchain]; a[n_mchain] = t; - } - (*n_v) += a[n_mchain].align_length; - n_mchain++; - } - return n_mchain; -} - -int64_t filter_non_ovlp_xchains(overlap_region *a, int64_t a_n, int64_t *n_v) -{ - int64_t k, i, n_mchain, omx, opx, ovx, os, oe; overlap_region *m, *p, t; - for (k = n_mchain = (*n_v) = 0; k < a_n; k++) { - m = &(a[k]); - omx = m->x_pos_e + 1 - m->x_pos_s; - for (i = 0; i < n_mchain; i++) { - p = &(a[i]); - opx = p->x_pos_e + 1 - p->x_pos_s; - - os = ((m->x_pos_s>=p->x_pos_s)? m->x_pos_s:p->x_pos_s); - oe = ((m->x_pos_e<=p->x_pos_e)? m->x_pos_e:p->x_pos_e) + 1; - ovx = oe>os?oe-os:0; - if((ovx > omx*0.1) || (ovx > opx*0.1)) break; - } - if(i < n_mchain) continue; - - if (n_mchain != k) { - t = a[k]; a[k] = a[n_mchain]; a[n_mchain] = t; - } - (*n_v) += a[n_mchain].align_length; - n_mchain++; - } - return n_mchain; -} - -uint64_t lchain_qdp_mcopy(Candidates_list *cl, int64_t a_idx, int64_t a_n, int64_t des_idx, - Chain_Data* dp, overlap_region_alloc* res, int64_t max_skip, int64_t max_iter, - int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, - uint32_t xid, int64_t xl, int64_t yl, int64_t quick_check, uint32_t apend_be, - int64_t gen_cigar, int64_t enable_mcopy, double mcopy_rate, int64_t mcopy_khit_cutoff, - int64_t khit_n) -{ - if(a_n <= 0) return 0; - int64_t *p, *t, max_f, n_skip, st, max_j, end_j, sc, msc, msc_i, bw, max_ii, ovl, movl, plus = 0, min_sc, ch_n; - int32_t *f, max, tmp, *ii; int64_t i, k, j, cL = 0; k_mer_hit* a; k_mer_hit* des; k_mer_hit *swap; overlap_region *z; - resize_Chain_Data(dp, a_n, NULL); - t = dp->tmp; f = dp->score; p = dp->pre; ii = dp->occ; - bw = ((xl < yl)?xl:yl); bw *= bw_rate; - msc = msc_i = INT32_MIN; movl = INT32_MAX; ch_n = 1; - a = cl->list + a_idx; des = cl->list + des_idx; - // if(a_n && a[0].readID == 0) { - // fprintf(stderr, "---[M::%s::utg%.6dl::%c]\n", - // __func__, (int32_t)a[0].readID+1, "+-"[a[0].strand]); - // } - - memset(t, 0, (a_n*sizeof((*t)))); - for (i = st = plus = 0, max_ii = -1; i < a_n; ++i) { - max_f = a[i].cnt&(0xffu); - n_skip = 0; max_j = end_j = -1; - if ((i-st) > max_iter) st = i-max_iter; - while (a[i].strand != a[st].strand) ++st; - - for (j = i - 1; j >= st; --j) { - sc = comput_sc_ch(&a[i], &a[j], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); - if (sc == INT32_MIN) continue; - sc += f[j]; - if (sc > max_f) { - max_f = sc, max_j = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == (int32_t)i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - end_j = j; - - if ((max_ii<0) || (a[i].self_offset>a[max_ii].self_offset+max_dis) || (a[i].strand!=a[max_ii].strand)) { - max = INT32_MIN; max_ii = -1; - for (j=i-1; (j>=st) && (a[i].self_offset<=max_dis+a[j].self_offset)&&(a[i].strand==a[j].strand); --j) { - if (max < f[j]) { - max = f[j], max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - tmp = comput_sc_ch(&a[i], &a[max_ii], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); - if (tmp != INT32_MIN && max_f < tmp + f[max_ii]) - max_f = tmp + f[max_ii], max_j = max_ii; - } - f[i] = max_f; p[i] = max_j; - if ((max_ii < 0) || ((a[i].self_offset<=max_dis+a[max_ii].self_offset)&&(a[i].strand==a[max_ii].strand)&&(f[max_ii]= msc) { - ovl = get_chainLen(a[i].self_offset, a[i].self_offset, xl, a[i].offset, a[i].offset, yl); - if(f[i] > msc || ovl < movl) { - msc = f[i]; msc_i = i; movl = ovl; - } - } - if(f[i] < plus) plus = f[i]; - ii[i] = 0;///for mcopy, not here - // if(a_n && a[0].readID == 0) { - // fprintf(stderr, "i::%ld[M::%s::utg%.6dl::%c] x::%u, y::%u, st::%ld, max_ii::%ld, f[i]::%d, p[i]::%ld, msc_i::%ld, msc::%ld, movl::%ld\n", - // i, __func__, (int32_t)a[i].readID+1, "+-"[a[i].strand], - // a[i].self_offset, a[i].offset, st, max_ii, f[i], p[i], msc_i, msc, movl); - // } - } - - for (i = msc_i, cL = 0; i >= 0; i = p[i]) { ii[i] = 1; t[cL++] = i;}///label the best chain - if((movl < xl) && enable_mcopy/**(movl < yl)**/) { - if(cL >= mcopy_khit_cutoff) {///if there are too few k-mers, disable mcopy - msc -= plus; min_sc = msc*mcopy_rate/**0.2**/; ii[msc_i] = 0; - for (i = ch_n = 0; i < a_n; ++i) {///make all f[] positive - f[i] -= plus; if(i >= ch_n) t[i] = 0; - if((!(ii[i])) && (f[i] >= min_sc)) { - t[ch_n] = ((uint64_t)f[i])<<32; t[ch_n] += (i<<1); ch_n++; - } - } - if(ch_n > 1) { - int64_t n_v, n_v0, ni, n_u, n_u0 = res->length; - radix_sort_hc64i(t, t + ch_n); - for (k = ch_n-1, n_v = n_u = 0; k >= 0; --k) { - n_v0 = n_v; - for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { - ii[n_v++] = i; t[i] |= 1; i = p[i]; - } - if(n_v0 == n_v) continue; - sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); - if(sc >= min_sc) { - kv_pushp_ol(overlap_region, (*res), &z); - push_ovlp_chain_qgen(z, xid, xl, yl, sc+plus, &(a[ii[n_v-1]]), &(a[ii[n_v0]])); - ///mcopy_khit_cutoff <= 1: disable the mcopy_khit_cutoff filtering, for the realignment - if((mcopy_khit_cutoff <= 1) || ((z->x_pos_e+1-z->x_pos_s) <= (movl<<2))) { - z->align_length = n_v-n_v0; z->x_id = n_v0; - n_u++; - } else {///non-best is too long - res->length--; n_v = n_v0; - } - } else { - n_v = n_v0; - } - } - - if(n_u > 1) ks_introsort_or_sss(n_u, res->list + n_u0); - res->length = n_u0 + filter_non_ovlp_xchains(res->list + n_u0, n_u, &n_v); - n_u = res->length; - if(n_u > n_u0 + 1) { - kv_resize_cl(k_mer_hit, (*cl), (n_v+cl->length)); - a = cl->list + a_idx; des = cl->list + des_idx; swap = cl->list + cl->length; - for (k = n_u0, i = n_v0 = n_v = 0; k < n_u; k++) { - z = &(res->list[k]); - z->non_homopolymer_errors = des_idx + i; - n_v0 = z->x_id; ni = z->align_length; - for (j = 0; j < ni; j++, i++) { - ///k0 + (ni - j - 1) - swap[i] = a[ii[n_v0 + (ni- j - 1)]]; - swap[i].readID = k; - } - z->x_id = xid; - if(gen_cigar) gen_fake_cigar(&(z->f_cigar), z, apend_be, swap+i-ni, ni); - if(!khit_n) z->align_length = 0; - } - memcpy(des, swap, i*sizeof((*swap))); //assert(i == ch_n); - - // fprintf(stderr, "[M::%s::msc->%ld] msc_k_hits::%u, cL::%ld, min_sc::%ld, best_sc::%ld, n_u0_sc::%d, mcopy_rate::%f, # chains::%ld\n", - // __func__, msc, res->list[n_u0].align_length, cL, min_sc, msc+plus, res->list[n_u0].shared_seed, - // mcopy_rate, n_u-n_u0); - } else if(n_u == n_u0 + 1) { - z = &(res->list[n_u0]); k = n_u0; i = 0; - z->non_homopolymer_errors = des_idx + i; - n_v0 = z->x_id; ni = z->align_length; - for (j = 0; j < ni; j++, i++) { - ///k0 + (ni - j - 1) - des[i] = a[ii[n_v0 + (ni- j - 1)]]; - des[i].readID = k; - } - z->x_id = xid; - if(gen_cigar) gen_fake_cigar(&(z->f_cigar), z, apend_be, des+i-ni, ni); - if(!khit_n) z->align_length = 0; - } - return i; - } else { - msc += plus; i = msc_i; cL = 0; - while (i >= 0) {t[cL++] = i; i = p[i];} - } - } - } - ///a[] has been sorted by self_offset - // i = msc_i; cL = 0; - // while (i >= 0) {t[cL++] = i; i = p[i];} - kv_pushp_ol(overlap_region, (*res), &z); - push_ovlp_chain_qgen(z, xid, xl, yl, msc, &(a[t[cL-1]]), &(a[t[0]])); - for (i = 0; i < cL; i++) {des[i] = a[t[cL-i-1]]; des[i].readID = res->length-1;} - z->non_homopolymer_errors = des_idx; - if(gen_cigar) gen_fake_cigar(&(z->f_cigar), z, apend_be, des, cL); - if(khit_n) z->align_length = cL; - return cL; -} - -void quick_ck_lchain(k_mer_hit* a, int64_t a_n, int64_t xl, int64_t yl, double chn_pen_gap, double chn_pen_skip, double bw_rate, -int64_t *p, int64_t *t, int32_t *f, int32_t *ii, int64_t *plus, int64_t *msc, int64_t *msc_i, int64_t *movl, int64_t *si, int64_t *ei) -{ - if(a_n <= 0) return; - int64_t l, k, is_srt = 1, z; k_mer_hit *ai, *aj; - int64_t dq, dr, dd, dg, q_span, sc, csc, ddt; - int64_t plus0, msc0, msc_i0, movl0; double lin_pen, a_pen; - - *plus = 0; *msc = *msc_i = INT32_MIN; *movl = INT32_MAX; *si = 0; *ei = a_n; - - for (k = 1, l = 0; k <= a_n; k++) { - if(k == a_n || a[k].strand != a[l].strand) { - t[k-1] = 0; ii[k-1] = 0; - // if(a_n && a[0].readID == 3125488) { - // fprintf(stderr, "[M::%s::] ii::[%ld,%ld)(%c), is_srt::%ld, chn_pen_gap::%f, chn_pen_skip::%f, bw_rate::%f\n", __func__, l, k, "+-"[a[l].strand], is_srt, chn_pen_gap, chn_pen_skip, bw_rate); - // } - if(is_srt) { - plus0 = 0; msc0 = msc_i0 = INT32_MIN; movl0 = INT32_MAX; ddt = 0; - - - p[l] = -1; f[l] = a[l].cnt&(0xffu); - if(f[l] >= msc0) {msc0 = f[l]; msc_i0 = l;}///difference - if(f[l] < plus0) plus0 = f[l]; - - - for (z = l + 1; z < k; z++) { - ///roughly same to comput_sc_ch(&a[z], &a[z-1]) - ai = &a[z]; aj = &a[z-1]; - dq = (int64_t)(ai->self_offset) - (int64_t)(aj->self_offset); - if(dq <= 0) break; - dr = (int64_t)(ai->offset) - (int64_t)(aj->offset); - if(dr <= 0) break; - dd = dr > dq? dr - dq : dq - dr;//gap - // if(a_n && a[0].readID == 3125488) { - // fprintf(stderr, "%ld,", dd); - // } - if((dd > 16) && (dd > cal_bw(&(a[z]), &(a[z-1]), bw_rate, xl, yl))) break; - dg = dr < dq? dr : dq;//len - q_span = ai->cnt&(0xffu); - sc = q_span < dg? q_span : dg; - sc = normal_w(sc, ((int32_t)(ai->cnt>>8))); - if (dd || (dg > q_span && dg > 0)) { - lin_pen = (chn_pen_gap*(double)dd); - a_pen = ((double)(sc))*((((double)dd)/((double)dg))/bw_rate); - ///for long gap - // if(lin_pen > a_pen) lin_pen = a_pen; - if(dd < 4) lin_pen = ((lin_pen > a_pen)?(a_pen):(lin_pen)); - else lin_pen = ((lin_pen < a_pen)?(a_pen):(lin_pen)); - lin_pen += (chn_pen_skip*(double)dg); - sc -= (int32_t)lin_pen; - } - - sc += f[z-1]; csc = a[z].cnt&(0xffu); if(sc < csc) break; - p[z] = z - 1; f[z] = sc; ddt += dd; - - if(f[z] >= msc0) {msc0 = f[z]; msc_i0 = z;}///difference - if(f[z] < plus0) plus0 = f[z]; - } - - // if(a_n && a[0].readID == 3125488) { - // fprintf(stderr, "\n"); - // fprintf(stderr, "[M::%s::] msc0::%ld, msc_i0::%ld, (%c)\n", __func__, msc0, msc_i0, "+-"[a[l].strand]); - // } - if((z >= k) && (msc_i0 == (k - 1))) { - if((k - l >= 2) && (ddt > 16) && (ddt > cal_bw(&(a[k-1]), &(a[l]), bw_rate, xl, yl))) msc_i0 = INT32_MIN; - if(msc_i0 == (k - 1)) { - if(msc0 >= (*msc)) { - movl0 = get_chainLen(a[msc_i0].self_offset, a[msc_i0].self_offset, xl, a[msc_i0].offset, a[msc_i0].offset, yl); - if(msc0 > (*msc) || movl0 < (*movl)) { - *msc = msc0; *msc_i = msc_i0; *movl = movl0; - } - } - if(plus0 < (*plus)) *plus = plus0; - if((*ei) > k) { - (*si) = k; - } else { - (*ei) = l; - } - } - } - } - l = k; is_srt = 1; - } else { - if((a[k].self_offset <= a[k-1].self_offset) || (a[k].offset <= a[k-1].offset)) is_srt = 0; - t[k-1] = 0; ii[k-1] = 0; - } - } -} - - -uint64_t lchain_qdp_mcopy_fast(Candidates_list *cl, int64_t a_idx, int64_t a_n, int64_t des_idx, - Chain_Data* dp, overlap_region_alloc* res, int64_t max_skip, int64_t max_iter, - int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, - uint32_t xid, int64_t xl, int64_t yl, int64_t quick_check, uint32_t apend_be, - int64_t gen_cigar, int64_t mcopy_num, double mcopy_rate, int64_t mcopy_khit_cutoff, - int64_t khit_n) -{ - if(a_n <= 0) return 0; - int64_t *p, *t, max_f, n_skip, st, max_j, end_j, sc, msc, msc_i, max_ii, ovl, movl, plus = 0, min_sc, ch_n, si, ei; - int32_t *f, max, tmp, *ii; int64_t i, k, j, cL = 0; k_mer_hit* a; k_mer_hit* des; k_mer_hit *swap; overlap_region *z; - resize_Chain_Data(dp, a_n, NULL); ch_n = 1; // int64_t bw; bw = ((xl < yl)?xl:yl); bw *= bw_rate; - t = dp->tmp; f = dp->score; p = dp->pre; ii = dp->occ; - - a = cl->list + a_idx; des = cl->list + des_idx; - // if(a_n && a[0].readID == 0) { - // fprintf(stderr, "---[M::%s::utg%.6dl::%c]\n", - // __func__, (int32_t)a[0].readID+1, "+-"[a[0].strand]); - // } - if(quick_check) { - quick_ck_lchain(a, a_n, xl, yl, chn_pen_gap, chn_pen_skip, bw_rate, p, t, f, ii, &plus, &msc, &msc_i, &movl, &si, &ei); - } else { - msc = msc_i = INT32_MIN; movl = INT32_MAX; plus = 0; si = 0; ei = a_n; - memset(t, 0, (a_n*sizeof((*t)))); - } - // if(a_n && a[0].readID == 4412344) { - // fprintf(stderr, "[M::%s::] si::%ld, ei::%ld, a_n::%ld\n", __func__, si, ei, a_n); - // } - for (i = st = si, max_ii = -1; i < ei; ++i) { - max_f = a[i].cnt&(0xffu); - n_skip = 0; max_j = end_j = -1; - if ((i-st) > max_iter) st = i-max_iter; - while (a[i].strand != a[st].strand) ++st; - - for (j = i - 1; j >= st; --j) { - sc = comput_sc_ch_ec(&a[i], &a[j], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); - if (sc == INT32_MIN) continue; - sc += f[j]; - if (sc > max_f) { - max_f = sc, max_j = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == (int32_t)i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - end_j = j; - - if ((max_ii<0) || (a[i].self_offset>a[max_ii].self_offset+max_dis) || (a[i].strand!=a[max_ii].strand)) { - max = INT32_MIN; max_ii = -1; - for (j=i-1; (j>=st) && (a[i].self_offset<=max_dis+a[j].self_offset)&&(a[i].strand==a[j].strand); --j) { - if (max < f[j]) { - max = f[j], max_ii = j; - } - } - } - - if ((max_ii >= 0) && (max_ii < end_j) && (a[i].strand == a[max_ii].strand)) {///just have a try with a[i]<->a[max_ii] - tmp = comput_sc_ch_ec(&a[i], &a[max_ii], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); - if (tmp != INT32_MIN && max_f < tmp + f[max_ii]) - max_f = tmp + f[max_ii], max_j = max_ii; - } - f[i] = max_f; p[i] = max_j; - if ((max_ii < 0) || ((a[i].self_offset<=max_dis+a[max_ii].self_offset)&&(a[i].strand==a[max_ii].strand)&&(f[max_ii]= msc) { - ovl = get_chainLen(a[i].self_offset, a[i].self_offset, xl, a[i].offset, a[i].offset, yl); - if(f[i] > msc || ovl < movl) { - msc = f[i]; msc_i = i; movl = ovl; - } - } - if(f[i] < plus) plus = f[i]; - ii[i] = 0;///for mcopy, not here - // if(a_n && a[0].readID == 4412344) { - // fprintf(stderr, "i::%ld[M::%s::%c] q::%u, t::%u, st::%ld, max_ii::%ld, f[i]::%d, p[i]::%ld, msc_i::%ld, msc::%ld, movl::%ld\n", - // i, __func__, "+-"[a[i].strand], - // a[i].self_offset, a[i].offset, st, max_ii, f[i], p[i], msc_i, msc, movl); - // } - } - - for (i = msc_i, cL = 0; i >= 0; i = p[i]) { ii[i] = 1; t[cL++] = i;}///label the best chain - - if(mcopy_num > 1) { - // if(a[0].readID == 4412344) { - // fprintf(stderr, "[M::%s::] msc::%ld, cL::%ld\n", __func__, msc, cL); - // } - if(cL >= mcopy_khit_cutoff) {///if there are too few k-mers, disable mcopy - msc -= plus; min_sc = msc*mcopy_rate/**0.2**/; ii[msc_i] = 0; - for (i = ch_n = 0; i < a_n; ++i) {///make all f[] positive - f[i] -= plus; if(i >= ch_n) t[i] = 0; - if((!(ii[i])) && (f[i] >= min_sc)) {///!(ii[i]): skip the best chain - t[ch_n] = ((uint64_t)f[i])<<32; t[ch_n] += (i<<1); ch_n++; - } - } - // if(a[0].readID == 4412344) { - // fprintf(stderr, "[M::%s::] msc::%ld, min_sc::%ld, cL::%ld, ch_n::%ld, mcopy_num::%ld\n", __func__, msc, min_sc, cL, ch_n, mcopy_num); - // } - if(ch_n > 1) { - int64_t n_v, n_v0, ni, n_u, n_u0 = res->length; - radix_sort_hc64i(t, t + ch_n); - for (k = ch_n-1, n_v = n_u = 0; k >= 0 && n_u < mcopy_num; --k) { - n_v0 = n_v; - for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { - ii[n_v++] = i; t[i] |= 1; i = p[i]; - } - if(n_v0 == n_v) continue; - sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); - // if(a[0].readID == 4412344) { - // fprintf(stderr, "+[M::%s::] sc::%ld, n_a::%ld\n", __func__, sc, n_v-n_v0); - // } - if(sc >= min_sc) { - kv_pushp_ol(overlap_region, (*res), &z); - push_ovlp_chain_qgen(z, xid, xl, yl, sc+plus, &(a[ii[n_v-1]]), &(a[ii[n_v0]])); - // if(a[0].readID == 4412344) { - // fprintf(stderr, "-[M::%s::] sc::%ld, n_a::%ld, q::[%u,%u), t::[%u,%u), %c\n", __func__, sc, n_v-n_v0, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, "+-"[z->y_pos_strand]); - // } - ///mcopy_khit_cutoff <= 1: disable the mcopy_khit_cutoff filtering, for the realignment - // if((mcopy_khit_cutoff <= 1) || ((z->x_pos_e+1-z->x_pos_s) <= (movl<<2))) { - if((!n_u) || (n_v - n_v0 > 1)) { - z->align_length = n_v-n_v0; z->x_id = n_v0; - n_u++; - } else {///non-best is tiny - res->length--; n_v = n_v0; - } - } else { - n_v = n_v0; - } - } - - // if(n_u > 1) ks_introsort_or_sss(n_u, res->list + n_u0); - // res->length = n_u0 + filter_non_ovlp_xchains(res->list + n_u0, n_u, &n_v); - n_u = res->length; - if(n_u > n_u0 + 1) { - kv_resize_cl(k_mer_hit, (*cl), (n_v+cl->length)); - a = cl->list + a_idx; des = cl->list + des_idx; swap = cl->list + cl->length; - for (k = n_u0, i = n_v0 = n_v = 0; k < n_u; k++) { - z = &(res->list[k]); - z->non_homopolymer_errors = des_idx + i; - n_v0 = z->x_id; ni = z->align_length; - for (j = 0; j < ni; j++, i++) { - ///k0 + (ni - j - 1) - swap[i] = a[ii[n_v0 + (ni- j - 1)]]; - swap[i].readID = k; - } - z->x_id = xid; - if(gen_cigar) gen_fake_cigar(&(z->f_cigar), z, apend_be, swap+i-ni, ni); - if(!khit_n) z->align_length = 0; - } - memcpy(des, swap, i*sizeof((*swap))); //assert(i == ch_n); - - // fprintf(stderr, "[M::%s::msc->%ld] msc_k_hits::%u, cL::%ld, min_sc::%ld, best_sc::%ld, n_u0_sc::%d, mcopy_rate::%f, # chains::%ld\n", - // __func__, msc, res->list[n_u0].align_length, cL, min_sc, msc+plus, res->list[n_u0].shared_seed, - // mcopy_rate, n_u-n_u0); - } else if(n_u == n_u0 + 1) { - z = &(res->list[n_u0]); k = n_u0; i = 0; - z->non_homopolymer_errors = des_idx + i; - n_v0 = z->x_id; ni = z->align_length; - for (j = 0; j < ni; j++, i++) { - ///k0 + (ni - j - 1) - des[i] = a[ii[n_v0 + (ni- j - 1)]]; - des[i].readID = k; - } - z->x_id = xid; - if(gen_cigar) gen_fake_cigar(&(z->f_cigar), z, apend_be, des+i-ni, ni); - if(!khit_n) z->align_length = 0; - } - return i; - } else { - msc += plus; i = msc_i; cL = 0; - while (i >= 0) {t[cL++] = i; i = p[i];} - } - } - } - - - - ///a[] has been sorted by self_offset - // i = msc_i; cL = 0; - // while (i >= 0) {t[cL++] = i; i = p[i];} - kv_pushp_ol(overlap_region, (*res), &z); - push_ovlp_chain_qgen(z, xid, xl, yl, msc, &(a[t[cL-1]]), &(a[t[0]])); - for (i = 0; i < cL; i++) {des[i] = a[t[cL-i-1]]; des[i].readID = res->length-1;} - z->non_homopolymer_errors = des_idx; - if(gen_cigar) gen_fake_cigar(&(z->f_cigar), z, apend_be, des, cL); - if(khit_n) z->align_length = cL; - return cL; -} - - -#define rev_khit(an, xl, yl) do { \ - (an).self_offset = (xl)-1-((an).self_offset+1-((an).cnt&((uint32_t)(0xffu)))); \ - (an).offset = (yl)-1-((an).offset+1-((an).cnt&((uint32_t)(0xffu))));\ - } while (0) - -///it is unpossibale that (left_fix == 0 && right_fix == 0) -uint64_t lchain_qdp_fix(k_mer_hit* a, int64_t a_n, Chain_Data* dp, int64_t max_skip, - int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, - double bw_rate, int64_t xl, int64_t yl, int64_t quick_check, - int64_t left_fix, int64_t right_fix) -{ - int64_t *p, *t, max_f, n_skip, st, max_j, end_j, sc, msc, msc_i, bw, max_ii, ovl, movl; - int32_t *f, max, tmp; int64_t i, j, ret, cL = 0, must_p = 1, is_reorder = 0; k_mer_hit z; - resize_Chain_Data(dp, a_n, NULL); - t = dp->tmp; f = dp->score; p = dp->pre; - bw = ((xl < yl)?xl:yl); bw *= bw_rate; - msc = msc_i = -1; movl = INT32_MAX; - - if(quick_check) { - ret = lchain_qcheck(a, a_n, dp, bw_rate); - if (ret > 0) { - a_n = ret; msc_i = a_n-1; msc = f[msc_i]; - goto skip_ldp; - } - } - - memset(t, 0, (a_n*sizeof((*t)))); - if((right_fix) && (!left_fix)) { - // fprintf(stderr, "\n[M::%s::] a_n::%ld\n", __func__, a_n); - // for (i = 0; i < a_n; ++i) { - // fprintf(stderr, "+[M::%s::] x::[%u, %u), y::[%u, %u)\n", __func__, - // a[i].self_offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].self_offset+1, - // a[i].offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].offset+1); - // } - n_skip = a_n>>1; - for (i=0; i max_iter) st = i-max_iter; - // if(a[0].self_offset == 171728) { - // fprintf(stderr, "i::%ld[M::%s::] x::[%u, %u), y::[%u, %u)\n", i, __func__, - // a[i].self_offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].self_offset+1, - // a[i].offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].offset+1); - // } - for (j = i - 1; j >= 0; --j) { - sc = comput_sc_ff(&a[i], &a[j], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); - // if(a[0].self_offset == 171728) { - // fprintf(stderr, "j::%ld[M::%s::sc->%ld] x::[%u, %u), y::[%u, %u)\n", j, __func__, sc, - // a[j].self_offset+1-(a[j].cnt&((uint32_t)(0xffu))), a[j].self_offset+1, - // a[j].offset+1-(a[j].cnt&((uint32_t)(0xffu))), a[j].offset+1); - // } - if (sc == INT32_MIN) continue; - sc += f[j]; - if (sc > max_f) { - max_f = sc, max_j = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == (int32_t)i) { - if ((++n_skip) > max_skip) { - if((max_j != -1) || (must_p == 0)) break; - } - } - if (p[j] >= 0) t[p[j]] = i; - ///put it here will allow at least one prefix no matter max_dis - ///this is special for gap filling, not for chaining - if (a[i].self_offset > (max_dis + a[j].self_offset)) { - if((max_j != -1)) break; - } - if (j < st) { - if((max_j != -1) || (must_p == 0)) break; - } - } - end_j = j; - - if (max_ii < 0 || ((int64_t)a[i].self_offset) - ((int64_t)a[max_ii].self_offset) > max_dis) { - max = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && ((((int64_t)a[i].self_offset)-((int64_t)a[j].self_offset))<=max_dis); --j) { - if (max < f[j]) { - max = f[j], max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - tmp = comput_sc_ff(&a[i], &a[max_ii], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); - if (tmp != INT32_MIN && max_f < tmp + f[max_ii]) - max_f = tmp + f[max_ii], max_j = max_ii; - } - if(max_j == -1) { - f[i] = 0; p[i] = max_j; - } else { - f[i] = max_f; p[i] = max_j; - } - - if ((max_ii < 0) || (((((int64_t)a[i].self_offset)-((int64_t)a[max_ii].self_offset))<=max_dis) && (f[max_ii]= msc) { - ovl = get_chainLen(a[i].self_offset, a[i].self_offset, xl, a[i].offset, a[i].offset, yl); - if(f[i] > msc || ovl < movl) { - msc = f[i]; msc_i = i; movl = ovl; - } - } - } - - skip_ldp: - if(right_fix && left_fix) msc_i = a_n-1; - ///a[] has been sorted by self_offset - i = msc_i; cL = 0; - while (i >= 0) { - t[cL++] = i; msc_i = i; i = p[i]; - } - // if((right_fix) && (!left_fix)) { - // fprintf(stderr, "[M::%s::] cL::%ld\n", __func__, cL); - // } - - if(is_reorder) { - n_skip = a_n>>1; - for (i=0; i[M::%s::] t[%ld]::%ld\n", __func__, i, t[i]); - } - // for (i = 0; i < a_n; ++i) { - // fprintf(stderr, ">[M::%s::] x::[%u, %u), y::[%u, %u)\n", __func__, - // a[i].self_offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].self_offset+1, - // a[i].offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].offset+1); - // } - } else { - n_skip = cL>>1; - for (i = 0; i < n_skip; i++) { - msc_i = t[i]; t[i] = t[cL-i-1]; t[cL-i-1] = msc_i; - } - } - // if(cL != a_n) { - // fprintf(stderr, "\n[M::%s::] a_n::%ld, left_fix::%ld, right_fix::%ld\n", __func__, a_n, left_fix, right_fix); - // for (i = 0; i < a_n; ++i) { - // fprintf(stderr, "+[M::%s::] x::[%u, %u), y::[%u, %u)\n", __func__, - // a[i].self_offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].self_offset+1, - // a[i].offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].offset+1); - // } - // for (i = 0; i < cL; i++) { - // fprintf(stderr, ">[M::%s::] t[%ld]::%ld\n", __func__, i, t[i]); - // } - // } - return cL; -} - - -uint64_t lchain_refine(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, - int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t long_gap) -{ - if(a_n <= 0) return 0; - int64_t *p, *t, max_f, n_skip, st, max_j, sc, msc, msc_i, dq, dr, dd; - int32_t *f; int64_t i, j, cL = 0; - resize_Chain_Data(dp, a_n, NULL); - t = dp->tmp; f = dp->score; p = dp->pre; msc = msc_i = -1; - - for (i = 1, f[0] = 0, p[0] = -1, msc_i = a_n - 1; i < a_n; i++) { - j = i-1; - dq = (int64_t)(a[i].self_offset) - (int64_t)(a[j].self_offset); - dr = (int64_t)(a[i].offset) - (int64_t)(a[j].offset); - dd = dr > dq? dr - dq : dq - dr;//gap - if(dd <= long_gap || dq > max_dis) { - p[i] = i - 1; f[i] = i; - } else { - break; - } - } - if(i >= a_n) goto ss_kip; - - - memset(t, 0, (a_n*sizeof((*t)))); - f[0] = 0; p[0] = -1; - - for (i = 1, st = 0; i < a_n; ++i) { - max_f = INT32_MIN; n_skip = 0; max_j = -1; - if ((i-st) > max_iter) st = i-max_iter; - ///i-1 - j = i - 1; - dq = (int64_t)(a[i].self_offset) - (int64_t)(a[j].self_offset); - dr = (int64_t)(a[i].offset) - (int64_t)(a[j].offset); - dd = dr > dq? dr - dq : dq - dr;//gap - if(dd <= long_gap) dd = 0; - sc = f[j] - dd; - if (sc > max_f) { - max_f = sc, max_j = j; - } - if (p[j] >= 0) t[p[j]] = i; - - ///[st, i-2] - for (--j; (j >= st) && (a[i].self_offset <= (max_dis + a[j].self_offset)); --j) { - dq = (int64_t)(a[i].self_offset) - (int64_t)(a[j].self_offset); - dr = (int64_t)(a[i].offset) - (int64_t)(a[j].offset); - dd = dr > dq? dr - dq : dq - dr;//gap - if(dd <= long_gap) dd = 0; - sc = f[j] - dd; - if (sc > max_f) { - max_f = sc, max_j = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == (int32_t)i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - - f[i] = max_f; p[i] = max_j; - } - - i = a_n-1; msc = f[i]; msc_i = i; - for (j = i-1; (j >= 0) && (a[i].self_offset <= (max_dis + a[j].self_offset)); --j) { - if(msc < f[j] && p[j] >= 0) {///hold at least two hits in th final chain - msc = f[j]; msc_i = j; - } - } - - ss_kip: - ///a[] has been sorted by self_offset - i = msc_i; - cL = 0; - while (i >= 0) { - t[cL++] = i; i = p[i]; - } - - n_skip = cL>>1; - for (i = 0; i < n_skip; i++) { - msc_i = t[i]; t[i] = t[cL-i-1]; t[cL-i-1] = msc_i; - } - if(des) { - for (i = 0; i < cL; i++) des[i] = a[t[i]]; - } - return cL; -} - - -uint64_t lchain_simple(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, - int64_t max_skip, int64_t max_iter) -{ - if(a_n <= 0) return 0; - int64_t *p, *t, max_f, n_skip, st, max_j, sc, msc, msc_i; - int32_t *f; int64_t i, j, cL = 0; - resize_Chain_Data(dp, a_n, NULL); - t = dp->tmp; f = dp->score; p = dp->pre; msc = msc_i = -1; - - for (i=1, f[0]=a[0].cnt, p[0]=-1, msc_i=a_n-1; i a[j].self_offset)&&(a[i].offset > a[j].offset)) { - p[i] = j; f[i] = f[j]+a[i].cnt; - } else { - break; - } - } - if(i >= a_n) goto ss_kip; - - memset(t, 0, (a_n*sizeof((*t)))); - f[0]=a[0].cnt; p[0]=-1; msc = f[0]; msc_i = 0; - - for (i = 1, st = 0; i < a_n; ++i) { - max_f = INT32_MIN; n_skip = 0; max_j = -1; - if ((i-st) > max_iter) st = i-max_iter; - ///[st, i-2] - for (j=i-1; j >= st; --j) { - if((a[i].self_offset > a[j].self_offset)&&(a[i].offset > a[j].offset)) { - sc = f[j]+a[i].cnt; - if (sc > max_f) { - max_f = sc, max_j = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == (int32_t)i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - } - f[i] = max_f; p[i] = max_j; - if(f[i] > msc) { - msc = f[i]; msc_i = i; - } - } - - ss_kip: - ///a[] has been sorted by self_offset - i = msc_i; - cL = 0; - while (i >= 0) { - t[cL++] = i; i = p[i]; - } - - n_skip = cL>>1; - for (i = 0; i < n_skip; i++) { - msc_i = t[i]; t[i] = t[cL-i-1]; t[cL-i-1] = msc_i; - } - if(des) { - for (i = 0; i < cL; i++) des[i] = a[t[i]]; - } - return cL; -} - -inline int64_t hit_long_gap(k_mer_hit *a, k_mer_hit *b, int64_t max_lgap, double small_bw_rate, int64_t min_small_bw) -{ - int64_t dq, dr, dd, dm; - dq = b->self_offset-a->self_offset; - dr = b->offset-a->offset; - dd = dq>=dr? ((dq)-(dr)): ((dr)-(dq)); - if(max_lgap>=0) { - if(dd <= max_lgap) return 1; - return 0; - } else { - dm = dq>=dr?dr:dq; - if((dd > (dm*small_bw_rate)) && (dd > min_small_bw)) return 0; - return 1; - } -} - -int64_t filter_bad_seed_dp(k_mer_hit *sk, k_mer_hit *ek, k_mer_hit* a, int64_t a_n, int64_t max_lgap, double small_bw_rate, int64_t min_small_bw) -{ - int64_t k = 0; k_mer_hit *z; double bw_r; int64_t bw, mmgap, occ = 0; - bw_r = small_bw_rate; bw = min_small_bw; mmgap = max_lgap; - if(sk) { - for (k = 0; k < a_n; k++) { - z = &(a[k]); - if(z->cnt < z->readID) continue; - mmgap = max_lgap; - if(z->cnt <= 1) mmgap = -1; - if((sk && (!hit_long_gap(sk, z, mmgap, bw_r, bw))) || - (ek && (!hit_long_gap(z, ek, mmgap, bw_r, bw)))) { - z->offset = z->self_offset = (uint32_t)-1; occ++; - } else { - break; - } - } - } - - if(ek && k < a_n) { - for (k = a_n-1; k >= 0; k--) { - z = &(a[k]); - if(z->cnt < z->readID) continue; - mmgap = max_lgap; - if(z->cnt <= 1) mmgap = -1; - if((sk && (!hit_long_gap(sk, z, mmgap, bw_r, bw))) || - (ek && (!hit_long_gap(z, ek, mmgap, bw_r, bw)))) { - z->offset = z->self_offset = (uint32_t)-1; occ++; - } else { - break; - } - } - } - - return occ; -} - -uint64_t lchain_dp_trace(k_mer_hit* a, int64_t a_n, int64_t max_lgap, double sgap_rate, int64_t sgap) -{ - // fprintf(stderr, "[M::%s::] a_n::%ld\n", __func__, a_n); - if(a_n <= 0) return 0; - int64_t i, st, occ = 0; - - for (i = 1, st = 0; i <= a_n; ++i) { - // fprintf(stderr, "[M::%s::i->%ld] q::%u, t::%u, cnt::%u, readID::%u\n", __func__, - // i-1, a[i-1].self_offset, a[i-1].offset, a[i-1].cnt, a[i-1].readID); - if((i == a_n) || (is_alnw(a[i]))) {///[st, i) - if(i > st) { - occ += filter_bad_seed_dp((st>0)?&(a[st-1]):NULL, (i +#include +#include +#include +#include "Hash_Table.h" +#include "ksort.h" +#include "kalloc.h" +pthread_mutex_t output_mutex; + +#define overlap_region_key(a) ((a).y_id) +KRADIX_SORT_INIT(overlap_region_sort, overlap_region, overlap_region_key, member_size(overlap_region, y_id)) + +#define generic_key(x) (x) +KRADIX_SORT_INIT(hc64i, int64_t, generic_key, 8) + +#define oreg_sss_lt(a, b) ((a).shared_seed > (b).shared_seed) // in the decending order +KSORT_INIT(or_sss, overlap_region, oreg_sss_lt) + +#define normal_w(x, y) ((x)>=(y)?(x)/(y):1) + +void overlap_region_sort_y_id(overlap_region *a, long long n) +{ + radix_sort_overlap_region_sort(a, a + n); +} + +void init_overlap_region_alloc(overlap_region_alloc* list) +{ + list->size = 1000; + list->length = 0; + ///list->list = (overlap_region*)malloc(sizeof(overlap_region)*list->size); + list->list = (overlap_region*)calloc(list->size, sizeof(overlap_region)); + uint64_t i; + for (i = 0; i < list->size; i++) { + init_fake_cigar(&(list->list[i].f_cigar)); + init_window_list_alloc(&(list->list[i].w_list)); + init_window_list_alloc(&(list->list[i].boundary_cigars)); + } +} + +void clear_overlap_region_alloc(overlap_region_alloc* list) +{ + list->length = 0; + list->mapped_overlaps_length = 0; + uint64_t i = 0; + for (i = 0; i < list->size; i++) { + clear_fake_cigar(&(list->list[i].f_cigar)); + clear_window_list_alloc(&(list->list[i].w_list)); + clear_window_list_alloc(&(list->list[i].boundary_cigars)); + } +} + +void destory_overlap_region_alloc(overlap_region_alloc* list) +{ + uint64_t i = 0; + for (i = 0; i < list->size; i++) { + destory_fake_cigar(&(list->list[i].f_cigar)); + destory_window_list_alloc(&(list->list[i].w_list)); + destory_window_list_alloc(&(list->list[i].boundary_cigars)); + } + free(list->list); +} + +int get_fake_gap_pos(Fake_Cigar* x, int index) +{ + return (x->buffer[index]>>32); +} + +int get_fake_gap_shift(Fake_Cigar* x, int index) +{ + uint32_t tmp = ((uint32_t)(x->buffer[index])); + int result; + if(tmp & ((uint32_t)1)) + { + tmp = tmp >> 1; + result = tmp; + result = result * -1; + } + else + { + tmp = tmp >> 1; + result = tmp; + } + + return result; +} + +void gen_fake_cigar(Fake_Cigar* z, overlap_region *o, int64_t apend_be, k_mer_hit* hit, int64_t n_hit) +{ + int64_t k, dq, dr, dd, pdd; z->length = 0; + if(apend_be == 1) add_fake_cigar(z, o->x_pos_s, 0, NULL); + for (k = 0, pdd = INT32_MAX; k < n_hit; k++) { + dq = hit[k].self_offset - o->x_pos_s; + dr = hit[k].offset - o->y_pos_s; + dd = dr - dq; + // if(print) { + // fprintf(stderr, "[M::k->%lu] x::%u, y::%u, cnt::%u, dd::%ld, pdd::%ld, z->n::%u\n", + // k, hit[k].self_offset, hit[k].offset, hit[k].cnt&(0xffu), dd, pdd, z->length); + // } + if(dd != pdd) { + pdd = dd; + add_fake_cigar(z, hit[k].self_offset, pdd, NULL); + } + } + + if((apend_be == 1) && (get_fake_gap_pos(z, z->length-1)!=((int64_t)o->x_pos_e))) { + add_fake_cigar(z, o->x_pos_e, get_fake_gap_shift(z, z->length-1), NULL); + } +} + +void debug_cigar(Fake_Cigar* z, overlap_region *o, int64_t apend_be, k_mer_hit* hit, uint64_t n_hit) +{ + gen_fake_cigar(z, o, apend_be, hit, n_hit); + if(!((z->length==o->f_cigar.length) && + (!memcmp(z->buffer, o->f_cigar.buffer, sizeof((*(o->f_cigar.buffer)))*o->f_cigar.length)))) { + uint64_t k; + fprintf(stderr, "\n[M::%s] z->n::%u, o->n::%u, rev::%u\n", __func__, z->length, o->f_cigar.length, o->y_pos_strand); + for (k = 0; k < z->length; k++) { + fprintf(stderr, "[z::k->%lu] pos::%d, off::%d\n", k, + get_fake_gap_pos(z, k), get_fake_gap_shift(z, k)); + } + for (k = 0; k < o->f_cigar.length; k++) { + fprintf(stderr, "[o::k->%lu] pos::%d, off::%d\n", k, + get_fake_gap_pos(&(o->f_cigar), k), get_fake_gap_shift(&(o->f_cigar), k)); + } + // gen_fake_cigar(z, o, apend_be, hit, n_hit, 1); + // for (k = 0; k < o->f_cigar.length; k++) { + // fprintf(stderr, "[M::k->%lu] x::%u, y::%u, cnt::%u\n", + // k, hit[k].self_offset, hit[k].offset, hit[k].cnt&(0xffu)); + // } + + } +} + +///for backup +int ovlp_chain_gen(overlap_region_alloc* ol, overlap_region* t, int64_t xl, int64_t yl, int64_t apend_be, k_mer_hit* hit, int64_t n_hit) +{ + if (ol->length + 1 > ol->size) { + uint64_t sl = ol->size; + ol->size = ol->length + 1; + kroundup64(ol->size); + REALLOC(ol->list, ol->size); + /// need to set new space to be 0 + memset(ol->list + sl, 0, sizeof(overlap_region)*(ol->size - sl)); + } + + if ((ol->length!=0) && (ol->list[ol->length-1].y_id==t->y_id)) { + if((ol->list[ol->length-1].shared_seed > t->shared_seed) || + ((ol->list[ol->length-1].shared_seed == t->shared_seed) && + (ol->list[ol->length-1].overlapLen <= t->overlapLen))) { + return 0; + } else { + ol->length--; + } + } + + int64_t xr, yr; + if(t->x_pos_s <= t->y_pos_s) { + t->y_pos_s -= t->x_pos_s; t->x_pos_s = 0; + } else { + t->x_pos_s -= t->y_pos_s; t->y_pos_s = 0; + } + + xr = xl-t->x_pos_e-1; yr = yl-t->y_pos_e-1; + if(xr <= yr) { + t->x_pos_e = xl-1; t->y_pos_e += xr; + } else { + t->y_pos_e = yl-1; t->x_pos_e += yr; + } + + overlap_region *o = &(ol->list[ol->length++]); + o->shared_seed = t->shared_seed; + o->align_length = 0; + o->is_match = 0; + o->non_homopolymer_errors = 0; + o->strong = 0; + o->x_id = t->x_id; + o->y_id = t->y_id; + o->x_pos_strand = 0;///always 0 + o->y_pos_strand = t->x_pos_strand; + + if (t->x_pos_strand == 1) { + o->x_pos_e = xl-t->x_pos_s-1; o->x_pos_s = xl-t->x_pos_e-1; + o->y_pos_e = yl-t->y_pos_s-1; o->y_pos_s = yl-t->y_pos_e-1; + } else { + o->x_pos_e = t->x_pos_e; o->x_pos_s = t->x_pos_s; + o->y_pos_e = t->y_pos_e; o->y_pos_s = t->y_pos_s; + } + ///debug + // debug_cigar(&(t->f_cigar), o, apend_be, hit, n_hit); + + return 1; +} + +int ovlp_chain_qgen(overlap_region_alloc* ol, overlap_region* t, int64_t xl, int64_t yl, int64_t apend_be, k_mer_hit* hit, int64_t n_hit) +{ + if (ol->length + 1 > ol->size) { + uint64_t sl = ol->size; + ol->size = ol->length + 1; + kroundup64(ol->size); + REALLOC(ol->list, ol->size); + /// need to set new space to be 0 + memset(ol->list + sl, 0, sizeof(overlap_region)*(ol->size - sl)); + } + + if ((ol->length!=0) && (ol->list[ol->length-1].y_id==t->y_id)) { + if((ol->list[ol->length-1].shared_seed > t->shared_seed) || + ((ol->list[ol->length-1].shared_seed == t->shared_seed) && + (ol->list[ol->length-1].overlapLen <= t->overlapLen))) { + return 0; + } else { + ol->length--; + } + } + + int64_t xr, yr; + if(t->x_pos_s <= t->y_pos_s) { + t->y_pos_s -= t->x_pos_s; t->x_pos_s = 0; + } else { + t->x_pos_s -= t->y_pos_s; t->y_pos_s = 0; + } + + xr = xl-t->x_pos_e-1; yr = yl-t->y_pos_e-1; + if(xr <= yr) { + t->x_pos_e = xl-1; t->y_pos_e += xr; + } else { + t->y_pos_e = yl-1; t->x_pos_e += yr; + } + + overlap_region *o = &(ol->list[ol->length++]); + o->shared_seed = t->shared_seed; + o->align_length = 0; + o->is_match = 0; + o->non_homopolymer_errors = 0; + o->strong = 0; + o->x_id = t->x_id; + o->y_id = t->y_id; + o->x_pos_strand = 0;///always 0 + o->y_pos_strand = t->x_pos_strand; + + o->x_pos_e = t->x_pos_e; o->x_pos_s = t->x_pos_s; + o->y_pos_e = t->y_pos_e; o->y_pos_s = t->y_pos_s; + ///debug + // debug_cigar(&(t->f_cigar), o, apend_be, hit, n_hit); + + return 1; +} + +int ovlp_chain_gen_fcigar(overlap_region_alloc* ol, overlap_region* t, int64_t xl, int64_t yl, int64_t apend_be, k_mer_hit* hit, int64_t n_hit) +{ + if (ol->length + 1 > ol->size) { + uint64_t sl = ol->size; + ol->size = ol->length + 1; + kroundup64(ol->size); + REALLOC(ol->list, ol->size); + /// need to set new space to be 0 + memset(ol->list + sl, 0, sizeof(overlap_region)*(ol->size - sl)); + } + + if ((ol->length!=0) && (ol->list[ol->length-1].y_id==t->y_id)) { + if((ol->list[ol->length-1].shared_seed > t->shared_seed) || + ((ol->list[ol->length-1].shared_seed == t->shared_seed) && + (ol->list[ol->length-1].overlapLen <= t->overlapLen))) { + return 0; + } else { + ol->length--; + } + } + + int64_t xr, yr, dd, pdd, dq, dr, id, i, fn; + if(t->x_pos_s <= t->y_pos_s) { + t->y_pos_s -= t->x_pos_s; t->x_pos_s = 0; + } else { + t->x_pos_s -= t->y_pos_s; t->y_pos_s = 0; + } + + xr = xl-t->x_pos_e-1; yr = yl-t->y_pos_e-1; + if(xr <= yr) { + t->x_pos_e = xl-1; t->y_pos_e += xr; + } else { + t->y_pos_e = yl-1; t->x_pos_e += yr; + } + + overlap_region *o = &(ol->list[ol->length++]); + o->shared_seed = t->shared_seed; + o->align_length = 0; + o->is_match = 0; + o->non_homopolymer_errors = 0; + o->strong = 0; + o->x_id = t->x_id; + o->y_id = t->y_id; + o->x_pos_strand = 0;///always 0 + o->y_pos_strand = t->x_pos_strand; + + resize_fake_cigar(&(o->f_cigar), (t->f_cigar.length + 2), NULL); + if(apend_be == 1) { + add_fake_cigar(&(o->f_cigar), ((t->x_pos_strand)?(xl-t->x_pos_e-1):(t->x_pos_s)), 0, NULL); + } + + if (t->x_pos_strand == 1) { + o->x_pos_e = xl-t->x_pos_s-1; o->x_pos_s = xl-t->x_pos_e-1; + o->y_pos_e = yl-t->y_pos_s-1; o->y_pos_s = yl-t->y_pos_e-1; + + pdd = INT32_MAX; fn = t->f_cigar.length; + for (i = 0; i < fn; i++) { + dd = get_fake_gap_shift(&(t->f_cigar), i); + if(dd != pdd) { + pdd = dd; + add_fake_cigar(&(o->f_cigar), xl-get_fake_gap_pos(&(t->f_cigar), i)-1, pdd, NULL); + } + } + } else { + o->x_pos_e = t->x_pos_e; o->x_pos_s = t->x_pos_s; + o->y_pos_e = t->y_pos_e; o->y_pos_s = t->y_pos_s; + + dq = t->x_pos_e - t->x_pos_s; + dr = t->y_pos_e - t->y_pos_s; + id = dr - dq;///indel size from left + + pdd = INT32_MAX; fn = t->f_cigar.length; + for (i = fn-1; i >= 0; i--) { + dd = get_fake_gap_shift(&(t->f_cigar), i); + if(dd != pdd) { + pdd = dd; + add_fake_cigar(&(o->f_cigar), get_fake_gap_pos(&(t->f_cigar), i), id - pdd, NULL); + } + } + } + + if((apend_be == 1) && (get_fake_gap_pos(&(o->f_cigar), o->f_cigar.length-1) != ((int64_t)o->x_pos_e))) { + add_fake_cigar(&(o->f_cigar), o->x_pos_e, get_fake_gap_shift(&(o->f_cigar), o->f_cigar.length-1), NULL); + } + + ///debug + debug_cigar(&(t->f_cigar), o, apend_be, hit, n_hit); + + return 1; +} + +int append_inexact_overlap_region_alloc(overlap_region_alloc* list, overlap_region* tmp, + long long xLen, long long yLen, int add_beg_end, void *km) +{ + + if (list->length + 1 > list->size) + { + uint64_t sl = list->size; + list->size = list->length + 1; + kroundup64(list->size); + if(!km) { + REALLOC(list->list, list->size); + } else { + KREALLOC(km, list->list, list->size); + } + /// need to set new space to be 0 + memset(list->list + sl, 0, sizeof(overlap_region)*(list->size - sl)); + } + + if (list->length!=0 && list->list[list->length - 1].y_id==tmp->y_id) + { + ///if(list->list[list->length - 1].shared_seed >= tmp->shared_seed) + if((list->list[list->length - 1].shared_seed > tmp->shared_seed) + || + ((list->list[list->length - 1].shared_seed == tmp->shared_seed) && + (list->list[list->length - 1].overlapLen <= tmp->overlapLen))) + { + return 0; + } + else + { + list->length--; + } + } + + if(tmp->x_pos_s <= tmp->y_pos_s) + { + tmp->y_pos_s = tmp->y_pos_s - tmp->x_pos_s; + tmp->x_pos_s = 0; + } + else + { + tmp->x_pos_s = tmp->x_pos_s - tmp->y_pos_s; + tmp->y_pos_s = 0; + } + + + long long x_right_length = xLen - tmp->x_pos_e - 1; + long long y_right_length = yLen - tmp->y_pos_e - 1; + + if(x_right_length <= y_right_length) + { + tmp->x_pos_e = xLen - 1; + tmp->y_pos_e = tmp->y_pos_e + x_right_length; + } + else + { + tmp->x_pos_e = tmp->x_pos_e + y_right_length; + tmp->y_pos_e = yLen - 1; + } + + if (tmp->x_pos_strand == 1) + { + list->list[list->length].x_id = tmp->x_id; + list->list[list->length].x_pos_e = xLen - tmp->x_pos_s - 1; + list->list[list->length].x_pos_s = xLen - tmp->x_pos_e - 1; + list->list[list->length].x_pos_strand = 0; + + list->list[list->length].y_id = tmp->y_id; + list->list[list->length].y_pos_e = yLen - tmp->y_pos_s - 1; + list->list[list->length].y_pos_s = yLen - tmp->y_pos_e - 1; + list->list[list->length].y_pos_strand = 1; + + resize_fake_cigar(&(list->list[list->length].f_cigar), (tmp->f_cigar.length + 2), km); + if(add_beg_end == 1) + { + add_fake_cigar(&(list->list[list->length].f_cigar), list->list[list->length].x_pos_s, 0, km); + } + + long long distance_gap; + /****************************may have bugs********************************/ + ///long long pre_distance_gap = 0; + long long pre_distance_gap = 0xfffffffffffffff; + /****************************may have bugs********************************/ + long long i = 0; + for (i = 0; i < (long long)tmp->f_cigar.length; i++) + { + distance_gap = get_fake_gap_shift(&(tmp->f_cigar), i); + if(distance_gap != pre_distance_gap) + { + pre_distance_gap = distance_gap; + add_fake_cigar(&(list->list[list->length].f_cigar), xLen - get_fake_gap_pos(&(tmp->f_cigar), i) - 1, + pre_distance_gap, km); + } + } + + if(add_beg_end == 1 && get_fake_gap_pos(&(list->list[list->length].f_cigar), + list->list[list->length].f_cigar.length - 1) != (long long)list->list[list->length].x_pos_e) + { + add_fake_cigar(&(list->list[list->length].f_cigar), + list->list[list->length].x_pos_e, + get_fake_gap_shift(&(list->list[list->length].f_cigar), + list->list[list->length].f_cigar.length - 1), km); + } + } + else + { + list->list[list->length].x_id = tmp->x_id; + list->list[list->length].x_pos_e = tmp->x_pos_e; + list->list[list->length].x_pos_s = tmp->x_pos_s; + list->list[list->length].x_pos_strand = tmp->x_pos_strand; + + list->list[list->length].y_id = tmp->y_id; + list->list[list->length].y_pos_e = tmp->y_pos_e; + list->list[list->length].y_pos_s = tmp->y_pos_s; + list->list[list->length].y_pos_strand = tmp->y_pos_strand; + + + + resize_fake_cigar(&(list->list[list->length].f_cigar), (tmp->f_cigar.length + 2), km); + if(add_beg_end == 1) + { + add_fake_cigar(&(list->list[list->length].f_cigar), list->list[list->length].x_pos_s, 0, km); + } + + long long distance_self_pos = tmp->x_pos_e - tmp->x_pos_s; + long long distance_pos = tmp->y_pos_e - tmp->y_pos_s; + long long init_distance_gap = distance_pos - distance_self_pos; + /****************************may have bugs********************************/ + ///long long pre_distance_gap = init_distance_gap; + long long pre_distance_gap = 0xfffffffffffffff; + /****************************may have bugs********************************/ + long long distance_gap; + long long i = 0; + for (i = tmp->f_cigar.length - 1; i >= 0; i--) + { + distance_gap = get_fake_gap_shift(&(tmp->f_cigar), i); + if(distance_gap != pre_distance_gap) + { + pre_distance_gap = distance_gap; + + add_fake_cigar(&(list->list[list->length].f_cigar), + get_fake_gap_pos(&(tmp->f_cigar), i), init_distance_gap - pre_distance_gap, km); + } + } + + if(add_beg_end == 1 && get_fake_gap_pos(&(list->list[list->length].f_cigar), + list->list[list->length].f_cigar.length - 1) != (long long)list->list[list->length].x_pos_e) + { + add_fake_cigar(&(list->list[list->length].f_cigar), + list->list[list->length].x_pos_e, + get_fake_gap_shift(&(list->list[list->length].f_cigar), + list->list[list->length].f_cigar.length - 1), km); + } + } + + list->list[list->length].shared_seed = tmp->shared_seed; + list->list[list->length].align_length = 0; + list->list[list->length].is_match = 0; + list->list[list->length].non_homopolymer_errors = 0; + list->list[list->length].strong = 0; + + list->length++; + + return 1; +} + + +int append_utg_inexact_overlap_region_alloc(overlap_region_alloc* list, overlap_region* tmp, + ma_utg_v *ua, int add_beg_end, void *km) +{ + if (list->length + 1 > list->size) + { + uint64_t sl = list->size; + list->size = list->length + 1; + kroundup64(list->size); + if(!km) { + REALLOC(list->list, list->size); + } else { + KREALLOC(km, list->list, list->size); + } + /// need to set new space to be 0 + memset(list->list + sl, 0, sizeof(overlap_region)*(list->size - sl)); + } + + if (list->length!=0 && list->list[list->length - 1].y_id==tmp->y_id) + { + ///if(list->list[list->length - 1].shared_seed >= tmp->shared_seed) + if((list->list[list->length - 1].shared_seed > tmp->shared_seed) + || + ((list->list[list->length - 1].shared_seed == tmp->shared_seed) && + (list->list[list->length - 1].overlapLen <= tmp->overlapLen))) + { + return 0; + } + else + { + list->length--; + } + } + + if(tmp->x_pos_s <= tmp->y_pos_s) + { + tmp->y_pos_s = tmp->y_pos_s - tmp->x_pos_s; + tmp->x_pos_s = 0; + } + else + { + tmp->x_pos_s = tmp->x_pos_s - tmp->y_pos_s; + tmp->y_pos_s = 0; + } + + + long long x_right_length = ua->a[tmp->x_id].len - tmp->x_pos_e - 1; + long long y_right_length = ua->a[tmp->y_id].len - tmp->y_pos_e - 1; + + if(x_right_length <= y_right_length) + { + tmp->x_pos_e = ua->a[tmp->x_id].len - 1; + tmp->y_pos_e = tmp->y_pos_e + x_right_length; + } + else + { + tmp->x_pos_e = tmp->x_pos_e + y_right_length; + tmp->y_pos_e = ua->a[tmp->y_id].len - 1; + } + + if (tmp->x_pos_strand == 1) + { + list->list[list->length].x_id = tmp->x_id; + list->list[list->length].x_pos_e = ua->a[tmp->x_id].len - tmp->x_pos_s - 1; + list->list[list->length].x_pos_s = ua->a[tmp->x_id].len - tmp->x_pos_e - 1; + list->list[list->length].x_pos_strand = 0; + + list->list[list->length].y_id = tmp->y_id; + list->list[list->length].y_pos_e = ua->a[tmp->y_id].len - tmp->y_pos_s - 1; + list->list[list->length].y_pos_s = ua->a[tmp->y_id].len - tmp->y_pos_e - 1; + list->list[list->length].y_pos_strand = 1; + + resize_fake_cigar(&(list->list[list->length].f_cigar), (tmp->f_cigar.length + 2), km); + if(add_beg_end == 1) + { + add_fake_cigar(&(list->list[list->length].f_cigar), list->list[list->length].x_pos_s, 0, km); + } + + long long distance_gap; + /****************************may have bugs********************************/ + ///long long pre_distance_gap = 0; + long long pre_distance_gap = 0xfffffffffffffff; + /****************************may have bugs********************************/ + long long i = 0; + for (i = 0; i < (long long)tmp->f_cigar.length; i++) + { + distance_gap = get_fake_gap_shift(&(tmp->f_cigar), i); + if(distance_gap != pre_distance_gap) + { + pre_distance_gap = distance_gap; + add_fake_cigar(&(list->list[list->length].f_cigar), + ua->a[tmp->x_id].len - get_fake_gap_pos(&(tmp->f_cigar), i) - 1, + pre_distance_gap, km); + } + } + + if(add_beg_end == 1 && get_fake_gap_pos(&(list->list[list->length].f_cigar), + list->list[list->length].f_cigar.length - 1) != (long long)list->list[list->length].x_pos_e) + { + add_fake_cigar(&(list->list[list->length].f_cigar), + list->list[list->length].x_pos_e, + get_fake_gap_shift(&(list->list[list->length].f_cigar), + list->list[list->length].f_cigar.length - 1), km); + } + } + else + { + list->list[list->length].x_id = tmp->x_id; + list->list[list->length].x_pos_e = tmp->x_pos_e; + list->list[list->length].x_pos_s = tmp->x_pos_s; + list->list[list->length].x_pos_strand = tmp->x_pos_strand; + + list->list[list->length].y_id = tmp->y_id; + list->list[list->length].y_pos_e = tmp->y_pos_e; + list->list[list->length].y_pos_s = tmp->y_pos_s; + list->list[list->length].y_pos_strand = tmp->y_pos_strand; + + + + resize_fake_cigar(&(list->list[list->length].f_cigar), (tmp->f_cigar.length + 2), km); + if(add_beg_end == 1) + { + add_fake_cigar(&(list->list[list->length].f_cigar), list->list[list->length].x_pos_s, 0, km); + } + + long long distance_self_pos = tmp->x_pos_e - tmp->x_pos_s; + long long distance_pos = tmp->y_pos_e - tmp->y_pos_s; + long long init_distance_gap = distance_pos - distance_self_pos; + /****************************may have bugs********************************/ + ///long long pre_distance_gap = init_distance_gap; + long long pre_distance_gap = 0xfffffffffffffff; + /****************************may have bugs********************************/ + long long distance_gap; + long long i = 0; + for (i = tmp->f_cigar.length - 1; i >= 0; i--) + { + distance_gap = get_fake_gap_shift(&(tmp->f_cigar), i); + if(distance_gap != pre_distance_gap) + { + pre_distance_gap = distance_gap; + + add_fake_cigar(&(list->list[list->length].f_cigar), + get_fake_gap_pos(&(tmp->f_cigar), i), init_distance_gap - pre_distance_gap, km); + } + } + + if(add_beg_end == 1 && get_fake_gap_pos(&(list->list[list->length].f_cigar), + list->list[list->length].f_cigar.length - 1) != (long long)list->list[list->length].x_pos_e) + { + add_fake_cigar(&(list->list[list->length].f_cigar), + list->list[list->length].x_pos_e, + get_fake_gap_shift(&(list->list[list->length].f_cigar), + list->list[list->length].f_cigar.length - 1), km); + } + } + + list->list[list->length].shared_seed = tmp->shared_seed; + list->list[list->length].align_length = 0; + list->list[list->length].is_match = 0; + list->list[list->length].non_homopolymer_errors = 0; + list->list[list->length].strong = 0; + + list->length++; + + return 1; +} + +void append_overlap_region_alloc_debug(overlap_region_alloc* list, overlap_region* tmp) +{ + + if (list->length + 1 > list->size) + { + list->size = list->size * 2; + list->list = (overlap_region*)realloc(list->list, sizeof(overlap_region)*list->size); + } + + + list->list[list->length].x_id = tmp->x_id; + list->list[list->length].x_pos_e = tmp->x_pos_e; + list->list[list->length].x_pos_s = tmp->x_pos_s; + list->list[list->length].x_pos_strand = tmp->x_pos_strand; + + list->list[list->length].y_id = tmp->y_id; + list->list[list->length].y_pos_e = tmp->y_pos_e; + list->list[list->length].y_pos_s = tmp->y_pos_s; + list->list[list->length].y_pos_strand = tmp->y_pos_strand; + + list->list[list->length].shared_seed = tmp->shared_seed; + + list->length++; +} + +void debug_chain(k_mer_hit* a, long long a_n, Chain_Data* dp) +{ + long long i, j, current_j; + long long selfLen, indels; + long long distance_self_pos, distance_pos, distance_gap; + for (i = 0; i < a_n; ++i) + { + selfLen = indels = 0; + j = i; + while (j >= 0) + { + current_j = j; + + j = dp->pre[j]; + + if(j != -1) + { + distance_self_pos = a[current_j].self_offset - a[j].self_offset; + distance_pos = a[current_j].offset - a[j].offset; + distance_gap = distance_pos > distance_self_pos? distance_pos - distance_self_pos : distance_self_pos - distance_pos; + + indels += distance_gap; + selfLen += distance_self_pos; + } + } + + if(indels != dp->indels[i]) + { + fprintf(stderr, "indels: %lld, dp->indels[i]: %ld\n", indels, (long)dp->indels[i]); + } + + if(selfLen != dp->self_length[i]) + { + fprintf(stderr, "selfLen: %lld, dp->self_length[i]: %ld\n", selfLen, (long)dp->self_length[i]); + } + + } +} + +void print_chain(k_mer_hit* a, long long a_n, Chain_Data* dp, long long topN) +{ + fprintf(stderr, "topN: %lld\n", topN); + long long max_score = -1, max_i = -1, max_n = 0;; + long long ss, i, j, current_j; + kvec_t(long long) si; kv_init(si); + for (ss = 0; ss < topN && ss < a_n; ss++){ + for (i = 0, max_i = -1, max_score = -1; i < a_n; ++i) { + for (j = 0; j < (long long)si.n; j++){ + if(i == si.a[j]) break; + } + if(j < (long long)si.n) continue; + if(dp->score[i] > max_score) max_score = dp->score[i], max_i = i; + } + if(max_i < 0) continue; + j = max_i; max_n = 0; + while (j >= 0) + { + current_j = j; + if(current_j == -1) continue; + j = dp->pre[j]; + max_n++; + } + + fprintf(stderr, "\nmax_i: %lld, max_score: %lld, max_n: %lld\n", max_i, max_score, max_n); + + j = max_i; + while (j >= 0) + { + current_j = j; + if(current_j == -1) continue; + + kv_push(long long, si, current_j); + j = dp->pre[j]; + fprintf(stderr, "self_offset: %u, offset: %u, cnt: %u, score: %d\n", + a[current_j].self_offset, a[current_j].offset, a[current_j].cnt, dp->score[current_j]); + } + } + kv_destroy(si); +} + + +long long get_chainLen(long long x_beg, long long x_end, long long xLen, + long long y_beg, long long y_end, long long yLen) +{ + if(x_beg <= y_beg) + { + y_beg = y_beg - x_beg; + x_beg = 0; + } + else + { + x_beg = x_beg - y_beg; + y_beg = 0; + } + + long long x_right_length = xLen - x_end - 1; + long long y_right_length = yLen - y_end - 1; + + + if(x_right_length <= y_right_length) + { + x_end = xLen - 1; + y_end = y_end + x_right_length; + } + else + { + x_end = x_end + y_right_length; + y_end = yLen - 1; + } + + return x_end - x_beg + 1; +} + + +void debug_chain_single_site(k_mer_hit* a, long long a_n, Chain_Data* dp, int x_readLen, int y_readLen, int s_index) +{ + long long j, current_j = s_index; + long long selfLen = 0, indels = 0; + long long distance_self_pos, distance_pos, distance_gap; + + j = s_index; + while (j >= 0) + { + current_j = j; + + j = dp->pre[j]; + + if(j != -1) + { + distance_self_pos = a[current_j].self_offset - a[j].self_offset; + distance_pos = a[current_j].offset - a[j].offset; + distance_gap = distance_pos > distance_self_pos? distance_pos - distance_self_pos : distance_self_pos - distance_pos; + + indels += distance_gap; + selfLen += distance_self_pos; + } + fprintf(stderr, "j: %lld, score: %lld, occ: %d, pre_j: %lld\n", + current_j, (long long)dp->score[current_j], dp->occ[current_j], j); + } + + fprintf(stderr, "s_self_offset: %u, s_offset: %u, e_self_offset: %u, e_offset: %u, ovlp length: %lld, x_readLen: %d, y_readLen: %d\n", + a[s_index].self_offset, a[s_index].offset, a[current_j].self_offset, a[current_j].offset, + get_chainLen(a[s_index].self_offset, a[current_j].self_offset, x_readLen, + a[s_index].offset, a[current_j].offset, y_readLen), x_readLen, y_readLen); + + if(indels != dp->indels[s_index]) + { + fprintf(stderr, "indels: %lld, dp->indels[i]: %ld\n", indels, (long)dp->indels[s_index]); + } + + if(selfLen != dp->self_length[s_index]) + { + fprintf(stderr, "selfLen: %lld, dp->self_length[i]: %ld\n", selfLen, (long)dp->self_length[s_index]); + } + fprintf(stderr,"\n"); +} + +int32_t ha_chain_check(k_mer_hit *a, int32_t n_a, Chain_Data *dp, int32_t min_sc, double bw_thres) +{ + int32_t i, tot_indel = 0, tot_len = 0; + double bw_pen; + if (n_a == 0) return -1; + for (i = 1; i < n_a; ++i) + if (a[i-1].self_offset >= a[i].self_offset) + break; + if (i < n_a) return -1; + bw_pen = 1.0 / bw_thres; + // dp->score[0] = a[0].good? min_sc : min_sc>>1; + dp->score[0] = normal_w(min_sc, (int64_t)a[0].cnt); + dp->pre[0] = -1, dp->indels[0] = 0, dp->self_length[0] = 0, dp->occ[0] = 1; + for (i = 1; i < n_a; ++i) { + int32_t score, dg; + int32_t dx = (int32_t)a[i].offset - (int32_t)a[i-1].offset; + int32_t dy = (int32_t)a[i].self_offset - (int32_t)a[i-1].self_offset; + int32_t dd = dx > dy? dx - dy : dy - dx; + double gap_rate; + tot_indel += dd; + tot_len += dy; + if (tot_indel > tot_len * bw_thres) break; + dg = dx < dy? dx : dy; + if (dd > THRESHOLD_MAX_SIZE && dd > dg * bw_thres) break; + score = dg < min_sc? dg : min_sc; + score = normal_w(score, (int64_t)a[i].cnt); + gap_rate = (double)tot_indel / tot_len; + score -= (int)(gap_rate * score * bw_pen); + dp->score[i] = dp->score[i-1] + score; + dp->pre[i] = i - 1; + dp->indels[i] = tot_indel; + dp->self_length[i] = tot_len; + dp->occ[i] = i + 1; + } + if (i < n_a) return -1; + return n_a; +} + +///double band_width_threshold = 0.05; +long long chain_DP(k_mer_hit* a, long long a_n, Chain_Data* dp, overlap_region* result, + double band_width_threshold, int max_skip, int x_readLen, int y_readLen, void *km) +{ + long long i, j; + long long self_pos, pos, max_j, max_i, max_score, score; + long long distance_pos, distance_self_pos, distance_gap, distance_min; + ///double band_width_threshold = 0.05; + double band_width_penalty = 1 / band_width_threshold; + long long min_score = asm_opt.k_mer_length; + long long max_indels, max_self_length; + double gap_rate; + long long total_indels, total_self_length; + int32_t ret; + + resize_Chain_Data(dp, a_n, km); + + ret = ha_chain_check(a, a_n, dp, min_score, band_width_threshold); + if (ret > 0) { + a_n = ret; + goto skip_dp; + } + + // fill the score and backtrack arrays + for (i = 0; i < a_n; ++i) dp->tmp[i] = -1; + for (i = 0; i < a_n; ++i) + { + int n_chn_skip = 0; + int n_max_skip = 0; + + pos = a[i].offset; + self_pos = a[i].self_offset; + max_j = -1; + max_score = normal_w(min_score, (int64_t)a[i].cnt); + max_indels = 0; + max_self_length = 0; + + ///may have a pre-cut condition for j + for (j = i - 1; j >= 0; --j) + { + distance_pos = pos - a[j].offset; + distance_self_pos = self_pos - a[j].self_offset; + ///a has been sorted by a[].offset + ///note for a, we do not have any two elements that have both equal offsets and self_offsets + ///but there maybe two elements that have equal offsets or equal self_offsets + if(distance_pos == 0 || distance_self_pos <= 0) + { + continue; + } + + distance_gap = distance_pos > distance_self_pos? distance_pos - distance_self_pos : distance_self_pos - distance_pos; + + total_indels = dp->indels[j] + distance_gap; + total_self_length = dp->self_length[j] + distance_self_pos; + if(total_indels > band_width_threshold * total_self_length) + { + continue; + } + + ///min distance + distance_min = distance_pos < distance_self_pos? distance_pos:distance_self_pos; + score = distance_min < min_score? distance_min : min_score; + ///need to be fixed in r305 + ///if (!a[j].good) score = (score >> 1) + (score & 1); + score = normal_w(score, (int64_t)a[j].cnt); + + gap_rate = (double)((double)(total_indels)/(double)(total_self_length)); + ///if the gap rate > 0.06, score will be negative + score -= (long long)(gap_rate * score * band_width_penalty); + + score += dp->score[j]; + + ///find a new max score + if (score > max_score) {///must use > instead of >= + max_score = score; + max_j = j; + max_indels = total_indels; + max_self_length = total_self_length; + n_max_skip = 0; + if (n_chn_skip > 0) --n_chn_skip; + } else { + if (++n_max_skip > max_skip) + break; + if (dp->tmp[j] == i) { + if (++n_chn_skip > max_skip) + break; + } + } + if (dp->pre[j] >= 0) dp->tmp[dp->pre[j]] = i; + } + + dp->score[i] = max_score; + dp->pre[i] = max_j; + dp->indels[i] = max_indels; + dp->self_length[i] = max_self_length; + dp->occ[i] = 1; + if(max_j != -1) dp->occ[i] = dp->occ[max_j] + 1; + } + + ///debug_chain(a, a_n, dp); + // if((*result).x_id == 2162668 && (*result).y_id == 182804) print_chain(a, a_n, dp, 10); + +skip_dp: + + max_score = -1; + max_i = -1; + long long mini_xLen = x_readLen * 2 + 2, tmp_xLen; + for (i = 0; i < a_n; ++i) + { + if(dp->score[i] > max_score) + { + max_score = dp->score[i]; + max_i = i; + mini_xLen = get_chainLen(a[i].self_offset, a[i].self_offset, x_readLen, + a[i].offset, a[i].offset, y_readLen); + } + else if(dp->score[i] == max_score) + { + tmp_xLen = get_chainLen(a[i].self_offset, a[i].self_offset, x_readLen, + a[i].offset, a[i].offset, y_readLen); + + if(tmp_xLen < mini_xLen) + { + max_score = dp->score[i]; + max_i = i; + + mini_xLen = tmp_xLen; + } + } + + } + + clear_fake_cigar(&(result->f_cigar)); + ///note a has been sorted by offset, that means has been sorted by query offset + i = max_i; + result->x_pos_e = a[i].self_offset; + result->y_pos_e = a[i].offset; + result->shared_seed = max_score; + result->overlapLen = mini_xLen; + + distance_self_pos = result->x_pos_e - a[i].self_offset; + distance_pos = result->y_pos_e - a[i].offset; + long long pre_distance_gap = distance_pos - distance_self_pos; + ///record first site + ///the length of f_cigar should be at least 1 + ///record the offset of reference + add_fake_cigar(&(result->f_cigar), a[i].self_offset, pre_distance_gap, km); + long long chainLen = 0; + if(result->x_pos_strand == 1) + { + while (i >= 0) + { + distance_self_pos = result->x_pos_e - a[i].self_offset; + distance_pos = result->y_pos_e - a[i].offset; + distance_gap = distance_pos - distance_self_pos; + if(distance_gap != pre_distance_gap) + { + pre_distance_gap = distance_gap; + ///record this site + add_fake_cigar(&(result->f_cigar), a[i].self_offset, pre_distance_gap, km); + } + + chainLen++; + result->x_pos_s = a[i].self_offset; + result->y_pos_s = a[i].offset; + i = dp->pre[i]; + } + } + else + { + while (i >= 0) + { + distance_self_pos = result->x_pos_e - a[i].self_offset; + distance_pos = result->y_pos_e - a[i].offset; + distance_gap = distance_pos - distance_self_pos; + if(distance_gap == pre_distance_gap) + { + result->f_cigar.length--; + add_fake_cigar(&(result->f_cigar), a[i].self_offset, pre_distance_gap, km); + } + else + { + pre_distance_gap = distance_gap; + add_fake_cigar(&(result->f_cigar), a[i].self_offset, pre_distance_gap, km); + } + + chainLen++; + result->x_pos_s = a[i].self_offset; + result->y_pos_s = a[i].offset; + i = dp->pre[i]; + } + } + return chainLen; +} + + + +void calculate_overlap_region_by_chaining(Candidates_list* candidates, overlap_region_alloc* overlap_list, kvec_t_u64_warp* chain_idx, + uint64_t readID, uint64_t readLength, All_reads* R_INF, const ul_idx_t *uref, double band_width_threshold, int add_beg_end, overlap_region* f_cigar, void *km) +{ + long long i = 0; + uint64_t current_ID; + uint64_t current_stand; + + if (candidates->length == 0) return; + + long long sub_region_beg; + long long sub_region_end; + + clear_fake_cigar(&((*f_cigar).f_cigar)); + + i = 0; + while (i < candidates->length) + { + chain_idx->a.n = 0; + current_ID = candidates->list[i].readID; + current_stand = candidates->list[i].strand; + + ///reference read + (*f_cigar).x_id = readID; + (*f_cigar).x_pos_strand = current_stand; + ///query read + (*f_cigar).y_id = current_ID; + ///here the strand of query is always 0 + (*f_cigar).y_pos_strand = 0; + + sub_region_beg = i; + sub_region_end = i; + i++; + + while (i < candidates->length + && + current_ID == candidates->list[i].readID + && + current_stand == candidates->list[i].strand) + { + sub_region_end = i; + i++; + } + + if ((*f_cigar).x_id == (*f_cigar).y_id) + { + continue; + } + + chain_DP(candidates->list + sub_region_beg, + sub_region_end - sub_region_beg + 1, &(candidates->chainDP), f_cigar, band_width_threshold, + 25, /**Get_READ_LENGTH((*R_INF), (*f_cigar).x_id)**/readLength, + R_INF?Get_READ_LENGTH((*R_INF), (*f_cigar).y_id):uref->ug->u.a[(*f_cigar).y_id].len, km); + + ///if (tmp_region.x_id != tmp_region.y_id && tmp_region.shared_seed > 1) + if ((*f_cigar).x_id != (*f_cigar).y_id) + { + append_inexact_overlap_region_alloc(overlap_list, f_cigar, readLength, R_INF?Get_READ_LENGTH((*R_INF), (*f_cigar).y_id):uref->ug->u.a[(*f_cigar).y_id].len, add_beg_end, km); + } + } +} + + +void append_window_list(overlap_region* region, uint64_t x_start, uint64_t x_end, int y_start, int y_end, int error, + int extra_begin, int extra_end, int error_threshold, int blockLen, void *km) +{ + window_list *p = NULL; + kv_pushp(window_list, region->w_list, &p); + + p->x_start = x_start; + p->x_end = x_end; + p->y_start = y_start; + p->y_end = y_end; + p->error = error; + p->extra_begin = extra_begin; + p->extra_end = extra_end; + p->error_threshold = error_threshold; + p->cidx = p->clen = 0; +} + +void test_single_list(Candidates_list* candidates, k_mer_pos* n_list, uint64_t n_lengh, uint64_t end_pos, uint64_t strand) +{ + uint64_t i; + long long j = 0; + for (i = 0; i < n_lengh; i++) + { + + for (; j < candidates->length; j++) + { + if ( + n_list[i].offset == (uint64_t)candidates->list[j].offset + && + n_list[i].readID == candidates->list[j].readID + && + end_pos == (uint64_t)candidates->list[j].self_offset + && + strand == candidates->list[j].strand + ) + { + break; + } + } + + if (j == candidates->length) + { + fprintf(stderr, "ERROR 4\n"); + } + } +} + + +void init_Chain_Data(Chain_Data* x) +{ + memset(x, 0, sizeof(Chain_Data)); +} + +void clear_Chain_Data(Chain_Data* x) +{ + x->length = 0; +} + +void destory_Chain_Data(Chain_Data* x) +{ + free(x->score); + free(x->pre); + free(x->indels); + free(x->self_length); + free(x->occ); + free(x->tmp); +} + +void resize_Chain_Data(Chain_Data* x, long long size, void *km) +{ + if (size + 1 > x->size) { + x->size = size + 1; + kroundup64(x->size); + if(!km) { + REALLOC(x->score, x->size); + REALLOC(x->pre, x->size); + REALLOC(x->indels, x->size); + REALLOC(x->self_length, x->size); + REALLOC(x->occ, x->size); + REALLOC(x->tmp, x->size); + } else { + KREALLOC(km, x->score, x->size); + KREALLOC(km, x->pre, x->size); + KREALLOC(km, x->indels, x->size); + KREALLOC(km, x->self_length, x->size); + KREALLOC(km, x->occ, x->size); + KREALLOC(km, x->tmp, x->size); + } + } +} + +void init_Candidates_list(Candidates_list* l) +{ + l->length = 0; + l->size = 0; + l->list = NULL; + init_Chain_Data(&(l->chainDP)); +} + +void clear_Candidates_list(Candidates_list* l) +{ + l->length = 0; + clear_Chain_Data(&(l->chainDP)); +} + +void destory_Candidates_list(Candidates_list* l) +{ + free(l->list); + destory_Chain_Data(&(l->chainDP)); +} + +void destory_Candidates_list_buf(void *km, Candidates_list* l, int is_z) +{ + kfree(km, l->list); + kfree(km, l->chainDP.score); + kfree(km, l->chainDP.pre); + kfree(km, l->chainDP.indels); + kfree(km, l->chainDP.self_length); + kfree(km, l->chainDP.occ); + kfree(km, l->chainDP.tmp); + if(is_z) memset(l, 0, sizeof(*l)); +} + +void init_fake_cigar(Fake_Cigar* x) +{ + x->buffer = NULL; + x->length = 0; + x->size = 0; +} + +void destory_fake_cigar(Fake_Cigar* x) +{ + if(x->size > 0) + { + free(x->buffer); + } +} + +void clear_fake_cigar(Fake_Cigar* x) +{ + x->length = 0; +} + +void add_fake_cigar(Fake_Cigar* x, uint32_t gap_site, int32_t gap_shift, void *km) +{ + if(x->length + 1 > x->size) + { + x->size = x->length + 1; + kroundup32(x->size); + if(!km) { + REALLOC(x->buffer, x->size); + } else { + KREALLOC(km, x->buffer, x->size); + } + // x->buffer = (uint64_t*)realloc(x->buffer, sizeof(uint64_t) * x->size); + } + + x->buffer[x->length] = gap_site; + x->buffer[x->length] = x->buffer[x->length] << 32; + + if(gap_shift < 0) + { + gap_shift = gap_shift * -1; + gap_site = gap_shift; + gap_site = gap_site << 1; + gap_site = gap_site | ((uint32_t)1); + } + else + { + gap_site = gap_shift; + gap_site = gap_site << 1; + } + + x->buffer[x->length] = x->buffer[x->length] | ((uint32_t)gap_site); + + x->length++; +} + + +void resize_fake_cigar(Fake_Cigar* x, uint64_t size, void *km) +{ + if (size > x->size) { + x->size = size; + if(!km) { + REALLOC(x->buffer, x->size); + } + else { + KREALLOC(km, x->buffer, x->size); + } + + } + x->length = 0; +} + + +void init_window_list_alloc(window_list_alloc* x) +{ + memset(x, 0, sizeof((*x))); +} + +void clear_window_list_alloc(window_list_alloc* x) +{ + x->n = x->c.n = 0; +} + +void destory_window_list_alloc(window_list_alloc* x) +{ + free(x->a); free(x->c.a); +} + +void resize_window_list_alloc(window_list_alloc* x, uint64_t size) +{ + kv_resize(window_list, *x, size); x->n = x->c.n = 0; + uint64_t k; + for (k = 0; k < x->m; k++) x->a[k].error = -1; + x->c.n = 0; +} + +#define normal_cw(x) (((x)&(0xffu))>=((x)>>8)?(((x)&(0xffu))/((x)>>8)):1) + +int32_t lchain_check(k_mer_hit *a, int32_t n_a, Chain_Data *dp, double bw_thres) +{ + int32_t i, tot_g = 0, sc, dg, dq, dr, dd, span; + double bw_pen; + if (n_a == 0) return -1; + if (n_a > 1) { + if ((a[0].self_offset >= a[n_a-1].self_offset)||(a[0].offset == a[n_a-1].offset)) return -1; + dq = (int32_t)a[n_a-1].self_offset - (int32_t)a[0].self_offset; + dr = (int32_t)a[n_a-1].offset - (int32_t)a[0].offset; + dd = ((dq>=dr)? (dq-dr): (dr-dq));//gap + dg = ((dq>=dr)? (dr): (dq));///len + if (dg == 0 || dd > (dg*bw_thres)) return -1; + } + + for (i = 1; i < n_a; ++i) {///a[] is sorted by offset, instead of self_offset; but offset might be equal + if(a[i-1].self_offset >= a[i].self_offset) break; + if(a[i-1].offset == a[i].offset) break; + } + if (i < n_a) return -1; + + bw_pen = 1.0 / bw_thres; + dp->score[0] = normal_w((a[0].cnt&(0xffu)), (a[0].cnt>>8)); dp->pre[0] = -1; + for (i = 1; i < n_a; ++i) { + dq = (int32_t)a[i].self_offset - (int32_t)a[i-1].self_offset; + dr = (int32_t)a[i].offset - (int32_t)a[i-1].offset; + dd = ((dq>=dr)? (dq-dr): (dr-dq));//gap + dg = ((dq>=dr)? (dr): (dq));///len + if(dg == 0) break; + + tot_g += dd; + if (dd > THRESHOLD_MAX_SIZE && dd > (dg*bw_thres)) break; + span = a[i].cnt&(0xffu); + sc = dg < span? dg : span; + sc = normal_w(sc, ((int32_t)(a[i].cnt>>8))); + sc -= (int32_t)((((double)dd)/((double)dg))*bw_pen*((double)sc));///bw_pen is 20 for HiFi + + dp->score[i] = dp->score[i-1] + sc; + dp->pre[i] = i - 1; + } + if (i < n_a) return -1; + + if(n_a > 1) { + dq = (int32_t)a[n_a-1].self_offset - (int32_t)a[0].self_offset; + dr = (int32_t)a[n_a-1].offset - (int32_t)a[0].offset; + dg = ((dq>=dr)? (dr): (dq));///len + dd = tot_g;///gap + if (dd > (dg*bw_thres)) return -1; + } + return n_a; +} + + +int32_t lchain_qcheck(k_mer_hit *a, int32_t n_a, Chain_Data *dp, double bw_thres) +{ + int32_t i, tot_g = 0, sc, dg, dq, dr, dd, span; + double bw_pen; + if (n_a == 0) return -1; + if (n_a > 1) { + if ((a[0].self_offset >= a[n_a-1].self_offset)||(a[0].offset >= a[n_a-1].offset)) return -1; + dq = (int32_t)a[n_a-1].self_offset - (int32_t)a[0].self_offset; + dr = (int32_t)a[n_a-1].offset - (int32_t)a[0].offset; + dd = ((dq>=dr)? (dq-dr): (dr-dq));//gap + dg = ((dq>=dr)? (dr): (dq));///len + if (dg == 0 || dd > (dg*bw_thres)) return -1; + } + + for (i = 1; i < n_a; ++i) {///a[] is sorted by self_offset + if(a[i-1].self_offset >= a[i].self_offset) break; + if(a[i-1].offset >= a[i].offset) break; + } + if (i < n_a) return -1; + + bw_pen = 1.0 / bw_thres; + dp->score[0] = normal_w((a[0].cnt&(0xffu)), (a[0].cnt>>8)); dp->pre[0] = -1; + for (i = 1; i < n_a; ++i) { + dq = (int32_t)a[i].self_offset - (int32_t)a[i-1].self_offset; + dr = (int32_t)a[i].offset - (int32_t)a[i-1].offset; + dd = ((dq>=dr)? (dq-dr): (dr-dq));//gap + dg = ((dq>=dr)? (dr): (dq));///len + if(dg == 0) break; + + tot_g += dd; + if (dd > THRESHOLD_MAX_SIZE && dd > (dg*bw_thres)) break; + span = a[i].cnt&(0xffu); + sc = dg < span? dg : span; + sc = normal_w(sc, ((int32_t)(a[i].cnt>>8))); + sc -= (int32_t)((((double)dd)/((double)dg))*bw_pen*((double)sc));///bw_pen is 20 for HiFi + + dp->score[i] = dp->score[i-1] + sc; + dp->pre[i] = i - 1; + } + if (i < n_a) return -1; + + if(n_a > 1) { + dq = (int32_t)a[n_a-1].self_offset - (int32_t)a[0].self_offset; + dr = (int32_t)a[n_a-1].offset - (int32_t)a[0].offset; + dg = ((dq>=dr)? (dr): (dq));///len + dd = tot_g;///gap + if (dd > (dg*bw_thres)) return -1; + } + return n_a; +} + +inline int32_t cal_bw(const k_mer_hit *ai, const k_mer_hit *aj, double bw_rate, int64_t sf_l, int64_t ot_l) +{ + ///ai is the suffix of aj + int64_t sf_s = aj->self_offset, sf_e = ai->self_offset + 1; + int64_t ot_s = aj->offset, ot_e = ai->offset + 1; + int64_t sf_r = sf_l - sf_e, ot_r = ot_l - ot_e; + if(sf_s <= ot_s) sf_s = 0; + else sf_s -= ot_s; + + if(sf_r <= ot_r) sf_e = sf_l; + else sf_e += ot_r; + + return (sf_e - sf_s)*bw_rate; +} + +inline int32_t comput_sc_ch(const k_mer_hit *ai, const k_mer_hit *aj, double bw_rate, double chn_pen_gap, double chn_pen_skip, int64_t sl, int64_t ol) +{ + ///ai is the suffix of aj + int32_t dq, dr, dd, dg, q_span, sc; + dq = (int64_t)(ai->self_offset) - (int64_t)(aj->self_offset); + if(dq <= 0) return INT32_MIN; + dr = (int64_t)(ai->offset) - (int64_t)(aj->offset); + if(dr <= 0) return INT32_MIN; + dd = dr > dq? dr - dq : dq - dr;//gap + if((dd > 16) && (dd > cal_bw(ai, aj, bw_rate, sl, ol))) return INT32_MIN; + dg = dr < dq? dr : dq;//len + q_span = ai->cnt&(0xffu); + sc = q_span < dg? q_span : dg; + sc = normal_w(sc, ((int32_t)(ai->cnt>>8))); + if (dd || (dg > q_span && dg > 0)) { + double lin_pen, a_pen; + lin_pen = (chn_pen_gap*(double)dd); + a_pen = ((double)(sc))*((((double)dd)/((double)dg))/bw_rate); + if(lin_pen > a_pen) lin_pen = a_pen; + lin_pen += (chn_pen_skip*(double)dg); + sc -= (int32_t)lin_pen; + } + return sc; +} + +inline int32_t comput_sc_ch_ec(const k_mer_hit *ai, const k_mer_hit *aj, double bw_rate, double chn_pen_gap, double chn_pen_skip, int64_t sl, int64_t ol) +{ + ///ai is the suffix of aj + int32_t dq, dr, dd, dg, q_span, sc; + dq = (int64_t)(ai->self_offset) - (int64_t)(aj->self_offset); + if(dq <= 0) return INT32_MIN; + dr = (int64_t)(ai->offset) - (int64_t)(aj->offset); + if(dr <= 0) return INT32_MIN; + dd = dr > dq? dr - dq : dq - dr;//gap + if((dd > 16) && (dd > cal_bw(ai, aj, bw_rate, sl, ol))) return INT32_MIN; + dg = dr < dq? dr : dq;//len + q_span = ai->cnt&(0xffu); + sc = q_span < dg? q_span : dg; + sc = normal_w(sc, ((int32_t)(ai->cnt>>8))); + if (dd || (dg > q_span && dg > 0)) { + double lin_pen, a_pen; + lin_pen = (chn_pen_gap*(double)dd); + a_pen = ((double)(sc))*((((double)dd)/((double)dg))/bw_rate); + ///for long gap + // if(lin_pen > a_pen) lin_pen = a_pen; + if(dd < 4) lin_pen = ((lin_pen > a_pen)?(a_pen):(lin_pen)); + else lin_pen = ((lin_pen < a_pen)?(a_pen):(lin_pen)); + lin_pen += (chn_pen_skip*(double)dg); + sc -= (int32_t)lin_pen; + } + return sc; +} + +inline int32_t comput_sc_ff(const k_mer_hit *ai, const k_mer_hit *aj, double bw_rate, double chn_pen_gap, double chn_pen_skip, int64_t sl, int64_t ol) +{ + ///ai is the suffix of aj + int32_t dq, dr, dd, dg, q_span, sc; + dq = (int64_t)(ai->self_offset) - (int64_t)(aj->self_offset); + if(dq < 0) return INT32_MIN; + dr = (int64_t)(ai->offset) - (int64_t)(aj->offset); + if(dr < 0) return INT32_MIN; + dd = dr > dq? dr - dq : dq - dr;//gap + // if((dd > 16) && (dd > cal_bw(ai, aj, bw_rate, sl, ol))) return INT32_MIN; + dg = dr < dq? dr : dq;//len + q_span = ai->cnt&(0xffu); + sc = q_span < dg? q_span : dg; + sc = normal_w(sc, ((int32_t)(ai->cnt>>8))); + if (dd || (dg > q_span && dg > 0)) { + double lin_pen, a_pen; + lin_pen = (chn_pen_gap*(double)dd); + a_pen = ((double)(sc))*((((double)dd)/((double)dg))/bw_rate); + if(lin_pen > a_pen) lin_pen = a_pen; + lin_pen += (chn_pen_skip*(double)dg); + sc -= (int32_t)lin_pen; + } + return sc; +} + +uint64_t lchain_dp(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, overlap_region* res, + int64_t max_skip, int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, + int64_t xl, int64_t yl, int64_t quick_check) +{ + int64_t *p, *t, max_f, n_skip, st, max_j, end_j, sc, msc, msc_i, bw, max_ii, ovl, movl; + int32_t *f, max, tmp; int64_t i, j, ret, cL = 0; + resize_Chain_Data(dp, a_n, NULL); + t = dp->tmp; f = dp->score; p = dp->pre; + bw = ((xl < yl)?xl:yl); bw *= bw_rate; + msc = msc_i = -1; movl = INT32_MAX; + + if(quick_check) { + ret = lchain_check(a, a_n, dp, bw_rate); + if (ret > 0) { + a_n = ret; msc_i = a_n-1; msc = f[msc_i]; + goto skip_ldp; + } + } + + memset(t, 0, (a_n*sizeof((*t)))); + for (i = st = 0, max_ii = -1; i < a_n; ++i) { + max_f = a[i].cnt&(0xffu); + n_skip = 0; max_j = end_j = -1; + if ((i-st) > max_iter) st = i-max_iter; + + for (j = i - 1; j >= st; --j) { + sc = comput_sc_ch(&a[i], &a[j], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); + if (sc == INT32_MIN) continue; + sc += f[j]; + if (sc > max_f) { + max_f = sc, max_j = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == (int32_t)i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + end_j = j; + + if (max_ii < 0 || ((int64_t)a[i].offset) - ((int64_t)a[max_ii].offset) > max_dis) { + max = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && ((((int64_t)a[i].offset)-((int64_t)a[j].offset))<=max_dis); --j) { + if (max < f[j]) { + max = f[j], max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + tmp = comput_sc_ch(&a[i], &a[max_ii], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); + if (tmp != INT32_MIN && max_f < tmp + f[max_ii]) + max_f = tmp + f[max_ii], max_j = max_ii; + } + f[i] = max_f; p[i] = max_j; + if ((max_ii < 0) || (((((int64_t)a[i].offset)-((int64_t)a[max_ii].offset))<=max_dis) && (f[max_ii]= msc) { + ovl = get_chainLen(a[i].self_offset, a[i].self_offset, xl, a[i].offset, a[i].offset, yl); + if(f[i] > msc || ovl < movl) { + msc = f[i]; msc_i = i; movl = ovl; + } + } + } + + skip_ldp: + ///a[] has been sorted by offset + i = msc_i; + res->x_pos_s = res->x_pos_e = a[i].self_offset; + res->y_pos_s = res->y_pos_e = a[i].offset; + res->shared_seed = msc; + + cL = 0; + while (i >= 0) { + t[cL++] = i; msc_i = i; i = p[i]; + } + + res->x_pos_s = a[t[cL-1]].self_offset; + res->y_pos_s = a[t[cL-1]].offset; + res->overlapLen = get_chainLen(res->x_pos_s, res->x_pos_e, xl, res->y_pos_s, res->y_pos_e, yl); + for (i = 0; i < cL; i++) des[i] = a[t[cL-i-1]]; + return cL; +} + +uint64_t lchain_qdp(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, overlap_region* res, + int64_t max_skip, int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, + int64_t xl, int64_t yl, int64_t quick_check) +{ + int64_t *p, *t, max_f, n_skip, st, max_j, end_j, sc, msc, msc_i, bw, max_ii, ovl, movl; + int32_t *f, max, tmp; int64_t i, j, ret, cL = 0; + resize_Chain_Data(dp, a_n, NULL); + t = dp->tmp; f = dp->score; p = dp->pre; + bw = ((xl < yl)?xl:yl); bw *= bw_rate; + msc = msc_i = -1; movl = INT32_MAX; + // if(a_n && a[0].readID == 0) { + // fprintf(stderr, "---[M::%s::utg%.6dl::%c]\n", + // __func__, (int32_t)a[0].readID+1, "+-"[a[0].strand]); + // } + if(quick_check) { + ret = lchain_qcheck(a, a_n, dp, bw_rate); + if (ret > 0) { + a_n = ret; msc_i = a_n-1; msc = f[msc_i]; + goto skip_ldp; + } + } + + memset(t, 0, (a_n*sizeof((*t)))); + for (i = st = 0, max_ii = -1; i < a_n; ++i) { + max_f = a[i].cnt&(0xffu); + n_skip = 0; max_j = end_j = -1; + if ((i-st) > max_iter) st = i-max_iter; + + for (j = i - 1; j >= st; --j) { + sc = comput_sc_ch(&a[i], &a[j], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); + if (sc == INT32_MIN) continue; + sc += f[j]; + if (sc > max_f) { + max_f = sc, max_j = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == (int32_t)i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + end_j = j; + + if (max_ii < 0 || ((int64_t)a[i].self_offset) - ((int64_t)a[max_ii].self_offset) > max_dis) { + max = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && ((((int64_t)a[i].self_offset)-((int64_t)a[j].self_offset))<=max_dis); --j) { + if (max < f[j]) { + max = f[j], max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + tmp = comput_sc_ch(&a[i], &a[max_ii], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); + if (tmp != INT32_MIN && max_f < tmp + f[max_ii]) + max_f = tmp + f[max_ii], max_j = max_ii; + } + f[i] = max_f; p[i] = max_j; + if ((max_ii < 0) || (((((int64_t)a[i].self_offset)-((int64_t)a[max_ii].self_offset))<=max_dis) && (f[max_ii]= msc) { + ovl = get_chainLen(a[i].self_offset, a[i].self_offset, xl, a[i].offset, a[i].offset, yl); + if(f[i] > msc || ovl < movl) { + msc = f[i]; msc_i = i; movl = ovl; + } + } + // if(a_n && a[0].readID == 0) { + // fprintf(stderr, "i::%ld[M::%s::utg%.6dl::%c] x::%u, y::%u, st::%ld, max_ii::%ld, f[i]::%d, p[i]::%ld, msc_i::%ld, msc::%ld, movl::%ld\n", + // i, __func__, (int32_t)a[i].readID+1, "+-"[a[i].strand], + // a[i].self_offset, a[i].offset, st, max_ii, f[i], p[i], msc_i, msc, movl); + // } + } + + skip_ldp: + ///a[] has been sorted by self_offset + i = msc_i; + res->x_pos_s = res->x_pos_e = a[i].self_offset; + res->y_pos_s = res->y_pos_e = a[i].offset; + res->shared_seed = msc; + + cL = 0; + while (i >= 0) { + t[cL++] = i; msc_i = i; i = p[i]; + } + + res->x_pos_s = a[t[cL-1]].self_offset; + res->y_pos_s = a[t[cL-1]].offset; + res->overlapLen = get_chainLen(res->x_pos_s, res->x_pos_e, xl, res->y_pos_s, res->y_pos_e, yl); + for (i = 0; i < cL; i++) { + des[i] = a[t[cL-i-1]]; + // if(a_n && a[0].readID == 0) { + // fprintf(stderr, "i::%ld[M::%s::utg%.6dl::%c] x::%u, y::%u, cL::%ld\n", + // i, __func__, (int32_t)des[i].readID+1, "+-"[des[i].strand], des[i].self_offset, des[i].offset, cL); + // } + } + return cL; +} + +void push_ovlp_chain_qgen(overlap_region* o, uint32_t xid, int64_t xl, int64_t yl, int64_t sc, k_mer_hit *beg, k_mer_hit *end) +{ + int64_t xr, yr; + o->x_id = xid; o->y_id = beg->readID; + o->x_pos_strand = 0; o->y_pos_strand = beg->strand; + o->x_pos_s = beg->self_offset; o->y_pos_s = beg->offset; + o->x_pos_e = end->self_offset; o->y_pos_e = end->offset; + + if(o->x_pos_s <= o->y_pos_s) { + o->y_pos_s -= o->x_pos_s; o->x_pos_s = 0; + } else { + o->x_pos_s -= o->y_pos_s; o->y_pos_s = 0; + } + + xr = xl-o->x_pos_e-1; yr = yl-o->y_pos_e-1; + if(xr <= yr) { + o->x_pos_e = xl-1; o->y_pos_e += xr; + } else { + o->y_pos_e = yl-1; o->x_pos_e += yr; + } + + o->shared_seed = sc; + o->align_length = 0; + o->is_match = 0; + o->non_homopolymer_errors = 0; + o->strong = 0; + o->overlapLen = 0; +} + +int64_t filter_non_ovlp_chains(overlap_region *a, int64_t a_n, int64_t *n_v) +{ + int64_t k, i, n_mchain, omx, omy, opx, opy, ovx, ovy, os, oe; overlap_region *m, *p, t; + for (k = n_mchain = (*n_v) = 0; k < a_n; k++) { + m = &(a[k]); + omx = m->x_pos_e + 1 - m->x_pos_s; + omy = m->y_pos_e + 1 - m->y_pos_s; + for (i = 0; i < n_mchain; i++) { + p = &(a[i]); + opx = p->x_pos_e + 1 - p->x_pos_s; + opy = p->y_pos_e + 1 - p->y_pos_s; + + os = ((m->x_pos_s>=p->x_pos_s)? m->x_pos_s:p->x_pos_s); + oe = ((m->x_pos_e<=p->x_pos_e)? m->x_pos_e:p->x_pos_e) + 1; + ovx = oe>os?oe-os:0; + if((ovx > omx*0.1) || (ovx > opx*0.1)) break; + + os = ((m->y_pos_s>=p->y_pos_s)? m->y_pos_s:p->y_pos_s); + oe = ((m->y_pos_e<=p->y_pos_e)? m->y_pos_e:p->y_pos_e) + 1; + ovy = oe>os?oe-os:0; + if((ovy > omy*0.1) || (ovy > opy*0.1)) break; + } + if(i < n_mchain) continue; + + if (n_mchain != k) { + t = a[k]; a[k] = a[n_mchain]; a[n_mchain] = t; + } + (*n_v) += a[n_mchain].align_length; + n_mchain++; + } + return n_mchain; +} + +int64_t filter_non_ovlp_xchains(overlap_region *a, int64_t a_n, int64_t *n_v) +{ + int64_t k, i, n_mchain, omx, opx, ovx, os, oe; overlap_region *m, *p, t; + for (k = n_mchain = (*n_v) = 0; k < a_n; k++) { + m = &(a[k]); + omx = m->x_pos_e + 1 - m->x_pos_s; + for (i = 0; i < n_mchain; i++) { + p = &(a[i]); + opx = p->x_pos_e + 1 - p->x_pos_s; + + os = ((m->x_pos_s>=p->x_pos_s)? m->x_pos_s:p->x_pos_s); + oe = ((m->x_pos_e<=p->x_pos_e)? m->x_pos_e:p->x_pos_e) + 1; + ovx = oe>os?oe-os:0; + if((ovx > omx*0.1) || (ovx > opx*0.1)) break; + } + if(i < n_mchain) continue; + + if (n_mchain != k) { + t = a[k]; a[k] = a[n_mchain]; a[n_mchain] = t; + } + (*n_v) += a[n_mchain].align_length; + n_mchain++; + } + return n_mchain; +} + +uint64_t lchain_qdp_mcopy(Candidates_list *cl, int64_t a_idx, int64_t a_n, int64_t des_idx, + Chain_Data* dp, overlap_region_alloc* res, int64_t max_skip, int64_t max_iter, + int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, + uint32_t xid, int64_t xl, int64_t yl, int64_t quick_check, uint32_t apend_be, + int64_t gen_cigar, int64_t enable_mcopy, double mcopy_rate, int64_t mcopy_khit_cutoff, + int64_t khit_n) +{ + if(a_n <= 0) return 0; + int64_t *p, *t, max_f, n_skip, st, max_j, end_j, sc, msc, msc_i, bw, max_ii, ovl, movl, plus = 0, min_sc, ch_n; + int32_t *f, max, tmp, *ii; int64_t i, k, j, cL = 0; k_mer_hit* a; k_mer_hit* des; k_mer_hit *swap; overlap_region *z; + resize_Chain_Data(dp, a_n, NULL); + t = dp->tmp; f = dp->score; p = dp->pre; ii = dp->occ; + bw = ((xl < yl)?xl:yl); bw *= bw_rate; + msc = msc_i = INT32_MIN; movl = INT32_MAX; ch_n = 1; + a = cl->list + a_idx; des = cl->list + des_idx; + // if(a_n && a[0].readID == 0) { + // fprintf(stderr, "---[M::%s::utg%.6dl::%c]\n", + // __func__, (int32_t)a[0].readID+1, "+-"[a[0].strand]); + // } + + memset(t, 0, (a_n*sizeof((*t)))); + for (i = st = plus = 0, max_ii = -1; i < a_n; ++i) { + max_f = a[i].cnt&(0xffu); + n_skip = 0; max_j = end_j = -1; + if ((i-st) > max_iter) st = i-max_iter; + while (a[i].strand != a[st].strand) ++st; + + for (j = i - 1; j >= st; --j) { + sc = comput_sc_ch(&a[i], &a[j], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); + if (sc == INT32_MIN) continue; + sc += f[j]; + if (sc > max_f) { + max_f = sc, max_j = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == (int32_t)i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + end_j = j; + + if ((max_ii<0) || (a[i].self_offset>a[max_ii].self_offset+max_dis) || (a[i].strand!=a[max_ii].strand)) { + max = INT32_MIN; max_ii = -1; + for (j=i-1; (j>=st) && (a[i].self_offset<=max_dis+a[j].self_offset)&&(a[i].strand==a[j].strand); --j) { + if (max < f[j]) { + max = f[j], max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + tmp = comput_sc_ch(&a[i], &a[max_ii], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); + if (tmp != INT32_MIN && max_f < tmp + f[max_ii]) + max_f = tmp + f[max_ii], max_j = max_ii; + } + f[i] = max_f; p[i] = max_j; + if ((max_ii < 0) || ((a[i].self_offset<=max_dis+a[max_ii].self_offset)&&(a[i].strand==a[max_ii].strand)&&(f[max_ii]= msc) { + ovl = get_chainLen(a[i].self_offset, a[i].self_offset, xl, a[i].offset, a[i].offset, yl); + if(f[i] > msc || ovl < movl) { + msc = f[i]; msc_i = i; movl = ovl; + } + } + if(f[i] < plus) plus = f[i]; + ii[i] = 0;///for mcopy, not here + // if(a_n && a[0].readID == 0) { + // fprintf(stderr, "i::%ld[M::%s::utg%.6dl::%c] x::%u, y::%u, st::%ld, max_ii::%ld, f[i]::%d, p[i]::%ld, msc_i::%ld, msc::%ld, movl::%ld\n", + // i, __func__, (int32_t)a[i].readID+1, "+-"[a[i].strand], + // a[i].self_offset, a[i].offset, st, max_ii, f[i], p[i], msc_i, msc, movl); + // } + } + + for (i = msc_i, cL = 0; i >= 0; i = p[i]) { ii[i] = 1; t[cL++] = i;}///label the best chain + if((movl < xl) && enable_mcopy/**(movl < yl)**/) { + if(cL >= mcopy_khit_cutoff) {///if there are too few k-mers, disable mcopy + msc -= plus; min_sc = msc*mcopy_rate/**0.2**/; ii[msc_i] = 0; + for (i = ch_n = 0; i < a_n; ++i) {///make all f[] positive + f[i] -= plus; if(i >= ch_n) t[i] = 0; + if((!(ii[i])) && (f[i] >= min_sc)) { + t[ch_n] = ((uint64_t)f[i])<<32; t[ch_n] += (i<<1); ch_n++; + } + } + if(ch_n > 1) { + int64_t n_v, n_v0, ni, n_u, n_u0 = res->length; + radix_sort_hc64i(t, t + ch_n); + for (k = ch_n-1, n_v = n_u = 0; k >= 0; --k) { + n_v0 = n_v; + for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { + ii[n_v++] = i; t[i] |= 1; i = p[i]; + } + if(n_v0 == n_v) continue; + sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); + if(sc >= min_sc) { + kv_pushp_ol(overlap_region, (*res), &z); + push_ovlp_chain_qgen(z, xid, xl, yl, sc+plus, &(a[ii[n_v-1]]), &(a[ii[n_v0]])); + ///mcopy_khit_cutoff <= 1: disable the mcopy_khit_cutoff filtering, for the realignment + if((mcopy_khit_cutoff <= 1) || ((z->x_pos_e+1-z->x_pos_s) <= (movl<<2))) { + z->align_length = n_v-n_v0; z->x_id = n_v0; + n_u++; + } else {///non-best is too long + res->length--; n_v = n_v0; + } + } else { + n_v = n_v0; + } + } + + if(n_u > 1) ks_introsort_or_sss(n_u, res->list + n_u0); + res->length = n_u0 + filter_non_ovlp_xchains(res->list + n_u0, n_u, &n_v); + n_u = res->length; + if(n_u > n_u0 + 1) { + kv_resize_cl(k_mer_hit, (*cl), (n_v+cl->length)); + a = cl->list + a_idx; des = cl->list + des_idx; swap = cl->list + cl->length; + for (k = n_u0, i = n_v0 = n_v = 0; k < n_u; k++) { + z = &(res->list[k]); + z->non_homopolymer_errors = des_idx + i; + n_v0 = z->x_id; ni = z->align_length; + for (j = 0; j < ni; j++, i++) { + ///k0 + (ni - j - 1) + swap[i] = a[ii[n_v0 + (ni- j - 1)]]; + swap[i].readID = k; + } + z->x_id = xid; + if(gen_cigar) gen_fake_cigar(&(z->f_cigar), z, apend_be, swap+i-ni, ni); + if(!khit_n) z->align_length = 0; + } + memcpy(des, swap, i*sizeof((*swap))); //assert(i == ch_n); + + // fprintf(stderr, "[M::%s::msc->%ld] msc_k_hits::%u, cL::%ld, min_sc::%ld, best_sc::%ld, n_u0_sc::%d, mcopy_rate::%f, # chains::%ld\n", + // __func__, msc, res->list[n_u0].align_length, cL, min_sc, msc+plus, res->list[n_u0].shared_seed, + // mcopy_rate, n_u-n_u0); + } else if(n_u == n_u0 + 1) { + z = &(res->list[n_u0]); k = n_u0; i = 0; + z->non_homopolymer_errors = des_idx + i; + n_v0 = z->x_id; ni = z->align_length; + for (j = 0; j < ni; j++, i++) { + ///k0 + (ni - j - 1) + des[i] = a[ii[n_v0 + (ni- j - 1)]]; + des[i].readID = k; + } + z->x_id = xid; + if(gen_cigar) gen_fake_cigar(&(z->f_cigar), z, apend_be, des+i-ni, ni); + if(!khit_n) z->align_length = 0; + } + return i; + } else { + msc += plus; i = msc_i; cL = 0; + while (i >= 0) {t[cL++] = i; i = p[i];} + } + } + } + ///a[] has been sorted by self_offset + // i = msc_i; cL = 0; + // while (i >= 0) {t[cL++] = i; i = p[i];} + kv_pushp_ol(overlap_region, (*res), &z); + push_ovlp_chain_qgen(z, xid, xl, yl, msc, &(a[t[cL-1]]), &(a[t[0]])); + for (i = 0; i < cL; i++) {des[i] = a[t[cL-i-1]]; des[i].readID = res->length-1;} + z->non_homopolymer_errors = des_idx; + if(gen_cigar) gen_fake_cigar(&(z->f_cigar), z, apend_be, des, cL); + if(khit_n) z->align_length = cL; + return cL; +} + +void quick_ck_lchain(k_mer_hit* a, int64_t a_n, int64_t xl, int64_t yl, double chn_pen_gap, double chn_pen_skip, double bw_rate, +int64_t *p, int64_t *t, int32_t *f, int32_t *ii, int64_t *plus, int64_t *msc, int64_t *msc_i, int64_t *movl, int64_t *si, int64_t *ei) +{ + if(a_n <= 0) return; + int64_t l, k, is_srt = 1, z; k_mer_hit *ai, *aj; + int64_t dq, dr, dd, dg, q_span, sc, csc, ddt; + int64_t plus0, msc0, msc_i0, movl0; double lin_pen, a_pen; + + *plus = 0; *msc = *msc_i = INT32_MIN; *movl = INT32_MAX; *si = 0; *ei = a_n; + + for (k = 1, l = 0; k <= a_n; k++) { + if(k == a_n || a[k].strand != a[l].strand) { + t[k-1] = 0; ii[k-1] = 0; + // if(a_n && a[0].readID == 3125488) { + // fprintf(stderr, "[M::%s::] ii::[%ld,%ld)(%c), is_srt::%ld, chn_pen_gap::%f, chn_pen_skip::%f, bw_rate::%f\n", __func__, l, k, "+-"[a[l].strand], is_srt, chn_pen_gap, chn_pen_skip, bw_rate); + // } + if(is_srt) { + plus0 = 0; msc0 = msc_i0 = INT32_MIN; movl0 = INT32_MAX; ddt = 0; + + + p[l] = -1; f[l] = a[l].cnt&(0xffu); + if(f[l] >= msc0) {msc0 = f[l]; msc_i0 = l;}///difference + if(f[l] < plus0) plus0 = f[l]; + + + for (z = l + 1; z < k; z++) { + ///roughly same to comput_sc_ch(&a[z], &a[z-1]) + ai = &a[z]; aj = &a[z-1]; + dq = (int64_t)(ai->self_offset) - (int64_t)(aj->self_offset); + if(dq <= 0) break; + dr = (int64_t)(ai->offset) - (int64_t)(aj->offset); + if(dr <= 0) break; + dd = dr > dq? dr - dq : dq - dr;//gap + // if(a_n && a[0].readID == 3125488) { + // fprintf(stderr, "%ld,", dd); + // } + if((dd > 16) && (dd > cal_bw(&(a[z]), &(a[z-1]), bw_rate, xl, yl))) break; + dg = dr < dq? dr : dq;//len + q_span = ai->cnt&(0xffu); + sc = q_span < dg? q_span : dg; + sc = normal_w(sc, ((int32_t)(ai->cnt>>8))); + if (dd || (dg > q_span && dg > 0)) { + lin_pen = (chn_pen_gap*(double)dd); + a_pen = ((double)(sc))*((((double)dd)/((double)dg))/bw_rate); + ///for long gap + // if(lin_pen > a_pen) lin_pen = a_pen; + if(dd < 4) lin_pen = ((lin_pen > a_pen)?(a_pen):(lin_pen)); + else lin_pen = ((lin_pen < a_pen)?(a_pen):(lin_pen)); + lin_pen += (chn_pen_skip*(double)dg); + sc -= (int32_t)lin_pen; + } + + sc += f[z-1]; csc = a[z].cnt&(0xffu); if(sc < csc) break; + p[z] = z - 1; f[z] = sc; ddt += dd; + + if(f[z] >= msc0) {msc0 = f[z]; msc_i0 = z;}///difference + if(f[z] < plus0) plus0 = f[z]; + } + + // if(a_n && a[0].readID == 3125488) { + // fprintf(stderr, "\n"); + // fprintf(stderr, "[M::%s::] msc0::%ld, msc_i0::%ld, (%c)\n", __func__, msc0, msc_i0, "+-"[a[l].strand]); + // } + if((z >= k) && (msc_i0 == (k - 1))) { + if((k - l >= 2) && (ddt > 16) && (ddt > cal_bw(&(a[k-1]), &(a[l]), bw_rate, xl, yl))) msc_i0 = INT32_MIN; + if(msc_i0 == (k - 1)) { + if(msc0 >= (*msc)) { + movl0 = get_chainLen(a[msc_i0].self_offset, a[msc_i0].self_offset, xl, a[msc_i0].offset, a[msc_i0].offset, yl); + if(msc0 > (*msc) || movl0 < (*movl)) { + *msc = msc0; *msc_i = msc_i0; *movl = movl0; + } + } + if(plus0 < (*plus)) *plus = plus0; + if((*ei) > k) { + (*si) = k; + } else { + (*ei) = l; + } + } + } + } + l = k; is_srt = 1; + } else { + if((a[k].self_offset <= a[k-1].self_offset) || (a[k].offset <= a[k-1].offset)) is_srt = 0; + t[k-1] = 0; ii[k-1] = 0; + } + } +} + + +uint64_t lchain_qdp_mcopy_fast(Candidates_list *cl, int64_t a_idx, int64_t a_n, int64_t des_idx, + Chain_Data* dp, overlap_region_alloc* res, int64_t max_skip, int64_t max_iter, + int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, + uint32_t xid, int64_t xl, int64_t yl, int64_t quick_check, uint32_t apend_be, + int64_t gen_cigar, int64_t mcopy_num, double mcopy_rate, int64_t mcopy_khit_cutoff, + int64_t khit_n) +{ + if(a_n <= 0) return 0; + int64_t *p, *t, max_f, n_skip, st, max_j, end_j, sc, msc, msc_i, max_ii, ovl, movl, plus = 0, min_sc, ch_n, si, ei; + int32_t *f, max, tmp, *ii; int64_t i, k, j, cL = 0; k_mer_hit* a; k_mer_hit* des; k_mer_hit *swap; overlap_region *z; + resize_Chain_Data(dp, a_n, NULL); ch_n = 1; // int64_t bw; bw = ((xl < yl)?xl:yl); bw *= bw_rate; + t = dp->tmp; f = dp->score; p = dp->pre; ii = dp->occ; + + a = cl->list + a_idx; des = cl->list + des_idx; + // if(a_n && (a[0].readID == 27105 || a[0].readID == 7603)) {///r833 + // fprintf(stderr, "---[M::%s::rid->%u::%c]\ta_n::%ld\n", + // __func__, a[0].readID, "+-"[a[0].strand], a_n); + // } + if(quick_check) { + quick_ck_lchain(a, a_n, xl, yl, chn_pen_gap, chn_pen_skip, bw_rate, p, t, f, ii, &plus, &msc, &msc_i, &movl, &si, &ei); + } else { + msc = msc_i = INT32_MIN; movl = INT32_MAX; plus = 0; si = 0; ei = a_n; + memset(t, 0, (a_n*sizeof((*t)))); + } + // if(a_n && a[0].readID == 4412344) { + // fprintf(stderr, "[M::%s::] si::%ld, ei::%ld, a_n::%ld\n", __func__, si, ei, a_n); + // } + for (i = st = si, max_ii = -1; i < ei; ++i) { + max_f = a[i].cnt&(0xffu); + n_skip = 0; max_j = end_j = -1; + if ((i-st) > max_iter) st = i-max_iter; + while (a[i].strand != a[st].strand) ++st; + + for (j = i - 1; j >= st; --j) { + sc = comput_sc_ch_ec(&a[i], &a[j], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); + if (sc == INT32_MIN) continue; + sc += f[j]; + if (sc > max_f) { + max_f = sc, max_j = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == (int32_t)i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + end_j = j; + + if ((max_ii<0) || (a[i].self_offset>a[max_ii].self_offset+max_dis) || (a[i].strand!=a[max_ii].strand)) { + max = INT32_MIN; max_ii = -1; + for (j=i-1; (j>=st) && (a[i].self_offset<=max_dis+a[j].self_offset)&&(a[i].strand==a[j].strand); --j) { + if (max < f[j]) { + max = f[j], max_ii = j; + } + } + } + + if ((max_ii >= 0) && (max_ii < end_j) && (a[i].strand == a[max_ii].strand)) {///just have a try with a[i]<->a[max_ii] + tmp = comput_sc_ch_ec(&a[i], &a[max_ii], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); + if (tmp != INT32_MIN && max_f < tmp + f[max_ii]) + max_f = tmp + f[max_ii], max_j = max_ii; + } + f[i] = max_f; p[i] = max_j; + if ((max_ii < 0) || ((a[i].self_offset<=max_dis+a[max_ii].self_offset)&&(a[i].strand==a[max_ii].strand)&&(f[max_ii]= msc) { + ovl = get_chainLen(a[i].self_offset, a[i].self_offset, xl, a[i].offset, a[i].offset, yl); + if(f[i] > msc || ovl < movl) { + msc = f[i]; msc_i = i; movl = ovl; + } + } + if(f[i] < plus) plus = f[i]; + ii[i] = 0;///for mcopy, not here + // if(a_n && (a[0].readID == 27105 || a[0].readID == 7603)) {///r833 + // fprintf(stderr, "i::%ld[M::%s::rid->%u::%c] q::%u, t::%u, st::%ld, max_ii::%ld, f[i]::%d, p[i]::%ld, msc_i::%ld, msc::%ld, movl::%ld\n", + // i, __func__, a[i].readID, "+-"[a[i].strand], + // a[i].self_offset, a[i].offset, st, max_ii, f[i], p[i], msc_i, msc, movl); + // } + } + + for (i = msc_i, cL = 0; i >= 0; i = p[i]) { ii[i] = 1; t[cL++] = i;}///label the best chain + + if(mcopy_num > 1) { + // if(a[0].readID == 4412344) { + // fprintf(stderr, "[M::%s::] msc::%ld, cL::%ld\n", __func__, msc, cL); + // } + if(cL >= mcopy_khit_cutoff) {///if there are too few k-mers, disable mcopy + msc -= plus; min_sc = msc*mcopy_rate/**0.2**/; ii[msc_i] = 0; + for (i = ch_n = 0; i < a_n; ++i) {///make all f[] positive + f[i] -= plus; if(i >= ch_n) t[i] = 0; + if((!(ii[i])) && (f[i] >= min_sc)) {///!(ii[i]): skip the best chain + t[ch_n] = ((uint64_t)f[i])<<32; t[ch_n] += (i<<1); ch_n++; + } + } + // if(a[0].readID == 4412344) { + // fprintf(stderr, "[M::%s::] msc::%ld, min_sc::%ld, cL::%ld, ch_n::%ld, mcopy_num::%ld\n", __func__, msc, min_sc, cL, ch_n, mcopy_num); + // } + if(ch_n > 1) { + int64_t n_v, n_v0, ni, n_u, n_u0 = res->length; + radix_sort_hc64i(t, t + ch_n); + for (k = ch_n-1, n_v = n_u = 0; k >= 0 && n_u < mcopy_num; --k) { + n_v0 = n_v; + for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { + ii[n_v++] = i; t[i] |= 1; i = p[i]; + } + if(n_v0 == n_v) continue; + sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); + // if(a[0].readID == 4412344) { + // fprintf(stderr, "+[M::%s::] sc::%ld, n_a::%ld\n", __func__, sc, n_v-n_v0); + // } + if(sc >= min_sc) { + kv_pushp_ol(overlap_region, (*res), &z); + push_ovlp_chain_qgen(z, xid, xl, yl, sc+plus, &(a[ii[n_v-1]]), &(a[ii[n_v0]])); + // if(a[0].readID == 4412344) { + // fprintf(stderr, "-[M::%s::] sc::%ld, n_a::%ld, q::[%u,%u), t::[%u,%u), %c\n", __func__, sc, n_v-n_v0, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, "+-"[z->y_pos_strand]); + // } + ///mcopy_khit_cutoff <= 1: disable the mcopy_khit_cutoff filtering, for the realignment + // if((mcopy_khit_cutoff <= 1) || ((z->x_pos_e+1-z->x_pos_s) <= (movl<<2))) { + if((!n_u) || (n_v - n_v0 > 1)) { + z->align_length = n_v-n_v0; z->x_id = n_v0; + n_u++; + } else {///non-best is tiny + res->length--; n_v = n_v0; + } + } else { + n_v = n_v0; + } + } + + // if(n_u > 1) ks_introsort_or_sss(n_u, res->list + n_u0); + // res->length = n_u0 + filter_non_ovlp_xchains(res->list + n_u0, n_u, &n_v); + n_u = res->length; + if(n_u > n_u0 + 1) { + kv_resize_cl(k_mer_hit, (*cl), (n_v+cl->length)); + a = cl->list + a_idx; des = cl->list + des_idx; swap = cl->list + cl->length; + for (k = n_u0, i = n_v0 = n_v = 0; k < n_u; k++) { + z = &(res->list[k]); + z->non_homopolymer_errors = des_idx + i; + n_v0 = z->x_id; ni = z->align_length; + for (j = 0; j < ni; j++, i++) { + ///k0 + (ni - j - 1) + swap[i] = a[ii[n_v0 + (ni- j - 1)]]; + swap[i].readID = k; + } + z->x_id = xid; + if(gen_cigar) gen_fake_cigar(&(z->f_cigar), z, apend_be, swap+i-ni, ni); + if(!khit_n) z->align_length = 0; + } + memcpy(des, swap, i*sizeof((*swap))); //assert(i == ch_n); + + // fprintf(stderr, "[M::%s::msc->%ld] msc_k_hits::%u, cL::%ld, min_sc::%ld, best_sc::%ld, n_u0_sc::%d, mcopy_rate::%f, # chains::%ld\n", + // __func__, msc, res->list[n_u0].align_length, cL, min_sc, msc+plus, res->list[n_u0].shared_seed, + // mcopy_rate, n_u-n_u0); + } else if(n_u == n_u0 + 1) { + z = &(res->list[n_u0]); k = n_u0; i = 0; + z->non_homopolymer_errors = des_idx + i; + n_v0 = z->x_id; ni = z->align_length; + for (j = 0; j < ni; j++, i++) { + ///k0 + (ni - j - 1) + des[i] = a[ii[n_v0 + (ni- j - 1)]]; + des[i].readID = k; + } + z->x_id = xid; + if(gen_cigar) gen_fake_cigar(&(z->f_cigar), z, apend_be, des+i-ni, ni); + if(!khit_n) z->align_length = 0; + } + return i; + } else { + msc += plus; i = msc_i; cL = 0; + while (i >= 0) {t[cL++] = i; i = p[i];} + } + } + } + + + + ///a[] has been sorted by self_offset + // i = msc_i; cL = 0; + // while (i >= 0) {t[cL++] = i; i = p[i];} + kv_pushp_ol(overlap_region, (*res), &z); + push_ovlp_chain_qgen(z, xid, xl, yl, msc, &(a[t[cL-1]]), &(a[t[0]])); + for (i = 0; i < cL; i++) {des[i] = a[t[cL-i-1]]; des[i].readID = res->length-1;} + z->non_homopolymer_errors = des_idx; + if(gen_cigar) gen_fake_cigar(&(z->f_cigar), z, apend_be, des, cL); + if(khit_n) z->align_length = cL; + return cL; +} + + +#define rev_khit(an, xl, yl) do { \ + (an).self_offset = (xl)-1-((an).self_offset+1-((an).cnt&((uint32_t)(0xffu)))); \ + (an).offset = (yl)-1-((an).offset+1-((an).cnt&((uint32_t)(0xffu))));\ + } while (0) + +///it is unpossibale that (left_fix == 0 && right_fix == 0) +uint64_t lchain_qdp_fix(k_mer_hit* a, int64_t a_n, Chain_Data* dp, int64_t max_skip, + int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, + double bw_rate, int64_t xl, int64_t yl, int64_t quick_check, + int64_t left_fix, int64_t right_fix) +{ + int64_t *p, *t, max_f, n_skip, st, max_j, end_j, sc, msc, msc_i, bw, max_ii, ovl, movl; + int32_t *f, max, tmp; int64_t i, j, ret, cL = 0, must_p = 1, is_reorder = 0; k_mer_hit z; + resize_Chain_Data(dp, a_n, NULL); + t = dp->tmp; f = dp->score; p = dp->pre; + bw = ((xl < yl)?xl:yl); bw *= bw_rate; + msc = msc_i = -1; movl = INT32_MAX; + + if(quick_check) { + ret = lchain_qcheck(a, a_n, dp, bw_rate); + if (ret > 0) { + a_n = ret; msc_i = a_n-1; msc = f[msc_i]; + goto skip_ldp; + } + } + + memset(t, 0, (a_n*sizeof((*t)))); + if((right_fix) && (!left_fix)) { + // fprintf(stderr, "\n[M::%s::] a_n::%ld\n", __func__, a_n); + // for (i = 0; i < a_n; ++i) { + // fprintf(stderr, "+[M::%s::] x::[%u, %u), y::[%u, %u)\n", __func__, + // a[i].self_offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].self_offset+1, + // a[i].offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].offset+1); + // } + n_skip = a_n>>1; + for (i=0; i max_iter) st = i-max_iter; + // if(a[0].self_offset == 171728) { + // fprintf(stderr, "i::%ld[M::%s::] x::[%u, %u), y::[%u, %u)\n", i, __func__, + // a[i].self_offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].self_offset+1, + // a[i].offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].offset+1); + // } + for (j = i - 1; j >= 0; --j) { + sc = comput_sc_ff(&a[i], &a[j], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); + // if(a[0].self_offset == 171728) { + // fprintf(stderr, "j::%ld[M::%s::sc->%ld] x::[%u, %u), y::[%u, %u)\n", j, __func__, sc, + // a[j].self_offset+1-(a[j].cnt&((uint32_t)(0xffu))), a[j].self_offset+1, + // a[j].offset+1-(a[j].cnt&((uint32_t)(0xffu))), a[j].offset+1); + // } + if (sc == INT32_MIN) continue; + sc += f[j]; + if (sc > max_f) { + max_f = sc, max_j = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == (int32_t)i) { + if ((++n_skip) > max_skip) { + if((max_j != -1) || (must_p == 0)) break; + } + } + if (p[j] >= 0) t[p[j]] = i; + ///put it here will allow at least one prefix no matter max_dis + ///this is special for gap filling, not for chaining + if (a[i].self_offset > (max_dis + a[j].self_offset)) { + if((max_j != -1)) break; + } + if (j < st) { + if((max_j != -1) || (must_p == 0)) break; + } + } + end_j = j; + + if (max_ii < 0 || ((int64_t)a[i].self_offset) - ((int64_t)a[max_ii].self_offset) > max_dis) { + max = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && ((((int64_t)a[i].self_offset)-((int64_t)a[j].self_offset))<=max_dis); --j) { + if (max < f[j]) { + max = f[j], max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + tmp = comput_sc_ff(&a[i], &a[max_ii], bw_rate, chn_pen_gap, chn_pen_skip, xl, yl); + if (tmp != INT32_MIN && max_f < tmp + f[max_ii]) + max_f = tmp + f[max_ii], max_j = max_ii; + } + if(max_j == -1) { + f[i] = 0; p[i] = max_j; + } else { + f[i] = max_f; p[i] = max_j; + } + + if ((max_ii < 0) || (((((int64_t)a[i].self_offset)-((int64_t)a[max_ii].self_offset))<=max_dis) && (f[max_ii]= msc) { + ovl = get_chainLen(a[i].self_offset, a[i].self_offset, xl, a[i].offset, a[i].offset, yl); + if(f[i] > msc || ovl < movl) { + msc = f[i]; msc_i = i; movl = ovl; + } + } + } + + skip_ldp: + if(right_fix && left_fix) msc_i = a_n-1; + ///a[] has been sorted by self_offset + i = msc_i; cL = 0; + while (i >= 0) { + t[cL++] = i; msc_i = i; i = p[i]; + } + // if((right_fix) && (!left_fix)) { + // fprintf(stderr, "[M::%s::] cL::%ld\n", __func__, cL); + // } + + if(is_reorder) { + n_skip = a_n>>1; + for (i=0; i[M::%s::] t[%ld]::%ld\n", __func__, i, t[i]); + } + // for (i = 0; i < a_n; ++i) { + // fprintf(stderr, ">[M::%s::] x::[%u, %u), y::[%u, %u)\n", __func__, + // a[i].self_offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].self_offset+1, + // a[i].offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].offset+1); + // } + } else { + n_skip = cL>>1; + for (i = 0; i < n_skip; i++) { + msc_i = t[i]; t[i] = t[cL-i-1]; t[cL-i-1] = msc_i; + } + } + // if(cL != a_n) { + // fprintf(stderr, "\n[M::%s::] a_n::%ld, left_fix::%ld, right_fix::%ld\n", __func__, a_n, left_fix, right_fix); + // for (i = 0; i < a_n; ++i) { + // fprintf(stderr, "+[M::%s::] x::[%u, %u), y::[%u, %u)\n", __func__, + // a[i].self_offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].self_offset+1, + // a[i].offset+1-(a[i].cnt&((uint32_t)(0xffu))), a[i].offset+1); + // } + // for (i = 0; i < cL; i++) { + // fprintf(stderr, ">[M::%s::] t[%ld]::%ld\n", __func__, i, t[i]); + // } + // } + return cL; +} + + +uint64_t lchain_refine(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, + int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t long_gap) +{ + if(a_n <= 0) return 0; + int64_t *p, *t, max_f, n_skip, st, max_j, sc, msc, msc_i, dq, dr, dd; + int32_t *f; int64_t i, j, cL = 0; + resize_Chain_Data(dp, a_n, NULL); + t = dp->tmp; f = dp->score; p = dp->pre; msc = msc_i = -1; + + for (i = 1, f[0] = 0, p[0] = -1, msc_i = a_n - 1; i < a_n; i++) { + j = i-1; + dq = (int64_t)(a[i].self_offset) - (int64_t)(a[j].self_offset); + dr = (int64_t)(a[i].offset) - (int64_t)(a[j].offset); + dd = dr > dq? dr - dq : dq - dr;//gap + if(dd <= long_gap || dq > max_dis) { + p[i] = i - 1; f[i] = i; + } else { + break; + } + } + if(i >= a_n) goto ss_kip; + + + memset(t, 0, (a_n*sizeof((*t)))); + f[0] = 0; p[0] = -1; + + for (i = 1, st = 0; i < a_n; ++i) { + max_f = INT32_MIN; n_skip = 0; max_j = -1; + if ((i-st) > max_iter) st = i-max_iter; + ///i-1 + j = i - 1; + dq = (int64_t)(a[i].self_offset) - (int64_t)(a[j].self_offset); + dr = (int64_t)(a[i].offset) - (int64_t)(a[j].offset); + dd = dr > dq? dr - dq : dq - dr;//gap + if(dd <= long_gap) dd = 0; + sc = f[j] - dd; + if (sc > max_f) { + max_f = sc, max_j = j; + } + if (p[j] >= 0) t[p[j]] = i; + + ///[st, i-2] + for (--j; (j >= st) && (a[i].self_offset <= (max_dis + a[j].self_offset)); --j) { + dq = (int64_t)(a[i].self_offset) - (int64_t)(a[j].self_offset); + dr = (int64_t)(a[i].offset) - (int64_t)(a[j].offset); + dd = dr > dq? dr - dq : dq - dr;//gap + if(dd <= long_gap) dd = 0; + sc = f[j] - dd; + if (sc > max_f) { + max_f = sc, max_j = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == (int32_t)i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + + f[i] = max_f; p[i] = max_j; + } + + i = a_n-1; msc = f[i]; msc_i = i; + for (j = i-1; (j >= 0) && (a[i].self_offset <= (max_dis + a[j].self_offset)); --j) { + if(msc < f[j] && p[j] >= 0) {///hold at least two hits in th final chain + msc = f[j]; msc_i = j; + } + } + + ss_kip: + ///a[] has been sorted by self_offset + i = msc_i; + cL = 0; + while (i >= 0) { + t[cL++] = i; i = p[i]; + } + + n_skip = cL>>1; + for (i = 0; i < n_skip; i++) { + msc_i = t[i]; t[i] = t[cL-i-1]; t[cL-i-1] = msc_i; + } + if(des) { + for (i = 0; i < cL; i++) des[i] = a[t[i]]; + } + return cL; +} + + +uint64_t lchain_simple(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, + int64_t max_skip, int64_t max_iter) +{ + if(a_n <= 0) return 0; + int64_t *p, *t, max_f, n_skip, st, max_j, sc, msc, msc_i; + int32_t *f; int64_t i, j, cL = 0; + resize_Chain_Data(dp, a_n, NULL); + t = dp->tmp; f = dp->score; p = dp->pre; msc = msc_i = -1; + + for (i=1, f[0]=a[0].cnt, p[0]=-1, msc_i=a_n-1; i a[j].self_offset)&&(a[i].offset > a[j].offset)) { + p[i] = j; f[i] = f[j]+a[i].cnt; + } else { + break; + } + } + if(i >= a_n) goto ss_kip; + + memset(t, 0, (a_n*sizeof((*t)))); + f[0]=a[0].cnt; p[0]=-1; msc = f[0]; msc_i = 0; + + for (i = 1, st = 0; i < a_n; ++i) { + max_f = INT32_MIN; n_skip = 0; max_j = -1; + if ((i-st) > max_iter) st = i-max_iter; + ///[st, i-2] + for (j=i-1; j >= st; --j) { + if((a[i].self_offset > a[j].self_offset)&&(a[i].offset > a[j].offset)) { + sc = f[j]+a[i].cnt; + if (sc > max_f) { + max_f = sc, max_j = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == (int32_t)i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + } + f[i] = max_f; p[i] = max_j; + if(f[i] > msc) { + msc = f[i]; msc_i = i; + } + } + + ss_kip: + ///a[] has been sorted by self_offset + i = msc_i; + cL = 0; + while (i >= 0) { + t[cL++] = i; i = p[i]; + } + + n_skip = cL>>1; + for (i = 0; i < n_skip; i++) { + msc_i = t[i]; t[i] = t[cL-i-1]; t[cL-i-1] = msc_i; + } + if(des) { + for (i = 0; i < cL; i++) des[i] = a[t[i]]; + } + return cL; +} + +uint64_t lchain_simple0(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, int64_t max_skip, int64_t max_iter) +{ + if(a_n <= 0) return 0; + int64_t *p, *t, max_f, n_skip, st, max_j, sc, msc, msc_i; + int32_t *f; int64_t i, j, cL = 0; + resize_Chain_Data(dp, a_n, NULL); + t = dp->tmp; f = dp->score; p = dp->pre; msc = msc_i = -1; + + memset(t, 0, (a_n*sizeof((*t)))); + f[0]=a[0].cnt; p[0]=-1; msc = f[0]; msc_i = 0; + + for (i = 1, st = 0; i < a_n; ++i) { + max_f = INT32_MIN; n_skip = 0; max_j = -1; + if ((i-st) > max_iter) st = i-max_iter; + ///[st, i-2] + for (j=i-1; j >= st; --j) { + if((a[i].self_offset > a[j].self_offset)&&(a[i].offset > a[j].offset)) { + sc = f[j]+a[i].cnt; + if (sc > max_f) { + max_f = sc, max_j = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == (int32_t)i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + } + f[i] = max_f; p[i] = max_j; + if(f[i] > msc) { + msc = f[i]; msc_i = i; + } + } + + ///a[] has been sorted by self_offset + i = msc_i; + cL = 0; + while (i >= 0) { + t[cL++] = i; i = p[i]; + } + + n_skip = cL>>1; + for (i = 0; i < n_skip; i++) { + msc_i = t[i]; t[i] = t[cL-i-1]; t[cL-i-1] = msc_i; + } + if(des) { + for (i = 0; i < cL; i++) des[i] = a[t[i]]; + } + return cL; +} + +inline int64_t hit_long_gap(k_mer_hit *a, k_mer_hit *b, int64_t max_lgap, double small_bw_rate, int64_t min_small_bw) +{ + int64_t dq, dr, dd, dm; + dq = b->self_offset-a->self_offset; + dr = b->offset-a->offset; + dd = dq>=dr? ((dq)-(dr)): ((dr)-(dq)); + if(max_lgap>=0) { + if(dd <= max_lgap) return 1; + return 0; + } else { + dm = dq>=dr?dr:dq; + if((dd > (dm*small_bw_rate)) && (dd > min_small_bw)) return 0; + return 1; + } +} + +int64_t filter_bad_seed_dp(k_mer_hit *sk, k_mer_hit *ek, k_mer_hit* a, int64_t a_n, int64_t max_lgap, double small_bw_rate, int64_t min_small_bw) +{ + int64_t k = 0; k_mer_hit *z; double bw_r; int64_t bw, mmgap, occ = 0; + bw_r = small_bw_rate; bw = min_small_bw; mmgap = max_lgap; + if(sk) { + for (k = 0; k < a_n; k++) { + z = &(a[k]); + if(z->cnt < z->readID) continue; + mmgap = max_lgap; + if(z->cnt <= 1) mmgap = -1; + if((sk && (!hit_long_gap(sk, z, mmgap, bw_r, bw))) || + (ek && (!hit_long_gap(z, ek, mmgap, bw_r, bw)))) { + z->offset = z->self_offset = (uint32_t)-1; occ++; + } else { + break; + } + } + } + + if(ek && k < a_n) { + for (k = a_n-1; k >= 0; k--) { + z = &(a[k]); + if(z->cnt < z->readID) continue; + mmgap = max_lgap; + if(z->cnt <= 1) mmgap = -1; + if((sk && (!hit_long_gap(sk, z, mmgap, bw_r, bw))) || + (ek && (!hit_long_gap(z, ek, mmgap, bw_r, bw)))) { + z->offset = z->self_offset = (uint32_t)-1; occ++; + } else { + break; + } + } + } + + return occ; +} + +uint64_t lchain_dp_trace(k_mer_hit* a, int64_t a_n, int64_t max_lgap, double sgap_rate, int64_t sgap) +{ + // fprintf(stderr, "[M::%s::] a_n::%ld\n", __func__, a_n); + if(a_n <= 0) return 0; + int64_t i, st, occ = 0; + + for (i = 1, st = 0; i <= a_n; ++i) { + // fprintf(stderr, "[M::%s::i->%ld] q::%u, t::%u, cnt::%u, readID::%u\n", __func__, + // i-1, a[i-1].self_offset, a[i-1].offset, a[i-1].cnt, a[i-1].readID); + if((i == a_n) || (is_alnw(a[i]))) {///[st, i) + if(i > st) { + occ += filter_bad_seed_dp((st>0)?&(a[st-1]):NULL, (ilength - 1)) - { - return get_fake_gap_shift(o, o->length - 1); - } - - long long i; - for (i = 0; i < (long long)o->length; i++) - { - if(x_start < get_fake_gap_pos(o, i)) - { - break; - } - } - - if(i == 0 || i == (long long)o->length) - { - fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__); - exit(0); - } - - ///note here return i - 1 - return get_fake_gap_shift(o, i - 1); -} - -void resize_Chain_Data(Chain_Data* x, long long size, void *km); -void init_window_list_alloc(window_list_alloc* x); -void clear_window_list_alloc(window_list_alloc* x); -void destory_window_list_alloc(window_list_alloc* x); -void resize_window_list_alloc(window_list_alloc* x, uint64_t size); -long long chain_DP(k_mer_hit* a, long long a_n, Chain_Data* dp, overlap_region* result, double band_width_threshold, int max_skip, int x_readLen, int y_readLen, void *km); -uint64_t lchain_dp(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, overlap_region* res, - int64_t max_skip, int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, - int64_t xl, int64_t yl, int64_t quick_check); -int ovlp_chain_gen(overlap_region_alloc* ol, overlap_region* t, int64_t xl, int64_t yl, int64_t apend_be, k_mer_hit* hit, int64_t n_hit); -void gen_fake_cigar(Fake_Cigar* z, overlap_region *o, int64_t apend_be, k_mer_hit* hit, int64_t n_hit); -int append_utg_inexact_overlap_region_alloc(overlap_region_alloc* list, overlap_region* tmp, - ma_utg_v *ua, int add_beg_end, void *km); - -#define kv_pushp_cl(type, v, p) do { \ - if ((v).length == (v).size) { \ - (v).size = (v).size? (v).size<<1 : 2; \ - (v).list = (type*)realloc((v).list, sizeof(type) * (v).size); \ - } \ - *(p) = &((v).list[(v).length++]); \ - } while (0) - -#define kv_resize_cl(type, v, s) do { \ - if ((v).size < (s)) { \ - (v).size = (s); \ - kv_roundup32((v).size); \ - (v).list = (type*)realloc((v).list, sizeof(type) * (v).size); \ - } \ - } while (0) - -#define is_alnw(a) (((a).readID) == ((uint32_t)(0x7fffffff))) -#define is_pri_aln(a) ((((a).readID) == ((uint32_t)(0x7fffffff)))||((a).cnt >= (a).readID)) - -uint64_t lchain_dp_trace(k_mer_hit* a, int64_t a_n, int64_t max_lgap, double sgap_rate, int64_t sgap); -uint64_t lchain_qdp(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, overlap_region* res, - int64_t max_skip, int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, - int64_t xl, int64_t yl, int64_t quick_check); -int ovlp_chain_qgen(overlap_region_alloc* ol, overlap_region* t, int64_t xl, int64_t yl, int64_t apend_be, k_mer_hit* hit, int64_t n_hit); -uint64_t lchain_refine(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, - int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t long_gap); -uint64_t lchain_qdp_fix(k_mer_hit* a, int64_t a_n, Chain_Data* dp, int64_t max_skip, - int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, - double bw_rate, int64_t xl, int64_t yl, int64_t quick_check, - int64_t left_fix, int64_t right_fix); -uint64_t lchain_simple(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, - int64_t max_skip, int64_t max_iter); -uint64_t lchain_qdp_mcopy(Candidates_list *cl, int64_t a_idx, int64_t a_n, int64_t des_idx, - Chain_Data* dp, overlap_region_alloc* res, int64_t max_skip, int64_t max_iter, - int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, - uint32_t xid, int64_t xl, int64_t yl, int64_t quick_check, uint32_t apend_be, - int64_t gen_cigar, int64_t enable_mcopy, double mcopy_rate, int64_t mcopy_khit_cutoff, - int64_t khit_n); - -uint64_t lchain_qdp_mcopy_fast(Candidates_list *cl, int64_t a_idx, int64_t a_n, int64_t des_idx, - Chain_Data* dp, overlap_region_alloc* res, int64_t max_skip, int64_t max_iter, - int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, - uint32_t xid, int64_t xl, int64_t yl, int64_t quick_check, uint32_t apend_be, - int64_t gen_cigar, int64_t enable_mcopy, double mcopy_rate, int64_t mcopy_khit_cutoff, - int64_t khit_n); - -#define kv_pushp_ol(type, v, p) do { \ - if ((v).length == (v).size) { \ - (v).list = (type*)realloc((v).list, sizeof(type)*((v).size?((v).size<<1):(2))); \ - memset((v).list+(v).size, 0, sizeof(overlap_region)*(((v).size?((v).size<<1):2)-(v).size));\ - (v).size = (v).size?((v).size<<1):(2); \ - } \ - *(p) = &((v).list[(v).length++]); \ - } while (0) - -#endif +#ifndef __HASHTABLE__ +#define __HASHTABLE__ +#include "htab.h" + +#define PREFIX_BITS 16 +#define MAX_SUFFIX_BITS 64 +#define MODE_VALUE 101 + +#define WINDOW 375 +#define WINDOW_BOUNDARY 375 +#define WINDOW_HC 775 +///ONT high error +// #define WINDOW_OHC 475 +#define WINDOW_OHC 375 +#define WINDOW_HC_FAST 512 +///for one side, the first or last WINDOW_UNCORRECT_SINGLE_SIDE_BOUNDARY bases should not be corrected +#define WINDOW_UNCORRECT_SINGLE_SIDE_BOUNDARY 25 +#define THRESHOLD 15 +#define OVERLAP_THRESHOLD_HIFI_FILTER 0.9 +#define OVERLAP_THRESHOLD_HIFI_FF_FILTER 0.6 +#define OVERLAP_THRESHOLD_HIFI_FF_DE_FILTER 0.5 +#define OVERLAP_THRESHOLD_NOSI_FILTER 0.7 +#define OVERLAP_THRESHOLD_FILTER_HPC 0.75 +#define HIGH_HET_OVERLAP_THRESHOLD_FILTER 0.3 +#define HIGH_HET_ERROR_RATE 0.08 +#define THRESHOLD_MAX_SIZE 31 +#define THRESHOLD_UL_MAX 0.2 +#define WINDOW_UL 75 +#define WINDOW_UL_H 200 +// #define WINDOW_UL_H 150 +#define MIN_UL_ALIN_RATE 0.5 +#define MIN_UL_ALIN_LEN (WINDOW_UL*6) +#define WINDOW_UL_BOUND 48 +#define WINDOW_UL_BOUND_RATE 0.55 + +#define GROUP_SIZE 4 +///the max cigar likes 10M10D10M10D10M +///#define CIGAR_MAX_LENGTH THRESHOLD*2+2 +#define CIGAR_MAX_LENGTH 31*2+4 + +typedef struct +{ + uint32_t offset; + uint32_t readID:31, rev:1; +} k_mer_pos; + +typedef struct +{ + k_mer_pos* list; + uint64_t length; + uint64_t size; + uint8_t direction; + uint64_t end_pos; +} k_mer_pos_list; + +typedef struct +{ + ///the begining and end of a window, instead of the whole overlap + int32_t x_start, x_end; + int32_t y_start, y_end; + int16_t extra_begin, extra_end; + int16_t error, error_threshold; + uint32_t cidx, clen; +} window_list; + +typedef struct +{ + size_t n, m; + window_list *a; + kvec_t(uint16_t) c; +} window_list_alloc; + +typedef struct +{ + uint64_t* buffer; + uint32_t length; + uint32_t size; +} Fake_Cigar; + +typedef struct +{ + uint32_t x_id; + ///the begining and end of the whole overlap + uint32_t x_pos_s; + uint32_t x_pos_e; + uint32_t x_pos_strand; + + uint32_t y_id; + uint32_t y_pos_s; + uint32_t y_pos_e; + uint32_t y_pos_strand; + + uint32_t overlapLen; + int32_t shared_seed; + uint32_t align_length; + uint8_t is_match; + uint8_t without_large_indel; + int8_t strong; + uint32_t non_homopolymer_errors; + + // window_list* w_list; + // uint32_t w_list_size; + // uint32_t w_list_length; + Fake_Cigar f_cigar; + + window_list_alloc w_list; + window_list_alloc boundary_cigars; +} overlap_region; + +typedef struct +{ + overlap_region* list; + uint64_t size; + uint64_t length; + int64_t mapped_overlaps_length; +} overlap_region_alloc; + +typedef struct +{ + uint32_t readID:31, strand:1; + uint32_t offset, self_offset, cnt; +} k_mer_hit; + +typedef struct { + int32_t *score; + int64_t *pre; + int32_t *indels; + int32_t *self_length; + int32_t *occ; + int64_t *tmp; // MUST BE 64-bit integer + int64_t length; + int64_t size; +} Chain_Data; + +typedef struct +{ + k_mer_hit* list; + long long length; + long long size; + Chain_Data chainDP; +} Candidates_list; + +void init_Candidates_list(Candidates_list* l); +void clear_Candidates_list(Candidates_list* l); +void destory_Candidates_list(Candidates_list* l); +void destory_Candidates_list_buf(void *km, Candidates_list* l, int is_z); + +void init_overlap_region_alloc(overlap_region_alloc* list); +void clear_overlap_region_alloc(overlap_region_alloc* list); +void destory_overlap_region_alloc(overlap_region_alloc* list); +void append_window_list(overlap_region* region, uint64_t x_start, uint64_t x_end, int y_start, int y_end, int error, +int extra_begin, int extra_end, int error_threshold, int blockLen, void *km); + +void overlap_region_sort_y_id(overlap_region *a, long long n); + +void calculate_overlap_region_by_chaining(Candidates_list* candidates, overlap_region_alloc* overlap_list, kvec_t_u64_warp* chain_idx, +uint64_t readID, uint64_t readLength, All_reads* R_INF, const ul_idx_t *uref, double band_width_threshold, int add_beg_end, overlap_region* f_cigar, void *km); + +void init_fake_cigar(Fake_Cigar* x); +void destory_fake_cigar(Fake_Cigar* x); +void clear_fake_cigar(Fake_Cigar* x); +void add_fake_cigar(Fake_Cigar* x, uint32_t gap_site, int32_t gap_shift, void *km); +void resize_fake_cigar(Fake_Cigar* x, uint64_t size, void *km); +int get_fake_gap_pos(Fake_Cigar* x, int index); +int get_fake_gap_shift(Fake_Cigar* x, int index); + +static inline long long y_start_offset(long long x_start, Fake_Cigar* o) +{ + if(x_start == get_fake_gap_pos(o, o->length - 1)) + { + return get_fake_gap_shift(o, o->length - 1); + } + + long long i; + for (i = 0; i < (long long)o->length; i++) + { + if(x_start < get_fake_gap_pos(o, i)) + { + break; + } + } + + if(i == 0 || i == (long long)o->length) + { + fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__); + exit(0); + } + + ///note here return i - 1 + return get_fake_gap_shift(o, i - 1); +} + +void resize_Chain_Data(Chain_Data* x, long long size, void *km); +void init_window_list_alloc(window_list_alloc* x); +void clear_window_list_alloc(window_list_alloc* x); +void destory_window_list_alloc(window_list_alloc* x); +void resize_window_list_alloc(window_list_alloc* x, uint64_t size); +long long chain_DP(k_mer_hit* a, long long a_n, Chain_Data* dp, overlap_region* result, double band_width_threshold, int max_skip, int x_readLen, int y_readLen, void *km); +uint64_t lchain_dp(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, overlap_region* res, + int64_t max_skip, int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, + int64_t xl, int64_t yl, int64_t quick_check); +int ovlp_chain_gen(overlap_region_alloc* ol, overlap_region* t, int64_t xl, int64_t yl, int64_t apend_be, k_mer_hit* hit, int64_t n_hit); +void gen_fake_cigar(Fake_Cigar* z, overlap_region *o, int64_t apend_be, k_mer_hit* hit, int64_t n_hit); +int append_utg_inexact_overlap_region_alloc(overlap_region_alloc* list, overlap_region* tmp, + ma_utg_v *ua, int add_beg_end, void *km); + +#define kv_pushp_cl(type, v, p) do { \ + if ((v).length == (v).size) { \ + (v).size = (v).size? (v).size<<1 : 2; \ + (v).list = (type*)realloc((v).list, sizeof(type) * (v).size); \ + } \ + *(p) = &((v).list[(v).length++]); \ + } while (0) + +#define kv_resize_cl(type, v, s) do { \ + if ((v).size < (s)) { \ + (v).size = (s); \ + kv_roundup32((v).size); \ + (v).list = (type*)realloc((v).list, sizeof(type) * (v).size); \ + } \ + } while (0) + +#define is_alnw(a) (((a).readID) == ((uint32_t)(0x7fffffff))) +#define is_pri_aln(a) ((((a).readID) == ((uint32_t)(0x7fffffff)))||((a).cnt >= (a).readID)) + +uint64_t lchain_dp_trace(k_mer_hit* a, int64_t a_n, int64_t max_lgap, double sgap_rate, int64_t sgap); +uint64_t lchain_qdp(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, overlap_region* res, + int64_t max_skip, int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, + int64_t xl, int64_t yl, int64_t quick_check); +int ovlp_chain_qgen(overlap_region_alloc* ol, overlap_region* t, int64_t xl, int64_t yl, int64_t apend_be, k_mer_hit* hit, int64_t n_hit); +uint64_t lchain_refine(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, + int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t long_gap); +uint64_t lchain_qdp_fix(k_mer_hit* a, int64_t a_n, Chain_Data* dp, int64_t max_skip, + int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, + double bw_rate, int64_t xl, int64_t yl, int64_t quick_check, + int64_t left_fix, int64_t right_fix); +uint64_t lchain_simple(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, + int64_t max_skip, int64_t max_iter); +uint64_t lchain_simple0(k_mer_hit* a, int64_t a_n, k_mer_hit* des, Chain_Data* dp, int64_t max_skip, int64_t max_iter); +void push_ovlp_chain_qgen(overlap_region* o, uint32_t xid, int64_t xl, int64_t yl, int64_t sc, k_mer_hit *beg, k_mer_hit *end); + +uint64_t lchain_qdp_mcopy(Candidates_list *cl, int64_t a_idx, int64_t a_n, int64_t des_idx, + Chain_Data* dp, overlap_region_alloc* res, int64_t max_skip, int64_t max_iter, + int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, + uint32_t xid, int64_t xl, int64_t yl, int64_t quick_check, uint32_t apend_be, + int64_t gen_cigar, int64_t enable_mcopy, double mcopy_rate, int64_t mcopy_khit_cutoff, + int64_t khit_n); + +uint64_t lchain_qdp_mcopy_fast(Candidates_list *cl, int64_t a_idx, int64_t a_n, int64_t des_idx, + Chain_Data* dp, overlap_region_alloc* res, int64_t max_skip, int64_t max_iter, + int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, + uint32_t xid, int64_t xl, int64_t yl, int64_t quick_check, uint32_t apend_be, + int64_t gen_cigar, int64_t enable_mcopy, double mcopy_rate, int64_t mcopy_khit_cutoff, + int64_t khit_n); + +#define kv_pushp_ol(type, v, p) do { \ + if ((v).length == (v).size) { \ + (v).list = (type*)realloc((v).list, sizeof(type)*((v).size?((v).size<<1):(2))); \ + memset((v).list+(v).size, 0, sizeof(overlap_region)*(((v).size?((v).size<<1):2)-(v).size));\ + (v).size = (v).size?((v).size<<1):(2); \ + } \ + *(p) = &((v).list[(v).length++]); \ + } while (0) + +#endif diff --git a/LICENSE b/LICENSE index 8b23445..cbd9e60 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2019 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2019 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Levenshtein_distance.cpp b/Levenshtein_distance.cpp index 4622c9d..995e147 100644 --- a/Levenshtein_distance.cpp +++ b/Levenshtein_distance.cpp @@ -1 +1 @@ -#include "Levenshtein_distance.h" +#include "Levenshtein_distance.h" diff --git a/Levenshtein_distance.h b/Levenshtein_distance.h index a7c6ec7..2cae69a 100644 --- a/Levenshtein_distance.h +++ b/Levenshtein_distance.h @@ -1,5042 +1,5052 @@ -#ifndef __LEVENSHTEIN__ -#define __LEVENSHTEIN__ - -#define __STDC_LIMIT_MACROS -#include -#include "emmintrin.h" -#include "nmmintrin.h" -#include "smmintrin.h" -#include -#include -#include -#include -#include "kvec.h" - -extern const unsigned char seq_nt4_table[256]; -typedef uint64_t Word; -typedef uint32_t Word_32; -typedef struct {size_t n, m; uint16_t *a; } asg16_v; - -inline void get_error(int t_length, int errthold, int init_err, Word VP, Word VN, -unsigned int* return_err, int* back_site) -{ - (*return_err) = (unsigned int)-1; - int site = t_length - 1; - int return_site = -1; - ///in most cases, p_length should be t_length + 2 * errthold - ///int available_i = p_length - t_length; - int available_i = 2 * errthold; - - - if ((init_err <= errthold) && ((unsigned int)init_err <= (*return_err))) - { - (*return_err) = init_err; - return_site = site; - } - - - int i = 0; - unsigned int ungap_error = (unsigned int)-1; - - while (i < available_i) - { - init_err = init_err + ((VP >> i)&(Word)1); - init_err = init_err - ((VN >> i)&(Word)1); - ++i; - - if ((init_err <= errthold) && ((unsigned int)init_err <= *return_err)) - { - *return_err = init_err; - return_site = site + i; - } - - /****************************may have bugs********************************/ - if(i == errthold) - { - ungap_error = init_err; - } - /****************************may have bugs********************************/ - } - - /****************************may have bugs********************************/ - if((ungap_error<=(unsigned int)errthold) && (ungap_error == (*return_err))) - { - return_site = site + errthold; - } - /****************************may have bugs********************************/ - - (*back_site) = return_site; -} - -inline int Reserve_Banded_BPM_Extension -(char *pattern, int p_length, char *text, int t_length, unsigned short errthold, -unsigned int* return_err, int* return_p_end, int* return_t_end) -{ - (*return_err) = (unsigned int)-1; - (*return_p_end) = -1; - (*return_t_end) = -1; - - Word Peq[256]; - - unsigned int line_error = (unsigned int)-1; - int return_site; - int band_length = (errthold << 1) + 1; - int i = 0; - Word tmp_Peq_1 = (Word)1; - - Peq[(uint8_t)'A'] = (Word)0; - Peq[(uint8_t)'T'] = (Word)0; - Peq[(uint8_t)'G'] = (Word)0; - Peq[(uint8_t)'C'] = (Word)0; - - - Word Peq_A; - Word Peq_T; - Word Peq_C; - Word Peq_G; - - ///band_length = 2k + 1 - for (i = 0; i> 1; - VN = X&HP; - VP = HN | ~(X | HP); - - if (!(D0&err_mask)) - { - ++err; - if ((err - last_high)>errthold) - { - return (*return_t_end); - } - } - get_error(i + 1, errthold, err, VP, VN, &line_error, &return_site); - if(line_error != (unsigned int)-1) - { - (*return_t_end) = i; - (*return_p_end) = return_site; - (*return_err) = line_error; - } - - Peq[(uint8_t)'A'] = Peq[(uint8_t)'A'] >> 1; - Peq[(uint8_t)'C'] = Peq[(uint8_t)'C'] >> 1; - Peq[(uint8_t)'G'] = Peq[(uint8_t)'G'] >> 1; - Peq[(uint8_t)'T'] = Peq[(uint8_t)'T'] >> 1; - - - ++i; - ++i_bd; - Peq[(uint8_t)pattern[i_bd]] = Peq[(uint8_t)pattern[i_bd]] | Mask; - } - - - - - - X = Peq[(uint8_t)text[i]] | VN; - D0 = ((VP + (X&VP)) ^ VP) | X; - HN = VP&D0; - HP = VN | ~(VP | D0); - X = D0 >> 1; - VN = X&HP; - VP = HN | ~(X | HP); - if (!(D0&err_mask)) - { - ++err; - if ((err - last_high)>errthold) - { - return (*return_t_end); - } - } - ///i = t_length - 1 - get_error(i + 1, errthold, err, VP, VN, &line_error, &return_site); - if(line_error != (unsigned int)-1) - { - (*return_t_end) = i; - (*return_p_end) = return_site; - (*return_err) = line_error; - } - - return (*return_t_end); -} - -inline int Reserve_Banded_BPM_Extension_REV -(char *pattern, int p_length, char *text, int t_length, unsigned short errthold, -unsigned int* return_err, int* return_p_end, int* return_t_end) -{ - (*return_err) = (unsigned int)-1; - (*return_p_end) = -1; - (*return_t_end) = -1; - - Word Peq[256]; - - unsigned int line_error = (unsigned int)-1; - int return_site; - int band_length = (errthold << 1) + 1; - int i = 0; - Word tmp_Peq_1 = (Word)1; - - Peq[(uint8_t)'A'] = (Word)0; - Peq[(uint8_t)'T'] = (Word)0; - Peq[(uint8_t)'G'] = (Word)0; - Peq[(uint8_t)'C'] = (Word)0; - - - Word Peq_A; - Word Peq_T; - Word Peq_C; - Word Peq_G; - - ///band_length = 2k + 1 - for (i = 0; i> 1; - VN = X&HP; - VP = HN | ~(X | HP); - - if (!(D0&err_mask)) - { - ++err; - if ((err - last_high)>errthold) - { - return (*return_t_end); - } - } - get_error(i + 1, errthold, err, VP, VN, &line_error, &return_site); - if(line_error != (unsigned int)-1) - { - (*return_t_end) = t_length-i-1; - (*return_p_end) = p_length-return_site-1; - (*return_err) = line_error; - } - - Peq[(uint8_t)'A'] = Peq[(uint8_t)'A'] >> 1; - Peq[(uint8_t)'C'] = Peq[(uint8_t)'C'] >> 1; - Peq[(uint8_t)'G'] = Peq[(uint8_t)'G'] >> 1; - Peq[(uint8_t)'T'] = Peq[(uint8_t)'T'] >> 1; - - - ++i; - ++i_bd; - Peq[(uint8_t)pattern[p_length-i_bd-1]] = Peq[(uint8_t)pattern[p_length-i_bd-1]] | Mask; - } - - - - - - X = Peq[(uint8_t)text[t_length-i-1]] | VN; - D0 = ((VP + (X&VP)) ^ VP) | X; - HN = VP&D0; - HP = VN | ~(VP | D0); - X = D0 >> 1; - VN = X&HP; - VP = HN | ~(X | HP); - if (!(D0&err_mask)) - { - ++err; - if ((err - last_high)>errthold) - { - return (*return_t_end); - } - } - ///i = t_length - 1 - get_error(i + 1, errthold, err, VP, VN, &line_error, &return_site); - if(line_error != (unsigned int)-1) - { - (*return_t_end) = t_length-i-1; - (*return_p_end) = p_length-return_site-1; - (*return_err) = line_error; - } - - return (*return_t_end); -} - -inline void reverse_string(char* str, int strLen) -{ - int i, Len; - char k; - Len = strLen / 2; - for (i = 0; i < Len; i++) - { - k = str[i]; - str[i] = str[strLen - i - 1]; - str[strLen - i - 1] = k; - } -} - -inline int alignment_extension(char *pattern, int p_length, char *text, int t_length, -unsigned short errthold, int direction, unsigned int* return_err, int* return_p_end, -int* return_t_end, int* return_aligned_t_len) -{ - (*return_aligned_t_len) = 0; - - if(direction == 0) - { - Reserve_Banded_BPM_Extension(pattern, p_length, text, t_length, errthold, return_err, - return_p_end, return_t_end); - if((*return_p_end) != -1 && (*return_t_end) != -1) - { - (*return_aligned_t_len) = (*return_t_end) + 1; - return 1; - } - else - { - return -1; - } - - } - else - { - reverse_string(pattern, p_length); - reverse_string(text, t_length); - - Reserve_Banded_BPM_Extension(pattern, p_length, text, t_length, errthold, return_err, - return_p_end, return_t_end); - - reverse_string(pattern, p_length); - reverse_string(text, t_length); - - if((*return_p_end) != -1 && (*return_t_end) != -1) - { - (*return_aligned_t_len) = (*return_t_end) + 1; - (*return_p_end) = p_length - (*return_p_end); - (*return_t_end) = t_length - (*return_t_end); - return 1; - } - else - { - return -1; - } - } -} - -inline void print_bit(Word z, int64_t w, const char *cmd) -{ - int64_t k;//, w = (sizeof(Word)<<3); - fprintf(stderr, "%s\t", cmd); - for (k = w-1; k >= 0; k--) fprintf(stderr, "%llu", (z>>k)&(1ULL)); - fprintf(stderr, "\n"); -} - -inline int32_t ed_band_cal_global(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre) -{ - if((pn > tn + thre) || (tn > pn + thre)) return INT32_MAX; - if((pn < thre + 1) || (tn < thre + 1)) return INT32_MAX; - Word Peq[5] = {0}, mm, VP = 0, VN = 0, X = 0, D0 = 0, HN = 0, HP = 0; - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd = thre+1, i_bd = thre; - // fprintf(stderr, "\n[M::%s::]\n", __func__); - for (i = 0, mm = (((Word)1)<> 1; - VN = X&HP; - VP = HN | ~(X | HP); - // fprintf(stderr, "\n[M::%s::i->%d]\n", __func__, i); - // print_bit(VN, (thre<<1)+1, "VN"); - // print_bit(VP, (thre<<1)+1, "VP"); - // print_bit(HN, (thre<<1)+1, "HN"); - // print_bit(HP, (thre<<1)+1, "HP"); - // print_bit(D0, (thre<<1)+1, "D0"); - - if (!(D0&(1ULL))) { - ++err; - if (err>cut) return INT32_MAX; - } - // fprintf(stderr, "[M::%s::i->%d] err->%d\n", __func__, i, err); - - Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; ///Peq[4] >>= 1; - - ++i; ++i_bd; - if(i_bd < pn) { - Peq[seq_nt4_table[(uint8_t)pstr[i_bd]]] |= mm; Peq[4] = 0; - } - // if(i < pn) Peq[seq_nt4_table[(uint8_t)pstr[i]]] |= mm; - } - - X = Peq[seq_nt4_table[(uint8_t)tstr[i]]] | VN; - D0 = ((VP + (X&VP)) ^ VP) | X; - HN = VP&D0; - HP = VN | ~(VP | D0); - X = D0 >> 1; - VN = X&HP; - VP = HN | ~(X | HP); - // fprintf(stderr, "\n[M::%s::i->%d]\n", __func__, i); - // print_bit(VN, (thre<<1)+1, "VN"); - // print_bit(VP, (thre<<1)+1, "VP"); - // print_bit(HN, (thre<<1)+1, "HN"); - // print_bit(HP, (thre<<1)+1, "HP"); - // print_bit(D0, (thre<<1)+1, "D0"); - if (!(D0&(1ULL))) { - ++err; - if (err>cut) return INT32_MAX; - } - // fprintf(stderr, "[M::%s::i->%d] err->%d\n", __func__, i, err); - - int32_t site = tn - 1 - thre;///up bound - for (cut = pn - 1, i = 0; site < cut; site++, i++) { - // fprintf(stderr, "+[M::%s::site->%d] err->%d\n", __func__, site, err); - err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); - // fprintf(stderr, "-[M::%s::site->%d] err->%d\n", __func__, site, err); - } - - if (site == cut && err <= thre) return err; - return INT32_MAX; -} - -#define EAC_M 0 -#define MIS_M 1 -#define MOR_YP 2 -#define MOR_XT 3 - -inline void push_trace(asg16_v *res, uint16_t c, uint32_t len) -{ - uint16_t p; c <<= 14; - while (len >= (0x3fff)) { - p = (c + (0x3fff)); kv_push(uint16_t, *res, p); len -= (0x3fff); - } - if(len) { - p = (c + len); kv_push(uint16_t, *res, p); - } -} - -inline uint32_t pop_trace(asg16_v *res, uint32_t i, uint16_t *c, uint32_t *len) -{ - (*c) = (res->a[i]>>14); (*len) = (res->a[i]&(0x3fff)); - for (i++; (i < res->n) && ((*c) == (res->a[i]>>14)); i++) { - (*len) += (res->a[i]&(0x3fff)); - } - return i; -} - -inline int32_t pop_trace_back(asg16_v *res, int32_t i, uint16_t *c, uint32_t *len) -{ - (*c) = (res->a[i]>>14); (*len) = (res->a[i]&(0x3fff)); - for (i--; (i >= 0) && ((*c) == (res->a[i]>>14)); i--) { - (*len) += (res->a[i]&(0x3fff)); - } - return i; -} - -///compact functions -#define pop_trac_bpc(in, rc, rb, rl) do { \ - (rc) = ((in)>>14);\ - if((rc) == 1 || (rc) == 2) {(rb) = (((in)>>12)&3); (rl) = ((in)&(0xfff));}\ - else {(rl) = ((in)&(0x3fff));}\ - } while (0) - -inline void push_trace_bp(asg16_v *res, uint16_t c, uint16_t b, uint32_t len, uint32_t is_append) -{ - uint16_t p, c0, b0, len0, mm; - if((is_append) && (res->n)) { - b0 = b; - pop_trac_bpc(res->a[res->n-1], c0, b0, len0); - if((c == c0) && (b == b0)) { - res->n--; len += len0; - } - } - - mm = (0x3fff); c0 = c; c <<= 14; - if(c0 == 1 || c0 == 2) { - mm = (0xfff); c += ((b&3) << 12); - } - - - while (len >= mm) { - p = (c + mm); kv_push(uint16_t, *res, p); len -= mm; - } - // fprintf(stderr, "[M::%s] c::%u, len::%u\n", __func__, c, len); - if(len) { - p = (c + len); kv_push(uint16_t, *res, p); - } -} - -inline uint32_t pop_trace_bp(asg16_v *res, uint32_t i, uint16_t *c, uint16_t *b, uint32_t *len) -{ - (*c) = (res->a[i]>>14); - if((*c) == 1 || (*c) == 2) { - (*b) = ((res->a[i]>>12)&3); - (*len) = (res->a[i]&(0xfff)); - } else { - (*b) = (uint16_t)-1; - (*len) = (res->a[i]&(0x3fff)); - } - - uint32_t sl; uint16_t sb; - for (i++; (i < res->n) && ((*c) == (res->a[i]>>14)); i++) { - if((*c) == 1 || (*c) == 2) { - sb = ((res->a[i]>>12)&3); sl = (res->a[i]&(0xfff)); - } else { - sb = (uint16_t)-1; sl = (res->a[i]&(0x3fff)); - } - if((*b) != sb) break; - (*len) += sl; - } - return i; -} - -inline int64_t pop_trace_bp_rev(asg16_v *res, int64_t i, uint16_t *c, uint16_t *b, uint32_t *len) -{ - (*c) = (res->a[i]>>14); - if((*c) == 1 || (*c) == 2) { - (*b) = ((res->a[i]>>12)&3); - (*len) = (res->a[i]&(0xfff)); - } else { - (*b) = (uint16_t)-1; - (*len) = (res->a[i]&(0x3fff)); - } - - uint32_t sl; uint16_t sb; - for (i--; (i >= 0) && ((*c) == (res->a[i]>>14)); i--) { - if((*c) == 1 || (*c) == 2) { - sb = ((res->a[i]>>12)&3); sl = (res->a[i]&(0xfff)); - } else { - sb = (uint16_t)-1; sl = (res->a[i]&(0x3fff)); - } - if((*b) != sb) break; - (*len) += sl; - } - return i; -} - -///full functions -#define pop_trac_bpc_f(in, rc, rbq, rbt, rl) do { \ - (rc) = ((in)>>14);\ - if((rc) == 2 || (rc) == 3) {(rbt) = (((in)>>12)&3); (rl) = ((in)&(0xfff));}\ - else if((rc) == 1) {(rbt) = (((in)>>12)&3); (rbq) = (((in)>>10)&3); (rl) = ((in)&(0x3ff));}\ - else {(rl) = ((in)&(0x3fff));}\ - } while (0) - -inline void push_trace_bp_f(asg16_v *res, uint16_t c, uint16_t bq, uint16_t bt, uint32_t len, uint32_t is_append) -{ - uint16_t p, c0 = c, bq0, bt0, len0, mm; - if(c == 3) { - bt = bq; bq = (uint16_t)-1; - } - if((is_append) && (res->n)) { - bq0 = bq; bt0 = bt; - pop_trac_bpc_f(res->a[res->n-1], c0, bq0, bt0, len0); - if((c == c0) && (bq == bq0) && (bt == bt0)) { - res->n--; len += len0; - } - } - - - c0 = c; c <<= 14; - if(c0 == 2 || c0 == 3) { - mm = (0xfff); c += ((bt&3) << 12); - } else if(c0 == 1) { - mm = (0x3ff); c += ((bt&3) << 12); c += ((bq&3) << 10); - } else { - mm = (0x3fff); - } - - - while (len >= mm) { - p = (c + mm); kv_push(uint16_t, *res, p); len -= mm; - } - // fprintf(stderr, "[M::%s] c::%u, len::%u\n", __func__, c, len); - if(len) { - p = (c + len); kv_push(uint16_t, *res, p); - } -} - -inline uint32_t pop_trace_bp_f(asg16_v *res, uint32_t i, uint16_t *c, uint16_t *bq, uint16_t *bt, uint32_t *len) -{ - (*c) = (res->a[i]>>14); (*bq) = (*bt) = (uint16_t)-1; - if((*c) == 2 || (*c) == 3) { - (*bt) = ((res->a[i]>>12)&3); - (*len) = (res->a[i]&(0xfff)); - } else if((*c) == 1) { - (*bt) = ((res->a[i]>>12)&3); - (*bq) = ((res->a[i]>>10)&3); - (*len) = (res->a[i]&(0x3ff)); - } else { - (*len) = (res->a[i]&(0x3fff)); - } - - uint32_t sl; uint16_t sbq, sbt; - for (i++; (i < res->n) && ((*c) == (res->a[i]>>14)); i++) { - sbq = sbt = (uint16_t)-1; - if((*c) == 2 || (*c) == 3) { - sbt = ((res->a[i]>>12)&3); - sl = (res->a[i]&(0xfff)); - } else if((*c) == 1) { - sbt = ((res->a[i]>>12)&3); - sbq = ((res->a[i]>>10)&3); - sl = (res->a[i]&(0x3ff)); - } else { - sl = (res->a[i]&(0x3fff)); - } - if((*bq) != sbq || (*bt) != sbt) break; - (*len) += sl; - } - if((*c) == 3) { - (*bq) = (*bt); (*bt) = (uint16_t)-1; - } - return i; -} - -inline int64_t pop_trace_bp_rev_f(asg16_v *res, int64_t i, uint16_t *c, uint16_t *bq, uint16_t *bt, uint32_t *len) -{ - (*c) = (res->a[i]>>14); (*bq) = (*bt) = (uint16_t)-1; - if((*c) == 2 || (*c) == 3) { - (*bt) = ((res->a[i]>>12)&3); - (*len) = (res->a[i]&(0xfff)); - } else if((*c) == 1) { - (*bt) = ((res->a[i]>>12)&3); - (*bq) = ((res->a[i]>>10)&3); - (*len) = (res->a[i]&(0x3ff)); - } else { - (*len) = (res->a[i]&(0x3fff)); - } - - uint32_t sl; uint16_t sbq, sbt; - for (i--; (i >= 0) && ((*c) == (res->a[i]>>14)); i--) { - sbq = sbt = (uint16_t)-1; - if((*c) == 2 || (*c) == 3) { - sbt = ((res->a[i]>>12)&3); - sl = (res->a[i]&(0xfff)); - } else if((*c) == 1) { - sbt = ((res->a[i]>>12)&3); - sbq = ((res->a[i]>>10)&3); - sl = (res->a[i]&(0x3ff)); - } else { - sl = (res->a[i]&(0x3fff)); - } - if((*bq) != sbq || (*bt) != sbt) break; - (*len) += sl; - } - if((*c) == 3) { - (*bq) = (*bt); (*bt) = (uint16_t)-1; - } - return i; -} - -///511 -> 16 64-bits -// #define MAX_E 511 -// #define MAX_L 2500 - -///511 -> 32 64-bits -#define MAX_CNS_E 1023 -#define MAX_CNS_L 3072 -#define FORCE_CNS_L 256 - - -#define MAX_SIN_E 2047 -#define MAX_SIN_L 10000 -#define FORCE_SIN_L 512 - -typedef uint64_t w_sig; -#define bitw (6) -#define bitwbit (64) -#define bitz (63) -// typedef uint32_t w_sig; -// #define bitw (5) -// #define bitwbit (32) -// #define bitz (31) -// typedef uint16_t w_sig; -// #define bitw (4) -// #define bitwbit (16) -// #define bitz (15) -// typedef uint8_t w_sig; -// #define bitw (3) -// #define bitwbit (8) -// #define bitz (7) -typedef struct {w_sig *a;} w128_t; -typedef struct {size_t n, m; w_sig *a;} w64_trace_t; -typedef struct { - int32_t done_cigar, cigar_n, done_path, path_n; - int32_t ps, pe, pl, ts, te, tl; - int32_t thre, err, nword, mword; - uint32_t m, mm_thres; w_sig *a; - w128_t Peq[5], mm, VP, VN, X, D0, HN, HP; - asg16_v cigar; w64_trace_t path; -} bit_extz_t; - -#define is_align(exz) ((exz).err<=(exz).thre) -#define clear_align(exz) ((exz).err=INT32_MAX) - -inline uint32_t cigar_check(char *pstr, char *tstr, bit_extz_t *ez) -{ - int32_t pi = ez->ps, ti = ez->ts, err = 0; uint32_t ci = 0, cl, k; uint16_t c; - while (ci < ez->cigar.n) { - ci = pop_trace(&(ez->cigar), ci, &c, &cl); - // fprintf(stderr, "# %u = %u\n", c, cl); - if(c == 0) { - for (k=0;(kerr) { - fprintf(stderr, "ERROR-err\n"); - return 0; - } - return 1; -} - -inline int32_t dbg_ext_err(int32_t i, int32_t thre, int32_t err, int32_t pe, w128_t *VP, w128_t *VN) -{ - int32_t poff = i-thre, tmp_e = INT32_MAX, k, bd, k_bd; - if((poff) + (thre<<1) >= (pe)) { - tmp_e = err; - for ((k) = 0; (poff) < (pe); (poff)++) { - bd = (k>>bitw); k_bd = (k&bitz); - (tmp_e) += ((VP->a[bd]>>k_bd)&((w_sig)1)); - (tmp_e) -= ((VN->a[bd]>>k_bd)&((w_sig)1)); - (k)++; - } - } - return tmp_e; -} - - -inline void print_bits(w_sig *az, int64_t w, const char *cmd) -{ - int64_t k, m, s = (sizeof(*az)<<3), sw = (w/s) + (!!(w%s)), ks; - fprintf(stderr, "%s\t", cmd); - for (m = sw - 1, k = w-1; m >= 0 && k >= 0; m--) { - for (ks = k%s; ks >= 0 && k >= 0; ks--, k--) fprintf(stderr, "%llu", (az[m]>>ks)&(1ULL)); - } - fprintf(stderr, "\n"); -} - -#define prt_bit_extz_t(ez, w) do { \ - print_bits((ez).Peq[0].a, w, "Peq[0]");\ - print_bits((ez).Peq[1].a, w, "Peq[1]");\ - print_bits((ez).Peq[2].a, w, "Peq[2]");\ - print_bits((ez).Peq[3].a, w, "Peq[3]");\ - print_bits((ez).Peq[4].a, w, "Peq[4]");\ - print_bits((ez).VP.a, w, "VP");\ - print_bits((ez).VN.a, w, "VN");\ - print_bits((ez).X.a, w, "X");\ - print_bits((ez).D0.a, w, "D0");\ - print_bits((ez).HN.a, w, "HN");\ - print_bits((ez).HP.a, w, "HP");\ -} while (0) - - - -#define resize_bit_extz_t(ex, thres) do { \ - if(((int32_t)(thres)) > ((int32_t)(ex).mm_thres)) {\ - (ex).mm_thres = (((thres)<<1)+1);\ - (ex).mm_thres = (((ex).mm_thres>>bitw)+(!!((ex).mm_thres&bitz)))*12;\ - if((ex).mm_thres > (ex).m) {\ - (ex).a = (w_sig *)realloc((ex).a, (ex).mm_thres * sizeof(*((ex).a)));\ - (ex).mm_thres/=12; (ex).m=0;\ - (ex).Peq[0].a = (ex).a; (ex).m+=(ex).mm_thres;\ - (ex).Peq[1].a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ - (ex).Peq[2].a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ - (ex).Peq[3].a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ - (ex).Peq[4].a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ - (ex).mm.a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ - (ex).VP.a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ - (ex).VN.a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ - (ex).X.a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ - (ex).D0.a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ - (ex).HN.a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ - (ex).HP.a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ - (ex).mword = (ex).mm_thres;\ - }\ - (ex).mm_thres = (thres);\ - }\ - } while (0) - -inline void init_bit_extz_t(bit_extz_t *ex, uint64_t thres) { - memset(ex, 0, sizeof((*ex))); - ///(bitwbit<<2) >= (((thres)<<1)+1);->at least 4 cells for each w128_t - if(((uint64_t)thres)<(((((uint64_t)bitwbit)<<2)-1)>>1)) thres=(((bitwbit<<2)-1)>>1); - resize_bit_extz_t((*ex), (thres)); -} - -inline void destroy_bit_extz_t(bit_extz_t *ex) { - free((*ex).a); free((*ex).path.a); free((*ex).cigar.a); -} - - -inline void gen_trace(bit_extz_t *ez, int32_t ptrim, int32_t reverse)///ptrim = thre for global and extension; = 0 for semi -{ - if(ez->err > ez->thre) return; - ez->cigar.n = 0; - int32_t V, H, D, min, cur, tn = (ez->te+1-ez->ts), pn = tn + (ez->thre<<1), bd = (ez->thre<<1)+1; - int32_t bs = ez->path.n/tn, bbs = bs/5, poff = ez->pe, sft = bd - (pn - ez->pe - ptrim); - int32_t i = tn, low = bd-1, wi, wm, d = 0, pd = -1, pdn = 0; cur = ez->err; - w_sig *D0, *VP, *VN, *HP, *HN; - - // fprintf(stderr, "\n[M::%s::] bs::%d, bbs::%d, cur::%d, poff::%d, sft::%d\n", __func__, bs, bbs, cur, poff, sft); - - while (i > 0 && cur > 0) { - D0 = ez->path.a + ((i-1)*bs); VP = D0 + bbs; VN = VP + bbs; HP = VN + bbs; HN = HP + bbs; - - wi = (sft>>bitw); wm = sft&bitz; - D = cur - ((~(D0[wi]>>wm))&(1ULL)); d = 0; min = D; - H = V = INT32_MAX; - if(sft!=low) { - H = cur + ((HN[wi]>> wm)&(1ULL)) - ((HP[wi]>> wm)&(1ULL)); - if ((H+1) == cur && H <= min) {//prefer indels - min = H; d = 3; - } - } - if(sft!=0) { - wi = ((sft-1)>>bitw); wm = (sft-1)&bitz; - V = cur + ((VN[wi]>> wm)&(1ULL)) - ((VP[wi]>> wm)&(1ULL)); - if ((V+1) == cur && V <= min) {//prefer indels - min = V; d = 2; - } - } - // fprintf(stderr, "[M::%s::] cur::%d, D::%d, V::%d, H::%d, poff::%d, toff::%d, d::%d\n", __func__, cur, D, V, H, poff, i, d); - if(d == 0) { - if(D != cur) d = 1; - i--; poff--; - } else if(d == 2) {//more pstr - sft--; poff--; - } else if(d == 3) {///more tstr - i--; sft++; - } - - if(d == pd) { - pdn++; - } else { - if(pdn > 0) push_trace(&(ez->cigar), pd, pdn); - pd = d; pdn = 1; - } - cur = min; - } - - if (i > 0) { - d = 0; poff -= i; - if(d == pd) { - pdn += i; - } else { - if(pdn > 0) push_trace(&(ez->cigar), pd, pdn); - pd = d; pdn = i; - } - } - - poff++; - // fprintf(stderr, "[M::%s::] poff::%d, ez->ps::%d\n", __func__, poff, ez->ps); - if(ez->ps < 0 || ez->ps >= ez->pl) {//ps is unavailable - ez->ps = poff; - } else if(poff > ez->ps){ - d = 2; i = poff - ez->ps; - if(d == pd) { - pdn += i; - } else { - if(pdn > 0) push_trace(&(ez->cigar), pd, pdn); - pd = d; pdn = i; - } - } - if(pdn > 0) push_trace(&(ez->cigar), pd, pdn); - - if(reverse) { - uint16_t t; pdn = ez->cigar.n>>1; - for (i = 0; i < pdn; i++) { - t = ez->cigar.a[i]; - ez->cigar.a[i] = ez->cigar.a[ez->cigar.n-i-1]; - ez->cigar.a[ez->cigar.n-i-1] = t; - } - } -} - - - -#define init_base_ed(ez, thre, pn, tn) {\ - (ez).thre = (thre), (ez).err = INT32_MAX, (ez).pl = pn, (ez).tl = tn;\ - (ez).done_cigar = (ez).done_path = (ez).cigar_n = (ez).path_n = 0;\ -} - -#define w_bit(x, b) ((x).a[((b)>>bitw)]|=(((w_sig)1)<<((b)&bitz))) - -#define w_get_bit(x, b) (((x).a[((b)>>bitw)]>>((b)&bitz))&((w_sig)1)) - -/***********************2 words***********************/ -#define w_128_clear(x) ((x).a[0]=(x).a[1]=0) - -#define w_128_word (2) - -#define w_128_self_not(x) ((x).a[0]=~(x).a[0], \ - (x).a[1]=~(x).a[1]) - -#define w_128_self_or(x, y) ((x).a[0]|=(y).a[0], \ - (x).a[1]|=(y).a[1]) - -#define w_128_or(r, x, y) ((r).a[0] = (x).a[0]|(y).a[0], \ - (r).a[1] = (x).a[1]|(y).a[1]) - -#define w_128_and(r, x, y) ((r).a[0] = (x).a[0]&(y).a[0], \ - (r).a[1] = (x).a[1]&(y).a[1]) - -#define w_128_self_xor(x, y) ((x).a[0]^=(y).a[0], \ - (x).a[1]^=(y).a[1]) - -#define w_128_self_lsft_1(x) ((x).a[1] = ((x).a[1]<<1)|((x).a[0]>>bitz), \ - (x).a[0] <<= 1) - -#define w_128_self_rsft_1(x) ((x).a[0] = ((x).a[0]>>1)|((x).a[1]<>= 1) - -#define w_128_rsft_1(x, y) ((x).a[0] = ((y).a[0]>>1)|((y).a[1]<>1) -#define w_128_self_add(x, y, c) ((x).a[0]+=(y).a[0], \ - (x).a[1]+=(y).a[1]+((x).a[0]<(y).a[0])) - -#define w_128_set_bit_lsub(x, l) do { \ - (x).a[0] = (w_sig)-1, (x).a[1] = 0; \ - if((l) <= bitwbit) (x).a[0] = (((w_sig)1)<<(l))-1; \ - else (x).a[1] = (((w_sig)1)<<((l)-bitwbit))-1;\ - } while (0) \ - -#define w_128_copy(x, y) ((x).a[0]=(y).a[0], (x).a[1]=(y).a[1]) - -/***********************3 words***********************/ -#define w_192_clear(x) ((x).a[0]=(x).a[1]=(x).a[2]=0) - -#define w_192_word (3) - -#define w_192_self_not(x) ((x).a[0]=~(x).a[0],\ - (x).a[1]=~(x).a[1],\ - (x).a[2]=~(x).a[2]) - -#define w_192_self_or(x, y) ((x).a[0]|=(y).a[0],\ - (x).a[1]|=(y).a[1],\ - (x).a[2]|=(y).a[2]) - -#define w_192_or(r, x, y) ((r).a[0]=(x).a[0]|(y).a[0],\ - (r).a[1] = (x).a[1]|(y).a[1],\ - (r).a[2] = (x).a[2]|(y).a[2]) - -#define w_192_and(r, x, y) ((r).a[0] = (x).a[0]&(y).a[0], \ - (r).a[1] = (x).a[1]&(y).a[1], \ - (r).a[2] = (x).a[2]&(y).a[2]) - -#define w_192_self_xor(x, y) ((x).a[0]^=(y).a[0], \ - (x).a[1]^=(y).a[1], \ - (x).a[2]^=(y).a[2]) - -#define w_192_self_lsft_1(x) ((x).a[2] = ((x).a[2]<<1)|((x).a[1]>>bitz), \ - (x).a[1] = ((x).a[1]<<1)|((x).a[0]>>bitz), \ - (x).a[0] <<= 1) - -#define w_192_self_rsft_1(x) ((x).a[0] = ((x).a[0]>>1)|((x).a[1]<>1)|((x).a[2]<>= 1) - -#define w_192_rsft_1(x, y) ((x).a[0] = ((y).a[0]>>1)|((y).a[1]<>1)|((y).a[2]<>1) - -#define w_192_self_add(x, y, c) ((x).a[0]+=(y).a[0], c=((x).a[0]<(y).a[0]),\ - (x).a[1]+=c, c=((x).a[1]>bitw) memset((x).a, -1, sizeof(*((x).a))*((l)>>bitw));\ - if((l)&bitz) (x).a[(l)>>bitw] = (((w_sig)1)<<((l)&bitz))-1; \ - } while (0) \ - -#define w_192_copy(x, y) ((x).a[0]=(y).a[0], (x).a[1]=(y).a[1], (x).a[2]=(y).a[2]) - -/***********************4 words***********************/ -#define w_256_clear(x) ((x).a[0]=(x).a[1]=(x).a[2]=(x).a[3]=0) - -#define w_256_word (4) - -#define w_256_self_not(x) ((x).a[0]=~(x).a[0],\ - (x).a[1]=~(x).a[1],\ - (x).a[2]=~(x).a[2],\ - (x).a[3]=~(x).a[3]) - -#define w_256_self_or(x, y) ((x).a[0]|=(y).a[0],\ - (x).a[1]|=(y).a[1],\ - (x).a[2]|=(y).a[2],\ - (x).a[3]|=(y).a[3]) - -#define w_256_or(r, x, y) ((r).a[0]=(x).a[0]|(y).a[0],\ - (r).a[1] = (x).a[1]|(y).a[1],\ - (r).a[2] = (x).a[2]|(y).a[2],\ - (r).a[3] = (x).a[3]|(y).a[3]) - -#define w_256_and(r, x, y) ((r).a[0] = (x).a[0]&(y).a[0], \ - (r).a[1] = (x).a[1]&(y).a[1], \ - (r).a[2] = (x).a[2]&(y).a[2], \ - (r).a[3] = (x).a[3]&(y).a[3]) - -#define w_256_self_xor(x, y) ((x).a[0]^=(y).a[0], \ - (x).a[1]^=(y).a[1], \ - (x).a[2]^=(y).a[2],\ - (x).a[3]^=(y).a[3]) - -#define w_256_self_lsft_1(x) ((x).a[3] = ((x).a[3]<<1)|((x).a[2]>>bitz), \ - (x).a[2] = ((x).a[2]<<1)|((x).a[1]>>bitz), \ - (x).a[1] = ((x).a[1]<<1)|((x).a[0]>>bitz), \ - (x).a[0] <<= 1) - -#define w_256_self_rsft_1(x) ((x).a[0] = ((x).a[0]>>1)|((x).a[1]<>1)|((x).a[2]<>1)|((x).a[3]<>= 1) - -#define w_256_rsft_1(x, y) ((x).a[0] = ((y).a[0]>>1)|((y).a[1]<>1)|((y).a[2]<>1)|((y).a[3]<>1) - -#define w_256_self_add(x, y, c) ((x).a[0]+=(y).a[0], c=((x).a[0]<(y).a[0]),\ - (x).a[1]+=c, c=((x).a[1]>bitw) memset((x).a, -1, sizeof(*((x).a))*((l)>>bitw));\ - if((l)&bitz) (x).a[(l)>>bitw] = (((w_sig)1)<<((l)&bitz))-1; \ - } while (0) - -#define w_256_copy(x, y) ((x).a[0]=(y).a[0], (x).a[1]=(y).a[1], (x).a[2]=(y).a[2], (x).a[3]=(y).a[3]) - -#define cmp_Word(des, src, dd, ws) {\ - for ((dd)=0;(dd)<64;dd+=bitwbit){\ - if((((des)>>dd)&((w_sig)-1))!=(src).a[dd>>bitw]) break;\ - }\ - if((dd)<64) {\ - print_bit((des), (ws), "des");\ - print_bits((src).a, (ws), "src");\ - exit(0);\ - }\ -} - -#define dump_Word(des, src, dd, ws) {\ - for ((dd)=bitwbit,(des)=((Word)(src).a[0]);(dd)<64;dd+=bitwbit) {\ - (des) |= ((Word)(src).a[dd>>bitw])<> 1;**/\ - w##sf##copy((X), (D0));\ - prt_address(Peq, VP, VN, X, D0, HN, HP);\ - X_d = D0_d; fprintf(stderr, "X=D0\n"); cmp_Word(X_d, (X), dd, ws);\ - w##sf##self_rsft_1((X)); \ - prt_address(Peq, VP, VN, X, D0, HN, HP);\ - X_d >>= 1; fprintf(stderr, "X>>=1\n"); cmp_Word(X_d, (X), dd, ws);\ - /**VN = X&HP;**/\ - w##sf##and((VN), (X), (HP));\ - prt_address(Peq, VP, VN, X, D0, HN, HP);\ - VN_d = X_d&HP_d; fprintf(stderr, "VN=X&HP\n"); cmp_Word(VN_d, (VN), dd, ws);\ - /**VP = HN | ~(X | HP);**/\ - w##sf##or((VP), (X), (HP));\ - prt_address(Peq, VP, VN, X, D0, HN, HP);\ - VP_d = X_d|HP_d; fprintf(stderr, "VP=X|HP\n"); cmp_Word(VP_d, (VP), dd, ws);\ - w##sf##self_not((VP));\ - prt_address(Peq, VP, VN, X, D0, HN, HP);\ - VP_d = ~VP_d; fprintf(stderr, "VP=~VP\n"); cmp_Word(VP_d, (VP), dd, ws);\ - w##sf##self_or((VP), (HN));\ - prt_address(Peq, VP, VN, X, D0, HN, HP);\ - VP_d |= HN_d; fprintf(stderr, "VP|=HN\n"); cmp_Word(VP_d, (VP), dd, ws);\ -} - -#define ed_core(sf, Peq, VP, VN, X, D0, HN, HP, z, c) { \ - /**X = Peq[seq_nt4_table[(uint8_t)tstr[i]]] | VN;**/\ - (c) = seq_nt4_table[(z)];\ - w##sf##or((X), (Peq)[(c)], (VN));\ - /**D0 = ((VP + (X&VP)) ^ VP) | X;**/\ - w##sf##and((D0), (X), (VP));\ - w##sf##self_add((D0), (VP), (c));\ - w##sf##self_xor((D0), (VP));\ - w##sf##self_or((D0), (X));\ - /**HN = VP&D0;**/\ - w##sf##and((HN), (VP), (D0));\ - /**HP = VN | ~(VP | D0);**/\ - w##sf##or((HP), (VP), (D0));\ - w##sf##self_not((HP));\ - w##sf##self_or((HP), (VN));\ - /**X = D0 >> 1;**/\ - /**w##sf##copy((X), (D0));w##sf##self_rsft_1((X));**/\ - w##sf##rsft_1((X), (D0));\ - /**VN = X&HP;**/\ - w##sf##and((VN), (X), (HP));\ - /**VP = HN | ~(X | HP);**/\ - w##sf##or((VP), (X), (HP));\ - w##sf##self_not((VP));\ - w##sf##self_or((VP), (HN));\ -} - -#define ed_init_core(i, bd, i_bd, S, Peq) { \ - for ((i) = 0; (i) < (bd); (i)++) {\ - w_bit((Peq)[seq_nt4_table[(uint8_t)(S)[(i)]]], (i_bd));i_bd++;\ - }\ -} - -#define HA_ED_INIT(sf)\ -inline void ed_band_cal_global_##sf##_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ -{\ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0;\ - if((pn > tn + thre) || (tn > pn + thre)) return;\ - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, Peq_i; w_sig c, Peq_m;\ - w_##sf##_clear(ez->Peq[0]); w_##sf##_clear(ez->Peq[1]); w_##sf##_clear(ez->Peq[2]); w_##sf##_clear(ez->Peq[3]); w_##sf##_clear(ez->Peq[4]);\ - \ - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre;\ - ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ - bd = thre+1, i_bd = thre;\ - \ - w_##sf##_clear(ez->Peq[4]);\ - err = thre;\ - w_##sf##_set_bit_lsub(ez->VN, thre); /**VN = (((Word)1)<<(thre))-1;**/\ - w_##sf##_set_bit_lsub(ez->VP, (thre<<1)+1); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/\ - w_##sf##_self_xor(ez->VP, ez->VN); /**VP ^= VN;**/\ - \ - /** print_bits(VP.a, (thre<<1)+1, "-VP");**/\ - /**should make Peq[4] = 0 if N is always an error**/\ - i = 0; \ - /**for the incoming char/last char**/\ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ - while (i < tn0) {\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ - w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ - w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ - \ - ++i; ++i_bd; c = 4;\ - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ - }\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - \ - int32_t site = tn - 1 - thre;/**up bound**/\ - for (cut = pn - 1, i = 0; site < cut; site++, i++) {\ - bd = (i>>bitw); i_bd = (i&bitz);\ - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ - }\ - \ - if (site == cut && err <= thre) {\ - ez->err = err; \ - ez->pe = pn-1; ez->te = tn-1;\ - }\ - return;\ -}\ -inline void ed_band_cal_semi_##sf##_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ -{\ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1;\ - int32_t bd, i, err = 0, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, Peq_i; w_sig c, Peq_m;\ - if((pn > tn + cut) || (tn > pn + cut)) return;\ - \ - w_##sf##_clear(ez->Peq[0]);\ - w_##sf##_clear(ez->Peq[1]);\ - w_##sf##_clear(ez->Peq[2]);\ - w_##sf##_clear(ez->Peq[3]);\ - w_##sf##_clear(ez->Peq[4]);\ - w_##sf##_clear(ez->VP);\ - w_##sf##_clear(ez->VN);\ - \ - bd = (thre<<1)+1; bd = ((bd<=pn)?bd:pn); i_bd = 0;\ - ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ - bd = (thre<<1)+1, i_bd = (thre<<1);\ - \ - w_##sf##_clear(ez->Peq[4]);\ - i = 0;\ - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ - while (i < tn0) {\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ - w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ - w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ - ++i; ++i_bd; c = 4;\ - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ - }\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - \ - int32_t site = tn - 1;/**up bound**/\ - /**in most cases, ai = (thre<<1)**/\ - int32_t ai = pn - tn, uge = INT32_MAX;\ - if ((err <= thre) && (err <= ez->err)) {\ - ez->err = err; ez->pe = site;\ - }\ - \ - i = 0;\ - while (i < ai) {\ - bd = (i>>bitw); i_bd = (i&bitz);\ - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ - ++i;\ - if ((err <= thre) && (err <= ez->err)) {\ - ez->err = err; ez->pe = site + i;\ - }\ - if(i == thre) uge = err;\ - }\ - \ - if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre;\ -}\ -/**require:: (pn >= tn - thre && pn <= tn + thre)**/\ -inline void ed_band_cal_extension_##sf##_0_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ -{\ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; ez->pe = ez->te = -1;\ - if(pn > tn + thre) pn = tn + thre;\ - else if(tn > pn + thre) tn = pn + thre;\ - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, Peq_i; w_sig c, Peq_m;\ - int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k;\ - \ - w_##sf##_clear(ez->Peq[0]);\ - w_##sf##_clear(ez->Peq[1]);\ - w_##sf##_clear(ez->Peq[2]);\ - w_##sf##_clear(ez->Peq[3]);\ - w_##sf##_clear(ez->Peq[4]);\ - \ - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre;\ - ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ - bd = thre+1, i_bd = thre;\ - \ - w_##sf##_clear(ez->Peq[4]);\ - err = thre;\ - w_##sf##_set_bit_lsub(ez->VN, thre); /**VN = (((Word)1)<<(thre))-1; **/\ - w_##sf##_set_bit_lsub(ez->VP, (thre<<1)+1); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/\ - w_##sf##_self_xor(ez->VP, ez->VN); /**VP ^= VN;**/\ - \ - /** print_bits(ez->VP.a, (thre<<1)+1, "-VP");**/\ - /**should make Peq[4] = 0 if N is always an error**/\ - i = 0; \ - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ - while (i < tn0) {\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - \ - {\ - poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/\ - if(k >= 0) {\ - if(tmp_e == INT32_MAX) {\ - tmp_e = err;\ - for ((k) = 0; (poff) < (pe); (poff)++, (k)++) {\ - bd = (k>>bitw); k_bd = (k&bitz);\ - (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1));\ - (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1));\ - }\ - } else {\ - k = (thre<<1) - k;\ - if(k >= 0) {\ - bd = (k>>bitw); k_bd = (k&bitz);\ - (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1));\ - (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1));\ - }\ - }\ - if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) {\ - (*ez).err = tmp_e; (*ez).pe = pe; (*ez).te = i;\ - }\ - }\ - /**if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e)**/\ - }\ - \ - /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ - w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ - w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ - ++i; ++i_bd; c = 4;\ - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ - }\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - \ - int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/\ - for (cut = pn - 1, i = 0; site < cut; i++) {\ - bd = (i>>bitw); i_bd = (i&bitz);\ - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ - site++;\ - if(err <= thre && err < ez->err) {\ - ez->err = err; ez->pe = site; ez->te = tn-1;\ - }\ - }\ - if(err <= thre && err < ez->err) {\ - ez->err = err; ez->pe = site; ez->te = tn-1;\ - }\ - return;\ -}\ -/**require:: (pn >= tn - thre && pn <= tn + thre)**/\ -inline void ed_band_cal_extension_##sf##_1_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ -{\ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = INT32_MAX; ez->pe = pn-1; ez->te = tn-1;\ - if(pn > tn + thre) pn = tn + thre;\ - else if(tn > pn + thre) tn = pn + thre;\ - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, Peq_i; w_sig c, Peq_m;\ - int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k, pidx = ez->pe, tidx = ez->te;\ - \ - w_##sf##_clear(ez->Peq[0]);\ - w_##sf##_clear(ez->Peq[1]);\ - w_##sf##_clear(ez->Peq[2]);\ - w_##sf##_clear(ez->Peq[3]);\ - w_##sf##_clear(ez->Peq[4]);\ - \ - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre;\ - for (i = 0; i < bd; i++, i_bd++) {\ - w_bit((ez->Peq)[seq_nt4_table[(uint8_t)(pstr)[pidx-i]]], (i_bd));\ - }\ - bd = thre+1, i_bd = thre;\ - \ - w_##sf##_clear(ez->Peq[4]);\ - err = thre;\ - w_##sf##_set_bit_lsub(ez->VN, thre); /**VN = (((Word)1)<<(thre))-1; **/\ - w_##sf##_set_bit_lsub(ez->VP, (thre<<1)+1); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/\ - w_##sf##_self_xor(ez->VP, ez->VN); /**VP ^= VN;**/\ - \ - /** print_bits(ez->VP.a, (thre<<1)+1, "-VP");**/\ - /**should make Peq[4] = 0 if N is always an error**/\ - i = 0; \ - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ - while (i < tn0) {\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - \ - {\ - poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/\ - if(k >= 0) {\ - if(tmp_e == INT32_MAX) {\ - tmp_e = err;\ - for ((k) = 0; (poff) < (pe); (poff)++, (k)++) {\ - bd = (k>>bitw); k_bd = (k&bitz);\ - (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1));\ - (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1));\ - }\ - } else {\ - k = (thre<<1) - k;\ - if(k >= 0) {\ - bd = (k>>bitw); k_bd = (k&bitz);\ - (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1));\ - (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1));\ - }\ - }\ - if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) {\ - (*ez).err = tmp_e; (*ez).ps = pidx - pe; (*ez).ts = tidx-i;\ - }\ - }\ - /**if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e)**/\ - }\ - \ - /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ - w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ - w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ - ++i; ++i_bd; c = 4;\ - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[pidx-i_bd]];\ - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ - }\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - \ - int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/\ - for (cut = pn - 1, i = 0; site < cut; i++) {\ - bd = (i>>bitw); i_bd = (i&bitz);\ - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ - site++;\ - if(err <= thre && err < ez->err) {\ - ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn;\ - }\ - }\ - if(err <= thre && err < ez->err) {\ - ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn;\ - }\ - return;\ -}\ -inline void ed_band_cal_global_##sf##_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ -{\ - ez->cigar.n = 0; ez->nword = w_##sf##_word;\ - if(ez->err > thre) {\ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0;\ - } else if(ez->err == 0) {\ - push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;\ - }\ - if((pn > tn + thre) || (tn > pn + thre)) return;\ - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, ws, Peq_i; w_sig c, Peq_m;\ - w_##sf##_clear(ez->Peq[0]); w_##sf##_clear(ez->Peq[1]); w_##sf##_clear(ez->Peq[2]); w_##sf##_clear(ez->Peq[3]); w_##sf##_clear(ez->Peq[4]);\ - \ - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre;\ - ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ - bd = thre+1, i_bd = thre;\ - \ - w_##sf##_clear(ez->Peq[4]);\ - err = thre;\ - w_##sf##_set_bit_lsub(ez->VN, thre); /**VN = (((Word)1)<<(thre))-1;**/\ - w_##sf##_set_bit_lsub(ez->VP, (thre<<1)+1); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/\ - w_##sf##_self_xor(ez->VP, ez->VN); /**VP ^= VN;**/\ - \ - /** print_bits(VP.a, (thre<<1)+1, "-VP");**/\ - /**should make Peq[4] = 0 if N is always an error**/\ - i = 0; ws = sizeof(*(ez->a))*(ez->nword);\ - ez->path.n=(ez->nword*tn*5);\ - kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;\ - \ - /**for the incoming char/last char**/\ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ - while (i < tn0) {\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ - w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ - w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ - \ - ++i; ++i_bd; c = 4;\ - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ - \ - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ - }\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ - \ - int32_t site = tn - 1 - thre;/**up bound**/\ - if(ez->err > thre) {\ - for (cut = pn - 1, i = 0; site < cut; site++, i++) {\ - bd = (i>>bitw); i_bd = (i&bitz);\ - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ - }\ - \ - if (site == cut && err <= thre) {\ - ez->err = err; \ - ez->pe = pn-1; ez->te = tn-1;\ - }\ - }\ - gen_trace(ez, thre, 1);\ - return;\ -}\ -inline void ed_band_cal_semi_##sf##_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ -{\ - ez->cigar.n = 0; ez->nword = w_##sf##_word;\ - if(ez->err > thre) {\ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1;\ - } else if(ez->err == 0) {\ - push_trace(&(ez->cigar), 0, ez->te+1-ez->ts);\ - ez->ps = ez->pe - (ez->te-ez->ts);\ - return;\ - }\ - int32_t bd, i, err = 0, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, Peq_i, ws; w_sig c, Peq_m;\ - if((pn > tn + cut) || (tn > pn + cut)) return;\ - \ - w_##sf##_clear(ez->Peq[0]);\ - w_##sf##_clear(ez->Peq[1]);\ - w_##sf##_clear(ez->Peq[2]);\ - w_##sf##_clear(ez->Peq[3]);\ - w_##sf##_clear(ez->Peq[4]);\ - w_##sf##_clear(ez->VP);\ - w_##sf##_clear(ez->VN);\ - \ - bd = (thre<<1)+1; bd = ((bd<=pn)?bd:pn); i_bd = 0;\ - ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ - bd = (thre<<1)+1, i_bd = (thre<<1);\ - \ - w_##sf##_clear(ez->Peq[4]);\ - i = 0; ws = sizeof(*(ez->a))*(ez->nword);\ - ez->path.n=(ez->nword*tn*5);\ - kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;\ - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ - while (i < tn0) {\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ - w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ - w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ - ++i; ++i_bd; c = 4;\ - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ - \ - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ - }\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ - \ - int32_t site = tn - 1;/**up bound**/\ - /**in most cases, ai = (thre<<1)**/\ - int32_t ai = pn - tn, uge = INT32_MAX;\ - if(ez->err > thre) {\ - if ((err <= thre) && (err <= ez->err)) {\ - ez->err = err; ez->pe = site;\ - }\ - \ - i = 0;\ - while (i < ai) {\ - bd = (i>>bitw); i_bd = (i&bitz);\ - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ - ++i;\ - if ((err <= thre) && (err <= ez->err)) {\ - ez->err = err; ez->pe = site + i;\ - }\ - if(i == thre) uge = err;\ - }\ - \ - if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre;\ - }\ - gen_trace(ez, 0, 1);\ -}\ -inline void ed_band_cal_extension_##sf##_0_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ -{\ - int32_t done = 1;\ - ez->cigar.n = 0; ez->nword = w_##sf##_word;\ - if(ez->err > thre) {\ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; ez->pe = ez->te = -1;\ - if(pn > tn + thre) pn = tn + thre;\ - else if(tn > pn + thre) tn = pn + thre;\ - done = 0;\ - } else if(ez->err == 0) {\ - push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;\ - } else {\ - pn = ez->pe + 1 - ez->ps; tn = ez->te + 1 - ez->ts;\ - }\ - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, Peq_i, ws; w_sig c, Peq_m;\ - int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k;\ - \ - w_##sf##_clear(ez->Peq[0]);\ - w_##sf##_clear(ez->Peq[1]);\ - w_##sf##_clear(ez->Peq[2]);\ - w_##sf##_clear(ez->Peq[3]);\ - w_##sf##_clear(ez->Peq[4]);\ - \ - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre;\ - ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ - bd = thre+1, i_bd = thre;\ - \ - w_##sf##_clear(ez->Peq[4]);\ - err = thre;\ - w_##sf##_set_bit_lsub(ez->VN, thre); /**VN = (((Word)1)<<(thre))-1; **/\ - w_##sf##_set_bit_lsub(ez->VP, (thre<<1)+1); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/\ - w_##sf##_self_xor(ez->VP, ez->VN); /**VP ^= VN;**/\ - \ - /** print_bits(ez->VP.a, (thre<<1)+1, "-VP");**/\ - /**should make Peq[4] = 0 if N is always an error**/\ - i = 0; ws = sizeof(*(ez->a))*(ez->nword);\ - ez->path.n=(ez->nword*tn*5);\ - kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;\ - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ - while (i < tn0) {\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - \ - if(!done) {\ - poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/\ - if(k >= 0) {\ - if(tmp_e == INT32_MAX) {\ - tmp_e = err;\ - for ((k) = 0; (poff) < (pe); (poff)++, (k)++) {\ - bd = (k>>bitw); k_bd = (k&bitz);\ - (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1));\ - (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1));\ - }\ - } else {\ - k = (thre<<1) - k;\ - if(k >= 0) {\ - bd = (k>>bitw); k_bd = (k&bitz);\ - (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1));\ - (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1));\ - }\ - }\ - if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) {\ - (*ez).err = tmp_e; (*ez).pe = pe; (*ez).te = i;\ - }\ - }\ - /**if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e)**/\ - }\ - \ - /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ - w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ - w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ - ++i; ++i_bd; c = 4;\ - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ - \ - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ - }\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ - \ - int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/\ - if(!done) {\ - for (cut = pn - 1, i = 0; site < cut; i++) {\ - bd = (i>>bitw); i_bd = (i&bitz);\ - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ - site++;\ - if(err <= thre && err < ez->err) {\ - ez->err = err; ez->pe = site; ez->te = tn-1;\ - }\ - }\ - if(err <= thre && err < ez->err) {\ - ez->err = err; ez->pe = site; ez->te = tn-1;\ - }\ - }\ - \ - if((ez->te-ez->ts+1) != tn) {\ - ez->path.n /= tn; ez->path.n *= (ez->te+1-ez->ts);\ - }\ - gen_trace(ez, thre, 1);\ - return;\ -}\ -inline void ed_band_cal_extension_##sf##_1_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ -{\ - int32_t done = 1;\ - ez->cigar.n = 0; ez->nword = w_##sf##_word;\ - if(ez->err > thre) {\ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = INT32_MAX; ez->pe = pn-1; ez->te = tn-1;\ - if(pn > tn + thre) pn = tn + thre;\ - else if(tn > pn + thre) tn = pn + thre;\ - done = 0;\ - } else if(ez->err == 0) {\ - push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;\ - } else {\ - pn = ez->pe + 1 - ez->ps; tn = ez->te + 1 - ez->ts;\ - }\ - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, Peq_i, ws; w_sig c, Peq_m;\ - int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k, pidx = ez->pe, tidx = ez->te;\ - \ - w_##sf##_clear(ez->Peq[0]);\ - w_##sf##_clear(ez->Peq[1]);\ - w_##sf##_clear(ez->Peq[2]);\ - w_##sf##_clear(ez->Peq[3]);\ - w_##sf##_clear(ez->Peq[4]);\ - \ - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre;\ - for (i = 0; i < bd; i++, i_bd++) {\ - w_bit((ez->Peq)[seq_nt4_table[(uint8_t)(pstr)[pidx-i]]], (i_bd));\ - }\ - bd = thre+1, i_bd = thre;\ - \ - w_##sf##_clear(ez->Peq[4]);\ - err = thre;\ - w_##sf##_set_bit_lsub(ez->VN, thre); /**VN = (((Word)1)<<(thre))-1; **/\ - w_##sf##_set_bit_lsub(ez->VP, (thre<<1)+1); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/\ - w_##sf##_self_xor(ez->VP, ez->VN); /**VP ^= VN;**/\ - \ - /** print_bits(ez->VP.a, (thre<<1)+1, "-VP");**/\ - /**should make Peq[4] = 0 if N is always an error**/\ - i = 0; ws = sizeof(*(ez->a))*(ez->nword);\ - ez->path.n=(ez->nword*tn*5);\ - kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;\ - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ - while (i < tn0) {\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - \ - if(!done) {\ - poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/\ - if(k >= 0) {\ - if(tmp_e == INT32_MAX) {\ - tmp_e = err;\ - for ((k) = 0; (poff) < (pe); (poff)++, (k)++) {\ - bd = (k>>bitw); k_bd = (k&bitz);\ - (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1));\ - (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1));\ - }\ - } else {\ - k = (thre<<1) - k;\ - if(k >= 0) {\ - bd = (k>>bitw); k_bd = (k&bitz);\ - (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1));\ - (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1));\ - }\ - }\ - if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) {\ - (*ez).err = tmp_e; (*ez).ps = pidx - pe; (*ez).ts = tidx-i;\ - }\ - }\ - /**if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e)**/\ - }\ - \ - /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ - w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ - w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ - ++i; ++i_bd; c = 4;\ - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[pidx-i_bd]];\ - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ - \ - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ - }\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ - \ - int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/\ - if(!done) {\ - for (cut = pn - 1, i = 0; site < cut; i++) {\ - bd = (i>>bitw); i_bd = (i&bitz);\ - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ - site++;\ - if(err <= thre && err < ez->err) {\ - ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn;\ - }\ - }\ - if(err <= thre && err < ez->err) {\ - ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn;\ - }\ - }\ - \ - if((ez->te-ez->ts+1) != tn) {\ - ez->path.n /= tn; ez->path.n *= (ez->te+1-ez->ts);\ - }\ - \ - poff = ez->ps; ez->ps = pidx - ez->pe; ez->pe = pidx - poff;\ - gen_trace(ez, thre, 0);\ - poff = ez->ps; ez->ps = pidx - ez->pe; ez->pe = pidx - poff;\ - return;\ -}\ -inline void ed_band_cal_semi_##sf##_w_absent_diag(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t abs_diag, bit_extz_t *ez)\ -{\ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1;\ - int32_t bd, i, err = abs_diag, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, Peq_i; w_sig c, Peq_m;\ - if((pn > tn + cut) || (tn > pn + cut)) return;\ - \ - w_##sf##_clear(ez->Peq[0]);\ - w_##sf##_clear(ez->Peq[1]);\ - w_##sf##_clear(ez->Peq[2]);\ - w_##sf##_clear(ez->Peq[3]);\ - w_##sf##_clear(ez->Peq[4]);\ - w_##sf##_clear(ez->VP);\ - w_##sf##_set_bit_lsub(ez->VN, abs_diag);\ - \ - bd = ((thre<<1)+1)-abs_diag; bd = ((bd<=pn)?bd:pn); i_bd = abs_diag; \ - ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ - i_bd = (thre<<1)-abs_diag;\ - \ - w_##sf##_clear(ez->Peq[4]);\ - i = 0;\ - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ - while (i < tn0) {\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ - w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ - w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ - ++i; ++i_bd; c = 4;\ - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ - }\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - \ - int32_t site = tn - 1 - abs_diag;/**up bound**/\ - /**in most cases, ai = (thre<<1)**/\ - int32_t ai = pn - tn + abs_diag, uge = INT32_MAX; i = 0;\ - for (i = 0; site < 0 && i < ai; i++, site++) {\ - bd = (i>>bitw); i_bd = (i&bitz);\ - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ - }\ - if ((err <= thre) && (err <= ez->err)) {\ - ez->err = err; ez->pe = site;\ - }\ - \ - site -= i;\ - while (i < ai) {\ - bd = (i>>bitw); i_bd = (i&bitz);\ - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ - ++i;\ - if ((err <= thre) && (err <= ez->err)) {\ - ez->err = err; ez->pe = site + i;\ - }\ - if(i == thre) uge = err;\ - }\ - \ - if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre;\ -}\ -inline void ed_band_cal_semi_##sf##_w_absent_diag_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t abs_diag, bit_extz_t *ez)\ -{\ - ez->cigar.n = 0; ez->nword = w_##sf##_word;\ - if(ez->err > thre) {\ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1;\ - } else if(ez->err == 0) {\ - push_trace(&(ez->cigar), 0, ez->te+1-ez->ts);\ - ez->ps = ez->pe - (ez->te-ez->ts);\ - return;\ - }\ - int32_t bd, i, err = abs_diag, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, Peq_i, ws; w_sig c, Peq_m;\ - if((pn > tn + cut) || (tn > pn + cut)) return;\ - \ - w_##sf##_clear(ez->Peq[0]);\ - w_##sf##_clear(ez->Peq[1]);\ - w_##sf##_clear(ez->Peq[2]);\ - w_##sf##_clear(ez->Peq[3]);\ - w_##sf##_clear(ez->Peq[4]);\ - w_##sf##_clear(ez->VP);\ - w_##sf##_set_bit_lsub(ez->VN, abs_diag);\ - \ - bd = ((thre<<1)+1)-abs_diag; bd = ((bd<=pn)?bd:pn); i_bd = abs_diag;\ - ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ - i_bd = (thre<<1)-abs_diag;\ - \ - w_##sf##_clear(ez->Peq[4]);\ - i = 0; ws = sizeof(*(ez->a))*(ez->nword);\ - ez->path.n=(ez->nword*tn*5);\ - kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;\ - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ - while (i < tn0) {\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ - w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ - w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ - ++i; ++i_bd; c = 4;\ - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ - \ - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ - }\ - ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ - if (!(ez->D0.a[0]&(1ULL))) {\ - ++err; if (err>cut) return;\ - }\ - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ - \ - int32_t site = tn - 1 - abs_diag;/**up bound**/\ - /**in most cases, ai = (thre<<1)**/\ - int32_t ai = pn - tn + abs_diag, uge = INT32_MAX; i = 0;\ - if(ez->err > thre) {\ - for (i = 0; site < 0 && i < ai; i++, site++) {\ - bd = (i>>bitw); i_bd = (i&bitz);\ - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ - }\ - if ((err <= thre) && (err <= ez->err)) {\ - ez->err = err; ez->pe = site;\ - }\ - \ - site -= i;\ - while (i < ai) {\ - bd = (i>>bitw); i_bd = (i&bitz);\ - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ - ++i;\ - if ((err <= thre) && (err <= ez->err)) {\ - ez->err = err; ez->pe = site + i;\ - }\ - if(i == thre) uge = err;\ - }\ - \ - if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre;\ - }\ - gen_trace(ez, abs_diag, 1);\ -}\ - -HA_ED_INIT(128) -HA_ED_INIT(192) -HA_ED_INIT(256) - - -#define w_infi_clear(x, nw) (memset((x).a, 0, sizeof(*((x).a))*(nw))) - -#define w_infi_set_bit_lsub(x, l, nw) do { \ - w_infi_clear(x, nw);\ - if((l)>>bitw) memset((x).a, -1, sizeof(*((x).a))*((l)>>bitw));\ - if((l)&bitz) (x).a[(l)>>bitw] = (((w_sig)1)<<((l)&bitz))-1; \ - } while (0) - -#define w_infi_self_xor(x, y, nw, w_z) {\ - for((w_z)=0; (w_z)<(nw); (w_z)++) (x).a[w_z]^=(y).a[w_z];} - -#define w_self_add_sin(x, y, w_z, ad) {\ - (x).a[(w_z)]+=(ad), (ad)=((x).a[(w_z)]<(ad)), (x).a[(w_z)]+=(y).a[(w_z)], (ad)|=((x).a[(w_z)]<(y).a[(w_z)]);} - -#define ed_infi_core(Peq, VP, VN, X, D0, HN, HP, z, c, ad, w_z, nw) {\ - (c) = seq_nt4_table[(z)];\ - for((w_z)=(ad)=0; (w_z)<(nw); (w_z)++){\ - /**X = Peq[seq_nt4_table[(uint8_t)tstr[i]]] | VN;**/\ - (X).a[(w_z)]=(Peq)[(c)].a[(w_z)]|(VN).a[(w_z)];\ - /**D0 = ((VP + (X&VP)) ^ VP) | X;**/\ - (D0).a[(w_z)]=(X).a[(w_z)]&(VP).a[(w_z)];\ - w_self_add_sin((D0), (VP), (w_z), (ad));\ - (D0).a[(w_z)]^=(VP).a[(w_z)];\ - (D0).a[(w_z)]|=(X).a[(w_z)];\ - /**HN = VP&D0;**/\ - (HN).a[(w_z)]=(VP).a[(w_z)]&(D0).a[(w_z)];\ - /**HP = VN | ~(VP | D0);**/\ - (HP).a[(w_z)]=~((VP).a[(w_z)]|(D0).a[(w_z)]);\ - (HP).a[(w_z)]|=(VN).a[(w_z)];\ - }\ - for((w_z)=(nw)-1,(ad)=0; (w_z)>=0; (w_z)--){\ - /**X = D0 >> 1;**/\ - (X).a[(w_z)]=((D0).a[(w_z)]>>1)|(ad),(ad)=(D0).a[(w_z)]<>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ - for((w_z)=0, (w_z1)=1; (w_z1)<(nw); (w_z)++,(w_z1)++){\ - Peq[0].a[(w_z)]=(Peq[0].a[(w_z)]>>1)|(Peq[0].a[(w_z1)]<>1)|(Peq[1].a[(w_z1)]<>1)|(Peq[2].a[(w_z1)]<>1)|(Peq[3].a[(w_z1)]<>=1;\ - Peq[1].a[(w_z)]>>=1;\ - Peq[2].a[(w_z)]>>=1;\ - Peq[3].a[(w_z)]>>=1;\ -} - -inline void ed_band_cal_global_infi_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) -{ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; - if((pn > tn + thre) || (tn > pn + thre)) return; - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, wz, wz1, Peq_i; w_sig c, ad, Peq_m; - if(nword) { - ez->nword = (*nword); - } else { - bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); - } - resize_bit_extz_t((*ez), (thre)); - wz = sizeof(*(ez->a))*(ez->nword); - memset((ez->Peq[0]).a, 0, wz); - memset((ez->Peq[1]).a, 0, wz); - memset((ez->Peq[2]).a, 0, wz); - memset((ez->Peq[3]).a, 0, wz); - memset((ez->Peq[4]).a, 0, wz); - - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; - ed_init_core(i, bd, i_bd, pstr, ez->Peq); - bd = thre+1, i_bd = thre; - - memset((ez->Peq[4]).a, 0, wz); - err = thre; - w_infi_set_bit_lsub(ez->VN, thre, ez->nword); /**VN = (((Word)1)<<(thre))-1;**/ - w_infi_set_bit_lsub(ez->VP, (thre<<1)+1, ez->nword); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/ - w_infi_self_xor(ez->VP, ez->VN, ez->nword, wz) /**VP ^= VN;**/ - - i = 0; - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); - while (i < tn0) { - // fprintf(stderr, "\ni::%d\n", i); - // prt_bit_extz_t((*ez), (((thre<<1))+1)); - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - - ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); - ++i; ++i_bd; c = 4; - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; - // fprintf(stderr, "c::%u\n", c); - // print_bits(ez->Peq[c].a, (((thre<<1))+1), "Peq[c]"); - } - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - - int32_t site = tn - 1 - thre;/**up bound**/ - for (cut = pn - 1, i = 0; site < cut; site++, i++) { - bd = (i>>bitw); i_bd = (i&bitz); - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); - } - - if (site == cut && err <= thre) { - ez->err = err; - ez->pe = pn-1; ez->te = tn-1; - } - return; -} - -inline void ed_band_cal_semi_infi_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) -{ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1; - int32_t bd, i, err = 0, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, wz, wz1, Peq_i; w_sig c, ad, Peq_m; - if((pn > tn + cut) || (tn > pn + cut)) return; - - if(nword) { - ez->nword = (*nword); - } else { - bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); - } - resize_bit_extz_t((*ez), (thre)); - wz = sizeof(*(ez->a))*(ez->nword); - memset((ez->Peq[0]).a, 0, wz); - memset((ez->Peq[1]).a, 0, wz); - memset((ez->Peq[2]).a, 0, wz); - memset((ez->Peq[3]).a, 0, wz); - memset((ez->Peq[4]).a, 0, wz); - memset((ez->VP).a, 0, wz); - memset((ez->VN).a, 0, wz); - - bd = (thre<<1)+1; bd = ((bd<=pn)?bd:pn); i_bd = 0; - ed_init_core(i, bd, i_bd, pstr, ez->Peq); - bd = (thre<<1)+1, i_bd = (thre<<1); - - memset((ez->Peq[4]).a, 0, wz); - i = 0; - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); - while (i < tn0) { - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - - ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); - ++i; ++i_bd; c = 4; - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; - } - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - - int32_t site = tn - 1;/**up bound**/ - /**in most cases, ai = (thre<<1)**/ - int32_t ai = pn - tn, uge = INT32_MAX; - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site; - } - - i = 0; - while (i < ai) { - bd = (i>>bitw); i_bd = (i&bitz); - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); - ++i; - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site + i; - } - if(i == thre) uge = err; - } - - if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; -} - -inline void ed_band_cal_extension_infi_0_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) -{ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; ez->pe = ez->te = -1; - if(pn > tn + thre) pn = tn + thre; - else if(tn > pn + thre) tn = pn + thre; - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, wz, wz1, Peq_i; w_sig c, ad, Peq_m; - int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k; - if(nword) { - ez->nword = (*nword); - } else { - bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); - } - resize_bit_extz_t((*ez), (thre)); - wz = sizeof(*(ez->a))*(ez->nword); - memset((ez->Peq[0]).a, 0, wz); - memset((ez->Peq[1]).a, 0, wz); - memset((ez->Peq[2]).a, 0, wz); - memset((ez->Peq[3]).a, 0, wz); - memset((ez->Peq[4]).a, 0, wz); - - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; - ed_init_core(i, bd, i_bd, pstr, ez->Peq); - bd = thre+1, i_bd = thre; - - memset((ez->Peq[4]).a, 0, wz); - err = thre; - w_infi_set_bit_lsub(ez->VN, thre, ez->nword); /**VN = (((Word)1)<<(thre))-1;**/ - w_infi_set_bit_lsub(ez->VP, (thre<<1)+1, ez->nword); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/ - w_infi_self_xor(ez->VP, ez->VN, ez->nword, wz) /**VP ^= VN;**/ - - i = 0; - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); - //for debug - // memset((ez->X).a, 0, sizeof(*(ez->a))*(ez->nword)); - // memset((ez->D0).a, 0, sizeof(*(ez->a))*(ez->nword)); - // memset((ez->HN).a, 0, sizeof(*(ez->a))*(ez->nword)); - // memset((ez->HP).a, 0, sizeof(*(ez->a))*(ez->nword)); - while (i < tn0) { - // fprintf(stderr, "i::%d\n", i); - // prt_bit_extz_t((*ez), ((thre<<1)+1)); - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - - { - poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ - if(k >= 0) { - if(tmp_e == INT32_MAX) { - tmp_e = err; - for ((k) = 0; (poff) < (pe); (poff)++, (k)++) { - bd = (k>>bitw); k_bd = (k&bitz); - (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1)); - (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1)); - } - } else { - k = (thre<<1) - k; - if(k >= 0) { - bd = (k>>bitw); k_bd = (k&bitz); - (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1)); - (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1)); - } - } - if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) { - (*ez).err = tmp_e; (*ez).pe = pe; (*ez).te = i; - } - } - // if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e) { - // fprintf(stderr, "i::%d, tmp_e::%d, dbg_ext_err::%d\n", i, tmp_e, dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))); - // } - } - - ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); - ++i; ++i_bd; c = 4; - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; - } - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - - int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/ - for (cut = pn - 1, i = 0; site < cut; i++) { - bd = (i>>bitw); i_bd = (i&bitz); - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); - site++; - if(err <= thre && err < ez->err) { - ez->err = err; ez->pe = site; ez->te = tn-1; - } - } - if(err <= thre && err < ez->err) { - ez->err = err; ez->pe = site; ez->te = tn-1; - } - return; -} - -inline void ed_band_cal_extension_infi_1_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) -{ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = INT32_MAX; ez->pe = pn-1; ez->te = tn-1; - if(pn > tn + thre) pn = tn + thre; - else if(tn > pn + thre) tn = pn + thre; - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, wz, wz1, Peq_i; - int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k, pidx = ez->pe, tidx = ez->te; w_sig c, ad, Peq_m; - if(nword) { - ez->nword = (*nword); - } else { - bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); - } - resize_bit_extz_t((*ez), (thre)); - wz = sizeof(*(ez->a))*(ez->nword); - memset((ez->Peq[0]).a, 0, wz); - memset((ez->Peq[1]).a, 0, wz); - memset((ez->Peq[2]).a, 0, wz); - memset((ez->Peq[3]).a, 0, wz); - memset((ez->Peq[4]).a, 0, wz); - - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; - for (i = 0; i < bd; i++, i_bd++) { - w_bit((ez->Peq)[seq_nt4_table[(uint8_t)(pstr)[pidx-i]]], (i_bd)); - } - bd = thre+1, i_bd = thre; - - memset((ez->Peq[4]).a, 0, wz); - err = thre; - w_infi_set_bit_lsub(ez->VN, thre, ez->nword); /**VN = (((Word)1)<<(thre))-1;**/ - w_infi_set_bit_lsub(ez->VP, (thre<<1)+1, ez->nword); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/ - w_infi_self_xor(ez->VP, ez->VN, ez->nword, wz) /**VP ^= VN;**/ - - i = 0; - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); - while (i < tn0) { - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - - { - poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ - if(k >= 0) { - if(tmp_e == INT32_MAX) { - tmp_e = err; - for ((k) = 0; (poff) < (pe); (poff)++, (k)++) { - bd = (k>>bitw); k_bd = (k&bitz); - (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1)); - (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1)); - } - } else { - k = (thre<<1) - k; - if(k >= 0) { - bd = (k>>bitw); k_bd = (k&bitz); - (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1)); - (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1)); - } - } - if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) { - (*ez).err = tmp_e; (*ez).ps = pidx - pe; (*ez).ts = tidx-i; - } - } - } - // if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e) { - // fprintf(stderr, "i::%d, tmp_e::%d, dbg_ext_err::%d\n", i, tmp_e, dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))); - // } - - ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); - ++i; ++i_bd; c = 4; - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[pidx-i_bd]]; - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; - } - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - - int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/ - for (cut = pn - 1, i = 0; site < cut; i++) { - bd = (i>>bitw); i_bd = (i&bitz); - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); - site++; - if(err <= thre && err < ez->err) { - ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; - } - } - if(err <= thre && err < ez->err) { - ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; - } - return; -} - -inline void ed_band_cal_global_infi_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) -{ - ez->cigar.n = 0;//diff - if(ez->err > thre) {//diff - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; - } else if(ez->err == 0) {//diff - push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;//diff - } - if((pn > tn + thre) || (tn > pn + thre)) return; - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, wz, wz1, Peq_i, ws; w_sig c, ad, Peq_m; - if(nword) { - ez->nword = (*nword); - } else { - bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); - } - resize_bit_extz_t((*ez), (thre)); - wz = ws = sizeof(*(ez->a))*(ez->nword);//diff - memset((ez->Peq[0]).a, 0, wz); - memset((ez->Peq[1]).a, 0, wz); - memset((ez->Peq[2]).a, 0, wz); - memset((ez->Peq[3]).a, 0, wz); - memset((ez->Peq[4]).a, 0, wz); - - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; - ed_init_core(i, bd, i_bd, pstr, ez->Peq); - bd = thre+1, i_bd = thre; - - memset((ez->Peq[4]).a, 0, wz); - err = thre; - w_infi_set_bit_lsub(ez->VN, thre, ez->nword); /**VN = (((Word)1)<<(thre))-1;**/ - w_infi_set_bit_lsub(ez->VP, (thre<<1)+1, ez->nword); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/ - w_infi_self_xor(ez->VP, ez->VN, ez->nword, wz) /**VP ^= VN;**/ - - ez->path.n=(ez->nword*tn*5);//diff - kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff - - i = 0; - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); - while (i < tn0) { - // fprintf(stderr, "\ni::%d\n", i); - // prt_bit_extz_t((*ez), (((thre<<1))+1)); - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - - ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); - ++i; ++i_bd; c = 4; - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; - // fprintf(stderr, "c::%u\n", c); - // print_bits(ez->Peq[c].a, (((thre<<1))+1), "Peq[c]"); - - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff - } - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff - - int32_t site = tn - 1 - thre;/**up bound**/ - if(ez->err > thre) {//diff - for (cut = pn - 1, i = 0; site < cut; site++, i++) { - bd = (i>>bitw); i_bd = (i&bitz); - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); - } - - if (site == cut && err <= thre) { - ez->err = err; - ez->pe = pn-1; ez->te = tn-1; - } - } - gen_trace(ez, thre, 1);//diff - return; -} - -inline void ed_band_cal_semi_infi_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) -{ - ez->cigar.n = 0;//diff - if(ez->err > thre) {//diff - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1; - } else if(ez->err == 0) {//diff - push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); //diff - ez->ps = ez->pe - (ez->te-ez->ts);//diff - return;//diff - } - int32_t bd, i, err = 0, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, wz, wz1, ws, Peq_i; w_sig c, ad, Peq_m; - if((pn > tn + cut) || (tn > pn + cut)) return; - - if(nword) { - ez->nword = (*nword); - } else { - bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); - } - resize_bit_extz_t((*ez), (thre)); - wz = ws = sizeof(*(ez->a))*(ez->nword);//diff - memset((ez->Peq[0]).a, 0, wz); - memset((ez->Peq[1]).a, 0, wz); - memset((ez->Peq[2]).a, 0, wz); - memset((ez->Peq[3]).a, 0, wz); - memset((ez->Peq[4]).a, 0, wz); - memset((ez->VP).a, 0, wz); - memset((ez->VN).a, 0, wz); - - bd = (thre<<1)+1; bd = ((bd<=pn)?bd:pn); i_bd = 0; - ed_init_core(i, bd, i_bd, pstr, ez->Peq); - bd = (thre<<1)+1, i_bd = (thre<<1); - - memset((ez->Peq[4]).a, 0, wz); - - ez->path.n=(ez->nword*tn*5);//diff - kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff - - i = 0; - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); - while (i < tn0) { - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - - ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); - ++i; ++i_bd; c = 4; - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; - - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff - } - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff - - int32_t site = tn - 1;/**up bound**/ - /**in most cases, ai = (thre<<1)**/ - int32_t ai = pn - tn, uge = INT32_MAX; - if(ez->err > thre) {//diff - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site; - } - - i = 0; - while (i < ai) { - bd = (i>>bitw); i_bd = (i&bitz); - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); - ++i; - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site + i; - } - if(i == thre) uge = err; - } - if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; - } - gen_trace(ez, 0, 1);//diff -} - -inline void ed_band_cal_extension_infi_0_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) -{ - int32_t done = 1;//diff - ez->cigar.n = 0; //diff - if(ez->err > thre) {//diff - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; ez->pe = ez->te = -1; - if(pn > tn + thre) pn = tn + thre; - else if(tn > pn + thre) tn = pn + thre; - done = 0;//diff - } else if(ez->err == 0) {//diff - push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;//diff - } else { - pn = ez->pe + 1 - ez->ps; tn = ez->te + 1 - ez->ts; //diff - } - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, wz, wz1, ws, Peq_i; w_sig c, ad, Peq_m; - int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k; - if(nword) { - ez->nword = (*nword); - } else { - bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); - } - resize_bit_extz_t((*ez), (thre)); - wz = ws = sizeof(*(ez->a))*(ez->nword);//diff - memset((ez->Peq[0]).a, 0, wz); - memset((ez->Peq[1]).a, 0, wz); - memset((ez->Peq[2]).a, 0, wz); - memset((ez->Peq[3]).a, 0, wz); - memset((ez->Peq[4]).a, 0, wz); - - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; - ed_init_core(i, bd, i_bd, pstr, ez->Peq); - bd = thre+1, i_bd = thre; - - memset((ez->Peq[4]).a, 0, wz); - err = thre; - w_infi_set_bit_lsub(ez->VN, thre, ez->nword); /**VN = (((Word)1)<<(thre))-1;**/ - w_infi_set_bit_lsub(ez->VP, (thre<<1)+1, ez->nword); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/ - w_infi_self_xor(ez->VP, ez->VN, ez->nword, wz) /**VP ^= VN;**/ - - ez->path.n=(ez->nword*tn*5);//diff - kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff - - i = 0; - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); - //for debug - // memset((ez->X).a, 0, sizeof(*(ez->a))*(ez->nword)); - // memset((ez->D0).a, 0, sizeof(*(ez->a))*(ez->nword)); - // memset((ez->HN).a, 0, sizeof(*(ez->a))*(ez->nword)); - // memset((ez->HP).a, 0, sizeof(*(ez->a))*(ez->nword)); - while (i < tn0) { - // fprintf(stderr, "i::%d\n", i); - // prt_bit_extz_t((*ez), ((thre<<1)+1)); - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - - if(!done) {//diff - poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ - if(k >= 0) { - if(tmp_e == INT32_MAX) { - tmp_e = err; - for ((k) = 0; (poff) < (pe); (poff)++, (k)++) { - bd = (k>>bitw); k_bd = (k&bitz); - (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1)); - (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1)); - } - } else { - k = (thre<<1) - k; - if(k >= 0) { - bd = (k>>bitw); k_bd = (k&bitz); - (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1)); - (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1)); - } - } - if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) { - (*ez).err = tmp_e; (*ez).pe = pe; (*ez).te = i; - } - } - // if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e) { - // fprintf(stderr, "i::%d, tmp_e::%d, dbg_ext_err::%d\n", i, tmp_e, dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))); - // } - } - - ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); - ++i; ++i_bd; c = 4; - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; - - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff - } - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff - - int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/ - if(!done) {//diff - for (cut = pn - 1, i = 0; site < cut; i++) { - bd = (i>>bitw); i_bd = (i&bitz); - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); - site++; - if(err <= thre && err < ez->err) { - ez->err = err; ez->pe = site; ez->te = tn-1; - } - } - if(err <= thre && err < ez->err) { - ez->err = err; ez->pe = site; ez->te = tn-1; - } - } - - if((ez->te-ez->ts+1) != tn) {//diff - ez->path.n /= tn; ez->path.n *= (ez->te+1-ez->ts);//diff - }//diff - gen_trace(ez, thre, 1);//diff - return; -} - -inline void ed_band_cal_extension_infi_1_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) -{ - int32_t done = 1;//diff - ez->cigar.n = 0;//diff - if(ez->err > thre) {//diff - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = INT32_MAX; ez->pe = pn-1; ez->te = tn-1; - if(pn > tn + thre) pn = tn + thre; - else if(tn > pn + thre) tn = pn + thre; - done = 0;//diff - } else if(ez->err == 0) {//diff - push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;//diff - } else { - pn = ez->pe + 1 - ez->ps; tn = ez->te + 1 - ez->ts; //diff - } - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, wz, wz1, ws, Peq_i; - int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k, pidx = ez->pe, tidx = ez->te; w_sig c, ad, Peq_m; - if(nword) { - ez->nword = (*nword); - } else { - bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); - } - resize_bit_extz_t((*ez), (thre)); - wz = ws = sizeof(*(ez->a))*(ez->nword);//diff - memset((ez->Peq[0]).a, 0, wz); - memset((ez->Peq[1]).a, 0, wz); - memset((ez->Peq[2]).a, 0, wz); - memset((ez->Peq[3]).a, 0, wz); - memset((ez->Peq[4]).a, 0, wz); - - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; - for (i = 0; i < bd; i++, i_bd++) { - w_bit((ez->Peq)[seq_nt4_table[(uint8_t)(pstr)[pidx-i]]], (i_bd)); - } - bd = thre+1, i_bd = thre; - - memset((ez->Peq[4]).a, 0, wz); - err = thre; - w_infi_set_bit_lsub(ez->VN, thre, ez->nword); /**VN = (((Word)1)<<(thre))-1;**/ - w_infi_set_bit_lsub(ez->VP, (thre<<1)+1, ez->nword); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/ - w_infi_self_xor(ez->VP, ez->VN, ez->nword, wz) /**VP ^= VN;**/ - - ez->path.n=(ez->nword*tn*5);//diff - kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff - - i = 0; - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); - while (i < tn0) { - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - - if(!done) {//diff - poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ - if(k >= 0) { - if(tmp_e == INT32_MAX) { - tmp_e = err; - for ((k) = 0; (poff) < (pe); (poff)++, (k)++) { - bd = (k>>bitw); k_bd = (k&bitz); - (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1)); - (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1)); - } - } else { - k = (thre<<1) - k; - if(k >= 0) { - bd = (k>>bitw); k_bd = (k&bitz); - (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1)); - (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1)); - } - } - if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) { - (*ez).err = tmp_e; (*ez).ps = pidx - pe; (*ez).ts = tidx-i; - } - } - } - // if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e) { - // fprintf(stderr, "i::%d, tmp_e::%d, dbg_ext_err::%d\n", i, tmp_e, dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))); - // } - - ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); - ++i; ++i_bd; c = 4; - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[pidx-i_bd]]; - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; - - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff - } - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff - - int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/ - if(!done) {//diff - for (cut = pn - 1, i = 0; site < cut; i++) { - bd = (i>>bitw); i_bd = (i&bitz); - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); - site++; - if(err <= thre && err < ez->err) { - ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; - } - } - if(err <= thre && err < ez->err) { - ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; - } - } - - if((ez->te-ez->ts+1) != tn) {//diff - ez->path.n /= tn; ez->path.n *= (ez->te+1-ez->ts);//diff - }//diff - - poff = ez->ps; ez->ps = pidx - ez->pe; ez->pe = pidx - poff;//diff - gen_trace(ez, thre, 0);//diff - poff = ez->ps; ez->ps = pidx - ez->pe; ez->pe = pidx - poff;//diff - return; -} - -inline void ed_band_cal_semi_infi_w_absent_diag(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t abs_diag, int32_t *nword, bit_extz_t *ez) -{ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1; - int32_t bd, i, err = abs_diag, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, wz, wz1, Peq_i; w_sig c, ad, Peq_m; - if((pn > tn + cut) || (tn > pn + cut)) return; - - if(nword) { - ez->nword = (*nword); - } else { - bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); - } - resize_bit_extz_t((*ez), (thre)); - wz = sizeof(*(ez->a))*(ez->nword); - memset((ez->Peq[0]).a, 0, wz); - memset((ez->Peq[1]).a, 0, wz); - memset((ez->Peq[2]).a, 0, wz); - memset((ez->Peq[3]).a, 0, wz); - memset((ez->Peq[4]).a, 0, wz); - memset((ez->VP).a, 0, wz); - w_infi_set_bit_lsub(ez->VN, abs_diag, ez->nword); /**VN = (((Word)1)<<(abs_diag))-1; ;**/ - - bd = ((thre<<1)+1)-abs_diag; bd = ((bd<=pn)?bd:pn); i_bd = abs_diag; - ed_init_core(i, bd, i_bd, pstr, ez->Peq); - i_bd = (thre<<1)-abs_diag; - - memset((ez->Peq[4]).a, 0, wz); - i = 0; - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); - while (i < tn0) { - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - - ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); - ++i; ++i_bd; c = 4; - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; - } - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - - int32_t site = tn - 1 - abs_diag;/**up bound**/ - /**in most cases, ai = (thre<<1)**/ - int32_t ai = pn - tn + abs_diag, uge = INT32_MAX; i = 0; - for (i = 0; site < 0 && i < ai; i++, site++) { - bd = (i>>bitw); i_bd = (i&bitz); - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); - } - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site; - } - site -= i; - while (i < ai) { - bd = (i>>bitw); i_bd = (i&bitz); - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); - ++i; - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site + i; - } - if(i == thre) uge = err; - } - if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; -} - -inline void ed_band_cal_semi_infi_w_absent_diag_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t abs_diag, int32_t *nword, bit_extz_t *ez) -{ - ez->cigar.n = 0;//diff - if(ez->err > thre) {//diff - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1; - } else if(ez->err == 0) {//diff - push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); //diff - ez->ps = ez->pe - (ez->te-ez->ts);//diff - return;//diff - } - int32_t bd, i, err = abs_diag, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, wz, wz1, ws, Peq_i; w_sig c, ad, Peq_m; - if((pn > tn + cut) || (tn > pn + cut)) return; - - if(nword) { - ez->nword = (*nword); - } else { - bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); - } - resize_bit_extz_t((*ez), (thre)); - wz = ws = sizeof(*(ez->a))*(ez->nword);//diff - memset((ez->Peq[0]).a, 0, wz); - memset((ez->Peq[1]).a, 0, wz); - memset((ez->Peq[2]).a, 0, wz); - memset((ez->Peq[3]).a, 0, wz); - memset((ez->Peq[4]).a, 0, wz); - memset((ez->VP).a, 0, wz); - w_infi_set_bit_lsub(ez->VN, abs_diag, ez->nword); /**VN = (((Word)1)<<(abs_diag))-1; ;**/ - - bd = ((thre<<1)+1)-abs_diag; bd = ((bd<=pn)?bd:pn); i_bd = abs_diag; - ed_init_core(i, bd, i_bd, pstr, ez->Peq); - i_bd = (thre<<1)-abs_diag; - - memset((ez->Peq[4]).a, 0, wz); - - ez->path.n=(ez->nword*tn*5);//diff - kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff - - i = 0; - /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ - Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); - while (i < tn0) { - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - - ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); - ++i; ++i_bd; c = 4; - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; - - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff - } - ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); - if (!(ez->D0.a[0]&(1ULL))) { - ++err; if (err>cut) return; - } - memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff - memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff - - int32_t site = tn - 1 - abs_diag;/**up bound**/ - /**in most cases, ai = (thre<<1)**/ - int32_t ai = pn - tn + abs_diag, uge = INT32_MAX; i = 0; - if(ez->err > thre) {//diff - for (i = 0; site < 0 && i < ai; i++, site++) { - bd = (i>>bitw); i_bd = (i&bitz); - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); - } - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site; - } - site -= i; - while (i < ai) { - bd = (i>>bitw); i_bd = (i&bitz); - err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); - err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); - ++i; - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site + i; - } - if(i == thre) uge = err; - } - if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; - } - gen_trace(ez, abs_diag, 1);//diff -} - - -#define ed_core_64(Peq, VP, VN, X, D0, HN, HP, z) { \ - /**X = Peq[seq_nt4_table[(uint8_t)tstr[i]]] | VN;**/\ - (X) = (Peq)[(seq_nt4_table[(z)])]|(VN);\ - (D0) = (((VP) + ((X)&(VP))) ^ (VP)) | (X);\ - (HN) = (VP)&(D0);\ - (HP) = (VN) | ~((VP) | (D0));\ - (X) = (D0) >> 1;\ - (VN) = (X)&(HP);\ - (VP) = (HN) | ~((X) | (HP));\ -} - -inline void ed_band_cal_global_64_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) -{ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; - if((pn > tn + thre) || (tn > pn + thre)) return; - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd; - Word c, Peq[5] = {0}, VP, VN, X, D0, HN, HP, mm; - - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; - for (i = 0, mm = (((Word)1)<cut) return; - } - - Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; - ++i; ++i_bd; - if(i_bd < pn) { - c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) Peq[c] |= mm; - // fprintf(stderr, "c::%lu\n", c); - // print_bit(Peq[c], (((thre<<1))+1), "Peq[c]"); - } - } - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - - int32_t site = tn - 1 - thre;/**up bound**/\ - for (cut = pn - 1; site < cut; site++) { - err += VP&(1ULL); VP >>= 1; err -= VN&(1ULL); VN >>= 1; - } - - if (site == cut && err <= thre) { - ez->err = err; - ez->pe = pn-1; ez->te = tn-1; - } - return; -} - -inline void ed_band_cal_semi_64_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) -{ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1; - Word c, Peq[5] = {0}, VP = 0, VN = 0, X, D0, HN, HP, mm; - int32_t bd, i, err = 0, i_bd, last_high = (thre<<1), tn0 = tn - 1, cut = thre+last_high; - if((pn > tn + cut) || (tn > pn + cut)) return; - - bd = (thre<<1)+1; bd = ((bd<=pn)?bd:pn); - for (i = 0, mm = 1; i < bd; i++) { - Peq[seq_nt4_table[(uint8_t)pstr[i]]] |= mm; mm <<= 1; - } - bd = (thre<<1)+1, i_bd = (thre<<1); - - i = 0; Peq[4] = 0; mm = ((Word)1 << (thre<<1));///for the incoming char/last char** - while (i < tn0) { - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - - Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; - ++i; ++i_bd; c = 4; - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) Peq[c] |= mm; - } - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - - int32_t site = tn - 1;/**up bound**/ - /**in most cases, ai = (thre<<1)**/ - int32_t ai = pn - tn, uge = INT32_MAX; - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site; - } - - i = 0; - while (i < ai) {\ - err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); ++i; - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site + i; - } - if(i == thre) uge = err; - } - - if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; -} - -inline void ed_band_cal_extension_64_0_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) -{ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; ez->pe = ez->te = -1; - if(pn > tn + thre) pn = tn + thre; - else if(tn > pn + thre) tn = pn + thre; - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, poff, pe = pn-1, tmp_e = INT32_MAX, k; - Word c, Peq[5] = {0}, VP, VN, X, D0, HN, HP, mm; - - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; - for (i = 0, mm = (((Word)1)<cut) return; - } - - { - poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ - if(k >= 0) { - if(tmp_e == INT32_MAX) { - tmp_e = err; - for (k = 0; poff < pe; poff++, (k)++) { - tmp_e += ((VP>>k)&(1ULL)); tmp_e -= ((VN>>k)&(1ULL)); - } - } else { - k = (thre<<1) - k; - if(k >= 0) { - tmp_e += ((HP>>k)&(1ULL)); tmp_e -= ((HN>>k)&(1ULL)); - } - } - if(tmp_e <= (*ez).thre && tmp_e < (*ez).err) { - (*ez).err = tmp_e; (*ez).pe = pe; (*ez).te = i; - } - } - } - // fprintf(stderr, "i::%d, tmp_e::%d, err::%d\n", i, tmp_e, err); - - Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; - ++i; ++i_bd; - if(i_bd < pn) { - c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) Peq[c] |= mm; - } - } - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - - int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/\ - for (cut = pn - 1; site < cut; ) { - err += VP&(1ULL); VP >>= 1; err -= VN&(1ULL); VN >>= 1; - site++; - if(err <= thre && err < ez->err) { - ez->err = err; ez->pe = site; ez->te = tn-1; - } - } - if(err <= thre && err < ez->err) { - ez->err = err; ez->pe = site; ez->te = tn-1; - } - return; -} - -inline void ed_band_cal_extension_64_1_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) -{ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = INT32_MAX; ez->pe = pn-1; ez->te = tn-1; - if(pn > tn + thre) pn = tn + thre; - else if(tn > pn + thre) tn = pn + thre; - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd; - int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k, pidx = ez->pe, tidx = ez->te; - Word c, Peq[5] = {0}, VP, VN, X, D0, HN, HP, mm; - - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; - for (i = 0, mm = (((Word)1)<cut) return; - } - - { - poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ - if(k >= 0) { - if(tmp_e == INT32_MAX) { - tmp_e = err; - for (k = 0; poff < pe; poff++, (k)++) { - tmp_e += ((VP>>k)&(1ULL)); tmp_e -= ((VN>>k)&(1ULL)); - } - } else { - k = (thre<<1) - k; - if(k >= 0) { - tmp_e += ((HP>>k)&(1ULL)); tmp_e -= ((HN>>k)&(1ULL)); - } - } - if(tmp_e <= (*ez).thre && tmp_e < (*ez).err) { - (*ez).err = tmp_e; (*ez).ps = pidx - pe; (*ez).ts = tidx-i; - } - } - } - // fprintf(stderr, "i::%d, tmp_e::%d, err::%d\n", i, tmp_e, err); - - Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; - ++i; ++i_bd; - if(i_bd < pn) { - c = seq_nt4_table[(uint8_t)pstr[pidx-i_bd]]; - if(c < 4) Peq[c] |= mm; - } - } - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[tidx-i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - - int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/\ - for (cut = pn - 1; site < cut; ) { - err += VP&(1ULL); VP >>= 1; err -= VN&(1ULL); VN >>= 1; - site++; - if(err <= thre && err < ez->err) { - ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; - } - } - if(err <= thre && err < ez->err) { - ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; - } - return; -} - -inline void ed_band_cal_global_64_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) -{ - ez->cigar.n = 0; ez->nword = 1;//diff - if(ez->err > thre) {//diff - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0;//diff - } else if(ez->err == 0) {//diff - push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;//diff - } - if((pn > tn + thre) || (tn > pn + thre)) return; - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd; - w_sig c, Peq[5] = {0}, VP, VN, X, D0, HN, HP, mm; - - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; - for (i = 0, mm = (((w_sig)1)<path.n=(ez->nword*tn*5);//diff - kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff - - i = 0; mm = ((w_sig)1 << (thre<<1));///for the incoming char/last char - while (i < tn0) { - // fprintf(stderr, "\ni::%d\n", i); - // prt_vector(Peq, VP, VN, X, D0, HN, HP, (((thre<<1))+1)); - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - - Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; - ++i; ++i_bd; - if(i_bd < pn) { - c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) Peq[c] |= mm; - } - ez->path.a[ez->path.n++] = D0;//diff - ez->path.a[ez->path.n++] = VP;//diff - ez->path.a[ez->path.n++] = VN;//diff - ez->path.a[ez->path.n++] = HP;//diff - ez->path.a[ez->path.n++] = HN;//diff - } - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - ez->path.a[ez->path.n++] = D0;//diff - ez->path.a[ez->path.n++] = VP;//diff - ez->path.a[ez->path.n++] = VN;//diff - ez->path.a[ez->path.n++] = HP;//diff - ez->path.a[ez->path.n++] = HN;//diff - - int32_t site = tn - 1 - thre;/**up bound**/\ - if(ez->err > thre) {//diff - for (cut = pn - 1; site < cut; site++) { - err += VP&(1ULL); VP >>= 1; err -= VN&(1ULL); VN >>= 1; - } - - if (site == cut && err <= thre) { - ez->err = err; - ez->pe = pn-1; ez->te = tn-1; - } - } - ///should update ez->path.n for extension - gen_trace(ez, thre, 1);//diff - return; -} - -inline void ed_band_cal_semi_64_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) -{ - ez->cigar.n = 0; ez->nword = 1;//diff - if(ez->err > thre) {//diff - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1;//diff - } else if(ez->err == 0) {//diff - push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); //diff - ez->ps = ez->pe - (ez->te-ez->ts);//diff - return;//diff - } - Word c, Peq[5] = {0}, VP = 0, VN = 0, X, D0, HN, HP, mm; - int32_t bd, i, err = 0, i_bd, last_high = (thre<<1), tn0 = tn - 1, cut = thre+last_high; - if((pn > tn + cut) || (tn > pn + cut)) return; - - bd = (thre<<1)+1; bd = ((bd<=pn)?bd:pn); - for (i = 0, mm = 1; i < bd; i++) { - Peq[seq_nt4_table[(uint8_t)pstr[i]]] |= mm; mm <<= 1; - } - bd = (thre<<1)+1, i_bd = (thre<<1); - - ez->path.n=(ez->nword*tn*5);//diff - kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff - - i = 0; Peq[4] = 0; mm = ((Word)1 << (thre<<1));///for the incoming char/last char** - while (i < tn0) { - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - - Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; - ++i; ++i_bd; c = 4; - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) Peq[c] |= mm; - - ez->path.a[ez->path.n++] = D0;//diff - ez->path.a[ez->path.n++] = VP;//diff - ez->path.a[ez->path.n++] = VN;//diff - ez->path.a[ez->path.n++] = HP;//diff - ez->path.a[ez->path.n++] = HN;//diff - } - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - ez->path.a[ez->path.n++] = D0;//diff - ez->path.a[ez->path.n++] = VP;//diff - ez->path.a[ez->path.n++] = VN;//diff - ez->path.a[ez->path.n++] = HP;//diff - ez->path.a[ez->path.n++] = HN;//diff - - int32_t site = tn - 1;/**up bound**/ - /**in most cases, ai = (thre<<1)**/ - int32_t ai = pn - tn, uge = INT32_MAX; - if(ez->err > thre) {//diff - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site; - } - - i = 0; - while (i < ai) { - err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); ++i; - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site + i; - } - if(i == thre) uge = err; - } - if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; - } - ///should update ez->path.n for extension - gen_trace(ez, 0, 1);//diff -} - -inline void ed_band_cal_extension_64_0_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) -{ - int32_t done = 1;//diff - ez->cigar.n = 0; ez->nword = 1;//diff - if(ez->err > thre) {//diff - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; ez->pe = ez->te = -1; - if(pn > tn + thre) pn = tn + thre; - else if(tn > pn + thre) tn = pn + thre; - done = 0;//diff - } else if(ez->err == 0) {//diff - push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;//diff - } else { - pn = ez->pe + 1 - ez->ps; tn = ez->te + 1 - ez->ts; //diff - } - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, poff, pe = pn-1, tmp_e = INT32_MAX, k; - Word c, Peq[5] = {0}, VP, VN, X, D0, HN, HP, mm; - - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; - for (i = 0, mm = (((Word)1)<path.n=(ez->nword*tn*5);//diff - kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff - - i = 0; mm = ((Word)1 << (thre<<1)); - // X = D0 = HN = HP = mm = 0;//for debug - while (i < tn0) { - // fprintf(stderr, "i::%d\n", i); - // prt_vector(Peq, VP, VN, X, D0, HN, HP, ((thre<<1)+1)); - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - - if(!done) {//diff - poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ - if(k >= 0) { - if(tmp_e == INT32_MAX) { - tmp_e = err; - for (k = 0; poff < pe; poff++, (k)++) { - tmp_e += ((VP>>k)&(1ULL)); tmp_e -= ((VN>>k)&(1ULL)); - } - } else { - k = (thre<<1) - k; - if(k >= 0) { - tmp_e += ((HP>>k)&(1ULL)); tmp_e -= ((HN>>k)&(1ULL)); - } - } - if(tmp_e <= (*ez).thre && tmp_e < (*ez).err) { - (*ez).err = tmp_e; (*ez).pe = pe; (*ez).te = i; - } - // fprintf(stderr, "i::%d, (*ez).err::%d, (*ez).pe::%d, (*ez).te::%d, thre::%d, err::%d, tmp_e::%d, poff::%d, k::%d, pe::%d\n", - // i, (*ez).err, (*ez).pe, (*ez).te, thre, err, tmp_e, i-thre, i+thre-pe, pe); - } - } - - Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; - ++i; ++i_bd; - if(i_bd < pn) { - c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) Peq[c] |= mm; - } - // if(((ez->path.n+5)>(ez->nword*tn*5))||((ez->path.n+5)>(ez->path.m))) { - // fprintf(stderr, "[M::%s::] pn::%d, tn::%d\n", __func__, pn, tn); - // } - ez->path.a[ez->path.n++] = D0;//diff - ez->path.a[ez->path.n++] = VP;//diff - ez->path.a[ez->path.n++] = VN;//diff - ez->path.a[ez->path.n++] = HP;//diff - ez->path.a[ez->path.n++] = HN;//diff - } - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - // if(((ez->path.n+5)>(ez->nword*tn*5))||((ez->path.n+5)>(ez->path.m))) { - // fprintf(stderr, "[M::%s::] pn::%d, tn::%d\n", __func__, pn, tn); - // } - ez->path.a[ez->path.n++] = D0;//diff - ez->path.a[ez->path.n++] = VP;//diff - ez->path.a[ez->path.n++] = VN;//diff - ez->path.a[ez->path.n++] = HP;//diff - ez->path.a[ez->path.n++] = HN;//diff - - int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/ - if(!done) {//diff - for (cut = pn - 1; site < cut; ) { - err += VP&(1ULL); VP >>= 1; err -= VN&(1ULL); VN >>= 1; - site++; - if(err <= thre && err < ez->err) { - ez->err = err; ez->pe = site; ez->te = tn-1; - } - } - if(err <= thre && err < ez->err) { - ez->err = err; ez->pe = site; ez->te = tn-1; - } - } - - if((ez->te-ez->ts+1) != tn) {//diff - ez->path.n /= tn; ez->path.n *= (ez->te+1-ez->ts);//diff - }//diff - gen_trace(ez, thre, 1);//diff - return; -} - -inline void ed_band_cal_extension_64_1_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) -{ - int32_t done = 1;//diff - ez->cigar.n = 0; ez->nword = 1;//diff - if(ez->err > thre) {//diff - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = INT32_MAX; ez->pe = pn-1; ez->te = tn-1; - if(pn > tn + thre) pn = tn + thre; - else if(tn > pn + thre) tn = pn + thre; - done = 0;//diff - } else if(ez->err == 0) {//diff - push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;//diff - } else { - pn = ez->pe + 1 - ez->ps; tn = ez->te + 1 - ez->ts; //diff - } - - int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd; - int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k, pidx = ez->pe, tidx = ez->te; - Word c, Peq[5] = {0}, VP, VN, X, D0, HN, HP, mm; - - bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; - for (i = 0, mm = (((Word)1)<path.n=(ez->nword*tn*5);//diff - kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff - - i = 0; mm = ((Word)1 << (thre<<1)); - // X = D0 = HN = HP = mm = 0;//for debug - while (i < tn0) { - // fprintf(stderr, "i::%d\n", i); - // prt_vector(Peq, VP, VN, X, D0, HN, HP, ((thre<<1)+1)); - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[tidx-i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - - if(!done) {//diff - poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ - if(k >= 0) { - if(tmp_e == INT32_MAX) { - tmp_e = err; - for (k = 0; poff < pe; poff++, (k)++) { - tmp_e += ((VP>>k)&(1ULL)); tmp_e -= ((VN>>k)&(1ULL)); - } - } else { - k = (thre<<1) - k; - if(k >= 0) { - tmp_e += ((HP>>k)&(1ULL)); tmp_e -= ((HN>>k)&(1ULL)); - } - } - if(tmp_e <= (*ez).thre && tmp_e < (*ez).err) { - (*ez).err = tmp_e; (*ez).ps = pidx - pe; (*ez).ts = tidx-i; - } - } - } - // fprintf(stderr, "i::%d, tmp_e::%d, err::%d\n", i, tmp_e, err); - - Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; - ++i; ++i_bd; - if(i_bd < pn) { - c = seq_nt4_table[(uint8_t)pstr[pidx-i_bd]]; - if(c < 4) Peq[c] |= mm; - } - - ez->path.a[ez->path.n++] = D0;//diff - ez->path.a[ez->path.n++] = VP;//diff - ez->path.a[ez->path.n++] = VN;//diff - ez->path.a[ez->path.n++] = HP;//diff - ez->path.a[ez->path.n++] = HN;//diff - } - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[tidx-i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - ez->path.a[ez->path.n++] = D0;//diff - ez->path.a[ez->path.n++] = VP;//diff - ez->path.a[ez->path.n++] = VN;//diff - ez->path.a[ez->path.n++] = HP;//diff - ez->path.a[ez->path.n++] = HN;//diff - - int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/\ - if(!done) {//diff - for (cut = pn - 1; site < cut; ) { - err += VP&(1ULL); VP >>= 1; err -= VN&(1ULL); VN >>= 1; - site++; - if(err <= thre && err < ez->err) { - ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; - } - } - if(err <= thre && err < ez->err) { - ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; - } - } - - if((ez->te-ez->ts+1) != tn) {//diff - ez->path.n /= tn; ez->path.n *= (ez->te+1-ez->ts);//diff - }//diff - - poff = ez->ps; ez->ps = pidx - ez->pe; ez->pe = pidx - poff;//diff - gen_trace(ez, thre, 0);//diff - poff = ez->ps; ez->ps = pidx - ez->pe; ez->pe = pidx - poff;//diff - return; -} - -inline void ed_band_cal_semi_64_w_absent_diag(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t abs_diag, bit_extz_t *ez) -{ - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1; - Word c, Peq[5] = {0}, VP = 0, VN, X, D0, HN, HP, mm; - int32_t bd, i, err = abs_diag, i_bd, last_high = (thre<<1), tn0 = tn - 1, cut = thre+last_high; - if((pn > tn + cut) || (tn > pn + cut)) return; - - bd = ((thre<<1)+1)-abs_diag; bd = ((bd<=pn)?bd:pn); i_bd = abs_diag; - for (i = 0, mm = (((Word)1)<cut) return; - } - - Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; - ++i; ++i_bd; c = 4; - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) Peq[c] |= mm; - } - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - - int32_t site = tn - 1 - abs_diag;/**up bound**/ - /**in most cases, ai = (thre<<1)**/ - int32_t ai = pn - tn + abs_diag, uge = INT32_MAX; i = 0; - for (i = 0; site < 0 && i < ai; i++, site++) { - err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); - } - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site; - } - site -= i; - while (i < ai) { - err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); ++i; - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site + i; - } - if(i == thre) uge = err; - } - - if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; -} - -inline void ed_band_cal_semi_64_w_absent_diag_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t abs_diag, bit_extz_t *ez) -{ - ez->cigar.n = 0; ez->nword = 1;//diff - if(ez->err > thre) {//diff - init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1;//diff - } else if(ez->err == 0) {//diff - push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); //diff - ez->ps = ez->pe - (ez->te-ez->ts);//diff - return;//diff - } - Word c, Peq[5] = {0}, VP = 0, VN, X, D0, HN, HP, mm; - int32_t bd, i, err = abs_diag, i_bd, last_high = (thre<<1), tn0 = tn - 1, cut = thre+last_high; - if((pn > tn + cut) || (tn > pn + cut)) return; - - bd = ((thre<<1)+1)-abs_diag; bd = ((bd<=pn)?bd:pn); i_bd = abs_diag; - for (i = 0, mm = (((Word)1)<path.n=(ez->nword*tn*5);//diff - kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff - - i = 0; Peq[4] = 0; mm = ((Word)1 << (thre<<1));///for the incoming char/last char** - while (i < tn0) { - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - - Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; - ++i; ++i_bd; c = 4; - if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; - if(c < 4) Peq[c] |= mm; - - ez->path.a[ez->path.n++] = D0;//diff - ez->path.a[ez->path.n++] = VP;//diff - ez->path.a[ez->path.n++] = VN;//diff - ez->path.a[ez->path.n++] = HP;//diff - ez->path.a[ez->path.n++] = HN;//diff - } - ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); - if (!(D0&(1ULL))) { - ++err; if (err>cut) return; - } - ez->path.a[ez->path.n++] = D0;//diff - ez->path.a[ez->path.n++] = VP;//diff - ez->path.a[ez->path.n++] = VN;//diff - ez->path.a[ez->path.n++] = HP;//diff - ez->path.a[ez->path.n++] = HN;//diff - - int32_t site = tn - 1 - abs_diag;/**up bound**/ - /**in most cases, ai = (thre<<1)**/ - int32_t ai = pn - tn + abs_diag, uge = INT32_MAX; i = 0; - if(ez->err > thre) {//diff - for (i = 0; site < 0 && i < ai; i++, site++) { - err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); - } - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site; - } - site -= i; - while (i < ai) { - err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); ++i; - if ((err <= thre) && (err <= ez->err)) { - ez->err = err; ez->pe = site + i; - } - if(i == thre) uge = err; - } - - if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; - } - ///should update ez->path.n for extension - gen_trace(ez, abs_diag, 1);//diff -} - -/** - pattern is the longer one, while text is the shorter one - **/ -inline int Reserve_Banded_BPM -(char *pattern, int p_length, char *text, int t_length, unsigned short errthold, unsigned int* return_err) -{ - (*return_err) = (unsigned int)-1; - - // bit_extz_t exz; ed_band_cal_semi_128bit(pattern, p_length, text, t_length, errthold, &exz); - // if(exz.err <= exz.thre) (*return_err) = exz.err; - // return exz.pe; - - Word Peq[256]; - - int band_length = (errthold << 1) + 1; - int i = 0; - Word tmp_Peq_1 = (Word)1; - - Peq[(uint8_t)'A'] = (Word)0; - Peq[(uint8_t)'T'] = (Word)0; - Peq[(uint8_t)'G'] = (Word)0; - Peq[(uint8_t)'C'] = (Word)0; - - - Word Peq_A; - Word Peq_T; - Word Peq_C; - Word Peq_G; - - ///band_length = 2k + 1 - for (i = 0; i> 1; - VN = X&HP; - VP = HN | ~(X | HP); - - if (!(D0&err_mask)) - { - ++err; - - if ((err - last_high)>(int)errthold) - { - return -1; - } - - } - - - Peq[(uint8_t)'A'] = Peq[(uint8_t)'A'] >> 1; - Peq[(uint8_t)'C'] = Peq[(uint8_t)'C'] >> 1; - Peq[(uint8_t)'G'] = Peq[(uint8_t)'G'] >> 1; - Peq[(uint8_t)'T'] = Peq[(uint8_t)'T'] >> 1; - - - ++i; - ++i_bd; - Peq[(uint8_t)pattern[i_bd]] = Peq[(uint8_t)pattern[i_bd]] | Mask; - } - - - - - - X = Peq[(uint8_t)text[i]] | VN; - D0 = ((VP + (X&VP)) ^ VP) | X; - HN = VP&D0; - HP = VN | ~(VP | D0); - X = D0 >> 1; - VN = X&HP; - VP = HN | ~(X | HP); - if (!(D0&err_mask)) - { - ++err; - if ((err - last_high)>errthold) - return -1; - } - - - ////fprintf(stderr, "sucess(2)\n"); - - /// last_high = 2k - /// site = (SEQ_LENGTH + 2k) - 2k -1 - /// site = SEQ_LENGTH - 1 - ///int site = p_length - last_high - 1; - int site = t_length - 1; - int return_site = -1; - ///in most cases, p_lengthshould be t_length + 2 * errthold - int available_i = p_length - t_length; - if ((err <= errthold) && ((unsigned int)err<=*return_err)) - { - *return_err = err; - return_site = site; - } - i = 0; - - /****************************may have bugs********************************/ - unsigned int ungap_error = (unsigned int)-1; - /****************************may have bugs********************************/ - - while (i < available_i) - { - err = err + ((VP >> i)&(Word)1); - err = err - ((VN >> i)&(Word)1); - ++i; - - if ((err <= (int)errthold) && ((unsigned int)err <= *return_err)) - { - *return_err = err; - return_site = site + i; - } - - /****************************may have bugs********************************/ - if(i == (int)errthold) - { - ungap_error = err; - } - /****************************may have bugs********************************/ - } - - /****************************may have bugs********************************/ - if((ungap_error<=errthold) && (ungap_error == (*return_err))) - { - return_site = site + errthold; - } - /****************************may have bugs********************************/ - - return return_site; - -} - - - -inline int try_cigar(char *pattern, int p_length, - char *text, int t_length, int end_site, char* path, - int error, - int* return_start_site, - int* return_path_length) -{ - int i = 0; - int tmp_err = 0; - ///start pos of y - int start_site = end_site - t_length + 1; - - if (start_site >= 0) - { - - for (i = 0; i < t_length; i++) - { - ///path[i] = 0; - ///path is saved backwards - path[t_length - i - 1] = 0; - if (text[i] != pattern[i + start_site]) - { - path[t_length - i - 1] = 1; - tmp_err++; - - if (tmp_err > error) - { - return 0; - } - } - } - - if (tmp_err == error) - { - (*return_path_length) = t_length; - - (*return_start_site) = start_site; - - return 6; - } - } - - - return 0; -} - - - -///p_length might be samller than t_length + 2 * errthold -inline int Reserve_Banded_BPM_PATH -(char *pattern, int p_length, char *text, int t_length, unsigned short errthold, - unsigned int* return_err, int* return_start_site, int* return_path_length, Word* matrix_bit, char* path, - int old_error, int old_end_site) -{ - if (old_error != -1 && old_end_site != -1) - { - if (old_error == 0) - { - (*return_err) = old_error; - (*return_start_site) = old_end_site - t_length + 1; - return old_end_site; - } - - if (try_cigar(pattern, p_length, text, t_length, old_end_site, path, - old_error, return_start_site, return_path_length)) - { - (*return_err) = old_error; - return old_end_site; - } - - } - - (*return_err) = (unsigned int)-1; - - Word Peq[256]; - - int band_length = (errthold << 1) + 1; - int i = 0; - Word tmp_Peq_1 = (Word)1; - - Peq[(uint8_t)'A'] = (Word)0; - Peq[(uint8_t)'T'] = (Word)0; - Peq[(uint8_t)'G'] = (Word)0; - Peq[(uint8_t)'C'] = (Word)0; - - - Word Peq_A; - Word Peq_T; - Word Peq_C; - Word Peq_G; - - ///band_length = 2k + 1 - for (i = 0; i> 1; - VN = X&HP; - VP = HN | ~(X | HP); - - if (!(D0&err_mask)) - { - ++err; - - if ((err - last_high)>(int)errthold) - { - return -1; - } - - } - - - Peq[(uint8_t)'A'] = Peq[(uint8_t)'A'] >> 1; - Peq[(uint8_t)'C'] = Peq[(uint8_t)'C'] >> 1; - Peq[(uint8_t)'G'] = Peq[(uint8_t)'G'] >> 1; - Peq[(uint8_t)'T'] = Peq[(uint8_t)'T'] >> 1; - - - ++i; - ++i_bd; - Peq[(uint8_t)pattern[i_bd]] = Peq[(uint8_t)pattern[i_bd]] | Mask; - - - ///Peq[(uint8_t)'T'] = Peq[(uint8_t)'T'] | Peq[(uint8_t)'C']; - - column_start = i << 3; - matrix_bit[column_start] = D0; - matrix_bit[column_start + 1] = VP; - matrix_bit[column_start + 2] = VN; - matrix_bit[column_start + 3] = HP; - matrix_bit[column_start + 4] = HN; - } - - - - - - X = Peq[(uint8_t)text[i]] | VN; - D0 = ((VP + (X&VP)) ^ VP) | X; - HN = VP&D0; - HP = VN | ~(VP | D0); - X = D0 >> 1; - VN = X&HP; - VP = HN | ~(X | HP); - if (!(D0&err_mask)) - { - ++err; - if ((err - last_high)>(int)errthold) - return -1; - } - - - column_start = (i + 1) << 3; - matrix_bit[column_start] = D0; - matrix_bit[column_start + 1] = VP; - matrix_bit[column_start + 2] = VN; - matrix_bit[column_start + 3] = HP; - matrix_bit[column_start + 4] = HN; - - - ////fprintf(stderr, "sucess(2)\n"); - - /// last_high = 2k - /// site = (SEQ_LENGTH + 2k) - 2k -1 - /// site = SEQ_LENGTH - 1 - ///int site = p_length - last_high - 1; - int site = t_length - 1; - int return_site = -1; - - /****************************may have bugs********************************/ - unsigned int ungap_error = (unsigned int)-1; - /****************************may have bugs********************************/ - - ///in most cases, p_length should be t_length + 2 * errthold - int available_i = p_length - t_length; - if ((err <= (int)errthold) && ((unsigned int)err<=*return_err)) - { - *return_err = err; - return_site = site; - } - i = 0; - - while (i < available_i) - { - err = err + ((VP >> i)&(Word)1); - err = err - ((VN >> i)&(Word)1); - ++i; - - if ((err <= (int)errthold) && ((unsigned int)err <= *return_err)) - { - *return_err = err; - return_site = site + i; - } - - /****************************may have bugs********************************/ - if(i == (int)errthold) - { - ungap_error = err; - } - /****************************may have bugs********************************/ - } - - - - - if ((*return_err) == (unsigned int)-1) - { - return return_site; - } - - - /****************************may have bugs********************************/ - if((ungap_error<=errthold) && (ungap_error == (*return_err))) - { - return_site = site + errthold; - } - /****************************may have bugs********************************/ - - - ///need to correct p_length here, since p_length might be smaller than t_length + 2* err_threashlod - p_length = t_length + 2 * errthold; - ///end_site is always correct - int end_site = return_site; - int start_site = end_site; - int back_track_site = band_length - (p_length - end_site); - - Word v_value, h_value, delta_value, min_value, current_value; - ///Word direction; ///0 is match, 1 is mismatch, 2 is up, 3 is left - Word direction = 0; ///0 is match, 1 is mismatch, 2 is up, 3 is left - i = t_length; - int path_length = 0; - current_value = *return_err; - - - int low_bound = band_length - 1; - - - while (i>0) - { - if (current_value == 0) - { - break; - } - - column_start = i << 3; - - delta_value = current_value - - ((~(matrix_bit[column_start] >> back_track_site))&err_mask); - - - if (back_track_site == 0) - { - ///HP - h_value = current_value - ((matrix_bit[column_start + 3] >> back_track_site)&err_mask); - //HN - h_value = h_value + ((matrix_bit[column_start + 4] >> back_track_site)&err_mask); - - - min_value = delta_value; - direction = 0; - - if (h_value < min_value) - { - min_value = h_value; - direction = 3; - } - - } - else if (back_track_site == low_bound) - { - v_value = current_value - ((matrix_bit[column_start + 1] >> (back_track_site - 1))&err_mask); - v_value = v_value + ((matrix_bit[column_start + 2] >> (back_track_site - 1))&err_mask); - - min_value = delta_value; - direction = 0; - - if (v_value < min_value) - { - min_value = v_value; - direction = 2; - } - - } - else - { - - h_value = current_value - ((matrix_bit[column_start + 3] >> back_track_site)&(Word)1); - - - h_value = h_value + ((matrix_bit[column_start + 4] >> back_track_site)&(Word)1); - - - v_value = current_value - ((matrix_bit[column_start + 1] >> (back_track_site - 1))&err_mask); - v_value = v_value + ((matrix_bit[column_start + 2] >> (back_track_site - 1))&err_mask); - - - min_value = delta_value; - direction = 0; - - if (v_value < min_value) - { - min_value = v_value; - direction = 2; - } - - - if (h_value < min_value) - { - min_value = h_value; - direction = 3; - } - - } - - - if (direction == 0) - { - - if (delta_value != current_value) - { - direction = 1; - } - - i--; - - start_site--; - - } - if (direction == 2)///ru guo xiang shang yi dong, bing bu huan lie - { - back_track_site--; - start_site--; - } - else if (direction == 3)///ru guo xiang zuo yi dong - { - i--; - back_track_site++; - } - - - path[path_length++] = direction; - - - current_value = min_value; - - } - - - if (i > 0) - { - memset(path + path_length, 0, i); - start_site = start_site - i; - direction = 0; - path_length = path_length + i; - } - - if (direction != 3) - { - start_site++; - } - (*return_start_site) = start_site; - (*return_path_length) = path_length; - - return return_site; -} - -////four patterns have the same p_length -inline int Reserve_Banded_BPM_4_SSE_only(char *pattern1, char *pattern2, char *pattern3, char *pattern4, int p_length, char *text, int t_length, - int* return_sites, unsigned int* return_sites_error, unsigned short errthold, __m128i* Peq_SSE) - -{ - memset(return_sites, -1, sizeof(int)* 4); - memset(return_sites_error, -1, sizeof(unsigned int)* 4); - - Word_32 Peq[256][4]; - int band_length = (errthold << 1) + 1; - - - int i; - - Word_32 tmp_Peq_1 = 1; - - - memset(Peq[(uint8_t)'A'], 0, sizeof(Word_32)* 4); - memset(Peq[(uint8_t)'C'], 0, sizeof(Word_32)* 4); - memset(Peq[(uint8_t)'G'], 0, sizeof(Word_32)* 4); - memset(Peq[(uint8_t)'T'], 0, sizeof(Word_32)* 4); - - for (i = 0; i> 1; - X = _mm_srli_epi32(D0, 1); - ///VN = X&HP; - VN = _mm_and_si128(X, HP); - ///VP = HN | ~(X | HP); - tmp_process = _mm_or_si128(X, HP); - tmp_process = _mm_andnot_si128(tmp_process, for_not); - VP = _mm_or_si128(HN, tmp_process); - - ///D0&err_mask - err_arry = _mm_and_si128(D0, err_mask); - Err_4 = _mm_add_epi32(Err_4, err_mask); - Err_4 = _mm_sub_epi32(Err_4, err_arry); - - /**************** */ - ///shi ji shang zhe ge zhi hen xiao d - cmp_result = _mm_cmpgt_epi32(Err_4, pre_end); - - ///jian zhi - if (_mm_extract_epi32(cmp_result, 0) && _mm_extract_epi32(cmp_result, 1) - && _mm_extract_epi32(cmp_result, 2) && _mm_extract_epi32(cmp_result, 3)) - return 1; - /**************** */ - - - Peq_SSE[(uint8_t)'A'] = _mm_srli_epi32(Peq_SSE[(uint8_t)'A'], 1); - Peq_SSE[(uint8_t)'T'] = _mm_srli_epi32(Peq_SSE[(uint8_t)'T'], 1); - Peq_SSE[(uint8_t)'G'] = _mm_srli_epi32(Peq_SSE[(uint8_t)'G'], 1); - Peq_SSE[(uint8_t)'C'] = _mm_srli_epi32(Peq_SSE[(uint8_t)'C'], 1); - - ++i; - ++i_bd; - - Peq_SSE[(uint8_t)pattern1[i_bd]] = _mm_or_si128(Mask1, Peq_SSE[(uint8_t)pattern1[i_bd]]); - Peq_SSE[(uint8_t)pattern2[i_bd]] = _mm_or_si128(Mask2, Peq_SSE[(uint8_t)pattern2[i_bd]]); - Peq_SSE[(uint8_t)pattern3[i_bd]] = _mm_or_si128(Mask3, Peq_SSE[(uint8_t)pattern3[i_bd]]); - Peq_SSE[(uint8_t)pattern4[i_bd]] = _mm_or_si128(Mask4, Peq_SSE[(uint8_t)pattern4[i_bd]]); - ///Peq_SSE[(uint8_t)'T'] = _mm_or_si128(Peq_SSE[(uint8_t)'T'], Peq_SSE[(uint8_t)'C']); - } - - - - ///X = Peq[text[i]] | VN; - X = _mm_or_si128(Peq_SSE[(uint8_t)text[i]], VN); - - /*************D0 = ((VP + (X&VP)) ^ VP) | X*********************/ - ///X&VP - tmp_process1 = _mm_and_si128(X, VP); - ///(VP + (X&VP)) - tmp_process = _mm_add_epi32(tmp_process1, VP); - ///((VP + (X&VP)) ^ VP) - tmp_process = _mm_xor_si128(tmp_process, VP); - ///((VP + (X&VP)) ^ VP) | X - D0 = _mm_or_si128(tmp_process, X); - /*************D0 = ((VP + (X&VP)) ^ VP) | X*********************/ - - ///HN = VP&D0; - HN = _mm_and_si128(D0, VP); - - ///HP = VN | ~(VP | D0); - tmp_process = _mm_or_si128(D0, VP); - tmp_process = _mm_andnot_si128(tmp_process, for_not); - HP = _mm_or_si128(tmp_process, VN); - - - ///X = D0 >> 1; - X = _mm_srli_epi32(D0, 1); - ///VN = X&HP; - VN = _mm_and_si128(X, HP); - ///VP = HN | ~(X | HP); - tmp_process = _mm_or_si128(X, HP); - tmp_process = _mm_andnot_si128(tmp_process, for_not); - VP = _mm_or_si128(HN, tmp_process); - - ///D0&err_mask - err_arry = _mm_and_si128(D0, err_mask); - Err_4 = _mm_add_epi32(Err_4, err_mask); - Err_4 = _mm_sub_epi32(Err_4, err_arry); - - ///shi ji shang zhe ge zhi hen xiao d - cmp_result = _mm_cmpgt_epi32(Err_4, pre_end); - - ///jian zhi - if (_mm_extract_epi32(cmp_result, 0) && _mm_extract_epi32(cmp_result, 1) - && _mm_extract_epi32(cmp_result, 2) && _mm_extract_epi32(cmp_result, 3)) - return 1; - - int site = t_length - 1; - err1 = _mm_extract_epi32(Err_4, 0); - err2 = _mm_extract_epi32(Err_4, 1); - err3 = _mm_extract_epi32(Err_4, 2); - err4 = _mm_extract_epi32(Err_4, 3); - - - if ((err1 <= (int)errthold) && ((unsigned int)err1 <= return_sites_error[0])) - { - return_sites[0] = site; - return_sites_error[0] = err1; - } - if ((err2 <= (int)errthold) && ((unsigned int)err2 <= return_sites_error[1])) - { - return_sites[1] = site; - return_sites_error[1] = err2; - } - if ((err3 <= (int)errthold) && ((unsigned int)err3 <= return_sites_error[2])) - { - return_sites[2] = site; - return_sites_error[2] = err3; - } - if ((err4 <= (int)errthold) && ((unsigned int)err4 <= return_sites_error[3])) - { - return_sites[3] = site; - return_sites_error[3] = err4; - } - - - i = 0; - - /****************************may have bugs********************************/ - unsigned int ungap_error1 = (unsigned int)-1; - unsigned int ungap_error2 = (unsigned int)-1; - unsigned int ungap_error3 = (unsigned int)-1; - unsigned int ungap_error4 = (unsigned int)-1; - /****************************may have bugs********************************/ - - - ///in most cases, p_length should be t_length + 2 * errthold - int available_i = p_length - t_length; - - while (i < available_i) - { - ///err = err + ((VP >> i)&(Word_32)1); - tmp_process = _mm_srli_epi32(VP, i); - tmp_process = _mm_and_si128(tmp_process, err_mask); - Err_4 = _mm_add_epi32(Err_4, tmp_process); - - ///err = err - ((VN >> i)&(Word_32)1); - tmp_process1 = _mm_srli_epi32(VN, i); - tmp_process1 = _mm_and_si128(tmp_process1, err_mask); - Err_4 = _mm_sub_epi32(Err_4, tmp_process1); - ++i; - - err1 = _mm_extract_epi32(Err_4, 0); - err2 = _mm_extract_epi32(Err_4, 1); - err3 = _mm_extract_epi32(Err_4, 2); - err4 = _mm_extract_epi32(Err_4, 3); - - - if ((err1 <= (int)errthold) && ((unsigned int)err1 <= return_sites_error[0])) - { - return_sites[0] = site + i; - return_sites_error[0] = err1; - } - if ((err2 <= (int)errthold) && ((unsigned int)err2 <= return_sites_error[1])) - { - return_sites[1] = site + i; - return_sites_error[1] = err2; - } - if ((err3 <= (int)errthold) && ((unsigned int)err3 <= return_sites_error[2])) - { - return_sites[2] = site + i; - return_sites_error[2] = err3; - } - if ((err4 <= (int)errthold) && ((unsigned int)err4 <= return_sites_error[3])) - { - return_sites[3] = site + i; - return_sites_error[3] = err4; - } - - /****************************may have bugs********************************/ - if(i == (int)errthold) - { - ungap_error1 = err1; - ungap_error2 = err2; - ungap_error3 = err3; - ungap_error4 = err4; - } - /****************************may have bugs********************************/ - } - - /****************************may have bugs********************************/ - if((ungap_error1<=errthold) && (ungap_error1 == return_sites_error[0])) - { - return_sites[0] = site + errthold; - } - - if((ungap_error2<=errthold) && (ungap_error2 == return_sites_error[1])) - { - return_sites[1] = site + errthold; - } - - if((ungap_error3<=errthold) && (ungap_error3 == return_sites_error[2])) - { - return_sites[2] = site + errthold; - } - - if((ungap_error4<=errthold) && (ungap_error4 == return_sites_error[3])) - { - return_sites[3] = site + errthold; - } - /****************************may have bugs********************************/ - - return 1; -} - - -// void move_trace_gap(uint16_t *trace, int32_t trace_n, int32_t trace_i, -// char *pstr, int32_t pi, char *tstr, int32_t ti, int32_t *err) -// { -// uint16_t c = trace[trace_i]>>14, l = (trace[trace_i]<<2)>>2; -// if(c != 3 && c != 2) return; -// trace_i--; -// if(c == 3) pi--; -// else if(c == 2) ti--; - - -// if() - -// } - -// void adjust_trace(uint16_t *trace, int32_t *trace_n, int32_t *p_beg, int32_t *p_end, int32_t *err, char *pstr, char *tstr) -// { -// if((*err) == 0) return; -// int32_t i, pi, ti; uint16_t c, l; -// for (i = 0; i < (*trace_n) && (trace[i]>>14) == 1; i++) { -// trace[i] <<= 2; trace[i] >>= 2; trace[i] += (((uint16_t)3)<<14); -// l = (trace[i]<<2)>>2; (*p_beg) += l; -// } -// for (i = (*trace_n) - 1; i >= 0 && (trace[i]>>14) == 1; i--) { -// trace[i] <<= 2; trace[i] >>= 2; trace[i] += (((uint16_t)3)<<14); -// l = (trace[i]<<2)>>2; (*p_end) -= l; -// } - -// i = 0; pi = (*p_beg); ti = 0; -// for (i = 0; i < (*trace_n); i++) { -// c = trace[i]>>14; l = (trace[i]<<2)>>2; -// if(c == 0 || c == 1) { -// pi += l; ti += l; -// } else if(c == 2) { -// // move_trace_gap(trace, *trace_n, i, pstr, pi, tstr, ti, err); -// pi += l; -// } else if(c == 3) { -// // move_trace_gap(trace, *trace_n, i, pstr, pi, tstr, ti, err); -// ti += l; -// } -// } -// } - -inline int32_t ungap_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t know_err, int32_t know_end, -int32_t *r_err, int32_t *r_beg, asg16_v *cigar, int32_t *cigar_l) -{ - int32_t cn = cigar->n, pk, tk, e, l; - (*r_err) = (*r_beg) = INT32_MAX; (*cigar_l) = 0; - if(know_err < 0 || know_end < 0) return -1; - if(know_err == 0) { - push_trace(cigar, EAC_M, tn); - (*r_err) = know_err; (*r_beg) = know_end + 1 - tn; (*cigar_l) = cigar->n - cn; - return know_end; - } - - pk = know_end+1-tn; tk = 0; e = 0; - for (l = 0; tk < tn; tk++, pk++) { - if(pstr[pk]!=tstr[tk]) { - e++; if(e > know_err) break; - if(tk > l) push_trace(cigar, EAC_M, tk-l); - push_trace(cigar, MIS_M, 1); l = tk + 1; - } - } - if(tk == tn) { - if(tk > l) push_trace(cigar, EAC_M, tk-l); - (*r_err) = know_err; (*r_beg) = know_end + 1 - tn; (*cigar_l) = cigar->n - cn; - return know_end; - } - - cigar->n = cn; - return -1; -} - - -// ///p_length might be samller than t_length + 2 * errthold -inline int32_t ed_band_cal_semi_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, - int32_t know_err, int32_t know_end, int32_t *r_err, int32_t *r_beg, Word *buf, asg16_v *cigar, int32_t *cigar_l) { - int32_t cn = cigar->n; (*r_err) = (*r_beg) = INT32_MAX; (*cigar_l) = 0; - Word Peq[5] = {0}, mm = (Word)1, VP = 0, VN = 0, X = 0, D0 = 0, HN = 0, HP = 0, i_col, i_col_dux; - int32_t bd = (thre<<1)+1, i, err = 0, i_bd = (thre<<1), last_high = (thre<<1), tn0 = tn - 1; - int32_t cut = thre+last_high; ///kv_resize(uint16_t, *cigar, cigar->n+(uint32_t)know_err+2);//pre-alloc - - if(ungap_trace(pstr, pn, tstr, tn, know_err, know_end, r_err, r_beg, cigar, cigar_l) >= 0) { - return know_end; - } - - for (i = 0; i < bd; i++) { - Peq[seq_nt4_table[(uint8_t)pstr[i]]] |= mm; mm <<= 1; - } - Peq[4] = 0; - ///should make Peq[4] = 0 if N is always an error - i = i_col = 0; mm = ((Word)1 << (thre<<1));///for the incoming char/last char - - while (i < tn0) { - X = Peq[seq_nt4_table[(uint8_t)tstr[i]]] | VN; - - D0 = ((VP + (X&VP)) ^ VP) | X; - - HN = VP&D0; - HP = VN | ~(VP | D0); - - X = D0 >> 1; - VN = X&HP; - VP = HN | ~(X | HP); - - if (!(D0&(1ULL))) { - ++err; - if (err>cut) return -1; - } - - Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; ///Peq[4] >>= 1; - - ++i; ++i_bd; - Peq[seq_nt4_table[(uint8_t)pstr[i_bd]]] |= mm; Peq[4] = 0; - - buf[i_col++] = D0; buf[i_col++] = VP; buf[i_col++] = VN; buf[i_col++] = HP; buf[i_col++] = HN; - } - - X = Peq[seq_nt4_table[(uint8_t)tstr[i]]] | VN; - D0 = ((VP + (X&VP)) ^ VP) | X; - HN = VP&D0; - HP = VN | ~(VP | D0); - X = D0 >> 1; - VN = X&HP; - VP = HN | ~(X | HP); - if (!(D0&(1ULL))) { - ++err; - if (err>cut) return -1; - } - - buf[i_col++] = D0; buf[i_col++] = VP; buf[i_col++] = VN; buf[i_col++] = HP; buf[i_col++] = HN; - - i_col_dux = i_col/tn; - - int32_t site = tn - 1, end = -1;///up bound - ///in most cases, ai = (thre<<1) - int32_t ai = pn - tn, uge = INT32_MAX; - if ((err <= thre) && (err<=(*r_err))) { - *r_err = err; end = site; - } - i = 0; - - while (i < ai) { - err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); ++i; - if ((err <= thre) && (err <= (*r_err))) { - *r_err = err; end = site + i; - } - if(i == thre) uge = err; - } - if((uge<=thre) && (uge == (*r_err))) end = site + thre; - if ((*r_err) > thre) return end; - - - ///need to correct pn here, since pn might be smaller than tn + 2* thre - pn = tn + (thre<<1); - int32_t beg = end, back_track_site = bd - (pn - end); - - Word v_value, h_value, delta_value, min_value, current_value; - ///Word direction; ///0 is match, 1 is mismatch, 2 is up, 3 is left - Word direction = 0, *ba, pd, pdl; ///0 is match, 1 is mismatch, 2 is up, 3 is left - i = tn; pd = (Word)-1; pdl = 0; - current_value = *r_err; - int32_t low_bound = bd - 1; - - while (i > 0) { - if (current_value == 0) break; - ba = buf + ((i*i_col_dux) - i_col_dux); - delta_value = current_value - ((~(ba[0]>>back_track_site))&(1ULL)); - - if (back_track_site == 0) { - ///HP - h_value = current_value - ((ba[3] >> back_track_site)&(1ULL)); - //HN - h_value = h_value + ((ba[4] >> back_track_site)&1ULL); - min_value = delta_value; direction = 0; - if (h_value < min_value) { - min_value = h_value; - direction = 3; - } - } else if (back_track_site == low_bound) { - v_value = current_value - ((ba[1]>>(back_track_site-1))&(1ULL)); - v_value = v_value + ((ba[2]>>(back_track_site-1))&(1ULL)); - - min_value = delta_value; direction = 0; - if (v_value < min_value) { - min_value = v_value; - direction = 2; - } - } - else { - h_value = current_value-((ba[3]>>back_track_site)&(1ULL)); - h_value = h_value+((ba[4]>>back_track_site)&(1ULL)); - - v_value = current_value - ((ba[1]>>(back_track_site-1))&(1ULL)); - v_value = v_value + ((ba[2]>>(back_track_site-1))&(1ULL)); - - min_value = delta_value; direction = 0; - if (v_value < min_value) { - min_value = v_value; - direction = 2; - } - - if (h_value < min_value) { - min_value = h_value; - direction = 3; - } - } - - - if (direction == 0) { - if (delta_value != current_value) { - direction = 1; - } - i--; beg--; - } - if (direction == 2) {///ru guo xiang shang yi dong, bing bu huan lie - back_track_site--; beg--; - } - else if (direction == 3) {///ru guo xiang zuo yi dong - i--; - back_track_site++; - } - - if(direction != pd) { - if(pdl > 0) push_trace(cigar, pd, pdl); - pd = direction; pdl = 1; - } else { - pdl++; - } - // path[path_length++] = direction; - current_value = min_value; - } - - - if (i > 0) { - direction = 0; beg -= i; - if(direction != pd) { - if(pdl > 0) push_trace(cigar, pd, pdl); - pd = direction; pdl = i; - } else { - pdl += i; - } - } - - if(pdl > 0) push_trace(cigar, pd, pdl); - if (direction != 3) beg++; - - uint16_t *trac = cigar->a + cn, tt; int32_t trac_n = cigar->n - cn; ai = trac_n>>1; - for (i = 0; i < ai; i++) { - tt = trac[i]; trac[i] = trac[trac_n-i-1]; trac[trac_n-i-1] = tt; - } - (*cigar_l) = cigar->n - cn; - - (*r_beg) = beg; (*cigar_l) = cigar->n - cn; - return end; -} - - -#endif +#ifndef __LEVENSHTEIN__ +#define __LEVENSHTEIN__ + +#define __STDC_LIMIT_MACROS +#include +#include "emmintrin.h" +#include "nmmintrin.h" +#include "smmintrin.h" +#include +#include +#include +#include +#include "kvec.h" + +extern const unsigned char seq_nt4_table[256]; +typedef uint64_t Word; +typedef uint32_t Word_32; +typedef struct {size_t n, m; uint16_t *a; } asg16_v; + +inline void get_error(int t_length, int errthold, int init_err, Word VP, Word VN, +unsigned int* return_err, int* back_site) +{ + (*return_err) = (unsigned int)-1; + int site = t_length - 1; + int return_site = -1; + ///in most cases, p_length should be t_length + 2 * errthold + ///int available_i = p_length - t_length; + int available_i = 2 * errthold; + + + if ((init_err <= errthold) && ((unsigned int)init_err <= (*return_err))) + { + (*return_err) = init_err; + return_site = site; + } + + + int i = 0; + unsigned int ungap_error = (unsigned int)-1; + + while (i < available_i) + { + init_err = init_err + ((VP >> i)&(Word)1); + init_err = init_err - ((VN >> i)&(Word)1); + ++i; + + if ((init_err <= errthold) && ((unsigned int)init_err <= *return_err)) + { + *return_err = init_err; + return_site = site + i; + } + + /****************************may have bugs********************************/ + if(i == errthold) + { + ungap_error = init_err; + } + /****************************may have bugs********************************/ + } + + /****************************may have bugs********************************/ + if((ungap_error<=(unsigned int)errthold) && (ungap_error == (*return_err))) + { + return_site = site + errthold; + } + /****************************may have bugs********************************/ + + (*back_site) = return_site; +} + +inline int Reserve_Banded_BPM_Extension +(char *pattern, int p_length, char *text, int t_length, unsigned short errthold, +unsigned int* return_err, int* return_p_end, int* return_t_end) +{ + (*return_err) = (unsigned int)-1; + (*return_p_end) = -1; + (*return_t_end) = -1; + + Word Peq[256]; + + unsigned int line_error = (unsigned int)-1; + int return_site; + int band_length = (errthold << 1) + 1; + int i = 0; + Word tmp_Peq_1 = (Word)1; + + Peq[(uint8_t)'A'] = (Word)0; + Peq[(uint8_t)'T'] = (Word)0; + Peq[(uint8_t)'G'] = (Word)0; + Peq[(uint8_t)'C'] = (Word)0; + + + Word Peq_A; + Word Peq_T; + Word Peq_C; + Word Peq_G; + + ///band_length = 2k + 1 + for (i = 0; i> 1; + VN = X&HP; + VP = HN | ~(X | HP); + + if (!(D0&err_mask)) + { + ++err; + if ((err - last_high)>errthold) + { + return (*return_t_end); + } + } + get_error(i + 1, errthold, err, VP, VN, &line_error, &return_site); + if(line_error != (unsigned int)-1) + { + (*return_t_end) = i; + (*return_p_end) = return_site; + (*return_err) = line_error; + } + + Peq[(uint8_t)'A'] = Peq[(uint8_t)'A'] >> 1; + Peq[(uint8_t)'C'] = Peq[(uint8_t)'C'] >> 1; + Peq[(uint8_t)'G'] = Peq[(uint8_t)'G'] >> 1; + Peq[(uint8_t)'T'] = Peq[(uint8_t)'T'] >> 1; + + + ++i; + ++i_bd; + Peq[(uint8_t)pattern[i_bd]] = Peq[(uint8_t)pattern[i_bd]] | Mask; + } + + + + + + X = Peq[(uint8_t)text[i]] | VN; + D0 = ((VP + (X&VP)) ^ VP) | X; + HN = VP&D0; + HP = VN | ~(VP | D0); + X = D0 >> 1; + VN = X&HP; + VP = HN | ~(X | HP); + if (!(D0&err_mask)) + { + ++err; + if ((err - last_high)>errthold) + { + return (*return_t_end); + } + } + ///i = t_length - 1 + get_error(i + 1, errthold, err, VP, VN, &line_error, &return_site); + if(line_error != (unsigned int)-1) + { + (*return_t_end) = i; + (*return_p_end) = return_site; + (*return_err) = line_error; + } + + return (*return_t_end); +} + +inline int Reserve_Banded_BPM_Extension_REV +(char *pattern, int p_length, char *text, int t_length, unsigned short errthold, +unsigned int* return_err, int* return_p_end, int* return_t_end) +{ + (*return_err) = (unsigned int)-1; + (*return_p_end) = -1; + (*return_t_end) = -1; + + Word Peq[256]; + + unsigned int line_error = (unsigned int)-1; + int return_site; + int band_length = (errthold << 1) + 1; + int i = 0; + Word tmp_Peq_1 = (Word)1; + + Peq[(uint8_t)'A'] = (Word)0; + Peq[(uint8_t)'T'] = (Word)0; + Peq[(uint8_t)'G'] = (Word)0; + Peq[(uint8_t)'C'] = (Word)0; + + + Word Peq_A; + Word Peq_T; + Word Peq_C; + Word Peq_G; + + ///band_length = 2k + 1 + for (i = 0; i> 1; + VN = X&HP; + VP = HN | ~(X | HP); + + if (!(D0&err_mask)) + { + ++err; + if ((err - last_high)>errthold) + { + return (*return_t_end); + } + } + get_error(i + 1, errthold, err, VP, VN, &line_error, &return_site); + if(line_error != (unsigned int)-1) + { + (*return_t_end) = t_length-i-1; + (*return_p_end) = p_length-return_site-1; + (*return_err) = line_error; + } + + Peq[(uint8_t)'A'] = Peq[(uint8_t)'A'] >> 1; + Peq[(uint8_t)'C'] = Peq[(uint8_t)'C'] >> 1; + Peq[(uint8_t)'G'] = Peq[(uint8_t)'G'] >> 1; + Peq[(uint8_t)'T'] = Peq[(uint8_t)'T'] >> 1; + + + ++i; + ++i_bd; + Peq[(uint8_t)pattern[p_length-i_bd-1]] = Peq[(uint8_t)pattern[p_length-i_bd-1]] | Mask; + } + + + + + + X = Peq[(uint8_t)text[t_length-i-1]] | VN; + D0 = ((VP + (X&VP)) ^ VP) | X; + HN = VP&D0; + HP = VN | ~(VP | D0); + X = D0 >> 1; + VN = X&HP; + VP = HN | ~(X | HP); + if (!(D0&err_mask)) + { + ++err; + if ((err - last_high)>errthold) + { + return (*return_t_end); + } + } + ///i = t_length - 1 + get_error(i + 1, errthold, err, VP, VN, &line_error, &return_site); + if(line_error != (unsigned int)-1) + { + (*return_t_end) = t_length-i-1; + (*return_p_end) = p_length-return_site-1; + (*return_err) = line_error; + } + + return (*return_t_end); +} + +inline void reverse_string(char* str, int strLen) +{ + int i, Len; + char k; + Len = strLen / 2; + for (i = 0; i < Len; i++) + { + k = str[i]; + str[i] = str[strLen - i - 1]; + str[strLen - i - 1] = k; + } +} + +inline int alignment_extension(char *pattern, int p_length, char *text, int t_length, +unsigned short errthold, int direction, unsigned int* return_err, int* return_p_end, +int* return_t_end, int* return_aligned_t_len) +{ + (*return_aligned_t_len) = 0; + + if(direction == 0) + { + Reserve_Banded_BPM_Extension(pattern, p_length, text, t_length, errthold, return_err, + return_p_end, return_t_end); + if((*return_p_end) != -1 && (*return_t_end) != -1) + { + (*return_aligned_t_len) = (*return_t_end) + 1; + return 1; + } + else + { + return -1; + } + + } + else + { + reverse_string(pattern, p_length); + reverse_string(text, t_length); + + Reserve_Banded_BPM_Extension(pattern, p_length, text, t_length, errthold, return_err, + return_p_end, return_t_end); + + reverse_string(pattern, p_length); + reverse_string(text, t_length); + + if((*return_p_end) != -1 && (*return_t_end) != -1) + { + (*return_aligned_t_len) = (*return_t_end) + 1; + (*return_p_end) = p_length - (*return_p_end); + (*return_t_end) = t_length - (*return_t_end); + return 1; + } + else + { + return -1; + } + } +} + +inline void print_bit(Word z, int64_t w, const char *cmd) +{ + int64_t k;//, w = (sizeof(Word)<<3); + fprintf(stderr, "%s\t", cmd); + for (k = w-1; k >= 0; k--) fprintf(stderr, "%llu", (z>>k)&(1ULL)); + fprintf(stderr, "\n"); +} + +inline int32_t ed_band_cal_global(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre) +{ + if((pn > tn + thre) || (tn > pn + thre)) return INT32_MAX; + if((pn < thre + 1) || (tn < thre + 1)) return INT32_MAX; + Word Peq[5] = {0}, mm, VP = 0, VN = 0, X = 0, D0 = 0, HN = 0, HP = 0; + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd = thre+1, i_bd = thre; + // fprintf(stderr, "\n[M::%s::]\n", __func__); + for (i = 0, mm = (((Word)1)<> 1; + VN = X&HP; + VP = HN | ~(X | HP); + // fprintf(stderr, "\n[M::%s::i->%d]\n", __func__, i); + // print_bit(VN, (thre<<1)+1, "VN"); + // print_bit(VP, (thre<<1)+1, "VP"); + // print_bit(HN, (thre<<1)+1, "HN"); + // print_bit(HP, (thre<<1)+1, "HP"); + // print_bit(D0, (thre<<1)+1, "D0"); + + if (!(D0&(1ULL))) { + ++err; + if (err>cut) return INT32_MAX; + } + // fprintf(stderr, "[M::%s::i->%d] err->%d\n", __func__, i, err); + + Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; ///Peq[4] >>= 1; + + ++i; ++i_bd; + if(i_bd < pn) { + Peq[seq_nt4_table[(uint8_t)pstr[i_bd]]] |= mm; Peq[4] = 0; + } + // if(i < pn) Peq[seq_nt4_table[(uint8_t)pstr[i]]] |= mm; + } + + X = Peq[seq_nt4_table[(uint8_t)tstr[i]]] | VN; + D0 = ((VP + (X&VP)) ^ VP) | X; + HN = VP&D0; + HP = VN | ~(VP | D0); + X = D0 >> 1; + VN = X&HP; + VP = HN | ~(X | HP); + // fprintf(stderr, "\n[M::%s::i->%d]\n", __func__, i); + // print_bit(VN, (thre<<1)+1, "VN"); + // print_bit(VP, (thre<<1)+1, "VP"); + // print_bit(HN, (thre<<1)+1, "HN"); + // print_bit(HP, (thre<<1)+1, "HP"); + // print_bit(D0, (thre<<1)+1, "D0"); + if (!(D0&(1ULL))) { + ++err; + if (err>cut) return INT32_MAX; + } + // fprintf(stderr, "[M::%s::i->%d] err->%d\n", __func__, i, err); + + int32_t site = tn - 1 - thre;///up bound + for (cut = pn - 1, i = 0; site < cut; site++, i++) { + // fprintf(stderr, "+[M::%s::site->%d] err->%d\n", __func__, site, err); + err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); + // fprintf(stderr, "-[M::%s::site->%d] err->%d\n", __func__, site, err); + } + + if (site == cut && err <= thre) return err; + return INT32_MAX; +} + +#define EAC_M 0 +#define MIS_M 1 +#define MOR_YP 2 +#define MOR_XT 3 + +inline void push_trace(asg16_v *res, uint16_t c, uint32_t len) +{ + uint16_t p; c <<= 14; + while (len >= (0x3fff)) { + p = (c + (0x3fff)); kv_push(uint16_t, *res, p); len -= (0x3fff); + } + if(len) { + p = (c + len); kv_push(uint16_t, *res, p); + } +} + +inline uint32_t pop_trace(asg16_v *res, uint32_t i, uint16_t *c, uint32_t *len) +{ + (*c) = (res->a[i]>>14); (*len) = (res->a[i]&(0x3fff)); + for (i++; (i < res->n) && ((*c) == (res->a[i]>>14)); i++) { + (*len) += (res->a[i]&(0x3fff)); + } + return i; +} + +inline int32_t pop_trace_back(asg16_v *res, int32_t i, uint16_t *c, uint32_t *len) +{ + (*c) = (res->a[i]>>14); (*len) = (res->a[i]&(0x3fff)); + for (i--; (i >= 0) && ((*c) == (res->a[i]>>14)); i--) { + (*len) += (res->a[i]&(0x3fff)); + } + return i; +} + +///compact functions +#define pop_trac_bpc(in, rc, rb, rl) do { \ + (rc) = ((in)>>14);\ + if((rc) == 1 || (rc) == 2) {(rb) = (((in)>>12)&3); (rl) = ((in)&(0xfff));}\ + else {(rl) = ((in)&(0x3fff));}\ + } while (0) + +inline void push_trace_bp(asg16_v *res, uint16_t c, uint16_t b, uint32_t len, uint32_t is_append) +{ + uint16_t p, c0, b0, len0, mm; + if((is_append) && (res->n)) { + b0 = b; + pop_trac_bpc(res->a[res->n-1], c0, b0, len0); + if((c == c0) && (b == b0)) { + res->n--; len += len0; + } + } + + mm = (0x3fff); c0 = c; c <<= 14; + if(c0 == 1 || c0 == 2) { + mm = (0xfff); c += ((b&3) << 12); + } + + + while (len >= mm) { + p = (c + mm); kv_push(uint16_t, *res, p); len -= mm; + } + // fprintf(stderr, "[M::%s] c::%u, len::%u\n", __func__, c, len); + if(len) { + p = (c + len); kv_push(uint16_t, *res, p); + } +} + +inline uint32_t pop_trace_bp(asg16_v *res, uint32_t i, uint16_t *c, uint16_t *b, uint32_t *len) +{ + (*c) = (res->a[i]>>14); + if((*c) == 1 || (*c) == 2) { + (*b) = ((res->a[i]>>12)&3); + (*len) = (res->a[i]&(0xfff)); + } else { + (*b) = (uint16_t)-1; + (*len) = (res->a[i]&(0x3fff)); + } + + uint32_t sl; uint16_t sb; + for (i++; (i < res->n) && ((*c) == (res->a[i]>>14)); i++) { + if((*c) == 1 || (*c) == 2) { + sb = ((res->a[i]>>12)&3); sl = (res->a[i]&(0xfff)); + } else { + sb = (uint16_t)-1; sl = (res->a[i]&(0x3fff)); + } + if((*b) != sb) break; + (*len) += sl; + } + return i; +} + +inline int64_t pop_trace_bp_rev(asg16_v *res, int64_t i, uint16_t *c, uint16_t *b, uint32_t *len) +{ + (*c) = (res->a[i]>>14); + if((*c) == 1 || (*c) == 2) { + (*b) = ((res->a[i]>>12)&3); + (*len) = (res->a[i]&(0xfff)); + } else { + (*b) = (uint16_t)-1; + (*len) = (res->a[i]&(0x3fff)); + } + + uint32_t sl; uint16_t sb; + for (i--; (i >= 0) && ((*c) == (res->a[i]>>14)); i--) { + if((*c) == 1 || (*c) == 2) { + sb = ((res->a[i]>>12)&3); sl = (res->a[i]&(0xfff)); + } else { + sb = (uint16_t)-1; sl = (res->a[i]&(0x3fff)); + } + if((*b) != sb) break; + (*len) += sl; + } + return i; +} + +///full functions +#define pop_trac_bpc_f(in, rc, rbq, rbt, rl) do { \ + (rc) = ((in)>>14);\ + if((rc) == 2 || (rc) == 3) {(rbt) = (((in)>>12)&3); (rl) = ((in)&(0xfff));}\ + else if((rc) == 1) {(rbt) = (((in)>>12)&3); (rbq) = (((in)>>10)&3); (rl) = ((in)&(0x3ff));}\ + else {(rl) = ((in)&(0x3fff));}\ + } while (0) + +inline void push_trace_bp_f(asg16_v *res, uint16_t c, uint16_t bq, uint16_t bt, uint32_t len, uint32_t is_append) +{ + uint16_t p, c0 = c, bq0, bt0, len0, mm; + if(c == 3) { + bt = bq; bq = (uint16_t)-1; + } + if((is_append) && (res->n)) { + bq0 = bq; bt0 = bt; + pop_trac_bpc_f(res->a[res->n-1], c0, bq0, bt0, len0); + if((c == c0) && (bq == bq0) && (bt == bt0)) { + res->n--; len += len0; + } + } + + + c0 = c; c <<= 14; + if(c0 == 2 || c0 == 3) { + mm = (0xfff); c += ((bt&3) << 12); + } else if(c0 == 1) { + mm = (0x3ff); c += ((bt&3) << 12); c += ((bq&3) << 10); + } else { + mm = (0x3fff); + } + + + while (len >= mm) { + p = (c + mm); kv_push(uint16_t, *res, p); len -= mm; + } + // fprintf(stderr, "[M::%s] c::%u, len::%u\n", __func__, c, len); + if(len) { + p = (c + len); kv_push(uint16_t, *res, p); + } +} + +inline uint32_t pop_trace_bp_f(asg16_v *res, uint32_t i, uint16_t *c, uint16_t *bq, uint16_t *bt, uint32_t *len) +{ + (*c) = (res->a[i]>>14); (*bq) = (*bt) = (uint16_t)-1; + if((*c) == 2 || (*c) == 3) { + (*bt) = ((res->a[i]>>12)&3); + (*len) = (res->a[i]&(0xfff)); + } else if((*c) == 1) { + (*bt) = ((res->a[i]>>12)&3); + (*bq) = ((res->a[i]>>10)&3); + (*len) = (res->a[i]&(0x3ff)); + } else { + (*len) = (res->a[i]&(0x3fff)); + } + + uint32_t sl; uint16_t sbq, sbt; + for (i++; (i < res->n) && ((*c) == (res->a[i]>>14)); i++) { + sbq = sbt = (uint16_t)-1; + if((*c) == 2 || (*c) == 3) { + sbt = ((res->a[i]>>12)&3); + sl = (res->a[i]&(0xfff)); + } else if((*c) == 1) { + sbt = ((res->a[i]>>12)&3); + sbq = ((res->a[i]>>10)&3); + sl = (res->a[i]&(0x3ff)); + } else { + sl = (res->a[i]&(0x3fff)); + } + if((*bq) != sbq || (*bt) != sbt) break; + (*len) += sl; + } + if((*c) == 3) { + (*bq) = (*bt); (*bt) = (uint16_t)-1; + } + return i; +} + +inline int64_t pop_trace_bp_rev_f(asg16_v *res, int64_t i, uint16_t *c, uint16_t *bq, uint16_t *bt, uint32_t *len) +{ + (*c) = (res->a[i]>>14); (*bq) = (*bt) = (uint16_t)-1; + if((*c) == 2 || (*c) == 3) { + (*bt) = ((res->a[i]>>12)&3); + (*len) = (res->a[i]&(0xfff)); + } else if((*c) == 1) { + (*bt) = ((res->a[i]>>12)&3); + (*bq) = ((res->a[i]>>10)&3); + (*len) = (res->a[i]&(0x3ff)); + } else { + (*len) = (res->a[i]&(0x3fff)); + } + + uint32_t sl; uint16_t sbq, sbt; + for (i--; (i >= 0) && ((*c) == (res->a[i]>>14)); i--) { + sbq = sbt = (uint16_t)-1; + if((*c) == 2 || (*c) == 3) { + sbt = ((res->a[i]>>12)&3); + sl = (res->a[i]&(0xfff)); + } else if((*c) == 1) { + sbt = ((res->a[i]>>12)&3); + sbq = ((res->a[i]>>10)&3); + sl = (res->a[i]&(0x3ff)); + } else { + sl = (res->a[i]&(0x3fff)); + } + if((*bq) != sbq || (*bt) != sbt) break; + (*len) += sl; + } + if((*c) == 3) { + (*bq) = (*bt); (*bt) = (uint16_t)-1; + } + return i; +} + +///511 -> 16 64-bits +// #define MAX_E 511 +// #define MAX_L 2500 + +///511 -> 32 64-bits +#define MAX_CNS_E 1023 +#define MAX_CNS_L 3072 +#define FORCE_CNS_L 256 + + +#define MAX_SIN_E 2047 +#define MAX_SIN_L 10000 +#define FORCE_SIN_L 512 + +typedef uint64_t w_sig; +#define bitw (6) +#define bitwbit (64) +#define bitz (63) +// typedef uint32_t w_sig; +// #define bitw (5) +// #define bitwbit (32) +// #define bitz (31) +// typedef uint16_t w_sig; +// #define bitw (4) +// #define bitwbit (16) +// #define bitz (15) +// typedef uint8_t w_sig; +// #define bitw (3) +// #define bitwbit (8) +// #define bitz (7) +typedef struct {w_sig *a;} w128_t; +typedef struct {size_t n, m; w_sig *a;} w64_trace_t; +typedef struct { + int32_t done_cigar, cigar_n, done_path, path_n; + int32_t ps, pe, pl, ts, te, tl; + int32_t thre, err, nword, mword; + uint32_t m, mm_thres; w_sig *a; + w128_t Peq[5], mm, VP, VN, X, D0, HN, HP; + asg16_v cigar; w64_trace_t path; +} bit_extz_t; + +#define is_align(exz) ((exz).err<=(exz).thre) +#define clear_align(exz) ((exz).err=INT32_MAX) + +inline uint32_t cigar_check(char *pstr, char *tstr, bit_extz_t *ez) +{ + int32_t pi = ez->ps, ti = ez->ts, err = 0; uint32_t ci = 0, cl, k; uint16_t c; + while (ci < ez->cigar.n) { + ci = pop_trace(&(ez->cigar), ci, &c, &cl); + // fprintf(stderr, "# %u = %u\n", c, cl); + if(c == 0) { + for (k=0;(kerr) { + fprintf(stderr, "ERROR-err\n"); + return 0; + } + if(pi != ez->pe + 1) { + fprintf(stderr, "ERROR-pi\n"); + return 0; + } + if(ti != ez->te + 1) { + fprintf(stderr, "ERROR-ti\n"); + return 0; + } + + return 1; +} + +inline int32_t dbg_ext_err(int32_t i, int32_t thre, int32_t err, int32_t pe, w128_t *VP, w128_t *VN) +{ + int32_t poff = i-thre, tmp_e = INT32_MAX, k, bd, k_bd; + if((poff) + (thre<<1) >= (pe)) { + tmp_e = err; + for ((k) = 0; (poff) < (pe); (poff)++) { + bd = (k>>bitw); k_bd = (k&bitz); + (tmp_e) += ((VP->a[bd]>>k_bd)&((w_sig)1)); + (tmp_e) -= ((VN->a[bd]>>k_bd)&((w_sig)1)); + (k)++; + } + } + return tmp_e; +} + + +inline void print_bits(w_sig *az, int64_t w, const char *cmd) +{ + int64_t k, m, s = (sizeof(*az)<<3), sw = (w/s) + (!!(w%s)), ks; + fprintf(stderr, "%s\t", cmd); + for (m = sw - 1, k = w-1; m >= 0 && k >= 0; m--) { + for (ks = k%s; ks >= 0 && k >= 0; ks--, k--) fprintf(stderr, "%llu", (az[m]>>ks)&(1ULL)); + } + fprintf(stderr, "\n"); +} + +#define prt_bit_extz_t(ez, w) do { \ + print_bits((ez).Peq[0].a, w, "Peq[0]");\ + print_bits((ez).Peq[1].a, w, "Peq[1]");\ + print_bits((ez).Peq[2].a, w, "Peq[2]");\ + print_bits((ez).Peq[3].a, w, "Peq[3]");\ + print_bits((ez).Peq[4].a, w, "Peq[4]");\ + print_bits((ez).VP.a, w, "VP");\ + print_bits((ez).VN.a, w, "VN");\ + print_bits((ez).X.a, w, "X");\ + print_bits((ez).D0.a, w, "D0");\ + print_bits((ez).HN.a, w, "HN");\ + print_bits((ez).HP.a, w, "HP");\ +} while (0) + + + +#define resize_bit_extz_t(ex, thres) do { \ + if(((int32_t)(thres)) > ((int32_t)(ex).mm_thres)) {\ + (ex).mm_thres = (((thres)<<1)+1);\ + (ex).mm_thres = (((ex).mm_thres>>bitw)+(!!((ex).mm_thres&bitz)))*12;\ + if((ex).mm_thres > (ex).m) {\ + (ex).a = (w_sig *)realloc((ex).a, (ex).mm_thres * sizeof(*((ex).a)));\ + (ex).mm_thres/=12; (ex).m=0;\ + (ex).Peq[0].a = (ex).a; (ex).m+=(ex).mm_thres;\ + (ex).Peq[1].a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ + (ex).Peq[2].a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ + (ex).Peq[3].a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ + (ex).Peq[4].a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ + (ex).mm.a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ + (ex).VP.a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ + (ex).VN.a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ + (ex).X.a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ + (ex).D0.a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ + (ex).HN.a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ + (ex).HP.a = (ex).a+(ex).m; (ex).m+=(ex).mm_thres;\ + (ex).mword = (ex).mm_thres;\ + }\ + (ex).mm_thres = (thres);\ + }\ + } while (0) + +inline void init_bit_extz_t(bit_extz_t *ex, uint64_t thres) { + memset(ex, 0, sizeof((*ex))); + ///(bitwbit<<2) >= (((thres)<<1)+1);->at least 4 cells for each w128_t + if(((uint64_t)thres)<(((((uint64_t)bitwbit)<<2)-1)>>1)) thres=(((bitwbit<<2)-1)>>1); + resize_bit_extz_t((*ex), (thres)); +} + +inline void destroy_bit_extz_t(bit_extz_t *ex) { + free((*ex).a); free((*ex).path.a); free((*ex).cigar.a); +} + + +inline void gen_trace(bit_extz_t *ez, int32_t ptrim, int32_t reverse)///ptrim = thre for global and extension; = 0 for semi +{ + if(ez->err > ez->thre) return; + ez->cigar.n = 0; + int32_t V, H, D, min, cur, tn = (ez->te+1-ez->ts), pn = tn + (ez->thre<<1), bd = (ez->thre<<1)+1; + int32_t bs = ez->path.n/tn, bbs = bs/5, poff = ez->pe, sft = bd - (pn - ez->pe - ptrim); + int32_t i = tn, low = bd-1, wi, wm, d = 0, pd = -1, pdn = 0; cur = ez->err; + w_sig *D0, *VP, *VN, *HP, *HN; + + // fprintf(stderr, "\n[M::%s::] bs::%d, bbs::%d, cur::%d, poff::%d, sft::%d\n", __func__, bs, bbs, cur, poff, sft); + + while (i > 0 && cur > 0) { + D0 = ez->path.a + ((i-1)*bs); VP = D0 + bbs; VN = VP + bbs; HP = VN + bbs; HN = HP + bbs; + + wi = (sft>>bitw); wm = sft&bitz; + D = cur - ((~(D0[wi]>>wm))&(1ULL)); d = 0; min = D; + H = V = INT32_MAX; + if(sft!=low) { + H = cur + ((HN[wi]>> wm)&(1ULL)) - ((HP[wi]>> wm)&(1ULL)); + if ((H+1) == cur && H <= min) {//prefer indels + min = H; d = 3; + } + } + if(sft!=0) { + wi = ((sft-1)>>bitw); wm = (sft-1)&bitz; + V = cur + ((VN[wi]>> wm)&(1ULL)) - ((VP[wi]>> wm)&(1ULL)); + if ((V+1) == cur && V <= min) {//prefer indels + min = V; d = 2; + } + } + // fprintf(stderr, "[M::%s::] cur::%d, D::%d, V::%d, H::%d, poff::%d, toff::%d, d::%d\n", __func__, cur, D, V, H, poff, i, d); + if(d == 0) { + if(D != cur) d = 1; + i--; poff--; + } else if(d == 2) {//more pstr + sft--; poff--; + } else if(d == 3) {///more tstr + i--; sft++; + } + + if(d == pd) { + pdn++; + } else { + if(pdn > 0) push_trace(&(ez->cigar), pd, pdn); + pd = d; pdn = 1; + } + cur = min; + } + + if (i > 0) { + d = 0; poff -= i; + if(d == pd) { + pdn += i; + } else { + if(pdn > 0) push_trace(&(ez->cigar), pd, pdn); + pd = d; pdn = i; + } + } + + poff++; + // fprintf(stderr, "[M::%s::] poff::%d, ez->ps::%d\n", __func__, poff, ez->ps); + if(ez->ps < 0 || ez->ps >= ez->pl) {//ps is unavailable + ez->ps = poff; + } else if(poff > ez->ps){ + d = 2; i = poff - ez->ps; + if(d == pd) { + pdn += i; + } else { + if(pdn > 0) push_trace(&(ez->cigar), pd, pdn); + pd = d; pdn = i; + } + } + if(pdn > 0) push_trace(&(ez->cigar), pd, pdn); + + if(reverse) { + uint16_t t; pdn = ez->cigar.n>>1; + for (i = 0; i < pdn; i++) { + t = ez->cigar.a[i]; + ez->cigar.a[i] = ez->cigar.a[ez->cigar.n-i-1]; + ez->cigar.a[ez->cigar.n-i-1] = t; + } + } +} + + + +#define init_base_ed(ez, thre, pn, tn) {\ + (ez).thre = (thre), (ez).err = INT32_MAX, (ez).pl = pn, (ez).tl = tn;\ + (ez).done_cigar = (ez).done_path = (ez).cigar_n = (ez).path_n = 0;\ +} + +#define w_bit(x, b) ((x).a[((b)>>bitw)]|=(((w_sig)1)<<((b)&bitz))) + +#define w_get_bit(x, b) (((x).a[((b)>>bitw)]>>((b)&bitz))&((w_sig)1)) + +/***********************2 words***********************/ +#define w_128_clear(x) ((x).a[0]=(x).a[1]=0) + +#define w_128_word (2) + +#define w_128_self_not(x) ((x).a[0]=~(x).a[0], \ + (x).a[1]=~(x).a[1]) + +#define w_128_self_or(x, y) ((x).a[0]|=(y).a[0], \ + (x).a[1]|=(y).a[1]) + +#define w_128_or(r, x, y) ((r).a[0] = (x).a[0]|(y).a[0], \ + (r).a[1] = (x).a[1]|(y).a[1]) + +#define w_128_and(r, x, y) ((r).a[0] = (x).a[0]&(y).a[0], \ + (r).a[1] = (x).a[1]&(y).a[1]) + +#define w_128_self_xor(x, y) ((x).a[0]^=(y).a[0], \ + (x).a[1]^=(y).a[1]) + +#define w_128_self_lsft_1(x) ((x).a[1] = ((x).a[1]<<1)|((x).a[0]>>bitz), \ + (x).a[0] <<= 1) + +#define w_128_self_rsft_1(x) ((x).a[0] = ((x).a[0]>>1)|((x).a[1]<>= 1) + +#define w_128_rsft_1(x, y) ((x).a[0] = ((y).a[0]>>1)|((y).a[1]<>1) +#define w_128_self_add(x, y, c) ((x).a[0]+=(y).a[0], \ + (x).a[1]+=(y).a[1]+((x).a[0]<(y).a[0])) + +#define w_128_set_bit_lsub(x, l) do { \ + (x).a[0] = (w_sig)-1, (x).a[1] = 0; \ + if((l) <= bitwbit) (x).a[0] = (((w_sig)1)<<(l))-1; \ + else (x).a[1] = (((w_sig)1)<<((l)-bitwbit))-1;\ + } while (0) \ + +#define w_128_copy(x, y) ((x).a[0]=(y).a[0], (x).a[1]=(y).a[1]) + +/***********************3 words***********************/ +#define w_192_clear(x) ((x).a[0]=(x).a[1]=(x).a[2]=0) + +#define w_192_word (3) + +#define w_192_self_not(x) ((x).a[0]=~(x).a[0],\ + (x).a[1]=~(x).a[1],\ + (x).a[2]=~(x).a[2]) + +#define w_192_self_or(x, y) ((x).a[0]|=(y).a[0],\ + (x).a[1]|=(y).a[1],\ + (x).a[2]|=(y).a[2]) + +#define w_192_or(r, x, y) ((r).a[0]=(x).a[0]|(y).a[0],\ + (r).a[1] = (x).a[1]|(y).a[1],\ + (r).a[2] = (x).a[2]|(y).a[2]) + +#define w_192_and(r, x, y) ((r).a[0] = (x).a[0]&(y).a[0], \ + (r).a[1] = (x).a[1]&(y).a[1], \ + (r).a[2] = (x).a[2]&(y).a[2]) + +#define w_192_self_xor(x, y) ((x).a[0]^=(y).a[0], \ + (x).a[1]^=(y).a[1], \ + (x).a[2]^=(y).a[2]) + +#define w_192_self_lsft_1(x) ((x).a[2] = ((x).a[2]<<1)|((x).a[1]>>bitz), \ + (x).a[1] = ((x).a[1]<<1)|((x).a[0]>>bitz), \ + (x).a[0] <<= 1) + +#define w_192_self_rsft_1(x) ((x).a[0] = ((x).a[0]>>1)|((x).a[1]<>1)|((x).a[2]<>= 1) + +#define w_192_rsft_1(x, y) ((x).a[0] = ((y).a[0]>>1)|((y).a[1]<>1)|((y).a[2]<>1) + +#define w_192_self_add(x, y, c) ((x).a[0]+=(y).a[0], c=((x).a[0]<(y).a[0]),\ + (x).a[1]+=c, c=((x).a[1]>bitw) memset((x).a, -1, sizeof(*((x).a))*((l)>>bitw));\ + if((l)&bitz) (x).a[(l)>>bitw] = (((w_sig)1)<<((l)&bitz))-1; \ + } while (0) \ + +#define w_192_copy(x, y) ((x).a[0]=(y).a[0], (x).a[1]=(y).a[1], (x).a[2]=(y).a[2]) + +/***********************4 words***********************/ +#define w_256_clear(x) ((x).a[0]=(x).a[1]=(x).a[2]=(x).a[3]=0) + +#define w_256_word (4) + +#define w_256_self_not(x) ((x).a[0]=~(x).a[0],\ + (x).a[1]=~(x).a[1],\ + (x).a[2]=~(x).a[2],\ + (x).a[3]=~(x).a[3]) + +#define w_256_self_or(x, y) ((x).a[0]|=(y).a[0],\ + (x).a[1]|=(y).a[1],\ + (x).a[2]|=(y).a[2],\ + (x).a[3]|=(y).a[3]) + +#define w_256_or(r, x, y) ((r).a[0]=(x).a[0]|(y).a[0],\ + (r).a[1] = (x).a[1]|(y).a[1],\ + (r).a[2] = (x).a[2]|(y).a[2],\ + (r).a[3] = (x).a[3]|(y).a[3]) + +#define w_256_and(r, x, y) ((r).a[0] = (x).a[0]&(y).a[0], \ + (r).a[1] = (x).a[1]&(y).a[1], \ + (r).a[2] = (x).a[2]&(y).a[2], \ + (r).a[3] = (x).a[3]&(y).a[3]) + +#define w_256_self_xor(x, y) ((x).a[0]^=(y).a[0], \ + (x).a[1]^=(y).a[1], \ + (x).a[2]^=(y).a[2],\ + (x).a[3]^=(y).a[3]) + +#define w_256_self_lsft_1(x) ((x).a[3] = ((x).a[3]<<1)|((x).a[2]>>bitz), \ + (x).a[2] = ((x).a[2]<<1)|((x).a[1]>>bitz), \ + (x).a[1] = ((x).a[1]<<1)|((x).a[0]>>bitz), \ + (x).a[0] <<= 1) + +#define w_256_self_rsft_1(x) ((x).a[0] = ((x).a[0]>>1)|((x).a[1]<>1)|((x).a[2]<>1)|((x).a[3]<>= 1) + +#define w_256_rsft_1(x, y) ((x).a[0] = ((y).a[0]>>1)|((y).a[1]<>1)|((y).a[2]<>1)|((y).a[3]<>1) + +#define w_256_self_add(x, y, c) ((x).a[0]+=(y).a[0], c=((x).a[0]<(y).a[0]),\ + (x).a[1]+=c, c=((x).a[1]>bitw) memset((x).a, -1, sizeof(*((x).a))*((l)>>bitw));\ + if((l)&bitz) (x).a[(l)>>bitw] = (((w_sig)1)<<((l)&bitz))-1; \ + } while (0) + +#define w_256_copy(x, y) ((x).a[0]=(y).a[0], (x).a[1]=(y).a[1], (x).a[2]=(y).a[2], (x).a[3]=(y).a[3]) + +#define cmp_Word(des, src, dd, ws) {\ + for ((dd)=0;(dd)<64;dd+=bitwbit){\ + if((((des)>>dd)&((w_sig)-1))!=(src).a[dd>>bitw]) break;\ + }\ + if((dd)<64) {\ + print_bit((des), (ws), "des");\ + print_bits((src).a, (ws), "src");\ + exit(0);\ + }\ +} + +#define dump_Word(des, src, dd, ws) {\ + for ((dd)=bitwbit,(des)=((Word)(src).a[0]);(dd)<64;dd+=bitwbit) {\ + (des) |= ((Word)(src).a[dd>>bitw])<> 1;**/\ + w##sf##copy((X), (D0));\ + prt_address(Peq, VP, VN, X, D0, HN, HP);\ + X_d = D0_d; fprintf(stderr, "X=D0\n"); cmp_Word(X_d, (X), dd, ws);\ + w##sf##self_rsft_1((X)); \ + prt_address(Peq, VP, VN, X, D0, HN, HP);\ + X_d >>= 1; fprintf(stderr, "X>>=1\n"); cmp_Word(X_d, (X), dd, ws);\ + /**VN = X&HP;**/\ + w##sf##and((VN), (X), (HP));\ + prt_address(Peq, VP, VN, X, D0, HN, HP);\ + VN_d = X_d&HP_d; fprintf(stderr, "VN=X&HP\n"); cmp_Word(VN_d, (VN), dd, ws);\ + /**VP = HN | ~(X | HP);**/\ + w##sf##or((VP), (X), (HP));\ + prt_address(Peq, VP, VN, X, D0, HN, HP);\ + VP_d = X_d|HP_d; fprintf(stderr, "VP=X|HP\n"); cmp_Word(VP_d, (VP), dd, ws);\ + w##sf##self_not((VP));\ + prt_address(Peq, VP, VN, X, D0, HN, HP);\ + VP_d = ~VP_d; fprintf(stderr, "VP=~VP\n"); cmp_Word(VP_d, (VP), dd, ws);\ + w##sf##self_or((VP), (HN));\ + prt_address(Peq, VP, VN, X, D0, HN, HP);\ + VP_d |= HN_d; fprintf(stderr, "VP|=HN\n"); cmp_Word(VP_d, (VP), dd, ws);\ +} + +#define ed_core(sf, Peq, VP, VN, X, D0, HN, HP, z, c) { \ + /**X = Peq[seq_nt4_table[(uint8_t)tstr[i]]] | VN;**/\ + (c) = seq_nt4_table[(z)];\ + w##sf##or((X), (Peq)[(c)], (VN));\ + /**D0 = ((VP + (X&VP)) ^ VP) | X;**/\ + w##sf##and((D0), (X), (VP));\ + w##sf##self_add((D0), (VP), (c));\ + w##sf##self_xor((D0), (VP));\ + w##sf##self_or((D0), (X));\ + /**HN = VP&D0;**/\ + w##sf##and((HN), (VP), (D0));\ + /**HP = VN | ~(VP | D0);**/\ + w##sf##or((HP), (VP), (D0));\ + w##sf##self_not((HP));\ + w##sf##self_or((HP), (VN));\ + /**X = D0 >> 1;**/\ + /**w##sf##copy((X), (D0));w##sf##self_rsft_1((X));**/\ + w##sf##rsft_1((X), (D0));\ + /**VN = X&HP;**/\ + w##sf##and((VN), (X), (HP));\ + /**VP = HN | ~(X | HP);**/\ + w##sf##or((VP), (X), (HP));\ + w##sf##self_not((VP));\ + w##sf##self_or((VP), (HN));\ +} + +#define ed_init_core(i, bd, i_bd, S, Peq) { \ + for ((i) = 0; (i) < (bd); (i)++) {\ + w_bit((Peq)[seq_nt4_table[(uint8_t)(S)[(i)]]], (i_bd));i_bd++;\ + }\ +} + +#define HA_ED_INIT(sf)\ +inline void ed_band_cal_global_##sf##_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ +{\ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0;\ + if((pn > tn + thre) || (tn > pn + thre)) return;\ + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, Peq_i; w_sig c, Peq_m;\ + w_##sf##_clear(ez->Peq[0]); w_##sf##_clear(ez->Peq[1]); w_##sf##_clear(ez->Peq[2]); w_##sf##_clear(ez->Peq[3]); w_##sf##_clear(ez->Peq[4]);\ + \ + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre;\ + ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ + bd = thre+1, i_bd = thre;\ + \ + w_##sf##_clear(ez->Peq[4]);\ + err = thre;\ + w_##sf##_set_bit_lsub(ez->VN, thre); /**VN = (((Word)1)<<(thre))-1;**/\ + w_##sf##_set_bit_lsub(ez->VP, (thre<<1)+1); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/\ + w_##sf##_self_xor(ez->VP, ez->VN); /**VP ^= VN;**/\ + \ + /** print_bits(VP.a, (thre<<1)+1, "-VP");**/\ + /**should make Peq[4] = 0 if N is always an error**/\ + i = 0; \ + /**for the incoming char/last char**/\ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ + while (i < tn0) {\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ + w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ + w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ + \ + ++i; ++i_bd; c = 4;\ + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ + }\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + \ + int32_t site = tn - 1 - thre;/**up bound**/\ + for (cut = pn - 1, i = 0; site < cut; site++, i++) {\ + bd = (i>>bitw); i_bd = (i&bitz);\ + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ + }\ + \ + if (site == cut && err <= thre) {\ + ez->err = err; \ + ez->pe = pn-1; ez->te = tn-1;\ + }\ + return;\ +}\ +inline void ed_band_cal_semi_##sf##_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ +{\ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1;\ + int32_t bd, i, err = 0, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, Peq_i; w_sig c, Peq_m;\ + if((pn > tn + cut) || (tn > pn + cut)) return;\ + \ + w_##sf##_clear(ez->Peq[0]);\ + w_##sf##_clear(ez->Peq[1]);\ + w_##sf##_clear(ez->Peq[2]);\ + w_##sf##_clear(ez->Peq[3]);\ + w_##sf##_clear(ez->Peq[4]);\ + w_##sf##_clear(ez->VP);\ + w_##sf##_clear(ez->VN);\ + \ + bd = (thre<<1)+1; bd = ((bd<=pn)?bd:pn); i_bd = 0;\ + ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ + bd = (thre<<1)+1, i_bd = (thre<<1);\ + \ + w_##sf##_clear(ez->Peq[4]);\ + i = 0;\ + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ + while (i < tn0) {\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ + w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ + w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ + ++i; ++i_bd; c = 4;\ + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ + }\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + \ + int32_t site = tn - 1;/**up bound**/\ + /**in most cases, ai = (thre<<1)**/\ + int32_t ai = pn - tn, uge = INT32_MAX;\ + if ((err <= thre) && (err <= ez->err)) {\ + ez->err = err; ez->pe = site;\ + }\ + \ + i = 0;\ + while (i < ai) {\ + bd = (i>>bitw); i_bd = (i&bitz);\ + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ + ++i;\ + if ((err <= thre) && (err <= ez->err)) {\ + ez->err = err; ez->pe = site + i;\ + }\ + if(i == thre) uge = err;\ + }\ + \ + if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre;\ +}\ +/**require:: (pn >= tn - thre && pn <= tn + thre)**/\ +inline void ed_band_cal_extension_##sf##_0_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ +{\ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; ez->pe = ez->te = -1;\ + if(pn > tn + thre) pn = tn + thre;\ + else if(tn > pn + thre) tn = pn + thre;\ + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, Peq_i; w_sig c, Peq_m;\ + int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k;\ + \ + w_##sf##_clear(ez->Peq[0]);\ + w_##sf##_clear(ez->Peq[1]);\ + w_##sf##_clear(ez->Peq[2]);\ + w_##sf##_clear(ez->Peq[3]);\ + w_##sf##_clear(ez->Peq[4]);\ + \ + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre;\ + ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ + bd = thre+1, i_bd = thre;\ + \ + w_##sf##_clear(ez->Peq[4]);\ + err = thre;\ + w_##sf##_set_bit_lsub(ez->VN, thre); /**VN = (((Word)1)<<(thre))-1; **/\ + w_##sf##_set_bit_lsub(ez->VP, (thre<<1)+1); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/\ + w_##sf##_self_xor(ez->VP, ez->VN); /**VP ^= VN;**/\ + \ + /** print_bits(ez->VP.a, (thre<<1)+1, "-VP");**/\ + /**should make Peq[4] = 0 if N is always an error**/\ + i = 0; \ + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ + while (i < tn0) {\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + \ + {\ + poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/\ + if(k >= 0) {\ + if(tmp_e == INT32_MAX) {\ + tmp_e = err;\ + for ((k) = 0; (poff) < (pe); (poff)++, (k)++) {\ + bd = (k>>bitw); k_bd = (k&bitz);\ + (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1));\ + (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1));\ + }\ + } else {\ + k = (thre<<1) - k;\ + if(k >= 0) {\ + bd = (k>>bitw); k_bd = (k&bitz);\ + (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1));\ + (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1));\ + }\ + }\ + if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) {\ + (*ez).err = tmp_e; (*ez).pe = pe; (*ez).te = i;\ + }\ + }\ + /**if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e)**/\ + }\ + \ + /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ + w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ + w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ + ++i; ++i_bd; c = 4;\ + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ + }\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + \ + int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/\ + for (cut = pn - 1, i = 0; site < cut; i++) {\ + bd = (i>>bitw); i_bd = (i&bitz);\ + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ + site++;\ + if(err <= thre && err < ez->err) {\ + ez->err = err; ez->pe = site; ez->te = tn-1;\ + }\ + }\ + if(err <= thre && err < ez->err) {\ + ez->err = err; ez->pe = site; ez->te = tn-1;\ + }\ + return;\ +}\ +/**require:: (pn >= tn - thre && pn <= tn + thre)**/\ +inline void ed_band_cal_extension_##sf##_1_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ +{\ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = INT32_MAX; ez->pe = pn-1; ez->te = tn-1;\ + if(pn > tn + thre) pn = tn + thre;\ + else if(tn > pn + thre) tn = pn + thre;\ + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, Peq_i; w_sig c, Peq_m;\ + int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k, pidx = ez->pe, tidx = ez->te;\ + \ + w_##sf##_clear(ez->Peq[0]);\ + w_##sf##_clear(ez->Peq[1]);\ + w_##sf##_clear(ez->Peq[2]);\ + w_##sf##_clear(ez->Peq[3]);\ + w_##sf##_clear(ez->Peq[4]);\ + \ + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre;\ + for (i = 0; i < bd; i++, i_bd++) {\ + w_bit((ez->Peq)[seq_nt4_table[(uint8_t)(pstr)[pidx-i]]], (i_bd));\ + }\ + bd = thre+1, i_bd = thre;\ + \ + w_##sf##_clear(ez->Peq[4]);\ + err = thre;\ + w_##sf##_set_bit_lsub(ez->VN, thre); /**VN = (((Word)1)<<(thre))-1; **/\ + w_##sf##_set_bit_lsub(ez->VP, (thre<<1)+1); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/\ + w_##sf##_self_xor(ez->VP, ez->VN); /**VP ^= VN;**/\ + \ + /** print_bits(ez->VP.a, (thre<<1)+1, "-VP");**/\ + /**should make Peq[4] = 0 if N is always an error**/\ + i = 0; \ + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ + while (i < tn0) {\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + \ + {\ + poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/\ + if(k >= 0) {\ + if(tmp_e == INT32_MAX) {\ + tmp_e = err;\ + for ((k) = 0; (poff) < (pe); (poff)++, (k)++) {\ + bd = (k>>bitw); k_bd = (k&bitz);\ + (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1));\ + (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1));\ + }\ + } else {\ + k = (thre<<1) - k;\ + if(k >= 0) {\ + bd = (k>>bitw); k_bd = (k&bitz);\ + (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1));\ + (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1));\ + }\ + }\ + if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) {\ + (*ez).err = tmp_e; (*ez).ps = pidx - pe; (*ez).ts = tidx-i;\ + }\ + }\ + /**if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e)**/\ + }\ + \ + /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ + w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ + w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ + ++i; ++i_bd; c = 4;\ + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[pidx-i_bd]];\ + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ + }\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + \ + int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/\ + for (cut = pn - 1, i = 0; site < cut; i++) {\ + bd = (i>>bitw); i_bd = (i&bitz);\ + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ + site++;\ + if(err <= thre && err < ez->err) {\ + ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn;\ + }\ + }\ + if(err <= thre && err < ez->err) {\ + ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn;\ + }\ + return;\ +}\ +inline void ed_band_cal_global_##sf##_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ +{\ + ez->cigar.n = 0; ez->nword = w_##sf##_word;\ + if(ez->err > thre) {\ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0;\ + } else if(ez->err == 0) {\ + push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;\ + }\ + if((pn > tn + thre) || (tn > pn + thre)) return;\ + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, ws, Peq_i; w_sig c, Peq_m;\ + w_##sf##_clear(ez->Peq[0]); w_##sf##_clear(ez->Peq[1]); w_##sf##_clear(ez->Peq[2]); w_##sf##_clear(ez->Peq[3]); w_##sf##_clear(ez->Peq[4]);\ + \ + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre;\ + ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ + bd = thre+1, i_bd = thre;\ + \ + w_##sf##_clear(ez->Peq[4]);\ + err = thre;\ + w_##sf##_set_bit_lsub(ez->VN, thre); /**VN = (((Word)1)<<(thre))-1;**/\ + w_##sf##_set_bit_lsub(ez->VP, (thre<<1)+1); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/\ + w_##sf##_self_xor(ez->VP, ez->VN); /**VP ^= VN;**/\ + \ + /** print_bits(VP.a, (thre<<1)+1, "-VP");**/\ + /**should make Peq[4] = 0 if N is always an error**/\ + i = 0; ws = sizeof(*(ez->a))*(ez->nword);\ + ez->path.n=(ez->nword*tn*5);\ + kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;\ + \ + /**for the incoming char/last char**/\ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ + while (i < tn0) {\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ + w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ + w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ + \ + ++i; ++i_bd; c = 4;\ + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ + \ + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ + }\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ + \ + int32_t site = tn - 1 - thre;/**up bound**/\ + if(ez->err > thre) {\ + for (cut = pn - 1, i = 0; site < cut; site++, i++) {\ + bd = (i>>bitw); i_bd = (i&bitz);\ + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ + }\ + \ + if (site == cut && err <= thre) {\ + ez->err = err; \ + ez->pe = pn-1; ez->te = tn-1;\ + }\ + }\ + gen_trace(ez, thre, 1);\ + return;\ +}\ +inline void ed_band_cal_semi_##sf##_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ +{\ + ez->cigar.n = 0; ez->nword = w_##sf##_word;\ + if(ez->err > thre) {\ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1;\ + } else if(ez->err == 0) {\ + push_trace(&(ez->cigar), 0, ez->te+1-ez->ts);\ + ez->ps = ez->pe - (ez->te-ez->ts);\ + return;\ + }\ + int32_t bd, i, err = 0, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, Peq_i, ws; w_sig c, Peq_m;\ + if((pn > tn + cut) || (tn > pn + cut)) return;\ + \ + w_##sf##_clear(ez->Peq[0]);\ + w_##sf##_clear(ez->Peq[1]);\ + w_##sf##_clear(ez->Peq[2]);\ + w_##sf##_clear(ez->Peq[3]);\ + w_##sf##_clear(ez->Peq[4]);\ + w_##sf##_clear(ez->VP);\ + w_##sf##_clear(ez->VN);\ + \ + bd = (thre<<1)+1; bd = ((bd<=pn)?bd:pn); i_bd = 0;\ + ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ + bd = (thre<<1)+1, i_bd = (thre<<1);\ + \ + w_##sf##_clear(ez->Peq[4]);\ + i = 0; ws = sizeof(*(ez->a))*(ez->nword);\ + ez->path.n=(ez->nword*tn*5);\ + kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;\ + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ + while (i < tn0) {\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ + w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ + w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ + ++i; ++i_bd; c = 4;\ + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ + \ + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ + }\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ + \ + int32_t site = tn - 1;/**up bound**/\ + /**in most cases, ai = (thre<<1)**/\ + int32_t ai = pn - tn, uge = INT32_MAX;\ + if(ez->err > thre) {\ + if ((err <= thre) && (err <= ez->err)) {\ + ez->err = err; ez->pe = site;\ + }\ + \ + i = 0;\ + while (i < ai) {\ + bd = (i>>bitw); i_bd = (i&bitz);\ + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ + ++i;\ + if ((err <= thre) && (err <= ez->err)) {\ + ez->err = err; ez->pe = site + i;\ + }\ + if(i == thre) uge = err;\ + }\ + \ + if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre;\ + }\ + gen_trace(ez, 0, 1);\ +}\ +inline void ed_band_cal_extension_##sf##_0_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ +{\ + int32_t done = 1;\ + ez->cigar.n = 0; ez->nword = w_##sf##_word;\ + if(ez->err > thre) {\ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; ez->pe = ez->te = -1;\ + if(pn > tn + thre) pn = tn + thre;\ + else if(tn > pn + thre) tn = pn + thre;\ + done = 0;\ + } else if(ez->err == 0) {\ + push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;\ + } else {\ + pn = ez->pe + 1 - ez->ps; tn = ez->te + 1 - ez->ts;\ + }\ + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, Peq_i, ws; w_sig c, Peq_m;\ + int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k;\ + \ + w_##sf##_clear(ez->Peq[0]);\ + w_##sf##_clear(ez->Peq[1]);\ + w_##sf##_clear(ez->Peq[2]);\ + w_##sf##_clear(ez->Peq[3]);\ + w_##sf##_clear(ez->Peq[4]);\ + \ + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre;\ + ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ + bd = thre+1, i_bd = thre;\ + \ + w_##sf##_clear(ez->Peq[4]);\ + err = thre;\ + w_##sf##_set_bit_lsub(ez->VN, thre); /**VN = (((Word)1)<<(thre))-1; **/\ + w_##sf##_set_bit_lsub(ez->VP, (thre<<1)+1); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/\ + w_##sf##_self_xor(ez->VP, ez->VN); /**VP ^= VN;**/\ + \ + /** print_bits(ez->VP.a, (thre<<1)+1, "-VP");**/\ + /**should make Peq[4] = 0 if N is always an error**/\ + i = 0; ws = sizeof(*(ez->a))*(ez->nword);\ + ez->path.n=(ez->nword*tn*5);\ + kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;\ + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ + while (i < tn0) {\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + \ + if(!done) {\ + poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/\ + if(k >= 0) {\ + if(tmp_e == INT32_MAX) {\ + tmp_e = err;\ + for ((k) = 0; (poff) < (pe); (poff)++, (k)++) {\ + bd = (k>>bitw); k_bd = (k&bitz);\ + (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1));\ + (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1));\ + }\ + } else {\ + k = (thre<<1) - k;\ + if(k >= 0) {\ + bd = (k>>bitw); k_bd = (k&bitz);\ + (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1));\ + (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1));\ + }\ + }\ + if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) {\ + (*ez).err = tmp_e; (*ez).pe = pe; (*ez).te = i;\ + }\ + }\ + /**if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e)**/\ + }\ + \ + /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ + w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ + w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ + ++i; ++i_bd; c = 4;\ + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ + \ + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ + }\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ + \ + int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/\ + if(!done) {\ + for (cut = pn - 1, i = 0; site < cut; i++) {\ + bd = (i>>bitw); i_bd = (i&bitz);\ + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ + site++;\ + if(err <= thre && err < ez->err) {\ + ez->err = err; ez->pe = site; ez->te = tn-1;\ + }\ + }\ + if(err <= thre && err < ez->err) {\ + ez->err = err; ez->pe = site; ez->te = tn-1;\ + }\ + }\ + \ + if((ez->te-ez->ts+1) != tn) {\ + ez->path.n /= tn; ez->path.n *= (ez->te+1-ez->ts);\ + }\ + gen_trace(ez, thre, 1);\ + return;\ +}\ +inline void ed_band_cal_extension_##sf##_1_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez)\ +{\ + int32_t done = 1;\ + ez->cigar.n = 0; ez->nword = w_##sf##_word;\ + if(ez->err > thre) {\ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = INT32_MAX; ez->pe = pn-1; ez->te = tn-1;\ + if(pn > tn + thre) pn = tn + thre;\ + else if(tn > pn + thre) tn = pn + thre;\ + done = 0;\ + } else if(ez->err == 0) {\ + push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;\ + } else {\ + pn = ez->pe + 1 - ez->ps; tn = ez->te + 1 - ez->ts;\ + }\ + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, Peq_i, ws; w_sig c, Peq_m;\ + int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k, pidx = ez->pe, tidx = ez->te;\ + \ + w_##sf##_clear(ez->Peq[0]);\ + w_##sf##_clear(ez->Peq[1]);\ + w_##sf##_clear(ez->Peq[2]);\ + w_##sf##_clear(ez->Peq[3]);\ + w_##sf##_clear(ez->Peq[4]);\ + \ + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre;\ + for (i = 0; i < bd; i++, i_bd++) {\ + w_bit((ez->Peq)[seq_nt4_table[(uint8_t)(pstr)[pidx-i]]], (i_bd));\ + }\ + bd = thre+1, i_bd = thre;\ + \ + w_##sf##_clear(ez->Peq[4]);\ + err = thre;\ + w_##sf##_set_bit_lsub(ez->VN, thre); /**VN = (((Word)1)<<(thre))-1; **/\ + w_##sf##_set_bit_lsub(ez->VP, (thre<<1)+1); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/\ + w_##sf##_self_xor(ez->VP, ez->VN); /**VP ^= VN;**/\ + \ + /** print_bits(ez->VP.a, (thre<<1)+1, "-VP");**/\ + /**should make Peq[4] = 0 if N is always an error**/\ + i = 0; ws = sizeof(*(ez->a))*(ez->nword);\ + ez->path.n=(ez->nword*tn*5);\ + kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;\ + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ + while (i < tn0) {\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + \ + if(!done) {\ + poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/\ + if(k >= 0) {\ + if(tmp_e == INT32_MAX) {\ + tmp_e = err;\ + for ((k) = 0; (poff) < (pe); (poff)++, (k)++) {\ + bd = (k>>bitw); k_bd = (k&bitz);\ + (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1));\ + (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1));\ + }\ + } else {\ + k = (thre<<1) - k;\ + if(k >= 0) {\ + bd = (k>>bitw); k_bd = (k&bitz);\ + (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1));\ + (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1));\ + }\ + }\ + if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) {\ + (*ez).err = tmp_e; (*ez).ps = pidx - pe; (*ez).ts = tidx-i;\ + }\ + }\ + /**if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e)**/\ + }\ + \ + /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ + w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ + w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ + ++i; ++i_bd; c = 4;\ + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[pidx-i_bd]];\ + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ + \ + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ + }\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ + \ + int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/\ + if(!done) {\ + for (cut = pn - 1, i = 0; site < cut; i++) {\ + bd = (i>>bitw); i_bd = (i&bitz);\ + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ + site++;\ + if(err <= thre && err < ez->err) {\ + ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn;\ + }\ + }\ + if(err <= thre && err < ez->err) {\ + ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn;\ + }\ + }\ + \ + if((ez->te-ez->ts+1) != tn) {\ + ez->path.n /= tn; ez->path.n *= (ez->te+1-ez->ts);\ + }\ + \ + poff = ez->ps; ez->ps = pidx - ez->pe; ez->pe = pidx - poff;\ + gen_trace(ez, thre, 0);\ + poff = ez->ps; ez->ps = pidx - ez->pe; ez->pe = pidx - poff;\ + return;\ +}\ +inline void ed_band_cal_semi_##sf##_w_absent_diag(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t abs_diag, bit_extz_t *ez)\ +{\ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1;\ + int32_t bd, i, err = abs_diag, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, Peq_i; w_sig c, Peq_m;\ + if((pn > tn + cut) || (tn > pn + cut)) return;\ + \ + w_##sf##_clear(ez->Peq[0]);\ + w_##sf##_clear(ez->Peq[1]);\ + w_##sf##_clear(ez->Peq[2]);\ + w_##sf##_clear(ez->Peq[3]);\ + w_##sf##_clear(ez->Peq[4]);\ + w_##sf##_clear(ez->VP);\ + w_##sf##_set_bit_lsub(ez->VN, abs_diag);\ + \ + bd = ((thre<<1)+1)-abs_diag; bd = ((bd<=pn)?bd:pn); i_bd = abs_diag; \ + ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ + i_bd = (thre<<1)-abs_diag;\ + \ + w_##sf##_clear(ez->Peq[4]);\ + i = 0;\ + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ + while (i < tn0) {\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ + w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ + w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ + ++i; ++i_bd; c = 4;\ + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ + }\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + \ + int32_t site = tn - 1 - abs_diag;/**up bound**/\ + /**in most cases, ai = (thre<<1)**/\ + int32_t ai = pn - tn + abs_diag, uge = INT32_MAX; i = 0;\ + for (i = 0; site < 0 && i < ai; i++, site++) {\ + bd = (i>>bitw); i_bd = (i&bitz);\ + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ + }\ + if ((err <= thre) && (err <= ez->err)) {\ + ez->err = err; ez->pe = site;\ + }\ + \ + site -= i;\ + while (i < ai) {\ + bd = (i>>bitw); i_bd = (i&bitz);\ + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ + ++i;\ + if ((err <= thre) && (err <= ez->err)) {\ + ez->err = err; ez->pe = site + i;\ + }\ + if(i == thre) uge = err;\ + }\ + \ + if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre;\ +}\ +inline void ed_band_cal_semi_##sf##_w_absent_diag_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t abs_diag, bit_extz_t *ez)\ +{\ + ez->cigar.n = 0; ez->nword = w_##sf##_word;\ + if(ez->err > thre) {\ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1;\ + } else if(ez->err == 0) {\ + push_trace(&(ez->cigar), 0, ez->te+1-ez->ts);\ + ez->ps = ez->pe - (ez->te-ez->ts);\ + return;\ + }\ + int32_t bd, i, err = abs_diag, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, Peq_i, ws; w_sig c, Peq_m;\ + if((pn > tn + cut) || (tn > pn + cut)) return;\ + \ + w_##sf##_clear(ez->Peq[0]);\ + w_##sf##_clear(ez->Peq[1]);\ + w_##sf##_clear(ez->Peq[2]);\ + w_##sf##_clear(ez->Peq[3]);\ + w_##sf##_clear(ez->Peq[4]);\ + w_##sf##_clear(ez->VP);\ + w_##sf##_set_bit_lsub(ez->VN, abs_diag);\ + \ + bd = ((thre<<1)+1)-abs_diag; bd = ((bd<=pn)?bd:pn); i_bd = abs_diag;\ + ed_init_core(i, bd, i_bd, pstr, ez->Peq);\ + i_bd = (thre<<1)-abs_diag;\ + \ + w_##sf##_clear(ez->Peq[4]);\ + i = 0; ws = sizeof(*(ez->a))*(ez->nword);\ + ez->path.n=(ez->nword*tn*5);\ + kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;\ + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/\ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz));\ + while (i < tn0) {\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + /** Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ + w_##sf##_self_rsft_1(ez->Peq[0]); w_##sf##_self_rsft_1(ez->Peq[1]);\ + w_##sf##_self_rsft_1(ez->Peq[2]); w_##sf##_self_rsft_1(ez->Peq[3]);\ + ++i; ++i_bd; c = 4;\ + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]];\ + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m;\ + \ + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ + }\ + ed_core(_##sf##_, ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c);\ + if (!(ez->D0.a[0]&(1ULL))) {\ + ++err; if (err>cut) return;\ + }\ + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;\ + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;\ + \ + int32_t site = tn - 1 - abs_diag;/**up bound**/\ + /**in most cases, ai = (thre<<1)**/\ + int32_t ai = pn - tn + abs_diag, uge = INT32_MAX; i = 0;\ + if(ez->err > thre) {\ + for (i = 0; site < 0 && i < ai; i++, site++) {\ + bd = (i>>bitw); i_bd = (i&bitz);\ + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ + }\ + if ((err <= thre) && (err <= ez->err)) {\ + ez->err = err; ez->pe = site;\ + }\ + \ + site -= i;\ + while (i < ai) {\ + bd = (i>>bitw); i_bd = (i&bitz);\ + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1));\ + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1));\ + ++i;\ + if ((err <= thre) && (err <= ez->err)) {\ + ez->err = err; ez->pe = site + i;\ + }\ + if(i == thre) uge = err;\ + }\ + \ + if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre;\ + }\ + gen_trace(ez, abs_diag, 1);\ +}\ + +HA_ED_INIT(128) +HA_ED_INIT(192) +HA_ED_INIT(256) + + +#define w_infi_clear(x, nw) (memset((x).a, 0, sizeof(*((x).a))*(nw))) + +#define w_infi_set_bit_lsub(x, l, nw) do { \ + w_infi_clear(x, nw);\ + if((l)>>bitw) memset((x).a, -1, sizeof(*((x).a))*((l)>>bitw));\ + if((l)&bitz) (x).a[(l)>>bitw] = (((w_sig)1)<<((l)&bitz))-1; \ + } while (0) + +#define w_infi_self_xor(x, y, nw, w_z) {\ + for((w_z)=0; (w_z)<(nw); (w_z)++) (x).a[w_z]^=(y).a[w_z];} + +#define w_self_add_sin(x, y, w_z, ad) {\ + (x).a[(w_z)]+=(ad), (ad)=((x).a[(w_z)]<(ad)), (x).a[(w_z)]+=(y).a[(w_z)], (ad)|=((x).a[(w_z)]<(y).a[(w_z)]);} + +#define ed_infi_core(Peq, VP, VN, X, D0, HN, HP, z, c, ad, w_z, nw) {\ + (c) = seq_nt4_table[(z)];\ + for((w_z)=(ad)=0; (w_z)<(nw); (w_z)++){\ + /**X = Peq[seq_nt4_table[(uint8_t)tstr[i]]] | VN;**/\ + (X).a[(w_z)]=(Peq)[(c)].a[(w_z)]|(VN).a[(w_z)];\ + /**D0 = ((VP + (X&VP)) ^ VP) | X;**/\ + (D0).a[(w_z)]=(X).a[(w_z)]&(VP).a[(w_z)];\ + w_self_add_sin((D0), (VP), (w_z), (ad));\ + (D0).a[(w_z)]^=(VP).a[(w_z)];\ + (D0).a[(w_z)]|=(X).a[(w_z)];\ + /**HN = VP&D0;**/\ + (HN).a[(w_z)]=(VP).a[(w_z)]&(D0).a[(w_z)];\ + /**HP = VN | ~(VP | D0);**/\ + (HP).a[(w_z)]=~((VP).a[(w_z)]|(D0).a[(w_z)]);\ + (HP).a[(w_z)]|=(VN).a[(w_z)];\ + }\ + for((w_z)=(nw)-1,(ad)=0; (w_z)>=0; (w_z)--){\ + /**X = D0 >> 1;**/\ + (X).a[(w_z)]=((D0).a[(w_z)]>>1)|(ad),(ad)=(D0).a[(w_z)]<>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1;**/\ + for((w_z)=0, (w_z1)=1; (w_z1)<(nw); (w_z)++,(w_z1)++){\ + Peq[0].a[(w_z)]=(Peq[0].a[(w_z)]>>1)|(Peq[0].a[(w_z1)]<>1)|(Peq[1].a[(w_z1)]<>1)|(Peq[2].a[(w_z1)]<>1)|(Peq[3].a[(w_z1)]<>=1;\ + Peq[1].a[(w_z)]>>=1;\ + Peq[2].a[(w_z)]>>=1;\ + Peq[3].a[(w_z)]>>=1;\ +} + +inline void ed_band_cal_global_infi_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) +{ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; + if((pn > tn + thre) || (tn > pn + thre)) return; + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, wz, wz1, Peq_i; w_sig c, ad, Peq_m; + if(nword) { + ez->nword = (*nword); + } else { + bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); + } + resize_bit_extz_t((*ez), (thre)); + wz = sizeof(*(ez->a))*(ez->nword); + memset((ez->Peq[0]).a, 0, wz); + memset((ez->Peq[1]).a, 0, wz); + memset((ez->Peq[2]).a, 0, wz); + memset((ez->Peq[3]).a, 0, wz); + memset((ez->Peq[4]).a, 0, wz); + + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; + ed_init_core(i, bd, i_bd, pstr, ez->Peq); + bd = thre+1, i_bd = thre; + + memset((ez->Peq[4]).a, 0, wz); + err = thre; + w_infi_set_bit_lsub(ez->VN, thre, ez->nword); /**VN = (((Word)1)<<(thre))-1;**/ + w_infi_set_bit_lsub(ez->VP, (thre<<1)+1, ez->nword); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/ + w_infi_self_xor(ez->VP, ez->VN, ez->nword, wz) /**VP ^= VN;**/ + + i = 0; + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); + while (i < tn0) { + // fprintf(stderr, "\ni::%d\n", i); + // prt_bit_extz_t((*ez), (((thre<<1))+1)); + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + + ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); + ++i; ++i_bd; c = 4; + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; + // fprintf(stderr, "c::%u\n", c); + // print_bits(ez->Peq[c].a, (((thre<<1))+1), "Peq[c]"); + } + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + + int32_t site = tn - 1 - thre;/**up bound**/ + for (cut = pn - 1, i = 0; site < cut; site++, i++) { + bd = (i>>bitw); i_bd = (i&bitz); + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); + } + + if (site == cut && err <= thre) { + ez->err = err; + ez->pe = pn-1; ez->te = tn-1; + } + return; +} + +inline void ed_band_cal_semi_infi_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) +{ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1; + int32_t bd, i, err = 0, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, wz, wz1, Peq_i; w_sig c, ad, Peq_m; + if((pn > tn + cut) || (tn > pn + cut)) return; + + if(nword) { + ez->nword = (*nword); + } else { + bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); + } + resize_bit_extz_t((*ez), (thre)); + wz = sizeof(*(ez->a))*(ez->nword); + memset((ez->Peq[0]).a, 0, wz); + memset((ez->Peq[1]).a, 0, wz); + memset((ez->Peq[2]).a, 0, wz); + memset((ez->Peq[3]).a, 0, wz); + memset((ez->Peq[4]).a, 0, wz); + memset((ez->VP).a, 0, wz); + memset((ez->VN).a, 0, wz); + + bd = (thre<<1)+1; bd = ((bd<=pn)?bd:pn); i_bd = 0; + ed_init_core(i, bd, i_bd, pstr, ez->Peq); + bd = (thre<<1)+1, i_bd = (thre<<1); + + memset((ez->Peq[4]).a, 0, wz); + i = 0; + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); + while (i < tn0) { + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + + ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); + ++i; ++i_bd; c = 4; + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; + } + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + + int32_t site = tn - 1;/**up bound**/ + /**in most cases, ai = (thre<<1)**/ + int32_t ai = pn - tn, uge = INT32_MAX; + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site; + } + + i = 0; + while (i < ai) { + bd = (i>>bitw); i_bd = (i&bitz); + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); + ++i; + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site + i; + } + if(i == thre) uge = err; + } + + if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; +} + +inline void ed_band_cal_extension_infi_0_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) +{ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; ez->pe = ez->te = -1; + if(pn > tn + thre) pn = tn + thre; + else if(tn > pn + thre) tn = pn + thre; + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, wz, wz1, Peq_i; w_sig c, ad, Peq_m; + int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k; + if(nword) { + ez->nword = (*nword); + } else { + bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); + } + resize_bit_extz_t((*ez), (thre)); + wz = sizeof(*(ez->a))*(ez->nword); + memset((ez->Peq[0]).a, 0, wz); + memset((ez->Peq[1]).a, 0, wz); + memset((ez->Peq[2]).a, 0, wz); + memset((ez->Peq[3]).a, 0, wz); + memset((ez->Peq[4]).a, 0, wz); + + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; + ed_init_core(i, bd, i_bd, pstr, ez->Peq); + bd = thre+1, i_bd = thre; + + memset((ez->Peq[4]).a, 0, wz); + err = thre; + w_infi_set_bit_lsub(ez->VN, thre, ez->nword); /**VN = (((Word)1)<<(thre))-1;**/ + w_infi_set_bit_lsub(ez->VP, (thre<<1)+1, ez->nword); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/ + w_infi_self_xor(ez->VP, ez->VN, ez->nword, wz) /**VP ^= VN;**/ + + i = 0; + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); + //for debug + // memset((ez->X).a, 0, sizeof(*(ez->a))*(ez->nword)); + // memset((ez->D0).a, 0, sizeof(*(ez->a))*(ez->nword)); + // memset((ez->HN).a, 0, sizeof(*(ez->a))*(ez->nword)); + // memset((ez->HP).a, 0, sizeof(*(ez->a))*(ez->nword)); + while (i < tn0) { + // fprintf(stderr, "i::%d\n", i); + // prt_bit_extz_t((*ez), ((thre<<1)+1)); + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + + { + poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ + if(k >= 0) { + if(tmp_e == INT32_MAX) { + tmp_e = err; + for ((k) = 0; (poff) < (pe); (poff)++, (k)++) { + bd = (k>>bitw); k_bd = (k&bitz); + (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1)); + (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1)); + } + } else { + k = (thre<<1) - k; + if(k >= 0) { + bd = (k>>bitw); k_bd = (k&bitz); + (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1)); + (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1)); + } + } + if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) { + (*ez).err = tmp_e; (*ez).pe = pe; (*ez).te = i; + } + } + // if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e) { + // fprintf(stderr, "i::%d, tmp_e::%d, dbg_ext_err::%d\n", i, tmp_e, dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))); + // } + } + + ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); + ++i; ++i_bd; c = 4; + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; + } + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + + int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/ + for (cut = pn - 1, i = 0; site < cut; i++) { + bd = (i>>bitw); i_bd = (i&bitz); + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); + site++; + if(err <= thre && err < ez->err) { + ez->err = err; ez->pe = site; ez->te = tn-1; + } + } + if(err <= thre && err < ez->err) { + ez->err = err; ez->pe = site; ez->te = tn-1; + } + return; +} + +inline void ed_band_cal_extension_infi_1_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) +{ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = INT32_MAX; ez->pe = pn-1; ez->te = tn-1; + if(pn > tn + thre) pn = tn + thre; + else if(tn > pn + thre) tn = pn + thre; + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, wz, wz1, Peq_i; + int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k, pidx = ez->pe, tidx = ez->te; w_sig c, ad, Peq_m; + if(nword) { + ez->nword = (*nword); + } else { + bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); + } + resize_bit_extz_t((*ez), (thre)); + wz = sizeof(*(ez->a))*(ez->nword); + memset((ez->Peq[0]).a, 0, wz); + memset((ez->Peq[1]).a, 0, wz); + memset((ez->Peq[2]).a, 0, wz); + memset((ez->Peq[3]).a, 0, wz); + memset((ez->Peq[4]).a, 0, wz); + + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; + for (i = 0; i < bd; i++, i_bd++) { + w_bit((ez->Peq)[seq_nt4_table[(uint8_t)(pstr)[pidx-i]]], (i_bd)); + } + bd = thre+1, i_bd = thre; + + memset((ez->Peq[4]).a, 0, wz); + err = thre; + w_infi_set_bit_lsub(ez->VN, thre, ez->nword); /**VN = (((Word)1)<<(thre))-1;**/ + w_infi_set_bit_lsub(ez->VP, (thre<<1)+1, ez->nword); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/ + w_infi_self_xor(ez->VP, ez->VN, ez->nword, wz) /**VP ^= VN;**/ + + i = 0; + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); + while (i < tn0) { + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + + { + poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ + if(k >= 0) { + if(tmp_e == INT32_MAX) { + tmp_e = err; + for ((k) = 0; (poff) < (pe); (poff)++, (k)++) { + bd = (k>>bitw); k_bd = (k&bitz); + (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1)); + (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1)); + } + } else { + k = (thre<<1) - k; + if(k >= 0) { + bd = (k>>bitw); k_bd = (k&bitz); + (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1)); + (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1)); + } + } + if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) { + (*ez).err = tmp_e; (*ez).ps = pidx - pe; (*ez).ts = tidx-i; + } + } + } + // if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e) { + // fprintf(stderr, "i::%d, tmp_e::%d, dbg_ext_err::%d\n", i, tmp_e, dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))); + // } + + ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); + ++i; ++i_bd; c = 4; + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[pidx-i_bd]]; + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; + } + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + + int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/ + for (cut = pn - 1, i = 0; site < cut; i++) { + bd = (i>>bitw); i_bd = (i&bitz); + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); + site++; + if(err <= thre && err < ez->err) { + ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; + } + } + if(err <= thre && err < ez->err) { + ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; + } + return; +} + +inline void ed_band_cal_global_infi_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) +{ + ez->cigar.n = 0;//diff + if(ez->err > thre) {//diff + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; + } else if(ez->err == 0) {//diff + push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;//diff + } + if((pn > tn + thre) || (tn > pn + thre)) return; + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, wz, wz1, Peq_i, ws; w_sig c, ad, Peq_m; + if(nword) { + ez->nword = (*nword); + } else { + bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); + } + resize_bit_extz_t((*ez), (thre)); + wz = ws = sizeof(*(ez->a))*(ez->nword);//diff + memset((ez->Peq[0]).a, 0, wz); + memset((ez->Peq[1]).a, 0, wz); + memset((ez->Peq[2]).a, 0, wz); + memset((ez->Peq[3]).a, 0, wz); + memset((ez->Peq[4]).a, 0, wz); + + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; + ed_init_core(i, bd, i_bd, pstr, ez->Peq); + bd = thre+1, i_bd = thre; + + memset((ez->Peq[4]).a, 0, wz); + err = thre; + w_infi_set_bit_lsub(ez->VN, thre, ez->nword); /**VN = (((Word)1)<<(thre))-1;**/ + w_infi_set_bit_lsub(ez->VP, (thre<<1)+1, ez->nword); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/ + w_infi_self_xor(ez->VP, ez->VN, ez->nword, wz) /**VP ^= VN;**/ + + ez->path.n=(ez->nword*tn*5);//diff + kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff + + i = 0; + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); + while (i < tn0) { + // fprintf(stderr, "\ni::%d\n", i); + // prt_bit_extz_t((*ez), (((thre<<1))+1)); + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + + ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); + ++i; ++i_bd; c = 4; + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; + // fprintf(stderr, "c::%u\n", c); + // print_bits(ez->Peq[c].a, (((thre<<1))+1), "Peq[c]"); + + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff + } + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff + + int32_t site = tn - 1 - thre;/**up bound**/ + if(ez->err > thre) {//diff + for (cut = pn - 1, i = 0; site < cut; site++, i++) { + bd = (i>>bitw); i_bd = (i&bitz); + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); + } + + if (site == cut && err <= thre) { + ez->err = err; + ez->pe = pn-1; ez->te = tn-1; + } + } + gen_trace(ez, thre, 1);//diff + return; +} + +inline void ed_band_cal_semi_infi_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) +{ + ez->cigar.n = 0;//diff + if(ez->err > thre) {//diff + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1; + } else if(ez->err == 0) {//diff + push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); //diff + ez->ps = ez->pe - (ez->te-ez->ts);//diff + return;//diff + } + int32_t bd, i, err = 0, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, wz, wz1, ws, Peq_i; w_sig c, ad, Peq_m; + if((pn > tn + cut) || (tn > pn + cut)) return; + + if(nword) { + ez->nword = (*nword); + } else { + bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); + } + resize_bit_extz_t((*ez), (thre)); + wz = ws = sizeof(*(ez->a))*(ez->nword);//diff + memset((ez->Peq[0]).a, 0, wz); + memset((ez->Peq[1]).a, 0, wz); + memset((ez->Peq[2]).a, 0, wz); + memset((ez->Peq[3]).a, 0, wz); + memset((ez->Peq[4]).a, 0, wz); + memset((ez->VP).a, 0, wz); + memset((ez->VN).a, 0, wz); + + bd = (thre<<1)+1; bd = ((bd<=pn)?bd:pn); i_bd = 0; + ed_init_core(i, bd, i_bd, pstr, ez->Peq); + bd = (thre<<1)+1, i_bd = (thre<<1); + + memset((ez->Peq[4]).a, 0, wz); + + ez->path.n=(ez->nword*tn*5);//diff + kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff + + i = 0; + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); + while (i < tn0) { + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + + ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); + ++i; ++i_bd; c = 4; + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; + + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff + } + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff + + int32_t site = tn - 1;/**up bound**/ + /**in most cases, ai = (thre<<1)**/ + int32_t ai = pn - tn, uge = INT32_MAX; + if(ez->err > thre) {//diff + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site; + } + + i = 0; + while (i < ai) { + bd = (i>>bitw); i_bd = (i&bitz); + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); + ++i; + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site + i; + } + if(i == thre) uge = err; + } + if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; + } + gen_trace(ez, 0, 1);//diff +} + +inline void ed_band_cal_extension_infi_0_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) +{ + int32_t done = 1;//diff + ez->cigar.n = 0; //diff + if(ez->err > thre) {//diff + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; ez->pe = ez->te = -1; + if(pn > tn + thre) pn = tn + thre; + else if(tn > pn + thre) tn = pn + thre; + done = 0;//diff + } else if(ez->err == 0) {//diff + push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;//diff + } else { + pn = ez->pe + 1 - ez->ps; tn = ez->te + 1 - ez->ts; //diff + } + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, wz, wz1, ws, Peq_i; w_sig c, ad, Peq_m; + int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k; + if(nword) { + ez->nword = (*nword); + } else { + bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); + } + resize_bit_extz_t((*ez), (thre)); + wz = ws = sizeof(*(ez->a))*(ez->nword);//diff + memset((ez->Peq[0]).a, 0, wz); + memset((ez->Peq[1]).a, 0, wz); + memset((ez->Peq[2]).a, 0, wz); + memset((ez->Peq[3]).a, 0, wz); + memset((ez->Peq[4]).a, 0, wz); + + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; + ed_init_core(i, bd, i_bd, pstr, ez->Peq); + bd = thre+1, i_bd = thre; + + memset((ez->Peq[4]).a, 0, wz); + err = thre; + w_infi_set_bit_lsub(ez->VN, thre, ez->nword); /**VN = (((Word)1)<<(thre))-1;**/ + w_infi_set_bit_lsub(ez->VP, (thre<<1)+1, ez->nword); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/ + w_infi_self_xor(ez->VP, ez->VN, ez->nword, wz) /**VP ^= VN;**/ + + ez->path.n=(ez->nword*tn*5);//diff + kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff + + i = 0; + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); + //for debug + // memset((ez->X).a, 0, sizeof(*(ez->a))*(ez->nword)); + // memset((ez->D0).a, 0, sizeof(*(ez->a))*(ez->nword)); + // memset((ez->HN).a, 0, sizeof(*(ez->a))*(ez->nword)); + // memset((ez->HP).a, 0, sizeof(*(ez->a))*(ez->nword)); + while (i < tn0) { + // fprintf(stderr, "i::%d\n", i); + // prt_bit_extz_t((*ez), ((thre<<1)+1)); + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + + if(!done) {//diff + poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ + if(k >= 0) { + if(tmp_e == INT32_MAX) { + tmp_e = err; + for ((k) = 0; (poff) < (pe); (poff)++, (k)++) { + bd = (k>>bitw); k_bd = (k&bitz); + (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1)); + (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1)); + } + } else { + k = (thre<<1) - k; + if(k >= 0) { + bd = (k>>bitw); k_bd = (k&bitz); + (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1)); + (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1)); + } + } + if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) { + (*ez).err = tmp_e; (*ez).pe = pe; (*ez).te = i; + } + } + // if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e) { + // fprintf(stderr, "i::%d, tmp_e::%d, dbg_ext_err::%d\n", i, tmp_e, dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))); + // } + } + + ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); + ++i; ++i_bd; c = 4; + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; + + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff + } + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff + + int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/ + if(!done) {//diff + for (cut = pn - 1, i = 0; site < cut; i++) { + bd = (i>>bitw); i_bd = (i&bitz); + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); + site++; + if(err <= thre && err < ez->err) { + ez->err = err; ez->pe = site; ez->te = tn-1; + } + } + if(err <= thre && err < ez->err) { + ez->err = err; ez->pe = site; ez->te = tn-1; + } + } + + if((ez->te-ez->ts+1) != tn) {//diff + ez->path.n /= tn; ez->path.n *= (ez->te+1-ez->ts);//diff + }//diff + gen_trace(ez, thre, 1);//diff + return; +} + +inline void ed_band_cal_extension_infi_1_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t *nword, bit_extz_t *ez) +{ + int32_t done = 1;//diff + ez->cigar.n = 0;//diff + if(ez->err > thre) {//diff + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = INT32_MAX; ez->pe = pn-1; ez->te = tn-1; + if(pn > tn + thre) pn = tn + thre; + else if(tn > pn + thre) tn = pn + thre; + done = 0;//diff + } else if(ez->err == 0) {//diff + push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;//diff + } else { + pn = ez->pe + 1 - ez->ps; tn = ez->te + 1 - ez->ts; //diff + } + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, k_bd, wz, wz1, ws, Peq_i; + int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k, pidx = ez->pe, tidx = ez->te; w_sig c, ad, Peq_m; + if(nword) { + ez->nword = (*nword); + } else { + bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); + } + resize_bit_extz_t((*ez), (thre)); + wz = ws = sizeof(*(ez->a))*(ez->nword);//diff + memset((ez->Peq[0]).a, 0, wz); + memset((ez->Peq[1]).a, 0, wz); + memset((ez->Peq[2]).a, 0, wz); + memset((ez->Peq[3]).a, 0, wz); + memset((ez->Peq[4]).a, 0, wz); + + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; + for (i = 0; i < bd; i++, i_bd++) { + w_bit((ez->Peq)[seq_nt4_table[(uint8_t)(pstr)[pidx-i]]], (i_bd)); + } + bd = thre+1, i_bd = thre; + + memset((ez->Peq[4]).a, 0, wz); + err = thre; + w_infi_set_bit_lsub(ez->VN, thre, ez->nword); /**VN = (((Word)1)<<(thre))-1;**/ + w_infi_set_bit_lsub(ez->VP, (thre<<1)+1, ez->nword); /**VP = (((Word)1)<<((thre<<1)+1))-1;**/ + w_infi_self_xor(ez->VP, ez->VN, ez->nword, wz) /**VP ^= VN;**/ + + ez->path.n=(ez->nword*tn*5);//diff + kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff + + i = 0; + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); + while (i < tn0) { + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + + if(!done) {//diff + poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ + if(k >= 0) { + if(tmp_e == INT32_MAX) { + tmp_e = err; + for ((k) = 0; (poff) < (pe); (poff)++, (k)++) { + bd = (k>>bitw); k_bd = (k&bitz); + (tmp_e) += (((*ez).VP.a[bd]>>k_bd)&((w_sig)1)); + (tmp_e) -= (((*ez).VN.a[bd]>>k_bd)&((w_sig)1)); + } + } else { + k = (thre<<1) - k; + if(k >= 0) { + bd = (k>>bitw); k_bd = (k&bitz); + (tmp_e) += (((*ez).HP.a[bd]>>k_bd)&((w_sig)1)); + (tmp_e) -= (((*ez).HN.a[bd]>>k_bd)&((w_sig)1)); + } + } + if((tmp_e) <= (*ez).thre && (tmp_e) < (*ez).err) { + (*ez).err = tmp_e; (*ez).ps = pidx - pe; (*ez).ts = tidx-i; + } + } + } + // if(dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))!=tmp_e) { + // fprintf(stderr, "i::%d, tmp_e::%d, dbg_ext_err::%d\n", i, tmp_e, dbg_ext_err(i, thre, err, pe, &((*ez).VP), &((*ez).VN))); + // } + + ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); + ++i; ++i_bd; c = 4; + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[pidx-i_bd]]; + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; + + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff + } + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[tidx-i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff + + int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/ + if(!done) {//diff + for (cut = pn - 1, i = 0; site < cut; i++) { + bd = (i>>bitw); i_bd = (i&bitz); + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); + site++; + if(err <= thre && err < ez->err) { + ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; + } + } + if(err <= thre && err < ez->err) { + ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; + } + } + + if((ez->te-ez->ts+1) != tn) {//diff + ez->path.n /= tn; ez->path.n *= (ez->te+1-ez->ts);//diff + }//diff + + poff = ez->ps; ez->ps = pidx - ez->pe; ez->pe = pidx - poff;//diff + gen_trace(ez, thre, 0);//diff + poff = ez->ps; ez->ps = pidx - ez->pe; ez->pe = pidx - poff;//diff + return; +} + +inline void ed_band_cal_semi_infi_w_absent_diag(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t abs_diag, int32_t *nword, bit_extz_t *ez) +{ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1; + int32_t bd, i, err = abs_diag, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, wz, wz1, Peq_i; w_sig c, ad, Peq_m; + if((pn > tn + cut) || (tn > pn + cut)) return; + + if(nword) { + ez->nword = (*nword); + } else { + bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); + } + resize_bit_extz_t((*ez), (thre)); + wz = sizeof(*(ez->a))*(ez->nword); + memset((ez->Peq[0]).a, 0, wz); + memset((ez->Peq[1]).a, 0, wz); + memset((ez->Peq[2]).a, 0, wz); + memset((ez->Peq[3]).a, 0, wz); + memset((ez->Peq[4]).a, 0, wz); + memset((ez->VP).a, 0, wz); + w_infi_set_bit_lsub(ez->VN, abs_diag, ez->nword); /**VN = (((Word)1)<<(abs_diag))-1; ;**/ + + bd = ((thre<<1)+1)-abs_diag; bd = ((bd<=pn)?bd:pn); i_bd = abs_diag; + ed_init_core(i, bd, i_bd, pstr, ez->Peq); + i_bd = (thre<<1)-abs_diag; + + memset((ez->Peq[4]).a, 0, wz); + i = 0; + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); + while (i < tn0) { + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + + ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); + ++i; ++i_bd; c = 4; + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; + } + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + + int32_t site = tn - 1 - abs_diag;/**up bound**/ + /**in most cases, ai = (thre<<1)**/ + int32_t ai = pn - tn + abs_diag, uge = INT32_MAX; i = 0; + for (i = 0; site < 0 && i < ai; i++, site++) { + bd = (i>>bitw); i_bd = (i&bitz); + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); + } + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site; + } + site -= i; + while (i < ai) { + bd = (i>>bitw); i_bd = (i&bitz); + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); + ++i; + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site + i; + } + if(i == thre) uge = err; + } + if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; +} + +inline void ed_band_cal_semi_infi_w_absent_diag_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t abs_diag, int32_t *nword, bit_extz_t *ez) +{ + ez->cigar.n = 0;//diff + if(ez->err > thre) {//diff + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1; + } else if(ez->err == 0) {//diff + push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); //diff + ez->ps = ez->pe - (ez->te-ez->ts);//diff + return;//diff + } + int32_t bd, i, err = abs_diag, i_bd, cut = thre+(thre<<1), tn0 = tn - 1, wz, wz1, ws, Peq_i; w_sig c, ad, Peq_m; + if((pn > tn + cut) || (tn > pn + cut)) return; + + if(nword) { + ez->nword = (*nword); + } else { + bd = (((thre)<<1)+1); ez->nword = ((bd>>bitw)+(!!(bd&bitz))); + } + resize_bit_extz_t((*ez), (thre)); + wz = ws = sizeof(*(ez->a))*(ez->nword);//diff + memset((ez->Peq[0]).a, 0, wz); + memset((ez->Peq[1]).a, 0, wz); + memset((ez->Peq[2]).a, 0, wz); + memset((ez->Peq[3]).a, 0, wz); + memset((ez->Peq[4]).a, 0, wz); + memset((ez->VP).a, 0, wz); + w_infi_set_bit_lsub(ez->VN, abs_diag, ez->nword); /**VN = (((Word)1)<<(abs_diag))-1; ;**/ + + bd = ((thre<<1)+1)-abs_diag; bd = ((bd<=pn)?bd:pn); i_bd = abs_diag; + ed_init_core(i, bd, i_bd, pstr, ez->Peq); + i_bd = (thre<<1)-abs_diag; + + memset((ez->Peq[4]).a, 0, wz); + + ez->path.n=(ez->nword*tn*5);//diff + kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff + + i = 0; + /**for the incoming char/last char; mm = ((Word)1 << (thre<<1))**/ + Peq_i = (((thre<<1))>>bitw); Peq_m = (((w_sig)1)<<(((thre<<1))&bitz)); + while (i < tn0) { + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + + ed_infi_post_Peq(ez->Peq, wz, wz1, ez->nword); + ++i; ++i_bd; c = 4; + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) ez->Peq[c].a[Peq_i]|=Peq_m; + + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff + } + ed_infi_core(ez->Peq, ez->VP, ez->VN, ez->X, ez->D0, ez->HN, ez->HP, (uint8_t)tstr[i], c, ad, wz, ez->nword); + if (!(ez->D0.a[0]&(1ULL))) { + ++err; if (err>cut) return; + } + memcpy(ez->path.a+ez->path.n, ez->D0.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->VN.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HP.a, ws); ez->path.n += ez->nword;//diff + memcpy(ez->path.a+ez->path.n, ez->HN.a, ws); ez->path.n += ez->nword;//diff + + int32_t site = tn - 1 - abs_diag;/**up bound**/ + /**in most cases, ai = (thre<<1)**/ + int32_t ai = pn - tn + abs_diag, uge = INT32_MAX; i = 0; + if(ez->err > thre) {//diff + for (i = 0; site < 0 && i < ai; i++, site++) { + bd = (i>>bitw); i_bd = (i&bitz); + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); + } + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site; + } + site -= i; + while (i < ai) { + bd = (i>>bitw); i_bd = (i&bitz); + err += (((*ez).VP.a[bd]>>i_bd)&((w_sig)1)); + err -= (((*ez).VN.a[bd]>>i_bd)&((w_sig)1)); + ++i; + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site + i; + } + if(i == thre) uge = err; + } + if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; + } + gen_trace(ez, abs_diag, 1);//diff +} + + +#define ed_core_64(Peq, VP, VN, X, D0, HN, HP, z) { \ + /**X = Peq[seq_nt4_table[(uint8_t)tstr[i]]] | VN;**/\ + (X) = (Peq)[(seq_nt4_table[(z)])]|(VN);\ + (D0) = (((VP) + ((X)&(VP))) ^ (VP)) | (X);\ + (HN) = (VP)&(D0);\ + (HP) = (VN) | ~((VP) | (D0));\ + (X) = (D0) >> 1;\ + (VN) = (X)&(HP);\ + (VP) = (HN) | ~((X) | (HP));\ +} + +inline void ed_band_cal_global_64_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) +{ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; + if((pn > tn + thre) || (tn > pn + thre)) return; + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd; + Word c, Peq[5] = {0}, VP, VN, X, D0, HN, HP, mm; + + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; + for (i = 0, mm = (((Word)1)<cut) return; + } + + Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; + ++i; ++i_bd; + if(i_bd < pn) { + c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) Peq[c] |= mm; + // fprintf(stderr, "c::%lu\n", c); + // print_bit(Peq[c], (((thre<<1))+1), "Peq[c]"); + } + } + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + + int32_t site = tn - 1 - thre;/**up bound**/\ + for (cut = pn - 1; site < cut; site++) { + err += VP&(1ULL); VP >>= 1; err -= VN&(1ULL); VN >>= 1; + } + + if (site == cut && err <= thre) { + ez->err = err; + ez->pe = pn-1; ez->te = tn-1; + } + return; +} + +inline void ed_band_cal_semi_64_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) +{ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1; + Word c, Peq[5] = {0}, VP = 0, VN = 0, X, D0, HN, HP, mm; + int32_t bd, i, err = 0, i_bd, last_high = (thre<<1), tn0 = tn - 1, cut = thre+last_high; + if((pn > tn + cut) || (tn > pn + cut)) return; + + bd = (thre<<1)+1; bd = ((bd<=pn)?bd:pn); + for (i = 0, mm = 1; i < bd; i++) { + Peq[seq_nt4_table[(uint8_t)pstr[i]]] |= mm; mm <<= 1; + } + bd = (thre<<1)+1, i_bd = (thre<<1); + + i = 0; Peq[4] = 0; mm = ((Word)1 << (thre<<1));///for the incoming char/last char** + while (i < tn0) { + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + + Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; + ++i; ++i_bd; c = 4; + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) Peq[c] |= mm; + } + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + + int32_t site = tn - 1;/**up bound**/ + /**in most cases, ai = (thre<<1)**/ + int32_t ai = pn - tn, uge = INT32_MAX; + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site; + } + + i = 0; + while (i < ai) {\ + err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); ++i; + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site + i; + } + if(i == thre) uge = err; + } + + if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; +} + +inline void ed_band_cal_extension_64_0_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) +{ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; ez->pe = ez->te = -1; + if(pn > tn + thre) pn = tn + thre; + else if(tn > pn + thre) tn = pn + thre; + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, poff, pe = pn-1, tmp_e = INT32_MAX, k; + Word c, Peq[5] = {0}, VP, VN, X, D0, HN, HP, mm; + + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; + for (i = 0, mm = (((Word)1)<cut) return; + } + + { + poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ + if(k >= 0) { + if(tmp_e == INT32_MAX) { + tmp_e = err; + for (k = 0; poff < pe; poff++, (k)++) { + tmp_e += ((VP>>k)&(1ULL)); tmp_e -= ((VN>>k)&(1ULL)); + } + } else { + k = (thre<<1) - k; + if(k >= 0) { + tmp_e += ((HP>>k)&(1ULL)); tmp_e -= ((HN>>k)&(1ULL)); + } + } + if(tmp_e <= (*ez).thre && tmp_e < (*ez).err) { + (*ez).err = tmp_e; (*ez).pe = pe; (*ez).te = i; + } + } + } + // fprintf(stderr, "i::%d, tmp_e::%d, err::%d\n", i, tmp_e, err); + + Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; + ++i; ++i_bd; + if(i_bd < pn) { + c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) Peq[c] |= mm; + } + } + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + + int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/\ + for (cut = pn - 1; site < cut; ) { + err += VP&(1ULL); VP >>= 1; err -= VN&(1ULL); VN >>= 1; + site++; + if(err <= thre && err < ez->err) { + ez->err = err; ez->pe = site; ez->te = tn-1; + } + } + if(err <= thre && err < ez->err) { + ez->err = err; ez->pe = site; ez->te = tn-1; + } + return; +} + +inline void ed_band_cal_extension_64_1_w(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) +{ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = INT32_MAX; ez->pe = pn-1; ez->te = tn-1; + if(pn > tn + thre) pn = tn + thre; + else if(tn > pn + thre) tn = pn + thre; + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd; + int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k, pidx = ez->pe, tidx = ez->te; + Word c, Peq[5] = {0}, VP, VN, X, D0, HN, HP, mm; + + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; + for (i = 0, mm = (((Word)1)<cut) return; + } + + { + poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ + if(k >= 0) { + if(tmp_e == INT32_MAX) { + tmp_e = err; + for (k = 0; poff < pe; poff++, (k)++) { + tmp_e += ((VP>>k)&(1ULL)); tmp_e -= ((VN>>k)&(1ULL)); + } + } else { + k = (thre<<1) - k; + if(k >= 0) { + tmp_e += ((HP>>k)&(1ULL)); tmp_e -= ((HN>>k)&(1ULL)); + } + } + if(tmp_e <= (*ez).thre && tmp_e < (*ez).err) { + (*ez).err = tmp_e; (*ez).ps = pidx - pe; (*ez).ts = tidx-i; + } + } + } + // fprintf(stderr, "i::%d, tmp_e::%d, err::%d\n", i, tmp_e, err); + + Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; + ++i; ++i_bd; + if(i_bd < pn) { + c = seq_nt4_table[(uint8_t)pstr[pidx-i_bd]]; + if(c < 4) Peq[c] |= mm; + } + } + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[tidx-i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + + int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/\ + for (cut = pn - 1; site < cut; ) { + err += VP&(1ULL); VP >>= 1; err -= VN&(1ULL); VN >>= 1; + site++; + if(err <= thre && err < ez->err) { + ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; + } + } + if(err <= thre && err < ez->err) { + ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; + } + return; +} + +inline void ed_band_cal_global_64_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) +{ + ez->cigar.n = 0; ez->nword = 1;//diff + if(ez->err > thre) {//diff + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0;//diff + } else if(ez->err == 0) {//diff + push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;//diff + } + if((pn > tn + thre) || (tn > pn + thre)) return; + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd; + w_sig c, Peq[5] = {0}, VP, VN, X, D0, HN, HP, mm; + + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; + for (i = 0, mm = (((w_sig)1)<path.n=(ez->nword*tn*5);//diff + kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff + + i = 0; mm = ((w_sig)1 << (thre<<1));///for the incoming char/last char + while (i < tn0) { + // fprintf(stderr, "\ni::%d\n", i); + // prt_vector(Peq, VP, VN, X, D0, HN, HP, (((thre<<1))+1)); + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + + Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; + ++i; ++i_bd; + if(i_bd < pn) { + c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) Peq[c] |= mm; + } + ez->path.a[ez->path.n++] = D0;//diff + ez->path.a[ez->path.n++] = VP;//diff + ez->path.a[ez->path.n++] = VN;//diff + ez->path.a[ez->path.n++] = HP;//diff + ez->path.a[ez->path.n++] = HN;//diff + } + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + ez->path.a[ez->path.n++] = D0;//diff + ez->path.a[ez->path.n++] = VP;//diff + ez->path.a[ez->path.n++] = VN;//diff + ez->path.a[ez->path.n++] = HP;//diff + ez->path.a[ez->path.n++] = HN;//diff + + int32_t site = tn - 1 - thre;/**up bound**/\ + if(ez->err > thre) {//diff + for (cut = pn - 1; site < cut; site++) { + err += VP&(1ULL); VP >>= 1; err -= VN&(1ULL); VN >>= 1; + } + + if (site == cut && err <= thre) { + ez->err = err; + ez->pe = pn-1; ez->te = tn-1; + } + } + ///should update ez->path.n for extension + gen_trace(ez, thre, 1);//diff + return; +} + +inline void ed_band_cal_semi_64_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) +{ + ez->cigar.n = 0; ez->nword = 1;//diff + if(ez->err > thre) {//diff + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1;//diff + } else if(ez->err == 0) {//diff + push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); //diff + ez->ps = ez->pe - (ez->te-ez->ts);//diff + return;//diff + } + Word c, Peq[5] = {0}, VP = 0, VN = 0, X, D0, HN, HP, mm; + int32_t bd, i, err = 0, i_bd, last_high = (thre<<1), tn0 = tn - 1, cut = thre+last_high; + if((pn > tn + cut) || (tn > pn + cut)) return; + + bd = (thre<<1)+1; bd = ((bd<=pn)?bd:pn); + for (i = 0, mm = 1; i < bd; i++) { + Peq[seq_nt4_table[(uint8_t)pstr[i]]] |= mm; mm <<= 1; + } + bd = (thre<<1)+1, i_bd = (thre<<1); + + ez->path.n=(ez->nword*tn*5);//diff + kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff + + i = 0; Peq[4] = 0; mm = ((Word)1 << (thre<<1));///for the incoming char/last char** + while (i < tn0) { + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + + Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; + ++i; ++i_bd; c = 4; + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) Peq[c] |= mm; + + ez->path.a[ez->path.n++] = D0;//diff + ez->path.a[ez->path.n++] = VP;//diff + ez->path.a[ez->path.n++] = VN;//diff + ez->path.a[ez->path.n++] = HP;//diff + ez->path.a[ez->path.n++] = HN;//diff + } + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + ez->path.a[ez->path.n++] = D0;//diff + ez->path.a[ez->path.n++] = VP;//diff + ez->path.a[ez->path.n++] = VN;//diff + ez->path.a[ez->path.n++] = HP;//diff + ez->path.a[ez->path.n++] = HN;//diff + + int32_t site = tn - 1;/**up bound**/ + /**in most cases, ai = (thre<<1)**/ + int32_t ai = pn - tn, uge = INT32_MAX; + if(ez->err > thre) {//diff + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site; + } + + i = 0; + while (i < ai) { + err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); ++i; + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site + i; + } + if(i == thre) uge = err; + } + if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; + } + ///should update ez->path.n for extension + gen_trace(ez, 0, 1);//diff +} + +inline void ed_band_cal_extension_64_0_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) +{ + int32_t done = 1;//diff + ez->cigar.n = 0; ez->nword = 1;//diff + if(ez->err > thre) {//diff + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = 0; ez->pe = ez->te = -1; + if(pn > tn + thre) pn = tn + thre; + else if(tn > pn + thre) tn = pn + thre; + done = 0;//diff + } else if(ez->err == 0) {//diff + push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;//diff + } else { + pn = ez->pe + 1 - ez->ps; tn = ez->te + 1 - ez->ts; //diff + } + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd, poff, pe = pn-1, tmp_e = INT32_MAX, k; + Word c, Peq[5] = {0}, VP, VN, X, D0, HN, HP, mm; + + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; + for (i = 0, mm = (((Word)1)<path.n=(ez->nword*tn*5);//diff + kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff + + i = 0; mm = ((Word)1 << (thre<<1)); + // X = D0 = HN = HP = mm = 0;//for debug + while (i < tn0) { + // fprintf(stderr, "i::%d\n", i); + // prt_vector(Peq, VP, VN, X, D0, HN, HP, ((thre<<1)+1)); + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + + if(!done) {//diff + poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ + if(k >= 0) { + if(tmp_e == INT32_MAX) { + tmp_e = err; + for (k = 0; poff < pe; poff++, (k)++) { + tmp_e += ((VP>>k)&(1ULL)); tmp_e -= ((VN>>k)&(1ULL)); + } + } else { + k = (thre<<1) - k; + if(k >= 0) { + tmp_e += ((HP>>k)&(1ULL)); tmp_e -= ((HN>>k)&(1ULL)); + } + } + if(tmp_e <= (*ez).thre && tmp_e < (*ez).err) { + (*ez).err = tmp_e; (*ez).pe = pe; (*ez).te = i; + } + // fprintf(stderr, "i::%d, (*ez).err::%d, (*ez).pe::%d, (*ez).te::%d, thre::%d, err::%d, tmp_e::%d, poff::%d, k::%d, pe::%d\n", + // i, (*ez).err, (*ez).pe, (*ez).te, thre, err, tmp_e, i-thre, i+thre-pe, pe); + } + } + + Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; + ++i; ++i_bd; + if(i_bd < pn) { + c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) Peq[c] |= mm; + } + // if(((ez->path.n+5)>(ez->nword*tn*5))||((ez->path.n+5)>(ez->path.m))) { + // fprintf(stderr, "[M::%s::] pn::%d, tn::%d\n", __func__, pn, tn); + // } + ez->path.a[ez->path.n++] = D0;//diff + ez->path.a[ez->path.n++] = VP;//diff + ez->path.a[ez->path.n++] = VN;//diff + ez->path.a[ez->path.n++] = HP;//diff + ez->path.a[ez->path.n++] = HN;//diff + } + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + // if(((ez->path.n+5)>(ez->nword*tn*5))||((ez->path.n+5)>(ez->path.m))) { + // fprintf(stderr, "[M::%s::] pn::%d, tn::%d\n", __func__, pn, tn); + // } + ez->path.a[ez->path.n++] = D0;//diff + ez->path.a[ez->path.n++] = VP;//diff + ez->path.a[ez->path.n++] = VN;//diff + ez->path.a[ez->path.n++] = HP;//diff + ez->path.a[ez->path.n++] = HN;//diff + + int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/ + if(!done) {//diff + for (cut = pn - 1; site < cut; ) { + err += VP&(1ULL); VP >>= 1; err -= VN&(1ULL); VN >>= 1; + site++; + if(err <= thre && err < ez->err) { + ez->err = err; ez->pe = site; ez->te = tn-1; + } + } + if(err <= thre && err < ez->err) { + ez->err = err; ez->pe = site; ez->te = tn-1; + } + } + + if((ez->te-ez->ts+1) != tn) {//diff + ez->path.n /= tn; ez->path.n *= (ez->te+1-ez->ts);//diff + }//diff + gen_trace(ez, thre, 1);//diff + return; +} + +inline void ed_band_cal_extension_64_1_w_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, bit_extz_t *ez) +{ + int32_t done = 1;//diff + ez->cigar.n = 0; ez->nword = 1;//diff + if(ez->err > thre) {//diff + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->ts = INT32_MAX; ez->pe = pn-1; ez->te = tn-1; + if(pn > tn + thre) pn = tn + thre; + else if(tn > pn + thre) tn = pn + thre; + done = 0;//diff + } else if(ez->err == 0) {//diff + push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); return;//diff + } else { + pn = ez->pe + 1 - ez->ps; tn = ez->te + 1 - ez->ts; //diff + } + + int32_t i, err, tn0 = tn - 1, cut = thre+(thre<<1), bd, i_bd; + int32_t poff, pe = pn-1, tmp_e = INT32_MAX, k, pidx = ez->pe, tidx = ez->te; + Word c, Peq[5] = {0}, VP, VN, X, D0, HN, HP, mm; + + bd = thre+1; bd = ((bd<=pn)?bd:pn); i_bd = thre; + for (i = 0, mm = (((Word)1)<path.n=(ez->nword*tn*5);//diff + kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff + + i = 0; mm = ((Word)1 << (thre<<1)); + // X = D0 = HN = HP = mm = 0;//for debug + while (i < tn0) { + // fprintf(stderr, "i::%d\n", i); + // prt_vector(Peq, VP, VN, X, D0, HN, HP, ((thre<<1)+1)); + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[tidx-i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + + if(!done) {//diff + poff = i-thre; k = i+thre-pe;/**poff:[i-thre, i+thre]**/ + if(k >= 0) { + if(tmp_e == INT32_MAX) { + tmp_e = err; + for (k = 0; poff < pe; poff++, (k)++) { + tmp_e += ((VP>>k)&(1ULL)); tmp_e -= ((VN>>k)&(1ULL)); + } + } else { + k = (thre<<1) - k; + if(k >= 0) { + tmp_e += ((HP>>k)&(1ULL)); tmp_e -= ((HN>>k)&(1ULL)); + } + } + if(tmp_e <= (*ez).thre && tmp_e < (*ez).err) { + (*ez).err = tmp_e; (*ez).ps = pidx - pe; (*ez).ts = tidx-i; + } + } + } + // fprintf(stderr, "i::%d, tmp_e::%d, err::%d\n", i, tmp_e, err); + + Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; + ++i; ++i_bd; + if(i_bd < pn) { + c = seq_nt4_table[(uint8_t)pstr[pidx-i_bd]]; + if(c < 4) Peq[c] |= mm; + } + + ez->path.a[ez->path.n++] = D0;//diff + ez->path.a[ez->path.n++] = VP;//diff + ez->path.a[ez->path.n++] = VN;//diff + ez->path.a[ez->path.n++] = HP;//diff + ez->path.a[ez->path.n++] = HN;//diff + } + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[tidx-i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + ez->path.a[ez->path.n++] = D0;//diff + ez->path.a[ez->path.n++] = VP;//diff + ez->path.a[ez->path.n++] = VN;//diff + ez->path.a[ez->path.n++] = HP;//diff + ez->path.a[ez->path.n++] = HN;//diff + + int32_t site = tn - 1 - thre;/**up bound; site:[tn - 1 - thre, tn - 1 + thre]**/\ + if(!done) {//diff + for (cut = pn - 1; site < cut; ) { + err += VP&(1ULL); VP >>= 1; err -= VN&(1ULL); VN >>= 1; + site++; + if(err <= thre && err < ez->err) { + ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; + } + } + if(err <= thre && err < ez->err) { + ez->err = err; ez->ps = pidx-site; ez->ts = tidx+1-tn; + } + } + + if((ez->te-ez->ts+1) != tn) {//diff + ez->path.n /= tn; ez->path.n *= (ez->te+1-ez->ts);//diff + }//diff + + poff = ez->ps; ez->ps = pidx - ez->pe; ez->pe = pidx - poff;//diff + gen_trace(ez, thre, 0);//diff + poff = ez->ps; ez->ps = pidx - ez->pe; ez->pe = pidx - poff;//diff + return; +} + +inline void ed_band_cal_semi_64_w_absent_diag(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t abs_diag, bit_extz_t *ez) +{ + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1; + Word c, Peq[5] = {0}, VP = 0, VN, X, D0, HN, HP, mm; + int32_t bd, i, err = abs_diag, i_bd, last_high = (thre<<1), tn0 = tn - 1, cut = thre+last_high; + if((pn > tn + cut) || (tn > pn + cut)) return; + + bd = ((thre<<1)+1)-abs_diag; bd = ((bd<=pn)?bd:pn); i_bd = abs_diag; + for (i = 0, mm = (((Word)1)<cut) return; + } + + Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; + ++i; ++i_bd; c = 4; + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) Peq[c] |= mm; + } + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + + int32_t site = tn - 1 - abs_diag;/**up bound**/ + /**in most cases, ai = (thre<<1)**/ + int32_t ai = pn - tn + abs_diag, uge = INT32_MAX; i = 0; + for (i = 0; site < 0 && i < ai; i++, site++) { + err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); + } + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site; + } + site -= i; + while (i < ai) { + err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); ++i; + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site + i; + } + if(i == thre) uge = err; + } + + if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; +} + +inline void ed_band_cal_semi_64_w_absent_diag_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, int32_t abs_diag, bit_extz_t *ez) +{ + ez->cigar.n = 0; ez->nword = 1;//diff + if(ez->err > thre) {//diff + init_base_ed(*ez, thre, pn, tn); ez->ps = ez->pe = -1; ez->ts = 0; ez->te = tn-1;//diff + } else if(ez->err == 0) {//diff + push_trace(&(ez->cigar), 0, ez->te+1-ez->ts); //diff + ez->ps = ez->pe - (ez->te-ez->ts);//diff + return;//diff + } + Word c, Peq[5] = {0}, VP = 0, VN, X, D0, HN, HP, mm; + int32_t bd, i, err = abs_diag, i_bd, last_high = (thre<<1), tn0 = tn - 1, cut = thre+last_high; + if((pn > tn + cut) || (tn > pn + cut)) return; + + bd = ((thre<<1)+1)-abs_diag; bd = ((bd<=pn)?bd:pn); i_bd = abs_diag; + for (i = 0, mm = (((Word)1)<path.n=(ez->nword*tn*5);//diff + kv_resize(w_sig, ez->path, ez->path.n); ez->path.n=0;//diff + + i = 0; Peq[4] = 0; mm = ((Word)1 << (thre<<1));///for the incoming char/last char** + while (i < tn0) { + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + + Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; + ++i; ++i_bd; c = 4; + if(i_bd < pn) c = seq_nt4_table[(uint8_t)pstr[i_bd]]; + if(c < 4) Peq[c] |= mm; + + ez->path.a[ez->path.n++] = D0;//diff + ez->path.a[ez->path.n++] = VP;//diff + ez->path.a[ez->path.n++] = VN;//diff + ez->path.a[ez->path.n++] = HP;//diff + ez->path.a[ez->path.n++] = HN;//diff + } + ed_core_64(Peq, VP, VN, X, D0, HN, HP, (uint8_t)tstr[i]); + if (!(D0&(1ULL))) { + ++err; if (err>cut) return; + } + ez->path.a[ez->path.n++] = D0;//diff + ez->path.a[ez->path.n++] = VP;//diff + ez->path.a[ez->path.n++] = VN;//diff + ez->path.a[ez->path.n++] = HP;//diff + ez->path.a[ez->path.n++] = HN;//diff + + int32_t site = tn - 1 - abs_diag;/**up bound**/ + /**in most cases, ai = (thre<<1)**/ + int32_t ai = pn - tn + abs_diag, uge = INT32_MAX; i = 0; + if(ez->err > thre) {//diff + for (i = 0; site < 0 && i < ai; i++, site++) { + err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); + } + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site; + } + site -= i; + while (i < ai) { + err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); ++i; + if ((err <= thre) && (err <= ez->err)) { + ez->err = err; ez->pe = site + i; + } + if(i == thre) uge = err; + } + + if((uge <= thre) && (uge == ez->err)) ez->pe = site + thre; + } + ///should update ez->path.n for extension + gen_trace(ez, abs_diag, 1);//diff +} + +/** + pattern is the longer one, while text is the shorter one + **/ +inline int Reserve_Banded_BPM +(char *pattern, int p_length, char *text, int t_length, unsigned short errthold, unsigned int* return_err) +{ + (*return_err) = (unsigned int)-1; + + // bit_extz_t exz; ed_band_cal_semi_128bit(pattern, p_length, text, t_length, errthold, &exz); + // if(exz.err <= exz.thre) (*return_err) = exz.err; + // return exz.pe; + + Word Peq[256]; + + int band_length = (errthold << 1) + 1; + int i = 0; + Word tmp_Peq_1 = (Word)1; + + Peq[(uint8_t)'A'] = (Word)0; + Peq[(uint8_t)'T'] = (Word)0; + Peq[(uint8_t)'G'] = (Word)0; + Peq[(uint8_t)'C'] = (Word)0; + + + Word Peq_A; + Word Peq_T; + Word Peq_C; + Word Peq_G; + + ///band_length = 2k + 1 + for (i = 0; i> 1; + VN = X&HP; + VP = HN | ~(X | HP); + + if (!(D0&err_mask)) + { + ++err; + + if ((err - last_high)>(int)errthold) + { + return -1; + } + + } + + + Peq[(uint8_t)'A'] = Peq[(uint8_t)'A'] >> 1; + Peq[(uint8_t)'C'] = Peq[(uint8_t)'C'] >> 1; + Peq[(uint8_t)'G'] = Peq[(uint8_t)'G'] >> 1; + Peq[(uint8_t)'T'] = Peq[(uint8_t)'T'] >> 1; + + + ++i; + ++i_bd; + Peq[(uint8_t)pattern[i_bd]] = Peq[(uint8_t)pattern[i_bd]] | Mask; + } + + + + + + X = Peq[(uint8_t)text[i]] | VN; + D0 = ((VP + (X&VP)) ^ VP) | X; + HN = VP&D0; + HP = VN | ~(VP | D0); + X = D0 >> 1; + VN = X&HP; + VP = HN | ~(X | HP); + if (!(D0&err_mask)) + { + ++err; + if ((err - last_high)>errthold) + return -1; + } + + + ////fprintf(stderr, "sucess(2)\n"); + + /// last_high = 2k + /// site = (SEQ_LENGTH + 2k) - 2k -1 + /// site = SEQ_LENGTH - 1 + ///int site = p_length - last_high - 1; + int site = t_length - 1; + int return_site = -1; + ///in most cases, p_lengthshould be t_length + 2 * errthold + int available_i = p_length - t_length; + if ((err <= errthold) && ((unsigned int)err<=*return_err)) + { + *return_err = err; + return_site = site; + } + i = 0; + + /****************************may have bugs********************************/ + unsigned int ungap_error = (unsigned int)-1; + /****************************may have bugs********************************/ + + while (i < available_i) + { + err = err + ((VP >> i)&(Word)1); + err = err - ((VN >> i)&(Word)1); + ++i; + + if ((err <= (int)errthold) && ((unsigned int)err <= *return_err)) + { + *return_err = err; + return_site = site + i; + } + + /****************************may have bugs********************************/ + if(i == (int)errthold) + { + ungap_error = err; + } + /****************************may have bugs********************************/ + } + + /****************************may have bugs********************************/ + if((ungap_error<=errthold) && (ungap_error == (*return_err))) + { + return_site = site + errthold; + } + /****************************may have bugs********************************/ + + return return_site; + +} + + + +inline int try_cigar(char *pattern, int p_length, + char *text, int t_length, int end_site, char* path, + int error, + int* return_start_site, + int* return_path_length) +{ + int i = 0; + int tmp_err = 0; + ///start pos of y + int start_site = end_site - t_length + 1; + + if (start_site >= 0) + { + + for (i = 0; i < t_length; i++) + { + ///path[i] = 0; + ///path is saved backwards + path[t_length - i - 1] = 0; + if (text[i] != pattern[i + start_site]) + { + path[t_length - i - 1] = 1; + tmp_err++; + + if (tmp_err > error) + { + return 0; + } + } + } + + if (tmp_err == error) + { + (*return_path_length) = t_length; + + (*return_start_site) = start_site; + + return 6; + } + } + + + return 0; +} + + + +///p_length might be samller than t_length + 2 * errthold +inline int Reserve_Banded_BPM_PATH +(char *pattern, int p_length, char *text, int t_length, unsigned short errthold, + unsigned int* return_err, int* return_start_site, int* return_path_length, Word* matrix_bit, char* path, + int old_error, int old_end_site) +{ + if (old_error != -1 && old_end_site != -1) + { + if (old_error == 0) + { + (*return_err) = old_error; + (*return_start_site) = old_end_site - t_length + 1; + return old_end_site; + } + + if (try_cigar(pattern, p_length, text, t_length, old_end_site, path, + old_error, return_start_site, return_path_length)) + { + (*return_err) = old_error; + return old_end_site; + } + + } + + (*return_err) = (unsigned int)-1; + + Word Peq[256]; + + int band_length = (errthold << 1) + 1; + int i = 0; + Word tmp_Peq_1 = (Word)1; + + Peq[(uint8_t)'A'] = (Word)0; + Peq[(uint8_t)'T'] = (Word)0; + Peq[(uint8_t)'G'] = (Word)0; + Peq[(uint8_t)'C'] = (Word)0; + + + Word Peq_A; + Word Peq_T; + Word Peq_C; + Word Peq_G; + + ///band_length = 2k + 1 + for (i = 0; i> 1; + VN = X&HP; + VP = HN | ~(X | HP); + + if (!(D0&err_mask)) + { + ++err; + + if ((err - last_high)>(int)errthold) + { + return -1; + } + + } + + + Peq[(uint8_t)'A'] = Peq[(uint8_t)'A'] >> 1; + Peq[(uint8_t)'C'] = Peq[(uint8_t)'C'] >> 1; + Peq[(uint8_t)'G'] = Peq[(uint8_t)'G'] >> 1; + Peq[(uint8_t)'T'] = Peq[(uint8_t)'T'] >> 1; + + + ++i; + ++i_bd; + Peq[(uint8_t)pattern[i_bd]] = Peq[(uint8_t)pattern[i_bd]] | Mask; + + + ///Peq[(uint8_t)'T'] = Peq[(uint8_t)'T'] | Peq[(uint8_t)'C']; + + column_start = i << 3; + matrix_bit[column_start] = D0; + matrix_bit[column_start + 1] = VP; + matrix_bit[column_start + 2] = VN; + matrix_bit[column_start + 3] = HP; + matrix_bit[column_start + 4] = HN; + } + + + + + + X = Peq[(uint8_t)text[i]] | VN; + D0 = ((VP + (X&VP)) ^ VP) | X; + HN = VP&D0; + HP = VN | ~(VP | D0); + X = D0 >> 1; + VN = X&HP; + VP = HN | ~(X | HP); + if (!(D0&err_mask)) + { + ++err; + if ((err - last_high)>(int)errthold) + return -1; + } + + + column_start = (i + 1) << 3; + matrix_bit[column_start] = D0; + matrix_bit[column_start + 1] = VP; + matrix_bit[column_start + 2] = VN; + matrix_bit[column_start + 3] = HP; + matrix_bit[column_start + 4] = HN; + + + ////fprintf(stderr, "sucess(2)\n"); + + /// last_high = 2k + /// site = (SEQ_LENGTH + 2k) - 2k -1 + /// site = SEQ_LENGTH - 1 + ///int site = p_length - last_high - 1; + int site = t_length - 1; + int return_site = -1; + + /****************************may have bugs********************************/ + unsigned int ungap_error = (unsigned int)-1; + /****************************may have bugs********************************/ + + ///in most cases, p_length should be t_length + 2 * errthold + int available_i = p_length - t_length; + if ((err <= (int)errthold) && ((unsigned int)err<=*return_err)) + { + *return_err = err; + return_site = site; + } + i = 0; + + while (i < available_i) + { + err = err + ((VP >> i)&(Word)1); + err = err - ((VN >> i)&(Word)1); + ++i; + + if ((err <= (int)errthold) && ((unsigned int)err <= *return_err)) + { + *return_err = err; + return_site = site + i; + } + + /****************************may have bugs********************************/ + if(i == (int)errthold) + { + ungap_error = err; + } + /****************************may have bugs********************************/ + } + + + + + if ((*return_err) == (unsigned int)-1) + { + return return_site; + } + + + /****************************may have bugs********************************/ + if((ungap_error<=errthold) && (ungap_error == (*return_err))) + { + return_site = site + errthold; + } + /****************************may have bugs********************************/ + + + ///need to correct p_length here, since p_length might be smaller than t_length + 2* err_threashlod + p_length = t_length + 2 * errthold; + ///end_site is always correct + int end_site = return_site; + int start_site = end_site; + int back_track_site = band_length - (p_length - end_site); + + Word v_value, h_value, delta_value, min_value, current_value; + ///Word direction; ///0 is match, 1 is mismatch, 2 is up, 3 is left + Word direction = 0; ///0 is match, 1 is mismatch, 2 is up, 3 is left + i = t_length; + int path_length = 0; + current_value = *return_err; + + + int low_bound = band_length - 1; + + + while (i>0) + { + if (current_value == 0) + { + break; + } + + column_start = i << 3; + + delta_value = current_value - + ((~(matrix_bit[column_start] >> back_track_site))&err_mask); + + + if (back_track_site == 0) + { + ///HP + h_value = current_value - ((matrix_bit[column_start + 3] >> back_track_site)&err_mask); + //HN + h_value = h_value + ((matrix_bit[column_start + 4] >> back_track_site)&err_mask); + + + min_value = delta_value; + direction = 0; + + if (h_value < min_value) + { + min_value = h_value; + direction = 3; + } + + } + else if (back_track_site == low_bound) + { + v_value = current_value - ((matrix_bit[column_start + 1] >> (back_track_site - 1))&err_mask); + v_value = v_value + ((matrix_bit[column_start + 2] >> (back_track_site - 1))&err_mask); + + min_value = delta_value; + direction = 0; + + if (v_value < min_value) + { + min_value = v_value; + direction = 2; + } + + } + else + { + + h_value = current_value - ((matrix_bit[column_start + 3] >> back_track_site)&(Word)1); + + + h_value = h_value + ((matrix_bit[column_start + 4] >> back_track_site)&(Word)1); + + + v_value = current_value - ((matrix_bit[column_start + 1] >> (back_track_site - 1))&err_mask); + v_value = v_value + ((matrix_bit[column_start + 2] >> (back_track_site - 1))&err_mask); + + + min_value = delta_value; + direction = 0; + + if (v_value < min_value) + { + min_value = v_value; + direction = 2; + } + + + if (h_value < min_value) + { + min_value = h_value; + direction = 3; + } + + } + + + if (direction == 0) + { + + if (delta_value != current_value) + { + direction = 1; + } + + i--; + + start_site--; + + } + if (direction == 2)///ru guo xiang shang yi dong, bing bu huan lie + { + back_track_site--; + start_site--; + } + else if (direction == 3)///ru guo xiang zuo yi dong + { + i--; + back_track_site++; + } + + + path[path_length++] = direction; + + + current_value = min_value; + + } + + + if (i > 0) + { + memset(path + path_length, 0, i); + start_site = start_site - i; + direction = 0; + path_length = path_length + i; + } + + if (direction != 3) + { + start_site++; + } + (*return_start_site) = start_site; + (*return_path_length) = path_length; + + return return_site; +} + +////four patterns have the same p_length +inline int Reserve_Banded_BPM_4_SSE_only(char *pattern1, char *pattern2, char *pattern3, char *pattern4, int p_length, char *text, int t_length, + int* return_sites, unsigned int* return_sites_error, unsigned short errthold, __m128i* Peq_SSE) + +{ + memset(return_sites, -1, sizeof(int)* 4); + memset(return_sites_error, -1, sizeof(unsigned int)* 4); + + Word_32 Peq[256][4]; + int band_length = (errthold << 1) + 1; + + + int i; + + Word_32 tmp_Peq_1 = 1; + + + memset(Peq[(uint8_t)'A'], 0, sizeof(Word_32)* 4); + memset(Peq[(uint8_t)'C'], 0, sizeof(Word_32)* 4); + memset(Peq[(uint8_t)'G'], 0, sizeof(Word_32)* 4); + memset(Peq[(uint8_t)'T'], 0, sizeof(Word_32)* 4); + + for (i = 0; i> 1; + X = _mm_srli_epi32(D0, 1); + ///VN = X&HP; + VN = _mm_and_si128(X, HP); + ///VP = HN | ~(X | HP); + tmp_process = _mm_or_si128(X, HP); + tmp_process = _mm_andnot_si128(tmp_process, for_not); + VP = _mm_or_si128(HN, tmp_process); + + ///D0&err_mask + err_arry = _mm_and_si128(D0, err_mask); + Err_4 = _mm_add_epi32(Err_4, err_mask); + Err_4 = _mm_sub_epi32(Err_4, err_arry); + + /**************** */ + ///shi ji shang zhe ge zhi hen xiao d + cmp_result = _mm_cmpgt_epi32(Err_4, pre_end); + + ///jian zhi + if (_mm_extract_epi32(cmp_result, 0) && _mm_extract_epi32(cmp_result, 1) + && _mm_extract_epi32(cmp_result, 2) && _mm_extract_epi32(cmp_result, 3)) + return 1; + /**************** */ + + + Peq_SSE[(uint8_t)'A'] = _mm_srli_epi32(Peq_SSE[(uint8_t)'A'], 1); + Peq_SSE[(uint8_t)'T'] = _mm_srli_epi32(Peq_SSE[(uint8_t)'T'], 1); + Peq_SSE[(uint8_t)'G'] = _mm_srli_epi32(Peq_SSE[(uint8_t)'G'], 1); + Peq_SSE[(uint8_t)'C'] = _mm_srli_epi32(Peq_SSE[(uint8_t)'C'], 1); + + ++i; + ++i_bd; + + Peq_SSE[(uint8_t)pattern1[i_bd]] = _mm_or_si128(Mask1, Peq_SSE[(uint8_t)pattern1[i_bd]]); + Peq_SSE[(uint8_t)pattern2[i_bd]] = _mm_or_si128(Mask2, Peq_SSE[(uint8_t)pattern2[i_bd]]); + Peq_SSE[(uint8_t)pattern3[i_bd]] = _mm_or_si128(Mask3, Peq_SSE[(uint8_t)pattern3[i_bd]]); + Peq_SSE[(uint8_t)pattern4[i_bd]] = _mm_or_si128(Mask4, Peq_SSE[(uint8_t)pattern4[i_bd]]); + ///Peq_SSE[(uint8_t)'T'] = _mm_or_si128(Peq_SSE[(uint8_t)'T'], Peq_SSE[(uint8_t)'C']); + } + + + + ///X = Peq[text[i]] | VN; + X = _mm_or_si128(Peq_SSE[(uint8_t)text[i]], VN); + + /*************D0 = ((VP + (X&VP)) ^ VP) | X*********************/ + ///X&VP + tmp_process1 = _mm_and_si128(X, VP); + ///(VP + (X&VP)) + tmp_process = _mm_add_epi32(tmp_process1, VP); + ///((VP + (X&VP)) ^ VP) + tmp_process = _mm_xor_si128(tmp_process, VP); + ///((VP + (X&VP)) ^ VP) | X + D0 = _mm_or_si128(tmp_process, X); + /*************D0 = ((VP + (X&VP)) ^ VP) | X*********************/ + + ///HN = VP&D0; + HN = _mm_and_si128(D0, VP); + + ///HP = VN | ~(VP | D0); + tmp_process = _mm_or_si128(D0, VP); + tmp_process = _mm_andnot_si128(tmp_process, for_not); + HP = _mm_or_si128(tmp_process, VN); + + + ///X = D0 >> 1; + X = _mm_srli_epi32(D0, 1); + ///VN = X&HP; + VN = _mm_and_si128(X, HP); + ///VP = HN | ~(X | HP); + tmp_process = _mm_or_si128(X, HP); + tmp_process = _mm_andnot_si128(tmp_process, for_not); + VP = _mm_or_si128(HN, tmp_process); + + ///D0&err_mask + err_arry = _mm_and_si128(D0, err_mask); + Err_4 = _mm_add_epi32(Err_4, err_mask); + Err_4 = _mm_sub_epi32(Err_4, err_arry); + + ///shi ji shang zhe ge zhi hen xiao d + cmp_result = _mm_cmpgt_epi32(Err_4, pre_end); + + ///jian zhi + if (_mm_extract_epi32(cmp_result, 0) && _mm_extract_epi32(cmp_result, 1) + && _mm_extract_epi32(cmp_result, 2) && _mm_extract_epi32(cmp_result, 3)) + return 1; + + int site = t_length - 1; + err1 = _mm_extract_epi32(Err_4, 0); + err2 = _mm_extract_epi32(Err_4, 1); + err3 = _mm_extract_epi32(Err_4, 2); + err4 = _mm_extract_epi32(Err_4, 3); + + + if ((err1 <= (int)errthold) && ((unsigned int)err1 <= return_sites_error[0])) + { + return_sites[0] = site; + return_sites_error[0] = err1; + } + if ((err2 <= (int)errthold) && ((unsigned int)err2 <= return_sites_error[1])) + { + return_sites[1] = site; + return_sites_error[1] = err2; + } + if ((err3 <= (int)errthold) && ((unsigned int)err3 <= return_sites_error[2])) + { + return_sites[2] = site; + return_sites_error[2] = err3; + } + if ((err4 <= (int)errthold) && ((unsigned int)err4 <= return_sites_error[3])) + { + return_sites[3] = site; + return_sites_error[3] = err4; + } + + + i = 0; + + /****************************may have bugs********************************/ + unsigned int ungap_error1 = (unsigned int)-1; + unsigned int ungap_error2 = (unsigned int)-1; + unsigned int ungap_error3 = (unsigned int)-1; + unsigned int ungap_error4 = (unsigned int)-1; + /****************************may have bugs********************************/ + + + ///in most cases, p_length should be t_length + 2 * errthold + int available_i = p_length - t_length; + + while (i < available_i) + { + ///err = err + ((VP >> i)&(Word_32)1); + tmp_process = _mm_srli_epi32(VP, i); + tmp_process = _mm_and_si128(tmp_process, err_mask); + Err_4 = _mm_add_epi32(Err_4, tmp_process); + + ///err = err - ((VN >> i)&(Word_32)1); + tmp_process1 = _mm_srli_epi32(VN, i); + tmp_process1 = _mm_and_si128(tmp_process1, err_mask); + Err_4 = _mm_sub_epi32(Err_4, tmp_process1); + ++i; + + err1 = _mm_extract_epi32(Err_4, 0); + err2 = _mm_extract_epi32(Err_4, 1); + err3 = _mm_extract_epi32(Err_4, 2); + err4 = _mm_extract_epi32(Err_4, 3); + + + if ((err1 <= (int)errthold) && ((unsigned int)err1 <= return_sites_error[0])) + { + return_sites[0] = site + i; + return_sites_error[0] = err1; + } + if ((err2 <= (int)errthold) && ((unsigned int)err2 <= return_sites_error[1])) + { + return_sites[1] = site + i; + return_sites_error[1] = err2; + } + if ((err3 <= (int)errthold) && ((unsigned int)err3 <= return_sites_error[2])) + { + return_sites[2] = site + i; + return_sites_error[2] = err3; + } + if ((err4 <= (int)errthold) && ((unsigned int)err4 <= return_sites_error[3])) + { + return_sites[3] = site + i; + return_sites_error[3] = err4; + } + + /****************************may have bugs********************************/ + if(i == (int)errthold) + { + ungap_error1 = err1; + ungap_error2 = err2; + ungap_error3 = err3; + ungap_error4 = err4; + } + /****************************may have bugs********************************/ + } + + /****************************may have bugs********************************/ + if((ungap_error1<=errthold) && (ungap_error1 == return_sites_error[0])) + { + return_sites[0] = site + errthold; + } + + if((ungap_error2<=errthold) && (ungap_error2 == return_sites_error[1])) + { + return_sites[1] = site + errthold; + } + + if((ungap_error3<=errthold) && (ungap_error3 == return_sites_error[2])) + { + return_sites[2] = site + errthold; + } + + if((ungap_error4<=errthold) && (ungap_error4 == return_sites_error[3])) + { + return_sites[3] = site + errthold; + } + /****************************may have bugs********************************/ + + return 1; +} + + +// void move_trace_gap(uint16_t *trace, int32_t trace_n, int32_t trace_i, +// char *pstr, int32_t pi, char *tstr, int32_t ti, int32_t *err) +// { +// uint16_t c = trace[trace_i]>>14, l = (trace[trace_i]<<2)>>2; +// if(c != 3 && c != 2) return; +// trace_i--; +// if(c == 3) pi--; +// else if(c == 2) ti--; + + +// if() + +// } + +// void adjust_trace(uint16_t *trace, int32_t *trace_n, int32_t *p_beg, int32_t *p_end, int32_t *err, char *pstr, char *tstr) +// { +// if((*err) == 0) return; +// int32_t i, pi, ti; uint16_t c, l; +// for (i = 0; i < (*trace_n) && (trace[i]>>14) == 1; i++) { +// trace[i] <<= 2; trace[i] >>= 2; trace[i] += (((uint16_t)3)<<14); +// l = (trace[i]<<2)>>2; (*p_beg) += l; +// } +// for (i = (*trace_n) - 1; i >= 0 && (trace[i]>>14) == 1; i--) { +// trace[i] <<= 2; trace[i] >>= 2; trace[i] += (((uint16_t)3)<<14); +// l = (trace[i]<<2)>>2; (*p_end) -= l; +// } + +// i = 0; pi = (*p_beg); ti = 0; +// for (i = 0; i < (*trace_n); i++) { +// c = trace[i]>>14; l = (trace[i]<<2)>>2; +// if(c == 0 || c == 1) { +// pi += l; ti += l; +// } else if(c == 2) { +// // move_trace_gap(trace, *trace_n, i, pstr, pi, tstr, ti, err); +// pi += l; +// } else if(c == 3) { +// // move_trace_gap(trace, *trace_n, i, pstr, pi, tstr, ti, err); +// ti += l; +// } +// } +// } + +inline int32_t ungap_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t know_err, int32_t know_end, +int32_t *r_err, int32_t *r_beg, asg16_v *cigar, int32_t *cigar_l) +{ + int32_t cn = cigar->n, pk, tk, e, l; + (*r_err) = (*r_beg) = INT32_MAX; (*cigar_l) = 0; + if(know_err < 0 || know_end < 0) return -1; + if(know_err == 0) { + push_trace(cigar, EAC_M, tn); + (*r_err) = know_err; (*r_beg) = know_end + 1 - tn; (*cigar_l) = cigar->n - cn; + return know_end; + } + + pk = know_end+1-tn; tk = 0; e = 0; + for (l = 0; tk < tn; tk++, pk++) { + if(pstr[pk]!=tstr[tk]) { + e++; if(e > know_err) break; + if(tk > l) push_trace(cigar, EAC_M, tk-l); + push_trace(cigar, MIS_M, 1); l = tk + 1; + } + } + if(tk == tn) { + if(tk > l) push_trace(cigar, EAC_M, tk-l); + (*r_err) = know_err; (*r_beg) = know_end + 1 - tn; (*cigar_l) = cigar->n - cn; + return know_end; + } + + cigar->n = cn; + return -1; +} + + +// ///p_length might be samller than t_length + 2 * errthold +inline int32_t ed_band_cal_semi_trace(char *pstr, int32_t pn, char *tstr, int32_t tn, int32_t thre, + int32_t know_err, int32_t know_end, int32_t *r_err, int32_t *r_beg, Word *buf, asg16_v *cigar, int32_t *cigar_l) { + int32_t cn = cigar->n; (*r_err) = (*r_beg) = INT32_MAX; (*cigar_l) = 0; + Word Peq[5] = {0}, mm = (Word)1, VP = 0, VN = 0, X = 0, D0 = 0, HN = 0, HP = 0, i_col, i_col_dux; + int32_t bd = (thre<<1)+1, i, err = 0, i_bd = (thre<<1), last_high = (thre<<1), tn0 = tn - 1; + int32_t cut = thre+last_high; ///kv_resize(uint16_t, *cigar, cigar->n+(uint32_t)know_err+2);//pre-alloc + + if(ungap_trace(pstr, pn, tstr, tn, know_err, know_end, r_err, r_beg, cigar, cigar_l) >= 0) { + return know_end; + } + + for (i = 0; i < bd; i++) { + Peq[seq_nt4_table[(uint8_t)pstr[i]]] |= mm; mm <<= 1; + } + Peq[4] = 0; + ///should make Peq[4] = 0 if N is always an error + i = i_col = 0; mm = ((Word)1 << (thre<<1));///for the incoming char/last char + + while (i < tn0) { + X = Peq[seq_nt4_table[(uint8_t)tstr[i]]] | VN; + + D0 = ((VP + (X&VP)) ^ VP) | X; + + HN = VP&D0; + HP = VN | ~(VP | D0); + + X = D0 >> 1; + VN = X&HP; + VP = HN | ~(X | HP); + + if (!(D0&(1ULL))) { + ++err; + if (err>cut) return -1; + } + + Peq[0] >>= 1; Peq[1] >>= 1; Peq[2] >>= 1; Peq[3] >>= 1; ///Peq[4] >>= 1; + + ++i; ++i_bd; + Peq[seq_nt4_table[(uint8_t)pstr[i_bd]]] |= mm; Peq[4] = 0; + + buf[i_col++] = D0; buf[i_col++] = VP; buf[i_col++] = VN; buf[i_col++] = HP; buf[i_col++] = HN; + } + + X = Peq[seq_nt4_table[(uint8_t)tstr[i]]] | VN; + D0 = ((VP + (X&VP)) ^ VP) | X; + HN = VP&D0; + HP = VN | ~(VP | D0); + X = D0 >> 1; + VN = X&HP; + VP = HN | ~(X | HP); + if (!(D0&(1ULL))) { + ++err; + if (err>cut) return -1; + } + + buf[i_col++] = D0; buf[i_col++] = VP; buf[i_col++] = VN; buf[i_col++] = HP; buf[i_col++] = HN; + + i_col_dux = i_col/tn; + + int32_t site = tn - 1, end = -1;///up bound + ///in most cases, ai = (thre<<1) + int32_t ai = pn - tn, uge = INT32_MAX; + if ((err <= thre) && (err<=(*r_err))) { + *r_err = err; end = site; + } + i = 0; + + while (i < ai) { + err += ((VP >> i)&(1ULL)); err -= ((VN >> i)&(1ULL)); ++i; + if ((err <= thre) && (err <= (*r_err))) { + *r_err = err; end = site + i; + } + if(i == thre) uge = err; + } + if((uge<=thre) && (uge == (*r_err))) end = site + thre; + if ((*r_err) > thre) return end; + + + ///need to correct pn here, since pn might be smaller than tn + 2* thre + pn = tn + (thre<<1); + int32_t beg = end, back_track_site = bd - (pn - end); + + Word v_value, h_value, delta_value, min_value, current_value; + ///Word direction; ///0 is match, 1 is mismatch, 2 is up, 3 is left + Word direction = 0, *ba, pd, pdl; ///0 is match, 1 is mismatch, 2 is up, 3 is left + i = tn; pd = (Word)-1; pdl = 0; + current_value = *r_err; + int32_t low_bound = bd - 1; + + while (i > 0) { + if (current_value == 0) break; + ba = buf + ((i*i_col_dux) - i_col_dux); + delta_value = current_value - ((~(ba[0]>>back_track_site))&(1ULL)); + + if (back_track_site == 0) { + ///HP + h_value = current_value - ((ba[3] >> back_track_site)&(1ULL)); + //HN + h_value = h_value + ((ba[4] >> back_track_site)&1ULL); + min_value = delta_value; direction = 0; + if (h_value < min_value) { + min_value = h_value; + direction = 3; + } + } else if (back_track_site == low_bound) { + v_value = current_value - ((ba[1]>>(back_track_site-1))&(1ULL)); + v_value = v_value + ((ba[2]>>(back_track_site-1))&(1ULL)); + + min_value = delta_value; direction = 0; + if (v_value < min_value) { + min_value = v_value; + direction = 2; + } + } + else { + h_value = current_value-((ba[3]>>back_track_site)&(1ULL)); + h_value = h_value+((ba[4]>>back_track_site)&(1ULL)); + + v_value = current_value - ((ba[1]>>(back_track_site-1))&(1ULL)); + v_value = v_value + ((ba[2]>>(back_track_site-1))&(1ULL)); + + min_value = delta_value; direction = 0; + if (v_value < min_value) { + min_value = v_value; + direction = 2; + } + + if (h_value < min_value) { + min_value = h_value; + direction = 3; + } + } + + + if (direction == 0) { + if (delta_value != current_value) { + direction = 1; + } + i--; beg--; + } + if (direction == 2) {///ru guo xiang shang yi dong, bing bu huan lie + back_track_site--; beg--; + } + else if (direction == 3) {///ru guo xiang zuo yi dong + i--; + back_track_site++; + } + + if(direction != pd) { + if(pdl > 0) push_trace(cigar, pd, pdl); + pd = direction; pdl = 1; + } else { + pdl++; + } + // path[path_length++] = direction; + current_value = min_value; + } + + + if (i > 0) { + direction = 0; beg -= i; + if(direction != pd) { + if(pdl > 0) push_trace(cigar, pd, pdl); + pd = direction; pdl = i; + } else { + pdl += i; + } + } + + if(pdl > 0) push_trace(cigar, pd, pdl); + if (direction != 3) beg++; + + uint16_t *trac = cigar->a + cn, tt; int32_t trac_n = cigar->n - cn; ai = trac_n>>1; + for (i = 0; i < ai; i++) { + tt = trac[i]; trac[i] = trac[trac_n-i-1]; trac[trac_n-i-1] = tt; + } + (*cigar_l) = cigar->n - cn; + + (*r_beg) = beg; (*cigar_l) = cigar->n - cn; + return end; +} + + +#endif diff --git a/Makefile b/Makefile index f3714c2..94c037c 100644 --- a/Makefile +++ b/Makefile @@ -1,83 +1,83 @@ -CXX= g++ -CC= gcc -CXXFLAGS= -g -O3 -msse4.2 -mpopcnt -fomit-frame-pointer -Wall -CFLAGS= $(CXXFLAGS) -CPPFLAGS= -INCLUDES= -OBJS= CommandLines.o Process_Read.o Assembly.o Hash_Table.o \ - POA.o Correct.o Levenshtein_distance.o Overlaps.o Trio.o kthread.o Purge_Dups.o \ - htab.o hist.o sketch.o anchor.o extract.o sys.o hic.o rcut.o horder.o ecovlp.o\ - tovlp.o inter.o kalloc.o gfa_ut.o gchain_map.o -EXE= hifiasm -LIBS= -lz -lpthread -lm - -ifneq ($(asan),) - CXXFLAGS+=-fsanitize=address - LIBS+=-fsanitize=address -endif - -.SUFFIXES:.cpp .c .o -.PHONY:all clean depend - -.cpp.o: - $(CXX) -c $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $< -o $@ - -.c.o: - $(CC) -c $(CFLAGS) $(CPPFLAGS) $(INCLUDES) $< -o $@ - -all:$(EXE) - -$(EXE):$(OBJS) main.o - $(CXX) $(CXXFLAGS) $^ -o $@ $(LIBS) - -clean: - rm -fr gmon.out *.o a.out $(EXE) *~ *.a *.dSYM - -depend: - (LC_ALL=C; export LC_ALL; makedepend -Y -- $(CPPFLAGS) $(DFLAGS) -- *.cpp) - -# DO NOT DELETE - -Assembly.o: Assembly.h CommandLines.h Process_Read.h Overlaps.h kvec.h kdq.h -Assembly.o: Hash_Table.h htab.h POA.h Correct.h Levenshtein_distance.h -Assembly.o: kthread.h ecovlp.h -CommandLines.o: CommandLines.h ketopt.h -Correct.o: Correct.h Hash_Table.h htab.h Process_Read.h Overlaps.h kvec.h -Correct.o: kdq.h CommandLines.h Levenshtein_distance.h POA.h Assembly.h -Correct.o: ksort.h -Hash_Table.o: Hash_Table.h htab.h Process_Read.h Overlaps.h kvec.h kdq.h -Hash_Table.o: CommandLines.h ksort.h -Levenshtein_distance.o: Levenshtein_distance.h -Output.o: Output.h CommandLines.h -Overlaps.o: Overlaps.h kvec.h kdq.h ksort.h Process_Read.h CommandLines.h -Overlaps.o: Hash_Table.h htab.h Correct.h Levenshtein_distance.h POA.h -Overlaps.o: Purge_Dups.h -POA.o: POA.h Hash_Table.h htab.h Process_Read.h Overlaps.h kvec.h kdq.h -POA.o: CommandLines.h Correct.h Levenshtein_distance.h -Process_Read.o: Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h -Purge_Dups.o: ksort.h Purge_Dups.h kvec.h kdq.h Overlaps.h Hash_Table.h -Purge_Dups.o: htab.h Process_Read.h CommandLines.h Correct.h -Purge_Dups.o: Levenshtein_distance.h POA.h kthread.h -ecovlp.o: Hash_Table.h Process_Read.h Overlaps.h kthread.h -Trio.o: khashl.h kthread.h kseq.h Process_Read.h Overlaps.h kvec.h kdq.h -Trio.o: CommandLines.h htab.h -anchor.o: htab.h Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h -anchor.o: ksort.h Hash_Table.h -extract.o: Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h khashl.h -extract.o: kseq.h -hist.o: htab.h Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h -htab.o: kthread.h khashl.h kseq.h ksort.h htab.h Process_Read.h Overlaps.h -htab.o: kvec.h kdq.h CommandLines.h -kthread.o: kthread.h -main.o: CommandLines.h Process_Read.h Overlaps.h kvec.h kdq.h Assembly.h -main.o: Levenshtein_distance.h htab.h -sketch.o: kvec.h htab.h Process_Read.h Overlaps.h kdq.h CommandLines.h -sys.o: htab.h Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h -hic.o: hic.h -rcut.o: rcut.h -horder.o: horder.h -tovlp.o: tovlp.h -inter.o: inter.h Process_Read.h -kalloc.o: kalloc.h -gfa_ut.o: Overlaps.h +CXX= g++ +CC= gcc +CXXFLAGS= -g -O3 -msse4.2 -mpopcnt -fomit-frame-pointer -Wall +CFLAGS= $(CXXFLAGS) +CPPFLAGS= +INCLUDES= +OBJS= CommandLines.o Process_Read.o Assembly.o Hash_Table.o \ + POA.o Correct.o Levenshtein_distance.o Overlaps.o Trio.o kthread.o Purge_Dups.o \ + htab.o hist.o sketch.o anchor.o extract.o sys.o hic.o rcut.o horder.o ecovlp.o\ + tovlp.o inter.o kalloc.o gfa_ut.o gchain_map.o +EXE= hifiasm +LIBS= -lz -lpthread -lm + +ifneq ($(asan),) + CXXFLAGS+=-fsanitize=address + LIBS+=-fsanitize=address +endif + +.SUFFIXES:.cpp .c .o +.PHONY:all clean depend + +.cpp.o: + $(CXX) -c $(CXXFLAGS) $(CPPFLAGS) $(INCLUDES) $< -o $@ + +.c.o: + $(CC) -c $(CFLAGS) $(CPPFLAGS) $(INCLUDES) $< -o $@ + +all:$(EXE) + +$(EXE):$(OBJS) main.o + $(CXX) $(CXXFLAGS) $^ -o $@ $(LIBS) + +clean: + rm -fr gmon.out *.o a.out $(EXE) *~ *.a *.dSYM + +depend: + (LC_ALL=C; export LC_ALL; makedepend -Y -- $(CPPFLAGS) $(DFLAGS) -- *.cpp) + +# DO NOT DELETE + +Assembly.o: Assembly.h CommandLines.h Process_Read.h Overlaps.h kvec.h kdq.h +Assembly.o: Hash_Table.h htab.h POA.h Correct.h Levenshtein_distance.h +Assembly.o: kthread.h ecovlp.h +CommandLines.o: CommandLines.h ketopt.h +Correct.o: Correct.h Hash_Table.h htab.h Process_Read.h Overlaps.h kvec.h +Correct.o: kdq.h CommandLines.h Levenshtein_distance.h POA.h Assembly.h +Correct.o: ksort.h +Hash_Table.o: Hash_Table.h htab.h Process_Read.h Overlaps.h kvec.h kdq.h +Hash_Table.o: CommandLines.h ksort.h +Levenshtein_distance.o: Levenshtein_distance.h +Output.o: Output.h CommandLines.h +Overlaps.o: Overlaps.h kvec.h kdq.h ksort.h Process_Read.h CommandLines.h +Overlaps.o: Hash_Table.h htab.h Correct.h Levenshtein_distance.h POA.h +Overlaps.o: Purge_Dups.h +POA.o: POA.h Hash_Table.h htab.h Process_Read.h Overlaps.h kvec.h kdq.h +POA.o: CommandLines.h Correct.h Levenshtein_distance.h +Process_Read.o: Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h +Purge_Dups.o: ksort.h Purge_Dups.h kvec.h kdq.h Overlaps.h Hash_Table.h +Purge_Dups.o: htab.h Process_Read.h CommandLines.h Correct.h +Purge_Dups.o: Levenshtein_distance.h POA.h kthread.h +ecovlp.o: Hash_Table.h Process_Read.h Overlaps.h kthread.h +Trio.o: khashl.h kthread.h kseq.h Process_Read.h Overlaps.h kvec.h kdq.h +Trio.o: CommandLines.h htab.h +anchor.o: htab.h Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h +anchor.o: ksort.h Hash_Table.h +extract.o: Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h khashl.h +extract.o: kseq.h +hist.o: htab.h Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h +htab.o: kthread.h khashl.h kseq.h ksort.h htab.h Process_Read.h Overlaps.h +htab.o: kvec.h kdq.h CommandLines.h +kthread.o: kthread.h +main.o: CommandLines.h Process_Read.h Overlaps.h kvec.h kdq.h Assembly.h +main.o: Levenshtein_distance.h htab.h +sketch.o: kvec.h htab.h Process_Read.h Overlaps.h kdq.h CommandLines.h +sys.o: htab.h Process_Read.h Overlaps.h kvec.h kdq.h CommandLines.h +hic.o: hic.h +rcut.o: rcut.h +horder.o: horder.h +tovlp.o: tovlp.h +inter.o: inter.h Process_Read.h +kalloc.o: kalloc.h +gfa_ut.o: Overlaps.h gchain_map.o: gchain_map.h \ No newline at end of file diff --git a/Output.cpp b/Output.cpp index c558a8d..b2b7caa 100644 --- a/Output.cpp +++ b/Output.cpp @@ -1,235 +1,235 @@ -#include "Output.h" -#include "CommandLines.h" -#include - -pthread_mutex_t o_queueMutex; -pthread_cond_t o_flushCond; -pthread_cond_t o_stallCond; -pthread_mutex_t o_doneMutex; - - -Output_buffer buffer_out; -Output_buffer_sub_block tmp_buffer_sub_block; - -void init_buffer_sub_block(Output_buffer_sub_block* sub_block) -{ - sub_block->length = 0; - sub_block->size = SUB_BLOCK_INIT_SIZE; - sub_block->buffer = (char*)malloc(sub_block->size); -} - -void destory_buffer_sub_block(Output_buffer_sub_block* sub_block) -{ - free(sub_block->buffer); -} - -void destory_output_buffer() -{ - for (int i = 0; i < buffer_out.sub_block_size; i++) - { - destory_buffer_sub_block(&(buffer_out.sub_buffer[i])); - } - - free(buffer_out.sub_buffer); -} - -void init_output_buffer(int thread_number) -{ - buffer_out.sub_block_size = OUTPUT_BUFFER_SIZE * thread_number; - buffer_out.sub_block_number = 0; - - buffer_out.sub_buffer = (Output_buffer_sub_block*)malloc(sizeof(Output_buffer_sub_block)*buffer_out.sub_block_size); - - - - for (int i = 0; i < buffer_out.sub_block_size; i++) - { - init_buffer_sub_block(&(buffer_out.sub_buffer[i])); - } - - buffer_out.all_buffer_end = 0; -} - -inline int if_empty_buffer() -{ - - if (buffer_out.sub_block_number == 0) - { - return 1; - } - else - { - return 0; - } -} - - -inline int if_full_buffer() -{ - - if (buffer_out.sub_block_number >= buffer_out.sub_block_size) - { - return 1; - } - else - { - return 0; - } -} - -inline void pop_single_buffer(Output_buffer_sub_block* curr_sub_block) -{ - buffer_out.sub_block_number--; - char *k; - k = buffer_out.sub_buffer[buffer_out.sub_block_number].buffer; - buffer_out.sub_buffer[buffer_out.sub_block_number].buffer = curr_sub_block->buffer; - curr_sub_block->buffer = k; - - - long long tmp_size; - tmp_size = curr_sub_block->size; - curr_sub_block->size = buffer_out.sub_buffer[buffer_out.sub_block_number].size; - buffer_out.sub_buffer[buffer_out.sub_block_number].size = tmp_size; - - - curr_sub_block->length = buffer_out.sub_buffer[buffer_out.sub_block_number].length; - buffer_out.sub_buffer[buffer_out.sub_block_number].length = 0; -} - - - -void add_segment_to_sub_buffer(Output_buffer_sub_block* current_sub_buffer, char* seg, long long segLen) -{ - if(current_sub_buffer->length + segLen + 2 > current_sub_buffer->size) - { - current_sub_buffer->size = current_sub_buffer->length + segLen + 2; - current_sub_buffer->buffer = (char*)realloc(current_sub_buffer->buffer, current_sub_buffer->size); - } - - memcpy(current_sub_buffer->buffer + current_sub_buffer->length, seg, segLen); - current_sub_buffer->length += segLen; - current_sub_buffer->buffer[current_sub_buffer->length] = '\0'; -} - - -void add_base_to_sub_buffer(Output_buffer_sub_block* current_sub_buffer, char base) -{ - if(current_sub_buffer->length + 2 > current_sub_buffer->size) - { - current_sub_buffer->size = current_sub_buffer->length + 2; - current_sub_buffer->buffer = (char*)realloc(current_sub_buffer->buffer, current_sub_buffer->size); - } - - current_sub_buffer->buffer[current_sub_buffer->length] = base; - current_sub_buffer->length++; - current_sub_buffer->buffer[current_sub_buffer->length] = '\0'; - -} - - -inline void push_single_buffer(Output_buffer_sub_block* curr_sub_block) -{ - - char *k; - k = buffer_out.sub_buffer[buffer_out.sub_block_number].buffer; - buffer_out.sub_buffer[buffer_out.sub_block_number].buffer = curr_sub_block->buffer; - curr_sub_block->buffer = k; - - long long tmp_size; - tmp_size = curr_sub_block->size; - curr_sub_block->size = buffer_out.sub_buffer[buffer_out.sub_block_number].size; - buffer_out.sub_buffer[buffer_out.sub_block_number].size = tmp_size; - - buffer_out.sub_buffer[buffer_out.sub_block_number].length = curr_sub_block->length; - curr_sub_block->length = 0; - - buffer_out.sub_block_number++; -} - - -void* pop_buffer(void*) -{ - - FILE* output_file = fopen(asm_opt.output_file_name, "w"); - - init_buffer_sub_block(&tmp_buffer_sub_block); - - - - while (buffer_out.all_buffer_end < asm_opt.thread_num) - { - - pthread_mutex_lock(&o_queueMutex); - - while (if_empty_buffer() && (buffer_out.all_buffer_end < asm_opt.thread_num)) - { - pthread_cond_signal(&o_stallCond); - pthread_cond_wait(&o_flushCond, &o_queueMutex); - } - - if (!if_empty_buffer()) - { - pop_single_buffer(&tmp_buffer_sub_block); - } - - pthread_cond_signal(&o_stallCond); - pthread_mutex_unlock(&o_queueMutex); - - - - if (tmp_buffer_sub_block.length != 0) - { - fprintf(output_file, "%s", tmp_buffer_sub_block.buffer); - } - - } - - - while (buffer_out.sub_block_number>0) - { - buffer_out.sub_block_number--; - fprintf(output_file, "%s", buffer_out.sub_buffer[buffer_out.sub_block_number].buffer); - } - - - destory_buffer_sub_block(&tmp_buffer_sub_block); - - fclose(output_file); - - return NULL; -} - - -void push_results_to_buffer(Output_buffer_sub_block* sub_block) -{ - - pthread_mutex_lock(&o_queueMutex); - - while (if_full_buffer()) - { - pthread_cond_signal(&o_flushCond); - pthread_cond_wait(&o_stallCond, &o_queueMutex); - } - - push_single_buffer(sub_block); - pthread_cond_signal(&o_flushCond); - pthread_mutex_unlock(&o_queueMutex); - -} - - - -void finish_output_buffer() -{ - - pthread_mutex_lock(&o_doneMutex); - buffer_out.all_buffer_end++; - - - if (buffer_out.all_buffer_end == asm_opt.thread_num) - { - pthread_cond_signal(&o_flushCond); - } - - pthread_mutex_unlock(&o_doneMutex); +#include "Output.h" +#include "CommandLines.h" +#include + +pthread_mutex_t o_queueMutex; +pthread_cond_t o_flushCond; +pthread_cond_t o_stallCond; +pthread_mutex_t o_doneMutex; + + +Output_buffer buffer_out; +Output_buffer_sub_block tmp_buffer_sub_block; + +void init_buffer_sub_block(Output_buffer_sub_block* sub_block) +{ + sub_block->length = 0; + sub_block->size = SUB_BLOCK_INIT_SIZE; + sub_block->buffer = (char*)malloc(sub_block->size); +} + +void destory_buffer_sub_block(Output_buffer_sub_block* sub_block) +{ + free(sub_block->buffer); +} + +void destory_output_buffer() +{ + for (int i = 0; i < buffer_out.sub_block_size; i++) + { + destory_buffer_sub_block(&(buffer_out.sub_buffer[i])); + } + + free(buffer_out.sub_buffer); +} + +void init_output_buffer(int thread_number) +{ + buffer_out.sub_block_size = OUTPUT_BUFFER_SIZE * thread_number; + buffer_out.sub_block_number = 0; + + buffer_out.sub_buffer = (Output_buffer_sub_block*)malloc(sizeof(Output_buffer_sub_block)*buffer_out.sub_block_size); + + + + for (int i = 0; i < buffer_out.sub_block_size; i++) + { + init_buffer_sub_block(&(buffer_out.sub_buffer[i])); + } + + buffer_out.all_buffer_end = 0; +} + +inline int if_empty_buffer() +{ + + if (buffer_out.sub_block_number == 0) + { + return 1; + } + else + { + return 0; + } +} + + +inline int if_full_buffer() +{ + + if (buffer_out.sub_block_number >= buffer_out.sub_block_size) + { + return 1; + } + else + { + return 0; + } +} + +inline void pop_single_buffer(Output_buffer_sub_block* curr_sub_block) +{ + buffer_out.sub_block_number--; + char *k; + k = buffer_out.sub_buffer[buffer_out.sub_block_number].buffer; + buffer_out.sub_buffer[buffer_out.sub_block_number].buffer = curr_sub_block->buffer; + curr_sub_block->buffer = k; + + + long long tmp_size; + tmp_size = curr_sub_block->size; + curr_sub_block->size = buffer_out.sub_buffer[buffer_out.sub_block_number].size; + buffer_out.sub_buffer[buffer_out.sub_block_number].size = tmp_size; + + + curr_sub_block->length = buffer_out.sub_buffer[buffer_out.sub_block_number].length; + buffer_out.sub_buffer[buffer_out.sub_block_number].length = 0; +} + + + +void add_segment_to_sub_buffer(Output_buffer_sub_block* current_sub_buffer, char* seg, long long segLen) +{ + if(current_sub_buffer->length + segLen + 2 > current_sub_buffer->size) + { + current_sub_buffer->size = current_sub_buffer->length + segLen + 2; + current_sub_buffer->buffer = (char*)realloc(current_sub_buffer->buffer, current_sub_buffer->size); + } + + memcpy(current_sub_buffer->buffer + current_sub_buffer->length, seg, segLen); + current_sub_buffer->length += segLen; + current_sub_buffer->buffer[current_sub_buffer->length] = '\0'; +} + + +void add_base_to_sub_buffer(Output_buffer_sub_block* current_sub_buffer, char base) +{ + if(current_sub_buffer->length + 2 > current_sub_buffer->size) + { + current_sub_buffer->size = current_sub_buffer->length + 2; + current_sub_buffer->buffer = (char*)realloc(current_sub_buffer->buffer, current_sub_buffer->size); + } + + current_sub_buffer->buffer[current_sub_buffer->length] = base; + current_sub_buffer->length++; + current_sub_buffer->buffer[current_sub_buffer->length] = '\0'; + +} + + +inline void push_single_buffer(Output_buffer_sub_block* curr_sub_block) +{ + + char *k; + k = buffer_out.sub_buffer[buffer_out.sub_block_number].buffer; + buffer_out.sub_buffer[buffer_out.sub_block_number].buffer = curr_sub_block->buffer; + curr_sub_block->buffer = k; + + long long tmp_size; + tmp_size = curr_sub_block->size; + curr_sub_block->size = buffer_out.sub_buffer[buffer_out.sub_block_number].size; + buffer_out.sub_buffer[buffer_out.sub_block_number].size = tmp_size; + + buffer_out.sub_buffer[buffer_out.sub_block_number].length = curr_sub_block->length; + curr_sub_block->length = 0; + + buffer_out.sub_block_number++; +} + + +void* pop_buffer(void*) +{ + + FILE* output_file = fopen(asm_opt.output_file_name, "w"); + + init_buffer_sub_block(&tmp_buffer_sub_block); + + + + while (buffer_out.all_buffer_end < asm_opt.thread_num) + { + + pthread_mutex_lock(&o_queueMutex); + + while (if_empty_buffer() && (buffer_out.all_buffer_end < asm_opt.thread_num)) + { + pthread_cond_signal(&o_stallCond); + pthread_cond_wait(&o_flushCond, &o_queueMutex); + } + + if (!if_empty_buffer()) + { + pop_single_buffer(&tmp_buffer_sub_block); + } + + pthread_cond_signal(&o_stallCond); + pthread_mutex_unlock(&o_queueMutex); + + + + if (tmp_buffer_sub_block.length != 0) + { + fprintf(output_file, "%s", tmp_buffer_sub_block.buffer); + } + + } + + + while (buffer_out.sub_block_number>0) + { + buffer_out.sub_block_number--; + fprintf(output_file, "%s", buffer_out.sub_buffer[buffer_out.sub_block_number].buffer); + } + + + destory_buffer_sub_block(&tmp_buffer_sub_block); + + fclose(output_file); + + return NULL; +} + + +void push_results_to_buffer(Output_buffer_sub_block* sub_block) +{ + + pthread_mutex_lock(&o_queueMutex); + + while (if_full_buffer()) + { + pthread_cond_signal(&o_flushCond); + pthread_cond_wait(&o_stallCond, &o_queueMutex); + } + + push_single_buffer(sub_block); + pthread_cond_signal(&o_flushCond); + pthread_mutex_unlock(&o_queueMutex); + +} + + + +void finish_output_buffer() +{ + + pthread_mutex_lock(&o_doneMutex); + buffer_out.all_buffer_end++; + + + if (buffer_out.all_buffer_end == asm_opt.thread_num) + { + pthread_cond_signal(&o_flushCond); + } + + pthread_mutex_unlock(&o_doneMutex); } \ No newline at end of file diff --git a/Output.h b/Output.h index 46271b3..730d291 100644 --- a/Output.h +++ b/Output.h @@ -1,38 +1,38 @@ -#ifndef __OUTPUT__ -#define __OUTPUT__ - -#define __STDC_LIMIT_MACROS -#include -#include -#include -#include - -typedef struct -{ - char* buffer; - long long size; - long long length; -} Output_buffer_sub_block; - -typedef struct Output_buffer -{ - Output_buffer_sub_block* sub_buffer; - long long sub_block_size; - long long sub_block_number; - int all_buffer_end; -} Output_buffer; - -#define OUTPUT_BUFFER_SIZE 100 -#define SUB_BLOCK_INIT_SIZE 10000 - -void init_buffer_sub_block(Output_buffer_sub_block* sub_block); -void* pop_buffer(void*); -void add_segment_to_sub_buffer(Output_buffer_sub_block* current_sub_buffer, char* seg, long long segLen); -void add_base_to_sub_buffer(Output_buffer_sub_block* current_sub_buffer, char base); -void push_results_to_buffer(Output_buffer_sub_block* sub_block); -void finish_output_buffer(); -void destory_buffer_sub_block(Output_buffer_sub_block* sub_block); -void destory_output_buffer(); -void init_output_buffer(int thread_number); - -#endif +#ifndef __OUTPUT__ +#define __OUTPUT__ + +#define __STDC_LIMIT_MACROS +#include +#include +#include +#include + +typedef struct +{ + char* buffer; + long long size; + long long length; +} Output_buffer_sub_block; + +typedef struct Output_buffer +{ + Output_buffer_sub_block* sub_buffer; + long long sub_block_size; + long long sub_block_number; + int all_buffer_end; +} Output_buffer; + +#define OUTPUT_BUFFER_SIZE 100 +#define SUB_BLOCK_INIT_SIZE 10000 + +void init_buffer_sub_block(Output_buffer_sub_block* sub_block); +void* pop_buffer(void*); +void add_segment_to_sub_buffer(Output_buffer_sub_block* current_sub_buffer, char* seg, long long segLen); +void add_base_to_sub_buffer(Output_buffer_sub_block* current_sub_buffer, char base); +void push_results_to_buffer(Output_buffer_sub_block* sub_block); +void finish_output_buffer(); +void destory_buffer_sub_block(Output_buffer_sub_block* sub_block); +void destory_output_buffer(); +void init_output_buffer(int thread_number); + +#endif diff --git a/Overlaps.cpp b/Overlaps.cpp index 5d33191..3d5716a 100644 --- a/Overlaps.cpp +++ b/Overlaps.cpp @@ -1,39737 +1,40262 @@ -#include -#include -#define __STDC_LIMIT_MACROS -#include -#include "Overlaps.h" -#include "ksort.h" -#include "Process_Read.h" -#include "CommandLines.h" -#include "Hash_Table.h" -#include "Correct.h" -#include "Purge_Dups.h" -#include "hic.h" -#include "kthread.h" -#include "tovlp.h" -#include "Assembly.h" -#include "rcut.h" -#include "horder.h" -#include "inter.h" -#include "gfa_ut.h" -#include "assert.h" -#include "khash.h" -#include "ecovlp.h" - -KHASH_SET_INIT_INT64(64) - -uint32_t debug_purge_dup = 0; - -KDQ_INIT(uint64_t) -KDQ_INIT(uint32_t) - -#define ma_hit_key_tn(a) ((a).tn) -KRADIX_SORT_INIT(hit_tn, ma_hit_t, ma_hit_key_tn, member_size(ma_hit_t, tn)) - -#define ma_hit_key_qns(a) ((a).qns) -KRADIX_SORT_INIT(hit_qns, ma_hit_t, ma_hit_key_qns, member_size(ma_hit_t, qns)) - - -#define asg_arc_key(a) ((a).ul) -KRADIX_SORT_INIT(asg, asg_arc_t, asg_arc_key, 8) - -#define generic_key(x) (x) -KRADIX_SORT_INIT(arch64, uint64_t, generic_key, 8) - -#define generic_key(x) (x) -KRADIX_SORT_INIT(arch32, uint32_t, generic_key, 4) - -///#define Hap_Align_key(a) ((((uint64_t)((a).is_color))<<63)|(((uint64_t)((a).t_id))<<32)|((uint64_t)((a).q_pos))) -///#define Hap_Align_key(a) ((((uint64_t)((a).is_color))<<32)|(((uint64_t)((a).t_id))<<33)|((uint64_t)((a).q_pos))) -#define Hap_Align_key(a) ((((uint64_t)((a).t_id))<<33)|((uint64_t)((a).q_pos))) -KRADIX_SORT_INIT(Hap_Align_sort, Hap_Align, Hap_Align_key, 8) - -#define u_trans_key(a) (((uint64_t)((a).qn)<<32) | ((uint64_t)((a).tn)<<1) | ((uint64_t)((a).rev))) -KRADIX_SORT_INIT(u_trans, u_trans_t, u_trans_key, 8) - -#define u_trans_qs_key(a) ((a).qs) -KRADIX_SORT_INIT(u_trans_qs, u_trans_t, u_trans_qs_key, member_size(u_trans_t, qs)) - -#define u_trans_ts_key(a) ((a).ts) -KRADIX_SORT_INIT(u_trans_ts, u_trans_t, u_trans_ts_key, member_size(u_trans_t, ts)) - -#define ha_mzl_t_key(p) ((p).x) -KRADIX_SORT_INIT(ha_mzl_t_srt1, ha_mzl_t, ha_mzl_t_key, member_size(ha_mzl_t, x)) - -#define Uc_beg(z) ((uint32_t)((z).a[0]>>32)) -#define Uc_end(z) ((uint32_t)((z).a[(z).n-1]>>32)^1) - -#define PHASE_SEP 64 -#define PHASE_SEF 2 -#define PHASE_SEP_RATE 0.04 -#define PHASE_MISS_LEN 1000000 -#define PHASE_MISS_N 8 -// #define PHASE_MISS_SLEN 500000 -// #define PHASE_MISS_SN 24 - -KSORT_INIT_GENERIC(uint32_t) - -void reduce_hamming_error_adv(ma_ug_t *iug, asg_t *sg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -int max_hang, int min_ovlp, long long gap_fuzz, R_to_U *ru, bubble_type* bub); -void print_vw_edge(asg_t *sg, uint32_t vid, uint32_t wid, const char *cmd); -void output_trio_graph_joint(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, -long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, -int min_ovlp, long long gap_fuzz, bub_label_t* b_mask_t, ma_ug_t **rhu0, ma_ug_t **rhu1, ug_opt_t *opt); - -typedef struct { - uint32_t d, tot, ma, p; - uint8_t in; -} tip_t; - -typedef struct { - kvec_t(uint32_t) r; - kvec_t(uint32_t) st; - tip_t *b; -}kv_tip_t; - -typedef struct { - asg64_v z; - asg64_v idx; -}u_trans_cluster; - -typedef struct { // global data structure for kt_pipeline() - ma_ug_t *ug; - asg_t *rg; - kv_u_trans_t *res; - kv_u_trans_t *ta; - uint64_t n_thread, ov_cutoff; - double small_ov_rate, sec_rate, sc_sec_rate; - asg64_v *srt; - u_trans_cluster *cu; -} u_trans_clean_t; - -typedef struct { - buf_t *a; asg_t *ref, *g; - uint64_t n_thread, max_dist; - asg64_v *rr; -} rd_hamming_t; - -typedef struct { - asg_t *ref; - asg_t *nsg; - ma_ug_t *nug; - uint32_t *o2n; - uint64_t *ugh; - asg64_v *srt; -} rd_hamming_fly_t; - -typedef struct { - // asg_t *ref; - // asg_t *ng; - ma_hit_t_alloc* src; - ma_sub_t *cov; - int32_t max_hang; - int32_t min_ovlp; - int32_t gap_fuzz; - asg32_v *srt; - uint8_t *vs; - // uint32_t *rs; - ma_ug_t *fg; - kvec_asg_arc_t_warp *ae; - uint32_t n_insert; -} rd_hamming_fly_simp_t; - -typedef struct { - ma_ug_t *ug; - asg_t *rg; - uint32_t *ridx; - uint64_t *ra; - uint64_t ridx_n, ra_n; -} dedup_idx_t; - -typedef struct { - uint32_t id0, id1; - uint64_t len; -} NN_t; - -typedef struct { - NN_t *a; - size_t n, m; -} kvect_N_t; - -typedef struct { - uint64_t m, n, is_c; - uint64_t *a; -} sec_t; - -typedef struct { - sec_t *a; - size_t n, m; - ma_ug_t *ctg; -} kvect_sec_t; - - -typedef struct { - All_reads *Rinf; - UC_Read *aux; - telo_end_t *u; - khash_t(64) *h; - int64_t min_sc, penalty, max_drop; -} telo_end_pip_t; - -///this value has been updated at the first line of build_string_graph_without_clean -long long min_thres; - -uint32_t print_untig_by_read(ma_ug_t *g, const char* name, uint32_t in, ma_hit_t_alloc* sources, -ma_hit_t_alloc* reverse_sources, const char* info); -int asg_pop_bubble_primary_trio(ma_ug_t *ug, uint64_t* i_max_dist, uint32_t positive_flag, uint32_t negative_flag, hap_cov_t *cov, utg_trans_t *o, uint32_t is_update_chain, rd_hamming_fly_simp_t *p); -kv_u_trans_t *get_utg_ovlp(ma_ug_t **ug, asg_t* read_g, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* new_rtg_edges, bub_label_t* b_mask_t, uint8_t* r_het); -void delete_useless_nodes(ma_ug_t **ug); - -static void mark_telo_ends(void *data, long i, int tid) // callback for kt_for() -{ - telo_end_pip_t *sl = (telo_end_pip_t *)data; - int64_t k, l, rlen, tlen, sc, max_sc, pen = sl->penalty, max_drop = sl->max_drop, min_sc = sl->min_sc, z; - uint64_t rid = i, c, x, mask = sl->u->mask, hit, xz; - UC_Read *rr = &(sl->aux[tid]); rlen = Get_READ_LENGTH((*(sl->Rinf)), rid); sl->u->hh[rid] = 0; - recover_UC_Read(rr, sl->Rinf, rid); assert((rr->length) == rlen); tlen = sl->u->tlen; - - for (k = l = 0, sc = max_sc = x = 0; k < rlen; k++) { // 5'-end, check CCCTAA - hit = 0; c = seq_nt6_table[(uint8_t)rr->seq[k]]; - if (c >= 0 && c <= 3) { // not N - x = (x<<2 | (c)) & mask; - if (((++l) >= tlen) && (kh_get(64, sl->h, x) != kh_end(sl->h))) {// x is at least 6bp long and is a telomere motif - hit = 1; - } - } else {l = 0, x = 0;} // N, ambiguous base - if(k >= tlen) sc += ((hit)?(1):(-pen)); - if (sc > max_sc) {max_sc = sc;} - else if ((max_sc - sc) > max_drop) {break;} - - if(max_sc >= min_sc) break; - } - - if(max_sc >= min_sc) { - for (k = l = 0, sc = max_sc = x = 0, xz = ((uint64_t)-1); k < rlen; k++) { // 5'-end, check CCCTAA - hit = 0; c = seq_nt6_table[(uint8_t)rr->seq[k]]; - if (c >= 0 && c <= 3) { // not N - x = (x<<2 | (c)) & mask; - if (((++l) >= tlen) && (kh_get(64, sl->h, x) != kh_end(sl->h))) {// x is at least 6bp long and is a telomere motif - if((xz != ((uint64_t)-1)) && (xz == x)) { - hit = 1; - } else { - for (z = 0, xz = sl->u->tm; (z < tlen) && (xz != x); z++) { - xz = (((xz>>((tlen-1)<<1))&(3ULL))|(xz<<2))&mask; - } - if((z < tlen) && (xz == x)) hit = 1; - } - } - } else {l = 0, x = 0;} // N, ambiguous base - - if(!hit) { - xz = ((uint64_t)-1); - } else { - xz = (((x>>((tlen-1)<<1))&(3ULL))|(x<<2))&mask; - } - if(k >= tlen) sc += ((hit)?(1):(-pen)); - if (sc > max_sc) {max_sc = sc;} - else if ((max_sc - sc) > max_drop) {break;} - - if(max_sc >= min_sc) break; - } - - if(max_sc >= min_sc) sl->u->hh[rid] |= 1; - } - - - - - - - for (k = rlen-1, l = 0, sc = max_sc = x = 0; k >= 0; --k) { // 3'-end - hit = 0; c = seq_nt6_table[(uint8_t)(RC_CHAR(rr->seq[k]))]; - if (c >= 0 && c <= 3) { // not N - x = (x<<2 | (c)) & mask; - if (((++l) >= tlen) && (kh_get(64, sl->h, x) != kh_end(sl->h))) {// x is at least 6bp long and is a telomere motif - hit = 1; - } - } else {l = 0, x = 0;} // N, ambiguous base - if((rlen - k) >= tlen) sc += ((hit)?(1):(-pen)); - if (sc > max_sc) {max_sc = sc;} - else if ((max_sc - sc) > max_drop) {break;} - - if(max_sc >= min_sc) break; - } - - if(max_sc >= min_sc) { - for (k = rlen-1, l = 0, sc = max_sc = x = 0, xz = ((uint64_t)-1); k >= 0 ; --k) { // 3'-end - hit = 0; c = seq_nt6_table[(uint8_t)(RC_CHAR(rr->seq[k]))]; - if (c >= 0 && c <= 3) { // not N - x = (x<<2 | (c)) & mask; - if (((++l) >= tlen) && (kh_get(64, sl->h, x) != kh_end(sl->h))) {// x is at least 6bp long and is a telomere motif - if((xz != ((uint64_t)-1)) && (xz == x)) { - hit = 1; - } else { - for (z = 0, xz = sl->u->tm; (z < tlen) && (xz != x); z++) { - xz = (((xz>>((tlen-1)<<1))&(3ULL))|(xz<<2))&mask; - } - if((z < tlen) && (xz == x)) hit = 1; - } - } - } else {l = 0, x = 0;} // N, ambiguous base - - if(!hit) { - xz = ((uint64_t)-1); - } else { - xz = (((x>>((tlen-1)<<1))&(3ULL))|(x<<2))&mask; - } - if((rlen - k) >= tlen) sc += ((hit)?(1):(-pen)); - if (sc > max_sc) {max_sc = sc;} - else if ((max_sc - sc) > max_drop) {break;} - - if(max_sc >= min_sc) break; - } - - if(max_sc >= min_sc) sl->u->hh[rid] |= 2; - } -} - - -telo_end_t* gen_telo_end_t(All_reads *in, const char* motif, int64_t min_sc, int64_t penalty, int64_t max_drop, uint64_t n_thread) -{ - uint64_t j, k, c, x; int absent; - telo_end_t* p = NULL; CALLOC(p, 1); - p->tlen = strlen(motif); p->mask = ((1ULL)<<(p->tlen<<1))-1; - - for (j = 0, p->tm = 0; j < p->tlen; ++j) { - c = seq_nt6_table[(uint8_t)motif[j]]; - assert(c >= 0 && c <= 3); - p->tm = (p->tm<<2)|(c); - } - p->n = in->total_reads; CALLOC(p->hh, p->n); - - telo_end_pip_t *aux; CALLOC(aux, 1); - aux->min_sc = min_sc; aux->max_drop = max_drop; - aux->penalty = penalty; if(aux->penalty < 0) aux->penalty = (aux->penalty)*-1; - aux->Rinf = in; aux->u = p; CALLOC(aux->aux, n_thread); - for (k = 0; k < n_thread; k++) init_UC_Read(&(aux->aux[k])); - aux->h = kh_init(64); kh_resize(64, aux->h, (p->tlen*2)); // hash table for all roations of the telomere motif - for (k = 0, x = p->tm; k < p->tlen; k++) { - kh_put(64, aux->h, x, &absent); - x = (((x>>((p->tlen-1)<<1))&(3ULL))|(x<<2))&p->mask; - } - assert(x == p->tm); - - kt_for(n_thread, mark_telo_ends, aux, p->n); - - for (k = 0; k < n_thread; k++) destory_UC_Read(&(aux->aux[k])); - free(aux->aux); kh_destroy(64, aux->h); free(aux); - - uint64_t t3, t5; - for (k = t3 = t5 = 0; k < p->n; k++) { - if(p->hh[k]&1) { - // fprintf(stderr, "%.*s(+)\n", (int)Get_NAME_LENGTH((*in), k), Get_NAME((*in), k)); - t5++; - } - if(p->hh[k]&2) { - // fprintf(stderr, "%.*s(-)\n", (int)Get_NAME_LENGTH((*in), k), Get_NAME((*in), k)); - t3++; - } - } - - - fprintf(stderr, "[M::%s::] ==> # 5'-telomeres::%lu, # 3'-telomeres::%lu, # tot::%lu, motif::%s, motif_len::%lu\n", __func__, t5, t3, p->n, motif, p->tlen); - // exit(1); - - return p; -} - -void destory_telo_end_t(telo_end_t *p) -{ - free(p->hh); -} - -void init_bub_label_t(bub_label_t* x, uint32_t n_thres, uint32_t n_reads) -{ - uint32_t i; - x->check_cross = 0; - x->bub_dist = 0; - x->n_thres = n_thres; - x->n_reads = n_reads; - x->g = NULL; - CALLOC(x->b, x->n_thres); - for (i = 0; i < x->n_thres; i++) - { - CALLOC(x->b[i].a, x->n_reads<<1); - } -} - -void reset_bub_label_t(bub_label_t* x, asg_t *g, uint64_t bub_dist, uint32_t check_cross) -{ - uint32_t i; - x->bub_dist = bub_dist; - x->check_cross = check_cross; - x->g = g; - if(x->n_reads < x->g->n_seq) - { - x->n_reads = x->g->n_seq; - for (i = 0; i < x->n_thres; i++) - { - REALLOC(x->b[i].a, x->n_reads<<1); - } - } - - for (i = 0; i < x->n_thres; i++) - { - x->b[i].S.n = x->b[i].b.n = x->b[i].e.n = 0; - memset(x->b[i].a, 0, (x->n_reads<<1)*sizeof(binfo_s_t)); - } -} - -void destory_bub_label_t(bub_label_t* x) -{ - uint32_t i; - for (i = 0; i < x->n_thres; i++) - { - free(x->b[i].a); - free(x->b[i].S.a); - free(x->b[i].b.a); - free(x->b[i].e.a); - } - free(x->b); -} - -void ma_hit_sort_tn(ma_hit_t *a, long long n) -{ - radix_sort_hit_tn(a, a + n); -} - -void ma_hit_sort_qns(ma_hit_t *a, long long n) -{ - radix_sort_hit_qns(a, a + n); -} - -void sort_kvec_t_u64_warp(kvec_t_u64_warp* u_vecs, uint32_t is_descend) -{ - radix_sort_arch64(u_vecs->a.a, u_vecs->a.a + u_vecs->a.n); - if(is_descend) - { - uint64_t i, uInfor; - for (i = 0; i < (u_vecs->a.n>>1); ++i) - { - uInfor = u_vecs->a.a[i]; - u_vecs->a.a[i] = u_vecs->a.a[u_vecs->a.n - i - 1]; - u_vecs->a.a[u_vecs->a.n - i - 1] = uInfor; - } - } -} - -///if ug == NULL, nsg should be equal to read_sg -inline uint32_t check_different_haps(asg_t *nsg, ma_ug_t *ug, asg_t *read_sg, -uint32_t v_0, uint32_t v_1, ma_hit_t_alloc* reverse_sources, buf_t* b_0, buf_t* b_1, -R_to_U* ruIndex, uint8_t* is_r_het, uint32_t min_edge_length, uint32_t stops_threshold) -{ - uint32_t vEnd, qn, tn, j, is_Unitig, uId; - long long ELen_0, ELen_1, tmp, max_stop_nodeLen, max_stop_baseLen; - - b_0->b.n = b_1->b.n = 0; - if(get_unitig(nsg, ug, v_0, &vEnd, &ELen_0, &tmp, &max_stop_nodeLen, &max_stop_baseLen, - stops_threshold, b_0) == LOOP) - { - return UNAVAILABLE; - } - if(get_unitig(nsg, ug, v_1, &vEnd, &ELen_1, &tmp, &max_stop_nodeLen, &max_stop_baseLen, - stops_threshold, b_1) == LOOP) - { - return UNAVAILABLE; - } - if(ELen_0<=min_edge_length || ELen_1<=min_edge_length) return UNAVAILABLE; - - rIdContig b_max, b_min; - b_max.b_0 = b_min.b_0 = NULL; - b_max.offset = b_max.readI = b_max.untigI = 0; - b_min.offset = b_min.readI = b_min.untigI = 0; - - if(ELen_0<=ELen_1) - { - b_min.b_0 = b_0; - b_max.b_0 = b_1; - } - else - { - b_min.b_0 = b_1; - b_max.b_0 = b_0; - } - - uint32_t max_count = 0, min_count = 0, n_het = 0, n_hom = 0; - ma_utg_t *node_min = NULL, *node_max = NULL; - if(ug != NULL) - { - /*****************************label all unitigs****************************************/ - for (b_max.untigI = 0; b_max.untigI < b_max.b_0->b.n; b_max.untigI++) - { - node_max = &(ug->u.a[b_max.b_0->b.a[b_max.untigI]>>1]); - ///each read - for (b_max.readI = 0; b_max.readI < node_max->n; b_max.readI++) - { - qn = (node_max->a[b_max.readI]>>33); - set_R_to_U(ruIndex, qn, (b_max.b_0->b.a[b_max.untigI]>>1), 1, &(read_sg->seq[qn].c)); - } - } - /*****************************label all unitigs****************************************/ - - ///each unitig - for (b_min.untigI = 0; b_min.untigI < b_min.b_0->b.n; b_min.untigI++) - { - - node_min = &(ug->u.a[(b_min.b_0->b.a[b_min.untigI]>>1)]); - - ///each read - for (b_min.readI = 0; b_min.readI < node_min->n; b_min.readI++) - { - qn = node_min->a[b_min.readI]>>33; - - /************************BUG: don't forget****************************/ - if(reverse_sources[qn].length > 0) min_count++; - if((is_r_het[qn] & C_HET) || (is_r_het[qn] & P_HET)) n_het++; - n_hom++; - /************************BUG: don't forget****************************/ - for (j = 0; j < (long long)reverse_sources[qn].length; j++) - { - tn = Get_tn(reverse_sources[qn].buffer[j]); - if(read_sg->seq[tn].del == 1) - { - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_sg->seq[tn].del == 1) continue; - } - - get_R_to_U(ruIndex, tn, &uId, &is_Unitig); - if(uId!=(uint32_t)-1 && is_Unitig == 1) - { - // if(v_0==510 && v_1==67) fprintf(stderr, "###untigI-%u, readI-%um, un-%u\n", b_min.untigI, b_min.readI, (uint32_t)node_min->n); - max_count++; - break; - } - } - } - } - /*****************************label all unitigs****************************************/ - for (b_max.untigI = 0; b_max.untigI < b_max.b_0->b.n; b_max.untigI++) - { - node_max = &(ug->u.a[b_max.b_0->b.a[b_max.untigI]>>1]); - ///each read - for (b_max.readI = 0; b_max.readI < node_max->n; b_max.readI++) - { - qn = (node_max->a[b_max.readI]>>33); - ruIndex->index[qn] = (uint32_t)-1; - } - } - /*****************************label all unitigs****************************************/ - } - else - { - /*****************************label all reads****************************************/ - for (b_max.untigI = 0; b_max.untigI < b_max.b_0->b.n; b_max.untigI++) - { - qn = (b_max.b_0->b.a[b_max.untigI]>>1); - set_R_to_U(ruIndex, qn, 1, 1, &(read_sg->seq[qn].c)); - } - /*****************************label all reads****************************************/ - - ///each read - for (b_min.untigI = 0; b_min.untigI < b_min.b_0->b.n; b_min.untigI++) - { - qn = (b_min.b_0->b.a[b_min.untigI]>>1); - - /************************BUG: don't forget****************************/ - if(reverse_sources[qn].length > 0) min_count++; - if((is_r_het[qn] & C_HET) || (is_r_het[qn] & P_HET)) n_het++; - n_hom++; - /************************BUG: don't forget****************************/ - - for (j = 0; j < (long long)reverse_sources[qn].length; j++) - { - tn = Get_tn(reverse_sources[qn].buffer[j]); - if(nsg->seq[tn].del == 1) - { - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || nsg->seq[tn].del == 1) continue; - } - - - get_R_to_U(ruIndex, tn, &uId, &is_Unitig); - if(uId!=(uint32_t)-1 && is_Unitig == 1) - { - max_count++; - break; - } - } - } - - /*****************************label all reads****************************************/ - for (b_max.untigI = 0; b_max.untigI < b_max.b_0->b.n; b_max.untigI++) - { - qn = (b_max.b_0->b.a[b_max.untigI]>>1); - ruIndex->index[qn] = (uint32_t)-1; - } - /*****************************label all reads****************************************/ - } - - if(min_count == 0) return UNAVAILABLE; - if(max_count > min_count*asm_opt.purge_simi_thres && n_het >= n_hom*HET_HOM_RATE) return PLOID; - return NON_PLOID; -} - -inline void calculate_match_cover(uint32_t *b, uint32_t b_n, asg_t *nsg, ma_ug_t *ug, asg_t *read_sg, -ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, uint32_t *min_count, uint32_t *max_count) -{ - ma_utg_t *u = NULL; - uint32_t ui, ri, ori, qn, tn, v, w, k, nv, j, is_Unitig, uId; - asg_arc_t *av = NULL; - long long offset, r_beg, r_end, inp_beg, inp_end, hap_beg, hap_end, ovlp, hap_match, inp_match, l; - (*min_count) = (*max_count) = 0; - inp_beg = -1; inp_end = -2; - hap_beg = -1; hap_end = -2; - inp_match = hap_match = 0; - if(ug) - { - for (ui = 0, offset = 0; ui < b_n; ui++) - { - u = &(ug->u.a[(b[ui]>>1)]); - ori = b[ui]&1; - ///each read - for (ri = 0; ri < u->n; ri++) - { - qn = (ori==1?((uint64_t)((u->a[u->n-ri-1])))>>33:((uint64_t)(u->a[ri]))>>33); - r_beg = offset; r_end = offset + (long long)(read_sg->seq[qn].len) - 1; - offset += (ori==1?(uint32_t)(u->a[u->n-ri-1]):(uint32_t)(u->a[ri])); - if(ori==1) offset -= (long long)(read_sg->seq[qn].len); - - if(reverse_sources[qn].length > 0) - { - // min_count++; - if(r_beg <= hap_end) - { - hap_end = MAX(hap_end, r_end); - } - else - { - ovlp = hap_end - hap_beg + 1; - hap_match += (ovlp >= 0? ovlp : 0); - hap_beg = r_beg; hap_end = r_end; - } - } - - for (j = 0; j < reverse_sources[qn].length; j++) - { - tn = Get_tn(reverse_sources[qn].buffer[j]); - if(read_sg->seq[tn].del == 1) - { - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_sg->seq[tn].del == 1) continue; - } - - get_R_to_U(ruIndex, tn, &uId, &is_Unitig); - if(uId!=(uint32_t)-1 && is_Unitig == 1) - { - ///max_count++; - break; - } - } - - if(j < reverse_sources[qn].length) - { - if(r_beg <= inp_end) - { - inp_end = MAX(inp_end, r_end); - } - else - { - ovlp = inp_end - inp_beg + 1; - inp_match += (ovlp >= 0? ovlp : 0); - inp_beg = r_beg; inp_end = r_end; - } - } - } - - if(ui+1 < b_n) - { - v = b[ui]; w = b[ui+1]; - av = asg_arc_a(nsg, v); - nv = asg_arc_n(nsg, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - offset -= av[k].ol; - break; - } - } - if(k >= nv) fprintf(stderr, "ERROR-mc\n"); - } - } - } - else - { - for (ui = 0, offset = 0; ui < b_n; ui++) - { - qn = b[ui]>>1; - r_beg = offset; r_end = offset + (long long)(read_sg->seq[qn].len) - 1; - l = read_sg->seq[qn].len; - if(ui+1 < b_n) - { - v = b[ui]; w = b[ui+1]; - av = asg_arc_a(read_sg, v); - nv = asg_arc_n(read_sg, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - l = asg_arc_len(av[k]); - break; - } - } - if(k >= nv) fprintf(stderr, "ERROR-mc\n"); - } - offset += l; - - if(reverse_sources[qn].length > 0) - { - // min_count++; - if(r_beg <= hap_end) - { - hap_end = MAX(hap_end, r_end); - } - else - { - ovlp = hap_end - hap_beg + 1; - hap_match += (ovlp >= 0? ovlp : 0); - hap_beg = r_beg; hap_end = r_end; - } - } - - for (j = 0; j < reverse_sources[qn].length; j++) - { - tn = Get_tn(reverse_sources[qn].buffer[j]); - if(read_sg->seq[tn].del == 1) - { - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_sg->seq[tn].del == 1) continue; - } - - get_R_to_U(ruIndex, tn, &uId, &is_Unitig); - if(uId!=(uint32_t)-1 && is_Unitig == 1) - { - ///max_count++; - break; - } - } - - if(j < reverse_sources[qn].length) - { - if(r_beg <= inp_end) - { - inp_end = MAX(inp_end, r_end); - } - else - { - ovlp = inp_end - inp_beg + 1; - inp_match += (ovlp >= 0? ovlp : 0); - inp_beg = r_beg; inp_end = r_end; - } - } - } - } - - ovlp = inp_end - inp_beg + 1; - inp_match += (ovlp >= 0? ovlp : 0); - - ovlp = hap_end - hap_beg + 1; - hap_match += (ovlp >= 0? ovlp : 0); - - (*max_count) = inp_match; - (*min_count) = hap_match; -} - -asg_t *asg_init(void) -{ - return (asg_t*)calloc(1, sizeof(asg_t)); -} - -void asg_destroy(asg_t *g) -{ - if (g == 0) return; - free(g->seq); free(g->idx); free(g->arc); free(g->seq_vis); - - if(g->n_F_seq > 0 && g->F_seq) - { - uint32_t i = 0; - for (i = 0; i < g->n_F_seq; i++) - { - if(g->F_seq[i].a) free(g->F_seq[i].a); - if(g->F_seq[i].s) free(g->F_seq[i].s); - } - - free(g->F_seq); - } - - - free(g); -} - -void asg_arc_sort(asg_t *g) -{ - radix_sort_asg(g->arc, g->arc + g->n_arc); -} - - -void add_overlaps(ma_hit_t_alloc* source_paf, ma_hit_t_alloc* dest_paf, uint64_t* source_index, long long listLen) -{ - long long i; - ma_hit_t* tmp; - for (i = 0; i < listLen; i++) - { - tmp = &(source_paf->buffer[(uint32_t)(source_index[i])]); - add_ma_hit_t_alloc(dest_paf, tmp); - } -} - - -void remove_overlaps(ma_hit_t_alloc* source_paf, uint64_t* source_index, long long listLen) -{ - long long i, m; - for (i = 0; i < listLen; i++) - { - source_paf->buffer[(uint32_t)(source_index[i])].qns = (uint64_t)(-1); - } - - m = 0; - for (i = 0; i < source_paf->length; i++) - { - if(source_paf->buffer[i].qns != (uint64_t)(-1)) - { - source_paf->buffer[m] = source_paf->buffer[i]; - m++; - } - } - source_paf->length = m; -} - - -void add_overlaps_from_different_sources(ma_hit_t_alloc* source_paf_list, ma_hit_t_alloc* dest_paf, -uint64_t* source_index, long long listLen) -{ - long long i; - ma_hit_t ele; - ma_hit_t* tmp; - uint32_t source_n, source_i; - for (i = 0; i < listLen; i++) - { - source_n = source_index[i] >> 32; - source_i = (uint32_t)(source_index[i]); - tmp = &(source_paf_list[source_n].buffer[source_i]); - - ele.del = 0; - ele.rev = tmp->rev; - ele.qns = Get_tn((*tmp)); - ele.qns = ele.qns << 32; - ele.qns = ele.qns | (uint64_t)(Get_ts((*tmp))); - ele.qe = Get_te((*tmp)); - - ele.tn = Get_qn((*tmp)); - ele.ts = Get_qs((*tmp)); - ele.te = Get_qe((*tmp)); - - ele.bl = R_INF.read_length[ele.tn]; - ele.ml = tmp->ml; - ele.el = tmp->el; - ele.no_l_indel = tmp->no_l_indel; - - add_ma_hit_t_alloc(dest_paf, &ele); - } -} - - - -void ma_ug_destroy(ma_ug_t *ug) -{ - uint32_t i; - if (ug == 0) return; - for (i = 0; i < ug->u.n; ++i) { - free(ug->u.a[i].a); - free(ug->u.a[i].s); - } - free(ug->u.a); - asg_destroy(ug->g); - kv_destroy(ug->occ); - free(ug); -} - -uint64_t *asg_arc_index_core(size_t max_seq, size_t n, const asg_arc_t *a) -{ - size_t i, last; - uint64_t *idx; - idx = (uint64_t*)calloc(max_seq * 2, 8); - - - /** - * ul: |____________31__________|__________1___________|______________32_____________| - qns direction of overlap length of this node (not overlap length) - **/ - ///so if we use high 32-bit, we store the index of each qn with two direction - for (i = 1, last = 0; i <= n; ++i) - if (i == n || a[i-1].ul>>32 != a[i].ul>>32) - idx[a[i-1].ul>>32] = (uint64_t)last<<32 | (i - last), last = i; - - - return idx; -} - -void asg_arc_index(asg_t *g) -{ - if (g->idx) free(g->idx); - g->idx = asg_arc_index_core(g->n_seq, g->n_arc, g->arc); -} - -void asg_seq_set(asg_t *g, int sid, int len, int del) -{ - ///just malloc size - if (sid >= (int)g->m_seq) { - g->m_seq = sid + 1; - kv_roundup32(g->m_seq); - g->seq = (asg_seq_t*)realloc(g->seq, g->m_seq * sizeof(asg_seq_t)); - } - - if (sid >= g->n_seq) g->n_seq = sid + 1; - - g->seq[sid].del = !!del; - g->seq[sid].len = len; -} - -ma_utg_t* asg_F_seq_set(asg_t *g, int iid) -{ - if(iid < (int)g->r_seq) return NULL; - uint32_t index = iid - g->r_seq, pre_n_F_seq = g->n_F_seq; - - ///just malloc size - if (index >= g->n_F_seq) { - g->n_F_seq = index + 1; - kv_roundup32(g->n_F_seq); - g->F_seq = (ma_utg_t*)realloc(g->F_seq, g->n_F_seq*sizeof(ma_utg_t)); - memset(g->F_seq + pre_n_F_seq, 0, sizeof(ma_utg_t)*(g->n_F_seq-pre_n_F_seq)); - } - - return &(g->F_seq[index]); -} - - - -// hard remove arcs marked as "del" -void asg_arc_rm(asg_t *g) -{ - /** - p->ul: |____________31__________|__________1___________|______________32_____________| - qns direction of overlap length of this node (not overlap length) - p->v : |___________31___________|__________1___________| - tns relative strand between query and target - p->ol: overlap length - **/ - uint32_t e, n; - ///just clean arc requiring: 1. arc it self must be available 2. both the query and target are available - for (e = n = 0; e < g->n_arc; ++e) { - //u and v is the read id - uint32_t u = g->arc[e].ul>>32, v = g->arc[e].v; - if (!g->arc[e].del && !g->seq[u>>1].del && !g->seq[v>>1].del) - g->arc[n++] = g->arc[e]; - } - if (n < g->n_arc) { // arc index is out of sync - if (g->idx) free(g->idx); - g->idx = 0; - } - g->n_arc = n; -} - -void asg_cleanup(asg_t *g) -{ - ///remove overlaps, instead of reads - ///remove edges with del, and free idx - asg_arc_rm(g); - if (!g->is_srt) { - /** - * sort by ul, that is, sort by qns + direction - * ul: |____________31__________|__________1___________|______________32_____________| - qns direction of overlap length of this node (not overlap length) - **/ - asg_arc_sort(g); - g->is_srt = 1; - } - ///index the overlaps in graph with query id - if (g->idx == 0) asg_arc_index(g); -} - - - -// delete multi-arcs -/** - * remove edges like: v has two out-edges to w -**/ -int asg_arc_del_multi(asg_t *g) -{ - //the number of nodes are number of read times 2 - uint32_t *cnt, n_vtx = g->n_seq * 2, n_multi = 0, v; - cnt = (uint32_t*)calloc(n_vtx, 4); - for (v = 0; v < n_vtx; ++v) { - ///out-nodes of v - asg_arc_t *av = asg_arc_a(g, v); - int32_t i, nv = asg_arc_n(g, v); - ///if v just have one out-node, there is no muti-edge - if (nv < 2) continue; - for (i = nv - 1; i >= 0; --i) ++cnt[av[i].v]; - for (i = nv - 1; i >= 0; --i) - if (--cnt[av[i].v] != 0) - av[i].del = 1, ++n_multi; - } - free(cnt); - if (n_multi) asg_cleanup(g); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d multi-arcs\n", __func__, n_multi); - } - - return n_multi; -} - -// remove asymmetric arcs: u->v is present, but v'->u' not -int asg_arc_del_asymm(asg_t *g) -{ - uint32_t e, n_asymm = 0; - ///g->n_arc is the number of overlaps - for (e = 0; e < g->n_arc; ++e) { - uint32_t v = g->arc[e].v^1, u = g->arc[e].ul>>32^1; - 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 == u) break; - if (i == nv) g->arc[e].del = 1, ++n_asymm; - } - if (n_asymm) asg_cleanup(g); - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d asymmetric arcs\n", __func__, n_asymm); - } - return n_asymm; -} - - -void asg_symm(asg_t *g) -{ - asg_arc_del_multi(g); - asg_arc_del_asymm(g); - g->is_symm = 1; -} - -void init_ma_hit_t_alloc(ma_hit_t_alloc* x) -{ - x->size = 0; - x->buffer = NULL; - x->length = 0; - x->is_fully_corrected = 0; - x->is_abnormal = 0; -} - -void clear_ma_hit_t_alloc(ma_hit_t_alloc* x) -{ - x->length = 0; -} - -void resize_ma_hit_t_alloc(ma_hit_t_alloc* x, uint32_t size) -{ - if (size > x->size) { - x->size = size; - kroundup32(x->size); - REALLOC(x->buffer, x->size); - } -} - -void destory_ma_hit_t_alloc(ma_hit_t_alloc* x) -{ - free(x->buffer); -} - -void add_ma_hit_t_alloc(ma_hit_t_alloc* x, ma_hit_t* element) -{ - if (x->length + 1 > x->size) { - x->size = x->length + 1; - kroundup32(x->size); - REALLOC(x->buffer, x->size); - } - x->buffer[x->length++] = *element; -} - - -long long get_specific_overlap(ma_hit_t_alloc* x, uint32_t qn, uint32_t tn) -{ - long long i; - for (i = 0; i < x->length; i++) - { - if(x->buffer[i].tn == tn - && - ((uint32_t)(x->buffer[i].qns>>32)) == qn) - { - return i; - } - } - - return -1; -} - - - -void set_reverse_overlap(ma_hit_t* dest, ma_hit_t* source) -{ - dest->qns = Get_tn(*source); - dest->qns = dest->qns << 32; - dest->qns = dest->qns | Get_ts(*source); - dest->qe = Get_te(*source); - - - dest->tn = Get_qn(*source); - dest->ts = Get_qs(*source); - dest->te = Get_qe(*source); - - dest->rev = source->rev; - dest->el = source->el; - - - /****************************may have bugs********************************/ - /** - if(dest->ml == 0 || source->ml == 0) - { - dest->ml = source->ml = 0; - } - else - { - dest->ml = source->ml = 1; - } - - - if(dest->no_l_indel == 0 || source->no_l_indel == 0) - { - dest->no_l_indel = source->no_l_indel = 0; - } - else - { - dest->no_l_indel = source->no_l_indel = 1; - } - **/ - dest->ml = source->ml; - dest->no_l_indel = source->no_l_indel; - /****************************may have bugs********************************/ - dest->bl = source->bl/**Get_qe(*dest) - Get_qs(*dest)**/; -} - - - - -void normalize_ma_hit_t_single_side_advance(ma_hit_t_alloc* sources, long long num_sources, uint32_t recuse_el, uint8_t *cmk) -{ - double startTime = Get_T(); - - long long i, j, index; - uint32_t qn, tn, is_del = 0; - long long qLen_0, qLen_1; - ma_hit_t ele; - for (i = 0; i < num_sources; i++) - { - - for (j = 0; j < sources[i].length; j++) - { - qn = Get_qn(sources[i].buffer[j]); - tn = Get_tn(sources[i].buffer[j]); - - // sources[i].buffer[j].bl = Get_qe(sources[i].buffer[j]) - Get_qs(sources[i].buffer[j]); - - ///if(sources[i].buffer[j].del) continue; - - index = get_specific_overlap(&(sources[tn]), tn, qn); - - - ///if(index != -1 && sources[tn].buffer[index].del == 0) - if(index != -1) { - is_del = 0; - if(sources[i].buffer[j].del || sources[tn].buffer[index].del) is_del = 1; - - qLen_0 = Get_qe(sources[i].buffer[j]) - Get_qs(sources[i].buffer[j]); - qLen_1 = Get_qe(sources[tn].buffer[index]) - Get_qs(sources[tn].buffer[index]); - - if(qLen_0 == qLen_1) { - ///qn must be not equal to tn - ///make sources[qn] = sources[tn] if qn > tn - if(qn < tn) { - set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); - } - } else if(qLen_0 > qLen_1) { - set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); - } - - if(recuse_el && sources[i].buffer[j].el && sources[tn].buffer[index].el) is_del = 0; - if(cmk && (cmk[qn] <= asm_opt.chemical_cov/**FORCE_CUT**/ || cmk[tn] <= asm_opt.chemical_cov/**FORCE_CUT**/)) is_del = 1; - - sources[i].buffer[j].del = is_del; - sources[tn].buffer[index].del = is_del; - } else {///means this edge just occurs in one direction - is_del = 1; - set_reverse_overlap(&ele, &(sources[i].buffer[j])); - if(recuse_el && sources[i].buffer[j].el && ele.el) is_del = 0; - if(cmk && (cmk[qn] <= asm_opt.chemical_cov/**FORCE_CUT**/ || cmk[tn] <= asm_opt.chemical_cov/**FORCE_CUT**/)) is_del = 1; - sources[i].buffer[j].del = ele.del = is_del; - add_ma_hit_t_alloc(&(sources[tn]), &ele); - } - } - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2fs\n\n", __func__, Get_T()-startTime); - } -} - - -typedef struct { - kvec_t_u64_warp *buf; - ma_hit_t_alloc* src; - int64_t n_thread; -} ma_hit_t_aux; - -static void update_ma_hit_t_norm(void *data, long i, int tid) // callback for kt_for() -{ - ma_hit_t_aux *sl = (ma_hit_t_aux *)data; - ma_hit_t_alloc* src = sl->src; - uint64_t z, qn, tn, is_del = 0; - int64_t idx, qLen_0, qLen_1; - - for (z = 0; z < src[i].length; z++) { - qn = Get_qn(src[i].buffer[z]); - tn = Get_tn(src[i].buffer[z]); - is_del = 0; idx = get_specific_overlap(&(src[tn]), tn, qn); - - if(idx != -1 && qn <= tn) { ///qn must be not equal to tn - if(src[i].buffer[z].del || src[tn].buffer[idx].del) is_del = 1; - qLen_0 = Get_qe(src[i].buffer[z]) - Get_qs(src[i].buffer[z]); - qLen_1 = Get_qe(src[tn].buffer[idx]) - Get_qs(src[tn].buffer[idx]); - - if(qLen_0 == qLen_1) { - ///qn must be not equal to tn - ///make sources[qn] = sources[tn] if qn > tn - set_reverse_overlap(&(src[tn].buffer[idx]), &(src[i].buffer[z])); - } - else if(qLen_0 > qLen_1) { - set_reverse_overlap(&(src[tn].buffer[idx]), &(src[i].buffer[z])); - } else { - set_reverse_overlap(&(src[i].buffer[z]), &(src[tn].buffer[idx])); - } - - src[i].buffer[z].del = is_del; src[tn].buffer[idx].del = is_del; - } - else ///means this edge just occurs in one direction - { - tn = i; tn <<= 32; tn |= z; - kv_push(uint64_t, sl->buf[tid].a, tn); - src[i].buffer[z].del = 1; - } - } -} - -void normalize_ma_hit_t_single_side_advance_mult(ma_hit_t_alloc* src, int64_t n_src, int64_t n_thread) -{ - ma_hit_t_aux aux; int64_t k; uint64_t z; ma_hit_t e; - aux.n_thread = n_thread; aux.src = src; CALLOC(aux.buf, aux.n_thread); - - kt_for(aux.n_thread, update_ma_hit_t_norm, &aux, n_src); - - for (k = 0; k < aux.n_thread; k++) { - for (z = 0; z < aux.buf[k].a.n; z++) { - set_reverse_overlap(&e, &(src[aux.buf[k].a.a[z]>>32].buffer[(uint32_t)(aux.buf[k].a.a[z])])); - src[aux.buf[k].a.a[z]>>32].buffer[(uint32_t)(aux.buf[k].a.a[z])].del = e.del = 1; - add_ma_hit_t_alloc(&(src[Get_qn(e)]), &e); - } - free(aux.buf[k].a.a); - } - free(aux.buf); -} - - - -void get_end_match_length(ma_hit_t* edge, UC_Read* query, UC_Read* target, -uint32_t* left, uint32_t* right) -{ - (*left) = (*right) = 0; - - uint32_t query_beg, query_end, target_beg, target_end, targetLen, oLen; - long long i; - targetLen = Get_READ_LENGTH(R_INF, Get_tn(*edge)); - query_beg = Get_qs(*edge); - query_end = Get_qe(*edge)-1; - recover_UC_Read(query, &R_INF, Get_qn(*edge)); - - if(edge->rev) - { - target_beg = targetLen-(Get_te(*edge)-1)-1; - target_end = targetLen-Get_ts(*edge)-1; - recover_UC_Read_RC(target, &R_INF, Get_tn(*edge)); - } - else - { - target_beg = Get_ts(*edge); - target_end = Get_te(*edge)-1; - recover_UC_Read(target, &R_INF, Get_tn(*edge)); - } - - oLen = Get_qe(*edge) - Get_qs(*edge); - /***************************left*******************************/ - for (i = 0; i < oLen; i++) - { - if(query->seq[query_beg+i]!=target->seq[target_beg+i]) break; - (*left)++; - } - /***************************left*******************************/ - - /***************************right*******************************/ - for (i = 0; i < oLen; i++) - { - if(query->seq[query_end-i]!=target->seq[target_end-i]) break; - (*right)++; - } - /***************************right*******************************/ - -} - -void normalize_ma_hit_t_single_side_aggressive(ma_hit_t_alloc* sources, long long num_sources) -{ - double startTime = Get_T(); - - ///long long debug_prefect = 0, debug_not_bad = 0, debug_bad = 0; - - UC_Read query, target; - init_UC_Read(&query); - init_UC_Read(&target); - - long long i, j, index; - uint32_t qn, tn, queryLeftLen, queryRightLen, targetLeftLen, targetRightLen; - long long qLen_0, qLen_1, m; - for (i = 0; i < num_sources; i++) - { - - m = 0; - for (j = 0; j < sources[i].length; j++) - { - qn = Get_qn(sources[i].buffer[j]); - tn = Get_tn(sources[i].buffer[j]); - - // sources[i].buffer[j].bl = Get_qe(sources[i].buffer[j]) - Get_qs(sources[i].buffer[j]); - - index = get_specific_overlap(&(sources[tn]), tn, qn); - - - if(index != -1) - { - // sources[tn].buffer[index].bl = Get_qe(sources[tn].buffer[index]) - // - Get_qs(sources[tn].buffer[index]); - - if(Get_qs(sources[i].buffer[j]) == Get_ts(sources[tn].buffer[index]) - && - Get_qe(sources[i].buffer[j]) == Get_te(sources[tn].buffer[index]) - && - Get_ts(sources[i].buffer[j]) == Get_qs(sources[tn].buffer[index]) - && - Get_te(sources[i].buffer[j]) == Get_qe(sources[tn].buffer[index]) - && - sources[i].buffer[j].rev == sources[tn].buffer[index].rev) - { - ///actually two edges are same, here is just to unify el, ml, no_l_indel, bl - set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); - - sources[i].buffer[m] = sources[i].buffer[j]; - m++; - - ///debug_prefect++; - continue; - } - - - get_end_match_length(&(sources[i].buffer[j]), &query, &target, - &queryLeftLen, &queryRightLen); - - get_end_match_length(&(sources[tn].buffer[index]), &query, &target, - &targetLeftLen, &targetRightLen); - - ///query is right - if(queryLeftLen>0 && queryRightLen>0 && (targetLeftLen==0 || targetRightLen==0)) - { - set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); - - sources[i].buffer[m] = sources[i].buffer[j]; - m++; - - ///debug_not_bad++; - continue; - } - - - ///target is right - if(targetLeftLen>0 && targetRightLen>0 && (queryLeftLen==0 || queryRightLen==0)) - { - set_reverse_overlap(&(sources[i].buffer[j]), &(sources[tn].buffer[index])); - - sources[i].buffer[m] = sources[i].buffer[j]; - m++; - - ///debug_not_bad++; - continue; - } - - - ///query is right - if((queryLeftLen+queryRightLen)>(targetLeftLen+targetRightLen)) - { - set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); - }///target is right - else if((queryLeftLen+queryRightLen)<(targetLeftLen+targetRightLen)) - { - set_reverse_overlap(&(sources[i].buffer[j]), &(sources[tn].buffer[index])); - } - else - { - qLen_0 = Get_qe(sources[i].buffer[j]) - Get_qs(sources[i].buffer[j]); - qLen_1 = Get_qe(sources[tn].buffer[index]) - Get_qs(sources[tn].buffer[index]); - if(qLen_0 >= qLen_1) - { - set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); - } - else - { - set_reverse_overlap(&(sources[i].buffer[j]), &(sources[tn].buffer[index])); - } - } - - sources[i].buffer[m] = sources[i].buffer[j]; - m++; - - ///debug_bad++; - } - } - - sources[i].length = m; - } - - destory_UC_Read(&query); - destory_UC_Read(&target); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2fs\n\n", __func__, Get_T()-startTime); - } - - // fprintf(stderr, "debug_prefect: %ld, debug_not_bad: %ld, debug_bad: %ld\n", debug_prefect, debug_not_bad, - // debug_bad); -} - - -void normalize_ma_hit_t_single_side(ma_hit_t_alloc* sources, long long num_sources) -{ - double startTime = Get_T(); - - ///long long debug_prefect = 0, debug_not_bad = 0, debug_bad = 0; - - UC_Read query, target; - init_UC_Read(&query); - init_UC_Read(&target); - - long long i, j, index; - uint32_t qn, tn, queryLeftLen, queryRightLen, targetLeftLen, targetRightLen; - long long qLen_0, qLen_1, m; - for (i = 0; i < num_sources; i++) - { - - m = 0; - for (j = 0; j < sources[i].length; j++) - { - qn = Get_qn(sources[i].buffer[j]); - tn = Get_tn(sources[i].buffer[j]); - - // sources[i].buffer[j].bl = Get_qe(sources[i].buffer[j]) - Get_qs(sources[i].buffer[j]); - - index = get_specific_overlap(&(sources[tn]), tn, qn); - - - if(index != -1) - { - // sources[tn].buffer[index].bl = Get_qe(sources[tn].buffer[index]) - // - Get_qs(sources[tn].buffer[index]); - - if(Get_qs(sources[i].buffer[j]) == Get_ts(sources[tn].buffer[index]) - && - Get_qe(sources[i].buffer[j]) == Get_te(sources[tn].buffer[index]) - && - Get_ts(sources[i].buffer[j]) == Get_qs(sources[tn].buffer[index]) - && - Get_te(sources[i].buffer[j]) == Get_qe(sources[tn].buffer[index]) - && - sources[i].buffer[j].rev == sources[tn].buffer[index].rev) - { - ///actually two edges are same, here is just to unify el, ml, no_l_indel, bl - set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); - - sources[i].buffer[m] = sources[i].buffer[j]; - m++; - - ///debug_prefect++; - continue; - } - - - get_end_match_length(&(sources[i].buffer[j]), &query, &target, - &queryLeftLen, &queryRightLen); - - get_end_match_length(&(sources[tn].buffer[index]), &query, &target, - &targetLeftLen, &targetRightLen); - - ///query is right - if(queryLeftLen>0 && queryRightLen>0 && (targetLeftLen==0 || targetRightLen==0)) - { - set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); - - sources[i].buffer[m] = sources[i].buffer[j]; - m++; - - ///debug_not_bad++; - continue; - } - - - ///target is right - if(targetLeftLen>0 && targetRightLen>0 && (queryLeftLen==0 || queryRightLen==0)) - { - set_reverse_overlap(&(sources[i].buffer[j]), &(sources[tn].buffer[index])); - - sources[i].buffer[m] = sources[i].buffer[j]; - m++; - - ///debug_not_bad++; - continue; - } - - /** - ///query is right - if((queryLeftLen+queryRightLen)>(targetLeftLen+targetRightLen)) - { - set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); - }///target is right - else if((queryLeftLen+queryRightLen)<(targetLeftLen+targetRightLen)) - { - set_reverse_overlap(&(sources[i].buffer[j]), &(sources[tn].buffer[index])); - } - else - { - qLen_0 = Get_qe(sources[i].buffer[j]) - Get_qs(sources[i].buffer[j]); - qLen_1 = Get_qe(sources[tn].buffer[index]) - Get_qs(sources[tn].buffer[index]); - if(qLen_0 >= qLen_1) - { - set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); - } - else - { - set_reverse_overlap(&(sources[i].buffer[j]), &(sources[tn].buffer[index])); - } - } - **/ - - - - qLen_0 = Get_qe(sources[i].buffer[j]) - Get_qs(sources[i].buffer[j]); - qLen_1 = Get_qe(sources[tn].buffer[index]) - Get_qs(sources[tn].buffer[index]); - if(qLen_0 >= qLen_1) - { - set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); - } - else - { - set_reverse_overlap(&(sources[i].buffer[j]), &(sources[tn].buffer[index])); - } - - - sources[i].buffer[m] = sources[i].buffer[j]; - m++; - - ///debug_bad++; - } - } - - sources[i].length = m; - } - - destory_UC_Read(&query); - destory_UC_Read(&target); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2fs\n\n", __func__, Get_T()-startTime); - } - - // fprintf(stderr, "debug_prefect: %ld, debug_not_bad: %ld, debug_bad: %ld\n", debug_prefect, debug_not_bad, - // debug_bad); -} - - - -void drop_edges_by_trio(ma_hit_t_alloc* sources, long long num_sources) -{ - double startTime = Get_T(); - - long long i, j; - uint32_t qn, tn; - for (i = 0; i < num_sources; i++) - { - for (j = 0; j < sources[i].length; j++) - { - if(sources[i].buffer[j].del) continue; - - qn = Get_qn(sources[i].buffer[j]); - tn = Get_tn(sources[i].buffer[j]); - - if(R_INF.trio_flag[qn] != AMBIGU && R_INF.trio_flag[tn] != AMBIGU) - { - if(R_INF.trio_flag[qn] != R_INF.trio_flag[tn]) - { - sources[i].buffer[j].del = 1; - continue; - } - } - - sources[i].buffer[j].del = 0; - } - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2fs\n\n", __func__, Get_T()-startTime); - } -} - - - -ma_hit_t* get_specific_overlap_with_del(ma_hit_t_alloc* sources, 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, 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; -} - - -uint32_t get_real_sources_length(ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -int max_hang, int min_ovlp, uint32_t query) -{ - uint32_t qn = query>>1; - if(coverage_cut[qn].del) return 0; - int32_t r; - asg_arc_t t; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - ma_hit_t_alloc* x = &(sources[qn]); - uint32_t i, occ = 0; - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - if(h->del) continue; - ///now the edge has not been removed - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(sq->del || st->del) continue; - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - ///if it is a contained read - if(r < 0) continue; - if((t.ul>>32) == query) occ++; - } - - return occ; -} - - -uint32_t delete_all_edges_carefully(ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -int max_hang, int min_ovlp, uint32_t qn) -{ - if(coverage_cut[qn].del) return 0; - - int32_t r; - asg_arc_t t; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - ma_hit_t_alloc* x = &(sources[qn]); - uint32_t i, keep_edge = 0; - uint32_t flag[2]; - flag[0] = flag[1] = 0; - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - if(h->del) continue; - ///now the edge has not been removed - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(sq->del || st->del) - { - h->del = 1; - delete_single_edge(sources, coverage_cut, Get_tn(*h), Get_qn(*h)); - continue; - } - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - ///if it is a contained read - if(r < 0) - { - h->del = 1; - delete_single_edge(sources, coverage_cut, Get_tn(*h), Get_qn(*h)); - continue; - } - - if(get_real_sources_length(sources, coverage_cut, max_hang, min_ovlp, (t.v^1))==1) - { - flag[((t.ul>>32)^1)&1] = 1; - keep_edge++; - continue; - } - - // h->del = 1; - // delete_single_edge(sources, coverage_cut, Get_tn(*h), Get_qn(*h)); - } - - - if(keep_edge != 0) - { - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - if(h->del) continue; - ///now the edge has not been removed - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(sq->del || st->del) continue; - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - ///if it is a contained read - if(r < 0) continue; - - if(flag[(t.ul>>32)&1] == 1) continue; - - if(get_real_sources_length(sources, coverage_cut, max_hang, min_ovlp, (t.v^1))==1) continue; - - h->del = 1; - delete_single_edge(sources, coverage_cut, Get_tn(*h), Get_qn(*h)); - } - } - - if(keep_edge == 0) coverage_cut[qn].del = 1; - return keep_edge; -} - - -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) -{ - ///uint32_t qn_num = 0, no_fully_qn_num = 0, tn_num = 0, no_fully_tn_num = 0; - double startTime = Get_T(); - int32_t r; - long long i, j, m; - 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); - ///r could not be MA_HT_SHORT_OVLP or MA_HT_INT - if (r == MA_HT_QCONT) - { - h->del = 1; - 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, NULL); - } - else if (r == MA_HT_TCONT) - { - h->del = 1; - 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, NULL); - } - } - } - - transfor_R_to_U(ruIndex); - - - for (i = 0; i < n_read; ++i) - { - 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; - } - } - - ///if sources[i].length == 0, that means all overlapped reads with read i are the contained reads - if(m == 0) - { - coverage_cut[i].del = 1; - } - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } -} - - -void ma_hit_flt(ma_hit_t_alloc* sources, long long n_read, ma_sub_t *coverage_cut, int max_hang, int min_ovlp) -{ - double startTime = Get_T(); - long long i, j, rLen; - asg_arc_t t; - - for (i = 0; i < n_read; ++i) - { - rLen = 0; - for (j = 0; j < (long long)sources[i].length; j++) - { - ma_hit_t *h = &(sources[i].buffer[j]); - if(h->del) continue; - //check the corresponding two reads - const ma_sub_t *sq = &(coverage_cut[Get_qn(*h)]); - const ma_sub_t *st = &(coverage_cut[Get_tn(*h)]); - int r; - if (sq->del || st->del) continue; - ///[sq->s, sq->e) and [st->s, st->e) are the high coverage region in query and target - ///here just exculde the overhang? - ///in miniasm the 5-th option is 0.5, instead of 0.8 - /**note!!! h->qn and h->qs have been normalized by sq->s - * h->ts and h->tn have been normalized by sq->e - **/ - ///here the max_hang = 1000, asm_opt.max_hang_rate = 0.8, min_ovlp = 50 - ///for me, there should not have any overhang..so r cannot be equal to MA_HT_INT - ///sq->e - sq->s = the length of query; st->e - st->s = the length od target - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - - - ///for me, there should not have any overhang..so r cannot be equal to MA_HT_INT - ///and I think if we use same min_ovlp in all functions, r also cannot be MA_HT_SHORT_OVLP - ///so it does not matter we have ma_hit2arc or not - if (r >= 0 || r == MA_HT_QCONT || r == MA_HT_TCONT) - { - h->del = 0; - rLen++; - } - else - { - h->del = 1; - delete_single_edge(sources, coverage_cut, Get_tn(*h), Get_qn(*h)); - } - - - } - - if(rLen == 0) - { - (coverage_cut)[i].del = 1; - } - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } -} - - - - - -///a is the overlap vector, n is the length of overlap vector -///min_dp is used for coverage droping -///select reads with coverage >= min_dp -void ma_hit_sub(int min_dp, ma_hit_t_alloc* sources, long long n_read, uint64_t* readLen, -long long mini_overlap_length, ma_sub_t** coverage_cut) -{ - double startTime = Get_T(); - - (*coverage_cut) = (ma_sub_t*)malloc(sizeof(ma_sub_t)*n_read); - - uint64_t i, j, n_remained = 0; - kvec_t(uint32_t) b = {0,0,0}; - - ///all overlaps in vector a has been sorted by qns - ///so for overlaps of one reads, it must be contiguous - for (i = 0; i < (uint64_t)n_read; ++i) - { - if(min_dp <= 1) - { - (*coverage_cut)[i].s = 0; - (*coverage_cut)[i].e = readLen[i]; - (*coverage_cut)[i].del = 0; - ++n_remained; - continue; - } - - - kv_resize(uint32_t, b, sources[i].length); - b.n = 0; - for (j = 0; j < sources[i].length; j++) - { - if(sources[i].buffer[j].del) continue; - - uint32_t qs, qe; - qs = Get_qs(sources[i].buffer[j]); - qe = Get_qe(sources[i].buffer[j]); - kv_push(uint32_t, b, qs<<1); - kv_push(uint32_t, b, qe<<1|1); - } - - ///we can identify the qs and qe by the 0-th bit - ks_introsort_uint32_t(b.n, b.a); - ma_sub_t max, max2; - max.s = max.e = max.del = max2.s = max2.e = max2.del = 0; - int dp, start = 0; - ///max is the longest subregion, max2 is the second longest subregion - for (j = 0, dp = 0; j < b.n; ++j) - { - int old_dp = dp; - ///if a[j] is qe - if (b.a[j]&1) - { - --dp; - } - else - { - ++dp; - } - - /** - min_dp is the coverage drop threshold - there are two cases: - 1. old_dp = dp + 1 (b.a[j] is qe); 2. old_dp = dp - 1 (b.a[j] is qs); - if one read has multiple separate sub-regions with coverage >= min_dp, - does miniasm only select the longest one? - **/ - if (old_dp < min_dp && dp >= min_dp) ///old_dp < dp, b.a[j] is qs - { - ///case 2, a[j] is qs - start = b.a[j]>>1; - } - else if (old_dp >= min_dp && dp < min_dp) ///old_dp > min_dp, b.a[j] is qe - { - int len = (b.a[j]>>1) - start; - if (len > (int)(max.e - max.s)) - { - max2 = max; - max.s = start; - max.e = b.a[j]>>1; - } - else if (len > int(max2.e - max2.s)) - { - max2.s = start; - max2.e = b.a[j]>>1; - } - } - } - - - ///max.e - max.s is the - if (max.e - max.s > 0) - { - (*coverage_cut)[i].s = max.s; - (*coverage_cut)[i].e = max.e; - (*coverage_cut)[i].del = 0; - ++n_remained; - } - else - { - (*coverage_cut)[i].s = (*coverage_cut)[i].e = 0; - - (*coverage_cut)[i].del = 1; - } - } - - free(b.a); - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } -} - - - - -int boundary_verify(uint32_t x_interval_s, uint32_t x_interval_e, ma_hit_t* map, -char* x_buffer, char* y_buffer, All_reads* R_INF) -{ - uint32_t xs, ys, dir, x_id, y_id, x_interval_Len, y_interval_Len, y_interval_s, y_interval_e; - dir = (*map).rev; - xs = Get_qs((*map)); - x_id = Get_qn((*map)); - y_id = Get_tn((*map)); - long long yLen = Get_READ_LENGTH((*R_INF), y_id); - - if(dir == 1) - { - ys = yLen - (Get_te((*map)) - 1) - 1; - } - else - { - ys = Get_ts((*map)); - } - ///[x_interval_s, x_interval_e) - x_interval_Len = x_interval_e - x_interval_s; - - ///[y_interval_s, y_interval_e] - y_interval_s = (x_interval_s - xs) + ys; - if(y_interval_s >= yLen) - { - return 0; - } - y_interval_e = y_interval_s + x_interval_Len - 1; - if(y_interval_e >= yLen) - { - y_interval_e = yLen - 1; - } - - if(y_interval_e < y_interval_s) - { - return 0; - } - - y_interval_Len = y_interval_e - y_interval_s + 1; - - - if(y_interval_Len <= WINDOW) - { - return verify_single_window(y_interval_s, y_interval_e, ys, xs, y_id, x_id, - dir, y_buffer, x_buffer, R_INF); - } - else - { - - if(verify_single_window(y_interval_s, y_interval_s + WINDOW - 1, ys, xs, y_id, x_id, - dir, y_buffer, x_buffer, R_INF) == 0) - { - return 0; - } - - if(verify_single_window(y_interval_e - WINDOW + 1, y_interval_e, ys, xs, y_id, x_id, - dir, y_buffer, x_buffer, R_INF) == 0) - { - return 0; - } - - return 1; - } -} - - -void collect_sides_trio(ma_hit_t_alloc* paf, uint64_t rLen, ma_sub_t* max_left, ma_sub_t* max_right, -uint32_t trio_flag) -{ - long long j; - uint32_t qs, qe; - for (j = 0; j < paf->length; j++) - { - if(paf->buffer[j].del) continue; - - if(R_INF.trio_flag[Get_tn(paf->buffer[j])] == trio_flag) continue; - - qs = Get_qs(paf->buffer[j]); - qe = Get_qe(paf->buffer[j]); - - ///overlaps from left side - if(qs == 0) - { - if(qs < max_left->s) max_left->s = qs; - if(qe > max_left->e) max_left->e = qe; - } - - ///overlaps from right side - if(qe == rLen) - { - if(qs < max_right->s) max_right->s = qs; - if(qe > max_right->e) max_right->e = qe; - } - - ///note: if (qs == 0 && qe == rLen) - ///this overlap would be added to both b_left and b_right - ///that is what we want - } -} - - -void collect_contain_trio(ma_hit_t_alloc* paf1, ma_hit_t_alloc* paf2, uint64_t rLen, -ma_sub_t* max_left, ma_sub_t* max_right, float overlap_rate, uint32_t trio_flag) -{ - long long j, new_left_e, new_right_s; - new_left_e = max_left->e; - new_right_s = max_right->s; - uint32_t qs, qe; - ma_hit_t_alloc* paf; - - if(paf1 != NULL) - { - paf = paf1; - for (j = 0; j < paf->length; j++) - { - if(paf->buffer[j].del) continue; - - if(R_INF.trio_flag[Get_tn(paf->buffer[j])] == trio_flag) continue; - - qs = Get_qs(paf->buffer[j]); - qe = Get_qe(paf->buffer[j]); - ///check contained overlaps - if(qs != 0 && qe != rLen) - { - ///[qs, qe), [max_left.s, max_left.e) - if(qs < max_left->e && qe > max_left->e && max_left->e - qs > (overlap_rate * (qe -qs))) - { - ///if(qe > max_left->e) max_left->e = qe; - if(qe > max_left->e && qe > new_left_e) new_left_e = qe; - } - - ///[qs, qe), [max_right.s, max_right.e) - if(qs < max_right->s && qe > max_right->s && qe - max_right->s > (overlap_rate * (qe -qs))) - { - ///if(qs < max_right->s) max_right->s = qs; - if(qs < max_right->s && qs < new_right_s) new_right_s = qs; - } - } - } - } - - if(paf2 != NULL) - { - paf = paf2; - for (j = 0; j < paf->length; j++) - { - if(paf->buffer[j].del) continue; - - if(R_INF.trio_flag[Get_tn(paf->buffer[j])] == trio_flag) continue; - - qs = Get_qs(paf->buffer[j]); - qe = Get_qe(paf->buffer[j]); - ///check contained overlaps - if(qs != 0 && qe != rLen) - { - ///[qs, qe), [max_left.s, max_left.e) - if(qs < max_left->e && qe > max_left->e && max_left->e - qs > (overlap_rate * (qe -qs))) - { - ///if(qe > max_left->e) max_left->e = qe; - if(qe > max_left->e && qe > new_left_e) new_left_e = qe; - } - - ///[qs, qe), [max_right.s, max_right.e) - if(qs < max_right->s && qe > max_right->s && qe - max_right->s > (overlap_rate * (qe -qs))) - { - ///if(qs < max_right->s) max_right->s = qs; - if(qs < max_right->s && qs < new_right_s) new_right_s = qs; - } - } - } - } - - - max_left->e = new_left_e; - max_right->s = new_right_s; -} - - -void collect_sides(uint32_t rid, ma_hit_t_alloc* pafs, all_ul_t *x, uint64_t rLen, ma_sub_t* max_left, ma_sub_t* max_right, uint64_t ul_thres) -{ - long long j; - uint32_t qs, qe; - ma_hit_t_alloc *paf = (&pafs[rid]); - for (j = 0; j < paf->length; j++) - { - if(paf->buffer[j].del) continue; - - qs = Get_qs(paf->buffer[j]); - qe = Get_qe(paf->buffer[j]); - - - ///overlaps from left side - if(qs == 0) - { - if(qs < max_left->s) max_left->s = qs; - if(qe > max_left->e) max_left->e = qe; - } - - ///overlaps from right side - if(qe == rLen) - { - if(qs < max_right->s) max_right->s = qs; - if(qe > max_right->e) max_right->e = qe; - } - - ///note: if (qs == 0 && qe == rLen) - ///this overlap would be added to both b_left and b_right - ///that is what we want - } - - if(x) { - uint64_t *a = NULL, a_n, k; - uc_block_t *p = NULL; uint64_t cc = 0; - a = get_hifi2ul_list(x, rid, &a_n); - for (k = 0; k < a_n; k++) { - p = &(x->a[a[k]>>32].bb.a[(uint32_t)(a[k])]); - if(p->base||(!p->el)) continue; - qs = p->ts; qe = p->te;///note here is ts && te, instead of qs && qe - ///for UL, we only use overlaps which cover the whole HiFi read - if(qs == 0 && qe == rLen){ - cc++; - if(cc >= ul_thres) break; - } - } - if(cc >= ul_thres) { - max_left->s = 0; max_left->e = rLen; - max_right->s = 0; max_right->e = rLen; - } - } -} - -void collect_contain(ma_hit_t_alloc* paf1, ma_hit_t_alloc* paf2, uint64_t rLen, -ma_sub_t* max_left, ma_sub_t* max_right, float overlap_rate) -{ - long long j, new_left_e, new_right_s; - new_left_e = max_left->e; - new_right_s = max_right->s; - uint32_t qs, qe; - ma_hit_t_alloc* paf; - - if(paf1 != NULL) - { - paf = paf1; - for (j = 0; j < paf->length; j++) - { - if(paf->buffer[j].del) continue; - - qs = Get_qs(paf->buffer[j]); - qe = Get_qe(paf->buffer[j]); - ///check contained overlaps - if(qs != 0 && qe != rLen) - { - ///[qs, qe), [max_left.s, max_left.e) - if(qs < max_left->e && qe > max_left->e && max_left->e - qs > (overlap_rate * (qe -qs))) - { - ///if(qe > max_left->e) max_left->e = qe; - if(qe > max_left->e && qe > new_left_e) new_left_e = qe; - } - - ///[qs, qe), [max_right.s, max_right.e) - if(qs < max_right->s && qe > max_right->s && qe - max_right->s > (overlap_rate * (qe -qs))) - { - ///if(qs < max_right->s) max_right->s = qs; - if(qs < max_right->s && qs < new_right_s) new_right_s = qs; - } - } - } - } - - if(paf2 != NULL) - { - paf = paf2; - for (j = 0; j < paf->length; j++) - { - if(paf->buffer[j].del) continue; - - qs = Get_qs(paf->buffer[j]); - qe = Get_qe(paf->buffer[j]); - ///check contained overlaps - if(qs != 0 && qe != rLen) - { - ///[qs, qe), [max_left.s, max_left.e) - if(qs < max_left->e && qe > max_left->e && max_left->e - qs > (overlap_rate * (qe -qs))) - { - ///if(qe > max_left->e) max_left->e = qe; - if(qe > max_left->e && qe > new_left_e) new_left_e = qe; - } - - ///[qs, qe), [max_right.s, max_right.e) - if(qs < max_right->s && qe > max_right->s && qe - max_right->s > (overlap_rate * (qe -qs))) - { - ///if(qs < max_right->s) max_right->s = qs; - if(qs < max_right->s && qs < new_right_s) new_right_s = qs; - } - } - } - } - - max_left->e = new_left_e; - max_right->s = new_right_s; -} - - - -int intersection_check(ma_hit_t_alloc* paf, uint64_t rLen, uint32_t interval_s, uint32_t interval_e) -{ - long long j, cov = 0; - uint32_t qs, qe; - - for (j = 0; j < paf->length; j++) - { - qs = Get_qs(paf->buffer[j]); - qe = Get_qe(paf->buffer[j]); - ///[interval_s, interval_e) must be at least contained at one of the [qs, qe) - if(qs<=interval_s && qe>=interval_e) - { - cov++; - } - } - - return cov; -} - - -int intersection_check_by_base(ma_hit_t_alloc* paf, uint64_t rLen, uint32_t interval_s, uint32_t interval_e, -char* bq, char* bt) -{ - long long j; - uint32_t qs, qe; - - for (j = 0; j < paf->length; j++) { - if(paf->buffer[j].del) continue; - - qs = Get_qs(paf->buffer[j]); - qe = Get_qe(paf->buffer[j]); - ///[interval_s, interval_e) must be at least contained at one of the [qs, qe) - if(qs<=interval_s && qe>=interval_e) { - if((paf->buffer[j].el) || - (boundary_verify(interval_s, interval_e, &(paf->buffer[j]), bq, bt, &R_INF) == 0)) { - return 1; - } - } - } - - return 0; -} - -void print_overlaps(ma_hit_t_alloc* paf, long long rLen, long long interval_s, long long interval_e) -{ - long long j; - - fprintf(stderr, "left: \n"); - for (j = 0; j < paf->length; j++) - { - if(Get_qs(paf->buffer[j]) == 0) - { - fprintf(stderr, "?????? interval_s: %lld, interval_e: %lld, qn: %u, tn: %u, j: %lld, qs: %u, qe: %u, ts: %u, te: %u, dir: %u\n", - interval_s, interval_e, - Get_qn(paf->buffer[j]), Get_tn(paf->buffer[j]), - j, Get_qs(paf->buffer[j]), Get_qe(paf->buffer[j]), - Get_ts(paf->buffer[j]), Get_te(paf->buffer[j]), - paf->buffer[j].rev); - - fprintf(stderr, "%.*s\n", (int)Get_NAME_LENGTH(R_INF, Get_tn(paf->buffer[j])), - Get_NAME(R_INF, Get_tn(paf->buffer[j]))); - } - } - - fprintf(stderr, "right: \n"); - for (j = 0; j < paf->length; j++) - { - if(Get_qe(paf->buffer[j]) == rLen) - { - fprintf(stderr, "?????? interval_s: %lld, interval_e: %lld, qn: %u, tn: %u, j: %lld, qs: %u, qe: %u, ts: %u, te: %u, dir: %u\n", - interval_s, interval_e, - Get_qn(paf->buffer[j]), Get_tn(paf->buffer[j]), - j, Get_qs(paf->buffer[j]), Get_qe(paf->buffer[j]), - Get_ts(paf->buffer[j]), Get_te(paf->buffer[j]), - paf->buffer[j].rev); - - fprintf(stderr, "%.*s\n", (int)Get_NAME_LENGTH(R_INF, Get_tn(paf->buffer[j])), - Get_NAME(R_INF, Get_tn(paf->buffer[j]))); - } - } - - - fprintf(stderr, "middle: \n"); - for (j = 0; j < paf->length; j++) - { - if(Get_qs(paf->buffer[j]) != 0 && Get_qe(paf->buffer[j]) != rLen) - { - fprintf(stderr, "?????? interval_s: %lld, interval_e: %lld, qn: %u, tn: %u, j: %lld, qs: %u, qe: %u, ts: %u, te: %u, dir: %u\n", - interval_s, interval_e, - Get_qn(paf->buffer[j]), Get_tn(paf->buffer[j]), - j, Get_qs(paf->buffer[j]), Get_qe(paf->buffer[j]), - Get_ts(paf->buffer[j]), Get_te(paf->buffer[j]), - paf->buffer[j].rev); - - fprintf(stderr, "%.*s\n", (int)Get_NAME_LENGTH(R_INF, Get_tn(paf->buffer[j])), - Get_NAME(R_INF, Get_tn(paf->buffer[j]))); - } - } - -} - - -void detect_chimeric_reads(ma_hit_t_alloc* paf, long long n_read, uint64_t* readLen, -ma_sub_t* coverage_cut, float shift_rate, all_ul_t *x, uint64_t ul_thres) -{ - double startTime = Get_T(); - init_aux_table(); - long long i, rLen, n_simple_remove = 0, n_complex_remove = 0, n_complex_remove_real = 0; - uint32_t interval_s, interval_e; - ma_sub_t max_left, max_right; - kvec_t(char) b_q = {0,0,0}; - kvec_t(char) b_t = {0,0,0}; - for (i = 0; i < n_read; ++i) - { - coverage_cut[i].c = PRIMARY_LABLE; - rLen = readLen[i]; - - - max_left.s = max_right.s = rLen; - max_left.e = max_right.e = 0; - ///we just need to check UL alignment here as we only need UL which covers the whole HiFi read - collect_sides(i, paf, x, rLen, &max_left, &max_right, ul_thres); - ///collect_sides(&(rev_paf[i]), rLen, &max_left, &max_right); - ///that means this read is an end node - if(max_left.s == rLen || max_right.s == rLen) - { - continue; - } - collect_contain(&(paf[i]), NULL, rLen, &max_left, &max_right, 0.1); - ///collect_contain(&(paf[i]), &(rev_paf[i]), rLen, &max_left, &max_right, 0.1); - ////shift_rate should be (asm_opt.max_ov_diff_final*2) - ///this read is a normal read - if (max_left.e > max_right.s && (max_left.e - max_right.s >= rLen * shift_rate)) - { - continue; - } - ///simple chimeric reads - if(max_left.e <= max_right.s) - { - delete_all_edges(paf, coverage_cut, i); - n_simple_remove++; - continue; - } - - ///now max_left.e > max_right.s && max_left.e - max_right.s is small enough - //[interval_s, interval_e) - interval_s = max_right.s; - interval_e = max_left.e; - - /** - cov = 0; - cov += intersection_check(&(paf[i]), rLen, interval_s, interval_e); - cov += intersection_check(&(rev_paf[i]), rLen, interval_s, interval_e); - if(interval_e - interval_s < WINDOW && cov <= 2) - { - coverage_cut[i].del = 1; - paf[i].length = 0; - n_complex_remove_real++; - } - else**/ - { - kv_resize(char, b_q, WINDOW*4+20); - kv_resize(char, b_t, WINDOW*4+20); - if(intersection_check_by_base(&(paf[i]), rLen, interval_s, interval_e, b_q.a, b_t.a) - /**|| - intersection_check_by_base(&(rev_paf[i]), rLen, interval_s, interval_e, b_q.a, b_t.a)**/) - { - delete_all_edges(paf, coverage_cut, i); - n_complex_remove_real++; - } - } - - n_complex_remove++; - } - - free(b_q.a); - free(b_t.a); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2f s, n_simple_remove: %lld, n_complex_remove: %lld/%lld\n\n", - __func__, Get_T()-startTime, n_simple_remove, n_complex_remove_real, n_complex_remove); - } -} - - -void ma_hit_cut(ma_hit_t_alloc* sources, long long n_read, uint64_t* readLen, -long long mini_overlap_length, ma_sub_t** coverage_cut) -{ - double startTime = Get_T(); - size_t i, j; - ma_hit_t* p; - ma_sub_t* rq; - ma_sub_t* rt; - long long rLen = 0; - for (i = 0; i < (uint64_t)n_read; ++i) - { - rLen = 0; - for (j = 0; j < sources[i].length; j++) - { - ///this is a overlap - p = &(sources[i].buffer[j]); - if(p->del) continue; - - rq = &((*coverage_cut)[Get_qn(*p)]); - rt = &((*coverage_cut)[Get_tn(*p)]); - ///if any of target read and the query read has no enough coverage - if (rq->del || rt->del) continue; - int qs, qe, ts, te; - - - - - ///target and query in different strand - if (p->rev) - { - /** - here is an example in different strand: - - (te) (rt->e) (rt->s) (ts) - | | | | - target ---------------------------------------------------- - ------------------------------------------- query - qs qe - **/ - qs = p->te < rt->e? Get_qs(*p): Get_qs(*p) + (p->te - rt->e); - qe = p->ts > rt->s? p->qe : p->qe - (rt->s - p->ts); - ts = p->qe < rq->e? p->ts : p->ts + (p->qe - rq->e); - te = Get_qs(*p) > rq->s? p->te : p->te - (rq->s - Get_qs(*p)); - } - else ///target and query in same strand - { - /** - note: ts is the targe start in this overlap, - while rt->s is the high coverage start in the whole target (not only in this overlap) - so this line is to normalize the qs in quey to high coverage region - **/ - //(rt->s - p->ts) is the offset - qs = p->ts > rt->s? Get_qs(*p): Get_qs(*p) + (rt->s - p->ts); - //(p->te - rt->e) is the offset - qe = p->te < rt->e? p->qe : p->qe - (p->te - rt->e); - //(rq->s - Get_qs(*p) is the offset - ts = Get_qs(*p) > rq->s? p->ts : p->ts + (rq->s - Get_qs(*p)); - //(p->qe - rq->e) is the offset - te = p->qe < rq->e? p->te : p->te - (p->qe - rq->e); - } - - - - //cut by self coverage - //and normalize the qs, qe, ts, te by rq->s and rt->e - qs = ((uint32_t)qs > rq->s? qs : rq->s) - rq->s; - qe = ((uint32_t)qe < rq->e? qe : rq->e) - rq->s; - ts = ((uint32_t)ts > rt->s? ts : rt->s) - rt->s; - te = ((uint32_t)te < rt->e? te : rt->e) - rt->s; - - if (qe - qs >= mini_overlap_length && te - ts >= mini_overlap_length) - { - ///p->qns = p->qns>>32<<32 | qs; - p->qns = p->qns>>32; - p->qns = p->qns << 32; - p->qns = p->qns | qs; - - p->qe = qe; - p->ts = ts; - p->te = te; - p->del = 0; - rLen++; - } - else - { - p->del = 1; - delete_single_edge(sources, (*coverage_cut), Get_tn(*p), Get_qn(*p)); - ///delete_all_edges(paf, coverage_cut, i); - } - } - - if(rLen == 0) - { - (*coverage_cut)[i].del = 1; - } - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - -} - - - -/********************************** - * Filter short potential unitigs * - **********************************/ -#define ASG_ET_MERGEABLE 0 -#define ASG_ET_TIP 1 -#define ASG_ET_MULTI_OUT 2 -#define ASG_ET_MULTI_NEI 3 - -static inline int asg_is_utg_end(const asg_t *g, uint32_t v, uint64_t *lw) -{ - - /** - .............................. - . w1--------------- . - . w2-------------- . - . w3-------------- .--->asg_arc_a(g, v^1) - . w4------------- . - . w5------------ . - .............................. - v--------------- - .............................. - . w1--------------- . - . w2-------------- . - . w3-------------- .--->asg_arc_a(g, v) - . w4------------- . - . w5------------ . - .............................. - !!!!!note here the graph has already been cleaned by transitive reduction, so idealy: - - ......................... - . w1--------------- .--->asg_arc_a(g, v^1) - ......................... - v--------------- - ......................... - . w5--------------- .--->asg_arc_a(g, v) - ......................... - - **/ - ///v^1 is the another direction of v - uint32_t w, nv, nw, nw0, nv0 = asg_arc_n(g, v^1); - int i, i0 = -1; - asg_arc_t *aw, *av = asg_arc_a(g, v^1); - - ///if this arc has not been deleted - for (i = nv = 0; i < (int)nv0; ++i) - if (!av[i].del) i0 = i, ++nv; - - ///end without any out-degree - if (nv == 0) return ASG_ET_TIP; // tip - - /** - since the graph has already been cleaned by transitive reduction, - w1 and w2 should not be overlapped with each other - that mean v has mutiple in-edges, and each of them is not overlapped with others - ......................... - . w2--------------- .--->asg_arc_a(g, v^1) - . w1--------------- . - ......................... - v--------------- - - **/ - if (nv > 1) return ASG_ET_MULTI_OUT; // multiple outgoing arcs - - - - - /** - * ///until here, nv == 1 - note the graph has already been cleaned by transitive reduction, - ......................... - . w1--------------- .--->asg_arc_a(g, v^1) - ......................... - v--------------- - **/ - /** - p->ul: |____________31__________|__________1___________|______________32_____________| - qn direction of overlap length of this node (not overlap length) - (based on query) - p->v : |___________31___________|__________1___________| - tn reverse direction of overlap - (based on target) - p->ol: overlap length - **/ - ///until here, nv == 1 - if (lw) *lw = av[i0].ul<<32 | av[i0].v; - /** - p->ul: |____________31__________|__________1___________|______________32_____________| - qns direction of overlap length of this node (not overlap length) - (based on query) - p->v : |___________31___________|__________1___________| - tns reverse direction of overlap - (based on target) - p->ol: overlap length - **/ - w = av[i0].v ^ 1; - nw0 = asg_arc_n(g, w); - aw = asg_arc_a(g, w); - for (i = nw = 0; i < (int)nw0; ++i) - if (!aw[i].del) ++nw; - - - /** - note nw is at least 1, since we have v - nw > 1 means - ......................... - . av[i0].v^1---------- .--->asg_arc_a(g, v^1) - ......................... - v--------------- - w--------------- - z--------------- - asg_arc_a(av[i0].v^1) is the (v, w, z), and v, w, z are not overlapped with each others - **/ - if (nw != 1) return ASG_ET_MULTI_NEI; - - /** - * nw == 1 means - note the graph has already been cleaned by transitive reduction, - ......................... - . w1--------------- .--->asg_arc_a(g, v^1) - ......................... - v--------------- - ......................... - . w5--------------- .--->asg_arc_a(g, v) - ......................... - - **/ - return ASG_ET_MERGEABLE; -} - - -int asg_extend(const asg_t *g, uint32_t v, int max_ext, asg64_v *a) -{ - int ret; - uint64_t lw; - a->n = 0; - kv_push(uint64_t, *a, v); - do { - /** - test (v) and (v^1), - if the out-degrees of both (v) and (v^1) are 1, ret == 0 - **/ - ret = asg_is_utg_end(g, v^1, &lw); - /** - #define ASG_ET_MERGEABLE 0 - #define ASG_ET_TIP 1 - #define ASG_ET_MULTI_OUT 2 - #define ASG_ET_MULTI_NEI 3 - **/ - if (ret != 0) break; - kv_push(uint64_t, *a, lw); - /** - ret == 0 means: - v^1 and is the only prefix of (uint32_t)lw, - and (uint32_t)lw is the only prefix of v^1 - **/ - - v = (uint32_t)lw; - } while (--max_ext > 0); - return ret; -} - - -static inline int asg_is_single_edge(const asg_t *g, uint32_t v, uint32_t start_node) -{ - - /** - .............................. - . w1--------------- . - . w2-------------- . - . w3-------------- .--->asg_arc_a(g, v^1) - . w4------------- . - . w5------------ . - .............................. - v--------------- - .............................. - . w1--------------- . - . w2-------------- . - . w3-------------- .--->asg_arc_a(g, v) - . w4------------- . - . w5------------ . - .............................. - !!!!!note here the graph has already been cleaned by transitive reduction, so idealy: - - ......................... - . w1--------------- .--->asg_arc_a(g, v^1) - ......................... - v--------------- - ......................... - . w5--------------- .--->asg_arc_a(g, v) - ......................... - - **/ - ///v^1 is the another direction of v - uint32_t nv, nv0 = asg_arc_n(g, v^1); - int i; - asg_arc_t *av = asg_arc_a(g, v^1); - - int flag = 0; - ///if this arc has not been deleted - for (i = nv = 0; i < (int)nv0; ++i) - { - ///if (!av[i].del) - { - ++nv; - if(av[i].v>>1 == start_node) - { - flag = 1; - } - } - } - - if(flag == 0) - { - fprintf(stderr, "****ERROR\n"); - } - - return nv; -} - -void debug_info_of_specfic_node(const char* name, asg_t *g, R_to_U* ruIndex, const char* command) -{ - fprintf(stderr, "\n\n\n"); - uint32_t v, n_vtx = g->n_seq * 2, queryLen = strlen(name), flag = 0, contain_rId, is_Unitig; - for (v = 0; v < n_vtx; ++v) - { - if(queryLen == Get_NAME_LENGTH(R_INF, (v>>1)) && memcmp(name, Get_NAME(R_INF, (v>>1)), Get_NAME_LENGTH(R_INF, (v>>1))) == 0) - { - if(flag == 0) fprintf(stderr, "\nafter %s\n", command); - fprintf(stderr, "****************graph ref_read: %.*s, id: %u, dir: %u****************\n", - (int)Get_NAME_LENGTH(R_INF, (v>>1)), Get_NAME(R_INF, (v>>1)), v>>1, v&1); - if(g->seq[v>>1].del) - { - get_R_to_U(ruIndex, (v>>1), &contain_rId, &is_Unitig); - if(contain_rId != (uint32_t)-1 && is_Unitig != 1) - { - fprintf(stderr, "read is deleted as a contained read by: %.*s\n contain_rId: %u, del: %u\n", - (int)Get_NAME_LENGTH(R_INF, contain_rId), Get_NAME(R_INF, contain_rId), contain_rId, g->seq[contain_rId].del); - } - else - { - fprintf(stderr, "read has already been deleted.\n"); - } - - return; - } - - asg_arc_t *av = asg_arc_a(g, v); - uint32_t i, nv = asg_arc_n(g, v); - for (i = 0; i < nv; ++i) - { - fprintf(stderr, "target: %.*s, el: %u, strong: %u, ol: %u, del: %u\n", - (int)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), - Get_NAME(R_INF, (av[i].v>>1)), - av[i].el, av[i].strong, av[i].ol, av[i].del); - } - flag = 1; - } - } -} - - -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) -{ - double startTime = Get_T(); - size_t i, j; - asg_t *g; - ///just calloc - 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; - asg_arc_t t, *p; - const ma_hit_t *h = &(sources[i].buffer[j]); - if(h->del) continue; - - //high coverage region [sub[qn].e, sub[qn].s) in query - int ql = coverage_cut[Get_qn(*h)].e - coverage_cut[Get_qn(*h)].s; - //high coverage region [sub[qn].e, sub[qn].s) in target - int tl = coverage_cut[Get_tn(*h)].e - coverage_cut[Get_tn(*h)].s; - r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - /** - #define MA_HT_INT (-1) - #define MA_HT_QCONT (-2) - #define MA_HT_TCONT (-3) - #define MA_HT_SHORT_OVLP (-4) - the short overlaps and the overlaps with contain reads have already been removed - here we should have overhang - so r should always >= 0 - **/ - if (r >= 0) - { - ///push node? - p = asg_arc_pushp(g); - *p = t; - } - else - { - fprintf(stderr, "error\n"); - } - } - } - - asg_cleanup(g); - g->r_seq = g->n_seq; - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - return g; -} - -void prt_specific_overlap(ma_hit_t_alloc *src, uint64_t qn, uint64_t tn, const char *cmd) -{ - ma_hit_t *h = NULL; int64_t idx = -1, k; - if(tn != ((uint64_t)-1)) { - idx = get_specific_overlap(&(src[qn]), qn, tn); h = &(src[qn].buffer[idx]); - fprintf(stderr, "%s::idx::%ld[M::%s::] qn::%u, tn::%u, del::%u, bl::%u, ml::%u\n", cmd, idx, __func__, - Get_qn(*h), Get_tn(*h), h->del, h->bl, h->ml); - } else { - for (k = 0; k < src[qn].length; k++) { - h = &(src[qn].buffer[k]); - fprintf(stderr, "%s::idx::%ld[M::%s::] qn::%u, tn::%u, del::%u, bl::%u, ml::%u\n", cmd, idx, __func__, - Get_qn(*h), Get_tn(*h), h->del, h->bl, h->ml); - } - } -} - -asg_t *ma_sg_gen_ul(ma_hit_t_alloc* sources, int64_t n_read, const ma_sub_t *coverage_cut, -R_to_U* ruIndex, int64_t max_hang, int64_t min_ovlp, int64_t ul_occ) -{ - int64_t i, j, r; asg_arc_t t, *p; const ma_hit_t *h; - asg_t *g = asg_init(); - for (i = 0; i < n_read; ++i) { - 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; - } - CALLOC(g->seq_vis, (g->n_seq<<1)); - - // prt_specific_overlap(sources, 22233, 22235, "+"); - // prt_specific_overlap(sources, 22235, 22233, "+"); - // fprintf(stderr, "[M::%s::] n_read::%ld\n", __func__, n_read); - recover_contain_g(g, sources, ruIndex, max_hang, min_ovlp, ul_occ); - - for (i = 0; i < n_read; ++i) { - if(g->seq[i].del) continue; - for (j = 0; j < sources[i].length; j++) { - h = &(sources[i].buffer[j]); - // if((Get_qn(*h) == 22233 && Get_tn(*h) == 22235)|| - // (Get_qn(*h) == 22235 && Get_tn(*h) == 22233)) { - // fprintf(stderr, "[M::%s::] qn::%u, tn::%u, del::%u, bl::%u\n", __func__, Get_qn(*h), Get_tn(*h), - // h->del, h->bl); - // } - if(h->del) continue; - r = ma_hit2arc(h, (coverage_cut[Get_qn(*h)].e-coverage_cut[Get_qn(*h)].s), - (coverage_cut[Get_tn(*h)].e-coverage_cut[Get_tn(*h)].s), max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - assert(r >= 0); - p = asg_arc_pushp(g); *p = t; - p->ou = ((h->bl>OU_MASK)?OU_MASK:h->bl); - // if(Get_qn(*h) == 10498 && Get_tn(*h) == 10505) { - // fprintf(stderr, "[M::%s::] qn::%u, tn::%u, p->ou::%u, h->bl::%u\n", __func__, - // Get_qn(*h), Get_tn(*h), p->ou, h->bl); - // } - } - } - - asg_cleanup(g); - asg_symm(g); - g->r_seq = g->n_seq; - return g; -} - - - - -// pop bubbles from vertex v0; the graph MJUST BE symmetric: if u->v present, v'->u' must be present as well -//note!!!!!!!! here we don't exculde the deleted edges -static uint64_t asg_bub_finder_with_del_advance(asg_t *g, uint32_t v0, int max_dist, buf_t *b) -{ - uint32_t i, n_pending = 0; - uint64_t n_pop = 0; - ///if this node has been deleted - if (g->seq[v0>>1].del) return 0; // already deleted - ///asg_arc_n(n0) - if ((uint32_t)g->idx[v0] < 2) return 0; // no bubbles - ///S saves nodes with all incoming edges visited - b->S.n = b->T.n = b->b.n = b->e.n = 0; - ///for each node, b->a saves all related information - b->a[v0].c = b->a[v0].d = 0; - ///b->S is the nodes with all incoming edges visited - kv_push(uint32_t, b->S, v0); - - do { - ///v is a node that all incoming edges have been visited - ///d is the distance from v0 to v - uint32_t v = kv_pop(b->S), d = b->a[v].d, c = b->a[v].c; - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - ///why we have this assert? - /****************************may have bugs********************************/ - ///assert(nv > 0); - /****************************may have bugs********************************/ - - ///all out-edges of v - for (i = 0; i < nv; ++i) { // loop through v's neighbors - /** - p->ul: |____________31__________|__________1___________|______________32_____________| - qn direction of overlap length of this node (not overlap length) - (in the view of query) - p->v : |___________31___________|__________1___________| - tn reverse direction of overlap - (in the view of target) - p->ol: overlap length - **/ - uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l - binfo_t *t = &b->a[w]; - ///that means there is a circle, directly terminate the whole bubble poping - if (w == v0) - { - //fprintf(stderr, "n_pop error1\n"); - goto pop_reset; - } - - ///if this edge has been deleted - /****************************may have bugs********************************/ - ///if (av[i].del) continue; - /****************************may have bugs********************************/ - - ///push the edge - kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); - - ///find a too far path? directly terminate the whole bubble poping - if (d + l > (uint32_t)max_dist) - { - //fprintf(stderr, "n_pop error2\n"); - break; // too far - } - - - - if (t->s == 0) { // this vertex has never been visited - kv_push(uint32_t, b->b, w); // save it for revert - ///t->p means the in-node of w is v - ///t->s = 1 means w has been visited - ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) - t->p = v, t->s = 1, t->d = d + l, t->c = c + 1; - ///incoming edges of w - t->r = count_out_with_del(g, w^1); - ++n_pending; - } else { // visited before - ///c seems the max weight of node - if (c + 1 > t->c || (c + 1 == t->c && d + l > t->d)) t->p = v; - if (c + 1 > t->c) t->c = c + 1; - ///update len(v0->w) - if (d + l < t->d) t->d = d + l; // update dist - } - /****************************may have bugs********************************/ - ///assert(t->r > 0); - /****************************may have bugs********************************/ - //if all incoming edges of w have visited - //push it to b->S - if (--(t->r) == 0) { - uint32_t x = asg_arc_n(g, w); - if (x) kv_push(uint32_t, b->S, w); - else kv_push(uint32_t, b->T, w); // a tip - --n_pending; - } - } - ///if i < nv, that means (d + l > max_dist) - if (i < nv || b->S.n == 0) - { - ///fprintf(stderr, "n_pop error3\n"); - goto pop_reset; - } - - } while (b->S.n > 1 || n_pending); - ///asg_bub_backtrack(g, v0, b); - ///n_pop = 1 | (uint64_t)b->T.n<<32; - n_pop = 1; -pop_reset: - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - binfo_t *t = &b->a[b->b.a[i]]; - t->s = t->c = t->d = 0; - } - ///fprintf(stderr, "n_pop: %d\n", n_pop); - return n_pop; -} - - -// pop bubbles from vertex v0; the graph MJUST BE symmetric: if u->v present, v'->u' must be present as well -//note!!!!!!!! here we don't exculde the deleted edges -static uint64_t asg_bub_finder_without_del_advance(asg_t *g, uint32_t v0, int max_dist, -buf_t *b) -{ - uint32_t i, n_pending = 0; - uint64_t n_pop = 0; - ///if this node has been deleted - if (g->seq[v0>>1].del) return 0; // already deleted - ///asg_arc_n(n0) - if ((uint32_t)g->idx[v0] < 2) return 0; // no bubbles - if(count_out_without_del(g, v0) < 2) return 0; // no bubbles - - - ///S saves nodes with all incoming edges visited - b->S.n = b->T.n = b->b.n = b->e.n = 0; - ///for each node, b->a saves all related information - b->a[v0].c = b->a[v0].d = 0; - ///b->S is the nodes with all incoming edges visited - kv_push(uint32_t, b->S, v0); - - do { - ///v is a node that all incoming edges have been visited - ///d is the distance from v0 to v - uint32_t v = kv_pop(b->S), d = b->a[v].d, c = b->a[v].c; - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - ///why we have this assert? - /****************************may have bugs********************************/ - ///assert(nv > 0); - /****************************may have bugs********************************/ - - ///all out-edges of v - for (i = 0; i < nv; ++i) { // loop through v's neighbors - /** - p->ul: |____________31__________|__________1___________|______________32_____________| - qn direction of overlap length of this node (not overlap length) - (in the view of query) - p->v : |___________31___________|__________1___________| - tn reverse direction of overlap - (in the view of target) - p->ol: overlap length - **/ - uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l - binfo_t *t = &b->a[w]; - - ///if this edge has been deleted - /****************************may have bugs********************************/ - if (av[i].del) continue; - /****************************may have bugs********************************/ - - ///that means there is a circle, directly terminate the whole bubble poping - if (w == v0) - { - //fprintf(stderr, "n_pop error1\n"); - goto pop_reset; - } - - - ///push the edge - kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); - - ///find a too far path? directly terminate the whole bubble poping - if (d + l > (uint32_t)max_dist) - { - //fprintf(stderr, "n_pop error2\n"); - break; // too far - } - - - - if (t->s == 0) { // this vertex has never been visited - kv_push(uint32_t, b->b, w); // save it for revert - ///t->p means the in-node of w is v - ///t->s = 1 means w has been visited - ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) - t->p = v, t->s = 1, t->d = d + l, t->c = c + 1; - ///incoming edges of w - t->r = count_out_without_del(g, w^1); - ++n_pending; - } else { // visited before - ///c seems the max weight of node - if (c + 1 > t->c || (c + 1 == t->c && d + l > t->d)) t->p = v; - if (c + 1 > t->c) t->c = c + 1; - ///update len(v0->w) - if (d + l < t->d) t->d = d + l; // update dist - } - /****************************may have bugs********************************/ - ///assert(t->r > 0); - /****************************may have bugs********************************/ - //if all incoming edges of w have visited - //push it to b->S - if (--(t->r) == 0) { - uint32_t x = asg_arc_n(g, w); - if (x) kv_push(uint32_t, b->S, w); - else kv_push(uint32_t, b->T, w); // a tip - --n_pending; - } - } - ///if i < nv, that means (d + l > max_dist) - if (i < nv || b->S.n == 0) - { - ///fprintf(stderr, "n_pop error3\n"); - goto pop_reset; - } - - } while (b->S.n > 1 || n_pending); - ///asg_bub_backtrack(g, v0, b); - ///n_pop = 1 | (uint64_t)b->T.n<<32; - n_pop = 1; -pop_reset: - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - binfo_t *t = &b->a[b->b.a[i]]; - t->s = t->c = t->d = 0; - } - ///fprintf(stderr, "n_pop: %d\n", n_pop); - return n_pop; -} - - -// pop bubbles from vertex v0; the graph MJUST BE symmetric: if u->v present, v'->u' must be present as well -//note!!!!!!!! here we don't exculde the deleted edges -static uint64_t asg_bub_end_finder_with_del_advance(asg_t *g, uint32_t* v_Ns, uint32_t occ, -int max_dist, buf_t *b, uint32_t exculde_init, uint32_t exclude_node, uint32_t* sink) -{ - uint32_t i, j, n_pending = 0; - uint64_t n_pop = 0; - ///S saves nodes with all incoming edges visited - b->S.n = b->T.n = b->b.n = b->e.n = 0; - for (j = 0; j < occ; j++) - { - ///if this node has been deleted - if (g->seq[v_Ns[j]>>1].del) return 0; // already deleted - ///for each node, b->a saves all related information - b->a[v_Ns[j]].c = b->a[v_Ns[j]].d = 0; - ///b->S is the nodes with all incoming edges visited - kv_push(uint32_t, b->S, (v_Ns[j]<<1)|exculde_init); - } - - - - do { - ///v is a node that all incoming edges have been visited - ///d is the distance from v0 to v - uint32_t v = kv_pop(b->S), f = v & (uint32_t)1; - v = v >> 1; - uint32_t d = b->a[v].d, c = b->a[v].c; - - - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - - ///all out-edges of v - for (i = 0; i < nv; ++i) { // loop through v's neighbors - /** - p->ul: |____________31__________|__________1___________|______________32_____________| - qn direction of overlap length of this node (not overlap length) - (in the view of query) - p->v : |___________31___________|__________1___________| - tn reverse direction of overlap - (in the view of target) - p->ol: overlap length - **/ - uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l - binfo_t *t = &b->a[w]; - - for (j = 0; j < occ; j++) - { - if(w == v_Ns[j]) goto pop_reset; - } - - - - if(f && (exclude_node) == (w)) continue; - - ///if (av[i].del) continue; - - ///push the edge - kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); - - ///find a too far path? directly terminate the whole bubble poping - if (d + l > (uint32_t)max_dist) - { - break; // too far - } - - - - if (t->s == 0) { // this vertex has never been visited - kv_push(uint32_t, b->b, w); // save it for revert - ///t->p means the in-node of w is v - ///t->s = 1 means w has been visited - ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) - t->p = v, t->s = 1, t->d = d + l, t->c = c + 1; - ///incoming edges of w - t->r = count_out_with_del(g, w^1); - ///t->r = count_out_without_del(g, w^1); - ++n_pending; - } else { // visited before - ///c seems the max weight of node - if (c + 1 > t->c || (c + 1 == t->c && d + l > t->d)) t->p = v; - if (c + 1 > t->c) t->c = c + 1; - ///update len(v0->w) - if (d + l < t->d) t->d = d + l; // update dist - } - /****************************may have bugs********************************/ - ///assert(t->r > 0); - /****************************may have bugs********************************/ - //if all incoming edges of w have visited - //push it to b->S - if (--(t->r) == 0) { - uint32_t x = asg_arc_n(g, w); - //if (x) kv_push(uint32_t, b->S, w); - if (x) kv_push(uint32_t, b->S, w<<1); - else kv_push(uint32_t, b->T, w); // a tip - --n_pending; - } - } - ///if i < nv, that means (d + l > max_dist) - if (i < nv || b->S.n == 0) - { - goto pop_reset; - } - - } while (b->S.n > 1 || n_pending); - - (*sink) = b->S.a[0]>>1; - ///asg_bub_backtrack(g, v0, b); - ///n_pop = 1 | (uint64_t)b->T.n<<32; - n_pop = 1; -pop_reset: - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - binfo_t *t = &b->a[b->b.a[i]]; - t->s = t->c = t->d = 0; - } - return n_pop; -} - - - - -int if_node_exist(uint32_t* nodes, uint32_t length, uint32_t query) -{ - uint32_t i; - for (i = 0; i < length; ++i) - { - if((nodes[i]>>1) == query) - { - return 1; - } - } - - return 0; -} - - - - -long long single_edge_length(asg_t *g, uint32_t begNode, uint32_t endNode, long long edgeLen) -{ - - uint32_t v = begNode; - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - long long rLen = 0; - - while (rLen < edgeLen && nv == 1) - { - rLen++; - if((av[0].v>>1) == endNode) - { - return rLen; - } - - if(asg_is_single_edge(g, av[0].v, v>>1) != 1) - { - return -1; - } - - v = av[0].v; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - } - - return -1; - -} - -uint32_t detect_single_path(asg_t *g, uint32_t begNode, uint32_t* endNode, long long* Len, buf_t* b) -{ - - uint32_t v = begNode; - uint32_t nv, rnv; - asg_arc_t *av; - (*Len) = 0; - - - while (1) - { - (*Len)++; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - (*endNode) = v; - - if(b) kv_push(uint32_t, b->b, v>>1); - - if(nv == 0) - { - return END_TIPS; - } - - if(nv == 2) - { - return TWO_OUTPUT; - } - - if(nv > 2) - { - return MUL_OUTPUT; - } - - ///up to here, nv=1 - ///rnv must >= 1 - rnv = asg_is_single_edge(g, av[0].v, v>>1); - v = av[0].v; - (*endNode) = v; - if(rnv == 2) - { - (*Len)++; - if(b) kv_push(uint32_t, b->b, v>>1); - return TWO_INPUT; - } - - if(rnv > 2) - { - (*Len)++; - if(b) kv_push(uint32_t, b->b, v>>1); - return MUL_INPUT; - } - - - if((v>>1) == (begNode>>1)) - { - return LOOP; - } - } - - return LONG_TIPS; -} - -int detect_bubble_end(asg_t *g, uint32_t begNode1, uint32_t begNode2, uint32_t* endNode, -long long* minLen, buf_t* b) -{ - uint32_t e1, e2; - long long l1, l2; - - if(detect_single_path(g, begNode1, &e1, &l1, b) == TWO_INPUT - && - detect_single_path(g, begNode2, &e2, &l2, b) == TWO_INPUT) - { - if(e1 == e2) - { - (*endNode) = e1; - (*minLen) = (l1 <= l2)? l1: l2; - return 1; - } - } - - return 0; -} - - -int detect_simple_bubble(asg_t *g, uint32_t begNode, uint32_t* endNode, long long* minLen, buf_t* b) -{ - uint32_t e1, e2; - long long l1, l2; - - if(asg_arc_n(g, begNode) != 2) - { - return 0; - } - - if(asg_is_single_edge(g, asg_arc_a(g, begNode)[0].v, begNode>>1)!=1 - || - asg_is_single_edge(g, asg_arc_a(g, begNode)[1].v, begNode>>1)!=1) - { - return 0; - } - - if(b) kv_push(uint32_t, b->b, begNode>>1); - - - - - if(detect_single_path(g, asg_arc_a(g, begNode)[0].v, &e1, &l1, b) == TWO_INPUT - && - detect_single_path(g, asg_arc_a(g, begNode)[1].v, &e2, &l2, b) == TWO_INPUT) - { - if(e1 == e2) - { - (*endNode) = e1; - (*minLen) = (l1 <= l2)? l1: l2; - (*minLen)++; - return 1; - } - } - - return 0; -} - - -uint32_t detect_single_path_with_single_bubbles(asg_t *g, uint32_t begNode, uint32_t* endNode, -long long* Len, buf_t* b, uint32_t max_ext) -{ - - uint32_t v = begNode; - uint32_t nv, rnv; - asg_arc_t *av; - long long bLen; - long long pre_b_n = 0; - (*Len) = 0; - - - - while (1) - { - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - (*endNode) = v; - (*Len)++; - - - if((*Len) > max_ext) - { - return LONG_TIPS_UNDER_MAX_EXT; - } - - - if(b) kv_push(uint32_t, b->b, v>>1); - - - - if(nv == 0) - { - return END_TIPS; - } - - if(nv == 2) - { - - - if(b) pre_b_n = b->b.n; - if(!detect_simple_bubble(g, v, &v, &bLen, b)) - { - if(b) b->b.n = pre_b_n; - return TWO_OUTPUT; - } - - (*Len) = (*Len) + bLen - 2; - continue; - } - - if(nv > 2) - { - return MUL_OUTPUT; - } - - ///up to here, nv=1 - ///rnv must >= 1 - rnv = asg_is_single_edge(g, av[0].v, v>>1); - v = av[0].v; - (*endNode) = v; - if(rnv == 2) - { - if(b) kv_push(uint32_t, b->b, v>>1); - (*Len)++; - return TWO_INPUT; - } - - if(rnv > 2) - { - if(b) kv_push(uint32_t, b->b, v>>1); - (*Len)++; - return MUL_INPUT; - } - - if((v>>1) == (begNode>>1)) - { - return LOOP; - } - } - - return LONG_TIPS; -} - -int detect_bubble_end_with_bubbles(asg_t *g, uint32_t begNode1, uint32_t begNode2, -uint32_t* endNode, long long* minLen, buf_t* b) -{ - uint32_t e1, e2; - long long l1, l2; - - if(detect_single_path_with_single_bubbles(g, begNode1, &e1, &l1, b, (uint32_t)-1) == TWO_INPUT - && - detect_single_path_with_single_bubbles(g, begNode2, &e2, &l2, b, (uint32_t)-1) == TWO_INPUT) - { - if(e1 == e2) - { - (*endNode) = e1; - (*minLen) = (l1 <= l2)? l1: l2; - return 1; - } - } - - return 0; -} - - -int detect_mul_bubble_end_with_bubbles(asg_t *g, uint32_t* begs, uint32_t occ, -uint32_t* endNode, long long* minLen, buf_t* b) -{ - uint32_t e, flag, e_s; - long long l, i, l_s; - - if(occ < 1) return 0; - - flag = detect_single_path_with_single_bubbles(g, begs[0], &e, &l, b, (uint32_t)-1); - - if(flag == TWO_INPUT || flag == MUL_INPUT) - { - e_s = e; - l_s = l; - } - else - { - return 0; - } - - - - for (i = 1; i < occ; i++) - { - flag = detect_single_path_with_single_bubbles(g, begs[i], &e, &l, b, (uint32_t)-1); - if(flag == TWO_INPUT || flag == MUL_INPUT) - { - if(e != e_s) return 0; - if(l < l_s) l_s = l; - } - else - { - return 0; - } - } - - if(asg_arc_n(g, e_s^1) == occ) - { - (*endNode) = e_s; - (*minLen) = l_s; - return 1; - } - - return 0; -} - - -int detect_bubble_with_bubbles(asg_t *g, uint32_t begNode, uint32_t* endNode, long long* minLen, -buf_t* b, uint32_t max_ext) -{ - uint32_t e1, e2; - long long l1, l2; - - if(asg_arc_n(g, begNode) != 2) - { - return 0; - } - - if(asg_is_single_edge(g, asg_arc_a(g, begNode)[0].v, begNode>>1)!=1 - || - asg_is_single_edge(g, asg_arc_a(g, begNode)[1].v, begNode>>1)!=1) - { - return 0; - } - - if(b) kv_push(uint32_t, b->b, begNode>>1); - - - if(detect_single_path_with_single_bubbles(g, asg_arc_a(g, begNode)[0].v, &e1, &l1, b, max_ext) == TWO_INPUT) - { - b->b.n--; - if(detect_single_path_with_single_bubbles(g, asg_arc_a(g, begNode)[1].v, &e2, &l2, b, max_ext) == TWO_INPUT) - { - b->b.n--; - if(e1 == e2) - { - (*endNode) = e1; - (*minLen) = (l1 <= l2)? l1: l2; - (*minLen)++; - return 1; - } - } - } - - return 0; -} - -int test_triangular_exact(asg_t *g, uint32_t* nodes, uint32_t length, -uint32_t startNode, uint32_t endNode, int max_dist, buf_t* bub) -{ - - uint32_t i, v, w; - ///int flag0, flag1, node; - int n_reduced = 0, todel; - long long NodeLen_first[3]; - long long NodeLen_second[3]; - - uint32_t Ns_first[3]; - uint32_t Ns_second[3]; - - - for (i = 0; i < length; ++i) - { - v = nodes[i]; - - if((v>>1) == (startNode>>1) || (v>>1) == (endNode>>1)) - { - continue; - } - - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - if(nv != 2) - { - continue; - } - if(av[0].v == av[1].v) - { - continue; - } - /**********************test first node************************/ - NodeLen_first[0] = NodeLen_first[1] = NodeLen_first[2] = -1; - if(asg_is_single_edge(g, av[0].v, v>>1) <= 2 && asg_is_single_edge(g, av[1].v, v>>1) <= 2) - { - NodeLen_first[asg_is_single_edge(g, av[0].v, v>>1)] = 0; - NodeLen_first[asg_is_single_edge(g, av[1].v, v>>1)] = 1; - } - ///one node has one out-edge, another node has two out-edges - if(NodeLen_first[1] == -1 || NodeLen_first[2] == -1) - { - continue; - } - /**********************test first node************************/ - - ///if the potiential edge has already been removed - if(av[NodeLen_first[2]].del == 1) - { - continue; - } - - /**********************test second node************************/ - w = av[NodeLen_first[2]].v^1; - asg_arc_t *aw = asg_arc_a(g, w); - uint32_t nw = asg_arc_n(g, w); - if(nw != 2) - { - fprintf(stderr, "error\n"); - } - NodeLen_second[0] = NodeLen_second[1] = NodeLen_second[2] = -1; - if(asg_is_single_edge(g, aw[0].v, w>>1) <= 2 && asg_is_single_edge(g, aw[1].v, w>>1) <= 2) - { - NodeLen_second[asg_is_single_edge(g, aw[0].v, w>>1)] = 0; - NodeLen_second[asg_is_single_edge(g, aw[1].v, w>>1)] = 1; - } - ///one node has one out-edge, another node has two out-edges - if(NodeLen_second[1] == -1 || NodeLen_second[2] == -1) - { - continue; - } - - /**********************test second node************************/ - - if(if_node_exist(nodes, length, (w>>1)) && ((w>>1) != (endNode>>1))) - { - - uint32_t convex1 = 0, convex2 = 0, f1, f2; - long long l1 = 0, l2 = 0; - todel = 0; - f1 = detect_bubble_end_with_bubbles(g, av[0].v, av[1].v, &convex1, &l1, NULL); - f2 = detect_bubble_end_with_bubbles(g, aw[0].v, aw[1].v, &convex2, &l2, NULL); - if(f1 && f2) - { - if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1)) && - ((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) - { - if(l1 <= min_thres || l2 <= min_thres) - { - continue; - } - - todel = 1; - } - } - else if(f1) - { - if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1))) - { - if(l1 <= min_thres) - { - continue; - } - - todel = 1; - } - } - else if(f2) - { - if(((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) - { - if(l2 <= min_thres) - { - continue; - } - - todel = 1; - } - } - - - if(todel == 0) - { - if(!f1) - { - Ns_first[0] = av[0].v; Ns_first[1] = av[1].v; - f1 = asg_bub_end_finder_with_del_advance(g, Ns_first, 2, max_dist, - bub, 0, (uint32_t)-1, &convex1); - l1 = min_thres + 10; - } - - if(!f2) - { - Ns_second[0] = aw[0].v; Ns_second[1] = aw[1].v; - f2 = asg_bub_end_finder_with_del_advance(g, Ns_second, 2, max_dist, - bub, 0, (uint32_t)-1, &convex2); - l2 = min_thres + 10; - } - - - - - - if(f1 && f2) - { - if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1)) && - ((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) - { - if(l1 <= min_thres || l2 <= min_thres) - { - continue; - } - - todel = 1; - } - } - else if(f1) - { - if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1))) - { - if(l1 <= min_thres) - { - continue; - } - - todel = 1; - } - } - else if(f2) - { - if(((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) - { - if(l2 <= min_thres) - { - continue; - } - - todel = 1; - } - } - - } - - - if(todel) - { - av[NodeLen_first[2]].del = 1; - ///remove the reverse direction - asg_arc_del(g, av[NodeLen_first[2]].v^1, av[NodeLen_first[2]].ul>>32^1, 1); - n_reduced++; - } - - } - - } - - return n_reduced; -} - - - - - -int find_single_link(asg_t *g, uint32_t link_beg, int linkLen, uint32_t* link_end) -{ - uint32_t v, w; - v = link_beg^1; - uint32_t nv, nw; - asg_arc_t *av; - int edgeLen = 0; - - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - if(nv != 1) - { - return 0; - } - v = av[0].v; - - while (edgeLen < linkLen) - { - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - if(nv != 1) - { - return 0; - } - - w = v^1; - nw = asg_arc_n(g, w); - if(nw == 2) - { - (*link_end) = w; - return 1; - } - else if(nw > 2) - { - return 0; - } - - v = av[0].v; - edgeLen++; - } - - - return 0; -} - - -int if_edge_exist(asg_arc_t* edges, uint32_t length, uint32_t query) -{ - uint32_t i; - for (i = 0; i < length; ++i) - { - if((edges[i].v>>1) == query) - { - return 1; - } - } - - return 0; -} - -int test_quadangular_with_addition_node(asg_t *g, uint32_t* nodes, uint32_t length, -uint32_t addition_node_length) -{ - - uint32_t i, v, w; - int flag, occ_v_0, occ_v_1, occ_w_0, occ_w_1; - int n_reduced = 0; - uint32_t v_out2_node, w_out2_node; - uint32_t cut_edge_v, cut_edge_w; - for (i = 0; i < length; ++i) - { - v = nodes[i]; - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - if(nv != 1) - { - continue; - } - /**********************test first node************************/ - flag = asg_is_single_edge(g, av[0].v, v>>1); - if(flag != 2) - { - continue; - } - /**********************test first node************************/ - - if(!find_single_link(g, v, addition_node_length, &w)) - { - continue; - } - v = av[0].v^1; - ///up to now, v and w is the node what we want - asg_arc_t *aw = asg_arc_a(g, w); - uint32_t nw = asg_arc_n(g, w); - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - if(nv!=2 || nw != 2) - { - fprintf(stderr, "error\n"); - } - - if(!if_node_exist(nodes, length, (v>>1))) - { - continue; - } - if(!if_node_exist(nodes, length, (w>>1))) - { - continue; - } - /**********************for v************************/ - occ_v_0 = asg_is_single_edge(g, av[0].v, v>>1); - occ_v_1 = asg_is_single_edge(g, av[1].v, v>>1); - if(occ_v_0 == occ_v_1) - { - continue; - } - if(occ_v_0 < 1 || occ_v_0 > 2) - { - continue; - } - if(occ_v_1 < 1 || occ_v_1 > 2) - { - continue; - } - - if(occ_v_0 == 2) - { - v_out2_node = av[0].v^1; - cut_edge_v = 0; - } - else - { - v_out2_node = av[1].v^1; - cut_edge_v = 1; - } - if(!if_node_exist(nodes, length, (v_out2_node>>1))) - { - continue; - } - /**********************for v************************/ - - /**********************for w************************/ - occ_w_0 = asg_is_single_edge(g, aw[0].v, w>>1); - occ_w_1 = asg_is_single_edge(g, aw[1].v, w>>1); - if(occ_w_0 == occ_w_1) - { - continue; - } - if(occ_w_0 < 1 || occ_w_0 > 2) - { - continue; - } - if(occ_w_1 < 1 || occ_w_1 > 2) - { - continue; - } - - if(occ_w_0 == 2) - { - w_out2_node = aw[0].v^1; - cut_edge_w = 0; - } - else - { - w_out2_node = aw[1].v^1; - cut_edge_w = 1; - } - if(!if_node_exist(nodes, length, (w_out2_node>>1))) - { - continue; - } - /**********************for w************************/ - - - if(!if_edge_exist(asg_arc_a(g, w_out2_node), asg_arc_n(g, w_out2_node), (v_out2_node>>1))) - { - continue; - } - - if(!if_edge_exist(asg_arc_a(g, v_out2_node), asg_arc_n(g, v_out2_node), (w_out2_node>>1))) - { - continue; - } - - - av[cut_edge_v].del = 1; - ///remove the reverse direction - asg_arc_del(g, av[cut_edge_v].v^1, av[cut_edge_v].ul>>32^1, 1); - - aw[cut_edge_w].del = 1; - ///remove the reverse direction - asg_arc_del(g, aw[cut_edge_w].v^1, aw[cut_edge_w].ul>>32^1, 1); - - - n_reduced++; - } - - return n_reduced; -} - -int test_triangular_addition_exact(asg_t *g, uint32_t* nodes, uint32_t length, -uint32_t startNode, uint32_t endNode, int max_dist, buf_t* bub) -{ - - uint32_t i, j, v, w; - ///int flag0, flag1, node; - int n_reduced = 0, todel; - uint32_t Nodes1[2]={0}; - uint32_t Nodes2[2]={0}; - - uint32_t Ns_first[2]={0}; - uint32_t Ns_second[2]={0}; - - - - for (i = 0; i < length; ++i) - { - v = nodes[i]; - - if((v>>1) == (startNode>>1) || (v>>1) == (endNode>>1)) - { - continue; - } - - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - if(nv != 1) - { - continue; - } - if(asg_is_single_edge(g, av[0].v, v>>1) != 2) - { - continue; - } - - - w = v^1; - asg_arc_t *aw = asg_arc_a(g, w); - uint32_t nw = asg_arc_n(g, w); - if(nw != 1) - { - continue; - } - if(asg_is_single_edge(g, aw[0].v, w>>1) != 2) - { - continue; - } - - if((av[0].v>>1) == (aw[0].v>>1)) - { - continue; - } - - - - Nodes1[0] = av[0].v^1; - Nodes2[0] = aw[0].v^1; - - - for(j = 0; j < 2; j++) - { - if((asg_arc_a(g, Nodes1[0])[j].v>>1)!= (v>>1)) - { - Nodes1[1] = asg_arc_a(g, Nodes1[0])[j].v^1; - } - } - - for(j = 0; j < 2; j++) - { - if((asg_arc_a(g, Nodes2[0])[j].v>>1)!= (v>>1)) - { - Nodes2[1] = asg_arc_a(g, Nodes2[0])[j].v^1; - } - } - - if(asg_arc_n(g, Nodes1[1]) != 1 || asg_arc_n(g, Nodes2[1]) != 1) - { - continue; - } - - if((Nodes1[1]>>1) == (Nodes2[1]>>1)) - { - continue; - } - - - - if(asg_arc_a(g, Nodes1[1])[0].el == 0 || asg_arc_a(g, Nodes2[1])[0].el == 0) - { - continue; - } - - uint32_t convex1, convex2, f1, f2; - long long l1, l2; - todel = 0; - - if((Nodes1[0]^1) == (startNode^1) || (Nodes1[0]^1) == endNode) - { - continue; - } - if((Nodes2[1]^1) == (startNode^1) || (Nodes2[1]^1) == endNode) - { - continue; - } - - f1 = detect_bubble_end_with_bubbles(g, Nodes1[0]^1, Nodes2[1]^1, &convex1, &l1, NULL); - - - if((Nodes2[0]^1) == (startNode^1) || (Nodes2[0]^1) == endNode) - { - continue; - } - if((Nodes1[1]^1) == (startNode^1) || (Nodes1[1]^1) == endNode) - { - continue; - } - - f2 = detect_bubble_end_with_bubbles(g, Nodes2[0]^1, Nodes1[1]^1, &convex2, &l2, NULL); - - - if(f1 && f2) - { - if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1)) && - ((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) - { - if(l1 <= min_thres || l2 <= min_thres) - { - continue; - } - - todel = 1; - } - } - else if(f1) - { - if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1))) - { - if(l1 <= min_thres) - { - continue; - } - - todel = 1; - } - } - else if(f2) - { - if(((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) - { - if(l2 <= min_thres) - { - continue; - } - - todel = 1; - } - } - - if(todel == 0) - { - if(!f1) - { - Ns_first[0] = Nodes1[0]^1; Ns_first[1] = Nodes2[1]^1; - f1 = asg_bub_end_finder_with_del_advance(g, Ns_first, 2, max_dist, - bub, 0, (uint32_t)-1, &convex1); - l1 = min_thres + 10; - } - - if(!f2) - { - Ns_second[0] = Nodes2[0]^1; Ns_second[1] = Nodes1[1]^1; - f2 = asg_bub_end_finder_with_del_advance(g, Ns_second, 2, max_dist, - bub, 0, (uint32_t)-1, &convex2); - l2 = min_thres + 10; - } - - if(f1 && f2) - { - if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1)) && - ((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) - { - if(l1 <= min_thres || l2 <= min_thres) - { - continue; - } - - todel = 1; - } - } - else if(f1) - { - if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1))) - { - if(l1 <= min_thres) - { - continue; - } - - todel = 1; - } - } - else if(f2) - { - if(((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) - { - if(l2 <= min_thres) - { - continue; - } - - todel = 1; - } - } - - } - - - if(todel) - { - if(av[0].el == 0 || aw[0].el == 0) - { - av[0].del = 1; - asg_arc_del(g, av[0].v^1, av[0].ul>>32^1, 1); - - aw[0].del = 1; - asg_arc_del(g, aw[0].v^1, aw[0].ul>>32^1, 1); - - n_reduced++; - } - } - } - - return n_reduced; -} - -int asg_arc_del_triangular_advance(asg_t *g, long long max_dist) -{ - double startTime = Get_T(); - ///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, n_reduced_a = 0; - - - if (!g->is_symm) asg_symm(g); - - - buf_t b; - memset(&b, 0, sizeof(buf_t)); - b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - - - buf_t bub; - memset(&bub, 0, sizeof(buf_t)); - bub.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - - for (v = 0; v < n_vtx; ++v) - { - uint32_t nv = asg_arc_n(g, v); - if (g->seq[v>>1].del) - { - continue; - } - - if(nv < 2) - { - continue; - } - - - ///if this is a bubble - if(asg_bub_finder_with_del_advance(g, v, max_dist, &b) == 1) - { - n_reduced += test_triangular_exact(g, b.b.a, b.b.n, v, b.S.a[0], max_dist, &bub); - n_reduced_a += test_triangular_addition_exact(g, b.b.a, b.b.n, v, b.S.a[0],max_dist, &bub); - } - - } - - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - free(bub.a); free(bub.S.a); free(bub.T.a); free(bub.b.a); free(bub.e.a); - - if (n_reduced + n_reduced_a) { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d/%d triangular/triangular_a overlaps\n", - __func__, n_reduced, n_reduced_a); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - return n_reduced + n_reduced_a; -} - - - - - - -int check_if_cross(asg_t *g, uint32_t v) -{ - uint32_t N_list[5] = {0}; - if (g->seq[v>>1].del) return 0; - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - if(nv != 2) return 0; - if(asg_is_single_edge(g, av[0].v, v>>1) != 2 || asg_is_single_edge(g, av[1].v, v>>1) != 2) - { - return 0; - } - if(av[0].v == av[1].v) - { - return 0; - } - N_list[0] = v; - N_list[1] = av[0].v^1; - N_list[2] = av[1].v^1; - if(asg_arc_n(g, N_list[0]) != 2 || - asg_arc_n(g, N_list[1]) != 2 || - asg_arc_n(g, N_list[2]) != 2 ) - { - return 0; - } - - if(asg_arc_a(g, N_list[1])[0].v == asg_arc_a(g, N_list[1])[1].v) - { - return 0; - } - - if(asg_arc_a(g, N_list[2])[0].v == asg_arc_a(g, N_list[2])[1].v) - { - return 0; - } - - if(asg_arc_a(g, N_list[1])[0].v == (N_list[0]^1)) - { - N_list[3] = asg_arc_a(g, N_list[1])[1].v^1; - } - else if(asg_arc_a(g, N_list[1])[1].v == (N_list[0]^1)) - { - N_list[3] = asg_arc_a(g, N_list[1])[0].v^1; - } - - if(asg_arc_a(g, N_list[2])[0].v == (N_list[0]^1)) - { - N_list[4] = asg_arc_a(g, N_list[2])[1].v^1; - } - else if(asg_arc_a(g, N_list[2])[1].v == (N_list[0]^1)) - { - N_list[4] = asg_arc_a(g, N_list[2])[0].v^1; - } - - if(N_list[3] != N_list[4]) - { - return 0; - } - - if(asg_arc_n(g, N_list[0]) != 2 || - asg_arc_n(g, N_list[1]) != 2 || - asg_arc_n(g, N_list[2]) != 2 || - asg_arc_n(g, N_list[3]) != 2) - { - return 0; - } - - - uint32_t convex1, convex2, f1, f2; - long long l1, l2; - l1 = l2 = 0; - int todel = 0; - - f1 = detect_bubble_end_with_bubbles(g, N_list[0]^1, N_list[3]^1, &convex1, &l1, NULL); - f2 = detect_bubble_end_with_bubbles(g, N_list[1]^1, N_list[2]^1, &convex2, &l2, NULL); - - if(f1 && f2)///full bubble - { - if(l1 > min_thres && l2 > min_thres) - { - todel = 1; - } - } - else if(f1)//semi bubble - { - if(l1 > min_thres) - { - todel = 1; - } - } - else if(f2)//semi bubble - { - if(l2 > min_thres) - { - todel = 1; - } - } - - - return todel; -} - - - - -typedef struct { - int threadID; - int thread_num; - int check_cross; - asg_t *g; -} para_for_simple_bub; - -void* asg_arc_identify_simple_bubbles_pthread(void* arg) -{ - int thr_ID = ((para_for_simple_bub*)arg)->threadID; - int thr_num = ((para_for_simple_bub*)arg)->thread_num; - asg_t *g = ((para_for_simple_bub*)arg)->g; - int check_cross = ((para_for_simple_bub*)arg)->check_cross; - ///the reason is that each read has two direction (query->target, target->query) - - uint32_t v, w, n_vtx = g->n_seq * 2; - buf_t b; - memset(&b, 0, sizeof(buf_t)); - long long l, i; - ///for (v = 0; v < n_vtx; ++v) - for (v = thr_ID; v < n_vtx; v = v + thr_num) - { - if (g->seq[v>>1].del) continue; - - b.b.n = 0; - - if(g->seq_vis[v] != 1) - { - ///if(detect_bubble_with_bubbles(g, v, &w, &l, &b, (uint32_t)-1)) - if(detect_bubble_with_bubbles(g, v, &w, &l, &b, SMALL_BUBBLE_SIZE)) - { - for (i = 0; i < (long long)b.b.n; i++) - { - if(b.b.a[i] != (v>>1) && b.b.a[i] != (w>>1)) - { - g->seq_vis[b.b.a[i]<<1] = 1; - g->seq_vis[(b.b.a[i]<<1) + 1] = 1; - } - } - g->seq_vis[v] = 1; - g->seq_vis[w^1] = 1; - } - } - - if(check_cross == 1 && check_if_cross(g, v)) - { - g->seq_vis[v] = 2; - } - } - free(b.b.a); - - free(arg); - - return NULL; -} - -int asg_arc_identify_simple_bubbles_multi_back(asg_t *g, int check_cross) -{ - double startTime = Get_T(); - memset(g->seq_vis, 0, g->n_seq*2*sizeof(uint8_t)); - - pthread_t *_r_threads; - - _r_threads = (pthread_t *)malloc(sizeof(pthread_t)*asm_opt.thread_num); - - int i = 0; - - for (i = 0; i < asm_opt.thread_num; i++) - { - para_for_simple_bub* arg = (para_for_simple_bub*)malloc(sizeof(*arg)); - arg->g = g; - arg->thread_num = asm_opt.thread_num; - arg->threadID = i; - arg->check_cross = check_cross; - - pthread_create(_r_threads + i, NULL, asg_arc_identify_simple_bubbles_pthread, (void*)arg); - } - - - for (i = 0; in_seq * 2; - long long nodes, bub_nodes, cross_nodes; - bub_nodes = nodes = cross_nodes = 0; - for (v = 0; v < n_vtx; ++v) - { - if (g->seq[v>>1].del) continue; - nodes++; - if(g->seq_vis[v] == 1) bub_nodes++; - if(g->seq_vis[v] == 2) cross_nodes++; - } - - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return bub_nodes+cross_nodes; -} - -uint64_t asg_bub_pop1_label(asg_t *g, uint32_t v0, uint64_t max_dist, buf_s_t *b); -static void bubble_identify_worker(void *_data, long eid, int tid) -{ - bub_label_t *buf = (bub_label_t*)_data; - buf_s_t *b = &(buf->b[tid]); - uint32_t v = eid, i; - asg_t *g = buf->g; - if(g->seq[v>>1].del) return; - if(asg_arc_n(g, v) < 2 || get_real_length(g, v, NULL) < 2) return; - - if(g->seq_vis[v] != 1 && asg_bub_pop1_label(g, v, buf->bub_dist, b)) - { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (i = 0; i < b->b.n; i++) - { - if(b->b.a[i]==v || b->b.a[i]==b->S.a[0]) continue; - g->seq_vis[b->b.a[i]] = 1; - g->seq_vis[b->b.a[i]^1] = 1; - } - g->seq_vis[v] = 1; - g->seq_vis[b->S.a[0]^1] = 1; - } - - if(buf->check_cross == 1 && g->seq_vis[v] == 0 && check_if_cross(g, v)) - { - g->seq_vis[v] = 2; - } -} - -uint64_t get_s_bub_pop_max_dist_advance(asg_t *g, buf_s_t *b); -int asg_arc_identify_simple_bubbles_multi(asg_t *g, bub_label_t* x, int check_cross) -{ - double startTime = Get_T(); - memset(g->seq_vis, 0, g->n_seq*2*sizeof(uint8_t)); - uint64_t bub_dist = get_s_bub_pop_max_dist_advance(g, &(x->b[0])); - ///fprintf(stderr, "+++[M::%s] takes %0.2f s, bub_dist: %lu\n\n", __func__, Get_T()-startTime, bub_dist); - // startTime = Get_T(); - - reset_bub_label_t(x, g, bub_dist, check_cross); - kt_for(x->n_thres, bubble_identify_worker, x, g->n_seq<<1); - uint32_t v, n_vtx = g->n_seq<<1; - long long nodes, bub_nodes, cross_nodes; - bub_nodes = nodes = cross_nodes = 0; - for (v = 0; v < n_vtx; ++v) - { - if (g->seq[v>>1].del) continue; - nodes++; - if(g->seq_vis[v] == 1) bub_nodes++; - if(g->seq_vis[v] == 2) cross_nodes++; - } - ///fprintf(stderr, "---[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return bub_nodes+cross_nodes; -} - -int check_small_bubble(asg_t *g, uint32_t begNode, uint32_t v, uint32_t w, -long long* vLen, long long* wLen, uint32_t* endNode) -{ - uint32_t nv = asg_arc_n(g, v); - uint32_t nw = asg_arc_n(g, w); - - asg_arc_t *av = asg_arc_a(g, v); - asg_arc_t *aw = asg_arc_a(g, w); - if(nv != 1 || nw != 1) - { - return 0; - } - - ///first node - ///nv must be 1 - if(asg_is_single_edge(g, av[0].v, v>>1) == 2) - { - uint32_t vv; - vv = av[0].v^1; - - if( - asg_is_single_edge(g, asg_arc_a(g, vv)[0].v, vv>>1) == 1 - && - asg_is_single_edge(g, asg_arc_a(g, vv)[1].v, vv>>1) == 1 - ) - { - ///walk along first path - long long pLen1; - pLen1 = single_edge_length(g, asg_arc_a(g, vv)[0].v, begNode>>1, 1000); - - ///walk along first path - long long pLen2; - pLen2 = single_edge_length(g, asg_arc_a(g, vv)[1].v, begNode>>1, 1000); - - - - if(pLen1 >= 0 && pLen2 >= 0) - { - if(((asg_arc_a(g, vv)[0].v) == (v^1)) && pLen1 == 1) - { - (*vLen) = pLen1; - (*wLen) = pLen2; - } - else if(((asg_arc_a(g, vv)[1].v) == (v^1)) && pLen2 == 1) - { - (*vLen) = pLen2; - (*wLen) = pLen1; - } - else - { - fprintf(stderr, "error\n"); - } - ///(*endNode) = vv>>1; - (*endNode) = vv; - return 1; - } - - } - } - - - ///second node - ///nw must be 1 - if(asg_is_single_edge(g, aw[0].v, w>>1) == 2) - { - uint32_t ww; - ww = aw[0].v^1; - - if( - asg_is_single_edge(g, asg_arc_a(g, ww)[0].v, ww>>1) == 1 - && - asg_is_single_edge(g, asg_arc_a(g, ww)[1].v, ww>>1) == 1 - ) - { - ///walk along first path - long long pLen1; - pLen1 = single_edge_length(g, asg_arc_a(g, ww)[0].v, begNode>>1, 1000); - - ///walk along first path - long long pLen2; - pLen2 = single_edge_length(g, asg_arc_a(g, ww)[1].v, begNode>>1, 1000); - - if(pLen1 >= 0 && pLen2 >= 0) - { - if(((asg_arc_a(g, ww)[0].v) == (w^1)) && pLen1 == 1) - { - (*wLen) = pLen1; - (*vLen) = pLen2; - } - else if(((asg_arc_a(g, ww)[1].v) == (w^1)) && pLen2 == 1) - { - (*wLen) = pLen2; - (*vLen) = pLen1; - } - else - { - fprintf(stderr, "error\n"); - } - - //(*endNode) = ww>>1; - (*endNode) = ww; - - return 1; - } - } - } - - return 0; - -} - - -int test_single_node_bubble(asg_t *g, uint32_t* nodes, uint32_t length, -uint32_t startNode, uint32_t endNode) -{ - - uint32_t i, v, w; - uint32_t vEnd; - int flag0, flag1; - int n_reduced = 0; - long long Len[2], longLen; - long long longLen_thres = 4; - for (i = 0; i < length; ++i) - { - v = nodes[i]; - - if((v>>1) == (startNode>>1) || (v>>1) == (endNode>>1)) - { - continue; - } - - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - if(nv != 2) - { - continue; - } - - - flag0 = asg_is_single_edge(g, av[0].v, v>>1); - flag1 = asg_is_single_edge(g, av[1].v, v>>1); - if(flag0 != 1 || flag1 != 1) - { - continue; - } - - if(check_small_bubble(g, v, av[0].v, av[1].v, &(Len[0]), &(Len[1]), &vEnd)) - { - - if(if_node_exist(nodes, length, vEnd>>1) && ((vEnd>>1) != (endNode>>1))) - { - - if(Len[0] == 1 && Len[1] != 1) - { - w = av[0].v; - longLen = Len[1]; - - /****************************may have bugs********************************/ - if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) - { - // fprintf(stderr, "w>>1: %u, beg: %u, end: %u\n", - // w>>1, startNode>>1, endNode>>1); - asg_seq_del(g, w>>1); - n_reduced++; - }///up to here w is exactly overlapped in both directions - else if(longLen >= longLen_thres) - { - if(av[0].el == 1 && av[1].el == 1 - && - asg_arc_a(g, vEnd)[0].el == 1 && asg_arc_a(g, vEnd)[1].el == 1) - { - asg_seq_del(g, w>>1); - n_reduced++; - } - } - - /****************************may have bugs********************************/ - - } - else if(Len[0] != 1 && Len[1] == 1) - { - w = av[1].v; - longLen = Len[0]; - - /****************************may have bugs********************************/ - if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) - { - // fprintf(stderr, "w>>1: %u, beg: %u, end: %u\n", - // w>>1, startNode>>1, endNode>>1); - asg_seq_del(g, w>>1); - n_reduced++; - }///up to here w is exactly overlapped in both directions - else if(longLen >= longLen_thres) - { - if(av[0].el == 1 && av[1].el == 1 - && - asg_arc_a(g, vEnd)[0].el == 1 && asg_arc_a(g, vEnd)[1].el == 1) - { - asg_seq_del(g, w>>1); - n_reduced++; - } - } - /****************************may have bugs********************************/ - } - else if(Len[0] == 1 && Len[1] == 1) - { - w = av[0].v; - flag0 = asg_arc_a(g, w)[0].el + asg_arc_a(g, w^1)[0].el; - w = av[1].v; - flag1 = asg_arc_a(g, w)[0].el + asg_arc_a(g, w^1)[0].el; - ///>=2 means this is an exact overlap - if(flag0 < 2 && flag1 >= 2) - { - w = av[0].v; - - /****************************may have bugs********************************/ - if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) - { - // fprintf(stderr, "w>>1: %u, beg: %u, end: %u\n", - // w>>1, startNode>>1, endNode>>1); - asg_seq_del(g, w>>1); - n_reduced++; - } - /****************************may have bugs********************************/ - } - - if(flag0 >= 2 && flag1 < 2) - { - w = av[1].v; - - /****************************may have bugs********************************/ - if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) - { - // fprintf(stderr, "w>>1: %u, beg: %u, end: %u\n", - // w>>1, startNode>>1, endNode>>1); - asg_seq_del(g, w>>1); - n_reduced++; - } - /****************************may have bugs********************************/ - } - } - else - { - fprintf(stderr, "error\n"); - } - - } - } - - } - - return n_reduced; -} - - -int test_single_node_bubble_directly(asg_t *g, uint32_t v, long long longLen_thres, ma_hit_t_alloc* sources) -{ - uint32_t w, vEnd; - int flag0, flag1; - int n_reduced = 0; - long long Len[2], longLen; - ///long long longLen_thres = 4; - - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - if(nv != 2) - { - return 0; - } - - - flag0 = asg_is_single_edge(g, av[0].v, v>>1); - flag1 = asg_is_single_edge(g, av[1].v, v>>1); - if(flag0 != 1 || flag1 != 1) - { - return 0; - } - - if(check_small_bubble(g, v, av[0].v, av[1].v, &(Len[0]), &(Len[1]), &vEnd)) - { - if(Len[0] == 1 && Len[1] != 1) - { - w = av[0].v; - longLen = Len[1]; - - /****************************may have bugs********************************/ - ///if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) - if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0 || sources[w>>1].is_abnormal == 1) - { - asg_seq_del(g, w>>1); - n_reduced++; - }///up to here w is exactly overlapped in both directions - else if(longLen >= longLen_thres) - { - if(av[0].el == 1 && av[1].el == 1 - && - asg_arc_a(g, vEnd)[0].el == 1 && asg_arc_a(g, vEnd)[1].el == 1) - { - asg_seq_del(g, w>>1); - n_reduced++; - } - } - - /****************************may have bugs********************************/ - - } - else if(Len[0] != 1 && Len[1] == 1) - { - w = av[1].v; - longLen = Len[0]; - - /****************************may have bugs********************************/ - ///if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) - if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0 || sources[w>>1].is_abnormal == 1) - { - asg_seq_del(g, w>>1); - n_reduced++; - }///up to here w is exactly overlapped in both directions - else if(longLen >= longLen_thres) - { - if(av[0].el == 1 && av[1].el == 1 - && - asg_arc_a(g, vEnd)[0].el == 1 && asg_arc_a(g, vEnd)[1].el == 1) - { - asg_seq_del(g, w>>1); - n_reduced++; - } - } - /****************************may have bugs********************************/ - } - else if(Len[0] == 1 && Len[1] == 1) - { - flag0 = sources[av[0].v>>1].is_abnormal; - flag1 = sources[av[1].v>>1].is_abnormal; - - if(flag0 == 1 && flag1 == 0) - { - asg_seq_del(g, av[0].v>>1); - n_reduced++; - } - else if(flag0 == 0 && flag1 == 1) - { - asg_seq_del(g, av[1].v>>1); - n_reduced++; - } - else - { - w = av[0].v; - flag0 = asg_arc_a(g, w)[0].el + asg_arc_a(g, w^1)[0].el; - w = av[1].v; - flag1 = asg_arc_a(g, w)[0].el + asg_arc_a(g, w^1)[0].el; - ///>=2 means this is an exact overlap - if(flag0 < 2 && flag1 >= 2) - { - w = av[0].v; - - /****************************may have bugs********************************/ - if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) - { - asg_seq_del(g, w>>1); - n_reduced++; - } - /****************************may have bugs********************************/ - } - - if(flag0 >= 2 && flag1 < 2) - { - w = av[1].v; - - /****************************may have bugs********************************/ - if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) - { - asg_seq_del(g, w>>1); - n_reduced++; - } - /****************************may have bugs********************************/ - } - } - } - - } - return n_reduced; -} - - -int asg_arc_del_single_node_directly(asg_t *g, long long longLen_thres, ma_hit_t_alloc* sources) -{ - double startTime = Get_T(); - ///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; - for (v = 0; v < n_vtx; ++v) - { - uint32_t nv = asg_arc_n(g, v); - if (g->seq[v>>1].del) - { - continue; - } - - if(nv != 2) - { - continue; - } - - n_reduced += test_single_node_bubble_directly(g, v, longLen_thres, sources); - } - - - if (n_reduced) { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d small bubbles\n", __func__, n_reduced); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - return n_reduced; -} - - - -int test_cross(asg_t *g, uint32_t* nodes, uint32_t length, -uint32_t startNode, uint32_t endNode) -{ - uint32_t a1, a2; - uint32_t N_list[5] = {0}; - uint32_t i, v; - int flag0, flag1; - int n_reduced = 0; - for (i = 0; i < length; ++i) - { - v = nodes[i]; - - if((v>>1) == (startNode>>1) || (v>>1) == (endNode>>1)) - { - continue; - } - - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - if(nv != 2) - { - continue; - } - if(av[0].v == av[1].v) - { - continue; - } - flag0 = asg_is_single_edge(g, av[0].v, v>>1); - flag1 = asg_is_single_edge(g, av[1].v, v>>1); - - if(flag0 != 2 || flag1 != 2) - { - continue; - } - - - N_list[0] = v; - N_list[1] = av[0].v^1; - N_list[2] = av[1].v^1; - - if(asg_arc_n(g, N_list[0]) != 2 || - asg_arc_n(g, N_list[1]) != 2 || - asg_arc_n(g, N_list[2]) != 2 ) - { - continue; - } - - if(asg_arc_a(g, N_list[1])[0].v == asg_arc_a(g, N_list[1])[1].v) - { - continue; - } - - if(asg_arc_a(g, N_list[2])[0].v == asg_arc_a(g, N_list[2])[1].v) - { - continue; - } - - - if(asg_arc_a(g, N_list[1])[0].v == (N_list[0]^1)) - { - N_list[3] = asg_arc_a(g, N_list[1])[1].v^1; - } - else if(asg_arc_a(g, N_list[1])[1].v == (N_list[0]^1)) - { - N_list[3] = asg_arc_a(g, N_list[1])[0].v^1; - } - else - { - fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__); - } - - if(asg_arc_a(g, N_list[2])[0].v == (N_list[0]^1)) - { - N_list[4] = asg_arc_a(g, N_list[2])[1].v^1; - } - else if(asg_arc_a(g, N_list[2])[1].v == (N_list[0]^1)) - { - N_list[4] = asg_arc_a(g, N_list[2])[0].v^1; - } - else - { - fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__); - } - - if(N_list[3] != N_list[4]) - { - continue; - } - - if(asg_arc_n(g, N_list[0]) != 2 || - asg_arc_n(g, N_list[1]) != 2 || - asg_arc_n(g, N_list[2]) != 2 || - asg_arc_n(g, N_list[3]) != 2) - { - continue; - } - /** - N_list[3] N_list[0] - - N_list[2] N_list[1] - **/ - if(asg_arc_a(g, N_list[0])[0].el == asg_arc_a(g, N_list[0])[1].el) - { - continue; - } - - if(asg_arc_a(g, N_list[0])[0].el == 1) - { - //a1 = asg_arc_a(g, N_list[0])[0].v >> 1; - a1 = 0; - } - else - { - ///a1 = asg_arc_a(g, N_list[0])[1].v >> 1; - a1 = 1; - } - - - - - - - if(asg_arc_a(g, N_list[3])[0].el == asg_arc_a(g, N_list[3])[1].el) - { - continue; - } - - if(asg_arc_a(g, N_list[3])[0].el == 1) - { - //a2 = asg_arc_a(g, N_list[3])[0].v >> 1; - a2 = 0; - } - else - { - //a2 = asg_arc_a(g, N_list[3])[1].v >> 1; - a2 = 1; - } - - if( - (asg_arc_a(g, N_list[0])[a1].v >> 1) - != - (asg_arc_a(g, N_list[3])[a2].v >> 1) - ) - { - if(((N_list[0]>>1) != (endNode>>1)) && - ((N_list[1]>>1) != (endNode>>1)) && - ((N_list[2]>>1) != (endNode>>1)) && - ((N_list[3]>>1) != (endNode>>1))) - { - asg_arc_a(g, N_list[0])[a1].del = 1; - asg_arc_del(g, asg_arc_a(g, N_list[0])[a1].v^1, - asg_arc_a(g, N_list[0])[a1].ul>>32^1, 1); - - - asg_arc_a(g, N_list[3])[a2].del = 1; - asg_arc_del(g, asg_arc_a(g, N_list[3])[a2].v^1, - asg_arc_a(g, N_list[3])[a2].ul>>32^1, 1); - n_reduced++; - } - } - } - - return n_reduced; -} - -int asg_arc_del_cross_bubble(asg_t *g, long long max_dist) -{ - double startTime = Get_T(); - ///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; - buf_t b; - if (!g->is_symm) asg_symm(g); - memset(&b, 0, sizeof(buf_t)); - ///set information for each node - b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - for (v = 0; v < n_vtx; ++v) - { - uint32_t nv = asg_arc_n(g, v); - if (g->seq[v>>1].del) - { - continue; - } - - if(nv < 2) - { - continue; - } - - ///if this is a bubble - if(asg_bub_finder_with_del_advance(g, v, max_dist, &b) == 1) - { - n_reduced += test_cross(g, b.b.a, b.b.n, v, b.S.a[0]); - } - - } - - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - - if (n_reduced) { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d cross\n", __func__, n_reduced); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - return n_reduced; -} - - - -// transitive reduction; see Myers, 2005 -int asg_arc_del_trans(asg_t *g, int fuzz) -{ - double startTime = Get_T(); - - uint8_t *mark; - ///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 - mark = (uint8_t*)calloc(n_vtx, 1); - - /**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) mark[av[i].v] = 1; - - ///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) { - //w is an out-node of v - 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 w has already been reduced - if (mark[av[i].v] != 1) continue; - - for (j = 0; j < nw && asg_arc_len(aw[j]) + asg_arc_len(av[i]) <= L; ++j) - if (mark[aw[j].v]) mark[aw[j].v] = 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 (mark[aw[j].v]) mark[aw[j].v] = 2; - } - #endif - //remove edges - for (i = 0; i < nv; ++i) { - if (mark[av[i].v] == 2) av[i].del = 1, ++n_reduced; - mark[av[i].v] = 0; - } - } - free(mark); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] transitively reduced %d arcs\n", __func__, n_reduced); - } - - if (n_reduced) { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return n_reduced; -} - - -int asg_arc_del_trans_ul(asg_t *g, int fuzz) -{ - uint32_t v, n_vtx = g->n_seq<<1, n_reduced = 0, L, i, nv; - uint8_t *mark; asg_arc_t *av; CALLOC(mark, n_vtx); - uint32_t w, j, nw; asg_arc_t *aw; - - for (v = 0; v < n_vtx; ++v) { - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - if (nv == 0) continue; // no hits - if (g->seq[v>>1].del) { - for (i = 0; i < nv; ++i) av[i].del = 1, ++n_reduced; - continue; - } - /** - 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) mark[av[i].v] = 1; - - ///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) { - //w is an out-node of v - w = av[i].v; - nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); - ///if w has already been reduced - if (mark[av[i].v] != 1) continue; - - for (j = 0; j < nw && asg_arc_len(aw[j]) + asg_arc_len(av[i]) <= L; ++j) - if (mark[aw[j].v]) mark[aw[j].v] = 2; - } - - // for (i = 0; i < nv; ++i) { - // if((av[i].del) || (mark[av[i].v] != 1)) continue; - // w = av[i].v; - // nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); - // for (j = 0; j < nw && asg_arc_len(aw[j]) + asg_arc_len(av[i]) <= L; ++j) { - // if(v == 20996 && w == 21011) { - // fprintf(stderr, "(0):v->%u, ou->%u\n", aw[j].v, aw[j].ou); - // } - - // if (mark[aw[j].v] == 2) { - // if((((uint32_t)av[i].ou) + ((uint32_t)aw[j].ou)) <= OU_MASK) { - // av[i].ou = av[i].ou + aw[j].ou; - // } else { - // av[i].ou = OU_MASK; - // } - // } - // } - // } - //remove edges - for (i = 0; i < nv; ++i) { - if (mark[av[i].v] == 2) { - av[i].del = 1, ++n_reduced; - } - mark[av[i].v] = 0; - } - } - free(mark); - asg_cleanup(g); - asg_symm(g); - // prt_specfic_sge(g, 10498, 10505, __func__); - // normalize_gou(g); - - return n_reduced; -} - -///max_ext is 4 -int asg_cut_tip(asg_t *g, int max_ext) -{ - double startTime = Get_T(); - - asg64_v a = {0,0,0}; - uint32_t n_vtx = g->n_seq * 2, v, i, cnt = 0; - - for (v = 0; v < n_vtx; ++v) { - //if this seq has been deleted - if (g->seq[v>>1].del) continue; - ///check if the another direction of v has no overlaps - ///if the self direction of v has no overlaps, we don't have the overlaps of them - ///here is check if the reverse direction of v - /** - the following first line is to find (means v is a node has no prefix): - (v)--->()---->()---->()----->.... - another case is: - ......()---->()---->()----->()------>(v) - this case can be found by (v^1), so we don't need to process this case here - **/ - if (asg_is_utg_end(g, v, 0) != ASG_ET_TIP) continue; // not a tip - /** - the following second line is: - (v)--->()---->()---->()----->() - |--------max_ext-------| - **/ - ///that means here is a long tip, which is longer than max_ext - if (asg_extend(g, v, max_ext, &a) == ASG_ET_MERGEABLE) continue; // not a short unitig - - /** - * so combining the last two lines, they are designed to reomve(n(0), n(1), n(2)): - * ----->n(4) - * | - * n(0)--->n(1)---->n(2)---->n(3) - * | - * ----->n(5) - **/ - for (i = 0; i < a.n; ++i) - asg_seq_del(g, (uint32_t)a.a[i]>>1); - ++cnt; - } - free(a.a); - if (cnt > 0) asg_cleanup(g); - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] cut %d tips\n", __func__, cnt); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return cnt; -} - - -// delete short arcs -///for best graph? -int asg_arc_del_short(asg_t *g, float drop_ratio) -{ - uint32_t v, n_vtx = g->n_seq * 2, n_short = 0; - for (v = 0; v < n_vtx; ++v) { - asg_arc_t *av = asg_arc_a(g, v); - uint32_t i, thres, nv = asg_arc_n(g, v); - ///if there is just one overlap, do nothing - if (nv < 2) continue; - //av[0] has the most overlap length - ///remove short overlaps - thres = (uint32_t)(av[0].ol * drop_ratio + .499); - ///av has been sorted by overlap length - for (i = nv - 1; i >= 1 && av[i].ol < thres; --i); - for (i = i + 1; i < nv; ++i) - av[i].del = 1, ++n_short; - } - if (n_short) { - asg_cleanup(g); - asg_symm(g); - } - fprintf(stderr, "[M::%s] removed %d short overlaps\n", __func__, n_short); - return n_short; -} - - -inline int check_weak_ma_hit(ma_hit_t_alloc* aim_paf, ma_hit_t_alloc* reverse_paf_list, -long long weakID, uint32_t w_qs, uint32_t w_qe) -{ - long long i = 0; - long long strongID, index; - for (i = 0; i < aim_paf->length; i++) - { - ///if this is a strong overlap - if ( - aim_paf->buffer[i].del == 0 - && - aim_paf->buffer[i].ml == 1 - && - Get_qs(aim_paf->buffer[i]) <= w_qs - && - Get_qe(aim_paf->buffer[i]) >= w_qe) - { - strongID = Get_tn(aim_paf->buffer[i]); - index = get_specific_overlap(&(reverse_paf_list[strongID]), strongID, weakID); - if(index != -1) { - // if((Get_qn(aim_paf->buffer[i]) == 27087 && weakID == 27128) || (Get_qn(aim_paf->buffer[i]) == 27128 && weakID == 27087)) { - // ma_hit_t *h = &(aim_paf->buffer[i]); - // fprintf(stderr, "[M::%s]\t%.*s(qn::%u)\t%u\t%u\t%u\t%c\t%.*s(tn::%u)\t%u\t%u\t%u\t%u\t%u\t255\n", __func__, (int)Get_NAME_LENGTH(R_INF, Get_qn(*h)), Get_NAME((R_INF), Get_qn(*h)), Get_qn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_qn(*h)), Get_qs(*h), Get_qe(*h), "+-"[h->rev], - // (int)Get_NAME_LENGTH(R_INF, Get_tn(*h)), Get_NAME((R_INF), Get_tn(*h)), Get_tn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_tn(*h)), Get_ts(*h), Get_te(*h), h->ml, h->bl); - // } - return 0; - } - } - } - - return 1; -} - - -inline int check_weak_ma_hit_reverse(ma_hit_t_alloc* r_paf, ma_hit_t_alloc* r_paf_source, -long long weakID) -{ - long long i = 0; - long long strongID, index; - ///all overlaps coming from another haplotye are strong - for (i = 0; i < r_paf->length; i++) - { - strongID = Get_tn(r_paf->buffer[i]); - index = get_specific_overlap - (&(r_paf_source[strongID]), strongID, weakID); - ///must be a strong overlap - if(index != -1 && r_paf_source[strongID].buffer[index].ml == 1) - { - return 0; - } - } - - return 1; -} - - -inline int check_weak_ma_hit_debug(ma_hit_t_alloc* aim_paf, ma_hit_t_alloc* reverse_paf_list, -long long weakID) -{ - long long i = 0; - long long strongID, index; - for (i = 0; i < aim_paf->length; i++) - { - ///if this is a strong overlap - if (aim_paf->buffer[i].ml == 1) - { - strongID = Get_tn(aim_paf->buffer[i]); - index = get_specific_overlap(&(reverse_paf_list[strongID]), strongID, weakID); - if(index != -1) - { - return strongID; - } - } - - - } - - return 0; -} - - - -// delete short arcs -///for best graph? -int asg_arc_del_short_diploid_unclean(asg_t *g, float drop_ratio, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources) -{ - double startTime = Get_T(); - - uint32_t v, n_vtx = g->n_seq * 2, n_short = 0; - uint32_t last_e; - for (v = 0; v < n_vtx; ++v) - { - if (g->seq[v>>1].del) continue; - - asg_arc_t *av = asg_arc_a(g, v); - uint32_t i, thres, nv = asg_arc_n(g, v); - ///if there is just one overlap, do nothing - if (nv < 2) continue; - //av[0] has the most overlap length - ///remove short overlaps - thres = (uint32_t)(av[0].ol * drop_ratio + .499); - ///av has been sorted by overlap length - for (i = nv - 1; i >= 1 && av[i].ol < thres; --i) {} - last_e = i + 1; - - for (i = i + 1; i < nv; ++i) - av[i].del = 1, ++n_short; - - - if(nv >= 2 && av[1].del == 1) - { - ///second longest - av[1].del = 0; - --n_short; - last_e++; - } - - } - ///if (n_short) - { - asg_cleanup(g); - asg_symm(g); - } - fprintf(stderr, "[M::%s] removed %d short overlaps\n", __func__, n_short); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - - return n_short; -} - - - - - - - - - -/*****************************read graph*****************************/ - -uint32_t detect_single_path_with_dels(asg_t *g, uint32_t begNode, uint32_t* endNode, long long* Len, buf_t* b) -{ - uint32_t v = begNode, w; - uint32_t kv, kw; - (*Len) = 0; - - while (1) - { - (*Len)++; - kv = get_real_length(g, v, NULL); - (*endNode) = v; - - if(b) kv_push(uint32_t, b->b, v>>1); - - if(kv == 0) - { - return END_TIPS; - } - - if(kv == 2) - { - return TWO_OUTPUT; - } - - if(kv > 2) - { - return MUL_OUTPUT; - } - - ///up to here, kv=1 - ///kw must >= 1 - get_real_length(g, v, &w); - kw = get_real_length(g, w^1, NULL); - v = w; - (*endNode) = v; - - - if(kw == 2) - { - (*Len)++; - if(b) kv_push(uint32_t, b->b, v>>1); - return TWO_INPUT; - } - - if(kw > 2) - { - (*Len)++; - if(b) kv_push(uint32_t, b->b, v>>1); - return MUL_INPUT; - } - - - if((v>>1) == (begNode>>1)) - { - return LOOP; - } - } - - return LONG_TIPS; -} - -uint32_t detect_single_path_with_dels_n_stops(asg_t *g, uint32_t begNode, uint32_t* endNode, -long long* Len, long long* max_stop_Len, buf_t* b, uint32_t stops_threshold) -{ - - uint32_t v = begNode, w; - uint32_t kv, kw, n_stops = 0, flag = LONG_TIPS; - (*Len) = 0; - (*max_stop_Len) = 0; - long long preLen = 0, currentLen; - - while (1) - { - (*Len)++; - kv = get_real_length(g, v, NULL); - (*endNode) = v; - - if(b) kv_push(uint32_t, b->b, v>>1); - - if(kv == 0) - { - flag = END_TIPS; - break; - } - - if(kv == 2) - { - flag = TWO_OUTPUT; - break; - } - - if(kv > 2) - { - flag = MUL_OUTPUT; - break; - } - - ///up to here, kv=1 - ///kw must >= 1 - get_real_length(g, v, &w); - kw = get_real_length(g, w^1, NULL); - v = w; - (*endNode) = v; - - if(kw >= 2) - { - n_stops++; - currentLen = (*Len) - preLen; - preLen = (*Len); - if(currentLen > (*max_stop_Len)) - { - (*max_stop_Len) = currentLen; - } - } - if(kw >= 2 && n_stops >= stops_threshold) - { - (*Len)++; - if(b) kv_push(uint32_t, b->b, v>>1); - if(kw == 2) flag = TWO_INPUT; - if(kw > 2) flag = MUL_INPUT; - break; - } - - if((v>>1) == (begNode>>1)) - { - flag = LOOP; - break; - } - } - - - currentLen = (*Len) - preLen; - preLen = (*Len); - if(currentLen > (*max_stop_Len)) - { - (*max_stop_Len) = currentLen; - } - return flag; -} - -uint32_t detect_single_path_with_dels_contigLen(asg_t *g, uint32_t begNode, uint32_t* endNode, long long* baseLen, buf_t* b) -{ - - uint32_t v = begNode, w = 0; - uint32_t kv, kw, k; - (*baseLen) = 0; - - - while (1) - { - ///(*Len)++; - kv = get_real_length(g, v, NULL); - (*endNode) = v; - - if(b) kv_push(uint32_t, b->b, v>>1); - - if(kv == 0) - { - (*baseLen) += g->seq[v>>1].len; - return END_TIPS; - } - - if(kv == 2) - { - (*baseLen) += g->seq[v>>1].len; - return TWO_OUTPUT; - } - - if(kv > 2) - { - (*baseLen) += g->seq[v>>1].len; - return MUL_OUTPUT; - } - - ///kv must be 1 - for (k = 0; k < asg_arc_n(g, v); k++) - { - if(!asg_arc_a(g, v)[k].del) - { - w = asg_arc_a(g, v)[k].v; - (*baseLen) += ((uint32_t)(asg_arc_a(g, v)[k].ul)); - break; - } - } - - ///up to here, kv=1 - ///kw must >= 1 - kw = get_real_length(g, w^1, NULL); - v = w; - (*endNode) = v; - - - if(kw == 2) - { - (*baseLen) += g->seq[v>>1].len; - if(b) kv_push(uint32_t, b->b, v>>1); - return TWO_INPUT; - } - - if(kw > 2) - { - (*baseLen) += g->seq[v>>1].len; - if(b) kv_push(uint32_t, b->b, v>>1); - return MUL_INPUT; - } - - - if((v>>1) == (begNode>>1)) - { - return LOOP; - } - } - - return LONG_TIPS; -} - -uint32_t detect_single_path_with_dels_contigLen_complex(asg_t *g, uint32_t begNode, uint32_t* endNode, -long long* baseLen, long long* max_stop_base_Len, buf_t* b, uint32_t stops_threshold) -{ - - uint32_t v = begNode, w = 0; - uint32_t kv, kw, k, n_stops = 0, flag = LONG_TIPS; - (*baseLen) = 0; - (*max_stop_base_Len) = 0; - long long preBaseLen = 0, currentBaseLen; - - - while (1) - { - ///(*Len)++; - kv = get_real_length(g, v, NULL); - (*endNode) = v; - - if(b) kv_push(uint32_t, b->b, v>>1); - - if(kv == 0) - { - (*baseLen) += g->seq[v>>1].len; - flag = END_TIPS; - break; - } - - if(kv == 2) - { - (*baseLen) += g->seq[v>>1].len; - flag = TWO_OUTPUT; - break; - } - - if(kv > 2) - { - (*baseLen) += g->seq[v>>1].len; - flag = MUL_OUTPUT; - break; - } - - ///kv must be 1 - for (k = 0; k < asg_arc_n(g, v); k++) - { - if(!asg_arc_a(g, v)[k].del) - { - w = asg_arc_a(g, v)[k].v; - (*baseLen) += ((uint32_t)(asg_arc_a(g, v)[k].ul)); - break; - } - } - - ///up to here, kv=1 - ///kw must >= 1 - kw = get_real_length(g, w^1, NULL); - v = w; - (*endNode) = v; - - if(kw >= 2) - { - n_stops++; - currentBaseLen = (*baseLen) - preBaseLen; - preBaseLen = (*baseLen); - if(currentBaseLen > (*max_stop_base_Len)) - { - (*max_stop_base_Len) = currentBaseLen; - } - } - - if(kw >= 2 && n_stops >= stops_threshold) - { - (*baseLen) += g->seq[v>>1].len; - if(b) kv_push(uint32_t, b->b, v>>1); - if(kw == 2) flag = TWO_INPUT; - if(kw > 2) flag = MUL_INPUT; - break; - } - - - if((v>>1) == (begNode>>1)) - { - flag = LOOP; - break; - } - } - - currentBaseLen = (*baseLen) - preBaseLen; - preBaseLen = (*baseLen); - if(currentBaseLen > (*max_stop_base_Len)) - { - (*max_stop_base_Len) = currentBaseLen; - } - - return flag; -} - -/*****************************read graph*****************************/ - - -long long check_if_diploid(uint32_t v1, uint32_t v2, asg_t *g, -ma_hit_t_alloc* reverse_sources, long long min_edge_length, R_to_U* ruIndex) -{ - buf_t b_0, b_1; - memset(&b_0, 0, sizeof(buf_t)); - memset(&b_1, 0, sizeof(buf_t)); - - uint32_t convex1, convex2; - long long l1, l2; - - b_0.b.n = 0; - b_1.b.n = 0; - ///uint32_t flag1 = detect_single_path(g, v1, &convex1, &l1, &b_0); - uint32_t flag1 = detect_single_path_with_dels(g, v1, &convex1, &l1, &b_0); - - ///uint32_t flag2 = detect_single_path(g, v2, &convex2, &l2, &b_1); - uint32_t flag2 = detect_single_path_with_dels(g, v2, &convex2, &l2, &b_1); - - if(flag1 == LOOP || flag2 == LOOP) - { - free(b_0.b.a); free(b_1.b.a); - return -1; - } - - if(flag1 != END_TIPS && flag1 != LONG_TIPS) - { - l1--; - b_0.b.n--; - } - - if(flag2 != END_TIPS && flag2 != LONG_TIPS) - { - l2--; - b_1.b.n--; - } - - - if(l1 <= min_edge_length || l2 <= min_edge_length) - { - free(b_0.b.a); free(b_1.b.a); - return -1; - } - - buf_t* b_min; - buf_t* b_max; - if(l1<=l2) - { - b_min = &b_0; - b_max = &b_1; - } - else - { - b_min = &b_1; - b_max = &b_0; - } - - long long i, j, k; - double max_count = 0; - double min_count = 0; - uint32_t qn, tn, is_Unitig; - for (i = 0; i < (long long)b_min->b.n; i++) - { - qn = b_min->b.a[i]; - for (j = 0; j < (long long)reverse_sources[qn].length; j++) - { - tn = Get_tn(reverse_sources[qn].buffer[j]); - /****************************may have bugs********************************/ - ///if(g->seq[tn].del == 1) continue; - if(g->seq[tn].del == 1) - { - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || g->seq[tn].del == 1) continue; - } - /****************************may have bugs********************************/ - min_count++; - for (k = 0; k < (long long)b_max->b.n; k++) - { - if(b_max->b.a[k]==tn) - { - max_count++; - break; - } - } - } - } - - - free(b_0.b.a); - free(b_1.b.a); - - if(min_count == 0) return -1; - if(max_count == 0) return 0; - if(max_count/min_count>0.3) return 1; - return 0; - -} - - -long long check_if_diploid_primary_complex(uint32_t v1, uint32_t v2, asg_t *g, -ma_hit_t_alloc* reverse_sources, long long min_edge_length, uint32_t stops_threshold, -int if_drop, R_to_U* ruIndex) -{ - buf_t b_0, b_1; - memset(&b_0, 0, sizeof(buf_t)); - memset(&b_1, 0, sizeof(buf_t)); - - uint32_t convex1, convex2; - long long l1, l2, max_stop_Len; - - b_0.b.n = 0; - b_1.b.n = 0; - uint32_t flag1 = detect_single_path_with_dels_n_stops(g, v1, &convex1, &l1, - &max_stop_Len, &b_0, stops_threshold); - - uint32_t flag2 = detect_single_path_with_dels_n_stops(g, v2, &convex2, &l2, - &max_stop_Len, &b_1, stops_threshold); - - if(flag1 == LOOP || flag2 == LOOP) - { - return -1; - } - - if(flag1 != END_TIPS && flag1 != LONG_TIPS) - { - l1--; - b_0.b.n--; - } - - if(flag2 != END_TIPS && flag2 != LONG_TIPS) - { - l2--; - b_1.b.n--; - } - - - long long i, j, k; - i = b_0.b.n; i--; - j = b_1.b.n; j--; - while (i>=0 && j>=0) - { - if(b_0.b.a[i] == b_1.b.a[j]) - { - i--; - j--; - } - else - { - break; - } - - } - b_0.b.n = i+1; l1 = i+1; - b_1.b.n = j+1; l2 = j+1; - - - if(l1 <= min_edge_length || l2 <= min_edge_length) - { - return -1; - } - - buf_t* b_min; - buf_t* b_max; - if(l1<=l2) - { - b_min = &b_0; - b_max = &b_1; - } - else - { - b_min = &b_1; - b_max = &b_0; - } - - - double max_count = 0; - double min_count = 0; - uint32_t qn, tn, is_Unitig; - for (i = 0; i < (long long)b_min->b.n; i++) - { - qn = b_min->b.a[i]; - for (j = 0; j < (long long)reverse_sources[qn].length; j++) - { - tn = Get_tn(reverse_sources[qn].buffer[j]); - /****************************may have bugs********************************/ - ///if(g->seq[tn].del == 1 || (if_drop == 1 && g->seq[tn].c == ALTER_LABLE)) continue; - if(g->seq[tn].del == 1) - { - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || g->seq[tn].del == 1) continue; - } - /****************************may have bugs********************************/ - min_count++; - for (k = 0; k < (long long)b_max->b.n; k++) - { - if(b_max->b.a[k]==tn) - { - max_count++; - break; - } - } - } - } - - - free(b_0.b.a); - free(b_1.b.a); - if(min_count == 0) return -1; - if(max_count == 0) return 0; - if(max_count/min_count>0.3) return 1; - return 0; - -} - -uint32_t if_long_tip_length(asg_t *sg, ma_ug_t *ug, uint32_t begNode, uint32_t* untigLen, -long long minLongUntig, long long maxShortUntig, float ShortUntigRate, long long mainLen) -{ - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - uint32_t Len, endNode; - if(untigLen == NULL) - { - if(get_unitig(sg, ug, begNode, &endNode, &nodeLen, &baseLen, - &max_stop_nodeLen, &max_stop_baseLen, 1, NULL) == LOOP) - { - ///the length of LOOP is infinite - return 1; - } - Len = nodeLen; - } - else - { - Len = (*untigLen); - } - - - if(Len == 0) return 0; - if(Len < (ShortUntigRate*mainLen)) return 0; - if(Len >= maxShortUntig) return 1; - if(Len >= minLongUntig && Len >= (ShortUntigRate*mainLen)) return 1; - return 0; -} - -long long check_if_diploid_aggressive(uint32_t v1, uint32_t v2, asg_t *g, -ma_hit_t_alloc* reverse_sources, long long min_edge_length) -{ - buf_t b_0, b_1; - memset(&b_0, 0, sizeof(buf_t)); - memset(&b_1, 0, sizeof(buf_t)); - - uint32_t convex1, convex2; - long long l1, l2; - - b_0.b.n = 0; - b_1.b.n = 0; - ///uint32_t flag1 = detect_single_path(g, v1, &convex1, &l1, &b_0); - uint32_t flag1 = detect_single_path_with_dels(g, v1, &convex1, &l1, &b_0); - - ///uint32_t flag2 = detect_single_path(g, v2, &convex2, &l2, &b_1); - uint32_t flag2 = detect_single_path_with_dels(g, v2, &convex2, &l2, &b_1); - - if(flag1 == LOOP || flag2 == LOOP) - { - return -1; - } - - if(flag1 != END_TIPS && flag1 != LONG_TIPS) - { - l1--; - b_0.b.n--; - } - - if(flag2 != END_TIPS && flag2 != LONG_TIPS) - { - l2--; - b_1.b.n--; - } - - - if(l1 <= min_edge_length || l2 <= min_edge_length) - { - return -1; - } - - buf_t* b_min; - buf_t* b_max; - if(l1<=l2) - { - b_min = &b_0; - b_max = &b_1; - } - else - { - b_min = &b_1; - b_max = &b_0; - } - - long long i, j, k; - double max_count = 0; - double min_count = 0; - uint32_t qn, tn; - for (i = 0; i < (long long)b_min->b.n; i++) - { - qn = b_min->b.a[i]; - for (j = 0; j < (long long)reverse_sources[qn].length; j++) - { - tn = Get_tn(reverse_sources[qn].buffer[j]); - if(g->seq[tn].del == 1) continue; - min_count++; - for (k = 0; k < (long long)b_max->b.n; k++) - { - if(b_max->b.a[k]==tn) - { - max_count++; - break; - } - } - } - } - - - - free(b_0.b.a); - free(b_1.b.a); - - if(min_count == 0) return -1; - if(max_count == 0) return 0; - - return 1; - /** - if(max_count/min_count>0.3) return 1; - return 0; - **/ - -} - -int asg_arc_del_too_short_overlaps(asg_t *g, long long dropLen, float drop_ratio, -ma_hit_t_alloc* reverse_sources, long long min_edge_length, R_to_U* ruIndex) -{ - double startTime = Get_T(); - - uint32_t v, v_max, v_maxLen, n_vtx = g->n_seq * 2, n_short = 0; - long long drop_ratio_Len = 0; - - for (v = 0; v < n_vtx; ++v) - { - if (g->seq[v>>1].del) continue; - if (g->seq_vis[v] != 0) continue; - - uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del) continue; - - - - n_arc = get_real_length(g, v, NULL); - if (n_arc < 2) continue; - v_max = (uint32_t)-1; - - for (i = 0, n_arc = 0; i < nv; i++) - { - if (!av[i].del) - { - if(v_max == (uint32_t)-1) - { - v_max = av[i].v; - v_maxLen = av[i].ol; - if(v_maxLen < dropLen) break; - drop_ratio_Len = v_maxLen * drop_ratio; - if(dropLen < drop_ratio_Len) - { - drop_ratio_Len = dropLen; - } - } - else if(av[i].ol < drop_ratio_Len && - check_if_diploid(v_max, av[i].v, g, reverse_sources, min_edge_length, ruIndex) != 1) - { - // av[i].ol = 1;///should be a bug - av[i].del = 1; - asg_arc_del(g, av[i].v^1, av[i].ul>>32^1, 1); - ++n_short; - } - } - } - } - - - asg_cleanup(g); - asg_symm(g); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d short overlaps\n", __func__, n_short); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - return n_short; -} - - - -int asg_arc_del_short_diploid_unclean_exact(asg_t *g, float drop_ratio, ma_hit_t_alloc* sources) -{ - uint32_t v, n_vtx = g->n_seq * 2, n_short = 0; - for (v = 0; v < n_vtx; ++v) - { - if (g->seq[v>>1].del) continue; - - asg_arc_t *av = asg_arc_a(g, v); - uint32_t i, nv = asg_arc_n(g, v); - ///if there is just one overlap, do nothing - if (nv < 2) continue; - ///keep the longest one - for (i = 1; i < nv; i++) - { - ///if it is an inexact overlap - if(av[i].el == 0 && - sources[v>>1].is_fully_corrected == 1&& - sources[(av[i].v>>1)].is_fully_corrected == 1) - { - av[i].del = 1; - ++n_short; - } - } - - } - - if (n_short) - { - asg_cleanup(g); - asg_symm(g); - } - fprintf(stderr, "[M::%s] removed %d inexact overlaps\n", __func__, n_short); - return n_short; -} - - - -///check if v has only one branch -static uint32_t asg_check_unambi1(asg_t *g, uint32_t v) -{ - asg_arc_t *av = asg_arc_a(g, v); - uint32_t i, nv = asg_arc_n(g, v); - uint32_t k = nv, kv; - for (i = 0, kv = 0; i < nv; ++i) - if (!av[i].del) ++kv, k = i; - if (kv != 1) return (uint32_t)-1; - return av[k].v; -} -///to see if it is a long tip -int asg_topocut_aux(asg_t *g, uint32_t v, int max_ext) -{ - int32_t n_ext; - for (n_ext = 1; n_ext < max_ext && v != (uint32_t)-1; ++n_ext) { - if (asg_check_unambi1(g, v^1) == (uint32_t)-1) { - --n_ext; - break; - } - v = asg_check_unambi1(g, v); - } - - return n_ext; -} - -int asg_topocut_aux_pg(asg_t *g, uint32_t v, int max_ext, uint32_t *rv) -{ - int32_t n_ext; (*rv) = (uint32_t)-1; - for (n_ext = 1; n_ext < max_ext && v != (uint32_t)-1; ++n_ext) { - if (asg_check_unambi1(g, v^1) == (uint32_t)-1) { - --n_ext; (*rv) = v^1;/// asg_arc_n(g, v) >= 2 - break; - } - v = asg_check_unambi1(g, v); - } - - return n_ext; -} - -// delete short arcs -///for best graph? -int asg_arc_del_short_diploid_by_length(asg_t *g, float drop_ratio, int max_ext, -ma_hit_t_alloc* reverse_sources, long long miniedgeLen, uint32_t stops_threshold, -int if_skip_bubble, int if_drop, int if_check_hap, R_to_U* ruIndex) -{ - double startTime = Get_T(); - kvec_t(uint64_t) b; - memset(&b, 0, sizeof(b)); - - uint32_t v, n_vtx = g->n_seq * 2; - long long n_cut = 0; - - for (v = 0; v < n_vtx; ++v) - { - if(if_skip_bubble && g->seq_vis[v] != 0) continue; - if(if_drop && g->seq[v>>1].c == ALTER_LABLE) continue; - asg_arc_t *av = asg_arc_a(g, v); - uint32_t nv = asg_arc_n(g, v); - if (nv < 2) continue; - uint64_t i; - for (i = 0; i < nv; ++i) - { - kv_push(uint64_t, b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); - } - } - - radix_sort_arch64(b.a, b.a + b.n); - - uint64_t k; - for (k = 0; k < b.n; k++) - { - - asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; - ///v is self id, w is the id of another end - uint32_t i, iv, iw, v = (a->ul)>>32, w = a->v^1, to_del = 0; - uint32_t nv = asg_arc_n(g, v), nw = asg_arc_n(g, w), kv, kw; - uint32_t ov_max = 0, ow_max = 0, ov_max_i = 0, ow_max_i = 0; - asg_arc_t *av, *aw; - ///nv must be >= 2 - if (nv == 1 && nw == 1) continue; - av = asg_arc_a(g, v); - aw = asg_arc_a(g, w); - - - ///calculate the longest edge for v and w - for (i = 0, kv = 0; i < nv; ++i) { - if (av[i].del) continue; - if (ov_max < av[i].ol) ov_max = av[i].ol, ov_max_i = i; - ++kv; - } - if (kv >= 2 && a->ol > ov_max * drop_ratio) continue; - - - for (i = 0, kw = 0; i < nw; ++i) { - if (aw[i].del) continue; - if (ow_max < aw[i].ol) ow_max = aw[i].ol, ow_max_i = i; - ++kw; - } - if (kw >= 2 && a->ol > ow_max * drop_ratio) continue; - ///if (kv == 1 && kw == 1) continue; - if (kv <= 1 && kw <= 1) continue; - - - ///to see which one is the current edge (from v and w) - for (iv = 0; iv < nv; ++iv) - if (av[iv].v == (w^1)) break; - for (iw = 0; iw < nw; ++iw) - if (aw[iw].v == (v^1)) break; - ///if one edge has been deleted, it should be deleted in both direction - if (av[iv].del && aw[iw].del) continue; - - ///kv and kw is the avialiable - if (kv > 1 && kw > 1) { - if (a->ol < ov_max * drop_ratio && a->ol < ow_max * drop_ratio) - to_del = 1; - if(if_check_hap == 1 && to_del == 1) - { - - if(check_if_diploid_primary_complex(av[ov_max_i].v, w^1, g, reverse_sources, - miniedgeLen, stops_threshold, if_drop, ruIndex) == 1 - || - check_if_diploid_primary_complex(aw[ow_max_i].v, v^1, g, reverse_sources, - miniedgeLen, stops_threshold, if_drop, ruIndex) == 1) - { - to_del = 0; - } - } - - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - ///kv > 1 - if(if_check_hap == 1 && to_del == 1) - { - if(check_if_diploid_primary_complex(av[ov_max_i].v, w^1, g, reverse_sources, - miniedgeLen, stops_threshold, if_drop, ruIndex) == 1) - { - to_del = 0; - } - } - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - ///kw > 1 - if(if_check_hap == 1 && to_del == 1) - { - if(check_if_diploid_primary_complex(aw[ow_max_i].v, v^1, g, reverse_sources, - miniedgeLen, stops_threshold, if_drop, ruIndex) == 1) - { - to_del = 0; - } - } - } - if (to_del) - av[iv].del = aw[iw].del = 1, ++n_cut; - - } - - free(b.a); - if (n_cut) - { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %lld short overlaps\n", __func__, n_cut); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return n_cut; -} - -int unitig_arc_del_short_diploid_by_length_topo(asg_t *g, ma_ug_t *ug, float drop_ratio, -int max_ext, ma_hit_t_alloc* reverse_sources, int if_skip_bubble, int if_drop) -{ - double startTime = Get_T(); - kvec_t(uint64_t) b; - memset(&b, 0, sizeof(b)); - - uint32_t v, n_vtx = g->n_seq * 2, convex; - long long n_cut = 0, tmp, nodeLen, max_stop_nodeLen, max_stop_baseLen; - - for (v = 0; v < n_vtx; ++v) - { - if(if_skip_bubble && g->seq_vis[v] != 0) continue; - if(if_drop && g->seq[v>>1].c == ALTER_LABLE) continue; - asg_arc_t *av = asg_arc_a(g, v); - uint32_t nv = asg_arc_n(g, v); - if (nv < 2) continue; - if(get_real_length(g, v, NULL) < 2) continue; - uint64_t i; - for (i = 0; i < nv; ++i) - { - kv_push(uint64_t, b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); - } - } - - radix_sort_arch64(b.a, b.a + b.n); - - uint64_t k; - for (k = 0; k < b.n; k++) - { - - asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; - ///v is self id, w is the id of another end - uint32_t i, iv, iw, v = (a->ul)>>32, w = a->v^1, to_del = 0; - uint32_t nv = asg_arc_n(g, v), nw = asg_arc_n(g, w), kv, kw; - uint32_t ov_max = 0, ow_max = 0; - asg_arc_t *av, *aw; - ///nv must be >= 2 - if (nv == 1 && nw == 1) continue; - av = asg_arc_a(g, v); - aw = asg_arc_a(g, w); - - - ///calculate the longest edge for v and w - for (i = 0, kv = 0; i < nv; ++i) { - if (av[i].del) continue; - if (ov_max < av[i].ol) ov_max = av[i].ol; - ++kv; - } - if (kv >= 2 && a->ol > ov_max * drop_ratio) continue; - - - for (i = 0, kw = 0; i < nw; ++i) { - if (aw[i].del) continue; - if (ow_max < aw[i].ol) ow_max = aw[i].ol; - ++kw; - } - if (kw >= 2 && a->ol > ow_max * drop_ratio) continue; - ///if (kv == 1 && kw == 1) continue; - if (kv <= 1 && kw <= 1) continue; - - - ///to see which one is the current edge (from v and w) - for (iv = 0; iv < nv; ++iv) - if (av[iv].v == (w^1)) break; - for (iw = 0; iw < nw; ++iw) - if (aw[iw].v == (v^1)) break; - ///if one edge has been deleted, it should be deleted in both direction - if (av[iv].del && aw[iw].del) continue; - - ///kv and kw is the avialiable - if (kv > 1 && kw > 1) { - if (a->ol < ov_max * drop_ratio && a->ol < ow_max * drop_ratio) - { - to_del = 1; - } - } else if (kw == 1) { - get_unitig(g, ug, w^1, &convex, &nodeLen, &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, NULL); - if(nodeLen < max_ext) to_del = 1; - ///if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - } else if (kv == 1) { - get_unitig(g, ug, v^1, &convex, &nodeLen, &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, NULL); - if(nodeLen < max_ext) to_del = 1; - ///if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - } - if (to_del) - av[iv].del = aw[iw].del = 1, ++n_cut; - } - - free(b.a); - if (n_cut) - { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %lld short overlaps\n", __func__, n_cut); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return n_cut; -} - - -int unitig_arc_del_short_diploid_by_length(asg_t *g, float drop_ratio) -{ - double startTime = Get_T(); - kvec_t(uint64_t) b; - memset(&b, 0, sizeof(b)); - - uint32_t v, n_vtx = g->n_seq * 2; - long long n_cut = 0; - - for (v = 0; v < n_vtx; ++v) - { - if(g->seq[v>>1].c == ALTER_LABLE || g->seq[v>>1].del) continue; - asg_arc_t *av = asg_arc_a(g, v); - uint32_t nv = asg_arc_n(g, v); - if (nv < 2) continue; - uint64_t i; - for (i = 0; i < nv; ++i) - { - kv_push(uint64_t, b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); - } - } - - radix_sort_arch64(b.a, b.a + b.n); - - uint64_t k; - for (k = 0; k < b.n; k++) - { - - asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; - ///v is self id, w is the id of another end - uint32_t i, v = (a->ul)>>32; - uint32_t nv = asg_arc_n(g, v), kv; - uint32_t ov_max = 0; - asg_arc_t *av = NULL; - ///nv must be >= 2 - if (nv <= 1) continue; - av = asg_arc_a(g, v); - - - ///calculate the longest edge for v and w - for (i = 0, kv = 0; i < nv; ++i) { - if (av[i].del) continue; - if (ov_max < av[i].ol) ov_max = av[i].ol; - ++kv; - } - if (kv <= 1) continue; - if (kv >= 2 && a->ol > ov_max * drop_ratio) continue; - a->del = 1; - asg_arc_del(g, a->v^1, av->ul>>32^1, 1); - ++n_cut; - } - - free(b.a); - if (n_cut) - { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %lld short overlaps\n", __func__, n_cut); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return n_cut; -} - - -uint8_t get_tip_trio_infor(asg_t *sg, uint32_t begNode) -{ - uint32_t v = begNode, w; - uint32_t kv; - uint32_t eLen = 0, uLen = 0; - uint32_t father_occ = 0, mother_occ = 0, ambigious_occ = 0; - - while (1) - { - kv = get_real_length(sg, v, NULL); - eLen++; - - if(R_INF.trio_flag[v>>1]==FATHER) - { - father_occ++; - } - else if(R_INF.trio_flag[v>>1]==MOTHER) - { - mother_occ++; - } - else if((R_INF.trio_flag[v>>1]==AMBIGU) || (R_INF.trio_flag[v>>1]==DROP)) - { - ambigious_occ++; - } - - if(kv!=1) break; - ///kv must be 1 here - kv = get_real_length(sg, v, &w); - if(get_real_length(sg, w^1, NULL)!=1) break; - v = w; - if(v == begNode) break; - } - - uLen = eLen; - eLen = father_occ + mother_occ; - if(eLen == 0) return AMBIGU; - if(father_occ >= mother_occ) - { - if((father_occ > TRIO_THRES*eLen) && (father_occ >= DOUBLE_CHECK_THRES*uLen)) return FATHER; - } - else - { - if((mother_occ > TRIO_THRES*eLen) && (mother_occ >= DOUBLE_CHECK_THRES*uLen)) return MOTHER; - } - return AMBIGU; -} - -int asg_arc_del_short_diploid_by_length_trio(asg_t *g, float drop_ratio, int max_ext, -ma_hit_t_alloc* reverse_sources, long long miniedgeLen, uint32_t stops_threshold, -int if_skip_bubble, int if_drop, int if_check_hap, R_to_U* ruIndex) -{ - double startTime = Get_T(); - kvec_t(uint64_t) b; - memset(&b, 0, sizeof(b)); - - uint32_t v, n_vtx = g->n_seq * 2; - long long n_cut = 0; - - for (v = 0; v < n_vtx; ++v) - { - if(if_skip_bubble && g->seq_vis[v] != 0) continue; - if(if_drop && g->seq[v>>1].c == ALTER_LABLE) continue; - asg_arc_t *av = asg_arc_a(g, v); - uint32_t nv = asg_arc_n(g, v); - if (nv < 2) continue; - uint64_t i; - for (i = 0; i < nv; ++i) - { - kv_push(uint64_t, b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); - } - } - - radix_sort_arch64(b.a, b.a + b.n); - - uint64_t k; - for (k = 0; k < b.n; k++) - { - asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; - ///v is self id, w is the id of another end - uint32_t i, iv, iw, v = (a->ul)>>32, w = a->v^1, to_del = 0; - uint32_t nv = asg_arc_n(g, v), nw = asg_arc_n(g, w), kv, kw; - uint32_t ov_max = 0, ow_max = 0, ov_max_i = 0, ow_max_i = 0, trio_flag, non_trio_flag; - asg_arc_t *av, *aw; - ///nv must be >= 2 - if (nv == 1 && nw == 1) continue; - av = asg_arc_a(g, v); - aw = asg_arc_a(g, w); - kv = get_real_length(g, v, NULL); - kw = get_real_length(g, w, NULL); - if (kv <= 1 && kw <= 1) continue; - trio_flag = get_tip_trio_infor(g, v^1); - non_trio_flag = (uint32_t)-1; - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - - ///calculate the longest edge for v and w - for (i = 0, kv = 0; i < nv; ++i) { - if (av[i].del) continue; - kv++; - if(get_tip_trio_infor(g, av[i].v) == non_trio_flag) continue; - if (ov_max < av[i].ol) ov_max = av[i].ol, ov_max_i = i; - ///kv++; - } - if (kv >= 2 && a->ol > ov_max * drop_ratio) continue; - - for (i = 0, kw = 0; i < nw; ++i) { - if (aw[i].del) continue; - kw++; - if (get_tip_trio_infor(g, aw[i].v) == non_trio_flag) continue; - if (ow_max < aw[i].ol) ow_max = aw[i].ol, ow_max_i = i; - ///kw++; - } - if (kw >= 2 && a->ol > ow_max * drop_ratio) continue; - - if (kv <= 1 && kw <= 1) continue; - - ///to see which one is the current edge (from v and w) - for (iv = 0; iv < nv; ++iv) - if (av[iv].v == (w^1)) break; - for (iw = 0; iw < nw; ++iw) - if (aw[iw].v == (v^1)) break; - ///if one edge has been deleted, it should be deleted in both direction - if (av[iv].del && aw[iw].del) continue; - - ///kv and kw is the avialiable - if (kv > 1 && kw > 1) { - if (a->ol < ov_max * drop_ratio && a->ol < ow_max * drop_ratio) - to_del = 1; - if(if_check_hap == 1 && to_del == 1) - { - - if(check_if_diploid_primary_complex(av[ov_max_i].v, w^1, g, reverse_sources, - miniedgeLen, stops_threshold, if_drop, ruIndex) == 1 - || - check_if_diploid_primary_complex(aw[ow_max_i].v, v^1, g, reverse_sources, - miniedgeLen, stops_threshold, if_drop, ruIndex) == 1) - { - to_del = 0; - } - } - - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - ///kv > 1 - if(if_check_hap == 1 && to_del == 1) - { - if(check_if_diploid_primary_complex(av[ov_max_i].v, w^1, g, reverse_sources, - miniedgeLen, stops_threshold, if_drop, ruIndex) == 1) - { - to_del = 0; - } - } - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - ///kw > 1 - if(if_check_hap == 1 && to_del == 1) - { - if(check_if_diploid_primary_complex(aw[ow_max_i].v, v^1, g, reverse_sources, - miniedgeLen, stops_threshold, if_drop, ruIndex) == 1) - { - to_del = 0; - } - } - } - if (to_del) - av[iv].del = aw[iw].del = 1, ++n_cut; - - } - - free(b.a); - if (n_cut) - { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %lld short overlaps\n", __func__, n_cut); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return n_cut; -} - -int asg_arc_del_short_false_link(asg_t *g, float drop_ratio, float o_drop_ratio, int max_dist, -ma_hit_t_alloc* reverse_sources, long long miniedgeLen, R_to_U* ruIndex) -{ - double startTime = Get_T(); - - kvec_t(uint64_t) b; - memset(&b, 0, sizeof(b)); - - - kvec_t(uint32_t) b_f; - memset(&b_f, 0, sizeof(b_f)); - - kvec_t(uint32_t) b_r; - memset(&b_r, 0, sizeof(b_r)); - - - uint32_t v, w, n_vtx = g->n_seq * 2, n_cut = 0; - uint32_t sink; - - buf_t bub; - if (!g->is_symm) asg_symm(g); - memset(&bub, 0, sizeof(buf_t)); - bub.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - - for (v = 0; v < n_vtx; ++v) - { - if(g->seq_vis[v] == 0) - { - asg_arc_t *av = asg_arc_a(g, v); - uint32_t nv = asg_arc_n(g, v); - if(nv == 1 && asg_arc_n(g, v^1) == 1) continue; - - uint64_t t_ol = 0; - long long i; - for (i = 0; i < nv; ++i) - { - t_ol += av[i].ol; - } - kv_push(uint64_t, b, (uint64_t)(t_ol << 32 | v)); - } - } - - radix_sort_arch64(b.a, b.a + b.n); - - uint32_t min_edge; - - - uint64_t k, t; - for (k = 0; k < b.n; k++) - { - ///v is the node - v = (uint32_t)b.a[k]; - if (g->seq[v>>1].del) continue; - uint32_t nv = asg_arc_n(g, v), nw, to_del_l, to_del_r; - if (nv < 2) continue; - uint32_t kv = get_real_length(g, v, NULL), kw; - if (kv < 2) continue; - uint32_t i; - asg_arc_t *av = asg_arc_a(g, v), *aw; - - b_f.n = 0; - b_r.n = 0; - to_del_l = 0; - for (i = 0; i < nv; i++) - { - if (av[i].del) continue; - - w = av[i].v^1; - nw = asg_arc_n(g, w); - if(nw < 2) break; - kw = get_real_length(g, w, NULL); - if(kw < 2) break; - - kv_push(uint32_t, b_f, av[i].v); - kv_push(uint32_t, b_r, w); - - aw = asg_arc_a(g, w); - min_edge = (uint32_t)-1; - for (t = 0; t < nw; t++) - { - if(aw[t].del) continue; - if((aw[t].v>>1) == (v>>1)) continue; - if(aw[t].ol < min_edge) min_edge = aw[t].ol; - ///kv_push(uint32_t, b_r, aw[t].v); - } - - if(av[i].ol < min_edge * drop_ratio) to_del_l++; - } - - - - - - - - - - - - - /****************************may have bugs********************************/ - if(to_del_l != kv) - { - b_f.n = 0; - b_r.n = 0; - to_del_l = 0; - - for (i = 0; i < nv; i++) - { - if (av[i].del) continue; - - w = av[i].v^1; - nw = asg_arc_n(g, w); - if(nw < 2) break; - kw = get_real_length(g, w, NULL); - if(kw < 2) break; - - kv_push(uint32_t, b_f, av[i].v); - kv_push(uint32_t, b_r, w); - - aw = asg_arc_a(g, w); - min_edge = (uint32_t)-1; - for (t = 0; t < nw; t++) - { - if(aw[t].del) continue; - if((aw[t].v>>1) == (v>>1)) continue; - if(aw[t].ol < min_edge) min_edge = aw[t].ol; - } - - if(av[i].ol < min_edge * o_drop_ratio) to_del_l++; - } - - if(to_del_l == kv) - { - ///forward - to_del_l = 1; - for (i = 1; i < b_f.n; i++) - { - if(check_if_diploid(b_f.a[0], b_f.a[i], g, reverse_sources, miniedgeLen, ruIndex) == 1) - { - to_del_l++; - } - } - - ///backward - if(to_del_l != kv && b_r.n >= 2) - { - to_del_l = 0; - uint32_t w0 = 0, w1 = 0; - - - w = b_r.a[0]; - kw = get_real_length(g, w, NULL); - if(kw != 2) goto terminal; - aw = asg_arc_a(g, w); - nw = asg_arc_n(g, w); - for (t = 0; t < nw; t++) - { - if(aw[t].del) continue; - if((aw[t].v>>1) == (v>>1)) continue; - w0 = aw[t].v; - } - to_del_l = 1; - - - for (i = 1; i < b_r.n; i++) - { - w = b_r.a[i]; - kw = get_real_length(g, w, NULL); - if(kw != 2) goto terminal; - aw = asg_arc_a(g, w); - nw = asg_arc_n(g, w); - for (t = 0; t < nw; t++) - { - if(aw[t].del) continue; - if((aw[t].v>>1) == (v>>1)) continue; - w1 = aw[t].v; - } - - if(check_if_diploid(w0, w1, g, reverse_sources, miniedgeLen, ruIndex) == 1) - { - to_del_l++; - } - } - - } - } - } - - terminal: - /****************************may have bugs********************************/ - - - if(to_del_l != kv) continue; - - - - - - uint32_t convex1; - long long l1; - - - - - ////forward bubble - to_del_l = 0; - for (i = 0; i < b_f.n; i++) - { - if(b_f.a[i] == b_f.a[0]) - { - to_del_l = 1; - } - else - { - to_del_l = 0; - break; - } - } - //check the length - if(to_del_l == 0 && asg_bub_end_finder_with_del_advance(g, - b_f.a, b_f.n, max_dist, &bub, 0, (uint32_t)-1, &sink)==1) - { - to_del_l = 1; - } - if(to_del_l == 0 && detect_mul_bubble_end_with_bubbles(g, b_f.a, b_f.n, &convex1, &l1, NULL)) - { - to_del_l = 1; - } - - ////backward bubble - to_del_r = 0; - for (i = 0; i < b_r.n; i++) - { - if(b_r.a[i] == b_r.a[0]) - { - to_del_r = 1; - } - else - { - to_del_r = 0; - break; - } - } - if(to_del_r == 0 && asg_bub_end_finder_with_del_advance - (g, b_r.a, b_r.n, max_dist, &bub, 1, v^1, &sink)==1) - { - to_del_r = 1; - } - if(to_del_r == 0 && detect_mul_bubble_end_with_bubbles(g, b_r.a, b_r.n, &convex1, &l1, NULL)) - { - to_del_r = 1; - } - - - - - - - if (to_del_l && to_del_r) - { - for (i = 0; i < nv; ++i) - { - if (av[i].del) continue; - ++n_cut; - av[i].del = 1; - asg_arc_del(g, av[i].v^1, av[i].ul>>32^1, 1); - } - - } - } - - free(b.a); free(b_f.a); free(b_r.a); - free(bub.a); free(bub.S.a); free(bub.T.a); free(bub.b.a); free(bub.e.a); - if (n_cut) - { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %u false overlaps\n", __func__, n_cut); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return n_cut; -} - - -int asg_arc_del_short_false_link_primary(asg_t *g, float drop_ratio, float o_drop_ratio, int max_dist, -ma_hit_t_alloc* reverse_sources, long long miniedgeLen, R_to_U* ruIndex) -{ - double startTime = Get_T(); - - kvec_t(uint64_t) b; - memset(&b, 0, sizeof(b)); - - - kvec_t(uint32_t) b_f; - memset(&b_f, 0, sizeof(b_f)); - - kvec_t(uint32_t) b_r; - memset(&b_r, 0, sizeof(b_r)); - - - uint32_t v, w, n_vtx = g->n_seq * 2, n_cut = 0; - uint32_t sink; - - buf_t bub; - if (!g->is_symm) asg_symm(g); - memset(&bub, 0, sizeof(buf_t)); - bub.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - - for (v = 0; v < n_vtx; ++v) - { - if(g->seq[v>>1].c == ALTER_LABLE) continue; - - if(g->seq_vis[v] == 0) - { - asg_arc_t *av = asg_arc_a(g, v); - uint32_t nv = asg_arc_n(g, v); - if(nv == 1 && asg_arc_n(g, v^1) == 1) continue; - - uint64_t t_ol = 0; - long long i; - for (i = 0; i < nv; ++i) - { - t_ol += av[i].ol; - } - kv_push(uint64_t, b, (uint64_t)(t_ol << 32 | v)); - } - } - - radix_sort_arch64(b.a, b.a + b.n); - - uint32_t min_edge; - - - uint64_t k, t; - for (k = 0; k < b.n; k++) - { - ///v is the node - v = (uint32_t)b.a[k]; - if (g->seq[v>>1].del) continue; - uint32_t nv = asg_arc_n(g, v), nw, to_del_l, to_del_r; - if (nv < 2) continue; - uint32_t kv = get_real_length(g, v, NULL), kw; - if (kv < 2) continue; - uint32_t i; - asg_arc_t *av = asg_arc_a(g, v), *aw; - - b_f.n = 0; - b_r.n = 0; - to_del_l = 0; - for (i = 0; i < nv; i++) - { - if (av[i].del) continue; - - w = av[i].v^1; - nw = asg_arc_n(g, w); - if(nw < 2) break; - kw = get_real_length(g, w, NULL); - if(kw < 2) break; - - kv_push(uint32_t, b_f, av[i].v); - kv_push(uint32_t, b_r, w); - - aw = asg_arc_a(g, w); - min_edge = (uint32_t)-1; - for (t = 0; t < nw; t++) - { - if(aw[t].del) continue; - if((aw[t].v>>1) == (v>>1)) continue; - if(aw[t].ol < min_edge) min_edge = aw[t].ol; - ///kv_push(uint32_t, b_r, aw[t].v); - } - - if(av[i].ol < min_edge * drop_ratio) to_del_l++; - } - - - - - - - - - - - - - /****************************may have bugs********************************/ - if(to_del_l != kv) - { - b_f.n = 0; - b_r.n = 0; - to_del_l = 0; - - for (i = 0; i < nv; i++) - { - if (av[i].del) continue; - - w = av[i].v^1; - nw = asg_arc_n(g, w); - if(nw < 2) break; - kw = get_real_length(g, w, NULL); - if(kw < 2) break; - - kv_push(uint32_t, b_f, av[i].v); - kv_push(uint32_t, b_r, w); - - aw = asg_arc_a(g, w); - min_edge = (uint32_t)-1; - for (t = 0; t < nw; t++) - { - if(aw[t].del) continue; - if((aw[t].v>>1) == (v>>1)) continue; - if(aw[t].ol < min_edge) min_edge = aw[t].ol; - } - - if(av[i].ol < min_edge * o_drop_ratio) to_del_l++; - } - - if(to_del_l == kv) - { - ///forward - to_del_l = 1; - for (i = 1; i < b_f.n; i++) - { - /****************************may have bugs********************************/ - if(check_if_diploid(b_f.a[0], b_f.a[i], g, reverse_sources, miniedgeLen, ruIndex) == 1) - {/****************************may have bugs********************************/ - to_del_l++; - } - } - - ///backward - if(to_del_l != kv && b_r.n >= 2) - { - to_del_l = 0; - uint32_t w0 = 0, w1 = 0; - - - w = b_r.a[0]; - kw = get_real_length(g, w, NULL); - if(kw != 2) goto terminal; - aw = asg_arc_a(g, w); - nw = asg_arc_n(g, w); - for (t = 0; t < nw; t++) - { - if(aw[t].del) continue; - if((aw[t].v>>1) == (v>>1)) continue; - w0 = aw[t].v; - } - to_del_l = 1; - - - for (i = 1; i < b_r.n; i++) - { - w = b_r.a[i]; - kw = get_real_length(g, w, NULL); - if(kw != 2) goto terminal; - aw = asg_arc_a(g, w); - nw = asg_arc_n(g, w); - for (t = 0; t < nw; t++) - { - if(aw[t].del) continue; - if((aw[t].v>>1) == (v>>1)) continue; - w1 = aw[t].v; - } - /****************************may have bugs********************************/ - if(check_if_diploid(w0, w1, g, reverse_sources, miniedgeLen, ruIndex) == 1) - {/****************************may have bugs********************************/ - to_del_l++; - } - } - - } - } - } - - terminal: - /****************************may have bugs********************************/ - - - if(to_del_l != kv) continue; - - - - - - uint32_t convex1; - long long l1; - - - - - ////forward bubble - to_del_l = 0; - for (i = 0; i < b_f.n; i++) - { - if(b_f.a[i] == b_f.a[0]) - { - to_del_l = 1; - } - else - { - to_del_l = 0; - break; - } - } - //check the length - if(to_del_l == 0 && asg_bub_end_finder_with_del_advance(g, - b_f.a, b_f.n, max_dist, &bub, 0, (uint32_t)-1, &sink)==1) - { - to_del_l = 1; - } - if(to_del_l == 0 && detect_mul_bubble_end_with_bubbles(g, b_f.a, b_f.n, &convex1, &l1, NULL)) - { - to_del_l = 1; - } - - ////backward bubble - to_del_r = 0; - for (i = 0; i < b_r.n; i++) - { - if(b_r.a[i] == b_r.a[0]) - { - to_del_r = 1; - } - else - { - to_del_r = 0; - break; - } - } - if(to_del_r == 0 && asg_bub_end_finder_with_del_advance - (g, b_r.a, b_r.n, max_dist, &bub, 1, v^1, &sink)==1) - { - to_del_r = 1; - } - if(to_del_r == 0 && detect_mul_bubble_end_with_bubbles(g, b_r.a, b_r.n, &convex1, &l1, NULL)) - { - to_del_r = 1; - } - - - - - - - if (to_del_l && to_del_r) - { - for (i = 0; i < nv; ++i) - { - if (av[i].del) continue; - ++n_cut; - av[i].del = 1; - asg_arc_del(g, av[i].v^1, av[i].ul>>32^1, 1); - } - - } - } - - free(b.a); free(b_f.a); free(b_r.a); - free(bub.a); free(bub.S.a); free(bub.T.a); free(bub.b.a); free(bub.e.a); - if (n_cut) - { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %u false overlaps\n", __func__, n_cut); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return n_cut; -} - -int asg_arc_del_short_false_link_advance(asg_t *g, float drop_ratio, float o_drop_ratio, int max_dist, -ma_hit_t_alloc* reverse_sources, long long miniedgeLen, R_to_U* ruIndex) -{ - double startTime = Get_T(); - - kvec_t(uint64_t) b; - memset(&b, 0, sizeof(b)); - - - kvec_t(uint32_t) b_f; - memset(&b_f, 0, sizeof(b_f)); - - kvec_t(uint32_t) b_r; - memset(&b_r, 0, sizeof(b_r)); - - - uint32_t v, w, n_vtx = g->n_seq * 2, n_cut = 0; - uint32_t sink; - - buf_t bub; - if (!g->is_symm) asg_symm(g); - memset(&bub, 0, sizeof(buf_t)); - bub.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - - for (v = 0; v < n_vtx; ++v) - { - if(g->seq_vis[v] == 0) - { - asg_arc_t *av = asg_arc_a(g, v); - uint32_t nv = asg_arc_n(g, v); - if(nv == 1 && asg_arc_n(g, v^1) == 1) continue; - - uint64_t t_ol = 0; - long long i; - for (i = 0; i < nv; ++i) - { - t_ol += av[i].ol; - } - kv_push(uint64_t, b, (uint64_t)(t_ol << 32 | v)); - } - } - - radix_sort_arch64(b.a, b.a + b.n); - - uint32_t min_edge; - - uint64_t k, t; - for (k = 0; k < b.n; k++) - { - ///v is the node - v = (uint32_t)b.a[k]; - if (g->seq[v>>1].del) continue; - uint32_t nv = asg_arc_n(g, v), nw, to_del_l, to_del_r; - if (nv < 2) continue; - uint32_t kv = get_real_length(g, v, NULL), kw; - if (kv < 2) continue; - uint32_t i; - asg_arc_t *av = asg_arc_a(g, v), *aw; - - b_f.n = 0; - b_r.n = 0; - to_del_l = 0; - for (i = 0; i < nv; i++) - { - if (av[i].del) continue; - - w = av[i].v^1; - nw = asg_arc_n(g, w); - if(nw < 2) break; - kw = get_real_length(g, w, NULL); - if(kw < 2) break; - - kv_push(uint32_t, b_f, av[i].v); - kv_push(uint32_t, b_r, w); - - aw = asg_arc_a(g, w); - min_edge = (uint32_t)-1; - for (t = 0; t < nw; t++) - { - if(aw[t].del) continue; - if((aw[t].v>>1) == (v>>1)) continue; - if(aw[t].ol < min_edge) min_edge = aw[t].ol; - ///kv_push(uint32_t, b_r, aw[t].v); - } - - if(av[i].ol < min_edge * drop_ratio) to_del_l++; - } - - - - - - - - - - - - - /****************************may have bugs********************************/ - if(to_del_l != kv) - { - b_f.n = 0; - b_r.n = 0; - to_del_l = 0; - - for (i = 0; i < nv; i++) - { - if (av[i].del) continue; - - w = av[i].v^1; - nw = asg_arc_n(g, w); - if(nw < 2) break; - kw = get_real_length(g, w, NULL); - if(kw < 2) break; - - kv_push(uint32_t, b_f, av[i].v); - kv_push(uint32_t, b_r, w); - - aw = asg_arc_a(g, w); - min_edge = (uint32_t)-1; - for (t = 0; t < nw; t++) - { - if(aw[t].del) continue; - if((aw[t].v>>1) == (v>>1)) continue; - if(aw[t].ol < min_edge) min_edge = aw[t].ol; - } - - if(av[i].ol < min_edge * o_drop_ratio) to_del_l++; - } - - if(to_del_l == kv) - { - ///forward - to_del_l = 1; - for (i = 1; i < b_f.n; i++) - { - if(check_if_diploid(b_f.a[0], b_f.a[i], g, reverse_sources, miniedgeLen, ruIndex) == 1) - { - to_del_l++; - } - } - - ///backward - if(to_del_l != kv && b_r.n >= 2) - { - to_del_l = 0; - uint32_t w0 = 0, w1 = 0; - - - w = b_r.a[0]; - kw = get_real_length(g, w, NULL); - if(kw != 2) goto terminal; - aw = asg_arc_a(g, w); - nw = asg_arc_n(g, w); - for (t = 0; t < nw; t++) - { - if(aw[t].del) continue; - if((aw[t].v>>1) == (v>>1)) continue; - w0 = aw[t].v; - } - to_del_l = 1; - - - for (i = 1; i < b_r.n; i++) - { - w = b_r.a[i]; - kw = get_real_length(g, w, NULL); - if(kw != 2) goto terminal; - aw = asg_arc_a(g, w); - nw = asg_arc_n(g, w); - for (t = 0; t < nw; t++) - { - if(aw[t].del) continue; - if((aw[t].v>>1) == (v>>1)) continue; - w1 = aw[t].v; - } - - if(check_if_diploid(w0, w1, g, reverse_sources, miniedgeLen, ruIndex) == 1) - { - to_del_l++; - } - } - - } - } - } - - terminal: - /****************************may have bugs********************************/ - - - if(to_del_l != kv) continue; - - - - - - uint32_t convex1; - long long l1; - - - - - ////forward bubble - to_del_l = 0; - for (i = 0; i < b_f.n; i++) - { - if(b_f.a[i] == b_f.a[0]) - { - to_del_l = 1; - } - else - { - to_del_l = 0; - break; - } - } - //check the length - if(to_del_l == 0 && asg_bub_end_finder_with_del_advance(g, - b_f.a, b_f.n, max_dist, &bub, 0, (uint32_t)-1, &sink)==1) - { - to_del_l = 1; - } - if(to_del_l == 0 && detect_mul_bubble_end_with_bubbles(g, b_f.a, b_f.n, &convex1, &l1, NULL)) - { - to_del_l = 1; - } - - ////backward bubble - to_del_r = 0; - for (i = 0; i < b_r.n; i++) - { - if(b_r.a[i] == b_r.a[0]) - { - to_del_r = 1; - } - else - { - to_del_r = 0; - break; - } - } - if(to_del_r == 0 && asg_bub_end_finder_with_del_advance - (g, b_r.a, b_r.n, max_dist, &bub, 1, v^1, &sink)==1) - { - to_del_r = 1; - } - if(to_del_r == 0 && detect_mul_bubble_end_with_bubbles(g, b_r.a, b_r.n, &convex1, &l1, NULL)) - { - to_del_r = 1; - } - - - - - if (to_del_l && to_del_r) - { - ///fprintf(stderr, "%.*s\n", Get_NAME_LENGTH((R_INF), v>>1), Get_NAME((R_INF), v>>1)); - for (i = 0; i < nv; ++i) - { - if (av[i].del) continue; - - ++n_cut; - av[i].del = 1; - asg_arc_del(g, av[i].v^1, av[i].ul>>32^1, 1); - } - - } - } - - free(b.a); free(b_f.a); free(b_r.a); - free(bub.a); free(bub.S.a); free(bub.T.a); free(bub.b.a); free(bub.e.a); - if (n_cut) - { - asg_cleanup(g); - asg_symm(g); - } - fprintf(stderr, "[M::%s] removed %d false overlaps\n", __func__, n_cut); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - return n_cut; -} - - -int asg_arc_del_complex_false_link(asg_t *g, float drop_ratio, float o_drop_ratio, int max_dist, -ma_hit_t_alloc* reverse_sources, long long miniedgeLen) -{ - double startTime = Get_T(); - - kvec_t(uint64_t) b; - memset(&b, 0, sizeof(b)); - - - kvec_t(uint32_t) b_f; - memset(&b_f, 0, sizeof(b_f)); - - kvec_t(uint32_t) b_r; - memset(&b_r, 0, sizeof(b_r)); - - - uint32_t v, w, n_vtx = g->n_seq * 2, n_cut = 0; - - - buf_t bub; - if (!g->is_symm) asg_symm(g); - memset(&bub, 0, sizeof(buf_t)); - bub.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - - for (v = 0; v < n_vtx; ++v) - { - if(g->seq_vis[v] == 0) - { - asg_arc_t *av = asg_arc_a(g, v); - uint32_t nv = asg_arc_n(g, v); - - if(nv == 1 && asg_arc_n(g, v^1) == 1) continue; - - uint64_t t_ol = 0; - long long i; - for (i = 0; i < nv; ++i) - { - t_ol += av[i].ol; - } - kv_push(uint64_t, b, (uint64_t)(t_ol << 32 | v)); - } - } - - - radix_sort_arch64(b.a, b.a + b.n); - - uint32_t min_edge; - - - uint64_t k, t; - for (k = 0; k < b.n; k++) - { - ///v is the node - v = (uint32_t)b.a[k]; - if (g->seq[v>>1].del) continue; - uint32_t nv = asg_arc_n(g, v), nw, to_del; - if (nv < 2) continue; - uint32_t kv = get_real_length(g, v, NULL), kw; - if (kv < 2) continue;///V must have two out-nodes - uint32_t i; - asg_arc_t *av = asg_arc_a(g, v), *aw; - - b_f.n = 0; - b_r.n = 0; - to_del = 0; - for (i = 0; i < nv; i++) - { - if (av[i].del) continue; - - w = av[i].v^1; - nw = asg_arc_n(g, w); - if(nw < 2) break; - kw = get_real_length(g, w, NULL); - if(kw < 2) break; - - kv_push(uint32_t, b_f, av[i].v); - kv_push(uint32_t, b_r, w); - - aw = asg_arc_a(g, w); - min_edge = (uint32_t)-1; - for (t = 0; t < nw; t++) - { - if(aw[t].del) continue; - if((aw[t].v>>1) == (v>>1)) continue; - if(aw[t].ol < min_edge) min_edge = aw[t].ol; - } - - if(av[i].ol < min_edge * drop_ratio) to_del++; - } - - if(to_del != kv) continue; - - for (i = 0; i < nv; ++i) - { - if (av[i].del) continue; - ++n_cut; - av[i].del = 1; - asg_arc_del(g, av[i].v^1, av[i].ul>>32^1, 1); - } - } - - - if(n_cut > 0) - { - for (v = 0; v < n_vtx; ++v) - { - uint32_t nv = asg_arc_n(g, v); - if (g->seq[v>>1].del) - { - continue; - } - - if(nv < 2) - { - continue; - } - - - if(asg_bub_finder_without_del_advance(g, v, max_dist, &bub) == 1) - { - uint32_t i; - g->seq_vis[v] = 3; - g->seq_vis[v^1] = 3; - for (i = 0; i < bub.b.n; i++) - { - g->seq_vis[bub.b.a[i]] = 3; - g->seq_vis[bub.b.a[i]^1] = 3; - } - } - } - - - for (v = 0; v < n_vtx; ++v) - { - if(g->seq_vis[v] == 3) continue; - - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - uint32_t i; - for (i = 0; i < nv; ++i) - { - if (av[i].del && g->seq_vis[av[i].v] != 3) - { - av[i].del = 0; - asg_arc_del(g, av[i].v^1, av[i].ul>>32^1, 0); - } - } - } - } - - - - - free(b.a); free(b_f.a); free(b_r.a); - free(bub.a); free(bub.S.a); free(bub.T.a); free(bub.b.a); free(bub.e.a); - if (n_cut) - { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d false overlaps\n", __func__, n_cut); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return n_cut; -} - - -int asg_arc_del_short_diploid_by_exact(asg_t *g, int max_ext, ma_hit_t_alloc* sources) -{ - double startTime = Get_T(); - kvec_t(uint64_t) b; - memset(&b, 0, sizeof(b)); - - uint32_t v, n_vtx = g->n_seq * 2; - long long n_cut = 0; - - for (v = 0; v < n_vtx; ++v) - { - if(g->seq_vis[v] == 0) - { - asg_arc_t *av = asg_arc_a(g, v); - uint32_t nv = asg_arc_n(g, v); - if (nv < 2) continue; - long long i; - for (i = 0; i < nv; ++i) - { - kv_push(uint64_t, b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); - } - } - } - - radix_sort_arch64(b.a, b.a + b.n); - - uint64_t k; - for (k = 0; k < b.n; k++) - { - - asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; - ///v is self id, w is the id of another end - uint32_t i, iv, iw, v = (a->ul)>>32, w = a->v^1, to_del = 0; - uint32_t nv = asg_arc_n(g, v), nw = asg_arc_n(g, w), kv, kw; - uint32_t ov_max = 0, ow_max = 0, ov_max_i = 0; - asg_arc_t *av, *aw; - ///nv must be >= 2 - if (nv == 1 && nw == 1) continue; - av = asg_arc_a(g, v); - aw = asg_arc_a(g, w); - - - ///calculate the longest edge for v and w - for (i = 0, kv = 0; i < nv; ++i) { - if (av[i].del) continue; - if (ov_max < av[i].ol) - { - ov_max = av[i].ol; - ov_max_i = i; - } - ++kv; - } - if (kv >= 2 && a->ol == ov_max) continue; - - - for (i = 0, kw = 0; i < nw; ++i) { - if (aw[i].del) continue; - if (ow_max < aw[i].ol) - { - ow_max = aw[i].ol; - } - ++kw; - } - if (kw >= 2 && a->ol == ow_max) continue; - - ///if (kv == 1 && kw == 1) continue; - if (kv <= 1 && kw <= 1) continue; - - - ///to see which one is the current edge (from v and w) - for (iv = 0; iv < nv; ++iv) - if (av[iv].v == (w^1)) break; - for (iw = 0; iw < nw; ++iw) - if (aw[iw].v == (v^1)) break; - ///if one edge has been deleted, it should be deleted in both direction - if (av[iv].del && aw[iw].del) continue; - - - ///if this edge is an inexact edge - if(a->el == 0 && - sources[v>>1].is_fully_corrected == 1 && - sources[w>>1].is_fully_corrected == 1) - { - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - } - } - - if(a->el == 0 && - sources[v>>1].is_fully_corrected == 1 && - sources[w>>1].is_fully_corrected == 0) - { - /****************************may have bugs********************************/ - ///if(av[ov_max_i].el == 1 && sources[av[ov_max_i].v>>1].is_fully_corrected) - /****************************may have bugs********************************/ - if(av[ov_max_i].el == 1 && sources[av[ov_max_i].v>>1].is_fully_corrected == 1) - { - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - } - } - } - - - - if (to_del) - av[iv].del = aw[iw].del = 1, ++n_cut; - - } - - free(b.a); - if (n_cut) - { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %lld inexact overlaps\n", __func__, n_cut); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return n_cut; -} - -int asg_arc_del_short_diploid_by_exact_trio(asg_t *g, int max_ext, ma_hit_t_alloc* sources) -{ - double startTime = Get_T(); - kvec_t(uint64_t) b; - memset(&b, 0, sizeof(b)); - - uint32_t v, n_vtx = g->n_seq * 2; - long long n_cut = 0; - - for (v = 0; v < n_vtx; ++v) - { - if(g->seq_vis[v] == 0) - { - asg_arc_t *av = asg_arc_a(g, v); - uint32_t nv = asg_arc_n(g, v); - if (nv < 2) continue; - long long i; - for (i = 0; i < nv; ++i) - { - kv_push(uint64_t, b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); - } - } - } - - radix_sort_arch64(b.a, b.a + b.n); - - uint64_t k; - for (k = 0; k < b.n; k++) - { - - asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; - ///v is self id, w is the id of another end - uint32_t i, iv, iw, v = (a->ul)>>32, w = a->v^1, to_del = 0; - uint32_t nv = asg_arc_n(g, v), nw = asg_arc_n(g, w), kv, kw; - uint32_t ov_max = 0, ow_max = 0, ov_max_i = 0, trio_flag, non_trio_flag; - asg_arc_t *av, *aw; - ///nv must be >= 2 - if (nv == 1 && nw == 1) continue; - av = asg_arc_a(g, v); - aw = asg_arc_a(g, w); - kv = get_real_length(g, v, NULL); - kw = get_real_length(g, w, NULL); - if (kv <= 1 && kw <= 1) continue; - trio_flag = get_tip_trio_infor(g, v^1); - non_trio_flag = (uint32_t)-1; - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - - - ///calculate the longest edge for v and w - for (i = 0, kv = 0; i < nv; ++i) { - if (av[i].del) continue; - ++kv; - if(get_tip_trio_infor(g, av[i].v) == non_trio_flag) continue; - if (ov_max < av[i].ol) - { - ov_max = av[i].ol; - ov_max_i = i; - } - ///++kv; - } - if (kv >= 2 && a->ol == ov_max) continue; - - - for (i = 0, kw = 0; i < nw; ++i) { - if (aw[i].del) continue; - ++kw; - if (get_tip_trio_infor(g, aw[i].v) == non_trio_flag) continue; - if (ow_max < aw[i].ol) - { - ow_max = aw[i].ol; - } - ///++kw; - } - if (kw >= 2 && a->ol == ow_max) continue; - if (kv <= 1 && kw <= 1) continue; - - - ///to see which one is the current edge (from v and w) - for (iv = 0; iv < nv; ++iv) - if (av[iv].v == (w^1)) break; - for (iw = 0; iw < nw; ++iw) - if (aw[iw].v == (v^1)) break; - ///if one edge has been deleted, it should be deleted in both direction - if (av[iv].del && aw[iw].del) continue; - - - ///if this edge is an inexact edge - if(a->el == 0 && - sources[v>>1].is_fully_corrected == 1 && - sources[w>>1].is_fully_corrected == 1) - { - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - } - } - - if(a->el == 0 && - sources[v>>1].is_fully_corrected == 1 && - sources[w>>1].is_fully_corrected == 0) - { - /****************************may have bugs********************************/ - ///if(av[ov_max_i].el == 1 && sources[av[ov_max_i].v>>1].is_fully_corrected) - /****************************may have bugs********************************/ - if(av[ov_max_i].el == 1 && sources[av[ov_max_i].v>>1].is_fully_corrected == 1) - { - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - } - } - } - - - - if (to_del) - av[iv].del = aw[iw].del = 1, ++n_cut; - - } - - free(b.a); - if (n_cut) - { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %lld inexact overlaps\n", __func__, n_cut); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return n_cut; -} - - -int asg_arc_del_short_diploi_by_suspect_edge(asg_t *g, int max_ext) -{ - double startTime = Get_T(); - kvec_t(uint64_t) b; - memset(&b, 0, sizeof(b)); - - uint32_t v, n_vtx = g->n_seq * 2; - long long n_cut = 0; - - for (v = 0; v < n_vtx; ++v) - { - ///if(g->seq_vis[v] == 0) - { - asg_arc_t *av = asg_arc_a(g, v); - uint32_t nv = asg_arc_n(g, v); - if (nv < 2) continue; - - long long i; - for (i = 0; i < nv; ++i) - { - ///means there is a large indel at this edge - if(av[i].no_l_indel == 0) - { - kv_push(uint64_t, b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); - } - } - } - } - - - radix_sort_arch64(b.a, b.a + b.n); - - - uint64_t k; - for (k = 0; k < b.n; k++) - { - - asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; - ///v is self id, w is the id of another end - uint32_t i, iv, iw, v = (a->ul)>>32, w = a->v^1, to_del = 0; - uint32_t nv = asg_arc_n(g, v), nw = asg_arc_n(g, w), kv, kw; - asg_arc_t *av, *aw; - ///nv must be >= 2 - if (nv == 1 && nw == 1) continue; - av = asg_arc_a(g, v); - aw = asg_arc_a(g, w); - - ///calculate the longest edge for v and w - for (i = 0, kv = 0; i < nv; ++i) - { - if (av[i].del) continue; - ++kv; - } - - for (i = 0, kw = 0; i < nw; ++i) - { - if (aw[i].del) continue; - ++kw; - } - - if (kv == 1 && kw == 1) continue; - - ///to see which one is the current edge (from v and w) - for (iv = 0; iv < nv; ++iv) - if (av[iv].v == (w^1)) break; - for (iw = 0; iw < nw; ++iw) - if (aw[iw].v == (v^1)) break; - - ///if one edge has been deleted, it should be deleted in both direction - if (av[iv].del && aw[iw].del) continue; - - - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - } - - if (to_del) - av[iv].del = aw[iw].del = 1, ++n_cut; - } - - free(b.a); - if (n_cut) - { - asg_cleanup(g); - asg_symm(g); - } - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %lld suspect overlaps\n", __func__, n_cut); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return n_cut; -} - -int if_potential_false_node(ma_hit_t_alloc* paf, uint64_t rLen, ma_sub_t* max_left, ma_sub_t* max_right, int if_set) -{ - max_left->s = max_right->s = rLen; - max_left->e = max_right->e = 0; - - long long j; - uint32_t qs, qe; - for (j = 0; j < paf->length; j++) - { - if(paf->buffer[j].del) continue; - if(paf->buffer[j].el != 1) continue; - - qs = Get_qs(paf->buffer[j]); - qe = Get_qe(paf->buffer[j]); - - ///overlaps from left side - if(qs == 0) - { - if(qs < max_left->s) max_left->s = qs; - if(qe > max_left->e) max_left->e = qe; - } - - ///overlaps from right side - if(qe == rLen) - { - if(qs < max_right->s) max_right->s = qs; - if(qe > max_right->e) max_right->e = qe; - } - - ///note: if (qs == 0 && qe == rLen) - ///this overlap would be added to both b_left and b_right - ///that is what we want - } - - if (max_left->e > max_right->s) return 0; - - long long new_left_e, new_right_s; - new_left_e = max_left->e; - new_right_s = max_right->s; - - for (j = 0; j < paf->length; j++) - { - if(paf->buffer[j].del) continue; - if(paf->buffer[j].el != 1) continue; - - qs = Get_qs(paf->buffer[j]); - qe = Get_qe(paf->buffer[j]); - ///check contained overlaps - if(qs != 0 && qe != rLen) - { - ///[qs, qe), [max_left.s, max_left.e) - if(qs < max_left->e && qe > max_left->e) - { - ///if(qe > max_left->e) max_left->e = qe; - if(qe > max_left->e && qe > new_left_e) new_left_e = qe; - } - - ///[qs, qe), [max_right.s, max_right.e) - if(qs < max_right->s && qe > max_right->s) - { - ///if(qs < max_right->s) max_right->s = qs; - if(qs < max_right->s && qs < new_right_s) new_right_s = qs; - } - - - - if(if_set) - { - max_left->e = new_left_e; - max_right->s = new_right_s; - } - } - } - - max_left->e = new_left_e; - max_right->s = new_right_s; - - if (max_left->e > max_right->s) return 0; - - return 1; -} - -//reomve edge between two chromesomes -//this node must be a single read -int asg_arc_del_false_node(asg_t *g, ma_hit_t_alloc* sources, int max_ext) -{ - double startTime = Get_T(); - kvec_t(uint64_t) b; - memset(&b, 0, sizeof(b)); - ma_sub_t max_left, max_right; - - uint32_t v, n_vtx = g->n_seq * 2; - long long n_cut = 0; - - for (v = 0; v < n_vtx; ++v) - { - if(g->seq_vis[v] == 0) - { - if(asg_arc_n(g, v)!=1 || asg_arc_n(g, v^1)!=1) - { - continue; - } - - - if(asg_is_single_edge(g, asg_arc_a(g, v)[0].v, v>>1) < 2) - { - continue; - } - - if(asg_is_single_edge(g, asg_arc_a(g, v^1)[0].v, (v^1)>>1) < 2) - { - continue; - } - - if(asg_arc_a(g, v)[0].el == 1) - { - continue; - } - - if(if_potential_false_node(&(sources[v>>1]), g->seq[v>>1].len, &max_left, &max_right, 1)==0) - { - continue; - } - - asg_arc_t *av = asg_arc_a(g, v); - kv_push(uint64_t, b, (uint64_t)((uint64_t)av[0].ol << 32 | (av - g->arc))); - } - } - - radix_sort_arch64(b.a, b.a + b.n); - - uint64_t k; - ///here all edges are inexact matches - for (k = 0; k < b.n; k++) - { - - asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; - ///v is self id, w is the id of another end - uint32_t i, iv, iw, v = (a->ul)>>32, w = a->v^1; - uint32_t nv = asg_arc_n(g, v), nw = asg_arc_n(g, w), kv, kw; - asg_arc_t *av, *aw; - av = asg_arc_a(g, v); - aw = asg_arc_a(g, w); - - - ///calculate the longest edge for v and w - for (i = 0, kv = 0; i < nv; ++i) { - if (av[i].del) continue; - ++kv; - } - - for (i = 0, kw = 0; i < nw; ++i) { - if (aw[i].del) continue; - ++kw; - } - - if (kv < 1 || kw < 2) continue; - - ///to see which one is the current edge (from v and w) - for (iv = 0; iv < nv; ++iv) - if (av[iv].v == (w^1)) break; - for (iw = 0; iw < nw; ++iw) - if (aw[iw].v == (v^1)) break; - ///if one edge has been deleted, it should be deleted in both direction - if (av[iv].del && aw[iw].del) continue; - - - - uint32_t el_edges = 0; - ///there should be at least two available edges in aw - for (i = 0; i < nw; i++) - { - if (aw[i].del) continue; - - if(i != iw && aw[i].el == 1) - { - el_edges++; - } - } - - if(el_edges > 0 && av[iv].el == 0) - { - asg_seq_del(g, v>>1); - ++n_cut; - } - } - - free(b.a); - if (n_cut) - { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %lld single nodes\n", __func__, n_cut); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return n_cut; -} - -int64_t count_edges_v_w(asg_t *g, uint32_t v, uint32_t w) -{ - asg_arc_t* av = asg_arc_a(g, v); uint32_t nv = asg_arc_n(g, v), i, occ = 0; - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - if(av[i].v == w) occ++; - } - return occ; -} - -void update_ug_ou(ma_ug_t *ug, asg_t *sg) -{ - uint32_t k, i, uv, uw, rv, rw, nv; asg_arc_t *ue, *av; - for (k = 0; k < ug->g->n_arc; k++) { - ue = &(ug->g->arc[k]); ue->ou = 0; - uv = ue->ul>>32; uw = ue->v; - if(uv&1) rv = ug->u.a[uv>>1].start^1; - else rv = ug->u.a[uv>>1].end^1; - - if(uw&1) rw = ug->u.a[uw>>1].end; - else rw = ug->u.a[uw>>1].start; - - av = asg_arc_a(sg, rv); - nv = asg_arc_n(sg, rv); - for (i = 0; i < nv; i++) { - if(av[i].v == rw) break; - } - assert(i < nv); - ue->ou = av[i].ou; - } - - // asg_arc_t *e; uint32_t v, w; - // for (k = 0; k < sg->n_arc; k++) { - // e = &(sg->arc[k]); - // v = e->v^1; w = (e->ul>>32)^1; - // av = asg_arc_a(sg, v); nv = asg_arc_n(sg, v); - // for (i = 0; i < nv; i++) { - // if(av[i].v == w) break; - // } - // if(i >= nv || av[i].ou != e->ou) fprintf(stderr, "[M::%s::asymmetry]\n", __func__); - // } - - // for (k = 0; k < ug->g->n_arc; k++) { - // e = &(ug->g->arc[k]); - // v = e->v^1; w = (e->ul>>32)^1; - // av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); - // for (i = 0; i < nv; i++) { - // if(av[i].v == w) break; - // } - // if(i >= nv || av[i].ou != e->ou) fprintf(stderr, "[M::%s::asymmetry]\n", __func__); - // } -} - - -#define arc_cnt(g, v) ((uint32_t)(g)->idx[(v)]) -#define arc_first(g, v) ((g)->arc[(g)->idx[(v)]>>32]) - -ma_ug_t *ma_ug_gen(asg_t *g) -{ - asg_cleanup(g); - int32_t *mark; - uint32_t i, v, n_vtx = g->n_seq * 2; - ///is a queue - kdq_t(uint64_t) *q; - ma_ug_t *ug; - - ug = (ma_ug_t*)calloc(1, sizeof(ma_ug_t)); - ug->g = asg_init(); - ///each node has two directions - mark = (int32_t*)calloc(n_vtx, 4); - - q = kdq_init(uint64_t); - for (v = 0; v < n_vtx; ++v) { - uint32_t w, x, l, start, end, len; - ma_utg_t *p; - ///what's the usage of mark array - ///mark array is used to mark if this node has already been included in a contig - /****************************may have bugs********************************/ - ///if (g->seq[v>>1].del || arc_cnt(g, v) == 0 || mark[v]) continue; - if (g->seq[v>>1].del || mark[v]) continue; - if (arc_cnt(g, v) == 0 && arc_cnt(g, (v^1)) != 0) continue; - /****************************may have bugs********************************/ - mark[v] = 1; - q->count = 0, start = v, end = v^1, len = 0; - // forward - w = v; - while (1) { - /** - * w----->x - * w<-----x - * that means the only suffix of w is x, and the only prefix of x is w - **/ - if (arc_cnt(g, w) != 1) break; - x = arc_first(g, w).v; // w->x - if (arc_cnt(g, x^1) != 1) break; - - /** - * another direction of w would be marked as used (since w has been used) - **/ - mark[x] = mark[w^1] = 1; - ///l is the edge length, instead of overlap length - ///note: edge length is different with overlap length - l = asg_arc_len(arc_first(g, w)); - kdq_push(uint64_t, q, (uint64_t)w<<32 | l); - end = x^1, len += l; - w = x; - if (x == v) break; - } - if (start != (end^1) || kdq_size(q) == 0) { // linear unitig - ///length of seq, instead of edge - l = g->seq[end>>1].len; - kdq_push(uint64_t, q, (uint64_t)(end^1)<<32 | l); - len += l; - } else { // circular unitig - start = end = UINT32_MAX; - goto add_unitig; // then it is not necessary to do the backward - } - // backward - x = v; - while (1) { // similar to forward but not the same - if (arc_cnt(g, x^1) != 1) break; - w = arc_first(g, x^1).v ^ 1; // w->x - if (arc_cnt(g, w) != 1) break; - mark[x] = mark[w^1] = 1; - l = asg_arc_len(arc_first(g, w)); - ///w is the seq id + direction, l is the length of edge - ///push element to the front of a queue - kdq_unshift(uint64_t, q, (uint64_t)w<<32 | l); - - // fprintf(stderr, "uId: %u, >%.*s (%u)\n", - // ug->u.n, (int)Get_NAME_LENGTH((R_INF), w>>1), Get_NAME((R_INF), w>>1), w>>1); - - start = w, len += l; - x = w; - } -add_unitig: - if (start != UINT32_MAX) mark[start] = mark[end] = 1; - kv_pushp(ma_utg_t, ug->u, &p); - p->s = 0, p->start = start, p->end = end, p->len = len, p->n = kdq_size(q), p->circ = (start == UINT32_MAX); - p->m = p->n; - kv_roundup32(p->m); - p->a = (uint64_t*)malloc(8 * p->m); - //all elements are saved here - for (i = 0; i < kdq_size(q); ++i) - p->a[i] = kdq_at(q, i); - } - kdq_destroy(uint64_t, q); - - // add arcs between unitigs; reusing mark for a different purpose - //ug saves all unitigs - for (v = 0; v < n_vtx; ++v) mark[v] = -1; - - //mark all start nodes and end nodes of all unitigs - for (i = 0; i < ug->u.n; ++i) { - if (ug->u.a[i].circ) continue; - mark[ug->u.a[i].start] = i<<1 | 0; - mark[ug->u.a[i].end] = i<<1 | 1; - } - - //scan all edges - for (i = 0; i < g->n_arc; ++i) { - asg_arc_t *p = &g->arc[i]; - if (p->del) continue; - ///to connect two unitigs, we need to connect the end of unitig x to the start of unitig y - ///so we need to ^1 to get the reverse direction of (x's end)? - ///>=0 means this node is a start/end node of an unitig - ///means this node is a intersaction node - if (mark[p->ul>>32^1] >= 0 && mark[p->v] >= 0) { - asg_arc_t *q; - uint32_t u = mark[p->ul>>32^1]^1; - int l = ug->u.a[u>>1].len - p->ol; - if (l < 0) l = 1; - q = asg_arc_pushp(ug->g); - q->ol = p->ol, q->del = 0; - q->ul = (uint64_t)u<<32 | l; - q->v = mark[p->v]; q->ou = 0; - q->el = p->el; - } - } - for (i = 0; i < ug->u.n; ++i) - asg_seq_set(ug->g, i, ug->u.a[i].len, 0); - asg_cleanup(ug->g); - free(mark); - return ug; -} - -ma_ug_t *ma_ug_gen_phase(asg_t *g, uint32_t min_occ, double cutoff) -{ - // fprintf(stderr, "\n-0-[M::%s] min_occ::%u, cutoff::%f\n", __func__, min_occ, cutoff); - asg_cleanup(g); - int32_t *mark; - uint32_t i, v, n_vtx = g->n_seq * 2, fn, mn, fn0, mn0, fn1, mn1, n1, cn, k, st, pt, ct, sz, ez; - uint64_t z; - ///is a queue - kdq_t(uint64_t) *q; - asg64_v uidx; kv_init(uidx); - - ma_ug_t *ug; - - ug = (ma_ug_t*)calloc(1, sizeof(ma_ug_t)); - ug->g = asg_init(); - ///each node has two directions - mark = (int32_t*)calloc(n_vtx, 4); - - q = kdq_init(uint64_t); - for (v = 0; v < n_vtx; ++v) { - uint32_t w, x, l, start, end, len; - ma_utg_t *p; - if (g->seq[v>>1].del || mark[v]) continue; - if (arc_cnt(g, v) == 0 && arc_cnt(g, (v^1)) != 0) continue; - mark[v] = 1; - q->count = 0, start = v, end = v^1, len = 0; fn = mn = 0; - // forward - w = v; - while (1) { - /** - * w----->x - * w<-----x - * that means the only suffix of w is x, and the only prefix of x is w - **/ - if (arc_cnt(g, w) != 1) break; - x = arc_first(g, w).v; // w->x - if (arc_cnt(g, x^1) != 1) break; - /** - * another direction of w would be marked as used (since w has been used) - **/ - mark[x] = mark[w^1] = 1; - ///l is the edge length, instead of overlap length - ///note: edge length is different with overlap length - l = asg_arc_len(arc_first(g, w)); - kdq_push(uint64_t, q, (uint64_t)w<<32 | l); - if(R_INF.trio_flag[w>>1] == FATHER) fn++; - if(R_INF.trio_flag[w>>1] == MOTHER) mn++; - end = x^1, len += l; - w = x; - if (x == v) break; - } - if (start != (end^1) || kdq_size(q) == 0) { // linear unitig - ///length of seq, instead of edge - l = g->seq[end>>1].len; - kdq_push(uint64_t, q, (uint64_t)(end^1)<<32 | l); - if(R_INF.trio_flag[end>>1] == FATHER) fn++; - if(R_INF.trio_flag[end>>1] == MOTHER) mn++; - len += l; - } else { // circular unitig - start = end = UINT32_MAX; - goto add_unitig; // then it is not necessary to do the backward - } - // backward - x = v; - while (1) { // similar to forward but not the same - if (arc_cnt(g, x^1) != 1) break; - w = arc_first(g, x^1).v ^ 1; // w->x - if (arc_cnt(g, w) != 1) break; - mark[x] = mark[w^1] = 1; - l = asg_arc_len(arc_first(g, w)); - ///w is the seq id + direction, l is the length of edge - ///push element to the front of a queue - kdq_unshift(uint64_t, q, (uint64_t)w<<32 | l); - if(R_INF.trio_flag[w>>1] == FATHER) fn++; - if(R_INF.trio_flag[w>>1] == MOTHER) mn++; - // fprintf(stderr, "uId: %u, >%.*s (%u)\n", - // ug->u.n, (int)Get_NAME_LENGTH((R_INF), w>>1), Get_NAME((R_INF), w>>1), w>>1); - - start = w, len += l; - x = w; - } -add_unitig: - if (start != UINT32_MAX) mark[start] = mark[end] = 1; - // fprintf(stderr, "\n-0-[M::%s] fn::%u, mn::%u\n", __func__, fn, mn); - cn = MIN(fn, mn); - // if((cn > min_occ) && (cn > ((fn+mn)*cutoff))) - if((cn <= ((fn+mn)*cutoff)) || (cn <= min_occ)) { - kv_pushp(ma_utg_t, ug->u, &p); - p->s = 0, p->start = start, p->end = end, p->len = len, p->n = kdq_size(q), p->circ = (start == UINT32_MAX); - p->m = p->n; - kv_roundup32(p->m); - p->a = (uint64_t*)malloc(8 * p->m); - //all elements are saved here - for (i = 0; i < kdq_size(q); ++i) p->a[i] = kdq_at(q, i); - } else if(kdq_size(q)) { - ct = R_INF.trio_flag[kdq_at(q, 0)>>33]; - if((ct != FATHER) && (ct != MOTHER)) ct = AMBIGU; - pt = ct; - fn0 = fn; mn0 = mn; uidx.n = fn = mn = 0; - if(ct == FATHER) fn++; if(ct == MOTHER) mn++; - for (k = 1, l = 0; k <= kdq_size(q); k++) { - st = 0; ct = AMBIGU; - if(k == kdq_size(q)) { - st = 1; - } else { - ct = R_INF.trio_flag[kdq_at(q, k)>>33]; - if((ct != FATHER) && (ct != MOTHER)) ct = AMBIGU; - if((ct != AMBIGU) && (pt != AMBIGU) && (ct != pt)) { - st = 1; - } - } - if(st) { - // fprintf(stderr, "-1-[M::%s] l::%u, k::%u, kdq_size(q)::%u, fn::%u, mn::%u, ct::%u, pt::%u\n", - // __func__, l, k, (uint32_t)kdq_size(q), fn, mn, ct, pt); - if(k < kdq_size(q)) { - assert(fn || mn); assert((!fn) || (!mn)); - } - z = l<<1; z |= (((uint64_t)MAX(fn, mn))<<32); - if(mn) z |= 1; - kv_push(uint64_t, uidx, z); - fn = mn = 0; l = k; - } - if(ct != AMBIGU) pt = ct; - if(ct == FATHER) fn++; if(ct == MOTHER) mn++; - } - - - fn = mn = 0; fn1 = mn1 = n1 = 0; - if(uidx.a[0]&1) mn += uidx.a[0]>>32; - else fn += uidx.a[0]>>32; - for (k = 1, l = 0; k <= uidx.n; k++) { - st = 0; - if(k == uidx.n) { - st = 1; - } else { - if(uidx.a[k]&1) mn += uidx.a[k]>>32; - else fn += uidx.a[k]>>32; - cn = MIN(fn, mn); - if((cn > min_occ) && (cn > ((fn+mn)*cutoff))) st = 1; - // fprintf(stderr, "-2-[M::%s] fn::%u, mn::%u, cn::%u, ((fn+mn)*cutoff)::%u, st::%u\n", - // __func__, fn, mn, cn, (uint32_t)(((fn+mn)*cutoff)), st); - } - if(st) { - // fprintf(stderr, "-3-[M::%s] fn::%u, mn::%u\n", __func__, fn, mn); - sz = ((uint32_t)uidx.a[l])>>1; - ez = ((k>1):(kdq_size(q))); - assert(ez > sz); n1 += ez - sz; - kv_pushp(ma_utg_t, ug->u, &p); - if ((start == UINT32_MAX) && (sz == 0) && (ez == kdq_size(q))) {///circle - p->s = 0, p->start = start, p->end = end, p->len = len, p->n = kdq_size(q), p->circ = (start == UINT32_MAX); - p->m = p->n; - kv_roundup32(p->m); - p->a = (uint64_t*)malloc(8 * p->m); - //all elements are saved here - for (i = 0; i < kdq_size(q); ++i) { - p->a[i] = kdq_at(q, i); - ct = R_INF.trio_flag[p->a[i]>>33]; - if((ct != FATHER) && (ct != MOTHER)) ct = AMBIGU; - if(ct == FATHER) fn1++; if(ct == MOTHER) mn1++; - } - } else { - p->s = 0; p->len = 0; p->circ = 0; - p->start = kdq_at(q, sz)>>32; - p->end = (kdq_at(q, (ez-1))>>32)^1; - p->m = p->n = ez - sz; kv_roundup32(p->m); - p->a = (uint64_t*)malloc(8 * p->m); - - for (i = sz, z = 0; i+1 < ez; i++, z++) { - p->a[z] = kdq_at(q, i); p->len += (uint32_t)p->a[z]; - ct = R_INF.trio_flag[p->a[z]>>33]; - if((ct != FATHER) && (ct != MOTHER)) ct = AMBIGU; - if(ct == FATHER) fn1++; if(ct == MOTHER) mn1++; - } - p->a[z] = kdq_at(q, i); p->a[z] >>= 32; p->a[z] <<= 32; - p->a[z] |= g->seq[p->a[z]>>33].len; p->len += (uint32_t)p->a[z]; - ct = R_INF.trio_flag[p->a[z]>>33]; - if((ct != FATHER) && (ct != MOTHER)) ct = AMBIGU; - if(ct == FATHER) fn1++; if(ct == MOTHER) mn1++; - } - fn = mn = 0; l = k; - if(k < uidx.n) { - if(uidx.a[k]&1) mn += uidx.a[k]>>32; - else fn += uidx.a[k]>>32; - } - } - } - assert(n1 == kdq_size(q)); - assert(fn1 == fn0); assert(mn1 == mn0); - } - } - kdq_destroy(uint64_t, q); kv_destroy(uidx); - - // add arcs between unitigs; reusing mark for a different purpose - //ug saves all unitigs - for (v = 0; v < n_vtx; ++v) mark[v] = -1; - - //mark all start nodes and end nodes of all unitigs - for (i = 0; i < ug->u.n; ++i) { - if (ug->u.a[i].circ) continue; - mark[ug->u.a[i].start] = i<<1 | 0; - mark[ug->u.a[i].end] = i<<1 | 1; - } - - //scan all edges - for (i = 0; i < g->n_arc; ++i) { - asg_arc_t *p = &g->arc[i]; - if (p->del) continue; - ///to connect two unitigs, we need to connect the end of unitig x to the start of unitig y - ///so we need to ^1 to get the reverse direction of (x's end)? - ///>=0 means this node is a start/end node of an unitig - ///means this node is a intersaction node - if (mark[p->ul>>32^1] >= 0 && mark[p->v] >= 0) { - asg_arc_t *q; - uint32_t u = mark[p->ul>>32^1]^1; - int l = ug->u.a[u>>1].len - p->ol; - if (l < 0) l = 1; - q = asg_arc_pushp(ug->g); - q->ol = p->ol, q->del = 0; - q->ul = (uint64_t)u<<32 | l; - q->v = mark[p->v]; q->ou = 0; - q->el = p->el; - } - } - for (i = 0; i < ug->u.n; ++i) - asg_seq_set(ug->g, i, ug->u.a[i].len, 0); - asg_cleanup(ug->g); - free(mark); - return ug; -} - -ma_ug_t *ma_ug_gen_primary(asg_t *g, uint8_t flag) -{ - asg_cleanup(g); - int32_t *mark; - uint32_t i, v, n_vtx = g->n_seq * 2; - ///is a queue - kdq_t(uint64_t) *q; - ma_ug_t *ug; - - ug = (ma_ug_t*)calloc(1, sizeof(ma_ug_t)); - ug->g = asg_init(); - ///each node has two directions - mark = (int32_t*)calloc(n_vtx, 4); - - ///for each untig, all node have the same direction - ///and all node except the last one just have one edge - ///the last one may have multiple edges - q = kdq_init(uint64_t); - for (v = 0; v < n_vtx; ++v) { - uint32_t w, x, l, start, end, len; - ma_utg_t *p; - ///what's the usage of mark array - ///mark array is used to mark if this node has already been included in a contig - /****************************may have hap bugs********************************/ - ///if (g->seq[v>>1].del || arc_cnt(g, v) == 0 || mark[v] || g->seq[v>>1].c != flag) continue; - ///if (g->seq[v>>1].del || arc_cnt(g, v) == 0 || mark[v] || (g->seq[v>>1].c & flag) == 0) continue; - ///if (g->seq[v>>1].del || arc_cnt(g, v) == 0 || mark[v]) continue; - if (g->seq[v>>1].del || mark[v]) continue; - if (arc_cnt(g, v) == 0 && arc_cnt(g, (v^1)) != 0) continue; - if(flag == PRIMARY_LABLE && g->seq[v>>1].c == ALTER_LABLE) continue; - if(flag == ALTER_LABLE && g->seq[v>>1].c != ALTER_LABLE) continue; - /****************************may have hap bugs********************************/ - mark[v] = 1; - q->count = 0, start = v, end = v^1, len = 0; - // forward - w = v; - while (1) { - /** - * w----->x - * w<-----x - * that means the only suffix of w is x, and the only prefix of x is w - **/ - if (arc_cnt(g, w) != 1) break; - x = arc_first(g, w).v; // w->x - if (arc_cnt(g, x^1) != 1) break; - - /** - * another direction of w would be marked as used (since w has been used) - **/ - mark[x] = mark[w^1] = 1; - ///l is the edge length, instead of overlap length - ///note: edge length is different with overlap length - l = asg_arc_len(arc_first(g, w)); - kdq_push(uint64_t, q, (uint64_t)w<<32 | l); - end = x^1, len += l; - w = x; - if (x == v) break; - } - ///kdq_size(q) == 0 means there is just one read - if (start != (end^1) || kdq_size(q) == 0) { // linear unitig - ///length of seq, instead of edge - l = g->seq[end>>1].len; - kdq_push(uint64_t, q, (uint64_t)(end^1)<<32 | l); - len += l; - } else { // circular unitig - start = end = UINT32_MAX; - goto add_unitig; // then it is not necessary to do the backward - } - // backward - x = v; - while (1) { // similar to forward but not the same - if (arc_cnt(g, x^1) != 1) break; - w = arc_first(g, x^1).v ^ 1; // w->x - if (arc_cnt(g, w) != 1) break; - mark[x] = mark[w^1] = 1; - l = asg_arc_len(arc_first(g, w)); - ///w is the seq id + direction, l is the length of edge - ///push element to the front of a queue - kdq_unshift(uint64_t, q, (uint64_t)w<<32 | l); - start = w, len += l; - x = w; - } -add_unitig: - if (start != UINT32_MAX) mark[start] = mark[end] = 1; - kv_pushp(ma_utg_t, ug->u, &p); - p->s = 0, p->start = start, p->end = end, p->len = len, p->n = kdq_size(q), p->circ = (start == UINT32_MAX); - p->m = p->n; - kv_roundup32(p->m); - p->a = (uint64_t*)malloc(8 * p->m); - //all elements are saved here - for (i = 0; i < kdq_size(q); ++i) - p->a[i] = kdq_at(q, i); - } - kdq_destroy(uint64_t, q); - - // add arcs between unitigs; reusing mark for a different purpose - //ug saves all unitigs - for (v = 0; v < n_vtx; ++v) mark[v] = -1; - - //mark all start nodes and end nodes of all unitigs - ///note ug->u.a[i].start == ug->u.a[i].a[0] - ///but ug->u.a[i].end = ug->u.a[i].a[ug->u.a[i].n-1]^1 - ///ug->u.a[i].start has the same direction as other non-end node - ///while ug->u.a[i].end is the only one with reverse direction - for (i = 0; i < ug->u.n; ++i) { - if (ug->u.a[i].circ) continue; - ///i is the untig id - mark[ug->u.a[i].start] = i<<1 | 0; - mark[ug->u.a[i].end] = i<<1 | 1; - } - - //scan all edges - for (i = 0; i < g->n_arc; ++i) { - asg_arc_t *p = &g->arc[i]; - if (p->del) continue; - /** - p->ul: |____________31__________|__________1___________|______________32_____________| - qns direction of overlap length of this node (not overlap length) - (based on query) - p->v : |___________31___________|__________1___________| - tns reverse direction of overlap - (based on target) - p->ol: overlap length - **/ - ///to connect two unitigs, we need to connect the end of unitig x to the start of unitig y - ///so we need to ^1 to get the reverse direction of (x's end)? - ///>=0 means this node is a start/end node of an unitig - ///means this node is a intersaction node - /**for one untig, - start end - -----> <------ - so if we want to find the edge between two untigs, their start and end look like: - - start end - -----> <------ - --------------------------- - - start end - -----> <------ - --------------------------- - p->ul>>32^1 is the end of the first untig, - p->v is the start of the second untig - **/ - if (mark[p->ul>>32^1] >= 0 && mark[p->v] >= 0) { - asg_arc_t *q; - uint32_t u = mark[p->ul>>32^1]^1; - int l = ug->u.a[u>>1].len - p->ol; - if (l < 0) l = 1; - q = asg_arc_pushp(ug->g); - q->ol = p->ol, q->del = 0; - q->ul = (uint64_t)u<<32 | l; - q->v = mark[p->v]; q->ou = 0; - q->el = p->el; - } - } - for (i = 0; i < ug->u.n; ++i) - asg_seq_set(ug->g, i, ug->u.a[i].len, 0); - asg_cleanup(ug->g); - free(mark); - return ug; -} - -static char comp_tab[] = { // complement base - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 'T', 'V', 'G', 'H', 'E', 'F', 'C', 'D', 'I', 'J', 'M', 'L', 'K', 'N', 'O', - 'P', 'Q', 'Y', 'S', 'A', 'A', 'B', 'W', 'X', 'R', 'Z', 91, 92, 93, 94, 95, - 64, 't', 'v', 'g', 'h', 'e', 'f', 'c', 'd', 'i', 'j', 'm', 'l', 'k', 'n', 'o', - 'p', 'q', 'y', 's', 'a', 'a', 'b', 'w', 'x', 'r', 'z', 123, 124, 125, 126, 127 -}; - - -void recover_fake_read(UC_Read* result, UC_Read* tmp, ma_utg_t *u, -All_reads *RNF, const ma_sub_t *coverage_cut) -{ - uint32_t j, k, ori, start, l = 0, eLen, rId, readLen; - if(result->size < u->len) - { - result->size = u->len; - result->seq = (char*)realloc(result->seq,sizeof(char)*(result->size)); - } - char* readS = NULL; - - for (j = 0; j < u->n; ++j) { - rId = u->a[j]>>33; - ///uId = i; - ori = u->a[j]>>32&1; - start = l; - eLen = (uint32_t)u->a[j]; - l += eLen; - - if(eLen == 0) continue; - - recover_UC_Read(tmp, RNF, rId); - readS = tmp->seq + coverage_cut[rId].s; - readLen = coverage_cut[rId].e - coverage_cut[rId].s; - - - if (!ori) // forward strand - { - for (k = 0; k < eLen; k++) - { - result->seq[start + k] = readS[k]; - } - } - else - { - for (k = 0; k < eLen; k++) - { - uint8_t c = (uint8_t)readS[readLen - 1 - k]; - result->seq[start + k] = c >= 128? 'N' : comp_tab[c]; - } - } - } - - result->length = u->end - u->start; - for (j = u->start; j < u->end; j++) - { - result->seq[j - u->start] = result->seq[j]; - } -} - -void get_overlapLen(uint32_t rId, ma_hit_t_alloc* sources, uint32_t* exactLen, uint32_t* inexactLen) -{ - (*exactLen) = (*inexactLen) = 0; - ma_hit_t_alloc* x = &(sources[rId]); - ma_hit_t *h = NULL; - uint32_t i, len; - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - len = Get_qe((*h)) - Get_qs((*h)); - if(h->el == 1) - { - (*exactLen) += len; - } - else - { - (*inexactLen) += len; - } - } -} - - -void reduce_ma_utg_t(ma_utg_t* collection, asg_t* read_g, ma_hit_t_alloc* sources, -ma_sub_t *coverage_cut, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* newE) -{ - asg_arc_t t_f; - asg_arc_t* av = NULL; - uint32_t m = 0, k, i, nv; - for (i = 0; i < collection->n; i++) - { - if(collection->a[i] == (uint64_t)-1) - { - // if(newE) asg_seq_del(read_g, collection->a[i]>>33); - continue; - } - - collection->a[m] = collection->a[i]; - m++; - } - collection->n = m; - - - uint32_t totalLen = 0, v, w, l; - for (i = 0; i < collection->n - 1; i++) - { - v = (uint64_t)(collection->a[i])>>32; - w = (uint64_t)(collection->a[i + 1])>>32; - - - - - /*******************************for debug************************************/ - l = (uint32_t)-1; - av = asg_arc_a(read_g, v); - nv = asg_arc_n(read_g, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - l = asg_arc_len(av[k]); - break; - } - } - - if(k == nv) - { - for (k = 0; k < edge->a.n; k++) - { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) - { - l = asg_arc_len(edge->a.a[k]); - break; - } - } - - if(k == edge->a.n) - { - if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, v, w, &t_f)==0) - { - fprintf(stderr, "####ERROR1: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", - v>>1, v&1, w>>1, w&1, read_g->r_seq); - } - l = asg_arc_len(t_f); - - - if(newE) - { - kv_push(asg_arc_t, newE->a, t_f); - if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, w^1, v^1, &t_f)==0) - { - fprintf(stderr, "####ERROR2: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", - v>>1, v&1, w>>1, w&1, read_g->r_seq); - } - kv_push(asg_arc_t, newE->a, t_f); - } - - } - else if(newE) - { - kv_push(asg_arc_t, newE->a, edge->a.a[k]); - for (k = 0; k < edge->a.n; k++) - { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == (w^1) && edge->a.a[k].v == (v^1)) - { - l = asg_arc_len(edge->a.a[k]); - break; - } - } - kv_push(asg_arc_t, newE->a, edge->a.a[k]); - } - } - if(l == (uint32_t)-1) fprintf(stderr, "ERROR\n"); - /*******************************for debug************************************/ - - - - - - - - - - collection->a[i] = v; collection->a[i] = collection->a[i]<<32; - collection->a[i] = collection->a[i] | (uint64_t)(l); - totalLen += l; - } - - if(i < collection->n) - { - if(collection->circ) - { - v = (uint64_t)(collection->a[i])>>32; - w = (uint64_t)(collection->a[0])>>32; - - - - - /*******************************for debug************************************/ - l = (uint32_t)-1; - av = asg_arc_a(read_g, v); - nv = asg_arc_n(read_g, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - l = asg_arc_len(av[k]); - break; - } - } - - if(k == nv) - { - for (k = 0; k < edge->a.n; k++) - { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) - { - l = asg_arc_len(edge->a.a[k]); - break; - } - } - - if(k == edge->a.n) - { - if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, v, w, &t_f)==0) - { - fprintf(stderr, "####ERROR1: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", - v>>1, v&1, w>>1, w&1, read_g->r_seq); - } - l = asg_arc_len(t_f); - - if(newE) - { - kv_push(asg_arc_t, newE->a, t_f); - if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, w^1, v^1, &t_f)==0) - { - fprintf(stderr, "####ERROR2: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", - v>>1, v&1, w>>1, w&1, read_g->r_seq); - } - kv_push(asg_arc_t, newE->a, t_f); - } - } - else if(newE) - { - kv_push(asg_arc_t, newE->a, edge->a.a[k]); - for (k = 0; k < edge->a.n; k++) - { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == (w^1) && edge->a.a[k].v == (v^1)) - { - l = asg_arc_len(edge->a.a[k]); - break; - } - } - kv_push(asg_arc_t, newE->a, edge->a.a[k]); - } - } - if(l == (uint32_t)-1) fprintf(stderr, "ERROR\n"); - /*******************************for debug************************************/ - - - - - - - - - - - - - collection->a[i] = v; collection->a[i] = collection->a[i]<<32; - collection->a[i] = collection->a[i] | (uint64_t)(l); - - totalLen += l; - } - else - { - v = (uint64_t)(collection->a[i])>>32; - l = read_g->seq[v>>1].len; - collection->a[i] = v; - collection->a[i] = collection->a[i]<<32; - collection->a[i] = collection->a[i] | (uint64_t)(l); - totalLen += l; - } - } - - collection->len = totalLen; - if(!collection->circ) - { - collection->start = collection->a[0]>>32; - collection->end = (collection->a[collection->n-1]>>32)^1; - } -} - - -void reduce_ma_utg_t_scaf(ma_utg_t *in, asg_t *rg, ma_hit_t_alloc* src, ma_sub_t *cov, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* newE) -{ - asg_arc_t t_f; - asg_arc_t* av = NULL; - uint32_t m = 0, k, i, nv; - for (i = 0; i < in->n; i++) { - if(in->a[i] == (uint64_t)-1) { - // if(newE) asg_seq_del(read_g, collection->a[i]>>33); - continue; - } - - in->a[m] = in->a[i]; - m++; - } - in->n = m; - - - uint32_t totalLen = 0, v, w, l; - for (i = 0; i + 1 < in->n; i++) { - v = (uint64_t)(in->a[i])>>32; - w = (uint64_t)(in->a[i + 1])>>32; - l = Get_READ_LENGTH(R_INF, (v>>1)); ///for Ns - - if((!IS_SCAF_READ(R_INF, v>>1)) && (!IS_SCAF_READ(R_INF, w>>1))) { - /*******************************for debug************************************/ - l = (uint32_t)-1; - av = asg_arc_a(rg, v); nv = asg_arc_n(rg, v); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == w) { - l = asg_arc_len(av[k]); - break; - } - } - - if(k == nv) { - for (k = 0; k < edge->a.n; k++) { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) { - l = asg_arc_len(edge->a.a[k]); - break; - } - } - - if(k == edge->a.n) { - if(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, v, w, &t_f)==0) { - fprintf(stderr, "####ERROR1: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", - v>>1, v&1, w>>1, w&1, rg->r_seq); - } - l = asg_arc_len(t_f); - - - if(newE) { - kv_push(asg_arc_t, newE->a, t_f); - if(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, w^1, v^1, &t_f)==0) { - fprintf(stderr, "####ERROR2: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", - v>>1, v&1, w>>1, w&1, rg->r_seq); - } - kv_push(asg_arc_t, newE->a, t_f); - } - - } - else if(newE) { - kv_push(asg_arc_t, newE->a, edge->a.a[k]); - for (k = 0; k < edge->a.n; k++) { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == (w^1) && edge->a.a[k].v == (v^1)) { - l = asg_arc_len(edge->a.a[k]); - break; - } - } - kv_push(asg_arc_t, newE->a, edge->a.a[k]); - } - } - if(l == (uint32_t)-1) fprintf(stderr, "ERROR\n"); - /*******************************for debug************************************/ - } - - - in->a[i] = v; in->a[i] = in->a[i]<<32; - in->a[i] = in->a[i] | (uint64_t)(l); - totalLen += l; - } - - if(i < in->n) { - if(in->circ) { - v = (uint64_t)(in->a[i])>>32; - w = (uint64_t)(in->a[0])>>32; - l = Get_READ_LENGTH(R_INF, (v>>1)); ///for Ns - - if((!IS_SCAF_READ(R_INF, v>>1)) && (!IS_SCAF_READ(R_INF, w>>1))) { - /*******************************for debug************************************/ - l = (uint32_t)-1; - av = asg_arc_a(rg, v); - nv = asg_arc_n(rg, v); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == w) { - l = asg_arc_len(av[k]); - break; - } - } - - if(k == nv) { - for (k = 0; k < edge->a.n; k++) { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) { - l = asg_arc_len(edge->a.a[k]); - break; - } - } - - if(k == edge->a.n) { - if(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, v, w, &t_f)==0) { - fprintf(stderr, "####ERROR1: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", - v>>1, v&1, w>>1, w&1, rg->r_seq); - } - l = asg_arc_len(t_f); - - if(newE) { - kv_push(asg_arc_t, newE->a, t_f); - if(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, w^1, v^1, &t_f)==0) { - fprintf(stderr, "####ERROR2: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", - v>>1, v&1, w>>1, w&1, rg->r_seq); - } - kv_push(asg_arc_t, newE->a, t_f); - } - } else if(newE) { - kv_push(asg_arc_t, newE->a, edge->a.a[k]); - for (k = 0; k < edge->a.n; k++) { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == (w^1) && edge->a.a[k].v == (v^1)) { - l = asg_arc_len(edge->a.a[k]); - break; - } - } - kv_push(asg_arc_t, newE->a, edge->a.a[k]); - } - } - if(l == (uint32_t)-1) fprintf(stderr, "ERROR\n"); - /*******************************for debug************************************/ - } - - in->a[i] = v; in->a[i] = in->a[i]<<32; - in->a[i] = in->a[i] | (uint64_t)(l); - - totalLen += l; - } else { - v = (uint64_t)(in->a[i])>>32; - l = rg->seq[v>>1].len; - in->a[i] = v; - in->a[i] = in->a[i]<<32; - in->a[i] = in->a[i] | (uint64_t)(l); - totalLen += l; - } - } - - in->len = totalLen; - if(!in->circ) { - in->start = in->a[0]>>32; - in->end = (in->a[in->n-1]>>32)^1; - } -} - - -uint32_t detect_exact_ovec(ma_utg_t* collection, asg_t* read_g, ma_hit_t_alloc* sources, -ma_sub_t *coverage_cut, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, -uint32_t src, uint32_t dest_idx) -{ - asg_arc_t *t = NULL, i_t; - uint32_t i, k, dest; - for (i = dest_idx; i < collection->n; i++) - { - t = NULL; - dest = (uint64_t)(collection->a[i])>>32; - if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, src, dest, &i_t) == 0) - { - for (k = 0; k < edge->a.n; k++) - { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == src && edge->a.a[k].v == dest) - { - t = &(edge->a.a[k]); - break; - } - } - } - else - { - t = &i_t; - } - - if(t == NULL) return (uint32_t)-1; - if(t->el != 1) continue; - return i; - } - - return (uint32_t)-1; -} - -void get_specific_edge(ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, asg_t* read_g, int max_hang, -int min_ovlp, uint32_t query, uint32_t target, asg_arc_t* t) -{ - uint32_t nv, k; - (*t).ul = (uint64_t)-1; (*t).v = (uint32_t)-1; - if(read_g) - { - asg_arc_t* av = asg_arc_a(read_g, query); - nv = asg_arc_n(read_g, query); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == target) - { - (*t) = av[k]; - break; - } - } - } - - if((*t).ul == (uint64_t)-1) - { - if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, query, target, t)==0) - { - (*t).ul = (uint64_t)-1; - } - } - - if((*t).ul == (uint64_t)-1) - { - for (k = 0; k < edge->a.n; k++) - { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == query && edge->a.a[k].v == target) - { - (*t) = edge->a.a[k]; - break; - } - } - if(k == edge->a.n) fprintf(stderr, "ERROR\n"); - } - -} - -uint32_t polish_unitig(ma_utg_t* collection, asg_t* read_g, ma_hit_t_alloc* sources, -ma_sub_t *coverage_cut, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, -kvec_asg_arc_t_warp* newE) -{ - if(collection->m == 0) return 0; - if(collection->n < 3) return 0; - uint32_t i, k, v, pre, pre_i, afte, afte_i, exactLen, inexactLen, skip = 0; - uint32_t min_inexactLen, max_exactLen; - asg_arc_t pE, aE; - - pre = (uint64_t)(collection->a[0])>>32; pre_i = 0; afte_i = (uint32_t)-1; - for (i = 1; i < collection->n - 1; i++) { - if(collection->a[i] == (uint64_t)-1) continue; - ///v and after must be available - v = (uint64_t)(collection->a[i])>>32; - afte = (uint64_t)(collection->a[i+1])>>32; - - get_specific_edge(sources, coverage_cut, NULL, edge, pre_i == i-1? read_g:NULL, max_hang, min_ovlp, - v^1, pre^1, &pE); - get_specific_edge(sources, coverage_cut, NULL, edge, read_g, max_hang, min_ovlp, - v, afte, &aE); - - if(pE.el == 1 && aE.el == 1) - { - pre = (uint64_t)(collection->a[i])>>32; pre_i = i; - continue; - } - - ///pre must be a good read, we need to find a good after - ///update a new afte - afte_i = detect_exact_ovec(collection, read_g, sources, coverage_cut, edge, - max_hang, min_ovlp, pre, i+1); - if(afte_i == (uint32_t)-1) - { - pre = (uint64_t)(collection->a[i])>>32; pre_i = i; - continue; - } - afte = (uint64_t)(collection->a[afte_i])>>32; - - - min_inexactLen = (uint32_t)-1;max_exactLen = 0; - for (k = i; k < afte_i; k++) - { - get_overlapLen((uint64_t)(collection->a[k])>>33, sources, &exactLen, &inexactLen); - if(inexactLen < min_inexactLen) - { - min_inexactLen = inexactLen; - max_exactLen = exactLen; - } - } - - get_overlapLen(pre>>1, sources, &exactLen, &inexactLen); - if((inexactLen > min_inexactLen) || (inexactLen == min_inexactLen && exactLen <= max_exactLen)) - { - pre = (uint64_t)(collection->a[i])>>32; pre_i = i; - continue; - } - - get_overlapLen(afte>>1, sources, &exactLen, &inexactLen); - if((inexactLen > min_inexactLen) || (inexactLen == min_inexactLen && exactLen <= max_exactLen)) - { - pre = (uint64_t)(collection->a[i])>>32; pre_i = i; - continue; - } - - for (k = i; k < afte_i; k++) - { - collection->a[k] = (uint64_t)-1; - skip++; - } - } - - if(skip == 0) return 0; - reduce_ma_utg_t(collection, read_g, sources, coverage_cut, edge, max_hang, min_ovlp, newE); - - return 1; -} - - -uint32_t polish_unitig_scaf(ma_utg_t* in, asg_t* rg, ma_hit_t_alloc* src, ma_sub_t *cov, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* newE) -{ - if(in->m == 0) return 0; - if(in->n < 3) return 0; - uint32_t i, k, v, pre, pre_i, afte, afte_i, exactLen, inexactLen, skip = 0, z, l; - uint32_t min_inexactLen, max_exactLen; - asg_arc_t pE, aE; - - for (z = 1, l = 0; z <= in->n; z++) { - if(z == in->n || IS_SCAF_READ(R_INF, (in->a[z])>>33) ) { - if(z - l >= 3) { - pre = (uint64_t)(in->a[l])>>32; pre_i = l; afte_i = (uint32_t)-1; - for (i = l + 1; i < z - 1; i++) { - if(in->a[i] == (uint64_t)-1) continue; - ///v and after must be available - v = (uint64_t)(in->a[i])>>32; - afte = (uint64_t)(in->a[i+1])>>32; - - get_specific_edge(src, cov, NULL, edge, pre_i == i-1? rg:NULL, max_hang, min_ovlp, v^1, pre^1, &pE); - get_specific_edge(src, cov, NULL, edge, rg, max_hang, min_ovlp, v, afte, &aE); - - if(pE.el == 1 && aE.el == 1) { - pre = (uint64_t)(in->a[i])>>32; pre_i = i; - continue; - } - - ///pre must be a good read, we need to find a good after - ///update a new afte - afte_i = detect_exact_ovec(in, rg, src, cov, edge, max_hang, min_ovlp, pre, i+1); - if(afte_i == (uint32_t)-1) { - pre = (uint64_t)(in->a[i])>>32; pre_i = i; - continue; - } - afte = (uint64_t)(in->a[afte_i])>>32; - - - min_inexactLen = (uint32_t)-1;max_exactLen = 0; - for (k = i; k < afte_i; k++) { - get_overlapLen((uint64_t)(in->a[k])>>33, src, &exactLen, &inexactLen); - if(inexactLen < min_inexactLen) { - min_inexactLen = inexactLen; - max_exactLen = exactLen; - } - } - - get_overlapLen(pre>>1, src, &exactLen, &inexactLen); - if((inexactLen > min_inexactLen) || (inexactLen == min_inexactLen && exactLen <= max_exactLen)) { - pre = (uint64_t)(in->a[i])>>32; pre_i = i; - continue; - } - - get_overlapLen(afte>>1, src, &exactLen, &inexactLen); - if((inexactLen > min_inexactLen) || (inexactLen == min_inexactLen && exactLen <= max_exactLen)) { - pre = (uint64_t)(in->a[i])>>32; pre_i = i; - continue; - } - - for (k = i; k < afte_i; k++) { - in->a[k] = (uint64_t)-1; - skip++; - } - } - } - l = z; - } - } - - if(skip == 0) return 0; - reduce_ma_utg_t_scaf(in, rg, src, cov, edge, max_hang, min_ovlp, newE); - - return 1; -} - - -void print_rough_inconsistent_sites(ma_utg_t* collection, uint32_t cur_i, uint32_t next_i, -asg_t* read_g, All_reads *RNF, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -kvec_asg_arc_t_warp* edge, UC_Read* r_read, UC_Read* q_read, int max_hang, int min_ovlp, -uint32_t c_beg, uint32_t rate_thre, kvec_t_u32_warp* exact_count, kvec_t_u32_warp* total_count, -const char* prefix, int uID, FILE* fp, bed_in* interval) -{ - uint32_t v, w, i, rate; - int v_beg, v_end, v_sub_beg, v_sub_end, w_beg, w_end, w_sub_beg, w_sub_end, i_beg, i_end, j; - asg_arc_t t; - bed_interval* p = NULL; - v = (uint64_t)(collection->a[cur_i])>>32; - ///last element - if(cur_i == collection->n-1 && next_i == collection->n) - { - if(!collection->circ) - { - next_i = (uint32_t)-1; - } - else - { - next_i = 0; - } - } - - - if(next_i != ((uint32_t)-1)) - { - w = (uint64_t)(collection->a[next_i])>>32; - - get_specific_edge(sources, coverage_cut, NULL, edge, read_g, max_hang, min_ovlp, v, w, &t); - v_beg = 0; v_end = asg_arc_len(t) - 1; - if(v&1) - { - v_beg = Get_READ_LENGTH((*RNF), (v>>1)) - v_beg - 1; - v_end = Get_READ_LENGTH((*RNF), (v>>1)) - v_end - 1; - w = v_beg; v_beg = v_end; v_end = w; - } - } - else - { - v_beg = 0; v_end = Get_READ_LENGTH((*RNF), (v>>1)) - 1; - } - - kv_resize(uint32_t, exact_count->a, (uint32_t)(v_end - v_beg + 1)); - memset(exact_count->a.a, 0, (v_end-v_beg+1)*sizeof(uint32_t)); - kv_resize(uint32_t, total_count->a, (uint32_t)(v_end - v_beg + 1)); - memset(total_count->a.a, 0, (v_end-v_beg+1)*sizeof(uint32_t)); - exact_count->a.n = total_count->a.n = (v_end-v_beg+1); - - recover_UC_sub_Read(r_read, v_beg, v_end - v_beg + 1, 0, RNF, v>>1); - ma_hit_t_alloc* x = &(sources[v>>1]); - ma_hit_t *h = NULL; - ///[v_beg, v_end] must be the end of read, which means v_beg = 0 or v_end = Get_READ_LENGTH((*RNF), (v>>1)) - 1 - - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - if(inter_interval(v_beg, v_end, Get_qs((*h)), Get_qe((*h)) - 1, - &v_sub_beg, &v_sub_end) == 0) - { - continue; - } - - if(h->el) - { - for (j = v_sub_beg; j <= v_sub_end; j++) - { - exact_count->a.a[j-v_beg]++; - total_count->a.a[j-v_beg]++; - } - continue; - } - - w_beg = Get_ts((*h)); w_end = Get_te((*h)) - 1; - if(h->rev) - { - w_beg = Get_READ_LENGTH((*RNF), Get_tn((*h))) - w_beg - 1; - w_end = Get_READ_LENGTH((*RNF), Get_tn((*h))) - w_end - 1; - w = w_beg; w_beg = w_end; w_end = w; - } - - - - w_sub_beg = w_beg + (v_sub_beg - Get_qs((*h))); - if(w_sub_beg >= (int)(Get_READ_LENGTH((*RNF), Get_tn((*h))))) - { - w_sub_beg = Get_READ_LENGTH((*RNF), Get_tn((*h))) - 1; - } - - - w_sub_end = w_end - ((int)(Get_qe((*h))) - 1 - v_sub_end); - if(w_sub_end < 0) w_sub_end = 0; - if(w_sub_beg > w_sub_end || (v_sub_end-v_sub_beg) != (w_sub_end-w_sub_beg)) - { - for (j = v_sub_beg; j <= v_sub_end; j++) - { - total_count->a.a[j-v_beg]++; - } - continue; - } - - recover_UC_sub_Read(q_read, w_sub_beg, w_sub_end-w_sub_beg +1, h->rev, RNF, Get_tn((*h))); - if(if_exact_match(r_read->seq, r_read->length, q_read->seq, q_read->length, - v_sub_beg-v_beg, v_sub_end-v_beg, 0, q_read->length-1)) - { - for (j = v_sub_beg; j <= v_sub_end; j++) - { - exact_count->a.a[j-v_beg]++; - total_count->a.a[j-v_beg]++; - } - } - else - { - for (j = v_sub_beg; j <= v_sub_end; j++) - { - total_count->a.a[j-v_beg]++; - } - } - } - - i_beg = i_end = -1; - v = (uint64_t)(collection->a[cur_i])>>32; - uint32_t inexact = 0, total = 0; - for (i = 0; i < total_count->a.n; i++) - { - if(total_count->a.a[i] == 0) - { - rate = 100; - } - else - { - rate = ((total_count->a.a[i] - exact_count->a.a[i])*100)/total_count->a.a[i]; - } - - if(rate >= rate_thre) ///inexact rate - { - ///start a new interval - if(i_beg == -1 && i_end == -1) - { - i_beg = i_end = i; - } - else///extend current interval - { - i_end++; - } - total = total + total_count->a.a[i]; - inexact = inexact + (total_count->a.a[i] - exact_count->a.a[i]); - } - else///end an interval - { - if(i_beg != -1 && i_end != -1) - { - ///i_beg and i_end are the offsets in comparsion to v_beg - v_sub_beg = i_beg + v_beg; - v_sub_end = i_end + v_beg; - if(v&1) - { - i_beg = (v_end - v_beg + 1) - i_beg - 1; - i_end = (v_end - v_beg + 1) - i_end - 1; - w = i_beg; i_beg = i_end; i_end = w; - } - i_end++; - rate = (total == 0)? 100 : (inexact*100)/total; - - if(prefix != NULL && fp != NULL) - { - fprintf(fp,"%s%.6d%c\t%u\t%u\t%u\t", prefix, uID, "lc"[collection->circ], - (uint32_t)(i_beg + c_beg), (uint32_t)(i_end + c_beg), rate); - fprintf(fp,"%.*s", (int)Get_NAME_LENGTH((*RNF), (v>>1)), Get_NAME((*RNF), (v>>1))); - for (j = 0; j < (int)x->length; j++) - { - h = &(x->buffer[j]); - if(inter_interval(v_sub_beg, v_sub_end, Get_qs((*h)), Get_qe((*h)) - 1, - &w_sub_beg, &w_sub_end) == 0) - { - continue; - } - fprintf(fp,",%.*s", (int)Get_NAME_LENGTH((*RNF), Get_tn((*h))), Get_NAME((*RNF), Get_tn((*h)))); - } - fprintf(fp,"\n"); - } - else if(interval != NULL) - { - kv_pushp(bed_interval, *interval, &p); - p->beg = (uint32_t)(i_beg + c_beg); - p->end = (uint32_t)(i_end + c_beg); - } - - } - - i_beg = i_end = -1; - inexact = total = 0; - } - } - - if(i_beg != -1 && i_end != -1) - { - ///i_beg and i_end are the offsets in comparsion to v_beg - v_sub_beg = i_beg + v_beg; - v_sub_end = i_end + v_beg; - if(v&1) - { - i_beg = (v_end - v_beg + 1) - i_beg - 1; - i_end = (v_end - v_beg + 1) - i_end - 1; - w = i_beg; i_beg = i_end; i_end = w; - } - i_end++; - rate = (total == 0)? 100 : (inexact*100)/total; - - if(prefix != NULL && fp != NULL) - { - fprintf(fp,"%s%.6d%c\t%u\t%u\t%u\t", prefix, uID, "lc"[collection->circ], - (uint32_t)(i_beg + c_beg), (uint32_t)(i_end + c_beg), rate); - fprintf(fp,"%.*s", (int)Get_NAME_LENGTH((*RNF), (v>>1)), Get_NAME((*RNF), (v>>1))); - for (j = 0; j < (int)x->length; j++) - { - h = &(x->buffer[j]); - if(inter_interval(v_sub_beg, v_sub_end, Get_qs((*h)), Get_qe((*h)) - 1, - &w_sub_beg, &w_sub_end) == 0) - { - continue; - } - fprintf(fp,",%.*s", (int)Get_NAME_LENGTH((*RNF), Get_tn((*h))), Get_NAME((*RNF), Get_tn((*h)))); - } - fprintf(fp,"\n"); - } - else if(interval != NULL) - { - kv_pushp(bed_interval, *interval, &p); - p->beg = (uint32_t)(i_beg + c_beg); - p->end = (uint32_t)(i_end + c_beg); - } - } - -} - - - -int get_consensus_rate(ma_utg_t* collection, uint32_t cur_i, uint32_t next_i, -asg_t* read_g, All_reads *RNF, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -kvec_asg_arc_t_warp* edge, UC_Read* r_read, UC_Read* q_read, int max_hang, int min_ovlp, -int* r_match, int* r_total) -{ - (*r_match) = (*r_total) = 0; - if(cur_i < 1) return -1; - asg_arc_t *t = NULL, i_t; - uint32_t v, w, k, v_beg, v_end, w_beg, w_end; - int j; - if(collection->a[cur_i] == (uint64_t)-1 || collection->a[next_i] == (uint64_t)-1) return 0; - - v = (uint64_t)(collection->a[cur_i])>>32; - w = (uint64_t)(collection->a[next_i])>>32; - - if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, v, w, &i_t) == 0) - { - for (k = 0; k < edge->a.n; k++) - { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) - { - t = &(edge->a.a[k]); - break; - } - } - } - else - { - t = &i_t; - } - - if(t == NULL) return -1; - v_beg = 0; v_end = asg_arc_len(*t) - 1; r_read->length = 0; - ///cur_i must >= 1 - for (j = cur_i-1; j >= 0; j--) - { - if(collection->a[j] == (uint64_t)-1) continue; - - w = (uint64_t)(collection->a[j])>>32; - t = NULL; - - if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, w, v, &i_t) == 0) - { - for (k = 0; k < edge->a.n; k++) - { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == w && edge->a.a[k].v == v) - { - t = &(edge->a.a[k]); - break; - } - } - } - else - { - t = &i_t; - } - - if(t == NULL) break; - - w_beg = asg_arc_len(*t); - w_end = MIN(((int)(w_beg + v_end)), ((int)(read_g->seq[w>>1].len-1))); - // if(t->el == 1) - // { - // if(r_read->length == 0) recover_UC_sub_Read(r_read, v_beg, v_end - v_beg + 1, v&1, RNF, v>>1); - // ///for debug: check if v[v_beg, v_end] == w[w_beg, w_end] - // recover_UC_sub_Read(q_read, w_beg, w_end - w_beg +1, w&1, RNF, w>>1); - // ///q_read->length<=r_read->length - // if(if_exact_match(r_read->seq, r_read->length, q_read->seq, q_read->length, - // 0, q_read->length-1, 0, q_read->length-1) == 0) - // { - // fprintf(stderr, "ERROR: cur_i: %u, j: %d, r_len: %lld, q_len: %lld\n", cur_i, j, r_read->length, q_read->length); - // } - // } - - //filter overlaps which cannot cover the whole [v_beg, v_end] - if(w_end - w_beg != v_end - v_beg) break; - - (*r_total)++; - - if(t->el == 1) - { - (*r_match)++; - } - else - { - if(r_read->length == 0) recover_UC_sub_Read(r_read, v_beg, v_end - v_beg + 1, v&1, RNF, v>>1); - recover_UC_sub_Read(q_read, w_beg, w_end - w_beg +1, w&1, RNF, w>>1); - ///q_read->length<=r_read->length - if(if_exact_match(r_read->seq, r_read->length, q_read->seq, q_read->length, - 0, q_read->length-1, 0, q_read->length-1) == 1) - { - (*r_match)++; - } - } - } - - - return 1; -} - -uint32_t polish_unitig_advance(ma_utg_t* collection, asg_t* read_g, All_reads *RNF, -ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, kvec_asg_arc_t_warp* edge, -UC_Read* r_read, UC_Read* q_read, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* newE) -{ - if(collection->m == 0) return 0; - if(collection->n < 3) return 0; - uint32_t i, skip = 0; - int match_v, total_v, max_i, match_max, k; - double match_rate, match_rate_max; - - ///we should be able to handle i = collection->n-1 - for (i = 1; i < collection->n-1; i++) - { - ///in practice, collection->a[i] and collection->a[i+1] must be available - ///collection->a[index] might be unavailable only if index < i - if(get_consensus_rate(collection, i, i+1, read_g, RNF, sources, coverage_cut, - edge, r_read, q_read, max_hang, min_ovlp, &match_v, &total_v) != 1) - { - continue; - } - - match_rate = (total_v == 0)? 0:((double)(match_v)/(double)(total_v)); - ///most reads support collection[i], so it is right - if(match_v >= total_v * 0.5 && total_v > 0 && match_v > 0) continue; - - max_i = i; match_max = match_v; match_rate_max = match_rate; - for (k = i - 1; k >= 0; k--) - { - if(collection->a[k] == (uint64_t)-1) continue; - ///collection->a[k] might be unavailable, while collection->a[i+1] must be available - ///return -1 means there is no overlap from k to i+1 - if(get_consensus_rate(collection, k, i+1, read_g, RNF, sources, coverage_cut, - edge, r_read, q_read, max_hang, min_ovlp, &match_v, &total_v) < 0) - { - break; - } - - ///no read support k to i+1 - if(total_v == 0) break; - - match_rate = (total_v == 0)? 0:((double)(match_v)/(double)(total_v)); - if(match_rate > match_rate_max || (match_rate == match_rate_max && match_v > match_max)) - { - max_i = k; match_max = match_v; match_rate_max = match_rate; - } - } - - ///set [max_i+1, i] to be unavailable - for (k = max_i+1; k <= (int)i; k++) - { - if(collection->a[k] == (uint64_t)-1) continue; - collection->a[k] = (uint64_t)-1; - skip++; - } - } - - if(skip == 0) return 1; - - reduce_ma_utg_t(collection, read_g, sources, coverage_cut, edge, max_hang, min_ovlp, newE); - - return 1; -} - - -uint32_t polish_unitig_advance_scaf(ma_utg_t* in, asg_t* rg, All_reads *RNF, ma_hit_t_alloc* src, ma_sub_t *cov, kvec_asg_arc_t_warp* edge, -UC_Read* r_read, UC_Read* q_read, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* newE) -{ - if(in->m == 0) return 0; - if(in->n < 3) return 0; - // uint32_t i, skip = 0; - int match_v, total_v, max_i, match_max, k, z, l, in_n = in->n, i, skip = 0; - double match_rate, match_rate_max; - - - for (z = 1, l = 0; z <= in_n; z++) { - if(z == in_n || IS_SCAF_READ(R_INF, (in->a[z])>>33) ) { - if(z - l >= 3) { - ///we should be able to handle i = z-1 - for (i = l + 1; i < z - 1; i++) { - ///in practice, in->a[i] and in->a[i+1] must be available - ///in->a[index] might be unavailable only if index < i - if(get_consensus_rate(in, i, i+1, rg, RNF, src, cov, edge, r_read, q_read, max_hang, min_ovlp, &match_v, &total_v) != 1) { - continue; - } - - match_rate = (total_v == 0)? 0:((double)(match_v)/(double)(total_v)); - ///most reads support in[i], so it is right - if(match_v >= total_v * 0.5 && total_v > 0 && match_v > 0) continue; - - max_i = i; match_max = match_v; match_rate_max = match_rate; - for (k = i - 1; k >= 0; k--) { - if(in->a[k] == (uint64_t)-1) continue; - ///in->a[k] might be unavailable, while in->a[i+1] must be available - ///return -1 means there is no overlap from k to i+1 - if(get_consensus_rate(in, k, i+1, rg, RNF, src, cov, edge, r_read, q_read, max_hang, min_ovlp, &match_v, &total_v) < 0) { - break; - } - - ///no read support k to i+1 - if(total_v == 0) break; - - match_rate = (total_v == 0)? 0:((double)(match_v)/(double)(total_v)); - if(match_rate > match_rate_max || (match_rate == match_rate_max && match_v > match_max)) { - max_i = k; match_max = match_v; match_rate_max = match_rate; - } - } - - ///set [max_i+1, i] to be unavailable - for (k = max_i+1; k <= (int)i; k++) { - if(in->a[k] == (uint64_t)-1) continue; - in->a[k] = (uint64_t)-1; - skip++; - } - } - } - l = z; - } - } - - if(skip == 0) return 1; - - reduce_ma_utg_t_scaf(in, rg, src, cov, edge, max_hang, min_ovlp, newE); - - return 1; -} - - -ma_ug_t *gen_polished_ug(const ug_opt_t *uopt, asg_t *sg) -{ - kvec_asg_arc_t_warp e, d; - uint32_t i; ma_utg_t *u; - kv_init(e.a); kv_init(d.a); - ma_ug_t *ug = ma_ug_gen(sg); - UC_Read g_read, tmp; - init_UC_Read(&g_read); init_UC_Read(&tmp); - - for (i = e.a.n = d.a.n = 0; i < ug->u.n; ++i) { - u = &ug->u.a[i]; - if(u->m == 0) continue; - polish_unitig(u, sg, uopt->sources, uopt->coverage_cut, &e, uopt->max_hang, uopt->min_ovlp, &d); - polish_unitig_advance(u, sg, &R_INF, uopt->sources, uopt->coverage_cut, &e, &g_read, &tmp, uopt->max_hang, uopt->min_ovlp, &d); - ug->g->seq[i].len = u->len; - } - - destory_UC_Read(&g_read); destory_UC_Read(&tmp); - - uint32_t n_vtx = ug->g->n_seq*2, v, nv, vLen = 0; - asg_arc_t* av = NULL; - for (v = 0; v < n_vtx; ++v) { - if (ug->g->seq[v>>1].del) continue; - av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - vLen = ug->g->seq[(av[i].ul>>33)].len - av[i].ol; - av[i].ul = (av[i].ul>>32)<<32; - av[i].ul = av[i].ul | vLen; - } - } - - // if(d.a.n > 0) { - // for (k = 0; k < d.a.n; k++) { - // p = asg_arc_pushp(sg); - // *p = d.a.a[k]; - // } - // free(sg->idx); sg->idx = 0; sg->is_srt = 0; - // asg_cleanup(sg); - // } - - kv_destroy(e.a); kv_destroy(d.a); - return ug; -} - - -// generate unitig sequences -int ma_ug_seq(ma_ug_t *g, asg_t *read_g, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, -kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, kvec_asg_arc_t_warp *E, uint32_t is_polish) -{ - UC_Read g_read; - init_UC_Read(&g_read); - UC_Read tmp; - init_UC_Read(&tmp); - ///utg_intv_t *tmp; - uint32_t i, j, k; - uint32_t rId, /**uId,**/ori, start, eLen, readLen; - char* readS = NULL; - - ///why we need n_read here? it is just beacuse one read can only be included in one untig - ///but it is not true - ///tmp = (utg_intv_t*)calloc(n_read, sizeof(utg_intv_t)); - ///number of unitigs - for (i = 0; i < g->u.n; ++i) { - ma_utg_t *u = &g->u.a[i]; - if(u->m == 0) continue; - if(is_polish) { - polish_unitig_scaf(u, read_g, sources, coverage_cut, edge, max_hang, min_ovlp, E); - polish_unitig_advance_scaf(u, read_g, &R_INF, sources, coverage_cut, edge, &g_read, &tmp, max_hang, min_ovlp, E); - } - - g->g->seq[i].len = u->len; - - uint32_t l = 0; - u->s = (char*)calloc(1, u->len + 1); - memset(u->s, 'N', u->len); - for (j = 0; j < u->n; ++j) { - rId = u->a[j]>>33; - ///uId = i; - ori = u->a[j]>>32&1; - start = l; - eLen = (uint32_t)u->a[j]; - l += eLen; - - if(eLen == 0) continue; - if(rId < read_g->r_seq) { - recover_UC_Read(&g_read, &R_INF, rId); - } else { - recover_fake_read(&g_read, &tmp, &(read_g->F_seq[rId-read_g->r_seq]), - &R_INF, coverage_cut); - } - - readS = g_read.seq + coverage_cut[rId].s; - readLen = coverage_cut[rId].e - coverage_cut[rId].s; - - if (!ori) {// forward strand - for (k = 0; k < eLen; k++) { - u->s[start + k] = readS[k]; - } - } else { - for (k = 0; k < eLen; k++) { - uint8_t c = (uint8_t)readS[readLen - 1 - k]; - u->s[start + k] = c >= 128? 'N' : comp_tab[c]; - } - } - } - } - - destory_UC_Read(&g_read); - destory_UC_Read(&tmp); - - - uint32_t n_vtx = g->g->n_seq * 2, v, nv; - uint32_t vLen = 0; - asg_arc_t* av = NULL; - for (v = 0; v < n_vtx; ++v) - { - if (g->g->seq[v>>1].del) continue; - av = asg_arc_a(g->g, v); - nv = asg_arc_n(g->g, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - vLen = g->g->seq[(av[i].ul>>33)].len - av[i].ol; - av[i].ul = (av[i].ul>>32)<<32; - av[i].ul = av[i].ul | vLen; - } - } - - if(E && E->a.n > 0) - { - asg_arc_t* p = NULL; - for (k = 0; k < E->a.n; k++) - { - p = asg_arc_pushp(read_g); - *p = E->a.a[k]; - } - - free(read_g->idx); - read_g->idx = 0; - read_g->is_srt = 0; - asg_cleanup(read_g); - } - return 0; -} - - -void polish_unitig_scaffold(uint32_t uid, ma_utg_t* collection, asg_t* read_g, All_reads *RNF, -ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, kvec_asg_arc_t_warp* edge, -UC_Read* r_read, UC_Read* q_read, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* newE) -{ - uint32_t i, k, m, len, p_idx; - ma_utg_t qu; - for (i = p_idx = m = len = 0; i < collection->n; i++) - { - if(collection->a[i] == (uint64_t)-1) - { - qu.a = collection->a + p_idx; - qu.circ = 0; - qu.m = qu.n = i - p_idx; - for (k = qu.len = 0; k < qu.n; k++) - { - qu.len += (uint32_t)qu.a[k]; - } - - polish_unitig(&qu, read_g, sources, coverage_cut, edge, max_hang, min_ovlp, newE); - polish_unitig_advance(&qu, read_g, &R_INF, sources, coverage_cut, edge, r_read, q_read, max_hang, min_ovlp, newE); - - for (k = 0; k < qu.n; k++) - { - collection->a[m] = qu.a[k]; - m++; - } - len += qu.len; - - collection->a[m] = (uint64_t)-1; - m++; - len += GAP_LEN; - p_idx = i + 1; - } - } - - if(i - p_idx > 0) - { - qu.a = collection->a + p_idx; - qu.circ = collection->circ; - qu.m = qu.n = i - p_idx; - for (k = qu.len = 0; k < qu.n; k++) - { - qu.len += (uint32_t)qu.a[k]; - } - - polish_unitig(&qu, read_g, sources, coverage_cut, edge, max_hang, min_ovlp, newE); - polish_unitig_advance(&qu, read_g, &R_INF, sources, coverage_cut, edge, r_read, q_read, max_hang, min_ovlp, newE); - - for (k = 0; k < qu.n; k++) - { - collection->a[m] = qu.a[k]; - m++; - } - len += qu.len; - } - collection->n = m; - collection->len = len; -} - -int ma_ug_seq_scaffold(ma_ug_t *g, asg_t *read_g, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, -kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, kvec_asg_arc_t_warp *E, uint32_t is_polish) -{ - UC_Read g_read; - init_UC_Read(&g_read); - UC_Read tmp; - init_UC_Read(&tmp); - ///utg_intv_t *tmp; - uint32_t i, j, k; - uint32_t rId, /**uId,**/ori, start, eLen, readLen; - char* readS = NULL; - if(!(g->g)) - { - g->g = asg_init(); - for (i = 0; i < g->u.n; ++i) - { - asg_seq_set(g->g, i, g->u.a[i].len, 0); - } - asg_cleanup(g->g); - g->g->r_seq = g->g->n_seq; - } - - ///why we need n_read here? it is just beacuse one read can only be included in one untig - ///but it is not true - ///tmp = (utg_intv_t*)calloc(n_read, sizeof(utg_intv_t)); - ///number of unitigs - for (i = 0; i < g->u.n; ++i) { - ma_utg_t *u = &g->u.a[i]; - if(u->m == 0) continue; - if(is_polish) polish_unitig_scaffold(i, u, read_g, &R_INF, sources, coverage_cut, edge, &g_read, &tmp, max_hang, min_ovlp, E); - g->g->seq[i].len = u->len; - - uint32_t l = 0; - u->s = (char*)calloc(1, u->len + 1); - memset(u->s, 'N', u->len); - for (j = 0; j < u->n; ++j) { - // fprintf(stderr, "j=%u, u->a[j]: %lu\n", j, u->a[j]); - if(u->a[j] == (uint64_t)-1) - { - l += GAP_LEN; - continue; - } - rId = u->a[j]>>33; - ///uId = i; - ori = u->a[j]>>32&1; - start = l; - eLen = (uint32_t)u->a[j]; - l += eLen; - - if(eLen == 0) continue; - if(rId < read_g->r_seq) - { - recover_UC_Read(&g_read, &R_INF, rId); - } - else - { - recover_fake_read(&g_read, &tmp, &(read_g->F_seq[rId-read_g->r_seq]), - &R_INF, coverage_cut); - } - - readS = g_read.seq + coverage_cut[rId].s; - readLen = coverage_cut[rId].e - coverage_cut[rId].s; - - if (!ori) // forward strand - { - for (k = 0; k < eLen; k++) - { - u->s[start + k] = readS[k]; - } - } - else - { - for (k = 0; k < eLen; k++) - { - uint8_t c = (uint8_t)readS[readLen - 1 - k]; - u->s[start + k] = c >= 128? 'N' : comp_tab[c]; - } - } - } - } - - destory_UC_Read(&g_read); - destory_UC_Read(&tmp); - - - uint32_t n_vtx = g->g->n_seq * 2, v, nv; - uint32_t vLen = 0; - asg_arc_t* av = NULL; - for (v = 0; v < n_vtx; ++v) - { - if (g->g->seq[v>>1].del) continue; - av = asg_arc_a(g->g, v); - nv = asg_arc_n(g->g, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - vLen = g->g->seq[(av[i].ul>>33)].len - av[i].ol; - av[i].ul = (av[i].ul>>32)<<32; - av[i].ul = av[i].ul | vLen; - } - } - - if(E && E->a.n > 0) - { - asg_arc_t* p = NULL; - for (k = 0; k < E->a.n; k++) - { - p = asg_arc_pushp(read_g); - *p = E->a.a[k]; - } - - free(read_g->idx); - read_g->idx = 0; - read_g->is_srt = 0; - asg_cleanup(read_g); - } - return 0; -} -uint32_t get_ug_coverage(ma_utg_t* u, asg_t* read_g, const ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag, uint64_t *rR, uint64_t *rC) -{ - uint32_t k, j, rId, tn, is_Unitig; - long long R_bases = 0, C_bases = 0; - ma_hit_t *h; - if(rR) (*rR) = 0; if(rC) (*rC) = 0; - if(u->m == 0) return 0; - - for (k = 0; k < u->n; k++) - { - if(u->a[k] == (uint64_t)-1) continue; - rId = u->a[k]>>33; - r_flag[rId] = 1; - } - - for (k = 0; k < u->n; k++) - { - if(u->a[k] == (uint64_t)-1) continue; - rId = u->a[k]>>33; - R_bases += (coverage_cut[rId].e - coverage_cut[rId].s); - for (j = 0; j < (uint64_t)(sources[rId].length); j++) - { - h = &(sources[rId].buffer[j]); - if(h->el != 1) continue; - tn = Get_tn((*h)); - if(read_g->seq[tn].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - if(read_g->seq[tn].del == 1) continue; - if(r_flag[tn] != 1) continue; - C_bases += (Get_qe((*h)) - Get_qs((*h))); - } - } - - - for (k = 0; k < u->n; k++) - { - if(u->a[k] == (uint64_t)-1) continue; - rId = u->a[k]>>33; - r_flag[rId] = 0; - } - - if(rR) (*rR) = R_bases; if(rC) (*rC) = C_bases; - return R_bases == 0? 0:C_bases/R_bases; -} - -uint32_t get_ug_coverage_aggressive(ma_ug_t *ug, uint32_t uID, asg_t* read_g, -const ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag, -uint64_t *n_utg) -{ - ma_utg_t* u = &(ug->u.a[uID]); - uint32_t k, j, rId, tn, is_Unitig; - long long R_bases = 0, C_bases = 0; - ma_hit_t *h; - if(u->m == 0) return 0; - - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 1; - } - - (*n_utg) = u->n; - uint32_t nv, i; - asg_arc_t *av = NULL; - for (i = 0; i < 2; i++) - { - nv = asg_arc_n(ug->g, (uID<<1)+i); - av = asg_arc_a(ug->g, (uID<<1)+i); - for (j = 0; j < nv; j++) - { - u = &(ug->u.a[av[j].v>>1]); - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 2; - } - } - } - - - u = &(ug->u.a[uID]); - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - R_bases += (coverage_cut[rId].e - coverage_cut[rId].s); - for (j = 0; j < (uint64_t)(sources[rId].length); j++) - { - h = &(sources[rId].buffer[j]); - if(h->el != 1) continue; - tn = Get_tn((*h)); - if(read_g->seq[tn].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - if(read_g->seq[tn].del == 1) continue; - if(r_flag[tn] == 0) continue; - if(r_flag[tn] == 2) - { - (*n_utg)++; - r_flag[tn] = 3; - } - C_bases += (Get_qe((*h)) - Get_qs((*h))); - ///if(uID == 35701) fprintf(stderr, "flag: %u, coverage: %d\n", r_flag[tn], (int)(Get_qe((*h)) - Get_qs((*h)))); - } - } - - - - - - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 0; - } - - for (i = 0; i < 2; i++) - { - nv = asg_arc_n(ug->g, (uID<<1)+i); - av = asg_arc_a(ug->g, (uID<<1)+i); - for (j = 0; j < nv; j++) - { - u = &(ug->u.a[av[j].v>>1]); - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 0; - } - } - } - - ///if(uID == 35701) fprintf(stderr, "C_bases: %lld, R_bases: %lld, (*n_utg): %lu\n", C_bases, R_bases, (*n_utg)); - return C_bases/R_bases; -} - -uint32_t cal_circle_ov(const ma_ug_t *ug, uint32_t uid, uint32_t rev, asg_t *sg) -{ - uint32_t v, w, vx, wx, k; - v = w = (uid<<1)+(!!rev); - 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)); - v = vx; w = wx; - - if(sg) { - asg_arc_t *av; uint32_t nv; - av = asg_arc_a(sg, vx); nv = asg_arc_n(sg, vx); - for (k = 0; k < nv; k++) { - if(av[k].v == wx) return av[k].ol; - } - } - return 0; -} - -void ma_ug_print2(const ma_ug_t *ug, All_reads *RNF, asg_t* read_g, const ma_sub_t *coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex, int print_seq, const char* prefix, FILE *fp) -{ - uint8_t* primary_flag = read_g?(uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)):NULL; - uint32_t i, j, l, pc = read_g && coverage_cut && sources && ruIndex?1:0, co; - char name[32]; - for (i = 0; i < ug->u.n; ++i) { // the Segment lines in GFA - ma_utg_t *p = &ug->u.a[i]; - if(p->m == 0) continue; - sprintf(name, "%s%.6d%c", prefix, i + 1, "lc"[p->circ]); - if (print_seq) fprintf(fp, "S\t%s\t%s\tLN:i:%d\trd:i:%u\n", name, p->s? p->s : "*", p->len, - pc?get_ug_coverage(p, read_g, coverage_cut, sources, ruIndex, primary_flag, NULL, NULL):0); - else fprintf(fp, "S\t%s\t*\tLN:i:%d\trd:i:%u\n", name, p->len, - pc?get_ug_coverage(p, read_g, coverage_cut, sources, ruIndex, primary_flag, NULL, NULL):0); - - for (j = l = 0; j < p->n; j++) { - if(p->a[j] != (uint64_t)-1) - { - uint32_t x = p->a[j]>>33; - if(xtotal_reads) - { - - fprintf(fp, "A\t%s\t%d\t%c\t%.*s\t%d\t%d\tid:i:%d\tHG:A:%c\n", name, l, "+-"[p->a[j]>>32&1], - (int)Get_NAME_LENGTH((*RNF), x), Get_NAME((*RNF), x), - coverage_cut?coverage_cut[x].s:0, coverage_cut?coverage_cut[x].e:(int)Get_READ_LENGTH((*RNF), x), x, - "apmaaa"[((RNF->trio_flag[x]!=FATHER && RNF->trio_flag[x]!=MOTHER)?AMBIGU:RNF->trio_flag[x])]); - } - else - { - fprintf(fp, "A\t%s\t%d\t%c\t%s\t%d\t%d\tid:i:%d\tHG:A:%c\n", name, l, "+-"[p->a[j]>>32&1], - "FAKE", coverage_cut?coverage_cut[x].s:0, coverage_cut?coverage_cut[x].e:(int)Get_READ_LENGTH((*RNF), x), x, '*'); - } - } - else - { - fprintf(fp, "A\t%s\t%d\t*\t*\t*\t*\tid:i:*\tHG:A:*\n", name, l); - } - l += (uint32_t)p->a[j]; - } - } - // for (i = 0; i < ug->g->n_arc; ++i) { // the Link lines in GFA - // uint32_t u = ug->g->arc[i].ul>>32, v = ug->g->arc[i].v; - // fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", - // prefix, (u>>1)+1, "lc"[ug->u.a[u>>1].circ], "+-"[u&1], - // prefix, (v>>1)+1, "lc"[ug->u.a[v>>1].circ], "+-"[v&1], ug->g->arc[i].ol, asg_arc_len(ug->g->arc[i])); - // } - if(ug->g) - { - asg_arc_t* au = NULL; - uint32_t nu, u, v; - for (i = 0; i < ug->u.n; ++i) { - if(ug->u.a[i].m == 0) continue; - if(ug->u.a[i].circ) { - co = cal_circle_ov(ug, i, 0, read_g); - fprintf(fp, "L\t%s%.6dc\t+\t%s%.6dc\t+\t%dM\tL1:i:%d\tL2:i:%u\n", - prefix, i+1, prefix, i+1, co, ((ug->u.a[i].len>=co)?(ug->u.a[i].len-co):0), 0); - co = cal_circle_ov(ug, i, 1, read_g); - fprintf(fp, "L\t%s%.6dc\t-\t%s%.6dc\t-\t%dM\tL1:i:%d\tL2:i:%u\n", - prefix, i+1, prefix, i+1, co, ((ug->u.a[i].len>=co)?(ug->u.a[i].len-co):0), 0); - } else { - u = i<<1; - au = asg_arc_a(ug->g, u); - nu = asg_arc_n(ug->g, u); - for (j = 0; j < nu; j++) - { - if(au[j].del) continue; - v = au[j].v; - fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", - prefix, (u>>1)+1, "lc"[ug->u.a[u>>1].circ], "+-"[u&1], - prefix, (v>>1)+1, "lc"[ug->u.a[v>>1].circ], "+-"[v&1], au[j].ol, asg_arc_len(au[j]), 0/**au[j].ou**/); - } - - - u = (i<<1) + 1; - au = asg_arc_a(ug->g, u); - nu = asg_arc_n(ug->g, u); - for (j = 0; j < nu; j++) - { - if(au[j].del) continue; - v = au[j].v; - fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", - prefix, (u>>1)+1, "lc"[ug->u.a[u>>1].circ], "+-"[u&1], - prefix, (v>>1)+1, "lc"[ug->u.a[v>>1].circ], "+-"[v&1], au[j].ol, asg_arc_len(au[j]), 0/**au[j].ou**/); - } - } - } - } - free(primary_flag); -} - -void ma_ug_print(const ma_ug_t *ug, asg_t* read_g, const ma_sub_t *coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex, const char* prefix, FILE *fp) -{ - ma_ug_print2(ug, &R_INF, read_g, coverage_cut, sources, ruIndex, 1, prefix, fp); -} - -void prt_scaf_stats(sec_t *scp, ma_ug_t *ctg, const char* prefix, uint64_t id) -{ - uint64_t k, tl0, tl1; ma_utg_t *z = NULL; char name[32]; - for (k = tl0 = tl1 = 0; k < scp->n; k++) { - z = &(ctg->u.a[((uint32_t)scp->a[k])>>1]); tl0 += z->len; tl1 += (scp->a[k]>>32); - } - sprintf(name, "%s%.6lu%c", prefix, id + 1, "lc"[scp->is_c]); - - fprintf(stderr, "[M::%s] [M::%s] tot::%lu\tel::%lu\tnl::%lu\tis_c::%lu\t#::%lu\t%s\n", __func__, name, tl0+tl1, tl0, tl1, scp->is_c, (uint64_t)scp->n, ((scp->n>1)?"scf":"ctg")); - for (k = 0; k < scp->n; k++) { - z = &(ctg->u.a[((uint32_t)scp->a[k])>>1]); - fprintf(stderr, "%s%.6u%c(%c)\tlen::%u\tNs::%lu\n", - prefix, (((uint32_t)scp->a[k])>>1)+1, "lc"[z->circ], "+-"[(((uint32_t)scp->a[k])&1)], z->len, (scp->a[k]>>32)); - } - -} - -void ma_scg_print(const kvect_sec_t *sc, All_reads *RNF, asg_t* read_g, const ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, int print_seq, const char* prefix, FILE *fp) -{ - uint8_t* primary_flag = read_g?(uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)):NULL; - uint64_t i, j, l, pc = read_g && coverage_cut && sources && ruIndex?1:0, tl, m, x; sec_t *scp; - char name[32]; uint64_t Rb, Cb, tRb, tCb, Cov; ma_utg_t *z = NULL; uint8_t c; - for (i = 0; i < sc->n; ++i) { // the Segment lines in GFA - scp = &(sc->a[i]); - ///debug - // prt_scaf_stats(scp, sc->ctg, prefix, i); - - for (j = tl = tRb = tCb = 0; j < scp->n; j++) { - z = &(sc->ctg->u.a[((uint32_t)scp->a[j])>>1]); tl += z->len; tl += (scp->a[j]>>32); - if(pc) { - get_ug_coverage(z, read_g, coverage_cut, sources, ruIndex, primary_flag, &Rb, &Cb); tRb += Rb; tCb += Cb; - } - } - sprintf(name, "%s%.6lu%c", prefix, i + 1, "lc"[scp->is_c]); Cov = ((tRb==0)?(0):(tCb/tRb)); - - if (!print_seq) { - fprintf(fp, "S\t%s\t*\tLN:i:%lu\trd:i:%lu\n", name, tl, Cov); - } else { - fprintf(fp, "S\t%s\t", name); - for (j = 0; j < scp->n; j++) { - z = &(sc->ctg->u.a[((uint32_t)scp->a[j])>>1]); - if(!(((uint32_t)scp->a[j])&1)) { - fprintf(fp, "%s", z->s); - } else { - for(l = 0; l < z->len; l++) { - c = (uint8_t)(z->s[z->len-1-l]); - fprintf(fp, "%c", ((c>=128)?'N':comp_tab[c])); - } - } - for(l = 0; l < (scp->a[j]>>32); l++) fprintf(fp, "N"); - } - fprintf(fp, "\tLN:i:%lu\trd:i:%lu\n", tl, Cov); - } - - - for (j = tl = 0; j < scp->n; j++) { - z = &(sc->ctg->u.a[((uint32_t)scp->a[j])>>1]); l = tl; - if(!(((uint32_t)scp->a[j])&1)) { - for (m = 0; m < z->n; m++) { - x = z->a[m]>>33; - if(xtotal_reads) { - fprintf(fp, "A\t%s\t%lu\t%c\t%.*s\t%d\t%d\tid:i:%lu\tHG:A:%c\n", name, l, "+-"[(z->a[m]>>32)&1], - (int)Get_NAME_LENGTH((*RNF), x), Get_NAME((*RNF), x), - coverage_cut?coverage_cut[x].s:0, coverage_cut?coverage_cut[x].e:(int)Get_READ_LENGTH((*RNF), x), x, - "apmaaa"[((RNF->trio_flag[x]!=FATHER && RNF->trio_flag[x]!=MOTHER)?AMBIGU:RNF->trio_flag[x])]); - } else { - fprintf(fp, "A\t%s\t%lu\t%c\t%s\t%d\t%d\tid:i:%lu\tHG:A:%c\n", name, l, "+-"[(z->a[m]>>32)&1], - "FAKE", coverage_cut?coverage_cut[x].s:0, coverage_cut?coverage_cut[x].e:(int)Get_READ_LENGTH((*RNF), x), x, '*'); - } - l += (uint32_t)(z->a[m]); - } - } else { - for (m = 0; m < z->n; m++) { - x = z->a[z->n-m-1]>>33; - if(xtotal_reads) { - fprintf(fp, "A\t%s\t%lu\t%c\t%.*s\t%d\t%d\tid:i:%lu\tHG:A:%c\n", name, l, "+-"[((z->a[z->n-m-1]>>32)&1)^1], - (int)Get_NAME_LENGTH((*RNF), x), Get_NAME((*RNF), x), - coverage_cut?coverage_cut[x].s:0, coverage_cut?coverage_cut[x].e:(int)Get_READ_LENGTH((*RNF), x), x, - "apmaaa"[((RNF->trio_flag[x]!=FATHER && RNF->trio_flag[x]!=MOTHER)?AMBIGU:RNF->trio_flag[x])]); - } else { - fprintf(fp, "A\t%s\t%lu\t%c\t%s\t%d\t%d\tid:i:%lu\tHG:A:%c\n", name, l, "+-"[((z->a[z->n-m-1]>>32)&1)^1], - "FAKE", coverage_cut?coverage_cut[x].s:0, coverage_cut?coverage_cut[x].e:(int)Get_READ_LENGTH((*RNF), x), x, '*'); - } - l += (uint32_t)(z->a[z->n-m-1]); - } - } - tl = l; - - if((scp->a[j]>>32) > 0) fprintf(fp, "A\t%s\t%lu\t+\tNs\t0\t%lu\tid:i:-1\tHG:A:a\n", name, l, (scp->a[j]>>32)); - - tl += (scp->a[j]>>32); - } - } - free(primary_flag); -} - -int asg_cut_internal(asg_t *g, int max_ext) -{ - asg64_v a = {0,0,0}; - uint32_t n_vtx = g->n_seq * 2, v, i, cnt = 0; - for (v = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - if (asg_is_utg_end(g, v, 0) != ASG_ET_MULTI_NEI) continue; - if (asg_extend(g, v, max_ext, &a) != ASG_ET_MULTI_NEI) continue; - /** - * so combining the last two lines, they are designed to reomve(n(1), n(2))? - -----> <------- - | | - n(0)--->n(1)---->n(2)---->n(3) - | | - ------> <------- - **/ - for (i = 0; i < a.n; ++i) - asg_seq_del(g, (uint32_t)a.a[i]>>1); - ++cnt; - } - free(a.a); - if (cnt > 0) asg_cleanup(g); - fprintf(stderr, "[M::%s] cut %d internal sequences\n", __func__, cnt); - return cnt; -} - -uint32_t reset_weak_ovlp(ma_hit_t_alloc *sc, uint32_t src, uint32_t dst) -{ - ma_hit_t_alloc *x = &(sc[src]); uint32_t k, tn; int32_t idx; - for (k = 0; k < x->length; k++) { - if((x->buffer[k].bl&((uint32_t)0x40000000))) continue; - if((x->buffer[k].del)) continue; - tn = Get_tn(x->buffer[k]); - if((Get_ts(x->buffer[k]) == 0) && (Get_te(x->buffer[k]) == Get_READ_LENGTH(R_INF, tn))) { - idx = get_specific_overlap(&(sc[tn]), tn, dst); - if((idx >= 0) && (!(sc[tn].buffer[idx].del)) && (!(sc[tn].buffer[idx].bl&((uint32_t)0x40000000)))) { - return 1; - } - } - } - return 0; -} - -static void update_weak_by_contain(void *data, long i, int tid) -{ - sset_aux *sl = (sset_aux *)data; - ma_hit_t_alloc *x = &(sl->src[i]); - uint32_t k, qn, tn; int32_t idx; - if(sl->ul_occ == 0) { - for (k = 0; k < x->length; k++) { - if(x->buffer[k].bl&((uint32_t)0x40000000)) x->buffer[k].del = 1; - } - } else if(sl->ul_occ == 1) { - for (k = 0; k < x->length; k++) { - qn = Get_qn(x->buffer[k]); - tn = Get_tn(x->buffer[k]); - if(qn > tn) continue; - if((x->buffer[k].del) && (x->buffer[k].bl&((uint32_t)0x40000000))) { - if(reset_weak_ovlp(sl->src, qn, tn)) { - idx = get_specific_overlap(&(sl->src[tn]), tn, qn); - sl->src[tn].buffer[idx].del = x->buffer[k].del = 0; - } - } - } - } else { - for (k = 0; k < x->length; k++) { - if(x->buffer[k].bl&((uint32_t)0x40000000)) { - x->buffer[k].bl -= ((uint32_t)0x40000000); - } - } - } -} - -void clean_weak_ma_hit_t(ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long num_sources, uint32_t ou_thres) -{ - double startTime = Get_T(); - long long i, j, index; - uint32_t qn, tn, ou; - - for (i = 0; i < num_sources; i++) { - for (j = 0; j < sources[i].length; j++) { - qn = Get_qn(sources[i].buffer[j]); - tn = Get_tn(sources[i].buffer[j]); - - if(sources[i].buffer[j].del) continue; - ou = (sources[i].buffer[j].bl&((uint32_t)0x3fffffff)); - //if this is a weak overlap; ml == 0 -> weak overlap - if((sources[i].buffer[j].ml == 0) && ((ou_thres==((uint32_t)-1)) || (ou < ou_thres))) - { - if( - !check_weak_ma_hit(&(sources[qn]), reverse_sources, tn, - Get_qs(sources[i].buffer[j]), Get_qe(sources[i].buffer[j])) - /** - || - !check_weak_ma_hit_reverse(&(reverse_sources[qn]), sources, tn)**/) - { - sources[i].buffer[j].bl |= ((uint32_t)0x40000000); - index = get_specific_overlap(&(sources[tn]), tn, qn); - // if(index < 0 || index >= sources[tn].length) fprintf(stderr, "sb, tn: %u, qn: %u, index: %ld, length: %u\n", tn, qn, index, sources[tn].length); - sources[tn].buffer[index].bl |= ((uint32_t)0x40000000); - // ma_hit_t *h = &(sources[i].buffer[j]); - // if((Get_qn(*h) == 27087 && Get_tn(*h) == 27128) || (Get_tn(*h) == 27087 && Get_qn(*h) == 27128)) { - // fprintf(stderr, "[M::%s]\t%.*s(qn::%u)\t%u\t%u\t%u\t%c\t%.*s(tn::%u)\t%u\t%u\t%u\t%u\t%u\t255\n", __func__, (int)Get_NAME_LENGTH(R_INF, Get_qn(*h)), Get_NAME((R_INF), Get_qn(*h)), Get_qn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_qn(*h)), Get_qs(*h), Get_qe(*h), "+-"[h->rev], - // (int)Get_NAME_LENGTH(R_INF, Get_tn(*h)), Get_NAME((R_INF), Get_tn(*h)), Get_tn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_tn(*h)), Get_ts(*h), Get_te(*h), h->ml, h->bl); - // } - } - } - } - } - - sset_aux s; s.src = sources; s.ul_occ = 0; - kt_for(asm_opt.thread_num, update_weak_by_contain, &s, num_sources); - - if(ou_thres != ((uint32_t)-1)) { - s.ul_occ = 1; - kt_for(asm_opt.thread_num, update_weak_by_contain, &s, num_sources); - } - - s.ul_occ = 2; - kt_for(asm_opt.thread_num, update_weak_by_contain, &s, num_sources); - - // for (i = 0; i < num_sources; i++) - // { - - // for (j = 0; j < sources[i].length; j++) - // { - // if(sources[i].buffer[j].del) continue; - - // if(sources[i].buffer[j].bl&((uint32_t)0x40000000)) - // { - // sources[i].buffer[j].del = 1; - // sources[i].buffer[j].bl -= ((uint32_t)0x40000000); - // } - // else - // { - // sources[i].buffer[j].del = 0; - // } - // } - // } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } -} - - - - - - - -void debug_info_of_specfic_read(const char* name, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, int id, const char* command) -{ - long long i, j, Len; - uint32_t tn; - - if(id == -1) - { - i = 0; - Len = R_INF.total_reads; - } - else - { - i = id; - Len = id + 1; - } - - - for (; i < Len; i++) - { - if(memcmp(name, Get_NAME(R_INF, i), Get_NAME_LENGTH(R_INF, i)) == 0) - { - fprintf(stderr, "\n\n\nafter %s\n", command); - - fprintf(stderr, "****************ma_hit_t (%lld)ref_read: %.*s, len: %lu****************\n", - i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i), (unsigned long)Get_READ_LENGTH(R_INF, i)); - - - fprintf(stderr, "sources Len: %d, is_fully_corrected: %d\n", - sources[i].length, sources[i].is_fully_corrected); - - for (j = 0; j < sources[i].length; j++) - { - tn = Get_tn(sources[i].buffer[j]); - fprintf(stderr, "target: %.*s, qs: %u, qe: %u, ts: %u, te: %u, ml: %u, rev: %u, el: %u, del: %u\n", - (int)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), - Get_qs(sources[i].buffer[j]), - Get_qe(sources[i].buffer[j]), - Get_ts(sources[i].buffer[j]), - Get_te(sources[i].buffer[j]), - sources[i].buffer[j].ml, - sources[i].buffer[j].rev, - sources[i].buffer[j].el, - (uint32_t)sources[i].buffer[j].del); - } - - - - fprintf(stderr, "######reverse_query_read Len: %d\n", reverse_sources[i].length); - - - - for (j = 0; j < reverse_sources[i].length; j++) - { - tn = Get_tn(reverse_sources[i].buffer[j]); - fprintf(stderr, "target: %.*s, qs: %u, qe: %u, ts: %u, te: %u, rev: %u, del: %u\n", - (int)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), - Get_qs(reverse_sources[i].buffer[j]), - Get_qe(reverse_sources[i].buffer[j]), - Get_ts(reverse_sources[i].buffer[j]), - Get_te(reverse_sources[i].buffer[j]), - reverse_sources[i].buffer[j].rev, - (uint32_t)sources[i].buffer[j].del); - } - - break; - - } - } - - fflush(stderr); - - -} - -void ma_sg_print(const asg_t *g, const All_reads *RNF, const ma_sub_t *sub, FILE *fp) -{ - uint32_t i; - for (i = 0; i < g->n_seq; ++i) - { - if(!g->seq[i].del) - { - fprintf(fp, - "S\t%.*s\t*\tLN:i:%u\n", - (int)Get_NAME_LENGTH((*RNF), i), - Get_NAME((*RNF), i), - g->seq[i].len); - } - } - - for (i = 0; i < g->n_arc; ++i) { - const asg_arc_t *p = &g->arc[i]; - if (sub) { - const ma_sub_t *sq = &sub[p->ul>>33], *st = &sub[p->v>>1]; - - fprintf(fp, - "L\t%.*s:%d-%d\t%c\t%.*s:%d-%d\t%c\t%d:\tL1:i:%u\n", - (int)Get_NAME_LENGTH((*RNF), p->ul>>33), - Get_NAME((*RNF), p->ul>>33), - sq->s + 1, sq->e, "+-"[p->ul>>32&1], - (int)Get_NAME_LENGTH((*RNF), p->v>>1), - Get_NAME((*RNF), p->v>>1), - st->s + 1, st->e, "+-"[p->v&1], p->ol, (uint32_t)p->ul); - - - } - else - { - fprintf(fp, "L\t%.*s\t%c\t%.*s\t%c\t%d:\tL1:i:%u\n", - (int)Get_NAME_LENGTH((*RNF), p->ul>>33), - Get_NAME((*RNF), p->ul>>33), - "+-"[p->ul>>32&1], - (int)Get_NAME_LENGTH((*RNF), p->v>>1), - Get_NAME((*RNF), p->v>>1), - "+-"[p->v&1], p->ol, (uint32_t)p->ul); - } - } -} - - -void ma_ug_print_simple(const ma_ug_t *ug, asg_t* read_g, const ma_sub_t *coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex, const char* prefix, FILE *fp) -{ - ma_ug_print2(ug, &R_INF, read_g, coverage_cut, sources, ruIndex, 0, prefix, fp); -} - -void ma_ug_print_bed(const ma_ug_t *g, asg_t *read_g, All_reads *RNF, ma_sub_t *coverage_cut, -ma_hit_t_alloc* sources, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, uint32_t rate_thres, -const char* prefix, FILE *fp, trans_chain* t_ch) -{ - UC_Read g_read; - init_UC_Read(&g_read); - UC_Read tmp; - init_UC_Read(&tmp); - kvec_t_u32_warp exact_count, total_count; - kv_init(exact_count.a); - kv_init(total_count.a); - uint32_t i, j, l, eLen, start; - for (i = 0; i < g->u.n; ++i) { - ma_utg_t *u = &g->u.a[i]; - if(u->m == 0) continue; - if(u->n < 2) continue; - l = 0; - for (j = 0; j < u->n; ++j) - { - start = l; - eLen = (uint32_t)u->a[j]; - l += eLen; - - print_rough_inconsistent_sites(u, j, j+1, read_g, RNF, sources, coverage_cut, - edge, &g_read, &tmp, max_hang, min_ovlp, start, rate_thres, &exact_count, - &total_count, prefix, i+1, fp, t_ch? &(t_ch->bed.a[i]): NULL); - } - } - - destory_UC_Read(&g_read); - destory_UC_Read(&tmp); - kv_destroy(exact_count.a); - kv_destroy(total_count.a); -} - -uint32_t get_break_point_cov(ma_utg_t* collection, uint32_t cur_i, uint32_t next_i, -asg_t* read_g, All_reads *RNF, ma_hit_t_alloc* sources, R_to_U* ruIndex, ma_sub_t *coverage_cut, -int max_hang, int min_ovlp, kvec_asg_arc_t_warp* edge, uint8_t* r_flag) -{ - uint32_t v, w, i, tn, is_Unitig; - int v_beg, v_end, v_sub_beg, v_sub_end; - asg_arc_t t; - - v = (uint64_t)(collection->a[cur_i])>>32; - ///last element - if(cur_i == collection->n-1 && next_i == collection->n) - { - if(!collection->circ) - { - next_i = (uint32_t)-1; - } - else - { - next_i = 0; - } - } - - if(next_i != ((uint32_t)-1)) - { - w = (uint64_t)(collection->a[next_i])>>32; - - get_specific_edge(sources, coverage_cut, NULL, edge, read_g, max_hang, min_ovlp, v, w, &t); - v_beg = 0; v_end = asg_arc_len(t) - 1; - if(v&1) - { - v_beg = Get_READ_LENGTH((*RNF), (v>>1)) - v_beg - 1; - v_end = Get_READ_LENGTH((*RNF), (v>>1)) - v_end - 1; - w = v_beg; v_beg = v_end; v_end = w; - } - } - else - { - v_beg = 0; v_end = Get_READ_LENGTH((*RNF), (v>>1)) - 1; - } - - ma_hit_t_alloc* x = &(sources[v>>1]); - ma_hit_t *h = NULL; - long long R_bases = v_end + 1 - v_beg, C_bases = 0; - ///[v_beg, v_end] must be the end of read, which means v_beg = 0 or v_end = Get_READ_LENGTH((*RNF), (v>>1)) - 1 - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - tn = Get_tn((*h)); - if(read_g->seq[tn].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - if(read_g->seq[tn].del == 1) continue; - if(r_flag[tn] != 1) continue; - - - if(inter_interval(v_beg, v_end, Get_qs((*h)), Get_qe((*h)) - 1, - &v_sub_beg, &v_sub_end) == 0) - { - continue; - } - - C_bases += (v_sub_end + 1 - v_sub_beg); - } - if(R_bases <= 0 || C_bases <= 0) return 0; - - return C_bases/R_bases; -} - - - -uint32_t push_cov_interval_direct(kvec_t_u64_warp* a, long long x_beg, long long x_end, long long utg_len, uint64_t is_circle) -{ - if(x_beg <= x_end && x_beg >= 0 && x_end >= 0 && x_beg < utg_len && x_end < utg_len) - { - uint64_t key; - key = x_beg; key <<= 1; key |= (!is_circle); key <<= 1; key|=1; - kv_push(uint64_t, a->a, key); - key = x_end + 1; key <<= 1; key |= (!is_circle); key <<= 1; - kv_push(uint64_t, a->a, key); - return 1; - } - return 0; -} - -uint32_t push_cov_interval_advance(kvec_t_u64_warp* a, long long x_beg, long long x_end, long long utg_len, uint32_t is_circle) -{ - if(x_beg > x_end) return 0; - - if(push_cov_interval_direct(a, x_beg, x_end, utg_len, 0)) return 1; - - - if(x_beg < 0 && x_end < 0) - { - x_beg = utg_len + x_beg; - x_end = utg_len + x_end; - return push_cov_interval_direct(a, x_beg, x_end, utg_len, 0); - } - - if(x_beg >= utg_len && x_end >= utg_len) - { - x_beg = x_beg - utg_len; - x_end = x_end - utg_len; - return push_cov_interval_direct(a, x_beg, x_end, utg_len, 0); - } - - if(x_beg < 0 && x_end >= 0) - { - x_beg = utg_len + x_beg; - if(push_cov_interval_direct(a, x_beg, utg_len - 1, utg_len, is_circle) || - push_cov_interval_direct(a, 0, x_end, utg_len, is_circle)) - { - return 1; - } - } - - return 0; -} - -void get_break_point_cov_advance(uint32_t v, long long c_beg, asg_t* read_g, All_reads *RNF, -ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag, kvec_t_u64_warp* depth, long long utg_len, -uint32_t is_circle, uint32_t* uID) -{ - uint32_t i, tn, is_Unitig; - long long v_beg, v_end, w_beg, w_end; - - v_beg = 0; v_end = Get_READ_LENGTH((*RNF), (v>>1)) - 1; - if(uID && (r_flag[v>>1]&1) && (!(r_flag[v>>1]&2))) - { - if(push_cov_interval_advance(depth, v_beg+c_beg, v_end+c_beg, utg_len, is_circle)) r_flag[v>>1] |= 2; - return; - } - - - ma_hit_t_alloc* x = &(sources[v>>1]); - ma_hit_t *h = NULL; - long long qs, qe, ts, te; - ///[v_beg, v_end] must be the end of read, which means v_beg = 0 or v_end = Get_READ_LENGTH((*RNF), (v>>1)) - 1 - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - tn = Get_tn((*h)); - if(read_g->seq[tn].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - if(read_g->seq[tn].del == 1) continue; - if(!(r_flag[tn]&1)) continue; - tn = Get_tn((*h));///must!!!! - - if(r_flag[tn]&2) continue; - - qs = Get_qs((*h)); qe = Get_qe((*h)) - 1; - ts = Get_ts((*h)); te = Get_te((*h)) - 1; - if(h->rev) - { - ts = (long long)(Get_READ_LENGTH((*RNF), tn)) - ((long long)(Get_te((*h))) - 1) - 1; - te = (long long)(Get_READ_LENGTH((*RNF), tn)) - (long long)(Get_ts((*h))) - 1; - } - ts = qs - ts; - te = qe + ((long long)(Get_READ_LENGTH((*RNF), tn)) - te - 1); - w_beg = ts; w_end = te; - - if(v&1) - { - ts = (long long)(Get_READ_LENGTH((*RNF), v>>1)) - ts - 1; - te = (long long)(Get_READ_LENGTH((*RNF), v>>1)) - te - 1; - w_beg = te; w_end = ts; - } - - if(push_cov_interval_advance(depth, w_beg+c_beg, w_end+c_beg, utg_len, is_circle)) r_flag[tn] |= 2; - } -} -typedef struct { - uint32_t dp; - uint64_t k_beg, k_end; -} in_sub_t; - -typedef struct { - size_t n, m; - in_sub_t* a; -}kv_in_sub_t; - - -void debug_r_contig_pos(ma_utg_t *u, uint32_t tn, All_reads *RNF) -{ - uint32_t c_beg, c_end, l, k; - for (k = l = 0; k < u->n; k++) - { - c_beg = l; - c_end = c_beg + Get_READ_LENGTH((*RNF), (u->a[k]>>33)); - l += (uint32_t)u->a[k]; - if((u->a[k]>>33) == tn) - { - fprintf(stderr, "#####c_beg: %u, c_end: %u\n", c_beg, c_end); - break; - } - } -} - -uint32_t get_overlap_contig_dir(uint32_t v, uint32_t tn, ma_hit_t *h, All_reads *RNF, long long ctg_beg, -uint32_t p_beg, uint32_t p_end) -{ - long long qs, qe, ts, te, c_beg, c_end; - - qs = Get_qs((*h)); qe = Get_qe((*h)) - 1; - ts = Get_ts((*h)); te = Get_te((*h)) - 1; - if(h->rev) - { - ts = (long long)(Get_READ_LENGTH((*RNF), tn)) - ((long long)(Get_te((*h))) - 1) - 1; - te = (long long)(Get_READ_LENGTH((*RNF), tn)) - (long long)(Get_ts((*h))) - 1; - } - ts = qs - ts; - te = qe + ((long long)(Get_READ_LENGTH((*RNF), tn)) - te - 1); - c_beg = ts; c_end = te; - - if(v&1) - { - ts = (long long)(Get_READ_LENGTH((*RNF), v>>1)) - ts - 1; - te = (long long)(Get_READ_LENGTH((*RNF), v>>1)) - te - 1; - c_beg = te; c_end = ts; - } - - c_end++; - c_beg += ctg_beg; c_end += ctg_beg; - - if((p_beg != p_end && c_beg <= p_beg && c_end >= p_end) || - (p_beg == p_end && c_beg < p_beg && c_end > p_end)) - { - return 2; - } - - if(c_beg < p_beg) return 0; - if(c_end > p_end) return 1; - - return 2; - -} -///[beg, end) -uint32_t get_break_point_idx(ma_utg_t *u, All_reads *RNF, uint8_t* r_flag, ma_hit_t_alloc* sources, -asg_t* read_g, R_to_U* ruIndex, uint32_t p_beg, uint32_t p_end, double m_rate) -{ - uint32_t k, i, tn, is_Unitig, min_k = (uint32_t)-1, min_l = (uint32_t)-1, l, c_beg, c_end, index; - uint32_t e_occ = 0, ne_occ = 0; - double e_occ_dir[3], ne_occ_dir[3], rate[2]; - ma_hit_t_alloc* x = NULL; - ma_hit_t *h = NULL; - - e_occ = ne_occ = 0; - for (k = l = 0; k < u->n; k++) - { - c_beg = l; - c_end = c_beg + Get_READ_LENGTH((*RNF), (u->a[k]>>33)); - l += (uint32_t)u->a[k]; - - if((p_beg != p_end && c_beg <= p_beg && c_end >= p_end) || - (p_beg == p_end && c_beg < p_beg && c_end > p_end)) - { - - if(min_k == (uint32_t)-1) min_k = k, min_l = c_beg; - - x = &(sources[u->a[k]>>33]); - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - tn = Get_tn((*h)); - if(read_g->seq[tn].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - if(read_g->seq[tn].del == 1) continue; - if(!(r_flag[tn]&1)) continue; - if(h->el) e_occ++; - else ne_occ++; - } - } - else if(min_k != (uint32_t)-1) - { - break; - } - } - - if(min_k == (uint32_t)-1) return (uint32_t)-1; - if(e_occ <= ((e_occ+ne_occ)*m_rate)) goto c_break; - - e_occ = ne_occ = 0; - for (k = min_k, l = min_l; k < u->n; k++) - { - c_beg = l; - c_end = c_beg + Get_READ_LENGTH((*RNF), (u->a[k]>>33)); - l += (uint32_t)u->a[k]; - - if((p_beg != p_end && c_beg <= p_beg && c_end >= p_end) || - (p_beg == p_end && c_beg < p_beg && c_end > p_end)) - { - e_occ_dir[0] = e_occ_dir[1] = e_occ_dir[2] = 0; - ne_occ_dir[0] = ne_occ_dir[1] = ne_occ_dir[2] = 0; - - x = &(sources[u->a[k]>>33]); - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - tn = Get_tn((*h)); - if(read_g->seq[tn].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - if(read_g->seq[tn].del == 1) continue; - if(!(r_flag[tn]&1)) continue; - - tn = Get_tn((*h));///must!!!! - - index = get_overlap_contig_dir(u->a[k]>>32, tn, h, RNF, c_beg, p_beg, p_end); - - ///debug_r_contig_pos(u, tn, RNF); - if(h->el) e_occ_dir[index]++; - else ne_occ_dir[index]++; - } - - e_occ_dir[0] += e_occ_dir[2]; e_occ_dir[1] += e_occ_dir[2]; - ne_occ_dir[0] += ne_occ_dir[2]; ne_occ_dir[1] += ne_occ_dir[2]; - rate[0] = ne_occ_dir[0] / (ne_occ_dir[0] + e_occ_dir[0]); - rate[1] = ne_occ_dir[1] / (ne_occ_dir[1] + e_occ_dir[1]); - if(rate[0] >= rate[1]) - { - e_occ += e_occ_dir[0]; - ne_occ += ne_occ_dir[0]; - } - else - { - e_occ += e_occ_dir[1]; - ne_occ += ne_occ_dir[1]; - } - } - else if(min_k != (uint32_t)-1) - { - break; - } - } - - if(e_occ <= ((e_occ+ne_occ)*m_rate)) goto c_break; - return (uint32_t)-1; - - - c_break: - k = min_k; c_beg = min_l; c_end = c_beg + Get_READ_LENGTH((*RNF), (u->a[k]>>33)); - if((p_beg - c_beg) <= (c_end - p_end)) - { - if(k == 0 && !u->circ) return (uint32_t)-1; - return k; - } - else - { - if((k+1) < u->n) return k+1; - if((k+1) == u->n && u->circ) return 0; - return (uint32_t)-1; - } - - return (uint32_t)-1; -} - -void debug_break_point_advance(ma_utg_t *u, uint32_t uID, asg_t* read_g, All_reads *RNF, ma_hit_t_alloc* sources, -R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, uint8_t* r_flag) -{ - if(u->n < 2 || u->m == 0) return; - uint32_t k, l, c_beg; - memset(r_flag, 0, read_g->n_seq); - for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 1; - kvec_t_u64_warp d; kv_init(d.a); - kvec_t_u64_warp b_d; kv_init(b_d.a); - - d.a.n = 0; - for (k = l = 0; k < u->n; k++) - { - c_beg = l; - l += (uint32_t)u->a[k]; - get_break_point_cov_advance((uint64_t)(u->a[k])>>32, c_beg, read_g, RNF, sources, ruIndex, r_flag, &d, u->len, u->circ, &uID); - } - - for (k = l = 0; k < u->n; k++) - { - c_beg = l; - l += (uint32_t)u->a[k]; - get_break_point_cov_advance((uint64_t)(u->a[k])>>32, c_beg, read_g, RNF, sources, ruIndex, r_flag, &d, u->len, u->circ, NULL); - } - - kv_malloc(b_d.a, d.a.n); b_d.a.n = d.a.n; - memcpy(b_d.a.a, d.a.a, d.a.n*sizeof(uint64_t)); - - radix_sort_arch64(d.a.a, d.a.a + d.a.n); - - long long dp, o_dp; - uint32_t idx, o_idx, dir, o_dir, i; - uint64_t k_beg, k_end, k_dp, b_beg, b_end, occ; - dp = 0; o_idx = 0; o_dir = 1;///means it is a beg - for (k = 0; k < d.a.n; k++) - { - o_dp = dp; - ///if start = end, we should meet end first, otherwise it will have a bug - if(d.a.a[k]&1) ++dp; - else --dp; - - dir = d.a.a[k]&1; idx = d.a.a[k]>>2; - if((idx - o_idx > 0) || (idx == o_idx && o_dir != dir)) - { - k_beg = o_idx; k_end = idx; k_dp = o_dp; - - for (i = occ = 0; i < b_d.a.n; i += 2) - { - b_beg = b_d.a.a[i]>>2; - b_end = b_d.a.a[i+1]>>2; - if(b_beg <= k_beg && b_end >= k_end) occ++; - if((k_beg == k_end) && (b_beg == k_beg || b_end == k_beg)) occ--; - } - if(occ != k_dp) - { - fprintf(stderr, "k_beg: %lu, k_end: %lu, k_dp: %lu, occ: %lu\n", k_beg, k_end, k_dp, occ); - } - } - o_idx = idx; - o_dir = dir; - } - - if(o_idx != u->len) - { - k_beg = o_idx; k_end = u->len; k_dp = 0; - - for (i = occ = 0; i < b_d.a.n; i += 2) - { - b_beg = b_d.a.a[i]>>2; - b_end = b_d.a.a[i+1]>>2; - if(b_beg <= k_beg && b_end >= k_end) occ++; - } - if(occ != k_dp) - { - fprintf(stderr, "k_beg: %lu, k_end: %lu, k_dp: %lu, occ: %lu\n", k_beg, k_end, k_dp, occ); - } - } - - kv_destroy(d.a); kv_destroy(b_d.a); -} - -void detect_break_point_advance(ma_utg_t *u, uint32_t uID, asg_t* read_g, All_reads *RNF, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, -uint8_t* r_flag, kvec_t_u64_warp* d, kv_in_sub_t* depth_i, kvec_t_u64_warp* res, int* b_low_cov, -int* b_high_cov, double m_rate) -{ - if(u->n < 2 || u->m == 0) return; - uint32_t k, l, c_beg; - memset(r_flag, 0, read_g->n_seq); - for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 1; - - d->a.n = 0; - for (k = l = 0; k < u->n; k++) - { - c_beg = l; - l += (uint32_t)u->a[k]; - get_break_point_cov_advance((uint64_t)(u->a[k])>>32, c_beg, read_g, RNF, sources, ruIndex, r_flag, d, u->len, u->circ, &uID); - } - - for (k = l = 0; k < u->n; k++) - { - c_beg = l; - l += (uint32_t)u->a[k]; - get_break_point_cov_advance((uint64_t)(u->a[k])>>32, c_beg, read_g, RNF, sources, ruIndex, r_flag, d, u->len, u->circ, NULL); - } - - radix_sort_arch64(d->a.a, d->a.a + d->a.n); - - long long dp, o_dp; - uint32_t idx, o_idx, dir, o_dir; - in_sub_t* p = NULL; - - - - /*******************************for debug************************************/ - ///debug_break_point_advance(u, uID, read_g, RNF, sources, ruIndex, edge, r_flag); - /*******************************for debug************************************/ - - - - - - - - - - depth_i->n = 0; - ///[start, end) - ///for circle - dp = 0; o_idx = 0; o_dir = 1;///means it is a beg - for (k = 0; k < d->a.n; k++) - { - o_dp = dp; - ///if start = end, we should meet end first, otherwise it will have a bug - if(d->a.a[k]&1) ++dp; - else --dp; - - dir = d->a.a[k]&1; idx = d->a.a[k]>>2; - if((idx - o_idx > 0) || (idx == o_idx && o_dir != dir)) - { - if(b_low_cov) - { - ///merge - if(o_dp >= (*b_low_cov) && depth_i->n > 0 && (int)depth_i->a[depth_i->n-1].dp >= (*b_low_cov)) - { - p = &(depth_i->a[depth_i->n-1]); - p->k_end = idx; - p->dp = o_dp; - } - else //insert new - { - kv_pushp(in_sub_t, *depth_i, &p); - p->k_beg = o_idx; - p->k_end = idx; - p->dp = o_dp; - } - } - - if(b_high_cov) - { - if(o_dp <= (*b_high_cov) && depth_i->n > 0 && (int)depth_i->a[depth_i->n-1].dp <= (*b_high_cov)) - { - p = &(depth_i->a[depth_i->n-1]); - p->k_end = idx; - p->dp = o_dp; - } - else //insert new - { - kv_pushp(in_sub_t, *depth_i, &p); - p->k_beg = o_idx; - p->k_end = idx; - p->dp = o_dp; - } - } - - } - o_idx = idx; - o_dir = dir; - } - - if(o_idx != u->len) - { - kv_pushp(in_sub_t, *depth_i, &p); - p->k_beg = o_idx; - p->k_end = u->len; - p->dp = 0; - } - - // if(b_high_cov) - // { - // fprintf(stderr, "\n\n\n\n\n\n\n\n\n\n"); - // fprintf(stderr, "uID: %u, u->n: %u, u->len: %u\n", uID, (uint32_t)u->n, (uint32_t)u->len); - // for (k = 0; k < depth_i->n; k++) - // { - // fprintf(stderr, "k: %u, k_beg: %lu, k_end: %lu, dp: %u\n", - // k, depth_i->a[k].k_beg, depth_i->a[k].k_end, depth_i->a[k].dp); - // } - // } - - - uint32_t beg_idx, end_idx, cir_beg_idx, cir_end_idx, min, min_idx, cur_idx, i; - beg_idx = end_idx = (uint32_t)-1; - cir_beg_idx = cir_end_idx = (uint32_t)-1; - uint64_t tmp; - - for (k = 0; k < depth_i->n; k++) - { - if(k > 0) - { - if((b_low_cov && (int)depth_i->a[k-1].dp >= (*b_low_cov) && (int)depth_i->a[k].dp < (*b_low_cov)) || - (b_high_cov && (int)depth_i->a[k-1].dp <= (*b_high_cov) && (int)depth_i->a[k].dp > (*b_high_cov))) - { - beg_idx = k; - } - } - - if(k < depth_i->n-1) - { - if((b_low_cov && (int)depth_i->a[k].dp < (*b_low_cov) && (int)depth_i->a[k+1].dp >= (*b_low_cov)) || - (b_high_cov && (int)depth_i->a[k].dp > (*b_high_cov) && (int)depth_i->a[k+1].dp <= (*b_high_cov))) - { - end_idx = k; - if(beg_idx == (uint32_t)-1) cir_end_idx = k; - - - if(beg_idx != (uint32_t)-1 && end_idx >= beg_idx) - { - min = min_idx = (uint32_t)-1; - for (i = beg_idx; i <= end_idx; i++) - { - // if(b_high_cov) - // { - // fprintf(stderr, "+k_end: %lu, k_end: %lu, dp: %u\n", depth_i->a[i].k_beg, depth_i->a[i].k_end, depth_i->a[i].dp); - // } - if(depth_i->a[i].dp < min) - { - cur_idx = get_break_point_idx(u, RNF, r_flag, sources, read_g, ruIndex, - depth_i->a[i].k_beg, depth_i->a[i].k_end, m_rate); - if(cur_idx == (uint32_t)-1) continue; - min = depth_i->a[i].dp; min_idx = cur_idx; - } - } - if(min_idx != (uint32_t)-1) - { - //fprintf(stderr, "+uID: %u, min_idx: %u, k_beg: %lu, k_end: %lu\n", uID, min_idx, depth_i->a[min_idx].k_beg, depth_i->a[min_idx].k_end); - if(min_idx != (uint32_t)-1) - { - tmp = uID; tmp <<=32; tmp += min_idx; - kv_push(uint64_t, res->a, tmp); - } - } - } - beg_idx = end_idx = (uint32_t)-1; - } - } - } - - if(beg_idx != (uint32_t)-1 && end_idx == (uint32_t)-1) cir_beg_idx = beg_idx; - - if(u->circ && (cir_beg_idx != (uint32_t)-1 || cir_end_idx != (uint32_t)-1)) - { - beg_idx = cir_beg_idx; - end_idx = cir_end_idx; - - min = min_idx = (uint32_t)-1; - if(beg_idx != (uint32_t)-1) - { - for (i = beg_idx; i < depth_i->n; i++) - { - // if(b_high_cov) - // { - // fprintf(stderr, "-0-k_end: %lu, k_end: %lu, dp: %u\n", depth_i->a[i].k_beg, depth_i->a[i].k_end, depth_i->a[i].dp); - // } - if(depth_i->a[i].dp < min) - { - // min = depth_i->a[i].dp; - // min_idx = i; - cur_idx = get_break_point_idx(u, RNF, r_flag, sources, read_g, ruIndex, - depth_i->a[i].k_beg, depth_i->a[i].k_end, m_rate); - if(cur_idx == (uint32_t)-1) continue; - min = depth_i->a[i].dp; min_idx = cur_idx; - } - } - } - - if(end_idx != (uint32_t)-1) - { - for (i = 0; i <= end_idx; i++) - { - // if(b_high_cov) - // { - // fprintf(stderr, "-1-k_end: %lu, k_end: %lu, dp: %u\n", depth_i->a[i].k_beg, depth_i->a[i].k_end, depth_i->a[i].dp); - // } - if(depth_i->a[i].dp < min) - { - cur_idx = get_break_point_idx(u, RNF, r_flag, sources, read_g, ruIndex, - depth_i->a[i].k_beg, depth_i->a[i].k_end, m_rate); - if(cur_idx == (uint32_t)-1) continue; - min = depth_i->a[i].dp; min_idx = cur_idx; - } - } - } - - if(min_idx != (uint32_t)-1) - { - ///fprintf(stderr, "-uID: %u, min_idx: %u, k_beg: %lu, k_end: %lu\n", uID, min_idx, depth_i->a[min_idx].k_beg, depth_i->a[min_idx].k_end); - if(min_idx != (uint32_t)-1) - { - tmp = uID; tmp <<=32; tmp += min_idx; - kv_push(uint64_t, res->a, tmp); - } - } - } -} - -void detect_break_point(ma_utg_t *u, uint32_t uID, asg_t* read_g, All_reads *RNF, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, -uint8_t* r_flag, kvec_t_u32_warp* depth, kvec_t_u64_warp* res, uint32_t b_low_cov) -{ - depth->a.n = 0; - ///res->a.n = 0; - if(u->n < 2) return; - uint32_t k, i, min, min_idx, rId, *p = NULL, beg_idx, end_idx, cir_beg_idx, cir_end_idx; - uint64_t tmp; - if(u->m == 0) return; - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 1; - } - - - for (k = 0; k < u->n; k++) - { - kv_pushp(uint32_t, depth->a, &p); - (*p) = get_break_point_cov(u, k, k+1, read_g, RNF, sources, ruIndex, coverage_cut, max_hang, min_ovlp, edge, r_flag); - } - - - beg_idx = end_idx = (uint32_t)-1; - cir_beg_idx = cir_end_idx = (uint32_t)-1; - for (k = 0; k < u->n; k++) - { - if(k > 0 && depth->a.a[k-1] >= b_low_cov && depth->a.a[k] < b_low_cov) - { - beg_idx = k; - } - - if(k < u->n-1 && depth->a.a[k] < b_low_cov && depth->a.a[k+1] >= b_low_cov) - { - end_idx = k; - if(beg_idx == (uint32_t)-1) cir_end_idx = k; - if(beg_idx != (uint32_t)-1 && end_idx >= beg_idx) - { - min = min_idx = (uint32_t)-1; - for (i = beg_idx; i <= end_idx; i++) - { - if(depth->a.a[i] < min) - { - min = depth->a.a[i]; - min_idx = i; - } - } - if(min_idx != (uint32_t)-1) - { - tmp = uID; tmp <<=32; tmp += min_idx; - kv_push(uint64_t, res->a, tmp); - } - } - beg_idx = end_idx = (uint32_t)-1; - } - } - - if(beg_idx != (uint32_t)-1 && end_idx == (uint32_t)-1) cir_beg_idx = beg_idx; - - if(u->circ && (cir_beg_idx != (uint32_t)-1 || cir_end_idx != (uint32_t)-1)) - { - beg_idx = cir_beg_idx; - end_idx = cir_end_idx; - - min = min_idx = (uint32_t)-1; - - if(beg_idx != (uint32_t)-1) - { - for (i = beg_idx; i < u->n; i++) - { - if(depth->a.a[i] < min) - { - min = depth->a.a[i]; - min_idx = i; - } - } - } - - if(end_idx != (uint32_t)-1) - { - for (i = 0; i <= end_idx; i++) - { - if(depth->a.a[i] < min) - { - min = depth->a.a[i]; - min_idx = i; - } - } - } - - if(min_idx != (uint32_t)-1) - { - tmp = uID; tmp <<=32; tmp += min_idx; - kv_push(uint64_t, res->a, tmp); - } - } - - - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 0; - } -} - -void debug_break_point(ma_utg_t *u, uint32_t uID, asg_t* read_g, All_reads *RNF, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, -uint8_t* r_flag, kvec_t_u32_warp* depth, kvec_t_u64_warp* res, uint32_t b_low_cov) -{ - depth->a.n = 0; - ///res->a.n = 0; - if(u->n < 2) return; - uint32_t k, min, min_idx, rId, *p = NULL; - if(u->m == 0) return; - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 1; - } - - - for (k = 0; k < u->n; k++) - { - kv_pushp(uint32_t, depth->a, &p); - (*p) = get_break_point_cov(u, k, k+1, read_g, RNF, sources, ruIndex, coverage_cut, max_hang, min_ovlp, edge, r_flag); - } - - int k_i, is_end; - min_idx = min = (uint32_t)-1; - for (k = 0; k < res->a.n; k++) - { - if((res->a.a[k]>>32) != uID) continue; - min_idx = (uint32_t)res->a.a[k]; - min = depth->a.a[min_idx]; - - is_end = 0; - k_i = (int)(min_idx) - 1; - while (k_i >= 0) - { - if(depth->a.a[k_i] >= b_low_cov) break; - if(depth->a.a[k_i] < min) fprintf(stderr, "ERROR1\n"); - k_i--; - if(k_i < 0 && u->circ && is_end == 0) - { - k_i = u->n - 1; - is_end = 1; - } - } - - is_end = 0; - k_i = (int)(min_idx) + 1; - while(k_i < (int)u->n) - { - if(depth->a.a[k_i] >= b_low_cov) break; - if(depth->a.a[k_i] < min) fprintf(stderr, "ERROR2\n"); - k_i++; - if(k_i >= (int)u->n && u->circ && is_end == 0) - { - k_i = 0; - is_end = 1; - } - } - } - - - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 0; - } -} - -void debug_contig_end(ma_ug_t *ug, asg_t* read_g, kvec_asg_arc_t_warp* edge) -{ - asg_t* nsg = ug->g; - uint32_t n_vtx = nsg->n_seq<<1, v, w, nv, v_occ, rv, rw, i; - asg_arc_t *av = NULL; - ma_utg_t* u = NULL; - - for (v = 0; v < n_vtx; v++) - { - if(ug->g->seq[v>>1].del) continue; - u = &(ug->u.a[v>>1]); - if(u->n == 0) continue; - av = asg_arc_a(ug->g, v); - nv = asg_arc_n(ug->g, v); - if(nv == 0) continue; - - if(v&1) rv = ug->u.a[v>>1].start^1; - else rv = ug->u.a[v>>1].end^1; - - for (i = v_occ = 0; i < nv; i++) - { - if(av[i].del) continue; - v_occ++; - } - if(v_occ == 0) continue; - - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - w = av[i].v; - if(w&1) rw = ug->u.a[w>>1].end; - else rw = ug->u.a[w>>1].start; - - fprintf(stderr, "utg: (v>>1: %u)[v&1: %u]->(w>>1: %u)[w&1: %u]\n", v>>1, v&1, w>>1, w&1); - fprintf(stderr, "rtg: (r_v>>1: %u)[r_v&1: %u]->(r_w>>1: %u)[r_w&1: %u]\n\n", - rv>>1, rv&1, rw>>1, rw&1); - } - } -} - -void push_sub_unitig(ma_ug_t *n_ug, ma_utg_t *src_u, asg_t *read_g, kvec_asg_arc_t_warp* edge, -uint32_t beg_idx, uint32_t occ) -{ - uint32_t i; - uint64_t totalLen; - ma_utg_t* p = NULL; - kv_pushp(ma_utg_t, n_ug->u, &p); - p->s = NULL; - p->n = occ; - p->circ = 0; - if(beg_idx == 0 && occ == src_u->n) p->circ = src_u->circ; - p->m = p->n; - p->a = (uint64_t*)malloc(8 * p->m); - for (i = 0; i < occ; i++) p->a[i] = src_u->a[beg_idx+i]; - fill_unitig(p->a, occ, read_g, edge, p->circ, &totalLen); - p->len = totalLen; - if(!p->circ) - { - p->start = p->a[0]>>32; - p->end = (p->a[p->n-1]>>32)^1; - } - else - { - p->start = p->end = UINT32_MAX; - } -} - -void break_all_contigs(ma_ug_t **ug, asg_t *read_g, kvec_asg_arc_t_warp* edge, kvec_t_u64_warp* break_points) -{ - asg_cleanup((*ug)->g); - uint32_t k, l, m, occ, uID, idx; - uint64_t *a = NULL, w; - ma_utg_t *u = NULL; - radix_sort_arch64(break_points->a.a, break_points->a.a + break_points->a.n); - uint32_t *utg_idx = NULL; MALLOC(utg_idx, (*ug)->u.n<<1); - memset(utg_idx, -1, sizeof(uint32_t)*((*ug)->u.n<<1)); - asg_arc_t *av = NULL; - uint32_t p_u_idx, nv, v, s_i, p_i; - ma_ug_t *n_ug = NULL; - ma_utg_t *p = NULL, *z = NULL; - n_ug = (ma_ug_t*)calloc(1, sizeof(ma_ug_t)); - n_ug->g = asg_init(); - - for (k = m = 0; k < break_points->a.n; k++) - { - if(k == 0 || (m > 0 && break_points->a.a[m-1] != break_points->a.a[k])) - { - break_points->a.a[m] = break_points->a.a[k]; - m++; - } - } - ///fprintf(stderr, "break_points->a.n: %u, m: %u\n", (uint32_t)break_points->a.n, m); - break_points->a.n = m; - - for (k = 1, l = 0, p_i = 0; k <= break_points->a.n; ++k) - { - if (k == break_points->a.n || (break_points->a.a[k]>>32) != (break_points->a.a[l]>>32)) - { - occ = k - l; - a = break_points->a.a + l; - l = k; - if(occ == 0) continue; - uID = a[0]>>32; - u = &((*ug)->u.a[uID]); - if(u->n < 2) continue; - - for (s_i = p_i; s_i < uID; s_i++) - { - kv_pushp(ma_utg_t, n_ug->u, &p); - z = &((*ug)->u.a[s_i]); - (*p) = (*z); - z->len = z->circ = /**z->start = z->end =**/ z->m = z->n = 0; - z->a = NULL; z->s = NULL; - - utg_idx[s_i<<1] = ((uint32_t)(n_ug->u.n-1))<<1; - utg_idx[(s_i<<1)+1] = (((uint32_t)(n_ug->u.n-1))<<1)+1; - } - p_i = uID + 1; - - - utg_idx[(uID<<1)+1] = (((uint32_t)(n_ug->u.n))<<1)+1; - for (m = p_u_idx = 0; m < occ; m++) - { - idx = (uint32_t)(a[m]); - if(!u->circ && idx == 0) - { - fprintf(stderr, "ERROR 1\n"); - continue; - } - - - if(u->circ && idx == 0) - { - av = asg_arc_a((*ug)->g, (uID<<1)+1); - nv = asg_arc_n((*ug)->g, (uID<<1)+1); - for (v = 0; v < nv; v++) - { - if(av[v].del) continue; - av[v].del = 1; - asg_arc_del((*ug)->g, (av[v].v)^1, (av[v].ul>>32)^1, 1); - } - u->circ = 0; - u->start = u->a[0]>>32; - u->end = (u->a[u->n-1]>>32)^1; - continue; - } - - if(idx - p_u_idx <= 0) - { - fprintf(stderr, "ERROR2: uID: %u, u->circ: %u, idx: %u, p_u_idx: %u\n", - uID, u->circ, idx, p_u_idx); - continue; - } - - - push_sub_unitig(n_ug, u, read_g, edge, p_u_idx, idx - p_u_idx); - p_u_idx = idx; - } - push_sub_unitig(n_ug, u, read_g, edge, p_u_idx, u->n - p_u_idx); - utg_idx[(uID<<1)] = ((uint32_t)(n_ug->u.n-1))<<1; - - } - } - - for (s_i = p_i; s_i < (*ug)->u.n; s_i++) - { - kv_pushp(ma_utg_t, n_ug->u, &p); - z = &((*ug)->u.a[s_i]); - (*p) = (*z); - z->len = z->circ = /**z->start = z->end =**/ z->m = z->n = 0; - z->a = NULL; z->s = NULL; - - utg_idx[s_i<<1] = ((uint32_t)(n_ug->u.n-1))<<1; - utg_idx[(s_i<<1)+1] = (((uint32_t)(n_ug->u.n-1))<<1)+1; - } - - // for (k = 0; k < (*ug)->u.n; k++) - // { - // if(utg_idx[(k<<1)] == (uint32_t)-1) fprintf(stderr, "ERROR 3\n"); - // if(utg_idx[(k<<1)+1] == (uint32_t)-1) fprintf(stderr, "ERROR 4\n"); - // } - - asg_arc_t *q = NULL; - for (k = 0; k < (*ug)->g->n_arc; k++) - { - if((*ug)->g->arc[k].del) continue; - q = asg_arc_pushp(n_ug->g); - (*q) = (*ug)->g->arc[k]; - - q->v = utg_idx[q->v^1]^1; - - w = q->ul>>32; w = utg_idx[w]; w <<= 32; - q->ul <<= 32; q->ul >>= 32; q->ul |= w; - } - - for (k = 0; k < n_ug->u.n; k++) - { - asg_seq_set(n_ug->g, k, n_ug->u.a[k].len, 0); - } - - asg_cleanup(n_ug->g); - - // fprintf(stderr, "n_ug->u.n: %u, n_ug->g->n_seq: %u, (*ug)->u.n: %u\n", (uint32_t)n_ug->u.n, (uint32_t)n_ug->g->n_seq, - // (uint32_t)(*ug)->u.n); - - // for (k = 0; k < ((*ug)->u.n<<1); k++) - // { - // uint32_t ug_rid, n_ug_rid; - // if(k&1) ug_rid = ((*ug)->u.a[k>>1]).start; - // else ug_rid = ((*ug)->u.a[k>>1]).end; - - // if(utg_idx[k]&1) n_ug_rid = n_ug->u.a[utg_idx[k]>>1].start; - // else n_ug_rid = n_ug->u.a[utg_idx[k]>>1].end; - - // if(ug_rid != n_ug_rid) - // { - // fprintf(stderr, "ERROR, uid: %u, dir: %u, circle: %u, ug_rid: %u, n_ug_rid: %u\n", - // k>>1, k&1, (*ug)->u.a[k>>1].circ, ug_rid, n_ug_rid); - // } - // } - - - - ma_ug_destroy((*ug)); - (*ug) = n_ug; - renew_utg(ug, read_g, edge); ///for circle - // fprintf(stderr, "***********(1)edge->a.n: %u***********\n", (uint32_t)edge->a.n); - // debug_utg_graph(*ug, read_g, edge, 0, 0); - // fprintf(stderr, "***********(1)edge->a.n: %u***********\n", (uint32_t)edge->a.n); - free(utg_idx); -} - -void print_utg_stats(ma_ug_t *ug, const char* command) -{ - uint32_t i; - uint64_t len, occ_n, occ_m, occ_n_0; - for (i = len = occ_n = occ_m = occ_n_0 = 0; i < ug->u.n; ++i) { - ma_utg_t *u = &ug->u.a[i]; - len += u->len; - occ_n += u->n; - occ_m += u->m; - if(u->n == 0) occ_n_0++; - } - - fprintf(stderr, "%s: len: %lu, occ_n: %lu, occ_m: %lu, occ_n_0: %lu\n", - command, len, occ_n, occ_m, occ_n_0); -} - -void break_ug_contig(ma_ug_t **ug, asg_t *read_g, All_reads *RNF, ma_sub_t *coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, -int* b_low_cov, int* b_high_cov, double m_rate) -{ - if(b_low_cov) - { - fprintf(stderr, "[M::%s] break potential misassemblies with <%d-fold coverage\n", - __func__, *b_low_cov); - } - - if(b_high_cov) - { - fprintf(stderr, "[M::%s] break potential misassemblies with >%d-fold coverage\n", - __func__, *b_high_cov); - } - - kvec_t_u64_warp depth; - kv_init(depth.a); - kvec_t_u64_warp break_points; - kv_init(break_points.a); - kv_in_sub_t depth_i; - kv_init(depth_i); - uint32_t i; - uint8_t* primary_flag = (uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)); - ma_utg_t *u = NULL; - - for (i = 0; i < (*ug)->u.n; ++i) - { - u = &((*ug)->u.a[i]); - if(u->m == 0) continue; - if(u->n < 2) continue; - // detect_break_point(u, i, read_g, RNF, coverage_cut, sources, ruIndex, edge, max_hang, min_ovlp, primary_flag, &depth, &break_points, b_low_cov); - // debug_break_point(u, i, read_g, RNF, coverage_cut, sources, ruIndex, edge, max_hang, min_ovlp, primary_flag, &depth, &break_points, b_low_cov); - detect_break_point_advance(u, i, read_g, RNF, coverage_cut, sources, ruIndex, edge, max_hang, min_ovlp, - primary_flag, &depth, &depth_i, &break_points, b_low_cov, b_high_cov, m_rate); - - } - - break_all_contigs(ug, read_g, edge, &break_points); - - kv_destroy(depth.a); - kv_destroy(break_points.a); - kv_destroy(depth_i); - free(primary_flag); -} - -int asg_arc_cut_long_tip_primary_complex(asg_t *g, float drop_ratio, uint32_t stops_threshold) -{ - double startTime = Get_T(); - ///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, convex, flag; - long long ll, max_stopLen; - - buf_t b; - memset(&b, 0, sizeof(buf_t)); - - for (v = 0; v < n_vtx; ++v) - { - uint32_t i; - ///some node could be deleted - if (g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - ///tip - if (get_real_length(g, v, NULL) != 0) continue; - if(get_real_length(g, v^1, NULL) != 1) continue; - flag = detect_single_path_with_dels(g, v^1, &convex, &ll, NULL); - if(flag != TWO_INPUT && flag != MUL_INPUT) continue; - convex = convex^1;ll--; - uint32_t n_convex = asg_arc_n(g, convex), convexLen = ll; - asg_arc_t *a_convex = asg_arc_a(g, convex); - - - for (i = 0; i < n_convex; i++) - { - if (!a_convex[i].del) - { - ///if stops_threshold = 1, - ///detect_single_path_with_dels_n_stops() is detect_single_path_with_dels() - detect_single_path_with_dels_n_stops(g, a_convex[i].v, &convex, &ll, &max_stopLen, - NULL, stops_threshold); - - if(convex == v) continue; - - if(ll*drop_ratio > convexLen && max_stopLen*2>ll) - { - - b.b.n = 0; - flag = detect_single_path_with_dels(g, v^1, &convex, &ll, &b); - if(b.b.n < 2) break; - b.b.n--; - - - n_reduced++; - uint64_t k; - - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]].c = ALTER_LABLE; - } - - for (k = 0; k < b.b.n; k++) - { - asg_seq_drop(g, b.b.a[k]); - } - break; - } - } - } - } - - - asg_cleanup(g); - asg_symm(g); - free(b.b.a); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d long tips\n", - __func__, n_reduced); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - return n_reduced; -} - -int asg_arc_cut_long_equal_tips_assembly(asg_t *g, ma_hit_t_alloc* reverse_sources, -long long miniedgeLen, R_to_U* ruIndex) -{ - double startTime = Get_T(); - ///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, convex, flag, is_hap; - long long ll, base_maxLen, base_maxLen_i; - - buf_t b; - memset(&b, 0, sizeof(buf_t)); - - for (v = 0; v < n_vtx; ++v) - { - uint32_t i, n_arc = 0, nv = asg_arc_n(g, v), n_tips; - asg_arc_t *av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - n_arc = get_real_length(g, v, NULL); - if (n_arc < 2) continue; - - base_maxLen = -1; - base_maxLen_i = -1; - n_tips = 0; - is_hap = 0; - - for (i = 0; i < nv; i++) - { - if (!av[i].del) - { - flag = detect_single_path_with_dels_contigLen(g, av[i].v, &convex, &ll, NULL); - - if(base_maxLen < ll) - { - base_maxLen = ll; - base_maxLen_i = i; - } - - if(flag == END_TIPS) - { - n_tips++; - } - } - } - - ///at least one tip - if(n_tips > 0) - { - for (i = 0; i < nv; i++) - { - if(i == base_maxLen_i) continue; - if (!av[i].del) - { - b.b.n = 0; - if(detect_single_path_with_dels_contigLen(g, av[i].v, &convex, &ll, &b) - != END_TIPS) - { - continue; - } - //we can only cut tips - /****************************may have bugs********************************/ - if(check_if_diploid(av[base_maxLen_i].v, av[i].v, g, - reverse_sources, miniedgeLen, ruIndex)==1) - {/****************************may have bugs********************************/ - n_reduced++; - uint64_t k; - - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]].c = ALTER_LABLE; - } - for (k = 0; k < b.b.n; k++) - { - asg_seq_drop(g, b.b.a[k]); - } - is_hap++; - } - } - } - } - - - if(is_hap > 0) - { - i = base_maxLen_i; - b.b.n = 0; - detect_single_path_with_dels_contigLen(g, av[i].v, &convex, &ll, &b); - - uint64_t k; - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]].c = HAP_LABLE; - } - } - - - } - - - asg_cleanup(g); - asg_symm(g); - free(b.b.a); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d long tips\n", - __func__, n_reduced); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - - return n_reduced; -} - - -int asg_arc_simple_large_bubbles(asg_t *g, ma_hit_t_alloc* reverse_sources, long long miniedgeLen, -R_to_U* ruIndex) -{ - double startTime = Get_T(); - ///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, convex, flag, is_hap; - long long ll, base_maxLen, base_maxLen_i, all_covex; - - buf_t b; - memset(&b, 0, sizeof(buf_t)); - - for (v = 0; v < n_vtx; ++v) - { - uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - n_arc = get_real_length(g, v, NULL); - if (n_arc < 2) continue; - - base_maxLen = -1; - base_maxLen_i = -1; - all_covex = -1; - is_hap = 0; - - for (i = 0; i < nv; i++) - { - if (!av[i].del) - { - flag = detect_single_path_with_dels_contigLen(g, av[i].v, &convex, &ll, NULL); - if(flag != TWO_INPUT && flag != MUL_INPUT) - { - break; - } - - if(all_covex != -1 && (uint32_t)all_covex != convex) - { - break; - } - - if(all_covex == -1) - { - all_covex = convex; - } - - if(base_maxLen < ll) - { - base_maxLen = ll; - base_maxLen_i = i; - } - - } - } - - - if(i == nv) - { - for (i = 0; i < nv; i++) - { - if(i == base_maxLen_i) continue; - if (!av[i].del) - { - b.b.n = 0; - detect_single_path_with_dels_contigLen(g, av[i].v, &convex, &ll, &b); - if(b.b.n < 2) continue; - b.b.n--; - - //we can only cut tips - /****************************may have bugs********************************/ - if(check_if_diploid(av[base_maxLen_i].v, av[i].v, g, - reverse_sources, miniedgeLen, ruIndex)==1) - {/****************************may have bugs********************************/ - n_reduced++; - uint64_t k; - - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]].c = ALTER_LABLE; - } - for (k = 0; k < b.b.n; k++) - { - asg_seq_drop(g, b.b.a[k]); - } - - is_hap++; - } - } - } - - if(is_hap > 0) - { - i = base_maxLen_i; - b.b.n = 0; - detect_single_path_with_dels_contigLen(g, av[i].v, &convex, &ll, &b); - uint64_t k; - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]].c = HAP_LABLE; - } - } - } - - } - - - asg_cleanup(g); - asg_symm(g); - free(b.b.a); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d long tips\n", - __func__, n_reduced); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - - return n_reduced; -} - -uint32_t get_num_trio_flag(ma_ug_t *ug, uint32_t v, uint32_t flag) -{ - if(flag == (uint32_t)-1) return 0; - ma_utg_t* u = NULL; - asg_t* nsg = ug->g; - uint32_t k, rId, flag_occ = 0; - if (nsg->seq[v].del) return 0; - u = &(ug->u.a[v]); - if(u->m == 0) return 0; - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - if(R_INF.trio_flag[rId] == flag) flag_occ++; - } - - return flag_occ; -} - - - -inline uint64_t get_utg_len(buf_t* b, ma_ug_t *ug, asg_t *read_sg, uint64_t ignore_end, uint64_t* len_thre, uint64_t* occ) -{ - if(len_thre && occ)(*occ) = (uint64_t)-1; - uint32_t ori, uid, v, nv, l, k, idx; - uint32_t *a = b->b.a, a_n = b->b.n; - uint32_t u_i, r_i, len, p_v; - asg_arc_t *av = NULL; - ma_utg_t* u = NULL; - for (u_i = r_i = len = idx = 0, p_v = (uint32_t)-1; u_i < a_n; u_i++) - { - uid = a[u_i] >> 1; - ori = a[u_i] & 1; - u = &(ug->u.a[uid]); - if(u->n == 0) continue; - if(ori == 1) - { - for (r_i = 0; r_i < u->n; r_i++, idx++) - { - v = ((uint64_t)((u->a[u->n - r_i - 1])^(uint64_t)(0x100000000)))>>32; - if(p_v == (uint32_t)-1) - { - p_v = v; - continue; - } - - av = asg_arc_a(read_sg, p_v); - nv = asg_arc_n(read_sg, p_v); - l = 0; - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == v) - { - l = asg_arc_len(av[k]); - break; - } - } - if(k == nv) fprintf(stderr, "ERROR\n"); - len += l; - if(len_thre && occ && len >= (*len_thre)) - { - (*occ) = idx; - return len; - } - p_v = v; - } - } - else - { - for (r_i = 0; r_i < u->n; r_i++, idx++) - { - v = ((uint64_t)(u->a[r_i]))>>32; - ///w = ((uint64_t)(u->a[x->r_i + 1]))>>32; - if(p_v == (uint32_t)-1) - { - p_v = v; - continue; - } - - - av = asg_arc_a(read_sg, p_v); - nv = asg_arc_n(read_sg, p_v); - l = 0; - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == v) - { - l = asg_arc_len(av[k]); - break; - } - } - if(k == nv) fprintf(stderr, "ERROR\n"); - len += l; - if(len_thre && occ && len >= (*len_thre)) - { - (*occ) = idx; - return len; - } - p_v = v; - } - } - } - - if(ignore_end == 0 && p_v != (uint32_t)-1) - { - len += read_sg->seq[p_v>>1].len; - if(len_thre && occ && len >= (*len_thre)) - { - (*occ) = idx; - return len; - } - } - - if(len_thre && occ) - { - (*occ) = idx; - } - - return len; -} - -uint32_t set_utg_offset(uint32_t *a, uint32_t a_n, ma_ug_t *ug, asg_t *read_sg, uint64_t* pos_idx, uint32_t is_clear, -uint32_t only_len) -{ - uint32_t ori, uid, v, nv, l, k; - ///uint32_t *a = b->b.a, a_n = b->b.n; - uint32_t u_i, r_i, len, p_v; - asg_arc_t *av = NULL; - ma_utg_t* u = NULL; - for (u_i = r_i = len = 0, p_v = (uint32_t)-1; u_i < a_n; u_i++) - { - uid = a[u_i] >> 1; - ori = a[u_i] & 1; - u = &(ug->u.a[uid]); - if(u->n == 0) continue; - - for (r_i = 0; r_i < u->n; r_i++) - { - l = 0; - v = (ori == 1?((uint64_t)((u->a[u->n - r_i - 1])^(uint64_t)(0x100000000)))>>32:((uint64_t)(u->a[r_i]))>>32); - - if(p_v != (uint32_t)-1 && is_clear == 0) - { - av = asg_arc_a(read_sg, p_v); - nv = asg_arc_n(read_sg, p_v); - - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == v) - { - l = asg_arc_len(av[k]); - break; - } - } - if(k == nv) fprintf(stderr, "ERROR-set_utg_offset\n"); - } - - p_v = v; len += l; - if(only_len) continue; - - if(is_clear == 1) - { - pos_idx[v>>1] = (uint64_t)-1; - } - else - { - pos_idx[v>>1] = len; - pos_idx[v>>1] <<= 32; - pos_idx[v>>1] |= (uint64_t)v; - } - } - } - - if(p_v != (uint32_t)-1) len += read_sg->seq[p_v>>1].len; - - return len; -} - - - -void print_buf_t(ma_ug_t *ug, buf_t* x, const char* command) -{ - fprintf(stderr, "%s\n", command); - uint32_t i, ori; - ma_utg_t* u = NULL; - for (i = 0; i < x->b.n; i++) - { - u = &(ug->u.a[x->b.a[i]>>1]); - if(u->n == 0) continue; - ori = x->b.a[i] & 1; - fprintf(stderr, "utg%.6ul\tori:%u\tocc:%u\tlen:%u\n", (x->b.a[i]>>1)+1, ori, (uint32_t)u->n, u->len); - } -} - -#define origin_trans_key(a) ((a).weight) -KRADIX_SORT_INIT(origin_trans_sort, asg_arc_t_offset, origin_trans_key, member_size(asg_arc_t_offset, weight)) - -#define origin_trans_el_key(a) ((a).x.el) -KRADIX_SORT_INIT(origin_trans_el_sort, asg_arc_t_offset, origin_trans_el_key, 1) - - -void refine_u_trans_t(u_trans_hit_t *q, kv_ca_buf_t* cb) -{ - ///already know [qScur, qEcur), [qSpre, qEpre) - uint32_t s, e, i, si, ei; - s = q->qScur; e = q->qEcur;///[s, e) - for (i = 0, si = ei = cb->n; i < cb->n; i++) - { - if(cb->a[i].c_x_p > s && si == cb->n) - { - si = i; - } - - if(cb->a[i].c_x_p > (e-1) && ei == cb->n) - { - ei = i; - } - - if(si != cb->n && ei != cb->n) break; - } - - if(si == 0 || ei == 0) fprintf(stderr, "ERROR-si-ei-0\n"); - if(si >= cb->n || ei >= cb->n) fprintf(stderr, "ERROR-si-ei-1\n"); - si--; ei--; - - if(s < cb->a[si].c_x_p || ((si + 1) < cb->n && s >= cb->a[si + 1].c_x_p)) - { - fprintf(stderr, "ERROR3\n"); - } - if(e < cb->a[ei].c_x_p || ((ei + 1) < cb->n && e > cb->a[ei + 1].c_x_p)) - { - fprintf(stderr, "ERROR4\n"); - } - ///si and ei must be less than (cb->n-1) - // q->tScur = cb->a[si].c_y_p + ((cb->a[si+1].c_y_p - cb->a[si].c_y_p) - // *(double)((double)(s - cb->a[si].c_x_p)/(double)(cb->a[si+1].c_x_p - cb->a[si].c_x_p))); - q->tScur = cb->a[si].c_y_p + - get_offset_adjust(s-cb->a[si].c_x_p, cb->a[si+1].c_x_p-cb->a[si].c_x_p, cb->a[si+1].c_y_p-cb->a[si].c_y_p); - - - // q->tEcur = cb->a[ei].c_y_p + ((cb->a[ei+1].c_y_p - cb->a[ei].c_y_p) - // *(double)((double)(e - cb->a[ei].c_x_p)/(double)(cb->a[ei+1].c_x_p - cb->a[ei].c_x_p))); - q->tEcur = cb->a[ei].c_y_p + - get_offset_adjust(e-cb->a[ei].c_x_p, cb->a[ei+1].c_x_p-cb->a[ei].c_x_p, cb->a[ei+1].c_y_p-cb->a[ei].c_y_p); - - - - ///might be equal - if(q->tScur > q->tEcur) fprintf(stderr, "ERROR5\n"); - // if(q->tScur >= q->tEcur) - // { - // fprintf(stderr, "\n###q->tScur: %u, s: %u, si: %u, q->tEcur: %u, e: %u, ei: %u\n", - // q->tScur, s, si, q->tEcur, e, ei); - - // fprintf(stderr, "###cb->a[si].c_x_p: %u, cb->a[si].c_y_p: %u, cb->a[si+1].c_x_p: %u, cb->a[si+1].c_y_p: %u\n", - // cb->a[si].c_x_p, cb->a[si].c_y_p, cb->a[si+1].c_x_p, cb->a[si+1].c_y_p); - - // fprintf(stderr, "###cb->a[ei].c_x_p: %u, cb->a[ei].c_y_p: %u, cb->a[ei+1].c_x_p: %u, cb->a[ei+1].c_y_p: %u\n", - // cb->a[ei].c_x_p, cb->a[ei].c_y_p, cb->a[ei+1].c_x_p, cb->a[ei+1].c_y_p); - - // fprintf(stderr, "ERROR5\n"); - // } -} - - - -///[ts, te) -void extract_sub_overlaps(uint32_t i_tScur, uint32_t i_tEcur, uint32_t i_tSpre, uint32_t i_tEpre, -uint32_t tn, kv_u_trans_hit_t* ktb, uint32_t bn) -{ - uint32_t i, ovlp, found, beg, end, offS, offE; - u_trans_hit_t *q = NULL, x; - for (i = found = 0; i < bn; i++) - { - q = &(ktb->a[i]);///for q, already know [qScur, qEcur), [qSpre, qEpre), [tScur, tEcur) - - ovlp = ((MIN(i_tEcur, q->tEcur) > MAX(i_tScur, q->tScur))? - MIN(i_tEcur, q->tEcur) - MAX(i_tScur, q->tScur):0); - if(found == 1 && ovlp == 0) break; - if(ovlp > 0) found = 1; - if(ovlp == 0) continue; - - - beg = MAX(i_tScur, q->tScur); end = MIN(i_tEcur, q->tEcur); - offS = beg - q->tScur; offE = q->tEcur - end; - x.tScur = q->tScur + offS; - x.tEcur = q->tEcur - offE; - //x.qScur = q->qScur + offS; - x.qScur = q->qScur + get_offset_adjust(offS, q->tEcur-q->tScur, q->qEcur-q->qScur); - ///x.qEcur = q->qEcur - offE; - x.qScur = q->qEcur - get_offset_adjust(offE, q->tEcur-q->tScur, q->qEcur-q->qScur); - - x.qn = q->qn; - offS = beg - q->tScur; offE = q->tEcur - end; - if((x.qn&1) == 0) - { - // x.qSpre = q->qSpre + offS; - x.qSpre = q->qSpre + get_offset_adjust(offS, q->tEcur-q->tScur, q->qEpre-q->qSpre); - // x.qEpre = q->qEpre - offE; - x.qEpre = q->qEpre - get_offset_adjust(offE, q->tEcur-q->tScur, q->qEpre-q->qSpre); - } - else - { - // x.qSpre = q->qSpre + offE; - x.qSpre = q->qSpre + get_offset_adjust(offE, q->tEcur-q->tScur, q->qEpre-q->qSpre); - // x.qEpre = q->qEpre - offS; - x.qEpre = q->qEpre - get_offset_adjust(offS, q->tEcur-q->tScur, q->qEpre-q->qSpre); - } - - x.tn = tn; - offS = beg - i_tScur; offE = i_tEcur - end; - if((x.tn&1) == 0) - { - // x.tSpre = i_tSpre + offS; - x.tSpre = i_tSpre + get_offset_adjust(offS, i_tEcur-i_tScur, i_tEpre-i_tSpre); - // x.tEpre = i_tEpre - offE; - x.tEpre = i_tEpre - get_offset_adjust(offE, i_tEcur-i_tScur, i_tEpre-i_tSpre); - } - else - { - // x.tSpre = i_tSpre + offE; - x.tSpre = i_tSpre + get_offset_adjust(offE, i_tEcur-i_tScur, i_tEpre-i_tSpre); - // x.tEpre = i_tEpre - offS; - x.tEpre = i_tEpre - get_offset_adjust(offS, i_tEcur-i_tScur, i_tEpre-i_tSpre); - } - - kv_push(u_trans_hit_t, *ktb, x); - - // if(x.tSpre >= x.tEpre || x.qSpre >= x.qEpre) - // { - // fprintf(stderr, "\n*********x.qn: %u, x.tn: %u\n", x.qn, x.tn); - // fprintf(stderr, "x.qSpre: %u, x.qEpre: %u, x.tSpre: %u, x.tEpre: %u\n", - // x.qSpre, x.qEpre, x.tSpre, x.tEpre); - // fprintf(stderr, "q->qScur: %u, q->qEcur: %u, q->qSpre: %u, q->qEpre: %u\n", - // q->qScur, q->qEcur, q->qSpre, q->qEpre); - // fprintf(stderr, "q->tScur: %u, q->tEcur: %u, q->tSpre: %u, q->tEpre: %u\n", - // q->tScur, q->tEcur, q->tSpre, q->tEpre); - // fprintf(stderr, "i_tScur: %u, i_tEcur: %u, i_tSpre: %u, i_tEpre: %u\n", - // i_tScur, i_tEcur, i_tSpre, i_tEpre); - // } - } -} - - - -void reset_u_trans_hit_idx(u_trans_hit_idx *t, uint32_t* i_x_a, uint32_t i_x_n, ma_ug_t *i_ug, -asg_t *i_read_sg, trans_chain* i_t_ch, uint32_t i_cBeg, uint32_t i_cEnd) -{ - t->a = i_x_a; - t->an = i_x_n; - t->ug = i_ug; - t->read_sg = i_read_sg; - t->t_ch = i_t_ch; - t->cBeg = i_cBeg; - t->cEnd = i_cEnd; - t->u_i = t->r_i = t->len = t->s_pos_cur = t->s_pre_v = t->s_pre_w = 0; - t->p_v = t->p_uId = t->p_idx = (uint32_t)-1; -} - -uint32_t get_u_trans_hit(u_trans_hit_idx *t, u_trans_hit_t *hit) -{ - uint32_t uid, ori, l, v, nv, is_update, r_beg, r_end, ovlp; - uint32_t *a = t->a, a_n = t->an, k, c_uId, idx, offPre; - ma_utg_t *u = NULL; - asg_arc_t *av = NULL; - hit->qSpre = hit->qEpre = hit->qScur = hit->qEcur = hit->qn = (uint32_t)-1; - hit->tSpre = hit->tEpre = hit->tScur = hit->tEcur = hit->tn = (uint32_t)-1; - - while (t->u_i < a_n) ///(u_i = 0; u_i < a_n; u_i++) - { - uid = a[t->u_i] >> 1; - ori = a[t->u_i] & 1; - u = &(t->ug->u.a[uid]); - if(u->n == 0) continue; - - while(t->r_i < u->n) ///for (r_i = 0; r_i < u->n; r_i++) - { - l = 0; - v = (ori == 1?((uint64_t)((u->a[u->n-t->r_i-1])^(uint64_t)(0x100000000)))>>32:((uint64_t)(u->a[t->r_i]))>>32); - - if(t->p_v != (uint32_t)-1) - { - av = asg_arc_a(t->read_sg, t->p_v); - nv = asg_arc_n(t->read_sg, t->p_v); - - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == v) - { - l = asg_arc_len(av[k]); - break; - } - } - if(k == nv) fprintf(stderr, "ERROR-nv\n"); - } - - ///[t->cBeg, t->cEnd) - r_beg = t->len; r_end = t->len + - (t->p_v != (uint32_t)-1? t->read_sg->seq[t->p_v>>1].len : 0); - ovlp = ((MIN(t->cEnd, r_end) > MAX(t->cBeg, r_beg))? (MIN(t->cEnd, r_end) - MAX(t->cBeg, r_beg)) : 0); - c_uId = get_origin_uid(v, t->t_ch, &offPre, &idx); - - - if(ovlp == 0) - { - if(r_beg >= t->cEnd) - { - if(t->p_uId != (uint32_t)-1) - { - hit->qn = t->p_uId; - hit->qScur = t->s_pos_cur; hit->qEcur = t->len + t->read_sg->seq[t->p_v>>1].len; - - - ovlp = ((MIN(t->cEnd, hit->qEcur) > MAX(t->cBeg, hit->qScur))? - (MIN(t->cEnd, hit->qEcur) - MAX(t->cBeg, hit->qScur)) : 0); - if(ovlp == 0) return 0; - - - ///[t->s_pre_v, t->p_v] - uint32_t a_pos, b_pos; - get_origin_uid(t->s_pre_v, t->t_ch, &a_pos, NULL); - get_origin_uid(t->p_v, t->t_ch, &b_pos, NULL); - hit->qSpre = MIN(a_pos, b_pos); - hit->qEpre = MAX((a_pos + t->read_sg->seq[t->s_pre_v>>1].len), (b_pos+t->read_sg->seq[t->p_v>>1].len)); - - ///[t->cBeg, t->cEnd) - if(hit->qScur < t->cBeg) - { - if((hit->qn&1) == 0) - { - ///hit->qSpre += (t->cBeg - hit->qScur); - hit->qSpre += get_offset_adjust(t->cBeg - hit->qScur, - hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); - } - else - { - ///hit->qEpre -= (t->cBeg - hit->qScur); - hit->qEpre -= get_offset_adjust(t->cBeg - hit->qScur, - hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); - } - hit->qScur = t->cBeg; - } - - if(hit->qEcur > t->cEnd) - { - if((hit->qn&1) == 0) - { - ///hit->qEpre -= (hit->qEcur - t->cEnd); - hit->qEpre -= get_offset_adjust(hit->qEcur - t->cEnd, - hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); - } - else - { - // hit->qSpre += (hit->qEcur - t->cEnd); - hit->qSpre += get_offset_adjust(hit->qEcur - t->cEnd, - hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); - } - hit->qEcur = t->cEnd; - } - t->p_uId = (uint32_t)-1; - return 1; - } - return 0; - } - else - { - t->p_uId = c_uId; t->s_pos_cur = t->len + l; t->s_pre_v = v; - t->p_v = v; t->len += l; t->p_idx = idx; - t->r_i++; - continue; - } - } - - - is_update = 0; - if(t->p_uId != c_uId) - { - is_update = 1; - - } - else///p_uId == c_uId - { - if((t->p_uId&1) == 0) ///forward - { - if(idx != (t->p_idx+1)) - { - is_update = 1; - } - } - else //backward - { - if((idx + 1) != t->p_idx) - { - is_update = 1; - } - } - } - - if(is_update) - { - if(t->p_uId != (uint32_t)-1) - { - hit->qn = t->p_uId; - hit->qScur = t->s_pos_cur; hit->qEcur = t->len + t->read_sg->seq[t->p_v>>1].len; - ///[t->s_pre_v, t->p_v] - uint32_t a_pos, b_pos; - get_origin_uid(t->s_pre_v, t->t_ch, &a_pos, NULL); - get_origin_uid(t->p_v, t->t_ch, &b_pos, NULL); - hit->qSpre = MIN(a_pos, b_pos); - hit->qEpre = MAX((a_pos + t->read_sg->seq[t->s_pre_v>>1].len), (b_pos+t->read_sg->seq[t->p_v>>1].len)); - - ///[t->cBeg, t->cEnd) - if(hit->qScur < t->cBeg) - { - if((hit->qn&1) == 0) - { - ///hit->qSpre += (t->cBeg - hit->qScur); - hit->qSpre += get_offset_adjust(t->cBeg - hit->qScur, - hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); - } - else - { - ///hit->qEpre -= (t->cBeg - hit->qScur); - hit->qEpre -= get_offset_adjust(t->cBeg - hit->qScur, - hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); - } - hit->qScur = t->cBeg; - } - - if(hit->qEcur > t->cEnd) - { - if((hit->qn&1) == 0) - { - ///hit->qEpre -= (hit->qEcur - t->cEnd); - hit->qEpre -= get_offset_adjust(hit->qEcur - t->cEnd, - hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); - } - else - { - // hit->qSpre += (hit->qEcur - t->cEnd); - hit->qSpre += get_offset_adjust(hit->qEcur - t->cEnd, - hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); - } - hit->qEcur = t->cEnd; - } - - - t->p_uId = c_uId; t->s_pos_cur = t->len + l; t->s_pre_v = v; - t->p_v = v; t->len += l; t->p_idx = idx; - t->r_i++; - return 1; - } - t->p_uId = c_uId; t->s_pos_cur = t->len + l; t->s_pre_v = v; - } - - t->p_v = v; t->len += l; t->p_idx = idx; - t->r_i++; - } - t->r_i = 0; - t->u_i++; - } - - if(t->p_uId != (uint32_t)-1) - { - hit->qn = t->p_uId; - hit->qScur = t->s_pos_cur; hit->qEcur = t->len + t->read_sg->seq[t->p_v>>1].len; - - - ovlp = ((MIN(t->cEnd, hit->qEcur) > MAX(t->cBeg, hit->qScur))? - (MIN(t->cEnd, hit->qEcur) - MAX(t->cBeg, hit->qScur)) : 0); - if(ovlp == 0) return 0; - - - ///[t->s_pre_v, t->p_v] - uint32_t a_pos, b_pos; - get_origin_uid(t->s_pre_v, t->t_ch, &a_pos, NULL); - get_origin_uid(t->p_v, t->t_ch, &b_pos, NULL); - hit->qSpre = MIN(a_pos, b_pos); - hit->qEpre = MAX((a_pos + t->read_sg->seq[t->s_pre_v>>1].len), (b_pos+t->read_sg->seq[t->p_v>>1].len)); - - ///[t->cBeg, t->cEnd) - if(hit->qScur < t->cBeg) - { - if((hit->qn&1) == 0) - { - ///hit->qSpre += (t->cBeg - hit->qScur); - hit->qSpre += get_offset_adjust(t->cBeg - hit->qScur, - hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); - } - else - { - ///hit->qEpre -= (t->cBeg - hit->qScur); - hit->qEpre -= get_offset_adjust(t->cBeg - hit->qScur, - hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); - } - hit->qScur = t->cBeg; - } - - if(hit->qEcur > t->cEnd) - { - if((hit->qn&1) == 0) - { - ///hit->qEpre -= (hit->qEcur - t->cEnd); - hit->qEpre -= get_offset_adjust(hit->qEcur - t->cEnd, - hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); - } - else - { - // hit->qSpre += (hit->qEcur - t->cEnd); - hit->qSpre += get_offset_adjust(hit->qEcur - t->cEnd, - hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); - } - hit->qEcur = t->cEnd; - } - - t->p_uId = (uint32_t)-1; - return 1; - } - return 0; -} - - -void chain_origin_trans_uid_by_distance(hap_cov_t *cov, asg_t *read_sg, -uint32_t *pri_a, uint32_t pri_n, uint32_t pri_beg, uint64_t *i_pri_len, -uint32_t *aux_a, uint32_t aux_n, uint32_t aux_beg, uint64_t *i_aux_len, -ma_ug_t *ug, uint32_t flag, double score, const char* cmd) -{ - uint32_t i, len, bn; - uint64_t pri_len, aux_len; - kvec_asg_arc_t_offset* u_buffer = &(cov->u_buffer); - kvec_t_i32_warp* tailIndex = &(cov->tailIndex); - trans_chain* t_ch = cov->t_ch; - asg_arc_t_offset *tt = NULL; - ca_buf_t *tx = NULL; - - if(i_pri_len) pri_len = (*i_pri_len); - else pri_len = set_utg_offset(pri_a, pri_n, ug, read_sg, cov->pos_idx, 0, 1); - - if(i_aux_len) aux_len = (*i_aux_len); - else aux_len = set_utg_offset(aux_a, aux_n, ug, read_sg, cov->pos_idx, 0, 1); - - tt = NULL; t_ch->c_buf.n = 0; t_ch->k_t_b.n = 0; - if(tailIndex->a.n > 0) tt = &(u_buffer->a.a[tailIndex->a.a[0]]); - if(!tt || (pri_beg < (tt->Off>>32) && aux_beg < ((uint32_t)tt->Off))) - { - kv_pushp(ca_buf_t, t_ch->c_buf, &tx); - tx->c_x_p = pri_beg; - tx->c_y_p = aux_beg; - - for (i = 0; i < tailIndex->a.n; i++) - { - tt = &(u_buffer->a.a[tailIndex->a.a[i]]); - kv_pushp(ca_buf_t, t_ch->c_buf, &tx); - - tx->c_x_p = tt->Off>>32; - tx->c_y_p = (uint32_t)tt->Off; - } - } - else if(tailIndex->a.n == 1)//1 ele in chain - { - kv_pushp(ca_buf_t, t_ch->c_buf, &tx); - tx->c_x_p = pri_beg; tx->c_y_p = aux_beg; - } - else if(tailIndex->a.n > 0) - { - uint32_t cx, cy, ax, ay, found = 0; - for (i = 0; i < tailIndex->a.n; i++) - { - cx = cy = ax = ay = (uint32_t)-1; - - cx = u_buffer->a.a[tailIndex->a.a[i]].Off>>32; - cy = (uint32_t)u_buffer->a.a[tailIndex->a.a[i]].Off; - if((i + 1) < tailIndex->a.n) - { - ax = u_buffer->a.a[tailIndex->a.a[i+1]].Off>>32; - ay = (uint32_t)u_buffer->a.a[tailIndex->a.a[i+1]].Off; - } - - kv_pushp(ca_buf_t, t_ch->c_buf, &tx); - tx->c_x_p = cx; tx->c_y_p = cy; - - if(found) continue; - if(pri_beg > cx && pri_beg < ax && aux_beg > cy && aux_beg < ay) - { - kv_pushp(ca_buf_t, t_ch->c_buf, &tx); - tx->c_x_p = pri_beg; tx->c_y_p = aux_beg; - found = 1; - } - } - } - - - // fprintf(stderr, "\ncmd-%s\n", cmd); - // fprintf(stderr, "pri_beg=%u, pri_len=%lu\n", pri_beg, pri_len); - // fprintf(stderr, "aux_beg=%u, aux_len=%lu\n", aux_beg, aux_len); - - // print_buf_t(ug, pri, "pri"); - // print_buf_t(ug, aux, "aux"); - - - tx = &(t_ch->c_buf.a[t_ch->c_buf.n-1]); - len = MIN(pri_len - tx->c_x_p, aux_len - tx->c_y_p); - if(len > 0)///insert boundary - { - kv_pushp(ca_buf_t, t_ch->c_buf, &tx); - tx->c_x_p = t_ch->c_buf.a[t_ch->c_buf.n-2].c_x_p + len; - tx->c_y_p = t_ch->c_buf.a[t_ch->c_buf.n-2].c_y_p + len; - } - - tx = &(t_ch->c_buf.a[0]);///insert boundary - if(tx->c_x_p != 0 && tx->c_y_p != 0)///already at boundary - { - len = MIN(tx->c_x_p, tx->c_y_p);///offset - kv_pushp(ca_buf_t, t_ch->c_buf, &tx); - for (i = 0; (i + 1)< t_ch->c_buf.n; i++) - { - t_ch->c_buf.a[t_ch->c_buf.n - i - 1] = t_ch->c_buf.a[t_ch->c_buf.n - i - 2]; - } - t_ch->c_buf.a[0].c_x_p = t_ch->c_buf.a[1].c_x_p - len; - t_ch->c_buf.a[0].c_y_p = t_ch->c_buf.a[1].c_y_p - len; - } - - ///chain is [s, e) - if(t_ch->c_buf.a[0].c_x_p != 0 && t_ch->c_buf.a[0].c_y_p != 0) fprintf(stderr, "ERROR1\n"); - if(t_ch->c_buf.a[t_ch->c_buf.n-1].c_x_p!= pri_len && - t_ch->c_buf.a[t_ch->c_buf.n-1].c_y_p!= aux_len) - { - fprintf(stderr, "ERROR2\n"); - } - - u_trans_hit_idx iter; - u_trans_hit_t hit, *kh = NULL; - ////////prx - reset_u_trans_hit_idx(&iter, pri_a, pri_n, ug, read_sg, t_ch, - t_ch->c_buf.a[0].c_x_p, t_ch->c_buf.a[t_ch->c_buf.n-1].c_x_p); - while(get_u_trans_hit(&iter, &hit))//get [qScur, qEcur), [qSpre, qEpre) - { - refine_u_trans_t(&hit, &(t_ch->c_buf)); ///get [tScur, tEcur) - kv_push(u_trans_hit_t, t_ch->k_t_b, hit); - } - bn = t_ch->k_t_b.n; - - ////////aux - reset_u_trans_hit_idx(&iter, aux_a, aux_n, ug, read_sg, t_ch, - t_ch->c_buf.a[0].c_y_p, t_ch->c_buf.a[t_ch->c_buf.n-1].c_y_p); - while(get_u_trans_hit(&iter, &hit)) - { - extract_sub_overlaps(hit.qScur, hit.qEcur, hit.qSpre, hit.qEpre, hit.qn, &(t_ch->k_t_b), bn); - } - - - if(t_ch->k_t_b.n - bn == 0) fprintf(stderr, "ERROR6\n"); - - - - u_trans_t *kt = NULL; - double x_score, y_score; - for (i = bn; i < t_ch->k_t_b.n; i++) - { - kh = &(t_ch->k_t_b.a[i]); - if(kh->qEpre <= kh->qSpre) continue; - if(kh->tEpre <= kh->tSpre) continue; - kv_pushp(u_trans_t, t_ch->k_trans, &kt); - kt->f = flag; kt->rev = ((kh->qn ^ kh->tn) & 1); kt->del = 0; - kt->qn = kh->qn>>1; kt->qs = kh->qSpre; kt->qe = kh->qEpre; - kt->tn = kh->tn>>1; kt->ts = kh->tSpre; kt->te = kh->tEpre; - if(score < 0) - { - kt->nw = (MIN((kt->qe - kt->qs), (kt->te - kt->ts)))*CHAIN_MATCH; - } - else - { - x_score = ((double)(kt->qe-kt->qs)/(double)(t_ch->c_buf.a[t_ch->c_buf.n-1].c_x_p-t_ch->c_buf.a[0].c_x_p))*score; - y_score = ((double)(kt->te-kt->ts)/(double)(t_ch->c_buf.a[t_ch->c_buf.n-1].c_y_p-t_ch->c_buf.a[0].c_y_p))*score; - kt->nw = MIN(x_score, y_score); - } - } - - -} - - -void collect_trans_cov(const char* cmd, buf_t* pri, uint64_t pri_offset, buf_t* aux, uint64_t aux_offset, -ma_ug_t *ug, asg_t *read_sg, hap_cov_t *cov) -{ - uint32_t i, k, rid, occ, ori, thre_pri; - uint64_t len_aux, uLen, uCov; - ma_utg_t* u = NULL; - trans_chain* t_ch = cov->t_ch; - if(pri->b.n == 0 || aux->b.n == 0) return; - - len_aux = set_utg_offset(aux->b.a, aux->b.n, ug, read_sg, cov->pos_idx, 0, 0); - chain_trans_ovlp(cov, NULL, ug, read_sg, pri, len_aux, &thre_pri); - if(thre_pri > 0) - { - /*******************************for debug************************************/ - // fprintf(stderr, "\n%s, thre_pri: %u, len_aux: %lu\n", cmd, thre_pri, len_aux); - // print_buf_t(ug, pri, "pri"); - // print_buf_t(ug, aux, "aux"); - /*******************************for debug************************************/ - - if(t_ch) - { - chain_origin_trans_uid_by_distance(cov, read_sg, pri->b.a, pri->b.n, pri_offset, NULL, - aux->b.a, aux->b.n, aux_offset, &len_aux, ug, RC_1, -1024, cmd); - } - - - for (i = uCov = 0; i < aux->b.n; i++) - { - u = &(ug->u.a[aux->b.a[i]>>1]); - if(u->n == 0) continue; - ori = aux->b.a[i] & 1; - for (k = 0; k < u->n; k++) - { - rid = (ori == 1?(u->a[u->n-k-1]>>33):(u->a[k]>>33)); - uCov += cov->cov[rid]; - - if(t_ch) t_ch->ir_het[(ori == 1?(u->a[u->n-k-1]>>33):(u->a[k]>>33))] |= P_HET; - } - } - - for (i = uLen = occ = 0; i < pri->b.n; i++) - { - u = &(ug->u.a[pri->b.a[i]>>1]); - if(u->n == 0) continue; - ori = pri->b.a[i] & 1; - for (k = 0; k < u->n; k++, occ++) - { - if(occ >= thre_pri) break; - ///rid = u->a[k]>>33; - rid = (ori == 1?(u->a[u->n-k-1]>>33):(u->a[k]>>33)); - uLen += read_sg->seq[rid].len; - - if(t_ch) t_ch->ir_het[(ori == 1?(u->a[u->n-k-1]>>33):(u->a[k]>>33))] |= P_HET; - } - if(occ >= thre_pri) break; - } - - uCov = (uLen == 0? 0 : uCov / uLen); - - for (i = occ = 0; i < pri->b.n; i++) - { - u = &(ug->u.a[pri->b.a[i]>>1]); - if(u->n == 0) continue; - ori = pri->b.a[i] & 1; - for (k = 0; k < u->n; k++, occ++) - { - if(occ >= thre_pri) break; - ///rid = u->a[k]>>33; - rid = (ori == 1?(u->a[u->n-k-1]>>33):(u->a[k]>>33)); - cov->cov[rid] += (uCov * read_sg->seq[rid].len); - } - if(occ >= thre_pri) break; - } - } - set_utg_offset(aux->b.a, aux->b.n, ug, read_sg, cov->pos_idx, 1, 0); -} - - -int asg_arc_cut_long_equal_tips_assembly_complex(asg_t *g, ma_hit_t_alloc* reverse_sources, -long long miniedgeLen, uint32_t stops_threshold, R_to_U* ruIndex) -{ - double startTime = Get_T(); - ///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, convex, flag; - long long ll, max_stopLen; - - buf_t b; - memset(&b, 0, sizeof(buf_t)); - - for (v = 0; v < n_vtx; ++v) - { - - uint32_t i; - ///some node could be deleted - if (g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - ///tip - if (get_real_length(g, v, NULL) != 0) continue; - if(get_real_length(g, v^1, NULL) != 1) continue; - flag = detect_single_path_with_dels_contigLen(g, v^1, &convex, &ll, NULL); - if(flag != TWO_INPUT && flag != MUL_INPUT) continue; - convex = convex^1; - ///uint32_t n_convex = asg_arc_n(g, convex), convexLen = ll; - uint32_t n_convex = asg_arc_n(g, convex), convexLen = (uint32_t)-1, convex_i = (uint32_t)-1; - asg_arc_t *a_convex = asg_arc_a(g, convex); - for (i = 0; i < n_convex; i++) - { - if (!a_convex[i].del) - { - detect_single_path_with_dels_contigLen(g, a_convex[i].v, &convex, &ll, NULL); - if(convex == v) - { - convexLen = ll; - convex_i = i; - break; - } - } - } - - - for (i = 0; i < n_convex; i++) - { - if (!a_convex[i].del) - { - if(i == convex_i) continue; - - detect_single_path_with_dels_contigLen_complex(g, a_convex[i].v, &convex, &ll, - &max_stopLen, NULL, stops_threshold); - ///threshold = 0.8 - if(ll > convexLen && max_stopLen*1.25>ll) - { - ///keep all nodes of this tip - b.b.n = 0; - detect_single_path_with_dels_contigLen(g, v^1, &convex, &ll, &b); - if(b.b.n < 2) break; - b.b.n--; - ///keep all nodes of this tip - - //we can only cut tips - if(check_if_diploid_primary_complex(v^1, a_convex[i].v, g, - reverse_sources, miniedgeLen, stops_threshold, 1, ruIndex)==1) - { - n_reduced++; - uint64_t k; - - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]].c = ALTER_LABLE; - } - for (k = 0; k < b.b.n; k++) - { - asg_seq_drop(g, b.b.a[k]); - } - - - ///lable the primary one - b.b.n = 0; - detect_single_path_with_dels_contigLen_complex(g, a_convex[i].v, &convex, - &ll, &max_stopLen, &b, stops_threshold); - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]].c = HAP_LABLE; - } - - break; - } - - } - - } - } - } - - - asg_cleanup(g); - asg_symm(g); - free(b.b.a); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d long tips\n", - __func__, n_reduced); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - - return n_reduced; -} - - -void output_unitig_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, R_to_U* ruIndex, int max_hang, int min_ovlp) -{ - kvec_asg_arc_t_warp new_rtg_edges; - kv_init(new_rtg_edges.a); - - ma_ug_t *ug = NULL; - ug = ma_ug_gen(sg); - ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 1); - - fprintf(stderr, "Writing raw unitig GFA to disk... \n"); - char* gfa_name = (char*)malloc(strlen(output_file_name)+25); - sprintf(gfa_name, "%s.r_utg.gfa", output_file_name); - FILE* output_file = fopen(gfa_name, "w"); - ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - fclose(output_file); - sprintf(gfa_name, "%s.r_utg.noseq.gfa", output_file_name); - output_file = fopen(gfa_name, "w"); - ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - fclose(output_file); - if(asm_opt.bed_inconsist_rate != 0) - { - sprintf(gfa_name, "%s.r_utg.lowQ.bed", output_file_name); - output_file = fopen(gfa_name, "w"); - ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, - max_hang, min_ovlp, asm_opt.bed_inconsist_rate, "utg", output_file, NULL); - fclose(output_file); - } - - free(gfa_name); - ma_ug_destroy(ug); - kv_destroy(new_rtg_edges.a); -} - -void set_ug_coverage_aggressive(ma_ug_t *ug, uint32_t uID, asg_t* read_g, -const ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag, -uint8_t* is_r_het, long long het_cov_thres) -{ - ma_utg_t *u = &(ug->u.a[uID]); - uint32_t k, j, rId, tn, is_Unitig; - long long R_bases = 0, C_bases = 0; - long long cov_in_s, cov_in_e, cov_out_s, cov_out_e, cov_in, cov_out, try_cov, cen_cov; - uint32_t nv, i; - asg_arc_t *av = NULL; - ma_hit_t *h; - if(u->m == 0) return; - - ///set - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 1; - } - - for (i = 0; i < 2; i++) - { - nv = asg_arc_n(ug->g, (uID<<1)+i); - av = asg_arc_a(ug->g, (uID<<1)+i); - for (j = 0; j < nv; j++) - { - u = &(ug->u.a[av[j].v>>1]); - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 2; - } - } - } - - - u = &(ug->u.a[uID]); - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - cov_in = cov_out = 0; - cov_in_s = cov_in_e = cov_out_s = cov_out_e = 0; - for (j = 0; j < (uint64_t)(sources[rId].length); j++) - { - h = &(sources[rId].buffer[j]); - ///if(h->del) continue; - if(h->el != 1) continue; - tn = Get_tn((*h)); - if(read_g->seq[tn].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - if(read_g->seq[tn].del == 1) continue; - if(r_flag[tn] == 0) continue; - if(r_flag[tn] == 1) - { - cov_in += (Get_qe((*h)) - Get_qs((*h))); - if(((Get_qs((*h)) <= coverage_cut[rId].s))) cov_in_s++; - if(((Get_qe((*h)) >= coverage_cut[rId].e))) cov_in_e++; - } - - if(r_flag[tn] == 2) - { - cov_out += (Get_qe((*h)) - Get_qs((*h))); - if(((Get_qs((*h)) <= coverage_cut[rId].s))) cov_out_s++; - if(((Get_qe((*h)) >= coverage_cut[rId].e))) cov_out_e++; - } - } - - if(cov_out_s >= cov_out_e) ///more out overlap from s - { - cen_cov = cov_in_e; - try_cov = cov_in_s + cov_out_s; - } - else ///more out overlap from e - { - cen_cov = cov_in_s; - try_cov = cov_in_e + cov_out_e; - } - - if(cov_out <= (cov_in*0.1)) - { - C_bases = cov_in + cov_out; - R_bases = (coverage_cut[rId].e - coverage_cut[rId].s); - } - else if((try_cov <= cen_cov*1.1) && (MIN(cov_out_s, cov_out_e)<=((MAX(cov_out_s, cov_out_e))*0.2))) - { - C_bases = cov_in + cov_out; - R_bases = (coverage_cut[rId].e - coverage_cut[rId].s); - } - else - { - C_bases = cen_cov; - R_bases = 1; - } - - if((R_bases <= 0) || ((C_bases/R_bases) <= het_cov_thres)) - { - is_r_het[rId] |= C_HET; - } - } - - - ///reset - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 0; - } - - for (i = 0; i < 2; i++) - { - nv = asg_arc_n(ug->g, (uID<<1)+i); - av = asg_arc_a(ug->g, (uID<<1)+i); - for (j = 0; j < nv; j++) - { - u = &(ug->u.a[av[j].v>>1]); - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 0; - } - } - } -} - - -void set_r_het_flag(ma_ug_t *ug, asg_t *sg, ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* is_r_het) -{ - uint64_t m, dip_thre_max, dip_thres; - uint8_t* primary_flag = (uint8_t*)calloc(sg->n_seq, sizeof(uint8_t)); - - if(asm_opt.hom_global_coverage_set) - { - dip_thre_max = asm_opt.hom_global_coverage; - } - else - { - dip_thre_max = ((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE); - } - // dip_thre_max *= 0.75; - dip_thre_max = (double)(dip_thre_max) - (((double)(dip_thre_max)*0.5)/asm_opt.polyploidy); - - // fprintf(stderr, "dip_thre_max: %lu\n", dip_thre_max); - - for (m = 0; m < ug->g->n_seq; m++) - { - dip_thres = dip_thre_max; - ///if(ug->u.a[m].n <= dip_thre_max) dip_thres = dip_thre_max * 1.1; - set_ug_coverage_aggressive(ug, m, sg, coverage_cut, sources, ruIndex, primary_flag, is_r_het, dip_thres); - } - free(primary_flag); -} - - -trans_chain* init_trans_chain(ma_ug_t *ug, uint64_t r_num) -{ - trans_chain *x = NULL; CALLOC(x, 1); - x->r_num = r_num; - x->u_num = ug->g->n_seq; - kv_init(x->k_trans); kv_init(x->k_trans.idx); - kv_init(x->k_t_b); - MALLOC(x->rUidx, r_num); - memset(x->rUidx, -1, x->r_num*sizeof(uint32_t)); - MALLOC(x->rUpos, r_num); - memset(x->rUpos, -1, x->r_num*sizeof(uint64_t)); - memset(&(x->b_buf_0), 0, sizeof(buf_t)); - memset(&(x->b_buf_1), 0, sizeof(buf_t)); - kv_init(x->topo_buf); - kv_init(x->topo_res); - ///MALLOC(x->uLen, x->u_num); - kv_init(x->c_buf); - - ma_utg_t *u = NULL; - asg_t* nsg = ug->g; - uint64_t n_vtx = nsg->n_seq, v, k, rId, is_dup = 0, vid, offset; - - - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - u = &(ug->u.a[v]); - if(u->m == 0) continue; - for (k = offset = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - - vid = v<<1; vid |= ((u->a[k]>>32) & 1); - if(x->rUidx[rId] != (uint32_t)-1 && x->rUidx[rId] != vid) is_dup = 1; - x->rUidx[rId] = vid; - - - vid = offset; vid <<=32; vid |= k; - if(x->rUpos[rId] != (uint64_t)-1 && x->rUpos[rId] != vid) is_dup = 1; - x->rUpos[rId] = vid; - - offset += (uint32_t)u->a[k]; - } - ///x->uLen[v] = u->len; - } - - if(is_dup) - { - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - u = &(ug->u.a[v]); - if(u->m == 0) continue; - for (k = offset = 0; k < u->n; k++) - { - rId = u->a[k]>>33; is_dup = 0; - - vid = v<<1; vid |= ((u->a[k]>>32) & 1); - if(x->rUidx[rId] != vid) is_dup = 1; - vid = offset; vid <<=32; vid |= k; - if(x->rUpos[rId] != vid) is_dup = 1; - - if(is_dup) - { - x->rUidx[rId] = (uint32_t)-1; - x->rUpos[rId] = (uint64_t)-1; - } - offset += (uint32_t)u->a[k]; - } - } - } - - - kv_malloc(x->bed, x->u_num); x->bed.n = x->u_num; - for (k = 0; k < x->bed.n; k++) kv_init(x->bed.a[k]); - x->st.chain_num = 0; - kv_init(x->st.uIDs); - kv_init(x->st.iDXs); - kv_push(uint32_t, x->st.iDXs, 0); - return x; -} - -void destory_trans_chain(trans_chain **x) -{ - if(x) - { - kv_destroy((*x)->k_trans); kv_destroy((*x)->k_trans.idx); - kv_destroy((*x)->k_t_b); - free((*x)->rUidx); - free((*x)->rUpos); - uint32_t k; - for (k = 0; k < (*x)->bed.n; k++) kv_destroy((*x)->bed.a[k]); - kv_destroy((*x)->bed); - free((*x)->b_buf_0.b.a); - free((*x)->b_buf_1.b.a); - kv_destroy((*x)->topo_buf); - kv_destroy((*x)->topo_res); - kv_destroy((*x)->c_buf); - kv_destroy((*x)->st.uIDs); - kv_destroy((*x)->st.iDXs); - ///free((*x)->uLen); - free((*x)); - } -} - -void init_hc_links(hc_links* link, uint64_t ug_num, trans_chain* t_ch) -{ - kv_malloc(link->a, ug_num); link->a.n = ug_num; - kv_malloc(link->enzymes, ug_num); link->enzymes.n = ug_num; - uint64_t i; - for (i = 0; i < link->a.n; i++) - { - kv_init(link->a.a[i].e); - kv_init(link->a.a[i].f); - } - - if(t_ch) - { - kv_u_trans_t *ta = &(t_ch->k_trans); - uint64_t d = RC_1; - for (i = 0; i < ta->n; i++) - { - if(ta->a[i].f == RC_2) continue; - push_hc_edge(&(link->a.a[ta->a[i].qn]), ta->a[i].tn, 1, 1, &d); - push_hc_edge(&(link->a.a[ta->a[i].tn]), ta->a[i].qn, 1, 1, &d); - } - } -} - -void destory_hc_links(hc_links* link) -{ - uint64_t i; - for (i = 0; i < link->a.n; i++) - { - kv_destroy(link->a.a[i].e); - kv_destroy(link->a.a[i].f); - } - kv_destroy(link->a); - kv_destroy(link->enzymes); -} - -void print_utg(ma_ug_t **ug, asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, R_to_U* ruIndex, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* new_rtg_edges) -{ - if(asm_opt.b_low_cov > 0) - { - break_ug_contig(ug, sg, &R_INF, coverage_cut, sources, ruIndex, new_rtg_edges, max_hang, min_ovlp, - &asm_opt.b_low_cov, NULL, asm_opt.m_rate); - } - - if(asm_opt.b_high_cov > 0) - { - break_ug_contig(ug, sg, &R_INF, coverage_cut, sources, ruIndex, new_rtg_edges, max_hang, min_ovlp, - NULL, &asm_opt.b_high_cov, asm_opt.m_rate); - } - - ma_ug_seq(*ug, sg, coverage_cut, sources, new_rtg_edges, max_hang, min_ovlp, 0, 1); - - - char* gfa_name = (char*)malloc(strlen(output_file_name)+35); - sprintf(gfa_name, "%s.p_ctg.gfa", output_file_name); - fprintf(stderr, "Writing %s to disk... \n", gfa_name); - FILE* output_file = fopen(gfa_name, "w"); - ma_ug_print(*ug, sg, coverage_cut, sources, ruIndex, "ptg", output_file); - fclose(output_file); - - sprintf(gfa_name, "%s.p_ctg.noseq.gfa", output_file_name); - output_file = fopen(gfa_name, "w"); - ma_ug_print_simple(*ug, sg, coverage_cut, sources, ruIndex, "ptg", output_file); - fclose(output_file); - if(asm_opt.bed_inconsist_rate != 0) - { - sprintf(gfa_name, "%s.p_ctg.lowQ.bed", output_file_name); - output_file = fopen(gfa_name, "w"); - ma_ug_print_bed(*ug, sg, &R_INF, coverage_cut, sources, new_rtg_edges, - max_hang, min_ovlp, asm_opt.bed_inconsist_rate, "ptg", output_file, NULL); - fclose(output_file); - } - free(gfa_name); - - /*******************************for debug************************************/ - // uint32_t i; - // for (i = 0; i < sg->n_seq; i++) - // { - // if(R_INF.trio_flag[i] == FATHER || R_INF.trio_flag[i] == MOTHER) fprintf(stderr, "ERROR\n"); - // } - /*******************************for debug************************************/ -} - -void write_trans_chain(trans_chain* t_ch, const char *fn) -{ - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.hic.trans.bin", fn); - FILE* fp = fopen(buf, "w"); - - fwrite(&t_ch->r_num, sizeof(t_ch->r_num), 1, fp); - fwrite(t_ch->ir_het, sizeof(uint8_t), t_ch->r_num, fp); - - uint32_t i; - fwrite(&t_ch->bed.n, sizeof(t_ch->bed.n), 1, fp); - for (i = 0; i < t_ch->bed.n; i++) - { - fwrite(&t_ch->bed.a[i].n, sizeof(t_ch->bed.a[i].n), 1, fp); - fwrite(t_ch->bed.a[i].a, sizeof(bed_interval), t_ch->bed.a[i].n, fp); - } - - fwrite(&t_ch->k_trans.n, sizeof(t_ch->k_trans.n), 1, fp); - fwrite(t_ch->k_trans.a, sizeof(u_trans_t), t_ch->k_trans.n, fp); - - fwrite(&t_ch->k_trans.idx.n, sizeof(t_ch->k_trans.idx.n), 1, fp); - fwrite(t_ch->k_trans.idx.a, sizeof(uint64_t), t_ch->k_trans.idx.n, fp); - - - fclose(fp); - free(buf); -} - - -trans_chain* load_hc_trans(const char *fn) -{ - uint64_t flag = 0; - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.hic.trans.bin", fn); - - FILE* fp = NULL; - fp = fopen(buf, "r"); - if(!fp) return NULL; - - trans_chain *t_ch = NULL; - CALLOC(t_ch, 1); - - flag += fread(&t_ch->r_num, sizeof(t_ch->r_num), 1, fp); - MALLOC(t_ch->ir_het, t_ch->r_num); - flag += fread(t_ch->ir_het, sizeof(uint8_t), t_ch->r_num, fp); - - uint32_t i; - flag += fread(&t_ch->bed.n, sizeof(t_ch->bed.n), 1, fp); - MALLOC(t_ch->bed.a, t_ch->bed.n); t_ch->bed.m = t_ch->bed.n; - for (i = 0; i < t_ch->bed.n; i++) - { - flag += fread(&t_ch->bed.a[i].n, sizeof(t_ch->bed.a[i].n), 1, fp); - MALLOC(t_ch->bed.a[i].a, t_ch->bed.a[i].n); t_ch->bed.a[i].m = t_ch->bed.a[i].n; - flag += fread(t_ch->bed.a[i].a, sizeof(bed_interval), t_ch->bed.a[i].n, fp); - } - - flag += fread(&t_ch->k_trans.n, sizeof(t_ch->k_trans.n), 1, fp); - MALLOC(t_ch->k_trans.a, t_ch->k_trans.n); t_ch->k_trans.m = t_ch->k_trans.n; - flag += fread(t_ch->k_trans.a, sizeof(u_trans_t), t_ch->k_trans.n, fp); - - flag += fread(&t_ch->k_trans.idx.n, sizeof(t_ch->k_trans.idx.n), 1, fp); - MALLOC(t_ch->k_trans.idx.a, t_ch->k_trans.idx.n); t_ch->k_trans.idx.m = t_ch->k_trans.idx.n; - flag += fread(t_ch->k_trans.idx.a, sizeof(uint64_t), t_ch->k_trans.idx.n, fp); - - - fclose(fp); - free(buf); - fprintf(stderr, "[M::%s::] ==> Hi-C cov have been loaded\n", __func__); - return t_ch; -} - -void hic_clean(asg_t* read_g) -{ - uint32_t n_vtx, v, u; - uint64_t i, k, k_i, tLen, v_occ, u_occ, utg_occ; - double bub_rate = 0.1; - ma_ug_t *ug = NULL; - ug = ma_ug_gen_primary(read_g, PRIMARY_LABLE); - n_vtx = ug->g->n_seq * 2; - buf_t b; memset(&b, 0, sizeof(buf_t)); b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - ///for (i = 0, tLen = 1; i < ug->u.n; i++) tLen += ug->u.a[i].len; - tLen = get_bub_pop_max_dist_advance(ug->g, &b); - uint8_t* bs_flag = (uint8_t*)calloc(n_vtx, 1); - kvec_t(uint32_t) ax; - kv_init(ax); - for (v = 0; v < ug->g->n_seq; ++v) - { - if(ug->g->seq[v].del) continue; - ug->g->seq[v].c = PRIMARY_LABLE; - EvaluateLen(ug->u, v) = ug->u.a[v].n; - } - - - for (v = 0; v < n_vtx; ++v) - { - if(ug->g->seq[v>>1].del) continue; - if(asg_arc_n(ug->g, v) < 2) continue; - if(bs_flag[v] != 0) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) - { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (i = 0; i < b.b.n; i++) - { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - bs_flag[b.b.a[i]] = bs_flag[b.b.a[i]^1] = 1; - } - bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 3; - } - } - - - for (v = 0; v < n_vtx; ++v) - { - if(bs_flag[v] !=2) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) - { - //note b.b include end, does not include beg - for (i = v_occ = ax.n = 0; i < b.b.n; i++) - { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - v_occ += ug->u.a[b.b.a[i]>>1].n; - kv_push(uint32_t, ax, b.b.a[i]>>1); - } - - for (i = 0; i < ax.n; i++) - { - for (k = 0; k < 2; k++) - { - u = (ax.a[i]<<1) + k; - if(asg_arc_n(ug->g, u) < 2) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, u, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) - { - for (k_i = u_occ = utg_occ = 0; k_i < b.b.n; k_i++) - { - if(b.b.a[k_i]==u || b.b.a[k_i]==b.S.a[0]) continue; - u_occ += ug->u.a[b.b.a[k_i]>>1].n; - utg_occ++; - } - - if(u_occ >= v_occ*bub_rate) continue; - if(u_occ > 3) continue; - if(utg_occ > 2) continue; - asg_bub_pop1_primary_trio(ug->g, NULL, u, tLen, &b, (uint32_t)-1, (uint32_t)-1, 1, NULL, NULL, NULL, 0, 0, NULL); - } - } - } - } - } - - ma_utg_t* m = NULL; - for (v = 0; v < ug->g->n_seq; ++v) - { - if(ug->g->seq[v].del) continue; - if(ug->g->seq[v].c != ALTER_LABLE) continue; - m = &(ug->u.a[v]); - if(m->m == 0) continue; - for (k = 0; k < m->n; k++) - { - asg_seq_del(read_g, m->a[k]>>33); - } - } - - asg_cleanup(read_g); - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); free(bs_flag); - ma_ug_destroy(ug); - kv_destroy(ax); -} - - -void hic_clean_adv(asg_t *sg, ug_opt_t *uopt) -{ - uint32_t i, k, m, z, v, w, mk; ma_utg_t *u = NULL; uint32_t *ba, bn, n_vtx, beg, end, n0, n1; ma_utg_t *mz = NULL; - ma_ug_t *ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); n_vtx = ug->g->n_seq<<1; double bub_rate = 0.1; - uint8_t *bf = NULL; bubble_type *bub = gen_bubble_chain(sg, ug, uopt, &bf, ((asm_opt.polyploidy>2)?1:0)); - uint64_t tLen, vocc, socc, pocc; buf_t b; memset(&b, 0, sizeof(buf_t)); CALLOC(b.a, n_vtx); - REALLOC(bf, n_vtx); memset(bf, 0, sizeof((*bf))*n_vtx); - kvec_t(uint64_t) buf; kv_init(buf); n0 = n1 = 0; - for (i = 0; i < ug->g->n_seq; ++i) { - if(ug->g->seq[i].del) continue; - ug->g->seq[i].c = PRIMARY_LABLE; - } - - for (i = 0; i < bub->b_ug->u.n; i++) { - u = &(bub->b_ug->u.a[i]); - if(u->n == 0) continue; - for (k = 0; k < u->n; k++) {///bubble chain - get_bubbles(bub, u->a[k]>>33, &beg, &end, &ba, &bn, NULL);///bubble - for (m = vocc = tLen = 0; m < bn; m++) { - bf[ba[m]] = bf[ba[m]^1] = 1; - tLen += ug->u.a[ba[m]>>1].len; - if(IF_HOM((ba[m]>>1), *bub)) continue; - if(ug->g->seq[ba[m]>>1].del) continue; - vocc += ug->u.a[ba[m]>>1].n; - } - if(beg != (uint32_t)-1) tLen += ug->u.a[beg>>1].len; - if(end != (uint32_t)-1) tLen += ug->u.a[end>>1].len; - - if(vocc) { - for (m = buf.n = 0; m < bn; m++) { - v = ba[m]; - if(ug->g->seq[v>>1].del) continue; - if(asg_arc_n(ug->g, v) < 2) continue; - if(get_real_length(ug->g, v, NULL) < 2) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (z = socc = 0; z < b.b.n; z++) { - if(b.b.a[z]==v || b.b.a[z]==b.S.a[0]) continue; - socc += ug->u.a[b.b.a[z]>>1].n; - if((!bf[b.b.a[z]])&&(!bf[b.b.a[z]^1])) break; - } - if(z < b.b.n) continue; - kv_push(uint64_t, buf, ((socc<<32)|v)); - } - - v ^= 1; - if(asg_arc_n(ug->g, v) < 2) continue; - if(get_real_length(ug->g, v, NULL) < 2) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (z = socc = 0; z < b.b.n; z++) { - if(b.b.a[z]==v || b.b.a[z]==b.S.a[0]) continue; - socc += ug->u.a[b.b.a[z]>>1].n; - if((!bf[b.b.a[z]])&&(!bf[b.b.a[z]^1])) break; - } - if(z < b.b.n) continue; - kv_push(uint64_t, buf, ((socc<<32)|v)); - } - } - - radix_sort_arch64(buf.a, buf.a + buf.n); - for (m = pocc = 0; m < buf.n; m++) { - v = (uint32_t)buf.a[m]; - if(ug->g->seq[v>>1].del) continue; - if(asg_arc_n(ug->g, v) < 2) continue; - if(get_real_length(ug->g, v, NULL) < 2) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (z = socc = 0; z < b.b.n; z++) { - if(b.b.a[z]==v || b.b.a[z]==b.S.a[0]) continue; - socc += ug->u.a[b.b.a[z]>>1].n; - if((!bf[b.b.a[z]])&&(!bf[b.b.a[z]^1])) break; - } - if(z < b.b.n) continue; - if((pocc+socc) >= (vocc*bub_rate)) continue; - pocc += socc; - asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 1, NULL, NULL, NULL, 0, 0, NULL); - for (z = 0; z < b.b.n; z++) { - if(b.b.a[z]==v || b.b.a[z]==b.S.a[0]) continue; - // socc += ug->u.a[b.b.a[i]>>1].n; - if(ug->g->seq[b.b.a[z]>>1].del) continue; - if(ug->g->seq[b.b.a[z]>>1].c != ALTER_LABLE) continue; - mz = &(ug->u.a[b.b.a[z]>>1]); - if(mz->m == 0) continue; - for (mk = 0; mk < mz->n; mk++) asg_seq_del(sg, mz->a[mk]>>33); - asg_seq_del(ug->g, b.b.a[z]>>1); - if(ug->u.a[b.b.a[z]>>1].m) { - ug->u.a[b.b.a[z]>>1].m = ug->u.a[b.b.a[z]>>1].n = 0; - free(ug->u.a[b.b.a[z]>>1].a); ug->u.a[b.b.a[z]>>1].a = NULL; - } - } - // fprintf(stderr, "+utg%.6dl\tutg%.6dl\n", (int32_t)(v>>1)+1, (int32_t)(b.S.a[0]>>1)+1); - n0++; - } - } - } - for (m = 0; m < bn; m++) { - bf[ba[m]] = bf[ba[m]^1] = 0; - } - } - } - - for (v = 0; v < ug->g->n_seq; ++v) { - if(ug->g->seq[v].del) continue; - if(ug->g->seq[v].c != ALTER_LABLE) continue; - mz = &(ug->u.a[v]); - if(mz->m == 0) continue; - for (k = 0; k < mz->n; k++) asg_seq_del(sg, mz->a[k]>>33); - asg_seq_del(ug->g, v); - if(ug->u.a[v].m) { - ug->u.a[v].m = ug->u.a[v].n = 0; - free(ug->u.a[v].a); ug->u.a[v].a = NULL; - } - } - asg_cleanup(ug->g); - - - - tLen = get_bub_pop_max_dist_advance(ug->g, &b); - for (v = buf.n = 0; v < n_vtx; ++v) { - if(ug->g->seq[v>>1].del) continue; - if(asg_arc_n(ug->g, v) < 2) continue; - if(get_real_length(ug->g, v, NULL) < 2) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (i = socc = 0; i < b.b.n; i++) { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - socc += ug->u.a[b.b.a[i]>>1].n; - } - if(socc <= 16) kv_push(uint64_t, buf, ((socc<<32)|v)); - } - } - - uint32_t convex; long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; - radix_sort_arch64(buf.a, buf.a + buf.n); - for (m = 0; m < buf.n; m++) { - v = (uint32_t)buf.a[m]; - if(ug->g->seq[v>>1].del) continue; - if(asg_arc_n(ug->g, v) < 2) continue; - if(get_real_length(ug->g, v, NULL) < 2) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { - w = b.S.a[0]^1; - for (i = socc = 0; i < b.b.n; i++) { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - socc += ug->u.a[b.b.a[i]>>1].n; - } - if(socc <= 16) { - b.b.n = 0; - get_unitig(ug->g, NULL, v^1, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, &b); - for (k = vocc = 0; k < b.b.n; k++) { - if(IF_HOM((b.b.a[k]>>1), *bub)) break; - vocc += ug->u.a[b.b.a[k]>>1].n; - } - if((socc) >= (vocc*bub_rate)) continue; - - b.b.n = 0; - get_unitig(ug->g, NULL, w^1, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, &b); - for (k = vocc = 0; k < b.b.n; k++) { - if(IF_HOM((b.b.a[k]>>1), *bub)) break; - vocc += ug->u.a[b.b.a[k]>>1].n; - } - if((socc) >= (vocc*bub_rate)) continue; - - asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 1, NULL, NULL, NULL, 0, 0, NULL); - for (i = 0; i < b.b.n; i++) { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - // socc += ug->u.a[b.b.a[i]>>1].n; - if(ug->g->seq[b.b.a[i]>>1].del) continue; - if(ug->g->seq[b.b.a[i]>>1].c != ALTER_LABLE) continue; - mz = &(ug->u.a[b.b.a[i]>>1]); - if(mz->m == 0) continue; - for (mk = 0; mk < mz->n; mk++) asg_seq_del(sg, mz->a[mk]>>33); - asg_seq_del(ug->g, b.b.a[i]>>1); - if(ug->u.a[b.b.a[i]>>1].m) { - ug->u.a[b.b.a[i]>>1].m = ug->u.a[b.b.a[i]>>1].n = 0; - free(ug->u.a[b.b.a[i]>>1].a); ug->u.a[b.b.a[i]>>1].a = NULL; - } - } - // fprintf(stderr, "-utg%.6dl\tutg%.6dl\n", (int32_t)(v>>1)+1, (int32_t)(b.S.a[0]>>1)+1); - n1++; - } - } - } - // filter_sg_by_ug(sg, ug, uopt); - for (v = 0; v < ug->g->n_seq; ++v) { - if(ug->g->seq[v].del) continue; - if(ug->g->seq[v].c != ALTER_LABLE) continue; - mz = &(ug->u.a[v]); - if(mz->m == 0) continue; - for (k = 0; k < mz->n; k++) asg_seq_del(sg, mz->a[k]>>33); - asg_seq_del(ug->g, v); - if(ug->u.a[v].m) { - ug->u.a[v].m = ug->u.a[v].n = 0; - free(ug->u.a[v].a); ug->u.a[v].a = NULL; - } - } - asg_cleanup(ug->g); - - asg_cleanup(sg); - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - ma_ug_destroy(ug); free(bf); kv_destroy(buf); - destory_bubbles(bub); free(bub); - // fprintf(stderr, "[M::%s::] # type0::%u, # type1::%u\n", __func__, n0, n1); -} - -void update_dump_trio(uint8_t* trio_flag, uint32_t rn, uint8_t *rf, ma_ug_t *ug) -{ - uint32_t k, i, x; - ma_utg_t *p = NULL; - if(ug) { - for (i = 0; i < ug->u.n; ++i) { // the Segment lines in GFA - p = &ug->u.a[i]; - if(p->m == 0) continue; - for (k = 0; k < p->n; k++) { - x = p->a[k]>>33; - if(trio_flag[x] == FATHER || trio_flag[x] == MOTHER) { - rf[x] = trio_flag[x]; - } else if(rf[x] != FATHER && rf[x] != MOTHER) { - rf[x] = DROP; - } - } - } - } else { - for (i = 0; i < rn; i++) { - if(rf[i]) { - rf[i] <<= 1; rf[i] += 1; - } else { - rf[i] = trio_flag[i]; rf[i] <<= 1; - } - - if(trio_flag[i] == FATHER || trio_flag[i] == MOTHER) { - trio_flag[i] = ((rf[i]&1)?MOTHER:FATHER); - } else { - trio_flag[i] = ((rf[i]&1)?DROP:AMBIGU); - } - } - } -} - -void update_poly_trio(uint32_t mm, uint32_t *hapS, uint32_t rn) -{ - uint32_t i; - for (i = 0; i < rn; i++) { - if(R_INF.trio_flag[i] == DROP) continue; - R_INF.trio_flag[i] = AMBIGU; - if(!hapS[i]) continue; - R_INF.trio_flag[i] = (hapS[i]&mm?FATHER:MOTHER); - } -} -void debug_hapS(uint32_t *hapS, uint32_t rn) -{ - uint32_t i, p, tot, nt, max_tot = 0, *occ = NULL, *freq = NULL; - for (i = 0; i < rn; i++) { - for (p = hapS[i], tot = 0; p; p>>=1, tot++); - max_tot = MAX(max_tot, tot); - } - fprintf(stderr, "[M::%s:] ==> %u haplotypes in total\n", __func__, max_tot); - if(max_tot){ - CALLOC(occ, max_tot+1); - CALLOC(freq, max_tot+1); - for (i = 0; i < rn; i++) { - for (p = hapS[i], tot = nt = 0; p; p>>=1, tot++){ - if(p&1) occ[tot+1]++, nt++; - } - freq[nt]++; - } - for (i = 1; i <= max_tot; i++) { - fprintf(stderr, "[M::%s:] ==> # reads in hap%u: %u\n", __func__, i, occ[i]); - } - for (i = 0; i <= max_tot; i++) { - fprintf(stderr, "[M::%s:] ==> # reads within %u haplotypes: %u\n", __func__, i, freq[i]); - } - free(occ); free(freq); - } -} -void output_poly_trio(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, ma_hit_t_alloc* sources, -ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, long long stops_threshold, -R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, int gap_fuzz, int is_bench, -bub_label_t* b_mask_t, uint32_t hapN) -{ - uint32_t i; - uint32_t *hapS = ha_polybin_list(&asm_opt); - // debug_hapS(hapS, sg->n_seq); - char *fp = NULL; MALLOC(fp, 100); - for (i = 0; i < hapN; i++){ - update_poly_trio(1<n_seq); - sprintf(fp, "hap%u", i+1); - output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, reverse_sources, tipsLen, tip_drop_ratio, - stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, gap_fuzz, is_bench, b_mask_t, fp, NULL, NULL); - } - free(fp); free(hapS); -} - -uint32_t test_dbug(ma_ug_t* ug, FILE* fp) -{ - uint32_t f_flag = 0, t, i, r_flag = 0; - size_t tt; - ma_utg_t ua, *ub = NULL; memset(&ua, 0, sizeof(ua)); - f_flag = fread(&tt, sizeof(tt), 1, fp); - if(f_flag == 0 || tt != ug->u.n) goto DES; - - for (i = 0; i < tt; i++) - { - ub = &(ug->u.a[i]); - f_flag = fread(&t, sizeof(t), 1, fp); - if(f_flag == 0 || t != ub->len) goto DES; - f_flag = fread(&t, sizeof(t), 1, fp); - if(f_flag == 0 || t != ub->circ) goto DES; - f_flag = fread(&(ua.start), sizeof(ua.start), 1, fp); - if(f_flag == 0 || ua.start != ub->start) goto DES; - f_flag = fread(&(ua.end), sizeof(ua.end), 1, fp); - if(f_flag == 0 || ua.end != ub->end) goto DES; - f_flag = fread(&(ua.n), sizeof(ua.n), 1, fp); - if(f_flag == 0 || ua.n != ub->n) goto DES; - t = ua.n; - ua.n = 0; - kv_resize(uint64_t, ua, t); - ua.n = t; - f_flag = fread(ua.a, sizeof(uint64_t), ua.n, fp); - if(f_flag == 0 || memcmp(ua.a, ub->a, ua.n)) goto DES; - } - r_flag = 1; - - DES: - free(ua.a); - return r_flag; -} - -void write_dbug(ma_ug_t* ug, FILE* fp) -{ - ma_utg_t *u = NULL; - uint32_t t, i; - fwrite(&(ug->u.n), sizeof(ug->u.n), 1, fp); - for (i = 0; i < ug->u.n; i++) - { - u = &(ug->u.a[i]); - t = u->len; - fwrite(&t, sizeof(t), 1, fp); - t = u->circ; - fwrite(&t, sizeof(t), 1, fp); - fwrite(&(u->start), sizeof(u->start), 1, fp); - fwrite(&(u->end), sizeof(u->end), 1, fp); - fwrite(&(u->n), sizeof(u->n), 1, fp); - fwrite(u->a, sizeof(uint64_t), u->n, fp); - } -} - -void filter_u_trans(kv_u_trans_t *ta, uint8_t keep_bub, uint8_t keep_topo, uint8_t keep_read, uint8_t keep_base) -{ - if(keep_bub && keep_topo && keep_read && keep_base) return; - uint32_t i, m; - for (i = m = 0; i < ta->n; i++) { - if((!keep_bub) && (ta->a[i].f == RC_0)) continue; - if((!keep_topo) && (ta->a[i].f == RC_1)) continue; - if((!keep_read) && (ta->a[i].f == RC_2)) continue; - if((!keep_base) && (ta->a[i].f == RC_3)) continue; - ta->a[m++] = ta->a[i]; - } - ta->n = m; -} - -uint32_t trans_ovlp_connect1(u_trans_t *p, ma_ug_t *ug) -{ - uint32_t v = p->qn<<1, w = (p->tn<<1) + ((uint32_t)p->rev), i, dg = (uint32_t)-1, da, dif, mm; - asg_arc_t *av = asg_arc_a(ug->g, v); uint32_t nv = asg_arc_n(ug->g, v); - for (i = 0; i < nv; i++) { - if(av[i].del || av[i].v != w) continue; - dg = av[i].ol; - break; - } - // if((v>>1) == 43 && (w>>1) == 45) { - // fprintf(stderr, "+[M::%s::] utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tf::%u\n", __func__, - // p->qn+1, "lc"[s->ug->u.a[p->qn].circ], s->ug->u.a[p->qn].len, p->qs, p->qe, - // "+-"[p->rev], p->tn+1, "lc"[s->ug->u.a[p->tn].circ], s->ug->u.a[p->tn].len, p->ts, p->te, p->f); - // } - - if(i < nv) { - // if(i >= nv) return 1; - da = (p->qe - p->qs); - dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; - if(dif <= mm) return 0; - - da = (p->te - p->ts); - dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; - if(dif <= mm) return 0; - } - - v ^= 1; w ^= 1; dg = (uint32_t)-1; - av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); - for (i = 0; i < nv; i++) { - if(av[i].del || av[i].v != w) continue; - dg = av[i].ol; - break; - } - if(i < nv) { - // if(i >= nv) return 1; - da = (p->qe - p->qs); - dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; - if(dif <= mm) return 0; - - da = (p->te - p->ts); - dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; - if(dif <= mm) return 0; - } - - return 1; -} - - -uint32_t ovlp_rocc(u_trans_t *p, ma_ug_t *ug, asg_t *rg, double cov_rate, uint32_t cov_cutoff) -{ - ma_utg_t *u = NULL; uint32_t s, e, rs, re, occ, k, l; - u = &(ug->u.a[p->qn]); s = p->qs; e = p->qe; - if((e-s) >= (u->len*cov_rate)) return 1; - for (k = l = occ = 0; k < u->n && occ < cov_cutoff; k++) { - rs = l; re = l + rg->seq[u->a[k]>>33].len; - if(rs >= e) break; - if(s <= rs && e >= re) occ++; - l += (uint32_t)u->a[k]; - } - if(occ >= cov_cutoff) return 1; - - u = &(ug->u.a[p->tn]); s = p->ts; e = p->te; - if((e-s) >= (u->len*cov_rate)) return 1; - for (k = l = occ = 0; k < u->n && occ < cov_cutoff; k++) { - rs = l; re = l + rg->seq[u->a[k]>>33].len; - if(rs >= e) break; - if(s <= rs && e >= re) occ++; - l += (uint32_t)u->a[k]; - } - if(occ >= cov_cutoff) return 1; - return 0; -} - -static void worker_for_trans_clean(void *data, long i, int tid) // callback for kt_for() -{ - u_trans_clean_t *s = (u_trans_clean_t*)data; - kv_u_trans_t *ta = s->ta; - kv_u_trans_t *res = &(s->res[tid]); - u_trans_t *a = NULL, *r_a = NULL, *mz, *cz; - uint32_t n, r_n, id = i, k, l, z; - - a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); - for (k = 1, l = 0; k <= n; k++) { - if(k == n || a[l].tn != a[k].tn) { - if(k > l) { - get_u_trans_spec(ta, a[l].tn, a[l].qn, &r_a, &r_n); - if(r_n > 0 && id > a[l].tn) { - l = k; continue; - } - mz = cz = NULL; - for (z = l; z < k; z++) { - cz = &(a[z]); - // fprintf(stderr, ">[M::%s::] qn::%u, tn::%u, cz->nw::%f, cz->f::%u\n", - // __func__, a[l].qn, a[l].tn, cz->nw, cz->f); - if(mz) { - if((mz->f == RC_0) && (cz->f != RC_0)) continue; - if((mz->f == RC_1) && ((cz->f == RC_2) || (cz->f == RC_3))) continue; - } - if((!mz) || ((cz->f < mz->f) && ((cz->f == RC_0) || (cz->f == RC_1))) || - (mz->nw < cz->nw) || ((mz->nw == cz->nw) && ((mz->qe - mz->qs) < (cz->qe - cz->qs)))) { - // fprintf(stderr, "+[M::%s::] qn::%u, tn::%u, mz->nw::%f, mz->f::%u, cz->nw::%f, cz->f::%u\n", - // __func__, a[l].qn, a[l].tn, mz?mz->nw:-1, mz?mz->f:255, cz->nw, cz->f); - mz = cz; - } - } - for (z = 0; z < r_n; z++) { - cz = &(r_a[z]); - if(mz) { - if((mz->f == RC_0) && (cz->f != RC_0)) continue; - if((mz->f == RC_1) && ((cz->f == RC_2) || (cz->f == RC_3))) continue; - } - if((!mz) || ((cz->f < mz->f) && ((cz->f == RC_0) || (cz->f == RC_1))) || - (mz->nw < cz->nw) || ((mz->nw == cz->nw) && ((mz->qe - mz->qs) < (cz->te - cz->ts)))) { - ///note here is (cz->te - cz->ts) - // fprintf(stderr, "-[M::%s::] qn::%u, tn::%u, mz->nw::%f, mz->f::%u, cz->nw::%f, cz->f::%u\n", - // __func__, a[l].qn, a[l].tn, mz?mz->nw:-1, mz?mz->f:255, cz->nw, cz->f); - mz = cz; - } - } - - // fprintf(stderr, "-[M::%s::] is_mz::%u, qn::%u, tn::%u\n", __func__, (uint32_t)(!!mz), mz->qn, mz->tn); - if((mz) && (mz->qn != mz->tn)) { - ///need to check it cover enough reads - kv_pushp(u_trans_t, *res, &cz); (*cz) = (*mz); - if(mz->qn != id) { - cz->qn = mz->tn; cz->qs = mz->ts; cz->qe = mz->te; - cz->tn = mz->qn; cz->ts = mz->qs; cz->te = mz->qe; - } - - if((cz->nw >= 0) && ((!trans_ovlp_connect1(cz, s->ug)) - || (!ovlp_rocc(cz, s->ug, s->rg, s->small_ov_rate, s->ov_cutoff)))) { - // if(mz->qn == 43 && mz->tn == 45) { - // fprintf(stderr, "-[M::%s::] utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, - // mz->qn+1, "lc"[s->ug->u.a[mz->qn].circ], s->ug->u.a[mz->qn].len, mz->qs, mz->qe, - // "+-"[mz->rev], - // mz->tn+1, "lc"[s->ug->u.a[mz->tn].circ], s->ug->u.a[mz->tn].len, mz->ts, mz->te); - // } - - res->n--; - } - // else { - // if(mz->qn == 43 && mz->tn == 45) { - // fprintf(stderr, "+[M::%s::] utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tf::%u\n", __func__, - // mz->qn+1, "lc"[s->ug->u.a[mz->qn].circ], s->ug->u.a[mz->qn].len, mz->qs, mz->qe, - // "+-"[mz->rev], mz->tn+1, "lc"[s->ug->u.a[mz->tn].circ], s->ug->u.a[mz->tn].len, mz->ts, mz->te, mz->f); - // } - // } - } - } - l = k; - } - } -} - -static void worker_for_trans_clean_re(void *data, long i, int tid) // callback for kt_for() -{ - u_trans_clean_t *s = (u_trans_clean_t*)data; - kv_u_trans_t *ta = s->ta; - kv_u_trans_t *res = &(s->res[tid]); - u_trans_t *a = NULL, *r_a = NULL, *mz, *cz, *sz; - uint32_t n, r_n, id = i, k, l, z; - uint32_t ovq, ovt, os, oe; - - a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); - for (k = 1, l = 0; k <= n; k++) { - if(k == n || a[l].tn != a[k].tn) { - if(k > l) { - get_u_trans_spec(ta, a[l].tn, a[l].qn, &r_a, &r_n); - if(r_n > 0 && id > a[l].tn) { - l = k; continue; - } - - mz = cz = sz = NULL; - for (z = l; z < k; z++) { - cz = &(a[z]); - if(cz->f == RC_3) { - if((!sz) || (sz->nw < cz->nw)) sz = cz; - } - if(mz) { - if((mz->f == RC_0) && (cz->f != RC_0)) continue; - if((mz->f == RC_1) && ((cz->f == RC_2) || (cz->f == RC_3))) continue; - } - if((!mz) || ((cz->f < mz->f) && ((cz->f == RC_0) || (cz->f == RC_1))) || - (mz->nw < cz->nw) || ((mz->nw == cz->nw) && ((mz->qe - mz->qs) < (cz->qe - cz->qs)))) { - mz = cz; - } - } - for (z = 0; z < r_n; z++) { - cz = &(r_a[z]); - if(cz->f == RC_3) { - if((!sz) || (sz->nw < cz->nw)) sz = cz; - } - if(mz) { - if((mz->f == RC_0) && (cz->f != RC_0)) continue; - if((mz->f == RC_1) && ((cz->f == RC_2) || (cz->f == RC_3))) continue; - } - if((!mz) || ((cz->f < mz->f) && ((cz->f == RC_0) || (cz->f == RC_1))) || - (mz->nw < cz->nw) || ((mz->nw == cz->nw) && ((mz->qe - mz->qs) < (cz->te - cz->ts)))) { - mz = cz; - } - } - - - - // fprintf(stderr, "-[M::%s::] is_mz::%u, qn::%u, tn::%u\n", __func__, (uint32_t)(!!mz), mz->qn, mz->tn); - if((mz) && (mz->qn != mz->tn)) { - ///need to check it cover enough reads - kv_pushp(u_trans_t, *res, &cz); (*cz) = (*mz); - if((sz) && (sz->rev == cz->rev)) { - if((cz->qn != sz->qn) || (cz->tn != sz->tn)) { - cz->qn = mz->tn; cz->qs = mz->ts; cz->qe = mz->te; - cz->tn = mz->qn; cz->ts = mz->qs; cz->te = mz->qe; - } - if((cz->qn == sz->qn) && (cz->tn == sz->tn)) { - os = MAX(cz->qs, sz->qs); oe = MIN(cz->qe, sz->qe); - ovq = ((oe > os)? (oe - os):0); - - os = MAX(cz->ts, sz->ts); oe = MIN(cz->te, sz->te); - ovt = ((oe > os)? (oe - os):0); - - if(((ovq) && (ovq > ((cz->qe-cz->qs)*0.8)) && (ovq > ((sz->qe-sz->qs)*0.8))) && - (((ovt) && (ovt > ((cz->te-cz->ts)*0.8)) && (ovt > ((sz->te-sz->ts)*0.8))))) {///sounds like base-level alignment coordinates are more reliable - (*cz) = (*sz); cz->f = mz->f; - } - } - } - if(cz->qn != id) { - z = cz->qn; cz->qn = cz->tn; cz->tn = z; - z = cz->qs; cz->qs = cz->ts; cz->ts = z; - z = cz->qe; cz->qe = cz->te; cz->te = z; - } - - // if(id == 394 || id == 1698 || id == 84) { - // fprintf(stderr, "+[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, - // cz->qn+1, "lc"[s->ug->u.a[cz->qn].circ], s->ug->u.a[cz->qn].len, cz->qs, cz->qe, "+-"[cz->rev], - // cz->tn+1, "lc"[s->ug->u.a[cz->tn].circ], s->ug->u.a[cz->tn].len, cz->ts, cz->te); - // } - - if((cz->nw >= 0) && ((!trans_ovlp_connect1(cz, s->ug)) - || (!ovlp_rocc(cz, s->ug, s->rg, s->small_ov_rate, s->ov_cutoff)))) { - // if(id == 394 || id == 1698 || id == 84) { - // fprintf(stderr, "-[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, - // cz->qn+1, "lc"[s->ug->u.a[cz->qn].circ], s->ug->u.a[cz->qn].len, cz->qs, cz->qe, "+-"[cz->rev], - // cz->tn+1, "lc"[s->ug->u.a[cz->tn].circ], s->ug->u.a[cz->tn].len, cz->ts, cz->te); - // } - res->n--; - } - } - } - l = k; - } - } -} - -int cmp_u_trans_weight(const void * a, const void * b) -{ - if((*(u_trans_t*)a).nw == (*(u_trans_t*)b).nw) return 0; - return ((*(u_trans_t*)a).nw) > ((*(u_trans_t*)b).nw)?-1:1; -} - -int64_t infer_utrans_ovlp_len(u_trans_t *li, u_trans_t *lj, ma_ug_t *ug) -{ - int64_t in, is, ie, irev, iqs, iqe, jn, js, je, jrev, jqs, jqe, ir, jr, ts, te, max_s, min_e, s_shift, e_shift; - - in = ug->u.a[li->tn].len; - is = li->ts; ie = li->te; irev = li->rev; iqs = li->qs; iqe = li->qe; - jn = ug->u.a[lj->tn].len; - js = lj->ts; je = lj->te; jrev = lj->rev; jqs = lj->qs; jqe = lj->qe; - - max_s = MAX(iqs, jqs); min_e = MIN(iqe, jqe); - if(min_e <= max_s) return 0; - s_shift = get_offset_adjust(max_s - iqs, iqe-iqs, ie-is); - e_shift = get_offset_adjust(iqe - min_e, iqe-iqs, ie-is); - if(irev) { - ts = s_shift; s_shift = e_shift; e_shift = ts; - } - is += s_shift; ie-= e_shift; - - s_shift = get_offset_adjust(max_s - jqs, jqe-jqs, je-js); - e_shift = get_offset_adjust(jqe - min_e, jqe-jqs, je-js); - if(jrev) { - ts = s_shift; s_shift = e_shift; e_shift = ts; - } - js += s_shift; je-= e_shift; - - if(irev) { - ts = in - ie; te = in - is; - is = ts; ie = te; - } - - if(jrev) { - ts = jn - je; te = jn - js; - js = ts; je = te; - } - - if(is <= js) { - js -= is; is = 0; - } else { - is -= js; js = 0; - } - - ir = in - ie; jr = jn - je; - - if(ir <= jr){ - ie = in; je += ir; - } - else { - je = jn; ie += jr; - } - - ir = ie - is; jr = je - js; - return MAX(ir, jr); -} - -///li is the suffix of lj -uint32_t is_connect_arc(u_trans_t *li, u_trans_t *lj, ma_ug_t *ug, double diff_ec_ul) -{ - if(li->qs >= lj->qs && li->qe >= lj->qe) { - int64_t dq = infer_utrans_ovlp_len(li, lj, ug); - uint32_t v = (li->tn<<1)|li->rev, w = (lj->tn<<1)|lj->rev; - int64_t dt = -1, dif, mm; uint32_t nv, i; asg_arc_t *av; - nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); - for (i = 0; i < nv; i++) { - if(av[i].del || av[i].v != w) continue; - dt = av[i].ol; - break; - } - - if(dt < 0) return 0; - dif = (dq>dt? dq-dt:dt-dq); - mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < 8) mm = 8; - if(dif <= mm) return 1; - } - return 0; -} - -uint32_t test_arc_rm(ma_ug_t *ug, u_trans_t *a, uint32_t a_n, uint32_t a_k, uint32_t len, asg64_v *srt, uint32_t len_cut, double rate_cut) -{ - uint32_t z, i, l, os, oe, ovq; - - srt->n = 0; kv_resize(uint64_t, *srt, a_n); - for (z = 0; z < a_n; z++) { - if(z == a_k) continue; - if(a[z].occ == ((uint32_t)-1)) continue; - srt->a[srt->n] = a[z].qs; - srt->a[srt->n] <<= 32; - srt->a[srt->n] |= a[z].qe; - srt->n++; - } - radix_sort_arch64(srt->a, srt->a+srt->n); - for (i = z = 0; i < srt->n; i++) { - os = (uint32_t)(srt->a[i]>>32); oe = (uint32_t)srt->a[i]; - if(z > 0 && os <= ((uint32_t)srt->a[z-1])) { - if(oe > ((uint32_t)srt->a[z-1])) { - srt->a[z-1] >>= 32; srt->a[z-1] <<= 32; srt->a[z-1] |= oe; - } - } else { - srt->a[z++] = srt->a[i]; - } - } - srt->n = z; l = (a[a_k].qe - a[a_k].qs); - for (z = 0; (z < srt->n) && (l > 0); z++) { - os = MAX(a[a_k].qs, ((uint32_t)(srt->a[z]>>32))); - oe = MIN(a[a_k].qe, ((uint32_t)srt->a[z])); - ovq = ((oe > os)? (oe - os):0); - assert(l >= ovq); l -= ovq; - } - // if((a[a_k].qn == 3924 && a[a_k].tn == 160) || (a[a_k].tn == 3924 && a[a_k].qn == 160)) { - // fprintf(stderr, "[M::%s::]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\tdel::%u\tlen::%u\tlen_cut::%u\trate_cut::%f\tl::%u\n", __func__, - // a[a_k].qn+1, "lc"[ug->u.a[a[a_k].qn].circ], ug->u.a[a[a_k].qn].len, a[a_k].qs, a[a_k].qe, "+-"[a[a_k].rev], - // a[a_k].tn+1, "lc"[ug->u.a[a[a_k].tn].circ], ug->u.a[a[a_k].tn].len, a[a_k].ts, a[a_k].te, a[a_k].nw, a[a_k].f, - // (a[a_k].occ == ((uint32_t)-1))?1:0, len, len_cut, rate_cut, l); - // } - if((l > len_cut) && (l > (len*rate_cut))) return 0;///cannot be dropped - return 1; -} - -void deep_clean_u_trans(kv_u_trans_t *ta, u_trans_t *mz, ma_ug_t *ug, asg64_v *srt, uint32_t len_cut, double rate_cut) -{ - if(mz->qn > mz->tn) return; - u_trans_t *r_a, *cz, *a; uint32_t r_k, r_n, n, k; - r_a = u_trans_a(*ta, mz->tn); r_n = u_trans_n(*ta, mz->tn); - for (r_k = 0; (r_k < r_n) && (r_a[r_k].tn != mz->qn); r_k++); - assert(r_k < r_n); cz = &(r_a[r_k]); - // if((mz->qn == 3924 && mz->tn == 160) || (mz->tn == 3924 && mz->qn == 160)) { - // fprintf(stderr, "[M::%s::]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\tdel::%u\n", __func__, - // mz->qn+1, "lc"[ug->u.a[mz->qn].circ], ug->u.a[mz->qn].len, mz->qs, mz->qe, "+-"[mz->rev], - // mz->tn+1, "lc"[ug->u.a[mz->tn].circ], ug->u.a[mz->tn].len, mz->ts, mz->te, mz->nw, mz->f, - // (mz->occ == ((uint32_t)-1))?1:0); - // fprintf(stderr, "[M::%s::]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\tdel::%u\n", __func__, - // cz->qn+1, "lc"[ug->u.a[cz->qn].circ], ug->u.a[cz->qn].len, cz->qs, cz->qe, "+-"[cz->rev], - // cz->tn+1, "lc"[ug->u.a[cz->tn].circ], ug->u.a[cz->tn].len, cz->ts, cz->te, cz->nw, cz->f, - // (cz->occ == ((uint32_t)-1))?1:0); - // } - if((mz->occ == ((uint32_t)-1)) && (cz->occ == ((uint32_t)-1))) return; - if((mz->occ != ((uint32_t)-1)) && (cz->occ != ((uint32_t)-1))) return; - - if(!test_arc_rm(ug, r_a, r_n, r_k, ug->u.a[mz->tn].len, srt, len_cut, rate_cut)) { - mz->occ = cz->occ = 0; return; - } else { - a = u_trans_a(*ta, mz->qn); n = u_trans_n(*ta, mz->qn); - for (k = 0; (k < n) && (a[k].tn != mz->tn); k++); assert(k < n); - if(!test_arc_rm(ug, a, n, k, ug->u.a[mz->qn].len, srt, len_cut, rate_cut)) { - mz->occ = cz->occ = 0; return; - } - } - mz->occ = cz->occ = ((uint32_t)-1); -} - -static void worker_for_trans_sec_cut(void *data, long i, int tid) // callback for kt_for() -{ - u_trans_clean_t *s = (u_trans_clean_t*)data; - kv_u_trans_t *ta = s->ta; - asg64_v *srt = &(s->srt[tid]); - u_trans_t *a = NULL, *mz, *cz, t; - uint32_t n, r_n, id = i, k, l, z, m, wm, wl, len; - uint32_t ovq, os, oe; uint64_t *ss, *hs, *bu, *wu; - - if(!(s->cu)) { - a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); - for (k = r_n = 0; k < n; k++) {///RC_0/RC_1 to a[0, r_n) - if((a[k].f == RC_0) || (a[k].f == RC_1)) { - if(k != r_n) { - t = a[k]; a[k] = a[r_n]; a[r_n] = t; - } - r_n++; - } - } - if(r_n >= n) return; - if(n-r_n > 1) qsort(a+r_n, n-r_n, sizeof((*a)), cmp_u_trans_weight); - // if(id == 3924 || id == 160) { - // fprintf(stderr, "[M::%s::]\tutg%.6u%c\tr_n::%u\tn::%u\n", __func__, - // id + 1, "lc"[s->ug->u.a[id].circ], r_n, n); - // for (k = 0; k < n; k++) { - // fprintf(stderr, "+[%u]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\n", k, - // a[k].qn+1, "lc"[s->ug->u.a[a[k].qn].circ], s->ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], - // a[k].tn+1, "lc"[s->ug->u.a[a[k].tn].circ], s->ug->u.a[a[k].tn].len, a[k].ts, a[k].te, a[k].nw, a[k].f); - // } - // } - srt->n = 0; kv_resize(uint64_t, *srt, (n<<2)); - for (k = 0; k < n; k++) { - srt->a[srt->n] = a[k].qs; - srt->a[srt->n] <<= 32; - srt->a[srt->n] |= k; - srt->n++; - } - ss = srt->a; hs = ss + srt->n; bu = hs + srt->n; wu = bu + srt->n; - radix_sort_arch64(ss, ss+n); - for (k = 0; k < n; k++) { - ss[k] = (uint32_t)ss[k]; hs[ss[k]] = k; - } - for (k = r_n; k < n; k++) { - cz = &(a[k]); len = (cz->qe-cz->qs)*s->sec_rate; m = wm = 0; - for (z = l = wl = 0; z < n; z++) { - if(z == hs[k]) { - assert(ss[z] == k); - continue; - } - if(ss[z] > k) continue;///smaller nw than a[k] - mz = &(a[ss[z]]); - if(mz->qs >= cz->qe) break; - if(mz->occ == ((uint32_t)-1)) continue;///has been deleted - if((mz->f != RC_0) && (mz->f != RC_1) && (cz->nw > (mz->nw*s->sc_sec_rate/**0.95**/))) continue; - os = MAX(cz->qs, mz->qs); oe = MIN(cz->qe, mz->qe); - ovq = ((oe > os)? (oe - os):0); - if(!ovq) continue; - if(is_connect_arc(cz, mz, s->ug, 0.04) || is_connect_arc(mz, cz, s->ug, 0.04)) continue; - - if((m > 0) && (((uint32_t)bu[m-1]) >= os)) { - if(oe > ((uint32_t)bu[m-1])) { - l += (oe - ((uint32_t)bu[m-1])); - bu[m-1] += (oe - ((uint32_t)bu[m-1])); - } - } else { - l += oe - os; - bu[m] = os; bu[m] <<= 32; bu[m] |= oe; m++; - } - - if((wm > 0) && (((uint32_t)wu[wm-1]) >= mz->qs)) { - if(mz->qe > ((uint32_t)wu[wm-1])) { - wl += (mz->qe - ((uint32_t)wu[wm-1])); - wu[wm-1] += (mz->qe - ((uint32_t)wu[wm-1])); - } - } else { - wl += mz->qe - mz->qs; - wu[wm] = mz->qs; wu[wm] <<= 32; wu[wm] |= mz->qe; wm++; - } - - if((l > 0) && ((l>=len) || (l>=(wl*s->sec_rate)))) { - // if((cz->qn == 3924 && cz->tn == 160) || (cz->tn == 3924 && cz->qn == 160)) { - // fprintf(stderr, "[M::%s]\tutg%.6u%c\t->\tutg%.6u%c\tl::%u\tlen::%u\twl::%u\tsec_rate::%f\n", __func__, - // cz->qn+1, "lc"[s->ug->u.a[cz->qn].circ], - // cz->tn+1, "lc"[s->ug->u.a[cz->tn].circ], - // l, len, wl, s->sec_rate); - // } - cz->occ = ((uint32_t)-1); - break; - } - } - } - // if(id == 3924 || id == 160) { - // for (k = 0; k < n; k++) { - // fprintf(stderr, "-[%u]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\tdel::%u\n", k, - // a[k].qn+1, "lc"[s->ug->u.a[a[k].qn].circ], s->ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], - // a[k].tn+1, "lc"[s->ug->u.a[a[k].tn].circ], s->ug->u.a[a[k].tn].len, a[k].ts, a[k].te, a[k].nw, a[k].f, - // (a[k].occ == ((uint32_t)-1))?1:0); - // } - // } - } else { - assert(((uint32_t)(s->cu->idx.a[id])) > (s->cu->idx.a[id]>>32)+1); - for (z = (s->cu->idx.a[id]>>32); z < ((uint32_t)(s->cu->idx.a[id])); z++) { - a = u_trans_a(*ta, ((uint32_t)s->cu->z.a[z])); - n = u_trans_n(*ta, ((uint32_t)s->cu->z.a[z])); - for (k = 0; k < n; k++) deep_clean_u_trans(ta, &(a[k]), s->ug, srt, 3000000, 0.5); - } - } -} - - -uint64_t trans_sec_cut0(kv_u_trans_t *ta, asg64_v *srt, uint32_t id, double sec_rate, uint64_t bd, ma_ug_t *ug) -{ - u_trans_t *a = NULL, *mz, *cz, t, *ca; - uint32_t a_n, r_n, c_n, k, l, z, i, m, wm, wl, len, b_n = srt->n; - uint32_t ovq, os, oe; uint64_t *ss, *hs, *bu, *wu, occ = 0; - - a = u_trans_a(*ta, id); a_n = u_trans_n(*ta, id); - for (k = r_n = 0; k < a_n; k++) {///RC_0/RC_1 to a[0, r_n) - if(a[k].del) continue; - if(k != r_n) { - t = a[k]; a[k] = a[r_n]; a[r_n] = t; - } - r_n++; - } - if(r_n <= 1) return occ; - qsort(a, r_n, sizeof((*a)), cmp_u_trans_weight); - - kv_resize(uint64_t, *srt, (b_n+(r_n<<2))); - for (k = 0; k < r_n; k++) { - srt->a[srt->n] = a[k].qs; - srt->a[srt->n] <<= 32; - srt->a[srt->n] |= k; - srt->n++; - } - - ss = srt->a + b_n; hs = ss + r_n; bu = hs + r_n; wu = bu + r_n; - radix_sort_arch64(ss, ss + r_n); - for (k = 0; k < r_n; k++) { - ss[k] = (uint32_t)ss[k]; hs[ss[k]] = k; - } - - for (k = 0; k < r_n; k++) { - cz = &(a[k]); len = (cz->qe-cz->qs)*sec_rate; m = wm = 0; - for (z = l = wl = 0; z < r_n; z++) { - if(z == hs[k]) { - assert(ss[z] == k); - continue; - } - if(ss[z] > k) continue;///smaller nw than a[k] - mz = &(a[ss[z]]); - if(mz->qs >= cz->qe) break; - if(mz->del) continue;///has been deleted - // if((mz->f != RC_0) && (mz->f != RC_1) && (cz->nw > (mz->nw*0.95))) continue; - os = MAX(cz->qs, mz->qs); oe = MIN(cz->qe, mz->qe); - ovq = ((oe > os)? (oe - os):0); - if(!ovq) continue; - if(is_connect_arc(cz, mz, ug, 0.04) || is_connect_arc(mz, cz, ug, 0.04)) continue; - - if((m > 0) && (((uint32_t)bu[m-1]) >= os)) { - if(oe > ((uint32_t)bu[m-1])) { - l += (oe - ((uint32_t)bu[m-1])); - bu[m-1] += (oe - ((uint32_t)bu[m-1])); - } - } else { - l += oe - os; - bu[m] = os; bu[m] <<= 32; bu[m] |= oe; m++; - } - - if((wm > 0) && (((uint32_t)wu[wm-1]) >= mz->qs)) { - if(mz->qe > ((uint32_t)wu[wm-1])) { - wl += (mz->qe - ((uint32_t)wu[wm-1])); - wu[wm-1] += (mz->qe - ((uint32_t)wu[wm-1])); - } - } else { - wl += mz->qe - mz->qs; - wu[wm] = mz->qs; wu[wm] <<= 32; wu[wm] |= mz->qe; wm++; - } - - if((l >= bd) && ((l>=len) || (l>=(wl*sec_rate)))) { - cz->del = 1; occ++; - ca = u_trans_a(*ta, cz->tn); c_n = u_trans_n(*ta, cz->tn); - for (i = 0; i < c_n; i++) { - if(ca[i].tn == cz->qn) ca[i].del = 1; - } - break; - } - } - } - - srt->n = b_n; - return occ; -} - -void dbg_prt_utg_trans(kv_u_trans_t *ta, ma_ug_t *ug, const char *o_n) -{ - char* gfa_name = (char*)malloc(strlen(o_n)+100); - FILE *fn = NULL; sprintf(gfa_name, "%s.tran.dbg.ovlp.log", o_n); - u_trans_t *p = NULL; uint32_t i; fn = fopen(gfa_name, "w"); - for (i = 0; i < ta->n; i++) { - p = &(ta->a[i]); - fprintf(fn, "utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tw(%f)\tf(%u)\n", - p->qn+1, "lc"[ug->u.a[p->qn].circ], ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], - p->tn+1, "lc"[ug->u.a[p->tn].circ], ug->u.a[p->tn].len, p->ts, p->te, p->nw, p->f); - } - fclose(fn); free(gfa_name); fprintf(stderr, "[M::%s::] done\n", __func__); -} - -void clean_u_trans_t_idx_adv(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g) -{ - u_trans_clean_t sl; uint64_t k, i, l, occ; ha_mzl_t *tz; - ha_mzl_v srt_a; kv_u_trans_t *bl; u_trans_t *z; - memset(&sl, 0, sizeof(sl)); kv_init(srt_a); - - kt_u_trans_t_idx(ta, ug->g->n_seq); - sl.n_thread = asm_opt.thread_num; sl.ug = ug; sl.rg = read_g; sl.ta = ta; - CALLOC(sl.res, sl.n_thread); - sl.ov_cutoff = 3; sl.small_ov_rate = 0.8; - // dbg_prt_utg_trans(ta, ug, "pre"); - kt_for(sl.n_thread, worker_for_trans_clean, &sl, sl.ta->idx.n); - - for (i = srt_a.n = occ = 0; i < sl.n_thread; i++) { - bl = &(sl.res[i]); - if(!(bl->n)) continue; - for (k = 1, l = 0; k <= bl->n; k++) { - if(k == bl->n || bl->a[k].qn != bl->a[l].qn) { - if(k > l) { - kv_pushp(ha_mzl_t, srt_a, &tz); - tz->x = bl->a[l].qn; tz->x <<= 32; tz->x |= i; - tz->rid = l>>32; tz->pos = (uint32_t)l; - occ += (k - l); - } - l = k; - } - } - } - // fprintf(stderr, "[M::%s::] occ::%lu \n", __func__, occ); - assert(srt_a.n <= sl.ug->u.n); - radix_sort_ha_mzl_t_srt1(srt_a.a, srt_a.a + srt_a.n); - occ <<= 1; ta->n = 0; kv_resize(u_trans_t, *ta, occ); - for (i = 0; i < srt_a.n; i++) { - tz = &(srt_a.a[i]); - bl = &(sl.res[(uint32_t)(tz->x)]); - k = tz->rid; k <<= 32; k += tz->pos; - assert(bl->a[k].qn == (tz->x>>32)); - for (; (k < bl->n) && (bl->a[k].qn == (tz->x>>32)); k++) { - if(bl->a[k].qn == bl->a[k].tn) continue; - kv_pushp(u_trans_t, *ta, &z); - (*z) = bl->a[k]; if(z->f == RC_3) z->f = RC_2; - - kv_pushp(u_trans_t, *ta, &z); - (*z) = bl->a[k]; if(z->f == RC_3) z->f = RC_2; - z->qn = bl->a[k].tn; z->qs = bl->a[k].ts; z->qe = bl->a[k].te; - z->tn = bl->a[k].qn; z->ts = bl->a[k].qs; z->te = bl->a[k].qe; - } - } - - for (k = 0; k < sl.n_thread; k++) free(sl.res[k].a); - free(sl.res); kv_destroy(srt_a); - kt_u_trans_t_idx(ta, ug->g->n_seq); - // dbg_prt_utg_trans(ta, ug, "after"); -} - - -void dbg_prt_utg_extra_trans(kv_u_trans_t *ta, ma_ug_t *ug, const char *o_n) -{ - char* gfa_name = (char*)malloc(strlen(o_n)+100); - FILE *fn = NULL; sprintf(gfa_name, "%s.tran.dbg.ovlp.log", o_n); - u_trans_t *p = NULL; uint32_t i; fn = fopen(gfa_name, "w"); - double nw[2], ml, uml, sec, fw; - for (i = 0; i < ta->n; i++) { - p = &(ta->a[i]); - if((p->f == RC_0) || (p->f == RC_1)) continue; - - sec = ((p->qe-p->qs)*asm_opt.trans_base_rate); - if(sec < ((p->te-p->ts)*asm_opt.trans_base_rate)) { - sec = ((p->te-p->ts)*asm_opt.trans_base_rate); - } - ml = p->qe - p->qs; uml = sec; ml -= uml; - nw[0] = (ml*CHAIN_MATCH) - (uml*CHAIN_UNMATCH); - ml = p->te - p->ts; uml = sec; ml -= uml; - nw[1] = (ml*CHAIN_MATCH) - (uml*CHAIN_UNMATCH); - fw = MIN(nw[0], nw[1]); - if(fw <= p->nw) continue; - - fprintf(fn, "utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tw(%f)\tf(%u)\n", - p->qn+1, "lc"[ug->u.a[p->qn].circ], ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], - p->tn+1, "lc"[ug->u.a[p->tn].circ], ug->u.a[p->tn].len, p->ts, p->te, p->nw, p->f); - } - fclose(fn); free(gfa_name); fprintf(stderr, "[M::%s::] done\n", __func__); -} - -u_trans_cluster* gen_u_trans_cluster(kv_u_trans_t *ta) -{ - u_trans_cluster *p; CALLOC(p, 1); - p->z.n = p->z.m = ta->idx.n; MALLOC(p->z.a, p->z.n); - memset(p->z.a, -1, sizeof(*(p->z.a))*p->z.n); - u_trans_t *a = NULL; uint64_t n, v, k, l, i, cn, m; asg64_v b; kv_init(b); - for (i = b.n = cn = 0; i < ta->idx.n; i++) { - v = i; - if(p->z.a[v] != ((uint64_t)-1)) continue; - kv_push(uint64_t, b, v); m = 0; - while(b.n) { - v = b.a[--b.n]; - if(p->z.a[v] != ((uint64_t)-1)) continue; - p->z.a[v] = i; p->z.a[v] <<= 32; p->z.a[v] |= v; m++; - a = u_trans_a(*ta, v); n = u_trans_n(*ta, v); - for (k = 0; k < n; k++) { - if(p->z.a[a[k].tn] != ((uint64_t)-1)) continue; - kv_push(uint64_t, b, a[k].tn); - } - } - if(m > 1) cn++; - } - radix_sort_arch64(p->z.a, p->z.a + p->z.n); - p->idx.n = 0; p->idx.m = cn; CALLOC(p->idx.a, p->idx.m); - for (l = 0, k = 1; k <= p->z.n; k++) { - if(k == p->z.n || (p->z.a[k]>>32) != (p->z.a[l]>>32)) { - if(k - l > 1) p->idx.a[p->idx.n++] = (l<<32)|(k); - l = k; - } - } - assert(p->idx.n == cn); - free(b.a); - return p; -} - -void clean_u_trans_t_idx_filter_adv(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, double sc_sec_rate, uint64_t uniform_only) -{ - u_trans_clean_t sl; uint64_t k, i, l, st, occ; ha_mzl_t *tz; - ha_mzl_v srt_a; kv_u_trans_t *bl; u_trans_t *z; - memset(&sl, 0, sizeof(sl)); kv_init(srt_a); - - kt_u_trans_t_idx(ta, ug->g->n_seq); - sl.n_thread = asm_opt.thread_num; sl.ug = ug; sl.rg = read_g; sl.ta = ta; - CALLOC(sl.res, sl.n_thread); - sl.ov_cutoff = 3; sl.small_ov_rate = 0.8; sl.sc_sec_rate = sc_sec_rate; - // dbg_prt_utg_trans(ta, ug, "pre"); - kt_for(sl.n_thread, worker_for_trans_clean_re, &sl, sl.ta->idx.n); - - for (i = srt_a.n = occ = 0; i < sl.n_thread; i++) { - bl = &(sl.res[i]); - if(!(bl->n)) continue; - for (k = 1, l = 0; k <= bl->n; k++) { - if(k == bl->n || bl->a[k].qn != bl->a[l].qn) { - if(k > l) { - kv_pushp(ha_mzl_t, srt_a, &tz); - tz->x = bl->a[l].qn; tz->x <<= 32; tz->x |= i; - tz->rid = l>>32; tz->pos = (uint32_t)l; - occ += (k - l); - } - l = k; - } - } - } - // fprintf(stderr, "[M::%s::] occ::%lu \n", __func__, occ); - assert(srt_a.n <= sl.ug->u.n); - radix_sort_ha_mzl_t_srt1(srt_a.a, srt_a.a + srt_a.n); - occ <<= 1; ta->n = 0; kv_resize(u_trans_t, *ta, occ); - for (i = 0; i < srt_a.n; i++) { - tz = &(srt_a.a[i]); - bl = &(sl.res[(uint32_t)(tz->x)]); - k = tz->rid; k <<= 32; k += tz->pos; - assert(bl->a[k].qn == (tz->x>>32)); - for (; (k < bl->n) && (bl->a[k].qn == (tz->x>>32)); k++) { - if(bl->a[k].qn == bl->a[k].tn) continue; - kv_pushp(u_trans_t, *ta, &z); - (*z) = bl->a[k]; z->occ = 0; if(z->f == RC_3) z->f = RC_2; - - kv_pushp(u_trans_t, *ta, &z); - (*z) = bl->a[k]; z->occ = 0; if(z->f == RC_3) z->f = RC_2; - z->qn = bl->a[k].tn; z->qs = bl->a[k].ts; z->qe = bl->a[k].te; - z->tn = bl->a[k].qn; z->ts = bl->a[k].qs; z->te = bl->a[k].qe; - } - } - - for (k = 0; k < sl.n_thread; k++) free(sl.res[k].a); - free(sl.res); kv_destroy(srt_a); - kt_u_trans_t_idx(ta, ug->g->n_seq); - // dbg_prt_utg_trans(ta, ug, "after"); - if(uniform_only) return; - - - - CALLOC(sl.srt, sl.n_thread); sl.sec_rate = 0.5; sl.sc_sec_rate = sc_sec_rate; - kt_for(sl.n_thread, worker_for_trans_sec_cut, &sl, sl.ta->idx.n); - sl.cu = gen_u_trans_cluster(ta); - kt_for(sl.n_thread, worker_for_trans_sec_cut, &sl, sl.cu->idx.n); - free(sl.cu->idx.a); free(sl.cu->z.a); free(sl.cu); - for (k = 0; k < sl.n_thread; k++) free(sl.srt[k].a); free(sl.srt); - - for (k = st = 0; k < ta->n; k++) { - if(ta->a[k].occ == ((uint32_t)-1)) continue; - ta->a[st++] = ta->a[k]; - } - ta->n = st; - for (st = 0, i = 1; i <= ta->n; ++i) { - if (i == ta->n || ta->a[i].qn != ta->a[st].qn) { - ta->idx.a[ta->a[st].qn] = (((uint64_t)st)<<32)|(i-st); - st = i; - } - } - // dbg_prt_utg_extra_trans(ta, ug, asm_opt.output_file_name); -} - -void refine_hic_trans(ug_opt_t *opt, kv_u_trans_t *ta, asg_t *sg, ma_ug_t *ug) -{ - filter_u_trans(ta, asm_opt.is_bub_trans, asm_opt.is_topo_trans, asm_opt.is_read_trans, asm_opt.is_base_trans); - if(asm_opt.is_base_trans) { - trans_base_infer(ug, sg, opt, ta, NULL); - } - // dbg_prt_utg_trans(ta, ug, "pre"); - clean_u_trans_t_idx_filter_adv(ta, ug, sg, 0.95, 0); - // dbg_prt_utg_trans(ta, ug, "after"); -} - -void set_rset(ma_ug_t *ug, uint32_t uid, uint8_t *ff, uint8_t s) -{ - if(ug->g->seq[uid].del) return; - ma_utg_t* u; uint32_t k, v, nv, w, z; - asg_arc_t *av = NULL; - - u = &(ug->u.a[uid]); - for (k = 0; k < u->n; k++) ff[u->a[k]>>33] = s; - - v = uid<<1; - nv = asg_arc_n(ug->g, v); - av = asg_arc_a(ug->g, v); - for (k = 0; k < nv; k++) { - w = av[k].v; - if(av[k].del) continue; - if(ug->g->seq[w>>1].del) continue; - u = &(ug->u.a[w>>1]); - for (z = 0; z < u->n; z++) ff[u->a[z]>>33] = s; - } - - v = (uid<<1)+1; - nv = asg_arc_n(ug->g, v); - av = asg_arc_a(ug->g, v); - for (k = 0; k < nv; k++) { - w = av[k].v; - if(av[k].del) continue; - if(ug->g->seq[w>>1].del) continue; - u = &(ug->u.a[w>>1]); - for (z = 0; z < u->n; z++) ff[u->a[z]>>33] = s; - } -} - -uint32_t check_nc_status(asg_t *sg, ma_hit_t_alloc *src, uint8_t *ff, uint32_t id) -{ - uint32_t i, tn; ma_hit_t *h; - for (i = 0; i < src[id].length; i++) { - h = &(src[id].buffer[i]); tn = Get_tn((*h)); - if(sg->seq[tn].del) continue; - if(!ff[tn]) continue; - if((Get_qs((*h)) == 0) && (Get_qe((*h)) == sg->seq[id].len)) return 1; - } - return 0; -} - -uint64_t *gen_cov_rg(ma_ug_t *ug, asg_t *sg, ma_hit_t_alloc *src) -{ - uint32_t i, k, rid, j, tn; uint8_t *ff; - uint64_t C_bases, *cc; ma_hit_t *h; ma_utg_t *u; - CALLOC(cc, sg->n_seq); CALLOC(ff, sg->n_seq); - - for (i = 0; i < ug->g->n_seq; i++) { - if(ug->g->seq[i].del) continue; - set_rset(ug, i, ff, 1); - - u = &(ug->u.a[i]); - for (k = 0; k < u->n; k++) { - C_bases = 0; rid = u->a[k]>>33; - for (j = 0; j < src[rid].length; j++) { - h = &(src[rid].buffer[j]); - tn = Get_tn((*h)); - if((!sg->seq[tn].del) && (!ff[tn])) continue; - if((sg->seq[tn].del) && (!check_nc_status(sg, src, ff, tn))) continue; - C_bases += (Get_qe((*h)) - Get_qs((*h))); - } - if(C_bases > cc[rid]) cc[rid] = C_bases; - } - - set_rset(ug, i, ff, 0); - } - free(ff); - - return cc; -} - -void fill_cov_arr(ma_ug_t *ug, asg_t *sg, ma_hit_t_alloc *src, uint8_t *ff, uint64_t uid, uint64_t *res) -{ - ma_hit_t *h; ma_utg_t *u; - uint64_t C_bases, k, j, rid, tn; - set_rset(ug, uid, ff, 1); - - u = &(ug->u.a[uid]); - for (k = 0; k < u->n; k++) { - C_bases = 0; rid = u->a[k]>>33; - for (j = 0; j < src[rid].length; j++) { - h = &(src[rid].buffer[j]); - tn = Get_tn((*h)); - if((!sg->seq[tn].del) && (!ff[tn])) continue; - if((sg->seq[tn].del) && (!check_nc_status(sg, src, ff, tn))) continue; - C_bases += (Get_qe((*h)) - Get_qs((*h))); - } - res[k] = C_bases; - } - - set_rset(ug, uid, ff, 0); -} - -uint64_t infer_mmhap_copy(ma_ug_t *ug, asg_t *sg, ma_hit_t_alloc *src, uint8_t *ff, uint64_t uid, uint64_t het_cov, uint64_t n_hap) -{ - ma_hit_t *h; ma_utg_t *u; - uint64_t C_bases, R_bases, cc, dd, k, j, rid, tn, md, mk; - set_rset(ug, uid, ff, 1); - - u = &(ug->u.a[uid]); - for (k = C_bases = R_bases = 0; k < u->n; k++) { - rid = u->a[k]>>33; R_bases += sg->seq[rid].len; - for (j = 0; j < src[rid].length; j++) { - h = &(src[rid].buffer[j]); - tn = Get_tn((*h)); - if((!sg->seq[tn].del) && (!ff[tn])) continue; - if((sg->seq[tn].del) && (!check_nc_status(sg, src, ff, tn))) continue; - C_bases += (Get_qe((*h)) - Get_qs((*h))); - } - // res[k] = C_bases; - } - - set_rset(ug, uid, ff, 0); - - if(R_bases) C_bases /= R_bases; - else C_bases = 0; - - md = mk = (uint64_t)-1; - for (k = 1; k <= n_hap; k++) { - cc = het_cov*k; - dd = ((C_bases>=cc)?(C_bases-cc):(cc-C_bases)); - if(dd <= md) { - md = dd; mk = k; - } - } - if(mk == ((uint64_t)-1)) mk = n_hap; - return mk; -} - -ug_rid_cov_t* gen_ug_rid_cov_t(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc *src) -{ - uint64_t k; uint8_t *ff; CALLOC(ff, rg->n_seq); - ug_rid_cov_t *p; CALLOC(p, 1); - p->rg = rg; p->ug = ug; - MALLOC(p->idx, ug->g->n_seq); - p->cov.n = p->cov.m = 0; p->cov.a = NULL; - for (k = 0; k < p->ug->u.n; k++) { - p->idx[k] = p->cov.n; p->cov.n += p->ug->u.a[k].n; - } - p->cov.m = p->cov.n; MALLOC(p->cov.a, p->cov.n); - for (k = 0; k < p->ug->u.n; k++) { - fill_cov_arr(ug, rg, src, ff, k, p->cov.a+p->idx[k]); - } - free(ff); - - uint64_t hom_cov, het_cov, hom_cut; - if(asm_opt.hom_global_coverage_set) { - hom_cov = asm_opt.hom_global_coverage; - } else { - hom_cov = ((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE); - } - het_cov = hom_cov/asm_opt.polyploidy; - hom_cut = hom_cov + (het_cov*(0.5+(((double)asm_opt.polyploidy)*0.05))); - p->hom_max = hom_cut; - p->hom_min = (het_cov*(asm_opt.polyploidy-1)) + (het_cov*(0.5+(((double)(asm_opt.polyploidy-1))*0.05))); - p->hom_cov = hom_cov; p->het_cov = het_cov; - return p; -} - -void destory_ug_rid_cov_t(ug_rid_cov_t *p) -{ - if(!p) return; - free(p->idx); free(p->cov.a); -} - -uint64_t get_ovlp_cov(ma_utg_t *in, uint64_t *cc, asg_t *sg, int64_t s, int64_t e, int64_t *itk, int64_t *itl, uint64_t reflen) -{ - int64_t k, l, n = in->n; uint64_t rid, o, ol; int64_t qs, qe, os, oe; - k = (*itk); l = (*itl); o = ol = 0; - if(k >= n) { - k = n-1; l = ((int64_t)(in->len))-((int64_t)(sg->seq[k].len)); - } - if(k < 0 || l < 0) { - k = 0; l = 0; - } - - - for (; k > 0; k--) { - rid = in->a[k]>>33; - qs = l; qe = l + sg->seq[rid].len; - if(qe <= s) break; - l -= (int64_t)((uint32_t)in->a[k]); - } - - for (; k < n; k++) { - rid = in->a[k]>>33; - qs = l; qe = l + sg->seq[rid].len; - if(qs >= e) break; - l += (uint32_t)in->a[k]; - if(qe <= s) continue; - - os = MAX(qs, s); oe = MIN(qe, e); - if(oe <= os) continue; - assert(oe > os); - o += (((double)(oe-os))/((double)(sg->seq[rid].len)))*(cc[rid]); - ol += oe - os; - } - - (*itk) = k; (*itl) = l; - o = ((ol)?(o/ol):(0)); - return o*reflen; -} - -uint64_t get_ovlp_cov_1(ma_utg_t *in, uint64_t *idx, asg_t *sg, int64_t s, int64_t e, int64_t *itk, int64_t *itl, uint64_t reflen) -{ - int64_t k, l, n = in->n; uint64_t rid, o, ol; int64_t qs, qe, os, oe; - k = (*itk); l = (*itl); o = ol = 0; - if(k >= n) { - k = n-1; l = ((int64_t)(in->len))-((int64_t)(sg->seq[k].len)); - } - if(k < 0 || l < 0) { - k = 0; l = 0; - } - - - for (; k > 0; k--) { - rid = in->a[k]>>33; - qs = l; qe = l + sg->seq[rid].len; - if(qe <= s) break; - l -= (int64_t)((uint32_t)in->a[k]); - } - - for (; k < n; k++) { - rid = in->a[k]>>33; - qs = l; qe = l + sg->seq[rid].len; - if(qs >= e) break; - l += (uint32_t)in->a[k]; - if(qe <= s) continue; - - os = MAX(qs, s); oe = MIN(qe, e); - if(oe <= os) continue; - assert(oe > os); - o += (((double)(oe-os))/((double)(sg->seq[rid].len)))*(idx[k]); - ol += oe - os; - } - - (*itk) = k; (*itl) = l; - o = ((ol)?(o/ol):(0)); - return o*reflen; -} - -uint32_t append_cov_line_ug_rid_cov_t(uint64_t uid, uint64_t *qcc, u_trans_t *p, ug_rid_cov_t *idx, uint64_t hom_cut, double cut_rate) -{ - uint32_t k, rid; uint64_t qs, qe, oqs, oqe, ovq, ots, ote, no, tot, ava; - ma_utg_t *qu, *tu; uint64_t s_shift, e_shift; int64_t itk, itl, l; - qu = &(idx->ug->u.a[p->qn]); tu = &(idx->ug->u.a[p->tn]); - if(qu->n <= 0 || tu->n <= 0) return 0; - if(p->rev) { - itk = tu->n-1; itl = ((int64_t)(tu->len))-((int64_t)(idx->rg->seq[itk].len)); - } else { - itk = 0; itl = 0; - } - // if(uid == 7929) { - // fprintf(stderr, "*****[M::%s]\tutg%.6lu%c\tqu->n::%u\ttu->n::%u\n", __func__, - // uid+1, "lc"[idx->ug->u.a[uid].circ], (uint32_t)qu->n, (uint32_t)tu->n); - // } - for (k = l = 0, tot = ava = 0; k < qu->n; k++) { - rid = qu->a[k]>>33; - qs = l; qe = l + idx->rg->seq[rid].len; - l += (uint32_t)qu->a[k]; - if(qe <= p->qs) continue; - if(qs >= p->qe) break; - ///qe > p->qs && qs < p->qe && qe > qs - - oqs = MAX(qs, p->qs); oqe = MIN(qe, p->qe); - ovq = ((oqe > oqs)? (oqe - oqs):0); - - // if(!(ovq > 0)) { - // fprintf(stderr, "[M::%s::] qn::%u, tn::%u, q::[%lu, %lu), p->q::[%u, %u)\n", - // __func__, p->qn, p->tn, qs, qe, p->qs, p->qe); - // } - if(ovq <= 0) continue; - assert(ovq > 0); - if((hom_cut != ((uint64_t)-1)) && (cut_rate >= 0) && (ovq <= (idx->rg->seq[rid].len*0.55))) { - continue; - } - - s_shift = get_offset_adjust(oqs-p->qs, p->qe-p->qs, p->te-p->ts); - e_shift = get_offset_adjust(p->qe-oqe, p->qe-p->qs, p->te-p->ts); - if(p->rev) { - ovq = s_shift; s_shift = e_shift; e_shift = ovq; - } - ots = p->ts + s_shift; ote = p->te-e_shift; - if(ote <= ots) continue; - no = get_ovlp_cov_1(tu, idx->cov.a + idx->idx[p->tn], idx->rg, ots, ote, &itk, &itl, idx->rg->seq[rid].len); - // if(uid == 7929) { - // fprintf(stderr, "[%u]\trid::%u\tno::%lu\tqcc[k]::%lu\trlen::%u\n", - // k, rid, no, qcc[k], idx->rg->seq[rid].len); - // } - // to = qcc[k] + no; - // qcc[k] = to; - if((hom_cut == ((uint64_t)-1)) || (cut_rate < 0)) { - qcc[k] += no; - } else { - tot++; - if((qcc[k] + no) <= (hom_cut*((uint64_t)idx->rg->seq[rid].len))) ava++; - } - } - - // if(uid == 7929) { - // fprintf(stderr, "[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tis_reliable::%u\tw::%f\n", __func__, - // p->qn+1, "lc"[idx->ug->u.a[p->qn].circ], idx->ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], - // p->tn+1, "lc"[idx->ug->u.a[p->tn].circ], idx->ug->u.a[p->tn].len, p->ts, p->te, ((p->f == RC_0) || (p->f == RC_1))?1:0, p->nw); - // fprintf(stderr, "[M::%s]\tutg%.6lu%c\thom_cut::%lu\tcut_rate::%f\tava::%lu\ttot::%lu\n", __func__, - // uid+1, "lc"[idx->ug->u.a[uid].circ], hom_cut, cut_rate, ava, tot); - // } - - if((hom_cut != ((uint64_t)-1)) && (cut_rate >= 0) && (ava >= (tot*cut_rate))) { - return 1; - } - return 0; -} - -uint32_t append_cov_line(uint64_t uid, uint64_t *qcc, uint64_t *cc, u_trans_t *p, ma_ug_t *ug, asg_t *sg, uint64_t hom_cut, double cut_rate) -{ - uint32_t k, rid; uint64_t qs, qe, oqs, oqe, ovq, ots, ote, no, tot, ava; - ma_utg_t *qu, *tu; uint64_t s_shift, e_shift; int64_t itk, itl, l; - qu = &(ug->u.a[p->qn]); tu = &(ug->u.a[p->tn]); - if(qu->n <= 0 || tu->n <= 0) return 0; - if(p->rev) { - itk = tu->n-1; itl = ((int64_t)(tu->len))-((int64_t)(sg->seq[itk].len)); - } else { - itk = 0; itl = 0; - } - // if(uid == 315 || uid == 1055) { - // fprintf(stderr, "*****[M::%s]\tutg%.6lu%c\tqu->n::%u\ttu->n::%u\n", __func__, - // uid+1, "lc"[ug->u.a[uid].circ], (uint32_t)qu->n, (uint32_t)tu->n); - // } - for (k = l = 0, tot = ava = 0; k < qu->n; k++) { - rid = qu->a[k]>>33; - qs = l; qe = l + sg->seq[rid].len; - l += (uint32_t)qu->a[k]; - if(qe <= p->qs) continue; - if(qs >= p->qe) break; - ///qe > p->qs && qs < p->qe && qe > qs - - oqs = MAX(qs, p->qs); oqe = MIN(qe, p->qe); - ovq = ((oqe > oqs)? (oqe - oqs):0); - - // if(!(ovq > 0)) { - // fprintf(stderr, "[M::%s::] qn::%u, tn::%u, q::[%lu, %lu), p->q::[%u, %u)\n", - // __func__, p->qn, p->tn, qs, qe, p->qs, p->qe); - // } - if(ovq <= 0) continue; - assert(ovq > 0); - if((hom_cut != ((uint64_t)-1)) && (cut_rate >= 0) && (ovq <= (sg->seq[rid].len*0.55))) { - continue; - } - - s_shift = get_offset_adjust(oqs-p->qs, p->qe-p->qs, p->te-p->ts); - e_shift = get_offset_adjust(p->qe-oqe, p->qe-p->qs, p->te-p->ts); - if(p->rev) { - ovq = s_shift; s_shift = e_shift; e_shift = ovq; - } - ots = p->ts + s_shift; ote = p->te-e_shift; - if(ote <= ots) continue; - no = get_ovlp_cov(tu, cc, sg, ots, ote, &itk, &itl, sg->seq[rid].len); - // if(uid == 315 || uid == 1055) { - // fprintf(stderr, "[%u]\trid::%u\tno::%lu\tqcc[k]::%lu\trlen::%u\n", k, rid, no, qcc[k], sg->seq[rid].len); - // } - // to = qcc[k] + no; - // qcc[k] = to; - if((hom_cut == ((uint64_t)-1)) || (cut_rate < 0)) { - qcc[k] += no; - } else { - tot++; - if((qcc[k] + no) <= (hom_cut*((uint64_t)sg->seq[rid].len))) ava++; - } - } - - // if(uid == 315 || uid == 1055) { - // fprintf(stderr, "[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tis_reliable::%u\tw::%f\n", __func__, - // p->qn+1, "lc"[ug->u.a[p->qn].circ], ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], - // p->tn+1, "lc"[ug->u.a[p->tn].circ], ug->u.a[p->tn].len, p->ts, p->te, ((p->f == RC_0) || (p->f == RC_1))?1:0, p->nw); - // fprintf(stderr, "[M::%s]\tutg%.6lu%c\thom_cut::%lu\tcut_rate::%f\tava::%lu\ttot::%lu\n", __func__, - // uid+1, "lc"[ug->u.a[uid].circ], hom_cut, cut_rate, ava, tot); - // } - - if((hom_cut != ((uint64_t)-1)) && (cut_rate >= 0) && (ava >= (tot*cut_rate))) { - return 1; - } - return 0; -} - -void purge_ovlp_cov(uint32_t id, kv_u_trans_t *ta, ma_ug_t *ug, asg_t *sg, asg64_v *b64, uint64_t *cc, uint64_t hom_cut) -{ - ma_utg_t *u = &(ug->u.a[id]); uint32_t k, n, cn; - u_trans_t *a = NULL, t; - kv_resize(uint64_t, *b64, u->n); - for (k = 0; k < u->n; k++) b64->a[k] = cc[u->a[k]>>33]; - a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); - // if(id == 315 || id == 1055) { - // fprintf(stderr, "\n[M::%s]\tutg%.6u%c\tn::%u\n", __func__, id+1, "lc"[ug->u.a[id].circ], n); - // } - for (k = cn = 0; k < n; k++) {///RC_0/RC_1 to a[0, r_n) - // if(id == 315 || id == 1055) { - // fprintf(stderr, "-0-[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tis_reliable::%u\tw::%f\n", __func__, - // a[k].qn+1, "lc"[ug->u.a[a[k].qn].circ], ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], - // a[k].tn+1, "lc"[ug->u.a[a[k].tn].circ], ug->u.a[a[k].tn].len, a[k].ts, a[k].te, - // ((a[k].f == RC_0) || (a[k].f == RC_1))?1:0, a[k].nw); - // } - if((a[k].f == RC_0) || (a[k].f == RC_1)) { - if(k != cn) { - t = a[k]; a[k] = a[cn]; a[cn] = t; - } - cn++; - } - } - // if(id == 315 || id == 1055) { - // fprintf(stderr, "[M::%s]\tutg%.6u%c\tn::%u\tcn::%u\n", __func__, - // id+1, "lc"[ug->u.a[id].circ], n, cn); - // } - if(cn >= n) return; - if(n-cn > 1) qsort(a+cn, n-cn, sizeof((*a)), cmp_u_trans_weight); - for (k = 0; k < cn; k++) {///calculate coverage for - append_cov_line(id, b64->a, cc, &(a[k]), ug, sg, ((uint64_t)-1), -1); - } - - for (k = cn; k < n; k++) { - if(append_cov_line(id, b64->a, cc, &(a[k]), ug, sg, hom_cut, 0.51)) { - append_cov_line(id, b64->a, cc, &(a[k]), ug, sg, ((uint64_t)-1), -1); - continue; - } - a[k].del = 1; - } -} - -void trans_sec_cut_filter_mmhap(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *sg, ma_hit_t_alloc* src) -{ - uint64_t k, hom_cov, het_cov, hom_cut; - asg64_v b64; kv_init(b64); - uint64_t *cc = gen_cov_rg(ug, sg, src); - if(asm_opt.hom_global_coverage_set) { - hom_cov = asm_opt.hom_global_coverage; - } else { - hom_cov = ((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE); - } - het_cov = hom_cov/asm_opt.polyploidy; - hom_cut = hom_cov + (het_cov*(0.5+(((double)asm_opt.polyploidy)*0.05))); - - fprintf(stderr, "+[M::%s]\thom_cov::%lu\thet_cov::%lu\thom_cut::%lu\n", __func__, - hom_cov, het_cov, hom_cut); - - for (k = 0; k < ug->g->n_seq; k++) { - purge_ovlp_cov(k, ta, ug, sg, &b64, cc, hom_cut); - } - free(cc); kv_destroy(b64); -} - - -void purge_ovlp_cov_adv(uint32_t id, kv_u_trans_t *ta, asg64_v *b64, ug_rid_cov_t *cc, uint64_t hom_cut) -{ - ma_utg_t *u = &(cc->ug->u.a[id]); uint32_t k, n, cn; - u_trans_t *a = NULL, t; - kv_resize(uint64_t, *b64, u->n); - memcpy(b64->a, cc->cov.a+cc->idx[id], sizeof((*(b64->a)))*cc->ug->u.a[id].n); - a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); - // if(id == 7929) { - // fprintf(stderr, "\n[M::%s]\tutg%.6u%c\tn::%u\n", __func__, id+1, "lc"[cc->ug->u.a[id].circ], n); - // } - for (k = cn = 0; k < n; k++) {///RC_0/RC_1 to a[0, r_n) - // if(id == 7929) { - // fprintf(stderr, "-0-[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tis_reliable::%u\tw::%f\n", __func__, - // a[k].qn+1, "lc"[cc->ug->u.a[a[k].qn].circ], cc->ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], - // a[k].tn+1, "lc"[cc->ug->u.a[a[k].tn].circ], cc->ug->u.a[a[k].tn].len, a[k].ts, a[k].te, - // ((a[k].f == RC_0) || (a[k].f == RC_1))?1:0, a[k].nw); - // } - if((a[k].f == RC_0) || (a[k].f == RC_1)) { - if(k != cn) { - t = a[k]; a[k] = a[cn]; a[cn] = t; - } - cn++; - } - } - // if(id == 7929) { - // fprintf(stderr, "[M::%s]\tutg%.6u%c\tn::%u\tcn::%u\n", __func__, - // id+1, "lc"[cc->ug->u.a[id].circ], n, cn); - // } - if(cn >= n) return; - if(n-cn > 1) qsort(a+cn, n-cn, sizeof((*a)), cmp_u_trans_weight); - for (k = 0; k < cn; k++) {///calculate coverage for - append_cov_line_ug_rid_cov_t(id, b64->a, &(a[k]), cc, ((uint64_t)-1), -1); - } - - for (k = cn; k < n; k++) { - if(append_cov_line_ug_rid_cov_t(id, b64->a, &(a[k]), cc, hom_cut, 0.51)) { - append_cov_line_ug_rid_cov_t(id, b64->a, &(a[k]), cc, ((uint64_t)-1), -1); - continue; - } - a[k].del = 1; - } -} - -void trans_sec_cut_filter_mmhap_adv(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *sg, ma_hit_t_alloc* src, ug_rid_cov_t *in) -{ - uint64_t k; asg64_v b64; kv_init(b64); - ug_rid_cov_t *cc = ((in)?(in):(gen_ug_rid_cov_t(ug, sg, src))); - - fprintf(stderr, "+[M::%s]\thom_cov::%lu\thet_cov::%lu\thom_cut::%lu\n", __func__, - cc->hom_cov, cc->het_cov, cc->hom_max); - - for (k = 0; k < ug->g->n_seq; k++) { - purge_ovlp_cov_adv(k, ta, &b64, cc, cc->hom_max); - } - - if(!in) {destory_ug_rid_cov_t(cc); free(cc);} kv_destroy(b64); -} - -static void worker_for_trans_sec_simple_cut(void *data, long i, int tid) // callback for kt_for() -{ - u_trans_clean_t *s = (u_trans_clean_t*)data; - kv_u_trans_t *ta = s->ta; u_trans_t *a, *za; - uint32_t id = i, n, k, z, zn; - - a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); - for (k = 0; k < n; k++) { - if((!a[k].del)) continue; - za = u_trans_a(*ta, a[k].tn); zn = u_trans_n(*ta, a[k].tn); - for (z = 0; z < zn; z++) { - if(za[z].tn == id) break; - } - assert(z < zn); - if(za[z].del) { ///both a[k] and za[z] have been deleted - if(a[k].qn < a[k].tn) a[k].occ = za[z].occ = ((uint32_t)-1); - continue; - } - ///a[k].del == 1 && za[z].del == 0 - if(za[z].qe-za[z].qs >= 3000000) { - a[k].occ = za[z].occ = 0; - } else { - a[k].occ = za[z].occ = ((uint32_t)-1); - } - } -} - -void gen_ug_rid_cov_t_by_ovlp(kv_u_trans_t *ta, ug_rid_cov_t *cc) -{ - uint64_t z, k, id, n; u_trans_t *a; - for (z = 0; z < cc->ug->g->n_seq; z++) { - id = z; a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); - for (k = 0; k < n; k++) { - append_cov_line_ug_rid_cov_t(id, cc->cov.a+cc->idx[id], &(a[k]), cc, ((uint64_t)-1), -1); - } - } -} - -void clean_u_trans_t_idx_filter_mmhap_adv(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* src, ug_rid_cov_t *in) -{ - u_trans_clean_t sl; uint64_t k, i, l, st, occ; ha_mzl_t *tz; - ha_mzl_v srt_a; kv_u_trans_t *bl; u_trans_t *z; - memset(&sl, 0, sizeof(sl)); kv_init(srt_a); - - kt_u_trans_t_idx(ta, ug->g->n_seq); - sl.n_thread = asm_opt.thread_num; sl.ug = ug; sl.rg = read_g; sl.ta = ta; - CALLOC(sl.res, sl.n_thread); - sl.ov_cutoff = 3; sl.small_ov_rate = 0.8; - // dbg_prt_utg_trans(ta, ug, "pre"); - kt_for(sl.n_thread, worker_for_trans_clean_re, &sl, sl.ta->idx.n); - - for (i = srt_a.n = occ = 0; i < sl.n_thread; i++) { - bl = &(sl.res[i]); - if(!(bl->n)) continue; - for (k = 1, l = 0; k <= bl->n; k++) { - if(k == bl->n || bl->a[k].qn != bl->a[l].qn) { - if(k > l) { - kv_pushp(ha_mzl_t, srt_a, &tz); - tz->x = bl->a[l].qn; tz->x <<= 32; tz->x |= i; - tz->rid = l>>32; tz->pos = (uint32_t)l; - occ += (k - l); - } - l = k; - } - } - } - // fprintf(stderr, "[M::%s::] occ::%lu \n", __func__, occ); - assert(srt_a.n <= sl.ug->u.n); - radix_sort_ha_mzl_t_srt1(srt_a.a, srt_a.a + srt_a.n); - occ <<= 1; ta->n = 0; kv_resize(u_trans_t, *ta, occ); - for (i = 0; i < srt_a.n; i++) { - tz = &(srt_a.a[i]); - bl = &(sl.res[(uint32_t)(tz->x)]); - k = tz->rid; k <<= 32; k += tz->pos; - assert(bl->a[k].qn == (tz->x>>32)); - for (; (k < bl->n) && (bl->a[k].qn == (tz->x>>32)); k++) { - if(bl->a[k].qn == bl->a[k].tn) continue; - if(bl->a[k].qe-bl->a[k].qs <= 0) continue; - if(bl->a[k].te-bl->a[k].ts <= 0) continue; - kv_pushp(u_trans_t, *ta, &z); - (*z) = bl->a[k]; z->occ = 0; if(z->f == RC_3) z->f = RC_2; - // if(z->ts >= z->te || z->qs >= z->qe) { - // fprintf(stderr, "+[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, - // z->qn+1, "lc"[ug->u.a[z->qn].circ], ug->u.a[z->qn].len, z->qs, z->qe, "+-"[z->rev], - // z->tn+1, "lc"[ug->u.a[z->tn].circ], ug->u.a[z->tn].len, z->ts, z->te); - // } - - kv_pushp(u_trans_t, *ta, &z); - (*z) = bl->a[k]; z->occ = 0; if(z->f == RC_3) z->f = RC_2; - z->qn = bl->a[k].tn; z->qs = bl->a[k].ts; z->qe = bl->a[k].te; - z->tn = bl->a[k].qn; z->ts = bl->a[k].qs; z->te = bl->a[k].qe; - - // if(z->ts >= z->te || z->qs >= z->qe) { - // fprintf(stderr, "-[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, - // z->qn+1, "lc"[ug->u.a[z->qn].circ], ug->u.a[z->qn].len, z->qs, z->qe, "+-"[z->rev], - // z->tn+1, "lc"[ug->u.a[z->tn].circ], ug->u.a[z->tn].len, z->ts, z->te); - // } - } - } - - for (k = 0; k < sl.n_thread; k++) free(sl.res[k].a); - free(sl.res); kv_destroy(srt_a); - kt_u_trans_t_idx(ta, ug->g->n_seq); - // dbg_prt_utg_trans(ta, ug, "after"); - trans_sec_cut_filter_mmhap_adv(ta, ug, read_g, src, in); - kt_for(sl.n_thread, worker_for_trans_sec_simple_cut, &sl, sl.ta->idx.n); - - // CALLOC(sl.srt, sl.n_thread); sl.sec_rate = 0.5; - // kt_for(sl.n_thread, worker_for_trans_sec_cut, &sl, sl.ta->idx.n); - // sl.cu = gen_u_trans_cluster(ta); - // kt_for(sl.n_thread, worker_for_trans_sec_cut, &sl, sl.cu->idx.n); - // free(sl.cu->idx.a); free(sl.cu->z.a); free(sl.cu); - // for (k = 0; k < sl.n_thread; k++) free(sl.srt[k].a); free(sl.srt); - for (k = st = 0; k < ta->n; k++) { - if(ta->a[k].occ == ((uint32_t)-1)) continue; - ta->a[st] = ta->a[k]; ta->a[st].del = 0; st++; - } - ta->n = st; - for (st = 0, i = 1; i <= ta->n; ++i) { - if (i == ta->n || ta->a[i].qn != ta->a[st].qn) { - ta->idx.a[ta->a[st].qn] = (((uint64_t)st)<<32)|(i-st); - st = i; - } - } - - // dbg_prt_utg_extra_trans(ta, ug, asm_opt.output_file_name); -} - -void refine_hic_trans_mmhap(ug_opt_t *opt, kv_u_trans_t *ta, asg_t *sg, ma_ug_t *ug) -{ - filter_u_trans(ta, asm_opt.is_bub_trans, asm_opt.is_topo_trans, asm_opt.is_read_trans, asm_opt.is_base_trans); - if(asm_opt.is_base_trans) { - trans_base_mmhap_infer(ug, sg, opt, ta); - } - // dbg_prt_utg_trans(ta, ug, "pre"); - // clean_u_trans_t_idx_filter_mmhap_adv(ta, ug, sg, opt->sources); - // dbg_prt_utg_trans(ta, ug, "after"); -} - -void output_contig_graph_alternative(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, R_to_U* ruIndex, int max_hang, int min_ovlp); -void output_hic_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, -R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, -long long gap_fuzz, bub_label_t* b_mask_t, ug_opt_t *opt) -{ - hic_clean(sg); - kvec_pe_hit *rhits = NULL; - ma_ug_t *ug_fa = NULL, *ug_mo = NULL; - - kvec_asg_arc_t_warp new_rtg_edges, d_edges; - kv_init(new_rtg_edges.a); kv_init(d_edges.a); - ma_ug_t *ug = NULL; - ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); - - new_rtg_edges.a.n = 0; - ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, &d_edges, 1);///polish - - hap_cov_t *cov = NULL; - trans_chain* t_ch = NULL; - if((asm_opt.flag & HA_F_VERBOSE_GFA)) t_ch = load_hc_trans(output_file_name); - - if(!t_ch) - { - new_rtg_edges.a.n = 0; - asg_t *copy_sg = copy_read_graph(sg); - ma_ug_t *copy_ug = copy_untig_graph(ug); - ///asm_opt.purge_overlap_len = asm_opt.purge_overlap_len_hic; - ///asm_opt.purge_simi_thres = asm_opt.purge_simi_rate_hic; - adjust_utg_by_primary(©_ug, copy_sg, TRIO_THRES, sources, reverse_sources, coverage_cut, - tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, - max_hang, min_ovlp, &new_rtg_edges, &cov, b_mask_t, 1, 0); - print_utg(©_ug, copy_sg, coverage_cut, output_file_name, sources, ruIndex, max_hang, - min_ovlp, &new_rtg_edges); - - if(asm_opt.is_alt) - { - output_contig_graph_alternative(copy_sg, coverage_cut, output_file_name, sources, ruIndex, max_hang, - min_ovlp); - } - ma_ug_destroy(copy_ug); - asg_destroy(copy_sg); - // clean_u_trans_t_idx(&(cov->t_ch->k_trans), ug, sg); - - - new_rtg_edges.a.n = 0; - ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, - max_hang, min_ovlp, asm_opt.hic_inconsist_rate, NULL, NULL, cov->t_ch); - - if((asm_opt.flag & HA_F_VERBOSE_GFA)) write_trans_chain(cov->t_ch, output_file_name); - } - - refine_hic_trans(opt, &(cov?cov->t_ch->k_trans:t_ch->k_trans), sg, ug); - ///for debug - // char* gfa_name = (char*)malloc(strlen(output_file_name)+50); FILE* output_file = NULL; - - // sprintf(gfa_name, "%s.pre.clean_d_utg.noseq.gfa", output_file_name); - // output_file = fopen(gfa_name, "w"); - // ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - // fclose(output_file); - - // sprintf(gfa_name, "%s.pre.clean_d_utg.gfa", output_file_name); - // output_file = fopen(gfa_name, "w"); - // ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - // fclose(output_file); - - // free(gfa_name); - // exit(1); - ///for debug - - - - hic_analysis(ug, sg, cov?cov->t_ch:t_ch, opt, NULL, asm_opt.scffold?&rhits:NULL); - - - if(!rhits && cov) destory_hap_cov_t(&cov); - if(!rhits && t_ch) destory_trans_chain(&t_ch); - - - // char* gfa_name = (char*)malloc(strlen(output_file_name)+50); - // sprintf(gfa_name, "%s.after.clean_d_utg.noseq.gfa", output_file_name); - // FILE* output_file = fopen(gfa_name, "w"); - // ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - // fclose(output_file); - // free(gfa_name); - - ma_ug_destroy(ug); - kv_destroy(new_rtg_edges.a); - - - asg_arc_t* av = NULL; - uint32_t v, w, k, i, nv; - for (i = 0; i < d_edges.a.n; i++) - { - v = d_edges.a.a[i].ul>>32; - w = d_edges.a.a[i].v; - av = asg_arc_a(sg, v); - nv = asg_arc_n(sg, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - av[k].del = 1; - break; - } - } - } - kv_destroy(d_edges.a); - asg_cleanup(sg); - - // reduce_hamming_error_adv(NULL, sg, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz, opt->ruIndex, NULL); - - // ug_fa = output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, - // 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, rhits?1:0, b_mask_t, NULL, NULL, NULL); - // ug_mo = output_trio_unitig_graph(sg, coverage_cut, output_file_name, MOTHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, - // 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, rhits?1:0, b_mask_t, NULL, NULL, NULL); - - - output_trio_graph_joint(sg, coverage_cut, output_file_name, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, - 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, b_mask_t, rhits?(&ug_fa):NULL, rhits?(&ug_mo):NULL, opt); - if(rhits) - { - ha_aware_order(rhits, sg, ug_fa, ug_mo, cov?&(cov->t_ch->k_trans):&(t_ch->k_trans), opt, 3); - kv_destroy(rhits->a); kv_destroy(rhits->idx); kv_destroy(rhits->occ); free(rhits); - if(cov) destory_hap_cov_t(&cov); - if(t_ch) destory_trans_chain(&t_ch); - ma_ug_destroy(ug_fa); ma_ug_destroy(ug_mo); - } -} - - -uint64_t dump_trans_ovlp(trans_chain* t_ch, const char *fn, ma_ug_t *ug) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(fn)+50); - sprintf(gfa_name, "%s.trans.bin", fn); - FILE* fp = fopen(gfa_name, "w"); free(gfa_name); - if (!fp) return 0; - if(ug) write_dbug(ug, fp); - - fwrite(&t_ch->r_num, sizeof(t_ch->r_num), 1, fp); - fwrite(t_ch->ir_het, sizeof(uint8_t), t_ch->r_num, fp); - uint64_t i; - fwrite(&t_ch->bed.n, sizeof(t_ch->bed.n), 1, fp); - for (i = 0; i < t_ch->bed.n; i++) { - fwrite(&t_ch->bed.a[i].n, sizeof(t_ch->bed.a[i].n), 1, fp); - fwrite(t_ch->bed.a[i].a, sizeof(bed_interval), t_ch->bed.a[i].n, fp); - } - - fwrite(&t_ch->k_trans.n, sizeof(t_ch->k_trans.n), 1, fp); - fwrite(t_ch->k_trans.a, sizeof(u_trans_t), t_ch->k_trans.n, fp); - - fwrite(&t_ch->k_trans.idx.n, sizeof(t_ch->k_trans.idx.n), 1, fp); - fwrite(t_ch->k_trans.idx.a, sizeof(uint64_t), t_ch->k_trans.idx.n, fp); - - fclose(fp); - fprintf(stderr, "[M::%s] Dump trans overlaps\n", __func__); - return 1; -} - -trans_chain* load_trans_ovlp(const char *fn, ma_ug_t *ug) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(fn)+50); - sprintf(gfa_name, "%s.trans.bin", fn); - FILE* fp = fopen(gfa_name, "r"); free(gfa_name); - if (!fp) return NULL; - if(ug && (!test_dbug(ug, fp))) { - fprintf(stderr, "[M::%s] Renew trans overlaps\n", __func__); - fclose(fp); - return NULL; - } - - uint64_t flag = 0; - trans_chain *t_ch = NULL; - CALLOC(t_ch, 1); - - flag += fread(&t_ch->r_num, sizeof(t_ch->r_num), 1, fp); - MALLOC(t_ch->ir_het, t_ch->r_num); - flag += fread(t_ch->ir_het, sizeof(uint8_t), t_ch->r_num, fp); - - uint64_t i; - flag += fread(&t_ch->bed.n, sizeof(t_ch->bed.n), 1, fp); - MALLOC(t_ch->bed.a, t_ch->bed.n); t_ch->bed.m = t_ch->bed.n; - for (i = 0; i < t_ch->bed.n; i++) { - flag += fread(&t_ch->bed.a[i].n, sizeof(t_ch->bed.a[i].n), 1, fp); - MALLOC(t_ch->bed.a[i].a, t_ch->bed.a[i].n); t_ch->bed.a[i].m = t_ch->bed.a[i].n; - flag += fread(t_ch->bed.a[i].a, sizeof(bed_interval), t_ch->bed.a[i].n, fp); - } - - flag += fread(&t_ch->k_trans.n, sizeof(t_ch->k_trans.n), 1, fp); - MALLOC(t_ch->k_trans.a, t_ch->k_trans.n); t_ch->k_trans.m = t_ch->k_trans.n; - flag += fread(t_ch->k_trans.a, sizeof(u_trans_t), t_ch->k_trans.n, fp); - - flag += fread(&t_ch->k_trans.idx.n, sizeof(t_ch->k_trans.idx.n), 1, fp); - MALLOC(t_ch->k_trans.idx.a, t_ch->k_trans.idx.n); t_ch->k_trans.idx.m = t_ch->k_trans.idx.n; - flag += fread(t_ch->k_trans.idx.a, sizeof(uint64_t), t_ch->k_trans.idx.n, fp); - - fclose(fp); - fprintf(stderr, "[M::%s::] ==> Trans overlaps have been loaded\n", __func__); - return t_ch; -} - -void update_trio_mmhap(uint32_t hapid, ma_ug_t *mm_ug, mmhap_t *rh, asg_t *sg, uint32_t n_hap) -{ - uint64_t k, z, m, rid; ma_utg_t *u; - for (k = 0; k < sg->n_seq; k++) { - if(R_INF.trio_flag[k] == DROP) continue; - R_INF.trio_flag[k] = AMBIGU; - } - - for (k = 0; k < mm_ug->u.n; k++) { - if(rh->h.a[k].m == n_hap || rh->h.a[k].n == 0) { - m = AMBIGU; - } else { - for (z = 0, m = MOTHER; z < rh->h.a[k].n; z++) { - if(rh->a.a[rh->h.a[k].a+z] == hapid) {m = FATHER; break;} - } - } - - u = &(mm_ug->u.a[k]); - for (z = 0; z < u->n; z++) { - rid = u->a[z]>>33; - if(R_INF.trio_flag[rid] == DROP) continue; - R_INF.trio_flag[rid] = m; - } - fprintf(stderr, "utg%.6lu%c\tm::%lu\n", k+1, "lc"[mm_ug->u.a[k].circ], m); - } -} - -void dbg_prt_trio_mmhap_label(ma_ug_t *ug, mmhap_t *rh, const char *o_n) -{ - char* gfa_name = (char*)malloc(strlen(o_n)+100); - FILE *fn = NULL; sprintf(gfa_name, "%s.mmhap.binning.log", o_n); - uint32_t i, z; fn = fopen(gfa_name, "w"); - for (i = 0; i < ug->g->n_seq; i++) { - fprintf(fn, "utg%.6u%c\tm::%u\tn::%u", i+1, "lc"[ug->u.a[i].circ], rh->h.a[i].m, rh->h.a[i].n); - for (z = 0; z < rh->h.a[i].n; z++) { - fprintf(fn, "\t%u", rh->a.a[rh->h.a[i].a+z]); - } - fprintf(fn, "\n"); - } - fclose(fn); free(gfa_name); fprintf(stderr, "[M::%s::] done\n", __func__); -} - -void output_trio_mmhap(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, ma_hit_t_alloc* sources, -ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, -float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, long long gap_fuzz, bub_label_t* b_mask_t, ug_opt_t *opt, -ma_ug_t *mm_ug, mmhap_t *rh, uint32_t n_hap) -{ - uint32_t i; char *fp = NULL; MALLOC(fp, 100); - memset(R_INF.trio_flag, 0, sizeof((*(R_INF.trio_flag)))*sg->n_seq); - for (i = 0; i < n_hap; i++){ - sprintf(fp, "hap%u", i+1); - update_trio_mmhap(i, mm_ug, rh, sg, n_hap); - output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, reverse_sources, tipsLen, tip_drop_ratio, - stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, gap_fuzz, 0, b_mask_t, fp, NULL, NULL); - } - free(fp); -} - -void output_hic_graph_mmhap(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, ma_hit_t_alloc* sources, -ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, -float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, long long gap_fuzz, bub_label_t* b_mask_t, ug_opt_t *opt) -{ - hic_clean(sg); - mmhap_t *rh = NULL; - - kvec_asg_arc_t_warp new_rtg_edges, d_edges; - kv_init(new_rtg_edges.a); kv_init(d_edges.a); - ma_ug_t *ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); - - new_rtg_edges.a.n = 0; - ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, &d_edges, 1);///polish - - hap_cov_t *cov = NULL; - trans_chain* t_ch = NULL; - t_ch = load_trans_ovlp(output_file_name, ug); - // if((asm_opt.flag & HA_F_VERBOSE_GFA)) t_ch = load_hc_trans(output_file_name); - - if(!t_ch) { - new_rtg_edges.a.n = 0; - asg_t *copy_sg = copy_read_graph(sg); - ma_ug_t *copy_ug = copy_untig_graph(ug); - ///asm_opt.purge_overlap_len = asm_opt.purge_overlap_len_hic; - ///asm_opt.purge_simi_thres = asm_opt.purge_simi_rate_hic; - adjust_utg_by_primary(©_ug, copy_sg, TRIO_THRES, sources, reverse_sources, coverage_cut, - tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, - max_hang, min_ovlp, &new_rtg_edges, &cov, b_mask_t, 1, 0); - print_utg(©_ug, copy_sg, coverage_cut, output_file_name, sources, ruIndex, max_hang, - min_ovlp, &new_rtg_edges); - - if(asm_opt.is_alt) { - output_contig_graph_alternative(copy_sg, coverage_cut, output_file_name, sources, ruIndex, max_hang, - min_ovlp); - } - ma_ug_destroy(copy_ug); - asg_destroy(copy_sg); - // clean_u_trans_t_idx(&(cov->t_ch->k_trans), ug, sg); - - - new_rtg_edges.a.n = 0; - ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, - max_hang, min_ovlp, asm_opt.hic_inconsist_rate, NULL, NULL, cov->t_ch); - - refine_hic_trans_mmhap(opt, &(cov->t_ch->k_trans), sg, ug); - dump_trans_ovlp(cov->t_ch, output_file_name, ug); - // if((asm_opt.flag & HA_F_VERBOSE_GFA)) write_trans_chain(cov->t_ch, output_file_name); - } - - // dbg_prt_utg_trans(&(cov?cov->t_ch->k_trans:t_ch->k_trans), ug, "pre"); - clean_u_trans_t_idx_filter_mmhap_adv(&(cov?cov->t_ch->k_trans:t_ch->k_trans), ug, sg, opt->sources, NULL); - // dbg_prt_utg_trans(&(cov?cov->t_ch->k_trans:t_ch->k_trans), ug, "after"); - - // refine_hic_trans_mmhap(opt, &(cov?cov->t_ch->k_trans:t_ch->k_trans), sg, ug); - ///for debug - // dbg_prt_utg_trans(&(cov?cov->t_ch->k_trans:t_ch->k_trans), ug, "dd"); - // char* gfa_name = (char*)malloc(strlen(output_file_name)+50); FILE* output_file = NULL; - - // sprintf(gfa_name, "%s.pre.clean_d_utg.noseq.gfa", output_file_name); - // output_file = fopen(gfa_name, "w"); - // ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - // fclose(output_file); - - // sprintf(gfa_name, "%s.pre.clean_d_utg.gfa", output_file_name); - // output_file = fopen(gfa_name, "w"); - // ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - // fclose(output_file); - - // free(gfa_name); - // exit(1); - ///for debug - - - hic_analysis(ug, sg, cov?cov->t_ch:t_ch, opt, &rh, NULL); - - - if(cov) destory_hap_cov_t(&cov); - if(t_ch) destory_trans_chain(&t_ch); - - - // char* gfa_name = (char*)malloc(strlen(output_file_name)+50); - // sprintf(gfa_name, "%s.after.clean_d_utg.noseq.gfa", output_file_name); - // FILE* output_file = fopen(gfa_name, "w"); - // ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - // fclose(output_file); - // free(gfa_name); - - // ma_ug_destroy(ug); - kv_destroy(new_rtg_edges.a); - - - asg_arc_t* av = NULL; - uint32_t v, w, k, i, nv; - for (i = 0; i < d_edges.a.n; i++) - { - v = d_edges.a.a[i].ul>>32; - w = d_edges.a.a[i].v; - av = asg_arc_a(sg, v); - nv = asg_arc_n(sg, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - av[k].del = 1; - break; - } - } - } - kv_destroy(d_edges.a); - asg_cleanup(sg); - - // dbg_prt_trio_mmhap_label(ug, rh, output_file_name); - - output_trio_mmhap(sg, coverage_cut, output_file_name, sources, reverse_sources, tipsLen, tip_drop_ratio, - stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, gap_fuzz, b_mask_t, opt, ug, rh, asm_opt.polyploidy); - - ma_ug_destroy(ug); - free(rh->a.a); free(rh->h.a); free(rh); -} - -void print_debug_gfa(ma_ug_t *ug, asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, R_to_U* ruIndex) -{ - char* gfa_name = (char*)malloc(strlen(output_file_name)+50); - sprintf(gfa_name, "%s.after.clean_d_utg.gfa", output_file_name); - FILE* output_file = fopen(gfa_name, "w"); - ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - fclose(output_file); - - sprintf(gfa_name, "%s.after.clean_d_utg.noseq.gfa", output_file_name); - output_file = fopen(gfa_name, "w"); - ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - fclose(output_file); - - free(gfa_name); -} - -void print_simple_dbg_gfa(asg_t *g, const char* prt) -{ - char* gfa_name = (char*)malloc(strlen(prt)+50); - sprintf(gfa_name, "%s.dbg.noseq.gfa", prt); - FILE *fp = fopen(gfa_name, "w"); - uint32_t i, j; char name[32]; - for (i = 0; i < g->n_seq; ++i) { // the Segment lines in GFA - if(g->seq[i].del) continue; - sprintf(name, "utg%.6dl", i + 1); - fprintf(fp, "S\t%s\t*\tLN:i:%d\trd:i:%u\n", name, g->seq[i].len, 0); - } - - asg_arc_t* au = NULL; uint32_t nu, u, v; - for (i = 0; i < g->n_seq; ++i) { - if(g->seq[i].del) continue; - - u = i<<1; - au = asg_arc_a(g, u); nu = asg_arc_n(g, u); - for (j = 0; j < nu; j++) { - if(au[j].del) continue; - v = au[j].v; - fprintf(fp, "L\tutg%.6dl\t%c\tutg%.6dl\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", - (u>>1)+1, "+-"[u&1], (v>>1)+1, "+-"[v&1], au[j].ol, asg_arc_len(au[j]), 0/**au[j].ou**/); - } - - - u = (i<<1) + 1; - au = asg_arc_a(g, u); nu = asg_arc_n(g, u); - for (j = 0; j < nu; j++) { - if(au[j].del) continue; - v = au[j].v; - fprintf(fp, "L\tutg%.6dl\t%c\tutg%.6dl\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", - (u>>1)+1, "+-"[u&1], (v>>1)+1, "+-"[v&1], au[j].ol, asg_arc_len(au[j]), 0/**au[j].ou**/); - } - } - - fclose(fp); free(gfa_name); -} - -ma_ug_t *get_poly_ug(asg_t *sg, ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -int max_hang, int min_ovlp, R_to_U* ruIndex, bub_label_t* b_mask_t) -{ - kvec_asg_arc_t_warp new_rtg_edges, d_edges; - kv_init(new_rtg_edges.a); kv_init(d_edges.a); - - ma_ug_t *ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); - - uint8_t* is_r_het = NULL; - CALLOC(is_r_het, sg->n_seq); - set_r_het_flag(ug, sg, coverage_cut, sources, ruIndex, is_r_het); - - adjust_utg_advance(sg, ug, reverse_sources, ruIndex, b_mask_t, is_r_het); - asg_t* nsg = (*ug).g; - uint32_t v, n_vtx = nsg->n_seq; - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - nsg->seq[v].c = PRIMARY_LABLE; - } - delete_useless_nodes(&ug); - renew_utg(&ug, sg, NULL); - - ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, &d_edges, 1); - - kv_destroy(new_rtg_edges.a); kv_destroy(d_edges.a); - horder_clean_sg_by_utg(sg, ug); - free(is_r_het); - return ug; -} - -trans_chain* get_hic_polyploid_trans_chain(ma_ug_t *ug, asg_t *sg, ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -int max_hang, int min_ovlp, R_to_U* ruIndex, bub_label_t* b_mask_t) -{ - uint32_t k; - trans_chain* p = NULL; CALLOC(p, 1); - p->r_num = sg->n_seq; p->u_num = ug->u.n; - kv_malloc(p->bed, p->u_num); p->bed.n = p->u_num; - for (k = 0; k < p->bed.n; k++) kv_init(p->bed.a[k]); - CALLOC(p->ir_het, p->r_num); - kv_u_trans_t *ta = get_utg_ovlp(&ug, sg, sources, reverse_sources, coverage_cut, ruIndex, max_hang, min_ovlp, NULL, b_mask_t, p->ir_het); - p->k_trans = *ta; free(ta); - return p; -} - -void output_hic_graph_polyploid(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, -R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, -long long gap_fuzz, bub_label_t* b_mask_t) -{ - ug_opt_t opt; memset(&opt, 0, sizeof(opt)); - opt.coverage_cut = coverage_cut; - opt.sources = sources; - opt.reverse_sources = reverse_sources; - opt.tipsLen = (asm_opt.max_short_tip*2); - opt.tip_drop_ratio = 0.15; - opt.stops_threshold = 3; - opt.ruIndex = ruIndex; - opt.chimeric_rate = 0.05; - opt.drop_ratio = 0.9; - opt.max_hang = max_hang; - opt.min_ovlp = min_ovlp; - opt.is_bench = 0; - opt.b_mask_t = b_mask_t; - opt.gap_fuzz = gap_fuzz; - - - ma_ug_t *ug = get_poly_ug(sg, coverage_cut, sources, reverse_sources, max_hang, min_ovlp, ruIndex, b_mask_t); - trans_chain* t_ch = NULL; - - char* gfa_name = (char*)malloc(strlen(output_file_name)+50); - sprintf(gfa_name, "%s.pre.clean_d_utg.noseq.gfa", output_file_name); - FILE* output_file = fopen(gfa_name, "w"); - ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - fclose(output_file); - free(gfa_name); - - if((asm_opt.flag & HA_F_VERBOSE_GFA)) t_ch = load_hc_trans(output_file_name); - if(!t_ch) - { - t_ch = get_hic_polyploid_trans_chain(ug, sg, coverage_cut, sources, reverse_sources, max_hang, min_ovlp, ruIndex, b_mask_t); - ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, NULL, - max_hang, min_ovlp, asm_opt.hic_inconsist_rate, NULL, NULL, t_ch); - if((asm_opt.flag & HA_F_VERBOSE_GFA)) write_trans_chain(t_ch, output_file_name); - } - - hic_analysis(ug, sg, t_ch, &opt, NULL, NULL); - destory_trans_chain(&t_ch); - ma_ug_destroy(ug); - asg_cleanup(sg); - - // reduce_hamming_error(sg, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz); - reduce_hamming_error_adv(NULL, sg, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz, opt.ruIndex, NULL); - - output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, - 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, 0, b_mask_t, NULL, NULL, NULL); - output_trio_unitig_graph(sg, coverage_cut, output_file_name, MOTHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, - 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, 0, b_mask_t, NULL, NULL, NULL); -} - -void set_trio_flag_by_cov(ma_ug_t *ug, asg_t *read_g, hap_cov_t *cov) -{ - kvec_t(uint64_t) idx; kv_init(idx); - uint32_t i, k, j, qn, tn, s[2], flag, n, found = 0; - uint64_t offset, r_beg, r_end, ovlp; - ma_utg_t *u = NULL, *w = NULL; - u_trans_t *a = NULL; - kv_u_trans_t *ta = &(cov->t_ch->k_trans); - - for (i = 0, idx.n = 0; i < ta->idx.n; i++) - { - qn = i; - u = &(ug->u.a[qn]); - for (k = 0; k < u->n; k++) - { - if((R_INF.trio_flag[u->a[k]>>33]&SET_TRIO)==0) break; - } - - if(k >= u->n) continue; ///whole unitig is primary - - a = u_trans_a(*ta, qn); - n = u_trans_n(*ta, qn); - for (k = 0, s[0] = s[1] = 0; k < n; k++) - { - tn = a[k].tn; - w = &(ug->u.a[tn]); - for (j = found = 0, offset = 0; j < w->n; j++) - { - - r_beg = offset; r_end = offset + read_g->seq[w->a[j]>>33].len; - offset += (uint32_t)w->a[j]; - ovlp = ((MIN(r_end, a[k].te) > MAX(r_beg, a[k].ts))? - MIN(r_end, a[k].te) - MAX(r_beg, a[k].ts):0); - if(found == 1 && ovlp == 0) break; - if(ovlp == 0) continue; - found = 1; - if(ovlp <= (read_g->seq[w->a[j]>>33].len)*0.8) continue; - - if((R_INF.trio_flag[w->a[j]>>33]&FATHER)||(R_INF.trio_flag[w->a[j]>>33]&MOTHER)) - { - s[0]++; - } - - if(R_INF.trio_flag[w->a[j]>>33]&SET_TRIO) - { - s[1]++; - } - } - } - - if(s[1] > 0) - { - kv_push(uint64_t, idx, (uint64_t)((uint32_t)-1 - s[0]) << 32 | (qn)); - } - } - - for (i = 0; i < idx.n; i++) - { - qn = (uint32_t)idx.a[i]; - u = &(ug->u.a[qn]); - a = u_trans_a(*ta, qn); - n = u_trans_n(*ta, qn); - for (k = 0, s[0] = s[1] = 0; k < n; k++) - { - tn = a[k].tn; - w = &(ug->u.a[tn]); - for (j = found = 0, offset = 0; j < w->n; j++) - { - - r_beg = offset; r_end = offset + read_g->seq[w->a[j]>>33].len; - offset += (uint32_t)w->a[j]; - ovlp = ((MIN(r_end, a[k].te) > MAX(r_beg, a[k].ts))? - MIN(r_end, a[k].te) - MAX(r_beg, a[k].ts):0); - if(found == 1 && ovlp == 0) break; - if(ovlp == 0) continue; - found = 1; - if(ovlp <= (read_g->seq[w->a[j]>>33].len)*0.8) continue; - - if(R_INF.trio_flag[w->a[j]>>33]&FATHER) - { - s[0]++; - } - - if(R_INF.trio_flag[w->a[j]>>33]&MOTHER) - { - s[1]++; - } - } - } - - if(s[0] >= s[1]) - { - flag = MOTHER; - } - else - { - flag = FATHER; - } - for (k = 0; k < u->n; k++) - { - if(R_INF.trio_flag[u->a[k]>>33]&SET_TRIO) continue; - if(cov->t_ch->ir_het[u->a[k]>>33] == N_HET) continue; - R_INF.trio_flag[u->a[k]>>33] |= flag; - } - } - - - for (i = 0, idx.n = 0; i < ta->idx.n; i++) - { - qn = i; - u = &(ug->u.a[qn]); - for (k = 0; k < u->n; k++) - { - if(R_INF.trio_flag[u->a[k]>>33]&FATHER) - { - R_INF.trio_flag[u->a[k]>>33] = FATHER; - } - else if(R_INF.trio_flag[u->a[k]>>33]&MOTHER) - { - R_INF.trio_flag[u->a[k]>>33] = MOTHER; - } - else - { - R_INF.trio_flag[u->a[k]>>33] = AMBIGU; - } - } - } - kv_destroy(idx); -} - - - -uint64_t get_utg_cov(ma_ug_t *ug, uint32_t uID, asg_t* read_g, -const ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag) -{ - ma_utg_t *u = &(ug->u.a[uID]); - uint32_t k, j, rId, tn, is_Unitig; - long long R_bases = 0, C_bases = 0; - long long cov_in, cov_out; - uint32_t nv, i; - asg_arc_t *av = NULL; - ma_hit_t *h; - if(u->m == 0 || ug->g->seq[uID].del) return 0; - ///set - for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 1; - for (i = 0; i < 2; i++) - { - nv = asg_arc_n(ug->g, (uID<<1)+i); - av = asg_arc_a(ug->g, (uID<<1)+i); - for (j = 0; j < nv; j++) - { - if(av[j].del) continue; - u = &(ug->u.a[av[j].v>>1]); - for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 2; - } - } - - u = &(ug->u.a[uID]); - cov_in = cov_out = R_bases = 0; - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - R_bases += (coverage_cut[rId].e - coverage_cut[rId].s); - for (j = 0; j < (uint64_t)(sources[rId].length); j++) - { - h = &(sources[rId].buffer[j]); - ///if(h->del) continue; - if(h->el != 1) continue; - tn = Get_tn((*h)); - if(read_g->seq[tn].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - if(read_g->seq[tn].del == 1) continue; - if(r_flag[tn] == 0) continue; - if(r_flag[tn] == 1) cov_in += (Get_qe((*h)) - Get_qs((*h))); - if(r_flag[tn] == 2) cov_out += (Get_qe((*h)) - Get_qs((*h))); - } - } - C_bases = cov_in; - if(cov_out <= (cov_in*0.2)) C_bases += cov_out; - - ///reset - for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 0; - - for (i = 0; i < 2; i++) - { - nv = asg_arc_n(ug->g, (uID<<1)+i); - av = asg_arc_a(ug->g, (uID<<1)+i); - for (j = 0; j < nv; j++) - { - u = &(ug->u.a[av[j].v>>1]); - for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 0; - } - } - - return R_bases == 0? 0 : C_bases/R_bases; -} - -void kt_u_trans_t_idx(kv_u_trans_t *ta, uint32_t n) -{ - radix_sort_u_trans(ta->a, ta->a + ta->n); - kv_resize(uint64_t, ta->idx, n); - ta->idx.n = n; - memset(ta->idx.a, 0, ta->idx.n*sizeof(uint64_t)); - uint32_t st, i; - for (st = 0, i = 1; i <= ta->n; ++i) - { - if (i == ta->n || ta->a[i].qn != ta->a[st].qn) - { - ta->idx.a[ta->a[st].qn] = (uint64_t)st << 32 | (i - st); - st = i; - } - } -} - -uint32_t get_u_trans_spec(kv_u_trans_t *ta, uint32_t qn, uint32_t tn, u_trans_t **r_a, uint32_t *occ) -{ - if(r_a) (*r_a) = NULL; - if(occ) (*occ) = 0; - u_trans_t *a = NULL; - uint32_t n, st, i; - a = u_trans_a(*ta, qn); - n = u_trans_n(*ta, qn); - for (st = 0, i = 1; i <= n; ++i) - { - if (i == n || a[i].tn != a[st].tn) - { - if(a[st].tn == tn) - { - if(r_a) (*r_a) = a + st; - if(occ) (*occ) = i - st; - return 1; - } - st = i; - } - } - return 0; -} - -double merge_u_trans(u_trans_t *a, uint32_t occ, ma_ug_t *ug) -{ - radix_sort_u_trans_qs(a, a+occ); - uint32_t i, k, ov_q, ov_t, is_found = 1, ts, te; - double w_q, w_s; - u_trans_t *p = NULL; - - for (i = 0; i < occ; i++) - { - if(a[i].del || a[i].rev == 0) continue; - ts = a[i].ts; te = a[i].te - 1; - a[i].ts = ug->g->seq[a[i].tn].len - te - 1; - a[i].te = ug->g->seq[a[i].tn].len - ts - 1 + 1; - } - - - while (is_found) - { - for (i = is_found = 0; i < occ; i++) - { - if(a[i].del) continue; - p = &(a[i]); - for (k = i+1; k < occ; k++) - { - if(a[k].del) continue; - if(p->qe < a[k].qs) break; - - if(p->qe >= a[k].qs && p->te >= a[k].ts) - { - ov_q = ((MIN(p->qe, a[k].qe) > MAX(p->qs, a[k].qs))? - MIN(p->qe, a[k].qe) - MAX(p->qs, a[k].qs):0); - ov_t = ((MIN(p->te, a[k].te) > MAX(p->ts, a[k].ts))? - MIN(p->te, a[k].te) - MAX(p->ts, a[k].ts):0); - - ov_q = a[k].qe - a[k].qs - ov_q; - ov_t = a[k].te - a[k].ts - ov_t; - - w_q = ((double)ov_q/(double)(a[k].qe - a[k].qs)) * a[k].nw; - w_s = ((double)ov_t/(double)(a[k].te - a[k].ts)) * a[k].nw; - - p->qe = MAX(p->qe, a[k].qe); - p->te = MAX(p->te, a[k].te); - p->nw += MIN(w_q, w_s); - is_found = 1; - a[k].del = 1; - } - } - } - for (i = k = 0; i < occ; i++) - { - if(a[i].del) continue; - a[k] = a[i]; - k++; - } - occ = k; - } - - - for (i = 0; i < occ; i++) - { - if(a[i].del) continue; - p = &(a[i]); - for (k = i+1; k < occ; k++) - { - if(a[k].del) continue; - ov_q = ((MIN(p->qe, a[k].qe) > MAX(p->qs, a[k].qs))? - MIN(p->qe, a[k].qe) - MAX(p->qs, a[k].qs):0); - - if(ov_q == 0) break; - if(ov_q == (a[k].qe-a[k].qs)) - { - a[k].del = 1; - continue; - } - if(ov_q == (p->qe - p->qs)) - { - p->del = 1; - continue; - } - ov_t = get_offset_adjust(ov_q, a[k].qe-a[k].qs, a[k].te-a[k].ts); - a[k].qs += ov_q; a[k].ts += ov_t; - a[k].nw -= ((double)ov_q/(double)(a[k].qe - a[k].qs)) * a[k].nw; - } - } - for (i = k = 0; i < occ; i++) - { - if(a[i].del) continue; - a[k] = a[i]; - k++; - } - occ = k; - - - - - radix_sort_u_trans_ts(a, a+occ); - for (i = 0; i < occ; i++) - { - if(a[i].del) continue; - p = &(a[i]); - for (k = i+1; k < occ; k++) - { - if(a[k].del) continue; - ov_t = ((MIN(p->te, a[k].te) > MAX(p->ts, a[k].ts))? - MIN(p->te, a[k].te) - MAX(p->ts, a[k].ts):0); - - if(ov_t == 0) break; - if(ov_t == (a[k].te-a[k].ts)) - { - a[k].del = 1; - continue; - } - if(ov_t == (p->te - p->ts)) - { - p->del = 1; - continue; - } - ov_q = get_offset_adjust(ov_t, a[k].te-a[k].ts, a[k].qe-a[k].qs); - a[k].ts += ov_t; a[k].qs += ov_q; - a[k].nw -= ((double)ov_t/(double)(a[k].te - a[k].ts)) * a[k].nw; - } - } - for (i = k = 0, w_q = 0; i < occ; i++) - { - if(a[i].del) continue; - w_q += a[i].nw; - a[k] = a[i]; - k++; - } - occ = k; - - - for (i = 0; i < occ; i++) - { - if(a[i].del || a[i].rev == 0) continue; - ts = a[i].ts; te = a[i].te - 1; - a[i].ts = ug->g->seq[a[i].tn].len - te - 1; - a[i].te = ug->g->seq[a[i].tn].len - ts - 1 + 1; - } - - return w_q; -} - -void kt_u_trans_t_symm(kv_u_trans_t *ta, ma_ug_t *ug) -{ - u_trans_t *a = NULL, *r_a = NULL, *p = NULL; - uint32_t k, n, r_n, st, i, m; - double w0, w1; - kvec_t(u_trans_t) e0; kv_init(e0); - kvec_t(u_trans_t) e1; kv_init(e1); - for (k = 0; k < ta->idx.n; k++) - { - a = u_trans_a(*ta, k); - n = u_trans_n(*ta, k); - for (st = 0, i = 1; i <= n; ++i) - { - if (i == n || a[i].tn != a[st].tn) - { - get_u_trans_spec(ta, a[st].tn, a[st].qn, &r_a, &r_n); - if(i == st + 1 && r_n == 0) {///should be always here - st = i; - continue; - } - - e0.n = e1.n = 0; - for (m = st; m < i; m++) { - if(a[m].del) continue; - if(a[m].rev) { - kv_push(u_trans_t, e1, a[m]); - } else { - kv_push(u_trans_t, e0, a[m]); - } - } - - for (m = 0; m < r_n; m++) { - if(r_a[m].del) continue; - if(r_a[m].rev) { - kv_pushp(u_trans_t, e1, &p); - } else { - kv_pushp(u_trans_t, e0, &p); - } - (*p) = r_a[m]; - p->qn = r_a[m].tn; p->qs = r_a[m].ts; p->qe = r_a[m].te; - p->tn = r_a[m].qn; p->ts = r_a[m].qs; p->te = r_a[m].qe; - } - - - if(e0.n + e1.n > 1) { - ///must be here - for (m = st; m < i; m++) a[m].del = 1; - for (m = 0; m < r_n; m++) r_a[m].del = 1; - - w0 = merge_u_trans(e0.a, e0.n, ug); - w1 = merge_u_trans(e1.a, e1.n, ug); - if(w0 >= w1) - { - for (m = 0; m < e0.n; m++) - { - kv_push(u_trans_t, *ta, e0.a[m]); - } - } - else - { - for (m = 0; m < e1.n; m++) - { - kv_push(u_trans_t, *ta, e1.a[m]); - } - } - } - st = i; - } - } - - } - kv_destroy(e0); - kv_destroy(e1); - for (i = m = 0; i < ta->n; ++i) - { - if(ta->a[i].del) continue; - ta->a[m] = ta->a[i]; - m++; - } - ta->n = m; - n = ta->n; - for (i = 0; i < n; ++i) - { - if(ta->a[i].del) continue; - kv_pushp(u_trans_t, *ta, &p); - (*p) = ta->a[i]; - p->qn = ta->a[i].tn; p->qs = ta->a[i].ts; p->qe = ta->a[i].te; - p->tn = ta->a[i].qn; p->ts = ta->a[i].qs; p->te = ta->a[i].qe; - } - kt_u_trans_t_idx(ta, ug->g->n_seq); -} - - -void kt_u_trans_t_simple_symm(kv_u_trans_t *ta, uint32_t un, uint32_t symm_add) -{ - u_trans_t *a = NULL, *r_a = NULL, *p = NULL; - uint32_t k, n, m; - n = ta->n; - for (k = 0; k < n; k++) - { - if(ta->a[k].del || ta->a[k].qn > ta->a[k].tn) continue; - get_u_trans_spec(ta, ta->a[k].tn, ta->a[k].qn, &r_a, NULL); - a = &(ta->a[k]); - if(!r_a || r_a->del) - { - if(symm_add) kv_pushp(u_trans_t, *ta, &r_a); - else - { - a->del = 1; - continue; - } - } - else - { - if(r_a->nw > a->nw) - { - p = a; - a = r_a; - r_a = p; - } - } - (*r_a) = (*a); - r_a->qn = a->tn; r_a->qs = a->ts; r_a->qe = a->te; - r_a->tn = a->qn; r_a->ts = a->qs; r_a->te = a->qe; - } - - for (k = m = 0; k < ta->n; ++k) - { - if(ta->a[k].del) continue; - ta->a[m] = ta->a[k]; - m++; - } - ta->n = m; - kt_u_trans_t_idx(ta, un); -} - -void debug_u_trans_t(kv_u_trans_t *ta) -{ - u_trans_t *a = NULL, *r_a = NULL; - uint32_t i, k, m, j, st, n, r_n, ovlp; - for (i = 0; i < ta->n; ++i) - { - if(ta->a[i].nw <= 0) fprintf(stderr, "ERROR-1\n"); - if(ta->a[i].qe <= ta->a[i].qs) fprintf(stderr, "ERROR-2\n"); - if(ta->a[i].te <= ta->a[i].ts) fprintf(stderr, "ERROR-3\n"); - } - for (k = 0; k < ta->idx.n; k++) - { - a = u_trans_a(*ta, k); - n = u_trans_n(*ta, k); - for (st = 0, i = 1; i <= n; ++i) - { - if (i == n || a[i].tn != a[st].tn) - { - get_u_trans_spec(ta, a[st].tn, a[st].qn, &r_a, &r_n); - - if(i - st != r_n) - { - fprintf(stderr, "ERROR-4, i - st: %u, r_n: %u\n", i - st, r_n); - } - - for (m = st; m < i; m++) - { - if(a[m].rev != a[st].rev) fprintf(stderr, "ERROR-5\n"); - for (j = st; j < i; j++) - { - if(j == m) continue; - - ovlp = ((MIN(a[m].qe, a[j].qe) > MAX(a[m].qs, a[j].qs))? - MIN(a[m].qe, a[j].qe) - MAX(a[m].qs, a[j].qs):0); - if(ovlp > 0) fprintf(stderr, "ERROR-6\n"); - - ovlp = ((MIN(a[m].te, a[j].te) > MAX(a[m].ts, a[j].ts))? - MIN(a[m].te, a[j].te) - MAX(a[m].ts, a[j].ts):0); - if(ovlp > 0) fprintf(stderr, "ERROR-7\n"); - } - - for (j = 0; j < r_n; j++) - { - if(r_a[j].rev != a[m].rev) fprintf(stderr, "ERROR-8\n"); - if(r_a[j].tn == a[m].qn && r_a[j].qn == a[m].tn && - r_a[j].ts == a[m].qs && r_a[j].te == a[m].qe && - r_a[j].qs == a[m].ts && r_a[j].qe == a[m].te && - r_a[j].nw == a[m].nw) - { - break; - } - } - if(j >= r_n) fprintf(stderr, "ERROR-9\n"); - - } - st = i; - } - } - } -} - - -void filter_u_trans_t(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, uint32_t thres) -{ - u_trans_t *a = NULL, *r_a = NULL; - ma_utg_t *u = NULL; - uint32_t i, k, m, j, st, n, r_n; - uint64_t offset, r_beg, r_end, ovlp, min, max, pass; - kvec_t(uint32_t) cnt; kv_init(cnt); - for (k = 0; k < ta->idx.n; k++) - { - a = u_trans_a(*ta, k); - n = u_trans_n(*ta, k); - if(n == 0) continue; - kv_resize(uint32_t, cnt, n); cnt.n = n; - min = a[0].qs; max = a[0].qe; - for (i = 0; i < n; i++) - { - cnt.a[i] = 0; - min = MIN(min, a[i].qs); - max = MAX(max, a[i].qe); - } - - - u = &(ug->u.a[k]); pass = 0; - for (j = 0, offset = 0; j < u->n; j++) - { - pass = 0; - r_beg = offset; r_end = offset + read_g->seq[u->a[j]>>33].len; - offset += (uint32_t)u->a[j]; - if(min >= r_end) continue; - if(max <= r_beg) break; - for (i = 0; i < n; i++) - { - if(cnt.a[i] >= thres || r_beg >= a[i].qe) - { - pass++; - continue; - } - ovlp = ((MIN(r_end, a[i].qe) > MAX(r_beg, a[i].qs))? - MIN(r_end, a[i].qe) - MAX(r_beg, a[i].qs):0); - if(ovlp == (r_end - r_beg)) - { - cnt.a[i]++; - if(cnt.a[i] >= thres) pass++; - } - } - - if(pass == n) - { - for (i = 0; i < n; i++) - { - if(cnt.a[i] < thres) a[i].del = 1; - } - break; - } - } - - if(pass < n) - { - for (i = 0; i < n; i++) - { - if(cnt.a[i] < thres) a[i].del = 1; - } - } - } - kv_destroy(cnt); - - for (k = 0; k < ta->idx.n; k++) - { - a = u_trans_a(*ta, k); - n = u_trans_n(*ta, k); - for (st = 0, i = 1; i <= n; ++i) - { - if (i == n || a[i].tn != a[st].tn)///same qn && tn - { - get_u_trans_spec(ta, a[st].tn, a[st].qn, &r_a, &r_n); - - for (m = st; m < i; m++) - { - if(!a[m].del) continue; - - for (j = 0; j < r_n; j++) - { - if(r_a[j].tn == a[m].qn && r_a[j].qn == a[m].tn && - r_a[j].ts == a[m].qs && r_a[j].te == a[m].qe && - r_a[j].qs == a[m].ts && r_a[j].qe == a[m].te && - r_a[j].nw == a[m].nw && r_a[j].rev == a[m].rev) - { - r_a[j].del = 1; - break; - } - } - } - st = i; - } - } - } - /*******************************for debug************************************/ - // for (i = 0; i < ta->n; ++i) - // { - // uint32_t c_q = 0, c_t = 0, s, e; - // u = &(ug->u.a[ta->a[i].qn]); s = ta->a[i].qs; e = ta->a[i].qe; - // for (j = 0, offset = 0; j < u->n; j++) - // { - // r_beg = offset; r_end = offset + read_g->seq[u->a[j]>>33].len; - // offset += (uint32_t)u->a[j]; - - // ovlp = ((MIN(r_end, e) > MAX(r_beg, s))? MIN(r_end, e) - MAX(r_beg, s):0); - // if(ovlp == (r_end - r_beg)) - // { - // c_q++; - // if(c_q >= thres) break; - // } - // } - - - // u = &(ug->u.a[ta->a[i].tn]); s = ta->a[i].ts; e = ta->a[i].te; - // for (j = 0, offset = 0; j < u->n; j++) - // { - // r_beg = offset; r_end = offset + read_g->seq[u->a[j]>>33].len; - // offset += (uint32_t)u->a[j]; - - // ovlp = ((MIN(r_end, e) > MAX(r_beg, s))? MIN(r_end, e) - MAX(r_beg, s):0); - // if(ovlp == (r_end - r_beg)) - // { - // c_t++; - // if(c_t >= thres) break; - // } - // } - - // if(ta->a[i].del && (c_q >= thres && c_t >= thres)) fprintf(stderr, "ERROR\n"); - // if(!ta->a[i].del && (c_q < thres || c_t < thres)) fprintf(stderr, "ERROR\n"); - // } - /*******************************for debug************************************/ - - for (i = m = 0; i < ta->n; ++i) - { - if(ta->a[i].del) continue; - ta->a[m] = ta->a[i]; - m++; - } - ta->n = m; - kt_u_trans_t_idx(ta, ug->g->n_seq); -} - -void clean_u_trans_t_idx(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g) -{ - // dbg_prt_utg_trans(ta, ug, "pre"); - kt_u_trans_t_idx(ta, ug->g->n_seq); - kt_u_trans_t_symm(ta, ug); - filter_u_trans_t(ta, ug, read_g, 3); - ///debug_u_trans_t(ta); - // dbg_prt_utg_trans(ta, ug, "after"); -} - -void gen_bp_phasing(ug_opt_t *opt, kv_u_trans_t *ta, ma_ug_t *ug, asg_t *sg) -{ - uint8_t *bf = NULL; - bubble_type *bub = gen_bubble_chain(sg, ug, opt, &bf, 0); free(bf); - filter_u_trans(ta, asm_opt.is_bub_trans, asm_opt.is_topo_trans, asm_opt.is_read_trans, asm_opt.is_base_trans); - // dbg_prt_utg_trans(ta, ug, "pre"); - if(asm_opt.is_base_trans) { - trans_base_infer(ug, sg, opt, ta, bub); - } - // dbg_prt_utg_trans(ta, ug, "after"); - clean_u_trans_t_idx_filter_adv(ta, ug, sg, 0.95, 0); - - - bp_solve(opt, ta, ug, sg, bub, asm_opt.trans_base_rate); - - destory_bubbles(bub); free(bub); -} - - -void output_bp_graph_adv(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, -R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, -int gap_fuzz, bub_label_t* b_mask_t, ug_opt_t *opt) -{ - hic_clean(sg); - - kvec_asg_arc_t_warp new_rtg_edges, d_edges; - kv_init(new_rtg_edges.a); kv_init(d_edges.a); - ma_ug_t *ug = NULL; - ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); - - new_rtg_edges.a.n = 0; - ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, &d_edges, 1);///polish - - new_rtg_edges.a.n = 0; - hap_cov_t *cov = NULL; - asg_t *copy_sg = copy_read_graph(sg); - ma_ug_t *copy_ug = copy_untig_graph(ug); - /*******************************for debug************************************/ - adjust_utg_by_primary(©_ug, copy_sg, TRIO_THRES, sources, reverse_sources, coverage_cut, - tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, - max_hang, min_ovlp, &new_rtg_edges, &cov, b_mask_t, 1, 0/**1**/); - // adjust_utg_advance(copy_sg, copy_ug, reverse_sources, ruIndex, b_mask_t); - // get_utg_ovlp(©_ug, copy_sg, sources, reverse_sources, coverage_cut, - // ruIndex, max_hang, min_ovlp, &new_rtg_edges, b_mask_t, NULL); - // exit(1); - /*******************************for debug************************************/ - print_utg(©_ug, copy_sg, coverage_cut, output_file_name, sources, ruIndex, max_hang, - min_ovlp, &new_rtg_edges); - ma_ug_destroy(copy_ug); - asg_destroy(copy_sg); - - // gen_bp_phasing(opt, &(cov->t_ch->k_trans), ug, sg); - clean_u_trans_t_idx(&(cov->t_ch->k_trans), ug, sg); - set_trio_flag_by_cov(ug, sg, cov); - - //for debug - // char* gfa_name = (char*)malloc(strlen(output_file_name)+50); - // sprintf(gfa_name, "%s.pre.clean_d_utg.noseq.gfa", output_file_name); - // FILE* output_file = fopen(gfa_name, "w"); - // ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - // fclose(output_file); - // free(gfa_name); - // exit(1); - //for debug - - - // print_untig_by_read(copy_ug, "m64011_190830_220126/88867583/ccs", 603738, NULL, NULL, "sb"); - - ///debug_gfa_space(ug, cov); - - - // print_r_het(cov, R_INF.trio_flag, "out-1"); - // print_debug_gfa(ug, sg, coverage_cut, output_file_name, sources, ruIndex); - - destory_hap_cov_t(&cov); - ma_ug_destroy(ug); - kv_destroy(new_rtg_edges.a); - - asg_arc_t* av = NULL; - uint32_t v, w, k, i, nv; - for (i = 0; i < d_edges.a.n; i++) - { - v = d_edges.a.a[i].ul>>32; - w = d_edges.a.a[i].v; - av = asg_arc_a(sg, v); - nv = asg_arc_n(sg, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - av[k].del = 1; - break; - } - } - } - kv_destroy(d_edges.a); - asg_cleanup(sg); - - - output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, - 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, 0, b_mask_t, NULL, NULL, NULL); - output_trio_unitig_graph(sg, coverage_cut, output_file_name, MOTHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, - 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, 0, b_mask_t, NULL, NULL, NULL); -} - -void output_bp_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, long long stops_threshold, -R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, bub_label_t* b_mask_t, -long long gap_fuzz, ug_opt_t *opt) -{ - hic_clean(sg); - kvec_asg_arc_t_warp new_rtg_edges; - kv_init(new_rtg_edges.a); - ma_ug_t *ug = NULL; - ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); - - hap_cov_t *cov = NULL; - asg_t *copy_sg = copy_read_graph(sg); - ma_ug_t *copy_ug = copy_untig_graph(ug); - /*******************************for debug************************************/ - adjust_utg_by_primary(©_ug, copy_sg, TRIO_THRES, sources, reverse_sources, coverage_cut, - tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, - max_hang, min_ovlp, &new_rtg_edges, &cov, b_mask_t, 1, 1); - // adjust_utg_advance(copy_sg, copy_ug, reverse_sources, ruIndex, b_mask_t); - // get_utg_ovlp(©_ug, copy_sg, sources, reverse_sources, coverage_cut, - // ruIndex, max_hang, min_ovlp, &new_rtg_edges, b_mask_t, NULL); - // exit(1); - /*******************************for debug************************************/ - print_utg(©_ug, copy_sg, coverage_cut, output_file_name, sources, ruIndex, max_hang, - min_ovlp, &new_rtg_edges); - ma_ug_destroy(copy_ug); - asg_destroy(copy_sg); - - clean_u_trans_t_idx(&(cov->t_ch->k_trans), ug, sg); - // print_untig_by_read(copy_ug, "m64011_190830_220126/88867583/ccs", 603738, NULL, NULL, "sb"); - - ///debug_gfa_space(ug, cov); - - set_trio_flag_by_cov(ug, sg, cov); - // print_r_het(cov, R_INF.trio_flag, "out-1"); - // print_debug_gfa(ug, sg, coverage_cut, output_file_name, sources, ruIndex); - // exit(1); - - destory_hap_cov_t(&cov); - ma_ug_destroy(ug); - kv_destroy(new_rtg_edges.a); - - // reduce_hamming_error_adv(NULL, sg, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz, opt->ruIndex, NULL); - - // output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, - // 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, 0, b_mask_t, NULL, NULL, NULL); - // output_trio_unitig_graph(sg, coverage_cut, output_file_name, MOTHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, - // 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, 0, b_mask_t, NULL, NULL, NULL); - - output_trio_graph_joint(sg, coverage_cut, output_file_name, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, - 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, b_mask_t, NULL, NULL, opt); -} - -void output_bp_trio_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, long long stops_threshold, -R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, bub_label_t* b_mask_t, -long long gap_fuzz, ug_opt_t *opt) -{ - hic_clean(sg); - - kvec_asg_arc_t_warp new_rtg_edges; - kv_init(new_rtg_edges.a); - ma_ug_t *ug = NULL; - ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); - - hap_cov_t *cov = NULL; - trans_chain* t_ch = NULL; - if((asm_opt.flag & HA_F_VERBOSE_GFA)) t_ch = load_hc_trans(output_file_name); - - if(!t_ch) { - new_rtg_edges.a.n = 0; - asg_t *copy_sg = copy_read_graph(sg); - ma_ug_t *copy_ug = copy_untig_graph(ug); - ///asm_opt.purge_overlap_len = asm_opt.purge_overlap_len_hic; - ///asm_opt.purge_simi_thres = asm_opt.purge_simi_rate_hic; - adjust_utg_by_primary(©_ug, copy_sg, TRIO_THRES, sources, reverse_sources, coverage_cut, - tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, - max_hang, min_ovlp, &new_rtg_edges, &cov, b_mask_t, 1, 0); - - ma_ug_destroy(copy_ug); - asg_destroy(copy_sg); - - if((asm_opt.flag & HA_F_VERBOSE_GFA)) write_trans_chain(cov->t_ch, output_file_name); - } - - // clean_u_trans_t_idx_filter_adv(&(cov?cov->t_ch->k_trans:t_ch->k_trans), ug, sg); - trio_phasing_refine(ug, sg, cov?&(cov->t_ch->k_trans):&(t_ch->k_trans), opt); - - if(cov) destory_hap_cov_t(&cov); - if(t_ch) destory_trans_chain(&t_ch); - - - // char* gfa_name = (char*)malloc(strlen(output_file_name)+50); - // sprintf(gfa_name, "%s.after.clean_d_utg.noseq.gfa", output_file_name); - // FILE* output_file = fopen(gfa_name, "w"); - // ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - // fclose(output_file); - // free(gfa_name); - - - - ma_ug_destroy(ug); - kv_destroy(new_rtg_edges.a); - - - output_trio_graph_joint(sg, coverage_cut, output_file_name, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, - 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, b_mask_t, NULL, NULL, opt); -} - -ma_ug_t* merge_utg(ma_ug_t **dest, ma_ug_t **src) -{ - asg_t *g_d = (*dest)->g, *g_s = (*src)->g; - uint64_t occ_d = g_d->n_seq, occ_s = g_s->n_seq, i; - asg_arc_t *p = NULL; - g_d->is_srt = g_d->is_symm = 0; - - for (i = 0; i < occ_s; i++) - { - asg_seq_set(g_d, i+occ_d, g_s->seq[i].len, g_s->seq[i].del); - g_d->seq[i+occ_d].c = g_s->seq[i].c; - } - - g_d->seq_vis = (uint8_t*)realloc(g_d->seq_vis, g_d->n_seq*2*sizeof(uint8_t)); - - - for (i = 0; i < g_s->n_arc; i++) - { - p = asg_arc_pushp(g_d); - (*p) = g_s->arc[i]; - p->ul += (occ_d<<33); - p->v += (occ_d<<1); - } - - asg_cleanup(g_d); - g_d->r_seq = g_d->n_seq; - - if(g_s->n_F_seq > 0 && g_s->F_seq) - { - uint64_t n_F_seq = g_d->n_F_seq + g_s->n_F_seq; - g_d->F_seq = (ma_utg_t*)realloc(g_d->F_seq, n_F_seq*sizeof(ma_utg_t)); - memcpy(g_d->F_seq + g_d->n_F_seq, g_s->F_seq, g_s->n_F_seq*sizeof(ma_utg_t)); - g_d->n_F_seq = n_F_seq; - free(g_s->F_seq); - g_s->F_seq = NULL; - g_s->n_F_seq = 0; - } - - ma_utg_v *u_d = &((*dest)->u), *u_s = &((*src)->u); - if(u_s->n > 0) - { - uint64_t n = u_d->n + u_s->n; - u_d->a = (ma_utg_t*)realloc(u_d->a, n*sizeof(ma_utg_t)); - memcpy(u_d->a + u_d->n, u_s->a, u_s->n*sizeof(ma_utg_t)); - u_d->n = u_d->m = n; - free(u_s->a); - u_s->a = NULL; - u_s->n = u_s->m = 0; - } - - kv_push(uint64_t, (*dest)->occ, occ_d); - kv_push(uint64_t, (*dest)->occ, occ_s); - - ma_ug_destroy(*src); - return (*dest); -} - -void benchmark_hic_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, -float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, int gap_fuzz, bub_label_t* b_mask_t) -{ - ma_ug_t *ug_1 = output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, - reverse_sources, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, - chimeric_rate, drop_ratio, max_hang, min_ovlp, gap_fuzz, 1, b_mask_t, NULL, NULL, NULL); - - ma_ug_t *ug_2 = output_trio_unitig_graph(sg, coverage_cut, output_file_name, MOTHER, sources, - reverse_sources, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, - chimeric_rate, drop_ratio, max_hang, min_ovlp, gap_fuzz, 1, b_mask_t, NULL, NULL, NULL); - fprintf(stderr, "ug_1->u.n: %u, ug_2->u.n: %u\n", (uint32_t)ug_1->u.n, (uint32_t)ug_2->u.n); - ma_ug_t *ug = merge_utg(&ug_1, &ug_2); - fprintf(stderr, "ug->u.n: %u\n", (uint32_t)ug->u.n); - - hic_benchmark(ug, sg); - - ma_ug_destroy(ug); -} - -void merge_unitig_content(ma_utg_t* collection, ma_ug_t* ug, asg_t* read_g, kvec_asg_arc_t_warp* edge) -{ - if(collection->m == 0) return; - uint32_t i, j, index = 0, uId, ori; - uint64_t totalLen; - ma_utg_t* query = NULL; - for (i = 0; i < collection->n; i++) - { - uId = collection->a[i]>>33; - ori = collection->a[i]>>32&1; - query = &(ug->u.a[uId]); - index += query->n; - } - - uint64_t* buffer = (uint64_t*)malloc(sizeof(uint64_t)*index); - uint64_t* aim = NULL; - index = 0; - for (i = 0; i < collection->n; i++) - { - uId = collection->a[i]>>33; - ori = collection->a[i]>>32&1; - query = &(ug->u.a[uId]); - aim = buffer + index; - if(ori == 1) - { - for (j = 0; j < query->n; j++) - { - aim[query->n - j - 1] = (query->a[j])^(uint64_t)(0x100000000); - } - } - else - { - for (j = 0; j < query->n; j++) - { - aim[j] = query->a[j]; - } - } - index += query->n; - free(query->a);query->m=0;query->a=NULL; - } - - if(index == 0) return; - - ///fill_unitig(buffer, index, read_g, edge, collection->circ, &totalLen); - fill_unitig(buffer, index, read_g, edge, /**collection->circ**/ - (collection->n == 1 && ug->u.a[collection->a[0]>>33].circ), &totalLen); - - ///important. must be here - if(collection->n == 1 && ug->u.a[collection->a[0]>>33].circ) collection->circ = 1; - - free(collection->a); - collection->a = buffer; - collection->n = collection->m = index; - collection->len = totalLen; - if(!collection->circ) - { - collection->start = collection->a[0]>>32; - collection->end = (collection->a[collection->n-1]>>32)^1; - } - else - { - collection->start = collection->end = UINT32_MAX; - } - - -} - -void print_unitig(ma_utg_t* collection, ma_ug_t* ug) -{ - if(collection->m == 0) return; - uint32_t i, index = 0, uId, ori, l; - ma_utg_t* query = NULL; - for (i = 0; i < collection->n; i++) - { - uId = collection->a[i]>>33; - ori = collection->a[i]>>32&1; - l = (uint32_t)(collection->a[i]); - fprintf(stderr, "i: %u, uId: %u, ori: %u, l: %u\n", i, uId, ori, l); - if(ug) - { - query = &(ug->u.a[uId]); - index += query->n; - } - } - fprintf(stderr, "index: %u\n", index); -} - - -void print_specfic_read_ovlp(uint32_t Rid, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -const char* command) -{ - long long j, i = Rid; - uint32_t tn; - - - fprintf(stderr, "\n\n\nafter %s\n", command); - - fprintf(stderr, "****************ma_hit_t (%lld)ref_read: %.*s****************\n", - i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); - - - fprintf(stderr, "sources Len: %d, is_fully_corrected: %d\n", - sources[i].length, sources[i].is_fully_corrected); - - for (j = 0; j < sources[i].length; j++) - { - tn = Get_tn(sources[i].buffer[j]); - fprintf(stderr, "target: %.*s, qs: %u, qe: %u, ts: %u, te: %u, ml: %u, rev: %u, el: %u, del: %u\n", - (int)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), - Get_qs(sources[i].buffer[j]), - Get_qe(sources[i].buffer[j]), - Get_ts(sources[i].buffer[j]), - Get_te(sources[i].buffer[j]), - sources[i].buffer[j].ml, - sources[i].buffer[j].rev, - sources[i].buffer[j].el, - (uint32_t)sources[i].buffer[j].del); - } - - - - fprintf(stderr, "######reverse_query_read Len: %d\n", reverse_sources[i].length); - - - - for (j = 0; j < reverse_sources[i].length; j++) - { - tn = Get_tn(reverse_sources[i].buffer[j]); - fprintf(stderr, "target: %.*s, qs: %u, qe: %u, ts: %u, te: %u, del: %u\n", - (int)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), - Get_qs(reverse_sources[i].buffer[j]), - Get_qe(reverse_sources[i].buffer[j]), - Get_ts(reverse_sources[i].buffer[j]), - Get_te(reverse_sources[i].buffer[j]), - (uint32_t)sources[i].buffer[j].del); - } - - - - - fflush(stderr); - - -} - - -uint32_t print_debug_gfa(asg_t *read_g, ma_ug_t *ug, ma_sub_t* coverage_cut, const char* output_file_name, -ma_hit_t_alloc* sources, R_to_U* ruIndex, int max_hang, int min_ovlp, int is_update_ou, int is_check_alter_lable, int is_seq) -{ - kvec_asg_arc_t_warp new_rtg_edges; - uint32_t free_ug = ((ug == NULL)?1:0); - kv_init(new_rtg_edges.a); - - if(ug == NULL) { - ug = ma_ug_gen(read_g); - } else if(is_check_alter_lable) { - uint32_t i; - for (i = 0; i < ug->u.n; ++i) - { - ma_utg_t *u = &ug->u.a[i]; - if(u->m == 0 || ug->g->seq[i].c == ALTER_LABLE) - { - asg_seq_del(ug->g, i); - if(ug->u.a[i].m!=0) - { - ug->u.a[i].m = ug->u.a[i].n = 0; - free(ug->u.a[i].a); - ug->u.a[i].a = NULL; - } - } - } - } - - if(is_update_ou) update_ug_ou(ug, read_g); - if(is_seq) { - ma_ug_seq(ug, read_g, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 0); - } - // if(is_polish) ma_ug_seq(ug, read_g, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 0); - - fprintf(stderr, "Writing raw unitig GFA to disk... \n"); - char* gfa_name = (char*)malloc(strlen(output_file_name)+50); - FILE* output_file = NULL; - - if(is_seq) { - sprintf(gfa_name, "%s.r_utg.gfa", output_file_name); - output_file = fopen(gfa_name, "w"); - ma_ug_print(ug, read_g, coverage_cut, sources, ruIndex, "utg", output_file); - } else { - sprintf(gfa_name, "%s.r_utg.noseq.gfa", output_file_name); - output_file = fopen(gfa_name, "w"); - ma_ug_print_simple(ug, read_g, coverage_cut, sources, ruIndex, "utg", output_file); - } - fclose(output_file); - - free(gfa_name); - if(free_ug) ma_ug_destroy(ug); - kv_destroy(new_rtg_edges.a); - // exit(0); - return 1; -} - - -uint32_t print_untig_by_read(ma_ug_t *g, const char* name, uint32_t in, ma_hit_t_alloc* sources, -ma_hit_t_alloc* reverse_sources, const char* info) -{ - uint32_t i, k, rId = (uint32_t)-1, flag = 0; - if(in != (uint32_t)-1) - { - rId = in; - } - else - { - for (i = 0; i < R_INF.total_reads; ++i) - { - if(Get_NAME_LENGTH(R_INF, i) != strlen(name)) continue; - if(memcmp(name, Get_NAME(R_INF, i), Get_NAME_LENGTH(R_INF, i)) == 0) - { - fprintf(stderr, "%s: i: %u, >%.*s\n", info, i, - (int)Get_NAME_LENGTH((R_INF), i), Get_NAME((R_INF), i)); - rId = i; - break; - } - } - } - - - - if(rId == (uint32_t)-1) - { - fprintf(stderr, "%s: Cannot find %s\n", info, name); - return (uint32_t)-1; - } - - if(sources && reverse_sources) print_specfic_read_ovlp(rId, sources, reverse_sources, info); - - if(g != NULL) - { - for (i = 0; i < g->u.n; ++i) - { - ma_utg_t *u = &g->u.a[i]; - if(u->m == 0) continue; - for (k = 0; k < u->n; k++) - { - if(rId == (u->a[k]>>33)) - { - fprintf(stderr, "%s: %s is the %u-th read at %u-th unitig (label: %u, occ: %u)\n", - info, name, k, i, g->g->seq[i].c, u->n); - flag = 1; - ///return i; - } - } - } - } - - - - - - if(flag == 0) fprintf(stderr, "%s: %s is not at any unitig\n", info, name); - return (uint32_t)-1; -} - - -void print_untig(ma_ug_t *g, uint32_t uId, const char* info, uint32_t is_print_read) -{ - uint32_t i, k; - asg_t* nsg = g->g; - - uId = uId<<1; - asg_arc_t *aw = asg_arc_a(nsg, uId); - uint32_t nw = asg_arc_n(nsg, uId); - - fprintf(stderr, "\n%s: c = %u, del: %u\n", info, nsg->seq[uId>>1].c, nsg->seq[uId>>1].del); - fprintf(stderr, "%s(%u): direction = 0...\n", info, uId>>1); - for (i = 0; i < nw; i++) - { - if(aw[i].del) continue; - fprintf(stderr, "%s: (%u) v>>1: %u, dir: %u\n", info, i, aw[i].v>>1, aw[i].v&1); - } - - uId = uId^1; - aw = asg_arc_a(nsg, uId); - nw = asg_arc_n(nsg, uId); - fprintf(stderr, "\n%s(%u): direction = 1...\n", info, uId>>1); - for (i = 0; i < nw; i++) - { - if(aw[i].del) continue; - fprintf(stderr, "%s: (%u) v>>1: %u, dir: %u\n", info, i, aw[i].v>>1, aw[i].v&1); - } - - if(is_print_read == 0) return; - - - uId = uId>>1; - ma_utg_t *u = &g->u.a[uId]; - fprintf(stderr, "\n%s: include %u reads in total...\n", info, u->n); - for (k = 0; k < u->n; k++) - { - fprintf(stderr, "%s: rId>>1: %lu, dir: %lu, name: %.*s\n", - info, (unsigned long)(u->a[k]>>33), (unsigned long)((u->a[k]>>32)&1), - (int)Get_NAME_LENGTH((R_INF), (u->a[k]>>33)), Get_NAME((R_INF), (u->a[k]>>33))); - } -} - - -void reset_untig_hap_label(ma_ug_t *g, uint32_t uId, uint8_t trio_flag, uint8_t* bin_res) -{ - uint32_t k; - ma_utg_t *u = &g->u.a[uId]; - for (k = 0; k < u->n; k++) { - if(bin_res[u->a[k]>>33] == AMBIGU) bin_res[u->a[k]>>33] = trio_flag; - } -} - - -void print_read_all(ma_ug_t *ug, const char* name, ma_hit_t_alloc* sources, -ma_hit_t_alloc* reverse_sources, const char* info) -{ - fprintf(stderr, "\n\n****************************\n"); - uint32_t uId; - uId = print_untig_by_read(ug, name, (uint32_t)-1, sources, reverse_sources, info); - if(uId != (uint32_t)-1) print_untig(ug, uId, info, 1); - fprintf(stderr, "****************************\n"); -} - - -void renew_utg(ma_ug_t **ug, asg_t* read_g, kvec_asg_arc_t_warp* edge) -{ - ma_ug_t* high_level_ug = NULL; - asg_t* nsg = (*ug)->g; - uint32_t i; - ma_utg_t *u; - high_level_ug = ma_ug_gen(nsg); - for (i = 0; i < high_level_ug->u.n; i++) - { - high_level_ug->g->seq[i].c = PRIMARY_LABLE; - u = &(high_level_ug->u.a[i]); - if(u->m == 0) continue; - merge_unitig_content(u, (*ug), read_g, edge); - high_level_ug->g->seq[i].len = u->len; - } - ma_ug_destroy((*ug)); - (*ug) = high_level_ug; -} - - - -long long get_graph_statistic(asg_t *g) -{ - long long num_arc = 0; - uint32_t n_vtx = g->n_seq * 2, v; - - for (v = 0; v < n_vtx; ++v) - { - if (g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - ///num_arc += asg_arc_n(g, v); - num_arc += get_real_length(g, v, NULL); - } - - return num_arc; -} - -void get_trio_labs(buf_t* b, ma_ug_t *ug, Trio_counter* flag) -{ - flag->father_occ = flag->mother_occ = flag->ambig_occ = flag->drop_occ = 0; - uint32_t i, v, k, rId; - if(ug == NULL) - { - for (i = 0; i < b->b.n; ++i) - { - if(R_INF.trio_flag[b->b.a[i]>>1]==FATHER) - { - flag->father_occ++; - } - else if(R_INF.trio_flag[b->b.a[i]>>1]==MOTHER) - { - flag->mother_occ++; - } - else if(R_INF.trio_flag[b->b.a[i]>>1]==AMBIGU) - { - flag->ambig_occ++; - } - else if(R_INF.trio_flag[b->b.a[i]>>1]==DROP) - { - flag->drop_occ++; - } - } - } - else - { - ma_utg_t* u = NULL; - for (i = 0; i < b->b.n; ++i) - { - v = b->b.a[i]>>1; - u = &(ug->u.a[v]); - if(u->m == 0) continue; - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - if(R_INF.trio_flag[rId]==FATHER) - { - flag->father_occ++; - } - else if(R_INF.trio_flag[rId]==MOTHER) - { - flag->mother_occ++; - } - else if(R_INF.trio_flag[rId]==AMBIGU) - { - flag->ambig_occ++; - } - else if(R_INF.trio_flag[rId]==DROP) - { - flag->drop_occ++; - } - } - } - } - - flag->total = flag->father_occ + flag->mother_occ + flag->ambig_occ + flag->drop_occ; -} - -uint32_t cal_trio_vec(buf_t* b, ma_ug_t *ug, float thres) -{ - uint32_t i, father_occ = 0, mother_occ = 0, v, k, rId; - if(ug == NULL) - { - for (i = 0; i < b->b.n; ++i) - { - if(R_INF.trio_flag[b->b.a[i]>>1]==FATHER) - { - father_occ++; - } - else if(R_INF.trio_flag[b->b.a[i]>>1]==MOTHER) - { - mother_occ++; - } - } - } - else - { - ma_utg_t* u = NULL; - for (i = 0; i < b->b.n; ++i) - { - v = b->b.a[i]>>1; - u = &(ug->u.a[v]); - if(u->m == 0) continue; - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - if(R_INF.trio_flag[rId]==FATHER) - { - father_occ++; - } - else if(R_INF.trio_flag[rId]==MOTHER) - { - mother_occ++; - } - } - } - } - - - - if(father_occ >= thres*(father_occ+mother_occ)) return FATHER; - if(mother_occ >= thres*(father_occ+mother_occ)) return MOTHER; - return AMBIGU; -} - -int cut_trio_tip_primary(asg_t *g, ma_ug_t *ug, uint32_t max_ext, uint32_t trio_flag, uint32_t keep_out_node, -asg_t *read_sg, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, uint8_t* is_r_het, uint32_t min_edge_length) -{ - double startTime = Get_T(); - uint32_t n_vtx = g->n_seq * 2, v, w, i, cnt = 0, tipEvaluateLen, flag, inner_flag, operation, tip_trio_flag; - uint32_t non_trio_flag = (uint32_t)-1, nw; - asg_arc_t *aw = NULL; - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - - buf_t b, b_0, b_1; - - memset(&b, 0, sizeof(buf_t)); - memset(&b_0, 0, sizeof(buf_t)); - memset(&b_1, 0, sizeof(buf_t)); - - for (v = 0; v < n_vtx; ++v) - { - if (g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - if (g->seq[v>>1].c == CUT || g->seq[v>>1].c == CUT_DIF_HAP || g->seq[v>>1].c == TRIM) continue; - if(get_real_length(g, (v^1), NULL) != 0) continue; - ///cut tip of length <= max_ext - flag = check_tip(g, v, &w, &b, max_ext); - if(flag == LOOP || flag == LONG_TIPS) continue; - if(keep_out_node && flag == MUL_OUTPUT) continue; - if(ug!=NULL) - { - tipEvaluateLen = 0; - for (i = 0; i < b.b.n; ++i) - { - tipEvaluateLen += EvaluateLen(ug->u, (b.b.a[i]>>1)); - } - if(tipEvaluateLen > max_ext) continue; - } - - operation = TRIM; - ///we need to deal with MUL_INPUT and END_TIPS - ///two operations: 1. trimming 2. cutting - if(flag == END_TIPS) - { - tip_trio_flag = cal_trio_vec(&b, ug, TRIO_THRES); - if(((tip_trio_flag == FATHER) || (tip_trio_flag == MOTHER)) - && - (tip_trio_flag != non_trio_flag)) - { - operation = CUT; - } - } - - ///if(flag == MUL_INPUT || flag == MUL_OUTPUT) - if(flag == MUL_INPUT) - { - // tip_trio_flag = cal_trio_vec(&b, ug, TRIO_THRES); - // if(((tip_trio_flag == FATHER) || (tip_trio_flag == MOTHER)) - // && - // (tip_trio_flag != non_trio_flag)) - // { - // operation = CUT; - // } - /** - To do lists: we can refine this function at the final step - 1. ideally, we should check if this tip comes from different haplotype with another unitig. - That might be helpful to recover bubbles. We should keep all break points in a vector, - and break these types of tip. At last, recover them. - - 2. if this tip has enough haplotype information, we should check if it does not - come from different haplotype with another unitig. If it does not, do not trim them - if(operation == TRIM) - { - get_real_length(g, b.b.a[b.b.n-1], &w); - w = w^1; - ; - } - **/ - get_real_length(g, b.b.a[b.b.n-1], &w); - w = w^1; - aw = asg_arc_a(g, w); - nw = asg_arc_n(g, w); - for (i = 0; i < nw; ++i) - { - if(operation == CUT) break; - if(aw[i].del) continue; - if(aw[i].v == (b.b.a[b.b.n-1]^1)) continue; - inner_flag = check_different_haps(g, ug, read_sg, b.b.a[b.b.n-1]^1, aw[i].v, - reverse_sources, &b_0, &b_1, ruIndex, is_r_het, min_edge_length, 1); - if(inner_flag == NON_PLOID) operation = CUT; - } - } - - - for (i = 0; i < b.b.n; ++i) - { - g->seq[(b.b.a[i]>>1)].c = ALTER_LABLE; - } - - for (i = 0; i < b.b.n; ++i) - { - asg_seq_drop(g, (b.b.a[i]>>1)); - } - - - if(operation == CUT) - { - for (i = 0; i < b.b.n; ++i) - { - g->seq[(b.b.a[i]>>1)].c = CUT; - } - } - - ++cnt; - } - - - if (cnt > 0) asg_cleanup(g); - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] cut %d tips\n", __func__, cnt); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - free(b.b.a); - free(b_0.b.a); - free(b_1.b.a); - - - return cnt; -} - -void label_r_set(buf_t* b, R_to_U* ruIndex, ma_ug_t *ug, uint32_t flag) -{ - uint32_t uid, rid, qn; - ma_utg_t *u = NULL; - for (uid = 0; uid < b->b.n;uid++) - { - u = &(ug->u.a[b->b.a[uid]>>1]); - ///each read - for (rid = 0; rid < u->n; rid++) - { - qn = (u->a[rid]>>33); - if(flag != (uint32_t)-1) - { - set_R_to_U(ruIndex, qn, b->b.a[uid]>>1, 1, NULL); - } - else - { - ruIndex->index[qn] = (uint32_t)-1; - } - } - } -} - -inline int trio_check(ma_ug_t *ug, uint32_t *a, uint32_t a_n, uint32_t flag) -{ - if(flag != FATHER && flag != MOTHER) return 0; - uint32_t flag_occ = 0, non_flag_occ = 0, ambigious = 0, u_n = 0, f, nf, ab, k; - for (k = 0; k < a_n; k++) { - get_unitig_trio_flag(&(ug->u.a[a[k]>>1]), flag, &f, &nf, &ab); - flag_occ += f; - non_flag_occ += nf; - ambigious += ab; - u_n += ug->u.a[a[k]>>1].n; - } - if((flag_occ+non_flag_occ) == 0) return 0; - if(flag_occ <= ((non_flag_occ+flag_occ)*0.75)) return 0; - if(non_flag_occ == 0 && flag_occ >= 20) return 1; - if(u_n >= 100) - { - if(flag_occ < u_n*DOUBLE_CHECK_THRES) return 0; - } - else if(u_n >= 50) - { - if(flag_occ < u_n*DOUBLE_CHECK_THRES*0.5) return 0; - } - else - { - if(flag_occ < u_n*DOUBLE_CHECK_THRES*0.25) return 0; - } - return 1; -} - -int asg_arc_cut_trio_long_tip_primary(asg_t *g, ma_ug_t *ug, asg_t *read_sg, ma_hit_t_alloc* reverse_sources, -R_to_U* ruIndex, uint32_t min_edge_length, float drop_ratio, uint32_t trio_flag, hap_cov_t *cov, utg_trans_t *o) -{ - double startTime = Get_T(); - ///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, convex, v_maxLen_i = (uint32_t)-1, flag, operation; - uint32_t return_flag, n_tips; - long long ll, v_maxLen, tmp, max_stop_nodeLen, max_stop_baseLen; - - buf_t b, b_0, b_1; - memset(&b, 0, sizeof(buf_t)); - memset(&b_0, 0, sizeof(buf_t)); - memset(&b_1, 0, sizeof(buf_t)); - - for (v = 0; v < n_vtx; ++v) - { - uint32_t i, k, n_arc = 0, nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - n_arc = get_real_length(g, v, NULL); - if (n_arc < 2) continue; - - v_maxLen = -1; - v_maxLen_i = (uint32_t)-1; - n_tips = 0; - - for (i = 0, n_arc = 0; i < nv; i++) - { - if (!av[i].del) - { - return_flag = get_unitig(g, ug, av[i].v, &convex, &ll, &tmp, &max_stop_nodeLen, - &max_stop_baseLen, 1, NULL); - - if(return_flag==LOOP) continue; - if(return_flag==END_TIPS) n_tips++; - - if(v_maxLen < ll) - { - v_maxLen = ll; - v_maxLen_i = i; - } - } - } - - if(n_tips==0) continue; - - for (i = 0, n_arc = 0; i < nv; i++) - { - if (!av[i].del) - { - ///skip the longest way - if(v_maxLen_i == i) continue; - - b.b.n = 0; - if(get_unitig(g, ug, av[i].v, &convex, &ll, &tmp, &max_stop_nodeLen, - &max_stop_baseLen, 1, &b)!=END_TIPS) - { - continue; - } - - if(ll >= (v_maxLen*drop_ratio)) continue; - if(trio_check(ug, b.b.a, b.b.n, trio_flag)) continue; - n_reduced++; - - operation = TRIM; - flag = check_different_haps(g, ug, read_sg, av[v_maxLen_i].v, av[i].v, reverse_sources, - &b_0, &b_1, ruIndex, cov->is_r_het, min_edge_length, 1); - // #define UNAVAILABLE (uint32_t)-1 - // #define PLOID 0 - // #define NON_PLOID 1 - if(flag == NON_PLOID) operation = CUT; - - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]>>1].c = ALTER_LABLE; - } - - for (k = 0; k < b.b.n; k++) - { - asg_seq_drop(g, b.b.a[k]>>1); - } - - if(operation == CUT) - { - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]>>1].c = CUT; - } - } - - if(cov && operation != CUT) - { - collect_trans_cov(__func__, &b_0, av[v_maxLen_i].ol, &b_1, av[i].ol, ug, read_sg, cov); - } - - if(o && operation != CUT) - { - collect_trans_ovlp(__func__, &b_0, av[v_maxLen_i].ol, &b_1, av[i].ol, ug, o); - } - - } - } - } - - - asg_cleanup(g); - asg_symm(g); - free(b.b.a); - free(b_0.b.a); - free(b_1.b.a); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d long tips\n", - __func__, n_reduced); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - return n_reduced; -} - -int asg_arc_cut_trio_long_tip_primary_complex(asg_t *g, ma_ug_t *ug, asg_t *read_sg, ma_hit_t_alloc* reverse_sources, -R_to_U* ruIndex, uint32_t min_edge_length, float drop_ratio, uint32_t stops_threshold, hap_cov_t *cov, utg_trans_t *o, uint32_t trio_flag) -{ - double startTime = Get_T(); - uint32_t v, n_vtx = g->n_seq * 2, n_reduced = 0, convex, in, flag, operation; - uint32_t return_flag, convex_i, k; - long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; - - buf_t b, b_0, b_1; - memset(&b, 0, sizeof(buf_t)); - memset(&b_0, 0, sizeof(buf_t)); - memset(&b_1, 0, sizeof(buf_t)); - for (v = 0; v < n_vtx; ++v) - { - uint32_t i; - if(g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - ///tip - if (get_real_length(g, v, NULL) != 0) continue; - if(get_real_length(g, v^1, NULL) != 1) continue; - - b.b.n = 0; - return_flag = get_unitig(g, ug, v^1, &convex, &ll, &tmp, &max_stop_nodeLen, - &max_stop_baseLen, 1, &b); - - if(return_flag != MUL_INPUT) continue; - if(trio_check(ug, b.b.a, b.b.n, trio_flag)) continue; - in = convex^1; - get_real_length(g, convex, &convex); - convex = convex^1; - uint32_t n_convex = asg_arc_n(g, convex), convexLen = ll; - asg_arc_t *a_convex = asg_arc_a(g, convex); - for (i = 0; i < n_convex; i++) - { - if(a_convex[i].del) continue; - if(a_convex[i].v == in) break; - } - convex_i = i; - ///if(convex_i == n_convex) fprintf(stderr, "ERROR\n"); - - - for (i = 0; i < n_convex; i++) - { - if(a_convex[i].del) continue; - if(i == convex_i) continue; - - return_flag = get_unitig(g, ug, a_convex[i].v, &convex, &ll, &tmp, &max_stop_nodeLen, - &max_stop_baseLen, stops_threshold, NULL); - - if(convexLen < ll*drop_ratio && max_stop_nodeLen >= ll*MAX_STOP_RATE) - { - n_reduced++; - operation = TRIM; - flag = check_different_haps(g, ug, read_sg, a_convex[convex_i].v, a_convex[i].v, - reverse_sources, &b_0, &b_1, ruIndex, cov->is_r_het, min_edge_length, stops_threshold); - // #define UNAVAILABLE (uint32_t)-1 - // #define PLOID 0 - // #define NON_PLOID 1 - if(flag == NON_PLOID) operation = CUT; - - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]>>1].c = ALTER_LABLE; - } - - for (k = 0; k < b.b.n; k++) - { - asg_seq_drop(g, b.b.a[k]>>1); - } - - if(operation == CUT) - { - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]>>1].c = CUT; - } - } - - ///note: we need to remove b_0, insetad of b_1 here - if(cov && operation != CUT) - { - collect_trans_cov(__func__, &b_1, a_convex[i].ol, &b_0, a_convex[convex_i].ol, ug, read_sg, cov); - } - - if(o && operation != CUT) - { - collect_trans_ovlp(__func__, &b_1, a_convex[i].ol, &b_0, a_convex[convex_i].ol, ug, o); - } - - - break; - } - } - } - - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d long tips\n", - __func__, n_reduced); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - asg_cleanup(g); - asg_symm(g); - free(b.b.a); - free(b_0.b.a); - free(b_1.b.a); - - return n_reduced; -} - -void renew_longest_tip_by_drop(asg_t *g, ma_ug_t *ug, asg_arc_t *av, uint32_t nv, -long long* base_maxLen, long long* base_maxLen_i, uint32_t stops_threshold, buf_t* b, -uint32_t trio_flag) -{ - if(trio_flag != FATHER && trio_flag != MOTHER) return; - Trio_counter max, cur; - memset(&max, 0, sizeof(Trio_counter)); - memset(&cur, 0, sizeof(Trio_counter)); - long long ll, tmp, max_stop_nodeLen, max_stop_baseLen, max_weight = 0, cur_weight = 0; - uint32_t convex, i, return_flag, best_tip_i, best_tip_len; - - b->b.n = 0; - return_flag = get_unitig(g, ug, av[(*base_maxLen_i)].v, &convex, &tmp, &ll, - &max_stop_nodeLen, &max_stop_baseLen, stops_threshold, b); - if(return_flag!=END_TIPS) return; - - - get_trio_labs(b, ug, &max); - ///means this unitig might be at current haplotype - ///if(max.drop_occ<(max.total*TRIO_DROP_THRES)) return; - - - best_tip_i = (*base_maxLen_i); - best_tip_len = (*base_maxLen); - - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - if(i==(*base_maxLen_i)) continue; - - b->b.n = 0; - return_flag = get_unitig(g, ug, av[i].v, &convex, &tmp, &ll, - &max_stop_nodeLen, &max_stop_baseLen, stops_threshold, b); - - if(return_flag!=END_TIPS) return; - ///this tip should be long enough - if(ll<(TRIO_DROP_LENGTH_THRES*(*base_maxLen))) continue; - - get_trio_labs(b, ug, &cur); - - if(trio_flag == FATHER) - { - max_weight = (long long)max.father_occ - (long long)max.drop_occ - (long long)max.mother_occ; - cur_weight = (long long)cur.father_occ - (long long)cur.drop_occ - (long long)cur.mother_occ; - ///this unitig is very likly at another haplotype, ignore it - if((cur.drop_occ+cur.mother_occ)>=(cur.total*TRIO_DROP_THRES)) continue; - } - - if(trio_flag == MOTHER) - { - max_weight = (long long)max.mother_occ - (long long)max.drop_occ - (long long)max.father_occ; - cur_weight = (long long)cur.mother_occ - (long long)cur.drop_occ - (long long)cur.father_occ; - ///this unitig is very likly at another haplotype, ignore it - if((cur.drop_occ+cur.father_occ)>=(cur.total*TRIO_DROP_THRES)) continue; - } - - - if(cur_weight > max_weight) - { - max = cur; - best_tip_i = i; - best_tip_len = ll; - } - else if(cur_weight == max_weight && ll>best_tip_len) - { - max = cur; - best_tip_i = i; - best_tip_len = ll; - } - } - - (*base_maxLen_i) = best_tip_i; - (*base_maxLen) = best_tip_len; -} - -int asg_arc_cut_trio_long_equal_tips_assembly(asg_t *g, ma_ug_t *ug, asg_t *read_sg, -ma_hit_t_alloc* reverse_sources, long long miniedgeLen, R_to_U* ruIndex, uint32_t trio_flag, -hap_cov_t *cov, utg_trans_t *o) -{ - double startTime = Get_T(); - uint32_t v, n_vtx = g->n_seq * 2, n_reduced = 0, convex, flag, is_hap, n_tips, return_flag, k; - long long ll, base_maxLen, base_maxLen_i, max_stop_nodeLen, max_stop_baseLen, tmp; - buf_t b, b_0, b_1; - memset(&b, 0, sizeof(buf_t)); - memset(&b_0, 0, sizeof(buf_t)); - memset(&b_1, 0, sizeof(buf_t)); - - for (v = 0; v < n_vtx; ++v) - { - uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - n_arc = get_real_length(g, v, NULL); - if (n_arc < 2) continue; - - base_maxLen = -1; - base_maxLen_i = -1; - n_tips = 0; - is_hap = 0; - - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - return_flag = get_unitig(g, ug, av[i].v, &convex, &tmp, &ll, &max_stop_nodeLen, - &max_stop_baseLen, 1, NULL); - - if(return_flag==LOOP) continue; - if(return_flag==END_TIPS) n_tips++; - - if(base_maxLen < ll) - { - base_maxLen = ll; - base_maxLen_i = i; - } - } - - if(n_tips==0) continue; - ///all the unitigs here are tips - if(n_arc == n_tips) - { - renew_longest_tip_by_drop(g, ug, av, nv, &base_maxLen, - &base_maxLen_i, 1, &b, trio_flag); - } - - for (i = 0; i < nv; i++) - { - if(i==base_maxLen_i) continue; - if(av[i].del) continue; - - b.b.n = 0; - return_flag = get_unitig(g, ug, av[i].v, &convex, &tmp, &ll, &max_stop_nodeLen, - &max_stop_baseLen, 1, &b); - - if(return_flag != END_TIPS) continue; - if(trio_check(ug, b.b.a, b.b.n, trio_flag)) continue; - - flag = check_different_haps(g, ug, read_sg, av[base_maxLen_i].v, av[i].v, - reverse_sources, &b_0, &b_1, ruIndex, cov->is_r_het, miniedgeLen, 1); - - // #define UNAVAILABLE (uint32_t)-1 - // #define PLOID 0 - // #define NON_PLOID 1 - if(flag != PLOID) continue; - n_reduced++; - - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]>>1].c = ALTER_LABLE; - } - - for (k = 0; k < b.b.n; k++) - { - asg_seq_drop(g, b.b.a[k]>>1); - } - - if(cov) - { - collect_trans_cov(__func__, &b_0, av[base_maxLen_i].ol, &b_1, av[i].ol, ug, read_sg, cov); - } - - if(o) - { - collect_trans_ovlp(__func__, &b_0, av[base_maxLen_i].ol, &b_1, av[i].ol, ug, o); - } - - - is_hap++; - } - - if(is_hap > 0) - { - i = base_maxLen_i; - b.b.n = 0; - get_unitig(g, ug, av[i].v, &convex, &tmp, &ll, &max_stop_nodeLen, - &max_stop_baseLen, 1, &b); - - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]>>1].c = HAP_LABLE; - } - } - } - - asg_cleanup(g); - asg_symm(g); - free(b.b.a); - free(b_0.b.a); - free(b_1.b.a); - - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d long tips\n", - __func__, n_reduced); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - return n_reduced; -} - -uint8_t if_primary_unitig(ma_utg_t* u, asg_t* read_g, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag) -{ - if(asm_opt.recover_atg_cov_min < 0 || asm_opt.recover_atg_cov_max < 0) return 0; - long long R_bases = 0, C_bases = 0, C_bases_primary = 0, C_bases_alter = 0; - long long total_C_bases = 0, total_C_bases_primary = 0; - uint32_t available_reads = 0, k, j, rId, tn, is_Unitig; - ma_hit_t *h; - if(u->m == 0) return 0; - total_C_bases = total_C_bases_primary = available_reads = 0; - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 1; - } - - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - C_bases = C_bases_primary = C_bases_alter = 0; - R_bases = coverage_cut[rId].e - coverage_cut[rId].s; - for (j = 0; j < (uint64_t)(sources[rId].length); j++) - { - h = &(sources[rId].buffer[j]); - if(h->el != 1) continue; - tn = Get_tn((*h)); - if(read_g->seq[tn].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - if(read_g->seq[tn].del == 1) continue; - if(r_flag[tn]) - { - C_bases_primary += Get_qe((*h)) - Get_qs((*h)); - } - else - { - C_bases_alter += Get_qe((*h)) - Get_qs((*h)); - } - } - - C_bases = C_bases_primary + C_bases_alter; - total_C_bases += C_bases; - ///if(C_bases_primary < C_bases * ALTER_COV_THRES) continue; - - C_bases = C_bases/R_bases; - if(C_bases >= asm_opt.recover_atg_cov_min && C_bases <= asm_opt.recover_atg_cov_max) - { - if(C_bases_primary >= (C_bases_primary + C_bases_alter) * ALTER_COV_THRES) available_reads++; - total_C_bases_primary += C_bases_primary; - } - } - - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 0; - } - - ///fprintf(stderr, "available_reads: %u, u->n: %u\n", available_reads, u->n); - - //if(available_reads < (u->n * 0.8) || available_reads == 0) - if(((available_reads < (u->n * 0.8)) && (total_C_bases_primary < (total_C_bases * 0.8))) - || available_reads == 0) - { - return 0; - } - else - { - return 1; - } -} - - - -int magic_trio_phasing(asg_t *g, ma_ug_t *ug, asg_t *read_sg, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long miniedgeLen, -R_to_U* ruIndex, uint32_t positive_flag, float drop_rate) -{ - uint32_t v, n_vtx = g->n_seq * 2, n_reduced = 0; - ma_utg_t* nsu = NULL; - uint32_t flag = (uint32_t)-1, flag_occ, non_flag_occ, ambigious, del_node, keep_node; - if(positive_flag == FATHER) flag = MOTHER; - if(positive_flag == MOTHER) flag = FATHER; - uint8_t* primary_flag = (uint8_t*)calloc(read_sg->n_seq, sizeof(uint8_t)); - - for (v = 0; v < n_vtx; ++v) - { - uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - if (nv < 2 || g->seq[v>>1].del /**|| g->seq[v>>1].c == ALTER_LABLE**/) continue; - n_arc = get_real_length(g, v, NULL); - if (n_arc < 2) continue; - del_node = keep_node = 0; - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - nsu = &(ug->u.a[av[i].v>>1]); - get_unitig_trio_flag(nsu, flag, &flag_occ, &non_flag_occ, &ambigious); - ///we may need it or not - if((flag_occ <= ((non_flag_occ+flag_occ)*drop_rate))||((flag_occ+non_flag_occ) == 0)) - { - keep_node++; - continue; - } - - if(nsu->n >= 100) - { - if(flag_occ < nsu->n*DOUBLE_CHECK_THRES) - { - keep_node++; - continue; - } - } - else if(nsu->n >= 50) - { - if(flag_occ < nsu->n*DOUBLE_CHECK_THRES*0.5) - { - keep_node++; - continue; - } - } - else - { - if(flag_occ < nsu->n*DOUBLE_CHECK_THRES*0.25) - { - keep_node++; - continue; - } - } - - del_node++; - } - - if(keep_node == 0 || del_node == 0) continue; - - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - nsu = &(ug->u.a[av[i].v>>1]); - - get_unitig_trio_flag(nsu, flag, &flag_occ, &non_flag_occ, &ambigious); - ///we may need it or not - if((flag_occ <= ((non_flag_occ+flag_occ)*drop_rate))||((flag_occ+non_flag_occ) == 0)) - { - continue; - } - - if(nsu->n >= 100) - { - if(flag_occ < nsu->n*DOUBLE_CHECK_THRES) - { - continue; - } - } - else if(nsu->n >= 50) - { - if(flag_occ < nsu->n*DOUBLE_CHECK_THRES*0.5) - { - continue; - } - } - else - { - if(flag_occ < nsu->n*DOUBLE_CHECK_THRES*0.25) - { - continue; - } - } - - if(if_primary_unitig(nsu, read_sg, coverage_cut, sources, ruIndex, primary_flag)) - { - continue; - } - - g->seq[av[i].v>>1].c = ALTER_LABLE; - asg_seq_drop(g, av[i].v>>1); - n_reduced++; - } - } - - - - - asg_cleanup(g); - free(primary_flag); - return n_reduced; -} - -int asg_arc_cut_trio_long_equal_tips_assembly_complex(asg_t *g, ma_ug_t *ug, asg_t *read_sg, -ma_hit_t_alloc* reverse_sources, long long miniedgeLen, R_to_U* ruIndex, uint32_t stops_threshold, -hap_cov_t *cov, utg_trans_t *o, uint32_t trio_flag) -{ - double startTime = Get_T(); - uint32_t v, n_vtx = g->n_seq * 2, n_reduced = 0, convex, in, flag; - uint32_t return_flag, convex_i, k; - long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; - - buf_t b, b_0, b_1; - memset(&b, 0, sizeof(buf_t)); - memset(&b_0, 0, sizeof(buf_t)); - memset(&b_1, 0, sizeof(buf_t)); - - - for (v = 0; v < n_vtx; ++v) - { - uint32_t i; - if (g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - ///tip - if (get_real_length(g, v, NULL) != 0) continue; - if (get_real_length(g, v^1, NULL) != 1) continue; - - b.b.n = 0; - return_flag = get_unitig(g, ug, v^1, &convex, &tmp, &ll, &max_stop_nodeLen, - &max_stop_baseLen, 1, &b); - - if(return_flag != MUL_INPUT) continue; - if(trio_check(ug, b.b.a, b.b.n, trio_flag)) continue; - in = convex^1; - get_real_length(g, convex, &convex); - convex = convex^1; - uint32_t n_convex = asg_arc_n(g, convex), convexLen = ll; - asg_arc_t *a_convex = asg_arc_a(g, convex); - for (i = 0; i < n_convex; i++) - { - if(a_convex[i].del) continue; - if(a_convex[i].v == in) break; - } - convex_i = i; - ///if(convex_i == n_convex) fprintf(stderr, "ERROR1\n"); - // if((v>>1) == 304 && (convex>>1) == 12875) - // { - // fprintf(stderr, "\n++v-%u, convex-%u, n_convex-%u\n", v, convex, n_convex); - // } - - for (i = 0; i < n_convex; i++) - { - if(a_convex[i].del) continue; - if(i == convex_i) continue; - - return_flag = get_unitig(g, ug, a_convex[i].v, &convex, &tmp, &ll, &max_stop_nodeLen, - &max_stop_baseLen, stops_threshold, NULL); - - // if((v>>1) == 304 && n_convex == 2) - // { - // fprintf(stderr, "---v-%u (len: %u), convex-%u, a_convex[i].v-%u (len: %lld), max_stop_baseLen: %lld\n", - // v, convexLen, convex, a_convex[i].v, ll, max_stop_baseLen); - // } - - if(ll>convexLen && max_stop_baseLen>=ll*MAX_STOP_RATE) - { - flag = check_different_haps(g, ug, read_sg, a_convex[convex_i].v, a_convex[i].v, - reverse_sources, &b_0, &b_1, ruIndex, cov->is_r_het, miniedgeLen, stops_threshold); - // #define UNAVAILABLE (uint32_t)-1 - // #define PLOID 0 - // #define NON_PLOID 1 - if(flag != PLOID) continue; - n_reduced++; - - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]>>1].c = ALTER_LABLE; - } - - for (k = 0; k < b.b.n; k++) - { - asg_seq_drop(g, b.b.a[k]>>1); - } - - ///note: we need to remove b_0, insetad of b_1 here - if(cov) - { - collect_trans_cov(__func__, &b_1, a_convex[i].ol, &b_0, a_convex[convex_i].ol, ug, read_sg, cov); - } - - if(o) - { - collect_trans_ovlp(__func__, &b_1, a_convex[i].ol, &b_0, a_convex[convex_i].ol, ug, o); - } - - - ///lable the primary one - b_0.b.n = 0; - get_unitig(g, ug, a_convex[i].v, &convex, &tmp, &ll, &max_stop_nodeLen, - &max_stop_baseLen, stops_threshold, &b_0); - for (k = 0; k < b_0.b.n; k++) - { - g->seq[b_0.b.a[k]>>1].c = HAP_LABLE; - } - - break; - } - } - - } - - asg_cleanup(g); - asg_symm(g); - free(b.b.a); - free(b_0.b.a); - free(b_1.b.a); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d long tips\n", - __func__, n_reduced); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - return n_reduced; -} - - -int detect_chimeric_by_topo(asg_t *g, ma_ug_t *ug, asg_t *read_sg, -ma_hit_t_alloc* reverse_sources, long long miniedgeLen, uint32_t stops_threshold, float drop_rate, -R_to_U* ruIndex, utg_trans_t *o, uint8_t* is_r_het) -{ - double startTime = Get_T(); - uint32_t i, k, v_i, v_beg, v_end, selfLen, w1, w2, wv, nw, n_vtx = g->n_seq * 2, n_reduced = 0, convex, convex_T, read_num; - asg_arc_t *aw; - long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; - - buf_t b_0, b_1; - memset(&b_0, 0, sizeof(buf_t)); - memset(&b_1, 0, sizeof(buf_t)); - - - for (v_i = 0; v_i < n_vtx; ++v_i) - { - v_beg = v_i; - ///some node could be deleted - if (g->seq[v_beg>>1].del || g->seq[v_beg>>1].c == ALTER_LABLE) continue; - if(get_real_length(g, v_beg, NULL) != 1) continue; - - get_real_length(g, v_beg, &w1); - if(get_real_length(g, w1^1, NULL)<=1) continue; - - if(get_unitig(g, ug, v_beg^1, &v_end, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, - 1, NULL)==LOOP) - { - continue; - } - selfLen = ll; - if(get_real_length(g, v_end, NULL) != 1) continue; - - - get_real_length(g, v_end, &w2); - if(get_real_length(g, w2^1, NULL)<=1) continue; - - get_unitig(g, ug, w1, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, - stops_threshold, NULL); - if(ll*drop_rate < selfLen) continue; - if(ll*0.4 > max_stop_nodeLen) continue; - - get_unitig(g, ug, w2, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, - stops_threshold, NULL); - if(ll*drop_rate < selfLen) continue; - if(ll*0.4 > max_stop_nodeLen) continue; - - stops_threshold++; - - - w1 = w1^1;wv=v_beg^1;aw = asg_arc_a(g, w1); nw = asg_arc_n(g, w1);convex_T = (uint32_t)-1; - for (i = 0; i < nw; i++) - { - if(aw[i].del) continue; - - get_unitig(g, ug, aw[i].v, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, - stops_threshold, NULL); - if(ll*drop_rate < selfLen) break; - if(ll*0.4 > max_stop_nodeLen) continue; - - if((aw[i].v>>1)==(v_beg>>1)) - { - if(convex_T != (uint32_t)-1) break; - convex_T = convex; - } - } - if(i!=nw) continue; - - for (i = 0; i < nw; i++) - { - if(aw[i].del) continue; - if((aw[i].v>>1) == (v_beg>>1)) continue; - - b_0.b.n = 0; - get_unitig(g, ug, aw[i].v, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, - stops_threshold, &b_0); - ///if(convex == convex_T) break; - for (k = 0; k < b_0.b.n; k++) - { - if((b_0.b.a[k]>>1) == (convex_T>>1)) break; - } - if(k != b_0.b.n) break; - - if(check_different_haps(g, ug, read_sg, wv, aw[i].v, reverse_sources, &b_0, &b_1, - ruIndex, is_r_het, miniedgeLen, stops_threshold)==PLOID) - { - break; - } - } - if(i!=nw) continue; - - - - - - w2 = w2^1;wv=v_end^1;aw = asg_arc_a(g, w2); nw = asg_arc_n(g, w2);convex_T = (uint32_t)-1; - for (i = 0; i < nw; i++) - { - if(aw[i].del) continue; - - - get_unitig(g, ug, aw[i].v, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, - stops_threshold, NULL); - if(ll*drop_rate < selfLen) break; - if(ll*0.4 > max_stop_nodeLen) continue; - - if((aw[i].v>>1) == (v_end>>1)) - { - if(convex_T != (uint32_t)-1) break; - convex_T = convex; - } - } - if(i!=nw) continue; - - for (i = 0; i < nw; i++) - { - if(aw[i].del) continue; - if((aw[i].v>>1) == (v_end>>1)) continue; - - b_0.b.n = 0; - get_unitig(g, ug, aw[i].v, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, - stops_threshold, &b_0); - ///if(convex == convex_T) break; - for (k = 0; k < b_0.b.n; k++) - { - if((b_0.b.a[k]>>1) == (convex_T>>1)) break; - } - if(k != b_0.b.n) break; - - if(check_different_haps(g, ug, read_sg, wv, aw[i].v, reverse_sources, &b_0, &b_1, - ruIndex, is_r_het, miniedgeLen, stops_threshold)==PLOID) - { - break; - } - } - if(i!=nw) continue; - - n_reduced++; - b_0.b.n = 0; - read_num = 0; - get_unitig(g, ug, v_beg^1, &v_end, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, &b_0); - for (k = 0; k < b_0.b.n; k++) - { - g->seq[b_0.b.a[k]>>1].c = ALTER_LABLE; - read_num += ug->u.a[b_0.b.a[k]>>1].n; - } - - for (k = 0; k < b_0.b.n; k++) - { - asg_seq_drop(g, b_0.b.a[k]>>1); - if(o) asg_seq_del(o->cug->g, b_0.b.a[k]>>1); - } - - if(read_num <= CHIMERIC_TRIM_THRES) - { - for (k = 0; k < b_0.b.n; k++) - { - g->seq[b_0.b.a[k]>>1].c = CUT; - } - } - - } - - if(o) asg_cleanup(o->cug->g); - asg_cleanup(g); - free(b_0.b.a); - free(b_1.b.a); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d long tips\n", - __func__, n_reduced); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - - return n_reduced; -} - -uint32_t cmp_untig_graph(ma_ug_t *src, ma_ug_t *dest) -{ - uint32_t nv, nw; - asg_arc_t *av = NULL, *aw = NULL; - uint32_t v, i, k, n_vtx = dest->g->n_seq*2; - if(src->g->n_seq!=dest->g->n_seq) - { - fprintf(stderr, "src->g->n_seq: %u, dest->g->n_seq: %u\n", src->g->n_seq, dest->g->n_seq); - ///return 1; - } - if(src->g->r_seq!=dest->g->r_seq) - { - fprintf(stderr, "src->g->r_seq: %u, dest->g->r_seq: %u\n", src->g->r_seq, dest->g->r_seq); - ///return 1; - } - if(src->g->is_srt!=dest->g->is_srt) - { - fprintf(stderr, "src->g->is_srt: %u, dest->g->is_srt: %u\n", src->g->is_srt, dest->g->is_srt); - ///return 1; - } - if(src->g->is_symm!=dest->g->is_symm) - { - fprintf(stderr, "src->g->is_symm: %u, dest->g->is_symm: %u\n", src->g->is_symm, dest->g->is_symm); - ///return 1; - } - ///if(memcmp(src->g->seq, dest->g->seq, sizeof(asg_seq_t)*src->g->n_seq)!=0) return 1; - - n_vtx = dest->g->n_seq; - for (v = 0; v < n_vtx; v++) - { - if(src->g->seq[v].c != dest->g->seq[v].c) - { - fprintf(stderr, "src->g->seq[%u].c: %u, dest->g->seq[%u].c: %u\n", - v, src->g->seq[v].c, v, dest->g->seq[v].c); - } - - if(src->g->seq[v].del != dest->g->seq[v].del) - { - fprintf(stderr, "src->g->seq[%u].del: %u, dest->g->seq[%u].del: %u\n", - v, src->g->seq[v].del, v, dest->g->seq[v].del); - } - - if(src->g->seq[v].len != dest->g->seq[v].len) - { - fprintf(stderr, "src->g->seq[%u].len: %u, dest->g->seq[%u].len: %u\n", - v, src->g->seq[v].len, v, dest->g->seq[v].len); - } - - if(src->u.a[v].n != dest->u.a[v].n) - { - fprintf(stderr, "src->u.a[%u].n: %u, dest->u.a[%u].n: %u\n", - v, src->u.a[v].n, v, dest->u.a[v].n); - } - - if(src->u.a[v].a[0] != dest->u.a[v].a[0] || - src->u.a[v].a[src->u.a[v].n-1] != dest->u.a[v].a[dest->u.a[v].n - 1]) - { - fprintf(stderr, "unequal beg/end node\n"); - } - } - - - n_vtx = dest->g->n_seq*2; - for (v = 0; v < n_vtx; v++) - { - nv = asg_arc_n(src->g, v); - av = asg_arc_a(src->g, v); - nw = asg_arc_n(dest->g, v); - aw = asg_arc_a(dest->g, v); - if(get_real_length(src->g, v, NULL) != get_real_length(dest->g, v, NULL)) - { - fprintf(stderr, "v>>1: %u, v&1: %u, get_real_length(src->g, v, NULL): %u, get_real_length(dest->g, v, NULL): %u\n", - v>>1, v&1, get_real_length(src->g, v, NULL), get_real_length(dest->g, v, NULL)); - ///return 1; - } - - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - for (k = 0; k < nw; k++) - { - if(aw[k].del) continue; - if(av[i].v == aw[k].v) break; - } - - if(k == nw) return 1; - } - } - - n_vtx = dest->g->n_seq; - ma_utg_t *src_u = NULL, *dest_u = NULL; - for (v = 0; v < n_vtx; v++) - { - src_u = &(src->u.a[v]); - dest_u = &(dest->u.a[v]); - if(src_u->circ!=dest_u->circ) return 1; - if(src_u->end!=dest_u->end) return 1; - if(src_u->len!=dest_u->len) return 1; - if(src_u->n!=dest_u->n) return 1; - if(src_u->start!=dest_u->start) return 1; - if(memcmp(src_u->a, dest_u->a, 8*src_u->n)!=0) return 1; - } - - return 0; -} - -ma_ug_t* copy_untig_graph(ma_ug_t *src) -{ - ma_ug_t *ug = NULL; - ug = (ma_ug_t*)calloc(1, sizeof(ma_ug_t)); - ug->g = asg_init(); - uint32_t v; - - ug->g->n_F_seq = src->g->n_F_seq; - ug->g->r_seq = src->g->r_seq; - ug->g->m_seq = ug->g->n_seq = src->g->n_seq; - ug->g->seq = (asg_seq_t*)malloc(ug->g->n_seq * sizeof(asg_seq_t)); - memcpy(ug->g->seq, src->g->seq, sizeof(asg_seq_t)*ug->g->n_seq); - - ug->g->m_arc = ug->g->n_arc = src->g->n_arc; - ug->g->arc = (asg_arc_t*)malloc(ug->g->n_arc*sizeof(asg_arc_t)); - memcpy(ug->g->arc, src->g->arc, sizeof(asg_arc_t)*ug->g->n_arc); - - ug->g->is_srt = src->g->is_srt; - ug->g->is_symm = src->g->is_symm; - ug->g->idx = (uint64_t*)malloc(ug->g->n_seq*2*8); - memcpy(ug->g->idx, src->g->idx, ug->g->n_seq*2*8); - asg_cleanup(ug->g); - - - - ug->u.m = ug->u.n = src->u.n; - ug->u.a = (ma_utg_t*)malloc(sizeof(ma_utg_t)*ug->u.n); - - ma_utg_t *src_u = NULL, *ug_u = NULL; - for (v = 0; v < ug->u.n; v++) - { - src_u = &(src->u.a[v]); - ug_u = &(ug->u.a[v]); - (*ug_u) = (*src_u); - ug_u->s = NULL; - ug_u->a = NULL; - ug_u->m = ug_u->n = src_u->n; - - ug_u->a = (uint64_t*)malloc(8 * ug_u->n); - memcpy(ug_u->a, src_u->a, 8*ug_u->n); - } - - /** - if(cmp_untig_graph(src, ug)) fprintf(stderr, "ERROR\n"); - ma_ug_destroy(ug); - return NULL; - **/ - return ug; -} - -asg_t* copy_read_graph(asg_t *src) -{ - asg_t *dest = NULL; - dest = asg_init(); - - dest->r_seq = src->r_seq; - dest->m_seq = dest->n_seq = src->n_seq; - dest->seq = (asg_seq_t*)malloc(dest->n_seq * sizeof(asg_seq_t)); - memcpy(dest->seq, src->seq, sizeof(asg_seq_t)*dest->n_seq); - - dest->m_arc = dest->n_arc = src->n_arc; - dest->arc = (asg_arc_t*)malloc(dest->n_arc*sizeof(asg_arc_t)); - memcpy(dest->arc, src->arc, sizeof(asg_arc_t)*dest->n_arc); - - dest->is_srt = src->is_srt; - dest->is_symm = src->is_symm; - dest->idx = NULL; - // dest->idx = (uint64_t*)malloc(dest->n_seq*2*8); - // memcpy(dest->idx, src->idx, dest->n_seq*2*8); - asg_cleanup(dest); - - if(src->seq_vis) - { - dest->seq_vis = (uint8_t*)malloc(dest->n_seq*2*sizeof(uint8_t)); - memcpy(dest->seq_vis, src->seq_vis, dest->n_seq*2*sizeof(uint8_t)); - } - - if(src->n_F_seq > 0 && src->F_seq) - { - dest->n_F_seq = src->n_F_seq; - dest->F_seq = (ma_utg_t*)malloc(dest->n_F_seq*sizeof(ma_utg_t)); - memcpy(dest->F_seq, src->F_seq, dest->n_F_seq*sizeof(ma_utg_t)); - } - return dest; -} - -rd_hamming_fly_t* gen_rd_hamming_fly_t(ma_ug_t *ug, asg_t *sg) -{ - rd_hamming_fly_t *p; CALLOC(p, 1); - MALLOC(p->o2n, sg->n_seq); - memset(p->o2n, -1, sizeof((*(p->o2n)))*sg->n_seq); - MALLOC(p->ugh, ug->g->n_seq); - return p; -} - -void destroy_rd_hamming_fly_t(rd_hamming_fly_t *p) -{ - free(p->o2n); free(p->srt->a); free(p->srt); - ma_ug_destroy(p->nug); asg_destroy(p->nsg); - asg_destroy(p->ref); free(p->ugh); -} - -void recall_arcs(asg_t *des, asg_t *src) -{ - uint32_t v, w, n_vtx = src->n_seq*2; - asg_arc_t *av, *za, *p; uint32_t an, zn, ai, zi, k; - kvec_t(asg_arc_t) ka; kv_init(ka); - - for (v = 0; v < n_vtx; ++v) { - if(src->seq[v>>1].del) continue; - za = asg_arc_a(src, v); zn = asg_arc_n(src, v); - av = asg_arc_a(des, v); an = asg_arc_n(des, v); - for (zi = 0; zi < zn; zi++) { - if(za[zi].del) continue; - w = za[zi].v; - for (ai = 0; ai < an; ai++) { - if(av[ai].del) continue; - if(av[ai].v == w) break; - } - if(ai >= an) kv_push(asg_arc_t, ka, za[zi]); - } - } - - if(ka.n) { - for (k = 0; k < ka.n; k++) { - p = asg_arc_pushp(des); *p = (ka.a[k]); - } - free(des->idx); - des->idx = 0; - des->is_srt = 0; - asg_cleanup(des); - // asg_symm(des); - } - fprintf(stderr, "[M::%s] # transitive arcs::%u\n", __func__, (uint32_t)ka.n); - fprintf(stderr, "[M::%s] # new arcs::%u, # old arcs::%u\n", __func__, des->n_arc, src->n_arc); - - kv_destroy(ka); -} - -ma_ug_t* gen_fg(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc* src, ma_sub_t *cov, int32_t max_hang, int32_t min_ovlp, int32_t gap_fuzz) -{ - uint32_t *idx; MALLOC(idx, rg->n_seq); - memset(idx, -1, sizeof((*idx))*rg->n_seq); - ma_ug_t *fg = copy_untig_graph(ug); asg_cleanup(fg->g);///some edges might be deleted - kvec_t(uint64_t) srt; kv_init(srt); - uint64_t i, k, l, m, rv, rw, uv, uw, zn, z, nist = 0; ma_utg_t *u; - for (k = 0; k < fg->u.n; k++) { - u = &(ug->u.a[k]); fg->g->seq[k].c = PRIMARY_LABLE; - if((u->circ) || (u->n == 0)) continue; - m = k<<1; m |= (((uint64_t)Uc_beg((*u)))<<32); kv_push(uint64_t, srt, m);///((uint32_t)(((*u)).a[0]>>32)); - m = (k<<1)+1; m |= (((uint64_t)Uc_end((*u)))<<32); kv_push(uint64_t, srt, m); - } - - - radix_sort_arch64(srt.a, srt.a+srt.n); - for (k = 1, l = 0; k <= srt.n; k++) { - if(k == srt.n || (srt.a[k]>>33) != (srt.a[l]>>33)) { - idx[srt.a[l]>>33] = l; - l = k; - } - } - - ma_hit_t_alloc* x; asg_arc_t *za; - ma_hit_t *h; ma_sub_t *sq, *st; - int32_t r; asg_arc_t t0, t1, *p; - for (k = 0; k < fg->u.n; k++) { - u = &(ug->u.a[k]); - if((u->circ) || (u->n == 0)) continue; - - uv = k<<1; rv = Uc_end((*u))^1; - x = &(src[rv>>1]); - za = asg_arc_a(ug->g, uv); - zn = asg_arc_n(ug->g, uv); - for (i = 0; i < x->length; i++) { - h = &(x->buffer[i]); - // if(!(h->el)) continue; - sq = &(cov[Get_qn(*h)]); st = &(cov[Get_tn(*h)]); - if(st->del || rg->seq[Get_tn(*h)].del) continue; - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t0); - - ///if it is a contained read, skip - if(r < 0) continue; - if((t0.ul>>32) != rv) continue; - rw = t0.v; - if(idx[rw>>1] == ((uint32_t)-1)) continue; - if(!(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, t0.ul>>32, t0.v, &t0))) continue; - - m = idx[rw>>1]; assert((srt.a[m]>>33) == (rw>>1)); - for (; m < srt.n && (srt.a[m]>>33) == (rw>>1); m++) { - if(rw == (srt.a[m]>>32)) { - uw = (uint32_t)srt.a[m]; - if(uv == uw) continue; - for (z = 0; z < zn; z++) { - if((!za[z].del) && (za[z].v==uw)) break; - } - if(z < zn) continue; - if(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, (t0.v^1), ((t0.ul>>32)^1), &t1)) { - p = asg_arc_pushp(fg->g); *p = t0; - p->ul<<=32; p->ul>>=32; p->ul |= (uv<<32); p->v = uw; - - p = asg_arc_pushp(fg->g); *p = t1; - p->ul<<=32; p->ul>>=32; p->ul |= ((uw^1)<<32); p->v = uv^1; - nist++; - } - } - } - } - - - uv = (k<<1)+1; rv = Uc_beg((*u))^1; - x = &(src[rv>>1]); - za = asg_arc_a(ug->g, uv); - zn = asg_arc_n(ug->g, uv); - for (i = 0; i < x->length; i++) { - h = &(x->buffer[i]); - // if(!(h->el)) continue; - sq = &(cov[Get_qn(*h)]); st = &(cov[Get_tn(*h)]); - if(st->del || rg->seq[Get_tn(*h)].del) continue; - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t0); - - ///if it is a contained read, skip - if(r < 0) continue; - if((t0.ul>>32) != rv) continue; - rw = t0.v; - if(idx[rw>>1] == ((uint32_t)-1)) continue; - if(!(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, t0.ul>>32, t0.v, &t0))) continue; - - m = idx[rw>>1]; assert((srt.a[m]>>33) == (rw>>1)); - for (; m < srt.n && (srt.a[m]>>33) == (rw>>1); m++) { - if(rw == (srt.a[m]>>32)) { - uw = (uint32_t)srt.a[m]; - if(uv == uw) continue; - for (z = 0; z < zn; z++) { - if((!za[z].del) && (za[z].v==uw)) break; - } - if(z < zn) continue; - if(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, (t0.v^1), ((t0.ul>>32)^1), &t1)) { - p = asg_arc_pushp(fg->g); *p = t0; - p->ul<<=32; p->ul>>=32; p->ul |= (uv<<32); p->v = uw; - - p = asg_arc_pushp(fg->g); *p = t1; - p->ul<<=32; p->ul>>=32; p->ul |= ((uw^1)<<32); p->v = uv^1; - nist++; - } - } - } - } - } - - if(nist) { - free(fg->g->idx); - fg->g->idx = 0; - fg->g->is_srt = 0; - asg_cleanup(fg->g); - asg_symm(fg->g); - asg_arc_del_trans(fg->g, gap_fuzz); - ///some of old edges might be lost due the transitive reduction - recall_arcs(fg->g, ug->g); - } - - kv_destroy(srt); free(idx); - return fg; -} - - -rd_hamming_fly_simp_t* gen_rd_hamming_fly_simp_t(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc* src, ma_sub_t *cov, int32_t max_hang, int32_t min_ovlp, int32_t gap_fuzz, kvec_asg_arc_t_warp *ae) -{ - rd_hamming_fly_simp_t *p; CALLOC(p, 1); - // p->ng = asg_init(); - // p->ng->n_seq = p->ng->m_seq = ug->g->n_seq; - // MALLOC(p->ng->seq, p->ng->n_seq); - // memcpy(p->ng->seq, ug->g->seq, (sizeof((*(p->ng->seq)))*p->ng->n_seq)); - p->src = src; p->cov = cov; p->max_hang = max_hang; p->min_ovlp = min_ovlp; p->gap_fuzz = gap_fuzz; - p->fg = gen_fg(ug, rg, src, cov, max_hang, min_ovlp, gap_fuzz); p->n_insert = 0; - CALLOC(p->vs, (ug->g->n_seq<<1)); CALLOC(p->srt, 1); p->ae = ae; - // p->fg = gen_fg(); - // p->rg = rg; MALLOC(p->rs, rg->n_seq<<1); - // memset(p->rs, -1, sizeof((*(p->rs)))*(rg->n_seq<<1)); - return p; -} - -void destroy_rd_hamming_fly_simp_t(rd_hamming_fly_simp_t *p) -{ - ///asg_destroy(p->ng); ///free(p->rs); - ma_ug_destroy(p->fg); - free(p->vs); - free(p->srt->a); - free(p->srt); -} - -static void dbg_asys_gfa0(void *data, long i, int tid) // callback for kt_for() -{ - asg_t *g = (asg_t *)data; asg_arc_t *s = &(g->arc[i]), *ra; - if(s->del) return; - uint64_t rn, ri, v, w; - ra = asg_arc_a(g, (s->v^1)); rn = asg_arc_n(g, (s->v^1)); - for (ri = 0; ri < rn; ri++) { - if(ra[ri].del) continue; - if(ra[ri].v == ((s->ul>>32)^1)) break; - } - if(ri >= rn) { - v = s->ul>>32; w = s->v; - fprintf(stderr, "[M::%s] v::utg%.6lul(%c)\tw::utg%.6lul(%c)\n", __func__, (v>>1) + 1, "+-"[(v&1)], (w>>1) + 1, "+-"[(w&1)]); - exit(1); - } -} - -static void dbg_asys_gfa1(void *data, long i, int tid) // callback for kt_for() -{ - asg_t *g = (asg_t *)data; asg_arc_t *av, *ra; - uint64_t rn, ri, v, w, an, k; - v = i<<1; av = asg_arc_a(g, v); an = asg_arc_n(g, v); - for (k = 0; k < an; k++) { - if(av[k].del) continue; - ra = asg_arc_a(g, (av[k].v^1)); rn = asg_arc_n(g, (av[k].v^1)); - for (ri = 0; ri < rn; ri++) { - if(ra[ri].del) continue; - if(ra[ri].v == ((av[k].ul>>32)^1)) break; - } - if(ri >= rn) { - w = av[k].v; - fprintf(stderr, "[M::%s] v::utg%.6lul(%c)\tw::utg%.6lul(%c)\n", __func__, (v>>1) + 1, "+-"[(v&1)], (w>>1) + 1, "+-"[(w&1)]); - exit(1); - } - - } - - v = (i<<1) + 1; av = asg_arc_a(g, v); an = asg_arc_n(g, v); - for (k = 0; k < an; k++) { - if(av[k].del) continue; - ra = asg_arc_a(g, (av[k].v^1)); rn = asg_arc_n(g, (av[k].v^1)); - for (ri = 0; ri < rn; ri++) { - if(ra[ri].del) continue; - if(ra[ri].v == ((av[k].ul>>32)^1)) break; - } - if(ri >= rn) { - w = av[k].v; - fprintf(stderr, "[M::%s] v::utg%.6lul(%c)\tw::utg%.6lul(%c)\n", __func__, (v>>1) + 1, "+-"[(v&1)], (w>>1) + 1, "+-"[(w&1)]); - exit(1); - } - } -} - -void dbg_asys_gfa(asg_t *g) -{ - kt_for(asm_opt.thread_num, dbg_asys_gfa0, g, g->n_arc); - kt_for(asm_opt.thread_num, dbg_asys_gfa1, g, g->n_seq); -} - -void clean_trio_untig_graph(ma_ug_t *ug, asg_t *read_g, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, -R_to_U* ruIndex, buf_t* b_0, uint8_t* visit, float density, uint32_t miniHapLen, -uint32_t miniBiGraph, float chimeric_rate, int is_final_clean, int just_bubble_pop, -float drop_ratio, uint32_t trio_flag, float trio_drop_rate, int max_hang, int min_ovlp, -int gap_fuzz, hap_cov_t *cov, kvec_asg_arc_t_warp *ae) -{ - asg_t *g = ug->g; rd_hamming_fly_simp_t *p = NULL; - uint32_t is_first = 1; - // if(trio_flag == MOTHER) { - // print_debug_gfa(read_g, ug, coverage_cut, "debug_dups", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len, 0, 1, 0); - // exit(1); - // } - redo: - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-0:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-0:", 0); - ///debug - // if(!p) p = gen_rd_hamming_fly_simp_t(ug, read_g, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz); - // fprintf(stderr, "[M::%s] 0\n", __func__); dbg_asys_gfa(g); - asg_pop_bubble_primary_trio(ug, NULL, trio_flag, DROP, cov, NULL, 1, p); - ///do not need to refine bubbles during the first round of cleaning - if(!p) p = gen_rd_hamming_fly_simp_t(ug, read_g, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz, ae); - - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-1:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-1:", 0); - // fprintf(stderr, "[M::%s] 1\n", __func__); dbg_asys_gfa(g); - magic_trio_phasing(g, ug, read_g, coverage_cut, sources, reverse_sources, 2, ruIndex, trio_flag, trio_drop_rate); - // fprintf(stderr, "[M::%s] 2\n", __func__); dbg_asys_gfa(g); - - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-2:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-2:", 0); - /**********debug**********/ - if(just_bubble_pop == 0) - { - cut_trio_tip_primary(g, ug, tipsLen, trio_flag, 0, read_g, reverse_sources, ruIndex, cov->is_r_het, 2); - } - // fprintf(stderr, "[M::%s] 3\n", __func__); dbg_asys_gfa(g); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-3:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-3:", 0); - /**********debug**********/ - long long pre_cons = get_graph_statistic(g); - long long cur_cons = 0; - while(pre_cons != cur_cons) - { - // fprintf(stderr, "[M::%s] 4\n", __func__); dbg_asys_gfa(g); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-4:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-4:", 0); - pre_cons = get_graph_statistic(g); - // fprintf(stderr, "[M::%s] 5\n", __func__); dbg_asys_gfa(g); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-5:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-5:", 0); - ///need consider tangles - asg_pop_bubble_primary_trio(ug, NULL, trio_flag, DROP, cov, NULL, 1, p); - // fprintf(stderr, "[M::%s] 6\n", __func__); dbg_asys_gfa(g); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-6:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-6:", 0); - /**********debug**********/ - if(just_bubble_pop == 0) - { - ///need consider tangles - asg_arc_cut_trio_long_tip_primary(g, ug, read_g, reverse_sources, ruIndex, 2, tip_drop_ratio, trio_flag, cov, NULL); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-7:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-7:", 0); - // fprintf(stderr, "[M::%s] 7\n", __func__); dbg_asys_gfa(g); - // if(trio_flag == MOTHER) print_debug_gfa(read_g, ug, coverage_cut, "debug_dups", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); - asg_arc_cut_trio_long_equal_tips_assembly(g, ug, read_g, reverse_sources, 2, ruIndex, trio_flag, cov, NULL); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-8:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-8:", 0); - // fprintf(stderr, "[M::%s] 8\n", __func__); dbg_asys_gfa(g); - asg_arc_cut_trio_long_tip_primary_complex(g, ug, read_g, reverse_sources, ruIndex, 2, tip_drop_ratio, stops_threshold, cov, NULL, trio_flag); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-9:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-9:", 0); - // fprintf(stderr, "[M::%s] 9\n", __func__); dbg_asys_gfa(g); - asg_arc_cut_trio_long_equal_tips_assembly_complex(g, ug, read_g, reverse_sources, 2, ruIndex, stops_threshold, cov, NULL, trio_flag); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-10:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-10:", 0); - // fprintf(stderr, "[M::%s] 10\n", __func__); dbg_asys_gfa(g); - detect_chimeric_by_topo(g, ug, read_g, reverse_sources, 2, stops_threshold, chimeric_rate, ruIndex, NULL, cov->is_r_het); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-11:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-11:", 0); - // fprintf(stderr, "[M::%s] 11\n", __func__); dbg_asys_gfa(g); - ///need consider tangles - ///note we need both the read graph and the untig graph - } - /**********debug**********/ - cur_cons = get_graph_statistic(g); - // fprintf(stderr, "[M::%s] 12\n", __func__); dbg_asys_gfa(g); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-12:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-12:", 0); - } - if(just_bubble_pop == 0) - { - // fprintf(stderr, "[M::%s] 13\n", __func__); dbg_asys_gfa(g); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-13:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-13:", 0); - cut_trio_tip_primary(g, ug, tipsLen, trio_flag, 0, read_g, reverse_sources, ruIndex, cov->is_r_het, 2); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-14:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-14:", 0); - // fprintf(stderr, "[M::%s] 14\n", __func__); dbg_asys_gfa(g); - } - - // print_debug_gfa(read_g, ug, coverage_cut, "debug_dups", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); - // fprintf(stderr, "[M::%s] 15\n", __func__); dbg_asys_gfa(g); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-15:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-15:", 0); - magic_trio_phasing(g, ug, read_g, coverage_cut, sources, reverse_sources, 2, ruIndex, trio_flag, trio_drop_rate); - // fprintf(stderr, "[M::%s] 16\n", __func__); dbg_asys_gfa(g); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-16:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-16:", 0); - - // print_debug_gfa(read_g, ug, coverage_cut, "resolve_tangles", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len, 0, 0, 0); - // exit(1); - ///bug here - resolve_tangles(ug, read_g, reverse_sources, 20, 100, 0.05, 0.2, ruIndex, cov->is_r_het, trio_flag, drop_ratio); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-17:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-17:", 0); - // fprintf(stderr, "[M::%s] 17\n", __func__); dbg_asys_gfa(g); - drop_semi_circle(ug, g, read_g, reverse_sources, ruIndex, cov->is_r_het); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-18:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-18:", 0); - // fprintf(stderr, "[M::%s] 18\n", __func__); dbg_asys_gfa(g); - all_to_all_deduplicate(ug, read_g, coverage_cut, sources, trio_flag, trio_drop_rate, reverse_sources, ruIndex, cov->is_r_het, DOUBLE_CHECK_THRES, asm_opt.trio_flag_occ_thres); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-19:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-19:", 0); - // fprintf(stderr, "[M::%s] 19\n", __func__); dbg_asys_gfa(g); - // if(trio_flag == MOTHER) print_untig_by_read(ug, "m54329U_190827_173812/30214441/ccs", (uint32_t)-1, NULL, NULL, "bf-16"); - if(is_first) - { - is_first = 0; - unitig_arc_del_short_diploid_by_length(ug->g, drop_ratio); - // if(trio_flag == MOTHER) print_untig((ug), 9, "i-20:", 0); - // if(trio_flag == MOTHER) print_untig((ug), 10, "i-20:", 0); - // fprintf(stderr, "[M::%s] 20\n", __func__); dbg_asys_gfa(g); - goto redo; - } - if(p) { - fprintf(stderr, "[M::%s] # adjusted arcs::%u\n", __func__, p->n_insert); - destroy_rd_hamming_fly_simp_t(p); free(p); - } -} - -void print_graph_statistic(asg_t *g, const char* cmd) -{ - uint64_t n_arc = 0, n_node = 0, size = 0; - uint32_t n_vtx = g->n_seq, v; - - for (v = 0; v < n_vtx; ++v) - { - if (g->seq[v].del || g->seq[v].c == ALTER_LABLE) continue; - n_arc += get_real_length(g, v<<1, NULL) + get_real_length(g, (v<<1)+1, NULL); - n_node++; - size += g->seq[v].len; - } - - fprintf(stderr, "%s->n_node: %lu, n_arc: %lu, size: %lu\n", cmd, n_node, n_arc, size); -} - - - -void clean_primary_untig_graph(ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* sources, -ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, long long tipsLen, float tip_drop_ratio, -long long stops_threshold, R_to_U* ruIndex, buf_t* b_0, uint8_t* visit, float density, -uint32_t miniHapLen, uint32_t miniBiGraph, float chimeric_rate, int is_final_clean, -int just_bubble_pop, float drop_ratio, hap_cov_t *cov) -{ - #define T_ROUND 2 - asg_t *g = ug->g; - int round = T_ROUND; - - redo: - ///print_graph_statistic(g, "beg"); - ///print_debug_gfa(read_g, ug, coverage_cut, "debug_trans_ovlp_hg002", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); - asg_pop_bubble_primary_trio(ug, NULL, (uint32_t)-1, DROP, cov, NULL, 1, NULL); - if(just_bubble_pop == 0) - { - cut_trio_tip_primary(g, ug, tipsLen, (uint32_t)-1, 0, read_g, reverse_sources, ruIndex, cov->is_r_het, 2); - } - // print_debug_gfa(read_g, ug, coverage_cut, "debug_init", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); - long long pre_cons = get_graph_statistic(g); - long long cur_cons = 0; - while(pre_cons != cur_cons) - { - pre_cons = get_graph_statistic(g); - asg_pop_bubble_primary_trio(ug, NULL, (uint32_t)-1, DROP, cov, NULL, 1, NULL); - if(just_bubble_pop == 0) - { - ///need consider tangles - asg_arc_cut_trio_long_tip_primary(g, ug, read_g, reverse_sources, ruIndex, 2, tip_drop_ratio, (uint32_t)-1, cov, NULL); - asg_arc_cut_trio_long_equal_tips_assembly(g, ug, read_g, reverse_sources, 2, ruIndex, (uint32_t)-1, cov, NULL); - asg_arc_cut_trio_long_tip_primary_complex(g, ug, read_g, reverse_sources, ruIndex, 2, tip_drop_ratio, stops_threshold, cov, NULL, (uint32_t)-1); - asg_arc_cut_trio_long_equal_tips_assembly_complex(g, ug, read_g, reverse_sources, 2, ruIndex, stops_threshold, cov, NULL, (uint32_t)-1); - detect_chimeric_by_topo(g, ug, read_g, reverse_sources, 2, stops_threshold, chimeric_rate, ruIndex, NULL, cov->is_r_het); - if(round != T_ROUND) - { - unitig_arc_del_short_diploid_by_length_topo(g, ug, drop_ratio, asm_opt.max_short_tip, - reverse_sources, 0, 1); - } - } - cur_cons = get_graph_statistic(g); - } - if(just_bubble_pop == 0) - { - cut_trio_tip_primary(g, ug, tipsLen, (uint32_t)-1, 0, read_g, reverse_sources, ruIndex, cov->is_r_het, 2); - } - resolve_tangles(ug, read_g, reverse_sources, 20, 100, 0.05, 0.2, ruIndex, cov->is_r_het, (uint32_t)-1, drop_ratio); - drop_semi_circle(ug, g, read_g, reverse_sources, ruIndex, cov->is_r_het); - // print_debug_gfa(read_g, ug, coverage_cut, "debug_clean_end", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); - unitig_arc_del_short_diploid_by_length_topo(g, ug, drop_ratio, asm_opt.max_short_tip, reverse_sources, 0, 1); - ///print_graph_statistic(g, "end"); - if(round > 0) - { - if(round != T_ROUND) - { - unitig_arc_del_short_diploid_by_length(ug->g, drop_ratio); - } - round--; - goto redo; - } -} - - - -utg_trans_t *topo_ovlp_collect(ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* sources, -ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, long long tipsLen, float tip_drop_ratio, -long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, -int min_ovlp, hap_cov_t *cov) -{ - utg_trans_t *o = init_utg_trans_t(ug, reverse_sources, coverage_cut, ruIndex, read_g, max_hang, min_ovlp); - #define T_ROUND 2 - asg_t *g = ug->g; - int round = T_ROUND; - - // print_debug_gfa(read_g, ug, coverage_cut, "debug_init", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); - - redo: - asg_pop_bubble_primary_trio(ug, NULL, (uint32_t)-1, DROP, cov, o, 1, NULL); - cut_trio_tip_primary(g, ug, tipsLen, (uint32_t)-1, 0, read_g, reverse_sources, ruIndex, cov->is_r_het, 2); - - long long pre_cons = get_graph_statistic(g); - long long cur_cons = 0; - while(pre_cons != cur_cons) - { - while(pre_cons != cur_cons) - { - while(pre_cons != cur_cons) - { - pre_cons = get_graph_statistic(g); - asg_pop_bubble_primary_trio(ug, NULL, (uint32_t)-1, DROP, cov, o, 1, NULL); - - ///need consider tangles - asg_arc_cut_trio_long_tip_primary(g, ug, read_g, reverse_sources, ruIndex, 2, tip_drop_ratio, (uint32_t)-1, cov, o); - asg_arc_cut_trio_long_equal_tips_assembly(g, ug, read_g, reverse_sources, 2, ruIndex, (uint32_t)-1, cov, o); - asg_arc_cut_trio_long_tip_primary_complex(g, ug, read_g, reverse_sources, ruIndex, 2, tip_drop_ratio, stops_threshold, cov, o, (uint32_t)-1); - asg_arc_cut_trio_long_equal_tips_assembly_complex(g, ug, read_g, reverse_sources, 2, ruIndex, stops_threshold, cov, o, (uint32_t)-1); - detect_chimeric_by_topo(g, ug, read_g, reverse_sources, 2, stops_threshold, chimeric_rate, ruIndex, o, cov->is_r_het); - - cur_cons = get_graph_statistic(g); - } - - // if(asm_opt.polyploidy > 2) asg_arc_decompress(g, ug, read_g, reverse_sources, ruIndex, o); - if(asm_opt.polyploidy > 2) - { - asg_arc_decompress_mul(g, ug, read_g, (uint32_t)-1, DROP, reverse_sources, ruIndex, o); - } - - cur_cons = get_graph_statistic(g); - } - if(round != T_ROUND) - { - unitig_arc_del_short_diploid_by_length_topo(g, ug, drop_ratio, asm_opt.max_short_tip, - reverse_sources, 0, 1); - } - cur_cons = get_graph_statistic(g); - } - - - cut_trio_tip_primary(g, ug, tipsLen, (uint32_t)-1, 0, read_g, reverse_sources, ruIndex, cov->is_r_het, 2); - - resolve_tangles(ug, read_g, reverse_sources, 20, 100, 0.05, 0.2, ruIndex, cov->is_r_het, (uint32_t)-1, drop_ratio); - drop_semi_circle(ug, g, read_g, reverse_sources, ruIndex, cov->is_r_het); - // print_debug_gfa(read_g, ug, coverage_cut, "debug_clean_end", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); - unitig_arc_del_short_diploid_by_length_topo(g, ug, drop_ratio, asm_opt.max_short_tip, reverse_sources, 0, 1); - - if(round > 0) - { - if(round != T_ROUND) - { - unitig_arc_del_short_diploid_by_length(ug->g, drop_ratio); - } - round--; - goto redo; - } - return o; -} - -void set_drop_trio_flag(ma_ug_t *ug) -{ - ma_utg_t* u = NULL; - asg_t* nsg = ug->g; - uint32_t k, rId; - uint32_t v, n_vtx = nsg->n_seq; - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - if(nsg->seq[v].c == ALTER_LABLE) continue; - u = &(ug->u.a[v]); - if(u->m == 0) continue; - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - if(R_INF.trio_flag[rId] != AMBIGU) continue; - R_INF.trio_flag[rId] = DROP; - } - } -} - -void update_unitig_graph(ma_ug_t* ug, asg_t* read_g, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, uint8_t* is_r_het, -uint8_t is_final_check, float double_check_rate, uint8_t flag, float drop_rate) -{ - asg_t* nsg = ug->g; - uint32_t v, n_vtx = nsg->n_seq, k, rId, flag_occ, non_flag_occ, hap_label_occ, n_reduce = 1; - ma_utg_t *u; - uint8_t* primary_flag = (uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)); - - drop_semi_circle(ug, nsg, read_g, reverse_sources, ruIndex, is_r_het); - - while (n_reduce) - { - n_reduce = 0; - n_vtx = nsg->n_seq; - for (v = 0; v < n_vtx; ++v) - { - if (nsg->seq[v].del) continue; - u = &((ug)->u.a[v]); - if(u->m == 0) continue; - if((get_real_length(nsg, v<<1, NULL)!=0) - && (get_real_length(nsg, ((v<<1)^1), NULL)!=0)) continue;///check tig - flag_occ = non_flag_occ = hap_label_occ = 0; - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - if(read_g->seq[rId].c == HAP_LABLE) hap_label_occ++; - if(R_INF.trio_flag[rId] == AMBIGU) continue; - if(R_INF.trio_flag[rId] == DROP) continue; - if(R_INF.trio_flag[rId] == flag) flag_occ++; - if(R_INF.trio_flag[rId] != flag) non_flag_occ++; - } - - ///if(is_final_check && v == 0) fprintf(stderr, "flag: %u, flag_occ: %u, non_flag_occ: %u\n", flag, flag_occ, non_flag_occ); - - if(is_final_check == 0 && hap_label_occ == u->n) continue; - ///if(is_double_check && non_flag_occ < u->n*DOUBLE_CHECK_THRES) continue; - ///if(is_double_check && non_flag_occ < u->n*double_check_rate) continue; - - if(is_final_check) - { - /**if(non_flag_occ < u->n*double_check_rate) continues**/; - } - else - { - if(u->n >= 100) - { - if(non_flag_occ < u->n*double_check_rate) - { - continue; - } - } - else if(u->n >= 50) - { - if(non_flag_occ < u->n*double_check_rate*0.5) - { - continue; - } - } - else - { - if(non_flag_occ < u->n*double_check_rate*0.25) - { - continue; - } - } - } - - if(non_flag_occ > ((non_flag_occ+flag_occ)*drop_rate)) - { - - if(if_primary_unitig(u, read_g, coverage_cut, sources, ruIndex, primary_flag)) - { - continue; - } - - if(u->m != 0) - { - u->circ = u->end = u->len = u->m = u->n = u->start = 0; - free(u->a); - u->a = NULL; - } - asg_seq_del(nsg, v); - n_reduce++; - } - } - } - - drop_semi_circle(ug, nsg, read_g, reverse_sources, ruIndex, is_r_het); - asg_cleanup(nsg); - free(primary_flag); -} - - -void force_trio_clean(ma_ug_t* ug, asg_t* read_g, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, -uint8_t flag, float self_drop_rate, float contig_drop_rate, uint32_t min_occ) -{ - asg_t* nsg = ug->g; - uint32_t beg, end, n_vtx = nsg->n_seq<<1, k, i, rId, tf_occ, tnf_occ, flag_occ, non_flag_occ, n_reduce = 1; - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - buf_t b; memset(&b, 0, sizeof(buf_t)); - ma_utg_t *u = NULL; - uint8_t* primary_flag = (uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)); - - while (n_reduce) - { - n_reduce = 0; - n_vtx = nsg->n_seq; - for (beg = 0; beg < n_vtx; ++beg) - { - if(nsg->seq[beg>>1].del || asg_arc_n(nsg, beg) <= 0 || get_real_length(nsg, beg, NULL)<=0) - { - continue; - } - if(get_real_length(nsg, beg^1, NULL) == 1)///check if beg is the tig end - { - get_real_length(nsg, beg^1, &end); - if(get_real_length(nsg, end^1, NULL) == 1) continue; - } - b.b.n = 0; tf_occ = tnf_occ = 0; - get_unitig(nsg, ug, beg, &end, &nodeLen, &baseLen, &max_stop_nodeLen, &max_stop_baseLen, 1, &b); - - for (i = 0; i < b.b.n; i++) - { - u = &((ug)->u.a[b.b.a[i]>>1]); - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - if(R_INF.trio_flag[rId] == AMBIGU) continue; - if(R_INF.trio_flag[rId] == DROP) continue; - if(R_INF.trio_flag[rId] == flag) tf_occ++; - if(R_INF.trio_flag[rId] != flag) tnf_occ++; - } - } - if(tnf_occ <= ((tnf_occ+tf_occ)*contig_drop_rate)) continue; - - for (i = 0; i < b.b.n; i++) - { - flag_occ = non_flag_occ = 0; - u = &((ug)->u.a[b.b.a[i]>>1]); - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - if(R_INF.trio_flag[rId] == AMBIGU) continue; - if(R_INF.trio_flag[rId] == DROP) continue; - if(R_INF.trio_flag[rId] == flag) flag_occ++; - if(R_INF.trio_flag[rId] != flag) non_flag_occ++; - } - - if(non_flag_occ <= min_occ) continue; - if(non_flag_occ <= ((non_flag_occ+flag_occ)*self_drop_rate)) continue; - if(non_flag_occ <= ((tf_occ+tnf_occ)*contig_drop_rate)) continue; - if(if_primary_unitig(u, read_g, coverage_cut, sources, ruIndex, primary_flag)) - { - continue; - } - - if(u->m != 0) - { - u->circ = u->end = u->len = u->m = u->n = u->start = 0; - free(u->a); - u->a = NULL; - } - asg_seq_del(nsg, b.b.a[i]>>1); - n_reduce++; - } - - } - } - - free(b.b.a); - asg_cleanup(nsg); - free(primary_flag); -} - -void get_candidate_uids(asg_t* nsg, ma_utg_t* nsu, kvec_t_u64_warp* u_vecs, -ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex) -{ - uint32_t k, j, rId, uId, is_Unitig, m; - uint64_t pre; - u_vecs->a.n = 0; - if(nsu->m == 0) return; - for (k = 0; k < nsu->n; k++) - { - rId = nsu->a[k]>>33; - for (j = 0; j < reverse_sources[rId].length; j++) - { - get_R_to_U(ruIndex, Get_tn(reverse_sources[rId].buffer[j]), &uId, &is_Unitig); - if(uId==(uint32_t)-1) continue; - ///contained read - if(is_Unitig == 0) get_R_to_U(ruIndex, uId, &uId, &is_Unitig); - if(uId == (uint32_t)-1 || is_Unitig == 0) continue; - ///need this line - if(nsg->seq[uId].c == ALTER_LABLE) continue; - pre = uId; - pre = pre | (uint64_t)(0x100000000); - kv_push(uint64_t, u_vecs->a, pre); - } - } - if(u_vecs->a.n == 0) return; - radix_sort_arch64(u_vecs->a.a, u_vecs->a.a + u_vecs->a.n); - for (m = 0, k = 1; k < u_vecs->a.n; k++) - { - if(u_vecs->a.a[k] == u_vecs->a.a[k-1]) - { - u_vecs->a.a[m] += (uint64_t)(0x100000000); - } - else - { - m++; - u_vecs->a.a[m] = u_vecs->a.a[k]; - } - } - - u_vecs->a.n = m + 1; -} - -uint32_t unitig_simi(uint32_t x, uint32_t y, ma_ug_t* ug, ma_hit_t_alloc* reverse_sources, -R_to_U* ruIndex, uint8_t* is_r_het) -{ - uint32_t k, j, uId, tn, is_Unitig, rId, ref_unitig, min_count, max_count, n_het, n_hom; - ma_utg_t *nsu_x = NULL, *nsu_y = NULL, *nsu_query = NULL; - nsu_x = &(ug->u.a[x]); - nsu_y = &(ug->u.a[y]); - - if(nsu_x->n == 0 || nsu_y->n == 0) return UNAVAILABLE; - - if(nsu_x->n <= nsu_y->n) - { - nsu_query = nsu_x; - ref_unitig = y; - } - else - { - nsu_query = nsu_y; - ref_unitig = x; - } - - min_count = max_count = n_het = n_hom = 0; - for (k = 0; k < nsu_query->n; k++) - { - rId = nsu_query->a[k]>>33; - if(reverse_sources[rId].length >= 0) min_count++; - if((is_r_het[rId] & C_HET) || (is_r_het[rId] & P_HET)) n_het++; - n_hom++; - - for (j = 0; j < reverse_sources[rId].length; j++) - { - tn = Get_tn(reverse_sources[rId].buffer[j]); - get_R_to_U(ruIndex, tn, &uId, &is_Unitig); - if(uId==(uint32_t)-1) continue; - ///contained read - if(is_Unitig == 0) get_R_to_U(ruIndex, uId, &uId, &is_Unitig); - if(uId == (uint32_t)-1 || is_Unitig == 0) continue; - if(uId == ref_unitig) - { - max_count++; - break; - } - } - } - - if(min_count == 0) return UNAVAILABLE; - if(max_count > min_count*asm_opt.purge_simi_thres && n_het >= n_hom*HET_HOM_RATE) return PLOID; - return NON_PLOID; -} - -void get_unitig_trio_flag(ma_utg_t* nsu, uint32_t flag, uint32_t* require, -uint32_t* non_require, uint32_t* ambigious) -{ - uint32_t k, rId; - (*require) = (*non_require) = (*ambigious) = 0; - for (k = 0; k < nsu->n; k++) - { - rId = nsu->a[k]>>33; - if(R_INF.trio_flag[rId] == AMBIGU || R_INF.trio_flag[rId] == DROP) - { - (*ambigious)++; - continue; - } - if(R_INF.trio_flag[rId] == flag) - { - (*require)++; - continue; - } - if(R_INF.trio_flag[rId] != flag) - { - (*non_require)++; - continue; - } - } -} - - -///note: to use this function, don't renew unitig graph!!!!!!!!! -void all_to_all_deduplicate(ma_ug_t* ug, asg_t* read_g, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, uint8_t postive_flag, float drop_rate, -ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, uint8_t* is_r_het, float double_check_rate, int non_tig_occ) -{ - - - kvec_t_u64_warp u_vecs; - kv_init(u_vecs.a); - uint32_t n_vtx, v, k, is_Unitig, is_tig, uId, rId, convex, flag_occ, non_flag_occ, ambigious, /**is_ambigious,**/ flag, n_reduce = 1; - asg_t* nsg = NULL; - ma_utg_t* nsu = NULL; - nsg = ug->g; - if(postive_flag == FATHER) flag = MOTHER; - if(postive_flag == MOTHER) flag = FATHER; - uint8_t* primary_flag = (uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)); - - for (v = 0; v < nsg->n_seq; v++) - { - uId = v; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsg->seq[v].del) continue; - if(nsg->seq[v].c==ALTER_LABLE) continue; - - for (k = 0; k < nsu->n; k++) - { - rId = nsu->a[k]>>33; - set_R_to_U(ruIndex, rId, uId, 1, &(read_g->seq[rId].c)); - } - } - - n_reduce = 1; - while (n_reduce) - { - n_reduce = 0; - n_vtx = nsg->n_seq*2; - for (v = 0; v < n_vtx; ++v) - { - - uId = v>>1; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsg->seq[uId].del) continue; - if(nsg->seq[uId].c == ALTER_LABLE) continue; - is_tig = 1; - - if(get_real_length(nsg, v^1, NULL) == 1) - { - get_real_length(nsg, v^1, &convex); - if(get_real_length(nsg, convex^1, NULL) == 1) - { - is_tig = 0; - ///continue; - } - } - - get_unitig_trio_flag(nsu, flag, &flag_occ, &non_flag_occ, &ambigious); - /** - is_ambigious = 0; - if((flag_occ+non_flag_occ)==0 && ambigious > 0) - { - is_ambigious = 1; - } - else**/ - { - ///we may need it or not - if(is_tig == 0 && (int)flag_occ <= non_tig_occ) continue; - if(flag_occ <= ((non_flag_occ+flag_occ)*drop_rate)) continue; - if((flag_occ+non_flag_occ) == 0) continue; - if(nsu->n >= 100) - { - if(flag_occ < nsu->n*double_check_rate) - { - continue; - } - } - else if(nsu->n >= 50) - { - if(flag_occ < nsu->n*double_check_rate*0.5) - { - continue; - } - } - else - { - if(flag_occ < nsu->n*double_check_rate*0.25) - { - continue; - } - } - } - - - get_candidate_uids(nsg, nsu, &u_vecs, reverse_sources, ruIndex); - - - if(u_vecs.a.n == 0) continue; - - for (k = 0; k < u_vecs.a.n; k++) - { - /** - if(is_ambigious) - { - get_unitig_trio_flag(&(ug->u.a[(uint32_t)(u_vecs.a.a[k])]), postive_flag, - &flag_occ, &non_flag_occ, &ambigious); - if(flag_occ <= ((non_flag_occ+flag_occ)*drop_rate)) continue; - if((flag_occ+non_flag_occ) == 0) continue; - }**/ - if(unitig_simi(uId, (uint32_t)(u_vecs.a.a[k]), ug, reverse_sources, ruIndex, is_r_het)==PLOID) - { - break; - } - } - - if(k != u_vecs.a.n) - { - if(if_primary_unitig(nsu, read_g, coverage_cut, sources, ruIndex, primary_flag)) - { - continue; - } - if(nsu->m != 0) - { - nsu->circ = nsu->end = nsu->len = nsu->m = nsu->n = nsu->start = 0; - free(nsu->a); - nsu->a = NULL; - } - asg_seq_del(nsg, uId); - n_reduce++; - } - } - } - - for (v = 0; v < ruIndex->len; v++) - { - get_R_to_U(ruIndex, v, &uId, &is_Unitig); - if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; - } - - kv_destroy(u_vecs.a); - free(primary_flag); -} - -void delete_useless_nodes(ma_ug_t **ug) -{ - asg_t* nsg = (*ug)->g; - uint32_t v, n_vtx = nsg->n_seq; - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - if(nsg->seq[v].c == ALTER_LABLE) - { - asg_seq_del(nsg, v); - if((*ug)->u.a[v].m!=0) - { - (*ug)->u.a[v].m = (*ug)->u.a[v].n = 0; - free((*ug)->u.a[v].a); - (*ug)->u.a[v].a = NULL; - } - - continue; - } - - //note: after cleaning, some cirle might be gone, or we have some new circles - //so need to renew .circ - /** - if(get_unitig(nsg, NULL, (v<<1), &convex, &nodeLen, &baseLen, - &max_stop_nodeLen, &max_stop_baseLen, 1, NULL)==LOOP) - { - (*ug)->u.a[v].circ = 1; - (*ug)->u.a[v].start = (*ug)->u.a[v].end = UINT32_MAX; - } - else - { - (*ug)->u.a[v].circ = 0; - - (*ug)->u.a[v].start = (*ug)->u.a[v].a[0]>>32; - (*ug)->u.a[v].end = ((*ug)->u.a[v].a[(*ug)->u.a[v].n-1]>>32)^1; - } - **/ - } - - asg_cleanup(nsg); -} - -inline uint32_t is_useful_node(uint32_t flag_occ, uint32_t non_flag_occ, uint32_t drop_occ, uint32_t tot_occ, -float flag_rate, float used_rate, uint32_t min_occ) -{ - if((flag_occ > 0) && (flag_occ >= min_occ) && (flag_occ >= ((non_flag_occ+flag_occ+drop_occ)*flag_rate)) - && (drop_occ <= (tot_occ*used_rate))) { - return 1; - } - return 0; -} - - -void recover_chain_nodes(buf_t *in, ma_ug_t *ug, uint32_t flag, float flag_rate, float used_rate, uint32_t min_occ) -{ - ma_utg_t *u = NULL; uint32_t flag_occ, non_flag_occ, drop_occ, rid; - uint32_t tot_flag_occ, tot_non_flag_occ, tot_drop_occ, tot_occ, i, k, z; - tot_flag_occ = tot_non_flag_occ = tot_drop_occ = tot_occ = 0; - - for (i = 0; i < in->b.n; i++) { - u = &(ug->u.a[in->b.a[i]>>1]); - flag_occ = non_flag_occ = drop_occ = 0; - for (k = 0; k < u->n; k++) { - rid = u->a[k]>>33; - if(R_INF.trio_flag[rid] == AMBIGU) continue; - else if(R_INF.trio_flag[rid] == DROP) drop_occ++; - else if(R_INF.trio_flag[rid] == flag) flag_occ++; - else if(R_INF.trio_flag[rid] != flag) non_flag_occ++; - } - - if(is_useful_node(flag_occ, non_flag_occ, drop_occ, u->n, flag_rate, used_rate, min_occ)) { - ug->g->seq[in->b.a[i]>>1].c = PRIMARY_LABLE; - } - tot_flag_occ += flag_occ; - tot_non_flag_occ += non_flag_occ; - tot_drop_occ += drop_occ; - tot_occ += u->n; - if(is_useful_node(tot_flag_occ, tot_non_flag_occ, tot_drop_occ, tot_occ, flag_rate, used_rate, min_occ)) { - for (z = 0; z <= i; z++) { - if(ug->g->seq[in->b.a[z]>>1].c == ALTER_LABLE) { - u = &(ug->u.a[in->b.a[z]>>1]); - flag_occ = non_flag_occ = drop_occ = 0; - for (k = 0; k < u->n; k++) { - rid = u->a[k]>>33; - if(R_INF.trio_flag[rid] == AMBIGU) continue; - else if(R_INF.trio_flag[rid] == DROP) drop_occ++; - else if(R_INF.trio_flag[rid] == flag) flag_occ++; - else if(R_INF.trio_flag[rid] != flag) non_flag_occ++; - } - if(is_useful_node(flag_occ, non_flag_occ, drop_occ, u->n, flag_rate, used_rate, 0/**min_occ**/)) { - ug->g->seq[in->b.a[z]>>1].c = PRIMARY_LABLE; - } - } - } - } - } -} - -void rescue_useless_trio_nodes(ma_ug_t *ug, uint32_t flag, float flag_rate, float used_rate, uint32_t min_occ) -{ - asg_t* nsg = ug->g; - uint32_t v, w, n_vtx = nsg->n_seq<<1, i, k, z; - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - buf_t b; memset(&b, 0, sizeof(buf_t)); - - for (v = 0; v < n_vtx; v++) { - if(nsg->seq[v>>1].del) continue; - if(nsg->seq[v>>1].c != ALTER_LABLE) continue; - ///check if beg is the tig end - if(get_real_length(nsg, v^1, NULL) == 1) { - get_real_length(nsg, v^1, &w); - if(get_real_length(nsg, w^1, NULL) == 1) continue; - } - - b.b.n = 0; - get_unitig(nsg, ug, v, &w, &nodeLen, &baseLen, &max_stop_nodeLen, &max_stop_baseLen, 1, &b); - recover_chain_nodes(&b, ug, flag, flag_rate, used_rate, min_occ); - if(b.b.n > 1) { - k = b.b.n>>1; - for (i = 0; i < k; i++) { - z = b.b.a[i]; b.b.a[i] = b.b.a[b.b.n-i-1]; b.b.a[b.b.n-i-1] = z; - } - recover_chain_nodes(&b, ug, flag, flag_rate, used_rate, min_occ); - } - } - - free(b.b.a); - asg_cleanup(nsg); -} - -void delete_useless_trio_nodes(ma_ug_t **ug, asg_t* read_g, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex, uint32_t flag, float flag_rate, float used_rate, uint32_t min_occ) -{ - asg_t* nsg = (*ug)->g; - uint32_t v, n_vtx = nsg->n_seq; - uint8_t* primary_flag = (uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)); - - if(flag_rate > 0 && used_rate > 0 && min_occ > 0) { - rescue_useless_trio_nodes(*ug, flag, flag_rate, used_rate, min_occ); - } - - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - if(nsg->seq[v].c == ALTER_LABLE && - (if_primary_unitig(&((*ug)->u.a[v]), read_g, coverage_cut, sources, - ruIndex, primary_flag) == 0)) - { - asg_seq_del(nsg, v); - if((*ug)->u.a[v].m!=0) - { - (*ug)->u.a[v].m = (*ug)->u.a[v].n = 0; - free((*ug)->u.a[v].a); - (*ug)->u.a[v].a = NULL; - } - - continue; - } - - //note: after cleaning, some cirle might be gone, or we have some new circles - //so need to renew .circ - /** - if(get_unitig(nsg, NULL, (v<<1), &convex, &nodeLen, &baseLen, - &max_stop_nodeLen, &max_stop_baseLen, 1, NULL)==LOOP) - { - (*ug)->u.a[v].circ = 1; - (*ug)->u.a[v].start = (*ug)->u.a[v].end = UINT32_MAX; - } - else - { - (*ug)->u.a[v].circ = 0; - - (*ug)->u.a[v].start = (*ug)->u.a[v].a[0]>>32; - (*ug)->u.a[v].end = ((*ug)->u.a[v].a[(*ug)->u.a[v].n-1]>>32)^1; - } - **/ - } - - asg_cleanup(nsg); - free(primary_flag); -} - - - - - -void drop_semi_circle(ma_ug_t *ug, asg_t* nsg, asg_t* read_g, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, uint8_t* is_r_het) -{ - uint32_t v, n_vtx = nsg->n_seq*2, convex_f, convex_b, i, nv; - long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; - asg_arc_t *av = NULL; - buf_t b_0, b_1; - memset(&b_0, 0, sizeof(buf_t)); - memset(&b_1, 0, sizeof(buf_t)); - - for (v = 0; v < n_vtx; ++v) - { - if(get_real_length(nsg, v, NULL) == 0) continue; - if(get_real_length(nsg, v^1, NULL) == 0) continue; - - if(get_unitig(nsg, ug, v^1, &convex_b, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, - 1, NULL)!=MUL_INPUT) - { - continue; - } - - get_real_length(nsg, convex_b, &convex_b); - - av = asg_arc_a(nsg, v); - nv = asg_arc_n(nsg, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - - if(get_unitig(nsg, ug, av[i].v, &convex_f, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, - 1, NULL)!=MUL_INPUT) - { - continue; - } - get_real_length(nsg, convex_f, &convex_f); - if(convex_f != convex_b) continue; - if(check_different_haps(nsg, ug, read_g, v^1, av[i].v, - reverse_sources, &b_0, &b_1, ruIndex, is_r_het, 2, 1) == PLOID) - { - av[i].del = 1; - asg_arc_del(nsg, av[i].v^1, v^1, 1); - } - } - - } - - free(b_0.b.a); - free(b_1.b.a); - -} - -void update_hap_label(ma_ug_t *ug, asg_t* read_g) -{ - uint32_t v, n_vtx, k; - uint64_t rId; - - if(ug == NULL) - { - n_vtx = read_g->n_seq; - for (v = 0; v < n_vtx; ++v) - { - if(read_g->seq[v].del) continue; - if(read_g->seq[v].c != HAP_LABLE) continue; - read_g->seq[v].c = PRIMARY_LABLE; - } - return; - } - - - asg_t* nsg = ug->g; - n_vtx = nsg->n_seq; - ma_utg_t* u = NULL; - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - if(nsg->seq[v].c != HAP_LABLE) continue; - u = &((ug)->u.a[v]); - if(u->m == 0) continue; - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - read_g->seq[rId].c = HAP_LABLE; - } - } -} - - -uint8_t* get_utg_attributes(ma_ug_t *ug, asg_t* read_g, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex) -{ - asg_t* nsg = ug->g; - uint32_t v, n_vtx = nsg->n_seq, k, j, rId, available_reads = 0, tn, is_Unitig; - ma_utg_t* u = NULL; - ma_hit_t *h; - long long R_bases = 0, C_bases = 0, C_bases_primary = 0, C_bases_alter = 0; - uint8_t* r_flag = (uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)); - uint8_t* u_flag = (uint8_t*)calloc(n_vtx, sizeof(uint8_t)); - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - u = &(ug->u.a[v]); - if(u->m == 0) continue; - available_reads = 0; - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 1; - } - - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - C_bases = C_bases_primary = C_bases_alter = 0; - R_bases = coverage_cut[rId].e - coverage_cut[rId].s; - for (j = 0; j < (uint64_t)(sources[rId].length); j++) - { - h = &(sources[rId].buffer[j]); - if(h->el != 1) continue; - tn = Get_tn((*h)); - if(read_g->seq[tn].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - if(read_g->seq[tn].del == 1) continue; - if(r_flag[tn]) - { - C_bases_primary += Get_qe((*h)) - Get_qs((*h)); - } - else - { - C_bases_alter += Get_qe((*h)) - Get_qs((*h)); - } - } - - C_bases = C_bases_primary + C_bases_alter; - if(C_bases_alter < C_bases * ALTER_COV_THRES) continue; - - C_bases = C_bases/R_bases; - if(C_bases >= asm_opt.recover_atg_cov_min && C_bases <= asm_opt.recover_atg_cov_max) - { - available_reads++; - } - } - - - if(available_reads < (u->n * 0.8) || available_reads == 0) - { - u_flag[v] = 0; - } - else - { - u_flag[v] = 1; - } - - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - r_flag[rId] = 0; - } - } - - free(r_flag); - return u_flag; -} - -void purge_dump(ma_ug_t* ug) -{ - asg_t* nsg = ug->g; - uint32_t v, n_vtx = nsg->n_seq, k, rId; - ma_utg_t *u = NULL; - for (v = 0; v < n_vtx; ++v) { - if (nsg->seq[v].del) continue; - u = &((ug)->u.a[v]); - if(u->m == 0) continue; - for (k = 0; k < u->n; k++){ - rId = u->a[k]>>33; - if(R_INF.trio_flag[rId] != AMBIGU && R_INF.trio_flag[rId] != DROP) break; - } - if(k >= u->n){ - if(u->m != 0){ - u->circ = u->end = u->len = u->m = u->n = u->start = 0; - free(u->a); - u->a = NULL; - } - asg_seq_del(nsg, v); - } - } - asg_cleanup(nsg); -} - -void discard_small_ctg(ma_ug_t **ug, asg_t* rg, kvec_asg_arc_t_warp* edge, int32_t max_rg_cut, uint32_t is_renew0, uint32_t is_renew1) -{ - if(is_renew0) renew_utg(ug, rg, edge); - uint32_t i, cnt = 0; ma_utg_t* u = NULL; - for (i = 0; i < (*ug)->u.n; i++) { - if(((int32_t)(*ug)->u.a[i].n) > max_rg_cut) continue; - u = &(((*ug))->u.a[i]); - asg_seq_del((*ug)->g, i); - if(u->m!=0) { - u->m = u->n = 0; free(u->a); u->a = NULL; u->len = u->circ = 0; u->start = u->end = 0; - } - cnt++; - } - - if(cnt && is_renew1) renew_utg(ug, rg, edge); -} - - -void adjust_utg_by_trio(ma_ug_t **ug, asg_t* read_g, uint8_t flag, float drop_rate, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, -R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, int gap_fuzz, -kvec_asg_arc_t_warp* new_rtg_edges, bub_label_t* b_mask_t) -{ - asg_t* nsg = (*ug)->g; - uint32_t v, n_vtx = nsg->n_seq; - hap_cov_t *cov = init_hap_cov_t(*ug, read_g, sources, ruIndex, reverse_sources, - coverage_cut, max_hang, min_ovlp, asm_opt.purge_level_trio>0?1:0); - if(cov->t_ch) cov->t_ch->ir_het = cov->is_r_het; - - if(asm_opt.recover_atg_cov_min == -1024) - { - asm_opt.recover_atg_cov_max = (asm_opt.hom_global_coverage_set? - (asm_opt.hom_global_coverage):(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); - asm_opt.recover_atg_cov_min = asm_opt.recover_atg_cov_max * 0.85; - asm_opt.recover_atg_cov_max = INT32_MAX; - } - if(asm_opt.recover_atg_cov_max != INT32_MAX) - { - fprintf(stderr, "[M::%s] primary contig coverage range: [%d, %d]\n", - __func__, asm_opt.recover_atg_cov_min, asm_opt.recover_atg_cov_max); - } - else - { - fprintf(stderr, "[M::%s] primary contig coverage range: [%d, infinity]\n", - __func__, asm_opt.recover_atg_cov_min); - } - - // fprintf(stderr, "[M::%s] 0\n", __func__); dbg_asys_gfa((*ug)->g); - adjust_utg_advance(read_g, (*ug), reverse_sources, ruIndex, b_mask_t, cov->is_r_het); - // fprintf(stderr, "[M::%s] 1\n", __func__); dbg_asys_gfa((*ug)->g); - - ///primary_flag = get_utg_attributes(*ug, read_g, coverage_cut, sources, ruIndex); - update_unitig_graph((*ug), read_g, coverage_cut, sources, reverse_sources, ruIndex, cov->is_r_het, 0, - DOUBLE_CHECK_THRES, flag, drop_rate); - // fprintf(stderr, "[M::%s] 2\n", __func__); dbg_asys_gfa((*ug)->g); - - nsg = (*ug)->g; - n_vtx = nsg->n_seq; - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - nsg->seq[v].c = PRIMARY_LABLE; - EvaluateLen((*ug)->u, v) = (*ug)->u.a[v].n; - } - // fprintf(stderr, "[M::%s] 3\n", __func__); - clean_trio_untig_graph(*ug, read_g, coverage_cut, sources, reverse_sources, tipsLen, - tip_drop_ratio, stops_threshold, ruIndex, NULL, NULL, 0, 0, 0, chimeric_rate, 0, 0, drop_ratio, flag, drop_rate, max_hang, min_ovlp, gap_fuzz, cov, new_rtg_edges); - // fprintf(stderr, "[M::%s] 4\n", __func__); - - ///delete_useless_nodes(ug); - delete_useless_trio_nodes(ug, read_g, coverage_cut, sources, ruIndex, flag, 0.8, 0.15, 16); - // fprintf(stderr, "[M::%s] 5\n", __func__); - - update_hap_label(*ug, read_g); - // fprintf(stderr, "[M::%s] 6\n", __func__); - - update_unitig_graph((*ug), read_g, coverage_cut, sources, reverse_sources, ruIndex, cov->is_r_het, 0, - DOUBLE_CHECK_THRES, flag, drop_rate); - // fprintf(stderr, "[M::%s] 7\n", __func__); - - force_trio_clean((*ug), read_g, coverage_cut, sources, reverse_sources, ruIndex, flag, 0.55, 0.01, 5); - // fprintf(stderr, "[M::%s] 8\n", __func__); - ///if(flag == MOTHER) print_debug_gfa(read_g, *ug, coverage_cut, "debug_trio_1", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); - - renew_utg(ug, read_g, new_rtg_edges); - // fprintf(stderr, "[M::%s] 9\n", __func__); - - if (!(asm_opt.flag & HA_F_BAN_POST_JOIN)) - { - rescue_missing_overlaps_aggressive(*ug, read_g, sources, coverage_cut, ruIndex, max_hang, - min_ovlp, 0, 1, NULL, b_mask_t); - // fprintf(stderr, "[M::%s] 10\n", __func__); - - renew_utg(ug, read_g, new_rtg_edges); - // fprintf(stderr, "[M::%s] 11\n", __func__); - - rescue_contained_reads_aggressive(*ug, read_g, sources, coverage_cut, ruIndex, max_hang, - min_ovlp, 10, 0, 1, NULL, NULL, b_mask_t); - // fprintf(stderr, "[M::%s] 12\n", __func__); - - renew_utg(ug, read_g, new_rtg_edges); - // fprintf(stderr, "[M::%s] 13\n", __func__); - } - - ///if(flag == MOTHER) print_untig_by_read(*ug, "m64043_200627_000137/124716590/ccs", 2789716, NULL, NULL, "beg"); - - - update_unitig_graph((*ug), read_g, coverage_cut, sources, reverse_sources, ruIndex, cov->is_r_het, 1, - FINAL_DOUBLE_CHECK_THRES, flag, drop_rate); - // fprintf(stderr, "[M::%s] 14\n", __func__); - - update_hap_label(NULL, read_g); - // fprintf(stderr, "[M::%s] 15\n", __func__); - - renew_utg(ug, read_g, new_rtg_edges); - // fprintf(stderr, "[M::%s] 16\n", __func__); - - ///delete_useless_nodes(ug); - delete_useless_trio_nodes(ug, read_g, coverage_cut, sources, ruIndex, flag, 0.8, 0.15, 16); - // fprintf(stderr, "[M::%s] 17\n", __func__); - - - if(asm_opt.purge_level_trio == 1) - { - purge_dups(*ug, read_g, coverage_cut, sources, reverse_sources, ruIndex, new_rtg_edges, - asm_opt.purge_simi_thres, asm_opt.purge_overlap_len, max_hang, min_ovlp, drop_ratio, 1, 0, - cov, 0, 0); - ///delete_useless_nodes(ug); - delete_useless_trio_nodes(ug, read_g, coverage_cut, sources, ruIndex, flag, 0.8, 0.15, 16); - } - // fprintf(stderr, "[M::%s] 18\n", __func__); - - if(asm_opt.max_contig_tip > 0) { - discard_small_ctg(ug, read_g, new_rtg_edges, asm_opt.max_contig_tip, 1, 0); - } - - // fprintf(stderr, "[M::%s] 19\n", __func__); - set_drop_trio_flag(*ug); - destory_hap_cov_t(&cov); - // fprintf(stderr, "[M::%s] 20\n", __func__); - // purge_dump(*ug); - renew_utg(ug, read_g, new_rtg_edges); - // fprintf(stderr, "[M::%s] 21\n", __func__); -} - - -int debug_untig_length(ma_ug_t *g, uint32_t tipsLen, const char* name) -{ - uint32_t i; - - for (i = 0; i < g->u.n; ++i) { - ma_utg_t *u = &g->u.a[i]; - if(u->m == 0) continue; - if(u->n <= tipsLen) - { - fprintf(stderr, "i: %u, u->n: %u, tipsLen: %u, %s\n", i, u->n, tipsLen, name); - } - } - - return 0; -} - -void prt_phase_dbg_graph(char *in, asg_t *sg, ma_sub_t *cov, ma_hit_t_alloc *src, R_to_U* ri, int max_hang, int min_ovlp) -{ - char* gfa_name = (char*)malloc(strlen(in)+100); - sprintf(gfa_name, "%s.phase", in); - uint64_t pscut = 0; - pscut = (asm_opt.hom_global_coverage_set?(asm_opt.hom_global_coverage):(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); - pscut *= PHASE_SEF; if(pscut < PHASE_SEP) pscut = PHASE_SEP; - ma_ug_t *ug = ma_ug_gen_phase(sg, pscut, PHASE_SEP_RATE); - print_debug_gfa(sg, ug, cov, gfa_name, src, ri, max_hang, min_ovlp, 0, 0, 0); - ma_ug_destroy(ug); - - sprintf(gfa_name, "%s.raw", in); - ug = ma_ug_gen(sg); - print_debug_gfa(sg, ug, cov, gfa_name, src, ri, max_hang, min_ovlp, 0, 0, 0); - ma_ug_destroy(ug); - - free(gfa_name); -} - -ma_ug_t* output_trio_unitig_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -uint8_t flag, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, -float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, int gap_fuzz, -int is_bench, bub_label_t* b_mask_t, char *f_prefix, uint8_t *kpt_buf, kvec_asg_arc_t_warp *r_edges) -{ - char* gfa_name = (char*)malloc(strlen(output_file_name)+100); - sprintf(gfa_name, "%s.%s.p_ctg.gfa", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); - FILE* output_file = NULL; - if(is_bench == 0) output_file = fopen(gfa_name, "w"); - - // prt_phase_dbg_graph(gfa_name, sg, coverage_cut, sources, ruIndex, max_hang, min_ovlp); - - ma_ug_t *ug = NULL; uint64_t pscut = 0; - // ug = ma_ug_gen(sg); - pscut = (asm_opt.hom_global_coverage_set?(asm_opt.hom_global_coverage):(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); - pscut *= PHASE_SEF; if(pscut < PHASE_SEP) pscut = PHASE_SEP; - ug = ma_ug_gen_phase(sg, pscut, PHASE_SEP_RATE); - - kvec_asg_arc_t_warp new_rtg_edges; - kv_init(new_rtg_edges.a); - adjust_utg_by_trio(&ug, sg, flag, TRIO_THRES, sources, reverse_sources, coverage_cut, - tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, - min_ovlp, gap_fuzz, &new_rtg_edges, b_mask_t); - if(asm_opt.b_low_cov > 0) - { - break_ug_contig(&ug, sg, &R_INF, coverage_cut, sources, ruIndex, &new_rtg_edges, max_hang, min_ovlp, - &asm_opt.b_low_cov, NULL, asm_opt.m_rate); - } - if(asm_opt.b_high_cov > 0) - { - break_ug_contig(&ug, sg, &R_INF, coverage_cut, sources, ruIndex, &new_rtg_edges, max_hang, min_ovlp, - NULL, &asm_opt.b_high_cov, asm_opt.m_rate); - } - if(kpt_buf) - { - update_dump_trio(R_INF.trio_flag, sg->n_seq, kpt_buf, ug); - } - if(is_bench) - { - free(gfa_name); - if(r_edges && new_rtg_edges.a.n > 0) { - kv_resize(asg_arc_t, r_edges->a, r_edges->a.n + new_rtg_edges.a.n); - memcpy(r_edges->a.a + r_edges->a.n, new_rtg_edges.a.a, new_rtg_edges.a.n*sizeof(asg_arc_t)); - r_edges->a.n += new_rtg_edges.a.n; - } - kv_destroy(new_rtg_edges.a); - return ug; - } - - fprintf(stderr, "Writing %s to disk... \n", gfa_name); - ///debug_utg_graph(ug, sg, 0, 0); - ///debug_untig_length(ug, tipsLen, gfa_name); - ///print_untig_by_read(ug, "m64011_190901_095311/125831121/ccs", 2310925, "end"); - ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 1); - ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, (flag==FATHER?"h1tg":"h2tg"), output_file); - fclose(output_file); - - sprintf(gfa_name, "%s.%s.p_ctg.noseq.gfa", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); - output_file = fopen(gfa_name, "w"); - ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, (flag==FATHER?"h1tg":"h2tg"), output_file); - fclose(output_file); - if(asm_opt.bed_inconsist_rate != 0) - { - sprintf(gfa_name, "%s.%s.p_ctg.lowQ.bed", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); - output_file = fopen(gfa_name, "w"); - ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, - max_hang, min_ovlp, asm_opt.bed_inconsist_rate, (flag==FATHER?"h1tg":"h2tg"), output_file, NULL); - fclose(output_file); - } - - free(gfa_name); - ma_ug_destroy(ug); - kv_destroy(new_rtg_edges.a); - return NULL; -} - - -void output_hap_graph(ma_ug_t *ug, asg_t *sg, kvec_asg_arc_t_warp *arcs, -ma_sub_t* coverage_cut, char* output_file_name, uint8_t flag, ma_hit_t_alloc* sources, -R_to_U* ruIndex, int max_hang, int min_ovlp, char *f_prefix) -{ - char* gfa_name = (char*)malloc(strlen(output_file_name)+100); - sprintf(gfa_name, "%s.%s.p_ctg.gfa", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); - FILE* output_file = fopen(gfa_name, "w"); - - fprintf(stderr, "Writing %s to disk... \n", gfa_name); - ///debug_utg_graph(ug, sg, 0, 0); - ///debug_untig_length(ug, tipsLen, gfa_name); - ///print_untig_by_read(ug, "m64011_190901_095311/125831121/ccs", 2310925, "end"); - ma_ug_seq(ug, sg, coverage_cut, sources, arcs, max_hang, min_ovlp, 0, 1); - ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, (flag==FATHER?"h1tg":"h2tg"), output_file); - fclose(output_file); - - sprintf(gfa_name, "%s.%s.p_ctg.noseq.gfa", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); - output_file = fopen(gfa_name, "w"); - ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, (flag==FATHER?"h1tg":"h2tg"), output_file); - fclose(output_file); - if(asm_opt.bed_inconsist_rate != 0) - { - sprintf(gfa_name, "%s.%s.p_ctg.lowQ.bed", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); - output_file = fopen(gfa_name, "w"); - ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, arcs, - max_hang, min_ovlp, asm_opt.bed_inconsist_rate, (flag==FATHER?"h1tg":"h2tg"), output_file, NULL); - fclose(output_file); - } - - free(gfa_name); -} - -void output_hap_sc_graph(kvect_sec_t *ug, asg_t *sg, /**kvec_asg_arc_t_warp *arcs,**/ ma_sub_t* coverage_cut, char* output_file_name, uint8_t flag, ma_hit_t_alloc* sources, R_to_U* ruIndex, /**int max_hang, int min_ovlp,**/ char *f_prefix) -{ - char* gfa_name = (char*)malloc(strlen(output_file_name)+100); - sprintf(gfa_name, "%s.%s.p_ctg.gfa", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); - FILE* output_file = fopen(gfa_name, "w"); - - fprintf(stderr, "Writing %s to disk... \n", gfa_name); - - // ma_ug_seq(ug->ctg, sg, coverage_cut, sources, arcs, max_hang, min_ovlp, 0, 1); - // ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, (flag==FATHER?"h1tg":"h2tg"), output_file); - ma_scg_print(ug, &R_INF, sg, coverage_cut, sources, ruIndex, 1, (flag==FATHER?"h1tg":"h2tg"), output_file); - fclose(output_file); - - free(gfa_name); -} - - -void filter_set_kug(uint8_t* trio_flag, asg_t *rg, uint8_t *rf, kvec_asg_arc_t_warp *r_edges, float f_rate, ma_ug_t **ug) -{ - asg_t* nsg = (*ug)->g; ma_utg_t *u = NULL; - uint32_t k, v, n_vtx = nsg->n_seq, rn = rg->n_seq; - int64_t flag_occ; - for (k = 0; k < rn; k++) { - trio_flag[k] = rf[k]>>1; - if(trio_flag[k] != FATHER && trio_flag[k] != MOTHER) trio_flag[k] = AMBIGU; - } - - for (k = 0; k < nsg->n_arc; k++) nsg->arc[k].del = 1; - for (v = 0; v < n_vtx; ++v) { - if (nsg->seq[v].del) continue; - u = &((*ug)->u.a[v]); - if(u->m == 0) continue; - for (k = flag_occ = 0; k < u->n; k++) flag_occ += (rf[u->a[k]>>33]&1); - if (flag_occ == (int64_t)u->n || flag_occ >= (int64_t)(u->n*f_rate)) { - if(u->m != 0){ - u->circ = u->end = u->len = u->m = u->n = u->start = 0; - free(u->a); - u->a = NULL; - } - nsg->seq[v].del = 1; - } - } - asg_cleanup(nsg); - renew_utg(ug, rg, r_edges); - - char name[32]; - for (v = 0, n_vtx = (*ug)->g->n_seq; v < n_vtx; ++v) { - u = &((*ug)->u.a[v]); - if(u->m == 0) continue; - for (k = flag_occ = 0; k < u->n; k++) flag_occ += (rf[u->a[k]>>33]&1); - sprintf(name, "ptg%.6d%c", v + 1, "lc"[u->circ]); - fprintf(stderr, "S\t%s\t*\tTN:i:%u\tUN:i:%ld\n", name, u->n, flag_occ); - } -} - - -void output_trio_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, -long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, -int min_ovlp, int is_bench, long long gap_fuzz, ug_opt_t *opt, bub_label_t* b_mask_t) -{ - reduce_hamming_error_adv(NULL, sg, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz, opt->ruIndex, NULL); - uint8_t *rf = NULL; - - if(asm_opt.kpt_rate > 0) CALLOC(rf, sg->n_seq); - - output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, - reverse_sources, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, - drop_ratio, max_hang, min_ovlp, gap_fuzz, is_bench, b_mask_t, NULL, rf, NULL); - - output_trio_unitig_graph(sg, coverage_cut, output_file_name, MOTHER, sources, - reverse_sources, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, - drop_ratio, max_hang, min_ovlp, gap_fuzz, is_bench, b_mask_t, NULL, rf, NULL); - - if(rf) { - kvec_asg_arc_t_warp r_edges; kv_init(r_edges.a); - ma_ug_t *kug = NULL; - char* kug_n = (char*)malloc(strlen(output_file_name)+100); - sprintf(kug_n, "%s.kdp", output_file_name); - - update_dump_trio(R_INF.trio_flag, sg->n_seq, rf, NULL); - kug = output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, - reverse_sources, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, - drop_ratio, max_hang, min_ovlp, gap_fuzz, 1, b_mask_t, NULL, NULL, &r_edges); - filter_set_kug(R_INF.trio_flag, sg, rf, &r_edges, asm_opt.kpt_rate, &kug); - print_utg(&kug, sg, coverage_cut, kug_n, sources, ruIndex, max_hang, min_ovlp, &r_edges); - - free(kug_n), kv_destroy(r_edges.a); ma_ug_destroy(kug); - free(rf); - } -} - -dedup_idx_t *gen_dedup_idx_t(ma_ug_t *ug, asg_t *rg) -{ - // fprintf(stderr, "[M::%s] Start\n", __func__); - dedup_idx_t *p = NULL; CALLOC(p, 1); - p->rg = rg; p->ug = ug; p->ridx_n = rg->n_seq + 1; - uint64_t k, m, l, z, *a, a_n; ma_utg_t *u; - - CALLOC(p->ridx, p->ridx_n); - for (k = p->ra_n = 0; k < ug->u.n; k++) { - u = &(ug->u.a[k]); p->ra_n += u->n; - if(!(u->n)) continue; - for (z = 0; z < u->n; z++) p->ridx[u->a[z]>>33]++; - } - for (k = l = 0; k < p->ridx_n; k++) { - m = p->ridx[k]; p->ridx[k] = l; l += m; - } - - - MALLOC(p->ra, p->ra_n); memset(p->ra, -1, sizeof((*(p->ra)))*p->ra_n); - for (k = 1; k < p->ridx_n; k++) { - a = p->ra + p->ridx[k-1]; - a_n = p->ridx[k] - p->ridx[k-1]; - if(a_n) a[a_n-1] = 0; - } - - for (k = 0; k < ug->u.n; k++) { - u = &(ug->u.a[k]); - if(!(u->n)) continue; - for (z = 0; z < u->n; z++) { - a = p->ra + p->ridx[u->a[z]>>33]; - a_n = p->ridx[(u->a[z]>>33)+1] - p->ridx[u->a[z]>>33]; - if(a_n) { - if(a[a_n-1] == a_n-1) a[a_n-1] = (k<<32)|z; - else a[a[a_n-1]++] = (k<<32)|z; - } - } - } - // fprintf(stderr, "[M::%s] End\n", __func__); - return p; -} - -void destroy_dedup_idx_t(dedup_idx_t *p) -{ - // fprintf(stderr, "[M::%s] Start\n", __func__); - if(p == NULL) return; - free(p->ridx); free(p->ra); free(p); - // fprintf(stderr, "[M::%s] End\n", __func__); -} - -void update_recover_atg_cov() -{ - if(asm_opt.recover_atg_cov_min == -1024) { - asm_opt.recover_atg_cov_max = (asm_opt.hom_global_coverage_set? - (asm_opt.hom_global_coverage):(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); - asm_opt.recover_atg_cov_min = asm_opt.recover_atg_cov_max * 0.85; - asm_opt.recover_atg_cov_max = INT32_MAX; - } -} - -int64_t cal_exact_ug_o(dedup_idx_t *idx, ma_utg_t *u, uint64_t f) -{ - if(u->n <= 0) return INT32_MIN; - uint64_t sv, *sa, sn, ev, *ea, en, si, ei, zn, *za, rev, k, nf = (uint64_t)-1, m, fn, nfn; ma_utg_t *z; - if(f == FATHER) nf = MOTHER; if(f == MOTHER) nf = FATHER; - sv = u->a[0]>>32; sa = idx->ra + idx->ridx[sv>>1]; sn = idx->ridx[(sv>>1)+1]-idx->ridx[sv>>1]; - ev = u->a[u->n-1]>>32; ea = idx->ra + idx->ridx[ev>>1]; en = idx->ridx[(ev>>1)+1] - idx->ridx[ev>>1]; - for (si = 0; si < sn; si++) { - z = &(idx->ug->u.a[sa[si]>>32]); - if((z->n == 0) || (z->m == 0) || (idx->ug->g->seq[sa[si]>>32].del)) continue; - assert(((z->a[(uint32_t)sa[si]]>>32)>>1) == (sv>>1)); - if((z->a[(uint32_t)sa[si]]>>32) == sv) rev = 0; - else rev = 1; - for (ei = 0; ei < en; ei++) { - if((idx->ug->u.a[ea[ei]>>32].n == 0) || (idx->ug->u.a[ea[ei]>>32].m == 0) || (idx->ug->g->seq[ea[ei]>>32].del)) continue; - assert(((idx->ug->u.a[ea[ei]>>32].a[(uint32_t)ea[ei]]>>32)>>1) == (ev>>1)); - if((sa[si]>>32) != (ea[ei]>>32)) continue;///not the same uid - if(((uint32_t)sa[si]) >= ((uint32_t)ea[ei])) { - zn = ((uint32_t)sa[si]) - ((uint32_t)ea[ei]) + 1; za = z->a + ((uint32_t)ea[ei]); - } else { - zn = ((uint32_t)ea[ei]) - ((uint32_t)sa[si]) + 1; za = z->a + ((uint32_t)sa[si]); - } - if(u->n != zn) continue; - if(!rev) { - for (k = 0; (k < zn) && ((u->a[k]>>32) == ((za[k]>>32))); k++); - if(k < zn) continue; - } else { - for (k = 0; (k < zn) && ((u->a[k]>>32) == (((uint64_t)(za[zn-k-1]>>32))^1)); k++); - if(k < zn) continue; - } - - assert(u->n <= z->n); - if(u->n < z->n) { - return -1;///delete u - } else if(u->n == z->n) { - for (m = fn = nfn = 0; m < u->n; m++) { - if(R_INF.trio_flag[u->a[m]>>33] == f) fn++; - if(R_INF.trio_flag[u->a[m]>>33] == nf) nfn++; - } - if(fn < nfn) return -1;///delete u - else return sa[si]>>32;///delete z - } - } - } - return INT32_MIN; -} - -void delete_ug_node(ma_ug_t *ug, uint64_t nid) -{ - asg_seq_del(ug->g, nid); - if(ug->u.a[nid].m!=0) { - ug->u.a[nid].m = ug->u.a[nid].n = 0; - free(ug->u.a[nid].a); ug->u.a[nid].a = NULL; - } -} - -uint64_t dedup_exact_ug(dedup_idx_t *ref, dedup_idx_t *qry, ma_sub_t *cov, ma_hit_t_alloc *src, R_to_U *rui, uint8_t *ff, uint8_t trio_f) -{ - // fprintf(stderr, "[M::%s] Start\n", __func__); - uint64_t k, n_base = 0; int64_t f; - for (k = 0; k < qry->ug->u.n; k++) { - if((qry->ug->u.a[k].n == 0) || (qry->ug->u.a[k].m == 0) || (qry->ug->g->seq[k].del)) continue; - if(if_primary_unitig(&(qry->ug->u.a[k]), qry->rg, cov, src, rui, ff)) continue; - f = cal_exact_ug_o(ref, &(qry->ug->u.a[k]), trio_f); - if(f == INT32_MIN) continue; - if(f == -1) {///delete qry - delete_ug_node(qry->ug, k); n_base += qry->ug->u.a[k].len; - } else if(f >= 0) {///delete ref - delete_ug_node(ref->ug, f); n_base += ref->ug->u.a[f].len; - } - } - // fprintf(stderr, "[M::%s] End\n", __func__); - return n_base; -} - -void push_ma_utg_t(ma_ug_t *ug, ma_utg_t *u) -{ - ma_utg_t *p; - ///graph - asg_seq_set(ug->g, ug->u.n, u->len, 0); ug->g->seq[ug->u.n].c = 0; - - //unitig - kv_pushp(ma_utg_t, ug->u, &p); memset(p, 0, sizeof((*p))); - *p = *u; p->a = NULL; p->s = NULL; - MALLOC(p->a, p->m); memcpy(p->a, u->a, sizeof((*(p->a)))*p->m); - if(u->s) { - MALLOC(p->s, p->len); memcpy(p->s, u->s, sizeof((*(p->s)))*p->len); - } - assert(ug->g->n_seq == ug->u.n); - if(p->n) { - p->circ = 0; p->start = (p->a[0]>>32); p->end = (p->a[p->n-1]>>32)^1; - } -} - -uint64_t append_miss_nid(asg_t *sg, ma_ug_t *hap0, ma_ug_t *hap1, uint8_t *ff, uint64_t len_cut, uint64_t occ_cut) -{ - ma_ug_t *ug = NULL; ma_utg_t *u; uint64_t k, z, pscut, n_set, fn, nfn, hap0n, hap1n, n_base = 0; - kvec_asg_arc_t_warp fe; memset(&fe, 0, sizeof(fe)); - memset(ff, 0, sizeof((*ff))*sg->n_seq); - ug = hap0; - for (k = 0; k < ug->u.n; k++) { - u = &(ug->u.a[k]); - if((u->n == 0) || (u->m == 0) || (ug->g->seq[k].del)) continue; - for (z = 0; z < u->n; z++) ff[u->a[z]>>33] = 1; - } - ug = hap1; - for (k = 0; k < ug->u.n; k++) { - u = &(ug->u.a[k]); - if((u->n == 0) || (u->m == 0) || (ug->g->seq[k].del)) continue; - for (z = 0; z < u->n; z++) ff[u->a[z]>>33] = 1; - } - ug = NULL; pscut = 0; - pscut = (asm_opt.hom_global_coverage_set?(asm_opt.hom_global_coverage):(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); - pscut *= PHASE_SEF; if(pscut < PHASE_SEP) pscut = PHASE_SEP; - ug = ma_ug_gen_phase(sg, pscut, PHASE_SEP_RATE); - for (k = 0; k < ug->u.n; k++) { - u = &(ug->u.a[k]); - if((u->n == 0) || (u->m == 0) || (ug->g->seq[k].del)) continue; - for (z = n_set = 0; z < u->n; z++) { - if(ff[u->a[z]>>33]) n_set++; - } - if((n_set > 0) && (n_set >= (u->n*0.2))) delete_ug_node(ug, k); - } - renew_utg((&ug), sg, &fe); - - for (k = hap0n = hap1n = 0; k < ug->u.n; k++) { - u = &(ug->u.a[k]); - if((u->n == 0) || (u->m == 0) || (ug->g->seq[k].del)) continue; - if((u->len < len_cut) || (u->n < occ_cut)) continue; - for (z = n_set = 0; z < u->n; z++) { - if(ff[u->a[z]>>33]) n_set++; - } - if((n_set > 0) && (n_set >= (u->n*0.2))) continue; - for (z = fn = nfn = 0; z < u->n; z++) { - if(R_INF.trio_flag[u->a[z]>>33] == FATHER) fn++; - if(R_INF.trio_flag[u->a[z]>>33] == MOTHER) nfn++; - } - if(fn > nfn) { - push_ma_utg_t(hap0, u); hap0n++; n_base += u->len; - } else { - push_ma_utg_t(hap1, u); hap1n++; n_base += u->len; - } - } - ma_ug_destroy(ug); ug = NULL; - if(hap0n) { - ug = hap0; - free(ug->g->idx); ug->g->idx = 0; ug->g->is_srt = 0; - asg_cleanup(ug->g); asg_symm(ug->g); - if(ug->g->seq_vis) { - REALLOC(ug->g->seq_vis, (ug->g->n_seq*2)); - memset(ug->g->seq_vis, 0, sizeof((*(ug->g->seq_vis)))*(ug->g->n_seq*2)); - } - } - if(hap1n) { - ug = hap1; - free(ug->g->idx); ug->g->idx = 0; ug->g->is_srt = 0; - asg_cleanup(ug->g); asg_symm(ug->g); - if(ug->g->seq_vis) { - REALLOC(ug->g->seq_vis, (ug->g->n_seq*2)); - memset(ug->g->seq_vis, 0, sizeof((*(ug->g->seq_vis)))*(ug->g->n_seq*2)); - } - } - return n_base; -} - -void prt_scaf_res_t(scaf_res_t *pa, ma_ug_t *ref, ma_ug_t *ctg, const char *cn) -{ - uint32_t k, i, z, a_n; ma_utg_t *rch; ul_vec_t *idx; uc_block_t *a; - for(i = 0; i < ctg->u.n; i++) { - rch = &(ctg->u.a[i]); idx = &(pa->a[i]); - fprintf(stderr, "[M::%s] %s%.6u%c. rch->len::%u, rch->n::%u, idx->n::%u\n", __func__, cn, i + 1, "lc"[rch->circ], (uint32_t)rch->len, (uint32_t)rch->n, (uint32_t)idx->bb.n); - if(idx->bb.n > 1) fprintf(stderr, "[M::%s::>>>>>>] idx->n::%u\n", __func__, (uint32_t)idx->bb.n); - // for (k = 0; k < idx->bb.n; k++) { - // fprintf(stderr, "[k->%u::utg%.6u%c(len->%u::n->%u)]\tq::[%u, %u)\t%c\tt::[%u, %u)\n", - // k, (idx->bb.a[k].hid) + 1, "lc"[ref->u.a[(idx->bb.a[k].hid)].circ], ref->u.a[(idx->bb.a[k].hid)].len, ref->u.a[(idx->bb.a[k].hid)].n, - // idx->bb.a[k].qs, idx->bb.a[k].qe, "+-"[idx->bb.a[k].rev], idx->bb.a[k].ts, idx->bb.a[k].te); - // } - - for (k = 0; k < idx->bb.n; k++) { - a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; - fprintf(stderr, "q::[%u, %u)\n", idx->bb.a[k].qs, idx->bb.a[k].qe); - for (z = 0; z < a_n; z++) fprintf(stderr, "utg%.6u%c,", (a[z].hid)+1, "lc"[ref->u.a[a[z].hid].circ]); - fprintf(stderr, "\n"); - for (z = 0; z < a_n; z++) fprintf(stderr, "utg%.6u%c[%u,%u),", (a[z].hid)+1, "lc"[ref->u.a[a[z].hid].circ], a[z].qs, a[z].qe); - fprintf(stderr, "\n"); - } - } -} - - -typedef struct { - uint32_t len[2], num[2], h; -} ug_res_t; - -typedef struct { - uint32_t *idx; - ug_res_t *map; - uint8_t *f; - ma_ug_t *ref; - kvec_t_u32_warp st, res; -} tangle_res_t; - - -ma_ug_t *gen_clean_ug(ma_ug_t *ref, scaf_res_t *cp0, scaf_res_t *cp1) -{ - ma_ug_t *ug = copy_untig_graph(ref); - uint32_t i, k, a_n, z, v, w; scaf_res_t *ctg = NULL; ul_vec_t *idx; uc_block_t *a; - if(cp0 || cp1) { - for (i = 0; i < ug->g->n_seq; i++) ug->g->seq[i].del = 1; - for (i = 0; i < ug->g->n_arc; i++) ug->g->arc[i].del = 1; - - ctg = cp0; - if (ctg) { - for(i = 0; i < ctg->n; i++) { - idx = &(ctg->a[i]); - for (k = 0; k < idx->bb.n; k++) { - a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; - for (z = 0; z < a_n; z++) ug->g->seq[a[z].hid].del = 0; - for (z = 1; z < a_n; z++) { - v = a[z-1].hid<<1; v |= (uint32_t)a[z-1].rev; - w = a[z].hid<<1; w |= (uint32_t)a[z].rev; - - asg_arc_del(ug->g, v, w, 0); - asg_arc_del(ug->g, w^1, v^1, 0); - } - } - } - } - - ctg = cp1; - if (ctg) { - for(i = 0; i < ctg->n; i++) { - idx = &(ctg->a[i]); - for (k = 0; k < idx->bb.n; k++) { - a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; - for (z = 0; z < a_n; z++) ug->g->seq[a[z].hid].del = 0; - for (z = 1; z < a_n; z++) { - v = a[z-1].hid<<1; v |= (uint32_t)a[z-1].rev; - w = a[z].hid<<1; w |= (uint32_t)a[z].rev; - - asg_arc_del(ug->g, v, w, 0); - asg_arc_del(ug->g, w^1, v^1, 0); - } - } - } - } - } - - - for (i = 0; i < ug->g->n_seq; i++) { - if(ug->g->seq[i].del == 1) { - asg_seq_del(ug->g, i); - if(ug->u.a[i].m!=0) { - ug->u.a[i].m = ug->u.a[i].n = 0; - free(ug->u.a[i].a); - ug->u.a[i].a = NULL; - } - } - } - - asg_cleanup(ug->g); - - return ug; -} - -ma_ug_t *gen_shallow_clean_ug(ma_ug_t *ref, bubble_type *bu, scaf_res_t *cp0, scaf_res_t *cp1) -{ - ma_ug_t *ug = copy_untig_graph(ref); - uint32_t i, k, a_n, z, v, w; scaf_res_t *ctg = NULL; ul_vec_t *idx; uc_block_t *a; - if(cp0 || cp1) { - ///just clean bubbles - for (i = 0; i < ug->g->n_seq; i++) { - // if(i < bu->f_bub) ug->g->seq[i].del = 1;///no need broken bubble; looks like a bug in scaffolding - if(bu->index[i] < bu->f_bub) ug->g->seq[i].del = 1; - } - for (i = 0; i < ug->g->n_arc; i++) { - if((bu->index[ug->g->arc[i].ul>>33] < bu->f_bub) || (bu->index[ug->g->arc[i].v>>1] < bu->f_bub)) {///no need broken bubble - ug->g->arc[i].del = 1; - } - } - - ctg = cp0; - if (ctg) { - for(i = 0; i < ctg->n; i++) { - idx = &(ctg->a[i]); - for (k = 0; k < idx->bb.n; k++) { - a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; - for (z = 0; z < a_n; z++) ug->g->seq[a[z].hid].del = 0; - for (z = 1; z < a_n; z++) { - v = a[z-1].hid<<1; v |= (uint32_t)a[z-1].rev; - w = a[z].hid<<1; w |= (uint32_t)a[z].rev; - // if(((v>>1) < bu->f_bub) || ((w>>1) < bu->f_bub)) { - if((bu->index[(v>>1)] < bu->f_bub) || (bu->index[(w>>1)] < bu->f_bub)) { - asg_arc_del(ug->g, v, w, 0); - asg_arc_del(ug->g, w^1, v^1, 0); - } - } - } - } - } - - ctg = cp1; - if (ctg) { - for(i = 0; i < ctg->n; i++) { - idx = &(ctg->a[i]); - for (k = 0; k < idx->bb.n; k++) { - a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; - for (z = 0; z < a_n; z++) ug->g->seq[a[z].hid].del = 0; - for (z = 1; z < a_n; z++) { - v = a[z-1].hid<<1; v |= (uint32_t)a[z-1].rev; - w = a[z].hid<<1; w |= (uint32_t)a[z].rev; - // if(((v>>1) < bu->f_bub) || ((w>>1) < bu->f_bub)) { - if((bu->index[(v>>1)] < bu->f_bub) || (bu->index[(w>>1)] < bu->f_bub)) { - asg_arc_del(ug->g, v, w, 0); - asg_arc_del(ug->g, w^1, v^1, 0); - } - } - } - } - } - } - - - for (i = 0; i < ug->g->n_seq; i++) { - if(ug->g->seq[i].del == 1) { - asg_seq_del(ug->g, i); - if(ug->u.a[i].m!=0) { - ug->u.a[i].m = ug->u.a[i].n = 0; - free(ug->u.a[i].a); - ug->u.a[i].a = NULL; - } - } - } - - asg_cleanup(ug->g); - - return ug; -} - -static void worker_for_ctg_trans_cc(void *data, long i, int tid) // callback for kt_for() -{ - kv_u_trans_t *ta = (kv_u_trans_t*)data; - u_trans_t *a = NULL, *r_a = NULL, *mz, *cz; - uint32_t n, r_n, id = i, k, l, z; - - a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); - for (k = 1, l = 0; k <= n; k++) { - if(k == n || a[l].tn != a[k].tn) { - if(k > l) { - get_u_trans_spec(ta, a[l].tn, a[l].qn, &r_a, &r_n); - assert(r_n > 0); - if(id > a[l].tn) { - l = k; continue; - } - - mz = cz = NULL; - for (z = l; z < k; z++) { - cz = &(a[z]); cz->del = 1; - if((mz) && (mz->f == 1) && (cz->f != 1)) continue; - if((!mz) || ((cz->f == 1) && (mz->f != 1)) || ((cz->f == mz->f) && ((mz->nw < cz->nw) || ((mz->nw == cz->nw) && ((mz->qe - mz->qs) < (cz->qe - cz->qs)))))) { - mz = cz; - } - } - for (z = 0; z < r_n; z++) { - cz = &(r_a[z]); cz->del = 1; - if((mz) && (mz->f == 1) && (cz->f != 1)) continue; - if((!mz) || ((cz->f == 1) && (mz->f != 1)) || ((cz->f == mz->f) && ((mz->nw < cz->nw) || ((mz->nw == cz->nw) && ((mz->qe - mz->qs) < (cz->qe - cz->qs)))))) { - mz = cz; - } - } - - assert(mz); - mz->del = 0; - } - l = k; - } - } -} - -void update_ctg_trans_cc(kv_u_trans_t *os) -{ - uint64_t k, m; u_trans_t *z; - kt_for(asm_opt.thread_num, worker_for_ctg_trans_cc, os, os->idx.n); - for (k = m = 0; k < os->n; k++) { - if(!(os->a[k].del)) os->a[m++] = os->a[k]; - } - os->n = m; - for (k = 0; k < m; k++) { - kv_pushp(u_trans_t, *os, &z); - *z = os->a[k]; - z->qn = os->a[k].tn; z->qs = os->a[k].ts; z->qe = os->a[k].te; - z->tn = os->a[k].qn; z->ts = os->a[k].qs; z->te = os->a[k].qe; - } - kt_u_trans_t_idx(os, os->idx.n); -} - -uint32_t get_scaf_res_t(scaf_res_t *pa, uint32_t uid, uint32_t s, uint32_t e, uint32_t *in, uint32_t *rs, uint32_t *re, uint32_t *rn, uc_block_t **ra) -{ - // fprintf(stderr, "s::%u, e::%u, uid::%u, pa->n::%u\n", s, e, uid, (uint32_t)pa->n); - if(uid >= pa->n) return 0; - ul_vec_t *idx = &(pa->a[uid]); uint32_t k, z, a_n, os, oe, z0; uc_block_t *a; - (*rs) = (*re) = (uint32_t)-1; (*rn) = 0; (*ra) = NULL; - - for (k = (*in); k < idx->bb.n; k++) { - a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; - os = MAX(s, idx->bb.a[k].qs); - oe = MIN(e, idx->bb.a[k].qe); - // fprintf(stderr, "k::%u, os::%u, oe::%u, a_n::%u\n", k, os, oe, a_n); - if(os >= oe) continue; - for(z = 0; z < a_n && a[z].qe <= os; z++); - if(z >= a_n) continue; - for(z0 = z; z < a_n && a[z].qs < oe; z++); - if(z <= z0 ) continue; - *rs = os; *re = oe; *rn = z - z0; *ra = a + z0; (*in) = k + 1; - return 1; - } - return 0; -} - -void prt_scaf_res_t(ma_ug_t *ref, scaf_res_t *cp, ma_ug_t *ug, uint32_t uid, uint32_t s, uint32_t e, const char *pfx, uint32_t bw) -{ - uint32_t in, rs, re, rn, z; uc_block_t *ra; - - in = 0; - while (get_scaf_res_t(cp, uid, s, e, &in, &rs, &re, &rn, &ra)) { - fprintf(stderr, "%s%.6u%c\t%u\t%u\t%u\tn(%u)\n", pfx, uid+1, "lc"[ug->u.a[uid].circ], ug->u.a[uid].len, rs, re, rn); - if(rn <= (bw<<1)) { - for (z = 0; z < rn; z++) fprintf(stderr, "utg%.6u%c,", (ra[z].hid)+1, "lc"[ref->u.a[ra[z].hid].circ]); - } else { - for (z = 0; z < bw; z++) fprintf(stderr, "utg%.6u%c,", (ra[z].hid)+1, "lc"[ref->u.a[ra[z].hid].circ]); - fprintf(stderr, "......,"); - for (z = rn-bw; z < rn; z++) fprintf(stderr, "utg%.6u%c,", (ra[z].hid)+1, "lc"[ref->u.a[ra[z].hid].circ]); - } - fprintf(stderr, "\n"); - } -} - -void print_ctg_trans_ovlp(kv_u_trans_t *os, ma_ug_t *ref, ma_ug_t *hu1, scaf_res_t *cp1, ma_ug_t *hu2, scaf_res_t *cp2) -{ - u_trans_t *p = NULL; uint32_t i, qui, tui, qid, tid; ma_utg_t *uq, *ut; - for (i = 0; i < os->n; i++) { - p = &(os->a[i]); - qui = p->qnu.n?1:2; qid = ((p->qnu.n)?p->qn:p->qn-hu1->u.n); - tui = p->tnu.n?1:2; tid = ((p->tnu.n)?p->tn:p->tn-hu1->u.n); - uq = ((p->qnu.n)?&(hu1->u.a[p->qn]):&(hu2->u.a[p->qn-hu1->u.n])); - ut = ((p->tnu.n)?&(hu1->u.a[p->tn]):&(hu2->u.a[p->tn-hu1->u.n])); - fprintf(stderr, "************\n"); - fprintf(stderr, "[M::%s] h%utg%.6u%c\t%u\t%u\t%u\t%c\th%utg%.6u%c\t%u\t%u\t%u\tw(%f)\tf(%u)\n", __func__, - qui, qid+1, "lc"[uq->circ], uq->len, p->qs, p->qe, "+-"[p->rev], - tui, tid+1, "lc"[ut->circ], ut->len, p->ts, p->te, p->nw, p->f); - - prt_scaf_res_t(ref, qui==1?cp1:cp2, qui==1?hu1:hu2, (p->qnu.n)?p->qn:p->qn-hu1->u.n, p->qs, p->qe, qui==1?"h1tg":"h2tg", 3); - prt_scaf_res_t(ref, tui==1?cp1:cp2, tui==1?hu1:hu2, (p->tnu.n)?p->tn:p->tn-hu1->u.n, p->ts, p->te, tui==1?"h1tg":"h2tg", 3); - } -} - -static inline void scaf_hit2arc(u_trans_t *a0, u_trans_t *a1, uint64_t rev, uint64_t el, int64_t glen, asg_arc_t *p) -{ - uint64_t v, w; - memset(p, 0, sizeof((*p))); - v = ((uint64_t)(a0->tn<<1))|((uint64_t)(!!(a0->rev))); v^=((uint64_t)(!!(rev))); - w = ((uint64_t)(a1->tn<<1))|((uint64_t)(!!(a1->rev))); w^=((uint64_t)(!!(rev))); - // p->ul = v; p->ul <<= 32; p->ul |= a0i; p->v = w; p->ol = a1i; p->el = el; - p->ul = v; p->ul <<= 32; p->v = w; p->ol = ((glen>=0)?(glen):(-glen)); p->el = el; p->strong = ((glen>=0)?(1):(0)); - // a0r = 0; if((a0->f) || (((a0->qe-a0->qs) >= reliable_len) && ((a0->te-a0->ts) >= reliable_len))) a0r = 1; - // a1r = 0; if((a1->f) || (((a1->qe-a1->qs) >= reliable_len) && ((a1->te-a1->ts) >= reliable_len))) a1r = 1; - // p->el = ((a0r && a1r)?1:0); -} - -uint64_t is_noisy_ov(uint64_t s, uint64_t e, uint64_t len, uint64_t bd, double cov_rate, u_trans_t *a, uint64_t a_n) -{ - uint64_t w, k, zs, ze, oz, tot; - if(e - s < (bd<<1)) { - w = (e + s)>>1; - s = ((w>=bd)?(w-bd):(0)); - e = ((w+bd<=len)?(w+bd):(len)); - } - if(s >= e) return 0; - for(k = tot = 0; k < a_n; k++) { - if(a[k].qs >= e) break; - if(a[k].qe <= s) continue; - zs = MAX(s, a[k].qs); ze = MIN(e, a[k].qe); - oz = ((ze > zs)? (ze - zs):(0)); - tot += oz; - } - if((tot > 0) && (tot >= ((e - s)*cov_rate))) return 1; - return 0; -} - -uint64_t get_ref_nid(u_trans_t *z, ma_ug_t *hu1, ma_ug_t *hu2, scaf_res_t *cp1, scaf_res_t *cp2, uint64_t is_beg, uint64_t gap_bd) -{ - scaf_res_t *sc = NULL; uint64_t id, s_end, e_end; - if(z->tn < hu1->u.n) { - sc = cp1; id = z->tn; - } else { - sc = cp2; id = z->tn - hu1->u.n; - } - - if(is_beg) { - s_end = 0; e_end = 1; - } else { - s_end = 1; e_end = 0; - } - - if(!(z->rev)) { - s_end ^= 1; e_end ^= 1; - } - - - ul_vec_t *idx = &(sc->a[id]); uint64_t k, m, a_n, os, oe, m0; - uc_block_t *a, *am = NULL; uint64_t max_len = 0, cgap, clen; - - for (k = 0; k < idx->bb.n; k++) { - a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; - os = MAX(z->ts, idx->bb.a[k].qs); - oe = MIN(z->te, idx->bb.a[k].qe); - if(os >= oe) continue; - for(m = 0; m < a_n && a[m].qe <= os; z++); - if(m >= a_n) continue; - for(m0 = m; m < a_n && a[m].qs < oe; m++); - if(m <= m0) continue; - - os = MAX(z->ts, a[m0].qs); - oe = MIN(z->te, a[m-1].qe); - if(oe <= os) continue; - clen = oe - os; cgap = 0; - if(s_end) { - cgap = os - z->ts; - } else if(e_end) { - cgap = z->te - oe; - } - if(cgap > gap_bd) continue; - if(clen > max_len) { - max_len = clen; am = ((s_end)?(&(a[m0])):(&(a[m-1]))); - } - } - - if(!am) return (uint64_t)-1; - return ((uint64_t)(am->hid<<1))|((uint64_t)(!!(am->rev))); -} - -uint64_t cal_self_close_tang(asg_t *g, uint32_t s0, uint32_t e0, asg32_v *b1, asg32_v *b2, uint8_t *f, uint32_t max_path) -{ - uint32_t z, v, nv, k, se = 0, o0, o1, o, tot; asg_arc_t *av; - b1->n = 0; b2->n = 0; tot = 0; - kv_push(uint32_t, *b1, (s0>>1)); - while(b1->n) { - z = b1->a[--b1->n]; - if(f[z]) continue; - f[z] = 1; o0 = o1 = 0; - kv_push(uint32_t, *b2, z); - - v = (z<<1); o = 0; - if((v != e0) && (v != (s0^1))) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (k = o = 0; k < nv; k++) { - if(av[k].del) continue; - if((av[k].v == s0) || (av[k].v == (e0^1))) { - se = 1; break; - } - if(f[av[k].v>>1]) { - if(((av[k].v>>1) != (s0>>1)) && ((av[k].v>>1) != (e0>>1)) && (o < av[k].ol)) o = av[k].ol; - continue; - } - kv_push(uint32_t, *b1, (av[k].v>>1)); - } - if(se) break; - } - o0 = o; - - - v = (z<<1) + 1; o = 0; - if((v != e0) && (v != (s0^1))) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (k = o = 0; k < nv; k++) { - if(av[k].del) continue; - if((av[k].v == s0) || (av[k].v == (e0^1))) { - se = 1; break; - } - if(f[av[k].v>>1]) { - if(((av[k].v>>1) != (s0>>1)) && ((av[k].v>>1) != (e0>>1)) && (o < av[k].ol)) o = av[k].ol; - continue; - } - kv_push(uint32_t, *b1, (av[k].v>>1)); - } - if(se) break; - } - o1 = o; - - if(o0 + o1 < g->seq[z].len) tot += g->seq[z].len - o0 - o1; - if(tot > max_path) break; - } - - for (k = 0; k < b2->n; k++) f[b2->a[k]] = 0; - - if((!se) && (tot <= max_path)) return tot; - return (uint64_t)-1; -} - -uint64_t get_ref_nid_flank(u_trans_t *z, ma_ug_t *ref, ma_ug_t *hu1, ma_ug_t *hu2, scaf_res_t *cp1, scaf_res_t *cp2, uint64_t is_beg, uint64_t gap_bd, uint64_t flank_len, asg32_v *res) -{ - scaf_res_t *sc = NULL; uint64_t id, s_end, e_end, rn = res->n; - if(z->tn < hu1->u.n) { - sc = cp1; id = z->tn; - } else { - sc = cp2; id = z->tn - hu1->u.n; - } - - if(is_beg) { - s_end = 0; e_end = 1; - } else { - s_end = 1; e_end = 0; - } - - if(z->rev) { - s_end ^= 1; e_end ^= 1; - } - - - ul_vec_t *idx = &(sc->a[id]); uint64_t k, m, a_n, os, oe, m0; - uc_block_t *a, *am = NULL; uint64_t max_len = 0, cgap, clen; int64_t ami, amn = 0, as, ae, amz; - // if(z->tn == 5) { - // fprintf(stderr, "\n[M::%s] h1tg%.6u%c(%c)\ts::%u\te::%u\ts_end::%lu\te_end::%lu\n", __func__, z->tn+1, "lc"[hu1->u.a[z->tn].circ], "+-"[z->rev], z->ts, z->te, s_end, e_end); - // } - - for (k = 0; k < idx->bb.n; k++) { - a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; - os = MAX(z->ts, idx->bb.a[k].qs); - oe = MIN(z->te, idx->bb.a[k].qe); - // if(z->tn == 5) { - // fprintf(stderr, "[M::%s] idx->bb.a[%lu]::[%u, %u), o[%lu, %lu), a_n::%lu\n", __func__, k, idx->bb.a[k].qs, idx->bb.a[k].qe, os, oe, a_n); - // } - if(os >= oe) continue; - for(m = 0; m < a_n && a[m].qe <= os; m++); - // { - // if(z->tn == 5) fprintf(stderr, "+(%lu)utg%.6u%c[%u,%u),", m, (a[m].hid)+1, "lc"[ref->u.a[a[m].hid].circ], a[m].qs, a[m].qe); - // } - // if(z->tn == 5) fprintf(stderr, "\n[M::%s] +m::%lu\n", __func__, m); - if(m >= a_n) continue; - for(m0 = m; m < a_n && a[m].qs < oe; m++); - // { - // if(z->tn == 5) fprintf(stderr, "-(%lu)utg%.6u%c[%u,%u),", m, (a[m].hid)+1, "lc"[ref->u.a[a[m].hid].circ], a[m].qs, a[m].qe); - // } - // if(z->tn == 5) fprintf(stderr, "\n[M::%s] -m::%lu\n", __func__, m); - if(m <= m0) continue; - - os = MAX(z->ts, a[m0].qs); - oe = MIN(z->te, a[m-1].qe); - // if(z->tn == 5) { - // fprintf(stderr, "[M::%s] m0::%lu, m::%lu, o[%lu, %lu), a_n::%lu\n", __func__, m0, m, os, oe, a_n); - // } - if(oe <= os) continue; - clen = oe - os; cgap = 0; - if(s_end) { - cgap = os - z->ts; - } else if(e_end) { - cgap = z->te - oe; - } - if(cgap > gap_bd) continue; - if(clen > max_len) { - max_len = clen; am = a + m0; amn = m - m0; - } - } - - // if(z->tn == 49 && z->ts == 0 && z->te == 2143149) { - // fprintf(stderr, "-0-[M::%s] h1tg%.6ul(%c)\tts::%u\tte::%u\tamn::%ld\ts_end::%lu\te_end::%lu\n", __func__, - // z->tn+1, "+-"[z->rev], z->ts, z->te, amn, s_end, e_end); - // } - - // if(z->tn == 5) fprintf(stderr, "[M::%s] amn::%ld\n", __func__, amn); - - if((!am) || (!amn)) return 0; - os = oe = 0; as = 0; ae = amn; - if(s_end) { - for(ami = 0; (ami < amn) && ((z->ts + flank_len) >= am[ami].qe); ami++); - if((ami < amn) && ((z->ts + flank_len) >= am[ami].qs)) ami++; - as = 0; ae = ami; - } else if(e_end) { - for(ami = amn - 1; (ami >= 0) && (z->te <= (am[ami].qs + flank_len)); ami--); - if((ami >= 0) && (z->te <= (am[ami].qe + flank_len))) ami--; - ami++; as = ami; ae = amn; - } - // if(z->tn == 49 && z->ts == 0 && z->te == 2143149) { - // fprintf(stderr, "-1-[M::%s] h1tg%.6ul(%c)\tts::%u\tte::%u\tas::%ld\tae::%ld\n", __func__, - // z->tn+1, "+-"[z->rev], z->ts, z->te, as, ae); - // } - // if(z->tn == 5) fprintf(stderr, "+[M::%s] as::%ld, ae::%ld\n", __func__, as, ae); - if(as >= ae) return 0; - - ///make sure there are no identical node - if(s_end) { - for (ami = as; ami < ae; ami++) { - for (amz = ami + 1; (amz < ae) && (am[ami].hid != am[amz].hid); amz++); - if(amz < ae) { - ae = ami + 1; break; - } - } - } else if(e_end) { - for (ami = ae - 1; ami >= as; ami--) { - for (amz = ami - 1; (amz >= as) && (am[ami].hid != am[amz].hid); amz--); - if(amz >= as) { - as = ami; break; - } - } - } - // if(z->tn == 49 && z->ts == 0 && z->te == 2143149) { - // fprintf(stderr, "-1-[M::%s] h1tg%.6ul(%c)\tts::%u\tte::%u\tas::%ld\tae::%ld\n", __func__, - // z->tn+1, "+-"[z->rev], z->ts, z->te, as, ae); - // } - // if(z->tn == 5) fprintf(stderr, "+[M::%s] as::%ld, ae::%ld\n", __func__, as, ae); - if(as >= ae) return 0; - - uint32_t *fp = NULL, r2n = 0; - kv_resize(uint32_t, *res, rn + ((ae - as)<<1)); - for (ami = as; ami < ae; ami++) { - m = ((uint64_t)(am[ami].hid<<1))|((uint64_t)(!!(am[ami].rev))); m ^= ((uint64_t)(!!(z->rev))); - kv_push(uint32_t, *res, m); - } - rn = res->n - rn; - if(z->rev) { - fp = res->a + res->n - rn; r2n = rn>>1; - for (k = 0; k < r2n; k++) { - m = fp[k]; fp[k] = fp[rn - k -1]; fp[rn - k -1] = m; - } - } - - if(s_end) { - for (ami = as; ami < ae; ami++) { - m = ((am[ami].qs>=z->ts)?(am[ami].qs-z->ts):(0)); - kv_push(uint32_t, *res, m); - } - } else if(e_end) { - for (ami = as; ami < ae; ami++) { - m = ((z->te>=am[ami].qe)?(z->te-am[ami].qe):(0)); - kv_push(uint32_t, *res, m); - } - } - if(z->rev) { - fp = res->a + res->n - rn; r2n = rn>>1; - for (k = 0; k < r2n; k++) { - m = fp[k]; fp[k] = fp[rn - k - 1]; fp[rn - k - 1] = m; - } - } - - return rn; - // return ((uint64_t)(am->hid<<1))|((uint64_t)(!!(am->rev))); -} - -void dedup_tang_flank(uint32_t *va, uint32_t *vd, uint32_t *vn0, uint32_t *wa, uint32_t *wd, uint32_t *wn0) -{ - uint64_t k, z, vn = (*vn0), wn = (*wn0); - uint32_t vp, wp; - for (k = 0; k < vn && k < wn; k++) { - if(k < vn) { - vp = va[vn-k-1]>>1; - for (z = k; (z < wn) && (vp != (wa[z]>>1)); z++); - if(z < wn) wn = z; - } - if(k < wn) { - wp = wa[k]>>1; - for (z = k; (z < vn) && (wp != (va[vn-z-1]>>1)); z++); - if(z < vn) vn = z; - } - } - if(vn < (*vn0)) { - z = (*vn0) - vn; - for (k = 0; k < vn; k++) { - va[k] = va[k + z]; vd[k] = vd[k + z]; - } - } - (*vn0) = vn; (*wn0) = wn; -} - - -uint64_t cal_self_close_tang_flank0(asg_t *g, uint32_t v0, uint32_t s0, uint32_t e0, uint64_t sf, uint64_t ef, asg32_v *b1, asg32_v *b2, uint8_t *f, uint8_t *fs, uint64_t max_path) -{ - uint64_t se = 0, k, v, o, o0, o1, nv, tot = 0; asg_arc_t *av; - - if(f[v0]) return (uint64_t)-1; - - // if((v0>>1) == 47687) fprintf(stderr, "+[M::%s] v0->utg%.6ul(%c), s0::%u, e0::%u, sf::%lu, ef::%lu\n", __func__, (v0>>1)+1, "+-"[v0&1], s0, e0, sf, ef); - - b1->n = b2->n = 0; kv_push(uint32_t, *b1, v0); - while(b1->n) { - v = b1->a[--b1->n]; - if(f[v] && f[v^1]) continue; - // if((v0>>1) == 47687) fprintf(stderr, "[M::%s] utg%.6lul(%c), tot::%lu\n", __func__, (v>>1)+1, "+-"[v&1], tot); - - v = v; - // if((v0>>1) == 47687) fprintf(stderr, "[M::%s] v::%lu, f[v]::%u, fs[v]::%u, fs[v^1]::%u\n", __func__, v, f[v], fs[v], fs[v^1]); - if((!f[v]) && (v!=(s0^1)) && (v!=e0)) { - if((fs[v^1] != sf) && (fs[v] != ef)) { - f[v] = 1; kv_push(uint32_t, *b2, v); - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - // if((v0>>1) == 47687) fprintf(stderr, "[M::%s] k::%lu, f[av[k].v]::%u, fs[av[k].v]::%u, fs[av[k].v^1]::%u\n", __func__, k, f[av[k].v], fs[av[k].v], fs[av[k].v^1]); - if((av[k].v == s0) || (av[k].v == (e0^1))) { - se = 1; break; - } - if(fs[av[k].v] == sf) { - fs[av[k].v] = 0;///not a beg node anymore - if(!f[av[k].v^1]) kv_push(uint32_t, *b1, (av[k].v^1));///push reverse node - } - if(fs[(av[k].v^1)] == ef) { - fs[(av[k].v^1)] = 0;///not a end node anymore; do not need to push as it will be pushed later - if(!f[av[k].v]) kv_push(uint32_t, *b1, (av[k].v));///push reverse node - } - - /**if((fs[av[k].v^1] != sf) && (fs[av[k].v] != ef))**/ { - if((!f[av[k].v])) kv_push(uint32_t, *b1, av[k].v); - } - } - if(se) break; - } - } - - v = v^1; - // if((v0>>1) == 47687) fprintf(stderr, "[M::%s] v::%lu, f[v]::%u, fs[v]::%u, fs[v^1]::%u\n", __func__, v, f[v], fs[v], fs[v^1]); - if((!f[v]) && (v != (s0^1)) && (v != e0)) { - if((fs[v^1] != sf) && (fs[v] != ef)) { - f[v] = 1; kv_push(uint32_t, *b2, v); - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - // if((v0>>1) == 47687) fprintf(stderr, "[M::%s] k::%lu, f[av[k].v]::%u, fs[av[k].v]::%u, fs[av[k].v^1]::%u\n", __func__, k, f[av[k].v], fs[av[k].v], fs[av[k].v^1]); - if((av[k].v == s0) || (av[k].v == (e0^1))) { - se = 1; break; - } - if(fs[av[k].v] == sf) { - fs[av[k].v] = 0;///not a beg node anymore - if(!f[av[k].v^1]) kv_push(uint32_t, *b1, (av[k].v^1));///push reverse node - } - if(fs[(av[k].v^1)] == ef) fs[(av[k].v^1)] = 0;///not a end node anymore; do not need to push as it will be pushed later - - /**if((fs[av[k].v^1] != sf) && (fs[av[k].v] != ef))**/ { - if((!f[av[k].v])) kv_push(uint32_t, *b1, av[k].v); - } - } - if(se) break; - } - } - - if(f[v] && f[v^1]) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (k = o = 0; k < nv; k++) { - if(av[k].del) continue; - if((f[av[k].v^1]) && (f[av[k].v]) && (o < av[k].ol)) o = av[k].ol; - } - o0 = o; - - av = asg_arc_a(g, (v^1)); nv = asg_arc_n(g, (v^1)); - for (k = o = 0; k < nv; k++) { - if(av[k].del) continue; - if((f[av[k].v^1]) && (f[av[k].v]) && (o < av[k].ol)) o = av[k].ol; - } - o1 = o; - - if(o0 + o1 < g->seq[v>>1].len) tot += g->seq[v>>1].len - o0 - o1; - } - - if(tot > max_path) break; - } - - // if((v0>>1) == 47687) fprintf(stderr, "-[M::%s] v0->utg%.6ul(%c), tot::%lu, se::%lu\n", __func__, (v0>>1)+1, "+-"[v0&1], tot, se); - - if((!se) && (tot <= max_path)) return tot; - return (uint64_t)-1; -} - - - -uint64_t cal_self_close_tang_flank1(asg_t *g, uint32_t s0, uint32_t e0, asg32_v *b1, asg32_v *b2, uint8_t *f, uint8_t *fsk, uint64_t max_path) -{ - uint64_t se = 0, k, v, o, o0, o1, nv, tot = 0; asg_arc_t *av; - - b1->n = b2->n = 0; kv_push(uint32_t, *b1, s0); - while(b1->n) { - v = b1->a[--b1->n]; - if(f[v] && f[v^1]) continue; - - v = v; - if((!f[v]) && (v!=(s0^1)) && (v!=e0)) { - f[v] = 1; kv_push(uint32_t, *b2, v); - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if((av[k].v == s0) || (av[k].v == (e0^1))) { - se = 1; break; - } - if((!f[av[k].v])) kv_push(uint32_t, *b1, av[k].v); - } - if(se) break; - } - - v = v^1; - if((!f[v]) && (v!=(s0^1)) && (v!=e0)) { - f[v] = 1; kv_push(uint32_t, *b2, v); - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if((av[k].v == s0) || (av[k].v == (e0^1))) { - se = 1; break; - } - if((!f[av[k].v])) kv_push(uint32_t, *b1, av[k].v); - } - if(se) break; - } - - if(f[v] && f[v^1] && (!fsk[v>>1])) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (k = o = 0; k < nv; k++) { - if(av[k].del) continue; - if((f[av[k].v^1]) && (f[av[k].v]) && (!fsk[av[k].v>>1]) && (o < av[k].ol)) o = av[k].ol; - } - o0 = o; - - av = asg_arc_a(g, (v^1)); nv = asg_arc_n(g, (v^1)); - for (k = o = 0; k < nv; k++) { - if(av[k].del) continue; - if((f[av[k].v^1]) && (f[av[k].v]) && (!fsk[av[k].v>>1]) && (o < av[k].ol)) o = av[k].ol; - } - o1 = o; - - if(o0 + o1 < g->seq[v>>1].len) tot += g->seq[v>>1].len - o0 - o1; - } - - if(tot > max_path) break; - } - - if((!se) && (tot <= max_path)) return tot; - return (uint64_t)-1; -} - - -/** -uint64_t cal_self_close_tang_flank0_back(asg_t *g, uint32_t v0, uint32_t s0, uint32_t e0, uint64_t sf, uint64_t ef, asg32_v *b1, asg32_v *b2, uint8_t *f, uint8_t *fs, uint64_t max_path, uint64_t tot) -{ - if(f[v0]) return tot; - uint64_t se = 0, k, v, o, o0, o1, nv; asg_arc_t *av; - - b1->n = 0; kv_push(uint32_t, *b1, v0); - while(b1->n) { - v = b1->a[--b1->n]; - if(f[v] && f[v^1]) continue; - - o0 = o1 = 0; - - o = 0; - if((v != e0) && (v != (s0^1)) && (!f[v])) { - if((fs[v] != ef) && (fs[v^1] != sf)) { - f[v] = 1; kv_push(uint32_t, *b2, v); - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (k = o = 0; k < nv; k++) { - if(av[k].del) continue; - if((av[k].v == s0) || (av[k].v == (e0^1))) { - se = 1; break; - } - if((fs[av[k].v] != ef) && (fs[av[k].v^1] != sf)) { - if(f[av[k].v^1]) { - if((!fs[av[k].v]) && (!fs[av[k].v^1]) && (o < av[k].ol)) o = av[k].ol; - continue; - } - kv_push(uint32_t, *b1, av[k].v); - } - } - if(se) break; - } - } - o0 = o; - - v = v^1; - o = 0; - if((v != e0) && (v != (s0^1)) && (!f[v])) { - if((fs[v] != ef) && (fs[v^1] != sf)) { - f[v] = 1; kv_push(uint32_t, *b2, v); - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (k = o = 0; k < nv; k++) { - if(av[k].del) continue; - if((av[k].v == s0) || (av[k].v == (e0^1))) { - se = 1; break; - } - if((fs[av[k].v] != ef) && (fs[av[k].v^1] != sf)) { - if(f[av[k].v^1]) { - if((!fs[av[k].v]) && (!fs[av[k].v^1]) && (o < av[k].ol)) o = av[k].ol; - continue; - } - kv_push(uint32_t, *b1, av[k].v); - } - } - if(se) break; - } - } - o1 = o; - - if((!fs[v]) && (!fs[v^1]) && f[v] && f[v^1] && (o0 + o1 < g->seq[z].len)) { - tot += g->seq[z].len - o0 - o1; - } - if(tot > max_path) break; - } - - if((!se) && (tot <= max_path)) return tot; - return (uint64_t)-1; -} - -uint64_t cal_self_close_tang_flank1(asg_t *g, uint32_t *s, uint32_t sn, uint32_t *e, uint32_t en, uint32_t s0, uint32_t e0, uint64_t sf, uint64_t ef, asg32_v *b1, asg32_v *b2, uint8_t *f, uint8_t *fs, uint64_t max_path, uint64_t tot) -{ - uint64_t k, sk, ek; - for (k = 0, sk = (uint64_t)-1; (k < sn) && (!f[s[k]]) && (!f[s[k]^1]); k++); if(k < sn) sk = k; - for (k = 0, ek = (uint64_t)-1; (k < en) && (!f[e[en-k-1]]) && (!f[e[en-k-1]^1]); k++); if(k < en) ek = en-k-1; - if(sk != (uint64_t)-1) { - for (k = sk + 1; k < sn; k++) fs[s[k]] = 0; - } - if(ek != (uint64_t)-1) { - for (k = ek + 1; k < en; k++) fs[e[en-k-1]] = 0; - } - - if(sk != (uint64_t)-1) { - for (k = sk + 1; k < sn; k++) { - if((!fs[s[k]])) { - if(f[s[k]]) cal_self_close_tang_flank0(g, s[k], s0, e0, sf, ef, b1, b2, f, fs, max_path, tot); - - } - } - } - -} -**/ - - -uint64_t trace_back_tangle_dis(asg_t *g, uint32_t *s, uint32_t *sd, uint32_t sn, uint32_t *e, uint32_t *ed, uint32_t en, asg32_v *b, asg32_v *b1, asg32_v *b2, uint8_t *f, uint8_t *fs, uint8_t *fsk, uint64_t sf, uint64_t ef, uint64_t max_path, uint64_t *is_dip) -{ - uint64_t k, sk, sm, ek, em, s0, slen, e0, elen, tot; b->n = 0; (*is_dip) = 0; - for (sk = sm = 0; sk < sn; sk++) { - if((fs[s[sn-sk-1]] == sf) && (f[s[sn-sk-1]]) && (!f[s[sn-sk-1]^1])) {///a potiential - kv_push(uint32_t, *b, sn-sk-1); sm++; - } - } - if(!sm) return ((uint64_t)-1); - - for (ek = em = 0; ek < en; ek++) { - if((fs[e[ek]] == ef) && (!f[e[ek]]) && (f[e[ek]^1])) {///a potiential - kv_push(uint32_t, *b, ek); em++; - } - } - if(!em) return ((uint64_t)-1); - - uint32_t *si = b->a, *ei = b->a + sm; - for (sk = 0; sk < sm; sk++) { - s0 = s[si[sk]]; slen = sd[si[sk]]; - for (ek = 0; ek < em; ek++) { - e0 = e[ei[ek]]; elen = ed[ei[ek]]; - for (k = 0; k < b2->n; k++) f[b2->a[k]] = 0; - - tot = cal_self_close_tang_flank1(g, s0, e0, b1, b2, f, fsk, max_path + slen + elen); - if((tot != ((uint64_t)-1)) && (tot <= (max_path + slen + elen))) { - if(fsk[s0>>1] && fsk[e0>>1]) { - (*is_dip) = 1; - return 0; - } else { - return ((tot>=(slen + elen))?(tot-(slen + elen)):(0)); - } - } - } - } - return ((uint64_t)-1); -} - -uint64_t cal_self_close_tang_flank(asg_t *g, uint32_t *s, uint32_t *sd, uint32_t sn, uint32_t *e, uint32_t *ed, uint32_t en, asg32_v *b1, asg32_v *b2, asg32_v *b3, uint8_t *f, uint8_t *fs, uint8_t *fsk, uint64_t max_path, uint64_t *is_dip) -{ - (*is_dip) = 0; - if((!sn) || (!en)) return (uint64_t)-1; - - uint64_t z, k, tot, sf = 1, ef = 2, s0, e0; - for (k = 0; k < sn; k++) { - assert(!(fs[s[k]])); fs[s[k]] = sf; - } - s0 = s[0]; - - for (k = 0; k < en; k++) { - assert(!(fs[e[k]])); fs[e[k]] = ef; - } - e0 = e[en-1]; - - b1->n = 0; b2->n = 0; tot = ((uint64_t)-1); - for (k = 0; k < sn; k++) { - if(fs[s[sn-k-1]] != sf) continue; - tot = cal_self_close_tang_flank0(g, s[sn-k-1], s0, e0, sf, ef, b1, b2, f, fs, max_path); - if((tot == ((uint64_t)-1)) || (tot > max_path)) { - tot = ((uint64_t)-1); break; - } else { - tot = trace_back_tangle_dis(g, s, sd, sn, e, ed, en, b3, b1, b2, f, fs, fsk, sf, ef, max_path, is_dip); - if(tot != ((uint64_t)-1)) break; - } - - ///reset s && e - for (z = 0; z < sn; z++) fs[s[z]] = sf; - for (z = 0; z < en; z++) fs[e[z]] = ef; - for (z = 0; z < b2->n; z++) f[b2->a[z]] = 0; - } - - for (k = 0; k < sn; k++) fs[s[k]] = 0; - for (k = 0; k < en; k++) fs[e[k]] = 0; - for (k = 0; k < b2->n; k++) f[b2->a[k]] = 0; - - return tot; -} - - -void prt_scf_dbg_nds(u_trans_t *z, uint32_t *za, uint32_t *zd, uint32_t zn, ma_ug_t *ref, ma_ug_t *hu1, ma_ug_t *hu2, uint64_t s_end, uint64_t e_end, const char *cmd) -{ - uint64_t k, id, rev, ui, uid; ma_utg_t *u; - - id = z->tn; rev = z->rev; - u = ((idu.n)?&(hu1->u.a[id]):&(hu2->u.a[id-hu1->u.n])); - ui = ((idu.n)?1:2); uid = ((idu.n)?(id):(id-hu1->u.n)); - - fprintf(stderr, "\nCMD::%s[M::%s] h%lutg%.6lu%c(%c)\ts::%u\te::%u\ts_end::%lu\te_end::%lu\tref_n::%u\n", cmd, __func__, - ui, uid+1, "lc"[u->circ], "+-"[rev], z->ts, z->te, s_end, e_end, (uint32_t)ref->u.n); - for (k = 0; k < zn; k++) { - fprintf(stderr, "[%u|%u]", (za[k]>>1), (za[k]&1)); - fprintf(stderr, "utg%.6u%c(%c)(d::%u),", (za[k]>>1)+1, "lc"[ref->u.a[(za[k]>>1)].circ], "+-"[za[k]&1], zd[k]); - } - fprintf(stderr, "\n"); -} - - -uint64_t is_small_tangle(u_trans_t *s, u_trans_t *e, ma_ug_t *ref, ma_ug_t *hu1, ma_ug_t *hu2, scaf_res_t *cp1, scaf_res_t *cp2, asg32_v *b1, asg32_v *b2, asg32_v *b3, asg32_v *b4, uint8_t *f, uint8_t *fs, uint8_t *fsk, uint64_t max_len, uint64_t *is_dip) -{ - uint64_t tot; uint32_t *va = NULL, *vd = NULL, *wa = NULL, *wd = NULL, vn = 0, wn = 0; - b1->n = b2->n = b3->n = b4->n = 0; (*is_dip) = 0; - // v = get_ref_nid(s, hu1, hu2, cp1, cp2, 1, 1000); if(v == ((uint64_t)-1)) return ((uint64_t)-1); - // w = get_ref_nid(e, hu1, hu2, cp1, cp2, 0, 1000); if(w == ((uint64_t)-1)) return ((uint64_t)-1); - // if((v>>1) == (w>>1)) return ((uint64_t)-1); - - // fprintf(stderr, "-0-[M::%s]\n", __func__); - vn = get_ref_nid_flank(s, ref, hu1, hu2, cp1, cp2, 1, 1000, max_len, b3); if(!vn) return ((uint64_t)-1); - // fprintf(stderr, "-1-[M::%s]\n", __func__); - wn = get_ref_nid_flank(e, ref, hu1, hu2, cp1, cp2, 0, 1000, max_len, b3); if(!wn) return ((uint64_t)-1); - // fprintf(stderr, "-2-[M::%s]\n", __func__); - va = b3->a; vd = va + vn; wa = vd + vn; wd = wa + wn; - // prt_scf_dbg_nds(s, va, vd, vn, ref, hu1, hu2, 0, 1, "rawS"); - // prt_scf_dbg_nds(e, wa, wd, wn, ref, hu1, hu2, 1, 0, "rawE"); - dedup_tang_flank(va, vd, &vn, wa, wd, &wn); - if((!vn) || (!wn)) return ((uint64_t)-1); - // prt_scf_dbg_nds(s, va, vd, vn, ref, hu1, hu2, 0, 1, "fffS"); - // prt_scf_dbg_nds(e, wa, wd, wn, ref, hu1, hu2, 1, 0, "fffE"); - - tot = cal_self_close_tang_flank(ref->g, va, vd, vn, wa, wd, wn, b1, b2, b4, f, fs, fsk, max_len, is_dip); - if(tot > max_len) tot = ((uint64_t)-1); - return tot; - - // l0 = cal_self_close_tang(ref->g, v, w, b1, b2, f, max_len); if(l0 == ((uint64_t)-1)) return ((uint64_t)-1); - // l1 = cal_self_close_tang(ref->g, w^1, v^1, b1, b2, f, max_len); if(l1 == ((uint64_t)-1)) return ((uint64_t)-1); - // return MIN(l0, l1); -} - - -uint32_t gen_scaf_path_lst(asg_t *g, uint32_t s, asg64_v *b, uint64_t *blen, uint64_t *bf) -{ - - uint32_t v = s, w = 0; uint64_t m, c1 = 0, c2 = 0; - uint32_t kv, kw; (*blen) = 0; (*bf) = 0; - - while (1) { - kv = get_arcs(g, v, &w, 1); - m = v; - if(kv == 1) m |= ((uint64_t)(g->arc[w].ol))<<32; - kv_push(uint64_t, *b, m); - (*blen) += g->seq[v>>1].len + ((kv == 1)?g->arc[w].ol:0); - if(g->seq[v>>1].c == 1) c1++; - else if(g->seq[v>>1].c == 2) c2++; - - if(kv == 0) {(*bf) = (c1>=c2?1:2); return END_TIPS;} - if(kv == 2) {(*bf) = (c1>=c2?1:2); return TWO_OUTPUT;} - if(kv > 2) {(*bf) = (c1>=c2?1:2); return MUL_OUTPUT;} - w = g->arc[w].v; - ///up to here, kv=1 - ///kw must >= 1 - kw = get_arcs(g, w^1, NULL, 0); - v = w; - - if(kw == 2) {(*bf) = (c1>=c2?1:2); return TWO_INPUT;} - if(kw > 2) {(*bf) = (c1>=c2?1:2); return MUL_INPUT;} - if(v == s) {(*bf) = (c1>=c2?1:2); return LOOP;} - } - - (*bf) = (c1>=c2?1:2); - return LONG_TIPS; -} - -uint64_t prt_gen_scaf_path_lst(uint64_t *a, uint64_t n, uint64_t is_circle, ma_ug_t *hu1, ma_ug_t *hu2) -{ - uint64_t k, nl, el, tl, id, rev, ui, uid; ma_utg_t *u; - for (k = nl = el = tl = 0; k < n; k++) { - nl += (a[k]>>32); id = ((uint32_t)a[k])>>1; - u = ((idu.n)?&(hu1->u.a[id]):&(hu2->u.a[id-hu1->u.n])); - el += u->len; - } - tl = el + nl; - fprintf(stderr, "[M::%s]tot::%lu\tel::%lu\tnl::%lu\tis_c::%lu\t#::%lu\t%s\n", __func__, tl, el, nl, is_circle, n, ((n>1)?"scf":"ctg")); - for (k = 0; k < n; k++) { - id = ((uint32_t)a[k])>>1; rev = ((uint32_t)a[k])&1; - u = ((idu.n)?&(hu1->u.a[id]):&(hu2->u.a[id-hu1->u.n])); - ui = ((idu.n)?1:2); nl = (a[k]>>32); - uid = ((idu.n)?(id):(id-hu1->u.n)); - fprintf(stderr, "[M::%s] h%lutg%.6lu%c(%c)\tlen::%u\tNs::%lu\n", __func__, - ui, uid+1, "lc"[u->circ], "+-"[rev], u->len, nl); - } - return tl; -} - -void cal_arr_N50(uint32_t *a, uint32_t n, const char *cmd) -{ - uint64_t i, s, len; - for (i = len = 0; i < n; i++) len += a[i]; - radix_sort_arch32(a, a + n); - - i = n; s = 0; - while (i > 0) { - s += a[--i]; - if(s >= (len>>1)) { - fprintf(stderr, "CMD::%s[M::%s::] N50: %u, Size::%lu\n", cmd, __func__, a[i], len); - break; - } - } -} - -void set_fsk(uint8_t *fsk, uint8_t mm, ul_vec_t *idx) -{ - uint64_t k, m, a_n; uc_block_t *a; - for (k = 0; k < idx->bb.n; k++) { - a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; - for(m = 0; m < a_n; m++) fsk[a[m].hid] = mm; - } -} - -// void exchange_utgs(kvect_sec_t *i1, kvect_sec_t *i2, asg32_v *b0, asg_t *mg) -// { -// kvect_sec_t *sc = NULL; uint32_t *srt[2], *idx = NULL, srt_n[2], k, z; sec_t *scp; -// kv_resize(uint32_t, (*b0), (((uint32_t)(mg->n_seq)*2))); idx = b0->a + mg->n_seq; - -// sc = i1; srt[0] = b0->a; srt_n[0] = 0; -// for (k = 0; k < sc->n; k++) { -// scp = &(sc->a[k]); -// for (z = 0; z < scp->n; z++) { -// srt[0][srt_n[0]++] = ((uint32_t)scp->a[z])>>1; -// } -// } - - -// sc = i2; srt[1] = srt[0] + srt_n[0]; srt_n[1] = 0; -// for (k = 0; k < sc->n; k++) { -// scp = &(sc->a[k]); -// for (z = 0; z < scp->n; z++) { -// srt[1][srt_n[1]++] = ((uint32_t)scp->a[z])>>1; -// } -// } - -// assert(srt_n[0] + srt_n[1] == mg->n_seq); - -// radix_sort_arch32(srt[0], srt[0] + srt_n[0]); - - - -// radix_sort_arch32(srt[1], srt[1] + srt_n[1]); -// } - - -void gen_double_scaffold_gfa(ma_ug_t *ref, ma_ug_t *hu1, ma_ug_t *hu2, scaf_res_t *cp1, scaf_res_t *cp2, asg_t *sg, kv_u_trans_t *os, int64_t minNs, kvect_sec_t **sc1, kvect_sec_t **sc2) -{ - order_contig_trans(os); - asg_t *g = asg_init(); uint64_t k, s, e, z, rn, pn, dn, rthres = asm_opt.self_scaf_reliable_min, el, glen; ma_utg_t *u, *ut; u_trans_t *p, *d, *r; - asg_arc_t t, *c; int64_t zs, ze, gl, gmin = -asm_opt.self_scaf_gap_max, gmax = asm_opt.self_scaf_gap_max; uint64_t mf, blen, bf, is_dip; uint32_t sce[2]; sce[0] = 0; sce[1] = 1; - asg32_v b0, b1, b2, b3; kv_init(b0); kv_init(b1); kv_init(b2); kv_init(b3); uint8_t *f, *fs, *fsk; CALLOC(f, (ref->u.n<<1)); CALLOC(fs, (ref->u.n<<1)); CALLOC(fsk, ref->u.n); - - // fprintf(stderr, "[M::%s::] SSS\n", __func__); - for (k = 0; k < os->idx.n; ++k) { - u = ((ku.n)?&(hu1->u.a[k]):&(hu2->u.a[k-hu1->u.n])); - asg_seq_set(g, k, u->len, 0); g->seq[k].c = (ku.n?1:2); - } - - // fprintf(stderr, "[M::%s::] MMM\n", __func__); - for (k = 0; k < os->idx.n; ++k) { - - r = u_trans_a(*os, k); rn = u_trans_n(*os, k); p = d = NULL; pn = dn = 0; - // fprintf(stderr, "[M::%s::] # k:%lu, rn::%lu\n", __func__, k, rn); - if(rn <= 1) continue; - for (z = 0, p = r; (z < rn) && (!(r[z].del)); z++); pn = z; - for (d = r + z; (z < rn) && (r[z].qs != ((uint32_t)-1)); z++); dn = z - pn; - // fprintf(stderr, "[M::%s::] # k:%lu, pn::%lu, dn::%lu\n", __func__, k, pn, dn); - if(pn <= 1) continue;///no scaf - s = e = (uint64_t)-1; - for (z = 0; z < pn; z++) { - if((p[z].f) || (((p[z].qe-p[z].qs) >= rthres) && ((p[z].te-p[z].ts) >= rthres))) { - s = e = z; break; - } - } - for (; z < pn; z++) { - if((p[z].f) || (((p[z].qe-p[z].qs) >= rthres) && ((p[z].te-p[z].ts) >= rthres))) e = z; - } - // fprintf(stderr, "[M::%s::] # k:%lu, s::%lu, e::%lu\n", __func__, k, s, e); - ///[s, e] - u = ((ku.n)?&(hu1->u.a[k]):&(hu2->u.a[k-hu1->u.n])); - set_fsk(fsk, 1, ((ku.n)?&(cp1->a[k]):&(cp2->a[k-hu1->u.n]))); - for (z = 1; z < pn; z++) { - ///cannot scaffold circles - ut = ((p[z-1].tnu.n)?&(hu1->u.a[p[z-1].tn]):&(hu2->u.a[p[z-1].tn-hu1->u.n])); if(ut->circ) continue; - ut = ((p[z].tnu.n)?&(hu1->u.a[p[z].tn]):&(hu2->u.a[p[z].tn-hu1->u.n])); if(ut->circ) continue; - // fprintf(stderr, "[M::%s::] # k:%lu, z::%lu, p[z-1].tn::%u, p[z].tn::%u, hu1->u.n::%u, hu2->u.n::%u\n", __func__, k, z, p[z-1].tn, p[z].tn, (uint32_t)hu1->u.n, (uint32_t)hu2->u.n); - - el = 0; gl = 0; - if((sce[(p[z-1].tnu.n)?0:1] != sce[(p[z-1].qnu.n)?0:1]) && (sce[(p[z].tnu.n)?0:1] != sce[(p[z].qnu.n)?0:1])) {///tn and qn come from different haplotypes - if((((z-1)>=s)&&((z-1)<=e))&&(((z)>=s)&&((z)<=e))) el = 1; - // fprintf(stderr, "-0-[M::%s::] # k::%lu, z::%lu, el::%lu\n", __func__, k, z, el); - if(el) { - zs = MAX(p[z-1].qs, p[z].qs); - ze = MIN(p[z-1].qe, p[z].qe); - if(is_noisy_ov(MIN(zs, ze), MAX(zs, ze), u->len, 2500000, 0.5, d, dn)) el = 0; - // fprintf(stderr, "-1-[M::%s::] # k::%lu, z::%lu, el::%lu, zs::%ld, ze::%ld\n", __func__, k, z, el, zs, ze); - if(el) { - gl = zs - ze; - if((!(p[z-1].f)) || (!(p[z].f))) { - if(gl >= gmin && gl <= gmax) el = 1; - else el = 0;///gap is too long - } else if(p[z-1].f && p[z].f) { - if(gl <= gmax) el = 1; ///p[z-1] and p[z] are too far away is bad; p[z-1] and p[z] are overlapped is fine - else el = 0; - } - } - // fprintf(stderr, "-2-[M::%s::] # k::%lu, z::%lu, el::%lu, zs::%ld, ze::%ld, p[z-1].f::%u, p[z].f::%u, gmin::%ld, gmax::%ld\n", __func__, k, z, el, zs, ze, p[z-1].f, p[z].f, gmin, gmax); - } - ///final try in graph - // fprintf(stderr, "[M::%s::] # k::%lu, z::%lu, el::%lu, gl::%ld\n", __func__, k, z, el, gl); - is_dip = 0; - - glen = is_small_tangle(&(p[z-1]), &(p[z]), ref, hu1, hu2, cp1, cp2, &b0, &b1, &b2, &b3, f, fs, fsk, 5000000, &is_dip); - // fprintf(stderr, "[M::%s::] # k::%lu, z::%lu, el::%lu, glen::%lu, gl::%ld\n", __func__, k, z, el, glen, gl); - if((glen != (uint64_t)-1) && (((int64_t)glen) <= asm_opt.self_scaf_gap_max)) { - el = 1; if(!is_dip) gl = glen; - } - } - if(gl < minNs) gl = minNs; - if(el) { - ///in anyway the gap cannot be too large - if(gl <= gmax) el = 1; ///p[z-1] and p[z] are too far away is bad; p[z-1] and p[z] are overlapped is fine - else el = 0; - } - - scaf_hit2arc(&(p[z-1]), &(p[z]), 0, el, gl, &t); - c = asg_arc_pushp(g); *c = t; - scaf_hit2arc(&(p[z]), &(p[z-1]), 1, el, gl, &t); - c = asg_arc_pushp(g); *c = t; - } - set_fsk(fsk, 0, ((ku.n)?&(cp1->a[k]):&(cp2->a[k-hu1->u.n]))); - } - asg_cleanup(g); asg_symm(g); - // fprintf(stderr, "[M::%s::] EEE\n", __func__); - - uint64_t v, n_vtx = g->n_seq<<1, nv; asg_arc_t *av; - for (v = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - nv = asg_arc_n(g, v); - if(nv <= 1) continue; - av = asg_arc_a(g, v); - for(k = 0; k < nv; k++) { - if(av[k].del) continue; - av[k].del = 1; - asg_arc_del(g, av[k].v^1, (av[k].ul>>32)^1, 1); - } - } - for (k = 0; k < g->n_arc; k++) { - if(!(g->arc[k].el)) g->arc[k].del = 1; - } - asg_cleanup(g); - - if((ref->u.n<<1) < g->n_seq) REALLOC(f, g->n_seq); - memset(f, 0, sizeof((*f))*g->n_seq); - asg64_v b64; kv_init(b64); kvect_sec_t *i1 = NULL, *i2 = NULL, *im = NULL; uint64_t len[2];///, mmip; - sec_t *mmi; CALLOC(i1, 1); CALLOC(i2, 1); ///i1->ctg = hu1; i2->ctg = hu2; - - b0.n = 0; ///mmip = hu1->u.n; mmip <<= 1; - for (v = 0; v < n_vtx; ++v) { - nv = asg_arc_n(g, v); assert(nv <= 1); - if(f[v>>1]) continue; - if(asg_arc_n(g, (v^1)) != 0) continue; - b64.n = 0; mf = gen_scaf_path_lst(g, v, &b64, &blen, &bf); - assert(mf == END_TIPS); - // rn = prt_gen_scaf_path_lst(b64.a, b64.n, (mf==LOOP)?1:0, hu1, hu2); kv_push(uint32_t, b0, rn); - for (k = len[0] = len[1] = 0; k < b64.n; k++) { - f[((uint32_t)b64.a[k])>>1] = 1; - len[g->seq[((uint32_t)b64.a[k])>>1].c-1] += g->seq[((uint32_t)b64.a[k])>>1].len; - } - im = ((len[0] >= len[1])?i1:i2); kv_pushp(sec_t, (*im), &mmi); memset(mmi, 0, sizeof((*mmi))); - mmi->is_c = 0; mmi->n = mmi->m = b64.n; MALLOC(mmi->a, mmi->n); memcpy(mmi->a, b64.a, sizeof((*(mmi->a)))*mmi->n); - // for (k = 0; k < mmi->n; k++) { ///scaffold bug - // if((((uint32_t)mmi->a[k])>>1) >= hu1->u.n) mmi->a[k] -= mmip; - // } - } - - for (v = 0; v < n_vtx; ++v) { - nv = asg_arc_n(g, v); assert(nv <= 1); - if(f[v>>1]) continue; - assert((nv == 1) && (asg_arc_n(g, (v^1)) == 1)); - b64.n = 0; mf = gen_scaf_path_lst(g, v, &b64, &blen, &bf); - assert(mf == LOOP); - // rn = prt_gen_scaf_path_lst(b64.a, b64.n, (mf==LOOP)?1:0, hu1, hu2); kv_push(uint32_t, b0, rn); - for (k = len[0] = len[1] = 0; k < b64.n; k++) { - f[((uint32_t)b64.a[k])>>1] = 1; - len[g->seq[((uint32_t)b64.a[k])>>1].c-1] += g->seq[((uint32_t)b64.a[k])>>1].len; - } - im = ((len[0] >= len[1])?i1:i2); - im = ((len[0] >= len[1])?i1:i2); kv_pushp(sec_t, (*im), &mmi); memset(mmi, 0, sizeof((*mmi))); - mmi->is_c = 1; mmi->n = mmi->m = b64.n; MALLOC(mmi->a, mmi->n); memcpy(mmi->a, b64.a, sizeof((*(mmi->a)))*mmi->n); - // for (k = 0; k < mmi->n; k++) { ///scaffold bug - // if((((uint32_t)mmi->a[k])>>1) >= hu1->u.n) mmi->a[k] -= mmip; - // } - } - kv_destroy(b64); - // cal_arr_N50(b0.a, b0.n, "Scf"); - - // b1.n = 0; - // for(k = 0; k < hu1->u.n; k++) kv_push(uint32_t, b1, hu1->u.a[k].len); - // for(k = 0; k < hu2->u.n; k++) kv_push(uint32_t, b1, hu2->u.a[k].len); - // cal_arr_N50(b1.a, b1.n, "Ctg"); - - kv_destroy(b0); kv_destroy(b1); kv_destroy(b2); kv_destroy(b3); free(f); free(fs); free(fsk); asg_destroy(g); - (*sc1) = i1; (*sc2) = i2; -} - -kv_u_trans_t *gen_shallow_ref_trans(bubble_type *bu, scaf_res_t *cp0, scaf_res_t *cp1, asg_t *sg, ma_ug_t *ref, ma_sub_t* cover, ma_hit_t_alloc* src, ma_hit_t_alloc* rev, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, bub_label_t* b_mask_t) -{ - kvec_asg_arc_t_warp ne; kv_init(ne.a); kv_u_trans_t *p = NULL; CALLOC(p, 1); - ma_ug_t *cref = gen_shallow_clean_ug(ref, bu, cp0, cp1); - asg_t *csg = copy_read_graph(sg); hap_cov_t *cov = NULL; ne.a.n = 0; - - adjust_utg_by_primary(&cref, csg, TRIO_THRES, src, rev, cover, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, &ne, &cov, b_mask_t, 0, 0); - - ma_ug_destroy(cref); asg_destroy(csg); kv_destroy(ne.a); - p->n = cov->t_ch->k_trans.n; p->m = cov->t_ch->k_trans.m; p->a = cov->t_ch->k_trans.a; - p->idx.n = cov->t_ch->k_trans.idx.n; p->idx.m = cov->t_ch->k_trans.idx.m; p->idx.a = cov->t_ch->k_trans.idx.a; - cov->t_ch->k_trans.n = cov->t_ch->k_trans.m = 0; cov->t_ch->k_trans.a = NULL; - cov->t_ch->k_trans.idx.n = cov->t_ch->k_trans.idx.m = 0; cov->t_ch->k_trans.idx.a = NULL; - destory_hap_cov_t(&cov); - return p; -} - -kv_u_trans_t *gen_deep_ref_trans(kv_u_trans_t *in, scaf_res_t *cp0, scaf_res_t *cp1, asg_t *sg, ma_ug_t *ref, ma_sub_t* cover, ma_hit_t_alloc* src, ma_hit_t_alloc* rev, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, bub_label_t* b_mask_t, ug_opt_t *opt) -{ - kvec_asg_arc_t_warp ne; kv_init(ne.a); kv_u_trans_t *p = NULL; CALLOC(p, 1); - ma_ug_t *cref = gen_clean_ug(ref, cp0, cp1); ma_ug_t *ccref = copy_untig_graph(cref); - asg_t *csg = copy_read_graph(sg); hap_cov_t *cov = NULL; ne.a.n = 0; - // print_debug_gfa(sg, cref, cover, "cl.sb.utg", src, ruIndex, opt->max_hang, opt->min_ovlp, 0, 0, 0); - - adjust_utg_by_primary(&cref, csg, TRIO_THRES, src, rev, cover, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, &ne, &cov, b_mask_t, 1, 0); - - ma_ug_destroy(cref); asg_destroy(csg); kv_destroy(ne.a); - if(in) { - kv_resize(u_trans_t, cov->t_ch->k_trans, cov->t_ch->k_trans.n + in->n); - memcpy(cov->t_ch->k_trans.a + cov->t_ch->k_trans.n, in->a, (in->n*sizeof((*(in->a))))); - cov->t_ch->k_trans.n += in->n; - clean_u_trans_t_idx_filter_adv(&(cov->t_ch->k_trans), ref, sg, 0.6, 1);///select best overlap for each pair of contigs - } - - filter_u_trans(&(cov->t_ch->k_trans), asm_opt.is_bub_trans, asm_opt.is_topo_trans, asm_opt.is_read_trans, asm_opt.is_base_trans); - if(asm_opt.is_base_trans) { - ma_ug_seq(ccref, sg, cover, src, NULL, max_hang, min_ovlp, NULL, 0);///polish - trans_base_infer(ccref, sg, opt, &(cov->t_ch->k_trans), NULL); - ma_ug_destroy(ccref); - } - clean_u_trans_t_idx_filter_adv(&(cov->t_ch->k_trans), ref, sg, 0.6, 0); - - p->n = cov->t_ch->k_trans.n; p->m = cov->t_ch->k_trans.m; p->a = cov->t_ch->k_trans.a; - p->idx.n = cov->t_ch->k_trans.idx.n; p->idx.m = cov->t_ch->k_trans.idx.m; p->idx.a = cov->t_ch->k_trans.idx.a; - cov->t_ch->k_trans.n = cov->t_ch->k_trans.m = 0; cov->t_ch->k_trans.a = NULL; - cov->t_ch->k_trans.idx.n = cov->t_ch->k_trans.idx.m = 0; cov->t_ch->k_trans.idx.a = NULL; - destory_hap_cov_t(&cov); - return p; -} - -ma_ug_t *merge_utgs(ma_ug_t *in0, ma_ug_t *in1) -{ - uint64_t k, m[2]; ma_utg_t *su = NULL, *du = NULL; - m[0] = ((uint64_t)(in0->g->n_seq))<<1; - m[1] = ((uint64_t)(in0->g->n_seq))<<33; - ma_ug_t *ug = NULL; CALLOC(ug, 1); ug->g = asg_init(); - ug->g->n_F_seq = in0->g->n_F_seq + in1->g->n_F_seq; - ug->g->r_seq = in0->g->r_seq + in1->g->r_seq; - ug->g->m_seq = ug->g->n_seq = in0->g->n_seq + in1->g->n_seq; - MALLOC(ug->g->seq, ug->g->n_seq); - memcpy(ug->g->seq, in0->g->seq, sizeof((*(ug->g->seq)))*in0->g->n_seq); - memcpy(ug->g->seq+in0->g->n_seq, in1->g->seq, sizeof((*(ug->g->seq)))*in1->g->n_seq); - - ug->g->m_arc = ug->g->n_arc = in0->g->n_arc + in1->g->n_arc; - MALLOC(ug->g->arc, ug->g->n_arc); - memcpy(ug->g->arc, in0->g->arc, sizeof((*(ug->g->arc)))*in0->g->n_arc); - for(k = 0; k < in1->g->n_arc; k++) { - ug->g->arc[k+in0->g->n_arc] = in1->g->arc[k]; - ug->g->arc[k+in0->g->n_arc].v += m[0]; - ug->g->arc[k+in0->g->n_arc].ul += m[1]; - } - asg_cleanup(ug->g); asg_symm(ug->g); - - ug->u.m = ug->u.n = in0->u.n + in1->u.n; - MALLOC(ug->u.a, ug->u.n); - for (k = 0; k < in0->u.n; k++) { - su = &(in0->u.a[k]); du = &(ug->u.a[k]); - (*du) = (*su); - du->s = NULL; du->a = NULL; du->m = du->n = su->n; - MALLOC(du->a, du->n); memcpy(du->a, su->a, sizeof((*(du->a)))*du->n); - } - for (k = 0; k < in1->u.n; k++) { - su = &(in1->u.a[k]); du = &(ug->u.a[k + in0->u.n]); - (*du) = (*su); - du->s = NULL; du->a = NULL; du->m = du->n = su->n; - MALLOC(du->a, du->n); memcpy(du->a, su->a, sizeof((*(du->a)))*du->n); - } - - return ug; -} - -scaf_res_t *merge_scaf_res(scaf_res_t *in0, scaf_res_t *in1) -{ - uint64_t k; ul_vec_t *m; ul_vec_t *s; - scaf_res_t *p = NULL; CALLOC(p, 1); - p->n = p->m = in0->n + in1->n; - CALLOC(p->a, p->n); - for(k = 0; k < in0->n; k++) { - m = &(p->a[k]); s = &(in0->a[k]); - *m = *s; - - m->r_base.a = NULL; - if(m->r_base.m) { - MALLOC(m->r_base.a, m->r_base.m); - memcpy(m->r_base.a, s->r_base.a, sizeof((*(m->r_base.a)))*m->r_base.m); - } - - m->bb.a = NULL; - if(m->bb.m) { - MALLOC(m->bb.a, m->bb.m); - memcpy(m->bb.a, s->bb.a, sizeof((*(m->bb.a)))*m->bb.m); - } - - m->N_site.a = NULL; - if(m->N_site.m) { - MALLOC(m->N_site.a, m->N_site.m); - memcpy(m->N_site.a, s->N_site.a, sizeof((*(m->N_site.a)))*m->N_site.m); - } - } - - for(k = 0; k < in1->n; k++) { - m = &(p->a[k + in0->n]); s = &(in1->a[k]); - *m = *s; - - m->r_base.a = NULL; - if(m->r_base.m) { - MALLOC(m->r_base.a, m->r_base.m); - memcpy(m->r_base.a, s->r_base.a, sizeof((*(m->r_base.a)))*m->r_base.m); - } - - m->bb.a = NULL; - if(m->bb.m) { - MALLOC(m->bb.a, m->bb.m); - memcpy(m->bb.a, s->bb.a, sizeof((*(m->bb.a)))*m->bb.m); - } - - m->N_site.a = NULL; - if(m->N_site.m) { - MALLOC(m->N_site.a, m->N_site.m); - memcpy(m->N_site.a, s->N_site.a, sizeof((*(m->N_site.a)))*m->N_site.m); - } - } - - return p; -} - -kv_u_trans_t *gen_contig_trans_func(ma_ug_t *ref, ma_ug_t *hu0, ma_ug_t *hu1, scaf_res_t *cp0, scaf_res_t *cp1, asg_t *sg, bubble_type *bu, ug_opt_t *opt, kv_u_trans_t *bd, uint8_t is_sep, ma_ug_t **rmg, scaf_res_t **rms) -{ - - kv_u_trans_t *os; CALLOC(os, 1); - if(is_sep) { - gen_contig_trans(opt, sg, hu1, cp1, hu0, cp0, ref, bd, hu0->u.n, 0, bu, os); - gen_contig_trans(opt, sg, hu0, cp0, hu1, cp1, ref, bd, 0, hu0->u.n, bu, os); - } else { - ma_ug_t *mg = merge_utgs(hu0, hu1); scaf_res_t *ms = merge_scaf_res(cp0, cp1); - gen_contig_self(opt, sg, mg, ms, ref, bd, hu0->u.n, bu, os, 0); - if(!rmg) ma_ug_destroy(mg); - else (*rmg) = mg; - if(!rms) destroy_scaf_res_t(ms); - else (*rms) = ms; - } - - kt_u_trans_t_idx(os, hu0->u.n + hu1->u.n); - update_ctg_trans_cc(os); - return os; -} - -inline uint64_t get_scp_len(sec_t *scp, ma_ug_t *mg) -{ - uint64_t k, len; ma_utg_t *z = NULL; - for (k = len = 0; k < scp->n; k++) { - z = &(mg->u.a[((uint32_t)scp->a[k])>>1]); len += z->len; len += (scp->a[k]>>32); - } - - return len; -} - -void gen_scaf_res_via(sec_t *scp, uint64_t scp_len, ma_ug_t *mg, scaf_res_t *ms, ul_vec_t *res) -{ - uint64_t k, off, uid, urev, m, tt, s, e, crn, zi; ma_utg_t *z = NULL; ul_vec_t *ua; uc_block_t *p, *des, *src; - for (k = off = res->bb.n = tt = 0; k < scp->n; k++) { - uid = ((uint32_t)scp->a[k])>>1; urev = ((uint32_t)scp->a[k])&1; - z = &(mg->u.a[uid]); ua = &(ms->a[uid]); - for (m = 0; m < ua->bb.n; m++) { - kv_pushp(uc_block_t, res->bb, &p); memset(p, 0, sizeof((*p))); - - (*p) = ua->bb.a[m]; p->aidx = off; //offset of the whole contig within scaf - p->qs = ua->bb.a[m].qs; p->qe = ua->bb.a[m].qe; - if(urev) { - p->qs = ((z->len>ua->bb.a[m].qe)?(z->len-ua->bb.a[m].qe):(0)); - p->qe = ((z->len>ua->bb.a[m].qs)?(z->len-ua->bb.a[m].qs):(0)); - } - p->qs += off; p->qe += off; - - p->hid = uid; p->hid <<= 1; p->hid |= urev; - if(p->qs >= scp_len) p->qs = scp_len; - if(p->qe >= scp_len) p->qe = scp_len; - if(p->qe <= p->qs) res->bb.n--; - else tt += p->te - p->ts;//how many elements - } - off += z->len; off += (scp->a[k]>>32); - } - - sort_uc_block_qe(res->bb.a, res->bb.n); - kv_resize(uc_block_t, res->bb, res->bb.n + tt); - memset(res->bb.a + res->bb.n, 0, tt * sizeof(*(res->bb.a))); //res->bb.a[0, res->bb.n) -> index; res->bb.a[res->bb.n, res->bb.n + tt) -> details - - - for (k = 0, tt = res->bb.n; k < res->bb.n; k++) { - s = tt; e = tt + res->bb.a[k].te - res->bb.a[k].ts; tt = e; off = res->bb.a[k].aidx; - uid = res->bb.a[k].hid>>1; urev = res->bb.a[k].hid&1; z = &(mg->u.a[uid]); - - - src = ms->a[uid].bb.a + res->bb.a[k].ts; - des = res->bb.a + s; crn = e - s; - if(!urev) { - for(zi = 0; zi < crn; zi++) { - des[zi] = src[zi]; - des[zi].qs += off; - des[zi].qe += off; - des[zi].aidx = s; - - if(des[zi].qs >= res->bb.a[k].qe) des[zi].qs = res->bb.a[k].qe; - if(des[zi].qs <= res->bb.a[k].qs) des[zi].qs = res->bb.a[k].qs; - if(des[zi].qe >= res->bb.a[k].qe) des[zi].qe = res->bb.a[k].qe; - if(des[zi].qe <= res->bb.a[k].qs) des[zi].qe = res->bb.a[k].qs; - if(des[zi].qe <= des[zi].qs) des[zi].qe = des[zi].qs; - } - } else { - for(zi = 0; zi < crn; zi++) { - des[zi] = src[zi]; - des[zi].rev = 1 - des[zi].rev; - des[zi].aidx = s; - des[zi].qs = ((z->len>src[zi].qe)?(z->len-src[zi].qe):(0)); - des[zi].qe = ((z->len>src[zi].qs)?(z->len-src[zi].qs):(0)); - des[zi].qs += off; - des[zi].qe += off; - des[zi].aidx = s; - - if(des[zi].qs >= res->bb.a[k].qe) des[zi].qs = res->bb.a[k].qe; - if(des[zi].qs <= res->bb.a[k].qs) des[zi].qs = res->bb.a[k].qs; - if(des[zi].qe >= res->bb.a[k].qe) des[zi].qe = res->bb.a[k].qe; - if(des[zi].qe <= res->bb.a[k].qs) des[zi].qe = res->bb.a[k].qs; - if(des[zi].qe <= des[zi].qs) des[zi].qe = des[zi].qs; - } - } - res->bb.a[k].ts = s; res->bb.a[k].te = e; - - res->bb.a[k].hid = (uint32_t)-1; - } - assert(tt <= res->bb.m); -} - -kv_u_trans_t* cal_scaf_trans(ug_opt_t *opt, ma_ug_t *ref, bubble_type *bu, kv_u_trans_t *bd, asg_t *sg, kvect_sec_t *sc0, kvect_sec_t *sc1, ma_ug_t *mg, scaf_res_t *ms) -{ - ma_ug_t *smg = NULL; scaf_res_t *sms = NULL; uint64_t k; sec_t *u; - ///build ug - CALLOC(smg, 1); - smg->g = asg_init(); - smg->g->m_seq = smg->g->n_seq = sc0->n + sc1->n; MALLOC(smg->g->seq, smg->g->n_seq); - smg->u.m = smg->u.n = sc0->n + sc1->n; CALLOC(smg->u.a, smg->u.n); - for (k = 0; k < smg->g->n_seq; k++) { - smg->g->seq[k].c = 0; smg->g->seq[k].del = 0; - u = ((kn)?&(sc0->a[k]):&(sc1->a[k-sc0->n])); - smg->g->seq[k].len = get_scp_len(u, mg); - smg->u.a[k].len = smg->g->seq[k].len; - } - asg_cleanup(smg->g); asg_symm(smg->g); - - ///build scaf - sms = init_scaf_res_t(sc0->n + sc1->n); - for (k = 0; k < sms->n; k++) { - u = ((kn)?&(sc0->a[k]):&(sc1->a[k-sc0->n])); - gen_scaf_res_via(u, smg->u.a[k].len, mg, ms, &(sms->a[k])); - } - - kv_u_trans_t *p = NULL; CALLOC(p, 1); - gen_contig_self(opt, sg, smg, sms, ref, bd, sc0->n, bu, p, 1); - - kt_u_trans_t_idx(p, sc0->n + sc1->n); - update_ctg_trans_cc(p); - - ma_ug_destroy(smg); - destroy_scaf_res_t(sms); - return p; -} - -inline uint64_t cal_offset_len(double off, double len0, double len1) -{ - return (off*(len1/len0)); -} - -void gen_scaffold_bases(kvect_sec_t *sc0, kvect_sec_t *sc1, ma_ug_t *mg, asg_t *sg, ma_sub_t* cover, ma_hit_t_alloc* src, kvec_asg_arc_t_warp *arcs, int max_hang, int min_ovlp, kv_u_trans_t *p) -{ - if(!p) { - ma_ug_seq(mg, sg, cover, src, arcs, max_hang, min_ovlp, 0, 1); - } else { - uint64_t k, kn, *l0 = NULL, *l1 = NULL, s, e; - kn = sc0->n + sc1->n; - CALLOC(l0, kn); CALLOC(l1, kn); - for (k = 0; k < kn; k++) l0[k] = get_scp_len(((kn)?&(sc0->a[k]):&(sc1->a[k-sc0->n])), mg); - ma_ug_seq(mg, sg, cover, src, arcs, max_hang, min_ovlp, 0, 1); - for (k = 0; k < kn; k++) l1[k] = get_scp_len(((kn)?&(sc0->a[k]):&(sc1->a[k-sc0->n])), mg); - - for (k = 0; k < p->n; k++) { - if(l0[p->a[k].qn] != l1[p->a[k].qn]) { - s = p->a[k].qs; e = p->a[k].qe; - p->a[k].qs = cal_offset_len(s, l0[p->a[k].qn], l1[p->a[k].qn]); - p->a[k].qe = p->a[k].qs + cal_offset_len(((e>s)?(e-s):(0)), l0[p->a[k].qn], l1[p->a[k].qn]); - if(p->a[k].qs > l1[p->a[k].qn]) p->a[k].qs = l1[p->a[k].qn]; - if(p->a[k].qe > l1[p->a[k].qn]) p->a[k].qe = l1[p->a[k].qn]; - } - - if(l0[p->a[k].tn] != l1[p->a[k].tn]) { - s = p->a[k].ts; e = p->a[k].te; - p->a[k].ts = cal_offset_len(s, l0[p->a[k].tn], l1[p->a[k].tn]); - p->a[k].te = p->a[k].ts + cal_offset_len(((e>s)?(e-s):(0)), l0[p->a[k].tn], l1[p->a[k].tn]); - if(p->a[k].ts > l1[p->a[k].tn]) p->a[k].ts = l1[p->a[k].tn]; - if(p->a[k].te > l1[p->a[k].tn]) p->a[k].te = l1[p->a[k].tn]; - } - } - - free(l0); free(l1); - } -} - -void double_scaffold(ma_ug_t *ref, ma_ug_t *hu0, ma_ug_t *hu1, scaf_res_t *cp0, scaf_res_t *cp1, asg_t *sg, ma_sub_t* cover, ma_hit_t_alloc* src, ma_hit_t_alloc* rev, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, bub_label_t* b_mask_t, ug_opt_t *opt, kvect_sec_t **sc0, kvect_sec_t **sc1, ma_ug_t **rmg, kvec_asg_arc_t_warp *arcs, kv_u_trans_t **rs_trans) -{ - bubble_type *bu = NULL; uint8_t *bf = NULL; scaf_res_t *rms = NULL; - bu = gen_bubble_chain(sg, ref, opt, &bf, 0); free(bf); - - kv_u_trans_t *bs = gen_shallow_ref_trans(bu, cp0, cp1, sg, ref, cover, src, rev, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, b_mask_t); - kv_u_trans_t *bd = gen_deep_ref_trans(bs, cp0, cp1, sg, ref, cover, src, rev, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, b_mask_t, opt); - kv_destroy((*bs)); kv_destroy(bs->idx); free(bs); - - kv_u_trans_t *os = gen_contig_trans_func(ref, hu0, hu1, cp0, cp1, sg, bu, opt, bd, 0/**1**/, rmg, (rs_trans?(&rms):(NULL))); - - - // print_ctg_trans_ovlp(os, ref, hu0, cp0, hu1, cp1); - gen_double_scaffold_gfa(ref, hu0, hu1, cp0, cp1, sg, os, 100, sc0, sc1); kv_destroy((*os)); kv_destroy(os->idx); free(os); - - if(rs_trans) { - (*rs_trans) = cal_scaf_trans(opt, ref, bu, bd, sg, *sc0, *sc1, *rmg, rms); - destroy_scaf_res_t(rms); - } - destory_bubbles(bu); free(bu); kv_destroy((*bd)); kv_destroy(bd->idx); free(bd); - - gen_scaffold_bases(*sc0, *sc1, *rmg, sg, cover, src, arcs, max_hang, min_ovlp, ((rs_trans)?(*rs_trans):(NULL))); - - // ma_ug_seq(*rmg, sg, cover, src, arcs, max_hang, min_ovlp, 0, 1); - - // if(rs_trans) adjust_scaffold_ovlp(sc0, sc1, rmg, (*rs_trans)); - -} - - -void gen_self_scaf(ug_opt_t *opt, ma_ug_t *hu0, ma_ug_t *hu1, asg_t *sg, ma_sub_t *cov, ma_hit_t_alloc *src, ma_hit_t_alloc *rev, R_to_U *ri, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, bub_label_t* b_mask_t, -kvect_sec_t **sc0, kvect_sec_t **sc1, ma_ug_t **mug, kvec_asg_arc_t_warp *arcs, kv_u_trans_t **rs_trans) -{ - ma_ug_t *ug = NULL; - - ug = ma_ug_gen(sg); - - ///print_debug_gfa(sg, ug, cov, "sb.utg", src, ri, opt->max_hang, opt->min_ovlp, 0, 0, 0); - - ///fprintf(stderr, "[M::%s] hu0\n", __func__); - scaf_res_t *cp0 = gen_contig_path(opt, sg, hu0, ug); ///prt_scaf_res_t(cp0, ug, hu0, "h1tg"); - ///fprintf(stderr, "[M::%s] hu1\n", __func__); - scaf_res_t *cp1 = gen_contig_path(opt, sg, hu1, ug); ///prt_scaf_res_t(cp1, ug, hu1, "h2tg"); - - double_scaffold(ug, hu0, hu1, cp0, cp1, sg, cov, src, rev, tipsLen, tip_drop_ratio, stops_threshold, ri, chimeric_rate, drop_ratio, max_hang, min_ovlp, b_mask_t, opt, sc0, sc1, mug, arcs, rs_trans); - - ma_ug_destroy(ug); destroy_scaf_res_t(cp0); destroy_scaf_res_t(cp1); - -} - -void destory_kvect_sec_t(kvect_sec_t *p) -{ - uint64_t k; - for(k = 0; k < p->n; k++) free(p->a[k].a); - free(p->a); -} - -void merge_kvec_asg_arc_t_warp(kvec_asg_arc_t_warp *a, kvec_asg_arc_t_warp *b, kvec_asg_arc_t_warp *m) -{ - m->a.n = m->a.m = a->a.n + b->a.n; MALLOC(m->a.a, m->a.n); - memcpy(m->a.a, a->a.a, sizeof((*(a->a.a)))*a->a.n); - memcpy(m->a.a + a->a.n, b->a.a, sizeof((*(b->a.a)))*b->a.n); -} - -void output_trio_graph_joint(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, -long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, -int min_ovlp, long long gap_fuzz, bub_label_t* b_mask_t, ma_ug_t **rhu0, ma_ug_t **rhu1, ug_opt_t *opt) -{ - ma_ug_t *hu0 = NULL, *hu1 = NULL; kvec_asg_arc_t_warp arcs0, arcs1; - memset(&arcs0, 0, sizeof(arcs0)); memset(&arcs1, 0, sizeof(arcs1)); - - reduce_hamming_error_adv(NULL, sg, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz, ruIndex, NULL); - - hu0 = output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, - reverse_sources, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, - drop_ratio, max_hang, min_ovlp, gap_fuzz, 1, b_mask_t, NULL, NULL, &arcs0); - - hu1 = output_trio_unitig_graph(sg, coverage_cut, output_file_name, MOTHER, sources, - reverse_sources, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, - drop_ratio, max_hang, min_ovlp, gap_fuzz, 1, b_mask_t, NULL, NULL, &arcs1); - - dedup_idx_t *hidx0 = NULL, *hidx1 = NULL; uint8_t *ff; CALLOC(ff, sg->n_seq); - hidx0 = gen_dedup_idx_t(hu0, sg); hidx1 = gen_dedup_idx_t(hu1, sg); - update_recover_atg_cov(); - - uint64_t dedup_base = 0, miss_base = 0, s; - s = dedup_exact_ug(hidx1, hidx0, coverage_cut, sources, ruIndex, ff, FATHER); dedup_base += s; - s = dedup_exact_ug(hidx0, hidx1, coverage_cut, sources, ruIndex, ff, MOTHER); dedup_base += s; - destroy_dedup_idx_t(hidx0); destroy_dedup_idx_t(hidx1); - - s = append_miss_nid(sg, hu0, hu1, ff, PHASE_MISS_LEN, PHASE_MISS_N); miss_base += s; - // s = append_miss_nid(sg, hu0, hu1, ff, PHASE_MISS_SLEN, PHASE_MISS_SN); miss_base += s; - free(ff); - - renew_utg((&hu0), sg, &arcs0); renew_utg((&hu1), sg, &arcs1); - fprintf(stderr, "[M::%s] dedup_base::%lu, miss_base::%lu\n", __func__, dedup_base, miss_base); - - if((asm_opt.self_scaf) && (!rhu0) && (!rhu1)) { - kvect_sec_t *sc0 = NULL, *sc1 = NULL; ma_ug_t *mug = NULL; /**kv_u_trans_t *rs_trans = NULL;**/ kvec_asg_arc_t_warp ma; memset(&ma, 0, sizeof(ma)); - merge_kvec_asg_arc_t_warp(&arcs0, &arcs1, &ma); kv_destroy(arcs0.a); kv_destroy(arcs1.a); - gen_self_scaf(opt, hu0, hu1, sg, coverage_cut, sources, reverse_sources, ruIndex, tipsLen, tip_drop_ratio, stops_threshold, chimeric_rate, drop_ratio, max_hang, min_ovlp, b_mask_t, &sc0, &sc1, &mug, &ma, /**&rs_trans**/NULL); - ma_ug_destroy(hu0); ma_ug_destroy(hu1); kv_destroy(ma.a); - - ///output scaf trans - /**kv_destroy((*rs_trans)); kv_destroy(rs_trans->idx); free(rs_trans);**/ - - sc0->ctg = mug; - output_hap_sc_graph(sc0, sg, /**&arcs0,**/ coverage_cut, output_file_name, FATHER, sources, ruIndex, /**max_hang, min_ovlp,**/ NULL); - destory_kvect_sec_t(sc0); free(sc0); - - sc1->ctg = mug; - output_hap_sc_graph(sc1, sg, /**&arcs1,**/ coverage_cut, output_file_name, MOTHER, sources, ruIndex, /**max_hang, min_ovlp,**/ NULL); - destory_kvect_sec_t(sc1); free(sc1); - - ma_ug_destroy(mug); - } else { - if(!rhu0) { - output_hap_graph(hu0, sg, &arcs0, coverage_cut, output_file_name, FATHER, sources, ruIndex, max_hang, min_ovlp, NULL); - ma_ug_destroy(hu0); - } else { - (*rhu0) = hu0; - } - kv_destroy(arcs0.a); - - - if(!rhu1) { - output_hap_graph(hu1, sg, &arcs1, coverage_cut, output_file_name, MOTHER, sources, ruIndex, max_hang, min_ovlp, NULL); - ma_ug_destroy(hu1); - } else { - (*rhu1) = hu1; // ma_ug_destroy(hu1); - } - kv_destroy(arcs1.a); - } -} - -void output_read_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, long long n_read) -{ - fprintf(stderr, "Writing read GFA to disk... \n"); - char* gfa_name = (char*)malloc(strlen(output_file_name)+25); - sprintf(gfa_name, "%s.read.gfa", output_file_name); - FILE* output_file = fopen(gfa_name, "w"); - ma_sg_print(sg, &R_INF, coverage_cut, output_file); - free(gfa_name); - fclose(output_file); -} - - -int load_ma_hit_ts(ma_hit_t_alloc** x, char* read_file_name) -{ - fprintf(stderr, "Loading ma_hit_ts from disk... \n"); - char* index_name = (char*)malloc(strlen(read_file_name)+15); - sprintf(index_name, "%s.bin", read_file_name); - FILE* fp = fopen(index_name, "r"); - if(!fp) - { - return 0; - } - - - long long n_read; - long long i, k; - int f_flag; - f_flag = fread(&n_read, sizeof(n_read), 1, fp); - (*x) = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*n_read); - - - for (i = 0; i < n_read; i++) - { - f_flag += fread(&((*x)[i].is_fully_corrected), sizeof((*x)[i].is_fully_corrected), 1, fp); - f_flag += fread(&((*x)[i].is_abnormal), sizeof((*x)[i].is_abnormal), 1, fp); - f_flag += fread(&((*x)[i].length), sizeof((*x)[i].length), 1, fp); - (*x)[i].size = (*x)[i].length; - - (*x)[i].buffer = NULL; - if((*x)[i].length == 0) continue; - - (*x)[i].buffer = (ma_hit_t*)malloc(sizeof(ma_hit_t)*(*x)[i].length); - - for (k = 0; k < (*x)[i].length; k++) - { - read_ma(&((*x)[i].buffer[k]), fp); - } - // fread((*x)[i].buffer, sizeof((*((*x)[i].buffer))), (*x)[i].length, fp); - } - - free(index_name); - fclose(fp); - fprintf(stderr, "ma_hit_ts has been read.\n"); - - return 1; -} - - -int load_debug_ma_hit_ts(ma_hit_t_alloc** x, char* read_file_name) -{ - fprintf(stderr, "Loading ma_hit_ts from disk... \n"); - char* index_name = (char*)malloc(strlen(read_file_name)+15); - sprintf(index_name, "%s.bin", read_file_name); - FILE* fp = fopen(index_name, "r"); - if(!fp) - { - return 0; - } - - - long long n_read; - long long i/**, k**/; - int f_flag; - f_flag = fread(&n_read, sizeof(n_read), 1, fp); - (*x) = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*n_read); - - - for (i = 0; i < n_read; i++) - { - f_flag += fread(&((*x)[i].is_fully_corrected), sizeof((*x)[i].is_fully_corrected), 1, fp); - f_flag += fread(&((*x)[i].is_abnormal), sizeof((*x)[i].is_abnormal), 1, fp); - f_flag += fread(&((*x)[i].length), sizeof((*x)[i].length), 1, fp); - (*x)[i].size = (*x)[i].length; - - (*x)[i].buffer = NULL; - if((*x)[i].length == 0) continue; - - (*x)[i].buffer = (ma_hit_t*)malloc(sizeof(ma_hit_t)*(*x)[i].length); - - // for (k = 0; k < (*x)[i].length; k++) - // { - // read_ma(&((*x)[i].buffer[k]), fp); - // } - fread((*x)[i].buffer, sizeof((*((*x)[i].buffer))), (*x)[i].length, fp); - } - - free(index_name); - fclose(fp); - fprintf(stderr, "ma_hit_ts has been read.\n"); - - return 1; -} - - -void write_ma(ma_hit_t* x, FILE* fp) -{ - fwrite(&(x->qns), sizeof(x->qns), 1, fp); - fwrite(&(x->qe), sizeof(x->qe), 1, fp); - fwrite(&(x->tn), sizeof(x->tn), 1, fp); - fwrite(&(x->ts), sizeof(x->ts), 1, fp); - fwrite(&(x->te), sizeof(x->te), 1, fp); - fwrite(&(x->el), sizeof(x->el), 1, fp); - fwrite(&(x->no_l_indel), sizeof(x->no_l_indel), 1, fp); - - uint32_t t = x->ml; - fwrite(&(t), sizeof(t), 1, fp); - t = x->rev; - fwrite(&(t), sizeof(t), 1, fp); - - t = x->bl; - fwrite(&(t), sizeof(t), 1, fp); - t =x->del; - fwrite(&(t), sizeof(t), 1, fp); -} - - -void write_ma_hit_ts(ma_hit_t_alloc* x, long long n_read, char* read_file_name) -{ - fprintf(stderr, "Writing ma_hit_ts to disk... \n"); - char* index_name = (char*)malloc(strlen(read_file_name)+15); - sprintf(index_name, "%s.bin", read_file_name); - FILE* fp = fopen(index_name, "w"); - long long i, k; - fwrite(&n_read, sizeof(n_read), 1, fp); - - - for (i = 0; i < n_read; i++) - { - fwrite(&(x[i].is_fully_corrected), sizeof(x[i].is_fully_corrected), 1, fp); - fwrite(&(x[i].is_abnormal), sizeof(x[i].is_abnormal), 1, fp); - fwrite(&(x[i].length), sizeof(x[i].length), 1, fp); - for (k = 0; k < x[i].length; k++) - { - write_ma(x[i].buffer + k, fp); - } - // fwrite(x[i].buffer, sizeof((*(x[i].buffer))), x[i].length, fp); - } - - - free(index_name); - fflush(fp); - fclose(fp); - fprintf(stderr, "ma_hit_ts has been written.\n"); -} - - -void write_debug_ma_hit_ts(ma_hit_t_alloc* x, long long n_read, char* read_file_name) -{ - fprintf(stderr, "Writing ma_hit_ts to disk... \n"); - char* index_name = (char*)malloc(strlen(read_file_name)+15); - sprintf(index_name, "%s.bin", read_file_name); - FILE* fp = fopen(index_name, "w"); - long long i/**, k**/; - fwrite(&n_read, sizeof(n_read), 1, fp); - - - for (i = 0; i < n_read; i++) - { - fwrite(&(x[i].is_fully_corrected), sizeof(x[i].is_fully_corrected), 1, fp); - fwrite(&(x[i].is_abnormal), sizeof(x[i].is_abnormal), 1, fp); - fwrite(&(x[i].length), sizeof(x[i].length), 1, fp); - // for (k = 0; k < x[i].length; k++) - // { - // write_ma(x[i].buffer + k, fp); - // } - fwrite(x[i].buffer, sizeof((*(x[i].buffer))), x[i].length, fp); - } - - - free(index_name); - fflush(fp); - fclose(fp); - fprintf(stderr, "ma_hit_ts has been written.\n"); -} - -void write_yak_binning(char *ou, char *fn_bin_yak1, char *fn_bin_yak2) -{ - fprintf(stderr, "Writing binning to disk ...... \n"); - char* paf_name = (char*)malloc(strlen(ou)+50); - sprintf(paf_name, "%s.hap1.phase.bin", ou); - FILE* oh1 = fopen(paf_name, "w"); - sprintf(paf_name, "%s.hap2.phase.bin", ou); - FILE* oh2 = fopen(paf_name, "w"); - uint64_t i, s1, s2; - - for (i = s1 = s2 = 0; i < R_INF.total_reads; i++) { - if(R_INF.trio_flag[i]==FATHER) { - if(s1) { - fprintf(oh1, "%.*s\n", (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); - } else { - fprintf(oh1, "%.*s\t%s\n", (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i), fn_bin_yak1); - } - s1 = 1; - } - if(R_INF.trio_flag[i]==MOTHER) { - if(s2) { - fprintf(oh2, "%.*s\n", (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); - } else { - fprintf(oh2, "%.*s\t%s\n", (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i), fn_bin_yak2); - } - s2 = 1; - } - } - free(paf_name); - fclose(oh1); fclose(oh2); - fprintf(stderr, "Binning has been written.\n"); -} - -uint32_t load_yak_binning(hifiasm_opt_t *opt, char *ou)///asm_opt -{ - char* paf_name = (char*)malloc(strlen(ou)+50); - uint32_t len[2] = {0}; char *lst0, *lst1, *yak0, *yak1; - lst0 = lst1 = yak0 = yak1 = NULL; - - sprintf(paf_name, "%s.hap1.phase.bin", ou); len[0] = strlen(paf_name)+1; - if(!test_yak_binning(paf_name, opt->fn_bin_yak[0])) { - free(paf_name); return 0; - } - - sprintf(paf_name, "%s.hap2.phase.bin", ou); len[1] = strlen(paf_name)+1; - if(!test_yak_binning(paf_name, opt->fn_bin_yak[1])) { - free(paf_name); return 0; - } - free(paf_name); paf_name = NULL; - - lst0 = opt->fn_bin_list[0]; MALLOC(opt->fn_bin_list[0], len[0]); - sprintf(opt->fn_bin_list[0], "%s.hap1.phase.bin", ou); - - lst1 = opt->fn_bin_list[1]; MALLOC(opt->fn_bin_list[1], len[1]); - sprintf(opt->fn_bin_list[1], "%s.hap2.phase.bin", ou); - - memset(R_INF.trio_flag, AMBIGU, R_INF.total_reads * sizeof(uint8_t)); - yak0 = opt->fn_bin_yak[0]; opt->fn_bin_yak[0] = NULL; - yak1 = opt->fn_bin_yak[1]; opt->fn_bin_yak[1] = NULL; - ha_triobin(opt); - opt->fn_bin_yak[0] = yak0; opt->fn_bin_yak[1] = yak1; - free(opt->fn_bin_list[0]); opt->fn_bin_list[0] = lst0; - free(opt->fn_bin_list[1]); opt->fn_bin_list[1] = lst1; - return 1; -} - -void write_all_data_to_disk(ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, All_reads *RNF, char* output_file_name) -{ - char* gfa_name = (char*)malloc(strlen(output_file_name)+25); - sprintf(gfa_name, "%s.ec", output_file_name); - write_All_reads(RNF, gfa_name); - - if((ha_opt_triobin(&asm_opt)) && (asm_opt.fn_bin_yak[0] && asm_opt.fn_bin_yak[1])) { - write_yak_binning(asm_opt.output_file_name, asm_opt.fn_bin_yak[0], asm_opt.fn_bin_yak[1]); - } - - sprintf(gfa_name, "%s.ovlp.source", output_file_name); - write_ma_hit_ts(sources, RNF->total_reads, gfa_name); - - sprintf(gfa_name, "%s.ovlp.reverse", output_file_name); - write_ma_hit_ts(reverse_sources, RNF->total_reads, gfa_name); - - free(gfa_name); - fprintf(stderr, "bin files have been written.\n"); - if(asm_opt.bin_only) exit(0); -} - -int load_debug_graph(asg_t** sg, ma_hit_t_alloc** sources, ma_sub_t** coverage_cut, -char* output_file_name, ma_hit_t_alloc** reverse_sources, R_to_U* ruIndex, all_ul_t *ul_r_inf); -int load_all_data_from_disk(ma_hit_t_alloc **sources, ma_hit_t_alloc **reverse_sources, char* output_file_name) -{ - char* gfa_name = (char*)malloc(strlen(output_file_name)+25); - sprintf(gfa_name, "%s.ec", output_file_name); - if (!load_All_reads(&R_INF, gfa_name)) { - free(gfa_name); - return 0; - } - - if(ha_opt_triobin(&asm_opt)) { - if(!((asm_opt.fn_bin_yak[0]) && (asm_opt.fn_bin_yak[1]) && - (load_yak_binning(&asm_opt, asm_opt.output_file_name)))) { - ha_triobin(&asm_opt); - write_yak_binning(asm_opt.output_file_name, asm_opt.fn_bin_yak[0], asm_opt.fn_bin_yak[1]); - } - } - - if((asm_opt.flag & HA_F_VERBOSE_GFA) && load_debug_graph(NULL, NULL, NULL, output_file_name, NULL, NULL, NULL)) - { - (*sources) = NULL; - (*reverse_sources) = NULL; - free(gfa_name); - return 1; - } - - sprintf(gfa_name, "%s.ovlp.source", output_file_name); - if (!load_ma_hit_ts(sources, gfa_name)) { - free(gfa_name); - return 0; - } - sprintf(gfa_name, "%s.ovlp.reverse", output_file_name); - if (!load_ma_hit_ts(reverse_sources, gfa_name)) { - free(gfa_name); - return 0; - } - free(gfa_name); - return 1; -} - -// count the number of outgoing arcs, excluding reduced arcs -static inline int count_out(const asg_t *g, uint32_t v) -{ - uint32_t i, n, nv = asg_arc_n(g, v); - const asg_arc_t *av = asg_arc_a(g, v); - for (i = n = 0; i < nv; ++i) - if (!av[i].del) ++n; - return n; -} - - -void dfs_trans_chain_bub(asg_t *g, hap_cov_t *cov, uint32_t v, uint32_t beg, uint32_t sink) -{ - buf_t *b = &(cov->t_ch->b_buf_0); - b->b.n = 0; - if(v == beg || v == sink) return; - uint64_t *flag = cov->pos_idx; - asg_arc_t *acur = NULL; - uint32_t cur, ncur, i; - v = v << 1; - kv_push(uint32_t, b->b, v); - while (b->b.n > 0) - { - b->b.n--; - cur = b->b.a[b->b.n]; - if(flag[cur>>1] == 0 && (cur>>1) != (v>>1)) continue; - flag[cur>>1] = 0; - - ncur = asg_arc_n(g, cur); - acur = asg_arc_a(g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if((acur[i].v>>1) == beg || (acur[i].v>>1) == sink) continue; - if(flag[acur[i].v>>1] == 0) continue; - kv_push(uint32_t, b->b, acur[i].v); - } - } - - v = v + 1; - kv_push(uint32_t, b->b, v); - while (b->b.n > 0) - { - b->b.n--; - cur = b->b.a[b->b.n]; - if(flag[cur>>1] == 0 && (cur>>1) != (v>>1)) continue; - flag[cur>>1] = 0; - - ncur = asg_arc_n(g, cur); - acur = asg_arc_a(g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if((acur[i].v>>1) == beg || (acur[i].v>>1) == sink) continue; - if(flag[acur[i].v>>1] == 0) continue; - kv_push(uint32_t, b->b, acur[i].v); - } - } - - b->b.n = 0; - for (i = 0; i < cov->t_ch->topo_res.n; ++i) //has been sorted - { - if(flag[cov->t_ch->topo_res.a[i]>>1] == 0) - { - flag[cov->t_ch->topo_res.a[i]>>1] = (uint64_t)-1; - } - else - { - kv_push(uint32_t, b->b, cov->t_ch->topo_res.a[i]); - } - } - - - /*******************************for debug************************************/ - // for (i = 0; i < cov->n; ++i) - // { - // if(flag[i] != (uint64_t)-1) fprintf(stderr, "ERROR-0\n"); - // } - /*******************************for debug************************************/ -} - -void debug_topo_sorting(asg_t *g, hap_cov_t *cov, uint32_t beg, uint32_t sink) -{ - buf_t *b = &(cov->t_ch->b_buf_0); - uint64_t *flag = cov->pos_idx; - asg_arc_t *acur = NULL; - uint32_t cur, ncur, i, k, k_i, v; - - for (k = 0; k < cov->t_ch->topo_res.n; k++) - { - v = cov->t_ch->topo_res.a[k]; - - b->b.n = 0; - kv_push(uint32_t, b->b, v); - while (b->b.n > 0) - { - b->b.n--; - cur = b->b.a[b->b.n]; - - ncur = asg_arc_n(g, cur); - acur = asg_arc_a(g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if((acur[i].v>>1) == (beg>>1) || (acur[i].v>>1) == (sink>>1)) continue; - kv_push(uint32_t, b->b, acur[i].v); - if(flag[acur[i].v>>1] == 0) - { - fprintf(stderr, "\nERROR-1\n"); - fprintf(stderr, "beg>>1: %u, sink>>1: %u, topo_res.n: %u, v>>1: %u, w>>1: %u\n", - beg>>1, sink>>1, (uint32_t)cov->t_ch->topo_res.n, v>>1, acur[i].v>>1); - for (k_i = 0; k_i < cov->t_ch->topo_res.n; k_i++) - { - fprintf(stderr, "k_i: %u, topo_res>>1: %u\n", k_i, cov->t_ch->topo_res.a[k_i]>>1); - } - } - - } - } - - flag[cov->t_ch->topo_res.a[k]>>1] = 0; - } - - for (k = 0; k < cov->t_ch->topo_res.n; k++) - { - flag[cov->t_ch->topo_res.a[k]>>1] = (uint64_t)-1; - } -} - -void topologicalSortUtil(asg_t *g, hap_cov_t *cov, uint32_t beg, uint32_t sink) -{ - buf_t *b = &(cov->t_ch->b_buf_0); - uint64_t *visited = cov->pos_idx; - uint32_t v = beg, nv, kv, i; - asg_arc_t *av = NULL; - - b->b.n = 0; cov->t_ch->topo_res.n = 0; - kv_push(uint32_t, b->b, v); - while (b->b.n > 0) - { - ///b->b.n--; - v = b->b.a[b->b.n-1]; - if(visited[v>>1] == (uint64_t)-1) - { - visited[v>>1] = 0; - } - - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - for (i = kv = 0; i < nv; i++) - { - if(av[i].del) continue; - if((av[i].v>>1) == (beg>>1) || (av[i].v>>1) == (sink>>1)) continue; - if(visited[av[i].v>>1] != (uint64_t)-1) continue; - kv_push(uint32_t, b->b, av[i].v); - kv++; - } - - if(kv != 0) continue; - b->b.n--; - if(visited[v>>1] != 1) - { - kv_push(uint32_t, cov->t_ch->topo_res, v); - visited[v>>1] = 1; - } - } - for (i = 0; i < cov->t_ch->topo_res.n; ++i) - { - visited[cov->t_ch->topo_res.a[i]>>1] = (uint64_t)-1; - } - - cov->t_ch->topo_res.n--;//remove beg - for (i = 0; i < (cov->t_ch->topo_res.n>>1); ++i) - { - v = cov->t_ch->topo_res.a[i]; - cov->t_ch->topo_res.a[i] = cov->t_ch->topo_res.a[cov->t_ch->topo_res.n - i - 1]; - cov->t_ch->topo_res.a[cov->t_ch->topo_res.n - i - 1] = v; - } - - /*******************************for debug************************************/ - // for (i = 0; i < cov->n; ++i) - // { - // if(visited[i] != (uint64_t)-1) fprintf(stderr, "ERROR-2\n"); - // } - // debug_topo_sorting(g, cov, beg, sink); - /*******************************for debug************************************/ -} - -void chain_origin_trans_uid_s_bubble(buf_t *pri, buf_t* aux, uint32_t beg, uint32_t sink, ma_ug_t *ug, hap_cov_t *cov) -{ - if(pri->b.n == 0 || aux->b.n == 0) return; - asg_arc_t *av = NULL; - uint32_t pri_v, aux_v, nv, i, priBeg, priEnd, auxBeg, auxEnd; - uint64_t pri_len, aux_len; - - priBeg = priEnd = auxBeg = auxEnd = (uint32_t)-1; - pri_len = set_utg_offset(pri->b.a, pri->b.n, ug, cov->read_g, cov->pos_idx, 0, 1); - aux_len = set_utg_offset(aux->b.a, aux->b.n, ug, cov->read_g, cov->pos_idx, 0, 1); - - pri_v = pri->b.a[0]; aux_v = aux->b.a[0]; - av = asg_arc_a(ug->g, beg); - nv = asg_arc_n(ug->g, beg); - for (i = 0; i < nv; ++i) - { - if(av[i].del) continue; - if(av[i].v == pri_v) priBeg = av[i].ol; - if(av[i].v == aux_v) auxBeg = av[i].ol; - } - - pri_v = pri->b.a[pri->b.n-1]^1; aux_v = aux->b.a[aux->b.n-1]^1; - av = asg_arc_a(ug->g, sink); - nv = asg_arc_n(ug->g, sink); - for (i = 0; i < nv; ++i) - { - if(av[i].del) continue; - if(av[i].v == pri_v) priEnd = ((pri_len > av[i].ol)? (pri_len - av[i].ol - 1) : 0); - if(av[i].v == aux_v) auxEnd = ((aux_len > av[i].ol)? (aux_len - av[i].ol - 1) : 0); - } - ///[priBeg, priEnd) && [auxBeg, auxEnd) - if(priBeg == (uint32_t)-1 || priEnd == (uint32_t)-1 || auxBeg == (uint32_t)-1 || auxEnd == (uint32_t)-1) - { - fprintf(stderr, "ERROR-s_bubble\n"); - } - - cov->u_buffer.a.n = cov->tailIndex.a.n = 0; - - kv_resize(asg_arc_t_offset, cov->u_buffer.a, 1); - cov->u_buffer.a.n = 1; - cov->u_buffer.a.a[0].Off = priEnd; - cov->u_buffer.a.a[0].Off <<= 32; - cov->u_buffer.a.a[0].Off |= auxEnd; - - kv_resize(int32_t, cov->tailIndex.a, 1); - cov->tailIndex.a.n = 1; - cov->tailIndex.a.a[0] = 0; - - // uint32_t i_n = cov->t_ch->k_trans.n; - - chain_origin_trans_uid_by_distance(cov, cov->read_g, pri->b.a, pri->b.n, priBeg, &pri_len, aux->b.a, aux->b.n, auxBeg, &aux_len, ug, RC_0, -1024, __func__); - - // fprintf(stderr, "\nocc: %u\n", (uint32_t)(cov->t_ch->k_trans.n - i_n)); - // for (i = i_n; i < cov->t_ch->k_trans.n; i++) - // { - // fprintf(stderr, "s-utg%.6ul\t%u\t%u\td-utg%.6ul\t%u\t%u\trev(%u)\n", - // cov->t_ch->k_trans.a[i].qn+1, cov->t_ch->k_trans.a[i].qs, cov->t_ch->k_trans.a[i].qe, - // cov->t_ch->k_trans.a[i].tn+1, cov->t_ch->k_trans.a[i].ts, cov->t_ch->k_trans.a[i].te, - // cov->t_ch->k_trans.a[i].rev); - // } -} - -void chain_origin_trans_uid_c_bubble(uint32_t query, buf_t *target, buf_t *idx, ma_ug_t *ug, hap_cov_t *cov) -{ - if(target->b.n == 0) return; - uint32_t qs, qe, ts, te, i, v, ovlp; - qs = idx->a[query].d; qe = qs + ug->g->seq[query>>1].len; - uint64_t qlen = ug->g->seq[query>>1].len, tlen; - cov->u_buffer.a.n = cov->tailIndex.a.n = 0; - - ///uint32_t i_n = cov->t_ch->k_trans.n; - for (i = 0; i < target->b.n; ++i) - { - v = target->b.a[i]; - if(v < query) continue; //avoid dup - ts = idx->a[v].d; te = ts + ug->g->seq[v>>1].len; tlen = ug->g->seq[v>>1].len; - ovlp = ((MIN(qe, te) > MAX(qs, ts))? (MIN(qe, te) - MAX(qs, ts)) : 0); - if(ovlp == 0) continue; - chain_origin_trans_uid_by_distance(cov, cov->read_g, &query, 1, MAX(qs, ts) - qs, &qlen, - &v, 1, MAX(qs, ts) - ts, &tlen, ug, RC_0, -1024, __func__); - } - // fprintf(stderr, "\nocc: %u\n", (uint32_t)(cov->t_ch->k_trans.n - i_n)); - // for (i = i_n; i < cov->t_ch->k_trans.n; i++) - // { - // fprintf(stderr, "s-utg%.6ul\t%u\t%u\td-utg%.6ul\t%u\t%u\trev(%u)\n", - // cov->t_ch->k_trans.a[i].qn+1, cov->t_ch->k_trans.a[i].qs, cov->t_ch->k_trans.a[i].qe, - // cov->t_ch->k_trans.a[i].tn+1, cov->t_ch->k_trans.a[i].ts, cov->t_ch->k_trans.a[i].te, - // cov->t_ch->k_trans.a[i].rev); - // } -} - -// in a resolved bubble, mark unused vertices and arcs as "reduced" -static void asg_bub_backtrack_primary_cov(ma_ug_t *ug, uint32_t v0, buf_t *b, hap_cov_t *cov, uint32_t is_update_chain) -{ - uint32_t i, k, k_i, v, u, uLen = 0, uCov = 0, uId, rId, ori; - ma_utg_t* p = NULL; - trans_chain* t_ch = (is_update_chain?cov->t_ch:NULL); - ///b->S.a[0] is the sink of this bubble - - ///assert(b->S.n == 1); - ///first remove all nodes in this bubble - for (i = 0; i < b->b.n; ++i) - { - uId = b->b.a[i]>>1; - if(uId == (b->S.a[0]>>1)) continue; - p = &(ug->u.a[uId]); - if(p->n == 0) continue; - - for (k = 0; k < p->n; k++) - { - rId = p->a[k]>>33; - uCov += cov->cov[rId]; - } - } - - - ///v is the sink of this bubble - v = b->S.a[0]; - ///recover node - do { - u = b->a[v].p; // u->v - if(v != b->S.a[0]) - { - uId = v>>1; - p = &(ug->u.a[uId]); - if(p->n == 0) continue; - for (k = 0; k < p->n; k++) - { - rId = p->a[k]>>33; - uCov -= cov->cov[rId]; - uLen += cov->read_g->seq[rId].len; - } - } - v = u; - } while (v != v0); - - uCov = (uLen == 0? 0 : uCov / uLen); - - ///v is the sink of this bubble - v = b->S.a[0]; - ///recover node - do { - u = b->a[v].p; // u->v - if(v != b->S.a[0]) - { - uId = v>>1; - p = &(ug->u.a[uId]); - if(p->n == 0) continue; - for (k = 0; k < p->n; k++) - { - rId = p->a[k]>>33; - cov->cov[rId] += (uCov * cov->read_g->seq[rId].len);///this the average coverage of the whole bubble - } - } - v = u; - } while (v != v0); - - - if(t_ch) - { - ///is this requirement appropriate? - if(get_real_length(ug->g, v0, NULL) == 2 && get_real_length(ug->g, b->S.a[0]^1, NULL) == 2) - { - long long tmp, max_stop_nodeLen, max_stop_baseLen, bch_occ[2]; - uint32_t bch[2], convex[2]; - get_real_length(ug->g, v0, bch); - - ///in rare cases, one side of a bubble might be empty - if((bch[0]>>1)!=(b->S.a[0]>>1) && (bch[1]>>1)!=(b->S.a[0]>>1)) - { - get_unitig(ug->g, NULL, bch[0], &convex[0], &bch_occ[0], &tmp, - &max_stop_nodeLen, &max_stop_baseLen, 1, NULL); - get_unitig(ug->g, NULL, bch[1], &convex[1], &bch_occ[1], &tmp, - &max_stop_nodeLen, &max_stop_baseLen, 1, NULL); - ///if this is a simple bubble - if(((bch_occ[0] + bch_occ[1] + 1) == (uint32_t)b->b.n) && - get_real_length(ug->g, convex[0], NULL) == 1 && get_real_length(ug->g, convex[1], NULL) == 1) - { - get_real_length(ug->g, convex[0], &convex[0]); - get_real_length(ug->g, convex[1], &convex[1]); - if(convex[0] == b->S.a[0] && convex[1] == b->S.a[0])///double check if it is a simple bubble - { - t_ch->b_buf_0.b.n = 0; - get_unitig(ug->g, NULL, bch[0], &convex[0], &bch_occ[0], &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, &(t_ch->b_buf_0)); - for (i = 0; i < t_ch->b_buf_0.b.n; ++i)///retrive one side of the bubble - { - uId = t_ch->b_buf_0.b.a[i]>>1; - p = &(ug->u.a[uId]); - if(p->n == 0) continue; - ori = t_ch->b_buf_0.b.a[i]&1; - for (k = 0; k < p->n; k++) - { - t_ch->ir_het[(ori == 1?((p->a[p->n-k-1])>>33):(p->a[k]>>33))] |= P_HET; - } - } - - t_ch->b_buf_1.b.n = 0; - get_unitig(ug->g, NULL, bch[1], &convex[1], &bch_occ[1], &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, &(t_ch->b_buf_1)); - for (i = 0; i < t_ch->b_buf_1.b.n; ++i)///retrive another side of the bubble - { - uId = t_ch->b_buf_1.b.a[i]>>1; - p = &(ug->u.a[uId]); - if(p->n == 0) continue; - ori = t_ch->b_buf_1.b.a[i]&1; - for (k = 0; k < p->n; k++) - { - t_ch->ir_het[(ori == 1?((p->a[p->n-k-1])>>33):(p->a[k]>>33))] |= P_HET; - } - } - ///generate read-to-read overlaps - chain_origin_trans_uid_s_bubble(&(t_ch->b_buf_0), &(t_ch->b_buf_1), - v0, b->S.a[0]^1, ug, cov); - return; - } - } - } - } - - topologicalSortUtil(ug->g, cov, v0, b->S.a[0]); - ///if(cov->t_ch->topo_res.n != b->b.n - 1) fprintf(stderr, "ERROR-4\n"); - if(cov->t_ch->topo_res.n == 0) return; - for (i = 0; i < cov->t_ch->topo_res.n; ++i) - { - uId = cov->t_ch->topo_res.a[i]>>1; - if(uId == (b->S.a[0]>>1)) continue; - - dfs_trans_chain_bub(ug->g, cov, uId, v0>>1, b->S.a[0]>>1); - - if(cov->t_ch->b_buf_0.b.n == 0) continue; - chain_origin_trans_uid_c_bubble(cov->t_ch->topo_res.a[i], &(t_ch->b_buf_0), b, ug, cov); - - /***********************x***********************/ - uId = cov->t_ch->topo_res.a[i]>>1; - p = &(ug->u.a[uId]); - if(p->n == 0) continue; - ori = cov->t_ch->topo_res.a[i]&1; - for (k = 0; k < p->n; k++) - { - t_ch->ir_het[(ori == 1?((p->a[p->n-k-1])>>33):(p->a[k]>>33))] |= P_HET; - } - /***********************x***********************/ - - /***********************y***********************/ - for (k_i = 0; k_i < t_ch->b_buf_0.b.n; ++k_i) - { - uId = t_ch->b_buf_0.b.a[k_i]>>1; - p = &(ug->u.a[uId]); - if(p->n == 0) continue; - ori = t_ch->b_buf_0.b.a[k_i]&1; - for (k = 0; k < p->n; k++) - { - t_ch->ir_het[(ori == 1?((p->a[p->n-k-1])>>33):(p->a[k]>>33))] |= P_HET; - } - } - /***********************y***********************/ - } - } -} - - -// in a resolved bubble, mark unused vertices and arcs as "reduced" -void asg_bub_backtrack_primary(asg_t *g, uint32_t v0, buf_t *b) -{ - uint32_t i, v, qn, tn; - ///b->S.a[0] is the sink of this bubble - uint32_t tmp_c = g->seq[b->S.a[0]>>1].c; - - ///assert(b->S.n == 1); - ///first remove all nodes in this bubble - for (i = 0; i < b->b.n; ++i) - { - g->seq[b->b.a[i]>>1].c = ALTER_LABLE; - } - - ///v is the sink of this bubble - v = b->S.a[0]; - ///recover node - do { - uint32_t u = b->a[v].p; // u->v - /****************************may have hap bugs********************************/ - ////g->seq[v>>1].c = PRIMARY_LABLE; - g->seq[v>>1].c = HAP_LABLE; - /****************************may have hap bugs********************************/ - v = u; - } while (v != v0); - ///especially for unitig graph, don't label beg and sink node of a bubble as HAP_LABLE - ///since in unitig graph, a node may consist of a lot of reads - g->seq[b->S.a[0]>>1].c = tmp_c; - - ///remove all edges (self/reverse for each edge) in this bubble - for (i = 0; i < b->e.n; ++i) { - asg_arc_t *a = &g->arc[b->e.a[i]]; - qn = a->ul>>33; - tn = a->v>>1; - if(g->seq[qn].c == ALTER_LABLE && g->seq[tn].c == ALTER_LABLE) - { - continue; - } - ///remove this edge self - a->del = 1; - ///remove the reverse direction - asg_arc_del(g, a->v^1, a->ul>>32^1, 1); - } - - ///v is the sink of this bubble - v = b->S.a[0]; - ///recover node - do { - uint32_t u = b->a[v].p; // u->v - g->seq[v>>1].del = 0; - asg_arc_del(g, u, v, 0); - asg_arc_del(g, v^1, u^1, 0); - v = u; - } while (v != v0); -} - - -// in a resolved bubble, mark unused vertices and arcs as "reduced" -void asg_bub_backtrack_primary_length(asg_t *g, ma_ug_t *utg, uint32_t v0, buf_t *b, uint64_t* path_base_len, uint64_t* path_nodes) -{ - uint32_t i, v, u, nv; - uint64_t len = 0, node = 0; - ///b->S.a[0] is the sink of this bubble - asg_arc_t *av = NULL; - - ///v is the sink of this bubble - v = b->S.a[0]; - len = 0; - ///recover node - while (1) - { - u = b->a[v].p; // u->v - if(u == v0) break; - if(v == b->S.a[0]) - { - len += g->seq[u>>1].len; - } - else - { - nv = asg_arc_n(g, u); - av = asg_arc_a(g, u); - for (i = 0; i < nv; ++i) - { - if(av[i].del) continue; - if(av[i].v == v) break; - } - ///if(i == nv) fprintf(stderr, "ERROR\n"); - len += (uint32_t)av[i].ul; - } - - if(utg) - { - node += utg->u.a[u>>1].n; - } - else - { - node++; - } - - v = u; - } - - if(path_base_len) (*path_base_len) = len; - if(path_nodes) (*path_nodes) = node; -} - - -// in a resolved bubble, mark unused vertices and arcs as "reduced" -int asg_bub_backtrack_check_switch(asg_t *g, ma_ug_t *utg, uint32_t v0, buf_t *b) -{ - uint32_t v, k, rId, father_occ = 0, mother_occ = 0; - ma_utg_t* p = NULL; - ///b->S.a[0] is the sink of this bubble - ///v is the sink of this bubble - v = b->S.a[0]; - ///recover node - do { - uint32_t u = b->a[v].p; // u->v - if(v != b->S.a[0]) - { - p = &(utg->u.a[v>>1]); - for (k = 0; k < p->n; k++) - { - rId = p->a[k]>>33; - if(R_INF.trio_flag[rId] == FATHER) father_occ++; - if(R_INF.trio_flag[rId] == MOTHER) mother_occ++; - if(R_INF.trio_flag[rId] != AMBIGU) continue; - R_INF.trio_flag[rId] = DROP; - } - } - v = u; - } while (v != v0); - - if(father_occ > 0 && mother_occ > 0) return 1; - - return 0; -} - -// pop bubbles from vertex v0; the graph MJUST BE symmetric: if u->v present, v'->u' must be present as well -uint64_t asg_bub_pop1_primary_trio_switch_check(asg_t *g, ma_ug_t *utg, uint32_t v0, uint64_t max_dist, buf_t *b, -uint32_t positive_flag, uint32_t negative_flag, uint32_t is_pop, uint64_t* path_base_len, uint64_t* path_nodes, -int* is_switch) -{ - uint32_t i, n_pending = 0, /**is_first = 1,**/ cur_m, cur_c, cur_np, cur_nc, to_replace, n_tips, tip_end; - uint64_t n_pop = 0; - long long cur_weight = -1, max_weight = -1; - ///if this node has been deleted - if (g->seq[v0>>1].del || g->seq[v0>>1].c == ALTER_LABLE) return 0; // already deleted - ///if ((uint32_t)g->idx[v0] < 2) return 0; // no bubbles - if(get_real_length(g, v0, NULL)<2) return 0; - ///S saves nodes with all incoming edges visited - b->S.n = b->T.n = b->b.n = b->e.n = 0; - ///for each node, b->a saves all related information - b->a[v0].c = b->a[v0].d = b->a[v0].m = b->a[v0].nc = b->a[v0].np = 0; - ///b->S is the nodes with all incoming edges visited - kv_push(uint32_t, b->S, v0); - n_tips = 0; - tip_end = (uint32_t)-1; - uint32_t non_positive_flag = (uint32_t)-1; - if(positive_flag == FATHER) non_positive_flag = MOTHER; - if(positive_flag == MOTHER) non_positive_flag = FATHER; - - do { - ///v is a node that all incoming edges have been visited - ///d is the distance from v0 to v - uint32_t v = kv_pop(b->S), d = b->a[v].d, c = b->a[v].c, m = b->a[v].m, nc = b->a[v].nc, np = b->a[v].np; - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - ///why we have this assert? - ///assert(nv > 0); - ///all out-edges of v - for (i = 0; i < nv; ++i) { // loop through v's neighbors - /** - p->ul: |____________31__________|__________1___________|______________32_____________| - qn direction of overlap length of this node (not overlap length) - (in the view of query) - p->v : |___________31___________|__________1___________| - tn reverse direction of overlap - (in the view of target) - p->ol: overlap length - **/ - ///if this edge has been deleted - if (av[i].del) continue; - - uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l - binfo_t *t = &b->a[w]; - ///that means there is a circle, directly terminate the whole bubble poping - ///if (w == v0) goto pop_reset; - if ((w>>1) == (v0>>1)) goto pop_reset; - /****************************may have bugs********************************/ - ///important when poping at long untig graph - // if(is_first) l = 0; - /****************************may have bugs********************************/ - - - - ///push the edge - ///high 32-bit of g->idx[v] is the start point of v's edges - //so here is the point of this specfic edge - kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); - ///find a too far path? directly terminate the whole bubble poping - if (d + l > max_dist) break; // too far - - ///if this node - if (t->s == 0) { // this vertex has never been visited - kv_push(uint32_t, b->b, w); // save it for revert - ///t->p is the parent node of - ///t->s = 1 means w has been visited - ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) - t->p = v, t->s = 1, t->d = d + l; - /****************************may have bugs********************************/ - cur_c = cur_m = cur_np = 0; cur_nc = 1; - if(utg) - { - cur_c = get_num_trio_flag(utg, w>>1, positive_flag); - cur_m = get_num_trio_flag(utg, w>>1, negative_flag); - cur_np = 0; - if(non_positive_flag != (uint32_t)-1) - { - cur_np = get_num_trio_flag(utg, w>>1, non_positive_flag); - } - cur_nc = utg->u.a[(w>>1)].n; - } - - - t->c = c + cur_c; - t->m = m + cur_m; - t->nc = nc + cur_nc; - t->np = np + cur_np; - /****************************may have bugs********************************/ - ///incoming edges of w - ///t->r = count_out(g, w^1); - t->r = get_real_length(g, w^1, NULL); - ++n_pending; - } else { // visited before - /****************************may have bugs********************************/ - cur_c = cur_m = cur_np = 0; cur_nc = 1; - if(utg) - { - cur_c = get_num_trio_flag(utg, w>>1, positive_flag); - cur_m = get_num_trio_flag(utg, w>>1, negative_flag); - cur_np = 0; - if(non_positive_flag != (uint32_t)-1) - { - cur_np = get_num_trio_flag(utg, w>>1, non_positive_flag); - } - cur_nc = utg->u.a[(w>>1)].n; - } - ///BUG: select the path with less negative_flag, less non_positive_flag, more positive_flag, more distance - ///FIXED: select the path with less (negative_flag+non_positive_flag), more positive_flag, more distance - to_replace = 0; - - /****************************may have bugs********************************/ - cur_weight = (long long)(c + cur_c) - ((long long)(m + cur_m) + (long long)(np + cur_np)); - max_weight = (long long)t->c - ((long long)t->m + (long long)t->np); - if(cur_weight > max_weight) - { - to_replace = 1; - } - else if(cur_weight == max_weight) - { - if(nc + cur_nc > t->nc) - { - to_replace = 1; - } - else if(nc + cur_nc == t->nc) - { - if(d + l > t->d) - { - to_replace = 1; - } - } - } - /****************************may have bugs********************************/ - - /** - if(((m + cur_m) + (np + cur_np)) < (t->m + t->np)) - { - to_replace = 1; - } - else if(((m + cur_m) + (np + cur_np)) == (t->m + t->np)) - { - if(c + cur_c > t->c) - { - to_replace = 1; - } - else if(c + cur_c == t->c) - { - if(nc + cur_nc > t->nc) - { - to_replace = 1; - } - else if(nc + cur_nc == t->nc) - { - if(d + l > t->d) - { - to_replace = 1; - } - } - - } - } - **/ - - - if(to_replace) - { - t->p = v; - t->m = m + cur_m; - t->c = c + cur_c; - t->nc = nc + cur_nc; - t->np = np + cur_np; - } - ///c is the weight (is very likely the number of node in this edge) of the parent node - ///select the longest edge (longest meams most reads/longest edge) - // if (c + 1 > t->c || (c + 1 == t->c && d + l > t->d)) t->p = v; - // if (c + 1 > t->c) t->c = c + 1; - /****************************may have bugs********************************/ - ///update len(v0->w) - ///node: t->d is not the length from this node's parent - ///it is the shortest edge - if (d + l < t->d) t->d = d + l; // update dist - } - ///assert(t->r > 0); - //if all incoming edges of w have visited - //push it to b->S - if (--(t->r) == 0) { - uint32_t x = get_real_length(g, w, NULL); - /****************************may have bugs for bubble********************************/ - if(x > 0) - { - kv_push(uint32_t, b->S, w); - } - else - { - ///at most one tip - if(n_tips != 0) goto pop_reset; - n_tips++; - tip_end = w; - } - /****************************may have bugs for bubble********************************/ - --n_pending; - } - } - // is_first = 0; - //if found a tip - /****************************may have bugs for bubble********************************/ - if(n_tips == 1) - { - if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) - { - kv_push(uint32_t, b->S, tip_end); - break; - } - else - { - goto pop_reset; - } - } - /****************************may have bugs for bubble********************************/ - ///if i < nv, that means (d + l > max_dist) - if (i < nv || b->S.n == 0) goto pop_reset; - } while (b->S.n > 1 || n_pending); - - if(is_switch) (*is_switch) = asg_bub_backtrack_check_switch(g, utg, v0, b); - if(is_pop) asg_bub_backtrack_primary(g, v0, b); - if(path_base_len || path_nodes) asg_bub_backtrack_primary_length(g, utg, v0, b, path_base_len, path_nodes); - - - n_pop = 1; -pop_reset: - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - binfo_t *t = &b->a[b->b.a[i]]; - t->s = t->c = t->d = t->m = t->nc = t->np = 0; - } - return n_pop; -} - - -int bub_complex_hamming(asg_t *sg, ma_ug_t *ug, uint32_t beg_utg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, kvec_t_u32_warp* stack, -int max_hang, int min_ovlp, uint8_t* trio_flag, uint8_t* vis_flag, kv_asg_arc_t* e, buf_t *b, uint64_t tLen) -{ - uint32_t k_i, k_j, k_v, rID; - int is_switch_0, is_switch_1; - ma_utg_t* nsu = NULL; - - is_switch_0 = is_switch_1 = 1; - asg_bub_pop1_primary_trio_switch_check(ug->g, ug, beg_utg, tLen, b, FATHER, DROP, 0, NULL, NULL, &is_switch_0); - - if(is_switch_0 == 0) - { - asg_bub_pop1_primary_trio_switch_check(ug->g, ug, beg_utg, tLen, b, MOTHER, DROP, 0, NULL, NULL, &is_switch_1); - } - - - for (k_i = 0; k_i < b->b.n; k_i++) - { - if((b->b.a[k_i]>>1)==(beg_utg>>1) || (b->b.a[k_i]>>1)==(b->S.a[0]>>1)) continue; - nsu = &(ug->u.a[b->b.a[k_i]>>1]); - for (k_j = 0; k_j < nsu->n; k_j++) - { - rID = nsu->a[k_j]>>33; - if(R_INF.trio_flag[rID] == DROP) R_INF.trio_flag[rID] = AMBIGU; - } - } - - if(is_switch_0 == 0 && is_switch_1 == 0) return 0; - - - - uint32_t i, sink_utg, begRid, sinkRid; - sink_utg = b->S.a[0]^1; - - if(beg_utg&1) - { - begRid = ug->u.a[beg_utg>>1].start^1; - } - else - { - begRid = ug->u.a[beg_utg>>1].end^1; - } - - if(sink_utg&1) - { - sinkRid = ug->u.a[sink_utg>>1].start; - } - else - { - sinkRid = ug->u.a[sink_utg>>1].end; - } - - - - - asg_arc_t *acur = NULL; - uint32_t cur, ncur, v, n_vx = sg->n_seq<<1; - stack->a.n = 0; - memset(vis_flag, 0, n_vx); - - kv_push(uint32_t, stack->a, begRid); - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - ncur = asg_arc_n(sg, cur); - acur = asg_arc_a(sg, cur); - vis_flag[cur] = 1; - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if(vis_flag[acur[i].v]) continue; - if(acur[i].v == sinkRid) continue; - kv_push(uint32_t, stack->a, acur[i].v); - } - } - vis_flag[sinkRid] = 1; - - - ma_hit_t_alloc* x = NULL; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - int32_t r; - asg_arc_t t0, t1; - - - for (k_i = 0; k_i < b->b.n; k_i++) - { - if((b->b.a[k_i]>>1)==(beg_utg>>1) || (b->b.a[k_i]>>1)==(b->S.a[0]>>1)) continue; - // nsu = &(ug->u.a[a[k_i]>>1]); - nsu = &(ug->u.a[b->b.a[k_i]>>1]); - for (k_j = 0; k_j < nsu->n; k_j++) - { - rID = nsu->a[k_j]>>33; - for (k_v = 0; k_v < 2; k_v++) - { - v = (rID<<1) + k_v; - if(vis_flag[v] == 0) continue; - x = &(sources[v>>1]); - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(st->del || sg->seq[Get_tn(*h)].del) continue; - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t0); - - ///if it is a contained read, skip - if(r < 0) continue; - if((t0.ul>>32) != v) continue; - if(vis_flag[t0.ul>>32] == 0 || vis_flag[t0.v] == 0) continue; - if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, (t0.v^1), ((t0.ul>>32)^1), &t1)) { - kv_push(asg_arc_t, *e, t0); kv_push(asg_arc_t, *e, t1); - } - } - } - } - } - - return 1; -} - - -int gen_switch_phasing(asg_t *sg, ma_ug_t *ug, uint64_t bi, -ma_hit_t_alloc* src, ma_sub_t *cov, int32_t max_hang, -int32_t min_ovlp, uint8_t* trio_flag, uint8_t* vis_r_flag, -buf_t *b, uint64_t tLen, uint64_t vis_f, asg_t *res, asg64_v *sv) -{ - uint32_t k_i, k_j, k_v, rev, z, zn; asg_arc_t *za; - ma_utg_t* nsu = NULL; int sw0, sw1; - - sw0 = sw1 = 1; - asg_bub_pop1_primary_trio_switch_check(ug->g, ug, bi, tLen, b, FATHER, DROP, 0, NULL, NULL, &sw0); - if(sw0 == 0) { - asg_bub_pop1_primary_trio_switch_check(ug->g, ug, bi, tLen, b, MOTHER, DROP, 0, NULL, NULL, &sw1); - } - - for (k_i = 0; k_i < b->b.n; k_i++) { - if((b->b.a[k_i]>>1)==(bi>>1) || (b->b.a[k_i]>>1)==(b->S.a[0]>>1)) continue; - nsu = &(ug->u.a[b->b.a[k_i]>>1]); - for (k_j = 0; k_j < nsu->n; k_j++) { - if(R_INF.trio_flag[nsu->a[k_j]>>33] == DROP) R_INF.trio_flag[nsu->a[k_j]>>33] = AMBIGU; - } - } - if(sw0 == 0 && sw1 == 0) return 0; - - uint64_t i, ei = b->S.a[0]^1, v, bv, ev; - for (k_i = 0; k_i < b->b.n; k_i++) { - if((b->b.a[k_i]>>1)==(bi>>1) || (b->b.a[k_i]>>1)==(b->S.a[0]>>1)) continue; - nsu = &(ug->u.a[b->b.a[k_i]>>1]); rev = b->b.a[k_i]&1; - for (k_j = 0; k_j < nsu->n; k_j++) { - v = nsu->a[k_j]>>32; if(rev) v ^= 1; - vis_r_flag[v] = vis_f; - } - } - bv = (bi&1)?(ug->u.a[bi>>1].start^1):(ug->u.a[bi>>1].end^1); //vis_r_flag[bv] = vis_f; - ev = (ei&1)?(ug->u.a[ei>>1].start^1):(ug->u.a[ei>>1].end^1); //vis_r_flag[ev] = vis_f; - - ma_hit_t_alloc* x = NULL; - ma_hit_t *h; ma_sub_t *sq, *st; - int32_t r; asg_arc_t t0, t1, *p; - - for (k_i = 0; k_i < b->b.n; k_i++) { - if((b->b.a[k_i]>>1)==(bi>>1) || (b->b.a[k_i]>>1)==(b->S.a[0]>>1)) continue; - nsu = &(ug->u.a[b->b.a[k_i]>>1]); - for (k_j = 0; k_j < nsu->n; k_j++) { - for (k_v = 0; k_v < 2; k_v++) { - v = ((nsu->a[k_j]>>33)<<1) + k_v; - if(vis_r_flag[v] != vis_f) continue;; - x = &(src[v>>1]); - za = asg_arc_a(sg, v); - zn = asg_arc_n(sg, v); - for (i = 0; i < x->length; i++) { - h = &(x->buffer[i]); - // if(!(h->el)) continue; - sq = &(cov[Get_qn(*h)]); st = &(cov[Get_tn(*h)]); - if(st->del || sg->seq[Get_tn(*h)].del) continue; - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t0); - - ///if it is a contained read, skip - if(r < 0) continue; - if((t0.ul>>32) != v) continue; - if((vis_r_flag[t0.ul>>32] != vis_f) || (vis_r_flag[t0.v] != vis_f)) continue; - for (z = 0; (z < zn) && (za[z].v != t0.v); z++); - if(z < zn) continue; - if(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, (t0.v^1), ((t0.ul>>32)^1), &t1)) { - p = asg_arc_pushp(res); *p = t0; - p = asg_arc_pushp(res); *p = t1; - } - } - - } - } - } - kv_push(uint64_t, *sv, (bv<<32)|(ev)); - return 1; -} - -int asg_arc_del_trans_aux(asg_t *g, asg_t *aux, uint8_t *mark, int fuzz) -{ - uint32_t v, w, n_vtx = g->n_seq * 2, n_reduced = 0; - uint32_t L, i, j, nv0, nv1, kv; asg_arc_t *av0, *av1; - asg_arc_t *aw0, *aw1; uint32_t nw0, nw1; - memset(mark, 0, sizeof((*mark))*n_vtx); - - for (v = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - nv0 = asg_arc_n(g, v); av0 = asg_arc_a(g, v); - nv1 = asg_arc_n(aux, v); av1 = asg_arc_a(aux, v); - if (nv0 + nv1 == 0) continue; - //all outnode of v should be set to "not reduce" - for (i = kv = 0; i < nv0; ++i) { - if(av0[i].del) continue; - mark[av0[i].v] = 1; kv++; - } - for (i = 0; i < nv1; ++i) { - if(av1[i].del) continue; - mark[av1[i].v] = 1; kv++; - } - if(kv == 0) continue; - - ///av[nv-1] is longest out-dege - L = 0; - if(nv0) L = asg_arc_len(av0[nv0-1]); - if(nv1 && L < asg_arc_len(av1[nv1-1])) L = asg_arc_len(av1[nv1-1]); - L += fuzz; - for (i = 0; i < nv0; ++i) { - //w is an out-node of v - w = av0[i].v; if (mark[w] != 1) continue; ///w has already been reduced - nw0 = asg_arc_n(g, w); aw0 = asg_arc_a(g, w); - nw1 = asg_arc_n(aux, w); aw1 = asg_arc_a(aux, w); - - for (j = 0; j < nw0 && asg_arc_len(aw0[j]) + asg_arc_len(av0[i]) <= L; ++j) - if (mark[aw0[j].v]) mark[aw0[j].v] = 2; - for (j = 0; j < nw1 && asg_arc_len(aw1[j]) + asg_arc_len(av0[i]) <= L; ++j) - if (mark[aw1[j].v]) mark[aw1[j].v] = 2; - } - //remove edges - for (i = 0; i < nv0; ++i) { - if (mark[av0[i].v] == 2) { - av0[i].del = 1; ++n_reduced; - } - mark[av0[i].v] = 0; - } - } - - if (n_reduced) { - asg_cleanup(g); - asg_symm(g); - } - - return n_reduced; -} -/** -#define ba_fetch(pa, ca, v0, v) (((v)==(v0))?(pa)[(v)]:(ca)[(v)]) -uint64_t rd_hm_bub(asg_t *g, asg_t *ref, uint32_t v0, uint64_t max_dist, buf_t *b) -{ - uint32_t i0, i1, n_pending = 0, is_first = 1, n_tips, tip_end; uint64_t n_pop = 0; - uint32_t v, w, d, nv0, nv1, l, x, i; asg_arc_t *av0, *av1; binfo_t *t, *pa, *ca; - if (g->seq[v0>>1].del) return 0; // already deleted - nv0 = g?get_real_length(g, v0, NULL):0; - nv1 = ref?get_real_length(ref, v0, NULL):0; - // if((v0 == 4386) && (!ref)) { - // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), nv0::%u, nv1::%u\n", __func__, v0>>1, v0&1, - // nv0, nv1); - // } - if((nv0+nv1) < 2) return 0; - pa = b->a; ca = b->a + (g->n_seq<<1); - // if(v0 >= (ref->n_seq<<1)) { - // fprintf(stderr, "[M::%s] v0::%u, ref->n_seq::%u\n", __func__, v0, ref->n_seq); - // } - b->S.n = b->T.n = b->b.n = b->e.n = 0; - v = v0; t = &(ba_fetch(pa, ca, v0, v)); - t->c = t->d = t->m = t->nc = t->np = 0; - ///b->S is the nodes with all incoming edges visited - kv_push(uint32_t, b->S, v0); - n_tips = 0; tip_end = (uint32_t)-1; - - do { - ///v is a node that all incoming edges have been visited - ///d is the distance from v0 to v - v = kv_pop(b->S); d = (ba_fetch(pa, ca, v0, v)).d; - nv0 = 0; av0 = NULL; nv1 = 0; av1 = NULL; i0 = i1 = 0; - if(g) { - nv0 = asg_arc_n(g, v); av0 = asg_arc_a(g, v); - } - if(ref) { - nv1 = asg_arc_n(ref, v); av1 = asg_arc_a(ref, v); - } - // if((v0 == 4386) && (!ref)) { - // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), v>>1::%u(v&1::%u)\n", __func__, v0>>1, v0&1, v>>1, v&1); - // } - ///all out-edges of v - for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors - if (av0[i0].del) continue; - w = av0[i0].v; l = (uint32_t)av0[i0].ul; t = &((ba_fetch(pa, ca, v0, w))); - // if((v0 == 4386) && (!ref)) { - // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), w>>1::%u(w&1::%u)\n", - // __func__, v0>>1, v0&1, w>>1, w&1); - // } - if ((w>>1) == (v0>>1)) goto pop_rd_hm_bub; - if(is_first) l = 0; - if (d + l > max_dist) break; // too far - ///unvisited node - if (t->s == 0) { // this vertex has never been visited - kv_push(uint32_t, b->b, w); // save it for revert - t->p = v, t->s = 1, t->d = d + l; - t->r = (g?get_real_length(g, w^1, NULL):0)+(ref?get_real_length(ref, w^1, NULL):0); - ++n_pending; - } else { // visited before - ///the shortest path - if (d + l < t->d) t->d = d + l; // update dist - } - // if((v0 == 4386) && (!ref) && ((w>>1) == 2597)) { - // fprintf(stderr, "[M::%s] w>>1::%u(w&1::%u), t->r::%u\n", - // __func__, w>>1, w&1, t->r); - // } - //if all incoming edges of w have visited - //push it to b->S - if (--(t->r) == 0) { - x = (g?get_real_length(g, w, NULL):0)+(ref?get_real_length(ref, w, NULL):0); - // if((v0 == 4386) && (!ref) && ((w>>1) == 2597)) { - // fprintf(stderr, "[M::%s] w>>1::%u(w&1::%u), t->r::%u, x::%u, b->S.n::%u\n", - // __func__, w>>1, w&1, t->r, x, (uint32_t)b->S.n); - // } - if(x > 0) { - // if((v0 == 4386) && (!ref)) { - // fprintf(stderr, "+[M::%s] v0>>1::%u(v0&1::%u), push_w>>1::%u(w&1::%u)\n", - // __func__, v0>>1, v0&1, w>>1, w&1); - // uint32_t m; - // for (m = 0; m < b->S.n; m++) { - // fprintf(stderr, "+[M::%s] m>>1::%u(m&1::%u)\n", __func__, b->S.a[m]>>1, b->S.a[m]&1); - // } - // } - kv_push(uint32_t, b->S, w); - } else { - ///at most one tip - if(n_tips != 0) goto pop_rd_hm_bub; - n_tips++; tip_end = w; - } - --n_pending; - } - } - if (i0 >= nv0) { - for (i1 = 0; i1 < nv1; ++i1) { // loop through v's neighbors - if (av1[i1].del) continue; - w = av1[i1].v; l = (uint32_t)av1[i1].ul; t = &((ba_fetch(pa, ca, v0, w))); - if ((w>>1) == (v0>>1)) goto pop_rd_hm_bub; - if(is_first) l = 0; - if (d + l > max_dist) break; // too far - ///unvisited node - if (t->s == 0) { // this vertex has never been visited - kv_push(uint32_t, b->b, w); // save it for revert - t->p = v, t->s = 1, t->d = d + l; - t->r = (g?get_real_length(g, w^1, NULL):0)+(ref?get_real_length(ref, w^1, NULL):0); - ++n_pending; - } else { // visited before - ///the shortest path - if (d + l < t->d) t->d = d + l; // update dist - } - - //if all incoming edges of w have visited - //push it to b->S - if (--(t->r) == 0) { - x = (g?get_real_length(g, w, NULL):0)+(ref?get_real_length(ref, w, NULL):0); - if(x > 0) { - // if((v0 == 4386) && (!ref)) { - // fprintf(stderr, "-[M::%s] v0>>1::%u(v0&1::%u), push_w>>1::%u(w&1::%u)\n", - // __func__, v0>>1, v0&1, w>>1, w&1); - // } - kv_push(uint32_t, b->S, w); - } else { - ///at most one tip - if(n_tips != 0) goto pop_rd_hm_bub; - n_tips++; tip_end = w; - } - --n_pending; - } - } - } - - is_first = 0; - //if found a tip - if(n_tips == 1) { - if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) { - // if((v0 == 4386) && (!ref)) { - // fprintf(stderr, ">[M::%s] v0>>1::%u(v0&1::%u), push_w>>1::%u(w&1::%u)\n", - // __func__, v0>>1, v0&1, tip_end>>1, tip_end&1); - // } - kv_push(uint32_t, b->S, tip_end); - break; - } else { - goto pop_rd_hm_bub; - } - } - // if((v0 == 4386) && (!ref)) { - // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), b->S.n::%u, n_pending::%u\n", - // __func__, v0>>1, v0&1, (uint32_t)b->S.n, n_pending); - // } - ///if i < nv, that means (d + l > max_dist) - if (i0 < nv0 || i1 < nv1 || b->S.n == 0) goto pop_rd_hm_bub; - } while (b->S.n > 1 || n_pending); - n_pop = 1; - pop_rd_hm_bub: - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - t = &((ba_fetch(pa, ca, v0, b->b.a[i]))); - t->s = t->c = t->d = t->m = t->nc = t->np = 0; - } - return n_pop; -} - -uint64_t rd_hm_drop0(asg_t *g, asg_t *ref, uint32_t v, double cutoff) -{ - uint32_t nv0, nv1, mol = 0, i0, i1, ncut = 0; asg_arc_t *av0, *av1; - nv0 = asg_arc_n(g, v); av0 = asg_arc_a(g, v); - nv1 = asg_arc_n(ref, v); av1 = asg_arc_a(ref, v); - if(cutoff < 1) { - for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors - if (av0[i0].del) continue; - if(mol < av0[i0].ol) mol = av0[i0].ol; - } - for (i1 = 0; i1 < nv1; ++i1) { // loop through v's neighbors - if (av1[i1].del) continue; - if(mol < av1[i1].ol) mol = av1[i1].ol; - } - if(mol > 0) { - for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors - if (av0[i0].del) continue; - if(av0[i0].ol < (mol*cutoff)) { - av0[i0].del = 1; asg_arc_del(g, av0[i0].v^1, (av0[i0].ul>>32)^1, 1); - ncut++; - } - } - } - } else { - for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors - if (av0[i0].del) continue; - av0[i0].del = 1; asg_arc_del(g, av0[i0].v^1, (av0[i0].ul>>32)^1, 1); - ncut++; - } - } - return ncut; -} - -uint64_t rd_hm_drop(asg_t *g, asg_t *ref, uint32_t v0, uint32_t v1, double cutoff, buf_t *b) -{ - uint32_t i1, ncut = 0; - uint32_t v, w, nv1, i; asg_arc_t *av1; - if (g->seq[v0>>1].del) return 0; // already deleted - b->S.n = 0; binfo_t *pa, *ca; - pa = b->a; ca = b->a + (g->n_seq<<1); - ///b->S is the nodes with all incoming edges visited - kv_push(uint32_t, b->S, v0); - while(b->S.n) { - v = kv_pop(b->S); - if((ba_fetch(pa, ca, v0, v)).s) continue; - (ba_fetch(pa, ca, v0, v)).s = 1; - kv_push(uint32_t, b->b, v); // save it for revert - nv1 = asg_arc_n(ref, v); av1 = asg_arc_a(ref, v); - for (i1 = 0; i1 < nv1; ++i1) { // loop through v's neighbors - if (av1[i1].del) continue; - w = av1[i1].v; - if((ba_fetch(pa, ca, v0, w)).s || w == v1) continue; - kv_push(uint32_t, b->S, w); - } - } - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - v = b->b.a[i]; (ba_fetch(pa, ca, v0, b->b.a[i])).s = 0; - if(v == v0 || v == v1) continue; - ncut += rd_hm_drop0(g, ref, v, cutoff); - ncut += rd_hm_drop0(g, ref, v^1, cutoff); - } - ncut += rd_hm_drop0(g, ref, v0, cutoff); - ncut += rd_hm_drop0(g, ref, v1^1, cutoff); - return ncut; -} - -static void rd_hamming_symm(void *data, long i, int tid) // callback for kt_for() -{ - rd_hamming_t *s = (rd_hamming_t *)data; buf_t *b = &(s->a[tid]); - uint32_t st = s->rr->a[i]>>32, ed = (uint32_t)(s->rr->a[i]), p, k, ncut; - double step = 0.2, cuttoff; uint64_t max_dist = s->max_dist; - p = rd_hm_bub(s->g, s->ref, st, max_dist, b); - if(p) { - // if(!(b->S.a[0] == (ed^1))) { - // fprintf(stderr, "[M::%s] st>>1::%u(st&1::%u), ed>>1::%u(ed&1::%u), S[0]>>1::%u(S[0]&1::%u), max_dist::%lu\n", - // __func__, st>>1, st&1, ed>>1, ed&1, b->S.a[0]>>1, b->S.a[0]&1, max_dist); - // } - assert(b->S.a[0] == (ed^1)); - return; - } - ///recalculate max_dist - p = rd_hm_bub(s->ref, NULL, st, max_dist, b); - // if(!p) { - // fprintf(stderr, "[M::%s] st>>1::%u(st&1::%u), ed>>1::%u(ed&1::%u), max_dist::%lu\n", - // __func__, st>>1, st&1, ed>>1, ed&1, max_dist); - // } - assert(p); assert(b->S.a[0] == (ed^1)); - for (k = max_dist = 0; k < b->b.n; ++k) { - if(b->b.a[k]==st || b->b.a[k]==b->S.a[0]) continue; - max_dist += s->ref->seq[b->b.a[k]>>1].len; - } - max_dist += s->ref->seq[st>>1].len; - max_dist += s->ref->seq[b->S.a[0]>>1].len; - p = rd_hm_bub(s->g, s->ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - return; - } - - for (cuttoff = step; cuttoff < 1.0; cuttoff += step) { - ncut = rd_hm_drop(s->g, s->ref, st, ed^1, cuttoff, b); - p = rd_hm_bub(s->g, s->ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - return; - } - if(!ncut) break; - } - rd_hm_drop(s->g, s->ref, st, ed^1, 1024, b); - p = rd_hm_bub(s->g, s->ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - return; - } -} - -void reduce_hamming_error_adv(ma_ug_t *iug, asg_t *sg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -int max_hang, int min_ovlp, long long gap_fuzz, R_to_U *ru, bubble_type* bub) -{ - double index_time = yak_realtime(); - ma_ug_t *ug = NULL; rd_hamming_t aux_t; memset((&aux_t), 0, sizeof(aux_t)); - ug = (iug)?(iug):(ma_ug_gen_primary(sg, PRIMARY_LABLE)); - uint8_t* vis_flag = NULL; CALLOC(vis_flag, sg->n_seq*2); - uint32_t fix_bub = 0; asg_t *g = ug->g; - uint32_t v, n_vtx = g->n_seq * 2, n_arc, n_arc_0 = sg->n_arc, nv, i; - uint64_t n_pop = 0, max_dist; asg_arc_t *p; - asg_arc_t *av; asg_t *ig = asg_init(); asg64_v sv; kv_init(sv); - buf_t b; memset(&b, 0, sizeof(buf_t)); - b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - uint8_t* bs_flag = NULL; CALLOC(bs_flag, n_vtx); - for (i = 0; i < ug->g->n_seq; i++) ug->g->seq[i].c = 0; - max_dist = get_bub_pop_max_dist_advance(g, &b); - - if(max_dist > 0) { - if(bub) { - for (i = 0; i < bub->f_bub; i++) { - get_bubbles(bub, i, &v, NULL, NULL, NULL, NULL); - fix_bub += gen_switch_phasing(sg, ug, v, sources, coverage_cut, max_hang, min_ovlp, - R_INF.trio_flag, vis_flag, &b, max_dist, 1, ig, &sv); - } - } else { - for (v = 0; v < n_vtx; ++v) { - if(bs_flag[v] != 0) continue; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del) continue; - ///some edges could be deleted - for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs - if (!av[i].del) ++n_arc; - if (n_arc < 2) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, max_dist, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (i = 0; i < b.b.n; i++) { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - bs_flag[b.b.a[i]] = bs_flag[b.b.a[i]^1] = 1; - } - bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 3; - } - } - - //traverse all node with two directions - for (v = 0; v < n_vtx; ++v) { - if(bs_flag[v] !=2) continue; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del) continue; - ///some edges could be deleted - for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs - if (!av[i].del) ++n_arc; - if (n_arc > 1) { - fix_bub += gen_switch_phasing(sg, ug, v, sources, coverage_cut, max_hang, min_ovlp, - R_INF.trio_flag, vis_flag, &b, max_dist, 1, ig, &sv); - } - } - } - } - free(bs_flag); if(!iug) ma_ug_destroy(ug); - - if(sv.n > 0) { - ig->n_seq = ig->m_seq = sg->n_seq; - MALLOC(ig->seq, ig->n_seq); - memcpy(ig->seq, sg->seq, (sizeof((*(ig->seq)))*ig->n_seq)); - asg_cleanup(ig); asg_arc_del_trans_aux(ig, sg, vis_flag, gap_fuzz); - aux_t.n_thread = asm_opt.thread_num; CALLOC(aux_t.a, aux_t.n_thread); - REALLOC(b.a, (ig->n_seq<<2)); memset(b.a, 0, sizeof((*(b.a)))*(ig->n_seq<<2)); - for (i = 0; i < aux_t.n_thread; i++) aux_t.a[i].a = b.a; - aux_t.g = ig; aux_t.ref = sg; aux_t.rr = &sv; aux_t.max_dist = max_dist; - // print_debug_gfa(ug, sg, coverage_cut, "debug_hamming", sources, ru); - kt_for(aux_t.n_thread, rd_hamming_symm, &aux_t, aux_t.rr->n);///all ul + ug - for (i = 0; i < aux_t.n_thread; i++) { - free(aux_t.a[i].S.a); free(aux_t.a[i].T.a); - free(aux_t.a[i].b.a); free(aux_t.a[i].e.a); - } - free(aux_t.a); - } - free(sv.a); free(vis_flag); - - for (i = n_pop = 0; i < ig->n_arc; i++) { - if(ig->arc[i].del) continue; - p = asg_arc_pushp(sg); *p = (ig->arc[i]); n_pop++; - } - if(n_pop) { - free(sg->idx); - sg->idx = 0; - sg->is_srt = 0; - asg_cleanup(sg); - asg_symm(sg); - asg_arc_del_trans(sg, gap_fuzz); - } - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); asg_destroy(ig); - fprintf(stderr, "[M::%s::%.3f] # inserted edges: %u, # fixed bubbles: %u\n", - __func__, yak_realtime() - index_time, sg->n_arc - n_arc_0, fix_bub); -} -**/ - -uint64_t rd_hm_bub(asg_t *g, asg_t *ref, uint32_t v0, uint64_t max_dist, buf_t *b) -{ - uint32_t i0, i1, n_pending = 0, is_first = 1, n_tips, tip_end; uint64_t n_pop = 0; - uint32_t v, w, d, nv0, nv1, l, x, i; asg_arc_t *av0, *av1; binfo_t *t; - if (g->seq[v0>>1].del) return 0; // already deleted - nv0 = g?get_real_length(g, v0, NULL):0; - nv1 = ref?get_real_length(ref, v0, NULL):0; - // if((v0 == 4386) && (!ref)) { - // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), nv0::%u, nv1::%u\n", __func__, v0>>1, v0&1, - // nv0, nv1); - // } - if((nv0+nv1)<2) return 0; - // if(v0 >= (ref->n_seq<<1)) { - // fprintf(stderr, "[M::%s] v0::%u, ref->n_seq::%u\n", __func__, v0, ref->n_seq); - // } - b->S.n = b->T.n = b->b.n = b->e.n = 0; - b->a[v0].c = b->a[v0].d = b->a[v0].m = b->a[v0].nc = b->a[v0].np = 0; - ///b->S is the nodes with all incoming edges visited - kv_push(uint32_t, b->S, v0); - n_tips = 0; tip_end = (uint32_t)-1; - - do { - ///v is a node that all incoming edges have been visited - ///d is the distance from v0 to v - v = kv_pop(b->S); d = b->a[v].d; - nv0 = 0; av0 = NULL; nv1 = 0; av1 = NULL; i0 = i1 = 0; - if(g) { - nv0 = asg_arc_n(g, v); av0 = asg_arc_a(g, v); - } - if(ref) { - nv1 = asg_arc_n(ref, v); av1 = asg_arc_a(ref, v); - } - // if((v0 == 4386) && (!ref)) { - // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), v>>1::%u(v&1::%u)\n", __func__, v0>>1, v0&1, v>>1, v&1); - // } - ///all out-edges of v - for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors - if (av0[i0].del) continue; - w = av0[i0].v; l = (uint32_t)av0[i0].ul; t = &b->a[w]; - // if((v0 == 4386) && (!ref)) { - // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), w>>1::%u(w&1::%u)\n", - // __func__, v0>>1, v0&1, w>>1, w&1); - // } - if ((w>>1) == (v0>>1)) goto pop_rd_hm_bub; - if(is_first) l = 0; - if (d + l > max_dist) break; // too far - ///unvisited node - if (t->s == 0) { // this vertex has never been visited - kv_push(uint32_t, b->b, w); // save it for revert - t->p = v, t->s = 1, t->d = d + l; - t->r = (g?get_real_length(g, w^1, NULL):0)+(ref?get_real_length(ref, w^1, NULL):0); - ++n_pending; - } else { // visited before - ///the shortest path - if (d + l < t->d) t->d = d + l; // update dist - } - // if((v0 == 4386) && (!ref) && ((w>>1) == 2597)) { - // fprintf(stderr, "[M::%s] w>>1::%u(w&1::%u), t->r::%u\n", - // __func__, w>>1, w&1, t->r); - // } - //if all incoming edges of w have visited - //push it to b->S - if (--(t->r) == 0) { - x = (g?get_real_length(g, w, NULL):0)+(ref?get_real_length(ref, w, NULL):0); - // if((v0 == 4386) && (!ref) && ((w>>1) == 2597)) { - // fprintf(stderr, "[M::%s] w>>1::%u(w&1::%u), t->r::%u, x::%u, b->S.n::%u\n", - // __func__, w>>1, w&1, t->r, x, (uint32_t)b->S.n); - // } - if(x > 0) { - // if((v0 == 4386) && (!ref)) { - // fprintf(stderr, "+[M::%s] v0>>1::%u(v0&1::%u), push_w>>1::%u(w&1::%u)\n", - // __func__, v0>>1, v0&1, w>>1, w&1); - // uint32_t m; - // for (m = 0; m < b->S.n; m++) { - // fprintf(stderr, "+[M::%s] m>>1::%u(m&1::%u)\n", __func__, b->S.a[m]>>1, b->S.a[m]&1); - // } - // } - kv_push(uint32_t, b->S, w); - } else { - ///at most one tip - if(n_tips != 0) goto pop_rd_hm_bub; - n_tips++; tip_end = w; - } - --n_pending; - } - } - if (i0 >= nv0) { - for (i1 = 0; i1 < nv1; ++i1) { // loop through v's neighbors - if (av1[i1].del) continue; - w = av1[i1].v; l = (uint32_t)av1[i1].ul; t = &b->a[w]; - if ((w>>1) == (v0>>1)) goto pop_rd_hm_bub; - if(is_first) l = 0; - if (d + l > max_dist) break; // too far - ///unvisited node - if (t->s == 0) { // this vertex has never been visited - kv_push(uint32_t, b->b, w); // save it for revert - t->p = v, t->s = 1, t->d = d + l; - t->r = (g?get_real_length(g, w^1, NULL):0)+(ref?get_real_length(ref, w^1, NULL):0); - ++n_pending; - } else { // visited before - ///the shortest path - if (d + l < t->d) t->d = d + l; // update dist - } - - //if all incoming edges of w have visited - //push it to b->S - if (--(t->r) == 0) { - x = (g?get_real_length(g, w, NULL):0)+(ref?get_real_length(ref, w, NULL):0); - if(x > 0) { - // if((v0 == 4386) && (!ref)) { - // fprintf(stderr, "-[M::%s] v0>>1::%u(v0&1::%u), push_w>>1::%u(w&1::%u)\n", - // __func__, v0>>1, v0&1, w>>1, w&1); - // } - kv_push(uint32_t, b->S, w); - } else { - ///at most one tip - if(n_tips != 0) goto pop_rd_hm_bub; - n_tips++; tip_end = w; - } - --n_pending; - } - } - } - - is_first = 0; - //if found a tip - if(n_tips == 1) { - if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) { - // if((v0 == 4386) && (!ref)) { - // fprintf(stderr, ">[M::%s] v0>>1::%u(v0&1::%u), push_w>>1::%u(w&1::%u)\n", - // __func__, v0>>1, v0&1, tip_end>>1, tip_end&1); - // } - kv_push(uint32_t, b->S, tip_end); - break; - } else { - goto pop_rd_hm_bub; - } - } - // if((v0 == 4386) && (!ref)) { - // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), b->S.n::%u, n_pending::%u\n", - // __func__, v0>>1, v0&1, (uint32_t)b->S.n, n_pending); - // } - ///if i < nv, that means (d + l > max_dist) - if (i0 < nv0 || i1 < nv1 || b->S.n == 0) goto pop_rd_hm_bub; - } while (b->S.n > 1 || n_pending); - n_pop = 1; - pop_rd_hm_bub: - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - t = &b->a[b->b.a[i]]; - t->s = t->c = t->d = t->m = t->nc = t->np = 0; - } - return n_pop; -} - -uint64_t rd_hm_drop0(asg_t *g, asg_t *ref, uint32_t v, double cutoff, uint32_t drop_inexact) -{ - uint32_t nv0, nv1, mol = 0, i0, i1, ncut = 0; asg_arc_t *av0, *av1; - nv0 = asg_arc_n(g, v); av0 = asg_arc_a(g, v); - nv1 = asg_arc_n(ref, v); av1 = asg_arc_a(ref, v); - if(drop_inexact) { - for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors - if (av0[i0].del) continue; - if (av0[i0].el) continue; - av0[i0].del = 1; asg_arc_del(g, av0[i0].v^1, (av0[i0].ul>>32)^1, 1); - ncut++; - } - } else if(cutoff < 1) { - for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors - if (av0[i0].del) continue; - if(mol < av0[i0].ol) mol = av0[i0].ol; - } - for (i1 = 0; i1 < nv1; ++i1) { // loop through v's neighbors - if (av1[i1].del) continue; - if(mol < av1[i1].ol) mol = av1[i1].ol; - } - if(mol > 0) { - for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors - if (av0[i0].del) continue; - if(av0[i0].ol < (mol*cutoff)) { - av0[i0].del = 1; asg_arc_del(g, av0[i0].v^1, (av0[i0].ul>>32)^1, 1); - ncut++; - } - } - } - } else { - for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors - if (av0[i0].del) continue; - av0[i0].del = 1; asg_arc_del(g, av0[i0].v^1, (av0[i0].ul>>32)^1, 1); - ncut++; - } - } - return ncut; -} - -uint64_t rd_hm_drop(asg_t *g, asg_t *ref, uint32_t v0, uint32_t v1, double cutoff, uint32_t drop_inexact, buf_t *b) -{ - uint32_t i1, ncut = 0; - uint32_t v, w, nv1, i; asg_arc_t *av1; - if (g->seq[v0>>1].del) return 0; // already deleted - ///b->S is the nodes with all incoming edges visited - b->S.n = 0; - kv_push(uint32_t, b->S, v0); - while(b->S.n) { - v = kv_pop(b->S); - if(b->a[v].s) continue; - b->a[v].s = 1; - kv_push(uint32_t, b->b, v); // save it for revert - nv1 = asg_arc_n(ref, v); av1 = asg_arc_a(ref, v); - for (i1 = 0; i1 < nv1; ++i1) { // loop through v's neighbors - if (av1[i1].del) continue; - w = av1[i1].v; - if(b->a[w].s || w == v1) continue; - kv_push(uint32_t, b->S, w); - } - } - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - v = b->b.a[i]; b->a[b->b.a[i]].s = 0; - if(v == v0 || v == v1) continue; - ncut += rd_hm_drop0(g, ref, v, cutoff, drop_inexact); - ncut += rd_hm_drop0(g, ref, v^1, cutoff, drop_inexact); - } - ncut += rd_hm_drop0(g, ref, v0, cutoff, drop_inexact); - ncut += rd_hm_drop0(g, ref, v1^1, cutoff, drop_inexact); - return ncut; -} - -void rd_hamming_symm(void *data, long i, int tid) // callback for kt_for() -{ - rd_hamming_t *s = (rd_hamming_t *)data; buf_t *b = &(s->a[tid]); - uint32_t st = s->rr->a[i]>>32, ed = (uint32_t)(s->rr->a[i]), p, k, ncut; - double step = 0.2, cuttoff; uint64_t max_dist = s->max_dist; - p = rd_hm_bub(s->g, s->ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - return; - } - ///recalculate max_dist - p = rd_hm_bub(s->ref, NULL, st, max_dist, b); - // if(!p) { - // fprintf(stderr, "[M::%s] st>>1::%u(st&1::%u), ed>>1::%u(ed&1::%u), max_dist::%lu\n", - // __func__, st>>1, st&1, ed>>1, ed&1, max_dist); - // } - assert(p); assert(b->S.a[0] == (ed^1)); - for (k = max_dist = 0; k < b->b.n; ++k) { - if(b->b.a[k]==st || b->b.a[k]==b->S.a[0]) continue; - max_dist += s->ref->seq[b->b.a[k]>>1].len; - } - max_dist += s->ref->seq[st>>1].len; - max_dist += s->ref->seq[b->S.a[0]>>1].len; - p = rd_hm_bub(s->g, s->ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - return; - } - - ///drop inexact edges first - cuttoff = -1; - ncut = rd_hm_drop(s->g, s->ref, st, ed^1, cuttoff, 1, b); - p = rd_hm_bub(s->g, s->ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - return; - } - - for (cuttoff = step; cuttoff < 1.0; cuttoff += step) { - ncut = rd_hm_drop(s->g, s->ref, st, ed^1, cuttoff, 0, b); - p = rd_hm_bub(s->g, s->ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - return; - } - if(!ncut) break; - } - rd_hm_drop(s->g, s->ref, st, ed^1, 1024, 0, b); - p = rd_hm_bub(s->g, s->ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - return; - } -} - -void rd_hamming_symm_simple(rd_hamming_t *s, uint32_t st, uint32_t ed) // callback for kt_for() -{ - buf_t *b = &(s->a[0]); double step = 0.2, cuttoff; uint64_t max_dist = s->max_dist; - // uint32_t st = s->rr->a[i]>>32, ed = (uint32_t)(s->rr->a[i]); - uint32_t p, k, ncut; - p = rd_hm_bub(s->g, s->ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - return; - } - ///recalculate max_dist - p = rd_hm_bub(s->ref, NULL, st, max_dist, b); - // if(!p) { - // fprintf(stderr, "[M::%s] st>>1::%u(st&1::%u), ed>>1::%u(ed&1::%u), max_dist::%lu\n", - // __func__, st>>1, st&1, ed>>1, ed&1, max_dist); - // } - assert(p); assert(b->S.a[0] == (ed^1)); - for (k = max_dist = 0; k < b->b.n; ++k) { - if(b->b.a[k]==st || b->b.a[k]==b->S.a[0]) continue; - max_dist += s->ref->seq[b->b.a[k]>>1].len; - } - max_dist += s->ref->seq[st>>1].len; - max_dist += s->ref->seq[b->S.a[0]>>1].len; - p = rd_hm_bub(s->g, s->ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - return; - } - - for (cuttoff = step; cuttoff < 1.0; cuttoff += step) { - ncut = rd_hm_drop(s->g, s->ref, st, ed^1, cuttoff, 0, b); - p = rd_hm_bub(s->g, s->ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - return; - } - if(!ncut) break; - } - rd_hm_drop(s->g, s->ref, st, ed^1, 1024, 0, b); - p = rd_hm_bub(s->g, s->ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - return; - } -} - - -uint32_t rd_hamming_symm_simple0(buf_t *b, asg_t *ref, asg_t *g, uint32_t st, uint32_t ed, uint64_t max_dist, uint64_t *r_max_dist) // callback for kt_for() -{ - double step = 0.2, cuttoff; - uint32_t p, k, ncut; - p = rd_hm_bub(g, ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - if(r_max_dist) (*r_max_dist) = max_dist; - return 1; - } - ///recalculate max_dist - p = rd_hm_bub(ref, NULL, st, max_dist, b); - // if(!p) { - // fprintf(stderr, "[M::%s] st>>1::%u(st&1::%u), ed>>1::%u(ed&1::%u), max_dist::%lu\n", - // __func__, st>>1, st&1, ed>>1, ed&1, max_dist); - // } - assert(p); assert(b->S.a[0] == (ed^1)); - for (k = max_dist = 0; k < b->b.n; ++k) { - if(b->b.a[k]==st || b->b.a[k]==b->S.a[0]) continue; - max_dist += ref->seq[b->b.a[k]>>1].len; - } - max_dist += ref->seq[st>>1].len; - max_dist += ref->seq[b->S.a[0]>>1].len; - p = rd_hm_bub(g, ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - if(r_max_dist) (*r_max_dist) = max_dist; - return 1; - } - - ///drop inexact edges first - cuttoff = -1; - ncut = rd_hm_drop(g, ref, st, ed^1, cuttoff, 1, b); - p = rd_hm_bub(g, ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - if(r_max_dist) (*r_max_dist) = max_dist; - return 1; - } - - for (cuttoff = step; cuttoff < 1.0; cuttoff += step) { - ncut = rd_hm_drop(g, ref, st, ed^1, cuttoff, 0, b); - p = rd_hm_bub(g, ref, st, max_dist, b); - if(p) { - assert(b->S.a[0] == (ed^1)); - if(r_max_dist) (*r_max_dist) = max_dist; - return 1; - } - if(!ncut) break; - } - - rd_hm_drop(g, ref, st, ed^1, 1024, 0, b); - p = rd_hm_bub(g, ref, st, max_dist, b); - assert(p); assert(b->S.a[0] == (ed^1)); - if(r_max_dist) (*r_max_dist) = max_dist; - return 0; -} - -void reduce_hamming_error_adv(ma_ug_t *iug, asg_t *sg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -int max_hang, int min_ovlp, long long gap_fuzz, R_to_U *ru, bubble_type* bub) -{ - double index_time = yak_realtime(); - ma_ug_t *ug = NULL; ug = (iug)?(iug):(ma_ug_gen_primary(sg, PRIMARY_LABLE)); - uint8_t* vis_flag = NULL; CALLOC(vis_flag, sg->n_seq*2); - uint32_t fix_bub = 0; asg_t *g = ug->g; - uint32_t v, n_vtx = g->n_seq * 2, n_arc, n_arc_0 = sg->n_arc, nv, i; - uint64_t n_pop = 0, max_dist; asg_arc_t *p; - asg_arc_t *av; asg_t *ig = asg_init(); asg64_v sv; kv_init(sv); - buf_t b; memset(&b, 0, sizeof(buf_t)); - b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - uint8_t* bs_flag = NULL; CALLOC(bs_flag, n_vtx); - for (i = 0; i < ug->g->n_seq; i++) ug->g->seq[i].c = 0; - max_dist = get_bub_pop_max_dist_advance(g, &b); - - if(max_dist > 0) { - if(bub) { - for (i = 0; i < bub->f_bub; i++) { - get_bubbles(bub, i, &v, NULL, NULL, NULL, NULL); - fix_bub += gen_switch_phasing(sg, ug, v, sources, coverage_cut, max_hang, min_ovlp, - R_INF.trio_flag, vis_flag, &b, max_dist, 1, ig, &sv); - } - } else { - for (v = 0; v < n_vtx; ++v) { - if(bs_flag[v] != 0) continue; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del) continue; - ///some edges could be deleted - for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs - if (!av[i].del) ++n_arc; - if (n_arc < 2) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, max_dist, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (i = 0; i < b.b.n; i++) { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - bs_flag[b.b.a[i]] = bs_flag[b.b.a[i]^1] = 1; - } - bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 3; - } - } - - //traverse all node with two directions - for (v = 0; v < n_vtx; ++v) { - if(bs_flag[v] !=2) continue; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del) continue; - ///some edges could be deleted - for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs - if (!av[i].del) ++n_arc; - if (n_arc > 1) { - fix_bub += gen_switch_phasing(sg, ug, v, sources, coverage_cut, max_hang, min_ovlp, - R_INF.trio_flag, vis_flag, &b, max_dist, 1, ig, &sv); - } - } - } - } - free(bs_flag); if(!iug) ma_ug_destroy(ug); - - if(sv.n > 0) { - ig->n_seq = ig->m_seq = sg->n_seq; - MALLOC(ig->seq, ig->n_seq); - memcpy(ig->seq, sg->seq, (sizeof((*(ig->seq)))*ig->n_seq)); - asg_cleanup(ig); asg_arc_del_trans_aux(ig, sg, vis_flag, gap_fuzz); - REALLOC(b.a, (ig->n_seq<<1)); memset(b.a, 0, sizeof((*(b.a)))*(ig->n_seq<<1)); - - for (i = 0; i < sv.n; i++) rd_hamming_symm_simple0(&b, sg, ig, sv.a[i]>>32, (uint32_t)(sv.a[i]), max_dist, NULL); - /** - rd_hamming_t aux_t; memset((&aux_t), 0, sizeof(aux_t)); - aux_t.n_thread = 1; // aux_t.n_thread = asm_opt.thread_num; - CALLOC(aux_t.a, aux_t.n_thread); - for (i = 0; i < aux_t.n_thread; i++) aux_t.a[i].a = b.a; - aux_t.g = ig; aux_t.ref = sg; aux_t.rr = &sv; aux_t.max_dist = max_dist; - // print_debug_gfa(ug, sg, coverage_cut, "debug_hamming", sources, ru); - // kt_for(aux_t.n_thread, rd_hamming_symm, &aux_t, aux_t.rr->n); - for (i = 0; i < aux_t.rr->n; i++) { - rd_hamming_symm_simple(&aux_t, aux_t.rr->a[i]>>32, (uint32_t)(aux_t.rr->a[i])); - } - for (i = 0; i < aux_t.n_thread; i++) { - free(aux_t.a[i].S.a); free(aux_t.a[i].T.a); - free(aux_t.a[i].b.a); free(aux_t.a[i].e.a); - } - free(aux_t.a); - **/ - } - free(sv.a); free(vis_flag); - - for (i = n_pop = 0; i < ig->n_arc; i++) { - if(ig->arc[i].del) continue; - p = asg_arc_pushp(sg); *p = (ig->arc[i]); n_pop++; - } - if(n_pop) { - free(sg->idx); - sg->idx = 0; - sg->is_srt = 0; - asg_cleanup(sg); - asg_symm(sg); - asg_arc_del_trans(sg, gap_fuzz); - } - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); asg_destroy(ig); - fprintf(stderr, "[M::%s::%.3f] # inserted edges: %u, # fixed bubbles: %u\n", - __func__, yak_realtime() - index_time, sg->n_arc - n_arc_0, fix_bub); -} - -void reduce_hamming_error(asg_t *sg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -int max_hang, int min_ovlp, long long gap_fuzz) -{ - double index_time = yak_realtime(); - ma_ug_t *ug = NULL; - ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); - - uint8_t* vis_flag = NULL; CALLOC(vis_flag, sg->n_seq*2); - uint32_t fix_bub = 0; - kvec_t_u32_warp stack; kv_init(stack.a); - kv_asg_arc_t e; kv_init(e); - asg_t *g = ug->g; - uint32_t v, n_vtx = g->n_seq * 2, n_arc, n_arc_0 = sg->n_arc, nv, i; - uint64_t n_pop = 0, max_dist; - asg_arc_t *av = NULL; - buf_t b; - memset(&b, 0, sizeof(buf_t)); - b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - uint8_t* bs_flag = NULL; CALLOC(bs_flag, n_vtx); - for (i = 0; i < ug->g->n_seq; i++) ug->g->seq[i].c = 0; - max_dist = get_bub_pop_max_dist_advance(g, &b); - - - if(max_dist > 0) - { - for (v = 0; v < n_vtx; ++v) - { - if(bs_flag[v] != 0) continue; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - ///some edges could be deleted - for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs - if (!av[i].del) ++n_arc; - if (n_arc < 2) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, max_dist, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) - { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (i = 0; i < b.b.n; i++) - { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - bs_flag[b.b.a[i]] = bs_flag[b.b.a[i]^1] = 1; - } - bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 3; - } - } - - //traverse all node with two directions - for (v = 0; v < n_vtx; ++v) { - if(bs_flag[v] !=2) continue; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - ///some edges could be deleted - for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs - if (!av[i].del) ++n_arc; - if (n_arc > 1) - { - fix_bub += bub_complex_hamming(sg, ug, v, sources, coverage_cut, &stack, - max_hang, min_ovlp, R_INF.trio_flag, vis_flag, &e, &b, max_dist); - } - } - } - - asg_arc_t* p = NULL; - for (i = 0; i < e.n; i++) - { - p = asg_arc_pushp(sg); - *p = e.a[i]; - } - if(e.n != 0) - { - free(sg->idx); - sg->idx = 0; - sg->is_srt = 0; - asg_cleanup(sg); - asg_symm(sg); - asg_arc_del_trans(sg, gap_fuzz); - } - - free(vis_flag); - kv_destroy(stack.a); - kv_destroy(e); - - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - if (n_pop) asg_cleanup(g); - free(bs_flag); - ma_ug_destroy(ug); - - fprintf(stderr, "[M::%s::%.3f] # inserted edges: %u, # fixed bubbles: %u\n", - __func__, yak_realtime() - index_time, sg->n_arc - n_arc_0, fix_bub); - -} - - -uint64_t asg_bub_pop1_label(asg_t *g, uint32_t v0, uint64_t max_dist, buf_s_t *b) -{ - uint32_t i, n_pending = 0, /**is_first = 1,**/ n_tips, tip_end; - uint64_t n_pop = 0; - if (g->seq[v0>>1].del) return 0; // already deleted - if(get_real_length(g, v0, NULL)<2) return 0; - - ///S saves nodes with all incoming edges visited - b->S.n = b->b.n = b->e.n = 0; - ///for each node, b->a saves all related information - b->a[v0].d = 0; - ///b->S is the nodes with all incoming edges visited - kv_push(uint32_t, b->S, v0); n_tips = 0; tip_end = (uint32_t)-1; - - do { - ///v is a node that all incoming edges have been visited - ///d is the distance from v0 to v - uint32_t v = kv_pop(b->S), d = b->a[v].d; - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - ///why we have this assert? - ///assert(nv > 0); - ///all out-edges of v - for (i = 0; i < nv; ++i) { // loop through v's neighbors - ///if this edge has been deleted - if (av[i].del) continue; - - uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l - binfo_s_t *t = &b->a[w]; - ///that means there is a circle, directly terminate the whole bubble poping - ///if (w == v0) goto pop_reset; - if ((w>>1) == (v0>>1)) goto pop_reset; - /****************************may have bugs********************************/ - ///important when poping at long untig graph - // if(is_first) l = 0; - /****************************may have bugs********************************/ - ///find a too far path? directly terminate the whole bubble poping - if ((uint64_t)d + (uint64_t)l > max_dist) break; // too far - - ///if this node - if (t->s == 0) { // this vertex has never been visited - kv_push(uint32_t, b->b, w); // save it for revert - ///t->p is the parent node of - ///t->s = 1 means w has been visited - ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) - t->p = v, t->s = 1, t->d = d + l; - ///incoming edges of w - ///t->r = count_out(g, w^1); - t->r = get_real_length(g, w^1, NULL); - ++n_pending; - } else { // visited before - ///it is the shortest edge - if (d + l < t->d) t->d = d + l, t->p = v; // update dist - } - ///assert(t->r > 0); - //if all incoming edges of w have visited - //push it to b->S - if (--(t->r) == 0) { - uint32_t x = get_real_length(g, w, NULL); - /****************************may have bugs for bubble********************************/ - if(x > 0) - { - kv_push(uint32_t, b->S, w); - } - else - { - ///at most one tip - if(n_tips != 0) goto pop_reset; - n_tips++; - tip_end = w; - } - /****************************may have bugs for bubble********************************/ - --n_pending; - } - } - // is_first = 0; - //if found a tip - /****************************may have bugs for bubble********************************/ - if(n_tips == 1) - { - if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) - { - kv_push(uint32_t, b->S, tip_end); - break; - } - else - { - goto pop_reset; - } - } - /****************************may have bugs for bubble********************************/ - ///if i < nv, that means (d + l > max_dist) - if (i < nv || b->S.n == 0) goto pop_reset; - } while (b->S.n > 1 || n_pending); - - n_pop = 1; -pop_reset: - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - binfo_s_t *t = &b->a[b->b.a[i]]; - t->s = t->d = 0; - } - return n_pop; -} - -void debug_asg_bub_pop1_primary_trio(asg_t *g, ma_ug_t *utg, uint32_t v0, uint64_t max_dist, buf_t *b, -uint32_t positive_flag, uint32_t negative_flag, uint32_t found) -{ - buf_t b_new; - memset(&b_new, 0, sizeof(buf_t)); - b_new.a = (binfo_t*)calloc(g->n_seq * 2, sizeof(binfo_t)); - uint32_t n_pop = asg_bub_pop1_primary_trio(g, utg, v0, max_dist, &b_new, positive_flag, negative_flag, 0, NULL, NULL, NULL, 0, 0, NULL); - if(n_pop != found) fprintf(stderr, "ERROR\n"); - - free(b_new.a); free(b_new.S.a); free(b_new.T.a); free(b_new.b.a); free(b_new.e.a); -} - -uint64_t asg_bub_pop1_primary_trio(asg_t *g, ma_ug_t *utg, uint32_t v0, uint64_t max_dist, buf_t *b, -uint32_t positive_flag, uint32_t negative_flag, uint32_t is_pop, uint64_t* path_base_len, uint64_t* path_nodes, -hap_cov_t *cov, uint32_t is_update_chain, uint32_t keep_d, utg_trans_t *o) -{ - uint32_t i, n_pending = 0, is_first = 1, cur_m, cur_c, cur_np, cur_nc, to_replace, n_tips, tip_end; - uint64_t n_pop = 0; - long long cur_weight = -1, max_weight = -1; - ///if this node has been deleted - if (g->seq[v0>>1].del || g->seq[v0>>1].c == ALTER_LABLE) return 0; // already deleted - ///if ((uint32_t)g->idx[v0] < 2) return 0; // no bubbles - if(get_real_length(g, v0, NULL)<2) return 0; - ///S saves nodes with all incoming edges visited - b->S.n = b->T.n = b->b.n = b->e.n = 0; - ///for each node, b->a saves all related information - b->a[v0].c = b->a[v0].d = b->a[v0].m = b->a[v0].nc = b->a[v0].np = 0; - ///b->S is the nodes with all incoming edges visited - kv_push(uint32_t, b->S, v0); - n_tips = 0; - tip_end = (uint32_t)-1; - uint32_t non_positive_flag = (uint32_t)-1; - if(positive_flag == FATHER) non_positive_flag = MOTHER; - if(positive_flag == MOTHER) non_positive_flag = FATHER; - - do { - ///v is a node that all incoming edges have been visited - ///d is the distance from v0 to v - uint32_t v = kv_pop(b->S), d = b->a[v].d, c = b->a[v].c, m = b->a[v].m, nc = b->a[v].nc, np = b->a[v].np; - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - ///why we have this assert? - ///assert(nv > 0); - ///all out-edges of v - for (i = 0; i < nv; ++i) { // loop through v's neighbors - /** - p->ul: |____________31__________|__________1___________|______________32_____________| - qn direction of overlap length of this node (not overlap length) - (in the view of query) - p->v : |___________31___________|__________1___________| - tn reverse direction of overlap - (in the view of target) - p->ol: overlap length - **/ - ///if this edge has been deleted - if (av[i].del) continue; - - uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l - binfo_t *t = &b->a[w]; - ///that means there is a circle, directly terminate the whole bubble poping - ///if (w == v0) goto pop_reset; - if ((w>>1) == (v0>>1)) { - goto pop_reset; - } - /****************************may have bugs********************************/ - ///important when poping at long untig graph - if(is_first && keep_d) l = 0; - /****************************may have bugs********************************/ - - - - ///push the edge - ///high 32-bit of g->idx[v] is the start point of v's edges - //so here is the point of this specfic edge - kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); - ///find a too far path? directly terminate the whole bubble poping - if (d + l > max_dist) break; // too far - - ///if this node - if (t->s == 0) { // this vertex has never been visited - kv_push(uint32_t, b->b, w); // save it for revert - ///t->p is the parent node of - ///t->s = 1 means w has been visited - ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) - t->p = v, t->s = 1, t->d = d + l; - /****************************may have bugs********************************/ - cur_c = cur_m = cur_np = 0; cur_nc = 1; - if(utg) - { - cur_c = get_num_trio_flag(utg, w>>1, positive_flag); - cur_m = get_num_trio_flag(utg, w>>1, negative_flag); - cur_np = 0; - if(non_positive_flag != (uint32_t)-1) - { - cur_np = get_num_trio_flag(utg, w>>1, non_positive_flag); - } - cur_nc = utg->u.a[(w>>1)].n; - } - - - t->c = c + cur_c; - t->m = m + cur_m; - t->nc = nc + cur_nc; - t->np = np + cur_np; - /****************************may have bugs********************************/ - ///incoming edges of w - ///t->r = count_out(g, w^1); - t->r = get_real_length(g, w^1, NULL); - ++n_pending; - } else { // visited before - /****************************may have bugs********************************/ - cur_c = cur_m = cur_np = 0; cur_nc = 1; - if(utg) - { - cur_c = get_num_trio_flag(utg, w>>1, positive_flag); - cur_m = get_num_trio_flag(utg, w>>1, negative_flag); - cur_np = 0; - if(non_positive_flag != (uint32_t)-1) - { - cur_np = get_num_trio_flag(utg, w>>1, non_positive_flag); - } - cur_nc = utg->u.a[(w>>1)].n; - } - ///BUG: select the path with less negative_flag, less non_positive_flag, more positive_flag, more distance - ///FIXED: select the path with less (negative_flag+non_positive_flag), more positive_flag, more distance - to_replace = 0; - - /****************************may have bugs********************************/ - cur_weight = (long long)(c + cur_c) - ((long long)(m + cur_m) + (long long)(np + cur_np)); - max_weight = (long long)t->c - ((long long)t->m + (long long)t->np); - if(cur_weight > max_weight) - { - to_replace = 1; - } - else if(cur_weight == max_weight) - { - if(nc + cur_nc > t->nc) - { - to_replace = 1; - } - else if(nc + cur_nc == t->nc) - { - if(d + l > t->d) - { - to_replace = 1; - } - } - } - /****************************may have bugs********************************/ - if(to_replace) - { - t->p = v; - t->m = m + cur_m; - t->c = c + cur_c; - t->nc = nc + cur_nc; - t->np = np + cur_np; - } - ///c is the weight (is very likely the number of node in this edge) of the parent node - ///select the longest edge (longest meams most reads/longest edge) - // if (c + 1 > t->c || (c + 1 == t->c && d + l > t->d)) t->p = v; - // if (c + 1 > t->c) t->c = c + 1; - /****************************may have bugs********************************/ - ///update len(v0->w) - ///node: t->d is not the length from this node's parent - ///it is the shortest edge - if (d + l < t->d) t->d = d + l; // update dist - } - ///assert(t->r > 0); - //if all incoming edges of w have visited - //push it to b->S - if (--(t->r) == 0) { - uint32_t x = get_real_length(g, w, NULL); - /****************************may have bugs for bubble********************************/ - if(x > 0) - { - kv_push(uint32_t, b->S, w); - } - else - { - ///at most one tip - if(n_tips != 0) { - goto pop_reset; - } - n_tips++; - tip_end = w; - } - /****************************may have bugs for bubble********************************/ - --n_pending; - } - } - is_first = 0; - //if found a tip - /****************************may have bugs for bubble********************************/ - if(n_tips == 1) - { - if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) - { - kv_push(uint32_t, b->S, tip_end); - break; - } - else - { - goto pop_reset; - } - } - /****************************may have bugs for bubble********************************/ - ///if i < nv, that means (d + l > max_dist) - if (i < nv || b->S.n == 0) { - goto pop_reset; - } - } while (b->S.n > 1 || n_pending); - - - /****************************may have bugs********************************/ - ///if(keep_d != 0) debug_asg_bub_pop1_primary_trio(g, utg, v0, max_dist, b, positive_flag, negative_flag, 1); - /****************************may have bugs********************************/ - if(cov && utg) asg_bub_backtrack_primary_cov(utg, v0, b, cov, is_update_chain); - if(o && utg) asg_bub_collect_ovlp(utg, v0, b, o); - if(is_pop) asg_bub_backtrack_primary(g, v0, b); - if(path_base_len || path_nodes) asg_bub_backtrack_primary_length(g, utg, v0, b, path_base_len, path_nodes); - - n_pop = 1; -pop_reset: - - /****************************may have bugs********************************/ - ///if(!n_pop && keep_d != 0) debug_asg_bub_pop1_primary_trio(g, utg, v0, max_dist, b, positive_flag, negative_flag, 0); - /****************************may have bugs********************************/ - - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - binfo_t *t = &b->a[b->b.a[i]]; - t->s = t->c = t->d = t->m = t->nc = t->np = 0; - } - return n_pop; -} - -uint64_t dfs_subgraph(asg_t *g, buf_t *b, uint32_t id, uint32_t *p_bub) -{ - uint64_t len = 0; - uint32_t cur, nv, v, w, i, kv_0, kv_1, flag_0 = 0, flag_1 = 0; - asg_arc_t *av = NULL; - (*p_bub) = 0; - if(b->a[id].s) return 0; - b->S.n = 0; - kv_push(uint32_t, b->S, id); - - while (b->S.n > 0) - { - b->S.n--; - cur = b->S.a[b->S.n]; - if(b->a[cur].s) continue; - b->a[cur].s = 1; - len += g->seq[cur].len; - - v = cur<<1; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - for (i = kv_0 = 0; i < nv; i++) - { - w = av[i].v>>1; - if(av[i].del) continue; - kv_0++; - if(b->a[w].s) continue; - kv_push(uint32_t, b->S, w); - } - - v = (cur<<1)+1; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - for (i = kv_1 = 0; i < nv; i++) - { - w = av[i].v>>1; - if(av[i].del) continue; - kv_1++; - if(b->a[w].s) continue; - kv_push(uint32_t, b->S, w); - } - - if(kv_0 > 0 && kv_1 > 0) flag_0++; - if(kv_0 > 1) flag_1++; - if(kv_1 > 1) flag_1++; - } - - if(flag_0 > 0 && flag_1 > 1) (*p_bub) = 1; - return len; -} -uint64_t get_bub_pop_max_dist(asg_t *g, buf_t *b) -{ - uint32_t n_vtx = g->n_seq, i, p_bub; - uint64_t cLen = 0, mLen = 0, tLen = 0; - - - for (i = 0; i < n_vtx; ++i) - { - if(b->a[i].s) continue; - cLen = dfs_subgraph(g, b, i, &p_bub); - tLen += cLen; - if(p_bub == 0) continue;///no bubble - if(cLen > mLen) mLen = cLen; - } - - for (i = 0; i < n_vtx; ++i) - { - ///if(b->a[i].s == 0) fprintf(stderr, "ERROR\n"); - b->a[i].s = 0; - ///debug_tLen += g->seq[i].len; - } - ///if(debug_tLen != tLen) fprintf(stderr, "ERROR\n"); - - ///fprintf(stderr, "mLen: %lu, tLen: %lu\n", mLen, tLen); - b->S.n = 0; - return mLen; -} - -uint64_t dfs_subgraph_advance(asg_t *g, buf_t *b, uint32_t x, uint32_t *p_bub) -{ - uint64_t len = 0; - uint32_t c_v, e_v, nv, convex, v, i, kv_0, kv_1, flag_0 = 0, flag_1 = 0, op; - asg_arc_t *av = NULL; - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen, uLen; - (*p_bub) = 0; - if(b->a[x>>1].s || g->seq[x>>1].del) return 0; - b->S.n = 0; - kv_push(uint32_t, b->S, x); - - while (b->S.n > 0) - { - b->S.n--; - c_v = b->S.a[b->S.n]; - if(b->a[c_v>>1].s) continue; - - b->b.n = 0; - op = get_unitig(g, NULL, c_v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, - &max_stop_baseLen, 1, b); - uLen = baseLen; - for(i = 0; i < b->b.n; i++) - { - ///if(b->a[b->b.a[i]>>1].s == 1) fprintf(stderr, "ERROR 3\n"); - b->a[b->b.a[i]>>1].s = 1; - } - - if(op == LOOP) return 0; - - - e_v = convex^1; - b->b.n = 0; - op = get_unitig(g, NULL, e_v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, - &max_stop_baseLen, 1, b); - uLen = MAX(uLen, baseLen); - - len += uLen; - - - v = c_v^1; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - for (i = kv_0 = 0; i < nv; i++) - { - if(av[i].del) continue; - kv_0++; - if(b->a[av[i].v>>1].s) continue; - kv_push(uint32_t, b->S, av[i].v); - } - - v = e_v^1; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - for (i = kv_1 = 0; i < nv; i++) - { - if(av[i].del) continue; - kv_1++; - if(b->a[av[i].v>>1].s) continue; - kv_push(uint32_t, b->S, av[i].v); - } - - if(kv_0 > 0 && kv_1 > 0) flag_0++; - if(kv_0 > 1) flag_1++; - if(kv_1 > 1) flag_1++; - } - - if(flag_0 > 0 && flag_1 > 1) (*p_bub) = 1; - return len; -} - -uint64_t get_bub_pop_max_dist_advance(asg_t *g, buf_t *b) -{ - asg_arc_t *av = NULL; - uint32_t n_vtx = g->n_seq<<1, k, v, w, kv, nv, p_bub; - uint64_t cLen = 0, mLen = 0; - - - for (v = 0; v < n_vtx; ++v) - { - if(b->a[v>>1].s) continue; - if(g->seq[v>>1].del) continue; - - - av = asg_arc_a(g, v); - nv = asg_arc_n(g, v); - for (k = kv = 0; k < nv; k++) - { - if(av[k].del) continue; - w = av[k].v^1; - kv++; - } - if(kv == 1 && get_real_length(g, w, NULL) == 1) continue; - - cLen = dfs_subgraph_advance(g, b, v^1, &p_bub); - if(p_bub == 0) continue;///no bubble - if(cLen > mLen) mLen = cLen; - } - - for (k = 0; k < g->n_seq; ++k) - { - // if(b->a[k].s == 0 && !g->seq[k].del) - // { - // uint32_t convex; - // long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - // if(get_unitig(g, NULL, k<<1, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, - // &max_stop_baseLen, 1, NULL) != LOOP) - // { - // fprintf(stderr, "ERROR 1\n"); - // } - // } - b->a[k].s = 0; - } - - // for (; k < n_vtx; ++k) - // { - // if(b->a[k].s == 1) fprintf(stderr, "ERROR 2\n"); - // } - - ///fprintf(stderr, "mLen: %lu, tLen: %lu\n", mLen, tLen); - b->S.n = b->b.n = 0; - return mLen; -} - -inline uint32_t get_unitig_s(asg_t *sg, ma_ug_t *ug, uint32_t begNode, uint32_t* endNode, -long long* nodeLen, long long* baseLen, long long* max_stop_nodeLen, long long* max_stop_baseLen, -uint32_t stops_threshold, buf_s_t* b) -{ - ma_utg_v* u = NULL; - uint32_t v = begNode, w, k; - uint32_t kv, return_flag, n_stops = 0; - long long pre_baseLen = 0, pre_nodeLen = 0; - long long cur_baseLen = 0, cur_nodeLen = 0; - (*max_stop_nodeLen) = (*max_stop_baseLen) = (*nodeLen) = (*baseLen) = 0; - (*endNode) = (uint32_t)-1; - if(ug!=NULL) u = &(ug->u); - - while (1) - { - kv = get_real_length(sg, v, NULL); - (*endNode) = v; - if(u == NULL) - { - (*nodeLen)++; - } - else - { - (*nodeLen) += EvaluateLen((*u), v>>1); - } - if(b) kv_push(uint32_t, b->b, v); - ///means reach the end of a unitig - if(kv!=1) (*baseLen) += sg->seq[v>>1].len; - if(kv==0) - { - return_flag = END_TIPS; - break; - ///return END_TIPS; - } - if(kv>1) - { - return_flag = MUL_OUTPUT; - break; - ///return MUL_OUTPUT; - } - ///kv must be 1 here - kv = get_real_length(sg, v, &w); - ///means reach the end of a unitig - if(get_real_length(sg, w^1, NULL)!=1) - { - - n_stops++; - if(n_stops >= stops_threshold) - { - (*baseLen) += sg->seq[v>>1].len; - return_flag = MUL_INPUT; - break; - ///return MUL_INPUT; - } - else - { - for (k = 0; k < asg_arc_n(sg, v); k++) - { - if(asg_arc_a(sg, v)[k].del) continue; - ///here is just one undeleted edge - (*baseLen) += asg_arc_len(asg_arc_a(sg, v)[k]); - break; - } - } - - cur_baseLen = (*baseLen) - pre_baseLen; - pre_baseLen = (*baseLen); - if(cur_baseLen > (*max_stop_baseLen)) - { - (*max_stop_baseLen) = cur_baseLen; - } - - - cur_nodeLen = (*nodeLen) - pre_nodeLen; - pre_nodeLen = (*nodeLen); - if(cur_nodeLen > (*max_stop_nodeLen)) - { - (*max_stop_nodeLen) = cur_nodeLen; - } - } - else - { - for (k = 0; k < asg_arc_n(sg, v); k++) - { - if(asg_arc_a(sg, v)[k].del) continue; - ///here is just one undeleted edge - (*baseLen) += asg_arc_len(asg_arc_a(sg, v)[k]); - break; - } - } - - - v = w; - if(v == begNode) - { - return_flag = LOOP; - break; - ///return LOOP; - } - } - - - - - cur_baseLen = (*baseLen) - pre_baseLen; - pre_baseLen = (*baseLen); - if(cur_baseLen > (*max_stop_baseLen)) - { - (*max_stop_baseLen) = cur_baseLen; - } - - - cur_nodeLen = (*nodeLen) - pre_nodeLen; - pre_nodeLen = (*nodeLen); - if(cur_nodeLen > (*max_stop_nodeLen)) - { - (*max_stop_nodeLen) = cur_nodeLen; - } - - return return_flag; -} - -uint64_t dfs_subgraph_s_advance(asg_t *g, buf_s_t *b, uint32_t x, uint32_t *p_bub) -{ - uint64_t len = 0; - uint32_t c_v, e_v, nv, convex, v, i, kv_0, kv_1, flag_0 = 0, flag_1 = 0, op; - asg_arc_t *av = NULL; - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen, uLen; - (*p_bub) = 0; - if(b->a[x>>1].s || g->seq[x>>1].del) return 0; - b->S.n = 0; - kv_push(uint32_t, b->S, x); - - while (b->S.n > 0) - { - b->S.n--; - c_v = b->S.a[b->S.n]; - if(b->a[c_v>>1].s) continue; - - b->b.n = 0; - op = get_unitig_s(g, NULL, c_v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, - &max_stop_baseLen, 1, b); - - uLen = baseLen; - for(i = 0; i < b->b.n; i++) - { - ///if(b->a[b->b.a[i]>>1].s == 1) fprintf(stderr, "ERROR 3\n"); - b->a[b->b.a[i]>>1].s = 1; - } - - if(op == LOOP) return 0; - - - e_v = convex^1; - b->b.n = 0; - op = get_unitig_s(g, NULL, e_v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, - &max_stop_baseLen, 1, b); - uLen = MAX(uLen, baseLen); - - len += uLen; - - - v = c_v^1; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - for (i = kv_0 = 0; i < nv; i++) - { - if(av[i].del) continue; - kv_0++; - if(b->a[av[i].v>>1].s) continue; - kv_push(uint32_t, b->S, av[i].v); - } - - v = e_v^1; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - for (i = kv_1 = 0; i < nv; i++) - { - if(av[i].del) continue; - kv_1++; - if(b->a[av[i].v>>1].s) continue; - kv_push(uint32_t, b->S, av[i].v); - } - - if(kv_0 > 0 && kv_1 > 0) flag_0++; - if(kv_0 > 1) flag_1++; - if(kv_1 > 1) flag_1++; - } - - if(flag_0 > 0 && flag_1 > 1) (*p_bub) = 1; - return len; -} - -uint64_t get_s_bub_pop_max_dist_advance(asg_t *g, buf_s_t *b) -{ - asg_arc_t *av = NULL; - uint32_t n_vtx = g->n_seq<<1, k, v, w, kv, nv, p_bub; - uint64_t cLen = 0, mLen = 0; - - - for (v = 0; v < n_vtx; ++v) - { - if(b->a[v>>1].s) continue; - if(g->seq[v>>1].del) continue; - - - av = asg_arc_a(g, v); - nv = asg_arc_n(g, v); - for (k = kv = 0; k < nv; k++) - { - if(av[k].del) continue; - w = av[k].v^1; - kv++; - } - if(kv == 1 && get_real_length(g, w, NULL) == 1) continue; - cLen = dfs_subgraph_s_advance(g, b, v^1, &p_bub); - if(p_bub == 0) continue;///no bubble - if(cLen > mLen) mLen = cLen; - } - - for (k = 0; k < g->n_seq; ++k) - { - // if(b->a[k].s == 0 && !g->seq[k].del) - // { - // uint32_t convex; - // long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - // if(get_unitig(g, NULL, k<<1, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, - // &max_stop_baseLen, 1, NULL) != LOOP) - // { - // fprintf(stderr, "ERROR 1\n"); - // } - // } - b->a[k].s = 0; - } - - // for (; k < n_vtx; ++k) - // { - // if(b->a[k].s == 1) fprintf(stderr, "ERROR 2\n"); - // } - - ///fprintf(stderr, "mLen: %lu, tLen: %lu\n", mLen, tLen); - b->S.n = b->b.n = 0; - return mLen; -} - -void append_node_arcs(asg_t *des, asg_t *src, uint8_t *s, uint8_t se, uint32_t v) -{ - asg_arc_t *av, *za; uint32_t an, zn, k, n0, n1; - n0 = n1 = 0; - za = asg_arc_a(src, v); zn = asg_arc_n(src, v); - av = asg_arc_a(des, v); an = asg_arc_n(des, v); - ///set - for (k = 0; k < zn; k++) { - if(za[k].del) continue; - s[za[k].v] |= se; n0++; - } - - for (k = 0; k < an; k++) { - ///s[av[k].v]&se:: in the existing graph - if(s[av[k].v]&se) { - av[k].del = 0; n1++; - asg_arc_del(des, av[k].v^1, (av[k].ul>>32)^1, 0); - } - } - - ///reset - for (k = 0; k < zn; k++) { - if(za[k].del) continue; - if(s[za[k].v]&se) s[za[k].v] -= se; - } - if(!(n0 == n1)) { - fprintf(stderr, "[M::%s] n0::%u, n1::%u\n", __func__, n0, n1); - } - assert(n0 == n1); -} - - -static inline void asg_arc_rest(asg_t *des, asg_t *src, uint32_t v0, uint32_t w0, ma_ug_t *ug, kvec_asg_arc_t_warp *ae, ma_hit_t_alloc* src_e, ma_sub_t *cov, int32_t max_hang, int32_t min_ovlp, int32_t gap_fuzz, uint32_t *n_insert) -{ - uint32_t v, w, i, nv, rv, rw; asg_arc_t *av, *arc, t; - - v = v0; w = w0; - av = asg_arc_a(des, v); nv = asg_arc_n(des, v); - for (i = 0; i < nv; ++i) { - if (av[i].v == w) { - av[i].del = 0; break; - } - } - if(i < nv) { - v = w0^1; w = v0^1; - av = asg_arc_a(des, v); nv = asg_arc_n(des, v); - for (i = 0; i < nv; ++i) { - if (av[i].v == w) { - av[i].del = 0; break; - } - } - assert(i < nv); - return; - } - - ///replace a deleted arc - // fprintf(stderr, "[M::%s] replace\n", __func__); - v = v0; w = w0; - av = asg_arc_a(src, v); nv = asg_arc_n(src, v); - for (i = 0, arc = NULL; i < nv; ++i) { - if (av[i].v == w) { - av[i].del = 0; arc = &(av[i]); break; - } - } - assert(arc); - av = asg_arc_a(des, v); nv = asg_arc_n(des, v); - assert(nv); - for (i = 0; i < nv; ++i) assert(av[i].del); - for (i = 0; i < nv && av[i].ul < arc->ul; ++i); - if(i >= nv) i = nv - 1; av[i] = *arc; - - v = w0^1; w = v0^1; - av = asg_arc_a(src, v); nv = asg_arc_n(src, v); - for (i = 0, arc = NULL; i < nv; ++i) { - if (av[i].v == w) { - av[i].del = 0; arc = &(av[i]); break; - } - } - assert(arc); - av = asg_arc_a(des, v); nv = asg_arc_n(des, v); - assert(nv); - for (i = 0; i < nv; ++i) assert(av[i].del); - for (i = 0; i < nv && av[i].ul < arc->ul; ++i); - if(i >= nv) i = nv - 1; av[i] = *arc; - - - rv = ((v0&1)?(Uc_beg(ug->u.a[v0>>1])^1):(Uc_end(ug->u.a[v0>>1])^1)); - rw = ((w0&1)?(Uc_end(ug->u.a[w0>>1])):(Uc_beg(ug->u.a[w0>>1]))); - assert(get_edge_from_source(src_e, cov, NULL, max_hang, min_ovlp, rv, rw, &t)); - kv_push(asg_arc_t, ae->a, t); - - assert(get_edge_from_source(src_e, cov, NULL, max_hang, min_ovlp, rw^1, rv^1, &t)); - kv_push(asg_arc_t, ae->a, t); - - (*n_insert) += 2; -} - -uint32_t bub_pop_merge(ma_ug_t *raw_ug, ma_ug_t *new_ug, uint32_t v0, uint32_t v1, uint64_t max_dist, buf_t *b, -uint32_t positive_flag, uint32_t negative_flag, hap_cov_t *cov, uint32_t is_update_chain, utg_trans_t *o, kvec_asg_arc_t_warp *ae, -ma_hit_t_alloc* src, ma_sub_t *sub, int32_t max_hang, int32_t min_ovlp, int32_t gap_fuzz, uint32_t *n_insert) -{ - ///do not pop bubble within new_ug; - uint32_t is_pop = asg_bub_pop1_primary_trio(new_ug->g, new_ug, v0, max_dist, b, positive_flag, negative_flag, 0, NULL, NULL, cov, is_update_chain, 1/**0**/, o); - assert(is_pop); assert(b->S.a[0] == v1); - - ///b->S.a[0] is the sink of this bubble - uint32_t i, v, qn, tn, tmp_c, u; asg_arc_t *a; - asg_t *g = raw_ug->g; tmp_c = g->seq[b->S.a[0]>>1].c; - - ///assert(b->S.n == 1); - ///first remove all nodes in this bubble - for (i = 0; i < b->b.n; ++i) g->seq[b->b.a[i]>>1].c = ALTER_LABLE; - - - ///v is the sink of this bubble - v = b->S.a[0]; - ///recover node - do { - u = b->a[v].p; // u->v - /****************************may have hap bugs********************************/ - ////g->seq[v>>1].c = PRIMARY_LABLE; - g->seq[v>>1].c = HAP_LABLE; - /****************************may have hap bugs********************************/ - v = u; - } while (v != v0); - ///especially for unitig graph, don't label beg and sink node of a bubble as HAP_LABLE - ///since in unitig graph, a node may consist of a lot of reads - g->seq[b->S.a[0]>>1].c = tmp_c; - - ///remove all edges (self/reverse for each edge) in this bubble - for (i = 0; i < b->e.n; ++i) { - a = &(new_ug->g->arc[b->e.a[i]]);///note:: new_ug->g here - qn = a->ul>>33; - tn = a->v>>1; - if(g->seq[qn].c == ALTER_LABLE && g->seq[tn].c == ALTER_LABLE) continue; - ///remove this edge self - asg_arc_del(g, a->ul>>32, a->v, 1); - ///remove the reverse direction - asg_arc_del(g, a->v^1, a->ul>>32^1, 1); - } - - ///v is the sink of this bubble - v = b->S.a[0]; - ///recover node - do { - u = b->a[v].p; // u->v - g->seq[v>>1].del = 0; - asg_arc_rest(g, new_ug->g, u, v, raw_ug, ae, src, sub, max_hang, min_ovlp, gap_fuzz, n_insert); - v = u; - } while (v != v0); - return is_pop; -} - -uint64_t renew_phase_bubble(rd_hamming_fly_simp_t *pf, uint64_t v0, buf_t *b, ma_ug_t *ug, uint64_t max_dist, -uint32_t positive_flag, uint32_t negative_flag, hap_cov_t *cov, utg_trans_t *o, uint32_t is_update_chain) -{ - uint64_t v, k, i, v1 = b->S.a[0], is_update, is_pop = 0; ma_ug_t *fg = pf->fg; - uint8_t *s = pf->vs; asg32_v *bc = pf->srt; uint8_t sn = 1, se = 2; uint64_t max_dist0 = max_dist; - bc->n = 0; kv_resize(uint32_t, (*bc), b->b.n); - assert((fg->u.a[v0>>1].len == ug->u.a[v0>>1].len) && (fg->u.a[v0>>1].n == ug->u.a[v0>>1].n)); - assert((fg->u.a[v1>>1].len == ug->u.a[v1>>1].len) && (fg->u.a[v1>>1].n == ug->u.a[v1>>1].n)); - - - // if(((v0>>1) == 7536) && ((v1>>1) == 99223)) { - // print_simple_dbg_gfa(ug->g, "ug0"); - // } - - ///b->S.a[0] is the sink of this bubble - for (i = 0; i < b->b.n; i++) { - v = b->b.a[i]; - if((v == v0) || (v == v1)) continue; - s[v] = sn; - kv_push(uint32_t, *bc, v); - assert((fg->u.a[v>>1].len == ug->u.a[v>>1].len) && (fg->u.a[v>>1].n == ug->u.a[v>>1].n)); - } - - asg_arc_t *av, *za, *ra; uint32_t an, zn, rn, ri; - v = v0; - av = asg_arc_a(fg->g, v); - an = asg_arc_n(fg->g, v); - for (k = 0; k < an; k++) { - av[k].del = 1; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 1); - } - fg->g->seq[v>>1].c = ug->g->seq[v>>1].c; - - - v = v1^1; - av = asg_arc_a(fg->g, v); - an = asg_arc_n(fg->g, v); - for (k = 0; k < an; k++) { - av[k].del = 1; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 1); - } - fg->g->seq[v>>1].c = ug->g->seq[v>>1].c; - - - for (i = 0; i < bc->n; i++) { - v = bc->a[i]; - av = asg_arc_a(fg->g, v); an = asg_arc_n(fg->g, v); - for (k = 0; k < an; k++) { - // av[k].del = 1; - av[k].del = 1; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 1); - } - - v ^= 1; - av = asg_arc_a(fg->g, v); an = asg_arc_n(fg->g, v); - for (k = 0; k < an; k++) { - // av[k].del = 1; - av[k].del = 1; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 1); - } - - fg->g->seq[v>>1].c = ug->g->seq[v>>1].c; - } - - - for (i = 0; i < bc->n; i++) { - v = bc->a[i]; - za = asg_arc_a(ug->g, v); zn = asg_arc_n(ug->g, v); - av = asg_arc_a(fg->g, v); an = asg_arc_n(fg->g, v); - - ///set - for (k = 0; k < zn; k++) { - if((za[k].del) || (!s[za[k].v])) continue; - s[za[k].v] |= se; - } - - - for (k = 0; k < an; k++) { - ///s[av[k].v]&se:: in the existing graph - if((!s[av[k].v]) || (s[av[k].v]&se)) continue; ///in the existing graph - // if((av[k].v) == (v>>1)) continue;///looks like a bug - if((av[k].v>>1) == (v>>1)) continue; - av[k].del = 0; - - ra = asg_arc_a(fg->g, (av[k].v^1)); rn = asg_arc_n(fg->g, (av[k].v^1)); - for (ri = 0; ri < rn; ri++) { - if(ra[ri].v == ((av[k].ul>>32)^1)) { - ra[ri].del = 0; break; - } - } - assert(ri < rn); - } - - ///reset - for (k = 0; k < zn; k++) { - if((za[k].del) || (!s[za[k].v])) continue; - if(s[za[k].v]&se) s[za[k].v] -= se; - } - } - - - is_update = rd_hamming_symm_simple0(b, ug->g, fg->g, v0, v1^1, max_dist, &max_dist); - - // if(((v0>>1) == 7536) && ((v1>>1) == 99223)) { - // fprintf(stderr, "v0::utg%.6lul(%c)\tv1::utg%.6lul(%c)\n", (v0>>1) + 1, "+-"[(v0&1)], (v1>>1) + 1, "+-"[(v1&1)]); - // for (i = 0; i < bc->n; i++) fprintf(stderr, "w::utg%.6ul(%c)\n", (bc->a[i]>>1) + 1, "+-"[(bc->a[i]&1)]); - // print_simple_dbg_gfa(ug->g, "ug1"); - // print_simple_dbg_gfa(fg->g, "fg0"); - // } - - // fprintf(stderr, "[M::%s] is_update::%lu\n", __func__, is_update); - if(is_update) { - for (i = 0; i < bc->n; i++) { - append_node_arcs(fg->g, ug->g, s, se, bc->a[i]); - append_node_arcs(fg->g, ug->g, s, se, bc->a[i]^1); - } - append_node_arcs(fg->g, ug->g, s, se, v0); - append_node_arcs(fg->g, ug->g, s, se, v1^1); - is_pop = bub_pop_merge(ug, fg, v0, v1, max_dist, b, positive_flag, negative_flag, cov, is_update_chain, o, pf->ae, pf->src, pf->cov, pf->max_hang, pf->min_ovlp, pf->gap_fuzz, &(pf->n_insert)); - } else { - max_dist = max_dist0; - is_pop = asg_bub_pop1_primary_trio(ug->g, ug, v0, max_dist, b, positive_flag, negative_flag, 1, NULL, NULL, cov, is_update_chain, 0, o); - } - - - - for (i = 0; i < bc->n; i++) s[bc->a[i]] = 0; - ///reset - v = v0; - av = asg_arc_a(fg->g, v); - an = asg_arc_n(fg->g, v); - for (k = 0; k < an; k++) { - av[k].del = 0; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 0); - } - fg->g->seq[v>>1].c = PRIMARY_LABLE; - - - v = v1^1; - av = asg_arc_a(fg->g, v); - an = asg_arc_n(fg->g, v); - for (k = 0; k < an; k++) { - av[k].del = 0; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 0); - } - fg->g->seq[v>>1].c = PRIMARY_LABLE; - - - for (i = 0; i < bc->n; i++) { - v = bc->a[i]; - av = asg_arc_a(fg->g, v); - an = asg_arc_n(fg->g, v); - for (k = 0; k < an; k++) { - av[k].del = 0; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 0); - } - - v ^= 1; - av = asg_arc_a(fg->g, v); - an = asg_arc_n(fg->g, v); - for (k = 0; k < an; k++) { - av[k].del = 0; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 0); - } - - fg->g->seq[v>>1].c = PRIMARY_LABLE; - } - return is_pop; -} - -uint64_t refine_bubble_popping(ma_ug_t *ug, buf_t *b, uint32_t v0, uint64_t max_dist, uint32_t positive_flag, uint32_t negative_flag, hap_cov_t *cov, utg_trans_t *o, uint32_t is_update_chain, rd_hamming_fly_simp_t *pf) -{ - // fprintf(stderr, "[M::%s]\n", __func__); - if(!asg_bub_pop1_primary_trio(ug->g, ug, v0, max_dist, b, positive_flag, negative_flag, 0, NULL, NULL, NULL, 0, 0, NULL)) return 0; - // if(((v0>>1) == 7536) && ((b->S.a[0]>>1) == 99223)) { - // fprintf(stderr, "[M::%s] uga_v::%u\n", __func__, v0); dbg_asys_gfa(ug->g); - // print_simple_dbg_gfa(ug->g, "uga"); - // } - uint32_t non_positive_flag = (uint32_t)-1, v, u, k, rId, pn, npn; - if(positive_flag == FATHER) non_positive_flag = MOTHER; - if(positive_flag == MOTHER) non_positive_flag = FATHER; - ma_utg_t* p = NULL; - ///b->S.a[0] is the sink of this bubble - ///v is the sink of this bubble - v = b->S.a[0]; pn = npn = 0; - ///scan node - do { - u = b->a[v].p; // u->v - if(v != b->S.a[0]) { - p = &(ug->u.a[v>>1]); - for (k = 0; k < p->n; k++) { - rId = p->a[k]>>33; - if(R_INF.trio_flag[rId] == positive_flag) pn++; - if(R_INF.trio_flag[rId] == non_positive_flag) npn++; - } - } - v = u; - } while (v != v0); - // fprintf(stderr, "[M::%s] pn::%u, npn::%u\n", __func__, pn, npn); - ///debug - if((npn <= 0) || ((npn <= ((npn+pn)*0.05)) && (npn <= 64))) {///phasing is ok - return asg_bub_pop1_primary_trio(ug->g, ug, v0, max_dist, b, positive_flag, negative_flag, 1, NULL, NULL, cov, is_update_chain, 0, o); - } - return renew_phase_bubble(pf, v0, b, ug, max_dist, positive_flag, negative_flag, cov, o, is_update_chain); -} - -// pop bubbles -int asg_pop_bubble_primary_trio(ma_ug_t *ug, uint64_t* i_max_dist, uint32_t positive_flag, uint32_t negative_flag, hap_cov_t *cov, utg_trans_t *o, uint32_t is_update_chain, rd_hamming_fly_simp_t *p) -{ - asg_t *g = ug->g; uint64_t n_pop = 0, max_dist; - uint32_t v, n_vtx = g->n_seq * 2, n_arc, nv, i; - asg_arc_t *av = NULL; - buf_t b; - if (!g->is_symm) asg_symm(g); - memset(&b, 0, sizeof(buf_t)); - ///set information for each node - b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - if(i_max_dist) max_dist = (*i_max_dist); - else max_dist = get_bub_pop_max_dist_advance(g, &b); - uint8_t* bs_flag = NULL; CALLOC(bs_flag, n_vtx); - - if(max_dist > 0) - { - for (v = 0; v < n_vtx; ++v) - { - if(bs_flag[v] != 0) continue; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - ///some edges could be deleted - for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs - if (!av[i].del) ++n_arc; - if (n_arc < 2) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, max_dist, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) - { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (i = 0; i < b.b.n; i++) - { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - bs_flag[b.b.a[i]] = bs_flag[b.b.a[i]^1] = 1; - } - bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 3; - } - } - - //traverse all node with two directions - for (v = 0; v < n_vtx; ++v) { - if(bs_flag[v] !=2) continue; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - ///some edges could be deleted - for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs - if (!av[i].del) ++n_arc; - if (n_arc > 1) { - if(p){ - n_pop += refine_bubble_popping(ug, &b, v, max_dist, positive_flag, negative_flag, cov, o, is_update_chain, p); - } else { - n_pop += asg_bub_pop1_primary_trio(ug->g, ug, v, max_dist, &b, positive_flag, negative_flag, 1, NULL, NULL, cov, is_update_chain, 0, o); - } - } - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] popped %lu bubbles\n", __func__, (unsigned long)n_pop); - } - } - - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - if (n_pop) asg_cleanup(g); - free(bs_flag); - return n_pop; -} - - - -int test_triangular_directly(asg_t *g, uint32_t v, -long long min_edge_length, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex) -{ - - uint32_t w; - int todel; - long long NodeLen_first[3]; - long long NodeLen_second[3]; - - asg_arc_t *av = asg_arc_a(g, v); - if(av[0].v == av[1].v) - { - return 0; - } - /**********************test first node************************/ - NodeLen_first[0] = NodeLen_first[1] = NodeLen_first[2] = -1; - if(asg_is_single_edge(g, av[0].v, v>>1) <= 2 && asg_is_single_edge(g, av[1].v, v>>1) <= 2) - { - NodeLen_first[asg_is_single_edge(g, av[0].v, v>>1)] = 0; - NodeLen_first[asg_is_single_edge(g, av[1].v, v>>1)] = 1; - } - ///one node has one out-edge, another node has two out-edges - if(NodeLen_first[1] == -1 || NodeLen_first[2] == -1) - { - return 0; - } - /**********************test first node************************/ - ///if the potiential edge has already been removed - if(av[NodeLen_first[2]].del == 1) - { - return 0; - } - - /**********************test second node************************/ - w = av[NodeLen_first[2]].v^1; - asg_arc_t *aw = asg_arc_a(g, w); - uint32_t nw = asg_arc_n(g, w); - if(nw != 2) - { - fprintf(stderr, "error\n"); - } - NodeLen_second[0] = NodeLen_second[1] = NodeLen_second[2] = -1; - if(asg_is_single_edge(g, aw[0].v, w>>1) <= 2 && asg_is_single_edge(g, aw[1].v, w>>1) <= 2) - { - NodeLen_second[asg_is_single_edge(g, aw[0].v, w>>1)] = 0; - NodeLen_second[asg_is_single_edge(g, aw[1].v, w>>1)] = 1; - } - ///one node has one out-edge, another node has two out-edges - if(NodeLen_second[1] == -1 || NodeLen_second[2] == -1) - { - return 0; - } - - - - todel = 0; - // if(check_if_diploid(av[0].v, av[1].v, g, reverse_sources, min_edge_length) && - // check_if_diploid(aw[0].v, aw[1].v, g, reverse_sources, min_edge_length)) - if(check_if_diploid(av[0].v, av[1].v, g, reverse_sources, min_edge_length, ruIndex) == 1|| - check_if_diploid(aw[0].v, aw[1].v, g, reverse_sources, min_edge_length, ruIndex) == 1) - { - todel = 1; - } - - - - if(todel) - { - ///fprintf(stderr, "v: %u\n", v>>1); - av[NodeLen_first[2]].del = 1; - ///remove the reverse direction - asg_arc_del(g, av[NodeLen_first[2]].v^1, av[NodeLen_first[2]].ul>>32^1, 1); - } - - return todel; -} - - - -int asg_arc_del_triangular_directly(asg_t *g, long long min_edge_length, -ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex) -{ - double startTime = Get_T(); - ///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; - - for (v = 0; v < n_vtx; ++v) - { - uint32_t nv = asg_arc_n(g, v); - if (g->seq[v>>1].del) - { - continue; - } - - if(nv < 2) - { - continue; - } - - - n_reduced += test_triangular_directly(g, v, min_edge_length, reverse_sources, ruIndex); - } - - - - if (n_reduced) { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d triangular overlaps\n", - __func__, n_reduced); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - return n_reduced; -} - - - - -int asg_arc_del_orthology(asg_t *g, ma_hit_t_alloc* reverse_sources, float drop_ratio, -long long miniedgeLen, R_to_U* ruIndex) -{ - double startTime = Get_T(); - ///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; - uint32_t idx[2]; - - for (v = 0; v < n_vtx; ++v) - { - uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del) continue; - ///some edges could be deleted - for (i = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs - if (!av[i].del) ++n_arc; - if (n_arc != 2) continue; - - for (i = 0, n_arc = 0; i < nv; i++) - { - if (!av[i].del) - { - idx[n_arc] = i; - n_arc++; - } - } - - if(check_if_diploid(av[idx[0]].v, av[idx[1]].v, g, reverse_sources, miniedgeLen, ruIndex) == 0) - { - float max = av[idx[0]].ol; - float min = av[idx[1]].ol; - - if(min < drop_ratio * max) - { - av[idx[1]].del = 1; - asg_arc_del(g, av[idx[1]].v^1, av[idx[1]].ul>>32^1, 1); - n_reduced++; - } - } - } - - - - - - if (n_reduced) { - asg_cleanup(g); - asg_symm(g); - } - - fprintf(stderr, "[M::%s] removed %d different hap overlaps\n", - __func__, n_reduced); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - - return n_reduced; -} - - - - -int asg_arc_del_orthology_multiple_way(asg_t *g, ma_hit_t_alloc* reverse_sources, float drop_ratio, -long long miniedgeLen, R_to_U* ruIndex) -{ - double startTime = Get_T(); - ///the reason is that each read has two direction (query->target, target->query) - uint32_t v, v_max, v_maxLen, n_vtx = g->n_seq * 2, n_reduced = 0; - - for (v = 0; v < n_vtx; ++v) - { - if (g->seq_vis[v] != 0) continue; - uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del) continue; - n_arc = get_real_length(g, v, NULL); - if (n_arc < 2) continue; - v_max = (uint32_t)-1; - v_maxLen = 0; - - for (i = 0, n_arc = 0; i < nv; i++) - { - if (!av[i].del) - { - if(v_max == (uint32_t)-1) - { - v_max = av[i].v; - v_maxLen = av[i].ol; - } - else if(check_if_diploid(v_max, av[i].v, g, reverse_sources, miniedgeLen, ruIndex) == 0) - { - if(av[i].ol < drop_ratio * v_maxLen) - { - ///fprintf(stderr, "v: %u, v_max: %u, av[%d].v: %u\n", v>>1, v_max>>1, i, av[i].v>>1); - - // av[i].ol = 1;///should be a bug - av[i].del = 1; - asg_arc_del(g, av[i].v^1, av[i].ul>>32^1, 1); - n_reduced++; - } - } - } - } - } - - if (n_reduced) { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d different hap overlaps\n", - __func__, n_reduced); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - return n_reduced; -} - - - -uint32_t detect_single_path_with_dels_by_length -(asg_t *g, uint32_t begNode, uint32_t* endNode, long long* Len, buf_t* b, long long maxLen) -{ - - uint32_t v = begNode, w; - uint32_t kv, kw; - (*Len) = 0; - - - while (1) - { - (*Len)++; - kv = get_real_length(g, v, NULL); - (*endNode) = v; - - ///if(b) kv_push(uint32_t, b->b, v>>1); - if(b) kv_push(uint32_t, b->b, v); - - if(kv == 0) - { - return END_TIPS; - } - - if(kv == 2) - { - return TWO_OUTPUT; - } - - if(kv > 2) - { - return MUL_OUTPUT; - } - - if((*Len) > maxLen) - { - return LONG_TIPS; - } - - ///up to here, kv=1 - ///kw must >= 1 - get_real_length(g, v, &w); - kw = get_real_length(g, w^1, NULL); - v = w; - (*endNode) = v; - - - if(kw == 2) - { - (*Len)++; - ///if(b) kv_push(uint32_t, b->b, v>>1); - if(b) kv_push(uint32_t, b->b, v); - return TWO_INPUT; - } - - if(kw > 2) - { - (*Len)++; - ///if(b) kv_push(uint32_t, b->b, v>>1); - if(b) kv_push(uint32_t, b->b, v); - return MUL_INPUT; - } - - - if((v>>1) == (begNode>>1)) - { - return LOOP; - } - } - - return LONG_TIPS; -} - - - -long long asg_arc_del_self_circle_untig(asg_t *g, long long circleLen, int is_drop) -{ - uint32_t v, w, n_vtx = g->n_seq * 2, n_reduced = 0, convex, flag; - long long ll; - asg_arc_t *aw; - uint32_t nw, k; - for (v = 0; v < n_vtx; ++v) - { - uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - ///some node could be deleted - if (g->seq[v>>1].del) continue; - if(is_drop && g->seq[v>>1].c == ALTER_LABLE) continue; - - n_arc = get_real_length(g, v, NULL); - if (n_arc != 1) continue; - - for (i = 0; i < nv; i++) - { - ///actually there is just one un-del edge - if (!av[i].del) - { - flag = detect_single_path_with_dels_by_length(g, v, &convex, &ll, NULL, circleLen); - if(ll > circleLen || flag == LONG_TIPS) - { - break; - } - if(flag == LOOP) - { - break; - } - if(flag != END_TIPS && flag != LONG_TIPS) - { - w = v^1; - n_arc = get_real_length(g, w, NULL); - if(n_arc == 0) - { - break; - } - aw = asg_arc_a(g, w); - nw = asg_arc_n(g, w); - for (k = 0; k < nw; k++) - { - if ((!aw[k].del) && (aw[k].v == (convex^1))) - { - aw[k].del = 1; - asg_arc_del(g, aw[k].v^1, aw[k].ul>>32^1, 1); - n_reduced++; - } - } - } - } - } - } - - if (n_reduced) { - asg_cleanup(g); - asg_symm(g); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d self-circles\n", - __func__, n_reduced); - } - - return n_reduced; -} - - -long long get_untig_coverage(ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, uint32_t* b, uint64_t n) -{ - uint64_t k, j; - uint32_t v; - ma_hit_t *h; - long long R_bases = 0, C_bases = 0; - for (k = 0; k < n; ++k) - { - v = b[k]>>1; - R_bases += coverage_cut[v].e - coverage_cut[v].s; - for (j = 0; j < (uint64_t)(sources[v].length); j++) - { - h = &(sources[v].buffer[j]); - C_bases += Get_qe((*h)) - Get_qs((*h)); - } - } - return C_bases/R_bases; -} - -/** -void copy_untig(asg_t *g, long long times, uint32_t* b, long long n, C_graph* cg) -{ - if(times <= 1) return; - - times--; - long long i, j; - uint64_t tmp; - for (i = 0; i < times; i++) - { - for (j = 0; j < n; j++) - { - tmp = - kv_push(uint64_t, cg->Node, ); - asg_add_auxiliary_seq_set(g, (b[j]>>1), 0); - } - } -} -**/ - -void init_C_graph(C_graph* g, uint32_t n_seq) -{ - kv_init(g->Nodes); - kv_init(g->Edges); - g->pre_n_seq = n_seq; - g->seqID = n_seq; -} - -void destory_C_graph(C_graph* g) -{ - kv_destroy(g->Nodes); - kv_destroy(g->Edges); -} - - -long long asg_arc_del_simple_circle_untig(ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, asg_t *g, long long circleLen, int is_drop) -{ - uint32_t v, w, n_vtx = g->n_seq * 2, n_reduced = 0, convex, flag; - long long ll; - asg_arc_t *aw; - uint32_t nw, k; - buf_t b; - memset(&b, 0, sizeof(buf_t)); - - C_graph cg; - init_C_graph(&cg, g->n_seq); - - for (v = 0; v < n_vtx; ++v) - { - uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - ///some node could be deleted - if (g->seq[v>>1].del) continue; - if(is_drop && g->seq[v>>1].c == ALTER_LABLE) continue; - if(get_real_length(g, v^1, NULL)<=1) continue; - - n_arc = get_real_length(g, v, NULL); - if (n_arc != 1) continue; - - for (i = 0; i < nv; i++) - { - ///actually there is just one un-del edge - if (!av[i].del) - { - b.b.n = 0; - flag = detect_single_path_with_dels_by_length(g, v, &convex, &ll, &b, circleLen); - if(ll > circleLen || flag == LONG_TIPS) - { - break; - } - if(flag == LOOP) - { - break; - } - if(flag != END_TIPS && flag != LONG_TIPS) - { - if(v == convex && b.b.n > 1) - { - convex = b.b.a[b.b.n - 2]; - b.b.n--; - } - - w = v^1; - n_arc = get_real_length(g, w, NULL); - if(n_arc == 0) - { - break; - } - aw = asg_arc_a(g, w); - nw = asg_arc_n(g, w); - for (k = 0; k < nw; k++) - { - if ((!aw[k].del) && (aw[k].v == (convex^1))) - { - // coverage = get_untig_coverage(sources, coverage_cut, b.b.a, b.b.n); - // copy_untig(g, (coverage/asm_opt.coverage), b.b.a, b.b.n, &cg); - - - aw[k].del = 1; - asg_arc_del(g, aw[k].v^1, aw[k].ul>>32^1, 1); - n_reduced++; - } - } - } - } - } - } - - if (n_reduced) { - asg_cleanup(g); - asg_symm(g); - } - - free(b.b.a); - destory_C_graph(&cg); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d self-circles\n", - __func__, n_reduced); - } - - return n_reduced; -} - - -int double_check_tangle(uint32_t vBeg, uint32_t vEnd, uint32_t* u_vecs, uint32_t n, asg_t *nsg) -{ - uint32_t v, nv, k, i, j; - asg_arc_t *av = NULL; - if(vBeg != (uint32_t)-1) - { - v = vBeg; - nv = asg_arc_n(nsg, v); - av = asg_arc_a(nsg, v); - for(k = 0; k < nv; k++) - { - if(av[k].del) continue; - for (i = 0; i < n; i++) - { - if((av[k].v>>1)==(u_vecs[i]>>1)) break; - } - ///haven't found - if(i == n) return 0; - } - } - - if(vEnd != (uint32_t)-1) - { - v = vEnd^1; - nv = asg_arc_n(nsg, v); - av = asg_arc_a(nsg, v); - for(k = 0; k < nv; k++) - { - if(av[k].del) continue; - for (i = 0; i < n; i++) - { - if((av[k].v>>1)==(u_vecs[i]>>1)) break; - } - ///haven't found - if(i == n) return 0; - } - } - - ///scan tangles - for (j = 0; j < n; j++) - { - v = u_vecs[j]; - nv = asg_arc_n(nsg, v); - av = asg_arc_a(nsg, v); - for(k = 0; k < nv; k++) - { - if(av[k].del) continue; - for (i = 0; i < n; i++) - { - if((av[k].v>>1)==(u_vecs[i]>>1)) break; - } - if(i == n && av[k].v != (vBeg^1) && av[k].v != vEnd) return 0; - } - - - - v = v^1; - nv = asg_arc_n(nsg, v); - av = asg_arc_a(nsg, v); - for(k = 0; k < nv; k++) - { - if(av[k].del) continue; - for (i = 0; i < n; i++) - { - if((av[k].v>>1)==(u_vecs[i]>>1)) break; - } - if(i == n && av[k].v != (vBeg^1) && av[k].v != vEnd) return 0; - } - } - - return 1; -} - -int explore_graph(asg_t *nsg, uint32_t vBeg, float single_threshold, -float l_untig_rate_threshold, long long minLongUntig, long long maxShortUntig, uint32_t ignore_d, -buf_t* bb, uint32_t** r, size_t* rm, size_t* rn, uint8_t* visit, ma_ug_t *ug, uint32_t* r_ID) -{ - ///the ID of the end long unitig - (*r_ID) = (uint32_t)-1; - uint32_t nv, vBeg_end; - asg_arc_t *av; - - kvec_t(uint32_t) u_vecs; - kv_init(u_vecs); - if(r && rm && rn) kv_reuse(u_vecs, 0, (*rm), (*r)); - - memset(visit, 0, nsg->n_seq); - kdq_t(uint32_t) *buf; - buf = kdq_init(uint32_t); - - uint32_t vEnd, threshold, num_reads = 0, i, k, v, end = (uint32_t)-1, in = 0, vELen, tmp; - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - - bb->b.n = 0; - if(get_unitig(nsg, ug, vBeg, &vEnd, &nodeLen, &baseLen, - &max_stop_nodeLen, &max_stop_baseLen, 1, bb)==LOOP) - { - ///the length of LOO is infinite - kdq_destroy(uint32_t, buf); - return 0; - } - vBeg_end = vEnd; - threshold = nodeLen; - for (i = 0; i < bb->b.n; i++) - { - Set_vis(visit, bb->b.a[i], ignore_d); - Set_vis(visit, bb->b.a[i]^1, ignore_d); - } - v = vBeg; - - kdq_push(uint32_t, buf, v); - while (kdq_size(buf) != 0) - { - in++; - v = *(kdq_pop(uint32_t, buf)); - - ///in == 1 means the start node, it is useless - if(in != 1) - { - ///get current untig length - bb->b.n = 0; - if(get_unitig(nsg, ug, v, &vEnd, &nodeLen, &baseLen, - &max_stop_nodeLen, &max_stop_baseLen, 1, bb)==LOOP) - { - kdq_destroy(uint32_t, buf); - return 0; - } - vELen = nodeLen; - - ///first long unitig except the start node - if(if_long_tip_length(nsg, ug, v, &vELen, - minLongUntig, maxShortUntig, l_untig_rate_threshold, threshold)==1) - { - if(end == (uint32_t)-1) - { - end = v; - continue; - } - else - { - in = (uint32_t)-1; - break; - } - } - - if(vELen > (threshold * single_threshold)) - { - in = (uint32_t)-1; - break; - } - - num_reads = num_reads + vELen; - if(num_reads > threshold) - { - in = (uint32_t)-1; - break; - } - - if(r && rm && rn) - { - for (i = 0; i < bb->b.n; i++) - { - kv_push(uint32_t, u_vecs, bb->b.a[i]); - } - } - } - - tmp = v^1; - v = vEnd; - nv = asg_arc_n(nsg, v); - av = asg_arc_a(nsg, v); - for(k = 0; k < nv; k++) - { - if(av[k].del) continue; - - if(av[k].v == vBeg) - { - in = (uint32_t)-1; - goto termi; - } - - if(Get_vis(visit,av[k].v,ignore_d)==0) - { - kdq_push(uint32_t, buf, av[k].v); - - bb->b.n = 0; - get_unitig(nsg, ug, av[k].v, &vEnd, &nodeLen, &baseLen, - &max_stop_nodeLen, &max_stop_baseLen, 1, bb); - - for (i = 0; i < bb->b.n; i++) - { - Set_vis(visit, bb->b.a[i], ignore_d); - } - } - } - - ///for start node, we just need one direction - if(in != 1 && ignore_d) - { - v = tmp; - nv = asg_arc_n(nsg, v); - av = asg_arc_a(nsg, v); - for(k = 0; k < nv; k++) - { - if(av[k].del) continue; - - if(av[k].v == vBeg) - { - in = (uint32_t)-1; - goto termi; - } - - if(Get_vis(visit,av[k].v,ignore_d)==0) - { - kdq_push(uint32_t, buf, av[k].v); - - bb->b.n = 0; - get_unitig(nsg, ug, av[k].v, &vEnd, &nodeLen, &baseLen, - &max_stop_nodeLen, &max_stop_baseLen, 1, bb); - - - for (i = 0; i < bb->b.n; i++) - { - Set_vis(visit, bb->b.a[i], ignore_d); - } - } - } - } - } - - termi: - kdq_destroy(uint32_t, buf); - if(r && rm && rn) - { - (*rn) = u_vecs.n; - (*rm) = u_vecs.m; - (*r) = u_vecs.a; - } - - - (*r_ID) = end; - ///in == 1 means the end subgraph is the long untig itself - ///so here is no tangles - if(in == (uint32_t)-1 || in == 1) - { - return 0; - } - else - { - if(r && rm && rn) return double_check_tangle(vBeg_end, (*r_ID), u_vecs.a, u_vecs.n, nsg); - - return 1; - } -} - -void output_tangles(uint32_t startID, uint32_t endId, uint32_t* a, uint32_t n, const char* lable) -{ - kvec_t(uint32_t) u_vecs; - u_vecs.a = a, u_vecs.n = n; - - fprintf(stderr, "\n%sstartID: %u, dir: %u\n", lable, startID>>1, startID&1); - fprintf(stderr, "%sendID: %u, dir: %u\n", lable, endId>>1, endId&1); - uint32_t ijk; - for (ijk = 0; ijk < u_vecs.n; ijk++) - { - fprintf(stderr, "%stangleID: %u, dir: %u\n", lable, u_vecs.a[ijk]>>1, u_vecs.a[ijk]&1); - } -} - - -int get_arc(asg_t *g, uint32_t src, uint32_t dest, asg_arc_t* result) -{ - uint32_t i; - if(g->seq[src>>1].del) return 0; - - uint32_t nv = asg_arc_n(g, src); - asg_arc_t *av = asg_arc_a(g, src); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - if(av[i].v == dest) - { - (*result) = av[i]; - break; - } - } - - if(i != nv) return 1; - return 0; -} - -uint32_t insert_index(asg_t *g, uint32_t v) -{ - uint32_t v_tx = g->n_seq * 2; - if(v >= v_tx) return (uint32_t)-1; - if(asg_arc_n(g, v)!=0) return (g->idx[v]>>32) + asg_arc_n(g, v); - ///now v itself does not have any edge - while (v < v_tx && asg_arc_n(g, v) == 0){v++;} - ///means there are no edge at the whole graph - if(v>=v_tx) return g->n_arc; - return (g->idx[v]>>32); -} - -asg_arc_t* insert_index_p(asg_t *g, long long index, uint32_t m_distance) -{ - ///each edge has two direction - if (g->n_arc + m_distance > g->m_arc) - { - ///g->m_arc = g->n_arc + (m_distance<<1); - g->m_arc = (g->n_arc + m_distance)<<1; - g->arc = (asg_arc_t*)realloc(g->arc, g->m_arc * sizeof(asg_arc_t)); - } - long long i = g->n_arc; i--; - for (; i >= index; i--) - { - g->arc[i+m_distance] = g->arc[i]; - } - - g->n_arc = g->n_arc + m_distance; - - return &(g->arc[index]); -} - -void exchange_arcs(asg_arc_t* x, asg_arc_t* y) -{ - asg_arc_t k; - k = (*x);(*x) = (*y);(*y) = k; -} - -void insert_arc(asg_t *g, long long index, uint32_t m_distance, uint32_t src, uint32_t srcLen, uint32_t dest, -uint32_t oLen, uint8_t strong, uint8_t el, uint8_t no_l_indel) -{ - asg_arc_t* p; - uint32_t l; - long long i; - p = insert_index_p(g, index, m_distance); - p->del = !!(0);p->el = el; p->no_l_indel = no_l_indel; p->strong = strong; p->ol = oLen; - p->v = dest; - p->ul = src; p->ul = p->ul << 32; l = srcLen - oLen; p->ul = p->ul | l; - for (i = index - 1; i >= 0 && p->ul <= g->arc[i].ul; i--) - { - if((!g->arc[i].del)&&(g->arc[i].v==p->v) && ((g->arc[i].ul>>32)==(p->ul>>32))) - { - p->del = !!(1); - break; - } - exchange_arcs(p, &(g->arc[i]));p = &(g->arc[i]); - } - - - if(asg_arc_n(g, src) == 0) - { - g->idx[src] = index; g->idx[src] = g->idx[src]<<32; g->idx[src] = g->idx[src] | 1; - } - else - { - g->idx[src] = g->idx[src] + 1; - } - - uint32_t v, v_tx = g->n_seq*2; - uint64_t add = 1; add = add << 32; - for (v = src+1; v < v_tx; v++) - { - if(asg_arc_n(g, v) == 0) continue; - g->idx[v] += add; - } -} - -int asg_append_edges_to_srt(asg_t *g, uint32_t src, -uint32_t srcLen, uint32_t dest, uint32_t oLen, -uint8_t strong, uint8_t el, uint8_t no_l_indel) -{ - uint32_t v_tx = g->n_seq * 2; - /** - uint32_t d_i = 0, current_i, next_i, src_n, s_index, e_index; - while(d_i < v_tx) - { - current_i = d_i; - d_i++; - src_n = asg_arc_n(g, current_i); - if(src_n == 0) continue; - s_index = (g->idx[current_i]>>32); - e_index = s_index + src_n; - - while (d_i < v_tx && asg_arc_n(g, d_i) == 0){d_i++;} - if(d_i>=v_tx) break; - next_i = d_i; - - - if(current_i != v_tx) - { - if(e_index != (g->idx[next_i]>>32)) - { - fprintf(stderr, "v_tx: %u, current_i: %u, node: %u, s_index: %u, e_index: %u, g->idx[next_i]>>32: %u\n", - v_tx, current_i, current_i>>1, s_index, e_index, g->idx[next_i]>>32); - } - } - else - { - if(e_index != g->n_arc) - { - fprintf(stderr, "ERROR2\n"); - } - } - } - - for (d_i = 0; d_i < v_tx; d_i++) - { - uint32_t nv = asg_arc_n(g, d_i), s_i; - asg_arc_t *av = asg_arc_a(g, d_i); - asg_arc_t forward, backward; - for (s_i = 0; s_i < nv; s_i++) - { - if(av[s_i].del) continue; - forward = av[s_i]; - if(get_arc(g, forward.ul>>32, forward.v, &forward) == 0) - { - fprintf(stderr, "ERROR1\n"); - } - if(forward.del != av[s_i].del || forward.el != av[s_i].el || - forward.no_l_indel != av[s_i].no_l_indel ||forward.ol != av[s_i].ol || - forward.strong != av[s_i].strong || forward.ul != av[s_i].ul || - forward.v != av[s_i].v) - { - fprintf(stderr, "ERROR2\n"); - } - - if(get_arc(g, forward.v^1, (forward.ul>>32)^1, &backward) == 0) - { - fprintf(stderr, "ERROR3\n"); - } - - if(forward.ol != backward.ol) - { - fprintf(stderr, "forward.ol: %u, backward.ol: %u\n", - forward.ol, backward.ol); - } - - } - } - **/ - - - if (src >= v_tx || dest >= v_tx) - { - return 0; - } - - ///we need to link src--->dest and (dest^1)----->(src^1) - uint32_t src_i = insert_index(g, src); - insert_arc(g, src_i, 1, src, srcLen, dest, oLen, strong, el, no_l_indel); - - - /** - if (src >= v_tx || (src^1) >= v_tx || dest >= v_tx || (dest^1) >= v_tx) - { - return 0; - } - - ///we need to link src--->dest and (dest^1)----->(src^1) - uint32_t src_i = insert_index(g, src); - insert_arc(g, src_i, 1, src, srcLen, dest, oLen); - uint32_t dest_i = insert_index(g, (dest^1)); - insert_arc(g, dest_i, 1, dest^1, destLen, src^1, oLen); - **/ - - - ///we need to link src--->dest and (dest^1)----->(src^1) - /** - if(src > (dest^1)) - { - uint32_t src_i = insert_index(g, src); - insert_arc(g, src_i, src, srcLen, dest, oLen); - uint32_t dest_i = insert_index(g, (dest^1)); - insert_arc(g, dest_i, dest^1, destLen, src^1, oLen); - } - else - { - uint32_t dest_i = insert_index(g, (dest^1)); - insert_arc(g, dest_i, dest^1, destLen, src^1, oLen); - uint32_t src_i = insert_index(g, src); - insert_arc(g, src_i, src, srcLen, dest, oLen); - } - **/ - - return 1; -} - -void append_ma_utg_t(ma_utg_t* v_x, ma_utg_t* v_y) -{ - if(v_x->m < (v_x->n + v_y->n)) - { - v_x->m = v_x->n + v_y->n; - v_x->a = (uint64_t*)realloc(v_x->a, v_x->m * sizeof(uint64_t)); - } - memcpy(v_x->a+v_x->n, v_y->a, v_y->n*sizeof(uint64_t)); - v_x->n = v_x->n + v_y->n; - free(v_y->a); - v_y->m=v_y->n=0;v_y->a=NULL; -} - - -#define UNROLL 0 -#define CONVEX 1 -void merge_nodes(ma_ug_t *ug, uint32_t startID, uint32_t endId, uint32_t* a, uint32_t n, -uint32_t type) -{ - ma_utg_t *v_x = NULL, *v_y = NULL; - asg_t* nsg = ug->g; - kvec_t(uint32_t) u_vecs; - uint32_t i = 0, maxEvaluateLen = 0, maxBaseLen = 0, v, totalEvaluateLen = 0; - u_vecs.a = a, u_vecs.n = n; - if(u_vecs.n > 0) ///u_vecs does not contain startID && endId - { - v_x = &(ug->u.a[u_vecs.a[0]>>1]); - asg_seq_del(nsg, u_vecs.a[0]>>1); - maxEvaluateLen = EvaluateLen(ug->u, u_vecs.a[0]>>1); - maxBaseLen = v_x->len; - totalEvaluateLen += EvaluateLen(ug->u, u_vecs.a[0]>>1); - } - - - for (i = 1; i < u_vecs.n; i++) - { - v_y = &(ug->u.a[u_vecs.a[i]>>1]); - if(maxEvaluateLen <= EvaluateLen(ug->u, u_vecs.a[i]>>1)) - { - maxEvaluateLen = EvaluateLen(ug->u, u_vecs.a[i]>>1); - maxBaseLen = v_y->len; - } - totalEvaluateLen += EvaluateLen(ug->u, u_vecs.a[i]>>1); - - - append_ma_utg_t(v_x, v_y); - asg_seq_del(nsg, u_vecs.a[i]>>1); - } - - - if(u_vecs.n > 0) - { - i = 0; - nsg->seq[u_vecs.a[0]>>1].del = !!(0); - - - EvaluateLen(ug->u, u_vecs.a[0]>>1) = maxEvaluateLen; - totalEvaluateLen = totalEvaluateLen / 2; - if(totalEvaluateLen > EvaluateLen(ug->u, u_vecs.a[0]>>1)) - { - EvaluateLen(ug->u, u_vecs.a[0]>>1) = totalEvaluateLen; - } - IsMerge(ug->u, u_vecs.a[0]>>1)++; - - - v_x->len = maxBaseLen; - /****************************may have bugs********************************/ - nsg->seq[u_vecs.a[0]>>1].len = maxBaseLen; - /****************************may have bugs********************************/ - v = u_vecs.a[0]; - - if(type == UNROLL) - { - if(startID != (uint32_t)-1) - { - asg_append_edges_to_srt(nsg, startID, ug->u.a[startID>>1].len, v, 0, 0, 0 ,0); - asg_append_edges_to_srt(nsg, v^1, ug->u.a[v>>1].len, startID^1, 0, 0, 0, 0); - } - - if(endId != (uint32_t)-1) - { - asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, endId, 0, 0, 0 ,0); - asg_append_edges_to_srt(nsg, endId^1, ug->u.a[endId>>1].len, v^1, 0, 0, 0 ,0); - } - } - - if(type == CONVEX) - { - if(startID != (uint32_t)-1) - { - asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, startID^1, 0, 0, 0, 0); - asg_append_edges_to_srt(nsg, startID, ug->u.a[startID>>1].len, v^1, 0, 0, 0 ,0); - } - - if(endId != (uint32_t)-1) - { - asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, endId, 0, 0, 0 ,0); - asg_append_edges_to_srt(nsg, endId^1, ug->u.a[endId>>1].len, v^1, 0, 0, 0 ,0); - } - } - } -} - -///return 1 is what we want -///as for return value: 0: do nothing, 1: unroll, 2: convex -#define CONVEX_M 1 -#define UNROLL_M 2 -#define UNROLL_E 3 -inline uint32_t walk_through(asg_t *read_g, ma_ug_t *ug, ma_hit_t_alloc* reverse_sources, long long minLongUntig, -long long maxShortUntig, float l_untig_rate, float max_node_threshold, buf_t* b_0, buf_t* b_1, -kvec_t_u32_warp* u_vecs, uint8_t* visit, uint32_t v, uint32_t* r_beg, uint32_t* r_end, -uint32_t* r_next_uID, R_to_U* ruIndex, uint8_t* is_r_het) -{ - (*r_beg) = (*r_end) = (uint32_t)-1; - asg_t* nsg = ug->g; - uint32_t i, beg, end, primaryLen, returnFlag; - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - - /*****************************simple checking**********************************/ - beg = v; - if(nsg->seq[beg>>1].del || asg_arc_n(nsg, beg) <= 0 || get_real_length(nsg, beg, NULL)<=0) - { - return 0; - } - if(get_real_length(nsg, beg^1, NULL) == 1)///check if beg is the tig end - { - get_real_length(nsg, beg^1, &end); - if(get_real_length(nsg, end^1, NULL) == 1) - { - return 0; - } - } - - ///if the contig here is too small - primaryLen = get_unitig(nsg, ug, beg, &end, &nodeLen, &baseLen, - &max_stop_nodeLen, &max_stop_baseLen, 1, NULL); - if(primaryLen == LOOP || nodeLen < minLongUntig) - { - return 0; - } - primaryLen = nodeLen; - - if(get_real_length(nsg, end, NULL) <= 0)///if it is already a simple contig - { - return 0; - } - /*****************************simple checking**********************************/ - (*r_beg) = beg; (*r_end) = end; - - /*****************************adjacent checking**********************************/ - uint32_t nw = asg_arc_n(nsg, end), n_arc = 0, next_uID, next_uID_verify; - asg_arc_t *aw = asg_arc_a(nsg, end); - for (i = 0; i < nw; i++) - { - if(!aw[i].del) - { - n_arc++; - ////we don't want any long tip here - if(if_long_tip_length(nsg, ug, aw[i].v, NULL, - minLongUntig, maxShortUntig, l_untig_rate, primaryLen)==1) - { - n_arc = 0; - break; - } - } - } - - if(n_arc == 0) - { - return 0; - } - /*****************************adjacent checking**********************************/ - - ///here all out-nodes of v are small untigs - if(explore_graph(nsg, beg, max_node_threshold, l_untig_rate, - minLongUntig, maxShortUntig, 1, b_0, &(u_vecs->a.a), &(u_vecs->a.m), - &(u_vecs->a.n), visit, ug, &next_uID) == 1) - { - (*r_next_uID) = next_uID; - if(next_uID != (uint32_t)-1 && u_vecs->a.n == 1 - && IsMerge(ug->u, u_vecs->a.a[0]>>1) > 0) - { - return 0; - } - ///if next_uID == (uint32_t)-1, that means we found an end subgraph - if(next_uID != (uint32_t)-1) - { - ///need to avoid missassembly - ///merge all tangle as two types: 1. convex; 2, unroll them as a line - ///should do somthing here, but we just skip it for covenience - returnFlag = explore_graph(nsg, beg, max_node_threshold, l_untig_rate, - minLongUntig, maxShortUntig, 0, b_0, NULL, NULL, NULL, visit, ug, - &next_uID_verify); - - if((returnFlag == 1 && next_uID_verify != next_uID) || (returnFlag == 0)) - { - //output_tangles(beg, next_uID, u_vecs->a.a, u_vecs->a.n, (char*)("###")); - returnFlag = 0; - } - else - { - returnFlag = 1; - } - - // #define UNAVAILABLE (uint32_t)-1 - // #define PLOID 0 - // #define NON_PLOID 1 - if(returnFlag == 1 && check_different_haps(nsg, ug, read_g, beg, next_uID, - reverse_sources, b_0, b_1, ruIndex, is_r_het, minLongUntig-1, 1) == PLOID) - { - ///output_tangles(beg, next_uID, u_vecs->a.a, u_vecs->a.n, (char*)("???")); - returnFlag = 0; - } - - if(returnFlag == 0) - { - merge_nodes(ug, end, next_uID, u_vecs->a.a, u_vecs->a.n, CONVEX); - return CONVEX_M; - } - } - - ///actually it is not possible here - if(u_vecs->a.n <= 0 || next_uID>>1 == beg>>1) - { - return 0; - } - ///output_tangles(beg, next_uID, u_vecs->a.a, u_vecs->a.n, (char*)("")); - merge_nodes(ug, end, next_uID, u_vecs->a.a, u_vecs->a.n, UNROLL); - if(next_uID != (uint32_t)-1) - { - (*r_next_uID) = next_uID; - return UNROLL_M; - } - else ///end tangle - { - if(u_vecs->a.n > 0) - { - (*r_next_uID) = u_vecs->a.a[0]; - } - return UNROLL_E; - } - } - - return 0; -} - - -void adjust_asg_by_ug(ma_ug_t *ug, asg_t *read_g) -{ - uint32_t v, n_vtx, i = 0, qn; - asg_t* nsg = ug->g; - n_vtx = nsg->n_seq; - ma_utg_t* node = NULL; - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].c == ALTER_LABLE) - { - node = &(ug->u.a[v]); - for (i = 0; i < node->n; i++) - { - qn = node->a[i]>>33; - read_g->seq[qn].c = ALTER_LABLE; - } - } - } - - - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].c == ALTER_LABLE) - { - node = &(ug->u.a[v]); - for (i = 0; i < node->n; i++) - { - qn = node->a[i]>>33; - ///read_g->seq[qn].c = ALTER_LABLE; - asg_seq_drop(read_g, qn); - } - } - } - - asg_cleanup(read_g); - asg_symm(read_g); -} - -void lable_hap_asg_by_ug(ma_ug_t *ug, asg_t *read_g) -{ - uint32_t v, n_vtx, i = 0, qn; - asg_t* nsg = ug->g; - n_vtx = nsg->n_seq; - ma_utg_t* node = NULL; - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].c == HAP_LABLE) - { - node = &(ug->u.a[v]); - for (i = 0; i < node->n; i++) - { - qn = node->a[i]>>33; - read_g->seq[qn].c = HAP_LABLE; - } - } - } - -} - -///qn is the read Id -///self_offset is the offset of this read in contig -void query_reverse_sources(asg_t *read_g, ma_hit_t_alloc* reverse_sources, -R_to_U* ruIndex, uint32_t qn, uint32_t self_offset, kvec_t_u64_warp* u_vecs) -{ - uint32_t i, rId, is_Unitig, cId; - uint64_t mode; - ///means the reads coming from different haplotype have already been purged - if(read_g->seq[qn].c == HAP_LABLE) - { - cId = (uint32_t)-1; - mode = self_offset; mode = mode << 33; mode = mode|cId; mode = mode | (uint64_t)(0x100000000); - kv_push(uint64_t, u_vecs->a, mode); - return; - } - - - for (i = 0; i < reverse_sources[qn].length; i++) - { - rId = Get_tn(reverse_sources[qn].buffer[i]); - ///there are three cases: - ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id - ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 - ///3. read has bee deleted, get_R_to_U() return the id of read that contains it - if(read_g->seq[rId].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, rId, &rId, &is_Unitig); - if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; - } - - ///here rId is the id of the read coming from the different haplotype - ///cId is the id of the corresponding contig (note here is the contig, instead of untig) - get_R_to_U(ruIndex, rId, &cId, &is_Unitig); - if(is_Unitig == 0) continue; - ///if the read is at alternative contigs, cId might be (uint32_t)-1 - ///if(cId == (uint32_t)-1) - mode = self_offset; mode = mode << 33; mode = mode|(uint64_t)(cId); - kv_push(uint64_t, u_vecs->a, mode); - } - -} - - - -uint32_t get_rId_from_contig_by_offset(ma_ug_t *ug, rIdContig* array, uint32_t offset) -{ - uint32_t uId, rId; - ma_utg_t* reads; - for (;array->untigI < array->b_0->b.n; array->untigI++) - { - uId = array->b_0->b.a[array->untigI]>>1; - ///if(IsMerge(ug->u, uId)>0) continue; - reads = &(ug->u.a[uId]); - for (;array->readI < reads->n; array->readI++, array->offset++) - { - if(array->offset == offset) - { - rId = reads->a[array->readI]>>33; - return rId; - } - } - array->readI = 0; - } - - - array->offset = 0; - for (array->untigI = 0;array->untigI < array->b_0->b.n; array->untigI++) - { - uId = array->b_0->b.a[array->untigI]>>1; - ///if(IsMerge(ug->u, uId)>0) continue; - reads = &(ug->u.a[uId]); - for (array->readI = 0;array->readI < reads->n; array->readI++, array->offset++) - { - if(array->offset == offset) - { - rId = reads->a[array->readI]>>33; - return rId; - } - } - } - - array->untigI = array->readI = array->offset = 0; - return (uint32_t)-1; -} - -inline uint32_t get_contig_len(ma_ug_t *ug, buf_t* b_0) -{ - uint32_t uId, untigI, Len = 0; - ma_utg_t* reads; - - for (untigI = 0;untigI < b_0->b.n; untigI++) - { - uId = b_0->b.a[untigI]>>1; - ///if(IsMerge(ug->u, uId)>0) continue; - reads = &(ug->u.a[uId]); - Len = Len + reads->n; - } - - return Len; -} - -uint32_t get_offset_from_contig_by_rId(ma_ug_t *ug, rIdContig* array, uint32_t query_rId) -{ - uint32_t uId, rId; - ma_utg_t* reads; - for (;array->untigI < array->b_0->b.n; array->untigI++) - { - uId = array->b_0->b.a[array->untigI]>>1; - ///if(IsMerge(ug->u, uId)>0) continue; - reads = &(ug->u.a[uId]); - for (;array->readI < reads->n; array->readI++, array->offset++) - { - rId = reads->a[array->readI]>>33; - if(rId == query_rId) return array->offset; - } - array->readI = 0; - } - - - array->offset = 0; - for (array->untigI = 0;array->untigI < array->b_0->b.n; array->untigI++) - { - uId = array->b_0->b.a[array->untigI]>>1; - ///if(IsMerge(ug->u, uId)>0) continue; - reads = &(ug->u.a[uId]); - for (array->readI = 0;array->readI < reads->n; array->readI++, array->offset++) - { - rId = reads->a[array->readI]>>33; - if(rId == query_rId) return array->offset; - } - } - - array->untigI = array->readI = array->offset = 0; - return (uint32_t)-1; -} - -///tn is the cId, tn_off is the order of rId with the same cId -uint32_t get_reverseId(asg_t *read_g, ma_hit_t_alloc* reverse_sources, -R_to_U* ruIndex, uint32_t qn, uint32_t tn, uint32_t tn_off) -{ - uint32_t i, rId, is_Unitig, cId, cId_off = 0; - for (i = 0; i < reverse_sources[qn].length; i++) - { - rId = Get_tn(reverse_sources[qn].buffer[i]); - ///there are three cases: - ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id - ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 - ///3. read has bee deleted, get_R_to_U() return the id of read that contains it - if(read_g->seq[rId].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, rId, &rId, &is_Unitig); - if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; - } - - ///here rId is the id of the read coming from the different haplotype - ///cId is the id of the corresponding contig (note here is the contig, instead of untig) - get_R_to_U(ruIndex, rId, &cId, &is_Unitig); - if(is_Unitig == 0) continue; - ///if the read is at alternative contigs, cId might be (uint32_t)-1 - ///if(cId == (uint32_t)-1) - if(cId == tn) - { - if(cId_off == tn_off) return rId; - cId_off++; - } - } - - return (uint32_t)-1; -} - -uint32_t get_contig_overlap_interval(uint32_t is_reverse, -uint32_t q_beg, uint32_t q_end, uint32_t qLen, uint32_t t_beg, uint32_t t_end, uint32_t tLen, -uint32_t* r_q_beg, uint32_t* r_q_end, uint32_t* r_t_beg, uint32_t* r_t_end) -{ - uint32_t k; - (*r_q_beg) = (*r_q_end) = (*r_t_beg) = (*r_t_end) = (uint32_t)-1; - if(q_end >= qLen || t_end >= tLen) return 0; - if(q_beg >= qLen || t_beg >= tLen) return 0; - - if(is_reverse) - { - ///k = q_beg; q_beg = q_end; q_end = k; - ///q_beg = qLen - q_beg - 1; q_end = qLen - q_end - 1; k = q_beg; q_beg = q_end; q_end = k; - ///k = t_beg; t_beg = t_end; t_end = k; - t_beg = tLen - t_beg - 1; t_end = tLen - t_end - 1; k = t_beg; t_beg = t_end; t_end = k; - } - - - - - if(q_beg <= t_beg) - { - t_beg = t_beg - q_beg; q_beg = 0; - } - else - { - q_beg = q_beg - t_beg; t_beg = 0; - } - - uint32_t q_right_length = qLen - q_end - 1; - uint32_t t_right_length = tLen - t_end - 1; - if(q_right_length <= t_right_length) - { - q_end = qLen - 1; t_end = t_end + q_right_length; - } - else - { - t_end = tLen - 1; q_end = q_end + t_right_length; - } - - if(is_reverse) - { - ///q_beg = qLen - q_beg - 1; q_end = qLen - q_end - 1; k = q_beg; q_beg = q_end; q_end = k; - t_beg = tLen - t_beg - 1; t_end = tLen - t_end - 1; k = t_beg; t_beg = t_end; t_end = k; - } - - (*r_q_beg) = q_beg; (*r_q_end) = q_end; - (*r_t_beg) = t_beg; (*r_t_end) = t_end; - return 1; -} - - -int get_haplotype_rate(ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* reverse_sources, -R_to_U* ruIndex, buf_t* b_0, uint32_t beg, uint32_t end, uint32_t query_cId, float match_rate) -{ - uint32_t i, j, k, num, match_num, offset, uId, qn, rId, is_Unitig, cId; - ma_utg_t* reads; - - offset = match_num = num = 0; - for (i = 0; i < b_0->b.n; i++) - { - uId = b_0->b.a[i]>>1; - ///if(IsMerge(ug->u, uId)>0) continue; - reads = &(ug->u.a[uId]); - for (j = 0; j < reads->n; j++, offset++) - { - - if(offset < beg || offset > end) continue; - qn = reads->a[j]>>33; - if(reverse_sources[qn].length > 0) num++; - for (k = 0; k < reverse_sources[qn].length; k++) - { - rId = Get_tn(reverse_sources[qn].buffer[k]); - ///there are three cases: - ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id - ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 - ///3. read has bee deleted, get_R_to_U() return the id of read that contains it - if(read_g->seq[rId].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, rId, &rId, &is_Unitig); - if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; - } - - ///here rId is the id of the read coming from the different haplotype - ///cId is the id of the corresponding contig (note here is the contig, instead of untig) - get_R_to_U(ruIndex, rId, &cId, &is_Unitig); - if(is_Unitig == 0) continue; - ///if the read is at alternative contigs, cId might be (uint32_t)-1 - - if(cId == query_cId) - { - match_num++; - break; - } - - } - } - } - - if(match_num >= num*match_rate) return 1; - return 0; -} - - -#define contig_seed 20 -inline int get_useful_contig(kvec_t_u64_warp* u_vecs, float density, uint32_t miniLen, uint32_t* r_cId) -{ - (*r_cId) = (uint32_t)-1; - uint32_t cId; - uint32_t intervalLen = 0, realLen = 0, useful_index = (uint32_t)-1; - uint32_t i = u_vecs->i, end; - float T_density = density/2; - - if(i >= u_vecs->a.n) return -1; - if((uint32_t)(u_vecs->a.a[i]) == (uint32_t)-1) - { - u_vecs->i++; - return 0; - } - - end = i + contig_seed; - if(end > u_vecs->a.n) end = u_vecs->a.n; - cId = (uint32_t)(u_vecs->a.a[i]); - for (; i < end; i++) - { - if(cId == (uint32_t)(u_vecs->a.a[i])) realLen++; - intervalLen++; - if(realLen >= intervalLen*density) useful_index = i; - } - - if(realLen < intervalLen*T_density) - { - u_vecs->i++; - return 0; - } - ///here we found a useful seed - ///it seems we don't need to scan backward - for (; i < u_vecs->a.n; i++) - { - if(cId == (uint32_t)(u_vecs->a.a[i])) realLen++; - intervalLen++; - if(realLen < intervalLen*T_density) break; - if(realLen >= intervalLen*density) useful_index = i; - } - - if(useful_index == (uint32_t)-1 || (useful_index - u_vecs->i) < miniLen) - { - u_vecs->i++; - return 0; - } - - ///don't need to set backward - end = (uint32_t)-1; - for (i = u_vecs->i; i < u_vecs->a.n; i++) - { - if(cId == (uint32_t)(u_vecs->a.a[i])) - { - ///u_vecs->a.a[i] = (uint32_t)-1; - u_vecs->a.a[i] = u_vecs->a.a[i]|(uint64_t)(0xffffffff); - } - } - (*r_cId) = cId; - u_vecs->i++; - return (useful_index - u_vecs->i); -} - - - - - -#define UNVISIT (uint32_t)(0x7fffffff) -#define RED 0 -#define BLACK 1 -#define ISO 2 -#define LABLE 3 -void bi_paration(asg_t *bi_g, uint64_t* array, uint32_t bi_graph_Len) -{ - - kvec_t(uint64_t) a; - kv_init(a); - a.a = array; - a.n = a.m = bi_g->n_seq; - kdq_t(uint32_t) *buf; - buf = kdq_init(uint32_t); - uint32_t i, len, v, w, k, nv, roundID = 0; - asg_arc_t *av; - for (i = 0; i < bi_g->n_seq; i++) - { - bi_g->seq[i].c = 0; - } - - re_partition: - - for (i = 0; i < bi_g->n_seq; i++) - { - /****************************may have bugs********************************/ - ///how many reads contained in this contig - len = (a.a[i]>>33); - /****************************may have bugs********************************/ - ///if the contig is too small, or the contig has already been visited - ///if(len < bi_graph_Len || bi_g->seq[i].len != UNVISIT) continue; - if(len < bi_graph_Len || bi_g->seq[i].c == 1) continue; - if(roundID == 0 && bi_g->seq[i].len == UNVISIT) continue; - - ///set the color of this node - bi_g->seq[i].len = RED; bi_g->seq[i].c = 1; - kdq_push(uint32_t, buf, i); - while (kdq_size(buf) != 0) - { - v = *(kdq_pop(uint32_t, buf)); bi_g->seq[v].c = 1; - if(bi_g->seq[v].len == ISO) continue; - nv = asg_arc_n(bi_g, v); - av = asg_arc_a(bi_g, v); - - - ///get all out-nodes of v - for(k = 0; k < nv; k++) - { - w = av[k].v; - /****************************may have bugs********************************/ - ///if(bi_g->seq[w].len == bi_g->seq[v].len) - len = (a.a[w]>>33); - ///only check large contig - if(len >= bi_graph_Len && bi_g->seq[w].len == bi_g->seq[v].len) - { /****************************may have bugs********************************/ - break; - } - } - ///means v is conflict - if(k != nv) - { - bi_g->seq[v].len = ISO; bi_g->seq[v].c = 1; - continue; - } - - - - ///if v is not conflict with others - for(k = 0; k < nv; k++) - { - w = av[k].v; - ///if the out-node has not been visited - if(bi_g->seq[w].len == UNVISIT) - { - bi_g->seq[w].len = 1 - bi_g->seq[v].len; - bi_g->seq[w].c = 1; - /****************************may have bugs********************************/ - len = (a.a[w]>>33); - /****************************may have bugs********************************/ - if(len < bi_graph_Len) continue; - kdq_push(uint32_t, buf, w); - } - ///here bi_g->seq[w].len might be ISO or another color - ///don't need to do anything here - } - } - } - - if(roundID == 0) - { - roundID = 1; - goto re_partition; - } - - - //secondary checking - // uint32_t a_color; - // kdq_size(buf) = 0; - // for (i = 0; i < bi_g->n_seq; i++) - // { - // /****************************may have bugs********************************/ - // len = (a.a[i]>>33); - // /****************************may have bugs********************************/ - // ///just check end contig - // if(bi_g->seq[i].len != UNVISIT || (a.a[i] & (uint64_t)(0x100000000)) == 0) continue; - - // v = i; - // nv = asg_arc_n(bi_g, v); - // av = asg_arc_a(bi_g, v); - // a_color = UNVISIT; - - // for(k = 0; k < nv; k++) - // { - // w = av[k].v; - // ///check all out-nodes that has already been colored - // if(bi_g->seq[w].len != UNVISIT) - // { - // ///if this is the first colored node - // if(a_color == UNVISIT) - // { - // a_color = bi_g->seq[w].len; - // }///if this is not - // else if(a_color != bi_g->seq[w].len) - // { - // a_color = ISO; - // bi_g->seq[v].len = ISO; - // break; - // } - // } - // } - - // if(a_color == ISO) continue; - // ///no colored out-node - // if(a_color == UNVISIT) - // { - // bi_g->seq[v].len = RED; - // } - // else - // { - // bi_g->seq[v].len = 1 - a_color; - // } - - - - - - // ///check if all reachable nodes are end-contig - // kdq_push(uint32_t, buf, i); - // while (kdq_size(buf) != 0) - // { - // v = *(kdq_pop(uint32_t, buf)); - // ///find a non-end contig - // if((a.a[v] & (uint64_t)(0x100000000)) == 0) - // { - // bi_g->seq[i].len = UNVISIT; - // kdq_size(buf) = 0; - // break; - // } - - // nv = asg_arc_n(bi_g, v); - // av = asg_arc_a(bi_g, v); - // for(k = 0; k < nv; k++) - // { - // w = av[k].v; - // ///if the out-node has not been visited - // if(bi_g->seq[w].len == UNVISIT) - // { - // bi_g->seq[v].len = LABLE; - // kdq_push(uint32_t, buf, w); - // } - // } - // } - - // for (v = 0; v < bi_g->n_seq; v++) - // { - // if(bi_g->seq[v].len == LABLE) bi_g->seq[v].len = UNVISIT; - // } - - // if(bi_g->seq[i].len == UNVISIT) - // { - // continue; - // } - - - - - - - // ///now all reachable nodes of i are end-contigs - // kdq_push(uint32_t, buf, i); - // while (kdq_size(buf) != 0) - // { - // ///each v here is the uncolored node in the first round - // v = *(kdq_pop(uint32_t, buf)); - // if(bi_g->seq[v].len == ISO) continue; - // nv = asg_arc_n(bi_g, v); - // av = asg_arc_a(bi_g, v); - - - // ///get all out-nodes of v - // for(k = 0; k < nv; k++) - // { - // w = av[k].v; - // if(bi_g->seq[w].len == bi_g->seq[v].len) - // { - // break; - // } - // } - // ///means v is conflict - // if(k != nv) - // { - // bi_g->seq[v].len = ISO; - // continue; - // } - - - - // ///if v is not conflict with others - // for(k = 0; k < nv; k++) - // { - // w = av[k].v; - // ///if the out-node has not been visited - // if(bi_g->seq[w].len == UNVISIT) - // { - // bi_g->seq[w].len = 1 - bi_g->seq[v].len; - // kdq_push(uint32_t, buf, w); - // } - // } - // } - // } - - kdq_destroy(uint32_t, buf); -} - - -void process_bi_graph(asg_t *bi_g) -{ - asg_cleanup(bi_g); - asg_arc_del_multi(bi_g); - bi_g->is_symm = 1; - uint32_t v, i, j; - for (v = 0; v < bi_g->n_seq; v++) - { - uint32_t nv = asg_arc_n(bi_g, v), nw, w; - asg_arc_t *av = asg_arc_a(bi_g, v), *aw; - for (i = 0; i < nv; ++i) - { - w = av[i].v; - if(w == v) - { - av[i].del = 1; - continue; - } - nw = asg_arc_n(bi_g, w); - aw = asg_arc_a(bi_g, w); - for (j = 0; j < nw; j++) - { - if(aw[j].v == v) break; - } - - if(j == nw) av[i].del = 1; - } - } - - asg_cleanup(bi_g); - - ///asg_symm(bi_g); -} - -inline void reset_visit_flag(uint8_t* visit, asg_t *read_g, R_to_U* ruIndex, uint32_t contigNum, -ma_hit_t_alloc* x) -{ - uint32_t k, rId, is_Unitig, Hap_cId; - - if(x->length*2 > contigNum) - { - memset(visit, 0, contigNum); - } - else - { - for (k = 0; k < x->length; k++) - { - rId = Get_tn(x->buffer[k]); - - if(read_g->seq[rId].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, rId, &rId, &is_Unitig); - if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; - } - - ///there are two cases: - ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id - ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 - get_R_to_U(ruIndex, rId, &Hap_cId, &is_Unitig); - if(is_Unitig == 0 || Hap_cId == (uint32_t)-1) continue; - ///here rId is the id of the read coming from the different haplotype - ///Hap_cId is the id of the corresponding contig (note here is the contig, instead of untig) - visit[Hap_cId] = 0; - } - } -} - -void debug_visit_flag(uint8_t* visit, uint32_t contigNum) -{ - uint32_t k; - for (k = 0; k < contigNum; k++) - { - if(visit[k] != 0) fprintf(stderr, "ERROR visit\n"); - } -} - - -uint32_t get_readSeq(ma_ug_t *ug, asg_t *read_g, kvec_t_u32_warp* x_vecs, uint64_t* cBeg, -buf_t* b_0, uint32_t cId) -{ - ma_utg_t* reads = NULL; - uint32_t beg, end, i, j, rId, xLen, uId, uOri; - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - uint64_t tmp; - - x_vecs->a.n = 0; - beg = (uint32_t)(cBeg[cId]); - b_0->b.n = 0; - get_unitig(ug->g, ug, beg, &end, &nodeLen, &baseLen, &max_stop_nodeLen, &max_stop_baseLen, 1, b_0); - xLen = cBeg[cId]>>33; - kv_resize(uint32_t, x_vecs->a, xLen); - - for (i = 0; i < b_0->b.n; i++) - { - uId = b_0->b.a[i]>>1; - uOri = b_0->b.a[i]&(uint32_t)1; - reads = &(ug->u.a[uId]); - for (j = 0; j < reads->n; j++) - { - if(uOri == 1) - { - rId = reads->a[reads->n - j - 1]>>33; - } - else - { - rId = reads->a[j]>>33; - } - - - tmp = rId<<1; - if(read_g->seq[rId].c == HAP_LABLE) - { - tmp = tmp | 1; - kv_push(uint32_t, x_vecs->a, tmp); - continue; - } - kv_push(uint32_t, x_vecs->a, tmp); - } - } - - - if(x_vecs->a.n != xLen) fprintf(stderr, "ERROR: different length\n"); - return xLen; -} - - -uint32_t inline retrieve_skip_overlaps(ma_hit_t_alloc* x, uint32_t target) -{ - if(x == NULL) return (uint32_t)-1; - - uint32_t i; - for (i = 0; i < x->length; i++) - { - if(Get_tn(x->buffer[i]) == target) - { - return i; - } - } - - return (uint32_t)-1; -} - -inline uint32_t check_duplicate(Hap_Align_warp* u_buffer, uint32_t x_pos, uint32_t y_pos) -{ - if(u_buffer->x.n == 0) return 0; - - int i = u_buffer->x.n; - for (i--; i >= 0; i--) - { - if(x_pos != (uint32_t)-1 && u_buffer->x.a[i].q_pos != x_pos) return 0; - if(y_pos != (uint32_t)-1 && u_buffer->x.a[i].t_pos == y_pos) - { - u_buffer->x.a[i].is_color++; - return 1; - } - } - - if(x_pos == (uint32_t)-1) fprintf(stderr, "ERROR: cannot found y\n"); - - return 0; -} - -///x_vecs->a.a[k]>>1 - -void get_hap_similarity(uint32_t* list, uint32_t Len, uint32_t target_uId, -ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, -double* Match, double* Total) -{ - #define CUTOFF_THRES 100 - uint32_t i, j, qn, tn, is_Unitig, uId, min_count = 0, max_count = 0, cutoff = 0;; - for (i = 0; i < Len; i++) - { - if(cutoff > CUTOFF_THRES) - { - max_count = 0; - min_count = Len; - } - qn = list[i]>>1; - if(reverse_sources[qn].length > 0) min_count++; - for (j = 0; j < reverse_sources[qn].length; j++) - { - tn = Get_tn(reverse_sources[qn].buffer[j]); - if(read_g->seq[tn].del == 1) - { - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - - - get_R_to_U(ruIndex, tn, &uId, &is_Unitig); - if(uId!=(uint32_t)-1 && is_Unitig == 1 && uId == target_uId) - { - max_count++; - break; - } - } - - //means no match - if(j == reverse_sources[qn].length) - { - cutoff++; - } - else - { - cutoff = 0; - } - } - - (*Match) = max_count; - (*Total) = min_count; -} -uint32_t calculate_hap_similarity(Hap_Align* p, uint32_t dir, uint32_t xCid, uint32_t yCid, -kvec_t_u32_warp* x_vecs, kvec_t_u32_warp* y_vecs, ma_hit_t_alloc* reverse_sources, -asg_t *read_g, R_to_U* ruIndex, float Hap_rate, uint32_t seedOcc) -{ - uint32_t max_count = 0, min_count = 0; - uint32_t xLen = x_vecs->a.n; - uint32_t yLen = y_vecs->a.n; - uint32_t xLeftBeg, xLeftLen, yLeftBeg, yLeftLen; - uint32_t xRightBeg, xRightLen, yRightBeg, yRightLen; - if(dir == 0) - { - xLeftBeg = 0; xLeftLen = p->q_pos; xRightBeg = p->q_pos; xRightLen = xLen - xRightBeg; - yLeftBeg = 0; yLeftLen = p->t_pos; yRightBeg = p->t_pos; yRightLen = yLen - yRightBeg; - } - else - { - xLeftBeg = 0; xLeftLen = p->q_pos; xRightBeg = p->q_pos; xRightLen = xLen - xRightBeg; - - yLeftBeg = p->t_pos + 1; yLeftLen = yLen - yLeftBeg; - yRightBeg = 0; yRightLen = p->t_pos + 1; - } - - - - max_count = seedOcc; - min_count = MIN(xLeftLen, yLeftLen) + MIN(xRightLen, yRightLen); - if(min_count == 0) return NON_PLOID; - if(max_count <= min_count*Hap_rate) return NON_PLOID; - - - - - - double xLeftMatch, xLeftTotal, yLeftMatch, yLeftTotal; - double xRightMatch, xRightTotal, yRightMatch, yRightTotal; - - get_hap_similarity(x_vecs->a.a+xLeftBeg, xLeftLen, yCid, reverse_sources, read_g, ruIndex, - &xLeftMatch, &xLeftTotal); - get_hap_similarity(y_vecs->a.a+yLeftBeg, yLeftLen, xCid, reverse_sources, read_g, ruIndex, - &yLeftMatch, &yLeftTotal); - - get_hap_similarity(x_vecs->a.a+xRightBeg, xRightLen, yCid, reverse_sources, read_g, ruIndex, - &xRightMatch, &xRightTotal); - get_hap_similarity(y_vecs->a.a+yRightBeg, yRightLen, xCid, reverse_sources, read_g, ruIndex, - &yRightMatch, &yRightTotal); - - max_count = min_count = 0; - if((xLeftMatch/xLeftTotal) >= (yLeftMatch/yLeftTotal)) - { - max_count += xLeftMatch; - min_count += xLeftTotal; - } - else - { - max_count += yLeftMatch; - min_count += yLeftTotal; - } - - if((xRightMatch/xRightTotal) >= (yRightMatch/yRightTotal)) - { - max_count += xRightMatch; - min_count += xRightTotal; - } - else - { - max_count += yRightMatch; - min_count += yRightTotal; - } - - if(min_count == 0) return NON_PLOID; - if(max_count > min_count*Hap_rate) return PLOID; - return NON_PLOID; -} - - -#define Hap_Align_Pos_key(a) ((((uint64_t)((a).q_pos))<<32)|((uint64_t)((a).t_pos))) -KRADIX_SORT_INIT(Hap_Align_Pos_sort, Hap_Align, Hap_Align_Pos_key, 8) - -#define Hap_Align_Weight_key(a) ((a).is_color) -KRADIX_SORT_INIT(Hap_Align_Weight_sort, Hap_Align, Hap_Align_Weight_key, member_size(Hap_Align, is_color)) - -inline uint32_t merge_hap_hits(Hap_Align_warp* u_buffer) -{ - if(u_buffer->x.n == 0) return 0; - - radix_sort_Hap_Align_Pos_sort(u_buffer->x.a, u_buffer->x.a + u_buffer->x.n); - uint32_t x_pos, x_pos_end, x_pos_beg; - int k, i, j, m; - - /** - for (i = 0; i < (int)u_buffer->x.n; i++) - { - fprintf(stderr, "****x: %u, y: %u, t_id: %u, is_color: %u\n", u_buffer->x.a[i].q_pos, u_buffer->x.a[i].t_pos, - u_buffer->x.a[i].t_id, u_buffer->x.a[i].is_color); - } - **/ - - i = u_buffer->x.n; i--; - x_pos = u_buffer->x.a[i].q_pos; - x_pos_end = i; - for (; i >= 0; i--) - { - k = i - 1; - if(k < 0) continue; - if(u_buffer->x.a[k].q_pos == u_buffer->x.a[i].q_pos && - u_buffer->x.a[k].t_pos+1 == u_buffer->x.a[i].t_pos) - { - u_buffer->x.a[k].is_color += u_buffer->x.a[i].is_color; - u_buffer->x.a[i].t_id = (uint32_t)-1; - } - - ///meet a new x_pos - if(u_buffer->x.a[k].q_pos != u_buffer->x.a[i].q_pos) - { - x_pos_beg = i; - for (m = x_pos_beg; m <= (int)x_pos_end; m++) - { - if(u_buffer->x.a[m].t_id == (uint32_t)-1) continue; - for (j = k; j >= 0; j--) - { - if(u_buffer->x.a[j].q_pos != x_pos - 1) break; - if(u_buffer->x.a[j].t_pos == u_buffer->x.a[m].t_pos || - u_buffer->x.a[j].t_pos == u_buffer->x.a[m].t_pos - 1) - { - u_buffer->x.a[j].is_color += u_buffer->x.a[m].is_color; - u_buffer->x.a[m].t_id = (uint32_t)-1; - break; - } - } - } - - x_pos = u_buffer->x.a[k].q_pos; - x_pos_end = k; - } - } - - - - - for (i = 0, m = 0; i < (int)u_buffer->x.n; i++) - { - if(u_buffer->x.a[i].t_id!=(uint32_t)-1) - { - u_buffer->x.a[m].is_color = u_buffer->x.a[i].is_color; - u_buffer->x.a[m].t_id = u_buffer->x.a[i].t_id; - u_buffer->x.a[m].q_pos = u_buffer->x.a[i].q_pos; - u_buffer->x.a[m].t_pos = u_buffer->x.a[i].t_pos; - m++; - } - } - - u_buffer->x.n = m; - - /** - for (i = 0; i < (int)u_buffer->x.n; i++) - { - fprintf(stderr, "####x: %u, y: %u, t_id: %u, is_color: %u\n", u_buffer->x.a[i].q_pos, u_buffer->x.a[i].t_pos, - u_buffer->x.a[i].t_id, u_buffer->x.a[i].is_color); - } - **/ - radix_sort_Hap_Align_Weight_sort(u_buffer->x.a, u_buffer->x.a + u_buffer->x.n); - return 0; -} - -void get_hap_alignment(ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* reverse_sources, -buf_t* b_0, R_to_U* ruIndex, uint32_t* position_index, uint64_t* vote_counting, uint8_t* visit, -kvec_t_u64_warp* u_vecs, Hap_Align_warp* u_buffer, kvec_t_u32_warp* x_vecs, kvec_t_u32_warp* y_vecs, -uint32_t cId, uint32_t contigNum, uint64_t* cBeg, float Hap_rate, asg_t *bi_g, uint32_t is_bi_edge) -{ - ma_utg_t* reads = NULL; - uint32_t beg, end, i, j, k, rId, Hap_cId, y_cId, y_offset, qn, self_offset, uId, uOri, is_Unitig, xLen, seedOcc; - uint64_t tmp; - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - memset(vote_counting, 0, sizeof(uint64_t)*contigNum); - memset(visit, 0, contigNum); - u_vecs->a.n = x_vecs->a.n = y_vecs->a.n = 0; - - beg = (uint32_t)(cBeg[cId]); - b_0->b.n = 0; - get_unitig(ug->g, ug, beg, &end, &nodeLen, &baseLen, &max_stop_nodeLen, &max_stop_baseLen, 1, b_0); - xLen = cBeg[cId]>>33; - kv_resize(uint32_t, x_vecs->a, xLen); - - for (i = 0, self_offset = 0; i < b_0->b.n; i++) - { - uId = b_0->b.a[i]>>1; - uOri = b_0->b.a[i]&(uint32_t)1; - reads = &(ug->u.a[uId]); - for (j = 0; j < reads->n; j++, self_offset++) - { - if(uOri == 1) - { - rId = reads->a[reads->n - j - 1]>>33; - } - else - { - rId = reads->a[j]>>33; - } - - - tmp = rId<<1; - if(read_g->seq[rId].c == HAP_LABLE) - { - tmp = tmp | 1; - kv_push(uint32_t, x_vecs->a, tmp); - continue; - } - kv_push(uint32_t, x_vecs->a, tmp); - - - /**********************for debug*************************/ - ///debug_visit_flag(visit, contigNum); - /**********************for debug*************************/ - - qn = rId; - for (k = 0; k < reverse_sources[qn].length; k++) - { - rId = Get_tn(reverse_sources[qn].buffer[k]); - - if(read_g->seq[rId].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, rId, &rId, &is_Unitig); - if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; - } - - ///there are two cases: - ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id - ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 - get_R_to_U(ruIndex, rId, &Hap_cId, &is_Unitig); - if(is_Unitig == 0 || Hap_cId == (uint32_t)-1) continue; - ///here rId is the id of the read coming from the different haplotype - ///Hap_cId is the id of the corresponding contig (note here is the contig, instead of untig) - if(visit[Hap_cId]!=0) continue; - visit[Hap_cId] = 1; - if(vote_counting[Hap_cId] < UINT64_MAX) vote_counting[Hap_cId]++; - } - - reset_visit_flag(visit, read_g, ruIndex, contigNum, &(reverse_sources[qn])); - } - } - - - u_vecs->a.n = 0; - for (i = 0; i < contigNum; i++) - { - if(i == cId) continue; - if(vote_counting[i] == 0) continue; - tmp = vote_counting[i]; tmp = tmp << 32; tmp = tmp | (uint64_t)i; - kv_push(uint64_t, u_vecs->a, tmp); - } - - if(u_vecs->a.n == 0) return; - - sort_kvec_t_u64_warp(u_vecs, 1); - - - ma_hit_t_alloc *x = NULL, *pre_x = NULL; - Hap_Align* p = NULL; - asg_arc_t *e = NULL; - ///scan from the weightest candidate - for (i = 0; i < u_vecs->a.n; i++) - { - Hap_cId = (uint32_t)u_vecs->a.a[i]; - get_readSeq(ug, read_g, y_vecs, cBeg, b_0, Hap_cId); - y_cId = Hap_cId; - seedOcc = u_vecs->a.a[i]>>32; - - if(debug_purge_dup) - { - if(cId == 53) - { - fprintf(stderr, "cId: %u, y_cId: %u, seedOcc: %u\n", cId, y_cId, seedOcc); - } - } - - u_buffer->x.n = 0; - for (k = 0; k < x_vecs->a.n; k++) - { - x = pre_x = NULL; - rId = x_vecs->a.a[k]>>1; - if(read_g->seq[rId].c == HAP_LABLE) continue; - x = &(reverse_sources[rId]); - - if(k >= 1) - { - rId = x_vecs->a.a[k-1]>>1; - if(read_g->seq[rId].c != HAP_LABLE) - { - pre_x = &(reverse_sources[rId]); - } - } - - - - - for (j = 0; j < x->length; j++) - { - rId = Get_tn(x->buffer[j]); - if(read_g->seq[rId].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, rId, &rId, &is_Unitig); - if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; - } - - ///there are two cases: - ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id - ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 - get_R_to_U(ruIndex, rId, &Hap_cId, &is_Unitig); - if(is_Unitig == 0 || Hap_cId == (uint32_t)-1) continue; - if(Hap_cId != y_cId) continue; - - y_offset = position_index[rId]; - ///if(retrieve_skip_overlaps(pre_x, rId) != (uint32_t)-1) - if(retrieve_skip_overlaps(pre_x, Get_tn(x->buffer[j])) != (uint32_t)-1) - { - check_duplicate(u_buffer, (uint32_t)-1, y_offset); - continue; - } - if(check_duplicate(u_buffer, k, y_offset)) continue; - - kv_pushp(Hap_Align, u_buffer->x, &p); - p->q_pos = k; - p->t_pos = y_offset; - p->t_id = y_cId; - p->is_color = 1; - } - } - - merge_hap_hits(u_buffer); - if(u_buffer->x.n == 0) continue; - - ///for (k = 0; k < u_buffer->x.n; k++) - for (k = u_buffer->x.n-1; k >= 0; k--) - { - if(calculate_hap_similarity(&(u_buffer->x.a[k]), 0, cId, y_cId, x_vecs, y_vecs, - reverse_sources, read_g, ruIndex, Hap_rate, seedOcc)==PLOID) - { - break; - } - else if(calculate_hap_similarity(&(u_buffer->x.a[k]), 1, cId, y_cId, x_vecs, y_vecs, - reverse_sources, read_g, ruIndex, Hap_rate, seedOcc)==PLOID) - { - break; - } - if(k == 0) - { - k = (uint32_t)-1; - break; - } - } - - ///if(k < u_buffer->x.n) - if(k != (uint32_t)-1) - { - e = asg_arc_pushp(bi_g); - e->del = 0; - e->ol = 0; - e->ul = cId; e->ul = e->ul << 32; e->ul = e->ul | (uint64_t)(0); - e->v = y_cId; - - if(is_bi_edge) - { - e = asg_arc_pushp(bi_g); - e->del = 0; - e->ol = 0; - e->ul = y_cId; e->ul = e->ul << 32; e->ul = e->ul | (uint64_t)(0); - e->v = cId; - } - } - } -} - -void print_gfa(asg_t *g) -{ - uint32_t v, i, n_vtx = g->n_seq * 2; - for (v = 0; v < n_vtx; v++) - { - if(g->seq[v>>1].del) - { - fprintf(stderr, "(D) v>>1: %u, v&1: %u, %.*s\n", v>>1, v&1, - (int)Get_NAME_LENGTH((R_INF), v>>1), Get_NAME((R_INF), v>>1)); - continue; - } - - fprintf(stderr, "(E) v>>1: %u, v&1: %u, %.*s\n", v>>1, v&1, - (int)Get_NAME_LENGTH((R_INF), v>>1), Get_NAME((R_INF), v>>1)); - - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - fprintf(stderr, "av[i].v: %u, av[i].ul: %u\n", - av[i].v, (uint32_t)(av[i].ul>>32)); - } - - } - -} - - - -void print_purge_gfa(asg_t *g, uint64_t* cCount) -{ - uint32_t v, i, n_vtx = g->n_seq, beg, end; - for (v = 0; v < n_vtx; v++) - { - if(g->seq[v>>1].del) - { - fprintf(stderr, "(D) v: %u, Len: %u, start>>1: %u, flag: %u\n", v, (uint32_t)(cCount[v]>>33), - ((uint32_t)cCount[v])>>1, g->seq[v].len); - continue; - } - - fprintf(stderr, "(E) v: %u, Len: %u, start>>1: %u, flag: %u\n", v, (uint32_t)(cCount[v]>>33), - ((uint32_t)cCount[v])>>1, g->seq[v].len); - - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - beg = av[i].ul>>32; - end = av[i].v; - - fprintf(stderr, "****beg: %u (Len: %u) ---> end: %u (Len: %u)\n", - beg, (uint32_t)(cCount[beg]>>33), - end, (uint32_t)(cCount[end]>>33)); - - } - - } - -} - -void calculate_peak(uint64_t* counts, long long len, kvec_t_u32_warp* a, -long long TotalMean, long long HapMean, long long* peak0, long long* peak1) -{ - if(len == 0) return; - long long i, j, total_coverage = 0, current_coverage, step, pre, after, is_found = 0; - for (i = 0; i < len; i++) - { - total_coverage = total_coverage + ((counts[i]>>32) * ((uint32_t)counts[i])); - } - current_coverage = total_coverage; - for (i = len - 1; i >= 0; i--) - { - current_coverage = current_coverage - ((counts[i]>>32) * ((uint32_t)counts[i])); - if(current_coverage <= total_coverage*0.9) break; - } - i++; - step = i*0.1; - if(step < 2) step = 2; - ///fprintf(stderr, "step: %lld\n", step); - - - a->a.n = 0; - ///for (i = 0; i < len; i++) - for (i = 1; i < len; i++) - { - pre = i - step/2; - after = i + step/2; - if(pre < 0) pre = 0; - if(after >= len) after = len - 1; - is_found = 0; - for (j = pre; j < after; j++) - { - if(j == i) continue; - if(((uint32_t)counts[i]) <= ((uint32_t)counts[j])) - { - is_found = 1; - break; - } - } - - if(is_found == 0) - { - kv_push(uint32_t, a->a, i); - } - } - - - - uint32_t peak_0_i, peak_1_i; - peak_0_i = peak_1_i = 0; - - for (i = 0; i < (long long)a->a.n; i++) - { - if(((uint32_t)counts[a->a.a[peak_0_i]]) < ((uint32_t)counts[a->a.a[i]])) - { - peak_0_i = i; - } - } - - peak_1_i = (uint32_t)-1; - for (i = 0; i < (long long)a->a.n; i++) - { - if(peak_0_i == i) continue; - if(peak_1_i == (uint32_t)-1) - { - peak_1_i = i; - continue; - } - if(((uint32_t)counts[a->a.a[peak_1_i]]) < ((uint32_t)counts[a->a.a[i]])) - { - peak_1_i = i; - } - } - - if(peak_0_i == peak_1_i) peak_1_i = (uint32_t)-1; - - - // for (i = 0; i < (long long)a->a.n; i++) - // { - // fprintf(stderr, "i:%lld, freq: %u, num: %u\n", i, - // (uint32_t)(counts[a->a.a[i]]>>32), (uint32_t)counts[a->a.a[i]]); - // } - // fprintf(stderr, "peak_0_i: %u, peak_1_i: %u\n", peak_0_i, peak_1_i); - - (*peak0) = (*peak1) = -1; - /** - * There are three cases: - * 1. very low het rate: don't need purge_dup - * 2. very high het rate: TotalMean should be equal to peak_0 - * 3. not such high het rate: two peaks, HapMean should be useful - * **/ - - if(peak_1_i == (uint32_t)-1) - { - (*peak0) = (uint32_t)(counts[a->a.a[peak_0_i]]>>32); - return; - } - - (*peak0) = (uint32_t)(counts[a->a.a[peak_0_i]]>>32); - (*peak1) = (uint32_t)(counts[a->a.a[peak_1_i]]>>32); - - - if(TotalMean >= (long long)((uint32_t)(counts[a->a.a[peak_0_i]]>>32)) && - TotalMean >= (long long)((uint32_t)(counts[a->a.a[peak_1_i]]>>32))) - { - (*peak1) = -1; - return; - } - - long long max_cov = MAX((*peak0), TotalMean); - long long min_cov = MIN((*peak0), TotalMean); - if(min_cov >= max_cov*0.8) - { - max_cov = MAX((*peak1), TotalMean); - min_cov = MIN((*peak1), TotalMean); - if(min_cov < max_cov*0.6) - { - (*peak1) = -1; - return; - } - } - - - long long hap_cov = ((uint32_t)(counts[a->a.a[MIN(peak_0_i, peak_1_i)]]>>32)); - max_cov = MAX(hap_cov, HapMean); - min_cov = MIN(hap_cov, HapMean); - ///fprintf(stderr, "hap_cov: %lld, max_cov: %lld, min_cov: %lld\n", hap_cov, max_cov, min_cov); - if(min_cov < max_cov*0.70) - { - (*peak1) = -1; - return; - } - - min_cov = MIN((*peak0), (*peak1)); - max_cov = MAX((*peak0), (*peak1)); - (*peak0) = min_cov; - (*peak1) = max_cov; -} - -void get_purge_coverage(asg_t *read_g, ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, -uint32_t* junk_cov, uint32_t* hap_cov, uint32_t* dip_cov) -{ - (*junk_cov) = (*hap_cov) = 0; (*dip_cov) = (uint32_t)-1; - uint32_t i, j, num, m; - long long R_bases = 0, C_bases = 0, T_R_bases = 0, T_C_bases = 0, total_coverage = 0, T_mean, Hap_mean; - ma_hit_t *h = NULL; - uint64_t* counts = (uint64_t*)calloc(read_g->n_seq, sizeof(uint64_t)); - kvec_t_u32_warp a; - kv_init(a.a); - - for (i = 0; i < read_g->n_seq; ++i) - { - R_bases = C_bases = 0; - R_bases += coverage_cut[i].e - coverage_cut[i].s; - for (j = 0; j < (uint64_t)(sources[i].length); j++) - { - h = &(sources[i].buffer[j]); - C_bases += Get_qe((*h)) - Get_qs((*h)); - } - if(R_bases == 0) continue; - - counts[i] = C_bases/R_bases; - T_R_bases += R_bases; - T_C_bases += C_bases; - total_coverage += counts[i]; - } - - T_mean = 0; - if(T_R_bases > 0) T_mean = T_C_bases/T_R_bases; - - radix_sort_arch64(counts, counts + read_g->n_seq); - - - uint64_t tmp; - i = m = 0; - while(i < read_g->n_seq) - { - num = 0; - for (j = i; j < read_g->n_seq; j++) - { - if(counts[i] != counts[j]) break; - num++; - } - - tmp = counts[i]; tmp = tmp << 32; tmp = tmp | (uint64_t)num; - counts[m] = tmp; - m++; - i = j; - } - - - R_bases = C_bases = 0; - for (i = 0; i < read_g->n_seq; ++i) - { - if(read_g->seq[i].c != HAP_LABLE) continue; - R_bases += coverage_cut[i].e - coverage_cut[i].s; - for (j = 0; j < (uint64_t)(sources[i].length); j++) - { - h = &(sources[i].buffer[j]); - C_bases += Get_qe((*h)) - Get_qs((*h)); - } - } - Hap_mean = 0; - if(R_bases > 0) Hap_mean = C_bases/R_bases; - - - - long long peak0, peak1; - calculate_peak(counts, m, &a, T_mean, Hap_mean, &peak0, &peak1); - - - // fprintf(stderr, "T_mean: %lld, Hap_mean: %lld, peak0: %lld, peak1: %lld\n", - // T_mean, Hap_mean, peak0, peak1); - - - (*junk_cov) = MIN(JUNK_COV, (peak0/2)); - if(peak1 == -1) - { - if(peak0 <= T_mean) - { - (*hap_cov) = peak0*1.5; - (*dip_cov) = peak0*4.5; - } - else - { - (*hap_cov) = peak0*1.2; - (*dip_cov) = peak0*3.6; - } - } - else - { - num = MAX(T_mean, (peak0+peak1)/2); - (*hap_cov) = num; - (*dip_cov) = num*3; - } - - free(counts); - kv_destroy(a.a); -} - - -uint32_t get_single_coverage(ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, uint32_t rId) -{ - long long R_bases = 0, C_bases = 0; - uint32_t j; - ma_hit_t *h = NULL; - - R_bases += coverage_cut[rId].e - coverage_cut[rId].s; - for (j = 0; j < (uint64_t)(sources[rId].length); j++) - { - h = &(sources[rId].buffer[j]); - C_bases += Get_qe((*h)) - Get_qs((*h)); - } - - if(R_bases == 0) return 0; - return (C_bases/R_bases); -} - -void print_node(asg_t* g, ma_ug_t *ug) -{ - int input_iv; - uint32_t iv, v; - asg_arc_t *av, *aw; - uint32_t nv, nw, i, k, w; - while (1) - { - fprintf(stderr, "\n\ninput v: "); - if(scanf("%d", &input_iv) == 0) break; - if(input_iv == -1) break; - iv = input_iv; - iv = iv << 1; - - v = iv; - av = asg_arc_a(g, v); - nv = asg_arc_n(g, v); - fprintf(stderr, "0**************v>>1: %u, v&1: %u, c: %u, del: %u, len: %u**************\n", - v>>1, v&1, (uint32_t)g->seq[v>>1].c, (uint32_t)g->seq[v>>1].del, g->seq[v>>1].len); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - w = av[i].v; - fprintf(stderr, "(%u) w>>1: %u, w&1: %u, ol: %u, eLen: %u\n", - i, w>>1, w&1, av[i].ol, (uint32_t)av[i].ul); - - - aw = asg_arc_a(g, w^1); - nw = asg_arc_n(g, w^1); - for (k = 0; k < nw; k++) - { - if(aw[k].del) continue; - if(aw[k].v == (v^1)) break; - } - - fprintf(stderr, "self>>1: %u, self&1: %u, out>>1: %u, out^1: %u, is_sym: %u\n", - (uint32_t)(av[i].ul>>33), (uint32_t)((av[i].ul>>32)&1), av[i].v>>1, av[i].v&1, - (uint32_t)(k != nw)); - - } - - - - - - - v = iv^1; - av = asg_arc_a(g, v); - nv = asg_arc_n(g, v); - fprintf(stderr, "1**************v>>1: %u, v&1: %u, c: %u, del: %u, len: %u**************\n", - v>>1, v&1, (uint32_t)g->seq[v>>1].c, (uint32_t)g->seq[v>>1].del, (uint32_t)g->seq[v>>1].len); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - w = av[i].v; - fprintf(stderr, "w>>1: %u, w&1: %u, ol: %u, eLen: %u\n", - w>>1, w&1, (uint32_t)av[i].ol, (uint32_t)av[i].ul); - - - aw = asg_arc_a(g, w^1); - nw = asg_arc_n(g, w^1); - for (k = 0; k < nw; k++) - { - if(aw[k].del) continue; - if(aw[k].v == (v^1)) break; - } - - fprintf(stderr, "self>>1: %u, self&1: %u, out>>1: %u, out^1: %u, is_sym: %u\n", - (uint32_t)(av[i].ul>>33), (uint32_t)((av[i].ul>>32)&1), av[i].v>>1, av[i].v&1, - (uint32_t)(k != nw)); - - } - - if(ug != NULL) - { - ma_utg_t *ma_v = &(ug->u.a[v>>1]); - fprintf(stderr, "\n###\nma_v->n: %u, ma_v->len: %u\n", ma_v->n, ma_v->len); - fprintf(stderr, "start>>1: %u, start&1: %u, end>>1: %u, end&1: %u\n", - ma_v->start>>1, ma_v->start&1, ma_v->end>>1, ma_v->end&1); - for (i = 0; i < ma_v->n; i++) - { - v = ma_v->a[i]>>32; - fprintf(stderr, "i: %u, v>>1: %u, v&1: %u, len: %u\n", - i, v>>1, v&1, (uint32_t)ma_v->a[i]); - } - - } - } -} - -/*************************************for tangle resolve*************************************/ - -void recover_edges(asg_t* nsg, kvec_t_u64_warp* edges, uint64_t* nodes, uint64_t n, -uint32_t beg, uint32_t end, uint32_t beg_c, uint32_t end_c, uint32_t is_recover_edges) -{ - uint32_t i, v; - asg_arc_t *a = NULL; - for (i = 0; i < n; i++) - { - v = (uint32_t)nodes[i]; - nsg->seq[v].del = 0; - nsg->seq[v].c = (nodes[i]>>32); - } - nsg->seq[beg>>1].c = beg_c; nsg->seq[beg>>1].del = 0; - nsg->seq[end>>1].c = end_c; nsg->seq[end>>1].del = 0; - - if(is_recover_edges) - { - for (i = 0; i < edges->a.n; i++) - { - a = &(nsg->arc[(uint32_t)edges->a.a[i]]); - a->del = 0; - } - } -} - -///note: nodes does not have directions -void save_all_edges(kvec_t_u64_warp* u_vecs, asg_t* nsg, uint64_t* nodes, uint64_t n, -uint32_t beg, uint32_t end, uint32_t* beg_c, uint32_t* end_c) -{ - uint32_t i, v, nv, k; - uint64_t tmp; - asg_arc_t *av = NULL; - u_vecs->a.n = 0; - - (*beg_c) = nsg->seq[beg>>1].c; - (*end_c) = nsg->seq[end>>1].c; - for (i = 0; i < n; i++) - { - v = (uint32_t)nodes[i]; - tmp = nsg->seq[v].c; tmp = tmp<<32; tmp = (tmp)|((uint64_t)v); - nodes[i] = tmp; - - if(nsg->seq[v].del) continue; - if(nsg->seq[v].c == ALTER_LABLE) continue; - - v = v<<1; - av = asg_arc_a(nsg, v); - nv = asg_arc_n(nsg, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - kv_push(uint64_t, u_vecs->a, (uint64_t)((uint64_t)av[k].ol << 32 | (av - nsg->arc + k))); - } - - - v = v^1; - av = asg_arc_a(nsg, v); - nv = asg_arc_n(nsg, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - kv_push(uint64_t, u_vecs->a, (uint64_t)((uint64_t)av[k].ol << 32 | (av - nsg->arc + k))); - } - } - - v = beg; - if((!nsg->seq[v>>1].del)&&(nsg->seq[v>>1].c!=ALTER_LABLE)) - { - av = asg_arc_a(nsg, v); - nv = asg_arc_n(nsg, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - for (i = 0; i < n; i++) - { - if((av[k].v>>1)==((uint32_t)nodes[i])) break; - } - if(i==n) continue; - kv_push(uint64_t, u_vecs->a, (uint64_t)((uint64_t)av[k].ol << 32 | (av - nsg->arc + k))); - } - } - - - - - v = end^1; - if((!nsg->seq[v>>1].del)&&(nsg->seq[v>>1].c!=ALTER_LABLE)) - { - av = asg_arc_a(nsg, v); - nv = asg_arc_n(nsg, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - for (i = 0; i < n; i++) - { - if((av[k].v>>1)==((uint32_t)nodes[i])) break; - } - if(i==n) continue; - kv_push(uint64_t, u_vecs->a, (uint64_t)((uint64_t)av[k].ol << 32 | (av - nsg->arc + k))); - } - } -} - -///beg and end have directions, while nodes does not have -int drop_tips_at_tangle(asg_t* nsg, uint64_t* nodes, uint64_t n, uint32_t beg, uint32_t end, -buf_t* bb) -{ - uint32_t i, v, k, m, convex, return_flag, next_tips = 1, reduce = 0; - long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; - - while(next_tips > 0) - { - next_tips = 0; - - for (i = 0; i < n; i++) - { - v = (uint32_t)nodes[i]; - if(nsg->seq[v].del) continue; - if(nsg->seq[v].c == ALTER_LABLE) continue; - v = v<<1; - - for (k = 0; k < 2; k++) - { - v = v|k; - if(get_real_length(nsg, v^1, NULL) != 0) continue; - - bb->b.n = 0; - return_flag = get_unitig(nsg, NULL, v, &convex, &ll, &tmp, &max_stop_nodeLen, - &max_stop_baseLen, 1, bb); - if(return_flag == LOOP) continue; - if(return_flag == MUL_OUTPUT) next_tips++; - - for(m = 0; m < bb->b.n; m++) - { - if(((bb->b.a[m]>>1)==(beg>>1)) || ((bb->b.a[m]>>1)==(end>>1))) break; - } - ///means this unitig consists of beg or end - if(m != bb->b.n) continue; - - for(m = 0; m < bb->b.n; m++) - { - nsg->seq[(bb->b.a[m]>>1)].c = ALTER_LABLE; - } - - for(m = 0; m < bb->b.n; m++) - { - asg_seq_drop(nsg, (bb->b.a[m]>>1)); - } - - reduce++; - } - } - } - - return reduce; -} - -///max_dist is ok, since tangle shouldn't be too large -int pop_bubble_at_tangle(ma_ug_t *ug, uint64_t max_dist, uint64_t* nodes, uint64_t n, uint32_t beg, uint32_t end, -uint32_t positive_flag, uint32_t negative_flag) -{ - asg_t *g = ug->g; - uint32_t i, v, k, n_vtx = g->n_seq*2; - uint64_t n_pop = 0; - buf_t b; - if (!g->is_symm) asg_symm(g); - memset(&b, 0, sizeof(buf_t)); - b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - - v = beg; - if((!g->seq[v>>1].del)&&(g->seq[v>>1].c!=ALTER_LABLE)&&get_real_length(g, v, NULL)>=2) - { - n_pop += asg_bub_pop1_primary_trio(ug->g, ug, v, max_dist, &b, positive_flag, negative_flag, 1, NULL, NULL, NULL, 0, 1, NULL); - } - - v = end^1; - if((!g->seq[v>>1].del)&&(g->seq[v>>1].c!=ALTER_LABLE)&&get_real_length(g, v, NULL)>=2) - { - n_pop += asg_bub_pop1_primary_trio(ug->g, ug, v, max_dist, &b, positive_flag, negative_flag, 1, NULL, NULL, NULL, 0, 1, NULL); - } - - - for (i = 0; i < n; i++) - { - v = (uint32_t)nodes[i]; - if(g->seq[v].del) continue; - if(g->seq[v].c == ALTER_LABLE) continue; - v = v<<1; - - for (k = 0; k < 2; k++) - { - v = v|k; - if(get_real_length(g, v, NULL)<=1) continue; - n_pop += asg_bub_pop1_primary_trio(ug->g, ug, v, max_dist, &b, positive_flag, negative_flag, 1, NULL, NULL, NULL, 0, 1, NULL); - } - } - - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - ///if (n_pop) asg_cleanup(g); - return n_pop; -} - - -int find_spec_node(asg_t *nsg, uint32_t vBeg, uint32_t vDest, uint32_t* forbidden_nodes, -uint32_t forbidden_nodes_n, long long max_nodes, buf_t* bb, uint8_t* visit, ma_ug_t *ug) -{ - uint32_t nv, un_visit; - asg_arc_t *av; - - memset(visit, 0, nsg->n_seq); - kdq_t(uint32_t) *buf; - buf = kdq_init(uint32_t); - - uint32_t vEnd, i, k, v, is_found = 0, return_flag; - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen, totalNodes = 0; - - bb->b.n = 0; - if(get_unitig(nsg, ug, vBeg, &vEnd, &nodeLen, &baseLen, - &max_stop_nodeLen, &max_stop_baseLen, 1, bb)==LOOP) - { - kdq_destroy(uint32_t, buf); - - for (i = 0; i < bb->b.n; i++) - { - if(bb->b.a[i] == vDest) break; - } - if(i != bb->b.n) return 1; - - return 0; - } - - - for (i = 0; i < bb->b.n; i++) - { - Set_vis(visit, bb->b.a[i], 0); - ///Set_vis(visit, bb->b.a[i]^1, 0); - } - - if(forbidden_nodes != NULL && forbidden_nodes_n != 0) - { - for (i = 0; i < forbidden_nodes_n; i++) - { - Set_vis(visit, forbidden_nodes[i], 0); - } - } - - - - v = vBeg; - kdq_push(uint32_t, buf, v); - - while (kdq_size(buf) != 0) - { - - v = *(kdq_pop(uint32_t, buf)); - - bb->b.n = 0; - return_flag = get_unitig(nsg, ug, v, &vEnd, &nodeLen, &baseLen, - &max_stop_nodeLen, &max_stop_baseLen, 1, bb); - - for (i = 0; i < bb->b.n; i++) - { - if(bb->b.a[i] == vDest) break; - } - - if(i != bb->b.n) - { - is_found = 1; - break; - } - - if(return_flag == LOOP) break; - - totalNodes += nodeLen; - if(totalNodes > max_nodes) break; - - v = vEnd; - nv = asg_arc_n(nsg, v); - av = asg_arc_a(nsg, v); - for(k = 0; k < nv; k++) - { - if(av[k].del) continue; - - if(Get_vis(visit,av[k].v, 0)!=0) continue; - - un_visit = 0; - bb->b.n = 0; - get_unitig(nsg, ug, av[k].v, &vEnd, &nodeLen, &baseLen, - &max_stop_nodeLen, &max_stop_baseLen, 1, bb); - for (i = 0; i < bb->b.n; i++) - { - if(Get_vis(visit, bb->b.a[i], 0) != 0) break; - } - if(i == bb->b.n) un_visit = 1; - - if(un_visit) - { - kdq_push(uint32_t, buf, av[k].v); - for (i = 0; i < bb->b.n; i++) - { - Set_vis(visit, bb->b.a[i], 0); - } - } - - } - } - - kdq_destroy(uint32_t, buf); - return is_found; -} - -int drop_useless_edges(ma_ug_t *ug, buf_t* bb, uint8_t* visit, uint32_t beg, uint32_t end, -uint64_t* nodes, uint64_t nodes_n, uint32_t NodesThres) -{ - asg_t *nsg = ug->g; - asg_arc_t *av = NULL; - uint32_t v, w, nv, i, k, dest, n_reduce = 0; - uint32_t reach_beg[2]; - uint32_t reach_end[2]; - reach_beg[0] = reach_beg[1] = reach_end[0] = reach_end[1] = 0; - - v = beg; dest = end; - if(get_real_length(nsg, v, NULL) > 1) - { - w = v^1; - av = asg_arc_a(nsg, v); - nv = asg_arc_n(nsg, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(find_spec_node(nsg, av[k].v, dest, &w, 1, NodesThres, bb, visit, ug) == 0) - { - // if(get_real_length(nsg, v, NULL)<=1) - // { - // fprintf(stderr, "false edge: beg: %u, end: %u\n", (uint32_t)(av[k].ul>>33), av[k].v>>1); - // } - - av[k].del = 1; - asg_arc_del(nsg, av[k].v^1, ((uint32_t)(av[k].ul>>32))^1, 1); - n_reduce++; - } - } - } - - - - v = end^1; dest = beg^1; - if(get_real_length(nsg, v, NULL) > 1) - { - w = v^1; - av = asg_arc_a(nsg, v); - nv = asg_arc_n(nsg, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(find_spec_node(nsg, av[k].v, dest, &w, 1, NodesThres, bb, visit, ug) == 0) - { - // if(get_real_length(nsg, v, NULL)<=1) - // { - // fprintf(stderr, "false edge: beg: %u, end: %u\n", (uint32_t)(av[k].ul>>33), av[k].v>>1); - // } - - av[k].del = 1; - asg_arc_del(nsg, av[k].v^1, ((uint32_t)(av[k].ul>>32))^1, 1); - n_reduce++; - } - } - } - - uint32_t drop_dest, forbid_dest, drop_node; - for (i = 0; i < nodes_n; i++) - { - v = (uint32_t)nodes[i]; - if(nsg->seq[v].del) continue; - if(nsg->seq[v].c == ALTER_LABLE) continue; - v = v<<1; - - for (k = 0; k < 2; k++) - { - v = v|k; - - w = end; - reach_beg[k] = find_spec_node(nsg, v, beg^1, &w, 1, NodesThres, bb, visit, ug); - w = beg^1; - reach_end[k] = find_spec_node(nsg, v, end, &w, 1, NodesThres, bb, visit, ug); - } - - if((reach_beg[0]+reach_end[0])==0 || (reach_beg[1]+reach_end[1])==0) continue; - - k = drop_dest = forbid_dest = (uint32_t)-1; - if((reach_beg[0]+reach_end[0])==1 && (reach_beg[1]+reach_end[1])>1) k = 0; - if((reach_beg[0]+reach_end[0])>1 && (reach_beg[1]+reach_end[1])==1) k = 1; - if(k == (uint32_t)-1) continue; - - drop_node = (uint32_t)nodes[i]; - drop_node = drop_node <<1; - drop_node = drop_node | (uint32_t)(1-k); - if(reach_beg[k]==1) - { - //drop_dest = beg^1; forbid_dest = end; - drop_dest = end; forbid_dest = beg^1; - } - - if(reach_end[k]==1) - { - //drop_dest = end; forbid_dest = beg^1; - drop_dest = beg^1; forbid_dest = end; - } - - if(drop_dest == (uint32_t)-1 || forbid_dest == (uint32_t)-1) continue; - - av = asg_arc_a(nsg, drop_node); - nv = asg_arc_n(nsg, drop_node); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(find_spec_node(nsg, av[k].v, drop_dest, &forbid_dest, 1, NodesThres, bb, visit, ug) == 0) - { - av[k].del = 1; - asg_arc_del(nsg, av[k].v^1, ((uint32_t)(av[k].ul>>32))^1, 1); - - // fprintf(stderr, "false inner edge: beg: %u, end: %u\n", - // (uint32_t)(av[k].ul>>33), av[k].v>>1); - - n_reduce++; - } - } - - } - - return n_reduce; -} - -int detec_circles(asg_t *nsg, uint32_t vSrc, uint32_t vDest, -uint8_t* visit, ma_ug_t *ug, uint64_t* nodes, uint64_t nodes_n) -{ - uint32_t nv, nw, knw, i, k, v, w; - asg_arc_t *av, *aw; - - memset(visit, 0, nsg->n_seq); - kdq_t(uint32_t) *buf; - buf = kdq_init(uint32_t); - - vDest = vDest^1; - - Set_vis(visit, vSrc, 1); - Set_vis(visit, vDest, 1); - kdq_push(uint32_t, buf, vSrc); - kdq_push(uint32_t, buf, vDest); - - for (i = 0; i < nodes_n; i++) - { - v = (uint32_t)nodes[i]; - if(nsg->seq[v].del) continue; - if(nsg->seq[v].c == ALTER_LABLE) continue; - v = v<<1; - - for (k = 0; k < 2; k++) - { - v = v|k; - if(get_real_length(nsg, v, NULL)==0) - { - Set_vis(visit, v, 1); - kdq_push(uint32_t, buf, v^1); - } - } - } - - - - while (kdq_size(buf) != 0) - { - v = *(kdq_pop(uint32_t, buf)); - ///if(Get_vis(visit, v, 1) == 0) fprintf(stderr, "ERROR\n"); - - nv = asg_arc_n(nsg, v); - av = asg_arc_a(nsg, v); - for(k = 0; k < nv; k++) - { - if(av[k].del) continue; - w = av[k].v^1; - if(nsg->seq[w>>1].del) continue; - if(Get_vis(visit, w, 1) != 0) continue; - - ///check indegree - nw = asg_arc_n(nsg, w); - aw = asg_arc_a(nsg, w); - for (i = 0, knw = 0; i < nw; i++) - { - if(aw[i].del) continue; - if(Get_vis(visit, aw[i].v, 1) != 0) continue; - knw++; - } - - if(knw == 0) - { - kdq_push(uint32_t, buf, w^1); - Set_vis(visit, (w^1), 1); - } - } - } - - for (i = 0; i < nodes_n; i++) - { - v = (uint32_t)nodes[i]; - if(nsg->seq[v].del) continue; - if(nsg->seq[v].c == ALTER_LABLE) continue; - v = v<<1; - if(Get_vis(visit, v, 1) == 0) return 1; - } - - return 0; -} - -inline void check_connective(asg_t *nsg, uint32_t vBeg, uint32_t vEnd, long long totalNodeLen, buf_t* bb, -uint8_t* visit, ma_ug_t *ug, uint64_t* nodes, uint64_t nodes_n, uint32_t* is_connect, -uint32_t* is_circle) -{ - uint32_t w; - (*is_connect) = (*is_circle) = 0; - - w = vBeg^1; - (*is_connect) = find_spec_node(nsg, vBeg, vEnd, &w, 1, totalNodeLen, bb, visit, ug); - (*is_circle) = detec_circles(nsg, vBeg, vEnd, visit, ug, nodes, nodes_n); -} - - -inline uint32_t process_tangles(ma_ug_t *ug, uint64_t* nodes, uint64_t nodes_n, uint32_t beg, uint32_t end, -buf_t* bb, uint8_t* visit, uint32_t trio_flag, long long totalNodeLen, long long totalBaseLen) -{ - uint32_t n_reduce = 1, v, w, kv, is_found = 0; - asg_t* nsg = ug->g; - - while (n_reduce != 0) - { - while (n_reduce != 0) - { - n_reduce = 0; - n_reduce += drop_tips_at_tangle(nsg, nodes, nodes_n, beg, end, bb); - n_reduce += pop_bubble_at_tangle(ug, totalBaseLen, nodes, nodes_n, beg, end, trio_flag, DROP); - } - n_reduce = drop_useless_edges(ug, bb, visit, beg, end, nodes, nodes_n, totalNodeLen); - } - // if(pop_bubble_at_tangle(ug, 10000000, nodes, nodes_n, beg, end, trio_flag, DROP)!=0) - // { - // fprintf(stderr, "false bubble popping: beg: %u, end: %u\n", beg>>1, end>>1); - // } - - v = beg; - is_found = 0; - while (1) - { - if(v == end) is_found = 1; - if(is_found == 1) break; - - kv = get_real_length(nsg, v, NULL); - if(kv!=1) break; - kv = get_real_length(nsg, v, &w); - if(get_real_length(nsg, w^1, NULL)!=1) break; - - v = w; - if(v == beg) break; - } - return is_found; -} - -uint32_t cut_edges_progressive(ma_ug_t *ug, kvec_t_u64_warp* edges, float drop_ratio, -uint64_t* nodes, uint64_t nodes_n, uint32_t beg, uint32_t end, buf_t* bb, uint8_t* visit, -uint32_t trio_flag, long long totalNodeLen, long long totalBaseLen, uint32_t max_arc_n) -{ - uint32_t k, v, i, kv, w, nv, ov_max, ban, is_found = 0; - asg_arc_t *a = NULL, *av = NULL; - asg_t* nsg = ug->g; - radix_sort_arch64(edges->a.a, edges->a.a + edges->a.n); - for (k = 0; k < edges->a.n && k < max_arc_n; k++) - { - a = &nsg->arc[(uint32_t)edges->a.a[k]]; - if(a->del) continue; - v = (a->ul)>>32; w = a->v; - if(nsg->seq[v>>1].del || nsg->seq[v>>1].c == ALTER_LABLE) continue; - if(nsg->seq[w>>1].del || nsg->seq[w>>1].c == ALTER_LABLE) continue; - - nv = asg_arc_n(nsg, v); - if(nv<=1) continue; - - ov_max = 0; - av = asg_arc_a(nsg, v); - for(i = 0, kv = 0; i < nv; ++i) - { - if(av[i].del) continue; - if(ov_max < av[i].ol) ov_max = av[i].ol; - ++kv; - } - - if(kv<=1) continue; - if(a->ol > ov_max * drop_ratio) continue; - asg_arc_del(nsg, v, w, 1); - asg_arc_del(nsg, w^1, v^1, 1); - - ban = beg^1; - if(find_spec_node(nsg, beg, end, &ban, 1, totalNodeLen, bb, visit, ug) == 0) - { - is_found = 0; - asg_arc_del(nsg, v, w, 0); - asg_arc_del(nsg, w^1, v^1, 0); - break; - } - - is_found = process_tangles(ug, nodes, nodes_n, beg, end, bb, visit, trio_flag, totalNodeLen, - totalBaseLen); - if(is_found == 1) break; - } - - return is_found; -} - -///1. drop tips 2. break edges 3. drop tips 4. do bubble popping -///beg and end have direction, but nsu->a doesn't have -///note here we do everything on src, instead of ug -void unroll_tangle(ma_ug_t *ug, ma_ug_t *length_ug, uint64_t* nodes, uint64_t nodes_n, -uint32_t beg, uint32_t end, kvec_t_u64_warp* edges, uint32_t trio_flag, buf_t* bb, uint8_t* visit, -float drop_ratio) -{ - uint32_t v, w, is_found = 0, convex, i, beg_c, end_c; - long long tmp, max_stop_nodeLen, max_stop_baseLen, begLen, endLen, missLen; - long long totalNodeLen = 0, totalBaseLen = 0; - asg_t* nsg = ug->g; - edges->a.n = 0; - save_all_edges(edges, nsg, nodes, nodes_n, beg, end, &beg_c, &end_c); - - - for (i = 0; i < nodes_n; i++) - { - v = (uint32_t)nodes[i]; - totalNodeLen += ug->u.a[v].n; - totalBaseLen += ug->g->seq[v].len; - } - totalNodeLen += ug->u.a[beg>>1].n + ug->u.a[end>>1].n + 1; - totalBaseLen += ug->g->seq[beg>>1].len + ug->g->seq[end>>1].len + 1; - ///each might be visited twice - totalNodeLen = totalNodeLen * 2; - totalBaseLen = totalBaseLen * 2; - - /**************************debug**************************/ - // uint32_t debug_is_access = 0, debug_is_circle = 0; - // check_connective(nsg, beg, end, totalNodeLen, bb, visit, ug, nodes, nodes_n, &debug_is_access, - // &debug_is_circle); - // if(debug_is_access==0) fprintf(stderr, "Cannot approch end: beg: %u, end: %u\n", beg>>1, end>>1); - // if(debug_is_circle==0) fprintf(stderr, "Not circle: beg: %u, end: %u\n", beg>>1, end>>1); - // if(debug_is_circle==1) fprintf(stderr, "Circle: beg: %u, end: %u\n", beg>>1, end>>1); - /**************************debug**************************/ - is_found = process_tangles(ug, nodes, nodes_n, beg, end, bb, visit, trio_flag, totalNodeLen, - totalBaseLen); - ///if(is_found == 1) fprintf(stderr, "***Found: beg>>1: %u, end>>1: %u\n", beg>>1, end>>1); - - if(is_found == 0) - { - is_found = cut_edges_progressive(ug, edges, drop_ratio, nodes, nodes_n, - beg, end, bb, visit, trio_flag, totalNodeLen, totalBaseLen, 48); - - ///if(is_found == 1) fprintf(stderr, "***Cutting Found: beg>>1: %u, end>>1: %u\n", beg>>1, end>>1); - } - - if(is_found == 1) - { - get_unitig(length_ug->g, length_ug, beg^1, &convex, &begLen, &tmp, &max_stop_nodeLen, - &max_stop_baseLen, 1, NULL); - - get_unitig(length_ug->g, length_ug, end, &convex, &endLen, &tmp, &max_stop_nodeLen, - &max_stop_baseLen, 1, NULL); - - - missLen = 0; - for (i = 0; i < nodes_n; i++) - { - v = (uint32_t)nodes[i]; - if(nsg->seq[v].del || nsg->seq[v].c == ALTER_LABLE) - { - missLen += ug->u.a[v].n; - } - } - ///resolved! - if(missLen <= (begLen+endLen)*TANGLE_MISSED_THRES) - { - is_found = 0; - w = beg^1; - is_found = find_spec_node(nsg, beg, end, &w, 1, totalNodeLen, bb, visit, ug); - } - else - { - is_found = 0; - } - } - - recover_edges(nsg, edges, nodes, nodes_n, beg, end, beg_c, end_c, 1-is_found); -} - -void resolve_tangles(ma_ug_t *src, asg_t *read_g, ma_hit_t_alloc* reverse_sources, long long minLongUntig, -long long maxShortUntig, float l_untig_rate, float max_node_threshold, R_to_U* ruIndex, uint8_t* is_r_het, -uint32_t trio_flag, float drop_ratio) -{ - buf_t b_0, b_1; - memset(&b_0, 0, sizeof(buf_t)); - memset(&b_1, 0, sizeof(buf_t)); - uint32_t i, v, w, sv, n_vtx, beg, end, next_uID = (uint32_t)-1; - kvec_t_u32_warp u_vecs; - kv_init(u_vecs.a); - - kvec_t_u64_warp e_vecs; - kv_init(e_vecs.a); - - ///note: we must reset start for each unitig - n_vtx = src->g->n_seq; - for (v = 0; v < n_vtx; ++v) - { - if(src->g->seq[v].del) continue; - if(src->u.a[v].m==0) continue; - EvaluateLen(src->u, v) = src->u.a[v].n; - } - - ma_ug_t *ug = NULL; - ug = copy_untig_graph(src); - - asg_t* nsg = ug->g; - n_vtx = nsg->n_seq; - for (v = 0; v < n_vtx; ++v) - { - ///nsg->seq[v].c = PRIMARY_LABLE; - EvaluateLen(ug->u, v) = ug->u.a[v].n; - IsMerge(ug->u, v) = 0; - } - - uint8_t* visit = NULL; - visit = (uint8_t*)malloc(sizeof(uint8_t) * nsg->n_seq); - uint32_t n_reduce, flag, dbg_round = 0; - n_vtx = nsg->n_seq * 2; - while (1) - { - n_reduce = 0; - for (v = 0; v < n_vtx; ++v) - { - //as for return value: 0: do nothing, 1: unroll, 2: convex - //we just need 1 - sv = v; - flag = 0; - while (1) - { - flag = walk_through(read_g, ug, reverse_sources, minLongUntig, - maxShortUntig, l_untig_rate, max_node_threshold, &b_0, &b_1, - &u_vecs, visit, sv, &beg, &end, &next_uID, ruIndex, is_r_het); - n_reduce += flag; - if(flag != UNROLL_M) - { - break; - } - } - } - if(n_reduce == 0) break; - dbg_round++; - } - asg_cleanup(nsg); - asg_symm(nsg); - - uint32_t uId, rId, is_Unitig, m, pre; - ma_utg_t* nsu = NULL; - for (v = 0; v < src->g->n_seq; v++) - { - uId = v; - nsu = &(src->u.a[v]); - if(nsu->m == 0) continue; - if(src->g->seq[v].del) continue; - for (i = 0; i < nsu->n; i++) - { - rId = nsu->a[i]>>33; - ///ori = nsu->a[k]>>32&1; - set_R_to_U(ruIndex, rId, uId, 1, &(read_g->seq[rId].c)); - } - } - - n_vtx = nsg->n_seq; - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - nsu = &(ug->u.a[v]); - m = 0; - pre = (uint32_t)(-1); - for (i = 0; i < nsu->n; i++) - { - rId = nsu->a[i]>>33; - get_R_to_U(ruIndex, rId, &uId, &is_Unitig); - if(is_Unitig != 1 || uId == ((uint32_t)(-1))) continue; - if(i > 0 && pre == uId) continue; - pre = uId; - nsu->a[m] = uId; - m++; - } - nsu->n = m; - } - n_vtx = nsg->n_seq; - for (i = 0; i < n_vtx; ++i) - { - v = i; - nsu = &(ug->u.a[v]); - if(nsg->seq[v].del) continue; - if(IsMerge(ug->u, v) == 0) continue; - if(nsg->seq[v].c == ALTER_LABLE) continue; - - v = v<<1; - if(get_real_length(nsg, v, NULL) != 1) continue; - get_real_length(nsg, v, &w); - if(get_real_length(nsg, w^1, NULL) != 1) continue; - if(IsMerge(ug->u, w>>1) != 0) continue; - beg = w^1; - - - v = v^1; - if(get_real_length(nsg, v, NULL) != 1) continue; - get_real_length(nsg, v, &w); - if(get_real_length(nsg, w^1, NULL) != 1) continue; - if(IsMerge(ug->u, w>>1) != 0) continue; - end = w; - ///we have three types of merged nodes - ///1) CONVEX_M: one direction has two out-nodes, another direction has one out-node - ///2) UNROLL_E: one direction has one out-node, another direction doesn't has out-node - ///3) UNROLL_M: both directions have one out-node - ///here we just need UNROLL_M - ///beg and end must be unchanged in src - unroll_tangle(src, ug, nsu->a, nsu->n, beg, end, &e_vecs, trio_flag, &b_0, visit, drop_ratio); - } - - for (v = 0; v < ruIndex->len; v++) - { - get_R_to_U(ruIndex, v, &uId, &is_Unitig); - if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; - } - kv_destroy(u_vecs.a); - kv_destroy(e_vecs.a); - - ma_ug_destroy(ug); - free(visit); - free(b_0.b.a); - free(b_1.b.a); - - - ///note: we must reset start for each unitig - n_vtx = src->g->n_seq; - for (v = 0; v < n_vtx; ++v) - { - if(src->g->seq[v].del) continue; - if(src->u.a[v].m==0) continue; - EvaluateLen(src->u, v) = src->u.a[v].n; - } - ///print_untig_by_read(src, "m64076_200203_181219/82511682/ccs", 2429597, NULL, NULL, "end-1"); -} - - -/*************************************for tangle resolve*************************************/ - -uint32_t copy_ug_node(ma_ug_t *ug, asg_t* nsg, uint32_t v) -{ - ma_utg_t *p; - ma_utg_t *o = &(ug->u.a[v]); - uint32_t n_node = nsg->n_seq; - asg_seq_set(nsg, n_node, nsg->seq[v].len, 0); - kv_pushp(ma_utg_t, ug->u, &p); - - p->s = 0, p->start = o->start, p->end = o->end, p->len = o->len; - p->n = o->n, p->circ = o->circ, p->m = o->m; - p->a = (uint64_t*)malloc(8 * p->m); - memcpy(p->a, o->a, (8*p->m)); - - return n_node; -} - - -///v and w here have directions -uint32_t collect_ma_utg_ts(ma_ug_t *ug, uint32_t v, uint32_t w, ma_utg_t* result) -{ - uint32_t des_dir = w&1; - long long i; - uint64_t* aim = NULL; - ma_utg_t *ma_w = &(ug->u.a[w>>1]); - - if(v == (uint32_t)-1) - { - result->start = ma_w->start; - result->circ = ma_w->circ; - result->end = ma_w->end; - result->len = ma_w->len; - result->n = 0; - } - - - if(result->m < (result->n + ma_w->n)) - { - result->m = (result->n + ma_w->n); - result->a = (uint64_t*)realloc(result->a, result->m * sizeof(uint64_t)); - } - - aim = result->a + result->n; - - if(des_dir == 1) - { - for (i = 0; i < (long long)ma_w->n; i++) - { - aim[ma_w->n - i - 1] = (ma_w->a[i])^(uint64_t)(0x100000000); - } - } - else - { - for (i = 0; i < (long long)ma_w->n; i++) - { - aim[i] = ma_w->a[i]; - } - } - - result->n = result->n + ma_w->n; - return 1; -} - - -void debug_utg_graph(ma_ug_t *ug, asg_t* read_g, kvec_asg_arc_t_warp* edge, int require_equal_nv, int test_tangle) -{ - asg_t* nsg = ug->g; - uint32_t n_vtx = nsg->n_seq, i, j, k, l, totalLen, v, nv, nw, w, untig_v, rid_v; - asg_arc_t *aw = NULL, *av = NULL, *t_v = NULL, *t_w = NULL; - for (i = 0; i < n_vtx; i++) - { - if(ug->g->seq[i].del) continue; - - totalLen = 0; - ma_utg_t* result = &(ug->u.a[i]); - if(result->n == 0) continue; - v = (uint64_t)(result->a[0])>>32; - if(result->start != UINT32_MAX && result->start != v) fprintf(stderr, "hehe\n"); - v = (uint64_t)(result->a[result->n-1])>>32; - if(result->end != UINT32_MAX && result->end != (v^1)) fprintf(stderr, "haha\n"); - uint64_t end_index = result->n-1; - if(result->start == UINT32_MAX && result->end == UINT32_MAX) end_index++; - for (j = 0; j < end_index; j++) - { - v = (uint64_t)(result->a[j])>>32; - if(j == result->n-1) - { - w = (uint64_t)(result->a[0])>>32; - } - else - { - w = (uint64_t)(result->a[j+1])>>32; - } - - - - av = asg_arc_a(read_g, v); - nv = asg_arc_n(read_g, v); - l = (uint32_t)-1; - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - l = asg_arc_len(av[k]); - break; - } - } - - if(edge && k == nv) - { - for (k = 0; k < edge->a.n; k++) - { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) - { - l = asg_arc_len(edge->a.a[k]); - k = nv + 1; - break; - } - } - } - - if(k == nv) fprintf(stderr ,"******error, j: %u, k: %u, nv: %u\n", j, k, nv); - if(l != (uint32_t)(result->a[j])) - { - fprintf(stderr ,"(i: %u) ERROR Length, l: %u, result->a[j]: %u, j: %u, k: %u, nv: %u, circ: %u, result->n: %u\n", - i, l, (uint32_t)(result->a[j]), j, k, nv, result->circ, (uint32_t)result->n); - } - - totalLen = totalLen + l; - } - - - if(j < result->n) - { - v = (uint64_t)(result->a[j])>>32; - l = read_g->seq[v>>1].len; - if(l != (uint32_t)(result->a[j])) fprintf(stderr ,"*** ERROR Length, i: %u\n", i); - totalLen = totalLen + l; - } - - if(totalLen != result->len) - { - fprintf(stderr ,"ERROR Total Length, i: %u\n", i); - } - - - - if(ug->u.a[i].start == UINT32_MAX && ug->u.a[i].end == UINT32_MAX) continue; - - v = i<<1; v=v^1; - av = asg_arc_a(ug->g, v); - nv = asg_arc_n(ug->g, v); - - w = (ug->u.a[v>>1].start^1); - aw = asg_arc_a(read_g, w); - nw = asg_arc_n(read_g, w); - - - if(require_equal_nv && get_real_length(ug->g, v, NULL) != get_real_length(read_g, w, NULL)) - { - fprintf(stderr, "#########ERROR: i: %u, nv: %u, nw: %u\n", i, nv, nw); - } - - for (j = 0; j < nv; j++) - { - if(av[j].del) continue; - untig_v = av[j].v; - if(untig_v&1) rid_v = ug->u.a[untig_v>>1].end; - else rid_v = ug->u.a[untig_v>>1].start; - - t_v = t_w = NULL; - for (k = 0; k < nw; k++) - { - if(aw[k].del) continue; - if(aw[k].v == rid_v) - { - t_w = &(aw[k]); - break; - } - - } - - if(edge && t_w == NULL) - { - for (k = 0; k < edge->a.n; k++) - { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == w && edge->a.a[k].v == rid_v) - { - t_w = &(edge->a.a[k]); - break; - } - } - } - - if(t_w == NULL) fprintf(stderr, "#########ERROR: i: %u\n", i); - t_v = &av[j]; - if(t_w && (t_v->ol != t_w->ol)) - { - fprintf(stderr, "#########????????ERROR\n"); - fprintf(stderr, "nv: %u, nw: %u\n", nv, nw); - fprintf(stderr, "av[%u].ol: %u, aw[%u].ol: %u, untig_v>>1: %u, untig_v&1: %u\n", - j, t_v->ol, k, t_w->ol, untig_v>>1, untig_v&1); - } - } - - - - - - - v = v^1; - av = asg_arc_a(ug->g, v); - nv = asg_arc_n(ug->g, v); - - w = (ug->u.a[v>>1].end^1); - aw = asg_arc_a(read_g, w); - nw = asg_arc_n(read_g, w); - if(require_equal_nv && get_real_length(ug->g, v, NULL) != get_real_length(read_g, w, NULL)) - { - fprintf(stderr, "*******ERROR: i: %u, nv: %u, nw: %u\n", i, nv, nw); - } - for (j = 0; j < nv; j++) - { - if(av[j].del) continue; - untig_v = av[j].v; - if(untig_v&1) rid_v = ug->u.a[untig_v>>1].end; - else rid_v = ug->u.a[untig_v>>1].start; - - t_v = t_w = NULL; - for (k = 0; k < nw; k++) - { - if(aw[k].del) continue; - if(aw[k].v == rid_v) - { - t_w = &(aw[k]); - break; - } - - } - - if(edge && t_w == NULL) - { - for (k = 0; k < edge->a.n; k++) - { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == w && edge->a.a[k].v == rid_v) - { - t_w = &(edge->a.a[k]); - break; - } - } - } - - if(t_w == NULL) fprintf(stderr, "#########ERROR: i: %u\n", i); - t_v = &av[j]; - if(t_w && (t_v->ol != t_w->ol)) - { - fprintf(stderr, "#########????????ERROR\n"); - fprintf(stderr, "nv: %u, nw: %u\n", nv, nw); - fprintf(stderr, "av[%u].ol: %u, aw[%u].ol: %u, untig_v>>1: %u, untig_v&1: %u\n", - j, t_v->ol, k, t_w->ol, untig_v>>1, untig_v&1); - } - } - - } - - - if(test_tangle != 1) return; - fprintf(stderr, "test_tangle: %u\n", test_tangle); - n_vtx = nsg->n_seq * 2; - for (v = 0; v < n_vtx; ++v) - { - uint32_t w1, w2, beg, end, rnw; - if(nsg->seq[v>>1].del) continue; - if(asg_arc_n(nsg, v) < 1 || asg_arc_n(nsg, v^1) < 1) continue; - if(get_real_length(nsg, v, NULL) != 1 || get_real_length(nsg, v^1, NULL) != 1) continue; - get_real_length(nsg, v, &w1); get_real_length(nsg, v^1, &w2); - - ///for simple circle - if(w1 == (w2^1)) - { - beg = end = 0; - aw = asg_arc_a(nsg, w1^1); - nw = asg_arc_n(nsg, w1^1); - for (i = 0, rnw = 0; i < nw; i++) - { - if(aw[i].del) continue; - rnw++; - if(aw[i].v == (v^1)) continue; - beg = aw[i].v; - } - if(rnw != 2) continue; - - aw = asg_arc_a(nsg, w2^1); - nw = asg_arc_n(nsg, w2^1); - for (i = 0, rnw = 0; i < nw; i++) - { - if(aw[i].del) continue; - rnw++; - if(aw[i].v == v) continue; - end = aw[i].v; - } - if(rnw != 2) continue; - - if(get_real_length(nsg, beg^1, NULL)!=1) continue; - if(get_real_length(nsg, end^1, NULL)!=1) continue; - if((beg>>1) == (end>>1)) continue; - fprintf(stderr, "\n************\n"); - } - else if(w1 == w2) - { - if(get_real_length(nsg, w1^1, NULL) != 2) continue; - if(get_real_length(nsg, w1, NULL) != 2) continue; - end = beg = (uint32_t)-1; - - aw = asg_arc_a(nsg, w1); - nw = asg_arc_n(nsg, w1); - for (i = 0, rnw = 0; i < nw && rnw < 2; i++) - { - if(aw[i].del) continue; - if(rnw == 0) beg = aw[i].v; - if(rnw == 1) end = aw[i].v; - rnw++; - } - if((beg>>1) == (end>>1)) continue; - if(get_real_length(nsg, beg^1, NULL)!=1) continue; - if(get_real_length(nsg, end^1, NULL)!=1) continue; - fprintf(stderr, "\n#################\n"); - } - } -} - -///just merge, don't delete anything -void merge_ug_nodes(ma_ug_t *ug, asg_t* read_g, kvec_t_u64_warp* array) -{ - if(array->a.n == 0) return; - uint32_t i, k, v, w; - ma_utg_t result; - memset(&result, 0, sizeof(ma_utg_t)); - v = w = (uint32_t)-1; - for (i = 0; i < array->a.n; i++) - { - w = array->a.a[i]; - collect_ma_utg_ts(ug, v, w, &result); - v = w; - } - - - - if(result.n == 0) return; - asg_arc_t *av = NULL; - uint32_t nv, l; - result.len = 0; - for (i = 0; i < result.n - 1; i++) - { - - v = (uint64_t)(result.a[i])>>32; - w = (uint64_t)(result.a[i + 1])>>32; - av = asg_arc_a(read_g, v); - nv = asg_arc_n(read_g, v); - l = 0; - - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - l = asg_arc_len(av[k]); - break; - } - } - if(k == nv) fprintf(stderr ,"******error, i: %u, k: %u, nv: %u\n", i, k, nv); - result.a[i] = v; result.a[i] = result.a[i]<<32; result.a[i] = result.a[i] | (uint64_t)(l); - result.len += l; - } - - - if(i < result.n) - { - v = (uint64_t)(result.a[i])>>32; - l = read_g->seq[v>>1].len; - result.a[i] = v; - result.a[i] = result.a[i]<<32; - result.a[i] = result.a[i] | (uint64_t)(l); - result.len += l; - } - //has already set result.a, result.len, result.n, result.m - result.circ = 0; - result.start = result.a[0]>>32; - result.end = (result.a[result.n-1]>>32)^1; - - - uint32_t beg_uid = array->a.a[0]; - uint32_t end_uid = array->a.a[array->a.n-1]; - uint32_t realLen = array->a.n; - uint32_t new_uid = array->a.a[0]>>1; - uint64_t kmp; - - - - - - /*******************************just for debug**********************************/ - /** - if(beg_uid&1) - { - if(result.start != ug->u.a[beg_uid>>1].end) - { - fprintf(stderr, "ERROR\n"); - } - } - else - { - if(result.start != ug->u.a[beg_uid>>1].start) - { - fprintf(stderr, "ERROR\n"); - } - } - - if(end_uid&1) - { - if(result.end != ug->u.a[end_uid>>1].start) - { - fprintf(stderr, "ERROR\n"); - } - } - else - { - if(result.end != ug->u.a[end_uid>>1].end) - { - fprintf(stderr, "ERROR\n"); - } - } - **/ - /*******************************just for debug**********************************/ - - asg_arc_t *aw = NULL; - uint32_t nw = 0; - ///corresponding to direction 1 of new node - v = beg_uid^1; - av = asg_arc_a(ug->g, v); - nv = asg_arc_n(ug->g, v); - ///fprintf(stderr, "beg_uid_v>>1: %u, beg_uid_v&1: %u, nv: %u\n", v>>1, v&1, nv); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - kmp = new_uid<<1; kmp = kmp^1; kmp = kmp << 32; - - ///if((av[k].v>>1) == (end_uid>>1)) continue; - w = av[k].v^1; aw = asg_arc_a(ug->g, w); nw = asg_arc_n(ug->g, w); - for (i = 0; i < nw; i++) - { - if(aw[i].del) continue; - if(aw[i].v == (v^1)) break; - } - if(i == nw) fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__); - kmp = kmp | (uint64_t)(aw[i].ol); - - - ///kmp = kmp | (uint64_t)(((ug->g)->idx[v]>>32) + k);/**kmp = kmp | av[k].v;**/ - ///here kmp is ul - kv_push(uint64_t, array->a, kmp); - kmp = av[k].ol; kmp = kmp<<32; kmp = kmp|(uint64_t)(av[k].v); - ///here kmp is ol + v - kv_push(uint64_t, array->a, kmp); - ///fprintf(stderr, "*av[%u].v>>1: %u, v&1: %u, ol: %u\n", k, av[k].v>>1, av[k].v&1, av[k].ol); - } - - ///corresponding to direction 0 of new node - v = end_uid; - av = asg_arc_a(ug->g, v); - nv = asg_arc_n(ug->g, v); - ///fprintf(stderr, "end_uid_v>>1: %u, end_uid_v&1: %u, nv: %u\n", v>>1, v&1, nv); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - kmp = new_uid<<1; kmp = kmp << 32; - - w = av[k].v^1; - aw = asg_arc_a(ug->g, w); - nw = asg_arc_n(ug->g, w); - for (i = 0; i < nw; i++) - { - if(aw[i].del) continue; - if(aw[i].v == (v^1)) break; - } - if(i == nw) fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__); - kmp = kmp | (uint64_t)(aw[i].ol); - - - ///here kmp is ul - kv_push(uint64_t, array->a, kmp); - kmp = av[k].ol; kmp = kmp<<32; kmp = kmp|(uint64_t)(av[k].v); - ///here kmp is ol + v - kv_push(uint64_t, array->a, kmp); - ///fprintf(stderr, "#av[%u].v>>1: %u, v&1: %u, ol: %u\n", k, av[k].v>>1, av[k].v&1, av[k].ol); - } - - - ma_utg_t* tmp; - for (i = 0; i < realLen; i++) - { - w = array->a.a[i]; - tmp = &(ug->u.a[w>>1]); - if(tmp->m != 0) - { - tmp->circ = tmp->end = tmp->len = tmp->m = tmp->n = tmp->start = 0; - free(tmp->a); - tmp->a = NULL; - } - asg_seq_del(ug->g, w>>1); - } - - ug->u.a[beg_uid>>1] = result; - ug->g->seq[beg_uid>>1].del = 0; - ug->g->seq[beg_uid>>1].len = result.len; - - uint32_t oLen = 0; - for (; i < array->a.n; i += 2) - { - v = array->a.a[i]>>32; - w = (uint32_t)array->a.a[i+1]; - /****************************may have bugs********************************/ - ///may have bug here, if there is an edge between beg_uid and end_uid - ///if(((w>>1) == (beg_uid>>1)) || ((w>>1) == (end_uid>>1))) continue; - if(((w>>1) == (beg_uid>>1)) || ((w>>1) == (end_uid>>1))) w = v; - /****************************may have bugs********************************/ - - oLen = array->a.a[i+1]>>32; - asg_append_edges_to_srt(ug->g, v, ug->u.a[v>>1].len, w, oLen, 0, 0, 0); - oLen = (uint32_t)array->a.a[i]; - asg_append_edges_to_srt(ug->g, w^1, ug->u.a[w>>1].len, v^1, oLen, 0, 0, 0); - } -} - - -void init_Edge_iter(asg_t* g, uint32_t v, asg_arc_t* new_edges, uint32_t new_edges_n, Edge_iter* x) -{ - x->av_i = x->new_edges_i = 0; - x->g = g; - x->av = asg_arc_a(g, v); - x->nv = asg_arc_n(g, v); - - if(new_edges == NULL || new_edges_n == 0) - { - x->new_edges = NULL; - x->new_edges_n = 0; - } - else - { - x->new_edges = new_edges; - x->new_edges_n = new_edges_n; - } -} - -int get_arc_t(Edge_iter* x, asg_arc_t* get) -{ - for (; x->av_i < x->nv; x->av_i++) - { - if(x->av[x->av_i].del) continue; - get = &(x->av[x->av_i]); - x->av_i++; - return 1; - } - - - for (; x->new_edges_i < x->new_edges_n; x->new_edges_i++) - { - if(x->new_edges[x->new_edges_i].del) continue; - get = &(x->new_edges[x->new_edges_i]); - x->new_edges_i++; - return 1; - } - - return 0; -} - - -void unroll_simple_case_advance(ma_ug_t *ug, asg_t* read_g, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, bub_label_t* b_mask_t, uint8_t* is_r_het, double dupLenThres) -{ - asg_t* nsg = ug->g; - uint32_t v, n_vtx = nsg->n_seq * 2, rnw, nw, beg, end, i; - uint32_t v_left, v_right, w_left, w_term, w_right, return_flag, convex, /**is_found,**/ n_reduce = 1; - long long ll, rBase, dupBase, tmp, max_stop_nodeLen, max_stop_baseLen; - asg_arc_t *aw; - kvec_t_u64_warp u_vecs; - kv_init(u_vecs.a); - buf_t b_0, b_1; - memset(&b_0, 0, sizeof(buf_t)); - memset(&b_1, 0, sizeof(buf_t)); - if(b_mask_t) - { - uint64_t bub_dist = get_s_bub_pop_max_dist_advance(nsg, &(b_mask_t->b[0])); - reset_bub_label_t(b_mask_t, nsg, bub_dist, 0); - } - - - while (n_reduce > 0) - { - n_reduce = 0; - ///break nearly circle, forget why... - n_reduce += asg_arc_del_simple_circle_untig(NULL, NULL, nsg, 100, 0); - - for (v = 0; v < n_vtx; ++v) - { - if (nsg->seq[v>>1].del) continue; - v_left = v; - if(asg_arc_n(nsg, v_left)<1) continue; - if(get_real_length(nsg, v_left, NULL)!=1) continue; - - return_flag = get_unitig(nsg, NULL, v_left^1, &v_right, &ll, &rBase, &max_stop_nodeLen, - &max_stop_baseLen, 1, NULL); - if(return_flag == LOOP) continue; - if(return_flag != MUL_INPUT) continue; - if(asg_arc_n(nsg, v_right)<1) continue; - if(get_real_length(nsg, v_right, NULL)!=1) continue; - - get_real_length(nsg, v_left, &w_left); - get_real_length(nsg, v_right, &w_right); - if((v_left>>1)==(w_left>>1)||(v_left>>1)==(w_right>>1)) continue; - if((v_right>>1)==(w_left>>1)||(v_right>>1)==(w_right>>1)) continue; - - if(w_left!=w_right) - { - return_flag = get_unitig(nsg, NULL, w_left, &convex, &ll, &dupBase, &max_stop_nodeLen, - &max_stop_baseLen, 1, NULL); - if(return_flag == LOOP) continue; - if(return_flag != MUL_OUTPUT) continue; - if(convex != (w_right^1)) continue; - - - beg = end = (uint32_t)-1; - aw = asg_arc_a(nsg, w_left^1); - nw = asg_arc_n(nsg, w_left^1); - for (i = 0, rnw = 0; i < nw; i++) - { - if(aw[i].del) continue; - rnw++; - if(aw[i].v == (v_left^1)) continue; - beg = aw[i].v; - } - if(rnw != 2) continue; - - aw = asg_arc_a(nsg, w_right^1); - nw = asg_arc_n(nsg, w_right^1); - for (i = 0, rnw = 0; i < nw; i++) - { - if(aw[i].del) continue; - rnw++; - if(aw[i].v == (v_right^1)) continue; - end = aw[i].v; - } - if(rnw != 2) continue; - - if(get_real_length(nsg, beg^1, NULL)!=1) continue; - if(get_real_length(nsg, end^1, NULL)!=1) continue; - if((beg>>1) == (end>>1)) continue; - - u_vecs.a.n = 0; - kv_push(uint64_t, u_vecs.a, beg^1); - - - b_0.b.n = 0; - get_unitig(nsg, NULL, w_left, &convex, &ll, &tmp, &max_stop_nodeLen, - &max_stop_baseLen, 1, &b_0); - for (i = 0; i < b_0.b.n; i++) - { - kv_push(uint64_t, u_vecs.a, b_0.b.a[i]); - } - b_0.b.n = 0; - get_unitig(nsg, NULL, v_right^1, &convex, &ll, &tmp, &max_stop_nodeLen, - &max_stop_baseLen, 1, &b_0); - for (i = 0; i < b_0.b.n; i++) - { - kv_push(uint64_t, u_vecs.a, b_0.b.a[i]); - } - b_0.b.n = 0; - get_unitig(nsg, NULL, w_left, &convex, &ll, &tmp, &max_stop_nodeLen, - &max_stop_baseLen, 1, &b_0); - for (i = 0; i < b_0.b.n; i++) - { - kv_push(uint64_t, u_vecs.a, b_0.b.a[i]); - } - - kv_push(uint64_t, u_vecs.a, end); - merge_ug_nodes(ug, read_g, &u_vecs); - n_reduce++; - - // fprintf(stderr, "++1++v>>1: %u, w_left>>1: %u, w_right>>1: %u\n", - // v>>1, w_left>>1, w_right>>1); - } - else ///if(w_left == w_right) - { - if(get_real_length(nsg, w_left^1, NULL)!=2) continue; - return_flag = get_unitig(nsg, NULL, w_left, &convex, &ll, &dupBase, &max_stop_nodeLen, - &max_stop_baseLen, 1, NULL); - if(return_flag == LOOP) continue; - if(return_flag != MUL_OUTPUT) continue; - if(get_real_length(nsg, convex, NULL)!=2) continue; - if(dupBase >= rBase*dupLenThres) - { - continue; - } - beg = end = (uint32_t)-1; - - aw = asg_arc_a(nsg, convex); - nw = asg_arc_n(nsg, convex); - for (i = 0, rnw = 0; i < nw; i++) - { - if(aw[i].del) continue; - if(rnw == 0) beg = aw[i].v; - if(rnw == 1) end = aw[i].v; - rnw++; - } - - if(rnw != 2) continue; - if((beg>>1) == (end>>1)) continue; - if(get_real_length(nsg, beg^1, NULL)!=1) continue; - if(get_real_length(nsg, end^1, NULL)!=1) continue; - - - if(b_mask_t && asg_bub_pop1_label(nsg, convex, b_mask_t->bub_dist, &(b_mask_t->b[0]))) - { - continue; - } - - if(check_different_haps(nsg, ug, read_g, beg, end, reverse_sources, &b_0, &b_1, - ruIndex, is_r_het, 2, 1) == PLOID) - { - continue; - } - - - w_term = convex^1; - u_vecs.a.n = 0; - kv_push(uint64_t, u_vecs.a, beg^1); - - b_0.b.n = 0; - get_unitig(nsg, NULL, w_term, &convex, &ll, &tmp, &max_stop_nodeLen, - &max_stop_baseLen, 1, &b_0); - for (i = 0; i < b_0.b.n; i++) - { - kv_push(uint64_t, u_vecs.a, b_0.b.a[i]); - } - - b_0.b.n = 0; - get_unitig(nsg, NULL, v_left^1, &convex, &ll, &tmp, &max_stop_nodeLen, - &max_stop_baseLen, 1, &b_0); - for (i = 0; i < b_0.b.n; i++) - { - kv_push(uint64_t, u_vecs.a, b_0.b.a[i]); - } - - b_0.b.n = 0; - get_unitig(nsg, NULL, w_left, &convex, &ll, &tmp, &max_stop_nodeLen, - &max_stop_baseLen, 1, &b_0); - for (i = 0; i < b_0.b.n; i++) - { - kv_push(uint64_t, u_vecs.a, b_0.b.a[i]); - } - - kv_push(uint64_t, u_vecs.a, end); - merge_ug_nodes(ug, read_g, &u_vecs); - n_reduce++; - - // fprintf(stderr, "--1--v>>1: %u, w_left>>1: %u, w_right>>1: %u\n", - // v>>1, w_left>>1, w_right>>1); - } - } - - - } - - free(b_0.b.a); - free(b_1.b.a); - kv_destroy(u_vecs.a); -} - -void dbg_spec_edge(asg_t *g, uint32_t s, uint32_t e) -{ - asg_arc_t *av; uint32_t an, k, v, w; - - if(s >= g->n_seq) return; - - v = s<<1; - av = asg_arc_a(g, v); an = asg_arc_n(g, v); - for (k = 0; k < an; k++) { - if(av[k].del) continue; - if((av[k].v>>1) == e) { - w = av[k].v; - fprintf(stderr, "[M::%s]\tL\tutg%.6dl\t%c\tutg%.6dl\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", __func__, - (v>>1)+1, "+-"[v&1], (w>>1)+1, "+-"[w&1], av[k].ol, asg_arc_len(av[k]), 0/**au[j].ou**/); - } - } - - v = (s<<1)+1; - av = asg_arc_a(g, v); an = asg_arc_n(g, v); - for (k = 0; k < an; k++) { - if(av[k].del) continue; - if((av[k].v>>1) == e) { - w = av[k].v; - fprintf(stderr, "[M::%s]\tL\tutg%.6dl\t%c\tutg%.6dl\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", __func__, - (v>>1)+1, "+-"[v&1], (w>>1)+1, "+-"[w&1], av[k].ol, asg_arc_len(av[k]), 0/**au[j].ou**/); - } - } - -} - -void adjust_utg_advance(asg_t *sg, ma_ug_t *ug, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, bub_label_t* b_mask_t, uint8_t* is_r_het) -{ - double startTime = Get_T(); - asg_t* nsg = ug->g; - unroll_simple_case_advance(ug, sg, reverse_sources, ruIndex, b_mask_t, is_r_het, 2.5); - drop_semi_circle(ug, ug->g, sg, reverse_sources, ruIndex, is_r_het); - asg_cleanup(nsg); - asg_symm(nsg); - // fprintf(stderr, "[M::%s]-4-\n", __func__); dbg_spec_edge(ug->g, 7536, 28129); - ///debug_utg_graph(ug, sg, 0, 0); - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2f s\n", __func__, Get_T()-startTime); - } -} - - - - - -asg_t *copy_graph(asg_t* src, int round) -{ - asg_t *rg; - ///just calloc - rg = asg_init(); - uint64_t i, k; - for (i = 0; i < src->n_seq; ++i) - { - ///if a read has been deleted, should we still add them? - asg_seq_set(rg, i, src->seq[i].len, src->seq[i].del); - rg->seq[i].c = src->seq[i].c; - } - asg_cleanup(rg); - - - uint32_t v, n_vtx = src->n_seq * 2, totalL = 0;; - - - for (k = 0; k < (uint32_t)round; k++) - { - for (i = k; i < src->n_arc; i = i + round) - { - if(totalL%50000==0) fprintf(stderr, "totalL: %u, n_arc: %u\n", totalL, src->n_arc); - totalL++; - if(src->arc[i].del) continue; - asg_append_edges_to_srt(rg, src->arc[i].ul>>32, - (uint32_t)(src->arc[i].ul) + src->arc[i].ol, - src->arc[i].v, src->arc[i].ol, src->arc[i].strong, - src->arc[i].el, src->arc[i].no_l_indel); - } - } - - - totalL = 0; - for (v = 0; v < n_vtx; ++v) - { - if (src->seq[v>>1].del) continue; - uint32_t nv = asg_arc_n(src, v); - asg_arc_t *av = asg_arc_a(src, v); - for (i = 0; i < nv; i++) - { - if(totalL%50000==0) fprintf(stderr, "-totalL: %u, n_arc: %u\n", totalL, src->n_arc); - totalL++; - if(av[i].del) continue; - asg_append_edges_to_srt(rg, av[i].ul>>32, (uint32_t)(av[i].ul) + av[i].ol, - av[i].v, av[i].ol, av[i].strong, av[i].el, av[i].no_l_indel); - } - } - - - - - /** - for (v = 0; v < n_vtx; ++v) - { - if(src->idx[v] != rg->idx[v]) - { - fprintf(stderr, "*****v: %u, src_i: %u, srcLen: %u, rg_i: %u, rgLen: %u\n", - v, src->idx[v]>>32, (uint32_t)src->idx[v], - rg->idx[v]>>32, (uint32_t)rg->idx[v]); - } - } - **/ - - - for (v = 0; v < n_vtx; ++v) - { - - if(src->seq[v>>1].del != rg->seq[v>>1].del) - { - fprintf(stderr, "ERROR1\n"); - } - - uint32_t nv = asg_arc_n(src, v); - asg_arc_t *av = asg_arc_a(src, v); - ///if(nv != rnv) - if(get_real_length(src, v, NULL) != get_real_length(rg, v, NULL)) - { - fprintf(stderr, "ERROR2\n"); - } - - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - asg_arc_t forward = av[i], backward; - memset(&backward, 0, sizeof(backward)); - if(get_arc(rg, (forward.ul>>32), forward.v, &backward)!=1) - { - fprintf(stderr, "ERROR3\n"); - } - - if(forward.del != backward.del || forward.el != backward.el || - forward.no_l_indel != backward.no_l_indel || forward.ol != backward.ol || - forward.strong != backward.strong || forward.ul != backward.ul || forward.v != backward.v) - { - fprintf(stderr, "ERROR4\n"); - fprintf(stderr, "forward, del: %u, el: %u, no_l_indel: %u, ol: %u, strong: %u, ul: %u, v: %u\n", - (uint32_t)forward.del, (uint32_t)forward.el, (uint32_t)forward.no_l_indel, - (uint32_t)forward.ol, (uint32_t)forward.strong, - (uint32_t)forward.ul, (uint32_t)forward.v); - fprintf(stderr, "backward, del: %u, el: %u, no_l_indel: %u, ol: %u, strong: %u, ul: %u, v: %u\n", - (uint32_t)backward.del, (uint32_t)backward.el, (uint32_t)backward.no_l_indel, - (uint32_t)backward.ol, (uint32_t)backward.strong, - (uint32_t)backward.ul, (uint32_t)backward.v); - } - } - - - nv = asg_arc_n(rg, v); - av = asg_arc_a(rg, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - asg_arc_t forward = av[i], backward; - memset(&backward, 0, sizeof(backward)); - if(get_arc(src, (forward.ul>>32), forward.v, &backward)!=1) - { - fprintf(stderr, "ERROR5\n"); - } - - if(forward.del != backward.del || forward.el != backward.el || - forward.no_l_indel != backward.no_l_indel || forward.ol != backward.ol || - forward.strong != backward.strong || forward.ul != backward.ul || forward.v != backward.v) - { - fprintf(stderr, "ERROR6\n"); - } - } - - - ///get_arc(g, forward.v^1, (forward.ul>>32)^1, &backward) - ///fprintf(stderr, "+v: %u\n", v); - - } - - - if(src->seq_vis) - { - rg->seq_vis = (uint8_t*)malloc(src->n_seq*2*sizeof(uint8_t)); - memcpy(rg->seq_vis, src->seq_vis, src->n_seq*2*sizeof(uint8_t)); - } - - - fprintf(stderr, "end_copy\n"); - return rg; -} - -int load_coverage_cut(ma_sub_t** coverage_cut, char* read_file_name) -{ - char* index_name = (char*)malloc(strlen(read_file_name)+15); - sprintf(index_name, "%s.bin", read_file_name); - FILE* fp = fopen(index_name, "r"); - if(!fp) - { - return 0; - } - int f_flag = 0; - uint64_t n_read; - f_flag += fread(&n_read, sizeof(n_read), 1, fp); - (*coverage_cut) = (ma_sub_t*)malloc(sizeof(ma_sub_t)*n_read); - - // uint64_t i = 0, tmp; - // for (i = 0; i < n_read; i++) - // { - // f_flag += fread(&tmp, sizeof(tmp), 1, fp); - // (*coverage_cut)[i].c = tmp; - // f_flag += fread(&tmp, sizeof(tmp), 1, fp); - // (*coverage_cut)[i].del = tmp; - // f_flag += fread(&tmp, sizeof(tmp), 1, fp); - // (*coverage_cut)[i].e = tmp; - // f_flag += fread(&tmp, sizeof(tmp), 1, fp); - // (*coverage_cut)[i].s = tmp; - // } - fread((*coverage_cut), sizeof((*((*coverage_cut)))), n_read, fp); - - free(index_name); - fflush(fp); - fclose(fp); - return 1; -} - - -int write_coverage_cut(ma_sub_t* coverage_cut, char* read_file_name, uint64_t n_read) -{ - char* index_name = (char*)malloc(strlen(read_file_name)+15); - sprintf(index_name, "%s.bin", read_file_name); - FILE* fp = fopen(index_name, "w"); - fwrite(&n_read, sizeof(n_read), 1, fp); - // uint64_t i = 0, tmp; - // for (i = 0; i < n_read; i++) - // { - // tmp = coverage_cut[i].c; - // fwrite(&tmp, sizeof(tmp), 1, fp); - // tmp = coverage_cut[i].del; - // fwrite(&tmp, sizeof(tmp), 1, fp); - // tmp = coverage_cut[i].e; - // fwrite(&tmp, sizeof(tmp), 1, fp); - // tmp = coverage_cut[i].s; - // fwrite(&tmp, sizeof(tmp), 1, fp); - // } - fwrite(coverage_cut, sizeof((*(coverage_cut))), n_read, fp); - free(index_name); - fflush(fp); - fclose(fp); - - return 1; -} - -int write_ruIndex(R_to_U* ruIndex, char* read_file_name) -{ - char* index_name = (char*)malloc(strlen(read_file_name)+15); - sprintf(index_name, "%s.bin", read_file_name); - FILE* fp = fopen(index_name, "w"); - fwrite(&ruIndex->len, sizeof(ruIndex->len), 1, fp); - fwrite(ruIndex->index, sizeof(ruIndex->index[0]), ruIndex->len, fp); - fwrite(R_INF.trio_flag, sizeof(R_INF.trio_flag[0]), ruIndex->len, fp); - // fwrite(ruIndex->is_het, 1, ruIndex->len, fp); - fwrite(&(asm_opt.hom_global_coverage_set), sizeof(asm_opt.hom_global_coverage_set), 1, fp); - fwrite(&(asm_opt.hom_global_coverage), sizeof(asm_opt.hom_global_coverage), 1, fp); - free(index_name); - fflush(fp); - fclose(fp); - - return 1; -} - -int load_ruIndex(R_to_U* ruIndex, char* read_file_name) -{ - char* index_name = (char*)malloc(strlen(read_file_name)+15); - sprintf(index_name, "%s.bin", read_file_name); - FILE* fp = fopen(index_name, "r"); - if(!fp) - { - return 0; - } - int f_flag = 0; - f_flag += fread(&(ruIndex)->len, sizeof((ruIndex)->len), 1, fp); - (ruIndex)->index = (uint32_t*)malloc(sizeof(uint32_t)*(ruIndex)->len); - f_flag += fread((ruIndex)->index, sizeof((*((ruIndex)->index))), (ruIndex)->len, fp); - - if(!(asm_opt.ar)) { - R_INF.trio_flag = (uint8_t*)malloc(sizeof(uint8_t)*(ruIndex)->len); - f_flag += fread(R_INF.trio_flag, sizeof((*(R_INF.trio_flag))), (ruIndex)->len, fp); - } else { - fseek(fp, sizeof((*(R_INF.trio_flag)))*(ruIndex)->len, SEEK_CUR); - } - - // CALLOC(ruIndex->is_het, ruIndex->len); - // f_flag += fread(ruIndex->is_het, 1, ruIndex->len, fp); - - f_flag += fread(&(asm_opt.hom_global_coverage_set), sizeof(asm_opt.hom_global_coverage_set), 1, fp); - f_flag += fread(&(asm_opt.hom_global_coverage), sizeof(asm_opt.hom_global_coverage), 1, fp); - - free(index_name); - fflush(fp); - fclose(fp); - - return 1; -} - -int write_asg_t(asg_t *sg, char* read_file_name) -{ - char* index_name = (char*)malloc(strlen(read_file_name)+15); - sprintf(index_name, "%s.bin", read_file_name); - FILE* fp = fopen(index_name, "w"); - uint32_t tmp/**, i**/; - - tmp = sg->n_arc; - fwrite(&tmp, sizeof(tmp), 1, fp); - // tmp = sg->m_arc; - fwrite(&tmp, sizeof(tmp), 1, fp); - - tmp = sg->is_srt; - fwrite(&tmp, sizeof(tmp), 1, fp); - - - tmp = sg->n_seq; - fwrite(&tmp, sizeof(tmp), 1, fp); - // tmp = sg->m_seq; - fwrite(&tmp, sizeof(tmp), 1, fp); - - tmp = sg->is_symm; - fwrite(&tmp, sizeof(tmp), 1, fp); - tmp = sg->r_seq; - fwrite(&tmp, sizeof(tmp), 1, fp); - - - uint32_t Len; - - Len = sg->n_seq*2; - fwrite(sg->seq_vis, sizeof(sg->seq_vis[0]), Len, fp); - - Len = sg->n_seq*2; - fwrite(sg->idx, sizeof(sg->idx[0]), Len, fp); - - - // for (i = 0; i < sg->n_arc; i++) - // { - // tmp = sg->arc[i].del; - // fwrite(&tmp, sizeof(tmp), 1, fp); - // tmp = sg->arc[i].el; - // fwrite(&tmp, sizeof(tmp), 1, fp); - // tmp = sg->arc[i].no_l_indel; - // fwrite(&tmp, sizeof(tmp), 1, fp); - // tmp = sg->arc[i].ol; - // fwrite(&tmp, sizeof(tmp), 1, fp); - // tmp = sg->arc[i].strong; - // fwrite(&tmp, sizeof(tmp), 1, fp); - - // uint64_t tmp_64; - // tmp_64 = sg->arc[i].ul; - // fwrite(&tmp_64, sizeof(tmp_64), 1, fp); - - // tmp = sg->arc[i].v; - // fwrite(&tmp, sizeof(tmp), 1, fp); - // } - fwrite(sg->arc, sizeof((*(sg->arc))), sg->n_arc, fp); - - - // for (i = 0; i < sg->n_seq; i++) - // { - // tmp = sg->seq[i].c; - // fwrite(&tmp, sizeof(tmp), 1, fp); - // tmp = sg->seq[i].del; - // fwrite(&tmp, sizeof(tmp), 1, fp); - // tmp = sg->seq[i].len; - // fwrite(&tmp, sizeof(tmp), 1, fp); - // } - fwrite(sg->seq, sizeof((*(sg->seq))), sg->n_seq, fp); - - free(index_name); - fflush(fp); - fclose(fp); - - return 1; -} - - -int load_asg_t(asg_t **sg, char* read_file_name) -{ - char* index_name = (char*)malloc(strlen(read_file_name)+15); - sprintf(index_name, "%s.bin", read_file_name); - FILE* fp = fopen(index_name, "r"); - if(!fp) - { - return 0; - } - uint32_t tmp/**, i**/; - - (*sg) = (asg_t*)calloc(1, sizeof(asg_t)); - int f_flag = 0; - f_flag += fread(&tmp, sizeof(tmp), 1, fp); - (*sg)->n_arc = tmp; - f_flag += fread(&tmp, sizeof(tmp), 1, fp); - (*sg)->m_arc = tmp; - f_flag += fread(&tmp, sizeof(tmp), 1, fp); - (*sg)->is_srt = tmp; - f_flag += fread(&tmp, sizeof(tmp), 1, fp); - (*sg)->n_seq = tmp; - f_flag += fread(&tmp, sizeof(tmp), 1, fp); - (*sg)->m_seq = tmp; - f_flag += fread(&tmp, sizeof(tmp), 1, fp); - (*sg)->is_symm = tmp; - f_flag += fread(&tmp, sizeof(tmp), 1, fp); - (*sg)->r_seq = tmp; - - uint32_t Len; - - Len = (*sg)->n_seq*2; - (*sg)->seq_vis = (uint8_t*)malloc(sizeof(uint8_t)*Len); - f_flag += fread((*sg)->seq_vis, sizeof((*sg)->seq_vis[0]), Len, fp); - - - - Len = (*sg)->n_seq*2; - (*sg)->idx = (uint64_t*)malloc(sizeof(uint64_t)*Len); - f_flag += fread((*sg)->idx, sizeof((*sg)->idx[0]), Len, fp); - - - - - - (*sg)->arc = (asg_arc_t*)malloc(sizeof(asg_arc_t)*(*sg)->m_arc); - (*sg)->seq = (asg_seq_t*)malloc(sizeof(asg_seq_t)*(*sg)->m_seq); - - - // for (i = 0; i < (*sg)->n_arc; i++) - // { - // f_flag += fread(&tmp, sizeof(tmp), 1, fp); - // (*sg)->arc[i].del = tmp; - - // f_flag += fread(&tmp, sizeof(tmp), 1, fp); - // (*sg)->arc[i].el = tmp; - - // f_flag += fread(&tmp, sizeof(tmp), 1, fp); - // (*sg)->arc[i].no_l_indel = tmp; - - // f_flag += fread(&tmp, sizeof(tmp), 1, fp); - // (*sg)->arc[i].ol = tmp; - - // f_flag += fread(&tmp, sizeof(tmp), 1, fp); - // (*sg)->arc[i].strong = tmp; - - // uint64_t tmp_64; - // f_flag += fread(&tmp_64, sizeof(tmp_64), 1, fp); - // (*sg)->arc[i].ul = tmp_64; - - // f_flag += fread(&tmp, sizeof(tmp), 1, fp); - // (*sg)->arc[i].v = tmp; - // } - fread((*sg)->arc, sizeof((*((*sg)->arc))), (*sg)->n_arc, fp); - - - // for (i = 0; i < (*sg)->n_seq; i++) - // { - // f_flag += fread(&tmp, sizeof(tmp), 1, fp); - // (*sg)->seq[i].c = tmp; - // f_flag += fread(&tmp, sizeof(tmp), 1, fp); - // (*sg)->seq[i].del = tmp; - // f_flag += fread(&tmp, sizeof(tmp), 1, fp); - // (*sg)->seq[i].len = tmp; - // } - fread((*sg)->seq, sizeof((*((*sg)->seq))), (*sg)->n_seq, fp); - - free(index_name); - fflush(fp); - fclose(fp); - - return 1; -} - -int write_debug_graph(asg_t *sg, ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, -char* output_file_name, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, all_ul_t *ul_r_inf) -{ - - char* gfa_name = (char*)malloc(strlen(output_file_name)+55); - - ////write_All_reads(&R_INF, gfa_name); - sprintf(gfa_name, "%s.all.debug.source", output_file_name); - write_debug_ma_hit_ts(sources, R_INF.total_reads, gfa_name); - sprintf(gfa_name, "%s.all.debug.reverse", output_file_name); - write_debug_ma_hit_ts(reverse_sources, R_INF.total_reads, gfa_name); - if(coverage_cut) { - sprintf(gfa_name, "%s.all.debug.coverage_cut", output_file_name); - write_coverage_cut(coverage_cut, gfa_name, R_INF.total_reads); - } - sprintf(gfa_name, "%s.all.debug.ruIndex", output_file_name); - write_ruIndex(ruIndex, gfa_name); - if(sg) { - sprintf(gfa_name, "%s.all.debug.asg_t", output_file_name); - write_asg_t(sg, gfa_name); - } - if(ul_r_inf) { - sprintf(gfa_name, "%s.all.debug.ul.rinfor", output_file_name); - write_all_ul_t(ul_r_inf, gfa_name, NULL); - } - free(gfa_name); - fprintf(stderr, "debug_graph has been written.\n"); - return 1; -} - - -int load_debug_graph(asg_t** sg, ma_hit_t_alloc** sources, ma_sub_t** coverage_cut, -char* output_file_name, ma_hit_t_alloc** reverse_sources, R_to_U* ruIndex, all_ul_t *ul_r_inf) -{ - FILE* fp = NULL; - char* gfa_name = (char*)malloc(strlen(output_file_name)+55); - sprintf(gfa_name, "%s.all.debug.source.bin", output_file_name); - fp = fopen(gfa_name, "r"); if(!fp) return 0; fclose(fp); - sprintf(gfa_name, "%s.all.debug.reverse.bin", output_file_name); - fp = fopen(gfa_name, "r"); if(!fp) return 0; fclose(fp); - if(coverage_cut) { - sprintf(gfa_name, "%s.all.debug.coverage_cut.bin", output_file_name); - fp = fopen(gfa_name, "r"); if(!fp) return 0; fclose(fp); - } - sprintf(gfa_name, "%s.all.debug.ruIndex.bin", output_file_name); - fp = fopen(gfa_name, "r"); if(!fp) return 0; fclose(fp); - if(sg) { - sprintf(gfa_name, "%s.all.debug.asg_t.bin", output_file_name); - fp = fopen(gfa_name, "r"); if(!fp) return 0; fclose(fp); - } - if(ul_r_inf) { - sprintf(gfa_name, "%s.all.debug.ul.rinfor.ul.ovlp.bin", output_file_name); - fp = fopen(gfa_name, "r"); if(!fp) return 0; fclose(fp); - } - - if((sources == NULL) || (reverse_sources == NULL) || (ruIndex == NULL)) - { - return 1; - } - - if((*sources)!=NULL) - { - destory_ma_hit_t_alloc((*sources)); - } - - if((*reverse_sources)!=NULL) - { - destory_ma_hit_t_alloc((*reverse_sources)); - } - - if(coverage_cut && (*coverage_cut)!=NULL) - { - free((*coverage_cut)); - } - - if((ruIndex)!=NULL) - { - destory_R_to_U((ruIndex)); - } - - if(sg && (*sg)!=NULL) - { - asg_destroy(*sg); - } - - - - sprintf(gfa_name, "%s.all.debug.source", output_file_name); - if(!load_debug_ma_hit_ts(sources, gfa_name)) - { - return 0; - } - - sprintf(gfa_name, "%s.all.debug.reverse", output_file_name); - if(!load_debug_ma_hit_ts(reverse_sources, gfa_name)) - { - return 0; - } - - if(coverage_cut) { - sprintf(gfa_name, "%s.all.debug.coverage_cut", output_file_name); - if(!load_coverage_cut(coverage_cut, gfa_name)) - { - return 0; - } - } - - sprintf(gfa_name, "%s.all.debug.ruIndex", output_file_name); - if(!load_ruIndex(ruIndex, gfa_name)) - { - return 0; - } - - if(sg) { - sprintf(gfa_name, "%s.all.debug.asg_t", output_file_name); - if(!load_asg_t(sg, gfa_name)) - { - return 0; - } - } - - - if(ul_r_inf) { - sprintf(gfa_name, "%s.all.debug.ul.rinfor", output_file_name); - if(!load_all_ul_t(ul_r_inf, gfa_name, &R_INF, NULL)) return 0; - } - - R_INF.paf = (*sources); R_INF.reverse_paf = (*reverse_sources); - - return 1; -} - - -hap_cov_t* init_hap_cov_t(ma_ug_t *ug, asg_t* read_g, ma_hit_t_alloc* sources, R_to_U* ruIndex, -ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, int max_hang, int min_ovlp, -uint32_t is_collect_trans) -{ - uint32_t n_ux = ug->g->n_seq, i, k, j, v, rId, tn, is_Unitig, r_i, nv, w, C_bases; - uint8_t *set = NULL; - hap_cov_t *x = NULL; CALLOC(x, 1); - x->n = read_g->n_seq; - x->reverse_sources = reverse_sources; - x->coverage_cut = coverage_cut; - x->ruIndex = ruIndex; - x->max_hang = max_hang; - x->min_ovlp = min_ovlp; - x->read_g = read_g; - x->t_ch = NULL; - kv_init(x->u_buffer.a); - kv_init(x->tailIndex.a); - kv_init(x->prevIndex.a); - ma_utg_t* u = NULL; - asg_arc_t *av = NULL; - ma_hit_t *h = NULL; - MALLOC(x->pos_idx, x->n); memset(x->pos_idx, -1, x->n*sizeof(uint64_t)); - CALLOC(set, read_g->n_seq<<1); - CALLOC(x->cov, x->n); - for (i = 0; i < n_ux; i++)//get the coverage for each read - { - if(ug->g->seq[i].del) continue; - u = &(ug->u.a[i]); - for (r_i = 0; r_i < u->n; r_i++) set[u->a[r_i]>>33] = 1; - - v = i<<1; - nv = asg_arc_n(ug->g, v); - av = asg_arc_a(ug->g, v); - for (k = 0; k < nv; k++) - { - w = av[k].v; - if(av[k].del) continue; - if(ug->g->seq[w>>1].del) continue; - u = &(ug->u.a[w>>1]); - for (r_i = 0; r_i < u->n; r_i++) set[u->a[r_i]>>33] = 1; - } - - v = (i<<1)+1; - nv = asg_arc_n(ug->g, v); - av = asg_arc_a(ug->g, v); - for (k = 0; k < nv; k++) - { - w = av[k].v; - if(av[k].del) continue; - if(ug->g->seq[w>>1].del) continue; - u = &(ug->u.a[w>>1]); - for (r_i = 0; r_i < u->n; r_i++) set[u->a[r_i]>>33] = 1; - } - - - - u = &(ug->u.a[i]); - for (k = 0; k < u->n; k++) - { - C_bases = 0; - rId = u->a[k]>>33; - for (j = 0; j < (uint64_t)(sources[rId].length); j++) - { - h = &(sources[rId].buffer[j]); - tn = Get_tn((*h)); - if(read_g->seq[tn].del == 1) - { - ///get the id of read that contains it - // uint32_t tn0 = tn; - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - // if(tn != (uint32_t)-1 && is_Unitig != 1) { - // fprintf(stderr, "[M::%s]\ttn::%u\tn_seq::%u\tis_Unitig::%u\ttn0::%u\n", __func__, tn, read_g->n_seq, is_Unitig, tn0); - // } - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - if(read_g->seq[tn].del == 1) continue; - if(!set[tn]) continue; - C_bases += (Get_qe((*h)) - Get_qs((*h))); - } - x->cov[rId] = MAX(C_bases, x->cov[rId]); - } - - - - u = &(ug->u.a[i]); - for (r_i = 0; r_i < u->n; r_i++) set[u->a[r_i]>>33] = 0; - - v = i<<1; - nv = asg_arc_n(ug->g, v); - av = asg_arc_a(ug->g, v); - for (k = 0; k < nv; k++) - { - w = av[k].v; - if(av[k].del) continue; - if(ug->g->seq[w>>1].del) continue; - u = &(ug->u.a[w>>1]); - for (r_i = 0; r_i < u->n; r_i++) set[u->a[r_i]>>33] = 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++) - { - w = av[k].v; - if(av[k].del) continue; - if(ug->g->seq[w>>1].del) continue; - u = &(ug->u.a[w>>1]); - for (r_i = 0; r_i < u->n; r_i++) set[u->a[r_i]>>33] = 0; - } - } - - if(set) free(set); - CALLOC(x->is_r_het, read_g->n_seq); - set_r_het_flag(ug, read_g, coverage_cut, sources, ruIndex, x->is_r_het); - - x->t_ch = NULL; - if(is_collect_trans) x->t_ch = init_trans_chain(ug, read_g->n_seq); - - return x; -} - -void destory_hap_cov_t(hap_cov_t **x) -{ - if(*x) - { - free((*x)->cov); - free((*x)->pos_idx); - free((*x)->is_r_het); - kv_destroy((*x)->u_buffer.a); - kv_destroy((*x)->tailIndex.a); - kv_destroy((*x)->prevIndex.a); - if((*x)->t_ch) destory_trans_chain(&((*x)->t_ch)); - free((*x)); - } -} - - -void print_utg_hap(ma_ug_t *ug, asg_t* read_g, uint32_t uid, ma_hit_t_alloc* reverse_sources, -R_to_U* ruIndex) -{ - - uint32_t k, rId, qn, i, is_Unitig; - ma_utg_t* u = &(ug->u.a[uid]); - fprintf(stderr, "\nuid: %u, u->n: %u\n", uid, u->n); - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - fprintf(stderr, "self[%u]: %u\n", k, rId); - } - - for (k = 0; k < u->n; k++) - { - qn = u->a[k]>>33; - fprintf(stderr, "****self[%u]: %u, Len: %u\n", k, qn, reverse_sources[qn].length); - for (i = 0; i < reverse_sources[qn].length; i++) - { - rId = Get_tn(reverse_sources[qn].buffer[i]); - if(read_g->seq[rId].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, rId, &rId, &is_Unitig); - if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; - } - fprintf(stderr, "hap[%u]: %u\n", i, rId); - } - } - -} - - -void reset_trans_chain(trans_chain* t_ch, ma_utg_t *u) -{ - uint32_t k = 0; - if(u->n == 0 || u->m == 0) return; - for (k = 0; k < u->n; k++) t_ch->ir_het[u->a[k]>>33] = N_HET; -} - -void append_utg(ma_ug_t* ptg, ma_ug_t* atg, trans_chain* t_ch) -{ - uint64_t num_nodes = 0; - asg_t* nsg = atg->g; - uint32_t v, n_vtx = nsg->n_seq; - ma_utg_t *p; - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del || atg->u.a[v].m == 0) continue; - num_nodes++; - } - - if(num_nodes == 0) return; - - ptg->u.n = ptg->u.n + num_nodes; - if(ptg->u.n > ptg->u.m) - { - ptg->u.m = ptg->u.n; - ptg->u.a = (ma_utg_t*)realloc(ptg->u.a, ptg->u.m*sizeof(ma_utg_t)); - } - ptg->u.n = ptg->u.n - num_nodes; - - for (v = 0; v < atg->g->n_seq; ++v) - { - if(atg->g->seq[v].del || atg->u.a[v].m == 0) continue; - if(t_ch) reset_trans_chain(t_ch, &(atg->u.a[v])); - - p = &(ptg->u.a[ptg->u.n]); - p->len = atg->u.a[v].len; - p->circ = atg->u.a[v].circ; - p->start = atg->u.a[v].start; - p->end = atg->u.a[v].end; - p->m = atg->u.a[v].m; atg->u.a[v].m = 0; - p->n = atg->u.a[v].n; atg->u.a[v].n = 0; - p->a = atg->u.a[v].a; atg->u.a[v].a = 0; - p->s = atg->u.a[v].s; atg->u.a[v].s = 0; - asg_seq_set(ptg->g, ptg->u.n, p->len, 0); - ptg->u.n++; - } - - if(ptg->g->idx != 0) free(ptg->g->idx); - ptg->g->idx = 0; - asg_cleanup(ptg->g); -} - - -void print_utg_coverage(ma_ug_t *ug, ma_sub_t* coverage_cut, uint32_t v, ma_hit_t_alloc* sources) -{ - asg_t* nsg = ug->g; - uint32_t rId, k, j; - ma_utg_t* u = NULL; - ma_hit_t *h; - - if(nsg->seq[v].del) return; - u = &(ug->u.a[v]); - if(u->m == 0) return; - long long R_bases = 0, C_bases = 0; - long long U_R_bases = 0, U_C_bases = 0; - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - C_bases = 0; - R_bases = coverage_cut[rId].e - coverage_cut[rId].s; - for (j = 0; j < (uint64_t)(sources[rId].length); j++) - { - h = &(sources[rId].buffer[j]); - if(h->el != 1) continue; - C_bases += Get_qe((*h)) - Get_qs((*h)); - } - U_R_bases += R_bases; - U_C_bases += C_bases; - C_bases = C_bases/R_bases; - - fprintf(stderr, "%.*s\t%lld\n", (int)Get_NAME_LENGTH(R_INF, rId), Get_NAME(R_INF, rId), C_bases); - } - - fprintf(stderr, "v: %u, coverage: %lld\n\n", v, U_C_bases/U_R_bases); -} - -void recover_utg_by_coverage(ma_ug_t **ptg, asg_t* read_g, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex, trans_chain* t_ch) -{ - if(asm_opt.recover_atg_cov_min == -1) return; - if(asm_opt.recover_atg_cov_max == -1) return; - if(asm_opt.recover_atg_cov_min > asm_opt.recover_atg_cov_max) return; - ma_ug_t *atg = NULL; - atg = ma_ug_gen_primary(read_g, ALTER_LABLE); - asg_t* nsg = atg->g; - uint32_t v, n_vtx = nsg->n_seq, k, j, rId, available_reads = 0, keep_atg = 0, tn, is_Unitig; - ma_utg_t* u = NULL; - ma_hit_t *h; - - - ///print_untig_by_read(atg, "SRR11606870.634978", -1, NULL, NULL, "debug"); - long long R_bases = 0, C_bases = 0, C_bases_primary = 0, C_bases_alter = 0; - long long total_C_bases = 0, total_C_bases_alter = 0; - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - u = &(atg->u.a[v]); - if(u->m == 0) continue; - total_C_bases = total_C_bases_alter = available_reads = 0; - - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - C_bases = C_bases_primary = C_bases_alter = 0; - R_bases = coverage_cut[rId].e - coverage_cut[rId].s; - for (j = 0; j < (uint64_t)(sources[rId].length); j++) - { - h = &(sources[rId].buffer[j]); - if(h->el != 1) continue; - tn = Get_tn((*h)); - if(read_g->seq[tn].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - if(read_g->seq[tn].del == 1) continue; - if(read_g->seq[tn].c == ALTER_LABLE) - { - C_bases_alter += Get_qe((*h)) - Get_qs((*h)); - } - else - { - C_bases_primary += Get_qe((*h)) - Get_qs((*h)); - } - } - - C_bases = C_bases_primary + C_bases_alter; - total_C_bases += C_bases; - - C_bases = C_bases/R_bases; - if(C_bases >= asm_opt.recover_atg_cov_min && C_bases <= asm_opt.recover_atg_cov_max) - { - if(C_bases_alter >= (C_bases_primary + C_bases_alter) * ALTER_COV_THRES) available_reads++; - total_C_bases_alter += C_bases_alter; - } - } - - - if(((available_reads < (u->n * 0.8)) && (total_C_bases_alter < (total_C_bases * 0.8))) - || available_reads == 0) - { - asg_seq_del(nsg, v); - - if(u->m!=0) - { - u->m = u->n = 0; - free(u->a); - u->a = NULL; - } - } - else - { - ///print_utg_coverage(atg, coverage_cut, v, sources); - ///fprintf(stderr, "rId: %u\n", rId); - ///fprintf(stderr, "%.*s\t%lld\n", (int)Get_NAME_LENGTH(R_INF, rId), Get_NAME(R_INF, rId), C_bases); - keep_atg++; - } - } - - if(keep_atg > 0) - { - asg_cleanup(nsg); - asg_symm(nsg); - append_utg(*ptg, atg, t_ch); - - n_vtx = read_g->n_seq; - for (v = 0; v < n_vtx; v++) - { - read_g->seq[v].c = ALTER_LABLE; - } - - nsg = (*ptg)->g; - n_vtx = nsg->n_seq; - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - u = &((*ptg)->u.a[v]); - if(u->m == 0) continue; - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - read_g->seq[rId].c = nsg->seq[v].c; - } - } - - - n_vtx = read_g->n_seq; - for (v = 0; v < n_vtx; v++) - { - if(read_g->seq[v].c == ALTER_LABLE) - { - asg_seq_drop(read_g, v); - } - } - } - - ma_ug_destroy(atg); -} - - -void adjust_utg_by_primary(ma_ug_t **ug, asg_t* read_g, float drop_rate, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, -R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, -kvec_asg_arc_t_warp* new_rtg_edges, hap_cov_t **i_cov, bub_label_t* b_mask_t, -uint32_t collect_p_trans, uint32_t collect_p_trans_f) -{ - asg_t* nsg = (*ug)->g; - uint32_t v, n_vtx = nsg->n_seq, k, rId, just_contain; - ma_utg_t* u = NULL; - hap_cov_t *cov = init_hap_cov_t(*ug, read_g, sources, ruIndex, reverse_sources, - coverage_cut, max_hang, min_ovlp, (asm_opt.purge_level_primary>0||i_cov)?1:0); - if(cov->t_ch) cov->t_ch->ir_het = cov->is_r_het; - adjust_utg_advance(read_g, (*ug), reverse_sources, ruIndex, b_mask_t, cov->is_r_het); - - nsg = (*ug)->g; - n_vtx = nsg->n_seq; - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - nsg->seq[v].c = PRIMARY_LABLE; - EvaluateLen((*ug)->u, v) = (*ug)->u.a[v].n; - } - - clean_primary_untig_graph(*ug, read_g, sources, reverse_sources, coverage_cut, tipsLen, tip_drop_ratio, - stops_threshold, ruIndex, NULL, NULL, 0, 0, 0, chimeric_rate, 0, 0, drop_ratio, cov); - delete_useless_nodes(ug); - renew_utg(ug, read_g, new_rtg_edges); - if(i_cov && collect_p_trans == 0) goto skip_purge; - if(asm_opt.purge_level_primary > 0) - { - // print_debug_gfa(read_g, *ug, coverage_cut, "debug_purge", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); - just_contain = 0; - if(asm_opt.purge_level_primary == 1) just_contain = 1; - purge_dups(*ug, read_g, coverage_cut, sources, reverse_sources, ruIndex, new_rtg_edges, - asm_opt.purge_simi_thres, asm_opt.purge_overlap_len, max_hang, min_ovlp, drop_ratio, - just_contain, 0, cov, !!(cov->t_ch&&collect_p_trans), collect_p_trans_f); - delete_useless_nodes(ug); - renew_utg(ug, read_g, new_rtg_edges); - } - - if (!(asm_opt.flag & HA_F_BAN_POST_JOIN)) - { - rescue_missing_overlaps_aggressive(*ug, read_g, sources, coverage_cut, ruIndex, max_hang, - min_ovlp, 0, 1, NULL, b_mask_t); - renew_utg(ug, read_g, new_rtg_edges); - rescue_contained_reads_aggressive(*ug, read_g, sources, coverage_cut, ruIndex, max_hang, - min_ovlp, 10, 0, 1, NULL, NULL, b_mask_t); - renew_utg(ug, read_g, new_rtg_edges); - } - - - if(asm_opt.max_contig_tip > 0) { - discard_small_ctg(ug, read_g, new_rtg_edges, asm_opt.max_contig_tip, 0, 1); - } - - - n_vtx = read_g->n_seq; - for (v = 0; v < n_vtx; v++) - { - read_g->seq[v].c = ALTER_LABLE; - } - - - nsg = (*ug)->g; - n_vtx = nsg->n_seq; - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - if(nsg->seq[v].c == ALTER_LABLE) continue; - u = &((*ug)->u.a[v]); - if(u->m == 0) continue; - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - read_g->seq[rId].c = nsg->seq[v].c; - } - } - - n_vtx = read_g->n_seq; - for (v = 0; v < n_vtx; v++) - { - if(read_g->seq[v].c == ALTER_LABLE) - { - asg_seq_drop(read_g, v); - } - } - - if(asm_opt.recover_atg_cov_min == -1024) - { - asm_opt.recover_atg_cov_max = (asm_opt.hom_global_coverage_set? - (asm_opt.hom_global_coverage):(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); - asm_opt.recover_atg_cov_min = asm_opt.recover_atg_cov_max * 0.85; - asm_opt.recover_atg_cov_max = INT32_MAX; - } - - if(asm_opt.recover_atg_cov_max != INT32_MAX) - { - fprintf(stderr, "[M::%s] primary contig coverage range: [%d, %d]\n", - __func__, asm_opt.recover_atg_cov_min, asm_opt.recover_atg_cov_max); - } - else - { - fprintf(stderr, "[M::%s] primary contig coverage range: [%d, infinity]\n", - __func__, asm_opt.recover_atg_cov_min); - } - - skip_purge: - recover_utg_by_coverage(ug, read_g, coverage_cut, sources, ruIndex, cov->t_ch); - if(i_cov) - { - (*i_cov) = cov; - } - else - { - destory_hap_cov_t(&cov); - } -} - -void set_r_het_status(uint8_t* r_het, kv_gg_status *sa, ma_ug_t *ug, uint32_t hapN) -{ - uint32_t i, k, o, f; - ma_utg_t *u; - mcg_node_t s; - for (i = 0; i < sa->n; i++) - { - u = &(ug->u.a[i]); - s = sa->a[i].s; o = 0; - while (s) { - o += (s&1); s>>=1; - } - - f = N_HET; - if(o < hapN) f = C_HET; - for (k = 0; k < u->n; k++) r_het[u->a[k]>>33] = f; - } -} -kv_u_trans_t *get_utg_ovlp(ma_ug_t **ug, asg_t* read_g, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* new_rtg_edges, bub_label_t* b_mask_t, uint8_t* r_het) -{ - ///print_debug_gfa(read_g, *ug, coverage_cut, "init", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); - kv_u_trans_t *ta = pt_pdist(*ug, read_g,coverage_cut, sources, new_rtg_edges, max_hang, min_ovlp, 5); - kv_gg_status *sa = init_mc_gg_status(*ug, read_g, coverage_cut, sources, ruIndex, - asm_opt.hom_global_coverage_set?asm_opt.hom_global_coverage:((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE), - asm_opt.polyploidy); - mc_solve_general(ta, (*ug)->u.n, sa, asm_opt.polyploidy, 1, 1); - if(r_het) set_r_het_status(r_het, sa, *ug, asm_opt.polyploidy); - free(sa->a); free(sa); - return ta; - // ma_ug_seq(*ug, read_g, coverage_cut, sources, new_rtg_edges, max_hang, min_ovlp, 0, 0); - // ug_idx_build(*ug, asm_opt.polyploidy); - // topo_ovlp_collect(*ug, read_g, sources, reverse_sources, coverage_cut, tipsLen, tip_drop_ratio, - // stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, cov); -} - -void output_contig_graph_primary_pre(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, uint64_t bubble_dist, long long tipsLen, -R_to_U* ruIndex, int max_hang, int min_ovlp, const ug_opt_t *uopt) -{ - kvec_asg_arc_t_warp new_rtg_edges; - kv_init(new_rtg_edges.a); - - ma_ug_t *ug = NULL; - ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); - - asg_t* nsg = ug->g; - uint32_t n_vtx = nsg->n_seq, v; - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - nsg->seq[v].c = PRIMARY_LABLE; - EvaluateLen(ug->u, v) = ug->u.a[v].n; - } - - if(bubble_dist > 0) - { - asg_pop_bubble_primary_trio(ug, &bubble_dist, (uint32_t)-1, DROP, NULL, NULL, 0, NULL); - delete_useless_nodes(&ug); - renew_utg(&ug, sg, &new_rtg_edges); - } - - // reset_untig_hap_label(ug, 7, FATHER, R_INF.trio_flag); - // reset_untig_hap_label(ug, 35, FATHER, R_INF.trio_flag); - - // reset_untig_hap_label(ug, 713, FATHER, R_INF.trio_flag); - // reset_untig_hap_label(ug, 273, FATHER, R_INF.trio_flag); - // reset_untig_hap_label(ug, 822, FATHER, R_INF.trio_flag); - - ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 1); - - fprintf(stderr, "Writing processed unitig GFA to disk... \n"); - char* gfa_name = (char*)malloc(strlen(output_file_name)+35); - sprintf(gfa_name, "%s.p_utg.gfa", output_file_name); - FILE* output_file = fopen(gfa_name, "w"); - ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - fclose(output_file); - - sprintf(gfa_name, "%s.p_utg.noseq.gfa", output_file_name); - output_file = fopen(gfa_name, "w"); - ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - fclose(output_file); - if(asm_opt.bed_inconsist_rate != 0) - { - sprintf(gfa_name, "%s.p_utg.lowQ.bed", output_file_name); - output_file = fopen(gfa_name, "w"); - ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, - max_hang, min_ovlp, asm_opt.bed_inconsist_rate, "utg", output_file, NULL); - fclose(output_file); - } - - ///for debug - // graph_ovlp_binning(ug, sg, uopt); - // gen_hpc_re_t(ug); - - free(gfa_name); - ma_ug_destroy(ug); - kv_destroy(new_rtg_edges.a); -} - -void output_contig_graph_primary(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, long long stops_threshold, -R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, bub_label_t* b_mask_t) -{ - ma_ug_t *ug = NULL; - ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); - - kvec_asg_arc_t_warp new_rtg_edges; - kv_init(new_rtg_edges.a); - - adjust_utg_by_primary(&ug, sg, TRIO_THRES, sources, reverse_sources, coverage_cut, - tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, - max_hang, min_ovlp, &new_rtg_edges, NULL, b_mask_t, 0, 0); - - if(asm_opt.b_low_cov > 0) - { - break_ug_contig(&ug, sg, &R_INF, coverage_cut, sources, ruIndex, &new_rtg_edges, max_hang, min_ovlp, - &asm_opt.b_low_cov, NULL, asm_opt.m_rate); - } - if(asm_opt.b_high_cov > 0) - { - break_ug_contig(&ug, sg, &R_INF, coverage_cut, sources, ruIndex, &new_rtg_edges, max_hang, min_ovlp, - NULL, &asm_opt.b_high_cov, asm_opt.m_rate); - } - ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 1); - - - fprintf(stderr, "Writing primary contig GFA to disk... \n"); - char* gfa_name = (char*)malloc(strlen(output_file_name)+35); - sprintf(gfa_name, "%s.p_ctg.gfa", output_file_name); - FILE* output_file = fopen(gfa_name, "w"); - ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "ptg", output_file); - fclose(output_file); - - sprintf(gfa_name, "%s.p_ctg.noseq.gfa", output_file_name); - output_file = fopen(gfa_name, "w"); - ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "ptg", output_file); - fclose(output_file); - if(asm_opt.bed_inconsist_rate != 0) - { - sprintf(gfa_name, "%s.p_ctg.lowQ.bed", output_file_name); - output_file = fopen(gfa_name, "w"); - ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, - max_hang, min_ovlp, asm_opt.bed_inconsist_rate, "ptg", output_file, NULL); - fclose(output_file); - } - - free(gfa_name); - ma_ug_destroy(ug); - kv_destroy(new_rtg_edges.a); -} - - - - -void output_contig_graph_alternative(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, R_to_U* ruIndex, int max_hang, int min_ovlp) -{ - kvec_asg_arc_t_warp new_rtg_edges; - kv_init(new_rtg_edges.a); - ma_ug_t *ug = NULL; - ug = ma_ug_gen_primary(sg, ALTER_LABLE); - - // if(asm_opt.b_low_cov > 0) - // { - // break_ug_contig(&ug, sg, &R_INF, coverage_cut, sources, ruIndex, &new_rtg_edges, max_hang, min_ovlp, asm_opt.b_low_cov); - // } - - ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 1); - - fprintf(stderr, "Writing alternate contig GFA to disk... \n"); - char* gfa_name = (char*)malloc(strlen(output_file_name)+35); - sprintf(gfa_name, "%s.a_ctg.gfa", output_file_name); - FILE* output_file = fopen(gfa_name, "w"); - ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "atg", output_file); - fclose(output_file); - - sprintf(gfa_name, "%s.a_ctg.noseq.gfa", output_file_name); - output_file = fopen(gfa_name, "w"); - ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "atg", output_file); - fclose(output_file); - if(asm_opt.bed_inconsist_rate != 0) - { - sprintf(gfa_name, "%s.a_ctg.lowQ.bed", output_file_name); - output_file = fopen(gfa_name, "w"); - ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, - max_hang, min_ovlp, asm_opt.bed_inconsist_rate, "atg", output_file, NULL); - fclose(output_file); - } - - free(gfa_name); - ma_ug_destroy(ug); - kv_destroy(new_rtg_edges.a); -} - -int output_tips(asg_t *g, const All_reads *RNF) -{ - uint32_t v, n_vtx = g->n_seq * 2; - for (v = 0; v < n_vtx; ++v) - { - if (g->seq[v>>1].del) continue; - - if(asg_arc_n(g, v) == 0) - { - fprintf(stderr, "%.*s\n", - (int)Get_NAME_LENGTH((*RNF), v>>1), - Get_NAME((*RNF), v>>1)); - } - } - - return 1; -} - -void collect_abnormal_edges(ma_hit_t_alloc* paf, ma_hit_t_alloc* rev_paf, long long readNum) -{ - double startTime = Get_T(); - long long T_edges, T_Single_Dir_Edges_0, T_Single_Dir_Edges_1, T_Conflict_Equal_Edges, T_Conflict_Strong_Edges; - T_edges = T_Single_Dir_Edges_0 = T_Single_Dir_Edges_1 = T_Conflict_Equal_Edges = T_Conflict_Strong_Edges = 0; - long long T_Single_Dir_Edges_1_1000 = 0; - long long related_reads = 0; - long long related_overlaps = 0; - long long i, j; - uint32_t qn, tn; - int is_equal_f, is_strong_f; - int is_equal_b, is_strong_b, is_exist_b; - - kvec_t(uint64_t) edge_vector; - kv_init(edge_vector); - - for (i = 0; i < readNum; i++) - { - for (j = 0; j < (long long)paf[i].length; j++) - { - qn = Get_qn(paf[i].buffer[j]); - tn = Get_tn(paf[i].buffer[j]); - T_edges++; - - is_equal_f = paf[i].buffer[j].el; - is_strong_f = paf[i].buffer[j].ml; - - is_exist_b = get_specific_overlap(&(paf[tn]), tn, qn); - if(is_exist_b == -1) - { - is_exist_b = get_specific_overlap(&(rev_paf[tn]), tn, qn); - if(is_exist_b != -1) - { - T_Single_Dir_Edges_0++; - kv_push(uint64_t, edge_vector, qn); - kv_push(uint64_t, edge_vector, tn); - ///related_overlaps += paf[qn].length + rev_paf[qn].length + paf[tn].length + rev_paf[tn].length; - // fprintf(stderr, "%.*s(%d) ---(+)--> %.*s(%d), Len: %d\n", - // Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), qn, - // Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, - // Get_qe(paf[i].buffer[j]) - Get_qs(paf[i].buffer[j])); - - // fprintf(stderr, "%.*s(%d) ---(-)--> %.*s(%d), Len: %d\n\n", - // Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, - // Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), qn, - // Get_qe(rev_paf[tn].buffer[is_exist_b]) - Get_qs(rev_paf[tn].buffer[is_exist_b])); - } - else - { - T_Single_Dir_Edges_1++; - if(Get_qe(paf[i].buffer[j]) - Get_qs(paf[i].buffer[j]) >= 1000) - { - T_Single_Dir_Edges_1_1000++; - // fprintf(stderr, "%.*s(%d) ---(%d)--> %.*s(%d), Len: %d\n\n", - // Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), qn, - // is_strong_f, - // Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, - // Get_qe(paf[i].buffer[j]) - Get_qs(paf[i].buffer[j])); - } - } - - related_reads = related_reads + 2; - } - else - { - is_equal_b = paf[tn].buffer[is_exist_b].el; - is_strong_b = paf[tn].buffer[is_exist_b].ml; - - if(is_equal_f != is_equal_b) - { - T_Conflict_Equal_Edges++; - - // fprintf(stderr, "%.*s(%d) ---(%d)--> %.*s(%d), Len: %d\n", - // Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), qn, - // is_equal_f, - // Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, - // Get_qe(paf[i].buffer[j]) - Get_qs(paf[i].buffer[j])); - - // fprintf(stderr, "%.*s(%d) ---(%d)--> %.*s(%d), Len: %d\n\n", - // Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, - // is_equal_b, - // Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), qn, - // Get_qe(paf[tn].buffer[is_exist_b]) - Get_qs(paf[tn].buffer[is_exist_b])); - } - - if(is_strong_f != is_strong_b) - { - T_Conflict_Strong_Edges++; - // fprintf(stderr, "%.*s(%d) ---(%d)--> %.*s(%d), Len: %d\n", - // Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), qn, - // is_strong_f, - // Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, - // Get_qe(paf[i].buffer[j]) - Get_qs(paf[i].buffer[j])); - - // fprintf(stderr, "%.*s(%d) ---(%d)--> %.*s(%d), Len: %d\n\n", - // Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, - // is_strong_b, - // Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), qn, - // Get_qe(paf[tn].buffer[is_exist_b]) - Get_qs(paf[tn].buffer[is_exist_b])); - } - - if(is_equal_f != is_equal_b || is_strong_f != is_strong_b) - { - related_reads++; - } - } - } - } - - radix_sort_arch64(edge_vector.a, edge_vector.a + edge_vector.n); - uint64_t pre = (uint64_t)-1; - long long mn = 0; - for (i = 0; i < (long long)edge_vector.n; i++) - { - if(pre != edge_vector.a[i]) - { - mn++; - pre = edge_vector.a[i]; - related_overlaps += paf[pre].length + rev_paf[pre].length; - } - - if(i>0 && edge_vector.a[i] < edge_vector.a[i-1]) fprintf(stderr, "hehe\n"); - } - - - - fprintf(stderr, "****************statistic for abnormal overlaps****************\n"); - fprintf(stderr, "overlaps #: %lld\n", T_edges); - fprintf(stderr, "one direction overlaps (different phasing)#: %lld\n", T_Single_Dir_Edges_0); - fprintf(stderr, "one direction overlaps (missing)#: %lld\n", T_Single_Dir_Edges_1); - fprintf(stderr, "one direction overlaps (missing) >= 1000#: %lld\n", T_Single_Dir_Edges_1_1000); - fprintf(stderr, "conflict strong/weak overlaps #: %lld\n", T_Conflict_Strong_Edges); - fprintf(stderr, "conflict exact/inexact overlaps #: %lld\n", T_Conflict_Equal_Edges); - fprintf(stderr, "related_reads #: %lld/%lld\n", related_reads, mn); - fprintf(stderr, "related_overlaps #: %lld\n", related_overlaps); - fprintf(stderr, "****************statistic for abnormal overlaps****************\n"); - - fprintf(stderr, "[M::%s] took %0.2fs\n\n", __func__, Get_T()-startTime); - - kv_destroy(edge_vector); -} - -///if we don't have this function, we just simply remove all one-direction edges -///by utilizing this function, some one-direction edges can be recovered as two-direction edges -///trio does not influence this function -void try_rescue_overlaps(ma_hit_t_alloc* paf, ma_hit_t_alloc* rev, uint64_t rn, uint64_t rescue_threshold, uint32_t is_del) -{ - double startTime = Get_T(); - int64_t revises = 0, dd, dp, old_dp, start, max_dp, m; uint32_t qn, tn, qs, qe; uint64_t ff, i, j; ma_sub_t max_interval; - kvec_t(uint64_t) ev; kv_init(ev); - kvec_t(uint64_t) evi; kv_init(evi); - kvec_t(uint32_t) b; kv_init(b); - - for (i = 0; i < rn; i++) { - ev.n = evi.n = 0; - for (j = 0; j < rev[i].length; j++) { - if(is_del && rev[i].buffer[j].del) continue; - qn = Get_qn(rev[i].buffer[j]); tn = Get_tn(rev[i].buffer[j]); - dd = get_specific_overlap(&(paf[tn]), tn, qn); - if((dd != -1) && ((!is_del) || (paf[tn].buffer[dd].del == 0))) { - ff = tn; ff <<= 32; ff |= (uint64_t)(dd); - kv_push(uint64_t, ev, ff); kv_push(uint64_t, evi, j); - } - } - - ///based on qn, all edges at edge_vector/edge_vector_index come from different haplotype - ///but at another direction, all these edges come from the same haplotype - //here we want to recover these edges - if(evi.n >= rescue_threshold) { - kv_resize(uint32_t, b, evi.n); b.n = 0; - for (j = 0; j < evi.n; j++) { - qs = Get_qs(rev[i].buffer[evi.a[j]]); - qe = Get_qe(rev[i].buffer[evi.a[j]]); - kv_push(uint32_t, b, qs<<1); - kv_push(uint32_t, b, qe<<1|1); - } - - ks_introsort_uint32_t(b.n, b.a); - dp = 0, start = 0, max_dp = 0; - max_interval.s = max_interval.e = 0; - for (j = 0, dp = 0; j < b.n; ++j) { - old_dp = dp; - ///if a[j] is qe - if (b.a[j]&1) --dp; - else ++dp; - - if(old_dp < dp) {///b.a[j] is qs - ///case 2, a[j] is qs - //here should use dp >= max_dp, instead of dp > max_dp - if(dp >= max_dp) { - start = b.a[j]>>1; - max_dp = dp; - } - } else if (old_dp > dp) {///old_dp > min_dp, b.a[j] is qe - if(old_dp == max_dp) { - max_interval.s = start; - max_interval.e = b.a[j]>>1; - } - } - } - - if(((uint64_t)max_dp) >= rescue_threshold) { - m = 0; - for (j = 0; j < evi.n; j++) { - qs = Get_qs(rev[i].buffer[evi.a[j]]); - qe = Get_qe(rev[i].buffer[evi.a[j]]); - if(qs <= max_interval.s && qe >= max_interval.e) { - evi.a[m] = evi.a[j]; ev.a[m] = ev.a[j]; m++; - } - } - evi.n = ev.n = m; - - ///the read itself do not have these overlaps, but all related reads have - ///we need to remove all overlaps from rev_paf[i], and then add all overlaps to paf[i] - remove_overlaps(&(rev[i]), evi.a, evi.n); - add_overlaps_from_different_sources(paf, &(paf[i]), ev.a, ev.n); - revises = revises + ev.n; - } - } - } - - - kv_destroy(ev); kv_destroy(evi); kv_destroy(b); - if(VERBOSE >= 1) { - fprintf(stderr, "[M::%s] took %0.2fs, rescue edges #: %ld\n\n", __func__, Get_T()-startTime, revises); - } - -} - - - -long long get_coverage(ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, uint64_t n_read) -{ - uint64_t i, j; - ma_hit_t *h; - long long R_bases = 0, C_bases = 0; - for (i = 0; i < n_read; ++i) - { - R_bases += coverage_cut[i].e - coverage_cut[i].s; - for (j = 0; j < (uint64_t)(sources[i].length); j++) - { - h = &(sources[i].buffer[j]); - C_bases += Get_qe((*h)) - Get_qs((*h)); - } - } - - return C_bases/R_bases; -} - - -void pre_clean(ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, asg_t *sg, uint32_t pop_s_node) -{ - int tri_flag = 0; - while(1) - { - tri_flag = 0; - ///remove very simple circle - tri_flag += asg_arc_del_simple_circle_untig(sources, coverage_cut, sg, 100, 0); - - ///remove isoloated single read - if(pop_s_node) - { - tri_flag += asg_arc_del_single_node_directly(sg, asm_opt.max_short_tip, sources);///remove very small bubbles - } - - // if ((!ha_opt_triobin(&asm_opt))&&(!ha_opt_hic(&asm_opt))) - // { - // tri_flag += asg_arc_del_triangular_advance(sg, bubble_dist); - // ///remove the cross at the bubble carefully, just remove inexact cross - // tri_flag += asg_arc_del_cross_bubble(sg, bubble_dist); - // } - // tri_flag += asg_arc_del_single_node_directly(sg, asm_opt.max_short_tip, sources); - - if(tri_flag == 0) - { - break; - } - } -} - - -void init_R_to_U(R_to_U* x, uint64_t len) -{ - x->len = len; - CALLOC(x->index, x->len); - x->is_het = NULL; -} - -void destory_R_to_U(R_to_U* x) -{ - free(x->index); -} - -void set_R_to_U(R_to_U* x, uint32_t rID, uint32_t uID, uint32_t is_Unitig, uint8_t* flag) -{ - if(flag && (*flag) == FAKE_LABLE) return; - - if(rID >= x->len) - { - x->index = (uint32_t*)realloc(x->index, (rID + 1)*sizeof(uint32_t)); - memset(x->index + x->len, -1, sizeof(uint32_t)*((rID + 1) - x->len)); - x->len = rID + 1; - } - - x->index[rID] = uID & (uint32_t)(0x7fffffff); - x->index[rID] = x->index[rID] | (uint32_t)(is_Unitig<<31); -} - - -void get_R_to_U(R_to_U* x, uint32_t rID, uint32_t* uID, uint32_t* is_Unitig) -{ - if(rID >= x->len || (x->index[rID] == (uint32_t)(-1))) - { - (*uID) = (uint32_t)-1; - (*is_Unitig) = (uint32_t)-1; - return; - } - - (*uID) = x->index[rID] & (uint32_t)(0x7fffffff); - (*is_Unitig) = (x->index[rID]>>31); -} - -void transfor_R_to_U(R_to_U* x) -{ - uint64_t i = 0; - uint32_t rID, uID, is_Unitig; - for (i = 0; i < x->len; i++) - { - rID = i; - get_R_to_U(x, rID, &uID, &is_Unitig); - if(uID == (uint32_t)-1) continue; - if(is_Unitig == 1) continue; - - - ///here i/rID is contained in uID - rID = uID; - while (1) - { - get_R_to_U(x, rID, &uID, &is_Unitig); - if(uID == (uint32_t)-1) break; - if(is_Unitig == 1) break; - rID = uID; - } - - set_R_to_U(x, i, rID, 0, NULL); - } - - - /** - for (i = 0; i < x->len; i++) - { - rID = i; - get_R_to_U(x, rID, &uID, &is_Unitig); - if(uID == (uint32_t)-1) continue; - if(is_Unitig == 1) continue; - ///here i/rID is contained in uID - rID = uID; - get_R_to_U(x, rID, &uID, &is_Unitig); - if(uID != (uint32_t)-1) - { - fprintf(stderr, "ERROR\n"); - } - } - **/ - -} - - - -void asg_delete_node_by_trio(asg_t* sg, uint8_t flag) -{ - uint32_t v, n_vtx = sg->n_seq; - for (v = 0; v < n_vtx; ++v) - { - if (sg->seq[v].del) continue; - if (R_INF.trio_flag[v] == AMBIGU) continue; - if(R_INF.trio_flag[v] != flag) asg_seq_del(sg, v); - } - asg_cleanup(sg); -} - - - -void renew_graph_init(ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, asg_t *sg, ma_sub_t *coverage_cut, R_to_U* ruIndex, uint64_t n_read) -{ - if(sg != NULL) asg_destroy(sg); - sg = NULL; - - if(coverage_cut != NULL) free(coverage_cut); - coverage_cut = NULL; - - memset(ruIndex->index, -1, sizeof(uint32_t)*(ruIndex->len)); - - - uint64_t i = 0, j = 0; - for (i = 0; i < n_read; i++) { - for (j = 0; j < sources[i].length; j++) { - sources[i].buffer[j].del = 0; - } - - for (j = 0; j < reverse_sources[i].length; j++) { - reverse_sources[i].buffer[j].del = 0; - } - } -} - - - - -inline uint32_t get_num_edges2existing_nodes_advance(ma_ug_t *ug, asg_t *g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, uint32_t* oLen, uint32_t* skip_uId, uint32_t skip_uId_n, uint32_t ignore_trio_flag) -{ - (*oLen) = 0; - uint32_t qn = query>>1; - int32_t r; - asg_arc_t t; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - ma_hit_t_alloc* x = &(sources[qn]); - uint32_t i, k, occ = 0, uId, is_Unitig, v, w; - - uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; - if(ignore_trio_flag == 0) - { - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - } - - - - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - ///sq has already been removed - ///st must not be removed - ///g-seq must not be removed - if(st->del || g->seq[Get_tn(*h)].del) continue; - if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - - ///if it is a contained read, skip - if(r < 0) continue; - - if((t.ul>>32) != query) continue; - get_R_to_U(ruIndex, t.v>>1, &uId, &is_Unitig); - /****************************may have bugs********************************/ - if(uId == (uint32_t)-1 || is_Unitig == 0) continue; - /****************************may have bugs********************************/ - for (k = 0; k < skip_uId_n; k++) - { - if(uId == skip_uId[k]) break; - } - if(k != skip_uId_n) continue; - // if(uId == skip_uId1) continue; - // if(uId == skip_uId2) continue; - /****************************may have bugs********************************/ - if(ug->g->seq[uId].del) continue; - /****************************may have bugs********************************/ - - if((t.v != ug->u.a[uId].start) - && - (t.v != ug->u.a[uId].end)) - { - continue; - } - /**********for debug*************/ - if(t.v == ug->u.a[uId].start) - { - ///v = uId<<1; - v = (uId<<1)^1; - } - - if(t.v == ug->u.a[uId].end) - { - ///v = (uId<<1)^1; - v = uId<<1; - } - - if(get_real_length(ug->g, v, NULL)==1) - { - get_real_length(ug->g, v, &w); - if(get_real_length(ug->g, w^1, NULL)==1) - { - continue; - } - } - /**********for debug*************/ - - occ++; - (*oLen) += t.ol; - } - - return occ; -} - - -inline uint32_t get_num_edges2existing_nodes_advance_by_broken_bub(ma_ug_t *ug, asg_t *g, -ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, uint8_t* expect_vis, -int max_hang, int min_ovlp, uint32_t query, uint32_t* oLen, uint8_t* utg_vis, -uint32_t ignore_trio_flag) -{ - (*oLen) = 0; - uint32_t qn = query>>1, is_first = 1;; - int32_t r; - asg_arc_t t; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - ma_hit_t_alloc* x = &(sources[qn]); - uint32_t i, occ = 0, uId, is_Unitig; - - uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; - if(ignore_trio_flag == 0) - { - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - } - - - - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - ///sq has already been removed - ///st must not be removed - ///g-seq must not be removed - if(st->del || g->seq[Get_tn(*h)].del) continue; - if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - - ///if it is a contained read, skip - if(r < 0) continue; - - if((t.ul>>32) != query) continue; - get_R_to_U(ruIndex, t.v>>1, &uId, &is_Unitig); - if(uId == (uint32_t)-1 || is_Unitig == 0 || ug->g->seq[uId].del) continue; - if(expect_vis[t.v>>1] == 0) continue; - - if(is_first && utg_vis) memset(utg_vis, 0, ug->g->n_seq); - if(utg_vis == NULL || (utg_vis && utg_vis[uId] == 0)) occ++; - ////fprintf(stderr, "found-utg%.6ul, occ: %u\n", uId+1, occ); - if(utg_vis) utg_vis[uId] = 1; - - (*oLen) += t.ol; - is_first = 0; - } - - return occ; -} - - - -inline uint32_t get_edge2existing_node_advance(ma_ug_t *ug, asg_t *g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, uint32_t* skip_uId, uint32_t skip_uId_n, -uint32_t* index, asg_arc_t* t, uint32_t ignore_trio_flag) -{ - uint32_t qn = query>>1, uId, is_Unitig, v, w, k; - int32_t r; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - ma_hit_t_alloc* x = &(sources[qn]); - - uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; - if(ignore_trio_flag == 0) - { - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - } - - - - for (; (*index) < x->length; (*index)++) - { - h = &(x->buffer[(*index)]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - ///sq has already been removed - ///st must not be removed - ///g-seq must not be removed - if(st->del || g->seq[Get_tn(*h)].del) continue; - if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, t); - - ///if it is a contained read, skip - if(r < 0) continue; - - if((t->ul>>32) != query) continue; - get_R_to_U(ruIndex, t->v>>1, &uId, &is_Unitig); - /****************************may have bugs********************************/ - if(uId == (uint32_t)-1 || is_Unitig == 0) continue; - /****************************may have bugs********************************/ - for (k = 0; k < skip_uId_n; k++) - { - if(uId == skip_uId[k]) break; - } - if(k != skip_uId_n) continue; - // if(uId == skip_uId1) continue; - // if(uId == skip_uId2) continue; - /****************************may have bugs********************************/ - if(ug->g->seq[uId].del) continue; - /****************************may have bugs********************************/ - - if((t->v != ug->u.a[uId].start) - && - (t->v != ug->u.a[uId].end)) - { - continue; - } - - /**********for debug*************/ - if(t->v == ug->u.a[uId].start) - { - ///v = uId<<1; - v = (uId<<1)^1; - } - - if(t->v == ug->u.a[uId].end) - { - ///v = (uId<<1)^1; - v = uId<<1; - } - - if(get_real_length(ug->g, v, NULL)==1) - { - get_real_length(ug->g, v, &w); - if(get_real_length(ug->g, w^1, NULL)==1) - { - continue; - } - } - /**********for debug*************/ - - (*index)++; - return 1; - } - - return 0; -} - - -inline uint32_t get_edge2existing_node_advance_by_broken_bub(ma_ug_t *ug, asg_t *g, -ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, uint8_t* expect_vis, -int max_hang, int min_ovlp, uint32_t query, uint32_t* index, asg_arc_t* t, -uint32_t ignore_trio_flag) -{ - uint32_t qn = query>>1, uId, is_Unitig; - int32_t r; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - ma_hit_t_alloc* x = &(sources[qn]); - - uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; - if(ignore_trio_flag == 0) - { - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - } - - - - for (; (*index) < x->length; (*index)++) - { - h = &(x->buffer[(*index)]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - ///sq has already been removed - ///st must not be removed - ///g-seq must not be removed - if(st->del || g->seq[Get_tn(*h)].del) continue; - if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, t); - - ///if it is a contained read, skip - if(r < 0) continue; - - if((t->ul>>32) != query) continue; - get_R_to_U(ruIndex, t->v>>1, &uId, &is_Unitig); - if(uId == (uint32_t)-1 || is_Unitig == 0 || ug->g->seq[uId].del) continue; - if(expect_vis[t->v>>1] == 0) continue; - - (*index)++; - return 1; - } - - return 0; -} - - - -inline uint32_t get_num_edges2existing_nodes(ma_ug_t *ug, asg_t *g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, uint32_t* oLen, -uint32_t skip_uId1, uint32_t skip_uId2) -{ - (*oLen) = 0; - uint32_t qn = query>>1; - int32_t r; - asg_arc_t t; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - ma_hit_t_alloc* x = &(sources[qn]); - uint32_t i, occ = 0, uId, is_Unitig, v, w; - - - uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - - - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - ///sq has already been removed - ///st must not be removed - ///g-seq must not be removed - if(st->del || g->seq[Get_tn(*h)].del) continue; - if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - - ///if it is a contained read, skip - if(r < 0) continue; - - if((t.ul>>32) != query) continue; - get_R_to_U(ruIndex, t.v>>1, &uId, &is_Unitig); - /****************************may have bugs********************************/ - if(uId == (uint32_t)-1 || is_Unitig == 0) continue; - /****************************may have bugs********************************/ - if(uId == skip_uId1) continue; - if(uId == skip_uId2) continue; - /****************************may have bugs********************************/ - if(ug->g->seq[uId].del) continue; - /****************************may have bugs********************************/ - - if((t.v != ug->u.a[uId].start) - && - (t.v != ug->u.a[uId].end)) - { - continue; - } - /**********for debug*************/ - if(t.v == ug->u.a[uId].start) - { - ///v = uId<<1; - v = (uId<<1)^1; - } - - if(t.v == ug->u.a[uId].end) - { - ///v = (uId<<1)^1; - v = uId<<1; - } - - if(get_real_length(ug->g, v, NULL)==1) - { - get_real_length(ug->g, v, &w); - if(get_real_length(ug->g, w^1, NULL)==1) - { - continue; - } - } - /**********for debug*************/ - - occ++; - (*oLen) += t.ol; - } - - return occ; -} - - -inline uint32_t get_edge2existing_node(ma_ug_t *ug, asg_t *g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, uint32_t skip_uId1, uint32_t skip_uId2, -uint32_t* index, asg_arc_t* t) -{ - uint32_t qn = query>>1, uId, is_Unitig, v, w; - int32_t r; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - ma_hit_t_alloc* x = &(sources[qn]); - - uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - - - for (; (*index) < x->length; (*index)++) - { - h = &(x->buffer[(*index)]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - ///sq has already been removed - ///st must not be removed - ///g-seq must not be removed - if(st->del || g->seq[Get_tn(*h)].del) continue; - if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, t); - - ///if it is a contained read, skip - if(r < 0) continue; - - if((t->ul>>32) != query) continue; - get_R_to_U(ruIndex, t->v>>1, &uId, &is_Unitig); - /****************************may have bugs********************************/ - if(uId == (uint32_t)-1 || is_Unitig == 0) continue; - /****************************may have bugs********************************/ - if(uId == skip_uId1) continue; - if(uId == skip_uId2) continue; - /****************************may have bugs********************************/ - if(ug->g->seq[uId].del) continue; - /****************************may have bugs********************************/ - - if((t->v != ug->u.a[uId].start) - && - (t->v != ug->u.a[uId].end)) - { - continue; - } - - /**********for debug*************/ - if(t->v == ug->u.a[uId].start) - { - ///v = uId<<1; - v = (uId<<1)^1; - } - - if(t->v == ug->u.a[uId].end) - { - ///v = (uId<<1)^1; - v = uId<<1; - } - - if(get_real_length(ug->g, v, NULL)==1) - { - get_real_length(ug->g, v, &w); - if(get_real_length(ug->g, w^1, NULL)==1) - { - continue; - } - } - /**********for debug*************/ - - (*index)++; - return 1; - } - - return 0; -} - - - -uint32_t get_edge_from_source(ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, uint32_t target, asg_arc_t* t) -{ - uint32_t qn = query>>1, i; - int32_t r; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - ma_hit_t_alloc* x = &(sources[qn]); - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, t); - - ///if it is a contained read, skip - if(r < 0) continue; - - if((t->ul>>32) != query) continue; - if(t->v != target) continue; - - return 1; - } - - return 0; -} - -void append_rId_to_Unitig(asg_t *r_g, ma_ug_t* ug, uint32_t uId, uint32_t rId, -ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp) -{ - asg_arc_t t; - t.ul = (uint64_t)-1; - ma_utg_t *nsu = &(ug->u.a[uId>>1]); - uint32_t l, i, beg, end; - - if(nsu->m < (nsu->n+1)) - { - nsu->m = nsu->n+1; - nsu->a = (uint64_t*)realloc(nsu->a, nsu->m*sizeof(uint64_t)); - } - - if((uId&1) == 0) - { - beg = nsu->end^1; - end = rId; - } - - if((uId&1) == 1) - { - beg = rId^1; - end = nsu->start; - } - - ///t is the edge that from beg to end - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, beg, - end, &t); - - ///add rId to the end of nsu - if((uId&1) == 0) - { - nsu->len -= (uint32_t)nsu->a[nsu->n-1]; - - l = r_g->seq[rId>>1].len; - nsu->a[nsu->n] = rId; - nsu->a[nsu->n] <<=32; - nsu->a[nsu->n] = nsu->a[nsu->n] | (uint64_t)(l); - - l = asg_arc_len(t); - nsu->a[nsu->n-1] = nsu->a[nsu->n-1]>>32; - nsu->a[nsu->n-1] = nsu->a[nsu->n-1]<<32; - nsu->a[nsu->n-1] = nsu->a[nsu->n-1] | (uint64_t)(l); - - nsu->len = nsu->len + (uint32_t)nsu->a[nsu->n-1] + (uint32_t)nsu->a[nsu->n]; - nsu->end = rId^1; - - nsu->n++; - } - - ///add rId to the start of nsu - if((uId&1) == 1) - { - rId = rId^1; - for(i = nsu->n; i >= 1; i--) - { - nsu->a[i] = nsu->a[i-1]; - } - - l = asg_arc_len(t); - nsu->a[0] = rId; - nsu->a[0] = nsu->a[0]<<32; - nsu->a[0] = nsu->a[0] | (uint64_t)(l); - nsu->len = nsu->len + (uint32_t)nsu->a[0]; - nsu->start = rId; - - nsu->n++; - } - - - set_R_to_U(ruIndex, rId>>1, uId>>1, 1, &(r_g->seq[rId>>1].c)); - - - - - /*************************just for debug**************************/ - uint32_t v, totalLen = 0; - v = (uint64_t)(nsu->a[0])>>32; - if(nsu->start != UINT32_MAX && nsu->start != v) fprintf(stderr, "hehe\n"); - - v = (uint64_t)(nsu->a[nsu->n-1])>>32; - if(nsu->end != UINT32_MAX && nsu->end != (v^1)) fprintf(stderr, "haha\n"); - - for (i = 0; i < nsu->n; i++) - { - l = (uint32_t)(nsu->a[i]); - totalLen = totalLen + l; - } - if(totalLen != nsu->len) fprintf(stderr, "xxxx\n"); - - ////fprintf(stderr, "utg%.6dl, dir: %u\n", uId+1, uId&1); - /*************************just for debug**************************/ - -} - - - - -void lable_all_bubbles(asg_t *r_g, bub_label_t* b_mask_t) -{ - ///must have this line, otherwise asg_arc_identify_simple_bubbles_multi will be wrong - asg_cleanup(r_g); - asg_arc_identify_simple_bubbles_multi(r_g, b_mask_t, 0); -} - - -void drop_inexact_edegs_at_bubbles(asg_t *r_g, bub_label_t* b_mask_t, uint64_t bubble_dist) -{ - asg_arc_identify_simple_bubbles_multi(r_g, b_mask_t, 0); - - uint32_t v, k, i, n_vtx = r_g->n_seq * 2, nv, flag, n_reduce = 0; - uint64_t oLen; - asg_arc_t *av = NULL; - - if (!r_g->is_symm) asg_symm(r_g); - - buf_t b; - memset(&b, 0, sizeof(buf_t)); - - kvec_t(uint64_t) e; - kv_init(e); - - b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - for (v = 0; v < n_vtx; ++v) - { - nv = asg_arc_n(r_g, v); - if(r_g->seq[v>>1].del) continue; - if(r_g->seq_vis[v] != 0) continue; - if(nv < 2) continue; - - - ///if this is a bubble - if(asg_bub_finder_without_del_advance(r_g, v, bubble_dist, &b) == 1) - { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (i = 0; i < b.b.n; i++) - { - if(b.b.a[i] == v) continue; - //note b.b include end, does not include beg - if(b.b.a[i] == b.S.a[0]) - { - b.b.a[i] = b.b.a[i]^1; - continue; - } - - r_g->seq_vis[b.b.a[i]] = 2; - r_g->seq_vis[b.b.a[i]^1] = 2; - } - - r_g->seq_vis[v] = 2; - r_g->seq_vis[b.S.a[0]^1] = 2; - - - //note b.b include end, does not include beg - //so push beg into b.b - kv_push(uint32_t, b.b, v); - for (i = 0; i < b.b.n; i++) - { - nv = asg_arc_n(r_g, b.b.a[i]); - if(nv <= 1) continue; - av = asg_arc_a(r_g, b.b.a[i]); - e.n = 0; - flag = 0; - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].el) - { - flag = 1; - continue; - } - oLen = av[k].ol; - oLen = oLen << 32; - oLen = oLen | (uint64_t)(k); - kv_push(uint64_t, e, oLen); - } - - if(flag == 0 || e.n == 0) continue; - - if(e.n>1) radix_sort_arch64(e.a, e.a + e.n); - - for (k = 0; k < e.n; k++) - { - if(get_real_length(r_g, av[(uint32_t)e.a[k]].v^1, NULL)<=1) continue; - av[(uint32_t)e.a[k]].del = 1; - asg_arc_del(r_g, av[(uint32_t)e.a[k]].v^1, av[(uint32_t)e.a[k]].ul>>32^1, 1); - n_reduce++; - } - - } - } - } - - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - kv_destroy(e); - if(n_reduce > 0) asg_cleanup(r_g); -} - - -uint32_t get_corresponding_uId(ma_ug_t *ug, R_to_U* ruIndex, uint32_t t) -{ - uint32_t w, uId, is_Unitig; - get_R_to_U(ruIndex, t>>1, &uId, &is_Unitig); - /****************************may have bugs********************************/ - if(uId == ((uint32_t)(-1)) || is_Unitig == 0) return ((uint32_t)(-1)); - if(ug->g->seq[uId].del) return ((uint32_t)(-1)); - /****************************may have bugs********************************/ - w = (uint32_t)-1; - if(t == ug->u.a[uId].start) w = uId<<1; - if(t == ug->u.a[uId].end) w = (uId<<1)^1; - return w; -} - -void minor_transitive_reduction(ma_ug_t *ug, R_to_U* ruIndex, asg_arc_t* rbub_edges, uint32_t num) -{ - asg_t* nsg = ug->g; - uint32_t i, j, k, uId, nv, w; - asg_arc_t* t = NULL; - asg_arc_t* p = NULL; - asg_arc_t *av = NULL; - ///here all edges from v are saved in rbub_edges - ///for edges already in graph, need to check del - ///but for edges in rbub_edges, don't check del - for (i = 0; i < num; i++) - { - t = &rbub_edges[i]; - ///if(t->del) continue; - uId = get_corresponding_uId(ug, ruIndex, t->v); - if(uId == ((uint32_t)(-1))) continue; - - nv = asg_arc_n(nsg, uId); - av = asg_arc_a(nsg, uId); - for (j = 0; j < nv; j++) - { - if(av[j].del) continue; - w = av[j].v; - - ///note w is the unitig ID - for (k = 0; k < num; k++) - { - p = &rbub_edges[k]; - ///if(p->del) continue; - ///this line is not necessary at all - if(k==i) continue; - ///w is the unitig ID, p->v is the read ID - if(get_corresponding_uId(ug, ruIndex, p->v) == w) p->del = 1; - } - } - } -} - - - - -///find contained read with longest overlap -ma_hit_t* get_best_contained_read(ma_ug_t *ug, asg_t *r_g, ma_hit_t_alloc* sources, -ma_sub_t *coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, -uint32_t ignore_trio_flag) -{ - uint32_t qn = query>>1; - int32_t r; - asg_arc_t t; - ma_hit_t *h = NULL, *return_h = NULL; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - ma_hit_t_alloc* x = &(sources[qn]); - uint32_t i, is_Unitig, contain_rId, contain_uId; - uint32_t maxOlen = 0; - asg_t* nsg = ug->g; - - uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; - if(ignore_trio_flag == 0) - { - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - } - - //scan all edges of qn - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - ///just need deleted edges - ///sq might be deleted or not - if(!st->del) continue; - if(!h->del) continue; - if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; - - ///tn must be contained in another existing read - get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); - if(contain_rId == (uint32_t)-1 || is_Unitig == 1) continue; - if(r_g->seq[contain_rId].del) continue; - - get_R_to_U(ruIndex, contain_rId, &contain_uId, &is_Unitig); - if(contain_uId == (uint32_t)-1 || is_Unitig != 1) continue; - if(nsg->seq[contain_uId].del) continue; - ///contain_uId must be a unitig - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - - ///if it is a contained read, skip - if(r < 0) continue; - - if((t.ul>>32) != query) continue; - - if(t.ol > maxOlen) - { - maxOlen = t.ol; - return_h = h; - } - } - - return return_h; -} - -///find contained read with longest overlap -ma_hit_t* get_best_cmk_read(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, uint32_t ignore_trio_flag, uint8_t *cmk) -{ - uint32_t qn = query>>1; int32_t r; - asg_arc_t t; ma_hit_t *h = NULL, *return_h = NULL; - ma_sub_t *sq = NULL; ma_sub_t *st = NULL; - ma_hit_t_alloc* x = &(sources[qn]); - uint32_t i, is_Unitig, contain_rId, maxOlen = 0; - uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; - - if(ignore_trio_flag == 0) { - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - } - - //scan all edges of qn - for (i = 0; i < x->length; i++) { - h = &(x->buffer[i]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - ///just need deleted edges - ///sq might be deleted or not - if((!st->del) || (!h->del) || (!rg->seq[Get_tn(*h)].del)) continue; - // if(cmk[Get_tn(*h)] != ((uint8_t)-1)) continue; - // if(cmk[Get_tn(*h)] == ((uint8_t)-1)) continue; - if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; - - ///tn must be contained in another existing read - get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); - if(is_Unitig == 1) continue; - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - - ///if it is a contained read, skip - if(r < 0) continue; - - if((t.ul>>32) != query) continue; - - if(t.ol > maxOlen) { - maxOlen = t.ol; - return_h = h; - } - } - - return return_h; -} - - - -int get_contained_reads_chain(ma_hit_t *h, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, ma_ug_t *ug, asg_t *r_g, int max_hang, int min_ovlp, uint32_t endRid, uint32_t uId, -kvec_t_u32_warp* chain_buffer, kvec_asg_arc_t_warp* chain_edges, uint32_t* return_ava_cur, -uint32_t* return_ava_ol, uint32_t* return_chainLen, uint32_t thresLen, uint32_t ignore_trio_flag) -{ - (*return_chainLen) = (*return_ava_cur) = (*return_ava_ol) = (uint32_t)-1; - uint32_t trio_flag, non_trio_flag = (uint32_t)-1, contain_rId, contain_uId, is_Unitig; - uint32_t chainLen = 0, ava_cur, test_oLen; - int ql, tl; - int32_t r; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - asg_arc_t t; - asg_t* nsg = ug->g; - chain_buffer->a.n = 0; - kv_push(uint32_t, chain_buffer->a, uId); - if(chain_edges) chain_edges->a.n = 0; - - - ///continue - ///need to update h, endRid, chainLen, chain_buffer and chain_edges - while (h) - { - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - trio_flag = R_INF.trio_flag[Get_qn(*h)]; - - ///don't want to edges between different haps - non_trio_flag = (uint32_t)-1; - if(ignore_trio_flag == 0) - { - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) break; - } - - ///just need deleted edges - ///sq might be deleted or not - if(!st->del) break; - if(!h->del) break; - - ///tn must be contained in another existing read - get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); - if(contain_rId == (uint32_t)-1 || is_Unitig == 1) break; - if(r_g->seq[contain_rId].del) break; - - get_R_to_U(ruIndex, contain_rId, &contain_uId, &is_Unitig); - if(contain_uId == (uint32_t)-1 || is_Unitig != 1) break; - if(nsg->seq[contain_uId].del) break; - ///contain_uId must be a unitig - - ql = sq->e - sq->s; tl = st->e - st->s; - r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - - ///if st is contained in sq, or vice verse, skip - if(r < 0) break; - - ///if sq and v are not in the same direction, skip - ///endRid is (t.ul>>32), and t.v is a contained read - if((t.ul>>32) != endRid) break; - - if(chain_edges) kv_push(asg_arc_t, chain_edges->a, t); - chainLen++; - kv_push(uint32_t, chain_buffer->a, contain_uId); - ///endRid is (t.ul>>32), and t.v is a contained read - ///find edges from t.v to existing unitigs - ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, sources, coverage_cut, ruIndex, - max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, - ignore_trio_flag); - //means find an aim - if(ava_cur > 0) - { - /** - //do nothing if the chainLen == 1 - if(chainLen > 1) - { - asg_arc_t t_max; - ma_hit_t_alloc* x = &(sources[(endRid>>1)]); - uint32_t ava_ol_max = 0, ava_max = 0, k; - for (k = 0; k < x->length; k++) - { - h = &(x->buffer[k]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - trio_flag = R_INF.trio_flag[Get_qn(*h)]; - - ///don't want to edges between different haps - non_trio_flag = (uint32_t)-1; - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; - - ///just need deleted edges - ///sq might be deleted or not - if(!st->del) continue; - if(!h->del) continue; - - ///tn must be contained in another existing read - get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); - if(contain_rId == (uint32_t)-1 || is_Unitig == 1) continue; - if(r_g->seq[contain_rId].del) continue; - - get_R_to_U(ruIndex, contain_rId, &contain_uId, &is_Unitig); - if(contain_uId == (uint32_t)-1 || is_Unitig != 1) continue; - if(nsg->seq[contain_uId].del) continue; - ///contain_uId must be a unitig - - ql = sq->e - sq->s; tl = st->e - st->s; - r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - - ///if st is contained in sq, or vice verse, skip - if(r < 0) continue; - - ///if sq and v are not in the same direction, skip - if((t.ul>>32) != endRid) continue; - - ///pop the last contain_uId - chain_buffer->a.n--; - kv_push(uint32_t, chain_buffer->a, contain_uId); - - ///note: t.v is a contained read - ///we need to find existing reads linked with w - ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, sources, coverage_cut, ruIndex, - max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, 1); - - if((ava_cur > ava_max) || (ava_cur == ava_max && test_oLen > ava_ol_max)) - { - ava_max = ava_cur; - ava_ol_max = test_oLen; - t_max = t; - } - } - - if(ava_max > 0) - { - ava_cur = ava_max; - test_oLen = ava_ol_max; - if(chain_edges) - { - //pop the last edge - chain_edges->a.n--; - kv_push(asg_arc_t, chain_edges->a, t_max); - } - } - else - { - break; - } - } - **/ - - (*return_ava_cur) = ava_cur; - (*return_ava_ol) = test_oLen; - (*return_chainLen) = chainLen; - h = NULL; - return 1; - } - - if(chainLen >= thresLen) break; - - ///endRid is (t.ul>>32), and t.v is a contained read - ///haven't found a existing unitig from t.v - ///check if t.v can link to a new contained read - endRid = t.v; - h = get_best_contained_read(ug, r_g, sources, coverage_cut, ruIndex, - max_hang, min_ovlp, endRid, ignore_trio_flag); - } - - return 0; -} - - -int get_chimeric_reads_chain(ma_hit_t *h, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, ma_ug_t *ug, asg_t *rg, int max_hang, int min_ovlp, uint32_t endRid, uint32_t uId, -kvec_t_u32_warp* chain_buffer, kvec_asg_arc_t_warp* chain_edges, uint32_t* return_ava_cur, -uint32_t* return_ava_ol, uint32_t* return_chainLen, uint32_t thresLen, uint32_t ignore_trio_flag, uint8_t *cmk) -{ - (*return_chainLen) = (*return_ava_cur) = (*return_ava_ol) = (uint32_t)-1; - uint32_t trio_flag, non_trio_flag = (uint32_t)-1, contain_rId, is_Unitig; - uint32_t chainLen = 0, ava_cur, test_oLen; int ql, tl; int32_t r; - ma_sub_t *sq = NULL; ma_sub_t *st = NULL; asg_arc_t t; - chain_buffer->a.n = 0; kv_push(uint32_t, chain_buffer->a, uId); - if(chain_edges) chain_edges->a.n = 0; - - - ///continue - ///need to update h, endRid, chainLen, chain_buffer and chain_edges - while (h) { - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - trio_flag = R_INF.trio_flag[Get_qn(*h)]; - - ///don't want to edges between different haps - non_trio_flag = (uint32_t)-1; - if(ignore_trio_flag == 0) { - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) break; - } - - ///just need deleted edges - ///sq might be deleted or not - if((!st->del) || (!h->del) || (!rg->seq[Get_tn(*h)].del)) break; - // if(cmk[Get_tn(*h)] != ((uint8_t)-1)) break; - // if(cmk[Get_tn(*h)] == ((uint8_t)-1)) break; - - ///tn must be contained in another existing read - get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); - if(is_Unitig == 1) break; - - ql = sq->e - sq->s; tl = st->e - st->s; - r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - - ///if st is contained in sq, or vice verse, skip - if(r < 0) break; - - ///if sq and v are not in the same direction, skip - ///endRid is (t.ul>>32), and t.v is a contained read - if((t.ul>>32) != endRid) break; - - if(chain_edges) kv_push(asg_arc_t, chain_edges->a, t); - chainLen++; - ///endRid is (t.ul>>32), and t.v is a contained read - ///find edges from t.v to existing unitigs - ///chain_buffer->a.n always be 1 - ava_cur = get_num_edges2existing_nodes_advance(ug, rg, sources, coverage_cut, ruIndex, max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, ignore_trio_flag); - //means find an aim - if(ava_cur > 0) { - (*return_ava_cur) = ava_cur; - (*return_ava_ol) = test_oLen; - (*return_chainLen) = chainLen; - h = NULL; - return 1; - } - - if(chainLen >= thresLen) break; - - ///endRid is (t.ul>>32), and t.v is a contained read - ///haven't found a existing unitig from t.v - ///check if t.v can link to a new contained read - endRid = t.v; - h = get_best_cmk_read(ug, rg, sources, coverage_cut, ruIndex, max_hang, min_ovlp, endRid, ignore_trio_flag, cmk); - } - - return 0; -} - - -int get_contained_reads_chain_by_broken_bub(ma_hit_t *h, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, ma_ug_t *ug, asg_t *r_g, int max_hang, int min_ovlp, uint32_t endRid, uint32_t uId, -kvec_asg_arc_t_warp* chain_edges, uint32_t* return_ava_cur, uint32_t* return_ava_ol, uint32_t* return_chainLen, -uint8_t* expect_vis, uint8_t* circle_vis, uint8_t* utg_vis, uint32_t thresLen, uint32_t ignore_trio_flag) -{ - (*return_chainLen) = (*return_ava_cur) = (*return_ava_ol) = (uint32_t)-1; - uint32_t trio_flag, non_trio_flag = (uint32_t)-1, contain_rId, contain_uId, is_Unitig, i; - uint32_t chainLen = 0, ava_cur, test_oLen; - int ql, tl; - int32_t r; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - asg_arc_t t; - asg_t* nsg = ug->g; - chain_edges->a.n = 0; - - - ///continue - ///need to update h, endRid, chainLen, chain_buffer and chain_edges - while (h) - { - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - trio_flag = R_INF.trio_flag[Get_qn(*h)]; - - ///don't want to edges between different haps - non_trio_flag = (uint32_t)-1; - if(ignore_trio_flag == 0) - { - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) break; - } - - ///just need deleted edges - ///sq might be deleted or not - if(!st->del) break; - if(!h->del) break; - - ///tn must be contained in another existing read - get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); - if(contain_rId == (uint32_t)-1 || is_Unitig == 1) break; - if(r_g->seq[contain_rId].del) break; - - get_R_to_U(ruIndex, contain_rId, &contain_uId, &is_Unitig); - if(contain_uId == (uint32_t)-1 || is_Unitig != 1) break; - if(nsg->seq[contain_uId].del) break; - ///contain_uId must be a unitig - - ql = sq->e - sq->s; tl = st->e - st->s; - r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - - ///if st is contained in sq, or vice verse, skip - if(r < 0) break; - - ///if sq and v are not in the same direction, skip - ///endRid is (t.ul>>32), and t.v is a contained read - if((t.ul>>32) != endRid) break; - - kv_push(asg_arc_t, chain_edges->a, t); - chainLen++; - - if(circle_vis[t.ul>>33] || circle_vis[t.v>>1]) break; - - circle_vis[t.ul>>33] = circle_vis[t.v>>1] = 1; - ///endRid is (t.ul>>32), and t.v is a contained read - ///find edges from t.v to existing unitigs - ava_cur = get_num_edges2existing_nodes_advance_by_broken_bub(ug, r_g, sources, - coverage_cut, ruIndex, expect_vis, max_hang, min_ovlp, t.v, &test_oLen, utg_vis, ignore_trio_flag); - //means find an aim - if(ava_cur > 0) - { - (*return_ava_cur) = ava_cur; - (*return_ava_ol) = test_oLen; - (*return_chainLen) = chainLen; - h = NULL; - for (i = 0; i < chain_edges->a.n; i++) - { - circle_vis[chain_edges->a.a[i].ul>>33] = 0; - circle_vis[chain_edges->a.a[i].v>>1] = 0; - } - return 1; - } - - ///if(chainLen >= thresLen) break; - - ///endRid is (t.ul>>32), and t.v is a contained read - ///haven't found a existing unitig from t.v - ///check if t.v can link to a new contained read - endRid = t.v; - h = get_best_contained_read(ug, r_g, sources, coverage_cut, ruIndex, - max_hang, min_ovlp, endRid, ignore_trio_flag); - } - - for (i = 0; i < chain_edges->a.n; i++) - { - circle_vis[chain_edges->a.a[i].ul>>33] = 0; - circle_vis[chain_edges->a.a[i].v>>1] = 0; - } - return 0; -} - -int get_chimeric_reads_chain_by_broken_bub(ma_hit_t *h, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, ma_ug_t *ug, asg_t *rg, int max_hang, int min_ovlp, uint32_t endRid, uint32_t uId, -kvec_asg_arc_t_warp* chain_edges, uint32_t* return_ava_cur, uint32_t* return_ava_ol, uint32_t* return_chainLen, -uint8_t* expect_vis, uint8_t* circle_vis, uint8_t* utg_vis, uint32_t thresLen, uint32_t ignore_trio_flag, uint8_t *cmk) -{ - (*return_chainLen) = (*return_ava_cur) = (*return_ava_ol) = (uint32_t)-1; - uint32_t trio_flag, non_trio_flag = (uint32_t)-1, contain_rId, is_Unitig, i; - uint32_t chainLen = 0, ava_cur, test_oLen; int ql, tl; int32_t r; ma_sub_t *sq = NULL; ma_sub_t *st = NULL; - asg_arc_t t; chain_edges->a.n = 0; - - ///need to update h, endRid, chainLen, chain_buffer and chain_edges - while (h) { - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - trio_flag = R_INF.trio_flag[Get_qn(*h)]; - - ///don't want to edges between different haps - non_trio_flag = (uint32_t)-1; - if(ignore_trio_flag == 0) { - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) break; - } - - ///just need deleted edges - ///sq might be deleted or not - if((!st->del) || (!h->del) || (!rg->seq[Get_tn(*h)].del)) break; - // if(cmk[Get_tn(*h)] != ((uint8_t)-1)) break; - // if(cmk[Get_tn(*h)] == ((uint8_t)-1)) break; - - ///tn must be contained in another existing read - get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); - if(is_Unitig == 1) break; - - ql = sq->e - sq->s; tl = st->e - st->s; - r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - - ///if st is contained in sq, or vice verse, skip - if(r < 0) break; - - ///if sq and v are not in the same direction, skip - ///endRid is (t.ul>>32), and t.v is a contained read - if((t.ul>>32) != endRid) break; - - kv_push(asg_arc_t, chain_edges->a, t); chainLen++; - - if(circle_vis[t.ul>>33] || circle_vis[t.v>>1]) break; - - circle_vis[t.ul>>33] = circle_vis[t.v>>1] = 1; - ///endRid is (t.ul>>32), and t.v is a contained read - ///find edges from t.v to existing unitigs - ava_cur = get_num_edges2existing_nodes_advance_by_broken_bub(ug, rg, sources, coverage_cut, ruIndex, expect_vis, max_hang, min_ovlp, t.v, &test_oLen, utg_vis, ignore_trio_flag); - //means find an aim - if(ava_cur > 0) { - (*return_ava_cur) = ava_cur; - (*return_ava_ol) = test_oLen; - (*return_chainLen) = chainLen; - h = NULL; - for (i = 0; i < chain_edges->a.n; i++) { - circle_vis[chain_edges->a.a[i].ul>>33] = 0; - circle_vis[chain_edges->a.a[i].v>>1] = 0; - } - return 1; - } - - ///if(chainLen >= thresLen) break; - - ///endRid is (t.ul>>32), and t.v is a contained read - ///haven't found a existing unitig from t.v - ///check if t.v can link to a new contained read - endRid = t.v; - h = get_best_cmk_read(ug, rg, sources, coverage_cut, ruIndex, max_hang, min_ovlp, endRid, ignore_trio_flag, cmk); - } - - for (i = 0; i < chain_edges->a.n; i++) { - circle_vis[chain_edges->a.a[i].ul>>33] = 0; - circle_vis[chain_edges->a.a[i].v>>1] = 0; - } - return 0; -} - - -///chainLenThres is used to avoid circle -void rescue_chimeric_reads_aggressive(ma_ug_t *i_ug, asg_t *rg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t chainLenThres, uint32_t is_bubble_check, uint32_t is_primary_check, kvec_asg_arc_t_warp* new_rtg_edges, -kvec_t_u32_warp* new_rtg_nodes, bub_label_t* b_mask_t, uint8_t *cmk) -{ - uint32_t n_vtx, v, k, contain_rId, is_Unitig, uId, rId, endRid, oLen, w, max_oLen, max_oLen_i = (uint32_t)-1; - uint32_t ava_max, ava_ol_max, ava_min_chain, ava_cur, ava_chainLen, test_oLen, is_update; - asg_t* nsg = NULL; ma_utg_t* nsu = NULL; asg_arc_t t, t_max, r_edge; t_max.v = t_max.ul = t.v = t.ul = (uint32_t)-1; - ma_hit_t *h = NULL, *h_max = NULL; ma_hit_t_alloc* x = NULL; ma_ug_t* ug = NULL; uint64_t a_nodes; - - kvec_t(asg_arc_t) new_edges; kv_init(new_edges); - kvec_t(asg_arc_t) rbub_edges; kv_init(rbub_edges); - kvec_t_u64_warp u_vecs; kv_init(u_vecs.a); - kvec_t_u32_warp chain_buffer; kv_init(chain_buffer.a); - kvec_asg_arc_t_warp chain_edges; kv_init(chain_edges.a); - - if(i_ug != NULL) { - ug = i_ug; - } else { - ug = ma_ug_gen(rg); - for (v = 0; v < ug->g->n_seq; v++) ug->g->seq[v].c = PRIMARY_LABLE; - } - nsg = ug->g; - - for (v = 0; v < nsg->n_seq; v++) { - uId = v; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsg->seq[v].del) continue; - if(is_primary_check && nsg->seq[v].c==ALTER_LABLE) continue; - for (k = 0; k < nsu->n; k++) { - rId = nsu->a[k]>>33; - set_R_to_U(ruIndex, rId, uId, 1, &(rg->seq[rId].c)); - } - } - - // fprintf(stderr, "-0-[M::%s]\tx->index[2300071]::%u\n", __func__, ruIndex->index[2300071]); - n_vtx = nsg->n_seq * 2; - for (v = 0; v < n_vtx; v++) { - uId = v>>1; - if(nsg->seq[uId].del) continue; - if(is_primary_check && nsg->seq[uId].c==ALTER_LABLE) continue; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsu->circ || nsu->start == UINT32_MAX || nsu->end == UINT32_MAX) continue; - if(get_real_length(nsg, v, NULL) != 0) continue; - - if(v&1) { - endRid = nsu->start^1; - } else { - endRid = nsu->end^1; - } - - ///x is the end read of a tip - ///find all overlap of x - x = &(sources[(endRid>>1)]); - ava_ol_max = ava_max = 0; ava_min_chain = (uint32_t)-1; - h_max = NULL; - for (k = 0; k < x->length; k++) { - ///h is the edge of endRid - h = &(x->buffer[k]); - ///means we found a contained read - if(get_chimeric_reads_chain(h, sources, coverage_cut, ruIndex, ug, rg, max_hang, min_ovlp, endRid, uId, &chain_buffer, NULL, &ava_cur, &test_oLen, &ava_chainLen, chainLenThres, 1, cmk)) { - is_update = 0; - if(ava_chainLen < ava_min_chain) { - is_update = 1; - } else if(ava_chainLen == ava_min_chain) { - if(ava_cur > ava_max) { - is_update = 1; - } else if(ava_cur == ava_max && test_oLen > ava_ol_max) { - is_update = 1; - } - } - - if(is_update) { - ava_min_chain = ava_chainLen; - ava_max = ava_cur; - ava_ol_max = test_oLen; - h_max = h; - } - } - } - - - - - - if(ava_max > 0) { - //get all edges between contained reads - get_chimeric_reads_chain(h_max, sources, coverage_cut, ruIndex, ug, rg, max_hang, min_ovlp, endRid, uId, &chain_buffer, &chain_edges, &ava_cur, &test_oLen, &ava_chainLen, chainLenThres, 1, cmk); - if(chain_edges.a.n < 1) continue; - ///the last read - t_max = chain_edges.a.a[chain_edges.a.n-1]; - - k = 0; rbub_edges.n = 0; - ///edges from the last contained read to other unitigs - while(get_edge2existing_node_advance(ug, rg, sources, coverage_cut, ruIndex, - max_hang, min_ovlp, t_max.v, chain_buffer.a.a, chain_buffer.a.n, &k, &r_edge, 1)) { - kv_push(asg_arc_t, rbub_edges, r_edge); - } - - ///need to do transitive reduction - ///note here is different to standard transitive reduction - minor_transitive_reduction(ug, ruIndex, rbub_edges.a, rbub_edges.n); - if(is_primary_check) { - max_oLen = 0; max_oLen_i = (uint32_t)-1; - for (k = 0; k < rbub_edges.n; k++) { - t = rbub_edges.a[k]; - if(t.del) continue; - if(t.ol > max_oLen) { - max_oLen = t.ol; - max_oLen_i = k; - } - } - - if(max_oLen_i == (uint32_t)-1) continue; - t = rbub_edges.a[max_oLen_i]; - w = get_corresponding_uId(ug, ruIndex, t.v); - if(w == ((uint32_t)(-1))) continue; - if(get_real_length(nsg, w^1, NULL)!=0) continue; - } - - //recover all contained reads - for (k = 0; k < chain_edges.a.n; k++) { - t_max = chain_edges.a.a[k]; - ///save all infor for reverting - get_R_to_U(ruIndex, t_max.v>>1, &contain_rId, &is_Unitig); - if((is_Unitig == 1) || (is_Unitig == ((uint32_t)-1))) contain_rId = ((uint32_t)-1);///shouldn't be possible - a_nodes=contain_rId; - a_nodes=a_nodes<<32; - a_nodes=a_nodes|((uint64_t)(t_max.v>>1)); - kv_push(uint64_t, u_vecs.a, a_nodes); - - - //(t_max.ul>>32)----->(t_max.v/r_edge.ul>>32)----->r_edge.v - //need to recover (t_max.v/r_edge.ul>>32), 1. set .del = 0 2. set ruIndex - rg->seq[t_max.v>>1].del = 0; - coverage_cut[t_max.v>>1].del = 0; - coverage_cut[t_max.v>>1].c = PRIMARY_LABLE; - //add recover to the end of the unitig - append_rId_to_Unitig(rg, ug, v, t_max.v, sources, coverage_cut, ruIndex, max_hang, min_ovlp); - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, (t_max.ul>>32), t_max.v, &t); - kv_push(asg_arc_t, new_edges, t); - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, (t_max.v^1), ((t_max.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); - } - - if(is_primary_check) { - t = rbub_edges.a[max_oLen_i]; - w = get_corresponding_uId(ug, ruIndex, t.v); - if(w == ((uint32_t)(-1))) continue; - kv_push(asg_arc_t, new_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); oLen = t.ol; - asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); - } else { - for (k = 0; k < rbub_edges.n; k++) { - t = rbub_edges.a[k]; - if(t.del) continue; - w = get_corresponding_uId(ug, ruIndex, t.v); - if(w == ((uint32_t)(-1))) continue; - - kv_push(asg_arc_t, new_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); - - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); - } - } - - } - } - - // fprintf(stderr, "-1-[M::%s]\tx->index[2300071]::%u\n", __func__, ruIndex->index[2300071]); - - asg_arc_t* p = NULL; - if(is_bubble_check) { - for (k = 0; k < new_edges.n; k++) { - p = asg_arc_pushp(rg); - *p = new_edges.a[k]; - } - - if(new_edges.n != 0) { - free(rg->idx); - rg->idx = 0; - rg->is_srt = 0; - asg_cleanup(rg); - } - - pre_clean(sources, coverage_cut, rg, 0); - - lable_all_bubbles(rg, b_mask_t); - - for (k = 0; k < new_edges.n; k++) { - v = new_edges.a[k].ul>>32; - w = new_edges.a[k].v; - - if(rg->seq[v>>1].del) continue; - if(rg->seq[w>>1].del) continue; - ///if this edge is at a bubble - if(rg->seq_vis[v]!=0 && rg->seq_vis[w^1]!=0) continue; - - asg_arc_del(rg, v, w, 1); - asg_arc_del(rg, w^1, v^1, 1); - } - asg_cleanup(rg); - // fprintf(stderr, "-2-[M::%s]\tx->index[2300071]::%u\n", __func__, ruIndex->index[2300071]); - - // w=max_contain_rId; w=w<<32; w=w|(t_max.v>>1); - // kv_push(uint64_t, u_vecs.a, w); - for (k = 0; k < u_vecs.a.n; k++) { - w = (uint32_t)u_vecs.a.a[k]; - w = w<<1; - if(!rg->seq[w>>1].del && get_real_length(rg, w, NULL)!=0) continue; - if(!rg->seq[w>>1].del && get_real_length(rg, (w^1), NULL)!=0) continue; - w=w>>1; - rg->seq[w].del = 1; - coverage_cut[w].del = 1; - if((u_vecs.a.a[k]>>32) == ((uint32_t)-1)) { - ruIndex->index[((uint32_t)(u_vecs.a.a[k]))] = (uint32_t)-1; - } else { - set_R_to_U(ruIndex, ((uint32_t)(u_vecs.a.a[k])), (u_vecs.a.a[k]>>32), 0, NULL); - } - } - - // fprintf(stderr, "-3-[M::%s]\tx->index[2300071]::%u\n", __func__, ruIndex->index[2300071]); - } - - ///actually we don't update sources - ///during the the primary_check, we need to recover everything for r_g, coverage_cut and ruIndex - if(is_primary_check) - { - ///don't remove nodes and edges - /** - for (k = 0; k < u_vecs.a.n; k++) - { - w = (uint32_t)u_vecs.a.a[k]; - r_g->seq[w].del = 1; - coverage_cut[w].del = 1; - set_R_to_U(ruIndex, ((uint32_t)(u_vecs.a.a[k])), (u_vecs.a.a[k]>>32), 0); - } - **/ - if(new_rtg_nodes) - { - for(k = 0; k < u_vecs.a.n; k++) - { - w = (uint32_t)u_vecs.a.a[k]; - kv_push(uint32_t, new_rtg_nodes->a, w); - } - } - - - for (k = 0; k < new_edges.n; k++) - { - p = asg_arc_pushp(rg); - *p = new_edges.a[k]; - if(new_rtg_edges) kv_push(asg_arc_t, new_rtg_edges->a, new_edges.a[k]); - } - - if(new_edges.n != 0) - { - free(rg->idx); - rg->idx = 0; - rg->is_srt = 0; - asg_cleanup(rg); - } - } - // fprintf(stderr, "-4-[M::%s]\tx->index[2300071]::%u\n", __func__, ruIndex->index[2300071]); - - for (v = 0; v < ruIndex->len; v++) - { - get_R_to_U(ruIndex, v, &uId, &is_Unitig); - if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; - } - // fprintf(stderr, "-5-[M::%s]\tx->index[2300071]::%u\n", __func__, ruIndex->index[2300071]); - - if(i_ug == NULL) ma_ug_destroy(ug); - kv_destroy(new_edges); - kv_destroy(rbub_edges); - kv_destroy(u_vecs.a); - kv_destroy(chain_buffer.a); - kv_destroy(chain_edges.a); - -} - - -///chainLenThres is used to avoid circle -void rescue_contained_reads_aggressive(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t chainLenThres, uint32_t is_bubble_check, uint32_t is_primary_check, kvec_asg_arc_t_warp* new_rtg_edges, -kvec_t_u32_warp* new_rtg_nodes, bub_label_t* b_mask_t) -{ - uint32_t n_vtx, v, k, contain_rId, is_Unitig, uId, rId, endRid, oLen, w, max_oLen, max_oLen_i = (uint32_t)-1; - uint32_t ava_max, ava_ol_max, ava_min_chain, ava_cur, ava_chainLen, test_oLen, is_update; - asg_t* nsg = NULL; - ma_utg_t* nsu = NULL; - asg_arc_t t, t_max, r_edge; - t_max.v = t_max.ul = t.v = t.ul = (uint32_t)-1; - ma_hit_t *h = NULL, *h_max = NULL; - ma_hit_t_alloc* x = NULL; - ma_ug_t* ug = NULL; - uint64_t a_nodes; - - kvec_t(asg_arc_t) new_edges; - kv_init(new_edges); - - kvec_t(asg_arc_t) rbub_edges; - kv_init(rbub_edges); - - kvec_t_u64_warp u_vecs; - kv_init(u_vecs.a); - - kvec_t_u32_warp chain_buffer; - kv_init(chain_buffer.a); - - kvec_asg_arc_t_warp chain_edges; - kv_init(chain_edges.a); - - if(i_ug != NULL) - { - ug = i_ug; - } - else - { - ug = ma_ug_gen(r_g); - for (v = 0; v < ug->g->n_seq; v++) - { - ug->g->seq[v].c = PRIMARY_LABLE; - } - } - nsg = ug->g; - - for (v = 0; v < nsg->n_seq; v++) - { - uId = v; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsg->seq[v].del) continue; - if(is_primary_check && nsg->seq[v].c==ALTER_LABLE) continue; - for (k = 0; k < nsu->n; k++) - { - rId = nsu->a[k]>>33; - set_R_to_U(ruIndex, rId, uId, 1, &(r_g->seq[rId].c)); - } - } - - - - - n_vtx = nsg->n_seq * 2; - for (v = 0; v < n_vtx; v++) - { - uId = v>>1; - if(nsg->seq[uId].del) continue; - if(is_primary_check && nsg->seq[uId].c==ALTER_LABLE) continue; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsu->circ || nsu->start == UINT32_MAX || nsu->end == UINT32_MAX) continue; - if(get_real_length(nsg, v, NULL) != 0) continue; - ///we probably don't need this line - ///if(get_real_length(nsg, v^1, NULL) == 0) continue; - if(v&1) - { - endRid = nsu->start^1; - } - else - { - endRid = nsu->end^1; - } - - ///x is the end read of a tip - ///find all overlap of x - x = &(sources[(endRid>>1)]); - ava_ol_max = ava_max = 0; ava_min_chain = (uint32_t)-1; - h_max = NULL; - for (k = 0; k < x->length; k++) - { - ///h is the edge of endRid - h = &(x->buffer[k]); - ///means we found a contained read - if(get_contained_reads_chain(h, sources, coverage_cut, ruIndex, ug, r_g, - max_hang, min_ovlp, endRid, uId, &chain_buffer, NULL, &ava_cur, &test_oLen, - &ava_chainLen, chainLenThres, 1)) - { - is_update = 0; - if(ava_chainLen < ava_min_chain) - { - is_update = 1; - } - else if(ava_chainLen == ava_min_chain) - { - if(ava_cur > ava_max) - { - is_update = 1; - } - else if(ava_cur == ava_max && test_oLen > ava_ol_max) - { - is_update = 1; - } - } - if(is_update) - { - ava_min_chain = ava_chainLen; - ava_max = ava_cur; - ava_ol_max = test_oLen; - h_max = h; - } - } - } - - - - - - if(ava_max > 0) - { - //get all edges between contained reads - get_contained_reads_chain(h_max, sources, coverage_cut, ruIndex, ug, r_g, - max_hang, min_ovlp, endRid, uId, &chain_buffer, &chain_edges, &ava_cur, &test_oLen, - &ava_chainLen, chainLenThres, 1); - if(chain_edges.a.n < 1) continue; - ///the last cantained read - t_max = chain_edges.a.a[chain_edges.a.n-1]; - - k = 0; rbub_edges.n = 0; - ///edges from the last contained read to other unitigs - while(get_edge2existing_node_advance(ug, r_g, sources, coverage_cut, ruIndex, - max_hang, min_ovlp, t_max.v, chain_buffer.a.a, chain_buffer.a.n, &k, &r_edge, 1)) - { - kv_push(asg_arc_t, rbub_edges, r_edge); - } - - ///need to do transitive reduction - ///note here is different to standard transitive reduction - minor_transitive_reduction(ug, ruIndex, rbub_edges.a, rbub_edges.n); - if(is_primary_check) - { - max_oLen = 0; max_oLen_i = (uint32_t)-1; - for (k = 0; k < rbub_edges.n; k++) - { - t = rbub_edges.a[k]; - if(t.del) continue; - if(t.ol > max_oLen) - { - max_oLen = t.ol; - max_oLen_i = k; - } - } - - if(max_oLen_i == (uint32_t)-1) continue; - t = rbub_edges.a[max_oLen_i]; - w = get_corresponding_uId(ug, ruIndex, t.v); - if(w == ((uint32_t)(-1))) continue; - if(get_real_length(nsg, w^1, NULL)!=0) continue; - } - - //recover all contained reads - for (k = 0; k < chain_edges.a.n; k++) - { - t_max = chain_edges.a.a[k]; - ///save all infor for reverting - get_R_to_U(ruIndex, t_max.v>>1, &contain_rId, &is_Unitig); - a_nodes=contain_rId; - a_nodes=a_nodes<<32; - a_nodes=a_nodes|((uint64_t)(t_max.v>>1)); - kv_push(uint64_t, u_vecs.a, a_nodes); - - - //(t_max.ul>>32)----->(t_max.v/r_edge.ul>>32)----->r_edge.v - //need to recover (t_max.v/r_edge.ul>>32), 1. set .del = 0 2. set ruIndex - r_g->seq[t_max.v>>1].del = 0; - coverage_cut[t_max.v>>1].del = 0; - coverage_cut[t_max.v>>1].c = PRIMARY_LABLE; - //add recover to the end of the unitig - append_rId_to_Unitig(r_g, ug, v, t_max.v, sources, coverage_cut, ruIndex, max_hang, - min_ovlp); - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, - (t_max.ul>>32), t_max.v, &t); - kv_push(asg_arc_t, new_edges, t); - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, - (t_max.v^1), ((t_max.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); - } - - if(is_primary_check) - { - t = rbub_edges.a[max_oLen_i]; - w = get_corresponding_uId(ug, ruIndex, t.v); - if(w == ((uint32_t)(-1))) continue; - kv_push(asg_arc_t, new_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, - (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); - } - else - { - for (k = 0; k < rbub_edges.n; k++) - { - t = rbub_edges.a[k]; - if(t.del) continue; - w = get_corresponding_uId(ug, ruIndex, t.v); - if(w == ((uint32_t)(-1))) continue; - - kv_push(asg_arc_t, new_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); - - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, - (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); - } - } - - } - } - - asg_arc_t* p = NULL; - if(is_bubble_check) - { - - for (k = 0; k < new_edges.n; k++) - { - p = asg_arc_pushp(r_g); - *p = new_edges.a[k]; - } - - if(new_edges.n != 0) - { - free(r_g->idx); - r_g->idx = 0; - r_g->is_srt = 0; - asg_cleanup(r_g); - } - - pre_clean(sources, coverage_cut, r_g, 0); - - lable_all_bubbles(r_g, b_mask_t); - - for (k = 0; k < new_edges.n; k++) - { - v = new_edges.a[k].ul>>32; - w = new_edges.a[k].v; - - if(r_g->seq[v>>1].del) continue; - if(r_g->seq[w>>1].del) continue; - ///if this edge is at a bubble - if(r_g->seq_vis[v]!=0 && r_g->seq_vis[w^1]!=0) continue; - - asg_arc_del(r_g, v, w, 1); - asg_arc_del(r_g, w^1, v^1, 1); - } - asg_cleanup(r_g); - - - // w=max_contain_rId; w=w<<32; w=w|(t_max.v>>1); - // kv_push(uint64_t, u_vecs.a, w); - for (k = 0; k < u_vecs.a.n; k++) - { - w = (uint32_t)u_vecs.a.a[k]; - w = w<<1; - if(!r_g->seq[w>>1].del && get_real_length(r_g, w, NULL)!=0) continue; - if(!r_g->seq[w>>1].del && get_real_length(r_g, (w^1), NULL)!=0) continue; - w=w>>1; - r_g->seq[w].del = 1; - coverage_cut[w].del = 1; - set_R_to_U(ruIndex, ((uint32_t)(u_vecs.a.a[k])), (u_vecs.a.a[k]>>32), 0, NULL); - } - } - - ///actually we don't update sources - ///during the the primary_check, we need to recover everything for r_g, coverage_cut and ruIndex - if(is_primary_check) - { - ///don't remove nodes and edges - /** - for (k = 0; k < u_vecs.a.n; k++) - { - w = (uint32_t)u_vecs.a.a[k]; - r_g->seq[w].del = 1; - coverage_cut[w].del = 1; - set_R_to_U(ruIndex, ((uint32_t)(u_vecs.a.a[k])), (u_vecs.a.a[k]>>32), 0); - } - **/ - if(new_rtg_nodes) - { - for(k = 0; k < u_vecs.a.n; k++) - { - w = (uint32_t)u_vecs.a.a[k]; - kv_push(uint32_t, new_rtg_nodes->a, w); - } - } - - - for (k = 0; k < new_edges.n; k++) - { - p = asg_arc_pushp(r_g); - *p = new_edges.a[k]; - if(new_rtg_edges) kv_push(asg_arc_t, new_rtg_edges->a, new_edges.a[k]); - } - - if(new_edges.n != 0) - { - free(r_g->idx); - r_g->idx = 0; - r_g->is_srt = 0; - asg_cleanup(r_g); - } - } - - - for (v = 0; v < ruIndex->len; v++) - { - get_R_to_U(ruIndex, v, &uId, &is_Unitig); - if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; - } - - - if(i_ug == NULL) ma_ug_destroy(ug); - kv_destroy(new_edges); - kv_destroy(rbub_edges); - kv_destroy(u_vecs.a); - kv_destroy(chain_buffer.a); - kv_destroy(chain_edges.a); - -} - - - -void rescue_missing_overlaps_aggressive(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t is_bubble_check, uint32_t is_primary_check, -kvec_asg_arc_t_warp* new_rtg_edges, bub_label_t* b_mask_t) -{ - uint32_t n_vtx, v, k, is_Unitig, uId, rId, endRid, oLen, w, max_oLen, max_oLen_i; - asg_t* nsg = NULL; - ma_utg_t* nsu = NULL; - ma_ug_t *ug = NULL; - asg_arc_t t, r_edge; - kvec_t(asg_arc_t) new_edges; - kv_init(new_edges); - - kvec_t(asg_arc_t) rbub_edges; - kv_init(rbub_edges); - - if(i_ug != NULL) - { - ug = i_ug; - } - else - { - ug = ma_ug_gen(r_g); - for (v = 0; v < ug->g->n_seq; v++) - { - ug->g->seq[v].c = PRIMARY_LABLE; - } - } - nsg = ug->g; - - for (v = 0; v < nsg->n_seq; v++) - { - uId = v; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsg->seq[v].del) continue; - if(is_primary_check && nsg->seq[v].c==ALTER_LABLE) continue; - - for (k = 0; k < nsu->n; k++) - { - rId = nsu->a[k]>>33; - set_R_to_U(ruIndex, rId, uId, 1, &(r_g->seq[rId].c)); - } - } - - - n_vtx = nsg->n_seq * 2; - for (v = 0; v < n_vtx; v++) - { - uId = v>>1; - if(nsg->seq[uId].del) continue; - if(is_primary_check && nsg->seq[uId].c == ALTER_LABLE) continue; - - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsu->circ || nsu->start == UINT32_MAX || nsu->end == UINT32_MAX) continue; - if(get_real_length(nsg, v, NULL) != 0) continue; - - if(v&1) - { - endRid = nsu->start^1; - } - else - { - endRid = nsu->end^1; - } - - - k = 0; - rbub_edges.n = 0; - while(get_edge2existing_node_advance(ug, r_g, sources, coverage_cut, ruIndex, - max_hang, min_ovlp, endRid, &uId, 1, &k, &r_edge, 1)) - { - kv_push(asg_arc_t, rbub_edges, r_edge); - } - - - - if(rbub_edges.n > 0) - { - ///need to do transitive reduction - ///note here is different to standard transitive reduction - minor_transitive_reduction(ug, ruIndex, rbub_edges.a, rbub_edges.n); - if(is_primary_check) - { - max_oLen = 0; max_oLen_i = (uint32_t)-1; - for (k = 0; k < rbub_edges.n; k++) - { - t = rbub_edges.a[k]; - if(t.del) continue; - if(t.ol > max_oLen) - { - max_oLen = t.ol; - max_oLen_i = k; - } - } - - if(max_oLen_i == (uint32_t)-1) continue; - t = rbub_edges.a[max_oLen_i]; - w = get_corresponding_uId(ug, ruIndex, t.v); - if(w == ((uint32_t)(-1))) continue; - if(get_real_length(nsg, w^1, NULL)!=0) continue; - - kv_push(asg_arc_t, new_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); - - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, - (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); - } - else - { - for (k = 0; k < rbub_edges.n; k++) - { - t = rbub_edges.a[k]; - if(t.del) continue; - w = get_corresponding_uId(ug, ruIndex, t.v); - if(w == ((uint32_t)(-1))) continue; - // get_R_to_U(ruIndex, t.v>>1, &uId, &is_Unitig); - // w = (uint32_t)-1; - // if(t.v == ug->u.a[uId].start) w = uId<<1; - // if(t.v == ug->u.a[uId].end) w = (uId<<1)^1; - kv_push(asg_arc_t, new_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); - - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, - (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); - } - } - - } - } - - asg_arc_t* p = NULL; - if(is_bubble_check) - { - - for (k = 0; k < new_edges.n; k++) - { - p = asg_arc_pushp(r_g); - *p = new_edges.a[k]; - } - - if(new_edges.n != 0) - { - free(r_g->idx); - r_g->idx = 0; - r_g->is_srt = 0; - asg_cleanup(r_g); - } - - - pre_clean(sources, coverage_cut, r_g, 0); - - lable_all_bubbles(r_g, b_mask_t); - - - for (k = 0; k < new_edges.n; k++) - { - v = new_edges.a[k].ul>>32; - w = new_edges.a[k].v; - - if(r_g->seq[v>>1].del) continue; - if(r_g->seq[w>>1].del) continue; - ///if this edge is at a bubble - if(r_g->seq_vis[v]!=0 && r_g->seq_vis[w^1]!=0) continue; - - asg_arc_del(r_g, v, w, 1); - asg_arc_del(r_g, w^1, v^1, 1); - } - asg_cleanup(r_g); - } - - if(is_primary_check) - { - for (k = 0; k < new_edges.n; k++) - { - p = asg_arc_pushp(r_g); - *p = new_edges.a[k]; - if(new_rtg_edges) kv_push(asg_arc_t, new_rtg_edges->a, new_edges.a[k]); - } - - if(new_edges.n != 0) - { - free(r_g->idx); - r_g->idx = 0; - r_g->is_srt = 0; - asg_cleanup(r_g); - } - } - - - for (v = 0; v < ruIndex->len; v++) - { - get_R_to_U(ruIndex, v, &uId, &is_Unitig); - if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; - } - - if(i_ug == NULL) ma_ug_destroy(ug); - - kv_destroy(new_edges); - kv_destroy(rbub_edges); - /*************************just for debug**************************/ - // debug_utg_graph(ug, r_g, 0, 0); - /*************************just for debug**************************/ -} - -void set_rtg_flag_by_bubble(bubble_type* bub, ma_ug_t* ug, asg_t *r_g, uint32_t v, uint8_t* vis_flag, -uint32_t flag) -{ - uint32_t beg, sink, *a = NULL, n, i, k, uId, rId; - ma_utg_t* nsu = NULL; - get_bubbles(bub, v, &beg, &sink, &a, &n, NULL); - for (i = 0; i < n; i++) - { - uId = a[i]>>1; - - nsu = &(ug->u.a[uId]); - if(nsu->m > 0) - { - for (k = 0; k < nsu->n; k++) - { - rId = nsu->a[k]>>33; - if(r_g->seq[rId].del) continue; - vis_flag[rId] = flag; - } - } - } - - if(beg != (uint32_t)-1) - { - uId = beg>>1; - - nsu = &(ug->u.a[uId]); - if(nsu->m > 0) - { - for (k = 0; k < nsu->n; k++) - { - rId = nsu->a[k]>>33; - if(r_g->seq[rId].del) continue; - vis_flag[rId] = flag; - } - } - } - - if(sink != (uint32_t)-1) - { - uId = sink>>1; - - nsu = &(ug->u.a[uId]); - if(nsu->m > 0) - { - for (k = 0; k < nsu->n; k++) - { - rId = nsu->a[k]>>33; - if(r_g->seq[rId].del) continue; - vis_flag[rId] = flag; - } - } - } -} - -void print_bubble_filling_status(ma_ug_t *copy_ug, asg_t *r_g, R_to_U* ruIndex, bubble_type* bub, -uint32_t beg_idx, uint32_t occ, asg_arc_t* new_edges, uint32_t new_edges_len) -{ - ma_utg_t* nsu = NULL; - ma_ug_t* ug = copy_ug; - uint32_t i, k_i, k_v, v, k, beg_utg, sink_utg, *a = NULL, n, uId, endRid, is_broken, is_tangle; - uint32_t tangle_occ = 0, broken_occ = 0, recover_occ = 0, is_Unitig, contain_uId; - asg_t* nsg = ug->g; - for (i = beg_idx; i < beg_idx + occ; i++) - { - get_bubbles(bub, i, &beg_utg, &sink_utg, &a, &n, NULL); - if(beg_utg == (uint32_t)-1 || sink_utg == (uint32_t)-1) continue; - for (k_i = 0, is_broken = 1, is_tangle = 1; k_i < n; k_i++) - { - uId = a[k_i]>>1; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - for (k_v = 0; k_v < 2; k_v++) - { - v = (uId<<1) + k_v; - if(get_real_length(nsg, v, NULL) != 0) continue; - - ///tig - is_tangle = 0; - if(v&1) - { - endRid = nsu->start^1; - } - else - { - endRid = nsu->end^1; - } - - if(r_g->seq[endRid>>1].del) - { - is_broken = 0; - continue; - } - - if(get_real_length(r_g, endRid, NULL) == 0) - { - is_broken = 1; - goto tig_end; - } - else - { - is_broken = 0; - } - } - } - - tig_end: - if(is_tangle) - { - tangle_occ++; - fprintf(stderr, "tangle: beg-utg%.6ul, end-utg%.6ul\n", (beg_utg>>1)+1, (sink_utg>>1)+1); - } - else if(is_broken) - { - broken_occ++; - fprintf(stderr, "broken: beg-utg%.6ul, end-utg%.6ul\n", (beg_utg>>1)+1, (sink_utg>>1)+1); - } - else - { - recover_occ++; - fprintf(stderr, "recover: beg-utg%.6ul, end-utg%.6ul\n", (beg_utg>>1)+1, (sink_utg>>1)+1); - } - } - - fprintf(stderr, "###########tangle_occ: %u, broken_occ: %u, recover_occ: %u\n", tangle_occ, broken_occ, recover_occ); - nsg = ug->g; - for (v = 0; v < nsg->n_seq; v++) - { - uId = v; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsg->seq[v].del) continue; - for (k = 0; k < nsu->n; k++) - { - set_R_to_U(ruIndex, nsu->a[k]>>33, uId, 1, &(r_g->seq[nsu->a[k]>>33].c)); - } - } - #define check_debug_edge(g, t) (((g).seq[(t).ul>>33].del == 1) && ((g).seq[(t).v>>1].del == 0)) - - - - for (k = 0; k < new_edges_len; k++) - { - v = new_edges[k].ul>>32; - - if(check_debug_edge(*r_g, new_edges[k])) - { - for (i = broken_occ = 0; i < new_edges_len; i++) - { - if((new_edges[i].ul>>32) == v) broken_occ++; - } - - if(broken_occ > 1) - { - fprintf(stderr, "*************tig_to_occ: %u\n", broken_occ); - for (i = 0; i < new_edges_len; i++) - { - if((new_edges[i].ul>>32) == v) - { - get_R_to_U(ruIndex, new_edges[i].v>>1, &contain_uId, &is_Unitig); - if(is_Unitig == 1) - { - nsu = &(ug->u.a[contain_uId]); - for (k_i = 0; k_i < nsu->n; k_i++) - { - if((nsu->a[k_i]>>33) == (new_edges[i].v>>1)) break; - } - - fprintf(stderr, "to-utg%.6ul, idx_of_u: %u, u_n: %u\n", - contain_uId+1, k_i, nsu->n); - } - - } - } - } - } - } - - - - for (v = 0; v < ruIndex->len; v++) - { - get_R_to_U(ruIndex, v, &uId, &is_Unitig); - if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; - } - -} - -void minor_transitive_reduction_r_g(asg_t *r_g, asg_arc_t* rbub_edges, uint32_t num) -{ - uint32_t i, j, k, rId, nv, w; - asg_arc_t* t = NULL; - asg_arc_t* p = NULL; - asg_arc_t *av = NULL; - ///here all edges from v are saved in rbub_edges - ///for edges already in graph, need to check del - ///but for edges in rbub_edges, don't check del - for (i = 0; i < num; i++) - { - t = &rbub_edges[i]; - rId = t->v; - - nv = asg_arc_n(r_g, rId); - av = asg_arc_a(r_g, rId); - for (j = 0; j < nv; j++) - { - if(av[j].del) continue; - w = av[j].v; - for (k = 0; k < num; k++) - { - p = &rbub_edges[k]; - ///this line is not necessary at all - if(k==i) continue; - if(p->v == w) p->del = 1; - } - } - } -} - - -int if_recoverable(asg_t *sg, ma_ug_t *ug, bubble_type* bub, uint32_t bid, kvec_t_u32_warp* stack, uint8_t* vis_flag) -{ - uint32_t beg_utg, sink_utg, *a = NULL, n, begRid, sinkRid, i; - get_bubbles(bub, bid, &beg_utg, &sink_utg, &a, &n, NULL); - if(beg_utg == (uint32_t)-1 || sink_utg == (uint32_t)-1) return 0; - if(beg_utg&1) - { - begRid = ug->u.a[beg_utg>>1].start^1; - } - else - { - begRid = ug->u.a[beg_utg>>1].end^1; - } - - if(sink_utg&1) - { - sinkRid = ug->u.a[sink_utg>>1].start; - } - else - { - sinkRid = ug->u.a[sink_utg>>1].end; - } - - asg_arc_t *acur = NULL; - uint32_t cur, ncur, v, n_vx = sg->n_seq<<1; - stack->a.n = 0; - memset(vis_flag, 0, n_vx); - - kv_push(uint32_t, stack->a, begRid); - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - ncur = asg_arc_n(sg, cur); - acur = asg_arc_a(sg, cur); - vis_flag[cur] |= 1; - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if(vis_flag[acur[i].v]&1) return 0; - if(vis_flag[acur[i].v^1]&1) return 0; - if(acur[i].v == sinkRid) continue; - kv_push(uint32_t, stack->a, acur[i].v); - } - } - vis_flag[sinkRid] |= 1; - - - - begRid ^= 1; sinkRid ^= 1; v = begRid; begRid = sinkRid; sinkRid = v; - - stack->a.n = 0; - kv_push(uint32_t, stack->a, begRid); - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - ncur = asg_arc_n(sg, cur); - acur = asg_arc_a(sg, cur); - vis_flag[cur] |= 2; - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if(vis_flag[acur[i].v]&2) return 0; - if(vis_flag[acur[i].v]&1) return 0; - if(vis_flag[acur[i].v^1]&2) return 0; - if(acur[i].v == sinkRid) continue; - kv_push(uint32_t, stack->a, acur[i].v); - } - } - vis_flag[sinkRid] |= 2; - - - - begRid ^= 1; sinkRid ^= 1; v = begRid; begRid = sinkRid; sinkRid = v; - - return 1; -} - -void rescue_bubbles_by_contained_reads(ma_ug_t *i_u_g, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t chainLenThres, uint32_t beg_idx, uint32_t occ, bubble_type* bub, -bub_label_t* b_mask_t) -{ - asg_t* nsg = NULL; - uint32_t beg_utg, sink_utg, *a = NULL, n, i, bub_i, k_i, k_v, k, uId, endRid, is_Unitig, contain_rId; - uint32_t ava_max, ava_ol_max, ava_min_chain, ava_cur, test_oLen, ava_chainLen, is_update, v, w; - uint64_t l_bub, m_bub, r_bub, /**bub_0, bub_1,**/ a_nodes; - ma_ug_t* ug = i_u_g; - ma_utg_t *nsu = NULL, *u = NULL; - ma_hit_t_alloc* x = NULL; - ma_hit_t *h = NULL, *h_max = NULL; - uint8_t* expect_vis = NULL; CALLOC(expect_vis, r_g->n_seq); - uint8_t* circle_vis = NULL; CALLOC(circle_vis, r_g->n_seq); - uint8_t* utg_vis = NULL; CALLOC(utg_vis, ug->g->n_seq); - asg_arc_t t, t_max, r_edge; - - for (v = 0; v < ug->u.n; v++) ug->g->seq[v].c = PRIMARY_LABLE; - - kvec_t(asg_arc_t) new_edges; - kv_init(new_edges); - - kvec_t(asg_arc_t) rbub_edges; - kv_init(rbub_edges); - - kvec_t_u64_warp u_vecs; - kv_init(u_vecs.a); - - kvec_asg_arc_t_warp chain_edges; - kv_init(chain_edges.a); - - nsg = ug->g; - for (v = 0; v < nsg->n_seq; v++) - { - uId = v; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsg->seq[v].del) continue; - for (k = 0; k < nsu->n; k++) - { - set_R_to_U(ruIndex, nsu->a[k]>>33, uId, 1, &(r_g->seq[nsu->a[k]>>33].c)); - } - } - - - for (i = 0; i < bub->b_ug->u.n; i++) - { - u = &(bub->b_ug->u.a[i]); - if(u->n < 3) continue; ///should be at least 3 - for (bub_i = 1; bub_i+1 < u->n; bub_i++) - { - m_bub = u->a[bub_i]>>33; l_bub = r_bub = (uint64_t)-1; - if(m_bub < beg_idx || m_bub >= beg_idx + occ) continue; - l_bub = u->a[bub_i-1]>>33; - r_bub = u->a[bub_i+1]>>33; - - set_rtg_flag_by_bubble(bub, ug, r_g, l_bub, expect_vis, 1); - set_rtg_flag_by_bubble(bub, ug, r_g, r_bub, expect_vis, 1); - set_rtg_flag_by_bubble(bub, ug, r_g, m_bub, expect_vis, 1); - - get_bubbles(bub, m_bub, &beg_utg, &sink_utg, &a, &n, NULL); - for (k_i = 0; k_i < n; k_i++) - { - uId = a[k_i]>>1; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - for (k_v = 0; k_v < 2; k_v++) - { - v = (uId<<1) + k_v; - if(get_real_length(nsg, v, NULL) != 0) continue; - - if(v&1) - { - endRid = nsu->start^1; - } - else - { - endRid = nsu->end^1; - } - - //x is the end read of a tip - ///find all overlap of x - x = &(sources[(endRid>>1)]); - ava_ol_max = ava_max = 0; ava_min_chain = (uint32_t)-1; - h_max = NULL; - for (k = 0; k < x->length; k++) - { - ///fprintf(stderr, "k: %u\n", k); - ///h is the edge of endRid - h = &(x->buffer[k]); - ///means we found a contained read - if(get_contained_reads_chain_by_broken_bub(h, sources, coverage_cut, ruIndex, ug, r_g, - max_hang, min_ovlp, endRid, uId, &chain_edges, &ava_cur, &test_oLen, &ava_chainLen, - expect_vis, circle_vis, utg_vis, chainLenThres, 1)) - { - is_update = 0; - - if(ava_cur > ava_max) - { - is_update = 1; - } - else if(ava_cur == ava_max) - { - if(ava_chainLen < ava_min_chain) - { - is_update = 1; - } - else if(ava_chainLen == ava_min_chain && test_oLen > ava_ol_max) - { - is_update = 1; - } - } - - if(is_update) - { - ava_min_chain = ava_chainLen; - ava_max = ava_cur; - ava_ol_max = test_oLen; - h_max = h; - } - } - } - - if(ava_max > 0) - { - ///fprintf(stderr, "ava_max: %u\n", ava_max); - get_contained_reads_chain_by_broken_bub(h_max, sources, coverage_cut, ruIndex, ug, r_g, - max_hang, min_ovlp, endRid, uId, &chain_edges, &ava_cur, &test_oLen, &ava_chainLen, - expect_vis, circle_vis, NULL, chainLenThres, 1); - if(chain_edges.a.n < 1) continue; - ///the last cantained read - t_max = chain_edges.a.a[chain_edges.a.n-1]; - - k = 0; rbub_edges.n = 0; - ///edges from the last contained read to other unitigs - - while(get_edge2existing_node_advance_by_broken_bub(ug, r_g, sources, coverage_cut, - ruIndex, expect_vis, max_hang, min_ovlp, t_max.v, &k, &r_edge, 1)) - { - kv_push(asg_arc_t, rbub_edges, r_edge); - } - - ///need to do transitive reduction - ///note here is different to standard transitive reduction - minor_transitive_reduction_r_g(r_g, rbub_edges.a, rbub_edges.n); - - for (k = 0; k < chain_edges.a.n; k++) - { - t_max = chain_edges.a.a[k]; - ///save all infor for reverting - get_R_to_U(ruIndex, t_max.v>>1, &contain_rId, &is_Unitig); - a_nodes=contain_rId; - a_nodes=a_nodes<<32; - a_nodes=a_nodes|((uint64_t)(t_max.v>>1)); - kv_push(uint64_t, u_vecs.a, a_nodes); - - r_g->seq[t_max.v>>1].del = 0; - coverage_cut[t_max.v>>1].del = 0; - coverage_cut[t_max.v>>1].c = PRIMARY_LABLE; - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, - (t_max.ul>>32), t_max.v, &t); - kv_push(asg_arc_t, new_edges, t); - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, - (t_max.v^1), ((t_max.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); - } - - - for (k = 0; k < rbub_edges.n; k++) - { - t = rbub_edges.a[k]; - if(t.del) continue; - - kv_push(asg_arc_t, new_edges, t); - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, - (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); - } - - } - } - } - - - set_rtg_flag_by_bubble(bub, ug, r_g, l_bub, expect_vis, 0); - set_rtg_flag_by_bubble(bub, ug, r_g, r_bub, expect_vis, 0); - set_rtg_flag_by_bubble(bub, ug, r_g, m_bub, expect_vis, 0); - } - } - - asg_arc_t* p = NULL; - for (k = 0; k < new_edges.n; k++) - { - p = asg_arc_pushp(r_g); - *p = new_edges.a[k]; - } - if(new_edges.n != 0) - { - free(r_g->idx); - r_g->idx = 0; - r_g->is_srt = 0; - asg_cleanup(r_g); - asg_symm(r_g); - } - - pre_clean(sources, coverage_cut, r_g, 0); - - lable_all_bubbles(r_g, b_mask_t); - - for (k = 0; k < new_edges.n; k++) - { - v = new_edges.a[k].ul>>32; - w = new_edges.a[k].v; - - if(r_g->seq[v>>1].del) continue; - if(r_g->seq[w>>1].del) continue; - ///if this edge is at a bubble - if(r_g->seq_vis[v]!=0 && r_g->seq_vis[w^1]!=0) continue; - - asg_arc_del(r_g, v, w, 1); - asg_arc_del(r_g, w^1, v^1, 1); - } - asg_cleanup(r_g); - asg_symm(r_g); - - for (k = 0; k < u_vecs.a.n; k++) - { - w = (uint32_t)u_vecs.a.a[k]; - w = w<<1; - if((!r_g->seq[w>>1].del) && - (get_real_length(r_g, w, NULL)!=0 || get_real_length(r_g, (w^1), NULL)!=0)) - { - w=w>>1; - ruIndex->index[w] = (uint32_t)-1; - } - else - { - w=w>>1; - r_g->seq[w].del = 1; - coverage_cut[w].del = 1; - } - } - - for (v = 0; v < ruIndex->len; v++) - { - get_R_to_U(ruIndex, v, &uId, &is_Unitig); - if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; - } - - // fprintf(stderr, "M::%s has done!\n", __func__); - // print_bubble_filling_status(ug, r_g, ruIndex, bub, beg_idx, occ, new_edges.a, new_edges.n); - - kv_destroy(new_edges); - kv_destroy(rbub_edges); - kv_destroy(u_vecs.a); - kv_destroy(chain_edges.a); - free(expect_vis); - free(circle_vis); - free(utg_vis); -} - -void rescue_bubbles_by_cmk_reads(ma_ug_t *i_u_g, asg_t *rg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t chainLenThres, uint32_t beg_idx, uint32_t occ, bubble_type* bub, bub_label_t* b_mask_t, uint8_t *cmk) -{ - asg_t* nsg = NULL; uint32_t beg_utg, sink_utg, *a = NULL, n, i, bub_i, k_i, k_v, k, uId, endRid, is_Unitig, contain_rId; - uint32_t ava_max, ava_ol_max, ava_min_chain, ava_cur, test_oLen, ava_chainLen, is_update, v, w; - uint64_t l_bub, m_bub, r_bub, a_nodes; ma_ug_t* ug = i_u_g; - ma_utg_t *nsu = NULL, *u = NULL; ma_hit_t_alloc* x = NULL; ma_hit_t *h = NULL, *h_max = NULL; - uint8_t* expect_vis = NULL; CALLOC(expect_vis, rg->n_seq); - uint8_t* circle_vis = NULL; CALLOC(circle_vis, rg->n_seq); - uint8_t* utg_vis = NULL; CALLOC(utg_vis, ug->g->n_seq); asg_arc_t t, t_max, r_edge; - - for (v = 0; v < ug->u.n; v++) ug->g->seq[v].c = PRIMARY_LABLE; - - kvec_t(asg_arc_t) new_edges; kv_init(new_edges); - - kvec_t(asg_arc_t) rbub_edges; kv_init(rbub_edges); - - kvec_t_u64_warp u_vecs; kv_init(u_vecs.a); - - kvec_asg_arc_t_warp chain_edges; kv_init(chain_edges.a); - - nsg = ug->g; - for (v = 0; v < nsg->n_seq; v++) { - uId = v; nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsg->seq[v].del) continue; - for (k = 0; k < nsu->n; k++) { - set_R_to_U(ruIndex, nsu->a[k]>>33, uId, 1, &(rg->seq[nsu->a[k]>>33].c)); - } - } - - for (i = 0; i < bub->b_ug->u.n; i++) { - u = &(bub->b_ug->u.a[i]); - if(u->n < 3) continue; ///should be at least 3 - for (bub_i = 1; bub_i+1 < u->n; bub_i++) { - m_bub = u->a[bub_i]>>33; l_bub = r_bub = (uint64_t)-1; - if(m_bub < beg_idx || m_bub >= beg_idx + occ) continue; - l_bub = u->a[bub_i-1]>>33; - r_bub = u->a[bub_i+1]>>33; - - set_rtg_flag_by_bubble(bub, ug, rg, l_bub, expect_vis, 1); - set_rtg_flag_by_bubble(bub, ug, rg, r_bub, expect_vis, 1); - set_rtg_flag_by_bubble(bub, ug, rg, m_bub, expect_vis, 1); - - get_bubbles(bub, m_bub, &beg_utg, &sink_utg, &a, &n, NULL); - for (k_i = 0; k_i < n; k_i++) { - uId = a[k_i]>>1; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - for (k_v = 0; k_v < 2; k_v++) { - v = (uId<<1) + k_v; - if(get_real_length(nsg, v, NULL) != 0) continue; - - if(v&1) endRid = nsu->start^1; - else endRid = nsu->end^1; - - //x is the end read of a tip - ///find all overlap of x - x = &(sources[(endRid>>1)]); - ava_ol_max = ava_max = 0; ava_min_chain = (uint32_t)-1; - h_max = NULL; - for (k = 0; k < x->length; k++) { - ///h is the edge of endRid - h = &(x->buffer[k]); - ///means we found a contained read - if(get_chimeric_reads_chain_by_broken_bub(h, sources, coverage_cut, ruIndex, ug, rg, max_hang, min_ovlp, endRid, uId, &chain_edges, &ava_cur, &test_oLen, &ava_chainLen, expect_vis, circle_vis, utg_vis, chainLenThres, 1, cmk)) { - is_update = 0; - - if(ava_cur > ava_max) { - is_update = 1; - } else if(ava_cur == ava_max) { - if(ava_chainLen < ava_min_chain) { - is_update = 1; - } else if(ava_chainLen == ava_min_chain && test_oLen > ava_ol_max) { - is_update = 1; - } - } - - if(is_update) { - ava_min_chain = ava_chainLen; - ava_max = ava_cur; - ava_ol_max = test_oLen; - h_max = h; - } - } - } - - if(ava_max > 0) { - ///fprintf(stderr, "ava_max: %u\n", ava_max); - get_chimeric_reads_chain_by_broken_bub(h_max, sources, coverage_cut, ruIndex, ug, rg, max_hang, min_ovlp, endRid, uId, &chain_edges, &ava_cur, &test_oLen, &ava_chainLen, expect_vis, circle_vis, NULL, chainLenThres, 1, cmk); - if(chain_edges.a.n < 1) continue; - ///the last cantained read - t_max = chain_edges.a.a[chain_edges.a.n-1]; - - k = 0; rbub_edges.n = 0; - ///edges from the last contained read to other unitigs - - while(get_edge2existing_node_advance_by_broken_bub(ug, rg, sources, coverage_cut, ruIndex, expect_vis, max_hang, min_ovlp, t_max.v, &k, &r_edge, 1)) { - kv_push(asg_arc_t, rbub_edges, r_edge); - } - - ///need to do transitive reduction - ///note here is different to standard transitive reduction - minor_transitive_reduction_r_g(rg, rbub_edges.a, rbub_edges.n); - - for (k = 0; k < chain_edges.a.n; k++) { - t_max = chain_edges.a.a[k]; - ///save all infor for reverting - get_R_to_U(ruIndex, t_max.v>>1, &contain_rId, &is_Unitig); - if((is_Unitig == 1) || (is_Unitig == ((uint32_t)-1))) contain_rId = ((uint32_t)-1);///shouldn't be possible - a_nodes=contain_rId; - a_nodes=a_nodes<<32; - a_nodes=a_nodes|((uint64_t)(t_max.v>>1)); - kv_push(uint64_t, u_vecs.a, a_nodes); - - rg->seq[t_max.v>>1].del = 0; - coverage_cut[t_max.v>>1].del = 0; - coverage_cut[t_max.v>>1].c = PRIMARY_LABLE; - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, (t_max.ul>>32), t_max.v, &t); - kv_push(asg_arc_t, new_edges, t); - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, (t_max.v^1), ((t_max.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); - } - - - for (k = 0; k < rbub_edges.n; k++) { - t = rbub_edges.a[k]; - if(t.del) continue; - - kv_push(asg_arc_t, new_edges, t); - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); - } - - } - } - } - - - set_rtg_flag_by_bubble(bub, ug, rg, l_bub, expect_vis, 0); - set_rtg_flag_by_bubble(bub, ug, rg, r_bub, expect_vis, 0); - set_rtg_flag_by_bubble(bub, ug, rg, m_bub, expect_vis, 0); - } - } - - asg_arc_t* p = NULL; - for (k = 0; k < new_edges.n; k++) { - p = asg_arc_pushp(rg); - *p = new_edges.a[k]; - } - - if(new_edges.n != 0) { - free(rg->idx); - rg->idx = 0; - rg->is_srt = 0; - asg_cleanup(rg); - asg_symm(rg); - } - - pre_clean(sources, coverage_cut, rg, 0); - - lable_all_bubbles(rg, b_mask_t); - - for (k = 0; k < new_edges.n; k++) { - v = new_edges.a[k].ul>>32; - w = new_edges.a[k].v; - - if(rg->seq[v>>1].del) continue; - if(rg->seq[w>>1].del) continue; - ///if this edge is at a bubble - if(rg->seq_vis[v]!=0 && rg->seq_vis[w^1]!=0) continue; - - asg_arc_del(rg, v, w, 1); - asg_arc_del(rg, w^1, v^1, 1); - } - asg_cleanup(rg); - asg_symm(rg); - - for (k = 0; k < u_vecs.a.n; k++) { - w = (uint32_t)u_vecs.a.a[k]; - w = w<<1; - if((!rg->seq[w>>1].del) && (get_real_length(rg, w, NULL)!=0 || get_real_length(rg, (w^1), NULL)!=0)) { - w=w>>1; - ruIndex->index[w] = (uint32_t)-1; - } else { - w=w>>1; - rg->seq[w].del = 1; coverage_cut[w].del = 1; - } - } - - for (v = 0; v < ruIndex->len; v++) { - get_R_to_U(ruIndex, v, &uId, &is_Unitig); - if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; - } - - // fprintf(stderr, "M::%s has done!\n", __func__); - // print_bubble_filling_status(ug, r_g, ruIndex, bub, beg_idx, occ, new_edges.a, new_edges.n); - - kv_destroy(new_edges); - kv_destroy(rbub_edges); - kv_destroy(u_vecs.a); - kv_destroy(chain_edges.a); - free(expect_vis); - free(circle_vis); - free(utg_vis); -} - - -void rescue_bubbles_by_missing_ovlp(ma_ug_t *i_u_g, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t chainLenThres, uint32_t beg_idx, uint32_t occ, bubble_type* bub, -bub_label_t* b_mask_t) -{ - asg_t* nsg = NULL; - uint32_t beg_utg, sink_utg, *a = NULL, n, i, bub_i, k_i, k_v, k, uId, endRid, is_Unitig, v, w; - uint64_t l_bub, m_bub, r_bub/**, bub_0, bub_1**/; - ma_ug_t* ug = i_u_g; - ma_utg_t *nsu = NULL, *u = NULL; - uint8_t* expect_vis = NULL; CALLOC(expect_vis, r_g->n_seq); - asg_arc_t t, r_edge; - - for (v = 0; v < ug->u.n; v++) ug->g->seq[v].c = PRIMARY_LABLE; - - kvec_t(asg_arc_t) new_edges; - kv_init(new_edges); - - kvec_t(asg_arc_t) rbub_edges; - kv_init(rbub_edges); - - - nsg = ug->g; - for (v = 0; v < nsg->n_seq; v++) - { - uId = v; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsg->seq[v].del) continue; - for (k = 0; k < nsu->n; k++) - { - set_R_to_U(ruIndex, nsu->a[k]>>33, uId, 1, &(r_g->seq[nsu->a[k]>>33].c)); - } - } - - for (i = 0; i < bub->b_ug->u.n; i++) - { - u = &(bub->b_ug->u.a[i]); - if(u->n < 3) continue; ///should be at least 3 - for (bub_i = 1; bub_i+1 < u->n; bub_i++) - { - m_bub = u->a[bub_i]>>33; l_bub = r_bub = (uint64_t)-1; - if(m_bub < beg_idx || m_bub >= beg_idx + occ) continue; - l_bub = u->a[bub_i-1]>>33; - r_bub = u->a[bub_i+1]>>33; - - set_rtg_flag_by_bubble(bub, ug, r_g, l_bub, expect_vis, 1); - set_rtg_flag_by_bubble(bub, ug, r_g, r_bub, expect_vis, 1); - set_rtg_flag_by_bubble(bub, ug, r_g, m_bub, expect_vis, 1); - - get_bubbles(bub, m_bub, &beg_utg, &sink_utg, &a, &n, NULL); - - for (k_i = 0; k_i < n; k_i++) - { - uId = a[k_i]>>1; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - for (k_v = 0; k_v < 2; k_v++) - { - v = (uId<<1) + k_v; - if(get_real_length(nsg, v, NULL) != 0) continue; - - if(v&1) - { - endRid = nsu->start^1; - } - else - { - endRid = nsu->end^1; - } - - - k = 0; rbub_edges.n = 0; - while(get_edge2existing_node_advance_by_broken_bub(ug, r_g, sources, coverage_cut, - ruIndex, expect_vis, max_hang, min_ovlp, endRid, &k, &r_edge, 1)) - { - kv_push(asg_arc_t, rbub_edges, r_edge); - } - - if(rbub_edges.n > 0) - { - ///need to do transitive reduction - ///note here is different to standard transitive reduction - minor_transitive_reduction_r_g(r_g, rbub_edges.a, rbub_edges.n); - for (k = 0; k < rbub_edges.n; k++) - { - t = rbub_edges.a[k]; - if(t.del) continue; - - kv_push(asg_arc_t, new_edges, t); - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, - (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); - } - } - } - } - - - set_rtg_flag_by_bubble(bub, ug, r_g, l_bub, expect_vis, 0); - set_rtg_flag_by_bubble(bub, ug, r_g, r_bub, expect_vis, 0); - set_rtg_flag_by_bubble(bub, ug, r_g, m_bub, expect_vis, 0); - } - } - - asg_arc_t* p = NULL; - for (k = 0; k < new_edges.n; k++) - { - p = asg_arc_pushp(r_g); - *p = new_edges.a[k]; - } - if(new_edges.n != 0) - { - free(r_g->idx); - r_g->idx = 0; - r_g->is_srt = 0; - asg_cleanup(r_g); - asg_symm(r_g); - } - - pre_clean(sources, coverage_cut, r_g, 0); - - lable_all_bubbles(r_g, b_mask_t); - - - for (k = 0; k < new_edges.n; k++) - { - v = new_edges.a[k].ul>>32; - w = new_edges.a[k].v; - - if(r_g->seq[v>>1].del) continue; - if(r_g->seq[w>>1].del) continue; - ///if this edge is at a bubble - if(r_g->seq_vis[v]!=0 && r_g->seq_vis[w^1]!=0) continue; - - asg_arc_del(r_g, v, w, 1); - asg_arc_del(r_g, w^1, v^1, 1); - } - asg_cleanup(r_g); - asg_symm(r_g); - - - for (v = 0; v < ruIndex->len; v++) - { - get_R_to_U(ruIndex, v, &uId, &is_Unitig); - if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; - } - // fprintf(stderr, "M::%s has done!\n", __func__); - // print_bubble_filling_status(ug, r_g, ruIndex, bub, beg_idx, occ, new_edges.a, new_edges.n); - - kv_destroy(new_edges); - kv_destroy(rbub_edges); - free(expect_vis); -} - -void update_unitig(long long step, long long init, ma_utg_t* nsu, asg_t *r_g, kvec_asg_arc_t_warp* recover_edges, uint32_t update_mode); -void rescue_bubbles_by_missing_ovlp_backward(ma_ug_t *i_u_g, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t backward_steps, uint32_t beg_idx, uint32_t occ, bubble_type* bub, bub_label_t* b_mask_t) -{ - asg_t* nsg = NULL; - uint32_t beg_utg, sink_utg, *a = NULL, n, i, bub_i, k_i, k_v, k, uId, endRid, is_Unitig, round, cur_backward_steps; - uint32_t v, w, mode, nv; - uint64_t l_bub, m_bub, r_bub, /**bub_0, bub_1,**/ tmp; - ma_ug_t* ug = i_u_g; - ma_utg_t *nsu = NULL, *u = NULL; - uint8_t* expect_vis = NULL; CALLOC(expect_vis, r_g->n_seq); - long long init, step = 0; - asg_arc_t t, r_edge, *av = NULL; - - for (v = 0; v < ug->u.n; v++) ug->g->seq[v].c = PRIMARY_LABLE; - - kvec_t(asg_arc_t) new_edges; - kv_init(new_edges); - - kvec_asg_arc_t_warp recover_edges; - kv_init(recover_edges.a); - - kvec_t(asg_arc_t) rbub_edges; - kv_init(rbub_edges); - - kvec_t_u64_warp u_vecs; - kv_init(u_vecs.a); - - - nsg = ug->g; - for (v = 0; v < nsg->n_seq; v++) - { - uId = v; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsg->seq[v].del) continue; - for (k = 0; k < nsu->n; k++) - { - set_R_to_U(ruIndex, nsu->a[k]>>33, uId, 1, &(r_g->seq[nsu->a[k]>>33].c)); - } - } - - - for (i = 0; i < bub->b_ug->u.n; i++) - { - u = &(bub->b_ug->u.a[i]); - if(u->n < 3) continue; ///should be at least 3 - for (bub_i = 1; bub_i+1 < u->n; bub_i++) - { - m_bub = u->a[bub_i]>>33; l_bub = r_bub = (uint64_t)-1; - if(m_bub < beg_idx || m_bub >= beg_idx + occ) continue; - l_bub = u->a[bub_i-1]>>33; - r_bub = u->a[bub_i+1]>>33; - - set_rtg_flag_by_bubble(bub, ug, r_g, l_bub, expect_vis, 1); - set_rtg_flag_by_bubble(bub, ug, r_g, r_bub, expect_vis, 1); - set_rtg_flag_by_bubble(bub, ug, r_g, m_bub, expect_vis, 1); - get_bubbles(bub, m_bub, &beg_utg, &sink_utg, &a, &n, NULL); - for (k_i = 0; k_i < n; k_i++) - { - uId = a[k_i]>>1; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - - rbub_edges.n = round = 0; - for (k_v = 0; k_v < 2; k_v++) - { - if(rbub_edges.n > 0) - { - cur_backward_steps = nsu->n - round - 1; - if(cur_backward_steps > backward_steps) - { - cur_backward_steps = backward_steps; - } - } - else - { - cur_backward_steps = backward_steps; - } - - - v = (uId<<1) + k_v; - if(get_real_length(nsg, v, NULL) != 0) continue; - ///fprintf(stderr, "++++++tig-utg%.6ul\n", uId+1); - ///that means this unitig has been changed - // if(nsu->start!=((uint64_t)(nsu->a[0])>>32)) continue; - // if((nsu->end^1)!=((uint64_t)(nsu->a[nsu->n-1])>>32)) continue; - - if(v&1) - { - init = 0; - step = 1; - mode = 1; - } - else - { - init = nsu->n - 1; - step = -1; - mode = 0; - } - - rbub_edges.n = 0; - for (round = 0; round < cur_backward_steps && init >= 0 && init < (long long)nsu->n; - init = init + step, round++) - { - endRid = ((uint64_t)(nsu->a[init]))>>32; - endRid = endRid^mode; - - k = 0; rbub_edges.n = 0; - while(get_edge2existing_node_advance_by_broken_bub(ug, r_g, sources, coverage_cut, - ruIndex, expect_vis, max_hang, min_ovlp, endRid, &k, &r_edge, 1)) - { - kv_push(asg_arc_t, rbub_edges, r_edge); - } - - if(rbub_edges.n > 0) break; - } - - if(rbub_edges.n > 0) - { - //save for revert - tmp = mode; tmp = tmp <<31; tmp = tmp | (uint64_t)(init); tmp = tmp << 32; tmp = tmp | uId; - kv_push(uint64_t, u_vecs.a, tmp); - ///need to do transitive reduction - ///note here is different to standard transitive reduction - minor_transitive_reduction_r_g(r_g, rbub_edges.a, rbub_edges.n); - - - ///modify read graph - for (init = init - step; init >= 0 && init < (long long)nsu->n; init = init - step) - { - w = ((uint64_t)(nsu->a[init]))>>32; - nv = asg_arc_n(r_g, w); - av = asg_arc_a(r_g, w); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - kv_push(asg_arc_t, recover_edges.a, av[k]); - if(asg_get_arc(r_g, av[k].v^1, av[k].ul>>32^1, &t)==0) - { - fprintf(stderr, "error\n"); - } - kv_push(asg_arc_t, recover_edges.a, t); - } - - - nv = asg_arc_n(r_g, w^1); - av = asg_arc_a(r_g, w^1); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - kv_push(asg_arc_t, recover_edges.a, av[k]); - if(asg_get_arc(r_g, av[k].v^1, av[k].ul>>32^1, &t)==0) - { - fprintf(stderr, "error\n"); - } - kv_push(asg_arc_t, recover_edges.a, t); - } - - ///w = ((uint64_t)(nsu->a[init]))>>32; - asg_seq_del(r_g, w>>1); - expect_vis[w>>1] = 0; - } - - - for (k = 0; k < rbub_edges.n; k++) - { - t = rbub_edges.a[k]; - if(t.del) continue; - - kv_push(asg_arc_t, new_edges, t); - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, - (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); - } - } - - } - } - - - set_rtg_flag_by_bubble(bub, ug, r_g, l_bub, expect_vis, 0); - set_rtg_flag_by_bubble(bub, ug, r_g, r_bub, expect_vis, 0); - set_rtg_flag_by_bubble(bub, ug, r_g, m_bub, expect_vis, 0); - } - } - - asg_arc_t* p = NULL; - for (k = 0; k < new_edges.n; k++) - { - p = asg_arc_pushp(r_g); - *p = new_edges.a[k]; - } - if(new_edges.n != 0) - { - free(r_g->idx); - r_g->idx = 0; - r_g->is_srt = 0; - asg_cleanup(r_g); - asg_symm(r_g); - } - - pre_clean(sources, coverage_cut, r_g, 0); - - lable_all_bubbles(r_g, b_mask_t); - - for (k = 0; k < new_edges.n; k++) - { - v = new_edges.a[k].ul>>32; - w = new_edges.a[k].v; - - if(r_g->seq[v>>1].del) continue; - if(r_g->seq[w>>1].del) continue; - ///if this edge is at a bubble - if(r_g->seq_vis[v]!=0 && r_g->seq_vis[w^1]!=0) continue; - - asg_arc_del(r_g, v, w, 1); - asg_arc_del(r_g, w^1, v^1, 1); - } - asg_cleanup(r_g); - asg_symm(r_g); - - for (k = 0; k < recover_edges.a.n; k++) - { - recover_edges.a.a[k].del = 1; - } - - for (k = 0; k < u_vecs.a.n; k++) - { - mode = (uint64_t)u_vecs.a.a[k]>>63; - if(mode == 1) step = 1; - if(mode == 0) step = -1; - init = (uint64_t)((uint64_t)u_vecs.a.a[k]>>32)&((uint64_t)(0x7fffffff)); - uId = (uint32_t)u_vecs.a.a[k]; - nsu = &(ug->u.a[uId]); - - endRid = ((uint64_t)(nsu->a[init]))>>32; - endRid = endRid^mode; - if(get_real_length(r_g, endRid, NULL) > 0) - { - update_unitig(step, init, nsu, r_g, &recover_edges, 1); - } - else - { - update_unitig(step, init, nsu, r_g, &recover_edges, 0); - } - // if(get_real_length(r_g, endRid, NULL) <= 0) - // { - // update_unitig(step, init, nsu, r_g, &recover_edges, 0); - // } - } - - uint64_t recov_occ = 0; - for (k = 0; k < recover_edges.a.n; k++) - { - if(recover_edges.a.a[k].del) continue; - p = asg_arc_pushp(r_g); - *p = recover_edges.a.a[k]; - recov_occ++; - } - - if(recov_occ != 0) - { - free(r_g->idx); - r_g->idx = 0; - r_g->is_srt = 0; - asg_cleanup(r_g); - asg_symm(r_g); - } - - - for (v = 0; v < ruIndex->len; v++) - { - get_R_to_U(ruIndex, v, &uId, &is_Unitig); - if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; - } - - // fprintf(stderr, "M::%s has done!\n", __func__); - // print_bubble_filling_status(ug, r_g, ruIndex, bub, beg_idx, occ, new_edges.a, new_edges.n); - - kv_destroy(new_edges); - kv_destroy(rbub_edges); - kv_destroy(u_vecs.a); - kv_destroy(recover_edges.a); - free(expect_vis); -} - - -void reset_bub(bubble_type* bub, ma_ug_t *ug, trans_chain* back_ug_chain, kvec_asg_arc_t_warp* new_rtg_edges) -{ - destory_bubbles(bub); - memset(bub, 0, sizeof(bubble_type)); - - if(new_rtg_edges) new_rtg_edges->a.n = 0; - ///classify_untigs(ug, sg, coverage_cut, sources, reverse_sources, ruIndex, new_rtg_edges, max_hang, min_ovlp); - identify_bubbles(ug, bub, back_ug_chain->ir_het, NULL); - // update_bubble_chain(ug, bub, 0, 1); - // resolve_bubble_chain_tangle(ug, bub); - // fprintf(stderr, "bub.f_bub: %lu, bub.b_bub: %lu, bub.b_end_bub: %lu, bub.tangle_bub: %lu, bub.cross_bub: %lu\n", - // bub->f_bub, bub->b_bub, bub->b_end_bub, bub->tangle_bub, bub->cross_bub); -} - - -int bub_complex(asg_t *sg, ma_ug_t *ug, bubble_type* bub, uint32_t bid, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, kvec_t_u32_warp* stack, -int max_hang, int min_ovlp, uint8_t* trio_flag, uint8_t* vis_flag, kv_asg_arc_t* e, buf_t *b, uint64_t tLen) -{ - if(bid >= bub->f_bub) return 0; - uint32_t beg_utg, sink_utg, *a = NULL, n, begRid, sinkRid, i, k_i, k_j, k_v, rID/**, cur_flag, pre_flag, after_flag**/; - int is_switch_0, is_switch_1; - ma_utg_t* nsu = NULL; - get_bubbles(bub, bid, &beg_utg, &sink_utg, &a, &n, NULL); - if(beg_utg == (uint32_t)-1 || sink_utg == (uint32_t)-1) return 0; - if(beg_utg&1) - { - begRid = ug->u.a[beg_utg>>1].start^1; - } - else - { - begRid = ug->u.a[beg_utg>>1].end^1; - } - - if(sink_utg&1) - { - sinkRid = ug->u.a[sink_utg>>1].start; - } - else - { - sinkRid = ug->u.a[sink_utg>>1].end; - } - - - - is_switch_0 = is_switch_1 = 1; - asg_bub_pop1_primary_trio_switch_check(ug->g, ug, beg_utg, tLen, b, FATHER, DROP, 0, NULL, NULL, &is_switch_0); - - if(is_switch_0 == 0) - { - asg_bub_pop1_primary_trio_switch_check(ug->g, ug, beg_utg, tLen, b, MOTHER, DROP, 0, NULL, NULL, &is_switch_1); - } - - - for (k_i = 0; k_i < n; k_i++) - { - nsu = &(ug->u.a[a[k_i]>>1]); - for (k_j = 0; k_j < nsu->n; k_j++) - { - rID = nsu->a[k_j]>>33; - if(R_INF.trio_flag[rID] == DROP) R_INF.trio_flag[rID] = AMBIGU; - } - } - /*******************************for debug************************************/ - // for (i = 0; i < sg->n_seq; i++) - // { - // if(R_INF.trio_flag[i] == DROP) fprintf(stderr, "ERROR-1\n"); - // } - /*******************************for debug************************************/ - - if(is_switch_0 == 0 && is_switch_1 == 0) return 0; - - asg_arc_t *acur = NULL; - uint32_t cur, ncur, v, n_vx = sg->n_seq<<1; - stack->a.n = 0; - memset(vis_flag, 0, n_vx); - - kv_push(uint32_t, stack->a, begRid); - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - ncur = asg_arc_n(sg, cur); - acur = asg_arc_a(sg, cur); - vis_flag[cur] = 1; - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if(vis_flag[acur[i].v]) continue; - if(acur[i].v == sinkRid) continue; - kv_push(uint32_t, stack->a, acur[i].v); - } - } - vis_flag[sinkRid] = 1; - - - ma_hit_t_alloc* x = NULL; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - int32_t r; - asg_arc_t t; - - - for (k_i = 0; k_i < n; k_i++) - { - nsu = &(ug->u.a[a[k_i]>>1]); - for (k_j = 0; k_j < nsu->n; k_j++) - { - rID = nsu->a[k_j]>>33; - for (k_v = 0; k_v < 2; k_v++) - { - v = (rID<<1) + k_v; - if(vis_flag[v] == 0) continue; - x = &(sources[v>>1]); - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(st->del || sg->seq[Get_tn(*h)].del) continue; - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - - ///if it is a contained read, skip - if(r < 0) continue; - if((t.ul>>32) != v) continue; - if(vis_flag[t.ul>>32] == 0 || vis_flag[t.v] == 0) continue; - kv_push(asg_arc_t, *e, t); - get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, - (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, *e, t); - } - - } - } - } - - return 1; - - /** - for (v = 0; v < n_vx; v++) - { - if(vis_flag[v] == 0) continue; - fprintf(stderr, "v: %u, n_vx: %u\n", v, n_vx); - x = &(sources[v>>1]); - for (i = 0; i < x->length; i++) - { - fprintf(stderr, "i: %u, x->length: %u\n", i, x->length); - h = &(x->buffer[i]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(st->del || sg->seq[Get_tn(*h)].del) continue; - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - - ///if it is a contained read, skip - if(r < 0) continue; - if((t.ul>>32) != v) continue; - if(vis_flag[t.ul>>32] == 0 || vis_flag[t.v] == 0) continue; - kv_push(asg_arc_t, *e, t); - get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, - (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, *e, t); - } - } - **/ - - - /*******************************for debug************************************/ - // uint32_t utg_occ = 0, rtg_occ = 0; - // for (i = 0; i < n; i++) - // { - // utg_occ += ug->u.a[a[i]>>1].n; - // } - - // for (i = 0; i < n_vx; i++) - // { - // if(vis_flag[i]) rtg_occ++; - // } - - // fprintf(stderr, "bid: %u, rtg_occ: %u, utg_occ: %u\n", bid, rtg_occ, utg_occ); - // if(rtg_occ != utg_occ + 2) fprintf(stderr, "ERROR\n"); - /*******************************for debug************************************/ -} - - -void debug_bubble_chain(asg_t *sg, ma_ug_t *ug, bubble_type* bub, uint32_t bid, kvec_t_u32_warp* stack, uint8_t* vis_flag) -{ - if(bid >= bub->f_bub) return; - uint32_t beg_utg, sink_utg, *a = NULL, n, begRid, sinkRid; - get_bubbles(bub, bid, &beg_utg, &sink_utg, &a, &n, NULL); - if(beg_utg == (uint32_t)-1 || sink_utg == (uint32_t)-1) return; - if(beg_utg&1) - { - begRid = ug->u.a[beg_utg>>1].start^1; - } - else - { - begRid = ug->u.a[beg_utg>>1].end^1; - } - - if(sink_utg&1) - { - sinkRid = ug->u.a[sink_utg>>1].start; - } - else - { - sinkRid = ug->u.a[sink_utg>>1].end; - } - - asg_arc_t *acur = NULL; - uint32_t cur, ncur, i, n_vx = sg->n_seq<<1; - stack->a.n = 0; - memset(vis_flag, 0, n_vx); - - kv_push(uint32_t, stack->a, begRid); - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - ncur = asg_arc_n(sg, cur); - acur = asg_arc_a(sg, cur); - vis_flag[cur] = 1; - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if(vis_flag[acur[i].v]) continue; - if(acur[i].v == sinkRid) continue; - kv_push(uint32_t, stack->a, acur[i].v); - } - } - vis_flag[sinkRid] = 1; - - - /*******************************for debug************************************/ - uint32_t utg_occ = 0, rtg_occ = 0; - for (i = 0; i < n; i++) - { - utg_occ += ug->u.a[a[i]>>1].n; - } - - for (i = 0; i < n_vx; i++) - { - if(vis_flag[i]) rtg_occ++; - } - - fprintf(stderr, "bid: %u, rtg_occ: %u, utg_occ: %u\n", bid, rtg_occ, utg_occ); - if(rtg_occ != utg_occ + 2) fprintf(stderr, "ERROR\n"); - /*******************************for debug************************************/ -} - -void rescue_missing_hap_ovlp(ma_ug_t *u_g, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -int max_hang, int min_ovlp, bubble_type* bub, long long gap_fuzz) -{ - uint32_t i, n_arc = r_g->n_arc, fix_bub = 0; - uint8_t* vis_flag = NULL; CALLOC(vis_flag, r_g->n_seq*2); - kvec_t_u32_warp stack; kv_init(stack.a); - kv_asg_arc_t e; kv_init(e); - double index_time = yak_realtime(); - - buf_t b; memset(&b, 0, sizeof(buf_t)); - b.a = (binfo_t*)calloc(u_g->g->n_seq * 2, sizeof(binfo_t)); - uint64_t tLen = get_bub_pop_max_dist_advance(u_g->g, &b); - for (i = 0; i < bub->f_bub; i++) - { - fix_bub += bub_complex(r_g, u_g, bub, i, sources, coverage_cut, &stack, max_hang, min_ovlp, R_INF.trio_flag, vis_flag, &e, &b, tLen); - } - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - - asg_arc_t* p = NULL; - for (i = 0; i < e.n; i++) - { - p = asg_arc_pushp(r_g); - *p = e.a[i]; - } - if(e.n != 0) - { - free(r_g->idx); - r_g->idx = 0; - r_g->is_srt = 0; - asg_cleanup(r_g); - asg_symm(r_g); - asg_arc_del_trans(r_g, gap_fuzz); - // for (i = 0; i < bub->f_bub; i++) - // { - // debug_bubble_chain(r_g, u_g, bub, i, &stack, vis_flag); - // } - } - - fprintf(stderr, "[M::%s::%.3f] # inserted edges: %u, # fixed bubbles: %u\n", - __func__, yak_realtime() - index_time, r_g->n_arc - n_arc, fix_bub); - - free(vis_flag); - kv_destroy(stack.a); - kv_destroy(e); -} - - -void rescue_bubble_by_chain(asg_t *sg, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, -int max_hang, int min_ovlp, uint32_t chainLenThres, long long gap_fuzz, bub_label_t* b_mask_t, long long no_trio_recover, uint8_t *cmk) -{ - kvec_asg_arc_t_warp new_rtg_edges; - kv_init(new_rtg_edges.a); - ma_ug_t *ug = NULL; - ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); - - hap_cov_t *cov = NULL; - asg_t *copy_sg = copy_read_graph(sg); - ma_ug_t *copy_ug = copy_untig_graph(ug); - adjust_utg_by_primary(©_ug, copy_sg, TRIO_THRES, sources, reverse_sources, coverage_cut, - tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, - max_hang, min_ovlp, &new_rtg_edges, &cov, b_mask_t, 0, 0); - ma_ug_destroy(copy_ug); copy_ug = NULL; - asg_destroy(copy_sg); copy_sg = NULL; - - uint32_t beg_idx, occ; - bubble_type bub; - memset(&bub, 0, sizeof(bubble_type)); - copy_ug = copy_untig_graph(ug); - reset_bub(&bub, ug, cov->t_ch, &new_rtg_edges); - beg_idx = bub.f_bub; occ = bub.b_bub + bub.b_end_bub + bub.tangle_bub; - rescue_bubbles_by_contained_reads(ug, sg, sources, coverage_cut, ruIndex, max_hang, min_ovlp, chainLenThres, beg_idx, occ, &bub, b_mask_t); - - ma_ug_destroy(ug); ug = NULL; ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); - reset_bub(&bub, ug, cov->t_ch, &new_rtg_edges); - beg_idx = bub.f_bub; occ = bub.b_bub + bub.b_end_bub + bub.tangle_bub; - rescue_bubbles_by_missing_ovlp(ug, sg, sources, coverage_cut, ruIndex, max_hang, min_ovlp, chainLenThres, beg_idx, occ, &bub, b_mask_t); - - ma_ug_destroy(ug); ug = NULL; ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); - reset_bub(&bub, ug, cov->t_ch, &new_rtg_edges); - beg_idx = bub.f_bub; occ = bub.b_bub + bub.b_end_bub + bub.tangle_bub; - rescue_bubbles_by_missing_ovlp_backward(ug, sg, sources, coverage_cut, ruIndex, max_hang, min_ovlp, chainLenThres, beg_idx, occ, &bub, b_mask_t); - - if(cmk) { - ma_ug_destroy(ug); ug = NULL; ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); - reset_bub(&bub, ug, cov->t_ch, &new_rtg_edges); - beg_idx = bub.f_bub; occ = bub.b_bub + bub.b_end_bub + bub.tangle_bub; - rescue_bubbles_by_cmk_reads(ug, sg, sources, coverage_cut, ruIndex, max_hang, min_ovlp, chainLenThres, beg_idx, occ, &bub, b_mask_t, cmk); - } - /** - if((!no_trio_recover) && (ha_opt_triobin(&asm_opt))) - { - ma_ug_destroy(ug); ug = NULL; ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); - reset_bub(&bub, ug, cov->t_ch, &new_rtg_edges); - // rescue_missing_hap_ovlp(ug, sg, sources, coverage_cut, max_hang, min_ovlp, &bub, gap_fuzz); - reduce_hamming_error_adv(ug, sg, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz, ruIndex, &bub); - } - **/ - - destory_bubbles(&bub); - destory_hap_cov_t(&cov); - ma_ug_destroy(ug); - kv_destroy(new_rtg_edges.a); - ma_ug_destroy(copy_ug); copy_ug = NULL; -} - -void update_unitig(long long step, long long init, ma_utg_t* nsu, asg_t *r_g, -kvec_asg_arc_t_warp* recover_edges, uint32_t update_mode) -{ - uint64_t l, k; - uint32_t v; - ///recover - if(update_mode == 0) - { - if(step == 1) nsu->start = ((uint64_t)(nsu->a[0])>>32); - if(step == -1) nsu->end = ((uint64_t)(nsu->a[nsu->n-1])>>32)^1; - if(recover_edges) - { - ///the first node has not been deleted, others has been deleted - for (init = init - step; init >= 0 && init < (long long)nsu->n; init = init - step) - { - v = (uint64_t)nsu->a[init]>>32; - r_g->seq[v>>1].del = 0; - for (k = 0; k < recover_edges->a.n; k++) - { - if(((v>>1)==(recover_edges->a.a[k].ul>>33)) || - ((v>>1)==(recover_edges->a.a[k].v>>1))) - { - recover_edges->a.a[k].del = 0; - } - } - } - } - } - else ///update - { - //end of unitig - if(step == -1 && init != (long long)((long long)nsu->n - 1)) - { - l = r_g->seq[(nsu->a[init]>>33)].len; - nsu->n = init+1; - nsu->a[nsu->n-1] = nsu->a[nsu->n-1]>>32; - nsu->a[nsu->n-1] = nsu->a[nsu->n-1]<<32; - nsu->a[nsu->n-1] = nsu->a[nsu->n-1] | (uint64_t)(l); - } - - //beg of unitig - if(step == 1 && init != 0) - { - for(k = init; k < nsu->n; k++) - { - nsu->a[k-init] = nsu->a[k]; - } - nsu->n = nsu->n - init; - } - - nsu->len = 0; - for(k = 0; k < nsu->n; k++) - { - nsu->len += (uint32_t)nsu->a[k]; - } - } -} -void rescue_missing_overlaps_backward(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t backward_steps, uint32_t is_bubble_check, uint32_t is_primary_check, bub_label_t* b_mask_t) -{ - uint32_t v, vId, dir, k, cur_backward_steps, round, is_Unitig, uId, rId, endRid, oLen, w, max_oLen, max_oLen_i, mode, nv; - uint64_t tmp; - long long init, step = 0; - asg_t* nsg = NULL; - ma_utg_t* nsu = NULL; - ma_ug_t *ug = NULL; - asg_arc_t *av = NULL; - asg_arc_t t, r_edge; - kvec_t(asg_arc_t) new_edges; - kv_init(new_edges); - - kvec_asg_arc_t_warp recover_edges; - kv_init(recover_edges.a); - - kvec_t(asg_arc_t) rbub_edges; - kv_init(rbub_edges); - - kvec_t_u64_warp u_vecs; - kv_init(u_vecs.a); - - if(i_ug != NULL) - { - ug = i_ug; - } - else - { - ug = ma_ug_gen(r_g); - for (v = 0; v < ug->g->n_seq; v++) - { - ug->g->seq[v].c = PRIMARY_LABLE; - } - } - nsg = ug->g; - - for (v = 0; v < nsg->n_seq; v++) - { - uId = v; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsg->seq[v].del) continue; - if(is_primary_check && nsg->seq[v].c==ALTER_LABLE) continue; - - for (k = 0; k < nsu->n; k++) - { - rId = nsu->a[k]>>33; - set_R_to_U(ruIndex, rId, uId, 1, &(r_g->seq[rId].c)); - } - } - - - - for (vId = 0; vId < nsg->n_seq; vId++) - { - rbub_edges.n = round = 0; - for (dir = 0; dir < 2; dir++) - { - if(rbub_edges.n > 0) - { - cur_backward_steps = nsu->n - round - 1; - if(cur_backward_steps > backward_steps) - { - cur_backward_steps = backward_steps; - } - } - else - { - cur_backward_steps = backward_steps; - } - - - - v = vId; v = v<<1; v = v | dir; - uId = v>>1; - if(nsg->seq[uId].del) continue; - if(is_primary_check && nsg->seq[uId].c == ALTER_LABLE) continue; - - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsu->circ || nsu->start == UINT32_MAX || nsu->end == UINT32_MAX) continue; - if(get_real_length(nsg, v, NULL) != 0) continue; - ////if(get_real_length(nsg, v^1, NULL) == 0) continue; - ///that means this unitig has been changed - if(nsu->start!=((uint64_t)(nsu->a[0])>>32)) continue; - if((nsu->end^1)!=((uint64_t)(nsu->a[nsu->n-1])>>32)) continue; - - if(v&1) - { - init = 0; - step = 1; - mode = 1; - //endRid = nsu->start^1; - } - else - { - init = nsu->n - 1; - step = -1; - mode = 0; - ///endRid = nsu->end^1; - } - - - rbub_edges.n = 0; - for (round = 0; round < cur_backward_steps && init >= 0 && init < (long long)nsu->n; - init = init + step, round++) - { - endRid = ((uint64_t)(nsu->a[init]))>>32; - endRid = endRid^mode; - - k = 0; - rbub_edges.n = 0; - while(get_edge2existing_node_advance(ug, r_g, sources, coverage_cut, ruIndex, - max_hang, min_ovlp, endRid, &uId, 1, &k, &r_edge, 1)) - { - kv_push(asg_arc_t, rbub_edges, r_edge); - } - if(rbub_edges.n > 0) break; - } - - if(rbub_edges.n > 0) - { - if(mode == 1) nsu->start = endRid^1; - if(mode == 0) nsu->end = endRid^1; - //save for revert - tmp = mode; tmp = tmp <<31; tmp = tmp | (uint64_t)(init); tmp = tmp << 32; tmp = tmp | uId; - kv_push(uint64_t, u_vecs.a, tmp); - - - - ///need to do transitive reduction - ///note here is different to standard transitive reduction - minor_transitive_reduction(ug, ruIndex, rbub_edges.a, rbub_edges.n); - if(is_primary_check) - { - max_oLen = 0; max_oLen_i = (uint32_t)-1; - for (k = 0; k < rbub_edges.n; k++) - { - t = rbub_edges.a[k]; - if(t.del) continue; - if(t.ol > max_oLen) - { - max_oLen = t.ol; - max_oLen_i = k; - } - } - - if(max_oLen_i == (uint32_t)-1) continue; - t = rbub_edges.a[max_oLen_i]; - w = get_corresponding_uId(ug, ruIndex, t.v); - if(w == ((uint32_t)(-1))) continue; - if(get_real_length(nsg, w^1, NULL)!=0) continue; - - kv_push(asg_arc_t, new_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); - - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, - (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); - } - else - { - ///modify read graph - for (init = init - step; init >= 0 && init < (long long)nsu->n; init = init - step) - { - w = ((uint64_t)(nsu->a[init]))>>32; - nv = asg_arc_n(r_g, w); - av = asg_arc_a(r_g, w); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - kv_push(asg_arc_t, recover_edges.a, av[k]); - if(asg_get_arc(r_g, av[k].v^1, av[k].ul>>32^1, &t)==0) - { - fprintf(stderr, "error\n"); - } - kv_push(asg_arc_t, recover_edges.a, t); - } - - - nv = asg_arc_n(r_g, w^1); - av = asg_arc_a(r_g, w^1); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - kv_push(asg_arc_t, recover_edges.a, av[k]); - if(asg_get_arc(r_g, av[k].v^1, av[k].ul>>32^1, &t)==0) - { - fprintf(stderr, "error\n"); - } - kv_push(asg_arc_t, recover_edges.a, t); - } - - ///w = ((uint64_t)(nsu->a[init]))>>32; - asg_seq_del(r_g, w>>1); - } - - - - for (k = 0; k < rbub_edges.n; k++) - { - t = rbub_edges.a[k]; - if(t.del) continue; - w = get_corresponding_uId(ug, ruIndex, t.v); - if(w == ((uint32_t)(-1))) continue; - // get_R_to_U(ruIndex, t.v>>1, &uId, &is_Unitig); - // w = (uint32_t)-1; - // if(t.v == ug->u.a[uId].start) w = uId<<1; - // if(t.v == ug->u.a[uId].end) w = (uId<<1)^1; - kv_push(asg_arc_t, new_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); - - - get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, - (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, new_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); - } - } - - } - } - } - - - if(is_bubble_check) - { - asg_arc_t* p = NULL; - for (k = 0; k < new_edges.n; k++) - { - p = asg_arc_pushp(r_g); - *p = new_edges.a[k]; - } - - if(new_edges.n != 0) - { - free(r_g->idx); - r_g->idx = 0; - r_g->is_srt = 0; - asg_cleanup(r_g); - } - - pre_clean(sources, coverage_cut, r_g, 0); - - lable_all_bubbles(r_g, b_mask_t); - - - for (k = 0; k < new_edges.n; k++) - { - v = new_edges.a[k].ul>>32; - w = new_edges.a[k].v; - - if(r_g->seq[v>>1].del) continue; - if(r_g->seq[w>>1].del) continue; - ///if this edge is at a bubble - if(r_g->seq_vis[v]!=0 && r_g->seq_vis[w^1]!=0) continue; - - asg_arc_del(r_g, v, w, 1); - asg_arc_del(r_g, w^1, v^1, 1); - } - - asg_cleanup(r_g); - - - for (k = 0; k < recover_edges.a.n; k++) - { - recover_edges.a.a[k].del = 1; - } - - for (k = 0; k < u_vecs.a.n; k++) - { - mode = (uint64_t)u_vecs.a.a[k]>>63; - if(mode == 1) step = 1; - if(mode == 0) step = -1; - init = (uint64_t)((uint64_t)u_vecs.a.a[k]>>32)&((uint64_t)(0x7fffffff)); - uId = (uint32_t)u_vecs.a.a[k]; - nsu = &(ug->u.a[uId]); - - endRid = ((uint64_t)(nsu->a[init]))>>32; - endRid = endRid^mode; - /********************for debug**********************/ - // fprintf(stderr, "n: %u, k: %u, mode: %u, init: %lld, step: %lld, uId: %u, endRid: %u\n", - // (uint32_t)u_vecs.a.n, k, mode, init, step, uId, endRid); - // fprintf(stderr, "nsu->start: %u, nsu->end: %u\n", - // nsu->start, nsu->end); - // if(mode == 1 && nsu->start != (endRid^1)) fprintf(stderr, "ERROR\n"); - // if(mode == 0 && nsu->end != (endRid^1)) fprintf(stderr, "ERROR\n"); - // update_unitig(step, init, nsu, r_g, &recover_edges, 0); - /********************for debug**********************/ - if(get_real_length(r_g, endRid, NULL) > 0) - { - update_unitig(step, init, nsu, r_g, &recover_edges, 1); - // fprintf(stderr, "endRid: %u, %.*s, uId: %u\n", - // endRid>>1, (int)Get_NAME_LENGTH((R_INF), v>>1), Get_NAME((R_INF), v>>1), uId); - } - else - { - update_unitig(step, init, nsu, r_g, &recover_edges, 0); - } - } - - uint64_t recov_occ = 0; - for (k = 0; k < recover_edges.a.n; k++) - { - if(recover_edges.a.a[k].del) continue; - p = asg_arc_pushp(r_g); - *p = recover_edges.a.a[k]; - recov_occ++; - } - - if(recov_occ != 0) - { - free(r_g->idx); - r_g->idx = 0; - r_g->is_srt = 0; - } - - asg_cleanup(r_g); - } - - if(is_primary_check) - { - for (k = 0; k < u_vecs.a.n; k++) - { - mode = (uint64_t)u_vecs.a.a[k]>>63; - if(mode == 1) step = 1; - if(mode == 0) step = -1; - init = (uint64_t)((uint64_t)u_vecs.a.a[k]>>32)&((uint64_t)(0x7fffffff)); - uId = (uint32_t)u_vecs.a.a[k]; - nsu = &(ug->u.a[uId]); - - endRid = ((uint64_t)(nsu->a[init]))>>32; - endRid = endRid^mode; - - update_unitig(step, init, nsu, r_g, &recover_edges, 1); - } - } - - - for (v = 0; v < ruIndex->len; v++) - { - get_R_to_U(ruIndex, v, &uId, &is_Unitig); - if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; - } - - if(i_ug == NULL) ma_ug_destroy(ug); - - kv_destroy(new_edges); - kv_destroy(recover_edges.a); - kv_destroy(rbub_edges); - kv_destroy(u_vecs.a); -} - - - - -void rescue_wrong_overlaps_to_unitigs(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -ma_sub_t *coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp, long long bubble_dist, -kvec_asg_arc_t_warp* keep_edges, bub_label_t* b_mask_t) -{ - uint32_t n_vtx, v, k, is_Unitig, uId, rId, endRid, oLen, w; - asg_t* nsg = NULL; - ma_utg_t* nsu = NULL; - ma_ug_t *ug = NULL; - asg_arc_t t, r_edge; - ma_hit_t_alloc* x = NULL; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - int32_t r; - - kvec_t(asg_arc_t) new_utg_edges; - kv_init(new_utg_edges); - - kvec_t(asg_arc_t) new_rtg_edges; - kv_init(new_rtg_edges); - - kvec_t(asg_arc_t) rbub_edges; - kv_init(rbub_edges); - - if(i_ug != NULL) - { - ug = i_ug; - } - else - { - ug = ma_ug_gen(r_g); - for (v = 0; v < ug->g->n_seq; v++) - { - ug->g->seq[v].c = PRIMARY_LABLE; - } - } - - nsg = ug->g; - - for (v = 0; v < nsg->n_seq; v++) - { - uId = v; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsg->seq[v].del) continue; - - for (k = 0; k < nsu->n; k++) - { - rId = nsu->a[k]>>33; - set_R_to_U(ruIndex, rId, uId, 1, &(r_g->seq[rId].c)); - } - } - - n_vtx = nsg->n_seq * 2; - for (v = 0; v < n_vtx; v++) - { - uId = v>>1; - if(nsg->seq[uId].del) continue; - - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsu->circ || nsu->start == UINT32_MAX || nsu->end == UINT32_MAX) continue; - if(get_real_length(nsg, v, NULL) != 0) continue; - - - - if(v&1) - { - endRid = nsu->start^1; - } - else - { - endRid = nsu->end^1; - } - - - - /****************************may have bugs********************************/ - x = &(sources[(endRid>>1)]); - for (k = 0; k < x->length; k++) - { - ///h is the edge of endRid - h = &(x->buffer[k]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - ///sq, st, and h cannot be deleted - if(sq->del || st->del || h->del) continue; - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - if(r < 0) continue; - if((t.ul>>32) != endRid) continue; - break; - } - ///means there is >0 edges - if(k != x->length) continue; - /****************************may have bugs********************************/ - - - - - k = 0; - rbub_edges.n = 0; - ///note here use reverse_sources instead of sources - while(get_edge2existing_node_advance(ug, r_g, reverse_sources, coverage_cut, ruIndex, - max_hang, min_ovlp, endRid, &uId, 1, &k, &r_edge, 1)) - { - kv_push(asg_arc_t, rbub_edges, r_edge); - } - - - - if(rbub_edges.n > 0) - { - ///need to do transitive reduction - ///note here is different to standard transitive reduction - minor_transitive_reduction(ug, ruIndex, rbub_edges.a, rbub_edges.n); - - for (k = 0; k < rbub_edges.n; k++) - { - t = rbub_edges.a[k]; - if(t.del) continue; - w = get_corresponding_uId(ug, ruIndex, t.v); - if(w == ((uint32_t)(-1))) continue; - ///if(uId == 2474) fprintf(stderr, "###uId: %u, v: %u, r_edge.v>>1: %u\n", uId, v, r_edge.v>>1); - kv_push(asg_arc_t, new_rtg_edges, t); - oLen = t.ol; - asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); - - - get_edge_from_source(reverse_sources, coverage_cut, ruIndex, max_hang, min_ovlp, - (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, new_rtg_edges, t); - ///if edge does not exist in reverse, oLen won't change, it is what we want - oLen = t.ol; - asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); - - t.ul = v; t.ul = t.ul<<32; t.v = w; - kv_push(asg_arc_t, new_utg_edges, t); - - - t.ul = w^1; t.ul = t.ul<<32; t.v = v^1; - kv_push(asg_arc_t, new_utg_edges, t); - } - } - - } - - - nsg->seq_vis = (uint8_t*)calloc(nsg->n_seq*2, sizeof(uint8_t)); - lable_all_bubbles(nsg, b_mask_t); - - /*********************************for debug**************************************/ - // uint32_t v_uId, w_uId; - // if(new_utg_edges.n != new_rtg_edges.n) fprintf(stderr, "ERROR 1\n"); - // for (k = 0; k < new_utg_edges.n; k++) - // { - // v = new_rtg_edges.a[k].ul>>32; - // v_uId = (get_corresponding_uId(ug, ruIndex, v^1)^1); - // w = new_rtg_edges.a[k].v; - // w_uId = get_corresponding_uId(ug, ruIndex, w); - - // v = new_utg_edges.a[k].ul>>32; - // w = new_utg_edges.a[k].v; - - // if(v!=v_uId || w!= w_uId) - // { - // fprintf(stderr, "\n(%u) ERROR 2\n", k); - // fprintf(stderr, "v>>1: %u, v&1: %u, ug->u.a[v>>1].n: %u\n", - // v>>1, v&1, ug->u.a[v>>1].n); - // fprintf(stderr, "ug->u.a[v>>1].start>>1: %u, ug->u.a[v>>1].start&1: %u\n", - // ug->u.a[v>>1].start>>1, ug->u.a[v>>1].start&1); - // fprintf(stderr, "ug->u.a[v>>1].end>>1: %u, ug->u.a[v>>1].end&1: %u\n", - // ug->u.a[v>>1].end>>1, ug->u.a[v>>1].end&1); - // fprintf(stderr, "w>>1: %u, w&1: %u, ug->u.a[w>>1].n: %u\n", - // w>>1, w&1, ug->u.a[w>>1].n); - // fprintf(stderr, "ug->u.a[w>>1].start>>1: %u, ug->u.a[w>>1].start&1: %u\n", - // ug->u.a[w>>1].start>>1, ug->u.a[w>>1].start&1); - // fprintf(stderr, "ug->u.a[w>>1].end>>1: %u, ug->u.a[w>>1].end&1: %u\n", - // ug->u.a[w>>1].end>>1, ug->u.a[w>>1].end&1); - // fprintf(stderr, "v_uId>>1: %u, v_uId&1: %u\n", v_uId>>1, v_uId&1); - // fprintf(stderr, "w_uId>>1: %u, w_uId&1: %u\n", w_uId>>1, w_uId&1); - // v = new_rtg_edges.a[k].ul>>32; - // w = new_rtg_edges.a[k].v; - // get_R_to_U(ruIndex, v>>1, &uId, &is_Unitig); - // fprintf(stderr, "v(read)>>1: %u, v(read)&1: %u, uId: %u, is_Unitig: %u\n", - // v>>1, v&1, uId, is_Unitig); - // get_R_to_U(ruIndex, w>>1, &uId, &is_Unitig); - // fprintf(stderr, "w(read)>>1: %u, w(read)&1: %u, uId: %u, is_Unitig: %u\n", - // w>>1, w&1, uId, is_Unitig); - - - // } - // } - /*********************************for debug**************************************/ - - for (k = 0; k < new_utg_edges.n; k++) - { - v = new_utg_edges.a[k].ul>>32; - w = new_utg_edges.a[k].v; - - if(nsg->seq[v>>1].del) continue; - if(nsg->seq[w>>1].del) continue; - ///if this edge is at a bubble - if(nsg->seq_vis[v]!=0 && nsg->seq_vis[w^1]!=0) - { - ///fprintf(stderr, "v>>1: %u, w>>1: %u\n", v>>1, w>>1); - continue; - } - - asg_arc_del(nsg, v, w, 1); - asg_arc_del(nsg, w^1, v^1, 1); - new_rtg_edges.a[k].del = 1; - } - asg_cleanup(nsg); - free(nsg->seq_vis); nsg->seq_vis = NULL; - - /*********************************for debug**************************************/ - asg_arc_t* p = NULL; - uint32_t e_occ = 0; - for (k = 0; k < new_rtg_edges.n; k++) - { - if(new_rtg_edges.a[k].del) continue; - p = asg_arc_pushp(r_g); - *p = new_rtg_edges.a[k]; - e_occ++; - if(keep_edges) kv_push(asg_arc_t, keep_edges->a, new_rtg_edges.a[k]); - } - - if(e_occ != 0) - { - free(r_g->idx); - r_g->idx = 0; - r_g->is_srt = 0; - asg_cleanup(r_g); - } - /*********************************for debug**************************************/ - - for (v = 0; v < ruIndex->len; v++) - { - get_R_to_U(ruIndex, v, &uId, &is_Unitig); - if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; - } - - if(i_ug == NULL) ma_ug_destroy(ug); - kv_destroy(new_utg_edges); - kv_destroy(new_rtg_edges); - kv_destroy(rbub_edges); -} - - - - -///find contained read with longest overlap -ma_hit_t* get_best_no_coverage_read(ma_ug_t *ug, asg_t *r_g, ma_hit_t_alloc* reverse_sources, -ma_sub_t *coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, -uint32_t init_contain_uId) -{ - uint32_t qn = query>>1; - int32_t r; - asg_arc_t t; - ma_hit_t *h = NULL, *return_h = NULL; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - ma_hit_t_alloc* x = &(reverse_sources[qn]); - uint32_t i, is_Unitig, contain_uId; - uint32_t maxOlen = 0; - asg_t* nsg = ug->g; - - - //scan all edges of qn - for (i = 0; i < x->length; i++) - { - h = &(x->buffer[i]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - - ///all of them cannot be removed - if(sq->del || st->del || h->del) continue; - if(r_g->seq[Get_qn(*h)].del || r_g->seq[Get_tn(*h)].del) continue; - - get_R_to_U(ruIndex, Get_tn(*h), &contain_uId, &is_Unitig); - if(contain_uId == (uint32_t)-1 || is_Unitig != 1) continue; - if(nsg->seq[contain_uId].del) continue; - ///contain_uId must be a unitig - - if(init_contain_uId != contain_uId) continue; - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - - ///if it is a contained read, skip - if(r < 0) continue; - - if((t.ul>>32) != query) continue; - - if(t.ol > maxOlen) - { - maxOlen = t.ol; - return_h = h; - } - } - - return return_h; -} - - - - - -int get_no_coverage_reads_chain_simple(ma_hit_t *h, ma_hit_t_alloc* sources, -ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, ma_ug_t *ug, -asg_t *r_g, int max_hang, int min_ovlp, uint32_t endRid, uint32_t uId, -kvec_t_u32_warp* chain_buffer, kvec_asg_arc_t_warp* chain_edges, uint32_t* return_ava_cur, -uint32_t* return_ava_ol, uint32_t* return_chainLen, uint32_t thresLen) -{ - (*return_chainLen) = (*return_ava_cur) = (*return_ava_ol) = (uint32_t)-1; - uint32_t init_contain_uId = (uint32_t)-1, contain_uId, is_Unitig; - uint32_t chainLen = 0, ava_cur, test_oLen; - int ql, tl; - int32_t r; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - asg_arc_t t; - asg_t* nsg = ug->g; - chain_buffer->a.n = 0; - kv_push(uint32_t, chain_buffer->a, uId); - if(chain_edges) chain_edges->a.n = 0; - - if(!h) return 0; - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - ///sq and st cannot be deleted - ///for h, deleted or not does not matter - if(sq->del || st->del) return 0; - if(r_g->seq[Get_qn(*h)].del || r_g->seq[Get_tn(*h)].del) return 0; - get_R_to_U(ruIndex, Get_tn(*h), &contain_uId, &is_Unitig); - if(contain_uId == (uint32_t)-1 || is_Unitig != 1) return 0; - if(nsg->seq[contain_uId].del) return 0; - ql = sq->e - sq->s; tl = st->e - st->s; - r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - if(r < 0) return 0; - if((t.ul>>32) != endRid) return 0; - if(chain_edges) kv_push(asg_arc_t, chain_edges->a, t); - chainLen++; - kv_push(uint32_t, chain_buffer->a, contain_uId); - ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, reverse_sources, coverage_cut, - ruIndex, max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, 1); - //means find an aim - if(ava_cur > 0) - { - (*return_ava_cur) = ava_cur; - (*return_ava_ol) = test_oLen; - (*return_chainLen) = chainLen; - h = NULL; - return 1; - } - else - { - return 0; - } - - - ///continue - ///need to update h, endRid, chainLen, chain_buffer and chain_edges - while (h) - { - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - - ///sq, st, and h cannot be deleted - if(sq->del || st->del || h->del) break; - if(r_g->seq[Get_qn(*h)].del || r_g->seq[Get_tn(*h)].del) break; - - get_R_to_U(ruIndex, Get_tn(*h), &contain_uId, &is_Unitig); - if(contain_uId == (uint32_t)-1 || is_Unitig != 1) break; - if(nsg->seq[contain_uId].del) break; - ///contain_uId must be a unitig - - if(init_contain_uId != (uint32_t)-1) - { - init_contain_uId = contain_uId; - } - else - { - if(init_contain_uId != contain_uId) break; - } - - - ql = sq->e - sq->s; tl = st->e - st->s; - r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - - ///if st is contained in sq, or vice verse, skip - if(r < 0) break; - - ///if sq and v are not in the same direction, skip - ///endRid is (t.ul>>32), and t.v is a contained read - if((t.ul>>32) != endRid) break; - - if(chain_edges) kv_push(asg_arc_t, chain_edges->a, t); - chainLen++; - kv_push(uint32_t, chain_buffer->a, contain_uId); - ///endRid is (t.ul>>32), and t.v is a contained read - ///find edges from t.v to existing unitigs - ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, reverse_sources, coverage_cut, - ruIndex, max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, 1); - //means find an aim - if(ava_cur > 0) - { - /** - //do nothing if the chainLen == 1 - if(chainLen > 1) - { - asg_arc_t t_max; - ma_hit_t_alloc* x = &(sources[(endRid>>1)]); - uint32_t ava_ol_max = 0, ava_max = 0, k; - for (k = 0; k < x->length; k++) - { - h = &(x->buffer[k]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - trio_flag = R_INF.trio_flag[Get_qn(*h)]; - - ///don't want to edges between different haps - non_trio_flag = (uint32_t)-1; - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; - - ///just need deleted edges - ///sq might be deleted or not - if(!st->del) continue; - if(!h->del) continue; - - ///tn must be contained in another existing read - get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); - if(contain_rId == (uint32_t)-1 || is_Unitig == 1) continue; - if(r_g->seq[contain_rId].del) continue; - - get_R_to_U(ruIndex, contain_rId, &contain_uId, &is_Unitig); - if(contain_uId == (uint32_t)-1 || is_Unitig != 1) continue; - if(nsg->seq[contain_uId].del) continue; - ///contain_uId must be a unitig - - ql = sq->e - sq->s; tl = st->e - st->s; - r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - - ///if st is contained in sq, or vice verse, skip - if(r < 0) continue; - - ///if sq and v are not in the same direction, skip - if((t.ul>>32) != endRid) continue; - - ///pop the last contain_uId - chain_buffer->a.n--; - kv_push(uint32_t, chain_buffer->a, contain_uId); - - ///note: t.v is a contained read - ///we need to find existing reads linked with w - ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, sources, coverage_cut, ruIndex, - max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, 1); - - if((ava_cur > ava_max) || (ava_cur == ava_max && test_oLen > ava_ol_max)) - { - ava_max = ava_cur; - ava_ol_max = test_oLen; - t_max = t; - } - } - - if(ava_max > 0) - { - ava_cur = ava_max; - test_oLen = ava_ol_max; - if(chain_edges) - { - //pop the last edge - chain_edges->a.n--; - kv_push(asg_arc_t, chain_edges->a, t_max); - } - } - else - { - break; - } - } - **/ - - (*return_ava_cur) = ava_cur; - (*return_ava_ol) = test_oLen; - (*return_chainLen) = chainLen; - h = NULL; - return 1; - } - - if(chainLen >= thresLen) break; - - ///endRid is (t.ul>>32), and t.v is a contained read - ///haven't found a existing unitig from t.v - ///check if t.v can link to a new contained read - endRid = t.v; - h = get_best_no_coverage_read(ug, r_g, reverse_sources, coverage_cut, ruIndex, - max_hang, min_ovlp, endRid, init_contain_uId); - } - - return 0; -} - - -int get_no_coverage_reads_chain(ma_hit_t *h, ma_hit_t_alloc* sources, -ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, ma_ug_t *ug, -asg_t *r_g, int max_hang, int min_ovlp, uint32_t endRid, uint32_t uId, -kvec_t_u32_warp* chain_buffer, kvec_asg_arc_t_warp* chain_edges, uint32_t* return_ava_cur, -uint32_t* return_ava_ol, uint32_t* return_chainLen, uint32_t thresLen) -{ - (*return_chainLen) = (*return_ava_cur) = (*return_ava_ol) = (uint32_t)-1; - uint32_t init_contain_uId = (uint32_t)-1, contain_uId, is_Unitig; - uint32_t chainLen = 0, ava_cur, test_oLen; - int ql, tl; - int32_t r; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - asg_arc_t t; - asg_t* nsg = ug->g; - chain_buffer->a.n = 0; - kv_push(uint32_t, chain_buffer->a, uId); - if(chain_edges) chain_edges->a.n = 0; - - if(!h) return 0; - - while(h) - { - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - ///sq and st cannot be deleted - ///for h, deleted or not does not matter - if(sq->del || st->del) return 0; - if(r_g->seq[Get_qn(*h)].del || r_g->seq[Get_tn(*h)].del) return 0; - get_R_to_U(ruIndex, Get_tn(*h), &contain_uId, &is_Unitig); - if(contain_uId == (uint32_t)-1 || is_Unitig != 1) return 0; - if(nsg->seq[contain_uId].del) return 0; - ql = sq->e - sq->s; tl = st->e - st->s; - r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - if(r < 0) return 0; - if((t.ul>>32) != endRid) return 0; - if(chain_edges) kv_push(asg_arc_t, chain_edges->a, t); - chainLen++; - kv_push(uint32_t, chain_buffer->a, contain_uId); - ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, reverse_sources, coverage_cut, - ruIndex, max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, 1); - //means find an aim - if(ava_cur > 0) - { - (*return_ava_cur) = ava_cur; - (*return_ava_ol) = test_oLen; - (*return_chainLen) = chainLen; - h = NULL; - return 1; - } - - - if(chainLen >= thresLen) break; - - ///endRid is (t.ul>>32), and t.v is a contained read - ///haven't found a existing unitig from t.v - ///check if t.v can link to a new contained read - endRid = t.v; - h = get_best_no_coverage_read(ug, r_g, sources, coverage_cut, ruIndex, - max_hang, min_ovlp, endRid, init_contain_uId); - } - - - - ///continue - ///need to update h, endRid, chainLen, chain_buffer and chain_edges - while (h) - { - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - - ///sq, st, and h cannot be deleted - if(sq->del || st->del || h->del) break; - if(r_g->seq[Get_qn(*h)].del || r_g->seq[Get_tn(*h)].del) break; - - get_R_to_U(ruIndex, Get_tn(*h), &contain_uId, &is_Unitig); - if(contain_uId == (uint32_t)-1 || is_Unitig != 1) break; - if(nsg->seq[contain_uId].del) break; - ///contain_uId must be a unitig - - if(init_contain_uId != (uint32_t)-1) - { - init_contain_uId = contain_uId; - } - else - { - if(init_contain_uId != contain_uId) break; - } - - - ql = sq->e - sq->s; tl = st->e - st->s; - r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - - ///if st is contained in sq, or vice verse, skip - if(r < 0) break; - - ///if sq and v are not in the same direction, skip - ///endRid is (t.ul>>32), and t.v is a contained read - if((t.ul>>32) != endRid) break; - - if(chain_edges) kv_push(asg_arc_t, chain_edges->a, t); - chainLen++; - kv_push(uint32_t, chain_buffer->a, contain_uId); - ///endRid is (t.ul>>32), and t.v is a contained read - ///find edges from t.v to existing unitigs - ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, reverse_sources, coverage_cut, - ruIndex, max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, 1); - //means find an aim - if(ava_cur > 0) - { - /** - //do nothing if the chainLen == 1 - if(chainLen > 1) - { - asg_arc_t t_max; - ma_hit_t_alloc* x = &(sources[(endRid>>1)]); - uint32_t ava_ol_max = 0, ava_max = 0, k; - for (k = 0; k < x->length; k++) - { - h = &(x->buffer[k]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - trio_flag = R_INF.trio_flag[Get_qn(*h)]; - - ///don't want to edges between different haps - non_trio_flag = (uint32_t)-1; - if(trio_flag == FATHER) non_trio_flag = MOTHER; - if(trio_flag == MOTHER) non_trio_flag = FATHER; - if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; - - ///just need deleted edges - ///sq might be deleted or not - if(!st->del) continue; - if(!h->del) continue; - - ///tn must be contained in another existing read - get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); - if(contain_rId == (uint32_t)-1 || is_Unitig == 1) continue; - if(r_g->seq[contain_rId].del) continue; - - get_R_to_U(ruIndex, contain_rId, &contain_uId, &is_Unitig); - if(contain_uId == (uint32_t)-1 || is_Unitig != 1) continue; - if(nsg->seq[contain_uId].del) continue; - ///contain_uId must be a unitig - - ql = sq->e - sq->s; tl = st->e - st->s; - r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - - ///if st is contained in sq, or vice verse, skip - if(r < 0) continue; - - ///if sq and v are not in the same direction, skip - if((t.ul>>32) != endRid) continue; - - ///pop the last contain_uId - chain_buffer->a.n--; - kv_push(uint32_t, chain_buffer->a, contain_uId); - - ///note: t.v is a contained read - ///we need to find existing reads linked with w - ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, sources, coverage_cut, ruIndex, - max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, 1); - - if((ava_cur > ava_max) || (ava_cur == ava_max && test_oLen > ava_ol_max)) - { - ava_max = ava_cur; - ava_ol_max = test_oLen; - t_max = t; - } - } - - if(ava_max > 0) - { - ava_cur = ava_max; - test_oLen = ava_ol_max; - if(chain_edges) - { - //pop the last edge - chain_edges->a.n--; - kv_push(asg_arc_t, chain_edges->a, t_max); - } - } - else - { - break; - } - } - **/ - - (*return_ava_cur) = ava_cur; - (*return_ava_ol) = test_oLen; - (*return_chainLen) = chainLen; - h = NULL; - return 1; - } - - if(chainLen >= thresLen) break; - - ///endRid is (t.ul>>32), and t.v is a contained read - ///haven't found a existing unitig from t.v - ///check if t.v can link to a new contained read - endRid = t.v; - h = get_best_no_coverage_read(ug, r_g, reverse_sources, coverage_cut, ruIndex, - max_hang, min_ovlp, endRid, init_contain_uId); - } - - return 0; -} - - -uint32_t check_if_no_coverage(asg_t *r_g, asg_arc_t* list, uint32_t list_n) -{ - if(list_n < 2) return 0; - uint32_t i, v, w, u_n = list_n - 1, nv, l, k; - long long totalLen = 0; - asg_arc_t *av = NULL; - for (i = 0; i < u_n - 1; i++) - { - v = list[i].v; - w = list[i+1].v; - av = asg_arc_a(r_g, v); - nv = asg_arc_n(r_g, v); - l = 0; - - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - l = asg_arc_len(av[k]); - break; - } - } - - if(k == nv) fprintf(stderr, "####ERROR\n"); - totalLen += l; - } - - if(i < u_n) - { - v = list[i].v; - l = r_g->seq[v>>1].len; - totalLen += l; - } - - if(totalLen > list[0].ol + list[list_n - 1].ol) return 1; - - return 0; -} - -uint32_t create_fake_read(asg_t *r_g, asg_arc_t* list, uint32_t list_n) -{ - if(list_n < 2) return 0; - ma_utg_t* u = NULL; - uint32_t v, w, l, i, k, nv, totalLen = 0; - asg_arc_t *av = NULL; - u = asg_F_seq_set(r_g, r_g->n_seq); - if(u == NULL) return 0; - u->n = u->m = list_n - 1; - if(u->a) free(u->a); - u->a = (uint64_t*)malloc(sizeof(uint64_t)*u->n); - - /*****************for debug**********************/ - // fprintf(stderr, "list_n: %u\n", list_n); - // for (i = 0; i < list_n; i++) - // { - // fprintf(stderr, "(%u) v: %u, dir: %u, w: %u, w&1: %u, len: %u, ol: %u\n", - // i, (uint32_t)(list[i].ul>>33), (uint32_t)((list[i].ul>>32)&1), - // list[i].v>>1, list[i].v&1, (uint32_t)list[i].ul, list[i].ol); - // } - /*****************for debug**********************/ - - - for (i = 0; i < u->n; i++) - { - u->a[i] = list[i].v; - u->a[i] = u->a[i] << 32; - } - - /*****************for debug**********************/ - // fprintf(stderr, "u->n: %u\n", u->n); - // for (i = 0; i < u->n; i++) - // { - // fprintf(stderr, "(%u) v: %u, dir: %u\n", - // i, (uint32_t)(u->a[i]>>33), (uint32_t)((u->a[i]>>32)&1)); - // } - /*****************for debug**********************/ - - - for (i = 0; i < u->n - 1; i++) - { - v = (uint64_t)(u->a[i])>>32; - w = (uint64_t)(u->a[i + 1])>>32; - av = asg_arc_a(r_g, v); - nv = asg_arc_n(r_g, v); - l = 0; - - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - l = asg_arc_len(av[k]); - break; - } - } - - if(k == nv) fprintf(stderr, "####ERROR\n"); - u->a[i] = v; u->a[i] = u->a[i]<<32; u->a[i] = u->a[i] | (uint64_t)(l); - totalLen += l; - } - - if(i < u->n) - { - v = (uint64_t)(u->a[i])>>32; - l = r_g->seq[v>>1].len; - u->a[i] = v; - u->a[i] = u->a[i]<<32; - u->a[i] = u->a[i] | (uint64_t)(l); - totalLen += l; - } - - /*****************for debug**********************/ - // fprintf(stderr, "u->n: %u\n", u->n); - // for (i = 0; i < u->n; i++) - // { - // fprintf(stderr, "(%u) v: %u, dir: %u, len: %u\n", - // i, (uint32_t)(u->a[i]>>33), (uint32_t)((u->a[i]>>32)&1), (uint32_t)(u->a[i])); - // } - /*****************for debug**********************/ - - - - u->len = totalLen; - u->circ = 0; - u->start = list[0].ol; - u->end = u->len - list[list_n - 1].ol; - totalLen = u->len - list[0].ol - list[list_n - 1].ol; - ///u->len = totalLen; - - /*****************for debug**********************/ - // fprintf(stderr, "u->len: %u, u->start: %u, u->end: %u\n", u->len, u->start, u->end); - // fprintf(stderr, "totalLen: %u, list[0].ol: %u, list[list_n - 1].ol: %u\n", - // totalLen, list[0].ol, list[list_n - 1].ol); - /*****************for debug**********************/ - - /*****************for debug**********************/ - /** - (*coverage_cut) = (ma_sub_t*)realloc((*coverage_cut), (r_g->n_seq+1)*sizeof(ma_sub_t)); - (*coverage_cut)[r_g->n_seq].del = 0; - (*coverage_cut)[r_g->n_seq].c = PRIMARY_LABLE; - (*coverage_cut)[r_g->n_seq].s = 0; - (*coverage_cut)[r_g->n_seq].e = totalLen; - **/ - asg_seq_set(r_g, r_g->n_seq, totalLen, 0); - /*****************for debug**********************/ - return 1; -} - - -inline void generate_edge(asg_t *r_g, uint32_t v, uint32_t w, uint32_t ol, uint32_t del, -uint32_t strong, uint32_t el, uint32_t no_l_indel, asg_arc_t* t) -{ - uint64_t l = r_g->seq[v>>1].len - ol; - t->ul = v; t->ul = t->ul << 32; t->ul = t->ul|l; - t->v = w; - t->ol = ol; - t->del = del; - t->strong = strong; - t->el = el; - t->no_l_indel = no_l_indel; -} -///chainLenThres is used to avoid circle -void rescue_no_coverage_aggressive(asg_t *r_g, ma_hit_t_alloc* sources_count, -ma_hit_t_alloc* reverse_source, ma_sub_t **coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp, -long long bubble_dist, uint32_t chainLenThres, bub_label_t* b_mask_t) -{ - uint32_t n_vtx, v, k, kv, is_Unitig, uId, rId, endRid, w; - uint32_t ava_max, ava_ol_max, ava_min_chain, ava_cur, ava_chainLen, test_oLen, is_update; - uint64_t interval_beg, intervalLen; - asg_t* nsg = NULL; - ma_utg_t* nsu = NULL; - asg_arc_t t, t_max, r_edge; - t_max.v = t_max.ul = t.v = t.ul = (uint32_t)-1; - ma_hit_t *h = NULL, *h_max = NULL; - ma_hit_t_alloc* x = NULL; - ma_ug_t* ug = NULL; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - int32_t r; - - kvec_t(asg_arc_t) new_utg_edges; - kv_init(new_utg_edges); - - kvec_t(asg_arc_t) new_rtg_edges; - kv_init(new_rtg_edges); - - kvec_t(asg_arc_t) hap_edges; - kv_init(hap_edges); - - kvec_t(asg_arc_t) rbub_edges; - kv_init(rbub_edges); - - kvec_t_u64_warp u_vecs; - kv_init(u_vecs.a); - - kvec_t_u64_warp intervals; - kv_init(intervals.a); - - kvec_t_u32_warp chain_buffer; - kv_init(chain_buffer.a); - - kvec_asg_arc_t_warp chain_edges; - kv_init(chain_edges.a); - - - ug = ma_ug_gen(r_g); - nsg = ug->g; - - for (v = 0; v < nsg->n_seq; v++) - { - uId = v; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsg->seq[v].del) continue; - nsg->seq[v].c = PRIMARY_LABLE; - for (k = 0; k < nsu->n; k++) - { - rId = nsu->a[k]>>33; - set_R_to_U(ruIndex, rId, uId, 1, &(r_g->seq[rId].c)); - } - } - - - - - n_vtx = nsg->n_seq * 2; - for (v = 0; v < n_vtx; v++) - { - uId = v>>1; - if(nsg->seq[uId].del) continue; - nsu = &(ug->u.a[uId]); - if(nsu->m == 0) continue; - if(nsu->circ || nsu->start == UINT32_MAX || nsu->end == UINT32_MAX) continue; - if(get_real_length(nsg, v, NULL) != 0) continue; - ///we probably don't need this line - ///if(get_real_length(nsg, v^1, NULL) == 0) continue; - if(v&1) - { - endRid = nsu->start^1; - } - else - { - endRid = nsu->end^1; - } - - - x = &(sources_count[(endRid>>1)]); - for (k = 0; k < x->length; k++) - { - ///h is the edge of endRid - h = &(x->buffer[k]); - sq = &((*coverage_cut)[Get_qn(*h)]); - st = &((*coverage_cut)[Get_tn(*h)]); - ///sq, st, and h cannot be deleted - if(sq->del || st->del || h->del) continue; - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - if(r < 0) continue; - if((t.ul>>32) != endRid) continue; - break; - } - ///means there is >0 edges - if(k != x->length) continue; - - ///x is the end read of a tip - ///find all overlap of x - x = &(reverse_source[(endRid>>1)]); - ava_ol_max = ava_max = 0; ava_min_chain = (uint32_t)-1; - h_max = NULL; - for (k = 0; k < x->length; k++) - { - h = &(x->buffer[k]); - ///means we found a contained read - if(get_no_coverage_reads_chain_simple(h, sources_count, reverse_source, *coverage_cut, - ruIndex, ug, r_g, max_hang, min_ovlp, endRid, uId, &chain_buffer, NULL, &ava_cur, - &test_oLen, &ava_chainLen, chainLenThres)) - { - - is_update = 0; - if(ava_chainLen < ava_min_chain) - { - is_update = 1; - } - else if(ava_chainLen == ava_min_chain) - { - if(ava_cur > ava_max) - { - is_update = 1; - } - else if(ava_cur == ava_max && test_oLen > ava_ol_max) - { - is_update = 1; - } - } - if(is_update) - { - ava_min_chain = ava_chainLen; - ava_max = ava_cur; - ava_ol_max = test_oLen; - h_max = h; - } - } - } - - - - - - if(ava_max > 0) - { - - //get all edges between contained reads - get_no_coverage_reads_chain_simple(h_max, sources_count, reverse_source, - *coverage_cut, ruIndex, ug, r_g, max_hang, min_ovlp, endRid, uId, &chain_buffer, - &chain_edges, &ava_cur, &test_oLen, &ava_chainLen, chainLenThres); - if(chain_edges.a.n < 1) continue; - ///the last cantained read - t_max = chain_edges.a.a[chain_edges.a.n-1]; - - k = 0; rbub_edges.n = 0; - ///edges from the last contained read to other unitigs - while(get_edge2existing_node_advance(ug, r_g, reverse_source, *coverage_cut, ruIndex, - max_hang, min_ovlp, t_max.v, chain_buffer.a.a, chain_buffer.a.n, &k, &r_edge, 1)) - { - kv_push(asg_arc_t, rbub_edges, r_edge); - } - - ///need to do transitive reduction - ///note here is different to standard transitive reduction - minor_transitive_reduction(ug, ruIndex, rbub_edges.a, rbub_edges.n); - - for (k = 0, kv = 0; k < rbub_edges.n; k++) - { - t = rbub_edges.a[k]; - if(t.del) continue; - kv++; - } - - if(kv != 1) continue; - - interval_beg = hap_edges.n; - - //just saves all nodes here - ///note that only the first edge is generated from reverse_source, - ///others are generated from source - for (k = 0; k < chain_edges.a.n; k++) - { - kv_push(asg_arc_t, hap_edges, chain_edges.a.a[k]); - } - - for (k = 0; k < rbub_edges.n; k++) - { - t = rbub_edges.a[k]; - if(t.del) continue; - kv_push(asg_arc_t, hap_edges, t); - } - - - if(check_if_no_coverage(r_g, hap_edges.a+interval_beg, hap_edges.n - interval_beg) == 0) - { - hap_edges.n = interval_beg; - continue; - } - - ///there is just one edge - ///connect multiple edges is too difficult - for (k = 0; k < rbub_edges.n; k++) - { - t = rbub_edges.a[k]; - if(t.del) continue; - - w = get_corresponding_uId(ug, ruIndex, t.v); - if(w == ((uint32_t)(-1))) continue; - kv_push(asg_arc_t, new_rtg_edges, t); - - get_edge_from_source(reverse_source, *coverage_cut, ruIndex, max_hang, min_ovlp, - (t.v^1), ((t.ul>>32)^1), &t); - kv_push(asg_arc_t, new_rtg_edges, t); - - - ///for unitig graph - asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, 0, 0, 0, 0); - asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, 0, 0, 0, 0); - - t.ul = v; t.ul = t.ul<<32; t.v = w; - kv_push(asg_arc_t, new_utg_edges, t); - - t.ul = w^1; t.ul = t.ul<<32; t.v = v^1; - kv_push(asg_arc_t, new_utg_edges, t); - - } - - kv_push(uint64_t, u_vecs.a, v); - - intervalLen = hap_edges.n - interval_beg; - interval_beg = interval_beg << 32; - interval_beg = interval_beg | intervalLen; - kv_push(uint64_t, intervals.a, interval_beg); - } - } - - nsg->seq_vis = (uint8_t*)calloc(nsg->n_seq*2, sizeof(uint8_t)); - lable_all_bubbles(nsg, b_mask_t); - - - for (k = 0; k < new_utg_edges.n; k++) - { - v = new_utg_edges.a[k].ul>>32; - w = new_utg_edges.a[k].v; - - if(nsg->seq[v>>1].del) continue; - if(nsg->seq[w>>1].del) continue; - ///if this edge is at a bubble - if(nsg->seq_vis[v]!=0 && nsg->seq_vis[w^1]!=0) - { - continue; - } - - asg_arc_del(nsg, v, w, 1); - asg_arc_del(nsg, w^1, v^1, 1); - new_rtg_edges.a[k].del = 1; - } - free(nsg->seq_vis); nsg->seq_vis = NULL; - - - new_utg_edges.n = 0; - asg_arc_t* list = NULL; - uint32_t nextNode, curNode, pre_num_nodes = r_g->n_seq; - ///u_vecs saves the unitig Id - for (k = 0; k < u_vecs.a.n; k++) - { - w = (uint32_t)u_vecs.a.a[k]; - ///do nothing - if(get_real_length(r_g, w, NULL) == 0) continue; - - interval_beg = intervals.a.a[k]>>32; - intervalLen = intervals.a.a[k] & ((uint64_t)0xffffffff); - list = hap_edges.a + interval_beg; - if(intervalLen < 2) continue;///fprintf(stderr, "No enough edges\n"); - fprintf(stderr, "\n(%u) w>>1: %u, w&1: %u\n", k, w>>1, w&1); - ///continue; - - - if(create_fake_read(r_g, list, intervalLen) == 0) continue; - - - curNode = list[0].ul>>32; - nextNode = (r_g->n_seq - 1)<<1; - /*****************for debug**********************/ - generate_edge(r_g, curNode, nextNode, 0, 0, 0, 0, 0, &t); - kv_push(asg_arc_t, new_utg_edges, t); - - generate_edge(r_g, nextNode^1, curNode^1, 0, 0, 0, 0, 0, &t); - kv_push(asg_arc_t, new_utg_edges, t); - /*****************for debug**********************/ - // fprintf(stderr, "curNode>>1: %u, curNode&1: %u, nextNode>>1: %u, nextNode&1: %u\n", - // curNode>>1, curNode&1, nextNode>>1, nextNode&1); - - - curNode = (r_g->n_seq - 1)<<1; - nextNode = list[intervalLen - 1].v; - /*****************for debug**********************/ - generate_edge(r_g, curNode, nextNode, 0, 0, 0, 0, 0, &t); - kv_push(asg_arc_t, new_utg_edges, t); - - generate_edge(r_g, nextNode^1, curNode^1, 0, 0, 0, 0, 0, &t); - kv_push(asg_arc_t, new_utg_edges, t); - /*****************for debug**********************/ - // fprintf(stderr, "curNode>>1: %u, curNode&1: %u, nextNode>>1: %u, nextNode&1: %u\n", - // curNode>>1, curNode&1, nextNode>>1, nextNode&1); - } - - - - - asg_arc_t* p = NULL; - for (k = 0; k < new_utg_edges.n; k++) - { - p = asg_arc_pushp(r_g); - *p = new_utg_edges.a[k]; - } - - - free(r_g->idx); - r_g->idx = 0; - r_g->is_srt = 0; - asg_cleanup(r_g); - - if(r_g->n_seq > pre_num_nodes) - { - (*coverage_cut) = (ma_sub_t*)realloc((*coverage_cut), r_g->n_seq*sizeof(ma_sub_t)); - R_INF.trio_flag = (uint8_t*)realloc(R_INF.trio_flag, r_g->n_seq*sizeof(uint8_t)); - ruIndex->index = (uint32_t*)realloc(ruIndex->index, r_g->n_seq*sizeof(uint32_t)); - ruIndex->len = r_g->n_seq; - for (k = pre_num_nodes; k < r_g->n_seq; k++) - { - ruIndex->index[k] = (uint32_t)-1; - R_INF.trio_flag[k] = AMBIGU; - (*coverage_cut)[k].del = 0; - (*coverage_cut)[k].c = PRIMARY_LABLE; - (*coverage_cut)[k].s = 0; - (*coverage_cut)[k].e = r_g->seq[k].len; - } - } - - - for (v = 0; v < ruIndex->len; v++) - { - get_R_to_U(ruIndex, v, &uId, &is_Unitig); - if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; - } - - - ma_ug_destroy(ug); - kv_destroy(new_utg_edges); - kv_destroy(hap_edges); - kv_destroy(new_rtg_edges); - kv_destroy(rbub_edges); - kv_destroy(u_vecs.a); - kv_destroy(chain_buffer.a); - kv_destroy(chain_edges.a); - kv_destroy(intervals.a); -} - - -void fix_binned_reads(ma_hit_t_alloc* paf, uint64_t n_read, ma_sub_t* coverage_cut) -{ - double startTime = Get_T(); - uint64_t i, binned_flag, binned_reads = 0, binned_error_reads = 0, reduce = 1; - ma_sub_t max_left, max_right; - while (reduce != 0) - { - reduce = 0; - binned_reads = 0; - for (i = 0; i < n_read; ++i) - { - if(coverage_cut[i].del) continue; - binned_flag = R_INF.trio_flag[i]; - if(binned_flag == AMBIGU) continue; - binned_reads++; - max_left.s = max_right.s = Get_READ_LENGTH(R_INF,i); - max_left.e = max_right.e = 0; - collect_sides_trio(&(paf[i]), Get_READ_LENGTH(R_INF,i), &max_left, &max_right, binned_flag); - collect_contain_trio(&(paf[i]), NULL, Get_READ_LENGTH(R_INF,i), &max_left, &max_right, 0.1, - binned_flag); - if(max_left.e > max_right.s) - { - R_INF.trio_flag[i] = AMBIGU; - binned_error_reads++; - reduce++; - binned_reads--; - } - /** - if(max_left.e > max_right.s) - { - fprintf(stderr, "\ni: %lu, reference: %.*s, len: %lu, %c\n", - i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i), - Get_READ_LENGTH(R_INF, i), "apmaaa"[binned_flag]); - - for (uint64_t j = 0; j < paf[i].length; j++) - { - if(R_INF.trio_flag[Get_tn(paf[i].buffer[j])] == binned_flag) - { - fprintf(stderr, "###Compatible, "); - } - else - { - fprintf(stderr, "***Conflict, "); - } - - fprintf(stderr, "%c, qs: %u, qe: %u, ts: %u, te: %u, len: %lu, %.*s\n", - "apmaaa"[R_INF.trio_flag[Get_tn(paf[i].buffer[j])]], - Get_qs(paf[i].buffer[j]), - Get_qe(paf[i].buffer[j]), - Get_ts(paf[i].buffer[j]), - Get_te(paf[i].buffer[j]), - Get_READ_LENGTH(R_INF, Get_tn(paf[i].buffer[j])), - (int)Get_NAME_LENGTH(R_INF, Get_tn(paf[i].buffer[j])), - Get_NAME(R_INF, Get_tn(paf[i].buffer[j]))); - } - } - **/ - } - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - fprintf(stderr, "n_read: %lu, binned_reads: %lu, binned_error_reads: %lu\n", - (unsigned long)n_read, (unsigned long)binned_reads, (unsigned long)binned_error_reads); -} - - -void print_binned_reads(ma_hit_t_alloc* paf, uint64_t n_read, ma_sub_t* coverage_cut) -{ - uint64_t i, j, binned_flag; - - for (i = 0; i < n_read; ++i) - { - if(coverage_cut!=NULL && coverage_cut[i].del) continue; - binned_flag = R_INF.trio_flag[i]; - fprintf(stdout, "\n***i: %u, binned_flag: %u\n", (uint32_t)i, (uint32_t)binned_flag); - if(coverage_cut!=NULL) - { - fprintf(stdout, "coverage_cut[i].c: %u, coverage_cut[i].s: %u, coverage_cut[i].e: %u, coverage_cut[i].e: %u\n", - coverage_cut[i].c, coverage_cut[i].s, coverage_cut[i].e, coverage_cut[i].del); - } - for (j = 0; j < paf[i].length; j++) - { - if(paf[i].buffer[j].del) continue; - ///fprintf(stdout, "j: %u\n", (uint32_t)j); - fprintf(stdout, "qn: %u, qs: %u, qe: %u, tn: %u, ts: %u, te: %u\n", - (uint32_t)Get_qn(paf[i].buffer[j]), (uint32_t)Get_qs(paf[i].buffer[j]), (uint32_t)Get_qe(paf[i].buffer[j]), - (uint32_t)Get_tn(paf[i].buffer[j]), (uint32_t)Get_ts(paf[i].buffer[j]), (uint32_t)Get_te(paf[i].buffer[j])); - } - } -} - - - -void debug_ma_hit_t(ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, long long num_sources, -int max_hang, int min_ovlp) -{ - double startTime = Get_T(); - - long long i, j, index; - uint32_t qn, tn; - ma_sub_t *sq = NULL; - ma_sub_t *st = NULL; - ma_hit_t *h = NULL; - int32_t r_0, r_1; - asg_arc_t t_0, t_1; - fprintf(stderr, "start!\n"); - - for (i = 0; i < num_sources; i++) - { - - for (j = 0; j < sources[i].length; j++) - { - qn = Get_qn(sources[i].buffer[j]); - tn = Get_tn(sources[i].buffer[j]); - - - ///if(sources[i].buffer[j].del) continue; - - index = get_specific_overlap(&(sources[tn]), tn, qn); - if(index == -1) - { - fprintf(stderr, "ERROR 0: qn: %u, tn: %u\n", qn, tn); - continue; - } - - - - if(sources[i].buffer[j].del != sources[tn].buffer[index].del) - { - fprintf(stderr, "ERROR 2: qn: %u, tn: %u\n", qn, tn); - } - - h = &(sources[i].buffer[j]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - r_0 = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t_0); - - - h = &(sources[tn].buffer[index]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - r_1 = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t_1); - t_0.ul=t_0.v=t_1.ul=t_1.v = 0; - if(r_0 < 0 && r_1 < 0) continue; - if((t_0.ul>>32) != (t_1.v^1)) fprintf(stderr, "ERROR 3: qn: %u, tn: %u\n", qn, tn); - if((t_1.ul>>32) != (t_0.v^1)) fprintf(stderr, "ERROR 4: qn: %u, tn: %u\n", qn, tn); - } - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] takes %0.2fs\n\n", __func__, Get_T()-startTime); - } -} - -void set_hom_global_coverage(hifiasm_opt_t *opt, asg_t *sg, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, int max_hang, int min_ovlp) -{ - if(opt->hom_global_coverage_set == 0) - { - ma_ug_t *ug = NULL; - ug = ma_ug_gen(sg); - - hap_cov_t *cov = init_hap_cov_t(ug, sg, sources, ruIndex, reverse_sources, coverage_cut, max_hang, min_ovlp, 0); - purge_dups(ug, sg, coverage_cut, sources, reverse_sources, ruIndex, NULL, - opt->purge_simi_thres, opt->purge_overlap_len, max_hang, min_ovlp, 0, 0, 1, cov, 0, 0); - destory_hap_cov_t(&cov); - - ma_ug_destroy(ug); - } -} - -void 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); - } - - for (i = 0; i < ug->g->n_seq; ++i) - { - if(ug->g->seq[i].del) continue; - u = &(ug->u.a[i]); - if(ug->g->seq[i].c == ALTER_LABLE) - { - for (k = 0; k < u->n; k++) - { - asg_seq_del(sg, u->a[k]>>33); - } - } - else - { - for (k = 0; (k + 1) < u->n; k++) - { - v = u->a[k]>>32; w = u->a[k+1]>>32; - - asg_arc_del(sg, v, w, 0); - asg_arc_del(sg, w^1, v^1, 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_del(sg, vx, wx, 0); asg_arc_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_del(sg, vx, wx, 0); asg_arc_del(sg, wx^1, vx^1, 0); - } - } - } - asg_cleanup(sg); - - - /*******************************for debug************************************/ - // ma_ug_t *dbg = ma_ug_gen(sg); - // for (i = 0; i < ug->g->n_seq; ++i) - // { - // if(ug->g->seq[i].del) continue; - // if(ug->g->seq[i].c == ALTER_LABLE) - // { - // asg_seq_del(ug->g, i); - // } - // } - // for (i = 0; i < dbg->g->n_seq; ++i) - // { - // dbg->g->seq[v].c = PRIMARY_LABLE; - // EvaluateLen(dbg->u, v) = dbg->u.a[v].n; - // } - // cmp_untig_graph(dbg, ug); - /*******************************for debug************************************/ -} - -void flat_bubbles(asg_t *sg, uint8_t* r_het) -{ - ma_ug_t *ug = NULL; - ug = ma_ug_gen(sg); - ma_utg_t *u = NULL; - uint32_t n_vtx = ug->g->n_seq<<1, v, convex, i, k, ori, is_het_b, is_het_s, n_pop = 0, pass_b, pass_s; - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - buf_t b; memset(&b, 0, sizeof(buf_t)); b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - uint8_t* bs_flag = (uint8_t*)calloc(n_vtx, 1); - uint64_t tLen = get_bub_pop_max_dist_advance(ug->g, &b), path, hom_occ, het_occ; - - for (v = 0; v < ug->g->n_seq; ++v) - { - if(ug->g->seq[v].del) continue; - ug->g->seq[v].c = PRIMARY_LABLE; - EvaluateLen(ug->u, v) = ug->u.a[v].n; - } - - n_pop = 1; ///round = 0; - while(n_pop > 0) - { - for (v = n_pop = 0; v < n_vtx; ++v) - { - if(ug->g->seq[v>>1].del) continue; - if(asg_arc_n(ug->g, v) < 2) continue; - if(get_real_length(ug->g, v, NULL) < 2) continue; - if(bs_flag[v] == 1) continue; - if(bs_flag[v] == 0) bs_flag[v] = 1; - - if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) - { - //note b.b include end, does not include beg - for (i = path = 0; i < b.b.n; i++) - { - if((b.b.a[i]>>1) == (v>>1) || (b.b.a[i]>>1) == (b.S.a[0]>>1)) - { - continue; - } - path += ug->u.a[b.b.a[i]>>1].n; - } - - - - bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 2; - is_het_b = is_het_s = pass_b = pass_s = 0; - //beg is v, end is b.S.a[0] - b.b.n = 0; - get_unitig(ug->g, NULL, v^1, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, - &max_stop_baseLen, 1, &b); - - - for (i = hom_occ = het_occ = 0; i < b.b.n; i++) - { - u = &(ug->u.a[b.b.a[i]>>1]); - ori = b.b.a[i]&1; - for (k = 0; k < u->n; k++) - { - if(r_het[(ori == 1?(u->a[u->n-k-1]>>33):(u->a[k]>>33))] == N_HET) - { - hom_occ++; - } - else - { - het_occ++; - } - if(het_occ > ((het_occ+hom_occ)*0.85)) - { - is_het_b = (het_occ+hom_occ); - } - - if((het_occ+hom_occ) == MAX((path+1),5)) - { - if(het_occ > ((het_occ+hom_occ)*0.7)) - { - pass_b = 1; - } - } - } - } - if(pass_b == 0) continue; - - - b.b.n = 0; - get_unitig(ug->g, NULL, b.S.a[0], &convex, &nodeLen, &baseLen, &max_stop_nodeLen, - &max_stop_baseLen, 1, &b); - for (i = hom_occ = het_occ= 0; i < b.b.n; i++) - { - u = &(ug->u.a[b.b.a[i]>>1]); - ori = b.b.a[i]&1; - for (k = 0; k < u->n; k++) - { - if(r_het[(ori == 1?(u->a[u->n-k-1]>>33):(u->a[k]>>33))] == N_HET) - { - hom_occ++; - } - else - { - het_occ++; - } - if(het_occ > ((het_occ+hom_occ)*0.85)) - { - is_het_s = (het_occ+hom_occ); - } - - if((het_occ+hom_occ) == MAX((path+1),5)) - { - if(het_occ > ((het_occ+hom_occ)*0.7)) - { - pass_s = 1; - } - } - } - } - if(pass_s == 0) continue; - - - if(is_het_b > path && is_het_s > path && (is_het_b+is_het_s)>(path<<2)) - { - asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 1, NULL, NULL, NULL, 0, 0, NULL); - n_pop++; - } - } - } - ///round++; - } - - /*******************************for debug************************************/ - // kvec_t(uint64_t) occ_sort; kv_init(occ_sort); - // for (v = n_pop = 0; v < ug->g->n_seq; ++v) - // { - // if(ug->g->seq[v].del) continue; - // if(ug->g->seq[v].c != ALTER_LABLE) continue; - // u = &(ug->u.a[v]); - - // kv_push(uint64_t, occ_sort, (uint64_t)((uint32_t)(-1) - (uint32_t)(u->n)) << 32 | (v)); - // } - // radix_sort_arch64(occ_sort.a, occ_sort.a + occ_sort.n); - // for (i = 0; i < occ_sort.n; ++i) - // { - // fprintf(stderr, "-utg%.6ul, n=%u\n", ((uint32_t)occ_sort.a[i])+1, - // (uint32_t)(-1) - (uint32_t)(occ_sort.a[i]>>32)); - // } - // kv_destroy(occ_sort); - /*******************************for debug************************************/ - - clean_sg_by_utg(sg, ug); - - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - ma_ug_destroy(ug); free(bs_flag); -} - -uint64_t get_primary_path_len(asg_t *sg, ma_ug_t *ug, uint32_t v0, buf_t *b) -{ - uint32_t v, u, k; - uint64_t len; - ma_utg_t *p = NULL; - - v = b->S.a[0]; - len = 0; - while (1) - { - u = b->a[v].p; // u->v - if(u == v0) break; - - p = &(ug->u.a[u>>1]); - - for (k = 0; k < p->n; k++) - { - len += sg->seq[p->a[k]>>33].len; - } - - v = u; - } - - return len; -} - -void flat_bubbles_advance(asg_t *sg, ma_hit_t_alloc* sources, R_to_U* ruIndex, uint64_t het_thres) -{ - // fprintf(stderr, "het_thres-%lu\n", het_thres); - ma_ug_t *ug = NULL; - ug = ma_ug_gen(sg); - ma_utg_t *u = NULL; - ma_hit_t *h; - uint32_t n_vtx = ug->g->n_seq<<1, v, i, k, m, rId, tn, is_Unitig, n_pop = 0; - uint64_t C_bases, R_bases; - buf_t b; memset(&b, 0, sizeof(buf_t)); b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - uint8_t* bs_flag = (uint8_t*)calloc(n_vtx, 1); - uint8_t* r_flag = (uint8_t*)calloc(sg->n_seq, sizeof(uint8_t)); - uint64_t tLen = get_bub_pop_max_dist_advance(ug->g, &b); - - for (v = 0; v < ug->g->n_seq; ++v) - { - if(ug->g->seq[v].del) continue; - ug->g->seq[v].c = PRIMARY_LABLE; - EvaluateLen(ug->u, v) = ug->u.a[v].n; - } - - n_pop = 1; ///round = 0; - while(n_pop > 0) - { - for (v = n_pop = 0; v < n_vtx; ++v) - { - if(ug->g->seq[v>>1].del) continue; - if(asg_arc_n(ug->g, v) < 2) continue; - if(get_real_length(ug->g, v, NULL) < 2) continue; - if(bs_flag[v] == 1) continue; - if(bs_flag[v] == 0) bs_flag[v] = 1; - - if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) - { - bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 2; - //note b.b include end, does not include beg - for (i = 0; i < b.b.n; i++) - { - u = &(ug->u.a[b.b.a[i]>>1]); - for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 1; - } - - u = &(ug->u.a[v>>1]); - for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 1; - - u = &(ug->u.a[b.S.a[0]>>1]); - for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 1; - - - - - - - C_bases = 0; - for (i = 0; i < b.b.n; i++) - { - if((b.b.a[i]>>1) == (v>>1) || (b.b.a[i]>>1) == (b.S.a[0]>>1)) continue; - u = &(ug->u.a[b.b.a[i]>>1]); - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - // R_bases += sg->seq[rId].len; - for (m = 0; m < (uint64_t)(sources[rId].length); m++) - { - h = &(sources[rId].buffer[m]); - ///if(h->el != 1) continue; - tn = Get_tn((*h)); - if(sg->seq[tn].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || sg->seq[tn].del == 1) continue; - } - if(sg->seq[tn].del == 1) continue; - if(r_flag[tn] == 0) continue; - C_bases += (Get_qe((*h)) - Get_qs((*h))); - } - } - } - - R_bases = get_primary_path_len(sg, ug, v, &b); - - if((C_bases/R_bases) <= het_thres) - { - // fprintf(stderr, "s-utg%.6ul\te-utg%.6ul\tC_bases:%lu\tR_bases:%lu\n", (v>>1)+1, (b.S.a[0]>>1)+1, C_bases, R_bases); - asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 1, NULL, NULL, NULL, 0, 0, NULL); - n_pop++; - } - - - for (i = 0; i < b.b.n; i++) - { - u = &(ug->u.a[b.b.a[i]>>1]); - for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 0; - } - - u = &(ug->u.a[v>>1]); - for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 0; - - u = &(ug->u.a[b.S.a[0]>>1]); - for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 0; - } - } - ///round++; - } - - /*******************************for debug************************************/ - // kvec_t(uint64_t) occ_sort; kv_init(occ_sort); - // for (v = n_pop = 0; v < ug->g->n_seq; ++v) - // { - // if(ug->g->seq[v].del) continue; - // if(ug->g->seq[v].c != ALTER_LABLE) continue; - // u = &(ug->u.a[v]); - - // kv_push(uint64_t, occ_sort, (uint64_t)((uint32_t)(-1) - (uint32_t)(u->n)) << 32 | (v)); - // } - // radix_sort_arch64(occ_sort.a, occ_sort.a + occ_sort.n); - // for (i = 0; i < occ_sort.n; ++i) - // { - // fprintf(stderr, "-utg%.6ul, n=%u\n", ((uint32_t)occ_sort.a[i])+1, - // (uint32_t)(-1) - (uint32_t)(occ_sort.a[i]>>32)); - // } - // kv_destroy(occ_sort); - /*******************************for debug************************************/ - - clean_sg_by_utg(sg, ug); - - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - ma_ug_destroy(ug); free(bs_flag); free(r_flag); -} - - -void flat_soma_v(asg_t *sg, ma_hit_t_alloc* sources, R_to_U* ruIndex) -{ - uint64_t dip_thre_max; - if(asm_opt.somatic_cov >= 0) { - dip_thre_max = asm_opt.somatic_cov; - } else { - if(asm_opt.hom_global_coverage_set) { - dip_thre_max = asm_opt.hom_global_coverage; - } else { - dip_thre_max = ((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE); - } - dip_thre_max = (((double)(dip_thre_max)*1.15)/asm_opt.polyploidy); - } - flat_bubbles_advance(sg, sources, ruIndex, dip_thre_max); -} - -char *get_outfile_name(char* output_file_name) -{ - char *buf = NULL; - CALLOC(buf, strlen(output_file_name) + 25); - if(ha_opt_triobin(&asm_opt) && ha_opt_hic(&asm_opt)) - { - sprintf(buf, "%s.hic.bench", output_file_name); - } - else if(ha_opt_triobin(&asm_opt)) - { - sprintf(buf, "%s.dip", output_file_name); - } - else if(ha_opt_hic(&asm_opt)) - { - sprintf(buf, "%s.hic", output_file_name); - } - else if(asm_opt.flag & HA_F_PARTITION) - { - sprintf(buf, "%s.bp", output_file_name); - } - else - { - sprintf(buf, "%s", output_file_name); - } - - return buf; -} - -void gen_ug_opt_t(ug_opt_t *opt, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, int64_t max_hang, int64_t min_ovlp, -int64_t gap_fuzz, int64_t min_dp, uint64_t* readLen, ma_sub_t *coverage_cut, R_to_U* ruIndex, long long tipsLen, -float tip_drop_ratio, long long stops_threshold, float chimeric_rate, float drop_ratio, bub_label_t* b_mask_t, telo_end_t *te) -{ - memset(opt, 0, sizeof((*opt))); - opt->sources = sources; opt->reverse_sources = reverse_sources; opt->max_hang = max_hang; - opt->min_ovlp = min_ovlp; opt->gap_fuzz = gap_fuzz; opt->min_dp = min_dp; opt->readLen = readLen; - opt->coverage_cut = coverage_cut; opt->ruIndex = ruIndex; opt->tipsLen = tipsLen; - opt->tip_drop_ratio = tip_drop_ratio; opt->stops_threshold = stops_threshold; - opt->chimeric_rate = chimeric_rate; opt->drop_ratio = drop_ratio; opt->b_mask_t = b_mask_t; opt->te = te; -} - -void create_ul_info(ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, int64_t max_hang, int64_t min_ovlp, int64_t gap_fuzz, -int64_t min_dp, uint64_t* readLen, ma_sub_t *coverage_cut, R_to_U* ruIndex, long long tipsLen, float tip_drop_ratio, long long stops_threshold, float chimeric_rate, float drop_ratio, bub_label_t* b_mask_t, telo_end_t *te) -{ - ug_opt_t opt; - gen_ug_opt_t(&opt, sources, reverse_sources, max_hang, min_ovlp, gap_fuzz, min_dp, readLen, coverage_cut, ruIndex, - tipsLen, tip_drop_ratio, stops_threshold, chimeric_rate, drop_ratio, b_mask_t, te); - ul_load(&opt); -} - -void rescue_src_ul(ma_hit_t_alloc* src, uint64_t n_read, uint64_t occ) -{ - uint64_t k, i; - for (k = 0; k < n_read; k++) { - for (i = 0; i < src[k].length; i++) { - if(!src[k].buffer[i].del) continue; - if(src[k].buffer[i].bl>=occ) src[k].buffer[i].del = 0; - } - } -} - -void prt_dbg_gfa(asg_t *sg, const char *suffix, ma_sub_t *cov, ma_hit_t_alloc* src, R_to_U* ruIndex, int64_t max_hang, int64_t min_ovlp) -{ - char *o_file = get_outfile_name(asm_opt.output_file_name); - char* gfa_name; MALLOC(gfa_name, strlen(o_file)+strlen(suffix)+50); sprintf(gfa_name, "%s.%s", o_file, suffix); - print_debug_gfa(sg, NULL, cov, gfa_name, src, ruIndex, max_hang, min_ovlp, 0, 0, 1); - free(gfa_name); free(o_file); -} - -void prt_dbg_rid_ovlp(ma_hit_t_alloc *ov, int64_t rid, char *rn, const char *cmd) -{ - uint64_t k; ma_hit_t *h = NULL; - if(rid < 0) { - for (k = 0; k < R_INF.total_reads; k++) { - if (memcmp(rn, Get_NAME((R_INF), k), Get_NAME_LENGTH((R_INF), k)) == 0) break; - } - if(k >= R_INF.total_reads) return; - rid = k; - } - - fprintf(stderr, "\n[M::%s::%s::id::%ld]\n", __func__, cmd, rid); - for (k = 0; k < ov[rid].length; k++) { - h = &(ov[rid].buffer[k]); - if(h->del) continue; - fprintf(stderr, "%.*s(qn::%u)\t%u\t%u\t%u\t%c\t%.*s(tn::%u)\t%u\t%u\t%u\t%u\t%u\t255\n", (int)Get_NAME_LENGTH(R_INF, Get_qn(*h)), Get_NAME((R_INF), Get_qn(*h)), Get_qn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_qn(*h)), Get_qs(*h), Get_qe(*h), "+-"[h->rev], - (int)Get_NAME_LENGTH(R_INF, Get_tn(*h)), Get_NAME((R_INF), Get_tn(*h)), Get_tn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_tn(*h)), Get_ts(*h), Get_te(*h), h->ml, h->bl); - } -} - -asg_t *gen_init_sg(int32_t min_dp, uint64_t n_read, int64_t mini_overlap_length, int64_t max_hang_length, int64_t gap_fuzz, -ma_hit_t_alloc* src, uint64_t* readLen, R_to_U* ruIndex, bub_label_t *b_mask_t, ma_sub_t** cov, all_ul_t *ul, telo_end_t *te) -{ - asg_t *sg = NULL; - // prt_dbg_rid_ovlp(src, -1, (char*)"c85c2e91-0490-438b-977b-b7d056973996", "1"); - if(ul) rescue_src_ul(src, n_read, UL_COV_THRES); - // prt_dbg_rid_ovlp(src, -1, (char*)"c85c2e91-0490-438b-977b-b7d056973996", "2"); - ma_hit_sub(min_dp, src, n_read, readLen, mini_overlap_length, cov); - // prt_dbg_rid_ovlp(src, -1, (char*)"c85c2e91-0490-438b-977b-b7d056973996", "3"); - detect_chimeric_reads(src, n_read, readLen, *cov, asm_opt.max_ov_diff_final*2.0, ul, UL_COV_THRES); - // prt_dbg_rid_ovlp(src, -1, (char*)"c85c2e91-0490-438b-977b-b7d056973996", "4"); - ma_hit_cut(src, n_read, readLen, mini_overlap_length, cov); - // prt_dbg_rid_ovlp(src, -1, (char*)"c85c2e91-0490-438b-977b-b7d056973996", "5"); - ma_hit_flt(src, n_read, *cov, max_hang_length, mini_overlap_length); - // prt_dbg_rid_ovlp(src, -1, (char*)"c85c2e91-0490-438b-977b-b7d056973996", "6"); - ma_hit_contained_advance(src, n_read, *cov, ruIndex, max_hang_length, mini_overlap_length); - // prt_dbg_rid_ovlp(src, -1, (char*)"c85c2e91-0490-438b-977b-b7d056973996", "7"); - - if(!ul) { - sg = ma_sg_gen(src, n_read, *cov, max_hang_length, mini_overlap_length); - if(asm_opt.prt_dbg_gfa) prt_dbg_gfa(sg, "raw", *cov, src, ruIndex, max_hang_length, mini_overlap_length); - asg_arc_del_trans(sg, gap_fuzz); - } else { - ug_opt_t uopt; - sg = ma_sg_gen_ul(src, n_read, *cov, ruIndex, max_hang_length, mini_overlap_length, UL_COV_THRES); - if(asm_opt.prt_dbg_gfa) prt_dbg_gfa(sg, "raw", *cov, src, ruIndex, max_hang_length, mini_overlap_length); - gen_ug_opt_t(&uopt, src, NULL, max_hang_length, mini_overlap_length, gap_fuzz, min_dp, readLen, *cov, ruIndex, -1, -1, -1, -1, -1, b_mask_t, te); - - ///debug - // asg_symm(sg); - // dedup_contain_g(&uopt, sg); - - if(clean_contain_g(&uopt, sg, 0)) update_sg_uo(sg, src); - // prt_specfic_sge(sg, 10498, 10505, "--*--"); - asg_arc_del_trans_ul(sg, gap_fuzz); - // prt_specfic_sge(sg, 10498, 10505, "--#--"); - } - - init_bub_label_t(b_mask_t, MIN(10, asm_opt.thread_num), sg->n_seq); - asm_opt.coverage = get_coverage(src, *cov, n_read); - return sg; -} - -void renew_g(ma_hit_t_alloc **sources, ma_hit_t_alloc **reverse_sources, long long *n_read, -uint64_t **readLen, ma_sub_t **coverage_cut, R_to_U *ruIndex, asg_t **sg, int64_t mini_overlap_length, -int64_t max_hang_length, ug_opt_t *uopt, int64_t clean_round, double min_ovlp_drop_ratio, -double max_ovlp_drop_ratio, int64_t max_tip, bub_label_t *b_mask_t, uint32_t is_trio, -char *o_file, const char *bin_file, uint64_t free_uld, uint64_t is_bridg, uint64_t deep_clean) -{ - ul_renew_t nopt; memset(&nopt, 0, sizeof(nopt)); - nopt.src = sources; nopt.r_src = reverse_sources; nopt.ruIndex = ruIndex; - nopt.n_read = n_read; nopt.readLen = readLen; nopt.sg = sg; - nopt.cov = coverage_cut; nopt.b_mask_t = b_mask_t; - nopt.max_hang = max_hang_length; nopt.mini_ovlp = mini_overlap_length; - ul_realignment_gfa(uopt, *sg, clean_round, min_ovlp_drop_ratio, max_ovlp_drop_ratio, - asm_opt.max_short_tip, asm_opt.max_short_ul_tip, b_mask_t, ha_opt_triobin(&asm_opt), o_file, &nopt, bin_file, free_uld, is_bridg, deep_clean); - // ma_ug_t *iug = ul_realignment_gfa(uopt, *sg, clean_round, min_ovlp_drop_ratio, max_ovlp_drop_ratio, - // asm_opt.max_short_tip, b_mask_t, ha_opt_triobin(&asm_opt), o_file); - // asg_t *ng = gen_ng(iug, *sg, uopt, coverage_cut, ruIndex, 256); - // ma_ug_destroy(iug); asg_destroy(*sg); - // (*sources) = R_INF.paf; - // (*reverse_sources) = R_INF.reverse_paf; - // (*n_read) = R_INF.total_reads; - // (*readLen) = R_INF.read_length; - // (*sg) = ng; - // ma_hit_contained_advance(*sources, *n_read, *coverage_cut, ruIndex, max_hang_length, mini_overlap_length); - // post_rescue(uopt, *sg, (*sources), (*reverse_sources), ruIndex, b_mask_t, 0); -} - -void gradually_renew_g(ma_hit_t_alloc **src, ma_hit_t_alloc **rev_src, long long *n_read, -uint64_t **readLen, ma_sub_t **cov, R_to_U *ruIndex, asg_t **sg, int64_t mini_overlap_length, -int64_t max_hang_length, ug_opt_t *uopt, int64_t clean_round, double min_ovlp_drop_ratio, -double max_ovlp_drop_ratio, int64_t max_tip, int64_t gap_fuzz, int64_t min_dp, -bub_label_t *b_mask_t, uint32_t is_trio, int32_t ul_aln_round, char *o_file, const char *bin_file, telo_end_t *te) -{ - int32_t k, strl = strlen(bin_file)+1, kt, cl, sl; char *id = NULL; - renew_g(src, rev_src, n_read, readLen, cov, ruIndex, sg, mini_overlap_length, max_hang_length, - uopt, clean_round, min_ovlp_drop_ratio, max_ovlp_drop_ratio, asm_opt.max_short_tip, b_mask_t, - is_trio, o_file, bin_file, (ul_aln_round<=1)?1:0, 1, /**((is_trio)?(0):(1))**/((asm_opt.polyploidy<=2)?1:0)); - gen_ug_opt_t(uopt, *src, *rev_src, max_hang_length, mini_overlap_length, gap_fuzz, min_dp, *readLen, - *cov, ruIndex, (asm_opt.max_short_tip*2), 0.15, 3, 0.05, 0.9, b_mask_t, te); - ug_ext_gfa(uopt, *sg, ug_ext_len); - - /**if(!ha_opt_triobin(&asm_opt))**/ hic_clean_adv(*sg, uopt); - - cl = strl+1; MALLOC(id, cl); - for (k = 1; k < ul_aln_round; k++) { - for(kt = k, sl = strl+1; kt > 0; kt/=10) sl++; - if(cl < sl) { - cl = sl; REALLOC(id, cl); - } - - sprintf(id, "%s%d", bin_file, k); - renew_g(src, rev_src, n_read, readLen, cov, ruIndex, sg, mini_overlap_length, max_hang_length, - uopt, clean_round, min_ovlp_drop_ratio, max_ovlp_drop_ratio, asm_opt.max_short_tip, b_mask_t, - is_trio, o_file, id, ((k+1)==ul_aln_round)?1:0, 0, 0); - gen_ug_opt_t(uopt, *src, *rev_src, max_hang_length, mini_overlap_length, gap_fuzz, min_dp, *readLen, - *cov, ruIndex, (asm_opt.max_short_tip*2), 0.15, 3, 0.05, 0.9, b_mask_t, te); - ug_ext_gfa(uopt, *sg, ug_ext_len); - /**if(!ha_opt_triobin(&asm_opt))**/ hic_clean_adv(*sg, uopt); - } - free(id); -} - -void clean_graph( -int min_dp, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -long long n_read, uint64_t* readLen, long long mini_overlap_length, -long long max_hang_length, long long clean_round, long long gap_fuzz, -float min_ovlp_drop_ratio, float max_ovlp_drop_ratio, char* output_file_name, -long long bubble_dist, int read_graph, R_to_U* ruIndex, asg_t **sg_ptr, -ma_sub_t **coverage_cut_ptr, uint8_t *cmk, int debug_g) -{ - char *o_file = get_outfile_name(output_file_name); - ma_sub_t *coverage_cut = *coverage_cut_ptr; - asg_t *sg = *sg_ptr; - bub_label_t b_mask_t; - ug_opt_t uopt; - telo_end_t *te = NULL; - - if(asm_opt.telo_motif) te = gen_telo_end_t(&R_INF, asm_opt.telo_motif, asm_opt.telo_mic_sc, asm_opt.telo_pen, asm_opt.telo_drop, asm_opt.thread_num); - - if(debug_g) - { - init_bub_label_t(&b_mask_t, MIN(10, asm_opt.thread_num), n_read); - goto debug_gfa; - } - ///just for debug - if(!cmk) renew_graph_init(sources, reverse_sources, sg, coverage_cut, ruIndex, n_read); - // if(asm_opt.is_ont) handle_chemical_arc(asm_opt.thread_num, R_INF.total_reads); - // if(asm_opt.is_ont) handle_chemical_r(asm_opt.thread_num, R_INF.total_reads); - - ///it's hard to say which function is better - ///normalize_ma_hit_t_single_side(sources, n_read); - - normalize_ma_hit_t_single_side_advance(sources, n_read, asm_opt.is_ont, cmk); - // normalize_ma_hit_t_single_side_advance_mult(sources, n_read, asm_opt.thread_num); - normalize_ma_hit_t_single_side_advance(reverse_sources, n_read, 0, cmk); - // normalize_ma_hit_t_single_side_advance_mult(reverse_sources, n_read, asm_opt.thread_num); - - if (ha_opt_triobin(&asm_opt)) - { - drop_edges_by_trio(sources, n_read); - } - else - { - memset(R_INF.trio_flag, AMBIGU, R_INF.total_reads*sizeof(uint8_t)); - } - if(asm_opt.ar) init_all_ul_t(&UL_INF, &R_INF); - // if (asm_opt.flag & HA_F_VERBOSE_GFA) { - // write_debug_graph(NULL, sources, coverage_cut, output_file_name, reverse_sources, ruIndex, &UL_INF); - // debug_gfa:; - // } - ///should recover edges from sources by using UL alignments - // prt_specific_overlap(sources, 22233, 22235, "0-a"); - // prt_specific_overlap(sources, 22235, 22233, "0-a"); - if(asm_opt.ar) { - create_ul_info(sources, reverse_sources, max_hang_length, mini_overlap_length, gap_fuzz, min_dp, readLen, coverage_cut, ruIndex, - (asm_opt.max_short_tip*2), 0.15, 3, 0.05, 0.9, &b_mask_t, te); - } - // prt_specific_overlap(sources, 22233, 22235, "0-b"); - // prt_specific_overlap(sources, 22235, 22233, "0-b"); - // prt_dbg_rid_ovlp(sources, 27087, NULL, "0-a"); - if(!(asm_opt.is_ont)) clean_weak_ma_hit_t(sources, reverse_sources, n_read, asm_opt.ar?UL_COV_THRES:(uint32_t)-1); - // prt_dbg_rid_ovlp(sources, 27087, NULL, "0-b"); - // prt_specific_overlap(sources, 22233, 22235, "0-c"); - // prt_specific_overlap(sources, 22235, 22233, "0-c"); - sg = gen_init_sg(min_dp, n_read, mini_overlap_length, max_hang_length, gap_fuzz, sources, readLen, ruIndex, - &b_mask_t, &coverage_cut, asm_opt.ar?&UL_INF:NULL, te); - // if(asm_opt.ar) exit(1); - /** - ///print_binned_reads(sources, n_read, coverage_cut); - - ///ma_hit_sub is just use to init coverage_cut, - ///it seems we do not need ma_hit_cut & ma_hit_flt - ma_hit_sub(min_dp, sources, n_read, readLen, mini_overlap_length, &coverage_cut); - detect_chimeric_reads(sources, n_read, readLen, coverage_cut, asm_opt.max_ov_diff_final * 2.0, asm_opt.ar?&UL_INF:NULL); - ma_hit_cut(sources, n_read, readLen, mini_overlap_length, &coverage_cut); - ///print_binned_reads(sources, n_read, coverage_cut); - ma_hit_flt(sources, n_read, coverage_cut, max_hang_length, mini_overlap_length); - ///fix_binned_reads(sources, n_read, coverage_cut); - ///just need to deal with trio here - ma_hit_contained_advance(sources, n_read, coverage_cut, ruIndex, max_hang_length, mini_overlap_length); - sg = ma_sg_gen(sources, n_read, coverage_cut, max_hang_length, mini_overlap_length); - ///debug_info_of_specfic_node((char*)"m64043_200504_050026/93784180/ccs", sg, ruIndex, (char*)"sbsbsb"); - init_bub_label_t(&b_mask_t, MIN(10, asm_opt.thread_num), sg->n_seq); - asg_arc_del_trans(sg, gap_fuzz); - asm_opt.coverage = get_coverage(sources, coverage_cut, n_read); - **/ - if(VERBOSE >= 1) - { - char* unlean_name = (char*)malloc(strlen(output_file_name)+25); - sprintf(unlean_name, "%s.unclean", output_file_name); - output_read_graph(sg, coverage_cut, unlean_name, n_read); - free(unlean_name); - } - - - // if (asm_opt.flag & HA_F_VERBOSE_GFA) { - // write_debug_graph(sg, sources, coverage_cut, output_file_name, reverse_sources, ruIndex, &UL_INF); - // debug_gfa:; - // } - - gen_ug_opt_t(&uopt, sources, reverse_sources, max_hang_length, mini_overlap_length, gap_fuzz, min_dp, readLen, coverage_cut, ruIndex, - (asm_opt.max_short_tip*2), 0.15, 3, 0.05, 0.9, &b_mask_t, te); - ul_clean_gfa(&uopt, sg, sources, reverse_sources, ruIndex, clean_round, min_ovlp_drop_ratio, max_ovlp_drop_ratio, - 0.6, asm_opt.max_short_tip, gap_fuzz, &b_mask_t, !!asm_opt.ar, ha_opt_triobin(&asm_opt), UL_COV_THRES, cmk, o_file); - ///@brief debug - if (asm_opt.flag & HA_F_VERBOSE_GFA) { - write_debug_graph(sg, sources, coverage_cut, output_file_name, reverse_sources, ruIndex, &UL_INF); - debug_gfa:; - gen_ug_opt_t(&uopt, sources, reverse_sources, max_hang_length, mini_overlap_length, gap_fuzz, min_dp, readLen, coverage_cut, ruIndex, - (asm_opt.max_short_tip*2), 0.15, 3, 0.05, 0.9, &b_mask_t, te); - // set_hom_global_coverage(&asm_opt, sg, coverage_cut, sources, reverse_sources, ruIndex, max_hang_length, mini_overlap_length); - } - - if(asm_opt.ar) { - gradually_renew_g(&sources, &reverse_sources, &n_read, &readLen, &coverage_cut, ruIndex, - &sg, mini_overlap_length, max_hang_length, &uopt, clean_round, min_ovlp_drop_ratio, - max_ovlp_drop_ratio, asm_opt.max_short_tip, gap_fuzz, min_dp, &b_mask_t, - ha_opt_triobin(&asm_opt), asm_opt.ul_clean_round, o_file, "re", te); - } else { - ug_ext_gfa(&uopt, sg, ug_ext_len); - if(!ha_opt_triobin(&asm_opt)) { - // output_unitig_graph(sg, coverage_cut, "pre_clean", sources, ruIndex, max_hang_length, mini_overlap_length); - hic_clean_adv(sg, &uopt); - } - } - - /** - if(asm_opt.ar) { - renew_g(&sources, &reverse_sources, &n_read, &readLen, &coverage_cut, ruIndex, &sg, mini_overlap_length, max_hang_length, - &uopt, clean_round, min_ovlp_drop_ratio, max_ovlp_drop_ratio, asm_opt.max_short_tip, &b_mask_t, - ha_opt_triobin(&asm_opt), o_file); - ///make sure uopt has been updated; not necessary - gen_ug_opt_t(&uopt, sources, reverse_sources, max_hang_length, mini_overlap_length, gap_fuzz, min_dp, readLen, coverage_cut, ruIndex, - (asm_opt.max_short_tip*2), 0.15, 3, 0.05, 0.9, &b_mask_t); - } - **/ - // print_debug_gfa(sg, NULL, coverage_cut, "UL.debug", sources, ruIndex, max_hang_length, mini_overlap_length, 0, 0, 0); - /** - asg_cut_tip(sg, asm_opt.max_short_tip); - ///debug_info_of_specfic_node("m64043_200505_112554/8849050/ccs", sg, "inner_1"); - ///drop_inexact_edegs_at_bubbles(sg, bubble_dist); - - if(clean_round > 0) - { - double cut_step; - if(clean_round == 1) - { - cut_step = max_ovlp_drop_ratio; - } - else - { - cut_step = (max_ovlp_drop_ratio - min_ovlp_drop_ratio) / (clean_round - 1); - } - double drop_ratio = min_ovlp_drop_ratio; - int i = 0; - for (i = 0; i < clean_round; i++, drop_ratio += cut_step) - { - if(drop_ratio > max_ovlp_drop_ratio) - { - drop_ratio = max_ovlp_drop_ratio; - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "\n\n**********%d-th round drop: drop_ratio = %f**********\n", - i, drop_ratio); - } - - ///just topological clean - pre_clean(sources, coverage_cut, sg, 1); - ///asg_arc_del_orthology(sg, reverse_sources, drop_ratio, asm_opt.max_short_tip); - // asg_arc_del_orthology_multiple_way(sg, reverse_sources, drop_ratio, asm_opt.max_short_tip); - // asg_cut_tip(sg, asm_opt.max_short_tip); - - asg_arc_identify_simple_bubbles_multi(sg, &b_mask_t, 1); - //reomve edge between two chromesomes - //this node must be a single read - asg_arc_del_false_node(sg, sources, asm_opt.max_short_tip); - asg_cut_tip(sg, asm_opt.max_short_tip); - - ///asg_arc_identify_simple_bubbles_multi(sg, 1); - asg_arc_identify_simple_bubbles_multi(sg, &b_mask_t, 0); - ///asg_arc_del_short_diploid_unclean_exact(sg, drop_ratio, sources); - if (ha_opt_triobin(&asm_opt)) - { - asg_arc_del_short_diploid_by_exact_trio(sg, asm_opt.max_short_tip, sources); - } - else - { - asg_arc_del_short_diploid_by_exact(sg, asm_opt.max_short_tip, sources); - } - asg_cut_tip(sg, asm_opt.max_short_tip); - - asg_arc_identify_simple_bubbles_multi(sg, &b_mask_t, 1); - if (ha_opt_triobin(&asm_opt)) - { - asg_arc_del_short_diploid_by_length_trio(sg, drop_ratio, asm_opt.max_short_tip, reverse_sources, - asm_opt.max_short_tip, 1, 1, 0, 0, ruIndex); - } - else - { - asg_arc_del_short_diploid_by_length(sg, drop_ratio, asm_opt.max_short_tip, reverse_sources, - asm_opt.max_short_tip, 1, 1, 0, 0, ruIndex); - } - asg_cut_tip(sg, asm_opt.max_short_tip); - - asg_arc_identify_simple_bubbles_multi(sg, &b_mask_t, 1); - asg_arc_del_short_false_link(sg, 0.6, 0.85, bubble_dist, reverse_sources, asm_opt.max_short_tip, ruIndex); - - asg_arc_identify_simple_bubbles_multi(sg, &b_mask_t, 1); - asg_arc_del_complex_false_link(sg, 0.6, 0.85, bubble_dist, reverse_sources, asm_opt.max_short_tip); - - asg_cut_tip(sg, asm_opt.max_short_tip); - } - } - if(VERBOSE >= 1) - { - fprintf(stderr, "\n\n**********final clean**********\n"); - } - - - pre_clean(sources, coverage_cut, sg, 1); - - - asg_arc_del_short_diploi_by_suspect_edge(sg, asm_opt.max_short_tip); - asg_cut_tip(sg, asm_opt.max_short_tip); - asg_arc_del_triangular_directly(sg, asm_opt.max_short_tip, reverse_sources, ruIndex); - - - asg_arc_identify_simple_bubbles_multi(sg, &b_mask_t, 0); - asg_arc_del_orthology_multiple_way(sg, reverse_sources, 0.4, asm_opt.max_short_tip, ruIndex); - asg_cut_tip(sg, asm_opt.max_short_tip); - - - - - asg_arc_identify_simple_bubbles_multi(sg, &b_mask_t, 0); - asg_arc_del_too_short_overlaps(sg, 2000, min_ovlp_drop_ratio, reverse_sources, asm_opt.max_short_tip, ruIndex); - asg_cut_tip(sg, asm_opt.max_short_tip); - - asg_arc_del_simple_circle_untig(sources, coverage_cut, sg, 100, 0); - - ///note: don't apply asg_arc_del_too_short_overlaps() after this function!!!! - rescue_contained_reads_aggressive(NULL, sg, sources, coverage_cut, ruIndex, max_hang_length, - mini_overlap_length, 10, 1, 0, NULL, NULL, &b_mask_t); - rescue_missing_overlaps_aggressive(NULL, sg, sources, coverage_cut, ruIndex, max_hang_length, - mini_overlap_length, 1, 0, NULL, &b_mask_t); - rescue_missing_overlaps_backward(NULL, sg, sources, coverage_cut, ruIndex, max_hang_length, - mini_overlap_length, 10, 1, 0, &b_mask_t); - // rescue_wrong_overlaps_to_unitigs(NULL, sg, sources, reverse_sources, coverage_cut, ruIndex, - // max_hang_length, mini_overlap_length, bubble_dist, NULL); - // rescue_no_coverage_aggressive(sg, sources, reverse_sources, &coverage_cut, ruIndex, max_hang_length, - // mini_overlap_length, bubble_dist, 10); - - - set_hom_global_coverage(&asm_opt, sg, coverage_cut, sources, reverse_sources, ruIndex, - max_hang_length, mini_overlap_length); - - rescue_bubble_by_chain(sg, coverage_cut, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, - ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, 10, gap_fuzz, &b_mask_t); - - - output_unitig_graph(sg, coverage_cut, o_file, sources, ruIndex, max_hang_length, mini_overlap_length); - // flat_bubbles(sg, ruIndex->is_het); free(ruIndex->is_het); ruIndex->is_het = NULL; - flat_soma_v(sg, sources, ruIndex); - **/ - - output_contig_graph_primary_pre(sg, coverage_cut, o_file, sources, reverse_sources, - asm_opt.small_pop_bubble_size, asm_opt.max_short_tip, ruIndex, max_hang_length, mini_overlap_length, &uopt); - - // if(asm_opt.ar) { - // char *op_file = get_outfile_name(o_file); - // ul_clean_gfa(&uopt, sg, sources, reverse_sources, ruIndex, clean_round, min_ovlp_drop_ratio, max_ovlp_drop_ratio, - // 0.6, asm_opt.max_short_tip, gap_fuzz, &b_mask_t, 0/**!!asm_opt.ar**/, ha_opt_triobin(&asm_opt), UL_COV_THRES, op_file); - // output_contig_graph_primary_pre(sg, coverage_cut, op_file, sources, reverse_sources, - // asm_opt.small_pop_bubble_size, asm_opt.max_short_tip, ruIndex, max_hang_length, mini_overlap_length, &uopt); - // free(op_file); - // } - /** - if (asm_opt.flag & HA_F_VERBOSE_GFA) - { - write_debug_graph(sg, sources, coverage_cut, output_file_name, n_read, reverse_sources, ruIndex); - debug_gfa:; - }**/ - - if(asm_opt.fn_bin_poy) - { - if(asm_opt.flag & HA_F_PARTITION) asm_opt.flag -= HA_F_PARTITION; - output_poly_trio(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, - 0.05, 0.9, max_hang_length, mini_overlap_length, gap_fuzz, 0, &b_mask_t, asm_opt.polyploidy); - } - else if (ha_opt_triobin(&asm_opt) && ha_opt_hic(&asm_opt)) - { - if(asm_opt.flag & HA_F_PARTITION) asm_opt.flag -= HA_F_PARTITION; - benchmark_hic_graph(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, - ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, gap_fuzz, &b_mask_t); - } - else if (ha_opt_triobin(&asm_opt)) - { - if(asm_opt.flag & HA_F_PARTITION) asm_opt.flag -= HA_F_PARTITION; - // output_trio_graph(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), - // 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, 0, gap_fuzz, &uopt, &b_mask_t); - if(asm_opt.trio_cov_het_ovlp > 0) { - output_bp_trio_graph(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), - 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, &b_mask_t, gap_fuzz, &uopt); - } else { - output_trio_graph_joint(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), - 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, gap_fuzz, &b_mask_t, NULL, NULL, &uopt); - } - } - else if(ha_opt_hic(&asm_opt)) - { - if(asm_opt.flag & HA_F_PARTITION) asm_opt.flag -= HA_F_PARTITION; - if(asm_opt.polyploidy <= 2) { - output_hic_graph(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), - 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, gap_fuzz, &b_mask_t, &uopt); - } else { - output_hic_graph_mmhap(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), - 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, gap_fuzz, &b_mask_t, &uopt); - } - - // output_hic_graph_polyploid(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), - // 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, gap_fuzz, &b_mask_t); - } - else if((asm_opt.flag & HA_F_PARTITION) && (asm_opt.purge_level_primary > 0)) - { - output_bp_graph(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), - 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, &b_mask_t, gap_fuzz, &uopt); - } - else - { - if(asm_opt.flag & HA_F_PARTITION) asm_opt.flag -= HA_F_PARTITION; - output_contig_graph_primary(sg, coverage_cut, o_file, sources, reverse_sources, - (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, &b_mask_t); - - output_contig_graph_alternative(sg, coverage_cut, o_file, sources, ruIndex, max_hang_length, mini_overlap_length); - } - - *coverage_cut_ptr = coverage_cut; - *sg_ptr = sg; - destory_bub_label_t(&b_mask_t); - if(te) { - destory_telo_end_t(te); free(te); te = NULL; - } - free(o_file); ///if(asm_opt.ar) destory_all_ul_t(&UL_INF); - fprintf(stderr, "Inconsistency threshold for low-quality regions in BED files: %u%%\n", asm_opt.bed_inconsist_rate); -} - -void build_string_graph_without_clean( -int min_dp, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -uint64_t n_read, uint64_t* readLen, long long mini_overlap_length, -long long max_hang_length, long long clean_round, long long gap_fuzz, -float min_ovlp_drop_ratio, float max_ovlp_drop_ratio, char* output_file_name, -long long bubble_dist, int read_graph, int write) -{ - R_to_U ruIndex; - init_R_to_U(&ruIndex, n_read); - asg_t *sg = NULL; uint8_t *cmk = NULL; - ma_sub_t* coverage_cut = NULL; - init_aux_table(); - ///actually min_thres = asm_opt.max_short_tip + 1 there are asm_opt.max_short_tip reads - min_thres = asm_opt.max_short_tip + 1; - if (asm_opt.flag & HA_F_VERBOSE_GFA) - { - if(load_debug_graph(/**NULL**/&sg, &sources, /**NULL**/&coverage_cut, output_file_name, &reverse_sources, &ruIndex, &UL_INF)) - { - fprintf(stderr, "debug gfa has been loaded\n"); - - clean_graph(min_dp, sources, reverse_sources, n_read, readLen, mini_overlap_length, - max_hang_length, clean_round, gap_fuzz, min_ovlp_drop_ratio, max_ovlp_drop_ratio, - output_file_name, bubble_dist, read_graph, &ruIndex, &sg, &coverage_cut, cmk, 1); - asg_destroy(sg); - free(coverage_cut); - destory_R_to_U(&ruIndex); - return; - } - } - if (asm_opt.write_index_to_disk && write) - { - write_all_data_to_disk(sources, reverse_sources, - &R_INF, output_file_name); - } - ///debug_info_of_specfic_read("m64011_190830_220126/31720629/ccs", sources, reverse_sources, -1, "beg"); - - if (!(asm_opt.flag & HA_F_BAN_ASSEMBLY)) - { - // if(asm_opt.is_ont) handle_chemical_r(asm_opt.thread_num, R_INF.total_reads); - if(asm_opt.is_ont) { - uint64_t i = 0, j = 0; - memset(ruIndex.index, -1, sizeof(uint32_t)*(ruIndex.len)); - for (i = 0; i < n_read; i++) { - for (j = 0; j < sources[i].length; j++) sources[i].buffer[j].del = 0; - for (j = 0; j < reverse_sources[i].length; j++) reverse_sources[i].buffer[j].del = 0; - } - if(asm_opt.is_ont) cmk = gen_chemical_arc_rf(asm_opt.thread_num, R_INF.total_reads); - } - try_rescue_overlaps(sources, reverse_sources, n_read, 4, asm_opt.is_ont); - - clean_graph(min_dp, sources, reverse_sources, n_read, readLen, mini_overlap_length, - max_hang_length, clean_round, gap_fuzz, min_ovlp_drop_ratio, max_ovlp_drop_ratio, - output_file_name, bubble_dist, read_graph, &ruIndex, &sg, &coverage_cut, cmk, 0); - - asg_destroy(sg); - free(coverage_cut); - } - - destory_R_to_U(&ruIndex); free(cmk); -} +#include +#include +#define __STDC_LIMIT_MACROS +#include +#include "Overlaps.h" +#include "ksort.h" +#include "Process_Read.h" +#include "CommandLines.h" +#include "Hash_Table.h" +#include "Correct.h" +#include "Purge_Dups.h" +#include "hic.h" +#include "kthread.h" +#include "tovlp.h" +#include "Assembly.h" +#include "rcut.h" +#include "horder.h" +#include "inter.h" +#include "gfa_ut.h" +#include "assert.h" +#include "khash.h" +#include "ecovlp.h" + +KHASH_SET_INIT_INT64(64) + +uint32_t debug_purge_dup = 0; + +KDQ_INIT(uint64_t) +KDQ_INIT(uint32_t) + +#define ma_hit_key_tn(a) ((a).tn) +KRADIX_SORT_INIT(hit_tn, ma_hit_t, ma_hit_key_tn, member_size(ma_hit_t, tn)) + +#define ma_hit_key_qns(a) ((a).qns) +KRADIX_SORT_INIT(hit_qns, ma_hit_t, ma_hit_key_qns, member_size(ma_hit_t, qns)) + + +#define asg_arc_key(a) ((a).ul) +KRADIX_SORT_INIT(asg, asg_arc_t, asg_arc_key, 8) + +#define generic_key(x) (x) +KRADIX_SORT_INIT(arch64, uint64_t, generic_key, 8) + +#define generic_key(x) (x) +KRADIX_SORT_INIT(arch32, uint32_t, generic_key, 4) + +///#define Hap_Align_key(a) ((((uint64_t)((a).is_color))<<63)|(((uint64_t)((a).t_id))<<32)|((uint64_t)((a).q_pos))) +///#define Hap_Align_key(a) ((((uint64_t)((a).is_color))<<32)|(((uint64_t)((a).t_id))<<33)|((uint64_t)((a).q_pos))) +#define Hap_Align_key(a) ((((uint64_t)((a).t_id))<<33)|((uint64_t)((a).q_pos))) +KRADIX_SORT_INIT(Hap_Align_sort, Hap_Align, Hap_Align_key, 8) + +#define u_trans_key(a) (((uint64_t)((a).qn)<<32) | ((uint64_t)((a).tn)<<1) | ((uint64_t)((a).rev))) +KRADIX_SORT_INIT(u_trans, u_trans_t, u_trans_key, 8) + +#define u_trans_qs_key(a) ((a).qs) +KRADIX_SORT_INIT(u_trans_qs, u_trans_t, u_trans_qs_key, member_size(u_trans_t, qs)) + +#define u_trans_ts_key(a) ((a).ts) +KRADIX_SORT_INIT(u_trans_ts, u_trans_t, u_trans_ts_key, member_size(u_trans_t, ts)) + +#define ha_mzl_t_key(p) ((p).x) +KRADIX_SORT_INIT(ha_mzl_t_srt1, ha_mzl_t, ha_mzl_t_key, member_size(ha_mzl_t, x)) + +#define Uc_beg(z) ((uint32_t)((z).a[0]>>32)) +#define Uc_end(z) ((uint32_t)((z).a[(z).n-1]>>32)^1) + +#define PHASE_SEP 64 +#define PHASE_SEF 2 +#define PHASE_SEP_RATE 0.04 +#define PHASE_MISS_LEN 1000000 +#define PHASE_MISS_N 8 +// #define PHASE_MISS_SLEN 500000 +// #define PHASE_MISS_SN 24 + +KSORT_INIT_GENERIC(uint32_t) + +void reduce_hamming_error_adv(ma_ug_t *iug, asg_t *sg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +int max_hang, int min_ovlp, long long gap_fuzz, R_to_U *ru, bubble_type* bub, uint32_t max_ext); +void print_vw_edge(asg_t *sg, uint32_t vid, uint32_t wid, const char *cmd); +void output_trio_graph_joint(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, +long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, +int min_ovlp, long long gap_fuzz, bub_label_t* b_mask_t, ma_ug_t **rhu0, ma_ug_t **rhu1, ug_opt_t *opt); + +typedef struct { + uint32_t d, tot, ma, p; + uint8_t in; +} tip_t; + +typedef struct { + kvec_t(uint32_t) r; + kvec_t(uint32_t) st; + tip_t *b; +}kv_tip_t; + +typedef struct { + asg64_v z; + asg64_v idx; +}u_trans_cluster; + +typedef struct { // global data structure for kt_pipeline() + ma_ug_t *ug; + asg_t *rg; + kv_u_trans_t *res; + kv_u_trans_t *ta; + uint64_t n_thread, ov_cutoff; + double small_ov_rate, sec_rate, sc_sec_rate; + asg64_v *srt; + u_trans_cluster *cu; +} u_trans_clean_t; + +typedef struct { + buf_t *a; asg_t *ref, *g; + uint64_t n_thread, max_dist; + asg64_v *rr; +} rd_hamming_t; + +typedef struct { + asg_t *ref; + asg_t *nsg; + ma_ug_t *nug; + uint32_t *o2n; + uint64_t *ugh; + asg64_v *srt; +} rd_hamming_fly_t; + +typedef struct { + // asg_t *ref; + // asg_t *ng; + ma_hit_t_alloc* src; + ma_sub_t *cov; + int32_t max_hang; + int32_t min_ovlp; + int32_t gap_fuzz; + asg32_v *srt; + uint8_t *vs; + // uint32_t *rs; + ma_ug_t *fg; + kvec_asg_arc_t_warp *ae; + uint32_t n_insert; +} rd_hamming_fly_simp_t; + +typedef struct { + ma_ug_t *ug; + asg_t *rg; + uint32_t *ridx; + uint64_t *ra; + uint64_t ridx_n, ra_n; +} dedup_idx_t; + +typedef struct { + uint32_t id0, id1; + uint64_t len; +} NN_t; + +typedef struct { + NN_t *a; + size_t n, m; +} kvect_N_t; + +typedef struct { + uint64_t m, n, is_c; + uint64_t *a; +} sec_t; + +typedef struct { + sec_t *a; + size_t n, m; + ma_ug_t *ctg; +} kvect_sec_t; + + +typedef struct { + All_reads *Rinf; + UC_Read *aux; + telo_end_t *u; + khash_t(64) *h; + int64_t min_sc, penalty, max_drop; +} telo_end_pip_t; + +///this value has been updated at the first line of build_string_graph_without_clean +long long min_thres; + +uint32_t print_untig_by_read(ma_ug_t *g, const char* name, uint32_t in, ma_hit_t_alloc* sources, +ma_hit_t_alloc* reverse_sources, const char* info); +int asg_pop_bubble_primary_trio(ma_ug_t *ug, uint64_t* i_max_dist, uint32_t positive_flag, uint32_t negative_flag, hap_cov_t *cov, utg_trans_t *o, uint32_t is_update_chain, rd_hamming_fly_simp_t *p); +kv_u_trans_t *get_utg_ovlp(ma_ug_t **ug, asg_t* read_g, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* new_rtg_edges, bub_label_t* b_mask_t, uint8_t* r_het); +void delete_useless_nodes(ma_ug_t **ug); + +static void mark_telo_ends(void *data, long i, int tid) // callback for kt_for() +{ + telo_end_pip_t *sl = (telo_end_pip_t *)data; + int64_t k, l, rlen, tlen, sc, max_sc, pen = sl->penalty, max_drop = sl->max_drop, min_sc = sl->min_sc, z; + uint64_t rid = i, c, x, mask = sl->u->mask, hit, xz; + UC_Read *rr = &(sl->aux[tid]); rlen = Get_READ_LENGTH((*(sl->Rinf)), rid); sl->u->hh[rid] = 0; + recover_UC_Read(rr, sl->Rinf, rid); assert((rr->length) == rlen); tlen = sl->u->tlen; + + for (k = l = 0, sc = max_sc = x = 0; k < rlen; k++) { // 5'-end, check CCCTAA + hit = 0; c = seq_nt6_table[(uint8_t)rr->seq[k]]; + if (c >= 0 && c <= 3) { // not N + x = (x<<2 | (c)) & mask; + if (((++l) >= tlen) && (kh_get(64, sl->h, x) != kh_end(sl->h))) {// x is at least 6bp long and is a telomere motif + hit = 1; + } + } else {l = 0, x = 0;} // N, ambiguous base + if(k >= tlen) sc += ((hit)?(1):(-pen)); + if (sc > max_sc) {max_sc = sc;} + else if ((max_sc - sc) > max_drop) {break;} + + if(max_sc >= min_sc) break; + } + + if(max_sc >= min_sc) { + for (k = l = 0, sc = max_sc = x = 0, xz = ((uint64_t)-1); k < rlen; k++) { // 5'-end, check CCCTAA + hit = 0; c = seq_nt6_table[(uint8_t)rr->seq[k]]; + if (c >= 0 && c <= 3) { // not N + x = (x<<2 | (c)) & mask; + if (((++l) >= tlen) && (kh_get(64, sl->h, x) != kh_end(sl->h))) {// x is at least 6bp long and is a telomere motif + if((xz != ((uint64_t)-1)) && (xz == x)) { + hit = 1; + } else { + for (z = 0, xz = sl->u->tm; (z < tlen) && (xz != x); z++) { + xz = (((xz>>((tlen-1)<<1))&(3ULL))|(xz<<2))&mask; + } + if((z < tlen) && (xz == x)) hit = 1; + } + } + } else {l = 0, x = 0;} // N, ambiguous base + + if(!hit) { + xz = ((uint64_t)-1); + } else { + xz = (((x>>((tlen-1)<<1))&(3ULL))|(x<<2))&mask; + } + if(k >= tlen) sc += ((hit)?(1):(-pen)); + if (sc > max_sc) {max_sc = sc;} + else if ((max_sc - sc) > max_drop) {break;} + + if(max_sc >= min_sc) break; + } + + if(max_sc >= min_sc) sl->u->hh[rid] |= 1; + } + + + + + + + for (k = rlen-1, l = 0, sc = max_sc = x = 0; k >= 0; --k) { // 3'-end + hit = 0; c = seq_nt6_table[(uint8_t)(RC_CHAR(rr->seq[k]))]; + if (c >= 0 && c <= 3) { // not N + x = (x<<2 | (c)) & mask; + if (((++l) >= tlen) && (kh_get(64, sl->h, x) != kh_end(sl->h))) {// x is at least 6bp long and is a telomere motif + hit = 1; + } + } else {l = 0, x = 0;} // N, ambiguous base + if((rlen - k) >= tlen) sc += ((hit)?(1):(-pen)); + if (sc > max_sc) {max_sc = sc;} + else if ((max_sc - sc) > max_drop) {break;} + + if(max_sc >= min_sc) break; + } + + if(max_sc >= min_sc) { + for (k = rlen-1, l = 0, sc = max_sc = x = 0, xz = ((uint64_t)-1); k >= 0 ; --k) { // 3'-end + hit = 0; c = seq_nt6_table[(uint8_t)(RC_CHAR(rr->seq[k]))]; + if (c >= 0 && c <= 3) { // not N + x = (x<<2 | (c)) & mask; + if (((++l) >= tlen) && (kh_get(64, sl->h, x) != kh_end(sl->h))) {// x is at least 6bp long and is a telomere motif + if((xz != ((uint64_t)-1)) && (xz == x)) { + hit = 1; + } else { + for (z = 0, xz = sl->u->tm; (z < tlen) && (xz != x); z++) { + xz = (((xz>>((tlen-1)<<1))&(3ULL))|(xz<<2))&mask; + } + if((z < tlen) && (xz == x)) hit = 1; + } + } + } else {l = 0, x = 0;} // N, ambiguous base + + if(!hit) { + xz = ((uint64_t)-1); + } else { + xz = (((x>>((tlen-1)<<1))&(3ULL))|(x<<2))&mask; + } + if((rlen - k) >= tlen) sc += ((hit)?(1):(-pen)); + if (sc > max_sc) {max_sc = sc;} + else if ((max_sc - sc) > max_drop) {break;} + + if(max_sc >= min_sc) break; + } + + if(max_sc >= min_sc) sl->u->hh[rid] |= 2; + } +} + + +telo_end_t* gen_telo_end_t(All_reads *in, const char* motif, int64_t min_sc, int64_t penalty, int64_t max_drop, uint64_t n_thread) +{ + uint64_t j, k, c, x; int absent; + telo_end_t* p = NULL; CALLOC(p, 1); + p->tlen = strlen(motif); p->mask = ((1ULL)<<(p->tlen<<1))-1; + + for (j = 0, p->tm = 0; j < p->tlen; ++j) { + c = seq_nt6_table[(uint8_t)motif[j]]; + assert(c >= 0 && c <= 3); + p->tm = (p->tm<<2)|(c); + } + p->n = in->total_reads; CALLOC(p->hh, p->n); + + telo_end_pip_t *aux; CALLOC(aux, 1); + aux->min_sc = min_sc; aux->max_drop = max_drop; + aux->penalty = penalty; if(aux->penalty < 0) aux->penalty = (aux->penalty)*-1; + aux->Rinf = in; aux->u = p; CALLOC(aux->aux, n_thread); + for (k = 0; k < n_thread; k++) init_UC_Read(&(aux->aux[k])); + aux->h = kh_init(64); kh_resize(64, aux->h, (p->tlen*2)); // hash table for all roations of the telomere motif + for (k = 0, x = p->tm; k < p->tlen; k++) { + kh_put(64, aux->h, x, &absent); + x = (((x>>((p->tlen-1)<<1))&(3ULL))|(x<<2))&p->mask; + } + assert(x == p->tm); + + kt_for(n_thread, mark_telo_ends, aux, p->n); + + for (k = 0; k < n_thread; k++) destory_UC_Read(&(aux->aux[k])); + free(aux->aux); kh_destroy(64, aux->h); free(aux); + + uint64_t t3, t5; + for (k = t3 = t5 = 0; k < p->n; k++) { + if(p->hh[k]&1) { + // fprintf(stderr, "%.*s(+)\n", (int)Get_NAME_LENGTH((*in), k), Get_NAME((*in), k)); + t5++; + } + if(p->hh[k]&2) { + // fprintf(stderr, "%.*s(-)\n", (int)Get_NAME_LENGTH((*in), k), Get_NAME((*in), k)); + t3++; + } + } + + + fprintf(stderr, "[M::%s::] ==> # 5'-telomeres::%lu, # 3'-telomeres::%lu, # tot::%lu, motif::%s, motif_len::%lu\n", __func__, t5, t3, p->n, motif, p->tlen); + // exit(1); + + return p; +} + +void destory_telo_end_t(telo_end_t *p) +{ + free(p->hh); +} + +void init_bub_label_t(bub_label_t* x, uint32_t n_thres, uint32_t n_reads) +{ + uint32_t i; + x->check_cross = 0; + x->bub_dist = 0; + x->n_thres = n_thres; + x->n_reads = n_reads; + x->g = NULL; + CALLOC(x->b, x->n_thres); + for (i = 0; i < x->n_thres; i++) + { + CALLOC(x->b[i].a, x->n_reads<<1); + } +} + +void reset_bub_label_t(bub_label_t* x, asg_t *g, uint64_t bub_dist, uint32_t check_cross) +{ + uint32_t i; + x->bub_dist = bub_dist; + x->check_cross = check_cross; + x->g = g; + if(x->n_reads < x->g->n_seq) + { + x->n_reads = x->g->n_seq; + for (i = 0; i < x->n_thres; i++) + { + REALLOC(x->b[i].a, x->n_reads<<1); + } + } + + for (i = 0; i < x->n_thres; i++) + { + x->b[i].S.n = x->b[i].b.n = x->b[i].e.n = 0; + memset(x->b[i].a, 0, (x->n_reads<<1)*sizeof(binfo_s_t)); + } +} + +void destory_bub_label_t(bub_label_t* x) +{ + uint32_t i; + for (i = 0; i < x->n_thres; i++) + { + free(x->b[i].a); + free(x->b[i].S.a); + free(x->b[i].b.a); + free(x->b[i].e.a); + } + free(x->b); +} + +void ma_hit_sort_tn(ma_hit_t *a, long long n) +{ + radix_sort_hit_tn(a, a + n); +} + +void ma_hit_sort_qns(ma_hit_t *a, long long n) +{ + radix_sort_hit_qns(a, a + n); +} + +void sort_kvec_t_u64_warp(kvec_t_u64_warp* u_vecs, uint32_t is_descend) +{ + radix_sort_arch64(u_vecs->a.a, u_vecs->a.a + u_vecs->a.n); + if(is_descend) + { + uint64_t i, uInfor; + for (i = 0; i < (u_vecs->a.n>>1); ++i) + { + uInfor = u_vecs->a.a[i]; + u_vecs->a.a[i] = u_vecs->a.a[u_vecs->a.n - i - 1]; + u_vecs->a.a[u_vecs->a.n - i - 1] = uInfor; + } + } +} + +///if ug == NULL, nsg should be equal to read_sg +inline uint32_t check_different_haps(asg_t *nsg, ma_ug_t *ug, asg_t *read_sg, +uint32_t v_0, uint32_t v_1, ma_hit_t_alloc* reverse_sources, buf_t* b_0, buf_t* b_1, +R_to_U* ruIndex, uint8_t* is_r_het, uint32_t min_edge_length, uint32_t stops_threshold) +{ + uint32_t vEnd, qn, tn, j, is_Unitig, uId; + long long ELen_0, ELen_1, tmp, max_stop_nodeLen, max_stop_baseLen; + + b_0->b.n = b_1->b.n = 0; + if(get_unitig(nsg, ug, v_0, &vEnd, &ELen_0, &tmp, &max_stop_nodeLen, &max_stop_baseLen, + stops_threshold, b_0) == LOOP) + { + return UNAVAILABLE; + } + if(get_unitig(nsg, ug, v_1, &vEnd, &ELen_1, &tmp, &max_stop_nodeLen, &max_stop_baseLen, + stops_threshold, b_1) == LOOP) + { + return UNAVAILABLE; + } + if(ELen_0<=min_edge_length || ELen_1<=min_edge_length) return UNAVAILABLE; + + rIdContig b_max, b_min; + b_max.b_0 = b_min.b_0 = NULL; + b_max.offset = b_max.readI = b_max.untigI = 0; + b_min.offset = b_min.readI = b_min.untigI = 0; + + if(ELen_0<=ELen_1) + { + b_min.b_0 = b_0; + b_max.b_0 = b_1; + } + else + { + b_min.b_0 = b_1; + b_max.b_0 = b_0; + } + + uint32_t max_count = 0, min_count = 0, n_het = 0, n_hom = 0; + ma_utg_t *node_min = NULL, *node_max = NULL; + if(ug != NULL) + { + /*****************************label all unitigs****************************************/ + for (b_max.untigI = 0; b_max.untigI < b_max.b_0->b.n; b_max.untigI++) + { + node_max = &(ug->u.a[b_max.b_0->b.a[b_max.untigI]>>1]); + ///each read + for (b_max.readI = 0; b_max.readI < node_max->n; b_max.readI++) + { + qn = (node_max->a[b_max.readI]>>33); + set_R_to_U(ruIndex, qn, (b_max.b_0->b.a[b_max.untigI]>>1), 1, &(read_sg->seq[qn].c)); + } + } + /*****************************label all unitigs****************************************/ + + ///each unitig + for (b_min.untigI = 0; b_min.untigI < b_min.b_0->b.n; b_min.untigI++) + { + + node_min = &(ug->u.a[(b_min.b_0->b.a[b_min.untigI]>>1)]); + + ///each read + for (b_min.readI = 0; b_min.readI < node_min->n; b_min.readI++) + { + qn = node_min->a[b_min.readI]>>33; + + /************************BUG: don't forget****************************/ + if(reverse_sources[qn].length > 0) min_count++; + if((is_r_het[qn] & C_HET) || (is_r_het[qn] & P_HET)) n_het++; + n_hom++; + /************************BUG: don't forget****************************/ + for (j = 0; j < (long long)reverse_sources[qn].length; j++) + { + tn = Get_tn(reverse_sources[qn].buffer[j]); + if(read_sg->seq[tn].del == 1) + { + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_sg->seq[tn].del == 1) continue; + } + + get_R_to_U(ruIndex, tn, &uId, &is_Unitig); + if(uId!=(uint32_t)-1 && is_Unitig == 1) + { + // if(v_0==510 && v_1==67) fprintf(stderr, "###untigI-%u, readI-%um, un-%u\n", b_min.untigI, b_min.readI, (uint32_t)node_min->n); + max_count++; + break; + } + } + } + } + /*****************************label all unitigs****************************************/ + for (b_max.untigI = 0; b_max.untigI < b_max.b_0->b.n; b_max.untigI++) + { + node_max = &(ug->u.a[b_max.b_0->b.a[b_max.untigI]>>1]); + ///each read + for (b_max.readI = 0; b_max.readI < node_max->n; b_max.readI++) + { + qn = (node_max->a[b_max.readI]>>33); + ruIndex->index[qn] = (uint32_t)-1; + } + } + /*****************************label all unitigs****************************************/ + } + else + { + /*****************************label all reads****************************************/ + for (b_max.untigI = 0; b_max.untigI < b_max.b_0->b.n; b_max.untigI++) + { + qn = (b_max.b_0->b.a[b_max.untigI]>>1); + set_R_to_U(ruIndex, qn, 1, 1, &(read_sg->seq[qn].c)); + } + /*****************************label all reads****************************************/ + + ///each read + for (b_min.untigI = 0; b_min.untigI < b_min.b_0->b.n; b_min.untigI++) + { + qn = (b_min.b_0->b.a[b_min.untigI]>>1); + + /************************BUG: don't forget****************************/ + if(reverse_sources[qn].length > 0) min_count++; + if((is_r_het[qn] & C_HET) || (is_r_het[qn] & P_HET)) n_het++; + n_hom++; + /************************BUG: don't forget****************************/ + + for (j = 0; j < (long long)reverse_sources[qn].length; j++) + { + tn = Get_tn(reverse_sources[qn].buffer[j]); + if(nsg->seq[tn].del == 1) + { + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || nsg->seq[tn].del == 1) continue; + } + + + get_R_to_U(ruIndex, tn, &uId, &is_Unitig); + if(uId!=(uint32_t)-1 && is_Unitig == 1) + { + max_count++; + break; + } + } + } + + /*****************************label all reads****************************************/ + for (b_max.untigI = 0; b_max.untigI < b_max.b_0->b.n; b_max.untigI++) + { + qn = (b_max.b_0->b.a[b_max.untigI]>>1); + ruIndex->index[qn] = (uint32_t)-1; + } + /*****************************label all reads****************************************/ + } + + if(min_count == 0) return UNAVAILABLE; + if(max_count > min_count*asm_opt.purge_simi_thres && n_het >= n_hom*HET_HOM_RATE) return PLOID; + return NON_PLOID; +} + +inline void calculate_match_cover(uint32_t *b, uint32_t b_n, asg_t *nsg, ma_ug_t *ug, asg_t *read_sg, +ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, uint32_t *min_count, uint32_t *max_count) +{ + ma_utg_t *u = NULL; + uint32_t ui, ri, ori, qn, tn, v, w, k, nv, j, is_Unitig, uId; + asg_arc_t *av = NULL; + long long offset, r_beg, r_end, inp_beg, inp_end, hap_beg, hap_end, ovlp, hap_match, inp_match, l; + (*min_count) = (*max_count) = 0; + inp_beg = -1; inp_end = -2; + hap_beg = -1; hap_end = -2; + inp_match = hap_match = 0; + if(ug) + { + for (ui = 0, offset = 0; ui < b_n; ui++) + { + u = &(ug->u.a[(b[ui]>>1)]); + ori = b[ui]&1; + ///each read + for (ri = 0; ri < u->n; ri++) + { + qn = (ori==1?((uint64_t)((u->a[u->n-ri-1])))>>33:((uint64_t)(u->a[ri]))>>33); + r_beg = offset; r_end = offset + (long long)(read_sg->seq[qn].len) - 1; + offset += (ori==1?(uint32_t)(u->a[u->n-ri-1]):(uint32_t)(u->a[ri])); + if(ori==1) offset -= (long long)(read_sg->seq[qn].len); + + if(reverse_sources[qn].length > 0) + { + // min_count++; + if(r_beg <= hap_end) + { + hap_end = MAX(hap_end, r_end); + } + else + { + ovlp = hap_end - hap_beg + 1; + hap_match += (ovlp >= 0? ovlp : 0); + hap_beg = r_beg; hap_end = r_end; + } + } + + for (j = 0; j < reverse_sources[qn].length; j++) + { + tn = Get_tn(reverse_sources[qn].buffer[j]); + if(read_sg->seq[tn].del == 1) + { + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_sg->seq[tn].del == 1) continue; + } + + get_R_to_U(ruIndex, tn, &uId, &is_Unitig); + if(uId!=(uint32_t)-1 && is_Unitig == 1) + { + ///max_count++; + break; + } + } + + if(j < reverse_sources[qn].length) + { + if(r_beg <= inp_end) + { + inp_end = MAX(inp_end, r_end); + } + else + { + ovlp = inp_end - inp_beg + 1; + inp_match += (ovlp >= 0? ovlp : 0); + inp_beg = r_beg; inp_end = r_end; + } + } + } + + if(ui+1 < b_n) + { + v = b[ui]; w = b[ui+1]; + av = asg_arc_a(nsg, v); + nv = asg_arc_n(nsg, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + offset -= av[k].ol; + break; + } + } + if(k >= nv) fprintf(stderr, "ERROR-mc\n"); + } + } + } + else + { + for (ui = 0, offset = 0; ui < b_n; ui++) + { + qn = b[ui]>>1; + r_beg = offset; r_end = offset + (long long)(read_sg->seq[qn].len) - 1; + l = read_sg->seq[qn].len; + if(ui+1 < b_n) + { + v = b[ui]; w = b[ui+1]; + av = asg_arc_a(read_sg, v); + nv = asg_arc_n(read_sg, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + l = asg_arc_len(av[k]); + break; + } + } + if(k >= nv) fprintf(stderr, "ERROR-mc\n"); + } + offset += l; + + if(reverse_sources[qn].length > 0) + { + // min_count++; + if(r_beg <= hap_end) + { + hap_end = MAX(hap_end, r_end); + } + else + { + ovlp = hap_end - hap_beg + 1; + hap_match += (ovlp >= 0? ovlp : 0); + hap_beg = r_beg; hap_end = r_end; + } + } + + for (j = 0; j < reverse_sources[qn].length; j++) + { + tn = Get_tn(reverse_sources[qn].buffer[j]); + if(read_sg->seq[tn].del == 1) + { + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_sg->seq[tn].del == 1) continue; + } + + get_R_to_U(ruIndex, tn, &uId, &is_Unitig); + if(uId!=(uint32_t)-1 && is_Unitig == 1) + { + ///max_count++; + break; + } + } + + if(j < reverse_sources[qn].length) + { + if(r_beg <= inp_end) + { + inp_end = MAX(inp_end, r_end); + } + else + { + ovlp = inp_end - inp_beg + 1; + inp_match += (ovlp >= 0? ovlp : 0); + inp_beg = r_beg; inp_end = r_end; + } + } + } + } + + ovlp = inp_end - inp_beg + 1; + inp_match += (ovlp >= 0? ovlp : 0); + + ovlp = hap_end - hap_beg + 1; + hap_match += (ovlp >= 0? ovlp : 0); + + (*max_count) = inp_match; + (*min_count) = hap_match; +} + +asg_t *asg_init(void) +{ + return (asg_t*)calloc(1, sizeof(asg_t)); +} + +void asg_destroy(asg_t *g) +{ + if (g == 0) return; + free(g->seq); free(g->idx); free(g->arc); free(g->seq_vis); + + if(g->n_F_seq > 0 && g->F_seq) + { + uint32_t i = 0; + for (i = 0; i < g->n_F_seq; i++) + { + if(g->F_seq[i].a) free(g->F_seq[i].a); + if(g->F_seq[i].s) free(g->F_seq[i].s); + } + + free(g->F_seq); + } + + + free(g); +} + +void asg_arc_sort(asg_t *g) +{ + radix_sort_asg(g->arc, g->arc + g->n_arc); +} + + +void add_overlaps(ma_hit_t_alloc* source_paf, ma_hit_t_alloc* dest_paf, uint64_t* source_index, long long listLen) +{ + long long i; + ma_hit_t* tmp; + for (i = 0; i < listLen; i++) + { + tmp = &(source_paf->buffer[(uint32_t)(source_index[i])]); + add_ma_hit_t_alloc(dest_paf, tmp); + } +} + + +void remove_overlaps(ma_hit_t_alloc* source_paf, uint64_t* source_index, long long listLen) +{ + long long i, m; + for (i = 0; i < listLen; i++) + { + source_paf->buffer[(uint32_t)(source_index[i])].qns = (uint64_t)(-1); + } + + m = 0; + for (i = 0; i < source_paf->length; i++) + { + if(source_paf->buffer[i].qns != (uint64_t)(-1)) + { + source_paf->buffer[m] = source_paf->buffer[i]; + m++; + } + } + source_paf->length = m; +} + + +void add_overlaps_from_different_sources(ma_hit_t_alloc* source_paf_list, ma_hit_t_alloc* dest_paf, +uint64_t* source_index, long long listLen) +{ + long long i; + ma_hit_t ele; + ma_hit_t* tmp; + uint32_t source_n, source_i; + for (i = 0; i < listLen; i++) + { + source_n = source_index[i] >> 32; + source_i = (uint32_t)(source_index[i]); + tmp = &(source_paf_list[source_n].buffer[source_i]); + + ele.del = 0; + ele.rev = tmp->rev; + ele.qns = Get_tn((*tmp)); + ele.qns = ele.qns << 32; + ele.qns = ele.qns | (uint64_t)(Get_ts((*tmp))); + ele.qe = Get_te((*tmp)); + + ele.tn = Get_qn((*tmp)); + ele.ts = Get_qs((*tmp)); + ele.te = Get_qe((*tmp)); + + ele.bl = R_INF.read_length[ele.tn]; + ele.ml = tmp->ml; + ele.el = tmp->el; + ele.no_l_indel = tmp->no_l_indel; + + add_ma_hit_t_alloc(dest_paf, &ele); + } +} + + + +void ma_ug_destroy(ma_ug_t *ug) +{ + uint32_t i; + if (ug == 0) return; + for (i = 0; i < ug->u.n; ++i) { + free(ug->u.a[i].a); + free(ug->u.a[i].s); + } + free(ug->u.a); + asg_destroy(ug->g); + kv_destroy(ug->occ); + free(ug); +} + +uint64_t *asg_arc_index_core(size_t max_seq, size_t n, const asg_arc_t *a) +{ + size_t i, last; + uint64_t *idx; + idx = (uint64_t*)calloc(max_seq * 2, 8); + + + /** + * ul: |____________31__________|__________1___________|______________32_____________| + qns direction of overlap length of this node (not overlap length) + **/ + ///so if we use high 32-bit, we store the index of each qn with two direction + for (i = 1, last = 0; i <= n; ++i) + if (i == n || a[i-1].ul>>32 != a[i].ul>>32) + idx[a[i-1].ul>>32] = (uint64_t)last<<32 | (i - last), last = i; + + + return idx; +} + +void asg_arc_index(asg_t *g) +{ + if (g->idx) free(g->idx); + g->idx = asg_arc_index_core(g->n_seq, g->n_arc, g->arc); +} + +void asg_seq_set(asg_t *g, int sid, int len, int del) +{ + ///just malloc size + if (sid >= (int)g->m_seq) { + g->m_seq = sid + 1; + kv_roundup32(g->m_seq); + g->seq = (asg_seq_t*)realloc(g->seq, g->m_seq * sizeof(asg_seq_t)); + } + + if (sid >= g->n_seq) g->n_seq = sid + 1; + + g->seq[sid].del = !!del; + g->seq[sid].len = len; +} + +ma_utg_t* asg_F_seq_set(asg_t *g, int iid) +{ + if(iid < (int)g->r_seq) return NULL; + uint32_t index = iid - g->r_seq, pre_n_F_seq = g->n_F_seq; + + ///just malloc size + if (index >= g->n_F_seq) { + g->n_F_seq = index + 1; + kv_roundup32(g->n_F_seq); + g->F_seq = (ma_utg_t*)realloc(g->F_seq, g->n_F_seq*sizeof(ma_utg_t)); + memset(g->F_seq + pre_n_F_seq, 0, sizeof(ma_utg_t)*(g->n_F_seq-pre_n_F_seq)); + } + + return &(g->F_seq[index]); +} + + + +// hard remove arcs marked as "del" +void asg_arc_rm(asg_t *g) +{ + /** + p->ul: |____________31__________|__________1___________|______________32_____________| + qns direction of overlap length of this node (not overlap length) + p->v : |___________31___________|__________1___________| + tns relative strand between query and target + p->ol: overlap length + **/ + uint32_t e, n; + ///just clean arc requiring: 1. arc it self must be available 2. both the query and target are available + for (e = n = 0; e < g->n_arc; ++e) { + //u and v is the read id + uint32_t u = g->arc[e].ul>>32, v = g->arc[e].v; + if (!g->arc[e].del && !g->seq[u>>1].del && !g->seq[v>>1].del) + g->arc[n++] = g->arc[e]; + } + if (n < g->n_arc) { // arc index is out of sync + if (g->idx) free(g->idx); + g->idx = 0; + } + g->n_arc = n; +} + +void asg_cleanup(asg_t *g) +{ + ///remove overlaps, instead of reads + ///remove edges with del, and free idx + asg_arc_rm(g); + if (!g->is_srt) { + /** + * sort by ul, that is, sort by qns + direction + * ul: |____________31__________|__________1___________|______________32_____________| + qns direction of overlap length of this node (not overlap length) + **/ + asg_arc_sort(g); + g->is_srt = 1; + } + ///index the overlaps in graph with query id + if (g->idx == 0) asg_arc_index(g); +} + + + +// delete multi-arcs +/** + * remove edges like: v has two out-edges to w +**/ +int asg_arc_del_multi(asg_t *g) +{ + //the number of nodes are number of read times 2 + uint32_t *cnt, n_vtx = g->n_seq * 2, n_multi = 0, v; + cnt = (uint32_t*)calloc(n_vtx, 4); + for (v = 0; v < n_vtx; ++v) { + ///out-nodes of v + asg_arc_t *av = asg_arc_a(g, v); + int32_t i, nv = asg_arc_n(g, v); + ///if v just have one out-node, there is no muti-edge + if (nv < 2) continue; + for (i = nv - 1; i >= 0; --i) ++cnt[av[i].v]; + for (i = nv - 1; i >= 0; --i) + if (--cnt[av[i].v] != 0) + av[i].del = 1, ++n_multi; + } + free(cnt); + if (n_multi) asg_cleanup(g); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d multi-arcs\n", __func__, n_multi); + } + + return n_multi; +} + +// remove asymmetric arcs: u->v is present, but v'->u' not +int asg_arc_del_asymm(asg_t *g) +{ + uint32_t e, n_asymm = 0; + ///g->n_arc is the number of overlaps + for (e = 0; e < g->n_arc; ++e) { + uint32_t v = g->arc[e].v^1, u = g->arc[e].ul>>32^1; + 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 == u) break; + if (i == nv) g->arc[e].del = 1, ++n_asymm; + } + if (n_asymm) asg_cleanup(g); + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d asymmetric arcs\n", __func__, n_asymm); + } + return n_asymm; +} + + +void asg_symm(asg_t *g) +{ + asg_arc_del_multi(g); + asg_arc_del_asymm(g); + g->is_symm = 1; +} + +void init_ma_hit_t_alloc(ma_hit_t_alloc* x) +{ + x->size = 0; + x->buffer = NULL; + x->length = 0; + x->is_fully_corrected = 0; + x->is_abnormal = 0; +} + +void clear_ma_hit_t_alloc(ma_hit_t_alloc* x) +{ + x->length = 0; +} + +void resize_ma_hit_t_alloc(ma_hit_t_alloc* x, uint32_t size) +{ + if (size > x->size) { + x->size = size; + kroundup32(x->size); + REALLOC(x->buffer, x->size); + } +} + +void destory_ma_hit_t_alloc(ma_hit_t_alloc* x) +{ + free(x->buffer); +} + +void add_ma_hit_t_alloc(ma_hit_t_alloc* x, ma_hit_t* element) +{ + if (x->length + 1 > x->size) { + x->size = x->length + 1; + kroundup32(x->size); + REALLOC(x->buffer, x->size); + } + x->buffer[x->length++] = *element; +} + + +long long get_specific_overlap(ma_hit_t_alloc* x, uint32_t qn, uint32_t tn) +{ + long long i; + for (i = 0; i < x->length; i++) + { + if(x->buffer[i].tn == tn + && + ((uint32_t)(x->buffer[i].qns>>32)) == qn) + { + return i; + } + } + + return -1; +} + + + +void set_reverse_overlap(ma_hit_t* dest, ma_hit_t* source) +{ + dest->qns = Get_tn(*source); + dest->qns = dest->qns << 32; + dest->qns = dest->qns | Get_ts(*source); + dest->qe = Get_te(*source); + + + dest->tn = Get_qn(*source); + dest->ts = Get_qs(*source); + dest->te = Get_qe(*source); + + dest->rev = source->rev; + dest->el = source->el; + + + /****************************may have bugs********************************/ + /** + if(dest->ml == 0 || source->ml == 0) + { + dest->ml = source->ml = 0; + } + else + { + dest->ml = source->ml = 1; + } + + + if(dest->no_l_indel == 0 || source->no_l_indel == 0) + { + dest->no_l_indel = source->no_l_indel = 0; + } + else + { + dest->no_l_indel = source->no_l_indel = 1; + } + **/ + dest->ml = source->ml; + dest->no_l_indel = source->no_l_indel; + /****************************may have bugs********************************/ + dest->bl = source->bl/**Get_qe(*dest) - Get_qs(*dest)**/; +} + + + + +void normalize_ma_hit_t_single_side_advance(ma_hit_t_alloc* sources, long long num_sources, uint32_t recuse_el, uint8_t *cmk) +{ + double startTime = Get_T(); + + long long i, j, index; + uint32_t qn, tn, is_del = 0; + long long qLen_0, qLen_1; + ma_hit_t ele; + for (i = 0; i < num_sources; i++) + { + + for (j = 0; j < sources[i].length; j++) + { + qn = Get_qn(sources[i].buffer[j]); + tn = Get_tn(sources[i].buffer[j]); + + // sources[i].buffer[j].bl = Get_qe(sources[i].buffer[j]) - Get_qs(sources[i].buffer[j]); + + ///if(sources[i].buffer[j].del) continue; + + index = get_specific_overlap(&(sources[tn]), tn, qn); + + + ///if(index != -1 && sources[tn].buffer[index].del == 0) + if(index != -1) { + is_del = 0; + if(sources[i].buffer[j].del || sources[tn].buffer[index].del) is_del = 1; + + qLen_0 = Get_qe(sources[i].buffer[j]) - Get_qs(sources[i].buffer[j]); + qLen_1 = Get_qe(sources[tn].buffer[index]) - Get_qs(sources[tn].buffer[index]); + + if(qLen_0 == qLen_1) { + ///qn must be not equal to tn + ///make sources[qn] = sources[tn] if qn > tn + if(qn < tn) { + set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); + } + } else if(qLen_0 > qLen_1) { + set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); + } + + if(recuse_el && sources[i].buffer[j].el && sources[tn].buffer[index].el) is_del = 0; + if(cmk && (cmk[qn] <= asm_opt.chemical_cov/**FORCE_CUT**/ || cmk[tn] <= asm_opt.chemical_cov/**FORCE_CUT**/)) is_del = 1; + + sources[i].buffer[j].del = is_del; + sources[tn].buffer[index].del = is_del; + } else {///means this edge just occurs in one direction + is_del = 1; + set_reverse_overlap(&ele, &(sources[i].buffer[j])); + if(recuse_el && sources[i].buffer[j].el && ele.el) is_del = 0; + if(cmk && (cmk[qn] <= asm_opt.chemical_cov/**FORCE_CUT**/ || cmk[tn] <= asm_opt.chemical_cov/**FORCE_CUT**/)) is_del = 1; + sources[i].buffer[j].del = ele.del = is_del; + add_ma_hit_t_alloc(&(sources[tn]), &ele); + } + } + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2fs\n\n", __func__, Get_T()-startTime); + } +} + + +typedef struct { + kvec_t_u64_warp *buf; + ma_hit_t_alloc* src; + int64_t n_thread; +} ma_hit_t_aux; + +static void update_ma_hit_t_norm(void *data, long i, int tid) // callback for kt_for() +{ + ma_hit_t_aux *sl = (ma_hit_t_aux *)data; + ma_hit_t_alloc* src = sl->src; + uint64_t z, qn, tn, is_del = 0; + int64_t idx, qLen_0, qLen_1; + + for (z = 0; z < src[i].length; z++) { + qn = Get_qn(src[i].buffer[z]); + tn = Get_tn(src[i].buffer[z]); + is_del = 0; idx = get_specific_overlap(&(src[tn]), tn, qn); + + if(idx != -1 && qn <= tn) { ///qn must be not equal to tn + if(src[i].buffer[z].del || src[tn].buffer[idx].del) is_del = 1; + qLen_0 = Get_qe(src[i].buffer[z]) - Get_qs(src[i].buffer[z]); + qLen_1 = Get_qe(src[tn].buffer[idx]) - Get_qs(src[tn].buffer[idx]); + + if(qLen_0 == qLen_1) { + ///qn must be not equal to tn + ///make sources[qn] = sources[tn] if qn > tn + set_reverse_overlap(&(src[tn].buffer[idx]), &(src[i].buffer[z])); + } + else if(qLen_0 > qLen_1) { + set_reverse_overlap(&(src[tn].buffer[idx]), &(src[i].buffer[z])); + } else { + set_reverse_overlap(&(src[i].buffer[z]), &(src[tn].buffer[idx])); + } + + src[i].buffer[z].del = is_del; src[tn].buffer[idx].del = is_del; + } + else ///means this edge just occurs in one direction + { + tn = i; tn <<= 32; tn |= z; + kv_push(uint64_t, sl->buf[tid].a, tn); + src[i].buffer[z].del = 1; + } + } +} + +void normalize_ma_hit_t_single_side_advance_mult(ma_hit_t_alloc* src, int64_t n_src, int64_t n_thread) +{ + ma_hit_t_aux aux; int64_t k; uint64_t z; ma_hit_t e; + aux.n_thread = n_thread; aux.src = src; CALLOC(aux.buf, aux.n_thread); + + kt_for(aux.n_thread, update_ma_hit_t_norm, &aux, n_src); + + for (k = 0; k < aux.n_thread; k++) { + for (z = 0; z < aux.buf[k].a.n; z++) { + set_reverse_overlap(&e, &(src[aux.buf[k].a.a[z]>>32].buffer[(uint32_t)(aux.buf[k].a.a[z])])); + src[aux.buf[k].a.a[z]>>32].buffer[(uint32_t)(aux.buf[k].a.a[z])].del = e.del = 1; + add_ma_hit_t_alloc(&(src[Get_qn(e)]), &e); + } + free(aux.buf[k].a.a); + } + free(aux.buf); +} + + + +void get_end_match_length(ma_hit_t* edge, UC_Read* query, UC_Read* target, +uint32_t* left, uint32_t* right) +{ + (*left) = (*right) = 0; + + uint32_t query_beg, query_end, target_beg, target_end, targetLen, oLen; + long long i; + targetLen = Get_READ_LENGTH(R_INF, Get_tn(*edge)); + query_beg = Get_qs(*edge); + query_end = Get_qe(*edge)-1; + recover_UC_Read(query, &R_INF, Get_qn(*edge)); + + if(edge->rev) + { + target_beg = targetLen-(Get_te(*edge)-1)-1; + target_end = targetLen-Get_ts(*edge)-1; + recover_UC_Read_RC(target, &R_INF, Get_tn(*edge)); + } + else + { + target_beg = Get_ts(*edge); + target_end = Get_te(*edge)-1; + recover_UC_Read(target, &R_INF, Get_tn(*edge)); + } + + oLen = Get_qe(*edge) - Get_qs(*edge); + /***************************left*******************************/ + for (i = 0; i < oLen; i++) + { + if(query->seq[query_beg+i]!=target->seq[target_beg+i]) break; + (*left)++; + } + /***************************left*******************************/ + + /***************************right*******************************/ + for (i = 0; i < oLen; i++) + { + if(query->seq[query_end-i]!=target->seq[target_end-i]) break; + (*right)++; + } + /***************************right*******************************/ + +} + +void normalize_ma_hit_t_single_side_aggressive(ma_hit_t_alloc* sources, long long num_sources) +{ + double startTime = Get_T(); + + ///long long debug_prefect = 0, debug_not_bad = 0, debug_bad = 0; + + UC_Read query, target; + init_UC_Read(&query); + init_UC_Read(&target); + + long long i, j, index; + uint32_t qn, tn, queryLeftLen, queryRightLen, targetLeftLen, targetRightLen; + long long qLen_0, qLen_1, m; + for (i = 0; i < num_sources; i++) + { + + m = 0; + for (j = 0; j < sources[i].length; j++) + { + qn = Get_qn(sources[i].buffer[j]); + tn = Get_tn(sources[i].buffer[j]); + + // sources[i].buffer[j].bl = Get_qe(sources[i].buffer[j]) - Get_qs(sources[i].buffer[j]); + + index = get_specific_overlap(&(sources[tn]), tn, qn); + + + if(index != -1) + { + // sources[tn].buffer[index].bl = Get_qe(sources[tn].buffer[index]) + // - Get_qs(sources[tn].buffer[index]); + + if(Get_qs(sources[i].buffer[j]) == Get_ts(sources[tn].buffer[index]) + && + Get_qe(sources[i].buffer[j]) == Get_te(sources[tn].buffer[index]) + && + Get_ts(sources[i].buffer[j]) == Get_qs(sources[tn].buffer[index]) + && + Get_te(sources[i].buffer[j]) == Get_qe(sources[tn].buffer[index]) + && + sources[i].buffer[j].rev == sources[tn].buffer[index].rev) + { + ///actually two edges are same, here is just to unify el, ml, no_l_indel, bl + set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); + + sources[i].buffer[m] = sources[i].buffer[j]; + m++; + + ///debug_prefect++; + continue; + } + + + get_end_match_length(&(sources[i].buffer[j]), &query, &target, + &queryLeftLen, &queryRightLen); + + get_end_match_length(&(sources[tn].buffer[index]), &query, &target, + &targetLeftLen, &targetRightLen); + + ///query is right + if(queryLeftLen>0 && queryRightLen>0 && (targetLeftLen==0 || targetRightLen==0)) + { + set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); + + sources[i].buffer[m] = sources[i].buffer[j]; + m++; + + ///debug_not_bad++; + continue; + } + + + ///target is right + if(targetLeftLen>0 && targetRightLen>0 && (queryLeftLen==0 || queryRightLen==0)) + { + set_reverse_overlap(&(sources[i].buffer[j]), &(sources[tn].buffer[index])); + + sources[i].buffer[m] = sources[i].buffer[j]; + m++; + + ///debug_not_bad++; + continue; + } + + + ///query is right + if((queryLeftLen+queryRightLen)>(targetLeftLen+targetRightLen)) + { + set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); + }///target is right + else if((queryLeftLen+queryRightLen)<(targetLeftLen+targetRightLen)) + { + set_reverse_overlap(&(sources[i].buffer[j]), &(sources[tn].buffer[index])); + } + else + { + qLen_0 = Get_qe(sources[i].buffer[j]) - Get_qs(sources[i].buffer[j]); + qLen_1 = Get_qe(sources[tn].buffer[index]) - Get_qs(sources[tn].buffer[index]); + if(qLen_0 >= qLen_1) + { + set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); + } + else + { + set_reverse_overlap(&(sources[i].buffer[j]), &(sources[tn].buffer[index])); + } + } + + sources[i].buffer[m] = sources[i].buffer[j]; + m++; + + ///debug_bad++; + } + } + + sources[i].length = m; + } + + destory_UC_Read(&query); + destory_UC_Read(&target); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2fs\n\n", __func__, Get_T()-startTime); + } + + // fprintf(stderr, "debug_prefect: %ld, debug_not_bad: %ld, debug_bad: %ld\n", debug_prefect, debug_not_bad, + // debug_bad); +} + + +void normalize_ma_hit_t_single_side(ma_hit_t_alloc* sources, long long num_sources) +{ + double startTime = Get_T(); + + ///long long debug_prefect = 0, debug_not_bad = 0, debug_bad = 0; + + UC_Read query, target; + init_UC_Read(&query); + init_UC_Read(&target); + + long long i, j, index; + uint32_t qn, tn, queryLeftLen, queryRightLen, targetLeftLen, targetRightLen; + long long qLen_0, qLen_1, m; + for (i = 0; i < num_sources; i++) + { + + m = 0; + for (j = 0; j < sources[i].length; j++) + { + qn = Get_qn(sources[i].buffer[j]); + tn = Get_tn(sources[i].buffer[j]); + + // sources[i].buffer[j].bl = Get_qe(sources[i].buffer[j]) - Get_qs(sources[i].buffer[j]); + + index = get_specific_overlap(&(sources[tn]), tn, qn); + + + if(index != -1) + { + // sources[tn].buffer[index].bl = Get_qe(sources[tn].buffer[index]) + // - Get_qs(sources[tn].buffer[index]); + + if(Get_qs(sources[i].buffer[j]) == Get_ts(sources[tn].buffer[index]) + && + Get_qe(sources[i].buffer[j]) == Get_te(sources[tn].buffer[index]) + && + Get_ts(sources[i].buffer[j]) == Get_qs(sources[tn].buffer[index]) + && + Get_te(sources[i].buffer[j]) == Get_qe(sources[tn].buffer[index]) + && + sources[i].buffer[j].rev == sources[tn].buffer[index].rev) + { + ///actually two edges are same, here is just to unify el, ml, no_l_indel, bl + set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); + + sources[i].buffer[m] = sources[i].buffer[j]; + m++; + + ///debug_prefect++; + continue; + } + + + get_end_match_length(&(sources[i].buffer[j]), &query, &target, + &queryLeftLen, &queryRightLen); + + get_end_match_length(&(sources[tn].buffer[index]), &query, &target, + &targetLeftLen, &targetRightLen); + + ///query is right + if(queryLeftLen>0 && queryRightLen>0 && (targetLeftLen==0 || targetRightLen==0)) + { + set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); + + sources[i].buffer[m] = sources[i].buffer[j]; + m++; + + ///debug_not_bad++; + continue; + } + + + ///target is right + if(targetLeftLen>0 && targetRightLen>0 && (queryLeftLen==0 || queryRightLen==0)) + { + set_reverse_overlap(&(sources[i].buffer[j]), &(sources[tn].buffer[index])); + + sources[i].buffer[m] = sources[i].buffer[j]; + m++; + + ///debug_not_bad++; + continue; + } + + /** + ///query is right + if((queryLeftLen+queryRightLen)>(targetLeftLen+targetRightLen)) + { + set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); + }///target is right + else if((queryLeftLen+queryRightLen)<(targetLeftLen+targetRightLen)) + { + set_reverse_overlap(&(sources[i].buffer[j]), &(sources[tn].buffer[index])); + } + else + { + qLen_0 = Get_qe(sources[i].buffer[j]) - Get_qs(sources[i].buffer[j]); + qLen_1 = Get_qe(sources[tn].buffer[index]) - Get_qs(sources[tn].buffer[index]); + if(qLen_0 >= qLen_1) + { + set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); + } + else + { + set_reverse_overlap(&(sources[i].buffer[j]), &(sources[tn].buffer[index])); + } + } + **/ + + + + qLen_0 = Get_qe(sources[i].buffer[j]) - Get_qs(sources[i].buffer[j]); + qLen_1 = Get_qe(sources[tn].buffer[index]) - Get_qs(sources[tn].buffer[index]); + if(qLen_0 >= qLen_1) + { + set_reverse_overlap(&(sources[tn].buffer[index]), &(sources[i].buffer[j])); + } + else + { + set_reverse_overlap(&(sources[i].buffer[j]), &(sources[tn].buffer[index])); + } + + + sources[i].buffer[m] = sources[i].buffer[j]; + m++; + + ///debug_bad++; + } + } + + sources[i].length = m; + } + + destory_UC_Read(&query); + destory_UC_Read(&target); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2fs\n\n", __func__, Get_T()-startTime); + } + + // fprintf(stderr, "debug_prefect: %ld, debug_not_bad: %ld, debug_bad: %ld\n", debug_prefect, debug_not_bad, + // debug_bad); +} + + + +void drop_edges_by_trio(ma_hit_t_alloc* sources, long long num_sources) +{ + double startTime = Get_T(); + + long long i, j; + uint32_t qn, tn; + for (i = 0; i < num_sources; i++) + { + for (j = 0; j < sources[i].length; j++) + { + if(sources[i].buffer[j].del) continue; + + qn = Get_qn(sources[i].buffer[j]); + tn = Get_tn(sources[i].buffer[j]); + + if(R_INF.trio_flag[qn] != AMBIGU && R_INF.trio_flag[tn] != AMBIGU) + { + if(R_INF.trio_flag[qn] != R_INF.trio_flag[tn]) + { + sources[i].buffer[j].del = 1; + continue; + } + } + + sources[i].buffer[j].del = 0; + } + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2fs\n\n", __func__, Get_T()-startTime); + } +} + + + +ma_hit_t* get_specific_overlap_with_del(ma_hit_t_alloc* sources, 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, 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; +} + + +uint32_t get_real_sources_length(ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +int max_hang, int min_ovlp, uint32_t query) +{ + uint32_t qn = query>>1; + if(coverage_cut[qn].del) return 0; + int32_t r; + asg_arc_t t; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + ma_hit_t_alloc* x = &(sources[qn]); + uint32_t i, occ = 0; + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + if(h->del) continue; + ///now the edge has not been removed + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(sq->del || st->del) continue; + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + ///if it is a contained read + if(r < 0) continue; + if((t.ul>>32) == query) occ++; + } + + return occ; +} + + +uint32_t delete_all_edges_carefully(ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +int max_hang, int min_ovlp, uint32_t qn) +{ + if(coverage_cut[qn].del) return 0; + + int32_t r; + asg_arc_t t; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + ma_hit_t_alloc* x = &(sources[qn]); + uint32_t i, keep_edge = 0; + uint32_t flag[2]; + flag[0] = flag[1] = 0; + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + if(h->del) continue; + ///now the edge has not been removed + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(sq->del || st->del) + { + h->del = 1; + delete_single_edge(sources, coverage_cut, Get_tn(*h), Get_qn(*h)); + continue; + } + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + ///if it is a contained read + if(r < 0) + { + h->del = 1; + delete_single_edge(sources, coverage_cut, Get_tn(*h), Get_qn(*h)); + continue; + } + + if(get_real_sources_length(sources, coverage_cut, max_hang, min_ovlp, (t.v^1))==1) + { + flag[((t.ul>>32)^1)&1] = 1; + keep_edge++; + continue; + } + + // h->del = 1; + // delete_single_edge(sources, coverage_cut, Get_tn(*h), Get_qn(*h)); + } + + + if(keep_edge != 0) + { + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + if(h->del) continue; + ///now the edge has not been removed + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(sq->del || st->del) continue; + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + ///if it is a contained read + if(r < 0) continue; + + if(flag[(t.ul>>32)&1] == 1) continue; + + if(get_real_sources_length(sources, coverage_cut, max_hang, min_ovlp, (t.v^1))==1) continue; + + h->del = 1; + delete_single_edge(sources, coverage_cut, Get_tn(*h), Get_qn(*h)); + } + } + + if(keep_edge == 0) coverage_cut[qn].del = 1; + return keep_edge; +} + + +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) +{ + ///uint32_t qn_num = 0, no_fully_qn_num = 0, tn_num = 0, no_fully_tn_num = 0; + double startTime = Get_T(); + int32_t r; + long long i, j, m; + 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); + ///r could not be MA_HT_SHORT_OVLP or MA_HT_INT + if (r == MA_HT_QCONT) + { + h->del = 1; + 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, NULL); + } + else if (r == MA_HT_TCONT) + { + h->del = 1; + 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, NULL); + } + } + } + + transfor_R_to_U(ruIndex); + + + for (i = 0; i < n_read; ++i) + { + 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; + } + } + + ///if sources[i].length == 0, that means all overlapped reads with read i are the contained reads + if(m == 0) + { + coverage_cut[i].del = 1; + } + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } +} + + +void ma_hit_flt(ma_hit_t_alloc* sources, long long n_read, ma_sub_t *coverage_cut, int max_hang, int min_ovlp) +{ + double startTime = Get_T(); + long long i, j, rLen; + asg_arc_t t; + + for (i = 0; i < n_read; ++i) + { + rLen = 0; + for (j = 0; j < (long long)sources[i].length; j++) + { + ma_hit_t *h = &(sources[i].buffer[j]); + if(h->del) continue; + //check the corresponding two reads + const ma_sub_t *sq = &(coverage_cut[Get_qn(*h)]); + const ma_sub_t *st = &(coverage_cut[Get_tn(*h)]); + int r; + if (sq->del || st->del) continue; + ///[sq->s, sq->e) and [st->s, st->e) are the high coverage region in query and target + ///here just exculde the overhang? + ///in miniasm the 5-th option is 0.5, instead of 0.8 + /**note!!! h->qn and h->qs have been normalized by sq->s + * h->ts and h->tn have been normalized by sq->e + **/ + ///here the max_hang = 1000, asm_opt.max_hang_rate = 0.8, min_ovlp = 50 + ///for me, there should not have any overhang..so r cannot be equal to MA_HT_INT + ///sq->e - sq->s = the length of query; st->e - st->s = the length od target + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + + + ///for me, there should not have any overhang..so r cannot be equal to MA_HT_INT + ///and I think if we use same min_ovlp in all functions, r also cannot be MA_HT_SHORT_OVLP + ///so it does not matter we have ma_hit2arc or not + if (r >= 0 || r == MA_HT_QCONT || r == MA_HT_TCONT) + { + h->del = 0; + rLen++; + } + else + { + h->del = 1; + delete_single_edge(sources, coverage_cut, Get_tn(*h), Get_qn(*h)); + } + + + } + + if(rLen == 0) + { + (coverage_cut)[i].del = 1; + } + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } +} + + + + + +///a is the overlap vector, n is the length of overlap vector +///min_dp is used for coverage droping +///select reads with coverage >= min_dp +void ma_hit_sub(int min_dp, ma_hit_t_alloc* sources, long long n_read, uint64_t* readLen, +long long mini_overlap_length, ma_sub_t** coverage_cut) +{ + double startTime = Get_T(); + + (*coverage_cut) = (ma_sub_t*)malloc(sizeof(ma_sub_t)*n_read); + + uint64_t i, j, n_remained = 0; + kvec_t(uint32_t) b = {0,0,0}; + + ///all overlaps in vector a has been sorted by qns + ///so for overlaps of one reads, it must be contiguous + for (i = 0; i < (uint64_t)n_read; ++i) + { + if(min_dp <= 1) + { + (*coverage_cut)[i].s = 0; + (*coverage_cut)[i].e = readLen[i]; + (*coverage_cut)[i].del = 0; + ++n_remained; + continue; + } + + + kv_resize(uint32_t, b, sources[i].length); + b.n = 0; + for (j = 0; j < sources[i].length; j++) + { + if(sources[i].buffer[j].del) continue; + + uint32_t qs, qe; + qs = Get_qs(sources[i].buffer[j]); + qe = Get_qe(sources[i].buffer[j]); + kv_push(uint32_t, b, qs<<1); + kv_push(uint32_t, b, qe<<1|1); + } + + ///we can identify the qs and qe by the 0-th bit + ks_introsort_uint32_t(b.n, b.a); + ma_sub_t max, max2; + max.s = max.e = max.del = max2.s = max2.e = max2.del = 0; + int dp, start = 0; + ///max is the longest subregion, max2 is the second longest subregion + for (j = 0, dp = 0; j < b.n; ++j) + { + int old_dp = dp; + ///if a[j] is qe + if (b.a[j]&1) + { + --dp; + } + else + { + ++dp; + } + + /** + min_dp is the coverage drop threshold + there are two cases: + 1. old_dp = dp + 1 (b.a[j] is qe); 2. old_dp = dp - 1 (b.a[j] is qs); + if one read has multiple separate sub-regions with coverage >= min_dp, + does miniasm only select the longest one? + **/ + if (old_dp < min_dp && dp >= min_dp) ///old_dp < dp, b.a[j] is qs + { + ///case 2, a[j] is qs + start = b.a[j]>>1; + } + else if (old_dp >= min_dp && dp < min_dp) ///old_dp > min_dp, b.a[j] is qe + { + int len = (b.a[j]>>1) - start; + if (len > (int)(max.e - max.s)) + { + max2 = max; + max.s = start; + max.e = b.a[j]>>1; + } + else if (len > int(max2.e - max2.s)) + { + max2.s = start; + max2.e = b.a[j]>>1; + } + } + } + + + ///max.e - max.s is the + if (max.e - max.s > 0) + { + (*coverage_cut)[i].s = max.s; + (*coverage_cut)[i].e = max.e; + (*coverage_cut)[i].del = 0; + ++n_remained; + } + else + { + (*coverage_cut)[i].s = (*coverage_cut)[i].e = 0; + + (*coverage_cut)[i].del = 1; + } + } + + free(b.a); + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } +} + + + + +int boundary_verify(uint32_t x_interval_s, uint32_t x_interval_e, ma_hit_t* map, +char* x_buffer, char* y_buffer, All_reads* R_INF) +{ + uint32_t xs, ys, dir, x_id, y_id, x_interval_Len, y_interval_Len, y_interval_s, y_interval_e; + dir = (*map).rev; + xs = Get_qs((*map)); + x_id = Get_qn((*map)); + y_id = Get_tn((*map)); + long long yLen = Get_READ_LENGTH((*R_INF), y_id); + + if(dir == 1) + { + ys = yLen - (Get_te((*map)) - 1) - 1; + } + else + { + ys = Get_ts((*map)); + } + ///[x_interval_s, x_interval_e) + x_interval_Len = x_interval_e - x_interval_s; + + ///[y_interval_s, y_interval_e] + y_interval_s = (x_interval_s - xs) + ys; + if(y_interval_s >= yLen) + { + return 0; + } + y_interval_e = y_interval_s + x_interval_Len - 1; + if(y_interval_e >= yLen) + { + y_interval_e = yLen - 1; + } + + if(y_interval_e < y_interval_s) + { + return 0; + } + + y_interval_Len = y_interval_e - y_interval_s + 1; + + + if(y_interval_Len <= WINDOW) + { + return verify_single_window(y_interval_s, y_interval_e, ys, xs, y_id, x_id, + dir, y_buffer, x_buffer, R_INF); + } + else + { + + if(verify_single_window(y_interval_s, y_interval_s + WINDOW - 1, ys, xs, y_id, x_id, + dir, y_buffer, x_buffer, R_INF) == 0) + { + return 0; + } + + if(verify_single_window(y_interval_e - WINDOW + 1, y_interval_e, ys, xs, y_id, x_id, + dir, y_buffer, x_buffer, R_INF) == 0) + { + return 0; + } + + return 1; + } +} + + +void collect_sides_trio(ma_hit_t_alloc* paf, uint64_t rLen, ma_sub_t* max_left, ma_sub_t* max_right, +uint32_t trio_flag) +{ + long long j; + uint32_t qs, qe; + for (j = 0; j < paf->length; j++) + { + if(paf->buffer[j].del) continue; + + if(R_INF.trio_flag[Get_tn(paf->buffer[j])] == trio_flag) continue; + + qs = Get_qs(paf->buffer[j]); + qe = Get_qe(paf->buffer[j]); + + ///overlaps from left side + if(qs == 0) + { + if(qs < max_left->s) max_left->s = qs; + if(qe > max_left->e) max_left->e = qe; + } + + ///overlaps from right side + if(qe == rLen) + { + if(qs < max_right->s) max_right->s = qs; + if(qe > max_right->e) max_right->e = qe; + } + + ///note: if (qs == 0 && qe == rLen) + ///this overlap would be added to both b_left and b_right + ///that is what we want + } +} + + +void collect_contain_trio(ma_hit_t_alloc* paf1, ma_hit_t_alloc* paf2, uint64_t rLen, +ma_sub_t* max_left, ma_sub_t* max_right, float overlap_rate, uint32_t trio_flag) +{ + long long j, new_left_e, new_right_s; + new_left_e = max_left->e; + new_right_s = max_right->s; + uint32_t qs, qe; + ma_hit_t_alloc* paf; + + if(paf1 != NULL) + { + paf = paf1; + for (j = 0; j < paf->length; j++) + { + if(paf->buffer[j].del) continue; + + if(R_INF.trio_flag[Get_tn(paf->buffer[j])] == trio_flag) continue; + + qs = Get_qs(paf->buffer[j]); + qe = Get_qe(paf->buffer[j]); + ///check contained overlaps + if(qs != 0 && qe != rLen) + { + ///[qs, qe), [max_left.s, max_left.e) + if(qs < max_left->e && qe > max_left->e && max_left->e - qs > (overlap_rate * (qe -qs))) + { + ///if(qe > max_left->e) max_left->e = qe; + if(qe > max_left->e && qe > new_left_e) new_left_e = qe; + } + + ///[qs, qe), [max_right.s, max_right.e) + if(qs < max_right->s && qe > max_right->s && qe - max_right->s > (overlap_rate * (qe -qs))) + { + ///if(qs < max_right->s) max_right->s = qs; + if(qs < max_right->s && qs < new_right_s) new_right_s = qs; + } + } + } + } + + if(paf2 != NULL) + { + paf = paf2; + for (j = 0; j < paf->length; j++) + { + if(paf->buffer[j].del) continue; + + if(R_INF.trio_flag[Get_tn(paf->buffer[j])] == trio_flag) continue; + + qs = Get_qs(paf->buffer[j]); + qe = Get_qe(paf->buffer[j]); + ///check contained overlaps + if(qs != 0 && qe != rLen) + { + ///[qs, qe), [max_left.s, max_left.e) + if(qs < max_left->e && qe > max_left->e && max_left->e - qs > (overlap_rate * (qe -qs))) + { + ///if(qe > max_left->e) max_left->e = qe; + if(qe > max_left->e && qe > new_left_e) new_left_e = qe; + } + + ///[qs, qe), [max_right.s, max_right.e) + if(qs < max_right->s && qe > max_right->s && qe - max_right->s > (overlap_rate * (qe -qs))) + { + ///if(qs < max_right->s) max_right->s = qs; + if(qs < max_right->s && qs < new_right_s) new_right_s = qs; + } + } + } + } + + + max_left->e = new_left_e; + max_right->s = new_right_s; +} + + +void collect_sides(uint32_t rid, ma_hit_t_alloc* pafs, all_ul_t *x, uint64_t rLen, ma_sub_t* max_left, ma_sub_t* max_right, uint64_t ul_thres) +{ + long long j; + uint32_t qs, qe; + ma_hit_t_alloc *paf = (&pafs[rid]); + for (j = 0; j < paf->length; j++) + { + if(paf->buffer[j].del) continue; + + qs = Get_qs(paf->buffer[j]); + qe = Get_qe(paf->buffer[j]); + + + ///overlaps from left side + if(qs == 0) + { + if(qs < max_left->s) max_left->s = qs; + if(qe > max_left->e) max_left->e = qe; + } + + ///overlaps from right side + if(qe == rLen) + { + if(qs < max_right->s) max_right->s = qs; + if(qe > max_right->e) max_right->e = qe; + } + + ///note: if (qs == 0 && qe == rLen) + ///this overlap would be added to both b_left and b_right + ///that is what we want + } + + if(x) { + uint64_t *a = NULL, a_n, k; + uc_block_t *p = NULL; uint64_t cc = 0; + a = get_hifi2ul_list(x, rid, &a_n); + for (k = 0; k < a_n; k++) { + p = &(x->a[a[k]>>32].bb.a[(uint32_t)(a[k])]); + if(p->base||(!p->el)) continue; + qs = p->ts; qe = p->te;///note here is ts && te, instead of qs && qe + ///for UL, we only use overlaps which cover the whole HiFi read + if(qs == 0 && qe == rLen){ + cc++; + if(cc >= ul_thres) break; + } + } + if(cc >= ul_thres) { + max_left->s = 0; max_left->e = rLen; + max_right->s = 0; max_right->e = rLen; + } + } +} + +void collect_contain(ma_hit_t_alloc* paf1, ma_hit_t_alloc* paf2, uint64_t rLen, +ma_sub_t* max_left, ma_sub_t* max_right, float overlap_rate) +{ + long long j, new_left_e, new_right_s; + new_left_e = max_left->e; + new_right_s = max_right->s; + uint32_t qs, qe; + ma_hit_t_alloc* paf; + + if(paf1 != NULL) + { + paf = paf1; + for (j = 0; j < paf->length; j++) + { + if(paf->buffer[j].del) continue; + + qs = Get_qs(paf->buffer[j]); + qe = Get_qe(paf->buffer[j]); + ///check contained overlaps + if(qs != 0 && qe != rLen) + { + ///[qs, qe), [max_left.s, max_left.e) + if(qs < max_left->e && qe > max_left->e && max_left->e - qs > (overlap_rate * (qe -qs))) + { + ///if(qe > max_left->e) max_left->e = qe; + if(qe > max_left->e && qe > new_left_e) new_left_e = qe; + } + + ///[qs, qe), [max_right.s, max_right.e) + if(qs < max_right->s && qe > max_right->s && qe - max_right->s > (overlap_rate * (qe -qs))) + { + ///if(qs < max_right->s) max_right->s = qs; + if(qs < max_right->s && qs < new_right_s) new_right_s = qs; + } + } + } + } + + if(paf2 != NULL) + { + paf = paf2; + for (j = 0; j < paf->length; j++) + { + if(paf->buffer[j].del) continue; + + qs = Get_qs(paf->buffer[j]); + qe = Get_qe(paf->buffer[j]); + ///check contained overlaps + if(qs != 0 && qe != rLen) + { + ///[qs, qe), [max_left.s, max_left.e) + if(qs < max_left->e && qe > max_left->e && max_left->e - qs > (overlap_rate * (qe -qs))) + { + ///if(qe > max_left->e) max_left->e = qe; + if(qe > max_left->e && qe > new_left_e) new_left_e = qe; + } + + ///[qs, qe), [max_right.s, max_right.e) + if(qs < max_right->s && qe > max_right->s && qe - max_right->s > (overlap_rate * (qe -qs))) + { + ///if(qs < max_right->s) max_right->s = qs; + if(qs < max_right->s && qs < new_right_s) new_right_s = qs; + } + } + } + } + + max_left->e = new_left_e; + max_right->s = new_right_s; +} + + + +int intersection_check(ma_hit_t_alloc* paf, uint64_t rLen, uint32_t interval_s, uint32_t interval_e) +{ + long long j, cov = 0; + uint32_t qs, qe; + + for (j = 0; j < paf->length; j++) + { + qs = Get_qs(paf->buffer[j]); + qe = Get_qe(paf->buffer[j]); + ///[interval_s, interval_e) must be at least contained at one of the [qs, qe) + if(qs<=interval_s && qe>=interval_e) + { + cov++; + } + } + + return cov; +} + + +int intersection_check_by_base(ma_hit_t_alloc* paf, uint64_t rLen, uint32_t interval_s, uint32_t interval_e, +char* bq, char* bt) +{ + long long j; + uint32_t qs, qe; + + for (j = 0; j < paf->length; j++) { + if(paf->buffer[j].del) continue; + + qs = Get_qs(paf->buffer[j]); + qe = Get_qe(paf->buffer[j]); + ///[interval_s, interval_e) must be at least contained at one of the [qs, qe) + if(qs<=interval_s && qe>=interval_e) { + if((paf->buffer[j].el) || + (boundary_verify(interval_s, interval_e, &(paf->buffer[j]), bq, bt, &R_INF) == 0)) { + return 1; + } + } + } + + return 0; +} + +void print_overlaps(ma_hit_t_alloc* paf, long long rLen, long long interval_s, long long interval_e) +{ + long long j; + + fprintf(stderr, "left: \n"); + for (j = 0; j < paf->length; j++) + { + if(Get_qs(paf->buffer[j]) == 0) + { + fprintf(stderr, "?????? interval_s: %lld, interval_e: %lld, qn: %u, tn: %u, j: %lld, qs: %u, qe: %u, ts: %u, te: %u, dir: %u\n", + interval_s, interval_e, + Get_qn(paf->buffer[j]), Get_tn(paf->buffer[j]), + j, Get_qs(paf->buffer[j]), Get_qe(paf->buffer[j]), + Get_ts(paf->buffer[j]), Get_te(paf->buffer[j]), + paf->buffer[j].rev); + + fprintf(stderr, "%.*s\n", (int)Get_NAME_LENGTH(R_INF, Get_tn(paf->buffer[j])), + Get_NAME(R_INF, Get_tn(paf->buffer[j]))); + } + } + + fprintf(stderr, "right: \n"); + for (j = 0; j < paf->length; j++) + { + if(Get_qe(paf->buffer[j]) == rLen) + { + fprintf(stderr, "?????? interval_s: %lld, interval_e: %lld, qn: %u, tn: %u, j: %lld, qs: %u, qe: %u, ts: %u, te: %u, dir: %u\n", + interval_s, interval_e, + Get_qn(paf->buffer[j]), Get_tn(paf->buffer[j]), + j, Get_qs(paf->buffer[j]), Get_qe(paf->buffer[j]), + Get_ts(paf->buffer[j]), Get_te(paf->buffer[j]), + paf->buffer[j].rev); + + fprintf(stderr, "%.*s\n", (int)Get_NAME_LENGTH(R_INF, Get_tn(paf->buffer[j])), + Get_NAME(R_INF, Get_tn(paf->buffer[j]))); + } + } + + + fprintf(stderr, "middle: \n"); + for (j = 0; j < paf->length; j++) + { + if(Get_qs(paf->buffer[j]) != 0 && Get_qe(paf->buffer[j]) != rLen) + { + fprintf(stderr, "?????? interval_s: %lld, interval_e: %lld, qn: %u, tn: %u, j: %lld, qs: %u, qe: %u, ts: %u, te: %u, dir: %u\n", + interval_s, interval_e, + Get_qn(paf->buffer[j]), Get_tn(paf->buffer[j]), + j, Get_qs(paf->buffer[j]), Get_qe(paf->buffer[j]), + Get_ts(paf->buffer[j]), Get_te(paf->buffer[j]), + paf->buffer[j].rev); + + fprintf(stderr, "%.*s\n", (int)Get_NAME_LENGTH(R_INF, Get_tn(paf->buffer[j])), + Get_NAME(R_INF, Get_tn(paf->buffer[j]))); + } + } + +} + + +void detect_chimeric_reads(ma_hit_t_alloc* paf, long long n_read, uint64_t* readLen, +ma_sub_t* coverage_cut, float shift_rate, all_ul_t *x, uint64_t ul_thres) +{ + double startTime = Get_T(); + init_aux_table(); + long long i, rLen, n_simple_remove = 0, n_complex_remove = 0, n_complex_remove_real = 0; + uint32_t interval_s, interval_e; + ma_sub_t max_left, max_right; + kvec_t(char) b_q = {0,0,0}; + kvec_t(char) b_t = {0,0,0}; + for (i = 0; i < n_read; ++i) + { + coverage_cut[i].c = PRIMARY_LABLE; + rLen = readLen[i]; + + + max_left.s = max_right.s = rLen; + max_left.e = max_right.e = 0; + ///we just need to check UL alignment here as we only need UL which covers the whole HiFi read + collect_sides(i, paf, x, rLen, &max_left, &max_right, ul_thres); + ///collect_sides(&(rev_paf[i]), rLen, &max_left, &max_right); + ///that means this read is an end node + if(max_left.s == rLen || max_right.s == rLen) + { + continue; + } + collect_contain(&(paf[i]), NULL, rLen, &max_left, &max_right, 0.1); + ///collect_contain(&(paf[i]), &(rev_paf[i]), rLen, &max_left, &max_right, 0.1); + ////shift_rate should be (asm_opt.max_ov_diff_final*2) + ///this read is a normal read + if (max_left.e > max_right.s && (max_left.e - max_right.s >= rLen * shift_rate)) + { + continue; + } + ///simple chimeric reads + if(max_left.e <= max_right.s) + { + delete_all_edges(paf, coverage_cut, i); + n_simple_remove++; + continue; + } + + ///now max_left.e > max_right.s && max_left.e - max_right.s is small enough + //[interval_s, interval_e) + interval_s = max_right.s; + interval_e = max_left.e; + + /** + cov = 0; + cov += intersection_check(&(paf[i]), rLen, interval_s, interval_e); + cov += intersection_check(&(rev_paf[i]), rLen, interval_s, interval_e); + if(interval_e - interval_s < WINDOW && cov <= 2) + { + coverage_cut[i].del = 1; + paf[i].length = 0; + n_complex_remove_real++; + } + else**/ + { + kv_resize(char, b_q, WINDOW*4+20); + kv_resize(char, b_t, WINDOW*4+20); + if(intersection_check_by_base(&(paf[i]), rLen, interval_s, interval_e, b_q.a, b_t.a) + /**|| + intersection_check_by_base(&(rev_paf[i]), rLen, interval_s, interval_e, b_q.a, b_t.a)**/) + { + delete_all_edges(paf, coverage_cut, i); + n_complex_remove_real++; + } + } + + n_complex_remove++; + } + + free(b_q.a); + free(b_t.a); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2f s, n_simple_remove: %lld, n_complex_remove: %lld/%lld\n\n", + __func__, Get_T()-startTime, n_simple_remove, n_complex_remove_real, n_complex_remove); + } +} + + +void ma_hit_cut(ma_hit_t_alloc* sources, long long n_read, uint64_t* readLen, +long long mini_overlap_length, ma_sub_t** coverage_cut) +{ + double startTime = Get_T(); + size_t i, j; + ma_hit_t* p; + ma_sub_t* rq; + ma_sub_t* rt; + long long rLen = 0; + for (i = 0; i < (uint64_t)n_read; ++i) + { + rLen = 0; + for (j = 0; j < sources[i].length; j++) + { + ///this is a overlap + p = &(sources[i].buffer[j]); + if(p->del) continue; + + rq = &((*coverage_cut)[Get_qn(*p)]); + rt = &((*coverage_cut)[Get_tn(*p)]); + ///if any of target read and the query read has no enough coverage + if (rq->del || rt->del) continue; + int qs, qe, ts, te; + + + + + ///target and query in different strand + if (p->rev) + { + /** + here is an example in different strand: + + (te) (rt->e) (rt->s) (ts) + | | | | + target ---------------------------------------------------- + ------------------------------------------- query + qs qe + **/ + qs = p->te < rt->e? Get_qs(*p): Get_qs(*p) + (p->te - rt->e); + qe = p->ts > rt->s? p->qe : p->qe - (rt->s - p->ts); + ts = p->qe < rq->e? p->ts : p->ts + (p->qe - rq->e); + te = Get_qs(*p) > rq->s? p->te : p->te - (rq->s - Get_qs(*p)); + } + else ///target and query in same strand + { + /** + note: ts is the targe start in this overlap, + while rt->s is the high coverage start in the whole target (not only in this overlap) + so this line is to normalize the qs in quey to high coverage region + **/ + //(rt->s - p->ts) is the offset + qs = p->ts > rt->s? Get_qs(*p): Get_qs(*p) + (rt->s - p->ts); + //(p->te - rt->e) is the offset + qe = p->te < rt->e? p->qe : p->qe - (p->te - rt->e); + //(rq->s - Get_qs(*p) is the offset + ts = Get_qs(*p) > rq->s? p->ts : p->ts + (rq->s - Get_qs(*p)); + //(p->qe - rq->e) is the offset + te = p->qe < rq->e? p->te : p->te - (p->qe - rq->e); + } + + + + //cut by self coverage + //and normalize the qs, qe, ts, te by rq->s and rt->e + qs = ((uint32_t)qs > rq->s? qs : rq->s) - rq->s; + qe = ((uint32_t)qe < rq->e? qe : rq->e) - rq->s; + ts = ((uint32_t)ts > rt->s? ts : rt->s) - rt->s; + te = ((uint32_t)te < rt->e? te : rt->e) - rt->s; + + if (qe - qs >= mini_overlap_length && te - ts >= mini_overlap_length) + { + ///p->qns = p->qns>>32<<32 | qs; + p->qns = p->qns>>32; + p->qns = p->qns << 32; + p->qns = p->qns | qs; + + p->qe = qe; + p->ts = ts; + p->te = te; + p->del = 0; + rLen++; + } + else + { + p->del = 1; + delete_single_edge(sources, (*coverage_cut), Get_tn(*p), Get_qn(*p)); + ///delete_all_edges(paf, coverage_cut, i); + } + } + + if(rLen == 0) + { + (*coverage_cut)[i].del = 1; + } + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + +} + + + +/********************************** + * Filter short potential unitigs * + **********************************/ +#define ASG_ET_MERGEABLE 0 +#define ASG_ET_TIP 1 +#define ASG_ET_MULTI_OUT 2 +#define ASG_ET_MULTI_NEI 3 + +static inline int asg_is_utg_end(const asg_t *g, uint32_t v, uint64_t *lw) +{ + + /** + .............................. + . w1--------------- . + . w2-------------- . + . w3-------------- .--->asg_arc_a(g, v^1) + . w4------------- . + . w5------------ . + .............................. + v--------------- + .............................. + . w1--------------- . + . w2-------------- . + . w3-------------- .--->asg_arc_a(g, v) + . w4------------- . + . w5------------ . + .............................. + !!!!!note here the graph has already been cleaned by transitive reduction, so idealy: + + ......................... + . w1--------------- .--->asg_arc_a(g, v^1) + ......................... + v--------------- + ......................... + . w5--------------- .--->asg_arc_a(g, v) + ......................... + + **/ + ///v^1 is the another direction of v + uint32_t w, nv, nw, nw0, nv0 = asg_arc_n(g, v^1); + int i, i0 = -1; + asg_arc_t *aw, *av = asg_arc_a(g, v^1); + + ///if this arc has not been deleted + for (i = nv = 0; i < (int)nv0; ++i) + if (!av[i].del) i0 = i, ++nv; + + ///end without any out-degree + if (nv == 0) return ASG_ET_TIP; // tip + + /** + since the graph has already been cleaned by transitive reduction, + w1 and w2 should not be overlapped with each other + that mean v has mutiple in-edges, and each of them is not overlapped with others + ......................... + . w2--------------- .--->asg_arc_a(g, v^1) + . w1--------------- . + ......................... + v--------------- + + **/ + if (nv > 1) return ASG_ET_MULTI_OUT; // multiple outgoing arcs + + + + + /** + * ///until here, nv == 1 + note the graph has already been cleaned by transitive reduction, + ......................... + . w1--------------- .--->asg_arc_a(g, v^1) + ......................... + v--------------- + **/ + /** + p->ul: |____________31__________|__________1___________|______________32_____________| + qn direction of overlap length of this node (not overlap length) + (based on query) + p->v : |___________31___________|__________1___________| + tn reverse direction of overlap + (based on target) + p->ol: overlap length + **/ + ///until here, nv == 1 + if (lw) *lw = av[i0].ul<<32 | av[i0].v; + /** + p->ul: |____________31__________|__________1___________|______________32_____________| + qns direction of overlap length of this node (not overlap length) + (based on query) + p->v : |___________31___________|__________1___________| + tns reverse direction of overlap + (based on target) + p->ol: overlap length + **/ + w = av[i0].v ^ 1; + nw0 = asg_arc_n(g, w); + aw = asg_arc_a(g, w); + for (i = nw = 0; i < (int)nw0; ++i) + if (!aw[i].del) ++nw; + + + /** + note nw is at least 1, since we have v + nw > 1 means + ......................... + . av[i0].v^1---------- .--->asg_arc_a(g, v^1) + ......................... + v--------------- + w--------------- + z--------------- + asg_arc_a(av[i0].v^1) is the (v, w, z), and v, w, z are not overlapped with each others + **/ + if (nw != 1) return ASG_ET_MULTI_NEI; + + /** + * nw == 1 means + note the graph has already been cleaned by transitive reduction, + ......................... + . w1--------------- .--->asg_arc_a(g, v^1) + ......................... + v--------------- + ......................... + . w5--------------- .--->asg_arc_a(g, v) + ......................... + + **/ + return ASG_ET_MERGEABLE; +} + + +int asg_extend(const asg_t *g, uint32_t v, int max_ext, asg64_v *a) +{ + int ret; + uint64_t lw; + a->n = 0; + kv_push(uint64_t, *a, v); + do { + /** + test (v) and (v^1), + if the out-degrees of both (v) and (v^1) are 1, ret == 0 + **/ + ret = asg_is_utg_end(g, v^1, &lw); + /** + #define ASG_ET_MERGEABLE 0 + #define ASG_ET_TIP 1 + #define ASG_ET_MULTI_OUT 2 + #define ASG_ET_MULTI_NEI 3 + **/ + if (ret != 0) break; + kv_push(uint64_t, *a, lw); + /** + ret == 0 means: + v^1 and is the only prefix of (uint32_t)lw, + and (uint32_t)lw is the only prefix of v^1 + **/ + + v = (uint32_t)lw; + } while (--max_ext > 0); + return ret; +} + + +static inline int asg_is_single_edge(const asg_t *g, uint32_t v, uint32_t start_node) +{ + + /** + .............................. + . w1--------------- . + . w2-------------- . + . w3-------------- .--->asg_arc_a(g, v^1) + . w4------------- . + . w5------------ . + .............................. + v--------------- + .............................. + . w1--------------- . + . w2-------------- . + . w3-------------- .--->asg_arc_a(g, v) + . w4------------- . + . w5------------ . + .............................. + !!!!!note here the graph has already been cleaned by transitive reduction, so idealy: + + ......................... + . w1--------------- .--->asg_arc_a(g, v^1) + ......................... + v--------------- + ......................... + . w5--------------- .--->asg_arc_a(g, v) + ......................... + + **/ + ///v^1 is the another direction of v + uint32_t nv, nv0 = asg_arc_n(g, v^1); + int i; + asg_arc_t *av = asg_arc_a(g, v^1); + + int flag = 0; + ///if this arc has not been deleted + for (i = nv = 0; i < (int)nv0; ++i) + { + ///if (!av[i].del) + { + ++nv; + if(av[i].v>>1 == start_node) + { + flag = 1; + } + } + } + + if(flag == 0) + { + fprintf(stderr, "****ERROR\n"); + } + + return nv; +} + +void debug_info_of_specfic_node(const char* name, asg_t *g, R_to_U* ruIndex, const char* command) +{ + fprintf(stderr, "\n\n\n"); + uint32_t v, n_vtx = g->n_seq * 2, queryLen = strlen(name), flag = 0, contain_rId, is_Unitig; + for (v = 0; v < n_vtx; ++v) + { + if(queryLen == Get_NAME_LENGTH(R_INF, (v>>1)) && memcmp(name, Get_NAME(R_INF, (v>>1)), Get_NAME_LENGTH(R_INF, (v>>1))) == 0) + { + if(flag == 0) fprintf(stderr, "\nafter %s\n", command); + fprintf(stderr, "****************graph ref_read: %.*s, id: %u, dir: %u****************\n", + (int)Get_NAME_LENGTH(R_INF, (v>>1)), Get_NAME(R_INF, (v>>1)), v>>1, v&1); + if(g->seq[v>>1].del) + { + get_R_to_U(ruIndex, (v>>1), &contain_rId, &is_Unitig); + if(contain_rId != (uint32_t)-1 && is_Unitig != 1) + { + fprintf(stderr, "read is deleted as a contained read by: %.*s\n contain_rId: %u, del: %u\n", + (int)Get_NAME_LENGTH(R_INF, contain_rId), Get_NAME(R_INF, contain_rId), contain_rId, g->seq[contain_rId].del); + } + else + { + fprintf(stderr, "read has already been deleted.\n"); + } + + return; + } + + asg_arc_t *av = asg_arc_a(g, v); + uint32_t i, nv = asg_arc_n(g, v); + for (i = 0; i < nv; ++i) + { + fprintf(stderr, "target: %.*s, el: %u, strong: %u, ol: %u, del: %u\n", + (int)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), + Get_NAME(R_INF, (av[i].v>>1)), + av[i].el, av[i].strong, av[i].ol, av[i].del); + } + flag = 1; + } + } +} + + +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) +{ + double startTime = Get_T(); + size_t i, j; + asg_t *g; + ///just calloc + 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; + asg_arc_t t, *p; + const ma_hit_t *h = &(sources[i].buffer[j]); + if(h->del) continue; + + //high coverage region [sub[qn].e, sub[qn].s) in query + int ql = coverage_cut[Get_qn(*h)].e - coverage_cut[Get_qn(*h)].s; + //high coverage region [sub[qn].e, sub[qn].s) in target + int tl = coverage_cut[Get_tn(*h)].e - coverage_cut[Get_tn(*h)].s; + r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + /** + #define MA_HT_INT (-1) + #define MA_HT_QCONT (-2) + #define MA_HT_TCONT (-3) + #define MA_HT_SHORT_OVLP (-4) + the short overlaps and the overlaps with contain reads have already been removed + here we should have overhang + so r should always >= 0 + **/ + if (r >= 0) + { + ///push node? + p = asg_arc_pushp(g); + *p = t; + } + else + { + fprintf(stderr, "error\n"); + } + } + } + + asg_cleanup(g); + g->r_seq = g->n_seq; + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + return g; +} + +void prt_specific_overlap(ma_hit_t_alloc *src, uint64_t qn, uint64_t tn, const char *cmd) +{ + ma_hit_t *h = NULL; int64_t idx = -1, k; + if(tn != ((uint64_t)-1)) { + idx = get_specific_overlap(&(src[qn]), qn, tn); h = &(src[qn].buffer[idx]); + fprintf(stderr, "%s::idx::%ld[M::%s::] qn::%u, tn::%u, del::%u, bl::%u, ml::%u\n", cmd, idx, __func__, + Get_qn(*h), Get_tn(*h), h->del, h->bl, h->ml); + } else { + for (k = 0; k < src[qn].length; k++) { + h = &(src[qn].buffer[k]); + fprintf(stderr, "%s::idx::%ld[M::%s::] qn::%u, tn::%u, del::%u, bl::%u, ml::%u\n", cmd, idx, __func__, + Get_qn(*h), Get_tn(*h), h->del, h->bl, h->ml); + } + } +} + +asg_t *ma_sg_gen_ul(ma_hit_t_alloc* sources, int64_t n_read, const ma_sub_t *coverage_cut, +R_to_U* ruIndex, int64_t max_hang, int64_t min_ovlp, int64_t ul_occ) +{ + int64_t i, j, r; asg_arc_t t, *p; const ma_hit_t *h; + asg_t *g = asg_init(); + for (i = 0; i < n_read; ++i) { + 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; + } + CALLOC(g->seq_vis, (g->n_seq<<1)); + + // prt_specific_overlap(sources, 22233, 22235, "+"); + // prt_specific_overlap(sources, 22235, 22233, "+"); + // fprintf(stderr, "[M::%s::] n_read::%ld\n", __func__, n_read); + recover_contain_g(g, sources, ruIndex, max_hang, min_ovlp, ul_occ); + + for (i = 0; i < n_read; ++i) { + if(g->seq[i].del) continue; + for (j = 0; j < sources[i].length; j++) { + h = &(sources[i].buffer[j]); + // if((Get_qn(*h) == 22233 && Get_tn(*h) == 22235)|| + // (Get_qn(*h) == 22235 && Get_tn(*h) == 22233)) { + // fprintf(stderr, "[M::%s::] qn::%u, tn::%u, del::%u, bl::%u\n", __func__, Get_qn(*h), Get_tn(*h), + // h->del, h->bl); + // } + if(h->del) continue; + r = ma_hit2arc(h, (coverage_cut[Get_qn(*h)].e-coverage_cut[Get_qn(*h)].s), + (coverage_cut[Get_tn(*h)].e-coverage_cut[Get_tn(*h)].s), max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + assert(r >= 0); + p = asg_arc_pushp(g); *p = t; + p->ou = ((h->bl>OU_MASK)?OU_MASK:h->bl); + // if(Get_qn(*h) == 10498 && Get_tn(*h) == 10505) { + // fprintf(stderr, "[M::%s::] qn::%u, tn::%u, p->ou::%u, h->bl::%u\n", __func__, + // Get_qn(*h), Get_tn(*h), p->ou, h->bl); + // } + } + } + + asg_cleanup(g); + asg_symm(g); + g->r_seq = g->n_seq; + return g; +} + + + + +// pop bubbles from vertex v0; the graph MJUST BE symmetric: if u->v present, v'->u' must be present as well +//note!!!!!!!! here we don't exculde the deleted edges +static uint64_t asg_bub_finder_with_del_advance(asg_t *g, uint32_t v0, int max_dist, buf_t *b) +{ + uint32_t i, n_pending = 0; + uint64_t n_pop = 0; + ///if this node has been deleted + if (g->seq[v0>>1].del) return 0; // already deleted + ///asg_arc_n(n0) + if ((uint32_t)g->idx[v0] < 2) return 0; // no bubbles + ///S saves nodes with all incoming edges visited + b->S.n = b->T.n = b->b.n = b->e.n = 0; + ///for each node, b->a saves all related information + b->a[v0].c = b->a[v0].d = 0; + ///b->S is the nodes with all incoming edges visited + kv_push(uint32_t, b->S, v0); + + do { + ///v is a node that all incoming edges have been visited + ///d is the distance from v0 to v + uint32_t v = kv_pop(b->S), d = b->a[v].d, c = b->a[v].c; + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + ///why we have this assert? + /****************************may have bugs********************************/ + ///assert(nv > 0); + /****************************may have bugs********************************/ + + ///all out-edges of v + for (i = 0; i < nv; ++i) { // loop through v's neighbors + /** + p->ul: |____________31__________|__________1___________|______________32_____________| + qn direction of overlap length of this node (not overlap length) + (in the view of query) + p->v : |___________31___________|__________1___________| + tn reverse direction of overlap + (in the view of target) + p->ol: overlap length + **/ + uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l + binfo_t *t = &b->a[w]; + ///that means there is a circle, directly terminate the whole bubble poping + if (w == v0) + { + //fprintf(stderr, "n_pop error1\n"); + goto pop_reset; + } + + ///if this edge has been deleted + /****************************may have bugs********************************/ + ///if (av[i].del) continue; + /****************************may have bugs********************************/ + + ///push the edge + kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); + + ///find a too far path? directly terminate the whole bubble poping + if (d + l > (uint32_t)max_dist) + { + //fprintf(stderr, "n_pop error2\n"); + break; // too far + } + + + + if (t->s == 0) { // this vertex has never been visited + kv_push(uint32_t, b->b, w); // save it for revert + ///t->p means the in-node of w is v + ///t->s = 1 means w has been visited + ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) + t->p = v, t->s = 1, t->d = d + l, t->c = c + 1; + ///incoming edges of w + t->r = count_out_with_del(g, w^1); + ++n_pending; + } else { // visited before + ///c seems the max weight of node + if (c + 1 > t->c || (c + 1 == t->c && d + l > t->d)) t->p = v; + if (c + 1 > t->c) t->c = c + 1; + ///update len(v0->w) + if (d + l < t->d) t->d = d + l; // update dist + } + /****************************may have bugs********************************/ + ///assert(t->r > 0); + /****************************may have bugs********************************/ + //if all incoming edges of w have visited + //push it to b->S + if (--(t->r) == 0) { + uint32_t x = asg_arc_n(g, w); + if (x) kv_push(uint32_t, b->S, w); + else kv_push(uint32_t, b->T, w); // a tip + --n_pending; + } + } + ///if i < nv, that means (d + l > max_dist) + if (i < nv || b->S.n == 0) + { + ///fprintf(stderr, "n_pop error3\n"); + goto pop_reset; + } + + } while (b->S.n > 1 || n_pending); + ///asg_bub_backtrack(g, v0, b); + ///n_pop = 1 | (uint64_t)b->T.n<<32; + n_pop = 1; +pop_reset: + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + binfo_t *t = &b->a[b->b.a[i]]; + t->s = t->c = t->d = 0; + } + ///fprintf(stderr, "n_pop: %d\n", n_pop); + return n_pop; +} + + +// pop bubbles from vertex v0; the graph MJUST BE symmetric: if u->v present, v'->u' must be present as well +//note!!!!!!!! here we don't exculde the deleted edges +static uint64_t asg_bub_finder_without_del_advance(asg_t *g, uint32_t v0, int max_dist, +buf_t *b) +{ + uint32_t i, n_pending = 0; + uint64_t n_pop = 0; + ///if this node has been deleted + if (g->seq[v0>>1].del) return 0; // already deleted + ///asg_arc_n(n0) + if ((uint32_t)g->idx[v0] < 2) return 0; // no bubbles + if(count_out_without_del(g, v0) < 2) return 0; // no bubbles + + + ///S saves nodes with all incoming edges visited + b->S.n = b->T.n = b->b.n = b->e.n = 0; + ///for each node, b->a saves all related information + b->a[v0].c = b->a[v0].d = 0; + ///b->S is the nodes with all incoming edges visited + kv_push(uint32_t, b->S, v0); + + do { + ///v is a node that all incoming edges have been visited + ///d is the distance from v0 to v + uint32_t v = kv_pop(b->S), d = b->a[v].d, c = b->a[v].c; + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + ///why we have this assert? + /****************************may have bugs********************************/ + ///assert(nv > 0); + /****************************may have bugs********************************/ + + ///all out-edges of v + for (i = 0; i < nv; ++i) { // loop through v's neighbors + /** + p->ul: |____________31__________|__________1___________|______________32_____________| + qn direction of overlap length of this node (not overlap length) + (in the view of query) + p->v : |___________31___________|__________1___________| + tn reverse direction of overlap + (in the view of target) + p->ol: overlap length + **/ + uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l + binfo_t *t = &b->a[w]; + + ///if this edge has been deleted + /****************************may have bugs********************************/ + if (av[i].del) continue; + /****************************may have bugs********************************/ + + ///that means there is a circle, directly terminate the whole bubble poping + if (w == v0) + { + //fprintf(stderr, "n_pop error1\n"); + goto pop_reset; + } + + + ///push the edge + kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); + + ///find a too far path? directly terminate the whole bubble poping + if (d + l > (uint32_t)max_dist) + { + //fprintf(stderr, "n_pop error2\n"); + break; // too far + } + + + + if (t->s == 0) { // this vertex has never been visited + kv_push(uint32_t, b->b, w); // save it for revert + ///t->p means the in-node of w is v + ///t->s = 1 means w has been visited + ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) + t->p = v, t->s = 1, t->d = d + l, t->c = c + 1; + ///incoming edges of w + t->r = count_out_without_del(g, w^1); + ++n_pending; + } else { // visited before + ///c seems the max weight of node + if (c + 1 > t->c || (c + 1 == t->c && d + l > t->d)) t->p = v; + if (c + 1 > t->c) t->c = c + 1; + ///update len(v0->w) + if (d + l < t->d) t->d = d + l; // update dist + } + /****************************may have bugs********************************/ + ///assert(t->r > 0); + /****************************may have bugs********************************/ + //if all incoming edges of w have visited + //push it to b->S + if (--(t->r) == 0) { + uint32_t x = asg_arc_n(g, w); + if (x) kv_push(uint32_t, b->S, w); + else kv_push(uint32_t, b->T, w); // a tip + --n_pending; + } + } + ///if i < nv, that means (d + l > max_dist) + if (i < nv || b->S.n == 0) + { + ///fprintf(stderr, "n_pop error3\n"); + goto pop_reset; + } + + } while (b->S.n > 1 || n_pending); + ///asg_bub_backtrack(g, v0, b); + ///n_pop = 1 | (uint64_t)b->T.n<<32; + n_pop = 1; +pop_reset: + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + binfo_t *t = &b->a[b->b.a[i]]; + t->s = t->c = t->d = 0; + } + ///fprintf(stderr, "n_pop: %d\n", n_pop); + return n_pop; +} + + +// pop bubbles from vertex v0; the graph MJUST BE symmetric: if u->v present, v'->u' must be present as well +//note!!!!!!!! here we don't exculde the deleted edges +static uint64_t asg_bub_end_finder_with_del_advance(asg_t *g, uint32_t* v_Ns, uint32_t occ, +int max_dist, buf_t *b, uint32_t exculde_init, uint32_t exclude_node, uint32_t* sink) +{ + uint32_t i, j, n_pending = 0; + uint64_t n_pop = 0; + ///S saves nodes with all incoming edges visited + b->S.n = b->T.n = b->b.n = b->e.n = 0; + for (j = 0; j < occ; j++) + { + ///if this node has been deleted + if (g->seq[v_Ns[j]>>1].del) return 0; // already deleted + ///for each node, b->a saves all related information + b->a[v_Ns[j]].c = b->a[v_Ns[j]].d = 0; + ///b->S is the nodes with all incoming edges visited + kv_push(uint32_t, b->S, (v_Ns[j]<<1)|exculde_init); + } + + + + do { + ///v is a node that all incoming edges have been visited + ///d is the distance from v0 to v + uint32_t v = kv_pop(b->S), f = v & (uint32_t)1; + v = v >> 1; + uint32_t d = b->a[v].d, c = b->a[v].c; + + + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + + ///all out-edges of v + for (i = 0; i < nv; ++i) { // loop through v's neighbors + /** + p->ul: |____________31__________|__________1___________|______________32_____________| + qn direction of overlap length of this node (not overlap length) + (in the view of query) + p->v : |___________31___________|__________1___________| + tn reverse direction of overlap + (in the view of target) + p->ol: overlap length + **/ + uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l + binfo_t *t = &b->a[w]; + + for (j = 0; j < occ; j++) + { + if(w == v_Ns[j]) goto pop_reset; + } + + + + if(f && (exclude_node) == (w)) continue; + + ///if (av[i].del) continue; + + ///push the edge + kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); + + ///find a too far path? directly terminate the whole bubble poping + if (d + l > (uint32_t)max_dist) + { + break; // too far + } + + + + if (t->s == 0) { // this vertex has never been visited + kv_push(uint32_t, b->b, w); // save it for revert + ///t->p means the in-node of w is v + ///t->s = 1 means w has been visited + ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) + t->p = v, t->s = 1, t->d = d + l, t->c = c + 1; + ///incoming edges of w + t->r = count_out_with_del(g, w^1); + ///t->r = count_out_without_del(g, w^1); + ++n_pending; + } else { // visited before + ///c seems the max weight of node + if (c + 1 > t->c || (c + 1 == t->c && d + l > t->d)) t->p = v; + if (c + 1 > t->c) t->c = c + 1; + ///update len(v0->w) + if (d + l < t->d) t->d = d + l; // update dist + } + /****************************may have bugs********************************/ + ///assert(t->r > 0); + /****************************may have bugs********************************/ + //if all incoming edges of w have visited + //push it to b->S + if (--(t->r) == 0) { + uint32_t x = asg_arc_n(g, w); + //if (x) kv_push(uint32_t, b->S, w); + if (x) kv_push(uint32_t, b->S, w<<1); + else kv_push(uint32_t, b->T, w); // a tip + --n_pending; + } + } + ///if i < nv, that means (d + l > max_dist) + if (i < nv || b->S.n == 0) + { + goto pop_reset; + } + + } while (b->S.n > 1 || n_pending); + + (*sink) = b->S.a[0]>>1; + ///asg_bub_backtrack(g, v0, b); + ///n_pop = 1 | (uint64_t)b->T.n<<32; + n_pop = 1; +pop_reset: + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + binfo_t *t = &b->a[b->b.a[i]]; + t->s = t->c = t->d = 0; + } + return n_pop; +} + + + + +int if_node_exist(uint32_t* nodes, uint32_t length, uint32_t query) +{ + uint32_t i; + for (i = 0; i < length; ++i) + { + if((nodes[i]>>1) == query) + { + return 1; + } + } + + return 0; +} + + + + +long long single_edge_length(asg_t *g, uint32_t begNode, uint32_t endNode, long long edgeLen) +{ + + uint32_t v = begNode; + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + long long rLen = 0; + + while (rLen < edgeLen && nv == 1) + { + rLen++; + if((av[0].v>>1) == endNode) + { + return rLen; + } + + if(asg_is_single_edge(g, av[0].v, v>>1) != 1) + { + return -1; + } + + v = av[0].v; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + } + + return -1; + +} + +uint32_t detect_single_path(asg_t *g, uint32_t begNode, uint32_t* endNode, long long* Len, buf_t* b) +{ + + uint32_t v = begNode; + uint32_t nv, rnv; + asg_arc_t *av; + (*Len) = 0; + + + while (1) + { + (*Len)++; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + (*endNode) = v; + + if(b) kv_push(uint32_t, b->b, v>>1); + + if(nv == 0) + { + return END_TIPS; + } + + if(nv == 2) + { + return TWO_OUTPUT; + } + + if(nv > 2) + { + return MUL_OUTPUT; + } + + ///up to here, nv=1 + ///rnv must >= 1 + rnv = asg_is_single_edge(g, av[0].v, v>>1); + v = av[0].v; + (*endNode) = v; + if(rnv == 2) + { + (*Len)++; + if(b) kv_push(uint32_t, b->b, v>>1); + return TWO_INPUT; + } + + if(rnv > 2) + { + (*Len)++; + if(b) kv_push(uint32_t, b->b, v>>1); + return MUL_INPUT; + } + + + if((v>>1) == (begNode>>1)) + { + return LOOP; + } + } + + return LONG_TIPS; +} + +int detect_bubble_end(asg_t *g, uint32_t begNode1, uint32_t begNode2, uint32_t* endNode, +long long* minLen, buf_t* b) +{ + uint32_t e1, e2; + long long l1, l2; + + if(detect_single_path(g, begNode1, &e1, &l1, b) == TWO_INPUT + && + detect_single_path(g, begNode2, &e2, &l2, b) == TWO_INPUT) + { + if(e1 == e2) + { + (*endNode) = e1; + (*minLen) = (l1 <= l2)? l1: l2; + return 1; + } + } + + return 0; +} + + +int detect_simple_bubble(asg_t *g, uint32_t begNode, uint32_t* endNode, long long* minLen, buf_t* b) +{ + uint32_t e1, e2; + long long l1, l2; + + if(asg_arc_n(g, begNode) != 2) + { + return 0; + } + + if(asg_is_single_edge(g, asg_arc_a(g, begNode)[0].v, begNode>>1)!=1 + || + asg_is_single_edge(g, asg_arc_a(g, begNode)[1].v, begNode>>1)!=1) + { + return 0; + } + + if(b) kv_push(uint32_t, b->b, begNode>>1); + + + + + if(detect_single_path(g, asg_arc_a(g, begNode)[0].v, &e1, &l1, b) == TWO_INPUT + && + detect_single_path(g, asg_arc_a(g, begNode)[1].v, &e2, &l2, b) == TWO_INPUT) + { + if(e1 == e2) + { + (*endNode) = e1; + (*minLen) = (l1 <= l2)? l1: l2; + (*minLen)++; + return 1; + } + } + + return 0; +} + + +uint32_t detect_single_path_with_single_bubbles(asg_t *g, uint32_t begNode, uint32_t* endNode, +long long* Len, buf_t* b, uint32_t max_ext) +{ + + uint32_t v = begNode; + uint32_t nv, rnv; + asg_arc_t *av; + long long bLen; + long long pre_b_n = 0; + (*Len) = 0; + + + + while (1) + { + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + (*endNode) = v; + (*Len)++; + + + if((*Len) > max_ext) + { + return LONG_TIPS_UNDER_MAX_EXT; + } + + + if(b) kv_push(uint32_t, b->b, v>>1); + + + + if(nv == 0) + { + return END_TIPS; + } + + if(nv == 2) + { + + + if(b) pre_b_n = b->b.n; + if(!detect_simple_bubble(g, v, &v, &bLen, b)) + { + if(b) b->b.n = pre_b_n; + return TWO_OUTPUT; + } + + (*Len) = (*Len) + bLen - 2; + continue; + } + + if(nv > 2) + { + return MUL_OUTPUT; + } + + ///up to here, nv=1 + ///rnv must >= 1 + rnv = asg_is_single_edge(g, av[0].v, v>>1); + v = av[0].v; + (*endNode) = v; + if(rnv == 2) + { + if(b) kv_push(uint32_t, b->b, v>>1); + (*Len)++; + return TWO_INPUT; + } + + if(rnv > 2) + { + if(b) kv_push(uint32_t, b->b, v>>1); + (*Len)++; + return MUL_INPUT; + } + + if((v>>1) == (begNode>>1)) + { + return LOOP; + } + } + + return LONG_TIPS; +} + +int detect_bubble_end_with_bubbles(asg_t *g, uint32_t begNode1, uint32_t begNode2, +uint32_t* endNode, long long* minLen, buf_t* b) +{ + uint32_t e1, e2; + long long l1, l2; + + if(detect_single_path_with_single_bubbles(g, begNode1, &e1, &l1, b, (uint32_t)-1) == TWO_INPUT + && + detect_single_path_with_single_bubbles(g, begNode2, &e2, &l2, b, (uint32_t)-1) == TWO_INPUT) + { + if(e1 == e2) + { + (*endNode) = e1; + (*minLen) = (l1 <= l2)? l1: l2; + return 1; + } + } + + return 0; +} + + +int detect_mul_bubble_end_with_bubbles(asg_t *g, uint32_t* begs, uint32_t occ, +uint32_t* endNode, long long* minLen, buf_t* b) +{ + uint32_t e, flag, e_s; + long long l, i, l_s; + + if(occ < 1) return 0; + + flag = detect_single_path_with_single_bubbles(g, begs[0], &e, &l, b, (uint32_t)-1); + + if(flag == TWO_INPUT || flag == MUL_INPUT) + { + e_s = e; + l_s = l; + } + else + { + return 0; + } + + + + for (i = 1; i < occ; i++) + { + flag = detect_single_path_with_single_bubbles(g, begs[i], &e, &l, b, (uint32_t)-1); + if(flag == TWO_INPUT || flag == MUL_INPUT) + { + if(e != e_s) return 0; + if(l < l_s) l_s = l; + } + else + { + return 0; + } + } + + if(asg_arc_n(g, e_s^1) == occ) + { + (*endNode) = e_s; + (*minLen) = l_s; + return 1; + } + + return 0; +} + + +int detect_bubble_with_bubbles(asg_t *g, uint32_t begNode, uint32_t* endNode, long long* minLen, +buf_t* b, uint32_t max_ext) +{ + uint32_t e1, e2; + long long l1, l2; + + if(asg_arc_n(g, begNode) != 2) + { + return 0; + } + + if(asg_is_single_edge(g, asg_arc_a(g, begNode)[0].v, begNode>>1)!=1 + || + asg_is_single_edge(g, asg_arc_a(g, begNode)[1].v, begNode>>1)!=1) + { + return 0; + } + + if(b) kv_push(uint32_t, b->b, begNode>>1); + + + if(detect_single_path_with_single_bubbles(g, asg_arc_a(g, begNode)[0].v, &e1, &l1, b, max_ext) == TWO_INPUT) + { + b->b.n--; + if(detect_single_path_with_single_bubbles(g, asg_arc_a(g, begNode)[1].v, &e2, &l2, b, max_ext) == TWO_INPUT) + { + b->b.n--; + if(e1 == e2) + { + (*endNode) = e1; + (*minLen) = (l1 <= l2)? l1: l2; + (*minLen)++; + return 1; + } + } + } + + return 0; +} + +int test_triangular_exact(asg_t *g, uint32_t* nodes, uint32_t length, +uint32_t startNode, uint32_t endNode, int max_dist, buf_t* bub) +{ + + uint32_t i, v, w; + ///int flag0, flag1, node; + int n_reduced = 0, todel; + long long NodeLen_first[3]; + long long NodeLen_second[3]; + + uint32_t Ns_first[3]; + uint32_t Ns_second[3]; + + + for (i = 0; i < length; ++i) + { + v = nodes[i]; + + if((v>>1) == (startNode>>1) || (v>>1) == (endNode>>1)) + { + continue; + } + + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + if(nv != 2) + { + continue; + } + if(av[0].v == av[1].v) + { + continue; + } + /**********************test first node************************/ + NodeLen_first[0] = NodeLen_first[1] = NodeLen_first[2] = -1; + if(asg_is_single_edge(g, av[0].v, v>>1) <= 2 && asg_is_single_edge(g, av[1].v, v>>1) <= 2) + { + NodeLen_first[asg_is_single_edge(g, av[0].v, v>>1)] = 0; + NodeLen_first[asg_is_single_edge(g, av[1].v, v>>1)] = 1; + } + ///one node has one out-edge, another node has two out-edges + if(NodeLen_first[1] == -1 || NodeLen_first[2] == -1) + { + continue; + } + /**********************test first node************************/ + + ///if the potiential edge has already been removed + if(av[NodeLen_first[2]].del == 1) + { + continue; + } + + /**********************test second node************************/ + w = av[NodeLen_first[2]].v^1; + asg_arc_t *aw = asg_arc_a(g, w); + uint32_t nw = asg_arc_n(g, w); + if(nw != 2) + { + fprintf(stderr, "error\n"); + } + NodeLen_second[0] = NodeLen_second[1] = NodeLen_second[2] = -1; + if(asg_is_single_edge(g, aw[0].v, w>>1) <= 2 && asg_is_single_edge(g, aw[1].v, w>>1) <= 2) + { + NodeLen_second[asg_is_single_edge(g, aw[0].v, w>>1)] = 0; + NodeLen_second[asg_is_single_edge(g, aw[1].v, w>>1)] = 1; + } + ///one node has one out-edge, another node has two out-edges + if(NodeLen_second[1] == -1 || NodeLen_second[2] == -1) + { + continue; + } + + /**********************test second node************************/ + + if(if_node_exist(nodes, length, (w>>1)) && ((w>>1) != (endNode>>1))) + { + + uint32_t convex1 = 0, convex2 = 0, f1, f2; + long long l1 = 0, l2 = 0; + todel = 0; + f1 = detect_bubble_end_with_bubbles(g, av[0].v, av[1].v, &convex1, &l1, NULL); + f2 = detect_bubble_end_with_bubbles(g, aw[0].v, aw[1].v, &convex2, &l2, NULL); + if(f1 && f2) + { + if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1)) && + ((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) + { + if(l1 <= min_thres || l2 <= min_thres) + { + continue; + } + + todel = 1; + } + } + else if(f1) + { + if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1))) + { + if(l1 <= min_thres) + { + continue; + } + + todel = 1; + } + } + else if(f2) + { + if(((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) + { + if(l2 <= min_thres) + { + continue; + } + + todel = 1; + } + } + + + if(todel == 0) + { + if(!f1) + { + Ns_first[0] = av[0].v; Ns_first[1] = av[1].v; + f1 = asg_bub_end_finder_with_del_advance(g, Ns_first, 2, max_dist, + bub, 0, (uint32_t)-1, &convex1); + l1 = min_thres + 10; + } + + if(!f2) + { + Ns_second[0] = aw[0].v; Ns_second[1] = aw[1].v; + f2 = asg_bub_end_finder_with_del_advance(g, Ns_second, 2, max_dist, + bub, 0, (uint32_t)-1, &convex2); + l2 = min_thres + 10; + } + + + + + + if(f1 && f2) + { + if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1)) && + ((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) + { + if(l1 <= min_thres || l2 <= min_thres) + { + continue; + } + + todel = 1; + } + } + else if(f1) + { + if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1))) + { + if(l1 <= min_thres) + { + continue; + } + + todel = 1; + } + } + else if(f2) + { + if(((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) + { + if(l2 <= min_thres) + { + continue; + } + + todel = 1; + } + } + + } + + + if(todel) + { + av[NodeLen_first[2]].del = 1; + ///remove the reverse direction + asg_arc_del(g, av[NodeLen_first[2]].v^1, av[NodeLen_first[2]].ul>>32^1, 1); + n_reduced++; + } + + } + + } + + return n_reduced; +} + + + + + +int find_single_link(asg_t *g, uint32_t link_beg, int linkLen, uint32_t* link_end) +{ + uint32_t v, w; + v = link_beg^1; + uint32_t nv, nw; + asg_arc_t *av; + int edgeLen = 0; + + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + if(nv != 1) + { + return 0; + } + v = av[0].v; + + while (edgeLen < linkLen) + { + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + if(nv != 1) + { + return 0; + } + + w = v^1; + nw = asg_arc_n(g, w); + if(nw == 2) + { + (*link_end) = w; + return 1; + } + else if(nw > 2) + { + return 0; + } + + v = av[0].v; + edgeLen++; + } + + + return 0; +} + + +int if_edge_exist(asg_arc_t* edges, uint32_t length, uint32_t query) +{ + uint32_t i; + for (i = 0; i < length; ++i) + { + if((edges[i].v>>1) == query) + { + return 1; + } + } + + return 0; +} + +int test_quadangular_with_addition_node(asg_t *g, uint32_t* nodes, uint32_t length, +uint32_t addition_node_length) +{ + + uint32_t i, v, w; + int flag, occ_v_0, occ_v_1, occ_w_0, occ_w_1; + int n_reduced = 0; + uint32_t v_out2_node, w_out2_node; + uint32_t cut_edge_v, cut_edge_w; + for (i = 0; i < length; ++i) + { + v = nodes[i]; + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + if(nv != 1) + { + continue; + } + /**********************test first node************************/ + flag = asg_is_single_edge(g, av[0].v, v>>1); + if(flag != 2) + { + continue; + } + /**********************test first node************************/ + + if(!find_single_link(g, v, addition_node_length, &w)) + { + continue; + } + v = av[0].v^1; + ///up to now, v and w is the node what we want + asg_arc_t *aw = asg_arc_a(g, w); + uint32_t nw = asg_arc_n(g, w); + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + if(nv!=2 || nw != 2) + { + fprintf(stderr, "error\n"); + } + + if(!if_node_exist(nodes, length, (v>>1))) + { + continue; + } + if(!if_node_exist(nodes, length, (w>>1))) + { + continue; + } + /**********************for v************************/ + occ_v_0 = asg_is_single_edge(g, av[0].v, v>>1); + occ_v_1 = asg_is_single_edge(g, av[1].v, v>>1); + if(occ_v_0 == occ_v_1) + { + continue; + } + if(occ_v_0 < 1 || occ_v_0 > 2) + { + continue; + } + if(occ_v_1 < 1 || occ_v_1 > 2) + { + continue; + } + + if(occ_v_0 == 2) + { + v_out2_node = av[0].v^1; + cut_edge_v = 0; + } + else + { + v_out2_node = av[1].v^1; + cut_edge_v = 1; + } + if(!if_node_exist(nodes, length, (v_out2_node>>1))) + { + continue; + } + /**********************for v************************/ + + /**********************for w************************/ + occ_w_0 = asg_is_single_edge(g, aw[0].v, w>>1); + occ_w_1 = asg_is_single_edge(g, aw[1].v, w>>1); + if(occ_w_0 == occ_w_1) + { + continue; + } + if(occ_w_0 < 1 || occ_w_0 > 2) + { + continue; + } + if(occ_w_1 < 1 || occ_w_1 > 2) + { + continue; + } + + if(occ_w_0 == 2) + { + w_out2_node = aw[0].v^1; + cut_edge_w = 0; + } + else + { + w_out2_node = aw[1].v^1; + cut_edge_w = 1; + } + if(!if_node_exist(nodes, length, (w_out2_node>>1))) + { + continue; + } + /**********************for w************************/ + + + if(!if_edge_exist(asg_arc_a(g, w_out2_node), asg_arc_n(g, w_out2_node), (v_out2_node>>1))) + { + continue; + } + + if(!if_edge_exist(asg_arc_a(g, v_out2_node), asg_arc_n(g, v_out2_node), (w_out2_node>>1))) + { + continue; + } + + + av[cut_edge_v].del = 1; + ///remove the reverse direction + asg_arc_del(g, av[cut_edge_v].v^1, av[cut_edge_v].ul>>32^1, 1); + + aw[cut_edge_w].del = 1; + ///remove the reverse direction + asg_arc_del(g, aw[cut_edge_w].v^1, aw[cut_edge_w].ul>>32^1, 1); + + + n_reduced++; + } + + return n_reduced; +} + +int test_triangular_addition_exact(asg_t *g, uint32_t* nodes, uint32_t length, +uint32_t startNode, uint32_t endNode, int max_dist, buf_t* bub) +{ + + uint32_t i, j, v, w; + ///int flag0, flag1, node; + int n_reduced = 0, todel; + uint32_t Nodes1[2]={0}; + uint32_t Nodes2[2]={0}; + + uint32_t Ns_first[2]={0}; + uint32_t Ns_second[2]={0}; + + + + for (i = 0; i < length; ++i) + { + v = nodes[i]; + + if((v>>1) == (startNode>>1) || (v>>1) == (endNode>>1)) + { + continue; + } + + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + if(nv != 1) + { + continue; + } + if(asg_is_single_edge(g, av[0].v, v>>1) != 2) + { + continue; + } + + + w = v^1; + asg_arc_t *aw = asg_arc_a(g, w); + uint32_t nw = asg_arc_n(g, w); + if(nw != 1) + { + continue; + } + if(asg_is_single_edge(g, aw[0].v, w>>1) != 2) + { + continue; + } + + if((av[0].v>>1) == (aw[0].v>>1)) + { + continue; + } + + + + Nodes1[0] = av[0].v^1; + Nodes2[0] = aw[0].v^1; + + + for(j = 0; j < 2; j++) + { + if((asg_arc_a(g, Nodes1[0])[j].v>>1)!= (v>>1)) + { + Nodes1[1] = asg_arc_a(g, Nodes1[0])[j].v^1; + } + } + + for(j = 0; j < 2; j++) + { + if((asg_arc_a(g, Nodes2[0])[j].v>>1)!= (v>>1)) + { + Nodes2[1] = asg_arc_a(g, Nodes2[0])[j].v^1; + } + } + + if(asg_arc_n(g, Nodes1[1]) != 1 || asg_arc_n(g, Nodes2[1]) != 1) + { + continue; + } + + if((Nodes1[1]>>1) == (Nodes2[1]>>1)) + { + continue; + } + + + + if(asg_arc_a(g, Nodes1[1])[0].el == 0 || asg_arc_a(g, Nodes2[1])[0].el == 0) + { + continue; + } + + uint32_t convex1, convex2, f1, f2; + long long l1, l2; + todel = 0; + + if((Nodes1[0]^1) == (startNode^1) || (Nodes1[0]^1) == endNode) + { + continue; + } + if((Nodes2[1]^1) == (startNode^1) || (Nodes2[1]^1) == endNode) + { + continue; + } + + f1 = detect_bubble_end_with_bubbles(g, Nodes1[0]^1, Nodes2[1]^1, &convex1, &l1, NULL); + + + if((Nodes2[0]^1) == (startNode^1) || (Nodes2[0]^1) == endNode) + { + continue; + } + if((Nodes1[1]^1) == (startNode^1) || (Nodes1[1]^1) == endNode) + { + continue; + } + + f2 = detect_bubble_end_with_bubbles(g, Nodes2[0]^1, Nodes1[1]^1, &convex2, &l2, NULL); + + + if(f1 && f2) + { + if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1)) && + ((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) + { + if(l1 <= min_thres || l2 <= min_thres) + { + continue; + } + + todel = 1; + } + } + else if(f1) + { + if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1))) + { + if(l1 <= min_thres) + { + continue; + } + + todel = 1; + } + } + else if(f2) + { + if(((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) + { + if(l2 <= min_thres) + { + continue; + } + + todel = 1; + } + } + + if(todel == 0) + { + if(!f1) + { + Ns_first[0] = Nodes1[0]^1; Ns_first[1] = Nodes2[1]^1; + f1 = asg_bub_end_finder_with_del_advance(g, Ns_first, 2, max_dist, + bub, 0, (uint32_t)-1, &convex1); + l1 = min_thres + 10; + } + + if(!f2) + { + Ns_second[0] = Nodes2[0]^1; Ns_second[1] = Nodes1[1]^1; + f2 = asg_bub_end_finder_with_del_advance(g, Ns_second, 2, max_dist, + bub, 0, (uint32_t)-1, &convex2); + l2 = min_thres + 10; + } + + if(f1 && f2) + { + if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1)) && + ((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) + { + if(l1 <= min_thres || l2 <= min_thres) + { + continue; + } + + todel = 1; + } + } + else if(f1) + { + if(((convex1>>1) == (startNode>>1) || (convex1>>1) == (endNode>>1))) + { + if(l1 <= min_thres) + { + continue; + } + + todel = 1; + } + } + else if(f2) + { + if(((convex2>>1) == (startNode>>1) || (convex2>>1) == (endNode>>1))) + { + if(l2 <= min_thres) + { + continue; + } + + todel = 1; + } + } + + } + + + if(todel) + { + if(av[0].el == 0 || aw[0].el == 0) + { + av[0].del = 1; + asg_arc_del(g, av[0].v^1, av[0].ul>>32^1, 1); + + aw[0].del = 1; + asg_arc_del(g, aw[0].v^1, aw[0].ul>>32^1, 1); + + n_reduced++; + } + } + } + + return n_reduced; +} + +int asg_arc_del_triangular_advance(asg_t *g, long long max_dist) +{ + double startTime = Get_T(); + ///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, n_reduced_a = 0; + + + if (!g->is_symm) asg_symm(g); + + + buf_t b; + memset(&b, 0, sizeof(buf_t)); + b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + + + buf_t bub; + memset(&bub, 0, sizeof(buf_t)); + bub.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + + for (v = 0; v < n_vtx; ++v) + { + uint32_t nv = asg_arc_n(g, v); + if (g->seq[v>>1].del) + { + continue; + } + + if(nv < 2) + { + continue; + } + + + ///if this is a bubble + if(asg_bub_finder_with_del_advance(g, v, max_dist, &b) == 1) + { + n_reduced += test_triangular_exact(g, b.b.a, b.b.n, v, b.S.a[0], max_dist, &bub); + n_reduced_a += test_triangular_addition_exact(g, b.b.a, b.b.n, v, b.S.a[0],max_dist, &bub); + } + + } + + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + free(bub.a); free(bub.S.a); free(bub.T.a); free(bub.b.a); free(bub.e.a); + + if (n_reduced + n_reduced_a) { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d/%d triangular/triangular_a overlaps\n", + __func__, n_reduced, n_reduced_a); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + return n_reduced + n_reduced_a; +} + + + + + + +int check_if_cross(asg_t *g, uint32_t v) +{ + uint32_t N_list[5] = {0}; + if (g->seq[v>>1].del) return 0; + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + if(nv != 2) return 0; + if(asg_is_single_edge(g, av[0].v, v>>1) != 2 || asg_is_single_edge(g, av[1].v, v>>1) != 2) + { + return 0; + } + if(av[0].v == av[1].v) + { + return 0; + } + N_list[0] = v; + N_list[1] = av[0].v^1; + N_list[2] = av[1].v^1; + if(asg_arc_n(g, N_list[0]) != 2 || + asg_arc_n(g, N_list[1]) != 2 || + asg_arc_n(g, N_list[2]) != 2 ) + { + return 0; + } + + if(asg_arc_a(g, N_list[1])[0].v == asg_arc_a(g, N_list[1])[1].v) + { + return 0; + } + + if(asg_arc_a(g, N_list[2])[0].v == asg_arc_a(g, N_list[2])[1].v) + { + return 0; + } + + if(asg_arc_a(g, N_list[1])[0].v == (N_list[0]^1)) + { + N_list[3] = asg_arc_a(g, N_list[1])[1].v^1; + } + else if(asg_arc_a(g, N_list[1])[1].v == (N_list[0]^1)) + { + N_list[3] = asg_arc_a(g, N_list[1])[0].v^1; + } + + if(asg_arc_a(g, N_list[2])[0].v == (N_list[0]^1)) + { + N_list[4] = asg_arc_a(g, N_list[2])[1].v^1; + } + else if(asg_arc_a(g, N_list[2])[1].v == (N_list[0]^1)) + { + N_list[4] = asg_arc_a(g, N_list[2])[0].v^1; + } + + if(N_list[3] != N_list[4]) + { + return 0; + } + + if(asg_arc_n(g, N_list[0]) != 2 || + asg_arc_n(g, N_list[1]) != 2 || + asg_arc_n(g, N_list[2]) != 2 || + asg_arc_n(g, N_list[3]) != 2) + { + return 0; + } + + + uint32_t convex1, convex2, f1, f2; + long long l1, l2; + l1 = l2 = 0; + int todel = 0; + + f1 = detect_bubble_end_with_bubbles(g, N_list[0]^1, N_list[3]^1, &convex1, &l1, NULL); + f2 = detect_bubble_end_with_bubbles(g, N_list[1]^1, N_list[2]^1, &convex2, &l2, NULL); + + if(f1 && f2)///full bubble + { + if(l1 > min_thres && l2 > min_thres) + { + todel = 1; + } + } + else if(f1)//semi bubble + { + if(l1 > min_thres) + { + todel = 1; + } + } + else if(f2)//semi bubble + { + if(l2 > min_thres) + { + todel = 1; + } + } + + + return todel; +} + + + + +typedef struct { + int threadID; + int thread_num; + int check_cross; + asg_t *g; +} para_for_simple_bub; + +void* asg_arc_identify_simple_bubbles_pthread(void* arg) +{ + int thr_ID = ((para_for_simple_bub*)arg)->threadID; + int thr_num = ((para_for_simple_bub*)arg)->thread_num; + asg_t *g = ((para_for_simple_bub*)arg)->g; + int check_cross = ((para_for_simple_bub*)arg)->check_cross; + ///the reason is that each read has two direction (query->target, target->query) + + uint32_t v, w, n_vtx = g->n_seq * 2; + buf_t b; + memset(&b, 0, sizeof(buf_t)); + long long l, i; + ///for (v = 0; v < n_vtx; ++v) + for (v = thr_ID; v < n_vtx; v = v + thr_num) + { + if (g->seq[v>>1].del) continue; + + b.b.n = 0; + + if(g->seq_vis[v] != 1) + { + ///if(detect_bubble_with_bubbles(g, v, &w, &l, &b, (uint32_t)-1)) + if(detect_bubble_with_bubbles(g, v, &w, &l, &b, SMALL_BUBBLE_SIZE)) + { + for (i = 0; i < (long long)b.b.n; i++) + { + if(b.b.a[i] != (v>>1) && b.b.a[i] != (w>>1)) + { + g->seq_vis[b.b.a[i]<<1] = 1; + g->seq_vis[(b.b.a[i]<<1) + 1] = 1; + } + } + g->seq_vis[v] = 1; + g->seq_vis[w^1] = 1; + } + } + + if(check_cross == 1 && check_if_cross(g, v)) + { + g->seq_vis[v] = 2; + } + } + free(b.b.a); + + free(arg); + + return NULL; +} + +int asg_arc_identify_simple_bubbles_multi_back(asg_t *g, int check_cross) +{ + double startTime = Get_T(); + memset(g->seq_vis, 0, g->n_seq*2*sizeof(uint8_t)); + + pthread_t *_r_threads; + + _r_threads = (pthread_t *)malloc(sizeof(pthread_t)*asm_opt.thread_num); + + int i = 0; + + for (i = 0; i < asm_opt.thread_num; i++) + { + para_for_simple_bub* arg = (para_for_simple_bub*)malloc(sizeof(*arg)); + arg->g = g; + arg->thread_num = asm_opt.thread_num; + arg->threadID = i; + arg->check_cross = check_cross; + + pthread_create(_r_threads + i, NULL, asg_arc_identify_simple_bubbles_pthread, (void*)arg); + } + + + for (i = 0; in_seq * 2; + long long nodes, bub_nodes, cross_nodes; + bub_nodes = nodes = cross_nodes = 0; + for (v = 0; v < n_vtx; ++v) + { + if (g->seq[v>>1].del) continue; + nodes++; + if(g->seq_vis[v] == 1) bub_nodes++; + if(g->seq_vis[v] == 2) cross_nodes++; + } + + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return bub_nodes+cross_nodes; +} + +uint64_t asg_bub_pop1_label(asg_t *g, uint32_t v0, uint64_t max_dist, buf_s_t *b); +static void bubble_identify_worker(void *_data, long eid, int tid) +{ + bub_label_t *buf = (bub_label_t*)_data; + buf_s_t *b = &(buf->b[tid]); + uint32_t v = eid, i; + asg_t *g = buf->g; + if(g->seq[v>>1].del) return; + if(asg_arc_n(g, v) < 2 || get_real_length(g, v, NULL) < 2) return; + + if(g->seq_vis[v] != 1 && asg_bub_pop1_label(g, v, buf->bub_dist, b)) + { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (i = 0; i < b->b.n; i++) + { + if(b->b.a[i]==v || b->b.a[i]==b->S.a[0]) continue; + g->seq_vis[b->b.a[i]] = 1; + g->seq_vis[b->b.a[i]^1] = 1; + } + g->seq_vis[v] = 1; + g->seq_vis[b->S.a[0]^1] = 1; + } + + if(buf->check_cross == 1 && g->seq_vis[v] == 0 && check_if_cross(g, v)) + { + g->seq_vis[v] = 2; + } +} + +uint64_t get_s_bub_pop_max_dist_advance(asg_t *g, buf_s_t *b); +int asg_arc_identify_simple_bubbles_multi(asg_t *g, bub_label_t* x, int check_cross) +{ + double startTime = Get_T(); + memset(g->seq_vis, 0, g->n_seq*2*sizeof(uint8_t)); + uint64_t bub_dist = get_s_bub_pop_max_dist_advance(g, &(x->b[0])); + ///fprintf(stderr, "+++[M::%s] takes %0.2f s, bub_dist: %lu\n\n", __func__, Get_T()-startTime, bub_dist); + // startTime = Get_T(); + + reset_bub_label_t(x, g, bub_dist, check_cross); + kt_for(x->n_thres, bubble_identify_worker, x, g->n_seq<<1); + uint32_t v, n_vtx = g->n_seq<<1; + long long nodes, bub_nodes, cross_nodes; + bub_nodes = nodes = cross_nodes = 0; + for (v = 0; v < n_vtx; ++v) + { + if (g->seq[v>>1].del) continue; + nodes++; + if(g->seq_vis[v] == 1) bub_nodes++; + if(g->seq_vis[v] == 2) cross_nodes++; + } + ///fprintf(stderr, "---[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return bub_nodes+cross_nodes; +} + +int check_small_bubble(asg_t *g, uint32_t begNode, uint32_t v, uint32_t w, +long long* vLen, long long* wLen, uint32_t* endNode) +{ + uint32_t nv = asg_arc_n(g, v); + uint32_t nw = asg_arc_n(g, w); + + asg_arc_t *av = asg_arc_a(g, v); + asg_arc_t *aw = asg_arc_a(g, w); + if(nv != 1 || nw != 1) + { + return 0; + } + + ///first node + ///nv must be 1 + if(asg_is_single_edge(g, av[0].v, v>>1) == 2) + { + uint32_t vv; + vv = av[0].v^1; + + if( + asg_is_single_edge(g, asg_arc_a(g, vv)[0].v, vv>>1) == 1 + && + asg_is_single_edge(g, asg_arc_a(g, vv)[1].v, vv>>1) == 1 + ) + { + ///walk along first path + long long pLen1; + pLen1 = single_edge_length(g, asg_arc_a(g, vv)[0].v, begNode>>1, 1000); + + ///walk along first path + long long pLen2; + pLen2 = single_edge_length(g, asg_arc_a(g, vv)[1].v, begNode>>1, 1000); + + + + if(pLen1 >= 0 && pLen2 >= 0) + { + if(((asg_arc_a(g, vv)[0].v) == (v^1)) && pLen1 == 1) + { + (*vLen) = pLen1; + (*wLen) = pLen2; + } + else if(((asg_arc_a(g, vv)[1].v) == (v^1)) && pLen2 == 1) + { + (*vLen) = pLen2; + (*wLen) = pLen1; + } + else + { + fprintf(stderr, "error\n"); + } + ///(*endNode) = vv>>1; + (*endNode) = vv; + return 1; + } + + } + } + + + ///second node + ///nw must be 1 + if(asg_is_single_edge(g, aw[0].v, w>>1) == 2) + { + uint32_t ww; + ww = aw[0].v^1; + + if( + asg_is_single_edge(g, asg_arc_a(g, ww)[0].v, ww>>1) == 1 + && + asg_is_single_edge(g, asg_arc_a(g, ww)[1].v, ww>>1) == 1 + ) + { + ///walk along first path + long long pLen1; + pLen1 = single_edge_length(g, asg_arc_a(g, ww)[0].v, begNode>>1, 1000); + + ///walk along first path + long long pLen2; + pLen2 = single_edge_length(g, asg_arc_a(g, ww)[1].v, begNode>>1, 1000); + + if(pLen1 >= 0 && pLen2 >= 0) + { + if(((asg_arc_a(g, ww)[0].v) == (w^1)) && pLen1 == 1) + { + (*wLen) = pLen1; + (*vLen) = pLen2; + } + else if(((asg_arc_a(g, ww)[1].v) == (w^1)) && pLen2 == 1) + { + (*wLen) = pLen2; + (*vLen) = pLen1; + } + else + { + fprintf(stderr, "error\n"); + } + + //(*endNode) = ww>>1; + (*endNode) = ww; + + return 1; + } + } + } + + return 0; + +} + + +int test_single_node_bubble(asg_t *g, uint32_t* nodes, uint32_t length, +uint32_t startNode, uint32_t endNode) +{ + + uint32_t i, v, w; + uint32_t vEnd; + int flag0, flag1; + int n_reduced = 0; + long long Len[2], longLen; + long long longLen_thres = 4; + for (i = 0; i < length; ++i) + { + v = nodes[i]; + + if((v>>1) == (startNode>>1) || (v>>1) == (endNode>>1)) + { + continue; + } + + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + if(nv != 2) + { + continue; + } + + + flag0 = asg_is_single_edge(g, av[0].v, v>>1); + flag1 = asg_is_single_edge(g, av[1].v, v>>1); + if(flag0 != 1 || flag1 != 1) + { + continue; + } + + if(check_small_bubble(g, v, av[0].v, av[1].v, &(Len[0]), &(Len[1]), &vEnd)) + { + + if(if_node_exist(nodes, length, vEnd>>1) && ((vEnd>>1) != (endNode>>1))) + { + + if(Len[0] == 1 && Len[1] != 1) + { + w = av[0].v; + longLen = Len[1]; + + /****************************may have bugs********************************/ + if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) + { + // fprintf(stderr, "w>>1: %u, beg: %u, end: %u\n", + // w>>1, startNode>>1, endNode>>1); + asg_seq_del(g, w>>1); + n_reduced++; + }///up to here w is exactly overlapped in both directions + else if(longLen >= longLen_thres) + { + if(av[0].el == 1 && av[1].el == 1 + && + asg_arc_a(g, vEnd)[0].el == 1 && asg_arc_a(g, vEnd)[1].el == 1) + { + asg_seq_del(g, w>>1); + n_reduced++; + } + } + + /****************************may have bugs********************************/ + + } + else if(Len[0] != 1 && Len[1] == 1) + { + w = av[1].v; + longLen = Len[0]; + + /****************************may have bugs********************************/ + if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) + { + // fprintf(stderr, "w>>1: %u, beg: %u, end: %u\n", + // w>>1, startNode>>1, endNode>>1); + asg_seq_del(g, w>>1); + n_reduced++; + }///up to here w is exactly overlapped in both directions + else if(longLen >= longLen_thres) + { + if(av[0].el == 1 && av[1].el == 1 + && + asg_arc_a(g, vEnd)[0].el == 1 && asg_arc_a(g, vEnd)[1].el == 1) + { + asg_seq_del(g, w>>1); + n_reduced++; + } + } + /****************************may have bugs********************************/ + } + else if(Len[0] == 1 && Len[1] == 1) + { + w = av[0].v; + flag0 = asg_arc_a(g, w)[0].el + asg_arc_a(g, w^1)[0].el; + w = av[1].v; + flag1 = asg_arc_a(g, w)[0].el + asg_arc_a(g, w^1)[0].el; + ///>=2 means this is an exact overlap + if(flag0 < 2 && flag1 >= 2) + { + w = av[0].v; + + /****************************may have bugs********************************/ + if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) + { + // fprintf(stderr, "w>>1: %u, beg: %u, end: %u\n", + // w>>1, startNode>>1, endNode>>1); + asg_seq_del(g, w>>1); + n_reduced++; + } + /****************************may have bugs********************************/ + } + + if(flag0 >= 2 && flag1 < 2) + { + w = av[1].v; + + /****************************may have bugs********************************/ + if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) + { + // fprintf(stderr, "w>>1: %u, beg: %u, end: %u\n", + // w>>1, startNode>>1, endNode>>1); + asg_seq_del(g, w>>1); + n_reduced++; + } + /****************************may have bugs********************************/ + } + } + else + { + fprintf(stderr, "error\n"); + } + + } + } + + } + + return n_reduced; +} + + +int test_single_node_bubble_directly(asg_t *g, uint32_t v, long long longLen_thres, ma_hit_t_alloc* sources) +{ + uint32_t w, vEnd; + int flag0, flag1; + int n_reduced = 0; + long long Len[2], longLen; + ///long long longLen_thres = 4; + + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + if(nv != 2) + { + return 0; + } + + + flag0 = asg_is_single_edge(g, av[0].v, v>>1); + flag1 = asg_is_single_edge(g, av[1].v, v>>1); + if(flag0 != 1 || flag1 != 1) + { + return 0; + } + + if(check_small_bubble(g, v, av[0].v, av[1].v, &(Len[0]), &(Len[1]), &vEnd)) + { + if(Len[0] == 1 && Len[1] != 1) + { + w = av[0].v; + longLen = Len[1]; + + /****************************may have bugs********************************/ + ///if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) + if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0 || sources[w>>1].is_abnormal == 1) + { + asg_seq_del(g, w>>1); + n_reduced++; + }///up to here w is exactly overlapped in both directions + else if(longLen >= longLen_thres) + { + if(av[0].el == 1 && av[1].el == 1 + && + asg_arc_a(g, vEnd)[0].el == 1 && asg_arc_a(g, vEnd)[1].el == 1) + { + asg_seq_del(g, w>>1); + n_reduced++; + } + } + + /****************************may have bugs********************************/ + + } + else if(Len[0] != 1 && Len[1] == 1) + { + w = av[1].v; + longLen = Len[0]; + + /****************************may have bugs********************************/ + ///if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) + if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0 || sources[w>>1].is_abnormal == 1) + { + asg_seq_del(g, w>>1); + n_reduced++; + }///up to here w is exactly overlapped in both directions + else if(longLen >= longLen_thres) + { + if(av[0].el == 1 && av[1].el == 1 + && + asg_arc_a(g, vEnd)[0].el == 1 && asg_arc_a(g, vEnd)[1].el == 1) + { + asg_seq_del(g, w>>1); + n_reduced++; + } + } + /****************************may have bugs********************************/ + } + else if(Len[0] == 1 && Len[1] == 1) + { + flag0 = sources[av[0].v>>1].is_abnormal; + flag1 = sources[av[1].v>>1].is_abnormal; + + if(flag0 == 1 && flag1 == 0) + { + asg_seq_del(g, av[0].v>>1); + n_reduced++; + } + else if(flag0 == 0 && flag1 == 1) + { + asg_seq_del(g, av[1].v>>1); + n_reduced++; + } + else + { + w = av[0].v; + flag0 = asg_arc_a(g, w)[0].el + asg_arc_a(g, w^1)[0].el; + w = av[1].v; + flag1 = asg_arc_a(g, w)[0].el + asg_arc_a(g, w^1)[0].el; + ///>=2 means this is an exact overlap + if(flag0 < 2 && flag1 >= 2) + { + w = av[0].v; + + /****************************may have bugs********************************/ + if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) + { + asg_seq_del(g, w>>1); + n_reduced++; + } + /****************************may have bugs********************************/ + } + + if(flag0 >= 2 && flag1 < 2) + { + w = av[1].v; + + /****************************may have bugs********************************/ + if(asg_arc_a(g, w)[0].el == 0 || asg_arc_a(g, w^1)[0].el == 0) + { + asg_seq_del(g, w>>1); + n_reduced++; + } + /****************************may have bugs********************************/ + } + } + } + + } + return n_reduced; +} + + +int asg_arc_del_single_node_directly(asg_t *g, long long longLen_thres, ma_hit_t_alloc* sources) +{ + double startTime = Get_T(); + ///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; + for (v = 0; v < n_vtx; ++v) + { + uint32_t nv = asg_arc_n(g, v); + if (g->seq[v>>1].del) + { + continue; + } + + if(nv != 2) + { + continue; + } + + n_reduced += test_single_node_bubble_directly(g, v, longLen_thres, sources); + } + + + if (n_reduced) { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d small bubbles\n", __func__, n_reduced); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + return n_reduced; +} + + + +int test_cross(asg_t *g, uint32_t* nodes, uint32_t length, +uint32_t startNode, uint32_t endNode) +{ + uint32_t a1, a2; + uint32_t N_list[5] = {0}; + uint32_t i, v; + int flag0, flag1; + int n_reduced = 0; + for (i = 0; i < length; ++i) + { + v = nodes[i]; + + if((v>>1) == (startNode>>1) || (v>>1) == (endNode>>1)) + { + continue; + } + + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + if(nv != 2) + { + continue; + } + if(av[0].v == av[1].v) + { + continue; + } + flag0 = asg_is_single_edge(g, av[0].v, v>>1); + flag1 = asg_is_single_edge(g, av[1].v, v>>1); + + if(flag0 != 2 || flag1 != 2) + { + continue; + } + + + N_list[0] = v; + N_list[1] = av[0].v^1; + N_list[2] = av[1].v^1; + + if(asg_arc_n(g, N_list[0]) != 2 || + asg_arc_n(g, N_list[1]) != 2 || + asg_arc_n(g, N_list[2]) != 2 ) + { + continue; + } + + if(asg_arc_a(g, N_list[1])[0].v == asg_arc_a(g, N_list[1])[1].v) + { + continue; + } + + if(asg_arc_a(g, N_list[2])[0].v == asg_arc_a(g, N_list[2])[1].v) + { + continue; + } + + + if(asg_arc_a(g, N_list[1])[0].v == (N_list[0]^1)) + { + N_list[3] = asg_arc_a(g, N_list[1])[1].v^1; + } + else if(asg_arc_a(g, N_list[1])[1].v == (N_list[0]^1)) + { + N_list[3] = asg_arc_a(g, N_list[1])[0].v^1; + } + else + { + fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__); + } + + if(asg_arc_a(g, N_list[2])[0].v == (N_list[0]^1)) + { + N_list[4] = asg_arc_a(g, N_list[2])[1].v^1; + } + else if(asg_arc_a(g, N_list[2])[1].v == (N_list[0]^1)) + { + N_list[4] = asg_arc_a(g, N_list[2])[0].v^1; + } + else + { + fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__); + } + + if(N_list[3] != N_list[4]) + { + continue; + } + + if(asg_arc_n(g, N_list[0]) != 2 || + asg_arc_n(g, N_list[1]) != 2 || + asg_arc_n(g, N_list[2]) != 2 || + asg_arc_n(g, N_list[3]) != 2) + { + continue; + } + /** + N_list[3] N_list[0] + + N_list[2] N_list[1] + **/ + if(asg_arc_a(g, N_list[0])[0].el == asg_arc_a(g, N_list[0])[1].el) + { + continue; + } + + if(asg_arc_a(g, N_list[0])[0].el == 1) + { + //a1 = asg_arc_a(g, N_list[0])[0].v >> 1; + a1 = 0; + } + else + { + ///a1 = asg_arc_a(g, N_list[0])[1].v >> 1; + a1 = 1; + } + + + + + + + if(asg_arc_a(g, N_list[3])[0].el == asg_arc_a(g, N_list[3])[1].el) + { + continue; + } + + if(asg_arc_a(g, N_list[3])[0].el == 1) + { + //a2 = asg_arc_a(g, N_list[3])[0].v >> 1; + a2 = 0; + } + else + { + //a2 = asg_arc_a(g, N_list[3])[1].v >> 1; + a2 = 1; + } + + if( + (asg_arc_a(g, N_list[0])[a1].v >> 1) + != + (asg_arc_a(g, N_list[3])[a2].v >> 1) + ) + { + if(((N_list[0]>>1) != (endNode>>1)) && + ((N_list[1]>>1) != (endNode>>1)) && + ((N_list[2]>>1) != (endNode>>1)) && + ((N_list[3]>>1) != (endNode>>1))) + { + asg_arc_a(g, N_list[0])[a1].del = 1; + asg_arc_del(g, asg_arc_a(g, N_list[0])[a1].v^1, + asg_arc_a(g, N_list[0])[a1].ul>>32^1, 1); + + + asg_arc_a(g, N_list[3])[a2].del = 1; + asg_arc_del(g, asg_arc_a(g, N_list[3])[a2].v^1, + asg_arc_a(g, N_list[3])[a2].ul>>32^1, 1); + n_reduced++; + } + } + } + + return n_reduced; +} + +int asg_arc_del_cross_bubble(asg_t *g, long long max_dist) +{ + double startTime = Get_T(); + ///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; + buf_t b; + if (!g->is_symm) asg_symm(g); + memset(&b, 0, sizeof(buf_t)); + ///set information for each node + b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + for (v = 0; v < n_vtx; ++v) + { + uint32_t nv = asg_arc_n(g, v); + if (g->seq[v>>1].del) + { + continue; + } + + if(nv < 2) + { + continue; + } + + ///if this is a bubble + if(asg_bub_finder_with_del_advance(g, v, max_dist, &b) == 1) + { + n_reduced += test_cross(g, b.b.a, b.b.n, v, b.S.a[0]); + } + + } + + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + + if (n_reduced) { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d cross\n", __func__, n_reduced); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + return n_reduced; +} + + + +// transitive reduction; see Myers, 2005 +int asg_arc_del_trans(asg_t *g, int fuzz) +{ + double startTime = Get_T(); + + uint8_t *mark; + ///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 + mark = (uint8_t*)calloc(n_vtx, 1); + + /**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) mark[av[i].v] = 1; + + ///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) { + //w is an out-node of v + 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 w has already been reduced + if (mark[av[i].v] != 1) continue; + + for (j = 0; j < nw && asg_arc_len(aw[j]) + asg_arc_len(av[i]) <= L; ++j) + if (mark[aw[j].v]) mark[aw[j].v] = 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 (mark[aw[j].v]) mark[aw[j].v] = 2; + } + #endif + //remove edges + for (i = 0; i < nv; ++i) { + if (mark[av[i].v] == 2) av[i].del = 1, ++n_reduced; + mark[av[i].v] = 0; + } + } + free(mark); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] transitively reduced %d arcs\n", __func__, n_reduced); + } + + if (n_reduced) { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return n_reduced; +} + + +int asg_arc_del_trans_ul(asg_t *g, int fuzz) +{ + uint32_t v, n_vtx = g->n_seq<<1, n_reduced = 0, L, i, nv; + uint8_t *mark; asg_arc_t *av; CALLOC(mark, n_vtx); + uint32_t w, j, nw; asg_arc_t *aw; + + for (v = 0; v < n_vtx; ++v) { + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + if (nv == 0) continue; // no hits + if (g->seq[v>>1].del) { + for (i = 0; i < nv; ++i) av[i].del = 1, ++n_reduced; + continue; + } + /** + 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) mark[av[i].v] = 1; + + ///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) { + //w is an out-node of v + w = av[i].v; + nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); + ///if w has already been reduced + if (mark[av[i].v] != 1) continue; + + for (j = 0; j < nw && asg_arc_len(aw[j]) + asg_arc_len(av[i]) <= L; ++j) + if (mark[aw[j].v]) mark[aw[j].v] = 2; + } + + // for (i = 0; i < nv; ++i) { + // if((av[i].del) || (mark[av[i].v] != 1)) continue; + // w = av[i].v; + // nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); + // for (j = 0; j < nw && asg_arc_len(aw[j]) + asg_arc_len(av[i]) <= L; ++j) { + // if(v == 20996 && w == 21011) { + // fprintf(stderr, "(0):v->%u, ou->%u\n", aw[j].v, aw[j].ou); + // } + + // if (mark[aw[j].v] == 2) { + // if((((uint32_t)av[i].ou) + ((uint32_t)aw[j].ou)) <= OU_MASK) { + // av[i].ou = av[i].ou + aw[j].ou; + // } else { + // av[i].ou = OU_MASK; + // } + // } + // } + // } + //remove edges + for (i = 0; i < nv; ++i) { + if (mark[av[i].v] == 2) { + av[i].del = 1, ++n_reduced; + } + mark[av[i].v] = 0; + } + } + free(mark); + asg_cleanup(g); + asg_symm(g); + // prt_specfic_sge(g, 10498, 10505, __func__); + // normalize_gou(g); + + return n_reduced; +} + +///max_ext is 4 +int asg_cut_tip(asg_t *g, int max_ext) +{ + double startTime = Get_T(); + + asg64_v a = {0,0,0}; + uint32_t n_vtx = g->n_seq * 2, v, i, cnt = 0; + + for (v = 0; v < n_vtx; ++v) { + //if this seq has been deleted + if (g->seq[v>>1].del) continue; + ///check if the another direction of v has no overlaps + ///if the self direction of v has no overlaps, we don't have the overlaps of them + ///here is check if the reverse direction of v + /** + the following first line is to find (means v is a node has no prefix): + (v)--->()---->()---->()----->.... + another case is: + ......()---->()---->()----->()------>(v) + this case can be found by (v^1), so we don't need to process this case here + **/ + if (asg_is_utg_end(g, v, 0) != ASG_ET_TIP) continue; // not a tip + /** + the following second line is: + (v)--->()---->()---->()----->() + |--------max_ext-------| + **/ + ///that means here is a long tip, which is longer than max_ext + if (asg_extend(g, v, max_ext, &a) == ASG_ET_MERGEABLE) continue; // not a short unitig + + /** + * so combining the last two lines, they are designed to reomve(n(0), n(1), n(2)): + * ----->n(4) + * | + * n(0)--->n(1)---->n(2)---->n(3) + * | + * ----->n(5) + **/ + for (i = 0; i < a.n; ++i) + asg_seq_del(g, (uint32_t)a.a[i]>>1); + ++cnt; + } + free(a.a); + if (cnt > 0) asg_cleanup(g); + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] cut %d tips\n", __func__, cnt); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return cnt; +} + + +// delete short arcs +///for best graph? +int asg_arc_del_short(asg_t *g, float drop_ratio) +{ + uint32_t v, n_vtx = g->n_seq * 2, n_short = 0; + for (v = 0; v < n_vtx; ++v) { + asg_arc_t *av = asg_arc_a(g, v); + uint32_t i, thres, nv = asg_arc_n(g, v); + ///if there is just one overlap, do nothing + if (nv < 2) continue; + //av[0] has the most overlap length + ///remove short overlaps + thres = (uint32_t)(av[0].ol * drop_ratio + .499); + ///av has been sorted by overlap length + for (i = nv - 1; i >= 1 && av[i].ol < thres; --i); + for (i = i + 1; i < nv; ++i) + av[i].del = 1, ++n_short; + } + if (n_short) { + asg_cleanup(g); + asg_symm(g); + } + fprintf(stderr, "[M::%s] removed %d short overlaps\n", __func__, n_short); + return n_short; +} + + +inline int check_weak_ma_hit(ma_hit_t_alloc* aim_paf, ma_hit_t_alloc* reverse_paf_list, +long long weakID, uint32_t w_qs, uint32_t w_qe) +{ + long long i = 0; + long long strongID, index; + for (i = 0; i < aim_paf->length; i++) + { + ///if this is a strong overlap + if ( + aim_paf->buffer[i].del == 0 + && + aim_paf->buffer[i].ml == 1 + && + Get_qs(aim_paf->buffer[i]) <= w_qs + && + Get_qe(aim_paf->buffer[i]) >= w_qe) + { + strongID = Get_tn(aim_paf->buffer[i]); + index = get_specific_overlap(&(reverse_paf_list[strongID]), strongID, weakID); + if(index != -1) { + // if((Get_qn(aim_paf->buffer[i]) == 27087 && weakID == 27128) || (Get_qn(aim_paf->buffer[i]) == 27128 && weakID == 27087)) { + // ma_hit_t *h = &(aim_paf->buffer[i]); + // fprintf(stderr, "[M::%s]\t%.*s(qn::%u)\t%u\t%u\t%u\t%c\t%.*s(tn::%u)\t%u\t%u\t%u\t%u\t%u\t255\n", __func__, (int)Get_NAME_LENGTH(R_INF, Get_qn(*h)), Get_NAME((R_INF), Get_qn(*h)), Get_qn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_qn(*h)), Get_qs(*h), Get_qe(*h), "+-"[h->rev], + // (int)Get_NAME_LENGTH(R_INF, Get_tn(*h)), Get_NAME((R_INF), Get_tn(*h)), Get_tn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_tn(*h)), Get_ts(*h), Get_te(*h), h->ml, h->bl); + // } + return 0; + } + } + } + + return 1; +} + + +inline int check_weak_ma_hit_reverse(ma_hit_t_alloc* r_paf, ma_hit_t_alloc* r_paf_source, +long long weakID) +{ + long long i = 0; + long long strongID, index; + ///all overlaps coming from another haplotye are strong + for (i = 0; i < r_paf->length; i++) + { + strongID = Get_tn(r_paf->buffer[i]); + index = get_specific_overlap + (&(r_paf_source[strongID]), strongID, weakID); + ///must be a strong overlap + if(index != -1 && r_paf_source[strongID].buffer[index].ml == 1) + { + return 0; + } + } + + return 1; +} + + +inline int check_weak_ma_hit_debug(ma_hit_t_alloc* aim_paf, ma_hit_t_alloc* reverse_paf_list, +long long weakID) +{ + long long i = 0; + long long strongID, index; + for (i = 0; i < aim_paf->length; i++) + { + ///if this is a strong overlap + if (aim_paf->buffer[i].ml == 1) + { + strongID = Get_tn(aim_paf->buffer[i]); + index = get_specific_overlap(&(reverse_paf_list[strongID]), strongID, weakID); + if(index != -1) + { + return strongID; + } + } + + + } + + return 0; +} + + + +// delete short arcs +///for best graph? +int asg_arc_del_short_diploid_unclean(asg_t *g, float drop_ratio, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources) +{ + double startTime = Get_T(); + + uint32_t v, n_vtx = g->n_seq * 2, n_short = 0; + uint32_t last_e; + for (v = 0; v < n_vtx; ++v) + { + if (g->seq[v>>1].del) continue; + + asg_arc_t *av = asg_arc_a(g, v); + uint32_t i, thres, nv = asg_arc_n(g, v); + ///if there is just one overlap, do nothing + if (nv < 2) continue; + //av[0] has the most overlap length + ///remove short overlaps + thres = (uint32_t)(av[0].ol * drop_ratio + .499); + ///av has been sorted by overlap length + for (i = nv - 1; i >= 1 && av[i].ol < thres; --i) {} + last_e = i + 1; + + for (i = i + 1; i < nv; ++i) + av[i].del = 1, ++n_short; + + + if(nv >= 2 && av[1].del == 1) + { + ///second longest + av[1].del = 0; + --n_short; + last_e++; + } + + } + ///if (n_short) + { + asg_cleanup(g); + asg_symm(g); + } + fprintf(stderr, "[M::%s] removed %d short overlaps\n", __func__, n_short); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + + return n_short; +} + + + + + + + + + +/*****************************read graph*****************************/ + +uint32_t detect_single_path_with_dels(asg_t *g, uint32_t begNode, uint32_t* endNode, long long* Len, buf_t* b) +{ + uint32_t v = begNode, w; + uint32_t kv, kw; + (*Len) = 0; + + while (1) + { + (*Len)++; + kv = get_real_length(g, v, NULL); + (*endNode) = v; + + if(b) kv_push(uint32_t, b->b, v>>1); + + if(kv == 0) + { + return END_TIPS; + } + + if(kv == 2) + { + return TWO_OUTPUT; + } + + if(kv > 2) + { + return MUL_OUTPUT; + } + + ///up to here, kv=1 + ///kw must >= 1 + get_real_length(g, v, &w); + kw = get_real_length(g, w^1, NULL); + v = w; + (*endNode) = v; + + + if(kw == 2) + { + (*Len)++; + if(b) kv_push(uint32_t, b->b, v>>1); + return TWO_INPUT; + } + + if(kw > 2) + { + (*Len)++; + if(b) kv_push(uint32_t, b->b, v>>1); + return MUL_INPUT; + } + + + if((v>>1) == (begNode>>1)) + { + return LOOP; + } + } + + return LONG_TIPS; +} + +uint32_t detect_single_path_with_dels_n_stops(asg_t *g, uint32_t begNode, uint32_t* endNode, +long long* Len, long long* max_stop_Len, buf_t* b, uint32_t stops_threshold) +{ + + uint32_t v = begNode, w; + uint32_t kv, kw, n_stops = 0, flag = LONG_TIPS; + (*Len) = 0; + (*max_stop_Len) = 0; + long long preLen = 0, currentLen; + + while (1) + { + (*Len)++; + kv = get_real_length(g, v, NULL); + (*endNode) = v; + + if(b) kv_push(uint32_t, b->b, v>>1); + + if(kv == 0) + { + flag = END_TIPS; + break; + } + + if(kv == 2) + { + flag = TWO_OUTPUT; + break; + } + + if(kv > 2) + { + flag = MUL_OUTPUT; + break; + } + + ///up to here, kv=1 + ///kw must >= 1 + get_real_length(g, v, &w); + kw = get_real_length(g, w^1, NULL); + v = w; + (*endNode) = v; + + if(kw >= 2) + { + n_stops++; + currentLen = (*Len) - preLen; + preLen = (*Len); + if(currentLen > (*max_stop_Len)) + { + (*max_stop_Len) = currentLen; + } + } + if(kw >= 2 && n_stops >= stops_threshold) + { + (*Len)++; + if(b) kv_push(uint32_t, b->b, v>>1); + if(kw == 2) flag = TWO_INPUT; + if(kw > 2) flag = MUL_INPUT; + break; + } + + if((v>>1) == (begNode>>1)) + { + flag = LOOP; + break; + } + } + + + currentLen = (*Len) - preLen; + preLen = (*Len); + if(currentLen > (*max_stop_Len)) + { + (*max_stop_Len) = currentLen; + } + return flag; +} + +uint32_t detect_single_path_with_dels_contigLen(asg_t *g, uint32_t begNode, uint32_t* endNode, long long* baseLen, buf_t* b) +{ + + uint32_t v = begNode, w = 0; + uint32_t kv, kw, k; + (*baseLen) = 0; + + + while (1) + { + ///(*Len)++; + kv = get_real_length(g, v, NULL); + (*endNode) = v; + + if(b) kv_push(uint32_t, b->b, v>>1); + + if(kv == 0) + { + (*baseLen) += g->seq[v>>1].len; + return END_TIPS; + } + + if(kv == 2) + { + (*baseLen) += g->seq[v>>1].len; + return TWO_OUTPUT; + } + + if(kv > 2) + { + (*baseLen) += g->seq[v>>1].len; + return MUL_OUTPUT; + } + + ///kv must be 1 + for (k = 0; k < asg_arc_n(g, v); k++) + { + if(!asg_arc_a(g, v)[k].del) + { + w = asg_arc_a(g, v)[k].v; + (*baseLen) += ((uint32_t)(asg_arc_a(g, v)[k].ul)); + break; + } + } + + ///up to here, kv=1 + ///kw must >= 1 + kw = get_real_length(g, w^1, NULL); + v = w; + (*endNode) = v; + + + if(kw == 2) + { + (*baseLen) += g->seq[v>>1].len; + if(b) kv_push(uint32_t, b->b, v>>1); + return TWO_INPUT; + } + + if(kw > 2) + { + (*baseLen) += g->seq[v>>1].len; + if(b) kv_push(uint32_t, b->b, v>>1); + return MUL_INPUT; + } + + + if((v>>1) == (begNode>>1)) + { + return LOOP; + } + } + + return LONG_TIPS; +} + +uint32_t detect_single_path_with_dels_contigLen_complex(asg_t *g, uint32_t begNode, uint32_t* endNode, +long long* baseLen, long long* max_stop_base_Len, buf_t* b, uint32_t stops_threshold) +{ + + uint32_t v = begNode, w = 0; + uint32_t kv, kw, k, n_stops = 0, flag = LONG_TIPS; + (*baseLen) = 0; + (*max_stop_base_Len) = 0; + long long preBaseLen = 0, currentBaseLen; + + + while (1) + { + ///(*Len)++; + kv = get_real_length(g, v, NULL); + (*endNode) = v; + + if(b) kv_push(uint32_t, b->b, v>>1); + + if(kv == 0) + { + (*baseLen) += g->seq[v>>1].len; + flag = END_TIPS; + break; + } + + if(kv == 2) + { + (*baseLen) += g->seq[v>>1].len; + flag = TWO_OUTPUT; + break; + } + + if(kv > 2) + { + (*baseLen) += g->seq[v>>1].len; + flag = MUL_OUTPUT; + break; + } + + ///kv must be 1 + for (k = 0; k < asg_arc_n(g, v); k++) + { + if(!asg_arc_a(g, v)[k].del) + { + w = asg_arc_a(g, v)[k].v; + (*baseLen) += ((uint32_t)(asg_arc_a(g, v)[k].ul)); + break; + } + } + + ///up to here, kv=1 + ///kw must >= 1 + kw = get_real_length(g, w^1, NULL); + v = w; + (*endNode) = v; + + if(kw >= 2) + { + n_stops++; + currentBaseLen = (*baseLen) - preBaseLen; + preBaseLen = (*baseLen); + if(currentBaseLen > (*max_stop_base_Len)) + { + (*max_stop_base_Len) = currentBaseLen; + } + } + + if(kw >= 2 && n_stops >= stops_threshold) + { + (*baseLen) += g->seq[v>>1].len; + if(b) kv_push(uint32_t, b->b, v>>1); + if(kw == 2) flag = TWO_INPUT; + if(kw > 2) flag = MUL_INPUT; + break; + } + + + if((v>>1) == (begNode>>1)) + { + flag = LOOP; + break; + } + } + + currentBaseLen = (*baseLen) - preBaseLen; + preBaseLen = (*baseLen); + if(currentBaseLen > (*max_stop_base_Len)) + { + (*max_stop_base_Len) = currentBaseLen; + } + + return flag; +} + +/*****************************read graph*****************************/ + + +long long check_if_diploid(uint32_t v1, uint32_t v2, asg_t *g, +ma_hit_t_alloc* reverse_sources, long long min_edge_length, R_to_U* ruIndex) +{ + buf_t b_0, b_1; + memset(&b_0, 0, sizeof(buf_t)); + memset(&b_1, 0, sizeof(buf_t)); + + uint32_t convex1, convex2; + long long l1, l2; + + b_0.b.n = 0; + b_1.b.n = 0; + ///uint32_t flag1 = detect_single_path(g, v1, &convex1, &l1, &b_0); + uint32_t flag1 = detect_single_path_with_dels(g, v1, &convex1, &l1, &b_0); + + ///uint32_t flag2 = detect_single_path(g, v2, &convex2, &l2, &b_1); + uint32_t flag2 = detect_single_path_with_dels(g, v2, &convex2, &l2, &b_1); + + if(flag1 == LOOP || flag2 == LOOP) + { + free(b_0.b.a); free(b_1.b.a); + return -1; + } + + if(flag1 != END_TIPS && flag1 != LONG_TIPS) + { + l1--; + b_0.b.n--; + } + + if(flag2 != END_TIPS && flag2 != LONG_TIPS) + { + l2--; + b_1.b.n--; + } + + + if(l1 <= min_edge_length || l2 <= min_edge_length) + { + free(b_0.b.a); free(b_1.b.a); + return -1; + } + + buf_t* b_min; + buf_t* b_max; + if(l1<=l2) + { + b_min = &b_0; + b_max = &b_1; + } + else + { + b_min = &b_1; + b_max = &b_0; + } + + long long i, j, k; + double max_count = 0; + double min_count = 0; + uint32_t qn, tn, is_Unitig; + for (i = 0; i < (long long)b_min->b.n; i++) + { + qn = b_min->b.a[i]; + for (j = 0; j < (long long)reverse_sources[qn].length; j++) + { + tn = Get_tn(reverse_sources[qn].buffer[j]); + /****************************may have bugs********************************/ + ///if(g->seq[tn].del == 1) continue; + if(g->seq[tn].del == 1) + { + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || g->seq[tn].del == 1) continue; + } + /****************************may have bugs********************************/ + min_count++; + for (k = 0; k < (long long)b_max->b.n; k++) + { + if(b_max->b.a[k]==tn) + { + max_count++; + break; + } + } + } + } + + + free(b_0.b.a); + free(b_1.b.a); + + if(min_count == 0) return -1; + if(max_count == 0) return 0; + if(max_count/min_count>0.3) return 1; + return 0; + +} + + +long long check_if_diploid_primary_complex(uint32_t v1, uint32_t v2, asg_t *g, +ma_hit_t_alloc* reverse_sources, long long min_edge_length, uint32_t stops_threshold, +int if_drop, R_to_U* ruIndex) +{ + buf_t b_0, b_1; + memset(&b_0, 0, sizeof(buf_t)); + memset(&b_1, 0, sizeof(buf_t)); + + uint32_t convex1, convex2; + long long l1, l2, max_stop_Len; + + b_0.b.n = 0; + b_1.b.n = 0; + uint32_t flag1 = detect_single_path_with_dels_n_stops(g, v1, &convex1, &l1, + &max_stop_Len, &b_0, stops_threshold); + + uint32_t flag2 = detect_single_path_with_dels_n_stops(g, v2, &convex2, &l2, + &max_stop_Len, &b_1, stops_threshold); + + if(flag1 == LOOP || flag2 == LOOP) + { + return -1; + } + + if(flag1 != END_TIPS && flag1 != LONG_TIPS) + { + l1--; + b_0.b.n--; + } + + if(flag2 != END_TIPS && flag2 != LONG_TIPS) + { + l2--; + b_1.b.n--; + } + + + long long i, j, k; + i = b_0.b.n; i--; + j = b_1.b.n; j--; + while (i>=0 && j>=0) + { + if(b_0.b.a[i] == b_1.b.a[j]) + { + i--; + j--; + } + else + { + break; + } + + } + b_0.b.n = i+1; l1 = i+1; + b_1.b.n = j+1; l2 = j+1; + + + if(l1 <= min_edge_length || l2 <= min_edge_length) + { + return -1; + } + + buf_t* b_min; + buf_t* b_max; + if(l1<=l2) + { + b_min = &b_0; + b_max = &b_1; + } + else + { + b_min = &b_1; + b_max = &b_0; + } + + + double max_count = 0; + double min_count = 0; + uint32_t qn, tn, is_Unitig; + for (i = 0; i < (long long)b_min->b.n; i++) + { + qn = b_min->b.a[i]; + for (j = 0; j < (long long)reverse_sources[qn].length; j++) + { + tn = Get_tn(reverse_sources[qn].buffer[j]); + /****************************may have bugs********************************/ + ///if(g->seq[tn].del == 1 || (if_drop == 1 && g->seq[tn].c == ALTER_LABLE)) continue; + if(g->seq[tn].del == 1) + { + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || g->seq[tn].del == 1) continue; + } + /****************************may have bugs********************************/ + min_count++; + for (k = 0; k < (long long)b_max->b.n; k++) + { + if(b_max->b.a[k]==tn) + { + max_count++; + break; + } + } + } + } + + + free(b_0.b.a); + free(b_1.b.a); + if(min_count == 0) return -1; + if(max_count == 0) return 0; + if(max_count/min_count>0.3) return 1; + return 0; + +} + +uint32_t if_long_tip_length(asg_t *sg, ma_ug_t *ug, uint32_t begNode, uint32_t* untigLen, +long long minLongUntig, long long maxShortUntig, float ShortUntigRate, long long mainLen) +{ + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + uint32_t Len, endNode; + if(untigLen == NULL) + { + if(get_unitig(sg, ug, begNode, &endNode, &nodeLen, &baseLen, + &max_stop_nodeLen, &max_stop_baseLen, 1, NULL) == LOOP) + { + ///the length of LOOP is infinite + return 1; + } + Len = nodeLen; + } + else + { + Len = (*untigLen); + } + + + if(Len == 0) return 0; + if(Len < (ShortUntigRate*mainLen)) return 0; + if(Len >= maxShortUntig) return 1; + if(Len >= minLongUntig && Len >= (ShortUntigRate*mainLen)) return 1; + return 0; +} + +long long check_if_diploid_aggressive(uint32_t v1, uint32_t v2, asg_t *g, +ma_hit_t_alloc* reverse_sources, long long min_edge_length) +{ + buf_t b_0, b_1; + memset(&b_0, 0, sizeof(buf_t)); + memset(&b_1, 0, sizeof(buf_t)); + + uint32_t convex1, convex2; + long long l1, l2; + + b_0.b.n = 0; + b_1.b.n = 0; + ///uint32_t flag1 = detect_single_path(g, v1, &convex1, &l1, &b_0); + uint32_t flag1 = detect_single_path_with_dels(g, v1, &convex1, &l1, &b_0); + + ///uint32_t flag2 = detect_single_path(g, v2, &convex2, &l2, &b_1); + uint32_t flag2 = detect_single_path_with_dels(g, v2, &convex2, &l2, &b_1); + + if(flag1 == LOOP || flag2 == LOOP) + { + return -1; + } + + if(flag1 != END_TIPS && flag1 != LONG_TIPS) + { + l1--; + b_0.b.n--; + } + + if(flag2 != END_TIPS && flag2 != LONG_TIPS) + { + l2--; + b_1.b.n--; + } + + + if(l1 <= min_edge_length || l2 <= min_edge_length) + { + return -1; + } + + buf_t* b_min; + buf_t* b_max; + if(l1<=l2) + { + b_min = &b_0; + b_max = &b_1; + } + else + { + b_min = &b_1; + b_max = &b_0; + } + + long long i, j, k; + double max_count = 0; + double min_count = 0; + uint32_t qn, tn; + for (i = 0; i < (long long)b_min->b.n; i++) + { + qn = b_min->b.a[i]; + for (j = 0; j < (long long)reverse_sources[qn].length; j++) + { + tn = Get_tn(reverse_sources[qn].buffer[j]); + if(g->seq[tn].del == 1) continue; + min_count++; + for (k = 0; k < (long long)b_max->b.n; k++) + { + if(b_max->b.a[k]==tn) + { + max_count++; + break; + } + } + } + } + + + + free(b_0.b.a); + free(b_1.b.a); + + if(min_count == 0) return -1; + if(max_count == 0) return 0; + + return 1; + /** + if(max_count/min_count>0.3) return 1; + return 0; + **/ + +} + +int asg_arc_del_too_short_overlaps(asg_t *g, long long dropLen, float drop_ratio, +ma_hit_t_alloc* reverse_sources, long long min_edge_length, R_to_U* ruIndex) +{ + double startTime = Get_T(); + + uint32_t v, v_max, v_maxLen, n_vtx = g->n_seq * 2, n_short = 0; + long long drop_ratio_Len = 0; + + for (v = 0; v < n_vtx; ++v) + { + if (g->seq[v>>1].del) continue; + if (g->seq_vis[v] != 0) continue; + + uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del) continue; + + + + n_arc = get_real_length(g, v, NULL); + if (n_arc < 2) continue; + v_max = (uint32_t)-1; + + for (i = 0, n_arc = 0; i < nv; i++) + { + if (!av[i].del) + { + if(v_max == (uint32_t)-1) + { + v_max = av[i].v; + v_maxLen = av[i].ol; + if(v_maxLen < dropLen) break; + drop_ratio_Len = v_maxLen * drop_ratio; + if(dropLen < drop_ratio_Len) + { + drop_ratio_Len = dropLen; + } + } + else if(av[i].ol < drop_ratio_Len && + check_if_diploid(v_max, av[i].v, g, reverse_sources, min_edge_length, ruIndex) != 1) + { + // av[i].ol = 1;///should be a bug + av[i].del = 1; + asg_arc_del(g, av[i].v^1, av[i].ul>>32^1, 1); + ++n_short; + } + } + } + } + + + asg_cleanup(g); + asg_symm(g); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d short overlaps\n", __func__, n_short); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + return n_short; +} + + + +int asg_arc_del_short_diploid_unclean_exact(asg_t *g, float drop_ratio, ma_hit_t_alloc* sources) +{ + uint32_t v, n_vtx = g->n_seq * 2, n_short = 0; + for (v = 0; v < n_vtx; ++v) + { + if (g->seq[v>>1].del) continue; + + asg_arc_t *av = asg_arc_a(g, v); + uint32_t i, nv = asg_arc_n(g, v); + ///if there is just one overlap, do nothing + if (nv < 2) continue; + ///keep the longest one + for (i = 1; i < nv; i++) + { + ///if it is an inexact overlap + if(av[i].el == 0 && + sources[v>>1].is_fully_corrected == 1&& + sources[(av[i].v>>1)].is_fully_corrected == 1) + { + av[i].del = 1; + ++n_short; + } + } + + } + + if (n_short) + { + asg_cleanup(g); + asg_symm(g); + } + fprintf(stderr, "[M::%s] removed %d inexact overlaps\n", __func__, n_short); + return n_short; +} + + + +///check if v has only one branch +static uint32_t asg_check_unambi1(asg_t *g, uint32_t v) +{ + asg_arc_t *av = asg_arc_a(g, v); + uint32_t i, nv = asg_arc_n(g, v); + uint32_t k = nv, kv; + for (i = 0, kv = 0; i < nv; ++i) + if (!av[i].del) ++kv, k = i; + if (kv != 1) return (uint32_t)-1; + return av[k].v; +} +///to see if it is a long tip +int asg_topocut_aux(asg_t *g, uint32_t v, int max_ext) +{ + int32_t n_ext; + for (n_ext = 1; n_ext < max_ext && v != (uint32_t)-1; ++n_ext) { + if (asg_check_unambi1(g, v^1) == (uint32_t)-1) { + --n_ext; + break; + } + v = asg_check_unambi1(g, v); + } + + return n_ext; +} + +int asg_topocut_aux_pg(asg_t *g, uint32_t v, int max_ext, uint32_t *rv) +{ + int32_t n_ext; (*rv) = (uint32_t)-1; + for (n_ext = 1; n_ext < max_ext && v != (uint32_t)-1; ++n_ext) { + if (asg_check_unambi1(g, v^1) == (uint32_t)-1) { + --n_ext; (*rv) = v^1;/// asg_arc_n(g, v) >= 2 + break; + } + v = asg_check_unambi1(g, v); + } + + return n_ext; +} + +// delete short arcs +///for best graph? +int asg_arc_del_short_diploid_by_length(asg_t *g, float drop_ratio, int max_ext, +ma_hit_t_alloc* reverse_sources, long long miniedgeLen, uint32_t stops_threshold, +int if_skip_bubble, int if_drop, int if_check_hap, R_to_U* ruIndex) +{ + double startTime = Get_T(); + kvec_t(uint64_t) b; + memset(&b, 0, sizeof(b)); + + uint32_t v, n_vtx = g->n_seq * 2; + long long n_cut = 0; + + for (v = 0; v < n_vtx; ++v) + { + if(if_skip_bubble && g->seq_vis[v] != 0) continue; + if(if_drop && g->seq[v>>1].c == ALTER_LABLE) continue; + asg_arc_t *av = asg_arc_a(g, v); + uint32_t nv = asg_arc_n(g, v); + if (nv < 2) continue; + uint64_t i; + for (i = 0; i < nv; ++i) + { + kv_push(uint64_t, b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); + } + } + + radix_sort_arch64(b.a, b.a + b.n); + + uint64_t k; + for (k = 0; k < b.n; k++) + { + + asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; + ///v is self id, w is the id of another end + uint32_t i, iv, iw, v = (a->ul)>>32, w = a->v^1, to_del = 0; + uint32_t nv = asg_arc_n(g, v), nw = asg_arc_n(g, w), kv, kw; + uint32_t ov_max = 0, ow_max = 0, ov_max_i = 0, ow_max_i = 0; + asg_arc_t *av, *aw; + ///nv must be >= 2 + if (nv == 1 && nw == 1) continue; + av = asg_arc_a(g, v); + aw = asg_arc_a(g, w); + + + ///calculate the longest edge for v and w + for (i = 0, kv = 0; i < nv; ++i) { + if (av[i].del) continue; + if (ov_max < av[i].ol) ov_max = av[i].ol, ov_max_i = i; + ++kv; + } + if (kv >= 2 && a->ol > ov_max * drop_ratio) continue; + + + for (i = 0, kw = 0; i < nw; ++i) { + if (aw[i].del) continue; + if (ow_max < aw[i].ol) ow_max = aw[i].ol, ow_max_i = i; + ++kw; + } + if (kw >= 2 && a->ol > ow_max * drop_ratio) continue; + ///if (kv == 1 && kw == 1) continue; + if (kv <= 1 && kw <= 1) continue; + + + ///to see which one is the current edge (from v and w) + for (iv = 0; iv < nv; ++iv) + if (av[iv].v == (w^1)) break; + for (iw = 0; iw < nw; ++iw) + if (aw[iw].v == (v^1)) break; + ///if one edge has been deleted, it should be deleted in both direction + if (av[iv].del && aw[iw].del) continue; + + ///kv and kw is the avialiable + if (kv > 1 && kw > 1) { + if (a->ol < ov_max * drop_ratio && a->ol < ow_max * drop_ratio) + to_del = 1; + if(if_check_hap == 1 && to_del == 1) + { + + if(check_if_diploid_primary_complex(av[ov_max_i].v, w^1, g, reverse_sources, + miniedgeLen, stops_threshold, if_drop, ruIndex) == 1 + || + check_if_diploid_primary_complex(aw[ow_max_i].v, v^1, g, reverse_sources, + miniedgeLen, stops_threshold, if_drop, ruIndex) == 1) + { + to_del = 0; + } + } + + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + ///kv > 1 + if(if_check_hap == 1 && to_del == 1) + { + if(check_if_diploid_primary_complex(av[ov_max_i].v, w^1, g, reverse_sources, + miniedgeLen, stops_threshold, if_drop, ruIndex) == 1) + { + to_del = 0; + } + } + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + ///kw > 1 + if(if_check_hap == 1 && to_del == 1) + { + if(check_if_diploid_primary_complex(aw[ow_max_i].v, v^1, g, reverse_sources, + miniedgeLen, stops_threshold, if_drop, ruIndex) == 1) + { + to_del = 0; + } + } + } + if (to_del) + av[iv].del = aw[iw].del = 1, ++n_cut; + + } + + free(b.a); + if (n_cut) + { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %lld short overlaps\n", __func__, n_cut); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return n_cut; +} + +int unitig_arc_del_short_diploid_by_length_topo(asg_t *g, ma_ug_t *ug, float drop_ratio, +int max_ext, ma_hit_t_alloc* reverse_sources, int if_skip_bubble, int if_drop) +{ + double startTime = Get_T(); + kvec_t(uint64_t) b; + memset(&b, 0, sizeof(b)); + + uint32_t v, n_vtx = g->n_seq * 2, convex; + long long n_cut = 0, tmp, nodeLen, max_stop_nodeLen, max_stop_baseLen; + + for (v = 0; v < n_vtx; ++v) + { + if(if_skip_bubble && g->seq_vis[v] != 0) continue; + if(if_drop && g->seq[v>>1].c == ALTER_LABLE) continue; + asg_arc_t *av = asg_arc_a(g, v); + uint32_t nv = asg_arc_n(g, v); + if (nv < 2) continue; + if(get_real_length(g, v, NULL) < 2) continue; + uint64_t i; + for (i = 0; i < nv; ++i) + { + kv_push(uint64_t, b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); + } + } + + radix_sort_arch64(b.a, b.a + b.n); + + uint64_t k; + for (k = 0; k < b.n; k++) + { + + asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; + ///v is self id, w is the id of another end + uint32_t i, iv, iw, v = (a->ul)>>32, w = a->v^1, to_del = 0; + uint32_t nv = asg_arc_n(g, v), nw = asg_arc_n(g, w), kv, kw; + uint32_t ov_max = 0, ow_max = 0; + asg_arc_t *av, *aw; + ///nv must be >= 2 + if (nv == 1 && nw == 1) continue; + av = asg_arc_a(g, v); + aw = asg_arc_a(g, w); + + + ///calculate the longest edge for v and w + for (i = 0, kv = 0; i < nv; ++i) { + if (av[i].del) continue; + if (ov_max < av[i].ol) ov_max = av[i].ol; + ++kv; + } + if (kv >= 2 && a->ol > ov_max * drop_ratio) continue; + + + for (i = 0, kw = 0; i < nw; ++i) { + if (aw[i].del) continue; + if (ow_max < aw[i].ol) ow_max = aw[i].ol; + ++kw; + } + if (kw >= 2 && a->ol > ow_max * drop_ratio) continue; + ///if (kv == 1 && kw == 1) continue; + if (kv <= 1 && kw <= 1) continue; + + + ///to see which one is the current edge (from v and w) + for (iv = 0; iv < nv; ++iv) + if (av[iv].v == (w^1)) break; + for (iw = 0; iw < nw; ++iw) + if (aw[iw].v == (v^1)) break; + ///if one edge has been deleted, it should be deleted in both direction + if (av[iv].del && aw[iw].del) continue; + + ///kv and kw is the avialiable + if (kv > 1 && kw > 1) { + if (a->ol < ov_max * drop_ratio && a->ol < ow_max * drop_ratio) + { + to_del = 1; + } + } else if (kw == 1) { + get_unitig(g, ug, w^1, &convex, &nodeLen, &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, NULL); + if(nodeLen < max_ext) to_del = 1; + ///if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + } else if (kv == 1) { + get_unitig(g, ug, v^1, &convex, &nodeLen, &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, NULL); + if(nodeLen < max_ext) to_del = 1; + ///if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + } + if (to_del) + av[iv].del = aw[iw].del = 1, ++n_cut; + } + + free(b.a); + if (n_cut) + { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %lld short overlaps\n", __func__, n_cut); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return n_cut; +} + + +int unitig_arc_del_short_diploid_by_length(asg_t *g, float drop_ratio) +{ + double startTime = Get_T(); + kvec_t(uint64_t) b; + memset(&b, 0, sizeof(b)); + + uint32_t v, n_vtx = g->n_seq * 2; + long long n_cut = 0; + + for (v = 0; v < n_vtx; ++v) + { + if(g->seq[v>>1].c == ALTER_LABLE || g->seq[v>>1].del) continue; + asg_arc_t *av = asg_arc_a(g, v); + uint32_t nv = asg_arc_n(g, v); + if (nv < 2) continue; + uint64_t i; + for (i = 0; i < nv; ++i) + { + kv_push(uint64_t, b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); + } + } + + radix_sort_arch64(b.a, b.a + b.n); + + uint64_t k; + for (k = 0; k < b.n; k++) + { + + asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; + ///v is self id, w is the id of another end + uint32_t i, v = (a->ul)>>32; + uint32_t nv = asg_arc_n(g, v), kv; + uint32_t ov_max = 0; + asg_arc_t *av = NULL; + ///nv must be >= 2 + if (nv <= 1) continue; + av = asg_arc_a(g, v); + + + ///calculate the longest edge for v and w + for (i = 0, kv = 0; i < nv; ++i) { + if (av[i].del) continue; + if (ov_max < av[i].ol) ov_max = av[i].ol; + ++kv; + } + if (kv <= 1) continue; + if (kv >= 2 && a->ol > ov_max * drop_ratio) continue; + a->del = 1; + asg_arc_del(g, a->v^1, av->ul>>32^1, 1); + ++n_cut; + } + + free(b.a); + if (n_cut) + { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %lld short overlaps\n", __func__, n_cut); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return n_cut; +} + + +uint8_t get_tip_trio_infor(asg_t *sg, uint32_t begNode) +{ + uint32_t v = begNode, w; + uint32_t kv; + uint32_t eLen = 0, uLen = 0; + uint32_t father_occ = 0, mother_occ = 0, ambigious_occ = 0; + + while (1) + { + kv = get_real_length(sg, v, NULL); + eLen++; + + if(R_INF.trio_flag[v>>1]==FATHER) + { + father_occ++; + } + else if(R_INF.trio_flag[v>>1]==MOTHER) + { + mother_occ++; + } + else if((R_INF.trio_flag[v>>1]==AMBIGU) || (R_INF.trio_flag[v>>1]==DROP)) + { + ambigious_occ++; + } + + if(kv!=1) break; + ///kv must be 1 here + kv = get_real_length(sg, v, &w); + if(get_real_length(sg, w^1, NULL)!=1) break; + v = w; + if(v == begNode) break; + } + + uLen = eLen; + eLen = father_occ + mother_occ; + if(eLen == 0) return AMBIGU; + if(father_occ >= mother_occ) + { + if((father_occ > TRIO_THRES*eLen) && (father_occ >= DOUBLE_CHECK_THRES*uLen)) return FATHER; + } + else + { + if((mother_occ > TRIO_THRES*eLen) && (mother_occ >= DOUBLE_CHECK_THRES*uLen)) return MOTHER; + } + return AMBIGU; +} + +int asg_arc_del_short_diploid_by_length_trio(asg_t *g, float drop_ratio, int max_ext, +ma_hit_t_alloc* reverse_sources, long long miniedgeLen, uint32_t stops_threshold, +int if_skip_bubble, int if_drop, int if_check_hap, R_to_U* ruIndex) +{ + double startTime = Get_T(); + kvec_t(uint64_t) b; + memset(&b, 0, sizeof(b)); + + uint32_t v, n_vtx = g->n_seq * 2; + long long n_cut = 0; + + for (v = 0; v < n_vtx; ++v) + { + if(if_skip_bubble && g->seq_vis[v] != 0) continue; + if(if_drop && g->seq[v>>1].c == ALTER_LABLE) continue; + asg_arc_t *av = asg_arc_a(g, v); + uint32_t nv = asg_arc_n(g, v); + if (nv < 2) continue; + uint64_t i; + for (i = 0; i < nv; ++i) + { + kv_push(uint64_t, b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); + } + } + + radix_sort_arch64(b.a, b.a + b.n); + + uint64_t k; + for (k = 0; k < b.n; k++) + { + asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; + ///v is self id, w is the id of another end + uint32_t i, iv, iw, v = (a->ul)>>32, w = a->v^1, to_del = 0; + uint32_t nv = asg_arc_n(g, v), nw = asg_arc_n(g, w), kv, kw; + uint32_t ov_max = 0, ow_max = 0, ov_max_i = 0, ow_max_i = 0, trio_flag, non_trio_flag; + asg_arc_t *av, *aw; + ///nv must be >= 2 + if (nv == 1 && nw == 1) continue; + av = asg_arc_a(g, v); + aw = asg_arc_a(g, w); + kv = get_real_length(g, v, NULL); + kw = get_real_length(g, w, NULL); + if (kv <= 1 && kw <= 1) continue; + trio_flag = get_tip_trio_infor(g, v^1); + non_trio_flag = (uint32_t)-1; + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + + ///calculate the longest edge for v and w + for (i = 0, kv = 0; i < nv; ++i) { + if (av[i].del) continue; + kv++; + if(get_tip_trio_infor(g, av[i].v) == non_trio_flag) continue; + if (ov_max < av[i].ol) ov_max = av[i].ol, ov_max_i = i; + ///kv++; + } + if (kv >= 2 && a->ol > ov_max * drop_ratio) continue; + + for (i = 0, kw = 0; i < nw; ++i) { + if (aw[i].del) continue; + kw++; + if (get_tip_trio_infor(g, aw[i].v) == non_trio_flag) continue; + if (ow_max < aw[i].ol) ow_max = aw[i].ol, ow_max_i = i; + ///kw++; + } + if (kw >= 2 && a->ol > ow_max * drop_ratio) continue; + + if (kv <= 1 && kw <= 1) continue; + + ///to see which one is the current edge (from v and w) + for (iv = 0; iv < nv; ++iv) + if (av[iv].v == (w^1)) break; + for (iw = 0; iw < nw; ++iw) + if (aw[iw].v == (v^1)) break; + ///if one edge has been deleted, it should be deleted in both direction + if (av[iv].del && aw[iw].del) continue; + + ///kv and kw is the avialiable + if (kv > 1 && kw > 1) { + if (a->ol < ov_max * drop_ratio && a->ol < ow_max * drop_ratio) + to_del = 1; + if(if_check_hap == 1 && to_del == 1) + { + + if(check_if_diploid_primary_complex(av[ov_max_i].v, w^1, g, reverse_sources, + miniedgeLen, stops_threshold, if_drop, ruIndex) == 1 + || + check_if_diploid_primary_complex(aw[ow_max_i].v, v^1, g, reverse_sources, + miniedgeLen, stops_threshold, if_drop, ruIndex) == 1) + { + to_del = 0; + } + } + + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + ///kv > 1 + if(if_check_hap == 1 && to_del == 1) + { + if(check_if_diploid_primary_complex(av[ov_max_i].v, w^1, g, reverse_sources, + miniedgeLen, stops_threshold, if_drop, ruIndex) == 1) + { + to_del = 0; + } + } + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + ///kw > 1 + if(if_check_hap == 1 && to_del == 1) + { + if(check_if_diploid_primary_complex(aw[ow_max_i].v, v^1, g, reverse_sources, + miniedgeLen, stops_threshold, if_drop, ruIndex) == 1) + { + to_del = 0; + } + } + } + if (to_del) + av[iv].del = aw[iw].del = 1, ++n_cut; + + } + + free(b.a); + if (n_cut) + { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %lld short overlaps\n", __func__, n_cut); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return n_cut; +} + +int asg_arc_del_short_false_link(asg_t *g, float drop_ratio, float o_drop_ratio, int max_dist, +ma_hit_t_alloc* reverse_sources, long long miniedgeLen, R_to_U* ruIndex) +{ + double startTime = Get_T(); + + kvec_t(uint64_t) b; + memset(&b, 0, sizeof(b)); + + + kvec_t(uint32_t) b_f; + memset(&b_f, 0, sizeof(b_f)); + + kvec_t(uint32_t) b_r; + memset(&b_r, 0, sizeof(b_r)); + + + uint32_t v, w, n_vtx = g->n_seq * 2, n_cut = 0; + uint32_t sink; + + buf_t bub; + if (!g->is_symm) asg_symm(g); + memset(&bub, 0, sizeof(buf_t)); + bub.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + + for (v = 0; v < n_vtx; ++v) + { + if(g->seq_vis[v] == 0) + { + asg_arc_t *av = asg_arc_a(g, v); + uint32_t nv = asg_arc_n(g, v); + if(nv == 1 && asg_arc_n(g, v^1) == 1) continue; + + uint64_t t_ol = 0; + long long i; + for (i = 0; i < nv; ++i) + { + t_ol += av[i].ol; + } + kv_push(uint64_t, b, (uint64_t)(t_ol << 32 | v)); + } + } + + radix_sort_arch64(b.a, b.a + b.n); + + uint32_t min_edge; + + + uint64_t k, t; + for (k = 0; k < b.n; k++) + { + ///v is the node + v = (uint32_t)b.a[k]; + if (g->seq[v>>1].del) continue; + uint32_t nv = asg_arc_n(g, v), nw, to_del_l, to_del_r; + if (nv < 2) continue; + uint32_t kv = get_real_length(g, v, NULL), kw; + if (kv < 2) continue; + uint32_t i; + asg_arc_t *av = asg_arc_a(g, v), *aw; + + b_f.n = 0; + b_r.n = 0; + to_del_l = 0; + for (i = 0; i < nv; i++) + { + if (av[i].del) continue; + + w = av[i].v^1; + nw = asg_arc_n(g, w); + if(nw < 2) break; + kw = get_real_length(g, w, NULL); + if(kw < 2) break; + + kv_push(uint32_t, b_f, av[i].v); + kv_push(uint32_t, b_r, w); + + aw = asg_arc_a(g, w); + min_edge = (uint32_t)-1; + for (t = 0; t < nw; t++) + { + if(aw[t].del) continue; + if((aw[t].v>>1) == (v>>1)) continue; + if(aw[t].ol < min_edge) min_edge = aw[t].ol; + ///kv_push(uint32_t, b_r, aw[t].v); + } + + if(av[i].ol < min_edge * drop_ratio) to_del_l++; + } + + + + + + + + + + + + + /****************************may have bugs********************************/ + if(to_del_l != kv) + { + b_f.n = 0; + b_r.n = 0; + to_del_l = 0; + + for (i = 0; i < nv; i++) + { + if (av[i].del) continue; + + w = av[i].v^1; + nw = asg_arc_n(g, w); + if(nw < 2) break; + kw = get_real_length(g, w, NULL); + if(kw < 2) break; + + kv_push(uint32_t, b_f, av[i].v); + kv_push(uint32_t, b_r, w); + + aw = asg_arc_a(g, w); + min_edge = (uint32_t)-1; + for (t = 0; t < nw; t++) + { + if(aw[t].del) continue; + if((aw[t].v>>1) == (v>>1)) continue; + if(aw[t].ol < min_edge) min_edge = aw[t].ol; + } + + if(av[i].ol < min_edge * o_drop_ratio) to_del_l++; + } + + if(to_del_l == kv) + { + ///forward + to_del_l = 1; + for (i = 1; i < b_f.n; i++) + { + if(check_if_diploid(b_f.a[0], b_f.a[i], g, reverse_sources, miniedgeLen, ruIndex) == 1) + { + to_del_l++; + } + } + + ///backward + if(to_del_l != kv && b_r.n >= 2) + { + to_del_l = 0; + uint32_t w0 = 0, w1 = 0; + + + w = b_r.a[0]; + kw = get_real_length(g, w, NULL); + if(kw != 2) goto terminal; + aw = asg_arc_a(g, w); + nw = asg_arc_n(g, w); + for (t = 0; t < nw; t++) + { + if(aw[t].del) continue; + if((aw[t].v>>1) == (v>>1)) continue; + w0 = aw[t].v; + } + to_del_l = 1; + + + for (i = 1; i < b_r.n; i++) + { + w = b_r.a[i]; + kw = get_real_length(g, w, NULL); + if(kw != 2) goto terminal; + aw = asg_arc_a(g, w); + nw = asg_arc_n(g, w); + for (t = 0; t < nw; t++) + { + if(aw[t].del) continue; + if((aw[t].v>>1) == (v>>1)) continue; + w1 = aw[t].v; + } + + if(check_if_diploid(w0, w1, g, reverse_sources, miniedgeLen, ruIndex) == 1) + { + to_del_l++; + } + } + + } + } + } + + terminal: + /****************************may have bugs********************************/ + + + if(to_del_l != kv) continue; + + + + + + uint32_t convex1; + long long l1; + + + + + ////forward bubble + to_del_l = 0; + for (i = 0; i < b_f.n; i++) + { + if(b_f.a[i] == b_f.a[0]) + { + to_del_l = 1; + } + else + { + to_del_l = 0; + break; + } + } + //check the length + if(to_del_l == 0 && asg_bub_end_finder_with_del_advance(g, + b_f.a, b_f.n, max_dist, &bub, 0, (uint32_t)-1, &sink)==1) + { + to_del_l = 1; + } + if(to_del_l == 0 && detect_mul_bubble_end_with_bubbles(g, b_f.a, b_f.n, &convex1, &l1, NULL)) + { + to_del_l = 1; + } + + ////backward bubble + to_del_r = 0; + for (i = 0; i < b_r.n; i++) + { + if(b_r.a[i] == b_r.a[0]) + { + to_del_r = 1; + } + else + { + to_del_r = 0; + break; + } + } + if(to_del_r == 0 && asg_bub_end_finder_with_del_advance + (g, b_r.a, b_r.n, max_dist, &bub, 1, v^1, &sink)==1) + { + to_del_r = 1; + } + if(to_del_r == 0 && detect_mul_bubble_end_with_bubbles(g, b_r.a, b_r.n, &convex1, &l1, NULL)) + { + to_del_r = 1; + } + + + + + + + if (to_del_l && to_del_r) + { + for (i = 0; i < nv; ++i) + { + if (av[i].del) continue; + ++n_cut; + av[i].del = 1; + asg_arc_del(g, av[i].v^1, av[i].ul>>32^1, 1); + } + + } + } + + free(b.a); free(b_f.a); free(b_r.a); + free(bub.a); free(bub.S.a); free(bub.T.a); free(bub.b.a); free(bub.e.a); + if (n_cut) + { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %u false overlaps\n", __func__, n_cut); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return n_cut; +} + + +int asg_arc_del_short_false_link_primary(asg_t *g, float drop_ratio, float o_drop_ratio, int max_dist, +ma_hit_t_alloc* reverse_sources, long long miniedgeLen, R_to_U* ruIndex) +{ + double startTime = Get_T(); + + kvec_t(uint64_t) b; + memset(&b, 0, sizeof(b)); + + + kvec_t(uint32_t) b_f; + memset(&b_f, 0, sizeof(b_f)); + + kvec_t(uint32_t) b_r; + memset(&b_r, 0, sizeof(b_r)); + + + uint32_t v, w, n_vtx = g->n_seq * 2, n_cut = 0; + uint32_t sink; + + buf_t bub; + if (!g->is_symm) asg_symm(g); + memset(&bub, 0, sizeof(buf_t)); + bub.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + + for (v = 0; v < n_vtx; ++v) + { + if(g->seq[v>>1].c == ALTER_LABLE) continue; + + if(g->seq_vis[v] == 0) + { + asg_arc_t *av = asg_arc_a(g, v); + uint32_t nv = asg_arc_n(g, v); + if(nv == 1 && asg_arc_n(g, v^1) == 1) continue; + + uint64_t t_ol = 0; + long long i; + for (i = 0; i < nv; ++i) + { + t_ol += av[i].ol; + } + kv_push(uint64_t, b, (uint64_t)(t_ol << 32 | v)); + } + } + + radix_sort_arch64(b.a, b.a + b.n); + + uint32_t min_edge; + + + uint64_t k, t; + for (k = 0; k < b.n; k++) + { + ///v is the node + v = (uint32_t)b.a[k]; + if (g->seq[v>>1].del) continue; + uint32_t nv = asg_arc_n(g, v), nw, to_del_l, to_del_r; + if (nv < 2) continue; + uint32_t kv = get_real_length(g, v, NULL), kw; + if (kv < 2) continue; + uint32_t i; + asg_arc_t *av = asg_arc_a(g, v), *aw; + + b_f.n = 0; + b_r.n = 0; + to_del_l = 0; + for (i = 0; i < nv; i++) + { + if (av[i].del) continue; + + w = av[i].v^1; + nw = asg_arc_n(g, w); + if(nw < 2) break; + kw = get_real_length(g, w, NULL); + if(kw < 2) break; + + kv_push(uint32_t, b_f, av[i].v); + kv_push(uint32_t, b_r, w); + + aw = asg_arc_a(g, w); + min_edge = (uint32_t)-1; + for (t = 0; t < nw; t++) + { + if(aw[t].del) continue; + if((aw[t].v>>1) == (v>>1)) continue; + if(aw[t].ol < min_edge) min_edge = aw[t].ol; + ///kv_push(uint32_t, b_r, aw[t].v); + } + + if(av[i].ol < min_edge * drop_ratio) to_del_l++; + } + + + + + + + + + + + + + /****************************may have bugs********************************/ + if(to_del_l != kv) + { + b_f.n = 0; + b_r.n = 0; + to_del_l = 0; + + for (i = 0; i < nv; i++) + { + if (av[i].del) continue; + + w = av[i].v^1; + nw = asg_arc_n(g, w); + if(nw < 2) break; + kw = get_real_length(g, w, NULL); + if(kw < 2) break; + + kv_push(uint32_t, b_f, av[i].v); + kv_push(uint32_t, b_r, w); + + aw = asg_arc_a(g, w); + min_edge = (uint32_t)-1; + for (t = 0; t < nw; t++) + { + if(aw[t].del) continue; + if((aw[t].v>>1) == (v>>1)) continue; + if(aw[t].ol < min_edge) min_edge = aw[t].ol; + } + + if(av[i].ol < min_edge * o_drop_ratio) to_del_l++; + } + + if(to_del_l == kv) + { + ///forward + to_del_l = 1; + for (i = 1; i < b_f.n; i++) + { + /****************************may have bugs********************************/ + if(check_if_diploid(b_f.a[0], b_f.a[i], g, reverse_sources, miniedgeLen, ruIndex) == 1) + {/****************************may have bugs********************************/ + to_del_l++; + } + } + + ///backward + if(to_del_l != kv && b_r.n >= 2) + { + to_del_l = 0; + uint32_t w0 = 0, w1 = 0; + + + w = b_r.a[0]; + kw = get_real_length(g, w, NULL); + if(kw != 2) goto terminal; + aw = asg_arc_a(g, w); + nw = asg_arc_n(g, w); + for (t = 0; t < nw; t++) + { + if(aw[t].del) continue; + if((aw[t].v>>1) == (v>>1)) continue; + w0 = aw[t].v; + } + to_del_l = 1; + + + for (i = 1; i < b_r.n; i++) + { + w = b_r.a[i]; + kw = get_real_length(g, w, NULL); + if(kw != 2) goto terminal; + aw = asg_arc_a(g, w); + nw = asg_arc_n(g, w); + for (t = 0; t < nw; t++) + { + if(aw[t].del) continue; + if((aw[t].v>>1) == (v>>1)) continue; + w1 = aw[t].v; + } + /****************************may have bugs********************************/ + if(check_if_diploid(w0, w1, g, reverse_sources, miniedgeLen, ruIndex) == 1) + {/****************************may have bugs********************************/ + to_del_l++; + } + } + + } + } + } + + terminal: + /****************************may have bugs********************************/ + + + if(to_del_l != kv) continue; + + + + + + uint32_t convex1; + long long l1; + + + + + ////forward bubble + to_del_l = 0; + for (i = 0; i < b_f.n; i++) + { + if(b_f.a[i] == b_f.a[0]) + { + to_del_l = 1; + } + else + { + to_del_l = 0; + break; + } + } + //check the length + if(to_del_l == 0 && asg_bub_end_finder_with_del_advance(g, + b_f.a, b_f.n, max_dist, &bub, 0, (uint32_t)-1, &sink)==1) + { + to_del_l = 1; + } + if(to_del_l == 0 && detect_mul_bubble_end_with_bubbles(g, b_f.a, b_f.n, &convex1, &l1, NULL)) + { + to_del_l = 1; + } + + ////backward bubble + to_del_r = 0; + for (i = 0; i < b_r.n; i++) + { + if(b_r.a[i] == b_r.a[0]) + { + to_del_r = 1; + } + else + { + to_del_r = 0; + break; + } + } + if(to_del_r == 0 && asg_bub_end_finder_with_del_advance + (g, b_r.a, b_r.n, max_dist, &bub, 1, v^1, &sink)==1) + { + to_del_r = 1; + } + if(to_del_r == 0 && detect_mul_bubble_end_with_bubbles(g, b_r.a, b_r.n, &convex1, &l1, NULL)) + { + to_del_r = 1; + } + + + + + + + if (to_del_l && to_del_r) + { + for (i = 0; i < nv; ++i) + { + if (av[i].del) continue; + ++n_cut; + av[i].del = 1; + asg_arc_del(g, av[i].v^1, av[i].ul>>32^1, 1); + } + + } + } + + free(b.a); free(b_f.a); free(b_r.a); + free(bub.a); free(bub.S.a); free(bub.T.a); free(bub.b.a); free(bub.e.a); + if (n_cut) + { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %u false overlaps\n", __func__, n_cut); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return n_cut; +} + +int asg_arc_del_short_false_link_advance(asg_t *g, float drop_ratio, float o_drop_ratio, int max_dist, +ma_hit_t_alloc* reverse_sources, long long miniedgeLen, R_to_U* ruIndex) +{ + double startTime = Get_T(); + + kvec_t(uint64_t) b; + memset(&b, 0, sizeof(b)); + + + kvec_t(uint32_t) b_f; + memset(&b_f, 0, sizeof(b_f)); + + kvec_t(uint32_t) b_r; + memset(&b_r, 0, sizeof(b_r)); + + + uint32_t v, w, n_vtx = g->n_seq * 2, n_cut = 0; + uint32_t sink; + + buf_t bub; + if (!g->is_symm) asg_symm(g); + memset(&bub, 0, sizeof(buf_t)); + bub.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + + for (v = 0; v < n_vtx; ++v) + { + if(g->seq_vis[v] == 0) + { + asg_arc_t *av = asg_arc_a(g, v); + uint32_t nv = asg_arc_n(g, v); + if(nv == 1 && asg_arc_n(g, v^1) == 1) continue; + + uint64_t t_ol = 0; + long long i; + for (i = 0; i < nv; ++i) + { + t_ol += av[i].ol; + } + kv_push(uint64_t, b, (uint64_t)(t_ol << 32 | v)); + } + } + + radix_sort_arch64(b.a, b.a + b.n); + + uint32_t min_edge; + + uint64_t k, t; + for (k = 0; k < b.n; k++) + { + ///v is the node + v = (uint32_t)b.a[k]; + if (g->seq[v>>1].del) continue; + uint32_t nv = asg_arc_n(g, v), nw, to_del_l, to_del_r; + if (nv < 2) continue; + uint32_t kv = get_real_length(g, v, NULL), kw; + if (kv < 2) continue; + uint32_t i; + asg_arc_t *av = asg_arc_a(g, v), *aw; + + b_f.n = 0; + b_r.n = 0; + to_del_l = 0; + for (i = 0; i < nv; i++) + { + if (av[i].del) continue; + + w = av[i].v^1; + nw = asg_arc_n(g, w); + if(nw < 2) break; + kw = get_real_length(g, w, NULL); + if(kw < 2) break; + + kv_push(uint32_t, b_f, av[i].v); + kv_push(uint32_t, b_r, w); + + aw = asg_arc_a(g, w); + min_edge = (uint32_t)-1; + for (t = 0; t < nw; t++) + { + if(aw[t].del) continue; + if((aw[t].v>>1) == (v>>1)) continue; + if(aw[t].ol < min_edge) min_edge = aw[t].ol; + ///kv_push(uint32_t, b_r, aw[t].v); + } + + if(av[i].ol < min_edge * drop_ratio) to_del_l++; + } + + + + + + + + + + + + + /****************************may have bugs********************************/ + if(to_del_l != kv) + { + b_f.n = 0; + b_r.n = 0; + to_del_l = 0; + + for (i = 0; i < nv; i++) + { + if (av[i].del) continue; + + w = av[i].v^1; + nw = asg_arc_n(g, w); + if(nw < 2) break; + kw = get_real_length(g, w, NULL); + if(kw < 2) break; + + kv_push(uint32_t, b_f, av[i].v); + kv_push(uint32_t, b_r, w); + + aw = asg_arc_a(g, w); + min_edge = (uint32_t)-1; + for (t = 0; t < nw; t++) + { + if(aw[t].del) continue; + if((aw[t].v>>1) == (v>>1)) continue; + if(aw[t].ol < min_edge) min_edge = aw[t].ol; + } + + if(av[i].ol < min_edge * o_drop_ratio) to_del_l++; + } + + if(to_del_l == kv) + { + ///forward + to_del_l = 1; + for (i = 1; i < b_f.n; i++) + { + if(check_if_diploid(b_f.a[0], b_f.a[i], g, reverse_sources, miniedgeLen, ruIndex) == 1) + { + to_del_l++; + } + } + + ///backward + if(to_del_l != kv && b_r.n >= 2) + { + to_del_l = 0; + uint32_t w0 = 0, w1 = 0; + + + w = b_r.a[0]; + kw = get_real_length(g, w, NULL); + if(kw != 2) goto terminal; + aw = asg_arc_a(g, w); + nw = asg_arc_n(g, w); + for (t = 0; t < nw; t++) + { + if(aw[t].del) continue; + if((aw[t].v>>1) == (v>>1)) continue; + w0 = aw[t].v; + } + to_del_l = 1; + + + for (i = 1; i < b_r.n; i++) + { + w = b_r.a[i]; + kw = get_real_length(g, w, NULL); + if(kw != 2) goto terminal; + aw = asg_arc_a(g, w); + nw = asg_arc_n(g, w); + for (t = 0; t < nw; t++) + { + if(aw[t].del) continue; + if((aw[t].v>>1) == (v>>1)) continue; + w1 = aw[t].v; + } + + if(check_if_diploid(w0, w1, g, reverse_sources, miniedgeLen, ruIndex) == 1) + { + to_del_l++; + } + } + + } + } + } + + terminal: + /****************************may have bugs********************************/ + + + if(to_del_l != kv) continue; + + + + + + uint32_t convex1; + long long l1; + + + + + ////forward bubble + to_del_l = 0; + for (i = 0; i < b_f.n; i++) + { + if(b_f.a[i] == b_f.a[0]) + { + to_del_l = 1; + } + else + { + to_del_l = 0; + break; + } + } + //check the length + if(to_del_l == 0 && asg_bub_end_finder_with_del_advance(g, + b_f.a, b_f.n, max_dist, &bub, 0, (uint32_t)-1, &sink)==1) + { + to_del_l = 1; + } + if(to_del_l == 0 && detect_mul_bubble_end_with_bubbles(g, b_f.a, b_f.n, &convex1, &l1, NULL)) + { + to_del_l = 1; + } + + ////backward bubble + to_del_r = 0; + for (i = 0; i < b_r.n; i++) + { + if(b_r.a[i] == b_r.a[0]) + { + to_del_r = 1; + } + else + { + to_del_r = 0; + break; + } + } + if(to_del_r == 0 && asg_bub_end_finder_with_del_advance + (g, b_r.a, b_r.n, max_dist, &bub, 1, v^1, &sink)==1) + { + to_del_r = 1; + } + if(to_del_r == 0 && detect_mul_bubble_end_with_bubbles(g, b_r.a, b_r.n, &convex1, &l1, NULL)) + { + to_del_r = 1; + } + + + + + if (to_del_l && to_del_r) + { + ///fprintf(stderr, "%.*s\n", Get_NAME_LENGTH((R_INF), v>>1), Get_NAME((R_INF), v>>1)); + for (i = 0; i < nv; ++i) + { + if (av[i].del) continue; + + ++n_cut; + av[i].del = 1; + asg_arc_del(g, av[i].v^1, av[i].ul>>32^1, 1); + } + + } + } + + free(b.a); free(b_f.a); free(b_r.a); + free(bub.a); free(bub.S.a); free(bub.T.a); free(bub.b.a); free(bub.e.a); + if (n_cut) + { + asg_cleanup(g); + asg_symm(g); + } + fprintf(stderr, "[M::%s] removed %d false overlaps\n", __func__, n_cut); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + return n_cut; +} + + +int asg_arc_del_complex_false_link(asg_t *g, float drop_ratio, float o_drop_ratio, int max_dist, +ma_hit_t_alloc* reverse_sources, long long miniedgeLen) +{ + double startTime = Get_T(); + + kvec_t(uint64_t) b; + memset(&b, 0, sizeof(b)); + + + kvec_t(uint32_t) b_f; + memset(&b_f, 0, sizeof(b_f)); + + kvec_t(uint32_t) b_r; + memset(&b_r, 0, sizeof(b_r)); + + + uint32_t v, w, n_vtx = g->n_seq * 2, n_cut = 0; + + + buf_t bub; + if (!g->is_symm) asg_symm(g); + memset(&bub, 0, sizeof(buf_t)); + bub.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + + for (v = 0; v < n_vtx; ++v) + { + if(g->seq_vis[v] == 0) + { + asg_arc_t *av = asg_arc_a(g, v); + uint32_t nv = asg_arc_n(g, v); + + if(nv == 1 && asg_arc_n(g, v^1) == 1) continue; + + uint64_t t_ol = 0; + long long i; + for (i = 0; i < nv; ++i) + { + t_ol += av[i].ol; + } + kv_push(uint64_t, b, (uint64_t)(t_ol << 32 | v)); + } + } + + + radix_sort_arch64(b.a, b.a + b.n); + + uint32_t min_edge; + + + uint64_t k, t; + for (k = 0; k < b.n; k++) + { + ///v is the node + v = (uint32_t)b.a[k]; + if (g->seq[v>>1].del) continue; + uint32_t nv = asg_arc_n(g, v), nw, to_del; + if (nv < 2) continue; + uint32_t kv = get_real_length(g, v, NULL), kw; + if (kv < 2) continue;///V must have two out-nodes + uint32_t i; + asg_arc_t *av = asg_arc_a(g, v), *aw; + + b_f.n = 0; + b_r.n = 0; + to_del = 0; + for (i = 0; i < nv; i++) + { + if (av[i].del) continue; + + w = av[i].v^1; + nw = asg_arc_n(g, w); + if(nw < 2) break; + kw = get_real_length(g, w, NULL); + if(kw < 2) break; + + kv_push(uint32_t, b_f, av[i].v); + kv_push(uint32_t, b_r, w); + + aw = asg_arc_a(g, w); + min_edge = (uint32_t)-1; + for (t = 0; t < nw; t++) + { + if(aw[t].del) continue; + if((aw[t].v>>1) == (v>>1)) continue; + if(aw[t].ol < min_edge) min_edge = aw[t].ol; + } + + if(av[i].ol < min_edge * drop_ratio) to_del++; + } + + if(to_del != kv) continue; + + for (i = 0; i < nv; ++i) + { + if (av[i].del) continue; + ++n_cut; + av[i].del = 1; + asg_arc_del(g, av[i].v^1, av[i].ul>>32^1, 1); + } + } + + + if(n_cut > 0) + { + for (v = 0; v < n_vtx; ++v) + { + uint32_t nv = asg_arc_n(g, v); + if (g->seq[v>>1].del) + { + continue; + } + + if(nv < 2) + { + continue; + } + + + if(asg_bub_finder_without_del_advance(g, v, max_dist, &bub) == 1) + { + uint32_t i; + g->seq_vis[v] = 3; + g->seq_vis[v^1] = 3; + for (i = 0; i < bub.b.n; i++) + { + g->seq_vis[bub.b.a[i]] = 3; + g->seq_vis[bub.b.a[i]^1] = 3; + } + } + } + + + for (v = 0; v < n_vtx; ++v) + { + if(g->seq_vis[v] == 3) continue; + + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + uint32_t i; + for (i = 0; i < nv; ++i) + { + if (av[i].del && g->seq_vis[av[i].v] != 3) + { + av[i].del = 0; + asg_arc_del(g, av[i].v^1, av[i].ul>>32^1, 0); + } + } + } + } + + + + + free(b.a); free(b_f.a); free(b_r.a); + free(bub.a); free(bub.S.a); free(bub.T.a); free(bub.b.a); free(bub.e.a); + if (n_cut) + { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d false overlaps\n", __func__, n_cut); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return n_cut; +} + + +int asg_arc_del_short_diploid_by_exact(asg_t *g, int max_ext, ma_hit_t_alloc* sources) +{ + double startTime = Get_T(); + kvec_t(uint64_t) b; + memset(&b, 0, sizeof(b)); + + uint32_t v, n_vtx = g->n_seq * 2; + long long n_cut = 0; + + for (v = 0; v < n_vtx; ++v) + { + if(g->seq_vis[v] == 0) + { + asg_arc_t *av = asg_arc_a(g, v); + uint32_t nv = asg_arc_n(g, v); + if (nv < 2) continue; + long long i; + for (i = 0; i < nv; ++i) + { + kv_push(uint64_t, b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); + } + } + } + + radix_sort_arch64(b.a, b.a + b.n); + + uint64_t k; + for (k = 0; k < b.n; k++) + { + + asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; + ///v is self id, w is the id of another end + uint32_t i, iv, iw, v = (a->ul)>>32, w = a->v^1, to_del = 0; + uint32_t nv = asg_arc_n(g, v), nw = asg_arc_n(g, w), kv, kw; + uint32_t ov_max = 0, ow_max = 0, ov_max_i = 0; + asg_arc_t *av, *aw; + ///nv must be >= 2 + if (nv == 1 && nw == 1) continue; + av = asg_arc_a(g, v); + aw = asg_arc_a(g, w); + + + ///calculate the longest edge for v and w + for (i = 0, kv = 0; i < nv; ++i) { + if (av[i].del) continue; + if (ov_max < av[i].ol) + { + ov_max = av[i].ol; + ov_max_i = i; + } + ++kv; + } + if (kv >= 2 && a->ol == ov_max) continue; + + + for (i = 0, kw = 0; i < nw; ++i) { + if (aw[i].del) continue; + if (ow_max < aw[i].ol) + { + ow_max = aw[i].ol; + } + ++kw; + } + if (kw >= 2 && a->ol == ow_max) continue; + + ///if (kv == 1 && kw == 1) continue; + if (kv <= 1 && kw <= 1) continue; + + + ///to see which one is the current edge (from v and w) + for (iv = 0; iv < nv; ++iv) + if (av[iv].v == (w^1)) break; + for (iw = 0; iw < nw; ++iw) + if (aw[iw].v == (v^1)) break; + ///if one edge has been deleted, it should be deleted in both direction + if (av[iv].del && aw[iw].del) continue; + + + ///if this edge is an inexact edge + if(a->el == 0 && + sources[v>>1].is_fully_corrected == 1 && + sources[w>>1].is_fully_corrected == 1) + { + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + } + } + + if(a->el == 0 && + sources[v>>1].is_fully_corrected == 1 && + sources[w>>1].is_fully_corrected == 0) + { + /****************************may have bugs********************************/ + ///if(av[ov_max_i].el == 1 && sources[av[ov_max_i].v>>1].is_fully_corrected) + /****************************may have bugs********************************/ + if(av[ov_max_i].el == 1 && sources[av[ov_max_i].v>>1].is_fully_corrected == 1) + { + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + } + } + } + + + + if (to_del) + av[iv].del = aw[iw].del = 1, ++n_cut; + + } + + free(b.a); + if (n_cut) + { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %lld inexact overlaps\n", __func__, n_cut); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return n_cut; +} + +int asg_arc_del_short_diploid_by_exact_trio(asg_t *g, int max_ext, ma_hit_t_alloc* sources) +{ + double startTime = Get_T(); + kvec_t(uint64_t) b; + memset(&b, 0, sizeof(b)); + + uint32_t v, n_vtx = g->n_seq * 2; + long long n_cut = 0; + + for (v = 0; v < n_vtx; ++v) + { + if(g->seq_vis[v] == 0) + { + asg_arc_t *av = asg_arc_a(g, v); + uint32_t nv = asg_arc_n(g, v); + if (nv < 2) continue; + long long i; + for (i = 0; i < nv; ++i) + { + kv_push(uint64_t, b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); + } + } + } + + radix_sort_arch64(b.a, b.a + b.n); + + uint64_t k; + for (k = 0; k < b.n; k++) + { + + asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; + ///v is self id, w is the id of another end + uint32_t i, iv, iw, v = (a->ul)>>32, w = a->v^1, to_del = 0; + uint32_t nv = asg_arc_n(g, v), nw = asg_arc_n(g, w), kv, kw; + uint32_t ov_max = 0, ow_max = 0, ov_max_i = 0, trio_flag, non_trio_flag; + asg_arc_t *av, *aw; + ///nv must be >= 2 + if (nv == 1 && nw == 1) continue; + av = asg_arc_a(g, v); + aw = asg_arc_a(g, w); + kv = get_real_length(g, v, NULL); + kw = get_real_length(g, w, NULL); + if (kv <= 1 && kw <= 1) continue; + trio_flag = get_tip_trio_infor(g, v^1); + non_trio_flag = (uint32_t)-1; + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + + + ///calculate the longest edge for v and w + for (i = 0, kv = 0; i < nv; ++i) { + if (av[i].del) continue; + ++kv; + if(get_tip_trio_infor(g, av[i].v) == non_trio_flag) continue; + if (ov_max < av[i].ol) + { + ov_max = av[i].ol; + ov_max_i = i; + } + ///++kv; + } + if (kv >= 2 && a->ol == ov_max) continue; + + + for (i = 0, kw = 0; i < nw; ++i) { + if (aw[i].del) continue; + ++kw; + if (get_tip_trio_infor(g, aw[i].v) == non_trio_flag) continue; + if (ow_max < aw[i].ol) + { + ow_max = aw[i].ol; + } + ///++kw; + } + if (kw >= 2 && a->ol == ow_max) continue; + if (kv <= 1 && kw <= 1) continue; + + + ///to see which one is the current edge (from v and w) + for (iv = 0; iv < nv; ++iv) + if (av[iv].v == (w^1)) break; + for (iw = 0; iw < nw; ++iw) + if (aw[iw].v == (v^1)) break; + ///if one edge has been deleted, it should be deleted in both direction + if (av[iv].del && aw[iw].del) continue; + + + ///if this edge is an inexact edge + if(a->el == 0 && + sources[v>>1].is_fully_corrected == 1 && + sources[w>>1].is_fully_corrected == 1) + { + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + } + } + + if(a->el == 0 && + sources[v>>1].is_fully_corrected == 1 && + sources[w>>1].is_fully_corrected == 0) + { + /****************************may have bugs********************************/ + ///if(av[ov_max_i].el == 1 && sources[av[ov_max_i].v>>1].is_fully_corrected) + /****************************may have bugs********************************/ + if(av[ov_max_i].el == 1 && sources[av[ov_max_i].v>>1].is_fully_corrected == 1) + { + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + } + } + } + + + + if (to_del) + av[iv].del = aw[iw].del = 1, ++n_cut; + + } + + free(b.a); + if (n_cut) + { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %lld inexact overlaps\n", __func__, n_cut); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return n_cut; +} + + +int asg_arc_del_short_diploi_by_suspect_edge(asg_t *g, int max_ext) +{ + double startTime = Get_T(); + kvec_t(uint64_t) b; + memset(&b, 0, sizeof(b)); + + uint32_t v, n_vtx = g->n_seq * 2; + long long n_cut = 0; + + for (v = 0; v < n_vtx; ++v) + { + ///if(g->seq_vis[v] == 0) + { + asg_arc_t *av = asg_arc_a(g, v); + uint32_t nv = asg_arc_n(g, v); + if (nv < 2) continue; + + long long i; + for (i = 0; i < nv; ++i) + { + ///means there is a large indel at this edge + if(av[i].no_l_indel == 0) + { + kv_push(uint64_t, b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); + } + } + } + } + + + radix_sort_arch64(b.a, b.a + b.n); + + + uint64_t k; + for (k = 0; k < b.n; k++) + { + + asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; + ///v is self id, w is the id of another end + uint32_t i, iv, iw, v = (a->ul)>>32, w = a->v^1, to_del = 0; + uint32_t nv = asg_arc_n(g, v), nw = asg_arc_n(g, w), kv, kw; + asg_arc_t *av, *aw; + ///nv must be >= 2 + if (nv == 1 && nw == 1) continue; + av = asg_arc_a(g, v); + aw = asg_arc_a(g, w); + + ///calculate the longest edge for v and w + for (i = 0, kv = 0; i < nv; ++i) + { + if (av[i].del) continue; + ++kv; + } + + for (i = 0, kw = 0; i < nw; ++i) + { + if (aw[i].del) continue; + ++kw; + } + + if (kv == 1 && kw == 1) continue; + + ///to see which one is the current edge (from v and w) + for (iv = 0; iv < nv; ++iv) + if (av[iv].v == (w^1)) break; + for (iw = 0; iw < nw; ++iw) + if (aw[iw].v == (v^1)) break; + + ///if one edge has been deleted, it should be deleted in both direction + if (av[iv].del && aw[iw].del) continue; + + + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + } + + if (to_del) + av[iv].del = aw[iw].del = 1, ++n_cut; + } + + free(b.a); + if (n_cut) + { + asg_cleanup(g); + asg_symm(g); + } + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %lld suspect overlaps\n", __func__, n_cut); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return n_cut; +} + +int if_potential_false_node(ma_hit_t_alloc* paf, uint64_t rLen, ma_sub_t* max_left, ma_sub_t* max_right, int if_set) +{ + max_left->s = max_right->s = rLen; + max_left->e = max_right->e = 0; + + long long j; + uint32_t qs, qe; + for (j = 0; j < paf->length; j++) + { + if(paf->buffer[j].del) continue; + if(paf->buffer[j].el != 1) continue; + + qs = Get_qs(paf->buffer[j]); + qe = Get_qe(paf->buffer[j]); + + ///overlaps from left side + if(qs == 0) + { + if(qs < max_left->s) max_left->s = qs; + if(qe > max_left->e) max_left->e = qe; + } + + ///overlaps from right side + if(qe == rLen) + { + if(qs < max_right->s) max_right->s = qs; + if(qe > max_right->e) max_right->e = qe; + } + + ///note: if (qs == 0 && qe == rLen) + ///this overlap would be added to both b_left and b_right + ///that is what we want + } + + if (max_left->e > max_right->s) return 0; + + long long new_left_e, new_right_s; + new_left_e = max_left->e; + new_right_s = max_right->s; + + for (j = 0; j < paf->length; j++) + { + if(paf->buffer[j].del) continue; + if(paf->buffer[j].el != 1) continue; + + qs = Get_qs(paf->buffer[j]); + qe = Get_qe(paf->buffer[j]); + ///check contained overlaps + if(qs != 0 && qe != rLen) + { + ///[qs, qe), [max_left.s, max_left.e) + if(qs < max_left->e && qe > max_left->e) + { + ///if(qe > max_left->e) max_left->e = qe; + if(qe > max_left->e && qe > new_left_e) new_left_e = qe; + } + + ///[qs, qe), [max_right.s, max_right.e) + if(qs < max_right->s && qe > max_right->s) + { + ///if(qs < max_right->s) max_right->s = qs; + if(qs < max_right->s && qs < new_right_s) new_right_s = qs; + } + + + + if(if_set) + { + max_left->e = new_left_e; + max_right->s = new_right_s; + } + } + } + + max_left->e = new_left_e; + max_right->s = new_right_s; + + if (max_left->e > max_right->s) return 0; + + return 1; +} + +//reomve edge between two chromesomes +//this node must be a single read +int asg_arc_del_false_node(asg_t *g, ma_hit_t_alloc* sources, int max_ext) +{ + double startTime = Get_T(); + kvec_t(uint64_t) b; + memset(&b, 0, sizeof(b)); + ma_sub_t max_left, max_right; + + uint32_t v, n_vtx = g->n_seq * 2; + long long n_cut = 0; + + for (v = 0; v < n_vtx; ++v) + { + if(g->seq_vis[v] == 0) + { + if(asg_arc_n(g, v)!=1 || asg_arc_n(g, v^1)!=1) + { + continue; + } + + + if(asg_is_single_edge(g, asg_arc_a(g, v)[0].v, v>>1) < 2) + { + continue; + } + + if(asg_is_single_edge(g, asg_arc_a(g, v^1)[0].v, (v^1)>>1) < 2) + { + continue; + } + + if(asg_arc_a(g, v)[0].el == 1) + { + continue; + } + + if(if_potential_false_node(&(sources[v>>1]), g->seq[v>>1].len, &max_left, &max_right, 1)==0) + { + continue; + } + + asg_arc_t *av = asg_arc_a(g, v); + kv_push(uint64_t, b, (uint64_t)((uint64_t)av[0].ol << 32 | (av - g->arc))); + } + } + + radix_sort_arch64(b.a, b.a + b.n); + + uint64_t k; + ///here all edges are inexact matches + for (k = 0; k < b.n; k++) + { + + asg_arc_t *a = &g->arc[(uint32_t)b.a[k]]; + ///v is self id, w is the id of another end + uint32_t i, iv, iw, v = (a->ul)>>32, w = a->v^1; + uint32_t nv = asg_arc_n(g, v), nw = asg_arc_n(g, w), kv, kw; + asg_arc_t *av, *aw; + av = asg_arc_a(g, v); + aw = asg_arc_a(g, w); + + + ///calculate the longest edge for v and w + for (i = 0, kv = 0; i < nv; ++i) { + if (av[i].del) continue; + ++kv; + } + + for (i = 0, kw = 0; i < nw; ++i) { + if (aw[i].del) continue; + ++kw; + } + + if (kv < 1 || kw < 2) continue; + + ///to see which one is the current edge (from v and w) + for (iv = 0; iv < nv; ++iv) + if (av[iv].v == (w^1)) break; + for (iw = 0; iw < nw; ++iw) + if (aw[iw].v == (v^1)) break; + ///if one edge has been deleted, it should be deleted in both direction + if (av[iv].del && aw[iw].del) continue; + + + + uint32_t el_edges = 0; + ///there should be at least two available edges in aw + for (i = 0; i < nw; i++) + { + if (aw[i].del) continue; + + if(i != iw && aw[i].el == 1) + { + el_edges++; + } + } + + if(el_edges > 0 && av[iv].el == 0) + { + asg_seq_del(g, v>>1); + ++n_cut; + } + } + + free(b.a); + if (n_cut) + { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %lld single nodes\n", __func__, n_cut); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return n_cut; +} + +int64_t count_edges_v_w(asg_t *g, uint32_t v, uint32_t w) +{ + asg_arc_t* av = asg_arc_a(g, v); uint32_t nv = asg_arc_n(g, v), i, occ = 0; + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + if(av[i].v == w) occ++; + } + return occ; +} + +void update_ug_ou(ma_ug_t *ug, asg_t *sg) +{ + uint32_t k, i, uv, uw, rv, rw, nv; asg_arc_t *ue, *av; + for (k = 0; k < ug->g->n_arc; k++) { + ue = &(ug->g->arc[k]); ue->ou = 0; + uv = ue->ul>>32; uw = ue->v; + if(uv&1) rv = ug->u.a[uv>>1].start^1; + else rv = ug->u.a[uv>>1].end^1; + + if(uw&1) rw = ug->u.a[uw>>1].end; + else rw = ug->u.a[uw>>1].start; + + av = asg_arc_a(sg, rv); + nv = asg_arc_n(sg, rv); + for (i = 0; i < nv; i++) { + if(av[i].v == rw) break; + } + assert(i < nv); + ue->ou = av[i].ou; + } + + // asg_arc_t *e; uint32_t v, w; + // for (k = 0; k < sg->n_arc; k++) { + // e = &(sg->arc[k]); + // v = e->v^1; w = (e->ul>>32)^1; + // av = asg_arc_a(sg, v); nv = asg_arc_n(sg, v); + // for (i = 0; i < nv; i++) { + // if(av[i].v == w) break; + // } + // if(i >= nv || av[i].ou != e->ou) fprintf(stderr, "[M::%s::asymmetry]\n", __func__); + // } + + // for (k = 0; k < ug->g->n_arc; k++) { + // e = &(ug->g->arc[k]); + // v = e->v^1; w = (e->ul>>32)^1; + // av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); + // for (i = 0; i < nv; i++) { + // if(av[i].v == w) break; + // } + // if(i >= nv || av[i].ou != e->ou) fprintf(stderr, "[M::%s::asymmetry]\n", __func__); + // } +} + + +#define arc_cnt(g, v) ((uint32_t)(g)->idx[(v)]) +#define arc_first(g, v) ((g)->arc[(g)->idx[(v)]>>32]) + +ma_ug_t *ma_ug_gen(asg_t *g) +{ + asg_cleanup(g); + int32_t *mark; + uint32_t i, v, n_vtx = g->n_seq * 2; + ///is a queue + kdq_t(uint64_t) *q; + ma_ug_t *ug; + + ug = (ma_ug_t*)calloc(1, sizeof(ma_ug_t)); + ug->g = asg_init(); + ///each node has two directions + mark = (int32_t*)calloc(n_vtx, 4); + + q = kdq_init(uint64_t); + for (v = 0; v < n_vtx; ++v) { + uint32_t w, x, l, start, end, len; + ma_utg_t *p; + ///what's the usage of mark array + ///mark array is used to mark if this node has already been included in a contig + /****************************may have bugs********************************/ + ///if (g->seq[v>>1].del || arc_cnt(g, v) == 0 || mark[v]) continue; + if (g->seq[v>>1].del || mark[v]) continue; + if (arc_cnt(g, v) == 0 && arc_cnt(g, (v^1)) != 0) continue; + /****************************may have bugs********************************/ + mark[v] = 1; + q->count = 0, start = v, end = v^1, len = 0; + // forward + w = v; + while (1) { + /** + * w----->x + * w<-----x + * that means the only suffix of w is x, and the only prefix of x is w + **/ + if (arc_cnt(g, w) != 1) break; + x = arc_first(g, w).v; // w->x + if (arc_cnt(g, x^1) != 1) break; + + /** + * another direction of w would be marked as used (since w has been used) + **/ + mark[x] = mark[w^1] = 1; + ///l is the edge length, instead of overlap length + ///note: edge length is different with overlap length + l = asg_arc_len(arc_first(g, w)); + kdq_push(uint64_t, q, (uint64_t)w<<32 | l); + end = x^1, len += l; + w = x; + if (x == v) break; + } + if (start != (end^1) || kdq_size(q) == 0) { // linear unitig + ///length of seq, instead of edge + l = g->seq[end>>1].len; + kdq_push(uint64_t, q, (uint64_t)(end^1)<<32 | l); + len += l; + } else { // circular unitig + start = end = UINT32_MAX; + goto add_unitig; // then it is not necessary to do the backward + } + // backward + x = v; + while (1) { // similar to forward but not the same + if (arc_cnt(g, x^1) != 1) break; + w = arc_first(g, x^1).v ^ 1; // w->x + if (arc_cnt(g, w) != 1) break; + mark[x] = mark[w^1] = 1; + l = asg_arc_len(arc_first(g, w)); + ///w is the seq id + direction, l is the length of edge + ///push element to the front of a queue + kdq_unshift(uint64_t, q, (uint64_t)w<<32 | l); + + // fprintf(stderr, "uId: %u, >%.*s (%u)\n", + // ug->u.n, (int)Get_NAME_LENGTH((R_INF), w>>1), Get_NAME((R_INF), w>>1), w>>1); + + start = w, len += l; + x = w; + } +add_unitig: + if (start != UINT32_MAX) mark[start] = mark[end] = 1; + kv_pushp(ma_utg_t, ug->u, &p); + p->s = 0, p->start = start, p->end = end, p->len = len, p->n = kdq_size(q), p->circ = (start == UINT32_MAX); + p->m = p->n; + kv_roundup32(p->m); + p->a = (uint64_t*)malloc(8 * p->m); + //all elements are saved here + for (i = 0; i < kdq_size(q); ++i) + p->a[i] = kdq_at(q, i); + } + kdq_destroy(uint64_t, q); + + // add arcs between unitigs; reusing mark for a different purpose + //ug saves all unitigs + for (v = 0; v < n_vtx; ++v) mark[v] = -1; + + //mark all start nodes and end nodes of all unitigs + for (i = 0; i < ug->u.n; ++i) { + if (ug->u.a[i].circ) continue; + mark[ug->u.a[i].start] = i<<1 | 0; + mark[ug->u.a[i].end] = i<<1 | 1; + } + + //scan all edges + for (i = 0; i < g->n_arc; ++i) { + asg_arc_t *p = &g->arc[i]; + if (p->del) continue; + ///to connect two unitigs, we need to connect the end of unitig x to the start of unitig y + ///so we need to ^1 to get the reverse direction of (x's end)? + ///>=0 means this node is a start/end node of an unitig + ///means this node is a intersaction node + if (mark[p->ul>>32^1] >= 0 && mark[p->v] >= 0) { + asg_arc_t *q; + uint32_t u = mark[p->ul>>32^1]^1; + int l = ug->u.a[u>>1].len - p->ol; + if (l < 0) l = 1; + q = asg_arc_pushp(ug->g); + q->ol = p->ol, q->del = 0; + q->ul = (uint64_t)u<<32 | l; + q->v = mark[p->v]; q->ou = 0; + q->el = p->el; + } + } + for (i = 0; i < ug->u.n; ++i) + asg_seq_set(ug->g, i, ug->u.a[i].len, 0); + asg_cleanup(ug->g); + free(mark); + return ug; +} + +ma_ug_t *ma_ug_gen_phase(asg_t *g, uint32_t min_occ, double cutoff) +{ + // fprintf(stderr, "\n-0-[M::%s] min_occ::%u, cutoff::%f\n", __func__, min_occ, cutoff); + asg_cleanup(g); + int32_t *mark; + uint32_t i, v, n_vtx = g->n_seq * 2, fn, mn, fn0, mn0, fn1, mn1, n1, cn, k, st, pt, ct, sz, ez; + uint64_t z; + ///is a queue + kdq_t(uint64_t) *q; + asg64_v uidx; kv_init(uidx); + + ma_ug_t *ug; + + ug = (ma_ug_t*)calloc(1, sizeof(ma_ug_t)); + ug->g = asg_init(); + ///each node has two directions + mark = (int32_t*)calloc(n_vtx, 4); + + q = kdq_init(uint64_t); + for (v = 0; v < n_vtx; ++v) { + uint32_t w, x, l, start, end, len; + ma_utg_t *p; + if (g->seq[v>>1].del || mark[v]) continue; + if (arc_cnt(g, v) == 0 && arc_cnt(g, (v^1)) != 0) continue; + mark[v] = 1; + q->count = 0, start = v, end = v^1, len = 0; fn = mn = 0; + // forward + w = v; + while (1) { + /** + * w----->x + * w<-----x + * that means the only suffix of w is x, and the only prefix of x is w + **/ + if (arc_cnt(g, w) != 1) break; + x = arc_first(g, w).v; // w->x + if (arc_cnt(g, x^1) != 1) break; + /** + * another direction of w would be marked as used (since w has been used) + **/ + mark[x] = mark[w^1] = 1; + ///l is the edge length, instead of overlap length + ///note: edge length is different with overlap length + l = asg_arc_len(arc_first(g, w)); + kdq_push(uint64_t, q, (uint64_t)w<<32 | l); + if(R_INF.trio_flag[w>>1] == FATHER) fn++; + if(R_INF.trio_flag[w>>1] == MOTHER) mn++; + end = x^1, len += l; + w = x; + if (x == v) break; + } + if (start != (end^1) || kdq_size(q) == 0) { // linear unitig + ///length of seq, instead of edge + l = g->seq[end>>1].len; + kdq_push(uint64_t, q, (uint64_t)(end^1)<<32 | l); + if(R_INF.trio_flag[end>>1] == FATHER) fn++; + if(R_INF.trio_flag[end>>1] == MOTHER) mn++; + len += l; + } else { // circular unitig + start = end = UINT32_MAX; + goto add_unitig; // then it is not necessary to do the backward + } + // backward + x = v; + while (1) { // similar to forward but not the same + if (arc_cnt(g, x^1) != 1) break; + w = arc_first(g, x^1).v ^ 1; // w->x + if (arc_cnt(g, w) != 1) break; + mark[x] = mark[w^1] = 1; + l = asg_arc_len(arc_first(g, w)); + ///w is the seq id + direction, l is the length of edge + ///push element to the front of a queue + kdq_unshift(uint64_t, q, (uint64_t)w<<32 | l); + if(R_INF.trio_flag[w>>1] == FATHER) fn++; + if(R_INF.trio_flag[w>>1] == MOTHER) mn++; + // fprintf(stderr, "uId: %u, >%.*s (%u)\n", + // ug->u.n, (int)Get_NAME_LENGTH((R_INF), w>>1), Get_NAME((R_INF), w>>1), w>>1); + + start = w, len += l; + x = w; + } +add_unitig: + if (start != UINT32_MAX) mark[start] = mark[end] = 1; + // fprintf(stderr, "\n-0-[M::%s] fn::%u, mn::%u\n", __func__, fn, mn); + cn = MIN(fn, mn); + // if((cn > min_occ) && (cn > ((fn+mn)*cutoff))) + if((cn <= ((fn+mn)*cutoff)) || (cn <= min_occ)) { + kv_pushp(ma_utg_t, ug->u, &p); + p->s = 0, p->start = start, p->end = end, p->len = len, p->n = kdq_size(q), p->circ = (start == UINT32_MAX); + p->m = p->n; + kv_roundup32(p->m); + p->a = (uint64_t*)malloc(8 * p->m); + //all elements are saved here + for (i = 0; i < kdq_size(q); ++i) p->a[i] = kdq_at(q, i); + } else if(kdq_size(q)) { + ct = R_INF.trio_flag[kdq_at(q, 0)>>33]; + if((ct != FATHER) && (ct != MOTHER)) ct = AMBIGU; + pt = ct; + fn0 = fn; mn0 = mn; uidx.n = fn = mn = 0; + if(ct == FATHER) {fn++;} if(ct == MOTHER) {mn++;} + for (k = 1, l = 0; k <= kdq_size(q); k++) { + st = 0; ct = AMBIGU; + if(k == kdq_size(q)) { + st = 1; + } else { + ct = R_INF.trio_flag[kdq_at(q, k)>>33]; + if((ct != FATHER) && (ct != MOTHER)) ct = AMBIGU; + if((ct != AMBIGU) && (pt != AMBIGU) && (ct != pt)) { + st = 1; + } + } + if(st) { + // fprintf(stderr, "-1-[M::%s] l::%u, k::%u, kdq_size(q)::%u, fn::%u, mn::%u, ct::%u, pt::%u\n", + // __func__, l, k, (uint32_t)kdq_size(q), fn, mn, ct, pt); + if(k < kdq_size(q)) { + assert(fn || mn); assert((!fn) || (!mn)); + } + z = l<<1; z |= (((uint64_t)MAX(fn, mn))<<32); + if(mn) z |= 1; + kv_push(uint64_t, uidx, z); + fn = mn = 0; l = k; + } + if(ct != AMBIGU) pt = ct; + if(ct == FATHER) {fn++;} if(ct == MOTHER) {mn++;} + } + + + fn = mn = 0; fn1 = mn1 = n1 = 0; + if(uidx.a[0]&1) mn += uidx.a[0]>>32; + else fn += uidx.a[0]>>32; + for (k = 1, l = 0; k <= uidx.n; k++) { + st = 0; + if(k == uidx.n) { + st = 1; + } else { + if(uidx.a[k]&1) mn += uidx.a[k]>>32; + else fn += uidx.a[k]>>32; + cn = MIN(fn, mn); + if((cn > min_occ) && (cn > ((fn+mn)*cutoff))) st = 1; + // fprintf(stderr, "-2-[M::%s] fn::%u, mn::%u, cn::%u, ((fn+mn)*cutoff)::%u, st::%u\n", + // __func__, fn, mn, cn, (uint32_t)(((fn+mn)*cutoff)), st); + } + if(st) { + // fprintf(stderr, "-3-[M::%s] fn::%u, mn::%u\n", __func__, fn, mn); + sz = ((uint32_t)uidx.a[l])>>1; + ez = ((k>1):(kdq_size(q))); + assert(ez > sz); n1 += ez - sz; + kv_pushp(ma_utg_t, ug->u, &p); + if ((start == UINT32_MAX) && (sz == 0) && (ez == kdq_size(q))) {///circle + p->s = 0, p->start = start, p->end = end, p->len = len, p->n = kdq_size(q), p->circ = (start == UINT32_MAX); + p->m = p->n; + kv_roundup32(p->m); + p->a = (uint64_t*)malloc(8 * p->m); + //all elements are saved here + for (i = 0; i < kdq_size(q); ++i) { + p->a[i] = kdq_at(q, i); + ct = R_INF.trio_flag[p->a[i]>>33]; + if((ct != FATHER) && (ct != MOTHER)) ct = AMBIGU; + if(ct == FATHER) {fn1++;} if(ct == MOTHER) {mn1++;} + } + } else { + p->s = 0; p->len = 0; p->circ = 0; + p->start = kdq_at(q, sz)>>32; + p->end = (kdq_at(q, (ez-1))>>32)^1; + p->m = p->n = ez - sz; kv_roundup32(p->m); + p->a = (uint64_t*)malloc(8 * p->m); + + for (i = sz, z = 0; i+1 < ez; i++, z++) { + p->a[z] = kdq_at(q, i); p->len += (uint32_t)p->a[z]; + ct = R_INF.trio_flag[p->a[z]>>33]; + if((ct != FATHER) && (ct != MOTHER)) ct = AMBIGU; + if(ct == FATHER) {fn1++;} if(ct == MOTHER) {mn1++;} + } + p->a[z] = kdq_at(q, i); p->a[z] >>= 32; p->a[z] <<= 32; + p->a[z] |= g->seq[p->a[z]>>33].len; p->len += (uint32_t)p->a[z]; + ct = R_INF.trio_flag[p->a[z]>>33]; + if((ct != FATHER) && (ct != MOTHER)) ct = AMBIGU; + if(ct == FATHER) {fn1++;} if(ct == MOTHER) {mn1++;} + } + fn = mn = 0; l = k; + if(k < uidx.n) { + if(uidx.a[k]&1) mn += uidx.a[k]>>32; + else fn += uidx.a[k]>>32; + } + } + } + assert(n1 == kdq_size(q)); + assert(fn1 == fn0); assert(mn1 == mn0); + } + } + kdq_destroy(uint64_t, q); kv_destroy(uidx); + + // add arcs between unitigs; reusing mark for a different purpose + //ug saves all unitigs + for (v = 0; v < n_vtx; ++v) mark[v] = -1; + + //mark all start nodes and end nodes of all unitigs + for (i = 0; i < ug->u.n; ++i) { + if (ug->u.a[i].circ) continue; + mark[ug->u.a[i].start] = i<<1 | 0; + mark[ug->u.a[i].end] = i<<1 | 1; + } + + //scan all edges + for (i = 0; i < g->n_arc; ++i) { + asg_arc_t *p = &g->arc[i]; + if (p->del) continue; + ///to connect two unitigs, we need to connect the end of unitig x to the start of unitig y + ///so we need to ^1 to get the reverse direction of (x's end)? + ///>=0 means this node is a start/end node of an unitig + ///means this node is a intersaction node + if (mark[p->ul>>32^1] >= 0 && mark[p->v] >= 0) { + asg_arc_t *q; + uint32_t u = mark[p->ul>>32^1]^1; + int l = ug->u.a[u>>1].len - p->ol; + if (l < 0) l = 1; + q = asg_arc_pushp(ug->g); + q->ol = p->ol, q->del = 0; + q->ul = (uint64_t)u<<32 | l; + q->v = mark[p->v]; q->ou = 0; + q->el = p->el; + } + } + for (i = 0; i < ug->u.n; ++i) + asg_seq_set(ug->g, i, ug->u.a[i].len, 0); + asg_cleanup(ug->g); + free(mark); + return ug; +} + +ma_ug_t *ma_ug_gen_primary(asg_t *g, uint8_t flag) +{ + asg_cleanup(g); + int32_t *mark; + uint32_t i, v, n_vtx = g->n_seq * 2; + ///is a queue + kdq_t(uint64_t) *q; + ma_ug_t *ug; + + ug = (ma_ug_t*)calloc(1, sizeof(ma_ug_t)); + ug->g = asg_init(); + ///each node has two directions + mark = (int32_t*)calloc(n_vtx, 4); + + ///for each untig, all node have the same direction + ///and all node except the last one just have one edge + ///the last one may have multiple edges + q = kdq_init(uint64_t); + for (v = 0; v < n_vtx; ++v) { + uint32_t w, x, l, start, end, len; + ma_utg_t *p; + ///what's the usage of mark array + ///mark array is used to mark if this node has already been included in a contig + /****************************may have hap bugs********************************/ + ///if (g->seq[v>>1].del || arc_cnt(g, v) == 0 || mark[v] || g->seq[v>>1].c != flag) continue; + ///if (g->seq[v>>1].del || arc_cnt(g, v) == 0 || mark[v] || (g->seq[v>>1].c & flag) == 0) continue; + ///if (g->seq[v>>1].del || arc_cnt(g, v) == 0 || mark[v]) continue; + if (g->seq[v>>1].del || mark[v]) continue; + if (arc_cnt(g, v) == 0 && arc_cnt(g, (v^1)) != 0) continue; + if(flag == PRIMARY_LABLE && g->seq[v>>1].c == ALTER_LABLE) continue; + if(flag == ALTER_LABLE && g->seq[v>>1].c != ALTER_LABLE) continue; + /****************************may have hap bugs********************************/ + mark[v] = 1; + q->count = 0, start = v, end = v^1, len = 0; + // forward + w = v; + while (1) { + /** + * w----->x + * w<-----x + * that means the only suffix of w is x, and the only prefix of x is w + **/ + if (arc_cnt(g, w) != 1) break; + x = arc_first(g, w).v; // w->x + if (arc_cnt(g, x^1) != 1) break; + + /** + * another direction of w would be marked as used (since w has been used) + **/ + mark[x] = mark[w^1] = 1; + ///l is the edge length, instead of overlap length + ///note: edge length is different with overlap length + l = asg_arc_len(arc_first(g, w)); + kdq_push(uint64_t, q, (uint64_t)w<<32 | l); + end = x^1, len += l; + w = x; + if (x == v) break; + } + ///kdq_size(q) == 0 means there is just one read + if (start != (end^1) || kdq_size(q) == 0) { // linear unitig + ///length of seq, instead of edge + l = g->seq[end>>1].len; + kdq_push(uint64_t, q, (uint64_t)(end^1)<<32 | l); + len += l; + } else { // circular unitig + start = end = UINT32_MAX; + goto add_unitig; // then it is not necessary to do the backward + } + // backward + x = v; + while (1) { // similar to forward but not the same + if (arc_cnt(g, x^1) != 1) break; + w = arc_first(g, x^1).v ^ 1; // w->x + if (arc_cnt(g, w) != 1) break; + mark[x] = mark[w^1] = 1; + l = asg_arc_len(arc_first(g, w)); + ///w is the seq id + direction, l is the length of edge + ///push element to the front of a queue + kdq_unshift(uint64_t, q, (uint64_t)w<<32 | l); + start = w, len += l; + x = w; + } +add_unitig: + if (start != UINT32_MAX) mark[start] = mark[end] = 1; + kv_pushp(ma_utg_t, ug->u, &p); + p->s = 0, p->start = start, p->end = end, p->len = len, p->n = kdq_size(q), p->circ = (start == UINT32_MAX); + p->m = p->n; + kv_roundup32(p->m); + p->a = (uint64_t*)malloc(8 * p->m); + //all elements are saved here + for (i = 0; i < kdq_size(q); ++i) + p->a[i] = kdq_at(q, i); + } + kdq_destroy(uint64_t, q); + + // add arcs between unitigs; reusing mark for a different purpose + //ug saves all unitigs + for (v = 0; v < n_vtx; ++v) mark[v] = -1; + + //mark all start nodes and end nodes of all unitigs + ///note ug->u.a[i].start == ug->u.a[i].a[0] + ///but ug->u.a[i].end = ug->u.a[i].a[ug->u.a[i].n-1]^1 + ///ug->u.a[i].start has the same direction as other non-end node + ///while ug->u.a[i].end is the only one with reverse direction + for (i = 0; i < ug->u.n; ++i) { + if (ug->u.a[i].circ) continue; + ///i is the untig id + mark[ug->u.a[i].start] = i<<1 | 0; + mark[ug->u.a[i].end] = i<<1 | 1; + } + + //scan all edges + for (i = 0; i < g->n_arc; ++i) { + asg_arc_t *p = &g->arc[i]; + if (p->del) continue; + /** + p->ul: |____________31__________|__________1___________|______________32_____________| + qns direction of overlap length of this node (not overlap length) + (based on query) + p->v : |___________31___________|__________1___________| + tns reverse direction of overlap + (based on target) + p->ol: overlap length + **/ + ///to connect two unitigs, we need to connect the end of unitig x to the start of unitig y + ///so we need to ^1 to get the reverse direction of (x's end)? + ///>=0 means this node is a start/end node of an unitig + ///means this node is a intersaction node + /**for one untig, + start end + -----> <------ + so if we want to find the edge between two untigs, their start and end look like: + + start end + -----> <------ + --------------------------- + + start end + -----> <------ + --------------------------- + p->ul>>32^1 is the end of the first untig, + p->v is the start of the second untig + **/ + if (mark[p->ul>>32^1] >= 0 && mark[p->v] >= 0) { + asg_arc_t *q; + uint32_t u = mark[p->ul>>32^1]^1; + int l = ug->u.a[u>>1].len - p->ol; + if (l < 0) l = 1; + q = asg_arc_pushp(ug->g); + q->ol = p->ol, q->del = 0; + q->ul = (uint64_t)u<<32 | l; + q->v = mark[p->v]; q->ou = 0; + q->el = p->el; + } + } + for (i = 0; i < ug->u.n; ++i) + asg_seq_set(ug->g, i, ug->u.a[i].len, 0); + asg_cleanup(ug->g); + free(mark); + return ug; +} + +static char comp_tab[] = { // complement base + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 'T', 'V', 'G', 'H', 'E', 'F', 'C', 'D', 'I', 'J', 'M', 'L', 'K', 'N', 'O', + 'P', 'Q', 'Y', 'S', 'A', 'A', 'B', 'W', 'X', 'R', 'Z', 91, 92, 93, 94, 95, + 64, 't', 'v', 'g', 'h', 'e', 'f', 'c', 'd', 'i', 'j', 'm', 'l', 'k', 'n', 'o', + 'p', 'q', 'y', 's', 'a', 'a', 'b', 'w', 'x', 'r', 'z', 123, 124, 125, 126, 127 +}; + + +void recover_fake_read(UC_Read* result, UC_Read* tmp, ma_utg_t *u, +All_reads *RNF, const ma_sub_t *coverage_cut) +{ + uint32_t j, k, ori, start, l = 0, eLen, rId, readLen; + if(result->size < u->len) + { + result->size = u->len; + result->seq = (char*)realloc(result->seq,sizeof(char)*(result->size)); + } + char* readS = NULL; + + for (j = 0; j < u->n; ++j) { + rId = u->a[j]>>33; + ///uId = i; + ori = u->a[j]>>32&1; + start = l; + eLen = (uint32_t)u->a[j]; + l += eLen; + + if(eLen == 0) continue; + + recover_UC_Read(tmp, RNF, rId); + readS = tmp->seq + coverage_cut[rId].s; + readLen = coverage_cut[rId].e - coverage_cut[rId].s; + + + if (!ori) // forward strand + { + for (k = 0; k < eLen; k++) + { + result->seq[start + k] = readS[k]; + } + } + else + { + for (k = 0; k < eLen; k++) + { + uint8_t c = (uint8_t)readS[readLen - 1 - k]; + result->seq[start + k] = c >= 128? 'N' : comp_tab[c]; + } + } + } + + result->length = u->end - u->start; + for (j = u->start; j < u->end; j++) + { + result->seq[j - u->start] = result->seq[j]; + } +} + +void get_overlapLen(uint32_t rId, ma_hit_t_alloc* sources, uint32_t* exactLen, uint32_t* inexactLen) +{ + (*exactLen) = (*inexactLen) = 0; + ma_hit_t_alloc* x = &(sources[rId]); + ma_hit_t *h = NULL; + uint32_t i, len; + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + len = Get_qe((*h)) - Get_qs((*h)); + if(h->el == 1) + { + (*exactLen) += len; + } + else + { + (*inexactLen) += len; + } + } +} + + +void reduce_ma_utg_t(ma_utg_t* collection, asg_t* read_g, ma_hit_t_alloc* sources, +ma_sub_t *coverage_cut, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* newE) +{ + asg_arc_t t_f; + asg_arc_t* av = NULL; + uint32_t m = 0, k, i, nv; + for (i = 0; i < collection->n; i++) + { + if(collection->a[i] == (uint64_t)-1) + { + // if(newE) asg_seq_del(read_g, collection->a[i]>>33); + continue; + } + + collection->a[m] = collection->a[i]; + m++; + } + collection->n = m; + + + uint32_t totalLen = 0, v, w, l; + for (i = 0; i < collection->n - 1; i++) + { + v = (uint64_t)(collection->a[i])>>32; + w = (uint64_t)(collection->a[i + 1])>>32; + + + + + /*******************************for debug************************************/ + l = (uint32_t)-1; + av = asg_arc_a(read_g, v); + nv = asg_arc_n(read_g, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + l = asg_arc_len(av[k]); + break; + } + } + + if(k == nv) + { + for (k = 0; k < edge->a.n; k++) + { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) + { + l = asg_arc_len(edge->a.a[k]); + break; + } + } + + if(k == edge->a.n) + { + if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, v, w, &t_f)==0) + { + fprintf(stderr, "####ERROR1: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", + v>>1, v&1, w>>1, w&1, read_g->r_seq); + } + l = asg_arc_len(t_f); + + + if(newE) + { + kv_push(asg_arc_t, newE->a, t_f); + if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, w^1, v^1, &t_f)==0) + { + fprintf(stderr, "####ERROR2: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", + v>>1, v&1, w>>1, w&1, read_g->r_seq); + } + kv_push(asg_arc_t, newE->a, t_f); + } + + } + else if(newE) + { + kv_push(asg_arc_t, newE->a, edge->a.a[k]); + for (k = 0; k < edge->a.n; k++) + { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == (w^1) && edge->a.a[k].v == (v^1)) + { + l = asg_arc_len(edge->a.a[k]); + break; + } + } + kv_push(asg_arc_t, newE->a, edge->a.a[k]); + } + } + if(l == (uint32_t)-1) fprintf(stderr, "ERROR\n"); + /*******************************for debug************************************/ + + + + + + + + + + collection->a[i] = v; collection->a[i] = collection->a[i]<<32; + collection->a[i] = collection->a[i] | (uint64_t)(l); + totalLen += l; + } + + if(i < collection->n) + { + if(collection->circ) + { + v = (uint64_t)(collection->a[i])>>32; + w = (uint64_t)(collection->a[0])>>32; + + + + + /*******************************for debug************************************/ + l = (uint32_t)-1; + av = asg_arc_a(read_g, v); + nv = asg_arc_n(read_g, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + l = asg_arc_len(av[k]); + break; + } + } + + if(k == nv) + { + for (k = 0; k < edge->a.n; k++) + { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) + { + l = asg_arc_len(edge->a.a[k]); + break; + } + } + + if(k == edge->a.n) + { + if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, v, w, &t_f)==0) + { + fprintf(stderr, "####ERROR1: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", + v>>1, v&1, w>>1, w&1, read_g->r_seq); + } + l = asg_arc_len(t_f); + + if(newE) + { + kv_push(asg_arc_t, newE->a, t_f); + if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, w^1, v^1, &t_f)==0) + { + fprintf(stderr, "####ERROR2: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", + v>>1, v&1, w>>1, w&1, read_g->r_seq); + } + kv_push(asg_arc_t, newE->a, t_f); + } + } + else if(newE) + { + kv_push(asg_arc_t, newE->a, edge->a.a[k]); + for (k = 0; k < edge->a.n; k++) + { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == (w^1) && edge->a.a[k].v == (v^1)) + { + l = asg_arc_len(edge->a.a[k]); + break; + } + } + kv_push(asg_arc_t, newE->a, edge->a.a[k]); + } + } + if(l == (uint32_t)-1) fprintf(stderr, "ERROR\n"); + /*******************************for debug************************************/ + + + + + + + + + + + + + collection->a[i] = v; collection->a[i] = collection->a[i]<<32; + collection->a[i] = collection->a[i] | (uint64_t)(l); + + totalLen += l; + } + else + { + v = (uint64_t)(collection->a[i])>>32; + l = read_g->seq[v>>1].len; + collection->a[i] = v; + collection->a[i] = collection->a[i]<<32; + collection->a[i] = collection->a[i] | (uint64_t)(l); + totalLen += l; + } + } + + collection->len = totalLen; + if(!collection->circ) + { + collection->start = collection->a[0]>>32; + collection->end = (collection->a[collection->n-1]>>32)^1; + } +} + + +void reduce_ma_utg_t_scaf(ma_utg_t *in, asg_t *rg, ma_hit_t_alloc* src, ma_sub_t *cov, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* newE) +{ + asg_arc_t t_f; + asg_arc_t* av = NULL; + uint32_t m = 0, k, i, nv; + for (i = 0; i < in->n; i++) { + if(in->a[i] == (uint64_t)-1) { + // if(newE) asg_seq_del(read_g, collection->a[i]>>33); + continue; + } + + in->a[m] = in->a[i]; + m++; + } + in->n = m; + + + uint32_t totalLen = 0, v, w, l; + for (i = 0; i + 1 < in->n; i++) { + v = (uint64_t)(in->a[i])>>32; + w = (uint64_t)(in->a[i + 1])>>32; + l = Get_READ_LENGTH(R_INF, (v>>1)); ///for Ns + + if((!IS_SCAF_READ(R_INF, v>>1)) && (!IS_SCAF_READ(R_INF, w>>1))) { + /*******************************for debug************************************/ + l = (uint32_t)-1; + av = asg_arc_a(rg, v); nv = asg_arc_n(rg, v); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == w) { + l = asg_arc_len(av[k]); + break; + } + } + + if(k == nv) { + for (k = 0; k < edge->a.n; k++) { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) { + l = asg_arc_len(edge->a.a[k]); + break; + } + } + + if(k == edge->a.n) { + if(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, v, w, &t_f)==0) { + fprintf(stderr, "####ERROR1: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", + v>>1, v&1, w>>1, w&1, rg->r_seq); + } + l = asg_arc_len(t_f); + + + if(newE) { + kv_push(asg_arc_t, newE->a, t_f); + if(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, w^1, v^1, &t_f)==0) { + fprintf(stderr, "####ERROR2: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", + v>>1, v&1, w>>1, w&1, rg->r_seq); + } + kv_push(asg_arc_t, newE->a, t_f); + } + + } + else if(newE) { + kv_push(asg_arc_t, newE->a, edge->a.a[k]); + for (k = 0; k < edge->a.n; k++) { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == (w^1) && edge->a.a[k].v == (v^1)) { + l = asg_arc_len(edge->a.a[k]); + break; + } + } + kv_push(asg_arc_t, newE->a, edge->a.a[k]); + } + } + if(l == (uint32_t)-1) fprintf(stderr, "ERROR\n"); + /*******************************for debug************************************/ + } + + + in->a[i] = v; in->a[i] = in->a[i]<<32; + in->a[i] = in->a[i] | (uint64_t)(l); + totalLen += l; + } + + if(i < in->n) { + if(in->circ) { + v = (uint64_t)(in->a[i])>>32; + w = (uint64_t)(in->a[0])>>32; + l = Get_READ_LENGTH(R_INF, (v>>1)); ///for Ns + + if((!IS_SCAF_READ(R_INF, v>>1)) && (!IS_SCAF_READ(R_INF, w>>1))) { + /*******************************for debug************************************/ + l = (uint32_t)-1; + av = asg_arc_a(rg, v); + nv = asg_arc_n(rg, v); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == w) { + l = asg_arc_len(av[k]); + break; + } + } + + if(k == nv) { + for (k = 0; k < edge->a.n; k++) { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) { + l = asg_arc_len(edge->a.a[k]); + break; + } + } + + if(k == edge->a.n) { + if(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, v, w, &t_f)==0) { + fprintf(stderr, "####ERROR1: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", + v>>1, v&1, w>>1, w&1, rg->r_seq); + } + l = asg_arc_len(t_f); + + if(newE) { + kv_push(asg_arc_t, newE->a, t_f); + if(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, w^1, v^1, &t_f)==0) { + fprintf(stderr, "####ERROR2: v>>1: %u, v&1: %u, w>>1: %u, w&1: %u, r_seq: %u\n", + v>>1, v&1, w>>1, w&1, rg->r_seq); + } + kv_push(asg_arc_t, newE->a, t_f); + } + } else if(newE) { + kv_push(asg_arc_t, newE->a, edge->a.a[k]); + for (k = 0; k < edge->a.n; k++) { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == (w^1) && edge->a.a[k].v == (v^1)) { + l = asg_arc_len(edge->a.a[k]); + break; + } + } + kv_push(asg_arc_t, newE->a, edge->a.a[k]); + } + } + if(l == (uint32_t)-1) fprintf(stderr, "ERROR\n"); + /*******************************for debug************************************/ + } + + in->a[i] = v; in->a[i] = in->a[i]<<32; + in->a[i] = in->a[i] | (uint64_t)(l); + + totalLen += l; + } else { + v = (uint64_t)(in->a[i])>>32; + l = rg->seq[v>>1].len; + in->a[i] = v; + in->a[i] = in->a[i]<<32; + in->a[i] = in->a[i] | (uint64_t)(l); + totalLen += l; + } + } + + in->len = totalLen; + if(!in->circ) { + in->start = in->a[0]>>32; + in->end = (in->a[in->n-1]>>32)^1; + } +} + + +uint32_t detect_exact_ovec(ma_utg_t* collection, asg_t* read_g, ma_hit_t_alloc* sources, +ma_sub_t *coverage_cut, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, +uint32_t src, uint32_t dest_idx) +{ + asg_arc_t *t = NULL, i_t; + uint32_t i, k, dest; + for (i = dest_idx; i < collection->n; i++) + { + t = NULL; + dest = (uint64_t)(collection->a[i])>>32; + if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, src, dest, &i_t) == 0) + { + for (k = 0; k < edge->a.n; k++) + { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == src && edge->a.a[k].v == dest) + { + t = &(edge->a.a[k]); + break; + } + } + } + else + { + t = &i_t; + } + + if(t == NULL) return (uint32_t)-1; + if(t->el != 1) continue; + return i; + } + + return (uint32_t)-1; +} + +void get_specific_edge(ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, asg_t* read_g, int max_hang, +int min_ovlp, uint32_t query, uint32_t target, asg_arc_t* t) +{ + uint32_t nv, k; + (*t).ul = (uint64_t)-1; (*t).v = (uint32_t)-1; + if(read_g) + { + asg_arc_t* av = asg_arc_a(read_g, query); + nv = asg_arc_n(read_g, query); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == target) + { + (*t) = av[k]; + break; + } + } + } + + if((*t).ul == (uint64_t)-1) + { + if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, query, target, t)==0) + { + (*t).ul = (uint64_t)-1; + } + } + + if((*t).ul == (uint64_t)-1) + { + for (k = 0; k < edge->a.n; k++) + { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == query && edge->a.a[k].v == target) + { + (*t) = edge->a.a[k]; + break; + } + } + if(k == edge->a.n) fprintf(stderr, "ERROR\n"); + } + +} + +uint32_t polish_unitig(ma_utg_t* collection, asg_t* read_g, ma_hit_t_alloc* sources, +ma_sub_t *coverage_cut, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, +kvec_asg_arc_t_warp* newE) +{ + if(collection->m == 0) return 0; + if(collection->n < 3) return 0; + uint32_t i, k, v, pre, pre_i, afte, afte_i, exactLen, inexactLen, skip = 0; + uint32_t min_inexactLen, max_exactLen; + asg_arc_t pE, aE; + + pre = (uint64_t)(collection->a[0])>>32; pre_i = 0; afte_i = (uint32_t)-1; + for (i = 1; i < collection->n - 1; i++) { + if(collection->a[i] == (uint64_t)-1) continue; + ///v and after must be available + v = (uint64_t)(collection->a[i])>>32; + afte = (uint64_t)(collection->a[i+1])>>32; + + get_specific_edge(sources, coverage_cut, NULL, edge, pre_i == i-1? read_g:NULL, max_hang, min_ovlp, + v^1, pre^1, &pE); + get_specific_edge(sources, coverage_cut, NULL, edge, read_g, max_hang, min_ovlp, + v, afte, &aE); + + if(pE.el == 1 && aE.el == 1) + { + pre = (uint64_t)(collection->a[i])>>32; pre_i = i; + continue; + } + + ///pre must be a good read, we need to find a good after + ///update a new afte + afte_i = detect_exact_ovec(collection, read_g, sources, coverage_cut, edge, + max_hang, min_ovlp, pre, i+1); + if(afte_i == (uint32_t)-1) + { + pre = (uint64_t)(collection->a[i])>>32; pre_i = i; + continue; + } + afte = (uint64_t)(collection->a[afte_i])>>32; + + + min_inexactLen = (uint32_t)-1;max_exactLen = 0; + for (k = i; k < afte_i; k++) + { + get_overlapLen((uint64_t)(collection->a[k])>>33, sources, &exactLen, &inexactLen); + if(inexactLen < min_inexactLen) + { + min_inexactLen = inexactLen; + max_exactLen = exactLen; + } + } + + get_overlapLen(pre>>1, sources, &exactLen, &inexactLen); + if((inexactLen > min_inexactLen) || (inexactLen == min_inexactLen && exactLen <= max_exactLen)) + { + pre = (uint64_t)(collection->a[i])>>32; pre_i = i; + continue; + } + + get_overlapLen(afte>>1, sources, &exactLen, &inexactLen); + if((inexactLen > min_inexactLen) || (inexactLen == min_inexactLen && exactLen <= max_exactLen)) + { + pre = (uint64_t)(collection->a[i])>>32; pre_i = i; + continue; + } + + for (k = i; k < afte_i; k++) + { + collection->a[k] = (uint64_t)-1; + skip++; + } + } + + if(skip == 0) return 0; + reduce_ma_utg_t(collection, read_g, sources, coverage_cut, edge, max_hang, min_ovlp, newE); + + return 1; +} + + +uint32_t polish_unitig_scaf(ma_utg_t* in, asg_t* rg, ma_hit_t_alloc* src, ma_sub_t *cov, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* newE) +{ + if(in->m == 0) return 0; + if(in->n < 3) return 0; + uint32_t i, k, v, pre, pre_i, afte, afte_i, exactLen, inexactLen, skip = 0, z, l; + uint32_t min_inexactLen, max_exactLen; + asg_arc_t pE, aE; + + for (z = 1, l = 0; z <= in->n; z++) { + if(z == in->n || IS_SCAF_READ(R_INF, (in->a[z])>>33) ) { + if(z - l >= 3) { + pre = (uint64_t)(in->a[l])>>32; pre_i = l; afte_i = (uint32_t)-1; + for (i = l + 1; i < z - 1; i++) { + if(in->a[i] == (uint64_t)-1) continue; + ///v and after must be available + v = (uint64_t)(in->a[i])>>32; + afte = (uint64_t)(in->a[i+1])>>32; + + get_specific_edge(src, cov, NULL, edge, pre_i == i-1? rg:NULL, max_hang, min_ovlp, v^1, pre^1, &pE); + get_specific_edge(src, cov, NULL, edge, rg, max_hang, min_ovlp, v, afte, &aE); + + if(pE.el == 1 && aE.el == 1) { + pre = (uint64_t)(in->a[i])>>32; pre_i = i; + continue; + } + + ///pre must be a good read, we need to find a good after + ///update a new afte + afte_i = detect_exact_ovec(in, rg, src, cov, edge, max_hang, min_ovlp, pre, i+1); + if(afte_i == (uint32_t)-1) { + pre = (uint64_t)(in->a[i])>>32; pre_i = i; + continue; + } + afte = (uint64_t)(in->a[afte_i])>>32; + + + min_inexactLen = (uint32_t)-1;max_exactLen = 0; + for (k = i; k < afte_i; k++) { + get_overlapLen((uint64_t)(in->a[k])>>33, src, &exactLen, &inexactLen); + if(inexactLen < min_inexactLen) { + min_inexactLen = inexactLen; + max_exactLen = exactLen; + } + } + + get_overlapLen(pre>>1, src, &exactLen, &inexactLen); + if((inexactLen > min_inexactLen) || (inexactLen == min_inexactLen && exactLen <= max_exactLen)) { + pre = (uint64_t)(in->a[i])>>32; pre_i = i; + continue; + } + + get_overlapLen(afte>>1, src, &exactLen, &inexactLen); + if((inexactLen > min_inexactLen) || (inexactLen == min_inexactLen && exactLen <= max_exactLen)) { + pre = (uint64_t)(in->a[i])>>32; pre_i = i; + continue; + } + + for (k = i; k < afte_i; k++) { + in->a[k] = (uint64_t)-1; + skip++; + } + } + } + l = z; + } + } + + if(skip == 0) return 0; + reduce_ma_utg_t_scaf(in, rg, src, cov, edge, max_hang, min_ovlp, newE); + + return 1; +} + + +void print_rough_inconsistent_sites(ma_utg_t* collection, uint32_t cur_i, uint32_t next_i, +asg_t* read_g, All_reads *RNF, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +kvec_asg_arc_t_warp* edge, UC_Read* r_read, UC_Read* q_read, int max_hang, int min_ovlp, +uint32_t c_beg, uint32_t rate_thre, kvec_t_u32_warp* exact_count, kvec_t_u32_warp* total_count, +const char* prefix, int uID, FILE* fp, bed_in* interval) +{ + uint32_t v, w, i, rate; + int v_beg, v_end, v_sub_beg, v_sub_end, w_beg, w_end, w_sub_beg, w_sub_end, i_beg, i_end, j; + asg_arc_t t; + bed_interval* p = NULL; + v = (uint64_t)(collection->a[cur_i])>>32; + ///last element + if(cur_i == collection->n-1 && next_i == collection->n) + { + if(!collection->circ) + { + next_i = (uint32_t)-1; + } + else + { + next_i = 0; + } + } + + + if(next_i != ((uint32_t)-1)) + { + w = (uint64_t)(collection->a[next_i])>>32; + + get_specific_edge(sources, coverage_cut, NULL, edge, read_g, max_hang, min_ovlp, v, w, &t); + v_beg = 0; v_end = asg_arc_len(t) - 1; + if(v&1) + { + v_beg = Get_READ_LENGTH((*RNF), (v>>1)) - v_beg - 1; + v_end = Get_READ_LENGTH((*RNF), (v>>1)) - v_end - 1; + w = v_beg; v_beg = v_end; v_end = w; + } + } + else + { + v_beg = 0; v_end = Get_READ_LENGTH((*RNF), (v>>1)) - 1; + } + + kv_resize(uint32_t, exact_count->a, (uint32_t)(v_end - v_beg + 1)); + memset(exact_count->a.a, 0, (v_end-v_beg+1)*sizeof(uint32_t)); + kv_resize(uint32_t, total_count->a, (uint32_t)(v_end - v_beg + 1)); + memset(total_count->a.a, 0, (v_end-v_beg+1)*sizeof(uint32_t)); + exact_count->a.n = total_count->a.n = (v_end-v_beg+1); + + recover_UC_sub_Read(r_read, v_beg, v_end - v_beg + 1, 0, RNF, v>>1); + ma_hit_t_alloc* x = &(sources[v>>1]); + ma_hit_t *h = NULL; + ///[v_beg, v_end] must be the end of read, which means v_beg = 0 or v_end = Get_READ_LENGTH((*RNF), (v>>1)) - 1 + + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + if(inter_interval(v_beg, v_end, Get_qs((*h)), Get_qe((*h)) - 1, + &v_sub_beg, &v_sub_end) == 0) + { + continue; + } + + if(h->el) + { + for (j = v_sub_beg; j <= v_sub_end; j++) + { + exact_count->a.a[j-v_beg]++; + total_count->a.a[j-v_beg]++; + } + continue; + } + + w_beg = Get_ts((*h)); w_end = Get_te((*h)) - 1; + if(h->rev) + { + w_beg = Get_READ_LENGTH((*RNF), Get_tn((*h))) - w_beg - 1; + w_end = Get_READ_LENGTH((*RNF), Get_tn((*h))) - w_end - 1; + w = w_beg; w_beg = w_end; w_end = w; + } + + + + w_sub_beg = w_beg + (v_sub_beg - Get_qs((*h))); + if(w_sub_beg >= (int)(Get_READ_LENGTH((*RNF), Get_tn((*h))))) + { + w_sub_beg = Get_READ_LENGTH((*RNF), Get_tn((*h))) - 1; + } + + + w_sub_end = w_end - ((int)(Get_qe((*h))) - 1 - v_sub_end); + if(w_sub_end < 0) w_sub_end = 0; + if(w_sub_beg > w_sub_end || (v_sub_end-v_sub_beg) != (w_sub_end-w_sub_beg)) + { + for (j = v_sub_beg; j <= v_sub_end; j++) + { + total_count->a.a[j-v_beg]++; + } + continue; + } + + recover_UC_sub_Read(q_read, w_sub_beg, w_sub_end-w_sub_beg +1, h->rev, RNF, Get_tn((*h))); + if(if_exact_match(r_read->seq, r_read->length, q_read->seq, q_read->length, + v_sub_beg-v_beg, v_sub_end-v_beg, 0, q_read->length-1)) + { + for (j = v_sub_beg; j <= v_sub_end; j++) + { + exact_count->a.a[j-v_beg]++; + total_count->a.a[j-v_beg]++; + } + } + else + { + for (j = v_sub_beg; j <= v_sub_end; j++) + { + total_count->a.a[j-v_beg]++; + } + } + } + + i_beg = i_end = -1; + v = (uint64_t)(collection->a[cur_i])>>32; + uint32_t inexact = 0, total = 0; + for (i = 0; i < total_count->a.n; i++) + { + if(total_count->a.a[i] == 0) + { + rate = 100; + } + else + { + rate = ((total_count->a.a[i] - exact_count->a.a[i])*100)/total_count->a.a[i]; + } + + if(rate >= rate_thre) ///inexact rate + { + ///start a new interval + if(i_beg == -1 && i_end == -1) + { + i_beg = i_end = i; + } + else///extend current interval + { + i_end++; + } + total = total + total_count->a.a[i]; + inexact = inexact + (total_count->a.a[i] - exact_count->a.a[i]); + } + else///end an interval + { + if(i_beg != -1 && i_end != -1) + { + ///i_beg and i_end are the offsets in comparsion to v_beg + v_sub_beg = i_beg + v_beg; + v_sub_end = i_end + v_beg; + if(v&1) + { + i_beg = (v_end - v_beg + 1) - i_beg - 1; + i_end = (v_end - v_beg + 1) - i_end - 1; + w = i_beg; i_beg = i_end; i_end = w; + } + i_end++; + rate = (total == 0)? 100 : (inexact*100)/total; + + if(prefix != NULL && fp != NULL) + { + fprintf(fp,"%s%.6d%c\t%u\t%u\t%u\t", prefix, uID, "lc"[collection->circ], + (uint32_t)(i_beg + c_beg), (uint32_t)(i_end + c_beg), rate); + fprintf(fp,"%.*s", (int)Get_NAME_LENGTH((*RNF), (v>>1)), Get_NAME((*RNF), (v>>1))); + for (j = 0; j < (int)x->length; j++) + { + h = &(x->buffer[j]); + if(inter_interval(v_sub_beg, v_sub_end, Get_qs((*h)), Get_qe((*h)) - 1, + &w_sub_beg, &w_sub_end) == 0) + { + continue; + } + fprintf(fp,",%.*s", (int)Get_NAME_LENGTH((*RNF), Get_tn((*h))), Get_NAME((*RNF), Get_tn((*h)))); + } + fprintf(fp,"\n"); + } + else if(interval != NULL) + { + kv_pushp(bed_interval, *interval, &p); + p->beg = (uint32_t)(i_beg + c_beg); + p->end = (uint32_t)(i_end + c_beg); + } + + } + + i_beg = i_end = -1; + inexact = total = 0; + } + } + + if(i_beg != -1 && i_end != -1) + { + ///i_beg and i_end are the offsets in comparsion to v_beg + v_sub_beg = i_beg + v_beg; + v_sub_end = i_end + v_beg; + if(v&1) + { + i_beg = (v_end - v_beg + 1) - i_beg - 1; + i_end = (v_end - v_beg + 1) - i_end - 1; + w = i_beg; i_beg = i_end; i_end = w; + } + i_end++; + rate = (total == 0)? 100 : (inexact*100)/total; + + if(prefix != NULL && fp != NULL) + { + fprintf(fp,"%s%.6d%c\t%u\t%u\t%u\t", prefix, uID, "lc"[collection->circ], + (uint32_t)(i_beg + c_beg), (uint32_t)(i_end + c_beg), rate); + fprintf(fp,"%.*s", (int)Get_NAME_LENGTH((*RNF), (v>>1)), Get_NAME((*RNF), (v>>1))); + for (j = 0; j < (int)x->length; j++) + { + h = &(x->buffer[j]); + if(inter_interval(v_sub_beg, v_sub_end, Get_qs((*h)), Get_qe((*h)) - 1, + &w_sub_beg, &w_sub_end) == 0) + { + continue; + } + fprintf(fp,",%.*s", (int)Get_NAME_LENGTH((*RNF), Get_tn((*h))), Get_NAME((*RNF), Get_tn((*h)))); + } + fprintf(fp,"\n"); + } + else if(interval != NULL) + { + kv_pushp(bed_interval, *interval, &p); + p->beg = (uint32_t)(i_beg + c_beg); + p->end = (uint32_t)(i_end + c_beg); + } + } + +} + + + +int get_consensus_rate(ma_utg_t* collection, uint32_t cur_i, uint32_t next_i, +asg_t* read_g, All_reads *RNF, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +kvec_asg_arc_t_warp* edge, UC_Read* r_read, UC_Read* q_read, int max_hang, int min_ovlp, +int* r_match, int* r_total) +{ + (*r_match) = (*r_total) = 0; + if(cur_i < 1) return -1; + asg_arc_t *t = NULL, i_t; + uint32_t v, w, k, v_beg, v_end, w_beg, w_end; + int j; + if(collection->a[cur_i] == (uint64_t)-1 || collection->a[next_i] == (uint64_t)-1) return 0; + + v = (uint64_t)(collection->a[cur_i])>>32; + w = (uint64_t)(collection->a[next_i])>>32; + + if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, v, w, &i_t) == 0) + { + for (k = 0; k < edge->a.n; k++) + { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) + { + t = &(edge->a.a[k]); + break; + } + } + } + else + { + t = &i_t; + } + + if(t == NULL) return -1; + v_beg = 0; v_end = asg_arc_len(*t) - 1; r_read->length = 0; + ///cur_i must >= 1 + for (j = cur_i-1; j >= 0; j--) + { + if(collection->a[j] == (uint64_t)-1) continue; + + w = (uint64_t)(collection->a[j])>>32; + t = NULL; + + if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, w, v, &i_t) == 0) + { + for (k = 0; k < edge->a.n; k++) + { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == w && edge->a.a[k].v == v) + { + t = &(edge->a.a[k]); + break; + } + } + } + else + { + t = &i_t; + } + + if(t == NULL) break; + + w_beg = asg_arc_len(*t); + w_end = MIN(((int)(w_beg + v_end)), ((int)(read_g->seq[w>>1].len-1))); + // if(t->el == 1) + // { + // if(r_read->length == 0) recover_UC_sub_Read(r_read, v_beg, v_end - v_beg + 1, v&1, RNF, v>>1); + // ///for debug: check if v[v_beg, v_end] == w[w_beg, w_end] + // recover_UC_sub_Read(q_read, w_beg, w_end - w_beg +1, w&1, RNF, w>>1); + // ///q_read->length<=r_read->length + // if(if_exact_match(r_read->seq, r_read->length, q_read->seq, q_read->length, + // 0, q_read->length-1, 0, q_read->length-1) == 0) + // { + // fprintf(stderr, "ERROR: cur_i: %u, j: %d, r_len: %lld, q_len: %lld\n", cur_i, j, r_read->length, q_read->length); + // } + // } + + //filter overlaps which cannot cover the whole [v_beg, v_end] + if(w_end - w_beg != v_end - v_beg) break; + + (*r_total)++; + + if(t->el == 1) + { + (*r_match)++; + } + else + { + if(r_read->length == 0) recover_UC_sub_Read(r_read, v_beg, v_end - v_beg + 1, v&1, RNF, v>>1); + recover_UC_sub_Read(q_read, w_beg, w_end - w_beg +1, w&1, RNF, w>>1); + ///q_read->length<=r_read->length + if(if_exact_match(r_read->seq, r_read->length, q_read->seq, q_read->length, + 0, q_read->length-1, 0, q_read->length-1) == 1) + { + (*r_match)++; + } + } + } + + + return 1; +} + +uint32_t polish_unitig_advance(ma_utg_t* collection, asg_t* read_g, All_reads *RNF, +ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, kvec_asg_arc_t_warp* edge, +UC_Read* r_read, UC_Read* q_read, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* newE) +{ + if(collection->m == 0) return 0; + if(collection->n < 3) return 0; + uint32_t i, skip = 0; + int match_v, total_v, max_i, match_max, k; + double match_rate, match_rate_max; + + ///we should be able to handle i = collection->n-1 + for (i = 1; i < collection->n-1; i++) + { + ///in practice, collection->a[i] and collection->a[i+1] must be available + ///collection->a[index] might be unavailable only if index < i + if(get_consensus_rate(collection, i, i+1, read_g, RNF, sources, coverage_cut, + edge, r_read, q_read, max_hang, min_ovlp, &match_v, &total_v) != 1) + { + continue; + } + + match_rate = (total_v == 0)? 0:((double)(match_v)/(double)(total_v)); + ///most reads support collection[i], so it is right + if(match_v >= total_v * 0.5 && total_v > 0 && match_v > 0) continue; + + max_i = i; match_max = match_v; match_rate_max = match_rate; + for (k = i - 1; k >= 0; k--) + { + if(collection->a[k] == (uint64_t)-1) continue; + ///collection->a[k] might be unavailable, while collection->a[i+1] must be available + ///return -1 means there is no overlap from k to i+1 + if(get_consensus_rate(collection, k, i+1, read_g, RNF, sources, coverage_cut, + edge, r_read, q_read, max_hang, min_ovlp, &match_v, &total_v) < 0) + { + break; + } + + ///no read support k to i+1 + if(total_v == 0) break; + + match_rate = (total_v == 0)? 0:((double)(match_v)/(double)(total_v)); + if(match_rate > match_rate_max || (match_rate == match_rate_max && match_v > match_max)) + { + max_i = k; match_max = match_v; match_rate_max = match_rate; + } + } + + ///set [max_i+1, i] to be unavailable + for (k = max_i+1; k <= (int)i; k++) + { + if(collection->a[k] == (uint64_t)-1) continue; + collection->a[k] = (uint64_t)-1; + skip++; + } + } + + if(skip == 0) return 1; + + reduce_ma_utg_t(collection, read_g, sources, coverage_cut, edge, max_hang, min_ovlp, newE); + + return 1; +} + + +uint32_t polish_unitig_advance_scaf(ma_utg_t* in, asg_t* rg, All_reads *RNF, ma_hit_t_alloc* src, ma_sub_t *cov, kvec_asg_arc_t_warp* edge, +UC_Read* r_read, UC_Read* q_read, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* newE) +{ + if(in->m == 0) return 0; + if(in->n < 3) return 0; + // uint32_t i, skip = 0; + int match_v, total_v, max_i, match_max, k, z, l, in_n = in->n, i, skip = 0; + double match_rate, match_rate_max; + + + for (z = 1, l = 0; z <= in_n; z++) { + if(z == in_n || IS_SCAF_READ(R_INF, (in->a[z])>>33) ) { + if(z - l >= 3) { + ///we should be able to handle i = z-1 + for (i = l + 1; i < z - 1; i++) { + ///in practice, in->a[i] and in->a[i+1] must be available + ///in->a[index] might be unavailable only if index < i + if(get_consensus_rate(in, i, i+1, rg, RNF, src, cov, edge, r_read, q_read, max_hang, min_ovlp, &match_v, &total_v) != 1) { + continue; + } + + match_rate = (total_v == 0)? 0:((double)(match_v)/(double)(total_v)); + ///most reads support in[i], so it is right + if(match_v >= total_v * 0.5 && total_v > 0 && match_v > 0) continue; + + max_i = i; match_max = match_v; match_rate_max = match_rate; + for (k = i - 1; k >= 0; k--) { + if(in->a[k] == (uint64_t)-1) continue; + ///in->a[k] might be unavailable, while in->a[i+1] must be available + ///return -1 means there is no overlap from k to i+1 + if(get_consensus_rate(in, k, i+1, rg, RNF, src, cov, edge, r_read, q_read, max_hang, min_ovlp, &match_v, &total_v) < 0) { + break; + } + + ///no read support k to i+1 + if(total_v == 0) break; + + match_rate = (total_v == 0)? 0:((double)(match_v)/(double)(total_v)); + if(match_rate > match_rate_max || (match_rate == match_rate_max && match_v > match_max)) { + max_i = k; match_max = match_v; match_rate_max = match_rate; + } + } + + ///set [max_i+1, i] to be unavailable + for (k = max_i+1; k <= (int)i; k++) { + if(in->a[k] == (uint64_t)-1) continue; + in->a[k] = (uint64_t)-1; + skip++; + } + } + } + l = z; + } + } + + if(skip == 0) return 1; + + reduce_ma_utg_t_scaf(in, rg, src, cov, edge, max_hang, min_ovlp, newE); + + return 1; +} + + +ma_ug_t *gen_polished_ug(const ug_opt_t *uopt, asg_t *sg) +{ + kvec_asg_arc_t_warp e, d; + uint32_t i; ma_utg_t *u; + kv_init(e.a); kv_init(d.a); + ma_ug_t *ug = ma_ug_gen(sg); + UC_Read g_read, tmp; + init_UC_Read(&g_read); init_UC_Read(&tmp); + + for (i = e.a.n = d.a.n = 0; i < ug->u.n; ++i) { + u = &ug->u.a[i]; + if(u->m == 0) continue; + polish_unitig(u, sg, uopt->sources, uopt->coverage_cut, &e, uopt->max_hang, uopt->min_ovlp, &d); + polish_unitig_advance(u, sg, &R_INF, uopt->sources, uopt->coverage_cut, &e, &g_read, &tmp, uopt->max_hang, uopt->min_ovlp, &d); + ug->g->seq[i].len = u->len; + } + + destory_UC_Read(&g_read); destory_UC_Read(&tmp); + + uint32_t n_vtx = ug->g->n_seq*2, v, nv, vLen = 0; + asg_arc_t* av = NULL; + for (v = 0; v < n_vtx; ++v) { + if (ug->g->seq[v>>1].del) continue; + av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + vLen = ug->g->seq[(av[i].ul>>33)].len - av[i].ol; + av[i].ul = (av[i].ul>>32)<<32; + av[i].ul = av[i].ul | vLen; + } + } + + // if(d.a.n > 0) { + // for (k = 0; k < d.a.n; k++) { + // p = asg_arc_pushp(sg); + // *p = d.a.a[k]; + // } + // free(sg->idx); sg->idx = 0; sg->is_srt = 0; + // asg_cleanup(sg); + // } + + kv_destroy(e.a); kv_destroy(d.a); + return ug; +} + + +// generate unitig sequences +int ma_ug_seq(ma_ug_t *g, asg_t *read_g, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, +kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, kvec_asg_arc_t_warp *E, uint32_t is_polish) +{ + UC_Read g_read; + init_UC_Read(&g_read); + UC_Read tmp; + init_UC_Read(&tmp); + ///utg_intv_t *tmp; + uint32_t i, j, k; + uint32_t rId, /**uId,**/ori, start, eLen, readLen; + char* readS = NULL; + + ///why we need n_read here? it is just beacuse one read can only be included in one untig + ///but it is not true + ///tmp = (utg_intv_t*)calloc(n_read, sizeof(utg_intv_t)); + ///number of unitigs + for (i = 0; i < g->u.n; ++i) { + ma_utg_t *u = &g->u.a[i]; + if(u->m == 0) continue; + if(is_polish) { + polish_unitig_scaf(u, read_g, sources, coverage_cut, edge, max_hang, min_ovlp, E); + polish_unitig_advance_scaf(u, read_g, &R_INF, sources, coverage_cut, edge, &g_read, &tmp, max_hang, min_ovlp, E); + } + + g->g->seq[i].len = u->len; + + uint32_t l = 0; + u->s = (char*)calloc(1, u->len + 1); + memset(u->s, 'N', u->len); + for (j = 0; j < u->n; ++j) { + rId = u->a[j]>>33; + ///uId = i; + ori = u->a[j]>>32&1; + start = l; + eLen = (uint32_t)u->a[j]; + l += eLen; + + if(eLen == 0) continue; + if(rId < read_g->r_seq) { + recover_UC_Read(&g_read, &R_INF, rId); + } else { + recover_fake_read(&g_read, &tmp, &(read_g->F_seq[rId-read_g->r_seq]), + &R_INF, coverage_cut); + } + + readS = g_read.seq + coverage_cut[rId].s; + readLen = coverage_cut[rId].e - coverage_cut[rId].s; + + if (!ori) {// forward strand + for (k = 0; k < eLen; k++) { + u->s[start + k] = readS[k]; + } + } else { + for (k = 0; k < eLen; k++) { + uint8_t c = (uint8_t)readS[readLen - 1 - k]; + u->s[start + k] = c >= 128? 'N' : comp_tab[c]; + } + } + } + } + + destory_UC_Read(&g_read); + destory_UC_Read(&tmp); + + + uint32_t n_vtx = g->g->n_seq * 2, v, nv; + uint32_t vLen = 0; + asg_arc_t* av = NULL; + for (v = 0; v < n_vtx; ++v) + { + if (g->g->seq[v>>1].del) continue; + av = asg_arc_a(g->g, v); + nv = asg_arc_n(g->g, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + vLen = g->g->seq[(av[i].ul>>33)].len - av[i].ol; + av[i].ul = (av[i].ul>>32)<<32; + av[i].ul = av[i].ul | vLen; + } + } + + if(E && E->a.n > 0) + { + asg_arc_t* p = NULL; + for (k = 0; k < E->a.n; k++) + { + p = asg_arc_pushp(read_g); + *p = E->a.a[k]; + } + + free(read_g->idx); + read_g->idx = 0; + read_g->is_srt = 0; + asg_cleanup(read_g); + } + return 0; +} + + +void polish_unitig_scaffold(uint32_t uid, ma_utg_t* collection, asg_t* read_g, All_reads *RNF, +ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, kvec_asg_arc_t_warp* edge, +UC_Read* r_read, UC_Read* q_read, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* newE) +{ + uint32_t i, k, m, len, p_idx; + ma_utg_t qu; + for (i = p_idx = m = len = 0; i < collection->n; i++) + { + if(collection->a[i] == (uint64_t)-1) + { + qu.a = collection->a + p_idx; + qu.circ = 0; + qu.m = qu.n = i - p_idx; + for (k = qu.len = 0; k < qu.n; k++) + { + qu.len += (uint32_t)qu.a[k]; + } + + polish_unitig(&qu, read_g, sources, coverage_cut, edge, max_hang, min_ovlp, newE); + polish_unitig_advance(&qu, read_g, &R_INF, sources, coverage_cut, edge, r_read, q_read, max_hang, min_ovlp, newE); + + for (k = 0; k < qu.n; k++) + { + collection->a[m] = qu.a[k]; + m++; + } + len += qu.len; + + collection->a[m] = (uint64_t)-1; + m++; + len += GAP_LEN; + p_idx = i + 1; + } + } + + if(i - p_idx > 0) + { + qu.a = collection->a + p_idx; + qu.circ = collection->circ; + qu.m = qu.n = i - p_idx; + for (k = qu.len = 0; k < qu.n; k++) + { + qu.len += (uint32_t)qu.a[k]; + } + + polish_unitig(&qu, read_g, sources, coverage_cut, edge, max_hang, min_ovlp, newE); + polish_unitig_advance(&qu, read_g, &R_INF, sources, coverage_cut, edge, r_read, q_read, max_hang, min_ovlp, newE); + + for (k = 0; k < qu.n; k++) + { + collection->a[m] = qu.a[k]; + m++; + } + len += qu.len; + } + collection->n = m; + collection->len = len; +} + +int ma_ug_seq_scaffold(ma_ug_t *g, asg_t *read_g, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, +kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, kvec_asg_arc_t_warp *E, uint32_t is_polish) +{ + UC_Read g_read; + init_UC_Read(&g_read); + UC_Read tmp; + init_UC_Read(&tmp); + ///utg_intv_t *tmp; + uint32_t i, j, k; + uint32_t rId, /**uId,**/ori, start, eLen, readLen; + char* readS = NULL; + if(!(g->g)) + { + g->g = asg_init(); + for (i = 0; i < g->u.n; ++i) + { + asg_seq_set(g->g, i, g->u.a[i].len, 0); + } + asg_cleanup(g->g); + g->g->r_seq = g->g->n_seq; + } + + ///why we need n_read here? it is just beacuse one read can only be included in one untig + ///but it is not true + ///tmp = (utg_intv_t*)calloc(n_read, sizeof(utg_intv_t)); + ///number of unitigs + for (i = 0; i < g->u.n; ++i) { + ma_utg_t *u = &g->u.a[i]; + if(u->m == 0) continue; + if(is_polish) polish_unitig_scaffold(i, u, read_g, &R_INF, sources, coverage_cut, edge, &g_read, &tmp, max_hang, min_ovlp, E); + g->g->seq[i].len = u->len; + + uint32_t l = 0; + u->s = (char*)calloc(1, u->len + 1); + memset(u->s, 'N', u->len); + for (j = 0; j < u->n; ++j) { + // fprintf(stderr, "j=%u, u->a[j]: %lu\n", j, u->a[j]); + if(u->a[j] == (uint64_t)-1) + { + l += GAP_LEN; + continue; + } + rId = u->a[j]>>33; + ///uId = i; + ori = u->a[j]>>32&1; + start = l; + eLen = (uint32_t)u->a[j]; + l += eLen; + + if(eLen == 0) continue; + if(rId < read_g->r_seq) + { + recover_UC_Read(&g_read, &R_INF, rId); + } + else + { + recover_fake_read(&g_read, &tmp, &(read_g->F_seq[rId-read_g->r_seq]), + &R_INF, coverage_cut); + } + + readS = g_read.seq + coverage_cut[rId].s; + readLen = coverage_cut[rId].e - coverage_cut[rId].s; + + if (!ori) // forward strand + { + for (k = 0; k < eLen; k++) + { + u->s[start + k] = readS[k]; + } + } + else + { + for (k = 0; k < eLen; k++) + { + uint8_t c = (uint8_t)readS[readLen - 1 - k]; + u->s[start + k] = c >= 128? 'N' : comp_tab[c]; + } + } + } + } + + destory_UC_Read(&g_read); + destory_UC_Read(&tmp); + + + uint32_t n_vtx = g->g->n_seq * 2, v, nv; + uint32_t vLen = 0; + asg_arc_t* av = NULL; + for (v = 0; v < n_vtx; ++v) + { + if (g->g->seq[v>>1].del) continue; + av = asg_arc_a(g->g, v); + nv = asg_arc_n(g->g, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + vLen = g->g->seq[(av[i].ul>>33)].len - av[i].ol; + av[i].ul = (av[i].ul>>32)<<32; + av[i].ul = av[i].ul | vLen; + } + } + + if(E && E->a.n > 0) + { + asg_arc_t* p = NULL; + for (k = 0; k < E->a.n; k++) + { + p = asg_arc_pushp(read_g); + *p = E->a.a[k]; + } + + free(read_g->idx); + read_g->idx = 0; + read_g->is_srt = 0; + asg_cleanup(read_g); + } + return 0; +} +uint32_t get_ug_coverage(ma_utg_t* u, asg_t* read_g, const ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag, uint64_t *rR, uint64_t *rC) +{ + uint32_t k, j, rId, tn, is_Unitig; + long long R_bases = 0, C_bases = 0; + ma_hit_t *h; + if(rR) {(*rR) = 0;} if(rC) {(*rC) = 0;} + if(u->m == 0) return 0; + + for (k = 0; k < u->n; k++) + { + if(u->a[k] == (uint64_t)-1) continue; + rId = u->a[k]>>33; + r_flag[rId] = 1; + } + + for (k = 0; k < u->n; k++) + { + if(u->a[k] == (uint64_t)-1) continue; + rId = u->a[k]>>33; + R_bases += (coverage_cut[rId].e - coverage_cut[rId].s); + for (j = 0; j < (uint64_t)(sources[rId].length); j++) + { + h = &(sources[rId].buffer[j]); + if(h->el != 1) continue; + tn = Get_tn((*h)); + if(read_g->seq[tn].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + if(read_g->seq[tn].del == 1) continue; + if(r_flag[tn] != 1) continue; + C_bases += (Get_qe((*h)) - Get_qs((*h))); + } + } + + + for (k = 0; k < u->n; k++) + { + if(u->a[k] == (uint64_t)-1) continue; + rId = u->a[k]>>33; + r_flag[rId] = 0; + } + + if(rR) {(*rR) = R_bases;} if(rC) {(*rC) = C_bases;} + return R_bases == 0? 0:C_bases/R_bases; +} + +uint32_t get_ug_coverage_aggressive(ma_ug_t *ug, uint32_t uID, asg_t* read_g, +const ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag, +uint64_t *n_utg) +{ + ma_utg_t* u = &(ug->u.a[uID]); + uint32_t k, j, rId, tn, is_Unitig; + long long R_bases = 0, C_bases = 0; + ma_hit_t *h; + if(u->m == 0) return 0; + + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 1; + } + + (*n_utg) = u->n; + uint32_t nv, i; + asg_arc_t *av = NULL; + for (i = 0; i < 2; i++) + { + nv = asg_arc_n(ug->g, (uID<<1)+i); + av = asg_arc_a(ug->g, (uID<<1)+i); + for (j = 0; j < nv; j++) + { + u = &(ug->u.a[av[j].v>>1]); + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 2; + } + } + } + + + u = &(ug->u.a[uID]); + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + R_bases += (coverage_cut[rId].e - coverage_cut[rId].s); + for (j = 0; j < (uint64_t)(sources[rId].length); j++) + { + h = &(sources[rId].buffer[j]); + if(h->el != 1) continue; + tn = Get_tn((*h)); + if(read_g->seq[tn].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + if(read_g->seq[tn].del == 1) continue; + if(r_flag[tn] == 0) continue; + if(r_flag[tn] == 2) + { + (*n_utg)++; + r_flag[tn] = 3; + } + C_bases += (Get_qe((*h)) - Get_qs((*h))); + ///if(uID == 35701) fprintf(stderr, "flag: %u, coverage: %d\n", r_flag[tn], (int)(Get_qe((*h)) - Get_qs((*h)))); + } + } + + + + + + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 0; + } + + for (i = 0; i < 2; i++) + { + nv = asg_arc_n(ug->g, (uID<<1)+i); + av = asg_arc_a(ug->g, (uID<<1)+i); + for (j = 0; j < nv; j++) + { + u = &(ug->u.a[av[j].v>>1]); + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 0; + } + } + } + + ///if(uID == 35701) fprintf(stderr, "C_bases: %lld, R_bases: %lld, (*n_utg): %lu\n", C_bases, R_bases, (*n_utg)); + return C_bases/R_bases; +} + +uint32_t cal_circle_ov(const ma_ug_t *ug, uint32_t uid, uint32_t rev, asg_t *sg) +{ + uint32_t v, w, vx, wx, k; + v = w = (uid<<1)+(!!rev); + 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)); + v = vx; w = wx; + + if(sg) { + asg_arc_t *av; uint32_t nv; + av = asg_arc_a(sg, vx); nv = asg_arc_n(sg, vx); + for (k = 0; k < nv; k++) { + if(av[k].v == wx) return av[k].ol; + } + } + return 0; +} + +void ma_ug_print2(const ma_ug_t *ug, All_reads *RNF, asg_t* read_g, const ma_sub_t *coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex, int print_seq, const char* prefix, FILE *fp) +{ + uint8_t* primary_flag = read_g?(uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)):NULL; + uint32_t i, j, l, pc = read_g && coverage_cut && sources && ruIndex?1:0, co; + char name[32]; + for (i = 0; i < ug->u.n; ++i) { // the Segment lines in GFA + ma_utg_t *p = &ug->u.a[i]; + if(p->m == 0) continue; + sprintf(name, "%s%.6d%c", prefix, i + 1, "lc"[p->circ]); + if (print_seq) fprintf(fp, "S\t%s\t%s\tLN:i:%d\trd:i:%u\n", name, p->s? p->s : "*", p->len, + pc?get_ug_coverage(p, read_g, coverage_cut, sources, ruIndex, primary_flag, NULL, NULL):0); + else fprintf(fp, "S\t%s\t*\tLN:i:%d\trd:i:%u\n", name, p->len, + pc?get_ug_coverage(p, read_g, coverage_cut, sources, ruIndex, primary_flag, NULL, NULL):0); + + for (j = l = 0; j < p->n; j++) { + if(p->a[j] != (uint64_t)-1) + { + uint32_t x = p->a[j]>>33; + if(xtotal_reads) + { + + fprintf(fp, "A\t%s\t%d\t%c\t%.*s\t%d\t%d\tid:i:%d\tHG:A:%c\n", name, l, "+-"[p->a[j]>>32&1], + (int)Get_NAME_LENGTH((*RNF), x), Get_NAME((*RNF), x), + coverage_cut?coverage_cut[x].s:0, coverage_cut?coverage_cut[x].e:(int)Get_READ_LENGTH((*RNF), x), x, + "apmaaa"[((RNF->trio_flag[x]!=FATHER && RNF->trio_flag[x]!=MOTHER)?AMBIGU:RNF->trio_flag[x])]); + } + else + { + fprintf(fp, "A\t%s\t%d\t%c\t%s\t%d\t%d\tid:i:%d\tHG:A:%c\n", name, l, "+-"[p->a[j]>>32&1], + "FAKE", coverage_cut?coverage_cut[x].s:0, coverage_cut?coverage_cut[x].e:(int)Get_READ_LENGTH((*RNF), x), x, '*'); + } + } + else + { + fprintf(fp, "A\t%s\t%d\t*\t*\t*\t*\tid:i:*\tHG:A:*\n", name, l); + } + l += (uint32_t)p->a[j]; + } + } + // for (i = 0; i < ug->g->n_arc; ++i) { // the Link lines in GFA + // uint32_t u = ug->g->arc[i].ul>>32, v = ug->g->arc[i].v; + // fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", + // prefix, (u>>1)+1, "lc"[ug->u.a[u>>1].circ], "+-"[u&1], + // prefix, (v>>1)+1, "lc"[ug->u.a[v>>1].circ], "+-"[v&1], ug->g->arc[i].ol, asg_arc_len(ug->g->arc[i])); + // } + if(ug->g) + { + asg_arc_t* au = NULL; + uint32_t nu, u, v; + for (i = 0; i < ug->u.n; ++i) { + if(ug->u.a[i].m == 0) continue; + if(ug->u.a[i].circ) { + co = cal_circle_ov(ug, i, 0, read_g); + fprintf(fp, "L\t%s%.6dc\t+\t%s%.6dc\t+\t%dM\tL1:i:%d\tL2:i:%u\n", + prefix, i+1, prefix, i+1, co, ((ug->u.a[i].len>=co)?(ug->u.a[i].len-co):0), 0); + co = cal_circle_ov(ug, i, 1, read_g); + fprintf(fp, "L\t%s%.6dc\t-\t%s%.6dc\t-\t%dM\tL1:i:%d\tL2:i:%u\n", + prefix, i+1, prefix, i+1, co, ((ug->u.a[i].len>=co)?(ug->u.a[i].len-co):0), 0); + } else { + u = i<<1; + au = asg_arc_a(ug->g, u); + nu = asg_arc_n(ug->g, u); + for (j = 0; j < nu; j++) + { + if(au[j].del) continue; + v = au[j].v; + fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", + prefix, (u>>1)+1, "lc"[ug->u.a[u>>1].circ], "+-"[u&1], + prefix, (v>>1)+1, "lc"[ug->u.a[v>>1].circ], "+-"[v&1], au[j].ol, asg_arc_len(au[j]), 0/**au[j].ou**/); + } + + + u = (i<<1) + 1; + au = asg_arc_a(ug->g, u); + nu = asg_arc_n(ug->g, u); + for (j = 0; j < nu; j++) + { + if(au[j].del) continue; + v = au[j].v; + fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", + prefix, (u>>1)+1, "lc"[ug->u.a[u>>1].circ], "+-"[u&1], + prefix, (v>>1)+1, "lc"[ug->u.a[v>>1].circ], "+-"[v&1], au[j].ol, asg_arc_len(au[j]), 0/**au[j].ou**/); + } + } + } + } + free(primary_flag); +} + +void ma_ug_print(const ma_ug_t *ug, asg_t* read_g, const ma_sub_t *coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex, const char* prefix, FILE *fp) +{ + ma_ug_print2(ug, &R_INF, read_g, coverage_cut, sources, ruIndex, 1, prefix, fp); +} + +void prt_scaf_stats(sec_t *scp, ma_ug_t *ctg, const char* prefix, uint64_t id) +{ + uint64_t k, tl0, tl1; ma_utg_t *z = NULL; char name[32]; + for (k = tl0 = tl1 = 0; k < scp->n; k++) { + z = &(ctg->u.a[((uint32_t)scp->a[k])>>1]); tl0 += z->len; tl1 += (scp->a[k]>>32); + } + sprintf(name, "%s%.6lu%c", prefix, id + 1, "lc"[scp->is_c]); + + fprintf(stderr, "[M::%s] [M::%s] tot::%lu\tel::%lu\tnl::%lu\tis_c::%lu\t#::%lu\t%s\n", __func__, name, tl0+tl1, tl0, tl1, scp->is_c, (uint64_t)scp->n, ((scp->n>1)?"scf":"ctg")); + for (k = 0; k < scp->n; k++) { + z = &(ctg->u.a[((uint32_t)scp->a[k])>>1]); + fprintf(stderr, "%s%.6u%c(%c)\tlen::%u\tNs::%lu\n", + prefix, (((uint32_t)scp->a[k])>>1)+1, "lc"[z->circ], "+-"[(((uint32_t)scp->a[k])&1)], z->len, (scp->a[k]>>32)); + } + +} + +void ma_scg_print(const kvect_sec_t *sc, All_reads *RNF, asg_t* read_g, const ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, int print_seq, const char* prefix, FILE *fp) +{ + uint8_t* primary_flag = read_g?(uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)):NULL; + uint64_t i, j, l, pc = read_g && coverage_cut && sources && ruIndex?1:0, tl, m, x; sec_t *scp; + char name[32]; uint64_t Rb, Cb, tRb, tCb, Cov; ma_utg_t *z = NULL; uint8_t c; + for (i = 0; i < sc->n; ++i) { // the Segment lines in GFA + scp = &(sc->a[i]); + ///debug + // prt_scaf_stats(scp, sc->ctg, prefix, i); + + for (j = tl = tRb = tCb = 0; j < scp->n; j++) { + z = &(sc->ctg->u.a[((uint32_t)scp->a[j])>>1]); tl += z->len; tl += (scp->a[j]>>32); + if(pc) { + get_ug_coverage(z, read_g, coverage_cut, sources, ruIndex, primary_flag, &Rb, &Cb); tRb += Rb; tCb += Cb; + } + } + sprintf(name, "%s%.6lu%c", prefix, i + 1, "lc"[scp->is_c]); Cov = ((tRb==0)?(0):(tCb/tRb)); + + if (!print_seq) { + fprintf(fp, "S\t%s\t*\tLN:i:%lu\trd:i:%lu\n", name, tl, Cov); + } else { + fprintf(fp, "S\t%s\t", name); + for (j = 0; j < scp->n; j++) { + z = &(sc->ctg->u.a[((uint32_t)scp->a[j])>>1]); + if(!(((uint32_t)scp->a[j])&1)) { + fprintf(fp, "%s", z->s); + } else { + for(l = 0; l < z->len; l++) { + c = (uint8_t)(z->s[z->len-1-l]); + fprintf(fp, "%c", ((c>=128)?'N':comp_tab[c])); + } + } + for(l = 0; l < (scp->a[j]>>32); l++) fprintf(fp, "N"); + } + fprintf(fp, "\tLN:i:%lu\trd:i:%lu\n", tl, Cov); + } + + + for (j = tl = 0; j < scp->n; j++) { + z = &(sc->ctg->u.a[((uint32_t)scp->a[j])>>1]); l = tl; + if(!(((uint32_t)scp->a[j])&1)) { + for (m = 0; m < z->n; m++) { + x = z->a[m]>>33; + if(xtotal_reads) { + fprintf(fp, "A\t%s\t%lu\t%c\t%.*s\t%d\t%d\tid:i:%lu\tHG:A:%c\n", name, l, "+-"[(z->a[m]>>32)&1], + (int)Get_NAME_LENGTH((*RNF), x), Get_NAME((*RNF), x), + coverage_cut?coverage_cut[x].s:0, coverage_cut?coverage_cut[x].e:(int)Get_READ_LENGTH((*RNF), x), x, + "apmaaa"[((RNF->trio_flag[x]!=FATHER && RNF->trio_flag[x]!=MOTHER)?AMBIGU:RNF->trio_flag[x])]); + } else { + fprintf(fp, "A\t%s\t%lu\t%c\t%s\t%d\t%d\tid:i:%lu\tHG:A:%c\n", name, l, "+-"[(z->a[m]>>32)&1], + "FAKE", coverage_cut?coverage_cut[x].s:0, coverage_cut?coverage_cut[x].e:(int)Get_READ_LENGTH((*RNF), x), x, '*'); + } + l += (uint32_t)(z->a[m]); + } + } else { + for (m = 0; m < z->n; m++) { + x = z->a[z->n-m-1]>>33; + if(xtotal_reads) { + fprintf(fp, "A\t%s\t%lu\t%c\t%.*s\t%d\t%d\tid:i:%lu\tHG:A:%c\n", name, l, "+-"[((z->a[z->n-m-1]>>32)&1)^1], + (int)Get_NAME_LENGTH((*RNF), x), Get_NAME((*RNF), x), + coverage_cut?coverage_cut[x].s:0, coverage_cut?coverage_cut[x].e:(int)Get_READ_LENGTH((*RNF), x), x, + "apmaaa"[((RNF->trio_flag[x]!=FATHER && RNF->trio_flag[x]!=MOTHER)?AMBIGU:RNF->trio_flag[x])]); + } else { + fprintf(fp, "A\t%s\t%lu\t%c\t%s\t%d\t%d\tid:i:%lu\tHG:A:%c\n", name, l, "+-"[((z->a[z->n-m-1]>>32)&1)^1], + "FAKE", coverage_cut?coverage_cut[x].s:0, coverage_cut?coverage_cut[x].e:(int)Get_READ_LENGTH((*RNF), x), x, '*'); + } + l += (uint32_t)(z->a[z->n-m-1]); + } + } + tl = l; + + if((scp->a[j]>>32) > 0) fprintf(fp, "A\t%s\t%lu\t+\tNs\t0\t%lu\tid:i:-1\tHG:A:a\n", name, l, (scp->a[j]>>32)); + + tl += (scp->a[j]>>32); + } + } + free(primary_flag); +} + +void ma_scg_gpath_print(const kvect_sec_t *sc, const char* prefix, scaf_res_t *gpt, ma_ug_t *gpt_u, FILE *fp) +{ + uc_block_t *a; uint64_t i, j, k, zk, tl, scl, a_n; sec_t *scp; ul_vec_t *idx; + char name[32]; ma_utg_t *z = NULL; + for (i = 0; i < sc->n; ++i) { // the Segment lines in GFA + scp = &(sc->a[i]); + ///debug + // prt_scaf_stats(scp, sc->ctg, prefix, i); + sprintf(name, "%s%.6lu%c", prefix, i + 1, "lc"[scp->is_c]); + for (j = scl = 0; j < scp->n; j++) { + z = &(sc->ctg->u.a[((uint32_t)scp->a[j])>>1]); + scl += z->len; scl += (scp->a[j]>>32); + } + + for (j = tl = 0; j < scp->n; j++) { + z = &(sc->ctg->u.a[((uint32_t)scp->a[j])>>1]); ///each contig + idx = &(gpt->a[((uint32_t)scp->a[j])>>1]); ///alignment path + if(!(((uint32_t)scp->a[j])&1)) {///forward + for (k = 0; k < idx->bb.n; k++) { + a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; + for (zk = 0; zk < a_n; zk++) {///alignment + fprintf(fp, "%s\t%lu\t%lu\t%lu\t%c\tutg%.6u%c\t%u\t%u\t%u\n", name, scl, tl + a[zk].qs, tl + a[zk].qe, "+-"[a[zk].rev], + (a[zk].hid)+1, "lc"[gpt_u->u.a[a[zk].hid].circ], gpt_u->u.a[a[zk].hid].len, a[zk].ts, a[zk].te); + } + } + } else {///revrse + for (k = 0; k < idx->bb.n; k++) { + a = idx->bb.a + idx->bb.a[idx->bb.n-k-1].ts; a_n = idx->bb.a[idx->bb.n-k-1].te - idx->bb.a[idx->bb.n-k-1].ts; + for (zk = 0; zk < a_n; zk++) { + fprintf(fp, "%s\t%lu\t%lu\t%lu\t%c\tutg%.6u%c\t%u\t%u\t%u\n", name, scl, tl + z->len - a[a_n-zk-1].qe, tl + z->len - a[a_n-zk-1].qs, "+-"[a[a_n-zk-1].rev^1], + (a[a_n-zk-1].hid)+1, "lc"[gpt_u->u.a[a[a_n-zk-1].hid].circ], gpt_u->u.a[a[a_n-zk-1].hid].len, a[a_n-zk-1].ts, a[a_n-zk-1].te); + } + } + } + tl += z->len; tl += (scp->a[j]>>32); + } + } +} + +void ma_ug_gpath_print(const char* prefix, scaf_res_t *gpt, ma_ug_t *ctg_u, ma_ug_t *ref_u, FILE *fp) +{ + uc_block_t *a; uint64_t i, k, zk, a_n; ul_vec_t *idx; + char name[32]; ma_utg_t *z = NULL; + for (i = 0; i < ctg_u->u.n; ++i) { // the Segment lines in GFA + ///debug + // prt_scaf_stats(scp, sc->ctg, prefix, i); + z = &(ctg_u->u.a[i]); idx = &(gpt->a[i]); ///alignment path + sprintf(name, "%s%.6lu%c", prefix, i + 1, "lc"[z->circ]); + for (k = 0; k < idx->bb.n; k++) { + a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; + for (zk = 0; zk < a_n; zk++) {///alignment + fprintf(fp, "%s\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", name, z->len, a[zk].qs, a[zk].qe, "+-"[a[zk].rev], + (a[zk].hid)+1, "lc"[ref_u->u.a[a[zk].hid].circ], ref_u->u.a[a[zk].hid].len, a[zk].ts, a[zk].te); + } + } + } +} + +int asg_cut_internal(asg_t *g, int max_ext) +{ + asg64_v a = {0,0,0}; + uint32_t n_vtx = g->n_seq * 2, v, i, cnt = 0; + for (v = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + if (asg_is_utg_end(g, v, 0) != ASG_ET_MULTI_NEI) continue; + if (asg_extend(g, v, max_ext, &a) != ASG_ET_MULTI_NEI) continue; + /** + * so combining the last two lines, they are designed to reomve(n(1), n(2))? + -----> <------- + | | + n(0)--->n(1)---->n(2)---->n(3) + | | + ------> <------- + **/ + for (i = 0; i < a.n; ++i) + asg_seq_del(g, (uint32_t)a.a[i]>>1); + ++cnt; + } + free(a.a); + if (cnt > 0) asg_cleanup(g); + fprintf(stderr, "[M::%s] cut %d internal sequences\n", __func__, cnt); + return cnt; +} + +uint32_t reset_weak_ovlp(ma_hit_t_alloc *sc, uint32_t src, uint32_t dst) +{ + ma_hit_t_alloc *x = &(sc[src]); uint32_t k, tn; int32_t idx; + for (k = 0; k < x->length; k++) { + if((x->buffer[k].bl&((uint32_t)0x40000000))) continue; + if((x->buffer[k].del)) continue; + tn = Get_tn(x->buffer[k]); + if((Get_ts(x->buffer[k]) == 0) && (Get_te(x->buffer[k]) == Get_READ_LENGTH(R_INF, tn))) { + idx = get_specific_overlap(&(sc[tn]), tn, dst); + if((idx >= 0) && (!(sc[tn].buffer[idx].del)) && (!(sc[tn].buffer[idx].bl&((uint32_t)0x40000000)))) { + return 1; + } + } + } + return 0; +} + +static void update_weak_by_contain(void *data, long i, int tid) +{ + sset_aux *sl = (sset_aux *)data; + ma_hit_t_alloc *x = &(sl->src[i]); + uint32_t k, qn, tn; int32_t idx; + if(sl->ul_occ == 0) { + for (k = 0; k < x->length; k++) { + if(x->buffer[k].bl&((uint32_t)0x40000000)) x->buffer[k].del = 1; + } + } else if(sl->ul_occ == 1) { + for (k = 0; k < x->length; k++) { + qn = Get_qn(x->buffer[k]); + tn = Get_tn(x->buffer[k]); + if(qn > tn) continue; + if((x->buffer[k].del) && (x->buffer[k].bl&((uint32_t)0x40000000))) { + if(reset_weak_ovlp(sl->src, qn, tn)) { + idx = get_specific_overlap(&(sl->src[tn]), tn, qn); + sl->src[tn].buffer[idx].del = x->buffer[k].del = 0; + } + } + } + } else { + for (k = 0; k < x->length; k++) { + if(x->buffer[k].bl&((uint32_t)0x40000000)) { + x->buffer[k].bl -= ((uint32_t)0x40000000); + } + } + } +} + +void clean_weak_ma_hit_t(ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long num_sources, uint32_t ou_thres) +{ + double startTime = Get_T(); + long long i, j, index; + uint32_t qn, tn, ou; + + for (i = 0; i < num_sources; i++) { + for (j = 0; j < sources[i].length; j++) { + qn = Get_qn(sources[i].buffer[j]); + tn = Get_tn(sources[i].buffer[j]); + + if(sources[i].buffer[j].del) continue; + ou = (sources[i].buffer[j].bl&((uint32_t)0x3fffffff)); + //if this is a weak overlap; ml == 0 -> weak overlap + if((sources[i].buffer[j].ml == 0) && ((ou_thres==((uint32_t)-1)) || (ou < ou_thres))) + { + if( + !check_weak_ma_hit(&(sources[qn]), reverse_sources, tn, + Get_qs(sources[i].buffer[j]), Get_qe(sources[i].buffer[j])) + /** + || + !check_weak_ma_hit_reverse(&(reverse_sources[qn]), sources, tn)**/) + { + sources[i].buffer[j].bl |= ((uint32_t)0x40000000); + index = get_specific_overlap(&(sources[tn]), tn, qn); + // if(index < 0 || index >= sources[tn].length) fprintf(stderr, "sb, tn: %u, qn: %u, index: %ld, length: %u\n", tn, qn, index, sources[tn].length); + sources[tn].buffer[index].bl |= ((uint32_t)0x40000000); + // ma_hit_t *h = &(sources[i].buffer[j]); + // if((Get_qn(*h) == 27087 && Get_tn(*h) == 27128) || (Get_tn(*h) == 27087 && Get_qn(*h) == 27128)) { + // fprintf(stderr, "[M::%s]\t%.*s(qn::%u)\t%u\t%u\t%u\t%c\t%.*s(tn::%u)\t%u\t%u\t%u\t%u\t%u\t255\n", __func__, (int)Get_NAME_LENGTH(R_INF, Get_qn(*h)), Get_NAME((R_INF), Get_qn(*h)), Get_qn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_qn(*h)), Get_qs(*h), Get_qe(*h), "+-"[h->rev], + // (int)Get_NAME_LENGTH(R_INF, Get_tn(*h)), Get_NAME((R_INF), Get_tn(*h)), Get_tn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_tn(*h)), Get_ts(*h), Get_te(*h), h->ml, h->bl); + // } + } + } + } + } + + sset_aux s; s.src = sources; s.ul_occ = 0; + kt_for(asm_opt.thread_num, update_weak_by_contain, &s, num_sources); + + if(ou_thres != ((uint32_t)-1)) { + s.ul_occ = 1; + kt_for(asm_opt.thread_num, update_weak_by_contain, &s, num_sources); + } + + s.ul_occ = 2; + kt_for(asm_opt.thread_num, update_weak_by_contain, &s, num_sources); + + // for (i = 0; i < num_sources; i++) + // { + + // for (j = 0; j < sources[i].length; j++) + // { + // if(sources[i].buffer[j].del) continue; + + // if(sources[i].buffer[j].bl&((uint32_t)0x40000000)) + // { + // sources[i].buffer[j].del = 1; + // sources[i].buffer[j].bl -= ((uint32_t)0x40000000); + // } + // else + // { + // sources[i].buffer[j].del = 0; + // } + // } + // } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } +} + + + + + + + +void debug_info_of_specfic_read(const char* name, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, int id, const char* command) +{ + long long i, j, Len; + uint32_t tn; + + if(id == -1) + { + i = 0; + Len = R_INF.total_reads; + } + else + { + i = id; + Len = id + 1; + } + + + for (; i < Len; i++) + { + if(memcmp(name, Get_NAME(R_INF, i), Get_NAME_LENGTH(R_INF, i)) == 0) + { + fprintf(stderr, "\n\n\nafter %s\n", command); + + fprintf(stderr, "****************ma_hit_t (%lld)ref_read: %.*s, len: %lu****************\n", + i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i), (unsigned long)Get_READ_LENGTH(R_INF, i)); + + + fprintf(stderr, "sources Len: %d, is_fully_corrected: %d\n", + sources[i].length, sources[i].is_fully_corrected); + + for (j = 0; j < sources[i].length; j++) + { + tn = Get_tn(sources[i].buffer[j]); + fprintf(stderr, "target: %.*s, qs: %u, qe: %u, ts: %u, te: %u, ml: %u, rev: %u, el: %u, del: %u\n", + (int)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), + Get_qs(sources[i].buffer[j]), + Get_qe(sources[i].buffer[j]), + Get_ts(sources[i].buffer[j]), + Get_te(sources[i].buffer[j]), + sources[i].buffer[j].ml, + sources[i].buffer[j].rev, + sources[i].buffer[j].el, + (uint32_t)sources[i].buffer[j].del); + } + + + + fprintf(stderr, "######reverse_query_read Len: %d\n", reverse_sources[i].length); + + + + for (j = 0; j < reverse_sources[i].length; j++) + { + tn = Get_tn(reverse_sources[i].buffer[j]); + fprintf(stderr, "target: %.*s, qs: %u, qe: %u, ts: %u, te: %u, rev: %u, del: %u\n", + (int)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), + Get_qs(reverse_sources[i].buffer[j]), + Get_qe(reverse_sources[i].buffer[j]), + Get_ts(reverse_sources[i].buffer[j]), + Get_te(reverse_sources[i].buffer[j]), + reverse_sources[i].buffer[j].rev, + (uint32_t)sources[i].buffer[j].del); + } + + break; + + } + } + + fflush(stderr); + + +} + +void ma_sg_print(const asg_t *g, const All_reads *RNF, const ma_sub_t *sub, FILE *fp) +{ + uint32_t i; + for (i = 0; i < g->n_seq; ++i) + { + if(!g->seq[i].del) + { + fprintf(fp, + "S\t%.*s\t*\tLN:i:%u\n", + (int)Get_NAME_LENGTH((*RNF), i), + Get_NAME((*RNF), i), + g->seq[i].len); + } + } + + for (i = 0; i < g->n_arc; ++i) { + const asg_arc_t *p = &g->arc[i]; + if (sub) { + const ma_sub_t *sq = &sub[p->ul>>33], *st = &sub[p->v>>1]; + + fprintf(fp, + "L\t%.*s:%d-%d\t%c\t%.*s:%d-%d\t%c\t%d:\tL1:i:%u\n", + (int)Get_NAME_LENGTH((*RNF), p->ul>>33), + Get_NAME((*RNF), p->ul>>33), + sq->s + 1, sq->e, "+-"[p->ul>>32&1], + (int)Get_NAME_LENGTH((*RNF), p->v>>1), + Get_NAME((*RNF), p->v>>1), + st->s + 1, st->e, "+-"[p->v&1], p->ol, (uint32_t)p->ul); + + + } + else + { + fprintf(fp, "L\t%.*s\t%c\t%.*s\t%c\t%d:\tL1:i:%u\n", + (int)Get_NAME_LENGTH((*RNF), p->ul>>33), + Get_NAME((*RNF), p->ul>>33), + "+-"[p->ul>>32&1], + (int)Get_NAME_LENGTH((*RNF), p->v>>1), + Get_NAME((*RNF), p->v>>1), + "+-"[p->v&1], p->ol, (uint32_t)p->ul); + } + } +} + + +void ma_ug_print_simple(const ma_ug_t *ug, asg_t* read_g, const ma_sub_t *coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex, const char* prefix, FILE *fp) +{ + ma_ug_print2(ug, &R_INF, read_g, coverage_cut, sources, ruIndex, 0, prefix, fp); +} + +void ma_ug_print_bed(const ma_ug_t *g, asg_t *read_g, All_reads *RNF, ma_sub_t *coverage_cut, +ma_hit_t_alloc* sources, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, uint32_t rate_thres, +const char* prefix, FILE *fp, trans_chain* t_ch) +{ + UC_Read g_read; + init_UC_Read(&g_read); + UC_Read tmp; + init_UC_Read(&tmp); + kvec_t_u32_warp exact_count, total_count; + kv_init(exact_count.a); + kv_init(total_count.a); + uint32_t i, j, l, eLen, start; + for (i = 0; i < g->u.n; ++i) { + ma_utg_t *u = &g->u.a[i]; + if(u->m == 0) continue; + if(u->n < 2) continue; + l = 0; + for (j = 0; j < u->n; ++j) + { + start = l; + eLen = (uint32_t)u->a[j]; + l += eLen; + + print_rough_inconsistent_sites(u, j, j+1, read_g, RNF, sources, coverage_cut, + edge, &g_read, &tmp, max_hang, min_ovlp, start, rate_thres, &exact_count, + &total_count, prefix, i+1, fp, t_ch? &(t_ch->bed.a[i]): NULL); + } + } + + destory_UC_Read(&g_read); + destory_UC_Read(&tmp); + kv_destroy(exact_count.a); + kv_destroy(total_count.a); +} + +uint32_t get_break_point_cov(ma_utg_t* collection, uint32_t cur_i, uint32_t next_i, +asg_t* read_g, All_reads *RNF, ma_hit_t_alloc* sources, R_to_U* ruIndex, ma_sub_t *coverage_cut, +int max_hang, int min_ovlp, kvec_asg_arc_t_warp* edge, uint8_t* r_flag) +{ + uint32_t v, w, i, tn, is_Unitig; + int v_beg, v_end, v_sub_beg, v_sub_end; + asg_arc_t t; + + v = (uint64_t)(collection->a[cur_i])>>32; + ///last element + if(cur_i == collection->n-1 && next_i == collection->n) + { + if(!collection->circ) + { + next_i = (uint32_t)-1; + } + else + { + next_i = 0; + } + } + + if(next_i != ((uint32_t)-1)) + { + w = (uint64_t)(collection->a[next_i])>>32; + + get_specific_edge(sources, coverage_cut, NULL, edge, read_g, max_hang, min_ovlp, v, w, &t); + v_beg = 0; v_end = asg_arc_len(t) - 1; + if(v&1) + { + v_beg = Get_READ_LENGTH((*RNF), (v>>1)) - v_beg - 1; + v_end = Get_READ_LENGTH((*RNF), (v>>1)) - v_end - 1; + w = v_beg; v_beg = v_end; v_end = w; + } + } + else + { + v_beg = 0; v_end = Get_READ_LENGTH((*RNF), (v>>1)) - 1; + } + + ma_hit_t_alloc* x = &(sources[v>>1]); + ma_hit_t *h = NULL; + long long R_bases = v_end + 1 - v_beg, C_bases = 0; + ///[v_beg, v_end] must be the end of read, which means v_beg = 0 or v_end = Get_READ_LENGTH((*RNF), (v>>1)) - 1 + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + tn = Get_tn((*h)); + if(read_g->seq[tn].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + if(read_g->seq[tn].del == 1) continue; + if(r_flag[tn] != 1) continue; + + + if(inter_interval(v_beg, v_end, Get_qs((*h)), Get_qe((*h)) - 1, + &v_sub_beg, &v_sub_end) == 0) + { + continue; + } + + C_bases += (v_sub_end + 1 - v_sub_beg); + } + if(R_bases <= 0 || C_bases <= 0) return 0; + + return C_bases/R_bases; +} + + + +uint32_t push_cov_interval_direct(kvec_t_u64_warp* a, long long x_beg, long long x_end, long long utg_len, uint64_t is_circle) +{ + if(x_beg <= x_end && x_beg >= 0 && x_end >= 0 && x_beg < utg_len && x_end < utg_len) + { + uint64_t key; + key = x_beg; key <<= 1; key |= (!is_circle); key <<= 1; key|=1; + kv_push(uint64_t, a->a, key); + key = x_end + 1; key <<= 1; key |= (!is_circle); key <<= 1; + kv_push(uint64_t, a->a, key); + return 1; + } + return 0; +} + +uint32_t push_cov_interval_advance(kvec_t_u64_warp* a, long long x_beg, long long x_end, long long utg_len, uint32_t is_circle) +{ + if(x_beg > x_end) return 0; + + if(push_cov_interval_direct(a, x_beg, x_end, utg_len, 0)) return 1; + + + if(x_beg < 0 && x_end < 0) + { + x_beg = utg_len + x_beg; + x_end = utg_len + x_end; + return push_cov_interval_direct(a, x_beg, x_end, utg_len, 0); + } + + if(x_beg >= utg_len && x_end >= utg_len) + { + x_beg = x_beg - utg_len; + x_end = x_end - utg_len; + return push_cov_interval_direct(a, x_beg, x_end, utg_len, 0); + } + + if(x_beg < 0 && x_end >= 0) + { + x_beg = utg_len + x_beg; + if(push_cov_interval_direct(a, x_beg, utg_len - 1, utg_len, is_circle) || + push_cov_interval_direct(a, 0, x_end, utg_len, is_circle)) + { + return 1; + } + } + + return 0; +} + +void get_break_point_cov_advance(uint32_t v, long long c_beg, asg_t* read_g, All_reads *RNF, +ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag, kvec_t_u64_warp* depth, long long utg_len, +uint32_t is_circle, uint32_t* uID) +{ + uint32_t i, tn, is_Unitig; + long long v_beg, v_end, w_beg, w_end; + + v_beg = 0; v_end = Get_READ_LENGTH((*RNF), (v>>1)) - 1; + if(uID && (r_flag[v>>1]&1) && (!(r_flag[v>>1]&2))) + { + if(push_cov_interval_advance(depth, v_beg+c_beg, v_end+c_beg, utg_len, is_circle)) r_flag[v>>1] |= 2; + return; + } + + + ma_hit_t_alloc* x = &(sources[v>>1]); + ma_hit_t *h = NULL; + long long qs, qe, ts, te; + ///[v_beg, v_end] must be the end of read, which means v_beg = 0 or v_end = Get_READ_LENGTH((*RNF), (v>>1)) - 1 + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + tn = Get_tn((*h)); + if(read_g->seq[tn].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + if(read_g->seq[tn].del == 1) continue; + if(!(r_flag[tn]&1)) continue; + tn = Get_tn((*h));///must!!!! + + if(r_flag[tn]&2) continue; + + qs = Get_qs((*h)); qe = Get_qe((*h)) - 1; + ts = Get_ts((*h)); te = Get_te((*h)) - 1; + if(h->rev) + { + ts = (long long)(Get_READ_LENGTH((*RNF), tn)) - ((long long)(Get_te((*h))) - 1) - 1; + te = (long long)(Get_READ_LENGTH((*RNF), tn)) - (long long)(Get_ts((*h))) - 1; + } + ts = qs - ts; + te = qe + ((long long)(Get_READ_LENGTH((*RNF), tn)) - te - 1); + w_beg = ts; w_end = te; + + if(v&1) + { + ts = (long long)(Get_READ_LENGTH((*RNF), v>>1)) - ts - 1; + te = (long long)(Get_READ_LENGTH((*RNF), v>>1)) - te - 1; + w_beg = te; w_end = ts; + } + + if(push_cov_interval_advance(depth, w_beg+c_beg, w_end+c_beg, utg_len, is_circle)) r_flag[tn] |= 2; + } +} +typedef struct { + uint32_t dp; + uint64_t k_beg, k_end; +} in_sub_t; + +typedef struct { + size_t n, m; + in_sub_t* a; +}kv_in_sub_t; + + +void debug_r_contig_pos(ma_utg_t *u, uint32_t tn, All_reads *RNF) +{ + uint32_t c_beg, c_end, l, k; + for (k = l = 0; k < u->n; k++) + { + c_beg = l; + c_end = c_beg + Get_READ_LENGTH((*RNF), (u->a[k]>>33)); + l += (uint32_t)u->a[k]; + if((u->a[k]>>33) == tn) + { + fprintf(stderr, "#####c_beg: %u, c_end: %u\n", c_beg, c_end); + break; + } + } +} + +uint32_t get_overlap_contig_dir(uint32_t v, uint32_t tn, ma_hit_t *h, All_reads *RNF, long long ctg_beg, +uint32_t p_beg, uint32_t p_end) +{ + long long qs, qe, ts, te, c_beg, c_end; + + qs = Get_qs((*h)); qe = Get_qe((*h)) - 1; + ts = Get_ts((*h)); te = Get_te((*h)) - 1; + if(h->rev) + { + ts = (long long)(Get_READ_LENGTH((*RNF), tn)) - ((long long)(Get_te((*h))) - 1) - 1; + te = (long long)(Get_READ_LENGTH((*RNF), tn)) - (long long)(Get_ts((*h))) - 1; + } + ts = qs - ts; + te = qe + ((long long)(Get_READ_LENGTH((*RNF), tn)) - te - 1); + c_beg = ts; c_end = te; + + if(v&1) + { + ts = (long long)(Get_READ_LENGTH((*RNF), v>>1)) - ts - 1; + te = (long long)(Get_READ_LENGTH((*RNF), v>>1)) - te - 1; + c_beg = te; c_end = ts; + } + + c_end++; + c_beg += ctg_beg; c_end += ctg_beg; + + if((p_beg != p_end && c_beg <= p_beg && c_end >= p_end) || + (p_beg == p_end && c_beg < p_beg && c_end > p_end)) + { + return 2; + } + + if(c_beg < p_beg) return 0; + if(c_end > p_end) return 1; + + return 2; + +} +///[beg, end) +uint32_t get_break_point_idx(ma_utg_t *u, All_reads *RNF, uint8_t* r_flag, ma_hit_t_alloc* sources, +asg_t* read_g, R_to_U* ruIndex, uint32_t p_beg, uint32_t p_end, double m_rate) +{ + uint32_t k, i, tn, is_Unitig, min_k = (uint32_t)-1, min_l = (uint32_t)-1, l, c_beg, c_end, index; + uint32_t e_occ = 0, ne_occ = 0; + double e_occ_dir[3], ne_occ_dir[3], rate[2]; + ma_hit_t_alloc* x = NULL; + ma_hit_t *h = NULL; + + e_occ = ne_occ = 0; + for (k = l = 0; k < u->n; k++) + { + c_beg = l; + c_end = c_beg + Get_READ_LENGTH((*RNF), (u->a[k]>>33)); + l += (uint32_t)u->a[k]; + + if((p_beg != p_end && c_beg <= p_beg && c_end >= p_end) || + (p_beg == p_end && c_beg < p_beg && c_end > p_end)) + { + + if(min_k == (uint32_t)-1) min_k = k, min_l = c_beg; + + x = &(sources[u->a[k]>>33]); + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + tn = Get_tn((*h)); + if(read_g->seq[tn].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + if(read_g->seq[tn].del == 1) continue; + if(!(r_flag[tn]&1)) continue; + if(h->el) e_occ++; + else ne_occ++; + } + } + else if(min_k != (uint32_t)-1) + { + break; + } + } + + if(min_k == (uint32_t)-1) return (uint32_t)-1; + if(e_occ <= ((e_occ+ne_occ)*m_rate)) goto c_break; + + e_occ = ne_occ = 0; + for (k = min_k, l = min_l; k < u->n; k++) + { + c_beg = l; + c_end = c_beg + Get_READ_LENGTH((*RNF), (u->a[k]>>33)); + l += (uint32_t)u->a[k]; + + if((p_beg != p_end && c_beg <= p_beg && c_end >= p_end) || + (p_beg == p_end && c_beg < p_beg && c_end > p_end)) + { + e_occ_dir[0] = e_occ_dir[1] = e_occ_dir[2] = 0; + ne_occ_dir[0] = ne_occ_dir[1] = ne_occ_dir[2] = 0; + + x = &(sources[u->a[k]>>33]); + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + tn = Get_tn((*h)); + if(read_g->seq[tn].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + if(read_g->seq[tn].del == 1) continue; + if(!(r_flag[tn]&1)) continue; + + tn = Get_tn((*h));///must!!!! + + index = get_overlap_contig_dir(u->a[k]>>32, tn, h, RNF, c_beg, p_beg, p_end); + + ///debug_r_contig_pos(u, tn, RNF); + if(h->el) e_occ_dir[index]++; + else ne_occ_dir[index]++; + } + + e_occ_dir[0] += e_occ_dir[2]; e_occ_dir[1] += e_occ_dir[2]; + ne_occ_dir[0] += ne_occ_dir[2]; ne_occ_dir[1] += ne_occ_dir[2]; + rate[0] = ne_occ_dir[0] / (ne_occ_dir[0] + e_occ_dir[0]); + rate[1] = ne_occ_dir[1] / (ne_occ_dir[1] + e_occ_dir[1]); + if(rate[0] >= rate[1]) + { + e_occ += e_occ_dir[0]; + ne_occ += ne_occ_dir[0]; + } + else + { + e_occ += e_occ_dir[1]; + ne_occ += ne_occ_dir[1]; + } + } + else if(min_k != (uint32_t)-1) + { + break; + } + } + + if(e_occ <= ((e_occ+ne_occ)*m_rate)) goto c_break; + return (uint32_t)-1; + + + c_break: + k = min_k; c_beg = min_l; c_end = c_beg + Get_READ_LENGTH((*RNF), (u->a[k]>>33)); + if((p_beg - c_beg) <= (c_end - p_end)) + { + if(k == 0 && !u->circ) return (uint32_t)-1; + return k; + } + else + { + if((k+1) < u->n) return k+1; + if((k+1) == u->n && u->circ) return 0; + return (uint32_t)-1; + } + + return (uint32_t)-1; +} + +void debug_break_point_advance(ma_utg_t *u, uint32_t uID, asg_t* read_g, All_reads *RNF, ma_hit_t_alloc* sources, +R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, uint8_t* r_flag) +{ + if(u->n < 2 || u->m == 0) return; + uint32_t k, l, c_beg; + memset(r_flag, 0, read_g->n_seq); + for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 1; + kvec_t_u64_warp d; kv_init(d.a); + kvec_t_u64_warp b_d; kv_init(b_d.a); + + d.a.n = 0; + for (k = l = 0; k < u->n; k++) + { + c_beg = l; + l += (uint32_t)u->a[k]; + get_break_point_cov_advance((uint64_t)(u->a[k])>>32, c_beg, read_g, RNF, sources, ruIndex, r_flag, &d, u->len, u->circ, &uID); + } + + for (k = l = 0; k < u->n; k++) + { + c_beg = l; + l += (uint32_t)u->a[k]; + get_break_point_cov_advance((uint64_t)(u->a[k])>>32, c_beg, read_g, RNF, sources, ruIndex, r_flag, &d, u->len, u->circ, NULL); + } + + kv_malloc(b_d.a, d.a.n); b_d.a.n = d.a.n; + memcpy(b_d.a.a, d.a.a, d.a.n*sizeof(uint64_t)); + + radix_sort_arch64(d.a.a, d.a.a + d.a.n); + + long long dp, o_dp; + uint32_t idx, o_idx, dir, o_dir, i; + uint64_t k_beg, k_end, k_dp, b_beg, b_end, occ; + dp = 0; o_idx = 0; o_dir = 1;///means it is a beg + for (k = 0; k < d.a.n; k++) + { + o_dp = dp; + ///if start = end, we should meet end first, otherwise it will have a bug + if(d.a.a[k]&1) ++dp; + else --dp; + + dir = d.a.a[k]&1; idx = d.a.a[k]>>2; + if((idx - o_idx > 0) || (idx == o_idx && o_dir != dir)) + { + k_beg = o_idx; k_end = idx; k_dp = o_dp; + + for (i = occ = 0; i < b_d.a.n; i += 2) + { + b_beg = b_d.a.a[i]>>2; + b_end = b_d.a.a[i+1]>>2; + if(b_beg <= k_beg && b_end >= k_end) occ++; + if((k_beg == k_end) && (b_beg == k_beg || b_end == k_beg)) occ--; + } + if(occ != k_dp) + { + fprintf(stderr, "k_beg: %lu, k_end: %lu, k_dp: %lu, occ: %lu\n", k_beg, k_end, k_dp, occ); + } + } + o_idx = idx; + o_dir = dir; + } + + if(o_idx != u->len) + { + k_beg = o_idx; k_end = u->len; k_dp = 0; + + for (i = occ = 0; i < b_d.a.n; i += 2) + { + b_beg = b_d.a.a[i]>>2; + b_end = b_d.a.a[i+1]>>2; + if(b_beg <= k_beg && b_end >= k_end) occ++; + } + if(occ != k_dp) + { + fprintf(stderr, "k_beg: %lu, k_end: %lu, k_dp: %lu, occ: %lu\n", k_beg, k_end, k_dp, occ); + } + } + + kv_destroy(d.a); kv_destroy(b_d.a); +} + +void detect_break_point_advance(ma_utg_t *u, uint32_t uID, asg_t* read_g, All_reads *RNF, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, +uint8_t* r_flag, kvec_t_u64_warp* d, kv_in_sub_t* depth_i, kvec_t_u64_warp* res, int* b_low_cov, +int* b_high_cov, double m_rate) +{ + if(u->n < 2 || u->m == 0) return; + uint32_t k, l, c_beg; + memset(r_flag, 0, read_g->n_seq); + for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 1; + + d->a.n = 0; + for (k = l = 0; k < u->n; k++) + { + c_beg = l; + l += (uint32_t)u->a[k]; + get_break_point_cov_advance((uint64_t)(u->a[k])>>32, c_beg, read_g, RNF, sources, ruIndex, r_flag, d, u->len, u->circ, &uID); + } + + for (k = l = 0; k < u->n; k++) + { + c_beg = l; + l += (uint32_t)u->a[k]; + get_break_point_cov_advance((uint64_t)(u->a[k])>>32, c_beg, read_g, RNF, sources, ruIndex, r_flag, d, u->len, u->circ, NULL); + } + + radix_sort_arch64(d->a.a, d->a.a + d->a.n); + + long long dp, o_dp; + uint32_t idx, o_idx, dir, o_dir; + in_sub_t* p = NULL; + + + + /*******************************for debug************************************/ + ///debug_break_point_advance(u, uID, read_g, RNF, sources, ruIndex, edge, r_flag); + /*******************************for debug************************************/ + + + + + + + + + + depth_i->n = 0; + ///[start, end) + ///for circle + dp = 0; o_idx = 0; o_dir = 1;///means it is a beg + for (k = 0; k < d->a.n; k++) + { + o_dp = dp; + ///if start = end, we should meet end first, otherwise it will have a bug + if(d->a.a[k]&1) ++dp; + else --dp; + + dir = d->a.a[k]&1; idx = d->a.a[k]>>2; + if((idx - o_idx > 0) || (idx == o_idx && o_dir != dir)) + { + if(b_low_cov) + { + ///merge + if(o_dp >= (*b_low_cov) && depth_i->n > 0 && (int)depth_i->a[depth_i->n-1].dp >= (*b_low_cov)) + { + p = &(depth_i->a[depth_i->n-1]); + p->k_end = idx; + p->dp = o_dp; + } + else //insert new + { + kv_pushp(in_sub_t, *depth_i, &p); + p->k_beg = o_idx; + p->k_end = idx; + p->dp = o_dp; + } + } + + if(b_high_cov) + { + if(o_dp <= (*b_high_cov) && depth_i->n > 0 && (int)depth_i->a[depth_i->n-1].dp <= (*b_high_cov)) + { + p = &(depth_i->a[depth_i->n-1]); + p->k_end = idx; + p->dp = o_dp; + } + else //insert new + { + kv_pushp(in_sub_t, *depth_i, &p); + p->k_beg = o_idx; + p->k_end = idx; + p->dp = o_dp; + } + } + + } + o_idx = idx; + o_dir = dir; + } + + if(o_idx != u->len) + { + kv_pushp(in_sub_t, *depth_i, &p); + p->k_beg = o_idx; + p->k_end = u->len; + p->dp = 0; + } + + // if(b_high_cov) + // { + // fprintf(stderr, "\n\n\n\n\n\n\n\n\n\n"); + // fprintf(stderr, "uID: %u, u->n: %u, u->len: %u\n", uID, (uint32_t)u->n, (uint32_t)u->len); + // for (k = 0; k < depth_i->n; k++) + // { + // fprintf(stderr, "k: %u, k_beg: %lu, k_end: %lu, dp: %u\n", + // k, depth_i->a[k].k_beg, depth_i->a[k].k_end, depth_i->a[k].dp); + // } + // } + + + uint32_t beg_idx, end_idx, cir_beg_idx, cir_end_idx, min, min_idx, cur_idx, i; + beg_idx = end_idx = (uint32_t)-1; + cir_beg_idx = cir_end_idx = (uint32_t)-1; + uint64_t tmp; + + for (k = 0; k < depth_i->n; k++) + { + if(k > 0) + { + if((b_low_cov && (int)depth_i->a[k-1].dp >= (*b_low_cov) && (int)depth_i->a[k].dp < (*b_low_cov)) || + (b_high_cov && (int)depth_i->a[k-1].dp <= (*b_high_cov) && (int)depth_i->a[k].dp > (*b_high_cov))) + { + beg_idx = k; + } + } + + if(k < depth_i->n-1) + { + if((b_low_cov && (int)depth_i->a[k].dp < (*b_low_cov) && (int)depth_i->a[k+1].dp >= (*b_low_cov)) || + (b_high_cov && (int)depth_i->a[k].dp > (*b_high_cov) && (int)depth_i->a[k+1].dp <= (*b_high_cov))) + { + end_idx = k; + if(beg_idx == (uint32_t)-1) cir_end_idx = k; + + + if(beg_idx != (uint32_t)-1 && end_idx >= beg_idx) + { + min = min_idx = (uint32_t)-1; + for (i = beg_idx; i <= end_idx; i++) + { + // if(b_high_cov) + // { + // fprintf(stderr, "+k_end: %lu, k_end: %lu, dp: %u\n", depth_i->a[i].k_beg, depth_i->a[i].k_end, depth_i->a[i].dp); + // } + if(depth_i->a[i].dp < min) + { + cur_idx = get_break_point_idx(u, RNF, r_flag, sources, read_g, ruIndex, + depth_i->a[i].k_beg, depth_i->a[i].k_end, m_rate); + if(cur_idx == (uint32_t)-1) continue; + min = depth_i->a[i].dp; min_idx = cur_idx; + } + } + if(min_idx != (uint32_t)-1) + { + //fprintf(stderr, "+uID: %u, min_idx: %u, k_beg: %lu, k_end: %lu\n", uID, min_idx, depth_i->a[min_idx].k_beg, depth_i->a[min_idx].k_end); + if(min_idx != (uint32_t)-1) + { + tmp = uID; tmp <<=32; tmp += min_idx; + kv_push(uint64_t, res->a, tmp); + } + } + } + beg_idx = end_idx = (uint32_t)-1; + } + } + } + + if(beg_idx != (uint32_t)-1 && end_idx == (uint32_t)-1) cir_beg_idx = beg_idx; + + if(u->circ && (cir_beg_idx != (uint32_t)-1 || cir_end_idx != (uint32_t)-1)) + { + beg_idx = cir_beg_idx; + end_idx = cir_end_idx; + + min = min_idx = (uint32_t)-1; + if(beg_idx != (uint32_t)-1) + { + for (i = beg_idx; i < depth_i->n; i++) + { + // if(b_high_cov) + // { + // fprintf(stderr, "-0-k_end: %lu, k_end: %lu, dp: %u\n", depth_i->a[i].k_beg, depth_i->a[i].k_end, depth_i->a[i].dp); + // } + if(depth_i->a[i].dp < min) + { + // min = depth_i->a[i].dp; + // min_idx = i; + cur_idx = get_break_point_idx(u, RNF, r_flag, sources, read_g, ruIndex, + depth_i->a[i].k_beg, depth_i->a[i].k_end, m_rate); + if(cur_idx == (uint32_t)-1) continue; + min = depth_i->a[i].dp; min_idx = cur_idx; + } + } + } + + if(end_idx != (uint32_t)-1) + { + for (i = 0; i <= end_idx; i++) + { + // if(b_high_cov) + // { + // fprintf(stderr, "-1-k_end: %lu, k_end: %lu, dp: %u\n", depth_i->a[i].k_beg, depth_i->a[i].k_end, depth_i->a[i].dp); + // } + if(depth_i->a[i].dp < min) + { + cur_idx = get_break_point_idx(u, RNF, r_flag, sources, read_g, ruIndex, + depth_i->a[i].k_beg, depth_i->a[i].k_end, m_rate); + if(cur_idx == (uint32_t)-1) continue; + min = depth_i->a[i].dp; min_idx = cur_idx; + } + } + } + + if(min_idx != (uint32_t)-1) + { + ///fprintf(stderr, "-uID: %u, min_idx: %u, k_beg: %lu, k_end: %lu\n", uID, min_idx, depth_i->a[min_idx].k_beg, depth_i->a[min_idx].k_end); + if(min_idx != (uint32_t)-1) + { + tmp = uID; tmp <<=32; tmp += min_idx; + kv_push(uint64_t, res->a, tmp); + } + } + } +} + +void detect_break_point(ma_utg_t *u, uint32_t uID, asg_t* read_g, All_reads *RNF, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, +uint8_t* r_flag, kvec_t_u32_warp* depth, kvec_t_u64_warp* res, uint32_t b_low_cov) +{ + depth->a.n = 0; + ///res->a.n = 0; + if(u->n < 2) return; + uint32_t k, i, min, min_idx, rId, *p = NULL, beg_idx, end_idx, cir_beg_idx, cir_end_idx; + uint64_t tmp; + if(u->m == 0) return; + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 1; + } + + + for (k = 0; k < u->n; k++) + { + kv_pushp(uint32_t, depth->a, &p); + (*p) = get_break_point_cov(u, k, k+1, read_g, RNF, sources, ruIndex, coverage_cut, max_hang, min_ovlp, edge, r_flag); + } + + + beg_idx = end_idx = (uint32_t)-1; + cir_beg_idx = cir_end_idx = (uint32_t)-1; + for (k = 0; k < u->n; k++) + { + if(k > 0 && depth->a.a[k-1] >= b_low_cov && depth->a.a[k] < b_low_cov) + { + beg_idx = k; + } + + if(k < u->n-1 && depth->a.a[k] < b_low_cov && depth->a.a[k+1] >= b_low_cov) + { + end_idx = k; + if(beg_idx == (uint32_t)-1) cir_end_idx = k; + if(beg_idx != (uint32_t)-1 && end_idx >= beg_idx) + { + min = min_idx = (uint32_t)-1; + for (i = beg_idx; i <= end_idx; i++) + { + if(depth->a.a[i] < min) + { + min = depth->a.a[i]; + min_idx = i; + } + } + if(min_idx != (uint32_t)-1) + { + tmp = uID; tmp <<=32; tmp += min_idx; + kv_push(uint64_t, res->a, tmp); + } + } + beg_idx = end_idx = (uint32_t)-1; + } + } + + if(beg_idx != (uint32_t)-1 && end_idx == (uint32_t)-1) cir_beg_idx = beg_idx; + + if(u->circ && (cir_beg_idx != (uint32_t)-1 || cir_end_idx != (uint32_t)-1)) + { + beg_idx = cir_beg_idx; + end_idx = cir_end_idx; + + min = min_idx = (uint32_t)-1; + + if(beg_idx != (uint32_t)-1) + { + for (i = beg_idx; i < u->n; i++) + { + if(depth->a.a[i] < min) + { + min = depth->a.a[i]; + min_idx = i; + } + } + } + + if(end_idx != (uint32_t)-1) + { + for (i = 0; i <= end_idx; i++) + { + if(depth->a.a[i] < min) + { + min = depth->a.a[i]; + min_idx = i; + } + } + } + + if(min_idx != (uint32_t)-1) + { + tmp = uID; tmp <<=32; tmp += min_idx; + kv_push(uint64_t, res->a, tmp); + } + } + + + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 0; + } +} + +void debug_break_point(ma_utg_t *u, uint32_t uID, asg_t* read_g, All_reads *RNF, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, +uint8_t* r_flag, kvec_t_u32_warp* depth, kvec_t_u64_warp* res, uint32_t b_low_cov) +{ + depth->a.n = 0; + ///res->a.n = 0; + if(u->n < 2) return; + uint32_t k, min, min_idx, rId, *p = NULL; + if(u->m == 0) return; + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 1; + } + + + for (k = 0; k < u->n; k++) + { + kv_pushp(uint32_t, depth->a, &p); + (*p) = get_break_point_cov(u, k, k+1, read_g, RNF, sources, ruIndex, coverage_cut, max_hang, min_ovlp, edge, r_flag); + } + + int k_i, is_end; + min_idx = min = (uint32_t)-1; + for (k = 0; k < res->a.n; k++) + { + if((res->a.a[k]>>32) != uID) continue; + min_idx = (uint32_t)res->a.a[k]; + min = depth->a.a[min_idx]; + + is_end = 0; + k_i = (int)(min_idx) - 1; + while (k_i >= 0) + { + if(depth->a.a[k_i] >= b_low_cov) break; + if(depth->a.a[k_i] < min) fprintf(stderr, "ERROR1\n"); + k_i--; + if(k_i < 0 && u->circ && is_end == 0) + { + k_i = u->n - 1; + is_end = 1; + } + } + + is_end = 0; + k_i = (int)(min_idx) + 1; + while(k_i < (int)u->n) + { + if(depth->a.a[k_i] >= b_low_cov) break; + if(depth->a.a[k_i] < min) fprintf(stderr, "ERROR2\n"); + k_i++; + if(k_i >= (int)u->n && u->circ && is_end == 0) + { + k_i = 0; + is_end = 1; + } + } + } + + + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 0; + } +} + +void debug_contig_end(ma_ug_t *ug, asg_t* read_g, kvec_asg_arc_t_warp* edge) +{ + asg_t* nsg = ug->g; + uint32_t n_vtx = nsg->n_seq<<1, v, w, nv, v_occ, rv, rw, i; + asg_arc_t *av = NULL; + ma_utg_t* u = NULL; + + for (v = 0; v < n_vtx; v++) + { + if(ug->g->seq[v>>1].del) continue; + u = &(ug->u.a[v>>1]); + if(u->n == 0) continue; + av = asg_arc_a(ug->g, v); + nv = asg_arc_n(ug->g, v); + if(nv == 0) continue; + + if(v&1) rv = ug->u.a[v>>1].start^1; + else rv = ug->u.a[v>>1].end^1; + + for (i = v_occ = 0; i < nv; i++) + { + if(av[i].del) continue; + v_occ++; + } + if(v_occ == 0) continue; + + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + w = av[i].v; + if(w&1) rw = ug->u.a[w>>1].end; + else rw = ug->u.a[w>>1].start; + + fprintf(stderr, "utg: (v>>1: %u)[v&1: %u]->(w>>1: %u)[w&1: %u]\n", v>>1, v&1, w>>1, w&1); + fprintf(stderr, "rtg: (r_v>>1: %u)[r_v&1: %u]->(r_w>>1: %u)[r_w&1: %u]\n\n", + rv>>1, rv&1, rw>>1, rw&1); + } + } +} + +void push_sub_unitig(ma_ug_t *n_ug, ma_utg_t *src_u, asg_t *read_g, kvec_asg_arc_t_warp* edge, +uint32_t beg_idx, uint32_t occ) +{ + uint32_t i; + uint64_t totalLen; + ma_utg_t* p = NULL; + kv_pushp(ma_utg_t, n_ug->u, &p); + p->s = NULL; + p->n = occ; + p->circ = 0; + if(beg_idx == 0 && occ == src_u->n) p->circ = src_u->circ; + p->m = p->n; + p->a = (uint64_t*)malloc(8 * p->m); + for (i = 0; i < occ; i++) p->a[i] = src_u->a[beg_idx+i]; + fill_unitig(p->a, occ, read_g, edge, p->circ, &totalLen); + p->len = totalLen; + if(!p->circ) + { + p->start = p->a[0]>>32; + p->end = (p->a[p->n-1]>>32)^1; + } + else + { + p->start = p->end = UINT32_MAX; + } +} + +void break_all_contigs(ma_ug_t **ug, asg_t *read_g, kvec_asg_arc_t_warp* edge, kvec_t_u64_warp* break_points) +{ + asg_cleanup((*ug)->g); + uint32_t k, l, m, occ, uID, idx; + uint64_t *a = NULL, w; + ma_utg_t *u = NULL; + radix_sort_arch64(break_points->a.a, break_points->a.a + break_points->a.n); + uint32_t *utg_idx = NULL; MALLOC(utg_idx, (*ug)->u.n<<1); + memset(utg_idx, -1, sizeof(uint32_t)*((*ug)->u.n<<1)); + asg_arc_t *av = NULL; + uint32_t p_u_idx, nv, v, s_i, p_i; + ma_ug_t *n_ug = NULL; + ma_utg_t *p = NULL, *z = NULL; + n_ug = (ma_ug_t*)calloc(1, sizeof(ma_ug_t)); + n_ug->g = asg_init(); + + for (k = m = 0; k < break_points->a.n; k++) + { + if(k == 0 || (m > 0 && break_points->a.a[m-1] != break_points->a.a[k])) + { + break_points->a.a[m] = break_points->a.a[k]; + m++; + } + } + ///fprintf(stderr, "break_points->a.n: %u, m: %u\n", (uint32_t)break_points->a.n, m); + break_points->a.n = m; + + for (k = 1, l = 0, p_i = 0; k <= break_points->a.n; ++k) + { + if (k == break_points->a.n || (break_points->a.a[k]>>32) != (break_points->a.a[l]>>32)) + { + occ = k - l; + a = break_points->a.a + l; + l = k; + if(occ == 0) continue; + uID = a[0]>>32; + u = &((*ug)->u.a[uID]); + if(u->n < 2) continue; + + for (s_i = p_i; s_i < uID; s_i++) + { + kv_pushp(ma_utg_t, n_ug->u, &p); + z = &((*ug)->u.a[s_i]); + (*p) = (*z); + z->len = z->circ = /**z->start = z->end =**/ z->m = z->n = 0; + z->a = NULL; z->s = NULL; + + utg_idx[s_i<<1] = ((uint32_t)(n_ug->u.n-1))<<1; + utg_idx[(s_i<<1)+1] = (((uint32_t)(n_ug->u.n-1))<<1)+1; + } + p_i = uID + 1; + + + utg_idx[(uID<<1)+1] = (((uint32_t)(n_ug->u.n))<<1)+1; + for (m = p_u_idx = 0; m < occ; m++) + { + idx = (uint32_t)(a[m]); + if(!u->circ && idx == 0) + { + fprintf(stderr, "ERROR 1\n"); + continue; + } + + + if(u->circ && idx == 0) + { + av = asg_arc_a((*ug)->g, (uID<<1)+1); + nv = asg_arc_n((*ug)->g, (uID<<1)+1); + for (v = 0; v < nv; v++) + { + if(av[v].del) continue; + av[v].del = 1; + asg_arc_del((*ug)->g, (av[v].v)^1, (av[v].ul>>32)^1, 1); + } + u->circ = 0; + u->start = u->a[0]>>32; + u->end = (u->a[u->n-1]>>32)^1; + continue; + } + + if(idx - p_u_idx <= 0) + { + fprintf(stderr, "ERROR2: uID: %u, u->circ: %u, idx: %u, p_u_idx: %u\n", + uID, u->circ, idx, p_u_idx); + continue; + } + + + push_sub_unitig(n_ug, u, read_g, edge, p_u_idx, idx - p_u_idx); + p_u_idx = idx; + } + push_sub_unitig(n_ug, u, read_g, edge, p_u_idx, u->n - p_u_idx); + utg_idx[(uID<<1)] = ((uint32_t)(n_ug->u.n-1))<<1; + + } + } + + for (s_i = p_i; s_i < (*ug)->u.n; s_i++) + { + kv_pushp(ma_utg_t, n_ug->u, &p); + z = &((*ug)->u.a[s_i]); + (*p) = (*z); + z->len = z->circ = /**z->start = z->end =**/ z->m = z->n = 0; + z->a = NULL; z->s = NULL; + + utg_idx[s_i<<1] = ((uint32_t)(n_ug->u.n-1))<<1; + utg_idx[(s_i<<1)+1] = (((uint32_t)(n_ug->u.n-1))<<1)+1; + } + + // for (k = 0; k < (*ug)->u.n; k++) + // { + // if(utg_idx[(k<<1)] == (uint32_t)-1) fprintf(stderr, "ERROR 3\n"); + // if(utg_idx[(k<<1)+1] == (uint32_t)-1) fprintf(stderr, "ERROR 4\n"); + // } + + asg_arc_t *q = NULL; + for (k = 0; k < (*ug)->g->n_arc; k++) + { + if((*ug)->g->arc[k].del) continue; + q = asg_arc_pushp(n_ug->g); + (*q) = (*ug)->g->arc[k]; + + q->v = utg_idx[q->v^1]^1; + + w = q->ul>>32; w = utg_idx[w]; w <<= 32; + q->ul <<= 32; q->ul >>= 32; q->ul |= w; + } + + for (k = 0; k < n_ug->u.n; k++) + { + asg_seq_set(n_ug->g, k, n_ug->u.a[k].len, 0); + } + + asg_cleanup(n_ug->g); + + // fprintf(stderr, "n_ug->u.n: %u, n_ug->g->n_seq: %u, (*ug)->u.n: %u\n", (uint32_t)n_ug->u.n, (uint32_t)n_ug->g->n_seq, + // (uint32_t)(*ug)->u.n); + + // for (k = 0; k < ((*ug)->u.n<<1); k++) + // { + // uint32_t ug_rid, n_ug_rid; + // if(k&1) ug_rid = ((*ug)->u.a[k>>1]).start; + // else ug_rid = ((*ug)->u.a[k>>1]).end; + + // if(utg_idx[k]&1) n_ug_rid = n_ug->u.a[utg_idx[k]>>1].start; + // else n_ug_rid = n_ug->u.a[utg_idx[k]>>1].end; + + // if(ug_rid != n_ug_rid) + // { + // fprintf(stderr, "ERROR, uid: %u, dir: %u, circle: %u, ug_rid: %u, n_ug_rid: %u\n", + // k>>1, k&1, (*ug)->u.a[k>>1].circ, ug_rid, n_ug_rid); + // } + // } + + + + ma_ug_destroy((*ug)); + (*ug) = n_ug; + renew_utg(ug, read_g, edge); ///for circle + // fprintf(stderr, "***********(1)edge->a.n: %u***********\n", (uint32_t)edge->a.n); + // debug_utg_graph(*ug, read_g, edge, 0, 0); + // fprintf(stderr, "***********(1)edge->a.n: %u***********\n", (uint32_t)edge->a.n); + free(utg_idx); +} + +void print_utg_stats(ma_ug_t *ug, const char* command) +{ + uint32_t i; + uint64_t len, occ_n, occ_m, occ_n_0; + for (i = len = occ_n = occ_m = occ_n_0 = 0; i < ug->u.n; ++i) { + ma_utg_t *u = &ug->u.a[i]; + len += u->len; + occ_n += u->n; + occ_m += u->m; + if(u->n == 0) occ_n_0++; + } + + fprintf(stderr, "%s: len: %lu, occ_n: %lu, occ_m: %lu, occ_n_0: %lu\n", + command, len, occ_n, occ_m, occ_n_0); +} + +void break_ug_contig(ma_ug_t **ug, asg_t *read_g, All_reads *RNF, ma_sub_t *coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, +int* b_low_cov, int* b_high_cov, double m_rate) +{ + if(b_low_cov) + { + fprintf(stderr, "[M::%s] break potential misassemblies with <%d-fold coverage\n", + __func__, *b_low_cov); + } + + if(b_high_cov) + { + fprintf(stderr, "[M::%s] break potential misassemblies with >%d-fold coverage\n", + __func__, *b_high_cov); + } + + kvec_t_u64_warp depth; + kv_init(depth.a); + kvec_t_u64_warp break_points; + kv_init(break_points.a); + kv_in_sub_t depth_i; + kv_init(depth_i); + uint32_t i; + uint8_t* primary_flag = (uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)); + ma_utg_t *u = NULL; + + for (i = 0; i < (*ug)->u.n; ++i) + { + u = &((*ug)->u.a[i]); + if(u->m == 0) continue; + if(u->n < 2) continue; + // detect_break_point(u, i, read_g, RNF, coverage_cut, sources, ruIndex, edge, max_hang, min_ovlp, primary_flag, &depth, &break_points, b_low_cov); + // debug_break_point(u, i, read_g, RNF, coverage_cut, sources, ruIndex, edge, max_hang, min_ovlp, primary_flag, &depth, &break_points, b_low_cov); + detect_break_point_advance(u, i, read_g, RNF, coverage_cut, sources, ruIndex, edge, max_hang, min_ovlp, + primary_flag, &depth, &depth_i, &break_points, b_low_cov, b_high_cov, m_rate); + + } + + break_all_contigs(ug, read_g, edge, &break_points); + + kv_destroy(depth.a); + kv_destroy(break_points.a); + kv_destroy(depth_i); + free(primary_flag); +} + +int asg_arc_cut_long_tip_primary_complex(asg_t *g, float drop_ratio, uint32_t stops_threshold) +{ + double startTime = Get_T(); + ///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, convex, flag; + long long ll, max_stopLen; + + buf_t b; + memset(&b, 0, sizeof(buf_t)); + + for (v = 0; v < n_vtx; ++v) + { + uint32_t i; + ///some node could be deleted + if (g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + ///tip + if (get_real_length(g, v, NULL) != 0) continue; + if(get_real_length(g, v^1, NULL) != 1) continue; + flag = detect_single_path_with_dels(g, v^1, &convex, &ll, NULL); + if(flag != TWO_INPUT && flag != MUL_INPUT) continue; + convex = convex^1;ll--; + uint32_t n_convex = asg_arc_n(g, convex), convexLen = ll; + asg_arc_t *a_convex = asg_arc_a(g, convex); + + + for (i = 0; i < n_convex; i++) + { + if (!a_convex[i].del) + { + ///if stops_threshold = 1, + ///detect_single_path_with_dels_n_stops() is detect_single_path_with_dels() + detect_single_path_with_dels_n_stops(g, a_convex[i].v, &convex, &ll, &max_stopLen, + NULL, stops_threshold); + + if(convex == v) continue; + + if(ll*drop_ratio > convexLen && max_stopLen*2>ll) + { + + b.b.n = 0; + flag = detect_single_path_with_dels(g, v^1, &convex, &ll, &b); + if(b.b.n < 2) break; + b.b.n--; + + + n_reduced++; + uint64_t k; + + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]].c = ALTER_LABLE; + } + + for (k = 0; k < b.b.n; k++) + { + asg_seq_drop(g, b.b.a[k]); + } + break; + } + } + } + } + + + asg_cleanup(g); + asg_symm(g); + free(b.b.a); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d long tips\n", + __func__, n_reduced); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + return n_reduced; +} + +int asg_arc_cut_long_equal_tips_assembly(asg_t *g, ma_hit_t_alloc* reverse_sources, +long long miniedgeLen, R_to_U* ruIndex) +{ + double startTime = Get_T(); + ///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, convex, flag, is_hap; + long long ll, base_maxLen, base_maxLen_i; + + buf_t b; + memset(&b, 0, sizeof(buf_t)); + + for (v = 0; v < n_vtx; ++v) + { + uint32_t i, n_arc = 0, nv = asg_arc_n(g, v), n_tips; + asg_arc_t *av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + n_arc = get_real_length(g, v, NULL); + if (n_arc < 2) continue; + + base_maxLen = -1; + base_maxLen_i = -1; + n_tips = 0; + is_hap = 0; + + for (i = 0; i < nv; i++) + { + if (!av[i].del) + { + flag = detect_single_path_with_dels_contigLen(g, av[i].v, &convex, &ll, NULL); + + if(base_maxLen < ll) + { + base_maxLen = ll; + base_maxLen_i = i; + } + + if(flag == END_TIPS) + { + n_tips++; + } + } + } + + ///at least one tip + if(n_tips > 0) + { + for (i = 0; i < nv; i++) + { + if(i == base_maxLen_i) continue; + if (!av[i].del) + { + b.b.n = 0; + if(detect_single_path_with_dels_contigLen(g, av[i].v, &convex, &ll, &b) + != END_TIPS) + { + continue; + } + //we can only cut tips + /****************************may have bugs********************************/ + if(check_if_diploid(av[base_maxLen_i].v, av[i].v, g, + reverse_sources, miniedgeLen, ruIndex)==1) + {/****************************may have bugs********************************/ + n_reduced++; + uint64_t k; + + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]].c = ALTER_LABLE; + } + for (k = 0; k < b.b.n; k++) + { + asg_seq_drop(g, b.b.a[k]); + } + is_hap++; + } + } + } + } + + + if(is_hap > 0) + { + i = base_maxLen_i; + b.b.n = 0; + detect_single_path_with_dels_contigLen(g, av[i].v, &convex, &ll, &b); + + uint64_t k; + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]].c = HAP_LABLE; + } + } + + + } + + + asg_cleanup(g); + asg_symm(g); + free(b.b.a); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d long tips\n", + __func__, n_reduced); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + + return n_reduced; +} + + +int asg_arc_simple_large_bubbles(asg_t *g, ma_hit_t_alloc* reverse_sources, long long miniedgeLen, +R_to_U* ruIndex) +{ + double startTime = Get_T(); + ///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, convex, flag, is_hap; + long long ll, base_maxLen, base_maxLen_i, all_covex; + + buf_t b; + memset(&b, 0, sizeof(buf_t)); + + for (v = 0; v < n_vtx; ++v) + { + uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + n_arc = get_real_length(g, v, NULL); + if (n_arc < 2) continue; + + base_maxLen = -1; + base_maxLen_i = -1; + all_covex = -1; + is_hap = 0; + + for (i = 0; i < nv; i++) + { + if (!av[i].del) + { + flag = detect_single_path_with_dels_contigLen(g, av[i].v, &convex, &ll, NULL); + if(flag != TWO_INPUT && flag != MUL_INPUT) + { + break; + } + + if(all_covex != -1 && (uint32_t)all_covex != convex) + { + break; + } + + if(all_covex == -1) + { + all_covex = convex; + } + + if(base_maxLen < ll) + { + base_maxLen = ll; + base_maxLen_i = i; + } + + } + } + + + if(i == nv) + { + for (i = 0; i < nv; i++) + { + if(i == base_maxLen_i) continue; + if (!av[i].del) + { + b.b.n = 0; + detect_single_path_with_dels_contigLen(g, av[i].v, &convex, &ll, &b); + if(b.b.n < 2) continue; + b.b.n--; + + //we can only cut tips + /****************************may have bugs********************************/ + if(check_if_diploid(av[base_maxLen_i].v, av[i].v, g, + reverse_sources, miniedgeLen, ruIndex)==1) + {/****************************may have bugs********************************/ + n_reduced++; + uint64_t k; + + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]].c = ALTER_LABLE; + } + for (k = 0; k < b.b.n; k++) + { + asg_seq_drop(g, b.b.a[k]); + } + + is_hap++; + } + } + } + + if(is_hap > 0) + { + i = base_maxLen_i; + b.b.n = 0; + detect_single_path_with_dels_contigLen(g, av[i].v, &convex, &ll, &b); + uint64_t k; + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]].c = HAP_LABLE; + } + } + } + + } + + + asg_cleanup(g); + asg_symm(g); + free(b.b.a); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d long tips\n", + __func__, n_reduced); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + + return n_reduced; +} + +uint32_t get_num_trio_flag(ma_ug_t *ug, uint32_t v, uint32_t flag) +{ + if(flag == (uint32_t)-1) return 0; + ma_utg_t* u = NULL; + asg_t* nsg = ug->g; + uint32_t k, rId, flag_occ = 0; + if (nsg->seq[v].del) return 0; + u = &(ug->u.a[v]); + if(u->m == 0) return 0; + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + if(R_INF.trio_flag[rId] == flag) flag_occ++; + } + + return flag_occ; +} + + + +inline uint64_t get_utg_len(buf_t* b, ma_ug_t *ug, asg_t *read_sg, uint64_t ignore_end, uint64_t* len_thre, uint64_t* occ) +{ + if(len_thre && occ)(*occ) = (uint64_t)-1; + uint32_t ori, uid, v, nv, l, k, idx; + uint32_t *a = b->b.a, a_n = b->b.n; + uint32_t u_i, r_i, len, p_v; + asg_arc_t *av = NULL; + ma_utg_t* u = NULL; + for (u_i = r_i = len = idx = 0, p_v = (uint32_t)-1; u_i < a_n; u_i++) + { + uid = a[u_i] >> 1; + ori = a[u_i] & 1; + u = &(ug->u.a[uid]); + if(u->n == 0) continue; + if(ori == 1) + { + for (r_i = 0; r_i < u->n; r_i++, idx++) + { + v = ((uint64_t)((u->a[u->n - r_i - 1])^(uint64_t)(0x100000000)))>>32; + if(p_v == (uint32_t)-1) + { + p_v = v; + continue; + } + + av = asg_arc_a(read_sg, p_v); + nv = asg_arc_n(read_sg, p_v); + l = 0; + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == v) + { + l = asg_arc_len(av[k]); + break; + } + } + if(k == nv) fprintf(stderr, "ERROR\n"); + len += l; + if(len_thre && occ && len >= (*len_thre)) + { + (*occ) = idx; + return len; + } + p_v = v; + } + } + else + { + for (r_i = 0; r_i < u->n; r_i++, idx++) + { + v = ((uint64_t)(u->a[r_i]))>>32; + ///w = ((uint64_t)(u->a[x->r_i + 1]))>>32; + if(p_v == (uint32_t)-1) + { + p_v = v; + continue; + } + + + av = asg_arc_a(read_sg, p_v); + nv = asg_arc_n(read_sg, p_v); + l = 0; + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == v) + { + l = asg_arc_len(av[k]); + break; + } + } + if(k == nv) fprintf(stderr, "ERROR\n"); + len += l; + if(len_thre && occ && len >= (*len_thre)) + { + (*occ) = idx; + return len; + } + p_v = v; + } + } + } + + if(ignore_end == 0 && p_v != (uint32_t)-1) + { + len += read_sg->seq[p_v>>1].len; + if(len_thre && occ && len >= (*len_thre)) + { + (*occ) = idx; + return len; + } + } + + if(len_thre && occ) + { + (*occ) = idx; + } + + return len; +} + +uint32_t set_utg_offset(uint32_t *a, uint32_t a_n, ma_ug_t *ug, asg_t *read_sg, uint64_t* pos_idx, uint32_t is_clear, +uint32_t only_len) +{ + uint32_t ori, uid, v, nv, l, k; + ///uint32_t *a = b->b.a, a_n = b->b.n; + uint32_t u_i, r_i, len, p_v; + asg_arc_t *av = NULL; + ma_utg_t* u = NULL; + for (u_i = r_i = len = 0, p_v = (uint32_t)-1; u_i < a_n; u_i++) + { + uid = a[u_i] >> 1; + ori = a[u_i] & 1; + u = &(ug->u.a[uid]); + if(u->n == 0) continue; + + for (r_i = 0; r_i < u->n; r_i++) + { + l = 0; + v = (ori == 1?((uint64_t)((u->a[u->n - r_i - 1])^(uint64_t)(0x100000000)))>>32:((uint64_t)(u->a[r_i]))>>32); + + if(p_v != (uint32_t)-1 && is_clear == 0) + { + av = asg_arc_a(read_sg, p_v); + nv = asg_arc_n(read_sg, p_v); + + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == v) + { + l = asg_arc_len(av[k]); + break; + } + } + if(k == nv) fprintf(stderr, "ERROR-set_utg_offset\n"); + } + + p_v = v; len += l; + if(only_len) continue; + + if(is_clear == 1) + { + pos_idx[v>>1] = (uint64_t)-1; + } + else + { + pos_idx[v>>1] = len; + pos_idx[v>>1] <<= 32; + pos_idx[v>>1] |= (uint64_t)v; + } + } + } + + if(p_v != (uint32_t)-1) len += read_sg->seq[p_v>>1].len; + + return len; +} + + + +void print_buf_t(ma_ug_t *ug, buf_t* x, const char* command) +{ + fprintf(stderr, "%s\n", command); + uint32_t i, ori; + ma_utg_t* u = NULL; + for (i = 0; i < x->b.n; i++) + { + u = &(ug->u.a[x->b.a[i]>>1]); + if(u->n == 0) continue; + ori = x->b.a[i] & 1; + fprintf(stderr, "utg%.6ul\tori:%u\tocc:%u\tlen:%u\n", (x->b.a[i]>>1)+1, ori, (uint32_t)u->n, u->len); + } +} + +#define origin_trans_key(a) ((a).weight) +KRADIX_SORT_INIT(origin_trans_sort, asg_arc_t_offset, origin_trans_key, member_size(asg_arc_t_offset, weight)) + +#define origin_trans_el_key(a) ((a).x.el) +KRADIX_SORT_INIT(origin_trans_el_sort, asg_arc_t_offset, origin_trans_el_key, 1) + + +void refine_u_trans_t(u_trans_hit_t *q, kv_ca_buf_t* cb) +{ + ///already know [qScur, qEcur), [qSpre, qEpre) + uint32_t s, e, i, si, ei; + s = q->qScur; e = q->qEcur;///[s, e) + for (i = 0, si = ei = cb->n; i < cb->n; i++) + { + if(cb->a[i].c_x_p > s && si == cb->n) + { + si = i; + } + + if(cb->a[i].c_x_p > (e-1) && ei == cb->n) + { + ei = i; + } + + if(si != cb->n && ei != cb->n) break; + } + + if(si == 0 || ei == 0) fprintf(stderr, "ERROR-si-ei-0\n"); + if(si >= cb->n || ei >= cb->n) fprintf(stderr, "ERROR-si-ei-1\n"); + si--; ei--; + + if(s < cb->a[si].c_x_p || ((si + 1) < cb->n && s >= cb->a[si + 1].c_x_p)) + { + fprintf(stderr, "ERROR3\n"); + } + if(e < cb->a[ei].c_x_p || ((ei + 1) < cb->n && e > cb->a[ei + 1].c_x_p)) + { + fprintf(stderr, "ERROR4\n"); + } + ///si and ei must be less than (cb->n-1) + // q->tScur = cb->a[si].c_y_p + ((cb->a[si+1].c_y_p - cb->a[si].c_y_p) + // *(double)((double)(s - cb->a[si].c_x_p)/(double)(cb->a[si+1].c_x_p - cb->a[si].c_x_p))); + q->tScur = cb->a[si].c_y_p + + get_offset_adjust(s-cb->a[si].c_x_p, cb->a[si+1].c_x_p-cb->a[si].c_x_p, cb->a[si+1].c_y_p-cb->a[si].c_y_p); + + + // q->tEcur = cb->a[ei].c_y_p + ((cb->a[ei+1].c_y_p - cb->a[ei].c_y_p) + // *(double)((double)(e - cb->a[ei].c_x_p)/(double)(cb->a[ei+1].c_x_p - cb->a[ei].c_x_p))); + q->tEcur = cb->a[ei].c_y_p + + get_offset_adjust(e-cb->a[ei].c_x_p, cb->a[ei+1].c_x_p-cb->a[ei].c_x_p, cb->a[ei+1].c_y_p-cb->a[ei].c_y_p); + + + + ///might be equal + if(q->tScur > q->tEcur) fprintf(stderr, "ERROR5\n"); + // if(q->tScur >= q->tEcur) + // { + // fprintf(stderr, "\n###q->tScur: %u, s: %u, si: %u, q->tEcur: %u, e: %u, ei: %u\n", + // q->tScur, s, si, q->tEcur, e, ei); + + // fprintf(stderr, "###cb->a[si].c_x_p: %u, cb->a[si].c_y_p: %u, cb->a[si+1].c_x_p: %u, cb->a[si+1].c_y_p: %u\n", + // cb->a[si].c_x_p, cb->a[si].c_y_p, cb->a[si+1].c_x_p, cb->a[si+1].c_y_p); + + // fprintf(stderr, "###cb->a[ei].c_x_p: %u, cb->a[ei].c_y_p: %u, cb->a[ei+1].c_x_p: %u, cb->a[ei+1].c_y_p: %u\n", + // cb->a[ei].c_x_p, cb->a[ei].c_y_p, cb->a[ei+1].c_x_p, cb->a[ei+1].c_y_p); + + // fprintf(stderr, "ERROR5\n"); + // } +} + + + +///[ts, te) +void extract_sub_overlaps(uint32_t i_tScur, uint32_t i_tEcur, uint32_t i_tSpre, uint32_t i_tEpre, +uint32_t tn, kv_u_trans_hit_t* ktb, uint32_t bn) +{ + uint32_t i, ovlp, found, beg, end, offS, offE; + u_trans_hit_t *q = NULL, x; + for (i = found = 0; i < bn; i++) + { + q = &(ktb->a[i]);///for q, already know [qScur, qEcur), [qSpre, qEpre), [tScur, tEcur) + + ovlp = ((MIN(i_tEcur, q->tEcur) > MAX(i_tScur, q->tScur))? + MIN(i_tEcur, q->tEcur) - MAX(i_tScur, q->tScur):0); + if(found == 1 && ovlp == 0) break; + if(ovlp > 0) found = 1; + if(ovlp == 0) continue; + + + beg = MAX(i_tScur, q->tScur); end = MIN(i_tEcur, q->tEcur); + offS = beg - q->tScur; offE = q->tEcur - end; + x.tScur = q->tScur + offS; + x.tEcur = q->tEcur - offE; + //x.qScur = q->qScur + offS; + x.qScur = q->qScur + get_offset_adjust(offS, q->tEcur-q->tScur, q->qEcur-q->qScur); + ///x.qEcur = q->qEcur - offE; + x.qScur = q->qEcur - get_offset_adjust(offE, q->tEcur-q->tScur, q->qEcur-q->qScur); + + x.qn = q->qn; + offS = beg - q->tScur; offE = q->tEcur - end; + if((x.qn&1) == 0) + { + // x.qSpre = q->qSpre + offS; + x.qSpre = q->qSpre + get_offset_adjust(offS, q->tEcur-q->tScur, q->qEpre-q->qSpre); + // x.qEpre = q->qEpre - offE; + x.qEpre = q->qEpre - get_offset_adjust(offE, q->tEcur-q->tScur, q->qEpre-q->qSpre); + } + else + { + // x.qSpre = q->qSpre + offE; + x.qSpre = q->qSpre + get_offset_adjust(offE, q->tEcur-q->tScur, q->qEpre-q->qSpre); + // x.qEpre = q->qEpre - offS; + x.qEpre = q->qEpre - get_offset_adjust(offS, q->tEcur-q->tScur, q->qEpre-q->qSpre); + } + + x.tn = tn; + offS = beg - i_tScur; offE = i_tEcur - end; + if((x.tn&1) == 0) + { + // x.tSpre = i_tSpre + offS; + x.tSpre = i_tSpre + get_offset_adjust(offS, i_tEcur-i_tScur, i_tEpre-i_tSpre); + // x.tEpre = i_tEpre - offE; + x.tEpre = i_tEpre - get_offset_adjust(offE, i_tEcur-i_tScur, i_tEpre-i_tSpre); + } + else + { + // x.tSpre = i_tSpre + offE; + x.tSpre = i_tSpre + get_offset_adjust(offE, i_tEcur-i_tScur, i_tEpre-i_tSpre); + // x.tEpre = i_tEpre - offS; + x.tEpre = i_tEpre - get_offset_adjust(offS, i_tEcur-i_tScur, i_tEpre-i_tSpre); + } + + kv_push(u_trans_hit_t, *ktb, x); + + // if(x.tSpre >= x.tEpre || x.qSpre >= x.qEpre) + // { + // fprintf(stderr, "\n*********x.qn: %u, x.tn: %u\n", x.qn, x.tn); + // fprintf(stderr, "x.qSpre: %u, x.qEpre: %u, x.tSpre: %u, x.tEpre: %u\n", + // x.qSpre, x.qEpre, x.tSpre, x.tEpre); + // fprintf(stderr, "q->qScur: %u, q->qEcur: %u, q->qSpre: %u, q->qEpre: %u\n", + // q->qScur, q->qEcur, q->qSpre, q->qEpre); + // fprintf(stderr, "q->tScur: %u, q->tEcur: %u, q->tSpre: %u, q->tEpre: %u\n", + // q->tScur, q->tEcur, q->tSpre, q->tEpre); + // fprintf(stderr, "i_tScur: %u, i_tEcur: %u, i_tSpre: %u, i_tEpre: %u\n", + // i_tScur, i_tEcur, i_tSpre, i_tEpre); + // } + } +} + + + +void reset_u_trans_hit_idx(u_trans_hit_idx *t, uint32_t* i_x_a, uint32_t i_x_n, ma_ug_t *i_ug, +asg_t *i_read_sg, trans_chain* i_t_ch, uint32_t i_cBeg, uint32_t i_cEnd) +{ + t->a = i_x_a; + t->an = i_x_n; + t->ug = i_ug; + t->read_sg = i_read_sg; + t->t_ch = i_t_ch; + t->cBeg = i_cBeg; + t->cEnd = i_cEnd; + t->u_i = t->r_i = t->len = t->s_pos_cur = t->s_pre_v = t->s_pre_w = 0; + t->p_v = t->p_uId = t->p_idx = (uint32_t)-1; +} + +uint32_t get_u_trans_hit(u_trans_hit_idx *t, u_trans_hit_t *hit) +{ + uint32_t uid, ori, l, v, nv, is_update, r_beg, r_end, ovlp; + uint32_t *a = t->a, a_n = t->an, k, c_uId, idx, offPre; + ma_utg_t *u = NULL; + asg_arc_t *av = NULL; + hit->qSpre = hit->qEpre = hit->qScur = hit->qEcur = hit->qn = (uint32_t)-1; + hit->tSpre = hit->tEpre = hit->tScur = hit->tEcur = hit->tn = (uint32_t)-1; + + while (t->u_i < a_n) ///(u_i = 0; u_i < a_n; u_i++) + { + uid = a[t->u_i] >> 1; + ori = a[t->u_i] & 1; + u = &(t->ug->u.a[uid]); + if(u->n == 0) continue; + + while(t->r_i < u->n) ///for (r_i = 0; r_i < u->n; r_i++) + { + l = 0; + v = (ori == 1?((uint64_t)((u->a[u->n-t->r_i-1])^(uint64_t)(0x100000000)))>>32:((uint64_t)(u->a[t->r_i]))>>32); + + if(t->p_v != (uint32_t)-1) + { + av = asg_arc_a(t->read_sg, t->p_v); + nv = asg_arc_n(t->read_sg, t->p_v); + + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == v) + { + l = asg_arc_len(av[k]); + break; + } + } + if(k == nv) fprintf(stderr, "ERROR-nv\n"); + } + + ///[t->cBeg, t->cEnd) + r_beg = t->len; r_end = t->len + + (t->p_v != (uint32_t)-1? t->read_sg->seq[t->p_v>>1].len : 0); + ovlp = ((MIN(t->cEnd, r_end) > MAX(t->cBeg, r_beg))? (MIN(t->cEnd, r_end) - MAX(t->cBeg, r_beg)) : 0); + c_uId = get_origin_uid(v, t->t_ch, &offPre, &idx); + + + if(ovlp == 0) + { + if(r_beg >= t->cEnd) + { + if(t->p_uId != (uint32_t)-1) + { + hit->qn = t->p_uId; + hit->qScur = t->s_pos_cur; hit->qEcur = t->len + t->read_sg->seq[t->p_v>>1].len; + + + ovlp = ((MIN(t->cEnd, hit->qEcur) > MAX(t->cBeg, hit->qScur))? + (MIN(t->cEnd, hit->qEcur) - MAX(t->cBeg, hit->qScur)) : 0); + if(ovlp == 0) return 0; + + + ///[t->s_pre_v, t->p_v] + uint32_t a_pos, b_pos; + get_origin_uid(t->s_pre_v, t->t_ch, &a_pos, NULL); + get_origin_uid(t->p_v, t->t_ch, &b_pos, NULL); + hit->qSpre = MIN(a_pos, b_pos); + hit->qEpre = MAX((a_pos + t->read_sg->seq[t->s_pre_v>>1].len), (b_pos+t->read_sg->seq[t->p_v>>1].len)); + + ///[t->cBeg, t->cEnd) + if(hit->qScur < t->cBeg) + { + if((hit->qn&1) == 0) + { + ///hit->qSpre += (t->cBeg - hit->qScur); + hit->qSpre += get_offset_adjust(t->cBeg - hit->qScur, + hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); + } + else + { + ///hit->qEpre -= (t->cBeg - hit->qScur); + hit->qEpre -= get_offset_adjust(t->cBeg - hit->qScur, + hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); + } + hit->qScur = t->cBeg; + } + + if(hit->qEcur > t->cEnd) + { + if((hit->qn&1) == 0) + { + ///hit->qEpre -= (hit->qEcur - t->cEnd); + hit->qEpre -= get_offset_adjust(hit->qEcur - t->cEnd, + hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); + } + else + { + // hit->qSpre += (hit->qEcur - t->cEnd); + hit->qSpre += get_offset_adjust(hit->qEcur - t->cEnd, + hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); + } + hit->qEcur = t->cEnd; + } + t->p_uId = (uint32_t)-1; + return 1; + } + return 0; + } + else + { + t->p_uId = c_uId; t->s_pos_cur = t->len + l; t->s_pre_v = v; + t->p_v = v; t->len += l; t->p_idx = idx; + t->r_i++; + continue; + } + } + + + is_update = 0; + if(t->p_uId != c_uId) + { + is_update = 1; + + } + else///p_uId == c_uId + { + if((t->p_uId&1) == 0) ///forward + { + if(idx != (t->p_idx+1)) + { + is_update = 1; + } + } + else //backward + { + if((idx + 1) != t->p_idx) + { + is_update = 1; + } + } + } + + if(is_update) + { + if(t->p_uId != (uint32_t)-1) + { + hit->qn = t->p_uId; + hit->qScur = t->s_pos_cur; hit->qEcur = t->len + t->read_sg->seq[t->p_v>>1].len; + ///[t->s_pre_v, t->p_v] + uint32_t a_pos, b_pos; + get_origin_uid(t->s_pre_v, t->t_ch, &a_pos, NULL); + get_origin_uid(t->p_v, t->t_ch, &b_pos, NULL); + hit->qSpre = MIN(a_pos, b_pos); + hit->qEpre = MAX((a_pos + t->read_sg->seq[t->s_pre_v>>1].len), (b_pos+t->read_sg->seq[t->p_v>>1].len)); + + ///[t->cBeg, t->cEnd) + if(hit->qScur < t->cBeg) + { + if((hit->qn&1) == 0) + { + ///hit->qSpre += (t->cBeg - hit->qScur); + hit->qSpre += get_offset_adjust(t->cBeg - hit->qScur, + hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); + } + else + { + ///hit->qEpre -= (t->cBeg - hit->qScur); + hit->qEpre -= get_offset_adjust(t->cBeg - hit->qScur, + hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); + } + hit->qScur = t->cBeg; + } + + if(hit->qEcur > t->cEnd) + { + if((hit->qn&1) == 0) + { + ///hit->qEpre -= (hit->qEcur - t->cEnd); + hit->qEpre -= get_offset_adjust(hit->qEcur - t->cEnd, + hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); + } + else + { + // hit->qSpre += (hit->qEcur - t->cEnd); + hit->qSpre += get_offset_adjust(hit->qEcur - t->cEnd, + hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); + } + hit->qEcur = t->cEnd; + } + + + t->p_uId = c_uId; t->s_pos_cur = t->len + l; t->s_pre_v = v; + t->p_v = v; t->len += l; t->p_idx = idx; + t->r_i++; + return 1; + } + t->p_uId = c_uId; t->s_pos_cur = t->len + l; t->s_pre_v = v; + } + + t->p_v = v; t->len += l; t->p_idx = idx; + t->r_i++; + } + t->r_i = 0; + t->u_i++; + } + + if(t->p_uId != (uint32_t)-1) + { + hit->qn = t->p_uId; + hit->qScur = t->s_pos_cur; hit->qEcur = t->len + t->read_sg->seq[t->p_v>>1].len; + + + ovlp = ((MIN(t->cEnd, hit->qEcur) > MAX(t->cBeg, hit->qScur))? + (MIN(t->cEnd, hit->qEcur) - MAX(t->cBeg, hit->qScur)) : 0); + if(ovlp == 0) return 0; + + + ///[t->s_pre_v, t->p_v] + uint32_t a_pos, b_pos; + get_origin_uid(t->s_pre_v, t->t_ch, &a_pos, NULL); + get_origin_uid(t->p_v, t->t_ch, &b_pos, NULL); + hit->qSpre = MIN(a_pos, b_pos); + hit->qEpre = MAX((a_pos + t->read_sg->seq[t->s_pre_v>>1].len), (b_pos+t->read_sg->seq[t->p_v>>1].len)); + + ///[t->cBeg, t->cEnd) + if(hit->qScur < t->cBeg) + { + if((hit->qn&1) == 0) + { + ///hit->qSpre += (t->cBeg - hit->qScur); + hit->qSpre += get_offset_adjust(t->cBeg - hit->qScur, + hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); + } + else + { + ///hit->qEpre -= (t->cBeg - hit->qScur); + hit->qEpre -= get_offset_adjust(t->cBeg - hit->qScur, + hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); + } + hit->qScur = t->cBeg; + } + + if(hit->qEcur > t->cEnd) + { + if((hit->qn&1) == 0) + { + ///hit->qEpre -= (hit->qEcur - t->cEnd); + hit->qEpre -= get_offset_adjust(hit->qEcur - t->cEnd, + hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); + } + else + { + // hit->qSpre += (hit->qEcur - t->cEnd); + hit->qSpre += get_offset_adjust(hit->qEcur - t->cEnd, + hit->qEcur-hit->qScur, hit->qEpre-hit->qSpre); + } + hit->qEcur = t->cEnd; + } + + t->p_uId = (uint32_t)-1; + return 1; + } + return 0; +} + + +void chain_origin_trans_uid_by_distance(hap_cov_t *cov, asg_t *read_sg, +uint32_t *pri_a, uint32_t pri_n, uint32_t pri_beg, uint64_t *i_pri_len, +uint32_t *aux_a, uint32_t aux_n, uint32_t aux_beg, uint64_t *i_aux_len, +ma_ug_t *ug, uint32_t flag, double score, const char* cmd) +{ + uint32_t i, len, bn; + uint64_t pri_len, aux_len; + kvec_asg_arc_t_offset* u_buffer = &(cov->u_buffer); + kvec_t_i32_warp* tailIndex = &(cov->tailIndex); + trans_chain* t_ch = cov->t_ch; + asg_arc_t_offset *tt = NULL; + ca_buf_t *tx = NULL; + + if(i_pri_len) pri_len = (*i_pri_len); + else pri_len = set_utg_offset(pri_a, pri_n, ug, read_sg, cov->pos_idx, 0, 1); + + if(i_aux_len) aux_len = (*i_aux_len); + else aux_len = set_utg_offset(aux_a, aux_n, ug, read_sg, cov->pos_idx, 0, 1); + + tt = NULL; t_ch->c_buf.n = 0; t_ch->k_t_b.n = 0; + if(tailIndex->a.n > 0) tt = &(u_buffer->a.a[tailIndex->a.a[0]]); + if(!tt || (pri_beg < (tt->Off>>32) && aux_beg < ((uint32_t)tt->Off))) + { + kv_pushp(ca_buf_t, t_ch->c_buf, &tx); + tx->c_x_p = pri_beg; + tx->c_y_p = aux_beg; + + for (i = 0; i < tailIndex->a.n; i++) + { + tt = &(u_buffer->a.a[tailIndex->a.a[i]]); + kv_pushp(ca_buf_t, t_ch->c_buf, &tx); + + tx->c_x_p = tt->Off>>32; + tx->c_y_p = (uint32_t)tt->Off; + } + } + else if(tailIndex->a.n == 1)//1 ele in chain + { + kv_pushp(ca_buf_t, t_ch->c_buf, &tx); + tx->c_x_p = pri_beg; tx->c_y_p = aux_beg; + } + else if(tailIndex->a.n > 0) + { + uint32_t cx, cy, ax, ay, found = 0; + for (i = 0; i < tailIndex->a.n; i++) + { + cx = cy = ax = ay = (uint32_t)-1; + + cx = u_buffer->a.a[tailIndex->a.a[i]].Off>>32; + cy = (uint32_t)u_buffer->a.a[tailIndex->a.a[i]].Off; + if((i + 1) < tailIndex->a.n) + { + ax = u_buffer->a.a[tailIndex->a.a[i+1]].Off>>32; + ay = (uint32_t)u_buffer->a.a[tailIndex->a.a[i+1]].Off; + } + + kv_pushp(ca_buf_t, t_ch->c_buf, &tx); + tx->c_x_p = cx; tx->c_y_p = cy; + + if(found) continue; + if(pri_beg > cx && pri_beg < ax && aux_beg > cy && aux_beg < ay) + { + kv_pushp(ca_buf_t, t_ch->c_buf, &tx); + tx->c_x_p = pri_beg; tx->c_y_p = aux_beg; + found = 1; + } + } + } + + + // fprintf(stderr, "\ncmd-%s\n", cmd); + // fprintf(stderr, "pri_beg=%u, pri_len=%lu\n", pri_beg, pri_len); + // fprintf(stderr, "aux_beg=%u, aux_len=%lu\n", aux_beg, aux_len); + + // print_buf_t(ug, pri, "pri"); + // print_buf_t(ug, aux, "aux"); + + + tx = &(t_ch->c_buf.a[t_ch->c_buf.n-1]); + len = MIN(pri_len - tx->c_x_p, aux_len - tx->c_y_p); + if(len > 0)///insert boundary + { + kv_pushp(ca_buf_t, t_ch->c_buf, &tx); + tx->c_x_p = t_ch->c_buf.a[t_ch->c_buf.n-2].c_x_p + len; + tx->c_y_p = t_ch->c_buf.a[t_ch->c_buf.n-2].c_y_p + len; + } + + tx = &(t_ch->c_buf.a[0]);///insert boundary + if(tx->c_x_p != 0 && tx->c_y_p != 0)///already at boundary + { + len = MIN(tx->c_x_p, tx->c_y_p);///offset + kv_pushp(ca_buf_t, t_ch->c_buf, &tx); + for (i = 0; (i + 1)< t_ch->c_buf.n; i++) + { + t_ch->c_buf.a[t_ch->c_buf.n - i - 1] = t_ch->c_buf.a[t_ch->c_buf.n - i - 2]; + } + t_ch->c_buf.a[0].c_x_p = t_ch->c_buf.a[1].c_x_p - len; + t_ch->c_buf.a[0].c_y_p = t_ch->c_buf.a[1].c_y_p - len; + } + + ///chain is [s, e) + if(t_ch->c_buf.a[0].c_x_p != 0 && t_ch->c_buf.a[0].c_y_p != 0) fprintf(stderr, "ERROR1\n"); + if(t_ch->c_buf.a[t_ch->c_buf.n-1].c_x_p!= pri_len && + t_ch->c_buf.a[t_ch->c_buf.n-1].c_y_p!= aux_len) + { + fprintf(stderr, "ERROR2\n"); + } + + u_trans_hit_idx iter; + u_trans_hit_t hit, *kh = NULL; + ////////prx + reset_u_trans_hit_idx(&iter, pri_a, pri_n, ug, read_sg, t_ch, + t_ch->c_buf.a[0].c_x_p, t_ch->c_buf.a[t_ch->c_buf.n-1].c_x_p); + while(get_u_trans_hit(&iter, &hit))//get [qScur, qEcur), [qSpre, qEpre) + { + refine_u_trans_t(&hit, &(t_ch->c_buf)); ///get [tScur, tEcur) + kv_push(u_trans_hit_t, t_ch->k_t_b, hit); + } + bn = t_ch->k_t_b.n; + + ////////aux + reset_u_trans_hit_idx(&iter, aux_a, aux_n, ug, read_sg, t_ch, + t_ch->c_buf.a[0].c_y_p, t_ch->c_buf.a[t_ch->c_buf.n-1].c_y_p); + while(get_u_trans_hit(&iter, &hit)) + { + extract_sub_overlaps(hit.qScur, hit.qEcur, hit.qSpre, hit.qEpre, hit.qn, &(t_ch->k_t_b), bn); + } + + + if(t_ch->k_t_b.n - bn == 0) fprintf(stderr, "ERROR6\n"); + + + + u_trans_t *kt = NULL; + double x_score, y_score; + for (i = bn; i < t_ch->k_t_b.n; i++) + { + kh = &(t_ch->k_t_b.a[i]); + if(kh->qEpre <= kh->qSpre) continue; + if(kh->tEpre <= kh->tSpre) continue; + kv_pushp(u_trans_t, t_ch->k_trans, &kt); + kt->f = flag; kt->rev = ((kh->qn ^ kh->tn) & 1); kt->del = 0; + kt->qn = kh->qn>>1; kt->qs = kh->qSpre; kt->qe = kh->qEpre; + kt->tn = kh->tn>>1; kt->ts = kh->tSpre; kt->te = kh->tEpre; + if(score < 0) + { + kt->nw = (MIN((kt->qe - kt->qs), (kt->te - kt->ts)))*CHAIN_MATCH; + } + else + { + x_score = ((double)(kt->qe-kt->qs)/(double)(t_ch->c_buf.a[t_ch->c_buf.n-1].c_x_p-t_ch->c_buf.a[0].c_x_p))*score; + y_score = ((double)(kt->te-kt->ts)/(double)(t_ch->c_buf.a[t_ch->c_buf.n-1].c_y_p-t_ch->c_buf.a[0].c_y_p))*score; + kt->nw = MIN(x_score, y_score); + } + } + + +} + + +void collect_trans_cov(const char* cmd, buf_t* pri, uint64_t pri_offset, buf_t* aux, uint64_t aux_offset, +ma_ug_t *ug, asg_t *read_sg, hap_cov_t *cov) +{ + uint32_t i, k, rid, occ, ori, thre_pri; + uint64_t len_aux, uLen, uCov; + ma_utg_t* u = NULL; + trans_chain* t_ch = cov->t_ch; + if(pri->b.n == 0 || aux->b.n == 0) return; + + len_aux = set_utg_offset(aux->b.a, aux->b.n, ug, read_sg, cov->pos_idx, 0, 0); + chain_trans_ovlp(cov, NULL, ug, read_sg, pri, len_aux, &thre_pri); + if(thre_pri > 0) + { + /*******************************for debug************************************/ + // fprintf(stderr, "\n%s, thre_pri: %u, len_aux: %lu\n", cmd, thre_pri, len_aux); + // print_buf_t(ug, pri, "pri"); + // print_buf_t(ug, aux, "aux"); + /*******************************for debug************************************/ + + if(t_ch) + { + chain_origin_trans_uid_by_distance(cov, read_sg, pri->b.a, pri->b.n, pri_offset, NULL, + aux->b.a, aux->b.n, aux_offset, &len_aux, ug, RC_1, -1024, cmd); + } + + + for (i = uCov = 0; i < aux->b.n; i++) + { + u = &(ug->u.a[aux->b.a[i]>>1]); + if(u->n == 0) continue; + ori = aux->b.a[i] & 1; + for (k = 0; k < u->n; k++) + { + rid = (ori == 1?(u->a[u->n-k-1]>>33):(u->a[k]>>33)); + uCov += cov->cov[rid]; + + if(t_ch) t_ch->ir_het[(ori == 1?(u->a[u->n-k-1]>>33):(u->a[k]>>33))] |= P_HET; + } + } + + for (i = uLen = occ = 0; i < pri->b.n; i++) + { + u = &(ug->u.a[pri->b.a[i]>>1]); + if(u->n == 0) continue; + ori = pri->b.a[i] & 1; + for (k = 0; k < u->n; k++, occ++) + { + if(occ >= thre_pri) break; + ///rid = u->a[k]>>33; + rid = (ori == 1?(u->a[u->n-k-1]>>33):(u->a[k]>>33)); + uLen += read_sg->seq[rid].len; + + if(t_ch) t_ch->ir_het[(ori == 1?(u->a[u->n-k-1]>>33):(u->a[k]>>33))] |= P_HET; + } + if(occ >= thre_pri) break; + } + + uCov = (uLen == 0? 0 : uCov / uLen); + + for (i = occ = 0; i < pri->b.n; i++) + { + u = &(ug->u.a[pri->b.a[i]>>1]); + if(u->n == 0) continue; + ori = pri->b.a[i] & 1; + for (k = 0; k < u->n; k++, occ++) + { + if(occ >= thre_pri) break; + ///rid = u->a[k]>>33; + rid = (ori == 1?(u->a[u->n-k-1]>>33):(u->a[k]>>33)); + cov->cov[rid] += (uCov * read_sg->seq[rid].len); + } + if(occ >= thre_pri) break; + } + } + set_utg_offset(aux->b.a, aux->b.n, ug, read_sg, cov->pos_idx, 1, 0); +} + + +int asg_arc_cut_long_equal_tips_assembly_complex(asg_t *g, ma_hit_t_alloc* reverse_sources, +long long miniedgeLen, uint32_t stops_threshold, R_to_U* ruIndex) +{ + double startTime = Get_T(); + ///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, convex, flag; + long long ll, max_stopLen; + + buf_t b; + memset(&b, 0, sizeof(buf_t)); + + for (v = 0; v < n_vtx; ++v) + { + + uint32_t i; + ///some node could be deleted + if (g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + ///tip + if (get_real_length(g, v, NULL) != 0) continue; + if(get_real_length(g, v^1, NULL) != 1) continue; + flag = detect_single_path_with_dels_contigLen(g, v^1, &convex, &ll, NULL); + if(flag != TWO_INPUT && flag != MUL_INPUT) continue; + convex = convex^1; + ///uint32_t n_convex = asg_arc_n(g, convex), convexLen = ll; + uint32_t n_convex = asg_arc_n(g, convex), convexLen = (uint32_t)-1, convex_i = (uint32_t)-1; + asg_arc_t *a_convex = asg_arc_a(g, convex); + for (i = 0; i < n_convex; i++) + { + if (!a_convex[i].del) + { + detect_single_path_with_dels_contigLen(g, a_convex[i].v, &convex, &ll, NULL); + if(convex == v) + { + convexLen = ll; + convex_i = i; + break; + } + } + } + + + for (i = 0; i < n_convex; i++) + { + if (!a_convex[i].del) + { + if(i == convex_i) continue; + + detect_single_path_with_dels_contigLen_complex(g, a_convex[i].v, &convex, &ll, + &max_stopLen, NULL, stops_threshold); + ///threshold = 0.8 + if(ll > convexLen && max_stopLen*1.25>ll) + { + ///keep all nodes of this tip + b.b.n = 0; + detect_single_path_with_dels_contigLen(g, v^1, &convex, &ll, &b); + if(b.b.n < 2) break; + b.b.n--; + ///keep all nodes of this tip + + //we can only cut tips + if(check_if_diploid_primary_complex(v^1, a_convex[i].v, g, + reverse_sources, miniedgeLen, stops_threshold, 1, ruIndex)==1) + { + n_reduced++; + uint64_t k; + + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]].c = ALTER_LABLE; + } + for (k = 0; k < b.b.n; k++) + { + asg_seq_drop(g, b.b.a[k]); + } + + + ///lable the primary one + b.b.n = 0; + detect_single_path_with_dels_contigLen_complex(g, a_convex[i].v, &convex, + &ll, &max_stopLen, &b, stops_threshold); + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]].c = HAP_LABLE; + } + + break; + } + + } + + } + } + } + + + asg_cleanup(g); + asg_symm(g); + free(b.b.a); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d long tips\n", + __func__, n_reduced); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + + return n_reduced; +} + + +void output_unitig_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, R_to_U* ruIndex, int max_hang, int min_ovlp) +{ + kvec_asg_arc_t_warp new_rtg_edges; + kv_init(new_rtg_edges.a); + + ma_ug_t *ug = NULL; + ug = ma_ug_gen(sg); + ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 1); + + fprintf(stderr, "Writing raw unitig GFA to disk... \n"); + char* gfa_name = (char*)malloc(strlen(output_file_name)+25); + sprintf(gfa_name, "%s.r_utg.gfa", output_file_name); + FILE* output_file = fopen(gfa_name, "w"); + ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + fclose(output_file); + sprintf(gfa_name, "%s.r_utg.noseq.gfa", output_file_name); + output_file = fopen(gfa_name, "w"); + ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + fclose(output_file); + if(asm_opt.bed_inconsist_rate != 0) + { + sprintf(gfa_name, "%s.r_utg.lowQ.bed", output_file_name); + output_file = fopen(gfa_name, "w"); + ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, + max_hang, min_ovlp, asm_opt.bed_inconsist_rate, "utg", output_file, NULL); + fclose(output_file); + } + + free(gfa_name); + ma_ug_destroy(ug); + kv_destroy(new_rtg_edges.a); +} + +void set_ug_coverage_aggressive(ma_ug_t *ug, uint32_t uID, asg_t* read_g, +const ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag, +uint8_t* is_r_het, long long het_cov_thres) +{ + ma_utg_t *u = &(ug->u.a[uID]); + uint32_t k, j, rId, tn, is_Unitig; + long long R_bases = 0, C_bases = 0; + long long cov_in_s, cov_in_e, cov_out_s, cov_out_e, cov_in, cov_out, try_cov, cen_cov; + uint32_t nv, i; + asg_arc_t *av = NULL; + ma_hit_t *h; + if(u->m == 0) return; + + ///set + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 1; + } + + for (i = 0; i < 2; i++) + { + nv = asg_arc_n(ug->g, (uID<<1)+i); + av = asg_arc_a(ug->g, (uID<<1)+i); + for (j = 0; j < nv; j++) + { + u = &(ug->u.a[av[j].v>>1]); + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 2; + } + } + } + + + u = &(ug->u.a[uID]); + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + cov_in = cov_out = 0; + cov_in_s = cov_in_e = cov_out_s = cov_out_e = 0; + for (j = 0; j < (uint64_t)(sources[rId].length); j++) + { + h = &(sources[rId].buffer[j]); + ///if(h->del) continue; + if(h->el != 1) continue; + tn = Get_tn((*h)); + if(read_g->seq[tn].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + if(read_g->seq[tn].del == 1) continue; + if(r_flag[tn] == 0) continue; + if(r_flag[tn] == 1) + { + cov_in += (Get_qe((*h)) - Get_qs((*h))); + if(((Get_qs((*h)) <= coverage_cut[rId].s))) cov_in_s++; + if(((Get_qe((*h)) >= coverage_cut[rId].e))) cov_in_e++; + } + + if(r_flag[tn] == 2) + { + cov_out += (Get_qe((*h)) - Get_qs((*h))); + if(((Get_qs((*h)) <= coverage_cut[rId].s))) cov_out_s++; + if(((Get_qe((*h)) >= coverage_cut[rId].e))) cov_out_e++; + } + } + + if(cov_out_s >= cov_out_e) ///more out overlap from s + { + cen_cov = cov_in_e; + try_cov = cov_in_s + cov_out_s; + } + else ///more out overlap from e + { + cen_cov = cov_in_s; + try_cov = cov_in_e + cov_out_e; + } + + if(cov_out <= (cov_in*0.1)) + { + C_bases = cov_in + cov_out; + R_bases = (coverage_cut[rId].e - coverage_cut[rId].s); + } + else if((try_cov <= cen_cov*1.1) && (MIN(cov_out_s, cov_out_e)<=((MAX(cov_out_s, cov_out_e))*0.2))) + { + C_bases = cov_in + cov_out; + R_bases = (coverage_cut[rId].e - coverage_cut[rId].s); + } + else + { + C_bases = cen_cov; + R_bases = 1; + } + + if((R_bases <= 0) || ((C_bases/R_bases) <= het_cov_thres)) + { + is_r_het[rId] |= C_HET; + } + } + + + ///reset + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 0; + } + + for (i = 0; i < 2; i++) + { + nv = asg_arc_n(ug->g, (uID<<1)+i); + av = asg_arc_a(ug->g, (uID<<1)+i); + for (j = 0; j < nv; j++) + { + u = &(ug->u.a[av[j].v>>1]); + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 0; + } + } + } +} + + +void set_r_het_flag(ma_ug_t *ug, asg_t *sg, ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* is_r_het) +{ + uint64_t m, dip_thre_max, dip_thres; + uint8_t* primary_flag = (uint8_t*)calloc(sg->n_seq, sizeof(uint8_t)); + + if(asm_opt.hom_global_coverage_set) + { + dip_thre_max = asm_opt.hom_global_coverage; + } + else + { + dip_thre_max = ((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE); + } + // dip_thre_max *= 0.75; + dip_thre_max = (double)(dip_thre_max) - (((double)(dip_thre_max)*0.5)/asm_opt.polyploidy); + + // fprintf(stderr, "dip_thre_max: %lu\n", dip_thre_max); + + for (m = 0; m < ug->g->n_seq; m++) + { + dip_thres = dip_thre_max; + ///if(ug->u.a[m].n <= dip_thre_max) dip_thres = dip_thre_max * 1.1; + set_ug_coverage_aggressive(ug, m, sg, coverage_cut, sources, ruIndex, primary_flag, is_r_het, dip_thres); + } + free(primary_flag); +} + + +trans_chain* init_trans_chain(ma_ug_t *ug, uint64_t r_num) +{ + trans_chain *x = NULL; CALLOC(x, 1); + x->r_num = r_num; + x->u_num = ug->g->n_seq; + kv_init(x->k_trans); kv_init(x->k_trans.idx); + kv_init(x->k_t_b); + MALLOC(x->rUidx, r_num); + memset(x->rUidx, -1, x->r_num*sizeof(uint32_t)); + MALLOC(x->rUpos, r_num); + memset(x->rUpos, -1, x->r_num*sizeof(uint64_t)); + memset(&(x->b_buf_0), 0, sizeof(buf_t)); + memset(&(x->b_buf_1), 0, sizeof(buf_t)); + kv_init(x->topo_buf); + kv_init(x->topo_res); + ///MALLOC(x->uLen, x->u_num); + kv_init(x->c_buf); + + ma_utg_t *u = NULL; + asg_t* nsg = ug->g; + uint64_t n_vtx = nsg->n_seq, v, k, rId, is_dup = 0, vid, offset; + + + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + u = &(ug->u.a[v]); + if(u->m == 0) continue; + for (k = offset = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + + vid = v<<1; vid |= ((u->a[k]>>32) & 1); + if(x->rUidx[rId] != (uint32_t)-1 && x->rUidx[rId] != vid) is_dup = 1; + x->rUidx[rId] = vid; + + + vid = offset; vid <<=32; vid |= k; + if(x->rUpos[rId] != (uint64_t)-1 && x->rUpos[rId] != vid) is_dup = 1; + x->rUpos[rId] = vid; + + offset += (uint32_t)u->a[k]; + } + ///x->uLen[v] = u->len; + } + + if(is_dup) + { + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + u = &(ug->u.a[v]); + if(u->m == 0) continue; + for (k = offset = 0; k < u->n; k++) + { + rId = u->a[k]>>33; is_dup = 0; + + vid = v<<1; vid |= ((u->a[k]>>32) & 1); + if(x->rUidx[rId] != vid) is_dup = 1; + vid = offset; vid <<=32; vid |= k; + if(x->rUpos[rId] != vid) is_dup = 1; + + if(is_dup) + { + x->rUidx[rId] = (uint32_t)-1; + x->rUpos[rId] = (uint64_t)-1; + } + offset += (uint32_t)u->a[k]; + } + } + } + + + kv_malloc(x->bed, x->u_num); x->bed.n = x->u_num; + for (k = 0; k < x->bed.n; k++) kv_init(x->bed.a[k]); + x->st.chain_num = 0; + kv_init(x->st.uIDs); + kv_init(x->st.iDXs); + kv_push(uint32_t, x->st.iDXs, 0); + return x; +} + +void destory_trans_chain(trans_chain **x) +{ + if(x) + { + kv_destroy((*x)->k_trans); kv_destroy((*x)->k_trans.idx); + kv_destroy((*x)->k_t_b); + free((*x)->rUidx); + free((*x)->rUpos); + uint32_t k; + for (k = 0; k < (*x)->bed.n; k++) kv_destroy((*x)->bed.a[k]); + kv_destroy((*x)->bed); + free((*x)->b_buf_0.b.a); + free((*x)->b_buf_1.b.a); + kv_destroy((*x)->topo_buf); + kv_destroy((*x)->topo_res); + kv_destroy((*x)->c_buf); + kv_destroy((*x)->st.uIDs); + kv_destroy((*x)->st.iDXs); + ///free((*x)->uLen); + free((*x)); + } +} + +void init_hc_links(hc_links* link, uint64_t ug_num, trans_chain* t_ch) +{ + kv_malloc(link->a, ug_num); link->a.n = ug_num; + kv_malloc(link->enzymes, ug_num); link->enzymes.n = ug_num; + uint64_t i; + for (i = 0; i < link->a.n; i++) + { + kv_init(link->a.a[i].e); + kv_init(link->a.a[i].f); + } + + if(t_ch) + { + kv_u_trans_t *ta = &(t_ch->k_trans); + uint64_t d = RC_1; + for (i = 0; i < ta->n; i++) + { + if(ta->a[i].f == RC_2) continue; + push_hc_edge(&(link->a.a[ta->a[i].qn]), ta->a[i].tn, 1, 1, &d); + push_hc_edge(&(link->a.a[ta->a[i].tn]), ta->a[i].qn, 1, 1, &d); + } + } +} + +void destory_hc_links(hc_links* link) +{ + uint64_t i; + for (i = 0; i < link->a.n; i++) + { + kv_destroy(link->a.a[i].e); + kv_destroy(link->a.a[i].f); + } + kv_destroy(link->a); + kv_destroy(link->enzymes); +} + +void print_utg(ma_ug_t **ug, asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, R_to_U* ruIndex, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* new_rtg_edges) +{ + if(asm_opt.b_low_cov > 0) + { + break_ug_contig(ug, sg, &R_INF, coverage_cut, sources, ruIndex, new_rtg_edges, max_hang, min_ovlp, + &asm_opt.b_low_cov, NULL, asm_opt.m_rate); + } + + if(asm_opt.b_high_cov > 0) + { + break_ug_contig(ug, sg, &R_INF, coverage_cut, sources, ruIndex, new_rtg_edges, max_hang, min_ovlp, + NULL, &asm_opt.b_high_cov, asm_opt.m_rate); + } + + ma_ug_seq(*ug, sg, coverage_cut, sources, new_rtg_edges, max_hang, min_ovlp, 0, 1); + + + char* gfa_name = (char*)malloc(strlen(output_file_name)+35); + sprintf(gfa_name, "%s.p_ctg.gfa", output_file_name); + fprintf(stderr, "Writing %s to disk... \n", gfa_name); + FILE* output_file = fopen(gfa_name, "w"); + ma_ug_print(*ug, sg, coverage_cut, sources, ruIndex, "ptg", output_file); + fclose(output_file); + + sprintf(gfa_name, "%s.p_ctg.noseq.gfa", output_file_name); + output_file = fopen(gfa_name, "w"); + ma_ug_print_simple(*ug, sg, coverage_cut, sources, ruIndex, "ptg", output_file); + fclose(output_file); + if(asm_opt.bed_inconsist_rate != 0) + { + sprintf(gfa_name, "%s.p_ctg.lowQ.bed", output_file_name); + output_file = fopen(gfa_name, "w"); + ma_ug_print_bed(*ug, sg, &R_INF, coverage_cut, sources, new_rtg_edges, + max_hang, min_ovlp, asm_opt.bed_inconsist_rate, "ptg", output_file, NULL); + fclose(output_file); + } + free(gfa_name); + + /*******************************for debug************************************/ + // uint32_t i; + // for (i = 0; i < sg->n_seq; i++) + // { + // if(R_INF.trio_flag[i] == FATHER || R_INF.trio_flag[i] == MOTHER) fprintf(stderr, "ERROR\n"); + // } + /*******************************for debug************************************/ +} + +void write_trans_chain(trans_chain* t_ch, const char *fn) +{ + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.hic.trans.bin", fn); + FILE* fp = fopen(buf, "w"); + + fwrite(&t_ch->r_num, sizeof(t_ch->r_num), 1, fp); + fwrite(t_ch->ir_het, sizeof(uint8_t), t_ch->r_num, fp); + + uint32_t i; + fwrite(&t_ch->bed.n, sizeof(t_ch->bed.n), 1, fp); + for (i = 0; i < t_ch->bed.n; i++) + { + fwrite(&t_ch->bed.a[i].n, sizeof(t_ch->bed.a[i].n), 1, fp); + fwrite(t_ch->bed.a[i].a, sizeof(bed_interval), t_ch->bed.a[i].n, fp); + } + + fwrite(&t_ch->k_trans.n, sizeof(t_ch->k_trans.n), 1, fp); + fwrite(t_ch->k_trans.a, sizeof(u_trans_t), t_ch->k_trans.n, fp); + + fwrite(&t_ch->k_trans.idx.n, sizeof(t_ch->k_trans.idx.n), 1, fp); + fwrite(t_ch->k_trans.idx.a, sizeof(uint64_t), t_ch->k_trans.idx.n, fp); + + + fclose(fp); + free(buf); +} + + +trans_chain* load_hc_trans(const char *fn) +{ + uint64_t flag = 0; + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.hic.trans.bin", fn); + + FILE* fp = NULL; + fp = fopen(buf, "r"); + if(!fp) return NULL; + + trans_chain *t_ch = NULL; + CALLOC(t_ch, 1); + + flag += fread(&t_ch->r_num, sizeof(t_ch->r_num), 1, fp); + MALLOC(t_ch->ir_het, t_ch->r_num); + flag += fread(t_ch->ir_het, sizeof(uint8_t), t_ch->r_num, fp); + + uint32_t i; + flag += fread(&t_ch->bed.n, sizeof(t_ch->bed.n), 1, fp); + MALLOC(t_ch->bed.a, t_ch->bed.n); t_ch->bed.m = t_ch->bed.n; + for (i = 0; i < t_ch->bed.n; i++) + { + flag += fread(&t_ch->bed.a[i].n, sizeof(t_ch->bed.a[i].n), 1, fp); + MALLOC(t_ch->bed.a[i].a, t_ch->bed.a[i].n); t_ch->bed.a[i].m = t_ch->bed.a[i].n; + flag += fread(t_ch->bed.a[i].a, sizeof(bed_interval), t_ch->bed.a[i].n, fp); + } + + flag += fread(&t_ch->k_trans.n, sizeof(t_ch->k_trans.n), 1, fp); + MALLOC(t_ch->k_trans.a, t_ch->k_trans.n); t_ch->k_trans.m = t_ch->k_trans.n; + flag += fread(t_ch->k_trans.a, sizeof(u_trans_t), t_ch->k_trans.n, fp); + + flag += fread(&t_ch->k_trans.idx.n, sizeof(t_ch->k_trans.idx.n), 1, fp); + MALLOC(t_ch->k_trans.idx.a, t_ch->k_trans.idx.n); t_ch->k_trans.idx.m = t_ch->k_trans.idx.n; + flag += fread(t_ch->k_trans.idx.a, sizeof(uint64_t), t_ch->k_trans.idx.n, fp); + + + fclose(fp); + free(buf); + fprintf(stderr, "[M::%s::] ==> Hi-C cov have been loaded\n", __func__); + return t_ch; +} + +void hic_clean(asg_t* read_g) +{ + uint32_t n_vtx, v, u; + uint64_t i, k, k_i, tLen, v_occ, u_occ, utg_occ; + double bub_rate = 0.1; + ma_ug_t *ug = NULL; + ug = ma_ug_gen_primary(read_g, PRIMARY_LABLE); + n_vtx = ug->g->n_seq * 2; + buf_t b; memset(&b, 0, sizeof(buf_t)); b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + ///for (i = 0, tLen = 1; i < ug->u.n; i++) tLen += ug->u.a[i].len; + tLen = get_bub_pop_max_dist_advance(ug->g, &b); + uint8_t* bs_flag = (uint8_t*)calloc(n_vtx, 1); + kvec_t(uint32_t) ax; + kv_init(ax); + for (v = 0; v < ug->g->n_seq; ++v) + { + if(ug->g->seq[v].del) continue; + ug->g->seq[v].c = PRIMARY_LABLE; + EvaluateLen(ug->u, v) = ug->u.a[v].n; + } + + + for (v = 0; v < n_vtx; ++v) + { + if(ug->g->seq[v>>1].del) continue; + if(asg_arc_n(ug->g, v) < 2) continue; + if(bs_flag[v] != 0) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) + { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (i = 0; i < b.b.n; i++) + { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + bs_flag[b.b.a[i]] = bs_flag[b.b.a[i]^1] = 1; + } + bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 3; + } + } + + + for (v = 0; v < n_vtx; ++v) + { + if(bs_flag[v] !=2) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) + { + //note b.b include end, does not include beg + for (i = v_occ = ax.n = 0; i < b.b.n; i++) + { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + v_occ += ug->u.a[b.b.a[i]>>1].n; + kv_push(uint32_t, ax, b.b.a[i]>>1); + } + + for (i = 0; i < ax.n; i++) + { + for (k = 0; k < 2; k++) + { + u = (ax.a[i]<<1) + k; + if(asg_arc_n(ug->g, u) < 2) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, u, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) + { + for (k_i = u_occ = utg_occ = 0; k_i < b.b.n; k_i++) + { + if(b.b.a[k_i]==u || b.b.a[k_i]==b.S.a[0]) continue; + u_occ += ug->u.a[b.b.a[k_i]>>1].n; + utg_occ++; + } + + if(u_occ >= v_occ*bub_rate) continue; + if(u_occ > 3) continue; + if(utg_occ > 2) continue; + asg_bub_pop1_primary_trio(ug->g, NULL, u, tLen, &b, (uint32_t)-1, (uint32_t)-1, 1, NULL, NULL, NULL, 0, 0, NULL); + } + } + } + } + } + + ma_utg_t* m = NULL; + for (v = 0; v < ug->g->n_seq; ++v) + { + if(ug->g->seq[v].del) continue; + if(ug->g->seq[v].c != ALTER_LABLE) continue; + m = &(ug->u.a[v]); + if(m->m == 0) continue; + for (k = 0; k < m->n; k++) + { + asg_seq_del(read_g, m->a[k]>>33); + } + } + + asg_cleanup(read_g); + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); free(bs_flag); + ma_ug_destroy(ug); + kv_destroy(ax); +} + + +void hic_clean_adv(asg_t *sg, ug_opt_t *uopt) +{ + uint32_t i, k, m, z, v, w, mk; ma_utg_t *u = NULL; uint32_t *ba, bn, n_vtx, beg, end, n0, n1; ma_utg_t *mz = NULL; + ma_ug_t *ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); n_vtx = ug->g->n_seq<<1; double bub_rate = 0.1; + uint8_t *bf = NULL; bubble_type *bub = gen_bubble_chain(sg, ug, uopt, &bf, ((asm_opt.polyploidy>2)?1:0)); + uint64_t tLen, vocc, socc, pocc; buf_t b; memset(&b, 0, sizeof(buf_t)); CALLOC(b.a, n_vtx); + REALLOC(bf, n_vtx); memset(bf, 0, sizeof((*bf))*n_vtx); + kvec_t(uint64_t) buf; kv_init(buf); n0 = n1 = 0; + for (i = 0; i < ug->g->n_seq; ++i) { + if(ug->g->seq[i].del) continue; + ug->g->seq[i].c = PRIMARY_LABLE; + } + + for (i = 0; i < bub->b_ug->u.n; i++) { + u = &(bub->b_ug->u.a[i]); + if(u->n == 0) continue; + for (k = 0; k < u->n; k++) {///bubble chain + get_bubbles(bub, u->a[k]>>33, &beg, &end, &ba, &bn, NULL);///bubble + for (m = vocc = tLen = 0; m < bn; m++) { + bf[ba[m]] = bf[ba[m]^1] = 1; + tLen += ug->u.a[ba[m]>>1].len; + if(IF_HOM((ba[m]>>1), *bub)) continue; + if(ug->g->seq[ba[m]>>1].del) continue; + vocc += ug->u.a[ba[m]>>1].n; + } + if(beg != (uint32_t)-1) tLen += ug->u.a[beg>>1].len; + if(end != (uint32_t)-1) tLen += ug->u.a[end>>1].len; + + if(vocc) { + for (m = buf.n = 0; m < bn; m++) { + v = ba[m]; + if(ug->g->seq[v>>1].del) continue; + if(asg_arc_n(ug->g, v) < 2) continue; + if(get_real_length(ug->g, v, NULL) < 2) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (z = socc = 0; z < b.b.n; z++) { + if(b.b.a[z]==v || b.b.a[z]==b.S.a[0]) continue; + socc += ug->u.a[b.b.a[z]>>1].n; + if((!bf[b.b.a[z]])&&(!bf[b.b.a[z]^1])) break; + } + if(z < b.b.n) continue; + kv_push(uint64_t, buf, ((socc<<32)|v)); + } + + v ^= 1; + if(asg_arc_n(ug->g, v) < 2) continue; + if(get_real_length(ug->g, v, NULL) < 2) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (z = socc = 0; z < b.b.n; z++) { + if(b.b.a[z]==v || b.b.a[z]==b.S.a[0]) continue; + socc += ug->u.a[b.b.a[z]>>1].n; + if((!bf[b.b.a[z]])&&(!bf[b.b.a[z]^1])) break; + } + if(z < b.b.n) continue; + kv_push(uint64_t, buf, ((socc<<32)|v)); + } + } + + radix_sort_arch64(buf.a, buf.a + buf.n); + for (m = pocc = 0; m < buf.n; m++) { + v = (uint32_t)buf.a[m]; + if(ug->g->seq[v>>1].del) continue; + if(asg_arc_n(ug->g, v) < 2) continue; + if(get_real_length(ug->g, v, NULL) < 2) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (z = socc = 0; z < b.b.n; z++) { + if(b.b.a[z]==v || b.b.a[z]==b.S.a[0]) continue; + socc += ug->u.a[b.b.a[z]>>1].n; + if((!bf[b.b.a[z]])&&(!bf[b.b.a[z]^1])) break; + } + if(z < b.b.n) continue; + if((pocc+socc) >= (vocc*bub_rate)) continue; + pocc += socc; + asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 1, NULL, NULL, NULL, 0, 0, NULL); + for (z = 0; z < b.b.n; z++) { + if(b.b.a[z]==v || b.b.a[z]==b.S.a[0]) continue; + // socc += ug->u.a[b.b.a[i]>>1].n; + if(ug->g->seq[b.b.a[z]>>1].del) continue; + if(ug->g->seq[b.b.a[z]>>1].c != ALTER_LABLE) continue; + mz = &(ug->u.a[b.b.a[z]>>1]); + if(mz->m == 0) continue; + for (mk = 0; mk < mz->n; mk++) asg_seq_del(sg, mz->a[mk]>>33); + asg_seq_del(ug->g, b.b.a[z]>>1); + if(ug->u.a[b.b.a[z]>>1].m) { + ug->u.a[b.b.a[z]>>1].m = ug->u.a[b.b.a[z]>>1].n = 0; + free(ug->u.a[b.b.a[z]>>1].a); ug->u.a[b.b.a[z]>>1].a = NULL; + } + } + // fprintf(stderr, "+utg%.6dl\tutg%.6dl\n", (int32_t)(v>>1)+1, (int32_t)(b.S.a[0]>>1)+1); + n0++; + } + } + } + for (m = 0; m < bn; m++) { + bf[ba[m]] = bf[ba[m]^1] = 0; + } + } + } + + for (v = 0; v < ug->g->n_seq; ++v) { + if(ug->g->seq[v].del) continue; + if(ug->g->seq[v].c != ALTER_LABLE) continue; + mz = &(ug->u.a[v]); + if(mz->m == 0) continue; + for (k = 0; k < mz->n; k++) asg_seq_del(sg, mz->a[k]>>33); + asg_seq_del(ug->g, v); + if(ug->u.a[v].m) { + ug->u.a[v].m = ug->u.a[v].n = 0; + free(ug->u.a[v].a); ug->u.a[v].a = NULL; + } + } + asg_cleanup(ug->g); + + + + tLen = get_bub_pop_max_dist_advance(ug->g, &b); + for (v = buf.n = 0; v < n_vtx; ++v) { + if(ug->g->seq[v>>1].del) continue; + if(asg_arc_n(ug->g, v) < 2) continue; + if(get_real_length(ug->g, v, NULL) < 2) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (i = socc = 0; i < b.b.n; i++) { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + socc += ug->u.a[b.b.a[i]>>1].n; + } + if(socc <= 16) kv_push(uint64_t, buf, ((socc<<32)|v)); + } + } + + uint32_t convex; long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; + radix_sort_arch64(buf.a, buf.a + buf.n); + for (m = 0; m < buf.n; m++) { + v = (uint32_t)buf.a[m]; + if(ug->g->seq[v>>1].del) continue; + if(asg_arc_n(ug->g, v) < 2) continue; + if(get_real_length(ug->g, v, NULL) < 2) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { + w = b.S.a[0]^1; + for (i = socc = 0; i < b.b.n; i++) { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + socc += ug->u.a[b.b.a[i]>>1].n; + } + if(socc <= 16) { + b.b.n = 0; + get_unitig(ug->g, NULL, v^1, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, &b); + for (k = vocc = 0; k < b.b.n; k++) { + if(IF_HOM((b.b.a[k]>>1), *bub)) break; + vocc += ug->u.a[b.b.a[k]>>1].n; + } + if((socc) >= (vocc*bub_rate)) continue; + + b.b.n = 0; + get_unitig(ug->g, NULL, w^1, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, &b); + for (k = vocc = 0; k < b.b.n; k++) { + if(IF_HOM((b.b.a[k]>>1), *bub)) break; + vocc += ug->u.a[b.b.a[k]>>1].n; + } + if((socc) >= (vocc*bub_rate)) continue; + + asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 1, NULL, NULL, NULL, 0, 0, NULL); + for (i = 0; i < b.b.n; i++) { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + // socc += ug->u.a[b.b.a[i]>>1].n; + if(ug->g->seq[b.b.a[i]>>1].del) continue; + if(ug->g->seq[b.b.a[i]>>1].c != ALTER_LABLE) continue; + mz = &(ug->u.a[b.b.a[i]>>1]); + if(mz->m == 0) continue; + for (mk = 0; mk < mz->n; mk++) asg_seq_del(sg, mz->a[mk]>>33); + asg_seq_del(ug->g, b.b.a[i]>>1); + if(ug->u.a[b.b.a[i]>>1].m) { + ug->u.a[b.b.a[i]>>1].m = ug->u.a[b.b.a[i]>>1].n = 0; + free(ug->u.a[b.b.a[i]>>1].a); ug->u.a[b.b.a[i]>>1].a = NULL; + } + } + // fprintf(stderr, "-utg%.6dl\tutg%.6dl\n", (int32_t)(v>>1)+1, (int32_t)(b.S.a[0]>>1)+1); + n1++; + } + } + } + // filter_sg_by_ug(sg, ug, uopt); + for (v = 0; v < ug->g->n_seq; ++v) { + if(ug->g->seq[v].del) continue; + if(ug->g->seq[v].c != ALTER_LABLE) continue; + mz = &(ug->u.a[v]); + if(mz->m == 0) continue; + for (k = 0; k < mz->n; k++) asg_seq_del(sg, mz->a[k]>>33); + asg_seq_del(ug->g, v); + if(ug->u.a[v].m) { + ug->u.a[v].m = ug->u.a[v].n = 0; + free(ug->u.a[v].a); ug->u.a[v].a = NULL; + } + } + asg_cleanup(ug->g); + + asg_cleanup(sg); + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + ma_ug_destroy(ug); free(bf); kv_destroy(buf); + destory_bubbles(bub); free(bub); + // fprintf(stderr, "[M::%s::] # type0::%u, # type1::%u\n", __func__, n0, n1); +} + +void update_dump_trio(uint8_t* trio_flag, uint32_t rn, uint8_t *rf, ma_ug_t *ug) +{ + uint32_t k, i, x; + ma_utg_t *p = NULL; + if(ug) { + for (i = 0; i < ug->u.n; ++i) { // the Segment lines in GFA + p = &ug->u.a[i]; + if(p->m == 0) continue; + for (k = 0; k < p->n; k++) { + x = p->a[k]>>33; + if(trio_flag[x] == FATHER || trio_flag[x] == MOTHER) { + rf[x] = trio_flag[x]; + } else if(rf[x] != FATHER && rf[x] != MOTHER) { + rf[x] = DROP; + } + } + } + } else { + for (i = 0; i < rn; i++) { + if(rf[i]) { + rf[i] <<= 1; rf[i] += 1; + } else { + rf[i] = trio_flag[i]; rf[i] <<= 1; + } + + if(trio_flag[i] == FATHER || trio_flag[i] == MOTHER) { + trio_flag[i] = ((rf[i]&1)?MOTHER:FATHER); + } else { + trio_flag[i] = ((rf[i]&1)?DROP:AMBIGU); + } + } + } +} + +void update_poly_trio(uint32_t mm, uint32_t *hapS, uint32_t rn) +{ + uint32_t i; + for (i = 0; i < rn; i++) { + if(R_INF.trio_flag[i] == DROP) continue; + R_INF.trio_flag[i] = AMBIGU; + if(!hapS[i]) continue; + R_INF.trio_flag[i] = (hapS[i]&mm?FATHER:MOTHER); + } +} +void debug_hapS(uint32_t *hapS, uint32_t rn) +{ + uint32_t i, p, tot, nt, max_tot = 0, *occ = NULL, *freq = NULL; + for (i = 0; i < rn; i++) { + for (p = hapS[i], tot = 0; p; p>>=1, tot++); + max_tot = MAX(max_tot, tot); + } + fprintf(stderr, "[M::%s:] ==> %u haplotypes in total\n", __func__, max_tot); + if(max_tot){ + CALLOC(occ, max_tot+1); + CALLOC(freq, max_tot+1); + for (i = 0; i < rn; i++) { + for (p = hapS[i], tot = nt = 0; p; p>>=1, tot++){ + if(p&1) occ[tot+1]++, nt++; + } + freq[nt]++; + } + for (i = 1; i <= max_tot; i++) { + fprintf(stderr, "[M::%s:] ==> # reads in hap%u: %u\n", __func__, i, occ[i]); + } + for (i = 0; i <= max_tot; i++) { + fprintf(stderr, "[M::%s:] ==> # reads within %u haplotypes: %u\n", __func__, i, freq[i]); + } + free(occ); free(freq); + } +} + +void output_poly_trio(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, ma_hit_t_alloc* sources, +ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, long long stops_threshold, +R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, int gap_fuzz, int is_bench, +bub_label_t* b_mask_t, uint32_t hapN) +{ + uint32_t i; + uint32_t *hapS = ha_polybin_list(&asm_opt); + // debug_hapS(hapS, sg->n_seq); + char *fp = NULL; MALLOC(fp, 100); + for (i = 0; i < hapN; i++){ + update_poly_trio(1<n_seq); + sprintf(fp, "hap%u", i+1); + output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, reverse_sources, tipsLen, tip_drop_ratio, + stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, gap_fuzz, is_bench, b_mask_t, fp, NULL, NULL); + } + free(fp); free(hapS); +} + +void output_chr_bin_trio(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, ma_hit_t_alloc* sources, +ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, long long stops_threshold, +R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, int gap_fuzz, int is_bench, +bub_label_t* b_mask_t) +{ + uint32_t i, k, idx_n = 0, na; uint8_t *idx = NULL; + uint32_t *hapS = ha_charbin_list(&asm_opt, &idx, &idx_n); + fprintf(stderr, "[M::%s] # reads: %u\n", __func__, sg->n_seq); + // debug_hapS(hapS, sg->n_seq); + char *fp = NULL; MALLOC(fp, 100); + for (i = 0; i < idx_n; i++){ + if(!idx[i]) continue; + for (k = na = 0; k < sg->n_seq; k++) { + if(R_INF.trio_flag[k] == DROP) continue; + R_INF.trio_flag[k] = AMBIGU; + if(hapS[k] == ((uint32_t)-1)) continue; + if(hapS[k] == i) { + R_INF.trio_flag[k] = FATHER; na++; + } else { + R_INF.trio_flag[k] = MOTHER; + } + } + if(!na) continue; + sprintf(fp, "hap%u", i); + fprintf(stderr, "[M::%s] # %s reads: %u\n", __func__, fp, na); + output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, reverse_sources, tipsLen, tip_drop_ratio, + stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, gap_fuzz, is_bench, b_mask_t, fp, NULL, NULL); + } + free(fp); free(hapS); free(idx); +} + +uint32_t test_dbug(ma_ug_t* ug, FILE* fp) +{ + uint32_t f_flag = 0, t, i, r_flag = 0; + size_t tt; + ma_utg_t ua, *ub = NULL; memset(&ua, 0, sizeof(ua)); + f_flag = fread(&tt, sizeof(tt), 1, fp); + if(f_flag == 0 || tt != ug->u.n) goto DES; + + for (i = 0; i < tt; i++) + { + ub = &(ug->u.a[i]); + f_flag = fread(&t, sizeof(t), 1, fp); + if(f_flag == 0 || t != ub->len) goto DES; + f_flag = fread(&t, sizeof(t), 1, fp); + if(f_flag == 0 || t != ub->circ) goto DES; + f_flag = fread(&(ua.start), sizeof(ua.start), 1, fp); + if(f_flag == 0 || ua.start != ub->start) goto DES; + f_flag = fread(&(ua.end), sizeof(ua.end), 1, fp); + if(f_flag == 0 || ua.end != ub->end) goto DES; + f_flag = fread(&(ua.n), sizeof(ua.n), 1, fp); + if(f_flag == 0 || ua.n != ub->n) goto DES; + t = ua.n; + ua.n = 0; + kv_resize(uint64_t, ua, t); + ua.n = t; + f_flag = fread(ua.a, sizeof(uint64_t), ua.n, fp); + if(f_flag == 0 || memcmp(ua.a, ub->a, ua.n)) goto DES; + } + r_flag = 1; + + DES: + free(ua.a); + return r_flag; +} + +void write_dbug(ma_ug_t* ug, FILE* fp) +{ + ma_utg_t *u = NULL; + uint32_t t, i; + fwrite(&(ug->u.n), sizeof(ug->u.n), 1, fp); + for (i = 0; i < ug->u.n; i++) + { + u = &(ug->u.a[i]); + t = u->len; + fwrite(&t, sizeof(t), 1, fp); + t = u->circ; + fwrite(&t, sizeof(t), 1, fp); + fwrite(&(u->start), sizeof(u->start), 1, fp); + fwrite(&(u->end), sizeof(u->end), 1, fp); + fwrite(&(u->n), sizeof(u->n), 1, fp); + fwrite(u->a, sizeof(uint64_t), u->n, fp); + } +} + +void filter_u_trans(kv_u_trans_t *ta, uint8_t keep_bub, uint8_t keep_topo, uint8_t keep_read, uint8_t keep_base) +{ + if(keep_bub && keep_topo && keep_read && keep_base) return; + uint32_t i, m; + for (i = m = 0; i < ta->n; i++) { + if((!keep_bub) && (ta->a[i].f == RC_0)) continue; + if((!keep_topo) && (ta->a[i].f == RC_1)) continue; + if((!keep_read) && (ta->a[i].f == RC_2)) continue; + if((!keep_base) && (ta->a[i].f == RC_3)) continue; + ta->a[m++] = ta->a[i]; + } + ta->n = m; +} + +uint32_t trans_ovlp_connect1(u_trans_t *p, ma_ug_t *ug) +{ + uint32_t v = p->qn<<1, w = (p->tn<<1) + ((uint32_t)p->rev), i, dg = (uint32_t)-1, da, dif, mm; + asg_arc_t *av = asg_arc_a(ug->g, v); uint32_t nv = asg_arc_n(ug->g, v); + for (i = 0; i < nv; i++) { + if(av[i].del || av[i].v != w) continue; + dg = av[i].ol; + break; + } + // if((v>>1) == 43 && (w>>1) == 45) { + // fprintf(stderr, "+[M::%s::] utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tf::%u\n", __func__, + // p->qn+1, "lc"[s->ug->u.a[p->qn].circ], s->ug->u.a[p->qn].len, p->qs, p->qe, + // "+-"[p->rev], p->tn+1, "lc"[s->ug->u.a[p->tn].circ], s->ug->u.a[p->tn].len, p->ts, p->te, p->f); + // } + + if(i < nv) { + // if(i >= nv) return 1; + da = (p->qe - p->qs); + dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; + if(dif <= mm) return 0; + + da = (p->te - p->ts); + dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; + if(dif <= mm) return 0; + } + + v ^= 1; w ^= 1; dg = (uint32_t)-1; + av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); + for (i = 0; i < nv; i++) { + if(av[i].del || av[i].v != w) continue; + dg = av[i].ol; + break; + } + if(i < nv) { + // if(i >= nv) return 1; + da = (p->qe - p->qs); + dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; + if(dif <= mm) return 0; + + da = (p->te - p->ts); + dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; + if(dif <= mm) return 0; + } + + return 1; +} + + +uint32_t ovlp_rocc(u_trans_t *p, ma_ug_t *ug, asg_t *rg, double cov_rate, uint32_t cov_cutoff) +{ + ma_utg_t *u = NULL; uint32_t s, e, rs, re, occ, k, l; + u = &(ug->u.a[p->qn]); s = p->qs; e = p->qe; + if((e-s) >= (u->len*cov_rate)) return 1; + for (k = l = occ = 0; k < u->n && occ < cov_cutoff; k++) { + rs = l; re = l + rg->seq[u->a[k]>>33].len; + if(rs >= e) break; + if(s <= rs && e >= re) occ++; + l += (uint32_t)u->a[k]; + } + if(occ >= cov_cutoff) return 1; + + u = &(ug->u.a[p->tn]); s = p->ts; e = p->te; + if((e-s) >= (u->len*cov_rate)) return 1; + for (k = l = occ = 0; k < u->n && occ < cov_cutoff; k++) { + rs = l; re = l + rg->seq[u->a[k]>>33].len; + if(rs >= e) break; + if(s <= rs && e >= re) occ++; + l += (uint32_t)u->a[k]; + } + if(occ >= cov_cutoff) return 1; + return 0; +} + +static void worker_for_trans_clean(void *data, long i, int tid) // callback for kt_for() +{ + u_trans_clean_t *s = (u_trans_clean_t*)data; + kv_u_trans_t *ta = s->ta; + kv_u_trans_t *res = &(s->res[tid]); + u_trans_t *a = NULL, *r_a = NULL, *mz, *cz; + uint32_t n, r_n, id = i, k, l, z; + + a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); + for (k = 1, l = 0; k <= n; k++) { + if(k == n || a[l].tn != a[k].tn) { + if(k > l) { + get_u_trans_spec(ta, a[l].tn, a[l].qn, &r_a, &r_n); + if(r_n > 0 && id > a[l].tn) { + l = k; continue; + } + mz = cz = NULL; + for (z = l; z < k; z++) { + cz = &(a[z]); + // fprintf(stderr, ">[M::%s::] qn::%u, tn::%u, cz->nw::%f, cz->f::%u\n", + // __func__, a[l].qn, a[l].tn, cz->nw, cz->f); + if(mz) { + if((mz->f == RC_0) && (cz->f != RC_0)) continue; + if((mz->f == RC_1) && ((cz->f == RC_2) || (cz->f == RC_3))) continue; + } + if((!mz) || ((cz->f < mz->f) && ((cz->f == RC_0) || (cz->f == RC_1))) || + (mz->nw < cz->nw) || ((mz->nw == cz->nw) && ((mz->qe - mz->qs) < (cz->qe - cz->qs)))) { + // fprintf(stderr, "+[M::%s::] qn::%u, tn::%u, mz->nw::%f, mz->f::%u, cz->nw::%f, cz->f::%u\n", + // __func__, a[l].qn, a[l].tn, mz?mz->nw:-1, mz?mz->f:255, cz->nw, cz->f); + mz = cz; + } + } + for (z = 0; z < r_n; z++) { + cz = &(r_a[z]); + if(mz) { + if((mz->f == RC_0) && (cz->f != RC_0)) continue; + if((mz->f == RC_1) && ((cz->f == RC_2) || (cz->f == RC_3))) continue; + } + if((!mz) || ((cz->f < mz->f) && ((cz->f == RC_0) || (cz->f == RC_1))) || + (mz->nw < cz->nw) || ((mz->nw == cz->nw) && ((mz->qe - mz->qs) < (cz->te - cz->ts)))) { + ///note here is (cz->te - cz->ts) + // fprintf(stderr, "-[M::%s::] qn::%u, tn::%u, mz->nw::%f, mz->f::%u, cz->nw::%f, cz->f::%u\n", + // __func__, a[l].qn, a[l].tn, mz?mz->nw:-1, mz?mz->f:255, cz->nw, cz->f); + mz = cz; + } + } + + // fprintf(stderr, "-[M::%s::] is_mz::%u, qn::%u, tn::%u\n", __func__, (uint32_t)(!!mz), mz->qn, mz->tn); + if((mz) && (mz->qn != mz->tn)) { + ///need to check it cover enough reads + kv_pushp(u_trans_t, *res, &cz); (*cz) = (*mz); + if(mz->qn != id) { + cz->qn = mz->tn; cz->qs = mz->ts; cz->qe = mz->te; + cz->tn = mz->qn; cz->ts = mz->qs; cz->te = mz->qe; + } + + if((cz->nw >= 0) && ((!trans_ovlp_connect1(cz, s->ug)) + || (!ovlp_rocc(cz, s->ug, s->rg, s->small_ov_rate, s->ov_cutoff)))) { + // if(mz->qn == 43 && mz->tn == 45) { + // fprintf(stderr, "-[M::%s::] utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, + // mz->qn+1, "lc"[s->ug->u.a[mz->qn].circ], s->ug->u.a[mz->qn].len, mz->qs, mz->qe, + // "+-"[mz->rev], + // mz->tn+1, "lc"[s->ug->u.a[mz->tn].circ], s->ug->u.a[mz->tn].len, mz->ts, mz->te); + // } + + res->n--; + } + // else { + // if(mz->qn == 43 && mz->tn == 45) { + // fprintf(stderr, "+[M::%s::] utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tf::%u\n", __func__, + // mz->qn+1, "lc"[s->ug->u.a[mz->qn].circ], s->ug->u.a[mz->qn].len, mz->qs, mz->qe, + // "+-"[mz->rev], mz->tn+1, "lc"[s->ug->u.a[mz->tn].circ], s->ug->u.a[mz->tn].len, mz->ts, mz->te, mz->f); + // } + // } + } + } + l = k; + } + } +} + +static void worker_for_trans_clean_re(void *data, long i, int tid) // callback for kt_for() +{ + u_trans_clean_t *s = (u_trans_clean_t*)data; + kv_u_trans_t *ta = s->ta; + kv_u_trans_t *res = &(s->res[tid]); + u_trans_t *a = NULL, *r_a = NULL, *mz, *cz, *sz; + uint32_t n, r_n, id = i, k, l, z; + uint32_t ovq, ovt, os, oe; + + a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); + for (k = 1, l = 0; k <= n; k++) { + if(k == n || a[l].tn != a[k].tn) { + if(k > l) { + get_u_trans_spec(ta, a[l].tn, a[l].qn, &r_a, &r_n); + if(r_n > 0 && id > a[l].tn) { + l = k; continue; + } + + mz = cz = sz = NULL; + for (z = l; z < k; z++) { + cz = &(a[z]); + if(cz->f == RC_3) { + if((!sz) || (sz->nw < cz->nw)) sz = cz; + } + if(mz) { + if((mz->f == RC_0) && (cz->f != RC_0)) continue; + if((mz->f == RC_1) && ((cz->f == RC_2) || (cz->f == RC_3))) continue; + } + if((!mz) || ((cz->f < mz->f) && ((cz->f == RC_0) || (cz->f == RC_1))) || + (mz->nw < cz->nw) || ((mz->nw == cz->nw) && ((mz->qe - mz->qs) < (cz->qe - cz->qs)))) { + mz = cz; + } + } + for (z = 0; z < r_n; z++) { + cz = &(r_a[z]); + if(cz->f == RC_3) { + if((!sz) || (sz->nw < cz->nw)) sz = cz; + } + if(mz) { + if((mz->f == RC_0) && (cz->f != RC_0)) continue; + if((mz->f == RC_1) && ((cz->f == RC_2) || (cz->f == RC_3))) continue; + } + if((!mz) || ((cz->f < mz->f) && ((cz->f == RC_0) || (cz->f == RC_1))) || + (mz->nw < cz->nw) || ((mz->nw == cz->nw) && ((mz->qe - mz->qs) < (cz->te - cz->ts)))) { + mz = cz; + } + } + + + + // fprintf(stderr, "-[M::%s::] is_mz::%u, qn::%u, tn::%u\n", __func__, (uint32_t)(!!mz), mz->qn, mz->tn); + if((mz) && (mz->qn != mz->tn)) { + ///need to check it cover enough reads + kv_pushp(u_trans_t, *res, &cz); (*cz) = (*mz); + if((sz) && (sz->rev == cz->rev)) { + if((cz->qn != sz->qn) || (cz->tn != sz->tn)) { + cz->qn = mz->tn; cz->qs = mz->ts; cz->qe = mz->te; + cz->tn = mz->qn; cz->ts = mz->qs; cz->te = mz->qe; + } + if((cz->qn == sz->qn) && (cz->tn == sz->tn)) { + os = MAX(cz->qs, sz->qs); oe = MIN(cz->qe, sz->qe); + ovq = ((oe > os)? (oe - os):0); + + os = MAX(cz->ts, sz->ts); oe = MIN(cz->te, sz->te); + ovt = ((oe > os)? (oe - os):0); + + if(((ovq) && (ovq > ((cz->qe-cz->qs)*0.8)) && (ovq > ((sz->qe-sz->qs)*0.8))) && + (((ovt) && (ovt > ((cz->te-cz->ts)*0.8)) && (ovt > ((sz->te-sz->ts)*0.8))))) {///sounds like base-level alignment coordinates are more reliable + (*cz) = (*sz); cz->f = mz->f; + } + } + } + if(cz->qn != id) { + z = cz->qn; cz->qn = cz->tn; cz->tn = z; + z = cz->qs; cz->qs = cz->ts; cz->ts = z; + z = cz->qe; cz->qe = cz->te; cz->te = z; + } + + // if(id == 394 || id == 1698 || id == 84) { + // fprintf(stderr, "+[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, + // cz->qn+1, "lc"[s->ug->u.a[cz->qn].circ], s->ug->u.a[cz->qn].len, cz->qs, cz->qe, "+-"[cz->rev], + // cz->tn+1, "lc"[s->ug->u.a[cz->tn].circ], s->ug->u.a[cz->tn].len, cz->ts, cz->te); + // } + + if((cz->nw >= 0) && ((!trans_ovlp_connect1(cz, s->ug)) + || (!ovlp_rocc(cz, s->ug, s->rg, s->small_ov_rate, s->ov_cutoff)))) { + // if(id == 394 || id == 1698 || id == 84) { + // fprintf(stderr, "-[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, + // cz->qn+1, "lc"[s->ug->u.a[cz->qn].circ], s->ug->u.a[cz->qn].len, cz->qs, cz->qe, "+-"[cz->rev], + // cz->tn+1, "lc"[s->ug->u.a[cz->tn].circ], s->ug->u.a[cz->tn].len, cz->ts, cz->te); + // } + res->n--; + } + } + } + l = k; + } + } +} + +int cmp_u_trans_weight(const void * a, const void * b) +{ + if((*(u_trans_t*)a).nw == (*(u_trans_t*)b).nw) return 0; + return ((*(u_trans_t*)a).nw) > ((*(u_trans_t*)b).nw)?-1:1; +} + +int64_t infer_utrans_ovlp_len(u_trans_t *li, u_trans_t *lj, ma_ug_t *ug) +{ + int64_t in, is, ie, irev, iqs, iqe, jn, js, je, jrev, jqs, jqe, ir, jr, ts, te, max_s, min_e, s_shift, e_shift; + + in = ug->u.a[li->tn].len; + is = li->ts; ie = li->te; irev = li->rev; iqs = li->qs; iqe = li->qe; + jn = ug->u.a[lj->tn].len; + js = lj->ts; je = lj->te; jrev = lj->rev; jqs = lj->qs; jqe = lj->qe; + + max_s = MAX(iqs, jqs); min_e = MIN(iqe, jqe); + if(min_e <= max_s) return 0; + s_shift = get_offset_adjust(max_s - iqs, iqe-iqs, ie-is); + e_shift = get_offset_adjust(iqe - min_e, iqe-iqs, ie-is); + if(irev) { + ts = s_shift; s_shift = e_shift; e_shift = ts; + } + is += s_shift; ie-= e_shift; + + s_shift = get_offset_adjust(max_s - jqs, jqe-jqs, je-js); + e_shift = get_offset_adjust(jqe - min_e, jqe-jqs, je-js); + if(jrev) { + ts = s_shift; s_shift = e_shift; e_shift = ts; + } + js += s_shift; je-= e_shift; + + if(irev) { + ts = in - ie; te = in - is; + is = ts; ie = te; + } + + if(jrev) { + ts = jn - je; te = jn - js; + js = ts; je = te; + } + + if(is <= js) { + js -= is; is = 0; + } else { + is -= js; js = 0; + } + + ir = in - ie; jr = jn - je; + + if(ir <= jr){ + ie = in; je += ir; + } + else { + je = jn; ie += jr; + } + + ir = ie - is; jr = je - js; + return MAX(ir, jr); +} + +///li is the suffix of lj +uint32_t is_connect_arc(u_trans_t *li, u_trans_t *lj, ma_ug_t *ug, double diff_ec_ul) +{ + if(li->qs >= lj->qs && li->qe >= lj->qe) { + int64_t dq = infer_utrans_ovlp_len(li, lj, ug); + uint32_t v = (li->tn<<1)|li->rev, w = (lj->tn<<1)|lj->rev; + int64_t dt = -1, dif, mm; uint32_t nv, i; asg_arc_t *av; + nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); + for (i = 0; i < nv; i++) { + if(av[i].del || av[i].v != w) continue; + dt = av[i].ol; + break; + } + + if(dt < 0) return 0; + dif = (dq>dt? dq-dt:dt-dq); + mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < 8) mm = 8; + if(dif <= mm) return 1; + } + return 0; +} + +uint32_t test_arc_rm(ma_ug_t *ug, u_trans_t *a, uint32_t a_n, uint32_t a_k, uint32_t len, asg64_v *srt, uint32_t len_cut, double rate_cut) +{ + uint32_t z, i, l, os, oe, ovq; + + srt->n = 0; kv_resize(uint64_t, *srt, a_n); + for (z = 0; z < a_n; z++) { + if(z == a_k) continue; + if(a[z].occ == ((uint32_t)-1)) continue; + srt->a[srt->n] = a[z].qs; + srt->a[srt->n] <<= 32; + srt->a[srt->n] |= a[z].qe; + srt->n++; + } + radix_sort_arch64(srt->a, srt->a+srt->n); + for (i = z = 0; i < srt->n; i++) { + os = (uint32_t)(srt->a[i]>>32); oe = (uint32_t)srt->a[i]; + if(z > 0 && os <= ((uint32_t)srt->a[z-1])) { + if(oe > ((uint32_t)srt->a[z-1])) { + srt->a[z-1] >>= 32; srt->a[z-1] <<= 32; srt->a[z-1] |= oe; + } + } else { + srt->a[z++] = srt->a[i]; + } + } + srt->n = z; l = (a[a_k].qe - a[a_k].qs); + for (z = 0; (z < srt->n) && (l > 0); z++) { + os = MAX(a[a_k].qs, ((uint32_t)(srt->a[z]>>32))); + oe = MIN(a[a_k].qe, ((uint32_t)srt->a[z])); + ovq = ((oe > os)? (oe - os):0); + assert(l >= ovq); l -= ovq; + } + // if((a[a_k].qn == 3924 && a[a_k].tn == 160) || (a[a_k].tn == 3924 && a[a_k].qn == 160)) { + // fprintf(stderr, "[M::%s::]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\tdel::%u\tlen::%u\tlen_cut::%u\trate_cut::%f\tl::%u\n", __func__, + // a[a_k].qn+1, "lc"[ug->u.a[a[a_k].qn].circ], ug->u.a[a[a_k].qn].len, a[a_k].qs, a[a_k].qe, "+-"[a[a_k].rev], + // a[a_k].tn+1, "lc"[ug->u.a[a[a_k].tn].circ], ug->u.a[a[a_k].tn].len, a[a_k].ts, a[a_k].te, a[a_k].nw, a[a_k].f, + // (a[a_k].occ == ((uint32_t)-1))?1:0, len, len_cut, rate_cut, l); + // } + if((l > len_cut) && (l > (len*rate_cut))) return 0;///cannot be dropped + return 1; +} + +void deep_clean_u_trans(kv_u_trans_t *ta, u_trans_t *mz, ma_ug_t *ug, asg64_v *srt, uint32_t len_cut, double rate_cut) +{ + if(mz->qn > mz->tn) return; + u_trans_t *r_a, *cz, *a; uint32_t r_k, r_n, n, k; + r_a = u_trans_a(*ta, mz->tn); r_n = u_trans_n(*ta, mz->tn); + for (r_k = 0; (r_k < r_n) && (r_a[r_k].tn != mz->qn); r_k++); + assert(r_k < r_n); cz = &(r_a[r_k]); + // if((mz->qn == 3924 && mz->tn == 160) || (mz->tn == 3924 && mz->qn == 160)) { + // fprintf(stderr, "[M::%s::]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\tdel::%u\n", __func__, + // mz->qn+1, "lc"[ug->u.a[mz->qn].circ], ug->u.a[mz->qn].len, mz->qs, mz->qe, "+-"[mz->rev], + // mz->tn+1, "lc"[ug->u.a[mz->tn].circ], ug->u.a[mz->tn].len, mz->ts, mz->te, mz->nw, mz->f, + // (mz->occ == ((uint32_t)-1))?1:0); + // fprintf(stderr, "[M::%s::]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\tdel::%u\n", __func__, + // cz->qn+1, "lc"[ug->u.a[cz->qn].circ], ug->u.a[cz->qn].len, cz->qs, cz->qe, "+-"[cz->rev], + // cz->tn+1, "lc"[ug->u.a[cz->tn].circ], ug->u.a[cz->tn].len, cz->ts, cz->te, cz->nw, cz->f, + // (cz->occ == ((uint32_t)-1))?1:0); + // } + if((mz->occ == ((uint32_t)-1)) && (cz->occ == ((uint32_t)-1))) return; + if((mz->occ != ((uint32_t)-1)) && (cz->occ != ((uint32_t)-1))) return; + + if(!test_arc_rm(ug, r_a, r_n, r_k, ug->u.a[mz->tn].len, srt, len_cut, rate_cut)) { + mz->occ = cz->occ = 0; return; + } else { + a = u_trans_a(*ta, mz->qn); n = u_trans_n(*ta, mz->qn); + for (k = 0; (k < n) && (a[k].tn != mz->tn); k++){;} assert(k < n); + if(!test_arc_rm(ug, a, n, k, ug->u.a[mz->qn].len, srt, len_cut, rate_cut)) { + mz->occ = cz->occ = 0; return; + } + } + mz->occ = cz->occ = ((uint32_t)-1); +} + +static void worker_for_trans_sec_cut(void *data, long i, int tid) // callback for kt_for() +{ + u_trans_clean_t *s = (u_trans_clean_t*)data; + kv_u_trans_t *ta = s->ta; + asg64_v *srt = &(s->srt[tid]); + u_trans_t *a = NULL, *mz, *cz, t; + uint32_t n, r_n, id = i, k, l, z, m, wm, wl, len; + uint32_t ovq, os, oe; uint64_t *ss, *hs, *bu, *wu; + + if(!(s->cu)) { + a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); + for (k = r_n = 0; k < n; k++) {///RC_0/RC_1 to a[0, r_n) + if((a[k].f == RC_0) || (a[k].f == RC_1)) { + if(k != r_n) { + t = a[k]; a[k] = a[r_n]; a[r_n] = t; + } + r_n++; + } + } + if(r_n >= n) return; + if(n-r_n > 1) qsort(a+r_n, n-r_n, sizeof((*a)), cmp_u_trans_weight); + // if(id == 3924 || id == 160) { + // fprintf(stderr, "[M::%s::]\tutg%.6u%c\tr_n::%u\tn::%u\n", __func__, + // id + 1, "lc"[s->ug->u.a[id].circ], r_n, n); + // for (k = 0; k < n; k++) { + // fprintf(stderr, "+[%u]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\n", k, + // a[k].qn+1, "lc"[s->ug->u.a[a[k].qn].circ], s->ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], + // a[k].tn+1, "lc"[s->ug->u.a[a[k].tn].circ], s->ug->u.a[a[k].tn].len, a[k].ts, a[k].te, a[k].nw, a[k].f); + // } + // } + srt->n = 0; kv_resize(uint64_t, *srt, (n<<2)); + for (k = 0; k < n; k++) { + srt->a[srt->n] = a[k].qs; + srt->a[srt->n] <<= 32; + srt->a[srt->n] |= k; + srt->n++; + } + ss = srt->a; hs = ss + srt->n; bu = hs + srt->n; wu = bu + srt->n; + radix_sort_arch64(ss, ss+n); + for (k = 0; k < n; k++) { + ss[k] = (uint32_t)ss[k]; hs[ss[k]] = k; + } + for (k = r_n; k < n; k++) { + cz = &(a[k]); len = (cz->qe-cz->qs)*s->sec_rate; m = wm = 0; + for (z = l = wl = 0; z < n; z++) { + if(z == hs[k]) { + assert(ss[z] == k); + continue; + } + if(ss[z] > k) continue;///smaller nw than a[k] + mz = &(a[ss[z]]); + if(mz->qs >= cz->qe) break; + if(mz->occ == ((uint32_t)-1)) continue;///has been deleted + if((mz->f != RC_0) && (mz->f != RC_1) && (cz->nw > (mz->nw*s->sc_sec_rate/**0.95**/))) continue; + os = MAX(cz->qs, mz->qs); oe = MIN(cz->qe, mz->qe); + ovq = ((oe > os)? (oe - os):0); + if(!ovq) continue; + if(is_connect_arc(cz, mz, s->ug, 0.04) || is_connect_arc(mz, cz, s->ug, 0.04)) continue; + + if((m > 0) && (((uint32_t)bu[m-1]) >= os)) { + if(oe > ((uint32_t)bu[m-1])) { + l += (oe - ((uint32_t)bu[m-1])); + bu[m-1] += (oe - ((uint32_t)bu[m-1])); + } + } else { + l += oe - os; + bu[m] = os; bu[m] <<= 32; bu[m] |= oe; m++; + } + + if((wm > 0) && (((uint32_t)wu[wm-1]) >= mz->qs)) { + if(mz->qe > ((uint32_t)wu[wm-1])) { + wl += (mz->qe - ((uint32_t)wu[wm-1])); + wu[wm-1] += (mz->qe - ((uint32_t)wu[wm-1])); + } + } else { + wl += mz->qe - mz->qs; + wu[wm] = mz->qs; wu[wm] <<= 32; wu[wm] |= mz->qe; wm++; + } + + if((l > 0) && ((l>=len) || (l>=(wl*s->sec_rate)))) { + // if((cz->qn == 3924 && cz->tn == 160) || (cz->tn == 3924 && cz->qn == 160)) { + // fprintf(stderr, "[M::%s]\tutg%.6u%c\t->\tutg%.6u%c\tl::%u\tlen::%u\twl::%u\tsec_rate::%f\n", __func__, + // cz->qn+1, "lc"[s->ug->u.a[cz->qn].circ], + // cz->tn+1, "lc"[s->ug->u.a[cz->tn].circ], + // l, len, wl, s->sec_rate); + // } + cz->occ = ((uint32_t)-1); + break; + } + } + } + // if(id == 3924 || id == 160) { + // for (k = 0; k < n; k++) { + // fprintf(stderr, "-[%u]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\tdel::%u\n", k, + // a[k].qn+1, "lc"[s->ug->u.a[a[k].qn].circ], s->ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], + // a[k].tn+1, "lc"[s->ug->u.a[a[k].tn].circ], s->ug->u.a[a[k].tn].len, a[k].ts, a[k].te, a[k].nw, a[k].f, + // (a[k].occ == ((uint32_t)-1))?1:0); + // } + // } + } else { + assert(((uint32_t)(s->cu->idx.a[id])) > (s->cu->idx.a[id]>>32)+1); + for (z = (s->cu->idx.a[id]>>32); z < ((uint32_t)(s->cu->idx.a[id])); z++) { + a = u_trans_a(*ta, ((uint32_t)s->cu->z.a[z])); + n = u_trans_n(*ta, ((uint32_t)s->cu->z.a[z])); + for (k = 0; k < n; k++) deep_clean_u_trans(ta, &(a[k]), s->ug, srt, 3000000, 0.5); + } + } +} + + +uint64_t trans_sec_cut0(kv_u_trans_t *ta, asg64_v *srt, uint32_t id, double sec_rate, uint64_t bd, ma_ug_t *ug) +{ + u_trans_t *a = NULL, *mz, *cz, t, *ca; + uint32_t a_n, r_n, c_n, k, l, z, i, m, wm, wl, len, b_n = srt->n; + uint32_t ovq, os, oe; uint64_t *ss, *hs, *bu, *wu, occ = 0; + + a = u_trans_a(*ta, id); a_n = u_trans_n(*ta, id); + for (k = r_n = 0; k < a_n; k++) {///RC_0/RC_1 to a[0, r_n) + if(a[k].del) continue; + if(k != r_n) { + t = a[k]; a[k] = a[r_n]; a[r_n] = t; + } + r_n++; + } + if(r_n <= 1) return occ; + qsort(a, r_n, sizeof((*a)), cmp_u_trans_weight); + + kv_resize(uint64_t, *srt, (b_n+(r_n<<2))); + for (k = 0; k < r_n; k++) { + srt->a[srt->n] = a[k].qs; + srt->a[srt->n] <<= 32; + srt->a[srt->n] |= k; + srt->n++; + } + + ss = srt->a + b_n; hs = ss + r_n; bu = hs + r_n; wu = bu + r_n; + radix_sort_arch64(ss, ss + r_n); + for (k = 0; k < r_n; k++) { + ss[k] = (uint32_t)ss[k]; hs[ss[k]] = k; + } + + for (k = 0; k < r_n; k++) { + cz = &(a[k]); len = (cz->qe-cz->qs)*sec_rate; m = wm = 0; + for (z = l = wl = 0; z < r_n; z++) { + if(z == hs[k]) { + assert(ss[z] == k); + continue; + } + if(ss[z] > k) continue;///smaller nw than a[k] + mz = &(a[ss[z]]); + if(mz->qs >= cz->qe) break; + if(mz->del) continue;///has been deleted + // if((mz->f != RC_0) && (mz->f != RC_1) && (cz->nw > (mz->nw*0.95))) continue; + os = MAX(cz->qs, mz->qs); oe = MIN(cz->qe, mz->qe); + ovq = ((oe > os)? (oe - os):0); + if(!ovq) continue; + if(is_connect_arc(cz, mz, ug, 0.04) || is_connect_arc(mz, cz, ug, 0.04)) continue; + + if((m > 0) && (((uint32_t)bu[m-1]) >= os)) { + if(oe > ((uint32_t)bu[m-1])) { + l += (oe - ((uint32_t)bu[m-1])); + bu[m-1] += (oe - ((uint32_t)bu[m-1])); + } + } else { + l += oe - os; + bu[m] = os; bu[m] <<= 32; bu[m] |= oe; m++; + } + + if((wm > 0) && (((uint32_t)wu[wm-1]) >= mz->qs)) { + if(mz->qe > ((uint32_t)wu[wm-1])) { + wl += (mz->qe - ((uint32_t)wu[wm-1])); + wu[wm-1] += (mz->qe - ((uint32_t)wu[wm-1])); + } + } else { + wl += mz->qe - mz->qs; + wu[wm] = mz->qs; wu[wm] <<= 32; wu[wm] |= mz->qe; wm++; + } + + if((l >= bd) && ((l>=len) || (l>=(wl*sec_rate)))) { + cz->del = 1; occ++; + ca = u_trans_a(*ta, cz->tn); c_n = u_trans_n(*ta, cz->tn); + for (i = 0; i < c_n; i++) { + if(ca[i].tn == cz->qn) ca[i].del = 1; + } + break; + } + } + } + + srt->n = b_n; + return occ; +} + +void dbg_prt_utg_trans(kv_u_trans_t *ta, ma_ug_t *ug, const char *o_n) +{ + char* gfa_name = (char*)malloc(strlen(o_n)+100); + FILE *fn = NULL; sprintf(gfa_name, "%s.tran.dbg.ovlp.log", o_n); + u_trans_t *p = NULL; uint32_t i; fn = fopen(gfa_name, "w"); + for (i = 0; i < ta->n; i++) { + p = &(ta->a[i]); + fprintf(fn, "utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tw(%f)\tf(%u)\n", + p->qn+1, "lc"[ug->u.a[p->qn].circ], ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], + p->tn+1, "lc"[ug->u.a[p->tn].circ], ug->u.a[p->tn].len, p->ts, p->te, p->nw, p->f); + } + fclose(fn); free(gfa_name); fprintf(stderr, "[M::%s::] done\n", __func__); +} + +void clean_u_trans_t_idx_adv(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g) +{ + u_trans_clean_t sl; uint64_t k, i, l, occ; ha_mzl_t *tz; + ha_mzl_v srt_a; kv_u_trans_t *bl; u_trans_t *z; + memset(&sl, 0, sizeof(sl)); kv_init(srt_a); + + kt_u_trans_t_idx(ta, ug->g->n_seq); + sl.n_thread = asm_opt.thread_num; sl.ug = ug; sl.rg = read_g; sl.ta = ta; + CALLOC(sl.res, sl.n_thread); + sl.ov_cutoff = 3; sl.small_ov_rate = 0.8; + // dbg_prt_utg_trans(ta, ug, "pre"); + kt_for(sl.n_thread, worker_for_trans_clean, &sl, sl.ta->idx.n); + + for (i = srt_a.n = occ = 0; i < sl.n_thread; i++) { + bl = &(sl.res[i]); + if(!(bl->n)) continue; + for (k = 1, l = 0; k <= bl->n; k++) { + if(k == bl->n || bl->a[k].qn != bl->a[l].qn) { + if(k > l) { + kv_pushp(ha_mzl_t, srt_a, &tz); + tz->x = bl->a[l].qn; tz->x <<= 32; tz->x |= i; + tz->rid = l>>32; tz->pos = (uint32_t)l; + occ += (k - l); + } + l = k; + } + } + } + // fprintf(stderr, "[M::%s::] occ::%lu \n", __func__, occ); + assert(srt_a.n <= sl.ug->u.n); + radix_sort_ha_mzl_t_srt1(srt_a.a, srt_a.a + srt_a.n); + occ <<= 1; ta->n = 0; kv_resize(u_trans_t, *ta, occ); + for (i = 0; i < srt_a.n; i++) { + tz = &(srt_a.a[i]); + bl = &(sl.res[(uint32_t)(tz->x)]); + k = tz->rid; k <<= 32; k += tz->pos; + assert(bl->a[k].qn == (tz->x>>32)); + for (; (k < bl->n) && (bl->a[k].qn == (tz->x>>32)); k++) { + if(bl->a[k].qn == bl->a[k].tn) continue; + kv_pushp(u_trans_t, *ta, &z); + (*z) = bl->a[k]; if(z->f == RC_3) z->f = RC_2; + + kv_pushp(u_trans_t, *ta, &z); + (*z) = bl->a[k]; if(z->f == RC_3) z->f = RC_2; + z->qn = bl->a[k].tn; z->qs = bl->a[k].ts; z->qe = bl->a[k].te; + z->tn = bl->a[k].qn; z->ts = bl->a[k].qs; z->te = bl->a[k].qe; + } + } + + for (k = 0; k < sl.n_thread; k++) free(sl.res[k].a); + free(sl.res); kv_destroy(srt_a); + kt_u_trans_t_idx(ta, ug->g->n_seq); + // dbg_prt_utg_trans(ta, ug, "after"); +} + + +void dbg_prt_utg_extra_trans(kv_u_trans_t *ta, ma_ug_t *ug, const char *o_n) +{ + char* gfa_name = (char*)malloc(strlen(o_n)+100); + FILE *fn = NULL; sprintf(gfa_name, "%s.tran.dbg.ovlp.log", o_n); + u_trans_t *p = NULL; uint32_t i; fn = fopen(gfa_name, "w"); + double nw[2], ml, uml, sec, fw; + for (i = 0; i < ta->n; i++) { + p = &(ta->a[i]); + if((p->f == RC_0) || (p->f == RC_1)) continue; + + sec = ((p->qe-p->qs)*asm_opt.trans_base_rate); + if(sec < ((p->te-p->ts)*asm_opt.trans_base_rate)) { + sec = ((p->te-p->ts)*asm_opt.trans_base_rate); + } + ml = p->qe - p->qs; uml = sec; ml -= uml; + nw[0] = (ml*CHAIN_MATCH) - (uml*CHAIN_UNMATCH); + ml = p->te - p->ts; uml = sec; ml -= uml; + nw[1] = (ml*CHAIN_MATCH) - (uml*CHAIN_UNMATCH); + fw = MIN(nw[0], nw[1]); + if(fw <= p->nw) continue; + + fprintf(fn, "utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tw(%f)\tf(%u)\n", + p->qn+1, "lc"[ug->u.a[p->qn].circ], ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], + p->tn+1, "lc"[ug->u.a[p->tn].circ], ug->u.a[p->tn].len, p->ts, p->te, p->nw, p->f); + } + fclose(fn); free(gfa_name); fprintf(stderr, "[M::%s::] done\n", __func__); +} + +u_trans_cluster* gen_u_trans_cluster(kv_u_trans_t *ta) +{ + u_trans_cluster *p; CALLOC(p, 1); + p->z.n = p->z.m = ta->idx.n; MALLOC(p->z.a, p->z.n); + memset(p->z.a, -1, sizeof(*(p->z.a))*p->z.n); + u_trans_t *a = NULL; uint64_t n, v, k, l, i, cn, m; asg64_v b; kv_init(b); + for (i = b.n = cn = 0; i < ta->idx.n; i++) { + v = i; + if(p->z.a[v] != ((uint64_t)-1)) continue; + kv_push(uint64_t, b, v); m = 0; + while(b.n) { + v = b.a[--b.n]; + if(p->z.a[v] != ((uint64_t)-1)) continue; + p->z.a[v] = i; p->z.a[v] <<= 32; p->z.a[v] |= v; m++; + a = u_trans_a(*ta, v); n = u_trans_n(*ta, v); + for (k = 0; k < n; k++) { + if(p->z.a[a[k].tn] != ((uint64_t)-1)) continue; + kv_push(uint64_t, b, a[k].tn); + } + } + if(m > 1) cn++; + } + radix_sort_arch64(p->z.a, p->z.a + p->z.n); + p->idx.n = 0; p->idx.m = cn; CALLOC(p->idx.a, p->idx.m); + for (l = 0, k = 1; k <= p->z.n; k++) { + if(k == p->z.n || (p->z.a[k]>>32) != (p->z.a[l]>>32)) { + if(k - l > 1) p->idx.a[p->idx.n++] = (l<<32)|(k); + l = k; + } + } + assert(p->idx.n == cn); + free(b.a); + return p; +} + +void clean_u_trans_t_idx_filter_adv(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, double sc_sec_rate, uint64_t uniform_only) +{ + u_trans_clean_t sl; uint64_t k, i, l, st, occ; ha_mzl_t *tz; + ha_mzl_v srt_a; kv_u_trans_t *bl; u_trans_t *z; + memset(&sl, 0, sizeof(sl)); kv_init(srt_a); + + kt_u_trans_t_idx(ta, ug->g->n_seq); + sl.n_thread = asm_opt.thread_num; sl.ug = ug; sl.rg = read_g; sl.ta = ta; + CALLOC(sl.res, sl.n_thread); + sl.ov_cutoff = 3; sl.small_ov_rate = 0.8; sl.sc_sec_rate = sc_sec_rate; + // dbg_prt_utg_trans(ta, ug, "pre"); + kt_for(sl.n_thread, worker_for_trans_clean_re, &sl, sl.ta->idx.n); + + for (i = srt_a.n = occ = 0; i < sl.n_thread; i++) { + bl = &(sl.res[i]); + if(!(bl->n)) continue; + for (k = 1, l = 0; k <= bl->n; k++) { + if(k == bl->n || bl->a[k].qn != bl->a[l].qn) { + if(k > l) { + kv_pushp(ha_mzl_t, srt_a, &tz); + tz->x = bl->a[l].qn; tz->x <<= 32; tz->x |= i; + tz->rid = l>>32; tz->pos = (uint32_t)l; + occ += (k - l); + } + l = k; + } + } + } + // fprintf(stderr, "[M::%s::] occ::%lu \n", __func__, occ); + assert(srt_a.n <= sl.ug->u.n); + radix_sort_ha_mzl_t_srt1(srt_a.a, srt_a.a + srt_a.n); + occ <<= 1; ta->n = 0; kv_resize(u_trans_t, *ta, occ); + for (i = 0; i < srt_a.n; i++) { + tz = &(srt_a.a[i]); + bl = &(sl.res[(uint32_t)(tz->x)]); + k = tz->rid; k <<= 32; k += tz->pos; + assert(bl->a[k].qn == (tz->x>>32)); + for (; (k < bl->n) && (bl->a[k].qn == (tz->x>>32)); k++) { + if(bl->a[k].qn == bl->a[k].tn) continue; + kv_pushp(u_trans_t, *ta, &z); + (*z) = bl->a[k]; z->occ = 0; if(z->f == RC_3) z->f = RC_2; + + kv_pushp(u_trans_t, *ta, &z); + (*z) = bl->a[k]; z->occ = 0; if(z->f == RC_3) z->f = RC_2; + z->qn = bl->a[k].tn; z->qs = bl->a[k].ts; z->qe = bl->a[k].te; + z->tn = bl->a[k].qn; z->ts = bl->a[k].qs; z->te = bl->a[k].qe; + } + } + + for (k = 0; k < sl.n_thread; k++) free(sl.res[k].a); + free(sl.res); kv_destroy(srt_a); + kt_u_trans_t_idx(ta, ug->g->n_seq); + // dbg_prt_utg_trans(ta, ug, "after"); + if(uniform_only) return; + + + + CALLOC(sl.srt, sl.n_thread); sl.sec_rate = 0.5; sl.sc_sec_rate = sc_sec_rate; + kt_for(sl.n_thread, worker_for_trans_sec_cut, &sl, sl.ta->idx.n); + sl.cu = gen_u_trans_cluster(ta); + kt_for(sl.n_thread, worker_for_trans_sec_cut, &sl, sl.cu->idx.n); + free(sl.cu->idx.a); free(sl.cu->z.a); free(sl.cu); + for (k = 0; k < sl.n_thread; k++) {free(sl.srt[k].a);} free(sl.srt); + + for (k = st = 0; k < ta->n; k++) { + if(ta->a[k].occ == ((uint32_t)-1)) continue; + ta->a[st++] = ta->a[k]; + } + ta->n = st; + for (st = 0, i = 1; i <= ta->n; ++i) { + if (i == ta->n || ta->a[i].qn != ta->a[st].qn) { + ta->idx.a[ta->a[st].qn] = (((uint64_t)st)<<32)|(i-st); + st = i; + } + } + // dbg_prt_utg_extra_trans(ta, ug, asm_opt.output_file_name); +} + +void refine_hic_trans(ug_opt_t *opt, kv_u_trans_t *ta, asg_t *sg, ma_ug_t *ug) +{ + filter_u_trans(ta, asm_opt.is_bub_trans, asm_opt.is_topo_trans, asm_opt.is_read_trans, asm_opt.is_base_trans); + if(asm_opt.is_base_trans) { + trans_base_infer(ug, sg, opt, ta, NULL); + } + // dbg_prt_utg_trans(ta, ug, "pre"); + clean_u_trans_t_idx_filter_adv(ta, ug, sg, 0.95, 0); + // dbg_prt_utg_trans(ta, ug, "after"); +} + +void set_rset(ma_ug_t *ug, uint32_t uid, uint8_t *ff, uint8_t s) +{ + if(ug->g->seq[uid].del) return; + ma_utg_t* u; uint32_t k, v, nv, w, z; + asg_arc_t *av = NULL; + + u = &(ug->u.a[uid]); + for (k = 0; k < u->n; k++) ff[u->a[k]>>33] = s; + + v = uid<<1; + nv = asg_arc_n(ug->g, v); + av = asg_arc_a(ug->g, v); + for (k = 0; k < nv; k++) { + w = av[k].v; + if(av[k].del) continue; + if(ug->g->seq[w>>1].del) continue; + u = &(ug->u.a[w>>1]); + for (z = 0; z < u->n; z++) ff[u->a[z]>>33] = s; + } + + v = (uid<<1)+1; + nv = asg_arc_n(ug->g, v); + av = asg_arc_a(ug->g, v); + for (k = 0; k < nv; k++) { + w = av[k].v; + if(av[k].del) continue; + if(ug->g->seq[w>>1].del) continue; + u = &(ug->u.a[w>>1]); + for (z = 0; z < u->n; z++) ff[u->a[z]>>33] = s; + } +} + +uint32_t check_nc_status(asg_t *sg, ma_hit_t_alloc *src, uint8_t *ff, uint32_t id) +{ + uint32_t i, tn; ma_hit_t *h; + for (i = 0; i < src[id].length; i++) { + h = &(src[id].buffer[i]); tn = Get_tn((*h)); + if(sg->seq[tn].del) continue; + if(!ff[tn]) continue; + if((Get_qs((*h)) == 0) && (Get_qe((*h)) == sg->seq[id].len)) return 1; + } + return 0; +} + +uint64_t *gen_cov_rg(ma_ug_t *ug, asg_t *sg, ma_hit_t_alloc *src) +{ + uint32_t i, k, rid, j, tn; uint8_t *ff; + uint64_t C_bases, *cc; ma_hit_t *h; ma_utg_t *u; + CALLOC(cc, sg->n_seq); CALLOC(ff, sg->n_seq); + + for (i = 0; i < ug->g->n_seq; i++) { + if(ug->g->seq[i].del) continue; + set_rset(ug, i, ff, 1); + + u = &(ug->u.a[i]); + for (k = 0; k < u->n; k++) { + C_bases = 0; rid = u->a[k]>>33; + for (j = 0; j < src[rid].length; j++) { + h = &(src[rid].buffer[j]); + tn = Get_tn((*h)); + if((!sg->seq[tn].del) && (!ff[tn])) continue; + if((sg->seq[tn].del) && (!check_nc_status(sg, src, ff, tn))) continue; + C_bases += (Get_qe((*h)) - Get_qs((*h))); + } + if(C_bases > cc[rid]) cc[rid] = C_bases; + } + + set_rset(ug, i, ff, 0); + } + free(ff); + + return cc; +} + +void fill_cov_arr(ma_ug_t *ug, asg_t *sg, ma_hit_t_alloc *src, uint8_t *ff, uint64_t uid, uint64_t *res) +{ + ma_hit_t *h; ma_utg_t *u; + uint64_t C_bases, k, j, rid, tn; + set_rset(ug, uid, ff, 1); + + u = &(ug->u.a[uid]); + for (k = 0; k < u->n; k++) { + C_bases = 0; rid = u->a[k]>>33; + for (j = 0; j < src[rid].length; j++) { + h = &(src[rid].buffer[j]); + tn = Get_tn((*h)); + if((!sg->seq[tn].del) && (!ff[tn])) continue; + if((sg->seq[tn].del) && (!check_nc_status(sg, src, ff, tn))) continue; + C_bases += (Get_qe((*h)) - Get_qs((*h))); + } + res[k] = C_bases; + } + + set_rset(ug, uid, ff, 0); +} + +uint64_t infer_mmhap_copy(ma_ug_t *ug, asg_t *sg, ma_hit_t_alloc *src, uint8_t *ff, uint64_t uid, uint64_t het_cov, uint64_t n_hap) +{ + ma_hit_t *h; ma_utg_t *u; + uint64_t C_bases, R_bases, cc, dd, k, j, rid, tn, md, mk; + set_rset(ug, uid, ff, 1); + + u = &(ug->u.a[uid]); + for (k = C_bases = R_bases = 0; k < u->n; k++) { + rid = u->a[k]>>33; R_bases += sg->seq[rid].len; + for (j = 0; j < src[rid].length; j++) { + h = &(src[rid].buffer[j]); + tn = Get_tn((*h)); + if((!sg->seq[tn].del) && (!ff[tn])) continue; + if((sg->seq[tn].del) && (!check_nc_status(sg, src, ff, tn))) continue; + C_bases += (Get_qe((*h)) - Get_qs((*h))); + } + // res[k] = C_bases; + } + + set_rset(ug, uid, ff, 0); + + if(R_bases) C_bases /= R_bases; + else C_bases = 0; + + md = mk = (uint64_t)-1; + for (k = 1; k <= n_hap; k++) { + cc = het_cov*k; + dd = ((C_bases>=cc)?(C_bases-cc):(cc-C_bases)); + if(dd <= md) { + md = dd; mk = k; + } + } + if(mk == ((uint64_t)-1)) mk = n_hap; + return mk; +} + +ug_rid_cov_t* gen_ug_rid_cov_t(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc *src) +{ + uint64_t k; uint8_t *ff; CALLOC(ff, rg->n_seq); + ug_rid_cov_t *p; CALLOC(p, 1); + p->rg = rg; p->ug = ug; + MALLOC(p->idx, ug->g->n_seq); + p->cov.n = p->cov.m = 0; p->cov.a = NULL; + for (k = 0; k < p->ug->u.n; k++) { + p->idx[k] = p->cov.n; p->cov.n += p->ug->u.a[k].n; + } + p->cov.m = p->cov.n; MALLOC(p->cov.a, p->cov.n); + for (k = 0; k < p->ug->u.n; k++) { + fill_cov_arr(ug, rg, src, ff, k, p->cov.a+p->idx[k]); + } + free(ff); + + uint64_t hom_cov, het_cov, hom_cut; + if(asm_opt.hom_global_coverage_set) { + hom_cov = asm_opt.hom_global_coverage; + } else { + hom_cov = ((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE); + } + het_cov = hom_cov/asm_opt.polyploidy; + hom_cut = hom_cov + (het_cov*(0.5+(((double)asm_opt.polyploidy)*0.05))); + p->hom_max = hom_cut; + p->hom_min = (het_cov*(asm_opt.polyploidy-1)) + (het_cov*(0.5+(((double)(asm_opt.polyploidy-1))*0.05))); + p->hom_cov = hom_cov; p->het_cov = het_cov; + return p; +} + +void destory_ug_rid_cov_t(ug_rid_cov_t *p) +{ + if(!p) return; + free(p->idx); free(p->cov.a); +} + +uint64_t get_ovlp_cov(ma_utg_t *in, uint64_t *cc, asg_t *sg, int64_t s, int64_t e, int64_t *itk, int64_t *itl, uint64_t reflen) +{ + int64_t k, l, n = in->n; uint64_t rid, o, ol; int64_t qs, qe, os, oe; + k = (*itk); l = (*itl); o = ol = 0; + if(k >= n) { + k = n-1; l = ((int64_t)(in->len))-((int64_t)(sg->seq[k].len)); + } + if(k < 0 || l < 0) { + k = 0; l = 0; + } + + + for (; k > 0; k--) { + rid = in->a[k]>>33; + qs = l; qe = l + sg->seq[rid].len; + if(qe <= s) break; + l -= (int64_t)((uint32_t)in->a[k]); + } + + for (; k < n; k++) { + rid = in->a[k]>>33; + qs = l; qe = l + sg->seq[rid].len; + if(qs >= e) break; + l += (uint32_t)in->a[k]; + if(qe <= s) continue; + + os = MAX(qs, s); oe = MIN(qe, e); + if(oe <= os) continue; + assert(oe > os); + o += (((double)(oe-os))/((double)(sg->seq[rid].len)))*(cc[rid]); + ol += oe - os; + } + + (*itk) = k; (*itl) = l; + o = ((ol)?(o/ol):(0)); + return o*reflen; +} + +uint64_t get_ovlp_cov_1(ma_utg_t *in, uint64_t *idx, asg_t *sg, int64_t s, int64_t e, int64_t *itk, int64_t *itl, uint64_t reflen) +{ + int64_t k, l, n = in->n; uint64_t rid, o, ol; int64_t qs, qe, os, oe; + k = (*itk); l = (*itl); o = ol = 0; + if(k >= n) { + k = n-1; l = ((int64_t)(in->len))-((int64_t)(sg->seq[k].len)); + } + if(k < 0 || l < 0) { + k = 0; l = 0; + } + + + for (; k > 0; k--) { + rid = in->a[k]>>33; + qs = l; qe = l + sg->seq[rid].len; + if(qe <= s) break; + l -= (int64_t)((uint32_t)in->a[k]); + } + + for (; k < n; k++) { + rid = in->a[k]>>33; + qs = l; qe = l + sg->seq[rid].len; + if(qs >= e) break; + l += (uint32_t)in->a[k]; + if(qe <= s) continue; + + os = MAX(qs, s); oe = MIN(qe, e); + if(oe <= os) continue; + assert(oe > os); + o += (((double)(oe-os))/((double)(sg->seq[rid].len)))*(idx[k]); + ol += oe - os; + } + + (*itk) = k; (*itl) = l; + o = ((ol)?(o/ol):(0)); + return o*reflen; +} + +uint32_t append_cov_line_ug_rid_cov_t(uint64_t uid, uint64_t *qcc, u_trans_t *p, ug_rid_cov_t *idx, uint64_t hom_cut, double cut_rate) +{ + uint32_t k, rid; uint64_t qs, qe, oqs, oqe, ovq, ots, ote, no, tot, ava; + ma_utg_t *qu, *tu; uint64_t s_shift, e_shift; int64_t itk, itl, l; + qu = &(idx->ug->u.a[p->qn]); tu = &(idx->ug->u.a[p->tn]); + if(qu->n <= 0 || tu->n <= 0) return 0; + if(p->rev) { + itk = tu->n-1; itl = ((int64_t)(tu->len))-((int64_t)(idx->rg->seq[itk].len)); + } else { + itk = 0; itl = 0; + } + // if(uid == 7929) { + // fprintf(stderr, "*****[M::%s]\tutg%.6lu%c\tqu->n::%u\ttu->n::%u\n", __func__, + // uid+1, "lc"[idx->ug->u.a[uid].circ], (uint32_t)qu->n, (uint32_t)tu->n); + // } + for (k = l = 0, tot = ava = 0; k < qu->n; k++) { + rid = qu->a[k]>>33; + qs = l; qe = l + idx->rg->seq[rid].len; + l += (uint32_t)qu->a[k]; + if(qe <= p->qs) continue; + if(qs >= p->qe) break; + ///qe > p->qs && qs < p->qe && qe > qs + + oqs = MAX(qs, p->qs); oqe = MIN(qe, p->qe); + ovq = ((oqe > oqs)? (oqe - oqs):0); + + // if(!(ovq > 0)) { + // fprintf(stderr, "[M::%s::] qn::%u, tn::%u, q::[%lu, %lu), p->q::[%u, %u)\n", + // __func__, p->qn, p->tn, qs, qe, p->qs, p->qe); + // } + if(ovq <= 0) continue; + assert(ovq > 0); + if((hom_cut != ((uint64_t)-1)) && (cut_rate >= 0) && (ovq <= (idx->rg->seq[rid].len*0.55))) { + continue; + } + + s_shift = get_offset_adjust(oqs-p->qs, p->qe-p->qs, p->te-p->ts); + e_shift = get_offset_adjust(p->qe-oqe, p->qe-p->qs, p->te-p->ts); + if(p->rev) { + ovq = s_shift; s_shift = e_shift; e_shift = ovq; + } + ots = p->ts + s_shift; ote = p->te-e_shift; + if(ote <= ots) continue; + no = get_ovlp_cov_1(tu, idx->cov.a + idx->idx[p->tn], idx->rg, ots, ote, &itk, &itl, idx->rg->seq[rid].len); + // if(uid == 7929) { + // fprintf(stderr, "[%u]\trid::%u\tno::%lu\tqcc[k]::%lu\trlen::%u\n", + // k, rid, no, qcc[k], idx->rg->seq[rid].len); + // } + // to = qcc[k] + no; + // qcc[k] = to; + if((hom_cut == ((uint64_t)-1)) || (cut_rate < 0)) { + qcc[k] += no; + } else { + tot++; + if((qcc[k] + no) <= (hom_cut*((uint64_t)idx->rg->seq[rid].len))) ava++; + } + } + + // if(uid == 7929) { + // fprintf(stderr, "[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tis_reliable::%u\tw::%f\n", __func__, + // p->qn+1, "lc"[idx->ug->u.a[p->qn].circ], idx->ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], + // p->tn+1, "lc"[idx->ug->u.a[p->tn].circ], idx->ug->u.a[p->tn].len, p->ts, p->te, ((p->f == RC_0) || (p->f == RC_1))?1:0, p->nw); + // fprintf(stderr, "[M::%s]\tutg%.6lu%c\thom_cut::%lu\tcut_rate::%f\tava::%lu\ttot::%lu\n", __func__, + // uid+1, "lc"[idx->ug->u.a[uid].circ], hom_cut, cut_rate, ava, tot); + // } + + if((hom_cut != ((uint64_t)-1)) && (cut_rate >= 0) && (ava >= (tot*cut_rate))) { + return 1; + } + return 0; +} + +uint32_t append_cov_line(uint64_t uid, uint64_t *qcc, uint64_t *cc, u_trans_t *p, ma_ug_t *ug, asg_t *sg, uint64_t hom_cut, double cut_rate) +{ + uint32_t k, rid; uint64_t qs, qe, oqs, oqe, ovq, ots, ote, no, tot, ava; + ma_utg_t *qu, *tu; uint64_t s_shift, e_shift; int64_t itk, itl, l; + qu = &(ug->u.a[p->qn]); tu = &(ug->u.a[p->tn]); + if(qu->n <= 0 || tu->n <= 0) return 0; + if(p->rev) { + itk = tu->n-1; itl = ((int64_t)(tu->len))-((int64_t)(sg->seq[itk].len)); + } else { + itk = 0; itl = 0; + } + // if(uid == 315 || uid == 1055) { + // fprintf(stderr, "*****[M::%s]\tutg%.6lu%c\tqu->n::%u\ttu->n::%u\n", __func__, + // uid+1, "lc"[ug->u.a[uid].circ], (uint32_t)qu->n, (uint32_t)tu->n); + // } + for (k = l = 0, tot = ava = 0; k < qu->n; k++) { + rid = qu->a[k]>>33; + qs = l; qe = l + sg->seq[rid].len; + l += (uint32_t)qu->a[k]; + if(qe <= p->qs) continue; + if(qs >= p->qe) break; + ///qe > p->qs && qs < p->qe && qe > qs + + oqs = MAX(qs, p->qs); oqe = MIN(qe, p->qe); + ovq = ((oqe > oqs)? (oqe - oqs):0); + + // if(!(ovq > 0)) { + // fprintf(stderr, "[M::%s::] qn::%u, tn::%u, q::[%lu, %lu), p->q::[%u, %u)\n", + // __func__, p->qn, p->tn, qs, qe, p->qs, p->qe); + // } + if(ovq <= 0) continue; + assert(ovq > 0); + if((hom_cut != ((uint64_t)-1)) && (cut_rate >= 0) && (ovq <= (sg->seq[rid].len*0.55))) { + continue; + } + + s_shift = get_offset_adjust(oqs-p->qs, p->qe-p->qs, p->te-p->ts); + e_shift = get_offset_adjust(p->qe-oqe, p->qe-p->qs, p->te-p->ts); + if(p->rev) { + ovq = s_shift; s_shift = e_shift; e_shift = ovq; + } + ots = p->ts + s_shift; ote = p->te-e_shift; + if(ote <= ots) continue; + no = get_ovlp_cov(tu, cc, sg, ots, ote, &itk, &itl, sg->seq[rid].len); + // if(uid == 315 || uid == 1055) { + // fprintf(stderr, "[%u]\trid::%u\tno::%lu\tqcc[k]::%lu\trlen::%u\n", k, rid, no, qcc[k], sg->seq[rid].len); + // } + // to = qcc[k] + no; + // qcc[k] = to; + if((hom_cut == ((uint64_t)-1)) || (cut_rate < 0)) { + qcc[k] += no; + } else { + tot++; + if((qcc[k] + no) <= (hom_cut*((uint64_t)sg->seq[rid].len))) ava++; + } + } + + // if(uid == 315 || uid == 1055) { + // fprintf(stderr, "[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tis_reliable::%u\tw::%f\n", __func__, + // p->qn+1, "lc"[ug->u.a[p->qn].circ], ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], + // p->tn+1, "lc"[ug->u.a[p->tn].circ], ug->u.a[p->tn].len, p->ts, p->te, ((p->f == RC_0) || (p->f == RC_1))?1:0, p->nw); + // fprintf(stderr, "[M::%s]\tutg%.6lu%c\thom_cut::%lu\tcut_rate::%f\tava::%lu\ttot::%lu\n", __func__, + // uid+1, "lc"[ug->u.a[uid].circ], hom_cut, cut_rate, ava, tot); + // } + + if((hom_cut != ((uint64_t)-1)) && (cut_rate >= 0) && (ava >= (tot*cut_rate))) { + return 1; + } + return 0; +} + +void purge_ovlp_cov(uint32_t id, kv_u_trans_t *ta, ma_ug_t *ug, asg_t *sg, asg64_v *b64, uint64_t *cc, uint64_t hom_cut) +{ + ma_utg_t *u = &(ug->u.a[id]); uint32_t k, n, cn; + u_trans_t *a = NULL, t; + kv_resize(uint64_t, *b64, u->n); + for (k = 0; k < u->n; k++) b64->a[k] = cc[u->a[k]>>33]; + a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); + // if(id == 315 || id == 1055) { + // fprintf(stderr, "\n[M::%s]\tutg%.6u%c\tn::%u\n", __func__, id+1, "lc"[ug->u.a[id].circ], n); + // } + for (k = cn = 0; k < n; k++) {///RC_0/RC_1 to a[0, r_n) + // if(id == 315 || id == 1055) { + // fprintf(stderr, "-0-[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tis_reliable::%u\tw::%f\n", __func__, + // a[k].qn+1, "lc"[ug->u.a[a[k].qn].circ], ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], + // a[k].tn+1, "lc"[ug->u.a[a[k].tn].circ], ug->u.a[a[k].tn].len, a[k].ts, a[k].te, + // ((a[k].f == RC_0) || (a[k].f == RC_1))?1:0, a[k].nw); + // } + if((a[k].f == RC_0) || (a[k].f == RC_1)) { + if(k != cn) { + t = a[k]; a[k] = a[cn]; a[cn] = t; + } + cn++; + } + } + // if(id == 315 || id == 1055) { + // fprintf(stderr, "[M::%s]\tutg%.6u%c\tn::%u\tcn::%u\n", __func__, + // id+1, "lc"[ug->u.a[id].circ], n, cn); + // } + if(cn >= n) return; + if(n-cn > 1) qsort(a+cn, n-cn, sizeof((*a)), cmp_u_trans_weight); + for (k = 0; k < cn; k++) {///calculate coverage for + append_cov_line(id, b64->a, cc, &(a[k]), ug, sg, ((uint64_t)-1), -1); + } + + for (k = cn; k < n; k++) { + if(append_cov_line(id, b64->a, cc, &(a[k]), ug, sg, hom_cut, 0.51)) { + append_cov_line(id, b64->a, cc, &(a[k]), ug, sg, ((uint64_t)-1), -1); + continue; + } + a[k].del = 1; + } +} + +void trans_sec_cut_filter_mmhap(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *sg, ma_hit_t_alloc* src) +{ + uint64_t k, hom_cov, het_cov, hom_cut; + asg64_v b64; kv_init(b64); + uint64_t *cc = gen_cov_rg(ug, sg, src); + if(asm_opt.hom_global_coverage_set) { + hom_cov = asm_opt.hom_global_coverage; + } else { + hom_cov = ((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE); + } + het_cov = hom_cov/asm_opt.polyploidy; + hom_cut = hom_cov + (het_cov*(0.5+(((double)asm_opt.polyploidy)*0.05))); + + fprintf(stderr, "+[M::%s]\thom_cov::%lu\thet_cov::%lu\thom_cut::%lu\n", __func__, + hom_cov, het_cov, hom_cut); + + for (k = 0; k < ug->g->n_seq; k++) { + purge_ovlp_cov(k, ta, ug, sg, &b64, cc, hom_cut); + } + free(cc); kv_destroy(b64); +} + + +void purge_ovlp_cov_adv(uint32_t id, kv_u_trans_t *ta, asg64_v *b64, ug_rid_cov_t *cc, uint64_t hom_cut) +{ + ma_utg_t *u = &(cc->ug->u.a[id]); uint32_t k, n, cn; + u_trans_t *a = NULL, t; + kv_resize(uint64_t, *b64, u->n); + memcpy(b64->a, cc->cov.a+cc->idx[id], sizeof((*(b64->a)))*cc->ug->u.a[id].n); + a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); + // if(id == 7929) { + // fprintf(stderr, "\n[M::%s]\tutg%.6u%c\tn::%u\n", __func__, id+1, "lc"[cc->ug->u.a[id].circ], n); + // } + for (k = cn = 0; k < n; k++) {///RC_0/RC_1 to a[0, r_n) + // if(id == 7929) { + // fprintf(stderr, "-0-[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tis_reliable::%u\tw::%f\n", __func__, + // a[k].qn+1, "lc"[cc->ug->u.a[a[k].qn].circ], cc->ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], + // a[k].tn+1, "lc"[cc->ug->u.a[a[k].tn].circ], cc->ug->u.a[a[k].tn].len, a[k].ts, a[k].te, + // ((a[k].f == RC_0) || (a[k].f == RC_1))?1:0, a[k].nw); + // } + if((a[k].f == RC_0) || (a[k].f == RC_1)) { + if(k != cn) { + t = a[k]; a[k] = a[cn]; a[cn] = t; + } + cn++; + } + } + // if(id == 7929) { + // fprintf(stderr, "[M::%s]\tutg%.6u%c\tn::%u\tcn::%u\n", __func__, + // id+1, "lc"[cc->ug->u.a[id].circ], n, cn); + // } + if(cn >= n) return; + if(n-cn > 1) qsort(a+cn, n-cn, sizeof((*a)), cmp_u_trans_weight); + for (k = 0; k < cn; k++) {///calculate coverage for + append_cov_line_ug_rid_cov_t(id, b64->a, &(a[k]), cc, ((uint64_t)-1), -1); + } + + for (k = cn; k < n; k++) { + if(append_cov_line_ug_rid_cov_t(id, b64->a, &(a[k]), cc, hom_cut, 0.51)) { + append_cov_line_ug_rid_cov_t(id, b64->a, &(a[k]), cc, ((uint64_t)-1), -1); + continue; + } + a[k].del = 1; + } +} + +void trans_sec_cut_filter_mmhap_adv(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *sg, ma_hit_t_alloc* src, ug_rid_cov_t *in) +{ + uint64_t k; asg64_v b64; kv_init(b64); + ug_rid_cov_t *cc = ((in)?(in):(gen_ug_rid_cov_t(ug, sg, src))); + + fprintf(stderr, "+[M::%s]\thom_cov::%lu\thet_cov::%lu\thom_cut::%lu\n", __func__, + cc->hom_cov, cc->het_cov, cc->hom_max); + + for (k = 0; k < ug->g->n_seq; k++) { + purge_ovlp_cov_adv(k, ta, &b64, cc, cc->hom_max); + } + + if(!in) {destory_ug_rid_cov_t(cc); free(cc);} kv_destroy(b64); +} + +static void worker_for_trans_sec_simple_cut(void *data, long i, int tid) // callback for kt_for() +{ + u_trans_clean_t *s = (u_trans_clean_t*)data; + kv_u_trans_t *ta = s->ta; u_trans_t *a, *za; + uint32_t id = i, n, k, z, zn; + + a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); + for (k = 0; k < n; k++) { + if((!a[k].del)) continue; + za = u_trans_a(*ta, a[k].tn); zn = u_trans_n(*ta, a[k].tn); + for (z = 0; z < zn; z++) { + if(za[z].tn == id) break; + } + assert(z < zn); + if(za[z].del) { ///both a[k] and za[z] have been deleted + if(a[k].qn < a[k].tn) a[k].occ = za[z].occ = ((uint32_t)-1); + continue; + } + ///a[k].del == 1 && za[z].del == 0 + if(za[z].qe-za[z].qs >= 3000000) { + a[k].occ = za[z].occ = 0; + } else { + a[k].occ = za[z].occ = ((uint32_t)-1); + } + } +} + +void gen_ug_rid_cov_t_by_ovlp(kv_u_trans_t *ta, ug_rid_cov_t *cc) +{ + uint64_t z, k, id, n; u_trans_t *a; + for (z = 0; z < cc->ug->g->n_seq; z++) { + id = z; a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); + for (k = 0; k < n; k++) { + append_cov_line_ug_rid_cov_t(id, cc->cov.a+cc->idx[id], &(a[k]), cc, ((uint64_t)-1), -1); + } + } +} + +void clean_u_trans_t_idx_filter_mmhap_adv(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* src, ug_rid_cov_t *in) +{ + u_trans_clean_t sl; uint64_t k, i, l, st, occ; ha_mzl_t *tz; + ha_mzl_v srt_a; kv_u_trans_t *bl; u_trans_t *z; + memset(&sl, 0, sizeof(sl)); kv_init(srt_a); + + kt_u_trans_t_idx(ta, ug->g->n_seq); + sl.n_thread = asm_opt.thread_num; sl.ug = ug; sl.rg = read_g; sl.ta = ta; + CALLOC(sl.res, sl.n_thread); + sl.ov_cutoff = 3; sl.small_ov_rate = 0.8; + // dbg_prt_utg_trans(ta, ug, "pre"); + kt_for(sl.n_thread, worker_for_trans_clean_re, &sl, sl.ta->idx.n); + + for (i = srt_a.n = occ = 0; i < sl.n_thread; i++) { + bl = &(sl.res[i]); + if(!(bl->n)) continue; + for (k = 1, l = 0; k <= bl->n; k++) { + if(k == bl->n || bl->a[k].qn != bl->a[l].qn) { + if(k > l) { + kv_pushp(ha_mzl_t, srt_a, &tz); + tz->x = bl->a[l].qn; tz->x <<= 32; tz->x |= i; + tz->rid = l>>32; tz->pos = (uint32_t)l; + occ += (k - l); + } + l = k; + } + } + } + // fprintf(stderr, "[M::%s::] occ::%lu \n", __func__, occ); + assert(srt_a.n <= sl.ug->u.n); + radix_sort_ha_mzl_t_srt1(srt_a.a, srt_a.a + srt_a.n); + occ <<= 1; ta->n = 0; kv_resize(u_trans_t, *ta, occ); + for (i = 0; i < srt_a.n; i++) { + tz = &(srt_a.a[i]); + bl = &(sl.res[(uint32_t)(tz->x)]); + k = tz->rid; k <<= 32; k += tz->pos; + assert(bl->a[k].qn == (tz->x>>32)); + for (; (k < bl->n) && (bl->a[k].qn == (tz->x>>32)); k++) { + if(bl->a[k].qn == bl->a[k].tn) continue; + if(bl->a[k].qe-bl->a[k].qs <= 0) continue; + if(bl->a[k].te-bl->a[k].ts <= 0) continue; + kv_pushp(u_trans_t, *ta, &z); + (*z) = bl->a[k]; z->occ = 0; if(z->f == RC_3) z->f = RC_2; + // if(z->ts >= z->te || z->qs >= z->qe) { + // fprintf(stderr, "+[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, + // z->qn+1, "lc"[ug->u.a[z->qn].circ], ug->u.a[z->qn].len, z->qs, z->qe, "+-"[z->rev], + // z->tn+1, "lc"[ug->u.a[z->tn].circ], ug->u.a[z->tn].len, z->ts, z->te); + // } + + kv_pushp(u_trans_t, *ta, &z); + (*z) = bl->a[k]; z->occ = 0; if(z->f == RC_3) z->f = RC_2; + z->qn = bl->a[k].tn; z->qs = bl->a[k].ts; z->qe = bl->a[k].te; + z->tn = bl->a[k].qn; z->ts = bl->a[k].qs; z->te = bl->a[k].qe; + + // if(z->ts >= z->te || z->qs >= z->qe) { + // fprintf(stderr, "-[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, + // z->qn+1, "lc"[ug->u.a[z->qn].circ], ug->u.a[z->qn].len, z->qs, z->qe, "+-"[z->rev], + // z->tn+1, "lc"[ug->u.a[z->tn].circ], ug->u.a[z->tn].len, z->ts, z->te); + // } + } + } + + for (k = 0; k < sl.n_thread; k++) free(sl.res[k].a); + free(sl.res); kv_destroy(srt_a); + kt_u_trans_t_idx(ta, ug->g->n_seq); + // dbg_prt_utg_trans(ta, ug, "after"); + trans_sec_cut_filter_mmhap_adv(ta, ug, read_g, src, in); + kt_for(sl.n_thread, worker_for_trans_sec_simple_cut, &sl, sl.ta->idx.n); + + // CALLOC(sl.srt, sl.n_thread); sl.sec_rate = 0.5; + // kt_for(sl.n_thread, worker_for_trans_sec_cut, &sl, sl.ta->idx.n); + // sl.cu = gen_u_trans_cluster(ta); + // kt_for(sl.n_thread, worker_for_trans_sec_cut, &sl, sl.cu->idx.n); + // free(sl.cu->idx.a); free(sl.cu->z.a); free(sl.cu); + // for (k = 0; k < sl.n_thread; k++) free(sl.srt[k].a); free(sl.srt); + for (k = st = 0; k < ta->n; k++) { + if(ta->a[k].occ == ((uint32_t)-1)) continue; + ta->a[st] = ta->a[k]; ta->a[st].del = 0; st++; + } + ta->n = st; + for (st = 0, i = 1; i <= ta->n; ++i) { + if (i == ta->n || ta->a[i].qn != ta->a[st].qn) { + ta->idx.a[ta->a[st].qn] = (((uint64_t)st)<<32)|(i-st); + st = i; + } + } + + // dbg_prt_utg_extra_trans(ta, ug, asm_opt.output_file_name); +} + +void refine_hic_trans_mmhap(ug_opt_t *opt, kv_u_trans_t *ta, asg_t *sg, ma_ug_t *ug) +{ + filter_u_trans(ta, asm_opt.is_bub_trans, asm_opt.is_topo_trans, asm_opt.is_read_trans, asm_opt.is_base_trans); + if(asm_opt.is_base_trans) { + trans_base_mmhap_infer(ug, sg, opt, ta); + } + // dbg_prt_utg_trans(ta, ug, "pre"); + // clean_u_trans_t_idx_filter_mmhap_adv(ta, ug, sg, opt->sources); + // dbg_prt_utg_trans(ta, ug, "after"); +} + +void output_contig_graph_alternative(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, R_to_U* ruIndex, int max_hang, int min_ovlp); +void output_hic_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, +R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, +long long gap_fuzz, bub_label_t* b_mask_t, ug_opt_t *opt) +{ + hic_clean(sg); + kvec_pe_hit *rhits = NULL; + ma_ug_t *ug_fa = NULL, *ug_mo = NULL; + + kvec_asg_arc_t_warp new_rtg_edges, d_edges; + kv_init(new_rtg_edges.a); kv_init(d_edges.a); + ma_ug_t *ug = NULL; + ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); + + new_rtg_edges.a.n = 0; + ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, &d_edges, 1);///polish + + hap_cov_t *cov = NULL; + trans_chain* t_ch = NULL; + if((asm_opt.flag & HA_F_VERBOSE_GFA)) t_ch = load_hc_trans(output_file_name); + + if(!t_ch) + { + new_rtg_edges.a.n = 0; + asg_t *copy_sg = copy_read_graph(sg); + ma_ug_t *copy_ug = copy_untig_graph(ug); + ///asm_opt.purge_overlap_len = asm_opt.purge_overlap_len_hic; + ///asm_opt.purge_simi_thres = asm_opt.purge_simi_rate_hic; + adjust_utg_by_primary(©_ug, copy_sg, TRIO_THRES, sources, reverse_sources, coverage_cut, + tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, + max_hang, min_ovlp, &new_rtg_edges, &cov, b_mask_t, 1, 0); + print_utg(©_ug, copy_sg, coverage_cut, output_file_name, sources, ruIndex, max_hang, + min_ovlp, &new_rtg_edges); + + if(asm_opt.is_alt) + { + output_contig_graph_alternative(copy_sg, coverage_cut, output_file_name, sources, ruIndex, max_hang, + min_ovlp); + } + ma_ug_destroy(copy_ug); + asg_destroy(copy_sg); + // clean_u_trans_t_idx(&(cov->t_ch->k_trans), ug, sg); + + + new_rtg_edges.a.n = 0; + ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, + max_hang, min_ovlp, asm_opt.hic_inconsist_rate, NULL, NULL, cov->t_ch); + + if((asm_opt.flag & HA_F_VERBOSE_GFA)) write_trans_chain(cov->t_ch, output_file_name); + } + + refine_hic_trans(opt, &(cov?cov->t_ch->k_trans:t_ch->k_trans), sg, ug); + ///for debug + // char* gfa_name = (char*)malloc(strlen(output_file_name)+50); FILE* output_file = NULL; + + // sprintf(gfa_name, "%s.pre.clean_d_utg.noseq.gfa", output_file_name); + // output_file = fopen(gfa_name, "w"); + // ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + // fclose(output_file); + + // sprintf(gfa_name, "%s.pre.clean_d_utg.gfa", output_file_name); + // output_file = fopen(gfa_name, "w"); + // ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + // fclose(output_file); + + // free(gfa_name); + // exit(1); + ///for debug + + + + hic_analysis(ug, sg, cov?cov->t_ch:t_ch, opt, NULL, asm_opt.scffold?&rhits:NULL); + + + if(!rhits && cov) destory_hap_cov_t(&cov); + if(!rhits && t_ch) destory_trans_chain(&t_ch); + + + // char* gfa_name = (char*)malloc(strlen(output_file_name)+50); + // sprintf(gfa_name, "%s.after.clean_d_utg.noseq.gfa", output_file_name); + // FILE* output_file = fopen(gfa_name, "w"); + // ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + // fclose(output_file); + // free(gfa_name); + + ma_ug_destroy(ug); + kv_destroy(new_rtg_edges.a); + + + asg_arc_t* av = NULL; + uint32_t v, w, k, i, nv; + for (i = 0; i < d_edges.a.n; i++) + { + v = d_edges.a.a[i].ul>>32; + w = d_edges.a.a[i].v; + av = asg_arc_a(sg, v); + nv = asg_arc_n(sg, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + av[k].del = 1; + break; + } + } + } + kv_destroy(d_edges.a); + asg_cleanup(sg); + + // reduce_hamming_error_adv(NULL, sg, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz, opt->ruIndex, NULL); + + // ug_fa = output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, + // 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, rhits?1:0, b_mask_t, NULL, NULL, NULL); + // ug_mo = output_trio_unitig_graph(sg, coverage_cut, output_file_name, MOTHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, + // 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, rhits?1:0, b_mask_t, NULL, NULL, NULL); + + + output_trio_graph_joint(sg, coverage_cut, output_file_name, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, + 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, b_mask_t, rhits?(&ug_fa):NULL, rhits?(&ug_mo):NULL, opt); + if(rhits) + { + ha_aware_order(rhits, sg, ug_fa, ug_mo, cov?&(cov->t_ch->k_trans):&(t_ch->k_trans), opt, 3); + kv_destroy(rhits->a); kv_destroy(rhits->idx); kv_destroy(rhits->occ); free(rhits); + if(cov) destory_hap_cov_t(&cov); + if(t_ch) destory_trans_chain(&t_ch); + ma_ug_destroy(ug_fa); ma_ug_destroy(ug_mo); + } +} + + +uint64_t dump_trans_ovlp(trans_chain* t_ch, const char *fn, ma_ug_t *ug) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(fn)+50); + sprintf(gfa_name, "%s.trans.bin", fn); + FILE* fp = fopen(gfa_name, "w"); free(gfa_name); + if (!fp) return 0; + if(ug) write_dbug(ug, fp); + + fwrite(&t_ch->r_num, sizeof(t_ch->r_num), 1, fp); + fwrite(t_ch->ir_het, sizeof(uint8_t), t_ch->r_num, fp); + uint64_t i; + fwrite(&t_ch->bed.n, sizeof(t_ch->bed.n), 1, fp); + for (i = 0; i < t_ch->bed.n; i++) { + fwrite(&t_ch->bed.a[i].n, sizeof(t_ch->bed.a[i].n), 1, fp); + fwrite(t_ch->bed.a[i].a, sizeof(bed_interval), t_ch->bed.a[i].n, fp); + } + + fwrite(&t_ch->k_trans.n, sizeof(t_ch->k_trans.n), 1, fp); + fwrite(t_ch->k_trans.a, sizeof(u_trans_t), t_ch->k_trans.n, fp); + + fwrite(&t_ch->k_trans.idx.n, sizeof(t_ch->k_trans.idx.n), 1, fp); + fwrite(t_ch->k_trans.idx.a, sizeof(uint64_t), t_ch->k_trans.idx.n, fp); + + fclose(fp); + fprintf(stderr, "[M::%s] Dump trans overlaps\n", __func__); + return 1; +} + +trans_chain* load_trans_ovlp(const char *fn, ma_ug_t *ug) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(fn)+50); + sprintf(gfa_name, "%s.trans.bin", fn); + FILE* fp = fopen(gfa_name, "r"); free(gfa_name); + if (!fp) return NULL; + if(ug && (!test_dbug(ug, fp))) { + fprintf(stderr, "[M::%s] Renew trans overlaps\n", __func__); + fclose(fp); + return NULL; + } + + uint64_t flag = 0; + trans_chain *t_ch = NULL; + CALLOC(t_ch, 1); + + flag += fread(&t_ch->r_num, sizeof(t_ch->r_num), 1, fp); + MALLOC(t_ch->ir_het, t_ch->r_num); + flag += fread(t_ch->ir_het, sizeof(uint8_t), t_ch->r_num, fp); + + uint64_t i; + flag += fread(&t_ch->bed.n, sizeof(t_ch->bed.n), 1, fp); + MALLOC(t_ch->bed.a, t_ch->bed.n); t_ch->bed.m = t_ch->bed.n; + for (i = 0; i < t_ch->bed.n; i++) { + flag += fread(&t_ch->bed.a[i].n, sizeof(t_ch->bed.a[i].n), 1, fp); + MALLOC(t_ch->bed.a[i].a, t_ch->bed.a[i].n); t_ch->bed.a[i].m = t_ch->bed.a[i].n; + flag += fread(t_ch->bed.a[i].a, sizeof(bed_interval), t_ch->bed.a[i].n, fp); + } + + flag += fread(&t_ch->k_trans.n, sizeof(t_ch->k_trans.n), 1, fp); + MALLOC(t_ch->k_trans.a, t_ch->k_trans.n); t_ch->k_trans.m = t_ch->k_trans.n; + flag += fread(t_ch->k_trans.a, sizeof(u_trans_t), t_ch->k_trans.n, fp); + + flag += fread(&t_ch->k_trans.idx.n, sizeof(t_ch->k_trans.idx.n), 1, fp); + MALLOC(t_ch->k_trans.idx.a, t_ch->k_trans.idx.n); t_ch->k_trans.idx.m = t_ch->k_trans.idx.n; + flag += fread(t_ch->k_trans.idx.a, sizeof(uint64_t), t_ch->k_trans.idx.n, fp); + + fclose(fp); + fprintf(stderr, "[M::%s::] ==> Trans overlaps have been loaded\n", __func__); + return t_ch; +} + +void update_trio_mmhap(uint32_t hapid, ma_ug_t *mm_ug, mmhap_t *rh, asg_t *sg, uint32_t n_hap) +{ + uint64_t k, z, m, rid; ma_utg_t *u; + for (k = 0; k < sg->n_seq; k++) { + if(R_INF.trio_flag[k] == DROP) continue; + R_INF.trio_flag[k] = AMBIGU; + } + + for (k = 0; k < mm_ug->u.n; k++) { + if(rh->h.a[k].m == n_hap || rh->h.a[k].n == 0) { + m = AMBIGU; + } else { + for (z = 0, m = MOTHER; z < rh->h.a[k].n; z++) { + if(rh->a.a[rh->h.a[k].a+z] == hapid) {m = FATHER; break;} + } + } + + u = &(mm_ug->u.a[k]); + for (z = 0; z < u->n; z++) { + rid = u->a[z]>>33; + if(R_INF.trio_flag[rid] == DROP) continue; + R_INF.trio_flag[rid] = m; + } + fprintf(stderr, "utg%.6lu%c\tm::%lu\n", k+1, "lc"[mm_ug->u.a[k].circ], m); + } +} + +void dbg_prt_trio_mmhap_label(ma_ug_t *ug, mmhap_t *rh, const char *o_n) +{ + char* gfa_name = (char*)malloc(strlen(o_n)+100); + FILE *fn = NULL; sprintf(gfa_name, "%s.mmhap.binning.log", o_n); + uint32_t i, z; fn = fopen(gfa_name, "w"); + for (i = 0; i < ug->g->n_seq; i++) { + fprintf(fn, "utg%.6u%c\tm::%u\tn::%u", i+1, "lc"[ug->u.a[i].circ], rh->h.a[i].m, rh->h.a[i].n); + for (z = 0; z < rh->h.a[i].n; z++) { + fprintf(fn, "\t%u", rh->a.a[rh->h.a[i].a+z]); + } + fprintf(fn, "\n"); + } + fclose(fn); free(gfa_name); fprintf(stderr, "[M::%s::] done\n", __func__); +} + +void output_trio_mmhap(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, ma_hit_t_alloc* sources, +ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, +float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, long long gap_fuzz, bub_label_t* b_mask_t, ug_opt_t *opt, +ma_ug_t *mm_ug, mmhap_t *rh, uint32_t n_hap) +{ + uint32_t i; char *fp = NULL; MALLOC(fp, 100); + memset(R_INF.trio_flag, 0, sizeof((*(R_INF.trio_flag)))*sg->n_seq); + for (i = 0; i < n_hap; i++){ + sprintf(fp, "hap%u", i+1); + update_trio_mmhap(i, mm_ug, rh, sg, n_hap); + output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, reverse_sources, tipsLen, tip_drop_ratio, + stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, gap_fuzz, 0, b_mask_t, fp, NULL, NULL); + } + free(fp); +} + +void output_hic_graph_mmhap(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, ma_hit_t_alloc* sources, +ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, +float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, long long gap_fuzz, bub_label_t* b_mask_t, ug_opt_t *opt) +{ + hic_clean(sg); + mmhap_t *rh = NULL; + + kvec_asg_arc_t_warp new_rtg_edges, d_edges; + kv_init(new_rtg_edges.a); kv_init(d_edges.a); + ma_ug_t *ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); + + new_rtg_edges.a.n = 0; + ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, &d_edges, 1);///polish + + hap_cov_t *cov = NULL; + trans_chain* t_ch = NULL; + t_ch = load_trans_ovlp(output_file_name, ug); + // if((asm_opt.flag & HA_F_VERBOSE_GFA)) t_ch = load_hc_trans(output_file_name); + + if(!t_ch) { + new_rtg_edges.a.n = 0; + asg_t *copy_sg = copy_read_graph(sg); + ma_ug_t *copy_ug = copy_untig_graph(ug); + ///asm_opt.purge_overlap_len = asm_opt.purge_overlap_len_hic; + ///asm_opt.purge_simi_thres = asm_opt.purge_simi_rate_hic; + adjust_utg_by_primary(©_ug, copy_sg, TRIO_THRES, sources, reverse_sources, coverage_cut, + tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, + max_hang, min_ovlp, &new_rtg_edges, &cov, b_mask_t, 1, 0); + print_utg(©_ug, copy_sg, coverage_cut, output_file_name, sources, ruIndex, max_hang, + min_ovlp, &new_rtg_edges); + + if(asm_opt.is_alt) { + output_contig_graph_alternative(copy_sg, coverage_cut, output_file_name, sources, ruIndex, max_hang, + min_ovlp); + } + ma_ug_destroy(copy_ug); + asg_destroy(copy_sg); + // clean_u_trans_t_idx(&(cov->t_ch->k_trans), ug, sg); + + + new_rtg_edges.a.n = 0; + ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, + max_hang, min_ovlp, asm_opt.hic_inconsist_rate, NULL, NULL, cov->t_ch); + + refine_hic_trans_mmhap(opt, &(cov->t_ch->k_trans), sg, ug); + dump_trans_ovlp(cov->t_ch, output_file_name, ug); + // if((asm_opt.flag & HA_F_VERBOSE_GFA)) write_trans_chain(cov->t_ch, output_file_name); + } + + // dbg_prt_utg_trans(&(cov?cov->t_ch->k_trans:t_ch->k_trans), ug, "pre"); + clean_u_trans_t_idx_filter_mmhap_adv(&(cov?cov->t_ch->k_trans:t_ch->k_trans), ug, sg, opt->sources, NULL); + // dbg_prt_utg_trans(&(cov?cov->t_ch->k_trans:t_ch->k_trans), ug, "after"); + + // refine_hic_trans_mmhap(opt, &(cov?cov->t_ch->k_trans:t_ch->k_trans), sg, ug); + ///for debug + // dbg_prt_utg_trans(&(cov?cov->t_ch->k_trans:t_ch->k_trans), ug, "dd"); + // char* gfa_name = (char*)malloc(strlen(output_file_name)+50); FILE* output_file = NULL; + + // sprintf(gfa_name, "%s.pre.clean_d_utg.noseq.gfa", output_file_name); + // output_file = fopen(gfa_name, "w"); + // ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + // fclose(output_file); + + // sprintf(gfa_name, "%s.pre.clean_d_utg.gfa", output_file_name); + // output_file = fopen(gfa_name, "w"); + // ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + // fclose(output_file); + + // free(gfa_name); + // exit(1); + ///for debug + + + hic_analysis(ug, sg, cov?cov->t_ch:t_ch, opt, &rh, NULL); + + + if(cov) destory_hap_cov_t(&cov); + if(t_ch) destory_trans_chain(&t_ch); + + + // char* gfa_name = (char*)malloc(strlen(output_file_name)+50); + // sprintf(gfa_name, "%s.after.clean_d_utg.noseq.gfa", output_file_name); + // FILE* output_file = fopen(gfa_name, "w"); + // ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + // fclose(output_file); + // free(gfa_name); + + // ma_ug_destroy(ug); + kv_destroy(new_rtg_edges.a); + + + asg_arc_t* av = NULL; + uint32_t v, w, k, i, nv; + for (i = 0; i < d_edges.a.n; i++) + { + v = d_edges.a.a[i].ul>>32; + w = d_edges.a.a[i].v; + av = asg_arc_a(sg, v); + nv = asg_arc_n(sg, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + av[k].del = 1; + break; + } + } + } + kv_destroy(d_edges.a); + asg_cleanup(sg); + + // dbg_prt_trio_mmhap_label(ug, rh, output_file_name); + + output_trio_mmhap(sg, coverage_cut, output_file_name, sources, reverse_sources, tipsLen, tip_drop_ratio, + stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, gap_fuzz, b_mask_t, opt, ug, rh, asm_opt.polyploidy); + + ma_ug_destroy(ug); + free(rh->a.a); free(rh->h.a); free(rh); +} + +void print_debug_gfa(ma_ug_t *ug, asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, R_to_U* ruIndex) +{ + char* gfa_name = (char*)malloc(strlen(output_file_name)+50); + sprintf(gfa_name, "%s.after.clean_d_utg.gfa", output_file_name); + FILE* output_file = fopen(gfa_name, "w"); + ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + fclose(output_file); + + sprintf(gfa_name, "%s.after.clean_d_utg.noseq.gfa", output_file_name); + output_file = fopen(gfa_name, "w"); + ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + fclose(output_file); + + free(gfa_name); +} + +void print_simple_dbg_gfa(asg_t *g, const char* prt) +{ + char* gfa_name = (char*)malloc(strlen(prt)+50); + sprintf(gfa_name, "%s.dbg.noseq.gfa", prt); + FILE *fp = fopen(gfa_name, "w"); + uint32_t i, j; char name[32]; + for (i = 0; i < g->n_seq; ++i) { // the Segment lines in GFA + if(g->seq[i].del) continue; + sprintf(name, "utg%.6dl", i + 1); + fprintf(fp, "S\t%s\t*\tLN:i:%d\trd:i:%u\n", name, g->seq[i].len, 0); + } + + asg_arc_t* au = NULL; uint32_t nu, u, v; + for (i = 0; i < g->n_seq; ++i) { + if(g->seq[i].del) continue; + + u = i<<1; + au = asg_arc_a(g, u); nu = asg_arc_n(g, u); + for (j = 0; j < nu; j++) { + if(au[j].del) continue; + v = au[j].v; + fprintf(fp, "L\tutg%.6dl\t%c\tutg%.6dl\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", + (u>>1)+1, "+-"[u&1], (v>>1)+1, "+-"[v&1], au[j].ol, asg_arc_len(au[j]), 0/**au[j].ou**/); + } + + + u = (i<<1) + 1; + au = asg_arc_a(g, u); nu = asg_arc_n(g, u); + for (j = 0; j < nu; j++) { + if(au[j].del) continue; + v = au[j].v; + fprintf(fp, "L\tutg%.6dl\t%c\tutg%.6dl\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", + (u>>1)+1, "+-"[u&1], (v>>1)+1, "+-"[v&1], au[j].ol, asg_arc_len(au[j]), 0/**au[j].ou**/); + } + } + + fclose(fp); free(gfa_name); +} + +ma_ug_t *get_poly_ug(asg_t *sg, ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +int max_hang, int min_ovlp, R_to_U* ruIndex, bub_label_t* b_mask_t) +{ + kvec_asg_arc_t_warp new_rtg_edges, d_edges; + kv_init(new_rtg_edges.a); kv_init(d_edges.a); + + ma_ug_t *ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); + + uint8_t* is_r_het = NULL; + CALLOC(is_r_het, sg->n_seq); + set_r_het_flag(ug, sg, coverage_cut, sources, ruIndex, is_r_het); + + adjust_utg_advance(sg, ug, reverse_sources, ruIndex, b_mask_t, is_r_het); + asg_t* nsg = (*ug).g; + uint32_t v, n_vtx = nsg->n_seq; + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + nsg->seq[v].c = PRIMARY_LABLE; + } + delete_useless_nodes(&ug); + renew_utg(&ug, sg, NULL); + + ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, &d_edges, 1); + + kv_destroy(new_rtg_edges.a); kv_destroy(d_edges.a); + horder_clean_sg_by_utg(sg, ug); + free(is_r_het); + return ug; +} + +trans_chain* get_hic_polyploid_trans_chain(ma_ug_t *ug, asg_t *sg, ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +int max_hang, int min_ovlp, R_to_U* ruIndex, bub_label_t* b_mask_t) +{ + uint32_t k; + trans_chain* p = NULL; CALLOC(p, 1); + p->r_num = sg->n_seq; p->u_num = ug->u.n; + kv_malloc(p->bed, p->u_num); p->bed.n = p->u_num; + for (k = 0; k < p->bed.n; k++) kv_init(p->bed.a[k]); + CALLOC(p->ir_het, p->r_num); + kv_u_trans_t *ta = get_utg_ovlp(&ug, sg, sources, reverse_sources, coverage_cut, ruIndex, max_hang, min_ovlp, NULL, b_mask_t, p->ir_het); + p->k_trans = *ta; free(ta); + return p; +} + +void output_hic_graph_polyploid(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, +R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, +long long gap_fuzz, bub_label_t* b_mask_t) +{ + ug_opt_t opt; memset(&opt, 0, sizeof(opt)); + opt.coverage_cut = coverage_cut; + opt.sources = sources; + opt.reverse_sources = reverse_sources; + opt.tipsLen = (asm_opt.max_short_tip*2); + opt.tip_drop_ratio = 0.15; + opt.stops_threshold = 3; + opt.ruIndex = ruIndex; + opt.chimeric_rate = 0.05; + opt.drop_ratio = 0.9; + opt.max_hang = max_hang; + opt.min_ovlp = min_ovlp; + opt.is_bench = 0; + opt.b_mask_t = b_mask_t; + opt.gap_fuzz = gap_fuzz; + + + ma_ug_t *ug = get_poly_ug(sg, coverage_cut, sources, reverse_sources, max_hang, min_ovlp, ruIndex, b_mask_t); + trans_chain* t_ch = NULL; + + char* gfa_name = (char*)malloc(strlen(output_file_name)+50); + sprintf(gfa_name, "%s.pre.clean_d_utg.noseq.gfa", output_file_name); + FILE* output_file = fopen(gfa_name, "w"); + ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + fclose(output_file); + free(gfa_name); + + if((asm_opt.flag & HA_F_VERBOSE_GFA)) t_ch = load_hc_trans(output_file_name); + if(!t_ch) + { + t_ch = get_hic_polyploid_trans_chain(ug, sg, coverage_cut, sources, reverse_sources, max_hang, min_ovlp, ruIndex, b_mask_t); + ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, NULL, + max_hang, min_ovlp, asm_opt.hic_inconsist_rate, NULL, NULL, t_ch); + if((asm_opt.flag & HA_F_VERBOSE_GFA)) write_trans_chain(t_ch, output_file_name); + } + + hic_analysis(ug, sg, t_ch, &opt, NULL, NULL); + destory_trans_chain(&t_ch); + ma_ug_destroy(ug); + asg_cleanup(sg); + + // reduce_hamming_error(sg, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz); + reduce_hamming_error_adv(NULL, sg, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz, opt.ruIndex, NULL, tipsLen); + + output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, + 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, 0, b_mask_t, NULL, NULL, NULL); + output_trio_unitig_graph(sg, coverage_cut, output_file_name, MOTHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, + 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, 0, b_mask_t, NULL, NULL, NULL); +} + +void set_trio_flag_by_cov(ma_ug_t *ug, asg_t *read_g, hap_cov_t *cov) +{ + kvec_t(uint64_t) idx; kv_init(idx); + uint32_t i, k, j, qn, tn, s[2], flag, n, found = 0; + uint64_t offset, r_beg, r_end, ovlp; + ma_utg_t *u = NULL, *w = NULL; + u_trans_t *a = NULL; + kv_u_trans_t *ta = &(cov->t_ch->k_trans); + + for (i = 0, idx.n = 0; i < ta->idx.n; i++) + { + qn = i; + u = &(ug->u.a[qn]); + for (k = 0; k < u->n; k++) + { + if((R_INF.trio_flag[u->a[k]>>33]&SET_TRIO)==0) break; + } + + if(k >= u->n) continue; ///whole unitig is primary + + a = u_trans_a(*ta, qn); + n = u_trans_n(*ta, qn); + for (k = 0, s[0] = s[1] = 0; k < n; k++) + { + tn = a[k].tn; + w = &(ug->u.a[tn]); + for (j = found = 0, offset = 0; j < w->n; j++) + { + + r_beg = offset; r_end = offset + read_g->seq[w->a[j]>>33].len; + offset += (uint32_t)w->a[j]; + ovlp = ((MIN(r_end, a[k].te) > MAX(r_beg, a[k].ts))? + MIN(r_end, a[k].te) - MAX(r_beg, a[k].ts):0); + if(found == 1 && ovlp == 0) break; + if(ovlp == 0) continue; + found = 1; + if(ovlp <= (read_g->seq[w->a[j]>>33].len)*0.8) continue; + + if((R_INF.trio_flag[w->a[j]>>33]&FATHER)||(R_INF.trio_flag[w->a[j]>>33]&MOTHER)) + { + s[0]++; + } + + if(R_INF.trio_flag[w->a[j]>>33]&SET_TRIO) + { + s[1]++; + } + } + } + + if(s[1] > 0) + { + kv_push(uint64_t, idx, (uint64_t)((uint32_t)-1 - s[0]) << 32 | (qn)); + } + } + + for (i = 0; i < idx.n; i++) + { + qn = (uint32_t)idx.a[i]; + u = &(ug->u.a[qn]); + a = u_trans_a(*ta, qn); + n = u_trans_n(*ta, qn); + for (k = 0, s[0] = s[1] = 0; k < n; k++) + { + tn = a[k].tn; + w = &(ug->u.a[tn]); + for (j = found = 0, offset = 0; j < w->n; j++) + { + + r_beg = offset; r_end = offset + read_g->seq[w->a[j]>>33].len; + offset += (uint32_t)w->a[j]; + ovlp = ((MIN(r_end, a[k].te) > MAX(r_beg, a[k].ts))? + MIN(r_end, a[k].te) - MAX(r_beg, a[k].ts):0); + if(found == 1 && ovlp == 0) break; + if(ovlp == 0) continue; + found = 1; + if(ovlp <= (read_g->seq[w->a[j]>>33].len)*0.8) continue; + + if(R_INF.trio_flag[w->a[j]>>33]&FATHER) + { + s[0]++; + } + + if(R_INF.trio_flag[w->a[j]>>33]&MOTHER) + { + s[1]++; + } + } + } + + if(s[0] >= s[1]) + { + flag = MOTHER; + } + else + { + flag = FATHER; + } + for (k = 0; k < u->n; k++) + { + if(R_INF.trio_flag[u->a[k]>>33]&SET_TRIO) continue; + if(cov->t_ch->ir_het[u->a[k]>>33] == N_HET) continue; + R_INF.trio_flag[u->a[k]>>33] |= flag; + } + } + + + for (i = 0, idx.n = 0; i < ta->idx.n; i++) + { + qn = i; + u = &(ug->u.a[qn]); + for (k = 0; k < u->n; k++) + { + if(R_INF.trio_flag[u->a[k]>>33]&FATHER) + { + R_INF.trio_flag[u->a[k]>>33] = FATHER; + } + else if(R_INF.trio_flag[u->a[k]>>33]&MOTHER) + { + R_INF.trio_flag[u->a[k]>>33] = MOTHER; + } + else + { + R_INF.trio_flag[u->a[k]>>33] = AMBIGU; + } + } + } + kv_destroy(idx); +} + + + +uint64_t get_utg_cov(ma_ug_t *ug, uint32_t uID, asg_t* read_g, +const ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag) +{ + ma_utg_t *u = &(ug->u.a[uID]); + uint32_t k, j, rId, tn, is_Unitig; + long long R_bases = 0, C_bases = 0; + long long cov_in, cov_out; + uint32_t nv, i; + asg_arc_t *av = NULL; + ma_hit_t *h; + if(u->m == 0 || ug->g->seq[uID].del) return 0; + ///set + for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 1; + for (i = 0; i < 2; i++) + { + nv = asg_arc_n(ug->g, (uID<<1)+i); + av = asg_arc_a(ug->g, (uID<<1)+i); + for (j = 0; j < nv; j++) + { + if(av[j].del) continue; + u = &(ug->u.a[av[j].v>>1]); + for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 2; + } + } + + u = &(ug->u.a[uID]); + cov_in = cov_out = R_bases = 0; + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + R_bases += (coverage_cut[rId].e - coverage_cut[rId].s); + for (j = 0; j < (uint64_t)(sources[rId].length); j++) + { + h = &(sources[rId].buffer[j]); + ///if(h->del) continue; + if(h->el != 1) continue; + tn = Get_tn((*h)); + if(read_g->seq[tn].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + if(read_g->seq[tn].del == 1) continue; + if(r_flag[tn] == 0) continue; + if(r_flag[tn] == 1) cov_in += (Get_qe((*h)) - Get_qs((*h))); + if(r_flag[tn] == 2) cov_out += (Get_qe((*h)) - Get_qs((*h))); + } + } + C_bases = cov_in; + if(cov_out <= (cov_in*0.2)) C_bases += cov_out; + + ///reset + for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 0; + + for (i = 0; i < 2; i++) + { + nv = asg_arc_n(ug->g, (uID<<1)+i); + av = asg_arc_a(ug->g, (uID<<1)+i); + for (j = 0; j < nv; j++) + { + u = &(ug->u.a[av[j].v>>1]); + for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 0; + } + } + + return R_bases == 0? 0 : C_bases/R_bases; +} + +void kt_u_trans_t_idx(kv_u_trans_t *ta, uint32_t n) +{ + radix_sort_u_trans(ta->a, ta->a + ta->n); + kv_resize(uint64_t, ta->idx, n); + ta->idx.n = n; + memset(ta->idx.a, 0, ta->idx.n*sizeof(uint64_t)); + uint32_t st, i; + for (st = 0, i = 1; i <= ta->n; ++i) + { + if (i == ta->n || ta->a[i].qn != ta->a[st].qn) + { + ta->idx.a[ta->a[st].qn] = (uint64_t)st << 32 | (i - st); + st = i; + } + } +} + +uint32_t get_u_trans_spec(kv_u_trans_t *ta, uint32_t qn, uint32_t tn, u_trans_t **r_a, uint32_t *occ) +{ + if(r_a) (*r_a) = NULL; + if(occ) (*occ) = 0; + u_trans_t *a = NULL; + uint32_t n, st, i; + a = u_trans_a(*ta, qn); + n = u_trans_n(*ta, qn); + for (st = 0, i = 1; i <= n; ++i) + { + if (i == n || a[i].tn != a[st].tn) + { + if(a[st].tn == tn) + { + if(r_a) (*r_a) = a + st; + if(occ) (*occ) = i - st; + return 1; + } + st = i; + } + } + return 0; +} + +double merge_u_trans(u_trans_t *a, uint32_t occ, ma_ug_t *ug) +{ + radix_sort_u_trans_qs(a, a+occ); + uint32_t i, k, ov_q, ov_t, is_found = 1, ts, te; + double w_q, w_s; + u_trans_t *p = NULL; + + for (i = 0; i < occ; i++) + { + if(a[i].del || a[i].rev == 0) continue; + ts = a[i].ts; te = a[i].te - 1; + a[i].ts = ug->g->seq[a[i].tn].len - te - 1; + a[i].te = ug->g->seq[a[i].tn].len - ts - 1 + 1; + } + + + while (is_found) + { + for (i = is_found = 0; i < occ; i++) + { + if(a[i].del) continue; + p = &(a[i]); + for (k = i+1; k < occ; k++) + { + if(a[k].del) continue; + if(p->qe < a[k].qs) break; + + if(p->qe >= a[k].qs && p->te >= a[k].ts) + { + ov_q = ((MIN(p->qe, a[k].qe) > MAX(p->qs, a[k].qs))? + MIN(p->qe, a[k].qe) - MAX(p->qs, a[k].qs):0); + ov_t = ((MIN(p->te, a[k].te) > MAX(p->ts, a[k].ts))? + MIN(p->te, a[k].te) - MAX(p->ts, a[k].ts):0); + + ov_q = a[k].qe - a[k].qs - ov_q; + ov_t = a[k].te - a[k].ts - ov_t; + + w_q = ((double)ov_q/(double)(a[k].qe - a[k].qs)) * a[k].nw; + w_s = ((double)ov_t/(double)(a[k].te - a[k].ts)) * a[k].nw; + + p->qe = MAX(p->qe, a[k].qe); + p->te = MAX(p->te, a[k].te); + p->nw += MIN(w_q, w_s); + is_found = 1; + a[k].del = 1; + } + } + } + for (i = k = 0; i < occ; i++) + { + if(a[i].del) continue; + a[k] = a[i]; + k++; + } + occ = k; + } + + + for (i = 0; i < occ; i++) + { + if(a[i].del) continue; + p = &(a[i]); + for (k = i+1; k < occ; k++) + { + if(a[k].del) continue; + ov_q = ((MIN(p->qe, a[k].qe) > MAX(p->qs, a[k].qs))? + MIN(p->qe, a[k].qe) - MAX(p->qs, a[k].qs):0); + + if(ov_q == 0) break; + if(ov_q == (a[k].qe-a[k].qs)) + { + a[k].del = 1; + continue; + } + if(ov_q == (p->qe - p->qs)) + { + p->del = 1; + continue; + } + ov_t = get_offset_adjust(ov_q, a[k].qe-a[k].qs, a[k].te-a[k].ts); + a[k].qs += ov_q; a[k].ts += ov_t; + a[k].nw -= ((double)ov_q/(double)(a[k].qe - a[k].qs)) * a[k].nw; + } + } + for (i = k = 0; i < occ; i++) + { + if(a[i].del) continue; + a[k] = a[i]; + k++; + } + occ = k; + + + + + radix_sort_u_trans_ts(a, a+occ); + for (i = 0; i < occ; i++) + { + if(a[i].del) continue; + p = &(a[i]); + for (k = i+1; k < occ; k++) + { + if(a[k].del) continue; + ov_t = ((MIN(p->te, a[k].te) > MAX(p->ts, a[k].ts))? + MIN(p->te, a[k].te) - MAX(p->ts, a[k].ts):0); + + if(ov_t == 0) break; + if(ov_t == (a[k].te-a[k].ts)) + { + a[k].del = 1; + continue; + } + if(ov_t == (p->te - p->ts)) + { + p->del = 1; + continue; + } + ov_q = get_offset_adjust(ov_t, a[k].te-a[k].ts, a[k].qe-a[k].qs); + a[k].ts += ov_t; a[k].qs += ov_q; + a[k].nw -= ((double)ov_t/(double)(a[k].te - a[k].ts)) * a[k].nw; + } + } + for (i = k = 0, w_q = 0; i < occ; i++) + { + if(a[i].del) continue; + w_q += a[i].nw; + a[k] = a[i]; + k++; + } + occ = k; + + + for (i = 0; i < occ; i++) + { + if(a[i].del || a[i].rev == 0) continue; + ts = a[i].ts; te = a[i].te - 1; + a[i].ts = ug->g->seq[a[i].tn].len - te - 1; + a[i].te = ug->g->seq[a[i].tn].len - ts - 1 + 1; + } + + return w_q; +} + +void kt_u_trans_t_symm(kv_u_trans_t *ta, ma_ug_t *ug) +{ + u_trans_t *a = NULL, *r_a = NULL, *p = NULL; + uint32_t k, n, r_n, st, i, m; + double w0, w1; + kvec_t(u_trans_t) e0; kv_init(e0); + kvec_t(u_trans_t) e1; kv_init(e1); + for (k = 0; k < ta->idx.n; k++) + { + a = u_trans_a(*ta, k); + n = u_trans_n(*ta, k); + for (st = 0, i = 1; i <= n; ++i) + { + if (i == n || a[i].tn != a[st].tn) + { + get_u_trans_spec(ta, a[st].tn, a[st].qn, &r_a, &r_n); + if(i == st + 1 && r_n == 0) {///should be always here + st = i; + continue; + } + + e0.n = e1.n = 0; + for (m = st; m < i; m++) { + if(a[m].del) continue; + if(a[m].rev) { + kv_push(u_trans_t, e1, a[m]); + } else { + kv_push(u_trans_t, e0, a[m]); + } + } + + for (m = 0; m < r_n; m++) { + if(r_a[m].del) continue; + if(r_a[m].rev) { + kv_pushp(u_trans_t, e1, &p); + } else { + kv_pushp(u_trans_t, e0, &p); + } + (*p) = r_a[m]; + p->qn = r_a[m].tn; p->qs = r_a[m].ts; p->qe = r_a[m].te; + p->tn = r_a[m].qn; p->ts = r_a[m].qs; p->te = r_a[m].qe; + } + + + if(e0.n + e1.n > 1) { + ///must be here + for (m = st; m < i; m++) a[m].del = 1; + for (m = 0; m < r_n; m++) r_a[m].del = 1; + + w0 = merge_u_trans(e0.a, e0.n, ug); + w1 = merge_u_trans(e1.a, e1.n, ug); + if(w0 >= w1) + { + for (m = 0; m < e0.n; m++) + { + kv_push(u_trans_t, *ta, e0.a[m]); + } + } + else + { + for (m = 0; m < e1.n; m++) + { + kv_push(u_trans_t, *ta, e1.a[m]); + } + } + } + st = i; + } + } + + } + kv_destroy(e0); + kv_destroy(e1); + for (i = m = 0; i < ta->n; ++i) + { + if(ta->a[i].del) continue; + ta->a[m] = ta->a[i]; + m++; + } + ta->n = m; + n = ta->n; + for (i = 0; i < n; ++i) + { + if(ta->a[i].del) continue; + kv_pushp(u_trans_t, *ta, &p); + (*p) = ta->a[i]; + p->qn = ta->a[i].tn; p->qs = ta->a[i].ts; p->qe = ta->a[i].te; + p->tn = ta->a[i].qn; p->ts = ta->a[i].qs; p->te = ta->a[i].qe; + } + kt_u_trans_t_idx(ta, ug->g->n_seq); +} + + +void kt_u_trans_t_simple_symm(kv_u_trans_t *ta, uint32_t un, uint32_t symm_add) +{ + u_trans_t *a = NULL, *r_a = NULL, *p = NULL; + uint32_t k, n, m; + n = ta->n; + for (k = 0; k < n; k++) + { + if(ta->a[k].del || ta->a[k].qn > ta->a[k].tn) continue; + get_u_trans_spec(ta, ta->a[k].tn, ta->a[k].qn, &r_a, NULL); + a = &(ta->a[k]); + if(!r_a || r_a->del) + { + if(symm_add) kv_pushp(u_trans_t, *ta, &r_a); + else + { + a->del = 1; + continue; + } + } + else + { + if(r_a->nw > a->nw) + { + p = a; + a = r_a; + r_a = p; + } + } + (*r_a) = (*a); + r_a->qn = a->tn; r_a->qs = a->ts; r_a->qe = a->te; + r_a->tn = a->qn; r_a->ts = a->qs; r_a->te = a->qe; + } + + for (k = m = 0; k < ta->n; ++k) + { + if(ta->a[k].del) continue; + ta->a[m] = ta->a[k]; + m++; + } + ta->n = m; + kt_u_trans_t_idx(ta, un); +} + +void debug_u_trans_t(kv_u_trans_t *ta) +{ + u_trans_t *a = NULL, *r_a = NULL; + uint32_t i, k, m, j, st, n, r_n, ovlp; + for (i = 0; i < ta->n; ++i) + { + if(ta->a[i].nw <= 0) fprintf(stderr, "ERROR-1\n"); + if(ta->a[i].qe <= ta->a[i].qs) fprintf(stderr, "ERROR-2\n"); + if(ta->a[i].te <= ta->a[i].ts) fprintf(stderr, "ERROR-3\n"); + } + for (k = 0; k < ta->idx.n; k++) + { + a = u_trans_a(*ta, k); + n = u_trans_n(*ta, k); + for (st = 0, i = 1; i <= n; ++i) + { + if (i == n || a[i].tn != a[st].tn) + { + get_u_trans_spec(ta, a[st].tn, a[st].qn, &r_a, &r_n); + + if(i - st != r_n) + { + fprintf(stderr, "ERROR-4, i - st: %u, r_n: %u\n", i - st, r_n); + } + + for (m = st; m < i; m++) + { + if(a[m].rev != a[st].rev) fprintf(stderr, "ERROR-5\n"); + for (j = st; j < i; j++) + { + if(j == m) continue; + + ovlp = ((MIN(a[m].qe, a[j].qe) > MAX(a[m].qs, a[j].qs))? + MIN(a[m].qe, a[j].qe) - MAX(a[m].qs, a[j].qs):0); + if(ovlp > 0) fprintf(stderr, "ERROR-6\n"); + + ovlp = ((MIN(a[m].te, a[j].te) > MAX(a[m].ts, a[j].ts))? + MIN(a[m].te, a[j].te) - MAX(a[m].ts, a[j].ts):0); + if(ovlp > 0) fprintf(stderr, "ERROR-7\n"); + } + + for (j = 0; j < r_n; j++) + { + if(r_a[j].rev != a[m].rev) fprintf(stderr, "ERROR-8\n"); + if(r_a[j].tn == a[m].qn && r_a[j].qn == a[m].tn && + r_a[j].ts == a[m].qs && r_a[j].te == a[m].qe && + r_a[j].qs == a[m].ts && r_a[j].qe == a[m].te && + r_a[j].nw == a[m].nw) + { + break; + } + } + if(j >= r_n) fprintf(stderr, "ERROR-9\n"); + + } + st = i; + } + } + } +} + + +void filter_u_trans_t(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, uint32_t thres) +{ + u_trans_t *a = NULL, *r_a = NULL; + ma_utg_t *u = NULL; + uint32_t i, k, m, j, st, n, r_n; + uint64_t offset, r_beg, r_end, ovlp, min, max, pass; + kvec_t(uint32_t) cnt; kv_init(cnt); + for (k = 0; k < ta->idx.n; k++) + { + a = u_trans_a(*ta, k); + n = u_trans_n(*ta, k); + if(n == 0) continue; + kv_resize(uint32_t, cnt, n); cnt.n = n; + min = a[0].qs; max = a[0].qe; + for (i = 0; i < n; i++) + { + cnt.a[i] = 0; + min = MIN(min, a[i].qs); + max = MAX(max, a[i].qe); + } + + + u = &(ug->u.a[k]); pass = 0; + for (j = 0, offset = 0; j < u->n; j++) + { + pass = 0; + r_beg = offset; r_end = offset + read_g->seq[u->a[j]>>33].len; + offset += (uint32_t)u->a[j]; + if(min >= r_end) continue; + if(max <= r_beg) break; + for (i = 0; i < n; i++) + { + if(cnt.a[i] >= thres || r_beg >= a[i].qe) + { + pass++; + continue; + } + ovlp = ((MIN(r_end, a[i].qe) > MAX(r_beg, a[i].qs))? + MIN(r_end, a[i].qe) - MAX(r_beg, a[i].qs):0); + if(ovlp == (r_end - r_beg)) + { + cnt.a[i]++; + if(cnt.a[i] >= thres) pass++; + } + } + + if(pass == n) + { + for (i = 0; i < n; i++) + { + if(cnt.a[i] < thres) a[i].del = 1; + } + break; + } + } + + if(pass < n) + { + for (i = 0; i < n; i++) + { + if(cnt.a[i] < thres) a[i].del = 1; + } + } + } + kv_destroy(cnt); + + for (k = 0; k < ta->idx.n; k++) + { + a = u_trans_a(*ta, k); + n = u_trans_n(*ta, k); + for (st = 0, i = 1; i <= n; ++i) + { + if (i == n || a[i].tn != a[st].tn)///same qn && tn + { + get_u_trans_spec(ta, a[st].tn, a[st].qn, &r_a, &r_n); + + for (m = st; m < i; m++) + { + if(!a[m].del) continue; + + for (j = 0; j < r_n; j++) + { + if(r_a[j].tn == a[m].qn && r_a[j].qn == a[m].tn && + r_a[j].ts == a[m].qs && r_a[j].te == a[m].qe && + r_a[j].qs == a[m].ts && r_a[j].qe == a[m].te && + r_a[j].nw == a[m].nw && r_a[j].rev == a[m].rev) + { + r_a[j].del = 1; + break; + } + } + } + st = i; + } + } + } + /*******************************for debug************************************/ + // for (i = 0; i < ta->n; ++i) + // { + // uint32_t c_q = 0, c_t = 0, s, e; + // u = &(ug->u.a[ta->a[i].qn]); s = ta->a[i].qs; e = ta->a[i].qe; + // for (j = 0, offset = 0; j < u->n; j++) + // { + // r_beg = offset; r_end = offset + read_g->seq[u->a[j]>>33].len; + // offset += (uint32_t)u->a[j]; + + // ovlp = ((MIN(r_end, e) > MAX(r_beg, s))? MIN(r_end, e) - MAX(r_beg, s):0); + // if(ovlp == (r_end - r_beg)) + // { + // c_q++; + // if(c_q >= thres) break; + // } + // } + + + // u = &(ug->u.a[ta->a[i].tn]); s = ta->a[i].ts; e = ta->a[i].te; + // for (j = 0, offset = 0; j < u->n; j++) + // { + // r_beg = offset; r_end = offset + read_g->seq[u->a[j]>>33].len; + // offset += (uint32_t)u->a[j]; + + // ovlp = ((MIN(r_end, e) > MAX(r_beg, s))? MIN(r_end, e) - MAX(r_beg, s):0); + // if(ovlp == (r_end - r_beg)) + // { + // c_t++; + // if(c_t >= thres) break; + // } + // } + + // if(ta->a[i].del && (c_q >= thres && c_t >= thres)) fprintf(stderr, "ERROR\n"); + // if(!ta->a[i].del && (c_q < thres || c_t < thres)) fprintf(stderr, "ERROR\n"); + // } + /*******************************for debug************************************/ + + for (i = m = 0; i < ta->n; ++i) + { + if(ta->a[i].del) continue; + ta->a[m] = ta->a[i]; + m++; + } + ta->n = m; + kt_u_trans_t_idx(ta, ug->g->n_seq); +} + +void clean_u_trans_t_idx(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g) +{ + // dbg_prt_utg_trans(ta, ug, "pre"); + kt_u_trans_t_idx(ta, ug->g->n_seq); + kt_u_trans_t_symm(ta, ug); + filter_u_trans_t(ta, ug, read_g, 3); + ///debug_u_trans_t(ta); + // dbg_prt_utg_trans(ta, ug, "after"); +} + +void gen_bp_phasing(ug_opt_t *opt, kv_u_trans_t *ta, ma_ug_t *ug, asg_t *sg) +{ + uint8_t *bf = NULL; + bubble_type *bub = gen_bubble_chain(sg, ug, opt, &bf, 0); free(bf); + filter_u_trans(ta, asm_opt.is_bub_trans, asm_opt.is_topo_trans, asm_opt.is_read_trans, asm_opt.is_base_trans); + // dbg_prt_utg_trans(ta, ug, "pre"); + if(asm_opt.is_base_trans) { + trans_base_infer(ug, sg, opt, ta, bub); + } + // dbg_prt_utg_trans(ta, ug, "after"); + clean_u_trans_t_idx_filter_adv(ta, ug, sg, 0.95, 0); + + + bp_solve(opt, ta, ug, sg, bub, asm_opt.trans_base_rate); + + destory_bubbles(bub); free(bub); +} + + +void output_bp_graph_adv(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, +R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, +int gap_fuzz, bub_label_t* b_mask_t, ug_opt_t *opt) +{ + hic_clean(sg); + + kvec_asg_arc_t_warp new_rtg_edges, d_edges; + kv_init(new_rtg_edges.a); kv_init(d_edges.a); + ma_ug_t *ug = NULL; + ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); + + new_rtg_edges.a.n = 0; + ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, &d_edges, 1);///polish + + new_rtg_edges.a.n = 0; + hap_cov_t *cov = NULL; + asg_t *copy_sg = copy_read_graph(sg); + ma_ug_t *copy_ug = copy_untig_graph(ug); + /*******************************for debug************************************/ + adjust_utg_by_primary(©_ug, copy_sg, TRIO_THRES, sources, reverse_sources, coverage_cut, + tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, + max_hang, min_ovlp, &new_rtg_edges, &cov, b_mask_t, 1, 0/**1**/); + // adjust_utg_advance(copy_sg, copy_ug, reverse_sources, ruIndex, b_mask_t); + // get_utg_ovlp(©_ug, copy_sg, sources, reverse_sources, coverage_cut, + // ruIndex, max_hang, min_ovlp, &new_rtg_edges, b_mask_t, NULL); + // exit(1); + /*******************************for debug************************************/ + print_utg(©_ug, copy_sg, coverage_cut, output_file_name, sources, ruIndex, max_hang, + min_ovlp, &new_rtg_edges); + ma_ug_destroy(copy_ug); + asg_destroy(copy_sg); + + // gen_bp_phasing(opt, &(cov->t_ch->k_trans), ug, sg); + clean_u_trans_t_idx(&(cov->t_ch->k_trans), ug, sg); + set_trio_flag_by_cov(ug, sg, cov); + + //for debug + // char* gfa_name = (char*)malloc(strlen(output_file_name)+50); + // sprintf(gfa_name, "%s.pre.clean_d_utg.noseq.gfa", output_file_name); + // FILE* output_file = fopen(gfa_name, "w"); + // ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + // fclose(output_file); + // free(gfa_name); + // exit(1); + //for debug + + + // print_untig_by_read(copy_ug, "m64011_190830_220126/88867583/ccs", 603738, NULL, NULL, "sb"); + + ///debug_gfa_space(ug, cov); + + + // print_r_het(cov, R_INF.trio_flag, "out-1"); + // print_debug_gfa(ug, sg, coverage_cut, output_file_name, sources, ruIndex); + + destory_hap_cov_t(&cov); + ma_ug_destroy(ug); + kv_destroy(new_rtg_edges.a); + + asg_arc_t* av = NULL; + uint32_t v, w, k, i, nv; + for (i = 0; i < d_edges.a.n; i++) + { + v = d_edges.a.a[i].ul>>32; + w = d_edges.a.a[i].v; + av = asg_arc_a(sg, v); + nv = asg_arc_n(sg, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + av[k].del = 1; + break; + } + } + } + kv_destroy(d_edges.a); + asg_cleanup(sg); + + + output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, + 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, 0, b_mask_t, NULL, NULL, NULL); + output_trio_unitig_graph(sg, coverage_cut, output_file_name, MOTHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, + 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, 0, b_mask_t, NULL, NULL, NULL); +} + +void output_bp_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, long long stops_threshold, +R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, bub_label_t* b_mask_t, +long long gap_fuzz, ug_opt_t *opt) +{ + hic_clean(sg); + kvec_asg_arc_t_warp new_rtg_edges; + kv_init(new_rtg_edges.a); + ma_ug_t *ug = NULL; + ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); + + hap_cov_t *cov = NULL; + asg_t *copy_sg = copy_read_graph(sg); + ma_ug_t *copy_ug = copy_untig_graph(ug); + /*******************************for debug************************************/ + adjust_utg_by_primary(©_ug, copy_sg, TRIO_THRES, sources, reverse_sources, coverage_cut, + tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, + max_hang, min_ovlp, &new_rtg_edges, &cov, b_mask_t, 1, 1); + // adjust_utg_advance(copy_sg, copy_ug, reverse_sources, ruIndex, b_mask_t); + // get_utg_ovlp(©_ug, copy_sg, sources, reverse_sources, coverage_cut, + // ruIndex, max_hang, min_ovlp, &new_rtg_edges, b_mask_t, NULL); + // exit(1); + /*******************************for debug************************************/ + print_utg(©_ug, copy_sg, coverage_cut, output_file_name, sources, ruIndex, max_hang, + min_ovlp, &new_rtg_edges); + ma_ug_destroy(copy_ug); + asg_destroy(copy_sg); + + clean_u_trans_t_idx(&(cov->t_ch->k_trans), ug, sg); + // print_untig_by_read(copy_ug, "m64011_190830_220126/88867583/ccs", 603738, NULL, NULL, "sb"); + + ///debug_gfa_space(ug, cov); + + set_trio_flag_by_cov(ug, sg, cov); + // print_r_het(cov, R_INF.trio_flag, "out-1"); + // print_debug_gfa(ug, sg, coverage_cut, output_file_name, sources, ruIndex); + // exit(1); + + destory_hap_cov_t(&cov); + ma_ug_destroy(ug); + kv_destroy(new_rtg_edges.a); + + // reduce_hamming_error_adv(NULL, sg, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz, opt->ruIndex, NULL); + + // output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, + // 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, 0, b_mask_t, NULL, NULL, NULL); + // output_trio_unitig_graph(sg, coverage_cut, output_file_name, MOTHER, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, + // 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, 0, b_mask_t, NULL, NULL, NULL); + + output_trio_graph_joint(sg, coverage_cut, output_file_name, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, + 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, b_mask_t, NULL, NULL, opt); +} + +void output_bp_trio_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, long long stops_threshold, +R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, bub_label_t* b_mask_t, +long long gap_fuzz, ug_opt_t *opt) +{ + hic_clean(sg); + + kvec_asg_arc_t_warp new_rtg_edges; + kv_init(new_rtg_edges.a); + ma_ug_t *ug = NULL; + ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); + + hap_cov_t *cov = NULL; + trans_chain* t_ch = NULL; + if((asm_opt.flag & HA_F_VERBOSE_GFA)) t_ch = load_hc_trans(output_file_name); + + if(!t_ch) { + new_rtg_edges.a.n = 0; + asg_t *copy_sg = copy_read_graph(sg); + ma_ug_t *copy_ug = copy_untig_graph(ug); + ///asm_opt.purge_overlap_len = asm_opt.purge_overlap_len_hic; + ///asm_opt.purge_simi_thres = asm_opt.purge_simi_rate_hic; + adjust_utg_by_primary(©_ug, copy_sg, TRIO_THRES, sources, reverse_sources, coverage_cut, + tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, + max_hang, min_ovlp, &new_rtg_edges, &cov, b_mask_t, 1, 0); + + ma_ug_destroy(copy_ug); + asg_destroy(copy_sg); + + if((asm_opt.flag & HA_F_VERBOSE_GFA)) write_trans_chain(cov->t_ch, output_file_name); + } + + // clean_u_trans_t_idx_filter_adv(&(cov?cov->t_ch->k_trans:t_ch->k_trans), ug, sg); + trio_phasing_refine(ug, sg, cov?&(cov->t_ch->k_trans):&(t_ch->k_trans), opt); + + if(cov) destory_hap_cov_t(&cov); + if(t_ch) destory_trans_chain(&t_ch); + + + // char* gfa_name = (char*)malloc(strlen(output_file_name)+50); + // sprintf(gfa_name, "%s.after.clean_d_utg.noseq.gfa", output_file_name); + // FILE* output_file = fopen(gfa_name, "w"); + // ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + // fclose(output_file); + // free(gfa_name); + + + + ma_ug_destroy(ug); + kv_destroy(new_rtg_edges.a); + + + output_trio_graph_joint(sg, coverage_cut, output_file_name, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, + 0.05, 0.9, max_hang, min_ovlp, gap_fuzz, b_mask_t, NULL, NULL, opt); +} + +ma_ug_t* merge_utg(ma_ug_t **dest, ma_ug_t **src) +{ + asg_t *g_d = (*dest)->g, *g_s = (*src)->g; + uint64_t occ_d = g_d->n_seq, occ_s = g_s->n_seq, i; + asg_arc_t *p = NULL; + g_d->is_srt = g_d->is_symm = 0; + + for (i = 0; i < occ_s; i++) + { + asg_seq_set(g_d, i+occ_d, g_s->seq[i].len, g_s->seq[i].del); + g_d->seq[i+occ_d].c = g_s->seq[i].c; + } + + g_d->seq_vis = (uint8_t*)realloc(g_d->seq_vis, g_d->n_seq*2*sizeof(uint8_t)); + + + for (i = 0; i < g_s->n_arc; i++) + { + p = asg_arc_pushp(g_d); + (*p) = g_s->arc[i]; + p->ul += (occ_d<<33); + p->v += (occ_d<<1); + } + + asg_cleanup(g_d); + g_d->r_seq = g_d->n_seq; + + if(g_s->n_F_seq > 0 && g_s->F_seq) + { + uint64_t n_F_seq = g_d->n_F_seq + g_s->n_F_seq; + g_d->F_seq = (ma_utg_t*)realloc(g_d->F_seq, n_F_seq*sizeof(ma_utg_t)); + memcpy(g_d->F_seq + g_d->n_F_seq, g_s->F_seq, g_s->n_F_seq*sizeof(ma_utg_t)); + g_d->n_F_seq = n_F_seq; + free(g_s->F_seq); + g_s->F_seq = NULL; + g_s->n_F_seq = 0; + } + + ma_utg_v *u_d = &((*dest)->u), *u_s = &((*src)->u); + if(u_s->n > 0) + { + uint64_t n = u_d->n + u_s->n; + u_d->a = (ma_utg_t*)realloc(u_d->a, n*sizeof(ma_utg_t)); + memcpy(u_d->a + u_d->n, u_s->a, u_s->n*sizeof(ma_utg_t)); + u_d->n = u_d->m = n; + free(u_s->a); + u_s->a = NULL; + u_s->n = u_s->m = 0; + } + + kv_push(uint64_t, (*dest)->occ, occ_d); + kv_push(uint64_t, (*dest)->occ, occ_s); + + ma_ug_destroy(*src); + return (*dest); +} + +void benchmark_hic_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, +float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, int gap_fuzz, bub_label_t* b_mask_t) +{ + ma_ug_t *ug_1 = output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, + reverse_sources, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, + chimeric_rate, drop_ratio, max_hang, min_ovlp, gap_fuzz, 1, b_mask_t, NULL, NULL, NULL); + + ma_ug_t *ug_2 = output_trio_unitig_graph(sg, coverage_cut, output_file_name, MOTHER, sources, + reverse_sources, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, + chimeric_rate, drop_ratio, max_hang, min_ovlp, gap_fuzz, 1, b_mask_t, NULL, NULL, NULL); + fprintf(stderr, "ug_1->u.n: %u, ug_2->u.n: %u\n", (uint32_t)ug_1->u.n, (uint32_t)ug_2->u.n); + ma_ug_t *ug = merge_utg(&ug_1, &ug_2); + fprintf(stderr, "ug->u.n: %u\n", (uint32_t)ug->u.n); + + hic_benchmark(ug, sg); + + ma_ug_destroy(ug); +} + +void merge_unitig_content(ma_utg_t* collection, ma_ug_t* ug, asg_t* read_g, kvec_asg_arc_t_warp* edge) +{ + if(collection->m == 0) return; + uint32_t i, j, index = 0, uId, ori; + uint64_t totalLen; + ma_utg_t* query = NULL; + for (i = 0; i < collection->n; i++) + { + uId = collection->a[i]>>33; + ori = collection->a[i]>>32&1; + query = &(ug->u.a[uId]); + index += query->n; + } + + uint64_t* buffer = (uint64_t*)malloc(sizeof(uint64_t)*index); + uint64_t* aim = NULL; + index = 0; + for (i = 0; i < collection->n; i++) + { + uId = collection->a[i]>>33; + ori = collection->a[i]>>32&1; + query = &(ug->u.a[uId]); + aim = buffer + index; + if(ori == 1) + { + for (j = 0; j < query->n; j++) + { + aim[query->n - j - 1] = (query->a[j])^(uint64_t)(0x100000000); + } + } + else + { + for (j = 0; j < query->n; j++) + { + aim[j] = query->a[j]; + } + } + index += query->n; + free(query->a);query->m=0;query->a=NULL; + } + + if(index == 0) return; + + ///fill_unitig(buffer, index, read_g, edge, collection->circ, &totalLen); + fill_unitig(buffer, index, read_g, edge, /**collection->circ**/ + (collection->n == 1 && ug->u.a[collection->a[0]>>33].circ), &totalLen); + + ///important. must be here + if(collection->n == 1 && ug->u.a[collection->a[0]>>33].circ) collection->circ = 1; + + free(collection->a); + collection->a = buffer; + collection->n = collection->m = index; + collection->len = totalLen; + if(!collection->circ) + { + collection->start = collection->a[0]>>32; + collection->end = (collection->a[collection->n-1]>>32)^1; + } + else + { + collection->start = collection->end = UINT32_MAX; + } + + +} + +void print_unitig(ma_utg_t* collection, ma_ug_t* ug) +{ + if(collection->m == 0) return; + uint32_t i, index = 0, uId, ori, l; + ma_utg_t* query = NULL; + for (i = 0; i < collection->n; i++) + { + uId = collection->a[i]>>33; + ori = collection->a[i]>>32&1; + l = (uint32_t)(collection->a[i]); + fprintf(stderr, "i: %u, uId: %u, ori: %u, l: %u\n", i, uId, ori, l); + if(ug) + { + query = &(ug->u.a[uId]); + index += query->n; + } + } + fprintf(stderr, "index: %u\n", index); +} + + +void print_specfic_read_ovlp(uint32_t Rid, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +const char* command) +{ + long long j, i = Rid; + uint32_t tn; + + + fprintf(stderr, "\n\n\nafter %s\n", command); + + fprintf(stderr, "****************ma_hit_t (%lld)ref_read: %.*s****************\n", + i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); + + + fprintf(stderr, "sources Len: %d, is_fully_corrected: %d\n", + sources[i].length, sources[i].is_fully_corrected); + + for (j = 0; j < sources[i].length; j++) + { + tn = Get_tn(sources[i].buffer[j]); + fprintf(stderr, "target: %.*s, qs: %u, qe: %u, ts: %u, te: %u, ml: %u, rev: %u, el: %u, del: %u\n", + (int)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), + Get_qs(sources[i].buffer[j]), + Get_qe(sources[i].buffer[j]), + Get_ts(sources[i].buffer[j]), + Get_te(sources[i].buffer[j]), + sources[i].buffer[j].ml, + sources[i].buffer[j].rev, + sources[i].buffer[j].el, + (uint32_t)sources[i].buffer[j].del); + } + + + + fprintf(stderr, "######reverse_query_read Len: %d\n", reverse_sources[i].length); + + + + for (j = 0; j < reverse_sources[i].length; j++) + { + tn = Get_tn(reverse_sources[i].buffer[j]); + fprintf(stderr, "target: %.*s, qs: %u, qe: %u, ts: %u, te: %u, del: %u\n", + (int)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), + Get_qs(reverse_sources[i].buffer[j]), + Get_qe(reverse_sources[i].buffer[j]), + Get_ts(reverse_sources[i].buffer[j]), + Get_te(reverse_sources[i].buffer[j]), + (uint32_t)sources[i].buffer[j].del); + } + + + + + fflush(stderr); + + +} + + +uint32_t print_debug_gfa(asg_t *read_g, ma_ug_t *ug, ma_sub_t* coverage_cut, const char* output_file_name, +ma_hit_t_alloc* sources, R_to_U* ruIndex, int max_hang, int min_ovlp, int is_update_ou, int is_check_alter_lable, int is_seq) +{ + kvec_asg_arc_t_warp new_rtg_edges; + uint32_t free_ug = ((ug == NULL)?1:0); + kv_init(new_rtg_edges.a); + + if(ug == NULL) { + ug = ma_ug_gen(read_g); + } else if(is_check_alter_lable) { + uint32_t i; + for (i = 0; i < ug->u.n; ++i) + { + ma_utg_t *u = &ug->u.a[i]; + if(u->m == 0 || ug->g->seq[i].c == ALTER_LABLE) + { + asg_seq_del(ug->g, i); + if(ug->u.a[i].m!=0) + { + ug->u.a[i].m = ug->u.a[i].n = 0; + free(ug->u.a[i].a); + ug->u.a[i].a = NULL; + } + } + } + } + + if(is_update_ou) update_ug_ou(ug, read_g); + if(is_seq) { + ma_ug_seq(ug, read_g, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 0); + } + // if(is_polish) ma_ug_seq(ug, read_g, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 0); + + fprintf(stderr, "Writing raw unitig GFA to disk... \n"); + char* gfa_name = (char*)malloc(strlen(output_file_name)+50); + FILE* output_file = NULL; + + if(is_seq) { + sprintf(gfa_name, "%s.r_utg.gfa", output_file_name); + output_file = fopen(gfa_name, "w"); + ma_ug_print(ug, read_g, coverage_cut, sources, ruIndex, "utg", output_file); + } else { + sprintf(gfa_name, "%s.r_utg.noseq.gfa", output_file_name); + output_file = fopen(gfa_name, "w"); + ma_ug_print_simple(ug, read_g, coverage_cut, sources, ruIndex, "utg", output_file); + } + fclose(output_file); + + free(gfa_name); + if(free_ug) ma_ug_destroy(ug); + kv_destroy(new_rtg_edges.a); + // exit(0); + return 1; +} + + +uint32_t print_untig_by_read(ma_ug_t *g, const char* name, uint32_t in, ma_hit_t_alloc* sources, +ma_hit_t_alloc* reverse_sources, const char* info) +{ + uint32_t i, k, rId = (uint32_t)-1, flag = 0; + if(in != (uint32_t)-1) + { + rId = in; + } + else + { + for (i = 0; i < R_INF.total_reads; ++i) + { + if(Get_NAME_LENGTH(R_INF, i) != strlen(name)) continue; + if(memcmp(name, Get_NAME(R_INF, i), Get_NAME_LENGTH(R_INF, i)) == 0) + { + fprintf(stderr, "%s: i: %u, >%.*s\n", info, i, + (int)Get_NAME_LENGTH((R_INF), i), Get_NAME((R_INF), i)); + rId = i; + break; + } + } + } + + + + if(rId == (uint32_t)-1) + { + fprintf(stderr, "%s: Cannot find %s\n", info, name); + return (uint32_t)-1; + } + + if(sources && reverse_sources) print_specfic_read_ovlp(rId, sources, reverse_sources, info); + + if(g != NULL) + { + for (i = 0; i < g->u.n; ++i) + { + ma_utg_t *u = &g->u.a[i]; + if(u->m == 0) continue; + for (k = 0; k < u->n; k++) + { + if(rId == (u->a[k]>>33)) + { + fprintf(stderr, "%s: %s is the %u-th read at %u-th unitig (label: %u, occ: %u)\n", + info, name, k, i, g->g->seq[i].c, u->n); + flag = 1; + ///return i; + } + } + } + } + + + + + + if(flag == 0) fprintf(stderr, "%s: %s is not at any unitig\n", info, name); + return (uint32_t)-1; +} + + +void print_untig(ma_ug_t *g, uint32_t uId, const char* info, uint32_t is_print_read) +{ + uint32_t i, k; + asg_t* nsg = g->g; + + uId = uId<<1; + asg_arc_t *aw = asg_arc_a(nsg, uId); + uint32_t nw = asg_arc_n(nsg, uId); + + fprintf(stderr, "\n%s: c = %u, del: %u\n", info, nsg->seq[uId>>1].c, nsg->seq[uId>>1].del); + fprintf(stderr, "%s(%u): direction = 0...\n", info, uId>>1); + for (i = 0; i < nw; i++) + { + if(aw[i].del) continue; + fprintf(stderr, "%s: (%u) v>>1: %u, dir: %u\n", info, i, aw[i].v>>1, aw[i].v&1); + } + + uId = uId^1; + aw = asg_arc_a(nsg, uId); + nw = asg_arc_n(nsg, uId); + fprintf(stderr, "\n%s(%u): direction = 1...\n", info, uId>>1); + for (i = 0; i < nw; i++) + { + if(aw[i].del) continue; + fprintf(stderr, "%s: (%u) v>>1: %u, dir: %u\n", info, i, aw[i].v>>1, aw[i].v&1); + } + + if(is_print_read == 0) return; + + + uId = uId>>1; + ma_utg_t *u = &g->u.a[uId]; + fprintf(stderr, "\n%s: include %u reads in total...\n", info, u->n); + for (k = 0; k < u->n; k++) + { + fprintf(stderr, "%s: rId>>1: %lu, dir: %lu, name: %.*s\n", + info, (unsigned long)(u->a[k]>>33), (unsigned long)((u->a[k]>>32)&1), + (int)Get_NAME_LENGTH((R_INF), (u->a[k]>>33)), Get_NAME((R_INF), (u->a[k]>>33))); + } +} + + +void reset_untig_hap_label(ma_ug_t *g, uint32_t uId, uint8_t trio_flag, uint8_t* bin_res) +{ + uint32_t k; + ma_utg_t *u = &g->u.a[uId]; + for (k = 0; k < u->n; k++) { + if(bin_res[u->a[k]>>33] == AMBIGU) bin_res[u->a[k]>>33] = trio_flag; + } +} + + +void print_read_all(ma_ug_t *ug, const char* name, ma_hit_t_alloc* sources, +ma_hit_t_alloc* reverse_sources, const char* info) +{ + fprintf(stderr, "\n\n****************************\n"); + uint32_t uId; + uId = print_untig_by_read(ug, name, (uint32_t)-1, sources, reverse_sources, info); + if(uId != (uint32_t)-1) print_untig(ug, uId, info, 1); + fprintf(stderr, "****************************\n"); +} + + +void renew_utg(ma_ug_t **ug, asg_t* read_g, kvec_asg_arc_t_warp* edge) +{ + ma_ug_t* high_level_ug = NULL; + asg_t* nsg = (*ug)->g; + uint32_t i; + ma_utg_t *u; + high_level_ug = ma_ug_gen(nsg); + for (i = 0; i < high_level_ug->u.n; i++) + { + high_level_ug->g->seq[i].c = PRIMARY_LABLE; + u = &(high_level_ug->u.a[i]); + if(u->m == 0) continue; + merge_unitig_content(u, (*ug), read_g, edge); + high_level_ug->g->seq[i].len = u->len; + } + ma_ug_destroy((*ug)); + (*ug) = high_level_ug; +} + + + +long long get_graph_statistic(asg_t *g) +{ + long long num_arc = 0; + uint32_t n_vtx = g->n_seq * 2, v; + + for (v = 0; v < n_vtx; ++v) + { + if (g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + ///num_arc += asg_arc_n(g, v); + num_arc += get_real_length(g, v, NULL); + } + + return num_arc; +} + +void get_trio_labs(buf_t* b, ma_ug_t *ug, Trio_counter* flag) +{ + flag->father_occ = flag->mother_occ = flag->ambig_occ = flag->drop_occ = 0; + uint32_t i, v, k, rId; + if(ug == NULL) + { + for (i = 0; i < b->b.n; ++i) + { + if(R_INF.trio_flag[b->b.a[i]>>1]==FATHER) + { + flag->father_occ++; + } + else if(R_INF.trio_flag[b->b.a[i]>>1]==MOTHER) + { + flag->mother_occ++; + } + else if(R_INF.trio_flag[b->b.a[i]>>1]==AMBIGU) + { + flag->ambig_occ++; + } + else if(R_INF.trio_flag[b->b.a[i]>>1]==DROP) + { + flag->drop_occ++; + } + } + } + else + { + ma_utg_t* u = NULL; + for (i = 0; i < b->b.n; ++i) + { + v = b->b.a[i]>>1; + u = &(ug->u.a[v]); + if(u->m == 0) continue; + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + if(R_INF.trio_flag[rId]==FATHER) + { + flag->father_occ++; + } + else if(R_INF.trio_flag[rId]==MOTHER) + { + flag->mother_occ++; + } + else if(R_INF.trio_flag[rId]==AMBIGU) + { + flag->ambig_occ++; + } + else if(R_INF.trio_flag[rId]==DROP) + { + flag->drop_occ++; + } + } + } + } + + flag->total = flag->father_occ + flag->mother_occ + flag->ambig_occ + flag->drop_occ; +} + +uint32_t cal_trio_vec(buf_t* b, ma_ug_t *ug, float thres) +{ + uint32_t i, father_occ = 0, mother_occ = 0, v, k, rId; + if(ug == NULL) + { + for (i = 0; i < b->b.n; ++i) + { + if(R_INF.trio_flag[b->b.a[i]>>1]==FATHER) + { + father_occ++; + } + else if(R_INF.trio_flag[b->b.a[i]>>1]==MOTHER) + { + mother_occ++; + } + } + } + else + { + ma_utg_t* u = NULL; + for (i = 0; i < b->b.n; ++i) + { + v = b->b.a[i]>>1; + u = &(ug->u.a[v]); + if(u->m == 0) continue; + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + if(R_INF.trio_flag[rId]==FATHER) + { + father_occ++; + } + else if(R_INF.trio_flag[rId]==MOTHER) + { + mother_occ++; + } + } + } + } + + + + if(father_occ >= thres*(father_occ+mother_occ)) return FATHER; + if(mother_occ >= thres*(father_occ+mother_occ)) return MOTHER; + return AMBIGU; +} + +int cut_trio_tip_primary(asg_t *g, ma_ug_t *ug, uint32_t max_ext, uint32_t trio_flag, uint32_t keep_out_node, +asg_t *read_sg, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, uint8_t* is_r_het, uint32_t min_edge_length) +{ + double startTime = Get_T(); + uint32_t n_vtx = g->n_seq * 2, v, w, i, cnt = 0, tipEvaluateLen, flag, inner_flag, operation, tip_trio_flag; + uint32_t non_trio_flag = (uint32_t)-1, nw; + asg_arc_t *aw = NULL; + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + + buf_t b, b_0, b_1; + + memset(&b, 0, sizeof(buf_t)); + memset(&b_0, 0, sizeof(buf_t)); + memset(&b_1, 0, sizeof(buf_t)); + + for (v = 0; v < n_vtx; ++v) + { + if (g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + if (g->seq[v>>1].c == CUT || g->seq[v>>1].c == CUT_DIF_HAP || g->seq[v>>1].c == TRIM) continue; + if(get_real_length(g, (v^1), NULL) != 0) continue; + ///cut tip of length <= max_ext + flag = check_tip(g, v, &w, &b, max_ext); + if(flag == LOOP || flag == LONG_TIPS) continue; + if(keep_out_node && flag == MUL_OUTPUT) continue; + if(ug!=NULL) + { + tipEvaluateLen = 0; + for (i = 0; i < b.b.n; ++i) + { + tipEvaluateLen += EvaluateLen(ug->u, (b.b.a[i]>>1)); + } + if(tipEvaluateLen > max_ext) continue; + } + + operation = TRIM; + ///we need to deal with MUL_INPUT and END_TIPS + ///two operations: 1. trimming 2. cutting + if(flag == END_TIPS) + { + tip_trio_flag = cal_trio_vec(&b, ug, TRIO_THRES); + if(((tip_trio_flag == FATHER) || (tip_trio_flag == MOTHER)) + && + (tip_trio_flag != non_trio_flag)) + { + operation = CUT; + } + } + + ///if(flag == MUL_INPUT || flag == MUL_OUTPUT) + if(flag == MUL_INPUT) + { + // tip_trio_flag = cal_trio_vec(&b, ug, TRIO_THRES); + // if(((tip_trio_flag == FATHER) || (tip_trio_flag == MOTHER)) + // && + // (tip_trio_flag != non_trio_flag)) + // { + // operation = CUT; + // } + /** + To do lists: we can refine this function at the final step + 1. ideally, we should check if this tip comes from different haplotype with another unitig. + That might be helpful to recover bubbles. We should keep all break points in a vector, + and break these types of tip. At last, recover them. + + 2. if this tip has enough haplotype information, we should check if it does not + come from different haplotype with another unitig. If it does not, do not trim them + if(operation == TRIM) + { + get_real_length(g, b.b.a[b.b.n-1], &w); + w = w^1; + ; + } + **/ + get_real_length(g, b.b.a[b.b.n-1], &w); + w = w^1; + aw = asg_arc_a(g, w); + nw = asg_arc_n(g, w); + for (i = 0; i < nw; ++i) + { + if(operation == CUT) break; + if(aw[i].del) continue; + if(aw[i].v == (b.b.a[b.b.n-1]^1)) continue; + inner_flag = check_different_haps(g, ug, read_sg, b.b.a[b.b.n-1]^1, aw[i].v, + reverse_sources, &b_0, &b_1, ruIndex, is_r_het, min_edge_length, 1); + if(inner_flag == NON_PLOID) operation = CUT; + } + } + + + for (i = 0; i < b.b.n; ++i) + { + g->seq[(b.b.a[i]>>1)].c = ALTER_LABLE; + } + + for (i = 0; i < b.b.n; ++i) + { + asg_seq_drop(g, (b.b.a[i]>>1)); + } + + + if(operation == CUT) + { + for (i = 0; i < b.b.n; ++i) + { + g->seq[(b.b.a[i]>>1)].c = CUT; + } + } + + ++cnt; + } + + + if (cnt > 0) asg_cleanup(g); + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] cut %d tips\n", __func__, cnt); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + free(b.b.a); + free(b_0.b.a); + free(b_1.b.a); + + + return cnt; +} + +void label_r_set(buf_t* b, R_to_U* ruIndex, ma_ug_t *ug, uint32_t flag) +{ + uint32_t uid, rid, qn; + ma_utg_t *u = NULL; + for (uid = 0; uid < b->b.n;uid++) + { + u = &(ug->u.a[b->b.a[uid]>>1]); + ///each read + for (rid = 0; rid < u->n; rid++) + { + qn = (u->a[rid]>>33); + if(flag != (uint32_t)-1) + { + set_R_to_U(ruIndex, qn, b->b.a[uid]>>1, 1, NULL); + } + else + { + ruIndex->index[qn] = (uint32_t)-1; + } + } + } +} + +inline int trio_check(ma_ug_t *ug, uint32_t *a, uint32_t a_n, uint32_t flag) +{ + if(flag != FATHER && flag != MOTHER) return 0; + uint32_t flag_occ = 0, non_flag_occ = 0, ambigious = 0, u_n = 0, f, nf, ab, k; + for (k = 0; k < a_n; k++) { + get_unitig_trio_flag(&(ug->u.a[a[k]>>1]), flag, &f, &nf, &ab); + flag_occ += f; + non_flag_occ += nf; + ambigious += ab; + u_n += ug->u.a[a[k]>>1].n; + } + if((flag_occ+non_flag_occ) == 0) return 0; + if(flag_occ <= ((non_flag_occ+flag_occ)*0.75)) return 0; + if(non_flag_occ == 0 && flag_occ >= 20) return 1; + if(u_n >= 100) + { + if(flag_occ < u_n*DOUBLE_CHECK_THRES) return 0; + } + else if(u_n >= 50) + { + if(flag_occ < u_n*DOUBLE_CHECK_THRES*0.5) return 0; + } + else + { + if(flag_occ < u_n*DOUBLE_CHECK_THRES*0.25) return 0; + } + return 1; +} + +int asg_arc_cut_trio_long_tip_primary(asg_t *g, ma_ug_t *ug, asg_t *read_sg, ma_hit_t_alloc* reverse_sources, +R_to_U* ruIndex, uint32_t min_edge_length, float drop_ratio, uint32_t trio_flag, hap_cov_t *cov, utg_trans_t *o) +{ + double startTime = Get_T(); + ///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, convex, v_maxLen_i = (uint32_t)-1, flag, operation; + uint32_t return_flag, n_tips; + long long ll, v_maxLen, tmp, max_stop_nodeLen, max_stop_baseLen; + + buf_t b, b_0, b_1; + memset(&b, 0, sizeof(buf_t)); + memset(&b_0, 0, sizeof(buf_t)); + memset(&b_1, 0, sizeof(buf_t)); + + for (v = 0; v < n_vtx; ++v) + { + uint32_t i, k, n_arc = 0, nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + n_arc = get_real_length(g, v, NULL); + if (n_arc < 2) continue; + + v_maxLen = -1; + v_maxLen_i = (uint32_t)-1; + n_tips = 0; + + for (i = 0, n_arc = 0; i < nv; i++) + { + if (!av[i].del) + { + return_flag = get_unitig(g, ug, av[i].v, &convex, &ll, &tmp, &max_stop_nodeLen, + &max_stop_baseLen, 1, NULL); + + if(return_flag==LOOP) continue; + if(return_flag==END_TIPS) n_tips++; + + if(v_maxLen < ll) + { + v_maxLen = ll; + v_maxLen_i = i; + } + } + } + + if(n_tips==0) continue; + + for (i = 0, n_arc = 0; i < nv; i++) + { + if (!av[i].del) + { + ///skip the longest way + if(v_maxLen_i == i) continue; + + b.b.n = 0; + if(get_unitig(g, ug, av[i].v, &convex, &ll, &tmp, &max_stop_nodeLen, + &max_stop_baseLen, 1, &b)!=END_TIPS) + { + continue; + } + + if(ll >= (v_maxLen*drop_ratio)) continue; + if(trio_check(ug, b.b.a, b.b.n, trio_flag)) continue; + n_reduced++; + + operation = TRIM; + flag = check_different_haps(g, ug, read_sg, av[v_maxLen_i].v, av[i].v, reverse_sources, + &b_0, &b_1, ruIndex, cov->is_r_het, min_edge_length, 1); + // #define UNAVAILABLE (uint32_t)-1 + // #define PLOID 0 + // #define NON_PLOID 1 + if(flag == NON_PLOID) operation = CUT; + + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]>>1].c = ALTER_LABLE; + } + + for (k = 0; k < b.b.n; k++) + { + asg_seq_drop(g, b.b.a[k]>>1); + } + + if(operation == CUT) + { + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]>>1].c = CUT; + } + } + + if(cov && operation != CUT) + { + collect_trans_cov(__func__, &b_0, av[v_maxLen_i].ol, &b_1, av[i].ol, ug, read_sg, cov); + } + + if(o && operation != CUT) + { + collect_trans_ovlp(__func__, &b_0, av[v_maxLen_i].ol, &b_1, av[i].ol, ug, o); + } + + } + } + } + + + asg_cleanup(g); + asg_symm(g); + free(b.b.a); + free(b_0.b.a); + free(b_1.b.a); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d long tips\n", + __func__, n_reduced); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + return n_reduced; +} + +int asg_arc_cut_trio_long_tip_primary_complex(asg_t *g, ma_ug_t *ug, asg_t *read_sg, ma_hit_t_alloc* reverse_sources, +R_to_U* ruIndex, uint32_t min_edge_length, float drop_ratio, uint32_t stops_threshold, hap_cov_t *cov, utg_trans_t *o, uint32_t trio_flag) +{ + double startTime = Get_T(); + uint32_t v, n_vtx = g->n_seq * 2, n_reduced = 0, convex, in, flag, operation; + uint32_t return_flag, convex_i, k; + long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; + + buf_t b, b_0, b_1; + memset(&b, 0, sizeof(buf_t)); + memset(&b_0, 0, sizeof(buf_t)); + memset(&b_1, 0, sizeof(buf_t)); + for (v = 0; v < n_vtx; ++v) + { + uint32_t i; + if(g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + ///tip + if (get_real_length(g, v, NULL) != 0) continue; + if(get_real_length(g, v^1, NULL) != 1) continue; + + b.b.n = 0; + return_flag = get_unitig(g, ug, v^1, &convex, &ll, &tmp, &max_stop_nodeLen, + &max_stop_baseLen, 1, &b); + + if(return_flag != MUL_INPUT) continue; + if(trio_check(ug, b.b.a, b.b.n, trio_flag)) continue; + in = convex^1; + get_real_length(g, convex, &convex); + convex = convex^1; + uint32_t n_convex = asg_arc_n(g, convex), convexLen = ll; + asg_arc_t *a_convex = asg_arc_a(g, convex); + for (i = 0; i < n_convex; i++) + { + if(a_convex[i].del) continue; + if(a_convex[i].v == in) break; + } + convex_i = i; + ///if(convex_i == n_convex) fprintf(stderr, "ERROR\n"); + + + for (i = 0; i < n_convex; i++) + { + if(a_convex[i].del) continue; + if(i == convex_i) continue; + + return_flag = get_unitig(g, ug, a_convex[i].v, &convex, &ll, &tmp, &max_stop_nodeLen, + &max_stop_baseLen, stops_threshold, NULL); + + if(convexLen < ll*drop_ratio && max_stop_nodeLen >= ll*MAX_STOP_RATE) + { + n_reduced++; + operation = TRIM; + flag = check_different_haps(g, ug, read_sg, a_convex[convex_i].v, a_convex[i].v, + reverse_sources, &b_0, &b_1, ruIndex, cov->is_r_het, min_edge_length, stops_threshold); + // #define UNAVAILABLE (uint32_t)-1 + // #define PLOID 0 + // #define NON_PLOID 1 + if(flag == NON_PLOID) operation = CUT; + + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]>>1].c = ALTER_LABLE; + } + + for (k = 0; k < b.b.n; k++) + { + asg_seq_drop(g, b.b.a[k]>>1); + } + + if(operation == CUT) + { + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]>>1].c = CUT; + } + } + + ///note: we need to remove b_0, insetad of b_1 here + if(cov && operation != CUT) + { + collect_trans_cov(__func__, &b_1, a_convex[i].ol, &b_0, a_convex[convex_i].ol, ug, read_sg, cov); + } + + if(o && operation != CUT) + { + collect_trans_ovlp(__func__, &b_1, a_convex[i].ol, &b_0, a_convex[convex_i].ol, ug, o); + } + + + break; + } + } + } + + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d long tips\n", + __func__, n_reduced); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + asg_cleanup(g); + asg_symm(g); + free(b.b.a); + free(b_0.b.a); + free(b_1.b.a); + + return n_reduced; +} + +void renew_longest_tip_by_drop(asg_t *g, ma_ug_t *ug, asg_arc_t *av, uint32_t nv, +long long* base_maxLen, long long* base_maxLen_i, uint32_t stops_threshold, buf_t* b, +uint32_t trio_flag) +{ + if(trio_flag != FATHER && trio_flag != MOTHER) return; + Trio_counter max, cur; + memset(&max, 0, sizeof(Trio_counter)); + memset(&cur, 0, sizeof(Trio_counter)); + long long ll, tmp, max_stop_nodeLen, max_stop_baseLen, max_weight = 0, cur_weight = 0; + uint32_t convex, i, return_flag, best_tip_i, best_tip_len; + + b->b.n = 0; + return_flag = get_unitig(g, ug, av[(*base_maxLen_i)].v, &convex, &tmp, &ll, + &max_stop_nodeLen, &max_stop_baseLen, stops_threshold, b); + if(return_flag!=END_TIPS) return; + + + get_trio_labs(b, ug, &max); + ///means this unitig might be at current haplotype + ///if(max.drop_occ<(max.total*TRIO_DROP_THRES)) return; + + + best_tip_i = (*base_maxLen_i); + best_tip_len = (*base_maxLen); + + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + if(i==(*base_maxLen_i)) continue; + + b->b.n = 0; + return_flag = get_unitig(g, ug, av[i].v, &convex, &tmp, &ll, + &max_stop_nodeLen, &max_stop_baseLen, stops_threshold, b); + + if(return_flag!=END_TIPS) return; + ///this tip should be long enough + if(ll<(TRIO_DROP_LENGTH_THRES*(*base_maxLen))) continue; + + get_trio_labs(b, ug, &cur); + + if(trio_flag == FATHER) + { + max_weight = (long long)max.father_occ - (long long)max.drop_occ - (long long)max.mother_occ; + cur_weight = (long long)cur.father_occ - (long long)cur.drop_occ - (long long)cur.mother_occ; + ///this unitig is very likly at another haplotype, ignore it + if((cur.drop_occ+cur.mother_occ)>=(cur.total*TRIO_DROP_THRES)) continue; + } + + if(trio_flag == MOTHER) + { + max_weight = (long long)max.mother_occ - (long long)max.drop_occ - (long long)max.father_occ; + cur_weight = (long long)cur.mother_occ - (long long)cur.drop_occ - (long long)cur.father_occ; + ///this unitig is very likly at another haplotype, ignore it + if((cur.drop_occ+cur.father_occ)>=(cur.total*TRIO_DROP_THRES)) continue; + } + + + if(cur_weight > max_weight) + { + max = cur; + best_tip_i = i; + best_tip_len = ll; + } + else if(cur_weight == max_weight && ll>best_tip_len) + { + max = cur; + best_tip_i = i; + best_tip_len = ll; + } + } + + (*base_maxLen_i) = best_tip_i; + (*base_maxLen) = best_tip_len; +} + +int asg_arc_cut_trio_long_equal_tips_assembly(asg_t *g, ma_ug_t *ug, asg_t *read_sg, +ma_hit_t_alloc* reverse_sources, long long miniedgeLen, R_to_U* ruIndex, uint32_t trio_flag, +hap_cov_t *cov, utg_trans_t *o) +{ + double startTime = Get_T(); + uint32_t v, n_vtx = g->n_seq * 2, n_reduced = 0, convex, flag, is_hap, n_tips, return_flag, k; + long long ll, base_maxLen, base_maxLen_i, max_stop_nodeLen, max_stop_baseLen, tmp; + buf_t b, b_0, b_1; + memset(&b, 0, sizeof(buf_t)); + memset(&b_0, 0, sizeof(buf_t)); + memset(&b_1, 0, sizeof(buf_t)); + + for (v = 0; v < n_vtx; ++v) + { + uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + n_arc = get_real_length(g, v, NULL); + if (n_arc < 2) continue; + + base_maxLen = -1; + base_maxLen_i = -1; + n_tips = 0; + is_hap = 0; + + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + return_flag = get_unitig(g, ug, av[i].v, &convex, &tmp, &ll, &max_stop_nodeLen, + &max_stop_baseLen, 1, NULL); + + if(return_flag==LOOP) continue; + if(return_flag==END_TIPS) n_tips++; + + if(base_maxLen < ll) + { + base_maxLen = ll; + base_maxLen_i = i; + } + } + + if(n_tips==0) continue; + ///all the unitigs here are tips + if(n_arc == n_tips) + { + renew_longest_tip_by_drop(g, ug, av, nv, &base_maxLen, + &base_maxLen_i, 1, &b, trio_flag); + } + + for (i = 0; i < nv; i++) + { + if(i==base_maxLen_i) continue; + if(av[i].del) continue; + + b.b.n = 0; + return_flag = get_unitig(g, ug, av[i].v, &convex, &tmp, &ll, &max_stop_nodeLen, + &max_stop_baseLen, 1, &b); + + if(return_flag != END_TIPS) continue; + if(trio_check(ug, b.b.a, b.b.n, trio_flag)) continue; + + flag = check_different_haps(g, ug, read_sg, av[base_maxLen_i].v, av[i].v, + reverse_sources, &b_0, &b_1, ruIndex, cov->is_r_het, miniedgeLen, 1); + + // #define UNAVAILABLE (uint32_t)-1 + // #define PLOID 0 + // #define NON_PLOID 1 + if(flag != PLOID) continue; + n_reduced++; + + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]>>1].c = ALTER_LABLE; + } + + for (k = 0; k < b.b.n; k++) + { + asg_seq_drop(g, b.b.a[k]>>1); + } + + if(cov) + { + collect_trans_cov(__func__, &b_0, av[base_maxLen_i].ol, &b_1, av[i].ol, ug, read_sg, cov); + } + + if(o) + { + collect_trans_ovlp(__func__, &b_0, av[base_maxLen_i].ol, &b_1, av[i].ol, ug, o); + } + + + is_hap++; + } + + if(is_hap > 0) + { + i = base_maxLen_i; + b.b.n = 0; + get_unitig(g, ug, av[i].v, &convex, &tmp, &ll, &max_stop_nodeLen, + &max_stop_baseLen, 1, &b); + + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]>>1].c = HAP_LABLE; + } + } + } + + asg_cleanup(g); + asg_symm(g); + free(b.b.a); + free(b_0.b.a); + free(b_1.b.a); + + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d long tips\n", + __func__, n_reduced); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + return n_reduced; +} + +uint8_t if_primary_unitig(ma_utg_t* u, asg_t* read_g, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag) +{ + if(asm_opt.recover_atg_cov_min < 0 || asm_opt.recover_atg_cov_max < 0) return 0; + long long R_bases = 0, C_bases = 0, C_bases_primary = 0, C_bases_alter = 0; + long long total_C_bases = 0, total_C_bases_primary = 0; + uint32_t available_reads = 0, k, j, rId, tn, is_Unitig; + ma_hit_t *h; + if(u->m == 0) return 0; + total_C_bases = total_C_bases_primary = available_reads = 0; + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 1; + } + + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + C_bases = C_bases_primary = C_bases_alter = 0; + R_bases = coverage_cut[rId].e - coverage_cut[rId].s; + for (j = 0; j < (uint64_t)(sources[rId].length); j++) + { + h = &(sources[rId].buffer[j]); + if(h->el != 1) continue; + tn = Get_tn((*h)); + if(read_g->seq[tn].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + if(read_g->seq[tn].del == 1) continue; + if(r_flag[tn]) + { + C_bases_primary += Get_qe((*h)) - Get_qs((*h)); + } + else + { + C_bases_alter += Get_qe((*h)) - Get_qs((*h)); + } + } + + C_bases = C_bases_primary + C_bases_alter; + total_C_bases += C_bases; + ///if(C_bases_primary < C_bases * ALTER_COV_THRES) continue; + + C_bases = C_bases/R_bases; + if(C_bases >= asm_opt.recover_atg_cov_min && C_bases <= asm_opt.recover_atg_cov_max) + { + if(C_bases_primary >= (C_bases_primary + C_bases_alter) * ALTER_COV_THRES) available_reads++; + total_C_bases_primary += C_bases_primary; + } + } + + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 0; + } + + ///fprintf(stderr, "available_reads: %u, u->n: %u\n", available_reads, u->n); + + //if(available_reads < (u->n * 0.8) || available_reads == 0) + if(((available_reads < (u->n * 0.8)) && (total_C_bases_primary < (total_C_bases * 0.8))) + || available_reads == 0) + { + return 0; + } + else + { + return 1; + } +} + + + +int magic_trio_phasing(asg_t *g, ma_ug_t *ug, asg_t *read_sg, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long miniedgeLen, +R_to_U* ruIndex, uint32_t positive_flag, float drop_rate) +{ + uint32_t v, n_vtx = g->n_seq * 2, n_reduced = 0; + ma_utg_t* nsu = NULL; + uint32_t flag = (uint32_t)-1, flag_occ, non_flag_occ, ambigious, del_node, keep_node; + if(positive_flag == FATHER) flag = MOTHER; + if(positive_flag == MOTHER) flag = FATHER; + uint8_t* primary_flag = (uint8_t*)calloc(read_sg->n_seq, sizeof(uint8_t)); + + for (v = 0; v < n_vtx; ++v) + { + uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + if (nv < 2 || g->seq[v>>1].del /**|| g->seq[v>>1].c == ALTER_LABLE**/) continue; + n_arc = get_real_length(g, v, NULL); + if (n_arc < 2) continue; + del_node = keep_node = 0; + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + nsu = &(ug->u.a[av[i].v>>1]); + get_unitig_trio_flag(nsu, flag, &flag_occ, &non_flag_occ, &ambigious); + ///we may need it or not + if((flag_occ <= ((non_flag_occ+flag_occ)*drop_rate))||((flag_occ+non_flag_occ) == 0)) + { + keep_node++; + continue; + } + + if(nsu->n >= 100) + { + if(flag_occ < nsu->n*DOUBLE_CHECK_THRES) + { + keep_node++; + continue; + } + } + else if(nsu->n >= 50) + { + if(flag_occ < nsu->n*DOUBLE_CHECK_THRES*0.5) + { + keep_node++; + continue; + } + } + else + { + if(flag_occ < nsu->n*DOUBLE_CHECK_THRES*0.25) + { + keep_node++; + continue; + } + } + + del_node++; + } + + if(keep_node == 0 || del_node == 0) continue; + + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + nsu = &(ug->u.a[av[i].v>>1]); + + get_unitig_trio_flag(nsu, flag, &flag_occ, &non_flag_occ, &ambigious); + ///we may need it or not + if((flag_occ <= ((non_flag_occ+flag_occ)*drop_rate))||((flag_occ+non_flag_occ) == 0)) + { + continue; + } + + if(nsu->n >= 100) + { + if(flag_occ < nsu->n*DOUBLE_CHECK_THRES) + { + continue; + } + } + else if(nsu->n >= 50) + { + if(flag_occ < nsu->n*DOUBLE_CHECK_THRES*0.5) + { + continue; + } + } + else + { + if(flag_occ < nsu->n*DOUBLE_CHECK_THRES*0.25) + { + continue; + } + } + + if(if_primary_unitig(nsu, read_sg, coverage_cut, sources, ruIndex, primary_flag)) + { + continue; + } + + g->seq[av[i].v>>1].c = ALTER_LABLE; + asg_seq_drop(g, av[i].v>>1); + n_reduced++; + } + } + + + + + asg_cleanup(g); + free(primary_flag); + return n_reduced; +} + +int asg_arc_cut_trio_long_equal_tips_assembly_complex(asg_t *g, ma_ug_t *ug, asg_t *read_sg, +ma_hit_t_alloc* reverse_sources, long long miniedgeLen, R_to_U* ruIndex, uint32_t stops_threshold, +hap_cov_t *cov, utg_trans_t *o, uint32_t trio_flag) +{ + double startTime = Get_T(); + uint32_t v, n_vtx = g->n_seq * 2, n_reduced = 0, convex, in, flag; + uint32_t return_flag, convex_i, k; + long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; + + buf_t b, b_0, b_1; + memset(&b, 0, sizeof(buf_t)); + memset(&b_0, 0, sizeof(buf_t)); + memset(&b_1, 0, sizeof(buf_t)); + + + for (v = 0; v < n_vtx; ++v) + { + uint32_t i; + if (g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + ///tip + if (get_real_length(g, v, NULL) != 0) continue; + if (get_real_length(g, v^1, NULL) != 1) continue; + + b.b.n = 0; + return_flag = get_unitig(g, ug, v^1, &convex, &tmp, &ll, &max_stop_nodeLen, + &max_stop_baseLen, 1, &b); + + if(return_flag != MUL_INPUT) continue; + if(trio_check(ug, b.b.a, b.b.n, trio_flag)) continue; + in = convex^1; + get_real_length(g, convex, &convex); + convex = convex^1; + uint32_t n_convex = asg_arc_n(g, convex), convexLen = ll; + asg_arc_t *a_convex = asg_arc_a(g, convex); + for (i = 0; i < n_convex; i++) + { + if(a_convex[i].del) continue; + if(a_convex[i].v == in) break; + } + convex_i = i; + ///if(convex_i == n_convex) fprintf(stderr, "ERROR1\n"); + // if((v>>1) == 304 && (convex>>1) == 12875) + // { + // fprintf(stderr, "\n++v-%u, convex-%u, n_convex-%u\n", v, convex, n_convex); + // } + + for (i = 0; i < n_convex; i++) + { + if(a_convex[i].del) continue; + if(i == convex_i) continue; + + return_flag = get_unitig(g, ug, a_convex[i].v, &convex, &tmp, &ll, &max_stop_nodeLen, + &max_stop_baseLen, stops_threshold, NULL); + + // if((v>>1) == 304 && n_convex == 2) + // { + // fprintf(stderr, "---v-%u (len: %u), convex-%u, a_convex[i].v-%u (len: %lld), max_stop_baseLen: %lld\n", + // v, convexLen, convex, a_convex[i].v, ll, max_stop_baseLen); + // } + + if(ll>convexLen && max_stop_baseLen>=ll*MAX_STOP_RATE) + { + flag = check_different_haps(g, ug, read_sg, a_convex[convex_i].v, a_convex[i].v, + reverse_sources, &b_0, &b_1, ruIndex, cov->is_r_het, miniedgeLen, stops_threshold); + // #define UNAVAILABLE (uint32_t)-1 + // #define PLOID 0 + // #define NON_PLOID 1 + if(flag != PLOID) continue; + n_reduced++; + + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]>>1].c = ALTER_LABLE; + } + + for (k = 0; k < b.b.n; k++) + { + asg_seq_drop(g, b.b.a[k]>>1); + } + + ///note: we need to remove b_0, insetad of b_1 here + if(cov) + { + collect_trans_cov(__func__, &b_1, a_convex[i].ol, &b_0, a_convex[convex_i].ol, ug, read_sg, cov); + } + + if(o) + { + collect_trans_ovlp(__func__, &b_1, a_convex[i].ol, &b_0, a_convex[convex_i].ol, ug, o); + } + + + ///lable the primary one + b_0.b.n = 0; + get_unitig(g, ug, a_convex[i].v, &convex, &tmp, &ll, &max_stop_nodeLen, + &max_stop_baseLen, stops_threshold, &b_0); + for (k = 0; k < b_0.b.n; k++) + { + g->seq[b_0.b.a[k]>>1].c = HAP_LABLE; + } + + break; + } + } + + } + + asg_cleanup(g); + asg_symm(g); + free(b.b.a); + free(b_0.b.a); + free(b_1.b.a); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d long tips\n", + __func__, n_reduced); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + return n_reduced; +} + + +int detect_chimeric_by_topo(asg_t *g, ma_ug_t *ug, asg_t *read_sg, +ma_hit_t_alloc* reverse_sources, long long miniedgeLen, uint32_t stops_threshold, float drop_rate, +R_to_U* ruIndex, utg_trans_t *o, uint8_t* is_r_het) +{ + double startTime = Get_T(); + uint32_t i, k, v_i, v_beg, v_end, selfLen, w1, w2, wv, nw, n_vtx = g->n_seq * 2, n_reduced = 0, convex, convex_T, read_num; + asg_arc_t *aw; + long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; + + buf_t b_0, b_1; + memset(&b_0, 0, sizeof(buf_t)); + memset(&b_1, 0, sizeof(buf_t)); + + + for (v_i = 0; v_i < n_vtx; ++v_i) + { + v_beg = v_i; + ///some node could be deleted + if (g->seq[v_beg>>1].del || g->seq[v_beg>>1].c == ALTER_LABLE) continue; + if(get_real_length(g, v_beg, NULL) != 1) continue; + + get_real_length(g, v_beg, &w1); + if(get_real_length(g, w1^1, NULL)<=1) continue; + + if(get_unitig(g, ug, v_beg^1, &v_end, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, + 1, NULL)==LOOP) + { + continue; + } + selfLen = ll; + if(get_real_length(g, v_end, NULL) != 1) continue; + + + get_real_length(g, v_end, &w2); + if(get_real_length(g, w2^1, NULL)<=1) continue; + + get_unitig(g, ug, w1, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, + stops_threshold, NULL); + if(ll*drop_rate < selfLen) continue; + if(ll*0.4 > max_stop_nodeLen) continue; + + get_unitig(g, ug, w2, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, + stops_threshold, NULL); + if(ll*drop_rate < selfLen) continue; + if(ll*0.4 > max_stop_nodeLen) continue; + + stops_threshold++; + + + w1 = w1^1;wv=v_beg^1;aw = asg_arc_a(g, w1); nw = asg_arc_n(g, w1);convex_T = (uint32_t)-1; + for (i = 0; i < nw; i++) + { + if(aw[i].del) continue; + + get_unitig(g, ug, aw[i].v, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, + stops_threshold, NULL); + if(ll*drop_rate < selfLen) break; + if(ll*0.4 > max_stop_nodeLen) continue; + + if((aw[i].v>>1)==(v_beg>>1)) + { + if(convex_T != (uint32_t)-1) break; + convex_T = convex; + } + } + if(i!=nw) continue; + + for (i = 0; i < nw; i++) + { + if(aw[i].del) continue; + if((aw[i].v>>1) == (v_beg>>1)) continue; + + b_0.b.n = 0; + get_unitig(g, ug, aw[i].v, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, + stops_threshold, &b_0); + ///if(convex == convex_T) break; + for (k = 0; k < b_0.b.n; k++) + { + if((b_0.b.a[k]>>1) == (convex_T>>1)) break; + } + if(k != b_0.b.n) break; + + if(check_different_haps(g, ug, read_sg, wv, aw[i].v, reverse_sources, &b_0, &b_1, + ruIndex, is_r_het, miniedgeLen, stops_threshold)==PLOID) + { + break; + } + } + if(i!=nw) continue; + + + + + + w2 = w2^1;wv=v_end^1;aw = asg_arc_a(g, w2); nw = asg_arc_n(g, w2);convex_T = (uint32_t)-1; + for (i = 0; i < nw; i++) + { + if(aw[i].del) continue; + + + get_unitig(g, ug, aw[i].v, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, + stops_threshold, NULL); + if(ll*drop_rate < selfLen) break; + if(ll*0.4 > max_stop_nodeLen) continue; + + if((aw[i].v>>1) == (v_end>>1)) + { + if(convex_T != (uint32_t)-1) break; + convex_T = convex; + } + } + if(i!=nw) continue; + + for (i = 0; i < nw; i++) + { + if(aw[i].del) continue; + if((aw[i].v>>1) == (v_end>>1)) continue; + + b_0.b.n = 0; + get_unitig(g, ug, aw[i].v, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, + stops_threshold, &b_0); + ///if(convex == convex_T) break; + for (k = 0; k < b_0.b.n; k++) + { + if((b_0.b.a[k]>>1) == (convex_T>>1)) break; + } + if(k != b_0.b.n) break; + + if(check_different_haps(g, ug, read_sg, wv, aw[i].v, reverse_sources, &b_0, &b_1, + ruIndex, is_r_het, miniedgeLen, stops_threshold)==PLOID) + { + break; + } + } + if(i!=nw) continue; + + n_reduced++; + b_0.b.n = 0; + read_num = 0; + get_unitig(g, ug, v_beg^1, &v_end, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, &b_0); + for (k = 0; k < b_0.b.n; k++) + { + g->seq[b_0.b.a[k]>>1].c = ALTER_LABLE; + read_num += ug->u.a[b_0.b.a[k]>>1].n; + } + + for (k = 0; k < b_0.b.n; k++) + { + asg_seq_drop(g, b_0.b.a[k]>>1); + if(o) asg_seq_del(o->cug->g, b_0.b.a[k]>>1); + } + + if(read_num <= CHIMERIC_TRIM_THRES) + { + for (k = 0; k < b_0.b.n; k++) + { + g->seq[b_0.b.a[k]>>1].c = CUT; + } + } + + } + + if(o) asg_cleanup(o->cug->g); + asg_cleanup(g); + free(b_0.b.a); + free(b_1.b.a); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d long tips\n", + __func__, n_reduced); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + + return n_reduced; +} + +uint32_t cmp_untig_graph(ma_ug_t *src, ma_ug_t *dest) +{ + uint32_t nv, nw; + asg_arc_t *av = NULL, *aw = NULL; + uint32_t v, i, k, n_vtx = dest->g->n_seq*2; + if(src->g->n_seq!=dest->g->n_seq) + { + fprintf(stderr, "src->g->n_seq: %u, dest->g->n_seq: %u\n", src->g->n_seq, dest->g->n_seq); + ///return 1; + } + if(src->g->r_seq!=dest->g->r_seq) + { + fprintf(stderr, "src->g->r_seq: %u, dest->g->r_seq: %u\n", src->g->r_seq, dest->g->r_seq); + ///return 1; + } + if(src->g->is_srt!=dest->g->is_srt) + { + fprintf(stderr, "src->g->is_srt: %u, dest->g->is_srt: %u\n", src->g->is_srt, dest->g->is_srt); + ///return 1; + } + if(src->g->is_symm!=dest->g->is_symm) + { + fprintf(stderr, "src->g->is_symm: %u, dest->g->is_symm: %u\n", src->g->is_symm, dest->g->is_symm); + ///return 1; + } + ///if(memcmp(src->g->seq, dest->g->seq, sizeof(asg_seq_t)*src->g->n_seq)!=0) return 1; + + n_vtx = dest->g->n_seq; + for (v = 0; v < n_vtx; v++) + { + if(src->g->seq[v].c != dest->g->seq[v].c) + { + fprintf(stderr, "src->g->seq[%u].c: %u, dest->g->seq[%u].c: %u\n", + v, src->g->seq[v].c, v, dest->g->seq[v].c); + } + + if(src->g->seq[v].del != dest->g->seq[v].del) + { + fprintf(stderr, "src->g->seq[%u].del: %u, dest->g->seq[%u].del: %u\n", + v, src->g->seq[v].del, v, dest->g->seq[v].del); + } + + if(src->g->seq[v].len != dest->g->seq[v].len) + { + fprintf(stderr, "src->g->seq[%u].len: %u, dest->g->seq[%u].len: %u\n", + v, src->g->seq[v].len, v, dest->g->seq[v].len); + } + + if(src->u.a[v].n != dest->u.a[v].n) + { + fprintf(stderr, "src->u.a[%u].n: %u, dest->u.a[%u].n: %u\n", + v, src->u.a[v].n, v, dest->u.a[v].n); + } + + if(src->u.a[v].a[0] != dest->u.a[v].a[0] || + src->u.a[v].a[src->u.a[v].n-1] != dest->u.a[v].a[dest->u.a[v].n - 1]) + { + fprintf(stderr, "unequal beg/end node\n"); + } + } + + + n_vtx = dest->g->n_seq*2; + for (v = 0; v < n_vtx; v++) + { + nv = asg_arc_n(src->g, v); + av = asg_arc_a(src->g, v); + nw = asg_arc_n(dest->g, v); + aw = asg_arc_a(dest->g, v); + if(get_real_length(src->g, v, NULL) != get_real_length(dest->g, v, NULL)) + { + fprintf(stderr, "v>>1: %u, v&1: %u, get_real_length(src->g, v, NULL): %u, get_real_length(dest->g, v, NULL): %u\n", + v>>1, v&1, get_real_length(src->g, v, NULL), get_real_length(dest->g, v, NULL)); + ///return 1; + } + + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + for (k = 0; k < nw; k++) + { + if(aw[k].del) continue; + if(av[i].v == aw[k].v) break; + } + + if(k == nw) return 1; + } + } + + n_vtx = dest->g->n_seq; + ma_utg_t *src_u = NULL, *dest_u = NULL; + for (v = 0; v < n_vtx; v++) + { + src_u = &(src->u.a[v]); + dest_u = &(dest->u.a[v]); + if(src_u->circ!=dest_u->circ) return 1; + if(src_u->end!=dest_u->end) return 1; + if(src_u->len!=dest_u->len) return 1; + if(src_u->n!=dest_u->n) return 1; + if(src_u->start!=dest_u->start) return 1; + if(memcmp(src_u->a, dest_u->a, 8*src_u->n)!=0) return 1; + } + + return 0; +} + +ma_ug_t* copy_untig_graph(ma_ug_t *src) +{ + ma_ug_t *ug = NULL; + ug = (ma_ug_t*)calloc(1, sizeof(ma_ug_t)); + ug->g = asg_init(); + uint32_t v; + + ug->g->n_F_seq = src->g->n_F_seq; + ug->g->r_seq = src->g->r_seq; + ug->g->m_seq = ug->g->n_seq = src->g->n_seq; + ug->g->seq = (asg_seq_t*)malloc(ug->g->n_seq * sizeof(asg_seq_t)); + memcpy(ug->g->seq, src->g->seq, sizeof(asg_seq_t)*ug->g->n_seq); + + ug->g->m_arc = ug->g->n_arc = src->g->n_arc; + ug->g->arc = (asg_arc_t*)malloc(ug->g->n_arc*sizeof(asg_arc_t)); + memcpy(ug->g->arc, src->g->arc, sizeof(asg_arc_t)*ug->g->n_arc); + + ug->g->is_srt = src->g->is_srt; + ug->g->is_symm = src->g->is_symm; + ug->g->idx = (uint64_t*)malloc(ug->g->n_seq*2*8); + memcpy(ug->g->idx, src->g->idx, ug->g->n_seq*2*8); + asg_cleanup(ug->g); + + + + ug->u.m = ug->u.n = src->u.n; + ug->u.a = (ma_utg_t*)malloc(sizeof(ma_utg_t)*ug->u.n); + + ma_utg_t *src_u = NULL, *ug_u = NULL; + for (v = 0; v < ug->u.n; v++) + { + src_u = &(src->u.a[v]); + ug_u = &(ug->u.a[v]); + (*ug_u) = (*src_u); + ug_u->s = NULL; + ug_u->a = NULL; + ug_u->m = ug_u->n = src_u->n; + + ug_u->a = (uint64_t*)malloc(8 * ug_u->n); + memcpy(ug_u->a, src_u->a, 8*ug_u->n); + } + + /** + if(cmp_untig_graph(src, ug)) fprintf(stderr, "ERROR\n"); + ma_ug_destroy(ug); + return NULL; + **/ + return ug; +} + +asg_t* copy_read_graph(asg_t *src) +{ + asg_t *dest = NULL; + dest = asg_init(); + + dest->r_seq = src->r_seq; + dest->m_seq = dest->n_seq = src->n_seq; + dest->seq = (asg_seq_t*)malloc(dest->n_seq * sizeof(asg_seq_t)); + memcpy(dest->seq, src->seq, sizeof(asg_seq_t)*dest->n_seq); + + dest->m_arc = dest->n_arc = src->n_arc; + dest->arc = (asg_arc_t*)malloc(dest->n_arc*sizeof(asg_arc_t)); + memcpy(dest->arc, src->arc, sizeof(asg_arc_t)*dest->n_arc); + + dest->is_srt = src->is_srt; + dest->is_symm = src->is_symm; + dest->idx = NULL; + // dest->idx = (uint64_t*)malloc(dest->n_seq*2*8); + // memcpy(dest->idx, src->idx, dest->n_seq*2*8); + asg_cleanup(dest); + + if(src->seq_vis) + { + dest->seq_vis = (uint8_t*)malloc(dest->n_seq*2*sizeof(uint8_t)); + memcpy(dest->seq_vis, src->seq_vis, dest->n_seq*2*sizeof(uint8_t)); + } + + if(src->n_F_seq > 0 && src->F_seq) + { + dest->n_F_seq = src->n_F_seq; + dest->F_seq = (ma_utg_t*)malloc(dest->n_F_seq*sizeof(ma_utg_t)); + memcpy(dest->F_seq, src->F_seq, dest->n_F_seq*sizeof(ma_utg_t)); + } + return dest; +} + +rd_hamming_fly_t* gen_rd_hamming_fly_t(ma_ug_t *ug, asg_t *sg) +{ + rd_hamming_fly_t *p; CALLOC(p, 1); + MALLOC(p->o2n, sg->n_seq); + memset(p->o2n, -1, sizeof((*(p->o2n)))*sg->n_seq); + MALLOC(p->ugh, ug->g->n_seq); + return p; +} + +void destroy_rd_hamming_fly_t(rd_hamming_fly_t *p) +{ + free(p->o2n); free(p->srt->a); free(p->srt); + ma_ug_destroy(p->nug); asg_destroy(p->nsg); + asg_destroy(p->ref); free(p->ugh); +} + +void recall_arcs(asg_t *des, asg_t *src) +{ + uint32_t v, w, n_vtx = src->n_seq*2; + asg_arc_t *av, *za, *p; uint32_t an, zn, ai, zi, k; + kvec_t(asg_arc_t) ka; kv_init(ka); + + for (v = 0; v < n_vtx; ++v) { + if(src->seq[v>>1].del) continue; + za = asg_arc_a(src, v); zn = asg_arc_n(src, v); + av = asg_arc_a(des, v); an = asg_arc_n(des, v); + for (zi = 0; zi < zn; zi++) { + if(za[zi].del) continue; + w = za[zi].v; + for (ai = 0; ai < an; ai++) { + if(av[ai].del) continue; + if(av[ai].v == w) break; + } + if(ai >= an) kv_push(asg_arc_t, ka, za[zi]); + } + } + + if(ka.n) { + for (k = 0; k < ka.n; k++) { + p = asg_arc_pushp(des); *p = (ka.a[k]); + } + free(des->idx); + des->idx = 0; + des->is_srt = 0; + asg_cleanup(des); + // asg_symm(des); + } + fprintf(stderr, "[M::%s] # transitive arcs::%u\n", __func__, (uint32_t)ka.n); + fprintf(stderr, "[M::%s] # new arcs::%u, # old arcs::%u\n", __func__, des->n_arc, src->n_arc); + + kv_destroy(ka); +} + +ma_ug_t* gen_fg(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc* src, ma_sub_t *cov, int32_t max_hang, int32_t min_ovlp, int32_t gap_fuzz) +{ + uint32_t *idx; MALLOC(idx, rg->n_seq); + memset(idx, -1, sizeof((*idx))*rg->n_seq); + ma_ug_t *fg = copy_untig_graph(ug); asg_cleanup(fg->g);///some edges might be deleted + kvec_t(uint64_t) srt; kv_init(srt); + uint64_t i, k, l, m, rv, rw, uv, uw, zn, z, nist = 0; ma_utg_t *u; + for (k = 0; k < fg->u.n; k++) { + u = &(ug->u.a[k]); fg->g->seq[k].c = PRIMARY_LABLE; + if((u->circ) || (u->n == 0)) continue; + m = k<<1; m |= (((uint64_t)Uc_beg((*u)))<<32); kv_push(uint64_t, srt, m);///((uint32_t)(((*u)).a[0]>>32)); + m = (k<<1)+1; m |= (((uint64_t)Uc_end((*u)))<<32); kv_push(uint64_t, srt, m); + } + + + radix_sort_arch64(srt.a, srt.a+srt.n); + for (k = 1, l = 0; k <= srt.n; k++) { + if(k == srt.n || (srt.a[k]>>33) != (srt.a[l]>>33)) { + idx[srt.a[l]>>33] = l; + l = k; + } + } + + ma_hit_t_alloc* x; asg_arc_t *za; + ma_hit_t *h; ma_sub_t *sq, *st; + int32_t r; asg_arc_t t0, t1, *p; + for (k = 0; k < fg->u.n; k++) { + u = &(ug->u.a[k]); + if((u->circ) || (u->n == 0)) continue; + + uv = k<<1; rv = Uc_end((*u))^1; + x = &(src[rv>>1]); + za = asg_arc_a(ug->g, uv); + zn = asg_arc_n(ug->g, uv); + for (i = 0; i < x->length; i++) { + h = &(x->buffer[i]); + // if(!(h->el)) continue; + sq = &(cov[Get_qn(*h)]); st = &(cov[Get_tn(*h)]); + if(st->del || rg->seq[Get_tn(*h)].del) continue; + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t0); + + ///if it is a contained read, skip + if(r < 0) continue; + if((t0.ul>>32) != rv) continue; + rw = t0.v; + if(idx[rw>>1] == ((uint32_t)-1)) continue; + if(!(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, t0.ul>>32, t0.v, &t0))) continue; + + m = idx[rw>>1]; assert((srt.a[m]>>33) == (rw>>1)); + for (; m < srt.n && (srt.a[m]>>33) == (rw>>1); m++) { + if(rw == (srt.a[m]>>32)) { + uw = (uint32_t)srt.a[m]; + if(uv == uw) continue; + for (z = 0; z < zn; z++) { + if((!za[z].del) && (za[z].v==uw)) break; + } + if(z < zn) continue; + if(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, (t0.v^1), ((t0.ul>>32)^1), &t1)) { + p = asg_arc_pushp(fg->g); *p = t0; + p->ul<<=32; p->ul>>=32; p->ul |= (uv<<32); p->v = uw; + + p = asg_arc_pushp(fg->g); *p = t1; + p->ul<<=32; p->ul>>=32; p->ul |= ((uw^1)<<32); p->v = uv^1; + nist++; + } + } + } + } + + + uv = (k<<1)+1; rv = Uc_beg((*u))^1; + x = &(src[rv>>1]); + za = asg_arc_a(ug->g, uv); + zn = asg_arc_n(ug->g, uv); + for (i = 0; i < x->length; i++) { + h = &(x->buffer[i]); + // if(!(h->el)) continue; + sq = &(cov[Get_qn(*h)]); st = &(cov[Get_tn(*h)]); + if(st->del || rg->seq[Get_tn(*h)].del) continue; + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t0); + + ///if it is a contained read, skip + if(r < 0) continue; + if((t0.ul>>32) != rv) continue; + rw = t0.v; + if(idx[rw>>1] == ((uint32_t)-1)) continue; + if(!(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, t0.ul>>32, t0.v, &t0))) continue; + + m = idx[rw>>1]; assert((srt.a[m]>>33) == (rw>>1)); + for (; m < srt.n && (srt.a[m]>>33) == (rw>>1); m++) { + if(rw == (srt.a[m]>>32)) { + uw = (uint32_t)srt.a[m]; + if(uv == uw) continue; + for (z = 0; z < zn; z++) { + if((!za[z].del) && (za[z].v==uw)) break; + } + if(z < zn) continue; + if(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, (t0.v^1), ((t0.ul>>32)^1), &t1)) { + p = asg_arc_pushp(fg->g); *p = t0; + p->ul<<=32; p->ul>>=32; p->ul |= (uv<<32); p->v = uw; + + p = asg_arc_pushp(fg->g); *p = t1; + p->ul<<=32; p->ul>>=32; p->ul |= ((uw^1)<<32); p->v = uv^1; + nist++; + } + } + } + } + } + + if(nist) { + free(fg->g->idx); + fg->g->idx = 0; + fg->g->is_srt = 0; + asg_cleanup(fg->g); + asg_symm(fg->g); + asg_arc_del_trans(fg->g, gap_fuzz); + ///some of old edges might be lost due the transitive reduction + recall_arcs(fg->g, ug->g); + } + + kv_destroy(srt); free(idx); + return fg; +} + + +rd_hamming_fly_simp_t* gen_rd_hamming_fly_simp_t(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc* src, ma_sub_t *cov, int32_t max_hang, int32_t min_ovlp, int32_t gap_fuzz, kvec_asg_arc_t_warp *ae) +{ + rd_hamming_fly_simp_t *p; CALLOC(p, 1); + // p->ng = asg_init(); + // p->ng->n_seq = p->ng->m_seq = ug->g->n_seq; + // MALLOC(p->ng->seq, p->ng->n_seq); + // memcpy(p->ng->seq, ug->g->seq, (sizeof((*(p->ng->seq)))*p->ng->n_seq)); + p->src = src; p->cov = cov; p->max_hang = max_hang; p->min_ovlp = min_ovlp; p->gap_fuzz = gap_fuzz; + p->fg = gen_fg(ug, rg, src, cov, max_hang, min_ovlp, gap_fuzz); p->n_insert = 0; + CALLOC(p->vs, (ug->g->n_seq<<1)); CALLOC(p->srt, 1); p->ae = ae; + // p->fg = gen_fg(); + // p->rg = rg; MALLOC(p->rs, rg->n_seq<<1); + // memset(p->rs, -1, sizeof((*(p->rs)))*(rg->n_seq<<1)); + return p; +} + +void destroy_rd_hamming_fly_simp_t(rd_hamming_fly_simp_t *p) +{ + ///asg_destroy(p->ng); ///free(p->rs); + ma_ug_destroy(p->fg); + free(p->vs); + free(p->srt->a); + free(p->srt); +} + +static void dbg_asys_gfa0(void *data, long i, int tid) // callback for kt_for() +{ + asg_t *g = (asg_t *)data; asg_arc_t *s = &(g->arc[i]), *ra; + if(s->del) return; + uint64_t rn, ri, v, w; + ra = asg_arc_a(g, (s->v^1)); rn = asg_arc_n(g, (s->v^1)); + for (ri = 0; ri < rn; ri++) { + if(ra[ri].del) continue; + if(ra[ri].v == ((s->ul>>32)^1)) break; + } + if(ri >= rn) { + v = s->ul>>32; w = s->v; + fprintf(stderr, "[M::%s] v::utg%.6lul(%c)\tw::utg%.6lul(%c)\n", __func__, (v>>1) + 1, "+-"[(v&1)], (w>>1) + 1, "+-"[(w&1)]); + exit(1); + } +} + +static void dbg_asys_gfa1(void *data, long i, int tid) // callback for kt_for() +{ + asg_t *g = (asg_t *)data; asg_arc_t *av, *ra; + uint64_t rn, ri, v, w, an, k; + v = i<<1; av = asg_arc_a(g, v); an = asg_arc_n(g, v); + for (k = 0; k < an; k++) { + if(av[k].del) continue; + ra = asg_arc_a(g, (av[k].v^1)); rn = asg_arc_n(g, (av[k].v^1)); + for (ri = 0; ri < rn; ri++) { + if(ra[ri].del) continue; + if(ra[ri].v == ((av[k].ul>>32)^1)) break; + } + if(ri >= rn) { + w = av[k].v; + fprintf(stderr, "[M::%s] v::utg%.6lul(%c)\tw::utg%.6lul(%c)\n", __func__, (v>>1) + 1, "+-"[(v&1)], (w>>1) + 1, "+-"[(w&1)]); + exit(1); + } + + } + + v = (i<<1) + 1; av = asg_arc_a(g, v); an = asg_arc_n(g, v); + for (k = 0; k < an; k++) { + if(av[k].del) continue; + ra = asg_arc_a(g, (av[k].v^1)); rn = asg_arc_n(g, (av[k].v^1)); + for (ri = 0; ri < rn; ri++) { + if(ra[ri].del) continue; + if(ra[ri].v == ((av[k].ul>>32)^1)) break; + } + if(ri >= rn) { + w = av[k].v; + fprintf(stderr, "[M::%s] v::utg%.6lul(%c)\tw::utg%.6lul(%c)\n", __func__, (v>>1) + 1, "+-"[(v&1)], (w>>1) + 1, "+-"[(w&1)]); + exit(1); + } + } +} + +void dbg_asys_gfa(asg_t *g) +{ + kt_for(asm_opt.thread_num, dbg_asys_gfa0, g, g->n_arc); + kt_for(asm_opt.thread_num, dbg_asys_gfa1, g, g->n_seq); +} + +void clean_trio_untig_graph(ma_ug_t *ug, asg_t *read_g, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, +R_to_U* ruIndex, buf_t* b_0, uint8_t* visit, float density, uint32_t miniHapLen, +uint32_t miniBiGraph, float chimeric_rate, int is_final_clean, int just_bubble_pop, +float drop_ratio, uint32_t trio_flag, float trio_drop_rate, int max_hang, int min_ovlp, +int gap_fuzz, hap_cov_t *cov, kvec_asg_arc_t_warp *ae) +{ + asg_t *g = ug->g; rd_hamming_fly_simp_t *p = NULL; + uint32_t is_first = 1; + // if(trio_flag == MOTHER) { + // print_debug_gfa(read_g, ug, coverage_cut, "debug_dups", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len, 0, 1, 0); + // exit(1); + // } + redo: + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-0:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-0:", 0); + ///debug + // if(!p) p = gen_rd_hamming_fly_simp_t(ug, read_g, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz); + // fprintf(stderr, "[M::%s] 0\n", __func__); dbg_asys_gfa(g); + asg_pop_bubble_primary_trio(ug, NULL, trio_flag, DROP, cov, NULL, 1, p); + ///do not need to refine bubbles during the first round of cleaning + if(!p) p = gen_rd_hamming_fly_simp_t(ug, read_g, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz, ae); + + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-1:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-1:", 0); + // fprintf(stderr, "[M::%s] 1\n", __func__); dbg_asys_gfa(g); + magic_trio_phasing(g, ug, read_g, coverage_cut, sources, reverse_sources, 2, ruIndex, trio_flag, trio_drop_rate); + // fprintf(stderr, "[M::%s] 2\n", __func__); dbg_asys_gfa(g); + + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-2:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-2:", 0); + /**********debug**********/ + if(just_bubble_pop == 0) + { + cut_trio_tip_primary(g, ug, tipsLen, trio_flag, 0, read_g, reverse_sources, ruIndex, cov->is_r_het, 2); + } + // fprintf(stderr, "[M::%s] 3\n", __func__); dbg_asys_gfa(g); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-3:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-3:", 0); + /**********debug**********/ + long long pre_cons = get_graph_statistic(g); + long long cur_cons = 0; + while(pre_cons != cur_cons) + { + // fprintf(stderr, "[M::%s] 4\n", __func__); dbg_asys_gfa(g); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-4:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-4:", 0); + pre_cons = get_graph_statistic(g); + // fprintf(stderr, "[M::%s] 5\n", __func__); dbg_asys_gfa(g); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-5:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-5:", 0); + ///need consider tangles + asg_pop_bubble_primary_trio(ug, NULL, trio_flag, DROP, cov, NULL, 1, p); + // fprintf(stderr, "[M::%s] 6\n", __func__); dbg_asys_gfa(g); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-6:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-6:", 0); + /**********debug**********/ + if(just_bubble_pop == 0) + { + ///need consider tangles + asg_arc_cut_trio_long_tip_primary(g, ug, read_g, reverse_sources, ruIndex, 2, tip_drop_ratio, trio_flag, cov, NULL); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-7:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-7:", 0); + // fprintf(stderr, "[M::%s] 7\n", __func__); dbg_asys_gfa(g); + // if(trio_flag == MOTHER) print_debug_gfa(read_g, ug, coverage_cut, "debug_dups", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); + asg_arc_cut_trio_long_equal_tips_assembly(g, ug, read_g, reverse_sources, 2, ruIndex, trio_flag, cov, NULL); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-8:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-8:", 0); + // fprintf(stderr, "[M::%s] 8\n", __func__); dbg_asys_gfa(g); + asg_arc_cut_trio_long_tip_primary_complex(g, ug, read_g, reverse_sources, ruIndex, 2, tip_drop_ratio, stops_threshold, cov, NULL, trio_flag); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-9:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-9:", 0); + // fprintf(stderr, "[M::%s] 9\n", __func__); dbg_asys_gfa(g); + asg_arc_cut_trio_long_equal_tips_assembly_complex(g, ug, read_g, reverse_sources, 2, ruIndex, stops_threshold, cov, NULL, trio_flag); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-10:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-10:", 0); + // fprintf(stderr, "[M::%s] 10\n", __func__); dbg_asys_gfa(g); + detect_chimeric_by_topo(g, ug, read_g, reverse_sources, 2, stops_threshold, chimeric_rate, ruIndex, NULL, cov->is_r_het); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-11:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-11:", 0); + // fprintf(stderr, "[M::%s] 11\n", __func__); dbg_asys_gfa(g); + ///need consider tangles + ///note we need both the read graph and the untig graph + } + /**********debug**********/ + cur_cons = get_graph_statistic(g); + // fprintf(stderr, "[M::%s] 12\n", __func__); dbg_asys_gfa(g); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-12:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-12:", 0); + } + if(just_bubble_pop == 0) + { + // fprintf(stderr, "[M::%s] 13\n", __func__); dbg_asys_gfa(g); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-13:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-13:", 0); + cut_trio_tip_primary(g, ug, tipsLen, trio_flag, 0, read_g, reverse_sources, ruIndex, cov->is_r_het, 2); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-14:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-14:", 0); + // fprintf(stderr, "[M::%s] 14\n", __func__); dbg_asys_gfa(g); + } + + // print_debug_gfa(read_g, ug, coverage_cut, "debug_dups", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); + // fprintf(stderr, "[M::%s] 15\n", __func__); dbg_asys_gfa(g); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-15:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-15:", 0); + magic_trio_phasing(g, ug, read_g, coverage_cut, sources, reverse_sources, 2, ruIndex, trio_flag, trio_drop_rate); + // fprintf(stderr, "[M::%s] 16\n", __func__); dbg_asys_gfa(g); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-16:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-16:", 0); + + // print_debug_gfa(read_g, ug, coverage_cut, "resolve_tangles", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len, 0, 0, 0); + // exit(1); + ///bug here + resolve_tangles(ug, read_g, reverse_sources, 20, 100, 0.05, 0.2, ruIndex, cov->is_r_het, trio_flag, drop_ratio); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-17:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-17:", 0); + // fprintf(stderr, "[M::%s] 17\n", __func__); dbg_asys_gfa(g); + drop_semi_circle(ug, g, read_g, reverse_sources, ruIndex, cov->is_r_het); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-18:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-18:", 0); + // fprintf(stderr, "[M::%s] 18\n", __func__); dbg_asys_gfa(g); + all_to_all_deduplicate(ug, read_g, coverage_cut, sources, trio_flag, trio_drop_rate, reverse_sources, ruIndex, cov->is_r_het, DOUBLE_CHECK_THRES, asm_opt.trio_flag_occ_thres); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-19:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-19:", 0); + // fprintf(stderr, "[M::%s] 19\n", __func__); dbg_asys_gfa(g); + // if(trio_flag == MOTHER) print_untig_by_read(ug, "m54329U_190827_173812/30214441/ccs", (uint32_t)-1, NULL, NULL, "bf-16"); + if(is_first) + { + is_first = 0; + unitig_arc_del_short_diploid_by_length(ug->g, drop_ratio); + // if(trio_flag == MOTHER) print_untig((ug), 9, "i-20:", 0); + // if(trio_flag == MOTHER) print_untig((ug), 10, "i-20:", 0); + // fprintf(stderr, "[M::%s] 20\n", __func__); dbg_asys_gfa(g); + goto redo; + } + if(p) { + fprintf(stderr, "[M::%s] # adjusted arcs::%u\n", __func__, p->n_insert); + destroy_rd_hamming_fly_simp_t(p); free(p); + } +} + +void print_graph_statistic(asg_t *g, const char* cmd) +{ + uint64_t n_arc = 0, n_node = 0, size = 0; + uint32_t n_vtx = g->n_seq, v; + + for (v = 0; v < n_vtx; ++v) + { + if (g->seq[v].del || g->seq[v].c == ALTER_LABLE) continue; + n_arc += get_real_length(g, v<<1, NULL) + get_real_length(g, (v<<1)+1, NULL); + n_node++; + size += g->seq[v].len; + } + + fprintf(stderr, "%s->n_node: %lu, n_arc: %lu, size: %lu\n", cmd, n_node, n_arc, size); +} + + + +void clean_primary_untig_graph(ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* sources, +ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, long long tipsLen, float tip_drop_ratio, +long long stops_threshold, R_to_U* ruIndex, buf_t* b_0, uint8_t* visit, float density, +uint32_t miniHapLen, uint32_t miniBiGraph, float chimeric_rate, int is_final_clean, +int just_bubble_pop, float drop_ratio, hap_cov_t *cov) +{ + #define T_ROUND 2 + asg_t *g = ug->g; + int round = T_ROUND; + + redo: + ///print_graph_statistic(g, "beg"); + ///print_debug_gfa(read_g, ug, coverage_cut, "debug_trans_ovlp_hg002", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); + asg_pop_bubble_primary_trio(ug, NULL, (uint32_t)-1, DROP, cov, NULL, 1, NULL); + if(just_bubble_pop == 0) + { + cut_trio_tip_primary(g, ug, tipsLen, (uint32_t)-1, 0, read_g, reverse_sources, ruIndex, cov->is_r_het, 2); + } + // print_debug_gfa(read_g, ug, coverage_cut, "debug_init", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); + long long pre_cons = get_graph_statistic(g); + long long cur_cons = 0; + while(pre_cons != cur_cons) + { + pre_cons = get_graph_statistic(g); + asg_pop_bubble_primary_trio(ug, NULL, (uint32_t)-1, DROP, cov, NULL, 1, NULL); + if(just_bubble_pop == 0) + { + ///need consider tangles + asg_arc_cut_trio_long_tip_primary(g, ug, read_g, reverse_sources, ruIndex, 2, tip_drop_ratio, (uint32_t)-1, cov, NULL); + asg_arc_cut_trio_long_equal_tips_assembly(g, ug, read_g, reverse_sources, 2, ruIndex, (uint32_t)-1, cov, NULL); + asg_arc_cut_trio_long_tip_primary_complex(g, ug, read_g, reverse_sources, ruIndex, 2, tip_drop_ratio, stops_threshold, cov, NULL, (uint32_t)-1); + asg_arc_cut_trio_long_equal_tips_assembly_complex(g, ug, read_g, reverse_sources, 2, ruIndex, stops_threshold, cov, NULL, (uint32_t)-1); + detect_chimeric_by_topo(g, ug, read_g, reverse_sources, 2, stops_threshold, chimeric_rate, ruIndex, NULL, cov->is_r_het); + if(round != T_ROUND) + { + unitig_arc_del_short_diploid_by_length_topo(g, ug, drop_ratio, asm_opt.max_short_tip, + reverse_sources, 0, 1); + } + } + cur_cons = get_graph_statistic(g); + } + if(just_bubble_pop == 0) + { + cut_trio_tip_primary(g, ug, tipsLen, (uint32_t)-1, 0, read_g, reverse_sources, ruIndex, cov->is_r_het, 2); + } + resolve_tangles(ug, read_g, reverse_sources, 20, 100, 0.05, 0.2, ruIndex, cov->is_r_het, (uint32_t)-1, drop_ratio); + drop_semi_circle(ug, g, read_g, reverse_sources, ruIndex, cov->is_r_het); + // print_debug_gfa(read_g, ug, coverage_cut, "debug_clean_end", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); + unitig_arc_del_short_diploid_by_length_topo(g, ug, drop_ratio, asm_opt.max_short_tip, reverse_sources, 0, 1); + ///print_graph_statistic(g, "end"); + if(round > 0) + { + if(round != T_ROUND) + { + unitig_arc_del_short_diploid_by_length(ug->g, drop_ratio); + } + round--; + goto redo; + } +} + + + +utg_trans_t *topo_ovlp_collect(ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* sources, +ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, long long tipsLen, float tip_drop_ratio, +long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, +int min_ovlp, hap_cov_t *cov) +{ + utg_trans_t *o = init_utg_trans_t(ug, reverse_sources, coverage_cut, ruIndex, read_g, max_hang, min_ovlp); + #define T_ROUND 2 + asg_t *g = ug->g; + int round = T_ROUND; + + // print_debug_gfa(read_g, ug, coverage_cut, "debug_init", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); + + redo: + asg_pop_bubble_primary_trio(ug, NULL, (uint32_t)-1, DROP, cov, o, 1, NULL); + cut_trio_tip_primary(g, ug, tipsLen, (uint32_t)-1, 0, read_g, reverse_sources, ruIndex, cov->is_r_het, 2); + + long long pre_cons = get_graph_statistic(g); + long long cur_cons = 0; + while(pre_cons != cur_cons) + { + while(pre_cons != cur_cons) + { + while(pre_cons != cur_cons) + { + pre_cons = get_graph_statistic(g); + asg_pop_bubble_primary_trio(ug, NULL, (uint32_t)-1, DROP, cov, o, 1, NULL); + + ///need consider tangles + asg_arc_cut_trio_long_tip_primary(g, ug, read_g, reverse_sources, ruIndex, 2, tip_drop_ratio, (uint32_t)-1, cov, o); + asg_arc_cut_trio_long_equal_tips_assembly(g, ug, read_g, reverse_sources, 2, ruIndex, (uint32_t)-1, cov, o); + asg_arc_cut_trio_long_tip_primary_complex(g, ug, read_g, reverse_sources, ruIndex, 2, tip_drop_ratio, stops_threshold, cov, o, (uint32_t)-1); + asg_arc_cut_trio_long_equal_tips_assembly_complex(g, ug, read_g, reverse_sources, 2, ruIndex, stops_threshold, cov, o, (uint32_t)-1); + detect_chimeric_by_topo(g, ug, read_g, reverse_sources, 2, stops_threshold, chimeric_rate, ruIndex, o, cov->is_r_het); + + cur_cons = get_graph_statistic(g); + } + + // if(asm_opt.polyploidy > 2) asg_arc_decompress(g, ug, read_g, reverse_sources, ruIndex, o); + if(asm_opt.polyploidy > 2) + { + asg_arc_decompress_mul(g, ug, read_g, (uint32_t)-1, DROP, reverse_sources, ruIndex, o); + } + + cur_cons = get_graph_statistic(g); + } + if(round != T_ROUND) + { + unitig_arc_del_short_diploid_by_length_topo(g, ug, drop_ratio, asm_opt.max_short_tip, + reverse_sources, 0, 1); + } + cur_cons = get_graph_statistic(g); + } + + + cut_trio_tip_primary(g, ug, tipsLen, (uint32_t)-1, 0, read_g, reverse_sources, ruIndex, cov->is_r_het, 2); + + resolve_tangles(ug, read_g, reverse_sources, 20, 100, 0.05, 0.2, ruIndex, cov->is_r_het, (uint32_t)-1, drop_ratio); + drop_semi_circle(ug, g, read_g, reverse_sources, ruIndex, cov->is_r_het); + // print_debug_gfa(read_g, ug, coverage_cut, "debug_clean_end", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); + unitig_arc_del_short_diploid_by_length_topo(g, ug, drop_ratio, asm_opt.max_short_tip, reverse_sources, 0, 1); + + if(round > 0) + { + if(round != T_ROUND) + { + unitig_arc_del_short_diploid_by_length(ug->g, drop_ratio); + } + round--; + goto redo; + } + return o; +} + +void set_drop_trio_flag(ma_ug_t *ug) +{ + ma_utg_t* u = NULL; + asg_t* nsg = ug->g; + uint32_t k, rId; + uint32_t v, n_vtx = nsg->n_seq; + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + if(nsg->seq[v].c == ALTER_LABLE) continue; + u = &(ug->u.a[v]); + if(u->m == 0) continue; + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + if(R_INF.trio_flag[rId] != AMBIGU) continue; + R_INF.trio_flag[rId] = DROP; + } + } +} + +void update_unitig_graph(ma_ug_t* ug, asg_t* read_g, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, uint8_t* is_r_het, +uint8_t is_final_check, float double_check_rate, uint8_t flag, float drop_rate) +{ + asg_t* nsg = ug->g; + uint32_t v, n_vtx = nsg->n_seq, k, rId, flag_occ, non_flag_occ, hap_label_occ, n_reduce = 1; + ma_utg_t *u; + uint8_t* primary_flag = (uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)); + + drop_semi_circle(ug, nsg, read_g, reverse_sources, ruIndex, is_r_het); + + while (n_reduce) + { + n_reduce = 0; + n_vtx = nsg->n_seq; + for (v = 0; v < n_vtx; ++v) + { + if (nsg->seq[v].del) continue; + u = &((ug)->u.a[v]); + if(u->m == 0) continue; + if((get_real_length(nsg, v<<1, NULL)!=0) + && (get_real_length(nsg, ((v<<1)^1), NULL)!=0)) continue;///check tig + flag_occ = non_flag_occ = hap_label_occ = 0; + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + if(read_g->seq[rId].c == HAP_LABLE) hap_label_occ++; + if(R_INF.trio_flag[rId] == AMBIGU) continue; + if(R_INF.trio_flag[rId] == DROP) continue; + if(R_INF.trio_flag[rId] == flag) flag_occ++; + if(R_INF.trio_flag[rId] != flag) non_flag_occ++; + } + + ///if(is_final_check && v == 0) fprintf(stderr, "flag: %u, flag_occ: %u, non_flag_occ: %u\n", flag, flag_occ, non_flag_occ); + + if(is_final_check == 0 && hap_label_occ == u->n) continue; + ///if(is_double_check && non_flag_occ < u->n*DOUBLE_CHECK_THRES) continue; + ///if(is_double_check && non_flag_occ < u->n*double_check_rate) continue; + + if(is_final_check) + { + /**if(non_flag_occ < u->n*double_check_rate) continues**/; + } + else + { + if(u->n >= 100) + { + if(non_flag_occ < u->n*double_check_rate) + { + continue; + } + } + else if(u->n >= 50) + { + if(non_flag_occ < u->n*double_check_rate*0.5) + { + continue; + } + } + else + { + if(non_flag_occ < u->n*double_check_rate*0.25) + { + continue; + } + } + } + + if(non_flag_occ > ((non_flag_occ+flag_occ)*drop_rate)) + { + + if(if_primary_unitig(u, read_g, coverage_cut, sources, ruIndex, primary_flag)) + { + continue; + } + + if(u->m != 0) + { + u->circ = u->end = u->len = u->m = u->n = u->start = 0; + free(u->a); + u->a = NULL; + } + asg_seq_del(nsg, v); + n_reduce++; + } + } + } + + drop_semi_circle(ug, nsg, read_g, reverse_sources, ruIndex, is_r_het); + asg_cleanup(nsg); + free(primary_flag); +} + + +void force_trio_clean(ma_ug_t* ug, asg_t* read_g, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, +uint8_t flag, float self_drop_rate, float contig_drop_rate, uint32_t min_occ) +{ + asg_t* nsg = ug->g; + uint32_t beg, end, n_vtx = nsg->n_seq<<1, k, i, rId, tf_occ, tnf_occ, flag_occ, non_flag_occ, n_reduce = 1; + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + buf_t b; memset(&b, 0, sizeof(buf_t)); + ma_utg_t *u = NULL; + uint8_t* primary_flag = (uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)); + + while (n_reduce) + { + n_reduce = 0; + n_vtx = nsg->n_seq; + for (beg = 0; beg < n_vtx; ++beg) + { + if(nsg->seq[beg>>1].del || asg_arc_n(nsg, beg) <= 0 || get_real_length(nsg, beg, NULL)<=0) + { + continue; + } + if(get_real_length(nsg, beg^1, NULL) == 1)///check if beg is the tig end + { + get_real_length(nsg, beg^1, &end); + if(get_real_length(nsg, end^1, NULL) == 1) continue; + } + b.b.n = 0; tf_occ = tnf_occ = 0; + get_unitig(nsg, ug, beg, &end, &nodeLen, &baseLen, &max_stop_nodeLen, &max_stop_baseLen, 1, &b); + + for (i = 0; i < b.b.n; i++) + { + u = &((ug)->u.a[b.b.a[i]>>1]); + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + if(R_INF.trio_flag[rId] == AMBIGU) continue; + if(R_INF.trio_flag[rId] == DROP) continue; + if(R_INF.trio_flag[rId] == flag) tf_occ++; + if(R_INF.trio_flag[rId] != flag) tnf_occ++; + } + } + if(tnf_occ <= ((tnf_occ+tf_occ)*contig_drop_rate)) continue; + + for (i = 0; i < b.b.n; i++) + { + flag_occ = non_flag_occ = 0; + u = &((ug)->u.a[b.b.a[i]>>1]); + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + if(R_INF.trio_flag[rId] == AMBIGU) continue; + if(R_INF.trio_flag[rId] == DROP) continue; + if(R_INF.trio_flag[rId] == flag) flag_occ++; + if(R_INF.trio_flag[rId] != flag) non_flag_occ++; + } + + if(non_flag_occ <= min_occ) continue; + if(non_flag_occ <= ((non_flag_occ+flag_occ)*self_drop_rate)) continue; + if(non_flag_occ <= ((tf_occ+tnf_occ)*contig_drop_rate)) continue; + if(if_primary_unitig(u, read_g, coverage_cut, sources, ruIndex, primary_flag)) + { + continue; + } + + if(u->m != 0) + { + u->circ = u->end = u->len = u->m = u->n = u->start = 0; + free(u->a); + u->a = NULL; + } + asg_seq_del(nsg, b.b.a[i]>>1); + n_reduce++; + } + + } + } + + free(b.b.a); + asg_cleanup(nsg); + free(primary_flag); +} + +void get_candidate_uids(asg_t* nsg, ma_utg_t* nsu, kvec_t_u64_warp* u_vecs, +ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex) +{ + uint32_t k, j, rId, uId, is_Unitig, m; + uint64_t pre; + u_vecs->a.n = 0; + if(nsu->m == 0) return; + for (k = 0; k < nsu->n; k++) + { + rId = nsu->a[k]>>33; + for (j = 0; j < reverse_sources[rId].length; j++) + { + get_R_to_U(ruIndex, Get_tn(reverse_sources[rId].buffer[j]), &uId, &is_Unitig); + if(uId==(uint32_t)-1) continue; + ///contained read + if(is_Unitig == 0) get_R_to_U(ruIndex, uId, &uId, &is_Unitig); + if(uId == (uint32_t)-1 || is_Unitig == 0) continue; + ///need this line + if(nsg->seq[uId].c == ALTER_LABLE) continue; + pre = uId; + pre = pre | (uint64_t)(0x100000000); + kv_push(uint64_t, u_vecs->a, pre); + } + } + if(u_vecs->a.n == 0) return; + radix_sort_arch64(u_vecs->a.a, u_vecs->a.a + u_vecs->a.n); + for (m = 0, k = 1; k < u_vecs->a.n; k++) + { + if(u_vecs->a.a[k] == u_vecs->a.a[k-1]) + { + u_vecs->a.a[m] += (uint64_t)(0x100000000); + } + else + { + m++; + u_vecs->a.a[m] = u_vecs->a.a[k]; + } + } + + u_vecs->a.n = m + 1; +} + +uint32_t unitig_simi(uint32_t x, uint32_t y, ma_ug_t* ug, ma_hit_t_alloc* reverse_sources, +R_to_U* ruIndex, uint8_t* is_r_het) +{ + uint32_t k, j, uId, tn, is_Unitig, rId, ref_unitig, min_count, max_count, n_het, n_hom; + ma_utg_t *nsu_x = NULL, *nsu_y = NULL, *nsu_query = NULL; + nsu_x = &(ug->u.a[x]); + nsu_y = &(ug->u.a[y]); + + if(nsu_x->n == 0 || nsu_y->n == 0) return UNAVAILABLE; + + if(nsu_x->n <= nsu_y->n) + { + nsu_query = nsu_x; + ref_unitig = y; + } + else + { + nsu_query = nsu_y; + ref_unitig = x; + } + + min_count = max_count = n_het = n_hom = 0; + for (k = 0; k < nsu_query->n; k++) + { + rId = nsu_query->a[k]>>33; + if(reverse_sources[rId].length >= 0) min_count++; + if((is_r_het[rId] & C_HET) || (is_r_het[rId] & P_HET)) n_het++; + n_hom++; + + for (j = 0; j < reverse_sources[rId].length; j++) + { + tn = Get_tn(reverse_sources[rId].buffer[j]); + get_R_to_U(ruIndex, tn, &uId, &is_Unitig); + if(uId==(uint32_t)-1) continue; + ///contained read + if(is_Unitig == 0) get_R_to_U(ruIndex, uId, &uId, &is_Unitig); + if(uId == (uint32_t)-1 || is_Unitig == 0) continue; + if(uId == ref_unitig) + { + max_count++; + break; + } + } + } + + if(min_count == 0) return UNAVAILABLE; + if(max_count > min_count*asm_opt.purge_simi_thres && n_het >= n_hom*HET_HOM_RATE) return PLOID; + return NON_PLOID; +} + +void get_unitig_trio_flag(ma_utg_t* nsu, uint32_t flag, uint32_t* require, +uint32_t* non_require, uint32_t* ambigious) +{ + uint32_t k, rId; + (*require) = (*non_require) = (*ambigious) = 0; + for (k = 0; k < nsu->n; k++) + { + rId = nsu->a[k]>>33; + if(R_INF.trio_flag[rId] == AMBIGU || R_INF.trio_flag[rId] == DROP) + { + (*ambigious)++; + continue; + } + if(R_INF.trio_flag[rId] == flag) + { + (*require)++; + continue; + } + if(R_INF.trio_flag[rId] != flag) + { + (*non_require)++; + continue; + } + } +} + + +///note: to use this function, don't renew unitig graph!!!!!!!!! +void all_to_all_deduplicate(ma_ug_t* ug, asg_t* read_g, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, uint8_t postive_flag, float drop_rate, +ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, uint8_t* is_r_het, float double_check_rate, int non_tig_occ) +{ + + + kvec_t_u64_warp u_vecs; + kv_init(u_vecs.a); + uint32_t n_vtx, v, k, is_Unitig, is_tig, uId, rId, convex, flag_occ, non_flag_occ, ambigious, /**is_ambigious,**/ flag, n_reduce = 1; + asg_t* nsg = NULL; + ma_utg_t* nsu = NULL; + nsg = ug->g; + if(postive_flag == FATHER) flag = MOTHER; + if(postive_flag == MOTHER) flag = FATHER; + uint8_t* primary_flag = (uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)); + + for (v = 0; v < nsg->n_seq; v++) + { + uId = v; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsg->seq[v].del) continue; + if(nsg->seq[v].c==ALTER_LABLE) continue; + + for (k = 0; k < nsu->n; k++) + { + rId = nsu->a[k]>>33; + set_R_to_U(ruIndex, rId, uId, 1, &(read_g->seq[rId].c)); + } + } + + n_reduce = 1; + while (n_reduce) + { + n_reduce = 0; + n_vtx = nsg->n_seq*2; + for (v = 0; v < n_vtx; ++v) + { + + uId = v>>1; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsg->seq[uId].del) continue; + if(nsg->seq[uId].c == ALTER_LABLE) continue; + is_tig = 1; + + if(get_real_length(nsg, v^1, NULL) == 1) + { + get_real_length(nsg, v^1, &convex); + if(get_real_length(nsg, convex^1, NULL) == 1) + { + is_tig = 0; + ///continue; + } + } + + get_unitig_trio_flag(nsu, flag, &flag_occ, &non_flag_occ, &ambigious); + /** + is_ambigious = 0; + if((flag_occ+non_flag_occ)==0 && ambigious > 0) + { + is_ambigious = 1; + } + else**/ + { + ///we may need it or not + if(is_tig == 0 && (int)flag_occ <= non_tig_occ) continue; + if(flag_occ <= ((non_flag_occ+flag_occ)*drop_rate)) continue; + if((flag_occ+non_flag_occ) == 0) continue; + if(nsu->n >= 100) + { + if(flag_occ < nsu->n*double_check_rate) + { + continue; + } + } + else if(nsu->n >= 50) + { + if(flag_occ < nsu->n*double_check_rate*0.5) + { + continue; + } + } + else + { + if(flag_occ < nsu->n*double_check_rate*0.25) + { + continue; + } + } + } + + + get_candidate_uids(nsg, nsu, &u_vecs, reverse_sources, ruIndex); + + + if(u_vecs.a.n == 0) continue; + + for (k = 0; k < u_vecs.a.n; k++) + { + /** + if(is_ambigious) + { + get_unitig_trio_flag(&(ug->u.a[(uint32_t)(u_vecs.a.a[k])]), postive_flag, + &flag_occ, &non_flag_occ, &ambigious); + if(flag_occ <= ((non_flag_occ+flag_occ)*drop_rate)) continue; + if((flag_occ+non_flag_occ) == 0) continue; + }**/ + if(unitig_simi(uId, (uint32_t)(u_vecs.a.a[k]), ug, reverse_sources, ruIndex, is_r_het)==PLOID) + { + break; + } + } + + if(k != u_vecs.a.n) + { + if(if_primary_unitig(nsu, read_g, coverage_cut, sources, ruIndex, primary_flag)) + { + continue; + } + if(nsu->m != 0) + { + nsu->circ = nsu->end = nsu->len = nsu->m = nsu->n = nsu->start = 0; + free(nsu->a); + nsu->a = NULL; + } + asg_seq_del(nsg, uId); + n_reduce++; + } + } + } + + for (v = 0; v < ruIndex->len; v++) + { + get_R_to_U(ruIndex, v, &uId, &is_Unitig); + if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; + } + + kv_destroy(u_vecs.a); + free(primary_flag); +} + +void delete_useless_nodes(ma_ug_t **ug) +{ + asg_t* nsg = (*ug)->g; + uint32_t v, n_vtx = nsg->n_seq; + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + if(nsg->seq[v].c == ALTER_LABLE) + { + asg_seq_del(nsg, v); + if((*ug)->u.a[v].m!=0) + { + (*ug)->u.a[v].m = (*ug)->u.a[v].n = 0; + free((*ug)->u.a[v].a); + (*ug)->u.a[v].a = NULL; + } + + continue; + } + + //note: after cleaning, some cirle might be gone, or we have some new circles + //so need to renew .circ + /** + if(get_unitig(nsg, NULL, (v<<1), &convex, &nodeLen, &baseLen, + &max_stop_nodeLen, &max_stop_baseLen, 1, NULL)==LOOP) + { + (*ug)->u.a[v].circ = 1; + (*ug)->u.a[v].start = (*ug)->u.a[v].end = UINT32_MAX; + } + else + { + (*ug)->u.a[v].circ = 0; + + (*ug)->u.a[v].start = (*ug)->u.a[v].a[0]>>32; + (*ug)->u.a[v].end = ((*ug)->u.a[v].a[(*ug)->u.a[v].n-1]>>32)^1; + } + **/ + } + + asg_cleanup(nsg); +} + +inline uint32_t is_useful_node(uint32_t flag_occ, uint32_t non_flag_occ, uint32_t drop_occ, uint32_t tot_occ, +float flag_rate, float used_rate, uint32_t min_occ) +{ + if((flag_occ > 0) && (flag_occ >= min_occ) && (flag_occ >= ((non_flag_occ+flag_occ+drop_occ)*flag_rate)) + && (drop_occ <= (tot_occ*used_rate))) { + return 1; + } + return 0; +} + + +void recover_chain_nodes(buf_t *in, ma_ug_t *ug, uint32_t flag, float flag_rate, float used_rate, uint32_t min_occ) +{ + ma_utg_t *u = NULL; uint32_t flag_occ, non_flag_occ, drop_occ, rid; + uint32_t tot_flag_occ, tot_non_flag_occ, tot_drop_occ, tot_occ, i, k, z; + tot_flag_occ = tot_non_flag_occ = tot_drop_occ = tot_occ = 0; + + for (i = 0; i < in->b.n; i++) { + u = &(ug->u.a[in->b.a[i]>>1]); + flag_occ = non_flag_occ = drop_occ = 0; + for (k = 0; k < u->n; k++) { + rid = u->a[k]>>33; + if(R_INF.trio_flag[rid] == AMBIGU) continue; + else if(R_INF.trio_flag[rid] == DROP) drop_occ++; + else if(R_INF.trio_flag[rid] == flag) flag_occ++; + else if(R_INF.trio_flag[rid] != flag) non_flag_occ++; + } + + if(is_useful_node(flag_occ, non_flag_occ, drop_occ, u->n, flag_rate, used_rate, min_occ)) { + ug->g->seq[in->b.a[i]>>1].c = PRIMARY_LABLE; + } + tot_flag_occ += flag_occ; + tot_non_flag_occ += non_flag_occ; + tot_drop_occ += drop_occ; + tot_occ += u->n; + if(is_useful_node(tot_flag_occ, tot_non_flag_occ, tot_drop_occ, tot_occ, flag_rate, used_rate, min_occ)) { + for (z = 0; z <= i; z++) { + if(ug->g->seq[in->b.a[z]>>1].c == ALTER_LABLE) { + u = &(ug->u.a[in->b.a[z]>>1]); + flag_occ = non_flag_occ = drop_occ = 0; + for (k = 0; k < u->n; k++) { + rid = u->a[k]>>33; + if(R_INF.trio_flag[rid] == AMBIGU) continue; + else if(R_INF.trio_flag[rid] == DROP) drop_occ++; + else if(R_INF.trio_flag[rid] == flag) flag_occ++; + else if(R_INF.trio_flag[rid] != flag) non_flag_occ++; + } + if(is_useful_node(flag_occ, non_flag_occ, drop_occ, u->n, flag_rate, used_rate, 0/**min_occ**/)) { + ug->g->seq[in->b.a[z]>>1].c = PRIMARY_LABLE; + } + } + } + } + } +} + +void rescue_useless_trio_nodes(ma_ug_t *ug, uint32_t flag, float flag_rate, float used_rate, uint32_t min_occ) +{ + asg_t* nsg = ug->g; + uint32_t v, w, n_vtx = nsg->n_seq<<1, i, k, z; + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + buf_t b; memset(&b, 0, sizeof(buf_t)); + + for (v = 0; v < n_vtx; v++) { + if(nsg->seq[v>>1].del) continue; + if(nsg->seq[v>>1].c != ALTER_LABLE) continue; + ///check if beg is the tig end + if(get_real_length(nsg, v^1, NULL) == 1) { + get_real_length(nsg, v^1, &w); + if(get_real_length(nsg, w^1, NULL) == 1) continue; + } + + b.b.n = 0; + get_unitig(nsg, ug, v, &w, &nodeLen, &baseLen, &max_stop_nodeLen, &max_stop_baseLen, 1, &b); + recover_chain_nodes(&b, ug, flag, flag_rate, used_rate, min_occ); + if(b.b.n > 1) { + k = b.b.n>>1; + for (i = 0; i < k; i++) { + z = b.b.a[i]; b.b.a[i] = b.b.a[b.b.n-i-1]; b.b.a[b.b.n-i-1] = z; + } + recover_chain_nodes(&b, ug, flag, flag_rate, used_rate, min_occ); + } + } + + free(b.b.a); + asg_cleanup(nsg); +} + +void delete_useless_trio_nodes(ma_ug_t **ug, asg_t* read_g, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex, uint32_t flag, float flag_rate, float used_rate, uint32_t min_occ) +{ + asg_t* nsg = (*ug)->g; + uint32_t v, n_vtx = nsg->n_seq; + uint8_t* primary_flag = (uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)); + + if(flag_rate > 0 && used_rate > 0 && min_occ > 0) { + rescue_useless_trio_nodes(*ug, flag, flag_rate, used_rate, min_occ); + } + + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + if(nsg->seq[v].c == ALTER_LABLE && + (if_primary_unitig(&((*ug)->u.a[v]), read_g, coverage_cut, sources, + ruIndex, primary_flag) == 0)) + { + asg_seq_del(nsg, v); + if((*ug)->u.a[v].m!=0) + { + (*ug)->u.a[v].m = (*ug)->u.a[v].n = 0; + free((*ug)->u.a[v].a); + (*ug)->u.a[v].a = NULL; + } + + continue; + } + + //note: after cleaning, some cirle might be gone, or we have some new circles + //so need to renew .circ + /** + if(get_unitig(nsg, NULL, (v<<1), &convex, &nodeLen, &baseLen, + &max_stop_nodeLen, &max_stop_baseLen, 1, NULL)==LOOP) + { + (*ug)->u.a[v].circ = 1; + (*ug)->u.a[v].start = (*ug)->u.a[v].end = UINT32_MAX; + } + else + { + (*ug)->u.a[v].circ = 0; + + (*ug)->u.a[v].start = (*ug)->u.a[v].a[0]>>32; + (*ug)->u.a[v].end = ((*ug)->u.a[v].a[(*ug)->u.a[v].n-1]>>32)^1; + } + **/ + } + + asg_cleanup(nsg); + free(primary_flag); +} + + + + + +void drop_semi_circle(ma_ug_t *ug, asg_t* nsg, asg_t* read_g, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, uint8_t* is_r_het) +{ + uint32_t v, n_vtx = nsg->n_seq*2, convex_f, convex_b, i, nv; + long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; + asg_arc_t *av = NULL; + buf_t b_0, b_1; + memset(&b_0, 0, sizeof(buf_t)); + memset(&b_1, 0, sizeof(buf_t)); + + for (v = 0; v < n_vtx; ++v) + { + if(get_real_length(nsg, v, NULL) == 0) continue; + if(get_real_length(nsg, v^1, NULL) == 0) continue; + + if(get_unitig(nsg, ug, v^1, &convex_b, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, + 1, NULL)!=MUL_INPUT) + { + continue; + } + + get_real_length(nsg, convex_b, &convex_b); + + av = asg_arc_a(nsg, v); + nv = asg_arc_n(nsg, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + + if(get_unitig(nsg, ug, av[i].v, &convex_f, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, + 1, NULL)!=MUL_INPUT) + { + continue; + } + get_real_length(nsg, convex_f, &convex_f); + if(convex_f != convex_b) continue; + if(check_different_haps(nsg, ug, read_g, v^1, av[i].v, + reverse_sources, &b_0, &b_1, ruIndex, is_r_het, 2, 1) == PLOID) + { + av[i].del = 1; + asg_arc_del(nsg, av[i].v^1, v^1, 1); + } + } + + } + + free(b_0.b.a); + free(b_1.b.a); + +} + +void update_hap_label(ma_ug_t *ug, asg_t* read_g) +{ + uint32_t v, n_vtx, k; + uint64_t rId; + + if(ug == NULL) + { + n_vtx = read_g->n_seq; + for (v = 0; v < n_vtx; ++v) + { + if(read_g->seq[v].del) continue; + if(read_g->seq[v].c != HAP_LABLE) continue; + read_g->seq[v].c = PRIMARY_LABLE; + } + return; + } + + + asg_t* nsg = ug->g; + n_vtx = nsg->n_seq; + ma_utg_t* u = NULL; + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + if(nsg->seq[v].c != HAP_LABLE) continue; + u = &((ug)->u.a[v]); + if(u->m == 0) continue; + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + read_g->seq[rId].c = HAP_LABLE; + } + } +} + + +uint8_t* get_utg_attributes(ma_ug_t *ug, asg_t* read_g, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex) +{ + asg_t* nsg = ug->g; + uint32_t v, n_vtx = nsg->n_seq, k, j, rId, available_reads = 0, tn, is_Unitig; + ma_utg_t* u = NULL; + ma_hit_t *h; + long long R_bases = 0, C_bases = 0, C_bases_primary = 0, C_bases_alter = 0; + uint8_t* r_flag = (uint8_t*)calloc(read_g->n_seq, sizeof(uint8_t)); + uint8_t* u_flag = (uint8_t*)calloc(n_vtx, sizeof(uint8_t)); + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + u = &(ug->u.a[v]); + if(u->m == 0) continue; + available_reads = 0; + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 1; + } + + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + C_bases = C_bases_primary = C_bases_alter = 0; + R_bases = coverage_cut[rId].e - coverage_cut[rId].s; + for (j = 0; j < (uint64_t)(sources[rId].length); j++) + { + h = &(sources[rId].buffer[j]); + if(h->el != 1) continue; + tn = Get_tn((*h)); + if(read_g->seq[tn].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + if(read_g->seq[tn].del == 1) continue; + if(r_flag[tn]) + { + C_bases_primary += Get_qe((*h)) - Get_qs((*h)); + } + else + { + C_bases_alter += Get_qe((*h)) - Get_qs((*h)); + } + } + + C_bases = C_bases_primary + C_bases_alter; + if(C_bases_alter < C_bases * ALTER_COV_THRES) continue; + + C_bases = C_bases/R_bases; + if(C_bases >= asm_opt.recover_atg_cov_min && C_bases <= asm_opt.recover_atg_cov_max) + { + available_reads++; + } + } + + + if(available_reads < (u->n * 0.8) || available_reads == 0) + { + u_flag[v] = 0; + } + else + { + u_flag[v] = 1; + } + + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + r_flag[rId] = 0; + } + } + + free(r_flag); + return u_flag; +} + +void purge_dump(ma_ug_t* ug) +{ + asg_t* nsg = ug->g; + uint32_t v, n_vtx = nsg->n_seq, k, rId; + ma_utg_t *u = NULL; + for (v = 0; v < n_vtx; ++v) { + if (nsg->seq[v].del) continue; + u = &((ug)->u.a[v]); + if(u->m == 0) continue; + for (k = 0; k < u->n; k++){ + rId = u->a[k]>>33; + if(R_INF.trio_flag[rId] != AMBIGU && R_INF.trio_flag[rId] != DROP) break; + } + if(k >= u->n){ + if(u->m != 0){ + u->circ = u->end = u->len = u->m = u->n = u->start = 0; + free(u->a); + u->a = NULL; + } + asg_seq_del(nsg, v); + } + } + asg_cleanup(nsg); +} + +void discard_small_ctg(ma_ug_t **ug, asg_t* rg, kvec_asg_arc_t_warp* edge, int32_t max_rg_cut, uint32_t is_renew0, uint32_t is_renew1) +{ + if(is_renew0) renew_utg(ug, rg, edge); + uint32_t i, cnt = 0; ma_utg_t* u = NULL; + for (i = 0; i < (*ug)->u.n; i++) { + if(((int32_t)(*ug)->u.a[i].n) > max_rg_cut) continue; + u = &(((*ug))->u.a[i]); + asg_seq_del((*ug)->g, i); + if(u->m!=0) { + u->m = u->n = 0; free(u->a); u->a = NULL; u->len = u->circ = 0; u->start = u->end = 0; + } + cnt++; + } + + if(cnt && is_renew1) renew_utg(ug, rg, edge); +} + + +void adjust_utg_by_trio(ma_ug_t **ug, asg_t* read_g, uint8_t flag, float drop_rate, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, +R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, int gap_fuzz, +kvec_asg_arc_t_warp* new_rtg_edges, bub_label_t* b_mask_t) +{ + asg_t* nsg = (*ug)->g; + uint32_t v, n_vtx = nsg->n_seq; + hap_cov_t *cov = init_hap_cov_t(*ug, read_g, sources, ruIndex, reverse_sources, + coverage_cut, max_hang, min_ovlp, asm_opt.purge_level_trio>0?1:0); + if(cov->t_ch) cov->t_ch->ir_het = cov->is_r_het; + + if(asm_opt.recover_atg_cov_min == -1024) + { + asm_opt.recover_atg_cov_max = (asm_opt.hom_global_coverage_set? + (asm_opt.hom_global_coverage):(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); + asm_opt.recover_atg_cov_min = asm_opt.recover_atg_cov_max * 0.85; + asm_opt.recover_atg_cov_max = INT32_MAX; + } + if(asm_opt.recover_atg_cov_max != INT32_MAX) + { + fprintf(stderr, "[M::%s] primary contig coverage range: [%d, %d]\n", + __func__, asm_opt.recover_atg_cov_min, asm_opt.recover_atg_cov_max); + } + else + { + fprintf(stderr, "[M::%s] primary contig coverage range: [%d, infinity]\n", + __func__, asm_opt.recover_atg_cov_min); + } + + // fprintf(stderr, "[M::%s] 0\n", __func__); dbg_asys_gfa((*ug)->g); + adjust_utg_advance(read_g, (*ug), reverse_sources, ruIndex, b_mask_t, cov->is_r_het); + // fprintf(stderr, "[M::%s] 1\n", __func__); dbg_asys_gfa((*ug)->g); + + ///primary_flag = get_utg_attributes(*ug, read_g, coverage_cut, sources, ruIndex); + update_unitig_graph((*ug), read_g, coverage_cut, sources, reverse_sources, ruIndex, cov->is_r_het, 0, + DOUBLE_CHECK_THRES, flag, drop_rate); + // fprintf(stderr, "[M::%s] 2\n", __func__); dbg_asys_gfa((*ug)->g); + + nsg = (*ug)->g; + n_vtx = nsg->n_seq; + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + nsg->seq[v].c = PRIMARY_LABLE; + EvaluateLen((*ug)->u, v) = (*ug)->u.a[v].n; + } + // fprintf(stderr, "[M::%s] 3\n", __func__); + clean_trio_untig_graph(*ug, read_g, coverage_cut, sources, reverse_sources, tipsLen, + tip_drop_ratio, stops_threshold, ruIndex, NULL, NULL, 0, 0, 0, chimeric_rate, 0, 0, drop_ratio, flag, drop_rate, max_hang, min_ovlp, gap_fuzz, cov, new_rtg_edges); + // fprintf(stderr, "[M::%s] 4\n", __func__); + + ///delete_useless_nodes(ug); + delete_useless_trio_nodes(ug, read_g, coverage_cut, sources, ruIndex, flag, 0.8, 0.15, 16); + // fprintf(stderr, "[M::%s] 5\n", __func__); + + update_hap_label(*ug, read_g); + // fprintf(stderr, "[M::%s] 6\n", __func__); + + update_unitig_graph((*ug), read_g, coverage_cut, sources, reverse_sources, ruIndex, cov->is_r_het, 0, + DOUBLE_CHECK_THRES, flag, drop_rate); + // fprintf(stderr, "[M::%s] 7\n", __func__); + + force_trio_clean((*ug), read_g, coverage_cut, sources, reverse_sources, ruIndex, flag, 0.55, 0.01, 5); + // fprintf(stderr, "[M::%s] 8\n", __func__); + ///if(flag == MOTHER) print_debug_gfa(read_g, *ug, coverage_cut, "debug_trio_1", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); + + renew_utg(ug, read_g, new_rtg_edges); + // fprintf(stderr, "[M::%s] 9\n", __func__); + + if (!(asm_opt.flag & HA_F_BAN_POST_JOIN)) + { + rescue_missing_overlaps_aggressive(*ug, read_g, sources, coverage_cut, ruIndex, max_hang, + min_ovlp, 0, 1, NULL, b_mask_t); + // fprintf(stderr, "[M::%s] 10\n", __func__); + + renew_utg(ug, read_g, new_rtg_edges); + // fprintf(stderr, "[M::%s] 11\n", __func__); + + rescue_contained_reads_aggressive(*ug, read_g, sources, coverage_cut, ruIndex, max_hang, + min_ovlp, 10, 0, 1, NULL, NULL, b_mask_t); + // fprintf(stderr, "[M::%s] 12\n", __func__); + + renew_utg(ug, read_g, new_rtg_edges); + // fprintf(stderr, "[M::%s] 13\n", __func__); + } + + ///if(flag == MOTHER) print_untig_by_read(*ug, "m64043_200627_000137/124716590/ccs", 2789716, NULL, NULL, "beg"); + + + update_unitig_graph((*ug), read_g, coverage_cut, sources, reverse_sources, ruIndex, cov->is_r_het, 1, + FINAL_DOUBLE_CHECK_THRES, flag, drop_rate); + // fprintf(stderr, "[M::%s] 14\n", __func__); + + update_hap_label(NULL, read_g); + // fprintf(stderr, "[M::%s] 15\n", __func__); + + renew_utg(ug, read_g, new_rtg_edges); + // fprintf(stderr, "[M::%s] 16\n", __func__); + + ///delete_useless_nodes(ug); + delete_useless_trio_nodes(ug, read_g, coverage_cut, sources, ruIndex, flag, 0.8, 0.15, 16); + // fprintf(stderr, "[M::%s] 17\n", __func__); + + + if(asm_opt.purge_level_trio == 1) + { + purge_dups(*ug, read_g, coverage_cut, sources, reverse_sources, ruIndex, new_rtg_edges, + asm_opt.purge_simi_thres, asm_opt.purge_overlap_len, max_hang, min_ovlp, drop_ratio, 1, 0, + cov, 0, 0); + ///delete_useless_nodes(ug); + delete_useless_trio_nodes(ug, read_g, coverage_cut, sources, ruIndex, flag, 0.8, 0.15, 16); + } + // fprintf(stderr, "[M::%s] 18\n", __func__); + + if(asm_opt.max_contig_tip > 0) { + discard_small_ctg(ug, read_g, new_rtg_edges, asm_opt.max_contig_tip, 1, 0); + } + + // fprintf(stderr, "[M::%s] 19\n", __func__); + set_drop_trio_flag(*ug); + destory_hap_cov_t(&cov); + // fprintf(stderr, "[M::%s] 20\n", __func__); + // purge_dump(*ug); + renew_utg(ug, read_g, new_rtg_edges); + // fprintf(stderr, "[M::%s] 21\n", __func__); +} + + +int debug_untig_length(ma_ug_t *g, uint32_t tipsLen, const char* name) +{ + uint32_t i; + + for (i = 0; i < g->u.n; ++i) { + ma_utg_t *u = &g->u.a[i]; + if(u->m == 0) continue; + if(u->n <= tipsLen) + { + fprintf(stderr, "i: %u, u->n: %u, tipsLen: %u, %s\n", i, u->n, tipsLen, name); + } + } + + return 0; +} + +void prt_phase_dbg_graph(char *in, asg_t *sg, ma_sub_t *cov, ma_hit_t_alloc *src, R_to_U* ri, int max_hang, int min_ovlp) +{ + char* gfa_name = (char*)malloc(strlen(in)+100); + sprintf(gfa_name, "%s.phase", in); + uint64_t pscut = 0; + pscut = (asm_opt.hom_global_coverage_set?(asm_opt.hom_global_coverage):(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); + pscut *= PHASE_SEF; if(pscut < PHASE_SEP) pscut = PHASE_SEP; + ma_ug_t *ug = ma_ug_gen_phase(sg, pscut, PHASE_SEP_RATE); + print_debug_gfa(sg, ug, cov, gfa_name, src, ri, max_hang, min_ovlp, 0, 0, 0); + ma_ug_destroy(ug); + + sprintf(gfa_name, "%s.raw", in); + ug = ma_ug_gen(sg); + print_debug_gfa(sg, ug, cov, gfa_name, src, ri, max_hang, min_ovlp, 0, 0, 0); + ma_ug_destroy(ug); + + free(gfa_name); +} + +ma_ug_t* output_trio_unitig_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +uint8_t flag, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, +float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, int gap_fuzz, +int is_bench, bub_label_t* b_mask_t, char *f_prefix, uint8_t *kpt_buf, kvec_asg_arc_t_warp *r_edges) +{ + char* gfa_name = (char*)malloc(strlen(output_file_name)+100); + sprintf(gfa_name, "%s.%s.p_ctg.gfa", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); + FILE* output_file = NULL; + if(is_bench == 0) output_file = fopen(gfa_name, "w"); + + // prt_phase_dbg_graph(gfa_name, sg, coverage_cut, sources, ruIndex, max_hang, min_ovlp); + + ma_ug_t *ug = NULL; uint64_t pscut = 0; + // ug = ma_ug_gen(sg); + pscut = (asm_opt.hom_global_coverage_set?(asm_opt.hom_global_coverage):(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); + pscut *= PHASE_SEF; if(pscut < PHASE_SEP) pscut = PHASE_SEP; + ug = ma_ug_gen_phase(sg, pscut, PHASE_SEP_RATE); + + kvec_asg_arc_t_warp new_rtg_edges; + kv_init(new_rtg_edges.a); + adjust_utg_by_trio(&ug, sg, flag, TRIO_THRES, sources, reverse_sources, coverage_cut, + tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, + min_ovlp, gap_fuzz, &new_rtg_edges, b_mask_t); + if(asm_opt.b_low_cov > 0) + { + break_ug_contig(&ug, sg, &R_INF, coverage_cut, sources, ruIndex, &new_rtg_edges, max_hang, min_ovlp, + &asm_opt.b_low_cov, NULL, asm_opt.m_rate); + } + if(asm_opt.b_high_cov > 0) + { + break_ug_contig(&ug, sg, &R_INF, coverage_cut, sources, ruIndex, &new_rtg_edges, max_hang, min_ovlp, + NULL, &asm_opt.b_high_cov, asm_opt.m_rate); + } + if(kpt_buf) + { + update_dump_trio(R_INF.trio_flag, sg->n_seq, kpt_buf, ug); + } + if(is_bench) + { + free(gfa_name); + if(r_edges && new_rtg_edges.a.n > 0) { + kv_resize(asg_arc_t, r_edges->a, r_edges->a.n + new_rtg_edges.a.n); + memcpy(r_edges->a.a + r_edges->a.n, new_rtg_edges.a.a, new_rtg_edges.a.n*sizeof(asg_arc_t)); + r_edges->a.n += new_rtg_edges.a.n; + } + kv_destroy(new_rtg_edges.a); + return ug; + } + + fprintf(stderr, "Writing %s to disk... \n", gfa_name); + ///debug_utg_graph(ug, sg, 0, 0); + ///debug_untig_length(ug, tipsLen, gfa_name); + ///print_untig_by_read(ug, "m64011_190901_095311/125831121/ccs", 2310925, "end"); + ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 1); + ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, (flag==FATHER?"h1tg":"h2tg"), output_file); + fclose(output_file); + + sprintf(gfa_name, "%s.%s.p_ctg.noseq.gfa", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); + output_file = fopen(gfa_name, "w"); + ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, (flag==FATHER?"h1tg":"h2tg"), output_file); + fclose(output_file); + if(asm_opt.bed_inconsist_rate != 0) + { + sprintf(gfa_name, "%s.%s.p_ctg.lowQ.bed", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); + output_file = fopen(gfa_name, "w"); + ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, + max_hang, min_ovlp, asm_opt.bed_inconsist_rate, (flag==FATHER?"h1tg":"h2tg"), output_file, NULL); + fclose(output_file); + } + + free(gfa_name); + ma_ug_destroy(ug); + kv_destroy(new_rtg_edges.a); + return NULL; +} + + +void output_hap_graph(ma_ug_t *ug, asg_t *sg, kvec_asg_arc_t_warp *arcs, +ma_sub_t* coverage_cut, char* output_file_name, uint8_t flag, ma_hit_t_alloc* sources, +R_to_U* ruIndex, int max_hang, int min_ovlp, char *f_prefix) +{ + char* gfa_name = (char*)malloc(strlen(output_file_name)+100); + sprintf(gfa_name, "%s.%s.p_ctg.gfa", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); + FILE* output_file = fopen(gfa_name, "w"); + + fprintf(stderr, "Writing %s to disk... \n", gfa_name); + ///debug_utg_graph(ug, sg, 0, 0); + ///debug_untig_length(ug, tipsLen, gfa_name); + ///print_untig_by_read(ug, "m64011_190901_095311/125831121/ccs", 2310925, "end"); + ma_ug_seq(ug, sg, coverage_cut, sources, arcs, max_hang, min_ovlp, 0, 1); + ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, (flag==FATHER?"h1tg":"h2tg"), output_file); + fclose(output_file); + + sprintf(gfa_name, "%s.%s.p_ctg.noseq.gfa", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); + output_file = fopen(gfa_name, "w"); + ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, (flag==FATHER?"h1tg":"h2tg"), output_file); + fclose(output_file); + if(asm_opt.bed_inconsist_rate != 0) + { + sprintf(gfa_name, "%s.%s.p_ctg.lowQ.bed", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); + output_file = fopen(gfa_name, "w"); + ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, arcs, + max_hang, min_ovlp, asm_opt.bed_inconsist_rate, (flag==FATHER?"h1tg":"h2tg"), output_file, NULL); + fclose(output_file); + } + + free(gfa_name); +} + +void output_hap_sc_graph(kvect_sec_t *ug, asg_t *sg, /**kvec_asg_arc_t_warp *arcs,**/ ma_sub_t* coverage_cut, char* output_file_name, uint8_t flag, ma_hit_t_alloc* sources, R_to_U* ruIndex, /**int max_hang, int min_ovlp,**/ char *f_prefix) +{ + char* gfa_name = (char*)malloc(strlen(output_file_name)+100); + sprintf(gfa_name, "%s.%s.p_ctg.gfa", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); + FILE* output_file = fopen(gfa_name, "w"); + + fprintf(stderr, "Writing %s to disk... \n", gfa_name); + + // ma_ug_seq(ug->ctg, sg, coverage_cut, sources, arcs, max_hang, min_ovlp, 0, 1); + // ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, (flag==FATHER?"h1tg":"h2tg"), output_file); + ma_scg_print(ug, &R_INF, sg, coverage_cut, sources, ruIndex, 1, (flag==FATHER?"h1tg":"h2tg"), output_file); + fclose(output_file); + + free(gfa_name); +} + +scaf_res_t *gen_scaf_res_t(ug_opt_t *opt, ma_ug_t *sug, asg_t *rg, ma_ug_t *iug, ma_ug_t **res_ug) +{ + ma_ug_t *ug = (iug?(iug):(ma_ug_gen(rg))); + scaf_res_t *sc = gen_contig_path(opt, rg, sug, ug); + if(res_ug) (*res_ug) = ug; + return sc; +} + +void output_hap_sc_gpath(kvect_sec_t *ug, char* output_file_name, uint8_t flag, scaf_res_t *gpt, ma_ug_t *gpt_u, char *f_prefix) +{ + char* gfa_name = (char*)malloc(strlen(output_file_name)+100); + sprintf(gfa_name, "%s.%s.p_ctg.path.paf", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); + FILE* output_file = fopen(gfa_name, "w"); + + fprintf(stderr, "Writing %s to disk... \n", gfa_name); + + // ma_ug_seq(ug->ctg, sg, coverage_cut, sources, arcs, max_hang, min_ovlp, 0, 1); + // ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, (flag==FATHER?"h1tg":"h2tg"), output_file); + ma_scg_gpath_print(ug, (flag==FATHER?"h1tg":"h2tg"), gpt, gpt_u, output_file); + fclose(output_file); + + free(gfa_name); +} + +void output_hap_bp_gpath(ug_opt_t *opt, ma_ug_t *ug, asg_t *sg, char* output_file_name, uint8_t flag, ma_ug_t *gpt_u, char *f_prefix) +{ + scaf_res_t *gpt = gen_scaf_res_t(opt, ug, sg, gpt_u, NULL); + char* gfa_name = (char*)malloc(strlen(output_file_name)+100); + sprintf(gfa_name, "%s.%s.p_ctg.path.paf", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); + FILE* output_file = fopen(gfa_name, "w"); + fprintf(stderr, "Writing %s to disk... \n", gfa_name); + + ma_ug_gpath_print((flag==FATHER?"h1tg":"h2tg"), gpt, ug, gpt_u, output_file); + + destroy_scaf_res_t(gpt); + fclose(output_file); + free(gfa_name); +} + + +void filter_set_kug(uint8_t* trio_flag, asg_t *rg, uint8_t *rf, kvec_asg_arc_t_warp *r_edges, float f_rate, ma_ug_t **ug) +{ + asg_t* nsg = (*ug)->g; ma_utg_t *u = NULL; + uint32_t k, v, n_vtx = nsg->n_seq, rn = rg->n_seq; + int64_t flag_occ; + for (k = 0; k < rn; k++) { + trio_flag[k] = rf[k]>>1; + if(trio_flag[k] != FATHER && trio_flag[k] != MOTHER) trio_flag[k] = AMBIGU; + } + + for (k = 0; k < nsg->n_arc; k++) nsg->arc[k].del = 1; + for (v = 0; v < n_vtx; ++v) { + if (nsg->seq[v].del) continue; + u = &((*ug)->u.a[v]); + if(u->m == 0) continue; + for (k = flag_occ = 0; k < u->n; k++) flag_occ += (rf[u->a[k]>>33]&1); + if (flag_occ == (int64_t)u->n || flag_occ >= (int64_t)(u->n*f_rate)) { + if(u->m != 0){ + u->circ = u->end = u->len = u->m = u->n = u->start = 0; + free(u->a); + u->a = NULL; + } + nsg->seq[v].del = 1; + } + } + asg_cleanup(nsg); + renew_utg(ug, rg, r_edges); + + char name[32]; + for (v = 0, n_vtx = (*ug)->g->n_seq; v < n_vtx; ++v) { + u = &((*ug)->u.a[v]); + if(u->m == 0) continue; + for (k = flag_occ = 0; k < u->n; k++) flag_occ += (rf[u->a[k]>>33]&1); + sprintf(name, "ptg%.6d%c", v + 1, "lc"[u->circ]); + fprintf(stderr, "S\t%s\t*\tTN:i:%u\tUN:i:%ld\n", name, u->n, flag_occ); + } +} + + +void output_trio_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, +long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, +int min_ovlp, int is_bench, long long gap_fuzz, ug_opt_t *opt, bub_label_t* b_mask_t) +{ + reduce_hamming_error_adv(NULL, sg, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz, opt->ruIndex, NULL, tipsLen); + uint8_t *rf = NULL; + + if(asm_opt.kpt_rate > 0) CALLOC(rf, sg->n_seq); + + output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, + reverse_sources, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, + drop_ratio, max_hang, min_ovlp, gap_fuzz, is_bench, b_mask_t, NULL, rf, NULL); + + output_trio_unitig_graph(sg, coverage_cut, output_file_name, MOTHER, sources, + reverse_sources, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, + drop_ratio, max_hang, min_ovlp, gap_fuzz, is_bench, b_mask_t, NULL, rf, NULL); + + if(rf) { + kvec_asg_arc_t_warp r_edges; kv_init(r_edges.a); + ma_ug_t *kug = NULL; + char* kug_n = (char*)malloc(strlen(output_file_name)+100); + sprintf(kug_n, "%s.kdp", output_file_name); + + update_dump_trio(R_INF.trio_flag, sg->n_seq, rf, NULL); + kug = output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, + reverse_sources, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, + drop_ratio, max_hang, min_ovlp, gap_fuzz, 1, b_mask_t, NULL, NULL, &r_edges); + filter_set_kug(R_INF.trio_flag, sg, rf, &r_edges, asm_opt.kpt_rate, &kug); + print_utg(&kug, sg, coverage_cut, kug_n, sources, ruIndex, max_hang, min_ovlp, &r_edges); + + free(kug_n), kv_destroy(r_edges.a); ma_ug_destroy(kug); + free(rf); + } +} + +dedup_idx_t *gen_dedup_idx_t(ma_ug_t *ug, asg_t *rg) +{ + // fprintf(stderr, "[M::%s] Start\n", __func__); + dedup_idx_t *p = NULL; CALLOC(p, 1); + p->rg = rg; p->ug = ug; p->ridx_n = rg->n_seq + 1; + uint64_t k, m, l, z, *a, a_n; ma_utg_t *u; + + CALLOC(p->ridx, p->ridx_n); + for (k = p->ra_n = 0; k < ug->u.n; k++) { + u = &(ug->u.a[k]); p->ra_n += u->n; + if(!(u->n)) continue; + for (z = 0; z < u->n; z++) p->ridx[u->a[z]>>33]++; + } + for (k = l = 0; k < p->ridx_n; k++) { + m = p->ridx[k]; p->ridx[k] = l; l += m; + } + + + MALLOC(p->ra, p->ra_n); memset(p->ra, -1, sizeof((*(p->ra)))*p->ra_n); + for (k = 1; k < p->ridx_n; k++) { + a = p->ra + p->ridx[k-1]; + a_n = p->ridx[k] - p->ridx[k-1]; + if(a_n) a[a_n-1] = 0; + } + + for (k = 0; k < ug->u.n; k++) { + u = &(ug->u.a[k]); + if(!(u->n)) continue; + for (z = 0; z < u->n; z++) { + a = p->ra + p->ridx[u->a[z]>>33]; + a_n = p->ridx[(u->a[z]>>33)+1] - p->ridx[u->a[z]>>33]; + if(a_n) { + if(a[a_n-1] == a_n-1) a[a_n-1] = (k<<32)|z; + else a[a[a_n-1]++] = (k<<32)|z; + } + } + } + // fprintf(stderr, "[M::%s] End\n", __func__); + return p; +} + +void destroy_dedup_idx_t(dedup_idx_t *p) +{ + // fprintf(stderr, "[M::%s] Start\n", __func__); + if(p == NULL) return; + free(p->ridx); free(p->ra); free(p); + // fprintf(stderr, "[M::%s] End\n", __func__); +} + +void update_recover_atg_cov() +{ + if(asm_opt.recover_atg_cov_min == -1024) { + asm_opt.recover_atg_cov_max = (asm_opt.hom_global_coverage_set? + (asm_opt.hom_global_coverage):(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); + asm_opt.recover_atg_cov_min = asm_opt.recover_atg_cov_max * 0.85; + asm_opt.recover_atg_cov_max = INT32_MAX; + } +} + +int64_t cal_exact_ug_o(dedup_idx_t *idx, ma_utg_t *u, uint64_t f) +{ + if(u->n <= 0) return INT32_MIN; + uint64_t sv, *sa, sn, ev, *ea, en, si, ei, zn, *za, rev, k, nf = (uint64_t)-1, m, fn, nfn; ma_utg_t *z; + if(f == FATHER) {nf = MOTHER;} if(f == MOTHER) {nf = FATHER;} + sv = u->a[0]>>32; sa = idx->ra + idx->ridx[sv>>1]; sn = idx->ridx[(sv>>1)+1]-idx->ridx[sv>>1]; + ev = u->a[u->n-1]>>32; ea = idx->ra + idx->ridx[ev>>1]; en = idx->ridx[(ev>>1)+1] - idx->ridx[ev>>1]; + for (si = 0; si < sn; si++) { + z = &(idx->ug->u.a[sa[si]>>32]); + if((z->n == 0) || (z->m == 0) || (idx->ug->g->seq[sa[si]>>32].del)) continue; + assert(((z->a[(uint32_t)sa[si]]>>32)>>1) == (sv>>1)); + if((z->a[(uint32_t)sa[si]]>>32) == sv) rev = 0; + else rev = 1; + for (ei = 0; ei < en; ei++) { + if((idx->ug->u.a[ea[ei]>>32].n == 0) || (idx->ug->u.a[ea[ei]>>32].m == 0) || (idx->ug->g->seq[ea[ei]>>32].del)) continue; + assert(((idx->ug->u.a[ea[ei]>>32].a[(uint32_t)ea[ei]]>>32)>>1) == (ev>>1)); + if((sa[si]>>32) != (ea[ei]>>32)) continue;///not the same uid + if(((uint32_t)sa[si]) >= ((uint32_t)ea[ei])) { + zn = ((uint32_t)sa[si]) - ((uint32_t)ea[ei]) + 1; za = z->a + ((uint32_t)ea[ei]); + } else { + zn = ((uint32_t)ea[ei]) - ((uint32_t)sa[si]) + 1; za = z->a + ((uint32_t)sa[si]); + } + if(u->n != zn) continue; + if(!rev) { + for (k = 0; (k < zn) && ((u->a[k]>>32) == ((za[k]>>32))); k++); + if(k < zn) continue; + } else { + for (k = 0; (k < zn) && ((u->a[k]>>32) == (((uint64_t)(za[zn-k-1]>>32))^1)); k++); + if(k < zn) continue; + } + + assert(u->n <= z->n); + if(u->n < z->n) { + return -1;///delete u + } else if(u->n == z->n) { + for (m = fn = nfn = 0; m < u->n; m++) { + if(R_INF.trio_flag[u->a[m]>>33] == f) fn++; + if(R_INF.trio_flag[u->a[m]>>33] == nf) nfn++; + } + if(fn < nfn) return -1;///delete u + else return sa[si]>>32;///delete z + } + } + } + return INT32_MIN; +} + +void delete_ug_node(ma_ug_t *ug, uint64_t nid) +{ + asg_seq_del(ug->g, nid); + if(ug->u.a[nid].m!=0) { + ug->u.a[nid].m = ug->u.a[nid].n = 0; + free(ug->u.a[nid].a); ug->u.a[nid].a = NULL; + } +} + +uint64_t dedup_exact_ug(dedup_idx_t *ref, dedup_idx_t *qry, ma_sub_t *cov, ma_hit_t_alloc *src, R_to_U *rui, uint8_t *ff, uint8_t trio_f) +{ + // fprintf(stderr, "[M::%s] Start\n", __func__); + uint64_t k, n_base = 0; int64_t f; + for (k = 0; k < qry->ug->u.n; k++) { + if((qry->ug->u.a[k].n == 0) || (qry->ug->u.a[k].m == 0) || (qry->ug->g->seq[k].del)) continue; + if(if_primary_unitig(&(qry->ug->u.a[k]), qry->rg, cov, src, rui, ff)) continue; + f = cal_exact_ug_o(ref, &(qry->ug->u.a[k]), trio_f); + if(f == INT32_MIN) continue; + if(f == -1) {///delete qry + delete_ug_node(qry->ug, k); n_base += qry->ug->u.a[k].len; + } else if(f >= 0) {///delete ref + delete_ug_node(ref->ug, f); n_base += ref->ug->u.a[f].len; + } + } + // fprintf(stderr, "[M::%s] End\n", __func__); + return n_base; +} + +void push_ma_utg_t(ma_ug_t *ug, ma_utg_t *u) +{ + ma_utg_t *p; + ///graph + asg_seq_set(ug->g, ug->u.n, u->len, 0); ug->g->seq[ug->u.n].c = 0; + + //unitig + kv_pushp(ma_utg_t, ug->u, &p); memset(p, 0, sizeof((*p))); + *p = *u; p->a = NULL; p->s = NULL; + MALLOC(p->a, p->m); memcpy(p->a, u->a, sizeof((*(p->a)))*p->m); + if(u->s) { + MALLOC(p->s, p->len); memcpy(p->s, u->s, sizeof((*(p->s)))*p->len); + } + assert(ug->g->n_seq == ug->u.n); + if(p->n) { + p->circ = 0; p->start = (p->a[0]>>32); p->end = (p->a[p->n-1]>>32)^1; + } +} + +uint64_t append_miss_nid(asg_t *sg, ma_ug_t *hap0, ma_ug_t *hap1, uint8_t *ff, uint64_t len_cut, uint64_t occ_cut) +{ + ma_ug_t *ug = NULL; ma_utg_t *u; uint64_t k, z, pscut, n_set, fn, nfn, hap0n, hap1n, n_base = 0; + kvec_asg_arc_t_warp fe; memset(&fe, 0, sizeof(fe)); + memset(ff, 0, sizeof((*ff))*sg->n_seq); + ug = hap0; + for (k = 0; k < ug->u.n; k++) { + u = &(ug->u.a[k]); + if((u->n == 0) || (u->m == 0) || (ug->g->seq[k].del)) continue; + for (z = 0; z < u->n; z++) ff[u->a[z]>>33] = 1; + } + ug = hap1; + for (k = 0; k < ug->u.n; k++) { + u = &(ug->u.a[k]); + if((u->n == 0) || (u->m == 0) || (ug->g->seq[k].del)) continue; + for (z = 0; z < u->n; z++) ff[u->a[z]>>33] = 1; + } + ug = NULL; pscut = 0; + pscut = (asm_opt.hom_global_coverage_set?(asm_opt.hom_global_coverage):(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); + pscut *= PHASE_SEF; if(pscut < PHASE_SEP) pscut = PHASE_SEP; + ug = ma_ug_gen_phase(sg, pscut, PHASE_SEP_RATE); + for (k = 0; k < ug->u.n; k++) { + u = &(ug->u.a[k]); + if((u->n == 0) || (u->m == 0) || (ug->g->seq[k].del)) continue; + for (z = n_set = 0; z < u->n; z++) { + if(ff[u->a[z]>>33]) n_set++; + } + if((n_set > 0) && (n_set >= (u->n*0.2))) delete_ug_node(ug, k); + } + renew_utg((&ug), sg, &fe); + + for (k = hap0n = hap1n = 0; k < ug->u.n; k++) { + u = &(ug->u.a[k]); + if((u->n == 0) || (u->m == 0) || (ug->g->seq[k].del)) continue; + if((u->len < len_cut) || (u->n < occ_cut)) continue; + for (z = n_set = 0; z < u->n; z++) { + if(ff[u->a[z]>>33]) n_set++; + } + if((n_set > 0) && (n_set >= (u->n*0.2))) continue; + for (z = fn = nfn = 0; z < u->n; z++) { + if(R_INF.trio_flag[u->a[z]>>33] == FATHER) fn++; + if(R_INF.trio_flag[u->a[z]>>33] == MOTHER) nfn++; + } + if(fn > nfn) { + push_ma_utg_t(hap0, u); hap0n++; n_base += u->len; + } else { + push_ma_utg_t(hap1, u); hap1n++; n_base += u->len; + } + } + ma_ug_destroy(ug); ug = NULL; + if(hap0n) { + ug = hap0; + free(ug->g->idx); ug->g->idx = 0; ug->g->is_srt = 0; + asg_cleanup(ug->g); asg_symm(ug->g); + if(ug->g->seq_vis) { + REALLOC(ug->g->seq_vis, (ug->g->n_seq*2)); + memset(ug->g->seq_vis, 0, sizeof((*(ug->g->seq_vis)))*(ug->g->n_seq*2)); + } + } + if(hap1n) { + ug = hap1; + free(ug->g->idx); ug->g->idx = 0; ug->g->is_srt = 0; + asg_cleanup(ug->g); asg_symm(ug->g); + if(ug->g->seq_vis) { + REALLOC(ug->g->seq_vis, (ug->g->n_seq*2)); + memset(ug->g->seq_vis, 0, sizeof((*(ug->g->seq_vis)))*(ug->g->n_seq*2)); + } + } + return n_base; +} + +void prt_scaf_res_t(scaf_res_t *pa, ma_ug_t *ref, ma_ug_t *ctg, const char *cn) +{ + uint32_t k, i, z, a_n; ma_utg_t *rch; ul_vec_t *idx; uc_block_t *a; + for(i = 0; i < ctg->u.n; i++) { + rch = &(ctg->u.a[i]); idx = &(pa->a[i]); + fprintf(stderr, "[M::%s] %s%.6u%c. rch->len::%u, rch->n::%u, idx->n::%u\n", __func__, cn, i + 1, "lc"[rch->circ], (uint32_t)rch->len, (uint32_t)rch->n, (uint32_t)idx->bb.n); + if(idx->bb.n > 1) fprintf(stderr, "[M::%s::>>>>>>] idx->n::%u\n", __func__, (uint32_t)idx->bb.n); + // for (k = 0; k < idx->bb.n; k++) { + // fprintf(stderr, "[k->%u::utg%.6u%c(len->%u::n->%u)]\tq::[%u, %u)\t%c\tt::[%u, %u)\n", + // k, (idx->bb.a[k].hid) + 1, "lc"[ref->u.a[(idx->bb.a[k].hid)].circ], ref->u.a[(idx->bb.a[k].hid)].len, ref->u.a[(idx->bb.a[k].hid)].n, + // idx->bb.a[k].qs, idx->bb.a[k].qe, "+-"[idx->bb.a[k].rev], idx->bb.a[k].ts, idx->bb.a[k].te); + // } + + for (k = 0; k < idx->bb.n; k++) { + a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; + fprintf(stderr, "q::[%u, %u)\n", idx->bb.a[k].qs, idx->bb.a[k].qe); + for (z = 0; z < a_n; z++) fprintf(stderr, "utg%.6u%c,", (a[z].hid)+1, "lc"[ref->u.a[a[z].hid].circ]); + fprintf(stderr, "\n"); + for (z = 0; z < a_n; z++) fprintf(stderr, "utg%.6u%c[%u,%u),", (a[z].hid)+1, "lc"[ref->u.a[a[z].hid].circ], a[z].qs, a[z].qe); + fprintf(stderr, "\n"); + } + } +} + + +typedef struct { + uint32_t len[2], num[2], h; +} ug_res_t; + +typedef struct { + uint32_t *idx; + ug_res_t *map; + uint8_t *f; + ma_ug_t *ref; + kvec_t_u32_warp st, res; +} tangle_res_t; + + +ma_ug_t *gen_clean_ug(ma_ug_t *ref, scaf_res_t *cp0, scaf_res_t *cp1) +{ + ma_ug_t *ug = copy_untig_graph(ref); + uint32_t i, k, a_n, z, v, w; scaf_res_t *ctg = NULL; ul_vec_t *idx; uc_block_t *a; + if(cp0 || cp1) { + for (i = 0; i < ug->g->n_seq; i++) ug->g->seq[i].del = 1; + for (i = 0; i < ug->g->n_arc; i++) ug->g->arc[i].del = 1; + + ctg = cp0; + if (ctg) { + for(i = 0; i < ctg->n; i++) { + idx = &(ctg->a[i]); + for (k = 0; k < idx->bb.n; k++) { + a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; + for (z = 0; z < a_n; z++) ug->g->seq[a[z].hid].del = 0; + for (z = 1; z < a_n; z++) { + v = a[z-1].hid<<1; v |= (uint32_t)a[z-1].rev; + w = a[z].hid<<1; w |= (uint32_t)a[z].rev; + + asg_arc_del(ug->g, v, w, 0); + asg_arc_del(ug->g, w^1, v^1, 0); + } + } + } + } + + ctg = cp1; + if (ctg) { + for(i = 0; i < ctg->n; i++) { + idx = &(ctg->a[i]); + for (k = 0; k < idx->bb.n; k++) { + a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; + for (z = 0; z < a_n; z++) ug->g->seq[a[z].hid].del = 0; + for (z = 1; z < a_n; z++) { + v = a[z-1].hid<<1; v |= (uint32_t)a[z-1].rev; + w = a[z].hid<<1; w |= (uint32_t)a[z].rev; + + asg_arc_del(ug->g, v, w, 0); + asg_arc_del(ug->g, w^1, v^1, 0); + } + } + } + } + } + + + for (i = 0; i < ug->g->n_seq; i++) { + if(ug->g->seq[i].del == 1) { + asg_seq_del(ug->g, i); + if(ug->u.a[i].m!=0) { + ug->u.a[i].m = ug->u.a[i].n = 0; + free(ug->u.a[i].a); + ug->u.a[i].a = NULL; + } + } + } + + asg_cleanup(ug->g); + + return ug; +} + +ma_ug_t *gen_shallow_clean_ug(ma_ug_t *ref, bubble_type *bu, scaf_res_t *cp0, scaf_res_t *cp1) +{ + ma_ug_t *ug = copy_untig_graph(ref); + uint32_t i, k, a_n, z, v, w; scaf_res_t *ctg = NULL; ul_vec_t *idx; uc_block_t *a; + if(cp0 || cp1) { + ///just clean bubbles + for (i = 0; i < ug->g->n_seq; i++) { + // if(i < bu->f_bub) ug->g->seq[i].del = 1;///no need broken bubble; looks like a bug in scaffolding + if(bu->index[i] < bu->f_bub) ug->g->seq[i].del = 1; + } + for (i = 0; i < ug->g->n_arc; i++) { + if((bu->index[ug->g->arc[i].ul>>33] < bu->f_bub) || (bu->index[ug->g->arc[i].v>>1] < bu->f_bub)) {///no need broken bubble + ug->g->arc[i].del = 1; + } + } + + ctg = cp0; + if (ctg) { + for(i = 0; i < ctg->n; i++) { + idx = &(ctg->a[i]); + for (k = 0; k < idx->bb.n; k++) { + a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; + for (z = 0; z < a_n; z++) ug->g->seq[a[z].hid].del = 0; + for (z = 1; z < a_n; z++) { + v = a[z-1].hid<<1; v |= (uint32_t)a[z-1].rev; + w = a[z].hid<<1; w |= (uint32_t)a[z].rev; + // if(((v>>1) < bu->f_bub) || ((w>>1) < bu->f_bub)) { + if((bu->index[(v>>1)] < bu->f_bub) || (bu->index[(w>>1)] < bu->f_bub)) { + asg_arc_del(ug->g, v, w, 0); + asg_arc_del(ug->g, w^1, v^1, 0); + } + } + } + } + } + + ctg = cp1; + if (ctg) { + for(i = 0; i < ctg->n; i++) { + idx = &(ctg->a[i]); + for (k = 0; k < idx->bb.n; k++) { + a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; + for (z = 0; z < a_n; z++) ug->g->seq[a[z].hid].del = 0; + for (z = 1; z < a_n; z++) { + v = a[z-1].hid<<1; v |= (uint32_t)a[z-1].rev; + w = a[z].hid<<1; w |= (uint32_t)a[z].rev; + // if(((v>>1) < bu->f_bub) || ((w>>1) < bu->f_bub)) { + if((bu->index[(v>>1)] < bu->f_bub) || (bu->index[(w>>1)] < bu->f_bub)) { + asg_arc_del(ug->g, v, w, 0); + asg_arc_del(ug->g, w^1, v^1, 0); + } + } + } + } + } + } + + + for (i = 0; i < ug->g->n_seq; i++) { + if(ug->g->seq[i].del == 1) { + asg_seq_del(ug->g, i); + if(ug->u.a[i].m!=0) { + ug->u.a[i].m = ug->u.a[i].n = 0; + free(ug->u.a[i].a); + ug->u.a[i].a = NULL; + } + } + } + + asg_cleanup(ug->g); + + return ug; +} + +static void worker_for_ctg_trans_cc(void *data, long i, int tid) // callback for kt_for() +{ + kv_u_trans_t *ta = (kv_u_trans_t*)data; + u_trans_t *a = NULL, *r_a = NULL, *mz, *cz; + uint32_t n, r_n, id = i, k, l, z; + + a = u_trans_a(*ta, id); n = u_trans_n(*ta, id); + for (k = 1, l = 0; k <= n; k++) { + if(k == n || a[l].tn != a[k].tn) { + if(k > l) { + get_u_trans_spec(ta, a[l].tn, a[l].qn, &r_a, &r_n); + assert(r_n > 0); + if(id > a[l].tn) { + l = k; continue; + } + + mz = cz = NULL; + for (z = l; z < k; z++) { + cz = &(a[z]); cz->del = 1; + if((mz) && (mz->f == 1) && (cz->f != 1)) continue; + if((!mz) || ((cz->f == 1) && (mz->f != 1)) || ((cz->f == mz->f) && ((mz->nw < cz->nw) || ((mz->nw == cz->nw) && ((mz->qe - mz->qs) < (cz->qe - cz->qs)))))) { + mz = cz; + } + } + for (z = 0; z < r_n; z++) { + cz = &(r_a[z]); cz->del = 1; + if((mz) && (mz->f == 1) && (cz->f != 1)) continue; + if((!mz) || ((cz->f == 1) && (mz->f != 1)) || ((cz->f == mz->f) && ((mz->nw < cz->nw) || ((mz->nw == cz->nw) && ((mz->qe - mz->qs) < (cz->qe - cz->qs)))))) { + mz = cz; + } + } + + assert(mz); + mz->del = 0; + } + l = k; + } + } +} + +void update_ctg_trans_cc(kv_u_trans_t *os) +{ + uint64_t k, m; u_trans_t *z; + kt_for(asm_opt.thread_num, worker_for_ctg_trans_cc, os, os->idx.n); + for (k = m = 0; k < os->n; k++) { + if(!(os->a[k].del)) os->a[m++] = os->a[k]; + } + os->n = m; + for (k = 0; k < m; k++) { + kv_pushp(u_trans_t, *os, &z); + *z = os->a[k]; + z->qn = os->a[k].tn; z->qs = os->a[k].ts; z->qe = os->a[k].te; + z->tn = os->a[k].qn; z->ts = os->a[k].qs; z->te = os->a[k].qe; + } + kt_u_trans_t_idx(os, os->idx.n); +} + +uint32_t get_scaf_res_t(scaf_res_t *pa, uint32_t uid, uint32_t s, uint32_t e, uint32_t *in, uint32_t *rs, uint32_t *re, uint32_t *rn, uc_block_t **ra) +{ + // fprintf(stderr, "s::%u, e::%u, uid::%u, pa->n::%u\n", s, e, uid, (uint32_t)pa->n); + if(uid >= pa->n) return 0; + ul_vec_t *idx = &(pa->a[uid]); uint32_t k, z, a_n, os, oe, z0; uc_block_t *a; + (*rs) = (*re) = (uint32_t)-1; (*rn) = 0; (*ra) = NULL; + + for (k = (*in); k < idx->bb.n; k++) { + a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; + os = MAX(s, idx->bb.a[k].qs); + oe = MIN(e, idx->bb.a[k].qe); + // fprintf(stderr, "k::%u, os::%u, oe::%u, a_n::%u\n", k, os, oe, a_n); + if(os >= oe) continue; + for(z = 0; z < a_n && a[z].qe <= os; z++); + if(z >= a_n) continue; + for(z0 = z; z < a_n && a[z].qs < oe; z++); + if(z <= z0 ) continue; + *rs = os; *re = oe; *rn = z - z0; *ra = a + z0; (*in) = k + 1; + return 1; + } + return 0; +} + +void prt_scaf_res_t(ma_ug_t *ref, scaf_res_t *cp, ma_ug_t *ug, uint32_t uid, uint32_t s, uint32_t e, const char *pfx, uint32_t bw) +{ + uint32_t in, rs, re, rn, z; uc_block_t *ra; + + in = 0; + while (get_scaf_res_t(cp, uid, s, e, &in, &rs, &re, &rn, &ra)) { + fprintf(stderr, "%s%.6u%c\t%u\t%u\t%u\tn(%u)\n", pfx, uid+1, "lc"[ug->u.a[uid].circ], ug->u.a[uid].len, rs, re, rn); + if(rn <= (bw<<1)) { + for (z = 0; z < rn; z++) fprintf(stderr, "utg%.6u%c,", (ra[z].hid)+1, "lc"[ref->u.a[ra[z].hid].circ]); + } else { + for (z = 0; z < bw; z++) fprintf(stderr, "utg%.6u%c,", (ra[z].hid)+1, "lc"[ref->u.a[ra[z].hid].circ]); + fprintf(stderr, "......,"); + for (z = rn-bw; z < rn; z++) fprintf(stderr, "utg%.6u%c,", (ra[z].hid)+1, "lc"[ref->u.a[ra[z].hid].circ]); + } + fprintf(stderr, "\n"); + } +} + +void print_ctg_trans_ovlp(kv_u_trans_t *os, ma_ug_t *ref, ma_ug_t *hu1, scaf_res_t *cp1, ma_ug_t *hu2, scaf_res_t *cp2) +{ + u_trans_t *p = NULL; uint32_t i, qui, tui, qid, tid; ma_utg_t *uq, *ut; + for (i = 0; i < os->n; i++) { + p = &(os->a[i]); + qui = p->qnu.n?1:2; qid = ((p->qnu.n)?p->qn:p->qn-hu1->u.n); + tui = p->tnu.n?1:2; tid = ((p->tnu.n)?p->tn:p->tn-hu1->u.n); + uq = ((p->qnu.n)?&(hu1->u.a[p->qn]):&(hu2->u.a[p->qn-hu1->u.n])); + ut = ((p->tnu.n)?&(hu1->u.a[p->tn]):&(hu2->u.a[p->tn-hu1->u.n])); + fprintf(stderr, "************\n"); + fprintf(stderr, "[M::%s] h%utg%.6u%c\t%u\t%u\t%u\t%c\th%utg%.6u%c\t%u\t%u\t%u\tw(%f)\tf(%u)\n", __func__, + qui, qid+1, "lc"[uq->circ], uq->len, p->qs, p->qe, "+-"[p->rev], + tui, tid+1, "lc"[ut->circ], ut->len, p->ts, p->te, p->nw, p->f); + + prt_scaf_res_t(ref, qui==1?cp1:cp2, qui==1?hu1:hu2, (p->qnu.n)?p->qn:p->qn-hu1->u.n, p->qs, p->qe, qui==1?"h1tg":"h2tg", 3); + prt_scaf_res_t(ref, tui==1?cp1:cp2, tui==1?hu1:hu2, (p->tnu.n)?p->tn:p->tn-hu1->u.n, p->ts, p->te, tui==1?"h1tg":"h2tg", 3); + } +} + +static inline void scaf_hit2arc(u_trans_t *a0, u_trans_t *a1, uint64_t rev, uint64_t el, int64_t glen, asg_arc_t *p) +{ + uint64_t v, w; + memset(p, 0, sizeof((*p))); + v = ((uint64_t)(a0->tn<<1))|((uint64_t)(!!(a0->rev))); v^=((uint64_t)(!!(rev))); + w = ((uint64_t)(a1->tn<<1))|((uint64_t)(!!(a1->rev))); w^=((uint64_t)(!!(rev))); + // p->ul = v; p->ul <<= 32; p->ul |= a0i; p->v = w; p->ol = a1i; p->el = el; + p->ul = v; p->ul <<= 32; p->v = w; p->ol = ((glen>=0)?(glen):(-glen)); p->el = el; p->strong = ((glen>=0)?(1):(0)); + // a0r = 0; if((a0->f) || (((a0->qe-a0->qs) >= reliable_len) && ((a0->te-a0->ts) >= reliable_len))) a0r = 1; + // a1r = 0; if((a1->f) || (((a1->qe-a1->qs) >= reliable_len) && ((a1->te-a1->ts) >= reliable_len))) a1r = 1; + // p->el = ((a0r && a1r)?1:0); +} + +uint64_t is_noisy_ov(uint64_t s, uint64_t e, uint64_t len, uint64_t bd, double cov_rate, u_trans_t *a, uint64_t a_n) +{ + uint64_t w, k, zs, ze, oz, tot; + if(e - s < (bd<<1)) { + w = (e + s)>>1; + s = ((w>=bd)?(w-bd):(0)); + e = ((w+bd<=len)?(w+bd):(len)); + } + if(s >= e) return 0; + for(k = tot = 0; k < a_n; k++) { + if(a[k].qs >= e) break; + if(a[k].qe <= s) continue; + zs = MAX(s, a[k].qs); ze = MIN(e, a[k].qe); + oz = ((ze > zs)? (ze - zs):(0)); + tot += oz; + } + if((tot > 0) && (tot >= ((e - s)*cov_rate))) return 1; + return 0; +} + +uint64_t get_ref_nid(u_trans_t *z, ma_ug_t *hu1, ma_ug_t *hu2, scaf_res_t *cp1, scaf_res_t *cp2, uint64_t is_beg, uint64_t gap_bd) +{ + scaf_res_t *sc = NULL; uint64_t id, s_end, e_end; + if(z->tn < hu1->u.n) { + sc = cp1; id = z->tn; + } else { + sc = cp2; id = z->tn - hu1->u.n; + } + + if(is_beg) { + s_end = 0; e_end = 1; + } else { + s_end = 1; e_end = 0; + } + + if(!(z->rev)) { + s_end ^= 1; e_end ^= 1; + } + + + ul_vec_t *idx = &(sc->a[id]); uint64_t k, m, a_n, os, oe, m0; + uc_block_t *a, *am = NULL; uint64_t max_len = 0, cgap, clen; + + for (k = 0; k < idx->bb.n; k++) { + a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; + os = MAX(z->ts, idx->bb.a[k].qs); + oe = MIN(z->te, idx->bb.a[k].qe); + if(os >= oe) continue; + for(m = 0; m < a_n && a[m].qe <= os; z++); + if(m >= a_n) continue; + for(m0 = m; m < a_n && a[m].qs < oe; m++); + if(m <= m0) continue; + + os = MAX(z->ts, a[m0].qs); + oe = MIN(z->te, a[m-1].qe); + if(oe <= os) continue; + clen = oe - os; cgap = 0; + if(s_end) { + cgap = os - z->ts; + } else if(e_end) { + cgap = z->te - oe; + } + if(cgap > gap_bd) continue; + if(clen > max_len) { + max_len = clen; am = ((s_end)?(&(a[m0])):(&(a[m-1]))); + } + } + + if(!am) return (uint64_t)-1; + return ((uint64_t)(am->hid<<1))|((uint64_t)(!!(am->rev))); +} + +uint64_t cal_self_close_tang(asg_t *g, uint32_t s0, uint32_t e0, asg32_v *b1, asg32_v *b2, uint8_t *f, uint32_t max_path) +{ + uint32_t z, v, nv, k, se = 0, o0, o1, o, tot; asg_arc_t *av; + b1->n = 0; b2->n = 0; tot = 0; + kv_push(uint32_t, *b1, (s0>>1)); + while(b1->n) { + z = b1->a[--b1->n]; + if(f[z]) continue; + f[z] = 1; o0 = o1 = 0; + kv_push(uint32_t, *b2, z); + + v = (z<<1); o = 0; + if((v != e0) && (v != (s0^1))) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (k = o = 0; k < nv; k++) { + if(av[k].del) continue; + if((av[k].v == s0) || (av[k].v == (e0^1))) { + se = 1; break; + } + if(f[av[k].v>>1]) { + if(((av[k].v>>1) != (s0>>1)) && ((av[k].v>>1) != (e0>>1)) && (o < av[k].ol)) o = av[k].ol; + continue; + } + kv_push(uint32_t, *b1, (av[k].v>>1)); + } + if(se) break; + } + o0 = o; + + + v = (z<<1) + 1; o = 0; + if((v != e0) && (v != (s0^1))) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (k = o = 0; k < nv; k++) { + if(av[k].del) continue; + if((av[k].v == s0) || (av[k].v == (e0^1))) { + se = 1; break; + } + if(f[av[k].v>>1]) { + if(((av[k].v>>1) != (s0>>1)) && ((av[k].v>>1) != (e0>>1)) && (o < av[k].ol)) o = av[k].ol; + continue; + } + kv_push(uint32_t, *b1, (av[k].v>>1)); + } + if(se) break; + } + o1 = o; + + if(o0 + o1 < g->seq[z].len) tot += g->seq[z].len - o0 - o1; + if(tot > max_path) break; + } + + for (k = 0; k < b2->n; k++) f[b2->a[k]] = 0; + + if((!se) && (tot <= max_path)) return tot; + return (uint64_t)-1; +} + +uint64_t get_ref_nid_flank(u_trans_t *z, ma_ug_t *ref, ma_ug_t *hu1, ma_ug_t *hu2, scaf_res_t *cp1, scaf_res_t *cp2, uint64_t is_beg, uint64_t gap_bd, uint64_t flank_len, asg32_v *res) +{ + scaf_res_t *sc = NULL; uint64_t id, s_end, e_end, rn = res->n; + if(z->tn < hu1->u.n) { + sc = cp1; id = z->tn; + } else { + sc = cp2; id = z->tn - hu1->u.n; + } + + if(is_beg) { + s_end = 0; e_end = 1; + } else { + s_end = 1; e_end = 0; + } + + if(z->rev) { + s_end ^= 1; e_end ^= 1; + } + + + ul_vec_t *idx = &(sc->a[id]); uint64_t k, m, a_n, os, oe, m0; + uc_block_t *a, *am = NULL; uint64_t max_len = 0, cgap, clen; int64_t ami, amn = 0, as, ae, amz; + // if(z->tn == 5) { + // fprintf(stderr, "\n[M::%s] h1tg%.6u%c(%c)\ts::%u\te::%u\ts_end::%lu\te_end::%lu\n", __func__, z->tn+1, "lc"[hu1->u.a[z->tn].circ], "+-"[z->rev], z->ts, z->te, s_end, e_end); + // } + + for (k = 0; k < idx->bb.n; k++) { + a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; + os = MAX(z->ts, idx->bb.a[k].qs); + oe = MIN(z->te, idx->bb.a[k].qe); + // if(z->tn == 5) { + // fprintf(stderr, "[M::%s] idx->bb.a[%lu]::[%u, %u), o[%lu, %lu), a_n::%lu\n", __func__, k, idx->bb.a[k].qs, idx->bb.a[k].qe, os, oe, a_n); + // } + if(os >= oe) continue; + for(m = 0; m < a_n && a[m].qe <= os; m++); + // { + // if(z->tn == 5) fprintf(stderr, "+(%lu)utg%.6u%c[%u,%u),", m, (a[m].hid)+1, "lc"[ref->u.a[a[m].hid].circ], a[m].qs, a[m].qe); + // } + // if(z->tn == 5) fprintf(stderr, "\n[M::%s] +m::%lu\n", __func__, m); + if(m >= a_n) continue; + for(m0 = m; m < a_n && a[m].qs < oe; m++); + // { + // if(z->tn == 5) fprintf(stderr, "-(%lu)utg%.6u%c[%u,%u),", m, (a[m].hid)+1, "lc"[ref->u.a[a[m].hid].circ], a[m].qs, a[m].qe); + // } + // if(z->tn == 5) fprintf(stderr, "\n[M::%s] -m::%lu\n", __func__, m); + if(m <= m0) continue; + + os = MAX(z->ts, a[m0].qs); + oe = MIN(z->te, a[m-1].qe); + // if(z->tn == 5) { + // fprintf(stderr, "[M::%s] m0::%lu, m::%lu, o[%lu, %lu), a_n::%lu\n", __func__, m0, m, os, oe, a_n); + // } + if(oe <= os) continue; + clen = oe - os; cgap = 0; + if(s_end) { + cgap = os - z->ts; + } else if(e_end) { + cgap = z->te - oe; + } + if(cgap > gap_bd) continue; + if(clen > max_len) { + max_len = clen; am = a + m0; amn = m - m0; + } + } + + // if(z->tn == 49 && z->ts == 0 && z->te == 2143149) { + // fprintf(stderr, "-0-[M::%s] h1tg%.6ul(%c)\tts::%u\tte::%u\tamn::%ld\ts_end::%lu\te_end::%lu\n", __func__, + // z->tn+1, "+-"[z->rev], z->ts, z->te, amn, s_end, e_end); + // } + + // if(z->tn == 5) fprintf(stderr, "[M::%s] amn::%ld\n", __func__, amn); + + if((!am) || (!amn)) return 0; + os = oe = 0; as = 0; ae = amn; + if(s_end) { + for(ami = 0; (ami < amn) && ((z->ts + flank_len) >= am[ami].qe); ami++); + if((ami < amn) && ((z->ts + flank_len) >= am[ami].qs)) ami++; + as = 0; ae = ami; + } else if(e_end) { + for(ami = amn - 1; (ami >= 0) && (z->te <= (am[ami].qs + flank_len)); ami--); + if((ami >= 0) && (z->te <= (am[ami].qe + flank_len))) ami--; + ami++; as = ami; ae = amn; + } + // if(z->tn == 49 && z->ts == 0 && z->te == 2143149) { + // fprintf(stderr, "-1-[M::%s] h1tg%.6ul(%c)\tts::%u\tte::%u\tas::%ld\tae::%ld\n", __func__, + // z->tn+1, "+-"[z->rev], z->ts, z->te, as, ae); + // } + // if(z->tn == 5) fprintf(stderr, "+[M::%s] as::%ld, ae::%ld\n", __func__, as, ae); + if(as >= ae) return 0; + + ///make sure there are no identical node + if(s_end) { + for (ami = as; ami < ae; ami++) { + for (amz = ami + 1; (amz < ae) && (am[ami].hid != am[amz].hid); amz++); + if(amz < ae) { + ae = ami + 1; break; + } + } + } else if(e_end) { + for (ami = ae - 1; ami >= as; ami--) { + for (amz = ami - 1; (amz >= as) && (am[ami].hid != am[amz].hid); amz--); + if(amz >= as) { + as = ami; break; + } + } + } + // if(z->tn == 49 && z->ts == 0 && z->te == 2143149) { + // fprintf(stderr, "-1-[M::%s] h1tg%.6ul(%c)\tts::%u\tte::%u\tas::%ld\tae::%ld\n", __func__, + // z->tn+1, "+-"[z->rev], z->ts, z->te, as, ae); + // } + // if(z->tn == 5) fprintf(stderr, "+[M::%s] as::%ld, ae::%ld\n", __func__, as, ae); + if(as >= ae) return 0; + + uint32_t *fp = NULL, r2n = 0; + kv_resize(uint32_t, *res, rn + ((ae - as)<<1)); + for (ami = as; ami < ae; ami++) { + m = ((uint64_t)(am[ami].hid<<1))|((uint64_t)(!!(am[ami].rev))); m ^= ((uint64_t)(!!(z->rev))); + kv_push(uint32_t, *res, m); + } + rn = res->n - rn; + if(z->rev) { + fp = res->a + res->n - rn; r2n = rn>>1; + for (k = 0; k < r2n; k++) { + m = fp[k]; fp[k] = fp[rn - k -1]; fp[rn - k -1] = m; + } + } + + if(s_end) { + for (ami = as; ami < ae; ami++) { + m = ((am[ami].qs>=z->ts)?(am[ami].qs-z->ts):(0)); + kv_push(uint32_t, *res, m); + } + } else if(e_end) { + for (ami = as; ami < ae; ami++) { + m = ((z->te>=am[ami].qe)?(z->te-am[ami].qe):(0)); + kv_push(uint32_t, *res, m); + } + } + if(z->rev) { + fp = res->a + res->n - rn; r2n = rn>>1; + for (k = 0; k < r2n; k++) { + m = fp[k]; fp[k] = fp[rn - k - 1]; fp[rn - k - 1] = m; + } + } + + return rn; + // return ((uint64_t)(am->hid<<1))|((uint64_t)(!!(am->rev))); +} + +void dedup_tang_flank(uint32_t *va, uint32_t *vd, uint32_t *vn0, uint32_t *wa, uint32_t *wd, uint32_t *wn0) +{ + uint64_t k, z, vn = (*vn0), wn = (*wn0); + uint32_t vp, wp; + for (k = 0; k < vn && k < wn; k++) { + if(k < vn) { + vp = va[vn-k-1]>>1; + for (z = k; (z < wn) && (vp != (wa[z]>>1)); z++); + if(z < wn) wn = z; + } + if(k < wn) { + wp = wa[k]>>1; + for (z = k; (z < vn) && (wp != (va[vn-z-1]>>1)); z++); + if(z < vn) vn = z; + } + } + if(vn < (*vn0)) { + z = (*vn0) - vn; + for (k = 0; k < vn; k++) { + va[k] = va[k + z]; vd[k] = vd[k + z]; + } + } + (*vn0) = vn; (*wn0) = wn; +} + + +uint64_t cal_self_close_tang_flank0(asg_t *g, uint32_t v0, uint32_t s0, uint32_t e0, uint64_t sf, uint64_t ef, asg32_v *b1, asg32_v *b2, uint8_t *f, uint8_t *fs, uint64_t max_path) +{ + uint64_t se = 0, k, v, o, o0, o1, nv, tot = 0; asg_arc_t *av; + + if(f[v0]) return (uint64_t)-1; + + // if((v0>>1) == 47687) fprintf(stderr, "+[M::%s] v0->utg%.6ul(%c), s0::%u, e0::%u, sf::%lu, ef::%lu\n", __func__, (v0>>1)+1, "+-"[v0&1], s0, e0, sf, ef); + + b1->n = b2->n = 0; kv_push(uint32_t, *b1, v0); + while(b1->n) { + v = b1->a[--b1->n]; + if(f[v] && f[v^1]) continue; + // if((v0>>1) == 47687) fprintf(stderr, "[M::%s] utg%.6lul(%c), tot::%lu\n", __func__, (v>>1)+1, "+-"[v&1], tot); + + v = v; + // if((v0>>1) == 47687) fprintf(stderr, "[M::%s] v::%lu, f[v]::%u, fs[v]::%u, fs[v^1]::%u\n", __func__, v, f[v], fs[v], fs[v^1]); + if((!f[v]) && (v!=(s0^1)) && (v!=e0)) { + if((fs[v^1] != sf) && (fs[v] != ef)) { + f[v] = 1; kv_push(uint32_t, *b2, v); + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + // if((v0>>1) == 47687) fprintf(stderr, "[M::%s] k::%lu, f[av[k].v]::%u, fs[av[k].v]::%u, fs[av[k].v^1]::%u\n", __func__, k, f[av[k].v], fs[av[k].v], fs[av[k].v^1]); + if((av[k].v == s0) || (av[k].v == (e0^1))) { + se = 1; break; + } + if(fs[av[k].v] == sf) { + fs[av[k].v] = 0;///not a beg node anymore + if(!f[av[k].v^1]) kv_push(uint32_t, *b1, (av[k].v^1));///push reverse node + } + if(fs[(av[k].v^1)] == ef) { + fs[(av[k].v^1)] = 0;///not a end node anymore; do not need to push as it will be pushed later + if(!f[av[k].v]) kv_push(uint32_t, *b1, (av[k].v));///push reverse node + } + + /**if((fs[av[k].v^1] != sf) && (fs[av[k].v] != ef))**/ { + if((!f[av[k].v])) kv_push(uint32_t, *b1, av[k].v); + } + } + if(se) break; + } + } + + v = v^1; + // if((v0>>1) == 47687) fprintf(stderr, "[M::%s] v::%lu, f[v]::%u, fs[v]::%u, fs[v^1]::%u\n", __func__, v, f[v], fs[v], fs[v^1]); + if((!f[v]) && (v != (s0^1)) && (v != e0)) { + if((fs[v^1] != sf) && (fs[v] != ef)) { + f[v] = 1; kv_push(uint32_t, *b2, v); + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + // if((v0>>1) == 47687) fprintf(stderr, "[M::%s] k::%lu, f[av[k].v]::%u, fs[av[k].v]::%u, fs[av[k].v^1]::%u\n", __func__, k, f[av[k].v], fs[av[k].v], fs[av[k].v^1]); + if((av[k].v == s0) || (av[k].v == (e0^1))) { + se = 1; break; + } + if(fs[av[k].v] == sf) { + fs[av[k].v] = 0;///not a beg node anymore + if(!f[av[k].v^1]) kv_push(uint32_t, *b1, (av[k].v^1));///push reverse node + } + if(fs[(av[k].v^1)] == ef) fs[(av[k].v^1)] = 0;///not a end node anymore; do not need to push as it will be pushed later + + /**if((fs[av[k].v^1] != sf) && (fs[av[k].v] != ef))**/ { + if((!f[av[k].v])) kv_push(uint32_t, *b1, av[k].v); + } + } + if(se) break; + } + } + + if(f[v] && f[v^1]) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (k = o = 0; k < nv; k++) { + if(av[k].del) continue; + if((f[av[k].v^1]) && (f[av[k].v]) && (o < av[k].ol)) o = av[k].ol; + } + o0 = o; + + av = asg_arc_a(g, (v^1)); nv = asg_arc_n(g, (v^1)); + for (k = o = 0; k < nv; k++) { + if(av[k].del) continue; + if((f[av[k].v^1]) && (f[av[k].v]) && (o < av[k].ol)) o = av[k].ol; + } + o1 = o; + + if(o0 + o1 < g->seq[v>>1].len) tot += g->seq[v>>1].len - o0 - o1; + } + + if(tot > max_path) break; + } + + // if((v0>>1) == 47687) fprintf(stderr, "-[M::%s] v0->utg%.6ul(%c), tot::%lu, se::%lu\n", __func__, (v0>>1)+1, "+-"[v0&1], tot, se); + + if((!se) && (tot <= max_path)) return tot; + return (uint64_t)-1; +} + + + +uint64_t cal_self_close_tang_flank1(asg_t *g, uint32_t s0, uint32_t e0, asg32_v *b1, asg32_v *b2, uint8_t *f, uint8_t *fsk, uint64_t max_path) +{ + uint64_t se = 0, k, v, o, o0, o1, nv, tot = 0; asg_arc_t *av; + + b1->n = b2->n = 0; kv_push(uint32_t, *b1, s0); + while(b1->n) { + v = b1->a[--b1->n]; + if(f[v] && f[v^1]) continue; + + v = v; + if((!f[v]) && (v!=(s0^1)) && (v!=e0)) { + f[v] = 1; kv_push(uint32_t, *b2, v); + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if((av[k].v == s0) || (av[k].v == (e0^1))) { + se = 1; break; + } + if((!f[av[k].v])) kv_push(uint32_t, *b1, av[k].v); + } + if(se) break; + } + + v = v^1; + if((!f[v]) && (v!=(s0^1)) && (v!=e0)) { + f[v] = 1; kv_push(uint32_t, *b2, v); + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if((av[k].v == s0) || (av[k].v == (e0^1))) { + se = 1; break; + } + if((!f[av[k].v])) kv_push(uint32_t, *b1, av[k].v); + } + if(se) break; + } + + if(f[v] && f[v^1] && (!fsk[v>>1])) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (k = o = 0; k < nv; k++) { + if(av[k].del) continue; + if((f[av[k].v^1]) && (f[av[k].v]) && (!fsk[av[k].v>>1]) && (o < av[k].ol)) o = av[k].ol; + } + o0 = o; + + av = asg_arc_a(g, (v^1)); nv = asg_arc_n(g, (v^1)); + for (k = o = 0; k < nv; k++) { + if(av[k].del) continue; + if((f[av[k].v^1]) && (f[av[k].v]) && (!fsk[av[k].v>>1]) && (o < av[k].ol)) o = av[k].ol; + } + o1 = o; + + if(o0 + o1 < g->seq[v>>1].len) tot += g->seq[v>>1].len - o0 - o1; + } + + if(tot > max_path) break; + } + + if((!se) && (tot <= max_path)) return tot; + return (uint64_t)-1; +} + + +/** +uint64_t cal_self_close_tang_flank0_back(asg_t *g, uint32_t v0, uint32_t s0, uint32_t e0, uint64_t sf, uint64_t ef, asg32_v *b1, asg32_v *b2, uint8_t *f, uint8_t *fs, uint64_t max_path, uint64_t tot) +{ + if(f[v0]) return tot; + uint64_t se = 0, k, v, o, o0, o1, nv; asg_arc_t *av; + + b1->n = 0; kv_push(uint32_t, *b1, v0); + while(b1->n) { + v = b1->a[--b1->n]; + if(f[v] && f[v^1]) continue; + + o0 = o1 = 0; + + o = 0; + if((v != e0) && (v != (s0^1)) && (!f[v])) { + if((fs[v] != ef) && (fs[v^1] != sf)) { + f[v] = 1; kv_push(uint32_t, *b2, v); + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (k = o = 0; k < nv; k++) { + if(av[k].del) continue; + if((av[k].v == s0) || (av[k].v == (e0^1))) { + se = 1; break; + } + if((fs[av[k].v] != ef) && (fs[av[k].v^1] != sf)) { + if(f[av[k].v^1]) { + if((!fs[av[k].v]) && (!fs[av[k].v^1]) && (o < av[k].ol)) o = av[k].ol; + continue; + } + kv_push(uint32_t, *b1, av[k].v); + } + } + if(se) break; + } + } + o0 = o; + + v = v^1; + o = 0; + if((v != e0) && (v != (s0^1)) && (!f[v])) { + if((fs[v] != ef) && (fs[v^1] != sf)) { + f[v] = 1; kv_push(uint32_t, *b2, v); + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (k = o = 0; k < nv; k++) { + if(av[k].del) continue; + if((av[k].v == s0) || (av[k].v == (e0^1))) { + se = 1; break; + } + if((fs[av[k].v] != ef) && (fs[av[k].v^1] != sf)) { + if(f[av[k].v^1]) { + if((!fs[av[k].v]) && (!fs[av[k].v^1]) && (o < av[k].ol)) o = av[k].ol; + continue; + } + kv_push(uint32_t, *b1, av[k].v); + } + } + if(se) break; + } + } + o1 = o; + + if((!fs[v]) && (!fs[v^1]) && f[v] && f[v^1] && (o0 + o1 < g->seq[z].len)) { + tot += g->seq[z].len - o0 - o1; + } + if(tot > max_path) break; + } + + if((!se) && (tot <= max_path)) return tot; + return (uint64_t)-1; +} + +uint64_t cal_self_close_tang_flank1(asg_t *g, uint32_t *s, uint32_t sn, uint32_t *e, uint32_t en, uint32_t s0, uint32_t e0, uint64_t sf, uint64_t ef, asg32_v *b1, asg32_v *b2, uint8_t *f, uint8_t *fs, uint64_t max_path, uint64_t tot) +{ + uint64_t k, sk, ek; + for (k = 0, sk = (uint64_t)-1; (k < sn) && (!f[s[k]]) && (!f[s[k]^1]); k++); if(k < sn) sk = k; + for (k = 0, ek = (uint64_t)-1; (k < en) && (!f[e[en-k-1]]) && (!f[e[en-k-1]^1]); k++); if(k < en) ek = en-k-1; + if(sk != (uint64_t)-1) { + for (k = sk + 1; k < sn; k++) fs[s[k]] = 0; + } + if(ek != (uint64_t)-1) { + for (k = ek + 1; k < en; k++) fs[e[en-k-1]] = 0; + } + + if(sk != (uint64_t)-1) { + for (k = sk + 1; k < sn; k++) { + if((!fs[s[k]])) { + if(f[s[k]]) cal_self_close_tang_flank0(g, s[k], s0, e0, sf, ef, b1, b2, f, fs, max_path, tot); + + } + } + } + +} +**/ + + +uint64_t trace_back_tangle_dis(asg_t *g, uint32_t *s, uint32_t *sd, uint32_t sn, uint32_t *e, uint32_t *ed, uint32_t en, asg32_v *b, asg32_v *b1, asg32_v *b2, uint8_t *f, uint8_t *fs, uint8_t *fsk, uint64_t sf, uint64_t ef, uint64_t max_path, uint64_t *is_dip) +{ + uint64_t k, sk, sm, ek, em, s0, slen, e0, elen, tot; b->n = 0; (*is_dip) = 0; + for (sk = sm = 0; sk < sn; sk++) { + if((fs[s[sn-sk-1]] == sf) && (f[s[sn-sk-1]]) && (!f[s[sn-sk-1]^1])) {///a potiential + kv_push(uint32_t, *b, sn-sk-1); sm++; + } + } + if(!sm) return ((uint64_t)-1); + + for (ek = em = 0; ek < en; ek++) { + if((fs[e[ek]] == ef) && (!f[e[ek]]) && (f[e[ek]^1])) {///a potiential + kv_push(uint32_t, *b, ek); em++; + } + } + if(!em) return ((uint64_t)-1); + + uint32_t *si = b->a, *ei = b->a + sm; + for (sk = 0; sk < sm; sk++) { + s0 = s[si[sk]]; slen = sd[si[sk]]; + for (ek = 0; ek < em; ek++) { + e0 = e[ei[ek]]; elen = ed[ei[ek]]; + for (k = 0; k < b2->n; k++) f[b2->a[k]] = 0; + + tot = cal_self_close_tang_flank1(g, s0, e0, b1, b2, f, fsk, max_path + slen + elen); + if((tot != ((uint64_t)-1)) && (tot <= (max_path + slen + elen))) { + if(fsk[s0>>1] && fsk[e0>>1]) { + (*is_dip) = 1; + return 0; + } else { + return ((tot>=(slen + elen))?(tot-(slen + elen)):(0)); + } + } + } + } + return ((uint64_t)-1); +} + +uint64_t cal_self_close_tang_flank(asg_t *g, uint32_t *s, uint32_t *sd, uint32_t sn, uint32_t *e, uint32_t *ed, uint32_t en, asg32_v *b1, asg32_v *b2, asg32_v *b3, uint8_t *f, uint8_t *fs, uint8_t *fsk, uint64_t max_path, uint64_t *is_dip) +{ + (*is_dip) = 0; + if((!sn) || (!en)) return (uint64_t)-1; + + uint64_t z, k, tot, sf = 1, ef = 2, s0, e0; + for (k = 0; k < sn; k++) { + assert(!(fs[s[k]])); fs[s[k]] = sf; + } + s0 = s[0]; + + for (k = 0; k < en; k++) { + assert(!(fs[e[k]])); fs[e[k]] = ef; + } + e0 = e[en-1]; + + b1->n = 0; b2->n = 0; tot = ((uint64_t)-1); + for (k = 0; k < sn; k++) { + if(fs[s[sn-k-1]] != sf) continue; + tot = cal_self_close_tang_flank0(g, s[sn-k-1], s0, e0, sf, ef, b1, b2, f, fs, max_path); + if((tot == ((uint64_t)-1)) || (tot > max_path)) { + tot = ((uint64_t)-1); break; + } else { + tot = trace_back_tangle_dis(g, s, sd, sn, e, ed, en, b3, b1, b2, f, fs, fsk, sf, ef, max_path, is_dip); + if(tot != ((uint64_t)-1)) break; + } + + ///reset s && e + for (z = 0; z < sn; z++) fs[s[z]] = sf; + for (z = 0; z < en; z++) fs[e[z]] = ef; + for (z = 0; z < b2->n; z++) f[b2->a[z]] = 0; + } + + for (k = 0; k < sn; k++) fs[s[k]] = 0; + for (k = 0; k < en; k++) fs[e[k]] = 0; + for (k = 0; k < b2->n; k++) f[b2->a[k]] = 0; + + return tot; +} + + +void prt_scf_dbg_nds(u_trans_t *z, uint32_t *za, uint32_t *zd, uint32_t zn, ma_ug_t *ref, ma_ug_t *hu1, ma_ug_t *hu2, uint64_t s_end, uint64_t e_end, const char *cmd) +{ + uint64_t k, id, rev, ui, uid; ma_utg_t *u; + + id = z->tn; rev = z->rev; + u = ((idu.n)?&(hu1->u.a[id]):&(hu2->u.a[id-hu1->u.n])); + ui = ((idu.n)?1:2); uid = ((idu.n)?(id):(id-hu1->u.n)); + + fprintf(stderr, "\nCMD::%s[M::%s] h%lutg%.6lu%c(%c)\ts::%u\te::%u\ts_end::%lu\te_end::%lu\tref_n::%u\n", cmd, __func__, + ui, uid+1, "lc"[u->circ], "+-"[rev], z->ts, z->te, s_end, e_end, (uint32_t)ref->u.n); + for (k = 0; k < zn; k++) { + fprintf(stderr, "[%u|%u]", (za[k]>>1), (za[k]&1)); + fprintf(stderr, "utg%.6u%c(%c)(d::%u),", (za[k]>>1)+1, "lc"[ref->u.a[(za[k]>>1)].circ], "+-"[za[k]&1], zd[k]); + } + fprintf(stderr, "\n"); +} + + +uint64_t is_small_tangle(u_trans_t *s, u_trans_t *e, ma_ug_t *ref, ma_ug_t *hu1, ma_ug_t *hu2, scaf_res_t *cp1, scaf_res_t *cp2, asg32_v *b1, asg32_v *b2, asg32_v *b3, asg32_v *b4, uint8_t *f, uint8_t *fs, uint8_t *fsk, uint64_t max_len, uint64_t *is_dip) +{ + uint64_t tot; uint32_t *va = NULL, *vd = NULL, *wa = NULL, *wd = NULL, vn = 0, wn = 0; + b1->n = b2->n = b3->n = b4->n = 0; (*is_dip) = 0; + // v = get_ref_nid(s, hu1, hu2, cp1, cp2, 1, 1000); if(v == ((uint64_t)-1)) return ((uint64_t)-1); + // w = get_ref_nid(e, hu1, hu2, cp1, cp2, 0, 1000); if(w == ((uint64_t)-1)) return ((uint64_t)-1); + // if((v>>1) == (w>>1)) return ((uint64_t)-1); + + // fprintf(stderr, "-0-[M::%s]\n", __func__); + vn = get_ref_nid_flank(s, ref, hu1, hu2, cp1, cp2, 1, 1000, max_len, b3); if(!vn) return ((uint64_t)-1); + // fprintf(stderr, "-1-[M::%s]\n", __func__); + wn = get_ref_nid_flank(e, ref, hu1, hu2, cp1, cp2, 0, 1000, max_len, b3); if(!wn) return ((uint64_t)-1); + // fprintf(stderr, "-2-[M::%s]\n", __func__); + va = b3->a; vd = va + vn; wa = vd + vn; wd = wa + wn; + // prt_scf_dbg_nds(s, va, vd, vn, ref, hu1, hu2, 0, 1, "rawS"); + // prt_scf_dbg_nds(e, wa, wd, wn, ref, hu1, hu2, 1, 0, "rawE"); + dedup_tang_flank(va, vd, &vn, wa, wd, &wn); + if((!vn) || (!wn)) return ((uint64_t)-1); + // prt_scf_dbg_nds(s, va, vd, vn, ref, hu1, hu2, 0, 1, "fffS"); + // prt_scf_dbg_nds(e, wa, wd, wn, ref, hu1, hu2, 1, 0, "fffE"); + + tot = cal_self_close_tang_flank(ref->g, va, vd, vn, wa, wd, wn, b1, b2, b4, f, fs, fsk, max_len, is_dip); + if(tot > max_len) tot = ((uint64_t)-1); + return tot; + + // l0 = cal_self_close_tang(ref->g, v, w, b1, b2, f, max_len); if(l0 == ((uint64_t)-1)) return ((uint64_t)-1); + // l1 = cal_self_close_tang(ref->g, w^1, v^1, b1, b2, f, max_len); if(l1 == ((uint64_t)-1)) return ((uint64_t)-1); + // return MIN(l0, l1); +} + + +uint32_t gen_scaf_path_lst(asg_t *g, uint32_t s, asg64_v *b, uint64_t *blen, uint64_t *bf) +{ + + uint32_t v = s, w = 0; uint64_t m, c1 = 0, c2 = 0; + uint32_t kv, kw; (*blen) = 0; (*bf) = 0; + + while (1) { + kv = get_arcs(g, v, &w, 1); + m = v; + if(kv == 1) m |= ((uint64_t)(g->arc[w].ol))<<32; + kv_push(uint64_t, *b, m); + (*blen) += g->seq[v>>1].len + ((kv == 1)?g->arc[w].ol:0); + if(g->seq[v>>1].c == 1) c1++; + else if(g->seq[v>>1].c == 2) c2++; + + if(kv == 0) {(*bf) = (c1>=c2?1:2); return END_TIPS;} + if(kv == 2) {(*bf) = (c1>=c2?1:2); return TWO_OUTPUT;} + if(kv > 2) {(*bf) = (c1>=c2?1:2); return MUL_OUTPUT;} + w = g->arc[w].v; + ///up to here, kv=1 + ///kw must >= 1 + kw = get_arcs(g, w^1, NULL, 0); + v = w; + + if(kw == 2) {(*bf) = (c1>=c2?1:2); return TWO_INPUT;} + if(kw > 2) {(*bf) = (c1>=c2?1:2); return MUL_INPUT;} + if(v == s) {(*bf) = (c1>=c2?1:2); return LOOP;} + } + + (*bf) = (c1>=c2?1:2); + return LONG_TIPS; +} + +uint64_t prt_gen_scaf_path_lst(uint64_t *a, uint64_t n, uint64_t is_circle, ma_ug_t *hu1, ma_ug_t *hu2) +{ + uint64_t k, nl, el, tl, id, rev, ui, uid; ma_utg_t *u; + for (k = nl = el = tl = 0; k < n; k++) { + nl += (a[k]>>32); id = ((uint32_t)a[k])>>1; + u = ((idu.n)?&(hu1->u.a[id]):&(hu2->u.a[id-hu1->u.n])); + el += u->len; + } + tl = el + nl; + fprintf(stderr, "[M::%s]tot::%lu\tel::%lu\tnl::%lu\tis_c::%lu\t#::%lu\t%s\n", __func__, tl, el, nl, is_circle, n, ((n>1)?"scf":"ctg")); + for (k = 0; k < n; k++) { + id = ((uint32_t)a[k])>>1; rev = ((uint32_t)a[k])&1; + u = ((idu.n)?&(hu1->u.a[id]):&(hu2->u.a[id-hu1->u.n])); + ui = ((idu.n)?1:2); nl = (a[k]>>32); + uid = ((idu.n)?(id):(id-hu1->u.n)); + fprintf(stderr, "[M::%s] h%lutg%.6lu%c(%c)\tlen::%u\tNs::%lu\n", __func__, + ui, uid+1, "lc"[u->circ], "+-"[rev], u->len, nl); + } + return tl; +} + +void cal_arr_N50(uint32_t *a, uint32_t n, const char *cmd) +{ + uint64_t i, s, len; + for (i = len = 0; i < n; i++) len += a[i]; + radix_sort_arch32(a, a + n); + + i = n; s = 0; + while (i > 0) { + s += a[--i]; + if(s >= (len>>1)) { + fprintf(stderr, "CMD::%s[M::%s::] N50: %u, Size::%lu\n", cmd, __func__, a[i], len); + break; + } + } +} + +void set_fsk(uint8_t *fsk, uint8_t mm, ul_vec_t *idx) +{ + uint64_t k, m, a_n; uc_block_t *a; + for (k = 0; k < idx->bb.n; k++) { + a = idx->bb.a + idx->bb.a[k].ts; a_n = idx->bb.a[k].te - idx->bb.a[k].ts; + for(m = 0; m < a_n; m++) fsk[a[m].hid] = mm; + } +} + +// void exchange_utgs(kvect_sec_t *i1, kvect_sec_t *i2, asg32_v *b0, asg_t *mg) +// { +// kvect_sec_t *sc = NULL; uint32_t *srt[2], *idx = NULL, srt_n[2], k, z; sec_t *scp; +// kv_resize(uint32_t, (*b0), (((uint32_t)(mg->n_seq)*2))); idx = b0->a + mg->n_seq; + +// sc = i1; srt[0] = b0->a; srt_n[0] = 0; +// for (k = 0; k < sc->n; k++) { +// scp = &(sc->a[k]); +// for (z = 0; z < scp->n; z++) { +// srt[0][srt_n[0]++] = ((uint32_t)scp->a[z])>>1; +// } +// } + + +// sc = i2; srt[1] = srt[0] + srt_n[0]; srt_n[1] = 0; +// for (k = 0; k < sc->n; k++) { +// scp = &(sc->a[k]); +// for (z = 0; z < scp->n; z++) { +// srt[1][srt_n[1]++] = ((uint32_t)scp->a[z])>>1; +// } +// } + +// assert(srt_n[0] + srt_n[1] == mg->n_seq); + +// radix_sort_arch32(srt[0], srt[0] + srt_n[0]); + + + +// radix_sort_arch32(srt[1], srt[1] + srt_n[1]); +// } + + +void gen_double_scaffold_gfa(ma_ug_t *ref, ma_ug_t *hu1, ma_ug_t *hu2, scaf_res_t *cp1, scaf_res_t *cp2, asg_t *sg, kv_u_trans_t *os, int64_t minNs, kvect_sec_t **sc1, kvect_sec_t **sc2) +{ + order_contig_trans(os); + asg_t *g = asg_init(); uint64_t k, s, e, z, rn, pn, dn, rthres = asm_opt.self_scaf_reliable_min, el, glen; ma_utg_t *u, *ut; u_trans_t *p, *d, *r; + asg_arc_t t, *c; int64_t zs, ze, gl, gmin = -asm_opt.self_scaf_gap_max, gmax = asm_opt.self_scaf_gap_max; uint64_t mf, blen, bf, is_dip; uint32_t sce[2]; sce[0] = 0; sce[1] = 1; + asg32_v b0, b1, b2, b3; kv_init(b0); kv_init(b1); kv_init(b2); kv_init(b3); uint8_t *f, *fs, *fsk; CALLOC(f, (ref->u.n<<1)); CALLOC(fs, (ref->u.n<<1)); CALLOC(fsk, ref->u.n); + + // fprintf(stderr, "[M::%s::] SSS\n", __func__); + for (k = 0; k < os->idx.n; ++k) { + u = ((ku.n)?&(hu1->u.a[k]):&(hu2->u.a[k-hu1->u.n])); + asg_seq_set(g, k, u->len, 0); g->seq[k].c = (ku.n?1:2); + } + + // fprintf(stderr, "[M::%s::] MMM\n", __func__); + for (k = 0; k < os->idx.n; ++k) { + + r = u_trans_a(*os, k); rn = u_trans_n(*os, k); p = d = NULL; pn = dn = 0; + // fprintf(stderr, "[M::%s::] # k:%lu, rn::%lu\n", __func__, k, rn); + if(rn <= 1) continue; + for (z = 0, p = r; (z < rn) && (!(r[z].del)); z++){;} pn = z; + for (d = r + z; (z < rn) && (r[z].qs != ((uint32_t)-1)); z++){;} dn = z - pn; + // fprintf(stderr, "[M::%s::] # k:%lu, pn::%lu, dn::%lu\n", __func__, k, pn, dn); + if(pn <= 1) continue;///no scaf + s = e = (uint64_t)-1; + for (z = 0; z < pn; z++) { + if((p[z].f) || (((p[z].qe-p[z].qs) >= rthres) && ((p[z].te-p[z].ts) >= rthres))) { + s = e = z; break; + } + } + for (; z < pn; z++) { + if((p[z].f) || (((p[z].qe-p[z].qs) >= rthres) && ((p[z].te-p[z].ts) >= rthres))) e = z; + } + // fprintf(stderr, "[M::%s::] # k:%lu, s::%lu, e::%lu\n", __func__, k, s, e); + ///[s, e] + u = ((ku.n)?&(hu1->u.a[k]):&(hu2->u.a[k-hu1->u.n])); + set_fsk(fsk, 1, ((ku.n)?&(cp1->a[k]):&(cp2->a[k-hu1->u.n]))); + for (z = 1; z < pn; z++) { + ///cannot scaffold circles + ut = ((p[z-1].tnu.n)?&(hu1->u.a[p[z-1].tn]):&(hu2->u.a[p[z-1].tn-hu1->u.n])); if(ut->circ) continue; + ut = ((p[z].tnu.n)?&(hu1->u.a[p[z].tn]):&(hu2->u.a[p[z].tn-hu1->u.n])); if(ut->circ) continue; + // fprintf(stderr, "[M::%s::] # k:%lu, z::%lu, p[z-1].tn::%u, p[z].tn::%u, hu1->u.n::%u, hu2->u.n::%u\n", __func__, k, z, p[z-1].tn, p[z].tn, (uint32_t)hu1->u.n, (uint32_t)hu2->u.n); + + el = 0; gl = 0; + if((sce[(p[z-1].tnu.n)?0:1] != sce[(p[z-1].qnu.n)?0:1]) && (sce[(p[z].tnu.n)?0:1] != sce[(p[z].qnu.n)?0:1])) {///tn and qn come from different haplotypes + if((((z-1)>=s)&&((z-1)<=e))&&(((z)>=s)&&((z)<=e))) el = 1; + // fprintf(stderr, "-0-[M::%s::] # k::%lu, z::%lu, el::%lu\n", __func__, k, z, el); + if(el) { + zs = MAX(p[z-1].qs, p[z].qs); + ze = MIN(p[z-1].qe, p[z].qe); + if(is_noisy_ov(MIN(zs, ze), MAX(zs, ze), u->len, 2500000, 0.5, d, dn)) el = 0; + // fprintf(stderr, "-1-[M::%s::] # k::%lu, z::%lu, el::%lu, zs::%ld, ze::%ld\n", __func__, k, z, el, zs, ze); + if(el) { + gl = zs - ze; + if((!(p[z-1].f)) || (!(p[z].f))) { + if(gl >= gmin && gl <= gmax) el = 1; + else el = 0;///gap is too long + } else if(p[z-1].f && p[z].f) { + if(gl <= gmax) el = 1; ///p[z-1] and p[z] are too far away is bad; p[z-1] and p[z] are overlapped is fine + else el = 0; + } + } + // fprintf(stderr, "-2-[M::%s::] # k::%lu, z::%lu, el::%lu, zs::%ld, ze::%ld, p[z-1].f::%u, p[z].f::%u, gmin::%ld, gmax::%ld\n", __func__, k, z, el, zs, ze, p[z-1].f, p[z].f, gmin, gmax); + } + ///final try in graph + // fprintf(stderr, "[M::%s::] # k::%lu, z::%lu, el::%lu, gl::%ld\n", __func__, k, z, el, gl); + is_dip = 0; + + glen = is_small_tangle(&(p[z-1]), &(p[z]), ref, hu1, hu2, cp1, cp2, &b0, &b1, &b2, &b3, f, fs, fsk, 5000000, &is_dip); + // fprintf(stderr, "[M::%s::] # k::%lu, z::%lu, el::%lu, glen::%lu, gl::%ld\n", __func__, k, z, el, glen, gl); + if((glen != (uint64_t)-1) && (((int64_t)glen) <= asm_opt.self_scaf_gap_max)) { + el = 1; if(!is_dip) gl = glen; + } + } + if(gl < minNs) gl = minNs; + if(el) { + ///in anyway the gap cannot be too large + if(gl <= gmax) el = 1; ///p[z-1] and p[z] are too far away is bad; p[z-1] and p[z] are overlapped is fine + else el = 0; + } + + scaf_hit2arc(&(p[z-1]), &(p[z]), 0, el, gl, &t); + c = asg_arc_pushp(g); *c = t; + scaf_hit2arc(&(p[z]), &(p[z-1]), 1, el, gl, &t); + c = asg_arc_pushp(g); *c = t; + } + set_fsk(fsk, 0, ((ku.n)?&(cp1->a[k]):&(cp2->a[k-hu1->u.n]))); + } + asg_cleanup(g); asg_symm(g); + // fprintf(stderr, "[M::%s::] EEE\n", __func__); + + uint64_t v, n_vtx = g->n_seq<<1, nv; asg_arc_t *av; + for (v = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + nv = asg_arc_n(g, v); + if(nv <= 1) continue; + av = asg_arc_a(g, v); + for(k = 0; k < nv; k++) { + if(av[k].del) continue; + av[k].del = 1; + asg_arc_del(g, av[k].v^1, (av[k].ul>>32)^1, 1); + } + } + for (k = 0; k < g->n_arc; k++) { + if(!(g->arc[k].el)) g->arc[k].del = 1; + } + asg_cleanup(g); + + if((ref->u.n<<1) < g->n_seq) REALLOC(f, g->n_seq); + memset(f, 0, sizeof((*f))*g->n_seq); + asg64_v b64; kv_init(b64); kvect_sec_t *i1 = NULL, *i2 = NULL, *im = NULL; uint64_t len[2];///, mmip; + sec_t *mmi; CALLOC(i1, 1); CALLOC(i2, 1); ///i1->ctg = hu1; i2->ctg = hu2; + + b0.n = 0; ///mmip = hu1->u.n; mmip <<= 1; + for (v = 0; v < n_vtx; ++v) { + nv = asg_arc_n(g, v); assert(nv <= 1); + if(f[v>>1]) continue; + if(asg_arc_n(g, (v^1)) != 0) continue; + b64.n = 0; mf = gen_scaf_path_lst(g, v, &b64, &blen, &bf); + assert(mf == END_TIPS); + // rn = prt_gen_scaf_path_lst(b64.a, b64.n, (mf==LOOP)?1:0, hu1, hu2); kv_push(uint32_t, b0, rn); + for (k = len[0] = len[1] = 0; k < b64.n; k++) { + f[((uint32_t)b64.a[k])>>1] = 1; + len[g->seq[((uint32_t)b64.a[k])>>1].c-1] += g->seq[((uint32_t)b64.a[k])>>1].len; + } + im = ((len[0] >= len[1])?i1:i2); kv_pushp(sec_t, (*im), &mmi); memset(mmi, 0, sizeof((*mmi))); + mmi->is_c = 0; mmi->n = mmi->m = b64.n; MALLOC(mmi->a, mmi->n); memcpy(mmi->a, b64.a, sizeof((*(mmi->a)))*mmi->n); + // for (k = 0; k < mmi->n; k++) { ///scaffold bug + // if((((uint32_t)mmi->a[k])>>1) >= hu1->u.n) mmi->a[k] -= mmip; + // } + } + + for (v = 0; v < n_vtx; ++v) { + nv = asg_arc_n(g, v); assert(nv <= 1); + if(f[v>>1]) continue; + assert((nv == 1) && (asg_arc_n(g, (v^1)) == 1)); + b64.n = 0; mf = gen_scaf_path_lst(g, v, &b64, &blen, &bf); + assert(mf == LOOP); + // rn = prt_gen_scaf_path_lst(b64.a, b64.n, (mf==LOOP)?1:0, hu1, hu2); kv_push(uint32_t, b0, rn); + for (k = len[0] = len[1] = 0; k < b64.n; k++) { + f[((uint32_t)b64.a[k])>>1] = 1; + len[g->seq[((uint32_t)b64.a[k])>>1].c-1] += g->seq[((uint32_t)b64.a[k])>>1].len; + } + im = ((len[0] >= len[1])?i1:i2); + im = ((len[0] >= len[1])?i1:i2); kv_pushp(sec_t, (*im), &mmi); memset(mmi, 0, sizeof((*mmi))); + mmi->is_c = 1; mmi->n = mmi->m = b64.n; MALLOC(mmi->a, mmi->n); memcpy(mmi->a, b64.a, sizeof((*(mmi->a)))*mmi->n); + // for (k = 0; k < mmi->n; k++) { ///scaffold bug + // if((((uint32_t)mmi->a[k])>>1) >= hu1->u.n) mmi->a[k] -= mmip; + // } + } + kv_destroy(b64); + // cal_arr_N50(b0.a, b0.n, "Scf"); + + // b1.n = 0; + // for(k = 0; k < hu1->u.n; k++) kv_push(uint32_t, b1, hu1->u.a[k].len); + // for(k = 0; k < hu2->u.n; k++) kv_push(uint32_t, b1, hu2->u.a[k].len); + // cal_arr_N50(b1.a, b1.n, "Ctg"); + + kv_destroy(b0); kv_destroy(b1); kv_destroy(b2); kv_destroy(b3); free(f); free(fs); free(fsk); asg_destroy(g); + (*sc1) = i1; (*sc2) = i2; +} + +kv_u_trans_t *gen_shallow_ref_trans(bubble_type *bu, scaf_res_t *cp0, scaf_res_t *cp1, asg_t *sg, ma_ug_t *ref, ma_sub_t* cover, ma_hit_t_alloc* src, ma_hit_t_alloc* rev, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, bub_label_t* b_mask_t) +{ + kvec_asg_arc_t_warp ne; kv_init(ne.a); kv_u_trans_t *p = NULL; CALLOC(p, 1); + ma_ug_t *cref = gen_shallow_clean_ug(ref, bu, cp0, cp1); + asg_t *csg = copy_read_graph(sg); hap_cov_t *cov = NULL; ne.a.n = 0; + + adjust_utg_by_primary(&cref, csg, TRIO_THRES, src, rev, cover, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, &ne, &cov, b_mask_t, 0, 0); + + ma_ug_destroy(cref); asg_destroy(csg); kv_destroy(ne.a); + p->n = cov->t_ch->k_trans.n; p->m = cov->t_ch->k_trans.m; p->a = cov->t_ch->k_trans.a; + p->idx.n = cov->t_ch->k_trans.idx.n; p->idx.m = cov->t_ch->k_trans.idx.m; p->idx.a = cov->t_ch->k_trans.idx.a; + cov->t_ch->k_trans.n = cov->t_ch->k_trans.m = 0; cov->t_ch->k_trans.a = NULL; + cov->t_ch->k_trans.idx.n = cov->t_ch->k_trans.idx.m = 0; cov->t_ch->k_trans.idx.a = NULL; + destory_hap_cov_t(&cov); + return p; +} + +kv_u_trans_t *gen_deep_ref_trans(kv_u_trans_t *in, scaf_res_t *cp0, scaf_res_t *cp1, asg_t *sg, ma_ug_t *ref, ma_sub_t* cover, ma_hit_t_alloc* src, ma_hit_t_alloc* rev, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, bub_label_t* b_mask_t, ug_opt_t *opt) +{ + kvec_asg_arc_t_warp ne; kv_init(ne.a); kv_u_trans_t *p = NULL; CALLOC(p, 1); + ma_ug_t *cref = gen_clean_ug(ref, cp0, cp1); ma_ug_t *ccref = copy_untig_graph(cref); + asg_t *csg = copy_read_graph(sg); hap_cov_t *cov = NULL; ne.a.n = 0; + // print_debug_gfa(sg, cref, cover, "cl.sb.utg", src, ruIndex, opt->max_hang, opt->min_ovlp, 0, 0, 0); + + adjust_utg_by_primary(&cref, csg, TRIO_THRES, src, rev, cover, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, &ne, &cov, b_mask_t, 1, 0); + + ma_ug_destroy(cref); asg_destroy(csg); kv_destroy(ne.a); + if(in) { + kv_resize(u_trans_t, cov->t_ch->k_trans, cov->t_ch->k_trans.n + in->n); + memcpy(cov->t_ch->k_trans.a + cov->t_ch->k_trans.n, in->a, (in->n*sizeof((*(in->a))))); + cov->t_ch->k_trans.n += in->n; + clean_u_trans_t_idx_filter_adv(&(cov->t_ch->k_trans), ref, sg, 0.6, 1);///select best overlap for each pair of contigs + } + + filter_u_trans(&(cov->t_ch->k_trans), asm_opt.is_bub_trans, asm_opt.is_topo_trans, asm_opt.is_read_trans, asm_opt.is_base_trans); + if(asm_opt.is_base_trans) { + ma_ug_seq(ccref, sg, cover, src, NULL, max_hang, min_ovlp, NULL, 0);///polish + trans_base_infer(ccref, sg, opt, &(cov->t_ch->k_trans), NULL); + ma_ug_destroy(ccref); + } + clean_u_trans_t_idx_filter_adv(&(cov->t_ch->k_trans), ref, sg, 0.6, 0); + + p->n = cov->t_ch->k_trans.n; p->m = cov->t_ch->k_trans.m; p->a = cov->t_ch->k_trans.a; + p->idx.n = cov->t_ch->k_trans.idx.n; p->idx.m = cov->t_ch->k_trans.idx.m; p->idx.a = cov->t_ch->k_trans.idx.a; + cov->t_ch->k_trans.n = cov->t_ch->k_trans.m = 0; cov->t_ch->k_trans.a = NULL; + cov->t_ch->k_trans.idx.n = cov->t_ch->k_trans.idx.m = 0; cov->t_ch->k_trans.idx.a = NULL; + destory_hap_cov_t(&cov); + return p; +} + +ma_ug_t *merge_utgs(ma_ug_t *in0, ma_ug_t *in1) +{ + uint64_t k, m[2]; ma_utg_t *su = NULL, *du = NULL; + m[0] = ((uint64_t)(in0->g->n_seq))<<1; + m[1] = ((uint64_t)(in0->g->n_seq))<<33; + ma_ug_t *ug = NULL; CALLOC(ug, 1); ug->g = asg_init(); + ug->g->n_F_seq = in0->g->n_F_seq + in1->g->n_F_seq; + ug->g->r_seq = in0->g->r_seq + in1->g->r_seq; + ug->g->m_seq = ug->g->n_seq = in0->g->n_seq + in1->g->n_seq; + MALLOC(ug->g->seq, ug->g->n_seq); + memcpy(ug->g->seq, in0->g->seq, sizeof((*(ug->g->seq)))*in0->g->n_seq); + memcpy(ug->g->seq+in0->g->n_seq, in1->g->seq, sizeof((*(ug->g->seq)))*in1->g->n_seq); + + ug->g->m_arc = ug->g->n_arc = in0->g->n_arc + in1->g->n_arc; + MALLOC(ug->g->arc, ug->g->n_arc); + memcpy(ug->g->arc, in0->g->arc, sizeof((*(ug->g->arc)))*in0->g->n_arc); + for(k = 0; k < in1->g->n_arc; k++) { + ug->g->arc[k+in0->g->n_arc] = in1->g->arc[k]; + ug->g->arc[k+in0->g->n_arc].v += m[0]; + ug->g->arc[k+in0->g->n_arc].ul += m[1]; + } + asg_cleanup(ug->g); asg_symm(ug->g); + + ug->u.m = ug->u.n = in0->u.n + in1->u.n; + MALLOC(ug->u.a, ug->u.n); + for (k = 0; k < in0->u.n; k++) { + su = &(in0->u.a[k]); du = &(ug->u.a[k]); + (*du) = (*su); + du->s = NULL; du->a = NULL; du->m = du->n = su->n; + MALLOC(du->a, du->n); memcpy(du->a, su->a, sizeof((*(du->a)))*du->n); + } + for (k = 0; k < in1->u.n; k++) { + su = &(in1->u.a[k]); du = &(ug->u.a[k + in0->u.n]); + (*du) = (*su); + du->s = NULL; du->a = NULL; du->m = du->n = su->n; + MALLOC(du->a, du->n); memcpy(du->a, su->a, sizeof((*(du->a)))*du->n); + } + + return ug; +} + +scaf_res_t *merge_scaf_res(scaf_res_t *in0, scaf_res_t *in1) +{ + uint64_t k; ul_vec_t *m; ul_vec_t *s; + scaf_res_t *p = NULL; CALLOC(p, 1); + p->n = p->m = in0->n + in1->n; + CALLOC(p->a, p->n); + for(k = 0; k < in0->n; k++) { + m = &(p->a[k]); s = &(in0->a[k]); + *m = *s; + + m->r_base.a = NULL; + if(m->r_base.m) { + MALLOC(m->r_base.a, m->r_base.m); + memcpy(m->r_base.a, s->r_base.a, sizeof((*(m->r_base.a)))*m->r_base.m); + } + + m->bb.a = NULL; + if(m->bb.m) { + MALLOC(m->bb.a, m->bb.m); + memcpy(m->bb.a, s->bb.a, sizeof((*(m->bb.a)))*m->bb.m); + } + + m->N_site.a = NULL; + if(m->N_site.m) { + MALLOC(m->N_site.a, m->N_site.m); + memcpy(m->N_site.a, s->N_site.a, sizeof((*(m->N_site.a)))*m->N_site.m); + } + } + + for(k = 0; k < in1->n; k++) { + m = &(p->a[k + in0->n]); s = &(in1->a[k]); + *m = *s; + + m->r_base.a = NULL; + if(m->r_base.m) { + MALLOC(m->r_base.a, m->r_base.m); + memcpy(m->r_base.a, s->r_base.a, sizeof((*(m->r_base.a)))*m->r_base.m); + } + + m->bb.a = NULL; + if(m->bb.m) { + MALLOC(m->bb.a, m->bb.m); + memcpy(m->bb.a, s->bb.a, sizeof((*(m->bb.a)))*m->bb.m); + } + + m->N_site.a = NULL; + if(m->N_site.m) { + MALLOC(m->N_site.a, m->N_site.m); + memcpy(m->N_site.a, s->N_site.a, sizeof((*(m->N_site.a)))*m->N_site.m); + } + } + + return p; +} + +kv_u_trans_t *gen_contig_trans_func(ma_ug_t *ref, ma_ug_t *hu0, ma_ug_t *hu1, scaf_res_t *cp0, scaf_res_t *cp1, asg_t *sg, bubble_type *bu, ug_opt_t *opt, kv_u_trans_t *bd, uint8_t is_sep, ma_ug_t **rmg, scaf_res_t **rms) +{ + + kv_u_trans_t *os; CALLOC(os, 1); + if(is_sep) { + gen_contig_trans(opt, sg, hu1, cp1, hu0, cp0, ref, bd, hu0->u.n, 0, bu, os); + gen_contig_trans(opt, sg, hu0, cp0, hu1, cp1, ref, bd, 0, hu0->u.n, bu, os); + } else { + ma_ug_t *mg = merge_utgs(hu0, hu1); scaf_res_t *ms = merge_scaf_res(cp0, cp1); + gen_contig_self(opt, sg, mg, ms, ref, bd, hu0->u.n, bu, os, 0); + if(!rmg) ma_ug_destroy(mg); + else (*rmg) = mg; + if(!rms) destroy_scaf_res_t(ms); + else (*rms) = ms; + } + + kt_u_trans_t_idx(os, hu0->u.n + hu1->u.n); + update_ctg_trans_cc(os); + return os; +} + +inline uint64_t get_scp_len(sec_t *scp, ma_ug_t *mg) +{ + uint64_t k, len; ma_utg_t *z = NULL; + for (k = len = 0; k < scp->n; k++) { + z = &(mg->u.a[((uint32_t)scp->a[k])>>1]); len += z->len; len += (scp->a[k]>>32); + } + + return len; +} + +void gen_scaf_res_via(sec_t *scp, uint64_t scp_len, ma_ug_t *mg, scaf_res_t *ms, ul_vec_t *res) +{ + uint64_t k, off, uid, urev, m, tt, s, e, crn, zi; ma_utg_t *z = NULL; ul_vec_t *ua; uc_block_t *p, *des, *src; + for (k = off = res->bb.n = tt = 0; k < scp->n; k++) { + uid = ((uint32_t)scp->a[k])>>1; urev = ((uint32_t)scp->a[k])&1; + z = &(mg->u.a[uid]); ua = &(ms->a[uid]); + for (m = 0; m < ua->bb.n; m++) { + kv_pushp(uc_block_t, res->bb, &p); memset(p, 0, sizeof((*p))); + + (*p) = ua->bb.a[m]; p->aidx = off; //offset of the whole contig within scaf + p->qs = ua->bb.a[m].qs; p->qe = ua->bb.a[m].qe; + if(urev) { + p->qs = ((z->len>ua->bb.a[m].qe)?(z->len-ua->bb.a[m].qe):(0)); + p->qe = ((z->len>ua->bb.a[m].qs)?(z->len-ua->bb.a[m].qs):(0)); + } + p->qs += off; p->qe += off; + + p->hid = uid; p->hid <<= 1; p->hid |= urev; + if(p->qs >= scp_len) p->qs = scp_len; + if(p->qe >= scp_len) p->qe = scp_len; + if(p->qe <= p->qs) res->bb.n--; + else tt += p->te - p->ts;//how many elements + } + off += z->len; off += (scp->a[k]>>32); + } + + sort_uc_block_qe(res->bb.a, res->bb.n); + kv_resize(uc_block_t, res->bb, res->bb.n + tt); + memset(res->bb.a + res->bb.n, 0, tt * sizeof(*(res->bb.a))); //res->bb.a[0, res->bb.n) -> index; res->bb.a[res->bb.n, res->bb.n + tt) -> details + + + for (k = 0, tt = res->bb.n; k < res->bb.n; k++) { + s = tt; e = tt + res->bb.a[k].te - res->bb.a[k].ts; tt = e; off = res->bb.a[k].aidx; + uid = res->bb.a[k].hid>>1; urev = res->bb.a[k].hid&1; z = &(mg->u.a[uid]); + + + src = ms->a[uid].bb.a + res->bb.a[k].ts; + des = res->bb.a + s; crn = e - s; + if(!urev) { + for(zi = 0; zi < crn; zi++) { + des[zi] = src[zi]; + des[zi].qs += off; + des[zi].qe += off; + des[zi].aidx = s; + + if(des[zi].qs >= res->bb.a[k].qe) des[zi].qs = res->bb.a[k].qe; + if(des[zi].qs <= res->bb.a[k].qs) des[zi].qs = res->bb.a[k].qs; + if(des[zi].qe >= res->bb.a[k].qe) des[zi].qe = res->bb.a[k].qe; + if(des[zi].qe <= res->bb.a[k].qs) des[zi].qe = res->bb.a[k].qs; + if(des[zi].qe <= des[zi].qs) des[zi].qe = des[zi].qs; + } + } else { + for(zi = 0; zi < crn; zi++) { + des[zi] = src[zi]; + des[zi].rev = 1 - des[zi].rev; + des[zi].aidx = s; + des[zi].qs = ((z->len>src[zi].qe)?(z->len-src[zi].qe):(0)); + des[zi].qe = ((z->len>src[zi].qs)?(z->len-src[zi].qs):(0)); + des[zi].qs += off; + des[zi].qe += off; + des[zi].aidx = s; + + if(des[zi].qs >= res->bb.a[k].qe) des[zi].qs = res->bb.a[k].qe; + if(des[zi].qs <= res->bb.a[k].qs) des[zi].qs = res->bb.a[k].qs; + if(des[zi].qe >= res->bb.a[k].qe) des[zi].qe = res->bb.a[k].qe; + if(des[zi].qe <= res->bb.a[k].qs) des[zi].qe = res->bb.a[k].qs; + if(des[zi].qe <= des[zi].qs) des[zi].qe = des[zi].qs; + } + } + res->bb.a[k].ts = s; res->bb.a[k].te = e; + + res->bb.a[k].hid = (uint32_t)-1; + } + assert(tt <= res->bb.m); +} + +kv_u_trans_t* cal_scaf_trans(ug_opt_t *opt, ma_ug_t *ref, bubble_type *bu, kv_u_trans_t *bd, asg_t *sg, kvect_sec_t *sc0, kvect_sec_t *sc1, ma_ug_t *mg, scaf_res_t *ms) +{ + ma_ug_t *smg = NULL; scaf_res_t *sms = NULL; uint64_t k; sec_t *u; + ///build ug + CALLOC(smg, 1); + smg->g = asg_init(); + smg->g->m_seq = smg->g->n_seq = sc0->n + sc1->n; MALLOC(smg->g->seq, smg->g->n_seq); + smg->u.m = smg->u.n = sc0->n + sc1->n; CALLOC(smg->u.a, smg->u.n); + for (k = 0; k < smg->g->n_seq; k++) { + smg->g->seq[k].c = 0; smg->g->seq[k].del = 0; + u = ((kn)?&(sc0->a[k]):&(sc1->a[k-sc0->n])); + smg->g->seq[k].len = get_scp_len(u, mg); + smg->u.a[k].len = smg->g->seq[k].len; + } + asg_cleanup(smg->g); asg_symm(smg->g); + + ///build scaf + sms = init_scaf_res_t(sc0->n + sc1->n); + for (k = 0; k < sms->n; k++) { + u = ((kn)?&(sc0->a[k]):&(sc1->a[k-sc0->n])); + gen_scaf_res_via(u, smg->u.a[k].len, mg, ms, &(sms->a[k])); + } + + kv_u_trans_t *p = NULL; CALLOC(p, 1); + gen_contig_self(opt, sg, smg, sms, ref, bd, sc0->n, bu, p, 1); + + kt_u_trans_t_idx(p, sc0->n + sc1->n); + update_ctg_trans_cc(p); + + ma_ug_destroy(smg); + destroy_scaf_res_t(sms); + return p; +} + +inline uint64_t cal_offset_len(double off, double len0, double len1) +{ + return (off*(len1/len0)); +} + +void gen_scaffold_bases(kvect_sec_t *sc0, kvect_sec_t *sc1, ma_ug_t *mg, asg_t *sg, ma_sub_t* cover, ma_hit_t_alloc* src, kvec_asg_arc_t_warp *arcs, int max_hang, int min_ovlp, kv_u_trans_t *p) +{ + if(!p) { + ma_ug_seq(mg, sg, cover, src, arcs, max_hang, min_ovlp, 0, 1); + } else { + uint64_t k, kn, *l0 = NULL, *l1 = NULL, s, e; + kn = sc0->n + sc1->n; + CALLOC(l0, kn); CALLOC(l1, kn); + for (k = 0; k < kn; k++) l0[k] = get_scp_len(((kn)?&(sc0->a[k]):&(sc1->a[k-sc0->n])), mg); + ma_ug_seq(mg, sg, cover, src, arcs, max_hang, min_ovlp, 0, 1); + for (k = 0; k < kn; k++) l1[k] = get_scp_len(((kn)?&(sc0->a[k]):&(sc1->a[k-sc0->n])), mg); + + for (k = 0; k < p->n; k++) { + if(l0[p->a[k].qn] != l1[p->a[k].qn]) { + s = p->a[k].qs; e = p->a[k].qe; + p->a[k].qs = cal_offset_len(s, l0[p->a[k].qn], l1[p->a[k].qn]); + p->a[k].qe = p->a[k].qs + cal_offset_len(((e>s)?(e-s):(0)), l0[p->a[k].qn], l1[p->a[k].qn]); + if(p->a[k].qs > l1[p->a[k].qn]) p->a[k].qs = l1[p->a[k].qn]; + if(p->a[k].qe > l1[p->a[k].qn]) p->a[k].qe = l1[p->a[k].qn]; + } + + if(l0[p->a[k].tn] != l1[p->a[k].tn]) { + s = p->a[k].ts; e = p->a[k].te; + p->a[k].ts = cal_offset_len(s, l0[p->a[k].tn], l1[p->a[k].tn]); + p->a[k].te = p->a[k].ts + cal_offset_len(((e>s)?(e-s):(0)), l0[p->a[k].tn], l1[p->a[k].tn]); + if(p->a[k].ts > l1[p->a[k].tn]) p->a[k].ts = l1[p->a[k].tn]; + if(p->a[k].te > l1[p->a[k].tn]) p->a[k].te = l1[p->a[k].tn]; + } + } + + free(l0); free(l1); + } +} + +void double_scaffold(ma_ug_t *ref, ma_ug_t *hu0, ma_ug_t *hu1, scaf_res_t *cp0, scaf_res_t *cp1, asg_t *sg, ma_sub_t* cover, ma_hit_t_alloc* src, ma_hit_t_alloc* rev, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, bub_label_t* b_mask_t, ug_opt_t *opt, kvect_sec_t **sc0, kvect_sec_t **sc1, ma_ug_t **rmg, kvec_asg_arc_t_warp *arcs, kv_u_trans_t **rs_trans) +{ + bubble_type *bu = NULL; uint8_t *bf = NULL; scaf_res_t *rms = NULL; + bu = gen_bubble_chain(sg, ref, opt, &bf, 0); free(bf); + + kv_u_trans_t *bs = gen_shallow_ref_trans(bu, cp0, cp1, sg, ref, cover, src, rev, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, b_mask_t); + kv_u_trans_t *bd = gen_deep_ref_trans(bs, cp0, cp1, sg, ref, cover, src, rev, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, b_mask_t, opt); + kv_destroy((*bs)); kv_destroy(bs->idx); free(bs); + + kv_u_trans_t *os = gen_contig_trans_func(ref, hu0, hu1, cp0, cp1, sg, bu, opt, bd, 0/**1**/, rmg, (rs_trans?(&rms):(NULL))); + + + // print_ctg_trans_ovlp(os, ref, hu0, cp0, hu1, cp1); + gen_double_scaffold_gfa(ref, hu0, hu1, cp0, cp1, sg, os, 100, sc0, sc1); kv_destroy((*os)); kv_destroy(os->idx); free(os); + + if(rs_trans) { + (*rs_trans) = cal_scaf_trans(opt, ref, bu, bd, sg, *sc0, *sc1, *rmg, rms); + destroy_scaf_res_t(rms); + } + destory_bubbles(bu); free(bu); kv_destroy((*bd)); kv_destroy(bd->idx); free(bd); + + gen_scaffold_bases(*sc0, *sc1, *rmg, sg, cover, src, arcs, max_hang, min_ovlp, ((rs_trans)?(*rs_trans):(NULL))); + + // ma_ug_seq(*rmg, sg, cover, src, arcs, max_hang, min_ovlp, 0, 1); + + // if(rs_trans) adjust_scaffold_ovlp(sc0, sc1, rmg, (*rs_trans)); + +} + + +void gen_self_scaf(ug_opt_t *opt, ma_ug_t *hu0, ma_ug_t *hu1, asg_t *sg, ma_sub_t *cov, ma_hit_t_alloc *src, ma_hit_t_alloc *rev, R_to_U *ri, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, bub_label_t* b_mask_t, +kvect_sec_t **sc0, kvect_sec_t **sc1, ma_ug_t **mug, kvec_asg_arc_t_warp *arcs, kv_u_trans_t **rs_trans) +{ + ma_ug_t *ug = NULL; + + ug = ma_ug_gen(sg); + + ///print_debug_gfa(sg, ug, cov, "sb.utg", src, ri, opt->max_hang, opt->min_ovlp, 0, 0, 0); + + ///fprintf(stderr, "[M::%s] hu0\n", __func__); + scaf_res_t *cp0 = gen_contig_path(opt, sg, hu0, ug); ///prt_scaf_res_t(cp0, ug, hu0, "h1tg"); + ///fprintf(stderr, "[M::%s] hu1\n", __func__); + scaf_res_t *cp1 = gen_contig_path(opt, sg, hu1, ug); ///prt_scaf_res_t(cp1, ug, hu1, "h2tg"); + + double_scaffold(ug, hu0, hu1, cp0, cp1, sg, cov, src, rev, tipsLen, tip_drop_ratio, stops_threshold, ri, chimeric_rate, drop_ratio, max_hang, min_ovlp, b_mask_t, opt, sc0, sc1, mug, arcs, rs_trans); + + ma_ug_destroy(ug); destroy_scaf_res_t(cp0); destroy_scaf_res_t(cp1); + +} + +void destory_kvect_sec_t(kvect_sec_t *p) +{ + uint64_t k; + for(k = 0; k < p->n; k++) free(p->a[k].a); + free(p->a); +} + +void merge_kvec_asg_arc_t_warp(kvec_asg_arc_t_warp *a, kvec_asg_arc_t_warp *b, kvec_asg_arc_t_warp *m) +{ + m->a.n = m->a.m = a->a.n + b->a.n; MALLOC(m->a.a, m->a.n); + memcpy(m->a.a, a->a.a, sizeof((*(a->a.a)))*a->a.n); + memcpy(m->a.a + a->a.n, b->a.a, sizeof((*(b->a.a)))*b->a.n); +} + +void output_noseq_gfa(ma_ug_t *ug, asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, ma_hit_t_alloc* sources, R_to_U* ruIndex) +{ + char* gfa_name = (char*)malloc(strlen(output_file_name)+100); + sprintf(gfa_name, "%s.d_utg.noseq.gfa", output_file_name); + FILE* output_file = fopen(gfa_name, "w"); + fprintf(stderr, "Writing %s to disk... \n", gfa_name); + ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + fclose(output_file); + free(gfa_name); +} + +void output_trio_graph_joint(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, +long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, +int min_ovlp, long long gap_fuzz, bub_label_t* b_mask_t, ma_ug_t **rhu0, ma_ug_t **rhu1, ug_opt_t *opt) +{ + ma_ug_t *hu0 = NULL, *hu1 = NULL; kvec_asg_arc_t_warp arcs0, arcs1; + memset(&arcs0, 0, sizeof(arcs0)); memset(&arcs1, 0, sizeof(arcs1)); + + reduce_hamming_error_adv(NULL, sg, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz, ruIndex, NULL, tipsLen); + //debug + // print_debug_gfa(sg, NULL, opt->coverage_cut, "rd.hamm.debug", opt->sources, opt->ruIndex, opt->max_hang, opt->min_ovlp, 1, 0, 0); + // exit(1); + + hu0 = output_trio_unitig_graph(sg, coverage_cut, output_file_name, FATHER, sources, + reverse_sources, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, + drop_ratio, max_hang, min_ovlp, gap_fuzz, 1, b_mask_t, NULL, NULL, &arcs0); + + hu1 = output_trio_unitig_graph(sg, coverage_cut, output_file_name, MOTHER, sources, + reverse_sources, tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, + drop_ratio, max_hang, min_ovlp, gap_fuzz, 1, b_mask_t, NULL, NULL, &arcs1); + + dedup_idx_t *hidx0 = NULL, *hidx1 = NULL; uint8_t *ff; CALLOC(ff, sg->n_seq); + hidx0 = gen_dedup_idx_t(hu0, sg); hidx1 = gen_dedup_idx_t(hu1, sg); + update_recover_atg_cov(); + + uint64_t dedup_base = 0, miss_base = 0, s; + s = dedup_exact_ug(hidx1, hidx0, coverage_cut, sources, ruIndex, ff, FATHER); dedup_base += s; + s = dedup_exact_ug(hidx0, hidx1, coverage_cut, sources, ruIndex, ff, MOTHER); dedup_base += s; + destroy_dedup_idx_t(hidx0); destroy_dedup_idx_t(hidx1); + + s = append_miss_nid(sg, hu0, hu1, ff, PHASE_MISS_LEN, PHASE_MISS_N); miss_base += s; + // s = append_miss_nid(sg, hu0, hu1, ff, PHASE_MISS_SLEN, PHASE_MISS_SN); miss_base += s; + free(ff); + + renew_utg((&hu0), sg, &arcs0); renew_utg((&hu1), sg, &arcs1); + fprintf(stderr, "[M::%s] dedup_base::%lu, miss_base::%lu\n", __func__, dedup_base, miss_base); + + if((asm_opt.self_scaf) && (!rhu0) && (!rhu1)) { + kvect_sec_t *sc0 = NULL, *sc1 = NULL; ma_ug_t *mug = NULL; /**kv_u_trans_t *rs_trans = NULL;**/ kvec_asg_arc_t_warp ma; memset(&ma, 0, sizeof(ma)); + scaf_res_t *gpt = NULL; ma_ug_t *gpt_u = NULL; + + merge_kvec_asg_arc_t_warp(&arcs0, &arcs1, &ma); kv_destroy(arcs0.a); kv_destroy(arcs1.a); + gen_self_scaf(opt, hu0, hu1, sg, coverage_cut, sources, reverse_sources, ruIndex, tipsLen, tip_drop_ratio, stops_threshold, chimeric_rate, drop_ratio, max_hang, min_ovlp, b_mask_t, &sc0, &sc1, &mug, &ma, /**&rs_trans**/NULL); + ma_ug_destroy(hu0); ma_ug_destroy(hu1); kv_destroy(ma.a); + + ///output scaf trans + /**kv_destroy((*rs_trans)); kv_destroy(rs_trans->idx); free(rs_trans);**/ + if(asm_opt.gpath) gpt = gen_scaf_res_t(opt, mug, sg, NULL, &gpt_u); + + sc0->ctg = mug; + output_hap_sc_graph(sc0, sg, /**&arcs0,**/ coverage_cut, output_file_name, FATHER, sources, ruIndex, /**max_hang, min_ovlp,**/ NULL); + if(asm_opt.gpath) output_hap_sc_gpath(sc0, output_file_name, FATHER, gpt, gpt_u, NULL); + destory_kvect_sec_t(sc0); free(sc0); + + sc1->ctg = mug; + output_hap_sc_graph(sc1, sg, /**&arcs1,**/ coverage_cut, output_file_name, MOTHER, sources, ruIndex, /**max_hang, min_ovlp,**/ NULL); + if(asm_opt.gpath) output_hap_sc_gpath(sc1, output_file_name, MOTHER, gpt, gpt_u, NULL); + destory_kvect_sec_t(sc1); free(sc1); + + if(asm_opt.gpath) { + output_noseq_gfa(gpt_u, sg, coverage_cut, output_file_name, sources, ruIndex); + ma_ug_destroy(gpt_u); + } + + ma_ug_destroy(mug); if(gpt) destroy_scaf_res_t(gpt); + } else { + ma_ug_t *gpt_u = NULL; + if((asm_opt.gpath) && ((!rhu0) || (!rhu1))) gpt_u = ma_ug_gen(sg); + + if(!rhu0) { + output_hap_graph(hu0, sg, &arcs0, coverage_cut, output_file_name, FATHER, sources, ruIndex, max_hang, min_ovlp, NULL); + if(asm_opt.gpath) output_hap_bp_gpath(opt, hu0, sg, output_file_name, FATHER, gpt_u, NULL); + ma_ug_destroy(hu0); + } else { + (*rhu0) = hu0; + } + kv_destroy(arcs0.a); + + + if(!rhu1) { + output_hap_graph(hu1, sg, &arcs1, coverage_cut, output_file_name, MOTHER, sources, ruIndex, max_hang, min_ovlp, NULL); + if(asm_opt.gpath) output_hap_bp_gpath(opt, hu1, sg, output_file_name, MOTHER, gpt_u, NULL); + ma_ug_destroy(hu1); + } else { + (*rhu1) = hu1; // ma_ug_destroy(hu1); + } + kv_destroy(arcs1.a); + + if(gpt_u) { + output_noseq_gfa(gpt_u, sg, coverage_cut, output_file_name, sources, ruIndex); + ma_ug_destroy(gpt_u); + } + } +} + +void output_read_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, long long n_read) +{ + fprintf(stderr, "Writing read GFA to disk... \n"); + char* gfa_name = (char*)malloc(strlen(output_file_name)+25); + sprintf(gfa_name, "%s.read.gfa", output_file_name); + FILE* output_file = fopen(gfa_name, "w"); + ma_sg_print(sg, &R_INF, coverage_cut, output_file); + free(gfa_name); + fclose(output_file); +} + + +int load_ma_hit_ts(ma_hit_t_alloc** x, char* read_file_name) +{ + fprintf(stderr, "Loading ma_hit_ts from disk... \n"); + char* index_name = (char*)malloc(strlen(read_file_name)+15); + sprintf(index_name, "%s.bin", read_file_name); + FILE* fp = fopen(index_name, "r"); + if(!fp) + { + return 0; + } + + + long long n_read; + long long i, k; + int f_flag; + f_flag = fread(&n_read, sizeof(n_read), 1, fp); + (*x) = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*n_read); + + + for (i = 0; i < n_read; i++) + { + f_flag += fread(&((*x)[i].is_fully_corrected), sizeof((*x)[i].is_fully_corrected), 1, fp); + f_flag += fread(&((*x)[i].is_abnormal), sizeof((*x)[i].is_abnormal), 1, fp); + f_flag += fread(&((*x)[i].length), sizeof((*x)[i].length), 1, fp); + (*x)[i].size = (*x)[i].length; + + (*x)[i].buffer = NULL; + if((*x)[i].length == 0) continue; + + (*x)[i].buffer = (ma_hit_t*)malloc(sizeof(ma_hit_t)*(*x)[i].length); + + for (k = 0; k < (*x)[i].length; k++) + { + read_ma(&((*x)[i].buffer[k]), fp); + } + // fread((*x)[i].buffer, sizeof((*((*x)[i].buffer))), (*x)[i].length, fp); + } + + free(index_name); + fclose(fp); + fprintf(stderr, "ma_hit_ts has been read.\n"); + + return 1; +} + + +int load_debug_ma_hit_ts(ma_hit_t_alloc** x, char* read_file_name) +{ + fprintf(stderr, "Loading ma_hit_ts from disk... \n"); + char* index_name = (char*)malloc(strlen(read_file_name)+15); + sprintf(index_name, "%s.bin", read_file_name); + FILE* fp = fopen(index_name, "r"); + if(!fp) + { + return 0; + } + + + long long n_read; + long long i/**, k**/; + int f_flag; + f_flag = fread(&n_read, sizeof(n_read), 1, fp); + (*x) = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*n_read); + + + for (i = 0; i < n_read; i++) + { + f_flag += fread(&((*x)[i].is_fully_corrected), sizeof((*x)[i].is_fully_corrected), 1, fp); + f_flag += fread(&((*x)[i].is_abnormal), sizeof((*x)[i].is_abnormal), 1, fp); + f_flag += fread(&((*x)[i].length), sizeof((*x)[i].length), 1, fp); + (*x)[i].size = (*x)[i].length; + + (*x)[i].buffer = NULL; + if((*x)[i].length == 0) continue; + + (*x)[i].buffer = (ma_hit_t*)malloc(sizeof(ma_hit_t)*(*x)[i].length); + + // for (k = 0; k < (*x)[i].length; k++) + // { + // read_ma(&((*x)[i].buffer[k]), fp); + // } + fread((*x)[i].buffer, sizeof((*((*x)[i].buffer))), (*x)[i].length, fp); + } + + free(index_name); + fclose(fp); + fprintf(stderr, "ma_hit_ts has been read.\n"); + + return 1; +} + + +void write_ma(ma_hit_t* x, FILE* fp) +{ + fwrite(&(x->qns), sizeof(x->qns), 1, fp); + fwrite(&(x->qe), sizeof(x->qe), 1, fp); + fwrite(&(x->tn), sizeof(x->tn), 1, fp); + fwrite(&(x->ts), sizeof(x->ts), 1, fp); + fwrite(&(x->te), sizeof(x->te), 1, fp); + fwrite(&(x->el), sizeof(x->el), 1, fp); + fwrite(&(x->no_l_indel), sizeof(x->no_l_indel), 1, fp); + + uint32_t t = x->ml; + fwrite(&(t), sizeof(t), 1, fp); + t = x->rev; + fwrite(&(t), sizeof(t), 1, fp); + + t = x->bl; + fwrite(&(t), sizeof(t), 1, fp); + t =x->del; + fwrite(&(t), sizeof(t), 1, fp); +} + + +void write_ma_hit_ts(ma_hit_t_alloc* x, long long n_read, char* read_file_name) +{ + fprintf(stderr, "Writing ma_hit_ts to disk... \n"); + char* index_name = (char*)malloc(strlen(read_file_name)+15); + sprintf(index_name, "%s.bin", read_file_name); + FILE* fp = fopen(index_name, "w"); + long long i, k; + fwrite(&n_read, sizeof(n_read), 1, fp); + + + for (i = 0; i < n_read; i++) + { + fwrite(&(x[i].is_fully_corrected), sizeof(x[i].is_fully_corrected), 1, fp); + fwrite(&(x[i].is_abnormal), sizeof(x[i].is_abnormal), 1, fp); + fwrite(&(x[i].length), sizeof(x[i].length), 1, fp); + for (k = 0; k < x[i].length; k++) + { + write_ma(x[i].buffer + k, fp); + } + // fwrite(x[i].buffer, sizeof((*(x[i].buffer))), x[i].length, fp); + } + + + free(index_name); + fflush(fp); + fclose(fp); + fprintf(stderr, "ma_hit_ts has been written.\n"); +} + + +void write_debug_ma_hit_ts(ma_hit_t_alloc* x, long long n_read, char* read_file_name) +{ + fprintf(stderr, "Writing ma_hit_ts to disk... \n"); + char* index_name = (char*)malloc(strlen(read_file_name)+15); + sprintf(index_name, "%s.bin", read_file_name); + FILE* fp = fopen(index_name, "w"); + long long i/**, k**/; + fwrite(&n_read, sizeof(n_read), 1, fp); + + + for (i = 0; i < n_read; i++) + { + fwrite(&(x[i].is_fully_corrected), sizeof(x[i].is_fully_corrected), 1, fp); + fwrite(&(x[i].is_abnormal), sizeof(x[i].is_abnormal), 1, fp); + fwrite(&(x[i].length), sizeof(x[i].length), 1, fp); + // for (k = 0; k < x[i].length; k++) + // { + // write_ma(x[i].buffer + k, fp); + // } + fwrite(x[i].buffer, sizeof((*(x[i].buffer))), x[i].length, fp); + } + + + free(index_name); + fflush(fp); + fclose(fp); + fprintf(stderr, "ma_hit_ts has been written.\n"); +} + +void write_yak_binning(char *ou, char *fn_bin_yak1, char *fn_bin_yak2) +{ + fprintf(stderr, "Writing binning to disk ...... \n"); + char* paf_name = (char*)malloc(strlen(ou)+50); + sprintf(paf_name, "%s.hap1.phase.bin", ou); + FILE* oh1 = fopen(paf_name, "w"); + sprintf(paf_name, "%s.hap2.phase.bin", ou); + FILE* oh2 = fopen(paf_name, "w"); + uint64_t i, s1, s2; + + for (i = s1 = s2 = 0; i < R_INF.total_reads; i++) { + if(R_INF.trio_flag[i]==FATHER) { + if(s1) { + fprintf(oh1, "%.*s\n", (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); + } else { + fprintf(oh1, "%.*s\t%s\n", (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i), fn_bin_yak1); + } + s1 = 1; + } + if(R_INF.trio_flag[i]==MOTHER) { + if(s2) { + fprintf(oh2, "%.*s\n", (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); + } else { + fprintf(oh2, "%.*s\t%s\n", (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i), fn_bin_yak2); + } + s2 = 1; + } + } + free(paf_name); + fclose(oh1); fclose(oh2); + fprintf(stderr, "Binning has been written.\n"); +} + +uint32_t load_yak_binning(hifiasm_opt_t *opt, char *ou)///asm_opt +{ + char* paf_name = (char*)malloc(strlen(ou)+50); + uint32_t len[2] = {0}; char *lst0, *lst1, *yak0, *yak1; + lst0 = lst1 = yak0 = yak1 = NULL; + + sprintf(paf_name, "%s.hap1.phase.bin", ou); len[0] = strlen(paf_name)+1; + if(!test_yak_binning(paf_name, opt->fn_bin_yak[0])) { + free(paf_name); return 0; + } + + sprintf(paf_name, "%s.hap2.phase.bin", ou); len[1] = strlen(paf_name)+1; + if(!test_yak_binning(paf_name, opt->fn_bin_yak[1])) { + free(paf_name); return 0; + } + free(paf_name); paf_name = NULL; + + lst0 = opt->fn_bin_list[0]; MALLOC(opt->fn_bin_list[0], len[0]); + sprintf(opt->fn_bin_list[0], "%s.hap1.phase.bin", ou); + + lst1 = opt->fn_bin_list[1]; MALLOC(opt->fn_bin_list[1], len[1]); + sprintf(opt->fn_bin_list[1], "%s.hap2.phase.bin", ou); + + memset(R_INF.trio_flag, AMBIGU, R_INF.total_reads * sizeof(uint8_t)); + yak0 = opt->fn_bin_yak[0]; opt->fn_bin_yak[0] = NULL; + yak1 = opt->fn_bin_yak[1]; opt->fn_bin_yak[1] = NULL; + ha_triobin(opt); + opt->fn_bin_yak[0] = yak0; opt->fn_bin_yak[1] = yak1; + free(opt->fn_bin_list[0]); opt->fn_bin_list[0] = lst0; + free(opt->fn_bin_list[1]); opt->fn_bin_list[1] = lst1; + return 1; +} + +void write_all_data_to_disk(ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, All_reads *RNF, char* output_file_name) +{ + char* gfa_name = (char*)malloc(strlen(output_file_name)+25); + sprintf(gfa_name, "%s.ec", output_file_name); + write_All_reads(RNF, gfa_name); + + if((ha_opt_triobin(&asm_opt)) && (asm_opt.fn_bin_yak[0] && asm_opt.fn_bin_yak[1])) { + write_yak_binning(asm_opt.output_file_name, asm_opt.fn_bin_yak[0], asm_opt.fn_bin_yak[1]); + } + + sprintf(gfa_name, "%s.ovlp.source", output_file_name); + write_ma_hit_ts(sources, RNF->total_reads, gfa_name); + + sprintf(gfa_name, "%s.ovlp.reverse", output_file_name); + write_ma_hit_ts(reverse_sources, RNF->total_reads, gfa_name); + + free(gfa_name); + fprintf(stderr, "bin files have been written.\n"); + if(asm_opt.bin_only) exit(0); +} + +int load_debug_graph(asg_t** sg, ma_hit_t_alloc** sources, ma_sub_t** coverage_cut, +char* output_file_name, ma_hit_t_alloc** reverse_sources, R_to_U* ruIndex, all_ul_t *ul_r_inf); +int load_all_data_from_disk(ma_hit_t_alloc **sources, ma_hit_t_alloc **reverse_sources, char* output_file_name) +{ + char* gfa_name = (char*)malloc(strlen(output_file_name)+25); + sprintf(gfa_name, "%s.ec", output_file_name); + if (!load_All_reads(&R_INF, gfa_name)) { + free(gfa_name); + return 0; + } + + if(ha_opt_triobin(&asm_opt)) { + if(!((asm_opt.fn_bin_yak[0]) && (asm_opt.fn_bin_yak[1]) && + (load_yak_binning(&asm_opt, asm_opt.output_file_name)))) { + ha_triobin(&asm_opt); + write_yak_binning(asm_opt.output_file_name, asm_opt.fn_bin_yak[0], asm_opt.fn_bin_yak[1]); + } + } + + if((asm_opt.flag & HA_F_VERBOSE_GFA) && load_debug_graph(NULL, NULL, NULL, output_file_name, NULL, NULL, NULL)) + { + (*sources) = NULL; + (*reverse_sources) = NULL; + free(gfa_name); + return 1; + } + + sprintf(gfa_name, "%s.ovlp.source", output_file_name); + if (!load_ma_hit_ts(sources, gfa_name)) { + free(gfa_name); + return 0; + } + sprintf(gfa_name, "%s.ovlp.reverse", output_file_name); + if (!load_ma_hit_ts(reverse_sources, gfa_name)) { + free(gfa_name); + return 0; + } + free(gfa_name); + + if(asm_opt.write_pos_idx) { + int32_t m; + asm_opt.hom_cov_0 = asm_opt.hom_cov; + asm_opt.het_cov_0 = asm_opt.het_cov; + asm_opt.max_n_chain_0 = asm_opt.max_n_chain; + refresh_pt_idx(&ha_flt_tab, &ha_idx, NULL, &asm_opt, output_file_name, 0); + // load_pt_index(&ha_flt_tab, &ha_idx, NULL, &asm_opt, output_file_name); + m = asm_opt.hom_cov_0; asm_opt.hom_cov_0 = asm_opt.hom_cov; asm_opt.hom_cov = m; + m = asm_opt.het_cov_0; asm_opt.het_cov_0 = asm_opt.het_cov; asm_opt.het_cov = m; + m = asm_opt.max_n_chain_0; asm_opt.max_n_chain_0 = asm_opt.max_n_chain; asm_opt.max_n_chain = m; + } + return 1; +} + +// count the number of outgoing arcs, excluding reduced arcs +static inline int count_out(const asg_t *g, uint32_t v) +{ + uint32_t i, n, nv = asg_arc_n(g, v); + const asg_arc_t *av = asg_arc_a(g, v); + for (i = n = 0; i < nv; ++i) + if (!av[i].del) ++n; + return n; +} + + +void dfs_trans_chain_bub(asg_t *g, hap_cov_t *cov, uint32_t v, uint32_t beg, uint32_t sink) +{ + buf_t *b = &(cov->t_ch->b_buf_0); + b->b.n = 0; + if(v == beg || v == sink) return; + uint64_t *flag = cov->pos_idx; + asg_arc_t *acur = NULL; + uint32_t cur, ncur, i; + v = v << 1; + kv_push(uint32_t, b->b, v); + while (b->b.n > 0) + { + b->b.n--; + cur = b->b.a[b->b.n]; + if(flag[cur>>1] == 0 && (cur>>1) != (v>>1)) continue; + flag[cur>>1] = 0; + + ncur = asg_arc_n(g, cur); + acur = asg_arc_a(g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if((acur[i].v>>1) == beg || (acur[i].v>>1) == sink) continue; + if(flag[acur[i].v>>1] == 0) continue; + kv_push(uint32_t, b->b, acur[i].v); + } + } + + v = v + 1; + kv_push(uint32_t, b->b, v); + while (b->b.n > 0) + { + b->b.n--; + cur = b->b.a[b->b.n]; + if(flag[cur>>1] == 0 && (cur>>1) != (v>>1)) continue; + flag[cur>>1] = 0; + + ncur = asg_arc_n(g, cur); + acur = asg_arc_a(g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if((acur[i].v>>1) == beg || (acur[i].v>>1) == sink) continue; + if(flag[acur[i].v>>1] == 0) continue; + kv_push(uint32_t, b->b, acur[i].v); + } + } + + b->b.n = 0; + for (i = 0; i < cov->t_ch->topo_res.n; ++i) //has been sorted + { + if(flag[cov->t_ch->topo_res.a[i]>>1] == 0) + { + flag[cov->t_ch->topo_res.a[i]>>1] = (uint64_t)-1; + } + else + { + kv_push(uint32_t, b->b, cov->t_ch->topo_res.a[i]); + } + } + + + /*******************************for debug************************************/ + // for (i = 0; i < cov->n; ++i) + // { + // if(flag[i] != (uint64_t)-1) fprintf(stderr, "ERROR-0\n"); + // } + /*******************************for debug************************************/ +} + +void debug_topo_sorting(asg_t *g, hap_cov_t *cov, uint32_t beg, uint32_t sink) +{ + buf_t *b = &(cov->t_ch->b_buf_0); + uint64_t *flag = cov->pos_idx; + asg_arc_t *acur = NULL; + uint32_t cur, ncur, i, k, k_i, v; + + for (k = 0; k < cov->t_ch->topo_res.n; k++) + { + v = cov->t_ch->topo_res.a[k]; + + b->b.n = 0; + kv_push(uint32_t, b->b, v); + while (b->b.n > 0) + { + b->b.n--; + cur = b->b.a[b->b.n]; + + ncur = asg_arc_n(g, cur); + acur = asg_arc_a(g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if((acur[i].v>>1) == (beg>>1) || (acur[i].v>>1) == (sink>>1)) continue; + kv_push(uint32_t, b->b, acur[i].v); + if(flag[acur[i].v>>1] == 0) + { + fprintf(stderr, "\nERROR-1\n"); + fprintf(stderr, "beg>>1: %u, sink>>1: %u, topo_res.n: %u, v>>1: %u, w>>1: %u\n", + beg>>1, sink>>1, (uint32_t)cov->t_ch->topo_res.n, v>>1, acur[i].v>>1); + for (k_i = 0; k_i < cov->t_ch->topo_res.n; k_i++) + { + fprintf(stderr, "k_i: %u, topo_res>>1: %u\n", k_i, cov->t_ch->topo_res.a[k_i]>>1); + } + } + + } + } + + flag[cov->t_ch->topo_res.a[k]>>1] = 0; + } + + for (k = 0; k < cov->t_ch->topo_res.n; k++) + { + flag[cov->t_ch->topo_res.a[k]>>1] = (uint64_t)-1; + } +} + +void topologicalSortUtil(asg_t *g, hap_cov_t *cov, uint32_t beg, uint32_t sink) +{ + buf_t *b = &(cov->t_ch->b_buf_0); + uint64_t *visited = cov->pos_idx; + uint32_t v = beg, nv, kv, i; + asg_arc_t *av = NULL; + + b->b.n = 0; cov->t_ch->topo_res.n = 0; + kv_push(uint32_t, b->b, v); + while (b->b.n > 0) + { + ///b->b.n--; + v = b->b.a[b->b.n-1]; + if(visited[v>>1] == (uint64_t)-1) + { + visited[v>>1] = 0; + } + + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + for (i = kv = 0; i < nv; i++) + { + if(av[i].del) continue; + if((av[i].v>>1) == (beg>>1) || (av[i].v>>1) == (sink>>1)) continue; + if(visited[av[i].v>>1] != (uint64_t)-1) continue; + kv_push(uint32_t, b->b, av[i].v); + kv++; + } + + if(kv != 0) continue; + b->b.n--; + if(visited[v>>1] != 1) + { + kv_push(uint32_t, cov->t_ch->topo_res, v); + visited[v>>1] = 1; + } + } + for (i = 0; i < cov->t_ch->topo_res.n; ++i) + { + visited[cov->t_ch->topo_res.a[i]>>1] = (uint64_t)-1; + } + + cov->t_ch->topo_res.n--;//remove beg + for (i = 0; i < (cov->t_ch->topo_res.n>>1); ++i) + { + v = cov->t_ch->topo_res.a[i]; + cov->t_ch->topo_res.a[i] = cov->t_ch->topo_res.a[cov->t_ch->topo_res.n - i - 1]; + cov->t_ch->topo_res.a[cov->t_ch->topo_res.n - i - 1] = v; + } + + /*******************************for debug************************************/ + // for (i = 0; i < cov->n; ++i) + // { + // if(visited[i] != (uint64_t)-1) fprintf(stderr, "ERROR-2\n"); + // } + // debug_topo_sorting(g, cov, beg, sink); + /*******************************for debug************************************/ +} + +void chain_origin_trans_uid_s_bubble(buf_t *pri, buf_t* aux, uint32_t beg, uint32_t sink, ma_ug_t *ug, hap_cov_t *cov) +{ + if(pri->b.n == 0 || aux->b.n == 0) return; + asg_arc_t *av = NULL; + uint32_t pri_v, aux_v, nv, i, priBeg, priEnd, auxBeg, auxEnd; + uint64_t pri_len, aux_len; + + priBeg = priEnd = auxBeg = auxEnd = (uint32_t)-1; + pri_len = set_utg_offset(pri->b.a, pri->b.n, ug, cov->read_g, cov->pos_idx, 0, 1); + aux_len = set_utg_offset(aux->b.a, aux->b.n, ug, cov->read_g, cov->pos_idx, 0, 1); + + pri_v = pri->b.a[0]; aux_v = aux->b.a[0]; + av = asg_arc_a(ug->g, beg); + nv = asg_arc_n(ug->g, beg); + for (i = 0; i < nv; ++i) + { + if(av[i].del) continue; + if(av[i].v == pri_v) priBeg = av[i].ol; + if(av[i].v == aux_v) auxBeg = av[i].ol; + } + + pri_v = pri->b.a[pri->b.n-1]^1; aux_v = aux->b.a[aux->b.n-1]^1; + av = asg_arc_a(ug->g, sink); + nv = asg_arc_n(ug->g, sink); + for (i = 0; i < nv; ++i) + { + if(av[i].del) continue; + if(av[i].v == pri_v) priEnd = ((pri_len > av[i].ol)? (pri_len - av[i].ol - 1) : 0); + if(av[i].v == aux_v) auxEnd = ((aux_len > av[i].ol)? (aux_len - av[i].ol - 1) : 0); + } + ///[priBeg, priEnd) && [auxBeg, auxEnd) + if(priBeg == (uint32_t)-1 || priEnd == (uint32_t)-1 || auxBeg == (uint32_t)-1 || auxEnd == (uint32_t)-1) + { + fprintf(stderr, "ERROR-s_bubble\n"); + } + + cov->u_buffer.a.n = cov->tailIndex.a.n = 0; + + kv_resize(asg_arc_t_offset, cov->u_buffer.a, 1); + cov->u_buffer.a.n = 1; + cov->u_buffer.a.a[0].Off = priEnd; + cov->u_buffer.a.a[0].Off <<= 32; + cov->u_buffer.a.a[0].Off |= auxEnd; + + kv_resize(int32_t, cov->tailIndex.a, 1); + cov->tailIndex.a.n = 1; + cov->tailIndex.a.a[0] = 0; + + // uint32_t i_n = cov->t_ch->k_trans.n; + + chain_origin_trans_uid_by_distance(cov, cov->read_g, pri->b.a, pri->b.n, priBeg, &pri_len, aux->b.a, aux->b.n, auxBeg, &aux_len, ug, RC_0, -1024, __func__); + + // fprintf(stderr, "\nocc: %u\n", (uint32_t)(cov->t_ch->k_trans.n - i_n)); + // for (i = i_n; i < cov->t_ch->k_trans.n; i++) + // { + // fprintf(stderr, "s-utg%.6ul\t%u\t%u\td-utg%.6ul\t%u\t%u\trev(%u)\n", + // cov->t_ch->k_trans.a[i].qn+1, cov->t_ch->k_trans.a[i].qs, cov->t_ch->k_trans.a[i].qe, + // cov->t_ch->k_trans.a[i].tn+1, cov->t_ch->k_trans.a[i].ts, cov->t_ch->k_trans.a[i].te, + // cov->t_ch->k_trans.a[i].rev); + // } +} + +void chain_origin_trans_uid_c_bubble(uint32_t query, buf_t *target, buf_t *idx, ma_ug_t *ug, hap_cov_t *cov) +{ + if(target->b.n == 0) return; + uint32_t qs, qe, ts, te, i, v, ovlp; + qs = idx->a[query].d; qe = qs + ug->g->seq[query>>1].len; + uint64_t qlen = ug->g->seq[query>>1].len, tlen; + cov->u_buffer.a.n = cov->tailIndex.a.n = 0; + + ///uint32_t i_n = cov->t_ch->k_trans.n; + for (i = 0; i < target->b.n; ++i) + { + v = target->b.a[i]; + if(v < query) continue; //avoid dup + ts = idx->a[v].d; te = ts + ug->g->seq[v>>1].len; tlen = ug->g->seq[v>>1].len; + ovlp = ((MIN(qe, te) > MAX(qs, ts))? (MIN(qe, te) - MAX(qs, ts)) : 0); + if(ovlp == 0) continue; + chain_origin_trans_uid_by_distance(cov, cov->read_g, &query, 1, MAX(qs, ts) - qs, &qlen, + &v, 1, MAX(qs, ts) - ts, &tlen, ug, RC_0, -1024, __func__); + } + // fprintf(stderr, "\nocc: %u\n", (uint32_t)(cov->t_ch->k_trans.n - i_n)); + // for (i = i_n; i < cov->t_ch->k_trans.n; i++) + // { + // fprintf(stderr, "s-utg%.6ul\t%u\t%u\td-utg%.6ul\t%u\t%u\trev(%u)\n", + // cov->t_ch->k_trans.a[i].qn+1, cov->t_ch->k_trans.a[i].qs, cov->t_ch->k_trans.a[i].qe, + // cov->t_ch->k_trans.a[i].tn+1, cov->t_ch->k_trans.a[i].ts, cov->t_ch->k_trans.a[i].te, + // cov->t_ch->k_trans.a[i].rev); + // } +} + +// in a resolved bubble, mark unused vertices and arcs as "reduced" +static void asg_bub_backtrack_primary_cov(ma_ug_t *ug, uint32_t v0, buf_t *b, hap_cov_t *cov, uint32_t is_update_chain) +{ + uint32_t i, k, k_i, v, u, uLen = 0, uCov = 0, uId, rId, ori; + ma_utg_t* p = NULL; + trans_chain* t_ch = (is_update_chain?cov->t_ch:NULL); + ///b->S.a[0] is the sink of this bubble + + ///assert(b->S.n == 1); + ///first remove all nodes in this bubble + for (i = 0; i < b->b.n; ++i) + { + uId = b->b.a[i]>>1; + if(uId == (b->S.a[0]>>1)) continue; + p = &(ug->u.a[uId]); + if(p->n == 0) continue; + + for (k = 0; k < p->n; k++) + { + rId = p->a[k]>>33; + uCov += cov->cov[rId]; + } + } + + + ///v is the sink of this bubble + v = b->S.a[0]; + ///recover node + do { + u = b->a[v].p; // u->v + if(v != b->S.a[0]) + { + uId = v>>1; + p = &(ug->u.a[uId]); + if(p->n == 0) continue; + for (k = 0; k < p->n; k++) + { + rId = p->a[k]>>33; + uCov -= cov->cov[rId]; + uLen += cov->read_g->seq[rId].len; + } + } + v = u; + } while (v != v0); + + uCov = (uLen == 0? 0 : uCov / uLen); + + ///v is the sink of this bubble + v = b->S.a[0]; + ///recover node + do { + u = b->a[v].p; // u->v + if(v != b->S.a[0]) + { + uId = v>>1; + p = &(ug->u.a[uId]); + if(p->n == 0) continue; + for (k = 0; k < p->n; k++) + { + rId = p->a[k]>>33; + cov->cov[rId] += (uCov * cov->read_g->seq[rId].len);///this the average coverage of the whole bubble + } + } + v = u; + } while (v != v0); + + + if(t_ch) + { + ///is this requirement appropriate? + if(get_real_length(ug->g, v0, NULL) == 2 && get_real_length(ug->g, b->S.a[0]^1, NULL) == 2) + { + long long tmp, max_stop_nodeLen, max_stop_baseLen, bch_occ[2]; + uint32_t bch[2], convex[2]; + get_real_length(ug->g, v0, bch); + + ///in rare cases, one side of a bubble might be empty + if((bch[0]>>1)!=(b->S.a[0]>>1) && (bch[1]>>1)!=(b->S.a[0]>>1)) + { + get_unitig(ug->g, NULL, bch[0], &convex[0], &bch_occ[0], &tmp, + &max_stop_nodeLen, &max_stop_baseLen, 1, NULL); + get_unitig(ug->g, NULL, bch[1], &convex[1], &bch_occ[1], &tmp, + &max_stop_nodeLen, &max_stop_baseLen, 1, NULL); + ///if this is a simple bubble + if(((bch_occ[0] + bch_occ[1] + 1) == (uint32_t)b->b.n) && + get_real_length(ug->g, convex[0], NULL) == 1 && get_real_length(ug->g, convex[1], NULL) == 1) + { + get_real_length(ug->g, convex[0], &convex[0]); + get_real_length(ug->g, convex[1], &convex[1]); + if(convex[0] == b->S.a[0] && convex[1] == b->S.a[0])///double check if it is a simple bubble + { + t_ch->b_buf_0.b.n = 0; + get_unitig(ug->g, NULL, bch[0], &convex[0], &bch_occ[0], &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, &(t_ch->b_buf_0)); + for (i = 0; i < t_ch->b_buf_0.b.n; ++i)///retrive one side of the bubble + { + uId = t_ch->b_buf_0.b.a[i]>>1; + p = &(ug->u.a[uId]); + if(p->n == 0) continue; + ori = t_ch->b_buf_0.b.a[i]&1; + for (k = 0; k < p->n; k++) + { + t_ch->ir_het[(ori == 1?((p->a[p->n-k-1])>>33):(p->a[k]>>33))] |= P_HET; + } + } + + t_ch->b_buf_1.b.n = 0; + get_unitig(ug->g, NULL, bch[1], &convex[1], &bch_occ[1], &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, &(t_ch->b_buf_1)); + for (i = 0; i < t_ch->b_buf_1.b.n; ++i)///retrive another side of the bubble + { + uId = t_ch->b_buf_1.b.a[i]>>1; + p = &(ug->u.a[uId]); + if(p->n == 0) continue; + ori = t_ch->b_buf_1.b.a[i]&1; + for (k = 0; k < p->n; k++) + { + t_ch->ir_het[(ori == 1?((p->a[p->n-k-1])>>33):(p->a[k]>>33))] |= P_HET; + } + } + ///generate read-to-read overlaps + chain_origin_trans_uid_s_bubble(&(t_ch->b_buf_0), &(t_ch->b_buf_1), + v0, b->S.a[0]^1, ug, cov); + return; + } + } + } + } + + topologicalSortUtil(ug->g, cov, v0, b->S.a[0]); + ///if(cov->t_ch->topo_res.n != b->b.n - 1) fprintf(stderr, "ERROR-4\n"); + if(cov->t_ch->topo_res.n == 0) return; + for (i = 0; i < cov->t_ch->topo_res.n; ++i) + { + uId = cov->t_ch->topo_res.a[i]>>1; + if(uId == (b->S.a[0]>>1)) continue; + + dfs_trans_chain_bub(ug->g, cov, uId, v0>>1, b->S.a[0]>>1); + + if(cov->t_ch->b_buf_0.b.n == 0) continue; + chain_origin_trans_uid_c_bubble(cov->t_ch->topo_res.a[i], &(t_ch->b_buf_0), b, ug, cov); + + /***********************x***********************/ + uId = cov->t_ch->topo_res.a[i]>>1; + p = &(ug->u.a[uId]); + if(p->n == 0) continue; + ori = cov->t_ch->topo_res.a[i]&1; + for (k = 0; k < p->n; k++) + { + t_ch->ir_het[(ori == 1?((p->a[p->n-k-1])>>33):(p->a[k]>>33))] |= P_HET; + } + /***********************x***********************/ + + /***********************y***********************/ + for (k_i = 0; k_i < t_ch->b_buf_0.b.n; ++k_i) + { + uId = t_ch->b_buf_0.b.a[k_i]>>1; + p = &(ug->u.a[uId]); + if(p->n == 0) continue; + ori = t_ch->b_buf_0.b.a[k_i]&1; + for (k = 0; k < p->n; k++) + { + t_ch->ir_het[(ori == 1?((p->a[p->n-k-1])>>33):(p->a[k]>>33))] |= P_HET; + } + } + /***********************y***********************/ + } + } +} + + +// in a resolved bubble, mark unused vertices and arcs as "reduced" +void asg_bub_backtrack_primary(asg_t *g, uint32_t v0, buf_t *b) +{ + uint32_t i, v, qn, tn; + ///b->S.a[0] is the sink of this bubble + uint32_t tmp_c = g->seq[b->S.a[0]>>1].c; + + ///assert(b->S.n == 1); + ///first remove all nodes in this bubble + for (i = 0; i < b->b.n; ++i) + { + g->seq[b->b.a[i]>>1].c = ALTER_LABLE; + } + + ///v is the sink of this bubble + v = b->S.a[0]; + ///recover node + do { + uint32_t u = b->a[v].p; // u->v + /****************************may have hap bugs********************************/ + ////g->seq[v>>1].c = PRIMARY_LABLE; + g->seq[v>>1].c = HAP_LABLE; + /****************************may have hap bugs********************************/ + v = u; + } while (v != v0); + ///especially for unitig graph, don't label beg and sink node of a bubble as HAP_LABLE + ///since in unitig graph, a node may consist of a lot of reads + g->seq[b->S.a[0]>>1].c = tmp_c; + + ///remove all edges (self/reverse for each edge) in this bubble + for (i = 0; i < b->e.n; ++i) { + asg_arc_t *a = &g->arc[b->e.a[i]]; + qn = a->ul>>33; + tn = a->v>>1; + if(g->seq[qn].c == ALTER_LABLE && g->seq[tn].c == ALTER_LABLE) + { + continue; + } + ///remove this edge self + a->del = 1; + ///remove the reverse direction + asg_arc_del(g, a->v^1, a->ul>>32^1, 1); + } + + ///v is the sink of this bubble + v = b->S.a[0]; + ///recover node + do { + uint32_t u = b->a[v].p; // u->v + g->seq[v>>1].del = 0; + asg_arc_del(g, u, v, 0); + asg_arc_del(g, v^1, u^1, 0); + v = u; + } while (v != v0); +} + + +// in a resolved bubble, mark unused vertices and arcs as "reduced" +void asg_bub_backtrack_primary_length(asg_t *g, ma_ug_t *utg, uint32_t v0, buf_t *b, uint64_t* path_base_len, uint64_t* path_nodes) +{ + uint32_t i, v, u, nv; + uint64_t len = 0, node = 0; + ///b->S.a[0] is the sink of this bubble + asg_arc_t *av = NULL; + + ///v is the sink of this bubble + v = b->S.a[0]; + len = 0; + ///recover node + while (1) + { + u = b->a[v].p; // u->v + if(u == v0) break; + if(v == b->S.a[0]) + { + len += g->seq[u>>1].len; + } + else + { + nv = asg_arc_n(g, u); + av = asg_arc_a(g, u); + for (i = 0; i < nv; ++i) + { + if(av[i].del) continue; + if(av[i].v == v) break; + } + ///if(i == nv) fprintf(stderr, "ERROR\n"); + len += (uint32_t)av[i].ul; + } + + if(utg) + { + node += utg->u.a[u>>1].n; + } + else + { + node++; + } + + v = u; + } + + if(path_base_len) (*path_base_len) = len; + if(path_nodes) (*path_nodes) = node; +} + + +// in a resolved bubble, mark unused vertices and arcs as "reduced" +int asg_bub_backtrack_check_switch(asg_t *g, ma_ug_t *utg, uint32_t v0, buf_t *b) +{ + uint32_t v, k, rId, father_occ = 0, mother_occ = 0; + ma_utg_t* p = NULL; + ///b->S.a[0] is the sink of this bubble + ///v is the sink of this bubble + v = b->S.a[0]; + ///recover node + do { + uint32_t u = b->a[v].p; // u->v + if(v != b->S.a[0]) + { + p = &(utg->u.a[v>>1]); + for (k = 0; k < p->n; k++) + { + rId = p->a[k]>>33; + if(R_INF.trio_flag[rId] == FATHER) father_occ++; + if(R_INF.trio_flag[rId] == MOTHER) mother_occ++; + if(R_INF.trio_flag[rId] != AMBIGU) continue; + R_INF.trio_flag[rId] = DROP; + } + } + v = u; + } while (v != v0); + + if(father_occ > 0 && mother_occ > 0) return 1; + + return 0; +} + +// pop bubbles from vertex v0; the graph MJUST BE symmetric: if u->v present, v'->u' must be present as well +uint64_t asg_bub_pop1_primary_trio_switch_check(asg_t *g, ma_ug_t *utg, uint32_t v0, uint64_t max_dist, buf_t *b, +uint32_t positive_flag, uint32_t negative_flag, uint32_t is_pop, uint64_t* path_base_len, uint64_t* path_nodes, +int* is_switch) +{ + uint32_t i, n_pending = 0, /**is_first = 1,**/ cur_m, cur_c, cur_np, cur_nc, to_replace, n_tips, tip_end; + uint64_t n_pop = 0; + long long cur_weight = -1, max_weight = -1; + ///if this node has been deleted + if (g->seq[v0>>1].del || g->seq[v0>>1].c == ALTER_LABLE) return 0; // already deleted + ///if ((uint32_t)g->idx[v0] < 2) return 0; // no bubbles + if(get_real_length(g, v0, NULL)<2) return 0; + ///S saves nodes with all incoming edges visited + b->S.n = b->T.n = b->b.n = b->e.n = 0; + ///for each node, b->a saves all related information + b->a[v0].c = b->a[v0].d = b->a[v0].m = b->a[v0].nc = b->a[v0].np = 0; + ///b->S is the nodes with all incoming edges visited + kv_push(uint32_t, b->S, v0); + n_tips = 0; + tip_end = (uint32_t)-1; + uint32_t non_positive_flag = (uint32_t)-1; + if(positive_flag == FATHER) non_positive_flag = MOTHER; + if(positive_flag == MOTHER) non_positive_flag = FATHER; + + do { + ///v is a node that all incoming edges have been visited + ///d is the distance from v0 to v + uint32_t v = kv_pop(b->S), d = b->a[v].d, c = b->a[v].c, m = b->a[v].m, nc = b->a[v].nc, np = b->a[v].np; + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + ///why we have this assert? + ///assert(nv > 0); + ///all out-edges of v + for (i = 0; i < nv; ++i) { // loop through v's neighbors + /** + p->ul: |____________31__________|__________1___________|______________32_____________| + qn direction of overlap length of this node (not overlap length) + (in the view of query) + p->v : |___________31___________|__________1___________| + tn reverse direction of overlap + (in the view of target) + p->ol: overlap length + **/ + ///if this edge has been deleted + if (av[i].del) continue; + + uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l + binfo_t *t = &b->a[w]; + ///that means there is a circle, directly terminate the whole bubble poping + ///if (w == v0) goto pop_reset; + if ((w>>1) == (v0>>1)) goto pop_reset; + /****************************may have bugs********************************/ + ///important when poping at long untig graph + // if(is_first) l = 0; + /****************************may have bugs********************************/ + + + + ///push the edge + ///high 32-bit of g->idx[v] is the start point of v's edges + //so here is the point of this specfic edge + kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); + ///find a too far path? directly terminate the whole bubble poping + if (d + l > max_dist) break; // too far + + ///if this node + if (t->s == 0) { // this vertex has never been visited + kv_push(uint32_t, b->b, w); // save it for revert + ///t->p is the parent node of + ///t->s = 1 means w has been visited + ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) + t->p = v, t->s = 1, t->d = d + l; + /****************************may have bugs********************************/ + cur_c = cur_m = cur_np = 0; cur_nc = 1; + if(utg) + { + cur_c = get_num_trio_flag(utg, w>>1, positive_flag); + cur_m = get_num_trio_flag(utg, w>>1, negative_flag); + cur_np = 0; + if(non_positive_flag != (uint32_t)-1) + { + cur_np = get_num_trio_flag(utg, w>>1, non_positive_flag); + } + cur_nc = utg->u.a[(w>>1)].n; + } + + + t->c = c + cur_c; + t->m = m + cur_m; + t->nc = nc + cur_nc; + t->np = np + cur_np; + /****************************may have bugs********************************/ + ///incoming edges of w + ///t->r = count_out(g, w^1); + t->r = get_real_length(g, w^1, NULL); + ++n_pending; + } else { // visited before + /****************************may have bugs********************************/ + cur_c = cur_m = cur_np = 0; cur_nc = 1; + if(utg) + { + cur_c = get_num_trio_flag(utg, w>>1, positive_flag); + cur_m = get_num_trio_flag(utg, w>>1, negative_flag); + cur_np = 0; + if(non_positive_flag != (uint32_t)-1) + { + cur_np = get_num_trio_flag(utg, w>>1, non_positive_flag); + } + cur_nc = utg->u.a[(w>>1)].n; + } + ///BUG: select the path with less negative_flag, less non_positive_flag, more positive_flag, more distance + ///FIXED: select the path with less (negative_flag+non_positive_flag), more positive_flag, more distance + to_replace = 0; + + /****************************may have bugs********************************/ + cur_weight = (long long)(c + cur_c) - ((long long)(m + cur_m) + (long long)(np + cur_np)); + max_weight = (long long)t->c - ((long long)t->m + (long long)t->np); + if(cur_weight > max_weight) + { + to_replace = 1; + } + else if(cur_weight == max_weight) + { + if(nc + cur_nc > t->nc) + { + to_replace = 1; + } + else if(nc + cur_nc == t->nc) + { + if(d + l > t->d) + { + to_replace = 1; + } + } + } + /****************************may have bugs********************************/ + + /** + if(((m + cur_m) + (np + cur_np)) < (t->m + t->np)) + { + to_replace = 1; + } + else if(((m + cur_m) + (np + cur_np)) == (t->m + t->np)) + { + if(c + cur_c > t->c) + { + to_replace = 1; + } + else if(c + cur_c == t->c) + { + if(nc + cur_nc > t->nc) + { + to_replace = 1; + } + else if(nc + cur_nc == t->nc) + { + if(d + l > t->d) + { + to_replace = 1; + } + } + + } + } + **/ + + + if(to_replace) + { + t->p = v; + t->m = m + cur_m; + t->c = c + cur_c; + t->nc = nc + cur_nc; + t->np = np + cur_np; + } + ///c is the weight (is very likely the number of node in this edge) of the parent node + ///select the longest edge (longest meams most reads/longest edge) + // if (c + 1 > t->c || (c + 1 == t->c && d + l > t->d)) t->p = v; + // if (c + 1 > t->c) t->c = c + 1; + /****************************may have bugs********************************/ + ///update len(v0->w) + ///node: t->d is not the length from this node's parent + ///it is the shortest edge + if (d + l < t->d) t->d = d + l; // update dist + } + ///assert(t->r > 0); + //if all incoming edges of w have visited + //push it to b->S + if (--(t->r) == 0) { + uint32_t x = get_real_length(g, w, NULL); + /****************************may have bugs for bubble********************************/ + if(x > 0) + { + kv_push(uint32_t, b->S, w); + } + else + { + ///at most one tip + if(n_tips != 0) goto pop_reset; + n_tips++; + tip_end = w; + } + /****************************may have bugs for bubble********************************/ + --n_pending; + } + } + // is_first = 0; + //if found a tip + /****************************may have bugs for bubble********************************/ + if(n_tips == 1) + { + if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) + { + kv_push(uint32_t, b->S, tip_end); + break; + } + else + { + goto pop_reset; + } + } + /****************************may have bugs for bubble********************************/ + ///if i < nv, that means (d + l > max_dist) + if (i < nv || b->S.n == 0) goto pop_reset; + } while (b->S.n > 1 || n_pending); + + if(is_switch) (*is_switch) = asg_bub_backtrack_check_switch(g, utg, v0, b); + if(is_pop) asg_bub_backtrack_primary(g, v0, b); + if(path_base_len || path_nodes) asg_bub_backtrack_primary_length(g, utg, v0, b, path_base_len, path_nodes); + + + n_pop = 1; +pop_reset: + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + binfo_t *t = &b->a[b->b.a[i]]; + t->s = t->c = t->d = t->m = t->nc = t->np = 0; + } + return n_pop; +} + + +int bub_complex_hamming(asg_t *sg, ma_ug_t *ug, uint32_t beg_utg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, kvec_t_u32_warp* stack, +int max_hang, int min_ovlp, uint8_t* trio_flag, uint8_t* vis_flag, kv_asg_arc_t* e, buf_t *b, uint64_t tLen) +{ + uint32_t k_i, k_j, k_v, rID; + int is_switch_0, is_switch_1; + ma_utg_t* nsu = NULL; + + is_switch_0 = is_switch_1 = 1; + asg_bub_pop1_primary_trio_switch_check(ug->g, ug, beg_utg, tLen, b, FATHER, DROP, 0, NULL, NULL, &is_switch_0); + + if(is_switch_0 == 0) + { + asg_bub_pop1_primary_trio_switch_check(ug->g, ug, beg_utg, tLen, b, MOTHER, DROP, 0, NULL, NULL, &is_switch_1); + } + + + for (k_i = 0; k_i < b->b.n; k_i++) + { + if((b->b.a[k_i]>>1)==(beg_utg>>1) || (b->b.a[k_i]>>1)==(b->S.a[0]>>1)) continue; + nsu = &(ug->u.a[b->b.a[k_i]>>1]); + for (k_j = 0; k_j < nsu->n; k_j++) + { + rID = nsu->a[k_j]>>33; + if(R_INF.trio_flag[rID] == DROP) R_INF.trio_flag[rID] = AMBIGU; + } + } + + if(is_switch_0 == 0 && is_switch_1 == 0) return 0; + + + + uint32_t i, sink_utg, begRid, sinkRid; + sink_utg = b->S.a[0]^1; + + if(beg_utg&1) + { + begRid = ug->u.a[beg_utg>>1].start^1; + } + else + { + begRid = ug->u.a[beg_utg>>1].end^1; + } + + if(sink_utg&1) + { + sinkRid = ug->u.a[sink_utg>>1].start; + } + else + { + sinkRid = ug->u.a[sink_utg>>1].end; + } + + + + + asg_arc_t *acur = NULL; + uint32_t cur, ncur, v, n_vx = sg->n_seq<<1; + stack->a.n = 0; + memset(vis_flag, 0, n_vx); + + kv_push(uint32_t, stack->a, begRid); + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + ncur = asg_arc_n(sg, cur); + acur = asg_arc_a(sg, cur); + vis_flag[cur] = 1; + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if(vis_flag[acur[i].v]) continue; + if(acur[i].v == sinkRid) continue; + kv_push(uint32_t, stack->a, acur[i].v); + } + } + vis_flag[sinkRid] = 1; + + + ma_hit_t_alloc* x = NULL; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + int32_t r; + asg_arc_t t0, t1; + + + for (k_i = 0; k_i < b->b.n; k_i++) + { + if((b->b.a[k_i]>>1)==(beg_utg>>1) || (b->b.a[k_i]>>1)==(b->S.a[0]>>1)) continue; + // nsu = &(ug->u.a[a[k_i]>>1]); + nsu = &(ug->u.a[b->b.a[k_i]>>1]); + for (k_j = 0; k_j < nsu->n; k_j++) + { + rID = nsu->a[k_j]>>33; + for (k_v = 0; k_v < 2; k_v++) + { + v = (rID<<1) + k_v; + if(vis_flag[v] == 0) continue; + x = &(sources[v>>1]); + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(st->del || sg->seq[Get_tn(*h)].del) continue; + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t0); + + ///if it is a contained read, skip + if(r < 0) continue; + if((t0.ul>>32) != v) continue; + if(vis_flag[t0.ul>>32] == 0 || vis_flag[t0.v] == 0) continue; + if(get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, (t0.v^1), ((t0.ul>>32)^1), &t1)) { + kv_push(asg_arc_t, *e, t0); kv_push(asg_arc_t, *e, t1); + } + } + } + } + } + + return 1; +} + + +int gen_switch_phasing(asg_t *sg, ma_ug_t *ug, uint64_t bi, +ma_hit_t_alloc* src, ma_sub_t *cov, int32_t max_hang, +int32_t min_ovlp, uint8_t* trio_flag, uint8_t* vis_r_flag, +buf_t *b, uint64_t tLen, uint64_t vis_f, asg_t *res, asg64_v *sv) +{ + uint32_t k_i, k_j, k_v, rev, z, zn; asg_arc_t *za; + ma_utg_t* nsu = NULL; int sw0, sw1; + + sw0 = sw1 = 1; + asg_bub_pop1_primary_trio_switch_check(ug->g, ug, bi, tLen, b, FATHER, DROP, 0, NULL, NULL, &sw0); + if(sw0 == 0) { + asg_bub_pop1_primary_trio_switch_check(ug->g, ug, bi, tLen, b, MOTHER, DROP, 0, NULL, NULL, &sw1); + } + + for (k_i = 0; k_i < b->b.n; k_i++) { + if((b->b.a[k_i]>>1)==(bi>>1) || (b->b.a[k_i]>>1)==(b->S.a[0]>>1)) continue; + nsu = &(ug->u.a[b->b.a[k_i]>>1]); + for (k_j = 0; k_j < nsu->n; k_j++) { + if(R_INF.trio_flag[nsu->a[k_j]>>33] == DROP) R_INF.trio_flag[nsu->a[k_j]>>33] = AMBIGU; + } + } + if(sw0 == 0 && sw1 == 0) return 0; + + uint64_t i, ei = b->S.a[0]^1, v, bv, ev; + for (k_i = 0; k_i < b->b.n; k_i++) { + if((b->b.a[k_i]>>1)==(bi>>1) || (b->b.a[k_i]>>1)==(b->S.a[0]>>1)) continue; + nsu = &(ug->u.a[b->b.a[k_i]>>1]); rev = b->b.a[k_i]&1; + for (k_j = 0; k_j < nsu->n; k_j++) { + v = nsu->a[k_j]>>32; if(rev) v ^= 1; + vis_r_flag[v] = vis_f; + } + } + bv = (bi&1)?(ug->u.a[bi>>1].start^1):(ug->u.a[bi>>1].end^1); //vis_r_flag[bv] = vis_f; + ev = (ei&1)?(ug->u.a[ei>>1].start^1):(ug->u.a[ei>>1].end^1); //vis_r_flag[ev] = vis_f; + + ma_hit_t_alloc* x = NULL; + ma_hit_t *h; ma_sub_t *sq, *st; + int32_t r; asg_arc_t t0, t1, *p; + + for (k_i = 0; k_i < b->b.n; k_i++) { + if((b->b.a[k_i]>>1)==(bi>>1) || (b->b.a[k_i]>>1)==(b->S.a[0]>>1)) continue; + nsu = &(ug->u.a[b->b.a[k_i]>>1]); + for (k_j = 0; k_j < nsu->n; k_j++) { + for (k_v = 0; k_v < 2; k_v++) { + v = ((nsu->a[k_j]>>33)<<1) + k_v; + if(vis_r_flag[v] != vis_f) continue;; + x = &(src[v>>1]); + za = asg_arc_a(sg, v); + zn = asg_arc_n(sg, v); + for (i = 0; i < x->length; i++) { + h = &(x->buffer[i]); + // if(!(h->el)) continue; + sq = &(cov[Get_qn(*h)]); st = &(cov[Get_tn(*h)]); + if(st->del || sg->seq[Get_tn(*h)].del) continue; + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t0); + + ///if it is a contained read, skip + if(r < 0) continue; + if((t0.ul>>32) != v) continue; + if((vis_r_flag[t0.ul>>32] != vis_f) || (vis_r_flag[t0.v] != vis_f)) continue; + for (z = 0; (z < zn) && (za[z].v != t0.v); z++); + if(z < zn) continue; + if(get_edge_from_source(src, cov, NULL, max_hang, min_ovlp, (t0.v^1), ((t0.ul>>32)^1), &t1)) { + p = asg_arc_pushp(res); *p = t0; + p = asg_arc_pushp(res); *p = t1; + } + } + + } + } + } + kv_push(uint64_t, *sv, (bv<<32)|(ev)); + return 1; +} + +int asg_arc_del_trans_aux(asg_t *g, asg_t *aux, uint8_t *mark, int fuzz) +{ + uint32_t v, w, n_vtx = g->n_seq * 2, n_reduced = 0; + uint32_t L, i, j, nv0, nv1, kv; asg_arc_t *av0, *av1; + asg_arc_t *aw0, *aw1; uint32_t nw0, nw1; + memset(mark, 0, sizeof((*mark))*n_vtx); + + for (v = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + nv0 = asg_arc_n(g, v); av0 = asg_arc_a(g, v); + nv1 = asg_arc_n(aux, v); av1 = asg_arc_a(aux, v); + if (nv0 + nv1 == 0) continue; + //all outnode of v should be set to "not reduce" + for (i = kv = 0; i < nv0; ++i) { + if(av0[i].del) continue; + mark[av0[i].v] = 1; kv++; + } + for (i = 0; i < nv1; ++i) { + if(av1[i].del) continue; + mark[av1[i].v] = 1; kv++; + } + if(kv == 0) continue; + + ///av[nv-1] is longest out-dege + L = 0; + if(nv0) L = asg_arc_len(av0[nv0-1]); + if(nv1 && L < asg_arc_len(av1[nv1-1])) L = asg_arc_len(av1[nv1-1]); + L += fuzz; + for (i = 0; i < nv0; ++i) { + //w is an out-node of v + w = av0[i].v; if (mark[w] != 1) continue; ///w has already been reduced + nw0 = asg_arc_n(g, w); aw0 = asg_arc_a(g, w); + nw1 = asg_arc_n(aux, w); aw1 = asg_arc_a(aux, w); + + for (j = 0; j < nw0 && asg_arc_len(aw0[j]) + asg_arc_len(av0[i]) <= L; ++j) + if (mark[aw0[j].v]) mark[aw0[j].v] = 2; + for (j = 0; j < nw1 && asg_arc_len(aw1[j]) + asg_arc_len(av0[i]) <= L; ++j) + if (mark[aw1[j].v]) mark[aw1[j].v] = 2; + } + for (i = 0; i < nv1; ++i) { + //w is an out-node of v + w = av1[i].v; if (mark[w] != 1) continue; ///w has already been reduced + nw0 = asg_arc_n(g, w); aw0 = asg_arc_a(g, w); + nw1 = asg_arc_n(aux, w); aw1 = asg_arc_a(aux, w); + + for (j = 0; j < nw0 && asg_arc_len(aw0[j]) + asg_arc_len(av1[i]) <= L; ++j) + if (mark[aw0[j].v]) mark[aw0[j].v] = 2; + for (j = 0; j < nw1 && asg_arc_len(aw1[j]) + asg_arc_len(av1[i]) <= L; ++j) + if (mark[aw1[j].v]) mark[aw1[j].v] = 2; + } + //remove edges + for (i = 0; i < nv0; ++i) { + if (mark[av0[i].v] == 2) { + av0[i].del = 1; ++n_reduced; + } + mark[av0[i].v] = 0; + } + for (i = 0; i < nv1; ++i) mark[av1[i].v] = 0; + } + + if (n_reduced) { + asg_cleanup(g); + asg_symm(g); + } + + return n_reduced; +} +/** +#define ba_fetch(pa, ca, v0, v) (((v)==(v0))?(pa)[(v)]:(ca)[(v)]) +uint64_t rd_hm_bub(asg_t *g, asg_t *ref, uint32_t v0, uint64_t max_dist, buf_t *b) +{ + uint32_t i0, i1, n_pending = 0, is_first = 1, n_tips, tip_end; uint64_t n_pop = 0; + uint32_t v, w, d, nv0, nv1, l, x, i; asg_arc_t *av0, *av1; binfo_t *t, *pa, *ca; + if (g->seq[v0>>1].del) return 0; // already deleted + nv0 = g?get_real_length(g, v0, NULL):0; + nv1 = ref?get_real_length(ref, v0, NULL):0; + // if((v0 == 4386) && (!ref)) { + // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), nv0::%u, nv1::%u\n", __func__, v0>>1, v0&1, + // nv0, nv1); + // } + if((nv0+nv1) < 2) return 0; + pa = b->a; ca = b->a + (g->n_seq<<1); + // if(v0 >= (ref->n_seq<<1)) { + // fprintf(stderr, "[M::%s] v0::%u, ref->n_seq::%u\n", __func__, v0, ref->n_seq); + // } + b->S.n = b->T.n = b->b.n = b->e.n = 0; + v = v0; t = &(ba_fetch(pa, ca, v0, v)); + t->c = t->d = t->m = t->nc = t->np = 0; + ///b->S is the nodes with all incoming edges visited + kv_push(uint32_t, b->S, v0); + n_tips = 0; tip_end = (uint32_t)-1; + + do { + ///v is a node that all incoming edges have been visited + ///d is the distance from v0 to v + v = kv_pop(b->S); d = (ba_fetch(pa, ca, v0, v)).d; + nv0 = 0; av0 = NULL; nv1 = 0; av1 = NULL; i0 = i1 = 0; + if(g) { + nv0 = asg_arc_n(g, v); av0 = asg_arc_a(g, v); + } + if(ref) { + nv1 = asg_arc_n(ref, v); av1 = asg_arc_a(ref, v); + } + // if((v0 == 4386) && (!ref)) { + // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), v>>1::%u(v&1::%u)\n", __func__, v0>>1, v0&1, v>>1, v&1); + // } + ///all out-edges of v + for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors + if (av0[i0].del) continue; + w = av0[i0].v; l = (uint32_t)av0[i0].ul; t = &((ba_fetch(pa, ca, v0, w))); + // if((v0 == 4386) && (!ref)) { + // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), w>>1::%u(w&1::%u)\n", + // __func__, v0>>1, v0&1, w>>1, w&1); + // } + if ((w>>1) == (v0>>1)) goto pop_rd_hm_bub; + if(is_first) l = 0; + if (d + l > max_dist) break; // too far + ///unvisited node + if (t->s == 0) { // this vertex has never been visited + kv_push(uint32_t, b->b, w); // save it for revert + t->p = v, t->s = 1, t->d = d + l; + t->r = (g?get_real_length(g, w^1, NULL):0)+(ref?get_real_length(ref, w^1, NULL):0); + ++n_pending; + } else { // visited before + ///the shortest path + if (d + l < t->d) t->d = d + l; // update dist + } + // if((v0 == 4386) && (!ref) && ((w>>1) == 2597)) { + // fprintf(stderr, "[M::%s] w>>1::%u(w&1::%u), t->r::%u\n", + // __func__, w>>1, w&1, t->r); + // } + //if all incoming edges of w have visited + //push it to b->S + if (--(t->r) == 0) { + x = (g?get_real_length(g, w, NULL):0)+(ref?get_real_length(ref, w, NULL):0); + // if((v0 == 4386) && (!ref) && ((w>>1) == 2597)) { + // fprintf(stderr, "[M::%s] w>>1::%u(w&1::%u), t->r::%u, x::%u, b->S.n::%u\n", + // __func__, w>>1, w&1, t->r, x, (uint32_t)b->S.n); + // } + if(x > 0) { + // if((v0 == 4386) && (!ref)) { + // fprintf(stderr, "+[M::%s] v0>>1::%u(v0&1::%u), push_w>>1::%u(w&1::%u)\n", + // __func__, v0>>1, v0&1, w>>1, w&1); + // uint32_t m; + // for (m = 0; m < b->S.n; m++) { + // fprintf(stderr, "+[M::%s] m>>1::%u(m&1::%u)\n", __func__, b->S.a[m]>>1, b->S.a[m]&1); + // } + // } + kv_push(uint32_t, b->S, w); + } else { + ///at most one tip + if(n_tips != 0) goto pop_rd_hm_bub; + n_tips++; tip_end = w; + } + --n_pending; + } + } + if (i0 >= nv0) { + for (i1 = 0; i1 < nv1; ++i1) { // loop through v's neighbors + if (av1[i1].del) continue; + w = av1[i1].v; l = (uint32_t)av1[i1].ul; t = &((ba_fetch(pa, ca, v0, w))); + if ((w>>1) == (v0>>1)) goto pop_rd_hm_bub; + if(is_first) l = 0; + if (d + l > max_dist) break; // too far + ///unvisited node + if (t->s == 0) { // this vertex has never been visited + kv_push(uint32_t, b->b, w); // save it for revert + t->p = v, t->s = 1, t->d = d + l; + t->r = (g?get_real_length(g, w^1, NULL):0)+(ref?get_real_length(ref, w^1, NULL):0); + ++n_pending; + } else { // visited before + ///the shortest path + if (d + l < t->d) t->d = d + l; // update dist + } + + //if all incoming edges of w have visited + //push it to b->S + if (--(t->r) == 0) { + x = (g?get_real_length(g, w, NULL):0)+(ref?get_real_length(ref, w, NULL):0); + if(x > 0) { + // if((v0 == 4386) && (!ref)) { + // fprintf(stderr, "-[M::%s] v0>>1::%u(v0&1::%u), push_w>>1::%u(w&1::%u)\n", + // __func__, v0>>1, v0&1, w>>1, w&1); + // } + kv_push(uint32_t, b->S, w); + } else { + ///at most one tip + if(n_tips != 0) goto pop_rd_hm_bub; + n_tips++; tip_end = w; + } + --n_pending; + } + } + } + + is_first = 0; + //if found a tip + if(n_tips == 1) { + if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) { + // if((v0 == 4386) && (!ref)) { + // fprintf(stderr, ">[M::%s] v0>>1::%u(v0&1::%u), push_w>>1::%u(w&1::%u)\n", + // __func__, v0>>1, v0&1, tip_end>>1, tip_end&1); + // } + kv_push(uint32_t, b->S, tip_end); + break; + } else { + goto pop_rd_hm_bub; + } + } + // if((v0 == 4386) && (!ref)) { + // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), b->S.n::%u, n_pending::%u\n", + // __func__, v0>>1, v0&1, (uint32_t)b->S.n, n_pending); + // } + ///if i < nv, that means (d + l > max_dist) + if (i0 < nv0 || i1 < nv1 || b->S.n == 0) goto pop_rd_hm_bub; + } while (b->S.n > 1 || n_pending); + n_pop = 1; + pop_rd_hm_bub: + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + t = &((ba_fetch(pa, ca, v0, b->b.a[i]))); + t->s = t->c = t->d = t->m = t->nc = t->np = 0; + } + return n_pop; +} + +uint64_t rd_hm_drop0(asg_t *g, asg_t *ref, uint32_t v, double cutoff) +{ + uint32_t nv0, nv1, mol = 0, i0, i1, ncut = 0; asg_arc_t *av0, *av1; + nv0 = asg_arc_n(g, v); av0 = asg_arc_a(g, v); + nv1 = asg_arc_n(ref, v); av1 = asg_arc_a(ref, v); + if(cutoff < 1) { + for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors + if (av0[i0].del) continue; + if(mol < av0[i0].ol) mol = av0[i0].ol; + } + for (i1 = 0; i1 < nv1; ++i1) { // loop through v's neighbors + if (av1[i1].del) continue; + if(mol < av1[i1].ol) mol = av1[i1].ol; + } + if(mol > 0) { + for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors + if (av0[i0].del) continue; + if(av0[i0].ol < (mol*cutoff)) { + av0[i0].del = 1; asg_arc_del(g, av0[i0].v^1, (av0[i0].ul>>32)^1, 1); + ncut++; + } + } + } + } else { + for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors + if (av0[i0].del) continue; + av0[i0].del = 1; asg_arc_del(g, av0[i0].v^1, (av0[i0].ul>>32)^1, 1); + ncut++; + } + } + return ncut; +} + +uint64_t rd_hm_drop(asg_t *g, asg_t *ref, uint32_t v0, uint32_t v1, double cutoff, buf_t *b) +{ + uint32_t i1, ncut = 0; + uint32_t v, w, nv1, i; asg_arc_t *av1; + if (g->seq[v0>>1].del) return 0; // already deleted + b->S.n = 0; binfo_t *pa, *ca; + pa = b->a; ca = b->a + (g->n_seq<<1); + ///b->S is the nodes with all incoming edges visited + kv_push(uint32_t, b->S, v0); + while(b->S.n) { + v = kv_pop(b->S); + if((ba_fetch(pa, ca, v0, v)).s) continue; + (ba_fetch(pa, ca, v0, v)).s = 1; + kv_push(uint32_t, b->b, v); // save it for revert + nv1 = asg_arc_n(ref, v); av1 = asg_arc_a(ref, v); + for (i1 = 0; i1 < nv1; ++i1) { // loop through v's neighbors + if (av1[i1].del) continue; + w = av1[i1].v; + if((ba_fetch(pa, ca, v0, w)).s || w == v1) continue; + kv_push(uint32_t, b->S, w); + } + } + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + v = b->b.a[i]; (ba_fetch(pa, ca, v0, b->b.a[i])).s = 0; + if(v == v0 || v == v1) continue; + ncut += rd_hm_drop0(g, ref, v, cutoff); + ncut += rd_hm_drop0(g, ref, v^1, cutoff); + } + ncut += rd_hm_drop0(g, ref, v0, cutoff); + ncut += rd_hm_drop0(g, ref, v1^1, cutoff); + return ncut; +} + +static void rd_hamming_symm(void *data, long i, int tid) // callback for kt_for() +{ + rd_hamming_t *s = (rd_hamming_t *)data; buf_t *b = &(s->a[tid]); + uint32_t st = s->rr->a[i]>>32, ed = (uint32_t)(s->rr->a[i]), p, k, ncut; + double step = 0.2, cuttoff; uint64_t max_dist = s->max_dist; + p = rd_hm_bub(s->g, s->ref, st, max_dist, b); + if(p) { + // if(!(b->S.a[0] == (ed^1))) { + // fprintf(stderr, "[M::%s] st>>1::%u(st&1::%u), ed>>1::%u(ed&1::%u), S[0]>>1::%u(S[0]&1::%u), max_dist::%lu\n", + // __func__, st>>1, st&1, ed>>1, ed&1, b->S.a[0]>>1, b->S.a[0]&1, max_dist); + // } + assert(b->S.a[0] == (ed^1)); + return; + } + ///recalculate max_dist + p = rd_hm_bub(s->ref, NULL, st, max_dist, b); + // if(!p) { + // fprintf(stderr, "[M::%s] st>>1::%u(st&1::%u), ed>>1::%u(ed&1::%u), max_dist::%lu\n", + // __func__, st>>1, st&1, ed>>1, ed&1, max_dist); + // } + assert(p); assert(b->S.a[0] == (ed^1)); + for (k = max_dist = 0; k < b->b.n; ++k) { + if(b->b.a[k]==st || b->b.a[k]==b->S.a[0]) continue; + max_dist += s->ref->seq[b->b.a[k]>>1].len; + } + max_dist += s->ref->seq[st>>1].len; + max_dist += s->ref->seq[b->S.a[0]>>1].len; + p = rd_hm_bub(s->g, s->ref, st, max_dist, b); + if(p) { + assert(b->S.a[0] == (ed^1)); + return; + } + + for (cuttoff = step; cuttoff < 1.0; cuttoff += step) { + ncut = rd_hm_drop(s->g, s->ref, st, ed^1, cuttoff, b); + p = rd_hm_bub(s->g, s->ref, st, max_dist, b); + if(p) { + assert(b->S.a[0] == (ed^1)); + return; + } + if(!ncut) break; + } + rd_hm_drop(s->g, s->ref, st, ed^1, 1024, b); + p = rd_hm_bub(s->g, s->ref, st, max_dist, b); + if(p) { + assert(b->S.a[0] == (ed^1)); + return; + } +} + +void reduce_hamming_error_adv(ma_ug_t *iug, asg_t *sg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +int max_hang, int min_ovlp, long long gap_fuzz, R_to_U *ru, bubble_type* bub) +{ + double index_time = yak_realtime(); + ma_ug_t *ug = NULL; rd_hamming_t aux_t; memset((&aux_t), 0, sizeof(aux_t)); + ug = (iug)?(iug):(ma_ug_gen_primary(sg, PRIMARY_LABLE)); + uint8_t* vis_flag = NULL; CALLOC(vis_flag, sg->n_seq*2); + uint32_t fix_bub = 0; asg_t *g = ug->g; + uint32_t v, n_vtx = g->n_seq * 2, n_arc, n_arc_0 = sg->n_arc, nv, i; + uint64_t n_pop = 0, max_dist; asg_arc_t *p; + asg_arc_t *av; asg_t *ig = asg_init(); asg64_v sv; kv_init(sv); + buf_t b; memset(&b, 0, sizeof(buf_t)); + b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + uint8_t* bs_flag = NULL; CALLOC(bs_flag, n_vtx); + for (i = 0; i < ug->g->n_seq; i++) ug->g->seq[i].c = 0; + max_dist = get_bub_pop_max_dist_advance(g, &b); + + if(max_dist > 0) { + if(bub) { + for (i = 0; i < bub->f_bub; i++) { + get_bubbles(bub, i, &v, NULL, NULL, NULL, NULL); + fix_bub += gen_switch_phasing(sg, ug, v, sources, coverage_cut, max_hang, min_ovlp, + R_INF.trio_flag, vis_flag, &b, max_dist, 1, ig, &sv); + } + } else { + for (v = 0; v < n_vtx; ++v) { + if(bs_flag[v] != 0) continue; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del) continue; + ///some edges could be deleted + for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs + if (!av[i].del) ++n_arc; + if (n_arc < 2) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, max_dist, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (i = 0; i < b.b.n; i++) { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + bs_flag[b.b.a[i]] = bs_flag[b.b.a[i]^1] = 1; + } + bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 3; + } + } + + //traverse all node with two directions + for (v = 0; v < n_vtx; ++v) { + if(bs_flag[v] !=2) continue; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del) continue; + ///some edges could be deleted + for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs + if (!av[i].del) ++n_arc; + if (n_arc > 1) { + fix_bub += gen_switch_phasing(sg, ug, v, sources, coverage_cut, max_hang, min_ovlp, + R_INF.trio_flag, vis_flag, &b, max_dist, 1, ig, &sv); + } + } + } + } + free(bs_flag); if(!iug) ma_ug_destroy(ug); + + if(sv.n > 0) { + ig->n_seq = ig->m_seq = sg->n_seq; + MALLOC(ig->seq, ig->n_seq); + memcpy(ig->seq, sg->seq, (sizeof((*(ig->seq)))*ig->n_seq)); + asg_cleanup(ig); asg_arc_del_trans_aux(ig, sg, vis_flag, gap_fuzz); + aux_t.n_thread = asm_opt.thread_num; CALLOC(aux_t.a, aux_t.n_thread); + REALLOC(b.a, (ig->n_seq<<2)); memset(b.a, 0, sizeof((*(b.a)))*(ig->n_seq<<2)); + for (i = 0; i < aux_t.n_thread; i++) aux_t.a[i].a = b.a; + aux_t.g = ig; aux_t.ref = sg; aux_t.rr = &sv; aux_t.max_dist = max_dist; + // print_debug_gfa(ug, sg, coverage_cut, "debug_hamming", sources, ru); + kt_for(aux_t.n_thread, rd_hamming_symm, &aux_t, aux_t.rr->n);///all ul + ug + for (i = 0; i < aux_t.n_thread; i++) { + free(aux_t.a[i].S.a); free(aux_t.a[i].T.a); + free(aux_t.a[i].b.a); free(aux_t.a[i].e.a); + } + free(aux_t.a); + } + free(sv.a); free(vis_flag); + + for (i = n_pop = 0; i < ig->n_arc; i++) { + if(ig->arc[i].del) continue; + p = asg_arc_pushp(sg); *p = (ig->arc[i]); n_pop++; + } + if(n_pop) { + free(sg->idx); + sg->idx = 0; + sg->is_srt = 0; + asg_cleanup(sg); + asg_symm(sg); + asg_arc_del_trans(sg, gap_fuzz); + } + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); asg_destroy(ig); + fprintf(stderr, "[M::%s::%.3f] # inserted edges: %u, # fixed bubbles: %u\n", + __func__, yak_realtime() - index_time, sg->n_arc - n_arc_0, fix_bub); +} +**/ + +uint64_t rd_hm_bub(asg_t *g, asg_t *ref, uint32_t v0, uint64_t max_dist, buf_t *b) +{ + uint32_t i0, i1, n_pending = 0, is_first = 1, n_tips, tip_end; uint64_t n_pop = 0; + uint32_t v, w, d, nv0, nv1, l, x, i; asg_arc_t *av0, *av1; binfo_t *t; + if (g->seq[v0>>1].del) return 0; // already deleted + nv0 = g?get_real_length(g, v0, NULL):0; + nv1 = ref?get_real_length(ref, v0, NULL):0; + // if((v0 == 4386) && (!ref)) { + // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), nv0::%u, nv1::%u\n", __func__, v0>>1, v0&1, + // nv0, nv1); + // } + if((nv0+nv1)<2) return 0; + // if(v0 >= (ref->n_seq<<1)) { + // fprintf(stderr, "[M::%s] v0::%u, ref->n_seq::%u\n", __func__, v0, ref->n_seq); + // } + b->S.n = b->T.n = b->b.n = b->e.n = 0; + b->a[v0].c = b->a[v0].d = b->a[v0].m = b->a[v0].nc = b->a[v0].np = 0; + ///b->S is the nodes with all incoming edges visited + kv_push(uint32_t, b->S, v0); + n_tips = 0; tip_end = (uint32_t)-1; + + do { + ///v is a node that all incoming edges have been visited + ///d is the distance from v0 to v + v = kv_pop(b->S); d = b->a[v].d; + nv0 = 0; av0 = NULL; nv1 = 0; av1 = NULL; i0 = i1 = 0; + if(g) { + nv0 = asg_arc_n(g, v); av0 = asg_arc_a(g, v); + } + if(ref) { + nv1 = asg_arc_n(ref, v); av1 = asg_arc_a(ref, v); + } + // if((v0 == 4386) && (!ref)) { + // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), v>>1::%u(v&1::%u)\n", __func__, v0>>1, v0&1, v>>1, v&1); + // } + ///all out-edges of v + for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors + if (av0[i0].del) continue; + w = av0[i0].v; l = (uint32_t)av0[i0].ul; t = &b->a[w]; + // if((v0 == 4386) && (!ref)) { + // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), w>>1::%u(w&1::%u)\n", + // __func__, v0>>1, v0&1, w>>1, w&1); + // } + if ((w>>1) == (v0>>1)) goto pop_rd_hm_bub; + if(is_first) l = 0; + if (d + l > max_dist) break; // too far + ///unvisited node + if (t->s == 0) { // this vertex has never been visited + kv_push(uint32_t, b->b, w); // save it for revert + t->p = v, t->s = 1, t->d = d + l; + t->r = (g?get_real_length(g, w^1, NULL):0)+(ref?get_real_length(ref, w^1, NULL):0); + ++n_pending; + } else { // visited before + ///the shortest path + if (d + l < t->d) t->d = d + l; // update dist + } + // if((v0 == 4386) && (!ref) && ((w>>1) == 2597)) { + // fprintf(stderr, "[M::%s] w>>1::%u(w&1::%u), t->r::%u\n", + // __func__, w>>1, w&1, t->r); + // } + //if all incoming edges of w have visited + //push it to b->S + if (--(t->r) == 0) { + x = (g?get_real_length(g, w, NULL):0)+(ref?get_real_length(ref, w, NULL):0); + // if((v0 == 4386) && (!ref) && ((w>>1) == 2597)) { + // fprintf(stderr, "[M::%s] w>>1::%u(w&1::%u), t->r::%u, x::%u, b->S.n::%u\n", + // __func__, w>>1, w&1, t->r, x, (uint32_t)b->S.n); + // } + if(x > 0) { + // if((v0 == 4386) && (!ref)) { + // fprintf(stderr, "+[M::%s] v0>>1::%u(v0&1::%u), push_w>>1::%u(w&1::%u)\n", + // __func__, v0>>1, v0&1, w>>1, w&1); + // uint32_t m; + // for (m = 0; m < b->S.n; m++) { + // fprintf(stderr, "+[M::%s] m>>1::%u(m&1::%u)\n", __func__, b->S.a[m]>>1, b->S.a[m]&1); + // } + // } + kv_push(uint32_t, b->S, w); + } else { + ///at most one tip + if(n_tips != 0) goto pop_rd_hm_bub; + n_tips++; tip_end = w; + } + --n_pending; + } + } + if (i0 >= nv0) { + for (i1 = 0; i1 < nv1; ++i1) { // loop through v's neighbors + if (av1[i1].del) continue; + w = av1[i1].v; l = (uint32_t)av1[i1].ul; t = &b->a[w]; + if ((w>>1) == (v0>>1)) goto pop_rd_hm_bub; + if(is_first) l = 0; + if (d + l > max_dist) break; // too far + ///unvisited node + if (t->s == 0) { // this vertex has never been visited + kv_push(uint32_t, b->b, w); // save it for revert + t->p = v, t->s = 1, t->d = d + l; + t->r = (g?get_real_length(g, w^1, NULL):0)+(ref?get_real_length(ref, w^1, NULL):0); + ++n_pending; + } else { // visited before + ///the shortest path + if (d + l < t->d) t->d = d + l; // update dist + } + + //if all incoming edges of w have visited + //push it to b->S + if (--(t->r) == 0) { + x = (g?get_real_length(g, w, NULL):0)+(ref?get_real_length(ref, w, NULL):0); + if(x > 0) { + // if((v0 == 4386) && (!ref)) { + // fprintf(stderr, "-[M::%s] v0>>1::%u(v0&1::%u), push_w>>1::%u(w&1::%u)\n", + // __func__, v0>>1, v0&1, w>>1, w&1); + // } + kv_push(uint32_t, b->S, w); + } else { + ///at most one tip + if(n_tips != 0) goto pop_rd_hm_bub; + n_tips++; tip_end = w; + } + --n_pending; + } + } + } + + is_first = 0; + //if found a tip + if(n_tips == 1) { + if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) { + // if((v0 == 4386) && (!ref)) { + // fprintf(stderr, ">[M::%s] v0>>1::%u(v0&1::%u), push_w>>1::%u(w&1::%u)\n", + // __func__, v0>>1, v0&1, tip_end>>1, tip_end&1); + // } + kv_push(uint32_t, b->S, tip_end); + break; + } else { + goto pop_rd_hm_bub; + } + } + // if((v0 == 4386) && (!ref)) { + // fprintf(stderr, "[M::%s] v0>>1::%u(v0&1::%u), b->S.n::%u, n_pending::%u\n", + // __func__, v0>>1, v0&1, (uint32_t)b->S.n, n_pending); + // } + ///if i < nv, that means (d + l > max_dist) + if (i0 < nv0 || i1 < nv1 || b->S.n == 0) goto pop_rd_hm_bub; + } while (b->S.n > 1 || n_pending); + n_pop = 1; + pop_rd_hm_bub: + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + t = &b->a[b->b.a[i]]; + t->s = t->c = t->d = t->m = t->nc = t->np = 0; + } + return n_pop; +} + +uint64_t rd_hm_drop0(asg_t *g, asg_t *ref, uint32_t v, double cutoff, uint32_t drop_inexact) +{ + uint32_t nv0, nv1, mol = 0, i0, i1, ncut = 0; asg_arc_t *av0, *av1; + nv0 = asg_arc_n(g, v); av0 = asg_arc_a(g, v); + nv1 = asg_arc_n(ref, v); av1 = asg_arc_a(ref, v); + if(drop_inexact) { + for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors + if (av0[i0].del) continue; + if (av0[i0].el) continue; + av0[i0].del = 1; asg_arc_del(g, av0[i0].v^1, (av0[i0].ul>>32)^1, 1); + ncut++; + } + } else if(cutoff < 1) { + for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors + if (av0[i0].del) continue; + if(mol < av0[i0].ol) mol = av0[i0].ol; + } + for (i1 = 0; i1 < nv1; ++i1) { // loop through v's neighbors + if (av1[i1].del) continue; + if(mol < av1[i1].ol) mol = av1[i1].ol; + } + if(mol > 0) { + for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors + if (av0[i0].del) continue; + if(av0[i0].ol < (mol*cutoff)) { + av0[i0].del = 1; asg_arc_del(g, av0[i0].v^1, (av0[i0].ul>>32)^1, 1); + ncut++; + } + } + } + } else { + for (i0 = 0; i0 < nv0; ++i0) { // loop through v's neighbors + if (av0[i0].del) continue; + av0[i0].del = 1; asg_arc_del(g, av0[i0].v^1, (av0[i0].ul>>32)^1, 1); + ncut++; + } + } + return ncut; +} + +uint64_t rd_hm_drop(asg_t *g, asg_t *ref, uint32_t v0, uint32_t v1, double cutoff, uint32_t drop_inexact, buf_t *b) +{ + uint32_t i1, ncut = 0; + uint32_t v, w, nv1, i; asg_arc_t *av1; + if (g->seq[v0>>1].del) return 0; // already deleted + ///b->S is the nodes with all incoming edges visited + b->S.n = 0; + kv_push(uint32_t, b->S, v0); + while(b->S.n) { + v = kv_pop(b->S); + if(b->a[v].s) continue; + b->a[v].s = 1; + kv_push(uint32_t, b->b, v); // save it for revert + nv1 = asg_arc_n(ref, v); av1 = asg_arc_a(ref, v); + for (i1 = 0; i1 < nv1; ++i1) { // loop through v's neighbors + if (av1[i1].del) continue; + w = av1[i1].v; + if(b->a[w].s || w == v1) continue; + kv_push(uint32_t, b->S, w); + } + } + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + v = b->b.a[i]; b->a[b->b.a[i]].s = 0; + if(v == v0 || v == v1) continue; + ncut += rd_hm_drop0(g, ref, v, cutoff, drop_inexact); + ncut += rd_hm_drop0(g, ref, v^1, cutoff, drop_inexact); + } + ncut += rd_hm_drop0(g, ref, v0, cutoff, drop_inexact); + ncut += rd_hm_drop0(g, ref, v1^1, cutoff, drop_inexact); + return ncut; +} + +void rd_hamming_symm(void *data, long i, int tid) // callback for kt_for() +{ + rd_hamming_t *s = (rd_hamming_t *)data; buf_t *b = &(s->a[tid]); + uint32_t st = s->rr->a[i]>>32, ed = (uint32_t)(s->rr->a[i]), p, k, ncut; + double step = 0.2, cuttoff; uint64_t max_dist = s->max_dist; + p = rd_hm_bub(s->g, s->ref, st, max_dist, b); + if(p) { + assert(b->S.a[0] == (ed^1)); + return; + } + ///recalculate max_dist + p = rd_hm_bub(s->ref, NULL, st, max_dist, b); + // if(!p) { + // fprintf(stderr, "[M::%s] st>>1::%u(st&1::%u), ed>>1::%u(ed&1::%u), max_dist::%lu\n", + // __func__, st>>1, st&1, ed>>1, ed&1, max_dist); + // } + assert(p); assert(b->S.a[0] == (ed^1)); + for (k = max_dist = 0; k < b->b.n; ++k) { + if(b->b.a[k]==st || b->b.a[k]==b->S.a[0]) continue; + max_dist += s->ref->seq[b->b.a[k]>>1].len; + } + max_dist += s->ref->seq[st>>1].len; + max_dist += s->ref->seq[b->S.a[0]>>1].len; + p = rd_hm_bub(s->g, s->ref, st, max_dist, b); + if(p) { + assert(b->S.a[0] == (ed^1)); + return; + } + + ///drop inexact edges first + cuttoff = -1; + ncut = rd_hm_drop(s->g, s->ref, st, ed^1, cuttoff, 1, b); + p = rd_hm_bub(s->g, s->ref, st, max_dist, b); + if(p) { + assert(b->S.a[0] == (ed^1)); + return; + } + + for (cuttoff = step; cuttoff < 1.0; cuttoff += step) { + ncut = rd_hm_drop(s->g, s->ref, st, ed^1, cuttoff, 0, b); + p = rd_hm_bub(s->g, s->ref, st, max_dist, b); + if(p) { + assert(b->S.a[0] == (ed^1)); + return; + } + if(!ncut) break; + } + rd_hm_drop(s->g, s->ref, st, ed^1, 1024, 0, b); + p = rd_hm_bub(s->g, s->ref, st, max_dist, b); + if(p) { + assert(b->S.a[0] == (ed^1)); + return; + } +} + +void rd_hamming_symm_simple(rd_hamming_t *s, uint32_t st, uint32_t ed) // callback for kt_for() +{ + buf_t *b = &(s->a[0]); double step = 0.2, cuttoff; uint64_t max_dist = s->max_dist; + // uint32_t st = s->rr->a[i]>>32, ed = (uint32_t)(s->rr->a[i]); + uint32_t p, k, ncut; + p = rd_hm_bub(s->g, s->ref, st, max_dist, b); + if(p) { + assert(b->S.a[0] == (ed^1)); + return; + } + ///recalculate max_dist + p = rd_hm_bub(s->ref, NULL, st, max_dist, b); + // if(!p) { + // fprintf(stderr, "[M::%s] st>>1::%u(st&1::%u), ed>>1::%u(ed&1::%u), max_dist::%lu\n", + // __func__, st>>1, st&1, ed>>1, ed&1, max_dist); + // } + assert(p); assert(b->S.a[0] == (ed^1)); + for (k = max_dist = 0; k < b->b.n; ++k) { + if(b->b.a[k]==st || b->b.a[k]==b->S.a[0]) continue; + max_dist += s->ref->seq[b->b.a[k]>>1].len; + } + max_dist += s->ref->seq[st>>1].len; + max_dist += s->ref->seq[b->S.a[0]>>1].len; + p = rd_hm_bub(s->g, s->ref, st, max_dist, b); + if(p) { + assert(b->S.a[0] == (ed^1)); + return; + } + + for (cuttoff = step; cuttoff < 1.0; cuttoff += step) { + ncut = rd_hm_drop(s->g, s->ref, st, ed^1, cuttoff, 0, b); + p = rd_hm_bub(s->g, s->ref, st, max_dist, b); + if(p) { + assert(b->S.a[0] == (ed^1)); + return; + } + if(!ncut) break; + } + rd_hm_drop(s->g, s->ref, st, ed^1, 1024, 0, b); + p = rd_hm_bub(s->g, s->ref, st, max_dist, b); + if(p) { + assert(b->S.a[0] == (ed^1)); + return; + } +} + +uint32_t pp_cut(uint32_t vi0, uint32_t v0, asg_t *g, asg_t *ref, asg32_v *sa, asg32_v *sb, uint32_t max_ext) +{ + //e078bbb4-47b8-49af-9221-889e67f7097a 0 47735 id:i:1477089 (w) + //f552c01e-a9ea-47f2-b1ab-a56f6afa3121 0 42133 id:i:1477068 (v) + // if((vi0>>1) == 1476811 || (vi0>>1) == 1479120) { + // fprintf(stderr, "\n\ns1s[M::%s] S\t%.*s(%c)\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, v0>>1), Get_NAME(R_INF, v0>>1), "+-"[v0&1]); + // } + uint32_t k, i, nv, nw, kv, kw, w, v = v0, ntip = 0, f; asg_arc_t *av, *aw; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (k = 0; k < nv && av[k].del; ++k); + if(k >= nv) return 1;///no new arcs + + // if((vi0>>1) == 1476811 || (vi0>>1) == 1479120) { + // fprintf(stderr, "s2s[M::%s] S\t%.*s(%c)\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, v0>>1), Get_NAME(R_INF, v0>>1), "+-"[v0&1]); + // } + + sa->n = sb->n = 0; + nv = asg_arc_n(ref, v); av = asg_arc_a(ref, v); + for (k = kv = 0; k < nv; ++k) { + if(av[k].del) continue; + kv++; w = av[k].v^1; + kv_push(u_int32_t, *sb, av-ref->arc + k + g->n_arc); + av[k].del = 1; + + nw = asg_arc_n(ref, w); aw = asg_arc_a(ref, w); + for (i = kw = f = 0; i < nw; i++) { + if(aw[i].del) continue; + if(aw[i].v == (v^1)) { + kv_push(u_int32_t, *sb, aw-ref->arc + i + g->n_arc); + aw[i].del = 1; f = 1; + } else { + // if(((vi0>>1) == 1476811 || (vi0>>1) == 1479120) && ((v>>1) == 1477068) && ((w>>1) == 1477089)) { + // fprintf(stderr, "arc_0[M::%s] L\t%.*s(%c)\t%.*s(%c)\tkw::%u\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, aw[i].ul>>33), Get_NAME(R_INF, aw[i].ul>>33), "+-"[(aw[i].ul>>32)&1], + // (int)Get_NAME_LENGTH(R_INF, aw[i].v>>1), Get_NAME(R_INF, aw[i].v>>1), "+-"[aw[i].v&1], kw); + // } + kw++; + } + } + assert(f); + nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); + for (i = 0; i < nw; i++) { + if(aw[i].del) continue; + // if(((vi0>>1) == 1476811 || (vi0>>1) == 1479120) && ((v>>1) == 1477068) && ((w>>1) == 1477089)) { + // fprintf(stderr, "arc_1[M::%s] L\t%.*s(%c)\t%.*s(%c)\tkw::%u\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, aw[i].ul>>33), Get_NAME(R_INF, aw[i].ul>>33), "+-"[(aw[i].ul>>32)&1], + // (int)Get_NAME_LENGTH(R_INF, aw[i].v>>1), Get_NAME(R_INF, aw[i].v>>1), "+-"[aw[i].v&1], kw); + // } + kw++; + } + + // if((vi0>>1) == 1476811 || (vi0>>1) == 1479120) { + // fprintf(stderr, "init_a[M::%s] L\t%.*s(%c)\t%.*s(%c)\tkw::%u\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, v>>1), Get_NAME(R_INF, v>>1), "+-"[v&1], + // (int)Get_NAME_LENGTH(R_INF, w>>1), Get_NAME(R_INF, w>>1), "+-"[w&1], kw); + // } + + if(!kw) {///a new tip + // if((vi0>>1) == 1476811 || (vi0>>1) == 1479120) { + // fprintf(stderr, "[M::%s] L\t%.*s(%c)\t%.*s(%c)\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, v0>>1), Get_NAME(R_INF, v0>>1), "+-"[v0&1], + // (int)Get_NAME_LENGTH(R_INF, w>>1), Get_NAME(R_INF, w>>1), "+-"[w&1]); + // } + kv_push(uint32_t, *sa, (w^1)); ntip++; + } + } + + while (sa->n) { + v = kv_pop(*sa); + + nv = asg_arc_n(ref, v); av = asg_arc_a(ref, v); + for (k = kv = 0; k < nv; ++k) { + if(av[k].del) continue; + kv_push(u_int32_t, *sb, av-ref->arc + k + g->n_arc); + av[k].del = 1; kv++; w = av[k].v^1; f = 0; + + nw = asg_arc_n(ref, w); aw = asg_arc_a(ref, w); + for (i = kw = 0; i < nw; i++) { + if(aw[i].del) continue; + if(aw[i].v == (v^1)) { + kv_push(u_int32_t, *sb, aw-ref->arc + i + g->n_arc); + aw[i].del = 1; f = 1; + } else { + // if(((vi0>>1) == 1476811 || (vi0>>1) == 1479120) && ((v>>1) == 1477068) && ((w>>1) == 1477089)) { + // fprintf(stderr, "arc_0_a[M::%s] L\t%.*s(%c)\t%.*s(%c)\tkw::%u\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, aw[i].ul>>33), Get_NAME(R_INF, aw[i].ul>>33), "+-"[(aw[i].ul>>32)&1], + // (int)Get_NAME_LENGTH(R_INF, aw[i].v>>1), Get_NAME(R_INF, aw[i].v>>1), "+-"[aw[i].v&1], kw); + // } + kw++; + } + } + assert(f); + nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); + for (i = 0; i < nw; i++) { + if(aw[i].del) continue; + // if(((vi0>>1) == 1476811 || (vi0>>1) == 1479120) && ((v>>1) == 1477068) && ((w>>1) == 1477089)) { + // fprintf(stderr, "arc_1_a[M::%s] L\t%.*s(%c)\t%.*s(%c)\tkw::%u\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, aw[i].ul>>33), Get_NAME(R_INF, aw[i].ul>>33), "+-"[(aw[i].ul>>32)&1], + // (int)Get_NAME_LENGTH(R_INF, aw[i].v>>1), Get_NAME(R_INF, aw[i].v>>1), "+-"[aw[i].v&1], kw); + // } + kw++; + } + + // if((vi0>>1) == 1476811 || (vi0>>1) == 1479120) { + // fprintf(stderr, "init_b[M::%s] L\t%.*s(%c)\t%.*s(%c)\tkw::%u\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, v>>1), Get_NAME(R_INF, v>>1), "+-"[v&1], + // (int)Get_NAME_LENGTH(R_INF, w>>1), Get_NAME(R_INF, w>>1), "+-"[w&1], kw); + // } + + if(!kw) { + // if((vi0>>1) == 1476811 || (vi0>>1) == 1479120) { + // fprintf(stderr, "[M::%s] L\t%.*s(%c)\t%.*s(%c)\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, v0>>1), Get_NAME(R_INF, v0>>1), "+-"[v0&1], + // (int)Get_NAME_LENGTH(R_INF, w>>1), Get_NAME(R_INF, w>>1), "+-"[w&1]); + // } + kv_push(uint32_t, *sa, (w^1)); ntip++; + } + } + + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (k = 0; k < nv; ++k) { + if(av[k].del) continue; + kv_push(u_int32_t, *sb, av-g->arc + k); + av[k].del = 1; kv++; w = av[k].v^1; f = 0; + + nw = asg_arc_n(ref, w); aw = asg_arc_a(ref, w); + for (i = kw = 0; i < nw; i++) { + if(aw[i].del) continue; + // if(((vi0>>1) == 1476811 || (vi0>>1) == 1479120) && ((v>>1) == 1477068) && ((w>>1) == 1477089)) { + // fprintf(stderr, "arc_2_a[M::%s] L\t%.*s(%c)\t%.*s(%c)\tkw::%u\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, aw[i].ul>>33), Get_NAME(R_INF, aw[i].ul>>33), "+-"[(aw[i].ul>>32)&1], + // (int)Get_NAME_LENGTH(R_INF, aw[i].v>>1), Get_NAME(R_INF, aw[i].v>>1), "+-"[aw[i].v&1], kw); + // } + kw++; + } + nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); + for (i = 0; i < nw; i++) { + if(aw[i].del) continue; + if(aw[i].v == (v^1)) { + kv_push(u_int32_t, *sb, aw-g->arc + i); + aw[i].del = 1; f = 1; + } else { + // if(((vi0>>1) == 1476811 || (vi0>>1) == 1479120) && ((v>>1) == 1477068) && ((w>>1) == 1477089)) { + // fprintf(stderr, "arc_2_b[M::%s] L\t%.*s(%c)\t%.*s(%c)\tkw::%u\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, aw[i].ul>>33), Get_NAME(R_INF, aw[i].ul>>33), "+-"[(aw[i].ul>>32)&1], + // (int)Get_NAME_LENGTH(R_INF, aw[i].v>>1), Get_NAME(R_INF, aw[i].v>>1), "+-"[aw[i].v&1], kw); + // } + kw++; + } + } + assert(f); + + // if((vi0>>1) == 1476811 || (vi0>>1) == 1479120) { + // fprintf(stderr, "init_c[M::%s] L\t%.*s(%c)\t%.*s(%c)\tkw::%u\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, v>>1), Get_NAME(R_INF, v>>1), "+-"[v&1], + // (int)Get_NAME_LENGTH(R_INF, w>>1), Get_NAME(R_INF, w>>1), "+-"[w&1], kw); + // } + + if(!kw) { + // if((vi0>>1) == 1476811 || (vi0>>1) == 1479120) { + // fprintf(stderr, "[M::%s] L\t%.*s(%c)\t%.*s(%c)\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, v0>>1), Get_NAME(R_INF, v0>>1), "+-"[v0&1], + // (int)Get_NAME_LENGTH(R_INF, w>>1), Get_NAME(R_INF, w>>1), "+-"[w&1]); + // } + kv_push(uint32_t, *sa, (w^1)); ntip++; + } + } + } + + for (i = 0; i < sb->n; i++) { + if(sb->a[i] < g->n_arc) { + assert(g->arc[sb->a[i]].del); + g->arc[sb->a[i]].del = 0; + } else { + assert(ref->arc[sb->a[i] - g->n_arc].del); + ref->arc[sb->a[i] - g->n_arc].del = 0; + } + } + + + if(ntip > 0 && ntip >= max_ext) return 0; + return 1; +} + +uint32_t refine_rd_hamming_symm(asg_t *g, asg_t *ref, uint32_t v0, uint32_t v1, buf_t *z, uint32_t max_ext) +{ + // if((v0>>1) == 1476811 || (v0>>1) == 1479120) { + // fprintf(stderr, "[M::%s]\n", __func__); + // } + + uint32_t i, ncut = 0; + uint32_t v, w, nv, k; asg_arc_t *av; + if (g->seq[v0>>1].del) return 0; // already deleted + asg32_v ai, bi, ci; + copy_asg_arr(ai, z->S); copy_asg_arr(bi, z->T); copy_asg_arr(ci, z->b); + ai.n = bi.n = ci.n = 0; + + + kv_push(uint32_t, ai, v0); + while(ai.n) { + v = kv_pop(ai); + if(z->a[v].s) continue; + z->a[v].s = 1; + kv_push(uint32_t, bi, v); // save it for revert + nv = asg_arc_n(ref, v); av = asg_arc_a(ref, v); + for (k = 0; k < nv; ++k) { // loop through v's neighbors + if (av[k].del) continue; + w = av[k].v; + if(z->a[w].s || w == v1) continue; + kv_push(uint32_t, ai, w); + } + } + ncut = 1; + while (ncut) { + for (i = ncut = 0; i < bi.n; ++i) { // clear the states of visited vertices + v = bi.a[i]; z->a[v].s = 0; + if(v == v0 || v == v1) continue; + if(!pp_cut(v0, v, g, ref, &ai, &ci, max_ext)) { + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (k = 0; k < nv; ++k) { // loop through v's neighbors + if (av[k].del) continue; + w = av[k].v; av[k].del = 1; + asg_arc_del(g, av[k].v^1, (av[k].ul>>32)^1, 1); ncut++; + // fprintf(stderr, "L\t%.*s(%c)\t%.*s(%c)\n", + // (int)Get_NAME_LENGTH(R_INF, (av[k].ul>>33)), Get_NAME(R_INF, (av[k].ul>>33)), "+-"[(av[k].ul>>32)&1], + // (int)Get_NAME_LENGTH(R_INF, (av[k].v>>1)), Get_NAME(R_INF, (av[k].v>>1)), "+-"[av[k].v&1]); + } + } + if(!pp_cut(v0, v^1, g, ref, &ai, &ci, max_ext)) { + nv = asg_arc_n(g, v^1); av = asg_arc_a(g, v^1); + for (k = 0; k < nv; ++k) { // loop through v's neighbors + if (av[k].del) continue; + w = av[k].v; av[k].del = 1; + asg_arc_del(g, av[k].v^1, (av[k].ul>>32)^1, 1); ncut++; + // fprintf(stderr, "L\t%.*s(%c)\t%.*s(%c)\n", + // (int)Get_NAME_LENGTH(R_INF, (av[k].ul>>33)), Get_NAME(R_INF, (av[k].ul>>33)), "+-"[(av[k].ul>>32)&1], + // (int)Get_NAME_LENGTH(R_INF, (av[k].v>>1)), Get_NAME(R_INF, (av[k].v>>1)), "+-"[av[k].v&1]); + } + } + } + } + + ai.n = bi.n = ci.n = 0; + copy_asg_arr(z->S, ai); copy_asg_arr(z->T, bi); copy_asg_arr(z->b, ci); + return ncut; +} + + +uint32_t rd_hamming_symm_simple0(buf_t *b, asg_t *ref, asg_t *g, uint32_t st, uint32_t ed, uint64_t max_dist, uint64_t *r_max_dist, uint32_t max_ext) // callback for kt_for() +{ + // if((st>>1) == 1476811 || (st>>1) == 1479120) { + // fprintf(stderr, "[M::%s]\tst>>1::%u(%c)\ted>>1::%u(%c)\n", __func__, st>>1, "+-"[st&1], ed>>1, "+-"[ed&1]); + // } + + double step = 0.2, cuttoff; + uint32_t p, k, ncut; + p = rd_hm_bub(g, ref, st, max_dist, b); + if(p) { + // if((st>>1) == 1476811 || (st>>1) == 1479120) { + // fprintf(stderr, "-a-[M::%s]\tst>>1::%u(%c)\ted>>1::%u(%c)\n", __func__, st>>1, "+-"[st&1], ed>>1, "+-"[ed&1]); + // } + assert(b->S.a[0] == (ed^1)); + if(r_max_dist) (*r_max_dist) = max_dist; + refine_rd_hamming_symm(g, ref, st, ed^1, b, max_ext); + return 1; + } + ///recalculate max_dist + p = rd_hm_bub(ref, NULL, st, max_dist, b); + // if(!p) { + // fprintf(stderr, "[M::%s] st>>1::%u(st&1::%u), ed>>1::%u(ed&1::%u), max_dist::%lu\n", + // __func__, st>>1, st&1, ed>>1, ed&1, max_dist); + // } + assert(p); assert(b->S.a[0] == (ed^1)); + for (k = max_dist = 0; k < b->b.n; ++k) { + if(b->b.a[k]==st || b->b.a[k]==b->S.a[0]) continue; + max_dist += ref->seq[b->b.a[k]>>1].len; + } + max_dist += ref->seq[st>>1].len; + max_dist += ref->seq[b->S.a[0]>>1].len; + p = rd_hm_bub(g, ref, st, max_dist, b); + if(p) { + // if((st>>1) == 1476811 || (st>>1) == 1479120) { + // fprintf(stderr, "-b-[M::%s]\tst>>1::%u(%c)\ted>>1::%u(%c)\n", __func__, st>>1, "+-"[st&1], ed>>1, "+-"[ed&1]); + // } + assert(b->S.a[0] == (ed^1)); + if(r_max_dist) (*r_max_dist) = max_dist; + refine_rd_hamming_symm(g, ref, st, ed^1, b, max_ext); + return 1; + } + + ///drop inexact edges first + cuttoff = -1; + ncut = rd_hm_drop(g, ref, st, ed^1, cuttoff, 1, b); + p = rd_hm_bub(g, ref, st, max_dist, b); + if(p) { + // if((st>>1) == 1476811 || (st>>1) == 1479120) { + // fprintf(stderr, "-c-[M::%s]\tst>>1::%u(%c)\ted>>1::%u(%c)\n", __func__, st>>1, "+-"[st&1], ed>>1, "+-"[ed&1]); + // } + assert(b->S.a[0] == (ed^1)); + if(r_max_dist) (*r_max_dist) = max_dist; + refine_rd_hamming_symm(g, ref, st, ed^1, b, max_ext); + return 1; + } + + for (cuttoff = step; cuttoff < 1.0; cuttoff += step) { + ncut = rd_hm_drop(g, ref, st, ed^1, cuttoff, 0, b); + p = rd_hm_bub(g, ref, st, max_dist, b); + if(p) { + // if((st>>1) == 1476811 || (st>>1) == 1479120) { + // fprintf(stderr, "-d-[M::%s]\tst>>1::%u(%c)\ted>>1::%u(%c)\n", __func__, st>>1, "+-"[st&1], ed>>1, "+-"[ed&1]); + // } + assert(b->S.a[0] == (ed^1)); + if(r_max_dist) (*r_max_dist) = max_dist; + refine_rd_hamming_symm(g, ref, st, ed^1, b, max_ext); + return 1; + } + if(!ncut) break; + } + + rd_hm_drop(g, ref, st, ed^1, 1024, 0, b); + p = rd_hm_bub(g, ref, st, max_dist, b); + assert(p); assert(b->S.a[0] == (ed^1)); + if(r_max_dist) (*r_max_dist) = max_dist; + return 0; +} + +uint32_t prt_arc_status(asg_t *g, uint32_t v0, uint32_t w0, const char *cmd) +{ + uint32_t v, w, i, nv; asg_arc_t *av; + + v = v0<<1; w = w0; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (i = 0; i < nv; ++i) { + if (((av[i].v>>1) == w) && (!av[i].del)) { + fprintf(stderr, "%s\tL\t%.*s(%c)\t%.*s(%c)\n", cmd, + (int)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], + (int)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1]); + } + } + + v = (v0<<1) + 1; w = w0; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (i = 0; i < nv; ++i) { + if (((av[i].v>>1) == w) && (!av[i].del)) { + fprintf(stderr, "%s\tL\t%.*s(%c)\t%.*s(%c)\n", cmd, + (int)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], + (int)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1]); + } + } + + v = w0<<1; w = v0; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (i = 0; i < nv; ++i) { + if (((av[i].v>>1) == w) && (!av[i].del)) { + fprintf(stderr, "%s\tL\t%.*s(%c)\t%.*s(%c)\n", cmd, + (int)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], + (int)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1]); + } + } + + v = (w0<<1) + 1; w = v0; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (i = 0; i < nv; ++i) { + if (((av[i].v>>1) == w) && (!av[i].del)) { + fprintf(stderr, "%s\tL\t%.*s(%c)\t%.*s(%c)\n", cmd, + (int)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], + (int)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1]); + } + } + + return 1; +} + +void reduce_hamming_error_adv(ma_ug_t *iug, asg_t *sg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +int max_hang, int min_ovlp, long long gap_fuzz, R_to_U *ru, bubble_type* bub, uint32_t max_ext) +{ + double index_time = yak_realtime(); + ma_ug_t *ug = NULL; ug = (iug)?(iug):(ma_ug_gen_primary(sg, PRIMARY_LABLE)); + uint8_t* vis_flag = NULL; CALLOC(vis_flag, sg->n_seq*2); + uint32_t fix_bub = 0; asg_t *g = ug->g; + uint32_t v, n_vtx = g->n_seq * 2, n_arc, n_arc_0 = sg->n_arc, nv, i; + uint64_t n_pop = 0, max_dist; asg_arc_t *p; + asg_arc_t *av; asg_t *ig = asg_init(); asg64_v sv; kv_init(sv); + buf_t b; memset(&b, 0, sizeof(buf_t)); + b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + uint8_t* bs_flag = NULL; CALLOC(bs_flag, n_vtx); + for (i = 0; i < ug->g->n_seq; i++) ug->g->seq[i].c = 0; + max_dist = get_bub_pop_max_dist_advance(g, &b); + + if(max_dist > 0) { + if(bub) { + for (i = 0; i < bub->f_bub; i++) { + get_bubbles(bub, i, &v, NULL, NULL, NULL, NULL); + fix_bub += gen_switch_phasing(sg, ug, v, sources, coverage_cut, max_hang, min_ovlp, + R_INF.trio_flag, vis_flag, &b, max_dist, 1, ig, &sv); + } + } else { + for (v = 0; v < n_vtx; ++v) { + if(bs_flag[v] != 0) continue; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del) continue; + ///some edges could be deleted + for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs + if (!av[i].del) ++n_arc; + if (n_arc < 2) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, max_dist, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (i = 0; i < b.b.n; i++) { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + bs_flag[b.b.a[i]] = bs_flag[b.b.a[i]^1] = 1; + } + bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 3; + } + } + + //traverse all node with two directions + for (v = 0; v < n_vtx; ++v) { + if(bs_flag[v] !=2) continue; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del) continue; + ///some edges could be deleted + for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs + if (!av[i].del) ++n_arc; + if (n_arc > 1) { + fix_bub += gen_switch_phasing(sg, ug, v, sources, coverage_cut, max_hang, min_ovlp, + R_INF.trio_flag, vis_flag, &b, max_dist, 1, ig, &sv); + } + } + } + } + free(bs_flag); if(!iug) ma_ug_destroy(ug); + + if(sv.n > 0) { + + + ig->n_seq = ig->m_seq = sg->n_seq; + MALLOC(ig->seq, ig->n_seq); + memcpy(ig->seq, sg->seq, (sizeof((*(ig->seq)))*ig->n_seq)); + asg_cleanup(ig); asg_arc_del_trans_aux(ig, sg, vis_flag, gap_fuzz); + REALLOC(b.a, (ig->n_seq<<1)); memset(b.a, 0, sizeof((*(b.a)))*(ig->n_seq<<1)); + + // prt_arc_status(ig, 1477050, 1477089, "init"); + + for (i = 0; i < sv.n; i++) { + rd_hamming_symm_simple0(&b, sg, ig, sv.a[i]>>32, (uint32_t)(sv.a[i]), max_dist, NULL, max_ext); + // fprintf(stderr, "[M::%s]\tst>>1::%lu(%c)\ted>>1::%u(%c)\n", __func__, (sv.a[i]>>32)>>1, "+-"[(sv.a[i]>>32)&1], ((uint32_t)(sv.a[i]))>>1, "+-"[(uint32_t)(sv.a[i])&1]); + // prt_arc_status(ig, 1477050, 1477089, "mm"); + } + + // prt_arc_status(ig, 1477050, 1477089, "end"); + /** + rd_hamming_t aux_t; memset((&aux_t), 0, sizeof(aux_t)); + aux_t.n_thread = 1; // aux_t.n_thread = asm_opt.thread_num; + CALLOC(aux_t.a, aux_t.n_thread); + for (i = 0; i < aux_t.n_thread; i++) aux_t.a[i].a = b.a; + aux_t.g = ig; aux_t.ref = sg; aux_t.rr = &sv; aux_t.max_dist = max_dist; + // print_debug_gfa(ug, sg, coverage_cut, "debug_hamming", sources, ru); + // kt_for(aux_t.n_thread, rd_hamming_symm, &aux_t, aux_t.rr->n); + for (i = 0; i < aux_t.rr->n; i++) { + rd_hamming_symm_simple(&aux_t, aux_t.rr->a[i]>>32, (uint32_t)(aux_t.rr->a[i])); + } + for (i = 0; i < aux_t.n_thread; i++) { + free(aux_t.a[i].S.a); free(aux_t.a[i].T.a); + free(aux_t.a[i].b.a); free(aux_t.a[i].e.a); + } + free(aux_t.a); + **/ + } + free(sv.a); free(vis_flag); + + // prt_arc_status(ig, 1477050, 1477089, "fin"); + + for (i = n_pop = 0; i < ig->n_arc; i++) { + if(ig->arc[i].del) continue; + p = asg_arc_pushp(sg); *p = (ig->arc[i]); n_pop++; + } + if(n_pop) { + free(sg->idx); + sg->idx = 0; + sg->is_srt = 0; + asg_cleanup(sg); + // prt_arc_status(sg, 1477050, 1477089, "ff0"); + asg_symm(sg); + // prt_arc_status(sg, 1477050, 1477089, "ff1"); + asg_arc_del_trans(sg, gap_fuzz); + // prt_arc_status(sg, 1477050, 1477089, "ff2"); + } + + // prt_arc_status(sg, 1477050, 1477089, "ffe"); + + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); asg_destroy(ig); + fprintf(stderr, "[M::%s::%.3f] # inserted edges: %u, # fixed bubbles: %u\n", + __func__, yak_realtime() - index_time, sg->n_arc - n_arc_0, fix_bub); +} + +void reduce_hamming_error(asg_t *sg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +int max_hang, int min_ovlp, long long gap_fuzz) +{ + double index_time = yak_realtime(); + ma_ug_t *ug = NULL; + ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); + + uint8_t* vis_flag = NULL; CALLOC(vis_flag, sg->n_seq*2); + uint32_t fix_bub = 0; + kvec_t_u32_warp stack; kv_init(stack.a); + kv_asg_arc_t e; kv_init(e); + asg_t *g = ug->g; + uint32_t v, n_vtx = g->n_seq * 2, n_arc, n_arc_0 = sg->n_arc, nv, i; + uint64_t n_pop = 0, max_dist; + asg_arc_t *av = NULL; + buf_t b; + memset(&b, 0, sizeof(buf_t)); + b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + uint8_t* bs_flag = NULL; CALLOC(bs_flag, n_vtx); + for (i = 0; i < ug->g->n_seq; i++) ug->g->seq[i].c = 0; + max_dist = get_bub_pop_max_dist_advance(g, &b); + + + if(max_dist > 0) + { + for (v = 0; v < n_vtx; ++v) + { + if(bs_flag[v] != 0) continue; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + ///some edges could be deleted + for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs + if (!av[i].del) ++n_arc; + if (n_arc < 2) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, max_dist, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) + { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (i = 0; i < b.b.n; i++) + { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + bs_flag[b.b.a[i]] = bs_flag[b.b.a[i]^1] = 1; + } + bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 3; + } + } + + //traverse all node with two directions + for (v = 0; v < n_vtx; ++v) { + if(bs_flag[v] !=2) continue; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + ///some edges could be deleted + for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs + if (!av[i].del) ++n_arc; + if (n_arc > 1) + { + fix_bub += bub_complex_hamming(sg, ug, v, sources, coverage_cut, &stack, + max_hang, min_ovlp, R_INF.trio_flag, vis_flag, &e, &b, max_dist); + } + } + } + + asg_arc_t* p = NULL; + for (i = 0; i < e.n; i++) + { + p = asg_arc_pushp(sg); + *p = e.a[i]; + } + if(e.n != 0) + { + free(sg->idx); + sg->idx = 0; + sg->is_srt = 0; + asg_cleanup(sg); + asg_symm(sg); + asg_arc_del_trans(sg, gap_fuzz); + } + + free(vis_flag); + kv_destroy(stack.a); + kv_destroy(e); + + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + if (n_pop) asg_cleanup(g); + free(bs_flag); + ma_ug_destroy(ug); + + fprintf(stderr, "[M::%s::%.3f] # inserted edges: %u, # fixed bubbles: %u\n", + __func__, yak_realtime() - index_time, sg->n_arc - n_arc_0, fix_bub); + +} + + +uint64_t asg_bub_pop1_label(asg_t *g, uint32_t v0, uint64_t max_dist, buf_s_t *b) +{ + uint32_t i, n_pending = 0, /**is_first = 1,**/ n_tips, tip_end; + uint64_t n_pop = 0; + if (g->seq[v0>>1].del) return 0; // already deleted + if(get_real_length(g, v0, NULL)<2) return 0; + + ///S saves nodes with all incoming edges visited + b->S.n = b->b.n = b->e.n = 0; + ///for each node, b->a saves all related information + b->a[v0].d = 0; + ///b->S is the nodes with all incoming edges visited + kv_push(uint32_t, b->S, v0); n_tips = 0; tip_end = (uint32_t)-1; + + do { + ///v is a node that all incoming edges have been visited + ///d is the distance from v0 to v + uint32_t v = kv_pop(b->S), d = b->a[v].d; + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + ///why we have this assert? + ///assert(nv > 0); + ///all out-edges of v + for (i = 0; i < nv; ++i) { // loop through v's neighbors + ///if this edge has been deleted + if (av[i].del) continue; + + uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l + binfo_s_t *t = &b->a[w]; + ///that means there is a circle, directly terminate the whole bubble poping + ///if (w == v0) goto pop_reset; + if ((w>>1) == (v0>>1)) goto pop_reset; + /****************************may have bugs********************************/ + ///important when poping at long untig graph + // if(is_first) l = 0; + /****************************may have bugs********************************/ + ///find a too far path? directly terminate the whole bubble poping + if ((uint64_t)d + (uint64_t)l > max_dist) break; // too far + + ///if this node + if (t->s == 0) { // this vertex has never been visited + kv_push(uint32_t, b->b, w); // save it for revert + ///t->p is the parent node of + ///t->s = 1 means w has been visited + ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) + t->p = v, t->s = 1, t->d = d + l; + ///incoming edges of w + ///t->r = count_out(g, w^1); + t->r = get_real_length(g, w^1, NULL); + ++n_pending; + } else { // visited before + ///it is the shortest edge + if (d + l < t->d) t->d = d + l, t->p = v; // update dist + } + ///assert(t->r > 0); + //if all incoming edges of w have visited + //push it to b->S + if (--(t->r) == 0) { + uint32_t x = get_real_length(g, w, NULL); + /****************************may have bugs for bubble********************************/ + if(x > 0) + { + kv_push(uint32_t, b->S, w); + } + else + { + ///at most one tip + if(n_tips != 0) goto pop_reset; + n_tips++; + tip_end = w; + } + /****************************may have bugs for bubble********************************/ + --n_pending; + } + } + // is_first = 0; + //if found a tip + /****************************may have bugs for bubble********************************/ + if(n_tips == 1) + { + if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) + { + kv_push(uint32_t, b->S, tip_end); + break; + } + else + { + goto pop_reset; + } + } + /****************************may have bugs for bubble********************************/ + ///if i < nv, that means (d + l > max_dist) + if (i < nv || b->S.n == 0) goto pop_reset; + } while (b->S.n > 1 || n_pending); + + n_pop = 1; +pop_reset: + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + binfo_s_t *t = &b->a[b->b.a[i]]; + t->s = t->d = 0; + } + return n_pop; +} + +void debug_asg_bub_pop1_primary_trio(asg_t *g, ma_ug_t *utg, uint32_t v0, uint64_t max_dist, buf_t *b, +uint32_t positive_flag, uint32_t negative_flag, uint32_t found) +{ + buf_t b_new; + memset(&b_new, 0, sizeof(buf_t)); + b_new.a = (binfo_t*)calloc(g->n_seq * 2, sizeof(binfo_t)); + uint32_t n_pop = asg_bub_pop1_primary_trio(g, utg, v0, max_dist, &b_new, positive_flag, negative_flag, 0, NULL, NULL, NULL, 0, 0, NULL); + if(n_pop != found) fprintf(stderr, "ERROR\n"); + + free(b_new.a); free(b_new.S.a); free(b_new.T.a); free(b_new.b.a); free(b_new.e.a); +} + +uint64_t asg_bub_pop1_primary_trio(asg_t *g, ma_ug_t *utg, uint32_t v0, uint64_t max_dist, buf_t *b, +uint32_t positive_flag, uint32_t negative_flag, uint32_t is_pop, uint64_t* path_base_len, uint64_t* path_nodes, +hap_cov_t *cov, uint32_t is_update_chain, uint32_t keep_d, utg_trans_t *o) +{ + uint32_t i, n_pending = 0, is_first = 1, cur_m, cur_c, cur_np, cur_nc, to_replace, n_tips, tip_end; + uint64_t n_pop = 0; + long long cur_weight = -1, max_weight = -1; + ///if this node has been deleted + if (g->seq[v0>>1].del || g->seq[v0>>1].c == ALTER_LABLE) return 0; // already deleted + ///if ((uint32_t)g->idx[v0] < 2) return 0; // no bubbles + if(get_real_length(g, v0, NULL)<2) return 0; + ///S saves nodes with all incoming edges visited + b->S.n = b->T.n = b->b.n = b->e.n = 0; + ///for each node, b->a saves all related information + b->a[v0].c = b->a[v0].d = b->a[v0].m = b->a[v0].nc = b->a[v0].np = 0; + ///b->S is the nodes with all incoming edges visited + kv_push(uint32_t, b->S, v0); + n_tips = 0; + tip_end = (uint32_t)-1; + uint32_t non_positive_flag = (uint32_t)-1; + if(positive_flag == FATHER) non_positive_flag = MOTHER; + if(positive_flag == MOTHER) non_positive_flag = FATHER; + + do { + ///v is a node that all incoming edges have been visited + ///d is the distance from v0 to v + uint32_t v = kv_pop(b->S), d = b->a[v].d, c = b->a[v].c, m = b->a[v].m, nc = b->a[v].nc, np = b->a[v].np; + uint32_t nv = asg_arc_n(g, v); asg_arc_t *av = asg_arc_a(g, v); + ///why we have this assert? + ///assert(nv > 0); + ///all out-edges of v + for (i = 0; i < nv; ++i) { // loop through v's neighbors + /** + p->ul: |____________31__________|__________1___________|______________32_____________| + qn direction of overlap length of this node (not overlap length) + (in the view of query) + p->v : |___________31___________|__________1___________| + tn reverse direction of overlap + (in the view of target) + p->ol: overlap length + **/ + ///if this edge has been deleted + if (av[i].del) continue; + + uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l + binfo_t *t = &b->a[w]; + ///that means there is a circle, directly terminate the whole bubble poping + ///if (w == v0) goto pop_reset; + if ((w>>1) == (v0>>1)) { + goto pop_reset; + } + /****************************may have bugs********************************/ + ///important when poping at long untig graph + if(is_first && keep_d) l = 0; + /****************************may have bugs********************************/ + + + + ///push the edge + ///high 32-bit of g->idx[v] is the start point of v's edges + //so here is the point of this specfic edge + kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); + ///find a too far path? directly terminate the whole bubble poping + if (d + l > max_dist) break; // too far + + ///if this node + if (t->s == 0) { // this vertex has never been visited + kv_push(uint32_t, b->b, w); // save it for revert + ///t->p is the parent node of + ///t->s = 1 means w has been visited + ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) + t->p = v, t->s = 1, t->d = d + l; + /****************************may have bugs********************************/ + cur_c = cur_m = cur_np = 0; cur_nc = 1; + if(utg) + { + cur_c = get_num_trio_flag(utg, w>>1, positive_flag); + cur_m = get_num_trio_flag(utg, w>>1, negative_flag); + cur_np = 0; + if(non_positive_flag != (uint32_t)-1) + { + cur_np = get_num_trio_flag(utg, w>>1, non_positive_flag); + } + cur_nc = utg->u.a[(w>>1)].n; + } + + + t->c = c + cur_c; + t->m = m + cur_m; + t->nc = nc + cur_nc; + t->np = np + cur_np; + /****************************may have bugs********************************/ + ///incoming edges of w + ///t->r = count_out(g, w^1); + t->r = get_real_length(g, w^1, NULL); + ++n_pending; + } else { // visited before + /****************************may have bugs********************************/ + cur_c = cur_m = cur_np = 0; cur_nc = 1; + if(utg) + { + cur_c = get_num_trio_flag(utg, w>>1, positive_flag); + cur_m = get_num_trio_flag(utg, w>>1, negative_flag); + cur_np = 0; + if(non_positive_flag != (uint32_t)-1) + { + cur_np = get_num_trio_flag(utg, w>>1, non_positive_flag); + } + cur_nc = utg->u.a[(w>>1)].n; + } + ///BUG: select the path with less negative_flag, less non_positive_flag, more positive_flag, more distance + ///FIXED: select the path with less (negative_flag+non_positive_flag), more positive_flag, more distance + to_replace = 0; + + /****************************may have bugs********************************/ + cur_weight = (long long)(c + cur_c) - ((long long)(m + cur_m) + (long long)(np + cur_np)); + max_weight = (long long)t->c - ((long long)t->m + (long long)t->np); + if(cur_weight > max_weight) + { + to_replace = 1; + } + else if(cur_weight == max_weight) + { + if(nc + cur_nc > t->nc) + { + to_replace = 1; + } + else if(nc + cur_nc == t->nc) + { + if(d + l > t->d) + { + to_replace = 1; + } + } + } + /****************************may have bugs********************************/ + if(to_replace) + { + t->p = v; + t->m = m + cur_m; + t->c = c + cur_c; + t->nc = nc + cur_nc; + t->np = np + cur_np; + } + ///c is the weight (is very likely the number of node in this edge) of the parent node + ///select the longest edge (longest meams most reads/longest edge) + // if (c + 1 > t->c || (c + 1 == t->c && d + l > t->d)) t->p = v; + // if (c + 1 > t->c) t->c = c + 1; + /****************************may have bugs********************************/ + ///update len(v0->w) + ///node: t->d is not the length from this node's parent + ///it is the shortest edge + if (d + l < t->d) t->d = d + l; // update dist + } + ///assert(t->r > 0); + //if all incoming edges of w have visited + //push it to b->S + if (--(t->r) == 0) { + uint32_t x = get_real_length(g, w, NULL); + /****************************may have bugs for bubble********************************/ + if(x > 0) + { + kv_push(uint32_t, b->S, w); + } + else + { + ///at most one tip + if(n_tips != 0) { + goto pop_reset; + } + n_tips++; + tip_end = w; + } + /****************************may have bugs for bubble********************************/ + --n_pending; + } + } + is_first = 0; + //if found a tip + /****************************may have bugs for bubble********************************/ + if(n_tips == 1) + { + if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) + { + kv_push(uint32_t, b->S, tip_end); + break; + } + else + { + goto pop_reset; + } + } + /****************************may have bugs for bubble********************************/ + ///if i < nv, that means (d + l > max_dist) + if (i < nv || b->S.n == 0) { + goto pop_reset; + } + } while (b->S.n > 1 || n_pending); + + + /****************************may have bugs********************************/ + ///if(keep_d != 0) debug_asg_bub_pop1_primary_trio(g, utg, v0, max_dist, b, positive_flag, negative_flag, 1); + /****************************may have bugs********************************/ + if(cov && utg) asg_bub_backtrack_primary_cov(utg, v0, b, cov, is_update_chain); + if(o && utg) asg_bub_collect_ovlp(utg, v0, b, o); + if(is_pop) asg_bub_backtrack_primary(g, v0, b); + if(path_base_len || path_nodes) asg_bub_backtrack_primary_length(g, utg, v0, b, path_base_len, path_nodes); + + n_pop = 1; +pop_reset: + + /****************************may have bugs********************************/ + ///if(!n_pop && keep_d != 0) debug_asg_bub_pop1_primary_trio(g, utg, v0, max_dist, b, positive_flag, negative_flag, 0); + /****************************may have bugs********************************/ + + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + binfo_t *t = &b->a[b->b.a[i]]; + t->s = t->c = t->d = t->m = t->nc = t->np = 0; + } + return n_pop; +} + +uint64_t dfs_subgraph(asg_t *g, buf_t *b, uint32_t id, uint32_t *p_bub) +{ + uint64_t len = 0; + uint32_t cur, nv, v, w, i, kv_0, kv_1, flag_0 = 0, flag_1 = 0; + asg_arc_t *av = NULL; + (*p_bub) = 0; + if(b->a[id].s) return 0; + b->S.n = 0; + kv_push(uint32_t, b->S, id); + + while (b->S.n > 0) + { + b->S.n--; + cur = b->S.a[b->S.n]; + if(b->a[cur].s) continue; + b->a[cur].s = 1; + len += g->seq[cur].len; + + v = cur<<1; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + for (i = kv_0 = 0; i < nv; i++) + { + w = av[i].v>>1; + if(av[i].del) continue; + kv_0++; + if(b->a[w].s) continue; + kv_push(uint32_t, b->S, w); + } + + v = (cur<<1)+1; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + for (i = kv_1 = 0; i < nv; i++) + { + w = av[i].v>>1; + if(av[i].del) continue; + kv_1++; + if(b->a[w].s) continue; + kv_push(uint32_t, b->S, w); + } + + if(kv_0 > 0 && kv_1 > 0) flag_0++; + if(kv_0 > 1) flag_1++; + if(kv_1 > 1) flag_1++; + } + + if(flag_0 > 0 && flag_1 > 1) (*p_bub) = 1; + return len; +} +uint64_t get_bub_pop_max_dist(asg_t *g, buf_t *b) +{ + uint32_t n_vtx = g->n_seq, i, p_bub; + uint64_t cLen = 0, mLen = 0, tLen = 0; + + + for (i = 0; i < n_vtx; ++i) + { + if(b->a[i].s) continue; + cLen = dfs_subgraph(g, b, i, &p_bub); + tLen += cLen; + if(p_bub == 0) continue;///no bubble + if(cLen > mLen) mLen = cLen; + } + + for (i = 0; i < n_vtx; ++i) + { + ///if(b->a[i].s == 0) fprintf(stderr, "ERROR\n"); + b->a[i].s = 0; + ///debug_tLen += g->seq[i].len; + } + ///if(debug_tLen != tLen) fprintf(stderr, "ERROR\n"); + + ///fprintf(stderr, "mLen: %lu, tLen: %lu\n", mLen, tLen); + b->S.n = 0; + return mLen; +} + +uint64_t dfs_subgraph_advance(asg_t *g, buf_t *b, uint32_t x, uint32_t *p_bub) +{ + uint64_t len = 0; + uint32_t c_v, e_v, nv, convex, v, i, kv_0, kv_1, flag_0 = 0, flag_1 = 0, op; + asg_arc_t *av = NULL; + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen, uLen; + (*p_bub) = 0; + if(b->a[x>>1].s || g->seq[x>>1].del) return 0; + b->S.n = 0; + kv_push(uint32_t, b->S, x); + + while (b->S.n > 0) + { + b->S.n--; + c_v = b->S.a[b->S.n]; + if(b->a[c_v>>1].s) continue; + + b->b.n = 0; + op = get_unitig(g, NULL, c_v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, + &max_stop_baseLen, 1, b); + uLen = baseLen; + for(i = 0; i < b->b.n; i++) + { + ///if(b->a[b->b.a[i]>>1].s == 1) fprintf(stderr, "ERROR 3\n"); + b->a[b->b.a[i]>>1].s = 1; + } + + if(op == LOOP) return 0; + + + e_v = convex^1; + b->b.n = 0; + op = get_unitig(g, NULL, e_v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, + &max_stop_baseLen, 1, b); + uLen = MAX(uLen, baseLen); + + len += uLen; + + + v = c_v^1; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + for (i = kv_0 = 0; i < nv; i++) + { + if(av[i].del) continue; + kv_0++; + if(b->a[av[i].v>>1].s) continue; + kv_push(uint32_t, b->S, av[i].v); + } + + v = e_v^1; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + for (i = kv_1 = 0; i < nv; i++) + { + if(av[i].del) continue; + kv_1++; + if(b->a[av[i].v>>1].s) continue; + kv_push(uint32_t, b->S, av[i].v); + } + + if(kv_0 > 0 && kv_1 > 0) flag_0++; + if(kv_0 > 1) flag_1++; + if(kv_1 > 1) flag_1++; + } + + if(flag_0 > 0 && flag_1 > 1) (*p_bub) = 1; + return len; +} + +uint64_t get_bub_pop_max_dist_advance(asg_t *g, buf_t *b) +{ + asg_arc_t *av = NULL; + uint32_t n_vtx = g->n_seq<<1, k, v, w, kv, nv, p_bub; + uint64_t cLen = 0, mLen = 0; + + + for (v = 0; v < n_vtx; ++v) + { + if(b->a[v>>1].s) continue; + if(g->seq[v>>1].del) continue; + + + av = asg_arc_a(g, v); + nv = asg_arc_n(g, v); + for (k = kv = 0; k < nv; k++) + { + if(av[k].del) continue; + w = av[k].v^1; + kv++; + } + if(kv == 1 && get_real_length(g, w, NULL) == 1) continue; + + cLen = dfs_subgraph_advance(g, b, v^1, &p_bub); + if(p_bub == 0) continue;///no bubble + if(cLen > mLen) mLen = cLen; + } + + for (k = 0; k < g->n_seq; ++k) + { + // if(b->a[k].s == 0 && !g->seq[k].del) + // { + // uint32_t convex; + // long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + // if(get_unitig(g, NULL, k<<1, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, + // &max_stop_baseLen, 1, NULL) != LOOP) + // { + // fprintf(stderr, "ERROR 1\n"); + // } + // } + b->a[k].s = 0; + } + + // for (; k < n_vtx; ++k) + // { + // if(b->a[k].s == 1) fprintf(stderr, "ERROR 2\n"); + // } + + ///fprintf(stderr, "mLen: %lu, tLen: %lu\n", mLen, tLen); + b->S.n = b->b.n = 0; + return mLen; +} + +inline uint32_t get_unitig_s(asg_t *sg, ma_ug_t *ug, uint32_t begNode, uint32_t* endNode, +long long* nodeLen, long long* baseLen, long long* max_stop_nodeLen, long long* max_stop_baseLen, +uint32_t stops_threshold, buf_s_t* b) +{ + ma_utg_v* u = NULL; + uint32_t v = begNode, w, k; + uint32_t kv, return_flag, n_stops = 0; + long long pre_baseLen = 0, pre_nodeLen = 0; + long long cur_baseLen = 0, cur_nodeLen = 0; + (*max_stop_nodeLen) = (*max_stop_baseLen) = (*nodeLen) = (*baseLen) = 0; + (*endNode) = (uint32_t)-1; + if(ug!=NULL) u = &(ug->u); + + while (1) + { + kv = get_real_length(sg, v, NULL); + (*endNode) = v; + if(u == NULL) + { + (*nodeLen)++; + } + else + { + (*nodeLen) += EvaluateLen((*u), v>>1); + } + if(b) kv_push(uint32_t, b->b, v); + ///means reach the end of a unitig + if(kv!=1) (*baseLen) += sg->seq[v>>1].len; + if(kv==0) + { + return_flag = END_TIPS; + break; + ///return END_TIPS; + } + if(kv>1) + { + return_flag = MUL_OUTPUT; + break; + ///return MUL_OUTPUT; + } + ///kv must be 1 here + kv = get_real_length(sg, v, &w); + ///means reach the end of a unitig + if(get_real_length(sg, w^1, NULL)!=1) + { + + n_stops++; + if(n_stops >= stops_threshold) + { + (*baseLen) += sg->seq[v>>1].len; + return_flag = MUL_INPUT; + break; + ///return MUL_INPUT; + } + else + { + for (k = 0; k < asg_arc_n(sg, v); k++) + { + if(asg_arc_a(sg, v)[k].del) continue; + ///here is just one undeleted edge + (*baseLen) += asg_arc_len(asg_arc_a(sg, v)[k]); + break; + } + } + + cur_baseLen = (*baseLen) - pre_baseLen; + pre_baseLen = (*baseLen); + if(cur_baseLen > (*max_stop_baseLen)) + { + (*max_stop_baseLen) = cur_baseLen; + } + + + cur_nodeLen = (*nodeLen) - pre_nodeLen; + pre_nodeLen = (*nodeLen); + if(cur_nodeLen > (*max_stop_nodeLen)) + { + (*max_stop_nodeLen) = cur_nodeLen; + } + } + else + { + for (k = 0; k < asg_arc_n(sg, v); k++) + { + if(asg_arc_a(sg, v)[k].del) continue; + ///here is just one undeleted edge + (*baseLen) += asg_arc_len(asg_arc_a(sg, v)[k]); + break; + } + } + + + v = w; + if(v == begNode) + { + return_flag = LOOP; + break; + ///return LOOP; + } + } + + + + + cur_baseLen = (*baseLen) - pre_baseLen; + pre_baseLen = (*baseLen); + if(cur_baseLen > (*max_stop_baseLen)) + { + (*max_stop_baseLen) = cur_baseLen; + } + + + cur_nodeLen = (*nodeLen) - pre_nodeLen; + pre_nodeLen = (*nodeLen); + if(cur_nodeLen > (*max_stop_nodeLen)) + { + (*max_stop_nodeLen) = cur_nodeLen; + } + + return return_flag; +} + +uint64_t dfs_subgraph_s_advance(asg_t *g, buf_s_t *b, uint32_t x, uint32_t *p_bub) +{ + uint64_t len = 0; + uint32_t c_v, e_v, nv, convex, v, i, kv_0, kv_1, flag_0 = 0, flag_1 = 0, op; + asg_arc_t *av = NULL; + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen, uLen; + (*p_bub) = 0; + if(b->a[x>>1].s || g->seq[x>>1].del) return 0; + b->S.n = 0; + kv_push(uint32_t, b->S, x); + + while (b->S.n > 0) + { + b->S.n--; + c_v = b->S.a[b->S.n]; + if(b->a[c_v>>1].s) continue; + + b->b.n = 0; + op = get_unitig_s(g, NULL, c_v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, + &max_stop_baseLen, 1, b); + + uLen = baseLen; + for(i = 0; i < b->b.n; i++) + { + ///if(b->a[b->b.a[i]>>1].s == 1) fprintf(stderr, "ERROR 3\n"); + b->a[b->b.a[i]>>1].s = 1; + } + + if(op == LOOP) return 0; + + + e_v = convex^1; + b->b.n = 0; + op = get_unitig_s(g, NULL, e_v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, + &max_stop_baseLen, 1, b); + uLen = MAX(uLen, baseLen); + + len += uLen; + + + v = c_v^1; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + for (i = kv_0 = 0; i < nv; i++) + { + if(av[i].del) continue; + kv_0++; + if(b->a[av[i].v>>1].s) continue; + kv_push(uint32_t, b->S, av[i].v); + } + + v = e_v^1; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + for (i = kv_1 = 0; i < nv; i++) + { + if(av[i].del) continue; + kv_1++; + if(b->a[av[i].v>>1].s) continue; + kv_push(uint32_t, b->S, av[i].v); + } + + if(kv_0 > 0 && kv_1 > 0) flag_0++; + if(kv_0 > 1) flag_1++; + if(kv_1 > 1) flag_1++; + } + + if(flag_0 > 0 && flag_1 > 1) (*p_bub) = 1; + return len; +} + +uint64_t get_s_bub_pop_max_dist_advance(asg_t *g, buf_s_t *b) +{ + asg_arc_t *av = NULL; + uint32_t n_vtx = g->n_seq<<1, k, v, w, kv, nv, p_bub; + uint64_t cLen = 0, mLen = 0; + + + for (v = 0; v < n_vtx; ++v) + { + if(b->a[v>>1].s) continue; + if(g->seq[v>>1].del) continue; + + + av = asg_arc_a(g, v); + nv = asg_arc_n(g, v); + for (k = kv = 0; k < nv; k++) + { + if(av[k].del) continue; + w = av[k].v^1; + kv++; + } + if(kv == 1 && get_real_length(g, w, NULL) == 1) continue; + cLen = dfs_subgraph_s_advance(g, b, v^1, &p_bub); + if(p_bub == 0) continue;///no bubble + if(cLen > mLen) mLen = cLen; + } + + for (k = 0; k < g->n_seq; ++k) + { + // if(b->a[k].s == 0 && !g->seq[k].del) + // { + // uint32_t convex; + // long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + // if(get_unitig(g, NULL, k<<1, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, + // &max_stop_baseLen, 1, NULL) != LOOP) + // { + // fprintf(stderr, "ERROR 1\n"); + // } + // } + b->a[k].s = 0; + } + + // for (; k < n_vtx; ++k) + // { + // if(b->a[k].s == 1) fprintf(stderr, "ERROR 2\n"); + // } + + ///fprintf(stderr, "mLen: %lu, tLen: %lu\n", mLen, tLen); + b->S.n = b->b.n = 0; + return mLen; +} + +void append_node_arcs(asg_t *des, asg_t *src, uint8_t *s, uint8_t se, uint32_t v) +{ + asg_arc_t *av, *za; uint32_t an, zn, k, n0, n1; + n0 = n1 = 0; + za = asg_arc_a(src, v); zn = asg_arc_n(src, v); + av = asg_arc_a(des, v); an = asg_arc_n(des, v); + ///set + for (k = 0; k < zn; k++) { + if(za[k].del) continue; + s[za[k].v] |= se; n0++; + } + + for (k = 0; k < an; k++) { + ///s[av[k].v]&se:: in the existing graph + if(s[av[k].v]&se) { + av[k].del = 0; n1++; + asg_arc_del(des, av[k].v^1, (av[k].ul>>32)^1, 0); + } + } + + ///reset + for (k = 0; k < zn; k++) { + if(za[k].del) continue; + if(s[za[k].v]&se) s[za[k].v] -= se; + } + if(!(n0 == n1)) { + fprintf(stderr, "[M::%s] n0::%u, n1::%u\n", __func__, n0, n1); + } + assert(n0 == n1); +} + + +static inline void asg_arc_rest(asg_t *des, asg_t *src, uint32_t v0, uint32_t w0, ma_ug_t *ug, kvec_asg_arc_t_warp *ae, ma_hit_t_alloc* src_e, ma_sub_t *cov, int32_t max_hang, int32_t min_ovlp, int32_t gap_fuzz, uint32_t *n_insert) +{ + uint32_t v, w, i, nv, rv, rw; asg_arc_t *av, *arc, t; + + v = v0; w = w0; + av = asg_arc_a(des, v); nv = asg_arc_n(des, v); + for (i = 0; i < nv; ++i) { + if (av[i].v == w) { + av[i].del = 0; break; + } + } + if(i < nv) { + v = w0^1; w = v0^1; + av = asg_arc_a(des, v); nv = asg_arc_n(des, v); + for (i = 0; i < nv; ++i) { + if (av[i].v == w) { + av[i].del = 0; break; + } + } + assert(i < nv); + return; + } + + ///replace a deleted arc + // fprintf(stderr, "[M::%s] replace\n", __func__); + v = v0; w = w0; + av = asg_arc_a(src, v); nv = asg_arc_n(src, v); + for (i = 0, arc = NULL; i < nv; ++i) { + if (av[i].v == w) { + av[i].del = 0; arc = &(av[i]); break; + } + } + assert(arc); + av = asg_arc_a(des, v); nv = asg_arc_n(des, v); + assert(nv); + for (i = 0; i < nv; ++i) assert(av[i].del); + for (i = 0; i < nv && av[i].ul < arc->ul; ++i); + if(i >= nv) {i = nv - 1;} av[i] = *arc; + + v = w0^1; w = v0^1; + av = asg_arc_a(src, v); nv = asg_arc_n(src, v); + for (i = 0, arc = NULL; i < nv; ++i) { + if (av[i].v == w) { + av[i].del = 0; arc = &(av[i]); break; + } + } + assert(arc); + av = asg_arc_a(des, v); nv = asg_arc_n(des, v); + assert(nv); + for (i = 0; i < nv; ++i) assert(av[i].del); + for (i = 0; i < nv && av[i].ul < arc->ul; ++i); + if(i >= nv) {i = nv - 1;} av[i] = *arc; + + + rv = ((v0&1)?(Uc_beg(ug->u.a[v0>>1])^1):(Uc_end(ug->u.a[v0>>1])^1)); + rw = ((w0&1)?(Uc_end(ug->u.a[w0>>1])):(Uc_beg(ug->u.a[w0>>1]))); + assert(get_edge_from_source(src_e, cov, NULL, max_hang, min_ovlp, rv, rw, &t)); + kv_push(asg_arc_t, ae->a, t); + + assert(get_edge_from_source(src_e, cov, NULL, max_hang, min_ovlp, rw^1, rv^1, &t)); + kv_push(asg_arc_t, ae->a, t); + + (*n_insert) += 2; +} + +uint32_t bub_pop_merge(ma_ug_t *raw_ug, ma_ug_t *new_ug, uint32_t v0, uint32_t v1, uint64_t max_dist, buf_t *b, +uint32_t positive_flag, uint32_t negative_flag, hap_cov_t *cov, uint32_t is_update_chain, utg_trans_t *o, kvec_asg_arc_t_warp *ae, +ma_hit_t_alloc* src, ma_sub_t *sub, int32_t max_hang, int32_t min_ovlp, int32_t gap_fuzz, uint32_t *n_insert) +{ + ///do not pop bubble within new_ug; + uint32_t is_pop = asg_bub_pop1_primary_trio(new_ug->g, new_ug, v0, max_dist, b, positive_flag, negative_flag, 0, NULL, NULL, cov, is_update_chain, 1/**0**/, o); + assert(is_pop); assert(b->S.a[0] == v1); + + ///b->S.a[0] is the sink of this bubble + uint32_t i, v, qn, tn, tmp_c, u; asg_arc_t *a; + asg_t *g = raw_ug->g; tmp_c = g->seq[b->S.a[0]>>1].c; + + ///assert(b->S.n == 1); + ///first remove all nodes in this bubble + for (i = 0; i < b->b.n; ++i) g->seq[b->b.a[i]>>1].c = ALTER_LABLE; + + + ///v is the sink of this bubble + v = b->S.a[0]; + ///recover node + do { + u = b->a[v].p; // u->v + /****************************may have hap bugs********************************/ + ////g->seq[v>>1].c = PRIMARY_LABLE; + g->seq[v>>1].c = HAP_LABLE; + /****************************may have hap bugs********************************/ + v = u; + } while (v != v0); + ///especially for unitig graph, don't label beg and sink node of a bubble as HAP_LABLE + ///since in unitig graph, a node may consist of a lot of reads + g->seq[b->S.a[0]>>1].c = tmp_c; + + ///remove all edges (self/reverse for each edge) in this bubble + for (i = 0; i < b->e.n; ++i) { + a = &(new_ug->g->arc[b->e.a[i]]);///note:: new_ug->g here + qn = a->ul>>33; + tn = a->v>>1; + if(g->seq[qn].c == ALTER_LABLE && g->seq[tn].c == ALTER_LABLE) continue; + ///remove this edge self + asg_arc_del(g, a->ul>>32, a->v, 1); + ///remove the reverse direction + asg_arc_del(g, a->v^1, a->ul>>32^1, 1); + } + + ///v is the sink of this bubble + v = b->S.a[0]; + ///recover node + do { + u = b->a[v].p; // u->v + g->seq[v>>1].del = 0; + asg_arc_rest(g, new_ug->g, u, v, raw_ug, ae, src, sub, max_hang, min_ovlp, gap_fuzz, n_insert); + v = u; + } while (v != v0); + return is_pop; +} + +uint64_t renew_phase_bubble(rd_hamming_fly_simp_t *pf, uint64_t v0, buf_t *b, ma_ug_t *ug, uint64_t max_dist, +uint32_t positive_flag, uint32_t negative_flag, hap_cov_t *cov, utg_trans_t *o, uint32_t is_update_chain) +{ + uint64_t v, k, i, v1 = b->S.a[0], is_update, is_pop = 0; ma_ug_t *fg = pf->fg; + uint8_t *s = pf->vs; asg32_v *bc = pf->srt; uint8_t sn = 1, se = 2; uint64_t max_dist0 = max_dist; + bc->n = 0; kv_resize(uint32_t, (*bc), b->b.n); + assert((fg->u.a[v0>>1].len == ug->u.a[v0>>1].len) && (fg->u.a[v0>>1].n == ug->u.a[v0>>1].n)); + assert((fg->u.a[v1>>1].len == ug->u.a[v1>>1].len) && (fg->u.a[v1>>1].n == ug->u.a[v1>>1].n)); + + + // if(((v0>>1) == 7536) && ((v1>>1) == 99223)) { + // print_simple_dbg_gfa(ug->g, "ug0"); + // } + + ///b->S.a[0] is the sink of this bubble + for (i = 0; i < b->b.n; i++) { + v = b->b.a[i]; + if((v == v0) || (v == v1)) continue; + s[v] = sn; + kv_push(uint32_t, *bc, v); + assert((fg->u.a[v>>1].len == ug->u.a[v>>1].len) && (fg->u.a[v>>1].n == ug->u.a[v>>1].n)); + } + + asg_arc_t *av, *za, *ra; uint32_t an, zn, rn, ri; + v = v0; + av = asg_arc_a(fg->g, v); + an = asg_arc_n(fg->g, v); + for (k = 0; k < an; k++) { + av[k].del = 1; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 1); + } + fg->g->seq[v>>1].c = ug->g->seq[v>>1].c; + + + v = v1^1; + av = asg_arc_a(fg->g, v); + an = asg_arc_n(fg->g, v); + for (k = 0; k < an; k++) { + av[k].del = 1; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 1); + } + fg->g->seq[v>>1].c = ug->g->seq[v>>1].c; + + + for (i = 0; i < bc->n; i++) { + v = bc->a[i]; + av = asg_arc_a(fg->g, v); an = asg_arc_n(fg->g, v); + for (k = 0; k < an; k++) { + // av[k].del = 1; + av[k].del = 1; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 1); + } + + v ^= 1; + av = asg_arc_a(fg->g, v); an = asg_arc_n(fg->g, v); + for (k = 0; k < an; k++) { + // av[k].del = 1; + av[k].del = 1; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 1); + } + + fg->g->seq[v>>1].c = ug->g->seq[v>>1].c; + } + + + for (i = 0; i < bc->n; i++) { + v = bc->a[i]; + za = asg_arc_a(ug->g, v); zn = asg_arc_n(ug->g, v); + av = asg_arc_a(fg->g, v); an = asg_arc_n(fg->g, v); + + ///set + for (k = 0; k < zn; k++) { + if((za[k].del) || (!s[za[k].v])) continue; + s[za[k].v] |= se; + } + + + for (k = 0; k < an; k++) { + ///s[av[k].v]&se:: in the existing graph + if((!s[av[k].v]) || (s[av[k].v]&se)) continue; ///in the existing graph + // if((av[k].v) == (v>>1)) continue;///looks like a bug + if((av[k].v>>1) == (v>>1)) continue; + av[k].del = 0; + + ra = asg_arc_a(fg->g, (av[k].v^1)); rn = asg_arc_n(fg->g, (av[k].v^1)); + for (ri = 0; ri < rn; ri++) { + if(ra[ri].v == ((av[k].ul>>32)^1)) { + ra[ri].del = 0; break; + } + } + assert(ri < rn); + } + + ///reset + for (k = 0; k < zn; k++) { + if((za[k].del) || (!s[za[k].v])) continue; + if(s[za[k].v]&se) s[za[k].v] -= se; + } + } + + + is_update = rd_hamming_symm_simple0(b, ug->g, fg->g, v0, v1^1, max_dist, &max_dist, (asm_opt.max_short_tip*2)); + + // if(((v0>>1) == 7536) && ((v1>>1) == 99223)) { + // fprintf(stderr, "v0::utg%.6lul(%c)\tv1::utg%.6lul(%c)\n", (v0>>1) + 1, "+-"[(v0&1)], (v1>>1) + 1, "+-"[(v1&1)]); + // for (i = 0; i < bc->n; i++) fprintf(stderr, "w::utg%.6ul(%c)\n", (bc->a[i]>>1) + 1, "+-"[(bc->a[i]&1)]); + // print_simple_dbg_gfa(ug->g, "ug1"); + // print_simple_dbg_gfa(fg->g, "fg0"); + // } + + // fprintf(stderr, "[M::%s] is_update::%lu\n", __func__, is_update); + if(is_update) { + for (i = 0; i < bc->n; i++) { + append_node_arcs(fg->g, ug->g, s, se, bc->a[i]); + append_node_arcs(fg->g, ug->g, s, se, bc->a[i]^1); + } + append_node_arcs(fg->g, ug->g, s, se, v0); + append_node_arcs(fg->g, ug->g, s, se, v1^1); + is_pop = bub_pop_merge(ug, fg, v0, v1, max_dist, b, positive_flag, negative_flag, cov, is_update_chain, o, pf->ae, pf->src, pf->cov, pf->max_hang, pf->min_ovlp, pf->gap_fuzz, &(pf->n_insert)); + } else { + max_dist = max_dist0; + is_pop = asg_bub_pop1_primary_trio(ug->g, ug, v0, max_dist, b, positive_flag, negative_flag, 1, NULL, NULL, cov, is_update_chain, 0, o); + } + + + + for (i = 0; i < bc->n; i++) s[bc->a[i]] = 0; + ///reset + v = v0; + av = asg_arc_a(fg->g, v); + an = asg_arc_n(fg->g, v); + for (k = 0; k < an; k++) { + av[k].del = 0; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 0); + } + fg->g->seq[v>>1].c = PRIMARY_LABLE; + + + v = v1^1; + av = asg_arc_a(fg->g, v); + an = asg_arc_n(fg->g, v); + for (k = 0; k < an; k++) { + av[k].del = 0; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 0); + } + fg->g->seq[v>>1].c = PRIMARY_LABLE; + + + for (i = 0; i < bc->n; i++) { + v = bc->a[i]; + av = asg_arc_a(fg->g, v); + an = asg_arc_n(fg->g, v); + for (k = 0; k < an; k++) { + av[k].del = 0; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 0); + } + + v ^= 1; + av = asg_arc_a(fg->g, v); + an = asg_arc_n(fg->g, v); + for (k = 0; k < an; k++) { + av[k].del = 0; asg_arc_del(fg->g, av[k].v^1, (av[k].ul>>32)^1, 0); + } + + fg->g->seq[v>>1].c = PRIMARY_LABLE; + } + return is_pop; +} + +uint64_t refine_bubble_popping(ma_ug_t *ug, buf_t *b, uint32_t v0, uint64_t max_dist, uint32_t positive_flag, uint32_t negative_flag, hap_cov_t *cov, utg_trans_t *o, uint32_t is_update_chain, rd_hamming_fly_simp_t *pf) +{ + // fprintf(stderr, "[M::%s]\n", __func__); + if(!asg_bub_pop1_primary_trio(ug->g, ug, v0, max_dist, b, positive_flag, negative_flag, 0, NULL, NULL, NULL, 0, 0, NULL)) return 0; + // if(((v0>>1) == 7536) && ((b->S.a[0]>>1) == 99223)) { + // fprintf(stderr, "[M::%s] uga_v::%u\n", __func__, v0); dbg_asys_gfa(ug->g); + // print_simple_dbg_gfa(ug->g, "uga"); + // } + uint32_t non_positive_flag = (uint32_t)-1, v, u, k, rId, pn, npn; + if(positive_flag == FATHER) non_positive_flag = MOTHER; + if(positive_flag == MOTHER) non_positive_flag = FATHER; + ma_utg_t* p = NULL; + ///b->S.a[0] is the sink of this bubble + ///v is the sink of this bubble + v = b->S.a[0]; pn = npn = 0; + ///scan node + do { + u = b->a[v].p; // u->v + if(v != b->S.a[0]) { + p = &(ug->u.a[v>>1]); + for (k = 0; k < p->n; k++) { + rId = p->a[k]>>33; + if(R_INF.trio_flag[rId] == positive_flag) pn++; + if(R_INF.trio_flag[rId] == non_positive_flag) npn++; + } + } + v = u; + } while (v != v0); + // fprintf(stderr, "[M::%s] pn::%u, npn::%u\n", __func__, pn, npn); + ///debug + if((npn <= 0) || ((npn <= ((npn+pn)*0.05)) && (npn <= 64))) {///phasing is ok + return asg_bub_pop1_primary_trio(ug->g, ug, v0, max_dist, b, positive_flag, negative_flag, 1, NULL, NULL, cov, is_update_chain, 0, o); + } + return renew_phase_bubble(pf, v0, b, ug, max_dist, positive_flag, negative_flag, cov, o, is_update_chain); +} + +// pop bubbles +int asg_pop_bubble_primary_trio(ma_ug_t *ug, uint64_t* i_max_dist, uint32_t positive_flag, uint32_t negative_flag, hap_cov_t *cov, utg_trans_t *o, uint32_t is_update_chain, rd_hamming_fly_simp_t *p) +{ + asg_t *g = ug->g; uint64_t n_pop = 0, max_dist; + uint32_t v, n_vtx = g->n_seq * 2, n_arc, nv, i; + asg_arc_t *av = NULL; + buf_t b; + if (!g->is_symm) asg_symm(g); + memset(&b, 0, sizeof(buf_t)); + ///set information for each node + b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + if(i_max_dist) max_dist = (*i_max_dist); + else max_dist = get_bub_pop_max_dist_advance(g, &b); + uint8_t* bs_flag = NULL; CALLOC(bs_flag, n_vtx); + + if(max_dist > 0) + { + for (v = 0; v < n_vtx; ++v) + { + if(bs_flag[v] != 0) continue; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + ///some edges could be deleted + for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs + if (!av[i].del) ++n_arc; + if (n_arc < 2) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, max_dist, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) + { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (i = 0; i < b.b.n; i++) + { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + bs_flag[b.b.a[i]] = bs_flag[b.b.a[i]^1] = 1; + } + bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 3; + } + } + + //traverse all node with two directions + for (v = 0; v < n_vtx; ++v) { + if(bs_flag[v] !=2) continue; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + ///some edges could be deleted + for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs + if (!av[i].del) ++n_arc; + if (n_arc > 1) { + if(p){ + n_pop += refine_bubble_popping(ug, &b, v, max_dist, positive_flag, negative_flag, cov, o, is_update_chain, p); + } else { + n_pop += asg_bub_pop1_primary_trio(ug->g, ug, v, max_dist, &b, positive_flag, negative_flag, 1, NULL, NULL, cov, is_update_chain, 0, o); + } + } + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] popped %lu bubbles\n", __func__, (unsigned long)n_pop); + } + } + + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + if (n_pop) asg_cleanup(g); + free(bs_flag); + return n_pop; +} + + + +int test_triangular_directly(asg_t *g, uint32_t v, +long long min_edge_length, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex) +{ + + uint32_t w; + int todel; + long long NodeLen_first[3]; + long long NodeLen_second[3]; + + asg_arc_t *av = asg_arc_a(g, v); + if(av[0].v == av[1].v) + { + return 0; + } + /**********************test first node************************/ + NodeLen_first[0] = NodeLen_first[1] = NodeLen_first[2] = -1; + if(asg_is_single_edge(g, av[0].v, v>>1) <= 2 && asg_is_single_edge(g, av[1].v, v>>1) <= 2) + { + NodeLen_first[asg_is_single_edge(g, av[0].v, v>>1)] = 0; + NodeLen_first[asg_is_single_edge(g, av[1].v, v>>1)] = 1; + } + ///one node has one out-edge, another node has two out-edges + if(NodeLen_first[1] == -1 || NodeLen_first[2] == -1) + { + return 0; + } + /**********************test first node************************/ + ///if the potiential edge has already been removed + if(av[NodeLen_first[2]].del == 1) + { + return 0; + } + + /**********************test second node************************/ + w = av[NodeLen_first[2]].v^1; + asg_arc_t *aw = asg_arc_a(g, w); + uint32_t nw = asg_arc_n(g, w); + if(nw != 2) + { + fprintf(stderr, "error\n"); + } + NodeLen_second[0] = NodeLen_second[1] = NodeLen_second[2] = -1; + if(asg_is_single_edge(g, aw[0].v, w>>1) <= 2 && asg_is_single_edge(g, aw[1].v, w>>1) <= 2) + { + NodeLen_second[asg_is_single_edge(g, aw[0].v, w>>1)] = 0; + NodeLen_second[asg_is_single_edge(g, aw[1].v, w>>1)] = 1; + } + ///one node has one out-edge, another node has two out-edges + if(NodeLen_second[1] == -1 || NodeLen_second[2] == -1) + { + return 0; + } + + + + todel = 0; + // if(check_if_diploid(av[0].v, av[1].v, g, reverse_sources, min_edge_length) && + // check_if_diploid(aw[0].v, aw[1].v, g, reverse_sources, min_edge_length)) + if(check_if_diploid(av[0].v, av[1].v, g, reverse_sources, min_edge_length, ruIndex) == 1|| + check_if_diploid(aw[0].v, aw[1].v, g, reverse_sources, min_edge_length, ruIndex) == 1) + { + todel = 1; + } + + + + if(todel) + { + ///fprintf(stderr, "v: %u\n", v>>1); + av[NodeLen_first[2]].del = 1; + ///remove the reverse direction + asg_arc_del(g, av[NodeLen_first[2]].v^1, av[NodeLen_first[2]].ul>>32^1, 1); + } + + return todel; +} + + + +int asg_arc_del_triangular_directly(asg_t *g, long long min_edge_length, +ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex) +{ + double startTime = Get_T(); + ///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; + + for (v = 0; v < n_vtx; ++v) + { + uint32_t nv = asg_arc_n(g, v); + if (g->seq[v>>1].del) + { + continue; + } + + if(nv < 2) + { + continue; + } + + + n_reduced += test_triangular_directly(g, v, min_edge_length, reverse_sources, ruIndex); + } + + + + if (n_reduced) { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d triangular overlaps\n", + __func__, n_reduced); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + return n_reduced; +} + + + + +int asg_arc_del_orthology(asg_t *g, ma_hit_t_alloc* reverse_sources, float drop_ratio, +long long miniedgeLen, R_to_U* ruIndex) +{ + double startTime = Get_T(); + ///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; + uint32_t idx[2]; + + for (v = 0; v < n_vtx; ++v) + { + uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del) continue; + ///some edges could be deleted + for (i = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs + if (!av[i].del) ++n_arc; + if (n_arc != 2) continue; + + for (i = 0, n_arc = 0; i < nv; i++) + { + if (!av[i].del) + { + idx[n_arc] = i; + n_arc++; + } + } + + if(check_if_diploid(av[idx[0]].v, av[idx[1]].v, g, reverse_sources, miniedgeLen, ruIndex) == 0) + { + float max = av[idx[0]].ol; + float min = av[idx[1]].ol; + + if(min < drop_ratio * max) + { + av[idx[1]].del = 1; + asg_arc_del(g, av[idx[1]].v^1, av[idx[1]].ul>>32^1, 1); + n_reduced++; + } + } + } + + + + + + if (n_reduced) { + asg_cleanup(g); + asg_symm(g); + } + + fprintf(stderr, "[M::%s] removed %d different hap overlaps\n", + __func__, n_reduced); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + + return n_reduced; +} + + + + +int asg_arc_del_orthology_multiple_way(asg_t *g, ma_hit_t_alloc* reverse_sources, float drop_ratio, +long long miniedgeLen, R_to_U* ruIndex) +{ + double startTime = Get_T(); + ///the reason is that each read has two direction (query->target, target->query) + uint32_t v, v_max, v_maxLen, n_vtx = g->n_seq * 2, n_reduced = 0; + + for (v = 0; v < n_vtx; ++v) + { + if (g->seq_vis[v] != 0) continue; + uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del) continue; + n_arc = get_real_length(g, v, NULL); + if (n_arc < 2) continue; + v_max = (uint32_t)-1; + v_maxLen = 0; + + for (i = 0, n_arc = 0; i < nv; i++) + { + if (!av[i].del) + { + if(v_max == (uint32_t)-1) + { + v_max = av[i].v; + v_maxLen = av[i].ol; + } + else if(check_if_diploid(v_max, av[i].v, g, reverse_sources, miniedgeLen, ruIndex) == 0) + { + if(av[i].ol < drop_ratio * v_maxLen) + { + ///fprintf(stderr, "v: %u, v_max: %u, av[%d].v: %u\n", v>>1, v_max>>1, i, av[i].v>>1); + + // av[i].ol = 1;///should be a bug + av[i].del = 1; + asg_arc_del(g, av[i].v^1, av[i].ul>>32^1, 1); + n_reduced++; + } + } + } + } + } + + if (n_reduced) { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d different hap overlaps\n", + __func__, n_reduced); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + return n_reduced; +} + + + +uint32_t detect_single_path_with_dels_by_length +(asg_t *g, uint32_t begNode, uint32_t* endNode, long long* Len, buf_t* b, long long maxLen) +{ + + uint32_t v = begNode, w; + uint32_t kv, kw; + (*Len) = 0; + + + while (1) + { + (*Len)++; + kv = get_real_length(g, v, NULL); + (*endNode) = v; + + ///if(b) kv_push(uint32_t, b->b, v>>1); + if(b) kv_push(uint32_t, b->b, v); + + if(kv == 0) + { + return END_TIPS; + } + + if(kv == 2) + { + return TWO_OUTPUT; + } + + if(kv > 2) + { + return MUL_OUTPUT; + } + + if((*Len) > maxLen) + { + return LONG_TIPS; + } + + ///up to here, kv=1 + ///kw must >= 1 + get_real_length(g, v, &w); + kw = get_real_length(g, w^1, NULL); + v = w; + (*endNode) = v; + + + if(kw == 2) + { + (*Len)++; + ///if(b) kv_push(uint32_t, b->b, v>>1); + if(b) kv_push(uint32_t, b->b, v); + return TWO_INPUT; + } + + if(kw > 2) + { + (*Len)++; + ///if(b) kv_push(uint32_t, b->b, v>>1); + if(b) kv_push(uint32_t, b->b, v); + return MUL_INPUT; + } + + + if((v>>1) == (begNode>>1)) + { + return LOOP; + } + } + + return LONG_TIPS; +} + + + +long long asg_arc_del_self_circle_untig(asg_t *g, long long circleLen, int is_drop) +{ + uint32_t v, w, n_vtx = g->n_seq * 2, n_reduced = 0, convex, flag; + long long ll; + asg_arc_t *aw; + uint32_t nw, k; + for (v = 0; v < n_vtx; ++v) + { + uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + ///some node could be deleted + if (g->seq[v>>1].del) continue; + if(is_drop && g->seq[v>>1].c == ALTER_LABLE) continue; + + n_arc = get_real_length(g, v, NULL); + if (n_arc != 1) continue; + + for (i = 0; i < nv; i++) + { + ///actually there is just one un-del edge + if (!av[i].del) + { + flag = detect_single_path_with_dels_by_length(g, v, &convex, &ll, NULL, circleLen); + if(ll > circleLen || flag == LONG_TIPS) + { + break; + } + if(flag == LOOP) + { + break; + } + if(flag != END_TIPS && flag != LONG_TIPS) + { + w = v^1; + n_arc = get_real_length(g, w, NULL); + if(n_arc == 0) + { + break; + } + aw = asg_arc_a(g, w); + nw = asg_arc_n(g, w); + for (k = 0; k < nw; k++) + { + if ((!aw[k].del) && (aw[k].v == (convex^1))) + { + aw[k].del = 1; + asg_arc_del(g, aw[k].v^1, aw[k].ul>>32^1, 1); + n_reduced++; + } + } + } + } + } + } + + if (n_reduced) { + asg_cleanup(g); + asg_symm(g); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d self-circles\n", + __func__, n_reduced); + } + + return n_reduced; +} + + +long long get_untig_coverage(ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, uint32_t* b, uint64_t n) +{ + uint64_t k, j; + uint32_t v; + ma_hit_t *h; + long long R_bases = 0, C_bases = 0; + for (k = 0; k < n; ++k) + { + v = b[k]>>1; + R_bases += coverage_cut[v].e - coverage_cut[v].s; + for (j = 0; j < (uint64_t)(sources[v].length); j++) + { + h = &(sources[v].buffer[j]); + C_bases += Get_qe((*h)) - Get_qs((*h)); + } + } + return C_bases/R_bases; +} + +/** +void copy_untig(asg_t *g, long long times, uint32_t* b, long long n, C_graph* cg) +{ + if(times <= 1) return; + + times--; + long long i, j; + uint64_t tmp; + for (i = 0; i < times; i++) + { + for (j = 0; j < n; j++) + { + tmp = + kv_push(uint64_t, cg->Node, ); + asg_add_auxiliary_seq_set(g, (b[j]>>1), 0); + } + } +} +**/ + +void init_C_graph(C_graph* g, uint32_t n_seq) +{ + kv_init(g->Nodes); + kv_init(g->Edges); + g->pre_n_seq = n_seq; + g->seqID = n_seq; +} + +void destory_C_graph(C_graph* g) +{ + kv_destroy(g->Nodes); + kv_destroy(g->Edges); +} + + +long long asg_arc_del_simple_circle_untig(ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, asg_t *g, long long circleLen, int is_drop) +{ + uint32_t v, w, n_vtx = g->n_seq * 2, n_reduced = 0, convex, flag; + long long ll; + asg_arc_t *aw; + uint32_t nw, k; + buf_t b; + memset(&b, 0, sizeof(buf_t)); + + C_graph cg; + init_C_graph(&cg, g->n_seq); + + for (v = 0; v < n_vtx; ++v) + { + uint32_t i, n_arc = 0, nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + ///some node could be deleted + if (g->seq[v>>1].del) continue; + if(is_drop && g->seq[v>>1].c == ALTER_LABLE) continue; + if(get_real_length(g, v^1, NULL)<=1) continue; + + n_arc = get_real_length(g, v, NULL); + if (n_arc != 1) continue; + + for (i = 0; i < nv; i++) + { + ///actually there is just one un-del edge + if (!av[i].del) + { + b.b.n = 0; + flag = detect_single_path_with_dels_by_length(g, v, &convex, &ll, &b, circleLen); + if(ll > circleLen || flag == LONG_TIPS) + { + break; + } + if(flag == LOOP) + { + break; + } + if(flag != END_TIPS && flag != LONG_TIPS) + { + if(v == convex && b.b.n > 1) + { + convex = b.b.a[b.b.n - 2]; + b.b.n--; + } + + w = v^1; + n_arc = get_real_length(g, w, NULL); + if(n_arc == 0) + { + break; + } + aw = asg_arc_a(g, w); + nw = asg_arc_n(g, w); + for (k = 0; k < nw; k++) + { + if ((!aw[k].del) && (aw[k].v == (convex^1))) + { + // coverage = get_untig_coverage(sources, coverage_cut, b.b.a, b.b.n); + // copy_untig(g, (coverage/asm_opt.coverage), b.b.a, b.b.n, &cg); + + + aw[k].del = 1; + asg_arc_del(g, aw[k].v^1, aw[k].ul>>32^1, 1); + n_reduced++; + } + } + } + } + } + } + + if (n_reduced) { + asg_cleanup(g); + asg_symm(g); + } + + free(b.b.a); + destory_C_graph(&cg); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d self-circles\n", + __func__, n_reduced); + } + + return n_reduced; +} + + +int double_check_tangle(uint32_t vBeg, uint32_t vEnd, uint32_t* u_vecs, uint32_t n, asg_t *nsg) +{ + uint32_t v, nv, k, i, j; + asg_arc_t *av = NULL; + if(vBeg != (uint32_t)-1) + { + v = vBeg; + nv = asg_arc_n(nsg, v); + av = asg_arc_a(nsg, v); + for(k = 0; k < nv; k++) + { + if(av[k].del) continue; + for (i = 0; i < n; i++) + { + if((av[k].v>>1)==(u_vecs[i]>>1)) break; + } + ///haven't found + if(i == n) return 0; + } + } + + if(vEnd != (uint32_t)-1) + { + v = vEnd^1; + nv = asg_arc_n(nsg, v); + av = asg_arc_a(nsg, v); + for(k = 0; k < nv; k++) + { + if(av[k].del) continue; + for (i = 0; i < n; i++) + { + if((av[k].v>>1)==(u_vecs[i]>>1)) break; + } + ///haven't found + if(i == n) return 0; + } + } + + ///scan tangles + for (j = 0; j < n; j++) + { + v = u_vecs[j]; + nv = asg_arc_n(nsg, v); + av = asg_arc_a(nsg, v); + for(k = 0; k < nv; k++) + { + if(av[k].del) continue; + for (i = 0; i < n; i++) + { + if((av[k].v>>1)==(u_vecs[i]>>1)) break; + } + if(i == n && av[k].v != (vBeg^1) && av[k].v != vEnd) return 0; + } + + + + v = v^1; + nv = asg_arc_n(nsg, v); + av = asg_arc_a(nsg, v); + for(k = 0; k < nv; k++) + { + if(av[k].del) continue; + for (i = 0; i < n; i++) + { + if((av[k].v>>1)==(u_vecs[i]>>1)) break; + } + if(i == n && av[k].v != (vBeg^1) && av[k].v != vEnd) return 0; + } + } + + return 1; +} + +int explore_graph(asg_t *nsg, uint32_t vBeg, float single_threshold, +float l_untig_rate_threshold, long long minLongUntig, long long maxShortUntig, uint32_t ignore_d, +buf_t* bb, uint32_t** r, size_t* rm, size_t* rn, uint8_t* visit, ma_ug_t *ug, uint32_t* r_ID) +{ + ///the ID of the end long unitig + (*r_ID) = (uint32_t)-1; + uint32_t nv, vBeg_end; + asg_arc_t *av; + + kvec_t(uint32_t) u_vecs; + kv_init(u_vecs); + if(r && rm && rn) kv_reuse(u_vecs, 0, (*rm), (*r)); + + memset(visit, 0, nsg->n_seq); + kdq_t(uint32_t) *buf; + buf = kdq_init(uint32_t); + + uint32_t vEnd, threshold, num_reads = 0, i, k, v, end = (uint32_t)-1, in = 0, vELen, tmp; + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + + bb->b.n = 0; + if(get_unitig(nsg, ug, vBeg, &vEnd, &nodeLen, &baseLen, + &max_stop_nodeLen, &max_stop_baseLen, 1, bb)==LOOP) + { + ///the length of LOO is infinite + kdq_destroy(uint32_t, buf); + return 0; + } + vBeg_end = vEnd; + threshold = nodeLen; + for (i = 0; i < bb->b.n; i++) + { + Set_vis(visit, bb->b.a[i], ignore_d); + Set_vis(visit, bb->b.a[i]^1, ignore_d); + } + v = vBeg; + + kdq_push(uint32_t, buf, v); + while (kdq_size(buf) != 0) + { + in++; + v = *(kdq_pop(uint32_t, buf)); + + ///in == 1 means the start node, it is useless + if(in != 1) + { + ///get current untig length + bb->b.n = 0; + if(get_unitig(nsg, ug, v, &vEnd, &nodeLen, &baseLen, + &max_stop_nodeLen, &max_stop_baseLen, 1, bb)==LOOP) + { + kdq_destroy(uint32_t, buf); + return 0; + } + vELen = nodeLen; + + ///first long unitig except the start node + if(if_long_tip_length(nsg, ug, v, &vELen, + minLongUntig, maxShortUntig, l_untig_rate_threshold, threshold)==1) + { + if(end == (uint32_t)-1) + { + end = v; + continue; + } + else + { + in = (uint32_t)-1; + break; + } + } + + if(vELen > (threshold * single_threshold)) + { + in = (uint32_t)-1; + break; + } + + num_reads = num_reads + vELen; + if(num_reads > threshold) + { + in = (uint32_t)-1; + break; + } + + if(r && rm && rn) + { + for (i = 0; i < bb->b.n; i++) + { + kv_push(uint32_t, u_vecs, bb->b.a[i]); + } + } + } + + tmp = v^1; + v = vEnd; + nv = asg_arc_n(nsg, v); + av = asg_arc_a(nsg, v); + for(k = 0; k < nv; k++) + { + if(av[k].del) continue; + + if(av[k].v == vBeg) + { + in = (uint32_t)-1; + goto termi; + } + + if(Get_vis(visit,av[k].v,ignore_d)==0) + { + kdq_push(uint32_t, buf, av[k].v); + + bb->b.n = 0; + get_unitig(nsg, ug, av[k].v, &vEnd, &nodeLen, &baseLen, + &max_stop_nodeLen, &max_stop_baseLen, 1, bb); + + for (i = 0; i < bb->b.n; i++) + { + Set_vis(visit, bb->b.a[i], ignore_d); + } + } + } + + ///for start node, we just need one direction + if(in != 1 && ignore_d) + { + v = tmp; + nv = asg_arc_n(nsg, v); + av = asg_arc_a(nsg, v); + for(k = 0; k < nv; k++) + { + if(av[k].del) continue; + + if(av[k].v == vBeg) + { + in = (uint32_t)-1; + goto termi; + } + + if(Get_vis(visit,av[k].v,ignore_d)==0) + { + kdq_push(uint32_t, buf, av[k].v); + + bb->b.n = 0; + get_unitig(nsg, ug, av[k].v, &vEnd, &nodeLen, &baseLen, + &max_stop_nodeLen, &max_stop_baseLen, 1, bb); + + + for (i = 0; i < bb->b.n; i++) + { + Set_vis(visit, bb->b.a[i], ignore_d); + } + } + } + } + } + + termi: + kdq_destroy(uint32_t, buf); + if(r && rm && rn) + { + (*rn) = u_vecs.n; + (*rm) = u_vecs.m; + (*r) = u_vecs.a; + } + + + (*r_ID) = end; + ///in == 1 means the end subgraph is the long untig itself + ///so here is no tangles + if(in == (uint32_t)-1 || in == 1) + { + return 0; + } + else + { + if(r && rm && rn) return double_check_tangle(vBeg_end, (*r_ID), u_vecs.a, u_vecs.n, nsg); + + return 1; + } +} + +void output_tangles(uint32_t startID, uint32_t endId, uint32_t* a, uint32_t n, const char* lable) +{ + kvec_t(uint32_t) u_vecs; + u_vecs.a = a, u_vecs.n = n; + + fprintf(stderr, "\n%sstartID: %u, dir: %u\n", lable, startID>>1, startID&1); + fprintf(stderr, "%sendID: %u, dir: %u\n", lable, endId>>1, endId&1); + uint32_t ijk; + for (ijk = 0; ijk < u_vecs.n; ijk++) + { + fprintf(stderr, "%stangleID: %u, dir: %u\n", lable, u_vecs.a[ijk]>>1, u_vecs.a[ijk]&1); + } +} + + +int get_arc(asg_t *g, uint32_t src, uint32_t dest, asg_arc_t* result) +{ + uint32_t i; + if(g->seq[src>>1].del) return 0; + + uint32_t nv = asg_arc_n(g, src); + asg_arc_t *av = asg_arc_a(g, src); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + if(av[i].v == dest) + { + (*result) = av[i]; + break; + } + } + + if(i != nv) return 1; + return 0; +} + +uint32_t insert_index(asg_t *g, uint32_t v) +{ + uint32_t v_tx = g->n_seq * 2; + if(v >= v_tx) return (uint32_t)-1; + if(asg_arc_n(g, v)!=0) return (g->idx[v]>>32) + asg_arc_n(g, v); + ///now v itself does not have any edge + while (v < v_tx && asg_arc_n(g, v) == 0){v++;} + ///means there are no edge at the whole graph + if(v>=v_tx) return g->n_arc; + return (g->idx[v]>>32); +} + +asg_arc_t* insert_index_p(asg_t *g, long long index, uint32_t m_distance) +{ + ///each edge has two direction + if (g->n_arc + m_distance > g->m_arc) + { + ///g->m_arc = g->n_arc + (m_distance<<1); + g->m_arc = (g->n_arc + m_distance)<<1; + g->arc = (asg_arc_t*)realloc(g->arc, g->m_arc * sizeof(asg_arc_t)); + } + long long i = g->n_arc; i--; + for (; i >= index; i--) + { + g->arc[i+m_distance] = g->arc[i]; + } + + g->n_arc = g->n_arc + m_distance; + + return &(g->arc[index]); +} + +void exchange_arcs(asg_arc_t* x, asg_arc_t* y) +{ + asg_arc_t k; + k = (*x);(*x) = (*y);(*y) = k; +} + +void insert_arc(asg_t *g, long long index, uint32_t m_distance, uint32_t src, uint32_t srcLen, uint32_t dest, +uint32_t oLen, uint8_t strong, uint8_t el, uint8_t no_l_indel) +{ + asg_arc_t* p; + uint32_t l; + long long i; + p = insert_index_p(g, index, m_distance); + p->del = !!(0);p->el = el; p->no_l_indel = no_l_indel; p->strong = strong; p->ol = oLen; + p->v = dest; + p->ul = src; p->ul = p->ul << 32; l = srcLen - oLen; p->ul = p->ul | l; + for (i = index - 1; i >= 0 && p->ul <= g->arc[i].ul; i--) + { + if((!g->arc[i].del)&&(g->arc[i].v==p->v) && ((g->arc[i].ul>>32)==(p->ul>>32))) + { + p->del = !!(1); + break; + } + exchange_arcs(p, &(g->arc[i]));p = &(g->arc[i]); + } + + + if(asg_arc_n(g, src) == 0) + { + g->idx[src] = index; g->idx[src] = g->idx[src]<<32; g->idx[src] = g->idx[src] | 1; + } + else + { + g->idx[src] = g->idx[src] + 1; + } + + uint32_t v, v_tx = g->n_seq*2; + uint64_t add = 1; add = add << 32; + for (v = src+1; v < v_tx; v++) + { + if(asg_arc_n(g, v) == 0) continue; + g->idx[v] += add; + } +} + +int asg_append_edges_to_srt(asg_t *g, uint32_t src, +uint32_t srcLen, uint32_t dest, uint32_t oLen, +uint8_t strong, uint8_t el, uint8_t no_l_indel) +{ + uint32_t v_tx = g->n_seq * 2; + /** + uint32_t d_i = 0, current_i, next_i, src_n, s_index, e_index; + while(d_i < v_tx) + { + current_i = d_i; + d_i++; + src_n = asg_arc_n(g, current_i); + if(src_n == 0) continue; + s_index = (g->idx[current_i]>>32); + e_index = s_index + src_n; + + while (d_i < v_tx && asg_arc_n(g, d_i) == 0){d_i++;} + if(d_i>=v_tx) break; + next_i = d_i; + + + if(current_i != v_tx) + { + if(e_index != (g->idx[next_i]>>32)) + { + fprintf(stderr, "v_tx: %u, current_i: %u, node: %u, s_index: %u, e_index: %u, g->idx[next_i]>>32: %u\n", + v_tx, current_i, current_i>>1, s_index, e_index, g->idx[next_i]>>32); + } + } + else + { + if(e_index != g->n_arc) + { + fprintf(stderr, "ERROR2\n"); + } + } + } + + for (d_i = 0; d_i < v_tx; d_i++) + { + uint32_t nv = asg_arc_n(g, d_i), s_i; + asg_arc_t *av = asg_arc_a(g, d_i); + asg_arc_t forward, backward; + for (s_i = 0; s_i < nv; s_i++) + { + if(av[s_i].del) continue; + forward = av[s_i]; + if(get_arc(g, forward.ul>>32, forward.v, &forward) == 0) + { + fprintf(stderr, "ERROR1\n"); + } + if(forward.del != av[s_i].del || forward.el != av[s_i].el || + forward.no_l_indel != av[s_i].no_l_indel ||forward.ol != av[s_i].ol || + forward.strong != av[s_i].strong || forward.ul != av[s_i].ul || + forward.v != av[s_i].v) + { + fprintf(stderr, "ERROR2\n"); + } + + if(get_arc(g, forward.v^1, (forward.ul>>32)^1, &backward) == 0) + { + fprintf(stderr, "ERROR3\n"); + } + + if(forward.ol != backward.ol) + { + fprintf(stderr, "forward.ol: %u, backward.ol: %u\n", + forward.ol, backward.ol); + } + + } + } + **/ + + + if (src >= v_tx || dest >= v_tx) + { + return 0; + } + + ///we need to link src--->dest and (dest^1)----->(src^1) + uint32_t src_i = insert_index(g, src); + insert_arc(g, src_i, 1, src, srcLen, dest, oLen, strong, el, no_l_indel); + + + /** + if (src >= v_tx || (src^1) >= v_tx || dest >= v_tx || (dest^1) >= v_tx) + { + return 0; + } + + ///we need to link src--->dest and (dest^1)----->(src^1) + uint32_t src_i = insert_index(g, src); + insert_arc(g, src_i, 1, src, srcLen, dest, oLen); + uint32_t dest_i = insert_index(g, (dest^1)); + insert_arc(g, dest_i, 1, dest^1, destLen, src^1, oLen); + **/ + + + ///we need to link src--->dest and (dest^1)----->(src^1) + /** + if(src > (dest^1)) + { + uint32_t src_i = insert_index(g, src); + insert_arc(g, src_i, src, srcLen, dest, oLen); + uint32_t dest_i = insert_index(g, (dest^1)); + insert_arc(g, dest_i, dest^1, destLen, src^1, oLen); + } + else + { + uint32_t dest_i = insert_index(g, (dest^1)); + insert_arc(g, dest_i, dest^1, destLen, src^1, oLen); + uint32_t src_i = insert_index(g, src); + insert_arc(g, src_i, src, srcLen, dest, oLen); + } + **/ + + return 1; +} + +void append_ma_utg_t(ma_utg_t* v_x, ma_utg_t* v_y) +{ + if(v_x->m < (v_x->n + v_y->n)) + { + v_x->m = v_x->n + v_y->n; + v_x->a = (uint64_t*)realloc(v_x->a, v_x->m * sizeof(uint64_t)); + } + memcpy(v_x->a+v_x->n, v_y->a, v_y->n*sizeof(uint64_t)); + v_x->n = v_x->n + v_y->n; + free(v_y->a); + v_y->m=v_y->n=0;v_y->a=NULL; +} + + +#define UNROLL 0 +#define CONVEX 1 +void merge_nodes(ma_ug_t *ug, uint32_t startID, uint32_t endId, uint32_t* a, uint32_t n, +uint32_t type) +{ + ma_utg_t *v_x = NULL, *v_y = NULL; + asg_t* nsg = ug->g; + kvec_t(uint32_t) u_vecs; + uint32_t i = 0, maxEvaluateLen = 0, maxBaseLen = 0, v, totalEvaluateLen = 0; + u_vecs.a = a, u_vecs.n = n; + if(u_vecs.n > 0) ///u_vecs does not contain startID && endId + { + v_x = &(ug->u.a[u_vecs.a[0]>>1]); + asg_seq_del(nsg, u_vecs.a[0]>>1); + maxEvaluateLen = EvaluateLen(ug->u, u_vecs.a[0]>>1); + maxBaseLen = v_x->len; + totalEvaluateLen += EvaluateLen(ug->u, u_vecs.a[0]>>1); + } + + + for (i = 1; i < u_vecs.n; i++) + { + v_y = &(ug->u.a[u_vecs.a[i]>>1]); + if(maxEvaluateLen <= EvaluateLen(ug->u, u_vecs.a[i]>>1)) + { + maxEvaluateLen = EvaluateLen(ug->u, u_vecs.a[i]>>1); + maxBaseLen = v_y->len; + } + totalEvaluateLen += EvaluateLen(ug->u, u_vecs.a[i]>>1); + + + append_ma_utg_t(v_x, v_y); + asg_seq_del(nsg, u_vecs.a[i]>>1); + } + + + if(u_vecs.n > 0) + { + i = 0; + nsg->seq[u_vecs.a[0]>>1].del = !!(0); + + + EvaluateLen(ug->u, u_vecs.a[0]>>1) = maxEvaluateLen; + totalEvaluateLen = totalEvaluateLen / 2; + if(totalEvaluateLen > EvaluateLen(ug->u, u_vecs.a[0]>>1)) + { + EvaluateLen(ug->u, u_vecs.a[0]>>1) = totalEvaluateLen; + } + IsMerge(ug->u, u_vecs.a[0]>>1)++; + + + v_x->len = maxBaseLen; + /****************************may have bugs********************************/ + nsg->seq[u_vecs.a[0]>>1].len = maxBaseLen; + /****************************may have bugs********************************/ + v = u_vecs.a[0]; + + if(type == UNROLL) + { + if(startID != (uint32_t)-1) + { + asg_append_edges_to_srt(nsg, startID, ug->u.a[startID>>1].len, v, 0, 0, 0 ,0); + asg_append_edges_to_srt(nsg, v^1, ug->u.a[v>>1].len, startID^1, 0, 0, 0, 0); + } + + if(endId != (uint32_t)-1) + { + asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, endId, 0, 0, 0 ,0); + asg_append_edges_to_srt(nsg, endId^1, ug->u.a[endId>>1].len, v^1, 0, 0, 0 ,0); + } + } + + if(type == CONVEX) + { + if(startID != (uint32_t)-1) + { + asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, startID^1, 0, 0, 0, 0); + asg_append_edges_to_srt(nsg, startID, ug->u.a[startID>>1].len, v^1, 0, 0, 0 ,0); + } + + if(endId != (uint32_t)-1) + { + asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, endId, 0, 0, 0 ,0); + asg_append_edges_to_srt(nsg, endId^1, ug->u.a[endId>>1].len, v^1, 0, 0, 0 ,0); + } + } + } +} + +///return 1 is what we want +///as for return value: 0: do nothing, 1: unroll, 2: convex +#define CONVEX_M 1 +#define UNROLL_M 2 +#define UNROLL_E 3 +inline uint32_t walk_through(asg_t *read_g, ma_ug_t *ug, ma_hit_t_alloc* reverse_sources, long long minLongUntig, +long long maxShortUntig, float l_untig_rate, float max_node_threshold, buf_t* b_0, buf_t* b_1, +kvec_t_u32_warp* u_vecs, uint8_t* visit, uint32_t v, uint32_t* r_beg, uint32_t* r_end, +uint32_t* r_next_uID, R_to_U* ruIndex, uint8_t* is_r_het) +{ + (*r_beg) = (*r_end) = (uint32_t)-1; + asg_t* nsg = ug->g; + uint32_t i, beg, end, primaryLen, returnFlag; + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + + /*****************************simple checking**********************************/ + beg = v; + if(nsg->seq[beg>>1].del || asg_arc_n(nsg, beg) <= 0 || get_real_length(nsg, beg, NULL)<=0) + { + return 0; + } + if(get_real_length(nsg, beg^1, NULL) == 1)///check if beg is the tig end + { + get_real_length(nsg, beg^1, &end); + if(get_real_length(nsg, end^1, NULL) == 1) + { + return 0; + } + } + + ///if the contig here is too small + primaryLen = get_unitig(nsg, ug, beg, &end, &nodeLen, &baseLen, + &max_stop_nodeLen, &max_stop_baseLen, 1, NULL); + if(primaryLen == LOOP || nodeLen < minLongUntig) + { + return 0; + } + primaryLen = nodeLen; + + if(get_real_length(nsg, end, NULL) <= 0)///if it is already a simple contig + { + return 0; + } + /*****************************simple checking**********************************/ + (*r_beg) = beg; (*r_end) = end; + + /*****************************adjacent checking**********************************/ + uint32_t nw = asg_arc_n(nsg, end), n_arc = 0, next_uID, next_uID_verify; + asg_arc_t *aw = asg_arc_a(nsg, end); + for (i = 0; i < nw; i++) + { + if(!aw[i].del) + { + n_arc++; + ////we don't want any long tip here + if(if_long_tip_length(nsg, ug, aw[i].v, NULL, + minLongUntig, maxShortUntig, l_untig_rate, primaryLen)==1) + { + n_arc = 0; + break; + } + } + } + + if(n_arc == 0) + { + return 0; + } + /*****************************adjacent checking**********************************/ + + ///here all out-nodes of v are small untigs + if(explore_graph(nsg, beg, max_node_threshold, l_untig_rate, + minLongUntig, maxShortUntig, 1, b_0, &(u_vecs->a.a), &(u_vecs->a.m), + &(u_vecs->a.n), visit, ug, &next_uID) == 1) + { + (*r_next_uID) = next_uID; + if(next_uID != (uint32_t)-1 && u_vecs->a.n == 1 + && IsMerge(ug->u, u_vecs->a.a[0]>>1) > 0) + { + return 0; + } + ///if next_uID == (uint32_t)-1, that means we found an end subgraph + if(next_uID != (uint32_t)-1) + { + ///need to avoid missassembly + ///merge all tangle as two types: 1. convex; 2, unroll them as a line + ///should do somthing here, but we just skip it for covenience + returnFlag = explore_graph(nsg, beg, max_node_threshold, l_untig_rate, + minLongUntig, maxShortUntig, 0, b_0, NULL, NULL, NULL, visit, ug, + &next_uID_verify); + + if((returnFlag == 1 && next_uID_verify != next_uID) || (returnFlag == 0)) + { + //output_tangles(beg, next_uID, u_vecs->a.a, u_vecs->a.n, (char*)("###")); + returnFlag = 0; + } + else + { + returnFlag = 1; + } + + // #define UNAVAILABLE (uint32_t)-1 + // #define PLOID 0 + // #define NON_PLOID 1 + if(returnFlag == 1 && check_different_haps(nsg, ug, read_g, beg, next_uID, + reverse_sources, b_0, b_1, ruIndex, is_r_het, minLongUntig-1, 1) == PLOID) + { + ///output_tangles(beg, next_uID, u_vecs->a.a, u_vecs->a.n, (char*)("???")); + returnFlag = 0; + } + + if(returnFlag == 0) + { + merge_nodes(ug, end, next_uID, u_vecs->a.a, u_vecs->a.n, CONVEX); + return CONVEX_M; + } + } + + ///actually it is not possible here + if(u_vecs->a.n <= 0 || next_uID>>1 == beg>>1) + { + return 0; + } + ///output_tangles(beg, next_uID, u_vecs->a.a, u_vecs->a.n, (char*)("")); + merge_nodes(ug, end, next_uID, u_vecs->a.a, u_vecs->a.n, UNROLL); + if(next_uID != (uint32_t)-1) + { + (*r_next_uID) = next_uID; + return UNROLL_M; + } + else ///end tangle + { + if(u_vecs->a.n > 0) + { + (*r_next_uID) = u_vecs->a.a[0]; + } + return UNROLL_E; + } + } + + return 0; +} + + +void adjust_asg_by_ug(ma_ug_t *ug, asg_t *read_g) +{ + uint32_t v, n_vtx, i = 0, qn; + asg_t* nsg = ug->g; + n_vtx = nsg->n_seq; + ma_utg_t* node = NULL; + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].c == ALTER_LABLE) + { + node = &(ug->u.a[v]); + for (i = 0; i < node->n; i++) + { + qn = node->a[i]>>33; + read_g->seq[qn].c = ALTER_LABLE; + } + } + } + + + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].c == ALTER_LABLE) + { + node = &(ug->u.a[v]); + for (i = 0; i < node->n; i++) + { + qn = node->a[i]>>33; + ///read_g->seq[qn].c = ALTER_LABLE; + asg_seq_drop(read_g, qn); + } + } + } + + asg_cleanup(read_g); + asg_symm(read_g); +} + +void lable_hap_asg_by_ug(ma_ug_t *ug, asg_t *read_g) +{ + uint32_t v, n_vtx, i = 0, qn; + asg_t* nsg = ug->g; + n_vtx = nsg->n_seq; + ma_utg_t* node = NULL; + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].c == HAP_LABLE) + { + node = &(ug->u.a[v]); + for (i = 0; i < node->n; i++) + { + qn = node->a[i]>>33; + read_g->seq[qn].c = HAP_LABLE; + } + } + } + +} + +///qn is the read Id +///self_offset is the offset of this read in contig +void query_reverse_sources(asg_t *read_g, ma_hit_t_alloc* reverse_sources, +R_to_U* ruIndex, uint32_t qn, uint32_t self_offset, kvec_t_u64_warp* u_vecs) +{ + uint32_t i, rId, is_Unitig, cId; + uint64_t mode; + ///means the reads coming from different haplotype have already been purged + if(read_g->seq[qn].c == HAP_LABLE) + { + cId = (uint32_t)-1; + mode = self_offset; mode = mode << 33; mode = mode|cId; mode = mode | (uint64_t)(0x100000000); + kv_push(uint64_t, u_vecs->a, mode); + return; + } + + + for (i = 0; i < reverse_sources[qn].length; i++) + { + rId = Get_tn(reverse_sources[qn].buffer[i]); + ///there are three cases: + ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id + ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 + ///3. read has bee deleted, get_R_to_U() return the id of read that contains it + if(read_g->seq[rId].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, rId, &rId, &is_Unitig); + if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; + } + + ///here rId is the id of the read coming from the different haplotype + ///cId is the id of the corresponding contig (note here is the contig, instead of untig) + get_R_to_U(ruIndex, rId, &cId, &is_Unitig); + if(is_Unitig == 0) continue; + ///if the read is at alternative contigs, cId might be (uint32_t)-1 + ///if(cId == (uint32_t)-1) + mode = self_offset; mode = mode << 33; mode = mode|(uint64_t)(cId); + kv_push(uint64_t, u_vecs->a, mode); + } + +} + + + +uint32_t get_rId_from_contig_by_offset(ma_ug_t *ug, rIdContig* array, uint32_t offset) +{ + uint32_t uId, rId; + ma_utg_t* reads; + for (;array->untigI < array->b_0->b.n; array->untigI++) + { + uId = array->b_0->b.a[array->untigI]>>1; + ///if(IsMerge(ug->u, uId)>0) continue; + reads = &(ug->u.a[uId]); + for (;array->readI < reads->n; array->readI++, array->offset++) + { + if(array->offset == offset) + { + rId = reads->a[array->readI]>>33; + return rId; + } + } + array->readI = 0; + } + + + array->offset = 0; + for (array->untigI = 0;array->untigI < array->b_0->b.n; array->untigI++) + { + uId = array->b_0->b.a[array->untigI]>>1; + ///if(IsMerge(ug->u, uId)>0) continue; + reads = &(ug->u.a[uId]); + for (array->readI = 0;array->readI < reads->n; array->readI++, array->offset++) + { + if(array->offset == offset) + { + rId = reads->a[array->readI]>>33; + return rId; + } + } + } + + array->untigI = array->readI = array->offset = 0; + return (uint32_t)-1; +} + +inline uint32_t get_contig_len(ma_ug_t *ug, buf_t* b_0) +{ + uint32_t uId, untigI, Len = 0; + ma_utg_t* reads; + + for (untigI = 0;untigI < b_0->b.n; untigI++) + { + uId = b_0->b.a[untigI]>>1; + ///if(IsMerge(ug->u, uId)>0) continue; + reads = &(ug->u.a[uId]); + Len = Len + reads->n; + } + + return Len; +} + +uint32_t get_offset_from_contig_by_rId(ma_ug_t *ug, rIdContig* array, uint32_t query_rId) +{ + uint32_t uId, rId; + ma_utg_t* reads; + for (;array->untigI < array->b_0->b.n; array->untigI++) + { + uId = array->b_0->b.a[array->untigI]>>1; + ///if(IsMerge(ug->u, uId)>0) continue; + reads = &(ug->u.a[uId]); + for (;array->readI < reads->n; array->readI++, array->offset++) + { + rId = reads->a[array->readI]>>33; + if(rId == query_rId) return array->offset; + } + array->readI = 0; + } + + + array->offset = 0; + for (array->untigI = 0;array->untigI < array->b_0->b.n; array->untigI++) + { + uId = array->b_0->b.a[array->untigI]>>1; + ///if(IsMerge(ug->u, uId)>0) continue; + reads = &(ug->u.a[uId]); + for (array->readI = 0;array->readI < reads->n; array->readI++, array->offset++) + { + rId = reads->a[array->readI]>>33; + if(rId == query_rId) return array->offset; + } + } + + array->untigI = array->readI = array->offset = 0; + return (uint32_t)-1; +} + +///tn is the cId, tn_off is the order of rId with the same cId +uint32_t get_reverseId(asg_t *read_g, ma_hit_t_alloc* reverse_sources, +R_to_U* ruIndex, uint32_t qn, uint32_t tn, uint32_t tn_off) +{ + uint32_t i, rId, is_Unitig, cId, cId_off = 0; + for (i = 0; i < reverse_sources[qn].length; i++) + { + rId = Get_tn(reverse_sources[qn].buffer[i]); + ///there are three cases: + ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id + ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 + ///3. read has bee deleted, get_R_to_U() return the id of read that contains it + if(read_g->seq[rId].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, rId, &rId, &is_Unitig); + if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; + } + + ///here rId is the id of the read coming from the different haplotype + ///cId is the id of the corresponding contig (note here is the contig, instead of untig) + get_R_to_U(ruIndex, rId, &cId, &is_Unitig); + if(is_Unitig == 0) continue; + ///if the read is at alternative contigs, cId might be (uint32_t)-1 + ///if(cId == (uint32_t)-1) + if(cId == tn) + { + if(cId_off == tn_off) return rId; + cId_off++; + } + } + + return (uint32_t)-1; +} + +uint32_t get_contig_overlap_interval(uint32_t is_reverse, +uint32_t q_beg, uint32_t q_end, uint32_t qLen, uint32_t t_beg, uint32_t t_end, uint32_t tLen, +uint32_t* r_q_beg, uint32_t* r_q_end, uint32_t* r_t_beg, uint32_t* r_t_end) +{ + uint32_t k; + (*r_q_beg) = (*r_q_end) = (*r_t_beg) = (*r_t_end) = (uint32_t)-1; + if(q_end >= qLen || t_end >= tLen) return 0; + if(q_beg >= qLen || t_beg >= tLen) return 0; + + if(is_reverse) + { + ///k = q_beg; q_beg = q_end; q_end = k; + ///q_beg = qLen - q_beg - 1; q_end = qLen - q_end - 1; k = q_beg; q_beg = q_end; q_end = k; + ///k = t_beg; t_beg = t_end; t_end = k; + t_beg = tLen - t_beg - 1; t_end = tLen - t_end - 1; k = t_beg; t_beg = t_end; t_end = k; + } + + + + + if(q_beg <= t_beg) + { + t_beg = t_beg - q_beg; q_beg = 0; + } + else + { + q_beg = q_beg - t_beg; t_beg = 0; + } + + uint32_t q_right_length = qLen - q_end - 1; + uint32_t t_right_length = tLen - t_end - 1; + if(q_right_length <= t_right_length) + { + q_end = qLen - 1; t_end = t_end + q_right_length; + } + else + { + t_end = tLen - 1; q_end = q_end + t_right_length; + } + + if(is_reverse) + { + ///q_beg = qLen - q_beg - 1; q_end = qLen - q_end - 1; k = q_beg; q_beg = q_end; q_end = k; + t_beg = tLen - t_beg - 1; t_end = tLen - t_end - 1; k = t_beg; t_beg = t_end; t_end = k; + } + + (*r_q_beg) = q_beg; (*r_q_end) = q_end; + (*r_t_beg) = t_beg; (*r_t_end) = t_end; + return 1; +} + + +int get_haplotype_rate(ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* reverse_sources, +R_to_U* ruIndex, buf_t* b_0, uint32_t beg, uint32_t end, uint32_t query_cId, float match_rate) +{ + uint32_t i, j, k, num, match_num, offset, uId, qn, rId, is_Unitig, cId; + ma_utg_t* reads; + + offset = match_num = num = 0; + for (i = 0; i < b_0->b.n; i++) + { + uId = b_0->b.a[i]>>1; + ///if(IsMerge(ug->u, uId)>0) continue; + reads = &(ug->u.a[uId]); + for (j = 0; j < reads->n; j++, offset++) + { + + if(offset < beg || offset > end) continue; + qn = reads->a[j]>>33; + if(reverse_sources[qn].length > 0) num++; + for (k = 0; k < reverse_sources[qn].length; k++) + { + rId = Get_tn(reverse_sources[qn].buffer[k]); + ///there are three cases: + ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id + ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 + ///3. read has bee deleted, get_R_to_U() return the id of read that contains it + if(read_g->seq[rId].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, rId, &rId, &is_Unitig); + if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; + } + + ///here rId is the id of the read coming from the different haplotype + ///cId is the id of the corresponding contig (note here is the contig, instead of untig) + get_R_to_U(ruIndex, rId, &cId, &is_Unitig); + if(is_Unitig == 0) continue; + ///if the read is at alternative contigs, cId might be (uint32_t)-1 + + if(cId == query_cId) + { + match_num++; + break; + } + + } + } + } + + if(match_num >= num*match_rate) return 1; + return 0; +} + + +#define contig_seed 20 +inline int get_useful_contig(kvec_t_u64_warp* u_vecs, float density, uint32_t miniLen, uint32_t* r_cId) +{ + (*r_cId) = (uint32_t)-1; + uint32_t cId; + uint32_t intervalLen = 0, realLen = 0, useful_index = (uint32_t)-1; + uint32_t i = u_vecs->i, end; + float T_density = density/2; + + if(i >= u_vecs->a.n) return -1; + if((uint32_t)(u_vecs->a.a[i]) == (uint32_t)-1) + { + u_vecs->i++; + return 0; + } + + end = i + contig_seed; + if(end > u_vecs->a.n) end = u_vecs->a.n; + cId = (uint32_t)(u_vecs->a.a[i]); + for (; i < end; i++) + { + if(cId == (uint32_t)(u_vecs->a.a[i])) realLen++; + intervalLen++; + if(realLen >= intervalLen*density) useful_index = i; + } + + if(realLen < intervalLen*T_density) + { + u_vecs->i++; + return 0; + } + ///here we found a useful seed + ///it seems we don't need to scan backward + for (; i < u_vecs->a.n; i++) + { + if(cId == (uint32_t)(u_vecs->a.a[i])) realLen++; + intervalLen++; + if(realLen < intervalLen*T_density) break; + if(realLen >= intervalLen*density) useful_index = i; + } + + if(useful_index == (uint32_t)-1 || (useful_index - u_vecs->i) < miniLen) + { + u_vecs->i++; + return 0; + } + + ///don't need to set backward + end = (uint32_t)-1; + for (i = u_vecs->i; i < u_vecs->a.n; i++) + { + if(cId == (uint32_t)(u_vecs->a.a[i])) + { + ///u_vecs->a.a[i] = (uint32_t)-1; + u_vecs->a.a[i] = u_vecs->a.a[i]|(uint64_t)(0xffffffff); + } + } + (*r_cId) = cId; + u_vecs->i++; + return (useful_index - u_vecs->i); +} + + + + + +#define UNVISIT (uint32_t)(0x7fffffff) +#define RED 0 +#define BLACK 1 +#define ISO 2 +#define LABLE 3 +void bi_paration(asg_t *bi_g, uint64_t* array, uint32_t bi_graph_Len) +{ + + kvec_t(uint64_t) a; + kv_init(a); + a.a = array; + a.n = a.m = bi_g->n_seq; + kdq_t(uint32_t) *buf; + buf = kdq_init(uint32_t); + uint32_t i, len, v, w, k, nv, roundID = 0; + asg_arc_t *av; + for (i = 0; i < bi_g->n_seq; i++) + { + bi_g->seq[i].c = 0; + } + + re_partition: + + for (i = 0; i < bi_g->n_seq; i++) + { + /****************************may have bugs********************************/ + ///how many reads contained in this contig + len = (a.a[i]>>33); + /****************************may have bugs********************************/ + ///if the contig is too small, or the contig has already been visited + ///if(len < bi_graph_Len || bi_g->seq[i].len != UNVISIT) continue; + if(len < bi_graph_Len || bi_g->seq[i].c == 1) continue; + if(roundID == 0 && bi_g->seq[i].len == UNVISIT) continue; + + ///set the color of this node + bi_g->seq[i].len = RED; bi_g->seq[i].c = 1; + kdq_push(uint32_t, buf, i); + while (kdq_size(buf) != 0) + { + v = *(kdq_pop(uint32_t, buf)); bi_g->seq[v].c = 1; + if(bi_g->seq[v].len == ISO) continue; + nv = asg_arc_n(bi_g, v); + av = asg_arc_a(bi_g, v); + + + ///get all out-nodes of v + for(k = 0; k < nv; k++) + { + w = av[k].v; + /****************************may have bugs********************************/ + ///if(bi_g->seq[w].len == bi_g->seq[v].len) + len = (a.a[w]>>33); + ///only check large contig + if(len >= bi_graph_Len && bi_g->seq[w].len == bi_g->seq[v].len) + { /****************************may have bugs********************************/ + break; + } + } + ///means v is conflict + if(k != nv) + { + bi_g->seq[v].len = ISO; bi_g->seq[v].c = 1; + continue; + } + + + + ///if v is not conflict with others + for(k = 0; k < nv; k++) + { + w = av[k].v; + ///if the out-node has not been visited + if(bi_g->seq[w].len == UNVISIT) + { + bi_g->seq[w].len = 1 - bi_g->seq[v].len; + bi_g->seq[w].c = 1; + /****************************may have bugs********************************/ + len = (a.a[w]>>33); + /****************************may have bugs********************************/ + if(len < bi_graph_Len) continue; + kdq_push(uint32_t, buf, w); + } + ///here bi_g->seq[w].len might be ISO or another color + ///don't need to do anything here + } + } + } + + if(roundID == 0) + { + roundID = 1; + goto re_partition; + } + + + //secondary checking + // uint32_t a_color; + // kdq_size(buf) = 0; + // for (i = 0; i < bi_g->n_seq; i++) + // { + // /****************************may have bugs********************************/ + // len = (a.a[i]>>33); + // /****************************may have bugs********************************/ + // ///just check end contig + // if(bi_g->seq[i].len != UNVISIT || (a.a[i] & (uint64_t)(0x100000000)) == 0) continue; + + // v = i; + // nv = asg_arc_n(bi_g, v); + // av = asg_arc_a(bi_g, v); + // a_color = UNVISIT; + + // for(k = 0; k < nv; k++) + // { + // w = av[k].v; + // ///check all out-nodes that has already been colored + // if(bi_g->seq[w].len != UNVISIT) + // { + // ///if this is the first colored node + // if(a_color == UNVISIT) + // { + // a_color = bi_g->seq[w].len; + // }///if this is not + // else if(a_color != bi_g->seq[w].len) + // { + // a_color = ISO; + // bi_g->seq[v].len = ISO; + // break; + // } + // } + // } + + // if(a_color == ISO) continue; + // ///no colored out-node + // if(a_color == UNVISIT) + // { + // bi_g->seq[v].len = RED; + // } + // else + // { + // bi_g->seq[v].len = 1 - a_color; + // } + + + + + + // ///check if all reachable nodes are end-contig + // kdq_push(uint32_t, buf, i); + // while (kdq_size(buf) != 0) + // { + // v = *(kdq_pop(uint32_t, buf)); + // ///find a non-end contig + // if((a.a[v] & (uint64_t)(0x100000000)) == 0) + // { + // bi_g->seq[i].len = UNVISIT; + // kdq_size(buf) = 0; + // break; + // } + + // nv = asg_arc_n(bi_g, v); + // av = asg_arc_a(bi_g, v); + // for(k = 0; k < nv; k++) + // { + // w = av[k].v; + // ///if the out-node has not been visited + // if(bi_g->seq[w].len == UNVISIT) + // { + // bi_g->seq[v].len = LABLE; + // kdq_push(uint32_t, buf, w); + // } + // } + // } + + // for (v = 0; v < bi_g->n_seq; v++) + // { + // if(bi_g->seq[v].len == LABLE) bi_g->seq[v].len = UNVISIT; + // } + + // if(bi_g->seq[i].len == UNVISIT) + // { + // continue; + // } + + + + + + + // ///now all reachable nodes of i are end-contigs + // kdq_push(uint32_t, buf, i); + // while (kdq_size(buf) != 0) + // { + // ///each v here is the uncolored node in the first round + // v = *(kdq_pop(uint32_t, buf)); + // if(bi_g->seq[v].len == ISO) continue; + // nv = asg_arc_n(bi_g, v); + // av = asg_arc_a(bi_g, v); + + + // ///get all out-nodes of v + // for(k = 0; k < nv; k++) + // { + // w = av[k].v; + // if(bi_g->seq[w].len == bi_g->seq[v].len) + // { + // break; + // } + // } + // ///means v is conflict + // if(k != nv) + // { + // bi_g->seq[v].len = ISO; + // continue; + // } + + + + // ///if v is not conflict with others + // for(k = 0; k < nv; k++) + // { + // w = av[k].v; + // ///if the out-node has not been visited + // if(bi_g->seq[w].len == UNVISIT) + // { + // bi_g->seq[w].len = 1 - bi_g->seq[v].len; + // kdq_push(uint32_t, buf, w); + // } + // } + // } + // } + + kdq_destroy(uint32_t, buf); +} + + +void process_bi_graph(asg_t *bi_g) +{ + asg_cleanup(bi_g); + asg_arc_del_multi(bi_g); + bi_g->is_symm = 1; + uint32_t v, i, j; + for (v = 0; v < bi_g->n_seq; v++) + { + uint32_t nv = asg_arc_n(bi_g, v), nw, w; + asg_arc_t *av = asg_arc_a(bi_g, v), *aw; + for (i = 0; i < nv; ++i) + { + w = av[i].v; + if(w == v) + { + av[i].del = 1; + continue; + } + nw = asg_arc_n(bi_g, w); + aw = asg_arc_a(bi_g, w); + for (j = 0; j < nw; j++) + { + if(aw[j].v == v) break; + } + + if(j == nw) av[i].del = 1; + } + } + + asg_cleanup(bi_g); + + ///asg_symm(bi_g); +} + +inline void reset_visit_flag(uint8_t* visit, asg_t *read_g, R_to_U* ruIndex, uint32_t contigNum, +ma_hit_t_alloc* x) +{ + uint32_t k, rId, is_Unitig, Hap_cId; + + if(x->length*2 > contigNum) + { + memset(visit, 0, contigNum); + } + else + { + for (k = 0; k < x->length; k++) + { + rId = Get_tn(x->buffer[k]); + + if(read_g->seq[rId].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, rId, &rId, &is_Unitig); + if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; + } + + ///there are two cases: + ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id + ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 + get_R_to_U(ruIndex, rId, &Hap_cId, &is_Unitig); + if(is_Unitig == 0 || Hap_cId == (uint32_t)-1) continue; + ///here rId is the id of the read coming from the different haplotype + ///Hap_cId is the id of the corresponding contig (note here is the contig, instead of untig) + visit[Hap_cId] = 0; + } + } +} + +void debug_visit_flag(uint8_t* visit, uint32_t contigNum) +{ + uint32_t k; + for (k = 0; k < contigNum; k++) + { + if(visit[k] != 0) fprintf(stderr, "ERROR visit\n"); + } +} + + +uint32_t get_readSeq(ma_ug_t *ug, asg_t *read_g, kvec_t_u32_warp* x_vecs, uint64_t* cBeg, +buf_t* b_0, uint32_t cId) +{ + ma_utg_t* reads = NULL; + uint32_t beg, end, i, j, rId, xLen, uId, uOri; + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + uint64_t tmp; + + x_vecs->a.n = 0; + beg = (uint32_t)(cBeg[cId]); + b_0->b.n = 0; + get_unitig(ug->g, ug, beg, &end, &nodeLen, &baseLen, &max_stop_nodeLen, &max_stop_baseLen, 1, b_0); + xLen = cBeg[cId]>>33; + kv_resize(uint32_t, x_vecs->a, xLen); + + for (i = 0; i < b_0->b.n; i++) + { + uId = b_0->b.a[i]>>1; + uOri = b_0->b.a[i]&(uint32_t)1; + reads = &(ug->u.a[uId]); + for (j = 0; j < reads->n; j++) + { + if(uOri == 1) + { + rId = reads->a[reads->n - j - 1]>>33; + } + else + { + rId = reads->a[j]>>33; + } + + + tmp = rId<<1; + if(read_g->seq[rId].c == HAP_LABLE) + { + tmp = tmp | 1; + kv_push(uint32_t, x_vecs->a, tmp); + continue; + } + kv_push(uint32_t, x_vecs->a, tmp); + } + } + + + if(x_vecs->a.n != xLen) fprintf(stderr, "ERROR: different length\n"); + return xLen; +} + + +uint32_t inline retrieve_skip_overlaps(ma_hit_t_alloc* x, uint32_t target) +{ + if(x == NULL) return (uint32_t)-1; + + uint32_t i; + for (i = 0; i < x->length; i++) + { + if(Get_tn(x->buffer[i]) == target) + { + return i; + } + } + + return (uint32_t)-1; +} + +inline uint32_t check_duplicate(Hap_Align_warp* u_buffer, uint32_t x_pos, uint32_t y_pos) +{ + if(u_buffer->x.n == 0) return 0; + + int i = u_buffer->x.n; + for (i--; i >= 0; i--) + { + if(x_pos != (uint32_t)-1 && u_buffer->x.a[i].q_pos != x_pos) return 0; + if(y_pos != (uint32_t)-1 && u_buffer->x.a[i].t_pos == y_pos) + { + u_buffer->x.a[i].is_color++; + return 1; + } + } + + if(x_pos == (uint32_t)-1) fprintf(stderr, "ERROR: cannot found y\n"); + + return 0; +} + +///x_vecs->a.a[k]>>1 + +void get_hap_similarity(uint32_t* list, uint32_t Len, uint32_t target_uId, +ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, +double* Match, double* Total) +{ + #define CUTOFF_THRES 100 + uint32_t i, j, qn, tn, is_Unitig, uId, min_count = 0, max_count = 0, cutoff = 0;; + for (i = 0; i < Len; i++) + { + if(cutoff > CUTOFF_THRES) + { + max_count = 0; + min_count = Len; + } + qn = list[i]>>1; + if(reverse_sources[qn].length > 0) min_count++; + for (j = 0; j < reverse_sources[qn].length; j++) + { + tn = Get_tn(reverse_sources[qn].buffer[j]); + if(read_g->seq[tn].del == 1) + { + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + + + get_R_to_U(ruIndex, tn, &uId, &is_Unitig); + if(uId!=(uint32_t)-1 && is_Unitig == 1 && uId == target_uId) + { + max_count++; + break; + } + } + + //means no match + if(j == reverse_sources[qn].length) + { + cutoff++; + } + else + { + cutoff = 0; + } + } + + (*Match) = max_count; + (*Total) = min_count; +} +uint32_t calculate_hap_similarity(Hap_Align* p, uint32_t dir, uint32_t xCid, uint32_t yCid, +kvec_t_u32_warp* x_vecs, kvec_t_u32_warp* y_vecs, ma_hit_t_alloc* reverse_sources, +asg_t *read_g, R_to_U* ruIndex, float Hap_rate, uint32_t seedOcc) +{ + uint32_t max_count = 0, min_count = 0; + uint32_t xLen = x_vecs->a.n; + uint32_t yLen = y_vecs->a.n; + uint32_t xLeftBeg, xLeftLen, yLeftBeg, yLeftLen; + uint32_t xRightBeg, xRightLen, yRightBeg, yRightLen; + if(dir == 0) + { + xLeftBeg = 0; xLeftLen = p->q_pos; xRightBeg = p->q_pos; xRightLen = xLen - xRightBeg; + yLeftBeg = 0; yLeftLen = p->t_pos; yRightBeg = p->t_pos; yRightLen = yLen - yRightBeg; + } + else + { + xLeftBeg = 0; xLeftLen = p->q_pos; xRightBeg = p->q_pos; xRightLen = xLen - xRightBeg; + + yLeftBeg = p->t_pos + 1; yLeftLen = yLen - yLeftBeg; + yRightBeg = 0; yRightLen = p->t_pos + 1; + } + + + + max_count = seedOcc; + min_count = MIN(xLeftLen, yLeftLen) + MIN(xRightLen, yRightLen); + if(min_count == 0) return NON_PLOID; + if(max_count <= min_count*Hap_rate) return NON_PLOID; + + + + + + double xLeftMatch, xLeftTotal, yLeftMatch, yLeftTotal; + double xRightMatch, xRightTotal, yRightMatch, yRightTotal; + + get_hap_similarity(x_vecs->a.a+xLeftBeg, xLeftLen, yCid, reverse_sources, read_g, ruIndex, + &xLeftMatch, &xLeftTotal); + get_hap_similarity(y_vecs->a.a+yLeftBeg, yLeftLen, xCid, reverse_sources, read_g, ruIndex, + &yLeftMatch, &yLeftTotal); + + get_hap_similarity(x_vecs->a.a+xRightBeg, xRightLen, yCid, reverse_sources, read_g, ruIndex, + &xRightMatch, &xRightTotal); + get_hap_similarity(y_vecs->a.a+yRightBeg, yRightLen, xCid, reverse_sources, read_g, ruIndex, + &yRightMatch, &yRightTotal); + + max_count = min_count = 0; + if((xLeftMatch/xLeftTotal) >= (yLeftMatch/yLeftTotal)) + { + max_count += xLeftMatch; + min_count += xLeftTotal; + } + else + { + max_count += yLeftMatch; + min_count += yLeftTotal; + } + + if((xRightMatch/xRightTotal) >= (yRightMatch/yRightTotal)) + { + max_count += xRightMatch; + min_count += xRightTotal; + } + else + { + max_count += yRightMatch; + min_count += yRightTotal; + } + + if(min_count == 0) return NON_PLOID; + if(max_count > min_count*Hap_rate) return PLOID; + return NON_PLOID; +} + + +#define Hap_Align_Pos_key(a) ((((uint64_t)((a).q_pos))<<32)|((uint64_t)((a).t_pos))) +KRADIX_SORT_INIT(Hap_Align_Pos_sort, Hap_Align, Hap_Align_Pos_key, 8) + +#define Hap_Align_Weight_key(a) ((a).is_color) +KRADIX_SORT_INIT(Hap_Align_Weight_sort, Hap_Align, Hap_Align_Weight_key, member_size(Hap_Align, is_color)) + +inline uint32_t merge_hap_hits(Hap_Align_warp* u_buffer) +{ + if(u_buffer->x.n == 0) return 0; + + radix_sort_Hap_Align_Pos_sort(u_buffer->x.a, u_buffer->x.a + u_buffer->x.n); + uint32_t x_pos, x_pos_end, x_pos_beg; + int k, i, j, m; + + /** + for (i = 0; i < (int)u_buffer->x.n; i++) + { + fprintf(stderr, "****x: %u, y: %u, t_id: %u, is_color: %u\n", u_buffer->x.a[i].q_pos, u_buffer->x.a[i].t_pos, + u_buffer->x.a[i].t_id, u_buffer->x.a[i].is_color); + } + **/ + + i = u_buffer->x.n; i--; + x_pos = u_buffer->x.a[i].q_pos; + x_pos_end = i; + for (; i >= 0; i--) + { + k = i - 1; + if(k < 0) continue; + if(u_buffer->x.a[k].q_pos == u_buffer->x.a[i].q_pos && + u_buffer->x.a[k].t_pos+1 == u_buffer->x.a[i].t_pos) + { + u_buffer->x.a[k].is_color += u_buffer->x.a[i].is_color; + u_buffer->x.a[i].t_id = (uint32_t)-1; + } + + ///meet a new x_pos + if(u_buffer->x.a[k].q_pos != u_buffer->x.a[i].q_pos) + { + x_pos_beg = i; + for (m = x_pos_beg; m <= (int)x_pos_end; m++) + { + if(u_buffer->x.a[m].t_id == (uint32_t)-1) continue; + for (j = k; j >= 0; j--) + { + if(u_buffer->x.a[j].q_pos != x_pos - 1) break; + if(u_buffer->x.a[j].t_pos == u_buffer->x.a[m].t_pos || + u_buffer->x.a[j].t_pos == u_buffer->x.a[m].t_pos - 1) + { + u_buffer->x.a[j].is_color += u_buffer->x.a[m].is_color; + u_buffer->x.a[m].t_id = (uint32_t)-1; + break; + } + } + } + + x_pos = u_buffer->x.a[k].q_pos; + x_pos_end = k; + } + } + + + + + for (i = 0, m = 0; i < (int)u_buffer->x.n; i++) + { + if(u_buffer->x.a[i].t_id!=(uint32_t)-1) + { + u_buffer->x.a[m].is_color = u_buffer->x.a[i].is_color; + u_buffer->x.a[m].t_id = u_buffer->x.a[i].t_id; + u_buffer->x.a[m].q_pos = u_buffer->x.a[i].q_pos; + u_buffer->x.a[m].t_pos = u_buffer->x.a[i].t_pos; + m++; + } + } + + u_buffer->x.n = m; + + /** + for (i = 0; i < (int)u_buffer->x.n; i++) + { + fprintf(stderr, "####x: %u, y: %u, t_id: %u, is_color: %u\n", u_buffer->x.a[i].q_pos, u_buffer->x.a[i].t_pos, + u_buffer->x.a[i].t_id, u_buffer->x.a[i].is_color); + } + **/ + radix_sort_Hap_Align_Weight_sort(u_buffer->x.a, u_buffer->x.a + u_buffer->x.n); + return 0; +} + +void get_hap_alignment(ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* reverse_sources, +buf_t* b_0, R_to_U* ruIndex, uint32_t* position_index, uint64_t* vote_counting, uint8_t* visit, +kvec_t_u64_warp* u_vecs, Hap_Align_warp* u_buffer, kvec_t_u32_warp* x_vecs, kvec_t_u32_warp* y_vecs, +uint32_t cId, uint32_t contigNum, uint64_t* cBeg, float Hap_rate, asg_t *bi_g, uint32_t is_bi_edge) +{ + ma_utg_t* reads = NULL; + uint32_t beg, end, i, j, k, rId, Hap_cId, y_cId, y_offset, qn, self_offset, uId, uOri, is_Unitig, xLen, seedOcc; + uint64_t tmp; + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + memset(vote_counting, 0, sizeof(uint64_t)*contigNum); + memset(visit, 0, contigNum); + u_vecs->a.n = x_vecs->a.n = y_vecs->a.n = 0; + + beg = (uint32_t)(cBeg[cId]); + b_0->b.n = 0; + get_unitig(ug->g, ug, beg, &end, &nodeLen, &baseLen, &max_stop_nodeLen, &max_stop_baseLen, 1, b_0); + xLen = cBeg[cId]>>33; + kv_resize(uint32_t, x_vecs->a, xLen); + + for (i = 0, self_offset = 0; i < b_0->b.n; i++) + { + uId = b_0->b.a[i]>>1; + uOri = b_0->b.a[i]&(uint32_t)1; + reads = &(ug->u.a[uId]); + for (j = 0; j < reads->n; j++, self_offset++) + { + if(uOri == 1) + { + rId = reads->a[reads->n - j - 1]>>33; + } + else + { + rId = reads->a[j]>>33; + } + + + tmp = rId<<1; + if(read_g->seq[rId].c == HAP_LABLE) + { + tmp = tmp | 1; + kv_push(uint32_t, x_vecs->a, tmp); + continue; + } + kv_push(uint32_t, x_vecs->a, tmp); + + + /**********************for debug*************************/ + ///debug_visit_flag(visit, contigNum); + /**********************for debug*************************/ + + qn = rId; + for (k = 0; k < reverse_sources[qn].length; k++) + { + rId = Get_tn(reverse_sources[qn].buffer[k]); + + if(read_g->seq[rId].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, rId, &rId, &is_Unitig); + if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; + } + + ///there are two cases: + ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id + ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 + get_R_to_U(ruIndex, rId, &Hap_cId, &is_Unitig); + if(is_Unitig == 0 || Hap_cId == (uint32_t)-1) continue; + ///here rId is the id of the read coming from the different haplotype + ///Hap_cId is the id of the corresponding contig (note here is the contig, instead of untig) + if(visit[Hap_cId]!=0) continue; + visit[Hap_cId] = 1; + if(vote_counting[Hap_cId] < UINT64_MAX) vote_counting[Hap_cId]++; + } + + reset_visit_flag(visit, read_g, ruIndex, contigNum, &(reverse_sources[qn])); + } + } + + + u_vecs->a.n = 0; + for (i = 0; i < contigNum; i++) + { + if(i == cId) continue; + if(vote_counting[i] == 0) continue; + tmp = vote_counting[i]; tmp = tmp << 32; tmp = tmp | (uint64_t)i; + kv_push(uint64_t, u_vecs->a, tmp); + } + + if(u_vecs->a.n == 0) return; + + sort_kvec_t_u64_warp(u_vecs, 1); + + + ma_hit_t_alloc *x = NULL, *pre_x = NULL; + Hap_Align* p = NULL; + asg_arc_t *e = NULL; + ///scan from the weightest candidate + for (i = 0; i < u_vecs->a.n; i++) + { + Hap_cId = (uint32_t)u_vecs->a.a[i]; + get_readSeq(ug, read_g, y_vecs, cBeg, b_0, Hap_cId); + y_cId = Hap_cId; + seedOcc = u_vecs->a.a[i]>>32; + + if(debug_purge_dup) + { + if(cId == 53) + { + fprintf(stderr, "cId: %u, y_cId: %u, seedOcc: %u\n", cId, y_cId, seedOcc); + } + } + + u_buffer->x.n = 0; + for (k = 0; k < x_vecs->a.n; k++) + { + x = pre_x = NULL; + rId = x_vecs->a.a[k]>>1; + if(read_g->seq[rId].c == HAP_LABLE) continue; + x = &(reverse_sources[rId]); + + if(k >= 1) + { + rId = x_vecs->a.a[k-1]>>1; + if(read_g->seq[rId].c != HAP_LABLE) + { + pre_x = &(reverse_sources[rId]); + } + } + + + + + for (j = 0; j < x->length; j++) + { + rId = Get_tn(x->buffer[j]); + if(read_g->seq[rId].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, rId, &rId, &is_Unitig); + if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; + } + + ///there are two cases: + ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id + ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 + get_R_to_U(ruIndex, rId, &Hap_cId, &is_Unitig); + if(is_Unitig == 0 || Hap_cId == (uint32_t)-1) continue; + if(Hap_cId != y_cId) continue; + + y_offset = position_index[rId]; + ///if(retrieve_skip_overlaps(pre_x, rId) != (uint32_t)-1) + if(retrieve_skip_overlaps(pre_x, Get_tn(x->buffer[j])) != (uint32_t)-1) + { + check_duplicate(u_buffer, (uint32_t)-1, y_offset); + continue; + } + if(check_duplicate(u_buffer, k, y_offset)) continue; + + kv_pushp(Hap_Align, u_buffer->x, &p); + p->q_pos = k; + p->t_pos = y_offset; + p->t_id = y_cId; + p->is_color = 1; + } + } + + merge_hap_hits(u_buffer); + if(u_buffer->x.n == 0) continue; + + ///for (k = 0; k < u_buffer->x.n; k++) + for (k = u_buffer->x.n-1; k >= 0; k--) + { + if(calculate_hap_similarity(&(u_buffer->x.a[k]), 0, cId, y_cId, x_vecs, y_vecs, + reverse_sources, read_g, ruIndex, Hap_rate, seedOcc)==PLOID) + { + break; + } + else if(calculate_hap_similarity(&(u_buffer->x.a[k]), 1, cId, y_cId, x_vecs, y_vecs, + reverse_sources, read_g, ruIndex, Hap_rate, seedOcc)==PLOID) + { + break; + } + if(k == 0) + { + k = (uint32_t)-1; + break; + } + } + + ///if(k < u_buffer->x.n) + if(k != (uint32_t)-1) + { + e = asg_arc_pushp(bi_g); + e->del = 0; + e->ol = 0; + e->ul = cId; e->ul = e->ul << 32; e->ul = e->ul | (uint64_t)(0); + e->v = y_cId; + + if(is_bi_edge) + { + e = asg_arc_pushp(bi_g); + e->del = 0; + e->ol = 0; + e->ul = y_cId; e->ul = e->ul << 32; e->ul = e->ul | (uint64_t)(0); + e->v = cId; + } + } + } +} + +void print_gfa(asg_t *g) +{ + uint32_t v, i, n_vtx = g->n_seq * 2; + for (v = 0; v < n_vtx; v++) + { + if(g->seq[v>>1].del) + { + fprintf(stderr, "(D) v>>1: %u, v&1: %u, %.*s\n", v>>1, v&1, + (int)Get_NAME_LENGTH((R_INF), v>>1), Get_NAME((R_INF), v>>1)); + continue; + } + + fprintf(stderr, "(E) v>>1: %u, v&1: %u, %.*s\n", v>>1, v&1, + (int)Get_NAME_LENGTH((R_INF), v>>1), Get_NAME((R_INF), v>>1)); + + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + fprintf(stderr, "av[i].v: %u, av[i].ul: %u\n", + av[i].v, (uint32_t)(av[i].ul>>32)); + } + + } + +} + + + +void print_purge_gfa(asg_t *g, uint64_t* cCount) +{ + uint32_t v, i, n_vtx = g->n_seq, beg, end; + for (v = 0; v < n_vtx; v++) + { + if(g->seq[v>>1].del) + { + fprintf(stderr, "(D) v: %u, Len: %u, start>>1: %u, flag: %u\n", v, (uint32_t)(cCount[v]>>33), + ((uint32_t)cCount[v])>>1, g->seq[v].len); + continue; + } + + fprintf(stderr, "(E) v: %u, Len: %u, start>>1: %u, flag: %u\n", v, (uint32_t)(cCount[v]>>33), + ((uint32_t)cCount[v])>>1, g->seq[v].len); + + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + beg = av[i].ul>>32; + end = av[i].v; + + fprintf(stderr, "****beg: %u (Len: %u) ---> end: %u (Len: %u)\n", + beg, (uint32_t)(cCount[beg]>>33), + end, (uint32_t)(cCount[end]>>33)); + + } + + } + +} + +void calculate_peak(uint64_t* counts, long long len, kvec_t_u32_warp* a, +long long TotalMean, long long HapMean, long long* peak0, long long* peak1) +{ + if(len == 0) return; + long long i, j, total_coverage = 0, current_coverage, step, pre, after, is_found = 0; + for (i = 0; i < len; i++) + { + total_coverage = total_coverage + ((counts[i]>>32) * ((uint32_t)counts[i])); + } + current_coverage = total_coverage; + for (i = len - 1; i >= 0; i--) + { + current_coverage = current_coverage - ((counts[i]>>32) * ((uint32_t)counts[i])); + if(current_coverage <= total_coverage*0.9) break; + } + i++; + step = i*0.1; + if(step < 2) step = 2; + ///fprintf(stderr, "step: %lld\n", step); + + + a->a.n = 0; + ///for (i = 0; i < len; i++) + for (i = 1; i < len; i++) + { + pre = i - step/2; + after = i + step/2; + if(pre < 0) pre = 0; + if(after >= len) after = len - 1; + is_found = 0; + for (j = pre; j < after; j++) + { + if(j == i) continue; + if(((uint32_t)counts[i]) <= ((uint32_t)counts[j])) + { + is_found = 1; + break; + } + } + + if(is_found == 0) + { + kv_push(uint32_t, a->a, i); + } + } + + + + uint32_t peak_0_i, peak_1_i; + peak_0_i = peak_1_i = 0; + + for (i = 0; i < (long long)a->a.n; i++) + { + if(((uint32_t)counts[a->a.a[peak_0_i]]) < ((uint32_t)counts[a->a.a[i]])) + { + peak_0_i = i; + } + } + + peak_1_i = (uint32_t)-1; + for (i = 0; i < (long long)a->a.n; i++) + { + if(peak_0_i == i) continue; + if(peak_1_i == (uint32_t)-1) + { + peak_1_i = i; + continue; + } + if(((uint32_t)counts[a->a.a[peak_1_i]]) < ((uint32_t)counts[a->a.a[i]])) + { + peak_1_i = i; + } + } + + if(peak_0_i == peak_1_i) peak_1_i = (uint32_t)-1; + + + // for (i = 0; i < (long long)a->a.n; i++) + // { + // fprintf(stderr, "i:%lld, freq: %u, num: %u\n", i, + // (uint32_t)(counts[a->a.a[i]]>>32), (uint32_t)counts[a->a.a[i]]); + // } + // fprintf(stderr, "peak_0_i: %u, peak_1_i: %u\n", peak_0_i, peak_1_i); + + (*peak0) = (*peak1) = -1; + /** + * There are three cases: + * 1. very low het rate: don't need purge_dup + * 2. very high het rate: TotalMean should be equal to peak_0 + * 3. not such high het rate: two peaks, HapMean should be useful + * **/ + + if(peak_1_i == (uint32_t)-1) + { + (*peak0) = (uint32_t)(counts[a->a.a[peak_0_i]]>>32); + return; + } + + (*peak0) = (uint32_t)(counts[a->a.a[peak_0_i]]>>32); + (*peak1) = (uint32_t)(counts[a->a.a[peak_1_i]]>>32); + + + if(TotalMean >= (long long)((uint32_t)(counts[a->a.a[peak_0_i]]>>32)) && + TotalMean >= (long long)((uint32_t)(counts[a->a.a[peak_1_i]]>>32))) + { + (*peak1) = -1; + return; + } + + long long max_cov = MAX((*peak0), TotalMean); + long long min_cov = MIN((*peak0), TotalMean); + if(min_cov >= max_cov*0.8) + { + max_cov = MAX((*peak1), TotalMean); + min_cov = MIN((*peak1), TotalMean); + if(min_cov < max_cov*0.6) + { + (*peak1) = -1; + return; + } + } + + + long long hap_cov = ((uint32_t)(counts[a->a.a[MIN(peak_0_i, peak_1_i)]]>>32)); + max_cov = MAX(hap_cov, HapMean); + min_cov = MIN(hap_cov, HapMean); + ///fprintf(stderr, "hap_cov: %lld, max_cov: %lld, min_cov: %lld\n", hap_cov, max_cov, min_cov); + if(min_cov < max_cov*0.70) + { + (*peak1) = -1; + return; + } + + min_cov = MIN((*peak0), (*peak1)); + max_cov = MAX((*peak0), (*peak1)); + (*peak0) = min_cov; + (*peak1) = max_cov; +} + +void get_purge_coverage(asg_t *read_g, ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, +uint32_t* junk_cov, uint32_t* hap_cov, uint32_t* dip_cov) +{ + (*junk_cov) = (*hap_cov) = 0; (*dip_cov) = (uint32_t)-1; + uint32_t i, j, num, m; + long long R_bases = 0, C_bases = 0, T_R_bases = 0, T_C_bases = 0, total_coverage = 0, T_mean, Hap_mean; + ma_hit_t *h = NULL; + uint64_t* counts = (uint64_t*)calloc(read_g->n_seq, sizeof(uint64_t)); + kvec_t_u32_warp a; + kv_init(a.a); + + for (i = 0; i < read_g->n_seq; ++i) + { + R_bases = C_bases = 0; + R_bases += coverage_cut[i].e - coverage_cut[i].s; + for (j = 0; j < (uint64_t)(sources[i].length); j++) + { + h = &(sources[i].buffer[j]); + C_bases += Get_qe((*h)) - Get_qs((*h)); + } + if(R_bases == 0) continue; + + counts[i] = C_bases/R_bases; + T_R_bases += R_bases; + T_C_bases += C_bases; + total_coverage += counts[i]; + } + + T_mean = 0; + if(T_R_bases > 0) T_mean = T_C_bases/T_R_bases; + + radix_sort_arch64(counts, counts + read_g->n_seq); + + + uint64_t tmp; + i = m = 0; + while(i < read_g->n_seq) + { + num = 0; + for (j = i; j < read_g->n_seq; j++) + { + if(counts[i] != counts[j]) break; + num++; + } + + tmp = counts[i]; tmp = tmp << 32; tmp = tmp | (uint64_t)num; + counts[m] = tmp; + m++; + i = j; + } + + + R_bases = C_bases = 0; + for (i = 0; i < read_g->n_seq; ++i) + { + if(read_g->seq[i].c != HAP_LABLE) continue; + R_bases += coverage_cut[i].e - coverage_cut[i].s; + for (j = 0; j < (uint64_t)(sources[i].length); j++) + { + h = &(sources[i].buffer[j]); + C_bases += Get_qe((*h)) - Get_qs((*h)); + } + } + Hap_mean = 0; + if(R_bases > 0) Hap_mean = C_bases/R_bases; + + + + long long peak0, peak1; + calculate_peak(counts, m, &a, T_mean, Hap_mean, &peak0, &peak1); + + + // fprintf(stderr, "T_mean: %lld, Hap_mean: %lld, peak0: %lld, peak1: %lld\n", + // T_mean, Hap_mean, peak0, peak1); + + + (*junk_cov) = MIN(JUNK_COV, (peak0/2)); + if(peak1 == -1) + { + if(peak0 <= T_mean) + { + (*hap_cov) = peak0*1.5; + (*dip_cov) = peak0*4.5; + } + else + { + (*hap_cov) = peak0*1.2; + (*dip_cov) = peak0*3.6; + } + } + else + { + num = MAX(T_mean, (peak0+peak1)/2); + (*hap_cov) = num; + (*dip_cov) = num*3; + } + + free(counts); + kv_destroy(a.a); +} + + +uint32_t get_single_coverage(ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, uint32_t rId) +{ + long long R_bases = 0, C_bases = 0; + uint32_t j; + ma_hit_t *h = NULL; + + R_bases += coverage_cut[rId].e - coverage_cut[rId].s; + for (j = 0; j < (uint64_t)(sources[rId].length); j++) + { + h = &(sources[rId].buffer[j]); + C_bases += Get_qe((*h)) - Get_qs((*h)); + } + + if(R_bases == 0) return 0; + return (C_bases/R_bases); +} + +void print_node(asg_t* g, ma_ug_t *ug) +{ + int input_iv; + uint32_t iv, v; + asg_arc_t *av, *aw; + uint32_t nv, nw, i, k, w; + while (1) + { + fprintf(stderr, "\n\ninput v: "); + if(scanf("%d", &input_iv) == 0) break; + if(input_iv == -1) break; + iv = input_iv; + iv = iv << 1; + + v = iv; + av = asg_arc_a(g, v); + nv = asg_arc_n(g, v); + fprintf(stderr, "0**************v>>1: %u, v&1: %u, c: %u, del: %u, len: %u**************\n", + v>>1, v&1, (uint32_t)g->seq[v>>1].c, (uint32_t)g->seq[v>>1].del, g->seq[v>>1].len); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + w = av[i].v; + fprintf(stderr, "(%u) w>>1: %u, w&1: %u, ol: %u, eLen: %u\n", + i, w>>1, w&1, av[i].ol, (uint32_t)av[i].ul); + + + aw = asg_arc_a(g, w^1); + nw = asg_arc_n(g, w^1); + for (k = 0; k < nw; k++) + { + if(aw[k].del) continue; + if(aw[k].v == (v^1)) break; + } + + fprintf(stderr, "self>>1: %u, self&1: %u, out>>1: %u, out^1: %u, is_sym: %u\n", + (uint32_t)(av[i].ul>>33), (uint32_t)((av[i].ul>>32)&1), av[i].v>>1, av[i].v&1, + (uint32_t)(k != nw)); + + } + + + + + + + v = iv^1; + av = asg_arc_a(g, v); + nv = asg_arc_n(g, v); + fprintf(stderr, "1**************v>>1: %u, v&1: %u, c: %u, del: %u, len: %u**************\n", + v>>1, v&1, (uint32_t)g->seq[v>>1].c, (uint32_t)g->seq[v>>1].del, (uint32_t)g->seq[v>>1].len); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + w = av[i].v; + fprintf(stderr, "w>>1: %u, w&1: %u, ol: %u, eLen: %u\n", + w>>1, w&1, (uint32_t)av[i].ol, (uint32_t)av[i].ul); + + + aw = asg_arc_a(g, w^1); + nw = asg_arc_n(g, w^1); + for (k = 0; k < nw; k++) + { + if(aw[k].del) continue; + if(aw[k].v == (v^1)) break; + } + + fprintf(stderr, "self>>1: %u, self&1: %u, out>>1: %u, out^1: %u, is_sym: %u\n", + (uint32_t)(av[i].ul>>33), (uint32_t)((av[i].ul>>32)&1), av[i].v>>1, av[i].v&1, + (uint32_t)(k != nw)); + + } + + if(ug != NULL) + { + ma_utg_t *ma_v = &(ug->u.a[v>>1]); + fprintf(stderr, "\n###\nma_v->n: %u, ma_v->len: %u\n", ma_v->n, ma_v->len); + fprintf(stderr, "start>>1: %u, start&1: %u, end>>1: %u, end&1: %u\n", + ma_v->start>>1, ma_v->start&1, ma_v->end>>1, ma_v->end&1); + for (i = 0; i < ma_v->n; i++) + { + v = ma_v->a[i]>>32; + fprintf(stderr, "i: %u, v>>1: %u, v&1: %u, len: %u\n", + i, v>>1, v&1, (uint32_t)ma_v->a[i]); + } + + } + } +} + +/*************************************for tangle resolve*************************************/ + +void recover_edges(asg_t* nsg, kvec_t_u64_warp* edges, uint64_t* nodes, uint64_t n, +uint32_t beg, uint32_t end, uint32_t beg_c, uint32_t end_c, uint32_t is_recover_edges) +{ + uint32_t i, v; + asg_arc_t *a = NULL; + for (i = 0; i < n; i++) + { + v = (uint32_t)nodes[i]; + nsg->seq[v].del = 0; + nsg->seq[v].c = (nodes[i]>>32); + } + nsg->seq[beg>>1].c = beg_c; nsg->seq[beg>>1].del = 0; + nsg->seq[end>>1].c = end_c; nsg->seq[end>>1].del = 0; + + if(is_recover_edges) + { + for (i = 0; i < edges->a.n; i++) + { + a = &(nsg->arc[(uint32_t)edges->a.a[i]]); + a->del = 0; + } + } +} + +///note: nodes does not have directions +void save_all_edges(kvec_t_u64_warp* u_vecs, asg_t* nsg, uint64_t* nodes, uint64_t n, +uint32_t beg, uint32_t end, uint32_t* beg_c, uint32_t* end_c) +{ + uint32_t i, v, nv, k; + uint64_t tmp; + asg_arc_t *av = NULL; + u_vecs->a.n = 0; + + (*beg_c) = nsg->seq[beg>>1].c; + (*end_c) = nsg->seq[end>>1].c; + for (i = 0; i < n; i++) + { + v = (uint32_t)nodes[i]; + tmp = nsg->seq[v].c; tmp = tmp<<32; tmp = (tmp)|((uint64_t)v); + nodes[i] = tmp; + + if(nsg->seq[v].del) continue; + if(nsg->seq[v].c == ALTER_LABLE) continue; + + v = v<<1; + av = asg_arc_a(nsg, v); + nv = asg_arc_n(nsg, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + kv_push(uint64_t, u_vecs->a, (uint64_t)((uint64_t)av[k].ol << 32 | (av - nsg->arc + k))); + } + + + v = v^1; + av = asg_arc_a(nsg, v); + nv = asg_arc_n(nsg, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + kv_push(uint64_t, u_vecs->a, (uint64_t)((uint64_t)av[k].ol << 32 | (av - nsg->arc + k))); + } + } + + v = beg; + if((!nsg->seq[v>>1].del)&&(nsg->seq[v>>1].c!=ALTER_LABLE)) + { + av = asg_arc_a(nsg, v); + nv = asg_arc_n(nsg, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + for (i = 0; i < n; i++) + { + if((av[k].v>>1)==((uint32_t)nodes[i])) break; + } + if(i==n) continue; + kv_push(uint64_t, u_vecs->a, (uint64_t)((uint64_t)av[k].ol << 32 | (av - nsg->arc + k))); + } + } + + + + + v = end^1; + if((!nsg->seq[v>>1].del)&&(nsg->seq[v>>1].c!=ALTER_LABLE)) + { + av = asg_arc_a(nsg, v); + nv = asg_arc_n(nsg, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + for (i = 0; i < n; i++) + { + if((av[k].v>>1)==((uint32_t)nodes[i])) break; + } + if(i==n) continue; + kv_push(uint64_t, u_vecs->a, (uint64_t)((uint64_t)av[k].ol << 32 | (av - nsg->arc + k))); + } + } +} + +///beg and end have directions, while nodes does not have +int drop_tips_at_tangle(asg_t* nsg, uint64_t* nodes, uint64_t n, uint32_t beg, uint32_t end, +buf_t* bb) +{ + uint32_t i, v, k, m, convex, return_flag, next_tips = 1, reduce = 0; + long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; + + while(next_tips > 0) + { + next_tips = 0; + + for (i = 0; i < n; i++) + { + v = (uint32_t)nodes[i]; + if(nsg->seq[v].del) continue; + if(nsg->seq[v].c == ALTER_LABLE) continue; + v = v<<1; + + for (k = 0; k < 2; k++) + { + v = v|k; + if(get_real_length(nsg, v^1, NULL) != 0) continue; + + bb->b.n = 0; + return_flag = get_unitig(nsg, NULL, v, &convex, &ll, &tmp, &max_stop_nodeLen, + &max_stop_baseLen, 1, bb); + if(return_flag == LOOP) continue; + if(return_flag == MUL_OUTPUT) next_tips++; + + for(m = 0; m < bb->b.n; m++) + { + if(((bb->b.a[m]>>1)==(beg>>1)) || ((bb->b.a[m]>>1)==(end>>1))) break; + } + ///means this unitig consists of beg or end + if(m != bb->b.n) continue; + + for(m = 0; m < bb->b.n; m++) + { + nsg->seq[(bb->b.a[m]>>1)].c = ALTER_LABLE; + } + + for(m = 0; m < bb->b.n; m++) + { + asg_seq_drop(nsg, (bb->b.a[m]>>1)); + } + + reduce++; + } + } + } + + return reduce; +} + +///max_dist is ok, since tangle shouldn't be too large +int pop_bubble_at_tangle(ma_ug_t *ug, uint64_t max_dist, uint64_t* nodes, uint64_t n, uint32_t beg, uint32_t end, +uint32_t positive_flag, uint32_t negative_flag) +{ + asg_t *g = ug->g; + uint32_t i, v, k, n_vtx = g->n_seq*2; + uint64_t n_pop = 0; + buf_t b; + if (!g->is_symm) asg_symm(g); + memset(&b, 0, sizeof(buf_t)); + b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + + v = beg; + if((!g->seq[v>>1].del)&&(g->seq[v>>1].c!=ALTER_LABLE)&&get_real_length(g, v, NULL)>=2) + { + n_pop += asg_bub_pop1_primary_trio(ug->g, ug, v, max_dist, &b, positive_flag, negative_flag, 1, NULL, NULL, NULL, 0, 1, NULL); + } + + v = end^1; + if((!g->seq[v>>1].del)&&(g->seq[v>>1].c!=ALTER_LABLE)&&get_real_length(g, v, NULL)>=2) + { + n_pop += asg_bub_pop1_primary_trio(ug->g, ug, v, max_dist, &b, positive_flag, negative_flag, 1, NULL, NULL, NULL, 0, 1, NULL); + } + + + for (i = 0; i < n; i++) + { + v = (uint32_t)nodes[i]; + if(g->seq[v].del) continue; + if(g->seq[v].c == ALTER_LABLE) continue; + v = v<<1; + + for (k = 0; k < 2; k++) + { + v = v|k; + if(get_real_length(g, v, NULL)<=1) continue; + n_pop += asg_bub_pop1_primary_trio(ug->g, ug, v, max_dist, &b, positive_flag, negative_flag, 1, NULL, NULL, NULL, 0, 1, NULL); + } + } + + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + ///if (n_pop) asg_cleanup(g); + return n_pop; +} + + +int find_spec_node(asg_t *nsg, uint32_t vBeg, uint32_t vDest, uint32_t* forbidden_nodes, +uint32_t forbidden_nodes_n, long long max_nodes, buf_t* bb, uint8_t* visit, ma_ug_t *ug) +{ + uint32_t nv, un_visit; + asg_arc_t *av; + + memset(visit, 0, nsg->n_seq); + kdq_t(uint32_t) *buf; + buf = kdq_init(uint32_t); + + uint32_t vEnd, i, k, v, is_found = 0, return_flag; + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen, totalNodes = 0; + + bb->b.n = 0; + if(get_unitig(nsg, ug, vBeg, &vEnd, &nodeLen, &baseLen, + &max_stop_nodeLen, &max_stop_baseLen, 1, bb)==LOOP) + { + kdq_destroy(uint32_t, buf); + + for (i = 0; i < bb->b.n; i++) + { + if(bb->b.a[i] == vDest) break; + } + if(i != bb->b.n) return 1; + + return 0; + } + + + for (i = 0; i < bb->b.n; i++) + { + Set_vis(visit, bb->b.a[i], 0); + ///Set_vis(visit, bb->b.a[i]^1, 0); + } + + if(forbidden_nodes != NULL && forbidden_nodes_n != 0) + { + for (i = 0; i < forbidden_nodes_n; i++) + { + Set_vis(visit, forbidden_nodes[i], 0); + } + } + + + + v = vBeg; + kdq_push(uint32_t, buf, v); + + while (kdq_size(buf) != 0) + { + + v = *(kdq_pop(uint32_t, buf)); + + bb->b.n = 0; + return_flag = get_unitig(nsg, ug, v, &vEnd, &nodeLen, &baseLen, + &max_stop_nodeLen, &max_stop_baseLen, 1, bb); + + for (i = 0; i < bb->b.n; i++) + { + if(bb->b.a[i] == vDest) break; + } + + if(i != bb->b.n) + { + is_found = 1; + break; + } + + if(return_flag == LOOP) break; + + totalNodes += nodeLen; + if(totalNodes > max_nodes) break; + + v = vEnd; + nv = asg_arc_n(nsg, v); + av = asg_arc_a(nsg, v); + for(k = 0; k < nv; k++) + { + if(av[k].del) continue; + + if(Get_vis(visit,av[k].v, 0)!=0) continue; + + un_visit = 0; + bb->b.n = 0; + get_unitig(nsg, ug, av[k].v, &vEnd, &nodeLen, &baseLen, + &max_stop_nodeLen, &max_stop_baseLen, 1, bb); + for (i = 0; i < bb->b.n; i++) + { + if(Get_vis(visit, bb->b.a[i], 0) != 0) break; + } + if(i == bb->b.n) un_visit = 1; + + if(un_visit) + { + kdq_push(uint32_t, buf, av[k].v); + for (i = 0; i < bb->b.n; i++) + { + Set_vis(visit, bb->b.a[i], 0); + } + } + + } + } + + kdq_destroy(uint32_t, buf); + return is_found; +} + +int drop_useless_edges(ma_ug_t *ug, buf_t* bb, uint8_t* visit, uint32_t beg, uint32_t end, +uint64_t* nodes, uint64_t nodes_n, uint32_t NodesThres) +{ + asg_t *nsg = ug->g; + asg_arc_t *av = NULL; + uint32_t v, w, nv, i, k, dest, n_reduce = 0; + uint32_t reach_beg[2]; + uint32_t reach_end[2]; + reach_beg[0] = reach_beg[1] = reach_end[0] = reach_end[1] = 0; + + v = beg; dest = end; + if(get_real_length(nsg, v, NULL) > 1) + { + w = v^1; + av = asg_arc_a(nsg, v); + nv = asg_arc_n(nsg, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(find_spec_node(nsg, av[k].v, dest, &w, 1, NodesThres, bb, visit, ug) == 0) + { + // if(get_real_length(nsg, v, NULL)<=1) + // { + // fprintf(stderr, "false edge: beg: %u, end: %u\n", (uint32_t)(av[k].ul>>33), av[k].v>>1); + // } + + av[k].del = 1; + asg_arc_del(nsg, av[k].v^1, ((uint32_t)(av[k].ul>>32))^1, 1); + n_reduce++; + } + } + } + + + + v = end^1; dest = beg^1; + if(get_real_length(nsg, v, NULL) > 1) + { + w = v^1; + av = asg_arc_a(nsg, v); + nv = asg_arc_n(nsg, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(find_spec_node(nsg, av[k].v, dest, &w, 1, NodesThres, bb, visit, ug) == 0) + { + // if(get_real_length(nsg, v, NULL)<=1) + // { + // fprintf(stderr, "false edge: beg: %u, end: %u\n", (uint32_t)(av[k].ul>>33), av[k].v>>1); + // } + + av[k].del = 1; + asg_arc_del(nsg, av[k].v^1, ((uint32_t)(av[k].ul>>32))^1, 1); + n_reduce++; + } + } + } + + uint32_t drop_dest, forbid_dest, drop_node; + for (i = 0; i < nodes_n; i++) + { + v = (uint32_t)nodes[i]; + if(nsg->seq[v].del) continue; + if(nsg->seq[v].c == ALTER_LABLE) continue; + v = v<<1; + + for (k = 0; k < 2; k++) + { + v = v|k; + + w = end; + reach_beg[k] = find_spec_node(nsg, v, beg^1, &w, 1, NodesThres, bb, visit, ug); + w = beg^1; + reach_end[k] = find_spec_node(nsg, v, end, &w, 1, NodesThres, bb, visit, ug); + } + + if((reach_beg[0]+reach_end[0])==0 || (reach_beg[1]+reach_end[1])==0) continue; + + k = drop_dest = forbid_dest = (uint32_t)-1; + if((reach_beg[0]+reach_end[0])==1 && (reach_beg[1]+reach_end[1])>1) k = 0; + if((reach_beg[0]+reach_end[0])>1 && (reach_beg[1]+reach_end[1])==1) k = 1; + if(k == (uint32_t)-1) continue; + + drop_node = (uint32_t)nodes[i]; + drop_node = drop_node <<1; + drop_node = drop_node | (uint32_t)(1-k); + if(reach_beg[k]==1) + { + //drop_dest = beg^1; forbid_dest = end; + drop_dest = end; forbid_dest = beg^1; + } + + if(reach_end[k]==1) + { + //drop_dest = end; forbid_dest = beg^1; + drop_dest = beg^1; forbid_dest = end; + } + + if(drop_dest == (uint32_t)-1 || forbid_dest == (uint32_t)-1) continue; + + av = asg_arc_a(nsg, drop_node); + nv = asg_arc_n(nsg, drop_node); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(find_spec_node(nsg, av[k].v, drop_dest, &forbid_dest, 1, NodesThres, bb, visit, ug) == 0) + { + av[k].del = 1; + asg_arc_del(nsg, av[k].v^1, ((uint32_t)(av[k].ul>>32))^1, 1); + + // fprintf(stderr, "false inner edge: beg: %u, end: %u\n", + // (uint32_t)(av[k].ul>>33), av[k].v>>1); + + n_reduce++; + } + } + + } + + return n_reduce; +} + +int detec_circles(asg_t *nsg, uint32_t vSrc, uint32_t vDest, +uint8_t* visit, ma_ug_t *ug, uint64_t* nodes, uint64_t nodes_n) +{ + uint32_t nv, nw, knw, i, k, v, w; + asg_arc_t *av, *aw; + + memset(visit, 0, nsg->n_seq); + kdq_t(uint32_t) *buf; + buf = kdq_init(uint32_t); + + vDest = vDest^1; + + Set_vis(visit, vSrc, 1); + Set_vis(visit, vDest, 1); + kdq_push(uint32_t, buf, vSrc); + kdq_push(uint32_t, buf, vDest); + + for (i = 0; i < nodes_n; i++) + { + v = (uint32_t)nodes[i]; + if(nsg->seq[v].del) continue; + if(nsg->seq[v].c == ALTER_LABLE) continue; + v = v<<1; + + for (k = 0; k < 2; k++) + { + v = v|k; + if(get_real_length(nsg, v, NULL)==0) + { + Set_vis(visit, v, 1); + kdq_push(uint32_t, buf, v^1); + } + } + } + + + + while (kdq_size(buf) != 0) + { + v = *(kdq_pop(uint32_t, buf)); + ///if(Get_vis(visit, v, 1) == 0) fprintf(stderr, "ERROR\n"); + + nv = asg_arc_n(nsg, v); + av = asg_arc_a(nsg, v); + for(k = 0; k < nv; k++) + { + if(av[k].del) continue; + w = av[k].v^1; + if(nsg->seq[w>>1].del) continue; + if(Get_vis(visit, w, 1) != 0) continue; + + ///check indegree + nw = asg_arc_n(nsg, w); + aw = asg_arc_a(nsg, w); + for (i = 0, knw = 0; i < nw; i++) + { + if(aw[i].del) continue; + if(Get_vis(visit, aw[i].v, 1) != 0) continue; + knw++; + } + + if(knw == 0) + { + kdq_push(uint32_t, buf, w^1); + Set_vis(visit, (w^1), 1); + } + } + } + + for (i = 0; i < nodes_n; i++) + { + v = (uint32_t)nodes[i]; + if(nsg->seq[v].del) continue; + if(nsg->seq[v].c == ALTER_LABLE) continue; + v = v<<1; + if(Get_vis(visit, v, 1) == 0) return 1; + } + + return 0; +} + +inline void check_connective(asg_t *nsg, uint32_t vBeg, uint32_t vEnd, long long totalNodeLen, buf_t* bb, +uint8_t* visit, ma_ug_t *ug, uint64_t* nodes, uint64_t nodes_n, uint32_t* is_connect, +uint32_t* is_circle) +{ + uint32_t w; + (*is_connect) = (*is_circle) = 0; + + w = vBeg^1; + (*is_connect) = find_spec_node(nsg, vBeg, vEnd, &w, 1, totalNodeLen, bb, visit, ug); + (*is_circle) = detec_circles(nsg, vBeg, vEnd, visit, ug, nodes, nodes_n); +} + + +inline uint32_t process_tangles(ma_ug_t *ug, uint64_t* nodes, uint64_t nodes_n, uint32_t beg, uint32_t end, +buf_t* bb, uint8_t* visit, uint32_t trio_flag, long long totalNodeLen, long long totalBaseLen) +{ + uint32_t n_reduce = 1, v, w, kv, is_found = 0; + asg_t* nsg = ug->g; + + while (n_reduce != 0) + { + while (n_reduce != 0) + { + n_reduce = 0; + n_reduce += drop_tips_at_tangle(nsg, nodes, nodes_n, beg, end, bb); + n_reduce += pop_bubble_at_tangle(ug, totalBaseLen, nodes, nodes_n, beg, end, trio_flag, DROP); + } + n_reduce = drop_useless_edges(ug, bb, visit, beg, end, nodes, nodes_n, totalNodeLen); + } + // if(pop_bubble_at_tangle(ug, 10000000, nodes, nodes_n, beg, end, trio_flag, DROP)!=0) + // { + // fprintf(stderr, "false bubble popping: beg: %u, end: %u\n", beg>>1, end>>1); + // } + + v = beg; + is_found = 0; + while (1) + { + if(v == end) is_found = 1; + if(is_found == 1) break; + + kv = get_real_length(nsg, v, NULL); + if(kv!=1) break; + kv = get_real_length(nsg, v, &w); + if(get_real_length(nsg, w^1, NULL)!=1) break; + + v = w; + if(v == beg) break; + } + return is_found; +} + +uint32_t cut_edges_progressive(ma_ug_t *ug, kvec_t_u64_warp* edges, float drop_ratio, +uint64_t* nodes, uint64_t nodes_n, uint32_t beg, uint32_t end, buf_t* bb, uint8_t* visit, +uint32_t trio_flag, long long totalNodeLen, long long totalBaseLen, uint32_t max_arc_n) +{ + uint32_t k, v, i, kv, w, nv, ov_max, ban, is_found = 0; + asg_arc_t *a = NULL, *av = NULL; + asg_t* nsg = ug->g; + radix_sort_arch64(edges->a.a, edges->a.a + edges->a.n); + for (k = 0; k < edges->a.n && k < max_arc_n; k++) + { + a = &nsg->arc[(uint32_t)edges->a.a[k]]; + if(a->del) continue; + v = (a->ul)>>32; w = a->v; + if(nsg->seq[v>>1].del || nsg->seq[v>>1].c == ALTER_LABLE) continue; + if(nsg->seq[w>>1].del || nsg->seq[w>>1].c == ALTER_LABLE) continue; + + nv = asg_arc_n(nsg, v); + if(nv<=1) continue; + + ov_max = 0; + av = asg_arc_a(nsg, v); + for(i = 0, kv = 0; i < nv; ++i) + { + if(av[i].del) continue; + if(ov_max < av[i].ol) ov_max = av[i].ol; + ++kv; + } + + if(kv<=1) continue; + if(a->ol > ov_max * drop_ratio) continue; + asg_arc_del(nsg, v, w, 1); + asg_arc_del(nsg, w^1, v^1, 1); + + ban = beg^1; + if(find_spec_node(nsg, beg, end, &ban, 1, totalNodeLen, bb, visit, ug) == 0) + { + is_found = 0; + asg_arc_del(nsg, v, w, 0); + asg_arc_del(nsg, w^1, v^1, 0); + break; + } + + is_found = process_tangles(ug, nodes, nodes_n, beg, end, bb, visit, trio_flag, totalNodeLen, + totalBaseLen); + if(is_found == 1) break; + } + + return is_found; +} + +///1. drop tips 2. break edges 3. drop tips 4. do bubble popping +///beg and end have direction, but nsu->a doesn't have +///note here we do everything on src, instead of ug +void unroll_tangle(ma_ug_t *ug, ma_ug_t *length_ug, uint64_t* nodes, uint64_t nodes_n, +uint32_t beg, uint32_t end, kvec_t_u64_warp* edges, uint32_t trio_flag, buf_t* bb, uint8_t* visit, +float drop_ratio) +{ + uint32_t v, w, is_found = 0, convex, i, beg_c, end_c; + long long tmp, max_stop_nodeLen, max_stop_baseLen, begLen, endLen, missLen; + long long totalNodeLen = 0, totalBaseLen = 0; + asg_t* nsg = ug->g; + edges->a.n = 0; + save_all_edges(edges, nsg, nodes, nodes_n, beg, end, &beg_c, &end_c); + + + for (i = 0; i < nodes_n; i++) + { + v = (uint32_t)nodes[i]; + totalNodeLen += ug->u.a[v].n; + totalBaseLen += ug->g->seq[v].len; + } + totalNodeLen += ug->u.a[beg>>1].n + ug->u.a[end>>1].n + 1; + totalBaseLen += ug->g->seq[beg>>1].len + ug->g->seq[end>>1].len + 1; + ///each might be visited twice + totalNodeLen = totalNodeLen * 2; + totalBaseLen = totalBaseLen * 2; + + /**************************debug**************************/ + // uint32_t debug_is_access = 0, debug_is_circle = 0; + // check_connective(nsg, beg, end, totalNodeLen, bb, visit, ug, nodes, nodes_n, &debug_is_access, + // &debug_is_circle); + // if(debug_is_access==0) fprintf(stderr, "Cannot approch end: beg: %u, end: %u\n", beg>>1, end>>1); + // if(debug_is_circle==0) fprintf(stderr, "Not circle: beg: %u, end: %u\n", beg>>1, end>>1); + // if(debug_is_circle==1) fprintf(stderr, "Circle: beg: %u, end: %u\n", beg>>1, end>>1); + /**************************debug**************************/ + is_found = process_tangles(ug, nodes, nodes_n, beg, end, bb, visit, trio_flag, totalNodeLen, + totalBaseLen); + ///if(is_found == 1) fprintf(stderr, "***Found: beg>>1: %u, end>>1: %u\n", beg>>1, end>>1); + + if(is_found == 0) + { + is_found = cut_edges_progressive(ug, edges, drop_ratio, nodes, nodes_n, + beg, end, bb, visit, trio_flag, totalNodeLen, totalBaseLen, 48); + + ///if(is_found == 1) fprintf(stderr, "***Cutting Found: beg>>1: %u, end>>1: %u\n", beg>>1, end>>1); + } + + if(is_found == 1) + { + get_unitig(length_ug->g, length_ug, beg^1, &convex, &begLen, &tmp, &max_stop_nodeLen, + &max_stop_baseLen, 1, NULL); + + get_unitig(length_ug->g, length_ug, end, &convex, &endLen, &tmp, &max_stop_nodeLen, + &max_stop_baseLen, 1, NULL); + + + missLen = 0; + for (i = 0; i < nodes_n; i++) + { + v = (uint32_t)nodes[i]; + if(nsg->seq[v].del || nsg->seq[v].c == ALTER_LABLE) + { + missLen += ug->u.a[v].n; + } + } + ///resolved! + if(missLen <= (begLen+endLen)*TANGLE_MISSED_THRES) + { + is_found = 0; + w = beg^1; + is_found = find_spec_node(nsg, beg, end, &w, 1, totalNodeLen, bb, visit, ug); + } + else + { + is_found = 0; + } + } + + recover_edges(nsg, edges, nodes, nodes_n, beg, end, beg_c, end_c, 1-is_found); +} + +void resolve_tangles(ma_ug_t *src, asg_t *read_g, ma_hit_t_alloc* reverse_sources, long long minLongUntig, +long long maxShortUntig, float l_untig_rate, float max_node_threshold, R_to_U* ruIndex, uint8_t* is_r_het, +uint32_t trio_flag, float drop_ratio) +{ + buf_t b_0, b_1; + memset(&b_0, 0, sizeof(buf_t)); + memset(&b_1, 0, sizeof(buf_t)); + uint32_t i, v, w, sv, n_vtx, beg, end, next_uID = (uint32_t)-1; + kvec_t_u32_warp u_vecs; + kv_init(u_vecs.a); + + kvec_t_u64_warp e_vecs; + kv_init(e_vecs.a); + + ///note: we must reset start for each unitig + n_vtx = src->g->n_seq; + for (v = 0; v < n_vtx; ++v) + { + if(src->g->seq[v].del) continue; + if(src->u.a[v].m==0) continue; + EvaluateLen(src->u, v) = src->u.a[v].n; + } + + ma_ug_t *ug = NULL; + ug = copy_untig_graph(src); + + asg_t* nsg = ug->g; + n_vtx = nsg->n_seq; + for (v = 0; v < n_vtx; ++v) + { + ///nsg->seq[v].c = PRIMARY_LABLE; + EvaluateLen(ug->u, v) = ug->u.a[v].n; + IsMerge(ug->u, v) = 0; + } + + uint8_t* visit = NULL; + visit = (uint8_t*)malloc(sizeof(uint8_t) * nsg->n_seq); + uint32_t n_reduce, flag, dbg_round = 0; + n_vtx = nsg->n_seq * 2; + while (1) + { + n_reduce = 0; + for (v = 0; v < n_vtx; ++v) + { + //as for return value: 0: do nothing, 1: unroll, 2: convex + //we just need 1 + sv = v; + flag = 0; + while (1) + { + flag = walk_through(read_g, ug, reverse_sources, minLongUntig, + maxShortUntig, l_untig_rate, max_node_threshold, &b_0, &b_1, + &u_vecs, visit, sv, &beg, &end, &next_uID, ruIndex, is_r_het); + n_reduce += flag; + if(flag != UNROLL_M) + { + break; + } + } + } + if(n_reduce == 0) break; + dbg_round++; + } + asg_cleanup(nsg); + asg_symm(nsg); + + uint32_t uId, rId, is_Unitig, m, pre; + ma_utg_t* nsu = NULL; + for (v = 0; v < src->g->n_seq; v++) + { + uId = v; + nsu = &(src->u.a[v]); + if(nsu->m == 0) continue; + if(src->g->seq[v].del) continue; + for (i = 0; i < nsu->n; i++) + { + rId = nsu->a[i]>>33; + ///ori = nsu->a[k]>>32&1; + set_R_to_U(ruIndex, rId, uId, 1, &(read_g->seq[rId].c)); + } + } + + n_vtx = nsg->n_seq; + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + nsu = &(ug->u.a[v]); + m = 0; + pre = (uint32_t)(-1); + for (i = 0; i < nsu->n; i++) + { + rId = nsu->a[i]>>33; + get_R_to_U(ruIndex, rId, &uId, &is_Unitig); + if(is_Unitig != 1 || uId == ((uint32_t)(-1))) continue; + if(i > 0 && pre == uId) continue; + pre = uId; + nsu->a[m] = uId; + m++; + } + nsu->n = m; + } + n_vtx = nsg->n_seq; + for (i = 0; i < n_vtx; ++i) + { + v = i; + nsu = &(ug->u.a[v]); + if(nsg->seq[v].del) continue; + if(IsMerge(ug->u, v) == 0) continue; + if(nsg->seq[v].c == ALTER_LABLE) continue; + + v = v<<1; + if(get_real_length(nsg, v, NULL) != 1) continue; + get_real_length(nsg, v, &w); + if(get_real_length(nsg, w^1, NULL) != 1) continue; + if(IsMerge(ug->u, w>>1) != 0) continue; + beg = w^1; + + + v = v^1; + if(get_real_length(nsg, v, NULL) != 1) continue; + get_real_length(nsg, v, &w); + if(get_real_length(nsg, w^1, NULL) != 1) continue; + if(IsMerge(ug->u, w>>1) != 0) continue; + end = w; + ///we have three types of merged nodes + ///1) CONVEX_M: one direction has two out-nodes, another direction has one out-node + ///2) UNROLL_E: one direction has one out-node, another direction doesn't has out-node + ///3) UNROLL_M: both directions have one out-node + ///here we just need UNROLL_M + ///beg and end must be unchanged in src + unroll_tangle(src, ug, nsu->a, nsu->n, beg, end, &e_vecs, trio_flag, &b_0, visit, drop_ratio); + } + + for (v = 0; v < ruIndex->len; v++) + { + get_R_to_U(ruIndex, v, &uId, &is_Unitig); + if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; + } + kv_destroy(u_vecs.a); + kv_destroy(e_vecs.a); + + ma_ug_destroy(ug); + free(visit); + free(b_0.b.a); + free(b_1.b.a); + + + ///note: we must reset start for each unitig + n_vtx = src->g->n_seq; + for (v = 0; v < n_vtx; ++v) + { + if(src->g->seq[v].del) continue; + if(src->u.a[v].m==0) continue; + EvaluateLen(src->u, v) = src->u.a[v].n; + } + ///print_untig_by_read(src, "m64076_200203_181219/82511682/ccs", 2429597, NULL, NULL, "end-1"); +} + + +/*************************************for tangle resolve*************************************/ + +uint32_t copy_ug_node(ma_ug_t *ug, asg_t* nsg, uint32_t v) +{ + ma_utg_t *p; + ma_utg_t *o = &(ug->u.a[v]); + uint32_t n_node = nsg->n_seq; + asg_seq_set(nsg, n_node, nsg->seq[v].len, 0); + kv_pushp(ma_utg_t, ug->u, &p); + + p->s = 0, p->start = o->start, p->end = o->end, p->len = o->len; + p->n = o->n, p->circ = o->circ, p->m = o->m; + p->a = (uint64_t*)malloc(8 * p->m); + memcpy(p->a, o->a, (8*p->m)); + + return n_node; +} + + +///v and w here have directions +uint32_t collect_ma_utg_ts(ma_ug_t *ug, uint32_t v, uint32_t w, ma_utg_t* result) +{ + uint32_t des_dir = w&1; + long long i; + uint64_t* aim = NULL; + ma_utg_t *ma_w = &(ug->u.a[w>>1]); + + if(v == (uint32_t)-1) + { + result->start = ma_w->start; + result->circ = ma_w->circ; + result->end = ma_w->end; + result->len = ma_w->len; + result->n = 0; + } + + + if(result->m < (result->n + ma_w->n)) + { + result->m = (result->n + ma_w->n); + result->a = (uint64_t*)realloc(result->a, result->m * sizeof(uint64_t)); + } + + aim = result->a + result->n; + + if(des_dir == 1) + { + for (i = 0; i < (long long)ma_w->n; i++) + { + aim[ma_w->n - i - 1] = (ma_w->a[i])^(uint64_t)(0x100000000); + } + } + else + { + for (i = 0; i < (long long)ma_w->n; i++) + { + aim[i] = ma_w->a[i]; + } + } + + result->n = result->n + ma_w->n; + return 1; +} + + +void debug_utg_graph(ma_ug_t *ug, asg_t* read_g, kvec_asg_arc_t_warp* edge, int require_equal_nv, int test_tangle) +{ + asg_t* nsg = ug->g; + uint32_t n_vtx = nsg->n_seq, i, j, k, l, totalLen, v, nv, nw, w, untig_v, rid_v; + asg_arc_t *aw = NULL, *av = NULL, *t_v = NULL, *t_w = NULL; + for (i = 0; i < n_vtx; i++) + { + if(ug->g->seq[i].del) continue; + + totalLen = 0; + ma_utg_t* result = &(ug->u.a[i]); + if(result->n == 0) continue; + v = (uint64_t)(result->a[0])>>32; + if(result->start != UINT32_MAX && result->start != v) fprintf(stderr, "hehe\n"); + v = (uint64_t)(result->a[result->n-1])>>32; + if(result->end != UINT32_MAX && result->end != (v^1)) fprintf(stderr, "haha\n"); + uint64_t end_index = result->n-1; + if(result->start == UINT32_MAX && result->end == UINT32_MAX) end_index++; + for (j = 0; j < end_index; j++) + { + v = (uint64_t)(result->a[j])>>32; + if(j == result->n-1) + { + w = (uint64_t)(result->a[0])>>32; + } + else + { + w = (uint64_t)(result->a[j+1])>>32; + } + + + + av = asg_arc_a(read_g, v); + nv = asg_arc_n(read_g, v); + l = (uint32_t)-1; + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + l = asg_arc_len(av[k]); + break; + } + } + + if(edge && k == nv) + { + for (k = 0; k < edge->a.n; k++) + { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) + { + l = asg_arc_len(edge->a.a[k]); + k = nv + 1; + break; + } + } + } + + if(k == nv) fprintf(stderr ,"******error, j: %u, k: %u, nv: %u\n", j, k, nv); + if(l != (uint32_t)(result->a[j])) + { + fprintf(stderr ,"(i: %u) ERROR Length, l: %u, result->a[j]: %u, j: %u, k: %u, nv: %u, circ: %u, result->n: %u\n", + i, l, (uint32_t)(result->a[j]), j, k, nv, result->circ, (uint32_t)result->n); + } + + totalLen = totalLen + l; + } + + + if(j < result->n) + { + v = (uint64_t)(result->a[j])>>32; + l = read_g->seq[v>>1].len; + if(l != (uint32_t)(result->a[j])) fprintf(stderr ,"*** ERROR Length, i: %u\n", i); + totalLen = totalLen + l; + } + + if(totalLen != result->len) + { + fprintf(stderr ,"ERROR Total Length, i: %u\n", i); + } + + + + if(ug->u.a[i].start == UINT32_MAX && ug->u.a[i].end == UINT32_MAX) continue; + + v = i<<1; v=v^1; + av = asg_arc_a(ug->g, v); + nv = asg_arc_n(ug->g, v); + + w = (ug->u.a[v>>1].start^1); + aw = asg_arc_a(read_g, w); + nw = asg_arc_n(read_g, w); + + + if(require_equal_nv && get_real_length(ug->g, v, NULL) != get_real_length(read_g, w, NULL)) + { + fprintf(stderr, "#########ERROR: i: %u, nv: %u, nw: %u\n", i, nv, nw); + } + + for (j = 0; j < nv; j++) + { + if(av[j].del) continue; + untig_v = av[j].v; + if(untig_v&1) rid_v = ug->u.a[untig_v>>1].end; + else rid_v = ug->u.a[untig_v>>1].start; + + t_v = t_w = NULL; + for (k = 0; k < nw; k++) + { + if(aw[k].del) continue; + if(aw[k].v == rid_v) + { + t_w = &(aw[k]); + break; + } + + } + + if(edge && t_w == NULL) + { + for (k = 0; k < edge->a.n; k++) + { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == w && edge->a.a[k].v == rid_v) + { + t_w = &(edge->a.a[k]); + break; + } + } + } + + if(t_w == NULL) fprintf(stderr, "#########ERROR: i: %u\n", i); + t_v = &av[j]; + if(t_w && (t_v->ol != t_w->ol)) + { + fprintf(stderr, "#########????????ERROR\n"); + fprintf(stderr, "nv: %u, nw: %u\n", nv, nw); + fprintf(stderr, "av[%u].ol: %u, aw[%u].ol: %u, untig_v>>1: %u, untig_v&1: %u\n", + j, t_v->ol, k, t_w->ol, untig_v>>1, untig_v&1); + } + } + + + + + + + v = v^1; + av = asg_arc_a(ug->g, v); + nv = asg_arc_n(ug->g, v); + + w = (ug->u.a[v>>1].end^1); + aw = asg_arc_a(read_g, w); + nw = asg_arc_n(read_g, w); + if(require_equal_nv && get_real_length(ug->g, v, NULL) != get_real_length(read_g, w, NULL)) + { + fprintf(stderr, "*******ERROR: i: %u, nv: %u, nw: %u\n", i, nv, nw); + } + for (j = 0; j < nv; j++) + { + if(av[j].del) continue; + untig_v = av[j].v; + if(untig_v&1) rid_v = ug->u.a[untig_v>>1].end; + else rid_v = ug->u.a[untig_v>>1].start; + + t_v = t_w = NULL; + for (k = 0; k < nw; k++) + { + if(aw[k].del) continue; + if(aw[k].v == rid_v) + { + t_w = &(aw[k]); + break; + } + + } + + if(edge && t_w == NULL) + { + for (k = 0; k < edge->a.n; k++) + { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == w && edge->a.a[k].v == rid_v) + { + t_w = &(edge->a.a[k]); + break; + } + } + } + + if(t_w == NULL) fprintf(stderr, "#########ERROR: i: %u\n", i); + t_v = &av[j]; + if(t_w && (t_v->ol != t_w->ol)) + { + fprintf(stderr, "#########????????ERROR\n"); + fprintf(stderr, "nv: %u, nw: %u\n", nv, nw); + fprintf(stderr, "av[%u].ol: %u, aw[%u].ol: %u, untig_v>>1: %u, untig_v&1: %u\n", + j, t_v->ol, k, t_w->ol, untig_v>>1, untig_v&1); + } + } + + } + + + if(test_tangle != 1) return; + fprintf(stderr, "test_tangle: %u\n", test_tangle); + n_vtx = nsg->n_seq * 2; + for (v = 0; v < n_vtx; ++v) + { + uint32_t w1, w2, beg, end, rnw; + if(nsg->seq[v>>1].del) continue; + if(asg_arc_n(nsg, v) < 1 || asg_arc_n(nsg, v^1) < 1) continue; + if(get_real_length(nsg, v, NULL) != 1 || get_real_length(nsg, v^1, NULL) != 1) continue; + get_real_length(nsg, v, &w1); get_real_length(nsg, v^1, &w2); + + ///for simple circle + if(w1 == (w2^1)) + { + beg = end = 0; + aw = asg_arc_a(nsg, w1^1); + nw = asg_arc_n(nsg, w1^1); + for (i = 0, rnw = 0; i < nw; i++) + { + if(aw[i].del) continue; + rnw++; + if(aw[i].v == (v^1)) continue; + beg = aw[i].v; + } + if(rnw != 2) continue; + + aw = asg_arc_a(nsg, w2^1); + nw = asg_arc_n(nsg, w2^1); + for (i = 0, rnw = 0; i < nw; i++) + { + if(aw[i].del) continue; + rnw++; + if(aw[i].v == v) continue; + end = aw[i].v; + } + if(rnw != 2) continue; + + if(get_real_length(nsg, beg^1, NULL)!=1) continue; + if(get_real_length(nsg, end^1, NULL)!=1) continue; + if((beg>>1) == (end>>1)) continue; + fprintf(stderr, "\n************\n"); + } + else if(w1 == w2) + { + if(get_real_length(nsg, w1^1, NULL) != 2) continue; + if(get_real_length(nsg, w1, NULL) != 2) continue; + end = beg = (uint32_t)-1; + + aw = asg_arc_a(nsg, w1); + nw = asg_arc_n(nsg, w1); + for (i = 0, rnw = 0; i < nw && rnw < 2; i++) + { + if(aw[i].del) continue; + if(rnw == 0) beg = aw[i].v; + if(rnw == 1) end = aw[i].v; + rnw++; + } + if((beg>>1) == (end>>1)) continue; + if(get_real_length(nsg, beg^1, NULL)!=1) continue; + if(get_real_length(nsg, end^1, NULL)!=1) continue; + fprintf(stderr, "\n#################\n"); + } + } +} + +///just merge, don't delete anything +void merge_ug_nodes(ma_ug_t *ug, asg_t* read_g, kvec_t_u64_warp* array) +{ + if(array->a.n == 0) return; + uint32_t i, k, v, w; + ma_utg_t result; + memset(&result, 0, sizeof(ma_utg_t)); + v = w = (uint32_t)-1; + for (i = 0; i < array->a.n; i++) + { + w = array->a.a[i]; + collect_ma_utg_ts(ug, v, w, &result); + v = w; + } + + + + if(result.n == 0) return; + asg_arc_t *av = NULL; + uint32_t nv, l; + result.len = 0; + for (i = 0; i < result.n - 1; i++) + { + + v = (uint64_t)(result.a[i])>>32; + w = (uint64_t)(result.a[i + 1])>>32; + av = asg_arc_a(read_g, v); + nv = asg_arc_n(read_g, v); + l = 0; + + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + l = asg_arc_len(av[k]); + break; + } + } + if(k == nv) fprintf(stderr ,"******error, i: %u, k: %u, nv: %u\n", i, k, nv); + result.a[i] = v; result.a[i] = result.a[i]<<32; result.a[i] = result.a[i] | (uint64_t)(l); + result.len += l; + } + + + if(i < result.n) + { + v = (uint64_t)(result.a[i])>>32; + l = read_g->seq[v>>1].len; + result.a[i] = v; + result.a[i] = result.a[i]<<32; + result.a[i] = result.a[i] | (uint64_t)(l); + result.len += l; + } + //has already set result.a, result.len, result.n, result.m + result.circ = 0; + result.start = result.a[0]>>32; + result.end = (result.a[result.n-1]>>32)^1; + + + uint32_t beg_uid = array->a.a[0]; + uint32_t end_uid = array->a.a[array->a.n-1]; + uint32_t realLen = array->a.n; + uint32_t new_uid = array->a.a[0]>>1; + uint64_t kmp; + + + + + + /*******************************just for debug**********************************/ + /** + if(beg_uid&1) + { + if(result.start != ug->u.a[beg_uid>>1].end) + { + fprintf(stderr, "ERROR\n"); + } + } + else + { + if(result.start != ug->u.a[beg_uid>>1].start) + { + fprintf(stderr, "ERROR\n"); + } + } + + if(end_uid&1) + { + if(result.end != ug->u.a[end_uid>>1].start) + { + fprintf(stderr, "ERROR\n"); + } + } + else + { + if(result.end != ug->u.a[end_uid>>1].end) + { + fprintf(stderr, "ERROR\n"); + } + } + **/ + /*******************************just for debug**********************************/ + + asg_arc_t *aw = NULL; + uint32_t nw = 0; + ///corresponding to direction 1 of new node + v = beg_uid^1; + av = asg_arc_a(ug->g, v); + nv = asg_arc_n(ug->g, v); + ///fprintf(stderr, "beg_uid_v>>1: %u, beg_uid_v&1: %u, nv: %u\n", v>>1, v&1, nv); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + kmp = new_uid<<1; kmp = kmp^1; kmp = kmp << 32; + + ///if((av[k].v>>1) == (end_uid>>1)) continue; + w = av[k].v^1; aw = asg_arc_a(ug->g, w); nw = asg_arc_n(ug->g, w); + for (i = 0; i < nw; i++) + { + if(aw[i].del) continue; + if(aw[i].v == (v^1)) break; + } + if(i == nw) fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__); + kmp = kmp | (uint64_t)(aw[i].ol); + + + ///kmp = kmp | (uint64_t)(((ug->g)->idx[v]>>32) + k);/**kmp = kmp | av[k].v;**/ + ///here kmp is ul + kv_push(uint64_t, array->a, kmp); + kmp = av[k].ol; kmp = kmp<<32; kmp = kmp|(uint64_t)(av[k].v); + ///here kmp is ol + v + kv_push(uint64_t, array->a, kmp); + ///fprintf(stderr, "*av[%u].v>>1: %u, v&1: %u, ol: %u\n", k, av[k].v>>1, av[k].v&1, av[k].ol); + } + + ///corresponding to direction 0 of new node + v = end_uid; + av = asg_arc_a(ug->g, v); + nv = asg_arc_n(ug->g, v); + ///fprintf(stderr, "end_uid_v>>1: %u, end_uid_v&1: %u, nv: %u\n", v>>1, v&1, nv); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + kmp = new_uid<<1; kmp = kmp << 32; + + w = av[k].v^1; + aw = asg_arc_a(ug->g, w); + nw = asg_arc_n(ug->g, w); + for (i = 0; i < nw; i++) + { + if(aw[i].del) continue; + if(aw[i].v == (v^1)) break; + } + if(i == nw) fprintf(stderr, "ERROR at %s:%d\n", __FILE__, __LINE__); + kmp = kmp | (uint64_t)(aw[i].ol); + + + ///here kmp is ul + kv_push(uint64_t, array->a, kmp); + kmp = av[k].ol; kmp = kmp<<32; kmp = kmp|(uint64_t)(av[k].v); + ///here kmp is ol + v + kv_push(uint64_t, array->a, kmp); + ///fprintf(stderr, "#av[%u].v>>1: %u, v&1: %u, ol: %u\n", k, av[k].v>>1, av[k].v&1, av[k].ol); + } + + + ma_utg_t* tmp; + for (i = 0; i < realLen; i++) + { + w = array->a.a[i]; + tmp = &(ug->u.a[w>>1]); + if(tmp->m != 0) + { + tmp->circ = tmp->end = tmp->len = tmp->m = tmp->n = tmp->start = 0; + free(tmp->a); + tmp->a = NULL; + } + asg_seq_del(ug->g, w>>1); + } + + ug->u.a[beg_uid>>1] = result; + ug->g->seq[beg_uid>>1].del = 0; + ug->g->seq[beg_uid>>1].len = result.len; + + uint32_t oLen = 0; + for (; i < array->a.n; i += 2) + { + v = array->a.a[i]>>32; + w = (uint32_t)array->a.a[i+1]; + /****************************may have bugs********************************/ + ///may have bug here, if there is an edge between beg_uid and end_uid + ///if(((w>>1) == (beg_uid>>1)) || ((w>>1) == (end_uid>>1))) continue; + if(((w>>1) == (beg_uid>>1)) || ((w>>1) == (end_uid>>1))) w = v; + /****************************may have bugs********************************/ + + oLen = array->a.a[i+1]>>32; + asg_append_edges_to_srt(ug->g, v, ug->u.a[v>>1].len, w, oLen, 0, 0, 0); + oLen = (uint32_t)array->a.a[i]; + asg_append_edges_to_srt(ug->g, w^1, ug->u.a[w>>1].len, v^1, oLen, 0, 0, 0); + } +} + + +void init_Edge_iter(asg_t* g, uint32_t v, asg_arc_t* new_edges, uint32_t new_edges_n, Edge_iter* x) +{ + x->av_i = x->new_edges_i = 0; + x->g = g; + x->av = asg_arc_a(g, v); + x->nv = asg_arc_n(g, v); + + if(new_edges == NULL || new_edges_n == 0) + { + x->new_edges = NULL; + x->new_edges_n = 0; + } + else + { + x->new_edges = new_edges; + x->new_edges_n = new_edges_n; + } +} + +int get_arc_t(Edge_iter* x, asg_arc_t* get) +{ + for (; x->av_i < x->nv; x->av_i++) + { + if(x->av[x->av_i].del) continue; + get = &(x->av[x->av_i]); + x->av_i++; + return 1; + } + + + for (; x->new_edges_i < x->new_edges_n; x->new_edges_i++) + { + if(x->new_edges[x->new_edges_i].del) continue; + get = &(x->new_edges[x->new_edges_i]); + x->new_edges_i++; + return 1; + } + + return 0; +} + + +void unroll_simple_case_advance(ma_ug_t *ug, asg_t* read_g, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, bub_label_t* b_mask_t, uint8_t* is_r_het, double dupLenThres) +{ + asg_t* nsg = ug->g; + uint32_t v, n_vtx = nsg->n_seq * 2, rnw, nw, beg, end, i; + uint32_t v_left, v_right, w_left, w_term, w_right, return_flag, convex, /**is_found,**/ n_reduce = 1; + long long ll, rBase, dupBase, tmp, max_stop_nodeLen, max_stop_baseLen; + asg_arc_t *aw; + kvec_t_u64_warp u_vecs; + kv_init(u_vecs.a); + buf_t b_0, b_1; + memset(&b_0, 0, sizeof(buf_t)); + memset(&b_1, 0, sizeof(buf_t)); + if(b_mask_t) + { + uint64_t bub_dist = get_s_bub_pop_max_dist_advance(nsg, &(b_mask_t->b[0])); + reset_bub_label_t(b_mask_t, nsg, bub_dist, 0); + } + + + while (n_reduce > 0) + { + n_reduce = 0; + ///break nearly circle, forget why... + n_reduce += asg_arc_del_simple_circle_untig(NULL, NULL, nsg, 100, 0); + + for (v = 0; v < n_vtx; ++v) + { + if (nsg->seq[v>>1].del) continue; + v_left = v; + if(asg_arc_n(nsg, v_left)<1) continue; + if(get_real_length(nsg, v_left, NULL)!=1) continue; + + return_flag = get_unitig(nsg, NULL, v_left^1, &v_right, &ll, &rBase, &max_stop_nodeLen, + &max_stop_baseLen, 1, NULL); + if(return_flag == LOOP) continue; + if(return_flag != MUL_INPUT) continue; + if(asg_arc_n(nsg, v_right)<1) continue; + if(get_real_length(nsg, v_right, NULL)!=1) continue; + + get_real_length(nsg, v_left, &w_left); + get_real_length(nsg, v_right, &w_right); + if((v_left>>1)==(w_left>>1)||(v_left>>1)==(w_right>>1)) continue; + if((v_right>>1)==(w_left>>1)||(v_right>>1)==(w_right>>1)) continue; + + if(w_left!=w_right) + { + return_flag = get_unitig(nsg, NULL, w_left, &convex, &ll, &dupBase, &max_stop_nodeLen, + &max_stop_baseLen, 1, NULL); + if(return_flag == LOOP) continue; + if(return_flag != MUL_OUTPUT) continue; + if(convex != (w_right^1)) continue; + + + beg = end = (uint32_t)-1; + aw = asg_arc_a(nsg, w_left^1); + nw = asg_arc_n(nsg, w_left^1); + for (i = 0, rnw = 0; i < nw; i++) + { + if(aw[i].del) continue; + rnw++; + if(aw[i].v == (v_left^1)) continue; + beg = aw[i].v; + } + if(rnw != 2) continue; + + aw = asg_arc_a(nsg, w_right^1); + nw = asg_arc_n(nsg, w_right^1); + for (i = 0, rnw = 0; i < nw; i++) + { + if(aw[i].del) continue; + rnw++; + if(aw[i].v == (v_right^1)) continue; + end = aw[i].v; + } + if(rnw != 2) continue; + + if(get_real_length(nsg, beg^1, NULL)!=1) continue; + if(get_real_length(nsg, end^1, NULL)!=1) continue; + if((beg>>1) == (end>>1)) continue; + + u_vecs.a.n = 0; + kv_push(uint64_t, u_vecs.a, beg^1); + + + b_0.b.n = 0; + get_unitig(nsg, NULL, w_left, &convex, &ll, &tmp, &max_stop_nodeLen, + &max_stop_baseLen, 1, &b_0); + for (i = 0; i < b_0.b.n; i++) + { + kv_push(uint64_t, u_vecs.a, b_0.b.a[i]); + } + b_0.b.n = 0; + get_unitig(nsg, NULL, v_right^1, &convex, &ll, &tmp, &max_stop_nodeLen, + &max_stop_baseLen, 1, &b_0); + for (i = 0; i < b_0.b.n; i++) + { + kv_push(uint64_t, u_vecs.a, b_0.b.a[i]); + } + b_0.b.n = 0; + get_unitig(nsg, NULL, w_left, &convex, &ll, &tmp, &max_stop_nodeLen, + &max_stop_baseLen, 1, &b_0); + for (i = 0; i < b_0.b.n; i++) + { + kv_push(uint64_t, u_vecs.a, b_0.b.a[i]); + } + + kv_push(uint64_t, u_vecs.a, end); + merge_ug_nodes(ug, read_g, &u_vecs); + n_reduce++; + + // fprintf(stderr, "++1++v>>1: %u, w_left>>1: %u, w_right>>1: %u\n", + // v>>1, w_left>>1, w_right>>1); + } + else ///if(w_left == w_right) + { + if(get_real_length(nsg, w_left^1, NULL)!=2) continue; + return_flag = get_unitig(nsg, NULL, w_left, &convex, &ll, &dupBase, &max_stop_nodeLen, + &max_stop_baseLen, 1, NULL); + if(return_flag == LOOP) continue; + if(return_flag != MUL_OUTPUT) continue; + if(get_real_length(nsg, convex, NULL)!=2) continue; + if(dupBase >= rBase*dupLenThres) + { + continue; + } + beg = end = (uint32_t)-1; + + aw = asg_arc_a(nsg, convex); + nw = asg_arc_n(nsg, convex); + for (i = 0, rnw = 0; i < nw; i++) + { + if(aw[i].del) continue; + if(rnw == 0) beg = aw[i].v; + if(rnw == 1) end = aw[i].v; + rnw++; + } + + if(rnw != 2) continue; + if((beg>>1) == (end>>1)) continue; + if(get_real_length(nsg, beg^1, NULL)!=1) continue; + if(get_real_length(nsg, end^1, NULL)!=1) continue; + + + if(b_mask_t && asg_bub_pop1_label(nsg, convex, b_mask_t->bub_dist, &(b_mask_t->b[0]))) + { + continue; + } + + if(check_different_haps(nsg, ug, read_g, beg, end, reverse_sources, &b_0, &b_1, + ruIndex, is_r_het, 2, 1) == PLOID) + { + continue; + } + + + w_term = convex^1; + u_vecs.a.n = 0; + kv_push(uint64_t, u_vecs.a, beg^1); + + b_0.b.n = 0; + get_unitig(nsg, NULL, w_term, &convex, &ll, &tmp, &max_stop_nodeLen, + &max_stop_baseLen, 1, &b_0); + for (i = 0; i < b_0.b.n; i++) + { + kv_push(uint64_t, u_vecs.a, b_0.b.a[i]); + } + + b_0.b.n = 0; + get_unitig(nsg, NULL, v_left^1, &convex, &ll, &tmp, &max_stop_nodeLen, + &max_stop_baseLen, 1, &b_0); + for (i = 0; i < b_0.b.n; i++) + { + kv_push(uint64_t, u_vecs.a, b_0.b.a[i]); + } + + b_0.b.n = 0; + get_unitig(nsg, NULL, w_left, &convex, &ll, &tmp, &max_stop_nodeLen, + &max_stop_baseLen, 1, &b_0); + for (i = 0; i < b_0.b.n; i++) + { + kv_push(uint64_t, u_vecs.a, b_0.b.a[i]); + } + + kv_push(uint64_t, u_vecs.a, end); + merge_ug_nodes(ug, read_g, &u_vecs); + n_reduce++; + + // fprintf(stderr, "--1--v>>1: %u, w_left>>1: %u, w_right>>1: %u\n", + // v>>1, w_left>>1, w_right>>1); + } + } + + + } + + free(b_0.b.a); + free(b_1.b.a); + kv_destroy(u_vecs.a); +} + +void dbg_spec_edge(asg_t *g, uint32_t s, uint32_t e) +{ + asg_arc_t *av; uint32_t an, k, v, w; + + if(s >= g->n_seq) return; + + v = s<<1; + av = asg_arc_a(g, v); an = asg_arc_n(g, v); + for (k = 0; k < an; k++) { + if(av[k].del) continue; + if((av[k].v>>1) == e) { + w = av[k].v; + fprintf(stderr, "[M::%s]\tL\tutg%.6dl\t%c\tutg%.6dl\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", __func__, + (v>>1)+1, "+-"[v&1], (w>>1)+1, "+-"[w&1], av[k].ol, asg_arc_len(av[k]), 0/**au[j].ou**/); + } + } + + v = (s<<1)+1; + av = asg_arc_a(g, v); an = asg_arc_n(g, v); + for (k = 0; k < an; k++) { + if(av[k].del) continue; + if((av[k].v>>1) == e) { + w = av[k].v; + fprintf(stderr, "[M::%s]\tL\tutg%.6dl\t%c\tutg%.6dl\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", __func__, + (v>>1)+1, "+-"[v&1], (w>>1)+1, "+-"[w&1], av[k].ol, asg_arc_len(av[k]), 0/**au[j].ou**/); + } + } + +} + +void adjust_utg_advance(asg_t *sg, ma_ug_t *ug, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, bub_label_t* b_mask_t, uint8_t* is_r_het) +{ + double startTime = Get_T(); + asg_t* nsg = ug->g; + unroll_simple_case_advance(ug, sg, reverse_sources, ruIndex, b_mask_t, is_r_het, 2.5); + drop_semi_circle(ug, ug->g, sg, reverse_sources, ruIndex, is_r_het); + asg_cleanup(nsg); + asg_symm(nsg); + // fprintf(stderr, "[M::%s]-4-\n", __func__); dbg_spec_edge(ug->g, 7536, 28129); + ///debug_utg_graph(ug, sg, 0, 0); + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2f s\n", __func__, Get_T()-startTime); + } +} + + + + + +asg_t *copy_graph(asg_t* src, int round) +{ + asg_t *rg; + ///just calloc + rg = asg_init(); + uint64_t i, k; + for (i = 0; i < src->n_seq; ++i) + { + ///if a read has been deleted, should we still add them? + asg_seq_set(rg, i, src->seq[i].len, src->seq[i].del); + rg->seq[i].c = src->seq[i].c; + } + asg_cleanup(rg); + + + uint32_t v, n_vtx = src->n_seq * 2, totalL = 0;; + + + for (k = 0; k < (uint32_t)round; k++) + { + for (i = k; i < src->n_arc; i = i + round) + { + if(totalL%50000==0) fprintf(stderr, "totalL: %u, n_arc: %u\n", totalL, src->n_arc); + totalL++; + if(src->arc[i].del) continue; + asg_append_edges_to_srt(rg, src->arc[i].ul>>32, + (uint32_t)(src->arc[i].ul) + src->arc[i].ol, + src->arc[i].v, src->arc[i].ol, src->arc[i].strong, + src->arc[i].el, src->arc[i].no_l_indel); + } + } + + + totalL = 0; + for (v = 0; v < n_vtx; ++v) + { + if (src->seq[v>>1].del) continue; + uint32_t nv = asg_arc_n(src, v); + asg_arc_t *av = asg_arc_a(src, v); + for (i = 0; i < nv; i++) + { + if(totalL%50000==0) fprintf(stderr, "-totalL: %u, n_arc: %u\n", totalL, src->n_arc); + totalL++; + if(av[i].del) continue; + asg_append_edges_to_srt(rg, av[i].ul>>32, (uint32_t)(av[i].ul) + av[i].ol, + av[i].v, av[i].ol, av[i].strong, av[i].el, av[i].no_l_indel); + } + } + + + + + /** + for (v = 0; v < n_vtx; ++v) + { + if(src->idx[v] != rg->idx[v]) + { + fprintf(stderr, "*****v: %u, src_i: %u, srcLen: %u, rg_i: %u, rgLen: %u\n", + v, src->idx[v]>>32, (uint32_t)src->idx[v], + rg->idx[v]>>32, (uint32_t)rg->idx[v]); + } + } + **/ + + + for (v = 0; v < n_vtx; ++v) + { + + if(src->seq[v>>1].del != rg->seq[v>>1].del) + { + fprintf(stderr, "ERROR1\n"); + } + + uint32_t nv = asg_arc_n(src, v); + asg_arc_t *av = asg_arc_a(src, v); + ///if(nv != rnv) + if(get_real_length(src, v, NULL) != get_real_length(rg, v, NULL)) + { + fprintf(stderr, "ERROR2\n"); + } + + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + asg_arc_t forward = av[i], backward; + memset(&backward, 0, sizeof(backward)); + if(get_arc(rg, (forward.ul>>32), forward.v, &backward)!=1) + { + fprintf(stderr, "ERROR3\n"); + } + + if(forward.del != backward.del || forward.el != backward.el || + forward.no_l_indel != backward.no_l_indel || forward.ol != backward.ol || + forward.strong != backward.strong || forward.ul != backward.ul || forward.v != backward.v) + { + fprintf(stderr, "ERROR4\n"); + fprintf(stderr, "forward, del: %u, el: %u, no_l_indel: %u, ol: %u, strong: %u, ul: %u, v: %u\n", + (uint32_t)forward.del, (uint32_t)forward.el, (uint32_t)forward.no_l_indel, + (uint32_t)forward.ol, (uint32_t)forward.strong, + (uint32_t)forward.ul, (uint32_t)forward.v); + fprintf(stderr, "backward, del: %u, el: %u, no_l_indel: %u, ol: %u, strong: %u, ul: %u, v: %u\n", + (uint32_t)backward.del, (uint32_t)backward.el, (uint32_t)backward.no_l_indel, + (uint32_t)backward.ol, (uint32_t)backward.strong, + (uint32_t)backward.ul, (uint32_t)backward.v); + } + } + + + nv = asg_arc_n(rg, v); + av = asg_arc_a(rg, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + asg_arc_t forward = av[i], backward; + memset(&backward, 0, sizeof(backward)); + if(get_arc(src, (forward.ul>>32), forward.v, &backward)!=1) + { + fprintf(stderr, "ERROR5\n"); + } + + if(forward.del != backward.del || forward.el != backward.el || + forward.no_l_indel != backward.no_l_indel || forward.ol != backward.ol || + forward.strong != backward.strong || forward.ul != backward.ul || forward.v != backward.v) + { + fprintf(stderr, "ERROR6\n"); + } + } + + + ///get_arc(g, forward.v^1, (forward.ul>>32)^1, &backward) + ///fprintf(stderr, "+v: %u\n", v); + + } + + + if(src->seq_vis) + { + rg->seq_vis = (uint8_t*)malloc(src->n_seq*2*sizeof(uint8_t)); + memcpy(rg->seq_vis, src->seq_vis, src->n_seq*2*sizeof(uint8_t)); + } + + + fprintf(stderr, "end_copy\n"); + return rg; +} + +int load_coverage_cut(ma_sub_t** coverage_cut, char* read_file_name) +{ + char* index_name = (char*)malloc(strlen(read_file_name)+15); + sprintf(index_name, "%s.bin", read_file_name); + FILE* fp = fopen(index_name, "r"); + if(!fp) + { + return 0; + } + int f_flag = 0; + uint64_t n_read; + f_flag += fread(&n_read, sizeof(n_read), 1, fp); + (*coverage_cut) = (ma_sub_t*)malloc(sizeof(ma_sub_t)*n_read); + + // uint64_t i = 0, tmp; + // for (i = 0; i < n_read; i++) + // { + // f_flag += fread(&tmp, sizeof(tmp), 1, fp); + // (*coverage_cut)[i].c = tmp; + // f_flag += fread(&tmp, sizeof(tmp), 1, fp); + // (*coverage_cut)[i].del = tmp; + // f_flag += fread(&tmp, sizeof(tmp), 1, fp); + // (*coverage_cut)[i].e = tmp; + // f_flag += fread(&tmp, sizeof(tmp), 1, fp); + // (*coverage_cut)[i].s = tmp; + // } + fread((*coverage_cut), sizeof((*((*coverage_cut)))), n_read, fp); + + free(index_name); + fflush(fp); + fclose(fp); + return 1; +} + + +int write_coverage_cut(ma_sub_t* coverage_cut, char* read_file_name, uint64_t n_read) +{ + char* index_name = (char*)malloc(strlen(read_file_name)+15); + sprintf(index_name, "%s.bin", read_file_name); + FILE* fp = fopen(index_name, "w"); + fwrite(&n_read, sizeof(n_read), 1, fp); + // uint64_t i = 0, tmp; + // for (i = 0; i < n_read; i++) + // { + // tmp = coverage_cut[i].c; + // fwrite(&tmp, sizeof(tmp), 1, fp); + // tmp = coverage_cut[i].del; + // fwrite(&tmp, sizeof(tmp), 1, fp); + // tmp = coverage_cut[i].e; + // fwrite(&tmp, sizeof(tmp), 1, fp); + // tmp = coverage_cut[i].s; + // fwrite(&tmp, sizeof(tmp), 1, fp); + // } + fwrite(coverage_cut, sizeof((*(coverage_cut))), n_read, fp); + free(index_name); + fflush(fp); + fclose(fp); + + return 1; +} + +int write_ruIndex(R_to_U* ruIndex, char* read_file_name) +{ + char* index_name = (char*)malloc(strlen(read_file_name)+15); + sprintf(index_name, "%s.bin", read_file_name); + FILE* fp = fopen(index_name, "w"); + fwrite(&ruIndex->len, sizeof(ruIndex->len), 1, fp); + fwrite(ruIndex->index, sizeof(ruIndex->index[0]), ruIndex->len, fp); + fwrite(R_INF.trio_flag, sizeof(R_INF.trio_flag[0]), ruIndex->len, fp); + // fwrite(ruIndex->is_het, 1, ruIndex->len, fp); + fwrite(&(asm_opt.hom_global_coverage_set), sizeof(asm_opt.hom_global_coverage_set), 1, fp); + fwrite(&(asm_opt.hom_global_coverage), sizeof(asm_opt.hom_global_coverage), 1, fp); + free(index_name); + fflush(fp); + fclose(fp); + + return 1; +} + +int load_ruIndex(R_to_U* ruIndex, char* read_file_name) +{ + char* index_name = (char*)malloc(strlen(read_file_name)+15); + sprintf(index_name, "%s.bin", read_file_name); + FILE* fp = fopen(index_name, "r"); + if(!fp) + { + return 0; + } + int f_flag = 0; + f_flag += fread(&(ruIndex)->len, sizeof((ruIndex)->len), 1, fp); + (ruIndex)->index = (uint32_t*)malloc(sizeof(uint32_t)*(ruIndex)->len); + f_flag += fread((ruIndex)->index, sizeof((*((ruIndex)->index))), (ruIndex)->len, fp); + + if(!(asm_opt.ar)) { + R_INF.trio_flag = (uint8_t*)malloc(sizeof(uint8_t)*(ruIndex)->len); + f_flag += fread(R_INF.trio_flag, sizeof((*(R_INF.trio_flag))), (ruIndex)->len, fp); + } else { + fseek(fp, sizeof((*(R_INF.trio_flag)))*(ruIndex)->len, SEEK_CUR); + } + + // CALLOC(ruIndex->is_het, ruIndex->len); + // f_flag += fread(ruIndex->is_het, 1, ruIndex->len, fp); + + f_flag += fread(&(asm_opt.hom_global_coverage_set), sizeof(asm_opt.hom_global_coverage_set), 1, fp); + f_flag += fread(&(asm_opt.hom_global_coverage), sizeof(asm_opt.hom_global_coverage), 1, fp); + + free(index_name); + fflush(fp); + fclose(fp); + + return 1; +} + +int write_asg_t(asg_t *sg, char* read_file_name) +{ + char* index_name = (char*)malloc(strlen(read_file_name)+15); + sprintf(index_name, "%s.bin", read_file_name); + FILE* fp = fopen(index_name, "w"); + uint32_t tmp/**, i**/; + + tmp = sg->n_arc; + fwrite(&tmp, sizeof(tmp), 1, fp); + // tmp = sg->m_arc; + fwrite(&tmp, sizeof(tmp), 1, fp); + + tmp = sg->is_srt; + fwrite(&tmp, sizeof(tmp), 1, fp); + + + tmp = sg->n_seq; + fwrite(&tmp, sizeof(tmp), 1, fp); + // tmp = sg->m_seq; + fwrite(&tmp, sizeof(tmp), 1, fp); + + tmp = sg->is_symm; + fwrite(&tmp, sizeof(tmp), 1, fp); + tmp = sg->r_seq; + fwrite(&tmp, sizeof(tmp), 1, fp); + + + uint32_t Len; + + Len = sg->n_seq*2; + fwrite(sg->seq_vis, sizeof(sg->seq_vis[0]), Len, fp); + + Len = sg->n_seq*2; + fwrite(sg->idx, sizeof(sg->idx[0]), Len, fp); + + + // for (i = 0; i < sg->n_arc; i++) + // { + // tmp = sg->arc[i].del; + // fwrite(&tmp, sizeof(tmp), 1, fp); + // tmp = sg->arc[i].el; + // fwrite(&tmp, sizeof(tmp), 1, fp); + // tmp = sg->arc[i].no_l_indel; + // fwrite(&tmp, sizeof(tmp), 1, fp); + // tmp = sg->arc[i].ol; + // fwrite(&tmp, sizeof(tmp), 1, fp); + // tmp = sg->arc[i].strong; + // fwrite(&tmp, sizeof(tmp), 1, fp); + + // uint64_t tmp_64; + // tmp_64 = sg->arc[i].ul; + // fwrite(&tmp_64, sizeof(tmp_64), 1, fp); + + // tmp = sg->arc[i].v; + // fwrite(&tmp, sizeof(tmp), 1, fp); + // } + fwrite(sg->arc, sizeof((*(sg->arc))), sg->n_arc, fp); + + + // for (i = 0; i < sg->n_seq; i++) + // { + // tmp = sg->seq[i].c; + // fwrite(&tmp, sizeof(tmp), 1, fp); + // tmp = sg->seq[i].del; + // fwrite(&tmp, sizeof(tmp), 1, fp); + // tmp = sg->seq[i].len; + // fwrite(&tmp, sizeof(tmp), 1, fp); + // } + fwrite(sg->seq, sizeof((*(sg->seq))), sg->n_seq, fp); + + free(index_name); + fflush(fp); + fclose(fp); + + return 1; +} + + +int load_asg_t(asg_t **sg, char* read_file_name) +{ + char* index_name = (char*)malloc(strlen(read_file_name)+15); + sprintf(index_name, "%s.bin", read_file_name); + FILE* fp = fopen(index_name, "r"); + if(!fp) + { + return 0; + } + uint32_t tmp/**, i**/; + + (*sg) = (asg_t*)calloc(1, sizeof(asg_t)); + int f_flag = 0; + f_flag += fread(&tmp, sizeof(tmp), 1, fp); + (*sg)->n_arc = tmp; + f_flag += fread(&tmp, sizeof(tmp), 1, fp); + (*sg)->m_arc = tmp; + f_flag += fread(&tmp, sizeof(tmp), 1, fp); + (*sg)->is_srt = tmp; + f_flag += fread(&tmp, sizeof(tmp), 1, fp); + (*sg)->n_seq = tmp; + f_flag += fread(&tmp, sizeof(tmp), 1, fp); + (*sg)->m_seq = tmp; + f_flag += fread(&tmp, sizeof(tmp), 1, fp); + (*sg)->is_symm = tmp; + f_flag += fread(&tmp, sizeof(tmp), 1, fp); + (*sg)->r_seq = tmp; + + uint32_t Len; + + Len = (*sg)->n_seq*2; + (*sg)->seq_vis = (uint8_t*)malloc(sizeof(uint8_t)*Len); + f_flag += fread((*sg)->seq_vis, sizeof((*sg)->seq_vis[0]), Len, fp); + + + + Len = (*sg)->n_seq*2; + (*sg)->idx = (uint64_t*)malloc(sizeof(uint64_t)*Len); + f_flag += fread((*sg)->idx, sizeof((*sg)->idx[0]), Len, fp); + + + + + + (*sg)->arc = (asg_arc_t*)malloc(sizeof(asg_arc_t)*(*sg)->m_arc); + (*sg)->seq = (asg_seq_t*)malloc(sizeof(asg_seq_t)*(*sg)->m_seq); + + + // for (i = 0; i < (*sg)->n_arc; i++) + // { + // f_flag += fread(&tmp, sizeof(tmp), 1, fp); + // (*sg)->arc[i].del = tmp; + + // f_flag += fread(&tmp, sizeof(tmp), 1, fp); + // (*sg)->arc[i].el = tmp; + + // f_flag += fread(&tmp, sizeof(tmp), 1, fp); + // (*sg)->arc[i].no_l_indel = tmp; + + // f_flag += fread(&tmp, sizeof(tmp), 1, fp); + // (*sg)->arc[i].ol = tmp; + + // f_flag += fread(&tmp, sizeof(tmp), 1, fp); + // (*sg)->arc[i].strong = tmp; + + // uint64_t tmp_64; + // f_flag += fread(&tmp_64, sizeof(tmp_64), 1, fp); + // (*sg)->arc[i].ul = tmp_64; + + // f_flag += fread(&tmp, sizeof(tmp), 1, fp); + // (*sg)->arc[i].v = tmp; + // } + fread((*sg)->arc, sizeof((*((*sg)->arc))), (*sg)->n_arc, fp); + + + // for (i = 0; i < (*sg)->n_seq; i++) + // { + // f_flag += fread(&tmp, sizeof(tmp), 1, fp); + // (*sg)->seq[i].c = tmp; + // f_flag += fread(&tmp, sizeof(tmp), 1, fp); + // (*sg)->seq[i].del = tmp; + // f_flag += fread(&tmp, sizeof(tmp), 1, fp); + // (*sg)->seq[i].len = tmp; + // } + fread((*sg)->seq, sizeof((*((*sg)->seq))), (*sg)->n_seq, fp); + + free(index_name); + fflush(fp); + fclose(fp); + + return 1; +} + +int write_debug_graph(asg_t *sg, ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, +char* output_file_name, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, all_ul_t *ul_r_inf) +{ + + char* gfa_name = (char*)malloc(strlen(output_file_name)+55); + + ////write_All_reads(&R_INF, gfa_name); + sprintf(gfa_name, "%s.all.debug.source", output_file_name); + write_debug_ma_hit_ts(sources, R_INF.total_reads, gfa_name); + sprintf(gfa_name, "%s.all.debug.reverse", output_file_name); + write_debug_ma_hit_ts(reverse_sources, R_INF.total_reads, gfa_name); + if(coverage_cut) { + sprintf(gfa_name, "%s.all.debug.coverage_cut", output_file_name); + write_coverage_cut(coverage_cut, gfa_name, R_INF.total_reads); + } + sprintf(gfa_name, "%s.all.debug.ruIndex", output_file_name); + write_ruIndex(ruIndex, gfa_name); + if(sg) { + sprintf(gfa_name, "%s.all.debug.asg_t", output_file_name); + write_asg_t(sg, gfa_name); + } + if(ul_r_inf) { + sprintf(gfa_name, "%s.all.debug.ul.rinfor", output_file_name); + write_all_ul_t(ul_r_inf, gfa_name, NULL); + } + free(gfa_name); + fprintf(stderr, "debug_graph has been written.\n"); + return 1; +} + + +int load_debug_graph(asg_t** sg, ma_hit_t_alloc** sources, ma_sub_t** coverage_cut, +char* output_file_name, ma_hit_t_alloc** reverse_sources, R_to_U* ruIndex, all_ul_t *ul_r_inf) +{ + FILE* fp = NULL; + char* gfa_name = (char*)malloc(strlen(output_file_name)+55); + sprintf(gfa_name, "%s.all.debug.source.bin", output_file_name); + fp = fopen(gfa_name, "r"); if(!fp) return 0; fclose(fp); + sprintf(gfa_name, "%s.all.debug.reverse.bin", output_file_name); + fp = fopen(gfa_name, "r"); if(!fp) return 0; fclose(fp); + if(coverage_cut) { + sprintf(gfa_name, "%s.all.debug.coverage_cut.bin", output_file_name); + fp = fopen(gfa_name, "r"); if(!fp) return 0; fclose(fp); + } + sprintf(gfa_name, "%s.all.debug.ruIndex.bin", output_file_name); + fp = fopen(gfa_name, "r"); if(!fp) return 0; fclose(fp); + if(sg) { + sprintf(gfa_name, "%s.all.debug.asg_t.bin", output_file_name); + fp = fopen(gfa_name, "r"); if(!fp) return 0; fclose(fp); + } + if(ul_r_inf) { + sprintf(gfa_name, "%s.all.debug.ul.rinfor.ul.ovlp.bin", output_file_name); + fp = fopen(gfa_name, "r"); if(!fp) return 0; fclose(fp); + } + + if((sources == NULL) || (reverse_sources == NULL) || (ruIndex == NULL)) + { + return 1; + } + + if((*sources)!=NULL) + { + destory_ma_hit_t_alloc((*sources)); + } + + if((*reverse_sources)!=NULL) + { + destory_ma_hit_t_alloc((*reverse_sources)); + } + + if(coverage_cut && (*coverage_cut)!=NULL) + { + free((*coverage_cut)); + } + + if((ruIndex)!=NULL) + { + destory_R_to_U((ruIndex)); + } + + if(sg && (*sg)!=NULL) + { + asg_destroy(*sg); + } + + + + sprintf(gfa_name, "%s.all.debug.source", output_file_name); + if(!load_debug_ma_hit_ts(sources, gfa_name)) + { + return 0; + } + + sprintf(gfa_name, "%s.all.debug.reverse", output_file_name); + if(!load_debug_ma_hit_ts(reverse_sources, gfa_name)) + { + return 0; + } + + if(coverage_cut) { + sprintf(gfa_name, "%s.all.debug.coverage_cut", output_file_name); + if(!load_coverage_cut(coverage_cut, gfa_name)) + { + return 0; + } + } + + sprintf(gfa_name, "%s.all.debug.ruIndex", output_file_name); + if(!load_ruIndex(ruIndex, gfa_name)) + { + return 0; + } + + if(sg) { + sprintf(gfa_name, "%s.all.debug.asg_t", output_file_name); + if(!load_asg_t(sg, gfa_name)) + { + return 0; + } + } + + + if(ul_r_inf) { + sprintf(gfa_name, "%s.all.debug.ul.rinfor", output_file_name); + if(!load_all_ul_t(ul_r_inf, gfa_name, &R_INF, NULL)) return 0; + } + + R_INF.paf = (*sources); R_INF.reverse_paf = (*reverse_sources); + + return 1; +} + + +hap_cov_t* init_hap_cov_t(ma_ug_t *ug, asg_t* read_g, ma_hit_t_alloc* sources, R_to_U* ruIndex, +ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, int max_hang, int min_ovlp, +uint32_t is_collect_trans) +{ + uint32_t n_ux = ug->g->n_seq, i, k, j, v, rId, tn, is_Unitig, r_i, nv, w, C_bases; + uint8_t *set = NULL; + hap_cov_t *x = NULL; CALLOC(x, 1); + x->n = read_g->n_seq; + x->reverse_sources = reverse_sources; + x->coverage_cut = coverage_cut; + x->ruIndex = ruIndex; + x->max_hang = max_hang; + x->min_ovlp = min_ovlp; + x->read_g = read_g; + x->t_ch = NULL; + kv_init(x->u_buffer.a); + kv_init(x->tailIndex.a); + kv_init(x->prevIndex.a); + ma_utg_t* u = NULL; + asg_arc_t *av = NULL; + ma_hit_t *h = NULL; + MALLOC(x->pos_idx, x->n); memset(x->pos_idx, -1, x->n*sizeof(uint64_t)); + CALLOC(set, read_g->n_seq<<1); + CALLOC(x->cov, x->n); + for (i = 0; i < n_ux; i++)//get the coverage for each read + { + if(ug->g->seq[i].del) continue; + u = &(ug->u.a[i]); + for (r_i = 0; r_i < u->n; r_i++) set[u->a[r_i]>>33] = 1; + + v = i<<1; + nv = asg_arc_n(ug->g, v); + av = asg_arc_a(ug->g, v); + for (k = 0; k < nv; k++) + { + w = av[k].v; + if(av[k].del) continue; + if(ug->g->seq[w>>1].del) continue; + u = &(ug->u.a[w>>1]); + for (r_i = 0; r_i < u->n; r_i++) set[u->a[r_i]>>33] = 1; + } + + v = (i<<1)+1; + nv = asg_arc_n(ug->g, v); + av = asg_arc_a(ug->g, v); + for (k = 0; k < nv; k++) + { + w = av[k].v; + if(av[k].del) continue; + if(ug->g->seq[w>>1].del) continue; + u = &(ug->u.a[w>>1]); + for (r_i = 0; r_i < u->n; r_i++) set[u->a[r_i]>>33] = 1; + } + + + + u = &(ug->u.a[i]); + for (k = 0; k < u->n; k++) + { + C_bases = 0; + rId = u->a[k]>>33; + for (j = 0; j < (uint64_t)(sources[rId].length); j++) + { + h = &(sources[rId].buffer[j]); + tn = Get_tn((*h)); + if(read_g->seq[tn].del == 1) + { + ///get the id of read that contains it + // uint32_t tn0 = tn; + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + // if(tn != (uint32_t)-1 && is_Unitig != 1) { + // fprintf(stderr, "[M::%s]\ttn::%u\tn_seq::%u\tis_Unitig::%u\ttn0::%u\n", __func__, tn, read_g->n_seq, is_Unitig, tn0); + // } + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + if(read_g->seq[tn].del == 1) continue; + if(!set[tn]) continue; + C_bases += (Get_qe((*h)) - Get_qs((*h))); + } + x->cov[rId] = MAX(C_bases, x->cov[rId]); + } + + + + u = &(ug->u.a[i]); + for (r_i = 0; r_i < u->n; r_i++) set[u->a[r_i]>>33] = 0; + + v = i<<1; + nv = asg_arc_n(ug->g, v); + av = asg_arc_a(ug->g, v); + for (k = 0; k < nv; k++) + { + w = av[k].v; + if(av[k].del) continue; + if(ug->g->seq[w>>1].del) continue; + u = &(ug->u.a[w>>1]); + for (r_i = 0; r_i < u->n; r_i++) set[u->a[r_i]>>33] = 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++) + { + w = av[k].v; + if(av[k].del) continue; + if(ug->g->seq[w>>1].del) continue; + u = &(ug->u.a[w>>1]); + for (r_i = 0; r_i < u->n; r_i++) set[u->a[r_i]>>33] = 0; + } + } + + if(set) free(set); + CALLOC(x->is_r_het, read_g->n_seq); + set_r_het_flag(ug, read_g, coverage_cut, sources, ruIndex, x->is_r_het); + + x->t_ch = NULL; + if(is_collect_trans) x->t_ch = init_trans_chain(ug, read_g->n_seq); + + return x; +} + +void destory_hap_cov_t(hap_cov_t **x) +{ + if(*x) + { + free((*x)->cov); + free((*x)->pos_idx); + free((*x)->is_r_het); + kv_destroy((*x)->u_buffer.a); + kv_destroy((*x)->tailIndex.a); + kv_destroy((*x)->prevIndex.a); + if((*x)->t_ch) destory_trans_chain(&((*x)->t_ch)); + free((*x)); + } +} + + +void print_utg_hap(ma_ug_t *ug, asg_t* read_g, uint32_t uid, ma_hit_t_alloc* reverse_sources, +R_to_U* ruIndex) +{ + + uint32_t k, rId, qn, i, is_Unitig; + ma_utg_t* u = &(ug->u.a[uid]); + fprintf(stderr, "\nuid: %u, u->n: %u\n", uid, u->n); + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + fprintf(stderr, "self[%u]: %u\n", k, rId); + } + + for (k = 0; k < u->n; k++) + { + qn = u->a[k]>>33; + fprintf(stderr, "****self[%u]: %u, Len: %u\n", k, qn, reverse_sources[qn].length); + for (i = 0; i < reverse_sources[qn].length; i++) + { + rId = Get_tn(reverse_sources[qn].buffer[i]); + if(read_g->seq[rId].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, rId, &rId, &is_Unitig); + if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; + } + fprintf(stderr, "hap[%u]: %u\n", i, rId); + } + } + +} + + +void reset_trans_chain(trans_chain* t_ch, ma_utg_t *u) +{ + uint32_t k = 0; + if(u->n == 0 || u->m == 0) return; + for (k = 0; k < u->n; k++) t_ch->ir_het[u->a[k]>>33] = N_HET; +} + +void append_utg(ma_ug_t* ptg, ma_ug_t* atg, trans_chain* t_ch) +{ + uint64_t num_nodes = 0; + asg_t* nsg = atg->g; + uint32_t v, n_vtx = nsg->n_seq; + ma_utg_t *p; + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del || atg->u.a[v].m == 0) continue; + num_nodes++; + } + + if(num_nodes == 0) return; + + ptg->u.n = ptg->u.n + num_nodes; + if(ptg->u.n > ptg->u.m) + { + ptg->u.m = ptg->u.n; + ptg->u.a = (ma_utg_t*)realloc(ptg->u.a, ptg->u.m*sizeof(ma_utg_t)); + } + ptg->u.n = ptg->u.n - num_nodes; + + for (v = 0; v < atg->g->n_seq; ++v) + { + if(atg->g->seq[v].del || atg->u.a[v].m == 0) continue; + if(t_ch) reset_trans_chain(t_ch, &(atg->u.a[v])); + + p = &(ptg->u.a[ptg->u.n]); + p->len = atg->u.a[v].len; + p->circ = atg->u.a[v].circ; + p->start = atg->u.a[v].start; + p->end = atg->u.a[v].end; + p->m = atg->u.a[v].m; atg->u.a[v].m = 0; + p->n = atg->u.a[v].n; atg->u.a[v].n = 0; + p->a = atg->u.a[v].a; atg->u.a[v].a = 0; + p->s = atg->u.a[v].s; atg->u.a[v].s = 0; + asg_seq_set(ptg->g, ptg->u.n, p->len, 0); + ptg->u.n++; + } + + if(ptg->g->idx != 0) free(ptg->g->idx); + ptg->g->idx = 0; + asg_cleanup(ptg->g); +} + + +void print_utg_coverage(ma_ug_t *ug, ma_sub_t* coverage_cut, uint32_t v, ma_hit_t_alloc* sources) +{ + asg_t* nsg = ug->g; + uint32_t rId, k, j; + ma_utg_t* u = NULL; + ma_hit_t *h; + + if(nsg->seq[v].del) return; + u = &(ug->u.a[v]); + if(u->m == 0) return; + long long R_bases = 0, C_bases = 0; + long long U_R_bases = 0, U_C_bases = 0; + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + C_bases = 0; + R_bases = coverage_cut[rId].e - coverage_cut[rId].s; + for (j = 0; j < (uint64_t)(sources[rId].length); j++) + { + h = &(sources[rId].buffer[j]); + if(h->el != 1) continue; + C_bases += Get_qe((*h)) - Get_qs((*h)); + } + U_R_bases += R_bases; + U_C_bases += C_bases; + C_bases = C_bases/R_bases; + + fprintf(stderr, "%.*s\t%lld\n", (int)Get_NAME_LENGTH(R_INF, rId), Get_NAME(R_INF, rId), C_bases); + } + + fprintf(stderr, "v: %u, coverage: %lld\n\n", v, U_C_bases/U_R_bases); +} + +void recover_utg_by_coverage(ma_ug_t **ptg, asg_t* read_g, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex, trans_chain* t_ch) +{ + if(asm_opt.recover_atg_cov_min == -1) return; + if(asm_opt.recover_atg_cov_max == -1) return; + if(asm_opt.recover_atg_cov_min > asm_opt.recover_atg_cov_max) return; + ma_ug_t *atg = NULL; + atg = ma_ug_gen_primary(read_g, ALTER_LABLE); + asg_t* nsg = atg->g; + uint32_t v, n_vtx = nsg->n_seq, k, j, rId, available_reads = 0, keep_atg = 0, tn, is_Unitig; + ma_utg_t* u = NULL; + ma_hit_t *h; + + + ///print_untig_by_read(atg, "SRR11606870.634978", -1, NULL, NULL, "debug"); + long long R_bases = 0, C_bases = 0, C_bases_primary = 0, C_bases_alter = 0; + long long total_C_bases = 0, total_C_bases_alter = 0; + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + u = &(atg->u.a[v]); + if(u->m == 0) continue; + total_C_bases = total_C_bases_alter = available_reads = 0; + + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + C_bases = C_bases_primary = C_bases_alter = 0; + R_bases = coverage_cut[rId].e - coverage_cut[rId].s; + for (j = 0; j < (uint64_t)(sources[rId].length); j++) + { + h = &(sources[rId].buffer[j]); + if(h->el != 1) continue; + tn = Get_tn((*h)); + if(read_g->seq[tn].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + if(read_g->seq[tn].del == 1) continue; + if(read_g->seq[tn].c == ALTER_LABLE) + { + C_bases_alter += Get_qe((*h)) - Get_qs((*h)); + } + else + { + C_bases_primary += Get_qe((*h)) - Get_qs((*h)); + } + } + + C_bases = C_bases_primary + C_bases_alter; + total_C_bases += C_bases; + + C_bases = C_bases/R_bases; + if(C_bases >= asm_opt.recover_atg_cov_min && C_bases <= asm_opt.recover_atg_cov_max) + { + if(C_bases_alter >= (C_bases_primary + C_bases_alter) * ALTER_COV_THRES) available_reads++; + total_C_bases_alter += C_bases_alter; + } + } + + + if(((available_reads < (u->n * 0.8)) && (total_C_bases_alter < (total_C_bases * 0.8))) + || available_reads == 0) + { + asg_seq_del(nsg, v); + + if(u->m!=0) + { + u->m = u->n = 0; + free(u->a); + u->a = NULL; + } + } + else + { + ///print_utg_coverage(atg, coverage_cut, v, sources); + ///fprintf(stderr, "rId: %u\n", rId); + ///fprintf(stderr, "%.*s\t%lld\n", (int)Get_NAME_LENGTH(R_INF, rId), Get_NAME(R_INF, rId), C_bases); + keep_atg++; + } + } + + if(keep_atg > 0) + { + asg_cleanup(nsg); + asg_symm(nsg); + append_utg(*ptg, atg, t_ch); + + n_vtx = read_g->n_seq; + for (v = 0; v < n_vtx; v++) + { + read_g->seq[v].c = ALTER_LABLE; + } + + nsg = (*ptg)->g; + n_vtx = nsg->n_seq; + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + u = &((*ptg)->u.a[v]); + if(u->m == 0) continue; + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + read_g->seq[rId].c = nsg->seq[v].c; + } + } + + + n_vtx = read_g->n_seq; + for (v = 0; v < n_vtx; v++) + { + if(read_g->seq[v].c == ALTER_LABLE) + { + asg_seq_drop(read_g, v); + } + } + } + + ma_ug_destroy(atg); +} + + +void adjust_utg_by_primary(ma_ug_t **ug, asg_t* read_g, float drop_rate, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, +R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, +kvec_asg_arc_t_warp* new_rtg_edges, hap_cov_t **i_cov, bub_label_t* b_mask_t, +uint32_t collect_p_trans, uint32_t collect_p_trans_f) +{ + asg_t* nsg = (*ug)->g; + uint32_t v, n_vtx = nsg->n_seq, k, rId, just_contain; + ma_utg_t* u = NULL; + hap_cov_t *cov = init_hap_cov_t(*ug, read_g, sources, ruIndex, reverse_sources, + coverage_cut, max_hang, min_ovlp, (asm_opt.purge_level_primary>0||i_cov)?1:0); + if(cov->t_ch) cov->t_ch->ir_het = cov->is_r_het; + adjust_utg_advance(read_g, (*ug), reverse_sources, ruIndex, b_mask_t, cov->is_r_het); + + nsg = (*ug)->g; + n_vtx = nsg->n_seq; + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + nsg->seq[v].c = PRIMARY_LABLE; + EvaluateLen((*ug)->u, v) = (*ug)->u.a[v].n; + } + + clean_primary_untig_graph(*ug, read_g, sources, reverse_sources, coverage_cut, tipsLen, tip_drop_ratio, + stops_threshold, ruIndex, NULL, NULL, 0, 0, 0, chimeric_rate, 0, 0, drop_ratio, cov); + delete_useless_nodes(ug); + renew_utg(ug, read_g, new_rtg_edges); + if(i_cov && collect_p_trans == 0) goto skip_purge; + if(asm_opt.purge_level_primary > 0) + { + // print_debug_gfa(read_g, *ug, coverage_cut, "debug_purge", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); + just_contain = 0; + if(asm_opt.purge_level_primary == 1) just_contain = 1; + purge_dups(*ug, read_g, coverage_cut, sources, reverse_sources, ruIndex, new_rtg_edges, + asm_opt.purge_simi_thres, asm_opt.purge_overlap_len, max_hang, min_ovlp, drop_ratio, + just_contain, 0, cov, !!(cov->t_ch&&collect_p_trans), collect_p_trans_f); + delete_useless_nodes(ug); + renew_utg(ug, read_g, new_rtg_edges); + } + + if (!(asm_opt.flag & HA_F_BAN_POST_JOIN)) + { + rescue_missing_overlaps_aggressive(*ug, read_g, sources, coverage_cut, ruIndex, max_hang, + min_ovlp, 0, 1, NULL, b_mask_t); + renew_utg(ug, read_g, new_rtg_edges); + rescue_contained_reads_aggressive(*ug, read_g, sources, coverage_cut, ruIndex, max_hang, + min_ovlp, 10, 0, 1, NULL, NULL, b_mask_t); + renew_utg(ug, read_g, new_rtg_edges); + } + + + if(asm_opt.max_contig_tip > 0) { + discard_small_ctg(ug, read_g, new_rtg_edges, asm_opt.max_contig_tip, 0, 1); + } + + + n_vtx = read_g->n_seq; + for (v = 0; v < n_vtx; v++) + { + read_g->seq[v].c = ALTER_LABLE; + } + + + nsg = (*ug)->g; + n_vtx = nsg->n_seq; + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + if(nsg->seq[v].c == ALTER_LABLE) continue; + u = &((*ug)->u.a[v]); + if(u->m == 0) continue; + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + read_g->seq[rId].c = nsg->seq[v].c; + } + } + + n_vtx = read_g->n_seq; + for (v = 0; v < n_vtx; v++) + { + if(read_g->seq[v].c == ALTER_LABLE) + { + asg_seq_drop(read_g, v); + } + } + + if(asm_opt.recover_atg_cov_min == -1024) + { + asm_opt.recover_atg_cov_max = (asm_opt.hom_global_coverage_set? + (asm_opt.hom_global_coverage):(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); + asm_opt.recover_atg_cov_min = asm_opt.recover_atg_cov_max * 0.85; + asm_opt.recover_atg_cov_max = INT32_MAX; + } + + if(asm_opt.recover_atg_cov_max != INT32_MAX) + { + fprintf(stderr, "[M::%s] primary contig coverage range: [%d, %d]\n", + __func__, asm_opt.recover_atg_cov_min, asm_opt.recover_atg_cov_max); + } + else + { + fprintf(stderr, "[M::%s] primary contig coverage range: [%d, infinity]\n", + __func__, asm_opt.recover_atg_cov_min); + } + + skip_purge: + recover_utg_by_coverage(ug, read_g, coverage_cut, sources, ruIndex, cov->t_ch); + if(i_cov) + { + (*i_cov) = cov; + } + else + { + destory_hap_cov_t(&cov); + } +} + +void set_r_het_status(uint8_t* r_het, kv_gg_status *sa, ma_ug_t *ug, uint32_t hapN) +{ + uint32_t i, k, o, f; + ma_utg_t *u; + mcg_node_t s; + for (i = 0; i < sa->n; i++) + { + u = &(ug->u.a[i]); + s = sa->a[i].s; o = 0; + while (s) { + o += (s&1); s>>=1; + } + + f = N_HET; + if(o < hapN) f = C_HET; + for (k = 0; k < u->n; k++) r_het[u->a[k]>>33] = f; + } +} +kv_u_trans_t *get_utg_ovlp(ma_ug_t **ug, asg_t* read_g, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* new_rtg_edges, bub_label_t* b_mask_t, uint8_t* r_het) +{ + ///print_debug_gfa(read_g, *ug, coverage_cut, "init", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); + kv_u_trans_t *ta = pt_pdist(*ug, read_g,coverage_cut, sources, new_rtg_edges, max_hang, min_ovlp, 5); + kv_gg_status *sa = init_mc_gg_status(*ug, read_g, coverage_cut, sources, ruIndex, + asm_opt.hom_global_coverage_set?asm_opt.hom_global_coverage:((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE), + asm_opt.polyploidy); + mc_solve_general(ta, (*ug)->u.n, sa, asm_opt.polyploidy, 1, 1); + if(r_het) set_r_het_status(r_het, sa, *ug, asm_opt.polyploidy); + free(sa->a); free(sa); + return ta; + // ma_ug_seq(*ug, read_g, coverage_cut, sources, new_rtg_edges, max_hang, min_ovlp, 0, 0); + // ug_idx_build(*ug, asm_opt.polyploidy); + // topo_ovlp_collect(*ug, read_g, sources, reverse_sources, coverage_cut, tipsLen, tip_drop_ratio, + // stops_threshold, ruIndex, chimeric_rate, drop_ratio, max_hang, min_ovlp, cov); +} + +void output_contig_graph_primary_pre(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, uint64_t bubble_dist, long long tipsLen, +R_to_U* ruIndex, int max_hang, int min_ovlp, const ug_opt_t *uopt) +{ + kvec_asg_arc_t_warp new_rtg_edges; + kv_init(new_rtg_edges.a); + + ma_ug_t *ug = NULL; + ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); + + asg_t* nsg = ug->g; + uint32_t n_vtx = nsg->n_seq, v; + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + nsg->seq[v].c = PRIMARY_LABLE; + EvaluateLen(ug->u, v) = ug->u.a[v].n; + } + + if(bubble_dist > 0) + { + asg_pop_bubble_primary_trio(ug, &bubble_dist, (uint32_t)-1, DROP, NULL, NULL, 0, NULL); + delete_useless_nodes(&ug); + renew_utg(&ug, sg, &new_rtg_edges); + } + + // reset_untig_hap_label(ug, 7, FATHER, R_INF.trio_flag); + // reset_untig_hap_label(ug, 35, FATHER, R_INF.trio_flag); + + // reset_untig_hap_label(ug, 713, FATHER, R_INF.trio_flag); + // reset_untig_hap_label(ug, 273, FATHER, R_INF.trio_flag); + // reset_untig_hap_label(ug, 822, FATHER, R_INF.trio_flag); + + ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 1); + + fprintf(stderr, "Writing processed unitig GFA to disk... \n"); + char* gfa_name = (char*)malloc(strlen(output_file_name)+35); + sprintf(gfa_name, "%s.p_utg.gfa", output_file_name); + FILE* output_file = fopen(gfa_name, "w"); + ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + fclose(output_file); + + sprintf(gfa_name, "%s.p_utg.noseq.gfa", output_file_name); + output_file = fopen(gfa_name, "w"); + ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + fclose(output_file); + if(asm_opt.bed_inconsist_rate != 0) + { + sprintf(gfa_name, "%s.p_utg.lowQ.bed", output_file_name); + output_file = fopen(gfa_name, "w"); + ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, + max_hang, min_ovlp, asm_opt.bed_inconsist_rate, "utg", output_file, NULL); + fclose(output_file); + } + + ///for debug + // graph_ovlp_binning(ug, sg, uopt); + // gen_hpc_re_t(ug); + + free(gfa_name); + ma_ug_destroy(ug); + kv_destroy(new_rtg_edges.a); +} + +void output_contig_graph_primary(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, long long tipsLen, float tip_drop_ratio, long long stops_threshold, +R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, bub_label_t* b_mask_t) +{ + ma_ug_t *ug = NULL; + ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); + + kvec_asg_arc_t_warp new_rtg_edges; + kv_init(new_rtg_edges.a); + + adjust_utg_by_primary(&ug, sg, TRIO_THRES, sources, reverse_sources, coverage_cut, + tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, + max_hang, min_ovlp, &new_rtg_edges, NULL, b_mask_t, 0, 0); + + if(asm_opt.b_low_cov > 0) + { + break_ug_contig(&ug, sg, &R_INF, coverage_cut, sources, ruIndex, &new_rtg_edges, max_hang, min_ovlp, + &asm_opt.b_low_cov, NULL, asm_opt.m_rate); + } + if(asm_opt.b_high_cov > 0) + { + break_ug_contig(&ug, sg, &R_INF, coverage_cut, sources, ruIndex, &new_rtg_edges, max_hang, min_ovlp, + NULL, &asm_opt.b_high_cov, asm_opt.m_rate); + } + ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 1); + + + fprintf(stderr, "Writing primary contig GFA to disk... \n"); + char* gfa_name = (char*)malloc(strlen(output_file_name)+35); + sprintf(gfa_name, "%s.p_ctg.gfa", output_file_name); + FILE* output_file = fopen(gfa_name, "w"); + ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "ptg", output_file); + fclose(output_file); + + sprintf(gfa_name, "%s.p_ctg.noseq.gfa", output_file_name); + output_file = fopen(gfa_name, "w"); + ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "ptg", output_file); + fclose(output_file); + if(asm_opt.bed_inconsist_rate != 0) + { + sprintf(gfa_name, "%s.p_ctg.lowQ.bed", output_file_name); + output_file = fopen(gfa_name, "w"); + ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, + max_hang, min_ovlp, asm_opt.bed_inconsist_rate, "ptg", output_file, NULL); + fclose(output_file); + } + + free(gfa_name); + ma_ug_destroy(ug); + kv_destroy(new_rtg_edges.a); +} + + + + +void output_contig_graph_alternative(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, R_to_U* ruIndex, int max_hang, int min_ovlp) +{ + kvec_asg_arc_t_warp new_rtg_edges; + kv_init(new_rtg_edges.a); + ma_ug_t *ug = NULL; + ug = ma_ug_gen_primary(sg, ALTER_LABLE); + + // if(asm_opt.b_low_cov > 0) + // { + // break_ug_contig(&ug, sg, &R_INF, coverage_cut, sources, ruIndex, &new_rtg_edges, max_hang, min_ovlp, asm_opt.b_low_cov); + // } + + ma_ug_seq(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 1); + + fprintf(stderr, "Writing alternate contig GFA to disk... \n"); + char* gfa_name = (char*)malloc(strlen(output_file_name)+35); + sprintf(gfa_name, "%s.a_ctg.gfa", output_file_name); + FILE* output_file = fopen(gfa_name, "w"); + ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "atg", output_file); + fclose(output_file); + + sprintf(gfa_name, "%s.a_ctg.noseq.gfa", output_file_name); + output_file = fopen(gfa_name, "w"); + ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "atg", output_file); + fclose(output_file); + if(asm_opt.bed_inconsist_rate != 0) + { + sprintf(gfa_name, "%s.a_ctg.lowQ.bed", output_file_name); + output_file = fopen(gfa_name, "w"); + ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, + max_hang, min_ovlp, asm_opt.bed_inconsist_rate, "atg", output_file, NULL); + fclose(output_file); + } + + free(gfa_name); + ma_ug_destroy(ug); + kv_destroy(new_rtg_edges.a); +} + +int output_tips(asg_t *g, const All_reads *RNF) +{ + uint32_t v, n_vtx = g->n_seq * 2; + for (v = 0; v < n_vtx; ++v) + { + if (g->seq[v>>1].del) continue; + + if(asg_arc_n(g, v) == 0) + { + fprintf(stderr, "%.*s\n", + (int)Get_NAME_LENGTH((*RNF), v>>1), + Get_NAME((*RNF), v>>1)); + } + } + + return 1; +} + +void collect_abnormal_edges(ma_hit_t_alloc* paf, ma_hit_t_alloc* rev_paf, long long readNum) +{ + double startTime = Get_T(); + long long T_edges, T_Single_Dir_Edges_0, T_Single_Dir_Edges_1, T_Conflict_Equal_Edges, T_Conflict_Strong_Edges; + T_edges = T_Single_Dir_Edges_0 = T_Single_Dir_Edges_1 = T_Conflict_Equal_Edges = T_Conflict_Strong_Edges = 0; + long long T_Single_Dir_Edges_1_1000 = 0; + long long related_reads = 0; + long long related_overlaps = 0; + long long i, j; + uint32_t qn, tn; + int is_equal_f, is_strong_f; + int is_equal_b, is_strong_b, is_exist_b; + + kvec_t(uint64_t) edge_vector; + kv_init(edge_vector); + + for (i = 0; i < readNum; i++) + { + for (j = 0; j < (long long)paf[i].length; j++) + { + qn = Get_qn(paf[i].buffer[j]); + tn = Get_tn(paf[i].buffer[j]); + T_edges++; + + is_equal_f = paf[i].buffer[j].el; + is_strong_f = paf[i].buffer[j].ml; + + is_exist_b = get_specific_overlap(&(paf[tn]), tn, qn); + if(is_exist_b == -1) + { + is_exist_b = get_specific_overlap(&(rev_paf[tn]), tn, qn); + if(is_exist_b != -1) + { + T_Single_Dir_Edges_0++; + kv_push(uint64_t, edge_vector, qn); + kv_push(uint64_t, edge_vector, tn); + ///related_overlaps += paf[qn].length + rev_paf[qn].length + paf[tn].length + rev_paf[tn].length; + // fprintf(stderr, "%.*s(%d) ---(+)--> %.*s(%d), Len: %d\n", + // Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), qn, + // Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, + // Get_qe(paf[i].buffer[j]) - Get_qs(paf[i].buffer[j])); + + // fprintf(stderr, "%.*s(%d) ---(-)--> %.*s(%d), Len: %d\n\n", + // Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, + // Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), qn, + // Get_qe(rev_paf[tn].buffer[is_exist_b]) - Get_qs(rev_paf[tn].buffer[is_exist_b])); + } + else + { + T_Single_Dir_Edges_1++; + if(Get_qe(paf[i].buffer[j]) - Get_qs(paf[i].buffer[j]) >= 1000) + { + T_Single_Dir_Edges_1_1000++; + // fprintf(stderr, "%.*s(%d) ---(%d)--> %.*s(%d), Len: %d\n\n", + // Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), qn, + // is_strong_f, + // Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, + // Get_qe(paf[i].buffer[j]) - Get_qs(paf[i].buffer[j])); + } + } + + related_reads = related_reads + 2; + } + else + { + is_equal_b = paf[tn].buffer[is_exist_b].el; + is_strong_b = paf[tn].buffer[is_exist_b].ml; + + if(is_equal_f != is_equal_b) + { + T_Conflict_Equal_Edges++; + + // fprintf(stderr, "%.*s(%d) ---(%d)--> %.*s(%d), Len: %d\n", + // Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), qn, + // is_equal_f, + // Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, + // Get_qe(paf[i].buffer[j]) - Get_qs(paf[i].buffer[j])); + + // fprintf(stderr, "%.*s(%d) ---(%d)--> %.*s(%d), Len: %d\n\n", + // Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, + // is_equal_b, + // Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), qn, + // Get_qe(paf[tn].buffer[is_exist_b]) - Get_qs(paf[tn].buffer[is_exist_b])); + } + + if(is_strong_f != is_strong_b) + { + T_Conflict_Strong_Edges++; + // fprintf(stderr, "%.*s(%d) ---(%d)--> %.*s(%d), Len: %d\n", + // Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), qn, + // is_strong_f, + // Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, + // Get_qe(paf[i].buffer[j]) - Get_qs(paf[i].buffer[j])); + + // fprintf(stderr, "%.*s(%d) ---(%d)--> %.*s(%d), Len: %d\n\n", + // Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, + // is_strong_b, + // Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), qn, + // Get_qe(paf[tn].buffer[is_exist_b]) - Get_qs(paf[tn].buffer[is_exist_b])); + } + + if(is_equal_f != is_equal_b || is_strong_f != is_strong_b) + { + related_reads++; + } + } + } + } + + radix_sort_arch64(edge_vector.a, edge_vector.a + edge_vector.n); + uint64_t pre = (uint64_t)-1; + long long mn = 0; + for (i = 0; i < (long long)edge_vector.n; i++) + { + if(pre != edge_vector.a[i]) + { + mn++; + pre = edge_vector.a[i]; + related_overlaps += paf[pre].length + rev_paf[pre].length; + } + + if(i>0 && edge_vector.a[i] < edge_vector.a[i-1]) fprintf(stderr, "hehe\n"); + } + + + + fprintf(stderr, "****************statistic for abnormal overlaps****************\n"); + fprintf(stderr, "overlaps #: %lld\n", T_edges); + fprintf(stderr, "one direction overlaps (different phasing)#: %lld\n", T_Single_Dir_Edges_0); + fprintf(stderr, "one direction overlaps (missing)#: %lld\n", T_Single_Dir_Edges_1); + fprintf(stderr, "one direction overlaps (missing) >= 1000#: %lld\n", T_Single_Dir_Edges_1_1000); + fprintf(stderr, "conflict strong/weak overlaps #: %lld\n", T_Conflict_Strong_Edges); + fprintf(stderr, "conflict exact/inexact overlaps #: %lld\n", T_Conflict_Equal_Edges); + fprintf(stderr, "related_reads #: %lld/%lld\n", related_reads, mn); + fprintf(stderr, "related_overlaps #: %lld\n", related_overlaps); + fprintf(stderr, "****************statistic for abnormal overlaps****************\n"); + + fprintf(stderr, "[M::%s] took %0.2fs\n\n", __func__, Get_T()-startTime); + + kv_destroy(edge_vector); +} + +///if we don't have this function, we just simply remove all one-direction edges +///by utilizing this function, some one-direction edges can be recovered as two-direction edges +///trio does not influence this function +void try_rescue_overlaps(ma_hit_t_alloc* paf, ma_hit_t_alloc* rev, uint64_t rn, uint64_t rescue_threshold, uint32_t is_del) +{ + double startTime = Get_T(); + int64_t revises = 0, dd, dp, old_dp, start, max_dp, m; uint32_t qn, tn, qs, qe; uint64_t ff, i, j; ma_sub_t max_interval; + kvec_t(uint64_t) ev; kv_init(ev); + kvec_t(uint64_t) evi; kv_init(evi); + kvec_t(uint32_t) b; kv_init(b); + + for (i = 0; i < rn; i++) { + ev.n = evi.n = 0; + for (j = 0; j < rev[i].length; j++) { + if(is_del && rev[i].buffer[j].del) continue; + qn = Get_qn(rev[i].buffer[j]); tn = Get_tn(rev[i].buffer[j]); + dd = get_specific_overlap(&(paf[tn]), tn, qn); + if((dd != -1) && ((!is_del) || (paf[tn].buffer[dd].del == 0))) { + ff = tn; ff <<= 32; ff |= (uint64_t)(dd); + kv_push(uint64_t, ev, ff); kv_push(uint64_t, evi, j); + } + } + + ///based on qn, all edges at edge_vector/edge_vector_index come from different haplotype + ///but at another direction, all these edges come from the same haplotype + //here we want to recover these edges + if(evi.n >= rescue_threshold) { + kv_resize(uint32_t, b, evi.n); b.n = 0; + for (j = 0; j < evi.n; j++) { + qs = Get_qs(rev[i].buffer[evi.a[j]]); + qe = Get_qe(rev[i].buffer[evi.a[j]]); + kv_push(uint32_t, b, qs<<1); + kv_push(uint32_t, b, qe<<1|1); + } + + ks_introsort_uint32_t(b.n, b.a); + dp = 0, start = 0, max_dp = 0; + max_interval.s = max_interval.e = 0; + for (j = 0, dp = 0; j < b.n; ++j) { + old_dp = dp; + ///if a[j] is qe + if (b.a[j]&1) --dp; + else ++dp; + + if(old_dp < dp) {///b.a[j] is qs + ///case 2, a[j] is qs + //here should use dp >= max_dp, instead of dp > max_dp + if(dp >= max_dp) { + start = b.a[j]>>1; + max_dp = dp; + } + } else if (old_dp > dp) {///old_dp > min_dp, b.a[j] is qe + if(old_dp == max_dp) { + max_interval.s = start; + max_interval.e = b.a[j]>>1; + } + } + } + + if(((uint64_t)max_dp) >= rescue_threshold) { + m = 0; + for (j = 0; j < evi.n; j++) { + qs = Get_qs(rev[i].buffer[evi.a[j]]); + qe = Get_qe(rev[i].buffer[evi.a[j]]); + if(qs <= max_interval.s && qe >= max_interval.e) { + evi.a[m] = evi.a[j]; ev.a[m] = ev.a[j]; m++; + } + } + evi.n = ev.n = m; + + ///the read itself do not have these overlaps, but all related reads have + ///we need to remove all overlaps from rev_paf[i], and then add all overlaps to paf[i] + remove_overlaps(&(rev[i]), evi.a, evi.n); + add_overlaps_from_different_sources(paf, &(paf[i]), ev.a, ev.n); + revises = revises + ev.n; + } + } + } + + + kv_destroy(ev); kv_destroy(evi); kv_destroy(b); + if(VERBOSE >= 1) { + fprintf(stderr, "[M::%s] took %0.2fs, rescue edges #: %ld\n\n", __func__, Get_T()-startTime, revises); + } + +} + + + +long long get_coverage(ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, uint64_t n_read) +{ + uint64_t i, j; + ma_hit_t *h; + long long R_bases = 0, C_bases = 0; + for (i = 0; i < n_read; ++i) + { + R_bases += coverage_cut[i].e - coverage_cut[i].s; + for (j = 0; j < (uint64_t)(sources[i].length); j++) + { + h = &(sources[i].buffer[j]); + C_bases += Get_qe((*h)) - Get_qs((*h)); + } + } + + return C_bases/R_bases; +} + + +void pre_clean(ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, asg_t *sg, uint32_t pop_s_node) +{ + int tri_flag = 0; + while(1) + { + tri_flag = 0; + ///remove very simple circle + tri_flag += asg_arc_del_simple_circle_untig(sources, coverage_cut, sg, 100, 0); + + ///remove isoloated single read + if(pop_s_node) + { + tri_flag += asg_arc_del_single_node_directly(sg, asm_opt.max_short_tip, sources);///remove very small bubbles + } + + // if ((!ha_opt_triobin(&asm_opt))&&(!ha_opt_hic(&asm_opt))) + // { + // tri_flag += asg_arc_del_triangular_advance(sg, bubble_dist); + // ///remove the cross at the bubble carefully, just remove inexact cross + // tri_flag += asg_arc_del_cross_bubble(sg, bubble_dist); + // } + // tri_flag += asg_arc_del_single_node_directly(sg, asm_opt.max_short_tip, sources); + + if(tri_flag == 0) + { + break; + } + } +} + + +void init_R_to_U(R_to_U* x, uint64_t len) +{ + x->len = len; + CALLOC(x->index, x->len); + x->is_het = NULL; +} + +void destory_R_to_U(R_to_U* x) +{ + free(x->index); +} + +void set_R_to_U(R_to_U* x, uint32_t rID, uint32_t uID, uint32_t is_Unitig, uint8_t* flag) +{ + if(flag && (*flag) == FAKE_LABLE) return; + + if(rID >= x->len) + { + x->index = (uint32_t*)realloc(x->index, (rID + 1)*sizeof(uint32_t)); + memset(x->index + x->len, -1, sizeof(uint32_t)*((rID + 1) - x->len)); + x->len = rID + 1; + } + + x->index[rID] = uID & (uint32_t)(0x7fffffff); + x->index[rID] = x->index[rID] | (uint32_t)(is_Unitig<<31); +} + + +void get_R_to_U(R_to_U* x, uint32_t rID, uint32_t* uID, uint32_t* is_Unitig) +{ + if(rID >= x->len || (x->index[rID] == (uint32_t)(-1))) + { + (*uID) = (uint32_t)-1; + (*is_Unitig) = (uint32_t)-1; + return; + } + + (*uID) = x->index[rID] & (uint32_t)(0x7fffffff); + (*is_Unitig) = (x->index[rID]>>31); +} + +void transfor_R_to_U(R_to_U* x) +{ + uint64_t i = 0; + uint32_t rID, uID, is_Unitig; + for (i = 0; i < x->len; i++) + { + rID = i; + get_R_to_U(x, rID, &uID, &is_Unitig); + if(uID == (uint32_t)-1) continue; + if(is_Unitig == 1) continue; + + + ///here i/rID is contained in uID + rID = uID; + while (1) + { + get_R_to_U(x, rID, &uID, &is_Unitig); + if(uID == (uint32_t)-1) break; + if(is_Unitig == 1) break; + rID = uID; + } + + set_R_to_U(x, i, rID, 0, NULL); + } + + + /** + for (i = 0; i < x->len; i++) + { + rID = i; + get_R_to_U(x, rID, &uID, &is_Unitig); + if(uID == (uint32_t)-1) continue; + if(is_Unitig == 1) continue; + ///here i/rID is contained in uID + rID = uID; + get_R_to_U(x, rID, &uID, &is_Unitig); + if(uID != (uint32_t)-1) + { + fprintf(stderr, "ERROR\n"); + } + } + **/ + +} + + + +void asg_delete_node_by_trio(asg_t* sg, uint8_t flag) +{ + uint32_t v, n_vtx = sg->n_seq; + for (v = 0; v < n_vtx; ++v) + { + if (sg->seq[v].del) continue; + if (R_INF.trio_flag[v] == AMBIGU) continue; + if(R_INF.trio_flag[v] != flag) asg_seq_del(sg, v); + } + asg_cleanup(sg); +} + + + +void renew_graph_init(ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, asg_t *sg, ma_sub_t *coverage_cut, R_to_U* ruIndex, uint64_t n_read) +{ + if(sg != NULL) asg_destroy(sg); + sg = NULL; + + if(coverage_cut != NULL) free(coverage_cut); + coverage_cut = NULL; + + memset(ruIndex->index, -1, sizeof(uint32_t)*(ruIndex->len)); + + + uint64_t i = 0, j = 0; + for (i = 0; i < n_read; i++) { + for (j = 0; j < sources[i].length; j++) { + sources[i].buffer[j].del = 0; + } + + for (j = 0; j < reverse_sources[i].length; j++) { + reverse_sources[i].buffer[j].del = 0; + } + } +} + + + + +inline uint32_t get_num_edges2existing_nodes_advance(ma_ug_t *ug, asg_t *g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, uint32_t* oLen, uint32_t* skip_uId, uint32_t skip_uId_n, uint32_t ignore_trio_flag) +{ + (*oLen) = 0; + uint32_t qn = query>>1; + int32_t r; + asg_arc_t t; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + ma_hit_t_alloc* x = &(sources[qn]); + uint32_t i, k, occ = 0, uId, is_Unitig, v, w; + + uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; + if(ignore_trio_flag == 0) + { + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + } + + + + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + ///sq has already been removed + ///st must not be removed + ///g-seq must not be removed + if(st->del || g->seq[Get_tn(*h)].del) continue; + if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + + ///if it is a contained read, skip + if(r < 0) continue; + + if((t.ul>>32) != query) continue; + get_R_to_U(ruIndex, t.v>>1, &uId, &is_Unitig); + /****************************may have bugs********************************/ + if(uId == (uint32_t)-1 || is_Unitig == 0) continue; + /****************************may have bugs********************************/ + for (k = 0; k < skip_uId_n; k++) + { + if(uId == skip_uId[k]) break; + } + if(k != skip_uId_n) continue; + // if(uId == skip_uId1) continue; + // if(uId == skip_uId2) continue; + /****************************may have bugs********************************/ + if(ug->g->seq[uId].del) continue; + /****************************may have bugs********************************/ + + if((t.v != ug->u.a[uId].start) + && + (t.v != ug->u.a[uId].end)) + { + continue; + } + /**********for debug*************/ + if(t.v == ug->u.a[uId].start) + { + ///v = uId<<1; + v = (uId<<1)^1; + } + + if(t.v == ug->u.a[uId].end) + { + ///v = (uId<<1)^1; + v = uId<<1; + } + + if(get_real_length(ug->g, v, NULL)==1) + { + get_real_length(ug->g, v, &w); + if(get_real_length(ug->g, w^1, NULL)==1) + { + continue; + } + } + /**********for debug*************/ + + occ++; + (*oLen) += t.ol; + } + + return occ; +} + + +inline uint32_t get_num_edges2existing_nodes_advance_by_broken_bub(ma_ug_t *ug, asg_t *g, +ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, uint8_t* expect_vis, +int max_hang, int min_ovlp, uint32_t query, uint32_t* oLen, uint8_t* utg_vis, +uint32_t ignore_trio_flag) +{ + (*oLen) = 0; + uint32_t qn = query>>1, is_first = 1;; + int32_t r; + asg_arc_t t; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + ma_hit_t_alloc* x = &(sources[qn]); + uint32_t i, occ = 0, uId, is_Unitig; + + uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; + if(ignore_trio_flag == 0) + { + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + } + + + + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + ///sq has already been removed + ///st must not be removed + ///g-seq must not be removed + if(st->del || g->seq[Get_tn(*h)].del) continue; + if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + + ///if it is a contained read, skip + if(r < 0) continue; + + if((t.ul>>32) != query) continue; + get_R_to_U(ruIndex, t.v>>1, &uId, &is_Unitig); + if(uId == (uint32_t)-1 || is_Unitig == 0 || ug->g->seq[uId].del) continue; + if(expect_vis[t.v>>1] == 0) continue; + + if(is_first && utg_vis) memset(utg_vis, 0, ug->g->n_seq); + if(utg_vis == NULL || (utg_vis && utg_vis[uId] == 0)) occ++; + ////fprintf(stderr, "found-utg%.6ul, occ: %u\n", uId+1, occ); + if(utg_vis) utg_vis[uId] = 1; + + (*oLen) += t.ol; + is_first = 0; + } + + return occ; +} + + + +inline uint32_t get_edge2existing_node_advance(ma_ug_t *ug, asg_t *g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, uint32_t* skip_uId, uint32_t skip_uId_n, +uint32_t* index, asg_arc_t* t, uint32_t ignore_trio_flag) +{ + uint32_t qn = query>>1, uId, is_Unitig, v, w, k; + int32_t r; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + ma_hit_t_alloc* x = &(sources[qn]); + + uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; + if(ignore_trio_flag == 0) + { + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + } + + + + for (; (*index) < x->length; (*index)++) + { + h = &(x->buffer[(*index)]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + ///sq has already been removed + ///st must not be removed + ///g-seq must not be removed + if(st->del || g->seq[Get_tn(*h)].del) continue; + if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, t); + + ///if it is a contained read, skip + if(r < 0) continue; + + if((t->ul>>32) != query) continue; + get_R_to_U(ruIndex, t->v>>1, &uId, &is_Unitig); + /****************************may have bugs********************************/ + if(uId == (uint32_t)-1 || is_Unitig == 0) continue; + /****************************may have bugs********************************/ + for (k = 0; k < skip_uId_n; k++) + { + if(uId == skip_uId[k]) break; + } + if(k != skip_uId_n) continue; + // if(uId == skip_uId1) continue; + // if(uId == skip_uId2) continue; + /****************************may have bugs********************************/ + if(ug->g->seq[uId].del) continue; + /****************************may have bugs********************************/ + + if((t->v != ug->u.a[uId].start) + && + (t->v != ug->u.a[uId].end)) + { + continue; + } + + /**********for debug*************/ + if(t->v == ug->u.a[uId].start) + { + ///v = uId<<1; + v = (uId<<1)^1; + } + + if(t->v == ug->u.a[uId].end) + { + ///v = (uId<<1)^1; + v = uId<<1; + } + + if(get_real_length(ug->g, v, NULL)==1) + { + get_real_length(ug->g, v, &w); + if(get_real_length(ug->g, w^1, NULL)==1) + { + continue; + } + } + /**********for debug*************/ + + (*index)++; + return 1; + } + + return 0; +} + + +inline uint32_t get_edge2existing_node_advance_by_broken_bub(ma_ug_t *ug, asg_t *g, +ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, uint8_t* expect_vis, +int max_hang, int min_ovlp, uint32_t query, uint32_t* index, asg_arc_t* t, +uint32_t ignore_trio_flag) +{ + uint32_t qn = query>>1, uId, is_Unitig; + int32_t r; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + ma_hit_t_alloc* x = &(sources[qn]); + + uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; + if(ignore_trio_flag == 0) + { + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + } + + + + for (; (*index) < x->length; (*index)++) + { + h = &(x->buffer[(*index)]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + ///sq has already been removed + ///st must not be removed + ///g-seq must not be removed + if(st->del || g->seq[Get_tn(*h)].del) continue; + if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, t); + + ///if it is a contained read, skip + if(r < 0) continue; + + if((t->ul>>32) != query) continue; + get_R_to_U(ruIndex, t->v>>1, &uId, &is_Unitig); + if(uId == (uint32_t)-1 || is_Unitig == 0 || ug->g->seq[uId].del) continue; + if(expect_vis[t->v>>1] == 0) continue; + + (*index)++; + return 1; + } + + return 0; +} + + + +inline uint32_t get_num_edges2existing_nodes(ma_ug_t *ug, asg_t *g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, uint32_t* oLen, +uint32_t skip_uId1, uint32_t skip_uId2) +{ + (*oLen) = 0; + uint32_t qn = query>>1; + int32_t r; + asg_arc_t t; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + ma_hit_t_alloc* x = &(sources[qn]); + uint32_t i, occ = 0, uId, is_Unitig, v, w; + + + uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + + + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + ///sq has already been removed + ///st must not be removed + ///g-seq must not be removed + if(st->del || g->seq[Get_tn(*h)].del) continue; + if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + + ///if it is a contained read, skip + if(r < 0) continue; + + if((t.ul>>32) != query) continue; + get_R_to_U(ruIndex, t.v>>1, &uId, &is_Unitig); + /****************************may have bugs********************************/ + if(uId == (uint32_t)-1 || is_Unitig == 0) continue; + /****************************may have bugs********************************/ + if(uId == skip_uId1) continue; + if(uId == skip_uId2) continue; + /****************************may have bugs********************************/ + if(ug->g->seq[uId].del) continue; + /****************************may have bugs********************************/ + + if((t.v != ug->u.a[uId].start) + && + (t.v != ug->u.a[uId].end)) + { + continue; + } + /**********for debug*************/ + if(t.v == ug->u.a[uId].start) + { + ///v = uId<<1; + v = (uId<<1)^1; + } + + if(t.v == ug->u.a[uId].end) + { + ///v = (uId<<1)^1; + v = uId<<1; + } + + if(get_real_length(ug->g, v, NULL)==1) + { + get_real_length(ug->g, v, &w); + if(get_real_length(ug->g, w^1, NULL)==1) + { + continue; + } + } + /**********for debug*************/ + + occ++; + (*oLen) += t.ol; + } + + return occ; +} + + +inline uint32_t get_edge2existing_node(ma_ug_t *ug, asg_t *g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, uint32_t skip_uId1, uint32_t skip_uId2, +uint32_t* index, asg_arc_t* t) +{ + uint32_t qn = query>>1, uId, is_Unitig, v, w; + int32_t r; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + ma_hit_t_alloc* x = &(sources[qn]); + + uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + + + for (; (*index) < x->length; (*index)++) + { + h = &(x->buffer[(*index)]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + ///sq has already been removed + ///st must not be removed + ///g-seq must not be removed + if(st->del || g->seq[Get_tn(*h)].del) continue; + if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, t); + + ///if it is a contained read, skip + if(r < 0) continue; + + if((t->ul>>32) != query) continue; + get_R_to_U(ruIndex, t->v>>1, &uId, &is_Unitig); + /****************************may have bugs********************************/ + if(uId == (uint32_t)-1 || is_Unitig == 0) continue; + /****************************may have bugs********************************/ + if(uId == skip_uId1) continue; + if(uId == skip_uId2) continue; + /****************************may have bugs********************************/ + if(ug->g->seq[uId].del) continue; + /****************************may have bugs********************************/ + + if((t->v != ug->u.a[uId].start) + && + (t->v != ug->u.a[uId].end)) + { + continue; + } + + /**********for debug*************/ + if(t->v == ug->u.a[uId].start) + { + ///v = uId<<1; + v = (uId<<1)^1; + } + + if(t->v == ug->u.a[uId].end) + { + ///v = (uId<<1)^1; + v = uId<<1; + } + + if(get_real_length(ug->g, v, NULL)==1) + { + get_real_length(ug->g, v, &w); + if(get_real_length(ug->g, w^1, NULL)==1) + { + continue; + } + } + /**********for debug*************/ + + (*index)++; + return 1; + } + + return 0; +} + + + +uint32_t get_edge_from_source(ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, uint32_t target, asg_arc_t* t) +{ + uint32_t qn = query>>1, i; + int32_t r; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + ma_hit_t_alloc* x = &(sources[qn]); + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, t); + + ///if it is a contained read, skip + if(r < 0) continue; + + if((t->ul>>32) != query) continue; + if(t->v != target) continue; + + return 1; + } + + return 0; +} + +void append_rId_to_Unitig(asg_t *r_g, ma_ug_t* ug, uint32_t uId, uint32_t rId, +ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp) +{ + asg_arc_t t; + t.ul = (uint64_t)-1; + ma_utg_t *nsu = &(ug->u.a[uId>>1]); + uint32_t l, i, beg, end; + + if(nsu->m < (nsu->n+1)) + { + nsu->m = nsu->n+1; + nsu->a = (uint64_t*)realloc(nsu->a, nsu->m*sizeof(uint64_t)); + } + + if((uId&1) == 0) + { + beg = nsu->end^1; + end = rId; + } + + if((uId&1) == 1) + { + beg = rId^1; + end = nsu->start; + } + + ///t is the edge that from beg to end + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, beg, + end, &t); + + ///add rId to the end of nsu + if((uId&1) == 0) + { + nsu->len -= (uint32_t)nsu->a[nsu->n-1]; + + l = r_g->seq[rId>>1].len; + nsu->a[nsu->n] = rId; + nsu->a[nsu->n] <<=32; + nsu->a[nsu->n] = nsu->a[nsu->n] | (uint64_t)(l); + + l = asg_arc_len(t); + nsu->a[nsu->n-1] = nsu->a[nsu->n-1]>>32; + nsu->a[nsu->n-1] = nsu->a[nsu->n-1]<<32; + nsu->a[nsu->n-1] = nsu->a[nsu->n-1] | (uint64_t)(l); + + nsu->len = nsu->len + (uint32_t)nsu->a[nsu->n-1] + (uint32_t)nsu->a[nsu->n]; + nsu->end = rId^1; + + nsu->n++; + } + + ///add rId to the start of nsu + if((uId&1) == 1) + { + rId = rId^1; + for(i = nsu->n; i >= 1; i--) + { + nsu->a[i] = nsu->a[i-1]; + } + + l = asg_arc_len(t); + nsu->a[0] = rId; + nsu->a[0] = nsu->a[0]<<32; + nsu->a[0] = nsu->a[0] | (uint64_t)(l); + nsu->len = nsu->len + (uint32_t)nsu->a[0]; + nsu->start = rId; + + nsu->n++; + } + + + set_R_to_U(ruIndex, rId>>1, uId>>1, 1, &(r_g->seq[rId>>1].c)); + + + + + /*************************just for debug**************************/ + uint32_t v, totalLen = 0; + v = (uint64_t)(nsu->a[0])>>32; + if(nsu->start != UINT32_MAX && nsu->start != v) fprintf(stderr, "hehe\n"); + + v = (uint64_t)(nsu->a[nsu->n-1])>>32; + if(nsu->end != UINT32_MAX && nsu->end != (v^1)) fprintf(stderr, "haha\n"); + + for (i = 0; i < nsu->n; i++) + { + l = (uint32_t)(nsu->a[i]); + totalLen = totalLen + l; + } + if(totalLen != nsu->len) fprintf(stderr, "xxxx\n"); + + ////fprintf(stderr, "utg%.6dl, dir: %u\n", uId+1, uId&1); + /*************************just for debug**************************/ + +} + + + + +void lable_all_bubbles(asg_t *r_g, bub_label_t* b_mask_t) +{ + ///must have this line, otherwise asg_arc_identify_simple_bubbles_multi will be wrong + asg_cleanup(r_g); + asg_arc_identify_simple_bubbles_multi(r_g, b_mask_t, 0); +} + + +void drop_inexact_edegs_at_bubbles(asg_t *r_g, bub_label_t* b_mask_t, uint64_t bubble_dist) +{ + asg_arc_identify_simple_bubbles_multi(r_g, b_mask_t, 0); + + uint32_t v, k, i, n_vtx = r_g->n_seq * 2, nv, flag, n_reduce = 0; + uint64_t oLen; + asg_arc_t *av = NULL; + + if (!r_g->is_symm) asg_symm(r_g); + + buf_t b; + memset(&b, 0, sizeof(buf_t)); + + kvec_t(uint64_t) e; + kv_init(e); + + b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + for (v = 0; v < n_vtx; ++v) + { + nv = asg_arc_n(r_g, v); + if(r_g->seq[v>>1].del) continue; + if(r_g->seq_vis[v] != 0) continue; + if(nv < 2) continue; + + + ///if this is a bubble + if(asg_bub_finder_without_del_advance(r_g, v, bubble_dist, &b) == 1) + { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (i = 0; i < b.b.n; i++) + { + if(b.b.a[i] == v) continue; + //note b.b include end, does not include beg + if(b.b.a[i] == b.S.a[0]) + { + b.b.a[i] = b.b.a[i]^1; + continue; + } + + r_g->seq_vis[b.b.a[i]] = 2; + r_g->seq_vis[b.b.a[i]^1] = 2; + } + + r_g->seq_vis[v] = 2; + r_g->seq_vis[b.S.a[0]^1] = 2; + + + //note b.b include end, does not include beg + //so push beg into b.b + kv_push(uint32_t, b.b, v); + for (i = 0; i < b.b.n; i++) + { + nv = asg_arc_n(r_g, b.b.a[i]); + if(nv <= 1) continue; + av = asg_arc_a(r_g, b.b.a[i]); + e.n = 0; + flag = 0; + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].el) + { + flag = 1; + continue; + } + oLen = av[k].ol; + oLen = oLen << 32; + oLen = oLen | (uint64_t)(k); + kv_push(uint64_t, e, oLen); + } + + if(flag == 0 || e.n == 0) continue; + + if(e.n>1) radix_sort_arch64(e.a, e.a + e.n); + + for (k = 0; k < e.n; k++) + { + if(get_real_length(r_g, av[(uint32_t)e.a[k]].v^1, NULL)<=1) continue; + av[(uint32_t)e.a[k]].del = 1; + asg_arc_del(r_g, av[(uint32_t)e.a[k]].v^1, av[(uint32_t)e.a[k]].ul>>32^1, 1); + n_reduce++; + } + + } + } + } + + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + kv_destroy(e); + if(n_reduce > 0) asg_cleanup(r_g); +} + + +uint32_t get_corresponding_uId(ma_ug_t *ug, R_to_U* ruIndex, uint32_t t) +{ + uint32_t w, uId, is_Unitig; + get_R_to_U(ruIndex, t>>1, &uId, &is_Unitig); + /****************************may have bugs********************************/ + if(uId == ((uint32_t)(-1)) || is_Unitig == 0) return ((uint32_t)(-1)); + if(ug->g->seq[uId].del) return ((uint32_t)(-1)); + /****************************may have bugs********************************/ + w = (uint32_t)-1; + if(t == ug->u.a[uId].start) w = uId<<1; + if(t == ug->u.a[uId].end) w = (uId<<1)^1; + return w; +} + +void minor_transitive_reduction(ma_ug_t *ug, R_to_U* ruIndex, asg_arc_t* rbub_edges, uint32_t num) +{ + asg_t* nsg = ug->g; + uint32_t i, j, k, uId, nv, w; + asg_arc_t* t = NULL; + asg_arc_t* p = NULL; + asg_arc_t *av = NULL; + ///here all edges from v are saved in rbub_edges + ///for edges already in graph, need to check del + ///but for edges in rbub_edges, don't check del + for (i = 0; i < num; i++) + { + t = &rbub_edges[i]; + ///if(t->del) continue; + uId = get_corresponding_uId(ug, ruIndex, t->v); + if(uId == ((uint32_t)(-1))) continue; + + nv = asg_arc_n(nsg, uId); + av = asg_arc_a(nsg, uId); + for (j = 0; j < nv; j++) + { + if(av[j].del) continue; + w = av[j].v; + + ///note w is the unitig ID + for (k = 0; k < num; k++) + { + p = &rbub_edges[k]; + ///if(p->del) continue; + ///this line is not necessary at all + if(k==i) continue; + ///w is the unitig ID, p->v is the read ID + if(get_corresponding_uId(ug, ruIndex, p->v) == w) p->del = 1; + } + } + } +} + + + + +///find contained read with longest overlap +ma_hit_t* get_best_contained_read(ma_ug_t *ug, asg_t *r_g, ma_hit_t_alloc* sources, +ma_sub_t *coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, +uint32_t ignore_trio_flag) +{ + uint32_t qn = query>>1; + int32_t r; + asg_arc_t t; + ma_hit_t *h = NULL, *return_h = NULL; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + ma_hit_t_alloc* x = &(sources[qn]); + uint32_t i, is_Unitig, contain_rId, contain_uId; + uint32_t maxOlen = 0; + asg_t* nsg = ug->g; + + uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; + if(ignore_trio_flag == 0) + { + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + } + + //scan all edges of qn + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + ///just need deleted edges + ///sq might be deleted or not + if(!st->del) continue; + if(!h->del) continue; + if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; + + ///tn must be contained in another existing read + get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); + if(contain_rId == (uint32_t)-1 || is_Unitig == 1) continue; + if(r_g->seq[contain_rId].del) continue; + + get_R_to_U(ruIndex, contain_rId, &contain_uId, &is_Unitig); + if(contain_uId == (uint32_t)-1 || is_Unitig != 1) continue; + if(nsg->seq[contain_uId].del) continue; + ///contain_uId must be a unitig + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + + ///if it is a contained read, skip + if(r < 0) continue; + + if((t.ul>>32) != query) continue; + + if(t.ol > maxOlen) + { + maxOlen = t.ol; + return_h = h; + } + } + + return return_h; +} + +///find contained read with longest overlap +ma_hit_t* get_best_cmk_read(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, uint32_t ignore_trio_flag, uint8_t *cmk) +{ + uint32_t qn = query>>1; int32_t r; + asg_arc_t t; ma_hit_t *h = NULL, *return_h = NULL; + ma_sub_t *sq = NULL; ma_sub_t *st = NULL; + ma_hit_t_alloc* x = &(sources[qn]); + uint32_t i, is_Unitig, contain_rId, maxOlen = 0; + uint32_t trio_flag = R_INF.trio_flag[qn], non_trio_flag = (uint32_t)-1; + + if(ignore_trio_flag == 0) { + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + } + + //scan all edges of qn + for (i = 0; i < x->length; i++) { + h = &(x->buffer[i]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + ///just need deleted edges + ///sq might be deleted or not + if((!st->del) || (!h->del) || (!rg->seq[Get_tn(*h)].del)) continue; + // if(cmk[Get_tn(*h)] != ((uint8_t)-1)) continue; + // if(cmk[Get_tn(*h)] == ((uint8_t)-1)) continue; + if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; + + ///tn must be contained in another existing read + get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); + if(is_Unitig == 1) continue; + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + + ///if it is a contained read, skip + if(r < 0) continue; + + if((t.ul>>32) != query) continue; + + if(t.ol > maxOlen) { + maxOlen = t.ol; + return_h = h; + } + } + + return return_h; +} + + + +int get_contained_reads_chain(ma_hit_t *h, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, ma_ug_t *ug, asg_t *r_g, int max_hang, int min_ovlp, uint32_t endRid, uint32_t uId, +kvec_t_u32_warp* chain_buffer, kvec_asg_arc_t_warp* chain_edges, uint32_t* return_ava_cur, +uint32_t* return_ava_ol, uint32_t* return_chainLen, uint32_t thresLen, uint32_t ignore_trio_flag) +{ + (*return_chainLen) = (*return_ava_cur) = (*return_ava_ol) = (uint32_t)-1; + uint32_t trio_flag, non_trio_flag = (uint32_t)-1, contain_rId, contain_uId, is_Unitig; + uint32_t chainLen = 0, ava_cur, test_oLen; + int ql, tl; + int32_t r; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + asg_arc_t t; + asg_t* nsg = ug->g; + chain_buffer->a.n = 0; + kv_push(uint32_t, chain_buffer->a, uId); + if(chain_edges) chain_edges->a.n = 0; + + + ///continue + ///need to update h, endRid, chainLen, chain_buffer and chain_edges + while (h) + { + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + trio_flag = R_INF.trio_flag[Get_qn(*h)]; + + ///don't want to edges between different haps + non_trio_flag = (uint32_t)-1; + if(ignore_trio_flag == 0) + { + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) break; + } + + ///just need deleted edges + ///sq might be deleted or not + if(!st->del) break; + if(!h->del) break; + + ///tn must be contained in another existing read + get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); + if(contain_rId == (uint32_t)-1 || is_Unitig == 1) break; + if(r_g->seq[contain_rId].del) break; + + get_R_to_U(ruIndex, contain_rId, &contain_uId, &is_Unitig); + if(contain_uId == (uint32_t)-1 || is_Unitig != 1) break; + if(nsg->seq[contain_uId].del) break; + ///contain_uId must be a unitig + + ql = sq->e - sq->s; tl = st->e - st->s; + r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + + ///if st is contained in sq, or vice verse, skip + if(r < 0) break; + + ///if sq and v are not in the same direction, skip + ///endRid is (t.ul>>32), and t.v is a contained read + if((t.ul>>32) != endRid) break; + + if(chain_edges) kv_push(asg_arc_t, chain_edges->a, t); + chainLen++; + kv_push(uint32_t, chain_buffer->a, contain_uId); + ///endRid is (t.ul>>32), and t.v is a contained read + ///find edges from t.v to existing unitigs + ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, sources, coverage_cut, ruIndex, + max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, + ignore_trio_flag); + //means find an aim + if(ava_cur > 0) + { + /** + //do nothing if the chainLen == 1 + if(chainLen > 1) + { + asg_arc_t t_max; + ma_hit_t_alloc* x = &(sources[(endRid>>1)]); + uint32_t ava_ol_max = 0, ava_max = 0, k; + for (k = 0; k < x->length; k++) + { + h = &(x->buffer[k]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + trio_flag = R_INF.trio_flag[Get_qn(*h)]; + + ///don't want to edges between different haps + non_trio_flag = (uint32_t)-1; + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; + + ///just need deleted edges + ///sq might be deleted or not + if(!st->del) continue; + if(!h->del) continue; + + ///tn must be contained in another existing read + get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); + if(contain_rId == (uint32_t)-1 || is_Unitig == 1) continue; + if(r_g->seq[contain_rId].del) continue; + + get_R_to_U(ruIndex, contain_rId, &contain_uId, &is_Unitig); + if(contain_uId == (uint32_t)-1 || is_Unitig != 1) continue; + if(nsg->seq[contain_uId].del) continue; + ///contain_uId must be a unitig + + ql = sq->e - sq->s; tl = st->e - st->s; + r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + + ///if st is contained in sq, or vice verse, skip + if(r < 0) continue; + + ///if sq and v are not in the same direction, skip + if((t.ul>>32) != endRid) continue; + + ///pop the last contain_uId + chain_buffer->a.n--; + kv_push(uint32_t, chain_buffer->a, contain_uId); + + ///note: t.v is a contained read + ///we need to find existing reads linked with w + ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, sources, coverage_cut, ruIndex, + max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, 1); + + if((ava_cur > ava_max) || (ava_cur == ava_max && test_oLen > ava_ol_max)) + { + ava_max = ava_cur; + ava_ol_max = test_oLen; + t_max = t; + } + } + + if(ava_max > 0) + { + ava_cur = ava_max; + test_oLen = ava_ol_max; + if(chain_edges) + { + //pop the last edge + chain_edges->a.n--; + kv_push(asg_arc_t, chain_edges->a, t_max); + } + } + else + { + break; + } + } + **/ + + (*return_ava_cur) = ava_cur; + (*return_ava_ol) = test_oLen; + (*return_chainLen) = chainLen; + h = NULL; + return 1; + } + + if(chainLen >= thresLen) break; + + ///endRid is (t.ul>>32), and t.v is a contained read + ///haven't found a existing unitig from t.v + ///check if t.v can link to a new contained read + endRid = t.v; + h = get_best_contained_read(ug, r_g, sources, coverage_cut, ruIndex, + max_hang, min_ovlp, endRid, ignore_trio_flag); + } + + return 0; +} + + +int get_chimeric_reads_chain(ma_hit_t *h, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, ma_ug_t *ug, asg_t *rg, int max_hang, int min_ovlp, uint32_t endRid, uint32_t uId, +kvec_t_u32_warp* chain_buffer, kvec_asg_arc_t_warp* chain_edges, uint32_t* return_ava_cur, +uint32_t* return_ava_ol, uint32_t* return_chainLen, uint32_t thresLen, uint32_t ignore_trio_flag, uint8_t *cmk) +{ + (*return_chainLen) = (*return_ava_cur) = (*return_ava_ol) = (uint32_t)-1; + uint32_t trio_flag, non_trio_flag = (uint32_t)-1, contain_rId, is_Unitig; + uint32_t chainLen = 0, ava_cur, test_oLen; int ql, tl; int32_t r; + ma_sub_t *sq = NULL; ma_sub_t *st = NULL; asg_arc_t t; + chain_buffer->a.n = 0; kv_push(uint32_t, chain_buffer->a, uId); + if(chain_edges) chain_edges->a.n = 0; + + + ///continue + ///need to update h, endRid, chainLen, chain_buffer and chain_edges + while (h) { + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + trio_flag = R_INF.trio_flag[Get_qn(*h)]; + + ///don't want to edges between different haps + non_trio_flag = (uint32_t)-1; + if(ignore_trio_flag == 0) { + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) break; + } + + ///just need deleted edges + ///sq might be deleted or not + if((!st->del) || (!h->del) || (!rg->seq[Get_tn(*h)].del)) break; + // if(cmk[Get_tn(*h)] != ((uint8_t)-1)) break; + // if(cmk[Get_tn(*h)] == ((uint8_t)-1)) break; + + ///tn must be contained in another existing read + get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); + if(is_Unitig == 1) break; + + ql = sq->e - sq->s; tl = st->e - st->s; + r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + + ///if st is contained in sq, or vice verse, skip + if(r < 0) break; + + ///if sq and v are not in the same direction, skip + ///endRid is (t.ul>>32), and t.v is a contained read + if((t.ul>>32) != endRid) break; + + if(chain_edges) kv_push(asg_arc_t, chain_edges->a, t); + chainLen++; + ///endRid is (t.ul>>32), and t.v is a contained read + ///find edges from t.v to existing unitigs + ///chain_buffer->a.n always be 1 + ava_cur = get_num_edges2existing_nodes_advance(ug, rg, sources, coverage_cut, ruIndex, max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, ignore_trio_flag); + //means find an aim + if(ava_cur > 0) { + (*return_ava_cur) = ava_cur; + (*return_ava_ol) = test_oLen; + (*return_chainLen) = chainLen; + h = NULL; + return 1; + } + + if(chainLen >= thresLen) break; + + ///endRid is (t.ul>>32), and t.v is a contained read + ///haven't found a existing unitig from t.v + ///check if t.v can link to a new contained read + endRid = t.v; + h = get_best_cmk_read(ug, rg, sources, coverage_cut, ruIndex, max_hang, min_ovlp, endRid, ignore_trio_flag, cmk); + } + + return 0; +} + + +int get_contained_reads_chain_by_broken_bub(ma_hit_t *h, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, ma_ug_t *ug, asg_t *r_g, int max_hang, int min_ovlp, uint32_t endRid, uint32_t uId, +kvec_asg_arc_t_warp* chain_edges, uint32_t* return_ava_cur, uint32_t* return_ava_ol, uint32_t* return_chainLen, +uint8_t* expect_vis, uint8_t* circle_vis, uint8_t* utg_vis, uint32_t thresLen, uint32_t ignore_trio_flag) +{ + (*return_chainLen) = (*return_ava_cur) = (*return_ava_ol) = (uint32_t)-1; + uint32_t trio_flag, non_trio_flag = (uint32_t)-1, contain_rId, contain_uId, is_Unitig, i; + uint32_t chainLen = 0, ava_cur, test_oLen; + int ql, tl; + int32_t r; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + asg_arc_t t; + asg_t* nsg = ug->g; + chain_edges->a.n = 0; + + + ///continue + ///need to update h, endRid, chainLen, chain_buffer and chain_edges + while (h) + { + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + trio_flag = R_INF.trio_flag[Get_qn(*h)]; + + ///don't want to edges between different haps + non_trio_flag = (uint32_t)-1; + if(ignore_trio_flag == 0) + { + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) break; + } + + ///just need deleted edges + ///sq might be deleted or not + if(!st->del) break; + if(!h->del) break; + + ///tn must be contained in another existing read + get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); + if(contain_rId == (uint32_t)-1 || is_Unitig == 1) break; + if(r_g->seq[contain_rId].del) break; + + get_R_to_U(ruIndex, contain_rId, &contain_uId, &is_Unitig); + if(contain_uId == (uint32_t)-1 || is_Unitig != 1) break; + if(nsg->seq[contain_uId].del) break; + ///contain_uId must be a unitig + + ql = sq->e - sq->s; tl = st->e - st->s; + r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + + ///if st is contained in sq, or vice verse, skip + if(r < 0) break; + + ///if sq and v are not in the same direction, skip + ///endRid is (t.ul>>32), and t.v is a contained read + if((t.ul>>32) != endRid) break; + + kv_push(asg_arc_t, chain_edges->a, t); + chainLen++; + + if(circle_vis[t.ul>>33] || circle_vis[t.v>>1]) break; + + circle_vis[t.ul>>33] = circle_vis[t.v>>1] = 1; + ///endRid is (t.ul>>32), and t.v is a contained read + ///find edges from t.v to existing unitigs + ava_cur = get_num_edges2existing_nodes_advance_by_broken_bub(ug, r_g, sources, + coverage_cut, ruIndex, expect_vis, max_hang, min_ovlp, t.v, &test_oLen, utg_vis, ignore_trio_flag); + //means find an aim + if(ava_cur > 0) + { + (*return_ava_cur) = ava_cur; + (*return_ava_ol) = test_oLen; + (*return_chainLen) = chainLen; + h = NULL; + for (i = 0; i < chain_edges->a.n; i++) + { + circle_vis[chain_edges->a.a[i].ul>>33] = 0; + circle_vis[chain_edges->a.a[i].v>>1] = 0; + } + return 1; + } + + ///if(chainLen >= thresLen) break; + + ///endRid is (t.ul>>32), and t.v is a contained read + ///haven't found a existing unitig from t.v + ///check if t.v can link to a new contained read + endRid = t.v; + h = get_best_contained_read(ug, r_g, sources, coverage_cut, ruIndex, + max_hang, min_ovlp, endRid, ignore_trio_flag); + } + + for (i = 0; i < chain_edges->a.n; i++) + { + circle_vis[chain_edges->a.a[i].ul>>33] = 0; + circle_vis[chain_edges->a.a[i].v>>1] = 0; + } + return 0; +} + +int get_chimeric_reads_chain_by_broken_bub(ma_hit_t *h, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, ma_ug_t *ug, asg_t *rg, int max_hang, int min_ovlp, uint32_t endRid, uint32_t uId, +kvec_asg_arc_t_warp* chain_edges, uint32_t* return_ava_cur, uint32_t* return_ava_ol, uint32_t* return_chainLen, +uint8_t* expect_vis, uint8_t* circle_vis, uint8_t* utg_vis, uint32_t thresLen, uint32_t ignore_trio_flag, uint8_t *cmk) +{ + (*return_chainLen) = (*return_ava_cur) = (*return_ava_ol) = (uint32_t)-1; + uint32_t trio_flag, non_trio_flag = (uint32_t)-1, contain_rId, is_Unitig, i; + uint32_t chainLen = 0, ava_cur, test_oLen; int ql, tl; int32_t r; ma_sub_t *sq = NULL; ma_sub_t *st = NULL; + asg_arc_t t; chain_edges->a.n = 0; + + ///need to update h, endRid, chainLen, chain_buffer and chain_edges + while (h) { + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + trio_flag = R_INF.trio_flag[Get_qn(*h)]; + + ///don't want to edges between different haps + non_trio_flag = (uint32_t)-1; + if(ignore_trio_flag == 0) { + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) break; + } + + ///just need deleted edges + ///sq might be deleted or not + if((!st->del) || (!h->del) || (!rg->seq[Get_tn(*h)].del)) break; + // if(cmk[Get_tn(*h)] != ((uint8_t)-1)) break; + // if(cmk[Get_tn(*h)] == ((uint8_t)-1)) break; + + ///tn must be contained in another existing read + get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); + if(is_Unitig == 1) break; + + ql = sq->e - sq->s; tl = st->e - st->s; + r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + + ///if st is contained in sq, or vice verse, skip + if(r < 0) break; + + ///if sq and v are not in the same direction, skip + ///endRid is (t.ul>>32), and t.v is a contained read + if((t.ul>>32) != endRid) break; + + kv_push(asg_arc_t, chain_edges->a, t); chainLen++; + + if(circle_vis[t.ul>>33] || circle_vis[t.v>>1]) break; + + circle_vis[t.ul>>33] = circle_vis[t.v>>1] = 1; + ///endRid is (t.ul>>32), and t.v is a contained read + ///find edges from t.v to existing unitigs + ava_cur = get_num_edges2existing_nodes_advance_by_broken_bub(ug, rg, sources, coverage_cut, ruIndex, expect_vis, max_hang, min_ovlp, t.v, &test_oLen, utg_vis, ignore_trio_flag); + //means find an aim + if(ava_cur > 0) { + (*return_ava_cur) = ava_cur; + (*return_ava_ol) = test_oLen; + (*return_chainLen) = chainLen; + h = NULL; + for (i = 0; i < chain_edges->a.n; i++) { + circle_vis[chain_edges->a.a[i].ul>>33] = 0; + circle_vis[chain_edges->a.a[i].v>>1] = 0; + } + return 1; + } + + ///if(chainLen >= thresLen) break; + + ///endRid is (t.ul>>32), and t.v is a contained read + ///haven't found a existing unitig from t.v + ///check if t.v can link to a new contained read + endRid = t.v; + h = get_best_cmk_read(ug, rg, sources, coverage_cut, ruIndex, max_hang, min_ovlp, endRid, ignore_trio_flag, cmk); + } + + for (i = 0; i < chain_edges->a.n; i++) { + circle_vis[chain_edges->a.a[i].ul>>33] = 0; + circle_vis[chain_edges->a.a[i].v>>1] = 0; + } + return 0; +} + + +///chainLenThres is used to avoid circle +void rescue_chimeric_reads_aggressive(ma_ug_t *i_ug, asg_t *rg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t chainLenThres, uint32_t is_bubble_check, uint32_t is_primary_check, kvec_asg_arc_t_warp* new_rtg_edges, +kvec_t_u32_warp* new_rtg_nodes, bub_label_t* b_mask_t, uint8_t *cmk) +{ + uint32_t n_vtx, v, k, contain_rId, is_Unitig, uId, rId, endRid, oLen, w, max_oLen, max_oLen_i = (uint32_t)-1; + uint32_t ava_max, ava_ol_max, ava_min_chain, ava_cur, ava_chainLen, test_oLen, is_update; + asg_t* nsg = NULL; ma_utg_t* nsu = NULL; asg_arc_t t, t_max, r_edge; t_max.v = t_max.ul = t.v = t.ul = (uint32_t)-1; + ma_hit_t *h = NULL, *h_max = NULL; ma_hit_t_alloc* x = NULL; ma_ug_t* ug = NULL; uint64_t a_nodes; + + kvec_t(asg_arc_t) new_edges; kv_init(new_edges); + kvec_t(asg_arc_t) rbub_edges; kv_init(rbub_edges); + kvec_t_u64_warp u_vecs; kv_init(u_vecs.a); + kvec_t_u32_warp chain_buffer; kv_init(chain_buffer.a); + kvec_asg_arc_t_warp chain_edges; kv_init(chain_edges.a); + + if(i_ug != NULL) { + ug = i_ug; + } else { + ug = ma_ug_gen(rg); + for (v = 0; v < ug->g->n_seq; v++) ug->g->seq[v].c = PRIMARY_LABLE; + } + nsg = ug->g; + + for (v = 0; v < nsg->n_seq; v++) { + uId = v; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsg->seq[v].del) continue; + if(is_primary_check && nsg->seq[v].c==ALTER_LABLE) continue; + for (k = 0; k < nsu->n; k++) { + rId = nsu->a[k]>>33; + set_R_to_U(ruIndex, rId, uId, 1, &(rg->seq[rId].c)); + } + } + + // fprintf(stderr, "-0-[M::%s]\tx->index[2300071]::%u\n", __func__, ruIndex->index[2300071]); + n_vtx = nsg->n_seq * 2; + for (v = 0; v < n_vtx; v++) { + uId = v>>1; + if(nsg->seq[uId].del) continue; + if(is_primary_check && nsg->seq[uId].c==ALTER_LABLE) continue; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsu->circ || nsu->start == UINT32_MAX || nsu->end == UINT32_MAX) continue; + if(get_real_length(nsg, v, NULL) != 0) continue; + + if(v&1) { + endRid = nsu->start^1; + } else { + endRid = nsu->end^1; + } + + ///x is the end read of a tip + ///find all overlap of x + x = &(sources[(endRid>>1)]); + ava_ol_max = ava_max = 0; ava_min_chain = (uint32_t)-1; + h_max = NULL; + for (k = 0; k < x->length; k++) { + ///h is the edge of endRid + h = &(x->buffer[k]); + ///means we found a contained read + if(get_chimeric_reads_chain(h, sources, coverage_cut, ruIndex, ug, rg, max_hang, min_ovlp, endRid, uId, &chain_buffer, NULL, &ava_cur, &test_oLen, &ava_chainLen, chainLenThres, 1, cmk)) { + is_update = 0; + if(ava_chainLen < ava_min_chain) { + is_update = 1; + } else if(ava_chainLen == ava_min_chain) { + if(ava_cur > ava_max) { + is_update = 1; + } else if(ava_cur == ava_max && test_oLen > ava_ol_max) { + is_update = 1; + } + } + + if(is_update) { + ava_min_chain = ava_chainLen; + ava_max = ava_cur; + ava_ol_max = test_oLen; + h_max = h; + } + } + } + + + + + + if(ava_max > 0) { + //get all edges between contained reads + get_chimeric_reads_chain(h_max, sources, coverage_cut, ruIndex, ug, rg, max_hang, min_ovlp, endRid, uId, &chain_buffer, &chain_edges, &ava_cur, &test_oLen, &ava_chainLen, chainLenThres, 1, cmk); + if(chain_edges.a.n < 1) continue; + ///the last read + t_max = chain_edges.a.a[chain_edges.a.n-1]; + + k = 0; rbub_edges.n = 0; + ///edges from the last contained read to other unitigs + while(get_edge2existing_node_advance(ug, rg, sources, coverage_cut, ruIndex, + max_hang, min_ovlp, t_max.v, chain_buffer.a.a, chain_buffer.a.n, &k, &r_edge, 1)) { + kv_push(asg_arc_t, rbub_edges, r_edge); + } + + ///need to do transitive reduction + ///note here is different to standard transitive reduction + minor_transitive_reduction(ug, ruIndex, rbub_edges.a, rbub_edges.n); + if(is_primary_check) { + max_oLen = 0; max_oLen_i = (uint32_t)-1; + for (k = 0; k < rbub_edges.n; k++) { + t = rbub_edges.a[k]; + if(t.del) continue; + if(t.ol > max_oLen) { + max_oLen = t.ol; + max_oLen_i = k; + } + } + + if(max_oLen_i == (uint32_t)-1) continue; + t = rbub_edges.a[max_oLen_i]; + w = get_corresponding_uId(ug, ruIndex, t.v); + if(w == ((uint32_t)(-1))) continue; + if(get_real_length(nsg, w^1, NULL)!=0) continue; + } + + //recover all contained reads + for (k = 0; k < chain_edges.a.n; k++) { + t_max = chain_edges.a.a[k]; + ///save all infor for reverting + get_R_to_U(ruIndex, t_max.v>>1, &contain_rId, &is_Unitig); + if((is_Unitig == 1) || (is_Unitig == ((uint32_t)-1))) contain_rId = ((uint32_t)-1);///shouldn't be possible + a_nodes=contain_rId; + a_nodes=a_nodes<<32; + a_nodes=a_nodes|((uint64_t)(t_max.v>>1)); + kv_push(uint64_t, u_vecs.a, a_nodes); + + + //(t_max.ul>>32)----->(t_max.v/r_edge.ul>>32)----->r_edge.v + //need to recover (t_max.v/r_edge.ul>>32), 1. set .del = 0 2. set ruIndex + rg->seq[t_max.v>>1].del = 0; + coverage_cut[t_max.v>>1].del = 0; + coverage_cut[t_max.v>>1].c = PRIMARY_LABLE; + //add recover to the end of the unitig + append_rId_to_Unitig(rg, ug, v, t_max.v, sources, coverage_cut, ruIndex, max_hang, min_ovlp); + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, (t_max.ul>>32), t_max.v, &t); + kv_push(asg_arc_t, new_edges, t); + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, (t_max.v^1), ((t_max.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); + } + + if(is_primary_check) { + t = rbub_edges.a[max_oLen_i]; + w = get_corresponding_uId(ug, ruIndex, t.v); + if(w == ((uint32_t)(-1))) continue; + kv_push(asg_arc_t, new_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); oLen = t.ol; + asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); + } else { + for (k = 0; k < rbub_edges.n; k++) { + t = rbub_edges.a[k]; + if(t.del) continue; + w = get_corresponding_uId(ug, ruIndex, t.v); + if(w == ((uint32_t)(-1))) continue; + + kv_push(asg_arc_t, new_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); + + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); + } + } + + } + } + + // fprintf(stderr, "-1-[M::%s]\tx->index[2300071]::%u\n", __func__, ruIndex->index[2300071]); + + asg_arc_t* p = NULL; + if(is_bubble_check) { + for (k = 0; k < new_edges.n; k++) { + p = asg_arc_pushp(rg); + *p = new_edges.a[k]; + } + + if(new_edges.n != 0) { + free(rg->idx); + rg->idx = 0; + rg->is_srt = 0; + asg_cleanup(rg); + } + + pre_clean(sources, coverage_cut, rg, 0); + + lable_all_bubbles(rg, b_mask_t); + + for (k = 0; k < new_edges.n; k++) { + v = new_edges.a[k].ul>>32; + w = new_edges.a[k].v; + + if(rg->seq[v>>1].del) continue; + if(rg->seq[w>>1].del) continue; + ///if this edge is at a bubble + if(rg->seq_vis[v]!=0 && rg->seq_vis[w^1]!=0) continue; + + asg_arc_del(rg, v, w, 1); + asg_arc_del(rg, w^1, v^1, 1); + } + asg_cleanup(rg); + // fprintf(stderr, "-2-[M::%s]\tx->index[2300071]::%u\n", __func__, ruIndex->index[2300071]); + + // w=max_contain_rId; w=w<<32; w=w|(t_max.v>>1); + // kv_push(uint64_t, u_vecs.a, w); + for (k = 0; k < u_vecs.a.n; k++) { + w = (uint32_t)u_vecs.a.a[k]; + w = w<<1; + if(!rg->seq[w>>1].del && get_real_length(rg, w, NULL)!=0) continue; + if(!rg->seq[w>>1].del && get_real_length(rg, (w^1), NULL)!=0) continue; + w=w>>1; + rg->seq[w].del = 1; + coverage_cut[w].del = 1; + if((u_vecs.a.a[k]>>32) == ((uint32_t)-1)) { + ruIndex->index[((uint32_t)(u_vecs.a.a[k]))] = (uint32_t)-1; + } else { + set_R_to_U(ruIndex, ((uint32_t)(u_vecs.a.a[k])), (u_vecs.a.a[k]>>32), 0, NULL); + } + } + + // fprintf(stderr, "-3-[M::%s]\tx->index[2300071]::%u\n", __func__, ruIndex->index[2300071]); + } + + ///actually we don't update sources + ///during the the primary_check, we need to recover everything for r_g, coverage_cut and ruIndex + if(is_primary_check) + { + ///don't remove nodes and edges + /** + for (k = 0; k < u_vecs.a.n; k++) + { + w = (uint32_t)u_vecs.a.a[k]; + r_g->seq[w].del = 1; + coverage_cut[w].del = 1; + set_R_to_U(ruIndex, ((uint32_t)(u_vecs.a.a[k])), (u_vecs.a.a[k]>>32), 0); + } + **/ + if(new_rtg_nodes) + { + for(k = 0; k < u_vecs.a.n; k++) + { + w = (uint32_t)u_vecs.a.a[k]; + kv_push(uint32_t, new_rtg_nodes->a, w); + } + } + + + for (k = 0; k < new_edges.n; k++) + { + p = asg_arc_pushp(rg); + *p = new_edges.a[k]; + if(new_rtg_edges) kv_push(asg_arc_t, new_rtg_edges->a, new_edges.a[k]); + } + + if(new_edges.n != 0) + { + free(rg->idx); + rg->idx = 0; + rg->is_srt = 0; + asg_cleanup(rg); + } + } + // fprintf(stderr, "-4-[M::%s]\tx->index[2300071]::%u\n", __func__, ruIndex->index[2300071]); + + for (v = 0; v < ruIndex->len; v++) + { + get_R_to_U(ruIndex, v, &uId, &is_Unitig); + if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; + } + // fprintf(stderr, "-5-[M::%s]\tx->index[2300071]::%u\n", __func__, ruIndex->index[2300071]); + + if(i_ug == NULL) ma_ug_destroy(ug); + kv_destroy(new_edges); + kv_destroy(rbub_edges); + kv_destroy(u_vecs.a); + kv_destroy(chain_buffer.a); + kv_destroy(chain_edges.a); + +} + + +///chainLenThres is used to avoid circle +void rescue_contained_reads_aggressive(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t chainLenThres, uint32_t is_bubble_check, uint32_t is_primary_check, kvec_asg_arc_t_warp* new_rtg_edges, +kvec_t_u32_warp* new_rtg_nodes, bub_label_t* b_mask_t) +{ + uint32_t n_vtx, v, k, contain_rId, is_Unitig, uId, rId, endRid, oLen, w, max_oLen, max_oLen_i = (uint32_t)-1; + uint32_t ava_max, ava_ol_max, ava_min_chain, ava_cur, ava_chainLen, test_oLen, is_update; + asg_t* nsg = NULL; + ma_utg_t* nsu = NULL; + asg_arc_t t, t_max, r_edge; + t_max.v = t_max.ul = t.v = t.ul = (uint32_t)-1; + ma_hit_t *h = NULL, *h_max = NULL; + ma_hit_t_alloc* x = NULL; + ma_ug_t* ug = NULL; + uint64_t a_nodes; + + kvec_t(asg_arc_t) new_edges; + kv_init(new_edges); + + kvec_t(asg_arc_t) rbub_edges; + kv_init(rbub_edges); + + kvec_t_u64_warp u_vecs; + kv_init(u_vecs.a); + + kvec_t_u32_warp chain_buffer; + kv_init(chain_buffer.a); + + kvec_asg_arc_t_warp chain_edges; + kv_init(chain_edges.a); + + if(i_ug != NULL) + { + ug = i_ug; + } + else + { + ug = ma_ug_gen(r_g); + for (v = 0; v < ug->g->n_seq; v++) + { + ug->g->seq[v].c = PRIMARY_LABLE; + } + } + nsg = ug->g; + + for (v = 0; v < nsg->n_seq; v++) + { + uId = v; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsg->seq[v].del) continue; + if(is_primary_check && nsg->seq[v].c==ALTER_LABLE) continue; + for (k = 0; k < nsu->n; k++) + { + rId = nsu->a[k]>>33; + set_R_to_U(ruIndex, rId, uId, 1, &(r_g->seq[rId].c)); + } + } + + + + + n_vtx = nsg->n_seq * 2; + for (v = 0; v < n_vtx; v++) + { + uId = v>>1; + if(nsg->seq[uId].del) continue; + if(is_primary_check && nsg->seq[uId].c==ALTER_LABLE) continue; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsu->circ || nsu->start == UINT32_MAX || nsu->end == UINT32_MAX) continue; + if(get_real_length(nsg, v, NULL) != 0) continue; + ///we probably don't need this line + ///if(get_real_length(nsg, v^1, NULL) == 0) continue; + if(v&1) + { + endRid = nsu->start^1; + } + else + { + endRid = nsu->end^1; + } + + ///x is the end read of a tip + ///find all overlap of x + x = &(sources[(endRid>>1)]); + ava_ol_max = ava_max = 0; ava_min_chain = (uint32_t)-1; + h_max = NULL; + for (k = 0; k < x->length; k++) + { + ///h is the edge of endRid + h = &(x->buffer[k]); + ///means we found a contained read + if(get_contained_reads_chain(h, sources, coverage_cut, ruIndex, ug, r_g, + max_hang, min_ovlp, endRid, uId, &chain_buffer, NULL, &ava_cur, &test_oLen, + &ava_chainLen, chainLenThres, 1)) + { + is_update = 0; + if(ava_chainLen < ava_min_chain) + { + is_update = 1; + } + else if(ava_chainLen == ava_min_chain) + { + if(ava_cur > ava_max) + { + is_update = 1; + } + else if(ava_cur == ava_max && test_oLen > ava_ol_max) + { + is_update = 1; + } + } + if(is_update) + { + ava_min_chain = ava_chainLen; + ava_max = ava_cur; + ava_ol_max = test_oLen; + h_max = h; + } + } + } + + + + + + if(ava_max > 0) + { + //get all edges between contained reads + get_contained_reads_chain(h_max, sources, coverage_cut, ruIndex, ug, r_g, + max_hang, min_ovlp, endRid, uId, &chain_buffer, &chain_edges, &ava_cur, &test_oLen, + &ava_chainLen, chainLenThres, 1); + if(chain_edges.a.n < 1) continue; + ///the last cantained read + t_max = chain_edges.a.a[chain_edges.a.n-1]; + + k = 0; rbub_edges.n = 0; + ///edges from the last contained read to other unitigs + while(get_edge2existing_node_advance(ug, r_g, sources, coverage_cut, ruIndex, + max_hang, min_ovlp, t_max.v, chain_buffer.a.a, chain_buffer.a.n, &k, &r_edge, 1)) + { + kv_push(asg_arc_t, rbub_edges, r_edge); + } + + ///need to do transitive reduction + ///note here is different to standard transitive reduction + minor_transitive_reduction(ug, ruIndex, rbub_edges.a, rbub_edges.n); + if(is_primary_check) + { + max_oLen = 0; max_oLen_i = (uint32_t)-1; + for (k = 0; k < rbub_edges.n; k++) + { + t = rbub_edges.a[k]; + if(t.del) continue; + if(t.ol > max_oLen) + { + max_oLen = t.ol; + max_oLen_i = k; + } + } + + if(max_oLen_i == (uint32_t)-1) continue; + t = rbub_edges.a[max_oLen_i]; + w = get_corresponding_uId(ug, ruIndex, t.v); + if(w == ((uint32_t)(-1))) continue; + if(get_real_length(nsg, w^1, NULL)!=0) continue; + } + + //recover all contained reads + for (k = 0; k < chain_edges.a.n; k++) + { + t_max = chain_edges.a.a[k]; + ///save all infor for reverting + get_R_to_U(ruIndex, t_max.v>>1, &contain_rId, &is_Unitig); + a_nodes=contain_rId; + a_nodes=a_nodes<<32; + a_nodes=a_nodes|((uint64_t)(t_max.v>>1)); + kv_push(uint64_t, u_vecs.a, a_nodes); + + + //(t_max.ul>>32)----->(t_max.v/r_edge.ul>>32)----->r_edge.v + //need to recover (t_max.v/r_edge.ul>>32), 1. set .del = 0 2. set ruIndex + r_g->seq[t_max.v>>1].del = 0; + coverage_cut[t_max.v>>1].del = 0; + coverage_cut[t_max.v>>1].c = PRIMARY_LABLE; + //add recover to the end of the unitig + append_rId_to_Unitig(r_g, ug, v, t_max.v, sources, coverage_cut, ruIndex, max_hang, + min_ovlp); + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, + (t_max.ul>>32), t_max.v, &t); + kv_push(asg_arc_t, new_edges, t); + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, + (t_max.v^1), ((t_max.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); + } + + if(is_primary_check) + { + t = rbub_edges.a[max_oLen_i]; + w = get_corresponding_uId(ug, ruIndex, t.v); + if(w == ((uint32_t)(-1))) continue; + kv_push(asg_arc_t, new_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, + (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); + } + else + { + for (k = 0; k < rbub_edges.n; k++) + { + t = rbub_edges.a[k]; + if(t.del) continue; + w = get_corresponding_uId(ug, ruIndex, t.v); + if(w == ((uint32_t)(-1))) continue; + + kv_push(asg_arc_t, new_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); + + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, + (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); + } + } + + } + } + + asg_arc_t* p = NULL; + if(is_bubble_check) + { + + for (k = 0; k < new_edges.n; k++) + { + p = asg_arc_pushp(r_g); + *p = new_edges.a[k]; + } + + if(new_edges.n != 0) + { + free(r_g->idx); + r_g->idx = 0; + r_g->is_srt = 0; + asg_cleanup(r_g); + } + + pre_clean(sources, coverage_cut, r_g, 0); + + lable_all_bubbles(r_g, b_mask_t); + + for (k = 0; k < new_edges.n; k++) + { + v = new_edges.a[k].ul>>32; + w = new_edges.a[k].v; + + if(r_g->seq[v>>1].del) continue; + if(r_g->seq[w>>1].del) continue; + ///if this edge is at a bubble + if(r_g->seq_vis[v]!=0 && r_g->seq_vis[w^1]!=0) continue; + + asg_arc_del(r_g, v, w, 1); + asg_arc_del(r_g, w^1, v^1, 1); + } + asg_cleanup(r_g); + + + // w=max_contain_rId; w=w<<32; w=w|(t_max.v>>1); + // kv_push(uint64_t, u_vecs.a, w); + for (k = 0; k < u_vecs.a.n; k++) + { + w = (uint32_t)u_vecs.a.a[k]; + w = w<<1; + if(!r_g->seq[w>>1].del && get_real_length(r_g, w, NULL)!=0) continue; + if(!r_g->seq[w>>1].del && get_real_length(r_g, (w^1), NULL)!=0) continue; + w=w>>1; + r_g->seq[w].del = 1; + coverage_cut[w].del = 1; + set_R_to_U(ruIndex, ((uint32_t)(u_vecs.a.a[k])), (u_vecs.a.a[k]>>32), 0, NULL); + } + } + + ///actually we don't update sources + ///during the the primary_check, we need to recover everything for r_g, coverage_cut and ruIndex + if(is_primary_check) + { + ///don't remove nodes and edges + /** + for (k = 0; k < u_vecs.a.n; k++) + { + w = (uint32_t)u_vecs.a.a[k]; + r_g->seq[w].del = 1; + coverage_cut[w].del = 1; + set_R_to_U(ruIndex, ((uint32_t)(u_vecs.a.a[k])), (u_vecs.a.a[k]>>32), 0); + } + **/ + if(new_rtg_nodes) + { + for(k = 0; k < u_vecs.a.n; k++) + { + w = (uint32_t)u_vecs.a.a[k]; + kv_push(uint32_t, new_rtg_nodes->a, w); + } + } + + + for (k = 0; k < new_edges.n; k++) + { + p = asg_arc_pushp(r_g); + *p = new_edges.a[k]; + if(new_rtg_edges) kv_push(asg_arc_t, new_rtg_edges->a, new_edges.a[k]); + } + + if(new_edges.n != 0) + { + free(r_g->idx); + r_g->idx = 0; + r_g->is_srt = 0; + asg_cleanup(r_g); + } + } + + + for (v = 0; v < ruIndex->len; v++) + { + get_R_to_U(ruIndex, v, &uId, &is_Unitig); + if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; + } + + + if(i_ug == NULL) ma_ug_destroy(ug); + kv_destroy(new_edges); + kv_destroy(rbub_edges); + kv_destroy(u_vecs.a); + kv_destroy(chain_buffer.a); + kv_destroy(chain_edges.a); + +} + + + +void rescue_missing_overlaps_aggressive(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t is_bubble_check, uint32_t is_primary_check, +kvec_asg_arc_t_warp* new_rtg_edges, bub_label_t* b_mask_t) +{ + uint32_t n_vtx, v, k, is_Unitig, uId, rId, endRid, oLen, w, max_oLen, max_oLen_i; + asg_t* nsg = NULL; + ma_utg_t* nsu = NULL; + ma_ug_t *ug = NULL; + asg_arc_t t, r_edge; + kvec_t(asg_arc_t) new_edges; + kv_init(new_edges); + + kvec_t(asg_arc_t) rbub_edges; + kv_init(rbub_edges); + + if(i_ug != NULL) + { + ug = i_ug; + } + else + { + ug = ma_ug_gen(r_g); + for (v = 0; v < ug->g->n_seq; v++) + { + ug->g->seq[v].c = PRIMARY_LABLE; + } + } + nsg = ug->g; + + for (v = 0; v < nsg->n_seq; v++) + { + uId = v; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsg->seq[v].del) continue; + if(is_primary_check && nsg->seq[v].c==ALTER_LABLE) continue; + + for (k = 0; k < nsu->n; k++) + { + rId = nsu->a[k]>>33; + set_R_to_U(ruIndex, rId, uId, 1, &(r_g->seq[rId].c)); + } + } + + + n_vtx = nsg->n_seq * 2; + for (v = 0; v < n_vtx; v++) + { + uId = v>>1; + if(nsg->seq[uId].del) continue; + if(is_primary_check && nsg->seq[uId].c == ALTER_LABLE) continue; + + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsu->circ || nsu->start == UINT32_MAX || nsu->end == UINT32_MAX) continue; + if(get_real_length(nsg, v, NULL) != 0) continue; + + if(v&1) + { + endRid = nsu->start^1; + } + else + { + endRid = nsu->end^1; + } + + + k = 0; + rbub_edges.n = 0; + while(get_edge2existing_node_advance(ug, r_g, sources, coverage_cut, ruIndex, + max_hang, min_ovlp, endRid, &uId, 1, &k, &r_edge, 1)) + { + kv_push(asg_arc_t, rbub_edges, r_edge); + } + + + + if(rbub_edges.n > 0) + { + ///need to do transitive reduction + ///note here is different to standard transitive reduction + minor_transitive_reduction(ug, ruIndex, rbub_edges.a, rbub_edges.n); + if(is_primary_check) + { + max_oLen = 0; max_oLen_i = (uint32_t)-1; + for (k = 0; k < rbub_edges.n; k++) + { + t = rbub_edges.a[k]; + if(t.del) continue; + if(t.ol > max_oLen) + { + max_oLen = t.ol; + max_oLen_i = k; + } + } + + if(max_oLen_i == (uint32_t)-1) continue; + t = rbub_edges.a[max_oLen_i]; + w = get_corresponding_uId(ug, ruIndex, t.v); + if(w == ((uint32_t)(-1))) continue; + if(get_real_length(nsg, w^1, NULL)!=0) continue; + + kv_push(asg_arc_t, new_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); + + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, + (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); + } + else + { + for (k = 0; k < rbub_edges.n; k++) + { + t = rbub_edges.a[k]; + if(t.del) continue; + w = get_corresponding_uId(ug, ruIndex, t.v); + if(w == ((uint32_t)(-1))) continue; + // get_R_to_U(ruIndex, t.v>>1, &uId, &is_Unitig); + // w = (uint32_t)-1; + // if(t.v == ug->u.a[uId].start) w = uId<<1; + // if(t.v == ug->u.a[uId].end) w = (uId<<1)^1; + kv_push(asg_arc_t, new_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); + + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, + (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); + } + } + + } + } + + asg_arc_t* p = NULL; + if(is_bubble_check) + { + + for (k = 0; k < new_edges.n; k++) + { + p = asg_arc_pushp(r_g); + *p = new_edges.a[k]; + } + + if(new_edges.n != 0) + { + free(r_g->idx); + r_g->idx = 0; + r_g->is_srt = 0; + asg_cleanup(r_g); + } + + + pre_clean(sources, coverage_cut, r_g, 0); + + lable_all_bubbles(r_g, b_mask_t); + + + for (k = 0; k < new_edges.n; k++) + { + v = new_edges.a[k].ul>>32; + w = new_edges.a[k].v; + + if(r_g->seq[v>>1].del) continue; + if(r_g->seq[w>>1].del) continue; + ///if this edge is at a bubble + if(r_g->seq_vis[v]!=0 && r_g->seq_vis[w^1]!=0) continue; + + asg_arc_del(r_g, v, w, 1); + asg_arc_del(r_g, w^1, v^1, 1); + } + asg_cleanup(r_g); + } + + if(is_primary_check) + { + for (k = 0; k < new_edges.n; k++) + { + p = asg_arc_pushp(r_g); + *p = new_edges.a[k]; + if(new_rtg_edges) kv_push(asg_arc_t, new_rtg_edges->a, new_edges.a[k]); + } + + if(new_edges.n != 0) + { + free(r_g->idx); + r_g->idx = 0; + r_g->is_srt = 0; + asg_cleanup(r_g); + } + } + + + for (v = 0; v < ruIndex->len; v++) + { + get_R_to_U(ruIndex, v, &uId, &is_Unitig); + if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; + } + + if(i_ug == NULL) ma_ug_destroy(ug); + + kv_destroy(new_edges); + kv_destroy(rbub_edges); + /*************************just for debug**************************/ + // debug_utg_graph(ug, r_g, 0, 0); + /*************************just for debug**************************/ +} + +void set_rtg_flag_by_bubble(bubble_type* bub, ma_ug_t* ug, asg_t *r_g, uint32_t v, uint8_t* vis_flag, +uint32_t flag) +{ + uint32_t beg, sink, *a = NULL, n, i, k, uId, rId; + ma_utg_t* nsu = NULL; + get_bubbles(bub, v, &beg, &sink, &a, &n, NULL); + for (i = 0; i < n; i++) + { + uId = a[i]>>1; + + nsu = &(ug->u.a[uId]); + if(nsu->m > 0) + { + for (k = 0; k < nsu->n; k++) + { + rId = nsu->a[k]>>33; + if(r_g->seq[rId].del) continue; + vis_flag[rId] = flag; + } + } + } + + if(beg != (uint32_t)-1) + { + uId = beg>>1; + + nsu = &(ug->u.a[uId]); + if(nsu->m > 0) + { + for (k = 0; k < nsu->n; k++) + { + rId = nsu->a[k]>>33; + if(r_g->seq[rId].del) continue; + vis_flag[rId] = flag; + } + } + } + + if(sink != (uint32_t)-1) + { + uId = sink>>1; + + nsu = &(ug->u.a[uId]); + if(nsu->m > 0) + { + for (k = 0; k < nsu->n; k++) + { + rId = nsu->a[k]>>33; + if(r_g->seq[rId].del) continue; + vis_flag[rId] = flag; + } + } + } +} + +void print_bubble_filling_status(ma_ug_t *copy_ug, asg_t *r_g, R_to_U* ruIndex, bubble_type* bub, +uint32_t beg_idx, uint32_t occ, asg_arc_t* new_edges, uint32_t new_edges_len) +{ + ma_utg_t* nsu = NULL; + ma_ug_t* ug = copy_ug; + uint32_t i, k_i, k_v, v, k, beg_utg, sink_utg, *a = NULL, n, uId, endRid, is_broken, is_tangle; + uint32_t tangle_occ = 0, broken_occ = 0, recover_occ = 0, is_Unitig, contain_uId; + asg_t* nsg = ug->g; + for (i = beg_idx; i < beg_idx + occ; i++) + { + get_bubbles(bub, i, &beg_utg, &sink_utg, &a, &n, NULL); + if(beg_utg == (uint32_t)-1 || sink_utg == (uint32_t)-1) continue; + for (k_i = 0, is_broken = 1, is_tangle = 1; k_i < n; k_i++) + { + uId = a[k_i]>>1; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + for (k_v = 0; k_v < 2; k_v++) + { + v = (uId<<1) + k_v; + if(get_real_length(nsg, v, NULL) != 0) continue; + + ///tig + is_tangle = 0; + if(v&1) + { + endRid = nsu->start^1; + } + else + { + endRid = nsu->end^1; + } + + if(r_g->seq[endRid>>1].del) + { + is_broken = 0; + continue; + } + + if(get_real_length(r_g, endRid, NULL) == 0) + { + is_broken = 1; + goto tig_end; + } + else + { + is_broken = 0; + } + } + } + + tig_end: + if(is_tangle) + { + tangle_occ++; + fprintf(stderr, "tangle: beg-utg%.6ul, end-utg%.6ul\n", (beg_utg>>1)+1, (sink_utg>>1)+1); + } + else if(is_broken) + { + broken_occ++; + fprintf(stderr, "broken: beg-utg%.6ul, end-utg%.6ul\n", (beg_utg>>1)+1, (sink_utg>>1)+1); + } + else + { + recover_occ++; + fprintf(stderr, "recover: beg-utg%.6ul, end-utg%.6ul\n", (beg_utg>>1)+1, (sink_utg>>1)+1); + } + } + + fprintf(stderr, "###########tangle_occ: %u, broken_occ: %u, recover_occ: %u\n", tangle_occ, broken_occ, recover_occ); + nsg = ug->g; + for (v = 0; v < nsg->n_seq; v++) + { + uId = v; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsg->seq[v].del) continue; + for (k = 0; k < nsu->n; k++) + { + set_R_to_U(ruIndex, nsu->a[k]>>33, uId, 1, &(r_g->seq[nsu->a[k]>>33].c)); + } + } + #define check_debug_edge(g, t) (((g).seq[(t).ul>>33].del == 1) && ((g).seq[(t).v>>1].del == 0)) + + + + for (k = 0; k < new_edges_len; k++) + { + v = new_edges[k].ul>>32; + + if(check_debug_edge(*r_g, new_edges[k])) + { + for (i = broken_occ = 0; i < new_edges_len; i++) + { + if((new_edges[i].ul>>32) == v) broken_occ++; + } + + if(broken_occ > 1) + { + fprintf(stderr, "*************tig_to_occ: %u\n", broken_occ); + for (i = 0; i < new_edges_len; i++) + { + if((new_edges[i].ul>>32) == v) + { + get_R_to_U(ruIndex, new_edges[i].v>>1, &contain_uId, &is_Unitig); + if(is_Unitig == 1) + { + nsu = &(ug->u.a[contain_uId]); + for (k_i = 0; k_i < nsu->n; k_i++) + { + if((nsu->a[k_i]>>33) == (new_edges[i].v>>1)) break; + } + + fprintf(stderr, "to-utg%.6ul, idx_of_u: %u, u_n: %u\n", + contain_uId+1, k_i, nsu->n); + } + + } + } + } + } + } + + + + for (v = 0; v < ruIndex->len; v++) + { + get_R_to_U(ruIndex, v, &uId, &is_Unitig); + if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; + } + +} + +void minor_transitive_reduction_r_g(asg_t *r_g, asg_arc_t* rbub_edges, uint32_t num) +{ + uint32_t i, j, k, rId, nv, w; + asg_arc_t* t = NULL; + asg_arc_t* p = NULL; + asg_arc_t *av = NULL; + ///here all edges from v are saved in rbub_edges + ///for edges already in graph, need to check del + ///but for edges in rbub_edges, don't check del + for (i = 0; i < num; i++) + { + t = &rbub_edges[i]; + rId = t->v; + + nv = asg_arc_n(r_g, rId); + av = asg_arc_a(r_g, rId); + for (j = 0; j < nv; j++) + { + if(av[j].del) continue; + w = av[j].v; + for (k = 0; k < num; k++) + { + p = &rbub_edges[k]; + ///this line is not necessary at all + if(k==i) continue; + if(p->v == w) p->del = 1; + } + } + } +} + + +int if_recoverable(asg_t *sg, ma_ug_t *ug, bubble_type* bub, uint32_t bid, kvec_t_u32_warp* stack, uint8_t* vis_flag) +{ + uint32_t beg_utg, sink_utg, *a = NULL, n, begRid, sinkRid, i; + get_bubbles(bub, bid, &beg_utg, &sink_utg, &a, &n, NULL); + if(beg_utg == (uint32_t)-1 || sink_utg == (uint32_t)-1) return 0; + if(beg_utg&1) + { + begRid = ug->u.a[beg_utg>>1].start^1; + } + else + { + begRid = ug->u.a[beg_utg>>1].end^1; + } + + if(sink_utg&1) + { + sinkRid = ug->u.a[sink_utg>>1].start; + } + else + { + sinkRid = ug->u.a[sink_utg>>1].end; + } + + asg_arc_t *acur = NULL; + uint32_t cur, ncur, v, n_vx = sg->n_seq<<1; + stack->a.n = 0; + memset(vis_flag, 0, n_vx); + + kv_push(uint32_t, stack->a, begRid); + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + ncur = asg_arc_n(sg, cur); + acur = asg_arc_a(sg, cur); + vis_flag[cur] |= 1; + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if(vis_flag[acur[i].v]&1) return 0; + if(vis_flag[acur[i].v^1]&1) return 0; + if(acur[i].v == sinkRid) continue; + kv_push(uint32_t, stack->a, acur[i].v); + } + } + vis_flag[sinkRid] |= 1; + + + + begRid ^= 1; sinkRid ^= 1; v = begRid; begRid = sinkRid; sinkRid = v; + + stack->a.n = 0; + kv_push(uint32_t, stack->a, begRid); + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + ncur = asg_arc_n(sg, cur); + acur = asg_arc_a(sg, cur); + vis_flag[cur] |= 2; + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if(vis_flag[acur[i].v]&2) return 0; + if(vis_flag[acur[i].v]&1) return 0; + if(vis_flag[acur[i].v^1]&2) return 0; + if(acur[i].v == sinkRid) continue; + kv_push(uint32_t, stack->a, acur[i].v); + } + } + vis_flag[sinkRid] |= 2; + + + + begRid ^= 1; sinkRid ^= 1; v = begRid; begRid = sinkRid; sinkRid = v; + + return 1; +} + +void rescue_bubbles_by_contained_reads(ma_ug_t *i_u_g, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t chainLenThres, uint32_t beg_idx, uint32_t occ, bubble_type* bub, +bub_label_t* b_mask_t) +{ + asg_t* nsg = NULL; + uint32_t beg_utg, sink_utg, *a = NULL, n, i, bub_i, k_i, k_v, k, uId, endRid, is_Unitig, contain_rId; + uint32_t ava_max, ava_ol_max, ava_min_chain, ava_cur, test_oLen, ava_chainLen, is_update, v, w; + uint64_t l_bub, m_bub, r_bub, /**bub_0, bub_1,**/ a_nodes; + ma_ug_t* ug = i_u_g; + ma_utg_t *nsu = NULL, *u = NULL; + ma_hit_t_alloc* x = NULL; + ma_hit_t *h = NULL, *h_max = NULL; + uint8_t* expect_vis = NULL; CALLOC(expect_vis, r_g->n_seq); + uint8_t* circle_vis = NULL; CALLOC(circle_vis, r_g->n_seq); + uint8_t* utg_vis = NULL; CALLOC(utg_vis, ug->g->n_seq); + asg_arc_t t, t_max, r_edge; + + for (v = 0; v < ug->u.n; v++) ug->g->seq[v].c = PRIMARY_LABLE; + + kvec_t(asg_arc_t) new_edges; + kv_init(new_edges); + + kvec_t(asg_arc_t) rbub_edges; + kv_init(rbub_edges); + + kvec_t_u64_warp u_vecs; + kv_init(u_vecs.a); + + kvec_asg_arc_t_warp chain_edges; + kv_init(chain_edges.a); + + nsg = ug->g; + for (v = 0; v < nsg->n_seq; v++) + { + uId = v; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsg->seq[v].del) continue; + for (k = 0; k < nsu->n; k++) + { + set_R_to_U(ruIndex, nsu->a[k]>>33, uId, 1, &(r_g->seq[nsu->a[k]>>33].c)); + } + } + + + for (i = 0; i < bub->b_ug->u.n; i++) + { + u = &(bub->b_ug->u.a[i]); + if(u->n < 3) continue; ///should be at least 3 + for (bub_i = 1; bub_i+1 < u->n; bub_i++) + { + m_bub = u->a[bub_i]>>33; l_bub = r_bub = (uint64_t)-1; + if(m_bub < beg_idx || m_bub >= beg_idx + occ) continue; + l_bub = u->a[bub_i-1]>>33; + r_bub = u->a[bub_i+1]>>33; + + set_rtg_flag_by_bubble(bub, ug, r_g, l_bub, expect_vis, 1); + set_rtg_flag_by_bubble(bub, ug, r_g, r_bub, expect_vis, 1); + set_rtg_flag_by_bubble(bub, ug, r_g, m_bub, expect_vis, 1); + + get_bubbles(bub, m_bub, &beg_utg, &sink_utg, &a, &n, NULL); + for (k_i = 0; k_i < n; k_i++) + { + uId = a[k_i]>>1; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + for (k_v = 0; k_v < 2; k_v++) + { + v = (uId<<1) + k_v; + if(get_real_length(nsg, v, NULL) != 0) continue; + + if(v&1) + { + endRid = nsu->start^1; + } + else + { + endRid = nsu->end^1; + } + + //x is the end read of a tip + ///find all overlap of x + x = &(sources[(endRid>>1)]); + ava_ol_max = ava_max = 0; ava_min_chain = (uint32_t)-1; + h_max = NULL; + for (k = 0; k < x->length; k++) + { + ///fprintf(stderr, "k: %u\n", k); + ///h is the edge of endRid + h = &(x->buffer[k]); + ///means we found a contained read + if(get_contained_reads_chain_by_broken_bub(h, sources, coverage_cut, ruIndex, ug, r_g, + max_hang, min_ovlp, endRid, uId, &chain_edges, &ava_cur, &test_oLen, &ava_chainLen, + expect_vis, circle_vis, utg_vis, chainLenThres, 1)) + { + is_update = 0; + + if(ava_cur > ava_max) + { + is_update = 1; + } + else if(ava_cur == ava_max) + { + if(ava_chainLen < ava_min_chain) + { + is_update = 1; + } + else if(ava_chainLen == ava_min_chain && test_oLen > ava_ol_max) + { + is_update = 1; + } + } + + if(is_update) + { + ava_min_chain = ava_chainLen; + ava_max = ava_cur; + ava_ol_max = test_oLen; + h_max = h; + } + } + } + + if(ava_max > 0) + { + ///fprintf(stderr, "ava_max: %u\n", ava_max); + get_contained_reads_chain_by_broken_bub(h_max, sources, coverage_cut, ruIndex, ug, r_g, + max_hang, min_ovlp, endRid, uId, &chain_edges, &ava_cur, &test_oLen, &ava_chainLen, + expect_vis, circle_vis, NULL, chainLenThres, 1); + if(chain_edges.a.n < 1) continue; + ///the last cantained read + t_max = chain_edges.a.a[chain_edges.a.n-1]; + + k = 0; rbub_edges.n = 0; + ///edges from the last contained read to other unitigs + + while(get_edge2existing_node_advance_by_broken_bub(ug, r_g, sources, coverage_cut, + ruIndex, expect_vis, max_hang, min_ovlp, t_max.v, &k, &r_edge, 1)) + { + kv_push(asg_arc_t, rbub_edges, r_edge); + } + + ///need to do transitive reduction + ///note here is different to standard transitive reduction + minor_transitive_reduction_r_g(r_g, rbub_edges.a, rbub_edges.n); + + for (k = 0; k < chain_edges.a.n; k++) + { + t_max = chain_edges.a.a[k]; + ///save all infor for reverting + get_R_to_U(ruIndex, t_max.v>>1, &contain_rId, &is_Unitig); + a_nodes=contain_rId; + a_nodes=a_nodes<<32; + a_nodes=a_nodes|((uint64_t)(t_max.v>>1)); + kv_push(uint64_t, u_vecs.a, a_nodes); + + r_g->seq[t_max.v>>1].del = 0; + coverage_cut[t_max.v>>1].del = 0; + coverage_cut[t_max.v>>1].c = PRIMARY_LABLE; + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, + (t_max.ul>>32), t_max.v, &t); + kv_push(asg_arc_t, new_edges, t); + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, + (t_max.v^1), ((t_max.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); + } + + + for (k = 0; k < rbub_edges.n; k++) + { + t = rbub_edges.a[k]; + if(t.del) continue; + + kv_push(asg_arc_t, new_edges, t); + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, + (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); + } + + } + } + } + + + set_rtg_flag_by_bubble(bub, ug, r_g, l_bub, expect_vis, 0); + set_rtg_flag_by_bubble(bub, ug, r_g, r_bub, expect_vis, 0); + set_rtg_flag_by_bubble(bub, ug, r_g, m_bub, expect_vis, 0); + } + } + + asg_arc_t* p = NULL; + for (k = 0; k < new_edges.n; k++) + { + p = asg_arc_pushp(r_g); + *p = new_edges.a[k]; + } + if(new_edges.n != 0) + { + free(r_g->idx); + r_g->idx = 0; + r_g->is_srt = 0; + asg_cleanup(r_g); + asg_symm(r_g); + } + + pre_clean(sources, coverage_cut, r_g, 0); + + lable_all_bubbles(r_g, b_mask_t); + + for (k = 0; k < new_edges.n; k++) + { + v = new_edges.a[k].ul>>32; + w = new_edges.a[k].v; + + if(r_g->seq[v>>1].del) continue; + if(r_g->seq[w>>1].del) continue; + ///if this edge is at a bubble + if(r_g->seq_vis[v]!=0 && r_g->seq_vis[w^1]!=0) continue; + + asg_arc_del(r_g, v, w, 1); + asg_arc_del(r_g, w^1, v^1, 1); + } + asg_cleanup(r_g); + asg_symm(r_g); + + for (k = 0; k < u_vecs.a.n; k++) + { + w = (uint32_t)u_vecs.a.a[k]; + w = w<<1; + if((!r_g->seq[w>>1].del) && + (get_real_length(r_g, w, NULL)!=0 || get_real_length(r_g, (w^1), NULL)!=0)) + { + w=w>>1; + ruIndex->index[w] = (uint32_t)-1; + } + else + { + w=w>>1; + r_g->seq[w].del = 1; + coverage_cut[w].del = 1; + } + } + + for (v = 0; v < ruIndex->len; v++) + { + get_R_to_U(ruIndex, v, &uId, &is_Unitig); + if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; + } + + // fprintf(stderr, "M::%s has done!\n", __func__); + // print_bubble_filling_status(ug, r_g, ruIndex, bub, beg_idx, occ, new_edges.a, new_edges.n); + + kv_destroy(new_edges); + kv_destroy(rbub_edges); + kv_destroy(u_vecs.a); + kv_destroy(chain_edges.a); + free(expect_vis); + free(circle_vis); + free(utg_vis); +} + +void rescue_bubbles_by_cmk_reads(ma_ug_t *i_u_g, asg_t *rg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t chainLenThres, uint32_t beg_idx, uint32_t occ, bubble_type* bub, bub_label_t* b_mask_t, uint8_t *cmk) +{ + asg_t* nsg = NULL; uint32_t beg_utg, sink_utg, *a = NULL, n, i, bub_i, k_i, k_v, k, uId, endRid, is_Unitig, contain_rId; + uint32_t ava_max, ava_ol_max, ava_min_chain, ava_cur, test_oLen, ava_chainLen, is_update, v, w; + uint64_t l_bub, m_bub, r_bub, a_nodes; ma_ug_t* ug = i_u_g; + ma_utg_t *nsu = NULL, *u = NULL; ma_hit_t_alloc* x = NULL; ma_hit_t *h = NULL, *h_max = NULL; + uint8_t* expect_vis = NULL; CALLOC(expect_vis, rg->n_seq); + uint8_t* circle_vis = NULL; CALLOC(circle_vis, rg->n_seq); + uint8_t* utg_vis = NULL; CALLOC(utg_vis, ug->g->n_seq); asg_arc_t t, t_max, r_edge; + + for (v = 0; v < ug->u.n; v++) ug->g->seq[v].c = PRIMARY_LABLE; + + kvec_t(asg_arc_t) new_edges; kv_init(new_edges); + + kvec_t(asg_arc_t) rbub_edges; kv_init(rbub_edges); + + kvec_t_u64_warp u_vecs; kv_init(u_vecs.a); + + kvec_asg_arc_t_warp chain_edges; kv_init(chain_edges.a); + + nsg = ug->g; + for (v = 0; v < nsg->n_seq; v++) { + uId = v; nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsg->seq[v].del) continue; + for (k = 0; k < nsu->n; k++) { + set_R_to_U(ruIndex, nsu->a[k]>>33, uId, 1, &(rg->seq[nsu->a[k]>>33].c)); + } + } + + for (i = 0; i < bub->b_ug->u.n; i++) { + u = &(bub->b_ug->u.a[i]); + if(u->n < 3) continue; ///should be at least 3 + for (bub_i = 1; bub_i+1 < u->n; bub_i++) { + m_bub = u->a[bub_i]>>33; l_bub = r_bub = (uint64_t)-1; + if(m_bub < beg_idx || m_bub >= beg_idx + occ) continue; + l_bub = u->a[bub_i-1]>>33; + r_bub = u->a[bub_i+1]>>33; + + set_rtg_flag_by_bubble(bub, ug, rg, l_bub, expect_vis, 1); + set_rtg_flag_by_bubble(bub, ug, rg, r_bub, expect_vis, 1); + set_rtg_flag_by_bubble(bub, ug, rg, m_bub, expect_vis, 1); + + get_bubbles(bub, m_bub, &beg_utg, &sink_utg, &a, &n, NULL); + for (k_i = 0; k_i < n; k_i++) { + uId = a[k_i]>>1; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + for (k_v = 0; k_v < 2; k_v++) { + v = (uId<<1) + k_v; + if(get_real_length(nsg, v, NULL) != 0) continue; + + if(v&1) endRid = nsu->start^1; + else endRid = nsu->end^1; + + //x is the end read of a tip + ///find all overlap of x + x = &(sources[(endRid>>1)]); + ava_ol_max = ava_max = 0; ava_min_chain = (uint32_t)-1; + h_max = NULL; + for (k = 0; k < x->length; k++) { + ///h is the edge of endRid + h = &(x->buffer[k]); + ///means we found a contained read + if(get_chimeric_reads_chain_by_broken_bub(h, sources, coverage_cut, ruIndex, ug, rg, max_hang, min_ovlp, endRid, uId, &chain_edges, &ava_cur, &test_oLen, &ava_chainLen, expect_vis, circle_vis, utg_vis, chainLenThres, 1, cmk)) { + is_update = 0; + + if(ava_cur > ava_max) { + is_update = 1; + } else if(ava_cur == ava_max) { + if(ava_chainLen < ava_min_chain) { + is_update = 1; + } else if(ava_chainLen == ava_min_chain && test_oLen > ava_ol_max) { + is_update = 1; + } + } + + if(is_update) { + ava_min_chain = ava_chainLen; + ava_max = ava_cur; + ava_ol_max = test_oLen; + h_max = h; + } + } + } + + if(ava_max > 0) { + ///fprintf(stderr, "ava_max: %u\n", ava_max); + get_chimeric_reads_chain_by_broken_bub(h_max, sources, coverage_cut, ruIndex, ug, rg, max_hang, min_ovlp, endRid, uId, &chain_edges, &ava_cur, &test_oLen, &ava_chainLen, expect_vis, circle_vis, NULL, chainLenThres, 1, cmk); + if(chain_edges.a.n < 1) continue; + ///the last cantained read + t_max = chain_edges.a.a[chain_edges.a.n-1]; + + k = 0; rbub_edges.n = 0; + ///edges from the last contained read to other unitigs + + while(get_edge2existing_node_advance_by_broken_bub(ug, rg, sources, coverage_cut, ruIndex, expect_vis, max_hang, min_ovlp, t_max.v, &k, &r_edge, 1)) { + kv_push(asg_arc_t, rbub_edges, r_edge); + } + + ///need to do transitive reduction + ///note here is different to standard transitive reduction + minor_transitive_reduction_r_g(rg, rbub_edges.a, rbub_edges.n); + + for (k = 0; k < chain_edges.a.n; k++) { + t_max = chain_edges.a.a[k]; + ///save all infor for reverting + get_R_to_U(ruIndex, t_max.v>>1, &contain_rId, &is_Unitig); + if((is_Unitig == 1) || (is_Unitig == ((uint32_t)-1))) contain_rId = ((uint32_t)-1);///shouldn't be possible + a_nodes=contain_rId; + a_nodes=a_nodes<<32; + a_nodes=a_nodes|((uint64_t)(t_max.v>>1)); + kv_push(uint64_t, u_vecs.a, a_nodes); + + rg->seq[t_max.v>>1].del = 0; + coverage_cut[t_max.v>>1].del = 0; + coverage_cut[t_max.v>>1].c = PRIMARY_LABLE; + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, (t_max.ul>>32), t_max.v, &t); + kv_push(asg_arc_t, new_edges, t); + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, (t_max.v^1), ((t_max.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); + } + + + for (k = 0; k < rbub_edges.n; k++) { + t = rbub_edges.a[k]; + if(t.del) continue; + + kv_push(asg_arc_t, new_edges, t); + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); + } + + } + } + } + + + set_rtg_flag_by_bubble(bub, ug, rg, l_bub, expect_vis, 0); + set_rtg_flag_by_bubble(bub, ug, rg, r_bub, expect_vis, 0); + set_rtg_flag_by_bubble(bub, ug, rg, m_bub, expect_vis, 0); + } + } + + asg_arc_t* p = NULL; + for (k = 0; k < new_edges.n; k++) { + p = asg_arc_pushp(rg); + *p = new_edges.a[k]; + } + + if(new_edges.n != 0) { + free(rg->idx); + rg->idx = 0; + rg->is_srt = 0; + asg_cleanup(rg); + asg_symm(rg); + } + + pre_clean(sources, coverage_cut, rg, 0); + + lable_all_bubbles(rg, b_mask_t); + + for (k = 0; k < new_edges.n; k++) { + v = new_edges.a[k].ul>>32; + w = new_edges.a[k].v; + + if(rg->seq[v>>1].del) continue; + if(rg->seq[w>>1].del) continue; + ///if this edge is at a bubble + if(rg->seq_vis[v]!=0 && rg->seq_vis[w^1]!=0) continue; + + asg_arc_del(rg, v, w, 1); + asg_arc_del(rg, w^1, v^1, 1); + } + asg_cleanup(rg); + asg_symm(rg); + + for (k = 0; k < u_vecs.a.n; k++) { + w = (uint32_t)u_vecs.a.a[k]; + w = w<<1; + if((!rg->seq[w>>1].del) && (get_real_length(rg, w, NULL)!=0 || get_real_length(rg, (w^1), NULL)!=0)) { + w=w>>1; + ruIndex->index[w] = (uint32_t)-1; + } else { + w=w>>1; + rg->seq[w].del = 1; coverage_cut[w].del = 1; + } + } + + for (v = 0; v < ruIndex->len; v++) { + get_R_to_U(ruIndex, v, &uId, &is_Unitig); + if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; + } + + // fprintf(stderr, "M::%s has done!\n", __func__); + // print_bubble_filling_status(ug, r_g, ruIndex, bub, beg_idx, occ, new_edges.a, new_edges.n); + + kv_destroy(new_edges); + kv_destroy(rbub_edges); + kv_destroy(u_vecs.a); + kv_destroy(chain_edges.a); + free(expect_vis); + free(circle_vis); + free(utg_vis); +} + + +void rescue_bubbles_by_missing_ovlp(ma_ug_t *i_u_g, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t chainLenThres, uint32_t beg_idx, uint32_t occ, bubble_type* bub, +bub_label_t* b_mask_t) +{ + asg_t* nsg = NULL; + uint32_t beg_utg, sink_utg, *a = NULL, n, i, bub_i, k_i, k_v, k, uId, endRid, is_Unitig, v, w; + uint64_t l_bub, m_bub, r_bub/**, bub_0, bub_1**/; + ma_ug_t* ug = i_u_g; + ma_utg_t *nsu = NULL, *u = NULL; + uint8_t* expect_vis = NULL; CALLOC(expect_vis, r_g->n_seq); + asg_arc_t t, r_edge; + + for (v = 0; v < ug->u.n; v++) ug->g->seq[v].c = PRIMARY_LABLE; + + kvec_t(asg_arc_t) new_edges; + kv_init(new_edges); + + kvec_t(asg_arc_t) rbub_edges; + kv_init(rbub_edges); + + + nsg = ug->g; + for (v = 0; v < nsg->n_seq; v++) + { + uId = v; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsg->seq[v].del) continue; + for (k = 0; k < nsu->n; k++) + { + set_R_to_U(ruIndex, nsu->a[k]>>33, uId, 1, &(r_g->seq[nsu->a[k]>>33].c)); + } + } + + for (i = 0; i < bub->b_ug->u.n; i++) + { + u = &(bub->b_ug->u.a[i]); + if(u->n < 3) continue; ///should be at least 3 + for (bub_i = 1; bub_i+1 < u->n; bub_i++) + { + m_bub = u->a[bub_i]>>33; l_bub = r_bub = (uint64_t)-1; + if(m_bub < beg_idx || m_bub >= beg_idx + occ) continue; + l_bub = u->a[bub_i-1]>>33; + r_bub = u->a[bub_i+1]>>33; + + set_rtg_flag_by_bubble(bub, ug, r_g, l_bub, expect_vis, 1); + set_rtg_flag_by_bubble(bub, ug, r_g, r_bub, expect_vis, 1); + set_rtg_flag_by_bubble(bub, ug, r_g, m_bub, expect_vis, 1); + + get_bubbles(bub, m_bub, &beg_utg, &sink_utg, &a, &n, NULL); + + for (k_i = 0; k_i < n; k_i++) + { + uId = a[k_i]>>1; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + for (k_v = 0; k_v < 2; k_v++) + { + v = (uId<<1) + k_v; + if(get_real_length(nsg, v, NULL) != 0) continue; + + if(v&1) + { + endRid = nsu->start^1; + } + else + { + endRid = nsu->end^1; + } + + + k = 0; rbub_edges.n = 0; + while(get_edge2existing_node_advance_by_broken_bub(ug, r_g, sources, coverage_cut, + ruIndex, expect_vis, max_hang, min_ovlp, endRid, &k, &r_edge, 1)) + { + kv_push(asg_arc_t, rbub_edges, r_edge); + } + + if(rbub_edges.n > 0) + { + ///need to do transitive reduction + ///note here is different to standard transitive reduction + minor_transitive_reduction_r_g(r_g, rbub_edges.a, rbub_edges.n); + for (k = 0; k < rbub_edges.n; k++) + { + t = rbub_edges.a[k]; + if(t.del) continue; + + kv_push(asg_arc_t, new_edges, t); + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, + (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); + } + } + } + } + + + set_rtg_flag_by_bubble(bub, ug, r_g, l_bub, expect_vis, 0); + set_rtg_flag_by_bubble(bub, ug, r_g, r_bub, expect_vis, 0); + set_rtg_flag_by_bubble(bub, ug, r_g, m_bub, expect_vis, 0); + } + } + + asg_arc_t* p = NULL; + for (k = 0; k < new_edges.n; k++) + { + p = asg_arc_pushp(r_g); + *p = new_edges.a[k]; + } + if(new_edges.n != 0) + { + free(r_g->idx); + r_g->idx = 0; + r_g->is_srt = 0; + asg_cleanup(r_g); + asg_symm(r_g); + } + + pre_clean(sources, coverage_cut, r_g, 0); + + lable_all_bubbles(r_g, b_mask_t); + + + for (k = 0; k < new_edges.n; k++) + { + v = new_edges.a[k].ul>>32; + w = new_edges.a[k].v; + + if(r_g->seq[v>>1].del) continue; + if(r_g->seq[w>>1].del) continue; + ///if this edge is at a bubble + if(r_g->seq_vis[v]!=0 && r_g->seq_vis[w^1]!=0) continue; + + asg_arc_del(r_g, v, w, 1); + asg_arc_del(r_g, w^1, v^1, 1); + } + asg_cleanup(r_g); + asg_symm(r_g); + + + for (v = 0; v < ruIndex->len; v++) + { + get_R_to_U(ruIndex, v, &uId, &is_Unitig); + if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; + } + // fprintf(stderr, "M::%s has done!\n", __func__); + // print_bubble_filling_status(ug, r_g, ruIndex, bub, beg_idx, occ, new_edges.a, new_edges.n); + + kv_destroy(new_edges); + kv_destroy(rbub_edges); + free(expect_vis); +} + +void update_unitig(long long step, long long init, ma_utg_t* nsu, asg_t *r_g, kvec_asg_arc_t_warp* recover_edges, uint32_t update_mode); +void rescue_bubbles_by_missing_ovlp_backward(ma_ug_t *i_u_g, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t backward_steps, uint32_t beg_idx, uint32_t occ, bubble_type* bub, bub_label_t* b_mask_t) +{ + asg_t* nsg = NULL; + uint32_t beg_utg, sink_utg, *a = NULL, n, i, bub_i, k_i, k_v, k, uId, endRid, is_Unitig, round, cur_backward_steps; + uint32_t v, w, mode, nv; + uint64_t l_bub, m_bub, r_bub, /**bub_0, bub_1,**/ tmp; + ma_ug_t* ug = i_u_g; + ma_utg_t *nsu = NULL, *u = NULL; + uint8_t* expect_vis = NULL; CALLOC(expect_vis, r_g->n_seq); + long long init, step = 0; + asg_arc_t t, r_edge, *av = NULL; + + for (v = 0; v < ug->u.n; v++) ug->g->seq[v].c = PRIMARY_LABLE; + + kvec_t(asg_arc_t) new_edges; + kv_init(new_edges); + + kvec_asg_arc_t_warp recover_edges; + kv_init(recover_edges.a); + + kvec_t(asg_arc_t) rbub_edges; + kv_init(rbub_edges); + + kvec_t_u64_warp u_vecs; + kv_init(u_vecs.a); + + + nsg = ug->g; + for (v = 0; v < nsg->n_seq; v++) + { + uId = v; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsg->seq[v].del) continue; + for (k = 0; k < nsu->n; k++) + { + set_R_to_U(ruIndex, nsu->a[k]>>33, uId, 1, &(r_g->seq[nsu->a[k]>>33].c)); + } + } + + + for (i = 0; i < bub->b_ug->u.n; i++) + { + u = &(bub->b_ug->u.a[i]); + if(u->n < 3) continue; ///should be at least 3 + for (bub_i = 1; bub_i+1 < u->n; bub_i++) + { + m_bub = u->a[bub_i]>>33; l_bub = r_bub = (uint64_t)-1; + if(m_bub < beg_idx || m_bub >= beg_idx + occ) continue; + l_bub = u->a[bub_i-1]>>33; + r_bub = u->a[bub_i+1]>>33; + + set_rtg_flag_by_bubble(bub, ug, r_g, l_bub, expect_vis, 1); + set_rtg_flag_by_bubble(bub, ug, r_g, r_bub, expect_vis, 1); + set_rtg_flag_by_bubble(bub, ug, r_g, m_bub, expect_vis, 1); + get_bubbles(bub, m_bub, &beg_utg, &sink_utg, &a, &n, NULL); + for (k_i = 0; k_i < n; k_i++) + { + uId = a[k_i]>>1; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + + rbub_edges.n = round = 0; + for (k_v = 0; k_v < 2; k_v++) + { + if(rbub_edges.n > 0) + { + cur_backward_steps = nsu->n - round - 1; + if(cur_backward_steps > backward_steps) + { + cur_backward_steps = backward_steps; + } + } + else + { + cur_backward_steps = backward_steps; + } + + + v = (uId<<1) + k_v; + if(get_real_length(nsg, v, NULL) != 0) continue; + ///fprintf(stderr, "++++++tig-utg%.6ul\n", uId+1); + ///that means this unitig has been changed + // if(nsu->start!=((uint64_t)(nsu->a[0])>>32)) continue; + // if((nsu->end^1)!=((uint64_t)(nsu->a[nsu->n-1])>>32)) continue; + + if(v&1) + { + init = 0; + step = 1; + mode = 1; + } + else + { + init = nsu->n - 1; + step = -1; + mode = 0; + } + + rbub_edges.n = 0; + for (round = 0; round < cur_backward_steps && init >= 0 && init < (long long)nsu->n; + init = init + step, round++) + { + endRid = ((uint64_t)(nsu->a[init]))>>32; + endRid = endRid^mode; + + k = 0; rbub_edges.n = 0; + while(get_edge2existing_node_advance_by_broken_bub(ug, r_g, sources, coverage_cut, + ruIndex, expect_vis, max_hang, min_ovlp, endRid, &k, &r_edge, 1)) + { + kv_push(asg_arc_t, rbub_edges, r_edge); + } + + if(rbub_edges.n > 0) break; + } + + if(rbub_edges.n > 0) + { + //save for revert + tmp = mode; tmp = tmp <<31; tmp = tmp | (uint64_t)(init); tmp = tmp << 32; tmp = tmp | uId; + kv_push(uint64_t, u_vecs.a, tmp); + ///need to do transitive reduction + ///note here is different to standard transitive reduction + minor_transitive_reduction_r_g(r_g, rbub_edges.a, rbub_edges.n); + + + ///modify read graph + for (init = init - step; init >= 0 && init < (long long)nsu->n; init = init - step) + { + w = ((uint64_t)(nsu->a[init]))>>32; + nv = asg_arc_n(r_g, w); + av = asg_arc_a(r_g, w); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + kv_push(asg_arc_t, recover_edges.a, av[k]); + if(asg_get_arc(r_g, av[k].v^1, av[k].ul>>32^1, &t)==0) + { + fprintf(stderr, "error\n"); + } + kv_push(asg_arc_t, recover_edges.a, t); + } + + + nv = asg_arc_n(r_g, w^1); + av = asg_arc_a(r_g, w^1); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + kv_push(asg_arc_t, recover_edges.a, av[k]); + if(asg_get_arc(r_g, av[k].v^1, av[k].ul>>32^1, &t)==0) + { + fprintf(stderr, "error\n"); + } + kv_push(asg_arc_t, recover_edges.a, t); + } + + ///w = ((uint64_t)(nsu->a[init]))>>32; + asg_seq_del(r_g, w>>1); + expect_vis[w>>1] = 0; + } + + + for (k = 0; k < rbub_edges.n; k++) + { + t = rbub_edges.a[k]; + if(t.del) continue; + + kv_push(asg_arc_t, new_edges, t); + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, + (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); + } + } + + } + } + + + set_rtg_flag_by_bubble(bub, ug, r_g, l_bub, expect_vis, 0); + set_rtg_flag_by_bubble(bub, ug, r_g, r_bub, expect_vis, 0); + set_rtg_flag_by_bubble(bub, ug, r_g, m_bub, expect_vis, 0); + } + } + + asg_arc_t* p = NULL; + for (k = 0; k < new_edges.n; k++) + { + p = asg_arc_pushp(r_g); + *p = new_edges.a[k]; + } + if(new_edges.n != 0) + { + free(r_g->idx); + r_g->idx = 0; + r_g->is_srt = 0; + asg_cleanup(r_g); + asg_symm(r_g); + } + + pre_clean(sources, coverage_cut, r_g, 0); + + lable_all_bubbles(r_g, b_mask_t); + + for (k = 0; k < new_edges.n; k++) + { + v = new_edges.a[k].ul>>32; + w = new_edges.a[k].v; + + if(r_g->seq[v>>1].del) continue; + if(r_g->seq[w>>1].del) continue; + ///if this edge is at a bubble + if(r_g->seq_vis[v]!=0 && r_g->seq_vis[w^1]!=0) continue; + + asg_arc_del(r_g, v, w, 1); + asg_arc_del(r_g, w^1, v^1, 1); + } + asg_cleanup(r_g); + asg_symm(r_g); + + for (k = 0; k < recover_edges.a.n; k++) + { + recover_edges.a.a[k].del = 1; + } + + for (k = 0; k < u_vecs.a.n; k++) + { + mode = (uint64_t)u_vecs.a.a[k]>>63; + if(mode == 1) step = 1; + if(mode == 0) step = -1; + init = (uint64_t)((uint64_t)u_vecs.a.a[k]>>32)&((uint64_t)(0x7fffffff)); + uId = (uint32_t)u_vecs.a.a[k]; + nsu = &(ug->u.a[uId]); + + endRid = ((uint64_t)(nsu->a[init]))>>32; + endRid = endRid^mode; + if(get_real_length(r_g, endRid, NULL) > 0) + { + update_unitig(step, init, nsu, r_g, &recover_edges, 1); + } + else + { + update_unitig(step, init, nsu, r_g, &recover_edges, 0); + } + // if(get_real_length(r_g, endRid, NULL) <= 0) + // { + // update_unitig(step, init, nsu, r_g, &recover_edges, 0); + // } + } + + uint64_t recov_occ = 0; + for (k = 0; k < recover_edges.a.n; k++) + { + if(recover_edges.a.a[k].del) continue; + p = asg_arc_pushp(r_g); + *p = recover_edges.a.a[k]; + recov_occ++; + } + + if(recov_occ != 0) + { + free(r_g->idx); + r_g->idx = 0; + r_g->is_srt = 0; + asg_cleanup(r_g); + asg_symm(r_g); + } + + + for (v = 0; v < ruIndex->len; v++) + { + get_R_to_U(ruIndex, v, &uId, &is_Unitig); + if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; + } + + // fprintf(stderr, "M::%s has done!\n", __func__); + // print_bubble_filling_status(ug, r_g, ruIndex, bub, beg_idx, occ, new_edges.a, new_edges.n); + + kv_destroy(new_edges); + kv_destroy(rbub_edges); + kv_destroy(u_vecs.a); + kv_destroy(recover_edges.a); + free(expect_vis); +} + + +void reset_bub(bubble_type* bub, ma_ug_t *ug, trans_chain* back_ug_chain, kvec_asg_arc_t_warp* new_rtg_edges) +{ + destory_bubbles(bub); + memset(bub, 0, sizeof(bubble_type)); + + if(new_rtg_edges) new_rtg_edges->a.n = 0; + ///classify_untigs(ug, sg, coverage_cut, sources, reverse_sources, ruIndex, new_rtg_edges, max_hang, min_ovlp); + identify_bubbles(ug, bub, back_ug_chain->ir_het, NULL); + // update_bubble_chain(ug, bub, 0, 1); + // resolve_bubble_chain_tangle(ug, bub); + // fprintf(stderr, "bub.f_bub: %lu, bub.b_bub: %lu, bub.b_end_bub: %lu, bub.tangle_bub: %lu, bub.cross_bub: %lu\n", + // bub->f_bub, bub->b_bub, bub->b_end_bub, bub->tangle_bub, bub->cross_bub); +} + + +int bub_complex(asg_t *sg, ma_ug_t *ug, bubble_type* bub, uint32_t bid, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, kvec_t_u32_warp* stack, +int max_hang, int min_ovlp, uint8_t* trio_flag, uint8_t* vis_flag, kv_asg_arc_t* e, buf_t *b, uint64_t tLen) +{ + if(bid >= bub->f_bub) return 0; + uint32_t beg_utg, sink_utg, *a = NULL, n, begRid, sinkRid, i, k_i, k_j, k_v, rID/**, cur_flag, pre_flag, after_flag**/; + int is_switch_0, is_switch_1; + ma_utg_t* nsu = NULL; + get_bubbles(bub, bid, &beg_utg, &sink_utg, &a, &n, NULL); + if(beg_utg == (uint32_t)-1 || sink_utg == (uint32_t)-1) return 0; + if(beg_utg&1) + { + begRid = ug->u.a[beg_utg>>1].start^1; + } + else + { + begRid = ug->u.a[beg_utg>>1].end^1; + } + + if(sink_utg&1) + { + sinkRid = ug->u.a[sink_utg>>1].start; + } + else + { + sinkRid = ug->u.a[sink_utg>>1].end; + } + + + + is_switch_0 = is_switch_1 = 1; + asg_bub_pop1_primary_trio_switch_check(ug->g, ug, beg_utg, tLen, b, FATHER, DROP, 0, NULL, NULL, &is_switch_0); + + if(is_switch_0 == 0) + { + asg_bub_pop1_primary_trio_switch_check(ug->g, ug, beg_utg, tLen, b, MOTHER, DROP, 0, NULL, NULL, &is_switch_1); + } + + + for (k_i = 0; k_i < n; k_i++) + { + nsu = &(ug->u.a[a[k_i]>>1]); + for (k_j = 0; k_j < nsu->n; k_j++) + { + rID = nsu->a[k_j]>>33; + if(R_INF.trio_flag[rID] == DROP) R_INF.trio_flag[rID] = AMBIGU; + } + } + /*******************************for debug************************************/ + // for (i = 0; i < sg->n_seq; i++) + // { + // if(R_INF.trio_flag[i] == DROP) fprintf(stderr, "ERROR-1\n"); + // } + /*******************************for debug************************************/ + + if(is_switch_0 == 0 && is_switch_1 == 0) return 0; + + asg_arc_t *acur = NULL; + uint32_t cur, ncur, v, n_vx = sg->n_seq<<1; + stack->a.n = 0; + memset(vis_flag, 0, n_vx); + + kv_push(uint32_t, stack->a, begRid); + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + ncur = asg_arc_n(sg, cur); + acur = asg_arc_a(sg, cur); + vis_flag[cur] = 1; + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if(vis_flag[acur[i].v]) continue; + if(acur[i].v == sinkRid) continue; + kv_push(uint32_t, stack->a, acur[i].v); + } + } + vis_flag[sinkRid] = 1; + + + ma_hit_t_alloc* x = NULL; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + int32_t r; + asg_arc_t t; + + + for (k_i = 0; k_i < n; k_i++) + { + nsu = &(ug->u.a[a[k_i]>>1]); + for (k_j = 0; k_j < nsu->n; k_j++) + { + rID = nsu->a[k_j]>>33; + for (k_v = 0; k_v < 2; k_v++) + { + v = (rID<<1) + k_v; + if(vis_flag[v] == 0) continue; + x = &(sources[v>>1]); + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(st->del || sg->seq[Get_tn(*h)].del) continue; + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + + ///if it is a contained read, skip + if(r < 0) continue; + if((t.ul>>32) != v) continue; + if(vis_flag[t.ul>>32] == 0 || vis_flag[t.v] == 0) continue; + kv_push(asg_arc_t, *e, t); + get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, + (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, *e, t); + } + + } + } + } + + return 1; + + /** + for (v = 0; v < n_vx; v++) + { + if(vis_flag[v] == 0) continue; + fprintf(stderr, "v: %u, n_vx: %u\n", v, n_vx); + x = &(sources[v>>1]); + for (i = 0; i < x->length; i++) + { + fprintf(stderr, "i: %u, x->length: %u\n", i, x->length); + h = &(x->buffer[i]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(st->del || sg->seq[Get_tn(*h)].del) continue; + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + + ///if it is a contained read, skip + if(r < 0) continue; + if((t.ul>>32) != v) continue; + if(vis_flag[t.ul>>32] == 0 || vis_flag[t.v] == 0) continue; + kv_push(asg_arc_t, *e, t); + get_edge_from_source(sources, coverage_cut, NULL, max_hang, min_ovlp, + (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, *e, t); + } + } + **/ + + + /*******************************for debug************************************/ + // uint32_t utg_occ = 0, rtg_occ = 0; + // for (i = 0; i < n; i++) + // { + // utg_occ += ug->u.a[a[i]>>1].n; + // } + + // for (i = 0; i < n_vx; i++) + // { + // if(vis_flag[i]) rtg_occ++; + // } + + // fprintf(stderr, "bid: %u, rtg_occ: %u, utg_occ: %u\n", bid, rtg_occ, utg_occ); + // if(rtg_occ != utg_occ + 2) fprintf(stderr, "ERROR\n"); + /*******************************for debug************************************/ +} + + +void debug_bubble_chain(asg_t *sg, ma_ug_t *ug, bubble_type* bub, uint32_t bid, kvec_t_u32_warp* stack, uint8_t* vis_flag) +{ + if(bid >= bub->f_bub) return; + uint32_t beg_utg, sink_utg, *a = NULL, n, begRid, sinkRid; + get_bubbles(bub, bid, &beg_utg, &sink_utg, &a, &n, NULL); + if(beg_utg == (uint32_t)-1 || sink_utg == (uint32_t)-1) return; + if(beg_utg&1) + { + begRid = ug->u.a[beg_utg>>1].start^1; + } + else + { + begRid = ug->u.a[beg_utg>>1].end^1; + } + + if(sink_utg&1) + { + sinkRid = ug->u.a[sink_utg>>1].start; + } + else + { + sinkRid = ug->u.a[sink_utg>>1].end; + } + + asg_arc_t *acur = NULL; + uint32_t cur, ncur, i, n_vx = sg->n_seq<<1; + stack->a.n = 0; + memset(vis_flag, 0, n_vx); + + kv_push(uint32_t, stack->a, begRid); + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + ncur = asg_arc_n(sg, cur); + acur = asg_arc_a(sg, cur); + vis_flag[cur] = 1; + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if(vis_flag[acur[i].v]) continue; + if(acur[i].v == sinkRid) continue; + kv_push(uint32_t, stack->a, acur[i].v); + } + } + vis_flag[sinkRid] = 1; + + + /*******************************for debug************************************/ + uint32_t utg_occ = 0, rtg_occ = 0; + for (i = 0; i < n; i++) + { + utg_occ += ug->u.a[a[i]>>1].n; + } + + for (i = 0; i < n_vx; i++) + { + if(vis_flag[i]) rtg_occ++; + } + + fprintf(stderr, "bid: %u, rtg_occ: %u, utg_occ: %u\n", bid, rtg_occ, utg_occ); + if(rtg_occ != utg_occ + 2) fprintf(stderr, "ERROR\n"); + /*******************************for debug************************************/ +} + +void rescue_missing_hap_ovlp(ma_ug_t *u_g, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +int max_hang, int min_ovlp, bubble_type* bub, long long gap_fuzz) +{ + uint32_t i, n_arc = r_g->n_arc, fix_bub = 0; + uint8_t* vis_flag = NULL; CALLOC(vis_flag, r_g->n_seq*2); + kvec_t_u32_warp stack; kv_init(stack.a); + kv_asg_arc_t e; kv_init(e); + double index_time = yak_realtime(); + + buf_t b; memset(&b, 0, sizeof(buf_t)); + b.a = (binfo_t*)calloc(u_g->g->n_seq * 2, sizeof(binfo_t)); + uint64_t tLen = get_bub_pop_max_dist_advance(u_g->g, &b); + for (i = 0; i < bub->f_bub; i++) + { + fix_bub += bub_complex(r_g, u_g, bub, i, sources, coverage_cut, &stack, max_hang, min_ovlp, R_INF.trio_flag, vis_flag, &e, &b, tLen); + } + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + + asg_arc_t* p = NULL; + for (i = 0; i < e.n; i++) + { + p = asg_arc_pushp(r_g); + *p = e.a[i]; + } + if(e.n != 0) + { + free(r_g->idx); + r_g->idx = 0; + r_g->is_srt = 0; + asg_cleanup(r_g); + asg_symm(r_g); + asg_arc_del_trans(r_g, gap_fuzz); + // for (i = 0; i < bub->f_bub; i++) + // { + // debug_bubble_chain(r_g, u_g, bub, i, &stack, vis_flag); + // } + } + + fprintf(stderr, "[M::%s::%.3f] # inserted edges: %u, # fixed bubbles: %u\n", + __func__, yak_realtime() - index_time, r_g->n_arc - n_arc, fix_bub); + + free(vis_flag); + kv_destroy(stack.a); + kv_destroy(e); +} + + +void rescue_bubble_by_chain(asg_t *sg, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, float chimeric_rate, float drop_ratio, +int max_hang, int min_ovlp, uint32_t chainLenThres, long long gap_fuzz, bub_label_t* b_mask_t, long long no_trio_recover, uint8_t *cmk) +{ + kvec_asg_arc_t_warp new_rtg_edges; + kv_init(new_rtg_edges.a); + ma_ug_t *ug = NULL; + ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); + + hap_cov_t *cov = NULL; + asg_t *copy_sg = copy_read_graph(sg); + ma_ug_t *copy_ug = copy_untig_graph(ug); + adjust_utg_by_primary(©_ug, copy_sg, TRIO_THRES, sources, reverse_sources, coverage_cut, + tipsLen, tip_drop_ratio, stops_threshold, ruIndex, chimeric_rate, drop_ratio, + max_hang, min_ovlp, &new_rtg_edges, &cov, b_mask_t, 0, 0); + ma_ug_destroy(copy_ug); copy_ug = NULL; + asg_destroy(copy_sg); copy_sg = NULL; + + uint32_t beg_idx, occ; + bubble_type bub; + memset(&bub, 0, sizeof(bubble_type)); + copy_ug = copy_untig_graph(ug); + reset_bub(&bub, ug, cov->t_ch, &new_rtg_edges); + beg_idx = bub.f_bub; occ = bub.b_bub + bub.b_end_bub + bub.tangle_bub; + rescue_bubbles_by_contained_reads(ug, sg, sources, coverage_cut, ruIndex, max_hang, min_ovlp, chainLenThres, beg_idx, occ, &bub, b_mask_t); + + ma_ug_destroy(ug); ug = NULL; ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); + reset_bub(&bub, ug, cov->t_ch, &new_rtg_edges); + beg_idx = bub.f_bub; occ = bub.b_bub + bub.b_end_bub + bub.tangle_bub; + rescue_bubbles_by_missing_ovlp(ug, sg, sources, coverage_cut, ruIndex, max_hang, min_ovlp, chainLenThres, beg_idx, occ, &bub, b_mask_t); + + ma_ug_destroy(ug); ug = NULL; ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); + reset_bub(&bub, ug, cov->t_ch, &new_rtg_edges); + beg_idx = bub.f_bub; occ = bub.b_bub + bub.b_end_bub + bub.tangle_bub; + rescue_bubbles_by_missing_ovlp_backward(ug, sg, sources, coverage_cut, ruIndex, max_hang, min_ovlp, chainLenThres, beg_idx, occ, &bub, b_mask_t); + + if(cmk) { + ma_ug_destroy(ug); ug = NULL; ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); + reset_bub(&bub, ug, cov->t_ch, &new_rtg_edges); + beg_idx = bub.f_bub; occ = bub.b_bub + bub.b_end_bub + bub.tangle_bub; + rescue_bubbles_by_cmk_reads(ug, sg, sources, coverage_cut, ruIndex, max_hang, min_ovlp, chainLenThres, beg_idx, occ, &bub, b_mask_t, cmk); + } + /** + if((!no_trio_recover) && (ha_opt_triobin(&asm_opt))) + { + ma_ug_destroy(ug); ug = NULL; ug = ma_ug_gen_primary(sg, PRIMARY_LABLE); + reset_bub(&bub, ug, cov->t_ch, &new_rtg_edges); + // rescue_missing_hap_ovlp(ug, sg, sources, coverage_cut, max_hang, min_ovlp, &bub, gap_fuzz); + reduce_hamming_error_adv(ug, sg, sources, coverage_cut, max_hang, min_ovlp, gap_fuzz, ruIndex, &bub); + } + **/ + + destory_bubbles(&bub); + destory_hap_cov_t(&cov); + ma_ug_destroy(ug); + kv_destroy(new_rtg_edges.a); + ma_ug_destroy(copy_ug); copy_ug = NULL; +} + +void update_unitig(long long step, long long init, ma_utg_t* nsu, asg_t *r_g, +kvec_asg_arc_t_warp* recover_edges, uint32_t update_mode) +{ + uint64_t l, k; + uint32_t v; + ///recover + if(update_mode == 0) + { + if(step == 1) nsu->start = ((uint64_t)(nsu->a[0])>>32); + if(step == -1) nsu->end = ((uint64_t)(nsu->a[nsu->n-1])>>32)^1; + if(recover_edges) + { + ///the first node has not been deleted, others has been deleted + for (init = init - step; init >= 0 && init < (long long)nsu->n; init = init - step) + { + v = (uint64_t)nsu->a[init]>>32; + r_g->seq[v>>1].del = 0; + for (k = 0; k < recover_edges->a.n; k++) + { + if(((v>>1)==(recover_edges->a.a[k].ul>>33)) || + ((v>>1)==(recover_edges->a.a[k].v>>1))) + { + recover_edges->a.a[k].del = 0; + } + } + } + } + } + else ///update + { + //end of unitig + if(step == -1 && init != (long long)((long long)nsu->n - 1)) + { + l = r_g->seq[(nsu->a[init]>>33)].len; + nsu->n = init+1; + nsu->a[nsu->n-1] = nsu->a[nsu->n-1]>>32; + nsu->a[nsu->n-1] = nsu->a[nsu->n-1]<<32; + nsu->a[nsu->n-1] = nsu->a[nsu->n-1] | (uint64_t)(l); + } + + //beg of unitig + if(step == 1 && init != 0) + { + for(k = init; k < nsu->n; k++) + { + nsu->a[k-init] = nsu->a[k]; + } + nsu->n = nsu->n - init; + } + + nsu->len = 0; + for(k = 0; k < nsu->n; k++) + { + nsu->len += (uint32_t)nsu->a[k]; + } + } +} +void rescue_missing_overlaps_backward(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t backward_steps, uint32_t is_bubble_check, uint32_t is_primary_check, bub_label_t* b_mask_t) +{ + uint32_t v, vId, dir, k, cur_backward_steps, round, is_Unitig, uId, rId, endRid, oLen, w, max_oLen, max_oLen_i, mode, nv; + uint64_t tmp; + long long init, step = 0; + asg_t* nsg = NULL; + ma_utg_t* nsu = NULL; + ma_ug_t *ug = NULL; + asg_arc_t *av = NULL; + asg_arc_t t, r_edge; + kvec_t(asg_arc_t) new_edges; + kv_init(new_edges); + + kvec_asg_arc_t_warp recover_edges; + kv_init(recover_edges.a); + + kvec_t(asg_arc_t) rbub_edges; + kv_init(rbub_edges); + + kvec_t_u64_warp u_vecs; + kv_init(u_vecs.a); + + if(i_ug != NULL) + { + ug = i_ug; + } + else + { + ug = ma_ug_gen(r_g); + for (v = 0; v < ug->g->n_seq; v++) + { + ug->g->seq[v].c = PRIMARY_LABLE; + } + } + nsg = ug->g; + + for (v = 0; v < nsg->n_seq; v++) + { + uId = v; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsg->seq[v].del) continue; + if(is_primary_check && nsg->seq[v].c==ALTER_LABLE) continue; + + for (k = 0; k < nsu->n; k++) + { + rId = nsu->a[k]>>33; + set_R_to_U(ruIndex, rId, uId, 1, &(r_g->seq[rId].c)); + } + } + + + + for (vId = 0; vId < nsg->n_seq; vId++) + { + rbub_edges.n = round = 0; + for (dir = 0; dir < 2; dir++) + { + if(rbub_edges.n > 0) + { + cur_backward_steps = nsu->n - round - 1; + if(cur_backward_steps > backward_steps) + { + cur_backward_steps = backward_steps; + } + } + else + { + cur_backward_steps = backward_steps; + } + + + + v = vId; v = v<<1; v = v | dir; + uId = v>>1; + if(nsg->seq[uId].del) continue; + if(is_primary_check && nsg->seq[uId].c == ALTER_LABLE) continue; + + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsu->circ || nsu->start == UINT32_MAX || nsu->end == UINT32_MAX) continue; + if(get_real_length(nsg, v, NULL) != 0) continue; + ////if(get_real_length(nsg, v^1, NULL) == 0) continue; + ///that means this unitig has been changed + if(nsu->start!=((uint64_t)(nsu->a[0])>>32)) continue; + if((nsu->end^1)!=((uint64_t)(nsu->a[nsu->n-1])>>32)) continue; + + if(v&1) + { + init = 0; + step = 1; + mode = 1; + //endRid = nsu->start^1; + } + else + { + init = nsu->n - 1; + step = -1; + mode = 0; + ///endRid = nsu->end^1; + } + + + rbub_edges.n = 0; + for (round = 0; round < cur_backward_steps && init >= 0 && init < (long long)nsu->n; + init = init + step, round++) + { + endRid = ((uint64_t)(nsu->a[init]))>>32; + endRid = endRid^mode; + + k = 0; + rbub_edges.n = 0; + while(get_edge2existing_node_advance(ug, r_g, sources, coverage_cut, ruIndex, + max_hang, min_ovlp, endRid, &uId, 1, &k, &r_edge, 1)) + { + kv_push(asg_arc_t, rbub_edges, r_edge); + } + if(rbub_edges.n > 0) break; + } + + if(rbub_edges.n > 0) + { + if(mode == 1) nsu->start = endRid^1; + if(mode == 0) nsu->end = endRid^1; + //save for revert + tmp = mode; tmp = tmp <<31; tmp = tmp | (uint64_t)(init); tmp = tmp << 32; tmp = tmp | uId; + kv_push(uint64_t, u_vecs.a, tmp); + + + + ///need to do transitive reduction + ///note here is different to standard transitive reduction + minor_transitive_reduction(ug, ruIndex, rbub_edges.a, rbub_edges.n); + if(is_primary_check) + { + max_oLen = 0; max_oLen_i = (uint32_t)-1; + for (k = 0; k < rbub_edges.n; k++) + { + t = rbub_edges.a[k]; + if(t.del) continue; + if(t.ol > max_oLen) + { + max_oLen = t.ol; + max_oLen_i = k; + } + } + + if(max_oLen_i == (uint32_t)-1) continue; + t = rbub_edges.a[max_oLen_i]; + w = get_corresponding_uId(ug, ruIndex, t.v); + if(w == ((uint32_t)(-1))) continue; + if(get_real_length(nsg, w^1, NULL)!=0) continue; + + kv_push(asg_arc_t, new_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); + + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, + (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); + } + else + { + ///modify read graph + for (init = init - step; init >= 0 && init < (long long)nsu->n; init = init - step) + { + w = ((uint64_t)(nsu->a[init]))>>32; + nv = asg_arc_n(r_g, w); + av = asg_arc_a(r_g, w); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + kv_push(asg_arc_t, recover_edges.a, av[k]); + if(asg_get_arc(r_g, av[k].v^1, av[k].ul>>32^1, &t)==0) + { + fprintf(stderr, "error\n"); + } + kv_push(asg_arc_t, recover_edges.a, t); + } + + + nv = asg_arc_n(r_g, w^1); + av = asg_arc_a(r_g, w^1); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + kv_push(asg_arc_t, recover_edges.a, av[k]); + if(asg_get_arc(r_g, av[k].v^1, av[k].ul>>32^1, &t)==0) + { + fprintf(stderr, "error\n"); + } + kv_push(asg_arc_t, recover_edges.a, t); + } + + ///w = ((uint64_t)(nsu->a[init]))>>32; + asg_seq_del(r_g, w>>1); + } + + + + for (k = 0; k < rbub_edges.n; k++) + { + t = rbub_edges.a[k]; + if(t.del) continue; + w = get_corresponding_uId(ug, ruIndex, t.v); + if(w == ((uint32_t)(-1))) continue; + // get_R_to_U(ruIndex, t.v>>1, &uId, &is_Unitig); + // w = (uint32_t)-1; + // if(t.v == ug->u.a[uId].start) w = uId<<1; + // if(t.v == ug->u.a[uId].end) w = (uId<<1)^1; + kv_push(asg_arc_t, new_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); + + + get_edge_from_source(sources, coverage_cut, ruIndex, max_hang, min_ovlp, + (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, new_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); + } + } + + } + } + } + + + if(is_bubble_check) + { + asg_arc_t* p = NULL; + for (k = 0; k < new_edges.n; k++) + { + p = asg_arc_pushp(r_g); + *p = new_edges.a[k]; + } + + if(new_edges.n != 0) + { + free(r_g->idx); + r_g->idx = 0; + r_g->is_srt = 0; + asg_cleanup(r_g); + } + + pre_clean(sources, coverage_cut, r_g, 0); + + lable_all_bubbles(r_g, b_mask_t); + + + for (k = 0; k < new_edges.n; k++) + { + v = new_edges.a[k].ul>>32; + w = new_edges.a[k].v; + + if(r_g->seq[v>>1].del) continue; + if(r_g->seq[w>>1].del) continue; + ///if this edge is at a bubble + if(r_g->seq_vis[v]!=0 && r_g->seq_vis[w^1]!=0) continue; + + asg_arc_del(r_g, v, w, 1); + asg_arc_del(r_g, w^1, v^1, 1); + } + + asg_cleanup(r_g); + + + for (k = 0; k < recover_edges.a.n; k++) + { + recover_edges.a.a[k].del = 1; + } + + for (k = 0; k < u_vecs.a.n; k++) + { + mode = (uint64_t)u_vecs.a.a[k]>>63; + if(mode == 1) step = 1; + if(mode == 0) step = -1; + init = (uint64_t)((uint64_t)u_vecs.a.a[k]>>32)&((uint64_t)(0x7fffffff)); + uId = (uint32_t)u_vecs.a.a[k]; + nsu = &(ug->u.a[uId]); + + endRid = ((uint64_t)(nsu->a[init]))>>32; + endRid = endRid^mode; + /********************for debug**********************/ + // fprintf(stderr, "n: %u, k: %u, mode: %u, init: %lld, step: %lld, uId: %u, endRid: %u\n", + // (uint32_t)u_vecs.a.n, k, mode, init, step, uId, endRid); + // fprintf(stderr, "nsu->start: %u, nsu->end: %u\n", + // nsu->start, nsu->end); + // if(mode == 1 && nsu->start != (endRid^1)) fprintf(stderr, "ERROR\n"); + // if(mode == 0 && nsu->end != (endRid^1)) fprintf(stderr, "ERROR\n"); + // update_unitig(step, init, nsu, r_g, &recover_edges, 0); + /********************for debug**********************/ + if(get_real_length(r_g, endRid, NULL) > 0) + { + update_unitig(step, init, nsu, r_g, &recover_edges, 1); + // fprintf(stderr, "endRid: %u, %.*s, uId: %u\n", + // endRid>>1, (int)Get_NAME_LENGTH((R_INF), v>>1), Get_NAME((R_INF), v>>1), uId); + } + else + { + update_unitig(step, init, nsu, r_g, &recover_edges, 0); + } + } + + uint64_t recov_occ = 0; + for (k = 0; k < recover_edges.a.n; k++) + { + if(recover_edges.a.a[k].del) continue; + p = asg_arc_pushp(r_g); + *p = recover_edges.a.a[k]; + recov_occ++; + } + + if(recov_occ != 0) + { + free(r_g->idx); + r_g->idx = 0; + r_g->is_srt = 0; + } + + asg_cleanup(r_g); + } + + if(is_primary_check) + { + for (k = 0; k < u_vecs.a.n; k++) + { + mode = (uint64_t)u_vecs.a.a[k]>>63; + if(mode == 1) step = 1; + if(mode == 0) step = -1; + init = (uint64_t)((uint64_t)u_vecs.a.a[k]>>32)&((uint64_t)(0x7fffffff)); + uId = (uint32_t)u_vecs.a.a[k]; + nsu = &(ug->u.a[uId]); + + endRid = ((uint64_t)(nsu->a[init]))>>32; + endRid = endRid^mode; + + update_unitig(step, init, nsu, r_g, &recover_edges, 1); + } + } + + + for (v = 0; v < ruIndex->len; v++) + { + get_R_to_U(ruIndex, v, &uId, &is_Unitig); + if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; + } + + if(i_ug == NULL) ma_ug_destroy(ug); + + kv_destroy(new_edges); + kv_destroy(recover_edges.a); + kv_destroy(rbub_edges); + kv_destroy(u_vecs.a); +} + + + + +void rescue_wrong_overlaps_to_unitigs(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +ma_sub_t *coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp, long long bubble_dist, +kvec_asg_arc_t_warp* keep_edges, bub_label_t* b_mask_t) +{ + uint32_t n_vtx, v, k, is_Unitig, uId, rId, endRid, oLen, w; + asg_t* nsg = NULL; + ma_utg_t* nsu = NULL; + ma_ug_t *ug = NULL; + asg_arc_t t, r_edge; + ma_hit_t_alloc* x = NULL; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + int32_t r; + + kvec_t(asg_arc_t) new_utg_edges; + kv_init(new_utg_edges); + + kvec_t(asg_arc_t) new_rtg_edges; + kv_init(new_rtg_edges); + + kvec_t(asg_arc_t) rbub_edges; + kv_init(rbub_edges); + + if(i_ug != NULL) + { + ug = i_ug; + } + else + { + ug = ma_ug_gen(r_g); + for (v = 0; v < ug->g->n_seq; v++) + { + ug->g->seq[v].c = PRIMARY_LABLE; + } + } + + nsg = ug->g; + + for (v = 0; v < nsg->n_seq; v++) + { + uId = v; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsg->seq[v].del) continue; + + for (k = 0; k < nsu->n; k++) + { + rId = nsu->a[k]>>33; + set_R_to_U(ruIndex, rId, uId, 1, &(r_g->seq[rId].c)); + } + } + + n_vtx = nsg->n_seq * 2; + for (v = 0; v < n_vtx; v++) + { + uId = v>>1; + if(nsg->seq[uId].del) continue; + + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsu->circ || nsu->start == UINT32_MAX || nsu->end == UINT32_MAX) continue; + if(get_real_length(nsg, v, NULL) != 0) continue; + + + + if(v&1) + { + endRid = nsu->start^1; + } + else + { + endRid = nsu->end^1; + } + + + + /****************************may have bugs********************************/ + x = &(sources[(endRid>>1)]); + for (k = 0; k < x->length; k++) + { + ///h is the edge of endRid + h = &(x->buffer[k]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + ///sq, st, and h cannot be deleted + if(sq->del || st->del || h->del) continue; + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + if(r < 0) continue; + if((t.ul>>32) != endRid) continue; + break; + } + ///means there is >0 edges + if(k != x->length) continue; + /****************************may have bugs********************************/ + + + + + k = 0; + rbub_edges.n = 0; + ///note here use reverse_sources instead of sources + while(get_edge2existing_node_advance(ug, r_g, reverse_sources, coverage_cut, ruIndex, + max_hang, min_ovlp, endRid, &uId, 1, &k, &r_edge, 1)) + { + kv_push(asg_arc_t, rbub_edges, r_edge); + } + + + + if(rbub_edges.n > 0) + { + ///need to do transitive reduction + ///note here is different to standard transitive reduction + minor_transitive_reduction(ug, ruIndex, rbub_edges.a, rbub_edges.n); + + for (k = 0; k < rbub_edges.n; k++) + { + t = rbub_edges.a[k]; + if(t.del) continue; + w = get_corresponding_uId(ug, ruIndex, t.v); + if(w == ((uint32_t)(-1))) continue; + ///if(uId == 2474) fprintf(stderr, "###uId: %u, v: %u, r_edge.v>>1: %u\n", uId, v, r_edge.v>>1); + kv_push(asg_arc_t, new_rtg_edges, t); + oLen = t.ol; + asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, oLen, t.strong, t.el, t.no_l_indel); + + + get_edge_from_source(reverse_sources, coverage_cut, ruIndex, max_hang, min_ovlp, + (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, new_rtg_edges, t); + ///if edge does not exist in reverse, oLen won't change, it is what we want + oLen = t.ol; + asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, oLen, t.strong, t.el, t.no_l_indel); + + t.ul = v; t.ul = t.ul<<32; t.v = w; + kv_push(asg_arc_t, new_utg_edges, t); + + + t.ul = w^1; t.ul = t.ul<<32; t.v = v^1; + kv_push(asg_arc_t, new_utg_edges, t); + } + } + + } + + + nsg->seq_vis = (uint8_t*)calloc(nsg->n_seq*2, sizeof(uint8_t)); + lable_all_bubbles(nsg, b_mask_t); + + /*********************************for debug**************************************/ + // uint32_t v_uId, w_uId; + // if(new_utg_edges.n != new_rtg_edges.n) fprintf(stderr, "ERROR 1\n"); + // for (k = 0; k < new_utg_edges.n; k++) + // { + // v = new_rtg_edges.a[k].ul>>32; + // v_uId = (get_corresponding_uId(ug, ruIndex, v^1)^1); + // w = new_rtg_edges.a[k].v; + // w_uId = get_corresponding_uId(ug, ruIndex, w); + + // v = new_utg_edges.a[k].ul>>32; + // w = new_utg_edges.a[k].v; + + // if(v!=v_uId || w!= w_uId) + // { + // fprintf(stderr, "\n(%u) ERROR 2\n", k); + // fprintf(stderr, "v>>1: %u, v&1: %u, ug->u.a[v>>1].n: %u\n", + // v>>1, v&1, ug->u.a[v>>1].n); + // fprintf(stderr, "ug->u.a[v>>1].start>>1: %u, ug->u.a[v>>1].start&1: %u\n", + // ug->u.a[v>>1].start>>1, ug->u.a[v>>1].start&1); + // fprintf(stderr, "ug->u.a[v>>1].end>>1: %u, ug->u.a[v>>1].end&1: %u\n", + // ug->u.a[v>>1].end>>1, ug->u.a[v>>1].end&1); + // fprintf(stderr, "w>>1: %u, w&1: %u, ug->u.a[w>>1].n: %u\n", + // w>>1, w&1, ug->u.a[w>>1].n); + // fprintf(stderr, "ug->u.a[w>>1].start>>1: %u, ug->u.a[w>>1].start&1: %u\n", + // ug->u.a[w>>1].start>>1, ug->u.a[w>>1].start&1); + // fprintf(stderr, "ug->u.a[w>>1].end>>1: %u, ug->u.a[w>>1].end&1: %u\n", + // ug->u.a[w>>1].end>>1, ug->u.a[w>>1].end&1); + // fprintf(stderr, "v_uId>>1: %u, v_uId&1: %u\n", v_uId>>1, v_uId&1); + // fprintf(stderr, "w_uId>>1: %u, w_uId&1: %u\n", w_uId>>1, w_uId&1); + // v = new_rtg_edges.a[k].ul>>32; + // w = new_rtg_edges.a[k].v; + // get_R_to_U(ruIndex, v>>1, &uId, &is_Unitig); + // fprintf(stderr, "v(read)>>1: %u, v(read)&1: %u, uId: %u, is_Unitig: %u\n", + // v>>1, v&1, uId, is_Unitig); + // get_R_to_U(ruIndex, w>>1, &uId, &is_Unitig); + // fprintf(stderr, "w(read)>>1: %u, w(read)&1: %u, uId: %u, is_Unitig: %u\n", + // w>>1, w&1, uId, is_Unitig); + + + // } + // } + /*********************************for debug**************************************/ + + for (k = 0; k < new_utg_edges.n; k++) + { + v = new_utg_edges.a[k].ul>>32; + w = new_utg_edges.a[k].v; + + if(nsg->seq[v>>1].del) continue; + if(nsg->seq[w>>1].del) continue; + ///if this edge is at a bubble + if(nsg->seq_vis[v]!=0 && nsg->seq_vis[w^1]!=0) + { + ///fprintf(stderr, "v>>1: %u, w>>1: %u\n", v>>1, w>>1); + continue; + } + + asg_arc_del(nsg, v, w, 1); + asg_arc_del(nsg, w^1, v^1, 1); + new_rtg_edges.a[k].del = 1; + } + asg_cleanup(nsg); + free(nsg->seq_vis); nsg->seq_vis = NULL; + + /*********************************for debug**************************************/ + asg_arc_t* p = NULL; + uint32_t e_occ = 0; + for (k = 0; k < new_rtg_edges.n; k++) + { + if(new_rtg_edges.a[k].del) continue; + p = asg_arc_pushp(r_g); + *p = new_rtg_edges.a[k]; + e_occ++; + if(keep_edges) kv_push(asg_arc_t, keep_edges->a, new_rtg_edges.a[k]); + } + + if(e_occ != 0) + { + free(r_g->idx); + r_g->idx = 0; + r_g->is_srt = 0; + asg_cleanup(r_g); + } + /*********************************for debug**************************************/ + + for (v = 0; v < ruIndex->len; v++) + { + get_R_to_U(ruIndex, v, &uId, &is_Unitig); + if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; + } + + if(i_ug == NULL) ma_ug_destroy(ug); + kv_destroy(new_utg_edges); + kv_destroy(new_rtg_edges); + kv_destroy(rbub_edges); +} + + + + +///find contained read with longest overlap +ma_hit_t* get_best_no_coverage_read(ma_ug_t *ug, asg_t *r_g, ma_hit_t_alloc* reverse_sources, +ma_sub_t *coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, +uint32_t init_contain_uId) +{ + uint32_t qn = query>>1; + int32_t r; + asg_arc_t t; + ma_hit_t *h = NULL, *return_h = NULL; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + ma_hit_t_alloc* x = &(reverse_sources[qn]); + uint32_t i, is_Unitig, contain_uId; + uint32_t maxOlen = 0; + asg_t* nsg = ug->g; + + + //scan all edges of qn + for (i = 0; i < x->length; i++) + { + h = &(x->buffer[i]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + + ///all of them cannot be removed + if(sq->del || st->del || h->del) continue; + if(r_g->seq[Get_qn(*h)].del || r_g->seq[Get_tn(*h)].del) continue; + + get_R_to_U(ruIndex, Get_tn(*h), &contain_uId, &is_Unitig); + if(contain_uId == (uint32_t)-1 || is_Unitig != 1) continue; + if(nsg->seq[contain_uId].del) continue; + ///contain_uId must be a unitig + + if(init_contain_uId != contain_uId) continue; + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + + ///if it is a contained read, skip + if(r < 0) continue; + + if((t.ul>>32) != query) continue; + + if(t.ol > maxOlen) + { + maxOlen = t.ol; + return_h = h; + } + } + + return return_h; +} + + + + + +int get_no_coverage_reads_chain_simple(ma_hit_t *h, ma_hit_t_alloc* sources, +ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, ma_ug_t *ug, +asg_t *r_g, int max_hang, int min_ovlp, uint32_t endRid, uint32_t uId, +kvec_t_u32_warp* chain_buffer, kvec_asg_arc_t_warp* chain_edges, uint32_t* return_ava_cur, +uint32_t* return_ava_ol, uint32_t* return_chainLen, uint32_t thresLen) +{ + (*return_chainLen) = (*return_ava_cur) = (*return_ava_ol) = (uint32_t)-1; + uint32_t init_contain_uId = (uint32_t)-1, contain_uId, is_Unitig; + uint32_t chainLen = 0, ava_cur, test_oLen; + int ql, tl; + int32_t r; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + asg_arc_t t; + asg_t* nsg = ug->g; + chain_buffer->a.n = 0; + kv_push(uint32_t, chain_buffer->a, uId); + if(chain_edges) chain_edges->a.n = 0; + + if(!h) return 0; + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + ///sq and st cannot be deleted + ///for h, deleted or not does not matter + if(sq->del || st->del) return 0; + if(r_g->seq[Get_qn(*h)].del || r_g->seq[Get_tn(*h)].del) return 0; + get_R_to_U(ruIndex, Get_tn(*h), &contain_uId, &is_Unitig); + if(contain_uId == (uint32_t)-1 || is_Unitig != 1) return 0; + if(nsg->seq[contain_uId].del) return 0; + ql = sq->e - sq->s; tl = st->e - st->s; + r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + if(r < 0) return 0; + if((t.ul>>32) != endRid) return 0; + if(chain_edges) kv_push(asg_arc_t, chain_edges->a, t); + chainLen++; + kv_push(uint32_t, chain_buffer->a, contain_uId); + ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, reverse_sources, coverage_cut, + ruIndex, max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, 1); + //means find an aim + if(ava_cur > 0) + { + (*return_ava_cur) = ava_cur; + (*return_ava_ol) = test_oLen; + (*return_chainLen) = chainLen; + h = NULL; + return 1; + } + else + { + return 0; + } + + + ///continue + ///need to update h, endRid, chainLen, chain_buffer and chain_edges + while (h) + { + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + + ///sq, st, and h cannot be deleted + if(sq->del || st->del || h->del) break; + if(r_g->seq[Get_qn(*h)].del || r_g->seq[Get_tn(*h)].del) break; + + get_R_to_U(ruIndex, Get_tn(*h), &contain_uId, &is_Unitig); + if(contain_uId == (uint32_t)-1 || is_Unitig != 1) break; + if(nsg->seq[contain_uId].del) break; + ///contain_uId must be a unitig + + if(init_contain_uId != (uint32_t)-1) + { + init_contain_uId = contain_uId; + } + else + { + if(init_contain_uId != contain_uId) break; + } + + + ql = sq->e - sq->s; tl = st->e - st->s; + r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + + ///if st is contained in sq, or vice verse, skip + if(r < 0) break; + + ///if sq and v are not in the same direction, skip + ///endRid is (t.ul>>32), and t.v is a contained read + if((t.ul>>32) != endRid) break; + + if(chain_edges) kv_push(asg_arc_t, chain_edges->a, t); + chainLen++; + kv_push(uint32_t, chain_buffer->a, contain_uId); + ///endRid is (t.ul>>32), and t.v is a contained read + ///find edges from t.v to existing unitigs + ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, reverse_sources, coverage_cut, + ruIndex, max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, 1); + //means find an aim + if(ava_cur > 0) + { + /** + //do nothing if the chainLen == 1 + if(chainLen > 1) + { + asg_arc_t t_max; + ma_hit_t_alloc* x = &(sources[(endRid>>1)]); + uint32_t ava_ol_max = 0, ava_max = 0, k; + for (k = 0; k < x->length; k++) + { + h = &(x->buffer[k]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + trio_flag = R_INF.trio_flag[Get_qn(*h)]; + + ///don't want to edges between different haps + non_trio_flag = (uint32_t)-1; + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; + + ///just need deleted edges + ///sq might be deleted or not + if(!st->del) continue; + if(!h->del) continue; + + ///tn must be contained in another existing read + get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); + if(contain_rId == (uint32_t)-1 || is_Unitig == 1) continue; + if(r_g->seq[contain_rId].del) continue; + + get_R_to_U(ruIndex, contain_rId, &contain_uId, &is_Unitig); + if(contain_uId == (uint32_t)-1 || is_Unitig != 1) continue; + if(nsg->seq[contain_uId].del) continue; + ///contain_uId must be a unitig + + ql = sq->e - sq->s; tl = st->e - st->s; + r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + + ///if st is contained in sq, or vice verse, skip + if(r < 0) continue; + + ///if sq and v are not in the same direction, skip + if((t.ul>>32) != endRid) continue; + + ///pop the last contain_uId + chain_buffer->a.n--; + kv_push(uint32_t, chain_buffer->a, contain_uId); + + ///note: t.v is a contained read + ///we need to find existing reads linked with w + ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, sources, coverage_cut, ruIndex, + max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, 1); + + if((ava_cur > ava_max) || (ava_cur == ava_max && test_oLen > ava_ol_max)) + { + ava_max = ava_cur; + ava_ol_max = test_oLen; + t_max = t; + } + } + + if(ava_max > 0) + { + ava_cur = ava_max; + test_oLen = ava_ol_max; + if(chain_edges) + { + //pop the last edge + chain_edges->a.n--; + kv_push(asg_arc_t, chain_edges->a, t_max); + } + } + else + { + break; + } + } + **/ + + (*return_ava_cur) = ava_cur; + (*return_ava_ol) = test_oLen; + (*return_chainLen) = chainLen; + h = NULL; + return 1; + } + + if(chainLen >= thresLen) break; + + ///endRid is (t.ul>>32), and t.v is a contained read + ///haven't found a existing unitig from t.v + ///check if t.v can link to a new contained read + endRid = t.v; + h = get_best_no_coverage_read(ug, r_g, reverse_sources, coverage_cut, ruIndex, + max_hang, min_ovlp, endRid, init_contain_uId); + } + + return 0; +} + + +int get_no_coverage_reads_chain(ma_hit_t *h, ma_hit_t_alloc* sources, +ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, ma_ug_t *ug, +asg_t *r_g, int max_hang, int min_ovlp, uint32_t endRid, uint32_t uId, +kvec_t_u32_warp* chain_buffer, kvec_asg_arc_t_warp* chain_edges, uint32_t* return_ava_cur, +uint32_t* return_ava_ol, uint32_t* return_chainLen, uint32_t thresLen) +{ + (*return_chainLen) = (*return_ava_cur) = (*return_ava_ol) = (uint32_t)-1; + uint32_t init_contain_uId = (uint32_t)-1, contain_uId, is_Unitig; + uint32_t chainLen = 0, ava_cur, test_oLen; + int ql, tl; + int32_t r; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + asg_arc_t t; + asg_t* nsg = ug->g; + chain_buffer->a.n = 0; + kv_push(uint32_t, chain_buffer->a, uId); + if(chain_edges) chain_edges->a.n = 0; + + if(!h) return 0; + + while(h) + { + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + ///sq and st cannot be deleted + ///for h, deleted or not does not matter + if(sq->del || st->del) return 0; + if(r_g->seq[Get_qn(*h)].del || r_g->seq[Get_tn(*h)].del) return 0; + get_R_to_U(ruIndex, Get_tn(*h), &contain_uId, &is_Unitig); + if(contain_uId == (uint32_t)-1 || is_Unitig != 1) return 0; + if(nsg->seq[contain_uId].del) return 0; + ql = sq->e - sq->s; tl = st->e - st->s; + r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + if(r < 0) return 0; + if((t.ul>>32) != endRid) return 0; + if(chain_edges) kv_push(asg_arc_t, chain_edges->a, t); + chainLen++; + kv_push(uint32_t, chain_buffer->a, contain_uId); + ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, reverse_sources, coverage_cut, + ruIndex, max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, 1); + //means find an aim + if(ava_cur > 0) + { + (*return_ava_cur) = ava_cur; + (*return_ava_ol) = test_oLen; + (*return_chainLen) = chainLen; + h = NULL; + return 1; + } + + + if(chainLen >= thresLen) break; + + ///endRid is (t.ul>>32), and t.v is a contained read + ///haven't found a existing unitig from t.v + ///check if t.v can link to a new contained read + endRid = t.v; + h = get_best_no_coverage_read(ug, r_g, sources, coverage_cut, ruIndex, + max_hang, min_ovlp, endRid, init_contain_uId); + } + + + + ///continue + ///need to update h, endRid, chainLen, chain_buffer and chain_edges + while (h) + { + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + + ///sq, st, and h cannot be deleted + if(sq->del || st->del || h->del) break; + if(r_g->seq[Get_qn(*h)].del || r_g->seq[Get_tn(*h)].del) break; + + get_R_to_U(ruIndex, Get_tn(*h), &contain_uId, &is_Unitig); + if(contain_uId == (uint32_t)-1 || is_Unitig != 1) break; + if(nsg->seq[contain_uId].del) break; + ///contain_uId must be a unitig + + if(init_contain_uId != (uint32_t)-1) + { + init_contain_uId = contain_uId; + } + else + { + if(init_contain_uId != contain_uId) break; + } + + + ql = sq->e - sq->s; tl = st->e - st->s; + r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + + ///if st is contained in sq, or vice verse, skip + if(r < 0) break; + + ///if sq and v are not in the same direction, skip + ///endRid is (t.ul>>32), and t.v is a contained read + if((t.ul>>32) != endRid) break; + + if(chain_edges) kv_push(asg_arc_t, chain_edges->a, t); + chainLen++; + kv_push(uint32_t, chain_buffer->a, contain_uId); + ///endRid is (t.ul>>32), and t.v is a contained read + ///find edges from t.v to existing unitigs + ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, reverse_sources, coverage_cut, + ruIndex, max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, 1); + //means find an aim + if(ava_cur > 0) + { + /** + //do nothing if the chainLen == 1 + if(chainLen > 1) + { + asg_arc_t t_max; + ma_hit_t_alloc* x = &(sources[(endRid>>1)]); + uint32_t ava_ol_max = 0, ava_max = 0, k; + for (k = 0; k < x->length; k++) + { + h = &(x->buffer[k]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + trio_flag = R_INF.trio_flag[Get_qn(*h)]; + + ///don't want to edges between different haps + non_trio_flag = (uint32_t)-1; + if(trio_flag == FATHER) non_trio_flag = MOTHER; + if(trio_flag == MOTHER) non_trio_flag = FATHER; + if(R_INF.trio_flag[Get_tn(*h)] == non_trio_flag) continue; + + ///just need deleted edges + ///sq might be deleted or not + if(!st->del) continue; + if(!h->del) continue; + + ///tn must be contained in another existing read + get_R_to_U(ruIndex, Get_tn(*h), &contain_rId, &is_Unitig); + if(contain_rId == (uint32_t)-1 || is_Unitig == 1) continue; + if(r_g->seq[contain_rId].del) continue; + + get_R_to_U(ruIndex, contain_rId, &contain_uId, &is_Unitig); + if(contain_uId == (uint32_t)-1 || is_Unitig != 1) continue; + if(nsg->seq[contain_uId].del) continue; + ///contain_uId must be a unitig + + ql = sq->e - sq->s; tl = st->e - st->s; + r = ma_hit2arc(h, ql, tl, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + + ///if st is contained in sq, or vice verse, skip + if(r < 0) continue; + + ///if sq and v are not in the same direction, skip + if((t.ul>>32) != endRid) continue; + + ///pop the last contain_uId + chain_buffer->a.n--; + kv_push(uint32_t, chain_buffer->a, contain_uId); + + ///note: t.v is a contained read + ///we need to find existing reads linked with w + ava_cur = get_num_edges2existing_nodes_advance(ug, r_g, sources, coverage_cut, ruIndex, + max_hang, min_ovlp, t.v, &test_oLen, chain_buffer->a.a, chain_buffer->a.n, 1); + + if((ava_cur > ava_max) || (ava_cur == ava_max && test_oLen > ava_ol_max)) + { + ava_max = ava_cur; + ava_ol_max = test_oLen; + t_max = t; + } + } + + if(ava_max > 0) + { + ava_cur = ava_max; + test_oLen = ava_ol_max; + if(chain_edges) + { + //pop the last edge + chain_edges->a.n--; + kv_push(asg_arc_t, chain_edges->a, t_max); + } + } + else + { + break; + } + } + **/ + + (*return_ava_cur) = ava_cur; + (*return_ava_ol) = test_oLen; + (*return_chainLen) = chainLen; + h = NULL; + return 1; + } + + if(chainLen >= thresLen) break; + + ///endRid is (t.ul>>32), and t.v is a contained read + ///haven't found a existing unitig from t.v + ///check if t.v can link to a new contained read + endRid = t.v; + h = get_best_no_coverage_read(ug, r_g, reverse_sources, coverage_cut, ruIndex, + max_hang, min_ovlp, endRid, init_contain_uId); + } + + return 0; +} + + +uint32_t check_if_no_coverage(asg_t *r_g, asg_arc_t* list, uint32_t list_n) +{ + if(list_n < 2) return 0; + uint32_t i, v, w, u_n = list_n - 1, nv, l, k; + long long totalLen = 0; + asg_arc_t *av = NULL; + for (i = 0; i < u_n - 1; i++) + { + v = list[i].v; + w = list[i+1].v; + av = asg_arc_a(r_g, v); + nv = asg_arc_n(r_g, v); + l = 0; + + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + l = asg_arc_len(av[k]); + break; + } + } + + if(k == nv) fprintf(stderr, "####ERROR\n"); + totalLen += l; + } + + if(i < u_n) + { + v = list[i].v; + l = r_g->seq[v>>1].len; + totalLen += l; + } + + if(totalLen > list[0].ol + list[list_n - 1].ol) return 1; + + return 0; +} + +uint32_t create_fake_read(asg_t *r_g, asg_arc_t* list, uint32_t list_n) +{ + if(list_n < 2) return 0; + ma_utg_t* u = NULL; + uint32_t v, w, l, i, k, nv, totalLen = 0; + asg_arc_t *av = NULL; + u = asg_F_seq_set(r_g, r_g->n_seq); + if(u == NULL) return 0; + u->n = u->m = list_n - 1; + if(u->a) free(u->a); + u->a = (uint64_t*)malloc(sizeof(uint64_t)*u->n); + + /*****************for debug**********************/ + // fprintf(stderr, "list_n: %u\n", list_n); + // for (i = 0; i < list_n; i++) + // { + // fprintf(stderr, "(%u) v: %u, dir: %u, w: %u, w&1: %u, len: %u, ol: %u\n", + // i, (uint32_t)(list[i].ul>>33), (uint32_t)((list[i].ul>>32)&1), + // list[i].v>>1, list[i].v&1, (uint32_t)list[i].ul, list[i].ol); + // } + /*****************for debug**********************/ + + + for (i = 0; i < u->n; i++) + { + u->a[i] = list[i].v; + u->a[i] = u->a[i] << 32; + } + + /*****************for debug**********************/ + // fprintf(stderr, "u->n: %u\n", u->n); + // for (i = 0; i < u->n; i++) + // { + // fprintf(stderr, "(%u) v: %u, dir: %u\n", + // i, (uint32_t)(u->a[i]>>33), (uint32_t)((u->a[i]>>32)&1)); + // } + /*****************for debug**********************/ + + + for (i = 0; i < u->n - 1; i++) + { + v = (uint64_t)(u->a[i])>>32; + w = (uint64_t)(u->a[i + 1])>>32; + av = asg_arc_a(r_g, v); + nv = asg_arc_n(r_g, v); + l = 0; + + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + l = asg_arc_len(av[k]); + break; + } + } + + if(k == nv) fprintf(stderr, "####ERROR\n"); + u->a[i] = v; u->a[i] = u->a[i]<<32; u->a[i] = u->a[i] | (uint64_t)(l); + totalLen += l; + } + + if(i < u->n) + { + v = (uint64_t)(u->a[i])>>32; + l = r_g->seq[v>>1].len; + u->a[i] = v; + u->a[i] = u->a[i]<<32; + u->a[i] = u->a[i] | (uint64_t)(l); + totalLen += l; + } + + /*****************for debug**********************/ + // fprintf(stderr, "u->n: %u\n", u->n); + // for (i = 0; i < u->n; i++) + // { + // fprintf(stderr, "(%u) v: %u, dir: %u, len: %u\n", + // i, (uint32_t)(u->a[i]>>33), (uint32_t)((u->a[i]>>32)&1), (uint32_t)(u->a[i])); + // } + /*****************for debug**********************/ + + + + u->len = totalLen; + u->circ = 0; + u->start = list[0].ol; + u->end = u->len - list[list_n - 1].ol; + totalLen = u->len - list[0].ol - list[list_n - 1].ol; + ///u->len = totalLen; + + /*****************for debug**********************/ + // fprintf(stderr, "u->len: %u, u->start: %u, u->end: %u\n", u->len, u->start, u->end); + // fprintf(stderr, "totalLen: %u, list[0].ol: %u, list[list_n - 1].ol: %u\n", + // totalLen, list[0].ol, list[list_n - 1].ol); + /*****************for debug**********************/ + + /*****************for debug**********************/ + /** + (*coverage_cut) = (ma_sub_t*)realloc((*coverage_cut), (r_g->n_seq+1)*sizeof(ma_sub_t)); + (*coverage_cut)[r_g->n_seq].del = 0; + (*coverage_cut)[r_g->n_seq].c = PRIMARY_LABLE; + (*coverage_cut)[r_g->n_seq].s = 0; + (*coverage_cut)[r_g->n_seq].e = totalLen; + **/ + asg_seq_set(r_g, r_g->n_seq, totalLen, 0); + /*****************for debug**********************/ + return 1; +} + + +inline void generate_edge(asg_t *r_g, uint32_t v, uint32_t w, uint32_t ol, uint32_t del, +uint32_t strong, uint32_t el, uint32_t no_l_indel, asg_arc_t* t) +{ + uint64_t l = r_g->seq[v>>1].len - ol; + t->ul = v; t->ul = t->ul << 32; t->ul = t->ul|l; + t->v = w; + t->ol = ol; + t->del = del; + t->strong = strong; + t->el = el; + t->no_l_indel = no_l_indel; +} +///chainLenThres is used to avoid circle +void rescue_no_coverage_aggressive(asg_t *r_g, ma_hit_t_alloc* sources_count, +ma_hit_t_alloc* reverse_source, ma_sub_t **coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp, +long long bubble_dist, uint32_t chainLenThres, bub_label_t* b_mask_t) +{ + uint32_t n_vtx, v, k, kv, is_Unitig, uId, rId, endRid, w; + uint32_t ava_max, ava_ol_max, ava_min_chain, ava_cur, ava_chainLen, test_oLen, is_update; + uint64_t interval_beg, intervalLen; + asg_t* nsg = NULL; + ma_utg_t* nsu = NULL; + asg_arc_t t, t_max, r_edge; + t_max.v = t_max.ul = t.v = t.ul = (uint32_t)-1; + ma_hit_t *h = NULL, *h_max = NULL; + ma_hit_t_alloc* x = NULL; + ma_ug_t* ug = NULL; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + int32_t r; + + kvec_t(asg_arc_t) new_utg_edges; + kv_init(new_utg_edges); + + kvec_t(asg_arc_t) new_rtg_edges; + kv_init(new_rtg_edges); + + kvec_t(asg_arc_t) hap_edges; + kv_init(hap_edges); + + kvec_t(asg_arc_t) rbub_edges; + kv_init(rbub_edges); + + kvec_t_u64_warp u_vecs; + kv_init(u_vecs.a); + + kvec_t_u64_warp intervals; + kv_init(intervals.a); + + kvec_t_u32_warp chain_buffer; + kv_init(chain_buffer.a); + + kvec_asg_arc_t_warp chain_edges; + kv_init(chain_edges.a); + + + ug = ma_ug_gen(r_g); + nsg = ug->g; + + for (v = 0; v < nsg->n_seq; v++) + { + uId = v; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsg->seq[v].del) continue; + nsg->seq[v].c = PRIMARY_LABLE; + for (k = 0; k < nsu->n; k++) + { + rId = nsu->a[k]>>33; + set_R_to_U(ruIndex, rId, uId, 1, &(r_g->seq[rId].c)); + } + } + + + + + n_vtx = nsg->n_seq * 2; + for (v = 0; v < n_vtx; v++) + { + uId = v>>1; + if(nsg->seq[uId].del) continue; + nsu = &(ug->u.a[uId]); + if(nsu->m == 0) continue; + if(nsu->circ || nsu->start == UINT32_MAX || nsu->end == UINT32_MAX) continue; + if(get_real_length(nsg, v, NULL) != 0) continue; + ///we probably don't need this line + ///if(get_real_length(nsg, v^1, NULL) == 0) continue; + if(v&1) + { + endRid = nsu->start^1; + } + else + { + endRid = nsu->end^1; + } + + + x = &(sources_count[(endRid>>1)]); + for (k = 0; k < x->length; k++) + { + ///h is the edge of endRid + h = &(x->buffer[k]); + sq = &((*coverage_cut)[Get_qn(*h)]); + st = &((*coverage_cut)[Get_tn(*h)]); + ///sq, st, and h cannot be deleted + if(sq->del || st->del || h->del) continue; + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + if(r < 0) continue; + if((t.ul>>32) != endRid) continue; + break; + } + ///means there is >0 edges + if(k != x->length) continue; + + ///x is the end read of a tip + ///find all overlap of x + x = &(reverse_source[(endRid>>1)]); + ava_ol_max = ava_max = 0; ava_min_chain = (uint32_t)-1; + h_max = NULL; + for (k = 0; k < x->length; k++) + { + h = &(x->buffer[k]); + ///means we found a contained read + if(get_no_coverage_reads_chain_simple(h, sources_count, reverse_source, *coverage_cut, + ruIndex, ug, r_g, max_hang, min_ovlp, endRid, uId, &chain_buffer, NULL, &ava_cur, + &test_oLen, &ava_chainLen, chainLenThres)) + { + + is_update = 0; + if(ava_chainLen < ava_min_chain) + { + is_update = 1; + } + else if(ava_chainLen == ava_min_chain) + { + if(ava_cur > ava_max) + { + is_update = 1; + } + else if(ava_cur == ava_max && test_oLen > ava_ol_max) + { + is_update = 1; + } + } + if(is_update) + { + ava_min_chain = ava_chainLen; + ava_max = ava_cur; + ava_ol_max = test_oLen; + h_max = h; + } + } + } + + + + + + if(ava_max > 0) + { + + //get all edges between contained reads + get_no_coverage_reads_chain_simple(h_max, sources_count, reverse_source, + *coverage_cut, ruIndex, ug, r_g, max_hang, min_ovlp, endRid, uId, &chain_buffer, + &chain_edges, &ava_cur, &test_oLen, &ava_chainLen, chainLenThres); + if(chain_edges.a.n < 1) continue; + ///the last cantained read + t_max = chain_edges.a.a[chain_edges.a.n-1]; + + k = 0; rbub_edges.n = 0; + ///edges from the last contained read to other unitigs + while(get_edge2existing_node_advance(ug, r_g, reverse_source, *coverage_cut, ruIndex, + max_hang, min_ovlp, t_max.v, chain_buffer.a.a, chain_buffer.a.n, &k, &r_edge, 1)) + { + kv_push(asg_arc_t, rbub_edges, r_edge); + } + + ///need to do transitive reduction + ///note here is different to standard transitive reduction + minor_transitive_reduction(ug, ruIndex, rbub_edges.a, rbub_edges.n); + + for (k = 0, kv = 0; k < rbub_edges.n; k++) + { + t = rbub_edges.a[k]; + if(t.del) continue; + kv++; + } + + if(kv != 1) continue; + + interval_beg = hap_edges.n; + + //just saves all nodes here + ///note that only the first edge is generated from reverse_source, + ///others are generated from source + for (k = 0; k < chain_edges.a.n; k++) + { + kv_push(asg_arc_t, hap_edges, chain_edges.a.a[k]); + } + + for (k = 0; k < rbub_edges.n; k++) + { + t = rbub_edges.a[k]; + if(t.del) continue; + kv_push(asg_arc_t, hap_edges, t); + } + + + if(check_if_no_coverage(r_g, hap_edges.a+interval_beg, hap_edges.n - interval_beg) == 0) + { + hap_edges.n = interval_beg; + continue; + } + + ///there is just one edge + ///connect multiple edges is too difficult + for (k = 0; k < rbub_edges.n; k++) + { + t = rbub_edges.a[k]; + if(t.del) continue; + + w = get_corresponding_uId(ug, ruIndex, t.v); + if(w == ((uint32_t)(-1))) continue; + kv_push(asg_arc_t, new_rtg_edges, t); + + get_edge_from_source(reverse_source, *coverage_cut, ruIndex, max_hang, min_ovlp, + (t.v^1), ((t.ul>>32)^1), &t); + kv_push(asg_arc_t, new_rtg_edges, t); + + + ///for unitig graph + asg_append_edges_to_srt(nsg, v, ug->u.a[v>>1].len, w, 0, 0, 0, 0); + asg_append_edges_to_srt(nsg, w^1, ug->u.a[w>>1].len, v^1, 0, 0, 0, 0); + + t.ul = v; t.ul = t.ul<<32; t.v = w; + kv_push(asg_arc_t, new_utg_edges, t); + + t.ul = w^1; t.ul = t.ul<<32; t.v = v^1; + kv_push(asg_arc_t, new_utg_edges, t); + + } + + kv_push(uint64_t, u_vecs.a, v); + + intervalLen = hap_edges.n - interval_beg; + interval_beg = interval_beg << 32; + interval_beg = interval_beg | intervalLen; + kv_push(uint64_t, intervals.a, interval_beg); + } + } + + nsg->seq_vis = (uint8_t*)calloc(nsg->n_seq*2, sizeof(uint8_t)); + lable_all_bubbles(nsg, b_mask_t); + + + for (k = 0; k < new_utg_edges.n; k++) + { + v = new_utg_edges.a[k].ul>>32; + w = new_utg_edges.a[k].v; + + if(nsg->seq[v>>1].del) continue; + if(nsg->seq[w>>1].del) continue; + ///if this edge is at a bubble + if(nsg->seq_vis[v]!=0 && nsg->seq_vis[w^1]!=0) + { + continue; + } + + asg_arc_del(nsg, v, w, 1); + asg_arc_del(nsg, w^1, v^1, 1); + new_rtg_edges.a[k].del = 1; + } + free(nsg->seq_vis); nsg->seq_vis = NULL; + + + new_utg_edges.n = 0; + asg_arc_t* list = NULL; + uint32_t nextNode, curNode, pre_num_nodes = r_g->n_seq; + ///u_vecs saves the unitig Id + for (k = 0; k < u_vecs.a.n; k++) + { + w = (uint32_t)u_vecs.a.a[k]; + ///do nothing + if(get_real_length(r_g, w, NULL) == 0) continue; + + interval_beg = intervals.a.a[k]>>32; + intervalLen = intervals.a.a[k] & ((uint64_t)0xffffffff); + list = hap_edges.a + interval_beg; + if(intervalLen < 2) continue;///fprintf(stderr, "No enough edges\n"); + fprintf(stderr, "\n(%u) w>>1: %u, w&1: %u\n", k, w>>1, w&1); + ///continue; + + + if(create_fake_read(r_g, list, intervalLen) == 0) continue; + + + curNode = list[0].ul>>32; + nextNode = (r_g->n_seq - 1)<<1; + /*****************for debug**********************/ + generate_edge(r_g, curNode, nextNode, 0, 0, 0, 0, 0, &t); + kv_push(asg_arc_t, new_utg_edges, t); + + generate_edge(r_g, nextNode^1, curNode^1, 0, 0, 0, 0, 0, &t); + kv_push(asg_arc_t, new_utg_edges, t); + /*****************for debug**********************/ + // fprintf(stderr, "curNode>>1: %u, curNode&1: %u, nextNode>>1: %u, nextNode&1: %u\n", + // curNode>>1, curNode&1, nextNode>>1, nextNode&1); + + + curNode = (r_g->n_seq - 1)<<1; + nextNode = list[intervalLen - 1].v; + /*****************for debug**********************/ + generate_edge(r_g, curNode, nextNode, 0, 0, 0, 0, 0, &t); + kv_push(asg_arc_t, new_utg_edges, t); + + generate_edge(r_g, nextNode^1, curNode^1, 0, 0, 0, 0, 0, &t); + kv_push(asg_arc_t, new_utg_edges, t); + /*****************for debug**********************/ + // fprintf(stderr, "curNode>>1: %u, curNode&1: %u, nextNode>>1: %u, nextNode&1: %u\n", + // curNode>>1, curNode&1, nextNode>>1, nextNode&1); + } + + + + + asg_arc_t* p = NULL; + for (k = 0; k < new_utg_edges.n; k++) + { + p = asg_arc_pushp(r_g); + *p = new_utg_edges.a[k]; + } + + + free(r_g->idx); + r_g->idx = 0; + r_g->is_srt = 0; + asg_cleanup(r_g); + + if(r_g->n_seq > pre_num_nodes) + { + (*coverage_cut) = (ma_sub_t*)realloc((*coverage_cut), r_g->n_seq*sizeof(ma_sub_t)); + R_INF.trio_flag = (uint8_t*)realloc(R_INF.trio_flag, r_g->n_seq*sizeof(uint8_t)); + ruIndex->index = (uint32_t*)realloc(ruIndex->index, r_g->n_seq*sizeof(uint32_t)); + ruIndex->len = r_g->n_seq; + for (k = pre_num_nodes; k < r_g->n_seq; k++) + { + ruIndex->index[k] = (uint32_t)-1; + R_INF.trio_flag[k] = AMBIGU; + (*coverage_cut)[k].del = 0; + (*coverage_cut)[k].c = PRIMARY_LABLE; + (*coverage_cut)[k].s = 0; + (*coverage_cut)[k].e = r_g->seq[k].len; + } + } + + + for (v = 0; v < ruIndex->len; v++) + { + get_R_to_U(ruIndex, v, &uId, &is_Unitig); + if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; + } + + + ma_ug_destroy(ug); + kv_destroy(new_utg_edges); + kv_destroy(hap_edges); + kv_destroy(new_rtg_edges); + kv_destroy(rbub_edges); + kv_destroy(u_vecs.a); + kv_destroy(chain_buffer.a); + kv_destroy(chain_edges.a); + kv_destroy(intervals.a); +} + + +void fix_binned_reads(ma_hit_t_alloc* paf, uint64_t n_read, ma_sub_t* coverage_cut) +{ + double startTime = Get_T(); + uint64_t i, binned_flag, binned_reads = 0, binned_error_reads = 0, reduce = 1; + ma_sub_t max_left, max_right; + while (reduce != 0) + { + reduce = 0; + binned_reads = 0; + for (i = 0; i < n_read; ++i) + { + if(coverage_cut[i].del) continue; + binned_flag = R_INF.trio_flag[i]; + if(binned_flag == AMBIGU) continue; + binned_reads++; + max_left.s = max_right.s = Get_READ_LENGTH(R_INF,i); + max_left.e = max_right.e = 0; + collect_sides_trio(&(paf[i]), Get_READ_LENGTH(R_INF,i), &max_left, &max_right, binned_flag); + collect_contain_trio(&(paf[i]), NULL, Get_READ_LENGTH(R_INF,i), &max_left, &max_right, 0.1, + binned_flag); + if(max_left.e > max_right.s) + { + R_INF.trio_flag[i] = AMBIGU; + binned_error_reads++; + reduce++; + binned_reads--; + } + /** + if(max_left.e > max_right.s) + { + fprintf(stderr, "\ni: %lu, reference: %.*s, len: %lu, %c\n", + i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i), + Get_READ_LENGTH(R_INF, i), "apmaaa"[binned_flag]); + + for (uint64_t j = 0; j < paf[i].length; j++) + { + if(R_INF.trio_flag[Get_tn(paf[i].buffer[j])] == binned_flag) + { + fprintf(stderr, "###Compatible, "); + } + else + { + fprintf(stderr, "***Conflict, "); + } + + fprintf(stderr, "%c, qs: %u, qe: %u, ts: %u, te: %u, len: %lu, %.*s\n", + "apmaaa"[R_INF.trio_flag[Get_tn(paf[i].buffer[j])]], + Get_qs(paf[i].buffer[j]), + Get_qe(paf[i].buffer[j]), + Get_ts(paf[i].buffer[j]), + Get_te(paf[i].buffer[j]), + Get_READ_LENGTH(R_INF, Get_tn(paf[i].buffer[j])), + (int)Get_NAME_LENGTH(R_INF, Get_tn(paf[i].buffer[j])), + Get_NAME(R_INF, Get_tn(paf[i].buffer[j]))); + } + } + **/ + } + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + fprintf(stderr, "n_read: %lu, binned_reads: %lu, binned_error_reads: %lu\n", + (unsigned long)n_read, (unsigned long)binned_reads, (unsigned long)binned_error_reads); +} + + +void print_binned_reads(ma_hit_t_alloc* paf, uint64_t n_read, ma_sub_t* coverage_cut) +{ + uint64_t i, j, binned_flag; + + for (i = 0; i < n_read; ++i) + { + if(coverage_cut!=NULL && coverage_cut[i].del) continue; + binned_flag = R_INF.trio_flag[i]; + fprintf(stdout, "\n***i: %u, binned_flag: %u\n", (uint32_t)i, (uint32_t)binned_flag); + if(coverage_cut!=NULL) + { + fprintf(stdout, "coverage_cut[i].c: %u, coverage_cut[i].s: %u, coverage_cut[i].e: %u, coverage_cut[i].e: %u\n", + coverage_cut[i].c, coverage_cut[i].s, coverage_cut[i].e, coverage_cut[i].del); + } + for (j = 0; j < paf[i].length; j++) + { + if(paf[i].buffer[j].del) continue; + ///fprintf(stdout, "j: %u\n", (uint32_t)j); + fprintf(stdout, "qn: %u, qs: %u, qe: %u, tn: %u, ts: %u, te: %u\n", + (uint32_t)Get_qn(paf[i].buffer[j]), (uint32_t)Get_qs(paf[i].buffer[j]), (uint32_t)Get_qe(paf[i].buffer[j]), + (uint32_t)Get_tn(paf[i].buffer[j]), (uint32_t)Get_ts(paf[i].buffer[j]), (uint32_t)Get_te(paf[i].buffer[j])); + } + } +} + + + +void debug_ma_hit_t(ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, long long num_sources, +int max_hang, int min_ovlp) +{ + double startTime = Get_T(); + + long long i, j, index; + uint32_t qn, tn; + ma_sub_t *sq = NULL; + ma_sub_t *st = NULL; + ma_hit_t *h = NULL; + int32_t r_0, r_1; + asg_arc_t t_0, t_1; + fprintf(stderr, "start!\n"); + + for (i = 0; i < num_sources; i++) + { + + for (j = 0; j < sources[i].length; j++) + { + qn = Get_qn(sources[i].buffer[j]); + tn = Get_tn(sources[i].buffer[j]); + + + ///if(sources[i].buffer[j].del) continue; + + index = get_specific_overlap(&(sources[tn]), tn, qn); + if(index == -1) + { + fprintf(stderr, "ERROR 0: qn: %u, tn: %u\n", qn, tn); + continue; + } + + + + if(sources[i].buffer[j].del != sources[tn].buffer[index].del) + { + fprintf(stderr, "ERROR 2: qn: %u, tn: %u\n", qn, tn); + } + + h = &(sources[i].buffer[j]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + r_0 = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t_0); + + + h = &(sources[tn].buffer[index]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + r_1 = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t_1); + t_0.ul=t_0.v=t_1.ul=t_1.v = 0; + if(r_0 < 0 && r_1 < 0) continue; + if((t_0.ul>>32) != (t_1.v^1)) fprintf(stderr, "ERROR 3: qn: %u, tn: %u\n", qn, tn); + if((t_1.ul>>32) != (t_0.v^1)) fprintf(stderr, "ERROR 4: qn: %u, tn: %u\n", qn, tn); + } + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] takes %0.2fs\n\n", __func__, Get_T()-startTime); + } +} + +void set_hom_global_coverage(hifiasm_opt_t *opt, asg_t *sg, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, int max_hang, int min_ovlp) +{ + if(opt->hom_global_coverage_set == 0) + { + ma_ug_t *ug = NULL; + ug = ma_ug_gen(sg); + + hap_cov_t *cov = init_hap_cov_t(ug, sg, sources, ruIndex, reverse_sources, coverage_cut, max_hang, min_ovlp, 0); + purge_dups(ug, sg, coverage_cut, sources, reverse_sources, ruIndex, NULL, + opt->purge_simi_thres, opt->purge_overlap_len, max_hang, min_ovlp, 0, 0, 1, cov, 0, 0); + destory_hap_cov_t(&cov); + + ma_ug_destroy(ug); + } +} + +void 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); + } + + for (i = 0; i < ug->g->n_seq; ++i) + { + if(ug->g->seq[i].del) continue; + u = &(ug->u.a[i]); + if(ug->g->seq[i].c == ALTER_LABLE) + { + for (k = 0; k < u->n; k++) + { + asg_seq_del(sg, u->a[k]>>33); + } + } + else + { + for (k = 0; (k + 1) < u->n; k++) + { + v = u->a[k]>>32; w = u->a[k+1]>>32; + + asg_arc_del(sg, v, w, 0); + asg_arc_del(sg, w^1, v^1, 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_del(sg, vx, wx, 0); asg_arc_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_del(sg, vx, wx, 0); asg_arc_del(sg, wx^1, vx^1, 0); + } + } + } + asg_cleanup(sg); + + + /*******************************for debug************************************/ + // ma_ug_t *dbg = ma_ug_gen(sg); + // for (i = 0; i < ug->g->n_seq; ++i) + // { + // if(ug->g->seq[i].del) continue; + // if(ug->g->seq[i].c == ALTER_LABLE) + // { + // asg_seq_del(ug->g, i); + // } + // } + // for (i = 0; i < dbg->g->n_seq; ++i) + // { + // dbg->g->seq[v].c = PRIMARY_LABLE; + // EvaluateLen(dbg->u, v) = dbg->u.a[v].n; + // } + // cmp_untig_graph(dbg, ug); + /*******************************for debug************************************/ +} + +void flat_bubbles(asg_t *sg, uint8_t* r_het) +{ + ma_ug_t *ug = NULL; + ug = ma_ug_gen(sg); + ma_utg_t *u = NULL; + uint32_t n_vtx = ug->g->n_seq<<1, v, convex, i, k, ori, is_het_b, is_het_s, n_pop = 0, pass_b, pass_s; + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + buf_t b; memset(&b, 0, sizeof(buf_t)); b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + uint8_t* bs_flag = (uint8_t*)calloc(n_vtx, 1); + uint64_t tLen = get_bub_pop_max_dist_advance(ug->g, &b), path, hom_occ, het_occ; + + for (v = 0; v < ug->g->n_seq; ++v) + { + if(ug->g->seq[v].del) continue; + ug->g->seq[v].c = PRIMARY_LABLE; + EvaluateLen(ug->u, v) = ug->u.a[v].n; + } + + n_pop = 1; ///round = 0; + while(n_pop > 0) + { + for (v = n_pop = 0; v < n_vtx; ++v) + { + if(ug->g->seq[v>>1].del) continue; + if(asg_arc_n(ug->g, v) < 2) continue; + if(get_real_length(ug->g, v, NULL) < 2) continue; + if(bs_flag[v] == 1) continue; + if(bs_flag[v] == 0) bs_flag[v] = 1; + + if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) + { + //note b.b include end, does not include beg + for (i = path = 0; i < b.b.n; i++) + { + if((b.b.a[i]>>1) == (v>>1) || (b.b.a[i]>>1) == (b.S.a[0]>>1)) + { + continue; + } + path += ug->u.a[b.b.a[i]>>1].n; + } + + + + bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 2; + is_het_b = is_het_s = pass_b = pass_s = 0; + //beg is v, end is b.S.a[0] + b.b.n = 0; + get_unitig(ug->g, NULL, v^1, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, + &max_stop_baseLen, 1, &b); + + + for (i = hom_occ = het_occ = 0; i < b.b.n; i++) + { + u = &(ug->u.a[b.b.a[i]>>1]); + ori = b.b.a[i]&1; + for (k = 0; k < u->n; k++) + { + if(r_het[(ori == 1?(u->a[u->n-k-1]>>33):(u->a[k]>>33))] == N_HET) + { + hom_occ++; + } + else + { + het_occ++; + } + if(het_occ > ((het_occ+hom_occ)*0.85)) + { + is_het_b = (het_occ+hom_occ); + } + + if((het_occ+hom_occ) == MAX((path+1),5)) + { + if(het_occ > ((het_occ+hom_occ)*0.7)) + { + pass_b = 1; + } + } + } + } + if(pass_b == 0) continue; + + + b.b.n = 0; + get_unitig(ug->g, NULL, b.S.a[0], &convex, &nodeLen, &baseLen, &max_stop_nodeLen, + &max_stop_baseLen, 1, &b); + for (i = hom_occ = het_occ= 0; i < b.b.n; i++) + { + u = &(ug->u.a[b.b.a[i]>>1]); + ori = b.b.a[i]&1; + for (k = 0; k < u->n; k++) + { + if(r_het[(ori == 1?(u->a[u->n-k-1]>>33):(u->a[k]>>33))] == N_HET) + { + hom_occ++; + } + else + { + het_occ++; + } + if(het_occ > ((het_occ+hom_occ)*0.85)) + { + is_het_s = (het_occ+hom_occ); + } + + if((het_occ+hom_occ) == MAX((path+1),5)) + { + if(het_occ > ((het_occ+hom_occ)*0.7)) + { + pass_s = 1; + } + } + } + } + if(pass_s == 0) continue; + + + if(is_het_b > path && is_het_s > path && (is_het_b+is_het_s)>(path<<2)) + { + asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 1, NULL, NULL, NULL, 0, 0, NULL); + n_pop++; + } + } + } + ///round++; + } + + /*******************************for debug************************************/ + // kvec_t(uint64_t) occ_sort; kv_init(occ_sort); + // for (v = n_pop = 0; v < ug->g->n_seq; ++v) + // { + // if(ug->g->seq[v].del) continue; + // if(ug->g->seq[v].c != ALTER_LABLE) continue; + // u = &(ug->u.a[v]); + + // kv_push(uint64_t, occ_sort, (uint64_t)((uint32_t)(-1) - (uint32_t)(u->n)) << 32 | (v)); + // } + // radix_sort_arch64(occ_sort.a, occ_sort.a + occ_sort.n); + // for (i = 0; i < occ_sort.n; ++i) + // { + // fprintf(stderr, "-utg%.6ul, n=%u\n", ((uint32_t)occ_sort.a[i])+1, + // (uint32_t)(-1) - (uint32_t)(occ_sort.a[i]>>32)); + // } + // kv_destroy(occ_sort); + /*******************************for debug************************************/ + + clean_sg_by_utg(sg, ug); + + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + ma_ug_destroy(ug); free(bs_flag); +} + +uint64_t get_primary_path_len(asg_t *sg, ma_ug_t *ug, uint32_t v0, buf_t *b) +{ + uint32_t v, u, k; + uint64_t len; + ma_utg_t *p = NULL; + + v = b->S.a[0]; + len = 0; + while (1) + { + u = b->a[v].p; // u->v + if(u == v0) break; + + p = &(ug->u.a[u>>1]); + + for (k = 0; k < p->n; k++) + { + len += sg->seq[p->a[k]>>33].len; + } + + v = u; + } + + return len; +} + +void flat_bubbles_advance(asg_t *sg, ma_hit_t_alloc* sources, R_to_U* ruIndex, uint64_t het_thres) +{ + // fprintf(stderr, "het_thres-%lu\n", het_thres); + ma_ug_t *ug = NULL; + ug = ma_ug_gen(sg); + ma_utg_t *u = NULL; + ma_hit_t *h; + uint32_t n_vtx = ug->g->n_seq<<1, v, i, k, m, rId, tn, is_Unitig, n_pop = 0; + uint64_t C_bases, R_bases; + buf_t b; memset(&b, 0, sizeof(buf_t)); b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + uint8_t* bs_flag = (uint8_t*)calloc(n_vtx, 1); + uint8_t* r_flag = (uint8_t*)calloc(sg->n_seq, sizeof(uint8_t)); + uint64_t tLen = get_bub_pop_max_dist_advance(ug->g, &b); + + for (v = 0; v < ug->g->n_seq; ++v) + { + if(ug->g->seq[v].del) continue; + ug->g->seq[v].c = PRIMARY_LABLE; + EvaluateLen(ug->u, v) = ug->u.a[v].n; + } + + n_pop = 1; ///round = 0; + while(n_pop > 0) + { + for (v = n_pop = 0; v < n_vtx; ++v) + { + if(ug->g->seq[v>>1].del) continue; + if(asg_arc_n(ug->g, v) < 2) continue; + if(get_real_length(ug->g, v, NULL) < 2) continue; + if(bs_flag[v] == 1) continue; + if(bs_flag[v] == 0) bs_flag[v] = 1; + + if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) + { + bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 2; + //note b.b include end, does not include beg + for (i = 0; i < b.b.n; i++) + { + u = &(ug->u.a[b.b.a[i]>>1]); + for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 1; + } + + u = &(ug->u.a[v>>1]); + for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 1; + + u = &(ug->u.a[b.S.a[0]>>1]); + for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 1; + + + + + + + C_bases = 0; + for (i = 0; i < b.b.n; i++) + { + if((b.b.a[i]>>1) == (v>>1) || (b.b.a[i]>>1) == (b.S.a[0]>>1)) continue; + u = &(ug->u.a[b.b.a[i]>>1]); + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + // R_bases += sg->seq[rId].len; + for (m = 0; m < (uint64_t)(sources[rId].length); m++) + { + h = &(sources[rId].buffer[m]); + ///if(h->el != 1) continue; + tn = Get_tn((*h)); + if(sg->seq[tn].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || sg->seq[tn].del == 1) continue; + } + if(sg->seq[tn].del == 1) continue; + if(r_flag[tn] == 0) continue; + C_bases += (Get_qe((*h)) - Get_qs((*h))); + } + } + } + + R_bases = get_primary_path_len(sg, ug, v, &b); + + if((C_bases/R_bases) <= het_thres) + { + // fprintf(stderr, "s-utg%.6ul\te-utg%.6ul\tC_bases:%lu\tR_bases:%lu\n", (v>>1)+1, (b.S.a[0]>>1)+1, C_bases, R_bases); + asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 1, NULL, NULL, NULL, 0, 0, NULL); + n_pop++; + } + + + for (i = 0; i < b.b.n; i++) + { + u = &(ug->u.a[b.b.a[i]>>1]); + for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 0; + } + + u = &(ug->u.a[v>>1]); + for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 0; + + u = &(ug->u.a[b.S.a[0]>>1]); + for (k = 0; k < u->n; k++) r_flag[u->a[k]>>33] = 0; + } + } + ///round++; + } + + /*******************************for debug************************************/ + // kvec_t(uint64_t) occ_sort; kv_init(occ_sort); + // for (v = n_pop = 0; v < ug->g->n_seq; ++v) + // { + // if(ug->g->seq[v].del) continue; + // if(ug->g->seq[v].c != ALTER_LABLE) continue; + // u = &(ug->u.a[v]); + + // kv_push(uint64_t, occ_sort, (uint64_t)((uint32_t)(-1) - (uint32_t)(u->n)) << 32 | (v)); + // } + // radix_sort_arch64(occ_sort.a, occ_sort.a + occ_sort.n); + // for (i = 0; i < occ_sort.n; ++i) + // { + // fprintf(stderr, "-utg%.6ul, n=%u\n", ((uint32_t)occ_sort.a[i])+1, + // (uint32_t)(-1) - (uint32_t)(occ_sort.a[i]>>32)); + // } + // kv_destroy(occ_sort); + /*******************************for debug************************************/ + + clean_sg_by_utg(sg, ug); + + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + ma_ug_destroy(ug); free(bs_flag); free(r_flag); +} + + +void flat_soma_v(asg_t *sg, ma_hit_t_alloc* sources, R_to_U* ruIndex) +{ + uint64_t dip_thre_max; + if(asm_opt.somatic_cov >= 0) { + dip_thre_max = asm_opt.somatic_cov; + } else { + if(asm_opt.hom_global_coverage_set) { + dip_thre_max = asm_opt.hom_global_coverage; + } else { + dip_thre_max = ((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE); + } + dip_thre_max = (((double)(dip_thre_max)*1.15)/asm_opt.polyploidy); + } + flat_bubbles_advance(sg, sources, ruIndex, dip_thre_max); +} + +char *get_outfile_name(char* output_file_name) +{ + char *buf = NULL; + CALLOC(buf, strlen(output_file_name) + 25); + if(ha_opt_triobin(&asm_opt) && ha_opt_hic(&asm_opt)) + { + sprintf(buf, "%s.hic.bench", output_file_name); + } + else if(ha_opt_triobin(&asm_opt)) + { + sprintf(buf, "%s.dip", output_file_name); + } + else if(ha_opt_hic(&asm_opt)) + { + sprintf(buf, "%s.hic", output_file_name); + } + else if(asm_opt.flag & HA_F_PARTITION) + { + sprintf(buf, "%s.bp", output_file_name); + } + else + { + sprintf(buf, "%s", output_file_name); + } + + return buf; +} + +void gen_ug_opt_t(ug_opt_t *opt, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, int64_t max_hang, int64_t min_ovlp, +int64_t gap_fuzz, int64_t min_dp, uint64_t* readLen, ma_sub_t *coverage_cut, R_to_U* ruIndex, long long tipsLen, +float tip_drop_ratio, long long stops_threshold, float chimeric_rate, float drop_ratio, bub_label_t* b_mask_t, telo_end_t *te) +{ + memset(opt, 0, sizeof((*opt))); + opt->sources = sources; opt->reverse_sources = reverse_sources; opt->max_hang = max_hang; + opt->min_ovlp = min_ovlp; opt->gap_fuzz = gap_fuzz; opt->min_dp = min_dp; opt->readLen = readLen; + opt->coverage_cut = coverage_cut; opt->ruIndex = ruIndex; opt->tipsLen = tipsLen; + opt->tip_drop_ratio = tip_drop_ratio; opt->stops_threshold = stops_threshold; + opt->chimeric_rate = chimeric_rate; opt->drop_ratio = drop_ratio; opt->b_mask_t = b_mask_t; opt->te = te; +} + +void create_ul_info(ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, int64_t max_hang, int64_t min_ovlp, int64_t gap_fuzz, +int64_t min_dp, uint64_t* readLen, ma_sub_t *coverage_cut, R_to_U* ruIndex, long long tipsLen, float tip_drop_ratio, long long stops_threshold, float chimeric_rate, float drop_ratio, bub_label_t* b_mask_t, telo_end_t *te) +{ + ug_opt_t opt; + gen_ug_opt_t(&opt, sources, reverse_sources, max_hang, min_ovlp, gap_fuzz, min_dp, readLen, coverage_cut, ruIndex, + tipsLen, tip_drop_ratio, stops_threshold, chimeric_rate, drop_ratio, b_mask_t, te); + ul_load(&opt); +} + +void rescue_src_ul(ma_hit_t_alloc* src, uint64_t n_read, uint64_t occ) +{ + uint64_t k, i; + for (k = 0; k < n_read; k++) { + for (i = 0; i < src[k].length; i++) { + if(!src[k].buffer[i].del) continue; + if(src[k].buffer[i].bl>=occ) src[k].buffer[i].del = 0; + } + } +} + +void prt_dbg_gfa(asg_t *sg, const char *suffix, ma_sub_t *cov, ma_hit_t_alloc* src, R_to_U* ruIndex, int64_t max_hang, int64_t min_ovlp) +{ + char *o_file = get_outfile_name(asm_opt.output_file_name); + char* gfa_name; MALLOC(gfa_name, strlen(o_file)+strlen(suffix)+50); sprintf(gfa_name, "%s.%s", o_file, suffix); + print_debug_gfa(sg, NULL, cov, gfa_name, src, ruIndex, max_hang, min_ovlp, 0, 0, 1); + free(gfa_name); free(o_file); +} + +void prt_dbg_rid_ovlp(ma_hit_t_alloc *ov, int64_t rid, char *rn, const char *cmd) +{ + uint64_t k; ma_hit_t *h = NULL; + if(rid < 0) { + for (k = 0; k < R_INF.total_reads; k++) { + if (memcmp(rn, Get_NAME((R_INF), k), Get_NAME_LENGTH((R_INF), k)) == 0) break; + } + if(k >= R_INF.total_reads) return; + rid = k; + } + + fprintf(stderr, "\n[M::%s::%s::id::%ld]\n", __func__, cmd, rid); + for (k = 0; k < ov[rid].length; k++) { + h = &(ov[rid].buffer[k]); + if(h->del) continue; + fprintf(stderr, "%.*s(qn::%u)\t%u\t%u\t%u\t%c\t%.*s(tn::%u)\t%u\t%u\t%u\t%u\t%u\t255\n", (int)Get_NAME_LENGTH(R_INF, Get_qn(*h)), Get_NAME((R_INF), Get_qn(*h)), Get_qn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_qn(*h)), Get_qs(*h), Get_qe(*h), "+-"[h->rev], + (int)Get_NAME_LENGTH(R_INF, Get_tn(*h)), Get_NAME((R_INF), Get_tn(*h)), Get_tn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_tn(*h)), Get_ts(*h), Get_te(*h), h->ml, h->bl); + } +} + +asg_t *gen_init_sg(int32_t min_dp, uint64_t n_read, int64_t mini_overlap_length, int64_t max_hang_length, int64_t gap_fuzz, +ma_hit_t_alloc* src, uint64_t* readLen, R_to_U* ruIndex, bub_label_t *b_mask_t, ma_sub_t** cov, all_ul_t *ul, telo_end_t *te) +{ + asg_t *sg = NULL; + // prt_dbg_rid_ovlp(src, -1, (char*)"c85c2e91-0490-438b-977b-b7d056973996", "1"); + if(ul) rescue_src_ul(src, n_read, UL_COV_THRES); + // prt_dbg_rid_ovlp(src, -1, (char*)"c85c2e91-0490-438b-977b-b7d056973996", "2"); + ma_hit_sub(min_dp, src, n_read, readLen, mini_overlap_length, cov); + // prt_dbg_rid_ovlp(src, -1, (char*)"c85c2e91-0490-438b-977b-b7d056973996", "3"); + detect_chimeric_reads(src, n_read, readLen, *cov, asm_opt.max_ov_diff_final*2.0, ul, UL_COV_THRES); + // prt_dbg_rid_ovlp(src, -1, (char*)"c85c2e91-0490-438b-977b-b7d056973996", "4"); + ma_hit_cut(src, n_read, readLen, mini_overlap_length, cov); + // prt_dbg_rid_ovlp(src, -1, (char*)"c85c2e91-0490-438b-977b-b7d056973996", "5"); + ma_hit_flt(src, n_read, *cov, max_hang_length, mini_overlap_length); + // prt_dbg_rid_ovlp(src, -1, (char*)"c85c2e91-0490-438b-977b-b7d056973996", "6"); + ma_hit_contained_advance(src, n_read, *cov, ruIndex, max_hang_length, mini_overlap_length); + // prt_dbg_rid_ovlp(src, -1, (char*)"7b70a587-f56c-48ac-adf8-b98a67365063_2", "7"); + + if(!ul) { + sg = ma_sg_gen(src, n_read, *cov, max_hang_length, mini_overlap_length); + if(asm_opt.prt_dbg_gfa) prt_dbg_gfa(sg, "raw", *cov, src, ruIndex, max_hang_length, mini_overlap_length); + asg_arc_del_trans(sg, gap_fuzz); + } else { + ug_opt_t uopt; + sg = ma_sg_gen_ul(src, n_read, *cov, ruIndex, max_hang_length, mini_overlap_length, UL_COV_THRES); + if(asm_opt.prt_dbg_gfa) prt_dbg_gfa(sg, "raw", *cov, src, ruIndex, max_hang_length, mini_overlap_length); + gen_ug_opt_t(&uopt, src, NULL, max_hang_length, mini_overlap_length, gap_fuzz, min_dp, readLen, *cov, ruIndex, -1, -1, -1, -1, -1, b_mask_t, te); + + ///debug + // asg_symm(sg); + // dedup_contain_g(&uopt, sg); + + if(clean_contain_g(&uopt, sg, 0)) update_sg_uo(sg, src); + // prt_specfic_sge(sg, 10498, 10505, "--*--"); + asg_arc_del_trans_ul(sg, gap_fuzz); + // prt_specfic_sge(sg, 10498, 10505, "--#--"); + } + + init_bub_label_t(b_mask_t, MIN(10, asm_opt.thread_num), sg->n_seq); + asm_opt.coverage = get_coverage(src, *cov, n_read); + // prt_specfic_sge(sg, 22708, 22646, "--#--"); + return sg; +} + +void renew_g(ma_hit_t_alloc **sources, ma_hit_t_alloc **reverse_sources, long long *n_read, +uint64_t **readLen, ma_sub_t **coverage_cut, R_to_U *ruIndex, asg_t **sg, int64_t mini_overlap_length, +int64_t max_hang_length, ug_opt_t *uopt, int64_t clean_round, double min_ovlp_drop_ratio, +double max_ovlp_drop_ratio, int64_t max_tip, bub_label_t *b_mask_t, uint32_t is_trio, +char *o_file, const char *bin_file, uint64_t free_uld, uint64_t is_bridg, uint64_t deep_clean) +{ + ul_renew_t nopt; memset(&nopt, 0, sizeof(nopt)); + nopt.src = sources; nopt.r_src = reverse_sources; nopt.ruIndex = ruIndex; + nopt.n_read = n_read; nopt.readLen = readLen; nopt.sg = sg; + nopt.cov = coverage_cut; nopt.b_mask_t = b_mask_t; + nopt.max_hang = max_hang_length; nopt.mini_ovlp = mini_overlap_length; + ul_realignment_gfa(uopt, *sg, clean_round, min_ovlp_drop_ratio, max_ovlp_drop_ratio, + asm_opt.max_short_tip, asm_opt.max_short_ul_tip, b_mask_t, ha_opt_triobin(&asm_opt), o_file, &nopt, bin_file, free_uld, is_bridg, deep_clean); + // ma_ug_t *iug = ul_realignment_gfa(uopt, *sg, clean_round, min_ovlp_drop_ratio, max_ovlp_drop_ratio, + // asm_opt.max_short_tip, b_mask_t, ha_opt_triobin(&asm_opt), o_file); + // asg_t *ng = gen_ng(iug, *sg, uopt, coverage_cut, ruIndex, 256); + // ma_ug_destroy(iug); asg_destroy(*sg); + // (*sources) = R_INF.paf; + // (*reverse_sources) = R_INF.reverse_paf; + // (*n_read) = R_INF.total_reads; + // (*readLen) = R_INF.read_length; + // (*sg) = ng; + // ma_hit_contained_advance(*sources, *n_read, *coverage_cut, ruIndex, max_hang_length, mini_overlap_length); + // post_rescue(uopt, *sg, (*sources), (*reverse_sources), ruIndex, b_mask_t, 0); +} + +void gradually_renew_g(ma_hit_t_alloc **src, ma_hit_t_alloc **rev_src, long long *n_read, +uint64_t **readLen, ma_sub_t **cov, R_to_U *ruIndex, asg_t **sg, int64_t mini_overlap_length, +int64_t max_hang_length, ug_opt_t *uopt, int64_t clean_round, double min_ovlp_drop_ratio, +double max_ovlp_drop_ratio, int64_t max_tip, int64_t gap_fuzz, int64_t min_dp, +bub_label_t *b_mask_t, uint32_t is_trio, int32_t ul_aln_round, char *o_file, const char *bin_file, telo_end_t *te) +{ + int32_t k, strl = strlen(bin_file)+1, kt, cl, sl; char *id = NULL; + renew_g(src, rev_src, n_read, readLen, cov, ruIndex, sg, mini_overlap_length, max_hang_length, + uopt, clean_round, min_ovlp_drop_ratio, max_ovlp_drop_ratio, asm_opt.max_short_tip, b_mask_t, + is_trio, o_file, bin_file, (ul_aln_round<=1)?1:0, 1, /**((is_trio)?(0):(1))**/((asm_opt.polyploidy<=2)?1:0)); + gen_ug_opt_t(uopt, *src, *rev_src, max_hang_length, mini_overlap_length, gap_fuzz, min_dp, *readLen, + *cov, ruIndex, (asm_opt.max_short_tip*2), 0.15, 3, 0.05, 0.9, b_mask_t, te); + ug_ext_gfa(uopt, *sg, ug_ext_len); + + /**if(!ha_opt_triobin(&asm_opt))**/ hic_clean_adv(*sg, uopt); + + cl = strl+1; MALLOC(id, cl); + for (k = 1; k < ul_aln_round; k++) { + for(kt = k, sl = strl+1; kt > 0; kt/=10) sl++; + if(cl < sl) { + cl = sl; REALLOC(id, cl); + } + + sprintf(id, "%s%d", bin_file, k); + renew_g(src, rev_src, n_read, readLen, cov, ruIndex, sg, mini_overlap_length, max_hang_length, + uopt, clean_round, min_ovlp_drop_ratio, max_ovlp_drop_ratio, asm_opt.max_short_tip, b_mask_t, + is_trio, o_file, id, ((k+1)==ul_aln_round)?1:0, 0, 0); + gen_ug_opt_t(uopt, *src, *rev_src, max_hang_length, mini_overlap_length, gap_fuzz, min_dp, *readLen, + *cov, ruIndex, (asm_opt.max_short_tip*2), 0.15, 3, 0.05, 0.9, b_mask_t, te); + ug_ext_gfa(uopt, *sg, ug_ext_len); + /**if(!ha_opt_triobin(&asm_opt))**/ hic_clean_adv(*sg, uopt); + } + free(id); +} + +void clean_graph( +int min_dp, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +long long n_read, uint64_t* readLen, long long mini_overlap_length, +long long max_hang_length, long long clean_round, long long gap_fuzz, +float min_ovlp_drop_ratio, float max_ovlp_drop_ratio, char* output_file_name, +long long bubble_dist, int read_graph, R_to_U* ruIndex, asg_t **sg_ptr, +ma_sub_t **coverage_cut_ptr, uint8_t *cmk, int debug_g) +{ + char *o_file = get_outfile_name(output_file_name); + ma_sub_t *coverage_cut = *coverage_cut_ptr; + asg_t *sg = *sg_ptr; + bub_label_t b_mask_t; + ug_opt_t uopt; + telo_end_t *te = NULL; + + if(asm_opt.telo_motif) te = gen_telo_end_t(&R_INF, asm_opt.telo_motif, asm_opt.telo_mic_sc, asm_opt.telo_pen, asm_opt.telo_drop, asm_opt.thread_num); + + if(debug_g) + { + init_bub_label_t(&b_mask_t, MIN(10, asm_opt.thread_num), n_read); + goto debug_gfa; + } + ///just for debug + if(!cmk) renew_graph_init(sources, reverse_sources, sg, coverage_cut, ruIndex, n_read); + // if(asm_opt.is_ont) handle_chemical_arc(asm_opt.thread_num, R_INF.total_reads); + // if(asm_opt.is_ont) handle_chemical_r(asm_opt.thread_num, R_INF.total_reads); + + ///it's hard to say which function is better + ///normalize_ma_hit_t_single_side(sources, n_read); + + normalize_ma_hit_t_single_side_advance(sources, n_read, asm_opt.is_ont, cmk); + // normalize_ma_hit_t_single_side_advance_mult(sources, n_read, asm_opt.thread_num); + normalize_ma_hit_t_single_side_advance(reverse_sources, n_read, 0, cmk); + // normalize_ma_hit_t_single_side_advance_mult(reverse_sources, n_read, asm_opt.thread_num); + + if (ha_opt_triobin(&asm_opt)) + { + drop_edges_by_trio(sources, n_read); + } + else + { + memset(R_INF.trio_flag, AMBIGU, R_INF.total_reads*sizeof(uint8_t)); + } + if(asm_opt.ar) init_all_ul_t(&UL_INF, &R_INF); + // if (asm_opt.flag & HA_F_VERBOSE_GFA) { + // write_debug_graph(NULL, sources, coverage_cut, output_file_name, reverse_sources, ruIndex, &UL_INF); + // debug_gfa:; + // } + ///should recover edges from sources by using UL alignments + // prt_specific_overlap(sources, 22233, 22235, "0-a"); + // prt_specific_overlap(sources, 22235, 22233, "0-a"); + if(asm_opt.ar) { + create_ul_info(sources, reverse_sources, max_hang_length, mini_overlap_length, gap_fuzz, min_dp, readLen, coverage_cut, ruIndex, + (asm_opt.max_short_tip*2), 0.15, 3, 0.05, 0.9, &b_mask_t, te); + } + // prt_specific_overlap(sources, 22233, 22235, "0-b"); + // prt_specific_overlap(sources, 22235, 22233, "0-b"); + // prt_dbg_rid_ovlp(sources, 27087, NULL, "0-a"); + if(!(asm_opt.is_ont)) clean_weak_ma_hit_t(sources, reverse_sources, n_read, asm_opt.ar?UL_COV_THRES:(uint32_t)-1); + // prt_dbg_rid_ovlp(sources, 27087, NULL, "0-b"); + // prt_specific_overlap(sources, 22233, 22235, "0-c"); + // prt_specific_overlap(sources, 22235, 22233, "0-c"); + sg = gen_init_sg(min_dp, n_read, mini_overlap_length, max_hang_length, gap_fuzz, sources, readLen, ruIndex, + &b_mask_t, &coverage_cut, asm_opt.ar?&UL_INF:NULL, te); + // if(asm_opt.ar) exit(1); + /** + ///print_binned_reads(sources, n_read, coverage_cut); + + ///ma_hit_sub is just use to init coverage_cut, + ///it seems we do not need ma_hit_cut & ma_hit_flt + ma_hit_sub(min_dp, sources, n_read, readLen, mini_overlap_length, &coverage_cut); + detect_chimeric_reads(sources, n_read, readLen, coverage_cut, asm_opt.max_ov_diff_final * 2.0, asm_opt.ar?&UL_INF:NULL); + ma_hit_cut(sources, n_read, readLen, mini_overlap_length, &coverage_cut); + ///print_binned_reads(sources, n_read, coverage_cut); + ma_hit_flt(sources, n_read, coverage_cut, max_hang_length, mini_overlap_length); + ///fix_binned_reads(sources, n_read, coverage_cut); + ///just need to deal with trio here + ma_hit_contained_advance(sources, n_read, coverage_cut, ruIndex, max_hang_length, mini_overlap_length); + sg = ma_sg_gen(sources, n_read, coverage_cut, max_hang_length, mini_overlap_length); + ///debug_info_of_specfic_node((char*)"m64043_200504_050026/93784180/ccs", sg, ruIndex, (char*)"sbsbsb"); + init_bub_label_t(&b_mask_t, MIN(10, asm_opt.thread_num), sg->n_seq); + asg_arc_del_trans(sg, gap_fuzz); + asm_opt.coverage = get_coverage(sources, coverage_cut, n_read); + **/ + if(VERBOSE >= 1) + { + char* unlean_name = (char*)malloc(strlen(output_file_name)+25); + sprintf(unlean_name, "%s.unclean", output_file_name); + output_read_graph(sg, coverage_cut, unlean_name, n_read); + free(unlean_name); + } + + + // if (asm_opt.flag & HA_F_VERBOSE_GFA) { + // write_debug_graph(sg, sources, coverage_cut, output_file_name, reverse_sources, ruIndex, &UL_INF); + // debug_gfa:; + // } + + gen_ug_opt_t(&uopt, sources, reverse_sources, max_hang_length, mini_overlap_length, gap_fuzz, min_dp, readLen, coverage_cut, ruIndex, + (asm_opt.max_short_tip*2), 0.15, 3, 0.05, 0.9, &b_mask_t, te); + ul_clean_gfa(&uopt, sg, sources, reverse_sources, ruIndex, clean_round, min_ovlp_drop_ratio, max_ovlp_drop_ratio, + 0.6, asm_opt.max_short_tip, gap_fuzz, &b_mask_t, !!asm_opt.ar, ha_opt_triobin(&asm_opt), UL_COV_THRES, cmk, o_file); + ///@brief debug + if (asm_opt.flag & HA_F_VERBOSE_GFA) { + write_debug_graph(sg, sources, coverage_cut, output_file_name, reverse_sources, ruIndex, &UL_INF); + debug_gfa:; + gen_ug_opt_t(&uopt, sources, reverse_sources, max_hang_length, mini_overlap_length, gap_fuzz, min_dp, readLen, coverage_cut, ruIndex, + (asm_opt.max_short_tip*2), 0.15, 3, 0.05, 0.9, &b_mask_t, te); + // set_hom_global_coverage(&asm_opt, sg, coverage_cut, sources, reverse_sources, ruIndex, max_hang_length, mini_overlap_length); + } + + if(asm_opt.ar) { + gradually_renew_g(&sources, &reverse_sources, &n_read, &readLen, &coverage_cut, ruIndex, + &sg, mini_overlap_length, max_hang_length, &uopt, clean_round, min_ovlp_drop_ratio, + max_ovlp_drop_ratio, asm_opt.max_short_tip, gap_fuzz, min_dp, &b_mask_t, + ha_opt_triobin(&asm_opt), asm_opt.ul_clean_round, o_file, "re", te); + } else { + ug_ext_gfa(&uopt, sg, ug_ext_len); + if(!ha_opt_triobin(&asm_opt)) { + // output_unitig_graph(sg, coverage_cut, "pre_clean", sources, ruIndex, max_hang_length, mini_overlap_length); + hic_clean_adv(sg, &uopt); + } + } + + /** + if(asm_opt.ar) { + renew_g(&sources, &reverse_sources, &n_read, &readLen, &coverage_cut, ruIndex, &sg, mini_overlap_length, max_hang_length, + &uopt, clean_round, min_ovlp_drop_ratio, max_ovlp_drop_ratio, asm_opt.max_short_tip, &b_mask_t, + ha_opt_triobin(&asm_opt), o_file); + ///make sure uopt has been updated; not necessary + gen_ug_opt_t(&uopt, sources, reverse_sources, max_hang_length, mini_overlap_length, gap_fuzz, min_dp, readLen, coverage_cut, ruIndex, + (asm_opt.max_short_tip*2), 0.15, 3, 0.05, 0.9, &b_mask_t); + } + **/ + // print_debug_gfa(sg, NULL, coverage_cut, "UL.debug", sources, ruIndex, max_hang_length, mini_overlap_length, 0, 0, 0); + /** + asg_cut_tip(sg, asm_opt.max_short_tip); + ///debug_info_of_specfic_node("m64043_200505_112554/8849050/ccs", sg, "inner_1"); + ///drop_inexact_edegs_at_bubbles(sg, bubble_dist); + + if(clean_round > 0) + { + double cut_step; + if(clean_round == 1) + { + cut_step = max_ovlp_drop_ratio; + } + else + { + cut_step = (max_ovlp_drop_ratio - min_ovlp_drop_ratio) / (clean_round - 1); + } + double drop_ratio = min_ovlp_drop_ratio; + int i = 0; + for (i = 0; i < clean_round; i++, drop_ratio += cut_step) + { + if(drop_ratio > max_ovlp_drop_ratio) + { + drop_ratio = max_ovlp_drop_ratio; + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "\n\n**********%d-th round drop: drop_ratio = %f**********\n", + i, drop_ratio); + } + + ///just topological clean + pre_clean(sources, coverage_cut, sg, 1); + ///asg_arc_del_orthology(sg, reverse_sources, drop_ratio, asm_opt.max_short_tip); + // asg_arc_del_orthology_multiple_way(sg, reverse_sources, drop_ratio, asm_opt.max_short_tip); + // asg_cut_tip(sg, asm_opt.max_short_tip); + + asg_arc_identify_simple_bubbles_multi(sg, &b_mask_t, 1); + //reomve edge between two chromesomes + //this node must be a single read + asg_arc_del_false_node(sg, sources, asm_opt.max_short_tip); + asg_cut_tip(sg, asm_opt.max_short_tip); + + ///asg_arc_identify_simple_bubbles_multi(sg, 1); + asg_arc_identify_simple_bubbles_multi(sg, &b_mask_t, 0); + ///asg_arc_del_short_diploid_unclean_exact(sg, drop_ratio, sources); + if (ha_opt_triobin(&asm_opt)) + { + asg_arc_del_short_diploid_by_exact_trio(sg, asm_opt.max_short_tip, sources); + } + else + { + asg_arc_del_short_diploid_by_exact(sg, asm_opt.max_short_tip, sources); + } + asg_cut_tip(sg, asm_opt.max_short_tip); + + asg_arc_identify_simple_bubbles_multi(sg, &b_mask_t, 1); + if (ha_opt_triobin(&asm_opt)) + { + asg_arc_del_short_diploid_by_length_trio(sg, drop_ratio, asm_opt.max_short_tip, reverse_sources, + asm_opt.max_short_tip, 1, 1, 0, 0, ruIndex); + } + else + { + asg_arc_del_short_diploid_by_length(sg, drop_ratio, asm_opt.max_short_tip, reverse_sources, + asm_opt.max_short_tip, 1, 1, 0, 0, ruIndex); + } + asg_cut_tip(sg, asm_opt.max_short_tip); + + asg_arc_identify_simple_bubbles_multi(sg, &b_mask_t, 1); + asg_arc_del_short_false_link(sg, 0.6, 0.85, bubble_dist, reverse_sources, asm_opt.max_short_tip, ruIndex); + + asg_arc_identify_simple_bubbles_multi(sg, &b_mask_t, 1); + asg_arc_del_complex_false_link(sg, 0.6, 0.85, bubble_dist, reverse_sources, asm_opt.max_short_tip); + + asg_cut_tip(sg, asm_opt.max_short_tip); + } + } + if(VERBOSE >= 1) + { + fprintf(stderr, "\n\n**********final clean**********\n"); + } + + + pre_clean(sources, coverage_cut, sg, 1); + + + asg_arc_del_short_diploi_by_suspect_edge(sg, asm_opt.max_short_tip); + asg_cut_tip(sg, asm_opt.max_short_tip); + asg_arc_del_triangular_directly(sg, asm_opt.max_short_tip, reverse_sources, ruIndex); + + + asg_arc_identify_simple_bubbles_multi(sg, &b_mask_t, 0); + asg_arc_del_orthology_multiple_way(sg, reverse_sources, 0.4, asm_opt.max_short_tip, ruIndex); + asg_cut_tip(sg, asm_opt.max_short_tip); + + + + + asg_arc_identify_simple_bubbles_multi(sg, &b_mask_t, 0); + asg_arc_del_too_short_overlaps(sg, 2000, min_ovlp_drop_ratio, reverse_sources, asm_opt.max_short_tip, ruIndex); + asg_cut_tip(sg, asm_opt.max_short_tip); + + asg_arc_del_simple_circle_untig(sources, coverage_cut, sg, 100, 0); + + ///note: don't apply asg_arc_del_too_short_overlaps() after this function!!!! + rescue_contained_reads_aggressive(NULL, sg, sources, coverage_cut, ruIndex, max_hang_length, + mini_overlap_length, 10, 1, 0, NULL, NULL, &b_mask_t); + rescue_missing_overlaps_aggressive(NULL, sg, sources, coverage_cut, ruIndex, max_hang_length, + mini_overlap_length, 1, 0, NULL, &b_mask_t); + rescue_missing_overlaps_backward(NULL, sg, sources, coverage_cut, ruIndex, max_hang_length, + mini_overlap_length, 10, 1, 0, &b_mask_t); + // rescue_wrong_overlaps_to_unitigs(NULL, sg, sources, reverse_sources, coverage_cut, ruIndex, + // max_hang_length, mini_overlap_length, bubble_dist, NULL); + // rescue_no_coverage_aggressive(sg, sources, reverse_sources, &coverage_cut, ruIndex, max_hang_length, + // mini_overlap_length, bubble_dist, 10); + + + set_hom_global_coverage(&asm_opt, sg, coverage_cut, sources, reverse_sources, ruIndex, + max_hang_length, mini_overlap_length); + + rescue_bubble_by_chain(sg, coverage_cut, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, + ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, 10, gap_fuzz, &b_mask_t); + + + output_unitig_graph(sg, coverage_cut, o_file, sources, ruIndex, max_hang_length, mini_overlap_length); + // flat_bubbles(sg, ruIndex->is_het); free(ruIndex->is_het); ruIndex->is_het = NULL; + flat_soma_v(sg, sources, ruIndex); + **/ + + output_contig_graph_primary_pre(sg, coverage_cut, o_file, sources, reverse_sources, + asm_opt.small_pop_bubble_size, asm_opt.max_short_tip, ruIndex, max_hang_length, mini_overlap_length, &uopt); + + // if(asm_opt.ar) { + // char *op_file = get_outfile_name(o_file); + // ul_clean_gfa(&uopt, sg, sources, reverse_sources, ruIndex, clean_round, min_ovlp_drop_ratio, max_ovlp_drop_ratio, + // 0.6, asm_opt.max_short_tip, gap_fuzz, &b_mask_t, 0/**!!asm_opt.ar**/, ha_opt_triobin(&asm_opt), UL_COV_THRES, op_file); + // output_contig_graph_primary_pre(sg, coverage_cut, op_file, sources, reverse_sources, + // asm_opt.small_pop_bubble_size, asm_opt.max_short_tip, ruIndex, max_hang_length, mini_overlap_length, &uopt); + // free(op_file); + // } + /** + if (asm_opt.flag & HA_F_VERBOSE_GFA) + { + write_debug_graph(sg, sources, coverage_cut, output_file_name, n_read, reverse_sources, ruIndex); + debug_gfa:; + }**/ + if(asm_opt.fn_chr_bin) { + if(asm_opt.flag & HA_F_PARTITION) asm_opt.flag -= HA_F_PARTITION; + output_chr_bin_trio(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, + 0.05, 0.9, max_hang_length, mini_overlap_length, gap_fuzz, 0, &b_mask_t); + } + else if(asm_opt.fn_bin_poy) + { + if(asm_opt.flag & HA_F_PARTITION) asm_opt.flag -= HA_F_PARTITION; + output_poly_trio(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, + 0.05, 0.9, max_hang_length, mini_overlap_length, gap_fuzz, 0, &b_mask_t, asm_opt.polyploidy); + } + else if (ha_opt_triobin(&asm_opt) && ha_opt_hic(&asm_opt)) + { + if(asm_opt.flag & HA_F_PARTITION) asm_opt.flag -= HA_F_PARTITION; + benchmark_hic_graph(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), 0.15, 3, + ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, gap_fuzz, &b_mask_t); + } + else if (ha_opt_triobin(&asm_opt)) + { + if(asm_opt.flag & HA_F_PARTITION) asm_opt.flag -= HA_F_PARTITION; + // output_trio_graph(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), + // 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, 0, gap_fuzz, &uopt, &b_mask_t); + if(asm_opt.trio_cov_het_ovlp > 0) { + output_bp_trio_graph(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), + 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, &b_mask_t, gap_fuzz, &uopt); + } else { + output_trio_graph_joint(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), + 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, gap_fuzz, &b_mask_t, NULL, NULL, &uopt); + } + } + else if(ha_opt_hic(&asm_opt)) + { + if(asm_opt.flag & HA_F_PARTITION) asm_opt.flag -= HA_F_PARTITION; + if(asm_opt.polyploidy <= 2) { + output_hic_graph(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), + 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, gap_fuzz, &b_mask_t, &uopt); + } else { + output_hic_graph_mmhap(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), + 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, gap_fuzz, &b_mask_t, &uopt); + } + + // output_hic_graph_polyploid(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), + // 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, gap_fuzz, &b_mask_t); + } + else if((asm_opt.flag & HA_F_PARTITION) && (asm_opt.purge_level_primary > 0)) + { + output_bp_graph(sg, coverage_cut, o_file, sources, reverse_sources, (asm_opt.max_short_tip*2), + 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, &b_mask_t, gap_fuzz, &uopt); + } + else + { + if(asm_opt.flag & HA_F_PARTITION) asm_opt.flag -= HA_F_PARTITION; + output_contig_graph_primary(sg, coverage_cut, o_file, sources, reverse_sources, + (asm_opt.max_short_tip*2), 0.15, 3, ruIndex, 0.05, 0.9, max_hang_length, mini_overlap_length, &b_mask_t); + + output_contig_graph_alternative(sg, coverage_cut, o_file, sources, ruIndex, max_hang_length, mini_overlap_length); + } + + *coverage_cut_ptr = coverage_cut; + *sg_ptr = sg; + destory_bub_label_t(&b_mask_t); + if(te) { + destory_telo_end_t(te); free(te); te = NULL; + } + free(o_file); ///if(asm_opt.ar) destory_all_ul_t(&UL_INF); + fprintf(stderr, "Inconsistency threshold for low-quality regions in BED files: %u%%\n", asm_opt.bed_inconsist_rate); +} + +void build_string_graph_without_clean( +int min_dp, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +uint64_t n_read, uint64_t* readLen, long long mini_overlap_length, +long long max_hang_length, long long clean_round, long long gap_fuzz, +float min_ovlp_drop_ratio, float max_ovlp_drop_ratio, char* output_file_name, +long long bubble_dist, int read_graph, int write) +{ + R_to_U ruIndex; + init_R_to_U(&ruIndex, n_read); + asg_t *sg = NULL; uint8_t *cmk = NULL; + ma_sub_t* coverage_cut = NULL; + init_aux_table(); + ///actually min_thres = asm_opt.max_short_tip + 1 there are asm_opt.max_short_tip reads + min_thres = asm_opt.max_short_tip + 1; + if (asm_opt.flag & HA_F_VERBOSE_GFA) + { + if(load_debug_graph(/**NULL**/&sg, &sources, /**NULL**/&coverage_cut, output_file_name, &reverse_sources, &ruIndex, &UL_INF)) + { + fprintf(stderr, "debug gfa has been loaded\n"); + + clean_graph(min_dp, sources, reverse_sources, n_read, readLen, mini_overlap_length, + max_hang_length, clean_round, gap_fuzz, min_ovlp_drop_ratio, max_ovlp_drop_ratio, + output_file_name, bubble_dist, read_graph, &ruIndex, &sg, &coverage_cut, cmk, 1); + asg_destroy(sg); + free(coverage_cut); + destory_R_to_U(&ruIndex); + return; + } + } + if (asm_opt.write_index_to_disk && write) + { + write_all_data_to_disk(sources, reverse_sources, + &R_INF, output_file_name); + } + ///debug_info_of_specfic_read("m64011_190830_220126/31720629/ccs", sources, reverse_sources, -1, "beg"); + + if (!(asm_opt.flag & HA_F_BAN_ASSEMBLY)) + { + // if(asm_opt.is_ont) handle_chemical_r(asm_opt.thread_num, R_INF.total_reads); + if(asm_opt.is_ont) { + uint64_t i = 0, j = 0; + memset(ruIndex.index, -1, sizeof(uint32_t)*(ruIndex.len)); + for (i = 0; i < n_read; i++) { + for (j = 0; j < sources[i].length; j++) sources[i].buffer[j].del = 0; + for (j = 0; j < reverse_sources[i].length; j++) reverse_sources[i].buffer[j].del = 0; + } + if(asm_opt.is_ont) cmk = gen_chemical_arc_rf(asm_opt.thread_num, R_INF.total_reads); + } + try_rescue_overlaps(sources, reverse_sources, n_read, 4, asm_opt.is_ont); + + clean_graph(min_dp, sources, reverse_sources, n_read, readLen, mini_overlap_length, + max_hang_length, clean_round, gap_fuzz, min_ovlp_drop_ratio, max_ovlp_drop_ratio, + output_file_name, bubble_dist, read_graph, &ruIndex, &sg, &coverage_cut, cmk, 0); + + asg_destroy(sg); + free(coverage_cut); + } + + destory_R_to_U(&ruIndex); free(cmk); +} diff --git a/Overlaps.h b/Overlaps.h index 5405e79..7417a78 100644 --- a/Overlaps.h +++ b/Overlaps.h @@ -1,1253 +1,1253 @@ -#ifndef __OVERLAPS__ -#define __OVERLAPS__ - -#define __STDC_LIMIT_MACROS -#include -#include -#include "kvec.h" -#include "kdq.h" -#include "ksort.h" -#include "CommandLines.h" - -///#define MIN_OVERLAP_LEN 2000 -///#define MIN_OVERLAP_LEN 500 -///#define MIN_OVERLAP_LEN 50 -///#define MIN_OVERLAP_LEN 50 -///#define MIN_OVERLAP_COVERAGE 1 -///#define MIN_OVERLAP_COVERAGE 0 -///#define MAX_HANG_LEN 1000 -///#define MAX_HANG_PRE 0.8 -///#define GAP_FUZZ 1000 -///#define MAX_SHORT_TIPS 3 -///#define MAX_BUBBLE_DIST 10000000 -#define SMALL_BUBBLE_SIZE (uint32_t)-1 -//#define SMALL_BUBBLE_SIZE 1000 -#define PRIMARY_LABLE 0 -#define ALTER_LABLE 1 -#define HAP_LABLE 2 -#define FAKE_LABLE 4 -#define TRIO_THRES 0.9 -#define DOUBLE_CHECK_THRES 0.1 -#define FINAL_DOUBLE_CHECK_THRES 0.2 -#define CHIMERIC_TRIM_THRES 4 -#define GAP_LEN 100 -// #define PRIMARY_LABLE 1 -// #define ALTER_LABLE 2 -// #define HAP_LABLE 4 -#define ug_ext_len 75000 -#define UL_COV_THRES 2 - -#define Get_qn(RECORD) ((uint32_t)((RECORD).qns>>32)) -#define Get_qs(RECORD) ((uint32_t)((RECORD).qns)) -#define Get_qe(RECORD) ((RECORD).qe) -#define Get_tn(RECORD) ((RECORD).tn) -#define Get_ts(RECORD) ((RECORD).ts) -#define Get_te(RECORD) ((RECORD).te) - -#define LONG_TIPS 0 -#define TWO_INPUT 1 -#define TWO_OUTPUT 2 -#define MUL_INPUT 3 -#define MUL_OUTPUT 4 -#define END_TIPS 5 -#define LONG_TIPS_UNDER_MAX_EXT 6 -#define LOOP 7 - -#define TRIM 10 -#define CUT 11 -#define CUT_DIF_HAP 12 -#define SEC_MODE ((uint32_t)(0x3fffffffU)) - -///query is the read itself -typedef struct { - uint32_t qn, qs, qe; - uint32_t tn, ts, te; - uint32_t sec:30, el:1, rev:1; -} ul_ov_t; - -typedef struct { - ul_ov_t *a; - size_t n, m; -} kv_ul_ov_t; - -typedef struct { - uint32_t tn, rn, el; - uint32_t qs, qe, ts, te; - uint8_t dir:5, pe:1, full:1, rev:1; -} emask_t; - -typedef struct { - emask_t *a; - size_t n, m; -} kv_emask_t; - -typedef struct { - kv_emask_t *a; - uint32_t n; -} idx_emask_t; - -typedef struct { - uint64_t n, mask; - uint8_t *hh; - uint64_t tlen, tm; -} telo_end_t; - -typedef struct { - ///off: start idx in mg128_t * a[]; - ///cnt: how many eles in this chain - ///a[off, off+cnt) saves the eles in this chain - int32_t off, cnt:31, inner_pre:1; - ///ref_id|rev - uint32_t v; - ///chain in ref: [rs, re) - ///chain in query: [qs, qe) - int32_t rs, re, qs, qe; - ///score: chain score - int32_t score, dist_pre; - uint32_t hash_pre; -} mg_lchain_t; - -typedef struct { - mg_lchain_t *a; - size_t n, m; -}vec_mg_lchain_t; - -///query is the read itself -typedef struct { - uint64_t qns; - uint32_t qe, tn, ts, te; - // uint32_t ml:31, rev:1; - uint32_t cc:30, ml:1, rev:1; - uint32_t bl:31, del:1; - uint8_t el; - uint8_t no_l_indel; -} ma_hit_t; - -typedef struct { - ma_hit_t* buffer; - uint32_t size; - uint32_t length; - uint8_t is_fully_corrected; - uint8_t is_abnormal; -} ma_hit_t_alloc; - - -void init_ma_hit_t_alloc(ma_hit_t_alloc* x); -void clear_ma_hit_t_alloc(ma_hit_t_alloc* x); -void resize_ma_hit_t_alloc(ma_hit_t_alloc* x, uint32_t size); -void destory_ma_hit_t_alloc(ma_hit_t_alloc* x); -void add_ma_hit_t_alloc(ma_hit_t_alloc* x, ma_hit_t* element); -void ma_hit_sort_tn(ma_hit_t *a, long long n); -void ma_hit_sort_qns(ma_hit_t *a, long long n); - -int load_all_data_from_disk(ma_hit_t_alloc **sources, ma_hit_t_alloc **reverse_sources, char* output_file_name); - - -typedef struct { - uint32_t s:31, del:1, e; - uint8_t c; -} ma_sub_t; - -void ma_hit_sub(int min_dp, ma_hit_t_alloc* sources, long long n_read, uint64_t* readLen, -long long mini_overlap_length, ma_sub_t** coverage_cut); -void ma_hit_cut(ma_hit_t_alloc* sources, long long n_read, uint64_t* readLen, -long long mini_overlap_length, ma_sub_t** coverage_cut); -void ma_hit_flt(ma_hit_t_alloc* sources, long long n_read, const ma_sub_t *coverage_cut, -int max_hang, int min_ovlp); -long long get_specific_overlap(ma_hit_t_alloc* x, uint32_t qn, uint32_t tn); - - -typedef struct { - uint32_t qSpre, qEpre, qScur, qEcur, qn;///[qSp, qEp) && [qSn, qEn] - uint32_t tSpre, tEpre, tScur, tEcur, tn; -} u_trans_hit_t; - -typedef struct { - size_t n, m; - u_trans_hit_t* a; -} kv_u_trans_hit_t; - - - -typedef struct { - uint32_t qs, qe, qn; - uint32_t ts, te, tn; - uint32_t occ; - double nw; - uint8_t f:6, rev:1, del:1; - ///uint8_t qo:4, to:4; -} u_trans_t; - -typedef struct { - size_t n, m; - u_trans_t* a; - kvec_t(uint64_t) idx; -} kv_u_trans_t; - -#define u_trans_a(x, id) ((x).a + ((x).idx.a[(id)]>>32)) -#define u_trans_n(x, id) ((uint32_t)((x).idx.a[(id)])) -#define OU_MASK (0x3fffU) - -typedef struct { - uint64_t ul; - uint32_t v; - uint32_t ol:31, del:1; - uint16_t ou:14, strong:1, no_l_indel:1; - uint8_t el; - // uint8_t strong; - // uint8_t el; - // uint8_t no_l_indel; -} asg_arc_t; - -typedef struct { - size_t n, m; - asg_arc_t* a; -} kv_asg_arc_t; - - -typedef struct { - uint32_t len:31, circ:1; // len: length of the unitig; circ: circular if non-zero - uint32_t start, end; // start: starting vertex in the string graph; end: ending vertex - uint32_t m, n; // number of reads - uint64_t *a; // list of reads - char *s; // unitig sequence is not null -} ma_utg_t; - - - -typedef struct { - uint32_t len:31, del:1; - uint8_t c; -} asg_seq_t; - -typedef struct { - uint32_t m_arc, n_arc:31, is_srt:1; - asg_arc_t *arc; - uint32_t m_seq, n_seq:31, is_symm:1; - uint32_t r_seq; - - asg_seq_t *seq; - uint64_t *idx; - - uint8_t* seq_vis; - - uint32_t n_F_seq; - ma_utg_t* F_seq; -} asg_t; - -typedef struct { - ma_hit_t_alloc* src; - int64_t min_ovlp, max_hang, max_hang_rate, need_srt, gap_fuzz; - asg_t *g; - uint32_t *idx; - kvec_t(uint32_t) pi; - asg_arc_t *a; - size_t n, m; -} flex_asg_t; - -typedef struct { - uint32_t i[2]; -}flex_asg_e_retrive_t; - -asg_t *asg_init(void); -void asg_destroy(asg_t *g); -void asg_arc_sort(asg_t *g); -void asg_seq_set(asg_t *g, int sid, int len, int del); -void asg_arc_index(asg_t *g); -void asg_cleanup(asg_t *g); -void asg_symm(asg_t *g); -void print_gfa(asg_t *g); - - -typedef struct { size_t n, m; uint64_t *a; } asg64_v; -typedef struct { size_t n, m; uint32_t *a; } asg32_v; -typedef struct { size_t n, m; ma_utg_t *a;} ma_utg_v; -typedef struct { asg64_v idx; kv_ul_ov_t srt;} mask_ul_ov_t; - -typedef struct { - ma_utg_v u; - asg_t *g; - kvec_t(uint64_t) occ; -} ma_ug_t; - -typedef struct { - uint32_t utg:31, ori:1, start, len; -} utg_intv_t; - -typedef struct { - uint32_t x, s, e; -} utg_ct_t; - -typedef struct { - uint32_t *idx; - kvec_t(uint64_t) interval; -} ucov_t; - -typedef struct { - uint32_t u, off, pos; -} utg_rid_dt; - -typedef struct { - uint32_t *idx; - kvec_t(utg_rid_dt) p; - asg_t *rg; -} utg_rid_t; - -typedef struct { - kvec_t(uint64_t) idx; - kvec_t(utg_ct_t) rids; - kvec_t(uint8_t) is_c; -} ul_contain; - -typedef struct { - ma_ug_t *ug; - asg_t *rg; - uint64_t *idx; -} cvert_t; - -typedef struct { - size_t n, m; - uint8_t *a; - uint64_t *idx; -} hmap_t; - -typedef struct { - ma_ug_t *hg; - size_t n, m; - uint64_t *a; - hmap_t *mm; -} hpc_t; - -typedef struct { - uint32_t s, e; - uint8_t k; -} hpc_ss_t; - -typedef struct { - uint32_t s, e; -} hpc_idx_t; - -typedef struct { - size_t n, m; - hpc_ss_t *a; - hpc_idx_t *idx; - uint64_t idx_n; -} hpc_re_t; - -#define hpc_len(x, id) ((x).hg->u.a[(id)].len>>1) -#define hpc_str(x, id, rev) (((x).hg->u.a[(id)].s)+((rev)?((x).hg->u.a[(id)].len>>1):(0))) - -typedef struct { - uint32_t n; - uint8_t *a; -} bit_mask_t; - -#define set_bit_mask_t(x, i) ((x).a[(i)>>3]|=(((uint8_t)1)<<((i)&((uint32_t)7)))) -#define get_bit_mask_t(x, i) ((x).a[(i)>>3]&(((uint8_t)1)<<((i)&((uint32_t)7)))) - -typedef struct { - ma_ug_t *ug; - hpc_t *hpc_g; - ucov_t *cc; - ucov_t *cr; - ul_contain *ct; - utg_rid_t *r_ug; - // cvert_t *nug; - // kv_ul_ov_t *ov; -} ul_idx_t; - -#define MA_HT_DOUBLE (-1024) -#define MA_HT_INT (-1) -#define MA_HT_QCONT (-2) -#define MA_HT_TCONT (-3) -#define MA_HT_SHORT_OVLP (-4) - -///in default, max_hang = 1000, int_frac = 0.8, min_ovlp = 50 -static inline int ma_hit2arc(const ma_hit_t *h, int ql, int tl, int max_hang, float int_frac, int min_ovlp, asg_arc_t *p) -{ - int32_t tl5, tl3, ext5, ext3, qs = (int32_t)h->qns; - uint32_t u, v, l; // u: query end; v: target end; l: length from u to v - - ///if query and target are in different strand - if (h->rev) tl5 = tl - h->te, tl3 = h->ts; // tl5: 5'-end overhang (on the query strand); tl3: similar - else tl5 = h->ts, tl3 = tl - h->te; - - ///ext5 and ext3 is the hang on left side and right side, respectively - ext5 = qs < tl5? qs : tl5; - ext3 = ql - (int)h->qe < tl3? ql - (int)h->qe : tl3; - - - /** - if (ext5 > max_hang || ext3 > max_hang || h->qe - qs < (h->qe - qs + ext5 + ext3) * int_frac) - return MA_HT_INT; - **/ - ///ext3 and ext5 should be always 0 - if (ext5 > max_hang || ext3 > max_hang - || h->qe - qs < (h->qe - qs + ext5 + ext3) * int_frac - || h->te - h->ts < (h->te - h->ts + ext5 + ext3) * int_frac) - { - return MA_HT_INT; - } - - /** - ********************************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**************************** - **/ - - if (qs <= tl5 && ql - (int)h->qe <= tl3) return MA_HT_QCONT; // query contained in target - else if (qs >= tl5 && ql - (int)h->qe >= tl3) return MA_HT_TCONT; // target contained in query - else if (qs > tl5) u = 0, v = !!h->rev, l = qs - tl5; ///u = 0 means query-to-target overlap, l is the length of node in string graph (not the overlap length) - else u = 1, v = !h->rev, l = (ql - h->qe) - tl3; ///u = 1 means target-to-query overlaps, l is the length of node in string graph (not the overlap length) - if ((int)h->qe - qs + ext5 + ext3 < min_ovlp || (int)h->te - (int)h->ts + ext5 + ext3 < min_ovlp) return MA_HT_SHORT_OVLP; // short overlap - ///u = 0 / 1 means query-to-target / target-to-query overlaps, - ///l is the length of node in string graph (not the overlap length between two reads) - u |= h->qns>>32<<1, v |= h->tn<<1; - /** - p->ul: |____________31__________|__________1___________|______________32_____________| - qn direction of overlap length of this node (not overlap length) - (in the view of query) - p->v : |___________31___________|__________1___________| - tn reverse direction of overlap - (in the view of target) - p->ol: overlap length - **/ - p->ul = (uint64_t)u<<32 | l, p->v = v, p->ol = ql - l, p->del = 0; - ///l is the length of node in string graph (not the overlap length) - - p->strong = h->ml; - p->el = h->el; - p->no_l_indel = h->no_l_indel; - return l; -} - - - -#define asg_arc_len(arc) ((uint32_t)(arc).ul) -#define asg_arc_n(g, v) ((uint32_t)(g)->idx[(v)]) -#define asg_arc_a(g, v) (&(g)->arc[(g)->idx[(v)]>>32]) - -static inline uint32_t asg_get_arc(asg_t *g, uint32_t v, uint32_t w, asg_arc_t* t) -{ - 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].del) continue; - if(av[i].v == w) - { - (*t) = av[i]; - return 1; - } - } - - return 0; -} - -// append an arc -static inline asg_arc_t *asg_arc_pushp(asg_t *g) -{ - if (g->n_arc == g->m_arc) { - g->m_arc = g->m_arc? g->m_arc<<1 : 16; - g->arc = (asg_arc_t*)realloc(g->arc, g->m_arc * sizeof(asg_arc_t)); - } - return &g->arc[g->n_arc++]; -} - -// set asg_arc_t::del for v->w -static inline void asg_arc_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; -} - -// set asg_arc_t::del and asg_seq_t::del to 1 for sequence s and all its associated arcs -static inline void asg_seq_del(asg_t *g, uint32_t s) -{ - uint32_t k; - g->seq[s].del = 1; - for (k = 0; k < 2; ++k) { - uint32_t i, v = s<<1 | k; - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - for (i = 0; i < nv; ++i) { - av[i].del = 1; - asg_arc_del(g, av[i].v^1, v^1, 1); - } - } -} - -static inline void asg_seq_drop(asg_t *g, uint32_t s) -{ - ///s is not at primary - if(g->seq[s].c == ALTER_LABLE) - { - uint32_t k; - for (k = 0; k < 2; ++k) - { - ///two directions of this node - uint32_t i, v = s<<1 | k; - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - for (i = 0; i < nv; ++i) - { - if(av[i].del) continue; - ///if output node is at primary - /****************************may have hap bugs********************************/ - ///if(g->seq[(av[i].v>>1)].c == PRIMARY_LABLE) - ///if(g->seq[(av[i].v>>1)].c == PRIMARY_LABLE || g->seq[(av[i].v>>1)].c == HAP_LABLE) - if(g->seq[(av[i].v>>1)].c != ALTER_LABLE) - {/****************************may have hap bugs********************************/ - av[i].del = 1; - asg_arc_del(g, av[i].v^1, v^1, 1); - } - } - } - } -} - - - - - -/****************** - * Bubble popping * - ******************/ - -typedef struct { - uint32_t p; // the optimal parent vertex - uint32_t d; // the shortest distance from the initial vertex - uint32_t c; // max count of positive reads - uint32_t m; // max count of negative reads - uint32_t np; // max count of non-positive reads - uint32_t nc; // max count of reads, no matter positive or negative - uint32_t r:31, s:1; // r: the number of remaining incoming arc; s: state - //s: state, s=0, this edge has not been visited, otherwise, s=1 -} binfo_t; - -typedef struct { - ///all information for each node - binfo_t *a; - kvec_t(uint32_t) S; // set of vertices without parents, nodes with all incoming edges visited - kvec_t(uint32_t) T; // set of tips - kvec_t(uint32_t) b; // visited vertices - kvec_t(uint32_t) e; // visited edges/arcs -} buf_t; - -typedef struct { - kvec_t(uint64_t) Nodes; - kvec_t(uint64_t) Edges; - uint32_t pre_n_seq, seqID; -} C_graph; - -typedef struct { - kvec_t(uint8_t) a; - uint32_t i; -} kvec_t_u8_warp; - -typedef struct { - kvec_t(uint32_t) a; - uint32_t i; -} kvec_t_u32_warp; - -typedef struct { - kvec_t(int32_t) a; - uint32_t i; -} kvec_t_i32_warp; - -typedef struct { - kvec_t(uint64_t) a; - uint64_t i; -} kvec_t_u64_warp; - -typedef struct { - kvec_t(asg_arc_t) a; - uint64_t i; -}kvec_asg_arc_t_warp; - -void sort_kvec_t_u64_warp(kvec_t_u64_warp* u_vecs, uint32_t is_descend); -int asg_arc_del_multi(asg_t *g); -int asg_arc_del_asymm(asg_t *g); - -typedef struct { - uint32_t q_pos; - uint32_t t_pos; - uint32_t t_id; - uint32_t is_color; -} Hap_Align; - -typedef struct { - kvec_t(Hap_Align) x; - uint64_t i; -} Hap_Align_warp; - -typedef struct { - buf_t* b_0; - uint32_t untigI; - uint32_t readI; - uint32_t offset; -} rIdContig; - -// count the number of outgoing arcs, including reduced arcs -static inline int count_out_with_del(const asg_t *g, uint32_t v) -{ - uint32_t nv = asg_arc_n(g, v); - return nv; -} - - -// count the number of outgoing arcs, including reduced arcs -static inline int count_out_without_del(const asg_t *g, uint32_t v) -{ - uint32_t i, n, nv = asg_arc_n(g, v); - const asg_arc_t *av = asg_arc_a(g, v); - - for (i = n = 0; i < nv; ++i) - if (!av[i].del) ++n; - return n; -} - - -void build_string_graph_without_clean( -int min_dp, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -uint64_t n_read, uint64_t* readLen, long long mini_overlap_length, -long long max_hang_length, long long clean_round, long long gap_fuzz, -float min_ovlp_drop_ratio, float max_ovlp_drop_ratio, char* output_file_name, -long long bubble_dist, int read_graph, int write); - -void debug_info_of_specfic_read(const char* name, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, int id, const char* command); -void collect_abnormal_edges(ma_hit_t_alloc* paf, ma_hit_t_alloc* rev_paf, long long readNum); -void add_overlaps(ma_hit_t_alloc* source_paf, ma_hit_t_alloc* dest_paf, uint64_t* source_index, long long listLen); -void remove_overlaps(ma_hit_t_alloc* source_paf, uint64_t* source_index, long long listLen); -void add_overlaps_from_different_sources(ma_hit_t_alloc* source_paf_list, ma_hit_t_alloc* dest_paf, -uint64_t* source_index, long long listLen); - -#define EvaluateLen(U, id) ((U).a[(id)].start) -#define IsMerge(U, id) ((U).a[(id)].end) -#define kv_reuse(v, rn, rm, r) ((v).n = (rn), (v).m = (rm), (v).a = (r)) -#define Get_vis(visit, v, d) (((visit)[(v)>>1])&(((((v)<<(d))&1)+1))) -#define Set_vis(visit, v, d) (((visit)[(v)>>1])|=(((((v)<<(d))&1)+1))) - - - - - -typedef struct { - uint64_t len; - uint32_t* index; - uint8_t* is_het; -} R_to_U; - -void init_R_to_U(R_to_U* x, uint64_t len); -void destory_R_to_U(R_to_U* x); -void set_R_to_U(R_to_U* x, uint32_t rID, uint32_t uID, uint32_t is_Unitig, uint8_t* flag); -void get_R_to_U(R_to_U* x, uint32_t rID, uint32_t* uID, uint32_t* is_Unitig); -void transfor_R_to_U(R_to_U* x); -void debug_utg_graph(ma_ug_t *ug, asg_t* read_g, kvec_asg_arc_t_warp* edge, int require_equal_nv, int test_tangle); -long long asg_arc_del_simple_circle_untig(ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, asg_t *g, long long circleLen, int is_drop); - -typedef struct { - asg_t* g; - - asg_arc_t *av; - uint32_t nv; - uint32_t av_i; - - asg_arc_t* new_edges; - uint32_t new_edges_n; - uint32_t new_edges_i; -} Edge_iter; - -typedef struct { - asg_arc_t x; - uint64_t Off; - uint64_t weight; -}asg_arc_t_offset; - -typedef struct { - kvec_t(asg_arc_t_offset) a; - uint64_t i; -}kvec_asg_arc_t_offset; - - - -void init_Edge_iter(asg_t* g, uint32_t v, asg_arc_t* new_edges, uint32_t new_edges_n, Edge_iter* x); -int get_arc_t(Edge_iter* x, asg_arc_t* get); - - -inline int get_real_length(asg_t *g, uint32_t v, uint32_t* v_s) -{ - uint32_t i, kv = 0; - for (i = 0, kv = 0; i < asg_arc_n(g, v); i++) - { - if(!asg_arc_a(g, v)[i].del) - { - if(v_s) v_s[kv] = asg_arc_a(g, v)[i].v; - kv++; - } - } - - return kv; -} - -inline uint32_t check_tip(asg_t *sg, uint32_t begNode, uint32_t* endNode, buf_t* b, uint32_t max_ext) -{ - ///cut tip of length <= max_ext - uint32_t v = begNode, w; - uint32_t kv; - uint32_t eLen = 0; - (*endNode) = (uint32_t)-1; - b->b.n = 0; - while (1) - { - kv = get_real_length(sg, v, NULL); - (*endNode) = v; - eLen++; - if(b) kv_push(uint32_t, b->b, v); - if(kv == 0) return END_TIPS; - if(kv > 1) return MUL_OUTPUT; - ///if(eLen > max_ext) return LONG_TIPS; - ///kv must be 1 here - kv = get_real_length(sg, v, &w); - ///here this value must be >= 1 - if(get_real_length(sg, w^1, NULL)!=1) return MUL_INPUT; - v = w; - if(v == begNode) return LOOP; - if(eLen >= max_ext) return LONG_TIPS; - } -} - -inline uint32_t get_unitig(asg_t *sg, ma_ug_t *ug, uint32_t begNode, uint32_t* endNode, -long long* nodeLen, long long* baseLen, long long* max_stop_nodeLen, long long* max_stop_baseLen, -uint32_t stops_threshold, buf_t* b) -{ - ma_utg_v* u = NULL; - uint32_t v = begNode, w, k; - uint32_t kv, return_flag, n_stops = 0; - long long pre_baseLen = 0, pre_nodeLen = 0; - long long cur_baseLen = 0, cur_nodeLen = 0; - (*max_stop_nodeLen) = (*max_stop_baseLen) = (*nodeLen) = (*baseLen) = 0; - (*endNode) = (uint32_t)-1; - if(ug!=NULL) u = &(ug->u); - - while (1) - { - kv = get_real_length(sg, v, NULL); - (*endNode) = v; - if(u == NULL) - { - (*nodeLen)++; - } - else - { - (*nodeLen) += EvaluateLen((*u), v>>1); - } - if(b) kv_push(uint32_t, b->b, v); - ///means reach the end of a unitig - if(kv!=1) (*baseLen) += sg->seq[v>>1].len; - if(kv==0) - { - return_flag = END_TIPS; - break; - ///return END_TIPS; - } - if(kv>1) - { - return_flag = MUL_OUTPUT; - break; - ///return MUL_OUTPUT; - } - ///kv must be 1 here - kv = get_real_length(sg, v, &w); - ///means reach the end of a unitig - if(get_real_length(sg, w^1, NULL)!=1) - { - - n_stops++; - if(n_stops >= stops_threshold) - { - (*baseLen) += sg->seq[v>>1].len; - return_flag = MUL_INPUT; - break; - ///return MUL_INPUT; - } - else - { - for (k = 0; k < asg_arc_n(sg, v); k++) - { - if(asg_arc_a(sg, v)[k].del) continue; - ///here is just one undeleted edge - (*baseLen) += asg_arc_len(asg_arc_a(sg, v)[k]); - break; - } - } - - cur_baseLen = (*baseLen) - pre_baseLen; - pre_baseLen = (*baseLen); - if(cur_baseLen > (*max_stop_baseLen)) - { - (*max_stop_baseLen) = cur_baseLen; - } - - - cur_nodeLen = (*nodeLen) - pre_nodeLen; - pre_nodeLen = (*nodeLen); - if(cur_nodeLen > (*max_stop_nodeLen)) - { - (*max_stop_nodeLen) = cur_nodeLen; - } - } - else - { - for (k = 0; k < asg_arc_n(sg, v); k++) - { - if(asg_arc_a(sg, v)[k].del) continue; - ///here is just one undeleted edge - (*baseLen) += asg_arc_len(asg_arc_a(sg, v)[k]); - break; - } - } - - - v = w; - if(v == begNode) - { - return_flag = LOOP; - break; - ///return LOOP; - } - } - - - - - cur_baseLen = (*baseLen) - pre_baseLen; - pre_baseLen = (*baseLen); - if(cur_baseLen > (*max_stop_baseLen)) - { - (*max_stop_baseLen) = cur_baseLen; - } - - - cur_nodeLen = (*nodeLen) - pre_nodeLen; - pre_nodeLen = (*nodeLen); - if(cur_nodeLen > (*max_stop_nodeLen)) - { - (*max_stop_nodeLen) = cur_nodeLen; - } - - return return_flag; -} - -#define UNAVAILABLE (uint32_t)-1 -#define PLOID 0 -#define NON_PLOID 1 -// #define DIFF_HAP_RATE 0.75 -#define TRIO_DROP_THRES 0.9 -#define TRIO_DROP_LENGTH_THRES 0.8 -#define MAX_STOP_RATE 0.6 -#define TANGLE_MISSED_THRES 0.6 -#define HET_HOM_RATE 0.7 - -typedef struct { - uint32_t father_occ; - uint32_t mother_occ; - uint32_t ambig_occ; - uint32_t drop_occ; - uint32_t total; -} Trio_counter; - -typedef struct { - uint32_t p; // the optimal parent vertex - uint32_t d; // the shortest distance from the initial vertex - uint32_t r:31, s:1; // r: the number of remaining incoming arc; s: state -} binfo_s_t; - -typedef struct { - ///all information for each node - binfo_s_t *a; - kvec_t(uint32_t) S; // set of vertices without parents, nodes with all incoming edges visited - kvec_t(uint32_t) b; // visited vertices - kvec_t(uint32_t) e; // visited edges/arcs -} buf_s_t; - -typedef struct{ - buf_s_t *b; - uint32_t n_thres, n_reads; - asg_t *g; - uint32_t check_cross; - uint64_t bub_dist; -} bub_label_t; - -void resolve_tangles(ma_ug_t *src, asg_t *read_g, ma_hit_t_alloc* reverse_sources, long long minLongUntig, -long long maxShortUntig, float l_untig_rate, float max_node_threshold, R_to_U* ruIndex, uint8_t* is_r_het, -uint32_t trio_flag, float drop_ratio); -void adjust_utg_advance(asg_t *sg, ma_ug_t *ug, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, bub_label_t* b_mask_t, uint8_t* is_r_het); -void rescue_contained_reads_aggressive(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t chainLenThres, uint32_t is_bubble_check, -uint32_t is_primary_check, kvec_asg_arc_t_warp* new_rtg_edges, kvec_t_u32_warp* new_rtg_nodes, bub_label_t* b_mask_t); -void rescue_missing_overlaps_aggressive(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t is_bubble_check, uint32_t is_primary_check, kvec_asg_arc_t_warp* new_rtg_edges, bub_label_t* b_mask_t); -void all_to_all_deduplicate(ma_ug_t* ug, asg_t* read_g, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, uint8_t postive_flag, float drop_rate, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, uint8_t* is_r_het, float double_check_rate, int non_tig_occ); -void drop_semi_circle(ma_ug_t *ug, asg_t* nsg, asg_t* read_g, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, uint8_t* is_r_het); -void rescue_wrong_overlaps_to_unitigs(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -ma_sub_t *coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp, long long bubble_dist, kvec_asg_arc_t_warp* keep_edges, bub_label_t* b_mask_t); -void get_unitig_trio_flag(ma_utg_t* nsu, uint32_t flag, uint32_t* require, uint32_t* non_require, uint32_t* ambigious); -void rescue_missing_overlaps_backward(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t backward_steps, uint32_t is_bubble_check, uint32_t is_primary_check, bub_label_t* b_mask_t); -uint32_t get_edge_from_source(ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, uint32_t target, asg_arc_t* t); -int unitig_arc_del_short_diploid_by_length(asg_t *g, float drop_ratio); -void asg_bub_backtrack_primary(asg_t *g, uint32_t v0, buf_t *b); -void set_hom_global_coverage(hifiasm_opt_t *opt, asg_t *sg, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, int max_hang, int min_ovlp); -void rescue_bubble_by_chain(asg_t *sg, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, -float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, uint32_t chainLenThres, long long gap_fuzz, -bub_label_t* b_mask_t, long long no_trio_recover, uint8_t *cmk); - -typedef struct{ - double weight; - uint32_t uID; - uint64_t dis; - uint8_t is_cc:7, del:1; - uint64_t occ; - ///uint64_t occ:63, scaff:1; - ///uint32_t enzyme; -} hc_edge; - -typedef struct{ - kvec_t(hc_edge) e; - kvec_t(hc_edge) f;//forbiden -} hc_linkeage; - -typedef struct{ - uint64_t beg, end; -}bed_interval; - -typedef struct{ - size_t n, m; - bed_interval* a; -}bed_in; - -typedef struct{ - kvec_t(hc_linkeage) a; - kvec_t(uint64_t) enzymes; -} hc_links; - -#define N_HET 0 -#define C_HET 1 -#define P_HET 2 -#define S_HET 4 - -typedef struct { - uint32_t p_x_p, p_y_p, p_x, p_y; - uint32_t c_x_p, c_y_p; - uint8_t c_rev; -} ca_buf_t; - -typedef struct { - size_t n, m; - ca_buf_t* a; -} kv_ca_buf_t; - -typedef struct { - kvec_t(uint32_t) uIDs; - kvec_t(uint32_t) iDXs; - uint32_t chain_num; -} sub_tran_t; - -typedef struct{ - uint32_t* rUidx; - uint64_t* rUpos; - uint8_t* ir_het; - uint32_t r_num, u_num; - kvec_t(bed_in) bed; - kvec_t(uint32_t) topo_buf; - kvec_t(uint32_t) topo_res; - buf_t b_buf_0, b_buf_1; - ///uint32_t* uLen; - kv_u_trans_t k_trans; - kv_u_trans_hit_t k_t_b; - kv_ca_buf_t c_buf; - sub_tran_t st; -}trans_chain; - -typedef struct { - uint32_t n; - uint32_t* cov; - uint64_t* pos_idx; - ma_hit_t_alloc* reverse_sources; - ma_sub_t *coverage_cut; - R_to_U* ruIndex; - asg_t *read_g; - int max_hang; - int min_ovlp; - kvec_asg_arc_t_offset u_buffer; - kvec_t_i32_warp tailIndex; - kvec_t_i32_warp prevIndex; - uint8_t* is_r_het; - trans_chain* t_ch; -}hap_cov_t; - -typedef struct{ - ///kvec_t(hc_edge) a; - size_t n, m; - hc_edge *a; -}hc_edge_warp; - -typedef struct { - uint32_t qs, qe, qn, qus, que; - uint32_t ts, te, tn, tus, tue; -} utg_thit_t; - -typedef struct { - size_t n, m; - utg_thit_t* a; -} kv_utg_thit_t_t; - -typedef struct { - ma_hit_t_alloc* reverse_sources; - ma_sub_t *coverage_cut; - R_to_U* ruIndex; - asg_t *read_g; - kvec_asg_arc_t_offset u_buffer; - kvec_t_i32_warp tailIndex; - kvec_t_i32_warp prevIndex; - kv_utg_thit_t_t k_t_b; - kv_ca_buf_t c_buf; - kv_u_trans_t k_trans; - uint64_t *pos_idx, rn; - kvec_t(uint32_t) topo_res; - ma_ug_t *cug; - int max_hang; - int min_ovlp; - - ma_utg_v u; - kv_u_trans_t t; - buf_t b0, b1; -} utg_trans_t; - -typedef struct { - ma_ug_t *ug; - kvec_t(uint64_t) idx; - kvec_t(uint32_t) dst; -} spg_t; - -void init_hc_links(hc_links* link, uint64_t ug_num, trans_chain* t_ch); -void destory_hc_links(hc_links* link); -uint64_t get_bub_pop_max_dist(asg_t *g, buf_t *b); -uint64_t get_bub_pop_max_dist_advance(asg_t *g, buf_t *b); -uint64_t asg_bub_pop1_primary_trio(asg_t *g, ma_ug_t *utg, uint32_t v0, uint64_t max_dist, buf_t *b, uint32_t positive_flag, -uint32_t negative_flag, uint32_t is_pop, uint64_t* path_base_len, uint64_t* path_nodes, hap_cov_t *cov, uint32_t is_update_chain, uint32_t keep_d, utg_trans_t *o); - -void adjust_utg_by_primary(ma_ug_t **ug, asg_t* read_g, float drop_rate, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, -R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, -kvec_asg_arc_t_warp* new_rtg_edges, hap_cov_t **i_cov, bub_label_t* b_mask_t, uint32_t collect_p_trans, uint32_t collect_p_trans_f); -ma_ug_t* copy_untig_graph(ma_ug_t *src); -ma_ug_t* output_trio_unitig_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -uint8_t flag, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, -float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, int gap_fuzz, int is_bench, bub_label_t* b_mask_t, char *f_prefix, uint8_t *kpt_buf, kvec_asg_arc_t_warp *r_edges); -asg_t* copy_read_graph(asg_t *src); -ma_ug_t *ma_ug_gen(asg_t *g); -void ma_ug_destroy(ma_ug_t *ug); - -inline int inter_interval(int a_s, int a_e, int b_s, int b_e, int* i_s, int* i_e) -{ - if(a_s > b_e || b_s > a_e) return 0; - if(i_s) (*i_s) = a_s >= b_s? a_s : b_s; ///MAX(a_s, b_s); - if(i_e) (*i_e) = a_e <= b_e? a_e : b_e; ///MIN(a_e, b_e); - return 1; -} - -inline uint32_t get_origin_uid(uint32_t v, trans_chain* t_ch, uint32_t *off, uint32_t *idx) -{ - if(off) (*off) = (t_ch->rUpos[v>>1]>>32); - if(idx) (*idx) = (uint32_t)(t_ch->rUpos[v>>1]); - if(t_ch->rUpos[v>>1] == (uint64_t)-1) return (uint32_t)-1; - return (uint32_t)(((t_ch->rUidx[v>>1]>>1)<<1) + ((t_ch->rUidx[v>>1]^v)&1)); -} -void chain_origin_trans_uid_by_distance(hap_cov_t *cov, asg_t *read_sg, -uint32_t *pri_a, uint32_t pri_n, uint32_t pri_beg, uint64_t *i_pri_len, -uint32_t *aux_a, uint32_t aux_n, uint32_t aux_beg, uint64_t *i_aux_len, -ma_ug_t *ug, uint32_t flag, double overall_score, const char* cmd); -int asg_arc_del_trans(asg_t *g, int fuzz); -void kt_u_trans_t_idx(kv_u_trans_t *ta, uint32_t n); -void kt_u_trans_t_simple_symm(kv_u_trans_t *ta, uint32_t un, uint32_t symm_add); -uint32_t get_u_trans_spec(kv_u_trans_t *ta, uint32_t qn, uint32_t tn, u_trans_t **r_a, uint32_t *occ); -int ma_ug_seq(ma_ug_t *g, asg_t *read_g, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, -kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, kvec_asg_arc_t_warp *E, uint32_t is_polish); - - -typedef struct{ - ma_sub_t* coverage_cut; - ma_hit_t_alloc* sources; - ma_hit_t_alloc* reverse_sources; - long long tipsLen; - float tip_drop_ratio; - long long stops_threshold; - R_to_U* ruIndex; - float chimeric_rate; - float drop_ratio; - int max_hang; - int min_ovlp; - int is_bench; - long long gap_fuzz; - int64_t min_dp; - bub_label_t* b_mask_t; - uint64_t* readLen; - telo_end_t *te; -}ug_opt_t; - -typedef struct{ - ma_hit_t_alloc **src; - ma_hit_t_alloc **r_src; - long long *n_read; - uint64_t **readLen; - asg_t **sg; - R_to_U *ruIndex; - ma_sub_t **cov; - bub_label_t *b_mask_t; - int64_t max_hang; - int64_t mini_ovlp; -}ul_renew_t; - -void adjust_utg_by_trio(ma_ug_t **ug, asg_t* read_g, uint8_t flag, float drop_rate, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, -R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, -int gap_fuzz, kvec_asg_arc_t_warp* new_rtg_edges, bub_label_t* b_mask_t); -uint32_t cmp_untig_graph(ma_ug_t *src, ma_ug_t *dest); -void reduce_hamming_error(asg_t *sg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -int max_hang, int min_ovlp, long long gap_fuzz); -int ma_ug_seq_scaffold(ma_ug_t *g, asg_t *read_g, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, -kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, kvec_asg_arc_t_warp *E, uint32_t is_polish); -void ma_ug_print(const ma_ug_t *ug, asg_t* read_g, const ma_sub_t *coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex, const char* prefix, FILE *fp); -void ma_ug_print_simple(const ma_ug_t *ug, asg_t* read_g, const ma_sub_t *coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex, const char* prefix, FILE *fp); -trans_chain* init_trans_chain(ma_ug_t *ug, uint64_t r_num); -void destory_trans_chain(trans_chain **x); - -typedef struct {///[cBeg, cEnd) - uint32_t u_i, r_i, len, s_pos_cur, s_pre_v, s_pre_w, p_v, p_idx, p_uId, cBeg, cEnd; - ///buf_t* x; - uint32_t *a, an; - ma_ug_t *ug; - asg_t *read_sg; - trans_chain* t_ch; -} u_trans_hit_idx; -void reset_u_trans_hit_idx(u_trans_hit_idx *t, uint32_t* i_x_a, uint32_t i_x_n, ma_ug_t *i_ug, -asg_t *i_read_sg, trans_chain* i_t_ch, uint32_t i_cBeg, uint32_t i_cEnd); -uint32_t get_u_trans_hit(u_trans_hit_idx *t, u_trans_hit_t *hit); -inline uint32_t get_offset_adjust(uint32_t offset, uint32_t offsetLen, uint32_t targetLen) -{ - return ((double)(offset)/(double)(offsetLen))*targetLen; -} - -uint32_t set_utg_offset(uint32_t *a, uint32_t a_n, ma_ug_t *ug, asg_t *read_sg, uint64_t* pos_idx, uint32_t is_clear, -uint32_t only_len); -uint64_t get_utg_cov(ma_ug_t *ug, uint32_t uID, asg_t* read_g, -const ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag); -trans_chain* load_hc_trans(const char *fn); -char *get_outfile_name(char* output_file_name); -void reset_u_trans_hit_idx(u_trans_hit_idx *t, uint32_t* i_x_a, uint32_t i_x_n, ma_ug_t *i_ug, -asg_t *i_read_sg, trans_chain* i_t_ch, uint32_t i_cBeg, uint32_t i_cEnd); -void extract_sub_overlaps(uint32_t i_tScur, uint32_t i_tEcur, uint32_t i_tSpre, uint32_t i_tEpre, -uint32_t tn, kv_u_trans_hit_t* ktb, uint32_t bn); -void clean_u_trans_t_idx(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g); -void clean_u_trans_t_idx_adv(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g); -void clean_u_trans_t_idx_filter_adv(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, double sc_sec_rate, uint64_t uniform_only); -uint32_t test_dbug(ma_ug_t* ug, FILE* fp); -void write_dbug(ma_ug_t* ug, FILE* fp); -int asg_arc_identify_simple_bubbles_multi(asg_t *g, bub_label_t* x, int check_cross); -uint8_t get_tip_trio_infor(asg_t *sg, uint32_t begNode); -int asg_topocut_aux(asg_t *g, uint32_t v, int max_ext); -int asg_topocut_aux_pg(asg_t *g, uint32_t v, int max_ext, uint32_t *rv); -int asg_arc_del_triangular_directly(asg_t *g, long long min_edge_length, -ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex); -int asg_arc_del_short_diploid_by_exact(asg_t *g, int max_ext, ma_hit_t_alloc* sources); -uint32_t print_debug_gfa(asg_t *read_g, ma_ug_t *ug, ma_sub_t* coverage_cut, const char* output_file_name, -ma_hit_t_alloc* sources, R_to_U* ruIndex, int max_hang, int min_ovlp, int is_update_ou, int is_check_alter_lable, int is_seq); -void debug_info_of_specfic_node(const char* name, asg_t *g, R_to_U* ruIndex, const char* command); -ma_ug_t *gen_polished_ug(const ug_opt_t *uopt, asg_t *sg); -void output_unitig_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, R_to_U* ruIndex, int max_hang, int min_ovlp); -void flat_soma_v(asg_t *sg, ma_hit_t_alloc* sources, R_to_U* ruIndex); -void hic_clean(asg_t* read_g); -int64_t count_edges_v_w(asg_t *g, uint32_t v, uint32_t w); -void renew_utg(ma_ug_t **ug, asg_t* read_g, kvec_asg_arc_t_warp* edge); -void merge_unitig_content(ma_utg_t* collection, ma_ug_t* ug, asg_t* read_g, kvec_asg_arc_t_warp* edge); -void reset_bub_label_t(bub_label_t* x, asg_t *g, uint64_t bub_dist, uint32_t check_cross); -void set_reverse_overlap(ma_hit_t* dest, ma_hit_t* source); -// void break_ug_contig(ma_ug_t **ug, asg_t *read_g, All_reads *RNF, ma_sub_t *coverage_cut, -// ma_hit_t_alloc* sources, R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, -// int* b_low_cov, int* b_high_cov, double m_rate); -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); -void hic_clean_adv(asg_t *sg, ug_opt_t *uopt); -void update_ug_ou(ma_ug_t *ug, asg_t *sg); -int asg_arc_del_trans_ul(asg_t *g, int fuzz); - -#define JUNK_COV 5 -#define DISCARD_RATE 0.8 - -typedef struct { - uint32_t n, m, a; -} mmhap_status_t; - -typedef struct { - kvec_t(mmhap_status_t) h; - kvec_t(uint32_t) a; -} mmhap_t; - -typedef struct { // global data structure for kt_pipeline() - ma_ug_t *ug; - asg_t *rg; - uint64_t *idx; - asg64_v cov; - uint64_t hom_min, hom_max, hom_cov, het_cov; -} ug_rid_cov_t; - -ug_rid_cov_t* gen_ug_rid_cov_t(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc *src); -void destory_ug_rid_cov_t(ug_rid_cov_t *p); -uint32_t append_cov_line_ug_rid_cov_t(uint64_t uid, uint64_t *qcc, u_trans_t *p, ug_rid_cov_t *idx, uint64_t hom_cut, double cut_rate); -uint64_t infer_mmhap_copy(ma_ug_t *ug, asg_t *sg, ma_hit_t_alloc *src, uint8_t *ff, uint64_t uid, uint64_t het_cov, uint64_t n_hap); -uint64_t trans_sec_cut0(kv_u_trans_t *ta, asg64_v *srt, uint32_t id, double sec_rate, uint64_t bd, ma_ug_t *ug); -void clean_u_trans_t_idx_filter_mmhap_adv(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* src, ug_rid_cov_t *in); -void gen_ug_rid_cov_t_by_ovlp(kv_u_trans_t *ta, ug_rid_cov_t *cc); -void rescue_chimeric_reads_aggressive(ma_ug_t *i_ug, asg_t *rg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t chainLenThres, uint32_t is_bubble_check, uint32_t is_primary_check, kvec_asg_arc_t_warp* new_rtg_edges, -kvec_t_u32_warp* new_rtg_nodes, bub_label_t* b_mask_t, uint8_t *cmk); - -#define UC_Read_resize(v, s) do {\ - if ((v).size<(s)) {REALLOC((v).seq,(s));(v).size=(s);}\ - } while (0) - -#endif +#ifndef __OVERLAPS__ +#define __OVERLAPS__ + +#define __STDC_LIMIT_MACROS +#include +#include +#include "kvec.h" +#include "kdq.h" +#include "ksort.h" +#include "CommandLines.h" + +///#define MIN_OVERLAP_LEN 2000 +///#define MIN_OVERLAP_LEN 500 +///#define MIN_OVERLAP_LEN 50 +///#define MIN_OVERLAP_LEN 50 +///#define MIN_OVERLAP_COVERAGE 1 +///#define MIN_OVERLAP_COVERAGE 0 +///#define MAX_HANG_LEN 1000 +///#define MAX_HANG_PRE 0.8 +///#define GAP_FUZZ 1000 +///#define MAX_SHORT_TIPS 3 +///#define MAX_BUBBLE_DIST 10000000 +#define SMALL_BUBBLE_SIZE (uint32_t)-1 +//#define SMALL_BUBBLE_SIZE 1000 +#define PRIMARY_LABLE 0 +#define ALTER_LABLE 1 +#define HAP_LABLE 2 +#define FAKE_LABLE 4 +#define TRIO_THRES 0.9 +#define DOUBLE_CHECK_THRES 0.1 +#define FINAL_DOUBLE_CHECK_THRES 0.2 +#define CHIMERIC_TRIM_THRES 4 +#define GAP_LEN 100 +// #define PRIMARY_LABLE 1 +// #define ALTER_LABLE 2 +// #define HAP_LABLE 4 +#define ug_ext_len 75000 +#define UL_COV_THRES 2 + +#define Get_qn(RECORD) ((uint32_t)((RECORD).qns>>32)) +#define Get_qs(RECORD) ((uint32_t)((RECORD).qns)) +#define Get_qe(RECORD) ((RECORD).qe) +#define Get_tn(RECORD) ((RECORD).tn) +#define Get_ts(RECORD) ((RECORD).ts) +#define Get_te(RECORD) ((RECORD).te) + +#define LONG_TIPS 0 +#define TWO_INPUT 1 +#define TWO_OUTPUT 2 +#define MUL_INPUT 3 +#define MUL_OUTPUT 4 +#define END_TIPS 5 +#define LONG_TIPS_UNDER_MAX_EXT 6 +#define LOOP 7 + +#define TRIM 10 +#define CUT 11 +#define CUT_DIF_HAP 12 +#define SEC_MODE ((uint32_t)(0x3fffffffU)) + +///query is the read itself +typedef struct { + uint32_t qn, qs, qe; + uint32_t tn, ts, te; + uint32_t sec:30, el:1, rev:1; +} ul_ov_t; + +typedef struct { + ul_ov_t *a; + size_t n, m; +} kv_ul_ov_t; + +typedef struct { + uint32_t tn, rn, el; + uint32_t qs, qe, ts, te; + uint8_t dir:5, pe:1, full:1, rev:1; +} emask_t; + +typedef struct { + emask_t *a; + size_t n, m; +} kv_emask_t; + +typedef struct { + kv_emask_t *a; + uint32_t n; +} idx_emask_t; + +typedef struct { + uint64_t n, mask; + uint8_t *hh; + uint64_t tlen, tm; +} telo_end_t; + +typedef struct { + ///off: start idx in mg128_t * a[]; + ///cnt: how many eles in this chain + ///a[off, off+cnt) saves the eles in this chain + int32_t off, cnt:31, inner_pre:1; + ///ref_id|rev + uint32_t v; + ///chain in ref: [rs, re) + ///chain in query: [qs, qe) + int32_t rs, re, qs, qe; + ///score: chain score + int32_t score, dist_pre; + uint32_t hash_pre; +} mg_lchain_t; + +typedef struct { + mg_lchain_t *a; + size_t n, m; +}vec_mg_lchain_t; + +///query is the read itself +typedef struct { + uint64_t qns; + uint32_t qe, tn, ts, te; + // uint32_t ml:31, rev:1; + uint32_t cc:30, ml:1, rev:1; + uint32_t bl:31, del:1; + uint8_t el; + uint8_t no_l_indel; +} ma_hit_t; + +typedef struct { + ma_hit_t* buffer; + uint32_t size; + uint32_t length; + uint8_t is_fully_corrected; + uint8_t is_abnormal; +} ma_hit_t_alloc; + + +void init_ma_hit_t_alloc(ma_hit_t_alloc* x); +void clear_ma_hit_t_alloc(ma_hit_t_alloc* x); +void resize_ma_hit_t_alloc(ma_hit_t_alloc* x, uint32_t size); +void destory_ma_hit_t_alloc(ma_hit_t_alloc* x); +void add_ma_hit_t_alloc(ma_hit_t_alloc* x, ma_hit_t* element); +void ma_hit_sort_tn(ma_hit_t *a, long long n); +void ma_hit_sort_qns(ma_hit_t *a, long long n); + +int load_all_data_from_disk(ma_hit_t_alloc **sources, ma_hit_t_alloc **reverse_sources, char* output_file_name); + + +typedef struct { + uint32_t s:31, del:1, e; + uint8_t c; +} ma_sub_t; + +void ma_hit_sub(int min_dp, ma_hit_t_alloc* sources, long long n_read, uint64_t* readLen, +long long mini_overlap_length, ma_sub_t** coverage_cut); +void ma_hit_cut(ma_hit_t_alloc* sources, long long n_read, uint64_t* readLen, +long long mini_overlap_length, ma_sub_t** coverage_cut); +void ma_hit_flt(ma_hit_t_alloc* sources, long long n_read, const ma_sub_t *coverage_cut, +int max_hang, int min_ovlp); +long long get_specific_overlap(ma_hit_t_alloc* x, uint32_t qn, uint32_t tn); + + +typedef struct { + uint32_t qSpre, qEpre, qScur, qEcur, qn;///[qSp, qEp) && [qSn, qEn] + uint32_t tSpre, tEpre, tScur, tEcur, tn; +} u_trans_hit_t; + +typedef struct { + size_t n, m; + u_trans_hit_t* a; +} kv_u_trans_hit_t; + + + +typedef struct { + uint32_t qs, qe, qn; + uint32_t ts, te, tn; + uint32_t occ; + double nw; + uint8_t f:6, rev:1, del:1; + ///uint8_t qo:4, to:4; +} u_trans_t; + +typedef struct { + size_t n, m; + u_trans_t* a; + kvec_t(uint64_t) idx; +} kv_u_trans_t; + +#define u_trans_a(x, id) ((x).a + ((x).idx.a[(id)]>>32)) +#define u_trans_n(x, id) ((uint32_t)((x).idx.a[(id)])) +#define OU_MASK (0x3fffU) + +typedef struct { + uint64_t ul; + uint32_t v; + uint32_t ol:31, del:1; + uint16_t ou:14, strong:1, no_l_indel:1; + uint8_t el; + // uint8_t strong; + // uint8_t el; + // uint8_t no_l_indel; +} asg_arc_t; + +typedef struct { + size_t n, m; + asg_arc_t* a; +} kv_asg_arc_t; + + +typedef struct { + uint32_t len:31, circ:1; // len: length of the unitig; circ: circular if non-zero + uint32_t start, end; // start: starting vertex in the string graph; end: ending vertex + uint32_t m, n; // number of reads + uint64_t *a; // list of reads + char *s; // unitig sequence is not null +} ma_utg_t; + + + +typedef struct { + uint32_t len:31, del:1; + uint8_t c; +} asg_seq_t; + +typedef struct { + uint32_t m_arc, n_arc:31, is_srt:1; + asg_arc_t *arc; + uint32_t m_seq, n_seq:31, is_symm:1; + uint32_t r_seq; + + asg_seq_t *seq; + uint64_t *idx; + + uint8_t* seq_vis; + + uint32_t n_F_seq; + ma_utg_t* F_seq; +} asg_t; + +typedef struct { + ma_hit_t_alloc* src; + int64_t min_ovlp, max_hang, max_hang_rate, need_srt, gap_fuzz; + asg_t *g; + uint32_t *idx; + kvec_t(uint32_t) pi; + asg_arc_t *a; + size_t n, m; +} flex_asg_t; + +typedef struct { + uint32_t i[2]; +}flex_asg_e_retrive_t; + +asg_t *asg_init(void); +void asg_destroy(asg_t *g); +void asg_arc_sort(asg_t *g); +void asg_seq_set(asg_t *g, int sid, int len, int del); +void asg_arc_index(asg_t *g); +void asg_cleanup(asg_t *g); +void asg_symm(asg_t *g); +void print_gfa(asg_t *g); + + +typedef struct { size_t n, m; uint64_t *a; } asg64_v; +typedef struct { size_t n, m; uint32_t *a; } asg32_v; +typedef struct { size_t n, m; ma_utg_t *a;} ma_utg_v; +typedef struct { asg64_v idx; kv_ul_ov_t srt;} mask_ul_ov_t; + +typedef struct { + ma_utg_v u; + asg_t *g; + kvec_t(uint64_t) occ; +} ma_ug_t; + +typedef struct { + uint32_t utg:31, ori:1, start, len; +} utg_intv_t; + +typedef struct { + uint32_t x, s, e; +} utg_ct_t; + +typedef struct { + uint32_t *idx; + kvec_t(uint64_t) interval; +} ucov_t; + +typedef struct { + uint32_t u, off, pos; +} utg_rid_dt; + +typedef struct { + uint32_t *idx; + kvec_t(utg_rid_dt) p; + asg_t *rg; +} utg_rid_t; + +typedef struct { + kvec_t(uint64_t) idx; + kvec_t(utg_ct_t) rids; + kvec_t(uint8_t) is_c; +} ul_contain; + +typedef struct { + ma_ug_t *ug; + asg_t *rg; + uint64_t *idx; +} cvert_t; + +typedef struct { + size_t n, m; + uint8_t *a; + uint64_t *idx; +} hmap_t; + +typedef struct { + ma_ug_t *hg; + size_t n, m; + uint64_t *a; + hmap_t *mm; +} hpc_t; + +typedef struct { + uint32_t s, e; + uint8_t k; +} hpc_ss_t; + +typedef struct { + uint32_t s, e; +} hpc_idx_t; + +typedef struct { + size_t n, m; + hpc_ss_t *a; + hpc_idx_t *idx; + uint64_t idx_n; +} hpc_re_t; + +#define hpc_len(x, id) ((x).hg->u.a[(id)].len>>1) +#define hpc_str(x, id, rev) (((x).hg->u.a[(id)].s)+((rev)?((x).hg->u.a[(id)].len>>1):(0))) + +typedef struct { + uint32_t n; + uint8_t *a; +} bit_mask_t; + +#define set_bit_mask_t(x, i) ((x).a[(i)>>3]|=(((uint8_t)1)<<((i)&((uint32_t)7)))) +#define get_bit_mask_t(x, i) ((x).a[(i)>>3]&(((uint8_t)1)<<((i)&((uint32_t)7)))) + +typedef struct { + ma_ug_t *ug; + hpc_t *hpc_g; + ucov_t *cc; + ucov_t *cr; + ul_contain *ct; + utg_rid_t *r_ug; + // cvert_t *nug; + // kv_ul_ov_t *ov; +} ul_idx_t; + +#define MA_HT_DOUBLE (-1024) +#define MA_HT_INT (-1) +#define MA_HT_QCONT (-2) +#define MA_HT_TCONT (-3) +#define MA_HT_SHORT_OVLP (-4) + +///in default, max_hang = 1000, int_frac = 0.8, min_ovlp = 50 +static inline int ma_hit2arc(const ma_hit_t *h, int ql, int tl, int max_hang, float int_frac, int min_ovlp, asg_arc_t *p) +{ + int32_t tl5, tl3, ext5, ext3, qs = (int32_t)h->qns; + uint32_t u, v, l; // u: query end; v: target end; l: length from u to v + + ///if query and target are in different strand + if (h->rev) tl5 = tl - h->te, tl3 = h->ts; // tl5: 5'-end overhang (on the query strand); tl3: similar + else tl5 = h->ts, tl3 = tl - h->te; + + ///ext5 and ext3 is the hang on left side and right side, respectively + ext5 = qs < tl5? qs : tl5; + ext3 = ql - (int)h->qe < tl3? ql - (int)h->qe : tl3; + + + /** + if (ext5 > max_hang || ext3 > max_hang || h->qe - qs < (h->qe - qs + ext5 + ext3) * int_frac) + return MA_HT_INT; + **/ + ///ext3 and ext5 should be always 0 + if (ext5 > max_hang || ext3 > max_hang + || h->qe - qs < (h->qe - qs + ext5 + ext3) * int_frac + || h->te - h->ts < (h->te - h->ts + ext5 + ext3) * int_frac) + { + return MA_HT_INT; + } + + /** + ********************************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**************************** + **/ + + if (qs <= tl5 && ql - (int)h->qe <= tl3) return MA_HT_QCONT; // query contained in target + else if (qs >= tl5 && ql - (int)h->qe >= tl3) return MA_HT_TCONT; // target contained in query + else if (qs > tl5) u = 0, v = !!h->rev, l = qs - tl5; ///u = 0 means query-to-target overlap, l is the length of node in string graph (not the overlap length) + else u = 1, v = !h->rev, l = (ql - h->qe) - tl3; ///u = 1 means target-to-query overlaps, l is the length of node in string graph (not the overlap length) + if ((int)h->qe - qs + ext5 + ext3 < min_ovlp || (int)h->te - (int)h->ts + ext5 + ext3 < min_ovlp) return MA_HT_SHORT_OVLP; // short overlap + ///u = 0 / 1 means query-to-target / target-to-query overlaps, + ///l is the length of node in string graph (not the overlap length between two reads) + u |= h->qns>>32<<1, v |= h->tn<<1; + /** + p->ul: |____________31__________|__________1___________|______________32_____________| + qn direction of overlap length of this node (not overlap length) + (in the view of query) + p->v : |___________31___________|__________1___________| + tn reverse direction of overlap + (in the view of target) + p->ol: overlap length + **/ + p->ul = (uint64_t)u<<32 | l, p->v = v, p->ol = ql - l, p->del = 0; + ///l is the length of node in string graph (not the overlap length) + + p->strong = h->ml; + p->el = h->el; + p->no_l_indel = h->no_l_indel; + return l; +} + + + +#define asg_arc_len(arc) ((uint32_t)(arc).ul) +#define asg_arc_n(g, v) ((uint32_t)(g)->idx[(v)]) +#define asg_arc_a(g, v) (&(g)->arc[(g)->idx[(v)]>>32]) + +static inline uint32_t asg_get_arc(asg_t *g, uint32_t v, uint32_t w, asg_arc_t* t) +{ + 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].del) continue; + if(av[i].v == w) + { + (*t) = av[i]; + return 1; + } + } + + return 0; +} + +// append an arc +static inline asg_arc_t *asg_arc_pushp(asg_t *g) +{ + if (g->n_arc == g->m_arc) { + g->m_arc = g->m_arc? g->m_arc<<1 : 16; + g->arc = (asg_arc_t*)realloc(g->arc, g->m_arc * sizeof(asg_arc_t)); + } + return &g->arc[g->n_arc++]; +} + +// set asg_arc_t::del for v->w +static inline void asg_arc_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; +} + +// set asg_arc_t::del and asg_seq_t::del to 1 for sequence s and all its associated arcs +static inline void asg_seq_del(asg_t *g, uint32_t s) +{ + uint32_t k; + g->seq[s].del = 1; + for (k = 0; k < 2; ++k) { + uint32_t i, v = s<<1 | k; + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + for (i = 0; i < nv; ++i) { + av[i].del = 1; + asg_arc_del(g, av[i].v^1, v^1, 1); + } + } +} + +static inline void asg_seq_drop(asg_t *g, uint32_t s) +{ + ///s is not at primary + if(g->seq[s].c == ALTER_LABLE) + { + uint32_t k; + for (k = 0; k < 2; ++k) + { + ///two directions of this node + uint32_t i, v = s<<1 | k; + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + for (i = 0; i < nv; ++i) + { + if(av[i].del) continue; + ///if output node is at primary + /****************************may have hap bugs********************************/ + ///if(g->seq[(av[i].v>>1)].c == PRIMARY_LABLE) + ///if(g->seq[(av[i].v>>1)].c == PRIMARY_LABLE || g->seq[(av[i].v>>1)].c == HAP_LABLE) + if(g->seq[(av[i].v>>1)].c != ALTER_LABLE) + {/****************************may have hap bugs********************************/ + av[i].del = 1; + asg_arc_del(g, av[i].v^1, v^1, 1); + } + } + } + } +} + + + + + +/****************** + * Bubble popping * + ******************/ + +typedef struct { + uint32_t p; // the optimal parent vertex + uint32_t d; // the shortest distance from the initial vertex + uint32_t c; // max count of positive reads + uint32_t m; // max count of negative reads + uint32_t np; // max count of non-positive reads + uint32_t nc; // max count of reads, no matter positive or negative + uint32_t r:31, s:1; // r: the number of remaining incoming arc; s: state + //s: state, s=0, this edge has not been visited, otherwise, s=1 +} binfo_t; + +typedef struct { + ///all information for each node + binfo_t *a; + kvec_t(uint32_t) S; // set of vertices without parents, nodes with all incoming edges visited + kvec_t(uint32_t) T; // set of tips + kvec_t(uint32_t) b; // visited vertices + kvec_t(uint32_t) e; // visited edges/arcs +} buf_t; + +typedef struct { + kvec_t(uint64_t) Nodes; + kvec_t(uint64_t) Edges; + uint32_t pre_n_seq, seqID; +} C_graph; + +typedef struct { + kvec_t(uint8_t) a; + uint32_t i; +} kvec_t_u8_warp; + +typedef struct { + kvec_t(uint32_t) a; + uint32_t i; +} kvec_t_u32_warp; + +typedef struct { + kvec_t(int32_t) a; + uint32_t i; +} kvec_t_i32_warp; + +typedef struct { + kvec_t(uint64_t) a; + uint64_t i; +} kvec_t_u64_warp; + +typedef struct { + kvec_t(asg_arc_t) a; + uint64_t i; +}kvec_asg_arc_t_warp; + +void sort_kvec_t_u64_warp(kvec_t_u64_warp* u_vecs, uint32_t is_descend); +int asg_arc_del_multi(asg_t *g); +int asg_arc_del_asymm(asg_t *g); + +typedef struct { + uint32_t q_pos; + uint32_t t_pos; + uint32_t t_id; + uint32_t is_color; +} Hap_Align; + +typedef struct { + kvec_t(Hap_Align) x; + uint64_t i; +} Hap_Align_warp; + +typedef struct { + buf_t* b_0; + uint32_t untigI; + uint32_t readI; + uint32_t offset; +} rIdContig; + +// count the number of outgoing arcs, including reduced arcs +static inline int count_out_with_del(const asg_t *g, uint32_t v) +{ + uint32_t nv = asg_arc_n(g, v); + return nv; +} + + +// count the number of outgoing arcs, including reduced arcs +static inline int count_out_without_del(const asg_t *g, uint32_t v) +{ + uint32_t i, n, nv = asg_arc_n(g, v); + const asg_arc_t *av = asg_arc_a(g, v); + + for (i = n = 0; i < nv; ++i) + if (!av[i].del) ++n; + return n; +} + + +void build_string_graph_without_clean( +int min_dp, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +uint64_t n_read, uint64_t* readLen, long long mini_overlap_length, +long long max_hang_length, long long clean_round, long long gap_fuzz, +float min_ovlp_drop_ratio, float max_ovlp_drop_ratio, char* output_file_name, +long long bubble_dist, int read_graph, int write); + +void debug_info_of_specfic_read(const char* name, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, int id, const char* command); +void collect_abnormal_edges(ma_hit_t_alloc* paf, ma_hit_t_alloc* rev_paf, long long readNum); +void add_overlaps(ma_hit_t_alloc* source_paf, ma_hit_t_alloc* dest_paf, uint64_t* source_index, long long listLen); +void remove_overlaps(ma_hit_t_alloc* source_paf, uint64_t* source_index, long long listLen); +void add_overlaps_from_different_sources(ma_hit_t_alloc* source_paf_list, ma_hit_t_alloc* dest_paf, +uint64_t* source_index, long long listLen); + +#define EvaluateLen(U, id) ((U).a[(id)].start) +#define IsMerge(U, id) ((U).a[(id)].end) +#define kv_reuse(v, rn, rm, r) ((v).n = (rn), (v).m = (rm), (v).a = (r)) +#define Get_vis(visit, v, d) (((visit)[(v)>>1])&(((((v)<<(d))&1)+1))) +#define Set_vis(visit, v, d) (((visit)[(v)>>1])|=(((((v)<<(d))&1)+1))) + + + + + +typedef struct { + uint64_t len; + uint32_t* index; + uint8_t* is_het; +} R_to_U; + +void init_R_to_U(R_to_U* x, uint64_t len); +void destory_R_to_U(R_to_U* x); +void set_R_to_U(R_to_U* x, uint32_t rID, uint32_t uID, uint32_t is_Unitig, uint8_t* flag); +void get_R_to_U(R_to_U* x, uint32_t rID, uint32_t* uID, uint32_t* is_Unitig); +void transfor_R_to_U(R_to_U* x); +void debug_utg_graph(ma_ug_t *ug, asg_t* read_g, kvec_asg_arc_t_warp* edge, int require_equal_nv, int test_tangle); +long long asg_arc_del_simple_circle_untig(ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, asg_t *g, long long circleLen, int is_drop); + +typedef struct { + asg_t* g; + + asg_arc_t *av; + uint32_t nv; + uint32_t av_i; + + asg_arc_t* new_edges; + uint32_t new_edges_n; + uint32_t new_edges_i; +} Edge_iter; + +typedef struct { + asg_arc_t x; + uint64_t Off; + uint64_t weight; +}asg_arc_t_offset; + +typedef struct { + kvec_t(asg_arc_t_offset) a; + uint64_t i; +}kvec_asg_arc_t_offset; + + + +void init_Edge_iter(asg_t* g, uint32_t v, asg_arc_t* new_edges, uint32_t new_edges_n, Edge_iter* x); +int get_arc_t(Edge_iter* x, asg_arc_t* get); + + +inline int get_real_length(asg_t *g, uint32_t v, uint32_t* v_s) +{ + uint32_t i, kv = 0; + for (i = 0, kv = 0; i < asg_arc_n(g, v); i++) + { + if(!asg_arc_a(g, v)[i].del) + { + if(v_s) v_s[kv] = asg_arc_a(g, v)[i].v; + kv++; + } + } + + return kv; +} + +inline uint32_t check_tip(asg_t *sg, uint32_t begNode, uint32_t* endNode, buf_t* b, uint32_t max_ext) +{ + ///cut tip of length <= max_ext + uint32_t v = begNode, w; + uint32_t kv; + uint32_t eLen = 0; + (*endNode) = (uint32_t)-1; + b->b.n = 0; + while (1) + { + kv = get_real_length(sg, v, NULL); + (*endNode) = v; + eLen++; + if(b) kv_push(uint32_t, b->b, v); + if(kv == 0) return END_TIPS; + if(kv > 1) return MUL_OUTPUT; + ///if(eLen > max_ext) return LONG_TIPS; + ///kv must be 1 here + kv = get_real_length(sg, v, &w); + ///here this value must be >= 1 + if(get_real_length(sg, w^1, NULL)!=1) return MUL_INPUT; + v = w; + if(v == begNode) return LOOP; + if(eLen >= max_ext) return LONG_TIPS; + } +} + +inline uint32_t get_unitig(asg_t *sg, ma_ug_t *ug, uint32_t begNode, uint32_t* endNode, +long long* nodeLen, long long* baseLen, long long* max_stop_nodeLen, long long* max_stop_baseLen, +uint32_t stops_threshold, buf_t* b) +{ + ma_utg_v* u = NULL; + uint32_t v = begNode, w, k; + uint32_t kv, return_flag, n_stops = 0; + long long pre_baseLen = 0, pre_nodeLen = 0; + long long cur_baseLen = 0, cur_nodeLen = 0; + (*max_stop_nodeLen) = (*max_stop_baseLen) = (*nodeLen) = (*baseLen) = 0; + (*endNode) = (uint32_t)-1; + if(ug!=NULL) u = &(ug->u); + + while (1) + { + kv = get_real_length(sg, v, NULL); + (*endNode) = v; + if(u == NULL) + { + (*nodeLen)++; + } + else + { + (*nodeLen) += EvaluateLen((*u), v>>1); + } + if(b) kv_push(uint32_t, b->b, v); + ///means reach the end of a unitig + if(kv!=1) (*baseLen) += sg->seq[v>>1].len; + if(kv==0) + { + return_flag = END_TIPS; + break; + ///return END_TIPS; + } + if(kv>1) + { + return_flag = MUL_OUTPUT; + break; + ///return MUL_OUTPUT; + } + ///kv must be 1 here + kv = get_real_length(sg, v, &w); + ///means reach the end of a unitig + if(get_real_length(sg, w^1, NULL)!=1) + { + + n_stops++; + if(n_stops >= stops_threshold) + { + (*baseLen) += sg->seq[v>>1].len; + return_flag = MUL_INPUT; + break; + ///return MUL_INPUT; + } + else + { + for (k = 0; k < asg_arc_n(sg, v); k++) + { + if(asg_arc_a(sg, v)[k].del) continue; + ///here is just one undeleted edge + (*baseLen) += asg_arc_len(asg_arc_a(sg, v)[k]); + break; + } + } + + cur_baseLen = (*baseLen) - pre_baseLen; + pre_baseLen = (*baseLen); + if(cur_baseLen > (*max_stop_baseLen)) + { + (*max_stop_baseLen) = cur_baseLen; + } + + + cur_nodeLen = (*nodeLen) - pre_nodeLen; + pre_nodeLen = (*nodeLen); + if(cur_nodeLen > (*max_stop_nodeLen)) + { + (*max_stop_nodeLen) = cur_nodeLen; + } + } + else + { + for (k = 0; k < asg_arc_n(sg, v); k++) + { + if(asg_arc_a(sg, v)[k].del) continue; + ///here is just one undeleted edge + (*baseLen) += asg_arc_len(asg_arc_a(sg, v)[k]); + break; + } + } + + + v = w; + if(v == begNode) + { + return_flag = LOOP; + break; + ///return LOOP; + } + } + + + + + cur_baseLen = (*baseLen) - pre_baseLen; + pre_baseLen = (*baseLen); + if(cur_baseLen > (*max_stop_baseLen)) + { + (*max_stop_baseLen) = cur_baseLen; + } + + + cur_nodeLen = (*nodeLen) - pre_nodeLen; + pre_nodeLen = (*nodeLen); + if(cur_nodeLen > (*max_stop_nodeLen)) + { + (*max_stop_nodeLen) = cur_nodeLen; + } + + return return_flag; +} + +#define UNAVAILABLE (uint32_t)-1 +#define PLOID 0 +#define NON_PLOID 1 +// #define DIFF_HAP_RATE 0.75 +#define TRIO_DROP_THRES 0.9 +#define TRIO_DROP_LENGTH_THRES 0.8 +#define MAX_STOP_RATE 0.6 +#define TANGLE_MISSED_THRES 0.6 +#define HET_HOM_RATE 0.7 + +typedef struct { + uint32_t father_occ; + uint32_t mother_occ; + uint32_t ambig_occ; + uint32_t drop_occ; + uint32_t total; +} Trio_counter; + +typedef struct { + uint32_t p; // the optimal parent vertex + uint32_t d; // the shortest distance from the initial vertex + uint32_t r:31, s:1; // r: the number of remaining incoming arc; s: state +} binfo_s_t; + +typedef struct { + ///all information for each node + binfo_s_t *a; + kvec_t(uint32_t) S; // set of vertices without parents, nodes with all incoming edges visited + kvec_t(uint32_t) b; // visited vertices + kvec_t(uint32_t) e; // visited edges/arcs +} buf_s_t; + +typedef struct{ + buf_s_t *b; + uint32_t n_thres, n_reads; + asg_t *g; + uint32_t check_cross; + uint64_t bub_dist; +} bub_label_t; + +void resolve_tangles(ma_ug_t *src, asg_t *read_g, ma_hit_t_alloc* reverse_sources, long long minLongUntig, +long long maxShortUntig, float l_untig_rate, float max_node_threshold, R_to_U* ruIndex, uint8_t* is_r_het, +uint32_t trio_flag, float drop_ratio); +void adjust_utg_advance(asg_t *sg, ma_ug_t *ug, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, bub_label_t* b_mask_t, uint8_t* is_r_het); +void rescue_contained_reads_aggressive(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t chainLenThres, uint32_t is_bubble_check, +uint32_t is_primary_check, kvec_asg_arc_t_warp* new_rtg_edges, kvec_t_u32_warp* new_rtg_nodes, bub_label_t* b_mask_t); +void rescue_missing_overlaps_aggressive(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t is_bubble_check, uint32_t is_primary_check, kvec_asg_arc_t_warp* new_rtg_edges, bub_label_t* b_mask_t); +void all_to_all_deduplicate(ma_ug_t* ug, asg_t* read_g, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, uint8_t postive_flag, float drop_rate, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, uint8_t* is_r_het, float double_check_rate, int non_tig_occ); +void drop_semi_circle(ma_ug_t *ug, asg_t* nsg, asg_t* read_g, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, uint8_t* is_r_het); +void rescue_wrong_overlaps_to_unitigs(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +ma_sub_t *coverage_cut, R_to_U* ruIndex, int max_hang, int min_ovlp, long long bubble_dist, kvec_asg_arc_t_warp* keep_edges, bub_label_t* b_mask_t); +void get_unitig_trio_flag(ma_utg_t* nsu, uint32_t flag, uint32_t* require, uint32_t* non_require, uint32_t* ambigious); +void rescue_missing_overlaps_backward(ma_ug_t *i_ug, asg_t *r_g, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t backward_steps, uint32_t is_bubble_check, uint32_t is_primary_check, bub_label_t* b_mask_t); +uint32_t get_edge_from_source(ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t query, uint32_t target, asg_arc_t* t); +int unitig_arc_del_short_diploid_by_length(asg_t *g, float drop_ratio); +void asg_bub_backtrack_primary(asg_t *g, uint32_t v0, buf_t *b); +void set_hom_global_coverage(hifiasm_opt_t *opt, asg_t *sg, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, int max_hang, int min_ovlp); +void rescue_bubble_by_chain(asg_t *sg, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, +float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, uint32_t chainLenThres, long long gap_fuzz, +bub_label_t* b_mask_t, long long no_trio_recover, uint8_t *cmk); + +typedef struct{ + double weight; + uint32_t uID; + uint64_t dis; + uint8_t is_cc:7, del:1; + uint64_t occ; + ///uint64_t occ:63, scaff:1; + ///uint32_t enzyme; +} hc_edge; + +typedef struct{ + kvec_t(hc_edge) e; + kvec_t(hc_edge) f;//forbiden +} hc_linkeage; + +typedef struct{ + uint64_t beg, end; +}bed_interval; + +typedef struct{ + size_t n, m; + bed_interval* a; +}bed_in; + +typedef struct{ + kvec_t(hc_linkeage) a; + kvec_t(uint64_t) enzymes; +} hc_links; + +#define N_HET 0 +#define C_HET 1 +#define P_HET 2 +#define S_HET 4 + +typedef struct { + uint32_t p_x_p, p_y_p, p_x, p_y; + uint32_t c_x_p, c_y_p; + uint8_t c_rev; +} ca_buf_t; + +typedef struct { + size_t n, m; + ca_buf_t* a; +} kv_ca_buf_t; + +typedef struct { + kvec_t(uint32_t) uIDs; + kvec_t(uint32_t) iDXs; + uint32_t chain_num; +} sub_tran_t; + +typedef struct{ + uint32_t* rUidx; + uint64_t* rUpos; + uint8_t* ir_het; + uint32_t r_num, u_num; + kvec_t(bed_in) bed; + kvec_t(uint32_t) topo_buf; + kvec_t(uint32_t) topo_res; + buf_t b_buf_0, b_buf_1; + ///uint32_t* uLen; + kv_u_trans_t k_trans; + kv_u_trans_hit_t k_t_b; + kv_ca_buf_t c_buf; + sub_tran_t st; +}trans_chain; + +typedef struct { + uint32_t n; + uint32_t* cov; + uint64_t* pos_idx; + ma_hit_t_alloc* reverse_sources; + ma_sub_t *coverage_cut; + R_to_U* ruIndex; + asg_t *read_g; + int max_hang; + int min_ovlp; + kvec_asg_arc_t_offset u_buffer; + kvec_t_i32_warp tailIndex; + kvec_t_i32_warp prevIndex; + uint8_t* is_r_het; + trans_chain* t_ch; +}hap_cov_t; + +typedef struct{ + ///kvec_t(hc_edge) a; + size_t n, m; + hc_edge *a; +}hc_edge_warp; + +typedef struct { + uint32_t qs, qe, qn, qus, que; + uint32_t ts, te, tn, tus, tue; +} utg_thit_t; + +typedef struct { + size_t n, m; + utg_thit_t* a; +} kv_utg_thit_t_t; + +typedef struct { + ma_hit_t_alloc* reverse_sources; + ma_sub_t *coverage_cut; + R_to_U* ruIndex; + asg_t *read_g; + kvec_asg_arc_t_offset u_buffer; + kvec_t_i32_warp tailIndex; + kvec_t_i32_warp prevIndex; + kv_utg_thit_t_t k_t_b; + kv_ca_buf_t c_buf; + kv_u_trans_t k_trans; + uint64_t *pos_idx, rn; + kvec_t(uint32_t) topo_res; + ma_ug_t *cug; + int max_hang; + int min_ovlp; + + ma_utg_v u; + kv_u_trans_t t; + buf_t b0, b1; +} utg_trans_t; + +typedef struct { + ma_ug_t *ug; + kvec_t(uint64_t) idx; + kvec_t(uint32_t) dst; +} spg_t; + +void init_hc_links(hc_links* link, uint64_t ug_num, trans_chain* t_ch); +void destory_hc_links(hc_links* link); +uint64_t get_bub_pop_max_dist(asg_t *g, buf_t *b); +uint64_t get_bub_pop_max_dist_advance(asg_t *g, buf_t *b); +uint64_t asg_bub_pop1_primary_trio(asg_t *g, ma_ug_t *utg, uint32_t v0, uint64_t max_dist, buf_t *b, uint32_t positive_flag, +uint32_t negative_flag, uint32_t is_pop, uint64_t* path_base_len, uint64_t* path_nodes, hap_cov_t *cov, uint32_t is_update_chain, uint32_t keep_d, utg_trans_t *o); + +void adjust_utg_by_primary(ma_ug_t **ug, asg_t* read_g, float drop_rate, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, +R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, +kvec_asg_arc_t_warp* new_rtg_edges, hap_cov_t **i_cov, bub_label_t* b_mask_t, uint32_t collect_p_trans, uint32_t collect_p_trans_f); +ma_ug_t* copy_untig_graph(ma_ug_t *src); +ma_ug_t* output_trio_unitig_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +uint8_t flag, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, +float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, int gap_fuzz, int is_bench, bub_label_t* b_mask_t, char *f_prefix, uint8_t *kpt_buf, kvec_asg_arc_t_warp *r_edges); +asg_t* copy_read_graph(asg_t *src); +ma_ug_t *ma_ug_gen(asg_t *g); +void ma_ug_destroy(ma_ug_t *ug); + +inline int inter_interval(int a_s, int a_e, int b_s, int b_e, int* i_s, int* i_e) +{ + if(a_s > b_e || b_s > a_e) return 0; + if(i_s) (*i_s) = a_s >= b_s? a_s : b_s; ///MAX(a_s, b_s); + if(i_e) (*i_e) = a_e <= b_e? a_e : b_e; ///MIN(a_e, b_e); + return 1; +} + +inline uint32_t get_origin_uid(uint32_t v, trans_chain* t_ch, uint32_t *off, uint32_t *idx) +{ + if(off) (*off) = (t_ch->rUpos[v>>1]>>32); + if(idx) (*idx) = (uint32_t)(t_ch->rUpos[v>>1]); + if(t_ch->rUpos[v>>1] == (uint64_t)-1) return (uint32_t)-1; + return (uint32_t)(((t_ch->rUidx[v>>1]>>1)<<1) + ((t_ch->rUidx[v>>1]^v)&1)); +} +void chain_origin_trans_uid_by_distance(hap_cov_t *cov, asg_t *read_sg, +uint32_t *pri_a, uint32_t pri_n, uint32_t pri_beg, uint64_t *i_pri_len, +uint32_t *aux_a, uint32_t aux_n, uint32_t aux_beg, uint64_t *i_aux_len, +ma_ug_t *ug, uint32_t flag, double overall_score, const char* cmd); +int asg_arc_del_trans(asg_t *g, int fuzz); +void kt_u_trans_t_idx(kv_u_trans_t *ta, uint32_t n); +void kt_u_trans_t_simple_symm(kv_u_trans_t *ta, uint32_t un, uint32_t symm_add); +uint32_t get_u_trans_spec(kv_u_trans_t *ta, uint32_t qn, uint32_t tn, u_trans_t **r_a, uint32_t *occ); +int ma_ug_seq(ma_ug_t *g, asg_t *read_g, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, +kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, kvec_asg_arc_t_warp *E, uint32_t is_polish); + + +typedef struct{ + ma_sub_t* coverage_cut; + ma_hit_t_alloc* sources; + ma_hit_t_alloc* reverse_sources; + long long tipsLen; + float tip_drop_ratio; + long long stops_threshold; + R_to_U* ruIndex; + float chimeric_rate; + float drop_ratio; + int max_hang; + int min_ovlp; + int is_bench; + long long gap_fuzz; + int64_t min_dp; + bub_label_t* b_mask_t; + uint64_t* readLen; + telo_end_t *te; +}ug_opt_t; + +typedef struct{ + ma_hit_t_alloc **src; + ma_hit_t_alloc **r_src; + long long *n_read; + uint64_t **readLen; + asg_t **sg; + R_to_U *ruIndex; + ma_sub_t **cov; + bub_label_t *b_mask_t; + int64_t max_hang; + int64_t mini_ovlp; +}ul_renew_t; + +void adjust_utg_by_trio(ma_ug_t **ug, asg_t* read_g, uint8_t flag, float drop_rate, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, +R_to_U* ruIndex, float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp, +int gap_fuzz, kvec_asg_arc_t_warp* new_rtg_edges, bub_label_t* b_mask_t); +uint32_t cmp_untig_graph(ma_ug_t *src, ma_ug_t *dest); +void reduce_hamming_error(asg_t *sg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +int max_hang, int min_ovlp, long long gap_fuzz); +int ma_ug_seq_scaffold(ma_ug_t *g, asg_t *read_g, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, +kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, kvec_asg_arc_t_warp *E, uint32_t is_polish); +void ma_ug_print(const ma_ug_t *ug, asg_t* read_g, const ma_sub_t *coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex, const char* prefix, FILE *fp); +void ma_ug_print_simple(const ma_ug_t *ug, asg_t* read_g, const ma_sub_t *coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex, const char* prefix, FILE *fp); +trans_chain* init_trans_chain(ma_ug_t *ug, uint64_t r_num); +void destory_trans_chain(trans_chain **x); + +typedef struct {///[cBeg, cEnd) + uint32_t u_i, r_i, len, s_pos_cur, s_pre_v, s_pre_w, p_v, p_idx, p_uId, cBeg, cEnd; + ///buf_t* x; + uint32_t *a, an; + ma_ug_t *ug; + asg_t *read_sg; + trans_chain* t_ch; +} u_trans_hit_idx; +void reset_u_trans_hit_idx(u_trans_hit_idx *t, uint32_t* i_x_a, uint32_t i_x_n, ma_ug_t *i_ug, +asg_t *i_read_sg, trans_chain* i_t_ch, uint32_t i_cBeg, uint32_t i_cEnd); +uint32_t get_u_trans_hit(u_trans_hit_idx *t, u_trans_hit_t *hit); +inline uint32_t get_offset_adjust(uint32_t offset, uint32_t offsetLen, uint32_t targetLen) +{ + return ((double)(offset)/(double)(offsetLen))*targetLen; +} + +uint32_t set_utg_offset(uint32_t *a, uint32_t a_n, ma_ug_t *ug, asg_t *read_sg, uint64_t* pos_idx, uint32_t is_clear, +uint32_t only_len); +uint64_t get_utg_cov(ma_ug_t *ug, uint32_t uID, asg_t* read_g, +const ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag); +trans_chain* load_hc_trans(const char *fn); +char *get_outfile_name(char* output_file_name); +void reset_u_trans_hit_idx(u_trans_hit_idx *t, uint32_t* i_x_a, uint32_t i_x_n, ma_ug_t *i_ug, +asg_t *i_read_sg, trans_chain* i_t_ch, uint32_t i_cBeg, uint32_t i_cEnd); +void extract_sub_overlaps(uint32_t i_tScur, uint32_t i_tEcur, uint32_t i_tSpre, uint32_t i_tEpre, +uint32_t tn, kv_u_trans_hit_t* ktb, uint32_t bn); +void clean_u_trans_t_idx(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g); +void clean_u_trans_t_idx_adv(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g); +void clean_u_trans_t_idx_filter_adv(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, double sc_sec_rate, uint64_t uniform_only); +uint32_t test_dbug(ma_ug_t* ug, FILE* fp); +void write_dbug(ma_ug_t* ug, FILE* fp); +int asg_arc_identify_simple_bubbles_multi(asg_t *g, bub_label_t* x, int check_cross); +uint8_t get_tip_trio_infor(asg_t *sg, uint32_t begNode); +int asg_topocut_aux(asg_t *g, uint32_t v, int max_ext); +int asg_topocut_aux_pg(asg_t *g, uint32_t v, int max_ext, uint32_t *rv); +int asg_arc_del_triangular_directly(asg_t *g, long long min_edge_length, +ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex); +int asg_arc_del_short_diploid_by_exact(asg_t *g, int max_ext, ma_hit_t_alloc* sources); +uint32_t print_debug_gfa(asg_t *read_g, ma_ug_t *ug, ma_sub_t* coverage_cut, const char* output_file_name, +ma_hit_t_alloc* sources, R_to_U* ruIndex, int max_hang, int min_ovlp, int is_update_ou, int is_check_alter_lable, int is_seq); +void debug_info_of_specfic_node(const char* name, asg_t *g, R_to_U* ruIndex, const char* command); +ma_ug_t *gen_polished_ug(const ug_opt_t *uopt, asg_t *sg); +void output_unitig_graph(asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, R_to_U* ruIndex, int max_hang, int min_ovlp); +void flat_soma_v(asg_t *sg, ma_hit_t_alloc* sources, R_to_U* ruIndex); +void hic_clean(asg_t* read_g); +int64_t count_edges_v_w(asg_t *g, uint32_t v, uint32_t w); +void renew_utg(ma_ug_t **ug, asg_t* read_g, kvec_asg_arc_t_warp* edge); +void merge_unitig_content(ma_utg_t* collection, ma_ug_t* ug, asg_t* read_g, kvec_asg_arc_t_warp* edge); +void reset_bub_label_t(bub_label_t* x, asg_t *g, uint64_t bub_dist, uint32_t check_cross); +void set_reverse_overlap(ma_hit_t* dest, ma_hit_t* source); +// void break_ug_contig(ma_ug_t **ug, asg_t *read_g, All_reads *RNF, ma_sub_t *coverage_cut, +// ma_hit_t_alloc* sources, R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, +// int* b_low_cov, int* b_high_cov, double m_rate); +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); +void hic_clean_adv(asg_t *sg, ug_opt_t *uopt); +void update_ug_ou(ma_ug_t *ug, asg_t *sg); +int asg_arc_del_trans_ul(asg_t *g, int fuzz); + +#define JUNK_COV 5 +#define DISCARD_RATE 0.8 + +typedef struct { + uint32_t n, m, a; +} mmhap_status_t; + +typedef struct { + kvec_t(mmhap_status_t) h; + kvec_t(uint32_t) a; +} mmhap_t; + +typedef struct { // global data structure for kt_pipeline() + ma_ug_t *ug; + asg_t *rg; + uint64_t *idx; + asg64_v cov; + uint64_t hom_min, hom_max, hom_cov, het_cov; +} ug_rid_cov_t; + +ug_rid_cov_t* gen_ug_rid_cov_t(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc *src); +void destory_ug_rid_cov_t(ug_rid_cov_t *p); +uint32_t append_cov_line_ug_rid_cov_t(uint64_t uid, uint64_t *qcc, u_trans_t *p, ug_rid_cov_t *idx, uint64_t hom_cut, double cut_rate); +uint64_t infer_mmhap_copy(ma_ug_t *ug, asg_t *sg, ma_hit_t_alloc *src, uint8_t *ff, uint64_t uid, uint64_t het_cov, uint64_t n_hap); +uint64_t trans_sec_cut0(kv_u_trans_t *ta, asg64_v *srt, uint32_t id, double sec_rate, uint64_t bd, ma_ug_t *ug); +void clean_u_trans_t_idx_filter_mmhap_adv(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* src, ug_rid_cov_t *in); +void gen_ug_rid_cov_t_by_ovlp(kv_u_trans_t *ta, ug_rid_cov_t *cc); +void rescue_chimeric_reads_aggressive(ma_ug_t *i_ug, asg_t *rg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp, uint32_t chainLenThres, uint32_t is_bubble_check, uint32_t is_primary_check, kvec_asg_arc_t_warp* new_rtg_edges, +kvec_t_u32_warp* new_rtg_nodes, bub_label_t* b_mask_t, uint8_t *cmk); + +#define UC_Read_resize(v, s) do {\ + if ((v).size<(s)) {REALLOC((v).seq,(s));(v).size=(s);}\ + } while (0) + +#endif diff --git a/POA.cpp b/POA.cpp index 1039cac..26d6600 100644 --- a/POA.cpp +++ b/POA.cpp @@ -1,359 +1,359 @@ -#include -#include -#include "POA.h" -#include "Correct.h" -#include "Process_Read.h" -#define INIT_EDGE_SIZE 50 -#define INCREASE_EDGE_SIZE 5 -#define INIT_NODE_SIZE 16000 - -/******** - * Edge * - ********/ - -void init_Edge_alloc(Edge_alloc* list) -{ - if (list->list == NULL) { - list->size = INIT_EDGE_SIZE; - list->length = 0; - list->delete_length = 0; - list->list = (Edge*)malloc(sizeof(Edge)*list->size); - } else { - list->length = 0; - list->delete_length = 0; - } -} - -void clear_Edge_alloc(Edge_alloc* list) -{ - list->length = 0; - list->delete_length = 0; -} - -void destory_Edge_alloc(Edge_alloc* list) -{ - if (list && list->list) - free(list->list); -} - -void append_Edge_alloc(Edge_alloc* list, uint64_t in_node, uint64_t out_node, uint64_t weight, uint64_t length) -{ - if (list->length + 1 > list->size) { - uint64_t old_size = list->size; - list->size = list->size + INCREASE_EDGE_SIZE; - list->list = (Edge*)realloc(list->list, sizeof(Edge)*list->size); - memset(&list->list[old_size], 0, (list->size - old_size) * sizeof(Edge)); - } - - list->list[list->length].in_node = in_node; - list->list[list->length].out_node = out_node; - list->list[list->length].weight = weight; - list->list[list->length].length = length; - list->list[list->length].num_insertions = 0; - list->list[list->length].self_edge_ID = list->length; - - list->length++; -} - -int add_and_check_bi_direction_edge(Graph* graph, Node* in_node, Node* out_node, uint64_t weight, uint64_t flag) -{ - Edge* e_forward; - Edge* e_backward; - - //if there are no edge from in_node to out_node - if(!get_bi_Edge(graph, in_node, out_node, &e_forward, &e_backward)) - { - append_Edge_alloc(&(Output_Edges((*in_node))), (*in_node).ID, (*out_node).ID, weight, flag); - append_Edge_alloc(&(Input_Edges((*out_node))), (*in_node).ID, (*out_node).ID, weight, flag); - - Output_Edges((*in_node)).list[Output_Edges((*in_node)).length - 1].reverse_edge_ID - = Input_Edges((*out_node)).length - 1; - - Input_Edges((*out_node)).list[Input_Edges((*out_node)).length - 1].reverse_edge_ID - = Output_Edges((*in_node)).length - 1; - - return 1; - } - else//if there is an edge from in_node to out_node, do nothing - { - return 0; - } -} - -void add_bi_direction_edge(Graph* graph, Node* in_node, Node* out_node, uint64_t weight, uint64_t flag) -{ - - append_Edge_alloc(&(Output_Edges((*in_node))), (*in_node).ID, (*out_node).ID, weight, flag); - append_Edge_alloc(&(Input_Edges((*out_node))), (*in_node).ID, (*out_node).ID, weight, flag); - - Output_Edges((*in_node)).list[Output_Edges((*in_node)).length - 1].reverse_edge_ID - = Input_Edges((*out_node)).length - 1; - - Input_Edges((*out_node)).list[Input_Edges((*out_node)).length - 1].reverse_edge_ID - = Output_Edges((*in_node)).length - 1; -} - -int remove_and_check_bi_direction_edge_from_nodes(Graph* graph, Node* in_node, Node* out_node) -{ - Edge* e_forward; - Edge* e_backward; - - //if there are no edge from in_node to out_node - //1. remove these two edges - //2. increase the edge_list.delete_length in both in_node and out_node - if(get_bi_Edge(graph, in_node, out_node, &e_forward, &e_backward)) - { - e_forward->in_node = (uint64_t)-1; - e_forward->out_node = (uint64_t)-1; - e_forward->weight = (uint64_t)-1; - e_forward->length = (uint64_t)-1; - e_forward->num_insertions = (uint64_t)-1; - e_forward->self_edge_ID = (uint64_t)-1; - e_forward->reverse_edge_ID = (uint64_t)-1; - - - e_backward->in_node = (uint64_t)-1; - e_backward->out_node = (uint64_t)-1; - e_backward->weight = (uint64_t)-1; - e_backward->length = (uint64_t)-1; - e_backward->num_insertions = (uint64_t)-1; - e_backward->self_edge_ID = (uint64_t)-1; - e_backward->reverse_edge_ID = (uint64_t)-1; - - Output_Edges(*in_node).delete_length++; - Input_Edges((*out_node)).delete_length++; - - return 1; - } - else//if there is an edge from in_node to out_node, do nothing - { - return 0; - } -} - -int remove_and_check_bi_direction_edge_from_edge(Graph* graph, Edge* e) -{ - Edge* e_forward; - Edge* e_backward; - - if(If_Edge_Exist(*e)) - { - get_bi_direction_edges(graph, e, &e_forward, &e_backward); - Output_Edges(G_Node(*graph, e_forward->in_node)).delete_length++; - Input_Edges(G_Node(*graph, e_forward->out_node)).delete_length++; - - e_forward->in_node = (uint64_t)-1; - e_forward->out_node = (uint64_t)-1; - e_forward->weight = (uint64_t)-1; - e_forward->length = (uint64_t)-1; - e_forward->num_insertions = (uint64_t)-1; - e_forward->self_edge_ID = (uint64_t)-1; - e_forward->reverse_edge_ID = (uint64_t)-1; - - - e_backward->in_node = (uint64_t)-1; - e_backward->out_node = (uint64_t)-1; - e_backward->weight = (uint64_t)-1; - e_backward->length = (uint64_t)-1; - e_backward->num_insertions = (uint64_t)-1; - e_backward->self_edge_ID = (uint64_t)-1; - e_backward->reverse_edge_ID = (uint64_t)-1; - - return 1; - } - else - { - return 0; - } -} - -/******** - * Node * - ********/ - -void init_Node_alloc(Node_alloc* list) -{ - memset(list, 0, sizeof(Node_alloc)); - list->size = INIT_NODE_SIZE; - list->list = (Node*)calloc(list->size, sizeof(Node)); -} - -void destory_Node_alloc(Node_alloc* list) -{ - uint64_t i; - for (i = 0; i < list->size; i++) { - destory_Edge_alloc(&list->list[i].deletion_edges); - destory_Edge_alloc(&list->list[i].insertion_edges); - destory_Edge_alloc(&list->list[i].mismatch_edges); - } - free(list->list); - free(list->sort.list); - free(list->sort.visit); - free(list->sort.iterative_buffer); - free(list->sort.iterative_buffer_visit); -} - -void clear_Node_alloc(Node_alloc* list) -{ - uint64_t i =0; - for (i = 0; i < list->length; i++) { // TODO: is this list->size or list->length? The original version is list->length. - clear_Edge_alloc(&list->list[i].insertion_edges); - clear_Edge_alloc(&list->list[i].mismatch_edges); - clear_Edge_alloc(&list->list[i].deletion_edges); - } - list->length = 0; - list->delete_length = 0; -} - -uint64_t append_Node_alloc(Node_alloc* list, char base) -{ - if (list->length + 1 > list->size) { - uint64_t old_size = list->size; - list->size = list->size * 2; - list->list = (Node*)realloc(list->list, sizeof(Node) * list->size); - memset(&list->list[old_size], 0, (list->size - old_size) * sizeof(Node)); - } - - list->list[list->length].ID = list->length; - list->list[list->length].base = base; - list->list[list->length].weight = 1; - list->list[list->length].num_insertions = 0; - init_Edge_alloc(&list->list[list->length].deletion_edges); - init_Edge_alloc(&list->list[list->length].insertion_edges); - init_Edge_alloc(&list->list[list->length].mismatch_edges); - - list->length++; - - return list->length - 1; -} - -/********* - * Graph * - *********/ - -void init_Graph(Graph* g) -{ - init_Node_alloc(&g->g_nodes); - g->g_n_edges = 0; - g->g_n_nodes = 0; - g->g_next_nodeID = 0; - g->s_end_nodeID = 0; - g->s_start_nodeID = 0; - g->seq = NULL; - g->seqID = (uint64_t)-1; - - init_Queue(&(g->node_q)); -} - -void destory_Graph(Graph* g) -{ - destory_Node_alloc(&g->g_nodes); - destory_Queue(&(g->node_q)); -} - -void clear_Graph(Graph* g) -{ - clear_Node_alloc(&g->g_nodes); - - g->g_n_edges = 0; - g->g_n_nodes = 0; - g->g_next_nodeID = 0; - g->s_end_nodeID = 0; - g->s_start_nodeID = 0; - g->seq = NULL; - g->seqID = (uint64_t)-1; - - clear_Queue(&(g->node_q)); -} - -void addUnmatchedSeqToGraph(Graph* g, char* g_read_seq, long long g_read_length, long long* startID, long long* endID) -{ - long long firstID, lastID, nodeID, i; - firstID = -1; - lastID = -1; - - if(g_read_length == 0) - return; - - ///start node - nodeID = add_Node_Graph(g, 'S'); - firstID = nodeID; - lastID = nodeID; - - - for (i = 0; i < g_read_length; i++) - { - nodeID = add_Node_Graph(g, g_read_seq[i]); - - if (firstID == -1) - { - firstID = nodeID; - } - if (lastID != -1) - { - ///the legnth of match edge is 0, while the length of musmatch is 1 - append_Edge_alloc(&(g->g_nodes.list[lastID].mismatch_edges), lastID, nodeID, 1, 0); - } - - lastID = nodeID; - } - - *startID = firstID; - *endID = lastID; - - g->s_start_nodeID = firstID; - g->s_end_nodeID = lastID; - -} - -void addmatchedSeqToGraph(Graph* backbone, long long currentNodeID, char* x_string, long long x_length, - char* y_string, long long y_length, window_list *cigar_idx, window_list_alloc *cigar_s, long long backbone_start, long long backbone_end) -{ - - int64_t x_i = 0, y_i = 0, c_i = 0, c_n = cigar_idx->clen; - uint32_t i, operLen; uint8_t oper; int8_t last_oper = -1; - // if(currentNodeID == 366 && x_length == 9 && y_length == 9) { - // fprintf(stderr, "[M::%s] currentNodeID::%lld, x_length::%lld, c_n::%ld, cidx::%u, cigar_s_n::%lld\n", __func__, - // currentNodeID, x_length, c_n, cigar_idx->cidx, (long long)cigar_s->c.n); - // } - - ///note that node 0 is the start node - ///0 is match, 1 is mismatch, 2 is up, 3 is left - ///2 mean y has more bases, while 3 means x has more bases - for (c_i = 0; c_i < c_n; c_i++) { - get_cigar_cell(cigar_idx, cigar_s, c_i, &oper, &operLen); - - // if(currentNodeID == 366 && x_length == 9 && y_length == 9) { - // fprintf(stderr, "[M::%s] c_i::%ld, oper::%u, operLen::%u, last_oper::%d\n", __func__, c_i, oper, operLen, last_oper); - // } - - if (oper == 0 || oper == 1) { ///match/mismatch - for (i = 0; i < operLen; i++) { - ///if the previous node is insertion, this node might be mismatch/match - add_mismatchEdge_weight(backbone, currentNodeID, y_string[y_i], last_oper); - x_i++; y_i++; currentNodeID++; - } - } else if (oper == 2) { ///insertion - ///the begin and end of cigar cannot be 2, so -1 is right here - ///if (operationLen <= CORRECT_INDEL_LENGTH) - { - add_insertionEdge_weight(backbone, currentNodeID, y_string + y_i, operLen); - backbone->g_nodes.list[currentNodeID].num_insertions++; - } - y_i += operLen; - } else if (oper == 3) { - ///3 means x has more bases, that means backbone has more bases - ///like a mismatch (-) - ///if (operationLen <= CORRECT_INDEL_LENGTH) - { - add_deletionEdge_weight(backbone, currentNodeID, operLen); - } - - - currentNodeID += operLen; - x_i += operLen; - } - - last_oper = oper; - } -} +#include +#include +#include "POA.h" +#include "Correct.h" +#include "Process_Read.h" +#define INIT_EDGE_SIZE 50 +#define INCREASE_EDGE_SIZE 5 +#define INIT_NODE_SIZE 16000 + +/******** + * Edge * + ********/ + +void init_Edge_alloc(Edge_alloc* list) +{ + if (list->list == NULL) { + list->size = INIT_EDGE_SIZE; + list->length = 0; + list->delete_length = 0; + list->list = (Edge*)malloc(sizeof(Edge)*list->size); + } else { + list->length = 0; + list->delete_length = 0; + } +} + +void clear_Edge_alloc(Edge_alloc* list) +{ + list->length = 0; + list->delete_length = 0; +} + +void destory_Edge_alloc(Edge_alloc* list) +{ + if (list && list->list) + free(list->list); +} + +void append_Edge_alloc(Edge_alloc* list, uint64_t in_node, uint64_t out_node, uint64_t weight, uint64_t length) +{ + if (list->length + 1 > list->size) { + uint64_t old_size = list->size; + list->size = list->size + INCREASE_EDGE_SIZE; + list->list = (Edge*)realloc(list->list, sizeof(Edge)*list->size); + memset(&list->list[old_size], 0, (list->size - old_size) * sizeof(Edge)); + } + + list->list[list->length].in_node = in_node; + list->list[list->length].out_node = out_node; + list->list[list->length].weight = weight; + list->list[list->length].length = length; + list->list[list->length].num_insertions = 0; + list->list[list->length].self_edge_ID = list->length; + + list->length++; +} + +int add_and_check_bi_direction_edge(Graph* graph, Node* in_node, Node* out_node, uint64_t weight, uint64_t flag) +{ + Edge* e_forward; + Edge* e_backward; + + //if there are no edge from in_node to out_node + if(!get_bi_Edge(graph, in_node, out_node, &e_forward, &e_backward)) + { + append_Edge_alloc(&(Output_Edges((*in_node))), (*in_node).ID, (*out_node).ID, weight, flag); + append_Edge_alloc(&(Input_Edges((*out_node))), (*in_node).ID, (*out_node).ID, weight, flag); + + Output_Edges((*in_node)).list[Output_Edges((*in_node)).length - 1].reverse_edge_ID + = Input_Edges((*out_node)).length - 1; + + Input_Edges((*out_node)).list[Input_Edges((*out_node)).length - 1].reverse_edge_ID + = Output_Edges((*in_node)).length - 1; + + return 1; + } + else//if there is an edge from in_node to out_node, do nothing + { + return 0; + } +} + +void add_bi_direction_edge(Graph* graph, Node* in_node, Node* out_node, uint64_t weight, uint64_t flag) +{ + + append_Edge_alloc(&(Output_Edges((*in_node))), (*in_node).ID, (*out_node).ID, weight, flag); + append_Edge_alloc(&(Input_Edges((*out_node))), (*in_node).ID, (*out_node).ID, weight, flag); + + Output_Edges((*in_node)).list[Output_Edges((*in_node)).length - 1].reverse_edge_ID + = Input_Edges((*out_node)).length - 1; + + Input_Edges((*out_node)).list[Input_Edges((*out_node)).length - 1].reverse_edge_ID + = Output_Edges((*in_node)).length - 1; +} + +int remove_and_check_bi_direction_edge_from_nodes(Graph* graph, Node* in_node, Node* out_node) +{ + Edge* e_forward; + Edge* e_backward; + + //if there are no edge from in_node to out_node + //1. remove these two edges + //2. increase the edge_list.delete_length in both in_node and out_node + if(get_bi_Edge(graph, in_node, out_node, &e_forward, &e_backward)) + { + e_forward->in_node = (uint64_t)-1; + e_forward->out_node = (uint64_t)-1; + e_forward->weight = (uint64_t)-1; + e_forward->length = (uint64_t)-1; + e_forward->num_insertions = (uint64_t)-1; + e_forward->self_edge_ID = (uint64_t)-1; + e_forward->reverse_edge_ID = (uint64_t)-1; + + + e_backward->in_node = (uint64_t)-1; + e_backward->out_node = (uint64_t)-1; + e_backward->weight = (uint64_t)-1; + e_backward->length = (uint64_t)-1; + e_backward->num_insertions = (uint64_t)-1; + e_backward->self_edge_ID = (uint64_t)-1; + e_backward->reverse_edge_ID = (uint64_t)-1; + + Output_Edges(*in_node).delete_length++; + Input_Edges((*out_node)).delete_length++; + + return 1; + } + else//if there is an edge from in_node to out_node, do nothing + { + return 0; + } +} + +int remove_and_check_bi_direction_edge_from_edge(Graph* graph, Edge* e) +{ + Edge* e_forward; + Edge* e_backward; + + if(If_Edge_Exist(*e)) + { + get_bi_direction_edges(graph, e, &e_forward, &e_backward); + Output_Edges(G_Node(*graph, e_forward->in_node)).delete_length++; + Input_Edges(G_Node(*graph, e_forward->out_node)).delete_length++; + + e_forward->in_node = (uint64_t)-1; + e_forward->out_node = (uint64_t)-1; + e_forward->weight = (uint64_t)-1; + e_forward->length = (uint64_t)-1; + e_forward->num_insertions = (uint64_t)-1; + e_forward->self_edge_ID = (uint64_t)-1; + e_forward->reverse_edge_ID = (uint64_t)-1; + + + e_backward->in_node = (uint64_t)-1; + e_backward->out_node = (uint64_t)-1; + e_backward->weight = (uint64_t)-1; + e_backward->length = (uint64_t)-1; + e_backward->num_insertions = (uint64_t)-1; + e_backward->self_edge_ID = (uint64_t)-1; + e_backward->reverse_edge_ID = (uint64_t)-1; + + return 1; + } + else + { + return 0; + } +} + +/******** + * Node * + ********/ + +void init_Node_alloc(Node_alloc* list) +{ + memset(list, 0, sizeof(Node_alloc)); + list->size = INIT_NODE_SIZE; + list->list = (Node*)calloc(list->size, sizeof(Node)); +} + +void destory_Node_alloc(Node_alloc* list) +{ + uint64_t i; + for (i = 0; i < list->size; i++) { + destory_Edge_alloc(&list->list[i].deletion_edges); + destory_Edge_alloc(&list->list[i].insertion_edges); + destory_Edge_alloc(&list->list[i].mismatch_edges); + } + free(list->list); + free(list->sort.list); + free(list->sort.visit); + free(list->sort.iterative_buffer); + free(list->sort.iterative_buffer_visit); +} + +void clear_Node_alloc(Node_alloc* list) +{ + uint64_t i =0; + for (i = 0; i < list->length; i++) { // TODO: is this list->size or list->length? The original version is list->length. + clear_Edge_alloc(&list->list[i].insertion_edges); + clear_Edge_alloc(&list->list[i].mismatch_edges); + clear_Edge_alloc(&list->list[i].deletion_edges); + } + list->length = 0; + list->delete_length = 0; +} + +uint64_t append_Node_alloc(Node_alloc* list, char base) +{ + if (list->length + 1 > list->size) { + uint64_t old_size = list->size; + list->size = list->size * 2; + list->list = (Node*)realloc(list->list, sizeof(Node) * list->size); + memset(&list->list[old_size], 0, (list->size - old_size) * sizeof(Node)); + } + + list->list[list->length].ID = list->length; + list->list[list->length].base = base; + list->list[list->length].weight = 1; + list->list[list->length].num_insertions = 0; + init_Edge_alloc(&list->list[list->length].deletion_edges); + init_Edge_alloc(&list->list[list->length].insertion_edges); + init_Edge_alloc(&list->list[list->length].mismatch_edges); + + list->length++; + + return list->length - 1; +} + +/********* + * Graph * + *********/ + +void init_Graph(Graph* g) +{ + init_Node_alloc(&g->g_nodes); + g->g_n_edges = 0; + g->g_n_nodes = 0; + g->g_next_nodeID = 0; + g->s_end_nodeID = 0; + g->s_start_nodeID = 0; + g->seq = NULL; + g->seqID = (uint64_t)-1; + + init_Queue(&(g->node_q)); +} + +void destory_Graph(Graph* g) +{ + destory_Node_alloc(&g->g_nodes); + destory_Queue(&(g->node_q)); +} + +void clear_Graph(Graph* g) +{ + clear_Node_alloc(&g->g_nodes); + + g->g_n_edges = 0; + g->g_n_nodes = 0; + g->g_next_nodeID = 0; + g->s_end_nodeID = 0; + g->s_start_nodeID = 0; + g->seq = NULL; + g->seqID = (uint64_t)-1; + + clear_Queue(&(g->node_q)); +} + +void addUnmatchedSeqToGraph(Graph* g, char* g_read_seq, long long g_read_length, long long* startID, long long* endID) +{ + long long firstID, lastID, nodeID, i; + firstID = -1; + lastID = -1; + + if(g_read_length == 0) + return; + + ///start node + nodeID = add_Node_Graph(g, 'S'); + firstID = nodeID; + lastID = nodeID; + + + for (i = 0; i < g_read_length; i++) + { + nodeID = add_Node_Graph(g, g_read_seq[i]); + + if (firstID == -1) + { + firstID = nodeID; + } + if (lastID != -1) + { + ///the legnth of match edge is 0, while the length of musmatch is 1 + append_Edge_alloc(&(g->g_nodes.list[lastID].mismatch_edges), lastID, nodeID, 1, 0); + } + + lastID = nodeID; + } + + *startID = firstID; + *endID = lastID; + + g->s_start_nodeID = firstID; + g->s_end_nodeID = lastID; + +} + +void addmatchedSeqToGraph(Graph* backbone, long long currentNodeID, char* x_string, long long x_length, + char* y_string, long long y_length, window_list *cigar_idx, window_list_alloc *cigar_s, long long backbone_start, long long backbone_end) +{ + + int64_t x_i = 0, y_i = 0, c_i = 0, c_n = cigar_idx->clen; + uint32_t i, operLen; uint8_t oper; int8_t last_oper = -1; + // if(currentNodeID == 366 && x_length == 9 && y_length == 9) { + // fprintf(stderr, "[M::%s] currentNodeID::%lld, x_length::%lld, c_n::%ld, cidx::%u, cigar_s_n::%lld\n", __func__, + // currentNodeID, x_length, c_n, cigar_idx->cidx, (long long)cigar_s->c.n); + // } + + ///note that node 0 is the start node + ///0 is match, 1 is mismatch, 2 is up, 3 is left + ///2 mean y has more bases, while 3 means x has more bases + for (c_i = 0; c_i < c_n; c_i++) { + get_cigar_cell(cigar_idx, cigar_s, c_i, &oper, &operLen); + + // if(currentNodeID == 366 && x_length == 9 && y_length == 9) { + // fprintf(stderr, "[M::%s] c_i::%ld, oper::%u, operLen::%u, last_oper::%d\n", __func__, c_i, oper, operLen, last_oper); + // } + + if (oper == 0 || oper == 1) { ///match/mismatch + for (i = 0; i < operLen; i++) { + ///if the previous node is insertion, this node might be mismatch/match + add_mismatchEdge_weight(backbone, currentNodeID, y_string[y_i], last_oper); + x_i++; y_i++; currentNodeID++; + } + } else if (oper == 2) { ///insertion + ///the begin and end of cigar cannot be 2, so -1 is right here + ///if (operationLen <= CORRECT_INDEL_LENGTH) + { + add_insertionEdge_weight(backbone, currentNodeID, y_string + y_i, operLen); + backbone->g_nodes.list[currentNodeID].num_insertions++; + } + y_i += operLen; + } else if (oper == 3) { + ///3 means x has more bases, that means backbone has more bases + ///like a mismatch (-) + ///if (operationLen <= CORRECT_INDEL_LENGTH) + { + add_deletionEdge_weight(backbone, currentNodeID, operLen); + } + + + currentNodeID += operLen; + x_i += operLen; + } + + last_oper = oper; + } +} diff --git a/POA.h b/POA.h index a19ed1c..f75b32a 100644 --- a/POA.h +++ b/POA.h @@ -1,773 +1,773 @@ -#ifndef __POA_PARSER__ -#define __POA_PARSER__ - -#define __STDC_LIMIT_MACROS -#include -#include "Hash_Table.h" -#include "Process_Read.h" - -typedef struct -{ - long long beg; - ///end is the index of next input data, instead of the index of last data - long long end; - long long length; - long long size; - long long* buffer; -} Queue; - -inline void init_Queue(Queue* q) -{ - q->beg = 0; - q->end = 0; - q->length = 0; - q->size = 20; - q->buffer = (long long*)malloc(sizeof(long long)*q->size); -} - -inline void clear_Queue(Queue* q) -{ - q->beg = 0; - q->end = 0; - q->length = 0; -} - -inline void destory_Queue(Queue* q) -{ - free(q->buffer); -} - -inline int is_empty_Queue(Queue* q) -{ - ///end is the index of next input data, instead of the index of last data - if(q->beg == q->end) - { - return 1; - } - else - { - return 0; - } -} - -inline int is_full_Queue(Queue* q) -{ - ///end is the index of next input data, instead of the index of last data - if(q->end < q->size) - { - return 0; - } - else - { - return 1; - } -} - -inline void push_to_Queue(Queue* q, long long nodeID) -{ - if(is_full_Queue(q)) - { - long long move_length = q->beg; - ///end is the index of next input data, instead of the index of last data - long long current_length = q->end - q->beg; - ///recalloc directly - if(move_length == 0) - { - q->size = q->size * 2; - q->buffer = (long long*)realloc(q->buffer, q->size*sizeof(long long)); - } - else - { - ///won't overlap - if(current_length <= move_length) - { - memcpy(q->buffer, q->buffer+q->beg, sizeof(long long)*current_length); - } - else///may overlap - { - memmove(q->buffer, q->buffer+q->beg, sizeof(long long)*current_length); - } - - q->beg = 0; - q->end = current_length; - } - } - - - q->buffer[q->end] = nodeID; - q->end++; -} - -inline int pop_from_Queue(Queue* q, long long* nodeID) -{ - if(is_empty_Queue(q)) - { - (*nodeID) = -1; - return 0; - } - else - { - (*nodeID) = q->buffer[q->beg]; - q->beg++; - - return 1; - } -} - - - - - -typedef struct -{ - uint64_t in_node; - uint64_t out_node; - ///0 is match,1 is mismatch,2 means y has more bases, 3 means x has more bases - uint64_t weight; - uint64_t num_insertions; - uint64_t length; - uint64_t self_edge_ID; - uint64_t reverse_edge_ID; -} Edge; - -typedef struct -{ - Edge* list; - uint64_t size; - uint64_t length; - uint64_t delete_length; -} Edge_alloc; - -#define Real_Length(X) ((X).length - (X).delete_length) -#define Input_Edges(Node) ((Node).insertion_edges) -#define Output_Edges(Node) ((Node).deletion_edges) -#define G_Node(G, Node) ((G).g_nodes.list[(Node)]) -#define If_Node_Exist(Node) ((Node).base != 'D') -#define If_Edge_Exist(E) ((E).out_node != (uint64_t)-1) -#define Visit(E) (E).length - -typedef struct -{ - long long index; -} RSet; - -inline void clear_RSet(RSet* set) -{ - set->index = 0; -} - -typedef struct -{ - uint64_t ID; - uint64_t weight; - ///number of deletion end with current node - uint64_t num_insertions; - char base; - Edge_alloc mismatch_edges; - Edge_alloc deletion_edges; - Edge_alloc insertion_edges; - -} Node; - -typedef struct -{ - uint64_t* list; - uint8_t* visit; - uint64_t size; - uint64_t length; - - uint64_t* iterative_buffer; - uint8_t* iterative_buffer_visit; - uint64_t iterative_i; -} topo_Sorting_buffer; - -typedef struct -{ - ///has a indivial start node 0 - Node* list; - topo_Sorting_buffer sort; - uint64_t size; - uint64_t length; - uint64_t delete_length; -} Node_alloc; - -typedef struct -{ - uint64_t g_n_nodes; - uint64_t g_n_edges; - uint64_t g_next_nodeID; - Node_alloc g_nodes; - - - Queue node_q; - char* seq; - uint64_t seqID; - uint64_t s_start_nodeID; - uint64_t s_end_nodeID; -} Graph; - -int add_and_check_bi_direction_edge(Graph* graph, Node* in_node, Node* out_node, uint64_t weight, uint64_t flag); -void add_bi_direction_edge(Graph* graph, Node* in_node, Node* out_node, uint64_t weight, uint64_t flag); -int remove_and_check_bi_direction_edge_from_nodes(Graph* graph, Node* in_node, Node* out_node); -int remove_and_check_bi_direction_edge_from_edge(Graph* graph, Edge* e); - - - -inline int Pop_Node(Graph* DAGCon, Node** node) -{ - long long nodeID = 0; - int return_flag = pop_from_Queue(&(DAGCon->node_q), &nodeID); - - (*node) = &(G_Node(*DAGCon, nodeID)); - return return_flag; -} - -inline int Push_Node(Graph* DAGCon, Node** node) -{ - push_to_Queue(&(DAGCon->node_q), (**node).ID); - - return 1; -} - -inline int getInputNodes(RSet* set, Graph* graph, Node* node, Node** get_Node) -{ - if(set->index >= (long long)Input_Edges(*node).length) - { - return 0; - } - - ///skip all deleted edges - while ( - set->index < (long long)Input_Edges(*node).length - && - !(If_Edge_Exist(Input_Edges(*node).list[set->index])) - ) - { - set->index++; - } - - - if( - set->index < (long long)Input_Edges(*node).length - && - If_Edge_Exist(Input_Edges(*node).list[set->index]) - ) - { - (*get_Node) = &(G_Node((*graph), Input_Edges(*node).list[set->index].in_node)); - set->index++; - return 1; - } - else - { - return 0; - } -} - - - -inline int getInputEdges(RSet* set, Graph* graph, Node* node, Edge** get_Edge) -{ - if(set->index >= (long long)Input_Edges(*node).length) - { - return 0; - } - - ///skip all deleted edges - while ( - set->index < (long long)Input_Edges(*node).length - && - !(If_Edge_Exist(Input_Edges(*node).list[set->index])) - ) - { - set->index++; - } - - - if( - set->index < (long long)Input_Edges(*node).length - && - If_Edge_Exist(Input_Edges(*node).list[set->index]) - ) - { - (*get_Edge) = &(Input_Edges(*node).list[set->index]); - set->index++; - return 1; - } - else - { - return 0; - } -} - - -inline int getOutputNodes(RSet* set, Graph* graph, Node* node, Node** get_Node) -{ - if(set->index >= (long long)Output_Edges(*node).length) - { - return 0; - } - - ///skip all deleted edges - while ( - set->index < (long long)Output_Edges(*node).length - && - !(If_Edge_Exist(Output_Edges(*node).list[set->index])) - ) - { - set->index++; - } - - if(set->index < (long long)Output_Edges(*node).length && - If_Edge_Exist(Output_Edges(*node).list[set->index])) - { - (*get_Node) = &(G_Node((*graph), Output_Edges(*node).list[set->index].out_node)); - set->index++; - return 1; - } - else - { - return 0; - } -} - - - -inline int getOutputEdges(RSet* set, Graph* graph, Node* node, Edge** get_Edge) -{ - if(set->index >= (long long)Output_Edges(*node).length) - { - return 0; - } - - ///skip all deleted edges - while ( - set->index < (long long)Output_Edges(*node).length - && - !(If_Edge_Exist(Output_Edges(*node).list[set->index])) - ) - { - set->index++; - } - - if(set->index < (long long)Output_Edges(*node).length && - If_Edge_Exist(Output_Edges(*node).list[set->index])) - { - (*get_Edge) = &(Output_Edges(*node).list[set->index]); - set->index++; - return 1; - } - else - { - return 0; - } -} - - -inline void get_bi_direction_edges(Graph* DAGCon, Edge* edge, Edge** e_forward, Edge** e_backward) -{ - long long in_node = edge->in_node; - long long out_node = edge->out_node; - - if( - edge->self_edge_ID < Output_Edges(G_Node(*DAGCon, in_node)).length - && - (long long)Output_Edges(G_Node(*DAGCon, in_node)).list[edge->self_edge_ID].in_node == in_node - && - (long long)Output_Edges(G_Node(*DAGCon, in_node)).list[edge->self_edge_ID].out_node == out_node - ) - { - (*e_forward) = &(Output_Edges(G_Node(*DAGCon, in_node)).list[edge->self_edge_ID]); - (*e_backward) = &(Input_Edges(G_Node(*DAGCon, out_node)).list[edge->reverse_edge_ID]); - } - else - { - (*e_forward) = &(Output_Edges(G_Node(*DAGCon, in_node)).list[edge->reverse_edge_ID]); - (*e_backward) = &(Input_Edges(G_Node(*DAGCon, out_node)).list[edge->self_edge_ID]); - } -} - - -inline long long get_bi_Edge(Graph* DAGCon, Node* inNode, Node* outNode, Edge** e_forward, Edge** e_backward) -{ - Edge* e; - RSet iter; - clear_RSet(&iter); - - if(If_Node_Exist(*inNode) && If_Node_Exist(*outNode)) - { - //find in-edge of outNode - while(getInputEdges(&iter, DAGCon, outNode, &e)) - { - if(e->in_node == inNode->ID) - { - get_bi_direction_edges(DAGCon, e, e_forward, e_backward); - return 1; - } - } - } - - return 0; -} - - -inline long long get_Edge_Weight(Graph* DAGCon, Node* inNode, Node* outNode) -{ - Edge* e_forward = NULL; - Edge* e_backward = NULL; - get_bi_Edge(DAGCon, inNode, outNode, &e_forward, &e_backward); - return e_forward->weight; -} - -void init_Edge_alloc(Edge_alloc* list); -void clear_Edge_alloc(Edge_alloc* list); -void destory_Edge_alloc(Edge_alloc* list); -void append_Edge_alloc(Edge_alloc* list, uint64_t in_node, uint64_t out_node, uint64_t weight, uint64_t length); - -void init_Node_alloc(Node_alloc* list); -void destory_Node_alloc(Node_alloc* list); -void clear_Node_alloc(Node_alloc* list); -uint64_t append_Node_alloc(Node_alloc* list, char base); -uint64_t* get_Topo_Sort_Order(Node_alloc* list, int need_sort); - - -void init_Graph(Graph* g); -void addUnmatchedSeqToGraph(Graph* g, char* g_read_seq, long long g_read_length, long long* startID, long long* endID); -void addmatchedSeqToGraph(Graph* backbone, long long currentNodeID, char* x_string, long long x_length, - char* y_string, long long y_length, window_list *cigar_idx, window_list_alloc *cigar_s, long long backbone_start, long long backbone_end); -void destory_Graph(Graph* g); -void clear_Graph(Graph* g); -void Perform_POA(Graph* g, overlap_region_alloc* overlap_list, All_reads* R_INF, UC_Read* g_read); - - - -uint64_t inline add_Node_Graph(Graph* g, char base) -{ - return append_Node_alloc(&g->g_nodes, base); -} - -inline Node* add_Node_DAGCon(Graph* g, char base) -{ - return &(G_Node(*g, append_Node_alloc(&g->g_nodes, base))); -} - -///to delete a node -///1. set the corresponding base to be 'D' -///2. remove all related edges -///2. clear all related edges -///3. g_nodes.delete_length++, please do not substract g_nodes.length -uint64_t inline delete_Node_DAGCon(Graph* g, Node* node) -{ - g->g_nodes.delete_length++; - g->g_nodes.list[(*node).ID].base = 'D'; - g->g_nodes.list[(*node).ID].num_insertions = (uint64_t)-1; - g->g_nodes.list[(*node).ID].weight = (uint64_t)-1; - - - RSet iter; - Edge* e; - clear_RSet(&iter); - while (getOutputEdges(&iter, g, node, &e)) - { - remove_and_check_bi_direction_edge_from_edge(g, e); - } - - clear_RSet(&iter); - while (getInputEdges(&iter, g, node, &e)) - { - remove_and_check_bi_direction_edge_from_edge(g, e); - } - - - - clear_Edge_alloc(&(g->g_nodes.list[(*node).ID].insertion_edges)); - clear_Edge_alloc(&(g->g_nodes.list[(*node).ID].mismatch_edges)); - clear_Edge_alloc(&(g->g_nodes.list[(*node).ID].deletion_edges)); - - return 1; -} - - - - - -///just for mimatch edges -inline void add_mismatchEdge_weight(Graph* g, uint64_t in_node, char base, int last_operation) -{ - long long i = 0; - long long nodeID; - Edge_alloc* edge = &(g->g_nodes.list[in_node].mismatch_edges); - - for (i = 0; i < (long long)edge->length; i++) - { - nodeID = edge->list[i].out_node; - if(g->g_nodes.list[nodeID].base == base) - { - edge->list[i].weight++; - ///if last operation is insertion - if (last_operation == 2) - { - edge->list[i].num_insertions++; - } - - break; - } - } - - ///there are no such edge - if (i == (long long)edge->length) - { - nodeID = add_Node_Graph(g, base); - - ///the length of match edge is 0, while the length of mismatch edge is 1 - append_Edge_alloc(edge, in_node, nodeID, 1, 1); - ///if last operation is insertion - if (last_operation == 2) - { - edge->list[edge->length - 1].num_insertions++; - } - - ///add the mismatch_edges of new node to the backbone - append_Edge_alloc(&(g->g_nodes.list[nodeID].mismatch_edges), nodeID, in_node + 1, 1, 0); - } -} - - - -inline void add_single_deletionEdge_weight(Graph* g, long long alignNodeID, long long nextNodeID, uint64_t edge_length) -{ - long long i = 0; - long long nodeID; - Edge_alloc* edge = &(g->g_nodes.list[alignNodeID].deletion_edges); - - for (i = 0; i < (long long)edge->length; i++) - { - nodeID = edge->list[i].out_node; - if(nodeID == nextNodeID) - { - edge->list[i].weight++; - break; - } - } - - ///there are no such edge - if (i == (long long)edge->length) - { - append_Edge_alloc(edge, alignNodeID, nextNodeID, 1, edge_length); - } -} - -inline void add_deletionEdge_weight(Graph* g, long long alignNodeID, long long deletion_length) -{ - long long i; - for (i = 0; i < deletion_length; i++) - { - add_single_deletionEdge_weight(g, alignNodeID + i, alignNodeID + i + 1, 0); - } - -} - - -inline int getEdge(Graph* g, Edge_alloc* edge, uint64_t edge_length, char base) -{ - long long i = 0; - long long nodeID; - - for (i = 0; i < (long long)edge->length; i++) - { - if (edge->list[i].length == edge_length) - { - nodeID = edge->list[i].out_node; - if(g->g_nodes.list[nodeID].base == base) - { - return i; - } - } - } - - return -1; -} - - -inline int get_insertion_Edges(Graph* g, Edge_alloc* edge, uint64_t edge_length, char* bases) -{ - long long i = 0; - long long nodeID; - long long edgeID; - - if (edge_length < 1) - { - return -1; - } - - - edgeID = getEdge(g, edge, edge_length, bases[0]); - - long long return_edgeID = edgeID; - - if(edgeID == -1) - { - return -1; - } - - - Edge_alloc* new_edge = edge; - - for (i = 1; i < (long long)edge_length; i++) - { - nodeID = new_edge->list[edgeID].out_node; - new_edge = &(g->g_nodes.list[nodeID].insertion_edges); - edgeID = getEdge(g, new_edge, edge_length - i, bases[i]); - if(edgeID == -1) - { - return -1; - } - } - /****************************may have bugs********************************/ - return return_edgeID; - /****************************may have bugs********************************/ -} - - - -inline int create_insertion_Edges(Graph* g, long long alignNodeID, uint64_t edge_length, char* bases) -{ - long long i = 0; - long long nodeID; - ///should link back to the intial node - ///long long backboneID = alignNodeID + 1; - long long backboneID = alignNodeID; - - - if (edge_length < 1) - { - return -1; - } - - - nodeID = add_Node_Graph(g, bases[0]); - ///add the new node to alignNodeID by insertion_edges - append_Edge_alloc(&(g->g_nodes.list[alignNodeID].insertion_edges), alignNodeID, nodeID, 1, edge_length); - - alignNodeID = nodeID; - - for (i = 1; i < (long long)edge_length; i++) - { - nodeID = add_Node_Graph(g, bases[i]); - ///add the new node to alignNodeID by insertion_edges - append_Edge_alloc(&(g->g_nodes.list[alignNodeID].insertion_edges), alignNodeID, nodeID, 1, edge_length - i); - alignNodeID = nodeID; - } - - append_Edge_alloc(&(g->g_nodes.list[alignNodeID].insertion_edges), alignNodeID, backboneID, 1, 0); - - return 1; -} - - -inline void extract_path(Graph* backbone, int debug_node_in_backbone, int path_i, char* pre) -{ - int step = G_Node(*backbone, debug_node_in_backbone).insertion_edges.list[path_i].length; - int string_i = 0, preNode = 0, j = 0; - if(step != 0) - { - string_i = 0; - preNode = G_Node(*backbone, debug_node_in_backbone).insertion_edges.list[path_i].out_node; - - for (j = 0; j < step; j++) - { - pre[string_i++] = G_Node(*backbone, preNode).base; - preNode = G_Node(*backbone, preNode).insertion_edges.list[0].out_node; - } - } - - pre[string_i] = '\0'; -} - - - -inline int get_insertion_Edges_new(Graph* backbone, int debug_node_in_backbone, uint64_t edge_length, char* bases) -{ - int path_i, j, step, preNode; - - for (path_i = 0; path_i < (long long)G_Node(*backbone, debug_node_in_backbone).insertion_edges.length; path_i++) - { - step = G_Node(*backbone, debug_node_in_backbone).insertion_edges.list[path_i].length; - - - if(step != (long long)edge_length) - { - continue; - } - - - if(step != 0) - { - preNode = G_Node(*backbone, debug_node_in_backbone).insertion_edges.list[path_i].out_node; - - for (j = 0; j < step; j++) - { - if(G_Node(*backbone, preNode).base != bases[j]) - { - break; - } - - preNode = G_Node(*backbone, preNode).insertion_edges.list[0].out_node; - } - - if(j == step) - { - return path_i; - } - } - } - - - return -1; -} - - - - -inline void add_insertionEdge_weight(Graph* g, long long alignNodeID, char* insert, long long insert_length) -{ - - long long nodeID; - long long edgeID; - Edge_alloc* edge = &(g->g_nodes.list[alignNodeID].insertion_edges); - - if (insert_length == 1) - { - edgeID = getEdge(g, edge, 1, insert[0]); - if (edgeID != -1) - { - edge->list[edgeID].weight++; - } - else ///there is no such edge - { - nodeID = add_Node_Graph(g, insert[0]); - append_Edge_alloc(edge, alignNodeID, nodeID, 1, 1); - ///add the new node to alignNodeID by insertion_edges - //should link to the initial node, instead of the next node of the initial node - ///append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID + 1, 1, 0); - append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID, 1, 0); - } - } - else - { - ///edgeID = get_insertion_Edges(g, edge, insert_length, insert); - edgeID = get_insertion_Edges_new(g, alignNodeID, insert_length, insert); - if (edgeID != -1) - { - ///just one outdegree - edge->list[edgeID].weight++; - } - else - { - create_insertion_Edges(g, alignNodeID, insert_length, insert); - } - } -} - - - +#ifndef __POA_PARSER__ +#define __POA_PARSER__ + +#define __STDC_LIMIT_MACROS +#include +#include "Hash_Table.h" +#include "Process_Read.h" + +typedef struct +{ + long long beg; + ///end is the index of next input data, instead of the index of last data + long long end; + long long length; + long long size; + long long* buffer; +} Queue; + +inline void init_Queue(Queue* q) +{ + q->beg = 0; + q->end = 0; + q->length = 0; + q->size = 20; + q->buffer = (long long*)malloc(sizeof(long long)*q->size); +} + +inline void clear_Queue(Queue* q) +{ + q->beg = 0; + q->end = 0; + q->length = 0; +} + +inline void destory_Queue(Queue* q) +{ + free(q->buffer); +} + +inline int is_empty_Queue(Queue* q) +{ + ///end is the index of next input data, instead of the index of last data + if(q->beg == q->end) + { + return 1; + } + else + { + return 0; + } +} + +inline int is_full_Queue(Queue* q) +{ + ///end is the index of next input data, instead of the index of last data + if(q->end < q->size) + { + return 0; + } + else + { + return 1; + } +} + +inline void push_to_Queue(Queue* q, long long nodeID) +{ + if(is_full_Queue(q)) + { + long long move_length = q->beg; + ///end is the index of next input data, instead of the index of last data + long long current_length = q->end - q->beg; + ///recalloc directly + if(move_length == 0) + { + q->size = q->size * 2; + q->buffer = (long long*)realloc(q->buffer, q->size*sizeof(long long)); + } + else + { + ///won't overlap + if(current_length <= move_length) + { + memcpy(q->buffer, q->buffer+q->beg, sizeof(long long)*current_length); + } + else///may overlap + { + memmove(q->buffer, q->buffer+q->beg, sizeof(long long)*current_length); + } + + q->beg = 0; + q->end = current_length; + } + } + + + q->buffer[q->end] = nodeID; + q->end++; +} + +inline int pop_from_Queue(Queue* q, long long* nodeID) +{ + if(is_empty_Queue(q)) + { + (*nodeID) = -1; + return 0; + } + else + { + (*nodeID) = q->buffer[q->beg]; + q->beg++; + + return 1; + } +} + + + + + +typedef struct +{ + uint64_t in_node; + uint64_t out_node; + ///0 is match,1 is mismatch,2 means y has more bases, 3 means x has more bases + uint64_t weight; + uint64_t num_insertions; + uint64_t length; + uint64_t self_edge_ID; + uint64_t reverse_edge_ID; +} Edge; + +typedef struct +{ + Edge* list; + uint64_t size; + uint64_t length; + uint64_t delete_length; +} Edge_alloc; + +#define Real_Length(X) ((X).length - (X).delete_length) +#define Input_Edges(Node) ((Node).insertion_edges) +#define Output_Edges(Node) ((Node).deletion_edges) +#define G_Node(G, Node) ((G).g_nodes.list[(Node)]) +#define If_Node_Exist(Node) ((Node).base != 'D') +#define If_Edge_Exist(E) ((E).out_node != (uint64_t)-1) +#define Visit(E) (E).length + +typedef struct +{ + long long index; +} RSet; + +inline void clear_RSet(RSet* set) +{ + set->index = 0; +} + +typedef struct +{ + uint64_t ID; + uint64_t weight; + ///number of deletion end with current node + uint64_t num_insertions; + char base; + Edge_alloc mismatch_edges; + Edge_alloc deletion_edges; + Edge_alloc insertion_edges; + +} Node; + +typedef struct +{ + uint64_t* list; + uint8_t* visit; + uint64_t size; + uint64_t length; + + uint64_t* iterative_buffer; + uint8_t* iterative_buffer_visit; + uint64_t iterative_i; +} topo_Sorting_buffer; + +typedef struct +{ + ///has a indivial start node 0 + Node* list; + topo_Sorting_buffer sort; + uint64_t size; + uint64_t length; + uint64_t delete_length; +} Node_alloc; + +typedef struct +{ + uint64_t g_n_nodes; + uint64_t g_n_edges; + uint64_t g_next_nodeID; + Node_alloc g_nodes; + + + Queue node_q; + char* seq; + uint64_t seqID; + uint64_t s_start_nodeID; + uint64_t s_end_nodeID; +} Graph; + +int add_and_check_bi_direction_edge(Graph* graph, Node* in_node, Node* out_node, uint64_t weight, uint64_t flag); +void add_bi_direction_edge(Graph* graph, Node* in_node, Node* out_node, uint64_t weight, uint64_t flag); +int remove_and_check_bi_direction_edge_from_nodes(Graph* graph, Node* in_node, Node* out_node); +int remove_and_check_bi_direction_edge_from_edge(Graph* graph, Edge* e); + + + +inline int Pop_Node(Graph* DAGCon, Node** node) +{ + long long nodeID = 0; + int return_flag = pop_from_Queue(&(DAGCon->node_q), &nodeID); + + (*node) = &(G_Node(*DAGCon, nodeID)); + return return_flag; +} + +inline int Push_Node(Graph* DAGCon, Node** node) +{ + push_to_Queue(&(DAGCon->node_q), (**node).ID); + + return 1; +} + +inline int getInputNodes(RSet* set, Graph* graph, Node* node, Node** get_Node) +{ + if(set->index >= (long long)Input_Edges(*node).length) + { + return 0; + } + + ///skip all deleted edges + while ( + set->index < (long long)Input_Edges(*node).length + && + !(If_Edge_Exist(Input_Edges(*node).list[set->index])) + ) + { + set->index++; + } + + + if( + set->index < (long long)Input_Edges(*node).length + && + If_Edge_Exist(Input_Edges(*node).list[set->index]) + ) + { + (*get_Node) = &(G_Node((*graph), Input_Edges(*node).list[set->index].in_node)); + set->index++; + return 1; + } + else + { + return 0; + } +} + + + +inline int getInputEdges(RSet* set, Graph* graph, Node* node, Edge** get_Edge) +{ + if(set->index >= (long long)Input_Edges(*node).length) + { + return 0; + } + + ///skip all deleted edges + while ( + set->index < (long long)Input_Edges(*node).length + && + !(If_Edge_Exist(Input_Edges(*node).list[set->index])) + ) + { + set->index++; + } + + + if( + set->index < (long long)Input_Edges(*node).length + && + If_Edge_Exist(Input_Edges(*node).list[set->index]) + ) + { + (*get_Edge) = &(Input_Edges(*node).list[set->index]); + set->index++; + return 1; + } + else + { + return 0; + } +} + + +inline int getOutputNodes(RSet* set, Graph* graph, Node* node, Node** get_Node) +{ + if(set->index >= (long long)Output_Edges(*node).length) + { + return 0; + } + + ///skip all deleted edges + while ( + set->index < (long long)Output_Edges(*node).length + && + !(If_Edge_Exist(Output_Edges(*node).list[set->index])) + ) + { + set->index++; + } + + if(set->index < (long long)Output_Edges(*node).length && + If_Edge_Exist(Output_Edges(*node).list[set->index])) + { + (*get_Node) = &(G_Node((*graph), Output_Edges(*node).list[set->index].out_node)); + set->index++; + return 1; + } + else + { + return 0; + } +} + + + +inline int getOutputEdges(RSet* set, Graph* graph, Node* node, Edge** get_Edge) +{ + if(set->index >= (long long)Output_Edges(*node).length) + { + return 0; + } + + ///skip all deleted edges + while ( + set->index < (long long)Output_Edges(*node).length + && + !(If_Edge_Exist(Output_Edges(*node).list[set->index])) + ) + { + set->index++; + } + + if(set->index < (long long)Output_Edges(*node).length && + If_Edge_Exist(Output_Edges(*node).list[set->index])) + { + (*get_Edge) = &(Output_Edges(*node).list[set->index]); + set->index++; + return 1; + } + else + { + return 0; + } +} + + +inline void get_bi_direction_edges(Graph* DAGCon, Edge* edge, Edge** e_forward, Edge** e_backward) +{ + long long in_node = edge->in_node; + long long out_node = edge->out_node; + + if( + edge->self_edge_ID < Output_Edges(G_Node(*DAGCon, in_node)).length + && + (long long)Output_Edges(G_Node(*DAGCon, in_node)).list[edge->self_edge_ID].in_node == in_node + && + (long long)Output_Edges(G_Node(*DAGCon, in_node)).list[edge->self_edge_ID].out_node == out_node + ) + { + (*e_forward) = &(Output_Edges(G_Node(*DAGCon, in_node)).list[edge->self_edge_ID]); + (*e_backward) = &(Input_Edges(G_Node(*DAGCon, out_node)).list[edge->reverse_edge_ID]); + } + else + { + (*e_forward) = &(Output_Edges(G_Node(*DAGCon, in_node)).list[edge->reverse_edge_ID]); + (*e_backward) = &(Input_Edges(G_Node(*DAGCon, out_node)).list[edge->self_edge_ID]); + } +} + + +inline long long get_bi_Edge(Graph* DAGCon, Node* inNode, Node* outNode, Edge** e_forward, Edge** e_backward) +{ + Edge* e; + RSet iter; + clear_RSet(&iter); + + if(If_Node_Exist(*inNode) && If_Node_Exist(*outNode)) + { + //find in-edge of outNode + while(getInputEdges(&iter, DAGCon, outNode, &e)) + { + if(e->in_node == inNode->ID) + { + get_bi_direction_edges(DAGCon, e, e_forward, e_backward); + return 1; + } + } + } + + return 0; +} + + +inline long long get_Edge_Weight(Graph* DAGCon, Node* inNode, Node* outNode) +{ + Edge* e_forward = NULL; + Edge* e_backward = NULL; + get_bi_Edge(DAGCon, inNode, outNode, &e_forward, &e_backward); + return e_forward->weight; +} + +void init_Edge_alloc(Edge_alloc* list); +void clear_Edge_alloc(Edge_alloc* list); +void destory_Edge_alloc(Edge_alloc* list); +void append_Edge_alloc(Edge_alloc* list, uint64_t in_node, uint64_t out_node, uint64_t weight, uint64_t length); + +void init_Node_alloc(Node_alloc* list); +void destory_Node_alloc(Node_alloc* list); +void clear_Node_alloc(Node_alloc* list); +uint64_t append_Node_alloc(Node_alloc* list, char base); +uint64_t* get_Topo_Sort_Order(Node_alloc* list, int need_sort); + + +void init_Graph(Graph* g); +void addUnmatchedSeqToGraph(Graph* g, char* g_read_seq, long long g_read_length, long long* startID, long long* endID); +void addmatchedSeqToGraph(Graph* backbone, long long currentNodeID, char* x_string, long long x_length, + char* y_string, long long y_length, window_list *cigar_idx, window_list_alloc *cigar_s, long long backbone_start, long long backbone_end); +void destory_Graph(Graph* g); +void clear_Graph(Graph* g); +void Perform_POA(Graph* g, overlap_region_alloc* overlap_list, All_reads* R_INF, UC_Read* g_read); + + + +uint64_t inline add_Node_Graph(Graph* g, char base) +{ + return append_Node_alloc(&g->g_nodes, base); +} + +inline Node* add_Node_DAGCon(Graph* g, char base) +{ + return &(G_Node(*g, append_Node_alloc(&g->g_nodes, base))); +} + +///to delete a node +///1. set the corresponding base to be 'D' +///2. remove all related edges +///2. clear all related edges +///3. g_nodes.delete_length++, please do not substract g_nodes.length +uint64_t inline delete_Node_DAGCon(Graph* g, Node* node) +{ + g->g_nodes.delete_length++; + g->g_nodes.list[(*node).ID].base = 'D'; + g->g_nodes.list[(*node).ID].num_insertions = (uint64_t)-1; + g->g_nodes.list[(*node).ID].weight = (uint64_t)-1; + + + RSet iter; + Edge* e; + clear_RSet(&iter); + while (getOutputEdges(&iter, g, node, &e)) + { + remove_and_check_bi_direction_edge_from_edge(g, e); + } + + clear_RSet(&iter); + while (getInputEdges(&iter, g, node, &e)) + { + remove_and_check_bi_direction_edge_from_edge(g, e); + } + + + + clear_Edge_alloc(&(g->g_nodes.list[(*node).ID].insertion_edges)); + clear_Edge_alloc(&(g->g_nodes.list[(*node).ID].mismatch_edges)); + clear_Edge_alloc(&(g->g_nodes.list[(*node).ID].deletion_edges)); + + return 1; +} + + + + + +///just for mimatch edges +inline void add_mismatchEdge_weight(Graph* g, uint64_t in_node, char base, int last_operation) +{ + long long i = 0; + long long nodeID; + Edge_alloc* edge = &(g->g_nodes.list[in_node].mismatch_edges); + + for (i = 0; i < (long long)edge->length; i++) + { + nodeID = edge->list[i].out_node; + if(g->g_nodes.list[nodeID].base == base) + { + edge->list[i].weight++; + ///if last operation is insertion + if (last_operation == 2) + { + edge->list[i].num_insertions++; + } + + break; + } + } + + ///there are no such edge + if (i == (long long)edge->length) + { + nodeID = add_Node_Graph(g, base); + + ///the length of match edge is 0, while the length of mismatch edge is 1 + append_Edge_alloc(edge, in_node, nodeID, 1, 1); + ///if last operation is insertion + if (last_operation == 2) + { + edge->list[edge->length - 1].num_insertions++; + } + + ///add the mismatch_edges of new node to the backbone + append_Edge_alloc(&(g->g_nodes.list[nodeID].mismatch_edges), nodeID, in_node + 1, 1, 0); + } +} + + + +inline void add_single_deletionEdge_weight(Graph* g, long long alignNodeID, long long nextNodeID, uint64_t edge_length) +{ + long long i = 0; + long long nodeID; + Edge_alloc* edge = &(g->g_nodes.list[alignNodeID].deletion_edges); + + for (i = 0; i < (long long)edge->length; i++) + { + nodeID = edge->list[i].out_node; + if(nodeID == nextNodeID) + { + edge->list[i].weight++; + break; + } + } + + ///there are no such edge + if (i == (long long)edge->length) + { + append_Edge_alloc(edge, alignNodeID, nextNodeID, 1, edge_length); + } +} + +inline void add_deletionEdge_weight(Graph* g, long long alignNodeID, long long deletion_length) +{ + long long i; + for (i = 0; i < deletion_length; i++) + { + add_single_deletionEdge_weight(g, alignNodeID + i, alignNodeID + i + 1, 0); + } + +} + + +inline int getEdge(Graph* g, Edge_alloc* edge, uint64_t edge_length, char base) +{ + long long i = 0; + long long nodeID; + + for (i = 0; i < (long long)edge->length; i++) + { + if (edge->list[i].length == edge_length) + { + nodeID = edge->list[i].out_node; + if(g->g_nodes.list[nodeID].base == base) + { + return i; + } + } + } + + return -1; +} + + +inline int get_insertion_Edges(Graph* g, Edge_alloc* edge, uint64_t edge_length, char* bases) +{ + long long i = 0; + long long nodeID; + long long edgeID; + + if (edge_length < 1) + { + return -1; + } + + + edgeID = getEdge(g, edge, edge_length, bases[0]); + + long long return_edgeID = edgeID; + + if(edgeID == -1) + { + return -1; + } + + + Edge_alloc* new_edge = edge; + + for (i = 1; i < (long long)edge_length; i++) + { + nodeID = new_edge->list[edgeID].out_node; + new_edge = &(g->g_nodes.list[nodeID].insertion_edges); + edgeID = getEdge(g, new_edge, edge_length - i, bases[i]); + if(edgeID == -1) + { + return -1; + } + } + /****************************may have bugs********************************/ + return return_edgeID; + /****************************may have bugs********************************/ +} + + + +inline int create_insertion_Edges(Graph* g, long long alignNodeID, uint64_t edge_length, char* bases) +{ + long long i = 0; + long long nodeID; + ///should link back to the intial node + ///long long backboneID = alignNodeID + 1; + long long backboneID = alignNodeID; + + + if (edge_length < 1) + { + return -1; + } + + + nodeID = add_Node_Graph(g, bases[0]); + ///add the new node to alignNodeID by insertion_edges + append_Edge_alloc(&(g->g_nodes.list[alignNodeID].insertion_edges), alignNodeID, nodeID, 1, edge_length); + + alignNodeID = nodeID; + + for (i = 1; i < (long long)edge_length; i++) + { + nodeID = add_Node_Graph(g, bases[i]); + ///add the new node to alignNodeID by insertion_edges + append_Edge_alloc(&(g->g_nodes.list[alignNodeID].insertion_edges), alignNodeID, nodeID, 1, edge_length - i); + alignNodeID = nodeID; + } + + append_Edge_alloc(&(g->g_nodes.list[alignNodeID].insertion_edges), alignNodeID, backboneID, 1, 0); + + return 1; +} + + +inline void extract_path(Graph* backbone, int debug_node_in_backbone, int path_i, char* pre) +{ + int step = G_Node(*backbone, debug_node_in_backbone).insertion_edges.list[path_i].length; + int string_i = 0, preNode = 0, j = 0; + if(step != 0) + { + string_i = 0; + preNode = G_Node(*backbone, debug_node_in_backbone).insertion_edges.list[path_i].out_node; + + for (j = 0; j < step; j++) + { + pre[string_i++] = G_Node(*backbone, preNode).base; + preNode = G_Node(*backbone, preNode).insertion_edges.list[0].out_node; + } + } + + pre[string_i] = '\0'; +} + + + +inline int get_insertion_Edges_new(Graph* backbone, int debug_node_in_backbone, uint64_t edge_length, char* bases) +{ + int path_i, j, step, preNode; + + for (path_i = 0; path_i < (long long)G_Node(*backbone, debug_node_in_backbone).insertion_edges.length; path_i++) + { + step = G_Node(*backbone, debug_node_in_backbone).insertion_edges.list[path_i].length; + + + if(step != (long long)edge_length) + { + continue; + } + + + if(step != 0) + { + preNode = G_Node(*backbone, debug_node_in_backbone).insertion_edges.list[path_i].out_node; + + for (j = 0; j < step; j++) + { + if(G_Node(*backbone, preNode).base != bases[j]) + { + break; + } + + preNode = G_Node(*backbone, preNode).insertion_edges.list[0].out_node; + } + + if(j == step) + { + return path_i; + } + } + } + + + return -1; +} + + + + +inline void add_insertionEdge_weight(Graph* g, long long alignNodeID, char* insert, long long insert_length) +{ + + long long nodeID; + long long edgeID; + Edge_alloc* edge = &(g->g_nodes.list[alignNodeID].insertion_edges); + + if (insert_length == 1) + { + edgeID = getEdge(g, edge, 1, insert[0]); + if (edgeID != -1) + { + edge->list[edgeID].weight++; + } + else ///there is no such edge + { + nodeID = add_Node_Graph(g, insert[0]); + append_Edge_alloc(edge, alignNodeID, nodeID, 1, 1); + ///add the new node to alignNodeID by insertion_edges + //should link to the initial node, instead of the next node of the initial node + ///append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID + 1, 1, 0); + append_Edge_alloc(&(g->g_nodes.list[nodeID].insertion_edges), nodeID, alignNodeID, 1, 0); + } + } + else + { + ///edgeID = get_insertion_Edges(g, edge, insert_length, insert); + edgeID = get_insertion_Edges_new(g, alignNodeID, insert_length, insert); + if (edgeID != -1) + { + ///just one outdegree + edge->list[edgeID].weight++; + } + else + { + create_insertion_Edges(g, alignNodeID, insert_length, insert); + } + } +} + + + #endif \ No newline at end of file diff --git a/Process_Read.cpp b/Process_Read.cpp index c95b7cc..673e657 100644 --- a/Process_Read.cpp +++ b/Process_Read.cpp @@ -1,2233 +1,2252 @@ -#include -#include -#include -#include -#include "Process_Read.h" -#include "htab.h" -#include "Correct.h" -#include "kalloc.h" -#include - -#define UL_FLANK 512 -uint8_t seq_nt6_table[256] = { - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 0, 5, 1, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 0, 5, 1, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 -}; - -char bit_t_seq_table[256][4] = {{0}}; -char bit_t_seq_table_rc[256][4] = {{0}}; -char s_H[5] = {'A', 'C', 'G', 'T', 'N'}; -char rc_Table[6] = {'T', 'G', 'C', 'A', 'N', 'N'}; - -void init_All_reads(All_reads* r) -{ - memset(r, 0, sizeof(All_reads)); - r->index_size = READ_INIT_NUMBER; - r->read_length = (uint64_t*)malloc(sizeof(uint64_t)*r->index_size); - r->name_index_size = READ_INIT_NUMBER; - r->name_index = (uint64_t*)malloc(sizeof(uint64_t)*r->name_index_size); - r->name_index[0] = 0; -} - -void destory_All_reads(All_reads* r) -{ - uint64_t i = 0; - for (i = 0; i < r->total_reads; i++) { - if (r->N_site[i]) free(r->N_site[i]); - if (r->read_sperate[i]) free(r->read_sperate[i]); - if (r->paf && r->paf[i].buffer) free(r->paf[i].buffer); - if (r->reverse_paf && r->reverse_paf[i].buffer) free(r->reverse_paf[i].buffer); - if(r->rsc && r->rsc[i]) free(r->rsc[i]); - ///if (r->pb_regions) kv_destroy(r->pb_regions[i].a); - } - free(r->paf); - free(r->reverse_paf); - free(r->N_site); - free(r->read_sperate); - free(r->name); - free(r->name_index); - free(r->read_length); - free(r->trio_flag); - free(r->rsc); - ///if (r->pb_regions) free(r->pb_regions); -} - -void write_All_reads(All_reads* r, char* read_file_name) -{ - fprintf(stderr, "Writing reads to disk... \n"); - char* index_name = (char*)malloc(strlen(read_file_name)+15); - sprintf(index_name, "%s.bin", read_file_name); - FILE* fp = fopen(index_name, "w"); - fwrite(&asm_opt.adapterLen, sizeof(asm_opt.adapterLen), 1, fp); - fwrite(&r->index_size, sizeof(r->index_size), 1, fp); - fwrite(&r->name_index_size, sizeof(r->name_index_size), 1, fp); - fwrite(&r->total_reads, sizeof(r->total_reads), 1, fp); - fwrite(&r->total_reads_bases, sizeof(r->total_reads_bases), 1, fp); - fwrite(&r->total_name_length, sizeof(r->total_name_length), 1, fp); - - uint64_t i = 0; - uint64_t zero = 0; - for (i = 0; i < r->total_reads; i++) - { - if (r->N_site[i] != NULL) - { - ///number of Ns - fwrite(&r->N_site[i][0], sizeof(r->N_site[i][0]), 1, fp); - if (r->N_site[i][0]) - { - fwrite(r->N_site[i]+1, sizeof(r->N_site[i][0]), r->N_site[i][0], fp); - } - } - else - { - fwrite(&zero, sizeof(zero), 1, fp); - } - } - - fwrite(r->read_length, sizeof(uint64_t), r->total_reads, fp); - for (i = 0; i < r->total_reads; i++) - { - fwrite(r->read_sperate[i], sizeof(uint8_t), r->read_length[i]/4+1, fp); - } - - fwrite(r->name, sizeof(char), r->total_name_length, fp); - fwrite(r->name_index, sizeof(uint64_t), r->name_index_size, fp); - fwrite(r->trio_flag, sizeof(uint8_t), r->total_reads, fp); - fwrite(&(asm_opt.hom_cov), sizeof(asm_opt.hom_cov), 1, fp); - fwrite(&(asm_opt.het_cov), sizeof(asm_opt.het_cov), 1, fp); - - uint64_t mm = 1; - if(asm_opt.is_sc) { - fwrite(&mm, sizeof(mm), 1, fp); - for (i = 0; i < r->total_reads; i++) { - fwrite(r->rsc[i], sizeof(uint8_t), ((r->read_length[i]/sc_bn) + ((r->read_length[i]%sc_bn)?1:0)), fp); - } - } - - free(index_name); - fflush(fp); - fclose(fp); - fprintf(stderr, "Reads has been written.\n"); -} - -int load_All_reads(All_reads* r, char* read_file_name) -{ - char* index_name = (char*)malloc(strlen(read_file_name)+15); - sprintf(index_name, "%s.bin", read_file_name); - FILE* fp = fopen(index_name, "r"); - if (!fp) { - free(index_name); - return 0; - } - int local_adapterLen; - int f_flag; - f_flag = fread(&local_adapterLen, sizeof(local_adapterLen), 1, fp); - if(local_adapterLen != asm_opt.adapterLen) - { - fprintf(stderr, "the adapterLen of index is: %d, but the adapterLen set by user is: %d\n", - local_adapterLen, asm_opt.adapterLen); - exit(1); - } - f_flag += fread(&r->index_size, sizeof(r->index_size), 1, fp); - f_flag += fread(&r->name_index_size, sizeof(r->name_index_size), 1, fp); - f_flag += fread(&r->total_reads, sizeof(r->total_reads), 1, fp); - f_flag += fread(&r->total_reads_bases, sizeof(r->total_reads_bases), 1, fp); - f_flag += fread(&r->total_name_length, sizeof(r->total_name_length), 1, fp); - - uint64_t i = 0; - uint64_t zero = 0; - r->N_site = (uint64_t**)malloc(sizeof(uint64_t*)*r->total_reads); - for (i = 0; i < r->total_reads; i++) - { - f_flag += fread(&zero, sizeof(zero), 1, fp); - - if (zero) - { - r->N_site[i] = (uint64_t*)malloc(sizeof(uint64_t)*(zero + 1)); - r->N_site[i][0] = zero; - if (r->N_site[i][0]) - { - f_flag += fread(r->N_site[i]+1, sizeof(r->N_site[i][0]), r->N_site[i][0], fp); - } - } - else - { - r->N_site[i] = NULL; - } - } - - r->read_length = (uint64_t*)malloc(sizeof(uint64_t)*r->total_reads); - f_flag += fread(r->read_length, sizeof(uint64_t), r->total_reads, fp); - - r->read_size = (uint64_t*)malloc(sizeof(uint64_t)*r->total_reads); - memcpy (r->read_size, r->read_length, sizeof(uint64_t)*r->total_reads); - - r->read_sperate = (uint8_t**)malloc(sizeof(uint8_t*)*r->total_reads); - for (i = 0; i < r->total_reads; i++) - { - r->read_sperate[i] = (uint8_t*)malloc(sizeof(uint8_t)*(r->read_length[i]/4+1)); - f_flag += fread(r->read_sperate[i], sizeof(uint8_t), r->read_length[i]/4+1, fp); - } - - - r->name = (char*)malloc(sizeof(char)*r->total_name_length); - f_flag += fread(r->name, sizeof(char), r->total_name_length, fp); - - r->name_index = (uint64_t*)malloc(sizeof(uint64_t)*r->name_index_size); - f_flag += fread(r->name_index, sizeof(uint64_t), r->name_index_size, fp); - - /****************************may have bugs********************************/ - r->trio_flag = (uint8_t*)malloc(sizeof(uint8_t)*r->total_reads); - f_flag += fread(r->trio_flag, sizeof(uint8_t), r->total_reads, fp); - f_flag += fread(&(asm_opt.hom_cov), sizeof(asm_opt.hom_cov), 1, fp); - f_flag += fread(&(asm_opt.het_cov), sizeof(asm_opt.het_cov), 1, fp); - /****************************may have bugs********************************/ - - r->cigars = (Compressed_Cigar_record*)malloc(sizeof(Compressed_Cigar_record)*r->total_reads); - r->second_round_cigar = (Compressed_Cigar_record*)malloc(sizeof(Compressed_Cigar_record)*r->total_reads); - for (i = 0; i < r->total_reads; i++) - { - r->second_round_cigar[i].size = r->cigars[i].size = 0; - r->second_round_cigar[i].length = r->cigars[i].length = 0; - r->second_round_cigar[i].record = r->cigars[i].record = NULL; - - r->second_round_cigar[i].lost_base_size = r->cigars[i].lost_base_size = 0; - r->second_round_cigar[i].lost_base_length = r->cigars[i].lost_base_length = 0; - r->second_round_cigar[i].lost_base = r->cigars[i].lost_base = NULL; - } - ///r->pb_regions = NULL; - - uint64_t mm = 0; - if (!feof(fp)) { - if((fread(&mm, sizeof(mm), 1, fp)) && (mm == 1)) { - MALLOC(r->rsc, r->total_reads); - for (i = 0; i < r->total_reads; i++) { - MALLOC(r->rsc[i], (r->read_length[i]/sc_bn) + ((r->read_length[i]%sc_bn)?1:0)); - f_flag += fread(r->rsc[i], sizeof(uint8_t), (r->read_length[i]/sc_bn) + ((r->read_length[i]%sc_bn)?1:0), fp); - } - } - } - - - - free(index_name); - fclose(fp); - fprintf(stderr, "Reads has been loaded.\n"); - - return 1; -} - -void read_ma(ma_hit_t* x, FILE* fp) -{ - int f_flag; - f_flag = fread(&(x->qns), sizeof(x->qns), 1, fp); - f_flag += fread(&(x->qe), sizeof(x->qe), 1, fp); - f_flag += fread(&(x->tn), sizeof(x->tn), 1, fp); - f_flag += fread(&(x->ts), sizeof(x->ts), 1, fp); - f_flag += fread(&(x->te), sizeof(x->te), 1, fp); - f_flag += fread(&(x->el), sizeof(x->el), 1, fp); - f_flag += fread(&(x->no_l_indel), sizeof(x->no_l_indel), 1, fp); - - uint32_t t; - f_flag += fread(&(t), sizeof(t), 1, fp); - x->ml = t; - - f_flag += fread(&(t), sizeof(t), 1, fp); - x->rev = t; - - f_flag += fread(&(t), sizeof(t), 1, fp); - x->bl = t; - - f_flag += fread(&(t), sizeof(t), 1, fp); - x->del = t; -} - - -int append_All_reads(All_reads* r, char *idx, uint32_t id) -{ - char *gfa_name = NULL; MALLOC(gfa_name, (strlen(idx)+100)); - FILE *fp = NULL, *fpo = NULL; - - sprintf(gfa_name, "%s.ec%u.bin", idx, id); - fp = fopen(gfa_name, "r"); - if (!fp) {free(gfa_name); return 0;} - - sprintf(gfa_name, "%s.ovlp%u.source.bin", idx, id); - fpo = fopen(gfa_name, "r"); - if (!fpo) {free(gfa_name); fclose(fp); return 0;} - free(gfa_name); - - int local_adapterLen, f_flag; - f_flag = fread(&local_adapterLen, sizeof(local_adapterLen), 1, fp); - if(local_adapterLen != asm_opt.adapterLen) { - fprintf(stderr, "the adapterLen of index is: %d, but the adapterLen set by user is: %d\n", - local_adapterLen, asm_opt.adapterLen); - exit(1); - } - uint64_t index_size0, name_index_size0, total_reads0, total_reads_bases0, total_name_length0; - index_size0 = r->index_size; - total_reads0 = r->total_reads; - total_reads_bases0 = r->total_reads_bases; - total_name_length0 = r->total_name_length; - name_index_size0 = ((total_reads0)?(total_reads0+1):(0));///r->name_index_size; - - f_flag += fread(&r->index_size, sizeof(r->index_size), 1, fp); - f_flag += fread(&r->name_index_size, sizeof(r->name_index_size), 1, fp); - f_flag += fread(&r->total_reads, sizeof(r->total_reads), 1, fp); - f_flag += fread(&r->total_reads_bases, sizeof(r->total_reads_bases), 1, fp); - f_flag += fread(&r->total_name_length, sizeof(r->total_name_length), 1, fp); - - r->index_size += index_size0; - r->name_index_size += name_index_size0; if(name_index_size0) r->name_index_size--; - r->total_reads += total_reads0; - r->total_reads_bases += total_reads_bases0; - r->total_name_length += total_name_length0; - - - uint64_t i = 0, zero = 0, k; - REALLOC(r->N_site, r->total_reads); - - for (i = total_reads0; i < r->total_reads; i++) { - f_flag += fread(&zero, sizeof(zero), 1, fp); - - if (zero) { - r->N_site[i] = (uint64_t*)malloc(sizeof(uint64_t)*(zero + 1)); - r->N_site[i][0] = zero; - if (r->N_site[i][0]) { - f_flag += fread(r->N_site[i]+1, sizeof(r->N_site[i][0]), r->N_site[i][0], fp); - } - } else { - r->N_site[i] = NULL; - } - } - - REALLOC(r->read_length, r->total_reads); - f_flag += fread(r->read_length + total_reads0, sizeof(uint64_t), r->total_reads-total_reads0, fp); - - REALLOC(r->read_size, r->total_reads); - memcpy (r->read_size + total_reads0, r->read_length + total_reads0, sizeof(uint64_t)*(r->total_reads-total_reads0)); - - REALLOC(r->read_sperate, r->total_reads); - for (i = total_reads0; i < r->total_reads; i++) { - r->read_sperate[i] = (uint8_t*)malloc(sizeof(uint8_t)*(r->read_length[i]/4+1)); - f_flag += fread(r->read_sperate[i], sizeof(uint8_t), r->read_length[i]/4+1, fp); - } - - - REALLOC(r->name, r->total_name_length); - f_flag += fread(r->name + total_name_length0, sizeof(char), r->total_name_length - total_name_length0, fp); - - REALLOC(r->name_index, r->name_index_size); uint64_t sft = 0; - if(name_index_size0) sft = r->name_index[--name_index_size0]; - // fprintf(stderr, "name_index_size0::%lu, total_reads0::%lu, sft::%lu\n", name_index_size0, total_reads0, sft); - f_flag += fread(r->name_index + name_index_size0, sizeof(uint64_t), r->name_index_size-name_index_size0, fp); - if(sft) { - for (i = name_index_size0; i < r->name_index_size; i++) r->name_index[i] += sft; - } - - /****************************may have bugs********************************/ - REALLOC(r->trio_flag, r->total_reads); - f_flag += fread(r->trio_flag + total_reads0, sizeof(uint8_t), r->total_reads - total_reads0, fp); - - int hom_cov0 = asm_opt.hom_cov, het_cov0 = asm_opt.het_cov; - f_flag += fread(&(asm_opt.hom_cov), sizeof(asm_opt.hom_cov), 1, fp); asm_opt.hom_cov += hom_cov0; - f_flag += fread(&(asm_opt.het_cov), sizeof(asm_opt.het_cov), 1, fp); asm_opt.het_cov += het_cov0; - /****************************may have bugs********************************/ - - REALLOC(r->cigars, r->total_reads); - REALLOC(r->second_round_cigar, r->total_reads); - for (i = total_reads0; i < r->total_reads; i++) { - r->second_round_cigar[i].size = r->cigars[i].size = 0; - r->second_round_cigar[i].length = r->cigars[i].length = 0; - r->second_round_cigar[i].record = r->cigars[i].record = NULL; - - r->second_round_cigar[i].lost_base_size = r->cigars[i].lost_base_size = 0; - r->second_round_cigar[i].lost_base_length = r->cigars[i].lost_base_length = 0; - r->second_round_cigar[i].lost_base = r->cigars[i].lost_base = NULL; - } - ///r->pb_regions = NULL; - - REALLOC(r->paf, r->total_reads); - memset(r->paf+total_reads0, 0, sizeof((*(r->paf)))*(r->total_reads - total_reads0)); - long long n_read; f_flag = fread(&n_read, sizeof(n_read), 1, fpo); ma_hit_t t; - for (i = total_reads0; i < r->total_reads; i++) { - f_flag += fread(&(r->paf[i].is_fully_corrected), sizeof(r->paf[i].is_fully_corrected), 1, fpo); - f_flag += fread(&(r->paf[i].is_abnormal), sizeof(r->paf[i].is_abnormal), 1, fpo); - f_flag += fread(&(r->paf[i].length), sizeof(r->paf[i].length), 1, fpo); - - if(r->paf[i].length == 0) continue; - for (k = 0; k < r->paf[i].length; k++) read_ma(&t, fpo); - r->paf[i].length = 0; - } - - REALLOC(r->reverse_paf, r->total_reads); - memset(r->reverse_paf+total_reads0, 0, sizeof((*(r->reverse_paf)))*(r->total_reads - total_reads0)); - - fclose(fp); fclose(fpo); - fprintf(stderr, "Reads has been loaded.\n"); - return 1; -} - - -int destory_read_bin(All_reads* r) -{ - - uint64_t i = 0; - for (i = 0; i < r->total_reads; i++) - { - if (r->N_site[i]) free(r->N_site[i]); - if (r->read_sperate[i]) free(r->read_sperate[i]); - if (r->cigars[i].record) free(r->cigars[i].record); - if (r->cigars[i].lost_base) free(r->cigars[i].lost_base); - if (r->second_round_cigar[i].record) free(r->second_round_cigar[i].record); - if (r->second_round_cigar[i].lost_base) free(r->second_round_cigar[i].lost_base); - } - - free(r->N_site); - free(r->read_length); - free(r->read_size); - free(r->read_sperate); - free(r->name); - free(r->name_index); - free(r->trio_flag); - free(r->cigars); - free(r->second_round_cigar); - return 1; -} - - - -void ha_insert_read_len(All_reads *r, int read_len, int name_len) -{ - r->total_reads++; - r->total_reads_bases += (uint64_t)read_len; - r->total_name_length += (uint64_t)name_len; - - // must +1 - if (r->index_size < r->total_reads + 2) { - r->index_size = r->index_size * 2 + 2; - r->read_length = (uint64_t*)realloc(r->read_length, sizeof(uint64_t) * r->index_size); - r->name_index_size = r->name_index_size * 2 + 2; - r->name_index = (uint64_t*)realloc(r->name_index, sizeof(uint64_t) * r->name_index_size); - } - - r->read_length[r->total_reads - 1] = read_len; - r->name_index[r->total_reads] = r->name_index[r->total_reads - 1] + name_len; -} - -void malloc_All_reads(All_reads* r) -{ - r->read_size = (uint64_t*)malloc(sizeof(uint64_t)*r->total_reads); - memcpy(r->read_size, r->read_length, sizeof(uint64_t)*r->total_reads); - - r->read_sperate = (uint8_t**)malloc(sizeof(uint8_t*)*r->total_reads); - if(asm_opt.is_sc) MALLOC(r->rsc, r->total_reads); - - long long i = 0; - for (i = 0; i < (long long)r->total_reads; i++) - { - r->read_sperate[i] = (uint8_t*)malloc(sizeof(uint8_t)*(r->read_length[i]/4+1)); - if(r->rsc) MALLOC(r->rsc[i], (r->read_length[i]/sc_bn) + ((r->read_length[i]%sc_bn)?1:0)); - } - - r->cigars = (Compressed_Cigar_record*)malloc(sizeof(Compressed_Cigar_record)*r->total_reads); - r->second_round_cigar = (Compressed_Cigar_record*)malloc(sizeof(Compressed_Cigar_record)*r->total_reads); - r->paf = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*r->total_reads); - r->reverse_paf = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*r->total_reads); - ///r->pb_regions = (kvec_t_u64_warp*)malloc(r->total_reads*sizeof(kvec_t_u64_warp)); - - for (i = 0; i < (long long)r->total_reads; i++) - { - r->second_round_cigar[i].size = r->cigars[i].size = 0; - r->second_round_cigar[i].length = r->cigars[i].length = 0; - r->second_round_cigar[i].record = r->cigars[i].record = NULL; - - r->second_round_cigar[i].lost_base_size = r->cigars[i].lost_base_size = 0; - r->second_round_cigar[i].lost_base_length = r->cigars[i].lost_base_length = 0; - r->second_round_cigar[i].lost_base = r->cigars[i].lost_base = NULL; - init_ma_hit_t_alloc(&(r->paf[i])); - init_ma_hit_t_alloc(&(r->reverse_paf[i])); - ///kv_init(r->pb_regions[i].a); - } - - r->name = (char*)malloc(sizeof(char)*r->total_name_length); - r->N_site = (uint64_t**)calloc(r->total_reads, sizeof(uint64_t*)); - r->trio_flag = (uint8_t*)malloc(r->total_reads*sizeof(uint8_t)); - memset(r->trio_flag, AMBIGU, r->total_reads*sizeof(uint8_t)); -} - -void destory_UC_Read(UC_Read* r) -{ - free(r->seq); -} - -void init_aux_table() -{ - if (bit_t_seq_table[0][0] == 0) - { - uint64_t i = 0; - - for (i = 0; i < 256; i++) - { - bit_t_seq_table[i][0] = s_H[((i >> 6)&(uint64_t)3)]; - bit_t_seq_table[i][1] = s_H[((i >> 4)&(uint64_t)3)]; - bit_t_seq_table[i][2] = s_H[((i >> 2)&(uint64_t)3)]; - bit_t_seq_table[i][3] = s_H[(i&(uint64_t)3)]; - - bit_t_seq_table_rc[i][0] = RC_CHAR(bit_t_seq_table[i][3]); - bit_t_seq_table_rc[i][1] = RC_CHAR(bit_t_seq_table[i][2]); - bit_t_seq_table_rc[i][2] = RC_CHAR(bit_t_seq_table[i][1]); - bit_t_seq_table_rc[i][3] = RC_CHAR(bit_t_seq_table[i][0]); - } - } -} - -void init_UC_Read(UC_Read* r) -{ - r->length = 0; - r->size = 0; - r->seq = NULL; - if (bit_t_seq_table[0][0] == 0) - { - uint64_t i = 0; - - for (i = 0; i < 256; i++) - { - bit_t_seq_table[i][0] = s_H[((i >> 6)&(uint64_t)3)]; - bit_t_seq_table[i][1] = s_H[((i >> 4)&(uint64_t)3)]; - bit_t_seq_table[i][2] = s_H[((i >> 2)&(uint64_t)3)]; - bit_t_seq_table[i][3] = s_H[(i&(uint64_t)3)]; - - bit_t_seq_table_rc[i][0] = RC_CHAR(bit_t_seq_table[i][3]); - bit_t_seq_table_rc[i][1] = RC_CHAR(bit_t_seq_table[i][2]); - bit_t_seq_table_rc[i][2] = RC_CHAR(bit_t_seq_table[i][1]); - bit_t_seq_table_rc[i][3] = RC_CHAR(bit_t_seq_table[i][0]); - } - } -} - - -void recover_UC_Read_sub_region(char* r, int64_t start_pos, int64_t length, uint8_t strand, All_reads* R_INF, int64_t ID) -{ - int64_t readLen = Get_READ_LENGTH((*R_INF), ID); - int64_t end_pos = start_pos + length - 1, begLen, tailLen, offset, mn, src_i, des_i, i; - uint8_t* src = Get_READ((*R_INF), ID); - - if(strand == 0) { - offset = start_pos&3; - begLen = 4-offset; - if(begLen > length) begLen = length; - tailLen = (length-begLen)&3; - mn = (length - begLen - tailLen)>>2; - src_i = start_pos; des_i = 0; i = 0; - - if(begLen > 0) { - memcpy(r+des_i, bit_t_seq_table[src[src_i>>2]]+offset, begLen); - des_i += begLen; src_i += begLen; - } - - for (i = 0; i < mn; i++) { - memcpy(r+des_i, bit_t_seq_table[src[src_i>>2]], 4); - des_i += 4; src_i += 4; - } - - if(tailLen > 0) { - memcpy(r+des_i, bit_t_seq_table[src[src_i>>2]], tailLen); - des_i += tailLen; src_i += tailLen; - } - - if (R_INF->N_site[ID]) { - for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++) { - if ((long long)R_INF->N_site[ID][i] >= start_pos && (long long)R_INF->N_site[ID][i] <= end_pos) { - r[R_INF->N_site[ID][i] - start_pos] = 'N'; - } - else if((long long)R_INF->N_site[ID][i] > end_pos) { - break; - } - } - } - } - else { - start_pos = readLen - start_pos - 1; - end_pos = readLen - end_pos - 1; - - begLen = (start_pos+1)&3; - offset = 4 - begLen; - if(begLen > length) begLen = length; - tailLen = (length-begLen)&3; - mn = (length - begLen - tailLen)>>2; - src_i = start_pos; des_i = 0; i = 0; - - if(begLen > 0) { - memcpy(r+des_i, bit_t_seq_table_rc[src[src_i>>2]]+offset, begLen); - des_i += begLen; src_i -= begLen; - } - - for (i = 0; i < mn; i++) { - memcpy(r+des_i, bit_t_seq_table_rc[src[src_i>>2]], 4); - des_i += 4; src_i -= 4; - } - - if(tailLen > 0) { - memcpy(r+des_i, bit_t_seq_table_rc[src[src_i>>2]], tailLen); - des_i += tailLen; src_i -= tailLen; - } - - /** - if (R_INF->N_site[ID]) { - offset = readLen - start_pos - 1; - for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++) { - if ((long long)R_INF->N_site[ID][i] >= end_pos && (long long)R_INF->N_site[ID][i] <= start_pos) { - r[readLen - R_INF->N_site[ID][i] - 1 - offset] = 'N'; - } - else if((long long)R_INF->N_site[ID][i] > start_pos) { - break; - } - } - } - **/ - if (R_INF->N_site[ID]) { - start_pos = readLen - start_pos - 1; end_pos = readLen - end_pos - 1; - for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++) { - offset = readLen - R_INF->N_site[ID][i] - 1; - if(offset >= start_pos && offset <= end_pos) { - r[offset - start_pos] = 'N'; - } else if(offset < start_pos) { - break; - } - } - } - } -} - - -void recover_UC_sub_Read(UC_Read* i_r, long long start_pos, long long length, uint8_t strand, All_reads* R_INF, long long ID) -{ - i_r->length = length;i_r->RID = ID; - if (i_r->length + 8 > i_r->size) - { - i_r->size = i_r->length + 4; - i_r->seq = (char*)realloc(i_r->seq,sizeof(char)*(i_r->size)); - } - char* r = i_r->seq; - long long readLen = Get_READ_LENGTH((*R_INF), ID); - uint8_t* src = Get_READ((*R_INF), ID); - - long long i; - long long copyLen; - long long end_pos = start_pos + length - 1; - - if (strand == 0) - { - i = start_pos; - copyLen = 0; - - long long initLen = start_pos % 4; - - if (initLen != 0) - { - memcpy(r, bit_t_seq_table[src[i>>2]] + initLen, 4 - initLen); - copyLen = copyLen + 4 - initLen; - i = i + copyLen; - } - - while (copyLen < length) - { - memcpy(r+copyLen, bit_t_seq_table[src[i>>2]], 4); - copyLen = copyLen + 4; - i = i + 4; - } - - if (R_INF->N_site[ID]) - { - for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++) - { - if ((long long)R_INF->N_site[ID][i] >= start_pos && (long long)R_INF->N_site[ID][i] <= end_pos) - { - r[R_INF->N_site[ID][i] - start_pos] = 'N'; - } - else if((long long)R_INF->N_site[ID][i] > end_pos) - { - break; - } - } - } - } - else - { - start_pos = readLen - start_pos - 1; - end_pos = readLen - end_pos - 1; - - ///start_pos > end_pos - i = start_pos; - copyLen = 0; - long long initLen = (start_pos + 1) % 4; - - if (initLen != 0) - { - memcpy(r, bit_t_seq_table_rc[src[i>>2]] + 4 - initLen, initLen); - copyLen = copyLen + initLen; - i = i - initLen; - } - - while (copyLen < length) - { - memcpy(r+copyLen, bit_t_seq_table_rc[src[i>>2]], 4); - copyLen = copyLen + 4; - i = i - 4; - } - - if (R_INF->N_site[ID]) - { - long long offset = readLen - start_pos - 1; - - for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++) - { - if ((long long)R_INF->N_site[ID][i] >= end_pos && (long long)R_INF->N_site[ID][i] <= start_pos) - { - r[readLen - R_INF->N_site[ID][i] - 1 - offset] = 'N'; - } - else if((long long)R_INF->N_site[ID][i] > start_pos) - { - break; - } - } - } - } -} - - - - -void recover_UC_Read(UC_Read* r, const All_reads *R_INF, uint64_t ID) -{ - r->length = Get_READ_LENGTH((*R_INF), ID); - uint8_t* src = Get_READ((*R_INF), ID); - - if (r->length + 4 > r->size) { - r->size = r->length + 4; - r->seq = (char*)realloc(r->seq,sizeof(char)*(r->size)); - } - - uint64_t i = 0; - - if(src) { - while ((long long)i < r->length) { - memcpy(r->seq+i, bit_t_seq_table[src[i>>2]], 4); - i = i + 4; - } - - if (R_INF->N_site[ID]) { - for (i = 1; i <= R_INF->N_site[ID][0]; i++) r->seq[R_INF->N_site[ID][i]] = 'N'; - } - } else {///N - memset(r->seq, 'N', r->length); - } - - r->RID = ID; -} - -void recover_UC_Read_RC(UC_Read* r, All_reads* R_INF, uint64_t ID) -{ - r->length = Get_READ_LENGTH((*R_INF), ID); - uint8_t* src = Get_READ((*R_INF), ID); - - if (r->length + 4 > r->size) { - r->size = r->length + 4; - r->seq = (char*)realloc(r->seq,sizeof(char)*(r->size)); - } - - long long last_chr = r->length % 4; - long long i = r->length / 4 - 1 + (last_chr != 0); - long long index = 0; - - if(src) { - if(last_chr!=0) { - memcpy(r->seq + index, bit_t_seq_table_rc[src[i]] + 4 - last_chr, last_chr); - index = last_chr; - i--; - } - - while (i >= 0) { - memcpy(r->seq + index, bit_t_seq_table_rc[src[i]], 4); - i--; - index = index + 4; - } - - if (R_INF->N_site[ID]) { - for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++) { - r->seq[r->length - R_INF->N_site[ID][i] - 1] = 'N'; - } - } - } else {///N - memset(r->seq, 'N', r->length); - } - - -} - -#define COMPRESS_BASE {c = seq_nt6_table[(uint8_t)src[i]];\ - if (c >= 4)\ - {\ - c = 0;\ - (*N_site_lis)[N_site_i] = i;\ - N_site_i++;\ - }\ - i++;}\ - -void ha_compress_base(uint8_t* dest, char* src, uint64_t src_l, uint64_t** N_site_lis, uint64_t N_site_occ) -{ - ///N_site_lis saves the pos of all Ns in this read - ///N_site_lis[0] is the number of Ns - free((*N_site_lis)); - if (N_site_occ) - { - (*N_site_lis) = (uint64_t*)malloc(sizeof(uint64_t)*(N_site_occ + 1)); - (*N_site_lis)[0] = N_site_occ; - } - else - { - (*N_site_lis) = NULL; - } - - uint64_t i = 0; - uint64_t N_site_i = 1; - uint64_t dest_i = 0; - uint8_t tmp = 0; - uint8_t c = 0; - - while (i + 4 <= src_l) - { - tmp = 0; - - COMPRESS_BASE; - tmp = tmp | (c<<6); - - COMPRESS_BASE; - tmp = tmp | (c<<4); - - COMPRESS_BASE; - tmp = tmp | (c<<2); - - COMPRESS_BASE; - tmp = tmp | c; - - dest[dest_i] = tmp; - - dest_i++; - } - - //at most 3 bases here - uint64_t shift = 6; - if (i < src_l) - { - tmp = 0; - - while (i < src_l) - { - COMPRESS_BASE; - tmp = tmp | (c << shift); - shift = shift -2; - } - - dest[dest_i] = tmp; - dest_i++; - } -} - -void convert_qual(uint8_t* dest, char* src, uint64_t src_l, uint64_t bitu, uint64_t rev, uint64_t sc_off) -{ - uint64_t i = 0; uint8_t c = 0, sc; - // fprintf(stderr, "\n[M::%s]\n", __func__); - for (i = 0; i < src_l; i++) { - for (c = 0, sc = ((uint8_t)src[i]) - sc_off; (c < bitu) && (sc_tb[c] < sc); c++); - if(c >= bitu) c = bitu - 1; - dest[(rev?(src_l-i-1):(i))] = c; - // fprintf(stderr, "%u->%u\n", sc, c); - } -} - -void ha_compress_qual_bit(uint8_t* dest, char* src, uint64_t src_l, uint64_t bitn) -{ - - uint64_t i = 0, k, bit_r = 8/bitn, dest_i = 0; - uint8_t tmp = 0, c = 0; - - for (i = 0; i + bit_r <= src_l;) { - for (k = tmp = 0; k < bit_r; k++) { - c = ((uint8_t)src[i]); - tmp <<= bitn; tmp |= c; i++; - } - dest[dest_i++] = tmp; - } - - if(i < src_l) { - for (k = tmp = 0; i < src_l; k++) { - c = ((uint8_t)src[i]); - tmp <<= bitn; tmp |= c; i++; - } - - dest[dest_i++] = (tmp<<(8-(bitn*k))); - } -} - -void ha_compress_qual(uint8_t* dest, char* src, uint64_t src_l, uint64_t bitn, uint64_t sc_off) -{ - - uint64_t i = 0, k, bit_r = 8/bitn, dest_i = 0, bitu = (1<= bitu) c = bitu - 1; - tmp <<= bitn; tmp |= c; i++; - } - dest[dest_i++] = tmp; - } - - if(i < src_l) { - for (k = tmp = 0; i < src_l; k++) { - for (c = 0, sc = ((uint8_t)src[i]) - sc_off; (c < bitu) && (sc_tb[c] < sc); c++); - if(c >= bitu) c = bitu - 1; - tmp <<= bitn; tmp |= c; i++; - } - - dest[dest_i++] = (tmp<<(8-(bitn*k))); - } -} - -///[s, e) -int64_t retrive_bqual(asg8_v *dv, uint8_t *ds, uint64_t id, int64_t s, int64_t e, uint8_t rev, int64_t bitn) -{ - int64_t rl = Get_READ_LENGTH(R_INF, id), l; - if(s < 0) s = 0; if(e < 0) e = rl; - if(s >= e || e > rl) return -1; - - uint8_t *da = NULL, *src = Get_QUAL(R_INF, id), mm = (((uint8_t)1)<a; - } else { - da = ds; - } - - if(!rev) { - dk = 0; sk = s; - - mrf = ((s%bitr)*bitn); - // if(s == 21519 && e == 22332) { - // fprintf(stderr, "+[M::%s] id::%lu, in::[%ld, %ld), rev::%u, bitn::%ld, bitr::%ld, mrf::%u\n", __func__, id, s, e, rev, bitn, bitr, mrf); - // } - if(mrf) { - for (swk = sk/bitr; mrf < 8 && sk < e; mrf += bitn, sk++) da[dk++] = ((src[swk]<>mlf)&mm; - } - - for (swk = sk/bitr; (sk + bitr) <= e; sk += bitr, swk++) { - for (mrf = 0; mrf < 8; mrf += bitn) da[dk++] = ((src[swk]<>mlf)&mm; - } - - if(sk < e) { - for (mrf = 0; sk < e; mrf += bitn, sk++) da[dk++] = ((src[swk]<>mlf)&mm; - } - // if(dk != l) { - // fprintf(stderr, "+[M::%s] id::%lu, in::[%ld, %ld), rev::%u, bitn::%ld, bitr::%ld\n", __func__, id, s, e, rev, bitn, bitr); - // } - assert(dk == l); - } else { - sk = s; s = e; e = sk; - s = rl - s; e = rl - e; - dk = l; sk = s; - - mrf = ((s%bitr)*bitn); - if(mrf) { - for (swk = sk/bitr; mrf < 8 && sk < e; mrf += bitn, sk++) da[--dk] = ((src[swk]<>mlf)&mm; - } - - for (swk = sk/bitr; (sk + bitr) <= e; sk += bitr, swk++) { - for (mrf = 0; mrf < 8; mrf += bitn) da[--dk] = ((src[swk]<>mlf)&mm; - } - - if(sk < e) { - for (mrf = 0; sk < e; mrf += bitn, sk++) da[--dk] = ((src[swk]<>mlf)&mm; - } - - assert(dk == 0); - } - dv->n = l; - - return l; -} - -void reverse_complement(char* pattern, uint64_t length) -{ - uint64_t i = 0; - uint64_t end = length / 2; - char k; - uint64_t index; - - for (i = 0; i < end; i++) - { - - index = length - i - 1; - k = pattern[index]; - pattern[index] = RC_CHAR(pattern[i]); - pattern[i] = RC_CHAR(k); - } - - if(length&(uint64_t)1) - { - pattern[end] = RC_CHAR(pattern[end]); - } -} - -void print_fastq(FILE *fp, char *id, char *bs, char *qual, uint64_t bitu, uint64_t sc_off) -{ - uint64_t i = 0, ql = strlen(qual); uint8_t c = 0, sc; - - if(fp) fprintf(fp, "@%s\n%s\n+\n", id, bs); - else fprintf(stdout, "@%s\n%s\n+\n", id, bs); - - for (i = 0; i < ql; i++) { - for (c = 0, sc = ((uint8_t)qual[i]) - sc_off; (c < bitu) && (sc_tb[c] < sc); c++); - if(c >= bitu) c = bitu - 1; - if(fp) fprintf(fp, "%u", c); - else fprintf(stdout, "%u", c); - } - - if(fp) fprintf(fp, "\n"); - else fprintf(stdout, "\n"); -} - - -void init_Debug_reads(Debug_reads* x, const char* file) -{ - int nameLen, i, bufLen = 1000; - if((uint64_t)(bufLen) < strlen(file) + 50) bufLen = strlen(file) + 50; - char* Name_Buffer = (char*)malloc(sizeof(char)*bufLen); - fprintf(stderr, "Queried debugging reads at: %s\n", file); - - x->fp = fopen(file,"r"); - x->query_num = 0; - - while(fgets(Name_Buffer, bufLen, x->fp)) - { - x->query_num++; - } - x->read_name = (char**)malloc(sizeof(char*)*x->query_num); - x->candidate_count = (kvec_t_u64_warp*)malloc(sizeof(kvec_t_u64_warp)*x->query_num); - x->read_id = NULL; MALLOC(x->read_id, x->query_num); - memset(x->read_id, -1, sizeof((*(x->read_id)))*x->query_num); - fseek(x->fp, 0, SEEK_SET); - - i = 0; - while(fgets(Name_Buffer, bufLen, x->fp)) - { - nameLen = strlen(Name_Buffer) - 1; - x->read_name[i] = (char*)malloc(sizeof(char)*(nameLen+1)); - memcpy(x->read_name[i], Name_Buffer, sizeof(char)*nameLen); - x->read_name[i][nameLen] = '\0'; - kv_init(x->candidate_count[i].a); - i++; - } - - fclose(x->fp); - - sprintf(Name_Buffer, "%s.debug.stdout", file); - x->fp = fopen(Name_Buffer,"w"); - fprintf(stderr, "Print debugging information to: %s\n", Name_Buffer); - - sprintf(Name_Buffer, "%s.debug.r0.fa", file); - x->fp_r0 = fopen(Name_Buffer,"w"); - fprintf(stderr, "Print raw reads to: %s\n", Name_Buffer); - - sprintf(Name_Buffer, "%s.debug.r1.fa", file); - x->fp_r1 = fopen(Name_Buffer,"w"); - fprintf(stderr, "Print corrected reads to: %s\n", Name_Buffer); - - free(Name_Buffer); -} - -void destory_Debug_reads(Debug_reads* x) -{ - uint64_t i; - for (i = 0; i < x->query_num; i++) - { - free(x->read_name[i]); - kv_destroy(x->candidate_count[i].a); - } - - free(x->read_name); free(x->read_id); - fclose(x->fp); fclose(x->fp_r0); fclose(x->fp_r1); -} - - -void init_all_ul_t(all_ul_t *x, All_reads *hR) { - memset(x, 0, sizeof(*x)); - x->hR = hR; - init_aux_table(); -} -void destory_all_ul_t(all_ul_t *x) { - uint64_t i; - for (i = 0; i < x->n; i++) { - free(x->a[i].N_site.a); free(x->a[i].r_base.a); free(x->a[i].bb.a); - } - free(x->a); - - for (i = 0; i < x->nid.n; i++) free(x->nid.a[i].a); - free(x->nid.a); - free(x->ridx.idx.a); free(x->ridx.occ.a); - - // if(x->mm) { - // for (i = 0; i < x->mm->n; i++) free(x->mm->a[i].a); - // free(x->mm->a); free(x->mm); x->mm = NULL; - // } -} - -void ha_encode_base(uint8_t* dest, char* src, uint64_t src_l, N_t *nn, uint64_t nn_offset) -{ - uint64_t i = 0; - uint64_t dest_i = 0; - uint8_t tmp = 0; - uint8_t c = 0; - - while (i + 4 <= src_l) { - tmp = 0; - // fprintf(stderr, "i->%lu, src_l->%ld, src[i]->%c, (uint8_t)src[i]->%u\n", i, src_l, src[i], (uint8_t)src[i]); - c = seq_nt6_table[(uint8_t)src[i]]; - if (c >= 4) { - c = 0; kv_push(uint32_t, *nn, i+nn_offset); - } - i++; - tmp = tmp | (c<<6); - - c = seq_nt6_table[(uint8_t)src[i]]; - if (c >= 4) { - c = 0; kv_push(uint32_t, *nn, i+nn_offset); - } - i++; - tmp = tmp | (c<<4); - - c = seq_nt6_table[(uint8_t)src[i]]; - if (c >= 4) { - c = 0; kv_push(uint32_t, *nn, i+nn_offset); - } - i++; - tmp = tmp | (c<<2); - - c = seq_nt6_table[(uint8_t)src[i]]; - if (c >= 4) { - c = 0; kv_push(uint32_t, *nn, i+nn_offset); - } - i++; - tmp = tmp | c; - - dest[dest_i] = tmp; - - dest_i++; - } - - //at most 3 bases here - uint64_t shift = 6; - if (i < src_l) { - tmp = 0; - while (i < src_l) { - c = seq_nt6_table[(uint8_t)src[i]]; - if (c >= 4) { - c = 0; kv_push(uint32_t, *nn, i+nn_offset); - } - i++; - tmp = tmp | (c << shift); - shift = shift -2; - } - - dest[dest_i] = tmp; - dest_i++; - } -} - -#define B4L(x) (((x)>>2)+(((x)&3)?1:0)) -void push_subblock_original_bases(char* str, all_ul_t *x, ul_vec_t *p, uint32_t s, uint32_t e, uint32_t subLen)//for debug -{ - uc_block_t *b = NULL; - uint32_t qs = s, qe = e; - while (qs < e) { - qe = qs + subLen; if(qe > e) qe = e; - kv_pushp(uc_block_t, p->bb, &b); - b->hid = (uint32_t)-1; b->rev = 0; - b->qs = qs; b->qe = qe; - b->ts = p->r_base.n; b->te = b->ts + B4L(b->qe - b->qs); - kv_resize(uint8_t, p->r_base, b->te); p->r_base.n = b->te; - ha_encode_base(p->r_base.a+b->ts, str+b->qs, b->qe-b->qs, &(p->N_site), b->qs); - - qs = qe; - } -} - -void append_ul_t_compress_ovlp(all_ul_t *x, uint64_t *rid, char* id, int64_t id_l, char* str, int64_t str_l, ul_ov_t *o, int64_t on) { - int64_t i, mine, maxs, ovlp, end; - ul_vec_t *p = NULL; - nid_t *np = NULL; - ul_ov_t *z = NULL, *zp = NULL; - uc_block_t *b = NULL; - - if(id) { - kv_pushp(nid_t, x->nid, &np); - np->n = id_l; MALLOC(np->a, np->n+1); memcpy(np->a, id, id_l); np->a[id_l] = '\0'; - } - - if(str) { - if(rid == NULL) { - kv_pushp(ul_vec_t, *x, &p); - memset(p, 0, sizeof(*p)); - } else { - if((*rid) >= x->m) kv_resize(ul_vec_t, *x, (*rid) + 1); - if((*rid) >= x->n) { - memset(x->a+x->n, 0, sizeof(*p)*((*rid) + 1 - x->n)); - x->n = (*rid) + 1; - } - p = &(x->a[(*rid)]); - } - - - p->bb.n = p->N_site.n = p->r_base.n = 0; - p->rlen = str_l; - - if(o == NULL || on == 0) on = 0; - for (i = end = 0, zp = NULL; i < on; i++) { - z = &(o[i]); - if(!z->el) continue; - if(zp) { - mine = MIN(zp->qe, z->qe); maxs = MAX(zp->qs, z->qs); - ovlp = mine - maxs; - if(zp->qe >= z->qe && zp->qs <= z->qs) continue; - } else { - ovlp = -z->qs; - } - if(ovlp < 0) {///push original bases - kv_pushp(uc_block_t, p->bb, &b); - b->hid = (uint32_t)-1/**x->mm**/; b->rev = 0; b->base = 1; b->pchain = 0; - b->qs = end; b->qe = b->qs - ovlp; - b->ts = p->r_base.n; b->te = b->ts + B4L(-ovlp); - kv_resize(uint8_t, p->r_base, b->te); p->r_base.n = b->te; - ha_encode_base(p->r_base.a+b->ts, str+b->qs, b->qe-b->qs, &(p->N_site), b->qs); - } - - ///push ovlp bases - kv_pushp(uc_block_t, p->bb, &b); - b->hid = (z->tn<<1)>>1; b->rev = z->rev; b->base = 0; b->pchain = 0; - b->qs = z->qs + (ovlp>0?ovlp:0); b->qe = z->qe; - if(z->rev) { - b->ts = z->ts; b->te = z->ts + (b->qe - b->qs); - } else { - b->ts = z->te - (b->qe - b->qs); b->te = z->te; - } - - end = MAX(zp?zp->qe:0, z->qe); - } - - if(end < str_l) {///push original bases - kv_pushp(uc_block_t, p->bb, &b); - b->hid = (uint32_t)-1/**x->mm**/; b->rev = 0; b->base = 1; b->pchain = 0; - b->qs = end; b->qe = str_l; - b->ts = p->r_base.n; b->te = b->ts + B4L(b->qe - b->qs); - kv_resize(uint8_t, p->r_base, b->te); p->r_base.n = b->te; - ha_encode_base(p->r_base.a+b->ts, str+b->qs, b->qe-b->qs, &(p->N_site), b->qs); - // push_subblock_original_bases(str, x, p, end, str_l, 321);//for debug - } - // char *sst = NULL; CALLOC(sst, str_l);//for debug - // retrieve_ul_t(NULL, sst, x, rid?*rid:x->n-1, 0, 0, -1); - // if(memcmp(sst, str, str_l)) { - // fprintf(stderr, "ap-Wrong read, id: %ld, [%d, %ld)\n", (int64_t)(rid?*rid:x->n-1), 0, str_l); - // for (i = 0; i < str_l; i++) { - // if(sst[i] != str[i]) fprintf(stderr, "[%ld] input:%c, decompress:%c\n", i, str[i], sst[i]); - // } - // } - // free(sst); - } -} - -void debug_append_ul_t(ul_ov_t *o, int64_t on, ul_vec_t *p) -{ - int64_t k, l = 0; - uint32_t sp = (uint32_t)-1, ep = (uint32_t)-1, qss, qee, m; - for (k = on-1; k >= 0; k--) { - if(sp == (uint32_t)-1 || o[k].qe <= sp) { - if(sp != (uint32_t)-1) l += ep - sp; - - if(sp == (uint32_t)-1) qss = o[k].qe, qee = p->rlen; - else qss = o[k].qe, qee = sp; - if(qee > qss) { - for (m = 0; m < p->bb.n; m++) { - if(qss == (p->bb.a[m].qs+((p->bb.a[m].hid>>15)&(0x7fffU))) && - qee == (p->bb.a[m].qe-(p->bb.a[m].hid&(0x7fffU)))) { - break; - } - } - if(m >= p->bb.n) fprintf(stderr, "ERROR\n"); - } - - sp = o[k].qs; - ep = o[k].qe; - } else { - sp = MIN(sp, o[k].qs); - } - } - if(sp != (uint32_t)-1) l += ep - sp; - - if(sp == (uint32_t)-1) qss = 0, qee = p->rlen; - else qss = 0, qee = sp; - if(qee > qss) { - for (m = 0; m < p->bb.n; m++) { - if(qss == (p->bb.a[m].qs+((p->bb.a[m].hid>>15)&(0x7fffU))) && - qee == (p->bb.a[m].qe-(p->bb.a[m].hid&(0x7fffU)))) { - break; - } - } - if(m >= p->bb.n) fprintf(stderr, "ERROR\n"); - } -} - -void append_ul_t_back(all_ul_t *x, uint64_t *rid, char* id, int64_t id_l, char* str, int64_t str_l, ul_ov_t *o, int64_t on, float p_chain_rate) { - int64_t i, mine, maxs, ovlp, st, et, bl = 0, pc = 0; - uint32_t o_l, o_r; - ul_vec_t *p = NULL; - nid_t *np = NULL; - ul_ov_t *z = NULL; - uc_block_t *b = NULL, tt; - - if(id) { - kv_pushp(nid_t, x->nid, &np); - np->n = id_l; MALLOC(np->a, np->n+1); memcpy(np->a, id, id_l); np->a[id_l] = '\0'; - } - - if(str||str_l) { - if(rid == NULL) { - kv_pushp(ul_vec_t, *x, &p); - memset(p, 0, sizeof(*p)); - } else { - if((*rid) >= x->m) kv_resize(ul_vec_t, *x, (*rid) + 1); - if((*rid) >= x->n) { - memset(x->a+x->n, 0, sizeof(*p)*((*rid) + 1 - x->n)); - x->n = (*rid) + 1; - } - p = &(x->a[(*rid)]); - } - // if((*rid) == 23) fprintf(stderr, "#rid->%lu, on->%ld\n", *rid, on); - - p->bb.n = p->N_site.n = p->r_base.n = 0; p->dd = 0; - p->rlen = str_l; - - if(o == NULL || on == 0) on = 0; - for (i = on-1, st = et = str_l; i >= 0; i--) { - z = &(o[i]); - if(z->el) { - mine = MIN(et, ((int64_t)z->qe)); maxs = MAX(st, ((int64_t)z->qs)); - ovlp = mine - maxs; - - if(ovlp < 0) {///push original bases - kv_pushp(uc_block_t, p->bb, &b); - b->hid = 0/**x->mm**/; b->rev = 0; b->base = 1; b->pchain = 0; b->el = 0; - b->qe = maxs; b->qs = b->qe + ovlp; bl += (b->qe-b->qs); - o_l = (b->qs >= UL_FLANK?UL_FLANK:b->qs); - o_r = ((str_l-b->qe)>=UL_FLANK?UL_FLANK:(str_l-b->qe)); - b->hid |= (o_l<<15); b->hid |= o_r; - b->qs -= o_l; b->qe += o_r; - b->ts = p->r_base.n; b->te = b->ts + B4L(b->qe-b->qs); - kv_resize(uint8_t, p->r_base, b->te); p->r_base.n = b->te; - // if(!str) fprintf(stderr, "+rid->%lu\n", *rid); - ha_encode_base(p->r_base.a+b->ts, str+b->qs, b->qe-b->qs, &(p->N_site), b->qs); - } - - st = MIN(st, z->qs); - } - - ///push ovlp bases - kv_pushp(uc_block_t, p->bb, &b); - b->hid = (z->tn<<1)>>1; b->rev = z->rev; b->base = 0; b->el = z->el; - b->pchain = ((z->tn&((uint32_t)(0x80000000)))?1:0); - b->qs = z->qs; b->qe = z->qe; - b->ts = z->ts; b->te = z->te; - if(b->pchain) pc++; - - // st = MIN(st, z->qs); - } - - if(st > 0) {///push original bases - kv_pushp(uc_block_t, p->bb, &b); - b->hid = 0/**x->mm**/; b->rev = 0; b->base = 1; b->pchain = 0; b->el = 0; - b->qe = st; b->qs = 0; bl += (b->qe-b->qs); - o_l = (b->qs >= UL_FLANK?UL_FLANK:b->qs); - o_r = ((str_l-b->qe)>=UL_FLANK?UL_FLANK:(str_l-b->qe)); - b->hid |= (o_l<<15); b->hid |= o_r; - b->qs -= o_l; b->qe += o_r; - b->ts = p->r_base.n; b->te = b->ts + B4L(b->qe-b->qs); - kv_resize(uint8_t, p->r_base, b->te); p->r_base.n = b->te; - // if(!str) fprintf(stderr, "-rid->%lu, st->%ld, str_l->%ld\n", *rid, st, str_l); - ha_encode_base(p->r_base.a+b->ts, str+b->qs, b->qe-b->qs, &(p->N_site), b->qs); - // push_subblock_original_bases(str, x, p, end, str_l, 321);//for debug - } - - if(pc > 0) p->dd = 3; - if((pc == on) && ((str_l-bl) > (str_l*p_chain_rate))) p->dd = 2; - if((pc == on) && (bl == 0)) p->dd = 1; - // debug_append_ul_t(o, on, p); - // char *sst = NULL; CALLOC(sst, str_l);//for debug - // retrieve_ul_t(NULL, sst, x, rid?*rid:x->n-1, 0, 0, -1); - // if(memcmp(sst, str, str_l)) { - // fprintf(stderr, "ap-Wrong read, id: %ld, [%d, %ld)\n", (int64_t)(rid?*rid:x->n-1), 0, str_l); - // for (i = 0; i < str_l; i++) { - // if(sst[i] != str[i]) fprintf(stderr, "[%ld] input:%c, decompress:%c\n", i, str[i], sst[i]); - // } - // } - // free(sst); - ovlp = p->bb.n>>1; - for (i = 0; i < ovlp; i++) { - tt = p->bb.a[i]; - p->bb.a[i] = p->bb.a[p->bb.n-i-1]; - p->bb.a[p->bb.n-i-1] = tt; - } - - } -} - - -void determine_chain_distance(ul_ov_t *o, int64_t on, ul_vec_t *p, ma_hit_t_alloc *src, int64_t max_hang, int64_t min_ovlp, int64_t rid) -{ - int64_t k, i, m, l = 0, r, last_i, last_dis; ul_ov_t *z = NULL; - uint32_t li_v, lj_v, t, qn, tn; ma_hit_t_alloc *x = NULL; asg_arc_t te; - - for (k = on-1; k >= 0; --k) { - z = &(o[k]); - if((!z->el) || (z->sec == SEC_MODE)) continue; - ///if z->el = 1, z->qn must work - if(p->bb.a[z->qn].pidx != (uint32_t)-1) continue; - last_i = -1; last_dis = 0; - for (i = k, l = 0; i >= 0;) { - assert((o[i].tn&((uint32_t)(0x80000000)))); - if(o[i].el) { - last_i = o[i].qn; last_dis = l; - } - m = i; i = o[i].sec; if(o[m].sec == SEC_MODE) i = -1; - // i = ((o[i].sec == SEC_MODE)?-1:o[i].sec); - if(i < 0) break; - // if(i >= on || i < 0) fprintf(stderr, "m->%ld, i->%ld, rid->%ld, on->%ld, o[m].sec->%u\n", m, i, rid, on, o[m].sec); - li_v = (o[m].tn<<1)|o[m].rev; li_v ^= 1; - lj_v = (o[i].tn<<1)|o[i].rev; lj_v ^= 1; - - x = &(src[li_v>>1]); - for (t = 0; t < x->length; t++) { - qn = Get_qn(x->buffer[t]); - tn = Get_tn(x->buffer[t]); - if(qn == (li_v>>1) && tn == (lj_v>>1)) { - r = ma_hit2arc(&(x->buffer[t]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), - max_hang, asm_opt.max_hang_rate, min_ovlp, &te); - if(r < 0) continue; - if((te.ul>>32) != li_v || te.v != lj_v) continue; - l += (uint32_t)te.ul; - break; - } - } - // if(t>=x->length) { - // fprintf(stderr, "m->%ld(id::%u), i->%ld(id::%u), rid->%ld, on->%ld\n", - // m, (o[m].tn<<1)>>1, i, (o[i].tn<<1)>>1, rid, on); - // // fprintf(stderr, "[i::%ld]id::%u\t\tq::[%u, %u)\tt::[%u, %u)\n", - // // i, o[i].tn, o[i].qs, o[i].qe, o[i].ts, o[i].te); - // // fprintf(stderr, "[m::%ld]id::%u\t\tq::[%u, %u)\tt::[%u, %u)\n", - // // m, o[m].tn, o[m].qs, o[m].qe, o[m].ts, o[m].te); - // fprintf(stderr, "[i::%ld]id::%u\t%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\n", - // i, (o[i].tn<<1)>>1, (int)Get_NAME_LENGTH(R_INF, ((o[i].tn<<1)>>1)), Get_NAME(R_INF, ((o[i].tn<<1)>>1)), - // "+-"[o[i].rev], o[i].qs, o[i].qe, o[i].ts, o[i].te); - // fprintf(stderr, "[m::%ld]id::%u\t%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\n", - // m, (o[m].tn<<1)>>1, (int)Get_NAME_LENGTH(R_INF, ((o[m].tn<<1)>>1)), Get_NAME(R_INF, ((o[m].tn<<1)>>1)), - // "+-"[o[m].rev], o[m].qs, o[m].qe, o[m].ts, o[m].te); - // exit(1); - // } - assert(tlength); - if(!(o[i].el)) continue; - assert(last_i>=0); - p->bb.a[last_i].pidx = o[i].qn; - p->bb.a[last_i].pdis = l - last_dis;///TODO: enable pdis - p->bb.a[p->bb.a[last_i].pidx].aidx = last_i; - } - } -} - -void append_ul_t(all_ul_t *x, uint64_t *rid, char* id, int64_t id_l, char* str, int64_t str_l, ul_ov_t *o, int64_t on, float p_chain_rate, const ug_opt_t *uopt, uint32_t save_bases) { - int64_t i, mine, maxs, ovlp, st, et, bl = 0, pc = 0, en = 0; - uint32_t o_l, o_r; - ul_vec_t *p = NULL; - nid_t *np = NULL; - ul_ov_t *z = NULL; - uc_block_t *b = NULL, tt; - - if(id) { - kv_pushp(nid_t, x->nid, &np); - np->n = id_l; MALLOC(np->a, np->n+1); memcpy(np->a, id, id_l); np->a[id_l] = '\0'; - } - - if(str||str_l) { - if(rid == NULL) { - kv_pushp(ul_vec_t, *x, &p); - memset(p, 0, sizeof(*p)); - } else { - if((*rid) >= x->m) kv_resize(ul_vec_t, *x, (*rid) + 1); - if((*rid) >= x->n) { - memset(x->a+x->n, 0, sizeof(*p)*((*rid) + 1 - x->n)); - x->n = (*rid) + 1; - } - p = &(x->a[(*rid)]); - } - // if((*rid) == 23) fprintf(stderr, "#rid->%lu, on->%ld\n", *rid, on); - - p->bb.n = p->N_site.n = p->r_base.n = 0; p->dd = 0; - p->rlen = str_l; - // fprintf(stderr, "str_l->%ld, str->%u\n", str_l, str?1:0); - - if(o == NULL || on == 0) on = 0; en = 0; - for (i = on-1, st = et = str_l; i >= 0; i--) { - z = &(o[i]); - if(z->el) { - if((z->tn&((uint32_t)(0x80000000)))) { - mine = MIN(et, ((int64_t)z->qe)); maxs = MAX(st, ((int64_t)z->qs)); - ovlp = mine - maxs; - if(ovlp < 0) bl -= ovlp; - if(save_bases && ovlp < 0) {///push original bases - kv_pushp(uc_block_t, p->bb, &b); - b->hid = 0/**x->mm**/; b->rev = 0; b->base = 1; b->pchain = 0; b->el = 0; - b->qe = maxs; b->qs = b->qe + ovlp; //bl += (b->qe-b->qs); - o_l = (b->qs >= UL_FLANK?UL_FLANK:b->qs); - o_r = ((str_l-b->qe)>=UL_FLANK?UL_FLANK:(str_l-b->qe)); - b->pidx = b->pdis = b->aidx = (uint32_t)-1; - b->hid |= (o_l<<15); b->hid |= o_r; - b->qs -= o_l; b->qe += o_r; - b->ts = p->r_base.n; b->te = b->ts + B4L(b->qe-b->qs); - kv_resize(uint8_t, p->r_base, b->te); p->r_base.n = b->te; - // fprintf(stderr, "\n+rid->%lu, str_l->%ld, b->qs->%u, b->qe->%u\n", *rid, str_l, b->qs, b->qe); - ha_encode_base(p->r_base.a+b->ts, str+b->qs, b->qe-b->qs, &(p->N_site), b->qs); - } - - st = MIN(st, z->qs); - } - - ///push ovlp bases - kv_pushp(uc_block_t, p->bb, &b); - b->hid = (z->tn<<1)>>1; b->rev = z->rev; b->base = 0; b->el = z->el; - b->pchain = ((z->tn&((uint32_t)(0x80000000)))?1:0); - b->qs = z->qs; b->qe = z->qe; - b->ts = z->ts; b->te = z->te; - if(b->pchain) pc++; - b->pidx = i; b->pdis = b->aidx = (uint32_t)-1; - en++; z->qn = p->bb.n - 1; - } - } - - if(st > 0) bl += st; - if(save_bases && st > 0) {///push original bases - kv_pushp(uc_block_t, p->bb, &b); - b->hid = 0/**x->mm**/; b->rev = 0; b->base = 1; b->pchain = 0; b->el = 0; - b->qe = st; b->qs = 0; //bl += (b->qe-b->qs); - o_l = (b->qs >= UL_FLANK?UL_FLANK:b->qs); - o_r = ((str_l-b->qe)>=UL_FLANK?UL_FLANK:(str_l-b->qe)); - b->pidx = b->pdis = b->aidx = (uint32_t)-1; - b->hid |= (o_l<<15); b->hid |= o_r; - b->qs -= o_l; b->qe += o_r; - b->ts = p->r_base.n; b->te = b->ts + B4L(b->qe-b->qs); - kv_resize(uint8_t, p->r_base, b->te); p->r_base.n = b->te; - // if(!str) fprintf(stderr, "-rid->%lu, st->%ld, str_l->%ld\n", *rid, st, str_l); - ha_encode_base(p->r_base.a+b->ts, str+b->qs, b->qe-b->qs, &(p->N_site), b->qs); - // push_subblock_original_bases(str, x, p, end, str_l, 321);//for debug - } - - if(pc > 0) p->dd = 3; - if((pc == en) && ((str_l-bl) > (str_l*p_chain_rate))) p->dd = 2; - if((pc == en) && (bl == 0)) p->dd = 1; - // debug_append_ul_t(o, on, p); - // char *sst = NULL; CALLOC(sst, str_l);//for debug - // retrieve_ul_t(NULL, sst, x, rid?*rid:x->n-1, 0, 0, -1); - // if(memcmp(sst, str, str_l)) { - // fprintf(stderr, "ap-Wrong read, id: %ld, [%d, %ld)\n", (int64_t)(rid?*rid:x->n-1), 0, str_l); - // for (i = 0; i < str_l; i++) { - // if(sst[i] != str[i]) fprintf(stderr, "[%ld] input:%c, decompress:%c\n", i, str[i], sst[i]); - // } - // } - // free(sst); - ovlp = p->bb.n>>1; - for (i = 0; i < ovlp; i++) { - tt = p->bb.a[i]; - p->bb.a[i] = p->bb.a[p->bb.n-i-1]; - p->bb.a[p->bb.n-i-1] = tt; - if(p->bb.a[i].pidx!=(uint32_t)-1) { - o[p->bb.a[i].pidx].qn = p->bb.n-o[p->bb.a[i].pidx].qn-1; - p->bb.a[i].pidx = (uint32_t)-1; - } - if(p->bb.a[p->bb.n-i-1].pidx!=(uint32_t)-1) { - o[p->bb.a[p->bb.n-i-1].pidx].qn = p->bb.n-o[p->bb.a[p->bb.n-i-1].pidx].qn-1; - p->bb.a[p->bb.n-i-1].pidx = (uint32_t)-1; - } - } - if(((uint32_t)p->bb.n)&1) { - o[p->bb.a[i].pidx].qn = p->bb.n-o[p->bb.a[i].pidx].qn-1; - p->bb.a[i].pidx = (uint32_t)-1; - } - - determine_chain_distance(o, on, p, uopt->sources, uopt->max_hang, uopt->min_ovlp, *rid); - } -} - -void retrieve_ul_t(UC_Read* i_r, char *i_s, all_ul_t *ref, uint64_t ID, uint8_t strand, int64_t s, int64_t l) { - ul_vec_t *p = &(ref->a[ID]); - if(l < 0) l = p->rlen; - uc_block_t *b = NULL; - char *r = NULL; - uint8_t *src = NULL; - int64_t k, i, a_n, e = s + l, ssp, sep, sl, rts, rte; - int64_t offset, begLen, tailLen, src_i, des_i; - if(i_r) { - i_r->length = l; i_r->RID = ID; - if(i_r->length > i_r->size) { - i_r->size = i_r->length; - i_r->seq = (char*)realloc(i_r->seq,sizeof(char)*(i_r->size)); - } - r = i_r->seq; - } - if(i_s) r = i_s; - - - - if(strand == 0) { - for (k = 0, des_i = 0; k < (int64_t)p->bb.n; k++) { - b = &(p->bb.a[k]); - if(b->qe <= s) continue; - if(b->qs >= e) break; - src = p->r_base.a + b->ts; - ssp = MAX(s, b->qs) - b->qs; - sep = MIN(e, b->qe) - b->qs; - sl = sep - ssp; - - if(b->base/**b->hid&ref->mm**/){///original bases - offset = ssp&3; - begLen = 4-offset; - if(begLen > sl) begLen = sl; - tailLen = (sl-begLen)&3; - a_n = (sl - begLen - tailLen)>>2; - - src_i = ssp; i = 0; - if(begLen > 0) { - memcpy(r+des_i, bit_t_seq_table[src[src_i>>2]]+offset, begLen); - des_i += begLen; src_i += begLen; - } - - for (i = 0; i < a_n; i++) { - memcpy(r+des_i, bit_t_seq_table[src[src_i>>2]], 4); - des_i += 4; src_i += 4; - } - - if(tailLen > 0) { - memcpy(r+des_i, bit_t_seq_table[src[src_i>>2]], tailLen); - des_i += tailLen; src_i += tailLen; - } - } else {///ovlps - if(b->rev == 0) { - recover_UC_Read_sub_region(r+des_i, b->ts + ssp, sep - ssp, b->rev, ref->hR, b->hid); - } else{ - rts = b->ts + (b->qe - sep); rte = rts + sep - ssp; - recover_UC_Read_sub_region(r+des_i, Get_READ_LENGTH((*ref->hR), b->hid) - rte, - sep - ssp, b->rev, ref->hR, b->hid); - } - des_i += sep - ssp; - } - } - for (k = 0; k < (int64_t)p->N_site.n; k++) { - if(p->N_site.a[k] >= s && p->N_site.a[k] < e){ - r[p->N_site.a[k]-s] = 'N'; - } - else if(p->N_site.a[k] >= e) { - break; - } - } - } else { - sep = p->rlen - s; - ssp = p->rlen - e; - s = ssp; e = sep; - ///[s, e) - for (k = ((int64_t)p->bb.n)-1, des_i = 0; k >= 0; k--) { - b = &(p->bb.a[k]); - if(b->qe <= s) break; - if(b->qs >= e) continue; - src = p->r_base.a + b->ts; - ssp = MAX(s, b->qs) - b->qs; - sep = MIN(e, b->qe) - b->qs; - sl = sep - ssp; - ///[ssp, sep) - - if(b->base/**b->hid&ref->mm**/){///original bases - begLen = sep&3; - offset = 4 - begLen; - if(begLen > sl) begLen = sl; - tailLen = (sl-begLen)&3; - a_n = (sl - begLen - tailLen)>>2; - src_i = sep-1; i = 0; - - if(begLen > 0) { - memcpy(r+des_i, bit_t_seq_table_rc[src[src_i>>2]]+offset, begLen); - des_i += begLen; src_i -= begLen; - } - - for (i = 0; i < a_n; i++) { - memcpy(r+des_i, bit_t_seq_table_rc[src[src_i>>2]], 4); - des_i += 4; src_i -= 4; - } - - if(tailLen > 0) { - memcpy(r+des_i, bit_t_seq_table_rc[src[src_i>>2]], tailLen); - des_i += tailLen; src_i -= tailLen; - } - } else {///ovlps - if(b->rev == 0) {///b->rev != strand - rts = b->ts + ssp; rte = rts + sep - ssp; - recover_UC_Read_sub_region(r+des_i, Get_READ_LENGTH((*ref->hR), b->hid) - rte, sep - ssp, 1, ref->hR, b->hid); - } else {///b->rev == strand - rts = b->ts + (b->qe - sep); rte = rts + sep - ssp; - recover_UC_Read_sub_region(r+des_i, rts, sep - ssp, 0, ref->hR, b->hid); - } - des_i += sep - ssp; - } - } - - sep = p->rlen - s; - ssp = p->rlen - e; - s = ssp; e = sep; - for (k = 0; k < (int64_t)p->N_site.n; k++) { - sl = p->rlen - p->N_site.a[k] - 1; - if(sl >= s && sl < e) r[sl-s] = 'N'; - else if(sl < s) { - break; - } - } - } -} - - -void retrieve_u_seq(UC_Read* i_r, char* i_s, ma_utg_t *u, uint8_t strand, int64_t s, int64_t l, void *km) -{ - if(u->m == 0 || u->n == 0) return; - if(l < 0) l = u->len; - char *r = NULL, *a = NULL; - int64_t e = s + l, ssp, sep, rs, re, des_i; - uint64_t k, rId, ori, r_l; - if(i_r) { - i_r->length = l; i_r->RID = 0; - if(i_r->length > i_r->size) { - i_r->size = i_r->length; - if(!km) REALLOC(i_r->seq, i_r->size); - else KREALLOC(km, i_r->seq, i_r->size); - // i_r->seq = (char*)realloc(i_r->seq,sizeof(char)*(i_r->size)); - } - r = i_r->seq; - } - if(i_s) r = i_s; - - if(strand == 1) { - sep = u->len - s; - ssp = u->len - e; - s = ssp; e = sep; - } - for (k = l = des_i = 0; k < u->n; k++) { - rId = u->a[k]>>33; - ori = u->a[k]>>32&1; - r_l = (uint32_t)u->a[k]; - if(r_l == 0) continue; - ssp = l; sep = l + r_l; - l += r_l; - if(sep <= s) continue; - if(ssp >= e) break; - rs = MAX(ssp, s); re = MIN(sep, e); - a = r + des_i; des_i += re - rs; - recover_UC_Read_sub_region(a, rs-ssp, re-rs, ori, &R_INF, rId); - } - if(strand == 1) { - char t; - re = (e - s); - l = re>>1; - for (k = 0; k < (uint64_t)l; k++) { - des_i = re - k - 1; - t = r[des_i]; - r[des_i] = RC_CHAR(r[k]); - r[k] = RC_CHAR(t); - } - if(re&1) r[l] = RC_CHAR(r[l]); - } -} - -uint32_t retrieve_u_cov(const ul_idx_t *ul, uint64_t id, uint8_t strand, uint64_t pos, uint8_t dir, int64_t *pi) -{ - uint64_t *a = ul->cc->interval.a + ul->cc->idx[id], cc = 0, ff = 0; - int64_t a_n = ul->cc->idx[id+1]-ul->cc->idx[id], k = 0, cc_i = pi? *pi:0; - if(a_n == 0) return 0; - if(cc_i + 1 >= a_n || cc_i < 0) cc_i = 0; - if(strand) pos = ul->ug->u.a[id].len - pos - 1; - if(dir == 0) { - for (k = cc_i; k + 1 < a_n; k++) { - if(pos>=(a[k]>>32) && pos<(a[k+1]>>32)) { - cc = (uint32_t)a[k]; - ff = 1; - break; - } - } - - if(ff == 0) { - for (k = 0; k < cc_i; k++) { - if(pos>=(a[k]>>32) && pos<(a[k+1]>>32)) { - cc = (uint32_t)a[k]; - ff = 1; - break; - } - } - } - } else { - for (k = cc_i; k >= 0; k--) { - if(pos>=(a[k]>>32) && pos<(a[k+1]>>32)) { - cc = (uint32_t)a[k]; - ff = 1; - break; - } - } - - if(ff == 0) { - for (k = cc_i+1; k + 1 < a_n; k++) { - if(pos>=(a[k]>>32) && pos<(a[k+1]>>32)) { - cc = (uint32_t)a[k]; - ff = 1; - break; - } - } - } - } - - if(pi) *pi = ff?k:0; - return cc; -} - -uint64_t retrieve_u_cov_region(const ul_idx_t *ul, uint64_t id, uint8_t strand, uint64_t s, uint64_t e, int64_t *pi) -{ - uint64_t *a = ul->cc->interval.a + ul->cc->idx[id], cc = 0, o = 0, tk, ts, te, tcc = 0; - int64_t a_n = ul->cc->idx[id+1]-ul->cc->idx[id], k = 0, cc_i = pi? *pi:0; - if(a_n == 0) return 0; - if(cc_i + 1 >= a_n || cc_i < 0) cc_i = 0; - if(strand) { - tk = s; - s = ul->ug->u.a[id].len - e; - e = ul->ug->u.a[id].len - tk; - } - // fprintf(stderr,"\nul->ug->u.a[id].len:%u, fs:%lu, fe:%lu\n", ul->ug->u.a[id].len, a[k]>>32, a[k+1]>>32); - k = cc_i; tk = s; - if(tk < (a[k]>>32)) { - for (; k >= 0; k--) { - if(tk>=(a[k]>>32) && tk<(a[k+1]>>32)) break; - } - } else if(tk >= (a[k+1]>>32)) { - for (; k + 1 < a_n; k++) { - if(tk>=(a[k]>>32) && tk<(a[k+1]>>32)) break; - } - } - if(pi) *pi = k; - - - - for (; k + 1 < a_n; k++) { - ts = a[k]>>32; te = a[k+1]>>32; cc = (uint32_t)a[k]; - o = (MIN(e, te) > MAX(s, ts))?(MIN(e, te)-MAX(s, ts)):0; - tcc += o*cc; - // fprintf(stderr, ">>k:%ld, s:%lu, e:%lu, ts:%lu, te:%lu, o:%lu, cc:%lu\n", k, s, e, ts, te, o, cc); - if(e>=(a[k]>>32) && e<(a[k+1]>>32)) break; - } - - // if(s == 54201 && e == 58376 && id == 492) fprintf(stderr, "tcc:%lu\n", tcc); - return tcc; -} - - -uint64_t retrieve_r_cov_region(const ul_idx_t *ul, uint64_t id, uint8_t strand, uint64_t s, uint64_t e, int64_t *pi) -{ - uint64_t *a = ul->cr->interval.a + ul->cr->idx[id], cc = 0, o = 0, tk, ts, te, tcc = 0; - int64_t a_n = ul->cr->idx[id+1]-ul->cr->idx[id], k = 0, cc_i = pi? *pi:0; - if(a_n == 0) return e>=s?e-s:0; - if(cc_i + 1 >= a_n || cc_i < 0) cc_i = 0; - if(strand) { - tk = s; - s = ul->ug->u.a[id].len - e; - e = ul->ug->u.a[id].len - tk; - } - // fprintf(stderr,"\nul->ug->u.a[id].len:%u, fs:%lu, fe:%lu\n", ul->ug->u.a[id].len, a[k]>>32, a[k+1]>>32); - k = cc_i; tk = s; - if(tk < (a[k]>>32)) { - for (; k >= 0; k--) { - if(tk>=(a[k]>>32) && tk<(a[k+1]>>32)) break; - } - } else if(tk >= (a[k+1]>>32)) { - for (; k + 1 < a_n; k++) { - if(tk>=(a[k]>>32) && tk<(a[k+1]>>32)) break; - } - } - if(pi) *pi = k; - if(k + 1 >= a_n) return e>=s?e-s:0; - if(k < 0) k = 0; - - ///note: for unitig coverage, all - for (; k + 1 < a_n; k++) { - // fprintf(stderr, "[M::%s] k:%ld, a_n:%ld\n", __func__, k, a_n); - ts = a[k]>>32; te = a[k+1]>>32; cc = (uint32_t)a[k]; - o = (MIN(e, te) > MAX(s, ts))?(MIN(e, te)-MAX(s, ts)):0; - tcc += o*cc; - // fprintf(stderr, ">>k:%ld, s:%lu, e:%lu, ts:%lu, te:%lu, o:%lu, cc:%lu\n", k, s, e, ts, te, o, cc); - if(e>=(a[k]>>32) && e<(a[k+1]>>32)) break; - if(e<=(a[k]>>32)) break;///if may happend when [s, e) does not overlap with the first region - } - - - return tcc + (e>=s?e-s:0); -} - -uint32_t produce_u_cov(ul_idx_t *ul, uint64_t id, uint8_t strand, uint64_t pos, ma_hit_t_alloc* src, int64_t min_ovlp, int64_t max_hang, int64_t gap_fuzz, -uint8_t *sset, kvec_t_u64_warp *buf) -{ - uint64_t k, l, i, z, s = 0, e = 0, qn, tn, qs, qe; - ma_utg_t *u = NULL; - int64_t dp, r; - asg_arc_t t; - - if(strand == (uint8_t)-1 || pos == (uint64_t)-1) { - u = &(ul->ug->u.a[id]); - buf->a.n = 0; kv_resize(uint64_t, buf->a, u->n*2); - for (k = l = 0; k < u->n; k++) { - kv_push(uint64_t, buf->a, l<<1); - kv_push(uint64_t, buf->a, ((l + Get_READ_LENGTH(R_INF, u->a[k]>>33))<<1)|1); - - - i = u->a[k]>>33;///rid - for (z = 0; z < src[i].length; z++) { - if(!src[i].buffer[z].el) continue; - qn = Get_qn(src[i].buffer[z]); tn = Get_tn(src[i].buffer[z]); - if(sset[tn]) continue; - if((Get_qe(src[i].buffer[z]) - Get_qs(src[i].buffer[z])) < min_ovlp) continue; - if((Get_te(src[i].buffer[z]) - Get_ts(src[i].buffer[z])) < min_ovlp) continue; - r = ma_hit2arc(&(src[i].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), - max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - if(r != MA_HT_TCONT) continue;///tn is contained - if(((u->a[k]>>32)&1) == 0) { - qs = Get_qs(src[i].buffer[z]); qe = Get_qe(src[i].buffer[z]); - } else { - qs = (Get_READ_LENGTH(R_INF, i)) - Get_qe(src[i].buffer[z]); - qe = (Get_READ_LENGTH(R_INF, i)) - Get_qs(src[i].buffer[z]); - } - kv_push(uint64_t, buf->a, (l+qs)<<1); - kv_push(uint64_t, buf->a, ((l+qe)<<1)|1); - } - - l += (uint32_t)u->a[k]; - } - sort_kvec_t_u64_warp(buf, 0); - return 0; - } - - if(strand) pos = ul->ug->u.a[id].len - pos - 1; - for (k = 0, dp = 0, s = e = 0; k < buf->a.n; k++) { - e = buf->a.a[k]>>1; - // fprintf(stderr, "[M::%s::k:%lu] [s, e)->[%lu, %lu), dp->%ld\n", __func__, k, s, e, dp); - if(pos >= s && pos < e) break; - s = buf->a.a[k]>>1; - if (buf->a.a[k]&1) --dp; - else ++dp; - } - - return dp; -} - - - -void produce_u_seq(char* r, ma_utg_t *u, UC_Read *buf) -{ - if(u->m == 0 || u->n == 0) return; - uint32_t j, k, l = 0; - uint32_t rId, ori, start, eLen, readLen; - char *readS = NULL; - memset(r, 'N', u->len); - for (j = 0; j < u->n; ++j) { - rId = u->a[j]>>33; - ///uId = i; - ori = u->a[j]>>32&1; - start = l; - eLen = (uint32_t)u->a[j]; - l += eLen; - - if(eLen == 0) continue; - recover_UC_Read(buf, &R_INF, rId); - - readS = buf->seq; - readLen = Get_READ_LENGTH(R_INF, rId); - - if (!ori) // forward strand - { - for (k = 0; k < eLen; k++) - { - r[start + k] = readS[k]; - } - } - else - { - for (k = 0; k < eLen; k++) - { - uint8_t c = (uint8_t)readS[readLen - 1 - k]; - r[start + k] = c >= 128? 'N' : RC_CHAR(c); - } - } - } -} - -void debug_retrieve_rc_sub(const ug_opt_t *uopt, all_ul_t *ref, const All_reads *R_INF, ul_idx_t *ul, uint32_t n_step) -{ - uint64_t i, step, s, e, occ, qc, rc; - UC_Read f, r; - init_UC_Read(&f); init_UC_Read(&r); - kvec_t(char) ss; kv_init(ss); - if(ref) { - for (i = 0, occ = 0; i < ref->n; i++) { - retrieve_ul_t(&f, NULL, ref, i, 0, 0, -1); - retrieve_ul_t(&r, NULL, ref, i, 1, 0, -1); - - kv_resize(char, ss, ref->a[i].rlen); - ss.n = ref->a[i].rlen; - memcpy(ss.a, r.seq, ss.n); - reverse_complement(ss.a, ss.n); - if(memcmp(ss.a, f.seq, ss.n)) { - fprintf(stderr, "1-Wrong whole reverse-read, id: %lu\n", i); - // for (s = 0; s < ss.n; s++) { - // if(ss.a[s] != f.seq[s]) { - // fprintf(stderr,"s:%lu, ss.a[s]:%c, f.seq[s]:%c, r.seq[rs]:%c\n", s, ss.a[s], f.seq[s], r.seq[ref->a[i].rlen - s - 1]); - // } - // } - } - - step = ss.n/n_step; - if(step <= 0) step = 1; - - for (s = 0; s < ss.n; s += step) { - e = MIN(s+step, ss.n); - retrieve_ul_t(NULL, ss.a, ref, i, 0, s, e-s); - if(memcmp(ss.a, f.seq + s, e - s)) { - fprintf(stderr, "1-Wrong sub forward-read, id: %lu, [%lu, %lu)\n", i, s, e); - } - - retrieve_ul_t(NULL, ss.a, ref, i, 1, s, e-s); - if(memcmp(ss.a, r.seq + s, e - s)) { - fprintf(stderr, "1-Wrong sub reverse-read, id: %lu, [%lu, %lu)\n", i, s, e); - // uint64_t dk; char *tf = ss.a; char *rf = r.seq + s; - // for (dk = 0; dk < e - s; dk++) { - // if(tf[dk] != rf[dk]) { - // fprintf(stderr,"dk:%lu, tf[dk]:%c, rf[dk]:%c\n", - // dk, tf[dk], rf[dk]); - // } - // } - } - occ++; - } - } - fprintf(stderr, "[M::%s::# checking: %lu] ==> all_ul_t\n", __func__, occ); - } - - - if(R_INF) { - for (i = 0, occ = 0; i < R_INF->total_reads; i++) { - recover_UC_Read(&f, R_INF, i); - recover_UC_Read_RC(&r, (All_reads*)R_INF, i); - kv_resize(char, ss, Get_READ_LENGTH((*R_INF), i)); - ss.n = Get_READ_LENGTH((*R_INF), i); - memcpy(ss.a, r.seq, ss.n); - reverse_complement(ss.a, ss.n); - if(memcmp(ss.a, f.seq, ss.n)) fprintf(stderr, "2-Wrong whole reverse-read, id: %lu\n", i); - - step = ss.n/n_step; - if(step <= 0) step = 1; - for (s = 0; s < ss.n; s += step) { - e = MIN(s+step, ss.n); - recover_UC_Read_sub_region(ss.a, s, e-s, 0, (All_reads*)R_INF, i); - if(memcmp(ss.a, f.seq + s, e - s)) fprintf(stderr, "2-Wrong sub forward-read, id: %lu, [%lu, %lu)\n", i, s, e); - - recover_UC_Read_sub_region(ss.a, s, e-s, 1, (All_reads*)R_INF, i); - if(memcmp(ss.a, r.seq + s, e - s)) fprintf(stderr, "2-Wrong sub reverse-read, id: %lu, [%lu, %lu)\n", i, s, e); - occ++; - } - } - fprintf(stderr, "[M::%s::# checking: %lu] ==> All_reads\n", __func__, occ); - } - - if(ul) { - - uint8_t *sset = NULL; CALLOC(sset, R_INF->total_reads); - for (i = 0; i < ul->ug->u.n; i++) { - for (s = 0; s < ul->ug->u.a[i].n; s++){ - sset[ul->ug->u.a[i].a[s]>>33] = 1; - } - } - - kvec_t_u64_warp buf; memset(&buf, 0, sizeof(buf)); int64_t pi = 0; - // produce_u_cov(ul, 0, (uint8_t)-1, (uint64_t)-1, &buf); - // produce_u_cov(ul, 0, 0, ul->ug->u.a[0].len>>1, &buf); - - for (i = 0, occ = 0; i < ul->ug->u.n; i++) { - kv_resize(char, ss, ul->ug->u.a[i].len); ss.n = ul->ug->u.a[i].len; - retrieve_u_seq(&f, NULL, &(ul->ug->u.a[i]), 0, 0, -1, NULL); - produce_u_seq(ss.a, &(ul->ug->u.a[i]), &r); - if(memcmp(ss.a, f.seq, ss.n)) fprintf(stderr, "4-Wrong whole reverse-read, id: %lu\n", i); - retrieve_u_seq(&r, NULL, &(ul->ug->u.a[i]), 1, 0, -1, NULL); - - memcpy(ss.a, r.seq, ss.n); - reverse_complement(ss.a, ss.n); - if(memcmp(ss.a, f.seq, ss.n)) fprintf(stderr, "3-Wrong whole reverse-read, id: %lu\n", i); - - produce_u_cov(ul, i, (uint8_t)-1, (uint64_t)-1, uopt->sources, uopt->min_ovlp, uopt->max_hang, uopt->gap_fuzz, sset, &buf); - step = ss.n/n_step; - if(step <= 0) step = 1; - - for (s = 0; s < ss.n; s += step) { - e = MIN(s+step, ss.n); - retrieve_u_seq(NULL, ss.a, &(ul->ug->u.a[i]), 0, s, e-s, NULL); - if(memcmp(ss.a, f.seq + s, e - s)) fprintf(stderr, "3-Wrong sub forward-read, id: %lu, [%lu, %lu)\n", i, s, e); - - retrieve_u_seq(NULL, ss.a, &(ul->ug->u.a[i]), 1, s, e-s, NULL); - if(memcmp(ss.a, r.seq + s, e - s)) fprintf(stderr, "3-Wrong sub reverse-read, id: %lu, [%lu, %lu)\n", i, s, e); - - /**if(ul->ug->u.a[i].n > 1)**/ { - rc = produce_u_cov(ul, i, 0, s, uopt->sources, uopt->min_ovlp, uopt->max_hang, uopt->gap_fuzz, sset, &buf); - - qc = retrieve_u_cov(ul, i, 0, s, 0, &pi); - if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); - pi++; - qc = retrieve_u_cov(ul, i, 0, s, 0, &pi); - if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); - pi--; - qc = retrieve_u_cov(ul, i, 0, s, 0, &pi); - if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); - pi++; - qc = retrieve_u_cov(ul, i, 0, s, 1, &pi); - if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); - pi--; - qc = retrieve_u_cov(ul, i, 0, s, 1, &pi); - if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); - - - - - rc = produce_u_cov(ul, i, 1, s, uopt->sources, uopt->min_ovlp, uopt->max_hang, uopt->gap_fuzz, sset, &buf); - qc = retrieve_u_cov(ul, i, 1, s, 0, &pi); - if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); - pi++; - qc = retrieve_u_cov(ul, i, 1, s, 0, &pi); - if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); - pi--; - qc = retrieve_u_cov(ul, i, 1, s, 0, &pi); - if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); - pi++; - qc = retrieve_u_cov(ul, i, 1, s, 1, &pi); - if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); - pi--; - qc = retrieve_u_cov(ul, i, 1, s, 1, &pi); - if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); - } - occ++; - } - } - - kv_destroy(buf.a); free(sset); - fprintf(stderr, "[M::%s::# checking: %lu] ==> ma_utg_v\n", __func__, occ); - } - - destory_UC_Read(&f); destory_UC_Read(&r); - kv_destroy(ss); -} - - -void write_compress_base_disk(FILE *fp, uint64_t ul_rid, char *str, uint32_t len, ul_vec_t *buf) -{ - buf->N_site.n = buf->bb.n = 0; buf->rlen = len; buf->r_base.n = B4L(len); - kv_resize(uint8_t, buf->r_base, buf->r_base.n); - ha_encode_base(buf->r_base.a, str, len, &(buf->N_site), 0); - - fwrite(&ul_rid, sizeof(ul_rid), 1, fp); - fwrite(&len, sizeof(len), 1, fp); - fwrite(&buf->N_site.n, sizeof(buf->N_site.n), 1, fp); - fwrite(buf->N_site.a, sizeof((*buf->N_site.a)), buf->N_site.n, fp); - fwrite(buf->r_base.a, sizeof((*buf->r_base.a)), buf->r_base.n, fp); -} - -int64_t load_compress_base_disk(FILE *fp, uint64_t *ul_rid, char *dest, uint32_t *len, ul_vec_t *buf) -{ - fread(ul_rid, sizeof((*ul_rid)), 1, fp); - if(feof(fp)) return 0; - fread(len, sizeof((*len)), 1, fp); - fread(&buf->N_site.n, sizeof(buf->N_site.n), 1, fp); - kv_resize(uint32_t, buf->N_site, buf->N_site.n); - fread(buf->N_site.a, sizeof((*buf->N_site.a)), buf->N_site.n, fp); - buf->r_base.n = B4L((*len)); kv_resize(uint8_t, buf->r_base, buf->r_base.n); - fread(buf->r_base.a, sizeof((*buf->r_base.a)), buf->r_base.n, fp); - - int64_t ssp, sep, sl, offset, begLen, tailLen, a_n, src_i, des_i, i; - ssp = 0; sep = (*len); sl = sep - ssp; - offset = ssp&3; begLen = 4-offset; - if(begLen > sl) begLen = sl; - tailLen = (sl-begLen)&3; - a_n = (sl - begLen - tailLen)>>2; - - src_i = ssp; i = 0; des_i = 0; - if(begLen > 0) { - memcpy(dest+des_i, bit_t_seq_table[buf->r_base.a[src_i>>2]]+offset, begLen); - des_i += begLen; src_i += begLen; - } - - for (i = 0; i < a_n; i++) { - memcpy(dest+des_i, bit_t_seq_table[buf->r_base.a[src_i>>2]], 4); - des_i += 4; src_i += 4; - } - - if(tailLen > 0) { - memcpy(dest+des_i, bit_t_seq_table[buf->r_base.a[src_i>>2]], tailLen); - des_i += tailLen; src_i += tailLen; - } - return 1; -} - - -scaf_res_t *init_scaf_res_t(uint32_t n) -{ - scaf_res_t *p = NULL; CALLOC(p, 1); - p->n = p->m = n; CALLOC(p->a, n); - return p; -} - -void destroy_scaf_res_t(scaf_res_t *p) -{ - if(p) { - uint32_t k; - for (k = 0; k < p->m; k++) { - free(p->a[k].N_site.a); free(p->a[k].r_base.a); free(p->a[k].bb.a); - } - free(p->a); - free(p); - } +#include +#include +#include +#include +#include "Process_Read.h" +#include "htab.h" +#include "Correct.h" +#include "kalloc.h" +#include + +#define UL_FLANK 512 +uint8_t seq_nt6_table[256] = { + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 0, 5, 1, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 0, 5, 1, 5, 5, 5, 2, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 +}; + +char bit_t_seq_table[256][4] = {{0}}; +char bit_t_seq_table_rc[256][4] = {{0}}; +char s_H[5] = {'A', 'C', 'G', 'T', 'N'}; +char rc_Table[6] = {'T', 'G', 'C', 'A', 'N', 'N'}; + +void init_All_reads(All_reads* r) +{ + memset(r, 0, sizeof(All_reads)); + r->index_size = READ_INIT_NUMBER; + r->read_length = (uint64_t*)malloc(sizeof(uint64_t)*r->index_size); + r->name_index_size = READ_INIT_NUMBER; + r->name_index = (uint64_t*)malloc(sizeof(uint64_t)*r->name_index_size); + r->name_index[0] = 0; +} + +void destory_All_reads(All_reads* r) +{ + uint64_t i = 0; + for (i = 0; i < r->tqn; i++) { + if (r->N_site[i]) free(r->N_site[i]); + if (r->read_sperate[i]) free(r->read_sperate[i]); + if (r->paf && r->paf[i].buffer) free(r->paf[i].buffer); + if (r->reverse_paf && r->reverse_paf[i].buffer) free(r->reverse_paf[i].buffer); + if(r->rsc && r->rsc[i]) free(r->rsc[i]); + } + for (; i < r->total_reads; i++) { + if (r->N_site[i]) free(r->N_site[i]); + if (r->read_sperate[i]) free(r->read_sperate[i]); + if (r->paf && r->paf[i].buffer) free(r->paf[i].buffer); + if (r->reverse_paf && r->reverse_paf[i].buffer) free(r->reverse_paf[i].buffer); + } + + free(r->paf); + free(r->reverse_paf); + free(r->N_site); + free(r->read_sperate); + free(r->name); + free(r->name_index); + free(r->read_length); + free(r->trio_flag); + free(r->rsc); + ///if (r->pb_regions) free(r->pb_regions); +} + +void write_All_reads(All_reads* r, char* read_file_name) +{ + fprintf(stderr, "Writing reads to disk... \n"); + char* index_name = (char*)malloc(strlen(read_file_name)+15); + sprintf(index_name, "%s.bin", read_file_name); + FILE* fp = fopen(index_name, "w"); + fwrite(&asm_opt.adapterLen, sizeof(asm_opt.adapterLen), 1, fp); + fwrite(&r->index_size, sizeof(r->index_size), 1, fp); + fwrite(&r->name_index_size, sizeof(r->name_index_size), 1, fp); + fwrite(&r->total_reads, sizeof(r->total_reads), 1, fp); + fwrite(&r->total_reads_bases, sizeof(r->total_reads_bases), 1, fp); + fwrite(&r->total_name_length, sizeof(r->total_name_length), 1, fp); + + uint64_t i = 0; + uint64_t zero = 0; + for (i = 0; i < r->total_reads; i++) + { + if (r->N_site[i] != NULL) + { + ///number of Ns + fwrite(&r->N_site[i][0], sizeof(r->N_site[i][0]), 1, fp); + if (r->N_site[i][0]) + { + fwrite(r->N_site[i]+1, sizeof(r->N_site[i][0]), r->N_site[i][0], fp); + } + } + else + { + fwrite(&zero, sizeof(zero), 1, fp); + } + } + + fwrite(r->read_length, sizeof(uint64_t), r->total_reads, fp); + for (i = 0; i < r->total_reads; i++) + { + fwrite(r->read_sperate[i], sizeof(uint8_t), r->read_length[i]/4+1, fp); + } + + fwrite(r->name, sizeof(char), r->total_name_length, fp); + fwrite(r->name_index, sizeof(uint64_t), r->name_index_size, fp); + fwrite(r->trio_flag, sizeof(uint8_t), r->total_reads, fp); + fwrite(&(asm_opt.hom_cov), sizeof(asm_opt.hom_cov), 1, fp); + fwrite(&(asm_opt.het_cov), sizeof(asm_opt.het_cov), 1, fp); + + uint64_t mm = 2;///1; + if(asm_opt.is_sc) { + fwrite(&mm, sizeof(mm), 1, fp); + fwrite(&(r->tqn), sizeof(r->tqn), 1, fp); + for (i = 0; i < r->tqn; i++) { + fwrite(r->rsc[i], sizeof(uint8_t), ((r->read_length[i]/sc_bn) + ((r->read_length[i]%sc_bn)?1:0)), fp); + } + } + + free(index_name); + fflush(fp); + fclose(fp); + fprintf(stderr, "Reads has been written.\n"); +} + +int load_All_reads(All_reads* r, char* read_file_name) +{ + char* index_name = (char*)malloc(strlen(read_file_name)+15); + sprintf(index_name, "%s.bin", read_file_name); + FILE* fp = fopen(index_name, "r"); + if (!fp) { + free(index_name); + return 0; + } + // fprintf(stderr, "[M::%s]\tindex_name::%s\n", __func__, index_name); + int local_adapterLen; + int f_flag; + f_flag = fread(&local_adapterLen, sizeof(local_adapterLen), 1, fp); + if(local_adapterLen != asm_opt.adapterLen) + { + fprintf(stderr, "the adapterLen of index is: %d, but the adapterLen set by user is: %d\n", + local_adapterLen, asm_opt.adapterLen); + exit(1); + } + f_flag += fread(&r->index_size, sizeof(r->index_size), 1, fp); + f_flag += fread(&r->name_index_size, sizeof(r->name_index_size), 1, fp); + f_flag += fread(&r->total_reads, sizeof(r->total_reads), 1, fp); + f_flag += fread(&r->total_reads_bases, sizeof(r->total_reads_bases), 1, fp); + f_flag += fread(&r->total_name_length, sizeof(r->total_name_length), 1, fp); + + uint64_t i = 0; + uint64_t zero = 0; + r->N_site = (uint64_t**)malloc(sizeof(uint64_t*)*r->total_reads); + for (i = 0; i < r->total_reads; i++) + { + f_flag += fread(&zero, sizeof(zero), 1, fp); + + if (zero) + { + r->N_site[i] = (uint64_t*)malloc(sizeof(uint64_t)*(zero + 1)); + r->N_site[i][0] = zero; + if (r->N_site[i][0]) + { + f_flag += fread(r->N_site[i]+1, sizeof(r->N_site[i][0]), r->N_site[i][0], fp); + } + } + else + { + r->N_site[i] = NULL; + } + } + + r->read_length = (uint64_t*)malloc(sizeof(uint64_t)*r->total_reads); + f_flag += fread(r->read_length, sizeof(uint64_t), r->total_reads, fp); + + r->read_size = (uint64_t*)malloc(sizeof(uint64_t)*r->total_reads); + memcpy (r->read_size, r->read_length, sizeof(uint64_t)*r->total_reads); + + r->read_sperate = (uint8_t**)malloc(sizeof(uint8_t*)*r->total_reads); + for (i = 0; i < r->total_reads; i++) + { + r->read_sperate[i] = (uint8_t*)malloc(sizeof(uint8_t)*(r->read_length[i]/4+1)); + f_flag += fread(r->read_sperate[i], sizeof(uint8_t), r->read_length[i]/4+1, fp); + } + + + r->name = (char*)malloc(sizeof(char)*r->total_name_length); + f_flag += fread(r->name, sizeof(char), r->total_name_length, fp); + + r->name_index = (uint64_t*)malloc(sizeof(uint64_t)*r->name_index_size); + f_flag += fread(r->name_index, sizeof(uint64_t), r->name_index_size, fp); + + /****************************may have bugs********************************/ + r->trio_flag = (uint8_t*)malloc(sizeof(uint8_t)*r->total_reads); + f_flag += fread(r->trio_flag, sizeof(uint8_t), r->total_reads, fp); + f_flag += fread(&(asm_opt.hom_cov), sizeof(asm_opt.hom_cov), 1, fp); + f_flag += fread(&(asm_opt.het_cov), sizeof(asm_opt.het_cov), 1, fp); + /****************************may have bugs********************************/ + + r->cigars = (Compressed_Cigar_record*)malloc(sizeof(Compressed_Cigar_record)*r->total_reads); + r->second_round_cigar = (Compressed_Cigar_record*)malloc(sizeof(Compressed_Cigar_record)*r->total_reads); + for (i = 0; i < r->total_reads; i++) + { + r->second_round_cigar[i].size = r->cigars[i].size = 0; + r->second_round_cigar[i].length = r->cigars[i].length = 0; + r->second_round_cigar[i].record = r->cigars[i].record = NULL; + + r->second_round_cigar[i].lost_base_size = r->cigars[i].lost_base_size = 0; + r->second_round_cigar[i].lost_base_length = r->cigars[i].lost_base_length = 0; + r->second_round_cigar[i].lost_base = r->cigars[i].lost_base = NULL; + } + ///r->pb_regions = NULL; + + uint64_t mm = 0; + if (!feof(fp)) { + if((fread(&mm, sizeof(mm), 1, fp)) && (mm == 1 || mm == 2)) { + if(mm == 1) { + mm = r->total_reads; + } else { + assert(mm == 2); + fread(&mm, sizeof(mm), 1, fp); + } + r->tqn = mm; + + MALLOC(r->rsc, r->tqn); + for (i = 0; i < r->tqn; i++) { + MALLOC(r->rsc[i], (r->read_length[i]/sc_bn) + ((r->read_length[i]%sc_bn)?1:0)); + f_flag += fread(r->rsc[i], sizeof(uint8_t), (r->read_length[i]/sc_bn) + ((r->read_length[i]%sc_bn)?1:0), fp); + } + } + } + + + + free(index_name); + fclose(fp); + fprintf(stderr, "Reads has been loaded.\n"); + + return 1; +} + +void read_ma(ma_hit_t* x, FILE* fp) +{ + int f_flag; + f_flag = fread(&(x->qns), sizeof(x->qns), 1, fp); + f_flag += fread(&(x->qe), sizeof(x->qe), 1, fp); + f_flag += fread(&(x->tn), sizeof(x->tn), 1, fp); + f_flag += fread(&(x->ts), sizeof(x->ts), 1, fp); + f_flag += fread(&(x->te), sizeof(x->te), 1, fp); + f_flag += fread(&(x->el), sizeof(x->el), 1, fp); + f_flag += fread(&(x->no_l_indel), sizeof(x->no_l_indel), 1, fp); + + uint32_t t; + f_flag += fread(&(t), sizeof(t), 1, fp); + x->ml = t; + + f_flag += fread(&(t), sizeof(t), 1, fp); + x->rev = t; + + f_flag += fread(&(t), sizeof(t), 1, fp); + x->bl = t; + + f_flag += fread(&(t), sizeof(t), 1, fp); + x->del = t; +} + + +int append_All_reads(All_reads* r, char *idx, uint32_t id) +{ + char *gfa_name = NULL; MALLOC(gfa_name, (strlen(idx)+100)); + FILE *fp = NULL, *fpo = NULL; + + sprintf(gfa_name, "%s.ec%u.bin", idx, id); + fp = fopen(gfa_name, "r"); + if (!fp) {free(gfa_name); return 0;} + + sprintf(gfa_name, "%s.ovlp%u.source.bin", idx, id); + fpo = fopen(gfa_name, "r"); + if (!fpo) {free(gfa_name); fclose(fp); return 0;} + free(gfa_name); + + int local_adapterLen, f_flag; + f_flag = fread(&local_adapterLen, sizeof(local_adapterLen), 1, fp); + if(local_adapterLen != asm_opt.adapterLen) { + fprintf(stderr, "[M::%s] the adapterLen of index is: %d, but the adapterLen set by user is: %d\n", + __func__, local_adapterLen, asm_opt.adapterLen); + exit(1); + } + uint64_t index_size0, name_index_size0, total_reads0, total_reads_bases0, total_name_length0; + index_size0 = r->index_size; + total_reads0 = r->total_reads; + total_reads_bases0 = r->total_reads_bases; + total_name_length0 = r->total_name_length; + name_index_size0 = ((total_reads0)?(total_reads0+1):(0));///r->name_index_size; + + f_flag += fread(&r->index_size, sizeof(r->index_size), 1, fp); + f_flag += fread(&r->name_index_size, sizeof(r->name_index_size), 1, fp); + f_flag += fread(&r->total_reads, sizeof(r->total_reads), 1, fp); + f_flag += fread(&r->total_reads_bases, sizeof(r->total_reads_bases), 1, fp); + f_flag += fread(&r->total_name_length, sizeof(r->total_name_length), 1, fp); + + r->index_size += index_size0; + r->name_index_size += name_index_size0; if(name_index_size0) r->name_index_size--; + r->total_reads += total_reads0; + r->total_reads_bases += total_reads_bases0; + r->total_name_length += total_name_length0; + + + uint64_t i = 0, zero = 0, k; + REALLOC(r->N_site, r->total_reads); + + for (i = total_reads0; i < r->total_reads; i++) { + f_flag += fread(&zero, sizeof(zero), 1, fp); + + if (zero) { + r->N_site[i] = (uint64_t*)malloc(sizeof(uint64_t)*(zero + 1)); + r->N_site[i][0] = zero; + if (r->N_site[i][0]) { + f_flag += fread(r->N_site[i]+1, sizeof(r->N_site[i][0]), r->N_site[i][0], fp); + } + } else { + r->N_site[i] = NULL; + } + } + + REALLOC(r->read_length, r->total_reads); + f_flag += fread(r->read_length + total_reads0, sizeof(uint64_t), r->total_reads-total_reads0, fp); + + REALLOC(r->read_size, r->total_reads); + memcpy (r->read_size + total_reads0, r->read_length + total_reads0, sizeof(uint64_t)*(r->total_reads-total_reads0)); + + REALLOC(r->read_sperate, r->total_reads); + for (i = total_reads0; i < r->total_reads; i++) { + r->read_sperate[i] = (uint8_t*)malloc(sizeof(uint8_t)*(r->read_length[i]/4+1)); + f_flag += fread(r->read_sperate[i], sizeof(uint8_t), r->read_length[i]/4+1, fp); + } + + + REALLOC(r->name, r->total_name_length); + f_flag += fread(r->name + total_name_length0, sizeof(char), r->total_name_length - total_name_length0, fp); + + REALLOC(r->name_index, r->name_index_size); uint64_t sft = 0; + if(name_index_size0) sft = r->name_index[--name_index_size0]; + // fprintf(stderr, "name_index_size0::%lu, total_reads0::%lu, sft::%lu\n", name_index_size0, total_reads0, sft); + f_flag += fread(r->name_index + name_index_size0, sizeof(uint64_t), r->name_index_size-name_index_size0, fp); + if(sft) { + for (i = name_index_size0; i < r->name_index_size; i++) r->name_index[i] += sft; + } + + /****************************may have bugs********************************/ + REALLOC(r->trio_flag, r->total_reads); + f_flag += fread(r->trio_flag + total_reads0, sizeof(uint8_t), r->total_reads - total_reads0, fp); + + int hom_cov0 = asm_opt.hom_cov, het_cov0 = asm_opt.het_cov; + f_flag += fread(&(asm_opt.hom_cov), sizeof(asm_opt.hom_cov), 1, fp); asm_opt.hom_cov += hom_cov0; + f_flag += fread(&(asm_opt.het_cov), sizeof(asm_opt.het_cov), 1, fp); asm_opt.het_cov += het_cov0; + /****************************may have bugs********************************/ + + REALLOC(r->cigars, r->total_reads); + REALLOC(r->second_round_cigar, r->total_reads); + for (i = total_reads0; i < r->total_reads; i++) { + r->second_round_cigar[i].size = r->cigars[i].size = 0; + r->second_round_cigar[i].length = r->cigars[i].length = 0; + r->second_round_cigar[i].record = r->cigars[i].record = NULL; + + r->second_round_cigar[i].lost_base_size = r->cigars[i].lost_base_size = 0; + r->second_round_cigar[i].lost_base_length = r->cigars[i].lost_base_length = 0; + r->second_round_cigar[i].lost_base = r->cigars[i].lost_base = NULL; + } + ///r->pb_regions = NULL; + + REALLOC(r->paf, r->total_reads); + memset(r->paf+total_reads0, 0, sizeof((*(r->paf)))*(r->total_reads - total_reads0)); + long long n_read; f_flag = fread(&n_read, sizeof(n_read), 1, fpo); ma_hit_t t; + for (i = total_reads0; i < r->total_reads; i++) { + f_flag += fread(&(r->paf[i].is_fully_corrected), sizeof(r->paf[i].is_fully_corrected), 1, fpo); + f_flag += fread(&(r->paf[i].is_abnormal), sizeof(r->paf[i].is_abnormal), 1, fpo); + f_flag += fread(&(r->paf[i].length), sizeof(r->paf[i].length), 1, fpo); + + if(r->paf[i].length == 0) continue; + for (k = 0; k < r->paf[i].length; k++) read_ma(&t, fpo); + r->paf[i].length = 0; + } + + REALLOC(r->reverse_paf, r->total_reads); + memset(r->reverse_paf+total_reads0, 0, sizeof((*(r->reverse_paf)))*(r->total_reads - total_reads0)); + + fclose(fp); fclose(fpo); + fprintf(stderr, "Reads has been loaded.\n"); + return 1; +} + + +int destory_read_bin(All_reads* r) +{ + + uint64_t i = 0; + for (i = 0; i < r->total_reads; i++) + { + if (r->N_site[i]) free(r->N_site[i]); + if (r->read_sperate[i]) free(r->read_sperate[i]); + if (r->cigars[i].record) free(r->cigars[i].record); + if (r->cigars[i].lost_base) free(r->cigars[i].lost_base); + if (r->second_round_cigar[i].record) free(r->second_round_cigar[i].record); + if (r->second_round_cigar[i].lost_base) free(r->second_round_cigar[i].lost_base); + } + + free(r->N_site); + free(r->read_length); + free(r->read_size); + free(r->read_sperate); + free(r->name); + free(r->name_index); + free(r->trio_flag); + free(r->cigars); + free(r->second_round_cigar); + return 1; +} + + + +void ha_insert_read_len(All_reads *r, int read_len, int name_len) +{ + r->total_reads++; + r->total_reads_bases += (uint64_t)read_len; + r->total_name_length += (uint64_t)name_len; + + // must +1 + if (r->index_size < r->total_reads + 2) { + r->index_size = r->index_size * 2 + 2; + r->read_length = (uint64_t*)realloc(r->read_length, sizeof(uint64_t) * r->index_size); + r->name_index_size = r->name_index_size * 2 + 2; + r->name_index = (uint64_t*)realloc(r->name_index, sizeof(uint64_t) * r->name_index_size); + } + + r->read_length[r->total_reads - 1] = read_len; + r->name_index[r->total_reads] = r->name_index[r->total_reads - 1] + name_len; +} + +void malloc_All_reads(All_reads *r) +{ + r->read_size = (uint64_t*)malloc(sizeof(uint64_t)*r->total_reads); + memcpy(r->read_size, r->read_length, sizeof(uint64_t)*r->total_reads); + + r->read_sperate = (uint8_t**)malloc(sizeof(uint8_t*)*r->total_reads); + if(asm_opt.is_sc && r->tqn) MALLOC(r->rsc, r->tqn); + assert(r->tqn <= r->total_reads); + + uint64_t i = 0; + if(r->rsc) { + for (i = 0; i < r->tqn; i++) { + MALLOC(r->read_sperate[i], (r->read_length[i]/4+1)); + MALLOC(r->rsc[i], (r->read_length[i]/sc_bn) + ((r->read_length[i]%sc_bn)?1:0)); + } + } + for (; i < r->total_reads; i++) { + MALLOC(r->read_sperate[i], (r->read_length[i]/4+1)); + } + + r->cigars = (Compressed_Cigar_record*)malloc(sizeof(Compressed_Cigar_record)*r->total_reads); + r->second_round_cigar = (Compressed_Cigar_record*)malloc(sizeof(Compressed_Cigar_record)*r->total_reads); + r->paf = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*r->total_reads); + r->reverse_paf = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*r->total_reads); + ///r->pb_regions = (kvec_t_u64_warp*)malloc(r->total_reads*sizeof(kvec_t_u64_warp)); + + for (i = 0; i < r->total_reads; i++) { + r->second_round_cigar[i].size = r->cigars[i].size = 0; + r->second_round_cigar[i].length = r->cigars[i].length = 0; + r->second_round_cigar[i].record = r->cigars[i].record = NULL; + + r->second_round_cigar[i].lost_base_size = r->cigars[i].lost_base_size = 0; + r->second_round_cigar[i].lost_base_length = r->cigars[i].lost_base_length = 0; + r->second_round_cigar[i].lost_base = r->cigars[i].lost_base = NULL; + init_ma_hit_t_alloc(&(r->paf[i])); + init_ma_hit_t_alloc(&(r->reverse_paf[i])); + ///kv_init(r->pb_regions[i].a); + } + + r->name = (char*)malloc(sizeof(char)*r->total_name_length); + r->N_site = (uint64_t**)calloc(r->total_reads, sizeof(uint64_t*)); + r->trio_flag = (uint8_t*)malloc(r->total_reads*sizeof(uint8_t)); + memset(r->trio_flag, AMBIGU, r->total_reads*sizeof(uint8_t)); +} + +void destory_UC_Read(UC_Read* r) +{ + free(r->seq); +} + +void init_aux_table() +{ + if (bit_t_seq_table[0][0] == 0) + { + uint64_t i = 0; + + for (i = 0; i < 256; i++) + { + bit_t_seq_table[i][0] = s_H[((i >> 6)&(uint64_t)3)]; + bit_t_seq_table[i][1] = s_H[((i >> 4)&(uint64_t)3)]; + bit_t_seq_table[i][2] = s_H[((i >> 2)&(uint64_t)3)]; + bit_t_seq_table[i][3] = s_H[(i&(uint64_t)3)]; + + bit_t_seq_table_rc[i][0] = RC_CHAR(bit_t_seq_table[i][3]); + bit_t_seq_table_rc[i][1] = RC_CHAR(bit_t_seq_table[i][2]); + bit_t_seq_table_rc[i][2] = RC_CHAR(bit_t_seq_table[i][1]); + bit_t_seq_table_rc[i][3] = RC_CHAR(bit_t_seq_table[i][0]); + } + } +} + +void init_UC_Read(UC_Read* r) +{ + r->length = 0; + r->size = 0; + r->seq = NULL; + if (bit_t_seq_table[0][0] == 0) + { + uint64_t i = 0; + + for (i = 0; i < 256; i++) + { + bit_t_seq_table[i][0] = s_H[((i >> 6)&(uint64_t)3)]; + bit_t_seq_table[i][1] = s_H[((i >> 4)&(uint64_t)3)]; + bit_t_seq_table[i][2] = s_H[((i >> 2)&(uint64_t)3)]; + bit_t_seq_table[i][3] = s_H[(i&(uint64_t)3)]; + + bit_t_seq_table_rc[i][0] = RC_CHAR(bit_t_seq_table[i][3]); + bit_t_seq_table_rc[i][1] = RC_CHAR(bit_t_seq_table[i][2]); + bit_t_seq_table_rc[i][2] = RC_CHAR(bit_t_seq_table[i][1]); + bit_t_seq_table_rc[i][3] = RC_CHAR(bit_t_seq_table[i][0]); + } + } +} + + +void recover_UC_Read_sub_region(char* r, int64_t start_pos, int64_t length, uint8_t strand, All_reads* R_INF, int64_t ID) +{ + int64_t readLen = Get_READ_LENGTH((*R_INF), ID); + int64_t end_pos = start_pos + length - 1, begLen, tailLen, offset, mn, src_i, des_i, i; + uint8_t* src = Get_READ((*R_INF), ID); + + if(strand == 0) { + offset = start_pos&3; + begLen = 4-offset; + if(begLen > length) begLen = length; + tailLen = (length-begLen)&3; + mn = (length - begLen - tailLen)>>2; + src_i = start_pos; des_i = 0; i = 0; + + if(begLen > 0) { + memcpy(r+des_i, bit_t_seq_table[src[src_i>>2]]+offset, begLen); + des_i += begLen; src_i += begLen; + } + + for (i = 0; i < mn; i++) { + memcpy(r+des_i, bit_t_seq_table[src[src_i>>2]], 4); + des_i += 4; src_i += 4; + } + + if(tailLen > 0) { + memcpy(r+des_i, bit_t_seq_table[src[src_i>>2]], tailLen); + des_i += tailLen; src_i += tailLen; + } + + if (R_INF->N_site[ID]) { + for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++) { + if ((long long)R_INF->N_site[ID][i] >= start_pos && (long long)R_INF->N_site[ID][i] <= end_pos) { + r[R_INF->N_site[ID][i] - start_pos] = 'N'; + } + else if((long long)R_INF->N_site[ID][i] > end_pos) { + break; + } + } + } + } + else { + start_pos = readLen - start_pos - 1; + end_pos = readLen - end_pos - 1; + + begLen = (start_pos+1)&3; + offset = 4 - begLen; + if(begLen > length) begLen = length; + tailLen = (length-begLen)&3; + mn = (length - begLen - tailLen)>>2; + src_i = start_pos; des_i = 0; i = 0; + + if(begLen > 0) { + memcpy(r+des_i, bit_t_seq_table_rc[src[src_i>>2]]+offset, begLen); + des_i += begLen; src_i -= begLen; + } + + for (i = 0; i < mn; i++) { + memcpy(r+des_i, bit_t_seq_table_rc[src[src_i>>2]], 4); + des_i += 4; src_i -= 4; + } + + if(tailLen > 0) { + memcpy(r+des_i, bit_t_seq_table_rc[src[src_i>>2]], tailLen); + des_i += tailLen; src_i -= tailLen; + } + + /** + if (R_INF->N_site[ID]) { + offset = readLen - start_pos - 1; + for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++) { + if ((long long)R_INF->N_site[ID][i] >= end_pos && (long long)R_INF->N_site[ID][i] <= start_pos) { + r[readLen - R_INF->N_site[ID][i] - 1 - offset] = 'N'; + } + else if((long long)R_INF->N_site[ID][i] > start_pos) { + break; + } + } + } + **/ + if (R_INF->N_site[ID]) { + start_pos = readLen - start_pos - 1; end_pos = readLen - end_pos - 1; + for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++) { + offset = readLen - R_INF->N_site[ID][i] - 1; + if(offset >= start_pos && offset <= end_pos) { + r[offset - start_pos] = 'N'; + } else if(offset < start_pos) { + break; + } + } + } + } +} + + +void recover_UC_sub_Read(UC_Read* i_r, long long start_pos, long long length, uint8_t strand, All_reads* R_INF, long long ID) +{ + i_r->length = length;i_r->RID = ID; + if (i_r->length + 8 > i_r->size) + { + i_r->size = i_r->length + 4; + i_r->seq = (char*)realloc(i_r->seq,sizeof(char)*(i_r->size)); + } + char* r = i_r->seq; + long long readLen = Get_READ_LENGTH((*R_INF), ID); + uint8_t* src = Get_READ((*R_INF), ID); + + long long i; + long long copyLen; + long long end_pos = start_pos + length - 1; + + if (strand == 0) + { + i = start_pos; + copyLen = 0; + + long long initLen = start_pos % 4; + + if (initLen != 0) + { + memcpy(r, bit_t_seq_table[src[i>>2]] + initLen, 4 - initLen); + copyLen = copyLen + 4 - initLen; + i = i + copyLen; + } + + while (copyLen < length) + { + memcpy(r+copyLen, bit_t_seq_table[src[i>>2]], 4); + copyLen = copyLen + 4; + i = i + 4; + } + + if (R_INF->N_site[ID]) + { + for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++) + { + if ((long long)R_INF->N_site[ID][i] >= start_pos && (long long)R_INF->N_site[ID][i] <= end_pos) + { + r[R_INF->N_site[ID][i] - start_pos] = 'N'; + } + else if((long long)R_INF->N_site[ID][i] > end_pos) + { + break; + } + } + } + } + else + { + start_pos = readLen - start_pos - 1; + end_pos = readLen - end_pos - 1; + + ///start_pos > end_pos + i = start_pos; + copyLen = 0; + long long initLen = (start_pos + 1) % 4; + + if (initLen != 0) + { + memcpy(r, bit_t_seq_table_rc[src[i>>2]] + 4 - initLen, initLen); + copyLen = copyLen + initLen; + i = i - initLen; + } + + while (copyLen < length) + { + memcpy(r+copyLen, bit_t_seq_table_rc[src[i>>2]], 4); + copyLen = copyLen + 4; + i = i - 4; + } + + if (R_INF->N_site[ID]) + { + long long offset = readLen - start_pos - 1; + + for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++) + { + if ((long long)R_INF->N_site[ID][i] >= end_pos && (long long)R_INF->N_site[ID][i] <= start_pos) + { + r[readLen - R_INF->N_site[ID][i] - 1 - offset] = 'N'; + } + else if((long long)R_INF->N_site[ID][i] > start_pos) + { + break; + } + } + } + } +} + + + + +void recover_UC_Read(UC_Read* r, const All_reads *R_INF, uint64_t ID) +{ + r->length = Get_READ_LENGTH((*R_INF), ID); + uint8_t* src = Get_READ((*R_INF), ID); + + if (r->length + 4 > r->size) { + r->size = r->length + 4; + r->seq = (char*)realloc(r->seq,sizeof(char)*(r->size)); + } + + uint64_t i = 0; + + if(src) { + while ((long long)i < r->length) { + memcpy(r->seq+i, bit_t_seq_table[src[i>>2]], 4); + i = i + 4; + } + + if (R_INF->N_site[ID]) { + for (i = 1; i <= R_INF->N_site[ID][0]; i++) r->seq[R_INF->N_site[ID][i]] = 'N'; + } + } else {///N + memset(r->seq, 'N', r->length); + } + + r->RID = ID; +} + +void recover_UC_Read_RC(UC_Read* r, All_reads* R_INF, uint64_t ID) +{ + r->length = Get_READ_LENGTH((*R_INF), ID); + uint8_t* src = Get_READ((*R_INF), ID); + + if (r->length + 4 > r->size) { + r->size = r->length + 4; + r->seq = (char*)realloc(r->seq,sizeof(char)*(r->size)); + } + + long long last_chr = r->length % 4; + long long i = r->length / 4 - 1 + (last_chr != 0); + long long index = 0; + + if(src) { + if(last_chr!=0) { + memcpy(r->seq + index, bit_t_seq_table_rc[src[i]] + 4 - last_chr, last_chr); + index = last_chr; + i--; + } + + while (i >= 0) { + memcpy(r->seq + index, bit_t_seq_table_rc[src[i]], 4); + i--; + index = index + 4; + } + + if (R_INF->N_site[ID]) { + for (i = 1; i <= (long long)R_INF->N_site[ID][0]; i++) { + r->seq[r->length - R_INF->N_site[ID][i] - 1] = 'N'; + } + } + } else {///N + memset(r->seq, 'N', r->length); + } + + +} + +#define COMPRESS_BASE {c = seq_nt6_table[(uint8_t)src[i]];\ + if (c >= 4)\ + {\ + c = 0;\ + (*N_site_lis)[N_site_i] = i;\ + N_site_i++;\ + }\ + i++;}\ + +void ha_compress_base(uint8_t* dest, char* src, uint64_t src_l, uint64_t** N_site_lis, uint64_t N_site_occ) +{ + ///N_site_lis saves the pos of all Ns in this read + ///N_site_lis[0] is the number of Ns + free((*N_site_lis)); + if (N_site_occ) + { + (*N_site_lis) = (uint64_t*)malloc(sizeof(uint64_t)*(N_site_occ + 1)); + (*N_site_lis)[0] = N_site_occ; + } + else + { + (*N_site_lis) = NULL; + } + + uint64_t i = 0; + uint64_t N_site_i = 1; + uint64_t dest_i = 0; + uint8_t tmp = 0; + uint8_t c = 0; + + while (i + 4 <= src_l) + { + tmp = 0; + + COMPRESS_BASE; + tmp = tmp | (c<<6); + + COMPRESS_BASE; + tmp = tmp | (c<<4); + + COMPRESS_BASE; + tmp = tmp | (c<<2); + + COMPRESS_BASE; + tmp = tmp | c; + + dest[dest_i] = tmp; + + dest_i++; + } + + //at most 3 bases here + uint64_t shift = 6; + if (i < src_l) + { + tmp = 0; + + while (i < src_l) + { + COMPRESS_BASE; + tmp = tmp | (c << shift); + shift = shift -2; + } + + dest[dest_i] = tmp; + dest_i++; + } +} + +void convert_qual(uint8_t* dest, char* src, uint64_t src_l, uint64_t bitu, uint64_t rev, uint64_t sc_off) +{ + uint64_t i = 0; uint8_t c = 0, sc; + // fprintf(stderr, "\n[M::%s]\n", __func__); + for (i = 0; i < src_l; i++) { + for (c = 0, sc = ((uint8_t)src[i]) - sc_off; (c < bitu) && (sc_tb[c] < sc); c++); + if(c >= bitu) c = bitu - 1; + dest[(rev?(src_l-i-1):(i))] = c; + // fprintf(stderr, "%u->%u\n", sc, c); + } +} + +void ha_compress_qual_bit(uint8_t* dest, char* src, uint64_t src_l, uint64_t bitn) +{ + + uint64_t i = 0, k, bit_r = 8/bitn, dest_i = 0; + uint8_t tmp = 0, c = 0; + + for (i = 0; i + bit_r <= src_l;) { + for (k = tmp = 0; k < bit_r; k++) { + c = ((uint8_t)src[i]); + tmp <<= bitn; tmp |= c; i++; + } + dest[dest_i++] = tmp; + } + + if(i < src_l) { + for (k = tmp = 0; i < src_l; k++) { + c = ((uint8_t)src[i]); + tmp <<= bitn; tmp |= c; i++; + } + + dest[dest_i++] = (tmp<<(8-(bitn*k))); + } +} + +void ha_compress_qual(uint8_t* dest, char* src, uint64_t src_l, uint64_t bitn, uint64_t sc_off) +{ + + uint64_t i = 0, k, bit_r = 8/bitn, dest_i = 0, bitu = (1<= bitu) c = bitu - 1; + tmp <<= bitn; tmp |= c; i++; + } + dest[dest_i++] = tmp; + } + + if(i < src_l) { + for (k = tmp = 0; i < src_l; k++) { + for (c = 0, sc = ((uint8_t)src[i]) - sc_off; (c < bitu) && (sc_tb[c] < sc); c++); + if(c >= bitu) c = bitu - 1; + tmp <<= bitn; tmp |= c; i++; + } + + dest[dest_i++] = (tmp<<(8-(bitn*k))); + } +} + +///[s, e) +int64_t retrive_bqual(asg8_v *dv, uint8_t *ds, uint64_t id, int64_t s, int64_t e, uint8_t rev, int64_t bitn) +{ + int64_t rl = Get_READ_LENGTH(R_INF, id), l; + if(s < 0) {s = 0;} if(e < 0) {e = rl;} + if(s >= e || e > rl) return -1; + + uint8_t *da = NULL, *src = Get_QUAL(R_INF, id), mm = (((uint8_t)1)<a; dv->n = l; + } else { + da = ds; + } + + if(!rev) { + dk = 0; sk = s; + + mrf = ((s%bitr)*bitn); + // if(s == 21519 && e == 22332) { + // fprintf(stderr, "+[M::%s] id::%lu, in::[%ld, %ld), rev::%u, bitn::%ld, bitr::%ld, mrf::%u\n", __func__, id, s, e, rev, bitn, bitr, mrf); + // } + if(mrf) { + for (swk = sk/bitr; mrf < 8 && sk < e; mrf += bitn, sk++) da[dk++] = ((src[swk]<>mlf)&mm; + } + + for (swk = sk/bitr; (sk + bitr) <= e; sk += bitr, swk++) { + for (mrf = 0; mrf < 8; mrf += bitn) da[dk++] = ((src[swk]<>mlf)&mm; + } + + if(sk < e) { + for (mrf = 0; sk < e; mrf += bitn, sk++) da[dk++] = ((src[swk]<>mlf)&mm; + } + // if(dk != l) { + // fprintf(stderr, "+[M::%s] id::%lu, in::[%ld, %ld), rev::%u, bitn::%ld, bitr::%ld\n", __func__, id, s, e, rev, bitn, bitr); + // } + assert(dk == l); + } else { + sk = s; s = e; e = sk; + s = rl - s; e = rl - e; + dk = l; sk = s; + + mrf = ((s%bitr)*bitn); + if(mrf) { + for (swk = sk/bitr; mrf < 8 && sk < e; mrf += bitn, sk++) da[--dk] = ((src[swk]<>mlf)&mm; + } + + for (swk = sk/bitr; (sk + bitr) <= e; sk += bitr, swk++) { + for (mrf = 0; mrf < 8; mrf += bitn) da[--dk] = ((src[swk]<>mlf)&mm; + } + + if(sk < e) { + for (mrf = 0; sk < e; mrf += bitn, sk++) da[--dk] = ((src[swk]<>mlf)&mm; + } + + assert(dk == 0); + } + + return l; +} + +void reverse_complement(char* pattern, uint64_t length) +{ + uint64_t i = 0; + uint64_t end = length / 2; + char k; + uint64_t index; + + for (i = 0; i < end; i++) + { + + index = length - i - 1; + k = pattern[index]; + pattern[index] = RC_CHAR(pattern[i]); + pattern[i] = RC_CHAR(k); + } + + if(length&(uint64_t)1) + { + pattern[end] = RC_CHAR(pattern[end]); + } +} + +void print_fastq(FILE *fp, char *id, char *bs, char *qual, uint64_t bitu, uint64_t sc_off) +{ + uint64_t i = 0, ql = strlen(qual); uint8_t c = 0, sc; + + if(fp) fprintf(fp, "@%s\n%s\n+\n", id, bs); + else fprintf(stdout, "@%s\n%s\n+\n", id, bs); + + for (i = 0; i < ql; i++) { + for (c = 0, sc = ((uint8_t)qual[i]) - sc_off; (c < bitu) && (sc_tb[c] < sc); c++); + if(c >= bitu) c = bitu - 1; + if(fp) fprintf(fp, "%u", c); + else fprintf(stdout, "%u", c); + } + + if(fp) fprintf(fp, "\n"); + else fprintf(stdout, "\n"); +} + + +void init_Debug_reads(Debug_reads* x, const char* file) +{ + int nameLen, i, bufLen = 1000; + if((uint64_t)(bufLen) < strlen(file) + 50) bufLen = strlen(file) + 50; + char* Name_Buffer = (char*)malloc(sizeof(char)*bufLen); + fprintf(stderr, "Queried debugging reads at: %s\n", file); + + x->fp = fopen(file,"r"); + x->query_num = 0; + + while(fgets(Name_Buffer, bufLen, x->fp)) + { + x->query_num++; + } + x->read_name = (char**)malloc(sizeof(char*)*x->query_num); + x->candidate_count = (kvec_t_u64_warp*)malloc(sizeof(kvec_t_u64_warp)*x->query_num); + x->read_id = NULL; MALLOC(x->read_id, x->query_num); + memset(x->read_id, -1, sizeof((*(x->read_id)))*x->query_num); + fseek(x->fp, 0, SEEK_SET); + + i = 0; + while(fgets(Name_Buffer, bufLen, x->fp)) + { + nameLen = strlen(Name_Buffer) - 1; + x->read_name[i] = (char*)malloc(sizeof(char)*(nameLen+1)); + memcpy(x->read_name[i], Name_Buffer, sizeof(char)*nameLen); + x->read_name[i][nameLen] = '\0'; + kv_init(x->candidate_count[i].a); + i++; + } + + fclose(x->fp); + + sprintf(Name_Buffer, "%s.debug.stdout", file); + x->fp = fopen(Name_Buffer,"w"); + fprintf(stderr, "Print debugging information to: %s\n", Name_Buffer); + + sprintf(Name_Buffer, "%s.debug.r0.fa", file); + x->fp_r0 = fopen(Name_Buffer,"w"); + fprintf(stderr, "Print raw reads to: %s\n", Name_Buffer); + + sprintf(Name_Buffer, "%s.debug.r1.fa", file); + x->fp_r1 = fopen(Name_Buffer,"w"); + fprintf(stderr, "Print corrected reads to: %s\n", Name_Buffer); + + free(Name_Buffer); +} + +void destory_Debug_reads(Debug_reads* x) +{ + uint64_t i; + for (i = 0; i < x->query_num; i++) + { + free(x->read_name[i]); + kv_destroy(x->candidate_count[i].a); + } + + free(x->read_name); free(x->read_id); + fclose(x->fp); fclose(x->fp_r0); fclose(x->fp_r1); +} + + +void init_all_ul_t(all_ul_t *x, All_reads *hR) { + memset(x, 0, sizeof(*x)); + x->hR = hR; + init_aux_table(); +} +void destory_all_ul_t(all_ul_t *x) { + uint64_t i; + for (i = 0; i < x->n; i++) { + free(x->a[i].N_site.a); free(x->a[i].r_base.a); free(x->a[i].bb.a); + } + free(x->a); + + for (i = 0; i < x->nid.n; i++) free(x->nid.a[i].a); + free(x->nid.a); + free(x->ridx.idx.a); free(x->ridx.occ.a); + + // if(x->mm) { + // for (i = 0; i < x->mm->n; i++) free(x->mm->a[i].a); + // free(x->mm->a); free(x->mm); x->mm = NULL; + // } +} + +void ha_encode_base(uint8_t* dest, char* src, uint64_t src_l, N_t *nn, uint64_t nn_offset) +{ + uint64_t i = 0; + uint64_t dest_i = 0; + uint8_t tmp = 0; + uint8_t c = 0; + + while (i + 4 <= src_l) { + tmp = 0; + // fprintf(stderr, "i->%lu, src_l->%ld, src[i]->%c, (uint8_t)src[i]->%u\n", i, src_l, src[i], (uint8_t)src[i]); + c = seq_nt6_table[(uint8_t)src[i]]; + if (c >= 4) { + c = 0; kv_push(uint32_t, *nn, i+nn_offset); + } + i++; + tmp = tmp | (c<<6); + + c = seq_nt6_table[(uint8_t)src[i]]; + if (c >= 4) { + c = 0; kv_push(uint32_t, *nn, i+nn_offset); + } + i++; + tmp = tmp | (c<<4); + + c = seq_nt6_table[(uint8_t)src[i]]; + if (c >= 4) { + c = 0; kv_push(uint32_t, *nn, i+nn_offset); + } + i++; + tmp = tmp | (c<<2); + + c = seq_nt6_table[(uint8_t)src[i]]; + if (c >= 4) { + c = 0; kv_push(uint32_t, *nn, i+nn_offset); + } + i++; + tmp = tmp | c; + + dest[dest_i] = tmp; + + dest_i++; + } + + //at most 3 bases here + uint64_t shift = 6; + if (i < src_l) { + tmp = 0; + while (i < src_l) { + c = seq_nt6_table[(uint8_t)src[i]]; + if (c >= 4) { + c = 0; kv_push(uint32_t, *nn, i+nn_offset); + } + i++; + tmp = tmp | (c << shift); + shift = shift -2; + } + + dest[dest_i] = tmp; + dest_i++; + } +} + +#define B4L(x) (((x)>>2)+(((x)&3)?1:0)) +void push_subblock_original_bases(char* str, all_ul_t *x, ul_vec_t *p, uint32_t s, uint32_t e, uint32_t subLen)//for debug +{ + uc_block_t *b = NULL; + uint32_t qs = s, qe = e; + while (qs < e) { + qe = qs + subLen; if(qe > e) qe = e; + kv_pushp(uc_block_t, p->bb, &b); + b->hid = (uint32_t)-1; b->rev = 0; + b->qs = qs; b->qe = qe; + b->ts = p->r_base.n; b->te = b->ts + B4L(b->qe - b->qs); + kv_resize(uint8_t, p->r_base, b->te); p->r_base.n = b->te; + ha_encode_base(p->r_base.a+b->ts, str+b->qs, b->qe-b->qs, &(p->N_site), b->qs); + + qs = qe; + } +} + +void append_ul_t_compress_ovlp(all_ul_t *x, uint64_t *rid, char* id, int64_t id_l, char* str, int64_t str_l, ul_ov_t *o, int64_t on) { + int64_t i, mine, maxs, ovlp, end; + ul_vec_t *p = NULL; + nid_t *np = NULL; + ul_ov_t *z = NULL, *zp = NULL; + uc_block_t *b = NULL; + + if(id) { + kv_pushp(nid_t, x->nid, &np); + np->n = id_l; MALLOC(np->a, np->n+1); memcpy(np->a, id, id_l); np->a[id_l] = '\0'; + } + + if(str) { + if(rid == NULL) { + kv_pushp(ul_vec_t, *x, &p); + memset(p, 0, sizeof(*p)); + } else { + if((*rid) >= x->m) kv_resize(ul_vec_t, *x, (*rid) + 1); + if((*rid) >= x->n) { + memset(x->a+x->n, 0, sizeof(*p)*((*rid) + 1 - x->n)); + x->n = (*rid) + 1; + } + p = &(x->a[(*rid)]); + } + + + p->bb.n = p->N_site.n = p->r_base.n = 0; + p->rlen = str_l; + + if(o == NULL || on == 0) on = 0; + for (i = end = 0, zp = NULL; i < on; i++) { + z = &(o[i]); + if(!z->el) continue; + if(zp) { + mine = MIN(zp->qe, z->qe); maxs = MAX(zp->qs, z->qs); + ovlp = mine - maxs; + if(zp->qe >= z->qe && zp->qs <= z->qs) continue; + } else { + ovlp = -z->qs; + } + if(ovlp < 0) {///push original bases + kv_pushp(uc_block_t, p->bb, &b); + b->hid = (uint32_t)-1/**x->mm**/; b->rev = 0; b->base = 1; b->pchain = 0; + b->qs = end; b->qe = b->qs - ovlp; + b->ts = p->r_base.n; b->te = b->ts + B4L(-ovlp); + kv_resize(uint8_t, p->r_base, b->te); p->r_base.n = b->te; + ha_encode_base(p->r_base.a+b->ts, str+b->qs, b->qe-b->qs, &(p->N_site), b->qs); + } + + ///push ovlp bases + kv_pushp(uc_block_t, p->bb, &b); + b->hid = (z->tn<<1)>>1; b->rev = z->rev; b->base = 0; b->pchain = 0; + b->qs = z->qs + (ovlp>0?ovlp:0); b->qe = z->qe; + if(z->rev) { + b->ts = z->ts; b->te = z->ts + (b->qe - b->qs); + } else { + b->ts = z->te - (b->qe - b->qs); b->te = z->te; + } + + end = MAX(zp?zp->qe:0, z->qe); + } + + if(end < str_l) {///push original bases + kv_pushp(uc_block_t, p->bb, &b); + b->hid = (uint32_t)-1/**x->mm**/; b->rev = 0; b->base = 1; b->pchain = 0; + b->qs = end; b->qe = str_l; + b->ts = p->r_base.n; b->te = b->ts + B4L(b->qe - b->qs); + kv_resize(uint8_t, p->r_base, b->te); p->r_base.n = b->te; + ha_encode_base(p->r_base.a+b->ts, str+b->qs, b->qe-b->qs, &(p->N_site), b->qs); + // push_subblock_original_bases(str, x, p, end, str_l, 321);//for debug + } + // char *sst = NULL; CALLOC(sst, str_l);//for debug + // retrieve_ul_t(NULL, sst, x, rid?*rid:x->n-1, 0, 0, -1); + // if(memcmp(sst, str, str_l)) { + // fprintf(stderr, "ap-Wrong read, id: %ld, [%d, %ld)\n", (int64_t)(rid?*rid:x->n-1), 0, str_l); + // for (i = 0; i < str_l; i++) { + // if(sst[i] != str[i]) fprintf(stderr, "[%ld] input:%c, decompress:%c\n", i, str[i], sst[i]); + // } + // } + // free(sst); + } +} + +void debug_append_ul_t(ul_ov_t *o, int64_t on, ul_vec_t *p) +{ + int64_t k, l = 0; + uint32_t sp = (uint32_t)-1, ep = (uint32_t)-1, qss, qee, m; + for (k = on-1; k >= 0; k--) { + if(sp == (uint32_t)-1 || o[k].qe <= sp) { + if(sp != (uint32_t)-1) l += ep - sp; + + if(sp == (uint32_t)-1) qss = o[k].qe, qee = p->rlen; + else qss = o[k].qe, qee = sp; + if(qee > qss) { + for (m = 0; m < p->bb.n; m++) { + if(qss == (p->bb.a[m].qs+((p->bb.a[m].hid>>15)&(0x7fffU))) && + qee == (p->bb.a[m].qe-(p->bb.a[m].hid&(0x7fffU)))) { + break; + } + } + if(m >= p->bb.n) fprintf(stderr, "ERROR\n"); + } + + sp = o[k].qs; + ep = o[k].qe; + } else { + sp = MIN(sp, o[k].qs); + } + } + if(sp != (uint32_t)-1) l += ep - sp; + + if(sp == (uint32_t)-1) qss = 0, qee = p->rlen; + else qss = 0, qee = sp; + if(qee > qss) { + for (m = 0; m < p->bb.n; m++) { + if(qss == (p->bb.a[m].qs+((p->bb.a[m].hid>>15)&(0x7fffU))) && + qee == (p->bb.a[m].qe-(p->bb.a[m].hid&(0x7fffU)))) { + break; + } + } + if(m >= p->bb.n) fprintf(stderr, "ERROR\n"); + } +} + +void append_ul_t_back(all_ul_t *x, uint64_t *rid, char* id, int64_t id_l, char* str, int64_t str_l, ul_ov_t *o, int64_t on, float p_chain_rate) { + int64_t i, mine, maxs, ovlp, st, et, bl = 0, pc = 0; + uint32_t o_l, o_r; + ul_vec_t *p = NULL; + nid_t *np = NULL; + ul_ov_t *z = NULL; + uc_block_t *b = NULL, tt; + + if(id) { + kv_pushp(nid_t, x->nid, &np); + np->n = id_l; MALLOC(np->a, np->n+1); memcpy(np->a, id, id_l); np->a[id_l] = '\0'; + } + + if(str||str_l) { + if(rid == NULL) { + kv_pushp(ul_vec_t, *x, &p); + memset(p, 0, sizeof(*p)); + } else { + if((*rid) >= x->m) kv_resize(ul_vec_t, *x, (*rid) + 1); + if((*rid) >= x->n) { + memset(x->a+x->n, 0, sizeof(*p)*((*rid) + 1 - x->n)); + x->n = (*rid) + 1; + } + p = &(x->a[(*rid)]); + } + // if((*rid) == 23) fprintf(stderr, "#rid->%lu, on->%ld\n", *rid, on); + + p->bb.n = p->N_site.n = p->r_base.n = 0; p->dd = 0; + p->rlen = str_l; + + if(o == NULL || on == 0) on = 0; + for (i = on-1, st = et = str_l; i >= 0; i--) { + z = &(o[i]); + if(z->el) { + mine = MIN(et, ((int64_t)z->qe)); maxs = MAX(st, ((int64_t)z->qs)); + ovlp = mine - maxs; + + if(ovlp < 0) {///push original bases + kv_pushp(uc_block_t, p->bb, &b); + b->hid = 0/**x->mm**/; b->rev = 0; b->base = 1; b->pchain = 0; b->el = 0; + b->qe = maxs; b->qs = b->qe + ovlp; bl += (b->qe-b->qs); + o_l = (b->qs >= UL_FLANK?UL_FLANK:b->qs); + o_r = ((str_l-b->qe)>=UL_FLANK?UL_FLANK:(str_l-b->qe)); + b->hid |= (o_l<<15); b->hid |= o_r; + b->qs -= o_l; b->qe += o_r; + b->ts = p->r_base.n; b->te = b->ts + B4L(b->qe-b->qs); + kv_resize(uint8_t, p->r_base, b->te); p->r_base.n = b->te; + // if(!str) fprintf(stderr, "+rid->%lu\n", *rid); + ha_encode_base(p->r_base.a+b->ts, str+b->qs, b->qe-b->qs, &(p->N_site), b->qs); + } + + st = MIN(st, z->qs); + } + + ///push ovlp bases + kv_pushp(uc_block_t, p->bb, &b); + b->hid = (z->tn<<1)>>1; b->rev = z->rev; b->base = 0; b->el = z->el; + b->pchain = ((z->tn&((uint32_t)(0x80000000)))?1:0); + b->qs = z->qs; b->qe = z->qe; + b->ts = z->ts; b->te = z->te; + if(b->pchain) pc++; + + // st = MIN(st, z->qs); + } + + if(st > 0) {///push original bases + kv_pushp(uc_block_t, p->bb, &b); + b->hid = 0/**x->mm**/; b->rev = 0; b->base = 1; b->pchain = 0; b->el = 0; + b->qe = st; b->qs = 0; bl += (b->qe-b->qs); + o_l = (b->qs >= UL_FLANK?UL_FLANK:b->qs); + o_r = ((str_l-b->qe)>=UL_FLANK?UL_FLANK:(str_l-b->qe)); + b->hid |= (o_l<<15); b->hid |= o_r; + b->qs -= o_l; b->qe += o_r; + b->ts = p->r_base.n; b->te = b->ts + B4L(b->qe-b->qs); + kv_resize(uint8_t, p->r_base, b->te); p->r_base.n = b->te; + // if(!str) fprintf(stderr, "-rid->%lu, st->%ld, str_l->%ld\n", *rid, st, str_l); + ha_encode_base(p->r_base.a+b->ts, str+b->qs, b->qe-b->qs, &(p->N_site), b->qs); + // push_subblock_original_bases(str, x, p, end, str_l, 321);//for debug + } + + if(pc > 0) p->dd = 3; + if((pc == on) && ((str_l-bl) > (str_l*p_chain_rate))) p->dd = 2; + if((pc == on) && (bl == 0)) p->dd = 1; + // debug_append_ul_t(o, on, p); + // char *sst = NULL; CALLOC(sst, str_l);//for debug + // retrieve_ul_t(NULL, sst, x, rid?*rid:x->n-1, 0, 0, -1); + // if(memcmp(sst, str, str_l)) { + // fprintf(stderr, "ap-Wrong read, id: %ld, [%d, %ld)\n", (int64_t)(rid?*rid:x->n-1), 0, str_l); + // for (i = 0; i < str_l; i++) { + // if(sst[i] != str[i]) fprintf(stderr, "[%ld] input:%c, decompress:%c\n", i, str[i], sst[i]); + // } + // } + // free(sst); + ovlp = p->bb.n>>1; + for (i = 0; i < ovlp; i++) { + tt = p->bb.a[i]; + p->bb.a[i] = p->bb.a[p->bb.n-i-1]; + p->bb.a[p->bb.n-i-1] = tt; + } + + } +} + + +void determine_chain_distance(ul_ov_t *o, int64_t on, ul_vec_t *p, ma_hit_t_alloc *src, int64_t max_hang, int64_t min_ovlp, int64_t rid) +{ + int64_t k, i, m, l = 0, r, last_i, last_dis; ul_ov_t *z = NULL; + uint32_t li_v, lj_v, t, qn, tn; ma_hit_t_alloc *x = NULL; asg_arc_t te; + + for (k = on-1; k >= 0; --k) { + z = &(o[k]); + if((!z->el) || (z->sec == SEC_MODE)) continue; + ///if z->el = 1, z->qn must work + if(p->bb.a[z->qn].pidx != (uint32_t)-1) continue; + last_i = -1; last_dis = 0; + for (i = k, l = 0; i >= 0;) { + assert((o[i].tn&((uint32_t)(0x80000000)))); + if(o[i].el) { + last_i = o[i].qn; last_dis = l; + } + m = i; i = o[i].sec; if(o[m].sec == SEC_MODE) i = -1; + // i = ((o[i].sec == SEC_MODE)?-1:o[i].sec); + if(i < 0) break; + // if(i >= on || i < 0) fprintf(stderr, "m->%ld, i->%ld, rid->%ld, on->%ld, o[m].sec->%u\n", m, i, rid, on, o[m].sec); + li_v = (o[m].tn<<1)|o[m].rev; li_v ^= 1; + lj_v = (o[i].tn<<1)|o[i].rev; lj_v ^= 1; + + x = &(src[li_v>>1]); + for (t = 0; t < x->length; t++) { + qn = Get_qn(x->buffer[t]); + tn = Get_tn(x->buffer[t]); + if(qn == (li_v>>1) && tn == (lj_v>>1)) { + r = ma_hit2arc(&(x->buffer[t]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), + max_hang, asm_opt.max_hang_rate, min_ovlp, &te); + if(r < 0) continue; + if((te.ul>>32) != li_v || te.v != lj_v) continue; + l += (uint32_t)te.ul; + break; + } + } + // if(t>=x->length) { + // fprintf(stderr, "m->%ld(id::%u), i->%ld(id::%u), rid->%ld, on->%ld\n", + // m, (o[m].tn<<1)>>1, i, (o[i].tn<<1)>>1, rid, on); + // // fprintf(stderr, "[i::%ld]id::%u\t\tq::[%u, %u)\tt::[%u, %u)\n", + // // i, o[i].tn, o[i].qs, o[i].qe, o[i].ts, o[i].te); + // // fprintf(stderr, "[m::%ld]id::%u\t\tq::[%u, %u)\tt::[%u, %u)\n", + // // m, o[m].tn, o[m].qs, o[m].qe, o[m].ts, o[m].te); + // fprintf(stderr, "[i::%ld]id::%u\t%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\n", + // i, (o[i].tn<<1)>>1, (int)Get_NAME_LENGTH(R_INF, ((o[i].tn<<1)>>1)), Get_NAME(R_INF, ((o[i].tn<<1)>>1)), + // "+-"[o[i].rev], o[i].qs, o[i].qe, o[i].ts, o[i].te); + // fprintf(stderr, "[m::%ld]id::%u\t%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\n", + // m, (o[m].tn<<1)>>1, (int)Get_NAME_LENGTH(R_INF, ((o[m].tn<<1)>>1)), Get_NAME(R_INF, ((o[m].tn<<1)>>1)), + // "+-"[o[m].rev], o[m].qs, o[m].qe, o[m].ts, o[m].te); + // exit(1); + // } + assert(tlength); + if(!(o[i].el)) continue; + assert(last_i>=0); + p->bb.a[last_i].pidx = o[i].qn; + p->bb.a[last_i].pdis = l - last_dis;///TODO: enable pdis + p->bb.a[p->bb.a[last_i].pidx].aidx = last_i; + } + } +} + +void append_ul_t(all_ul_t *x, uint64_t *rid, char* id, int64_t id_l, char* str, int64_t str_l, ul_ov_t *o, int64_t on, float p_chain_rate, const ug_opt_t *uopt, uint32_t save_bases) { + int64_t i, mine, maxs, ovlp, st, et, bl = 0, pc = 0, en = 0; + uint32_t o_l, o_r; + ul_vec_t *p = NULL; + nid_t *np = NULL; + ul_ov_t *z = NULL; + uc_block_t *b = NULL, tt; + + if(id) { + kv_pushp(nid_t, x->nid, &np); + np->n = id_l; MALLOC(np->a, np->n+1); memcpy(np->a, id, id_l); np->a[id_l] = '\0'; + } + + if(str||str_l) { + if(rid == NULL) { + kv_pushp(ul_vec_t, *x, &p); + memset(p, 0, sizeof(*p)); + } else { + if((*rid) >= x->m) kv_resize(ul_vec_t, *x, (*rid) + 1); + if((*rid) >= x->n) { + memset(x->a+x->n, 0, sizeof(*p)*((*rid) + 1 - x->n)); + x->n = (*rid) + 1; + } + p = &(x->a[(*rid)]); + } + // if((*rid) == 23) fprintf(stderr, "#rid->%lu, on->%ld\n", *rid, on); + + p->bb.n = p->N_site.n = p->r_base.n = 0; p->dd = 0; + p->rlen = str_l; + // fprintf(stderr, "str_l->%ld, str->%u\n", str_l, str?1:0); + + if(o == NULL || on == 0) {on = 0;} en = 0; + for (i = on-1, st = et = str_l; i >= 0; i--) { + z = &(o[i]); + if(z->el) { + if((z->tn&((uint32_t)(0x80000000)))) { + mine = MIN(et, ((int64_t)z->qe)); maxs = MAX(st, ((int64_t)z->qs)); + ovlp = mine - maxs; + if(ovlp < 0) bl -= ovlp; + if(save_bases && ovlp < 0) {///push original bases + kv_pushp(uc_block_t, p->bb, &b); + b->hid = 0/**x->mm**/; b->rev = 0; b->base = 1; b->pchain = 0; b->el = 0; + b->qe = maxs; b->qs = b->qe + ovlp; //bl += (b->qe-b->qs); + o_l = (b->qs >= UL_FLANK?UL_FLANK:b->qs); + o_r = ((str_l-b->qe)>=UL_FLANK?UL_FLANK:(str_l-b->qe)); + b->pidx = b->pdis = b->aidx = (uint32_t)-1; + b->hid |= (o_l<<15); b->hid |= o_r; + b->qs -= o_l; b->qe += o_r; + b->ts = p->r_base.n; b->te = b->ts + B4L(b->qe-b->qs); + kv_resize(uint8_t, p->r_base, b->te); p->r_base.n = b->te; + // fprintf(stderr, "\n+rid->%lu, str_l->%ld, b->qs->%u, b->qe->%u\n", *rid, str_l, b->qs, b->qe); + ha_encode_base(p->r_base.a+b->ts, str+b->qs, b->qe-b->qs, &(p->N_site), b->qs); + } + + st = MIN(st, z->qs); + } + + ///push ovlp bases + kv_pushp(uc_block_t, p->bb, &b); + b->hid = (z->tn<<1)>>1; b->rev = z->rev; b->base = 0; b->el = z->el; + b->pchain = ((z->tn&((uint32_t)(0x80000000)))?1:0); + b->qs = z->qs; b->qe = z->qe; + b->ts = z->ts; b->te = z->te; + if(b->pchain) pc++; + b->pidx = i; b->pdis = b->aidx = (uint32_t)-1; + en++; z->qn = p->bb.n - 1; + } + } + + if(st > 0) bl += st; + if(save_bases && st > 0) {///push original bases + kv_pushp(uc_block_t, p->bb, &b); + b->hid = 0/**x->mm**/; b->rev = 0; b->base = 1; b->pchain = 0; b->el = 0; + b->qe = st; b->qs = 0; //bl += (b->qe-b->qs); + o_l = (b->qs >= UL_FLANK?UL_FLANK:b->qs); + o_r = ((str_l-b->qe)>=UL_FLANK?UL_FLANK:(str_l-b->qe)); + b->pidx = b->pdis = b->aidx = (uint32_t)-1; + b->hid |= (o_l<<15); b->hid |= o_r; + b->qs -= o_l; b->qe += o_r; + b->ts = p->r_base.n; b->te = b->ts + B4L(b->qe-b->qs); + kv_resize(uint8_t, p->r_base, b->te); p->r_base.n = b->te; + // if(!str) fprintf(stderr, "-rid->%lu, st->%ld, str_l->%ld\n", *rid, st, str_l); + ha_encode_base(p->r_base.a+b->ts, str+b->qs, b->qe-b->qs, &(p->N_site), b->qs); + // push_subblock_original_bases(str, x, p, end, str_l, 321);//for debug + } + + if(pc > 0) p->dd = 3; + if((pc == en) && ((str_l-bl) > (str_l*p_chain_rate))) p->dd = 2; + if((pc == en) && (bl == 0)) p->dd = 1; + // debug_append_ul_t(o, on, p); + // char *sst = NULL; CALLOC(sst, str_l);//for debug + // retrieve_ul_t(NULL, sst, x, rid?*rid:x->n-1, 0, 0, -1); + // if(memcmp(sst, str, str_l)) { + // fprintf(stderr, "ap-Wrong read, id: %ld, [%d, %ld)\n", (int64_t)(rid?*rid:x->n-1), 0, str_l); + // for (i = 0; i < str_l; i++) { + // if(sst[i] != str[i]) fprintf(stderr, "[%ld] input:%c, decompress:%c\n", i, str[i], sst[i]); + // } + // } + // free(sst); + ovlp = p->bb.n>>1; + for (i = 0; i < ovlp; i++) { + tt = p->bb.a[i]; + p->bb.a[i] = p->bb.a[p->bb.n-i-1]; + p->bb.a[p->bb.n-i-1] = tt; + if(p->bb.a[i].pidx!=(uint32_t)-1) { + o[p->bb.a[i].pidx].qn = p->bb.n-o[p->bb.a[i].pidx].qn-1; + p->bb.a[i].pidx = (uint32_t)-1; + } + if(p->bb.a[p->bb.n-i-1].pidx!=(uint32_t)-1) { + o[p->bb.a[p->bb.n-i-1].pidx].qn = p->bb.n-o[p->bb.a[p->bb.n-i-1].pidx].qn-1; + p->bb.a[p->bb.n-i-1].pidx = (uint32_t)-1; + } + } + if(((uint32_t)p->bb.n)&1) { + o[p->bb.a[i].pidx].qn = p->bb.n-o[p->bb.a[i].pidx].qn-1; + p->bb.a[i].pidx = (uint32_t)-1; + } + + determine_chain_distance(o, on, p, uopt->sources, uopt->max_hang, uopt->min_ovlp, *rid); + } +} + +void retrieve_ul_t(UC_Read* i_r, char *i_s, all_ul_t *ref, uint64_t ID, uint8_t strand, int64_t s, int64_t l) { + ul_vec_t *p = &(ref->a[ID]); + if(l < 0) l = p->rlen; + uc_block_t *b = NULL; + char *r = NULL; + uint8_t *src = NULL; + int64_t k, i, a_n, e = s + l, ssp, sep, sl, rts, rte; + int64_t offset, begLen, tailLen, src_i, des_i; + if(i_r) { + i_r->length = l; i_r->RID = ID; + if(i_r->length > i_r->size) { + i_r->size = i_r->length; + i_r->seq = (char*)realloc(i_r->seq,sizeof(char)*(i_r->size)); + } + r = i_r->seq; + } + if(i_s) r = i_s; + + + + if(strand == 0) { + for (k = 0, des_i = 0; k < (int64_t)p->bb.n; k++) { + b = &(p->bb.a[k]); + if(b->qe <= s) continue; + if(b->qs >= e) break; + src = p->r_base.a + b->ts; + ssp = MAX(s, b->qs) - b->qs; + sep = MIN(e, b->qe) - b->qs; + sl = sep - ssp; + + if(b->base/**b->hid&ref->mm**/){///original bases + offset = ssp&3; + begLen = 4-offset; + if(begLen > sl) begLen = sl; + tailLen = (sl-begLen)&3; + a_n = (sl - begLen - tailLen)>>2; + + src_i = ssp; i = 0; + if(begLen > 0) { + memcpy(r+des_i, bit_t_seq_table[src[src_i>>2]]+offset, begLen); + des_i += begLen; src_i += begLen; + } + + for (i = 0; i < a_n; i++) { + memcpy(r+des_i, bit_t_seq_table[src[src_i>>2]], 4); + des_i += 4; src_i += 4; + } + + if(tailLen > 0) { + memcpy(r+des_i, bit_t_seq_table[src[src_i>>2]], tailLen); + des_i += tailLen; src_i += tailLen; + } + } else {///ovlps + if(b->rev == 0) { + recover_UC_Read_sub_region(r+des_i, b->ts + ssp, sep - ssp, b->rev, ref->hR, b->hid); + } else{ + rts = b->ts + (b->qe - sep); rte = rts + sep - ssp; + recover_UC_Read_sub_region(r+des_i, Get_READ_LENGTH((*ref->hR), b->hid) - rte, + sep - ssp, b->rev, ref->hR, b->hid); + } + des_i += sep - ssp; + } + } + for (k = 0; k < (int64_t)p->N_site.n; k++) { + if(p->N_site.a[k] >= s && p->N_site.a[k] < e){ + r[p->N_site.a[k]-s] = 'N'; + } + else if(p->N_site.a[k] >= e) { + break; + } + } + } else { + sep = p->rlen - s; + ssp = p->rlen - e; + s = ssp; e = sep; + ///[s, e) + for (k = ((int64_t)p->bb.n)-1, des_i = 0; k >= 0; k--) { + b = &(p->bb.a[k]); + if(b->qe <= s) break; + if(b->qs >= e) continue; + src = p->r_base.a + b->ts; + ssp = MAX(s, b->qs) - b->qs; + sep = MIN(e, b->qe) - b->qs; + sl = sep - ssp; + ///[ssp, sep) + + if(b->base/**b->hid&ref->mm**/){///original bases + begLen = sep&3; + offset = 4 - begLen; + if(begLen > sl) begLen = sl; + tailLen = (sl-begLen)&3; + a_n = (sl - begLen - tailLen)>>2; + src_i = sep-1; i = 0; + + if(begLen > 0) { + memcpy(r+des_i, bit_t_seq_table_rc[src[src_i>>2]]+offset, begLen); + des_i += begLen; src_i -= begLen; + } + + for (i = 0; i < a_n; i++) { + memcpy(r+des_i, bit_t_seq_table_rc[src[src_i>>2]], 4); + des_i += 4; src_i -= 4; + } + + if(tailLen > 0) { + memcpy(r+des_i, bit_t_seq_table_rc[src[src_i>>2]], tailLen); + des_i += tailLen; src_i -= tailLen; + } + } else {///ovlps + if(b->rev == 0) {///b->rev != strand + rts = b->ts + ssp; rte = rts + sep - ssp; + recover_UC_Read_sub_region(r+des_i, Get_READ_LENGTH((*ref->hR), b->hid) - rte, sep - ssp, 1, ref->hR, b->hid); + } else {///b->rev == strand + rts = b->ts + (b->qe - sep); rte = rts + sep - ssp; + recover_UC_Read_sub_region(r+des_i, rts, sep - ssp, 0, ref->hR, b->hid); + } + des_i += sep - ssp; + } + } + + sep = p->rlen - s; + ssp = p->rlen - e; + s = ssp; e = sep; + for (k = 0; k < (int64_t)p->N_site.n; k++) { + sl = p->rlen - p->N_site.a[k] - 1; + if(sl >= s && sl < e) r[sl-s] = 'N'; + else if(sl < s) { + break; + } + } + } +} + + +void retrieve_u_seq(UC_Read* i_r, char* i_s, ma_utg_t *u, uint8_t strand, int64_t s, int64_t l, void *km) +{ + if(u->m == 0 || u->n == 0) return; + if(l < 0) l = u->len; + char *r = NULL, *a = NULL; + int64_t e = s + l, ssp, sep, rs, re, des_i; + uint64_t k, rId, ori, r_l; + if(i_r) { + i_r->length = l; i_r->RID = 0; + if(i_r->length > i_r->size) { + i_r->size = i_r->length; + if(!km) REALLOC(i_r->seq, i_r->size); + else KREALLOC(km, i_r->seq, i_r->size); + // i_r->seq = (char*)realloc(i_r->seq,sizeof(char)*(i_r->size)); + } + r = i_r->seq; + } + if(i_s) r = i_s; + + if(strand == 1) { + sep = u->len - s; + ssp = u->len - e; + s = ssp; e = sep; + } + for (k = l = des_i = 0; k < u->n; k++) { + rId = u->a[k]>>33; + ori = u->a[k]>>32&1; + r_l = (uint32_t)u->a[k]; + if(r_l == 0) continue; + ssp = l; sep = l + r_l; + l += r_l; + if(sep <= s) continue; + if(ssp >= e) break; + rs = MAX(ssp, s); re = MIN(sep, e); + a = r + des_i; des_i += re - rs; + recover_UC_Read_sub_region(a, rs-ssp, re-rs, ori, &R_INF, rId); + } + if(strand == 1) { + char t; + re = (e - s); + l = re>>1; + for (k = 0; k < (uint64_t)l; k++) { + des_i = re - k - 1; + t = r[des_i]; + r[des_i] = RC_CHAR(r[k]); + r[k] = RC_CHAR(t); + } + if(re&1) r[l] = RC_CHAR(r[l]); + } +} + +uint32_t retrieve_u_cov(const ul_idx_t *ul, uint64_t id, uint8_t strand, uint64_t pos, uint8_t dir, int64_t *pi) +{ + uint64_t *a = ul->cc->interval.a + ul->cc->idx[id], cc = 0, ff = 0; + int64_t a_n = ul->cc->idx[id+1]-ul->cc->idx[id], k = 0, cc_i = pi? *pi:0; + if(a_n == 0) return 0; + if(cc_i + 1 >= a_n || cc_i < 0) cc_i = 0; + if(strand) pos = ul->ug->u.a[id].len - pos - 1; + if(dir == 0) { + for (k = cc_i; k + 1 < a_n; k++) { + if(pos>=(a[k]>>32) && pos<(a[k+1]>>32)) { + cc = (uint32_t)a[k]; + ff = 1; + break; + } + } + + if(ff == 0) { + for (k = 0; k < cc_i; k++) { + if(pos>=(a[k]>>32) && pos<(a[k+1]>>32)) { + cc = (uint32_t)a[k]; + ff = 1; + break; + } + } + } + } else { + for (k = cc_i; k >= 0; k--) { + if(pos>=(a[k]>>32) && pos<(a[k+1]>>32)) { + cc = (uint32_t)a[k]; + ff = 1; + break; + } + } + + if(ff == 0) { + for (k = cc_i+1; k + 1 < a_n; k++) { + if(pos>=(a[k]>>32) && pos<(a[k+1]>>32)) { + cc = (uint32_t)a[k]; + ff = 1; + break; + } + } + } + } + + if(pi) *pi = ff?k:0; + return cc; +} + +uint64_t retrieve_u_cov_region(const ul_idx_t *ul, uint64_t id, uint8_t strand, uint64_t s, uint64_t e, int64_t *pi) +{ + uint64_t *a = ul->cc->interval.a + ul->cc->idx[id], cc = 0, o = 0, tk, ts, te, tcc = 0; + int64_t a_n = ul->cc->idx[id+1]-ul->cc->idx[id], k = 0, cc_i = pi? *pi:0; + if(a_n == 0) return 0; + if(cc_i + 1 >= a_n || cc_i < 0) cc_i = 0; + if(strand) { + tk = s; + s = ul->ug->u.a[id].len - e; + e = ul->ug->u.a[id].len - tk; + } + // fprintf(stderr,"\nul->ug->u.a[id].len:%u, fs:%lu, fe:%lu\n", ul->ug->u.a[id].len, a[k]>>32, a[k+1]>>32); + k = cc_i; tk = s; + if(tk < (a[k]>>32)) { + for (; k >= 0; k--) { + if(tk>=(a[k]>>32) && tk<(a[k+1]>>32)) break; + } + } else if(tk >= (a[k+1]>>32)) { + for (; k + 1 < a_n; k++) { + if(tk>=(a[k]>>32) && tk<(a[k+1]>>32)) break; + } + } + if(pi) *pi = k; + + + + for (; k + 1 < a_n; k++) { + ts = a[k]>>32; te = a[k+1]>>32; cc = (uint32_t)a[k]; + o = (MIN(e, te) > MAX(s, ts))?(MIN(e, te)-MAX(s, ts)):0; + tcc += o*cc; + // fprintf(stderr, ">>k:%ld, s:%lu, e:%lu, ts:%lu, te:%lu, o:%lu, cc:%lu\n", k, s, e, ts, te, o, cc); + if(e>=(a[k]>>32) && e<(a[k+1]>>32)) break; + } + + // if(s == 54201 && e == 58376 && id == 492) fprintf(stderr, "tcc:%lu\n", tcc); + return tcc; +} + + +uint64_t retrieve_r_cov_region(const ul_idx_t *ul, uint64_t id, uint8_t strand, uint64_t s, uint64_t e, int64_t *pi) +{ + uint64_t *a = ul->cr->interval.a + ul->cr->idx[id], cc = 0, o = 0, tk, ts, te, tcc = 0; + int64_t a_n = ul->cr->idx[id+1]-ul->cr->idx[id], k = 0, cc_i = pi? *pi:0; + if(a_n == 0) return e>=s?e-s:0; + if(cc_i + 1 >= a_n || cc_i < 0) cc_i = 0; + if(strand) { + tk = s; + s = ul->ug->u.a[id].len - e; + e = ul->ug->u.a[id].len - tk; + } + // fprintf(stderr,"\nul->ug->u.a[id].len:%u, fs:%lu, fe:%lu\n", ul->ug->u.a[id].len, a[k]>>32, a[k+1]>>32); + k = cc_i; tk = s; + if(tk < (a[k]>>32)) { + for (; k >= 0; k--) { + if(tk>=(a[k]>>32) && tk<(a[k+1]>>32)) break; + } + } else if(tk >= (a[k+1]>>32)) { + for (; k + 1 < a_n; k++) { + if(tk>=(a[k]>>32) && tk<(a[k+1]>>32)) break; + } + } + if(pi) *pi = k; + if(k + 1 >= a_n) return e>=s?e-s:0; + if(k < 0) k = 0; + + ///note: for unitig coverage, all + for (; k + 1 < a_n; k++) { + // fprintf(stderr, "[M::%s] k:%ld, a_n:%ld\n", __func__, k, a_n); + ts = a[k]>>32; te = a[k+1]>>32; cc = (uint32_t)a[k]; + o = (MIN(e, te) > MAX(s, ts))?(MIN(e, te)-MAX(s, ts)):0; + tcc += o*cc; + // fprintf(stderr, ">>k:%ld, s:%lu, e:%lu, ts:%lu, te:%lu, o:%lu, cc:%lu\n", k, s, e, ts, te, o, cc); + if(e>=(a[k]>>32) && e<(a[k+1]>>32)) break; + if(e<=(a[k]>>32)) break;///if may happend when [s, e) does not overlap with the first region + } + + + return tcc + (e>=s?e-s:0); +} + +uint32_t produce_u_cov(ul_idx_t *ul, uint64_t id, uint8_t strand, uint64_t pos, ma_hit_t_alloc* src, int64_t min_ovlp, int64_t max_hang, int64_t gap_fuzz, +uint8_t *sset, kvec_t_u64_warp *buf) +{ + uint64_t k, l, i, z, s = 0, e = 0, qn, tn, qs, qe; + ma_utg_t *u = NULL; + int64_t dp, r; + asg_arc_t t; + + if(strand == (uint8_t)-1 || pos == (uint64_t)-1) { + u = &(ul->ug->u.a[id]); + buf->a.n = 0; kv_resize(uint64_t, buf->a, u->n*2); + for (k = l = 0; k < u->n; k++) { + kv_push(uint64_t, buf->a, l<<1); + kv_push(uint64_t, buf->a, ((l + Get_READ_LENGTH(R_INF, u->a[k]>>33))<<1)|1); + + + i = u->a[k]>>33;///rid + for (z = 0; z < src[i].length; z++) { + if(!src[i].buffer[z].el) continue; + qn = Get_qn(src[i].buffer[z]); tn = Get_tn(src[i].buffer[z]); + if(sset[tn]) continue; + if((Get_qe(src[i].buffer[z]) - Get_qs(src[i].buffer[z])) < min_ovlp) continue; + if((Get_te(src[i].buffer[z]) - Get_ts(src[i].buffer[z])) < min_ovlp) continue; + r = ma_hit2arc(&(src[i].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), + max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + if(r != MA_HT_TCONT) continue;///tn is contained + if(((u->a[k]>>32)&1) == 0) { + qs = Get_qs(src[i].buffer[z]); qe = Get_qe(src[i].buffer[z]); + } else { + qs = (Get_READ_LENGTH(R_INF, i)) - Get_qe(src[i].buffer[z]); + qe = (Get_READ_LENGTH(R_INF, i)) - Get_qs(src[i].buffer[z]); + } + kv_push(uint64_t, buf->a, (l+qs)<<1); + kv_push(uint64_t, buf->a, ((l+qe)<<1)|1); + } + + l += (uint32_t)u->a[k]; + } + sort_kvec_t_u64_warp(buf, 0); + return 0; + } + + if(strand) pos = ul->ug->u.a[id].len - pos - 1; + for (k = 0, dp = 0, s = e = 0; k < buf->a.n; k++) { + e = buf->a.a[k]>>1; + // fprintf(stderr, "[M::%s::k:%lu] [s, e)->[%lu, %lu), dp->%ld\n", __func__, k, s, e, dp); + if(pos >= s && pos < e) break; + s = buf->a.a[k]>>1; + if (buf->a.a[k]&1) --dp; + else ++dp; + } + + return dp; +} + + + +void produce_u_seq(char* r, ma_utg_t *u, UC_Read *buf) +{ + if(u->m == 0 || u->n == 0) return; + uint32_t j, k, l = 0; + uint32_t rId, ori, start, eLen, readLen; + char *readS = NULL; + memset(r, 'N', u->len); + for (j = 0; j < u->n; ++j) { + rId = u->a[j]>>33; + ///uId = i; + ori = u->a[j]>>32&1; + start = l; + eLen = (uint32_t)u->a[j]; + l += eLen; + + if(eLen == 0) continue; + recover_UC_Read(buf, &R_INF, rId); + + readS = buf->seq; + readLen = Get_READ_LENGTH(R_INF, rId); + + if (!ori) // forward strand + { + for (k = 0; k < eLen; k++) + { + r[start + k] = readS[k]; + } + } + else + { + for (k = 0; k < eLen; k++) + { + uint8_t c = (uint8_t)readS[readLen - 1 - k]; + r[start + k] = c >= 128? 'N' : RC_CHAR(c); + } + } + } +} + +void debug_retrieve_rc_sub(const ug_opt_t *uopt, all_ul_t *ref, const All_reads *R_INF, ul_idx_t *ul, uint32_t n_step) +{ + uint64_t i, step, s, e, occ, qc, rc; + UC_Read f, r; + init_UC_Read(&f); init_UC_Read(&r); + kvec_t(char) ss; kv_init(ss); + if(ref) { + for (i = 0, occ = 0; i < ref->n; i++) { + retrieve_ul_t(&f, NULL, ref, i, 0, 0, -1); + retrieve_ul_t(&r, NULL, ref, i, 1, 0, -1); + + kv_resize(char, ss, ref->a[i].rlen); + ss.n = ref->a[i].rlen; + memcpy(ss.a, r.seq, ss.n); + reverse_complement(ss.a, ss.n); + if(memcmp(ss.a, f.seq, ss.n)) { + fprintf(stderr, "1-Wrong whole reverse-read, id: %lu\n", i); + // for (s = 0; s < ss.n; s++) { + // if(ss.a[s] != f.seq[s]) { + // fprintf(stderr,"s:%lu, ss.a[s]:%c, f.seq[s]:%c, r.seq[rs]:%c\n", s, ss.a[s], f.seq[s], r.seq[ref->a[i].rlen - s - 1]); + // } + // } + } + + step = ss.n/n_step; + if(step <= 0) step = 1; + + for (s = 0; s < ss.n; s += step) { + e = MIN(s+step, ss.n); + retrieve_ul_t(NULL, ss.a, ref, i, 0, s, e-s); + if(memcmp(ss.a, f.seq + s, e - s)) { + fprintf(stderr, "1-Wrong sub forward-read, id: %lu, [%lu, %lu)\n", i, s, e); + } + + retrieve_ul_t(NULL, ss.a, ref, i, 1, s, e-s); + if(memcmp(ss.a, r.seq + s, e - s)) { + fprintf(stderr, "1-Wrong sub reverse-read, id: %lu, [%lu, %lu)\n", i, s, e); + // uint64_t dk; char *tf = ss.a; char *rf = r.seq + s; + // for (dk = 0; dk < e - s; dk++) { + // if(tf[dk] != rf[dk]) { + // fprintf(stderr,"dk:%lu, tf[dk]:%c, rf[dk]:%c\n", + // dk, tf[dk], rf[dk]); + // } + // } + } + occ++; + } + } + fprintf(stderr, "[M::%s::# checking: %lu] ==> all_ul_t\n", __func__, occ); + } + + + if(R_INF) { + for (i = 0, occ = 0; i < R_INF->total_reads; i++) { + recover_UC_Read(&f, R_INF, i); + recover_UC_Read_RC(&r, (All_reads*)R_INF, i); + kv_resize(char, ss, Get_READ_LENGTH((*R_INF), i)); + ss.n = Get_READ_LENGTH((*R_INF), i); + memcpy(ss.a, r.seq, ss.n); + reverse_complement(ss.a, ss.n); + if(memcmp(ss.a, f.seq, ss.n)) fprintf(stderr, "2-Wrong whole reverse-read, id: %lu\n", i); + + step = ss.n/n_step; + if(step <= 0) step = 1; + for (s = 0; s < ss.n; s += step) { + e = MIN(s+step, ss.n); + recover_UC_Read_sub_region(ss.a, s, e-s, 0, (All_reads*)R_INF, i); + if(memcmp(ss.a, f.seq + s, e - s)) fprintf(stderr, "2-Wrong sub forward-read, id: %lu, [%lu, %lu)\n", i, s, e); + + recover_UC_Read_sub_region(ss.a, s, e-s, 1, (All_reads*)R_INF, i); + if(memcmp(ss.a, r.seq + s, e - s)) fprintf(stderr, "2-Wrong sub reverse-read, id: %lu, [%lu, %lu)\n", i, s, e); + occ++; + } + } + fprintf(stderr, "[M::%s::# checking: %lu] ==> All_reads\n", __func__, occ); + } + + if(ul) { + + uint8_t *sset = NULL; CALLOC(sset, R_INF->total_reads); + for (i = 0; i < ul->ug->u.n; i++) { + for (s = 0; s < ul->ug->u.a[i].n; s++){ + sset[ul->ug->u.a[i].a[s]>>33] = 1; + } + } + + kvec_t_u64_warp buf; memset(&buf, 0, sizeof(buf)); int64_t pi = 0; + // produce_u_cov(ul, 0, (uint8_t)-1, (uint64_t)-1, &buf); + // produce_u_cov(ul, 0, 0, ul->ug->u.a[0].len>>1, &buf); + + for (i = 0, occ = 0; i < ul->ug->u.n; i++) { + kv_resize(char, ss, ul->ug->u.a[i].len); ss.n = ul->ug->u.a[i].len; + retrieve_u_seq(&f, NULL, &(ul->ug->u.a[i]), 0, 0, -1, NULL); + produce_u_seq(ss.a, &(ul->ug->u.a[i]), &r); + if(memcmp(ss.a, f.seq, ss.n)) fprintf(stderr, "4-Wrong whole reverse-read, id: %lu\n", i); + retrieve_u_seq(&r, NULL, &(ul->ug->u.a[i]), 1, 0, -1, NULL); + + memcpy(ss.a, r.seq, ss.n); + reverse_complement(ss.a, ss.n); + if(memcmp(ss.a, f.seq, ss.n)) fprintf(stderr, "3-Wrong whole reverse-read, id: %lu\n", i); + + produce_u_cov(ul, i, (uint8_t)-1, (uint64_t)-1, uopt->sources, uopt->min_ovlp, uopt->max_hang, uopt->gap_fuzz, sset, &buf); + step = ss.n/n_step; + if(step <= 0) step = 1; + + for (s = 0; s < ss.n; s += step) { + e = MIN(s+step, ss.n); + retrieve_u_seq(NULL, ss.a, &(ul->ug->u.a[i]), 0, s, e-s, NULL); + if(memcmp(ss.a, f.seq + s, e - s)) fprintf(stderr, "3-Wrong sub forward-read, id: %lu, [%lu, %lu)\n", i, s, e); + + retrieve_u_seq(NULL, ss.a, &(ul->ug->u.a[i]), 1, s, e-s, NULL); + if(memcmp(ss.a, r.seq + s, e - s)) fprintf(stderr, "3-Wrong sub reverse-read, id: %lu, [%lu, %lu)\n", i, s, e); + + /**if(ul->ug->u.a[i].n > 1)**/ { + rc = produce_u_cov(ul, i, 0, s, uopt->sources, uopt->min_ovlp, uopt->max_hang, uopt->gap_fuzz, sset, &buf); + + qc = retrieve_u_cov(ul, i, 0, s, 0, &pi); + if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); + pi++; + qc = retrieve_u_cov(ul, i, 0, s, 0, &pi); + if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); + pi--; + qc = retrieve_u_cov(ul, i, 0, s, 0, &pi); + if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); + pi++; + qc = retrieve_u_cov(ul, i, 0, s, 1, &pi); + if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); + pi--; + qc = retrieve_u_cov(ul, i, 0, s, 1, &pi); + if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); + + + + + rc = produce_u_cov(ul, i, 1, s, uopt->sources, uopt->min_ovlp, uopt->max_hang, uopt->gap_fuzz, sset, &buf); + qc = retrieve_u_cov(ul, i, 1, s, 0, &pi); + if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); + pi++; + qc = retrieve_u_cov(ul, i, 1, s, 0, &pi); + if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); + pi--; + qc = retrieve_u_cov(ul, i, 1, s, 0, &pi); + if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); + pi++; + qc = retrieve_u_cov(ul, i, 1, s, 1, &pi); + if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); + pi--; + qc = retrieve_u_cov(ul, i, 1, s, 1, &pi); + if(rc != qc) fprintf(stderr, "4-Wrong coverage, id: %lu, rc:%lu, qc:%lu, pos:%lu\n", i, rc, qc, s); + } + occ++; + } + } + + kv_destroy(buf.a); free(sset); + fprintf(stderr, "[M::%s::# checking: %lu] ==> ma_utg_v\n", __func__, occ); + } + + destory_UC_Read(&f); destory_UC_Read(&r); + kv_destroy(ss); +} + + +void write_compress_base_disk(FILE *fp, uint64_t ul_rid, char *str, uint32_t len, ul_vec_t *buf) +{ + buf->N_site.n = buf->bb.n = 0; buf->rlen = len; buf->r_base.n = B4L(len); + kv_resize(uint8_t, buf->r_base, buf->r_base.n); + ha_encode_base(buf->r_base.a, str, len, &(buf->N_site), 0); + + fwrite(&ul_rid, sizeof(ul_rid), 1, fp); + fwrite(&len, sizeof(len), 1, fp); + fwrite(&buf->N_site.n, sizeof(buf->N_site.n), 1, fp); + fwrite(buf->N_site.a, sizeof((*buf->N_site.a)), buf->N_site.n, fp); + fwrite(buf->r_base.a, sizeof((*buf->r_base.a)), buf->r_base.n, fp); +} + +int64_t load_compress_base_disk(FILE *fp, uint64_t *ul_rid, char *dest, uint32_t *len, ul_vec_t *buf) +{ + fread(ul_rid, sizeof((*ul_rid)), 1, fp); + if(feof(fp)) return 0; + fread(len, sizeof((*len)), 1, fp); + fread(&buf->N_site.n, sizeof(buf->N_site.n), 1, fp); + kv_resize(uint32_t, buf->N_site, buf->N_site.n); + fread(buf->N_site.a, sizeof((*buf->N_site.a)), buf->N_site.n, fp); + buf->r_base.n = B4L((*len)); kv_resize(uint8_t, buf->r_base, buf->r_base.n); + fread(buf->r_base.a, sizeof((*buf->r_base.a)), buf->r_base.n, fp); + + int64_t ssp, sep, sl, offset, begLen, tailLen, a_n, src_i, des_i, i; + ssp = 0; sep = (*len); sl = sep - ssp; + offset = ssp&3; begLen = 4-offset; + if(begLen > sl) begLen = sl; + tailLen = (sl-begLen)&3; + a_n = (sl - begLen - tailLen)>>2; + + src_i = ssp; i = 0; des_i = 0; + if(begLen > 0) { + memcpy(dest+des_i, bit_t_seq_table[buf->r_base.a[src_i>>2]]+offset, begLen); + des_i += begLen; src_i += begLen; + } + + for (i = 0; i < a_n; i++) { + memcpy(dest+des_i, bit_t_seq_table[buf->r_base.a[src_i>>2]], 4); + des_i += 4; src_i += 4; + } + + if(tailLen > 0) { + memcpy(dest+des_i, bit_t_seq_table[buf->r_base.a[src_i>>2]], tailLen); + des_i += tailLen; src_i += tailLen; + } + return 1; +} + + +scaf_res_t *init_scaf_res_t(uint32_t n) +{ + scaf_res_t *p = NULL; CALLOC(p, 1); + p->n = p->m = n; CALLOC(p->a, n); + return p; +} + +void destroy_scaf_res_t(scaf_res_t *p) +{ + if(p) { + uint32_t k; + for (k = 0; k < p->m; k++) { + free(p->a[k].N_site.a); free(p->a[k].r_base.a); free(p->a[k].bb.a); + } + free(p->a); + free(p); + } } \ No newline at end of file diff --git a/Process_Read.h b/Process_Read.h index 99d7e30..c728f71 100644 --- a/Process_Read.h +++ b/Process_Read.h @@ -1,275 +1,277 @@ -#ifndef __READ__ -#define __READ__ - -#define __STDC_LIMIT_MACROS -#include -#include -#include -#include -#include "Overlaps.h" -#include "CommandLines.h" -///#include "Hash_Table.h" - -#define READ_INIT_NUMBER 1000 - -#define READ_BLOCK_SIZE 64 -#define READ_BLOCK_NUM_PRE_THR 100 - -#define IS_FULL(buffer) ((buffer.num >= buffer.size)?1:0) -#define IS_EMPTY(buffer) ((buffer.num == 0)?1:0) -///#define Get_READ_LENGTH(R_INF, ID) (R_INF.index[ID+1] - R_INF.index[ID]) -#define Get_READ_LENGTH(R_INF, ID) (R_INF).read_length[(ID)] -#define Get_NAME_LENGTH(R_INF, ID) ((R_INF).name_index[(ID)+1] - (R_INF).name_index[(ID)]) -///#define Get_READ(R_INF, ID) R_INF.read + (R_INF.index[ID]>>2) + ID -#define Get_READ(R_INF, ID) (R_INF).read_sperate[(ID)] -#define Get_QUAL(R_INF, ID) (R_INF).rsc[(ID)] -#define Get_NAME(R_INF, ID) ((R_INF).name + (R_INF).name_index[(ID)]) -#define CHECK_BY_NAME(R_INF, NAME, ID) (Get_NAME_LENGTH((R_INF),(ID))==strlen((NAME)) && \ - memcmp((NAME), Get_NAME((R_INF), (ID)), Get_NAME_LENGTH((R_INF),(ID))) == 0) -#define IS_SCAF_READ(R_INF, ID) ((R_INF).read_sperate[(ID)] == NULL) - -extern uint8_t seq_nt6_table[256]; -extern char bit_t_seq_table[256][4]; -extern char bit_t_seq_table_rc[256][4]; -extern char s_H[5]; -extern char rc_Table[6]; - - -#define RC_CHAR(x) rc_Table[seq_nt6_table[(uint8_t)x]] - -void init_aux_table(); - -typedef struct { size_t n, m; uint8_t *a; } asg8_v; - -typedef struct -{ - uint64_t x_id; - uint64_t x_pos_s; - uint64_t x_pos_e; - uint8_t x_pos_strand; - - uint64_t y_id; - uint64_t y_pos_s; - uint64_t y_pos_e; - uint8_t y_pos_strand; - - uint64_t matchLen; - uint64_t totalLen; - -} PAF; - -typedef struct -{ - PAF* list; - uint64_t size; - uint64_t length; -} PAF_alloc; - - -inline void init_PAF_alloc(PAF_alloc* list) -{ - list->size = 15; - list->length = 0; - list->list = (PAF*)malloc(sizeof(PAF)*list->size); -} - -inline void append_PAF_alloc(PAF_alloc* list, PAF* e) -{ - if(list->length+1 > list->size) - { - list->size = list->size * 2; - list->list = (PAF*)realloc(list->list, sizeof(PAF)*list->size); - } - - list->list[list->length] = (*e); - list->length++; -} - -typedef struct -{ - /**[0-1] bits are type:**/ - /**[2-31] bits are length**/ - uint32_t* record; - uint32_t length; - uint32_t size; - - char* lost_base; - uint32_t lost_base_length; - uint32_t lost_base_size; - uint32_t new_length; -} Compressed_Cigar_record; - - -#define AMBIGU 0 -#define FATHER 1 -#define MOTHER 2 -#define MIX_TRIO 3 -#define NON_TRIO 4 -#define DROP 5 -#define SET_TRIO 8 -#define CHAIN_MATCH 1 -#define CHAIN_UNMATCH 0.334 - -#define NEC 1 - -typedef struct -{ - uint64_t** N_site; - ///uint8_t* read; - char* name; - - uint8_t** read_sperate; - uint64_t* read_length; - uint64_t* read_size; - uint8_t* trio_flag; - uint8_t** rsc; - - ///seq start pos in uint8_t* read - ///do not need it - ///uint64_t* index; - uint64_t index_size; - - ///name start pos in char* name - uint64_t* name_index; - uint64_t name_index_size; - uint64_t total_reads; - uint64_t total_reads_bases; - uint64_t total_name_length; - - Compressed_Cigar_record* cigars; - Compressed_Cigar_record* second_round_cigar; - - ma_hit_t_alloc* paf; - ma_hit_t_alloc* reverse_paf; - - ///kvec_t_u64_warp* pb_regions; -} All_reads; - -extern All_reads R_INF; - -typedef struct -{ - char* seq; - long long length; - long long size; - long long RID; -} UC_Read; - -typedef struct -{ - char** read_name; - uint64_t *read_id; - uint64_t query_num; - kvec_t_u64_warp* candidate_count; - FILE *fp, *fp_r0, *fp_r1; - pthread_mutex_t OutputMutex; -} Debug_reads; - - -typedef struct -{ - uint32_t hid; - uint32_t qs, qe, ts, te; uint32_t pidx, pdis, aidx;///TODO: enable pdis - uint8_t pchain:5, rev:1, base:1, el:1; -} uc_block_t; - -typedef struct -{ - uint32_t *a; - size_t n, m; -} N_t; - -typedef struct -{ - char *a; uint32_t n; -} nid_t; - -typedef struct -{ - kvec_t(uint8_t) r_base; - uint32_t rlen; - - kvec_t(uc_block_t) bb; - N_t N_site; - - uint8_t dd; -} ul_vec_t; - -typedef struct{ - kvec_t(uint32_t) idx; - kvec_t(uint64_t) occ; -} ul_vec_rid_t; - -typedef struct -{ - kvec_t(nid_t) nid; - ul_vec_rid_t ridx; - ul_vec_t *a; - size_t n, m; - All_reads *hR; - // idx_emask_t *mm; - // uint32_t mm; -} all_ul_t; - - -typedef struct { - ul_vec_t *a; - size_t n, m; - uint8_t dd; -} scaf_res_t; - -extern all_ul_t UL_INF; -extern all_ul_t ULG_INF; -// extern uint32_t *het_cnt; -// extern uint32_t debug_out; - -void init_All_reads(All_reads* r); -void malloc_All_reads(All_reads* r); -void ha_insert_read_len(All_reads *r, int read_len, int name_len); -void ha_compress_base(uint8_t* dest, char* src, uint64_t src_l, uint64_t** N_site_lis, uint64_t N_site_occ); -void ha_compress_qual(uint8_t* dest, char* src, uint64_t src_l, uint64_t bitn, uint64_t sc_off); -void init_UC_Read(UC_Read* r); -void recover_UC_Read(UC_Read* r, const All_reads *R_INF, uint64_t ID); -void recover_UC_Read_RC(UC_Read* r, All_reads* R_INF, uint64_t ID); -void recover_UC_Read_sub_region(char* r, int64_t start_pos, int64_t length, uint8_t strand, All_reads* R_INF, int64_t ID); -void destory_UC_Read(UC_Read* r); -void reverse_complement(char* pattern, uint64_t length); -void write_All_reads(All_reads* r, char* read_file_name); -int load_All_reads(All_reads* r, char* read_file_name); -int append_All_reads(All_reads* r, char *idx, uint32_t id); -void destory_All_reads(All_reads* r); -int destory_read_bin(All_reads* r); -void init_Debug_reads(Debug_reads* x, const char* file); -void destory_Debug_reads(Debug_reads* x); -void recover_UC_sub_Read(UC_Read* i_r, long long start_pos, long long length, uint8_t strand, All_reads* R_INF, long long ID); - -void init_all_ul_t(all_ul_t *x, All_reads *hR); -void destory_all_ul_t(all_ul_t *x); -void append_ul_t(all_ul_t *x, uint64_t *rid, char* id, int64_t id_l, char* str, int64_t str_l, ul_ov_t *o, int64_t on, float p_chain_rate, const ug_opt_t *uopt, uint32_t save_bases); -void retrieve_ul_t(UC_Read* i_r, char *i_s, all_ul_t *ref, uint64_t ID, uint8_t strand, int64_t s, int64_t l); -void retrieve_u_seq(UC_Read* i_r, char* i_s, ma_utg_t *u, uint8_t strand, int64_t s, int64_t l, void *km); -void debug_retrieve_rc_sub(const ug_opt_t *uopt, all_ul_t *ref, const All_reads *R_INF, ul_idx_t *ul, uint32_t n_step); -uint32_t retrieve_u_cov(const ul_idx_t *ul, uint64_t id, uint8_t strand, uint64_t pos, uint8_t dir, int64_t *pi); -uint64_t retrieve_u_cov_region(const ul_idx_t *ul, uint64_t id, uint8_t strand, uint64_t s, uint64_t e, int64_t *pi); -uint64_t retrieve_r_cov_region(const ul_idx_t *ul, uint64_t id, uint8_t strand, uint64_t s, uint64_t e, int64_t *pi); -void append_ul_t_back(all_ul_t *x, uint64_t *rid, char* id, int64_t id_l, char* str, int64_t str_l, ul_ov_t *o, int64_t on, float p_chain_rate); -void write_compress_base_disk(FILE *fp, uint64_t ul_rid, char *str, uint32_t len, ul_vec_t *buf); -int64_t load_compress_base_disk(FILE *fp, uint64_t *ul_rid, char *dest, uint32_t *len, ul_vec_t *buf); -scaf_res_t *init_scaf_res_t(uint32_t n); -void destroy_scaf_res_t(scaf_res_t *p); -void read_ma(ma_hit_t* x, FILE* fp); - -const uint64_t sc_tb[8] = { - 10, 20, 30, 40, 50, 60, 70, 80 -}; - -#define sc_bn 2 -#define sc_bm ((((uint64_t)1)< +#include +#include +#include +#include "Overlaps.h" +#include "CommandLines.h" +///#include "Hash_Table.h" + +#define READ_INIT_NUMBER 1000 + +#define READ_BLOCK_SIZE 64 +#define READ_BLOCK_NUM_PRE_THR 100 + +#define IS_FULL(buffer) ((buffer.num >= buffer.size)?1:0) +#define IS_EMPTY(buffer) ((buffer.num == 0)?1:0) +///#define Get_READ_LENGTH(R_INF, ID) (R_INF.index[ID+1] - R_INF.index[ID]) +#define Get_READ_LENGTH(R_INF, ID) (R_INF).read_length[(ID)] +#define Get_NAME_LENGTH(R_INF, ID) ((R_INF).name_index[(ID)+1] - (R_INF).name_index[(ID)]) +///#define Get_READ(R_INF, ID) R_INF.read + (R_INF.index[ID]>>2) + ID +#define Get_READ(R_INF, ID) (R_INF).read_sperate[(ID)] +#define Get_QUAL(R_INF, ID) (R_INF).rsc[(ID)] +#define Get_NAME(R_INF, ID) ((R_INF).name + (R_INF).name_index[(ID)]) +#define CHECK_BY_NAME(R_INF, NAME, ID) (Get_NAME_LENGTH((R_INF),(ID))==strlen((NAME)) && \ + memcmp((NAME), Get_NAME((R_INF), (ID)), Get_NAME_LENGTH((R_INF),(ID))) == 0) +#define IS_SCAF_READ(R_INF, ID) ((R_INF).read_sperate[(ID)] == NULL) + +extern uint8_t seq_nt6_table[256]; +extern char bit_t_seq_table[256][4]; +extern char bit_t_seq_table_rc[256][4]; +extern char s_H[5]; +extern char rc_Table[6]; + + +#define RC_CHAR(x) rc_Table[seq_nt6_table[(uint8_t)x]] + +void init_aux_table(); + +typedef struct { size_t n, m; uint8_t *a; } asg8_v; + +typedef struct +{ + uint64_t x_id; + uint64_t x_pos_s; + uint64_t x_pos_e; + uint8_t x_pos_strand; + + uint64_t y_id; + uint64_t y_pos_s; + uint64_t y_pos_e; + uint8_t y_pos_strand; + + uint64_t matchLen; + uint64_t totalLen; + +} PAF; + +typedef struct +{ + PAF* list; + uint64_t size; + uint64_t length; +} PAF_alloc; + + +inline void init_PAF_alloc(PAF_alloc* list) +{ + list->size = 15; + list->length = 0; + list->list = (PAF*)malloc(sizeof(PAF)*list->size); +} + +inline void append_PAF_alloc(PAF_alloc* list, PAF* e) +{ + if(list->length+1 > list->size) + { + list->size = list->size * 2; + list->list = (PAF*)realloc(list->list, sizeof(PAF)*list->size); + } + + list->list[list->length] = (*e); + list->length++; +} + +typedef struct +{ + /**[0-1] bits are type:**/ + /**[2-31] bits are length**/ + uint32_t* record; + uint32_t length; + uint32_t size; + + char* lost_base; + uint32_t lost_base_length; + uint32_t lost_base_size; + uint32_t new_length; +} Compressed_Cigar_record; + + +#define AMBIGU 0 +#define FATHER 1 +#define MOTHER 2 +#define MIX_TRIO 3 +#define NON_TRIO 4 +#define DROP 5 +#define SET_TRIO 8 +#define CHAIN_MATCH 1 +#define CHAIN_UNMATCH 0.334 + +#define NEC 1 + +typedef struct +{ + uint64_t** N_site; + ///uint8_t* read; + char* name; + + uint8_t** read_sperate; + uint64_t* read_length; + uint64_t* read_size; + uint8_t* trio_flag; + uint8_t** rsc; + + ///seq start pos in uint8_t* read + ///do not need it + ///uint64_t* index; + uint64_t index_size; + + ///name start pos in char* name + uint64_t* name_index; + uint64_t name_index_size; + uint64_t total_reads; + uint64_t tqn; + uint64_t total_reads_bases; + uint64_t total_name_length; + uint64_t tr[2]; + + Compressed_Cigar_record* cigars; + Compressed_Cigar_record* second_round_cigar; + + ma_hit_t_alloc* paf; + ma_hit_t_alloc* reverse_paf; + + ///kvec_t_u64_warp* pb_regions; +} All_reads; + +extern All_reads R_INF; + +typedef struct +{ + char* seq; + long long length; + long long size; + long long RID; +} UC_Read; + +typedef struct +{ + char** read_name; + uint64_t *read_id; + uint64_t query_num; + kvec_t_u64_warp* candidate_count; + FILE *fp, *fp_r0, *fp_r1; + pthread_mutex_t OutputMutex; +} Debug_reads; + + +typedef struct +{ + uint32_t hid; + uint32_t qs, qe, ts, te; uint32_t pidx, pdis, aidx;///TODO: enable pdis + uint8_t pchain:5, rev:1, base:1, el:1; +} uc_block_t; + +typedef struct +{ + uint32_t *a; + size_t n, m; +} N_t; + +typedef struct +{ + char *a; uint32_t n; +} nid_t; + +typedef struct +{ + kvec_t(uint8_t) r_base; + uint32_t rlen; + + kvec_t(uc_block_t) bb; + N_t N_site; + + uint8_t dd; +} ul_vec_t; + +typedef struct{ + kvec_t(uint32_t) idx; + kvec_t(uint64_t) occ; +} ul_vec_rid_t; + +typedef struct +{ + kvec_t(nid_t) nid; + ul_vec_rid_t ridx; + ul_vec_t *a; + size_t n, m; + All_reads *hR; + // idx_emask_t *mm; + // uint32_t mm; +} all_ul_t; + + +typedef struct { + ul_vec_t *a; + size_t n, m; + uint8_t dd; +} scaf_res_t; + +extern all_ul_t UL_INF; +extern all_ul_t ULG_INF; +// extern uint32_t *het_cnt; +// extern uint32_t debug_out; + +void init_All_reads(All_reads* r); +void malloc_All_reads(All_reads* r); +void ha_insert_read_len(All_reads *r, int read_len, int name_len); +void ha_compress_base(uint8_t* dest, char* src, uint64_t src_l, uint64_t** N_site_lis, uint64_t N_site_occ); +void ha_compress_qual(uint8_t* dest, char* src, uint64_t src_l, uint64_t bitn, uint64_t sc_off); +void init_UC_Read(UC_Read* r); +void recover_UC_Read(UC_Read* r, const All_reads *R_INF, uint64_t ID); +void recover_UC_Read_RC(UC_Read* r, All_reads* R_INF, uint64_t ID); +void recover_UC_Read_sub_region(char* r, int64_t start_pos, int64_t length, uint8_t strand, All_reads* R_INF, int64_t ID); +void destory_UC_Read(UC_Read* r); +void reverse_complement(char* pattern, uint64_t length); +void write_All_reads(All_reads* r, char* read_file_name); +int load_All_reads(All_reads* r, char* read_file_name); +int append_All_reads(All_reads* r, char *idx, uint32_t id); +void destory_All_reads(All_reads* r); +int destory_read_bin(All_reads* r); +void init_Debug_reads(Debug_reads* x, const char* file); +void destory_Debug_reads(Debug_reads* x); +void recover_UC_sub_Read(UC_Read* i_r, long long start_pos, long long length, uint8_t strand, All_reads* R_INF, long long ID); + +void init_all_ul_t(all_ul_t *x, All_reads *hR); +void destory_all_ul_t(all_ul_t *x); +void append_ul_t(all_ul_t *x, uint64_t *rid, char* id, int64_t id_l, char* str, int64_t str_l, ul_ov_t *o, int64_t on, float p_chain_rate, const ug_opt_t *uopt, uint32_t save_bases); +void retrieve_ul_t(UC_Read* i_r, char *i_s, all_ul_t *ref, uint64_t ID, uint8_t strand, int64_t s, int64_t l); +void retrieve_u_seq(UC_Read* i_r, char* i_s, ma_utg_t *u, uint8_t strand, int64_t s, int64_t l, void *km); +void debug_retrieve_rc_sub(const ug_opt_t *uopt, all_ul_t *ref, const All_reads *R_INF, ul_idx_t *ul, uint32_t n_step); +uint32_t retrieve_u_cov(const ul_idx_t *ul, uint64_t id, uint8_t strand, uint64_t pos, uint8_t dir, int64_t *pi); +uint64_t retrieve_u_cov_region(const ul_idx_t *ul, uint64_t id, uint8_t strand, uint64_t s, uint64_t e, int64_t *pi); +uint64_t retrieve_r_cov_region(const ul_idx_t *ul, uint64_t id, uint8_t strand, uint64_t s, uint64_t e, int64_t *pi); +void append_ul_t_back(all_ul_t *x, uint64_t *rid, char* id, int64_t id_l, char* str, int64_t str_l, ul_ov_t *o, int64_t on, float p_chain_rate); +void write_compress_base_disk(FILE *fp, uint64_t ul_rid, char *str, uint32_t len, ul_vec_t *buf); +int64_t load_compress_base_disk(FILE *fp, uint64_t *ul_rid, char *dest, uint32_t *len, ul_vec_t *buf); +scaf_res_t *init_scaf_res_t(uint32_t n); +void destroy_scaf_res_t(scaf_res_t *p); +void read_ma(ma_hit_t* x, FILE* fp); + +const uint64_t sc_tb[8] = { + 10, 20, 30, 40, 50, 60, 70, 80 +}; + +#define sc_bn 2 +#define sc_bm ((((uint64_t)1)< -#include -#include "ksort.h" -#include "Purge_Dups.h" -#include "Overlaps.h" -#include "Correct.h" -#include "kthread.h" -#include "kdq.h" -#include "hic.h" -#include "rcut.h" -#include "tovlp.h" - -KDQ_INIT(uint64_t) -KSORT_INIT_GENERIC(uint64_t) - -uint8_t debug_enable = 0; - -typedef struct { - uint64_t weight; - uint32_t x_beg_pos; - uint32_t x_end_pos; - uint32_t y_beg_pos; - uint32_t y_end_pos; - uint32_t index_beg; - uint32_t index_end; - long long score; - uint8_t rev; - asg_arc_t t; -}hap_candidates; - -typedef struct { - kvec_t(hap_candidates) a; - uint64_t i; -}kvec_hap_candidates; - - -typedef struct { - uint64_t* vote_counting; - uint8_t* visit; - kvec_t_u64_warp u_vecs; - kvec_asg_arc_t_offset u_buffer; - kvec_t_i32_warp u_buffer_tailIndex; - kvec_t_i32_warp u_buffer_prevIndex; - kvec_t_u8_warp u_buffer_flag; - kvec_t_i32_warp u_buffer_beg; - kvec_hap_candidates u_can; -}hap_alignment_struct; - - -typedef struct { - hap_alignment_struct* buf; - uint32_t num_threads; - uint8_t *hh; - ma_ug_t *ug; - asg_t *read_g; - ma_hit_t_alloc* sources; - ma_hit_t_alloc* reverse_sources; - R_to_U* ruIndex; - ma_sub_t *coverage_cut; - uint64_t* position_index; - float Hap_rate; - int max_hang; - int min_ovlp; - float chain_rate; - hap_overlaps_list* all_ovlp; - long long cov_threshold; - hap_cov_t *cov; -}hap_alignment_struct_pip; - -typedef struct { - uint32_t baseBeg, baseEnd; - uint32_t nodeBeg, nodeEnd; - uint32_t h_lev_idx; - uint32_t h_status, c_ug_id; -}p_node_t; - -typedef struct { - uint32_t beg; - uint32_t occ; -}p_g_in_t; - -typedef struct { - ma_ug_t *ug; - kvec_t(p_node_t) pg_het_node; - asg_t *pg_het; - asg_t *pg_h_lev; - kvec_t(p_g_in_t) pg_h_lev_idx; -}p_g_t; - -void print_peak_line(int c, int x, int exceed, int64_t cnt) -{ - int j; - if (c >= 0) fprintf(stderr, "[M::%s] %5d: ", __func__, c); - else fprintf(stderr, "[M::%s] %5s: ", __func__, "rest"); - for (j = 0; j < x; ++j) fputc('*', stderr); - if (exceed) fputc('>', stderr); - fprintf(stderr, " %lld\n", (long long)cnt); -} - -void print_peak(long long* cov_buf, long long cov_buf_length, long long max_i) -{ - long long i; - const long long hist_max = 100; - // print histogram - for (i = 0; i < cov_buf_length; ++i) - { - long long x, exceed = 0; - x = (int)((double)hist_max * cov_buf[i] / cov_buf[max_i] + .499); - if (x > hist_max) exceed = 1, x = hist_max; // may happen if cnt[2] is higher - if (i > max_i && x == 0) break; - print_peak_line(i, x, exceed, cov_buf[i]); - } - { - long long x, exceed = 0; - long long rest = 0; - for (; i < cov_buf_length; ++i) rest += cov_buf[i]; - x = (int)((double)hist_max * rest / cov_buf[max_i] + .499); - if (x > hist_max) exceed = 1, x = hist_max; - print_peak_line(-1, x, exceed, rest); - } -} - - -void get_read_peak(asg_t *read_g, long long* cov_buf, long long cov_buf_length, long long* topo_peak_cov, -long long* hom_peak, long long* het_peak, long long* k_mer_only, long long* coverage_only, long long g_size) -{ - long long i, start, err_i, max_i, max2_i, max3_i, topo_peak_i, max, max2, max3, topo_peak, min; - - i = start = err_i = max_i = max2_i = max3_i = topo_peak_i = -1; - max = max2 = max3 = topo_peak = min = -1; - - ///cov_buf[0] is usually very large - for (i = 1; i < cov_buf_length; ++i) - { - if(cov_buf[i] > cov_buf[i-1]) break; - } - err_i = i - 1; - // find the global highest peak - max_i = err_i + 1, max = cov_buf[max_i]; - for (i = max_i; i < cov_buf_length; ++i) - { - if (cov_buf[i] > max) - { - max = cov_buf[i]; - max_i = i; - } - } - - ///print_peak(cov_buf, cov_buf_length, max_i); - - // look for smaller peak on the low end - max2 = -1; max2_i = -1; - for (i = max_i - 1; i > err_i; --i) - { - ///at first, it should be a peak - if (cov_buf[i] >= cov_buf[i-1] && cov_buf[i] >= cov_buf[i+1]) - { - if (cov_buf[i] > max2) - { - max2 = cov_buf[i]; - max2_i = i; - } - } - } - - ///fprintf(stderr, "***max2: %lld, max2_i: %lld\n", max2, max2_i); - - if (max2_i != -1 && max2_i > err_i && max2_i < max_i) - { - for (i = max2_i + 1, min = max; i < max_i; ++i) - { - if (cov_buf[i] < min) min = cov_buf[i]; - } - - ///if the second peak is not significant - if(max2 < max * 0.05 || min > max2 * 0.95) max2 = max2_i = -1; - } - if(max2 < max*0.0075) max2 = max2_i = -1; - - - // look for smaller peak on the high end - max3 = -1; max3_i = -1; - // we'd better use i < cov_buf_length - 1, since cov_buf[cov_buf_length-1] may have problem - for (i = max_i + 1; i < cov_buf_length - 1; ++i) - { - //at first, it should be a peak - if (cov_buf[i] >= cov_buf[i-1] && cov_buf[i] >= cov_buf[i+1]) - { - if (cov_buf[i] > max3) - { - max3 = cov_buf[i], max3_i = i; - } - } - } - - ///fprintf(stderr, "***max3: %lld, max3_i: %lld\n", max3, max3_i); - - //if found a peak - if (max3 != -1 && max3_i > max_i) - { - for (i = max_i + 1, min = max; i < max3_i; ++i) - { - if (cov_buf[i] < min) min = cov_buf[i]; - } - - if (max3 < max * 0.05 || min > max3 * 0.95 || max3_i > max_i * 3) max3 = max3_i = -1; - } - if (max3 < max*0.0075) max3 = max3_i = -1; - - - - (*hom_peak) = (*het_peak) = -1; - if (topo_peak_cov && (*topo_peak_cov) < cov_buf_length) - { - topo_peak_i = (*topo_peak_cov); - topo_peak = cov_buf[topo_peak_i]; - if (topo_peak <= max * 0.05) topo_peak_i = topo_peak = -1; - } - - if(asm_opt.purge_level_primary == 0) - { - (*hom_peak) = max_i; - return; - } - - - long long k_mer_het, k_mer_hom, coverage_het, coverage_hom, alter_peak; - k_mer_het = k_mer_hom = coverage_het = coverage_hom = alter_peak = -1; - - alter_peak = topo_peak_i; - k_mer_het = asm_opt.het_cov; - k_mer_hom = asm_opt.hom_cov; - if(max3_i > 0) - { - coverage_het = max_i; - coverage_hom = max3_i; - } - else - { - coverage_het = max2_i; - coverage_hom = max_i; - } - - if(g_size > 0) { - long long n_bs, m_peak_hom = -1; - int p_ht = -1; - for (i = n_bs = 0; i < read_g->n_seq; i++) n_bs += read_g->seq[i].len; - m_peak_hom = n_bs/g_size; - if(m_peak_hom > 0) { - p_ht = -1; - coverage_hom = adj_m_peak_hom(m_peak_hom, max_i, max2_i, max3_i, &p_ht); - coverage_het = p_ht; - } - } - - if(k_mer_het != -1) - { - (*het_peak) = k_mer_het; - (*hom_peak) = k_mer_hom; - return; - } - else if(coverage_het != -1) - { - (*het_peak) = coverage_het; - (*hom_peak) = coverage_hom; - return; - } - else if(k_mer_hom > coverage_hom*1.5) - { - (*het_peak) = coverage_hom; - (*hom_peak) = k_mer_hom; - return; - } - else if(alter_peak != -1) - { - ///if peak is het, coverage peak is more reliable - if(coverage_hom >= alter_peak*0.8 && coverage_hom <= alter_peak*1.2) - { - (*het_peak) = coverage_hom; - return; - }///if peak is homo, k-mer peak is more reliable - else if(k_mer_hom >= alter_peak*0.8*2 && k_mer_hom <= alter_peak*1.2*2) - { - (*hom_peak) = k_mer_hom; - return; - } - } - - (*k_mer_only) = k_mer_hom; - (*coverage_only) = coverage_hom; - - - // fprintf(stderr, "max: %lld, max_i: %lld\n", max, max_i); - // fprintf(stderr, "max2: %lld, max2_i: %lld\n", max2, max2_i); - // fprintf(stderr, "max3: %lld, max3_i: %lld\n", max3, max3_i); - // fprintf(stderr, "[M::%s] Heterozygous k-mer peak: %d\n", __func__, asm_opt.het_cov); - // fprintf(stderr, "[M::%s] Homozygous k-mer peak: %d\n", __func__, asm_opt.hom_cov); - // fprintf(stderr, "[M::%s] Heterozygous coverage peak: %lld\n", __func__, (*het_peak)); - // fprintf(stderr, "[M::%s] Homozygous coverage peak: %lld\n", __func__, (*hom_peak)); - // fprintf(stderr, "[M::%s] Alter coverage peak: %lld\n", __func__, topo_peak_i); -} - - - - -long long get_alter_peak(ma_ug_t *ug, asg_t *read_g, R_to_U* ruIndex, uint64_t* position_index, -ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, long long cov_buf_length) -{ - - ma_utg_t* u = NULL; - asg_t* nsg = ug->g; - uint64_t v, j, k, qn, n_vtx = nsg->n_seq, primary_bases = 0, alter_bases = 0; - uint32_t tn, is_Unitig; - long long* cov_buf = NULL; - ma_hit_t *h; - cov_buf = (long long*)calloc(cov_buf_length, sizeof(long long)); - long long R_bases = 0, C_bases_primary = 0, C_bases_alter = 0, C_bases = 0; - memset(position_index, -1, sizeof(uint64_t)*read_g->n_seq); - - - for (v = 0; v < n_vtx; ++v) - { - if(nsg->seq[v].del) continue; - if(nsg->seq[v].c == ALTER_LABLE) continue; - u = &(ug->u.a[v]); - if(u->m == 0) continue; - for (k = 0; k < u->n; k++) - { - qn = u->a[k]>>33; - position_index[qn] = 0; - R_bases = coverage_cut[qn].e - coverage_cut[qn].s; - primary_bases += R_bases; - } - } - - for (qn = 0; qn < read_g->n_seq; qn++) - { - if(position_index[qn] == 0) continue; - if(read_g->seq[qn].del) continue; - - C_bases = C_bases_primary = C_bases_alter = 0; - R_bases = coverage_cut[qn].e - coverage_cut[qn].s; - alter_bases += R_bases; - for (j = 0; j < (uint64_t)(sources[qn].length); j++) - { - h = &(sources[qn].buffer[j]); - if(h->el != 1) continue; - tn = Get_tn((*h)); - - if(read_g->seq[tn].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - - if(position_index[tn] == 0) - { - C_bases_primary += Get_qe((*h)) - Get_qs((*h)); - } - else - { - C_bases_alter += Get_qe((*h)) - Get_qs((*h)); - } - } - - C_bases = C_bases_primary + C_bases_alter; - if(C_bases_alter < C_bases * ALTER_COV_THRES) continue; - - C_bases = C_bases/R_bases; - if(C_bases < 0 || C_bases >= cov_buf_length) continue; - cov_buf[C_bases]++; - } - - long long max_i = -1, max = -1; - for (j = 0; (long long)j < cov_buf_length; ++j) - { - if (cov_buf[j] > max) - { - max = cov_buf[j]; - max_i = j; - } - } - - if(alter_bases < primary_bases * REAL_ALTER_THRES) max_i = max = -1; - - free(cov_buf); - memset(position_index, -1, sizeof(uint64_t)*read_g->n_seq); - - return max_i; -} - -long long get_read_coverage_thres(ma_ug_t *ug, asg_t *read_g, R_to_U* ruIndex, uint64_t* position_index, -ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, uint64_t n_read, long long cov_buf_length, -long long* k_mer_only, long long* coverage_only) -{ - uint64_t i, j; - long long* cov_buf = NULL; - ma_hit_t *h; - cov_buf = (long long*)calloc(cov_buf_length, sizeof(long long)); - long long R_bases = 0, C_bases = 0; - for (i = 0; i < n_read; ++i) - { - C_bases = 0; - R_bases = coverage_cut[i].e - coverage_cut[i].s; - for (j = 0; j < (uint64_t)(sources[i].length); j++) - { - h = &(sources[i].buffer[j]); - if(h->el != 1) continue; - C_bases += Get_qe((*h)) - Get_qs((*h)); - } - C_bases = C_bases/R_bases; - if(C_bases < 0 || C_bases >= cov_buf_length) continue; - cov_buf[C_bases]++; - } - - long long alter_peak = -1, hom_peak = -1, het_peak = -1; - if(position_index) - { - alter_peak = get_alter_peak(ug, read_g, ruIndex, position_index, sources, coverage_cut, - cov_buf_length); - } - - get_read_peak(read_g, cov_buf, cov_buf_length, alter_peak == -1? NULL: &alter_peak, &hom_peak, &het_peak, - k_mer_only, coverage_only, asm_opt.hg_size); - - free(cov_buf); - - if(hom_peak != -1) return hom_peak*HOM_PEAK_RATE; - if(het_peak != -1) return het_peak*HET_PEAK_RATE; - return -1; -} - - - - - - - - - - -void init_hap_alignment_struct(hap_alignment_struct* x, uint32_t size) -{ - x->vote_counting = (uint64_t*)malloc(sizeof(uint64_t)*size); - memset(x->vote_counting, 0, sizeof(uint64_t)*size); - - x->visit = (uint8_t*)malloc(sizeof(uint8_t)*size); - memset(x->visit, 0, size); - - kv_init(x->u_vecs.a); - kv_init(x->u_buffer.a); - kv_init(x->u_buffer_tailIndex.a); - kv_init(x->u_buffer_prevIndex.a); - kv_init(x->u_buffer_beg.a); - kv_init(x->u_buffer_flag.a); - kv_init(x->u_can.a); -} - -void destory_hap_alignment_struct(hap_alignment_struct* x) -{ - free(x->vote_counting); - free(x->visit); - kv_destroy(x->u_vecs.a); - kv_destroy(x->u_buffer.a); - kv_destroy(x->u_buffer_tailIndex.a); - kv_destroy(x->u_buffer_prevIndex.a); - kv_destroy(x->u_buffer_beg.a); - kv_destroy(x->u_buffer_flag.a); - kv_destroy(x->u_can.a); -} - -uint8_t *init_pip_hh(asg_t *rg, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, long long sc) -{ - uint8_t *c = NULL; CALLOC(c, rg->n_seq); - ma_hit_t *h = NULL; - uint32_t i, k; - long long R_Base, C_Base; - for (i = 0; i < rg->n_seq; i++) { - if(sc <= 0){ - c[i] = 1; - continue; - } - R_Base = (coverage_cut[i].e - coverage_cut[i].s); - for (k = 0, C_Base = 0; k < reverse_sources[i].length; k++){ - h = &(reverse_sources[i].buffer[k]); - C_Base += (Get_qe((*h)) - Get_qs((*h))); - } - C_Base = (R_Base!=0?(C_Base/R_Base):0); - C_Base /= sc; - c[i] = 1; - if(C_Base < REV_W) c[i] = REV_W - C_Base; - } - return c; -} - -void init_hap_alignment_struct_pip(hap_alignment_struct_pip* x, uint32_t num_threads, uint32_t n_seq, -ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, ma_sub_t *coverage_cut, -uint64_t* position_index, float Hap_rate, int max_hang, int min_ovlp, float chain_rate, hap_overlaps_list* all_ovlp, hap_cov_t *cov) -{ - uint32_t i; - x->num_threads = num_threads; - x->buf = (hap_alignment_struct*)malloc(sizeof(hap_alignment_struct)*x->num_threads); - for (i = 0; i < x->num_threads; i++) - { - init_hap_alignment_struct(&(x->buf[i]), n_seq); - } - - x->ug = ug; - x->read_g = read_g; - x->sources = sources; - x->reverse_sources = reverse_sources; - x->ruIndex = ruIndex; - x->coverage_cut = coverage_cut; - x->position_index = position_index; - x->Hap_rate = Hap_rate; - x->max_hang = max_hang; - x->min_ovlp = min_ovlp; - x->chain_rate = chain_rate; - x->all_ovlp = all_ovlp; - x->cov = cov; - long long sc = -1; - if(asm_opt.hom_global_coverage_set) { - sc = asm_opt.hom_global_coverage*1.75; - } - else { - if(asm_opt.hom_global_coverage > 0){ - sc = ((int)(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE)))*1.75; - } - } - if(sc <= 0) sc = -1; - x->hh = init_pip_hh(read_g, reverse_sources, coverage_cut, sc); -} - - -void destory_hap_alignment_struct_pip(hap_alignment_struct_pip* x) -{ - uint32_t i; - for (i = 0; i < x->num_threads; i++) - { - destory_hap_alignment_struct(&(x->buf[i])); - } - - free(x->buf); - free(x->hh); -} - -void init_hap_overlaps_list(hap_overlaps_list* x, uint32_t num) -{ - uint32_t i = 0; - x->num = num; - x->x = (kvec_hap_overlaps*)malloc(sizeof(kvec_hap_overlaps)*x->num); - for (i = 0; i < x->num; i++) - { - kv_init(x->x[i].a); - } -} - -void enable_debug_mode(uint32_t mode) -{ - debug_enable = mode; -} - -void destory_hap_overlaps_list(hap_overlaps_list* x) -{ - uint32_t i = 0; - for (i = 0; i < x->num; i++) - { - kv_destroy(x->x[i].a); - } - free(x->x); -} - - - -inline void clean_visit_flag(uint8_t* visit, asg_t *read_g, R_to_U* ruIndex, uint32_t contigNum, -ma_hit_t_alloc* x) -{ - uint32_t k, rId, is_Unitig, Hap_cId; - - if(x->length*2 > contigNum) - { - memset(visit, 0, contigNum); - } - else - { - for (k = 0; k < x->length; k++) - { - rId = Get_tn(x->buffer[k]); - - if(read_g->seq[rId].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, rId, &rId, &is_Unitig); - if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; - } - - ///there are two cases: - ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id - ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 - get_R_to_U(ruIndex, rId, &Hap_cId, &is_Unitig); - if(is_Unitig == 0 || Hap_cId == (uint32_t)-1) continue; - ///here rId is the id of the read coming from the different haplotype - ///Hap_cId is the id of the corresponding contig (note here is the contig, instead of untig) - visit[Hap_cId] = 0; - } - } -} - -uint32_t prefilter(uint32_t x_pos, uint32_t y_pos, uint32_t xLen, uint32_t yLen, uint32_t dir, -float Hap_rate, uint32_t seedOcc) -{ - uint32_t max_count = 0, min_count = 0; - uint32_t /**xLeftBeg, **/xLeftLen, yLeftBeg, yLeftLen; - uint32_t xRightBeg, xRightLen, yRightBeg, yRightLen; - if(dir == 0) - { - /**xLeftBeg = 0;**/ xLeftLen = x_pos; xRightBeg = x_pos; xRightLen = xLen - xRightBeg; - yLeftBeg = 0; yLeftLen = y_pos; yRightBeg = y_pos; yRightLen = yLen - yRightBeg; - } - else - { - /**xLeftBeg = 0;**/ xLeftLen = x_pos; xRightBeg = x_pos; xRightLen = xLen - xRightBeg; - - yLeftBeg = y_pos + 1; yLeftLen = yLen - yLeftBeg; - yRightBeg = 0; yRightLen = y_pos + 1; - } - - - - max_count = seedOcc; - min_count = MIN(xLeftLen, yLeftLen) + MIN(xRightLen, yRightLen); - if(min_count == 0) return NON_PLOID; - if(max_count <= min_count*Hap_rate) return NON_PLOID; - return PLOID; -} - - - -inline uint64_t get_xy_pos(asg_t *read_g, asg_arc_t* t, uint32_t v_in_unitig, uint32_t w_in_unitig, -uint32_t xUnitigLen, uint32_t yUnitigLen, uint64_t* position_index, uint8_t* rev) -{ - uint32_t x_pos, y_pos, x_dir = 0, y_dir = 0; - uint64_t tmp; - x_pos = y_pos = (uint32_t)-1; - if((t->ul>>32)==v_in_unitig)///end pos - { - x_pos = (position_index[v_in_unitig>>1]>>32) + read_g->seq[v_in_unitig>>1].len - 1; - x_dir = 0; - } - else if((t->ul>>32)==(v_in_unitig^1))///start pos - { - x_pos = (position_index[v_in_unitig>>1]>>32); - x_dir = 1; - } - else - { - fprintf(stderr, "ERROR\n"); - } - - if(t->v == w_in_unitig) - { - y_pos = (position_index[w_in_unitig>>1]>>32) + t->ol - 1; - y_dir = 0; - } - else if(t->v == (w_in_unitig^1)) - { - y_pos = (position_index[w_in_unitig>>1]>>32) + read_g->seq[w_in_unitig>>1].len - t->ol; - y_dir = 1; - } - else - { - fprintf(stderr, "ERROR\n"); - } - - (*rev) = x_dir^y_dir; - if((*rev)) - { - if(yUnitigLen <= y_pos) - { - y_pos = (uint32_t)-1; - } - else - { - y_pos = yUnitigLen - y_pos - 1; - } - } - - if(x_pos>=xUnitigLen) x_pos = (uint32_t)-1; - if(y_pos>=yUnitigLen) y_pos = (uint32_t)-1; - - tmp = x_pos; tmp = tmp << 32; tmp = tmp | y_pos; - return tmp; -} - - -void print_debug_unitig(ma_utg_t *xReads, uint64_t* position_index, const char* infor) -{ - uint32_t k; - fprintf(stderr, "\n%s: n = %u\n", infor, xReads->n); - for (k = 0; k < xReads->n; k++) - { - fprintf(stderr, "(%u)v: %u, len: %u, index: %u, pos: %u\n", - k, (uint32_t)(xReads->a[k]>>32), (uint32_t)xReads->a[k], (uint32_t)(position_index[xReads->a[k]>>33]), - (uint32_t)(position_index[xReads->a[k]>>33]>>32)); - } -} - -void deduplicate_edge(kvec_asg_arc_t_offset* u_buffer) -{ - if(u_buffer->a.n == 0) return; - long long i = u_buffer->a.n - 1, k, i_off; - uint32_t v = u_buffer->a.a[i].x.ul>>33, m; - - for (; i >= 0; i--) { - if((u_buffer->a.a[i].x.ul>>33) != v) break; - } - - i = i + 1; - for (m = i; i < (long long)u_buffer->a.n; i++) - { - if(u_buffer->a.a[i].x.del) continue; - - i_off = Cal_Off(u_buffer->a.a[i].Off); - - for (k = i + 1; k < (long long)u_buffer->a.n; k++) - { - if(u_buffer->a.a[k].x.del) continue; - if(u_buffer->a.a[i].x.el != u_buffer->a.a[k].x.el) continue; - if(i_off != Cal_Off(u_buffer->a.a[k].Off)) continue; - u_buffer->a.a[k].x.del = 1; - u_buffer->a.a[i].weight += u_buffer->a.a[k].weight; - } - u_buffer->a.a[m] = u_buffer->a.a[i]; - m++; - } - - u_buffer->a.n = m; - ///fprintf(stderr, "u_buffer->a.n: %u, i: %lld\n", u_buffer->a.n, i); -} - -int cmp_hap_alignment(const void * a, const void * b) -{ - if((*(asg_arc_t_offset*)a).x.el > (*(asg_arc_t_offset*)b).x.el) return 1; - if((*(asg_arc_t_offset*)a).x.el < (*(asg_arc_t_offset*)b).x.el) return -1; - - long long aOff = Cal_Off((*(asg_arc_t_offset*)a).Off); - long long bOff = Cal_Off((*(asg_arc_t_offset*)b).Off); - - if(aOff > bOff) return 1; - if(aOff < bOff) return -1; - - if(((*(asg_arc_t_offset*)a).Off>>32) > ((*(asg_arc_t_offset*)b).Off>>32)) return 1; - if(((*(asg_arc_t_offset*)a).Off>>32) < ((*(asg_arc_t_offset*)b).Off>>32)) return -1; - - if((uint32_t)((*(asg_arc_t_offset*)a).Off) > (uint32_t)((*(asg_arc_t_offset*)b).Off)) return 1; - if((uint32_t)((*(asg_arc_t_offset*)a).Off) < (uint32_t)((*(asg_arc_t_offset*)b).Off)) return -1; - - if((*(asg_arc_t_offset*)a).weight < (*(asg_arc_t_offset*)b).weight) return 1; - if((*(asg_arc_t_offset*)a).weight > (*(asg_arc_t_offset*)b).weight) return -1; - - return 0; -} - - -int cmp_hap_alignment_chaining(const void * a, const void * b) -{ - if((*(asg_arc_t_offset*)a).x.el > (*(asg_arc_t_offset*)b).x.el) return 1; - if((*(asg_arc_t_offset*)a).x.el < (*(asg_arc_t_offset*)b).x.el) return -1; - - if(((*(asg_arc_t_offset*)a).Off>>32) > ((*(asg_arc_t_offset*)b).Off>>32)) return 1; - if(((*(asg_arc_t_offset*)a).Off>>32) < ((*(asg_arc_t_offset*)b).Off>>32)) return -1; - - if((uint32_t)((*(asg_arc_t_offset*)a).Off) > (uint32_t)((*(asg_arc_t_offset*)b).Off)) return 1; - if((uint32_t)((*(asg_arc_t_offset*)a).Off) < (uint32_t)((*(asg_arc_t_offset*)b).Off)) return -1; - - return 0; -} - -int cmp_hap_candidates(const void * a, const void * b) -{ - if((*(hap_candidates*)a).weight < (*(hap_candidates*)b).weight) return 1; - if((*(hap_candidates*)a).weight > (*(hap_candidates*)b).weight) return -1; - - if((*(hap_candidates*)a).index_beg > (*(hap_candidates*)b).index_beg) return 1; - if((*(hap_candidates*)a).index_beg < (*(hap_candidates*)b).index_beg) return -1; - - return 0; -} -inline long long get_hap_overlapLen(long long x_beg, long long x_end, long long xLen, -long long y_beg, long long y_end, long long yLen, long long* n_x_beg, long long* n_x_end, -long long* n_y_beg, long long* n_y_end) -{ - if(x_beg <= y_beg) - { - y_beg = y_beg - x_beg; - x_beg = 0; - } - else - { - x_beg = x_beg - y_beg; - y_beg = 0; - } - - long long x_right_length = xLen - x_end - 1; - long long y_right_length = yLen - y_end - 1; - - - if(x_right_length <= y_right_length) - { - x_end = xLen - 1; - y_end = y_end + x_right_length; - } - else - { - x_end = x_end + y_right_length; - y_end = yLen - 1; - } - - if(n_x_beg) (*n_x_beg) = x_beg; - if(n_x_end) (*n_x_end) = x_end; - if(n_y_beg) (*n_y_beg) = y_beg; - if(n_y_end) (*n_y_end) = y_end; - - return x_end - x_beg + 1; -} - - - -uint32_t classify_hap_overlap(long long xBeg, long long xEnd, long long xLen, -long long yBeg, long long yEnd, long long yLen, long long* r_xBeg, long long* r_xEnd, -long long* r_yBeg, long long* r_yEnd) -{ - long long n_x_beg, n_x_end, n_y_beg, n_y_end; - get_hap_overlapLen(xBeg, xEnd, xLen, yBeg, yEnd, yLen, &n_x_beg, &n_x_end, &n_y_beg, &n_y_end); - if(r_xBeg) (*r_xBeg) = n_x_beg; - if(r_xEnd) (*r_xEnd) = n_x_end; - if(r_yBeg) (*r_yBeg) = n_y_beg; - if(r_yEnd) (*r_yEnd) = n_y_end; - if(n_x_beg == 0 && n_x_end == xLen - 1) return YCX; - if(n_y_beg == 0 && n_y_end == yLen - 1) return XCY; - if(n_y_beg == 0 && n_x_end == xLen - 1) return X2Y; - if(n_x_beg == 0 && n_y_end == yLen - 1) return Y2X; - return XCY; -} - - -uint64_t get_pair_hap_coverage(uint64_t* readIDs, uint32_t Len, ma_hit_t_alloc* sources, ma_sub_t* coverage_cut) -{ - uint32_t m, n, qn; - ma_hit_t *h; - uint64_t R_bases = 0, C_bases = 0; - - for (m = 0; m < Len; m++) - { - qn = readIDs[m]>>33; - R_bases += coverage_cut[qn].e - coverage_cut[qn].s; - for (n = 0; n < (uint64_t)(sources[qn].length); n++) - { - h = &(sources[qn].buffer[n]); - C_bases += Get_qe((*h)) - Get_qs((*h)); - } - } - - return C_bases/R_bases; -} - - -uint64_t get_pair_purge_coverage(ma_utg_t *xReads, long long xPosBeg, long long xPosEnd, -ma_utg_t *yReads, long long yPosBeg, long long yPosEnd, uint32_t rev, asg_t *read_g, hap_cov_t *cov) -{ - long long offset, r_beg, r_end, i_beg, i_end, ovlp, IdxBeg, IdxEnd; - uint64_t i, rId, uCov, uLen; - ma_utg_t *x = NULL; - uCov = uLen = 0; - if(rev) - { - yPosBeg = yReads->len - yPosBeg - 1; - yPosEnd = yReads->len - yPosEnd - 1; - offset = yPosBeg; yPosBeg = yPosEnd; yPosEnd = offset; - } - - - IdxBeg = IdxEnd = -1; - x = xReads; i_beg = xPosBeg; i_end = xPosEnd; - for (i = 0, offset = 0; i < x->n; i++) - { - rId = x->a[i]>>33; - r_beg = offset; r_end = offset + (long long)(read_g->seq[rId].len) - 1; - offset += (uint32_t)x->a[i]; - ovlp = (long long)(MIN(r_end, i_end)) - (long long)(MAX(r_beg, i_beg)) + 1; - if(ovlp <= 0 || ovlp < read_g->seq[rId].len * 0.8) - { - if(IdxBeg != -1 && IdxEnd != -1) break; - continue; - } - - if(IdxBeg == -1) IdxBeg = i; - IdxEnd = i; - } - if(IdxBeg != -1 && IdxEnd != -1) - { - for (i = IdxBeg; (long long)i <= IdxEnd; i++) - { - rId = x->a[i]>>33; - uCov += cov->cov[rId]; - uLen += cov->read_g->seq[rId].len; - } - } - - - - IdxBeg = IdxEnd = -1; - x = yReads; i_beg = yPosBeg; i_end = yPosEnd; - for (i = 0, offset = 0; i < x->n; i++) - { - rId = x->a[i]>>33; - r_beg = offset; r_end = offset + (long long)(read_g->seq[rId].len) - 1; - offset += (uint32_t)x->a[i]; - ovlp = (long long)(MIN(r_end, i_end)) - (long long)(MAX(r_beg, i_beg)) + 1; - if(ovlp <= 0 || ovlp < read_g->seq[rId].len * 0.8) - { - if(IdxBeg != -1 && IdxEnd != -1) break; - continue; - } - - if(IdxBeg == -1) IdxBeg = i; - IdxEnd = i; - } - if(IdxBeg != -1 && IdxEnd != -1) - { - for (i = IdxBeg; (long long)i <= IdxEnd; i++) - { - rId = x->a[i]>>33; - uCov += cov->cov[rId]; - uLen += cov->read_g->seq[rId].len; - } - } - - return (uLen == 0? 0 : uCov / uLen); -} - - -void get_pair_hap_similarity_by_base(ma_utg_t *xReads, asg_t *read_g, uint32_t target_uId, -ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, long long xBegPos, long long xEndPos, -double* Match, double* Total) -{ - uint32_t i, j, qn, tn, is_Unitig, uId, min_count = 0, max_count = 0; - long long offset, r_beg, r_end, ovlp; - - for (i = 0, offset = 0; i < xReads->n; i++) - { - qn = xReads->a[i]>>33; - r_beg = offset; r_end = offset + (long long)(read_g->seq[qn].len) - 1; - offset += (uint32_t)xReads->a[i]; - - ovlp = (long long)(MIN(r_end, xEndPos)) - (long long)(MAX(r_beg, xBegPos)) + 1; - if(ovlp <= 0) continue; - - if(reverse_sources[qn].length > 0) min_count++; - if(reverse_sources[qn].length == 0) continue; - for (j = 0; j < reverse_sources[qn].length; j++) - { - tn = Get_tn(reverse_sources[qn].buffer[j]); - if(read_g->seq[tn].del == 1) - { - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - - - get_R_to_U(ruIndex, tn, &uId, &is_Unitig); - if(uId!=(uint32_t)-1 && is_Unitig == 1 && uId == target_uId) - { - max_count++; - break; - } - } - } - - (*Match) = max_count; - (*Total) = min_count; -} - -void get_pair_hap_similarity(uint64_t* readIDs, uint32_t Len, uint32_t target_uId, -ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, double* Match, double* Total) -{ - #define CUTOFF_THRES 1000 - uint32_t i, j, qn, tn, is_Unitig, uId, min_count = 0, max_count = 0, cutoff = 0;; - for (i = 0; i < Len; i++) - { - if(cutoff > CUTOFF_THRES && cutoff > (Len>>1)) - { - max_count = 0; - min_count = Len; - break; - } - qn = readIDs[i]>>33; - if(reverse_sources[qn].length > 0) min_count++; - if(reverse_sources[qn].length == 0) continue; - for (j = 0; j < reverse_sources[qn].length; j++) - { - tn = Get_tn(reverse_sources[qn].buffer[j]); - if(read_g->seq[tn].del == 1) - { - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - - - get_R_to_U(ruIndex, tn, &uId, &is_Unitig); - if(uId!=(uint32_t)-1 && is_Unitig == 1 && uId == target_uId) - { - max_count++; - break; - } - } - - //means no match - if(j == reverse_sources[qn].length) - { - cutoff++; - } - else - { - cutoff = 0; - } - } - - (*Match) = max_count; - (*Total) = min_count; -} -/** -void get_pair_hap_similarity_deduplicate(uint64_t* readIDs, uint32_t Len, uint32_t target_uId, -ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, double* Match, double* Total) -{ - get_pair_hap_similarity(readIDs, Len, target_uId, reverse_sources, read_g, ruIndex, Match, Total); - return; - - #define CUTOFF_THRES 100 - uint32_t i, j, qn, tn, is_Unitig, uId, min_count = 0, max_count = 0, cutoff = 0, is_found; - for (i = 0; i < Len; i++) - { - if(cutoff > CUTOFF_THRES) - { - max_count = 0; - min_count = Len; - break; - } - qn = readIDs[i]>>33; - is_found = 0; - - for (j = 0; j < reverse_sources[qn].length; j++) - { - tn = Get_tn(reverse_sources[qn].buffer[j]); - if(read_g->seq[tn].del == 1) - { - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - - - get_R_to_U(ruIndex, tn, &uId, &is_Unitig); - if(uId!=(uint32_t)-1 && is_Unitig == 1 && uId == target_uId) - { - max_count++; - } - min_count++; - is_found = 1; - } - - //means there is a match - if(is_found) - { - cutoff = 0; - } - else - { - cutoff++; - } - } - - (*Match) = max_count; - (*Total) = min_count; -} -**/ - -inline void check_hap_match(uint32_t qn, uint32_t targetBeg, uint32_t targetEnd, uint32_t targetID, -uint64_t* position_index, ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, uint32_t* is_found, uint32_t* is_match) -{ - uint32_t j, tn, uId, is_Unitig, offset; - (*is_found) = (*is_match) = 0; - if(reverse_sources[qn].length > 0) (*is_found) = 1; - for (j = 0; j < reverse_sources[qn].length; j++) - { - tn = Get_tn(reverse_sources[qn].buffer[j]); - if(read_g->seq[tn].del == 1) - { - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - - - get_R_to_U(ruIndex, tn, &uId, &is_Unitig); - if(uId!=(uint32_t)-1 && is_Unitig == 1 && uId == targetID) - { - offset = (uint32_t)(position_index[tn]); - if(offset >= targetBeg && offset <= targetEnd) - { - (*is_match) = 1; - break; - } - } - } - -} - -/** -inline void check_hap_match_deduplicate(uint32_t qn, uint32_t targetBeg, uint32_t targetEnd, uint32_t targetID, -uint64_t* position_index, ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, uint32_t* is_found, uint32_t* is_match) -{ - check_hap_match(qn, targetBeg, targetEnd, targetID, position_index, reverse_sources, read_g, - ruIndex, is_found, is_match); - return; - - - uint32_t j, tn, uId, is_Unitig, offset; - (*is_found) = (*is_match) = 0; - - for (j = 0; j < reverse_sources[qn].length; j++) - { - tn = Get_tn(reverse_sources[qn].buffer[j]); - if(read_g->seq[tn].del == 1) - { - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; - } - - - get_R_to_U(ruIndex, tn, &uId, &is_Unitig); - if(uId!=(uint32_t)-1 && is_Unitig == 1 && uId == targetID) - { - offset = (uint32_t)(position_index[tn]); - if(offset >= targetBeg && offset <= targetEnd) - { - (*is_match)++; - } - } - (*is_found)++; - } - -} -**/ - -void determin_hap_alignment_boundary_single_side(uint64_t* readIDs, long long queryLen, long long targetBeg, -long long targetEnd, long long targetID, long long eMatch, long long eTotal, long long dir, -float H_rate, int is_local, uint64_t* position_index, ma_hit_t_alloc* reverse_sources, asg_t *read_g, -R_to_U* ruIndex, uint32_t* n_matchLen, uint32_t* n_max_count, uint32_t* n_min_count) -{ - if(queryLen == 0) - { - (*n_matchLen) = (*n_min_count) = (*n_max_count) = 0; - return; - } - long long i, maxId, min_count = eTotal, max_count = eMatch, matchLen = 0; - long long rLen, score = 0, max_score = 0; - uint32_t is_found, is_match; - if(dir == 0) - { - for (i = 0, maxId = 0; i < queryLen; i++) - { - - check_hap_match(readIDs[i]>>33, targetBeg, targetEnd, targetID, position_index, reverse_sources, - read_g, ruIndex, &is_found, &is_match); - - min_count += is_found; - max_count += is_match; - if(max_count > min_count*H_rate) maxId = i; - - if(is_local && is_found) - { - rLen = read_g->seq[readIDs[i]>>33].len; - score += (is_match? rLen : (rLen*(-1))); - if(score >= max_score) max_score = score, maxId = i; - } - } - - for (i = maxId; i >= 0; i--) - { - check_hap_match(readIDs[i]>>33, targetBeg, targetEnd, targetID, position_index, reverse_sources, - read_g, ruIndex, &is_found, &is_match); - - ///if(is_found > 0 && is_match > 0 && is_match > is_found*Hap_rate) - if(is_found == 1 && is_match == 1) - { - break; - } - min_count -= is_found; - max_count -= is_match; - } - - matchLen = i+1; - } - else - { - for (i = queryLen - 1, maxId = queryLen - 1; i >= 0; i--) - { - check_hap_match(readIDs[i]>>33, targetBeg, targetEnd, targetID, position_index, reverse_sources, - read_g, ruIndex, &is_found, &is_match); - - min_count += is_found; - max_count += is_match; - if(max_count > min_count*H_rate) maxId = i; - - if(is_local && is_found) - { - rLen = read_g->seq[readIDs[i]>>33].len; - score += (is_match? rLen : (rLen*(-1))); - if(score >= max_score) max_score = score, maxId = i; - } - } - - for (i = maxId; i < queryLen; i++) - { - check_hap_match(readIDs[i]>>33, targetBeg, targetEnd, targetID, position_index, reverse_sources, - read_g, ruIndex, &is_found, &is_match); - - ///if(is_found > 0 && is_match > 0 && is_match > is_found*Hap_rate) - if(is_found == 1 && is_match == 1) - { - break; - } - min_count -= is_found; - max_count -= is_match; - } - - matchLen = queryLen - i; - } - - ///need to check if min_count == 0 - if(min_count == 0) - { - (*n_matchLen) = (*n_min_count) = (*n_max_count) = 0; - return; - } - - (*n_matchLen) = matchLen; - (*n_min_count) = min_count; - (*n_max_count) = max_count; -} - -inline void modify_target_interval(long long beg, long long end, long long len, -long long* target_beg, long long* target_end) -{ - #define TARGET_SGIFT 3 - beg -= TARGET_SGIFT; - end += TARGET_SGIFT; - if(beg < 0) beg = 0; - if(end >= len) end = len - 1; - (*target_beg) = beg; - (*target_end) = end; -} - - -void bi_direction_hap_alignment_extention(ma_utg_t* xReads, uint32_t xLeftBeg, uint32_t xLeftLen, -uint32_t xRightBeg, uint32_t xRightLen, uint32_t targetUid, uint32_t target_beg, uint32_t target_end, -float Hap_rate, int is_local, uint64_t* position_index, ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, -uint32_t rev, long long* x_interval_beg, long long* x_interval_end) -{ - if(rev) - { - uint32_t k; - k = xLeftBeg; xLeftBeg = xRightBeg; xRightBeg = k; - k = xLeftLen; xLeftLen = xRightLen; xRightLen = k; - } - uint32_t n_matchLenLeft, x_max_countLeft, x_min_countLeft; - uint32_t n_matchLenRight, x_max_countRight, x_min_countRight; - n_matchLenLeft = x_max_countLeft = x_min_countLeft = 0; - determin_hap_alignment_boundary_single_side(xReads->a+xLeftBeg, xLeftLen, - target_beg, target_end, targetUid, x_max_countLeft, x_min_countLeft, 1, Hap_rate, is_local, - position_index, reverse_sources, read_g, ruIndex, &n_matchLenLeft, &x_max_countLeft, - &x_min_countLeft); - - n_matchLenRight = x_max_countRight = x_min_countRight = 0; - determin_hap_alignment_boundary_single_side(xReads->a+xRightBeg, xRightLen, - target_beg, target_end, targetUid, x_max_countRight, x_min_countRight, 0, Hap_rate, is_local, - position_index, reverse_sources, read_g, ruIndex, &n_matchLenRight, &x_max_countRight, - &x_min_countRight); - - if(x_max_countLeft >= x_max_countRight) - { - determin_hap_alignment_boundary_single_side(xReads->a+xRightBeg, xRightLen, - target_beg, target_end, targetUid, x_max_countLeft, x_min_countLeft, 0, Hap_rate, is_local, - position_index, reverse_sources, read_g, ruIndex, &n_matchLenRight, &x_max_countRight, - &x_min_countRight); - } - else - { - determin_hap_alignment_boundary_single_side(xReads->a+xLeftBeg, xLeftLen, - target_beg, target_end, targetUid, x_max_countRight, x_min_countRight, 1, Hap_rate, is_local, - position_index, reverse_sources, read_g, ruIndex, &n_matchLenLeft, &x_max_countLeft, - &x_min_countLeft); - } - - (*x_interval_beg) = xLeftBeg + xLeftLen; (*x_interval_beg) -= n_matchLenLeft; - (*x_interval_end) = xRightBeg + n_matchLenRight; (*x_interval_end) -= 1; -} - -void get_hap_alignment_boundary(ma_utg_t* xReads, ma_utg_t* yReads, uint32_t type, -uint32_t xLeftMatch, uint32_t xLeftTotal, uint32_t yLeftMatch, uint32_t yLeftTotal, -uint32_t xRightMatch, uint32_t xRightTotal, uint32_t yRightMatch, uint32_t yRightTotal, -uint32_t xLeftBeg, uint32_t xLeftLen, uint32_t yLeftBeg, uint32_t yLeftLen, -uint32_t xRightBeg, uint32_t xRightLen, uint32_t yRightBeg, uint32_t yRightLen, -uint32_t xUid, uint32_t yUid, float Hap_rate, int is_local, uint64_t* position_index, -ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, uint32_t rev, -long long* r_x_interval_beg, long long* r_x_interval_end, -long long* r_y_interval_beg, long long* r_y_interval_end) -{ - - uint32_t x_max_count, x_min_count, y_max_count, y_min_count, n_matchLen; - long long x_interval_beg, x_interval_end, y_interval_beg, y_interval_end; - long long target_beg, target_end; - x_max_count = x_min_count = y_max_count = y_min_count = 0; - if(type == X2Y) - { - /********************x*********************/ - x_max_count = xRightMatch; - x_min_count = xRightTotal; - - modify_target_interval(yLeftBeg, yLeftBeg+yLeftLen-1, yReads->n, &target_beg, &target_end); - determin_hap_alignment_boundary_single_side(xReads->a+xLeftBeg, xLeftLen, - /**yLeftBeg, yLeftBeg+yLeftLen-1,**/ target_beg, target_end, yUid, - x_max_count, x_min_count, 1, Hap_rate, is_local, position_index, reverse_sources, - read_g, ruIndex, &n_matchLen, &x_max_count, &x_min_count); - - x_interval_beg = xLeftBeg + xLeftLen; x_interval_beg -= n_matchLen; - x_interval_end = xRightBeg + xRightLen; x_interval_end -= 1; - /********************x*********************/ - - /********************y*********************/ - y_max_count = yLeftMatch; - y_min_count = yLeftTotal; - modify_target_interval(xRightBeg, xRightBeg+xRightLen-1, xReads->n, &target_beg, &target_end); - determin_hap_alignment_boundary_single_side(yReads->a+yRightBeg, yRightLen, - /**xRightBeg, xRightBeg+xRightLen-1,**/ target_beg, target_end, xUid, - y_max_count, y_min_count, rev, Hap_rate, is_local, position_index, reverse_sources, - read_g, ruIndex, &n_matchLen, &y_max_count, &y_min_count); - if(rev == 0) - { - y_interval_beg = yLeftBeg; - y_interval_end = yRightBeg + n_matchLen; y_interval_end -= 1; - } - else - { - y_interval_beg = yRightBeg + yRightLen; y_interval_beg -= n_matchLen; - y_interval_end = yLeftBeg + yLeftLen; y_interval_end -= 1; - } - - /********************y*********************/ - } - else if(type == Y2X) - { - /********************x*********************/ - x_max_count = xLeftMatch; - x_min_count = xLeftTotal; - modify_target_interval(yRightBeg, yRightBeg+yRightLen-1, yReads->n, &target_beg, &target_end); - determin_hap_alignment_boundary_single_side(xReads->a+xRightBeg, xRightLen, - /**yRightBeg, yRightBeg+yRightLen-1,**/ target_beg, target_end, yUid, - x_max_count, x_min_count, 0, Hap_rate, is_local, position_index, reverse_sources, - read_g, ruIndex, &n_matchLen, &x_max_count, &x_min_count); - - x_interval_beg = xLeftBeg; - x_interval_end = xRightBeg + n_matchLen; x_interval_end -= 1; - /********************x*********************/ - - /********************y*********************/ - y_max_count = yRightMatch; - y_min_count = yRightTotal; - modify_target_interval(xLeftBeg, xLeftBeg+xLeftLen-1, xReads->n, &target_beg, &target_end); - determin_hap_alignment_boundary_single_side(yReads->a+yLeftBeg, yLeftLen, - /**xLeftBeg, xLeftBeg+xLeftLen-1,**/ target_beg, target_end, xUid, - y_max_count, y_min_count, 1-rev, Hap_rate, is_local, position_index, reverse_sources, - read_g, ruIndex, &n_matchLen, &y_max_count, &y_min_count); - if(rev == 0) - { - y_interval_beg = yLeftBeg + yLeftLen; y_interval_beg -= n_matchLen; - y_interval_end = yRightBeg + yRightLen; y_interval_end -= 1; - } - else - { - y_interval_beg = yRightBeg; - y_interval_end = yLeftBeg + n_matchLen; y_interval_end -= 1; - } - /********************y*********************/ - } - else if(type == XCY) - { - /********************x*********************/ - bi_direction_hap_alignment_extention(xReads, xLeftBeg, xLeftLen, xRightBeg, xRightLen, - yUid, 0, yReads->n - 1, Hap_rate, is_local, position_index, reverse_sources, read_g, ruIndex, 0, - &x_interval_beg, &x_interval_end); - /********************x*********************/ - - /********************y*********************/ - y_interval_beg = 0; - y_interval_end = yReads->n; y_interval_end -= 1; - /********************y*********************/ - } - else if(type == YCX) - { - /********************x*********************/ - x_interval_beg = 0; - x_interval_end = xReads->n; x_interval_end -= 1; - /********************x*********************/ - - /********************y*********************/ - bi_direction_hap_alignment_extention(yReads, yLeftBeg, yLeftLen, yRightBeg, yRightLen, - xUid, 0, xReads->n - 1, Hap_rate, is_local, position_index, reverse_sources, read_g, ruIndex, rev, - &y_interval_beg, &y_interval_end); - /********************y*********************/ - } else abort(); - - (*r_x_interval_beg) = x_interval_beg; - (*r_x_interval_end) = x_interval_end; - (*r_y_interval_beg) = y_interval_beg; - (*r_y_interval_end) = y_interval_end; -} - -uint32_t vote_overlap_type(kvec_asg_arc_t_offset* u_buffer, hap_candidates* hap_can, -uint64_t* position_index, ma_utg_t* xReads, ma_utg_t* yReads) -{ - uint32_t i, xBasePos, yBasePos; - asg_arc_t_offset* arch = NULL; - uint32_t flag[4]; - flag[X2Y] = flag[Y2X] = flag[XCY] = flag[YCX] = 0; - - - for (i = hap_can->index_beg; i <= hap_can->index_end; i++) - { - arch = &(u_buffer->a.a[i]); - xBasePos = (uint32_t)(arch->Off>>32); - yBasePos = (uint32_t)(arch->Off); - flag[classify_hap_overlap(xBasePos, xBasePos, xReads->len, yBasePos, yBasePos, yReads->len, - NULL, NULL, NULL, NULL)]++; - } - - uint32_t max_flag_i = 0; - for (i = 0; i < 4; i++) - { - if(i == max_flag_i) continue; - if(flag[i] > flag[max_flag_i]) - { - max_flag_i = i; - } - } - - return max_flag_i; -} - - -void get_base_boundary(R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, -asg_t *read_g, uint64_t* position_index, int max_hang, int min_ovlp, ma_utg_t *xReads, ma_utg_t *yReads, -uint32_t xUid, uint32_t yUid, long long xBegIndex, long long xEndIndex, long long yBegIndex, long long yEndIndex, -uint32_t dir, uint32_t rev, uint32_t* x_off, uint32_t* y_off) -{ - long long k, j, offset; - ma_hit_t_alloc *xR = NULL; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL, *st = NULL; - int32_t r; - asg_arc_t t; - uint32_t rId, Hap_uId, is_Unitig, v, w, v_dir, w_dir, is_found = 0, oLen = 0; - uint64_t tmp; - (*x_off) = (*y_off) = (uint32_t)-1; - if(dir == 1) - { - for (k = xEndIndex; k >= xBegIndex; k--) - { - xR = &(reverse_sources[xReads->a[k]>>33]); - is_found = 0; oLen = 0; - for (j = 0; j < xR->length; j++) - { - h = &(xR->buffer[j]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(st->del || read_g->seq[Get_tn(*h)].del) continue; - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - ///if it is a contained overlap, skip - if(r < 0) continue; - - rId = t.v>>1; - if(read_g->seq[rId].del == 1) continue; - ///there are two cases: - ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id - ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 - get_R_to_U(ruIndex, rId, &Hap_uId, &is_Unitig); - if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; - if(Hap_uId != yUid) continue; - - v = xReads->a[k]>>32; - get_R_to_U(ruIndex, v>>1, &Hap_uId, &is_Unitig); - if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; - if(Hap_uId != xUid) continue; - if((uint32_t)(position_index[v>>1]) != k) continue; - - w = (yReads->a[(uint32_t)(position_index[rId])])>>32; - - v_dir = ((t.ul>>32)==v)?1:0; - w_dir = (t.v == w)?1:0; - if(rev == 0 && v_dir != w_dir) continue; - if(rev == 1 && v_dir == w_dir) continue; - - /****************************may have bugs********************************/ - offset = (uint32_t)(position_index[rId]); - if(offset < yBegIndex || offset > yEndIndex) continue; - /****************************may have bugs********************************/ - - tmp = get_xy_pos(read_g, &t, v, w, xReads->len, yReads->len, position_index, &(t.el)); - if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue; - - ///if(is_found == 0 || ((uint32_t)(tmp>>32) > (*x_off) && ((uint32_t)tmp) > (*y_off))) - if(is_found == 0 || t.ol > oLen) - { - (*x_off) = tmp>>32; - (*y_off) = (uint32_t)tmp; - oLen = t.ol; - } - - is_found = 1; - } - if(is_found) return; - } - } - else - { - for (k = xBegIndex; k <= xEndIndex; k++) - { - xR = &(reverse_sources[xReads->a[k]>>33]); - is_found = 0; oLen = 0; - for (j = 0; j < xR->length; j++) - { - h = &(xR->buffer[j]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(st->del || read_g->seq[Get_tn(*h)].del) continue; - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - ///if it is a contained overlap, skip - if(r < 0) continue; - - rId = t.v>>1; - if(read_g->seq[rId].del == 1) continue; - ///there are two cases: - ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id - ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 - get_R_to_U(ruIndex, rId, &Hap_uId, &is_Unitig); - if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; - if(Hap_uId != yUid) continue; - - v = xReads->a[k]>>32; - get_R_to_U(ruIndex, v>>1, &Hap_uId, &is_Unitig); - if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; - if(Hap_uId != xUid) continue; - if((uint32_t)(position_index[v>>1]) != k) continue; - - w = (yReads->a[(uint32_t)(position_index[rId])])>>32; - - v_dir = ((t.ul>>32)==v)?1:0; - w_dir = (t.v == w)?1:0; - if(rev == 0 && v_dir != w_dir) continue; - if(rev == 1 && v_dir == w_dir) continue; - - /****************************may have bugs********************************/ - offset = (uint32_t)(position_index[rId]); - if(offset < yBegIndex || offset > yEndIndex) continue; - /****************************may have bugs********************************/ - - tmp = get_xy_pos(read_g, &t, v, w, xReads->len, yReads->len, position_index, &(t.el)); - if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue; - - ///if(is_found == 0 || ((uint32_t)(tmp>>32) < (*x_off) && ((uint32_t)tmp) < (*y_off))) - if(is_found == 0 || t.ol > oLen) - { - (*x_off) = tmp>>32; - (*y_off) = (uint32_t)tmp; - oLen = t.ol; - } - - is_found = 1; - } - if(is_found) return; - } - } - - - (*x_off) = (*y_off) = (uint32_t)-1; - -} - -void print_asg_arc_t_offset(asg_arc_t_offset* x, long long n, const char* info) -{ - fprintf(stderr,"\n\n(%s)n: %lld\n", info, n); - long long i, x_off, y_off; - for (i = 0; i < n; i++) - { - x_off = (long long)(x[i].Off>>32); - y_off = (long long)((uint32_t)x[i].Off); - fprintf(stderr, "i: %lld, x_off: %lld, y_off: %lld, weight: %lu, rev: %u, ol: %u\n", - i, x_off, y_off, (unsigned long)x[i].weight, x[i].x.el, x[i].x.ol); - } -} - - -// Binary search -inline int GetCeilIndex(asg_arc_t_offset* arr, kvec_t_i32_warp* T, int l, int r, uint32_t key) -{ - while (r - l > 1) { - int m = l + (r - l) / 2; - if (Get_yOff(arr[T->a.a[m]].Off) >= key) - r = m; - else - l = m; - } - - return r; -} - - -void quick_LIS(asg_arc_t_offset* x, uint32_t n, kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* prevIndex) -{ - tailIndex->a.n = prevIndex->a.n = 0; - if(n == 0) return; - - kv_resize(int32_t, tailIndex->a, n); - kv_resize(int32_t, prevIndex->a, n); - - long long len = 1, i, pos, m; ///the length of chain must be >=1 - tailIndex->a.a[0] = 0; - prevIndex->a.a[0] = -1; - - ///x has already sorted by x_pos - for(i = 1; i < (long long)n; i++) - { - if(Get_yOff(x[i].Off) < Get_yOff(x[tailIndex->a.a[0]].Off)) - { - // new smallest value - tailIndex->a.a[0] = i; ///doesn't matter too much - } - else if(Get_yOff(x[i].Off) > Get_yOff(x[tailIndex->a.a[len - 1]].Off)) - { - // arr[i] wants to extend largest subsequence - prevIndex->a.a[i] = tailIndex->a.a[len - 1]; - tailIndex->a.a[len++] = i; - } - else - { - // arr[i] wants to be a potential condidate of - // future subsequence - // It will replace ceil value in tailIndices - pos = GetCeilIndex(x, tailIndex, -1, len - 1, Get_yOff(x[i].Off)); - prevIndex->a.a[i] = pos > 0? tailIndex->a.a[pos - 1] : -1; - tailIndex->a.a[pos] = i; - } - } - - - for (m = 0, i = tailIndex->a.a[len - 1]; m < len; i = prevIndex->a.a[i], m++) - { - tailIndex->a.a[len-m-1] = i; - } - - tailIndex->a.n = len; -} - -uint64_t get_xy_pos_by_pos(asg_t *read_g, asg_arc_t* t, uint32_t v_in_unitig, uint32_t w_in_unitig, -uint32_t v_in_pos, uint32_t w_in_pos, uint32_t xUnitigLen, uint32_t yUnitigLen, uint8_t* rev) -{ - uint32_t x_pos, y_pos, x_dir = 0, y_dir = 0; - uint64_t tmp; - x_pos = y_pos = (uint32_t)-1; - if((t->ul>>32)==v_in_unitig)///end pos - { - x_pos = v_in_pos + read_g->seq[v_in_unitig>>1].len - 1; - x_dir = 0; - } - else if((t->ul>>32)==(v_in_unitig^1))///start pos - { - x_pos = v_in_pos; - x_dir = 1; - } - else - { - fprintf(stderr, "ERROR\n"); - } - - if(t->v == w_in_unitig) - { - y_pos = w_in_pos + t->ol - 1; - y_dir = 0; - } - else if(t->v == (w_in_unitig^1)) - { - y_pos = w_in_pos + read_g->seq[w_in_unitig>>1].len - t->ol; - y_dir = 1; - } - else - { - fprintf(stderr, "ERROR\n"); - } - - (*rev) = x_dir^y_dir; - if((*rev)) - { - if(yUnitigLen <= y_pos) - { - y_pos = (uint32_t)-1; - } - else - { - y_pos = yUnitigLen - y_pos - 1; - } - } - - if(x_pos>=xUnitigLen) x_pos = (uint32_t)-1; - if(y_pos>=yUnitigLen) y_pos = (uint32_t)-1; - - tmp = x_pos; tmp = tmp << 32; tmp = tmp | y_pos; - return tmp; -} - -void chain_trans_ovlp(hap_cov_t *cover, utg_trans_t *o, ma_ug_t *ug, asg_t *read_sg, buf_t* xReads, uint32_t targetBaseLen, uint32_t* xEnd) -{ - ma_hit_t_alloc* reverse_sources = (o? o->reverse_sources:cover->reverse_sources); - ma_sub_t *coverage_cut = (o? o->coverage_cut:cover->coverage_cut); - int max_hang = (o? o->max_hang:cover->max_hang); - int min_ovlp = (o? o->min_ovlp:cover->min_ovlp); - kvec_asg_arc_t_offset* u_buffer = (o? &(o->u_buffer):&(cover->u_buffer)); - kvec_t_i32_warp* tailIndex = (o? &(o->tailIndex):&(cover->tailIndex)); - kvec_t_i32_warp* prevIndex = (o? &(o->prevIndex):&(cover->prevIndex)); - uint64_t *pos_idx = (o? o->pos_idx:cover->pos_idx); - ma_hit_t_alloc *xR = NULL; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL, *st = NULL; - int32_t r; - asg_arc_t t; - uint32_t rId, v, w; - uint64_t tmp; - asg_arc_t_offset t_offset; - u_buffer->a.n = 0; - ///(*xEnd) = (uint32_t)-1; - (*xEnd) = 0; - uint32_t u_i, r_i, k, j, len, p_v, *a = xReads->b.a, uid, ori, l, m, aOcc, nv, xOcc = (uint32_t)-1; - ma_utg_t* u = NULL; - asg_arc_t *av = NULL; - - - for (u_i = r_i = len = aOcc = 0, xOcc = (uint32_t)-1, p_v = (uint32_t)-1; u_i < xReads->b.n; u_i++) - { - uid = a[u_i] >> 1; - ori = a[u_i] & 1; - u = &(ug->u.a[uid]); - if(u->n == 0) continue; - - for (r_i = 0; r_i < u->n; r_i++, aOcc++) - { - l = 0; - v = (ori == 1?((uint64_t)((u->a[u->n - r_i - 1])^(uint64_t)(0x100000000)))>>32:((uint64_t)(u->a[r_i]))>>32); - - if(p_v != (uint32_t)-1) - { - av = asg_arc_a(read_sg, p_v); - nv = asg_arc_n(read_sg, p_v); - - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == v) - { - l = asg_arc_len(av[k]); - break; - } - } - if(k == nv) fprintf(stderr, "ERROR\n"); - } - - p_v = v; len += l; - if(len >= targetBaseLen)///might be not right for centromeres - { - xOcc = aOcc; - break; - } - } - - if(xOcc != (uint32_t)-1) break; - } - if(xOcc == (uint32_t)-1) xOcc = aOcc; - if(xOcc == 0) xOcc = 1; - - - - for (u_i = r_i = len = aOcc = 0, p_v = (uint32_t)-1; u_i < xReads->b.n; u_i++) - { - uid = a[u_i] >> 1; - ori = a[u_i] & 1; - u = &(ug->u.a[uid]); - if(u->n == 0) continue; - - for (r_i = 0; r_i < u->n; r_i++, aOcc++) - { - if(aOcc >= xOcc) break; - l = 0; - v = (ori == 1?((uint64_t)((u->a[u->n - r_i - 1])^(uint64_t)(0x100000000)))>>32:((uint64_t)(u->a[r_i]))>>32); - - if(p_v != (uint32_t)-1) - { - av = asg_arc_a(read_sg, p_v); - nv = asg_arc_n(read_sg, p_v); - - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == v) - { - l = asg_arc_len(av[k]); - break; - } - } - if(k == nv) fprintf(stderr, "ERROR\n"); - } - - p_v = v; len += l; - - xR = &(reverse_sources[v>>1]); - for (j = 0; j < xR->length; j++) - { - h = &(xR->buffer[j]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(st->del || read_sg->seq[Get_tn(*h)].del) continue; - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - ///if it is a contained overlap, skip - if(r < 0) continue; - - rId = t.v>>1; - if(read_sg->seq[rId].del == 1) continue; - if(pos_idx[rId] == (uint64_t)-1) continue; - w = (uint32_t)(pos_idx[rId]); - if(rId != (w>>1)) continue; - - tmp = get_xy_pos_by_pos(read_sg, &t, v, w, len, pos_idx[w>>1]>>32, - (uint32_t)-1, targetBaseLen, &(t.el)); - if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue; - if(t.el) continue; ///must - - t_offset.Off = tmp; - t_offset.x = t; - t_offset.weight = 1; - kv_push(asg_arc_t_offset, u_buffer->a, t_offset); - } - } - - if(aOcc >= xOcc) break; - } - - if(u_buffer->a.n == 0) return; - - qsort(u_buffer->a.a, u_buffer->a.n, sizeof(asg_arc_t_offset), cmp_hap_alignment_chaining); - - ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n, "before"); - - - for (k = 1, l = 0, m = 0; k <= u_buffer->a.n; ++k) - { - if (k == u_buffer->a.n || u_buffer->a.a[k].x.el != u_buffer->a.a[l].x.el || - u_buffer->a.a[k].Off != u_buffer->a.a[l].Off) - { - u_buffer->a.a[m] = u_buffer->a.a[l]; - for (l += 1; l < k; l++) - { - u_buffer->a.a[m].weight += u_buffer->a.a[l].weight; - if(u_buffer->a.a[l].x.ol > u_buffer->a.a[m].x.ol) - { - u_buffer->a.a[m].x = u_buffer->a.a[l].x; - } - } - l = k; - m++; - } - } - u_buffer->a.n = m; - - ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n, "after"); - quick_LIS(u_buffer->a.a, u_buffer->a.n, tailIndex, prevIndex); - if(tailIndex->a.n == 0) return; - - - uint32_t xLen_thres = (uint32_t)-1; - asg_arc_t_offset* best = &(u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]]); - for (u_i = r_i = len = aOcc = 0, p_v = (uint32_t)-1; u_i < xReads->b.n; u_i++) - { - uid = a[u_i] >> 1; - ori = a[u_i] & 1; - u = &(ug->u.a[uid]); - if(u->n == 0) continue; - - for (r_i = 0; r_i < u->n; r_i++, aOcc++) - { - l = 0; - v = (ori == 1?((uint64_t)((u->a[u->n - r_i - 1])^(uint64_t)(0x100000000)))>>32:((uint64_t)(u->a[r_i]))>>32); - - if(p_v != (uint32_t)-1) - { - av = asg_arc_a(read_sg, p_v); - nv = asg_arc_n(read_sg, p_v); - - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == v) - { - l = asg_arc_len(av[k]); - break; - } - } - if(k == nv) fprintf(stderr, "ERROR\n"); - } - - p_v = v; len += l; - - if((v>>1) == (best->x.ul>>33) && xLen_thres == (uint32_t)-1) - { - ///cov->pos_idx[v>>1] = len; - xR = &(reverse_sources[v>>1]); - for (j = 0; j < xR->length; j++) - { - h = &(xR->buffer[j]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(st->del || read_sg->seq[Get_tn(*h)].del) continue; - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - ///if it is a contained overlap, skip - if(r < 0) continue; - - rId = t.v>>1; - if(read_sg->seq[rId].del == 1) continue; - if(pos_idx[rId] == (uint64_t)-1) continue; - w = (uint32_t)(pos_idx[rId]); - if(rId != (w>>1)) continue; - - tmp = get_xy_pos_by_pos(read_sg, &t, v, w, len, pos_idx[w>>1]>>32, - (uint32_t)-1, targetBaseLen, &(t.el)); - if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue; - if(t.el) continue; ///must - - t_offset.Off = tmp; - t_offset.x = t; - t_offset.weight = 1; - if(t_offset.Off == best->Off && t_offset.x.v == best->x.v && t_offset.x.ul == best->x.ul) - { - xLen_thres = Get_xOff(best->Off) + targetBaseLen - Get_yOff(best->Off); - } - } - } - - if(len >= xLen_thres) - { - (*xEnd) = aOcc; - return; - } - } - } - - (*xEnd) = aOcc; -} - - -void get_base_boundary_advance_back(R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, -asg_t *read_g, uint64_t* position_index, int max_hang, int min_ovlp, ma_utg_t *xReads, ma_utg_t *yReads, -uint32_t xUid, uint32_t yUid, long long xBegIndex, long long xEndIndex, long long yBegIndex, long long yEndIndex, -uint32_t rev, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* prevIndex, -uint32_t* xBeg, uint32_t* xEnd, uint32_t* yBeg, uint32_t* yEnd) -{ - long long k, j, offset, m; - ma_hit_t_alloc *xR = NULL; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL, *st = NULL; - int32_t r; - asg_arc_t t; - uint32_t rId, Hap_uId, is_Unitig, v, w, v_dir, w_dir; - uint64_t tmp; - asg_arc_t_offset t_offset; - u_buffer->a.n = 0; - (*xBeg) = (*xEnd) = (*yBeg) = (*yEnd) = (uint32_t)-1; - for (k = xBegIndex; k <= xEndIndex; k++) - { - xR = &(reverse_sources[xReads->a[k]>>33]); - for (j = 0; j < xR->length; j++) - { - h = &(xR->buffer[j]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(st->del || read_g->seq[Get_tn(*h)].del) continue; - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - ///if it is a contained overlap, skip - if(r < 0) continue; - - rId = t.v>>1; - if(read_g->seq[rId].del == 1) continue; - ///there are two cases: - ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id - ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 - get_R_to_U(ruIndex, rId, &Hap_uId, &is_Unitig); - if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; - if(Hap_uId != yUid) continue; - - v = xReads->a[k]>>32; - get_R_to_U(ruIndex, v>>1, &Hap_uId, &is_Unitig); - if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; - if(Hap_uId != xUid) continue; - if((uint32_t)(position_index[v>>1]) != k) continue; - - w = (yReads->a[(uint32_t)(position_index[rId])])>>32; - - v_dir = ((t.ul>>32)==v)?1:0; - w_dir = (t.v == w)?1:0; - if(rev == 0 && v_dir != w_dir) continue; - if(rev == 1 && v_dir == w_dir) continue; - - /****************************may have bugs********************************/ - offset = (uint32_t)(position_index[rId]); - if(offset < yBegIndex || offset > yEndIndex) continue; - /****************************may have bugs********************************/ - - tmp = get_xy_pos(read_g, &t, v, w, xReads->len, yReads->len, position_index, &(t.el)); - if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue; - - t_offset.Off = tmp; - t_offset.x = t; - t_offset.weight = 1; - kv_push(asg_arc_t_offset, u_buffer->a, t_offset); - } - } - if(u_buffer->a.n == 0) return; - - qsort(u_buffer->a.a, u_buffer->a.n, sizeof(asg_arc_t_offset), cmp_hap_alignment_chaining); - - ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n, "before"); - - for (k = 1, m = 1; k < (long long)u_buffer->a.n; k++) - { - if(u_buffer->a.a[m-1].Off == u_buffer->a.a[k].Off) - { - u_buffer->a.a[m-1].weight += u_buffer->a.a[k].weight; - if(u_buffer->a.a[k].x.ol > u_buffer->a.a[m-1].x.ol) - { - u_buffer->a.a[m-1].x = u_buffer->a.a[k].x; - } - continue; - } - u_buffer->a.a[m] = u_buffer->a.a[k]; - m++; - } - u_buffer->a.n = m; - - ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n, "after"); - quick_LIS(u_buffer->a.a, u_buffer->a.n, tailIndex, prevIndex); - - if(tailIndex->a.n == 0) return; - - (*xBeg) = Get_xOff(u_buffer->a.a[tailIndex->a.a[0]].Off); - (*yBeg) = Get_yOff(u_buffer->a.a[tailIndex->a.a[0]].Off); - (*xEnd) = Get_xOff(u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].Off); - (*yEnd) = Get_yOff(u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].Off); -} - -uint32_t determine_hap_overlap_type_advance_back(hap_candidates* hap_can, ma_utg_t *xReads, ma_utg_t *yReads, -R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, asg_t *read_g, uint64_t* position_index, -int max_hang, int min_ovlp, uint32_t xUid, uint32_t yUid, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, -kvec_t_i32_warp* prevIndex, long long* r_x_pos_beg, long long* r_x_pos_end, long long* r_y_pos_beg, long long* r_y_pos_end) -{ - uint32_t x_pos_beg, y_pos_beg, x_pos_end, y_pos_end; - /*************************x***************************/ - get_base_boundary_advance_back(ruIndex, reverse_sources, coverage_cut, read_g, position_index, - max_hang, min_ovlp, xReads, yReads, xUid, yUid, Get_x_beg(*hap_can), Get_x_end(*hap_can), - Get_y_beg(*hap_can), Get_y_end(*hap_can), Get_rev(*hap_can), u_buffer, tailIndex, prevIndex, - &x_pos_beg, &x_pos_end, &y_pos_beg, &y_pos_end); - /*************************x***************************/ - - if(x_pos_beg == (uint32_t)-1 || y_pos_beg == (uint32_t)-1 - || x_pos_end == (uint32_t)-1 || y_pos_end == (uint32_t)-1) - { - return (uint32_t)-1; - } - if(x_pos_beg > x_pos_end || y_pos_beg > y_pos_end) return (uint32_t)-1; - - /** - #define X2Y 0 - #define Y2X 1 - #define XCY 2 - #define YCX 3 - **/ - return classify_hap_overlap(x_pos_beg, x_pos_end, xReads->len, y_pos_beg, y_pos_end, yReads->len, - r_x_pos_beg, r_x_pos_end, r_y_pos_beg, r_y_pos_end); -} - -void get_idx_by_base(ma_utg_t *x, asg_t *read_g, long long beg_base, long long end_base, - long long* beg_idx, long long* end_idx) -{ - long long offset, r_beg, r_end; - uint64_t i, rId; - (*beg_idx) = (*end_idx) = -1; - for (i = 0, offset = 0; i < x->n; i++) - { - rId = x->a[i]>>33; - r_beg = offset; r_end = offset + (long long)(read_g->seq[rId].len) - 1; - offset += (uint32_t)x->a[i]; - if(beg_base > r_end || r_beg > end_base) - { - if((*beg_idx) != -1 && (*end_idx) != -1) break; - continue; - } - if((*beg_idx) == -1) (*beg_idx) = i; - (*end_idx) = i; - } -} - -int get_base_boundary_chain(R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, -asg_t *read_g, uint64_t* position_index, int max_hang, int min_ovlp, ma_utg_t *xReads, ma_utg_t *yReads, -uint32_t xUid, uint32_t yUid, long long xBegIndex, long long xEndIndex, long long yBegIndex, long long yEndIndex, -uint32_t rev, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* prevIndex) -{ - long long k, j, l, offset, m; - ma_hit_t_alloc *xR = NULL; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL, *st = NULL; - int32_t r; - asg_arc_t t; - uint32_t rId, Hap_uId, is_Unitig, v, w, v_dir, w_dir; - uint64_t tmp; - asg_arc_t_offset t_offset; - u_buffer->a.n = 0; - for (k = xBegIndex; k <= xEndIndex; k++) - { - xR = &(reverse_sources[xReads->a[k]>>33]); - for (j = 0; j < xR->length; j++) - { - h = &(xR->buffer[j]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(st->del || read_g->seq[Get_tn(*h)].del) continue; - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - ///if it is a contained overlap, skip - if(r < 0) continue; - - rId = t.v>>1; - if(read_g->seq[rId].del == 1) continue; - ///there are two cases: - ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id - ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 - get_R_to_U(ruIndex, rId, &Hap_uId, &is_Unitig); - if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; - if(Hap_uId != yUid) continue; - - v = xReads->a[k]>>32; - get_R_to_U(ruIndex, v>>1, &Hap_uId, &is_Unitig); - if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; - if(Hap_uId != xUid) continue; - if((uint32_t)(position_index[v>>1]) != k) continue; - - w = (yReads->a[(uint32_t)(position_index[rId])])>>32; - - v_dir = ((t.ul>>32)==v)?1:0; - w_dir = (t.v == w)?1:0; - if(rev == 0 && v_dir != w_dir) continue; - if(rev == 1 && v_dir == w_dir) continue; - - /****************************may have bugs********************************/ - offset = (uint32_t)(position_index[rId]); - if(offset < yBegIndex || offset > yEndIndex) continue; - /****************************may have bugs********************************/ - - tmp = get_xy_pos(read_g, &t, v, w, xReads->len, yReads->len, position_index, &(t.el)); - if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue; - - t_offset.Off = tmp; - t_offset.x = t; - t_offset.weight = 1; - kv_push(asg_arc_t_offset, u_buffer->a, t_offset); - } - } - if(u_buffer->a.n == 0) return 0; - - qsort(u_buffer->a.a, u_buffer->a.n, sizeof(asg_arc_t_offset), cmp_hap_alignment_chaining); - - ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n, "before"); - for (k = 1, l = 0, m = 0; k <= (long long)u_buffer->a.n; ++k) - { - if (k == (long long)u_buffer->a.n || u_buffer->a.a[k].Off != u_buffer->a.a[l].Off) - { - u_buffer->a.a[m] = u_buffer->a.a[l]; - for (l += 1; l < k; l++) - { - u_buffer->a.a[m].weight += u_buffer->a.a[l].weight; - if(u_buffer->a.a[l].x.ol > u_buffer->a.a[m].x.ol) - { - u_buffer->a.a[m].x = u_buffer->a.a[l].x; - } - } - l = k; - m++; - } - } - u_buffer->a.n = m; - - ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n, "after"); - quick_LIS(u_buffer->a.a, u_buffer->a.n, tailIndex, prevIndex); - - if(tailIndex->a.n == 0) return 0; - return 1; -} - - -void get_base_boundary_advance(R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, -asg_t *read_g, uint64_t* position_index, int max_hang, int min_ovlp, ma_utg_t *xReads, ma_utg_t *yReads, -uint32_t xUid, uint32_t yUid, long long xBegIndex, long long xEndIndex, long long yBegIndex, long long yEndIndex, -uint32_t rev, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* prevIndex, -uint32_t* xBeg, uint32_t* xEnd, uint32_t* yBeg, uint32_t* yEnd) -{ - long long offset; - long long new_xBeg, new_yBeg, new_xEnd, new_yEnd; - long long new_xIdxBeg, new_yIdxBeg, new_xIdxEnd, new_yIdxEnd; - - (*xBeg) = (*xEnd) = (*yBeg) = (*yEnd) = (uint32_t)-1; - if(!get_base_boundary_chain(ruIndex, reverse_sources, coverage_cut, read_g, position_index, - max_hang, min_ovlp, xReads, yReads, xUid, yUid, xBegIndex, xEndIndex, yBegIndex, yEndIndex, - rev, u_buffer, tailIndex, prevIndex)) - { - return; - } - ///base - new_xBeg = Get_xOff(u_buffer->a.a[tailIndex->a.a[0]].Off); - new_yBeg = Get_yOff(u_buffer->a.a[tailIndex->a.a[0]].Off); - new_xEnd = Get_xOff(u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].Off); - new_yEnd = Get_yOff(u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].Off); - - if(new_xBeg > new_xEnd || new_yBeg > new_yEnd) return; - - classify_hap_overlap(new_xBeg, new_xEnd, xReads->len, new_yBeg, new_yEnd, yReads->len, - &new_xBeg, &new_xEnd, &new_yBeg, &new_yEnd); - - if(rev) - { - new_yBeg = yReads->len - new_yBeg - 1; - new_yEnd = yReads->len - new_yEnd - 1; - offset = new_yBeg; new_yBeg = new_yEnd; new_yEnd = offset; - } - ///idx - get_idx_by_base(xReads, read_g, new_xBeg, new_xEnd, &new_xIdxBeg, &new_xIdxEnd); - get_idx_by_base(yReads, read_g, new_yBeg, new_yEnd, &new_yIdxBeg, &new_yIdxEnd); - if(new_xIdxBeg == -1 || new_xIdxEnd == -1 || new_yIdxBeg == -1 || new_yIdxEnd == -1) return; - - if(!get_base_boundary_chain(ruIndex, reverse_sources, coverage_cut, read_g, position_index, - max_hang, min_ovlp, xReads, yReads, xUid, yUid, new_xIdxBeg, new_xIdxEnd, new_yIdxBeg, - new_yIdxEnd, rev, u_buffer, tailIndex, prevIndex)) - { - return; - } - - (*xBeg) = Get_xOff(u_buffer->a.a[tailIndex->a.a[0]].Off); - (*yBeg) = Get_yOff(u_buffer->a.a[tailIndex->a.a[0]].Off); - (*xEnd) = Get_xOff(u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].Off); - (*yEnd) = Get_yOff(u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].Off); -} - -#define generic_key(x) (x) -KRADIX_SORT_INIT(i32, int32_t, generic_key, sizeof(int32_t)) -KRADIX_SORT_INIT(ru32, uint32_t, generic_key, sizeof(uint32_t)) - -long long get_chain_score(ma_utg_t *xReads, asg_t *read_g, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* idx, -ma_hit_t_alloc* reverse_sources, long long xBegPos, long long xEndPos) -{ - long long offset, r_beg, r_end, inp_beg, inp_end, hap_beg, hap_end, inp_match, hap_match, ovlp; - uint64_t i, k, rId; - idx->a.n = 0; - - for (i = k = 0; i < tailIndex->a.n; i++) - { - rId = u_buffer->a.a[tailIndex->a.a[i]].x.ul>>33; - - - for (; k < xReads->n; k++) - { - if(rId == (xReads->a[k]>>33)) break; - } - - if(k >= xReads->n) - { - for (k = 0; k < xReads->n; k++) - { - if(rId == (xReads->a[k]>>33)) break; - } - } - - if(k < xReads->n) kv_push(int32_t, idx->a, k); - else - { - fprintf(stderr, "\nERROR-get_chain_score: tailIndex->a.n: %lu, xReads->n: %lu\n", (uint64_t)tailIndex->a.n, (uint64_t)xReads->n); - } - } - - - radix_sort_i32(idx->a.a, idx->a.a + idx->a.n); - inp_beg = -1; inp_end = -2; - hap_beg = -1; hap_end = -2; - for (i = k = 0, offset = 0, inp_match = hap_match = 0; i < xReads->n; i++) - { - rId = xReads->a[i]>>33; - r_beg = offset; r_end = offset + (long long)(read_g->seq[rId].len) - 1; - offset += (uint32_t)xReads->a[i]; - - if(reverse_sources[rId].length > 0) - { - if(r_beg <= hap_end) - { - hap_end = MAX(hap_end, r_end); - } - else - { - ///match += (hap_end - hap_beg + 1); - ovlp = (long long)(MIN(hap_end, xEndPos)) - (long long)(MAX(hap_beg, xBegPos)) + 1; - hap_match += (ovlp >= 0? ovlp : 0); - hap_beg = r_beg; hap_end = r_end; - } - } - - for (; k < idx->a.n; k++) - { - if(i <= (uint64_t)idx->a.a[k]) break; - } - - if(k >= idx->a.n) continue; - - if(i == (uint64_t)idx->a.a[k]) - { - if(r_beg <= inp_end) - { - inp_end = MAX(inp_end, r_end); - } - else - { - ovlp = (long long)(MIN(inp_end, xEndPos)) - (long long)(MAX(inp_beg, xBegPos)) + 1; - inp_match += (ovlp >= 0? ovlp : 0); - inp_beg = r_beg; inp_end = r_end; - } - } - } - - ovlp = (long long)(MIN(inp_end, xEndPos)) - (long long)(MAX(inp_beg, xBegPos)) + 1; - inp_match += (ovlp >= 0? ovlp : 0); - - ovlp = (long long)(MIN(hap_end, xEndPos)) - (long long)(MAX(hap_beg, xBegPos)) + 1; - hap_match += (ovlp >= 0? ovlp : 0); - - // if(inp_match > (xEndPos - xBegPos + 1)) fprintf(stderr, "ERROR1\n"); - // if(hap_match > (xEndPos - xBegPos + 1)) fprintf(stderr, "ERRO2\n"); - // if(inp_match > hap_match) fprintf(stderr, "ERROR3\n"); - // fprintf(stderr, "tailIndex->a.n: %u, xReads->n: %u, total_match: %lld, hap_match: %lld, inp_match: %lld\n", - // tailIndex->a.n, xReads->n, (xEndPos - xBegPos + 1), hap_match, inp_match); - - return ((double)(inp_match)*CHAIN_MATCH) - ((double)(hap_match-inp_match)*CHAIN_UNMATCH); -} - - -uint32_t determine_hap_overlap_type_advance(hap_candidates* hap_can, ma_utg_t *xReads, ma_utg_t *yReads, -R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, asg_t *read_g, uint64_t* position_index, -int max_hang, int min_ovlp, uint32_t xUid, uint32_t yUid, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, -kvec_t_i32_warp* prevIndex, long long* r_x_pos_beg, long long* r_x_pos_end, long long* r_y_pos_beg, long long* r_y_pos_end) -{ - uint32_t x_pos_beg, y_pos_beg, x_pos_end, y_pos_end; - /*************************x***************************/ - get_base_boundary_advance(ruIndex, reverse_sources, coverage_cut, read_g, position_index, - max_hang, min_ovlp, xReads, yReads, xUid, yUid, Get_x_beg(*hap_can), Get_x_end(*hap_can), - Get_y_beg(*hap_can), Get_y_end(*hap_can), Get_rev(*hap_can), u_buffer, tailIndex, prevIndex, - &x_pos_beg, &x_pos_end, &y_pos_beg, &y_pos_end); - /*************************x***************************/ - if(x_pos_beg == (uint32_t)-1 || y_pos_beg == (uint32_t)-1 - || x_pos_end == (uint32_t)-1 || y_pos_end == (uint32_t)-1) - { - return (uint32_t)-1; - } - if(x_pos_beg > x_pos_end || y_pos_beg > y_pos_end) return (uint32_t)-1; - - /** - #define X2Y 0 - #define Y2X 1 - #define XCY 2 - #define YCX 3 - **/ - hap_can->index_end = classify_hap_overlap(x_pos_beg, x_pos_end, xReads->len, y_pos_beg, y_pos_end, yReads->len, - r_x_pos_beg, r_x_pos_end, r_y_pos_beg, r_y_pos_end); - hap_can->x_beg_pos = MIN((uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[0]].x.ul>>33]), - (uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].x.ul>>33])); - hap_can->x_end_pos = MAX((uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[0]].x.ul>>33]), - (uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].x.ul>>33])); - hap_can->y_beg_pos = MIN((uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[0]].x.v>>1]), - (uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].x.v>>1])); - hap_can->y_end_pos = MAX((uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[0]].x.v>>1]), - (uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].x.v>>1])); - double xLeftMatch, xLeftTotal; - get_pair_hap_similarity(xReads->a + hap_can->x_beg_pos, hap_can->x_end_pos + 1 - hap_can->x_beg_pos, - yUid, reverse_sources, read_g, ruIndex, &xLeftMatch, &xLeftTotal); - if(xLeftMatch == 0 || xLeftTotal == 0) return (uint32_t)-1; - hap_can->weight = xLeftMatch; - hap_can->index_beg = xLeftTotal; - hap_can->score = get_chain_score(xReads, read_g, u_buffer, tailIndex, prevIndex, reverse_sources, - (*r_x_pos_beg), (*r_x_pos_end)); - if(hap_can->score <= 0) return (uint32_t)-1; - return hap_can->index_end; -} - - - -uint32_t determine_hap_overlap_type(hap_candidates* hap_can, ma_utg_t *xReads, ma_utg_t *yReads, -R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, asg_t *read_g, -uint64_t* position_index, int max_hang, int min_ovlp, uint32_t xUid, uint32_t yUid, -long long* r_x_pos_beg, long long* r_x_pos_end, long long* r_y_pos_beg, long long* r_y_pos_end) -{ - uint32_t x_pos_beg, y_pos_beg, x_pos_end, y_pos_end; - /*************************x***************************/ - get_base_boundary(ruIndex, reverse_sources, coverage_cut, read_g, position_index, max_hang, - min_ovlp, xReads, yReads, xUid, yUid, Get_x_beg(*hap_can), Get_x_end(*hap_can), - Get_y_beg(*hap_can), Get_y_end(*hap_can), 0, Get_rev(*hap_can), &x_pos_beg, &y_pos_beg); - - get_base_boundary(ruIndex, reverse_sources, coverage_cut, read_g, position_index, max_hang, - min_ovlp, xReads, yReads, xUid, yUid, Get_x_beg(*hap_can), Get_x_end(*hap_can), - Get_y_beg(*hap_can), Get_y_end(*hap_can), 1, Get_rev(*hap_can), &x_pos_end, &y_pos_end); - /*************************x***************************/ - - if(x_pos_beg == (uint32_t)-1 || y_pos_beg == (uint32_t)-1 - || x_pos_end == (uint32_t)-1 || y_pos_end == (uint32_t)-1) - { - return (uint32_t)-1; - } - if(x_pos_beg > x_pos_end || y_pos_beg > y_pos_end) return (uint32_t)-1; - - /** - #define X2Y 0 - #define Y2X 1 - #define XCY 2 - #define YCX 3 - **/ - return classify_hap_overlap(x_pos_beg, x_pos_end, xReads->len, y_pos_beg, y_pos_end, yReads->len, - r_x_pos_beg, r_x_pos_end, r_y_pos_beg, r_y_pos_end); -} - -void adjust_hap_overlaps_score(ma_utg_t* xReads, float *sim, long long *score, -long long xUid, long long yUid, long long xBeg, long long xEnd) -{ - uint64_t all, found; - if(count_unique_k_mers(xReads->s + xBeg, xEnd+1-xBeg, xUid, yUid, &all, &found)) - { - double k_w = 1; - if(sim) (*sim) = MAX((*sim), (all == 0?0:(((double)found)/((double)all)))); - if(all) k_w += ((double)(found)/(double)(all)); - if(score) (*score) = ((*score)*k_w)/2; - } -} - -uint32_t calculate_pair_hap_similarity_advance(hap_candidates* hap_can, -uint64_t* position_index, uint32_t xUid, uint32_t yUid, ma_utg_t* xReads, ma_utg_t* yReads, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, ma_sub_t *coverage_cut, -float Hap_rate, int is_local, int max_hang, int min_ovlp, uint64_t cov_threshold, kvec_asg_arc_t_offset* u_buffer, -kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* prevIndex, hap_cov_t *cov, long long* r_x_pos_beg, long long* r_x_pos_end, -long long* r_y_pos_beg, long long* r_y_pos_end, float *sim) -{ - uint32_t max_count = 0, min_count = 0, flag; - uint32_t xLen = xReads->n, xIndex; - uint32_t yLen = yReads->n, yIndex; - uint32_t xLeftBeg, xLeftLen, yLeftBeg, yLeftLen; - uint32_t xRightBeg, xRightLen, yRightBeg, yRightLen; - double xLeftMatch = 0, xLeftTotal = 0, yLeftMatch = 0, yLeftTotal = 0; - double xRightMatch = 0, xRightTotal = 0, yRightMatch = 0, yRightTotal = 0; - asg_arc_t* arch = NULL; - - - arch = &(hap_can->t); - xIndex = (uint32_t)(position_index[arch->ul>>33]); - yIndex = (uint32_t)(position_index[arch->v>>1]); - - if(hap_can->rev == 0) - { - xLeftBeg = 0; xLeftLen = xIndex; xRightBeg = xIndex; xRightLen = xLen - xRightBeg; - yLeftBeg = 0; yLeftLen = yIndex; yRightBeg = yIndex; yRightLen = yLen - yRightBeg; - } - else - { - xLeftBeg = 0; xLeftLen = xIndex; xRightBeg = xIndex; xRightLen = xLen - xRightBeg; - - yLeftBeg = yIndex + 1; yLeftLen = yLen - yLeftBeg; - yRightBeg = 0; yRightLen = yIndex + 1; - } - - flag = Get_type(*hap_can); - - - if(flag == XCY) - { - get_pair_hap_similarity(yReads->a, yLen, xUid, reverse_sources, read_g, ruIndex, - &yLeftMatch, &yLeftTotal); - max_count = yLeftMatch; - min_count = yLeftTotal; - } - else if(flag == YCX) - { - get_pair_hap_similarity(xReads->a, xLen, yUid, reverse_sources, read_g, ruIndex, - &xLeftMatch, &xLeftTotal); - max_count = xLeftMatch; - min_count = xLeftTotal; - } - else if(flag == X2Y) - { - get_pair_hap_similarity(yReads->a+yLeftBeg, yLeftLen, xUid, reverse_sources, read_g, ruIndex, - &yLeftMatch, &yLeftTotal); - get_pair_hap_similarity(xReads->a+xRightBeg, xRightLen, yUid, reverse_sources, read_g, ruIndex, - &xRightMatch, &xRightTotal); - max_count = yLeftMatch + xRightMatch; - min_count = yLeftTotal + xRightTotal; - } - else if(flag == Y2X) - { - get_pair_hap_similarity(xReads->a+xLeftBeg, xLeftLen, yUid, reverse_sources, read_g, ruIndex, - &xLeftMatch, &xLeftTotal); - get_pair_hap_similarity(yReads->a+yRightBeg, yRightLen, xUid, reverse_sources, read_g, ruIndex, - &yRightMatch, &yRightTotal); - max_count = xLeftMatch + yRightMatch; - min_count = xLeftTotal + yRightTotal; - } else abort(); - - hap_can->weight = hap_can->index_beg = 0; - if(min_count == 0) return NON_PLOID; - if((max_count > min_count*Hap_rate) || is_local) - { - long long r_x_interval_beg, r_x_interval_end, r_y_interval_beg, r_y_interval_end; - uint64_t ploid_coverage = 0; - - ///for containment, don't need to do anything - get_hap_alignment_boundary(xReads, yReads, flag, xLeftMatch, xLeftTotal, - yLeftMatch, yLeftTotal, xRightMatch, xRightTotal, yRightMatch, yRightTotal, - xLeftBeg, xLeftLen, yLeftBeg, yLeftLen, xRightBeg, xRightLen, yRightBeg, yRightLen, - xUid, yUid, Hap_rate, is_local, position_index, reverse_sources, read_g, ruIndex, - hap_can->rev, &r_x_interval_beg, &r_x_interval_end, &r_y_interval_beg, &r_y_interval_end); - - if(r_x_interval_beg < 0 || r_x_interval_end < 0 || r_y_interval_beg < 0 || r_y_interval_end < 0) - { - return NON_PLOID; - } - - get_pair_hap_similarity(xReads->a + r_x_interval_beg, r_x_interval_end + 1 - r_x_interval_beg, - yUid, reverse_sources, read_g, ruIndex, &xLeftMatch, &xLeftTotal); - if(xLeftMatch == 0 || xLeftTotal == 0 || (is_local == 0 && xLeftMatch <= xLeftTotal*Hap_rate)) - { - return NON_PLOID; - } - - - hap_can->weight = xLeftMatch; - hap_can->index_beg = xLeftTotal; - hap_can->index_end = flag; - hap_can->x_beg_pos = r_x_interval_beg; - hap_can->x_end_pos = r_x_interval_end; - hap_can->y_beg_pos = r_y_interval_beg; - hap_can->y_end_pos = r_y_interval_end; - hap_can->index_end = determine_hap_overlap_type_advance(hap_can, xReads, yReads, - ruIndex, reverse_sources, coverage_cut, read_g, position_index, max_hang, min_ovlp, - xUid, yUid, u_buffer, tailIndex, prevIndex, r_x_pos_beg, r_x_pos_end, r_y_pos_beg, - r_y_pos_end); - if(hap_can->index_end == XCY && yReads->len > (xReads->len*2)) return NON_PLOID; - if(hap_can->index_end == YCX && xReads->len > (yReads->len*2)) return NON_PLOID; - if(hap_can->index_end == (uint32_t)-1) return NON_PLOID; - - ploid_coverage = get_pair_purge_coverage(xReads, *r_x_pos_beg, *r_x_pos_end, - yReads, *r_y_pos_beg, *r_y_pos_end, hap_can->rev, read_g, cov); - - if(cov_threshold > 0 && ploid_coverage >= cov_threshold) return NON_PLOID; - - get_pair_hap_similarity_by_base(xReads, read_g, yUid, reverse_sources, ruIndex, - *r_x_pos_beg, *r_x_pos_end, &xLeftMatch, &xLeftTotal); - (*sim) = (xLeftTotal== 0? 0:((double)xLeftMatch)/((double)xLeftTotal)); - - // adjust_hap_overlaps_score(xReads, sim, &(hap_can->score), xUid, yUid, (*r_x_pos_beg), (*r_x_pos_end)); - - if(xLeftMatch == 0 || xLeftTotal == 0 || (*sim) <= Hap_rate) - { - return NON_PLOID; - } - - return PLOID; - } - return NON_PLOID; -} - - -void print_hap_paf(ma_ug_t *ug, hap_overlaps* ovlp) -{ - fprintf(stderr, "utg%.6d%c\t%u(%u)\t%u(%u)\t%u(%u)\t%c\tutg%.6d%c\t%u(%u)\t%u(%u)\t%u(%u)\t%u\t%u\t%lld(%u)\n", - ovlp->xUid+1, "lc"[ug->u.a[ovlp->xUid].circ], ug->u.a[ovlp->xUid].len, ug->u.a[ovlp->xUid].n, - ovlp->x_beg_pos, ovlp->x_beg_id, ovlp->x_end_pos, ovlp->x_end_id, "+-"[ovlp->rev], - ovlp->yUid+1, "lc"[ug->u.a[ovlp->yUid].circ], ug->u.a[ovlp->yUid].len, ug->u.a[ovlp->yUid].n, - ovlp->y_beg_pos, ovlp->y_beg_id, ovlp->y_end_pos, ovlp->y_end_id, ovlp->type, ovlp->weight, - ovlp->score, ovlp->status); -} - -inline long long get_max_index(asg_arc_t_offset* x, int32_t* Scores, uint8_t* Flag, long long n, -long long x_readLen, long long y_readLen) -{ - long long i = 0, max_result = -1, max_i = -1, min_xLen = x_readLen * 2 + 2, x_off, y_off, tmp_xLen; - for (i = 0; i < n; i++) - { - if(Flag[i] != 0) continue; - x_off = (long long)(x[i].Off>>32); - y_off = (long long)((uint32_t)x[i].Off); - if(Scores[i] > max_result) - { - max_result = Scores[i]; - max_i = i; - min_xLen = get_hap_overlapLen(x_off, x_off, x_readLen, y_off, y_off, y_readLen, - NULL, NULL, NULL, NULL); - } - else if(Scores[i] == max_result) - { - tmp_xLen = get_hap_overlapLen(x_off, x_off, x_readLen, y_off, y_off, y_readLen, - NULL, NULL, NULL, NULL); - - if(tmp_xLen < min_xLen) - { - max_result = Scores[i]; - max_i = i; - min_xLen = tmp_xLen; - } - } - } - - return max_i; -} - - -inline void get_chain_details(int32_t* Pres, int32_t* Results, uint8_t* Flag, long long max_i, -long long* chainLen, long long* dup) -{ - long long i = max_i; - (*chainLen) = 0; - (*dup) = 0; - - while (i >= 0) - { - if(Flag[i] == 1) (*dup)++; - Results[(*chainLen)] = i; - i = Pres[i]; - (*chainLen)++; - } -} - -inline void push_hap_can(asg_arc_t_offset* x, kvec_hap_candidates* u_can, int32_t* Results, -long long chainLen, long long x_readLen, long long y_readLen) -{ - if(chainLen <= 0) return; - hap_candidates hap_can; - hap_can.rev = x[Results[0]].x.el; - hap_can.x_beg_pos = hap_can.x_end_pos = (uint32_t)(x[Results[0]].Off>>32); - hap_can.y_beg_pos = hap_can.y_end_pos = (uint32_t)(x[Results[0]].Off); - hap_can.weight = 0; - long long i = 0; - uint64_t totalWeigth = 0; - ///fprintf(stderr, "^^^chainLen: %lld\n", chainLen); - for (i = 0; i < chainLen; i++) - { - ///fprintf(stderr, "i: %lld, Results[i]: %d\n", i, Results[i]); - hap_can.x_beg_pos = (uint32_t)(x[Results[i]].Off>>32); - hap_can.y_beg_pos = (uint32_t)(x[Results[i]].Off); - hap_can.weight += x[Results[i]].weight; - } - - for (i = 0; i < chainLen; i++) - { - totalWeigth += x[Results[i]].weight; - if(totalWeigth >= (hap_can.weight/2)) break; - } - - if(i >= chainLen) i = chainLen-1; - ///Get_total(hap_can) = Results[i]; - hap_can.t = x[Results[i]].x; - Get_type(hap_can) = classify_hap_overlap(hap_can.x_beg_pos, hap_can.x_end_pos, - x_readLen, hap_can.y_beg_pos, hap_can.y_end_pos, y_readLen, NULL, NULL, NULL, NULL); - kv_push(hap_candidates, u_can->a, hap_can); - if(hap_can.x_beg_pos > hap_can.x_end_pos || hap_can.y_beg_pos > hap_can.y_end_pos) - { - fprintf(stderr, "ERROR\n"); - } -} - - - -void print_chain_data(int32_t* Scores, int32_t* Pres, int32_t* Begs, long long n) -{ - fprintf(stderr,"*****\nn_chain: %lld\n", n); - long long i; - for (i = 0; i < n; i++) - { - fprintf(stderr, "i: %lld, Scores: %d, Pres: %d, Begs: %d\n", - i, Scores[i], Pres[i], Begs[i]); - } -} - - - -void hap_chaining(asg_arc_t_offset* x, uint32_t n, kvec_t_i32_warp* score_vc, kvec_t_i32_warp* prevIndex_vec, -kvec_t_i32_warp* begIndex_vec, kvec_t_u8_warp* flag_vec, float band_width_threshold, long long max_skip, -long long x_readLen, long long y_readLen, kvec_hap_candidates* u_can) -{ - #define DUP_OVLP_RATE 0.75 - score_vc->a.n = prevIndex_vec->a.n = begIndex_vec->a.n = flag_vec->a.n = 0; - if(n == 0) return; - kv_resize(int32_t, score_vc->a, n); - kv_resize(int32_t, prevIndex_vec->a, n); - kv_resize(int32_t, begIndex_vec->a, n); - kv_resize(uint8_t, flag_vec->a, n); - - int32_t* Scores = score_vc->a.a; - int32_t* Pres = prevIndex_vec->a.a; - int32_t* Begs = begIndex_vec->a.a; - uint8_t* Flag = flag_vec->a.a; - long long i, j, n_max_skip, x_off, y_off, max_beg, max_j = -1, max_score, score; - long long distance_x, distance_y, total_distance_x, total_distance_y, distance_gap; - float gap_rate, band_width_penalty = 1 / band_width_threshold; - long long max_result, max_i, min_xLen, tmp_xLen, chainLen = 0, dup = 0; - max_result = max_i = -1; min_xLen = x_readLen * 2 + 2; - for (i = 0; i < n; i++) - { - n_max_skip = 0; - - x_off = (long long)(x[i].Off>>32); - y_off = (long long)((uint32_t)x[i].Off); - max_j = -1; - max_score = x[i].weight; - max_beg = i; //i itself - ///may have a pre-cut condition for j - for (j = i - 1; j >= 0; --j) - { - distance_x = x_off - (long long)(x[j].Off>>32); - distance_y = y_off - (long long)((uint32_t)x[j].Off); - ///x has been sorted by x_off - if(distance_x <= 0 || distance_y <= 0) continue; - - total_distance_x = x_off - (long long)(x[Begs[j]].Off>>32); - total_distance_y = y_off - (long long)((uint32_t)x[Begs[j]].Off); - - distance_gap = total_distance_x - total_distance_y; - if(distance_gap < 0) distance_gap = -distance_gap; - if(distance_gap > band_width_threshold * total_distance_x) - { - continue; - } - - score = x[i].weight; - gap_rate = (float)((float)(distance_gap)/(float)(total_distance_x)); - score -= (long long)(score * gap_rate * band_width_penalty); - score += Scores[j]; - - ///find a new max score - if (score > max_score) { - max_score = score; - max_j = j; - max_beg = Begs[j]; - n_max_skip = 0; - } - else - { - if (++n_max_skip > max_skip) break; - } - } - - Scores[i] = max_score; - Pres[i] = max_j; - Begs[i] = max_beg; - - if(Scores[i] > max_result) - { - max_result = Scores[i]; - max_i = i; - min_xLen = get_hap_overlapLen(x_off, x_off, x_readLen, y_off, y_off, y_readLen, - NULL, NULL, NULL, NULL); - } - else if(Scores[i] == max_result) - { - tmp_xLen = get_hap_overlapLen(x_off, x_off, x_readLen, y_off, y_off, y_readLen, - NULL, NULL, NULL, NULL); - - if(tmp_xLen < min_xLen) - { - max_result = Scores[i]; - max_i = i; - min_xLen = tmp_xLen; - } - } - Flag[i] = 0; - } - - // print_asg_arc_t_offset(x, n); - // print_chain_data(Scores, Pres, Begs, n); - while (max_i != -1) - { - get_chain_details(Pres, Begs, Flag, max_i, &chainLen, &dup); - if(chainLen == 0) break; - if(dup > chainLen*DUP_OVLP_RATE) - { - for (i = 0; i < chainLen; i++) - { - if(Flag[Begs[i]] == 1) continue; - Flag[Begs[i]] = 2; - } - - } - else - { - push_hap_can(x, u_can, Begs, chainLen, x_readLen, y_readLen); - - for (i = 0; i < chainLen; i++) - { - Flag[Begs[i]] = 1; - } - } - - max_i = get_max_index(x, Scores, Flag, n, x_readLen, y_readLen); - } -} - -void get_candidate_hap_alignment(kvec_hap_candidates* u_can, kvec_asg_arc_t_offset* u_buffer, -kvec_t_i32_warp* score_vc, kvec_t_i32_warp* prevIndex_vec, kvec_t_i32_warp* begIndex_vec, -kvec_t_u8_warp* flag_vec, float band_width_threshold, long long max_skip, long long x_readLen, -long long y_readLen) -{ - u_can->a.n = 0; - if(u_buffer->a.n == 0) return; - uint32_t i = 0, /**anchor_i = 0, **/m = 1, break_point = (uint32_t)-1, is_merge; - - qsort(u_buffer->a.a, u_buffer->a.n, sizeof(asg_arc_t_offset), cmp_hap_alignment_chaining); - - ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n); - - for (i = 1; i < u_buffer->a.n; i++) - { - is_merge = 0; - if(u_buffer->a.a[m-1].x.el == u_buffer->a.a[i].x.el) - { - if(u_buffer->a.a[m-1].Off == u_buffer->a.a[i].Off) is_merge = 1; - ///I think we don't need the following merging - // if(is_merge == 0 && (Get_xOff(u_buffer->a.a[m-1].Off)==Get_xOff(u_buffer->a.a[i].Off))) - // { - // if((Get_yOff(u_buffer->a.a[i].Off)-(Get_yOff(u_buffer->a.a[m-1].Off))) == (i-anchor_i))///not sure why, does it use for tolerate indels in overlaps? - // { - // is_merge = 1; - // } - // } - - if(is_merge) - { - u_buffer->a.a[m-1].weight += u_buffer->a.a[i].weight; - continue; - } - } - u_buffer->a.a[m] = u_buffer->a.a[i]; - // anchor_i = i; - if(u_buffer->a.a[m].x.el != u_buffer->a.a[m-1].x.el) break_point = m; - m++; - } - u_buffer->a.n = m; - if(break_point > u_buffer->a.n) break_point = u_buffer->a.n; - - ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n); - - hap_chaining(u_buffer->a.a, break_point, score_vc, prevIndex_vec, begIndex_vec, flag_vec, - band_width_threshold, max_skip, x_readLen, y_readLen, u_can); - - hap_chaining(u_buffer->a.a + break_point, u_buffer->a.n - break_point, score_vc, prevIndex_vec, - begIndex_vec, flag_vec, band_width_threshold, max_skip, x_readLen, y_readLen, u_can); -} - -int filter_secondary_chain(long long max_score, long long cur_score, double rate) -{ - if(cur_score >= max_score) return 1; - long long diff = max_score - cur_score; - if(max_score < 0) max_score *= -1; - if(diff >= max_score*(1-rate)) return 0; - return 1; -} - - -void filter_secondary_ovlp(kvec_hap_overlaps *x, kvec_t_u64_warp *a, float sim_flt, float ovlp_flt) -{ - if(sim_flt == 0 || ovlp_flt == 0 || x->a.n == 0) return; - #define f_ovlp(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) - uint32_t i, m, k; - uint64_t t, ovlp; - hap_overlaps *p = NULL; - a->a.n = 0; - for (i = 0; i < x->a.n; i++) - { - if(x->a.a[i].s < sim_flt) continue; - t = x->a.a[i].x_beg_pos; t<<=32; t |= x->a.a[i].x_end_pos; - kv_push(uint64_t, a->a, t); - } - - if(a->a.n == 0) return; - ks_introsort_uint64_t(a->a.n, a->a.a); - - for (i = m = 1; i < a->a.n; ++i) - { - t = a->a.a[m-1]; - ovlp = f_ovlp(t>>32, (uint32_t)t, a->a.a[i]>>32, (uint32_t)a->a.a[i]); - if(ovlp == 0) - { - a->a.a[m] = a->a.a[i]; - m++; - } - else - { - t = MIN(a->a.a[m-1]>>32, a->a.a[i]>>32); - t<<=32; - t |= MAX((uint32_t)a->a.a[m-1], (uint32_t)a->a.a[i]); - a->a.a[m-1] = t; - } - } - a->a.n = m; - - for (i = m = 0; i < x->a.n; i++) - { - p = &(x->a.a[i]); - if(p->s < sim_flt) - { - for (k = ovlp = 0; k < a->a.n; k++) - { - ovlp += f_ovlp(p->x_beg_pos, p->x_end_pos, a->a.a[k]>>32, (uint32_t)a->a.a[k]); - if(ovlp >= ovlp_flt*(p->x_end_pos-p->x_beg_pos)) break; - } - if(k < a->a.n) continue; - if(ovlp >= ovlp_flt*(p->x_end_pos-p->x_beg_pos)) continue; - } - x->a.a[m] = x->a.a[i]; - m++; - } - x->a.n = m; -} - -static void hap_alignment_advance_worker(void *_data, long eid, int tid) -{ - hap_alignment_struct_pip* hap_buf = (hap_alignment_struct_pip*)_data; - ma_ug_t *ug = hap_buf->ug; - asg_t *read_g = hap_buf->read_g; - ma_hit_t_alloc* sources = hap_buf->sources; - ma_hit_t_alloc* reverse_sources = hap_buf->reverse_sources; - R_to_U* ruIndex = hap_buf->ruIndex; - ma_sub_t *coverage_cut = hap_buf->coverage_cut; - uint64_t* position_index = hap_buf->position_index; - float Hap_rate = hap_buf->Hap_rate/**MIN(hap_buf->Hap_rate, 0.2)**/, sim; - int max_hang = hap_buf->max_hang; - int min_ovlp = hap_buf->min_ovlp; - float chain_rate = hap_buf->chain_rate; - hap_overlaps_list* all_ovlp = hap_buf->all_ovlp; - uint32_t Input_uId = eid; - uint64_t* vote_counting = hap_buf->buf[tid].vote_counting; - uint8_t* visit = hap_buf->buf[tid].visit; - kvec_t_u64_warp* u_vecs = &(hap_buf->buf[tid].u_vecs); - kvec_asg_arc_t_offset* u_buffer = &(hap_buf->buf[tid].u_buffer); - kvec_hap_candidates* u_can = &(hap_buf->buf[tid].u_can); - kvec_t_i32_warp* score_vc = &(hap_buf->buf[tid].u_buffer_tailIndex); - kvec_t_i32_warp* prevIndex_vec = &(hap_buf->buf[tid].u_buffer_prevIndex); - kvec_t_i32_warp* begIndex_vec = &(hap_buf->buf[tid].u_buffer_beg); - kvec_t_u8_warp* flag_vec = &(hap_buf->buf[tid].u_buffer_flag); - uint64_t cov_threshold = hap_buf->cov_threshold; - hap_cov_t *cov = hap_buf->cov; - uint8_t *hh = hap_buf->hh, hhc; - if(hap_buf->cov_threshold < 0) cov_threshold = (uint64_t)-1; - ma_utg_t *xReads = NULL, *yReads = NULL; - ma_hit_t_alloc *xR = NULL; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL, *st = NULL; - asg_t* nsg = ug->g; - uint32_t i, j, v, rId, k, is_Unitig, Hap_uId, xUid, yUid, seedOcc; - uint64_t tmp, max_weight, m; - long long r_x_pos_beg, r_x_pos_end, r_y_pos_beg, r_y_pos_end, max_score; - int32_t r; - asg_arc_t t; - asg_arc_t_offset t_offset; - hap_overlaps hap_align; - hap_overlaps *hap_align_x = NULL; - xUid = Input_uId; - if(nsg->seq[xUid].del || nsg->seq[xUid].c == ALTER_LABLE) return; - memset(vote_counting, 0, sizeof(uint64_t)*nsg->n_seq); - memset(visit, 0, nsg->n_seq); - u_vecs->a.n = 0; - u_can->a.n = 0; - - xReads = &(ug->u.a[xUid]); - for (i = 0; i < xReads->n; i++) - { - xR = &(reverse_sources[xReads->a[i]>>33]); - - for (k = 0; k < xR->length; k++) - { - rId = Get_tn(xR->buffer[k]); - - if(read_g->seq[rId].del == 1) - { - ///get the id of read that contains it - get_R_to_U(ruIndex, rId, &rId, &is_Unitig); - if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; - } - - ///there are two cases: - ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id - ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 - get_R_to_U(ruIndex, rId, &Hap_uId, &is_Unitig); - if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; - ///here rId is the id of the read coming from the different haplotype - ///Hap_cId is the id of the corresponding contig (note here is the contig, instead of untig) - if(visit[Hap_uId]!=0) continue; ///one read only has one vote for one hap unitig - visit[Hap_uId] = 1; - if(vote_counting[Hap_uId] < UINT64_MAX) vote_counting[Hap_uId]++; - } - - clean_visit_flag(visit, read_g, ruIndex, nsg->n_seq, xR); - } - - - - u_vecs->a.n = 0; - for (i = 0; i < nsg->n_seq; i++) - { - if(i == xUid) continue; - if(vote_counting[i] == 0) continue; - tmp = vote_counting[i]; tmp = tmp << 32; tmp = tmp | (uint64_t)i; - kv_push(uint64_t, u_vecs->a, tmp); - } - - if(u_vecs->a.n == 0) return; - sort_kvec_t_u64_warp(u_vecs, 1); - - - ///scan each candidate unitig - for (i = 0; i < u_vecs->a.n; i++) - { - yUid = (uint32_t)u_vecs->a.a[i]; - seedOcc = u_vecs->a.a[i]>>32; - xReads = &(ug->u.a[xUid]); - yReads = &(ug->u.a[yUid]); - u_buffer->a.n = 0; - - for (k = 0; k < xReads->n; k++) - { - xR = &(reverse_sources[xReads->a[k]>>33]); - hhc = hh[xReads->a[k]>>33]; - for (j = 0; j < xR->length; j++) - { - h = &(xR->buffer[j]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(st->del || read_g->seq[Get_tn(*h)].del) continue; - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t); - ///if it is a contained overlap, skip - if(r < 0) continue; - - rId = t.v>>1; - if(read_g->seq[rId].del == 1) continue; - ///there are two cases: - ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id - ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 - get_R_to_U(ruIndex, rId, &Hap_uId, &is_Unitig); - if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; - if(Hap_uId != yUid) continue; - - v = xReads->a[k]>>32; - get_R_to_U(ruIndex, v>>1, &Hap_uId, &is_Unitig); - if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; - if(Hap_uId != xUid) continue; - if((uint32_t)(position_index[v>>1]) != k) continue; - - if(asm_opt.purge_level_primary <= 2 && - (prefilter((uint32_t)(position_index[v>>1]), (uint32_t)(position_index[rId]), - xReads->n, yReads->n, 0, Hap_rate, seedOcc)==NON_PLOID) && - (prefilter((uint32_t)(position_index[v>>1]), (uint32_t)(position_index[rId]), - xReads->n, yReads->n, 1, Hap_rate, seedOcc)==NON_PLOID)) - { - continue; - } - - t_offset.Off = get_xy_pos(read_g, &t, v, (yReads->a[(uint32_t)(position_index[rId])])>>32, - xReads->len, yReads->len, position_index, &(t.el)); - if(((t_offset.Off>>32) == (uint32_t)-1) || (((uint32_t)t_offset.Off) == (uint32_t)-1)) continue; - - t_offset.x = t; - t_offset.weight = hhc; - - kv_push(asg_arc_t_offset, u_buffer->a, t_offset); - } - - deduplicate_edge(u_buffer); - } - - if(u_buffer->a.n == 0) continue; - - - get_candidate_hap_alignment(u_can, u_buffer, score_vc, prevIndex_vec, begIndex_vec, - flag_vec, chain_rate, 50, xReads->len, yReads->len); - - if(u_can->a.n == 0) continue; - - qsort(u_can->a.a, u_can->a.n, sizeof(hap_candidates), cmp_hap_candidates); - - memset(&hap_align, 0, sizeof(hap_overlaps)); - m = all_ovlp->x[xUid].a.n; - max_weight = 0; max_score = 0; - for (k = 0; k < u_can->a.n; k++) - { - if(u_can->a.a[k].weight < max_weight*0.33) continue; - if(calculate_pair_hap_similarity_advance(&(u_can->a.a[k]), position_index, xUid, yUid, - xReads, yReads, sources, reverse_sources, read_g, ruIndex, coverage_cut, Hap_rate, - (asm_opt.purge_level_primary<=2? 0:1), max_hang, min_ovlp, cov_threshold, u_buffer, - score_vc, prevIndex_vec, cov, &r_x_pos_beg, &r_x_pos_end, &r_y_pos_beg, &r_y_pos_end, &sim)!=PLOID) - { - continue; - } - ///max_weight == 0 means the first matched chain - if(max_weight == 0 || max_score < u_can->a.a[k].score) max_score = u_can->a.a[k].score; - if(max_weight < u_can->a.a[k].weight) max_weight = u_can->a.a[k].weight; - ///if one is positive and another one is negative, it is wrong - if(!filter_secondary_chain(max_score, u_can->a.a[k].score, CHAIN_FILTER_RATE)) continue; - - hap_align.rev = Get_rev(u_can->a.a[k]); - hap_align.type = Get_type(u_can->a.a[k]); - hap_align.x_beg_id = Get_x_beg(u_can->a.a[k]); - hap_align.x_end_id = Get_x_end(u_can->a.a[k]) + 1; - hap_align.y_beg_id = Get_y_beg(u_can->a.a[k]); - hap_align.y_end_id = Get_y_end(u_can->a.a[k]) + 1; - hap_align.weight = Get_match(u_can->a.a[k]); - hap_align.score = u_can->a.a[k].score; - hap_align.x_beg_pos = r_x_pos_beg; - hap_align.x_end_pos = r_x_pos_end + 1; - if(hap_align.rev == 0) - { - hap_align.y_beg_pos = r_y_pos_beg; - hap_align.y_end_pos = r_y_pos_end + 1; - } - else - { - hap_align.y_beg_pos = yReads->len - r_y_pos_end - 1; - hap_align.y_end_pos = yReads->len - r_y_pos_beg - 1 + 1; - } - hap_align.xUid = xUid; - hap_align.yUid = yUid; - hap_align.status = SELF_EXIST; - hap_align.s = sim; - kv_push(hap_overlaps, all_ovlp->x[hap_align.xUid].a, hap_align); - } - /** - ///chains with same xUid && yUid - for (k = m; k < all_ovlp->x[xUid].a.n; k++) - { - if(!filter_secondary_chain(max_score, - all_ovlp->x[xUid].a.a[k].score, CHAIN_FILTER_RATE)) - { - continue; - } - all_ovlp->x[xUid].a.a[m] = all_ovlp->x[xUid].a.a[k]; - m++; - } - all_ovlp->x[xUid].a.n = m; - **/ - - hap_align_x = NULL; - for (k = m; k < all_ovlp->x[xUid].a.n; k++) - { - if(all_ovlp->x[xUid].a.a[k].score != max_score) continue; - if(hap_align_x == NULL || all_ovlp->x[xUid].a.a[k].weight > hap_align_x->weight) - { - hap_align_x = &(all_ovlp->x[xUid].a.a[k]); - } - else if(all_ovlp->x[xUid].a.a[k].weight == hap_align_x->weight) - { - if((all_ovlp->x[xUid].a.a[k].x_end_pos - - all_ovlp->x[xUid].a.a[k].x_beg_pos) < - (hap_align_x->x_end_pos - hap_align_x->x_beg_pos)) - { - hap_align_x = &(all_ovlp->x[xUid].a.a[k]); - } - } - } - if(hap_align_x) - { - all_ovlp->x[xUid].a.a[m] = (*hap_align_x); - all_ovlp->x[xUid].a.n = m + 1; - } - } - // filter_secondary_ovlp(&all_ovlp->x[xUid], u_vecs, hap_buf->Hap_rate, 0.7); -} - -int get_specific_hap_overlap(kvec_hap_overlaps* x, uint32_t qn, uint32_t tn) -{ - uint32_t i; - for (i = 0; i < x->a.n; i++) - { - if(x->a.a[i].xUid == qn && x->a.a[i].yUid == tn) - { - return i; - } - } - - return -1; -} - -void set_reverse_hap_overlap(hap_overlaps* dest, hap_overlaps* source, uint32_t* types) -{ - dest->status = REVE_EXIST; - dest->rev = source->rev; - dest->type = types[source->type]; - dest->weight = source->weight; - dest->xUid = source->yUid; - dest->yUid = source->xUid; - dest->x_beg_pos = source->y_beg_pos; - dest->x_end_pos = source->y_end_pos; - dest->y_beg_pos = source->x_beg_pos; - dest->y_end_pos = source->x_end_pos; - dest->x_beg_id = source->y_beg_id; - dest->x_end_id = source->y_end_id; - dest->y_beg_id = source->x_beg_id; - dest->y_end_id = source->x_end_id; - dest->score = source->score; -} - -/** -#define X2Y 0 -#define Y2X 1 -#define XCY 2 -#define YCX 3 -**/ -void normalize_hap_overlaps(hap_overlaps_list* all_ovlp, hap_overlaps_list* back_all_ovlp) -{ - hap_overlaps *x = NULL, *y = NULL; - uint32_t v, i, uId, qn, tn; - uint32_t types[4]; - types[X2Y] = Y2X; types[Y2X] = X2Y; types[XCY] = YCX; types[YCX] = XCY; - int index; - for (v = 0; v < all_ovlp->num; v++) - { - uId = v; - for (i = 0; i < all_ovlp->x[uId].a.n; i++) - { - qn = all_ovlp->x[uId].a.a[i].xUid; - tn = all_ovlp->x[uId].a.a[i].yUid; - x = &(all_ovlp->x[uId].a.a[i]); - index = get_specific_hap_overlap(&(all_ovlp->x[tn]), tn, qn); - if(index != -1) - { - y = &(all_ovlp->x[tn].a.a[index]); - if(x->rev == y->rev && types[x->type]==y->type) continue; - if(x->weight >= y->weight) - { - kv_push(hap_overlaps, back_all_ovlp->x[tn].a, (*y)); - set_reverse_hap_overlap(y, x, types); - } - else - { - kv_push(hap_overlaps, back_all_ovlp->x[qn].a, (*x)); - set_reverse_hap_overlap(x, y, types); - } - } - else - { - kv_pushp(hap_overlaps, all_ovlp->x[tn].a, &y); - set_reverse_hap_overlap(y, x, types); - } - } - } -} - -inline uint64_t calculate_bi_weight(hap_overlaps *x, ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* reverse_sources, -R_to_U* ruIndex) -{ - double xMatch, xTotal; - uint64_t weight = x->weight; - ma_utg_t *yReads = &(ug->u.a[x->yUid]); - get_pair_hap_similarity(yReads->a + x->y_beg_id, x->y_end_id - x->y_beg_id, - x->xUid, reverse_sources, read_g, ruIndex, &xMatch, &xTotal); - weight += xMatch; - return weight; -} - -void normalize_hap_overlaps_advance(hap_overlaps_list* all_ovlp, hap_overlaps_list* back_all_ovlp, -ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex) -{ - hap_overlaps *x = NULL, *y = NULL; - uint32_t v, i, uId, qn, tn; - uint32_t types[4]; - - types[X2Y] = Y2X; types[Y2X] = X2Y; types[XCY] = YCX; types[YCX] = XCY; - int index; - for (v = 0; v < all_ovlp->num; v++) - { - uId = v; - for (i = 0; i < all_ovlp->x[uId].a.n; i++) - { - qn = all_ovlp->x[uId].a.a[i].xUid; - tn = all_ovlp->x[uId].a.a[i].yUid; - x = &(all_ovlp->x[uId].a.a[i]); - index = get_specific_hap_overlap(&(all_ovlp->x[tn]), tn, qn); - if(index != -1) - { - y = &(all_ovlp->x[tn].a.a[index]); - if(x->rev == y->rev && types[x->type]==y->type) continue; - ///if(x->weight >= y->weight) - // if((calculate_bi_weight(x, ug, read_g, reverse_sources, ruIndex)) >= - // (calculate_bi_weight(y, ug, read_g, reverse_sources, ruIndex))) - if(x->score >= y->score) - { - kv_push(hap_overlaps, back_all_ovlp->x[tn].a, (*y)); - set_reverse_hap_overlap(y, x, types); - } - else - { - kv_push(hap_overlaps, back_all_ovlp->x[qn].a, (*x)); - set_reverse_hap_overlap(x, y, types); - } - } - else - { - kv_pushp(hap_overlaps, all_ovlp->x[tn].a, &y); - set_reverse_hap_overlap(y, x, types); - } - } - } -} - -void get_p_nodes(p_g_t *pg, p_node_t **x, uint32_t *x_occ, uint32_t id) -{ - if(x) (*x) = pg->pg_het_node.a + pg->pg_h_lev_idx.a[id].beg; - if(x_occ) (*x_occ) = pg->pg_h_lev_idx.a[id].occ; -} - -void normalize_hap_overlaps_advance_by_p_g_t(hap_overlaps_list* all_ovlp, hap_overlaps_list* back_all_ovlp, -ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, p_g_t *pg, hap_cov_t *cov, -double filter_rate) -{ - hap_overlaps *x = NULL, *y = NULL; - uint32_t v, i, uId, qn, tn; - uint32_t types[4]; - - - types[X2Y] = Y2X; types[Y2X] = X2Y; types[XCY] = YCX; types[YCX] = XCY; - int index; - uint32_t k, qs, qe, ts, te, occ, as, ae, ovlp, hetLen, homLen; - p_node_t *a = NULL; - - - for (v = 0; v < all_ovlp->num; v++) - { - uId = v; - for (i = 0; i < all_ovlp->x[uId].a.n; i++) - { - /*****************qn*****************/ - qn = all_ovlp->x[uId].a.a[i].xUid; - qs = all_ovlp->x[uId].a.a[i].x_beg_pos; - qe = all_ovlp->x[uId].a.a[i].x_end_pos - 1; - get_p_nodes(pg, &a, &occ, qn); - for (k = 0, hetLen = 0, homLen = 0; k < occ; k++) - { - as = a[k].baseBeg; - ae = a[k].baseEnd; - ovlp = ((MIN(qe, ae) >= MAX(qs, as))? MIN(qe, ae) - MAX(qs, as) + 1 : 0); - if(homLen + hetLen > 0 && ovlp == 0) break; - if(ovlp == 0) continue; - if(a[k].h_status == N_HET) - { - homLen += ovlp; - } - else if(asm_opt.polyploidy <= 2 && (a[k].h_status&P_HET))///if(asm_opt.polyploidy <= 2 && (a[k].h_status&S_HET)) - { - homLen += ovlp; - } - else - { - hetLen += ovlp; - } - } - - if(hetLen <= ((hetLen + homLen) * filter_rate)) - { - all_ovlp->x[uId].a.a[i].status = DELETE; - continue; - } - /*****************qn*****************/ - - - /*****************tn*****************/ - tn = all_ovlp->x[uId].a.a[i].yUid; - ts = all_ovlp->x[uId].a.a[i].y_beg_pos; - te = all_ovlp->x[uId].a.a[i].y_end_pos - 1; - get_p_nodes(pg, &a, &occ, tn); - for (k = 0, hetLen = 0, homLen = 0; k < occ; k++) - { - as = a[k].baseBeg; - ae = a[k].baseEnd; - ovlp = ((MIN(te, ae) >= MAX(ts, as))? MIN(te, ae) - MAX(ts, as) + 1 : 0); - if(homLen + hetLen > 0 && ovlp == 0) break; - if(ovlp == 0) continue; - if(a[k].h_status == N_HET) - { - homLen += ovlp; - } - else if(asm_opt.polyploidy <= 2 && (a[k].h_status&P_HET))///if(asm_opt.polyploidy <= 2 && (a[k].h_status&S_HET)) - { - homLen += ovlp; - } - else - { - hetLen += ovlp; - } - } - - if(hetLen <= ((hetLen + homLen) * filter_rate)) - { - all_ovlp->x[uId].a.a[i].status = DELETE; - continue; - } - /*****************tn*****************/ - } - } - - for (v = 0; v < all_ovlp->num; v++) - { - uId = v; - k = 0; - for (i = 0; i < all_ovlp->x[uId].a.n; i++) - { - if(all_ovlp->x[uId].a.a[i].status == DELETE) continue; - all_ovlp->x[uId].a.a[k] = all_ovlp->x[uId].a.a[i]; - k++; - } - all_ovlp->x[uId].a.n = k; - } - - - for (v = 0; v < all_ovlp->num; v++) - { - uId = v; - for (i = 0; i < all_ovlp->x[uId].a.n; i++) - { - qn = all_ovlp->x[uId].a.a[i].xUid; - tn = all_ovlp->x[uId].a.a[i].yUid; - x = &(all_ovlp->x[uId].a.a[i]); - index = get_specific_hap_overlap(&(all_ovlp->x[tn]), tn, qn); - if(index != -1) - { - y = &(all_ovlp->x[tn].a.a[index]); - if(x->rev == y->rev && types[x->type]==y->type) continue; - if(x->score >= y->score) - { - kv_push(hap_overlaps, back_all_ovlp->x[tn].a, (*y)); - set_reverse_hap_overlap(y, x, types); - } - else - { - kv_push(hap_overlaps, back_all_ovlp->x[qn].a, (*x)); - set_reverse_hap_overlap(x, y, types); - } - } - else - { - kv_pushp(hap_overlaps, all_ovlp->x[tn].a, &y); - set_reverse_hap_overlap(y, x, types); - } - } - } -} - -void filter_hap_overlaps_by_length(hap_overlaps_list* all_ovlp, uint32_t minLen) -{ - if(minLen == 0) return; - hap_overlaps *x = NULL; - uint32_t v, i, m, uId; - - for (v = 0; v < all_ovlp->num; v++) - { - uId = v; - m = 0; - for (i = 0; i < all_ovlp->x[uId].a.n; i++) - { - x = &(all_ovlp->x[uId].a.a[i]); - if(x->x_end_id - x->x_beg_id < minLen) continue; - all_ovlp->x[uId].a.a[m] = (*x); - m++; - } - all_ovlp->x[uId].a.n = m; - } -} - -void debug_hap_overlaps(hap_overlaps_list* all_ovlp, hap_overlaps_list* back_all_ovlp) -{ - hap_overlaps *x = NULL, *y = NULL; - uint32_t v, i, uId, qn, tn; - uint32_t types[4]; - types[X2Y] = Y2X; types[Y2X] = X2Y; types[XCY] = YCX; types[YCX] = XCY; - int index; - for (v = 0; v < all_ovlp->num; v++) - { - uId = v; - for (i = 0; i < all_ovlp->x[uId].a.n; i++) - { - qn = all_ovlp->x[uId].a.a[i].xUid; - tn = all_ovlp->x[uId].a.a[i].yUid; - x = &(all_ovlp->x[uId].a.a[i]); - index = get_specific_hap_overlap(&(all_ovlp->x[tn]), tn, qn); - if(index == -1) - { - fprintf(stderr, "ERROR 0\n"); - continue; - } - - y = &(all_ovlp->x[tn].a.a[index]); - if(x->rev != y->rev || types[x->type] != y->type) - { - fprintf(stderr, "ERROR 1\n"); - continue; - } - - if(x->status == REVE_EXIST && y->status != SELF_EXIST) - { - fprintf(stderr, "ERROR 2\n"); - continue; - } - - if(x->status == REVE_EXIST) - { - if(x->weight != y->weight) fprintf(stderr, "ERROR 3\n"); - if(x->xUid != y->yUid) fprintf(stderr, "ERROR 4\n"); - if(x->yUid != y->xUid) fprintf(stderr, "ERROR 5\n"); - if(x->x_beg_pos != y->y_beg_pos) fprintf(stderr, "ERROR 6\n"); - if(x->x_end_pos != y->y_end_pos) fprintf(stderr, "ERROR 7\n"); - if(x->y_beg_pos != y->x_beg_pos) fprintf(stderr, "ERROR 8\n"); - if(x->y_end_pos != y->x_end_pos) fprintf(stderr, "ERROR 9\n"); - if(x->x_beg_id != y->y_beg_id) fprintf(stderr, "ERROR 10\n"); - if(x->x_end_id != y->y_end_id) fprintf(stderr, "ERROR 11\n"); - if(x->y_beg_id != y->x_beg_id) fprintf(stderr, "ERROR 12\n"); - if(x->y_beg_id != y->x_beg_id) fprintf(stderr, "ERROR 13\n"); - if(x->y_end_id != y->x_end_id) fprintf(stderr, "ERROR 14\n"); - - index = get_specific_hap_overlap(&(back_all_ovlp->x[qn]), qn, tn); - if(index != -1) - { - if(back_all_ovlp->x[qn].a.a[index].weight > x->weight) fprintf(stderr, "ERROR 15\n"); - } - } - - } - } -} - -void print_purge_gfa(ma_ug_t *ug, asg_t *purge_g) -{ - uint32_t v, i, n_vtx = purge_g->n_seq * 2; - for (v = 0; v < n_vtx; v++) - { - if(v%2==0) fprintf(stderr, "\n"); - if(purge_g->seq[v>>1].del) - { - fprintf(stderr, "(D) v>>1: %u, v&1: %u, utg%.6d%c\n", v>>1, v&1, (v>>1)+1, - "lc"[ug->u.a[v>>1].circ]); - continue; - } - - fprintf(stderr, "(E) v>>1: %u, v&1: %u, utg%.6dl%c\n", v>>1, v&1, (v>>1)+1, - "lc"[ug->u.a[v>>1].circ]); - - uint32_t nv = asg_arc_n(purge_g, v); - asg_arc_t *av = asg_arc_a(purge_g, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - fprintf(stderr, "av[i].ul: %u (utg%.6d%c, dir: %u, len: %u), av[i].v: %u (utg%.6d%c, dir: %u, len: %u), ol: %u\n", - (uint32_t)(av[i].ul>>33), (uint32_t)(av[i].ul>>33)+1, "lc"[ug->u.a[av[i].ul>>33].circ], (uint32_t)(av[i].ul>>32)&1, ug->u.a[av[i].ul>>33].len, - av[i].v>>1, (av[i].v>>1)+1, "lc"[ug->u.a[av[i].v>>1].circ], av[i].v&1, ug->u.a[av[i].v>>1].len, av[i].ol); - } - - } - -} - -long long decode_score(uint32_t h_bits, uint32_t l_bits) -{ - uint64_t x; - x = h_bits; x <<= 32; x += l_bits; - long long score = ((uint64_t)((uint64_t)x<<1)>>1); - if((x>>63) == 0) score *= -1; - return score; -} - -void encode_score(long long i_s, uint32_t *h_bits, uint32_t *l_bits) -{ - uint64_t score = (i_s >= 0? (i_s) : (i_s*(-1))); - if(i_s >= 0) score += (((uint64_t)1)<<63); - (*l_bits) = (uint32_t)score; (*h_bits)= (score>>32); -} - -uint64_t asg_bub_pop1_purge_graph(asg_t *g, uint32_t v0, int max_dist, buf_t *b) -{ - uint32_t i, n_pending = 0, n_tips, tip_end; - uint64_t n_pop = 0; - ///if this node has been deleted - if (g->seq[v0>>1].del || g->seq[v0>>1].c == ALTER_LABLE) return 0; // already deleted - ///if ((uint32_t)g->idx[v0] < 2) return 0; // no bubbles - if(get_real_length(g, v0, NULL)<2) return 0; - ///S saves nodes with all incoming edges visited - b->S.n = b->T.n = b->b.n = b->e.n = 0; - ///for each node, b->a saves all related information - b->a[v0].c = b->a[v0].d = b->a[v0].m = b->a[v0].nc = b->a[v0].np = 0; - ///b->S is the nodes with all incoming edges visited - kv_push(uint32_t, b->S, v0); - n_tips = 0; - tip_end = (uint32_t)-1; - - do { - ///v is a node that all incoming edges have been visited - ///d is the distance from v0 to v - uint32_t v = kv_pop(b->S), d = b->a[v].d; - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - long long t_s = decode_score(b->a[v].c, b->a[v].m), c_s; - ///why we have this assert? - ///assert(nv > 0); - ///all out-edges of v - for (i = 0; i < nv; ++i) { // loop through v's neighbors - ///if this edge has been deleted - if (av[i].del) continue; - uint32_t w = av[i].v; // v->w with length l - binfo_t *t = &b->a[w]; - ///that means there is a circle, directly terminate the whole bubble poping - ///if (w == v0) goto pop_reset; - if ((w>>1) == (v0>>1)) goto pop_reset; - c_s = decode_score((uint32_t)av[i].ul, av[i].ol); - ///push the edge - ///high 32-bit of g->idx[v] is the start point of v's edges - //so here is the point of this specfic edge - kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); - ///find a too far path? directly terminate the whole bubble poping - if (d + 1 > (uint32_t)max_dist) break; // too far - - ///if this node - if (t->s == 0) { // this vertex has never been visited - kv_push(uint32_t, b->b, w); // save it for revert - ///t->p is the parent node of - ///t->s = 1 means w has been visited - ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) - t->p = v, t->s = 1, t->d = d + 1; - encode_score(t_s + c_s, &(t->c), &(t->m)); - ///incoming edges of w - ///t->r = count_out(g, w^1); - t->r = get_real_length(g, w^1, NULL); - ++n_pending; - } else { // visited before - if((t_s + c_s)> decode_score(t->c, t->m)) - { - t->p = v; - encode_score(t_s + c_s, &(t->c), &(t->m)); - } - ///it is the shortest edge - if (d + 1 < t->d) t->d = d + 1; // update dist - } - ///assert(t->r > 0); - //if all incoming edges of w have visited - //push it to b->S - if (--(t->r) == 0) { - uint32_t x = get_real_length(g, w, NULL); - /****************************may have bugs for bubble********************************/ - if(x > 0) - { - kv_push(uint32_t, b->S, w); - } - else - { - ///at most one tip - if(n_tips != 0) goto pop_reset; - n_tips++; - tip_end = w; - } - /****************************may have bugs for bubble********************************/ - --n_pending; - } - } - //if found a tip - /****************************may have bugs for bubble********************************/ - if(n_tips == 1) - { - if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) - { - kv_push(uint32_t, b->S, tip_end); - break; - } - else - { - goto pop_reset; - } - } - /****************************may have bugs for bubble********************************/ - ///if i < nv, that means (d + l > max_dist) - if (i < nv || b->S.n == 0) goto pop_reset; - } while (b->S.n > 1 || n_pending); - - asg_bub_backtrack_primary(g, v0, b); - - n_pop = 1; -pop_reset: - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - binfo_t *t = &b->a[b->b.a[i]]; - t->s = t->c = t->d = t->m = t->nc = t->np = 0; - } - return n_pop; -} - - - -// pop bubbles -int asg_pop_bubble_purge_graph(asg_t *purge_g) -{ - uint32_t v, n_vtx = purge_g->n_seq * 2; - uint64_t n_pop = 0; - buf_t b; - if (!purge_g->is_symm) asg_symm(purge_g); - memset(&b, 0, sizeof(buf_t)); - ///set information for each node - b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - //traverse all node with two directions - for (v = 0; v < n_vtx; ++v) { - uint32_t i, n_arc = 0, nv = asg_arc_n(purge_g, v); - asg_arc_t *av = asg_arc_a(purge_g, v); - ///some node could be deleted - if (nv < 2 || purge_g->seq[v>>1].del || purge_g->seq[v>>1].c == ALTER_LABLE) continue; - ///some edges could be deleted - for (i = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs - if (!av[i].del) ++n_arc; - if (n_arc > 1) - n_pop += asg_bub_pop1_purge_graph(purge_g, v, purge_g->n_seq, &b); - } - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - if (n_pop) asg_cleanup(purge_g); - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] popped %lu bubbles\n", __func__, (unsigned long)n_pop); - } - return n_pop; -} - -int get_hap_arch(hap_overlaps* hap, uint32_t qLen, uint32_t tLen, int max_hang, float max_hang_rate, -int min_ovlp, asg_arc_t* t) -{ - int r; - ma_hit_t h; - h.qns = hap->xUid; - h.qns = h.qns << 32; - h.qns = h.qns | hap->x_beg_pos; - h.qe = hap->x_end_pos; - h.tn = hap->yUid; - h.ts = hap->y_beg_pos; - h.te = hap->y_end_pos; - h.rev = hap->rev; - h.del = 0; - h.bl = h.el = h.ml = h.no_l_indel = 0; - - r = ma_hit2arc(&h, qLen, tLen, max_hang, max_hang_rate, min_ovlp, t); - if(r < 0) return r; - uint64_t score = (hap->score >= 0? (hap->score) : (hap->score*(-1))); - if(hap->score >= 0) score += (((uint64_t)1)<<63); - t->ol = (uint32_t)score; - t->ul >>= 32; t->ul <<= 32; t->ul |= (score>>32); - return r; -} - -typedef struct { - uint64_t eid; - uint64_t score; -}e_score; - -typedef struct { - size_t n, m; - e_score* a; -}e_score_warp; - -#define e_score_key(a) ((a).score) -KRADIX_SORT_INIT(e_score, e_score, e_score_key, member_size(e_score, score)) - -int purge_g_arc_del_short_diploid_by_score(asg_t *g, float drop_ratio) -{ - e_score_warp b; - kv_init(b); - e_score *p = NULL; - - uint32_t v, n_vtx = g->n_seq * 2; - long long n_cut = 0; - - for (v = 0; v < n_vtx; ++v) - { - if(g->seq[v>>1].c == ALTER_LABLE || g->seq[v>>1].del) continue; - asg_arc_t *av = asg_arc_a(g, v); - uint32_t nv = asg_arc_n(g, v); - if (nv < 2) continue; - uint64_t i; - for (i = 0; i < nv; ++i) - { - kv_pushp(e_score, b, &p); - p->eid = av - g->arc + i; - p->score = (uint32_t)av[i].ul; - p->score <<= 32; - p->score |= av[i].ol; - } - } - - radix_sort_e_score(b.a, b.a + b.n); - - uint64_t k; - for (k = 0; k < b.n; k++) - { - asg_arc_t *a = &g->arc[b.a[k].eid]; - ///v is self id, w is the id of another end - uint32_t i, v = (a->ul)>>32; - uint32_t nv = asg_arc_n(g, v), kv; - long long ovlp_max = 0, ovlp; - asg_arc_t *av = NULL; - ///nv must be >= 2 - if (nv <= 1) continue; - av = asg_arc_a(g, v); - - ///calculate the longest edge for v and w - for (i = 0, kv = 0; i < nv; ++i) { - if (av[i].del) continue; - ovlp = decode_score((uint32_t)av[i].ul, av[i].ol); - if (kv == 0 || ovlp_max < ovlp) ovlp_max = ovlp; - ++kv; - } - - if (kv <= 1) continue; - ovlp = decode_score((uint32_t)a->ul, a->ol); - if (kv >= 2) - { - if(ovlp >= 0 && ovlp_max >= 0 && ovlp > ovlp_max * drop_ratio) continue; - } - - a->del = 1; - asg_arc_del(g, a->v^1, av->ul>>32^1, 1); - ++n_cut; - } - - kv_destroy(b); - if (n_cut) - { - asg_cleanup(g); - asg_symm(g); - } - - - return n_cut; -} - - -void clean_purge_graph(asg_t *purge_g, float drop_ratio, uint32_t is_force_break) -{ - uint64_t operation = 1; - while (operation > 0) - { - operation = 0; - operation += asg_pop_bubble_purge_graph(purge_g); - operation += purge_g_arc_del_short_diploid_by_score(purge_g, drop_ratio); - } - - if(is_force_break) purge_g_arc_del_short_diploid_by_score(purge_g, 1); -} - - -void get_node_boundary_advance(R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, -asg_t *read_g, uint64_t* position_index, int max_hang, int min_ovlp, ma_utg_t *xReads, ma_utg_t *yReads, -uint32_t xUid, uint32_t yUid, long long xBegIndex, long long xEndIndex, long long yBegIndex, -long long yEndIndex, uint32_t dir, uint32_t rev, kvec_asg_arc_t_offset* u_buffer, -kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* prevIndex, asg_arc_t* reture_t_f, asg_arc_t* reture_t_r) -{ - long long k, j, offset, m; - ma_hit_t_alloc *xR = NULL; - ma_hit_t *h = NULL; - ma_sub_t *sq = NULL, *st = NULL; - int r, index; - asg_arc_t t_f, t_r; - uint32_t rId, Hap_uId, is_Unitig, v, w, v_dir, w_dir; - uint64_t tmp; - asg_arc_t_offset t_offset; - reture_t_f->del = reture_t_r->del = 1; - u_buffer->a.n = 0; - - - for (k = xBegIndex; k <= xEndIndex; k++) - { - xR = &(reverse_sources[xReads->a[k]>>33]); - for (j = 0; j < xR->length; j++) - { - h = &(xR->buffer[j]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(st->del || read_g->seq[Get_tn(*h)].del) continue; - - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t_f); - ///if it is a contained overlap, skip - if(r < 0) continue; - - rId = t_f.v>>1; - if(read_g->seq[rId].del == 1) continue; - ///there are two cases: - ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id - ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 - get_R_to_U(ruIndex, rId, &Hap_uId, &is_Unitig); - if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; - if(Hap_uId != yUid) continue; - - v = xReads->a[k]>>32; - get_R_to_U(ruIndex, v>>1, &Hap_uId, &is_Unitig); - if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; - if(Hap_uId != xUid) continue; - if((uint32_t)(position_index[v>>1]) != k) continue; - - w = (yReads->a[(uint32_t)(position_index[rId])])>>32; - - v_dir = ((t_f.ul>>32)==v)?1:0; - w_dir = (t_f.v == w)?1:0; - if(rev == 0 && v_dir != w_dir) continue; - if(rev == 1 && v_dir == w_dir) continue; - if(dir == v_dir) continue; - - /****************************may have bugs********************************/ - offset = (uint32_t)(position_index[rId]); - if(offset < yBegIndex || offset > yEndIndex) continue; - /****************************may have bugs********************************/ - - /************************get reverse edge*************************/ - index = get_specific_overlap(&(reverse_sources[Get_tn(*h)]), Get_tn(*h), Get_qn(*h)); - if(index == -1) continue; - h = &(reverse_sources[Get_tn(*h)].buffer[index]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(st->del || read_g->seq[Get_tn(*h)].del) continue; - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t_r); - if(r < 0) continue; - /************************get reverse edge*************************/ - - tmp = get_xy_pos(read_g, &t_f, v, w, xReads->len, yReads->len, position_index, &(t_f.el)); - if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue; - - t_offset.Off = tmp; - t_offset.x = t_f; - t_offset.weight = 1; - kv_push(asg_arc_t_offset, u_buffer->a, t_offset); - - } - } - - if(u_buffer->a.n == 0) return; - - qsort(u_buffer->a.a, u_buffer->a.n, sizeof(asg_arc_t_offset), cmp_hap_alignment_chaining); - - for (k = 1, m = 1; k < (long long)u_buffer->a.n; k++) - { - if(u_buffer->a.a[m-1].Off == u_buffer->a.a[k].Off) - { - u_buffer->a.a[m-1].weight += u_buffer->a.a[k].weight; - if(u_buffer->a.a[k].x.ol > u_buffer->a.a[m-1].x.ol) - { - u_buffer->a.a[m-1].x = u_buffer->a.a[k].x; - } - continue; - } - u_buffer->a.a[m] = u_buffer->a.a[k]; - m++; - } - u_buffer->a.n = m; - - quick_LIS(u_buffer->a.a, u_buffer->a.n, tailIndex, prevIndex); - - if(tailIndex->a.n == 0) return; - - if(dir == 0) - { - for (k = 0; k < (long long)tailIndex->a.n; k++) - { - v = u_buffer->a.a[tailIndex->a.a[k]].x.v>>1; - w = u_buffer->a.a[tailIndex->a.a[k]].x.ul>>33; - index = get_specific_overlap(&(reverse_sources[v]), v, w); - if(index == -1) continue; - h = &(reverse_sources[v].buffer[index]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(st->del || read_g->seq[Get_tn(*h)].del) continue; - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t_r); - if(r < 0) continue; - - (*reture_t_f) = u_buffer->a.a[tailIndex->a.a[k]].x; - (*reture_t_r) = t_r; - return; - } - } - else - { - for (k = tailIndex->a.n-1; k >= 0; k--) - { - v = u_buffer->a.a[tailIndex->a.a[k]].x.v>>1; - w = u_buffer->a.a[tailIndex->a.a[k]].x.ul>>33; - index = get_specific_overlap(&(reverse_sources[v]), v, w); - if(index == -1) continue; - h = &(reverse_sources[v].buffer[index]); - sq = &(coverage_cut[Get_qn(*h)]); - st = &(coverage_cut[Get_tn(*h)]); - if(st->del || read_g->seq[Get_tn(*h)].del) continue; - r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, - asm_opt.max_hang_rate, min_ovlp, &t_r); - if(r < 0) continue; - - (*reture_t_f) = u_buffer->a.a[tailIndex->a.a[k]].x; - (*reture_t_r) = t_r; - return; - } - } -} - - -void fill_unitig(uint64_t* buffer, uint32_t bufferLen, asg_t* read_g, kvec_asg_arc_t_warp* edge, -uint32_t is_circle, uint64_t* rLen) -{ - uint32_t i, k, totalLen, v, w, nv, l; - asg_arc_t *av = NULL; - (*rLen) = totalLen = 0; - for (i = 0; i < bufferLen - 1; i++) - { - v = (uint64_t)(buffer[i])>>32; - w = (uint64_t)(buffer[i + 1])>>32; - av = asg_arc_a(read_g, v); - nv = asg_arc_n(read_g, v); - l = 0; - - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - l = asg_arc_len(av[k]); - break; - } - } - - if(k == nv) - { - for (k = 0; k < edge->a.n; k++) - { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) - { - l = asg_arc_len(edge->a.a[k]); - break; - } - } - - if(k == edge->a.n) - { - fprintf(stderr, "####ERROR1-fill: i: %u, v>>1: %u, v&1: %u, w>>1: %u, w&1: %u\n", - i, v>>1, v&1, w>>1, w&1); - } - } - - - - buffer[i] = v; buffer[i] = buffer[i]<<32; buffer[i] = buffer[i] | (uint64_t)(l); - totalLen += l; - } - - if(i < bufferLen) - { - if(is_circle) - { - v = (uint64_t)(buffer[i])>>32; - w = (uint64_t)(buffer[0])>>32; - av = asg_arc_a(read_g, v); - nv = asg_arc_n(read_g, v); - l = 0; - - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - l = asg_arc_len(av[k]); - break; - } - } - - if(k == nv) - { - for (k = 0; k < edge->a.n; k++) - { - if(edge->a.a[k].del) continue; - if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) - { - l = asg_arc_len(edge->a.a[k]); - break; - } - } - - if(k == edge->a.n) - { - fprintf(stderr, "####ERROR2-fill: i: %u, v>>1: %u, v&1: %u, w>>1: %u, w&1: %u\n", - i, v>>1, v&1, w>>1, w&1); - } - } - - buffer[i] = v; buffer[i] = buffer[i]<<32; buffer[i] = buffer[i] | (uint64_t)(l); - totalLen += l; - } - else - { - v = (uint64_t)(buffer[i])>>32; - l = read_g->seq[v>>1].len; - buffer[i] = v; - buffer[i] = buffer[i]<<32; - buffer[i] = buffer[i] | (uint64_t)(l); - totalLen += l; - } - } - - (*rLen) = totalLen; - -} - -void collect_trans_purge_cov(hap_cov_t *cov, ma_ug_t *ug, hap_overlaps* x, uint32_t is_keep_X) -{ - if(ug->u.a[x->xUid].n == 0 || ug->u.a[x->yUid].n == 0) return; - uint64_t *pri = NULL, pri_n, *aux = NULL, aux_n, i, rId, uCov = 0, uLen = 0; - - if(is_keep_X) - { - pri = ug->u.a[x->xUid].a + x->x_beg_id; - pri_n = x->x_end_id - x->x_beg_id; - - aux = ug->u.a[x->yUid].a + x->y_beg_id; - aux_n = x->y_end_id - x->y_beg_id; - } - else - { - pri = ug->u.a[x->yUid].a + x->y_beg_id; - pri_n = x->y_end_id - x->y_beg_id; - - aux = ug->u.a[x->xUid].a + x->x_beg_id; - aux_n = x->x_end_id - x->x_beg_id; - } - - - uCov = uLen = 0; - for (i = 0; i < aux_n; i++) - { - rId = aux[i]>>33; - uCov += cov->cov[rId]; - } - - for (i = 0; i < pri_n; i++) - { - rId = pri[i]>>33; - uLen += cov->read_g->seq[rId].len; - } - - uCov = (uLen == 0? 0 : uCov / uLen); - - - for (i = 0; i < pri_n; i++) - { - rId = pri[i]>>33; - cov->cov[rId] += (uCov * cov->read_g->seq[rId].len); - } -} - - -void collect_trans_purge_joint_cov(hap_cov_t *cov, ma_ug_t *ug, hap_overlaps* x) -{ - if(ug->u.a[x->xUid].n == 0 || ug->u.a[x->yUid].n == 0) return; - uint64_t *a[2], a_n[2], uCov[2], uLen[2], uDepth[2], i, rId; - - a[0] = ug->u.a[x->xUid].a + x->x_beg_id; - a_n[0] = x->x_end_id - x->x_beg_id; - uCov[0] = uLen[0] = 0; - for (i = 0; i < a_n[0]; i++) - { - rId = a[0][i]>>33; - uCov[0] += cov->cov[rId]; - uLen[0] += cov->read_g->seq[rId].len; - } - - a[1] = ug->u.a[x->yUid].a + x->y_beg_id; - a_n[1] = x->y_end_id - x->y_beg_id; - uCov[1] = uLen[1] = 0; - for (i = 0; i < a_n[1]; i++) - { - rId = a[1][i]>>33; - uCov[1] += cov->cov[rId]; - uLen[1] += cov->read_g->seq[rId].len; - } - - uDepth[0] = (uLen[0] == 0? 0 : uCov[1] / uLen[0]); - uDepth[1] = (uLen[1] == 0? 0 : uCov[0] / uLen[1]); - - for (i = 0; i < a_n[0]; i++) - { - rId = a[0][i]>>33; - cov->cov[rId] += (uDepth[0] * cov->read_g->seq[rId].len); - } - - for (i = 0; i < a_n[1]; i++) - { - rId = a[1][i]>>33; - cov->cov[rId] += (uDepth[1] * cov->read_g->seq[rId].len); - } -} - - - -void purge_merge(asg_t *purge_g, ma_ug_t *ug, hap_overlaps_list* all_ovlp, buf_t* b_0, -R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, asg_t *read_g, -uint64_t* position_index, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, -kvec_t_i32_warp* prevIndex, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* edge, uint8_t* visit, -hap_cov_t *cov) -{ - uint32_t i, nv, k, v, w, x_beg_index, x_end_index, y_beg_index, y_end_index, cut_beg, cut_end, begIndex, endIndex, keepUid; - hap_overlaps *x = NULL/**, *y = NULL**/; - ma_utg_t *xReads = NULL, *yReads = NULL; - asg_arc_t t_forward, t_backward; - asg_arc_t *av = NULL; - kvec_t(uint64_t) buffer; - uint64_t totalLen; - int index = 0; - i = 0; - while (i < b_0->b.n) - { - cut_beg = 0; cut_end = (uint32_t)-1; - kv_init(buffer); - /********************for the first node********************/ - v = b_0->b.a[i]; - keepUid = v>>1; - xReads = &(ug->u.a[v>>1]); - if(v&1) - { - for (k = 0; k < xReads->n; k++) - { - kv_push(uint64_t, buffer, (xReads->a[xReads->n - k - 1])^(uint64_t)(0x100000000)); - } - } - else - { - for (k = 0; k < xReads->n; k++) - { - kv_push(uint64_t, buffer, xReads->a[k]); - } - } - cut_beg = 0; cut_end = xReads->n - 1; - i++; - /********************for the first node********************/ - - - for (; i < b_0->b.n; i++) - { - ///x = y = NULL; - x = NULL; - - v = b_0->b.a[i-1]; - w = b_0->b.a[i]; - - - index = get_specific_hap_overlap(&(all_ovlp->x[v>>1]), v>>1, w>>1); - x = &(all_ovlp->x[v>>1].a.a[index]); - - - - xReads = &(ug->u.a[v>>1]); - yReads = &(ug->u.a[w>>1]); - - begIndex = x->x_beg_id; - if(cut_beg > begIndex) begIndex = cut_beg; - - endIndex = x->x_end_id-1; - if(cut_end < endIndex) endIndex = cut_end; - - get_node_boundary_advance(ruIndex, reverse_sources, coverage_cut, read_g, position_index, max_hang, - min_ovlp, xReads, yReads, v>>1, w>>1, begIndex, endIndex, x->y_beg_id, x->y_end_id-1, v&1, - x->rev, u_buffer, tailIndex, prevIndex, &t_forward, &t_backward); - - if(t_forward.del || t_backward.del) break; - - kv_push(asg_arc_t, edge->a, t_forward); - kv_push(asg_arc_t, edge->a, t_backward); - - x_beg_index = 0; x_end_index = xReads->n - 1; - y_beg_index = 0; y_end_index = yReads->n - 1; - - if((v&1) == 0) - { - x_end_index = (uint32_t)position_index[t_forward.ul>>33]; - buffer.n = buffer.n - (cut_end - x_end_index); - } - else - { - x_beg_index = (uint32_t)position_index[t_forward.ul>>33]; - buffer.n = buffer.n - (x_beg_index - cut_beg); - } - - if((w&1) == 1) - { - y_end_index = (uint32_t)position_index[t_forward.v>>1]; - } - else - { - y_beg_index = (uint32_t)position_index[t_forward.v>>1]; - } - - cut_beg = y_beg_index; - cut_end = y_end_index; - - if((w&1) == 1) - { - for (k = y_end_index; k >= y_beg_index; k--) - { - kv_push(uint64_t, buffer, (yReads->a[k])^(uint64_t)(0x100000000)); - if(k==0) break; - } - } - else - { - for (k = y_beg_index; k <= y_end_index; k++) - { - kv_push(uint64_t, buffer, yReads->a[k]); - } - } - - purge_g->seq[w>>1].c = ALTER_LABLE; - if(cov) collect_trans_purge_joint_cov(cov, ug, x); - - // if(buffer.n > 1) - // { - // for (k = 0; k < buffer.n - 1; k++) - // { - // if((buffer.a[k]>>32) == 854769 && (buffer.a[k+1]>>32) == 64486) - // { - // fprintf(stderr, "+++++++v: %u, w: %u, xReads->n: %u, yReads->n: %u\n", - // v, w, xReads->n, yReads->n); - // fprintf(stderr, "x->rev: %u, x->x_beg_id: %u, x->x_end_id: %u, x->y_beg_id: %u, x->y_end_id: %u\n", - // x->rev, x->x_beg_id, x->x_end_id, x->y_beg_id, x->y_end_id); - // fprintf(stderr, "t_forward.ul>>32: %u, t_forward.v: %u, y_beg_index: %u, y_end_index: %u\n", - // t_forward.ul>>32, t_forward.v, y_beg_index, y_end_index); - // fprintf(stderr, "type: %u, x->x_beg_pos: %u, x->x_end_pos: %u, xReads->len: %u\n", - // x->type, x->x_beg_pos, x->x_end_pos, xReads->len); - // fprintf(stderr, "x->y_beg_pos: %u, x->y_end_pos: %u, yReads->len: %u\n", - // x->y_beg_pos, x->y_end_pos, yReads->len); - // } - // } - // } - } - - // fprintf(stderr, "+keepUid: %u, i: %u, b_0->b.n: %u, buffer.n: %u\n", - // keepUid, i, (uint32_t)b_0->b.n, (uint32_t)buffer.n); - fill_unitig(buffer.a, buffer.n, read_g, edge, 0, &totalLen); - ///fprintf(stderr, "-keepUid: %u\n", keepUid); - - xReads = &(ug->u.a[keepUid]); - free(xReads->a); - xReads->a = buffer.a; - xReads->n = buffer.n; - xReads->m = buffer.m; - xReads->len = totalLen; - xReads->circ = 0; - if(xReads->start != (xReads->a[0]>>32)) - { - xReads->start = xReads->a[0]>>32; - v = (keepUid<<1)+1; - av = asg_arc_a(ug->g, v); - nv = asg_arc_n(ug->g, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - asg_arc_del(ug->g, av[k].ul>>32, av[k].v, 1); - asg_arc_del(ug->g, av[k].v^1, av[k].ul>>32^1, 1); - } - } - - if(xReads->end != ((xReads->a[xReads->n-1]>>32)^1)) - { - xReads->end = ((xReads->a[xReads->n-1]>>32)^1); - v = (keepUid<<1); - av = asg_arc_a(ug->g, v); - nv = asg_arc_n(ug->g, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - asg_arc_del(ug->g, av[k].ul>>32, av[k].v, 1); - asg_arc_del(ug->g, av[k].v^1, av[k].ul>>32^1, 1); - } - } - } - - for (i = 0; i < b_0->b.n; i++) - { - v = b_0->b.a[i]; - visit[v>>1] = 1; - if(purge_g->seq[v>1].c != ALTER_LABLE) continue; - asg_seq_drop(purge_g, v>1); - } -} - -void print_het_ovlp(p_g_t *pg, ma_ug_t *ug, hap_overlaps_list* ha, double filter_rate) -{ - uint32_t v, i, k, n_vtx = pg->pg_h_lev->n_seq * 2, nv, qn, qs, qe, tn, ts, te, as, ae, occ, ovlp, hetLen, homLen; - asg_arc_t *av = NULL; - hap_overlaps *x = NULL; - p_node_t *a = NULL; - int index; - for (v = 0; v < n_vtx; v++) - { - av = asg_arc_a(pg->pg_h_lev, v); - nv = asg_arc_n(pg->pg_h_lev, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - index = get_specific_hap_overlap(&(ha->x[av[i].ul>>33]), av[i].ul>>33, av[i].v>>1); - if(index == -1) fprintf(stderr, "ERROR\n"); - x = &(ha->x[av[i].ul>>33].a.a[index]); - - qn = x->xUid; - qs = x->x_beg_pos; - qe = x->x_end_pos - 1; - get_p_nodes(pg, &a, &occ, qn); - for (k = 0, hetLen = 0, homLen = 0; k < occ; k++) - { - as = a[k].baseBeg; - ae = a[k].baseEnd; - ovlp = ((MIN(qe, ae) >= MAX(qs, as))? MIN(qe, ae) - MAX(qs, as) + 1 : 0); - if(homLen + hetLen > 0 && ovlp == 0) break; - if(ovlp == 0) continue; - if(a[k].h_status == N_HET) - { - homLen += ovlp; - } - else if(asm_opt.polyploidy <= 2 && (a[k].h_status&P_HET)) - { - homLen += ovlp; - } - else - { - hetLen += ovlp; - } - } - - if(hetLen <= ((hetLen + homLen) * filter_rate)) - { - ///all_ovlp->x[uId].a.a[i].status = DELETE; - fprintf(stderr, "********XY********\n"); - print_hap_paf(ug, x); - } - - - tn = x->yUid; - ts = x->y_beg_pos; - te = x->y_end_pos - 1; - get_p_nodes(pg, &a, &occ, tn); - for (k = 0, hetLen = 0, homLen = 0; k < occ; k++) - { - as = a[k].baseBeg; - ae = a[k].baseEnd; - ovlp = ((MIN(te, ae) >= MAX(ts, as))? MIN(te, ae) - MAX(ts, as) + 1 : 0); - if(homLen + hetLen > 0 && ovlp == 0) break; - if(ovlp == 0) continue; - if(a[k].h_status == N_HET) - { - homLen += ovlp; - } - else if(asm_opt.polyploidy <= 2 && (a[k].h_status&P_HET)) - { - homLen += ovlp; - } - else - { - hetLen += ovlp; - } - } - - if(hetLen <= ((hetLen + homLen) * filter_rate)) - { - ///all_ovlp->x[uId].a.a[i].status = DELETE; - fprintf(stderr, "********YX********\n"); - print_hap_paf(ug, x); - } - } - } - - for (v = 0; v < ha->num; v++) - { - for (i = 0; i < ha->x[v].a.n; i++) - { - if(ha->x[v].a.a[i].status == DELETE) - { - x = &(ha->x[v].a.a[i]); - - qn = x->xUid; - qs = x->x_beg_pos; - qe = x->x_end_pos - 1; - get_p_nodes(pg, &a, &occ, qn); - for (k = 0, hetLen = 0, homLen = 0; k < occ; k++) - { - as = a[k].baseBeg; - ae = a[k].baseEnd; - ovlp = ((MIN(qe, ae) >= MAX(qs, as))? MIN(qe, ae) - MAX(qs, as) + 1 : 0); - if(homLen + hetLen > 0 && ovlp == 0) break; - if(ovlp == 0) continue; - if(a[k].h_status == N_HET) - { - homLen += ovlp; - } - else if(asm_opt.polyploidy <= 2 && (a[k].h_status&P_HET)) - { - homLen += ovlp; - } - else - { - hetLen += ovlp; - } - } - - if(hetLen <= ((hetLen + homLen) * filter_rate)) - { - fprintf(stderr, "********C(X)********hetLen-%u, homLen-%u\n", hetLen, homLen); - print_hap_paf(ug, x); - } - - - tn = x->yUid; - ts = x->y_beg_pos; - te = x->y_end_pos - 1; - get_p_nodes(pg, &a, &occ, tn); - for (k = 0, hetLen = 0, homLen = 0; k < occ; k++) - { - as = a[k].baseBeg; - ae = a[k].baseEnd; - ovlp = ((MIN(te, ae) >= MAX(ts, as))? MIN(te, ae) - MAX(ts, as) + 1 : 0); - if(homLen + hetLen > 0 && ovlp == 0) break; - if(ovlp == 0) continue; - if(a[k].h_status == N_HET) - { - homLen += ovlp; - } - else if(asm_opt.polyploidy <= 2 && (a[k].h_status&P_HET)) - { - homLen += ovlp; - } - else - { - hetLen += ovlp; - } - } - - if(hetLen <= ((hetLen + homLen) * filter_rate)) - { - fprintf(stderr, "********C(Y)********hetLen-%u, homLen-%u\n", hetLen, homLen); - print_hap_paf(ug, x); - } - } - } - } -} - -void link_unitigs(asg_t *purge_g, ma_ug_t *ug, hap_overlaps_list* all_ovlp, -R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, asg_t *read_g, -uint64_t* position_index, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, -kvec_t_i32_warp* prevIndex, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* edge, uint8_t* visit, -hap_cov_t *cov) -{ - uint32_t v, n_vtx = purge_g->n_seq * 2, beg, end; - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - buf_t b_0; - memset(&b_0, 0, sizeof(buf_t)); - memset(visit, 0, purge_g->n_seq); - for (v = 0; v < n_vtx; ++v) - { - if(purge_g->seq[v>>1].c == ALTER_LABLE || purge_g->seq[v>>1].del || visit[v>>1]) continue; - if(get_real_length(purge_g, v, NULL) != 1) continue; - if(get_real_length(purge_g, v^1, NULL) != 0) continue; - - beg = v; - b_0.b.n = 0; - if(get_unitig(purge_g, NULL, beg, &end, &nodeLen, &baseLen, &max_stop_nodeLen, - &max_stop_baseLen, 1, &b_0) == LOOP) - { - continue; - } - - ///if(cov->link) collect_reverse_unitigs_purge(&b_0, cov->link, ug, all_ovlp); - purge_merge(purge_g, ug, all_ovlp, &b_0, ruIndex, reverse_sources, coverage_cut, - read_g, position_index, u_buffer, tailIndex, prevIndex,max_hang, min_ovlp, edge, visit, cov); - } - free(b_0.b.a); -} - -void print_all_purge_ovlp(ma_ug_t *ug, hap_overlaps_list* all_ovlp, const char* cmd) -{ - fprintf(stderr, "\n%s--->ug->u.n: %u\n", cmd, (uint32_t)ug->u.n); - uint32_t v, uId, i; - for (v = 0; v < all_ovlp->num; v++) - { - uId = v; - for (i = 0; i < all_ovlp->x[uId].a.n; i++) - { - print_hap_paf(ug, &(all_ovlp->x[uId].a.a[i])); - } - } - -} - -inline int get_available_cnt(asg_t *g, uint32_t v, uint8_t* del, asg_arc_t* v_s) -{ - //v has direction - if(del && del[v>>1]) return 0; - uint32_t i, kv = 0; - asg_arc_t *av = asg_arc_a(g, v); - uint32_t nv = asg_arc_n(g, v); - - for (i = 0, kv = 0; i < nv; i++) - { - if(!av[i].del) - { - if(del && del[av[i].v>>1]) continue; - if(v_s) v_s[kv] = av[i]; - kv++; - } - } - - return kv; -} - -long long get_specific_contig_length(asg_t *g, uint8_t *del) -{ - asg_cleanup(g); - uint32_t v, n_vtx = g->n_seq * 2, q_occ; - uint8_t *mark = NULL; - ///is a queue - //kdq_t(uint64_t) *q; - ///each node has two directions - //q = kdq_init(uint64_t); - - - mark = (uint8_t*)calloc(n_vtx, 1); - - long long totalLen = 0; - for (v = 0; v < n_vtx; ++v) - { - uint32_t w, x, l, start, end, len; - asg_arc_t arc; - if (g->seq[v>>1].del || mark[v]) continue; - if (get_available_cnt(g, v, del, NULL) == 0 && get_available_cnt(g, (v^1), del, NULL) != 0) continue; - if (del[v>>1]) continue; - - mark[v] = 1; - //q->count = 0, start = v, end = v^1, len = 0; - q_occ =0, start = v, end = v^1, len = 0; - // forward - w = v; - - - while (1) - { - /** - * w----->x - * w<-----x - * that means the only suffix of w is x, and the only prefix of x is w - **/ - if (get_available_cnt(g, w, del, NULL) != 1) break; - get_available_cnt(g, w, del, &arc); - x = arc.v; // w->x - if (get_available_cnt(g, x^1, del, NULL) != 1) break; - - /** - * another direction of w would be marked as used (since w has been used) - **/ - mark[x] = mark[w^1] = 1; - ///l is the edge length, instead of overlap length - ///note: edge length is different with overlap length - ///l = asg_arc_len(arc_first(g, w)); - get_available_cnt(g, w, del, &arc); - l = ((uint32_t)((arc).ul)); - //kdq_push(uint64_t, q, (uint64_t)w<<32 | l); - q_occ++; - end = x^1, len += l; - w = x; - if (x == v) break; - } - - - //if (start != (end^1) || kdq_size(q) == 0) { // linear unitig - if (start != (end^1) || q_occ == 0) { // linear unitig - ///length of seq, instead of edge - l = g->seq[end>>1].len; - //kdq_push(uint64_t, q, (uint64_t)(end^1)<<32 | l); - q_occ++; - len += l; - } else { // circular unitig - start = end = UINT32_MAX; - goto add_unitig; // then it is not necessary to do the backward - } - - // backward - x = v; - while (1) { // similar to forward but not the same - if (get_available_cnt(g, x^1, del, NULL) != 1) break; - get_available_cnt(g, x^1, del, &arc); - w = arc.v ^ 1; - if (get_available_cnt(g, w, del, NULL) != 1) break; - mark[x] = mark[w^1] = 1; - ///l = asg_arc_len(arc_first(g, w)); - get_available_cnt(g, w, del, &arc); - l = ((uint32_t)((arc).ul)); - ///w is the seq id + direction, l is the length of edge - ///push element to the front of a queue - //kdq_unshift(uint64_t, q, (uint64_t)w<<32 | l); - q_occ++; - - start = w, len += l; - x = w; - } - - - add_unitig: - if (start != UINT32_MAX) mark[start] = mark[end] = 1; - totalLen += len; - } - //kdq_destroy(uint64_t, q); - free(mark); - return totalLen; -} - - -void get_contig_length(ma_ug_t *ug, asg_t *g, uint64_t* primaryLen, uint64_t* alterLen) -{ - uint8_t *del = (uint8_t *)malloc(sizeof(uint8_t)*g->n_seq); - uint32_t v, k; - ma_utg_t* u = NULL; - memset(del, 1, g->n_seq); - (*primaryLen) = (*alterLen) = 0; - - for (v = 0; v < ug->g->n_seq; ++v) - { - if(ug->g->seq[v].del) continue; - if(ug->g->seq[v].c == ALTER_LABLE) continue; - u = &(ug->u.a[v]); - if(u->m == 0) continue; - for (k = 0; k < u->n; k++) - { - del[u->a[k]>>33] = 0; - } - } - (*primaryLen) = get_specific_contig_length(g, del); - - - for (v = 0; v < g->n_seq; ++v) - { - del[v] = 1 - del[v]; - } - - (*alterLen) = get_specific_contig_length(g, del); - - free(del); -} - - -int if_ploid_sample(ma_ug_t *ug, asg_t *read_g, R_to_U* ruIndex, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, -hap_alignment_struct_pip* hap_buf, hap_overlaps_list* all_ovlp, hap_overlaps_list* back_all_ovlp, -uint32_t minLen, double purge_threshold) -{ - asg_t* nsg = ug->g; - uint64_t v, k, total_bases = 0, alter_bases = 0, primary_bases = 0, purge_bases = 0; - kt_for(asm_opt.thread_num, hap_alignment_advance_worker, hap_buf, nsg->n_seq); - - filter_hap_overlaps_by_length(all_ovlp, minLen); - normalize_hap_overlaps_advance(all_ovlp, back_all_ovlp, ug, read_g, reverse_sources, ruIndex); - - get_contig_length(ug, read_g, &primary_bases, &alter_bases); - total_bases = primary_bases + alter_bases; - // fprintf(stderr, "primary_bases: %lu\n", primary_bases); - // fprintf(stderr, "alter_bases: %lu\n", alter_bases); - // fprintf(stderr, "total_bases: %lu\n", total_bases); - - - for (v = 0; v < all_ovlp->num; v++) - { - for (k = 0; k < all_ovlp->x[v].a.n; k++) - { - purge_bases += all_ovlp->x[v].a.a[k].x_end_pos - all_ovlp->x[v].a.a[k].x_beg_pos; - } - } - purge_bases = purge_bases/2; - ///fprintf(stderr, "purge_bases: %lu\n", purge_bases); - alter_bases = alter_bases + purge_bases; - ///fprintf(stderr, "new alter_bases: %lu\n", alter_bases); - - - for (v = 0; v < all_ovlp->num; v++) - { - all_ovlp->x[v].a.n = 0; - } - - for (v = 0; v < back_all_ovlp->num; v++) - { - back_all_ovlp->x[v].a.n = 0; - } - - if(alter_bases > total_bases * purge_threshold) return 1; - return 0; -} - -int cmp_chain_score(const void * a, const void * b) -{ - if((*(hap_overlaps*)a).score < (*(hap_overlaps*)b).score) return 1; - if((*(hap_overlaps*)a).score > (*(hap_overlaps*)b).score) return -1; - - return 0; -} -long long get_ovlp_len(long long a_beg, long long a_end, long long b_beg, long long b_end) -{ - long long ovlp = (long long)(MIN(a_end, b_end)) - (long long)(MAX(a_beg, b_beg)) + 1; - return ovlp <= 0? 0 : ovlp; -} -void sort_hap_chain(hap_overlaps_list* all_ovlp) -{ - hap_overlaps *x = NULL, *p = NULL; - uint32_t v, i, k, uId; - long long ovlp, xLen, pLen; - kvec_t(hap_overlaps) pri; kv_init(pri); - kvec_t(hap_overlaps) alt; kv_init(alt); - - for (v = 0; v < all_ovlp->num; v++) - { - uId = v; - qsort(all_ovlp->x[uId].a.a, all_ovlp->x[uId].a.n, sizeof(hap_overlaps), cmp_chain_score); - pri.n = alt.n = 0; - for (i = 0; i < all_ovlp->x[uId].a.n; i++) - { - x = &(all_ovlp->x[uId].a.a[i]); - xLen = x->x_end_pos - x->x_beg_pos; - for (k = 0; k < pri.n; k++) - { - p = &(pri.a[k]); - pLen = p->x_end_pos - p->x_beg_pos; - ovlp = get_ovlp_len(x->x_beg_pos, x->x_end_pos-1, p->x_beg_pos, p->x_end_pos-1); - if(ovlp == 0) continue; - if(ovlp >= (MIN(xLen, pLen))*0.5) break; - } - - if(k < pri.n) - { - x->xUid = k; - kv_push(hap_overlaps, alt, *x); - } - else - { - kv_push(hap_overlaps, pri, *x); - } - } - - } - - kv_destroy(pri); kv_destroy(alt); -} - -void remove_contained_haplotig(hap_overlaps_list* all_ovlp, ma_ug_t *ug, asg_t* nsg, asg_t *purge_g, hap_cov_t *cov) -{ - uint32_t v, i, uId, xUid; - hap_overlaps *p = NULL; - for (v = 0; v < all_ovlp->num; v++) - { - uId = v; p = NULL; - for (i = 0; i < all_ovlp->x[uId].a.n; i++) - { - if(p == NULL || p->score < all_ovlp->x[uId].a.a[i].score) - { - p = &(all_ovlp->x[uId].a.a[i]); - } - } - - for (i = 0; i < all_ovlp->x[uId].a.n; i++) - { - if(all_ovlp->x[uId].a.a[i].type == YCX) - { - if(!filter_secondary_chain(p->score, all_ovlp->x[uId].a.a[i].score, 0.95)) - { - continue; - } - - xUid = all_ovlp->x[uId].a.a[i].xUid; - - nsg->seq[xUid].c = ALTER_LABLE; - purge_g->seq[xUid].c = ALTER_LABLE; - purge_g->seq[xUid].del = 1; - - all_ovlp->x[uId].a.a[i].status = DELETE; - ///if(cov->link) collect_reverse_unitig_pair(cov->link, ug, &(all_ovlp->x[uId].a.a[i])); - collect_trans_purge_cov(cov, ug, &(all_ovlp->x[uId].a.a[i]), 0); - } - - ///print_hap_paf(ug, &(all_ovlp.x[uId].a.a[i])); - } - } - - // for (v = 0; v < all_ovlp.num; v++) - // { - // uId = v; - // for (i = 0; i < all_ovlp.x[uId].a.n; i++) - // { - // if(all_ovlp.x[uId].a.a[i].type == YCX) - // { - // nsg->seq[all_ovlp.x[uId].a.a[i].xUid].c = ALTER_LABLE; - // purge_g->seq[all_ovlp.x[uId].a.a[i].xUid].c = ALTER_LABLE; - // purge_g->seq[all_ovlp.x[uId].a.a[i].xUid].del = 1; - // all_ovlp.x[uId].a.a[i].status = DELETE; - // if(link) collect_reverse_unitig_pair(link, ug, &(all_ovlp.x[uId].a.a[i])); - // collect_trans_purge_cov(cov, ug, &(all_ovlp.x[uId].a.a[i]), 0); - // } - - // if(all_ovlp.x[uId].a.a[i].type == XCY) - // { - // nsg->seq[all_ovlp.x[uId].a.a[i].yUid].c = ALTER_LABLE; - // purge_g->seq[all_ovlp.x[uId].a.a[i].yUid].c = ALTER_LABLE; - // purge_g->seq[all_ovlp.x[uId].a.a[i].yUid].del = 1; - // all_ovlp.x[uId].a.a[i].status = DELETE; - // if(link) collect_reverse_unitig_pair(link, ug, &(all_ovlp.x[uId].a.a[i])); - // collect_trans_purge_cov(cov, ug, &(all_ovlp.x[uId].a.a[i]), 1); - // } - // ///print_hap_paf(ug, &(all_ovlp.x[uId].a.a[i])); - // } - // } -} - -void debug_p_g_t(p_g_t* pg, hap_cov_t *cov, asg_t *read_g) -{ - fprintf(stderr, "----------[M::%s]----------\n", __func__); - uint32_t i, offset, v, sid, eid, spos, epos, p_status, p_uid, occ; - p_node_t *t = NULL; - ma_utg_t *u = NULL; - p_node_t *a = NULL; - - for (v = 0; v < pg->ug->u.n; v++) - { - ///fprintf(stderr, "\nu->n: %u, uid: %u\n", (uint32_t)(pg->ug->u.a[v].n), v); - get_p_nodes(pg, &a, &occ, v); - for (i = 0; i < occ; i++) - { - if(a[i].c_ug_id != v) fprintf(stderr, "sbsbsbsbsb\n"); - ///fprintf(stderr, "sid: %u, eid: %u\n", a[i].nodeBeg, a[i].nodeEnd); - } - } - - - for (v = 0, p_status = (uint32_t)-1, p_uid = (uint32_t)-1; v < pg->pg_het_node.n; v++) - { - t = &(pg->pg_het_node.a[v]); - sid = t->nodeBeg; - eid = t->nodeEnd; - spos = t->baseBeg; - epos = t->baseEnd; - // fprintf(stderr, "sid: %u, eid: %u, spos: %u, epos: %u, t->b_ug_id: %u\n", - // sid, eid, spos, epos, (uint32_t)t->b_ug_id); - // fprintf(stderr, "pg->pg_het_node.n: %u\n", (uint32_t)pg->pg_het_node.n); - if(p_uid == t->c_ug_id && p_status == t->h_status) - { - fprintf(stderr, "ERROR-(-1)\n"); - } - p_status = t->h_status; - p_uid = t->c_ug_id; - - u = &(pg->ug->u.a[t->c_ug_id]); - ///fprintf(stderr, "u->n: %u, sid: %u, eid: %u\n", (uint32_t)u->n, sid, eid); - for (i = offset = 0; i < u->n; i++) - { - if(i == sid) - { - if(spos != offset) - { - fprintf(stderr, "ERROR-1\n"); - } - } - - if(i == eid) - { - if(epos != (offset+read_g->seq[u->a[i]>>33].len - 1)) - { - fprintf(stderr, "ERROR-2, real end: %u\n", - (uint32_t)(offset+read_g->seq[u->a[i]>>33].len - 1)); - } - } - offset += (uint32_t)u->a[i]; - if(i >= sid && i <= eid) - { - if(cov->t_ch->ir_het[u->a[i]>>33] != t->h_status) - { - fprintf(stderr, "ERROR-(-3): is_r_het: %u, h_status: %u\n", cov->t_ch->ir_het[u->a[i]>>33], t->h_status); - } - } - } - } -} - - -void print_p_g_t_interval(p_g_t* pg, hap_cov_t *cov) -{ - fprintf(stderr, "----------[M::%s]----------\n", __func__); - uint32_t i, v, sid, eid; - p_node_t *t = NULL; - ma_utg_t *u = NULL; - - for (v = 0; v < pg->pg_het_node.n; v++) - { - t = &(pg->pg_het_node.a[v]); - sid = t->nodeBeg; - eid = t->nodeEnd; - - u = &(pg->ug->u.a[t->c_ug_id]); - fprintf(stderr, "\nu->n=%u, sid=%u, eid=%u, h_status=%u\n", - (uint32_t)u->n, sid, eid, t->h_status); - for (i = sid; i <= eid; i++) - { - fprintf(stderr, "id:i:%u------>utg%.6ul\n", - (uint32_t)(u->a[i]>>33), (get_origin_uid(u->a[i]>>32, cov->t_ch, NULL, NULL)>>1)+1); - } - } - fprintf(stderr, "----------[M::%s]----------\n", __func__); -} - - -p_g_t *init_p_g_t(ma_ug_t *ug, hap_cov_t *cov, asg_t *read_g) -{ - uint32_t v, uId, k, l, offset, l_pos, g_beg_idx, occ/**, ovlp, tLen, zLen**/; - p_g_t *pg = NULL; CALLOC(pg, 1); - pg->ug = ug; - asg_t* nsg = pg->ug->g; - ma_utg_t *u = NULL; - p_node_t *t = NULL/**, *z = NULL**/; - ///asg_arc_t *e = NULL; - p_g_in_t *x = NULL; - ///pg->pg_het = asg_init(); - pg->pg_h_lev = asg_init(); - kv_init(pg->pg_het_node); - kv_init(pg->pg_h_lev_idx); - - for (v = 0; v < nsg->n_seq; v++) - { - uId = v; - if(nsg->seq[uId].del || nsg->seq[uId].c == ALTER_LABLE) - { - asg_seq_set(pg->pg_h_lev, uId, 0, 1); - pg->pg_h_lev->seq[uId].c = ALTER_LABLE; - continue; - } - - asg_seq_set(pg->pg_h_lev, uId, ug->u.a[uId].len, 0); - pg->pg_h_lev->seq[uId].c = PRIMARY_LABLE; - } - - // if(asm_opt.polyploidy <= 2) - // { - // for (v = 0; v < cov->t_ch->r_num; v++) - // { - // if(cov->t_ch->is_r_het[v]&P_HET) cov->t_ch->is_r_het[v] |= S_HET; - // } - // } - - for (v = 0; v < nsg->n_seq; v++) - { - uId = v; - if(nsg->seq[uId].del || nsg->seq[uId].c == ALTER_LABLE) continue; - - u = &(ug->u.a[uId]); - g_beg_idx = pg->pg_het_node.n; - ///fprintf(stderr, "\n+v: %u, pg->pg_het_node.n: %u\n", v, (uint32_t)pg->pg_het_node.n); - for (k = 1, l = 0, offset = 0, l_pos = 0; k <= u->n; ++k) - { - ///if (k == u->n || (!!cov->t_ch->is_r_het[u->a[k]>>33]) != (!!cov->t_ch->is_r_het[u->a[l]>>33])) - if (k == u->n || cov->t_ch->ir_het[u->a[k]>>33] != cov->t_ch->ir_het[u->a[l]>>33]) - { - kv_pushp(p_node_t, pg->pg_het_node, &t); - t->c_ug_id = uId; - t->h_status = cov->t_ch->ir_het[u->a[l]>>33]; - t->baseBeg = l_pos; - t->baseEnd = offset + read_g->seq[u->a[k-1]>>33].len - 1; - t->nodeBeg = l; - t->nodeEnd = k - 1; - ///if(t->b_ug_id == (uint32_t)-1) fprintf(stderr, "xxxx\n"); - ///asg_seq_set(pg->pg_het, pg->pg_het_node.n-1, t->baseEnd+1-t->baseBeg, 0); - ///fprintf(stderr, "l: %u, k: %u, u->n: %u, t->h_status: %u\n", l, k, u->n, t->h_status); - l = k; - l_pos = offset + (uint32_t)u->a[k-1]; - } - offset += (uint32_t)u->a[k-1]; - } - - occ = pg->pg_het_node.n - g_beg_idx; - kv_pushp(p_g_in_t, pg->pg_h_lev_idx, &x); - x->beg = g_beg_idx; x->occ = occ; - ///fprintf(stderr, "-v: %u, pg->pg_het_node.n: %u\n", v, (uint32_t)pg->pg_het_node.n); - - // if(occ > 1) - // { - // for (k = g_beg_idx; (k + 1) < pg->pg_het_node.n; ++k) - // { - // t = &(pg->pg_het_node.a[k]); tLen = t->baseEnd + 1 - t->baseBeg; - // z = &(pg->pg_het_node.a[k+1]); zLen = z->baseEnd + 1 - z->baseBeg; - - // ovlp = ((MIN(t->baseEnd, z->baseEnd) >= MAX(t->baseBeg, z->baseBeg))? - // MIN(t->baseEnd, z->baseEnd) - MAX(t->baseBeg, z->baseBeg) + 1 : 0); - - // e = asg_arc_pushp(pg->pg_het); - // e->ol = ovlp; - // e->ul = (k<<1); e->ul <<= 32; e->ul += (tLen - ovlp); - // e->v = ((k+1)<<1); e->del = 0; e->el = e->no_l_indel = e->strong = 1; - - // e = asg_arc_pushp(pg->pg_het); - // e->ol = ovlp; - // e->ul = ((k+1)<<1)+1; e->ul <<= 32; e->ul += (zLen - ovlp); - // e->v = (k<<1)+1; e->del = 0; e->el = e->no_l_indel = e->strong = 1; - // } - // } - } - ///asg_cleanup(pg->pg_het); - ///debug_p_g_t(pg, cov, read_g); - ///print_p_g_t_interval(pg, cov); - - return pg; -} - -void destory_p_g_t(p_g_t **pg) -{ - if(pg && (*pg)) - { - kv_destroy((*pg)->pg_het_node); - kv_destroy((*pg)->pg_h_lev_idx); - asg_destroy((*pg)->pg_het); - asg_destroy((*pg)->pg_h_lev); - free((*pg)); - (*pg) = NULL; - } -} - -void chain_origin_trans_uid_by_purge(hap_overlaps *x, ma_ug_t *ug, hap_cov_t *cov, uint64_t* position_index) -{ - uint32_t pri_uid, aux_uid, r_x, r_y; - hap_candidates hap_for, hap_rev, *hap = NULL; - long long x_pos_beg, x_pos_end, y_pos_beg, y_pos_end; - - Get_rev(hap_for) = x->rev; - Get_x_beg(hap_for) = x->x_beg_id; Get_x_end(hap_for) = x->x_end_id - 1; - Get_y_beg(hap_for) = x->y_beg_id; Get_y_end(hap_for) = x->y_end_id - 1; - r_x = determine_hap_overlap_type_advance(&hap_for, &(ug->u.a[x->xUid]), &(ug->u.a[x->yUid]), - cov->ruIndex, cov->reverse_sources, cov->coverage_cut, cov->read_g, position_index, - cov->max_hang, cov->min_ovlp, x->xUid, x->yUid, &(cov->u_buffer), &(cov->tailIndex), - &(cov->prevIndex), &x_pos_beg, &x_pos_end, &y_pos_beg, &y_pos_end); - - // if(r_x != (uint32_t)-1) - // { - // adjust_hap_overlaps_score(&(ug->u.a[x->xUid]), NULL, &(hap_for.score), - // x->xUid, x->yUid, x_pos_beg, x_pos_end); - // } - - - Get_rev(hap_rev) = x->rev; - Get_x_beg(hap_rev) = x->y_beg_id; Get_x_end(hap_rev) = x->y_end_id - 1; - Get_y_beg(hap_rev) = x->x_beg_id; Get_y_end(hap_rev) = x->x_end_id - 1; - r_y = determine_hap_overlap_type_advance(&hap_rev, &(ug->u.a[x->yUid]), &(ug->u.a[x->xUid]), - cov->ruIndex, cov->reverse_sources, cov->coverage_cut, cov->read_g, position_index, - cov->max_hang, cov->min_ovlp, x->yUid, x->xUid, &(cov->u_buffer), &(cov->tailIndex), - &(cov->prevIndex), &y_pos_beg, &y_pos_end, &x_pos_beg, &x_pos_end); - - // if(r_y != (uint32_t)-1) - // { - // adjust_hap_overlaps_score(&(ug->u.a[x->yUid]), NULL, &(hap_rev.score), - // x->yUid, x->xUid, y_pos_beg, y_pos_end); - // } - - if(r_x == (uint32_t)-1 && r_y == (uint32_t)-1) - { - fprintf(stderr, "ERROR-purge\n"); - return; - } - - Get_rev(hap_for) = x->rev; - Get_x_beg(hap_for) = x->x_beg_id; Get_x_end(hap_for) = x->x_end_id - 1; - Get_y_beg(hap_for) = x->y_beg_id; Get_y_end(hap_for) = x->y_end_id - 1; - - Get_rev(hap_rev) = x->rev; - Get_x_beg(hap_rev) = x->y_beg_id; Get_x_end(hap_rev) = x->y_end_id - 1; - Get_y_beg(hap_rev) = x->x_beg_id; Get_y_end(hap_rev) = x->x_end_id - 1; - - - if(r_x != (uint32_t)-1 && r_y == (uint32_t)-1) - { - pri_uid = x->xUid; aux_uid = x->yUid; hap = &hap_for; - } - else if(r_x == (uint32_t)-1 && r_y != (uint32_t)-1) - { - aux_uid = x->xUid; pri_uid = x->yUid; hap = &hap_rev; - } - else - { - if(hap_for.score >= hap_rev.score) - { - pri_uid = x->xUid; aux_uid = x->yUid; hap = &hap_for; - } - else - { - aux_uid = x->xUid; pri_uid = x->yUid; hap = &hap_rev; - } - } - - determine_hap_overlap_type_advance(hap, &(ug->u.a[pri_uid]), &(ug->u.a[aux_uid]), - cov->ruIndex, cov->reverse_sources, cov->coverage_cut, cov->read_g, position_index, - cov->max_hang, cov->min_ovlp, pri_uid, aux_uid, &(cov->u_buffer), &(cov->tailIndex), - &(cov->prevIndex), &x_pos_beg, &x_pos_end, &y_pos_beg, &y_pos_end); - - // adjust_hap_overlaps_score(&(ug->u.a[pri_uid]), NULL, &(hap->score), - // pri_uid, aux_uid, x_pos_beg, x_pos_end); - - uint64_t pri_len = ug->u.a[pri_uid].len, aux_len = ug->u.a[aux_uid].len; - pri_uid <<= 1; aux_uid <<= 1; aux_uid += hap->rev; - - // uint32_t i_n = cov->t_ch->k_trans.n, i; - - chain_origin_trans_uid_by_distance(cov, cov->read_g, &pri_uid, 1, x_pos_beg, &pri_len, - &aux_uid, 1, y_pos_beg, &aux_len, ug, RC_2, hap->score, __func__); - - // fprintf(stderr, "\nocc: %u\n", (uint32_t)(cov->t_ch->k_trans.n - i_n)); - // fprintf(stderr, "#s-utg%.6ul\t%u\t%u\td-utg%.6ul\t%u\t%u\trev(%u)\n", - // x->xUid+1, x->x_beg_pos, x->x_end_pos, x->yUid+1, x->y_beg_pos, x->y_end_pos, x->rev); - // for (i = i_n; i < cov->t_ch->k_trans.n; i++) - // { - // fprintf(stderr, "s-utg%.6ul\t%u\t%u\td-utg%.6ul\t%u\t%u\trev(%u)\n", - // cov->t_ch->k_trans.a[i].qn+1, cov->t_ch->k_trans.a[i].qs, cov->t_ch->k_trans.a[i].qe, - // cov->t_ch->k_trans.a[i].tn+1, cov->t_ch->k_trans.a[i].ts, cov->t_ch->k_trans.a[i].te, - // cov->t_ch->k_trans.a[i].rev); - // } -} - -void collect_purge_trans_cov(ma_ug_t *ug, hap_overlaps_list* ha, hap_cov_t *cov, uint64_t* position_index) -{ - uint32_t v, i; - hap_overlaps *x = NULL; - for (v = 0; v < ha->num; v++) - { - for (i = 0; i < ha->x[v].a.n; i++) - { - x = &(ha->x[v].a.a[i]); - if(x->yUid < x->xUid) continue; - chain_origin_trans_uid_by_purge(x, ug, cov, position_index); - } - } -} - -/** -typedef struct { - uint32_t qn, qs, qe; - uint32_t tn, ts, te; - uint32_t oid; - uint8_t rev; -}scg_hits; - -typedef struct { - scg_hits *a; - size_t n,m; - kvec_t(uint64_t) idx; -}scg_hits_v; - -#define scg_key_qtn(a) ((((uint64_t)(a).qn)<<32)|((uint64_t)(a).tn)) -KRADIX_SORT_INIT(scg_qtn, scg_hits, scg_key_qtn, 8) -#define scg_key_qts(a) ((((uint64_t)(a).qs)<<32)|((uint64_t)(a).ts)) -KRADIX_SORT_INIT(scg_qts, scg_hits, scg_key_qts, 8) -#define scg_key_qte(a) ((((uint64_t)(a).qe)<<32)|((uint64_t)(a).te)) -KRADIX_SORT_INIT(scg_qte, scg_hits, scg_key_qte, 8) -#define scg_key_rev(a) ((a).rev) -KRADIX_SORT_INIT(scg_rev, scg_hits, scg_key_rev, member_size(scg_hits, rev)) - -inline void rev_scg_hits(scg_hits *p, spg_t *scg) -{ - if(p->rev){ - uint32_t t; - p->ts = scg->ug->u.a[p->tn].len - p->ts - 1; - p->te = scg->ug->u.a[p->tn].len - (p->te - 1) - 1; - t = p->ts; p->ts = p->te; p->te = t; p->te++; - } -} - -#define arc_first(g, v) ((g)->arc[(g)->idx[(v)]>>32]) -scg_hits_v *get_scg_hits_v(scg_hits_v *vp, spg_t *scg) -{ - scg_hits_v *hh = NULL; CALLOC(hh, 1); - ma_utg_v *u = &(scg->ug->u); - uint32_t i, mn, *ma = NULL; - uint64_t offset, *idx = NULL; - - for (i = 0; i < scg->idx.n; i++) { - mn = (uint32_t)scg->idx.a[i]; - ma = scg->dst.a + (scg->idx.a[i]>>32); - } - - - - - return hh; -} - -void refine_scg(spg_t *scg, ma_ug_t *lug, hap_overlaps_list *ha, hap_cov_t *cov, uint64_t* position_index) -{ - scg_hits_v vp; kv_init(vp); - uint32_t v, i, k, st, c[2]; - hap_overlaps *x = NULL; - u_trans_t *z = NULL; - scg_hits *p = NULL; - - for (v = 0; v < cov->t_ch->k_trans.n; v++){ - z = &(cov->t_ch->k_trans.a[v]); - if(z->del) continue; - kv_pushp(scg_hits, vp, &p); - p->rev = z->rev; p->oid = (uint32_t)-1; - p->qn = z->qn; p->qs = z->qs; p->qe = z->qe; - p->tn = z->tn; p->ts = z->ts; p->te = z->te; - // rev_scg_hits(p, scg); - kv_pushp(scg_hits, vp, &p); - p->rev = z->rev; p->oid = (uint32_t)-1; - p->qn = z->tn; p->qs = z->ts; p->qe = z->te; - p->tn = z->qn; p->ts = z->qs; p->te = z->qe; - // rev_scg_hits(p, scg); - } - - for (v = 0; v < ha->num; v++){ - for (i = 0; i < ha->x[v].a.n; i++){ - x = &(ha->x[v].a.a[i]); - st = cov->t_ch->k_trans.n; - chain_origin_trans_uid_by_purge(x, lug, cov, position_index); - for (k = st; k < cov->t_ch->k_trans.n; k++){ - z = &(cov->t_ch->k_trans.a[k]); - if(z->del) continue; - kv_pushp(scg_hits, vp, &p); - p->rev = z->rev; p->oid = v; - p->qn = z->qn; p->qs = z->qs; p->qe = z->qe; - p->tn = z->tn; p->ts = z->ts; p->te = z->te; - // rev_scg_hits(p, scg); - kv_pushp(scg_hits, vp, &p); - p->rev = z->rev; p->oid = v; - p->qn = z->tn; p->qs = z->ts; p->qe = z->te; - p->tn = z->qn; p->ts = z->qs; p->te = z->qe; - // rev_scg_hits(p, scg); - } - cov->t_ch->k_trans.n = st; - } - } - - ///two scg_hits might be totally equal; must remove first - radix_sort_scg_qtn(vp.a, vp.a + vp.n); - for (st = 0, i = 1; i <= vp.n; ++i){ - if (i == vp.n || vp.a[i].qn != vp.a[st].qn || vp.a[i].tn != vp.a[st].tn){ - if(i - st > 1) radix_sort_scg_rev(vp.a+st, vp.a+i); - for (v = st, c[0] = c[1] = 0; v < i; v++) c[vp.a[v].rev]++; - if(c[0]>1) radix_sort_scg_qts(vp.a+st, vp.a+st+c[0]); - if(c[1]>1) radix_sort_scg_qts(vp.a+st+c[0], vp.a+st+c[0]+c[1]); - st = i; - } - } - for (st = 0, i = 1; i <= vp.n; ++i){ - if (i == vp.n || vp.a[i].rev != vp.a[st].rev || - vp.a[i].qn != vp.a[st].qn || vp.a[i].tn != vp.a[st].tn || - vp.a[i].qs != vp.a[st].qs || vp.a[i].ts != vp.a[st].ts) - { - if(i - st > 1) radix_sort_scg_qte(vp.a+st, vp.a+i); - st = i; - } - } - for (st = 0, i = 1, k = 0; i <= vp.n; ++i){ - if (i == vp.n || vp.a[i].rev != vp.a[st].rev || - vp.a[i].qn != vp.a[st].qn || vp.a[i].tn != vp.a[st].tn || - vp.a[i].qs != vp.a[st].qs || vp.a[i].ts != vp.a[st].ts || - vp.a[i].qe != vp.a[st].qe || vp.a[i].te != vp.a[st].te) - { - vp.a[k] = vp.a[st]; - k++; - st = i; - } - } - ///build idx - vp.n = k; kv_resize(uint64_t, vp.idx, scg->ug->u.n); vp.idx.n = scg->ug->u.n; - memset(vp.idx.a, 0, vp.idx.n*sizeof(uint64_t)); - for (st = 0, i = 1; i <= vp.n; ++i) - { - if (i == vp.n || vp.a[i].qn != vp.a[st].qn) - { - vp.idx.a[vp.a[st].qn] = (uint64_t)st << 32 | (i - st); - st = i; - } - } - - - kv_destroy(vp); kv_destroy(vp.idx); -} -**/ -uint32_t seed_uid(ma_utg_t *vu, uint64_t* ps_idx, R_to_U* ruIndex, ma_ug_t *rug) -{ - int64_t v_i, v, w, w_i, wb, we, vb, ve, k; - uint32_t uid, is_u; - ma_utg_t *wu = NULL; - for (v_i = 0; v_i < vu->n; v_i++) { - v = vu->a[v_i]>>32; - get_R_to_U(ruIndex, v>>1, &uid, &is_u); - if(is_u == 0 || uid == (uint32_t)-1 || ps_idx[v>>1] == (uint64_t)-1) continue; - w_i = (uint32_t)ps_idx[v>>1]; - wu = &(rug->u.a[uid]); - w = wu->a[w_i]>>32; - if((v>>1)!=(w>>1)) continue; - vb = 0; ve = vu->n; ///[vb, ve) - if(v == w){ ///[wb, we) - wb = w_i - v_i; - we = wb + vu->n; - if(wb < 0 || we > wu->n) continue; - for (k = 0; k < vu->n; k++){ - if((vu->a[k+vb]>>32) != (wu->a[k+wb]>>32)) break; - } - if(k >= vu->n) return uid; - } else { - wb = w_i + 1 - (ve - v_i); - we = wb + vu->n; - if(wb < 0 || we > wu->n) continue; - for (k = 0; k < vu->n; k++){ - if((vu->a[k+vb]>>32) != ((wu->a[we-k-1]>>32)^1)) break; - } - if(k >= vu->n) return uid; - } - } - return (uint32_t)-1; -} - -void filter_ovlp_vecs(hap_overlaps_list* ha, uint32_t *a, uint32_t a_n) -{ - uint32_t st, k, i, m, v, w; - int idx; - radix_sort_ru32(a, a + a_n); - for (st = 0, m = 0, k = 1; k <= a_n; k++){ - if(k == a_n || a[k] != a[st]){ - a[m++] = a[st]; - st = k; - } - } - a_n = m; - if(a_n < 2) return; - for (k = 0; k < a_n; k++){ - v = a[k]; - for (i = k+1; i < a_n; i++) { - w = a[i]; - idx = get_specific_hap_overlap(&(ha->x[v]), v, w); - if(idx != -1) ha->x[v].a.a[idx].status = DELETE; - idx = get_specific_hap_overlap(&(ha->x[w]), w, v); - if(idx != -1) ha->x[w].a.a[idx].status = DELETE; - } - } -} - -void filter_ovlp_scg(hap_overlaps_list* ha, uint64_t* ps_idx, R_to_U* ruIndex, ma_ug_t *rug, spg_t *scg) -{ - uint32_t i, k, v, *ma = NULL, mn, luid; - ma_utg_v *pp = &(scg->ug->u); - kvec_t(uint32_t) vv; kv_init(vv); - for (i = 0; i < scg->idx.n; i++){ - ma = scg->dst.a + (scg->idx.a[i]>>32); - mn = (uint64_t)scg->idx.a[i]; - if(mn < 2) continue; - for (k = 0, vv.n = 0; k < mn; k++){ - luid = seed_uid(&(pp->a[ma[k]>>1]), ps_idx, ruIndex, rug); - if(luid == (uint32_t)-1) { - fprintf(stderr, "ERROR-scg\n"); - continue; - } - kv_push(uint32_t, vv, luid); - } - if(vv.n < 2) continue; - filter_ovlp_vecs(ha, vv.a, vv.n); - } - - for (v = 0; v < ha->num; v++){ - for (i = 0, k = 0; i < ha->x[v].a.n; i++){ - if(ha->x[v].a.a[i].status == DELETE) continue; - ha->x[v].a.a[k++] = ha->x[v].a.a[i]; - } - ha->x[v].a.n = k; - } - - kv_destroy(vv); -} - -void purge_dups(ma_ug_t *ug, asg_t *read_g, ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, -ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, float density, -uint32_t purege_minLen, int max_hang, int min_ovlp, float drop_ratio, uint32_t just_contain, -uint32_t just_coverage, hap_cov_t *cov, uint32_t collect_p_trans, uint32_t collect_p_trans_f) -{ - p_g_t *pg = NULL; - asg_t* nsg = ug->g; - uint32_t v, rId, uId, i, offset; - ma_utg_t* reads = NULL; - uint64_t* position_index = NULL; - if(cov) position_index = cov->pos_idx; - else position_index = (uint64_t*)malloc(sizeof(uint64_t)*read_g->n_seq); - memset(position_index, -1, sizeof(uint64_t)*read_g->n_seq); - - hap_overlaps_list all_ovlp; - init_hap_overlaps_list(&all_ovlp, nsg->n_seq); - hap_overlaps_list back_all_ovlp; - init_hap_overlaps_list(&back_all_ovlp, nsg->n_seq); - asg_arc_t t, *p = NULL; - int r; - hap_alignment_struct_pip hap_buf; - long long k_mer_only, coverage_only; - - if(asm_opt.hom_global_coverage != -1) - { - hap_buf.cov_threshold = (asm_opt.hom_global_coverage_set? - (((double)asm_opt.hom_global_coverage)*((double)HOM_PEAK_RATE)):(asm_opt.hom_global_coverage)); - } - else - { - hap_buf.cov_threshold = get_read_coverage_thres(ug, read_g, ruIndex, position_index, - sources, coverage_cut, read_g->n_seq, COV_COUNT, &k_mer_only, &coverage_only); - } - - - for (v = 0; v < nsg->n_seq; v++) - { - uId = v; - reads = &(ug->u.a[uId]); - for (i = 0, offset = 0; i < reads->n; i++) - { - rId = reads->a[i]>>33; - set_R_to_U(ruIndex, rId, uId, 1, &(read_g->seq[rId].c)); - - position_index[rId] = offset; - position_index[rId] = position_index[rId] << 32; - position_index[rId] = position_index[rId] | (uint64_t)i; - - offset += (uint32_t)reads->a[i]; - } - } - - // if(just_coverage == 0) - // { - // ma_ug_seq(ug, read_g, coverage_cut, sources, edge, max_hang, min_ovlp, 0, 0); - // } - // init_ug_idx(ug, asm_opt.k_mer_length, asm_opt.polyploidy, 2, !just_coverage); - - init_hap_alignment_struct_pip(&hap_buf, asm_opt.thread_num, nsg->n_seq, ug, read_g, - sources, reverse_sources, ruIndex, coverage_cut, position_index, density, max_hang, min_ovlp, - 0.1, &all_ovlp, cov); - - if(hap_buf.cov_threshold < 0) - { - if(if_ploid_sample(ug, read_g, ruIndex, sources, reverse_sources, coverage_cut, - &hap_buf, &all_ovlp, &back_all_ovlp, purege_minLen, 0.333)) - { - ///if peak is het, coverage peak is more reliable - hap_buf.cov_threshold = coverage_only * HET_PEAK_RATE; - } - else - { - ///if peak is homo, k-mer peak is more reliable - hap_buf.cov_threshold = k_mer_only * HOM_PEAK_RATE; - } - } - if(asm_opt.hom_global_coverage == -1) asm_opt.hom_global_coverage = hap_buf.cov_threshold; - if(asm_opt.pur_global_coverage != -1) hap_buf.cov_threshold = asm_opt.pur_global_coverage; - fprintf(stderr, "[M::%s] homozygous read coverage threshold: %d\n", __func__, asm_opt.hom_global_coverage_set? - asm_opt.hom_global_coverage:(int)(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); - fprintf(stderr, "[M::%s] purge duplication coverage threshold: %lld\n", __func__, hap_buf.cov_threshold); - if(just_coverage) goto end_coverage; - - kt_for(asm_opt.thread_num, hap_alignment_advance_worker, &hap_buf, nsg->n_seq); - - ///if(debug_enable) print_all_purge_ovlp(ug, &all_ovlp); - filter_hap_overlaps_by_length(&all_ovlp, purege_minLen); - - // normalize_hap_overlaps_advance(&all_ovlp, &back_all_ovlp, ug, read_g, reverse_sources, ruIndex); - pg = init_p_g_t(ug, cov, read_g); - normalize_hap_overlaps_advance_by_p_g_t(&all_ovlp, &back_all_ovlp, ug, read_g, reverse_sources, ruIndex, pg, cov, 0.8); - - if(collect_p_trans && collect_p_trans_f == 0) - { - collect_purge_trans_cov(ug, &all_ovlp, cov, position_index); - } - - if(asm_opt.polyploidy <= 2) - { - mc_solve(&all_ovlp, cov->t_ch, NULL, ug, read_g, 0.8, R_INF.trio_flag, 1, NULL, 1, NULL, NULL, 1, 0); - } - - if(collect_p_trans && collect_p_trans_f == 1) - { - collect_purge_trans_cov(ug, &all_ovlp, cov, position_index); - } - - ///normalize_hap_overlaps_advance(&all_ovlp, &back_all_ovlp, ug, read_g, reverse_sources, ruIndex); - ///debug_hap_overlaps(&all_ovlp, &back_all_ovlp); - - remove_contained_haplotig(&all_ovlp, ug, nsg, pg->pg_h_lev, cov); - - if(just_contain == 0) - { - for (v = 0; v < all_ovlp.num; v++) - { - uId = v; - if(pg->pg_h_lev->seq[uId].del || pg->pg_h_lev->seq[uId].c == ALTER_LABLE) continue; - for (i = 0; i < all_ovlp.x[uId].a.n; i++) - { - if(all_ovlp.x[uId].a.a[i].status == DELETE) continue; - if(pg->pg_h_lev->seq[all_ovlp.x[uId].a.a[i].xUid].c == ALTER_LABLE|| - pg->pg_h_lev->seq[all_ovlp.x[uId].a.a[i].xUid].del|| - pg->pg_h_lev->seq[all_ovlp.x[uId].a.a[i].yUid].c == ALTER_LABLE|| - pg->pg_h_lev->seq[all_ovlp.x[uId].a.a[i].yUid].del) - { - continue; - } - - - ///print_hap_paf(ug, &(all_ovlp.x[uId].a.a[i])); - - r = get_hap_arch(&(all_ovlp.x[uId].a.a[i]), ug->u.a[all_ovlp.x[uId].a.a[i].xUid].len, - ug->u.a[all_ovlp.x[uId].a.a[i].yUid].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - - if(r < 0) continue; - p = asg_arc_pushp(pg->pg_h_lev); - *p = t; - } - } - - asg_cleanup(pg->pg_h_lev); - asg_symm(pg->pg_h_lev); - ///may need to do transitive reduction - clean_purge_graph(pg->pg_h_lev, drop_ratio, 1); - - // if(debug_enable) print_purge_gfa(ug, purge_g); - // if(debug_enable) print_all_purge_ovlp(ug, &all_ovlp); - /*******************************for debug************************************/ - // print_het_ovlp(pg, ug, &all_ovlp, 0.8); - /*******************************for debug************************************/ - - link_unitigs(pg->pg_h_lev, ug, &all_ovlp, ruIndex, reverse_sources, coverage_cut, read_g, position_index, - &(hap_buf.buf[0].u_buffer), &(hap_buf.buf[0].u_buffer_tailIndex), &(hap_buf.buf[0].u_buffer_prevIndex), - max_hang, min_ovlp, edge, hap_buf.buf[0].visit, cov); - } - - for (v = 0; v < all_ovlp.num; v++) - { - uId = v; - if(pg->pg_h_lev->seq[uId].c == ALTER_LABLE) - { - ug->g->seq[uId].c = ALTER_LABLE; - } - } - - end_coverage: - uint32_t is_Unitig; - for (v = 0; v < ruIndex->len; v++) - { - get_R_to_U(ruIndex, v, &uId, &is_Unitig); - if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; - } - asg_cleanup(nsg); - destory_hap_overlaps_list(&all_ovlp); - destory_hap_overlaps_list(&back_all_ovlp); - if(cov) memset(position_index, -1, sizeof(uint64_t)*read_g->n_seq); - else free(position_index); - destory_hap_alignment_struct_pip(&hap_buf); - destory_p_g_t(&pg); - // if(just_coverage == 0) - // { - // des_ug_idx(); - // for (i = 0; i < ug->u.n; i++) - // { - // free(ug->u.a[i].s); - // ug->u.a[i].s = NULL; - // } - // } -} +#define __STDC_LIMIT_MACROS +#include +#include +#include "ksort.h" +#include "Purge_Dups.h" +#include "Overlaps.h" +#include "Correct.h" +#include "kthread.h" +#include "kdq.h" +#include "hic.h" +#include "rcut.h" +#include "tovlp.h" + +KDQ_INIT(uint64_t) +KSORT_INIT_GENERIC(uint64_t) + +uint8_t debug_enable = 0; + +typedef struct { + uint64_t weight; + uint32_t x_beg_pos; + uint32_t x_end_pos; + uint32_t y_beg_pos; + uint32_t y_end_pos; + uint32_t index_beg; + uint32_t index_end; + long long score; + uint8_t rev; + asg_arc_t t; +}hap_candidates; + +typedef struct { + kvec_t(hap_candidates) a; + uint64_t i; +}kvec_hap_candidates; + + +typedef struct { + uint64_t* vote_counting; + uint8_t* visit; + kvec_t_u64_warp u_vecs; + kvec_asg_arc_t_offset u_buffer; + kvec_t_i32_warp u_buffer_tailIndex; + kvec_t_i32_warp u_buffer_prevIndex; + kvec_t_u8_warp u_buffer_flag; + kvec_t_i32_warp u_buffer_beg; + kvec_hap_candidates u_can; +}hap_alignment_struct; + + +typedef struct { + hap_alignment_struct* buf; + uint32_t num_threads; + uint8_t *hh; + ma_ug_t *ug; + asg_t *read_g; + ma_hit_t_alloc* sources; + ma_hit_t_alloc* reverse_sources; + R_to_U* ruIndex; + ma_sub_t *coverage_cut; + uint64_t* position_index; + float Hap_rate; + int max_hang; + int min_ovlp; + float chain_rate; + hap_overlaps_list* all_ovlp; + long long cov_threshold; + hap_cov_t *cov; +}hap_alignment_struct_pip; + +typedef struct { + uint32_t baseBeg, baseEnd; + uint32_t nodeBeg, nodeEnd; + uint32_t h_lev_idx; + uint32_t h_status, c_ug_id; +}p_node_t; + +typedef struct { + uint32_t beg; + uint32_t occ; +}p_g_in_t; + +typedef struct { + ma_ug_t *ug; + kvec_t(p_node_t) pg_het_node; + asg_t *pg_het; + asg_t *pg_h_lev; + kvec_t(p_g_in_t) pg_h_lev_idx; +}p_g_t; + +void print_peak_line(int c, int x, int exceed, int64_t cnt) +{ + int j; + if (c >= 0) fprintf(stderr, "[M::%s] %5d: ", __func__, c); + else fprintf(stderr, "[M::%s] %5s: ", __func__, "rest"); + for (j = 0; j < x; ++j) fputc('*', stderr); + if (exceed) fputc('>', stderr); + fprintf(stderr, " %lld\n", (long long)cnt); +} + +void print_peak(long long* cov_buf, long long cov_buf_length, long long max_i) +{ + long long i; + const long long hist_max = 100; + // print histogram + for (i = 0; i < cov_buf_length; ++i) + { + long long x, exceed = 0; + x = (int)((double)hist_max * cov_buf[i] / cov_buf[max_i] + .499); + if (x > hist_max) exceed = 1, x = hist_max; // may happen if cnt[2] is higher + if (i > max_i && x == 0) break; + print_peak_line(i, x, exceed, cov_buf[i]); + } + { + long long x, exceed = 0; + long long rest = 0; + for (; i < cov_buf_length; ++i) rest += cov_buf[i]; + x = (int)((double)hist_max * rest / cov_buf[max_i] + .499); + if (x > hist_max) exceed = 1, x = hist_max; + print_peak_line(-1, x, exceed, rest); + } +} + + +void get_read_peak(asg_t *read_g, long long* cov_buf, long long cov_buf_length, long long* topo_peak_cov, +long long* hom_peak, long long* het_peak, long long* k_mer_only, long long* coverage_only, long long g_size) +{ + long long i, start, err_i, max_i, max2_i, max3_i, topo_peak_i, max, max2, max3, topo_peak, min; + + i = start = err_i = max_i = max2_i = max3_i = topo_peak_i = -1; + max = max2 = max3 = topo_peak = min = -1; + + ///cov_buf[0] is usually very large + for (i = 1; i < cov_buf_length; ++i) + { + if(cov_buf[i] > cov_buf[i-1]) break; + } + err_i = i - 1; + // find the global highest peak + max_i = err_i + 1, max = cov_buf[max_i]; + for (i = max_i; i < cov_buf_length; ++i) + { + if (cov_buf[i] > max) + { + max = cov_buf[i]; + max_i = i; + } + } + + ///print_peak(cov_buf, cov_buf_length, max_i); + + // look for smaller peak on the low end + max2 = -1; max2_i = -1; + for (i = max_i - 1; i > err_i; --i) + { + ///at first, it should be a peak + if (cov_buf[i] >= cov_buf[i-1] && cov_buf[i] >= cov_buf[i+1]) + { + if (cov_buf[i] > max2) + { + max2 = cov_buf[i]; + max2_i = i; + } + } + } + + ///fprintf(stderr, "***max2: %lld, max2_i: %lld\n", max2, max2_i); + + if (max2_i != -1 && max2_i > err_i && max2_i < max_i) + { + for (i = max2_i + 1, min = max; i < max_i; ++i) + { + if (cov_buf[i] < min) min = cov_buf[i]; + } + + ///if the second peak is not significant + if(max2 < max * 0.05 || min > max2 * 0.95) max2 = max2_i = -1; + } + if(max2 < max*0.0075) max2 = max2_i = -1; + + + // look for smaller peak on the high end + max3 = -1; max3_i = -1; + // we'd better use i < cov_buf_length - 1, since cov_buf[cov_buf_length-1] may have problem + for (i = max_i + 1; i < cov_buf_length - 1; ++i) + { + //at first, it should be a peak + if (cov_buf[i] >= cov_buf[i-1] && cov_buf[i] >= cov_buf[i+1]) + { + if (cov_buf[i] > max3) + { + max3 = cov_buf[i], max3_i = i; + } + } + } + + ///fprintf(stderr, "***max3: %lld, max3_i: %lld\n", max3, max3_i); + + //if found a peak + if (max3 != -1 && max3_i > max_i) + { + for (i = max_i + 1, min = max; i < max3_i; ++i) + { + if (cov_buf[i] < min) min = cov_buf[i]; + } + + if (max3 < max * 0.05 || min > max3 * 0.95 || max3_i > max_i * 3) max3 = max3_i = -1; + } + if (max3 < max*0.0075) max3 = max3_i = -1; + + + + (*hom_peak) = (*het_peak) = -1; + if (topo_peak_cov && (*topo_peak_cov) < cov_buf_length) + { + topo_peak_i = (*topo_peak_cov); + topo_peak = cov_buf[topo_peak_i]; + if (topo_peak <= max * 0.05) topo_peak_i = topo_peak = -1; + } + + if(asm_opt.purge_level_primary == 0) + { + (*hom_peak) = max_i; + return; + } + + + long long k_mer_het, k_mer_hom, coverage_het, coverage_hom, alter_peak; + k_mer_het = k_mer_hom = coverage_het = coverage_hom = alter_peak = -1; + + alter_peak = topo_peak_i; + k_mer_het = asm_opt.het_cov; + k_mer_hom = asm_opt.hom_cov; + if(max3_i > 0) + { + coverage_het = max_i; + coverage_hom = max3_i; + } + else + { + coverage_het = max2_i; + coverage_hom = max_i; + } + + if(g_size > 0) { + long long n_bs, m_peak_hom = -1; + int p_ht = -1; + for (i = n_bs = 0; i < read_g->n_seq; i++) n_bs += read_g->seq[i].len; + m_peak_hom = n_bs/g_size; + if(m_peak_hom > 0) { + p_ht = -1; + coverage_hom = adj_m_peak_hom(m_peak_hom, max_i, max2_i, max3_i, &p_ht); + coverage_het = p_ht; + } + } + + if(k_mer_het != -1) + { + (*het_peak) = k_mer_het; + (*hom_peak) = k_mer_hom; + return; + } + else if(coverage_het != -1) + { + (*het_peak) = coverage_het; + (*hom_peak) = coverage_hom; + return; + } + else if(k_mer_hom > coverage_hom*1.5) + { + (*het_peak) = coverage_hom; + (*hom_peak) = k_mer_hom; + return; + } + else if(alter_peak != -1) + { + ///if peak is het, coverage peak is more reliable + if(coverage_hom >= alter_peak*0.8 && coverage_hom <= alter_peak*1.2) + { + (*het_peak) = coverage_hom; + return; + }///if peak is homo, k-mer peak is more reliable + else if(k_mer_hom >= alter_peak*0.8*2 && k_mer_hom <= alter_peak*1.2*2) + { + (*hom_peak) = k_mer_hom; + return; + } + } + + (*k_mer_only) = k_mer_hom; + (*coverage_only) = coverage_hom; + + + // fprintf(stderr, "max: %lld, max_i: %lld\n", max, max_i); + // fprintf(stderr, "max2: %lld, max2_i: %lld\n", max2, max2_i); + // fprintf(stderr, "max3: %lld, max3_i: %lld\n", max3, max3_i); + // fprintf(stderr, "[M::%s] Heterozygous k-mer peak: %d\n", __func__, asm_opt.het_cov); + // fprintf(stderr, "[M::%s] Homozygous k-mer peak: %d\n", __func__, asm_opt.hom_cov); + // fprintf(stderr, "[M::%s] Heterozygous coverage peak: %lld\n", __func__, (*het_peak)); + // fprintf(stderr, "[M::%s] Homozygous coverage peak: %lld\n", __func__, (*hom_peak)); + // fprintf(stderr, "[M::%s] Alter coverage peak: %lld\n", __func__, topo_peak_i); +} + + + + +long long get_alter_peak(ma_ug_t *ug, asg_t *read_g, R_to_U* ruIndex, uint64_t* position_index, +ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, long long cov_buf_length) +{ + + ma_utg_t* u = NULL; + asg_t* nsg = ug->g; + uint64_t v, j, k, qn, n_vtx = nsg->n_seq, primary_bases = 0, alter_bases = 0; + uint32_t tn, is_Unitig; + long long* cov_buf = NULL; + ma_hit_t *h; + cov_buf = (long long*)calloc(cov_buf_length, sizeof(long long)); + long long R_bases = 0, C_bases_primary = 0, C_bases_alter = 0, C_bases = 0; + memset(position_index, -1, sizeof(uint64_t)*read_g->n_seq); + + + for (v = 0; v < n_vtx; ++v) + { + if(nsg->seq[v].del) continue; + if(nsg->seq[v].c == ALTER_LABLE) continue; + u = &(ug->u.a[v]); + if(u->m == 0) continue; + for (k = 0; k < u->n; k++) + { + qn = u->a[k]>>33; + position_index[qn] = 0; + R_bases = coverage_cut[qn].e - coverage_cut[qn].s; + primary_bases += R_bases; + } + } + + for (qn = 0; qn < read_g->n_seq; qn++) + { + if(position_index[qn] == 0) continue; + if(read_g->seq[qn].del) continue; + + C_bases = C_bases_primary = C_bases_alter = 0; + R_bases = coverage_cut[qn].e - coverage_cut[qn].s; + alter_bases += R_bases; + for (j = 0; j < (uint64_t)(sources[qn].length); j++) + { + h = &(sources[qn].buffer[j]); + if(h->el != 1) continue; + tn = Get_tn((*h)); + + if(read_g->seq[tn].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + + if(position_index[tn] == 0) + { + C_bases_primary += Get_qe((*h)) - Get_qs((*h)); + } + else + { + C_bases_alter += Get_qe((*h)) - Get_qs((*h)); + } + } + + C_bases = C_bases_primary + C_bases_alter; + if(C_bases_alter < C_bases * ALTER_COV_THRES) continue; + + C_bases = C_bases/R_bases; + if(C_bases < 0 || C_bases >= cov_buf_length) continue; + cov_buf[C_bases]++; + } + + long long max_i = -1, max = -1; + for (j = 0; (long long)j < cov_buf_length; ++j) + { + if (cov_buf[j] > max) + { + max = cov_buf[j]; + max_i = j; + } + } + + if(alter_bases < primary_bases * REAL_ALTER_THRES) max_i = max = -1; + + free(cov_buf); + memset(position_index, -1, sizeof(uint64_t)*read_g->n_seq); + + return max_i; +} + +long long get_read_coverage_thres(ma_ug_t *ug, asg_t *read_g, R_to_U* ruIndex, uint64_t* position_index, +ma_hit_t_alloc* sources, ma_sub_t* coverage_cut, uint64_t n_read, long long cov_buf_length, +long long* k_mer_only, long long* coverage_only) +{ + uint64_t i, j; + long long* cov_buf = NULL; + ma_hit_t *h; + cov_buf = (long long*)calloc(cov_buf_length, sizeof(long long)); + long long R_bases = 0, C_bases = 0; + for (i = 0; i < n_read; ++i) + { + C_bases = 0; + R_bases = coverage_cut[i].e - coverage_cut[i].s; + for (j = 0; j < (uint64_t)(sources[i].length); j++) + { + h = &(sources[i].buffer[j]); + if(h->el != 1) continue; + C_bases += Get_qe((*h)) - Get_qs((*h)); + } + C_bases = C_bases/R_bases; + if(C_bases < 0 || C_bases >= cov_buf_length) continue; + cov_buf[C_bases]++; + } + + long long alter_peak = -1, hom_peak = -1, het_peak = -1; + if(position_index) + { + alter_peak = get_alter_peak(ug, read_g, ruIndex, position_index, sources, coverage_cut, + cov_buf_length); + } + + get_read_peak(read_g, cov_buf, cov_buf_length, alter_peak == -1? NULL: &alter_peak, &hom_peak, &het_peak, + k_mer_only, coverage_only, asm_opt.hg_size); + + free(cov_buf); + + if(hom_peak != -1) return hom_peak*HOM_PEAK_RATE; + if(het_peak != -1) return het_peak*HET_PEAK_RATE; + return -1; +} + + + + + + + + + + +void init_hap_alignment_struct(hap_alignment_struct* x, uint32_t size) +{ + x->vote_counting = (uint64_t*)malloc(sizeof(uint64_t)*size); + memset(x->vote_counting, 0, sizeof(uint64_t)*size); + + x->visit = (uint8_t*)malloc(sizeof(uint8_t)*size); + memset(x->visit, 0, size); + + kv_init(x->u_vecs.a); + kv_init(x->u_buffer.a); + kv_init(x->u_buffer_tailIndex.a); + kv_init(x->u_buffer_prevIndex.a); + kv_init(x->u_buffer_beg.a); + kv_init(x->u_buffer_flag.a); + kv_init(x->u_can.a); +} + +void destory_hap_alignment_struct(hap_alignment_struct* x) +{ + free(x->vote_counting); + free(x->visit); + kv_destroy(x->u_vecs.a); + kv_destroy(x->u_buffer.a); + kv_destroy(x->u_buffer_tailIndex.a); + kv_destroy(x->u_buffer_prevIndex.a); + kv_destroy(x->u_buffer_beg.a); + kv_destroy(x->u_buffer_flag.a); + kv_destroy(x->u_can.a); +} + +uint8_t *init_pip_hh(asg_t *rg, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, long long sc) +{ + uint8_t *c = NULL; CALLOC(c, rg->n_seq); + ma_hit_t *h = NULL; + uint32_t i, k; + long long R_Base, C_Base; + for (i = 0; i < rg->n_seq; i++) { + if(sc <= 0){ + c[i] = 1; + continue; + } + R_Base = (coverage_cut[i].e - coverage_cut[i].s); + for (k = 0, C_Base = 0; k < reverse_sources[i].length; k++){ + h = &(reverse_sources[i].buffer[k]); + C_Base += (Get_qe((*h)) - Get_qs((*h))); + } + C_Base = (R_Base!=0?(C_Base/R_Base):0); + C_Base /= sc; + c[i] = 1; + if(C_Base < REV_W) c[i] = REV_W - C_Base; + } + return c; +} + +void init_hap_alignment_struct_pip(hap_alignment_struct_pip* x, uint32_t num_threads, uint32_t n_seq, +ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, ma_sub_t *coverage_cut, +uint64_t* position_index, float Hap_rate, int max_hang, int min_ovlp, float chain_rate, hap_overlaps_list* all_ovlp, hap_cov_t *cov) +{ + uint32_t i; + x->num_threads = num_threads; + x->buf = (hap_alignment_struct*)malloc(sizeof(hap_alignment_struct)*x->num_threads); + for (i = 0; i < x->num_threads; i++) + { + init_hap_alignment_struct(&(x->buf[i]), n_seq); + } + + x->ug = ug; + x->read_g = read_g; + x->sources = sources; + x->reverse_sources = reverse_sources; + x->ruIndex = ruIndex; + x->coverage_cut = coverage_cut; + x->position_index = position_index; + x->Hap_rate = Hap_rate; + x->max_hang = max_hang; + x->min_ovlp = min_ovlp; + x->chain_rate = chain_rate; + x->all_ovlp = all_ovlp; + x->cov = cov; + long long sc = -1; + if(asm_opt.hom_global_coverage_set) { + sc = asm_opt.hom_global_coverage*1.75; + } + else { + if(asm_opt.hom_global_coverage > 0){ + sc = ((int)(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE)))*1.75; + } + } + if(sc <= 0) sc = -1; + x->hh = init_pip_hh(read_g, reverse_sources, coverage_cut, sc); +} + + +void destory_hap_alignment_struct_pip(hap_alignment_struct_pip* x) +{ + uint32_t i; + for (i = 0; i < x->num_threads; i++) + { + destory_hap_alignment_struct(&(x->buf[i])); + } + + free(x->buf); + free(x->hh); +} + +void init_hap_overlaps_list(hap_overlaps_list* x, uint32_t num) +{ + uint32_t i = 0; + x->num = num; + x->x = (kvec_hap_overlaps*)malloc(sizeof(kvec_hap_overlaps)*x->num); + for (i = 0; i < x->num; i++) + { + kv_init(x->x[i].a); + } +} + +void enable_debug_mode(uint32_t mode) +{ + debug_enable = mode; +} + +void destory_hap_overlaps_list(hap_overlaps_list* x) +{ + uint32_t i = 0; + for (i = 0; i < x->num; i++) + { + kv_destroy(x->x[i].a); + } + free(x->x); +} + + + +inline void clean_visit_flag(uint8_t* visit, asg_t *read_g, R_to_U* ruIndex, uint32_t contigNum, +ma_hit_t_alloc* x) +{ + uint32_t k, rId, is_Unitig, Hap_cId; + + if(x->length*2 > contigNum) + { + memset(visit, 0, contigNum); + } + else + { + for (k = 0; k < x->length; k++) + { + rId = Get_tn(x->buffer[k]); + + if(read_g->seq[rId].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, rId, &rId, &is_Unitig); + if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; + } + + ///there are two cases: + ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id + ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 + get_R_to_U(ruIndex, rId, &Hap_cId, &is_Unitig); + if(is_Unitig == 0 || Hap_cId == (uint32_t)-1) continue; + ///here rId is the id of the read coming from the different haplotype + ///Hap_cId is the id of the corresponding contig (note here is the contig, instead of untig) + visit[Hap_cId] = 0; + } + } +} + +uint32_t prefilter(uint32_t x_pos, uint32_t y_pos, uint32_t xLen, uint32_t yLen, uint32_t dir, +float Hap_rate, uint32_t seedOcc) +{ + uint32_t max_count = 0, min_count = 0; + uint32_t /**xLeftBeg, **/xLeftLen, yLeftBeg, yLeftLen; + uint32_t xRightBeg, xRightLen, yRightBeg, yRightLen; + if(dir == 0) + { + /**xLeftBeg = 0;**/ xLeftLen = x_pos; xRightBeg = x_pos; xRightLen = xLen - xRightBeg; + yLeftBeg = 0; yLeftLen = y_pos; yRightBeg = y_pos; yRightLen = yLen - yRightBeg; + } + else + { + /**xLeftBeg = 0;**/ xLeftLen = x_pos; xRightBeg = x_pos; xRightLen = xLen - xRightBeg; + + yLeftBeg = y_pos + 1; yLeftLen = yLen - yLeftBeg; + yRightBeg = 0; yRightLen = y_pos + 1; + } + + + + max_count = seedOcc; + min_count = MIN(xLeftLen, yLeftLen) + MIN(xRightLen, yRightLen); + if(min_count == 0) return NON_PLOID; + if(max_count <= min_count*Hap_rate) return NON_PLOID; + return PLOID; +} + + + +inline uint64_t get_xy_pos(asg_t *read_g, asg_arc_t* t, uint32_t v_in_unitig, uint32_t w_in_unitig, +uint32_t xUnitigLen, uint32_t yUnitigLen, uint64_t* position_index, uint8_t* rev) +{ + uint32_t x_pos, y_pos, x_dir = 0, y_dir = 0; + uint64_t tmp; + x_pos = y_pos = (uint32_t)-1; + if((t->ul>>32)==v_in_unitig)///end pos + { + x_pos = (position_index[v_in_unitig>>1]>>32) + read_g->seq[v_in_unitig>>1].len - 1; + x_dir = 0; + } + else if((t->ul>>32)==(v_in_unitig^1))///start pos + { + x_pos = (position_index[v_in_unitig>>1]>>32); + x_dir = 1; + } + else + { + fprintf(stderr, "ERROR\n"); + } + + if(t->v == w_in_unitig) + { + y_pos = (position_index[w_in_unitig>>1]>>32) + t->ol - 1; + y_dir = 0; + } + else if(t->v == (w_in_unitig^1)) + { + y_pos = (position_index[w_in_unitig>>1]>>32) + read_g->seq[w_in_unitig>>1].len - t->ol; + y_dir = 1; + } + else + { + fprintf(stderr, "ERROR\n"); + } + + (*rev) = x_dir^y_dir; + if((*rev)) + { + if(yUnitigLen <= y_pos) + { + y_pos = (uint32_t)-1; + } + else + { + y_pos = yUnitigLen - y_pos - 1; + } + } + + if(x_pos>=xUnitigLen) x_pos = (uint32_t)-1; + if(y_pos>=yUnitigLen) y_pos = (uint32_t)-1; + + tmp = x_pos; tmp = tmp << 32; tmp = tmp | y_pos; + return tmp; +} + + +void print_debug_unitig(ma_utg_t *xReads, uint64_t* position_index, const char* infor) +{ + uint32_t k; + fprintf(stderr, "\n%s: n = %u\n", infor, xReads->n); + for (k = 0; k < xReads->n; k++) + { + fprintf(stderr, "(%u)v: %u, len: %u, index: %u, pos: %u\n", + k, (uint32_t)(xReads->a[k]>>32), (uint32_t)xReads->a[k], (uint32_t)(position_index[xReads->a[k]>>33]), + (uint32_t)(position_index[xReads->a[k]>>33]>>32)); + } +} + +void deduplicate_edge(kvec_asg_arc_t_offset* u_buffer) +{ + if(u_buffer->a.n == 0) return; + long long i = u_buffer->a.n - 1, k, i_off; + uint32_t v = u_buffer->a.a[i].x.ul>>33, m; + + for (; i >= 0; i--) { + if((u_buffer->a.a[i].x.ul>>33) != v) break; + } + + i = i + 1; + for (m = i; i < (long long)u_buffer->a.n; i++) + { + if(u_buffer->a.a[i].x.del) continue; + + i_off = Cal_Off(u_buffer->a.a[i].Off); + + for (k = i + 1; k < (long long)u_buffer->a.n; k++) + { + if(u_buffer->a.a[k].x.del) continue; + if(u_buffer->a.a[i].x.el != u_buffer->a.a[k].x.el) continue; + if(i_off != Cal_Off(u_buffer->a.a[k].Off)) continue; + u_buffer->a.a[k].x.del = 1; + u_buffer->a.a[i].weight += u_buffer->a.a[k].weight; + } + u_buffer->a.a[m] = u_buffer->a.a[i]; + m++; + } + + u_buffer->a.n = m; + ///fprintf(stderr, "u_buffer->a.n: %u, i: %lld\n", u_buffer->a.n, i); +} + +int cmp_hap_alignment(const void * a, const void * b) +{ + if((*(asg_arc_t_offset*)a).x.el > (*(asg_arc_t_offset*)b).x.el) return 1; + if((*(asg_arc_t_offset*)a).x.el < (*(asg_arc_t_offset*)b).x.el) return -1; + + long long aOff = Cal_Off((*(asg_arc_t_offset*)a).Off); + long long bOff = Cal_Off((*(asg_arc_t_offset*)b).Off); + + if(aOff > bOff) return 1; + if(aOff < bOff) return -1; + + if(((*(asg_arc_t_offset*)a).Off>>32) > ((*(asg_arc_t_offset*)b).Off>>32)) return 1; + if(((*(asg_arc_t_offset*)a).Off>>32) < ((*(asg_arc_t_offset*)b).Off>>32)) return -1; + + if((uint32_t)((*(asg_arc_t_offset*)a).Off) > (uint32_t)((*(asg_arc_t_offset*)b).Off)) return 1; + if((uint32_t)((*(asg_arc_t_offset*)a).Off) < (uint32_t)((*(asg_arc_t_offset*)b).Off)) return -1; + + if((*(asg_arc_t_offset*)a).weight < (*(asg_arc_t_offset*)b).weight) return 1; + if((*(asg_arc_t_offset*)a).weight > (*(asg_arc_t_offset*)b).weight) return -1; + + return 0; +} + + +int cmp_hap_alignment_chaining(const void * a, const void * b) +{ + if((*(asg_arc_t_offset*)a).x.el > (*(asg_arc_t_offset*)b).x.el) return 1; + if((*(asg_arc_t_offset*)a).x.el < (*(asg_arc_t_offset*)b).x.el) return -1; + + if(((*(asg_arc_t_offset*)a).Off>>32) > ((*(asg_arc_t_offset*)b).Off>>32)) return 1; + if(((*(asg_arc_t_offset*)a).Off>>32) < ((*(asg_arc_t_offset*)b).Off>>32)) return -1; + + if((uint32_t)((*(asg_arc_t_offset*)a).Off) > (uint32_t)((*(asg_arc_t_offset*)b).Off)) return 1; + if((uint32_t)((*(asg_arc_t_offset*)a).Off) < (uint32_t)((*(asg_arc_t_offset*)b).Off)) return -1; + + return 0; +} + +int cmp_hap_candidates(const void * a, const void * b) +{ + if((*(hap_candidates*)a).weight < (*(hap_candidates*)b).weight) return 1; + if((*(hap_candidates*)a).weight > (*(hap_candidates*)b).weight) return -1; + + if((*(hap_candidates*)a).index_beg > (*(hap_candidates*)b).index_beg) return 1; + if((*(hap_candidates*)a).index_beg < (*(hap_candidates*)b).index_beg) return -1; + + return 0; +} +inline long long get_hap_overlapLen(long long x_beg, long long x_end, long long xLen, +long long y_beg, long long y_end, long long yLen, long long* n_x_beg, long long* n_x_end, +long long* n_y_beg, long long* n_y_end) +{ + if(x_beg <= y_beg) + { + y_beg = y_beg - x_beg; + x_beg = 0; + } + else + { + x_beg = x_beg - y_beg; + y_beg = 0; + } + + long long x_right_length = xLen - x_end - 1; + long long y_right_length = yLen - y_end - 1; + + + if(x_right_length <= y_right_length) + { + x_end = xLen - 1; + y_end = y_end + x_right_length; + } + else + { + x_end = x_end + y_right_length; + y_end = yLen - 1; + } + + if(n_x_beg) (*n_x_beg) = x_beg; + if(n_x_end) (*n_x_end) = x_end; + if(n_y_beg) (*n_y_beg) = y_beg; + if(n_y_end) (*n_y_end) = y_end; + + return x_end - x_beg + 1; +} + + + +uint32_t classify_hap_overlap(long long xBeg, long long xEnd, long long xLen, +long long yBeg, long long yEnd, long long yLen, long long* r_xBeg, long long* r_xEnd, +long long* r_yBeg, long long* r_yEnd) +{ + long long n_x_beg, n_x_end, n_y_beg, n_y_end; + get_hap_overlapLen(xBeg, xEnd, xLen, yBeg, yEnd, yLen, &n_x_beg, &n_x_end, &n_y_beg, &n_y_end); + if(r_xBeg) (*r_xBeg) = n_x_beg; + if(r_xEnd) (*r_xEnd) = n_x_end; + if(r_yBeg) (*r_yBeg) = n_y_beg; + if(r_yEnd) (*r_yEnd) = n_y_end; + if(n_x_beg == 0 && n_x_end == xLen - 1) return YCX; + if(n_y_beg == 0 && n_y_end == yLen - 1) return XCY; + if(n_y_beg == 0 && n_x_end == xLen - 1) return X2Y; + if(n_x_beg == 0 && n_y_end == yLen - 1) return Y2X; + return XCY; +} + + +uint64_t get_pair_hap_coverage(uint64_t* readIDs, uint32_t Len, ma_hit_t_alloc* sources, ma_sub_t* coverage_cut) +{ + uint32_t m, n, qn; + ma_hit_t *h; + uint64_t R_bases = 0, C_bases = 0; + + for (m = 0; m < Len; m++) + { + qn = readIDs[m]>>33; + R_bases += coverage_cut[qn].e - coverage_cut[qn].s; + for (n = 0; n < (uint64_t)(sources[qn].length); n++) + { + h = &(sources[qn].buffer[n]); + C_bases += Get_qe((*h)) - Get_qs((*h)); + } + } + + return C_bases/R_bases; +} + + +uint64_t get_pair_purge_coverage(ma_utg_t *xReads, long long xPosBeg, long long xPosEnd, +ma_utg_t *yReads, long long yPosBeg, long long yPosEnd, uint32_t rev, asg_t *read_g, hap_cov_t *cov) +{ + long long offset, r_beg, r_end, i_beg, i_end, ovlp, IdxBeg, IdxEnd; + uint64_t i, rId, uCov, uLen; + ma_utg_t *x = NULL; + uCov = uLen = 0; + if(rev) + { + yPosBeg = yReads->len - yPosBeg - 1; + yPosEnd = yReads->len - yPosEnd - 1; + offset = yPosBeg; yPosBeg = yPosEnd; yPosEnd = offset; + } + + + IdxBeg = IdxEnd = -1; + x = xReads; i_beg = xPosBeg; i_end = xPosEnd; + for (i = 0, offset = 0; i < x->n; i++) + { + rId = x->a[i]>>33; + r_beg = offset; r_end = offset + (long long)(read_g->seq[rId].len) - 1; + offset += (uint32_t)x->a[i]; + ovlp = (long long)(MIN(r_end, i_end)) - (long long)(MAX(r_beg, i_beg)) + 1; + if(ovlp <= 0 || ovlp < read_g->seq[rId].len * 0.8) + { + if(IdxBeg != -1 && IdxEnd != -1) break; + continue; + } + + if(IdxBeg == -1) IdxBeg = i; + IdxEnd = i; + } + if(IdxBeg != -1 && IdxEnd != -1) + { + for (i = IdxBeg; (long long)i <= IdxEnd; i++) + { + rId = x->a[i]>>33; + uCov += cov->cov[rId]; + uLen += cov->read_g->seq[rId].len; + } + } + + + + IdxBeg = IdxEnd = -1; + x = yReads; i_beg = yPosBeg; i_end = yPosEnd; + for (i = 0, offset = 0; i < x->n; i++) + { + rId = x->a[i]>>33; + r_beg = offset; r_end = offset + (long long)(read_g->seq[rId].len) - 1; + offset += (uint32_t)x->a[i]; + ovlp = (long long)(MIN(r_end, i_end)) - (long long)(MAX(r_beg, i_beg)) + 1; + if(ovlp <= 0 || ovlp < read_g->seq[rId].len * 0.8) + { + if(IdxBeg != -1 && IdxEnd != -1) break; + continue; + } + + if(IdxBeg == -1) IdxBeg = i; + IdxEnd = i; + } + if(IdxBeg != -1 && IdxEnd != -1) + { + for (i = IdxBeg; (long long)i <= IdxEnd; i++) + { + rId = x->a[i]>>33; + uCov += cov->cov[rId]; + uLen += cov->read_g->seq[rId].len; + } + } + + return (uLen == 0? 0 : uCov / uLen); +} + + +void get_pair_hap_similarity_by_base(ma_utg_t *xReads, asg_t *read_g, uint32_t target_uId, +ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, long long xBegPos, long long xEndPos, +double* Match, double* Total) +{ + uint32_t i, j, qn, tn, is_Unitig, uId, min_count = 0, max_count = 0; + long long offset, r_beg, r_end, ovlp; + + for (i = 0, offset = 0; i < xReads->n; i++) + { + qn = xReads->a[i]>>33; + r_beg = offset; r_end = offset + (long long)(read_g->seq[qn].len) - 1; + offset += (uint32_t)xReads->a[i]; + + ovlp = (long long)(MIN(r_end, xEndPos)) - (long long)(MAX(r_beg, xBegPos)) + 1; + if(ovlp <= 0) continue; + + if(reverse_sources[qn].length > 0) min_count++; + if(reverse_sources[qn].length == 0) continue; + for (j = 0; j < reverse_sources[qn].length; j++) + { + tn = Get_tn(reverse_sources[qn].buffer[j]); + if(read_g->seq[tn].del == 1) + { + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + + + get_R_to_U(ruIndex, tn, &uId, &is_Unitig); + if(uId!=(uint32_t)-1 && is_Unitig == 1 && uId == target_uId) + { + max_count++; + break; + } + } + } + + (*Match) = max_count; + (*Total) = min_count; +} + +void get_pair_hap_similarity(uint64_t* readIDs, uint32_t Len, uint32_t target_uId, +ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, double* Match, double* Total) +{ + #define CUTOFF_THRES 1000 + uint32_t i, j, qn, tn, is_Unitig, uId, min_count = 0, max_count = 0, cutoff = 0;; + for (i = 0; i < Len; i++) + { + if(cutoff > CUTOFF_THRES && cutoff > (Len>>1)) + { + max_count = 0; + min_count = Len; + break; + } + qn = readIDs[i]>>33; + if(reverse_sources[qn].length > 0) min_count++; + if(reverse_sources[qn].length == 0) continue; + for (j = 0; j < reverse_sources[qn].length; j++) + { + tn = Get_tn(reverse_sources[qn].buffer[j]); + if(read_g->seq[tn].del == 1) + { + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + + + get_R_to_U(ruIndex, tn, &uId, &is_Unitig); + if(uId!=(uint32_t)-1 && is_Unitig == 1 && uId == target_uId) + { + max_count++; + break; + } + } + + //means no match + if(j == reverse_sources[qn].length) + { + cutoff++; + } + else + { + cutoff = 0; + } + } + + (*Match) = max_count; + (*Total) = min_count; +} +/** +void get_pair_hap_similarity_deduplicate(uint64_t* readIDs, uint32_t Len, uint32_t target_uId, +ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, double* Match, double* Total) +{ + get_pair_hap_similarity(readIDs, Len, target_uId, reverse_sources, read_g, ruIndex, Match, Total); + return; + + #define CUTOFF_THRES 100 + uint32_t i, j, qn, tn, is_Unitig, uId, min_count = 0, max_count = 0, cutoff = 0, is_found; + for (i = 0; i < Len; i++) + { + if(cutoff > CUTOFF_THRES) + { + max_count = 0; + min_count = Len; + break; + } + qn = readIDs[i]>>33; + is_found = 0; + + for (j = 0; j < reverse_sources[qn].length; j++) + { + tn = Get_tn(reverse_sources[qn].buffer[j]); + if(read_g->seq[tn].del == 1) + { + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + + + get_R_to_U(ruIndex, tn, &uId, &is_Unitig); + if(uId!=(uint32_t)-1 && is_Unitig == 1 && uId == target_uId) + { + max_count++; + } + min_count++; + is_found = 1; + } + + //means there is a match + if(is_found) + { + cutoff = 0; + } + else + { + cutoff++; + } + } + + (*Match) = max_count; + (*Total) = min_count; +} +**/ + +inline void check_hap_match(uint32_t qn, uint32_t targetBeg, uint32_t targetEnd, uint32_t targetID, +uint64_t* position_index, ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, uint32_t* is_found, uint32_t* is_match) +{ + uint32_t j, tn, uId, is_Unitig, offset; + (*is_found) = (*is_match) = 0; + if(reverse_sources[qn].length > 0) (*is_found) = 1; + for (j = 0; j < reverse_sources[qn].length; j++) + { + tn = Get_tn(reverse_sources[qn].buffer[j]); + if(read_g->seq[tn].del == 1) + { + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + + + get_R_to_U(ruIndex, tn, &uId, &is_Unitig); + if(uId!=(uint32_t)-1 && is_Unitig == 1 && uId == targetID) + { + offset = (uint32_t)(position_index[tn]); + if(offset >= targetBeg && offset <= targetEnd) + { + (*is_match) = 1; + break; + } + } + } + +} + +/** +inline void check_hap_match_deduplicate(uint32_t qn, uint32_t targetBeg, uint32_t targetEnd, uint32_t targetID, +uint64_t* position_index, ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, uint32_t* is_found, uint32_t* is_match) +{ + check_hap_match(qn, targetBeg, targetEnd, targetID, position_index, reverse_sources, read_g, + ruIndex, is_found, is_match); + return; + + + uint32_t j, tn, uId, is_Unitig, offset; + (*is_found) = (*is_match) = 0; + + for (j = 0; j < reverse_sources[qn].length; j++) + { + tn = Get_tn(reverse_sources[qn].buffer[j]); + if(read_g->seq[tn].del == 1) + { + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[tn].del == 1) continue; + } + + + get_R_to_U(ruIndex, tn, &uId, &is_Unitig); + if(uId!=(uint32_t)-1 && is_Unitig == 1 && uId == targetID) + { + offset = (uint32_t)(position_index[tn]); + if(offset >= targetBeg && offset <= targetEnd) + { + (*is_match)++; + } + } + (*is_found)++; + } + +} +**/ + +void determin_hap_alignment_boundary_single_side(uint64_t* readIDs, long long queryLen, long long targetBeg, +long long targetEnd, long long targetID, long long eMatch, long long eTotal, long long dir, +float H_rate, int is_local, uint64_t* position_index, ma_hit_t_alloc* reverse_sources, asg_t *read_g, +R_to_U* ruIndex, uint32_t* n_matchLen, uint32_t* n_max_count, uint32_t* n_min_count) +{ + if(queryLen == 0) + { + (*n_matchLen) = (*n_min_count) = (*n_max_count) = 0; + return; + } + long long i, maxId, min_count = eTotal, max_count = eMatch, matchLen = 0; + long long rLen, score = 0, max_score = 0; + uint32_t is_found, is_match; + if(dir == 0) + { + for (i = 0, maxId = 0; i < queryLen; i++) + { + + check_hap_match(readIDs[i]>>33, targetBeg, targetEnd, targetID, position_index, reverse_sources, + read_g, ruIndex, &is_found, &is_match); + + min_count += is_found; + max_count += is_match; + if(max_count > min_count*H_rate) maxId = i; + + if(is_local && is_found) + { + rLen = read_g->seq[readIDs[i]>>33].len; + score += (is_match? rLen : (rLen*(-1))); + if(score >= max_score) max_score = score, maxId = i; + } + } + + for (i = maxId; i >= 0; i--) + { + check_hap_match(readIDs[i]>>33, targetBeg, targetEnd, targetID, position_index, reverse_sources, + read_g, ruIndex, &is_found, &is_match); + + ///if(is_found > 0 && is_match > 0 && is_match > is_found*Hap_rate) + if(is_found == 1 && is_match == 1) + { + break; + } + min_count -= is_found; + max_count -= is_match; + } + + matchLen = i+1; + } + else + { + for (i = queryLen - 1, maxId = queryLen - 1; i >= 0; i--) + { + check_hap_match(readIDs[i]>>33, targetBeg, targetEnd, targetID, position_index, reverse_sources, + read_g, ruIndex, &is_found, &is_match); + + min_count += is_found; + max_count += is_match; + if(max_count > min_count*H_rate) maxId = i; + + if(is_local && is_found) + { + rLen = read_g->seq[readIDs[i]>>33].len; + score += (is_match? rLen : (rLen*(-1))); + if(score >= max_score) max_score = score, maxId = i; + } + } + + for (i = maxId; i < queryLen; i++) + { + check_hap_match(readIDs[i]>>33, targetBeg, targetEnd, targetID, position_index, reverse_sources, + read_g, ruIndex, &is_found, &is_match); + + ///if(is_found > 0 && is_match > 0 && is_match > is_found*Hap_rate) + if(is_found == 1 && is_match == 1) + { + break; + } + min_count -= is_found; + max_count -= is_match; + } + + matchLen = queryLen - i; + } + + ///need to check if min_count == 0 + if(min_count == 0) + { + (*n_matchLen) = (*n_min_count) = (*n_max_count) = 0; + return; + } + + (*n_matchLen) = matchLen; + (*n_min_count) = min_count; + (*n_max_count) = max_count; +} + +inline void modify_target_interval(long long beg, long long end, long long len, +long long* target_beg, long long* target_end) +{ + #define TARGET_SGIFT 3 + beg -= TARGET_SGIFT; + end += TARGET_SGIFT; + if(beg < 0) beg = 0; + if(end >= len) end = len - 1; + (*target_beg) = beg; + (*target_end) = end; +} + + +void bi_direction_hap_alignment_extention(ma_utg_t* xReads, uint32_t xLeftBeg, uint32_t xLeftLen, +uint32_t xRightBeg, uint32_t xRightLen, uint32_t targetUid, uint32_t target_beg, uint32_t target_end, +float Hap_rate, int is_local, uint64_t* position_index, ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, +uint32_t rev, long long* x_interval_beg, long long* x_interval_end) +{ + if(rev) + { + uint32_t k; + k = xLeftBeg; xLeftBeg = xRightBeg; xRightBeg = k; + k = xLeftLen; xLeftLen = xRightLen; xRightLen = k; + } + uint32_t n_matchLenLeft, x_max_countLeft, x_min_countLeft; + uint32_t n_matchLenRight, x_max_countRight, x_min_countRight; + n_matchLenLeft = x_max_countLeft = x_min_countLeft = 0; + determin_hap_alignment_boundary_single_side(xReads->a+xLeftBeg, xLeftLen, + target_beg, target_end, targetUid, x_max_countLeft, x_min_countLeft, 1, Hap_rate, is_local, + position_index, reverse_sources, read_g, ruIndex, &n_matchLenLeft, &x_max_countLeft, + &x_min_countLeft); + + n_matchLenRight = x_max_countRight = x_min_countRight = 0; + determin_hap_alignment_boundary_single_side(xReads->a+xRightBeg, xRightLen, + target_beg, target_end, targetUid, x_max_countRight, x_min_countRight, 0, Hap_rate, is_local, + position_index, reverse_sources, read_g, ruIndex, &n_matchLenRight, &x_max_countRight, + &x_min_countRight); + + if(x_max_countLeft >= x_max_countRight) + { + determin_hap_alignment_boundary_single_side(xReads->a+xRightBeg, xRightLen, + target_beg, target_end, targetUid, x_max_countLeft, x_min_countLeft, 0, Hap_rate, is_local, + position_index, reverse_sources, read_g, ruIndex, &n_matchLenRight, &x_max_countRight, + &x_min_countRight); + } + else + { + determin_hap_alignment_boundary_single_side(xReads->a+xLeftBeg, xLeftLen, + target_beg, target_end, targetUid, x_max_countRight, x_min_countRight, 1, Hap_rate, is_local, + position_index, reverse_sources, read_g, ruIndex, &n_matchLenLeft, &x_max_countLeft, + &x_min_countLeft); + } + + (*x_interval_beg) = xLeftBeg + xLeftLen; (*x_interval_beg) -= n_matchLenLeft; + (*x_interval_end) = xRightBeg + n_matchLenRight; (*x_interval_end) -= 1; +} + +void get_hap_alignment_boundary(ma_utg_t* xReads, ma_utg_t* yReads, uint32_t type, +uint32_t xLeftMatch, uint32_t xLeftTotal, uint32_t yLeftMatch, uint32_t yLeftTotal, +uint32_t xRightMatch, uint32_t xRightTotal, uint32_t yRightMatch, uint32_t yRightTotal, +uint32_t xLeftBeg, uint32_t xLeftLen, uint32_t yLeftBeg, uint32_t yLeftLen, +uint32_t xRightBeg, uint32_t xRightLen, uint32_t yRightBeg, uint32_t yRightLen, +uint32_t xUid, uint32_t yUid, float Hap_rate, int is_local, uint64_t* position_index, +ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, uint32_t rev, +long long* r_x_interval_beg, long long* r_x_interval_end, +long long* r_y_interval_beg, long long* r_y_interval_end) +{ + + uint32_t x_max_count, x_min_count, y_max_count, y_min_count, n_matchLen; + long long x_interval_beg, x_interval_end, y_interval_beg, y_interval_end; + long long target_beg, target_end; + x_max_count = x_min_count = y_max_count = y_min_count = 0; + if(type == X2Y) + { + /********************x*********************/ + x_max_count = xRightMatch; + x_min_count = xRightTotal; + + modify_target_interval(yLeftBeg, yLeftBeg+yLeftLen-1, yReads->n, &target_beg, &target_end); + determin_hap_alignment_boundary_single_side(xReads->a+xLeftBeg, xLeftLen, + /**yLeftBeg, yLeftBeg+yLeftLen-1,**/ target_beg, target_end, yUid, + x_max_count, x_min_count, 1, Hap_rate, is_local, position_index, reverse_sources, + read_g, ruIndex, &n_matchLen, &x_max_count, &x_min_count); + + x_interval_beg = xLeftBeg + xLeftLen; x_interval_beg -= n_matchLen; + x_interval_end = xRightBeg + xRightLen; x_interval_end -= 1; + /********************x*********************/ + + /********************y*********************/ + y_max_count = yLeftMatch; + y_min_count = yLeftTotal; + modify_target_interval(xRightBeg, xRightBeg+xRightLen-1, xReads->n, &target_beg, &target_end); + determin_hap_alignment_boundary_single_side(yReads->a+yRightBeg, yRightLen, + /**xRightBeg, xRightBeg+xRightLen-1,**/ target_beg, target_end, xUid, + y_max_count, y_min_count, rev, Hap_rate, is_local, position_index, reverse_sources, + read_g, ruIndex, &n_matchLen, &y_max_count, &y_min_count); + if(rev == 0) + { + y_interval_beg = yLeftBeg; + y_interval_end = yRightBeg + n_matchLen; y_interval_end -= 1; + } + else + { + y_interval_beg = yRightBeg + yRightLen; y_interval_beg -= n_matchLen; + y_interval_end = yLeftBeg + yLeftLen; y_interval_end -= 1; + } + + /********************y*********************/ + } + else if(type == Y2X) + { + /********************x*********************/ + x_max_count = xLeftMatch; + x_min_count = xLeftTotal; + modify_target_interval(yRightBeg, yRightBeg+yRightLen-1, yReads->n, &target_beg, &target_end); + determin_hap_alignment_boundary_single_side(xReads->a+xRightBeg, xRightLen, + /**yRightBeg, yRightBeg+yRightLen-1,**/ target_beg, target_end, yUid, + x_max_count, x_min_count, 0, Hap_rate, is_local, position_index, reverse_sources, + read_g, ruIndex, &n_matchLen, &x_max_count, &x_min_count); + + x_interval_beg = xLeftBeg; + x_interval_end = xRightBeg + n_matchLen; x_interval_end -= 1; + /********************x*********************/ + + /********************y*********************/ + y_max_count = yRightMatch; + y_min_count = yRightTotal; + modify_target_interval(xLeftBeg, xLeftBeg+xLeftLen-1, xReads->n, &target_beg, &target_end); + determin_hap_alignment_boundary_single_side(yReads->a+yLeftBeg, yLeftLen, + /**xLeftBeg, xLeftBeg+xLeftLen-1,**/ target_beg, target_end, xUid, + y_max_count, y_min_count, 1-rev, Hap_rate, is_local, position_index, reverse_sources, + read_g, ruIndex, &n_matchLen, &y_max_count, &y_min_count); + if(rev == 0) + { + y_interval_beg = yLeftBeg + yLeftLen; y_interval_beg -= n_matchLen; + y_interval_end = yRightBeg + yRightLen; y_interval_end -= 1; + } + else + { + y_interval_beg = yRightBeg; + y_interval_end = yLeftBeg + n_matchLen; y_interval_end -= 1; + } + /********************y*********************/ + } + else if(type == XCY) + { + /********************x*********************/ + bi_direction_hap_alignment_extention(xReads, xLeftBeg, xLeftLen, xRightBeg, xRightLen, + yUid, 0, yReads->n - 1, Hap_rate, is_local, position_index, reverse_sources, read_g, ruIndex, 0, + &x_interval_beg, &x_interval_end); + /********************x*********************/ + + /********************y*********************/ + y_interval_beg = 0; + y_interval_end = yReads->n; y_interval_end -= 1; + /********************y*********************/ + } + else if(type == YCX) + { + /********************x*********************/ + x_interval_beg = 0; + x_interval_end = xReads->n; x_interval_end -= 1; + /********************x*********************/ + + /********************y*********************/ + bi_direction_hap_alignment_extention(yReads, yLeftBeg, yLeftLen, yRightBeg, yRightLen, + xUid, 0, xReads->n - 1, Hap_rate, is_local, position_index, reverse_sources, read_g, ruIndex, rev, + &y_interval_beg, &y_interval_end); + /********************y*********************/ + } else abort(); + + (*r_x_interval_beg) = x_interval_beg; + (*r_x_interval_end) = x_interval_end; + (*r_y_interval_beg) = y_interval_beg; + (*r_y_interval_end) = y_interval_end; +} + +uint32_t vote_overlap_type(kvec_asg_arc_t_offset* u_buffer, hap_candidates* hap_can, +uint64_t* position_index, ma_utg_t* xReads, ma_utg_t* yReads) +{ + uint32_t i, xBasePos, yBasePos; + asg_arc_t_offset* arch = NULL; + uint32_t flag[4]; + flag[X2Y] = flag[Y2X] = flag[XCY] = flag[YCX] = 0; + + + for (i = hap_can->index_beg; i <= hap_can->index_end; i++) + { + arch = &(u_buffer->a.a[i]); + xBasePos = (uint32_t)(arch->Off>>32); + yBasePos = (uint32_t)(arch->Off); + flag[classify_hap_overlap(xBasePos, xBasePos, xReads->len, yBasePos, yBasePos, yReads->len, + NULL, NULL, NULL, NULL)]++; + } + + uint32_t max_flag_i = 0; + for (i = 0; i < 4; i++) + { + if(i == max_flag_i) continue; + if(flag[i] > flag[max_flag_i]) + { + max_flag_i = i; + } + } + + return max_flag_i; +} + + +void get_base_boundary(R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, +asg_t *read_g, uint64_t* position_index, int max_hang, int min_ovlp, ma_utg_t *xReads, ma_utg_t *yReads, +uint32_t xUid, uint32_t yUid, long long xBegIndex, long long xEndIndex, long long yBegIndex, long long yEndIndex, +uint32_t dir, uint32_t rev, uint32_t* x_off, uint32_t* y_off) +{ + long long k, j, offset; + ma_hit_t_alloc *xR = NULL; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL, *st = NULL; + int32_t r; + asg_arc_t t; + uint32_t rId, Hap_uId, is_Unitig, v, w, v_dir, w_dir, is_found = 0, oLen = 0; + uint64_t tmp; + (*x_off) = (*y_off) = (uint32_t)-1; + if(dir == 1) + { + for (k = xEndIndex; k >= xBegIndex; k--) + { + xR = &(reverse_sources[xReads->a[k]>>33]); + is_found = 0; oLen = 0; + for (j = 0; j < xR->length; j++) + { + h = &(xR->buffer[j]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(st->del || read_g->seq[Get_tn(*h)].del) continue; + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + ///if it is a contained overlap, skip + if(r < 0) continue; + + rId = t.v>>1; + if(read_g->seq[rId].del == 1) continue; + ///there are two cases: + ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id + ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 + get_R_to_U(ruIndex, rId, &Hap_uId, &is_Unitig); + if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; + if(Hap_uId != yUid) continue; + + v = xReads->a[k]>>32; + get_R_to_U(ruIndex, v>>1, &Hap_uId, &is_Unitig); + if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; + if(Hap_uId != xUid) continue; + if((uint32_t)(position_index[v>>1]) != k) continue; + + w = (yReads->a[(uint32_t)(position_index[rId])])>>32; + + v_dir = ((t.ul>>32)==v)?1:0; + w_dir = (t.v == w)?1:0; + if(rev == 0 && v_dir != w_dir) continue; + if(rev == 1 && v_dir == w_dir) continue; + + /****************************may have bugs********************************/ + offset = (uint32_t)(position_index[rId]); + if(offset < yBegIndex || offset > yEndIndex) continue; + /****************************may have bugs********************************/ + + tmp = get_xy_pos(read_g, &t, v, w, xReads->len, yReads->len, position_index, &(t.el)); + if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue; + + ///if(is_found == 0 || ((uint32_t)(tmp>>32) > (*x_off) && ((uint32_t)tmp) > (*y_off))) + if(is_found == 0 || t.ol > oLen) + { + (*x_off) = tmp>>32; + (*y_off) = (uint32_t)tmp; + oLen = t.ol; + } + + is_found = 1; + } + if(is_found) return; + } + } + else + { + for (k = xBegIndex; k <= xEndIndex; k++) + { + xR = &(reverse_sources[xReads->a[k]>>33]); + is_found = 0; oLen = 0; + for (j = 0; j < xR->length; j++) + { + h = &(xR->buffer[j]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(st->del || read_g->seq[Get_tn(*h)].del) continue; + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + ///if it is a contained overlap, skip + if(r < 0) continue; + + rId = t.v>>1; + if(read_g->seq[rId].del == 1) continue; + ///there are two cases: + ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id + ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 + get_R_to_U(ruIndex, rId, &Hap_uId, &is_Unitig); + if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; + if(Hap_uId != yUid) continue; + + v = xReads->a[k]>>32; + get_R_to_U(ruIndex, v>>1, &Hap_uId, &is_Unitig); + if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; + if(Hap_uId != xUid) continue; + if((uint32_t)(position_index[v>>1]) != k) continue; + + w = (yReads->a[(uint32_t)(position_index[rId])])>>32; + + v_dir = ((t.ul>>32)==v)?1:0; + w_dir = (t.v == w)?1:0; + if(rev == 0 && v_dir != w_dir) continue; + if(rev == 1 && v_dir == w_dir) continue; + + /****************************may have bugs********************************/ + offset = (uint32_t)(position_index[rId]); + if(offset < yBegIndex || offset > yEndIndex) continue; + /****************************may have bugs********************************/ + + tmp = get_xy_pos(read_g, &t, v, w, xReads->len, yReads->len, position_index, &(t.el)); + if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue; + + ///if(is_found == 0 || ((uint32_t)(tmp>>32) < (*x_off) && ((uint32_t)tmp) < (*y_off))) + if(is_found == 0 || t.ol > oLen) + { + (*x_off) = tmp>>32; + (*y_off) = (uint32_t)tmp; + oLen = t.ol; + } + + is_found = 1; + } + if(is_found) return; + } + } + + + (*x_off) = (*y_off) = (uint32_t)-1; + +} + +void print_asg_arc_t_offset(asg_arc_t_offset* x, long long n, const char* info) +{ + fprintf(stderr,"\n\n(%s)n: %lld\n", info, n); + long long i, x_off, y_off; + for (i = 0; i < n; i++) + { + x_off = (long long)(x[i].Off>>32); + y_off = (long long)((uint32_t)x[i].Off); + fprintf(stderr, "i: %lld, x_off: %lld, y_off: %lld, weight: %lu, rev: %u, ol: %u\n", + i, x_off, y_off, (unsigned long)x[i].weight, x[i].x.el, x[i].x.ol); + } +} + + +// Binary search +inline int GetCeilIndex(asg_arc_t_offset* arr, kvec_t_i32_warp* T, int l, int r, uint32_t key) +{ + while (r - l > 1) { + int m = l + (r - l) / 2; + if (Get_yOff(arr[T->a.a[m]].Off) >= key) + r = m; + else + l = m; + } + + return r; +} + + +void quick_LIS(asg_arc_t_offset* x, uint32_t n, kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* prevIndex) +{ + tailIndex->a.n = prevIndex->a.n = 0; + if(n == 0) return; + + kv_resize(int32_t, tailIndex->a, n); + kv_resize(int32_t, prevIndex->a, n); + + long long len = 1, i, pos, m; ///the length of chain must be >=1 + tailIndex->a.a[0] = 0; + prevIndex->a.a[0] = -1; + + ///x has already sorted by x_pos + for(i = 1; i < (long long)n; i++) + { + if(Get_yOff(x[i].Off) < Get_yOff(x[tailIndex->a.a[0]].Off)) + { + // new smallest value + tailIndex->a.a[0] = i; ///doesn't matter too much + } + else if(Get_yOff(x[i].Off) > Get_yOff(x[tailIndex->a.a[len - 1]].Off)) + { + // arr[i] wants to extend largest subsequence + prevIndex->a.a[i] = tailIndex->a.a[len - 1]; + tailIndex->a.a[len++] = i; + } + else + { + // arr[i] wants to be a potential condidate of + // future subsequence + // It will replace ceil value in tailIndices + pos = GetCeilIndex(x, tailIndex, -1, len - 1, Get_yOff(x[i].Off)); + prevIndex->a.a[i] = pos > 0? tailIndex->a.a[pos - 1] : -1; + tailIndex->a.a[pos] = i; + } + } + + + for (m = 0, i = tailIndex->a.a[len - 1]; m < len; i = prevIndex->a.a[i], m++) + { + tailIndex->a.a[len-m-1] = i; + } + + tailIndex->a.n = len; +} + +uint64_t get_xy_pos_by_pos(asg_t *read_g, asg_arc_t* t, uint32_t v_in_unitig, uint32_t w_in_unitig, +uint32_t v_in_pos, uint32_t w_in_pos, uint32_t xUnitigLen, uint32_t yUnitigLen, uint8_t* rev) +{ + uint32_t x_pos, y_pos, x_dir = 0, y_dir = 0; + uint64_t tmp; + x_pos = y_pos = (uint32_t)-1; + if((t->ul>>32)==v_in_unitig)///end pos + { + x_pos = v_in_pos + read_g->seq[v_in_unitig>>1].len - 1; + x_dir = 0; + } + else if((t->ul>>32)==(v_in_unitig^1))///start pos + { + x_pos = v_in_pos; + x_dir = 1; + } + else + { + fprintf(stderr, "ERROR\n"); + } + + if(t->v == w_in_unitig) + { + y_pos = w_in_pos + t->ol - 1; + y_dir = 0; + } + else if(t->v == (w_in_unitig^1)) + { + y_pos = w_in_pos + read_g->seq[w_in_unitig>>1].len - t->ol; + y_dir = 1; + } + else + { + fprintf(stderr, "ERROR\n"); + } + + (*rev) = x_dir^y_dir; + if((*rev)) + { + if(yUnitigLen <= y_pos) + { + y_pos = (uint32_t)-1; + } + else + { + y_pos = yUnitigLen - y_pos - 1; + } + } + + if(x_pos>=xUnitigLen) x_pos = (uint32_t)-1; + if(y_pos>=yUnitigLen) y_pos = (uint32_t)-1; + + tmp = x_pos; tmp = tmp << 32; tmp = tmp | y_pos; + return tmp; +} + +void chain_trans_ovlp(hap_cov_t *cover, utg_trans_t *o, ma_ug_t *ug, asg_t *read_sg, buf_t* xReads, uint32_t targetBaseLen, uint32_t* xEnd) +{ + ma_hit_t_alloc* reverse_sources = (o? o->reverse_sources:cover->reverse_sources); + ma_sub_t *coverage_cut = (o? o->coverage_cut:cover->coverage_cut); + int max_hang = (o? o->max_hang:cover->max_hang); + int min_ovlp = (o? o->min_ovlp:cover->min_ovlp); + kvec_asg_arc_t_offset* u_buffer = (o? &(o->u_buffer):&(cover->u_buffer)); + kvec_t_i32_warp* tailIndex = (o? &(o->tailIndex):&(cover->tailIndex)); + kvec_t_i32_warp* prevIndex = (o? &(o->prevIndex):&(cover->prevIndex)); + uint64_t *pos_idx = (o? o->pos_idx:cover->pos_idx); + ma_hit_t_alloc *xR = NULL; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL, *st = NULL; + int32_t r; + asg_arc_t t; + uint32_t rId, v, w; + uint64_t tmp; + asg_arc_t_offset t_offset; + u_buffer->a.n = 0; + ///(*xEnd) = (uint32_t)-1; + (*xEnd) = 0; + uint32_t u_i, r_i, k, j, len, p_v, *a = xReads->b.a, uid, ori, l, m, aOcc, nv, xOcc = (uint32_t)-1; + ma_utg_t* u = NULL; + asg_arc_t *av = NULL; + + + for (u_i = r_i = len = aOcc = 0, xOcc = (uint32_t)-1, p_v = (uint32_t)-1; u_i < xReads->b.n; u_i++) + { + uid = a[u_i] >> 1; + ori = a[u_i] & 1; + u = &(ug->u.a[uid]); + if(u->n == 0) continue; + + for (r_i = 0; r_i < u->n; r_i++, aOcc++) + { + l = 0; + v = (ori == 1?((uint64_t)((u->a[u->n - r_i - 1])^(uint64_t)(0x100000000)))>>32:((uint64_t)(u->a[r_i]))>>32); + + if(p_v != (uint32_t)-1) + { + av = asg_arc_a(read_sg, p_v); + nv = asg_arc_n(read_sg, p_v); + + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == v) + { + l = asg_arc_len(av[k]); + break; + } + } + if(k == nv) fprintf(stderr, "ERROR\n"); + } + + p_v = v; len += l; + if(len >= targetBaseLen)///might be not right for centromeres + { + xOcc = aOcc; + break; + } + } + + if(xOcc != (uint32_t)-1) break; + } + if(xOcc == (uint32_t)-1) xOcc = aOcc; + if(xOcc == 0) xOcc = 1; + + + + for (u_i = r_i = len = aOcc = 0, p_v = (uint32_t)-1; u_i < xReads->b.n; u_i++) + { + uid = a[u_i] >> 1; + ori = a[u_i] & 1; + u = &(ug->u.a[uid]); + if(u->n == 0) continue; + + for (r_i = 0; r_i < u->n; r_i++, aOcc++) + { + if(aOcc >= xOcc) break; + l = 0; + v = (ori == 1?((uint64_t)((u->a[u->n - r_i - 1])^(uint64_t)(0x100000000)))>>32:((uint64_t)(u->a[r_i]))>>32); + + if(p_v != (uint32_t)-1) + { + av = asg_arc_a(read_sg, p_v); + nv = asg_arc_n(read_sg, p_v); + + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == v) + { + l = asg_arc_len(av[k]); + break; + } + } + if(k == nv) fprintf(stderr, "ERROR\n"); + } + + p_v = v; len += l; + + xR = &(reverse_sources[v>>1]); + for (j = 0; j < xR->length; j++) + { + h = &(xR->buffer[j]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(st->del || read_sg->seq[Get_tn(*h)].del) continue; + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + ///if it is a contained overlap, skip + if(r < 0) continue; + + rId = t.v>>1; + if(read_sg->seq[rId].del == 1) continue; + if(pos_idx[rId] == (uint64_t)-1) continue; + w = (uint32_t)(pos_idx[rId]); + if(rId != (w>>1)) continue; + + tmp = get_xy_pos_by_pos(read_sg, &t, v, w, len, pos_idx[w>>1]>>32, + (uint32_t)-1, targetBaseLen, &(t.el)); + if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue; + if(t.el) continue; ///must + + t_offset.Off = tmp; + t_offset.x = t; + t_offset.weight = 1; + kv_push(asg_arc_t_offset, u_buffer->a, t_offset); + } + } + + if(aOcc >= xOcc) break; + } + + if(u_buffer->a.n == 0) return; + + qsort(u_buffer->a.a, u_buffer->a.n, sizeof(asg_arc_t_offset), cmp_hap_alignment_chaining); + + ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n, "before"); + + + for (k = 1, l = 0, m = 0; k <= u_buffer->a.n; ++k) + { + if (k == u_buffer->a.n || u_buffer->a.a[k].x.el != u_buffer->a.a[l].x.el || + u_buffer->a.a[k].Off != u_buffer->a.a[l].Off) + { + u_buffer->a.a[m] = u_buffer->a.a[l]; + for (l += 1; l < k; l++) + { + u_buffer->a.a[m].weight += u_buffer->a.a[l].weight; + if(u_buffer->a.a[l].x.ol > u_buffer->a.a[m].x.ol) + { + u_buffer->a.a[m].x = u_buffer->a.a[l].x; + } + } + l = k; + m++; + } + } + u_buffer->a.n = m; + + ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n, "after"); + quick_LIS(u_buffer->a.a, u_buffer->a.n, tailIndex, prevIndex); + if(tailIndex->a.n == 0) return; + + + uint32_t xLen_thres = (uint32_t)-1; + asg_arc_t_offset* best = &(u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]]); + for (u_i = r_i = len = aOcc = 0, p_v = (uint32_t)-1; u_i < xReads->b.n; u_i++) + { + uid = a[u_i] >> 1; + ori = a[u_i] & 1; + u = &(ug->u.a[uid]); + if(u->n == 0) continue; + + for (r_i = 0; r_i < u->n; r_i++, aOcc++) + { + l = 0; + v = (ori == 1?((uint64_t)((u->a[u->n - r_i - 1])^(uint64_t)(0x100000000)))>>32:((uint64_t)(u->a[r_i]))>>32); + + if(p_v != (uint32_t)-1) + { + av = asg_arc_a(read_sg, p_v); + nv = asg_arc_n(read_sg, p_v); + + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == v) + { + l = asg_arc_len(av[k]); + break; + } + } + if(k == nv) fprintf(stderr, "ERROR\n"); + } + + p_v = v; len += l; + + if((v>>1) == (best->x.ul>>33) && xLen_thres == (uint32_t)-1) + { + ///cov->pos_idx[v>>1] = len; + xR = &(reverse_sources[v>>1]); + for (j = 0; j < xR->length; j++) + { + h = &(xR->buffer[j]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(st->del || read_sg->seq[Get_tn(*h)].del) continue; + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + ///if it is a contained overlap, skip + if(r < 0) continue; + + rId = t.v>>1; + if(read_sg->seq[rId].del == 1) continue; + if(pos_idx[rId] == (uint64_t)-1) continue; + w = (uint32_t)(pos_idx[rId]); + if(rId != (w>>1)) continue; + + tmp = get_xy_pos_by_pos(read_sg, &t, v, w, len, pos_idx[w>>1]>>32, + (uint32_t)-1, targetBaseLen, &(t.el)); + if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue; + if(t.el) continue; ///must + + t_offset.Off = tmp; + t_offset.x = t; + t_offset.weight = 1; + if(t_offset.Off == best->Off && t_offset.x.v == best->x.v && t_offset.x.ul == best->x.ul) + { + xLen_thres = Get_xOff(best->Off) + targetBaseLen - Get_yOff(best->Off); + } + } + } + + if(len >= xLen_thres) + { + (*xEnd) = aOcc; + return; + } + } + } + + (*xEnd) = aOcc; +} + + +void get_base_boundary_advance_back(R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, +asg_t *read_g, uint64_t* position_index, int max_hang, int min_ovlp, ma_utg_t *xReads, ma_utg_t *yReads, +uint32_t xUid, uint32_t yUid, long long xBegIndex, long long xEndIndex, long long yBegIndex, long long yEndIndex, +uint32_t rev, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* prevIndex, +uint32_t* xBeg, uint32_t* xEnd, uint32_t* yBeg, uint32_t* yEnd) +{ + long long k, j, offset, m; + ma_hit_t_alloc *xR = NULL; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL, *st = NULL; + int32_t r; + asg_arc_t t; + uint32_t rId, Hap_uId, is_Unitig, v, w, v_dir, w_dir; + uint64_t tmp; + asg_arc_t_offset t_offset; + u_buffer->a.n = 0; + (*xBeg) = (*xEnd) = (*yBeg) = (*yEnd) = (uint32_t)-1; + for (k = xBegIndex; k <= xEndIndex; k++) + { + xR = &(reverse_sources[xReads->a[k]>>33]); + for (j = 0; j < xR->length; j++) + { + h = &(xR->buffer[j]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(st->del || read_g->seq[Get_tn(*h)].del) continue; + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + ///if it is a contained overlap, skip + if(r < 0) continue; + + rId = t.v>>1; + if(read_g->seq[rId].del == 1) continue; + ///there are two cases: + ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id + ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 + get_R_to_U(ruIndex, rId, &Hap_uId, &is_Unitig); + if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; + if(Hap_uId != yUid) continue; + + v = xReads->a[k]>>32; + get_R_to_U(ruIndex, v>>1, &Hap_uId, &is_Unitig); + if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; + if(Hap_uId != xUid) continue; + if((uint32_t)(position_index[v>>1]) != k) continue; + + w = (yReads->a[(uint32_t)(position_index[rId])])>>32; + + v_dir = ((t.ul>>32)==v)?1:0; + w_dir = (t.v == w)?1:0; + if(rev == 0 && v_dir != w_dir) continue; + if(rev == 1 && v_dir == w_dir) continue; + + /****************************may have bugs********************************/ + offset = (uint32_t)(position_index[rId]); + if(offset < yBegIndex || offset > yEndIndex) continue; + /****************************may have bugs********************************/ + + tmp = get_xy_pos(read_g, &t, v, w, xReads->len, yReads->len, position_index, &(t.el)); + if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue; + + t_offset.Off = tmp; + t_offset.x = t; + t_offset.weight = 1; + kv_push(asg_arc_t_offset, u_buffer->a, t_offset); + } + } + if(u_buffer->a.n == 0) return; + + qsort(u_buffer->a.a, u_buffer->a.n, sizeof(asg_arc_t_offset), cmp_hap_alignment_chaining); + + ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n, "before"); + + for (k = 1, m = 1; k < (long long)u_buffer->a.n; k++) + { + if(u_buffer->a.a[m-1].Off == u_buffer->a.a[k].Off) + { + u_buffer->a.a[m-1].weight += u_buffer->a.a[k].weight; + if(u_buffer->a.a[k].x.ol > u_buffer->a.a[m-1].x.ol) + { + u_buffer->a.a[m-1].x = u_buffer->a.a[k].x; + } + continue; + } + u_buffer->a.a[m] = u_buffer->a.a[k]; + m++; + } + u_buffer->a.n = m; + + ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n, "after"); + quick_LIS(u_buffer->a.a, u_buffer->a.n, tailIndex, prevIndex); + + if(tailIndex->a.n == 0) return; + + (*xBeg) = Get_xOff(u_buffer->a.a[tailIndex->a.a[0]].Off); + (*yBeg) = Get_yOff(u_buffer->a.a[tailIndex->a.a[0]].Off); + (*xEnd) = Get_xOff(u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].Off); + (*yEnd) = Get_yOff(u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].Off); +} + +uint32_t determine_hap_overlap_type_advance_back(hap_candidates* hap_can, ma_utg_t *xReads, ma_utg_t *yReads, +R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, asg_t *read_g, uint64_t* position_index, +int max_hang, int min_ovlp, uint32_t xUid, uint32_t yUid, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, +kvec_t_i32_warp* prevIndex, long long* r_x_pos_beg, long long* r_x_pos_end, long long* r_y_pos_beg, long long* r_y_pos_end) +{ + uint32_t x_pos_beg, y_pos_beg, x_pos_end, y_pos_end; + /*************************x***************************/ + get_base_boundary_advance_back(ruIndex, reverse_sources, coverage_cut, read_g, position_index, + max_hang, min_ovlp, xReads, yReads, xUid, yUid, Get_x_beg(*hap_can), Get_x_end(*hap_can), + Get_y_beg(*hap_can), Get_y_end(*hap_can), Get_rev(*hap_can), u_buffer, tailIndex, prevIndex, + &x_pos_beg, &x_pos_end, &y_pos_beg, &y_pos_end); + /*************************x***************************/ + + if(x_pos_beg == (uint32_t)-1 || y_pos_beg == (uint32_t)-1 + || x_pos_end == (uint32_t)-1 || y_pos_end == (uint32_t)-1) + { + return (uint32_t)-1; + } + if(x_pos_beg > x_pos_end || y_pos_beg > y_pos_end) return (uint32_t)-1; + + /** + #define X2Y 0 + #define Y2X 1 + #define XCY 2 + #define YCX 3 + **/ + return classify_hap_overlap(x_pos_beg, x_pos_end, xReads->len, y_pos_beg, y_pos_end, yReads->len, + r_x_pos_beg, r_x_pos_end, r_y_pos_beg, r_y_pos_end); +} + +void get_idx_by_base(ma_utg_t *x, asg_t *read_g, long long beg_base, long long end_base, + long long* beg_idx, long long* end_idx) +{ + long long offset, r_beg, r_end; + uint64_t i, rId; + (*beg_idx) = (*end_idx) = -1; + for (i = 0, offset = 0; i < x->n; i++) + { + rId = x->a[i]>>33; + r_beg = offset; r_end = offset + (long long)(read_g->seq[rId].len) - 1; + offset += (uint32_t)x->a[i]; + if(beg_base > r_end || r_beg > end_base) + { + if((*beg_idx) != -1 && (*end_idx) != -1) break; + continue; + } + if((*beg_idx) == -1) (*beg_idx) = i; + (*end_idx) = i; + } +} + +int get_base_boundary_chain(R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, +asg_t *read_g, uint64_t* position_index, int max_hang, int min_ovlp, ma_utg_t *xReads, ma_utg_t *yReads, +uint32_t xUid, uint32_t yUid, long long xBegIndex, long long xEndIndex, long long yBegIndex, long long yEndIndex, +uint32_t rev, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* prevIndex) +{ + long long k, j, l, offset, m; + ma_hit_t_alloc *xR = NULL; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL, *st = NULL; + int32_t r; + asg_arc_t t; + uint32_t rId, Hap_uId, is_Unitig, v, w, v_dir, w_dir; + uint64_t tmp; + asg_arc_t_offset t_offset; + u_buffer->a.n = 0; + for (k = xBegIndex; k <= xEndIndex; k++) + { + xR = &(reverse_sources[xReads->a[k]>>33]); + for (j = 0; j < xR->length; j++) + { + h = &(xR->buffer[j]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(st->del || read_g->seq[Get_tn(*h)].del) continue; + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + ///if it is a contained overlap, skip + if(r < 0) continue; + + rId = t.v>>1; + if(read_g->seq[rId].del == 1) continue; + ///there are two cases: + ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id + ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 + get_R_to_U(ruIndex, rId, &Hap_uId, &is_Unitig); + if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; + if(Hap_uId != yUid) continue; + + v = xReads->a[k]>>32; + get_R_to_U(ruIndex, v>>1, &Hap_uId, &is_Unitig); + if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; + if(Hap_uId != xUid) continue; + if((uint32_t)(position_index[v>>1]) != k) continue; + + w = (yReads->a[(uint32_t)(position_index[rId])])>>32; + + v_dir = ((t.ul>>32)==v)?1:0; + w_dir = (t.v == w)?1:0; + if(rev == 0 && v_dir != w_dir) continue; + if(rev == 1 && v_dir == w_dir) continue; + + /****************************may have bugs********************************/ + offset = (uint32_t)(position_index[rId]); + if(offset < yBegIndex || offset > yEndIndex) continue; + /****************************may have bugs********************************/ + + tmp = get_xy_pos(read_g, &t, v, w, xReads->len, yReads->len, position_index, &(t.el)); + if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue; + + t_offset.Off = tmp; + t_offset.x = t; + t_offset.weight = 1; + kv_push(asg_arc_t_offset, u_buffer->a, t_offset); + } + } + if(u_buffer->a.n == 0) return 0; + + qsort(u_buffer->a.a, u_buffer->a.n, sizeof(asg_arc_t_offset), cmp_hap_alignment_chaining); + + ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n, "before"); + for (k = 1, l = 0, m = 0; k <= (long long)u_buffer->a.n; ++k) + { + if (k == (long long)u_buffer->a.n || u_buffer->a.a[k].Off != u_buffer->a.a[l].Off) + { + u_buffer->a.a[m] = u_buffer->a.a[l]; + for (l += 1; l < k; l++) + { + u_buffer->a.a[m].weight += u_buffer->a.a[l].weight; + if(u_buffer->a.a[l].x.ol > u_buffer->a.a[m].x.ol) + { + u_buffer->a.a[m].x = u_buffer->a.a[l].x; + } + } + l = k; + m++; + } + } + u_buffer->a.n = m; + + ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n, "after"); + quick_LIS(u_buffer->a.a, u_buffer->a.n, tailIndex, prevIndex); + + if(tailIndex->a.n == 0) return 0; + return 1; +} + + +void get_base_boundary_advance(R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, +asg_t *read_g, uint64_t* position_index, int max_hang, int min_ovlp, ma_utg_t *xReads, ma_utg_t *yReads, +uint32_t xUid, uint32_t yUid, long long xBegIndex, long long xEndIndex, long long yBegIndex, long long yEndIndex, +uint32_t rev, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* prevIndex, +uint32_t* xBeg, uint32_t* xEnd, uint32_t* yBeg, uint32_t* yEnd) +{ + long long offset; + long long new_xBeg, new_yBeg, new_xEnd, new_yEnd; + long long new_xIdxBeg, new_yIdxBeg, new_xIdxEnd, new_yIdxEnd; + + (*xBeg) = (*xEnd) = (*yBeg) = (*yEnd) = (uint32_t)-1; + if(!get_base_boundary_chain(ruIndex, reverse_sources, coverage_cut, read_g, position_index, + max_hang, min_ovlp, xReads, yReads, xUid, yUid, xBegIndex, xEndIndex, yBegIndex, yEndIndex, + rev, u_buffer, tailIndex, prevIndex)) + { + return; + } + ///base + new_xBeg = Get_xOff(u_buffer->a.a[tailIndex->a.a[0]].Off); + new_yBeg = Get_yOff(u_buffer->a.a[tailIndex->a.a[0]].Off); + new_xEnd = Get_xOff(u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].Off); + new_yEnd = Get_yOff(u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].Off); + + if(new_xBeg > new_xEnd || new_yBeg > new_yEnd) return; + + classify_hap_overlap(new_xBeg, new_xEnd, xReads->len, new_yBeg, new_yEnd, yReads->len, + &new_xBeg, &new_xEnd, &new_yBeg, &new_yEnd); + + if(rev) + { + new_yBeg = yReads->len - new_yBeg - 1; + new_yEnd = yReads->len - new_yEnd - 1; + offset = new_yBeg; new_yBeg = new_yEnd; new_yEnd = offset; + } + ///idx + get_idx_by_base(xReads, read_g, new_xBeg, new_xEnd, &new_xIdxBeg, &new_xIdxEnd); + get_idx_by_base(yReads, read_g, new_yBeg, new_yEnd, &new_yIdxBeg, &new_yIdxEnd); + if(new_xIdxBeg == -1 || new_xIdxEnd == -1 || new_yIdxBeg == -1 || new_yIdxEnd == -1) return; + + if(!get_base_boundary_chain(ruIndex, reverse_sources, coverage_cut, read_g, position_index, + max_hang, min_ovlp, xReads, yReads, xUid, yUid, new_xIdxBeg, new_xIdxEnd, new_yIdxBeg, + new_yIdxEnd, rev, u_buffer, tailIndex, prevIndex)) + { + return; + } + + (*xBeg) = Get_xOff(u_buffer->a.a[tailIndex->a.a[0]].Off); + (*yBeg) = Get_yOff(u_buffer->a.a[tailIndex->a.a[0]].Off); + (*xEnd) = Get_xOff(u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].Off); + (*yEnd) = Get_yOff(u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].Off); +} + +#define generic_key(x) (x) +KRADIX_SORT_INIT(i32, int32_t, generic_key, sizeof(int32_t)) +KRADIX_SORT_INIT(ru32, uint32_t, generic_key, sizeof(uint32_t)) + +long long get_chain_score(ma_utg_t *xReads, asg_t *read_g, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* idx, +ma_hit_t_alloc* reverse_sources, long long xBegPos, long long xEndPos) +{ + long long offset, r_beg, r_end, inp_beg, inp_end, hap_beg, hap_end, inp_match, hap_match, ovlp; + uint64_t i, k, rId; + idx->a.n = 0; + + for (i = k = 0; i < tailIndex->a.n; i++) + { + rId = u_buffer->a.a[tailIndex->a.a[i]].x.ul>>33; + + + for (; k < xReads->n; k++) + { + if(rId == (xReads->a[k]>>33)) break; + } + + if(k >= xReads->n) + { + for (k = 0; k < xReads->n; k++) + { + if(rId == (xReads->a[k]>>33)) break; + } + } + + if(k < xReads->n) kv_push(int32_t, idx->a, k); + else + { + fprintf(stderr, "\nERROR-get_chain_score: tailIndex->a.n: %lu, xReads->n: %lu\n", (uint64_t)tailIndex->a.n, (uint64_t)xReads->n); + } + } + + + radix_sort_i32(idx->a.a, idx->a.a + idx->a.n); + inp_beg = -1; inp_end = -2; + hap_beg = -1; hap_end = -2; + for (i = k = 0, offset = 0, inp_match = hap_match = 0; i < xReads->n; i++) + { + rId = xReads->a[i]>>33; + r_beg = offset; r_end = offset + (long long)(read_g->seq[rId].len) - 1; + offset += (uint32_t)xReads->a[i]; + + if(reverse_sources[rId].length > 0) + { + if(r_beg <= hap_end) + { + hap_end = MAX(hap_end, r_end); + } + else + { + ///match += (hap_end - hap_beg + 1); + ovlp = (long long)(MIN(hap_end, xEndPos)) - (long long)(MAX(hap_beg, xBegPos)) + 1; + hap_match += (ovlp >= 0? ovlp : 0); + hap_beg = r_beg; hap_end = r_end; + } + } + + for (; k < idx->a.n; k++) + { + if(i <= (uint64_t)idx->a.a[k]) break; + } + + if(k >= idx->a.n) continue; + + if(i == (uint64_t)idx->a.a[k]) + { + if(r_beg <= inp_end) + { + inp_end = MAX(inp_end, r_end); + } + else + { + ovlp = (long long)(MIN(inp_end, xEndPos)) - (long long)(MAX(inp_beg, xBegPos)) + 1; + inp_match += (ovlp >= 0? ovlp : 0); + inp_beg = r_beg; inp_end = r_end; + } + } + } + + ovlp = (long long)(MIN(inp_end, xEndPos)) - (long long)(MAX(inp_beg, xBegPos)) + 1; + inp_match += (ovlp >= 0? ovlp : 0); + + ovlp = (long long)(MIN(hap_end, xEndPos)) - (long long)(MAX(hap_beg, xBegPos)) + 1; + hap_match += (ovlp >= 0? ovlp : 0); + + // if(inp_match > (xEndPos - xBegPos + 1)) fprintf(stderr, "ERROR1\n"); + // if(hap_match > (xEndPos - xBegPos + 1)) fprintf(stderr, "ERRO2\n"); + // if(inp_match > hap_match) fprintf(stderr, "ERROR3\n"); + // fprintf(stderr, "tailIndex->a.n: %u, xReads->n: %u, total_match: %lld, hap_match: %lld, inp_match: %lld\n", + // tailIndex->a.n, xReads->n, (xEndPos - xBegPos + 1), hap_match, inp_match); + + return ((double)(inp_match)*CHAIN_MATCH) - ((double)(hap_match-inp_match)*CHAIN_UNMATCH); +} + + +uint32_t determine_hap_overlap_type_advance(hap_candidates* hap_can, ma_utg_t *xReads, ma_utg_t *yReads, +R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, asg_t *read_g, uint64_t* position_index, +int max_hang, int min_ovlp, uint32_t xUid, uint32_t yUid, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, +kvec_t_i32_warp* prevIndex, long long* r_x_pos_beg, long long* r_x_pos_end, long long* r_y_pos_beg, long long* r_y_pos_end) +{ + uint32_t x_pos_beg, y_pos_beg, x_pos_end, y_pos_end; + /*************************x***************************/ + get_base_boundary_advance(ruIndex, reverse_sources, coverage_cut, read_g, position_index, + max_hang, min_ovlp, xReads, yReads, xUid, yUid, Get_x_beg(*hap_can), Get_x_end(*hap_can), + Get_y_beg(*hap_can), Get_y_end(*hap_can), Get_rev(*hap_can), u_buffer, tailIndex, prevIndex, + &x_pos_beg, &x_pos_end, &y_pos_beg, &y_pos_end); + /*************************x***************************/ + if(x_pos_beg == (uint32_t)-1 || y_pos_beg == (uint32_t)-1 + || x_pos_end == (uint32_t)-1 || y_pos_end == (uint32_t)-1) + { + return (uint32_t)-1; + } + if(x_pos_beg > x_pos_end || y_pos_beg > y_pos_end) return (uint32_t)-1; + + /** + #define X2Y 0 + #define Y2X 1 + #define XCY 2 + #define YCX 3 + **/ + hap_can->index_end = classify_hap_overlap(x_pos_beg, x_pos_end, xReads->len, y_pos_beg, y_pos_end, yReads->len, + r_x_pos_beg, r_x_pos_end, r_y_pos_beg, r_y_pos_end); + hap_can->x_beg_pos = MIN((uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[0]].x.ul>>33]), + (uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].x.ul>>33])); + hap_can->x_end_pos = MAX((uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[0]].x.ul>>33]), + (uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].x.ul>>33])); + hap_can->y_beg_pos = MIN((uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[0]].x.v>>1]), + (uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].x.v>>1])); + hap_can->y_end_pos = MAX((uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[0]].x.v>>1]), + (uint32_t)(position_index[u_buffer->a.a[tailIndex->a.a[tailIndex->a.n-1]].x.v>>1])); + double xLeftMatch, xLeftTotal; + get_pair_hap_similarity(xReads->a + hap_can->x_beg_pos, hap_can->x_end_pos + 1 - hap_can->x_beg_pos, + yUid, reverse_sources, read_g, ruIndex, &xLeftMatch, &xLeftTotal); + if(xLeftMatch == 0 || xLeftTotal == 0) return (uint32_t)-1; + hap_can->weight = xLeftMatch; + hap_can->index_beg = xLeftTotal; + hap_can->score = get_chain_score(xReads, read_g, u_buffer, tailIndex, prevIndex, reverse_sources, + (*r_x_pos_beg), (*r_x_pos_end)); + if(hap_can->score <= 0) return (uint32_t)-1; + return hap_can->index_end; +} + + + +uint32_t determine_hap_overlap_type(hap_candidates* hap_can, ma_utg_t *xReads, ma_utg_t *yReads, +R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, asg_t *read_g, +uint64_t* position_index, int max_hang, int min_ovlp, uint32_t xUid, uint32_t yUid, +long long* r_x_pos_beg, long long* r_x_pos_end, long long* r_y_pos_beg, long long* r_y_pos_end) +{ + uint32_t x_pos_beg, y_pos_beg, x_pos_end, y_pos_end; + /*************************x***************************/ + get_base_boundary(ruIndex, reverse_sources, coverage_cut, read_g, position_index, max_hang, + min_ovlp, xReads, yReads, xUid, yUid, Get_x_beg(*hap_can), Get_x_end(*hap_can), + Get_y_beg(*hap_can), Get_y_end(*hap_can), 0, Get_rev(*hap_can), &x_pos_beg, &y_pos_beg); + + get_base_boundary(ruIndex, reverse_sources, coverage_cut, read_g, position_index, max_hang, + min_ovlp, xReads, yReads, xUid, yUid, Get_x_beg(*hap_can), Get_x_end(*hap_can), + Get_y_beg(*hap_can), Get_y_end(*hap_can), 1, Get_rev(*hap_can), &x_pos_end, &y_pos_end); + /*************************x***************************/ + + if(x_pos_beg == (uint32_t)-1 || y_pos_beg == (uint32_t)-1 + || x_pos_end == (uint32_t)-1 || y_pos_end == (uint32_t)-1) + { + return (uint32_t)-1; + } + if(x_pos_beg > x_pos_end || y_pos_beg > y_pos_end) return (uint32_t)-1; + + /** + #define X2Y 0 + #define Y2X 1 + #define XCY 2 + #define YCX 3 + **/ + return classify_hap_overlap(x_pos_beg, x_pos_end, xReads->len, y_pos_beg, y_pos_end, yReads->len, + r_x_pos_beg, r_x_pos_end, r_y_pos_beg, r_y_pos_end); +} + +void adjust_hap_overlaps_score(ma_utg_t* xReads, float *sim, long long *score, +long long xUid, long long yUid, long long xBeg, long long xEnd) +{ + uint64_t all, found; + if(count_unique_k_mers(xReads->s + xBeg, xEnd+1-xBeg, xUid, yUid, &all, &found)) + { + double k_w = 1; + if(sim) (*sim) = MAX((*sim), (all == 0?0:(((double)found)/((double)all)))); + if(all) k_w += ((double)(found)/(double)(all)); + if(score) (*score) = ((*score)*k_w)/2; + } +} + +uint32_t calculate_pair_hap_similarity_advance(hap_candidates* hap_can, +uint64_t* position_index, uint32_t xUid, uint32_t yUid, ma_utg_t* xReads, ma_utg_t* yReads, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, asg_t *read_g, R_to_U* ruIndex, ma_sub_t *coverage_cut, +float Hap_rate, int is_local, int max_hang, int min_ovlp, uint64_t cov_threshold, kvec_asg_arc_t_offset* u_buffer, +kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* prevIndex, hap_cov_t *cov, long long* r_x_pos_beg, long long* r_x_pos_end, +long long* r_y_pos_beg, long long* r_y_pos_end, float *sim) +{ + uint32_t max_count = 0, min_count = 0, flag; + uint32_t xLen = xReads->n, xIndex; + uint32_t yLen = yReads->n, yIndex; + uint32_t xLeftBeg, xLeftLen, yLeftBeg, yLeftLen; + uint32_t xRightBeg, xRightLen, yRightBeg, yRightLen; + double xLeftMatch = 0, xLeftTotal = 0, yLeftMatch = 0, yLeftTotal = 0; + double xRightMatch = 0, xRightTotal = 0, yRightMatch = 0, yRightTotal = 0; + asg_arc_t* arch = NULL; + + + arch = &(hap_can->t); + xIndex = (uint32_t)(position_index[arch->ul>>33]); + yIndex = (uint32_t)(position_index[arch->v>>1]); + + if(hap_can->rev == 0) + { + xLeftBeg = 0; xLeftLen = xIndex; xRightBeg = xIndex; xRightLen = xLen - xRightBeg; + yLeftBeg = 0; yLeftLen = yIndex; yRightBeg = yIndex; yRightLen = yLen - yRightBeg; + } + else + { + xLeftBeg = 0; xLeftLen = xIndex; xRightBeg = xIndex; xRightLen = xLen - xRightBeg; + + yLeftBeg = yIndex + 1; yLeftLen = yLen - yLeftBeg; + yRightBeg = 0; yRightLen = yIndex + 1; + } + + flag = Get_type(*hap_can); + + + if(flag == XCY) + { + get_pair_hap_similarity(yReads->a, yLen, xUid, reverse_sources, read_g, ruIndex, + &yLeftMatch, &yLeftTotal); + max_count = yLeftMatch; + min_count = yLeftTotal; + } + else if(flag == YCX) + { + get_pair_hap_similarity(xReads->a, xLen, yUid, reverse_sources, read_g, ruIndex, + &xLeftMatch, &xLeftTotal); + max_count = xLeftMatch; + min_count = xLeftTotal; + } + else if(flag == X2Y) + { + get_pair_hap_similarity(yReads->a+yLeftBeg, yLeftLen, xUid, reverse_sources, read_g, ruIndex, + &yLeftMatch, &yLeftTotal); + get_pair_hap_similarity(xReads->a+xRightBeg, xRightLen, yUid, reverse_sources, read_g, ruIndex, + &xRightMatch, &xRightTotal); + max_count = yLeftMatch + xRightMatch; + min_count = yLeftTotal + xRightTotal; + } + else if(flag == Y2X) + { + get_pair_hap_similarity(xReads->a+xLeftBeg, xLeftLen, yUid, reverse_sources, read_g, ruIndex, + &xLeftMatch, &xLeftTotal); + get_pair_hap_similarity(yReads->a+yRightBeg, yRightLen, xUid, reverse_sources, read_g, ruIndex, + &yRightMatch, &yRightTotal); + max_count = xLeftMatch + yRightMatch; + min_count = xLeftTotal + yRightTotal; + } else abort(); + + hap_can->weight = hap_can->index_beg = 0; + if(min_count == 0) return NON_PLOID; + if((max_count > min_count*Hap_rate) || is_local) + { + long long r_x_interval_beg, r_x_interval_end, r_y_interval_beg, r_y_interval_end; + uint64_t ploid_coverage = 0; + + ///for containment, don't need to do anything + get_hap_alignment_boundary(xReads, yReads, flag, xLeftMatch, xLeftTotal, + yLeftMatch, yLeftTotal, xRightMatch, xRightTotal, yRightMatch, yRightTotal, + xLeftBeg, xLeftLen, yLeftBeg, yLeftLen, xRightBeg, xRightLen, yRightBeg, yRightLen, + xUid, yUid, Hap_rate, is_local, position_index, reverse_sources, read_g, ruIndex, + hap_can->rev, &r_x_interval_beg, &r_x_interval_end, &r_y_interval_beg, &r_y_interval_end); + + if(r_x_interval_beg < 0 || r_x_interval_end < 0 || r_y_interval_beg < 0 || r_y_interval_end < 0) + { + return NON_PLOID; + } + + get_pair_hap_similarity(xReads->a + r_x_interval_beg, r_x_interval_end + 1 - r_x_interval_beg, + yUid, reverse_sources, read_g, ruIndex, &xLeftMatch, &xLeftTotal); + if(xLeftMatch == 0 || xLeftTotal == 0 || (is_local == 0 && xLeftMatch <= xLeftTotal*Hap_rate)) + { + return NON_PLOID; + } + + + hap_can->weight = xLeftMatch; + hap_can->index_beg = xLeftTotal; + hap_can->index_end = flag; + hap_can->x_beg_pos = r_x_interval_beg; + hap_can->x_end_pos = r_x_interval_end; + hap_can->y_beg_pos = r_y_interval_beg; + hap_can->y_end_pos = r_y_interval_end; + hap_can->index_end = determine_hap_overlap_type_advance(hap_can, xReads, yReads, + ruIndex, reverse_sources, coverage_cut, read_g, position_index, max_hang, min_ovlp, + xUid, yUid, u_buffer, tailIndex, prevIndex, r_x_pos_beg, r_x_pos_end, r_y_pos_beg, + r_y_pos_end); + if(hap_can->index_end == XCY && yReads->len > (xReads->len*2)) return NON_PLOID; + if(hap_can->index_end == YCX && xReads->len > (yReads->len*2)) return NON_PLOID; + if(hap_can->index_end == (uint32_t)-1) return NON_PLOID; + + ploid_coverage = get_pair_purge_coverage(xReads, *r_x_pos_beg, *r_x_pos_end, + yReads, *r_y_pos_beg, *r_y_pos_end, hap_can->rev, read_g, cov); + + if(cov_threshold > 0 && ploid_coverage >= cov_threshold) return NON_PLOID; + + get_pair_hap_similarity_by_base(xReads, read_g, yUid, reverse_sources, ruIndex, + *r_x_pos_beg, *r_x_pos_end, &xLeftMatch, &xLeftTotal); + (*sim) = (xLeftTotal== 0? 0:((double)xLeftMatch)/((double)xLeftTotal)); + + // adjust_hap_overlaps_score(xReads, sim, &(hap_can->score), xUid, yUid, (*r_x_pos_beg), (*r_x_pos_end)); + + if(xLeftMatch == 0 || xLeftTotal == 0 || (*sim) <= Hap_rate) + { + return NON_PLOID; + } + + return PLOID; + } + return NON_PLOID; +} + + +void print_hap_paf(ma_ug_t *ug, hap_overlaps* ovlp) +{ + fprintf(stderr, "utg%.6d%c\t%u(%u)\t%u(%u)\t%u(%u)\t%c\tutg%.6d%c\t%u(%u)\t%u(%u)\t%u(%u)\t%u\t%u\t%lld(%u)\n", + ovlp->xUid+1, "lc"[ug->u.a[ovlp->xUid].circ], ug->u.a[ovlp->xUid].len, ug->u.a[ovlp->xUid].n, + ovlp->x_beg_pos, ovlp->x_beg_id, ovlp->x_end_pos, ovlp->x_end_id, "+-"[ovlp->rev], + ovlp->yUid+1, "lc"[ug->u.a[ovlp->yUid].circ], ug->u.a[ovlp->yUid].len, ug->u.a[ovlp->yUid].n, + ovlp->y_beg_pos, ovlp->y_beg_id, ovlp->y_end_pos, ovlp->y_end_id, ovlp->type, ovlp->weight, + ovlp->score, ovlp->status); +} + +inline long long get_max_index(asg_arc_t_offset* x, int32_t* Scores, uint8_t* Flag, long long n, +long long x_readLen, long long y_readLen) +{ + long long i = 0, max_result = -1, max_i = -1, min_xLen = x_readLen * 2 + 2, x_off, y_off, tmp_xLen; + for (i = 0; i < n; i++) + { + if(Flag[i] != 0) continue; + x_off = (long long)(x[i].Off>>32); + y_off = (long long)((uint32_t)x[i].Off); + if(Scores[i] > max_result) + { + max_result = Scores[i]; + max_i = i; + min_xLen = get_hap_overlapLen(x_off, x_off, x_readLen, y_off, y_off, y_readLen, + NULL, NULL, NULL, NULL); + } + else if(Scores[i] == max_result) + { + tmp_xLen = get_hap_overlapLen(x_off, x_off, x_readLen, y_off, y_off, y_readLen, + NULL, NULL, NULL, NULL); + + if(tmp_xLen < min_xLen) + { + max_result = Scores[i]; + max_i = i; + min_xLen = tmp_xLen; + } + } + } + + return max_i; +} + + +inline void get_chain_details(int32_t* Pres, int32_t* Results, uint8_t* Flag, long long max_i, +long long* chainLen, long long* dup) +{ + long long i = max_i; + (*chainLen) = 0; + (*dup) = 0; + + while (i >= 0) + { + if(Flag[i] == 1) (*dup)++; + Results[(*chainLen)] = i; + i = Pres[i]; + (*chainLen)++; + } +} + +inline void push_hap_can(asg_arc_t_offset* x, kvec_hap_candidates* u_can, int32_t* Results, +long long chainLen, long long x_readLen, long long y_readLen) +{ + if(chainLen <= 0) return; + hap_candidates hap_can; + hap_can.rev = x[Results[0]].x.el; + hap_can.x_beg_pos = hap_can.x_end_pos = (uint32_t)(x[Results[0]].Off>>32); + hap_can.y_beg_pos = hap_can.y_end_pos = (uint32_t)(x[Results[0]].Off); + hap_can.weight = 0; + long long i = 0; + uint64_t totalWeigth = 0; + ///fprintf(stderr, "^^^chainLen: %lld\n", chainLen); + for (i = 0; i < chainLen; i++) + { + ///fprintf(stderr, "i: %lld, Results[i]: %d\n", i, Results[i]); + hap_can.x_beg_pos = (uint32_t)(x[Results[i]].Off>>32); + hap_can.y_beg_pos = (uint32_t)(x[Results[i]].Off); + hap_can.weight += x[Results[i]].weight; + } + + for (i = 0; i < chainLen; i++) + { + totalWeigth += x[Results[i]].weight; + if(totalWeigth >= (hap_can.weight/2)) break; + } + + if(i >= chainLen) i = chainLen-1; + ///Get_total(hap_can) = Results[i]; + hap_can.t = x[Results[i]].x; + Get_type(hap_can) = classify_hap_overlap(hap_can.x_beg_pos, hap_can.x_end_pos, + x_readLen, hap_can.y_beg_pos, hap_can.y_end_pos, y_readLen, NULL, NULL, NULL, NULL); + kv_push(hap_candidates, u_can->a, hap_can); + if(hap_can.x_beg_pos > hap_can.x_end_pos || hap_can.y_beg_pos > hap_can.y_end_pos) + { + fprintf(stderr, "ERROR\n"); + } +} + + + +void print_chain_data(int32_t* Scores, int32_t* Pres, int32_t* Begs, long long n) +{ + fprintf(stderr,"*****\nn_chain: %lld\n", n); + long long i; + for (i = 0; i < n; i++) + { + fprintf(stderr, "i: %lld, Scores: %d, Pres: %d, Begs: %d\n", + i, Scores[i], Pres[i], Begs[i]); + } +} + + + +void hap_chaining(asg_arc_t_offset* x, uint32_t n, kvec_t_i32_warp* score_vc, kvec_t_i32_warp* prevIndex_vec, +kvec_t_i32_warp* begIndex_vec, kvec_t_u8_warp* flag_vec, float band_width_threshold, long long max_skip, +long long x_readLen, long long y_readLen, kvec_hap_candidates* u_can) +{ + #define DUP_OVLP_RATE 0.75 + score_vc->a.n = prevIndex_vec->a.n = begIndex_vec->a.n = flag_vec->a.n = 0; + if(n == 0) return; + kv_resize(int32_t, score_vc->a, n); + kv_resize(int32_t, prevIndex_vec->a, n); + kv_resize(int32_t, begIndex_vec->a, n); + kv_resize(uint8_t, flag_vec->a, n); + + int32_t* Scores = score_vc->a.a; + int32_t* Pres = prevIndex_vec->a.a; + int32_t* Begs = begIndex_vec->a.a; + uint8_t* Flag = flag_vec->a.a; + long long i, j, n_max_skip, x_off, y_off, max_beg, max_j = -1, max_score, score; + long long distance_x, distance_y, total_distance_x, total_distance_y, distance_gap; + float gap_rate, band_width_penalty = 1 / band_width_threshold; + long long max_result, max_i, min_xLen, tmp_xLen, chainLen = 0, dup = 0; + max_result = max_i = -1; min_xLen = x_readLen * 2 + 2; + for (i = 0; i < n; i++) + { + n_max_skip = 0; + + x_off = (long long)(x[i].Off>>32); + y_off = (long long)((uint32_t)x[i].Off); + max_j = -1; + max_score = x[i].weight; + max_beg = i; //i itself + ///may have a pre-cut condition for j + for (j = i - 1; j >= 0; --j) + { + distance_x = x_off - (long long)(x[j].Off>>32); + distance_y = y_off - (long long)((uint32_t)x[j].Off); + ///x has been sorted by x_off + if(distance_x <= 0 || distance_y <= 0) continue; + + total_distance_x = x_off - (long long)(x[Begs[j]].Off>>32); + total_distance_y = y_off - (long long)((uint32_t)x[Begs[j]].Off); + + distance_gap = total_distance_x - total_distance_y; + if(distance_gap < 0) distance_gap = -distance_gap; + if(distance_gap > band_width_threshold * total_distance_x) + { + continue; + } + + score = x[i].weight; + gap_rate = (float)((float)(distance_gap)/(float)(total_distance_x)); + score -= (long long)(score * gap_rate * band_width_penalty); + score += Scores[j]; + + ///find a new max score + if (score > max_score) { + max_score = score; + max_j = j; + max_beg = Begs[j]; + n_max_skip = 0; + } + else + { + if (++n_max_skip > max_skip) break; + } + } + + Scores[i] = max_score; + Pres[i] = max_j; + Begs[i] = max_beg; + + if(Scores[i] > max_result) + { + max_result = Scores[i]; + max_i = i; + min_xLen = get_hap_overlapLen(x_off, x_off, x_readLen, y_off, y_off, y_readLen, + NULL, NULL, NULL, NULL); + } + else if(Scores[i] == max_result) + { + tmp_xLen = get_hap_overlapLen(x_off, x_off, x_readLen, y_off, y_off, y_readLen, + NULL, NULL, NULL, NULL); + + if(tmp_xLen < min_xLen) + { + max_result = Scores[i]; + max_i = i; + min_xLen = tmp_xLen; + } + } + Flag[i] = 0; + } + + // print_asg_arc_t_offset(x, n); + // print_chain_data(Scores, Pres, Begs, n); + while (max_i != -1) + { + get_chain_details(Pres, Begs, Flag, max_i, &chainLen, &dup); + if(chainLen == 0) break; + if(dup > chainLen*DUP_OVLP_RATE) + { + for (i = 0; i < chainLen; i++) + { + if(Flag[Begs[i]] == 1) continue; + Flag[Begs[i]] = 2; + } + + } + else + { + push_hap_can(x, u_can, Begs, chainLen, x_readLen, y_readLen); + + for (i = 0; i < chainLen; i++) + { + Flag[Begs[i]] = 1; + } + } + + max_i = get_max_index(x, Scores, Flag, n, x_readLen, y_readLen); + } +} + +void get_candidate_hap_alignment(kvec_hap_candidates* u_can, kvec_asg_arc_t_offset* u_buffer, +kvec_t_i32_warp* score_vc, kvec_t_i32_warp* prevIndex_vec, kvec_t_i32_warp* begIndex_vec, +kvec_t_u8_warp* flag_vec, float band_width_threshold, long long max_skip, long long x_readLen, +long long y_readLen) +{ + u_can->a.n = 0; + if(u_buffer->a.n == 0) return; + uint32_t i = 0, /**anchor_i = 0, **/m = 1, break_point = (uint32_t)-1, is_merge; + + qsort(u_buffer->a.a, u_buffer->a.n, sizeof(asg_arc_t_offset), cmp_hap_alignment_chaining); + + ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n); + + for (i = 1; i < u_buffer->a.n; i++) + { + is_merge = 0; + if(u_buffer->a.a[m-1].x.el == u_buffer->a.a[i].x.el) + { + if(u_buffer->a.a[m-1].Off == u_buffer->a.a[i].Off) is_merge = 1; + ///I think we don't need the following merging + // if(is_merge == 0 && (Get_xOff(u_buffer->a.a[m-1].Off)==Get_xOff(u_buffer->a.a[i].Off))) + // { + // if((Get_yOff(u_buffer->a.a[i].Off)-(Get_yOff(u_buffer->a.a[m-1].Off))) == (i-anchor_i))///not sure why, does it use for tolerate indels in overlaps? + // { + // is_merge = 1; + // } + // } + + if(is_merge) + { + u_buffer->a.a[m-1].weight += u_buffer->a.a[i].weight; + continue; + } + } + u_buffer->a.a[m] = u_buffer->a.a[i]; + // anchor_i = i; + if(u_buffer->a.a[m].x.el != u_buffer->a.a[m-1].x.el) break_point = m; + m++; + } + u_buffer->a.n = m; + if(break_point > u_buffer->a.n) break_point = u_buffer->a.n; + + ///print_asg_arc_t_offset(u_buffer->a.a, u_buffer->a.n); + + hap_chaining(u_buffer->a.a, break_point, score_vc, prevIndex_vec, begIndex_vec, flag_vec, + band_width_threshold, max_skip, x_readLen, y_readLen, u_can); + + hap_chaining(u_buffer->a.a + break_point, u_buffer->a.n - break_point, score_vc, prevIndex_vec, + begIndex_vec, flag_vec, band_width_threshold, max_skip, x_readLen, y_readLen, u_can); +} + +int filter_secondary_chain(long long max_score, long long cur_score, double rate) +{ + if(cur_score >= max_score) return 1; + long long diff = max_score - cur_score; + if(max_score < 0) max_score *= -1; + if(diff >= max_score*(1-rate)) return 0; + return 1; +} + + +void filter_secondary_ovlp(kvec_hap_overlaps *x, kvec_t_u64_warp *a, float sim_flt, float ovlp_flt) +{ + if(sim_flt == 0 || ovlp_flt == 0 || x->a.n == 0) return; + #define f_ovlp(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) + uint32_t i, m, k; + uint64_t t, ovlp; + hap_overlaps *p = NULL; + a->a.n = 0; + for (i = 0; i < x->a.n; i++) + { + if(x->a.a[i].s < sim_flt) continue; + t = x->a.a[i].x_beg_pos; t<<=32; t |= x->a.a[i].x_end_pos; + kv_push(uint64_t, a->a, t); + } + + if(a->a.n == 0) return; + ks_introsort_uint64_t(a->a.n, a->a.a); + + for (i = m = 1; i < a->a.n; ++i) + { + t = a->a.a[m-1]; + ovlp = f_ovlp(t>>32, (uint32_t)t, a->a.a[i]>>32, (uint32_t)a->a.a[i]); + if(ovlp == 0) + { + a->a.a[m] = a->a.a[i]; + m++; + } + else + { + t = MIN(a->a.a[m-1]>>32, a->a.a[i]>>32); + t<<=32; + t |= MAX((uint32_t)a->a.a[m-1], (uint32_t)a->a.a[i]); + a->a.a[m-1] = t; + } + } + a->a.n = m; + + for (i = m = 0; i < x->a.n; i++) + { + p = &(x->a.a[i]); + if(p->s < sim_flt) + { + for (k = ovlp = 0; k < a->a.n; k++) + { + ovlp += f_ovlp(p->x_beg_pos, p->x_end_pos, a->a.a[k]>>32, (uint32_t)a->a.a[k]); + if(ovlp >= ovlp_flt*(p->x_end_pos-p->x_beg_pos)) break; + } + if(k < a->a.n) continue; + if(ovlp >= ovlp_flt*(p->x_end_pos-p->x_beg_pos)) continue; + } + x->a.a[m] = x->a.a[i]; + m++; + } + x->a.n = m; +} + +static void hap_alignment_advance_worker(void *_data, long eid, int tid) +{ + hap_alignment_struct_pip* hap_buf = (hap_alignment_struct_pip*)_data; + ma_ug_t *ug = hap_buf->ug; + asg_t *read_g = hap_buf->read_g; + ma_hit_t_alloc* sources = hap_buf->sources; + ma_hit_t_alloc* reverse_sources = hap_buf->reverse_sources; + R_to_U* ruIndex = hap_buf->ruIndex; + ma_sub_t *coverage_cut = hap_buf->coverage_cut; + uint64_t* position_index = hap_buf->position_index; + float Hap_rate = hap_buf->Hap_rate/**MIN(hap_buf->Hap_rate, 0.2)**/, sim; + int max_hang = hap_buf->max_hang; + int min_ovlp = hap_buf->min_ovlp; + float chain_rate = hap_buf->chain_rate; + hap_overlaps_list* all_ovlp = hap_buf->all_ovlp; + uint32_t Input_uId = eid; + uint64_t* vote_counting = hap_buf->buf[tid].vote_counting; + uint8_t* visit = hap_buf->buf[tid].visit; + kvec_t_u64_warp* u_vecs = &(hap_buf->buf[tid].u_vecs); + kvec_asg_arc_t_offset* u_buffer = &(hap_buf->buf[tid].u_buffer); + kvec_hap_candidates* u_can = &(hap_buf->buf[tid].u_can); + kvec_t_i32_warp* score_vc = &(hap_buf->buf[tid].u_buffer_tailIndex); + kvec_t_i32_warp* prevIndex_vec = &(hap_buf->buf[tid].u_buffer_prevIndex); + kvec_t_i32_warp* begIndex_vec = &(hap_buf->buf[tid].u_buffer_beg); + kvec_t_u8_warp* flag_vec = &(hap_buf->buf[tid].u_buffer_flag); + uint64_t cov_threshold = hap_buf->cov_threshold; + hap_cov_t *cov = hap_buf->cov; + uint8_t *hh = hap_buf->hh, hhc; + if(hap_buf->cov_threshold < 0) cov_threshold = (uint64_t)-1; + ma_utg_t *xReads = NULL, *yReads = NULL; + ma_hit_t_alloc *xR = NULL; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL, *st = NULL; + asg_t* nsg = ug->g; + uint32_t i, j, v, rId, k, is_Unitig, Hap_uId, xUid, yUid, seedOcc; + uint64_t tmp, max_weight, m; + long long r_x_pos_beg, r_x_pos_end, r_y_pos_beg, r_y_pos_end, max_score; + int32_t r; + asg_arc_t t; + asg_arc_t_offset t_offset; + hap_overlaps hap_align; + hap_overlaps *hap_align_x = NULL; + xUid = Input_uId; + if(nsg->seq[xUid].del || nsg->seq[xUid].c == ALTER_LABLE) return; + memset(vote_counting, 0, sizeof(uint64_t)*nsg->n_seq); + memset(visit, 0, nsg->n_seq); + u_vecs->a.n = 0; + u_can->a.n = 0; + + xReads = &(ug->u.a[xUid]); + for (i = 0; i < xReads->n; i++) + { + xR = &(reverse_sources[xReads->a[i]>>33]); + + for (k = 0; k < xR->length; k++) + { + rId = Get_tn(xR->buffer[k]); + + if(read_g->seq[rId].del == 1) + { + ///get the id of read that contains it + get_R_to_U(ruIndex, rId, &rId, &is_Unitig); + if(rId == (uint32_t)-1 || is_Unitig == 1 || read_g->seq[rId].del == 1) continue; + } + + ///there are two cases: + ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id + ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 + get_R_to_U(ruIndex, rId, &Hap_uId, &is_Unitig); + if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; + ///here rId is the id of the read coming from the different haplotype + ///Hap_cId is the id of the corresponding contig (note here is the contig, instead of untig) + if(visit[Hap_uId]!=0) continue; ///one read only has one vote for one hap unitig + visit[Hap_uId] = 1; + if(vote_counting[Hap_uId] < UINT64_MAX) vote_counting[Hap_uId]++; + } + + clean_visit_flag(visit, read_g, ruIndex, nsg->n_seq, xR); + } + + + + u_vecs->a.n = 0; + for (i = 0; i < nsg->n_seq; i++) + { + if(i == xUid) continue; + if(vote_counting[i] == 0) continue; + tmp = vote_counting[i]; tmp = tmp << 32; tmp = tmp | (uint64_t)i; + kv_push(uint64_t, u_vecs->a, tmp); + } + + if(u_vecs->a.n == 0) return; + sort_kvec_t_u64_warp(u_vecs, 1); + + + ///scan each candidate unitig + for (i = 0; i < u_vecs->a.n; i++) + { + yUid = (uint32_t)u_vecs->a.a[i]; + seedOcc = u_vecs->a.a[i]>>32; + xReads = &(ug->u.a[xUid]); + yReads = &(ug->u.a[yUid]); + u_buffer->a.n = 0; + + for (k = 0; k < xReads->n; k++) + { + xR = &(reverse_sources[xReads->a[k]>>33]); + hhc = hh[xReads->a[k]>>33]; + for (j = 0; j < xR->length; j++) + { + h = &(xR->buffer[j]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(st->del || read_g->seq[Get_tn(*h)].del) continue; + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t); + ///if it is a contained overlap, skip + if(r < 0) continue; + + rId = t.v>>1; + if(read_g->seq[rId].del == 1) continue; + ///there are two cases: + ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id + ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 + get_R_to_U(ruIndex, rId, &Hap_uId, &is_Unitig); + if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; + if(Hap_uId != yUid) continue; + + v = xReads->a[k]>>32; + get_R_to_U(ruIndex, v>>1, &Hap_uId, &is_Unitig); + if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; + if(Hap_uId != xUid) continue; + if((uint32_t)(position_index[v>>1]) != k) continue; + + if(asm_opt.purge_level_primary <= 2 && + (prefilter((uint32_t)(position_index[v>>1]), (uint32_t)(position_index[rId]), + xReads->n, yReads->n, 0, Hap_rate, seedOcc)==NON_PLOID) && + (prefilter((uint32_t)(position_index[v>>1]), (uint32_t)(position_index[rId]), + xReads->n, yReads->n, 1, Hap_rate, seedOcc)==NON_PLOID)) + { + continue; + } + + t_offset.Off = get_xy_pos(read_g, &t, v, (yReads->a[(uint32_t)(position_index[rId])])>>32, + xReads->len, yReads->len, position_index, &(t.el)); + if(((t_offset.Off>>32) == (uint32_t)-1) || (((uint32_t)t_offset.Off) == (uint32_t)-1)) continue; + + t_offset.x = t; + t_offset.weight = hhc; + + kv_push(asg_arc_t_offset, u_buffer->a, t_offset); + } + + deduplicate_edge(u_buffer); + } + + if(u_buffer->a.n == 0) continue; + + + get_candidate_hap_alignment(u_can, u_buffer, score_vc, prevIndex_vec, begIndex_vec, + flag_vec, chain_rate, 50, xReads->len, yReads->len); + + if(u_can->a.n == 0) continue; + + qsort(u_can->a.a, u_can->a.n, sizeof(hap_candidates), cmp_hap_candidates); + + memset(&hap_align, 0, sizeof(hap_overlaps)); + m = all_ovlp->x[xUid].a.n; + max_weight = 0; max_score = 0; + for (k = 0; k < u_can->a.n; k++) + { + if(u_can->a.a[k].weight < max_weight*0.33) continue; + if(calculate_pair_hap_similarity_advance(&(u_can->a.a[k]), position_index, xUid, yUid, + xReads, yReads, sources, reverse_sources, read_g, ruIndex, coverage_cut, Hap_rate, + (asm_opt.purge_level_primary<=2? 0:1), max_hang, min_ovlp, cov_threshold, u_buffer, + score_vc, prevIndex_vec, cov, &r_x_pos_beg, &r_x_pos_end, &r_y_pos_beg, &r_y_pos_end, &sim)!=PLOID) + { + continue; + } + ///max_weight == 0 means the first matched chain + if(max_weight == 0 || max_score < u_can->a.a[k].score) max_score = u_can->a.a[k].score; + if(max_weight < u_can->a.a[k].weight) max_weight = u_can->a.a[k].weight; + ///if one is positive and another one is negative, it is wrong + if(!filter_secondary_chain(max_score, u_can->a.a[k].score, CHAIN_FILTER_RATE)) continue; + + hap_align.rev = Get_rev(u_can->a.a[k]); + hap_align.type = Get_type(u_can->a.a[k]); + hap_align.x_beg_id = Get_x_beg(u_can->a.a[k]); + hap_align.x_end_id = Get_x_end(u_can->a.a[k]) + 1; + hap_align.y_beg_id = Get_y_beg(u_can->a.a[k]); + hap_align.y_end_id = Get_y_end(u_can->a.a[k]) + 1; + hap_align.weight = Get_match(u_can->a.a[k]); + hap_align.score = u_can->a.a[k].score; + hap_align.x_beg_pos = r_x_pos_beg; + hap_align.x_end_pos = r_x_pos_end + 1; + if(hap_align.rev == 0) + { + hap_align.y_beg_pos = r_y_pos_beg; + hap_align.y_end_pos = r_y_pos_end + 1; + } + else + { + hap_align.y_beg_pos = yReads->len - r_y_pos_end - 1; + hap_align.y_end_pos = yReads->len - r_y_pos_beg - 1 + 1; + } + hap_align.xUid = xUid; + hap_align.yUid = yUid; + hap_align.status = SELF_EXIST; + hap_align.s = sim; + kv_push(hap_overlaps, all_ovlp->x[hap_align.xUid].a, hap_align); + } + /** + ///chains with same xUid && yUid + for (k = m; k < all_ovlp->x[xUid].a.n; k++) + { + if(!filter_secondary_chain(max_score, + all_ovlp->x[xUid].a.a[k].score, CHAIN_FILTER_RATE)) + { + continue; + } + all_ovlp->x[xUid].a.a[m] = all_ovlp->x[xUid].a.a[k]; + m++; + } + all_ovlp->x[xUid].a.n = m; + **/ + + hap_align_x = NULL; + for (k = m; k < all_ovlp->x[xUid].a.n; k++) + { + if(all_ovlp->x[xUid].a.a[k].score != max_score) continue; + if(hap_align_x == NULL || all_ovlp->x[xUid].a.a[k].weight > hap_align_x->weight) + { + hap_align_x = &(all_ovlp->x[xUid].a.a[k]); + } + else if(all_ovlp->x[xUid].a.a[k].weight == hap_align_x->weight) + { + if((all_ovlp->x[xUid].a.a[k].x_end_pos + - all_ovlp->x[xUid].a.a[k].x_beg_pos) < + (hap_align_x->x_end_pos - hap_align_x->x_beg_pos)) + { + hap_align_x = &(all_ovlp->x[xUid].a.a[k]); + } + } + } + if(hap_align_x) + { + all_ovlp->x[xUid].a.a[m] = (*hap_align_x); + all_ovlp->x[xUid].a.n = m + 1; + } + } + // filter_secondary_ovlp(&all_ovlp->x[xUid], u_vecs, hap_buf->Hap_rate, 0.7); +} + +int get_specific_hap_overlap(kvec_hap_overlaps* x, uint32_t qn, uint32_t tn) +{ + uint32_t i; + for (i = 0; i < x->a.n; i++) + { + if(x->a.a[i].xUid == qn && x->a.a[i].yUid == tn) + { + return i; + } + } + + return -1; +} + +void set_reverse_hap_overlap(hap_overlaps* dest, hap_overlaps* source, uint32_t* types) +{ + dest->status = REVE_EXIST; + dest->rev = source->rev; + dest->type = types[source->type]; + dest->weight = source->weight; + dest->xUid = source->yUid; + dest->yUid = source->xUid; + dest->x_beg_pos = source->y_beg_pos; + dest->x_end_pos = source->y_end_pos; + dest->y_beg_pos = source->x_beg_pos; + dest->y_end_pos = source->x_end_pos; + dest->x_beg_id = source->y_beg_id; + dest->x_end_id = source->y_end_id; + dest->y_beg_id = source->x_beg_id; + dest->y_end_id = source->x_end_id; + dest->score = source->score; +} + +/** +#define X2Y 0 +#define Y2X 1 +#define XCY 2 +#define YCX 3 +**/ +void normalize_hap_overlaps(hap_overlaps_list* all_ovlp, hap_overlaps_list* back_all_ovlp) +{ + hap_overlaps *x = NULL, *y = NULL; + uint32_t v, i, uId, qn, tn; + uint32_t types[4]; + types[X2Y] = Y2X; types[Y2X] = X2Y; types[XCY] = YCX; types[YCX] = XCY; + int index; + for (v = 0; v < all_ovlp->num; v++) + { + uId = v; + for (i = 0; i < all_ovlp->x[uId].a.n; i++) + { + qn = all_ovlp->x[uId].a.a[i].xUid; + tn = all_ovlp->x[uId].a.a[i].yUid; + x = &(all_ovlp->x[uId].a.a[i]); + index = get_specific_hap_overlap(&(all_ovlp->x[tn]), tn, qn); + if(index != -1) + { + y = &(all_ovlp->x[tn].a.a[index]); + if(x->rev == y->rev && types[x->type]==y->type) continue; + if(x->weight >= y->weight) + { + kv_push(hap_overlaps, back_all_ovlp->x[tn].a, (*y)); + set_reverse_hap_overlap(y, x, types); + } + else + { + kv_push(hap_overlaps, back_all_ovlp->x[qn].a, (*x)); + set_reverse_hap_overlap(x, y, types); + } + } + else + { + kv_pushp(hap_overlaps, all_ovlp->x[tn].a, &y); + set_reverse_hap_overlap(y, x, types); + } + } + } +} + +inline uint64_t calculate_bi_weight(hap_overlaps *x, ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* reverse_sources, +R_to_U* ruIndex) +{ + double xMatch, xTotal; + uint64_t weight = x->weight; + ma_utg_t *yReads = &(ug->u.a[x->yUid]); + get_pair_hap_similarity(yReads->a + x->y_beg_id, x->y_end_id - x->y_beg_id, + x->xUid, reverse_sources, read_g, ruIndex, &xMatch, &xTotal); + weight += xMatch; + return weight; +} + +void normalize_hap_overlaps_advance(hap_overlaps_list* all_ovlp, hap_overlaps_list* back_all_ovlp, +ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex) +{ + hap_overlaps *x = NULL, *y = NULL; + uint32_t v, i, uId, qn, tn; + uint32_t types[4]; + + types[X2Y] = Y2X; types[Y2X] = X2Y; types[XCY] = YCX; types[YCX] = XCY; + int index; + for (v = 0; v < all_ovlp->num; v++) + { + uId = v; + for (i = 0; i < all_ovlp->x[uId].a.n; i++) + { + qn = all_ovlp->x[uId].a.a[i].xUid; + tn = all_ovlp->x[uId].a.a[i].yUid; + x = &(all_ovlp->x[uId].a.a[i]); + index = get_specific_hap_overlap(&(all_ovlp->x[tn]), tn, qn); + if(index != -1) + { + y = &(all_ovlp->x[tn].a.a[index]); + if(x->rev == y->rev && types[x->type]==y->type) continue; + ///if(x->weight >= y->weight) + // if((calculate_bi_weight(x, ug, read_g, reverse_sources, ruIndex)) >= + // (calculate_bi_weight(y, ug, read_g, reverse_sources, ruIndex))) + if(x->score >= y->score) + { + kv_push(hap_overlaps, back_all_ovlp->x[tn].a, (*y)); + set_reverse_hap_overlap(y, x, types); + } + else + { + kv_push(hap_overlaps, back_all_ovlp->x[qn].a, (*x)); + set_reverse_hap_overlap(x, y, types); + } + } + else + { + kv_pushp(hap_overlaps, all_ovlp->x[tn].a, &y); + set_reverse_hap_overlap(y, x, types); + } + } + } +} + +void get_p_nodes(p_g_t *pg, p_node_t **x, uint32_t *x_occ, uint32_t id) +{ + if(x) (*x) = pg->pg_het_node.a + pg->pg_h_lev_idx.a[id].beg; + if(x_occ) (*x_occ) = pg->pg_h_lev_idx.a[id].occ; +} + +void normalize_hap_overlaps_advance_by_p_g_t(hap_overlaps_list* all_ovlp, hap_overlaps_list* back_all_ovlp, +ma_ug_t *ug, asg_t *read_g, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, p_g_t *pg, hap_cov_t *cov, +double filter_rate) +{ + hap_overlaps *x = NULL, *y = NULL; + uint32_t v, i, uId, qn, tn; + uint32_t types[4]; + + + types[X2Y] = Y2X; types[Y2X] = X2Y; types[XCY] = YCX; types[YCX] = XCY; + int index; + uint32_t k, qs, qe, ts, te, occ, as, ae, ovlp, hetLen, homLen; + p_node_t *a = NULL; + + + for (v = 0; v < all_ovlp->num; v++) + { + uId = v; + for (i = 0; i < all_ovlp->x[uId].a.n; i++) + { + /*****************qn*****************/ + qn = all_ovlp->x[uId].a.a[i].xUid; + qs = all_ovlp->x[uId].a.a[i].x_beg_pos; + qe = all_ovlp->x[uId].a.a[i].x_end_pos - 1; + get_p_nodes(pg, &a, &occ, qn); + for (k = 0, hetLen = 0, homLen = 0; k < occ; k++) + { + as = a[k].baseBeg; + ae = a[k].baseEnd; + ovlp = ((MIN(qe, ae) >= MAX(qs, as))? MIN(qe, ae) - MAX(qs, as) + 1 : 0); + if(homLen + hetLen > 0 && ovlp == 0) break; + if(ovlp == 0) continue; + if(a[k].h_status == N_HET) + { + homLen += ovlp; + } + else if(asm_opt.polyploidy <= 2 && (a[k].h_status&P_HET))///if(asm_opt.polyploidy <= 2 && (a[k].h_status&S_HET)) + { + homLen += ovlp; + } + else + { + hetLen += ovlp; + } + } + + if(hetLen <= ((hetLen + homLen) * filter_rate)) + { + all_ovlp->x[uId].a.a[i].status = DELETE; + continue; + } + /*****************qn*****************/ + + + /*****************tn*****************/ + tn = all_ovlp->x[uId].a.a[i].yUid; + ts = all_ovlp->x[uId].a.a[i].y_beg_pos; + te = all_ovlp->x[uId].a.a[i].y_end_pos - 1; + get_p_nodes(pg, &a, &occ, tn); + for (k = 0, hetLen = 0, homLen = 0; k < occ; k++) + { + as = a[k].baseBeg; + ae = a[k].baseEnd; + ovlp = ((MIN(te, ae) >= MAX(ts, as))? MIN(te, ae) - MAX(ts, as) + 1 : 0); + if(homLen + hetLen > 0 && ovlp == 0) break; + if(ovlp == 0) continue; + if(a[k].h_status == N_HET) + { + homLen += ovlp; + } + else if(asm_opt.polyploidy <= 2 && (a[k].h_status&P_HET))///if(asm_opt.polyploidy <= 2 && (a[k].h_status&S_HET)) + { + homLen += ovlp; + } + else + { + hetLen += ovlp; + } + } + + if(hetLen <= ((hetLen + homLen) * filter_rate)) + { + all_ovlp->x[uId].a.a[i].status = DELETE; + continue; + } + /*****************tn*****************/ + } + } + + for (v = 0; v < all_ovlp->num; v++) + { + uId = v; + k = 0; + for (i = 0; i < all_ovlp->x[uId].a.n; i++) + { + if(all_ovlp->x[uId].a.a[i].status == DELETE) continue; + all_ovlp->x[uId].a.a[k] = all_ovlp->x[uId].a.a[i]; + k++; + } + all_ovlp->x[uId].a.n = k; + } + + + for (v = 0; v < all_ovlp->num; v++) + { + uId = v; + for (i = 0; i < all_ovlp->x[uId].a.n; i++) + { + qn = all_ovlp->x[uId].a.a[i].xUid; + tn = all_ovlp->x[uId].a.a[i].yUid; + x = &(all_ovlp->x[uId].a.a[i]); + index = get_specific_hap_overlap(&(all_ovlp->x[tn]), tn, qn); + if(index != -1) + { + y = &(all_ovlp->x[tn].a.a[index]); + if(x->rev == y->rev && types[x->type]==y->type) continue; + if(x->score >= y->score) + { + kv_push(hap_overlaps, back_all_ovlp->x[tn].a, (*y)); + set_reverse_hap_overlap(y, x, types); + } + else + { + kv_push(hap_overlaps, back_all_ovlp->x[qn].a, (*x)); + set_reverse_hap_overlap(x, y, types); + } + } + else + { + kv_pushp(hap_overlaps, all_ovlp->x[tn].a, &y); + set_reverse_hap_overlap(y, x, types); + } + } + } +} + +void filter_hap_overlaps_by_length(hap_overlaps_list* all_ovlp, uint32_t minLen) +{ + if(minLen == 0) return; + hap_overlaps *x = NULL; + uint32_t v, i, m, uId; + + for (v = 0; v < all_ovlp->num; v++) + { + uId = v; + m = 0; + for (i = 0; i < all_ovlp->x[uId].a.n; i++) + { + x = &(all_ovlp->x[uId].a.a[i]); + if(x->x_end_id - x->x_beg_id < minLen) continue; + all_ovlp->x[uId].a.a[m] = (*x); + m++; + } + all_ovlp->x[uId].a.n = m; + } +} + +void debug_hap_overlaps(hap_overlaps_list* all_ovlp, hap_overlaps_list* back_all_ovlp) +{ + hap_overlaps *x = NULL, *y = NULL; + uint32_t v, i, uId, qn, tn; + uint32_t types[4]; + types[X2Y] = Y2X; types[Y2X] = X2Y; types[XCY] = YCX; types[YCX] = XCY; + int index; + for (v = 0; v < all_ovlp->num; v++) + { + uId = v; + for (i = 0; i < all_ovlp->x[uId].a.n; i++) + { + qn = all_ovlp->x[uId].a.a[i].xUid; + tn = all_ovlp->x[uId].a.a[i].yUid; + x = &(all_ovlp->x[uId].a.a[i]); + index = get_specific_hap_overlap(&(all_ovlp->x[tn]), tn, qn); + if(index == -1) + { + fprintf(stderr, "ERROR 0\n"); + continue; + } + + y = &(all_ovlp->x[tn].a.a[index]); + if(x->rev != y->rev || types[x->type] != y->type) + { + fprintf(stderr, "ERROR 1\n"); + continue; + } + + if(x->status == REVE_EXIST && y->status != SELF_EXIST) + { + fprintf(stderr, "ERROR 2\n"); + continue; + } + + if(x->status == REVE_EXIST) + { + if(x->weight != y->weight) fprintf(stderr, "ERROR 3\n"); + if(x->xUid != y->yUid) fprintf(stderr, "ERROR 4\n"); + if(x->yUid != y->xUid) fprintf(stderr, "ERROR 5\n"); + if(x->x_beg_pos != y->y_beg_pos) fprintf(stderr, "ERROR 6\n"); + if(x->x_end_pos != y->y_end_pos) fprintf(stderr, "ERROR 7\n"); + if(x->y_beg_pos != y->x_beg_pos) fprintf(stderr, "ERROR 8\n"); + if(x->y_end_pos != y->x_end_pos) fprintf(stderr, "ERROR 9\n"); + if(x->x_beg_id != y->y_beg_id) fprintf(stderr, "ERROR 10\n"); + if(x->x_end_id != y->y_end_id) fprintf(stderr, "ERROR 11\n"); + if(x->y_beg_id != y->x_beg_id) fprintf(stderr, "ERROR 12\n"); + if(x->y_beg_id != y->x_beg_id) fprintf(stderr, "ERROR 13\n"); + if(x->y_end_id != y->x_end_id) fprintf(stderr, "ERROR 14\n"); + + index = get_specific_hap_overlap(&(back_all_ovlp->x[qn]), qn, tn); + if(index != -1) + { + if(back_all_ovlp->x[qn].a.a[index].weight > x->weight) fprintf(stderr, "ERROR 15\n"); + } + } + + } + } +} + +void print_purge_gfa(ma_ug_t *ug, asg_t *purge_g) +{ + uint32_t v, i, n_vtx = purge_g->n_seq * 2; + for (v = 0; v < n_vtx; v++) + { + if(v%2==0) fprintf(stderr, "\n"); + if(purge_g->seq[v>>1].del) + { + fprintf(stderr, "(D) v>>1: %u, v&1: %u, utg%.6d%c\n", v>>1, v&1, (v>>1)+1, + "lc"[ug->u.a[v>>1].circ]); + continue; + } + + fprintf(stderr, "(E) v>>1: %u, v&1: %u, utg%.6dl%c\n", v>>1, v&1, (v>>1)+1, + "lc"[ug->u.a[v>>1].circ]); + + uint32_t nv = asg_arc_n(purge_g, v); + asg_arc_t *av = asg_arc_a(purge_g, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + fprintf(stderr, "av[i].ul: %u (utg%.6d%c, dir: %u, len: %u), av[i].v: %u (utg%.6d%c, dir: %u, len: %u), ol: %u\n", + (uint32_t)(av[i].ul>>33), (uint32_t)(av[i].ul>>33)+1, "lc"[ug->u.a[av[i].ul>>33].circ], (uint32_t)(av[i].ul>>32)&1, ug->u.a[av[i].ul>>33].len, + av[i].v>>1, (av[i].v>>1)+1, "lc"[ug->u.a[av[i].v>>1].circ], av[i].v&1, ug->u.a[av[i].v>>1].len, av[i].ol); + } + + } + +} + +long long decode_score(uint32_t h_bits, uint32_t l_bits) +{ + uint64_t x; + x = h_bits; x <<= 32; x += l_bits; + long long score = ((uint64_t)((uint64_t)x<<1)>>1); + if((x>>63) == 0) score *= -1; + return score; +} + +void encode_score(long long i_s, uint32_t *h_bits, uint32_t *l_bits) +{ + uint64_t score = (i_s >= 0? (i_s) : (i_s*(-1))); + if(i_s >= 0) score += (((uint64_t)1)<<63); + (*l_bits) = (uint32_t)score; (*h_bits)= (score>>32); +} + +uint64_t asg_bub_pop1_purge_graph(asg_t *g, uint32_t v0, int max_dist, buf_t *b) +{ + uint32_t i, n_pending = 0, n_tips, tip_end; + uint64_t n_pop = 0; + ///if this node has been deleted + if (g->seq[v0>>1].del || g->seq[v0>>1].c == ALTER_LABLE) return 0; // already deleted + ///if ((uint32_t)g->idx[v0] < 2) return 0; // no bubbles + if(get_real_length(g, v0, NULL)<2) return 0; + ///S saves nodes with all incoming edges visited + b->S.n = b->T.n = b->b.n = b->e.n = 0; + ///for each node, b->a saves all related information + b->a[v0].c = b->a[v0].d = b->a[v0].m = b->a[v0].nc = b->a[v0].np = 0; + ///b->S is the nodes with all incoming edges visited + kv_push(uint32_t, b->S, v0); + n_tips = 0; + tip_end = (uint32_t)-1; + + do { + ///v is a node that all incoming edges have been visited + ///d is the distance from v0 to v + uint32_t v = kv_pop(b->S), d = b->a[v].d; + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + long long t_s = decode_score(b->a[v].c, b->a[v].m), c_s; + ///why we have this assert? + ///assert(nv > 0); + ///all out-edges of v + for (i = 0; i < nv; ++i) { // loop through v's neighbors + ///if this edge has been deleted + if (av[i].del) continue; + uint32_t w = av[i].v; // v->w with length l + binfo_t *t = &b->a[w]; + ///that means there is a circle, directly terminate the whole bubble poping + ///if (w == v0) goto pop_reset; + if ((w>>1) == (v0>>1)) goto pop_reset; + c_s = decode_score((uint32_t)av[i].ul, av[i].ol); + ///push the edge + ///high 32-bit of g->idx[v] is the start point of v's edges + //so here is the point of this specfic edge + kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); + ///find a too far path? directly terminate the whole bubble poping + if (d + 1 > (uint32_t)max_dist) break; // too far + + ///if this node + if (t->s == 0) { // this vertex has never been visited + kv_push(uint32_t, b->b, w); // save it for revert + ///t->p is the parent node of + ///t->s = 1 means w has been visited + ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) + t->p = v, t->s = 1, t->d = d + 1; + encode_score(t_s + c_s, &(t->c), &(t->m)); + ///incoming edges of w + ///t->r = count_out(g, w^1); + t->r = get_real_length(g, w^1, NULL); + ++n_pending; + } else { // visited before + if((t_s + c_s)> decode_score(t->c, t->m)) + { + t->p = v; + encode_score(t_s + c_s, &(t->c), &(t->m)); + } + ///it is the shortest edge + if (d + 1 < t->d) t->d = d + 1; // update dist + } + ///assert(t->r > 0); + //if all incoming edges of w have visited + //push it to b->S + if (--(t->r) == 0) { + uint32_t x = get_real_length(g, w, NULL); + /****************************may have bugs for bubble********************************/ + if(x > 0) + { + kv_push(uint32_t, b->S, w); + } + else + { + ///at most one tip + if(n_tips != 0) goto pop_reset; + n_tips++; + tip_end = w; + } + /****************************may have bugs for bubble********************************/ + --n_pending; + } + } + //if found a tip + /****************************may have bugs for bubble********************************/ + if(n_tips == 1) + { + if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) + { + kv_push(uint32_t, b->S, tip_end); + break; + } + else + { + goto pop_reset; + } + } + /****************************may have bugs for bubble********************************/ + ///if i < nv, that means (d + l > max_dist) + if (i < nv || b->S.n == 0) goto pop_reset; + } while (b->S.n > 1 || n_pending); + + asg_bub_backtrack_primary(g, v0, b); + + n_pop = 1; +pop_reset: + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + binfo_t *t = &b->a[b->b.a[i]]; + t->s = t->c = t->d = t->m = t->nc = t->np = 0; + } + return n_pop; +} + + + +// pop bubbles +int asg_pop_bubble_purge_graph(asg_t *purge_g) +{ + uint32_t v, n_vtx = purge_g->n_seq * 2; + uint64_t n_pop = 0; + buf_t b; + if (!purge_g->is_symm) asg_symm(purge_g); + memset(&b, 0, sizeof(buf_t)); + ///set information for each node + b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + //traverse all node with two directions + for (v = 0; v < n_vtx; ++v) { + uint32_t i, n_arc = 0, nv = asg_arc_n(purge_g, v); + asg_arc_t *av = asg_arc_a(purge_g, v); + ///some node could be deleted + if (nv < 2 || purge_g->seq[v>>1].del || purge_g->seq[v>>1].c == ALTER_LABLE) continue; + ///some edges could be deleted + for (i = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs + if (!av[i].del) ++n_arc; + if (n_arc > 1) + n_pop += asg_bub_pop1_purge_graph(purge_g, v, purge_g->n_seq, &b); + } + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + if (n_pop) asg_cleanup(purge_g); + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] popped %lu bubbles\n", __func__, (unsigned long)n_pop); + } + return n_pop; +} + +int get_hap_arch(hap_overlaps* hap, uint32_t qLen, uint32_t tLen, int max_hang, float max_hang_rate, +int min_ovlp, asg_arc_t* t) +{ + int r; + ma_hit_t h; + h.qns = hap->xUid; + h.qns = h.qns << 32; + h.qns = h.qns | hap->x_beg_pos; + h.qe = hap->x_end_pos; + h.tn = hap->yUid; + h.ts = hap->y_beg_pos; + h.te = hap->y_end_pos; + h.rev = hap->rev; + h.del = 0; + h.bl = h.el = h.ml = h.no_l_indel = 0; + + r = ma_hit2arc(&h, qLen, tLen, max_hang, max_hang_rate, min_ovlp, t); + if(r < 0) return r; + uint64_t score = (hap->score >= 0? (hap->score) : (hap->score*(-1))); + if(hap->score >= 0) score += (((uint64_t)1)<<63); + t->ol = (uint32_t)score; + t->ul >>= 32; t->ul <<= 32; t->ul |= (score>>32); + return r; +} + +typedef struct { + uint64_t eid; + uint64_t score; +}e_score; + +typedef struct { + size_t n, m; + e_score* a; +}e_score_warp; + +#define e_score_key(a) ((a).score) +KRADIX_SORT_INIT(e_score, e_score, e_score_key, member_size(e_score, score)) + +int purge_g_arc_del_short_diploid_by_score(asg_t *g, float drop_ratio) +{ + e_score_warp b; + kv_init(b); + e_score *p = NULL; + + uint32_t v, n_vtx = g->n_seq * 2; + long long n_cut = 0; + + for (v = 0; v < n_vtx; ++v) + { + if(g->seq[v>>1].c == ALTER_LABLE || g->seq[v>>1].del) continue; + asg_arc_t *av = asg_arc_a(g, v); + uint32_t nv = asg_arc_n(g, v); + if (nv < 2) continue; + uint64_t i; + for (i = 0; i < nv; ++i) + { + kv_pushp(e_score, b, &p); + p->eid = av - g->arc + i; + p->score = (uint32_t)av[i].ul; + p->score <<= 32; + p->score |= av[i].ol; + } + } + + radix_sort_e_score(b.a, b.a + b.n); + + uint64_t k; + for (k = 0; k < b.n; k++) + { + asg_arc_t *a = &g->arc[b.a[k].eid]; + ///v is self id, w is the id of another end + uint32_t i, v = (a->ul)>>32; + uint32_t nv = asg_arc_n(g, v), kv; + long long ovlp_max = 0, ovlp; + asg_arc_t *av = NULL; + ///nv must be >= 2 + if (nv <= 1) continue; + av = asg_arc_a(g, v); + + ///calculate the longest edge for v and w + for (i = 0, kv = 0; i < nv; ++i) { + if (av[i].del) continue; + ovlp = decode_score((uint32_t)av[i].ul, av[i].ol); + if (kv == 0 || ovlp_max < ovlp) ovlp_max = ovlp; + ++kv; + } + + if (kv <= 1) continue; + ovlp = decode_score((uint32_t)a->ul, a->ol); + if (kv >= 2) + { + if(ovlp >= 0 && ovlp_max >= 0 && ovlp > ovlp_max * drop_ratio) continue; + } + + a->del = 1; + asg_arc_del(g, a->v^1, av->ul>>32^1, 1); + ++n_cut; + } + + kv_destroy(b); + if (n_cut) + { + asg_cleanup(g); + asg_symm(g); + } + + + return n_cut; +} + + +void clean_purge_graph(asg_t *purge_g, float drop_ratio, uint32_t is_force_break) +{ + uint64_t operation = 1; + while (operation > 0) + { + operation = 0; + operation += asg_pop_bubble_purge_graph(purge_g); + operation += purge_g_arc_del_short_diploid_by_score(purge_g, drop_ratio); + } + + if(is_force_break) purge_g_arc_del_short_diploid_by_score(purge_g, 1); +} + + +void get_node_boundary_advance(R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, +asg_t *read_g, uint64_t* position_index, int max_hang, int min_ovlp, ma_utg_t *xReads, ma_utg_t *yReads, +uint32_t xUid, uint32_t yUid, long long xBegIndex, long long xEndIndex, long long yBegIndex, +long long yEndIndex, uint32_t dir, uint32_t rev, kvec_asg_arc_t_offset* u_buffer, +kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* prevIndex, asg_arc_t* reture_t_f, asg_arc_t* reture_t_r) +{ + long long k, j, offset, m; + ma_hit_t_alloc *xR = NULL; + ma_hit_t *h = NULL; + ma_sub_t *sq = NULL, *st = NULL; + int r, index; + asg_arc_t t_f, t_r; + uint32_t rId, Hap_uId, is_Unitig, v, w, v_dir, w_dir; + uint64_t tmp; + asg_arc_t_offset t_offset; + reture_t_f->del = reture_t_r->del = 1; + u_buffer->a.n = 0; + + + for (k = xBegIndex; k <= xEndIndex; k++) + { + xR = &(reverse_sources[xReads->a[k]>>33]); + for (j = 0; j < xR->length; j++) + { + h = &(xR->buffer[j]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(st->del || read_g->seq[Get_tn(*h)].del) continue; + + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t_f); + ///if it is a contained overlap, skip + if(r < 0) continue; + + rId = t_f.v>>1; + if(read_g->seq[rId].del == 1) continue; + ///there are two cases: + ///1. read at primary contigs, get_R_to_U() return its corresponding contig Id + ///2. read at alternative contigs, get_R_to_U() return (uint32_t)-1 + get_R_to_U(ruIndex, rId, &Hap_uId, &is_Unitig); + if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; + if(Hap_uId != yUid) continue; + + v = xReads->a[k]>>32; + get_R_to_U(ruIndex, v>>1, &Hap_uId, &is_Unitig); + if(is_Unitig == 0 || Hap_uId == (uint32_t)-1) continue; + if(Hap_uId != xUid) continue; + if((uint32_t)(position_index[v>>1]) != k) continue; + + w = (yReads->a[(uint32_t)(position_index[rId])])>>32; + + v_dir = ((t_f.ul>>32)==v)?1:0; + w_dir = (t_f.v == w)?1:0; + if(rev == 0 && v_dir != w_dir) continue; + if(rev == 1 && v_dir == w_dir) continue; + if(dir == v_dir) continue; + + /****************************may have bugs********************************/ + offset = (uint32_t)(position_index[rId]); + if(offset < yBegIndex || offset > yEndIndex) continue; + /****************************may have bugs********************************/ + + /************************get reverse edge*************************/ + index = get_specific_overlap(&(reverse_sources[Get_tn(*h)]), Get_tn(*h), Get_qn(*h)); + if(index == -1) continue; + h = &(reverse_sources[Get_tn(*h)].buffer[index]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(st->del || read_g->seq[Get_tn(*h)].del) continue; + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t_r); + if(r < 0) continue; + /************************get reverse edge*************************/ + + tmp = get_xy_pos(read_g, &t_f, v, w, xReads->len, yReads->len, position_index, &(t_f.el)); + if(((tmp>>32) == (uint32_t)-1) || (((uint32_t)tmp) == (uint32_t)-1)) continue; + + t_offset.Off = tmp; + t_offset.x = t_f; + t_offset.weight = 1; + kv_push(asg_arc_t_offset, u_buffer->a, t_offset); + + } + } + + if(u_buffer->a.n == 0) return; + + qsort(u_buffer->a.a, u_buffer->a.n, sizeof(asg_arc_t_offset), cmp_hap_alignment_chaining); + + for (k = 1, m = 1; k < (long long)u_buffer->a.n; k++) + { + if(u_buffer->a.a[m-1].Off == u_buffer->a.a[k].Off) + { + u_buffer->a.a[m-1].weight += u_buffer->a.a[k].weight; + if(u_buffer->a.a[k].x.ol > u_buffer->a.a[m-1].x.ol) + { + u_buffer->a.a[m-1].x = u_buffer->a.a[k].x; + } + continue; + } + u_buffer->a.a[m] = u_buffer->a.a[k]; + m++; + } + u_buffer->a.n = m; + + quick_LIS(u_buffer->a.a, u_buffer->a.n, tailIndex, prevIndex); + + if(tailIndex->a.n == 0) return; + + if(dir == 0) + { + for (k = 0; k < (long long)tailIndex->a.n; k++) + { + v = u_buffer->a.a[tailIndex->a.a[k]].x.v>>1; + w = u_buffer->a.a[tailIndex->a.a[k]].x.ul>>33; + index = get_specific_overlap(&(reverse_sources[v]), v, w); + if(index == -1) continue; + h = &(reverse_sources[v].buffer[index]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(st->del || read_g->seq[Get_tn(*h)].del) continue; + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t_r); + if(r < 0) continue; + + (*reture_t_f) = u_buffer->a.a[tailIndex->a.a[k]].x; + (*reture_t_r) = t_r; + return; + } + } + else + { + for (k = tailIndex->a.n-1; k >= 0; k--) + { + v = u_buffer->a.a[tailIndex->a.a[k]].x.v>>1; + w = u_buffer->a.a[tailIndex->a.a[k]].x.ul>>33; + index = get_specific_overlap(&(reverse_sources[v]), v, w); + if(index == -1) continue; + h = &(reverse_sources[v].buffer[index]); + sq = &(coverage_cut[Get_qn(*h)]); + st = &(coverage_cut[Get_tn(*h)]); + if(st->del || read_g->seq[Get_tn(*h)].del) continue; + r = ma_hit2arc(h, sq->e - sq->s, st->e - st->s, max_hang, + asm_opt.max_hang_rate, min_ovlp, &t_r); + if(r < 0) continue; + + (*reture_t_f) = u_buffer->a.a[tailIndex->a.a[k]].x; + (*reture_t_r) = t_r; + return; + } + } +} + + +void fill_unitig(uint64_t* buffer, uint32_t bufferLen, asg_t* read_g, kvec_asg_arc_t_warp* edge, +uint32_t is_circle, uint64_t* rLen) +{ + uint32_t i, k, totalLen, v, w, nv, l; + asg_arc_t *av = NULL; + (*rLen) = totalLen = 0; + for (i = 0; i < bufferLen - 1; i++) + { + v = (uint64_t)(buffer[i])>>32; + w = (uint64_t)(buffer[i + 1])>>32; + av = asg_arc_a(read_g, v); + nv = asg_arc_n(read_g, v); + l = 0; + + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + l = asg_arc_len(av[k]); + break; + } + } + + if(k == nv) + { + for (k = 0; k < edge->a.n; k++) + { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) + { + l = asg_arc_len(edge->a.a[k]); + break; + } + } + + if(k == edge->a.n) + { + fprintf(stderr, "####ERROR1-fill: i: %u, v>>1: %u, v&1: %u, w>>1: %u, w&1: %u\n", + i, v>>1, v&1, w>>1, w&1); + } + } + + + + buffer[i] = v; buffer[i] = buffer[i]<<32; buffer[i] = buffer[i] | (uint64_t)(l); + totalLen += l; + } + + if(i < bufferLen) + { + if(is_circle) + { + v = (uint64_t)(buffer[i])>>32; + w = (uint64_t)(buffer[0])>>32; + av = asg_arc_a(read_g, v); + nv = asg_arc_n(read_g, v); + l = 0; + + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + l = asg_arc_len(av[k]); + break; + } + } + + if(k == nv) + { + for (k = 0; k < edge->a.n; k++) + { + if(edge->a.a[k].del) continue; + if((edge->a.a[k].ul>>32) == v && edge->a.a[k].v == w) + { + l = asg_arc_len(edge->a.a[k]); + break; + } + } + + if(k == edge->a.n) + { + fprintf(stderr, "####ERROR2-fill: i: %u, v>>1: %u, v&1: %u, w>>1: %u, w&1: %u\n", + i, v>>1, v&1, w>>1, w&1); + } + } + + buffer[i] = v; buffer[i] = buffer[i]<<32; buffer[i] = buffer[i] | (uint64_t)(l); + totalLen += l; + } + else + { + v = (uint64_t)(buffer[i])>>32; + l = read_g->seq[v>>1].len; + buffer[i] = v; + buffer[i] = buffer[i]<<32; + buffer[i] = buffer[i] | (uint64_t)(l); + totalLen += l; + } + } + + (*rLen) = totalLen; + +} + +void collect_trans_purge_cov(hap_cov_t *cov, ma_ug_t *ug, hap_overlaps* x, uint32_t is_keep_X) +{ + if(ug->u.a[x->xUid].n == 0 || ug->u.a[x->yUid].n == 0) return; + uint64_t *pri = NULL, pri_n, *aux = NULL, aux_n, i, rId, uCov = 0, uLen = 0; + + if(is_keep_X) + { + pri = ug->u.a[x->xUid].a + x->x_beg_id; + pri_n = x->x_end_id - x->x_beg_id; + + aux = ug->u.a[x->yUid].a + x->y_beg_id; + aux_n = x->y_end_id - x->y_beg_id; + } + else + { + pri = ug->u.a[x->yUid].a + x->y_beg_id; + pri_n = x->y_end_id - x->y_beg_id; + + aux = ug->u.a[x->xUid].a + x->x_beg_id; + aux_n = x->x_end_id - x->x_beg_id; + } + + + uCov = uLen = 0; + for (i = 0; i < aux_n; i++) + { + rId = aux[i]>>33; + uCov += cov->cov[rId]; + } + + for (i = 0; i < pri_n; i++) + { + rId = pri[i]>>33; + uLen += cov->read_g->seq[rId].len; + } + + uCov = (uLen == 0? 0 : uCov / uLen); + + + for (i = 0; i < pri_n; i++) + { + rId = pri[i]>>33; + cov->cov[rId] += (uCov * cov->read_g->seq[rId].len); + } +} + + +void collect_trans_purge_joint_cov(hap_cov_t *cov, ma_ug_t *ug, hap_overlaps* x) +{ + if(ug->u.a[x->xUid].n == 0 || ug->u.a[x->yUid].n == 0) return; + uint64_t *a[2], a_n[2], uCov[2], uLen[2], uDepth[2], i, rId; + + a[0] = ug->u.a[x->xUid].a + x->x_beg_id; + a_n[0] = x->x_end_id - x->x_beg_id; + uCov[0] = uLen[0] = 0; + for (i = 0; i < a_n[0]; i++) + { + rId = a[0][i]>>33; + uCov[0] += cov->cov[rId]; + uLen[0] += cov->read_g->seq[rId].len; + } + + a[1] = ug->u.a[x->yUid].a + x->y_beg_id; + a_n[1] = x->y_end_id - x->y_beg_id; + uCov[1] = uLen[1] = 0; + for (i = 0; i < a_n[1]; i++) + { + rId = a[1][i]>>33; + uCov[1] += cov->cov[rId]; + uLen[1] += cov->read_g->seq[rId].len; + } + + uDepth[0] = (uLen[0] == 0? 0 : uCov[1] / uLen[0]); + uDepth[1] = (uLen[1] == 0? 0 : uCov[0] / uLen[1]); + + for (i = 0; i < a_n[0]; i++) + { + rId = a[0][i]>>33; + cov->cov[rId] += (uDepth[0] * cov->read_g->seq[rId].len); + } + + for (i = 0; i < a_n[1]; i++) + { + rId = a[1][i]>>33; + cov->cov[rId] += (uDepth[1] * cov->read_g->seq[rId].len); + } +} + + + +void purge_merge(asg_t *purge_g, ma_ug_t *ug, hap_overlaps_list* all_ovlp, buf_t* b_0, +R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, asg_t *read_g, +uint64_t* position_index, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, +kvec_t_i32_warp* prevIndex, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* edge, uint8_t* visit, +hap_cov_t *cov) +{ + uint32_t i, nv, k, v, w, x_beg_index, x_end_index, y_beg_index, y_end_index, cut_beg, cut_end, begIndex, endIndex, keepUid; + hap_overlaps *x = NULL/**, *y = NULL**/; + ma_utg_t *xReads = NULL, *yReads = NULL; + asg_arc_t t_forward, t_backward; + asg_arc_t *av = NULL; + kvec_t(uint64_t) buffer; + uint64_t totalLen; + int index = 0; + i = 0; + while (i < b_0->b.n) + { + cut_beg = 0; cut_end = (uint32_t)-1; + kv_init(buffer); + /********************for the first node********************/ + v = b_0->b.a[i]; + keepUid = v>>1; + xReads = &(ug->u.a[v>>1]); + if(v&1) + { + for (k = 0; k < xReads->n; k++) + { + kv_push(uint64_t, buffer, (xReads->a[xReads->n - k - 1])^(uint64_t)(0x100000000)); + } + } + else + { + for (k = 0; k < xReads->n; k++) + { + kv_push(uint64_t, buffer, xReads->a[k]); + } + } + cut_beg = 0; cut_end = xReads->n - 1; + i++; + /********************for the first node********************/ + + + for (; i < b_0->b.n; i++) + { + ///x = y = NULL; + x = NULL; + + v = b_0->b.a[i-1]; + w = b_0->b.a[i]; + + + index = get_specific_hap_overlap(&(all_ovlp->x[v>>1]), v>>1, w>>1); + x = &(all_ovlp->x[v>>1].a.a[index]); + + + + xReads = &(ug->u.a[v>>1]); + yReads = &(ug->u.a[w>>1]); + + begIndex = x->x_beg_id; + if(cut_beg > begIndex) begIndex = cut_beg; + + endIndex = x->x_end_id-1; + if(cut_end < endIndex) endIndex = cut_end; + + get_node_boundary_advance(ruIndex, reverse_sources, coverage_cut, read_g, position_index, max_hang, + min_ovlp, xReads, yReads, v>>1, w>>1, begIndex, endIndex, x->y_beg_id, x->y_end_id-1, v&1, + x->rev, u_buffer, tailIndex, prevIndex, &t_forward, &t_backward); + + if(t_forward.del || t_backward.del) break; + + kv_push(asg_arc_t, edge->a, t_forward); + kv_push(asg_arc_t, edge->a, t_backward); + + x_beg_index = 0; x_end_index = xReads->n - 1; + y_beg_index = 0; y_end_index = yReads->n - 1; + + if((v&1) == 0) + { + x_end_index = (uint32_t)position_index[t_forward.ul>>33]; + buffer.n = buffer.n - (cut_end - x_end_index); + } + else + { + x_beg_index = (uint32_t)position_index[t_forward.ul>>33]; + buffer.n = buffer.n - (x_beg_index - cut_beg); + } + + if((w&1) == 1) + { + y_end_index = (uint32_t)position_index[t_forward.v>>1]; + } + else + { + y_beg_index = (uint32_t)position_index[t_forward.v>>1]; + } + + cut_beg = y_beg_index; + cut_end = y_end_index; + + if((w&1) == 1) + { + for (k = y_end_index; k >= y_beg_index; k--) + { + kv_push(uint64_t, buffer, (yReads->a[k])^(uint64_t)(0x100000000)); + if(k==0) break; + } + } + else + { + for (k = y_beg_index; k <= y_end_index; k++) + { + kv_push(uint64_t, buffer, yReads->a[k]); + } + } + + purge_g->seq[w>>1].c = ALTER_LABLE; + if(cov) collect_trans_purge_joint_cov(cov, ug, x); + + // if(buffer.n > 1) + // { + // for (k = 0; k < buffer.n - 1; k++) + // { + // if((buffer.a[k]>>32) == 854769 && (buffer.a[k+1]>>32) == 64486) + // { + // fprintf(stderr, "+++++++v: %u, w: %u, xReads->n: %u, yReads->n: %u\n", + // v, w, xReads->n, yReads->n); + // fprintf(stderr, "x->rev: %u, x->x_beg_id: %u, x->x_end_id: %u, x->y_beg_id: %u, x->y_end_id: %u\n", + // x->rev, x->x_beg_id, x->x_end_id, x->y_beg_id, x->y_end_id); + // fprintf(stderr, "t_forward.ul>>32: %u, t_forward.v: %u, y_beg_index: %u, y_end_index: %u\n", + // t_forward.ul>>32, t_forward.v, y_beg_index, y_end_index); + // fprintf(stderr, "type: %u, x->x_beg_pos: %u, x->x_end_pos: %u, xReads->len: %u\n", + // x->type, x->x_beg_pos, x->x_end_pos, xReads->len); + // fprintf(stderr, "x->y_beg_pos: %u, x->y_end_pos: %u, yReads->len: %u\n", + // x->y_beg_pos, x->y_end_pos, yReads->len); + // } + // } + // } + } + + // fprintf(stderr, "+keepUid: %u, i: %u, b_0->b.n: %u, buffer.n: %u\n", + // keepUid, i, (uint32_t)b_0->b.n, (uint32_t)buffer.n); + fill_unitig(buffer.a, buffer.n, read_g, edge, 0, &totalLen); + ///fprintf(stderr, "-keepUid: %u\n", keepUid); + + xReads = &(ug->u.a[keepUid]); + free(xReads->a); + xReads->a = buffer.a; + xReads->n = buffer.n; + xReads->m = buffer.m; + xReads->len = totalLen; + xReads->circ = 0; + if(xReads->start != (xReads->a[0]>>32)) + { + xReads->start = xReads->a[0]>>32; + v = (keepUid<<1)+1; + av = asg_arc_a(ug->g, v); + nv = asg_arc_n(ug->g, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + asg_arc_del(ug->g, av[k].ul>>32, av[k].v, 1); + asg_arc_del(ug->g, av[k].v^1, av[k].ul>>32^1, 1); + } + } + + if(xReads->end != ((xReads->a[xReads->n-1]>>32)^1)) + { + xReads->end = ((xReads->a[xReads->n-1]>>32)^1); + v = (keepUid<<1); + av = asg_arc_a(ug->g, v); + nv = asg_arc_n(ug->g, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + asg_arc_del(ug->g, av[k].ul>>32, av[k].v, 1); + asg_arc_del(ug->g, av[k].v^1, av[k].ul>>32^1, 1); + } + } + } + + for (i = 0; i < b_0->b.n; i++) + { + v = b_0->b.a[i]; + visit[v>>1] = 1; + if(purge_g->seq[v>1].c != ALTER_LABLE) continue; + asg_seq_drop(purge_g, v>1); + } +} + +void print_het_ovlp(p_g_t *pg, ma_ug_t *ug, hap_overlaps_list* ha, double filter_rate) +{ + uint32_t v, i, k, n_vtx = pg->pg_h_lev->n_seq * 2, nv, qn, qs, qe, tn, ts, te, as, ae, occ, ovlp, hetLen, homLen; + asg_arc_t *av = NULL; + hap_overlaps *x = NULL; + p_node_t *a = NULL; + int index; + for (v = 0; v < n_vtx; v++) + { + av = asg_arc_a(pg->pg_h_lev, v); + nv = asg_arc_n(pg->pg_h_lev, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + index = get_specific_hap_overlap(&(ha->x[av[i].ul>>33]), av[i].ul>>33, av[i].v>>1); + if(index == -1) fprintf(stderr, "ERROR\n"); + x = &(ha->x[av[i].ul>>33].a.a[index]); + + qn = x->xUid; + qs = x->x_beg_pos; + qe = x->x_end_pos - 1; + get_p_nodes(pg, &a, &occ, qn); + for (k = 0, hetLen = 0, homLen = 0; k < occ; k++) + { + as = a[k].baseBeg; + ae = a[k].baseEnd; + ovlp = ((MIN(qe, ae) >= MAX(qs, as))? MIN(qe, ae) - MAX(qs, as) + 1 : 0); + if(homLen + hetLen > 0 && ovlp == 0) break; + if(ovlp == 0) continue; + if(a[k].h_status == N_HET) + { + homLen += ovlp; + } + else if(asm_opt.polyploidy <= 2 && (a[k].h_status&P_HET)) + { + homLen += ovlp; + } + else + { + hetLen += ovlp; + } + } + + if(hetLen <= ((hetLen + homLen) * filter_rate)) + { + ///all_ovlp->x[uId].a.a[i].status = DELETE; + fprintf(stderr, "********XY********\n"); + print_hap_paf(ug, x); + } + + + tn = x->yUid; + ts = x->y_beg_pos; + te = x->y_end_pos - 1; + get_p_nodes(pg, &a, &occ, tn); + for (k = 0, hetLen = 0, homLen = 0; k < occ; k++) + { + as = a[k].baseBeg; + ae = a[k].baseEnd; + ovlp = ((MIN(te, ae) >= MAX(ts, as))? MIN(te, ae) - MAX(ts, as) + 1 : 0); + if(homLen + hetLen > 0 && ovlp == 0) break; + if(ovlp == 0) continue; + if(a[k].h_status == N_HET) + { + homLen += ovlp; + } + else if(asm_opt.polyploidy <= 2 && (a[k].h_status&P_HET)) + { + homLen += ovlp; + } + else + { + hetLen += ovlp; + } + } + + if(hetLen <= ((hetLen + homLen) * filter_rate)) + { + ///all_ovlp->x[uId].a.a[i].status = DELETE; + fprintf(stderr, "********YX********\n"); + print_hap_paf(ug, x); + } + } + } + + for (v = 0; v < ha->num; v++) + { + for (i = 0; i < ha->x[v].a.n; i++) + { + if(ha->x[v].a.a[i].status == DELETE) + { + x = &(ha->x[v].a.a[i]); + + qn = x->xUid; + qs = x->x_beg_pos; + qe = x->x_end_pos - 1; + get_p_nodes(pg, &a, &occ, qn); + for (k = 0, hetLen = 0, homLen = 0; k < occ; k++) + { + as = a[k].baseBeg; + ae = a[k].baseEnd; + ovlp = ((MIN(qe, ae) >= MAX(qs, as))? MIN(qe, ae) - MAX(qs, as) + 1 : 0); + if(homLen + hetLen > 0 && ovlp == 0) break; + if(ovlp == 0) continue; + if(a[k].h_status == N_HET) + { + homLen += ovlp; + } + else if(asm_opt.polyploidy <= 2 && (a[k].h_status&P_HET)) + { + homLen += ovlp; + } + else + { + hetLen += ovlp; + } + } + + if(hetLen <= ((hetLen + homLen) * filter_rate)) + { + fprintf(stderr, "********C(X)********hetLen-%u, homLen-%u\n", hetLen, homLen); + print_hap_paf(ug, x); + } + + + tn = x->yUid; + ts = x->y_beg_pos; + te = x->y_end_pos - 1; + get_p_nodes(pg, &a, &occ, tn); + for (k = 0, hetLen = 0, homLen = 0; k < occ; k++) + { + as = a[k].baseBeg; + ae = a[k].baseEnd; + ovlp = ((MIN(te, ae) >= MAX(ts, as))? MIN(te, ae) - MAX(ts, as) + 1 : 0); + if(homLen + hetLen > 0 && ovlp == 0) break; + if(ovlp == 0) continue; + if(a[k].h_status == N_HET) + { + homLen += ovlp; + } + else if(asm_opt.polyploidy <= 2 && (a[k].h_status&P_HET)) + { + homLen += ovlp; + } + else + { + hetLen += ovlp; + } + } + + if(hetLen <= ((hetLen + homLen) * filter_rate)) + { + fprintf(stderr, "********C(Y)********hetLen-%u, homLen-%u\n", hetLen, homLen); + print_hap_paf(ug, x); + } + } + } + } +} + +void link_unitigs(asg_t *purge_g, ma_ug_t *ug, hap_overlaps_list* all_ovlp, +R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, asg_t *read_g, +uint64_t* position_index, kvec_asg_arc_t_offset* u_buffer, kvec_t_i32_warp* tailIndex, +kvec_t_i32_warp* prevIndex, int max_hang, int min_ovlp, kvec_asg_arc_t_warp* edge, uint8_t* visit, +hap_cov_t *cov) +{ + uint32_t v, n_vtx = purge_g->n_seq * 2, beg, end; + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + buf_t b_0; + memset(&b_0, 0, sizeof(buf_t)); + memset(visit, 0, purge_g->n_seq); + for (v = 0; v < n_vtx; ++v) + { + if(purge_g->seq[v>>1].c == ALTER_LABLE || purge_g->seq[v>>1].del || visit[v>>1]) continue; + if(get_real_length(purge_g, v, NULL) != 1) continue; + if(get_real_length(purge_g, v^1, NULL) != 0) continue; + + beg = v; + b_0.b.n = 0; + if(get_unitig(purge_g, NULL, beg, &end, &nodeLen, &baseLen, &max_stop_nodeLen, + &max_stop_baseLen, 1, &b_0) == LOOP) + { + continue; + } + + ///if(cov->link) collect_reverse_unitigs_purge(&b_0, cov->link, ug, all_ovlp); + purge_merge(purge_g, ug, all_ovlp, &b_0, ruIndex, reverse_sources, coverage_cut, + read_g, position_index, u_buffer, tailIndex, prevIndex,max_hang, min_ovlp, edge, visit, cov); + } + free(b_0.b.a); +} + +void print_all_purge_ovlp(ma_ug_t *ug, hap_overlaps_list* all_ovlp, const char* cmd) +{ + fprintf(stderr, "\n%s--->ug->u.n: %u\n", cmd, (uint32_t)ug->u.n); + uint32_t v, uId, i; + for (v = 0; v < all_ovlp->num; v++) + { + uId = v; + for (i = 0; i < all_ovlp->x[uId].a.n; i++) + { + print_hap_paf(ug, &(all_ovlp->x[uId].a.a[i])); + } + } + +} + +inline int get_available_cnt(asg_t *g, uint32_t v, uint8_t* del, asg_arc_t* v_s) +{ + //v has direction + if(del && del[v>>1]) return 0; + uint32_t i, kv = 0; + asg_arc_t *av = asg_arc_a(g, v); + uint32_t nv = asg_arc_n(g, v); + + for (i = 0, kv = 0; i < nv; i++) + { + if(!av[i].del) + { + if(del && del[av[i].v>>1]) continue; + if(v_s) v_s[kv] = av[i]; + kv++; + } + } + + return kv; +} + +long long get_specific_contig_length(asg_t *g, uint8_t *del) +{ + asg_cleanup(g); + uint32_t v, n_vtx = g->n_seq * 2, q_occ; + uint8_t *mark = NULL; + ///is a queue + //kdq_t(uint64_t) *q; + ///each node has two directions + //q = kdq_init(uint64_t); + + + mark = (uint8_t*)calloc(n_vtx, 1); + + long long totalLen = 0; + for (v = 0; v < n_vtx; ++v) + { + uint32_t w, x, l, start, end, len; + asg_arc_t arc; + if (g->seq[v>>1].del || mark[v]) continue; + if (get_available_cnt(g, v, del, NULL) == 0 && get_available_cnt(g, (v^1), del, NULL) != 0) continue; + if (del[v>>1]) continue; + + mark[v] = 1; + //q->count = 0, start = v, end = v^1, len = 0; + q_occ =0, start = v, end = v^1, len = 0; + // forward + w = v; + + + while (1) + { + /** + * w----->x + * w<-----x + * that means the only suffix of w is x, and the only prefix of x is w + **/ + if (get_available_cnt(g, w, del, NULL) != 1) break; + get_available_cnt(g, w, del, &arc); + x = arc.v; // w->x + if (get_available_cnt(g, x^1, del, NULL) != 1) break; + + /** + * another direction of w would be marked as used (since w has been used) + **/ + mark[x] = mark[w^1] = 1; + ///l is the edge length, instead of overlap length + ///note: edge length is different with overlap length + ///l = asg_arc_len(arc_first(g, w)); + get_available_cnt(g, w, del, &arc); + l = ((uint32_t)((arc).ul)); + //kdq_push(uint64_t, q, (uint64_t)w<<32 | l); + q_occ++; + end = x^1, len += l; + w = x; + if (x == v) break; + } + + + //if (start != (end^1) || kdq_size(q) == 0) { // linear unitig + if (start != (end^1) || q_occ == 0) { // linear unitig + ///length of seq, instead of edge + l = g->seq[end>>1].len; + //kdq_push(uint64_t, q, (uint64_t)(end^1)<<32 | l); + q_occ++; + len += l; + } else { // circular unitig + start = end = UINT32_MAX; + goto add_unitig; // then it is not necessary to do the backward + } + + // backward + x = v; + while (1) { // similar to forward but not the same + if (get_available_cnt(g, x^1, del, NULL) != 1) break; + get_available_cnt(g, x^1, del, &arc); + w = arc.v ^ 1; + if (get_available_cnt(g, w, del, NULL) != 1) break; + mark[x] = mark[w^1] = 1; + ///l = asg_arc_len(arc_first(g, w)); + get_available_cnt(g, w, del, &arc); + l = ((uint32_t)((arc).ul)); + ///w is the seq id + direction, l is the length of edge + ///push element to the front of a queue + //kdq_unshift(uint64_t, q, (uint64_t)w<<32 | l); + q_occ++; + + start = w, len += l; + x = w; + } + + + add_unitig: + if (start != UINT32_MAX) mark[start] = mark[end] = 1; + totalLen += len; + } + //kdq_destroy(uint64_t, q); + free(mark); + return totalLen; +} + + +void get_contig_length(ma_ug_t *ug, asg_t *g, uint64_t* primaryLen, uint64_t* alterLen) +{ + uint8_t *del = (uint8_t *)malloc(sizeof(uint8_t)*g->n_seq); + uint32_t v, k; + ma_utg_t* u = NULL; + memset(del, 1, g->n_seq); + (*primaryLen) = (*alterLen) = 0; + + for (v = 0; v < ug->g->n_seq; ++v) + { + if(ug->g->seq[v].del) continue; + if(ug->g->seq[v].c == ALTER_LABLE) continue; + u = &(ug->u.a[v]); + if(u->m == 0) continue; + for (k = 0; k < u->n; k++) + { + del[u->a[k]>>33] = 0; + } + } + (*primaryLen) = get_specific_contig_length(g, del); + + + for (v = 0; v < g->n_seq; ++v) + { + del[v] = 1 - del[v]; + } + + (*alterLen) = get_specific_contig_length(g, del); + + free(del); +} + + +int if_ploid_sample(ma_ug_t *ug, asg_t *read_g, R_to_U* ruIndex, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, ma_sub_t* coverage_cut, +hap_alignment_struct_pip* hap_buf, hap_overlaps_list* all_ovlp, hap_overlaps_list* back_all_ovlp, +uint32_t minLen, double purge_threshold) +{ + asg_t* nsg = ug->g; + uint64_t v, k, total_bases = 0, alter_bases = 0, primary_bases = 0, purge_bases = 0; + kt_for(asm_opt.thread_num, hap_alignment_advance_worker, hap_buf, nsg->n_seq); + + filter_hap_overlaps_by_length(all_ovlp, minLen); + normalize_hap_overlaps_advance(all_ovlp, back_all_ovlp, ug, read_g, reverse_sources, ruIndex); + + get_contig_length(ug, read_g, &primary_bases, &alter_bases); + total_bases = primary_bases + alter_bases; + // fprintf(stderr, "primary_bases: %lu\n", primary_bases); + // fprintf(stderr, "alter_bases: %lu\n", alter_bases); + // fprintf(stderr, "total_bases: %lu\n", total_bases); + + + for (v = 0; v < all_ovlp->num; v++) + { + for (k = 0; k < all_ovlp->x[v].a.n; k++) + { + purge_bases += all_ovlp->x[v].a.a[k].x_end_pos - all_ovlp->x[v].a.a[k].x_beg_pos; + } + } + purge_bases = purge_bases/2; + ///fprintf(stderr, "purge_bases: %lu\n", purge_bases); + alter_bases = alter_bases + purge_bases; + ///fprintf(stderr, "new alter_bases: %lu\n", alter_bases); + + + for (v = 0; v < all_ovlp->num; v++) + { + all_ovlp->x[v].a.n = 0; + } + + for (v = 0; v < back_all_ovlp->num; v++) + { + back_all_ovlp->x[v].a.n = 0; + } + + if(alter_bases > total_bases * purge_threshold) return 1; + return 0; +} + +int cmp_chain_score(const void * a, const void * b) +{ + if((*(hap_overlaps*)a).score < (*(hap_overlaps*)b).score) return 1; + if((*(hap_overlaps*)a).score > (*(hap_overlaps*)b).score) return -1; + + return 0; +} +long long get_ovlp_len(long long a_beg, long long a_end, long long b_beg, long long b_end) +{ + long long ovlp = (long long)(MIN(a_end, b_end)) - (long long)(MAX(a_beg, b_beg)) + 1; + return ovlp <= 0? 0 : ovlp; +} +void sort_hap_chain(hap_overlaps_list* all_ovlp) +{ + hap_overlaps *x = NULL, *p = NULL; + uint32_t v, i, k, uId; + long long ovlp, xLen, pLen; + kvec_t(hap_overlaps) pri; kv_init(pri); + kvec_t(hap_overlaps) alt; kv_init(alt); + + for (v = 0; v < all_ovlp->num; v++) + { + uId = v; + qsort(all_ovlp->x[uId].a.a, all_ovlp->x[uId].a.n, sizeof(hap_overlaps), cmp_chain_score); + pri.n = alt.n = 0; + for (i = 0; i < all_ovlp->x[uId].a.n; i++) + { + x = &(all_ovlp->x[uId].a.a[i]); + xLen = x->x_end_pos - x->x_beg_pos; + for (k = 0; k < pri.n; k++) + { + p = &(pri.a[k]); + pLen = p->x_end_pos - p->x_beg_pos; + ovlp = get_ovlp_len(x->x_beg_pos, x->x_end_pos-1, p->x_beg_pos, p->x_end_pos-1); + if(ovlp == 0) continue; + if(ovlp >= (MIN(xLen, pLen))*0.5) break; + } + + if(k < pri.n) + { + x->xUid = k; + kv_push(hap_overlaps, alt, *x); + } + else + { + kv_push(hap_overlaps, pri, *x); + } + } + + } + + kv_destroy(pri); kv_destroy(alt); +} + +void remove_contained_haplotig(hap_overlaps_list* all_ovlp, ma_ug_t *ug, asg_t* nsg, asg_t *purge_g, hap_cov_t *cov) +{ + uint32_t v, i, uId, xUid; + hap_overlaps *p = NULL; + for (v = 0; v < all_ovlp->num; v++) + { + uId = v; p = NULL; + for (i = 0; i < all_ovlp->x[uId].a.n; i++) + { + if(p == NULL || p->score < all_ovlp->x[uId].a.a[i].score) + { + p = &(all_ovlp->x[uId].a.a[i]); + } + } + + for (i = 0; i < all_ovlp->x[uId].a.n; i++) + { + if(all_ovlp->x[uId].a.a[i].type == YCX) + { + if(!filter_secondary_chain(p->score, all_ovlp->x[uId].a.a[i].score, 0.95)) + { + continue; + } + + xUid = all_ovlp->x[uId].a.a[i].xUid; + + nsg->seq[xUid].c = ALTER_LABLE; + purge_g->seq[xUid].c = ALTER_LABLE; + purge_g->seq[xUid].del = 1; + + all_ovlp->x[uId].a.a[i].status = DELETE; + ///if(cov->link) collect_reverse_unitig_pair(cov->link, ug, &(all_ovlp->x[uId].a.a[i])); + collect_trans_purge_cov(cov, ug, &(all_ovlp->x[uId].a.a[i]), 0); + } + + ///print_hap_paf(ug, &(all_ovlp.x[uId].a.a[i])); + } + } + + // for (v = 0; v < all_ovlp.num; v++) + // { + // uId = v; + // for (i = 0; i < all_ovlp.x[uId].a.n; i++) + // { + // if(all_ovlp.x[uId].a.a[i].type == YCX) + // { + // nsg->seq[all_ovlp.x[uId].a.a[i].xUid].c = ALTER_LABLE; + // purge_g->seq[all_ovlp.x[uId].a.a[i].xUid].c = ALTER_LABLE; + // purge_g->seq[all_ovlp.x[uId].a.a[i].xUid].del = 1; + // all_ovlp.x[uId].a.a[i].status = DELETE; + // if(link) collect_reverse_unitig_pair(link, ug, &(all_ovlp.x[uId].a.a[i])); + // collect_trans_purge_cov(cov, ug, &(all_ovlp.x[uId].a.a[i]), 0); + // } + + // if(all_ovlp.x[uId].a.a[i].type == XCY) + // { + // nsg->seq[all_ovlp.x[uId].a.a[i].yUid].c = ALTER_LABLE; + // purge_g->seq[all_ovlp.x[uId].a.a[i].yUid].c = ALTER_LABLE; + // purge_g->seq[all_ovlp.x[uId].a.a[i].yUid].del = 1; + // all_ovlp.x[uId].a.a[i].status = DELETE; + // if(link) collect_reverse_unitig_pair(link, ug, &(all_ovlp.x[uId].a.a[i])); + // collect_trans_purge_cov(cov, ug, &(all_ovlp.x[uId].a.a[i]), 1); + // } + // ///print_hap_paf(ug, &(all_ovlp.x[uId].a.a[i])); + // } + // } +} + +void debug_p_g_t(p_g_t* pg, hap_cov_t *cov, asg_t *read_g) +{ + fprintf(stderr, "----------[M::%s]----------\n", __func__); + uint32_t i, offset, v, sid, eid, spos, epos, p_status, p_uid, occ; + p_node_t *t = NULL; + ma_utg_t *u = NULL; + p_node_t *a = NULL; + + for (v = 0; v < pg->ug->u.n; v++) + { + ///fprintf(stderr, "\nu->n: %u, uid: %u\n", (uint32_t)(pg->ug->u.a[v].n), v); + get_p_nodes(pg, &a, &occ, v); + for (i = 0; i < occ; i++) + { + if(a[i].c_ug_id != v) fprintf(stderr, "sbsbsbsbsb\n"); + ///fprintf(stderr, "sid: %u, eid: %u\n", a[i].nodeBeg, a[i].nodeEnd); + } + } + + + for (v = 0, p_status = (uint32_t)-1, p_uid = (uint32_t)-1; v < pg->pg_het_node.n; v++) + { + t = &(pg->pg_het_node.a[v]); + sid = t->nodeBeg; + eid = t->nodeEnd; + spos = t->baseBeg; + epos = t->baseEnd; + // fprintf(stderr, "sid: %u, eid: %u, spos: %u, epos: %u, t->b_ug_id: %u\n", + // sid, eid, spos, epos, (uint32_t)t->b_ug_id); + // fprintf(stderr, "pg->pg_het_node.n: %u\n", (uint32_t)pg->pg_het_node.n); + if(p_uid == t->c_ug_id && p_status == t->h_status) + { + fprintf(stderr, "ERROR-(-1)\n"); + } + p_status = t->h_status; + p_uid = t->c_ug_id; + + u = &(pg->ug->u.a[t->c_ug_id]); + ///fprintf(stderr, "u->n: %u, sid: %u, eid: %u\n", (uint32_t)u->n, sid, eid); + for (i = offset = 0; i < u->n; i++) + { + if(i == sid) + { + if(spos != offset) + { + fprintf(stderr, "ERROR-1\n"); + } + } + + if(i == eid) + { + if(epos != (offset+read_g->seq[u->a[i]>>33].len - 1)) + { + fprintf(stderr, "ERROR-2, real end: %u\n", + (uint32_t)(offset+read_g->seq[u->a[i]>>33].len - 1)); + } + } + offset += (uint32_t)u->a[i]; + if(i >= sid && i <= eid) + { + if(cov->t_ch->ir_het[u->a[i]>>33] != t->h_status) + { + fprintf(stderr, "ERROR-(-3): is_r_het: %u, h_status: %u\n", cov->t_ch->ir_het[u->a[i]>>33], t->h_status); + } + } + } + } +} + + +void print_p_g_t_interval(p_g_t* pg, hap_cov_t *cov) +{ + fprintf(stderr, "----------[M::%s]----------\n", __func__); + uint32_t i, v, sid, eid; + p_node_t *t = NULL; + ma_utg_t *u = NULL; + + for (v = 0; v < pg->pg_het_node.n; v++) + { + t = &(pg->pg_het_node.a[v]); + sid = t->nodeBeg; + eid = t->nodeEnd; + + u = &(pg->ug->u.a[t->c_ug_id]); + fprintf(stderr, "\nu->n=%u, sid=%u, eid=%u, h_status=%u\n", + (uint32_t)u->n, sid, eid, t->h_status); + for (i = sid; i <= eid; i++) + { + fprintf(stderr, "id:i:%u------>utg%.6ul\n", + (uint32_t)(u->a[i]>>33), (get_origin_uid(u->a[i]>>32, cov->t_ch, NULL, NULL)>>1)+1); + } + } + fprintf(stderr, "----------[M::%s]----------\n", __func__); +} + + +p_g_t *init_p_g_t(ma_ug_t *ug, hap_cov_t *cov, asg_t *read_g) +{ + uint32_t v, uId, k, l, offset, l_pos, g_beg_idx, occ/**, ovlp, tLen, zLen**/; + p_g_t *pg = NULL; CALLOC(pg, 1); + pg->ug = ug; + asg_t* nsg = pg->ug->g; + ma_utg_t *u = NULL; + p_node_t *t = NULL/**, *z = NULL**/; + ///asg_arc_t *e = NULL; + p_g_in_t *x = NULL; + ///pg->pg_het = asg_init(); + pg->pg_h_lev = asg_init(); + kv_init(pg->pg_het_node); + kv_init(pg->pg_h_lev_idx); + + for (v = 0; v < nsg->n_seq; v++) + { + uId = v; + if(nsg->seq[uId].del || nsg->seq[uId].c == ALTER_LABLE) + { + asg_seq_set(pg->pg_h_lev, uId, 0, 1); + pg->pg_h_lev->seq[uId].c = ALTER_LABLE; + continue; + } + + asg_seq_set(pg->pg_h_lev, uId, ug->u.a[uId].len, 0); + pg->pg_h_lev->seq[uId].c = PRIMARY_LABLE; + } + + // if(asm_opt.polyploidy <= 2) + // { + // for (v = 0; v < cov->t_ch->r_num; v++) + // { + // if(cov->t_ch->is_r_het[v]&P_HET) cov->t_ch->is_r_het[v] |= S_HET; + // } + // } + + for (v = 0; v < nsg->n_seq; v++) + { + uId = v; + if(nsg->seq[uId].del || nsg->seq[uId].c == ALTER_LABLE) continue; + + u = &(ug->u.a[uId]); + g_beg_idx = pg->pg_het_node.n; + ///fprintf(stderr, "\n+v: %u, pg->pg_het_node.n: %u\n", v, (uint32_t)pg->pg_het_node.n); + for (k = 1, l = 0, offset = 0, l_pos = 0; k <= u->n; ++k) + { + ///if (k == u->n || (!!cov->t_ch->is_r_het[u->a[k]>>33]) != (!!cov->t_ch->is_r_het[u->a[l]>>33])) + if (k == u->n || cov->t_ch->ir_het[u->a[k]>>33] != cov->t_ch->ir_het[u->a[l]>>33]) + { + kv_pushp(p_node_t, pg->pg_het_node, &t); + t->c_ug_id = uId; + t->h_status = cov->t_ch->ir_het[u->a[l]>>33]; + t->baseBeg = l_pos; + t->baseEnd = offset + read_g->seq[u->a[k-1]>>33].len - 1; + t->nodeBeg = l; + t->nodeEnd = k - 1; + ///if(t->b_ug_id == (uint32_t)-1) fprintf(stderr, "xxxx\n"); + ///asg_seq_set(pg->pg_het, pg->pg_het_node.n-1, t->baseEnd+1-t->baseBeg, 0); + ///fprintf(stderr, "l: %u, k: %u, u->n: %u, t->h_status: %u\n", l, k, u->n, t->h_status); + l = k; + l_pos = offset + (uint32_t)u->a[k-1]; + } + offset += (uint32_t)u->a[k-1]; + } + + occ = pg->pg_het_node.n - g_beg_idx; + kv_pushp(p_g_in_t, pg->pg_h_lev_idx, &x); + x->beg = g_beg_idx; x->occ = occ; + ///fprintf(stderr, "-v: %u, pg->pg_het_node.n: %u\n", v, (uint32_t)pg->pg_het_node.n); + + // if(occ > 1) + // { + // for (k = g_beg_idx; (k + 1) < pg->pg_het_node.n; ++k) + // { + // t = &(pg->pg_het_node.a[k]); tLen = t->baseEnd + 1 - t->baseBeg; + // z = &(pg->pg_het_node.a[k+1]); zLen = z->baseEnd + 1 - z->baseBeg; + + // ovlp = ((MIN(t->baseEnd, z->baseEnd) >= MAX(t->baseBeg, z->baseBeg))? + // MIN(t->baseEnd, z->baseEnd) - MAX(t->baseBeg, z->baseBeg) + 1 : 0); + + // e = asg_arc_pushp(pg->pg_het); + // e->ol = ovlp; + // e->ul = (k<<1); e->ul <<= 32; e->ul += (tLen - ovlp); + // e->v = ((k+1)<<1); e->del = 0; e->el = e->no_l_indel = e->strong = 1; + + // e = asg_arc_pushp(pg->pg_het); + // e->ol = ovlp; + // e->ul = ((k+1)<<1)+1; e->ul <<= 32; e->ul += (zLen - ovlp); + // e->v = (k<<1)+1; e->del = 0; e->el = e->no_l_indel = e->strong = 1; + // } + // } + } + ///asg_cleanup(pg->pg_het); + ///debug_p_g_t(pg, cov, read_g); + ///print_p_g_t_interval(pg, cov); + + return pg; +} + +void destory_p_g_t(p_g_t **pg) +{ + if(pg && (*pg)) + { + kv_destroy((*pg)->pg_het_node); + kv_destroy((*pg)->pg_h_lev_idx); + asg_destroy((*pg)->pg_het); + asg_destroy((*pg)->pg_h_lev); + free((*pg)); + (*pg) = NULL; + } +} + +void chain_origin_trans_uid_by_purge(hap_overlaps *x, ma_ug_t *ug, hap_cov_t *cov, uint64_t* position_index) +{ + uint32_t pri_uid, aux_uid, r_x, r_y; + hap_candidates hap_for, hap_rev, *hap = NULL; + long long x_pos_beg, x_pos_end, y_pos_beg, y_pos_end; + + Get_rev(hap_for) = x->rev; + Get_x_beg(hap_for) = x->x_beg_id; Get_x_end(hap_for) = x->x_end_id - 1; + Get_y_beg(hap_for) = x->y_beg_id; Get_y_end(hap_for) = x->y_end_id - 1; + r_x = determine_hap_overlap_type_advance(&hap_for, &(ug->u.a[x->xUid]), &(ug->u.a[x->yUid]), + cov->ruIndex, cov->reverse_sources, cov->coverage_cut, cov->read_g, position_index, + cov->max_hang, cov->min_ovlp, x->xUid, x->yUid, &(cov->u_buffer), &(cov->tailIndex), + &(cov->prevIndex), &x_pos_beg, &x_pos_end, &y_pos_beg, &y_pos_end); + + // if(r_x != (uint32_t)-1) + // { + // adjust_hap_overlaps_score(&(ug->u.a[x->xUid]), NULL, &(hap_for.score), + // x->xUid, x->yUid, x_pos_beg, x_pos_end); + // } + + + Get_rev(hap_rev) = x->rev; + Get_x_beg(hap_rev) = x->y_beg_id; Get_x_end(hap_rev) = x->y_end_id - 1; + Get_y_beg(hap_rev) = x->x_beg_id; Get_y_end(hap_rev) = x->x_end_id - 1; + r_y = determine_hap_overlap_type_advance(&hap_rev, &(ug->u.a[x->yUid]), &(ug->u.a[x->xUid]), + cov->ruIndex, cov->reverse_sources, cov->coverage_cut, cov->read_g, position_index, + cov->max_hang, cov->min_ovlp, x->yUid, x->xUid, &(cov->u_buffer), &(cov->tailIndex), + &(cov->prevIndex), &y_pos_beg, &y_pos_end, &x_pos_beg, &x_pos_end); + + // if(r_y != (uint32_t)-1) + // { + // adjust_hap_overlaps_score(&(ug->u.a[x->yUid]), NULL, &(hap_rev.score), + // x->yUid, x->xUid, y_pos_beg, y_pos_end); + // } + + if(r_x == (uint32_t)-1 && r_y == (uint32_t)-1) + { + fprintf(stderr, "ERROR-purge\n"); + return; + } + + Get_rev(hap_for) = x->rev; + Get_x_beg(hap_for) = x->x_beg_id; Get_x_end(hap_for) = x->x_end_id - 1; + Get_y_beg(hap_for) = x->y_beg_id; Get_y_end(hap_for) = x->y_end_id - 1; + + Get_rev(hap_rev) = x->rev; + Get_x_beg(hap_rev) = x->y_beg_id; Get_x_end(hap_rev) = x->y_end_id - 1; + Get_y_beg(hap_rev) = x->x_beg_id; Get_y_end(hap_rev) = x->x_end_id - 1; + + + if(r_x != (uint32_t)-1 && r_y == (uint32_t)-1) + { + pri_uid = x->xUid; aux_uid = x->yUid; hap = &hap_for; + } + else if(r_x == (uint32_t)-1 && r_y != (uint32_t)-1) + { + aux_uid = x->xUid; pri_uid = x->yUid; hap = &hap_rev; + } + else + { + if(hap_for.score >= hap_rev.score) + { + pri_uid = x->xUid; aux_uid = x->yUid; hap = &hap_for; + } + else + { + aux_uid = x->xUid; pri_uid = x->yUid; hap = &hap_rev; + } + } + + determine_hap_overlap_type_advance(hap, &(ug->u.a[pri_uid]), &(ug->u.a[aux_uid]), + cov->ruIndex, cov->reverse_sources, cov->coverage_cut, cov->read_g, position_index, + cov->max_hang, cov->min_ovlp, pri_uid, aux_uid, &(cov->u_buffer), &(cov->tailIndex), + &(cov->prevIndex), &x_pos_beg, &x_pos_end, &y_pos_beg, &y_pos_end); + + // adjust_hap_overlaps_score(&(ug->u.a[pri_uid]), NULL, &(hap->score), + // pri_uid, aux_uid, x_pos_beg, x_pos_end); + + uint64_t pri_len = ug->u.a[pri_uid].len, aux_len = ug->u.a[aux_uid].len; + pri_uid <<= 1; aux_uid <<= 1; aux_uid += hap->rev; + + // uint32_t i_n = cov->t_ch->k_trans.n, i; + + chain_origin_trans_uid_by_distance(cov, cov->read_g, &pri_uid, 1, x_pos_beg, &pri_len, + &aux_uid, 1, y_pos_beg, &aux_len, ug, RC_2, hap->score, __func__); + + // fprintf(stderr, "\nocc: %u\n", (uint32_t)(cov->t_ch->k_trans.n - i_n)); + // fprintf(stderr, "#s-utg%.6ul\t%u\t%u\td-utg%.6ul\t%u\t%u\trev(%u)\n", + // x->xUid+1, x->x_beg_pos, x->x_end_pos, x->yUid+1, x->y_beg_pos, x->y_end_pos, x->rev); + // for (i = i_n; i < cov->t_ch->k_trans.n; i++) + // { + // fprintf(stderr, "s-utg%.6ul\t%u\t%u\td-utg%.6ul\t%u\t%u\trev(%u)\n", + // cov->t_ch->k_trans.a[i].qn+1, cov->t_ch->k_trans.a[i].qs, cov->t_ch->k_trans.a[i].qe, + // cov->t_ch->k_trans.a[i].tn+1, cov->t_ch->k_trans.a[i].ts, cov->t_ch->k_trans.a[i].te, + // cov->t_ch->k_trans.a[i].rev); + // } +} + +void collect_purge_trans_cov(ma_ug_t *ug, hap_overlaps_list* ha, hap_cov_t *cov, uint64_t* position_index) +{ + uint32_t v, i; + hap_overlaps *x = NULL; + for (v = 0; v < ha->num; v++) + { + for (i = 0; i < ha->x[v].a.n; i++) + { + x = &(ha->x[v].a.a[i]); + if(x->yUid < x->xUid) continue; + chain_origin_trans_uid_by_purge(x, ug, cov, position_index); + } + } +} + +/** +typedef struct { + uint32_t qn, qs, qe; + uint32_t tn, ts, te; + uint32_t oid; + uint8_t rev; +}scg_hits; + +typedef struct { + scg_hits *a; + size_t n,m; + kvec_t(uint64_t) idx; +}scg_hits_v; + +#define scg_key_qtn(a) ((((uint64_t)(a).qn)<<32)|((uint64_t)(a).tn)) +KRADIX_SORT_INIT(scg_qtn, scg_hits, scg_key_qtn, 8) +#define scg_key_qts(a) ((((uint64_t)(a).qs)<<32)|((uint64_t)(a).ts)) +KRADIX_SORT_INIT(scg_qts, scg_hits, scg_key_qts, 8) +#define scg_key_qte(a) ((((uint64_t)(a).qe)<<32)|((uint64_t)(a).te)) +KRADIX_SORT_INIT(scg_qte, scg_hits, scg_key_qte, 8) +#define scg_key_rev(a) ((a).rev) +KRADIX_SORT_INIT(scg_rev, scg_hits, scg_key_rev, member_size(scg_hits, rev)) + +inline void rev_scg_hits(scg_hits *p, spg_t *scg) +{ + if(p->rev){ + uint32_t t; + p->ts = scg->ug->u.a[p->tn].len - p->ts - 1; + p->te = scg->ug->u.a[p->tn].len - (p->te - 1) - 1; + t = p->ts; p->ts = p->te; p->te = t; p->te++; + } +} + +#define arc_first(g, v) ((g)->arc[(g)->idx[(v)]>>32]) +scg_hits_v *get_scg_hits_v(scg_hits_v *vp, spg_t *scg) +{ + scg_hits_v *hh = NULL; CALLOC(hh, 1); + ma_utg_v *u = &(scg->ug->u); + uint32_t i, mn, *ma = NULL; + uint64_t offset, *idx = NULL; + + for (i = 0; i < scg->idx.n; i++) { + mn = (uint32_t)scg->idx.a[i]; + ma = scg->dst.a + (scg->idx.a[i]>>32); + } + + + + + return hh; +} + +void refine_scg(spg_t *scg, ma_ug_t *lug, hap_overlaps_list *ha, hap_cov_t *cov, uint64_t* position_index) +{ + scg_hits_v vp; kv_init(vp); + uint32_t v, i, k, st, c[2]; + hap_overlaps *x = NULL; + u_trans_t *z = NULL; + scg_hits *p = NULL; + + for (v = 0; v < cov->t_ch->k_trans.n; v++){ + z = &(cov->t_ch->k_trans.a[v]); + if(z->del) continue; + kv_pushp(scg_hits, vp, &p); + p->rev = z->rev; p->oid = (uint32_t)-1; + p->qn = z->qn; p->qs = z->qs; p->qe = z->qe; + p->tn = z->tn; p->ts = z->ts; p->te = z->te; + // rev_scg_hits(p, scg); + kv_pushp(scg_hits, vp, &p); + p->rev = z->rev; p->oid = (uint32_t)-1; + p->qn = z->tn; p->qs = z->ts; p->qe = z->te; + p->tn = z->qn; p->ts = z->qs; p->te = z->qe; + // rev_scg_hits(p, scg); + } + + for (v = 0; v < ha->num; v++){ + for (i = 0; i < ha->x[v].a.n; i++){ + x = &(ha->x[v].a.a[i]); + st = cov->t_ch->k_trans.n; + chain_origin_trans_uid_by_purge(x, lug, cov, position_index); + for (k = st; k < cov->t_ch->k_trans.n; k++){ + z = &(cov->t_ch->k_trans.a[k]); + if(z->del) continue; + kv_pushp(scg_hits, vp, &p); + p->rev = z->rev; p->oid = v; + p->qn = z->qn; p->qs = z->qs; p->qe = z->qe; + p->tn = z->tn; p->ts = z->ts; p->te = z->te; + // rev_scg_hits(p, scg); + kv_pushp(scg_hits, vp, &p); + p->rev = z->rev; p->oid = v; + p->qn = z->tn; p->qs = z->ts; p->qe = z->te; + p->tn = z->qn; p->ts = z->qs; p->te = z->qe; + // rev_scg_hits(p, scg); + } + cov->t_ch->k_trans.n = st; + } + } + + ///two scg_hits might be totally equal; must remove first + radix_sort_scg_qtn(vp.a, vp.a + vp.n); + for (st = 0, i = 1; i <= vp.n; ++i){ + if (i == vp.n || vp.a[i].qn != vp.a[st].qn || vp.a[i].tn != vp.a[st].tn){ + if(i - st > 1) radix_sort_scg_rev(vp.a+st, vp.a+i); + for (v = st, c[0] = c[1] = 0; v < i; v++) c[vp.a[v].rev]++; + if(c[0]>1) radix_sort_scg_qts(vp.a+st, vp.a+st+c[0]); + if(c[1]>1) radix_sort_scg_qts(vp.a+st+c[0], vp.a+st+c[0]+c[1]); + st = i; + } + } + for (st = 0, i = 1; i <= vp.n; ++i){ + if (i == vp.n || vp.a[i].rev != vp.a[st].rev || + vp.a[i].qn != vp.a[st].qn || vp.a[i].tn != vp.a[st].tn || + vp.a[i].qs != vp.a[st].qs || vp.a[i].ts != vp.a[st].ts) + { + if(i - st > 1) radix_sort_scg_qte(vp.a+st, vp.a+i); + st = i; + } + } + for (st = 0, i = 1, k = 0; i <= vp.n; ++i){ + if (i == vp.n || vp.a[i].rev != vp.a[st].rev || + vp.a[i].qn != vp.a[st].qn || vp.a[i].tn != vp.a[st].tn || + vp.a[i].qs != vp.a[st].qs || vp.a[i].ts != vp.a[st].ts || + vp.a[i].qe != vp.a[st].qe || vp.a[i].te != vp.a[st].te) + { + vp.a[k] = vp.a[st]; + k++; + st = i; + } + } + ///build idx + vp.n = k; kv_resize(uint64_t, vp.idx, scg->ug->u.n); vp.idx.n = scg->ug->u.n; + memset(vp.idx.a, 0, vp.idx.n*sizeof(uint64_t)); + for (st = 0, i = 1; i <= vp.n; ++i) + { + if (i == vp.n || vp.a[i].qn != vp.a[st].qn) + { + vp.idx.a[vp.a[st].qn] = (uint64_t)st << 32 | (i - st); + st = i; + } + } + + + kv_destroy(vp); kv_destroy(vp.idx); +} +**/ +uint32_t seed_uid(ma_utg_t *vu, uint64_t* ps_idx, R_to_U* ruIndex, ma_ug_t *rug) +{ + int64_t v_i, v, w, w_i, wb, we, vb, ve, k; + uint32_t uid, is_u; + ma_utg_t *wu = NULL; + for (v_i = 0; v_i < vu->n; v_i++) { + v = vu->a[v_i]>>32; + get_R_to_U(ruIndex, v>>1, &uid, &is_u); + if(is_u == 0 || uid == (uint32_t)-1 || ps_idx[v>>1] == (uint64_t)-1) continue; + w_i = (uint32_t)ps_idx[v>>1]; + wu = &(rug->u.a[uid]); + w = wu->a[w_i]>>32; + if((v>>1)!=(w>>1)) continue; + vb = 0; ve = vu->n; ///[vb, ve) + if(v == w){ ///[wb, we) + wb = w_i - v_i; + we = wb + vu->n; + if(wb < 0 || we > wu->n) continue; + for (k = 0; k < vu->n; k++){ + if((vu->a[k+vb]>>32) != (wu->a[k+wb]>>32)) break; + } + if(k >= vu->n) return uid; + } else { + wb = w_i + 1 - (ve - v_i); + we = wb + vu->n; + if(wb < 0 || we > wu->n) continue; + for (k = 0; k < vu->n; k++){ + if((vu->a[k+vb]>>32) != ((wu->a[we-k-1]>>32)^1)) break; + } + if(k >= vu->n) return uid; + } + } + return (uint32_t)-1; +} + +void filter_ovlp_vecs(hap_overlaps_list* ha, uint32_t *a, uint32_t a_n) +{ + uint32_t st, k, i, m, v, w; + int idx; + radix_sort_ru32(a, a + a_n); + for (st = 0, m = 0, k = 1; k <= a_n; k++){ + if(k == a_n || a[k] != a[st]){ + a[m++] = a[st]; + st = k; + } + } + a_n = m; + if(a_n < 2) return; + for (k = 0; k < a_n; k++){ + v = a[k]; + for (i = k+1; i < a_n; i++) { + w = a[i]; + idx = get_specific_hap_overlap(&(ha->x[v]), v, w); + if(idx != -1) ha->x[v].a.a[idx].status = DELETE; + idx = get_specific_hap_overlap(&(ha->x[w]), w, v); + if(idx != -1) ha->x[w].a.a[idx].status = DELETE; + } + } +} + +void filter_ovlp_scg(hap_overlaps_list* ha, uint64_t* ps_idx, R_to_U* ruIndex, ma_ug_t *rug, spg_t *scg) +{ + uint32_t i, k, v, *ma = NULL, mn, luid; + ma_utg_v *pp = &(scg->ug->u); + kvec_t(uint32_t) vv; kv_init(vv); + for (i = 0; i < scg->idx.n; i++){ + ma = scg->dst.a + (scg->idx.a[i]>>32); + mn = (uint64_t)scg->idx.a[i]; + if(mn < 2) continue; + for (k = 0, vv.n = 0; k < mn; k++){ + luid = seed_uid(&(pp->a[ma[k]>>1]), ps_idx, ruIndex, rug); + if(luid == (uint32_t)-1) { + fprintf(stderr, "ERROR-scg\n"); + continue; + } + kv_push(uint32_t, vv, luid); + } + if(vv.n < 2) continue; + filter_ovlp_vecs(ha, vv.a, vv.n); + } + + for (v = 0; v < ha->num; v++){ + for (i = 0, k = 0; i < ha->x[v].a.n; i++){ + if(ha->x[v].a.a[i].status == DELETE) continue; + ha->x[v].a.a[k++] = ha->x[v].a.a[i]; + } + ha->x[v].a.n = k; + } + + kv_destroy(vv); +} + +void purge_dups(ma_ug_t *ug, asg_t *read_g, ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, +ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, float density, +uint32_t purege_minLen, int max_hang, int min_ovlp, float drop_ratio, uint32_t just_contain, +uint32_t just_coverage, hap_cov_t *cov, uint32_t collect_p_trans, uint32_t collect_p_trans_f) +{ + p_g_t *pg = NULL; + asg_t* nsg = ug->g; + uint32_t v, rId, uId, i, offset; + ma_utg_t* reads = NULL; + uint64_t* position_index = NULL; + if(cov) position_index = cov->pos_idx; + else position_index = (uint64_t*)malloc(sizeof(uint64_t)*read_g->n_seq); + memset(position_index, -1, sizeof(uint64_t)*read_g->n_seq); + + hap_overlaps_list all_ovlp; + init_hap_overlaps_list(&all_ovlp, nsg->n_seq); + hap_overlaps_list back_all_ovlp; + init_hap_overlaps_list(&back_all_ovlp, nsg->n_seq); + asg_arc_t t, *p = NULL; + int r; + hap_alignment_struct_pip hap_buf; + long long k_mer_only, coverage_only; + + if(asm_opt.hom_global_coverage != -1) + { + hap_buf.cov_threshold = (asm_opt.hom_global_coverage_set? + (((double)asm_opt.hom_global_coverage)*((double)HOM_PEAK_RATE)):(asm_opt.hom_global_coverage)); + } + else + { + hap_buf.cov_threshold = get_read_coverage_thres(ug, read_g, ruIndex, position_index, + sources, coverage_cut, read_g->n_seq, COV_COUNT, &k_mer_only, &coverage_only); + } + + + for (v = 0; v < nsg->n_seq; v++) + { + uId = v; + reads = &(ug->u.a[uId]); + for (i = 0, offset = 0; i < reads->n; i++) + { + rId = reads->a[i]>>33; + set_R_to_U(ruIndex, rId, uId, 1, &(read_g->seq[rId].c)); + + position_index[rId] = offset; + position_index[rId] = position_index[rId] << 32; + position_index[rId] = position_index[rId] | (uint64_t)i; + + offset += (uint32_t)reads->a[i]; + } + } + + // if(just_coverage == 0) + // { + // ma_ug_seq(ug, read_g, coverage_cut, sources, edge, max_hang, min_ovlp, 0, 0); + // } + // init_ug_idx(ug, asm_opt.k_mer_length, asm_opt.polyploidy, 2, !just_coverage); + + init_hap_alignment_struct_pip(&hap_buf, asm_opt.thread_num, nsg->n_seq, ug, read_g, + sources, reverse_sources, ruIndex, coverage_cut, position_index, density, max_hang, min_ovlp, + 0.1, &all_ovlp, cov); + + if(hap_buf.cov_threshold < 0) + { + if(if_ploid_sample(ug, read_g, ruIndex, sources, reverse_sources, coverage_cut, + &hap_buf, &all_ovlp, &back_all_ovlp, purege_minLen, 0.333)) + { + ///if peak is het, coverage peak is more reliable + hap_buf.cov_threshold = coverage_only * HET_PEAK_RATE; + } + else + { + ///if peak is homo, k-mer peak is more reliable + hap_buf.cov_threshold = k_mer_only * HOM_PEAK_RATE; + } + } + if(asm_opt.hom_global_coverage == -1) asm_opt.hom_global_coverage = hap_buf.cov_threshold; + if(asm_opt.pur_global_coverage != -1) hap_buf.cov_threshold = asm_opt.pur_global_coverage; + fprintf(stderr, "[M::%s] homozygous read coverage threshold: %d\n", __func__, asm_opt.hom_global_coverage_set? + asm_opt.hom_global_coverage:(int)(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); + fprintf(stderr, "[M::%s] purge duplication coverage threshold: %lld\n", __func__, hap_buf.cov_threshold); + if(just_coverage) goto end_coverage; + + kt_for(asm_opt.thread_num, hap_alignment_advance_worker, &hap_buf, nsg->n_seq); + + ///if(debug_enable) print_all_purge_ovlp(ug, &all_ovlp); + filter_hap_overlaps_by_length(&all_ovlp, purege_minLen); + + // normalize_hap_overlaps_advance(&all_ovlp, &back_all_ovlp, ug, read_g, reverse_sources, ruIndex); + pg = init_p_g_t(ug, cov, read_g); + normalize_hap_overlaps_advance_by_p_g_t(&all_ovlp, &back_all_ovlp, ug, read_g, reverse_sources, ruIndex, pg, cov, 0.8); + + if(collect_p_trans && collect_p_trans_f == 0) + { + collect_purge_trans_cov(ug, &all_ovlp, cov, position_index); + } + + if(asm_opt.polyploidy <= 2) + { + mc_solve(&all_ovlp, cov->t_ch, NULL, ug, read_g, 0.8, R_INF.trio_flag, 1, NULL, 1, NULL, NULL, 1, 0); + } + + if(collect_p_trans && collect_p_trans_f == 1) + { + collect_purge_trans_cov(ug, &all_ovlp, cov, position_index); + } + + ///normalize_hap_overlaps_advance(&all_ovlp, &back_all_ovlp, ug, read_g, reverse_sources, ruIndex); + ///debug_hap_overlaps(&all_ovlp, &back_all_ovlp); + + remove_contained_haplotig(&all_ovlp, ug, nsg, pg->pg_h_lev, cov); + + if(just_contain == 0) + { + for (v = 0; v < all_ovlp.num; v++) + { + uId = v; + if(pg->pg_h_lev->seq[uId].del || pg->pg_h_lev->seq[uId].c == ALTER_LABLE) continue; + for (i = 0; i < all_ovlp.x[uId].a.n; i++) + { + if(all_ovlp.x[uId].a.a[i].status == DELETE) continue; + if(pg->pg_h_lev->seq[all_ovlp.x[uId].a.a[i].xUid].c == ALTER_LABLE|| + pg->pg_h_lev->seq[all_ovlp.x[uId].a.a[i].xUid].del|| + pg->pg_h_lev->seq[all_ovlp.x[uId].a.a[i].yUid].c == ALTER_LABLE|| + pg->pg_h_lev->seq[all_ovlp.x[uId].a.a[i].yUid].del) + { + continue; + } + + + ///print_hap_paf(ug, &(all_ovlp.x[uId].a.a[i])); + + r = get_hap_arch(&(all_ovlp.x[uId].a.a[i]), ug->u.a[all_ovlp.x[uId].a.a[i].xUid].len, + ug->u.a[all_ovlp.x[uId].a.a[i].yUid].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + + if(r < 0) continue; + p = asg_arc_pushp(pg->pg_h_lev); + *p = t; + } + } + + asg_cleanup(pg->pg_h_lev); + asg_symm(pg->pg_h_lev); + ///may need to do transitive reduction + clean_purge_graph(pg->pg_h_lev, drop_ratio, 1); + + // if(debug_enable) print_purge_gfa(ug, purge_g); + // if(debug_enable) print_all_purge_ovlp(ug, &all_ovlp); + /*******************************for debug************************************/ + // print_het_ovlp(pg, ug, &all_ovlp, 0.8); + /*******************************for debug************************************/ + + link_unitigs(pg->pg_h_lev, ug, &all_ovlp, ruIndex, reverse_sources, coverage_cut, read_g, position_index, + &(hap_buf.buf[0].u_buffer), &(hap_buf.buf[0].u_buffer_tailIndex), &(hap_buf.buf[0].u_buffer_prevIndex), + max_hang, min_ovlp, edge, hap_buf.buf[0].visit, cov); + } + + for (v = 0; v < all_ovlp.num; v++) + { + uId = v; + if(pg->pg_h_lev->seq[uId].c == ALTER_LABLE) + { + ug->g->seq[uId].c = ALTER_LABLE; + } + } + + end_coverage: + uint32_t is_Unitig; + for (v = 0; v < ruIndex->len; v++) + { + get_R_to_U(ruIndex, v, &uId, &is_Unitig); + if(is_Unitig == 1) ruIndex->index[v] = (uint32_t)-1; + } + asg_cleanup(nsg); + destory_hap_overlaps_list(&all_ovlp); + destory_hap_overlaps_list(&back_all_ovlp); + if(cov) memset(position_index, -1, sizeof(uint64_t)*read_g->n_seq); + else free(position_index); + destory_hap_alignment_struct_pip(&hap_buf); + destory_p_g_t(&pg); + // if(just_coverage == 0) + // { + // des_ug_idx(); + // for (i = 0; i < ug->u.n; i++) + // { + // free(ug->u.a[i].s); + // ug->u.a[i].s = NULL; + // } + // } +} diff --git a/Purge_Dups.h b/Purge_Dups.h index ce0d18a..2f333e1 100644 --- a/Purge_Dups.h +++ b/Purge_Dups.h @@ -1,96 +1,96 @@ -#ifndef __PURGEDUPS__ -#define __PURGEDUPS__ - -#define __STDC_LIMIT_MACROS -#include -#include -#include "kvec.h" -#include "kdq.h" -#include "Overlaps.h" -#include "Hash_Table.h" -#define COV_COUNT 1024 -#define HOM_PEAK_RATE 1.25 -#define HET_PEAK_RATE (HOM_PEAK_RATE*2) -#define ALTER_COV_THRES 0.9 -#define REAL_ALTER_THRES 0.25 -#define CHAIN_FILTER_RATE 0.7 -#define REV_W 8 - -#define SELF_EXIST 0 -#define REVE_EXIST 1 -#define DELETE 2 -#define MIXED 3 -#define FLIP 4 - -#define X2Y 0 -#define Y2X 1 -#define XCY 2 -#define YCX 3 - -#define Cal_Off(OFF) ((long long)((uint32_t)((OFF)>>32)) - (long long)((uint32_t)((OFF)))) -#define Get_xOff(OFF) ((long long)((uint32_t)((OFF)>>32))) -#define Get_yOff(OFF) ((long long)((uint32_t)((OFF)))) -#define Get_match(x) ((x).weight) -#define Get_total(x) ((x).index_beg) -#define Get_type(x) ((x).index_end) -#define Get_x_beg(x) ((x).x_beg_pos) -#define Get_x_end(x) ((x).x_end_pos) -#define Get_y_beg(x) ((x).y_beg_pos) -#define Get_y_end(x) ((x).y_end_pos) -#define Get_rev(x) ((x).rev) - -typedef struct { - uint8_t rev; - uint8_t type; - uint8_t status; - uint32_t x_beg_pos; - uint32_t x_end_pos; - uint32_t y_beg_pos; - uint32_t y_end_pos; - uint32_t x_beg_id; - uint32_t x_end_id; - uint32_t y_beg_id; - uint32_t y_end_id; - uint32_t xUid; - uint32_t yUid; - uint32_t weight; - long long score; - float s; -}hap_overlaps; - -typedef struct { - kvec_t(hap_overlaps) a; -}kvec_hap_overlaps; - -typedef struct { - kvec_hap_overlaps* x; - uint32_t num; -}hap_overlaps_list; - -void purge_dups(ma_ug_t *ug, asg_t *read_g, ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, -ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, float density, -uint32_t purege_minLen, int max_hang, int min_ovlp, float drop_ratio, uint32_t just_contain, -uint32_t just_coverage, hap_cov_t *cov, uint32_t collect_p_trans, uint32_t collect_p_trans_f); -void fill_unitig(uint64_t* buffer, uint32_t bufferLen, asg_t* read_g, kvec_asg_arc_t_warp* edge, -uint32_t is_circle, uint64_t* rLen); -void get_contig_length(ma_ug_t *ug, asg_t *g, uint64_t* primaryLen, uint64_t* alterLen); -void enable_debug_mode(uint32_t mode); -hap_cov_t* init_hap_cov_t(ma_ug_t *ug, asg_t* read_g, ma_hit_t_alloc* sources, R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, -ma_sub_t *coverage_cut, int max_hang, int min_ovlp, uint32_t is_collect_trans); -void destory_hap_cov_t(hap_cov_t **x); -void chain_trans_ovlp(hap_cov_t *cov, utg_trans_t *o, ma_ug_t *ug, asg_t *read_sg, buf_t* xReads, uint32_t targetBaseLen, uint32_t* xEnd); -int get_specific_hap_overlap(kvec_hap_overlaps* x, uint32_t qn, uint32_t tn); -void set_reverse_hap_overlap(hap_overlaps* dest, hap_overlaps* source, uint32_t* types); -void print_hap_paf(ma_ug_t *ug, hap_overlaps* ovlp); -uint64_t get_xy_pos_by_pos(asg_t *read_g, asg_arc_t* t, uint32_t v_in_unitig, uint32_t w_in_unitig, -uint32_t v_in_pos, uint32_t w_in_pos, uint32_t xUnitigLen, uint32_t yUnitigLen, uint8_t* rev); -void quick_LIS(asg_arc_t_offset* x, uint32_t n, kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* prevIndex); -uint32_t classify_hap_overlap(long long xBeg, long long xEnd, long long xLen, -long long yBeg, long long yEnd, long long yLen, long long* r_xBeg, long long* r_xEnd, -long long* r_yBeg, long long* r_yEnd); -int cmp_hap_alignment_chaining(const void * a, const void * b); -uint32_t classify_hap_overlap(long long xBeg, long long xEnd, long long xLen, -long long yBeg, long long yEnd, long long yLen, long long* r_xBeg, long long* r_xEnd, -long long* r_yBeg, long long* r_yEnd); - +#ifndef __PURGEDUPS__ +#define __PURGEDUPS__ + +#define __STDC_LIMIT_MACROS +#include +#include +#include "kvec.h" +#include "kdq.h" +#include "Overlaps.h" +#include "Hash_Table.h" +#define COV_COUNT 1024 +#define HOM_PEAK_RATE 1.25 +#define HET_PEAK_RATE (HOM_PEAK_RATE*2) +#define ALTER_COV_THRES 0.9 +#define REAL_ALTER_THRES 0.25 +#define CHAIN_FILTER_RATE 0.7 +#define REV_W 8 + +#define SELF_EXIST 0 +#define REVE_EXIST 1 +#define DELETE 2 +#define MIXED 3 +#define FLIP 4 + +#define X2Y 0 +#define Y2X 1 +#define XCY 2 +#define YCX 3 + +#define Cal_Off(OFF) ((long long)((uint32_t)((OFF)>>32)) - (long long)((uint32_t)((OFF)))) +#define Get_xOff(OFF) ((long long)((uint32_t)((OFF)>>32))) +#define Get_yOff(OFF) ((long long)((uint32_t)((OFF)))) +#define Get_match(x) ((x).weight) +#define Get_total(x) ((x).index_beg) +#define Get_type(x) ((x).index_end) +#define Get_x_beg(x) ((x).x_beg_pos) +#define Get_x_end(x) ((x).x_end_pos) +#define Get_y_beg(x) ((x).y_beg_pos) +#define Get_y_end(x) ((x).y_end_pos) +#define Get_rev(x) ((x).rev) + +typedef struct { + uint8_t rev; + uint8_t type; + uint8_t status; + uint32_t x_beg_pos; + uint32_t x_end_pos; + uint32_t y_beg_pos; + uint32_t y_end_pos; + uint32_t x_beg_id; + uint32_t x_end_id; + uint32_t y_beg_id; + uint32_t y_end_id; + uint32_t xUid; + uint32_t yUid; + uint32_t weight; + long long score; + float s; +}hap_overlaps; + +typedef struct { + kvec_t(hap_overlaps) a; +}kvec_hap_overlaps; + +typedef struct { + kvec_hap_overlaps* x; + uint32_t num; +}hap_overlaps_list; + +void purge_dups(ma_ug_t *ug, asg_t *read_g, ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, +ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, kvec_asg_arc_t_warp* edge, float density, +uint32_t purege_minLen, int max_hang, int min_ovlp, float drop_ratio, uint32_t just_contain, +uint32_t just_coverage, hap_cov_t *cov, uint32_t collect_p_trans, uint32_t collect_p_trans_f); +void fill_unitig(uint64_t* buffer, uint32_t bufferLen, asg_t* read_g, kvec_asg_arc_t_warp* edge, +uint32_t is_circle, uint64_t* rLen); +void get_contig_length(ma_ug_t *ug, asg_t *g, uint64_t* primaryLen, uint64_t* alterLen); +void enable_debug_mode(uint32_t mode); +hap_cov_t* init_hap_cov_t(ma_ug_t *ug, asg_t* read_g, ma_hit_t_alloc* sources, R_to_U* ruIndex, ma_hit_t_alloc* reverse_sources, +ma_sub_t *coverage_cut, int max_hang, int min_ovlp, uint32_t is_collect_trans); +void destory_hap_cov_t(hap_cov_t **x); +void chain_trans_ovlp(hap_cov_t *cov, utg_trans_t *o, ma_ug_t *ug, asg_t *read_sg, buf_t* xReads, uint32_t targetBaseLen, uint32_t* xEnd); +int get_specific_hap_overlap(kvec_hap_overlaps* x, uint32_t qn, uint32_t tn); +void set_reverse_hap_overlap(hap_overlaps* dest, hap_overlaps* source, uint32_t* types); +void print_hap_paf(ma_ug_t *ug, hap_overlaps* ovlp); +uint64_t get_xy_pos_by_pos(asg_t *read_g, asg_arc_t* t, uint32_t v_in_unitig, uint32_t w_in_unitig, +uint32_t v_in_pos, uint32_t w_in_pos, uint32_t xUnitigLen, uint32_t yUnitigLen, uint8_t* rev); +void quick_LIS(asg_arc_t_offset* x, uint32_t n, kvec_t_i32_warp* tailIndex, kvec_t_i32_warp* prevIndex); +uint32_t classify_hap_overlap(long long xBeg, long long xEnd, long long xLen, +long long yBeg, long long yEnd, long long yLen, long long* r_xBeg, long long* r_xEnd, +long long* r_yBeg, long long* r_yEnd); +int cmp_hap_alignment_chaining(const void * a, const void * b); +uint32_t classify_hap_overlap(long long xBeg, long long xEnd, long long xLen, +long long yBeg, long long yEnd, long long yLen, long long* r_xBeg, long long* r_xEnd, +long long* r_yBeg, long long* r_yEnd); + #endif \ No newline at end of file diff --git a/README.md b/README.md index 6228920..685bc0b 100644 --- a/README.md +++ b/README.md @@ -1,296 +1,296 @@ -## Getting Started - -```sh -# Install hifiasm (requiring g++ and zlib) -git clone https://github.com/chhylp123/hifiasm -cd hifiasm && make - -# Run on test data (use -f0 for small datasets) -wget https://github.com/chhylp123/hifiasm/releases/download/v0.7/chr11-2M.fa.gz -./hifiasm -o test -t4 -f0 chr11-2M.fa.gz 2> test.log -awk '/^S/{print ">"$2;print $3}' test.bp.p_ctg.gfa > test.p_ctg.fa # get primary contigs in FASTA - -# Assemble inbred/homozygous genomes (-l0 disables duplication purging) -hifiasm -o CHM13.asm -t32 -l0 CHM13-HiFi.fa.gz 2> CHM13.asm.log -# Assemble heterozygous genomes with built-in duplication purging -hifiasm -o HG002.asm -t32 HG002-file1.fq.gz HG002-file2.fq.gz - -# Assemble genomes with ONT R10 reads rather than PacBio HiFi reads using the latest release of hifiasm (>0.21.0-r686) -hifiasm -o HG002.asm --ont -t32 HG002-ont.fq.gz - -# Hi-C phasing with paired-end short reads in two FASTQ files -hifiasm -o HG002.asm --h1 read1.fq.gz --h2 read2.fq.gz HG002-HiFi.fq.gz - -# Trio binning assembly (requiring https://github.com/lh3/yak) -yak count -b37 -t16 -o pat.yak <(cat pat_1.fq.gz pat_2.fq.gz) <(cat pat_1.fq.gz pat_2.fq.gz) -yak count -b37 -t16 -o mat.yak <(cat mat_1.fq.gz mat_2.fq.gz) <(cat mat_1.fq.gz mat_2.fq.gz) -hifiasm -o HG002.asm -t32 -1 pat.yak -2 mat.yak HG002-HiFi.fa.gz - -# Improve contiguity for diploid genome assembly by self-scaffolding (`--dual-scaf`) -hifiasm -o HG002.asm --dual-scaf --h1 read1.fq.gz --h2 read2.fq.gz HG002-HiFi.fq.gz - -# Preserve more telomeres for human genomes (`--telo-m CCCTAA`) -hifiasm -o HG002.asm --telo-m CCCTAA --h1 read1.fq.gz --h2 read2.fq.gz HG002-HiFi.fq.gz - -# Hybrid assembly with HiFi, ultralong and Hi-C reads -hifiasm -o HG002.asm --h1 read1.fq.gz --h2 read2.fq.gz --ul ul.fq.gz HG002-HiFi.fq.gz - -# Single-sample telomere-to-telomere assembly for diploid human genomes -hifiasm -o HG002.asm --dual-scaf --telo-m CCCTAA --h1 read1.fq.gz --h2 read2.fq.gz --ul ul.fq.gz HG002-HiFi.fq.gz - -``` -See [tutorial][tutorial] for more details. - -## Table of Contents - -- [Getting Started](#started) -- [Introduction](#intro) -- [Why Hifiasm?](#why) -- [Usage](#use) - - [Assembling HiFi reads without additional data types](#hifionly) - - [Assembling ONT reads](#ontonly) - - [Hi-C integration](#hic) - - [Trio binning](#trio) - - [Ultra-long ONT integration](#ul) - - [Output files](#output) -- [Results](#results) -- [Getting Help](#help) -- [Limitations](#limit) -- [Citing Hifiasm](#cite) - -## Introduction - -Hifiasm is a fast haplotype-resolved de novo assembler initially designed for PacBio HiFi reads. -Its latest release could support the telomere-to-telomere assembly by utilizing ultralong Oxford Nanopore reads. Hifiasm produces arguably the best single-sample telomere-to-telomere assemblies combing HiFi, ultralong and Hi-C reads, and it is one of the best haplotype-resolved assemblers for the trio-binning assembly given parental short reads. For a human genome, hifiasm can produce the telomere-to-telomere assembly in one day. - -## Why Hifiasm? - -* Hifiasm delivers high-quality telomere-to-telomere assemblies. It tends to generate longer contigs - and resolve more segmental duplications than other assemblers. - -* Given Hi-C reads or short reads from the parents, hifiasm can produce overall the best - haplotype-resolved assembly so far. It is the assembler of choice by the - [Human Pangenome Project][hpp] for the first batch of samples. - -* Hifiasm can purge duplications between haplotigs without relying on - third-party tools such as purge\_dups. Hifiasm does not need polishing tools - like pilon or racon, either. This simplifies the assembly pipeline and saves - running time. - -* Hifiasm is fast. It can assemble a human genome in half a day and assemble a - ~30Gb redwood genome in three days. No genome is too large for hifiasm. - -* Hifiasm is trivial to install and easy to use. It does not required Python, - R or C++11 compilers, and can be compiled into a single executable. The - default setting works well with a variety of genomes. - -[hpp]: https://humanpangenome.org - -## Usage - -### Assembling HiFi reads without additional data types - -A typical hifiasm command line looks like: -```sh -hifiasm -o NA12878.asm -t 32 NA12878.fq.gz -``` -where `NA12878.fq.gz` provides the input reads, `-t` sets the number of CPUs in -use and `-o` specifies the prefix of output files. For this example, the -primary contigs are written to `NA12878.asm.bp.p_ctg.gfa`. -Since v0.15, hifiasm also produces two sets of -partially phased contigs at `NA12878.asm.bp.hap?.p_ctg.gfa`. This pair of files -can be thought to represent the two haplotypes in a diploid genome, though with -occasional switch errors. The frequency of switches is determined by the -heterozygosity of the input sample. - -At the first run, hifiasm saves corrected reads and -overlaps to disk as `NA12878.asm.*.bin`. It reuses the saved results to avoid -the time-consuming all-vs-all overlap calculation next time. You may specify -`-i` to ignore precomputed overlaps and redo overlapping from raw reads. -You can also dump error corrected reads in FASTA and read overlaps in PAF with -```sh -hifiasm -o NA12878.asm -t 32 --write-paf --write-ec /dev/null -``` - -Hifiasm purges haplotig duplications by default. For inbred or homozygous -genomes, you may disable purging with option `-l0`. Old HiFi reads may contain -short adapter sequences at the ends of reads. You can specify `-z20` to trim -both ends of reads by 20bp. For small genomes, use `-f0` to disable the initial -bloom filter which takes 16GB memory at the beginning. For genomes much larger -than human, applying `-f38` or even `-f39` is preferred to save memory on k-mer -counting. - -### Assembling ONT reads - -Since version 0.21.0 (r686), hifiasm can support ONT assembly using ONT simplex R10 reads. -To enable this feature, add the `--ont` option as shown below: -```sh -hifiasm -t64 --ont -o ONT.asm ONT.read.fastq.gz -``` -Please note that this module requires input reads in FASTQ format. - - -### Hi-C integration - -Hifiasm can generate a pair of haplotype-resolved assemblies with paired-end -Hi-C reads: -```sh -hifiasm -o NA12878.asm -t32 --h1 read1.fq.gz --h2 read2.fq.gz HiFi-reads.fq.gz -``` -In this mode, each contig is supposed to be a haplotig, which by definition -comes from one parental haplotype only. Hifiasm often puts all contigs from the -same parental chromosome in one assembly. It has cleanly separated chrX and -chrY for a human male dataset. Nonetheless, phasing across centromeres is -challenging. Hifiasm is often able to phase entire chromosomes but it may fail -in rare cases. Also, contigs from different parental chromosomes are randomly mixed as -it is just not possible to phase across chromosomes with Hi-C. - -Hifiasm does not perform scaffolding for now. You need to run a standalone -scaffolder such as SALSA or 3D-DNA to scaffold phased haplotigs. - -### Trio binning - -When parental short reads are available, hifiasm can also generate a pair of -haplotype-resolved assemblies with trio binning. To perform such assembly, you -need to count k-mers first with [yak][yak] first and then do assembly: -```sh -yak count -k31 -b37 -t16 -o pat.yak paternal.fq.gz -yak count -k31 -b37 -t16 -o mat.yak maternal.fq.gz -hifiasm -o NA12878.asm -t 32 -1 pat.yak -2 mat.yak NA12878.fq.gz -``` -Here `NA12878.asm.dip.hap1.p_ctg.gfa` and `NA12878.asm.dip.hap2.p_ctg.gfa` give the two -haplotype assemblies. In the binning mode, hifiasm does not purge haplotig -duplicates by default. Because hifiasm reuses saved overlaps, you can -generate both primary/alternate assemblies and trio binning assemblies with -```sh -hifiasm -o NA12878.asm -t 32 NA12878.fq.gz 2> NA12878.asm.pri.log -hifiasm -o NA12878.asm -t 32 -1 pat.yak -2 mat.yak /dev/null 2> NA12878.asm.trio.log -``` -The second command line will run much faster than the first. - -### Ultra-long ONT integration - -Hifiasm could integrate ultra-long ONT reads to produce the telomere-to-telomere assembly: -```sh -hifiasm -o NA12878.asm -t32 --ul ul.fq.gz HiFi-reads.fq.gz -``` -For the single-sample telomere-to-telomere assembly with Hi-C reads: -```sh -hifiasm -o NA12878.asm -t32 --ul ul.fq.gz --h1 read1.fq.gz --h2 read2.fq.gz HiFi-reads.fq.gz -``` -For the trio-binning telomere-to-telomere assembly: -```sh -hifiasm -o NA12878.asm -t32 --ul ul.fq.gz -1 pat.yak -2 mat.yak HiFi-reads.fq.gz -``` - -### Self-scaffolding - -For diploid haplotype-resolved genome assembly, hifiasm can further enhance assembly contiguity -by introducing scaffolding. It leverages the assemblies of the two haplotypes to scaffold each other. -Specifically, if there is a gap within the haplotype 1 assembly, hifiasm will use the corresponding -homologous region in haplotype 2 to scaffold haplotype 1. Below is an example using the `--dual-scaf` option. -```sh -hifiasm -o NA12878.asm -t32 --dual-scaf HiFi-reads.fq.gz -``` - -### Preserve more telomeres for T2T assemblies - -Hifiasm can preserve more telomeres by specifying the telomere motif using the `--telo-m` option. -Below is an example applied to human genome assembly. -```sh -hifiasm -o NA12878.asm -t32 --telo-m CCCTAA HiFi-reads.fq.gz -``` - -### Output files - -Hifiasm generates different types of assemblies based on the input data. -It also writes error corrected reads to the *prefix*.ec.bin binary file and -writes overlaps to *prefix*.ovlp.source.bin and *prefix*.ovlp.reverse.bin. -For more details, please see the complete [documentation][tutorial_output]. - -## Results - -The following table shows the statistics of several hifiasm primary assemblies assembled with v0.12: - -|Dataset|Size|Cov.|Asm options|CPU time|Wall time|RAM| N50| -|:---------------|-----:|-----:|:---------------------|-------:|--------:|----:|----------------:| -|[Mouse (C57/BL6J)][mouse-data]|2.6Gb |×25|-t48 -l0 |172.9h |4.8h |76G |21.1Mb| -|[Maize (B73)][maize-data] |2.2Gb |×22|-t48 -l0 |203.2h |5.1h |68G |36.7Mb| -|[Strawberry][strawberry-data] |0.8Gb |×36|-t48 -D10|152.7h |3.7h |91G |17.8Mb| -|[Frog][frog-data] |9.5Gb |×29|-t48 |2834.3h|69.0h|463G|9.3Mb| -|[Redwood][redwood-data] |35.6Gb|×28|-t80 |3890.3h|65.5h|699G|5.4Mb| -|[Human (CHM13)][CHM13-data] |3.1Gb |×32|-t48 -l0 |310.7h |8.2h |114G|88.9Mb| -|[Human (HG00733)][HG00733-data]|3.1Gb|×33|-t48 |269.1h |6.9h |135G|69.9Mb| -|[Human (HG002)][NA24385-data] |3.1Gb |×36|-t48 |305.4h |7.7h |137G|98.7Mb| - -[mouse-data]: https://www.ncbi.nlm.nih.gov/sra/?term=SRR11606870 -[maize-data]: https://www.ncbi.nlm.nih.gov/sra/?term=SRR11606869 -[strawberry-data]: https://www.ncbi.nlm.nih.gov/sra/?term=SRR11606867 -[frog-data]: https://www.ncbi.nlm.nih.gov/sra?term=(SRR11606868)%20OR%20SRR12048570 -[redwood-data]: https://www.ncbi.nlm.nih.gov/sra/?term=SRP251156 -[CHM13-data]: https://www.ncbi.nlm.nih.gov/sra?term=(((SRR11292120)%20OR%20SRR11292121)%20OR%20SRR11292122)%20OR%20SRR11292123 - -Hifiasm can assemble a 3.1Gb human genome in several hours or a ~30Gb hexaploid -redwood genome in a few days on a single machine. For trio binning assembly: - -|Dataset|Cov.|CPU time|Elapsed time|RAM| N50| -|:---------------|-----:|-------:|--------:|----:|----------------:| -|[HG00733][HG00733-data], [\[father\]][HG00731-data], [\[mother\]][HG00732-data]|×33|269.1h|6.9h|135G|35.1Mb (paternal), 34.9Mb (maternal)| -|[HG002][NA24385-data], [\[father\]][NA24149-data], [\[mother\]][NA24143-data]|×36|305.4h|7.7h|137G|41.0Mb (paternal), 40.8Mb (maternal)| - - - -[HG00733-data]: https://www.ebi.ac.uk/ena/data/view/ERX3831682 -[HG00731-data]: https://www.ebi.ac.uk/ena/data/view/ERR3241754 -[HG00732-data]: https://www.ebi.ac.uk/ena/data/view/ERR3241755 -[NA24385-data]: https://www.ncbi.nlm.nih.gov/sra?term=(((SRR10382244)%20OR%20SRR10382245)%20OR%20SRR10382248)%20OR%20SRR10382249 -[NA24149-data]: https://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/data/AshkenazimTrio/HG003_NA24149_father/NIST_HiSeq_HG003_Homogeneity-12389378/HG003Run01-13262252/ -[NA24143-data]: https://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/data/AshkenazimTrio/HG004_NA24143_mother/NIST_HiSeq_HG004_Homogeneity-14572558/HG004Run01-15133132/ -[NA12878-data]: https://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/data/NA12878/PacBio_SequelII_CCS_11kb/ -[NA12891-data]: https://www.ebi.ac.uk/ena/data/view/ERR194160 -[NA12892-data]: https://www.ebi.ac.uk/ena/data/view/ERR194161 - -Human assemblies above can be acquired [from Zenodo][zenodo-human] and -non-human ones are available [here][zenodo-nonh]. - -[zenodo-human]: https://zenodo.org/record/4393631 -[zenodo-nonh]: https://zenodo.org/record/4393750 -[unitig]: http://wgs-assembler.sourceforge.net/wiki/index.php/Celera_Assembler_Terminology -[gfa]: https://github.com/pmelsted/GFA-spec/blob/master/GFA-spec.md -[paf]: https://github.com/lh3/miniasm/blob/master/PAF.md -[yak]: https://github.com/lh3/yak -[tutorial]: https://hifiasm.readthedocs.io/en/latest/index.html -[tutorial_output]: https://hifiasm.readthedocs.io/en/latest/interpreting-output.html#interpreting-output - - -## Getting Help - -For detailed description of options, please see [tutorial][tutorial] or `man ./hifiasm.1`. The `-h` -option of hifiasm also provides brief description of options. If you have -further questions, please raise an issue at the [issue -page](https://github.com/chhylp123/hifiasm/issues). - -## Limitations - -1. Purging haplotig duplications may introduce misassemblies. - -## Citating Hifiasm - -If you use hifiasm in your work, please cite: - -> Cheng, H., Concepcion, G.T., Feng, X., Zhang, H., Li H. (2021) -> Haplotype-resolved de novo assembly using phased assembly graphs with -> hifiasm. *Nat Methods*, **18**:170-175. -> https://doi.org/10.1038/s41592-020-01056-5 - -> Cheng, H., Jarvis, E.D., Fedrigo, O., Koepfli, K.P., Urban, L., Gemmell, N.J., Li, H. (2022) -> Haplotype-resolved assembly of diploid genomes without parental data. -> *Nature Biotechnology*, **40**:1332–1335. -> https://doi.org/10.1038/s41587-022-01261-x - -> Cheng, H., Asri, M., Lucas, J., Koren, S., Li, H. (2024) -> Scalable telomere-to-telomere assembly for diploid and polyploid genomes with double graph. -> *Nat Methods*, **21**:967-970. -> https://doi.org/10.1038/s41592-024-02269-8 +## Getting Started + +```sh +# Install hifiasm (requiring g++ and zlib) +git clone https://github.com/chhylp123/hifiasm +cd hifiasm && make + +# Run on test data (use -f0 for small datasets) +wget https://github.com/chhylp123/hifiasm/releases/download/v0.7/chr11-2M.fa.gz +./hifiasm -o test -t4 -f0 chr11-2M.fa.gz 2> test.log +awk '/^S/{print ">"$2;print $3}' test.bp.p_ctg.gfa > test.p_ctg.fa # get primary contigs in FASTA + +# Assemble inbred/homozygous genomes (-l0 disables duplication purging) +hifiasm -o CHM13.asm -t32 -l0 CHM13-HiFi.fa.gz 2> CHM13.asm.log +# Assemble heterozygous genomes with built-in duplication purging +hifiasm -o HG002.asm -t32 HG002-file1.fq.gz HG002-file2.fq.gz + +# Assemble genomes with ONT R10 reads rather than PacBio HiFi reads using the latest release of hifiasm (>0.21.0-r686) +hifiasm -o HG002.asm --ont -t32 HG002-ont.fq.gz + +# Hi-C phasing with paired-end short reads in two FASTQ files +hifiasm -o HG002.asm --h1 read1.fq.gz --h2 read2.fq.gz HG002-HiFi.fq.gz + +# Trio binning assembly (requiring https://github.com/lh3/yak) +yak count -b37 -t16 -o pat.yak <(cat pat_1.fq.gz pat_2.fq.gz) <(cat pat_1.fq.gz pat_2.fq.gz) +yak count -b37 -t16 -o mat.yak <(cat mat_1.fq.gz mat_2.fq.gz) <(cat mat_1.fq.gz mat_2.fq.gz) +hifiasm -o HG002.asm -t32 -1 pat.yak -2 mat.yak HG002-HiFi.fa.gz + +# Improve contiguity for diploid genome assembly by self-scaffolding (`--dual-scaf`) +hifiasm -o HG002.asm --dual-scaf --h1 read1.fq.gz --h2 read2.fq.gz HG002-HiFi.fq.gz + +# Preserve more telomeres for human genomes (`--telo-m CCCTAA`) +hifiasm -o HG002.asm --telo-m CCCTAA --h1 read1.fq.gz --h2 read2.fq.gz HG002-HiFi.fq.gz + +# Hybrid assembly with HiFi, ultralong and Hi-C reads +hifiasm -o HG002.asm --h1 read1.fq.gz --h2 read2.fq.gz --ul ul.fq.gz HG002-HiFi.fq.gz + +# Single-sample telomere-to-telomere assembly for diploid human genomes +hifiasm -o HG002.asm --dual-scaf --telo-m CCCTAA --h1 read1.fq.gz --h2 read2.fq.gz --ul ul.fq.gz HG002-HiFi.fq.gz + +``` +See [tutorial][tutorial] for more details. + +## Table of Contents + +- [Getting Started](#started) +- [Introduction](#intro) +- [Why Hifiasm?](#why) +- [Usage](#use) + - [Assembling HiFi reads without additional data types](#hifionly) + - [Assembling ONT reads](#ontonly) + - [Hi-C integration](#hic) + - [Trio binning](#trio) + - [Ultra-long ONT integration](#ul) + - [Output files](#output) +- [Results](#results) +- [Getting Help](#help) +- [Limitations](#limit) +- [Citing Hifiasm](#cite) + +## Introduction + +Hifiasm is a fast haplotype-resolved de novo assembler initially designed for PacBio HiFi reads. +Its latest release could support the telomere-to-telomere assembly by utilizing ultralong Oxford Nanopore reads. Hifiasm produces arguably the best single-sample telomere-to-telomere assemblies combing HiFi, ultralong and Hi-C reads, and it is one of the best haplotype-resolved assemblers for the trio-binning assembly given parental short reads. For a human genome, hifiasm can produce the telomere-to-telomere assembly in one day. + +## Why Hifiasm? + +* Hifiasm delivers high-quality telomere-to-telomere assemblies. It tends to generate longer contigs + and resolve more segmental duplications than other assemblers. + +* Given Hi-C reads or short reads from the parents, hifiasm can produce overall the best + haplotype-resolved assembly so far. It is the assembler of choice by the + [Human Pangenome Project][hpp] for the first batch of samples. + +* Hifiasm can purge duplications between haplotigs without relying on + third-party tools such as purge\_dups. Hifiasm does not need polishing tools + like pilon or racon, either. This simplifies the assembly pipeline and saves + running time. + +* Hifiasm is fast. It can assemble a human genome in half a day and assemble a + ~30Gb redwood genome in three days. No genome is too large for hifiasm. + +* Hifiasm is trivial to install and easy to use. It does not required Python, + R or C++11 compilers, and can be compiled into a single executable. The + default setting works well with a variety of genomes. + +[hpp]: https://humanpangenome.org + +## Usage + +### Assembling HiFi reads without additional data types + +A typical hifiasm command line looks like: +```sh +hifiasm -o NA12878.asm -t 32 NA12878.fq.gz +``` +where `NA12878.fq.gz` provides the input reads, `-t` sets the number of CPUs in +use and `-o` specifies the prefix of output files. For this example, the +primary contigs are written to `NA12878.asm.bp.p_ctg.gfa`. +Since v0.15, hifiasm also produces two sets of +partially phased contigs at `NA12878.asm.bp.hap?.p_ctg.gfa`. This pair of files +can be thought to represent the two haplotypes in a diploid genome, though with +occasional switch errors. The frequency of switches is determined by the +heterozygosity of the input sample. + +At the first run, hifiasm saves corrected reads and +overlaps to disk as `NA12878.asm.*.bin`. It reuses the saved results to avoid +the time-consuming all-vs-all overlap calculation next time. You may specify +`-i` to ignore precomputed overlaps and redo overlapping from raw reads. +You can also dump error corrected reads in FASTA and read overlaps in PAF with +```sh +hifiasm -o NA12878.asm -t 32 --write-paf --write-ec /dev/null +``` + +Hifiasm purges haplotig duplications by default. For inbred or homozygous +genomes, you may disable purging with option `-l0`. Old HiFi reads may contain +short adapter sequences at the ends of reads. You can specify `-z20` to trim +both ends of reads by 20bp. For small genomes, use `-f0` to disable the initial +bloom filter which takes 16GB memory at the beginning. For genomes much larger +than human, applying `-f38` or even `-f39` is preferred to save memory on k-mer +counting. + +### Assembling ONT reads + +Since version 0.21.0 (r686), hifiasm can support ONT assembly using ONT simplex R10 reads. +To enable this feature, add the `--ont` option as shown below: +```sh +hifiasm -t64 --ont -o ONT.asm ONT.read.fastq.gz +``` +Please note that this module requires input reads in FASTQ format. + + +### Hi-C integration + +Hifiasm can generate a pair of haplotype-resolved assemblies with paired-end +Hi-C reads: +```sh +hifiasm -o NA12878.asm -t32 --h1 read1.fq.gz --h2 read2.fq.gz HiFi-reads.fq.gz +``` +In this mode, each contig is supposed to be a haplotig, which by definition +comes from one parental haplotype only. Hifiasm often puts all contigs from the +same parental chromosome in one assembly. It has cleanly separated chrX and +chrY for a human male dataset. Nonetheless, phasing across centromeres is +challenging. Hifiasm is often able to phase entire chromosomes but it may fail +in rare cases. Also, contigs from different parental chromosomes are randomly mixed as +it is just not possible to phase across chromosomes with Hi-C. + +Hifiasm does not perform scaffolding for now. You need to run a standalone +scaffolder such as SALSA or 3D-DNA to scaffold phased haplotigs. + +### Trio binning + +When parental short reads are available, hifiasm can also generate a pair of +haplotype-resolved assemblies with trio binning. To perform such assembly, you +need to count k-mers first with [yak][yak] first and then do assembly: +```sh +yak count -k31 -b37 -t16 -o pat.yak paternal.fq.gz +yak count -k31 -b37 -t16 -o mat.yak maternal.fq.gz +hifiasm -o NA12878.asm -t 32 -1 pat.yak -2 mat.yak NA12878.fq.gz +``` +Here `NA12878.asm.dip.hap1.p_ctg.gfa` and `NA12878.asm.dip.hap2.p_ctg.gfa` give the two +haplotype assemblies. In the binning mode, hifiasm does not purge haplotig +duplicates by default. Because hifiasm reuses saved overlaps, you can +generate both primary/alternate assemblies and trio binning assemblies with +```sh +hifiasm -o NA12878.asm -t 32 NA12878.fq.gz 2> NA12878.asm.pri.log +hifiasm -o NA12878.asm -t 32 -1 pat.yak -2 mat.yak /dev/null 2> NA12878.asm.trio.log +``` +The second command line will run much faster than the first. + +### Ultra-long ONT integration + +Hifiasm could integrate ultra-long ONT reads to produce the telomere-to-telomere assembly: +```sh +hifiasm -o NA12878.asm -t32 --ul ul.fq.gz HiFi-reads.fq.gz +``` +For the single-sample telomere-to-telomere assembly with Hi-C reads: +```sh +hifiasm -o NA12878.asm -t32 --ul ul.fq.gz --h1 read1.fq.gz --h2 read2.fq.gz HiFi-reads.fq.gz +``` +For the trio-binning telomere-to-telomere assembly: +```sh +hifiasm -o NA12878.asm -t32 --ul ul.fq.gz -1 pat.yak -2 mat.yak HiFi-reads.fq.gz +``` + +### Self-scaffolding + +For diploid haplotype-resolved genome assembly, hifiasm can further enhance assembly contiguity +by introducing scaffolding. It leverages the assemblies of the two haplotypes to scaffold each other. +Specifically, if there is a gap within the haplotype 1 assembly, hifiasm will use the corresponding +homologous region in haplotype 2 to scaffold haplotype 1. Below is an example using the `--dual-scaf` option. +```sh +hifiasm -o NA12878.asm -t32 --dual-scaf HiFi-reads.fq.gz +``` + +### Preserve more telomeres for T2T assemblies + +Hifiasm can preserve more telomeres by specifying the telomere motif using the `--telo-m` option. +Below is an example applied to human genome assembly. +```sh +hifiasm -o NA12878.asm -t32 --telo-m CCCTAA HiFi-reads.fq.gz +``` + +### Output files + +Hifiasm generates different types of assemblies based on the input data. +It also writes error corrected reads to the *prefix*.ec.bin binary file and +writes overlaps to *prefix*.ovlp.source.bin and *prefix*.ovlp.reverse.bin. +For more details, please see the complete [documentation][tutorial_output]. + +## Results + +The following table shows the statistics of several hifiasm primary assemblies assembled with v0.12: + +|Dataset|Size|Cov.|Asm options|CPU time|Wall time|RAM| N50| +|:---------------|-----:|-----:|:---------------------|-------:|--------:|----:|----------------:| +|[Mouse (C57/BL6J)][mouse-data]|2.6Gb |×25|-t48 -l0 |172.9h |4.8h |76G |21.1Mb| +|[Maize (B73)][maize-data] |2.2Gb |×22|-t48 -l0 |203.2h |5.1h |68G |36.7Mb| +|[Strawberry][strawberry-data] |0.8Gb |×36|-t48 -D10|152.7h |3.7h |91G |17.8Mb| +|[Frog][frog-data] |9.5Gb |×29|-t48 |2834.3h|69.0h|463G|9.3Mb| +|[Redwood][redwood-data] |35.6Gb|×28|-t80 |3890.3h|65.5h|699G|5.4Mb| +|[Human (CHM13)][CHM13-data] |3.1Gb |×32|-t48 -l0 |310.7h |8.2h |114G|88.9Mb| +|[Human (HG00733)][HG00733-data]|3.1Gb|×33|-t48 |269.1h |6.9h |135G|69.9Mb| +|[Human (HG002)][NA24385-data] |3.1Gb |×36|-t48 |305.4h |7.7h |137G|98.7Mb| + +[mouse-data]: https://www.ncbi.nlm.nih.gov/sra/?term=SRR11606870 +[maize-data]: https://www.ncbi.nlm.nih.gov/sra/?term=SRR11606869 +[strawberry-data]: https://www.ncbi.nlm.nih.gov/sra/?term=SRR11606867 +[frog-data]: https://www.ncbi.nlm.nih.gov/sra?term=(SRR11606868)%20OR%20SRR12048570 +[redwood-data]: https://www.ncbi.nlm.nih.gov/sra/?term=SRP251156 +[CHM13-data]: https://www.ncbi.nlm.nih.gov/sra?term=(((SRR11292120)%20OR%20SRR11292121)%20OR%20SRR11292122)%20OR%20SRR11292123 + +Hifiasm can assemble a 3.1Gb human genome in several hours or a ~30Gb hexaploid +redwood genome in a few days on a single machine. For trio binning assembly: + +|Dataset|Cov.|CPU time|Elapsed time|RAM| N50| +|:---------------|-----:|-------:|--------:|----:|----------------:| +|[HG00733][HG00733-data], [\[father\]][HG00731-data], [\[mother\]][HG00732-data]|×33|269.1h|6.9h|135G|35.1Mb (paternal), 34.9Mb (maternal)| +|[HG002][NA24385-data], [\[father\]][NA24149-data], [\[mother\]][NA24143-data]|×36|305.4h|7.7h|137G|41.0Mb (paternal), 40.8Mb (maternal)| + + + +[HG00733-data]: https://www.ebi.ac.uk/ena/data/view/ERX3831682 +[HG00731-data]: https://www.ebi.ac.uk/ena/data/view/ERR3241754 +[HG00732-data]: https://www.ebi.ac.uk/ena/data/view/ERR3241755 +[NA24385-data]: https://www.ncbi.nlm.nih.gov/sra?term=(((SRR10382244)%20OR%20SRR10382245)%20OR%20SRR10382248)%20OR%20SRR10382249 +[NA24149-data]: https://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/data/AshkenazimTrio/HG003_NA24149_father/NIST_HiSeq_HG003_Homogeneity-12389378/HG003Run01-13262252/ +[NA24143-data]: https://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/data/AshkenazimTrio/HG004_NA24143_mother/NIST_HiSeq_HG004_Homogeneity-14572558/HG004Run01-15133132/ +[NA12878-data]: https://ftp-trace.ncbi.nlm.nih.gov/giab/ftp/data/NA12878/PacBio_SequelII_CCS_11kb/ +[NA12891-data]: https://www.ebi.ac.uk/ena/data/view/ERR194160 +[NA12892-data]: https://www.ebi.ac.uk/ena/data/view/ERR194161 + +Human assemblies above can be acquired [from Zenodo][zenodo-human] and +non-human ones are available [here][zenodo-nonh]. + +[zenodo-human]: https://zenodo.org/record/4393631 +[zenodo-nonh]: https://zenodo.org/record/4393750 +[unitig]: http://wgs-assembler.sourceforge.net/wiki/index.php/Celera_Assembler_Terminology +[gfa]: https://github.com/pmelsted/GFA-spec/blob/master/GFA-spec.md +[paf]: https://github.com/lh3/miniasm/blob/master/PAF.md +[yak]: https://github.com/lh3/yak +[tutorial]: https://hifiasm.readthedocs.io/en/latest/index.html +[tutorial_output]: https://hifiasm.readthedocs.io/en/latest/interpreting-output.html#interpreting-output + + +## Getting Help + +For detailed description of options, please see [tutorial][tutorial] or `man ./hifiasm.1`. The `-h` +option of hifiasm also provides brief description of options. If you have +further questions, please raise an issue at the [issue +page](https://github.com/chhylp123/hifiasm/issues). + +## Limitations + +1. Purging haplotig duplications may introduce misassemblies. + +## Citating Hifiasm + +If you use hifiasm in your work, please cite: + +> Cheng, H., Concepcion, G.T., Feng, X., Zhang, H., Li H. (2021) +> Haplotype-resolved de novo assembly using phased assembly graphs with +> hifiasm. *Nat Methods*, **18**:170-175. +> https://doi.org/10.1038/s41592-020-01056-5 + +> Cheng, H., Jarvis, E.D., Fedrigo, O., Koepfli, K.P., Urban, L., Gemmell, N.J., Li, H. (2022) +> Haplotype-resolved assembly of diploid genomes without parental data. +> *Nature Biotechnology*, **40**:1332–1335. +> https://doi.org/10.1038/s41587-022-01261-x + +> Cheng, H., Asri, M., Lucas, J., Koren, S., Li, H. (2024) +> Scalable telomere-to-telomere assembly for diploid and polyploid genomes with double graph. +> *Nat Methods*, **21**:967-970. +> https://doi.org/10.1038/s41592-024-02269-8 diff --git a/Trio.cpp b/Trio.cpp index 878b5c2..9d016f5 100644 --- a/Trio.cpp +++ b/Trio.cpp @@ -1,457 +1,550 @@ -#include -#include -#include -#include -#include -#include -#include "khashl.h" // hash table -#include "kthread.h" -#include "kseq.h" -#include "Process_Read.h" -#include "htab.h" -#include "CommandLines.h" - -#define YAK_MAX_KMER 31 -#define YAK_COUNTER_BITS 10 // yak uses 10, but hifiasm uses 12; we have to copy over some yak code here due to this -#define YAK_N_COUNTS (1<>YAK_COUNTER_BITS == (b)>>YAK_COUNTER_BITS) // lower 8 bits for counts; higher bits for k-mer -#define yak_ch_hash(a) ((a)>>YAK_COUNTER_BITS) -KHASHL_SET_INIT(static klib_unused, yak_ht_t, yak_ht, uint64_t, yak_ch_hash, yak_ch_eq) - -typedef const char *ha_cstr_t; -KHASHL_MAP_INIT(static klib_unused, cstr_ht_t, cstr_ht, ha_cstr_t, int64_t, kh_hash_str, kh_eq_str) - -KSTREAM_INIT(gzFile, gzread, 65536) - -typedef struct { - struct yak_ht_t *h; -} yak_ch1_t; - -typedef struct { - int k, pre, n_hash, n_shift; - uint64_t tot; - yak_ch1_t *h; -} yak_ch_t; - -static int yak_ch_get(const yak_ch_t *h, uint64_t x) -{ - int mask = (1<pre) - 1; - yak_ht_t *g = h->h[x&mask].h; - khint_t k; - k = yak_ht_get(g, x >> h->pre << YAK_COUNTER_BITS); - return k == kh_end(g)? -1 : kh_key(g, k)&YAK_MAX_COUNT; -} - -static yak_ch_t *yak_ch_init(int k, int pre) -{ - yak_ch_t *h; - int i; - if (pre < YAK_COUNTER_BITS) return 0; - CALLOC(h, 1); - h->k = k, h->pre = pre; - CALLOC(h->h, 1<pre); - for (i = 0; i < 1<pre; ++i) - h->h[i].h = yak_ht_init(); - return h; -} - -static yak_ch_t *yak_ch_restore_core(yak_ch_t *ch0, const char *fn, int mode, ...) -{ - va_list ap; - FILE *fp; - uint32_t t[3], f_tmp = 0; - char magic[4]; - int i, j, absent, min_cnt = 0, mid_cnt = 0, mode_err = 0; - uint64_t mask = (1ULL<= 4); - min_cnt = va_arg(ap, int); - mid_cnt = va_arg(ap, int); - if (ch0 == 0 && mode == YAK_LOAD_TRIOBIN2) - mode_err = 1; - } else mode_err = 1; - va_end(ap); - if (mode_err) return 0; - - if ((fp = fopen(fn, "rb")) == 0) return 0; - if (fread(magic, 1, 4, fp) != 4) return 0; - if (strncmp(magic, YAK_MAGIC, 4) != 0) { - fprintf(stderr, "ERROR: wrong file magic.\n"); - fclose(fp); - return 0; - } - f_tmp += fread(t, 4, 3, fp); - if (t[2] != YAK_COUNTER_BITS) { - fprintf(stderr, "ERROR: saved counter bits: %d; compile-time counter bits: %d\n", t[2], YAK_COUNTER_BITS); - fclose(fp); - return 0; - } - ///t[0] = k; t[1] = pre, t[2] = YAK_COUNTER_BITS; - ch = ch0 == 0? yak_ch_init(t[0], t[1]) : ch0; - assert((int)t[0] == ch->k && (int)t[1] == ch->pre); - for (i = 0; i < 1<pre; ++i) { - yak_ht_t *h = ch->h[i].h; - f_tmp += fread(t, 4, 2, fp); - ///t[0] = kh_capacity(h), t[1] = kh_size(h); - if (ch0 == 0) yak_ht_resize(h, t[0]); - for (j = 0; j < (int)t[1]; ++j) { - uint64_t key; - f_tmp += fread(&key, 8, 1, fp); - if (mode == YAK_LOAD_ALL) { - ++n_ins; - yak_ht_put(h, key, &absent); - if (absent) ++n_new; - } else if (mode == YAK_LOAD_TRIOBIN1 || mode == YAK_LOAD_TRIOBIN2) { - int cnt = key & mask, x, shift = mode == YAK_LOAD_TRIOBIN1? 0 : 2; - //1. filter singleton k-mer; 2. label non-repeat and repeat - if (cnt >= mid_cnt) x = 2<= min_cnt) x = 1<= 0) { - khint_t k; - ///no need cnt at all - key = (key & ~mask) | x; - ++n_ins; - k = yak_ht_put(h, key, &absent); - if (absent) ++n_new; - else kh_key(h, k) = kh_key(h, k) | x; - } - } - } - } - fclose(fp); - ///fprintf(stderr, "[M::%s] inserted %ld k-mers, of which %ld are new\n", __func__, (long)n_ins, (long)n_new); - return ch; -} - -static void yak_ch_destroy(yak_ch_t *h) -{ - int i; - if (h == 0) return; - for (i = 0; i < 1<pre; ++i) - yak_ht_destroy(h->h[i].h); - free(h->h); free(h); -} - -typedef struct { - int max; - uint32_t *s; -} tb_buf_t; - -typedef struct { - int k, n_threads, print_diff; - double ratio_thres; - const yak_ch_t *ch; - tb_buf_t *buf; - UC_Read *bseq; - All_reads* seq; -} tb_shared_t; - -typedef struct { - int c[16]; - int sc[2]; - int nk; -} tb_cnt_t; - -typedef struct { - int n_seq; - tb_shared_t *aux; -} tb_step_t; - -static char tb_classify(const int sc[2], const int *c, int k, double ratio_thres) -{ - char type; - if (sc[0] == 0 && sc[1] == 0) { - if (c[0<<2|2] == c[2<<2|0]) type = '0'; - else if (c[0<<2|2] >= k - 4 + c[2<<2|0] && (c[2<<2|0] <= 1 || c[0<<2|2] * 0.05 > c[2<<2|0])) type = 'p'; - else if (c[2<<2|0] >= k - 4 + c[0<<2|2] && (c[0<<2|2] <= 1 || c[2<<2|0] * 0.05 > c[0<<2|2])) type = 'm'; - else type = '0'; - } else if (sc[0] > k && sc[1] > k) { - type = 'a'; - } else if (sc[0] >= k - 4 + sc[1] && sc[0] * 0.05 >= sc[1] && c[0<<2|2] * ratio_thres > c[2<<2|0]) { - type = 'p'; - } else if (sc[1] >= k - 4 + sc[0] && sc[1] * 0.05 >= sc[0] && c[2<<2|0] * ratio_thres > c[0<<2|2]) { - type = 'm'; - } else { - type = 'a'; - } - return type; -} - -static void tb_worker(void *_data, long k, int tid) -{ - tb_shared_t *aux = (tb_shared_t*)_data; - UC_Read *s = &aux->bseq[tid]; - recover_UC_Read(s, aux->seq, k); - tb_buf_t *b = &aux->buf[tid]; - tb_cnt_t cnt; memset(&cnt, 0, sizeof(tb_cnt_t)); - uint64_t x[4], mask; - int i, l, shift; - if (aux->ch->k < 32) { - mask = (1ULL<<2*aux->ch->k) - 1; - shift = 2 * (aux->ch->k - 1); - } else { - mask = (1ULL<ch->k) - 1; - shift = aux->ch->k - 1; - } - if (s->length > b->max) { - b->max = s->length; - kroundup32(b->max); - b->s = (uint32_t*)realloc(b->s, b->max * sizeof(uint32_t)); - } - memset(b->s, 0, s->length * sizeof(uint32_t)); - for (i = l = 0, x[0] = x[1] = x[2] = x[3] = 0; i < s->length; ++i) { - int flag, c = seq_nt4_table[(uint8_t)s->seq[i]]; - if (c < 4) { - if (aux->ch->k < 32) { - x[0] = (x[0] << 2 | c) & mask; - x[1] = x[1] >> 2 | (uint64_t)(3 - c) << shift; - } else { - x[0] = (x[0] << 1 | (c&1)) & mask; - x[1] = (x[1] << 1 | (c>>1)) & mask; - x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; - x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; - } - if (++l >= aux->k) { - int type = 0, c1, c2; - uint64_t y; - ++cnt.nk; - if (aux->ch->k < 32) - y = yak_hash64(x[0] < x[1]? x[0] : x[1], mask); - else - y = yak_hash_long(x); - flag = yak_ch_get(aux->ch, y); - if (flag < 0) flag = 0; - c1 = flag&3, c2 = flag>>2&3; - if (c1 == 2 && c2 == 0) type = 1; - else if (c2 == 2 && c1 == 0) type = 2; - b->s[i] = type; - ++cnt.c[flag]; - } - } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; - } - for (l = 0, i = 1; i <= s->length; ++i) { - if (i == s->length || b->s[i] != b->s[l]) { - if (b->s[l] > 0 && i - l >= aux->k - 4) - cnt.sc[b->s[l] - 1] += i - l; - l = i; - } - } - - int *c = cnt.c; - char type; - type = tb_classify(cnt.sc, c, aux->k, aux->ratio_thres); - aux->seq->trio_flag[k] = AMBIGU; - if(type == 'p') aux->seq->trio_flag[k] = FATHER; - if(type == 'm') aux->seq->trio_flag[k] = MOTHER; -} - -static void ha_triobin_yak(const hifiasm_opt_t *opt) -{ - yak_ch_t *ch; - int i /**, min_cnt = 2, mid_cnt = 5**/; - tb_shared_t aux; - memset(&aux, 0, sizeof(tb_shared_t)); - aux.n_threads = opt->thread_num, aux.print_diff = 0; - aux.ratio_thres = 0.33; - aux.seq = &R_INF; - - ch = yak_ch_restore_core(0, opt->fn_bin_yak[0], YAK_LOAD_TRIOBIN1, opt->min_cnt, opt->mid_cnt); - ch = yak_ch_restore_core(ch, opt->fn_bin_yak[1], YAK_LOAD_TRIOBIN2, opt->min_cnt, opt->mid_cnt); - - aux.k = ch->k; - aux.ch = ch; - aux.buf = (tb_buf_t*)calloc(aux.n_threads, sizeof(tb_buf_t)); - aux.bseq = (UC_Read*)calloc(aux.n_threads, sizeof(UC_Read)); - for (i = 0; i < aux.n_threads; ++i) - init_UC_Read(&aux.bseq[i]); - - kt_for(aux.n_threads, tb_worker, &aux, aux.seq->total_reads); - - for (i = 0; i < aux.n_threads; ++i) { - free(aux.buf[i].s); - destory_UC_Read(&aux.bseq[i]); - } - free(aux.buf); - free(aux.bseq); - yak_ch_destroy(ch); - - fprintf(stderr, "[M::%s::%.3f*%.2f] ==> partitioned reads using yak dumps\n", __func__, yak_realtime(), yak_cpu_usage()); -} - -static int ha_triobin_set_list(const cstr_ht_t *h, const char *fn, int flag) -{ - gzFile fp; - kstream_t *ks; - kstring_t str = {0,0,0}; - int dret; - int64_t n_tot = 0, n_bin = 0; - fp = gzopen(fn, "r"); - if (fp == 0) { - fprintf(stderr, "ERROR: failed to open file '%s'\n", fn); - return -1; - } - ks = ks_init(fp); - while (ks_getuntil(ks, KS_SEP_LINE, &str, &dret) >= 0) { - char *p; - khint_t k; - ++n_tot; - for (p = str.s; *p; ++p) - if (*p == '\t' || *p == ' ') - *p = 0; - k = cstr_ht_get(h, str.s); - if (k != kh_end(h)) { - R_INF.trio_flag[kh_val(h, k)] = flag; - ++n_bin; - } - } - free(str.s); - ks_destroy(ks); - gzclose(fp); - fprintf(stderr, "[M::%s::%.3f*%.2f] flagged %ld reads, out of %ld lines in file '%s'\n", - __func__, yak_realtime(), yak_cpu_usage(), (long)n_bin, (long)n_tot, fn); - return 0; -} - -static void ha_triobin_list(const hifiasm_opt_t *opt) -{ - int64_t i; - khint_t k; - cstr_ht_t *h; - assert(R_INF.total_reads < (uint32_t)-1); - h = cstr_ht_init(); - for (i = 0; i < (int64_t)R_INF.total_reads; ++i) { - int absent; - char *str = (char*)calloc(Get_NAME_LENGTH(R_INF, i) + 1, 1); - strncpy(str, Get_NAME(R_INF, i), Get_NAME_LENGTH(R_INF, i)); - k = cstr_ht_put(h, str, &absent); - if (absent) kh_val(h, k) = i; - } - fprintf(stderr, "[M::%s::%.3f*%.2f] created the hash table for read names\n", __func__, yak_realtime(), yak_cpu_usage()); - ha_triobin_set_list(h, opt->fn_bin_list[0], FATHER); - ha_triobin_set_list(h, opt->fn_bin_list[1], MOTHER); - for (k = 0; k < kh_end(h); ++k) - if (kh_exist(h, k)) - free((char*)kh_key(h, k)); - cstr_ht_destroy(h); - fprintf(stderr, "[M::%s::%.3f*%.2f] ==> partitioned reads with external lists\n", __func__, yak_realtime(), yak_cpu_usage()); -} - -uint32_t test_yak_binning(char* fn, char *cmd) -{ - gzFile fp; kstream_t *ks; kstring_t str = {0,0,0}; - int dret, eq = 0; fp = gzopen(fn, "r"); - if (fp == 0) return eq; - ks = ks_init(fp); - if(ks_getuntil(ks, KS_SEP_LINE, &str, &dret) >= 0) { - uint64_t sl = strlen(str.s), z; - for (z = 0; (z < sl) && (str.s[z]!='\t'); z++); - if(((z+1)fn_bin_poy, "r"); - if (fp == 0) { - fprintf(stderr, "ERROR: failed to open file '%s'\n", opt->fn_bin_poy); - for (k = 0; k < kh_end(h); ++k) - if (kh_exist(h, k)) - free((char*)kh_key(h, k)); - cstr_ht_destroy(h); - return NULL; - } - CALLOC(ss, R_INF.total_reads); - ks = ks_init(fp); - while (ks_getuntil(ks, KS_SEP_LINE, &str, &dret) >= 0) { - khint_t k; ++n_tot; - phrase_hstatus(str.s, &rname, &hid); - if((!(*rname)) || hid == (uint32_t)-1) { - fprintf(stderr, "ERROR: wrong hap status\n"); - continue; - } - k = cstr_ht_get(h, rname); - if (k != kh_end(h)) { - ss[kh_val(h, k)] |= (((uint32_t)1)<<(hid-1)); - ++n_bin; - } - } - free(str.s); - ks_destroy(ks); - gzclose(fp); - - for (k = 0; k < kh_end(h); ++k) - if (kh_exist(h, k)) - free((char*)kh_key(h, k)); - cstr_ht_destroy(h); - fprintf(stderr, "[M::%s::%.3f*%.2f] ==> partitioned reads with external lists\n", __func__, yak_realtime(), yak_cpu_usage()); - return ss; -} - -void ha_triobin(const hifiasm_opt_t *opt) -{ - memset(R_INF.trio_flag, AMBIGU, R_INF.total_reads * sizeof(uint8_t)); - if (opt->fn_bin_list[0] && opt->fn_bin_list[1]) - ha_triobin_list(opt); - if (opt->fn_bin_yak[0] && opt->fn_bin_yak[1]) - ha_triobin_yak(opt); -} +#include +#include +#include +#include +#include +#include +#include "khashl.h" // hash table +#include "kthread.h" +#include "kseq.h" +#include "Process_Read.h" +#include "htab.h" +#include "CommandLines.h" + +#define YAK_MAX_KMER 31 +#define YAK_COUNTER_BITS 10 // yak uses 10, but hifiasm uses 12; we have to copy over some yak code here due to this +#define YAK_N_COUNTS (1<>YAK_COUNTER_BITS == (b)>>YAK_COUNTER_BITS) // lower 8 bits for counts; higher bits for k-mer +#define yak_ch_hash(a) ((a)>>YAK_COUNTER_BITS) +KHASHL_SET_INIT(static klib_unused, yak_ht_t, yak_ht, uint64_t, yak_ch_hash, yak_ch_eq) + +typedef const char *ha_cstr_t; +KHASHL_MAP_INIT(static klib_unused, cstr_ht_t, cstr_ht, ha_cstr_t, int64_t, kh_hash_str, kh_eq_str) + +KSTREAM_INIT(gzFile, gzread, 65536) + +typedef struct { + struct yak_ht_t *h; +} yak_ch1_t; + +typedef struct { + int k, pre, n_hash, n_shift; + uint64_t tot; + yak_ch1_t *h; +} yak_ch_t; + +static int yak_ch_get(const yak_ch_t *h, uint64_t x) +{ + int mask = (1<pre) - 1; + yak_ht_t *g = h->h[x&mask].h; + khint_t k; + k = yak_ht_get(g, x >> h->pre << YAK_COUNTER_BITS); + return k == kh_end(g)? -1 : kh_key(g, k)&YAK_MAX_COUNT; +} + +static yak_ch_t *yak_ch_init(int k, int pre) +{ + yak_ch_t *h; + int i; + if (pre < YAK_COUNTER_BITS) return 0; + CALLOC(h, 1); + h->k = k, h->pre = pre; + CALLOC(h->h, 1<pre); + for (i = 0; i < 1<pre; ++i) + h->h[i].h = yak_ht_init(); + return h; +} + +static yak_ch_t *yak_ch_restore_core(yak_ch_t *ch0, const char *fn, int mode, ...) +{ + va_list ap; + FILE *fp; + uint32_t t[3], f_tmp = 0; + char magic[4]; + int i, j, absent, min_cnt = 0, mid_cnt = 0, mode_err = 0; + uint64_t mask = (1ULL<= 4); + min_cnt = va_arg(ap, int); + mid_cnt = va_arg(ap, int); + if (ch0 == 0 && mode == YAK_LOAD_TRIOBIN2) + mode_err = 1; + } else mode_err = 1; + va_end(ap); + if (mode_err) return 0; + + if ((fp = fopen(fn, "rb")) == 0) return 0; + if (fread(magic, 1, 4, fp) != 4) return 0; + if (strncmp(magic, YAK_MAGIC, 4) != 0) { + fprintf(stderr, "ERROR: wrong file magic.\n"); + fclose(fp); + return 0; + } + f_tmp += fread(t, 4, 3, fp); + if (t[2] != YAK_COUNTER_BITS) { + fprintf(stderr, "ERROR: saved counter bits: %d; compile-time counter bits: %d\n", t[2], YAK_COUNTER_BITS); + fclose(fp); + return 0; + } + ///t[0] = k; t[1] = pre, t[2] = YAK_COUNTER_BITS; + ch = ch0 == 0? yak_ch_init(t[0], t[1]) : ch0; + assert((int)t[0] == ch->k && (int)t[1] == ch->pre); + for (i = 0; i < 1<pre; ++i) { + yak_ht_t *h = ch->h[i].h; + f_tmp += fread(t, 4, 2, fp); + ///t[0] = kh_capacity(h), t[1] = kh_size(h); + if (ch0 == 0) yak_ht_resize(h, t[0]); + for (j = 0; j < (int)t[1]; ++j) { + uint64_t key; + f_tmp += fread(&key, 8, 1, fp); + if (mode == YAK_LOAD_ALL) { + ++n_ins; + yak_ht_put(h, key, &absent); + if (absent) ++n_new; + } else if (mode == YAK_LOAD_TRIOBIN1 || mode == YAK_LOAD_TRIOBIN2) { + int cnt = key & mask, x, shift = mode == YAK_LOAD_TRIOBIN1? 0 : 2; + //1. filter singleton k-mer; 2. label non-repeat and repeat + if (cnt >= mid_cnt) x = 2<= min_cnt) x = 1<= 0) { + khint_t k; + ///no need cnt at all + key = (key & ~mask) | x; + ++n_ins; + k = yak_ht_put(h, key, &absent); + if (absent) ++n_new; + else kh_key(h, k) = kh_key(h, k) | x; + } + } + } + } + fclose(fp); + ///fprintf(stderr, "[M::%s] inserted %ld k-mers, of which %ld are new\n", __func__, (long)n_ins, (long)n_new); + return ch; +} + +static void yak_ch_destroy(yak_ch_t *h) +{ + int i; + if (h == 0) return; + for (i = 0; i < 1<pre; ++i) + yak_ht_destroy(h->h[i].h); + free(h->h); free(h); +} + +typedef struct { + int max; + uint32_t *s; +} tb_buf_t; + +typedef struct { + int k, n_threads, print_diff; + double ratio_thres; + const yak_ch_t *ch; + tb_buf_t *buf; + UC_Read *bseq; + All_reads* seq; +} tb_shared_t; + +typedef struct { + int c[16]; + int sc[2]; + int nk; +} tb_cnt_t; + +typedef struct { + int n_seq; + tb_shared_t *aux; +} tb_step_t; + +static char tb_classify(const int sc[2], const int *c, int k, double ratio_thres) +{ + char type; + if (sc[0] == 0 && sc[1] == 0) { + if (c[0<<2|2] == c[2<<2|0]) type = '0'; + else if (c[0<<2|2] >= k - 4 + c[2<<2|0] && (c[2<<2|0] <= 1 || c[0<<2|2] * 0.05 > c[2<<2|0])) type = 'p'; + else if (c[2<<2|0] >= k - 4 + c[0<<2|2] && (c[0<<2|2] <= 1 || c[2<<2|0] * 0.05 > c[0<<2|2])) type = 'm'; + else type = '0'; + } else if (sc[0] > k && sc[1] > k) { + type = 'a'; + } else if (sc[0] >= k - 4 + sc[1] && sc[0] * 0.05 >= sc[1] && c[0<<2|2] * ratio_thres > c[2<<2|0]) { + type = 'p'; + } else if (sc[1] >= k - 4 + sc[0] && sc[1] * 0.05 >= sc[0] && c[2<<2|0] * ratio_thres > c[0<<2|2]) { + type = 'm'; + } else { + type = 'a'; + } + return type; +} + +static void tb_worker(void *_data, long k, int tid) +{ + tb_shared_t *aux = (tb_shared_t*)_data; + UC_Read *s = &aux->bseq[tid]; + recover_UC_Read(s, aux->seq, k); + tb_buf_t *b = &aux->buf[tid]; + tb_cnt_t cnt; memset(&cnt, 0, sizeof(tb_cnt_t)); + uint64_t x[4], mask; + int i, l, shift; + if (aux->ch->k < 32) { + mask = (1ULL<<2*aux->ch->k) - 1; + shift = 2 * (aux->ch->k - 1); + } else { + mask = (1ULL<ch->k) - 1; + shift = aux->ch->k - 1; + } + if (s->length > b->max) { + b->max = s->length; + kroundup32(b->max); + b->s = (uint32_t*)realloc(b->s, b->max * sizeof(uint32_t)); + } + memset(b->s, 0, s->length * sizeof(uint32_t)); + for (i = l = 0, x[0] = x[1] = x[2] = x[3] = 0; i < s->length; ++i) { + int flag, c = seq_nt4_table[(uint8_t)s->seq[i]]; + if (c < 4) { + if (aux->ch->k < 32) { + x[0] = (x[0] << 2 | c) & mask; + x[1] = x[1] >> 2 | (uint64_t)(3 - c) << shift; + } else { + x[0] = (x[0] << 1 | (c&1)) & mask; + x[1] = (x[1] << 1 | (c>>1)) & mask; + x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; + x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; + } + if (++l >= aux->k) { + int type = 0, c1, c2; + uint64_t y; + ++cnt.nk; + if (aux->ch->k < 32) + y = yak_hash64(x[0] < x[1]? x[0] : x[1], mask); + else + y = yak_hash_long(x); + flag = yak_ch_get(aux->ch, y); + if (flag < 0) flag = 0; + c1 = flag&3, c2 = flag>>2&3; + if (c1 == 2 && c2 == 0) type = 1; + else if (c2 == 2 && c1 == 0) type = 2; + b->s[i] = type; + ++cnt.c[flag]; + } + } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; + } + for (l = 0, i = 1; i <= s->length; ++i) { + if (i == s->length || b->s[i] != b->s[l]) { + if (b->s[l] > 0 && i - l >= aux->k - 4) + cnt.sc[b->s[l] - 1] += i - l; + l = i; + } + } + + int *c = cnt.c; + char type; + type = tb_classify(cnt.sc, c, aux->k, aux->ratio_thres); + aux->seq->trio_flag[k] = AMBIGU; + if(type == 'p') aux->seq->trio_flag[k] = FATHER; + if(type == 'm') aux->seq->trio_flag[k] = MOTHER; +} + +static void ha_triobin_yak(const hifiasm_opt_t *opt) +{ + yak_ch_t *ch; + int i /**, min_cnt = 2, mid_cnt = 5**/; + tb_shared_t aux; + memset(&aux, 0, sizeof(tb_shared_t)); + aux.n_threads = opt->thread_num, aux.print_diff = 0; + aux.ratio_thres = 0.33; + aux.seq = &R_INF; + + ch = yak_ch_restore_core(0, opt->fn_bin_yak[0], YAK_LOAD_TRIOBIN1, opt->min_cnt, opt->mid_cnt); + ch = yak_ch_restore_core(ch, opt->fn_bin_yak[1], YAK_LOAD_TRIOBIN2, opt->min_cnt, opt->mid_cnt); + + aux.k = ch->k; + aux.ch = ch; + aux.buf = (tb_buf_t*)calloc(aux.n_threads, sizeof(tb_buf_t)); + aux.bseq = (UC_Read*)calloc(aux.n_threads, sizeof(UC_Read)); + for (i = 0; i < aux.n_threads; ++i) + init_UC_Read(&aux.bseq[i]); + + kt_for(aux.n_threads, tb_worker, &aux, aux.seq->total_reads); + + for (i = 0; i < aux.n_threads; ++i) { + free(aux.buf[i].s); + destory_UC_Read(&aux.bseq[i]); + } + free(aux.buf); + free(aux.bseq); + yak_ch_destroy(ch); + + fprintf(stderr, "[M::%s::%.3f*%.2f] ==> partitioned reads using yak dumps\n", __func__, yak_realtime(), yak_cpu_usage()); +} + +static int ha_triobin_set_list(const cstr_ht_t *h, const char *fn, int flag) +{ + gzFile fp; + kstream_t *ks; + kstring_t str = {0,0,0}; + int dret; + int64_t n_tot = 0, n_bin = 0; + fp = gzopen(fn, "r"); + if (fp == 0) { + fprintf(stderr, "ERROR: failed to open file '%s'\n", fn); + return -1; + } + ks = ks_init(fp); + while (ks_getuntil(ks, KS_SEP_LINE, &str, &dret) >= 0) { + char *p; + khint_t k; + ++n_tot; + for (p = str.s; *p; ++p) + if (*p == '\t' || *p == ' ') + *p = 0; + k = cstr_ht_get(h, str.s); + if (k != kh_end(h)) { + R_INF.trio_flag[kh_val(h, k)] = flag; + ++n_bin; + } + } + free(str.s); + ks_destroy(ks); + gzclose(fp); + fprintf(stderr, "[M::%s::%.3f*%.2f] flagged %ld reads, out of %ld lines in file '%s'\n", + __func__, yak_realtime(), yak_cpu_usage(), (long)n_bin, (long)n_tot, fn); + return 0; +} + +static void ha_triobin_list(const hifiasm_opt_t *opt) +{ + int64_t i; + khint_t k; + cstr_ht_t *h; + assert(R_INF.total_reads < (uint32_t)-1); + h = cstr_ht_init(); + for (i = 0; i < (int64_t)R_INF.total_reads; ++i) { + int absent; + char *str = (char*)calloc(Get_NAME_LENGTH(R_INF, i) + 1, 1); + strncpy(str, Get_NAME(R_INF, i), Get_NAME_LENGTH(R_INF, i)); + k = cstr_ht_put(h, str, &absent); + if (absent) kh_val(h, k) = i; + } + fprintf(stderr, "[M::%s::%.3f*%.2f] created the hash table for read names\n", __func__, yak_realtime(), yak_cpu_usage()); + ha_triobin_set_list(h, opt->fn_bin_list[0], FATHER); + ha_triobin_set_list(h, opt->fn_bin_list[1], MOTHER); + for (k = 0; k < kh_end(h); ++k) + if (kh_exist(h, k)) + free((char*)kh_key(h, k)); + cstr_ht_destroy(h); + fprintf(stderr, "[M::%s::%.3f*%.2f] ==> partitioned reads with external lists\n", __func__, yak_realtime(), yak_cpu_usage()); +} + +uint32_t test_yak_binning(char* fn, char *cmd) +{ + gzFile fp; kstream_t *ks; kstring_t str = {0,0,0}; + int dret, eq = 0; fp = gzopen(fn, "r"); + if (fp == 0) return eq; + ks = ks_init(fp); + if(ks_getuntil(ks, KS_SEP_LINE, &str, &dret) >= 0) { + uint64_t sl = strlen(str.s), z; + for (z = 0; (z < sl) && (str.s[z]!='\t'); z++); + if(((z+1) l) { + s[k] = 0; + if(tot == 0) { + *rname = s + l; + } else if(tot == 1) { + for (z = l; (z < k) && (s[z] >= '0') && (s[z] <= '9'); ++z); + if(z < k) { + fprintf(stderr, "ERROR: wrong hap id\n"); + return; + } + *hid = atoi(s + l); + } + tot++; + } + l = k + 1; + } + } +} + +uint32_t *ha_polybin_list(const hifiasm_opt_t *opt) +{ + int64_t i; + khint_t k; + cstr_ht_t *h; + assert(R_INF.total_reads < (uint32_t)-1); + h = cstr_ht_init(); + for (i = 0; i < (int64_t)R_INF.total_reads; ++i) { + int absent; + char *str = (char*)calloc(Get_NAME_LENGTH(R_INF, i) + 1, 1); + strncpy(str, Get_NAME(R_INF, i), Get_NAME_LENGTH(R_INF, i)); + k = cstr_ht_put(h, str, &absent); + if (absent) kh_val(h, k) = i; + } + fprintf(stderr, "[M::%s::%.3f*%.2f] created the hash table for read names\n", __func__, yak_realtime(), yak_cpu_usage()); + + gzFile fp; + kstream_t *ks; + kstring_t str = {0,0,0}; + char *rname = NULL; + uint32_t hid, *ss = NULL; + int dret; + int64_t n_tot = 0, n_bin = 0; + fp = gzopen(opt->fn_bin_poy, "r"); + if (fp == 0) { + fprintf(stderr, "ERROR: failed to open file '%s'\n", opt->fn_bin_poy); + for (k = 0; k < kh_end(h); ++k) + if (kh_exist(h, k)) + free((char*)kh_key(h, k)); + cstr_ht_destroy(h); + return NULL; + } + CALLOC(ss, R_INF.total_reads); + ks = ks_init(fp); + while (ks_getuntil(ks, KS_SEP_LINE, &str, &dret) >= 0) { + khint_t k; ++n_tot; + phrase_hstatus(str.s, &rname, &hid); + if((!(*rname)) || hid == (uint32_t)-1) { + fprintf(stderr, "ERROR: wrong hap status\n"); + continue; + } + k = cstr_ht_get(h, rname); + if (k != kh_end(h)) { + ss[kh_val(h, k)] |= (((uint32_t)1)<<(hid-1)); + ++n_bin; + } + } + free(str.s); + ks_destroy(ks); + gzclose(fp); + + for (k = 0; k < kh_end(h); ++k) + if (kh_exist(h, k)) + free((char*)kh_key(h, k)); + cstr_ht_destroy(h); + fprintf(stderr, "[M::%s::%.3f*%.2f] ==> partitioned reads with external lists\n", __func__, yak_realtime(), yak_cpu_usage()); + return ss; +} + +uint32_t *ha_charbin_list(const hifiasm_opt_t *opt, uint8_t **idx, uint32_t *idx_n) +{ + int64_t i; + khint_t k; + cstr_ht_t *h; (*idx) = NULL; *idx_n = 0; + assert(R_INF.total_reads < (uint32_t)-1); + h = cstr_ht_init(); + for (i = 0; i < (int64_t)R_INF.total_reads; ++i) { + int absent; + char *str = (char*)calloc(Get_NAME_LENGTH(R_INF, i) + 1, 1); + strncpy(str, Get_NAME(R_INF, i), Get_NAME_LENGTH(R_INF, i)); + k = cstr_ht_put(h, str, &absent); + if (absent) kh_val(h, k) = i; + } + fprintf(stderr, "[M::%s::%.3f*%.2f] created the hash table for read names\n", __func__, yak_realtime(), yak_cpu_usage()); + + gzFile fp; + kstream_t *ks; + kstring_t str = {0,0,0}; + char *rname = NULL; + uint32_t hid, mhid = 0, *ss = NULL; + int dret; + int64_t n_tot = 0, n_bin = 0; + fp = gzopen(opt->fn_chr_bin, "r"); + if (fp == 0) { + fprintf(stderr, "ERROR: failed to open file '%s'\n", opt->fn_chr_bin); + for (k = 0; k < kh_end(h); ++k) + if (kh_exist(h, k)) + free((char*)kh_key(h, k)); + cstr_ht_destroy(h); + return NULL; + } + MALLOC(ss, R_INF.total_reads); memset(ss, -1, sizeof((*ss))*R_INF.total_reads); + ks = ks_init(fp); + while (ks_getuntil(ks, KS_SEP_LINE, &str, &dret) >= 0) { + khint_t k; ++n_tot; + phrase_hchar(str.s, &rname, &hid); + if((!(*rname)) || hid == (uint32_t)-1) { + fprintf(stderr, "ERROR: wrong hap id\n"); + continue; + } + k = cstr_ht_get(h, rname); + if (k != kh_end(h)) { + ss[kh_val(h, k)] = hid; + if(hid > mhid) mhid = hid; + ++n_bin; + // fprintf(stderr, "%s\t%u\trid::%ld\n", rname, hid, kh_val(h, k)); + } + } + free(str.s); + ks_destroy(ks); + gzclose(fp); + + for (k = 0; k < kh_end(h); ++k) + if (kh_exist(h, k)) + free((char*)kh_key(h, k)); + cstr_ht_destroy(h); + + mhid++; CALLOC((*idx), mhid); + for (i = 0; i < (int64_t)R_INF.total_reads; ++i) { + if(ss[i] >= mhid) continue; + (*idx)[ss[i]] = 1; + } + *idx_n = mhid; + fprintf(stderr, "[M::%s::%.3f*%.2f] ==> partitioned reads with external lists\n", __func__, yak_realtime(), yak_cpu_usage()); + return ss; +} + +void ha_triobin(const hifiasm_opt_t *opt) +{ + memset(R_INF.trio_flag, AMBIGU, R_INF.total_reads * sizeof(uint8_t)); + if (opt->fn_bin_list[0] && opt->fn_bin_list[1]) + ha_triobin_list(opt); + if (opt->fn_bin_yak[0] && opt->fn_bin_yak[1]) + ha_triobin_yak(opt); +} diff --git a/anchor.cpp b/anchor.cpp index aeff331..6a69b87 100644 --- a/anchor.cpp +++ b/anchor.cpp @@ -1,3639 +1,4029 @@ -#include -#include -#include -#include "htab.h" -#include "ksort.h" -#include "Hash_Table.h" -#include "kalloc.h" -#include "Overlaps.h" -#include "Levenshtein_distance.h" - -#define HA_KMER_GOOD_RATIO 0.333 -#define OFL 0.95 -#define CH_OCC 4 -#define CH_SC 16 - -typedef struct { // this struct is not strictly necessary; we can use k_mer_pos instead, with modifications - uint64_t srt; - uint32_t self_off; - uint32_t other_off; - uint32_t cnt; -} anchor1_t; - -#define an_key1(a) ((a).srt) -#define an_key2(a) ((a).self_off) -#define an_key3(a) ((a).other_off) -KRADIX_SORT_INIT(ha_an1, anchor1_t, an_key1, 8) -KRADIX_SORT_INIT(ha_an2, anchor1_t, an_key2, 4) -KRADIX_SORT_INIT(ha_an3, anchor1_t, an_key3, 4) -#define generic_key(x) (x) -KRADIX_SORT_INIT(anc64, uint64_t, generic_key, 8) - -#define oreg_xs_lt(a, b) (((uint64_t)(a).x_pos_s<<32|(a).x_pos_e) < ((uint64_t)(b).x_pos_s<<32|(b).x_pos_e)) -KSORT_INIT(or_xs, overlap_region, oreg_xs_lt) - -#define oreg_ss_lt(a, b) ((a).shared_seed > (b).shared_seed) // in the decending order -KSORT_INIT(or_ss, overlap_region, oreg_ss_lt) - -#define oreg_occ_lt(a, b) ((a).align_length > (b).align_length) // in the decending order -KSORT_INIT(or_occ, overlap_region, oreg_occ_lt) - -#define oreg_id_lt(a, b) ((a).y_id < (b).y_id) -KSORT_INIT(or_id, overlap_region, oreg_id_lt) - -#define ha_mz1_t_key(p) ((p).x) -KRADIX_SORT_INIT(ha_mz1_v_srt, ha_mz1_t, ha_mz1_t_key, member_size(ha_mz1_t, x)) - -typedef struct { - int n; - const ha_idxpos_t *a; -} seed1_t; - -typedef struct { - int n, cnt; - const ha_idxposl_t *a; -} seedl_t; - -struct ha_abuf_s { - uint64_t n_a, m_a;///number of anchors (seed positions) - uint32_t old_mz_m;///number of seeds - ha_mz1_v mz; - seed1_t *seed; - anchor1_t *a; -}; - -struct ha_abufl_s { - uint64_t n_a, m_a;///number of anchors (seed positions) - uint32_t old_mz_m;///number of seeds - ha_mzl_v mz; - seedl_t *seed; - anchor1_t *a; -}; - -#define HA_ABUF_INIT(HType, MZType, SDType, sf) \ -HType *sf##_init_buf(void *km){HType *b = NULL; KCALLOC((km), b, 1); return b;}\ -HType *sf##_init(void){return (HType*)calloc(1, sizeof(HType));}\ -void sf##_free_buf(void *km, HType *ab, int is_z){if(ab){kfree(km, ab->seed); kfree(km, ab->a); kfree(km, ab->mz.a); if((is_z)){memset(ab, 0, sizeof(*ab));}}}\ -void sf##_destroy_buf(void *km, HType *ab){if(ab){kfree(km, ab->seed); kfree(km, ab->a); kfree(km, ab->mz.a); kfree(km, ab);}}\ -void sf##_destroy(HType *ab){if(ab){free(ab->seed); free(ab->a); free(ab->mz.a); free(ab);}}\ -uint64_t sf##_mem(const HType *ab){\ - return ab->m_a * sizeof(anchor1_t) + ab->mz.m * (sizeof(MZType) + sizeof(SDType)) + sizeof(HType);\ -} - -HA_ABUF_INIT(ha_abuf_s, ha_mz1_t, seed1_t, ha_abuf) -HA_ABUF_INIT(ha_abufl_s, ha_mzl_t, seedl_t, ha_abufl) - -int ha_ov_type(const overlap_region *r, uint32_t len) -{ - if (r->x_pos_s == 0 && r->x_pos_e == len - 1) return 2; // contained in a longer read - else if (r->x_pos_s > 0 && r->x_pos_e < len - 1) return 3; // containing a shorter read - else return r->x_pos_s == 0? 0 : 1; -} - -void ha_get_new_candidates(ha_abuf_t *ab, int64_t rid, UC_Read *ucr, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, int max_n_chain, int keep_whole_chain, - kvec_t_u8_warp* k_flag, kvec_t_u64_warp* chain_idx, void *ha_flt_tab, ha_pt_t *ha_idx, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp) -{ - uint32_t i, rlen; - uint64_t k, l; - uint32_t low_occ = asm_opt.hom_cov * HA_KMER_GOOD_RATIO; - uint32_t high_occ = asm_opt.hom_cov * (2.0 - HA_KMER_GOOD_RATIO); - if(low_occ < 2) low_occ = 2; - - // prepare - clear_Candidates_list(cl); - clear_overlap_region_alloc(overlap_list); - recover_UC_Read(ucr, &R_INF, rid); - ab->mz.n = 0, ab->n_a = 0; - rlen = Get_READ_LENGTH(R_INF, rid); // read length - - // get the list of anchors - mz1_ha_sketch(ucr->seq, ucr->length, asm_opt.mz_win, asm_opt.k_mer_length, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); - // minimizer of queried read - if (ab->mz.m > ab->old_mz_m) { - ab->old_mz_m = ab->mz.m; - REALLOC(ab->seed, ab->old_mz_m); - } - for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { - int n; - ab->seed[i].a = ha_pt_get(ha_idx, ab->mz.a[i].x, &n); - ab->seed[i].n = n; - ab->n_a += n; - } - if (ab->n_a > ab->m_a) { - ab->m_a = ab->n_a; - kroundup64(ab->m_a); - REALLOC(ab->a, ab->m_a); - } - for (i = 0, k = 0; i < ab->mz.n; ++i) { - int j; - ///z is one of the minimizer - ha_mz1_t *z = &ab->mz.a[i]; - seed1_t *s = &ab->seed[i]; - for (j = 0; j < s->n; ++j) { - const ha_idxpos_t *y = &s->a[j]; - anchor1_t *an = &ab->a[k++]; - uint8_t rev = z->rev == y->rev? 0 : 1; - an->other_off = y->pos; - an->self_off = rev? ucr->length - 1 - (z->pos + 1 - z->span) : z->pos; - an->cnt = s->n; - an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->other_off; - } - } - - // sort anchors - radix_sort_ha_an1(ab->a, ab->a + ab->n_a); - for (k = 1, l = 0; k <= ab->n_a; ++k) { - if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { - if (k - l > 1) - radix_sort_ha_an2(ab->a + l, ab->a + k); - l = k; - } - } - - - // copy over to _cl_ - if (ab->m_a >= (uint64_t)cl->size) { - cl->size = ab->m_a; - REALLOC(cl->list, cl->size); - } - for (k = 0; k < ab->n_a; ++k) { - k_mer_hit *p = &cl->list[k]; - p->readID = ab->a[k].srt >> 33; - p->strand = ab->a[k].srt >> 32 & 1; - p->offset = ab->a[k].other_off; - p->self_offset = ab->a[k].self_off; - if(ab->a[k].cnt > low_occ && ab->a[k].cnt < high_occ){ - p->cnt = 1; - } - else if(ab->a[k].cnt <= low_occ){ - p->cnt = 2; - } - else{ - p->cnt = 1 + ((ab->a[k].cnt + (high_occ<<1) - 1)/(high_occ<<1)); - p->cnt = pow(p->cnt, 1.1); - } - } - cl->length = ab->n_a; - - calculate_overlap_region_by_chaining(cl, overlap_list, chain_idx, rid, ucr->length, &R_INF, NULL, bw_thres, keep_whole_chain, f_cigar, NULL); - - #if 0 - if (overlap_list->length > 0) { - fprintf(stderr, "B\t%ld\t%ld\t%d\n", (long)rid, (long)overlap_list->length, rlen); - for (int i = 0; i < (int)overlap_list->length; ++i) { - overlap_region *r = &overlap_list->list[i]; - fprintf(stderr, "C\t%d\t%d\t%d\t%c\t%d\t%ld\t%d\t%d\t%c\t%d\t%d\n", (int)r->x_id, (int)r->x_pos_s, (int)r->x_pos_e, "+-"[r->x_pos_strand], - (int)r->y_id, (long)Get_READ_LENGTH(R_INF, r->y_id), (int)r->y_pos_s, (int)r->y_pos_e, "+-"[r->y_pos_strand], (int)r->shared_seed, ha_ov_type(r, rlen)); - } - } - #endif - - if ((int)overlap_list->length > max_n_chain) { - int32_t w, n[4], s[4]; - n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; - ks_introsort_or_ss(overlap_list->length, overlap_list->list); - for (i = 0; i < (uint32_t)overlap_list->length; ++i) { - const overlap_region *r = &overlap_list->list[i]; - w = ha_ov_type(r, rlen); - ++n[w]; - if ((int)n[w] == max_n_chain) s[w] = r->shared_seed; - } - if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { - // n[0] = n[1] = n[2] = n[3] = 0; - for (i = 0, k = 0; i < (uint32_t)overlap_list->length; ++i) { - overlap_region *r = &overlap_list->list[i]; - w = ha_ov_type(r, rlen); - // ++n[w]; - // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { - if (r->shared_seed >= s[w]) { - if ((uint32_t)k != i) { - overlap_region t; - t = overlap_list->list[k]; - overlap_list->list[k] = overlap_list->list[i]; - overlap_list->list[i] = t; - } - ++k; - } - } - overlap_list->length = k; - } - } - - ///ks_introsort_or_xs(overlap_list->length, overlap_list->list); -} - -void ha_get_new_ul_candidates(ha_abufl_t *ab, int64_t rid, char* rs, int64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, int max_n_chain, int keep_whole_chain, - kvec_t_u8_warp* k_flag, kvec_t_u64_warp* chain_idx, void *ha_flt_tab, ha_pt_t *ha_idx, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t high_occ, void *km) -{ - uint32_t i; - uint64_t k, l; - if(high_occ < 1) high_occ = 1; - // uint32_t high_occ = asm_opt.hom_cov >= 1?asm_opt.hom_cov:1; - - // prepare - clear_Candidates_list(cl); - clear_overlap_region_alloc(overlap_list); - ab->mz.n = 0, ab->n_a = 0; - - // get the list of anchors - mz2_ha_sketch(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, km); - - // minimizer of queried read - if (ab->mz.m > ab->old_mz_m) { - ab->old_mz_m = ab->mz.m; - KREALLOC(km, ab->seed, ab->old_mz_m); - } - - for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { - int n; - ab->seed[i].a = ha_ptl_get(ha_idx, ab->mz.a[i].x, &n); - ab->seed[i].n = n; - ab->n_a += n; - } - if (ab->n_a > ab->m_a) { - ab->m_a = ab->n_a; - KREALLOC(km, ab->a, ab->m_a); - } - - for (i = 0, k = 0; i < ab->mz.n; ++i) { - int j; - ///z is one of the minimizer - ha_mzl_t *z = &ab->mz.a[i]; - seedl_t *s = &ab->seed[i]; - for (j = 0; j < s->n; ++j) { - const ha_idxposl_t *y = &s->a[j]; - anchor1_t *an = &ab->a[k++]; - uint8_t rev = z->rev == y->rev? 0 : 1; - an->other_off = y->pos; - an->self_off = rev? rl - 1 - (z->pos + 1 - z->span) : z->pos; - an->cnt = s->n; - an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->other_off; - } - } - - // sort anchors - radix_sort_ha_an1(ab->a, ab->a + ab->n_a); - for (k = 1, l = 0; k <= ab->n_a; ++k) { - if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { - if (k - l > 1) - radix_sort_ha_an2(ab->a + l, ab->a + k); - l = k; - } - } - - - // copy over to _cl_ - if (ab->m_a >= (uint64_t)cl->size) { - cl->size = ab->m_a; - KREALLOC(km, cl->list, cl->size); - } - - for (k = 0; k < ab->n_a; ++k) { - k_mer_hit *p = &cl->list[k]; - p->readID = ab->a[k].srt >> 33; - p->strand = ab->a[k].srt >> 32 & 1; - p->offset = ab->a[k].other_off; - p->self_offset = ab->a[k].self_off; - if(ab->a[k].cnt <= high_occ){ - p->cnt = 1; - } - else{ - p->cnt = 1 + ((ab->a[k].cnt + (high_occ<<1) - 1)/(high_occ<<1)); - p->cnt = pow(p->cnt, 1.1); - } - } - cl->length = ab->n_a; - - calculate_overlap_region_by_chaining(cl, overlap_list, chain_idx, rid, rl, NULL, uref, bw_thres, keep_whole_chain, f_cigar, km); - - #if 0 - if (overlap_list->length > 0) { - fprintf(stderr, "B\t%ld\t%ld\t%d\n", (long)rid, (long)overlap_list->length, rlen); - for (int i = 0; i < (int)overlap_list->length; ++i) { - overlap_region *r = &overlap_list->list[i]; - fprintf(stderr, "C\t%d\t%d\t%d\t%c\t%d\t%ld\t%d\t%d\t%c\t%d\t%d\n", (int)r->x_id, (int)r->x_pos_s, (int)r->x_pos_e, "+-"[r->x_pos_strand], - (int)r->y_id, (long)Get_READ_LENGTH(R_INF, r->y_id), (int)r->y_pos_s, (int)r->y_pos_e, "+-"[r->y_pos_strand], (int)r->shared_seed, ha_ov_type(r, rlen)); - } - } - #endif - - if ((int)overlap_list->length > max_n_chain) { - int32_t w, n[4], s[4]; - n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; - ks_introsort_or_ss(overlap_list->length, overlap_list->list); - for (i = 0; i < (uint32_t)overlap_list->length; ++i) { - const overlap_region *r = &overlap_list->list[i]; - w = ha_ov_type(r, rl); - ++n[w]; - if ((int)n[w] == max_n_chain) s[w] = r->shared_seed; - } - if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { - // n[0] = n[1] = n[2] = n[3] = 0; - for (i = 0, k = 0; i < (uint32_t)overlap_list->length; ++i) { - overlap_region *r = &overlap_list->list[i]; - w = ha_ov_type(r, rl); - // ++n[w]; - // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { - if (r->shared_seed >= s[w]) { - if ((uint32_t)k != i) { - overlap_region t; - t = overlap_list->list[k]; - overlap_list->list[k] = overlap_list->list[i]; - overlap_list->list[i] = t; - } - ++k; - } - } - overlap_list->length = k; - } - } - - ///ks_introsort_or_xs(overlap_list->length, overlap_list->list); -} - - -void calculate_ug_chaining(Candidates_list* candidates, overlap_region_alloc* overlap_list, kvec_t_u64_warp* chain_idx, - uint64_t readID, ma_utg_v *ua, double band_width_threshold, int add_beg_end, overlap_region* f_cigar, long long mz_occ, double mz_rate) -{ - long long i = 0; - uint64_t current_ID; - uint64_t current_stand; - - if (candidates->length == 0) - { - return; - } - - long long sub_region_beg; - long long sub_region_end; - long long chain_len; - - clear_fake_cigar(&((*f_cigar).f_cigar)); - - i = 0; - while (i < candidates->length) - { - chain_idx->a.n = 0; - current_ID = candidates->list[i].readID; - current_stand = candidates->list[i].strand; - - ///reference read - (*f_cigar).x_id = readID; - (*f_cigar).x_pos_strand = current_stand; - ///query read - (*f_cigar).y_id = current_ID; - ///here the strand of query is always 0 - (*f_cigar).y_pos_strand = 0; - - sub_region_beg = i; - sub_region_end = i; - i++; - - while (i < candidates->length - && - current_ID == candidates->list[i].readID - && - current_stand == candidates->list[i].strand) - { - sub_region_end = i; - i++; - } - - if ((*f_cigar).x_id == (*f_cigar).y_id) - { - continue; - } - - chain_len = chain_DP(candidates->list + sub_region_beg, - sub_region_end - sub_region_beg + 1, &(candidates->chainDP), f_cigar, band_width_threshold, - 50, ua->a[(*f_cigar).x_id].len, ua->a[(*f_cigar).y_id].len, NULL); - - - // if ((*f_cigar).x_id != (*f_cigar).y_id) - if ((*f_cigar).x_id != (*f_cigar).y_id && chain_len > mz_occ*mz_rate) - { - append_utg_inexact_overlap_region_alloc(overlap_list, f_cigar, ua, add_beg_end, NULL); - } - } -} - - -void ha_get_inter_candidates(ha_abufl_t *ab, uint64_t id, char* r, uint64_t rlen, uint64_t rw, uint64_t rk, uint64_t is_hpc, - overlap_region_alloc *ol, Candidates_list *cl, double bw_thres, int max_n_chain, int keep_whole_chain, - kvec_t_u8_warp* k_flag, kvec_t_u64_warp* chain_idx, void *ha_flt_tab, ha_pt_t *ha_idx, - overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp) -{ - uint64_t i, k, l; - // prepare - clear_Candidates_list(cl); - clear_overlap_region_alloc(ol); - ab->mz.n = 0, ab->n_a = 0; - - // get the list of anchors - mz2_ha_sketch(r, rlen, rw, rk, 0, is_hpc, &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, - NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 1, NULL); - - // minimizer of queried read - if (ab->mz.m > ab->old_mz_m) { - ab->old_mz_m = ab->mz.m; - REALLOC(ab->seed, ab->old_mz_m); - } - for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { - int n; - ab->seed[i].a = ha_ptl_get(ha_idx, ab->mz.a[i].x, &n); - ab->seed[i].n = n; - ab->seed[i].cnt = ha_ft_cnt(ha_flt_tab, ab->mz.a[i].x); - ab->n_a += n; - } - if (ab->n_a > ab->m_a) { - ab->m_a = ab->n_a; - kroundup64(ab->m_a); - REALLOC(ab->a, ab->m_a); - } - for (i = 0, k = 0; i < ab->mz.n; ++i) { - int j; - ///z is one of the minimizer - ha_mzl_t *z = &ab->mz.a[i]; - seedl_t *s = &ab->seed[i]; - for (j = 0; j < s->n; ++j) { - const ha_idxposl_t *y = &s->a[j]; - anchor1_t *an = &ab->a[k++]; - uint8_t rev = z->rev == y->rev? 0 : 1; - an->other_off = y->pos; - an->self_off = rev? rlen - 1 - (z->pos + 1 - z->span) : z->pos; - an->cnt = s->n; - an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->other_off; - } - } - - // sort anchors - radix_sort_ha_an1(ab->a, ab->a + ab->n_a); - for (k = 1, l = 0; k <= ab->n_a; ++k) { - if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { - if (k - l > 1) - radix_sort_ha_an2(ab->a + l, ab->a + k); - l = k; - } - } - - - // copy over to _cl_ - if (ab->m_a >= (uint64_t)cl->size) { - cl->size = ab->m_a; - REALLOC(cl->list, cl->size); - } - for (k = 0; k < ab->n_a; ++k) { - k_mer_hit *p = &cl->list[k]; - p->readID = ab->a[k].srt >> 33; - p->strand = ab->a[k].srt >> 32 & 1; - p->offset = ab->a[k].other_off; - p->self_offset = ab->a[k].self_off; - p->cnt = (ab->a[k].cnt == 1? 1 : 16); - } - cl->length = ab->n_a; - - calculate_overlap_region_by_chaining(cl, ol, chain_idx, id, rlen, /**&R_INF**/NULL, NULL, bw_thres, keep_whole_chain, f_cigar, NULL); - - #if 0 - if (ol->length > 0) { - fprintf(stderr, "B\t%ld\t%ld\t%d\n", (long)rid, (long)ol->length, rlen); - for (int i = 0; i < (int)ol->length; ++i) { - overlap_region *r = &ol->list[i]; - fprintf(stderr, "C\t%d\t%d\t%d\t%c\t%d\t%ld\t%d\t%d\t%c\t%d\t%d\n", (int)r->x_id, (int)r->x_pos_s, (int)r->x_pos_e, "+-"[r->x_pos_strand], - (int)r->y_id, (long)Get_READ_LENGTH(R_INF, r->y_id), (int)r->y_pos_s, (int)r->y_pos_e, "+-"[r->y_pos_strand], (int)r->shared_seed, ha_ov_type(r, rlen)); - } - } - #endif - - if ((int)ol->length > max_n_chain) { - int32_t w, n[4], s[4]; - n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; - ks_introsort_or_ss(ol->length, ol->list); - for (i = 0; i < (uint32_t)ol->length; ++i) { - const overlap_region *r = &ol->list[i]; - w = ha_ov_type(r, rlen); - ++n[w]; - if ((int)n[w] == max_n_chain) s[w] = r->shared_seed; - } - if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { - // n[0] = n[1] = n[2] = n[3] = 0; - for (i = 0, k = 0; i < (uint32_t)ol->length; ++i) { - overlap_region *r = &ol->list[i]; - w = ha_ov_type(r, rlen); - // ++n[w]; - // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { - if (r->shared_seed >= s[w]) { - if ((uint32_t)k != i) { - overlap_region t; - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - ++k; - } - } - ol->length = k; - } - } - - ///ks_introsort_or_xs(overlap_list->length, overlap_list->list); -} - -void ha_get_ug_candidates(ha_abuf_t *ab, int64_t rid, ma_utg_t *u, ma_utg_v *ua, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, int max_n_chain, int keep_whole_chain, kvec_t_u8_warp* k_flag, -kvec_t_u64_warp* chain_idx, void *ha_flt_tab, ha_pt_t *ha_idx, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, double chain_match_rate) -{ - uint32_t i; - uint64_t k, l; - - // prepare - clear_Candidates_list(cl); - clear_overlap_region_alloc(overlap_list); - ab->mz.n = 0, ab->n_a = 0; - - // get the list of anchors - //should use the new version... - ///ha_sketch_query(u->s, u->len, asm_opt.mz_win, asm_opt.k_mer_length, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, k_flag, dbg_ct); - // minimizer of queried read - if (ab->mz.m > ab->old_mz_m) { - ab->old_mz_m = ab->mz.m; - REALLOC(ab->seed, ab->old_mz_m); - } - for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { - int n; - ab->seed[i].a = ha_pt_get(ha_idx, ab->mz.a[i].x, &n); - ab->seed[i].n = n; - ab->n_a += n; - } - if (ab->n_a > ab->m_a) { - ab->m_a = ab->n_a; - kroundup64(ab->m_a); - REALLOC(ab->a, ab->m_a); - } - for (i = 0, k = 0; i < ab->mz.n; ++i) { - int j; - ///z is one of the minimizer - ha_mz1_t *z = &ab->mz.a[i]; - seed1_t *s = &ab->seed[i]; - for (j = 0; j < s->n; ++j) { - const ha_idxpos_t *y = &s->a[j]; - anchor1_t *an = &ab->a[k++]; - uint8_t rev = z->rev == y->rev? 0 : 1; - an->other_off = y->pos; - an->self_off = rev? u->len - 1 - (z->pos + 1 - z->span) : z->pos; - an->cnt = 1; - an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->other_off; - } - } - - // sort anchors - radix_sort_ha_an1(ab->a, ab->a + ab->n_a); - for (k = 1, l = 0; k <= ab->n_a; ++k) { - if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { - if (k - l > 1) - radix_sort_ha_an2(ab->a + l, ab->a + k); - l = k; - } - } - - - // copy over to _cl_ - if (ab->m_a >= (uint64_t)cl->size) { - cl->size = ab->m_a; - REALLOC(cl->list, cl->size); - } - for (k = 0; k < ab->n_a; ++k) { - k_mer_hit *p = &cl->list[k]; - p->readID = ab->a[k].srt >> 33; - p->strand = ab->a[k].srt >> 32 & 1; - p->offset = ab->a[k].other_off; - p->self_offset = ab->a[k].self_off; - p->cnt = 1; - } - cl->length = ab->n_a; - - calculate_ug_chaining(cl, overlap_list, chain_idx, rid, ua, bw_thres, keep_whole_chain, f_cigar, ab->mz.n, chain_match_rate); - - #if 0 - if (overlap_list->length > 0) { - fprintf(stderr, "B\t%ld\t%ld\t%d\n", (long)rid, (long)overlap_list->length, rlen); - for (int i = 0; i < (int)overlap_list->length; ++i) { - overlap_region *r = &overlap_list->list[i]; - fprintf(stderr, "C\t%d\t%d\t%d\t%c\t%d\t%ld\t%d\t%d\t%c\t%d\t%d\n", (int)r->x_id, (int)r->x_pos_s, (int)r->x_pos_e, "+-"[r->x_pos_strand], - (int)r->y_id, (long)Get_READ_LENGTH(R_INF, r->y_id), (int)r->y_pos_s, (int)r->y_pos_e, "+-"[r->y_pos_strand], (int)r->shared_seed, ha_ov_type(r, rlen)); - } - } - #endif - - if ((int)overlap_list->length > max_n_chain) { - int32_t w, n[4], s[4]; - n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; - ks_introsort_or_ss(overlap_list->length, overlap_list->list); - for (i = 0; i < (uint32_t)overlap_list->length; ++i) { - const overlap_region *r = &overlap_list->list[i]; - w = ha_ov_type(r, u->len); - ++n[w]; - if ((int)n[w] == max_n_chain) s[w] = r->shared_seed; - } - if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { - for (i = 0, k = 0; i < (uint32_t)overlap_list->length; ++i) { - overlap_region *r = &overlap_list->list[i]; - w = ha_ov_type(r, u->len); - if (r->shared_seed >= s[w]) { - if ((uint32_t)k != i) { - overlap_region t; - t = overlap_list->list[k]; - overlap_list->list[k] = overlap_list->list[i]; - overlap_list->list[i] = t; - } - ++k; - } - } - overlap_list->length = k; - } - } - - ///ks_introsort_or_xs(overlap_list->length, overlap_list->list); -} - - -void lable_matched_ovlp(overlap_region_alloc* overlap_list, ma_hit_t_alloc* paf) -{ - uint64_t j = 0, inner_j = 0; - while (j < overlap_list->length && inner_j < paf->length) - { - if(overlap_list->list[j].y_id < paf->buffer[inner_j].tn) - { - j++; - } - else if(overlap_list->list[j].y_id > paf->buffer[inner_j].tn) - { - inner_j++; - } - else - { - if(overlap_list->list[j].y_pos_strand == paf->buffer[inner_j].rev) - { - overlap_list->list[j].is_match = 1; - } - j++; - inner_j++; - } - } -} - - -void ha_get_candidates_interface(ha_abuf_t *ab, int64_t rid, UC_Read *ucr, overlap_region_alloc *overlap_list, overlap_region_alloc *overlap_list_hp, Candidates_list *cl, double bw_thres, - int max_n_chain, int keep_whole_chain, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* chain_idx, ma_hit_t_alloc* paf, ma_hit_t_alloc* rev_paf, overlap_region* f_cigar, - kvec_t_u64_warp* dbg_ct, st_mt_t *sp) -{ - extern void *ha_flt_tab; - extern ha_pt_t *ha_idx; - extern void *ha_flt_tab_hp; - extern ha_pt_t *ha_idx_hp; - - ha_get_new_candidates(ab, rid, ucr, overlap_list, cl, bw_thres, max_n_chain, keep_whole_chain, k_flag, chain_idx, ha_flt_tab, ha_idx, f_cigar, dbg_ct, sp); - - if(ha_idx_hp) - { - uint32_t i, k, y_id, overlapLen, max_i; - int shared_seed; - overlap_region t; - overlap_region_sort_y_id(overlap_list->list, overlap_list->length); - ma_hit_sort_tn(paf->buffer, paf->length); - ma_hit_sort_tn(rev_paf->buffer, rev_paf->length); - lable_matched_ovlp(overlap_list, paf); - lable_matched_ovlp(overlap_list, rev_paf); - - for (i = 0, k = 0; i < overlap_list->length; ++i) - { - if(overlap_list->list[i].is_match == 1) - { - if(k != i) - { - t = overlap_list->list[k]; - overlap_list->list[k] = overlap_list->list[i]; - overlap_list->list[i] = t; - overlap_list->list[k].is_match = 0; - } - k++; - } - } - overlap_list->length = k; - - - ha_get_new_candidates(ab, rid, ucr, overlap_list_hp, cl, bw_thres, max_n_chain, keep_whole_chain, k_flag, chain_idx, ha_flt_tab_hp, ha_idx_hp, f_cigar, dbg_ct, sp); - - if(overlap_list->length + overlap_list_hp->length > overlap_list->size) - { - overlap_list->list = (overlap_region*)realloc(overlap_list->list, - sizeof(overlap_region)*(overlap_list->length + overlap_list_hp->length)); - memset(overlap_list->list + overlap_list->size, 0, sizeof(overlap_region)* - (overlap_list->length + overlap_list_hp->length - overlap_list->size)); - overlap_list->size = overlap_list->length + overlap_list_hp->length; - } - - for (i = 0, k = overlap_list->length; i < overlap_list_hp->length; i++, k++) - { - t = overlap_list->list[k]; - overlap_list->list[k] = overlap_list_hp->list[i]; - overlap_list_hp->list[i] = t; - } - overlap_list->length = k; - - overlap_region_sort_y_id(overlap_list->list, overlap_list->length); - - i = k = 0; - while (i < overlap_list->length) - { - y_id = overlap_list->list[i].y_id; - shared_seed = overlap_list->list[i].shared_seed; - overlapLen = overlap_list->list[i].overlapLen; - max_i = i; - i++; - while (i < overlap_list->length && overlap_list->list[i].y_id == y_id) - { - if((overlap_list->list[i].shared_seed > shared_seed) || - ((overlap_list->list[i].shared_seed == shared_seed) && (overlap_list->list[i].overlapLen <= overlapLen))) - { - y_id = overlap_list->list[i].y_id; - shared_seed = overlap_list->list[i].shared_seed; - overlapLen = overlap_list->list[i].overlapLen; - max_i = i; - } - i++; - } - - if(k != max_i) - { - t = overlap_list->list[k]; - overlap_list->list[k] = overlap_list->list[max_i]; - overlap_list->list[max_i] = t; - } - k++; - } - - overlap_list->length = k; - } - - ks_introsort_or_xs(overlap_list->length, overlap_list->list); -} - - -void ha_get_ul_candidates_interface(ha_abufl_t *ab, int64_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, overlap_region_alloc *overlap_list_hp, Candidates_list *cl, double bw_thres, - int max_n_chain, int keep_whole_chain, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* chain_idx, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t high_occ, void *km) -{ - extern void *ha_flt_tab; - extern ha_pt_t *ha_idx; - - ha_get_new_ul_candidates(ab, rid, rs, rl, mz_w, mz_k, uref, overlap_list, cl, bw_thres, max_n_chain, keep_whole_chain, k_flag, chain_idx, ha_flt_tab, ha_idx, f_cigar, dbg_ct, sp, high_occ, km); - if(km) { - ha_abufl_free_buf(km, ab, 1); - destory_Candidates_list_buf(km, cl, 1); - } - ks_introsort_or_xs(overlap_list->length, overlap_list->list); -} - - - -void ha_sort_list_by_anchor(overlap_region_alloc *overlap_list) -{ - ks_introsort_or_xs(overlap_list->length, overlap_list->list); -} - - -void minimizers_gen(ha_abufl_t *ab, char* rs, int64_t rl, uint64_t mz_w, uint64_t mz_k, Candidates_list *cl, kvec_t_u8_warp* k_flag, -void *ha_flt_tab, ha_pt_t *ha_idx, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ) -{ - // fprintf(stderr, "+[M::%s]\n", __func__); - uint64_t i, k, l, max_cnt = UINT32_MAX, min_cnt = 0; int n, j; ha_mzl_t *z; seedl_t *s; - if(high_occ) { - max_cnt = (*high_occ); - if(max_cnt < 2) max_cnt = 2; - } - if(low_occ) { - min_cnt = (*low_occ); - if(min_cnt < 2) min_cnt = 2; - } - clear_Candidates_list(cl); ab->mz.n = 0, ab->n_a = 0; - - // get the list of anchors - mz2_ha_sketch(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); - - // minimizer of queried read - if (ab->mz.m > ab->old_mz_m) { - ab->old_mz_m = ab->mz.m; - REALLOC(ab->seed, ab->old_mz_m); - } - - for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { - ab->seed[i].a = ha_ptl_get(ha_idx, ab->mz.a[i].x, &n); - ab->seed[i].n = n; - ab->n_a += n; - } - - if (ab->n_a > ab->m_a) { - ab->m_a = ab->n_a; - REALLOC(ab->a, ab->m_a); - } - - for (i = 0, k = 0; i < ab->mz.n; ++i) { - ///z is one of the minimizer - z = &ab->mz.a[i]; s = &ab->seed[i]; - for (j = 0; j < s->n; ++j) { - const ha_idxposl_t *y = &s->a[j]; - anchor1_t *an = &ab->a[k++]; - uint8_t rev = z->rev == y->rev? 0 : 1; - an->other_off = y->pos; - an->self_off = rev? rl - 1 - (z->pos + 1 - z->span) : z->pos; - ///an->cnt: cnt<<8|span - an->cnt = s->n; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; - an->cnt <<= 8; an->cnt |= ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); - an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->other_off; - } - } - - radix_sort_ha_an1(ab->a, ab->a + ab->n_a); - for (k = 1, l = 0; k <= ab->n_a; ++k) { - if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { - if (k - l > 1) - radix_sort_ha_an2(ab->a + l, ab->a + k); - l = k; - } - } - - // copy over to _cl_ - if (ab->m_a >= (uint64_t)cl->size) { - cl->size = ab->m_a; - REALLOC(cl->list, cl->size); - } - - for (k = 0; k < ab->n_a; ++k) { - k_mer_hit *p = &cl->list[k]; - p->readID = ab->a[k].srt >> 33; - p->strand = ab->a[k].srt >> 32 & 1; - p->offset = ab->a[k].other_off; - p->self_offset = ab->a[k].self_off; - if(((ab->a[k].cnt>>8) < max_cnt) && ((ab->a[k].cnt>>8) > min_cnt)){ - p->cnt = 1; - } else if((ab->a[k].cnt>>8) <= min_cnt) { - p->cnt = 2; - } else{ - p->cnt = 1 + (((ab->a[k].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); - p->cnt = pow(p->cnt, 1.1); - } - if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; - p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[k].cnt)); - } - cl->length = ab->n_a; -} - - -void minimizers_qgen(ha_abufl_t *ab, char* rs, int64_t rl, uint64_t mz_w, uint64_t mz_k, Candidates_list *cl, kvec_t_u8_warp* k_flag, -void *ha_flt_tab, ha_pt_t *ha_idx, All_reads* rdb, const ul_idx_t *udb, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, -uint32_t *low_occ) -{ - // fprintf(stderr, "+[M::%s]\n", __func__); - uint64_t i, k, l, max_cnt = UINT32_MAX, min_cnt = 0; int n, j; ha_mzl_t *z; seedl_t *s; - if(high_occ) { - max_cnt = (*high_occ); - if(max_cnt < 2) max_cnt = 2; - } - if(low_occ) { - min_cnt = (*low_occ); - if(min_cnt < 2) min_cnt = 2; - } - clear_Candidates_list(cl); ab->mz.n = 0, ab->n_a = 0; - - // get the list of anchors - mz2_ha_sketch(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); - - // minimizer of queried read - if (ab->mz.m > ab->old_mz_m) { - ab->old_mz_m = ab->mz.m; - REALLOC(ab->seed, ab->old_mz_m); - } - - for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { - ab->seed[i].a = ha_ptl_get(ha_idx, ab->mz.a[i].x, &n); - ab->seed[i].n = n; - ab->n_a += n; - } - - if (ab->n_a > ab->m_a) { - ab->m_a = ab->n_a; - REALLOC(ab->a, ab->m_a); - } - - for (i = 0, k = 0; i < ab->mz.n; ++i) { - ///z is one of the minimizer - z = &ab->mz.a[i]; s = &ab->seed[i]; - for (j = 0; j < s->n; ++j) { - const ha_idxposl_t *y = &s->a[j]; - anchor1_t *an = &ab->a[k++]; - uint8_t rev = z->rev == y->rev? 0 : 1; - an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; - an->self_off = z->pos; - ///an->cnt: cnt<<8|span - an->cnt = s->n; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; - an->cnt <<= 8; an->cnt |= ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); - an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; - } - } - - // copy over to _cl_ - if (ab->m_a >= (uint64_t)cl->size) { - cl->size = ab->m_a; - REALLOC(cl->list, cl->size); - } - - k_mer_hit *p; uint64_t tid = (uint64_t)-1, tl = (uint64_t)-1; - radix_sort_ha_an1(ab->a, ab->a + ab->n_a); - for (k = 1, l = 0; k <= ab->n_a; ++k) { - if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { - if (k-l>1) radix_sort_ha_an3(ab->a+l, ab->a+k); - if((ab->a[l].srt>>33)!=tid) { - tid = ab->a[l].srt>>33; - tl = rdb?Get_READ_LENGTH((*rdb), tid):udb->ug->u.a[tid].len; - } - for (i = l; i < k; i++) { - p = &cl->list[i]; - p->readID = ab->a[i].srt>>33; - p->strand = (ab->a[i].srt>>32)&1; - if(!(p->strand)) { - p->offset = ab->a[i].other_off; - } else { - p->offset = ((uint32_t)-1)-ab->a[i].other_off; - p->offset = tl-p->offset; - } - p->self_offset = ab->a[i].self_off; - if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ - p->cnt = 1; - } else if((ab->a[i].cnt>>8) <= min_cnt) { - p->cnt = 2; - } else{ - p->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); - p->cnt = pow(p->cnt, 1.1); - } - if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; - p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); - } - l = k; - } - } - cl->length = ab->n_a; -} - - -void minimizers_qgen0(ha_abuf_t *ab, char* rs, int64_t rl, uint64_t mz_w, uint64_t mz_k, Candidates_list *cl, kvec_t_u8_warp* k_flag, -void *ha_flt_tab, ha_pt_t *ha_idx, All_reads* rdb, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ) -{ - // fprintf(stderr, "+[M::%s]\n", __func__); - uint64_t i, k, l, max_cnt = UINT32_MAX, min_cnt = 0; int n, j; ha_mz1_t *z; seed1_t *s; - if(high_occ) { - max_cnt = (*high_occ); - if(max_cnt < 2) max_cnt = 2; - } - if(low_occ) { - min_cnt = (*low_occ); - if(min_cnt < 2) min_cnt = 2; - } - clear_Candidates_list(cl); ab->mz.n = 0, ab->n_a = 0; - - // get the list of anchors - mz1_ha_sketch(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); - - // minimizer of queried read - if (ab->mz.m > ab->old_mz_m) { - ab->old_mz_m = ab->mz.m; - REALLOC(ab->seed, ab->old_mz_m); - } - - for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { - - ab->seed[i].a = ha_pt_get(ha_idx, ab->mz.a[i].x, &n); - ab->seed[i].n = n; - ab->n_a += n; - } - - if (ab->n_a > ab->m_a) { - ab->m_a = ab->n_a; - REALLOC(ab->a, ab->m_a); - } - - for (i = 0, k = 0; i < ab->mz.n; ++i) { - ///z is one of the minimizer - z = &ab->mz.a[i]; s = &ab->seed[i]; - for (j = 0; j < s->n; ++j) { - const ha_idxpos_t *y = &s->a[j]; - anchor1_t *an = &ab->a[k++]; - uint8_t rev = z->rev == y->rev? 0 : 1; - an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; - an->self_off = z->pos; - ///an->cnt: cnt<<8|span - an->cnt = s->n; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; - an->cnt <<= 8; an->cnt |= ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); - an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; - } - } - - // copy over to _cl_ - if (ab->m_a >= (uint64_t)cl->size) { - cl->size = ab->m_a; - REALLOC(cl->list, cl->size); - } - - k_mer_hit *p; uint64_t tid = (uint64_t)-1, tl = (uint64_t)-1; - radix_sort_ha_an1(ab->a, ab->a + ab->n_a); - for (k = 1, l = 0; k <= ab->n_a; ++k) { - if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { - if (k-l>1) radix_sort_ha_an3(ab->a+l, ab->a+k); - if((ab->a[l].srt>>33)!=tid) { - tid = ab->a[l].srt>>33; - tl = Get_READ_LENGTH((*rdb), tid); - // tl = rdb?Get_READ_LENGTH((*rdb), tid):udb->ug->u.a[tid].len; - } - for (i = l; i < k; i++) { - p = &cl->list[i]; - p->readID = ab->a[i].srt>>33; - p->strand = (ab->a[i].srt>>32)&1; - if(!(p->strand)) { - p->offset = ab->a[i].other_off; - } else { - p->offset = ((uint32_t)-1)-ab->a[i].other_off; - p->offset = tl-p->offset; - } - p->self_offset = ab->a[i].self_off; - if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ - p->cnt = 1; - } else if((ab->a[i].cnt>>8) <= min_cnt) { - p->cnt = 2; - } else{ - p->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); - p->cnt = pow(p->cnt, 1.1); - } - if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; - p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); - } - l = k; - } - } - cl->length = ab->n_a; -} - -void minimizers_qgen0_amz(ha_abuf_t *ab, char* rs, int64_t rl, uint64_t mz_w, uint64_t mz_k, Candidates_list *cl, kvec_t_u8_warp* k_flag, -void *ha_flt_tab, ha_pt_t *ha_idx, All_reads* rdb, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ) -{ - // fprintf(stderr, "+[M::%s]\n", __func__); - uint64_t i, k, l, max_cnt = UINT32_MAX, min_cnt = 0; int n, j; ha_mz1_t *z; seed1_t *s; - if(high_occ) { - max_cnt = (*high_occ); - if(max_cnt < 2) max_cnt = 2; - } - if(low_occ) { - min_cnt = (*low_occ); - if(min_cnt < 2) min_cnt = 2; - } - clear_Candidates_list(cl); ab->mz.n = 0, ab->n_a = 0; - - // get the list of anchors - mz1_ha_sketch(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); - - // minimizer of queried read - if (ab->mz.m > ab->old_mz_m) { - ab->old_mz_m = ab->mz.m; - REALLOC(ab->seed, ab->old_mz_m); - } - - for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { - - ab->seed[i].a = ha_pt_get(ha_idx, ab->mz.a[i].x, &n); - ab->seed[i].n = n; - ab->n_a += n; - } - - if (ab->n_a > ab->m_a) { - ab->m_a = ab->n_a; - REALLOC(ab->a, ab->m_a); - } - - for (i = 0, k = 0; i < ab->mz.n; ++i) { - ///z is one of the minimizer - z = &ab->mz.a[i]; s = &ab->seed[i]; - for (j = 0; j < s->n; ++j) { - const ha_idxpos_t *y = &s->a[j]; - anchor1_t *an = &ab->a[k++]; - uint8_t rev = z->rev == y->rev? 0 : 1; - an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; - an->self_off = z->pos; - ///an->cnt: cnt<<8|span - an->cnt = s->n; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; - an->cnt <<= 8; an->cnt |= ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); - an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; - } - } - - // copy over to _cl_ - if (ab->m_a >= (uint64_t)cl->size) { - cl->size = ab->m_a; - REALLOC(cl->list, cl->size); - } - - k_mer_hit *p; uint64_t tid = (uint64_t)-1, tl = (uint64_t)-1; - radix_sort_ha_an1(ab->a, ab->a + ab->n_a); - for (k = 1, l = 0; k <= ab->n_a; ++k) { - if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { - if (k-l>1) radix_sort_ha_an3(ab->a+l, ab->a+k); - if((ab->a[l].srt>>33)!=tid) { - tid = ab->a[l].srt>>33; - tl = Get_READ_LENGTH((*rdb), tid); - // tl = rdb?Get_READ_LENGTH((*rdb), tid):udb->ug->u.a[tid].len; - } - for (i = l; i < k; i++) { - p = &cl->list[i]; - p->readID = ab->a[i].srt>>33; - p->strand = (ab->a[i].srt>>32)&1; - if(!(p->strand)) { - p->offset = ab->a[i].other_off; - } else { - p->offset = ((uint32_t)-1)-ab->a[i].other_off; - p->offset = tl-p->offset; - } - p->self_offset = ab->a[i].self_off; - if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ - p->cnt = 1; - } else if((ab->a[i].cnt>>8) <= min_cnt) { - p->cnt = 2; - } else{ - p->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); - p->cnt = pow(p->cnt, 1.1); - } - if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; - p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); - } - l = k; - } - } - cl->length = ab->n_a; -} - - -uint64_t lchain_qgen_mcopy_fast_re0(ha_abuf_t *ab, ha_pt_t *ha_idx, ha_mz1_t *ra, uint64_t rn, ha_mz1_t *qa, uint64_t qn, uint64_t qid, Candidates_list *cl, uint32_t *high_occ, uint32_t *low_occ) -{ - // fprintf(stderr, "+[M::%s]\n", __func__); - uint64_t i, k, l, max_cnt = UINT32_MAX, min_cnt = 0, ri, qi, sn; anchor1_t *an; k_mer_hit *p; - if(high_occ) { - max_cnt = (*high_occ); - if(max_cnt < 2) max_cnt = 2; - } - if(low_occ) { - min_cnt = (*low_occ); - if(min_cnt < 2) min_cnt = 2; - } - // clear_Candidates_list(cl); - - ///first try - for (k = 1, l = i = ab->n_a = 0; k <= rn; ++k) { - if (k == rn || ra[k].x != ra[l].x) { - for (; i < qn && qa[i].x < ra[l].x; i++); - if(i < qn && qa[i].x == ra[l].x) { - sn = 0; - if(ab->n_a < ab->m_a) sn = ab->seed[l].n;///ha_pt_cnt(ha_idx, ra[l].x); - - for (qi = i; qi < qn && qa[qi].x == ra[l].x; qi++) { - for (ri = l; ri < k; ri++) { - if(qa[qi].rev != ra[ri].rev) continue; - if(ab->n_a < ab->m_a) { - an = &(ab->a[ab->n_a++]); - - an->other_off = qa[qi].pos; - an->self_off = ra[ri].pos; - ///an->cnt: cnt<<8|span - an->cnt = sn; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; - an->cnt <<= 8; an->cnt |= ((ra[ri].span <= ((uint32_t)(0xffu)))?ra[ri].span:((uint32_t)(0xffu))); - an->srt = (((uint64_t)(an->self_off))<<32)|((uint64_t)(an->other_off)); - } else { - ab->n_a++; - } - } - } - } - l = k; - } - } - - - if (ab->n_a > ab->m_a) { - ab->m_a = ab->n_a; REALLOC(ab->a, ab->m_a); - - for (k = 1, l = i = ab->n_a = 0; k <= rn; ++k) { - if (k == rn || ra[k].x != ra[l].x) { - for (; i < qn && qa[i].x < ra[l].x; i++); - if(i < qn && qa[i].x == ra[l].x) { - sn = ab->seed[l].n;///ha_pt_cnt(ha_idx, ra[l].x); - - for (qi = i; qi < qn && qa[qi].x == ra[l].x; qi++) { - for (ri = l; ri < k; ri++) { - if(qa[qi].rev != ra[ri].rev) continue; - - an = &(ab->a[ab->n_a++]); - - an->other_off = qa[qi].pos; - an->self_off = ra[ri].pos; - ///an->cnt: cnt<<8|span - an->cnt = sn; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; - an->cnt <<= 8; an->cnt |= ((ra[ri].span <= ((uint32_t)(0xffu)))?ra[ri].span:((uint32_t)(0xffu))); - an->srt = (((uint64_t)(an->self_off))<<32)|((uint64_t)(an->other_off)); - } - } - } - l = k; - } - } - } - - // copy over to _cl_ - sn = ab->n_a + cl->length; - if (sn > (uint64_t)cl->size) { - cl->size = sn; - REALLOC(cl->list, cl->size); - } - - radix_sort_ha_an1(ab->a, ab->a + ab->n_a); - for (i = 0; i < ab->n_a; i++) { - p = &cl->list[cl->length++]; - p->readID = qid; - p->strand = 0; - p->offset = ab->a[i].other_off; - p->self_offset = ab->a[i].self_off; - - if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ - p->cnt = 1; - } else if((ab->a[i].cnt>>8) <= min_cnt) { - p->cnt = 2; - } else{ - p->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); - p->cnt = pow(p->cnt, 1.1); - } - if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; - p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); - } - // cl->length = ab->n_a; - return ab->n_a; -} - -void gen_pair_chain(ha_abufl_t *ab, uint64_t rid, st_mt_t *tid, uint64_t tid_n, ha_mzl_t *in, uint64_t in_n, ha_mzl_t *idx, int64_t idx_n, uint64_t mzl_cutoff) -{ - if(!tid_n) return; - uint64_t i, l, k, n, m, rev, x, tn, kn; ha_mzl_t *z, *p, *y; int64_t zi, ns, ne; anchor1_t *an; - for (i = tn = 0; i < in_n; ++i) { - ///z is one of the minimizer - z = &in[i]; p = &(idx[z->x]); n = 0; - assert(z->pos == p->pos && z->rid == p->rid && z->span == p->span && z->rev == p->rev); - for (zi = z->x+1; zi < idx_n && idx[zi].x == p->x && n < mzl_cutoff; zi++) { - if(idx[zi].rid == rid) continue; - x = idx[zi].rid; x <<= 1; x |= ((uint64_t)((z->rev == idx[zi].rev)?0:1)); - for (m = 0; m < tid_n; m++) { - if(tid->a[m] == x) { - n++; break; - } - } - } - for (zi = ((int64_t)z->x)-1; zi >= 0 && idx[zi].x == p->x && n < mzl_cutoff; zi--) { - if(idx[zi].rid == rid) continue; - x = idx[zi].rid; x <<= 1; x |= ((uint64_t)((z->rev == idx[zi].rev)?0:1)); - for (m = 0; m < tid_n; m++) { - if(tid->a[m] == x) { - n++; break; - } - } - } - if((!n) || (n >= mzl_cutoff)) continue; - tn += n; - } - if(!tn) return; - ab->n_a += tn; - if (ab->n_a > ab->m_a) { - ab->m_a = ab->n_a; - REALLOC(ab->a, ab->m_a); - } - - - for (i = 0, k = ab->n_a - tn; i < in_n; ++i) { - ///z is one of the minimizer - z = &in[i]; p = &(idx[z->x]); n = 0; ns = 0; ne = -1; - for (zi = z->x+1; zi < idx_n && idx[zi].x == p->x && n < mzl_cutoff; zi++) { - if(idx[zi].rid == rid) continue; - x = idx[zi].rid; x <<= 1; x |= ((uint64_t)((z->rev == idx[zi].rev)?0:1)); - for (m = 0; m < tid_n; m++) { - if(tid->a[m] == x) { - n++; break; - } - } - } - ne = zi; - for (zi = ((int64_t)z->x)-1; zi >= 0 && idx[zi].x == p->x && n < mzl_cutoff; zi--) { - if(idx[zi].rid == rid) continue; - x = idx[zi].rid; x <<= 1; x |= ((uint64_t)((z->rev == idx[zi].rev)?0:1)); - for (m = 0; m < tid_n; m++) { - if(tid->a[m] == x) { - n++; break; - } - } - } - ns = zi + 1; - if((!n) || (n >= mzl_cutoff)) continue; - n = ne - ns; if(n > ((uint32_t)(0xffffffu))) n = 0xffffffu; n<<=8; - - for (zi = z->x+1; zi < idx_n && idx[zi].x == p->x; zi++) { - if(idx[zi].rid == rid) continue; - x = idx[zi].rid; x <<= 1; x |= ((uint64_t)((z->rev == idx[zi].rev)?0:1)); - for (m = 0; m < tid_n; m++) { - if(tid->a[m] == x) break; - } - if(m >= tid_n) continue; - - - y = &(idx[zi]); an = &ab->a[k++]; - rev = z->rev == y->rev? 0 : 1; - an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; - an->self_off = z->pos; - ///an->cnt: cnt<<8|span - an->cnt = ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); an->cnt |= n; - an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; - } - for (zi = ((int64_t)z->x)-1; zi >= 0 && idx[zi].x == p->x; zi--) { - if(idx[zi].rid == rid) continue; - x = idx[zi].rid; x <<= 1; x |= ((uint64_t)((z->rev == idx[zi].rev)?0:1)); - for (m = 0; m < tid_n; m++) { - if(tid->a[m] == x) break; - } - if(m >= tid_n) continue; - - - - y = &(idx[zi]); an = &ab->a[k++]; - rev = z->rev == y->rev? 0 : 1; - an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; - an->self_off = z->pos; - ///an->cnt: cnt<<8|span - an->cnt = ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); an->cnt |= n; - an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; - } - } - assert(k == ab->n_a); - radix_sort_ha_an1(ab->a + ab->n_a - tn, ab->a + ab->n_a); kn = 0; - for (k = ab->n_a - tn + 1, l = ab->n_a - tn; k <= ab->n_a; ++k) { - if (k == ab->n_a || (ab->a[k].srt>>32) != (ab->a[l].srt>>32)) { - for (; kn < tid_n && tid->a[kn] < (ab->a[l].srt>>32); kn++); - if(kn < tid_n && tid->a[kn] == (ab->a[l].srt>>32)) kv_push(uint64_t, *tid, l); - for (; kn < tid_n && tid->a[kn] == (ab->a[l].srt>>32); kn++); - l = k; - } - } -} - -void minimizers_qgen_input(ha_abufl_t *ab, uint64_t rid, char* rs, int64_t rl, uint64_t mz_w, uint64_t mz_k, Candidates_list *cl, kvec_t_u8_warp* k_flag, -void *ha_flt_tab, ha_pt_t *ha_idx, All_reads* rdb, const ul_idx_t *udb, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, -uint32_t *low_occ, ha_mzl_t *in, uint64_t in_n, ha_mzl_t *idx, int64_t idx_n, uint64_t mzl_cutoff, uint64_t chain_cutoff, kv_u_trans_t *kov) -{ - // fprintf(stderr, "+[M::%s]\n", __func__); - uint64_t i, k, l, max_cnt = UINT32_MAX, min_cnt = 0, n; ha_mzl_t *z, *p, *y; anchor1_t *an; - int64_t zi, ns, ne; uint8_t rev; k_mer_hit *s; - if(high_occ) { - max_cnt = (*high_occ); - if(max_cnt < 2) max_cnt = 2; - } - if(low_occ) { - min_cnt = (*low_occ); - if(min_cnt < 2) min_cnt = 2; - } - clear_Candidates_list(cl); - - for (i = 0, ab->n_a = 0; i < in_n; ++i) { - ///z is one of the minimizer - z = &in[i]; p = &(idx[z->x]); n = 0; - assert(z->pos == p->pos && z->rid == p->rid && z->span == p->span && z->rev == p->rev); - for (zi = z->x+1; zi < idx_n && idx[zi].x == p->x && n < mzl_cutoff; zi++) { - if(idx[zi].rid == rid) continue; n++; - } - for (zi = ((int64_t)z->x)-1; zi >= 0 && idx[zi].x == p->x && n < mzl_cutoff; zi--) { - if(idx[zi].rid == rid) continue; n++; - } - if((!n) || (n >= mzl_cutoff)) continue; - ab->n_a += n; - } - // if(rid == 0) { - // fprintf(stderr, "-0-[M::%s] ab->n_a::%lu, in_n::%lu\n", __func__, ab->n_a, in_n); - // } - - if (ab->n_a > ab->m_a) { - ab->m_a = ab->n_a; - REALLOC(ab->a, ab->m_a); - } - - for (i = 0, k = 0; i < in_n; ++i) { - ///z is one of the minimizer - z = &in[i]; p = &(idx[z->x]); n = 0; ns = 0; ne = -1; - for (zi = z->x+1; zi < idx_n && idx[zi].x == p->x && n < mzl_cutoff; zi++) { - if(idx[zi].rid == rid) continue; n++; - } - ne = zi; - for (zi = ((int64_t)z->x)-1; zi >= 0 && idx[zi].x == p->x && n < mzl_cutoff; zi--) { - if(idx[zi].rid == rid) continue; n++; - } - ns = zi + 1; - if((!n) || (n >= mzl_cutoff)) continue; - n = ne - ns; if(n > ((uint32_t)(0xffffffu))) n = 0xffffffu; n<<=8; - - for (zi = z->x+1; zi < idx_n && idx[zi].x == p->x; zi++) { - if(idx[zi].rid == rid) continue; - y = &(idx[zi]); an = &ab->a[k++]; - rev = z->rev == y->rev? 0 : 1; - an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; - an->self_off = z->pos; - ///an->cnt: cnt<<8|span - an->cnt = ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); an->cnt |= n; - an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; - } - for (zi = ((int64_t)z->x)-1; zi >= 0 && idx[zi].x == p->x; zi--) { - if(idx[zi].rid == rid) continue; - y = &(idx[zi]); an = &ab->a[k++]; - rev = z->rev == y->rev? 0 : 1; - an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; - an->self_off = z->pos; - ///an->cnt: cnt<<8|span - an->cnt = ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); an->cnt |= n; - an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; - } - } - assert(k == ab->n_a); - - uint64_t kn, spn; u_trans_t *ka; - kn = spn = 0; ka = NULL; sp->n = 0; - if(kov) { - kn = u_trans_n(*kov, rid); ka = u_trans_a(*kov, rid); - } - if(kn > 0) { - kv_resize(uint64_t, *sp, kn); - for (k = 0; k < kn; ++k) { - if(ka[k].del) continue; - l = ka[k].tn; l <<= 1; l |= ka[k].rev; - kv_push(uint64_t, *sp, l); - } - if(sp->n > 1) radix_sort_anc64(sp->a, sp->a + sp->n); - } - - radix_sort_ha_an1(ab->a, ab->a + ab->n_a); kn = 0; - for (k = 1, l = n = 0, spn = sp->n; k <= ab->n_a; ++k) { - if (k == ab->n_a || (ab->a[k].srt>>32) != (ab->a[l].srt>>32)) { - if(k - l >= chain_cutoff) { - for (; kn < spn && sp->a[kn] < (ab->a[l].srt>>32); kn++); - if(kn < spn && sp->a[kn] == (ab->a[l].srt>>32)) kv_push(uint64_t, *sp, n); - for (; kn < spn && sp->a[kn] == (ab->a[l].srt>>32); kn++) sp->a[kn] = (uint64_t)-1; - for (i = l; i < k; i++) ab->a[n++] = ab->a[i]; - } - l = k; - } - } - ab->n_a = n; - for (k = kn = 0; k < spn; k++) { - if(sp->a[k] == (uint64_t)-1) continue; - sp->a[kn++] = sp->a[k]; - } - // sp->n = kn; - if(kn > 0) gen_pair_chain(ab, rid, sp, kn, in, in_n, idx, idx_n, mzl_cutoff); - if(spn > 0) { - for (k = spn, kn = 0; k < sp->n; k++) sp->a[kn++] = sp->a[k]; - sp->n = kn; - } - - - // copy over to _cl_ - if (ab->n_a >= (uint64_t)cl->size) { - cl->size = ab->n_a; - REALLOC(cl->list, cl->size); - } - - uint64_t tid = (uint64_t)-1, tl = (uint64_t)-1; - for (k = 1, l = 0; k <= ab->n_a; ++k) { - if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { - if (k-l>1) radix_sort_ha_an3(ab->a+l, ab->a+k); - if((ab->a[l].srt>>33)!=tid) { - tid = ab->a[l].srt>>33; - tl = rdb?Get_READ_LENGTH((*rdb), tid):udb->ug->u.a[tid].len; - } - for (i = l; i < k; i++) { - s = &cl->list[i]; - s->readID = ab->a[i].srt>>33; - s->strand = (ab->a[i].srt>>32)&1; - if(!(s->strand)) { - s->offset = ab->a[i].other_off; - } else { - s->offset = ((uint32_t)-1)-ab->a[i].other_off; - s->offset = tl-s->offset; - } - s->self_offset = ab->a[i].self_off; - if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ - s->cnt = 1; - } else if((ab->a[i].cnt>>8) <= min_cnt) { - s->cnt = 2; - } else{ - s->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); - s->cnt = pow(s->cnt, 1.1); - } - if(s->cnt > ((uint32_t)(0xffffffu))) s->cnt = 0xffffffu; - s->cnt <<= 8; s->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); - } - l = k; - } - } - cl->length = ab->n_a; -} - -void inline reverse_k_mer_hit(k_mer_hit *a, uint64_t a_n, uint64_t xl, uint64_t yl) -{ - uint64_t z, han = a_n>>1; k_mer_hit *ai, *aj, ka; - for (z = 0; z < han; z++) { - ai = &(a[z]); aj = &(a[a_n-z-1]); - ka = (*ai); (*ai) = (*aj); (*aj) = ka; - - ai->self_offset = xl-ai->self_offset-1; - ai->offset = yl-ai->offset-1; - - aj->self_offset = xl-aj->self_offset-1; - aj->offset = yl-aj->offset-1; - } - if(a_n&1) { - a[z].self_offset = xl-a[z].self_offset-1; - a[z].offset = yl-a[z].offset-1; - } -} - - -void inline reset_k_mer_hit(k_mer_hit *a, uint64_t a_n, uint64_t xl, uint64_t yl, uint64_t rev, uint64_t *nid) -{ - uint64_t z, han = a_n>>1; k_mer_hit *ai, *aj, ka; - if(rev) { - for (z = 0; z < han; z++) { - ai = &(a[z]); aj = &(a[a_n-z-1]); - ka = (*ai); (*ai) = (*aj); (*aj) = ka; - - ai->self_offset = xl-ai->self_offset-1; - ai->offset = yl-ai->offset-1; - - aj->self_offset = xl-aj->self_offset-1; - aj->offset = yl-aj->offset-1; - if(nid) ai->readID = aj->readID = (*nid); - } - if(a_n&1) { - a[z].self_offset = xl-a[z].self_offset-1; - a[z].offset = yl-a[z].offset-1; - if(nid) a[z].readID = (*nid); - } - } else if(nid) { - for (z = 0; z < a_n; z++) a[z].readID = (*nid); - } -} - -void lchain_gen(Candidates_list* cl, overlap_region_alloc* ol, uint32_t rid, uint64_t rl, All_reads* rdb, - const ul_idx_t *udb, uint32_t apend_be, overlap_region* tf, uint64_t max_n_chain, - int64_t max_skip, int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, int64_t quick_check, uint32_t gen_off) -{ - // fprintf(stderr, "+[M::%s]\n", __func__); - uint64_t i, k, l, m, sm, cn = cl->length; overlap_region *r; ///srt = 0 - clear_overlap_region_alloc(ol); - clear_fake_cigar(&(tf->f_cigar)); - - for (l = 0, k = 1, m = 0; k <= cn; k++) { - if((k == cn) || (cl->list[k].readID != cl->list[l].readID) - || (cl->list[k].strand != cl->list[l].strand)) { - if(cl->list[l].readID != rid) { - tf->x_id = rid; - tf->x_pos_strand = cl->list[l].strand; - tf->y_id = cl->list[l].readID; - tf->y_pos_strand = 0;///always 0 - // fprintf(stderr, "+[M::%s] l::%lu, k::%lu\n", __func__, l, k); - sm = lchain_dp(cl->list+l, k-l, cl->list+m, &(cl->chainDP), tf, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, - rl, rdb?Get_READ_LENGTH((*rdb), (*tf).y_id):udb->ug->u.a[(*tf).y_id].len, quick_check); - // assert(sm > 0); - if(ovlp_chain_gen(ol, tf, rl, rdb?Get_READ_LENGTH((*rdb), (*tf).y_id):udb->ug->u.a[(*tf).y_id].len, apend_be, cl->list+m, sm)) { - r = &(ol->list[ol->length-1]); r->non_homopolymer_errors = m; - // if(r->y_pos_strand) { - // reverse_k_mer_hit(cl->list+m, sm, rl, rdb?Get_READ_LENGTH((*rdb), r->y_id):udb->ug->u.a[r->y_id].len); - // } - reset_k_mer_hit(cl->list+m, sm, rl, rdb?Get_READ_LENGTH((*rdb), r->y_id):udb->ug->u.a[r->y_id].len, r->y_pos_strand, &(ol->length)); - if(gen_off) gen_fake_cigar(&(r->f_cigar), r, apend_be, cl->list+m, sm); - m += sm; - } - } - l = k; - } - } - cl->length = m; - - - k = ol->length; - if (ol->length > max_n_chain) { - int32_t w, n[4], s[4]; overlap_region t; - n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; - ks_introsort_or_ss(ol->length, ol->list); ///srt = 1; - for (i = 0; i < ol->length; ++i) { - r = &(ol->list[i]); - w = ha_ov_type(r, rl); - ++n[w]; - if (((uint64_t)n[w]) == max_n_chain) s[w] = r->shared_seed; - } - if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { - // n[0] = n[1] = n[2] = n[3] = 0; - for (i = 0, k = 0; i < ol->length; ++i) { - r = &(ol->list[i]); - w = ha_ov_type(r, rl); - // ++n[w]; - // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { - if (r->shared_seed >= s[w]) { - if (k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - ++k; - } - } - ol->length = k; - } - } - /** - if(!gen_off) { - if(srt) ks_introsort_or_id(ol->length, ol->list); - uint64_t cln = cl->length; - for (i = k = m = 0; i < ol->length; ++i) { - r = &(ol->list[i]); - for (;(klist[k].readID!=r->y_id)||(cl->list[k].strand!=r->y_pos_strand)); k++); - // assert(klist[k].readID!=r->y_id)||(cl->list[k].strand!=r->y_pos_strand)) break; - if(m != k) cl->list[m] = cl->list[k]; - } - // assert(m - cn > 0); - if(r->y_pos_strand) { - reverse_k_mer_hit(cl->list+cn, m-cn, rl, rdb?Get_READ_LENGTH((*rdb), r->y_id):udb->ug->u.a[r->y_id].len); - } - // gen_fake_cigar(&(r->f_cigar), r, apend_be, cl->list+cn, m-cn); - } - cl->length = m; - } - **/ - - ks_introsort_or_xs(ol->length, ol->list); -} - -void lchain_qgen(Candidates_list* cl, overlap_region_alloc* ol, uint32_t rid, uint64_t rl, All_reads* rdb, - const ul_idx_t *udb, uint32_t apend_be, overlap_region* tf, uint64_t max_n_chain, - int64_t max_skip, int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, int64_t quick_check, uint32_t gen_off) -{ - uint64_t i, k, l, m, sm, cn = cl->length; overlap_region *r; ///srt = 0 - clear_overlap_region_alloc(ol); - clear_fake_cigar(&(tf->f_cigar)); - - for (l = 0, k = 1, m = 0; k <= cn; k++) { - if((k == cn) || (cl->list[k].readID != cl->list[l].readID) - || (cl->list[k].strand != cl->list[l].strand)) { - if(cl->list[l].readID != rid) { - tf->x_id = rid; - tf->x_pos_strand = cl->list[l].strand; - tf->y_id = cl->list[l].readID; - tf->y_pos_strand = 0;///always 0 - // fprintf(stderr, "+[M::%s] l::%lu, k::%lu\n", __func__, l, k); - sm = lchain_qdp(cl->list+l, k-l, cl->list+m, &(cl->chainDP), tf, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, - rl, rdb?Get_READ_LENGTH((*rdb), (*tf).y_id):udb->ug->u.a[(*tf).y_id].len, quick_check); - // assert(sm > 0); - if(ovlp_chain_qgen(ol, tf, rl, rdb?Get_READ_LENGTH((*rdb), (*tf).y_id):udb->ug->u.a[(*tf).y_id].len, apend_be, cl->list+m, sm)) { - r = &(ol->list[ol->length-1]); r->non_homopolymer_errors = m; - // if(tf->y_id == 66 || tf->y_id == 66) { - // fprintf(stderr, "\n[M::%s::] utg%.6dl(%c), i::%lu\n", - // __func__, (int32_t)tf->y_id+1, "+-"[tf->x_pos_strand], m); - // } - // reset_k_mer_hit(cl->list+m, sm, rl, rdb?Get_READ_LENGTH((*rdb), r->y_id):udb->ug->u.a[r->y_id].len, r->y_pos_strand, &(ol->length)); - for (i = 0; i < sm; i++) { - cl->list[m+i].readID = ol->length; - // if(tf->y_id == 126) fprintf(stderr, "[M::%s::qoff->%u::toff->%u]\n", __func__, cl->list[m+i].self_offset, cl->list[m+i].offset); - } - if(gen_off) gen_fake_cigar(&(r->f_cigar), r, apend_be, cl->list+m, sm); - m += sm; - } - } - l = k; - } - } - cl->length = m; - // fprintf(stderr, "+[M::%s] cn::%lu, m::%lu, ol->length::%lu\n", __func__, cn, m, ol->length); - // for (k = 0; k < ol->length; k++) { - // fprintf(stderr, "---[M::%s::utg%.6dl] q[%d, %d), t[%d, %d), khit_off::%u\n", __func__, - // (int32_t)ol->list[k].y_id+1, ol->list[k].x_pos_s, ol->list[k].x_pos_e+1, - // ol->list[k].y_pos_s, ol->list[k].y_pos_e+1, ol->list[k].non_homopolymer_errors); - // } - - - k = ol->length; - if (ol->length > max_n_chain) { - int32_t w, n[4], s[4]; overlap_region t; - n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; - ks_introsort_or_ss(ol->length, ol->list); ///srt = 1; - for (i = 0; i < ol->length; ++i) { - r = &(ol->list[i]); - w = ha_ov_type(r, rl); - ++n[w]; - if (((uint64_t)n[w]) == max_n_chain) s[w] = r->shared_seed; - } - if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { - // n[0] = n[1] = n[2] = n[3] = 0; - for (i = 0, k = 0; i < ol->length; ++i) { - r = &(ol->list[i]); - w = ha_ov_type(r, rl); - // ++n[w]; - // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { - if (r->shared_seed >= s[w]) { - if (k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - ++k; - } - } - ol->length = k; - } - } - ks_introsort_or_xs(ol->length, ol->list); -} - - -void lchain_qgen_mcopy(Candidates_list* cl, overlap_region_alloc* ol, uint32_t rid, uint64_t rl, All_reads* rdb, - const ul_idx_t *udb, uint32_t apend_be, uint64_t max_n_chain, int64_t max_skip, int64_t max_iter, - int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, int64_t quick_check, - uint32_t gen_off, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut, st_mt_t *sp) -{ - // fprintf(stderr, "+[M::%s]\n", __func__); - uint64_t i, k, l, m, cn = cl->length, yid, ol0, lch; overlap_region *r, t; ///srt = 0 - clear_overlap_region_alloc(ol); - - for (l = 0, k = 1, m = 0, lch = 0; k <= cn; k++) { - if((k == cn) || (cl->list[k].readID != cl->list[l].readID)) { - if(cl->list[l].readID != rid) { - yid = cl->list[l].readID; ol0 = ol->length; - m += lchain_qdp_mcopy(cl, l, k-l, m, &(cl->chainDP), ol, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, - rid, rl, rdb?Get_READ_LENGTH((*rdb), yid):udb->ug->u.a[yid].len, quick_check, apend_be, gen_off, 1, mcopy_rate, mcopy_khit_cut, 1); - if((chain_cutoff >= 2) && (!lch)) { - for (i = ol0; (ilength) && (!lch); i++) { - if(ol->list[i].align_length < chain_cutoff) lch = 1; - } - } - } - l = k; - } - } - cl->length = m; - - // for (k = 0; k < ol->length; k++) { - // fprintf(stderr, "---[M::%s::utg%.6dl] q[%d, %d), t[%d, %d), khit_off::%u\n", __func__, - // (int32_t)ol->list[k].y_id+1, ol->list[k].x_pos_s, ol->list[k].x_pos_e+1, - // ol->list[k].y_pos_s, ol->list[k].y_pos_e+1, ol->list[k].non_homopolymer_errors); - // } - - k = ol->length; - if (ol->length > max_n_chain) { - int32_t w, n[4], s[4]; - n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; - ks_introsort_or_ss(ol->length, ol->list); - for (i = 0; i < ol->length; ++i) { - r = &(ol->list[i]); - w = ha_ov_type(r, rl); - ++n[w]; - if (((uint64_t)n[w]) == max_n_chain) s[w] = r->shared_seed; - } - if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { - // n[0] = n[1] = n[2] = n[3] = 0; - for (i = 0, k = 0, lch = 0; i < ol->length; ++i) { - r = &(ol->list[i]); - w = ha_ov_type(r, rl); - // ++n[w]; - // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { - if (r->shared_seed >= s[w]) { - if (k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - if(ol->list[k].align_length < chain_cutoff) lch = 1; - ++k; - } - } - ol->length = k; - } - } - - ks_introsort_or_xs(ol->length, ol->list); - if(lch) { - //@brief r485 - uint64_t zs, ze, rs, re, ob, os, oe, ocn, pp, kn, ms, me; int64_t osc; - for (i = l = 0, cn = cl->length; i < ol->length; ++i) { - if(ol->list[i].align_length < chain_cutoff) { - zs = ol->list[i].x_pos_s; ze = ol->list[i].x_pos_e + 1; - ob = (ze - zs)*OFL; if(ob < 16) ob = 16; - osc = ol->list[i].shared_seed*CH_SC; - ocn = ol->list[i].align_length<length) && (ze > ol->list[k].x_pos_s); k++) { - if(ol->list[k].align_length < chain_cutoff) continue; - if(ol->list[k].align_length < ocn) continue; - if(ol->list[k].shared_seed < osc) continue; - rs = ol->list[k].x_pos_s; re = ol->list[k].x_pos_e + 1; - os = ((rs>=zs)?rs:zs); oe = ((re<=ze)?re:ze); - if((oe > os) && (oe - os) >= ob) { - m = ol->list[k].non_homopolymer_errors; - pp = cl->list[m].readID; kn = 0; - for (; (m < cn) && (cl->list[m].readID == pp) && (kn < ocn); m++) { - me = cl->list[m].self_offset; ms = me - (cl->list[m].cnt&(0xffu)); - if((ms >= os) && (me <= oe)) kn++; - } - if(kn >= ocn) break; - } - } - if((k < ol->length) && (ze > ol->list[k].x_pos_s)) continue; - } - if (l != i) { - t = ol->list[l]; - ol->list[l] = ol->list[i]; - ol->list[i] = t; - } - l++; - } - // fprintf(stderr, "+[M::%s] rid::%u, ol->length0::%lu, ol->length1::%lu\n", __func__, rid, ol->length, l); - ol->length = l; - - - /** - //@brief r484 - for (i = sp->n = 0; i < ol->length; ++i) { - if(ol->list[i].align_length < chain_cutoff) continue; - os = ol->list[i].x_pos_s; oe = ol->list[i].x_pos_e + 1; - if((sp->n) && (((uint32_t)sp->a[sp->n-1]) >= os)) { - if(oe > ((uint32_t)sp->a[sp->n-1])) { - oe = oe - ((uint32_t)sp->a[sp->n-1]); - sp->a[sp->n-1] += oe; - } - } else { - os = (os<<32)|oe; kv_push(uint64_t, *sp, os); - } - } - - for (i = k = 0; i < ol->length; ++i) { - if(ol->list[i].align_length < chain_cutoff) {///ol has been sorted by x_pos_s - r = &(ol->list[i]); rs = r->x_pos_s; re = r->x_pos_e + 1; - rl = re - rs; ovl = 0; - for (m = 0; (m < sp->n) && (re > (sp->a[m]>>32)); m++) { - os = ((rs>=(sp->a[m]>>32))? rs:(sp->a[m]>>32)); - oe = ((re<=((uint32_t)sp->a[m]))? re:((uint32_t)sp->a[m])); - if(oe > os) { - ovl += (oe - os); if(ovl >= (rl*0.95)) break; - } - } - if(ovl >= (rl*0.95)) continue; - } - if (k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - ol->list[k++].align_length = 0; - } - // fprintf(stderr, "+[M::%s] ol->length0::%lu, ol->length1::%lu\n", __func__, ol->length, k); - ol->length = k; - **/ - } - /**else { - for (i = 0; i < ol->length; ++i) ol->list[i].align_length = 0; - } - **/ - for (i = 0; i < ol->length; ++i) ol->list[i].align_length = 0; -} - -void lchain_qgen_mcopy_fast(Candidates_list* cl, overlap_region_alloc* ol, uint32_t rid, uint64_t rl, All_reads* rdb, - uint32_t apend_be, uint64_t max_n_chain, int64_t max_skip, int64_t max_iter, - int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, int64_t quick_check, - uint32_t gen_off, int64_t mcopy_num, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut, st_mt_t *sp, uint64_t ocv_w) -{ - // fprintf(stderr, "+[M::%s] chain_cutoff::%u\n", __func__, chain_cutoff); - uint64_t i, k, l, m, cn = cl->length, yid, ol0, lch, *cc = NULL, cwn = 0, cws, cwe, os, oe, rs, re, cw0, cw1/**, dbgn = 0**/; overlap_region *r, t; ///srt = 0 - clear_overlap_region_alloc(ol); - - for (l = 0, k = 1, m = 0, lch = 0; k <= cn; k++) { - if((k == cn) || (cl->list[k].readID != cl->list[l].readID)) { - if(cl->list[l].readID != rid) { - yid = cl->list[l].readID; ol0 = ol->length; - m += lchain_qdp_mcopy_fast(cl, l, k-l, m, &(cl->chainDP), ol, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, - rid, rl, Get_READ_LENGTH((*rdb), yid), quick_check, apend_be, gen_off, mcopy_num, mcopy_rate, mcopy_khit_cut, 1); - if((chain_cutoff >= 2) && (!lch)) { - for (i = ol0; (ilength) && (!lch); i++) { - if(ol->list[i].align_length < chain_cutoff) lch = 1; - } - } - } - l = k; - } - } - cl->length = m; - - // fprintf(stderr, "[M::%s::] rn::%lu\tmax_n_chain::%lu\n", __func__, ol->length, max_n_chain); - // for (k = 0; k < ol->length; k++) { - // fprintf(stderr, "---[M::%s::%.*s(qid::%u)] q[%d, %d), t[%d, %d), sc::%d, type::%d\n", __func__, - // (int32_t)Get_NAME_LENGTH(R_INF, ol->list[k].y_id), Get_NAME(R_INF, ol->list[k].y_id), ol->list[k].y_id, - // ol->list[k].x_pos_s, ol->list[k].x_pos_e+1, ol->list[k].y_pos_s, ol->list[k].y_pos_e+1, ol->list[k].shared_seed, ha_ov_type(&(ol->list[k]), rl)); - // } - - k = ol->length; - if (ol->length > max_n_chain) { - int32_t w, n[4], s[4]; - n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; - ks_introsort_or_ss(ol->length, ol->list); - for (i = 0; i < ol->length; ++i) { - r = &(ol->list[i]); - w = ha_ov_type(r, rl); - ++n[w]; - if (((uint64_t)n[w]) == max_n_chain) s[w] = r->shared_seed; - } - // fprintf(stderr, "[M::%s::] s[0]::%d, s[1]::%d, s[2]::%d, s[3]::%d\n", __func__, s[0], s[1], s[2], s[3]); - if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { - if((((uint64_t)n[3]) >= max_n_chain) && (rl >= ocv_w)) { - cwn = (rl/ocv_w) + ((rl % ocv_w)?(1):(0)); - kv_resize(uint64_t, (*sp), (cwn)); - cc = sp->a; - for (i = cws = cwe = 0; i < cwn; i++) { - cwe = cws + ocv_w; if(cwe > rl) cwe = rl; - assert(cwe > cws); - cc[i] = (cwe - cws)*(max_n_chain>>1); - // fprintf(stderr, "[M::%s::] cw::[%lu, %lu), cc::%lu\n", __func__, cws, cwe, cc[i]); - if(cc[i] > UINT32_MAX) cc[i] = UINT32_MAX; cc[i] <<= 32; - cws += ocv_w; - } - } - for (i = 0, k = 0, lch = 0; i < ol->length; ++i) { - r = &(ol->list[i]); - w = ha_ov_type(r, rl); - // ++n[w]; - // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { - if (r->shared_seed >= s[w]) { - if(cwn) { - m = (ol->list[i].x_pos_s/ocv_w); - rs = ol->list[i].x_pos_s; re = ol->list[i].x_pos_e + 1; - for (cws = m*ocv_w; m < cwn; m++) { - cwe = cws + ocv_w; if(cwe > rl) cwe = rl; - os = ((rs >= cws)? rs : cws); - oe = ((re <= cwe)? re : cwe); - if(oe <= os) break; - if(((uint32_t)cc[m]) + (oe - os) < UINT32_MAX) { - cc[m] += (oe - os); - } else { - cc[m] >>= 32; cc[m] <<= 32; cc[m] |= UINT32_MAX; - } - cws += ocv_w; - } - } - if (k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - if(ol->list[k].align_length < chain_cutoff) lch = 1; - ++k; - } else if(w == 3 && cwn > 0) { - m = (ol->list[i].x_pos_s/ocv_w); cw0 = cw1 = 0; - rs = ol->list[i].x_pos_s; re = ol->list[i].x_pos_e + 1; - for (cws = m*ocv_w; m < cwn; m++) { - cwe = cws + ocv_w; if(cwe > rl) cwe = rl; - os = ((rs >= cws)? rs : cws); - oe = ((re <= cwe)? re : cwe); - if(oe <= os) break; - // fprintf(stderr, "+++[M::%s::%.*s(qid::%u)] o[%lu, %lu), cur::%lu, max::%lu\n", __func__, - // (int32_t)Get_NAME_LENGTH(R_INF, ol->list[i].y_id), Get_NAME(R_INF, ol->list[i].y_id), ol->list[i].y_id, - // os, oe, ((uint64_t)((uint32_t)cc[m])), (cc[m]>>32)); - if((oe - os) + ((uint64_t)((uint32_t)cc[m])) >= (cc[m]>>32)) { - cw1 += (oe - os); - } else { - cw0 += (oe - os); - } - cws += ocv_w; - } - - if(cw0 >= ((cw0 + cw1)*0.7)) { - m = (ol->list[i].x_pos_s/ocv_w); - rs = ol->list[i].x_pos_s; re = ol->list[i].x_pos_e + 1; - for (cws = m*ocv_w; m < cwn; m++) { - cwe = cws + ocv_w; if(cwe > rl) cwe = rl; - os = ((rs >= cws)? rs : cws); - oe = ((re <= cwe)? re : cwe); - if(oe <= os) break; - if(((uint32_t)cc[m]) + (oe - os) < UINT32_MAX) { - cc[m] += (oe - os); - } else { - cc[m] >>= 32; cc[m] <<= 32; cc[m] |= UINT32_MAX; - } - cws += ocv_w; - } - if (k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - if(ol->list[k].align_length < chain_cutoff) lch = 1; - ++k; - // dbgn++; - // fprintf(stderr, "+++[M::%s::%.*s(qid::%u)] q[%d, %d), t[%d, %d), sc::%d, type::%d, cw0::%lu, cw1::%lu\n", __func__, - // (int32_t)Get_NAME_LENGTH(R_INF, ol->list[k].y_id), Get_NAME(R_INF, ol->list[k].y_id), ol->list[k].y_id, - // ol->list[k].x_pos_s, ol->list[k].x_pos_e+1, ol->list[k].y_pos_s, ol->list[k].y_pos_e+1, ol->list[k].shared_seed, ha_ov_type(&(ol->list[k]), rl), cw0, cw1); - } - } - } - ol->length = k; - } - } - - ks_introsort_or_xs(ol->length, ol->list); - if(lch) { - //@brief r485 - uint64_t zs, ze, rs, re, ob, os, oe, ocn, pp, kn, ms, me; int64_t osc; - for (i = l = 0, cn = cl->length; i < ol->length; ++i) { - if(ol->list[i].align_length < chain_cutoff) { - zs = ol->list[i].x_pos_s; ze = ol->list[i].x_pos_e + 1; - ob = (ze - zs)*OFL; if(ob < 16) ob = 16; - osc = ol->list[i].shared_seed*CH_SC; - ocn = ol->list[i].align_length<length) && (ze > ol->list[k].x_pos_s); k++) { - if(ol->list[k].align_length < chain_cutoff) continue; - if(ol->list[k].align_length < ocn) continue; - if(ol->list[k].shared_seed < osc) continue; - rs = ol->list[k].x_pos_s; re = ol->list[k].x_pos_e + 1; - os = ((rs>=zs)?rs:zs); oe = ((re<=ze)?re:ze); - if((oe > os) && (oe - os) >= ob) { - m = ol->list[k].non_homopolymer_errors; - pp = cl->list[m].readID; kn = 0; - for (; (m < cn) && (cl->list[m].readID == pp) && (kn < ocn); m++) { - me = cl->list[m].self_offset; ms = me - (cl->list[m].cnt&(0xffu)); - if((ms >= os) && (me <= oe)) kn++; - } - if(kn >= ocn) break; - } - } - if((k < ol->length) && (ze > ol->list[k].x_pos_s)) continue; - } - if (l != i) { - t = ol->list[l]; - ol->list[l] = ol->list[i]; - ol->list[i] = t; - } - l++; - } - ol->length = l; - } - - for (i = 0; i < ol->length; ++i) ol->list[i].align_length = 0; - // fprintf(stderr, "+[M::%s] rid::%u, ol->length0::%lu, dbgn::%lu\n", __func__, rid, ol->length, dbgn); -} - -void lchain_qgen_mcopy_fast_re1(Candidates_list* cl, uint32_t cl_beg, overlap_region_alloc* ol, uint32_t rid, uint64_t rl, uint64_t tl, - uint32_t apend_be, int64_t max_skip, int64_t max_iter, - int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, int64_t quick_check, - uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut) -{ - uint64_t cn = cl->length, m = cl_beg; - if(cl_beg >= cn) return; - - m += lchain_qdp_mcopy_fast(cl, cl_beg, cn - cl_beg, m, &(cl->chainDP), ol, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, - rid, rl, tl, quick_check, apend_be, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, 1); - cl->length = m; -} - -inline uint64_t special_lchain(Candidates_list* cl, overlap_region_alloc* ol, uint32_t rid, uint64_t rl, All_reads* rdb, - const ul_idx_t *udb, uint32_t apend_be, int64_t max_skip, int64_t max_iter, int64_t max_dis, double chn_pen_gap, - double chn_pen_skip, double bw_rate, int64_t quick_check, uint32_t gen_off, double mcopy_rate, uint32_t mcopy_khit_cut, - st_mt_t *sp, uint64_t *si, uint64_t m, uint64_t l, uint64_t k) -{ - uint64_t z, s, e, yid, ol0 = ol->length, ol1, m0 = m; - if(l >= k) return m; - yid = cl->list[l].readID; - for (z = l; z < k && cl->list[z].strand == cl->list[l].strand; z++); - if(z > l) { - s = l; e = z; ol1 = ol->length; // m0 = m; - m += lchain_qdp_mcopy(cl, s, e-s, m, &(cl->chainDP), ol, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, - rid, rl, rdb?Get_READ_LENGTH((*rdb), yid):udb->ug->u.a[yid].len, quick_check, apend_be, gen_off, 0, mcopy_rate, mcopy_khit_cut, 0); - // if(rid == 7) { - // fprintf(stderr, "+[M::%s::utg%.6ul] inn::[%lu, %lu), (*si)::%lu, ol1::%lu, ol->length::%lu\n", - // __func__, rid+1, s, e, (*si), ol1, ol->length); - // } - if(((*si) < sp->n) && (sp->a[(*si)] == s) && (ol->length > ol1)) { - ol->list[ol->length-1].x_pos_strand = 1; - // fprintf(stderr, "+[M::%s] utg%.6u%c -> utg%.6u%c, n_khits0::%lu, n_khits::%lu\n", __func__, rid+1, "lc"[udb->ug->u.a[rid].circ], - // ol->list[ol->length-1].y_id+1, "lc"[udb->ug->u.a[ol->list[ol->length-1].y_id].circ], e-s, m-m0); - } - for (; (*si) < sp->n && sp->a[(*si)] == s; (*si)++); - } - - if(z < k) { - s = z; e = k; ol1 = ol->length; // m0 = m; - m += lchain_qdp_mcopy(cl, s, e-s, m, &(cl->chainDP), ol, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, - rid, rl, rdb?Get_READ_LENGTH((*rdb), yid):udb->ug->u.a[yid].len, quick_check, apend_be, gen_off, 0, mcopy_rate, mcopy_khit_cut, 0); - // if(rid == 7) { - // fprintf(stderr, "-[M::%s::utg%.6ul] inn::[%lu, %lu), (*si)::%lu, ol1::%lu, ol->length::%lu\n", - // __func__, rid+1, s, e, (*si), ol1, ol->length); - // } - if(((*si) < sp->n) && (sp->a[(*si)] == s) && (ol->length > ol1)) { - ol->list[ol->length-1].x_pos_strand = 1; - // fprintf(stderr, "-[M::%s] utg%.6u%c -> utg%.6u%c, n_khits0::%lu, n_khits::%lu\n", __func__, rid+1, "lc"[udb->ug->u.a[rid].circ], - // ol->list[ol->length-1].y_id+1, "lc"[udb->ug->u.a[ol->list[ol->length-1].y_id].circ], e-s, m-m0); - } - for (; (*si) < sp->n && sp->a[(*si)] == s; (*si)++); - } - if(ol->length > ol0) { - overlap_region *p = &(ol->list[ol0]); uint64_t pi = ol0; overlap_region t; - for (z = ol0; z < ol->length; z++) { - if((p->shared_seed < ol->list[z].shared_seed) || - ((p->shared_seed == ol->list[z].shared_seed) && (ol->list[z].x_pos_strand == 1))) { - p = &(ol->list[z]); pi = z; - } - } - - // if(rid == 7) { - // fprintf(stderr, ">[M::%s::] utg%.6ul\t->\tutg%.6ul\tflag::%u\n", - // __func__, p->x_id+1, p->y_id+1, p->x_pos_strand); - // } - - for (z = s = ol0; z < ol->length; z++) { - if((ol->list[z].x_pos_strand == 0) && (z != pi)) continue; - if(s != z) { - t = ol->list[s]; - ol->list[s] = ol->list[z]; - ol->list[z] = t; - } - s++; - } - - if(s != ol->length) { - ol->length = s; - for (z = ol0; z < ol->length; z++) { - s = ol->list[z].non_homopolymer_errors; - pi = cl->list[s].readID; - ol->list[z].non_homopolymer_errors = m0; - for (; s < m && cl->list[s].readID == pi; s++) { - cl->list[m0] = cl->list[s]; - cl->list[m0].readID = z; m0++; - } - } - m = m0; - } - - } - return m; -} - -void lchain_qgen_mcopy_input(Candidates_list* cl, overlap_region_alloc* ol, uint32_t rid, uint64_t rl, All_reads* rdb, - const ul_idx_t *udb, uint32_t apend_be, uint64_t max_n_chain, int64_t max_skip, int64_t max_iter, - int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, double bw_thres_sec, - int64_t quick_check, uint32_t gen_off, double mcopy_rate, uint32_t mcopy_khit_cut, st_mt_t *sp) -{ - // fprintf(stderr, "+[M::%s]\n", __func__); - uint64_t i, k, l, m, cn = cl->length, yid, si; overlap_region *r; ///srt = 0 - clear_overlap_region_alloc(ol); - - // if(rid == 160) { - // fprintf(stderr, "[M::%s::utg%.6ul] sp->n::%u\n", __func__, rid+1, (uint32_t)sp->n); - // } - for (l = 0, k = 1, m = 0, si = 0; k <= cn; k++) { - if((k == cn) || (cl->list[k].readID != cl->list[l].readID)) { - if(cl->list[l].readID != rid) { - yid = cl->list[l].readID; - // if(rid == 160) { - // fprintf(stderr, "+[M::%s::utg%.6lul] [%lu, %lu), m::%lu, ol->length::%lu\n", __func__, yid+1, l, k, m, ol->length); - // } - for (; si < sp->n && sp->a[si] < l; si++); - if(si >= sp->n || sp->a[si] >= k) {///might be unmatched - m += lchain_qdp_mcopy(cl, l, k-l, m, &(cl->chainDP), ol, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, - rid, rl, rdb?Get_READ_LENGTH((*rdb), yid):udb->ug->u.a[yid].len, quick_check, apend_be, gen_off, 0, mcopy_rate, mcopy_khit_cut, 0); - } else { - m = special_lchain(cl, ol, rid, rl, rdb, udb, apend_be, max_skip, max_iter, max_dis, chn_pen_gap, - chn_pen_skip, bw_thres_sec, quick_check, gen_off, mcopy_rate, mcopy_khit_cut, sp, &si, m, l, k); - } - // if(rid == 160) { - // fprintf(stderr, "-[M::%s::utg%.6lul] [%lu, %lu), m::%lu, ol->length::%lu\n", __func__, yid+1, l, k, m, ol->length); - // } - } - l = k; - } - } - cl->length = m; - - // for (k = 0; k < ol->length; k++) { - // fprintf(stderr, "---[M::%s::utg%.6dl] q[%d, %d), t[%d, %d), khit_off::%u\n", __func__, - // (int32_t)ol->list[k].y_id+1, ol->list[k].x_pos_s, ol->list[k].x_pos_e+1, - // ol->list[k].y_pos_s, ol->list[k].y_pos_e+1, ol->list[k].non_homopolymer_errors); - // } - - k = ol->length; - if (ol->length > max_n_chain) { - int32_t w, n[4], s[4]; overlap_region t; - n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; - ks_introsort_or_ss(ol->length, ol->list); ///srt = 1; - for (i = 0; i < ol->length; ++i) { - r = &(ol->list[i]); - w = ha_ov_type(r, rl); - ++n[w]; - if (((uint64_t)n[w]) == max_n_chain) s[w] = r->shared_seed; - } - if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { - // n[0] = n[1] = n[2] = n[3] = 0; - for (i = 0, k = 0; i < ol->length; ++i) { - r = &(ol->list[i]); - w = ha_ov_type(r, rl); - // ++n[w]; - // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { - if ((r->shared_seed >= s[w]) || (r->x_pos_strand == 1)) { - if (k != i) { - t = ol->list[k]; - ol->list[k] = ol->list[i]; - ol->list[i] = t; - } - ++k; - } - } - ol->length = k; - } - } - ks_introsort_or_xs(ol->length, ol->list); -} - -void set_lchain_dp_op(uint32_t is_accurate, uint32_t mz_k, int64_t *max_skip, int64_t *max_iter, int64_t *max_dis, double *chn_pen_gap, double *chn_pen_skip, int64_t *quick_check) -{ - double div, pen_gap, pen_skip, tmp; - if(is_accurate) { - (*quick_check) = 1; (*max_skip) = 25; (*max_iter) = 5000; (*max_dis) = 5000; div = 0.01; pen_gap = 0.5f; pen_skip = 0.0005f; - } else { - (*quick_check) = 0; (*max_skip) = 25; (*max_iter) = 5000; (*max_dis) = 5000; div = 0.1; pen_gap = 0.5f; pen_skip = 0.0005f; - } - tmp = expf(-div * (double)mz_k);///0.60049557881 -> HiFi; 0.18268352405 -> ont - *chn_pen_gap = pen_gap * tmp;///0.300247789405 -> HiFi; 0.091341762025 -> ont - ///0.000300247789405 -> HiFi (>3330 will be negative); - //0.000091341762025 -> ont (>10947 will be negative); - *chn_pen_skip = pen_skip * tmp; -} - -void ul_map_lchain(ha_abufl_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, - int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut) -{ - extern void *ha_flt_tab; - extern ha_pt_t *ha_idx; - int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; - set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); - // minimizers_gen(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, dbg_ct, sp, high_occ, low_occ); - minimizers_qgen(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, NULL, uref, dbg_ct, sp, high_occ, low_occ); - // lchain_gen(cl, overlap_list, rid, rl, NULL, uref, apend_be, f_cigar, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off); - // lchain_qgen(cl, overlap_list, rid, rl, NULL, uref, apend_be, f_cigar, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off); - ///no need to sort here, overlap_list has been sorted at lchain_gen - lchain_qgen_mcopy(cl, overlap_list, rid, rl, NULL, uref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off, mcopy_rate, chain_cutoff, mcopy_khit_cut, sp); -} - -void h_ec_lchain(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, - int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t mcopy_num, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut, uint64_t ocv_w) -{ - extern void *ha_flt_tab; - extern ha_pt_t *ha_idx; - int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; - set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); - // minimizers_gen(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, dbg_ct, sp, high_occ, low_occ); - minimizers_qgen0(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, rref, dbg_ct, sp, high_occ, low_occ); - // lchain_gen(cl, overlap_list, rid, rl, NULL, uref, apend_be, f_cigar, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off); - // lchain_qgen(cl, overlap_list, rid, rl, NULL, uref, apend_be, f_cigar, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off); - ///no need to sort here, overlap_list has been sorted at lchain_gen - lchain_qgen_mcopy_fast(cl, overlap_list, rid, rl, rref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off, mcopy_num, mcopy_rate, chain_cutoff, mcopy_khit_cut, sp, ocv_w); -} - -void h_ec_lchain_amz(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, - int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut, uint64_t ocv_w) -{ - extern void *ha_flt_tab; - extern ha_pt_t *ha_idx; - int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; - set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); - // minimizers_gen(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, dbg_ct, sp, high_occ, low_occ); - minimizers_qgen0_amz(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, rref, dbg_ct, sp, high_occ, low_occ); - // lchain_gen(cl, overlap_list, rid, rl, NULL, uref, apend_be, f_cigar, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off); - // lchain_qgen(cl, overlap_list, rid, rl, NULL, uref, apend_be, f_cigar, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off); - ///no need to sort here, overlap_list has been sorted at lchain_gen - lchain_qgen_mcopy_fast(cl, overlap_list, rid, rl, rref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off, enable_mcopy, mcopy_rate, chain_cutoff, mcopy_khit_cut, sp, ocv_w); -} - -uint64_t recalu_minimizer0(char *s, uint64_t len, uint64_t is_hpc, int64_t mz_k, uint64_t mz_h, tiny_queue_t *tq, uint64_t *rpos, uint64_t *rspan) -{ - uint64_t k, l, shift1 = mz_k - 1, mask = (1ULL<front = tq->count = 0; - for (k = 1, l = 0, mz_l = mz_span = 0; k <= len; ++k) { - if (k == len || seq_nt4_table[(uint8_t)s[k]] != seq_nt4_table[(uint8_t)s[l]]) { - c = seq_nt4_table[(uint8_t)s[l]]; - if(c < 4) { - kmer[0] = (kmer[0] << 1 | (c&1)) & mask;/**forward k-mer**/ - kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; - kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; /**reverse k-mer**/ - kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; - if (kmer[1] == kmer[3]) continue; /** skip "symmetric k-mers" as we don't know it strand**/ - z = kmer[1] < kmer[3]? 0 : 1; /** strand**/ - mz_l++; mz_span += (k - l); - tq_push(tq, k - l); if (tq->count > mz_k) mz_span -= tq_shift(tq); - if(mz_l >= mz_k && mz_span < 256) { - hs = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); - if(mz_h == hs) { - (*rpos) = k - 1; (*rspan) = mz_span; - return 1; - } - } - } else { - mz_l = mz_span = 0; - } - - l = k; - } - } - } else { - for (k = 0, mz_l = mz_span = 0; k < len; ++k) { - c = seq_nt4_table[(uint8_t)s[k]]; - if(c < 4) { - kmer[0] = (kmer[0] << 1 | (c&1)) & mask;/**forward k-mer**/ - kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; - kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; /**reverse k-mer**/ - kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; - if (kmer[1] == kmer[3]) continue; /** skip "symmetric k-mers" as we don't know it strand**/ - z = kmer[1] < kmer[3]? 0 : 1; /** strand**/ - mz_l++; mz_span++; if(mz_span > mz_k) mz_span = mz_k; - if(mz_l >= mz_k) { - hs = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); - if(mz_h == hs) { - (*rpos) = k; (*rspan) = mz_span; - return 1; - } - } - } else { - mz_l = mz_span = 0; - } - } - } - - return 0; -} - -uint64_t recalu_minimizer0_adv(char *s, uint64_t len, uint64_t is_hpc, int64_t mz_k, uint64_t mz_h, uint64_t rev, tiny_queue_t *tq, uint64_t *rpos, uint64_t *rspan) -{ - uint64_t k, l, shift1 = mz_k - 1, mask = (1ULL<front = tq->count = 0; - for (k = 1, l = 0, mz_l = mz_span = 0; k <= len; ++k) { - if (k == len || seq_nt4_table[(uint8_t)s[k]] != seq_nt4_table[(uint8_t)s[l]]) { - c = seq_nt4_table[(uint8_t)s[l]]; - if(c < 4) { - kmer[0] = (kmer[0] << 1 | (c&1)) & mask;/**forward k-mer**/ - kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; - kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; /**reverse k-mer**/ - kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; - if (kmer[1] == kmer[3]) continue; /** skip "symmetric k-mers" as we don't know it strand**/ - z = kmer[1] < kmer[3]? 0 : 1; /** strand**/ - mz_l++; mz_span += (k - l); - tq_push(tq, k - l); if (tq->count > mz_k) mz_span -= tq_shift(tq); - if(mz_l >= mz_k && mz_span < 256) { - hs = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); - if(mz_h == hs) { - (*rpos) = k - 1; (*rspan) = mz_span; - return 1; - } - } - } else { - mz_l = mz_span = 0; - } - - l = k; - } - } - } else { - for (k = 0, mz_l = mz_span = 0; k < len; ++k) { - c = seq_nt4_table[(uint8_t)s[k]]; - if(c < 4) { - kmer[0] = (kmer[0] << 1 | (c&1)) & mask;/**forward k-mer**/ - kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; - kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; /**reverse k-mer**/ - kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; - if (kmer[1] == kmer[3]) continue; /** skip "symmetric k-mers" as we don't know it strand**/ - z = kmer[1] < kmer[3]? 0 : 1; /** strand**/ - mz_l++; mz_span++; if(mz_span > mz_k) mz_span = mz_k; - if(mz_l >= mz_k) { - hs = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); - if(mz_h == hs) { - (*rpos) = k; (*rspan) = mz_span; - return 1; - } - } - } else { - mz_l = mz_span = 0; - } - } - } - } else { - uint8_t ch[5] = {3, 2, 1, 0, 5}; - if(is_hpc) { - tq->front = tq->count = 0; - for (k = 1, l = 0, mz_l = mz_span = 0; k <= len; ++k) { - if (k == len || seq_nt4_table[(uint8_t)s[len-k-1]] != seq_nt4_table[(uint8_t)s[len-l-1]]) { - c = ch[seq_nt4_table[(uint8_t)s[len-l-1]]]; - if(c < 4) { - kmer[0] = (kmer[0] << 1 | (c&1)) & mask;/**forward k-mer**/ - kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; - kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; /**reverse k-mer**/ - kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; - if (kmer[1] == kmer[3]) continue; /** skip "symmetric k-mers" as we don't know it strand**/ - z = kmer[1] < kmer[3]? 0 : 1; /** strand**/ - mz_l++; mz_span += (k - l); - tq_push(tq, k - l); if (tq->count > mz_k) mz_span -= tq_shift(tq); - if(mz_l >= mz_k && mz_span < 256) { - hs = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); - if(mz_h == hs) { - (*rpos) = k - 1; (*rspan) = mz_span; - return 1; - } - } - } else { - mz_l = mz_span = 0; - } - - l = k; - } - } - } else { - for (k = 0, mz_l = mz_span = 0; k < len; ++k) { - c = ch[seq_nt4_table[(uint8_t)s[len-k-1]]]; - if(c < 4) { - kmer[0] = (kmer[0] << 1 | (c&1)) & mask;/**forward k-mer**/ - kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; - kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; /**reverse k-mer**/ - kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; - if (kmer[1] == kmer[3]) continue; /** skip "symmetric k-mers" as we don't know it strand**/ - z = kmer[1] < kmer[3]? 0 : 1; /** strand**/ - mz_l++; mz_span++; if(mz_span > mz_k) mz_span = mz_k; - if(mz_l >= mz_k) { - hs = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); - if(mz_h == hs) { - (*rpos) = k; (*rspan) = mz_span; - return 1; - } - } - } else { - mz_l = mz_span = 0; - } - } - } - } - - return 0; -} - - -uint64_t recalu_minimizer(uint64_t rid, anchor1_t *z, asg16_v *sc, int64_t *iok, int64_t *ink, int64_t *ick, int64_t *str_s, int64_t *str_e, uint64_t mz_k, uint64_t mz_h, tiny_queue_t *tq, All_reads *rref, UC_Read *tu, char *qstr, uint64_t qs, uint64_t qe) -{ - int64_t id = z->srt>>33; char *str = NULL; uint64_t rpos, rspan; - int64_t ok = *iok, nk = *ink, ck = *ick, cn = sc->n, s0, e0, s1, e1, os, oe, ots, ote, ol, wo[2], wn[2], weo[2], wen[2], ovlp, len = Get_READ_LENGTH((*rref), id); uint16_t op, bq, bt; uint32_t cl; - e0 = ((uint32_t)z->srt) + 1; s0 = e0 - z->other_off; s1 = e1 = -1; weo[0] = weo[1] = wen[0] = wen[1] = -1; - if(e0 <= s0) return 0; - - ///debug - // ok = nk = ck = 0; - - if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed - ck = ok = nk = 0; - } - - // if(id == 1/**s0 == 10260 && e0 == 10334**/) { - // fprintf(stderr, "\n\n-0-qk::%ld,\ttk::%ld,\tck::%ld,\ts0::%ld,\te0::%ld\n", ok, nk, ck, s0, e0); - // } - - while (ck > 0 && ok >= s0) {///x -> t; y -> p; first insertion and then match/mismatch - --ck; - op = sc->a[ck]>>14; - // ol = (((op == 1) || (op == 2))?(sc->a[ck]&(0xfff)):(sc->a[ck]&(0x3fff))); - if((op == 2) || (op == 3)) { - ol = sc->a[ck]&(0xfff); - } else if(op == 1) { - ol = sc->a[ck]&(0x3ff); - } else { - ol = sc->a[ck]&(0x3fff); - } - if(op != 2) ok -= ol; - if(op != 3) nk -= ol; - } - - // char cm[4]; cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; - // if(id == 1/**s0 == 10260 && e0 == 10334**/) { - // fprintf(stderr, "-1-qk::%ld,\ttk::%ld,\tck::%ld\n", ok, nk, ck); - // } - - while (ck < cn && ok < e0) { ///[s0, e0) - wo[0] = ok; wn[0] = nk; - // ck = pop_trace_bp(sc, ck, &op, &b, &cl); - ck = pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); - if(op != 2) ok += cl; - if(op != 3) nk += cl; - wo[1] = ok; wn[1] = nk; - - os = ((s0 >= wo[0])? s0 : wo[0]); - oe = ((e0 <= wo[1])? e0 : wo[1]); - // os = MAX(s0, wo[0]); oe = MIN(e0, wo[1]); - ovlp = ((oe>os)? (oe-os):0); - // if(id == 1/**s0 == 10260 && e0 == 10334**/) { - // fprintf(stderr, "%u%c(q::[%ld,%ld))(t::[%ld,%ld))(ck::%ld)\n", cl, cm[op], wo[0], wo[1], wn[0], wn[1], ck); - // } - - if(op != 2) { - if(!ovlp) continue; - } else {///wo[0] == wo[1] - if(wo[0] < s0 || wo[0] >= e0) continue; - } - - if(op < 2) { - ots = os - wo[0] + wn[0]; ote = oe - wo[0] + wn[0]; - } else {///op == 2: more y; p == 3: more x - ots = wn[0]; ote = wn[1]; - } - - if(s1 == -1) s1 = ots; - e1 = ote; - - if((op == 0) && (ovlp > 0) && (ovlp > weo[1] - weo[0])) { - weo[0] = os; weo[1] = oe; - wen[0] = ots; wen[1] = ote; - } - } - - while (ck < cn && ok <= e0) { ///[s0, e0) - wo[0] = ok; wn[0] = nk; - // pop_trace_bp(sc, ck, &op, &b, &cl); - pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); - if(op != 2) break; - // ck = pop_trace_bp(sc, ck, &op, &b, &cl); - ck = pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); - // if(op != 2) ok += cl; - // if(op != 3) nk += cl; - nk += cl; - wo[1] = ok; wn[1] = nk; - - // if(id == 1/**s0 == 10260 && e0 == 10334**/) { - // fprintf(stderr, "%u%c(q::[%ld,%ld))(t::[%ld,%ld))(ck::%ld)\n", cl, cm[op], wo[0], wo[1], wn[0], wn[1], ck); - // } - - if(wo[0] >= s0 && wo[0] <= e0) { - ots = wn[0]; ote = wn[1]; - if(s1 == -1) s1 = ots; - e1 = ote; - } - } - - assert(wen[1] <= len); - assert(e1 <= len); - - *iok = ok; *ink = nk; *ick = ck; - - if(weo[0] == s0 && weo[1] == e0) { - z->srt >>= 32; z->srt <<= 32; z->srt |= ((uint64_t)(wen[1]-1)); - ///debug - // char sstr[256]; recover_UC_Read_sub_region(sstr, wen[0], wen[1] - wen[0], 0, rref, id); - // if(recalu_minimizer0(sstr, wen[1] - wen[0], !(asm_opt.flag & HA_F_NO_HPC), mz_k, mz_h, tq, &rpos, &rspan) && (rpos + 1 == ((uint64_t)(wen[1] - wen[0]))) && (((uint64_t)(wen[1] - wen[0])) == rspan)) { - // // fprintf(stderr, "-0-[M::%s]\n", __func__); - // } else { - // // if(((z->srt>>32)&1) == 0) { - // fprintf(stderr, "-1-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], wen[0], wen[1], s0, e0, e0 - s0); - // fprintf(stderr, "tstr::%.*s\n", ((uint32_t)(wen[1] - wen[0])), sstr); - // fprintf(stderr, "qstr::%.*s\n", ((uint32_t)(qe - qs)), qstr + qs); - // exit(1); - // // } - // } - // if(rid == 3196 && id == 3199) fprintf(stderr, "-full-[M::%s]\n", __func__); - return 1; - } - - if(e1 <= s1) return 0; - - - - if(s1 >= (*str_s) && e1 <= (*str_e)) { - str = tu->seq + s1 - (*str_s); - } else { - if(s1 >= (*str_s) && (s1 < (*str_e)) && (e1 > (*str_e))) { - UC_Read_resize((*tu), (e1 - (*str_s))); - recover_UC_Read_sub_region(tu->seq + (*str_e) - (*str_s), (*str_e), e1 - (*str_e), 0, rref, id); - str = tu->seq + s1 - (*str_s); (*str_e) = e1; - } else { - UC_Read_resize((*tu), (e1 - s1)); - recover_UC_Read_sub_region(tu->seq, s1, e1 - s1, 0, rref, id); - str = tu->seq; (*str_s) = s1; (*str_e) = e1; - } - } - - if(recalu_minimizer0(str, e1 - s1, !(asm_opt.flag & HA_F_NO_HPC), mz_k, mz_h, tq, &rpos, &rspan)) { - rpos += s1; - z->srt >>= 32; z->srt <<= 32; z->srt |= rpos; z->other_off = rspan; - // fprintf(stderr, "-1-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], s1, e1, s0, e0, e0 - s0); - // if(rid == 3196 && id == 3199) fprintf(stderr, "-part-[M::%s]\n", __func__); - return 1; - } - // fprintf(stderr, "-0-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], s1, e1, s0, e0, e0 - s0); - - return 0; -} - -int64_t hpc_minimizer_test(int64_t id, All_reads *rref, UC_Read *bu, int64_t str_s, int64_t str_e, int64_t z, int64_t len, int64_t rev, int64_t step) -{ - if(z < 0 || z >= len) return 0; - if(z == 0 && rev == 1) return 0; - if(z == len - 1 && rev == 0) return 0; - - int64_t an, sc, ec, k, tn = 0; char c = 0, *a = NULL; - if(z >= str_s && z < str_e) c = bu->seq[z-str_s]; - - if(rev) { - if(c != 0) { - if(z > str_s) { - a = bu->seq; an = z - str_s; - for (k = an - 1; k >= 0 && a[k] == c; k--); - tn += an - k - 1; - if((k >= 0) || (z - tn == 0)) return tn; - ec = str_s; - } else { - ec = z; - } - } else { - ec = z + 1; - } - - sc = ec - step; if(sc < 0) sc = 0; - if(ec <= 0 || ec > len || ec <= sc) return tn; - - UC_Read_resize((*bu), (str_e - str_s) + (step)); - a = bu->seq + str_e - str_s; - - while (1) { - recover_UC_Read_sub_region(a, sc, ec - sc, 0, rref, id); an = ec - sc; - if(c == 0) c = a[--an]; - for (k = an - 1; k >= 0 && a[k] == c; k--); - tn += an - k - 1; - if((k >= 0) || (z - tn == 0)) return tn; - ec = sc; - sc = ec - step; if(sc < 0) sc = 0; - if(ec <= 0 || ec > len || ec <= sc) return tn; - } - } else { - if(c != 0) { - if(z + 1 < str_e) { - a = bu->seq + z + 1 - str_s; an = str_e - z - 1; - for (k = 0; k < an && a[k] == c; k++); - tn += k; - if((k < an) || (z + tn + 1 == len)) return tn; - sc = str_e; - } else { - sc = z + 1; - } - } else { - sc = z; - } - - ec = sc + step; if(ec > len) ec = len; - if(sc < 0 || sc >= len || sc >= ec) return tn; - - UC_Read_resize((*bu), (str_e - str_s) + (step)); - a = bu->seq + str_e - str_s; - - while (1) { - // if(bu->size < (a - bu->seq) + (ec - sc)) { - // fprintf(stderr, "-1-[M::%s]\tid::%ld\n", __func__, id); - // } - recover_UC_Read_sub_region(a, sc, ec - sc, 0, rref, id); an = ec - sc; - a = bu->seq + str_e - str_s; - if(c == 0) { - c = a[0]; a = a + 1; an--; - } - for (k = 0; k < an && a[k] == c; k++); - tn += k; - if((k < an) || (z + tn + 1 == len)) return tn; - sc = ec; - ec = sc + step; if(ec > len) ec = len; - if(sc < 0 || sc >= len || sc >= ec) return tn; - } - } -} - -uint64_t recalu_minimizer_bd(uint64_t rid, anchor1_t *z, asg16_v *sc, int64_t *iok, int64_t *ink, int64_t *ick, int64_t *str_s, int64_t *str_e, uint64_t mz_k, uint64_t mz_h, tiny_queue_t *tq, All_reads *rref, UC_Read *tu, char *qstr, uint64_t qs, uint64_t qe) -{ - int64_t id = z->srt>>33; char *str = NULL; uint64_t rpos, rspan; - int64_t ok = *iok, nk = *ink, ck = *ick, cn = sc->n, s0, e0, s1, e1, si, ei, os, oe, ots, ote, ol, wo[2], wn[2], weo[2], wen[2], ovlp, len = Get_READ_LENGTH((*rref), id); uint16_t op, bq, bt; uint32_t cl; - e0 = ((uint32_t)z->srt) + 1; s0 = e0 - z->other_off; s1 = e1 = si = ei = -1; weo[0] = weo[1] = wen[0] = wen[1] = -1; - if(e0 <= s0) return 0; - - ///debug - // ok = nk = ck = 0; - - if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed - ck = ok = nk = 0; - } - - // if(id == 1/**s0 == 10260 && e0 == 10334**/) { - // fprintf(stderr, "\n\n-0-qk::%ld,\ttk::%ld,\tck::%ld,\ts0::%ld,\te0::%ld\n", ok, nk, ck, s0, e0); - // } - - while (ck > 0 && ok >= s0) {///x -> t; y -> p; first insertion and then match/mismatch - --ck; - op = sc->a[ck]>>14; - // ol = (((op == 1) || (op == 2))?(sc->a[ck]&(0xfff)):(sc->a[ck]&(0x3fff))); - if((op == 2) || (op == 3)) { - ol = sc->a[ck]&(0xfff); - } else if(op == 1) { - ol = sc->a[ck]&(0x3ff); - } else { - ol = sc->a[ck]&(0x3fff); - } - if(op != 2) ok -= ol; - if(op != 3) nk -= ol; - } - - // char cm[4]; cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; - // if(id == 1/**s0 == 10260 && e0 == 10334**/) { - // fprintf(stderr, "-1-qk::%ld,\ttk::%ld,\tck::%ld\n", ok, nk, ck); - // } - while (ck < cn && ok < e0) { ///[s0, e0) - wo[0] = ok; wn[0] = nk; - // ck = pop_trace_bp(sc, ck, &op, &b, &cl); - ck = pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); - if(op != 2) ok += cl; - if(op != 3) nk += cl; - wo[1] = ok; wn[1] = nk; - - os = ((s0 >= wo[0])? s0 : wo[0]); - oe = ((e0 <= wo[1])? e0 : wo[1]); - // os = MAX(s0, wo[0]); oe = MIN(e0, wo[1]); - ovlp = ((oe>os)? (oe-os):0); - // if(id == 1/**s0 == 10260 && e0 == 10334**/) { - // fprintf(stderr, "%u%c(q::[%ld,%ld))(t::[%ld,%ld))(ck::%ld)\n", cl, cm[op], wo[0], wo[1], wn[0], wn[1], ck); - // } - - if(op != 2) { - if(!ovlp) continue; - } else {///wo[0] == wo[1] - if(wo[0] < s0 || wo[0] >= e0) continue; - } - - if(op < 2) { - ots = os - wo[0] + wn[0]; ote = oe - wo[0] + wn[0]; - } else {///op == 2: more y; p == 3: more x - ots = wn[0]; ote = wn[1]; - } - - if(s1 == -1) { - s1 = ots; - // if((op == 0) && (wn[1] > ots) && ((wn[0] < ots) || (ots == 0))) si = 1; - if((op == 0) && (wo[1] > s0) && ((wo[0] < s0) || (s1 == 0))) si = 1; - } - - e1 = ote; - if((op == 0) && (wo[0] < e0) && ((wo[1] > e0) || (e1 == len))) ei = 1; - - if((op == 0) && (ovlp > 0) && (ovlp > weo[1] - weo[0])) { - weo[0] = os; weo[1] = oe; - wen[0] = ots; wen[1] = ote; - } - } - - while (ck < cn && ok <= e0) { ///[s0, e0) - wo[0] = ok; wn[0] = nk; - // pop_trace_bp(sc, ck, &op, &b, &cl); - pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); - if(op != 2) break; - // ck = pop_trace_bp(sc, ck, &op, &b, &cl); - ck = pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); - // if(op != 2) ok += cl; - // if(op != 3) nk += cl; - nk += cl; - wo[1] = ok; wn[1] = nk; - - // if(id == 1/**s0 == 10260 && e0 == 10334**/) { - // fprintf(stderr, "%u%c(q::[%ld,%ld))(t::[%ld,%ld))(ck::%ld)\n", cl, cm[op], wo[0], wo[1], wn[0], wn[1], ck); - // } - - if(wo[0] >= s0 && wo[0] <= e0) { - ots = wn[0]; ote = wn[1]; - if(s1 == -1) s1 = ots; - e1 = ote; - } - } - - assert(wen[1] <= len); - assert(e1 <= len); - - *iok = ok; *ink = nk; *ick = ck; - if(e1 <= s1) return 0; - rpos = rspan = ((uint64_t)-1); - - if(weo[0] == s0 && weo[1] == e0) { - rpos = wen[1]-1; rspan = e0 - s0; - /** - if(si == 1 && ei == 1) { - z->srt >>= 32; z->srt <<= 32; z->srt |= ((uint64_t)(wen[1]-1)); - ///debug - // char sstr[256]; recover_UC_Read_sub_region(sstr, wen[0], wen[1] - wen[0], 0, rref, id); - // if(recalu_minimizer0(sstr, wen[1] - wen[0], !(asm_opt.flag & HA_F_NO_HPC), mz_k, mz_h, tq, &rpos, &rspan) && (rpos + 1 == ((uint64_t)(wen[1] - wen[0]))) && (((uint64_t)(wen[1] - wen[0])) == rspan)) { - // // fprintf(stderr, "-0-[M::%s]\n", __func__); - // } else { - // // if(((z->srt>>32)&1) == 0) { - // fprintf(stderr, "-1-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], wen[0], wen[1], s0, e0, e0 - s0); - // fprintf(stderr, "tstr::%.*s\n", ((uint32_t)(wen[1] - wen[0])), sstr); - // fprintf(stderr, "qstr::%.*s\n", ((uint32_t)(qe - qs)), qstr + qs); - // exit(1); - // // } - // } - // if(rid == 3196 && id == 3199) fprintf(stderr, "-full-[M::%s]\n", __func__); - return 1; - } - **/ - } else { - if(s1 >= (*str_s) && e1 <= (*str_e)) { - str = tu->seq + s1 - (*str_s); - } else { - if(s1 >= (*str_s) && (s1 < (*str_e)) && (e1 > (*str_e))) { - UC_Read_resize((*tu), (e1 - (*str_s))); - recover_UC_Read_sub_region(tu->seq + (*str_e) - (*str_s), (*str_e), e1 - (*str_e), 0, rref, id); - str = tu->seq + s1 - (*str_s); (*str_e) = e1; - } else { - UC_Read_resize((*tu), (e1 - s1)); - recover_UC_Read_sub_region(tu->seq, s1, e1 - s1, 0, rref, id); - str = tu->seq; (*str_s) = s1; (*str_e) = e1; - } - } - - if(recalu_minimizer0(str, e1 - s1, !(asm_opt.flag & HA_F_NO_HPC), mz_k, mz_h, tq, &rpos, &rspan)) { - rpos += s1; - } - } - - if(rpos != ((uint64_t)-1) && rspan != ((uint64_t)-1)) { - e0 = rpos + 1; s0 = e0 - rspan; - if(!(asm_opt.flag & HA_F_NO_HPC)) { - if(si == -1) { - s0 -= hpc_minimizer_test(id, rref, tu, *str_s, *str_e, s0, len, 1, 8); - assert(s0 >= 0 && s0 < len && s0 < e0); - } - - if(ei == -1) { - e0 += hpc_minimizer_test(id, rref, tu, *str_s, *str_e, e0-1, len, 0, 8); - assert(e0 >= 0 && e0 < len && s0 < e0); - } - } - - rpos = e0 - 1; rspan = e0 - s0; - if(rspan < 256) { - z->srt >>= 32; z->srt <<= 32; z->srt |= rpos; z->other_off = rspan; - return 1; - } - } - /** - if(recalu_minimizer0(str, e1 - s1, !(asm_opt.flag & HA_F_NO_HPC), mz_k, mz_h, tq, &rpos, &rspan)) { - rpos += s1; - z->srt >>= 32; z->srt <<= 32; z->srt |= rpos; z->other_off = rspan; - // fprintf(stderr, "-1-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], s1, e1, s0, e0, e0 - s0); - // if(rid == 3196 && id == 3199) fprintf(stderr, "-part-[M::%s]\n", __func__); - return 1; - } - // fprintf(stderr, "-0-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], s1, e1, s0, e0, e0 - s0); - **/ - - return 0; -} - - -uint64_t recalu_minimizer_non_retrieve(uint64_t rid, anchor1_t *z, asg16_v *sc, int64_t *iok, int64_t *ink, int64_t *ick, uint64_t mz_k, uint64_t mz_h, tiny_queue_t *tq, char *tstr, int64_t tl, uint64_t trev/** , char *qstr, uint64_t qs, uint64_t qe**/) -{ - char *str = NULL; uint64_t rpos, rspan; char c; - int64_t ok = *iok, nk = *ink, ck = *ick, cn = sc->n, s0, e0, s1, e1, os, oe, ots, ote, ol, wo[2], wn[2], weo[2], wen[2], ovlp, k; uint16_t op, bq, bt; uint32_t cl; - e0 = ((uint32_t)z->srt) + 1; s0 = e0 - z->other_off; s1 = e1 = -1; weo[0] = weo[1] = wen[0] = wen[1] = -1; - if(e0 <= s0) return 0; - - - if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed - ck = ok = nk = 0; - } - - while (ck > 0 && ok >= s0) {///x -> t; y -> p; first insertion and then match/mismatch - --ck; - op = sc->a[ck]>>14; - // ol = (((op == 1) || (op == 2))?(sc->a[ck]&(0xfff)):(sc->a[ck]&(0x3fff))); - if((op == 2) || (op == 3)) { - ol = sc->a[ck]&(0xfff); - } else if(op == 1) { - ol = sc->a[ck]&(0x3ff); - } else { - ol = sc->a[ck]&(0x3fff); - } - if(op != 2) ok -= ol; - if(op != 3) nk -= ol; - } - - while (ck < cn && ok < e0) { ///[s0, e0) - wo[0] = ok; wn[0] = nk; - // ck = pop_trace_bp(sc, ck, &op, &b, &cl); - ck = pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); - if(op != 2) ok += cl; - if(op != 3) nk += cl; - wo[1] = ok; wn[1] = nk; - - os = ((s0 >= wo[0])? s0 : wo[0]); - oe = ((e0 <= wo[1])? e0 : wo[1]); - // os = MAX(s0, wo[0]); oe = MIN(e0, wo[1]); - ovlp = ((oe>os)? (oe-os):0); - - if(op != 2) { - if(!ovlp) continue; - } else {///wo[0] == wo[1] - if(wo[0] < s0 || wo[0] >= e0) continue; - } - - if(op < 2) { - ots = os - wo[0] + wn[0]; ote = oe - wo[0] + wn[0]; - } else {///op == 2: more y; p == 3: more x - ots = wn[0]; ote = wn[1]; - } - - if(s1 == -1) s1 = ots; - e1 = ote; - - if((op == 0) && (ovlp > 0) && (ovlp > weo[1] - weo[0])) { - weo[0] = os; weo[1] = oe; - wen[0] = ots; wen[1] = ote; - } - } - - while (ck < cn && ok <= e0) { ///[s0, e0) - wo[0] = ok; wn[0] = nk; - // pop_trace_bp(sc, ck, &op, &b, &cl); - pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); - if(op != 2) break; - // ck = pop_trace_bp(sc, ck, &op, &b, &cl); - ck = pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); - // if(op != 2) ok += cl; - // if(op != 3) nk += cl; - nk += cl; - wo[1] = ok; wn[1] = nk; - - - if(wo[0] >= s0 && wo[0] <= e0) { - ots = wn[0]; ote = wn[1]; - if(s1 == -1) s1 = ots; - e1 = ote; - } - } - - assert(wen[1] <= tl); - assert(e1 <= tl); - - *iok = ok; *ink = nk; *ick = ck; - - rpos = rspan = ((uint64_t)-1); - if(weo[0] == s0 && weo[1] == e0) { - rpos = wen[1]-1; rspan = e0 - s0; - // z->srt >>= 32; z->srt <<= 32; z->srt |= ((uint64_t)(wen[1]-1)); - ///debug - // char sstr[256]; recover_UC_Read_sub_region(sstr, wen[0], wen[1] - wen[0], 0, rref, id); - // if(recalu_minimizer0(sstr, wen[1] - wen[0], !(asm_opt.flag & HA_F_NO_HPC), mz_k, mz_h, tq, &rpos, &rspan) && (rpos + 1 == ((uint64_t)(wen[1] - wen[0]))) && (((uint64_t)(wen[1] - wen[0])) == rspan)) { - // // fprintf(stderr, "-0-[M::%s]\n", __func__); - // } else { - // // if(((z->srt>>32)&1) == 0) { - // fprintf(stderr, "-1-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], wen[0], wen[1], s0, e0, e0 - s0); - // fprintf(stderr, "tstr::%.*s\n", ((uint32_t)(wen[1] - wen[0])), sstr); - // fprintf(stderr, "qstr::%.*s\n", ((uint32_t)(qe - qs)), qstr + qs); - // exit(1); - // // } - // } - // if(rid == 3196 && id == 3199) fprintf(stderr, "-full-[M::%s]\n", __func__); - // return 1; - } else { - if(e1 <= s1) return 0; - // if(s1 >= tl || e1 >= tl) return 0; - - if(trev) str = tstr + tl - e1; - else str = tstr + s1; - - if(recalu_minimizer0_adv(str, e1 - s1, !(asm_opt.flag & HA_F_NO_HPC), mz_k, mz_h, trev, tq, &rpos, &rspan)) { - rpos += s1; - // z->srt >>= 32; z->srt <<= 32; z->srt |= rpos; z->other_off = rspan; - // fprintf(stderr, "-1-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], s1, e1, s0, e0, e0 - s0); - // if(rid == 3196 && id == 3199) fprintf(stderr, "-part-[M::%s]\n", __func__); - // return 1; - } - } - - if(rpos != ((uint64_t)-1) && rspan != ((uint64_t)-1)) { - e0 = rpos + 1; s0 = e0 - rspan; - if(!(asm_opt.flag & HA_F_NO_HPC)) { - if(!trev) { - s1 = s0; e1 = e0; - } else { - s1 = tl - e0; e1 = tl - s0; - } - - c = tstr[s1]; - for (k = s1 - 1; k >= 0 && tstr[k] == c; k--); s1 = k + 1; - - c = tstr[e1-1]; - for (k = e1; k < tl && tstr[k] == c; k++); e1 = k; - - if(!trev) { - s0 = s1; e0 = e1; - } else { - s0 = tl - e1; e0 = tl - s1; - } - } - - rpos = e0 - 1; rspan = e0 - s0; - if(rspan < 256) { - z->srt >>= 32; z->srt <<= 32; z->srt |= rpos; z->other_off = rspan; - return 1; - } - } - // fprintf(stderr, "-0-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], s1, e1, s0, e0, e0 - s0); - - return 0; -} - -void hpc_ext_check(All_reads *rref, uint32_t id, int64_t s0, int64_t e0, int64_t l, uint64_t rev, char *buf) -{ - if(s0 < 0) s0 = 0; if(e0 > l) e0 = l; - int64_t s = s0 - 256, e = e0 + 256, n, k, os0, oe0, os1, oe1; char c; if(s < 0) s = 0; if(e > l) e = l; - recover_UC_Read_sub_region(buf, s, e - s, rev, rref, id); - os0 = s0 - s; oe0 = e0 - s; n = e - s; os1 = os0; oe1 = oe0; - c = buf[os0]; - for (k = os0 - 1; k >= 0 && buf[k] == c; k--); os1 = k + 1; - - c = buf[oe0-1]; - for (k = oe0; k < n && buf[k] == c; k++); oe1 = k; - - if(os1 != os0 || oe1 != oe0) { - fprintf(stderr, "[M::%s]\to0::[%ld,%ld)\to1::[%ld,%ld)\n", __func__, os0 + s0, oe0 + s0, os1 + s0, oe1 + s0); - } - -} - -void h_ec_lchain_re_gen(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, ha_pt_t *ha_idx, All_reads *rref, overlap_region_alloc *olst, Candidates_list *cl, double bw_thres, - int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, - int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip, UC_Read *tu, asg64_v *oidx, asg16_v *scc) -{ - uint64_t i, k, l, m, max_cnt = UINT32_MAX, min_cnt = 0; int n, n0, j; ha_mz1_t *z; seed1_t *s; tiny_queue_t tq; memset(&tq, 0, sizeof(tiny_queue_t)); - if(high_occ) { - max_cnt = (*high_occ); - if(max_cnt < 2) max_cnt = 2; - } - if(low_occ) { - min_cnt = (*low_occ); - if(min_cnt < 2) min_cnt = 2; - } - clear_Candidates_list(cl); ab->n_a = 0; - - // minimizer of queried read - if (ab->mz.m > ab->old_mz_m) { - ab->old_mz_m = ab->mz.m; - REALLOC(ab->seed, ab->old_mz_m); - } - - for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { - ab->seed[i].a = ha_pt_get(ha_idx, ab->mz.a[i].x, &n); - ab->seed[i].n = n; - ab->n_a += n; - } - - if (ab->n_a > ab->m_a) { - ab->m_a = ab->n_a; - REALLOC(ab->a, ab->m_a); - } - - for (i = 0, k = 0; i < ab->mz.n; ++i) { - ///z is one of the minimizer - z = &ab->mz.a[i]; s = &ab->seed[i]; - - // uint64_t rpos, rspan; - // if(!recalu_minimizer0(rs + (z->pos+1-z->span), z->span, !(asm_opt.flag & HA_F_NO_HPC), mz_k, z->x, &tq, &rpos, &rspan)) { - // fprintf(stderr, "-1-[M::%s]\t%c\trg0::[%u,%u)\trid::%u\n", __func__, "+-"[z->rev], z->pos+1-z->span, z->pos+1, rid); - // } - // else { - // fprintf(stderr, "-0-[M::%s]\t%c\trg0::[%u,%u)\trid::%u\n", __func__, "+-"[z->rev], z->pos+1-z->span, z->pos+1, rid); - // } - - for (j = 0; j < s->n; ++j) { - const ha_idxpos_t *y = &s->a[j]; - anchor1_t *an = &ab->a[k++]; - uint8_t rev = z->rev == y->rev? 0 : 1; - - // an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; - an->other_off = y->span; - - // an->self_off = z->pos; - an->self_off = i; - - ///an->cnt: cnt<<8|span - an->cnt = s->n; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; - an->cnt <<= 8; an->cnt |= ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); - - // an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; - an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | y->pos; - } - } - - // copy over to _cl_ - if (ab->m_a >= (uint64_t)cl->size) { - cl->size = ab->m_a; - REALLOC(cl->list, cl->size); - } - clear_overlap_region_alloc(olst); - - // char dbg[256]; uint64_t rpos, rspan, thash; - // char dbg[768]; - k_mer_hit *p; uint64_t tid = (uint64_t)-1, tl = (uint64_t)-1, trev, tspan, ol, zn, olst_n; int64_t ok, nk, ck, str_s, str_e; - radix_sort_ha_an1(ab->a, ab->a + ab->n_a); - for (k = 1, l = ol = n = zn = 0; k <= ab->n_a; ++k) { - if (k == ab->n_a || (ab->a[k].srt>>32) != (ab->a[l].srt>>32)) { - for (; (ol < oidx->n) && ((oidx->a[ol]>>32) < (ab->a[l].srt>>32)); ol++); - if((ol < oidx->n) && ((ab->a[l].srt>>32) == (oidx->a[ol]>>32))) { - tl = Get_READ_LENGTH((*rref), ab->a[l].srt>>33); tid = ab->a[l].srt>>33; trev = (ab->a[l].srt>>32) & 1; olst_n = olst->length; - for (i = l, m = 0, ok = nk = ck = str_s = str_e = 0; i < k; i++) { - if(!recalu_minimizer(rid, &(ab->a[i]), &(scc[tid]), &ok, &nk, &ck, &str_s, &str_e, mz_k, ab->mz.a[ab->a[i].self_off].x, &tq, rref, tu, rs, ab->mz.a[ab->a[i].self_off].pos+1-ab->mz.a[ab->a[i].self_off].span, ab->mz.a[ab->a[i].self_off].pos+1)) continue; - ///debug - // recover_UC_Read_sub_region(dbg, ((uint32_t)ab->a[i].srt) + 1 - ab->a[i].other_off, ab->a[i].other_off, 0, rref, tid); - // if(recalu_minimizer0(dbg, ab->a[i].other_off, !(asm_opt.flag & HA_F_NO_HPC), mz_k, ab->mz.a[ab->a[i].self_off].x, &tq, &rpos, &rspan) && (rpos + 1 == ab->a[i].other_off) && (ab->a[i].other_off == rspan)) { - // // fprintf(stderr, "-0-[M::%s]\n", __func__); - // } else { - // fprintf(stderr, "-1-[M::%s]\n", __func__); - // } - // thash = ab->mz.a[ab->a[i].self_off].x; - ab->a[m] = ab->a[i]; tspan = ab->a[m].other_off; - ab->a[m].other_off = (uint32_t)ab->a[m].srt; - if(trev) ab->a[m].other_off = tl - (ab->a[m].other_off+1-tspan) - 1;///looks like a bug - ab->a[m].self_off = ab->mz.a[ab->a[m].self_off].pos; - ab->a[m].srt = ab->a[m].self_off; ab->a[m].srt <<= 32; ab->a[m].srt |= ab->a[m].other_off; - ///debug - // recover_UC_Read_sub_region(dbg, ab->a[m].other_off + 1 - tspan, tspan, trev, rref, tid); - // if(recalu_minimizer0(dbg, tspan, !(asm_opt.flag & HA_F_NO_HPC), mz_k, thash, &tq, &rpos, &rspan) && (rpos + 1 == tspan) && (tspan == rspan)) { - // fprintf(stderr, "-0-[M::%s]\n", __func__); - // } else { - // fprintf(stderr, "-1-[M::%s]\ttrev::%lu\n", __func__, trev); - // } - ///debug - // if(rid == 3196 && tid == 3199) hpc_ext_check(rref, tid, ab->a[m].other_off + 1 - tspan, ab->a[m].other_off + 1, tl, trev, dbg); - - - m++; - } - if(m > 1) radix_sort_ha_an1(ab->a, ab->a + m); - for (i = 0, n0 = n; i < m; i++) { - p = &cl->list[n++]; - p->readID = tid; - p->strand = trev; - p->offset = ab->a[i].other_off; - p->self_offset = ab->a[i].self_off; - if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ - p->cnt = 1; - } else if((ab->a[i].cnt>>8) <= min_cnt) { - p->cnt = 2; - } else{ - p->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); - p->cnt = pow(p->cnt, 1.1); - } - if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; - p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); - } - - // if(rid == 3196 && tid == 3199) fprintf(stderr, "[M::%s]\ttid::%lu\ttrev::%lu\told::%lu\tnew::%lu\n", __func__, tid, trev, k - l, m); - - if(m > 0 && tid != rid) { - zn += lchain_qdp_mcopy_fast(cl, n0, n-n0, zn, &(cl->chainDP), olst, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, - rid, rl, tl, quick_check, apend_be, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, 1); - } - - if(olst->length > olst_n) { - oidx->a[ol] >>= 32; oidx->a[ol] <<= 32; oidx->a[ol] |= ((uint64_t)((uint32_t)-1)); - } - } - - l = k; - } - } - cl->length = zn; - - for (k = m = 0; k < oidx->n; k++) { - if(((uint32_t)oidx->a[k]) == ((uint32_t)-1)) continue; - oidx->a[m++] = oidx->a[k]; - } - // fprintf(stderr, "[M::%s]\ttot::%lu\tremain::%lu\n", __func__, (uint64_t)oidx->n, m); - oidx->n = m; - - for (i = 0; i < olst->length; ++i) olst->list[i].align_length = 0; - - // minimizers_qgen0(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, rref, dbg_ct, sp, high_occ, low_occ); - - // lchain_qgen_mcopy_fast(cl, overlap_list, rid, rl, rref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off, enable_mcopy, mcopy_rate, chain_cutoff, mcopy_khit_cut, sp); -} - - -void h_ec_lchain_re_gen3(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, ha_pt_t *ha_idx, All_reads *rref, overlap_region_alloc *olst, Candidates_list *cl, double bw_thres, - int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, - int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip, UC_Read *tu, asg64_v *oidx, asg16_v *scc) -{ - uint64_t i, k, l, m, max_cnt = UINT32_MAX, min_cnt = 0; int n, n0, j; ha_mz1_t *z; seed1_t *s; tiny_queue_t tq; memset(&tq, 0, sizeof(tiny_queue_t)); - if(high_occ) { - max_cnt = (*high_occ); - if(max_cnt < 2) max_cnt = 2; - } - if(low_occ) { - min_cnt = (*low_occ); - if(min_cnt < 2) min_cnt = 2; - } - clear_Candidates_list(cl); ab->n_a = 0; - - // minimizer of queried read - if (ab->mz.m > ab->old_mz_m) { - ab->old_mz_m = ab->mz.m; - REALLOC(ab->seed, ab->old_mz_m); - } - - for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { - ab->seed[i].a = ha_pt_get(ha_idx, ab->mz.a[i].x, &n); - ab->seed[i].n = n; - ab->n_a += n; - } - - if (ab->n_a > ab->m_a) { - ab->m_a = ab->n_a; - REALLOC(ab->a, ab->m_a); - } - - for (i = 0, k = 0; i < ab->mz.n; ++i) { - ///z is one of the minimizer - z = &ab->mz.a[i]; s = &ab->seed[i]; - - // uint64_t rpos, rspan; - // if(!recalu_minimizer0(rs + (z->pos+1-z->span), z->span, !(asm_opt.flag & HA_F_NO_HPC), mz_k, z->x, &tq, &rpos, &rspan)) { - // fprintf(stderr, "-1-[M::%s]\t%c\trg0::[%u,%u)\trid::%u\n", __func__, "+-"[z->rev], z->pos+1-z->span, z->pos+1, rid); - // } - // else { - // fprintf(stderr, "-0-[M::%s]\t%c\trg0::[%u,%u)\trid::%u\n", __func__, "+-"[z->rev], z->pos+1-z->span, z->pos+1, rid); - // } - - for (j = 0; j < s->n; ++j) { - const ha_idxpos_t *y = &s->a[j]; - anchor1_t *an = &ab->a[k++]; - uint8_t rev = z->rev == y->rev? 0 : 1; - - // an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; - an->other_off = y->span; - - // an->self_off = z->pos; - an->self_off = i; - - ///an->cnt: cnt<<8|span - an->cnt = s->n; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; - an->cnt <<= 8; an->cnt |= ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); - - // an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; - an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | y->pos; - } - } - - // copy over to _cl_ - if (ab->m_a >= (uint64_t)cl->size) { - cl->size = ab->m_a; - REALLOC(cl->list, cl->size); - } - clear_overlap_region_alloc(olst); - - // char dbg[256]; uint64_t rpos, rspan, thash; - // char dbg[768]; uint64_t rpos, rspan, thash; - k_mer_hit *p; uint64_t tid = (uint64_t)-1, tl = (uint64_t)-1, trev, tspan, ol, zn, olst_n, sk, sv; int64_t ok, nk, ck, str_s, str_e; - radix_sort_ha_an1(ab->a, ab->a + ab->n_a); - for (k = 1, l = ol = n = zn = 0; k <= ab->n_a; ++k) { - if (k == ab->n_a || (ab->a[k].srt>>32) != (ab->a[l].srt>>32)) { - - for (sk = sv = 0; (ol < oidx->n) && ((oidx->a[ol]>>33) < (ab->a[l].srt>>33)); ol++); - if((ol < oidx->n) && ((ab->a[l].srt>>33) == (oidx->a[ol]>>33))) { - for (; (ol < oidx->n) && ((oidx->a[ol]>>32) < (ab->a[l].srt>>32)); ol++); - if((ol < oidx->n) && ((ab->a[l].srt>>32) == (oidx->a[ol]>>32))) { - if(((uint32_t)oidx->a[ol]) == ((uint32_t)-1)) sk = 1;///exact match - else sv = 1; - } else {///match in rev - sk = 1; - } - } - - if(!sk) { - tl = Get_READ_LENGTH((*rref), ab->a[l].srt>>33); tid = ab->a[l].srt>>33; trev = (ab->a[l].srt>>32) & 1; olst_n = olst->length; - if(tid != rid) { - for (i = l, m = 0, ok = nk = ck = str_s = str_e = 0; i < k; i++) { - if(!recalu_minimizer_bd(rid, &(ab->a[i]), &(scc[tid]), &ok, &nk, &ck, &str_s, &str_e, mz_k, ab->mz.a[ab->a[i].self_off].x, &tq, rref, tu, rs, ab->mz.a[ab->a[i].self_off].pos+1-ab->mz.a[ab->a[i].self_off].span, ab->mz.a[ab->a[i].self_off].pos+1)) continue; - ///debug - // recover_UC_Read_sub_region(dbg, ((uint32_t)ab->a[i].srt) + 1 - ab->a[i].other_off, ab->a[i].other_off, 0, rref, tid); - // if(recalu_minimizer0(dbg, ab->a[i].other_off, !(asm_opt.flag & HA_F_NO_HPC), mz_k, ab->mz.a[ab->a[i].self_off].x, &tq, &rpos, &rspan) && (rpos + 1 == ab->a[i].other_off) && (ab->a[i].other_off == rspan)) { - // // fprintf(stderr, "-0-[M::%s]\n", __func__); - // } else { - // fprintf(stderr, "-1-[M::%s]\n", __func__); - // } - // thash = ab->mz.a[ab->a[i].self_off].x; - ab->a[m] = ab->a[i]; tspan = ab->a[m].other_off; - ab->a[m].other_off = (uint32_t)ab->a[m].srt; - if(trev) ab->a[m].other_off = tl - (ab->a[m].other_off+1-tspan) - 1;///looks like a bug - ab->a[m].self_off = ab->mz.a[ab->a[m].self_off].pos; - ab->a[m].srt = ab->a[m].self_off; ab->a[m].srt <<= 32; ab->a[m].srt |= ab->a[m].other_off; - ///debug - /** - recover_UC_Read_sub_region(dbg, ab->a[m].other_off + 1 - tspan, tspan, trev, rref, tid); - if(recalu_minimizer0(dbg, tspan, !(asm_opt.flag & HA_F_NO_HPC), mz_k, thash, &tq, &rpos, &rspan) && (rpos + 1 == tspan) && (tspan == rspan)) { - // fprintf(stderr, "-0-[M::%s]\n", __func__); - } else { - fprintf(stderr, "-1-[M::%s]\ttrev::%lu\n", __func__, trev); - } - ///debug - hpc_ext_check(rref, tid, ab->a[m].other_off + 1 - tspan, ab->a[m].other_off + 1, tl, trev, dbg); - **/ - - m++; - } - if(m > 1) radix_sort_ha_an1(ab->a, ab->a + m); - for (i = 0, n0 = n; i < m; i++) { - p = &cl->list[n++]; - p->readID = tid; - p->strand = trev; - p->offset = ab->a[i].other_off; - p->self_offset = ab->a[i].self_off; - if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ - p->cnt = 1; - } else if((ab->a[i].cnt>>8) <= min_cnt) { - p->cnt = 2; - } else{ - p->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); - p->cnt = pow(p->cnt, 1.1); - } - if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; - p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); - } - - if(m > 0) { - zn += lchain_qdp_mcopy_fast(cl, n0, n-n0, zn, &(cl->chainDP), olst, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, - rid, rl, tl, quick_check, apend_be, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, 1); - } - - if(sv && olst->length > olst_n) { - oidx->a[ol] >>= 32; oidx->a[ol] <<= 32; oidx->a[ol] |= ((uint64_t)((uint32_t)-1)); - } - } - } - - l = k; - } - } - cl->length = zn; - - for (k = m = 0; k < oidx->n; k++) { - if(((uint32_t)oidx->a[k]) == ((uint32_t)-1)) continue; - oidx->a[m++] = oidx->a[k]; - } - // fprintf(stderr, "[M::%s]\ttot::%lu\tremain::%lu\n", __func__, (uint64_t)oidx->n, m); - oidx->n = m; - - for (i = 0; i < olst->length; ++i) olst->list[i].align_length = 0; - - // minimizers_qgen0(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, rref, dbg_ct, sp, high_occ, low_occ); - - // lchain_qgen_mcopy_fast(cl, overlap_list, rid, rl, rref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off, enable_mcopy, mcopy_rate, chain_cutoff, mcopy_khit_cut, sp); -} - - -void h_ec_lchain_re_gen_srt(ha_abuf_t *ab, ha_pt_t *ha_idx, overlap_region_alloc *olst, Candidates_list *cl) -{ - uint64_t i, k; int j, n; ha_mz1_t *z; seed1_t *s; - - clear_Candidates_list(cl); ab->n_a = 0; - - // minimizer of queried read - if (ab->mz.m > ab->old_mz_m) { - ab->old_mz_m = ab->mz.m; - REALLOC(ab->seed, ab->old_mz_m); - } - - for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { - ab->seed[i].a = ha_pt_get(ha_idx, ab->mz.a[i].x, &n); - ab->seed[i].n = n; - ab->n_a += n; - } - - if (ab->n_a > ab->m_a) { - ab->m_a = ab->n_a; - REALLOC(ab->a, ab->m_a); - } - - for (i = 0, k = 0; i < ab->mz.n; ++i) { - ///z is one of the minimizer - z = &ab->mz.a[i]; s = &ab->seed[i]; - - for (j = 0; j < s->n; ++j) { - const ha_idxpos_t *y = &s->a[j]; - anchor1_t *an = &ab->a[k++]; - uint8_t rev = z->rev == y->rev? 0 : 1; - - an->other_off = y->span; - an->self_off = i; - ///an->cnt: cnt<<8|span - an->cnt = s->n; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; - an->cnt <<= 8; an->cnt |= ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); - an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | y->pos; - } - } - - // copy over to _cl_ - if (ab->m_a >= (uint64_t)cl->size) { - cl->size = ab->m_a; - REALLOC(cl->list, cl->size); - } - clear_overlap_region_alloc(olst); - radix_sort_ha_an1(ab->a, ab->a + ab->n_a); -} - -uint64_t h_ec_lchain_re_gen_qry(ha_abuf_t *ab, uint64_t *k, uint64_t *l, uint64_t *i, uint64_t *idx_a, uint64_t idx_n, uint64_t *tid, uint64_t *trev) -{ - while ((*k) <= ab->n_a) { - if ((*k) == ab->n_a || (ab->a[*k].srt>>32) != (ab->a[*l].srt>>32)) { - for (; ((*i) < idx_n) && ((idx_a[*i]>>32) < (ab->a[*l].srt>>32)); (*i)++); - if(((*i) < idx_n) && ((ab->a[*l].srt>>32) == (idx_a[*i]>>32))) { - (*tid) = ab->a[*l].srt>>33; (*trev) = (ab->a[*l].srt>>32) & 1; - - return 1; - } - (*l) = (*k); - } - ++(*k); - } - return 0; -} - -uint64_t h_ec_lchain_re_chn(ha_abuf_t *ab, uint64_t si, uint64_t ei, uint32_t rid, char* rs, uint64_t rl, uint64_t tid, char* ts, uint64_t tl, uint64_t trev, uint64_t mz_w, uint64_t mz_k, overlap_region_alloc *olst, Candidates_list *cl, double bw_thres, - int apend_be, uint64_t max_cnt, uint64_t min_cnt, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip, tiny_queue_t *tq, asg16_v *scc, int64_t *n, int64_t *zn) -{ - // char dbg[768]; uint64_t rpos, rspan, thash; - - int64_t ok, nk, ck, n0; uint64_t i, m, tspan, on0; k_mer_hit *p; - for (i = si, m = ok = nk = ck = 0; i < ei; i++) { - if(!recalu_minimizer_non_retrieve(rid, &(ab->a[i]), &(scc[tid]), &ok, &nk, &ck, mz_k, ab->mz.a[ab->a[i].self_off].x, tq, ts, tl, trev)) continue; - ///debug - // thash = ab->mz.a[ab->a[i].self_off].x; - - ab->a[m] = ab->a[i]; tspan = ab->a[m].other_off; - ab->a[m].other_off = (uint32_t)ab->a[m].srt; - if(trev) ab->a[m].other_off = tl - (ab->a[m].other_off+1-tspan) - 1;///looks like a bug - ab->a[m].self_off = ab->mz.a[ab->a[m].self_off].pos; - ab->a[m].srt = ab->a[m].self_off; ab->a[m].srt <<= 32; ab->a[m].srt |= ab->a[m].other_off; - - - ///debug - // recover_UC_Read_sub_region(dbg, ab->a[m].other_off + 1 - tspan, tspan, trev, &R_INF, tid); - // if(recalu_minimizer0(dbg, tspan, !(asm_opt.flag & HA_F_NO_HPC), mz_k, thash, tq, &rpos, &rspan) && (rpos + 1 == tspan) && (tspan == rspan)) { - // // fprintf(stderr, "-0-[M::%s]\n", __func__); - // } else { - // fprintf(stderr, "-1-[M::%s]\ttrev::%lu\n", __func__, trev); - // } - ///debug - // hpc_ext_check(&R_INF, tid, ab->a[m].other_off + 1 - tspan, ab->a[m].other_off + 1, tl, trev, dbg); - - m++; - } - - if(m > 1) radix_sort_ha_an1(ab->a, ab->a + m); - - for (i = 0, n0 = (*n); i < m; i++) { - p = &cl->list[(*n)++]; - p->readID = tid; - p->strand = trev; - p->offset = ab->a[i].other_off; - p->self_offset = ab->a[i].self_off; - if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ - p->cnt = 1; - } else if((ab->a[i].cnt>>8) <= min_cnt) { - p->cnt = 2; - } else{ - p->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); - p->cnt = pow(p->cnt, 1.1); - } - if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; - p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); - } - - // if(rid == 3196 && tid == 3199) fprintf(stderr, "[M::%s]\ttid::%lu\ttrev::%lu\told::%lu\tnew::%lu\n", __func__, tid, trev, k - l, m); - // fprintf(stderr, "[M::%s]\ttid::%lu\ttrev::%lu\told::%lu\tnew::%lu\n", __func__, tid, trev, ei - si, m); - - if(m > 0 && tid != rid) { - on0 = olst->length; - *zn += lchain_qdp_mcopy_fast(cl, n0, (*n)-n0, *zn, &(cl->chainDP), olst, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, - rid, rl, tl, quick_check, apend_be, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, 1); - cl->length = *zn; - if(olst->length > on0) return 1; - } - - cl->length = *zn; - return 0; -} - -uint64_t get_mz1(const char *str, int len, int w, int k, uint32_t rid, int is_hpc, ha_abuf_t *ab, const void *hf, ha_pt_t *ha_idx, int sample_dist, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, ha_pt_t *pt, int min_freq, int32_t dp_min_len, float dp_e, st_mt_t *mt, int32_t ws, int32_t is_unique, void *km, uint64_t beg_i) -{ - ab->mz.n = beg_i; - // get the list of anchors - mz1_ha_sketch(str, len, w, k, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, hf, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, mt, asm_opt.mz_rewin, 0, NULL); - - radix_sort_ha_mz1_v_srt(ab->mz.a + beg_i, ab->mz.a + ab->mz.n); - - if(ha_idx) { - uint64_t i; - - if (ab->mz.m > ab->old_mz_m) { - ab->old_mz_m = ab->mz.m; - REALLOC(ab->seed, ab->old_mz_m); - } - - for (i = 0; i < ab->mz.n; ++i) { - ab->seed[i].a = NULL; - ab->seed[i].n = ha_pt_cnt(ha_idx, ab->mz.a[i].x); - } - } - - return ab->mz.n; -} - -void get_pi_ec_chain(ha_abuf_t *ab, uint64_t rid, uint64_t rl, uint32_t tid, char* ts, uint64_t tl, uint64_t mz_w, uint64_t mz_k, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, - int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, /**uint32_t is_accurate,**/ uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, - int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip) -{ - extern void *ha_flt_tab; - extern ha_pt_t *ha_idx; - uint64_t rn = ab->mz.n, tn, cn = 0; - - tn = get_mz1(ts, tl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), ab, ha_flt_tab, NULL, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL, rn); - - cn = lchain_qgen_mcopy_fast_re0(ab, ha_idx, ab->mz.a, rn, ab->mz.a + rn, tn - rn, tid, cl, high_occ, low_occ); - - if(cn) { - lchain_qgen_mcopy_fast_re1(cl, cl->length - cn, overlap_list, rid, rl, tl, apend_be, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut); - } - - ab->mz.n = rn; -} - - -int64_t ug_map_lchain(ha_abufl_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, double bw_thres_sec, - int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, - uint32_t gen_off, double mcopy_rate, uint32_t mcopy_khit_cut, uint32_t is_hpc, ha_mzl_t *res, uint64_t res_n, ha_mzl_t *idx, uint64_t idx_n, uint64_t mzl_cutoff, uint64_t chain_cutoff, kv_u_trans_t *kov) -{ - int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; - set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); - if((!overlap_list) || (!cl)) { - ab->mz.n = 0; - mz2_ha_sketch(rs, rl, mz_w, mz_k, rid, is_hpc, &ab->mz, NULL, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); - if(res) memcpy(res, ab->mz.a, ab->mz.n * (sizeof((*(ab->mz.a))))); - return ab->mz.n; - } else { - sp->n = 0; - minimizers_qgen_input(ab, rid, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, NULL, uref, dbg_ct, sp, high_occ, low_occ, res, res_n, idx, idx_n, mzl_cutoff, chain_cutoff, kov); - lchain_qgen_mcopy_input(cl, overlap_list, rid, rl, NULL, uref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, bw_thres_sec, quick_check, gen_off, mcopy_rate, mcopy_khit_cut, sp); - return 0; - } -} - -int64_t ug_map_lchain_simple(ha_abufl_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, - int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, - uint32_t gen_off, double mcopy_rate, uint32_t mcopy_khit_cut, uint32_t is_hpc, ha_mzl_t *res, uint64_t res_n, ha_mzl_t *idx, uint64_t idx_n, uint64_t mzl_cutoff, uint64_t chain_cutoff) -{ - int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; - set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); - if((!overlap_list) || (!cl)) { - ab->mz.n = 0; - mz2_ha_sketch(rs, rl, mz_w, mz_k, rid, is_hpc, &ab->mz, NULL, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); - if(res) memcpy(res, ab->mz.a, ab->mz.n * (sizeof((*(ab->mz.a))))); - return ab->mz.n; - } else { - sp->n = 0; - minimizers_qgen_input(ab, rid, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, NULL, uref, dbg_ct, sp, high_occ, low_occ, res, res_n, idx, idx_n, mzl_cutoff, chain_cutoff, NULL); - // lchain_qgen_mcopy_input(cl, overlap_list, rid, rl, NULL, uref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, bw_thres_sec, quick_check, gen_off, mcopy_rate, mcopy_khit_cut, sp); - lchain_qgen_mcopy(cl, overlap_list, rid, rl, NULL, uref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off, mcopy_rate, chain_cutoff, mcopy_khit_cut, sp); - return 0; - } +#include +#include +#include +#include "htab.h" +#include "ksort.h" +#include "Hash_Table.h" +#include "kalloc.h" +#include "Overlaps.h" +#include "Levenshtein_distance.h" + +#define HA_KMER_GOOD_RATIO 0.333 +#define OFL 0.95 +#define CH_OCC 4 +#define CH_SC 16 + +typedef struct { // this struct is not strictly necessary; we can use k_mer_pos instead, with modifications + uint64_t srt; + uint32_t self_off; + uint32_t other_off; + uint32_t cnt; +} anchor1_t; + +#define an_key1(a) ((a).srt) +#define an_key2(a) ((a).self_off) +#define an_key3(a) ((a).other_off) +KRADIX_SORT_INIT(ha_an1, anchor1_t, an_key1, 8) +KRADIX_SORT_INIT(ha_an2, anchor1_t, an_key2, 4) +KRADIX_SORT_INIT(ha_an3, anchor1_t, an_key3, 4) +#define generic_key(x) (x) +KRADIX_SORT_INIT(anc64, uint64_t, generic_key, 8) + +#define oreg_xs_lt(a, b) (((uint64_t)(a).x_pos_s<<32|(a).x_pos_e) < ((uint64_t)(b).x_pos_s<<32|(b).x_pos_e)) +KSORT_INIT(or_xs, overlap_region, oreg_xs_lt) + +#define oreg_ss_lt(a, b) ((a).shared_seed > (b).shared_seed) // in the decending order +KSORT_INIT(or_ss, overlap_region, oreg_ss_lt) + +#define oreg_occ_lt(a, b) ((a).align_length > (b).align_length) // in the decending order +KSORT_INIT(or_occ, overlap_region, oreg_occ_lt) + +#define oreg_id_lt(a, b) ((a).y_id < (b).y_id) +KSORT_INIT(or_id, overlap_region, oreg_id_lt) + +#define ha_mz1_t_key(p) ((p).x) +KRADIX_SORT_INIT(ha_mz1_v_srt, ha_mz1_t, ha_mz1_t_key, member_size(ha_mz1_t, x)) + +typedef struct { + int n; + const ha_idxpos_t *a; +} seed1_t; + +typedef struct { + int n, cnt; + const ha_idxposl_t *a; +} seedl_t; + +struct ha_abuf_s { + uint64_t n_a, m_a;///number of anchors (seed positions) + uint32_t old_mz_m;///number of seeds + ha_mz1_v mz; + seed1_t *seed; + anchor1_t *a; +}; + +struct ha_abufl_s { + uint64_t n_a, m_a;///number of anchors (seed positions) + uint32_t old_mz_m;///number of seeds + ha_mzl_v mz; + seedl_t *seed; + anchor1_t *a; +}; + +#define HA_ABUF_INIT(HType, MZType, SDType, sf) \ +HType *sf##_init_buf(void *km){HType *b = NULL; KCALLOC((km), b, 1); return b;}\ +HType *sf##_init(void){return (HType*)calloc(1, sizeof(HType));}\ +void sf##_free_buf(void *km, HType *ab, int is_z){if(ab){kfree(km, ab->seed); kfree(km, ab->a); kfree(km, ab->mz.a); if((is_z)){memset(ab, 0, sizeof(*ab));}}}\ +void sf##_destroy_buf(void *km, HType *ab){if(ab){kfree(km, ab->seed); kfree(km, ab->a); kfree(km, ab->mz.a); kfree(km, ab);}}\ +void sf##_destroy(HType *ab){if(ab){free(ab->seed); free(ab->a); free(ab->mz.a); free(ab);}}\ +uint64_t sf##_mem(const HType *ab){\ + return ab->m_a * sizeof(anchor1_t) + ab->mz.m * (sizeof(MZType) + sizeof(SDType)) + sizeof(HType);\ +} + +HA_ABUF_INIT(ha_abuf_s, ha_mz1_t, seed1_t, ha_abuf) +HA_ABUF_INIT(ha_abufl_s, ha_mzl_t, seedl_t, ha_abufl) + +int ha_ov_type(const overlap_region *r, uint32_t len) +{ + if (r->x_pos_s == 0 && r->x_pos_e == len - 1) return 2; // contained in a longer read + else if (r->x_pos_s > 0 && r->x_pos_e < len - 1) return 3; // containing a shorter read + else return r->x_pos_s == 0? 0 : 1; +} + +void ha_get_new_candidates(ha_abuf_t *ab, int64_t rid, UC_Read *ucr, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, int max_n_chain, int keep_whole_chain, + kvec_t_u8_warp* k_flag, kvec_t_u64_warp* chain_idx, void *ha_flt_tab, ha_pt_t *ha_idx, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp) +{ + uint32_t i, rlen; + uint64_t k, l; + uint32_t low_occ = asm_opt.hom_cov * HA_KMER_GOOD_RATIO; + uint32_t high_occ = asm_opt.hom_cov * (2.0 - HA_KMER_GOOD_RATIO); + if(low_occ < 2) low_occ = 2; + + // prepare + clear_Candidates_list(cl); + clear_overlap_region_alloc(overlap_list); + recover_UC_Read(ucr, &R_INF, rid); + ab->mz.n = 0, ab->n_a = 0; + rlen = Get_READ_LENGTH(R_INF, rid); // read length + + // get the list of anchors + mz1_ha_sketch(ucr->seq, ucr->length, asm_opt.mz_win, asm_opt.k_mer_length, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); + // minimizer of queried read + if (ab->mz.m > ab->old_mz_m) { + ab->old_mz_m = ab->mz.m; + REALLOC(ab->seed, ab->old_mz_m); + } + for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { + int n; + ab->seed[i].a = ha_pt_get(ha_idx, ab->mz.a[i].x, &n); + ab->seed[i].n = n; + ab->n_a += n; + } + if (ab->n_a > ab->m_a) { + ab->m_a = ab->n_a; + kroundup64(ab->m_a); + REALLOC(ab->a, ab->m_a); + } + for (i = 0, k = 0; i < ab->mz.n; ++i) { + int j; + ///z is one of the minimizer + ha_mz1_t *z = &ab->mz.a[i]; + seed1_t *s = &ab->seed[i]; + for (j = 0; j < s->n; ++j) { + const ha_idxpos_t *y = &s->a[j]; + anchor1_t *an = &ab->a[k++]; + uint8_t rev = z->rev == y->rev? 0 : 1; + an->other_off = y->pos; + an->self_off = rev? ucr->length - 1 - (z->pos + 1 - z->span) : z->pos; + an->cnt = s->n; + an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->other_off; + } + } + + // sort anchors + radix_sort_ha_an1(ab->a, ab->a + ab->n_a); + for (k = 1, l = 0; k <= ab->n_a; ++k) { + if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { + if (k - l > 1) + radix_sort_ha_an2(ab->a + l, ab->a + k); + l = k; + } + } + + + // copy over to _cl_ + if (ab->m_a >= (uint64_t)cl->size) { + cl->size = ab->m_a; + REALLOC(cl->list, cl->size); + } + for (k = 0; k < ab->n_a; ++k) { + k_mer_hit *p = &cl->list[k]; + p->readID = ab->a[k].srt >> 33; + p->strand = ab->a[k].srt >> 32 & 1; + p->offset = ab->a[k].other_off; + p->self_offset = ab->a[k].self_off; + if(ab->a[k].cnt > low_occ && ab->a[k].cnt < high_occ){ + p->cnt = 1; + } + else if(ab->a[k].cnt <= low_occ){ + p->cnt = 2; + } + else{ + p->cnt = 1 + ((ab->a[k].cnt + (high_occ<<1) - 1)/(high_occ<<1)); + p->cnt = pow(p->cnt, 1.1); + } + } + cl->length = ab->n_a; + + calculate_overlap_region_by_chaining(cl, overlap_list, chain_idx, rid, ucr->length, &R_INF, NULL, bw_thres, keep_whole_chain, f_cigar, NULL); + + #if 0 + if (overlap_list->length > 0) { + fprintf(stderr, "B\t%ld\t%ld\t%d\n", (long)rid, (long)overlap_list->length, rlen); + for (int i = 0; i < (int)overlap_list->length; ++i) { + overlap_region *r = &overlap_list->list[i]; + fprintf(stderr, "C\t%d\t%d\t%d\t%c\t%d\t%ld\t%d\t%d\t%c\t%d\t%d\n", (int)r->x_id, (int)r->x_pos_s, (int)r->x_pos_e, "+-"[r->x_pos_strand], + (int)r->y_id, (long)Get_READ_LENGTH(R_INF, r->y_id), (int)r->y_pos_s, (int)r->y_pos_e, "+-"[r->y_pos_strand], (int)r->shared_seed, ha_ov_type(r, rlen)); + } + } + #endif + + if ((int)overlap_list->length > max_n_chain) { + int32_t w, n[4], s[4]; + n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; + ks_introsort_or_ss(overlap_list->length, overlap_list->list); + for (i = 0; i < (uint32_t)overlap_list->length; ++i) { + const overlap_region *r = &overlap_list->list[i]; + w = ha_ov_type(r, rlen); + ++n[w]; + if ((int)n[w] == max_n_chain) s[w] = r->shared_seed; + } + if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { + // n[0] = n[1] = n[2] = n[3] = 0; + for (i = 0, k = 0; i < (uint32_t)overlap_list->length; ++i) { + overlap_region *r = &overlap_list->list[i]; + w = ha_ov_type(r, rlen); + // ++n[w]; + // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { + if (r->shared_seed >= s[w]) { + if ((uint32_t)k != i) { + overlap_region t; + t = overlap_list->list[k]; + overlap_list->list[k] = overlap_list->list[i]; + overlap_list->list[i] = t; + } + ++k; + } + } + overlap_list->length = k; + } + } + + ///ks_introsort_or_xs(overlap_list->length, overlap_list->list); +} + +void ha_get_new_ul_candidates(ha_abufl_t *ab, int64_t rid, char* rs, int64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, int max_n_chain, int keep_whole_chain, + kvec_t_u8_warp* k_flag, kvec_t_u64_warp* chain_idx, void *ha_flt_tab, ha_pt_t *ha_idx, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t high_occ, void *km) +{ + uint32_t i; + uint64_t k, l; + if(high_occ < 1) high_occ = 1; + // uint32_t high_occ = asm_opt.hom_cov >= 1?asm_opt.hom_cov:1; + + // prepare + clear_Candidates_list(cl); + clear_overlap_region_alloc(overlap_list); + ab->mz.n = 0, ab->n_a = 0; + + // get the list of anchors + mz2_ha_sketch(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, km); + + // minimizer of queried read + if (ab->mz.m > ab->old_mz_m) { + ab->old_mz_m = ab->mz.m; + KREALLOC(km, ab->seed, ab->old_mz_m); + } + + for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { + int n; + ab->seed[i].a = ha_ptl_get(ha_idx, ab->mz.a[i].x, &n); + ab->seed[i].n = n; + ab->n_a += n; + } + if (ab->n_a > ab->m_a) { + ab->m_a = ab->n_a; + KREALLOC(km, ab->a, ab->m_a); + } + + for (i = 0, k = 0; i < ab->mz.n; ++i) { + int j; + ///z is one of the minimizer + ha_mzl_t *z = &ab->mz.a[i]; + seedl_t *s = &ab->seed[i]; + for (j = 0; j < s->n; ++j) { + const ha_idxposl_t *y = &s->a[j]; + anchor1_t *an = &ab->a[k++]; + uint8_t rev = z->rev == y->rev? 0 : 1; + an->other_off = y->pos; + an->self_off = rev? rl - 1 - (z->pos + 1 - z->span) : z->pos; + an->cnt = s->n; + an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->other_off; + } + } + + // sort anchors + radix_sort_ha_an1(ab->a, ab->a + ab->n_a); + for (k = 1, l = 0; k <= ab->n_a; ++k) { + if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { + if (k - l > 1) + radix_sort_ha_an2(ab->a + l, ab->a + k); + l = k; + } + } + + + // copy over to _cl_ + if (ab->m_a >= (uint64_t)cl->size) { + cl->size = ab->m_a; + KREALLOC(km, cl->list, cl->size); + } + + for (k = 0; k < ab->n_a; ++k) { + k_mer_hit *p = &cl->list[k]; + p->readID = ab->a[k].srt >> 33; + p->strand = ab->a[k].srt >> 32 & 1; + p->offset = ab->a[k].other_off; + p->self_offset = ab->a[k].self_off; + if(ab->a[k].cnt <= high_occ){ + p->cnt = 1; + } + else{ + p->cnt = 1 + ((ab->a[k].cnt + (high_occ<<1) - 1)/(high_occ<<1)); + p->cnt = pow(p->cnt, 1.1); + } + } + cl->length = ab->n_a; + + calculate_overlap_region_by_chaining(cl, overlap_list, chain_idx, rid, rl, NULL, uref, bw_thres, keep_whole_chain, f_cigar, km); + + #if 0 + if (overlap_list->length > 0) { + fprintf(stderr, "B\t%ld\t%ld\t%d\n", (long)rid, (long)overlap_list->length, rlen); + for (int i = 0; i < (int)overlap_list->length; ++i) { + overlap_region *r = &overlap_list->list[i]; + fprintf(stderr, "C\t%d\t%d\t%d\t%c\t%d\t%ld\t%d\t%d\t%c\t%d\t%d\n", (int)r->x_id, (int)r->x_pos_s, (int)r->x_pos_e, "+-"[r->x_pos_strand], + (int)r->y_id, (long)Get_READ_LENGTH(R_INF, r->y_id), (int)r->y_pos_s, (int)r->y_pos_e, "+-"[r->y_pos_strand], (int)r->shared_seed, ha_ov_type(r, rlen)); + } + } + #endif + + if ((int)overlap_list->length > max_n_chain) { + int32_t w, n[4], s[4]; + n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; + ks_introsort_or_ss(overlap_list->length, overlap_list->list); + for (i = 0; i < (uint32_t)overlap_list->length; ++i) { + const overlap_region *r = &overlap_list->list[i]; + w = ha_ov_type(r, rl); + ++n[w]; + if ((int)n[w] == max_n_chain) s[w] = r->shared_seed; + } + if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { + // n[0] = n[1] = n[2] = n[3] = 0; + for (i = 0, k = 0; i < (uint32_t)overlap_list->length; ++i) { + overlap_region *r = &overlap_list->list[i]; + w = ha_ov_type(r, rl); + // ++n[w]; + // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { + if (r->shared_seed >= s[w]) { + if ((uint32_t)k != i) { + overlap_region t; + t = overlap_list->list[k]; + overlap_list->list[k] = overlap_list->list[i]; + overlap_list->list[i] = t; + } + ++k; + } + } + overlap_list->length = k; + } + } + + ///ks_introsort_or_xs(overlap_list->length, overlap_list->list); +} + + +void calculate_ug_chaining(Candidates_list* candidates, overlap_region_alloc* overlap_list, kvec_t_u64_warp* chain_idx, + uint64_t readID, ma_utg_v *ua, double band_width_threshold, int add_beg_end, overlap_region* f_cigar, long long mz_occ, double mz_rate) +{ + long long i = 0; + uint64_t current_ID; + uint64_t current_stand; + + if (candidates->length == 0) + { + return; + } + + long long sub_region_beg; + long long sub_region_end; + long long chain_len; + + clear_fake_cigar(&((*f_cigar).f_cigar)); + + i = 0; + while (i < candidates->length) + { + chain_idx->a.n = 0; + current_ID = candidates->list[i].readID; + current_stand = candidates->list[i].strand; + + ///reference read + (*f_cigar).x_id = readID; + (*f_cigar).x_pos_strand = current_stand; + ///query read + (*f_cigar).y_id = current_ID; + ///here the strand of query is always 0 + (*f_cigar).y_pos_strand = 0; + + sub_region_beg = i; + sub_region_end = i; + i++; + + while (i < candidates->length + && + current_ID == candidates->list[i].readID + && + current_stand == candidates->list[i].strand) + { + sub_region_end = i; + i++; + } + + if ((*f_cigar).x_id == (*f_cigar).y_id) + { + continue; + } + + chain_len = chain_DP(candidates->list + sub_region_beg, + sub_region_end - sub_region_beg + 1, &(candidates->chainDP), f_cigar, band_width_threshold, + 50, ua->a[(*f_cigar).x_id].len, ua->a[(*f_cigar).y_id].len, NULL); + + + // if ((*f_cigar).x_id != (*f_cigar).y_id) + if ((*f_cigar).x_id != (*f_cigar).y_id && chain_len > mz_occ*mz_rate) + { + append_utg_inexact_overlap_region_alloc(overlap_list, f_cigar, ua, add_beg_end, NULL); + } + } +} + + +void ha_get_inter_candidates(ha_abufl_t *ab, uint64_t id, char* r, uint64_t rlen, uint64_t rw, uint64_t rk, uint64_t is_hpc, + overlap_region_alloc *ol, Candidates_list *cl, double bw_thres, int max_n_chain, int keep_whole_chain, + kvec_t_u8_warp* k_flag, kvec_t_u64_warp* chain_idx, void *ha_flt_tab, ha_pt_t *ha_idx, + overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp) +{ + uint64_t i, k, l; + // prepare + clear_Candidates_list(cl); + clear_overlap_region_alloc(ol); + ab->mz.n = 0, ab->n_a = 0; + + // get the list of anchors + mz2_ha_sketch(r, rlen, rw, rk, 0, is_hpc, &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, + NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 1, NULL); + + // minimizer of queried read + if (ab->mz.m > ab->old_mz_m) { + ab->old_mz_m = ab->mz.m; + REALLOC(ab->seed, ab->old_mz_m); + } + for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { + int n; + ab->seed[i].a = ha_ptl_get(ha_idx, ab->mz.a[i].x, &n); + ab->seed[i].n = n; + ab->seed[i].cnt = ha_ft_cnt(ha_flt_tab, ab->mz.a[i].x); + ab->n_a += n; + } + if (ab->n_a > ab->m_a) { + ab->m_a = ab->n_a; + kroundup64(ab->m_a); + REALLOC(ab->a, ab->m_a); + } + for (i = 0, k = 0; i < ab->mz.n; ++i) { + int j; + ///z is one of the minimizer + ha_mzl_t *z = &ab->mz.a[i]; + seedl_t *s = &ab->seed[i]; + for (j = 0; j < s->n; ++j) { + const ha_idxposl_t *y = &s->a[j]; + anchor1_t *an = &ab->a[k++]; + uint8_t rev = z->rev == y->rev? 0 : 1; + an->other_off = y->pos; + an->self_off = rev? rlen - 1 - (z->pos + 1 - z->span) : z->pos; + an->cnt = s->n; + an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->other_off; + } + } + + // sort anchors + radix_sort_ha_an1(ab->a, ab->a + ab->n_a); + for (k = 1, l = 0; k <= ab->n_a; ++k) { + if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { + if (k - l > 1) + radix_sort_ha_an2(ab->a + l, ab->a + k); + l = k; + } + } + + + // copy over to _cl_ + if (ab->m_a >= (uint64_t)cl->size) { + cl->size = ab->m_a; + REALLOC(cl->list, cl->size); + } + for (k = 0; k < ab->n_a; ++k) { + k_mer_hit *p = &cl->list[k]; + p->readID = ab->a[k].srt >> 33; + p->strand = ab->a[k].srt >> 32 & 1; + p->offset = ab->a[k].other_off; + p->self_offset = ab->a[k].self_off; + p->cnt = (ab->a[k].cnt == 1? 1 : 16); + } + cl->length = ab->n_a; + + calculate_overlap_region_by_chaining(cl, ol, chain_idx, id, rlen, /**&R_INF**/NULL, NULL, bw_thres, keep_whole_chain, f_cigar, NULL); + + #if 0 + if (ol->length > 0) { + fprintf(stderr, "B\t%ld\t%ld\t%d\n", (long)rid, (long)ol->length, rlen); + for (int i = 0; i < (int)ol->length; ++i) { + overlap_region *r = &ol->list[i]; + fprintf(stderr, "C\t%d\t%d\t%d\t%c\t%d\t%ld\t%d\t%d\t%c\t%d\t%d\n", (int)r->x_id, (int)r->x_pos_s, (int)r->x_pos_e, "+-"[r->x_pos_strand], + (int)r->y_id, (long)Get_READ_LENGTH(R_INF, r->y_id), (int)r->y_pos_s, (int)r->y_pos_e, "+-"[r->y_pos_strand], (int)r->shared_seed, ha_ov_type(r, rlen)); + } + } + #endif + + if ((int)ol->length > max_n_chain) { + int32_t w, n[4], s[4]; + n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; + ks_introsort_or_ss(ol->length, ol->list); + for (i = 0; i < (uint32_t)ol->length; ++i) { + const overlap_region *r = &ol->list[i]; + w = ha_ov_type(r, rlen); + ++n[w]; + if ((int)n[w] == max_n_chain) s[w] = r->shared_seed; + } + if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { + // n[0] = n[1] = n[2] = n[3] = 0; + for (i = 0, k = 0; i < (uint32_t)ol->length; ++i) { + overlap_region *r = &ol->list[i]; + w = ha_ov_type(r, rlen); + // ++n[w]; + // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { + if (r->shared_seed >= s[w]) { + if ((uint32_t)k != i) { + overlap_region t; + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + ++k; + } + } + ol->length = k; + } + } + + ///ks_introsort_or_xs(overlap_list->length, overlap_list->list); +} + +void ha_get_ug_candidates(ha_abuf_t *ab, int64_t rid, ma_utg_t *u, ma_utg_v *ua, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, int max_n_chain, int keep_whole_chain, kvec_t_u8_warp* k_flag, +kvec_t_u64_warp* chain_idx, void *ha_flt_tab, ha_pt_t *ha_idx, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, double chain_match_rate) +{ + uint32_t i; + uint64_t k, l; + + // prepare + clear_Candidates_list(cl); + clear_overlap_region_alloc(overlap_list); + ab->mz.n = 0, ab->n_a = 0; + + // get the list of anchors + //should use the new version... + ///ha_sketch_query(u->s, u->len, asm_opt.mz_win, asm_opt.k_mer_length, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, k_flag, dbg_ct); + // minimizer of queried read + if (ab->mz.m > ab->old_mz_m) { + ab->old_mz_m = ab->mz.m; + REALLOC(ab->seed, ab->old_mz_m); + } + for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { + int n; + ab->seed[i].a = ha_pt_get(ha_idx, ab->mz.a[i].x, &n); + ab->seed[i].n = n; + ab->n_a += n; + } + if (ab->n_a > ab->m_a) { + ab->m_a = ab->n_a; + kroundup64(ab->m_a); + REALLOC(ab->a, ab->m_a); + } + for (i = 0, k = 0; i < ab->mz.n; ++i) { + int j; + ///z is one of the minimizer + ha_mz1_t *z = &ab->mz.a[i]; + seed1_t *s = &ab->seed[i]; + for (j = 0; j < s->n; ++j) { + const ha_idxpos_t *y = &s->a[j]; + anchor1_t *an = &ab->a[k++]; + uint8_t rev = z->rev == y->rev? 0 : 1; + an->other_off = y->pos; + an->self_off = rev? u->len - 1 - (z->pos + 1 - z->span) : z->pos; + an->cnt = 1; + an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->other_off; + } + } + + // sort anchors + radix_sort_ha_an1(ab->a, ab->a + ab->n_a); + for (k = 1, l = 0; k <= ab->n_a; ++k) { + if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { + if (k - l > 1) + radix_sort_ha_an2(ab->a + l, ab->a + k); + l = k; + } + } + + + // copy over to _cl_ + if (ab->m_a >= (uint64_t)cl->size) { + cl->size = ab->m_a; + REALLOC(cl->list, cl->size); + } + for (k = 0; k < ab->n_a; ++k) { + k_mer_hit *p = &cl->list[k]; + p->readID = ab->a[k].srt >> 33; + p->strand = ab->a[k].srt >> 32 & 1; + p->offset = ab->a[k].other_off; + p->self_offset = ab->a[k].self_off; + p->cnt = 1; + } + cl->length = ab->n_a; + + calculate_ug_chaining(cl, overlap_list, chain_idx, rid, ua, bw_thres, keep_whole_chain, f_cigar, ab->mz.n, chain_match_rate); + + #if 0 + if (overlap_list->length > 0) { + fprintf(stderr, "B\t%ld\t%ld\t%d\n", (long)rid, (long)overlap_list->length, rlen); + for (int i = 0; i < (int)overlap_list->length; ++i) { + overlap_region *r = &overlap_list->list[i]; + fprintf(stderr, "C\t%d\t%d\t%d\t%c\t%d\t%ld\t%d\t%d\t%c\t%d\t%d\n", (int)r->x_id, (int)r->x_pos_s, (int)r->x_pos_e, "+-"[r->x_pos_strand], + (int)r->y_id, (long)Get_READ_LENGTH(R_INF, r->y_id), (int)r->y_pos_s, (int)r->y_pos_e, "+-"[r->y_pos_strand], (int)r->shared_seed, ha_ov_type(r, rlen)); + } + } + #endif + + if ((int)overlap_list->length > max_n_chain) { + int32_t w, n[4], s[4]; + n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; + ks_introsort_or_ss(overlap_list->length, overlap_list->list); + for (i = 0; i < (uint32_t)overlap_list->length; ++i) { + const overlap_region *r = &overlap_list->list[i]; + w = ha_ov_type(r, u->len); + ++n[w]; + if ((int)n[w] == max_n_chain) s[w] = r->shared_seed; + } + if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { + for (i = 0, k = 0; i < (uint32_t)overlap_list->length; ++i) { + overlap_region *r = &overlap_list->list[i]; + w = ha_ov_type(r, u->len); + if (r->shared_seed >= s[w]) { + if ((uint32_t)k != i) { + overlap_region t; + t = overlap_list->list[k]; + overlap_list->list[k] = overlap_list->list[i]; + overlap_list->list[i] = t; + } + ++k; + } + } + overlap_list->length = k; + } + } + + ///ks_introsort_or_xs(overlap_list->length, overlap_list->list); +} + + +void lable_matched_ovlp(overlap_region_alloc* overlap_list, ma_hit_t_alloc* paf) +{ + uint64_t j = 0, inner_j = 0; + while (j < overlap_list->length && inner_j < paf->length) + { + if(overlap_list->list[j].y_id < paf->buffer[inner_j].tn) + { + j++; + } + else if(overlap_list->list[j].y_id > paf->buffer[inner_j].tn) + { + inner_j++; + } + else + { + if(overlap_list->list[j].y_pos_strand == paf->buffer[inner_j].rev) + { + overlap_list->list[j].is_match = 1; + } + j++; + inner_j++; + } + } +} + + +void ha_get_candidates_interface(ha_abuf_t *ab, int64_t rid, UC_Read *ucr, overlap_region_alloc *overlap_list, overlap_region_alloc *overlap_list_hp, Candidates_list *cl, double bw_thres, + int max_n_chain, int keep_whole_chain, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* chain_idx, ma_hit_t_alloc* paf, ma_hit_t_alloc* rev_paf, overlap_region* f_cigar, + kvec_t_u64_warp* dbg_ct, st_mt_t *sp) +{ + extern void *ha_flt_tab; + extern ha_pt_t *ha_idx; + extern void *ha_flt_tab_hp; + extern ha_pt_t *ha_idx_hp; + + ha_get_new_candidates(ab, rid, ucr, overlap_list, cl, bw_thres, max_n_chain, keep_whole_chain, k_flag, chain_idx, ha_flt_tab, ha_idx, f_cigar, dbg_ct, sp); + + if(ha_idx_hp) + { + uint32_t i, k, y_id, overlapLen, max_i; + int shared_seed; + overlap_region t; + overlap_region_sort_y_id(overlap_list->list, overlap_list->length); + ma_hit_sort_tn(paf->buffer, paf->length); + ma_hit_sort_tn(rev_paf->buffer, rev_paf->length); + lable_matched_ovlp(overlap_list, paf); + lable_matched_ovlp(overlap_list, rev_paf); + + for (i = 0, k = 0; i < overlap_list->length; ++i) + { + if(overlap_list->list[i].is_match == 1) + { + if(k != i) + { + t = overlap_list->list[k]; + overlap_list->list[k] = overlap_list->list[i]; + overlap_list->list[i] = t; + overlap_list->list[k].is_match = 0; + } + k++; + } + } + overlap_list->length = k; + + + ha_get_new_candidates(ab, rid, ucr, overlap_list_hp, cl, bw_thres, max_n_chain, keep_whole_chain, k_flag, chain_idx, ha_flt_tab_hp, ha_idx_hp, f_cigar, dbg_ct, sp); + + if(overlap_list->length + overlap_list_hp->length > overlap_list->size) + { + overlap_list->list = (overlap_region*)realloc(overlap_list->list, + sizeof(overlap_region)*(overlap_list->length + overlap_list_hp->length)); + memset(overlap_list->list + overlap_list->size, 0, sizeof(overlap_region)* + (overlap_list->length + overlap_list_hp->length - overlap_list->size)); + overlap_list->size = overlap_list->length + overlap_list_hp->length; + } + + for (i = 0, k = overlap_list->length; i < overlap_list_hp->length; i++, k++) + { + t = overlap_list->list[k]; + overlap_list->list[k] = overlap_list_hp->list[i]; + overlap_list_hp->list[i] = t; + } + overlap_list->length = k; + + overlap_region_sort_y_id(overlap_list->list, overlap_list->length); + + i = k = 0; + while (i < overlap_list->length) + { + y_id = overlap_list->list[i].y_id; + shared_seed = overlap_list->list[i].shared_seed; + overlapLen = overlap_list->list[i].overlapLen; + max_i = i; + i++; + while (i < overlap_list->length && overlap_list->list[i].y_id == y_id) + { + if((overlap_list->list[i].shared_seed > shared_seed) || + ((overlap_list->list[i].shared_seed == shared_seed) && (overlap_list->list[i].overlapLen <= overlapLen))) + { + y_id = overlap_list->list[i].y_id; + shared_seed = overlap_list->list[i].shared_seed; + overlapLen = overlap_list->list[i].overlapLen; + max_i = i; + } + i++; + } + + if(k != max_i) + { + t = overlap_list->list[k]; + overlap_list->list[k] = overlap_list->list[max_i]; + overlap_list->list[max_i] = t; + } + k++; + } + + overlap_list->length = k; + } + + ks_introsort_or_xs(overlap_list->length, overlap_list->list); +} + + +void ha_get_ul_candidates_interface(ha_abufl_t *ab, int64_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, overlap_region_alloc *overlap_list_hp, Candidates_list *cl, double bw_thres, + int max_n_chain, int keep_whole_chain, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* chain_idx, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t high_occ, void *km) +{ + extern void *ha_flt_tab; + extern ha_pt_t *ha_idx; + + ha_get_new_ul_candidates(ab, rid, rs, rl, mz_w, mz_k, uref, overlap_list, cl, bw_thres, max_n_chain, keep_whole_chain, k_flag, chain_idx, ha_flt_tab, ha_idx, f_cigar, dbg_ct, sp, high_occ, km); + if(km) { + ha_abufl_free_buf(km, ab, 1); + destory_Candidates_list_buf(km, cl, 1); + } + ks_introsort_or_xs(overlap_list->length, overlap_list->list); +} + + + +void ha_sort_list_by_anchor(overlap_region_alloc *overlap_list) +{ + ks_introsort_or_xs(overlap_list->length, overlap_list->list); +} + + +void minimizers_gen(ha_abufl_t *ab, char* rs, int64_t rl, uint64_t mz_w, uint64_t mz_k, Candidates_list *cl, kvec_t_u8_warp* k_flag, +void *ha_flt_tab, ha_pt_t *ha_idx, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ) +{ + // fprintf(stderr, "+[M::%s]\n", __func__); + uint64_t i, k, l, max_cnt = UINT32_MAX, min_cnt = 0; int n, j; ha_mzl_t *z; seedl_t *s; + if(high_occ) { + max_cnt = (*high_occ); + if(max_cnt < 2) max_cnt = 2; + } + if(low_occ) { + min_cnt = (*low_occ); + if(min_cnt < 2) min_cnt = 2; + } + clear_Candidates_list(cl); ab->mz.n = 0, ab->n_a = 0; + + // get the list of anchors + mz2_ha_sketch(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); + + // minimizer of queried read + if (ab->mz.m > ab->old_mz_m) { + ab->old_mz_m = ab->mz.m; + REALLOC(ab->seed, ab->old_mz_m); + } + + for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { + ab->seed[i].a = ha_ptl_get(ha_idx, ab->mz.a[i].x, &n); + ab->seed[i].n = n; + ab->n_a += n; + } + + if (ab->n_a > ab->m_a) { + ab->m_a = ab->n_a; + REALLOC(ab->a, ab->m_a); + } + + for (i = 0, k = 0; i < ab->mz.n; ++i) { + ///z is one of the minimizer + z = &ab->mz.a[i]; s = &ab->seed[i]; + for (j = 0; j < s->n; ++j) { + const ha_idxposl_t *y = &s->a[j]; + anchor1_t *an = &ab->a[k++]; + uint8_t rev = z->rev == y->rev? 0 : 1; + an->other_off = y->pos; + an->self_off = rev? rl - 1 - (z->pos + 1 - z->span) : z->pos; + ///an->cnt: cnt<<8|span + an->cnt = s->n; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; + an->cnt <<= 8; an->cnt |= ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); + an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->other_off; + } + } + + radix_sort_ha_an1(ab->a, ab->a + ab->n_a); + for (k = 1, l = 0; k <= ab->n_a; ++k) { + if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { + if (k - l > 1) + radix_sort_ha_an2(ab->a + l, ab->a + k); + l = k; + } + } + + // copy over to _cl_ + if (ab->m_a >= (uint64_t)cl->size) { + cl->size = ab->m_a; + REALLOC(cl->list, cl->size); + } + + for (k = 0; k < ab->n_a; ++k) { + k_mer_hit *p = &cl->list[k]; + p->readID = ab->a[k].srt >> 33; + p->strand = ab->a[k].srt >> 32 & 1; + p->offset = ab->a[k].other_off; + p->self_offset = ab->a[k].self_off; + if(((ab->a[k].cnt>>8) < max_cnt) && ((ab->a[k].cnt>>8) > min_cnt)){ + p->cnt = 1; + } else if((ab->a[k].cnt>>8) <= min_cnt) { + p->cnt = 2; + } else{ + p->cnt = 1 + (((ab->a[k].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); + p->cnt = pow(p->cnt, 1.1); + } + if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; + p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[k].cnt)); + } + cl->length = ab->n_a; +} + + +void minimizers_qgen(ha_abufl_t *ab, char* rs, int64_t rl, uint64_t mz_w, uint64_t mz_k, Candidates_list *cl, kvec_t_u8_warp* k_flag, +void *ha_flt_tab, ha_pt_t *ha_idx, All_reads* rdb, const ul_idx_t *udb, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, +uint32_t *low_occ) +{ + // fprintf(stderr, "+[M::%s]\n", __func__); + uint64_t i, k, l, max_cnt = UINT32_MAX, min_cnt = 0; int n, j; ha_mzl_t *z; seedl_t *s; + if(high_occ) { + max_cnt = (*high_occ); + if(max_cnt < 2) max_cnt = 2; + } + if(low_occ) { + min_cnt = (*low_occ); + if(min_cnt < 2) min_cnt = 2; + } + clear_Candidates_list(cl); ab->mz.n = 0, ab->n_a = 0; + + // get the list of anchors + mz2_ha_sketch(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); + + // minimizer of queried read + if (ab->mz.m > ab->old_mz_m) { + ab->old_mz_m = ab->mz.m; + REALLOC(ab->seed, ab->old_mz_m); + } + + for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { + ab->seed[i].a = ha_ptl_get(ha_idx, ab->mz.a[i].x, &n); + ab->seed[i].n = n; + ab->n_a += n; + } + + if (ab->n_a > ab->m_a) { + ab->m_a = ab->n_a; + REALLOC(ab->a, ab->m_a); + } + + for (i = 0, k = 0; i < ab->mz.n; ++i) { + ///z is one of the minimizer + z = &ab->mz.a[i]; s = &ab->seed[i]; + for (j = 0; j < s->n; ++j) { + const ha_idxposl_t *y = &s->a[j]; + anchor1_t *an = &ab->a[k++]; + uint8_t rev = z->rev == y->rev? 0 : 1; + an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; + an->self_off = z->pos; + ///an->cnt: cnt<<8|span + an->cnt = s->n; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; + an->cnt <<= 8; an->cnt |= ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); + an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; + } + } + + // copy over to _cl_ + if (ab->m_a >= (uint64_t)cl->size) { + cl->size = ab->m_a; + REALLOC(cl->list, cl->size); + } + + k_mer_hit *p; uint64_t tid = (uint64_t)-1, tl = (uint64_t)-1; + radix_sort_ha_an1(ab->a, ab->a + ab->n_a); + for (k = 1, l = 0; k <= ab->n_a; ++k) { + if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { + if (k-l>1) radix_sort_ha_an3(ab->a+l, ab->a+k); + if((ab->a[l].srt>>33)!=tid) { + tid = ab->a[l].srt>>33; + tl = rdb?Get_READ_LENGTH((*rdb), tid):udb->ug->u.a[tid].len; + } + for (i = l; i < k; i++) { + p = &cl->list[i]; + p->readID = ab->a[i].srt>>33; + p->strand = (ab->a[i].srt>>32)&1; + if(!(p->strand)) { + p->offset = ab->a[i].other_off; + } else { + p->offset = ((uint32_t)-1)-ab->a[i].other_off; + p->offset = tl-p->offset; + } + p->self_offset = ab->a[i].self_off; + if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ + p->cnt = 1; + } else if((ab->a[i].cnt>>8) <= min_cnt) { + p->cnt = 2; + } else{ + p->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); + p->cnt = pow(p->cnt, 1.1); + } + if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; + p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); + } + l = k; + } + } + cl->length = ab->n_a; +} + + +uint64_t minimizers_qgen0(ha_abuf_t *ab, char* rs, int64_t rl, uint64_t mz_w, uint64_t mz_k, Candidates_list *cl, kvec_t_u8_warp* k_flag, +void *ha_flt_tab, ha_pt_t *ha_idx, All_reads* rdb, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint64_t ti_cut) +{ + // fprintf(stderr, "+[M::%s]\n", __func__); + uint64_t i, k, l, max_cnt = UINT32_MAX, min_cnt = 0; int n, j; ha_mz1_t *z; seed1_t *s; + if(high_occ) { + max_cnt = (*high_occ); + if(max_cnt < 2) max_cnt = 2; + } + if(low_occ) { + min_cnt = (*low_occ); + if(min_cnt < 2) min_cnt = 2; + } + clear_Candidates_list(cl); ab->mz.n = 0, ab->n_a = 0; + + // get the list of anchors + mz1_ha_sketch(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); + + // minimizer of queried read + if (ab->mz.m > ab->old_mz_m) { + ab->old_mz_m = ab->mz.m; + REALLOC(ab->seed, ab->old_mz_m); + } + + for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { + + ab->seed[i].a = ha_pt_get(ha_idx, ab->mz.a[i].x, &n); + ab->seed[i].n = n; + ab->n_a += n; + } + + if (ab->n_a > ab->m_a) { + ab->m_a = ab->n_a; + REALLOC(ab->a, ab->m_a); + } + + for (i = 0, k = 0; i < ab->mz.n; ++i) { + ///z is one of the minimizer + z = &ab->mz.a[i]; s = &ab->seed[i]; + for (j = 0; j < s->n; ++j) { + const ha_idxpos_t *y = &s->a[j]; + anchor1_t *an = &ab->a[k++]; + uint8_t rev = z->rev == y->rev? 0 : 1; + an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; + an->self_off = z->pos; + ///an->cnt: cnt<<8|span + an->cnt = s->n; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; + an->cnt <<= 8; an->cnt |= ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); + an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; + } + } + + // copy over to _cl_ + if (ab->m_a >= (uint64_t)cl->size) { + cl->size = ab->m_a; + REALLOC(cl->list, cl->size); + } + + k_mer_hit *p; uint64_t tid = (uint64_t)-1, tl = (uint64_t)-1, tcut_n = 0; + radix_sort_ha_an1(ab->a, ab->a + ab->n_a); + for (k = 1, l = 0; k <= ab->n_a; ++k) { + if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { + if (k-l>1) radix_sort_ha_an3(ab->a+l, ab->a+k); + if((ab->a[l].srt>>33)!=tid) { + tid = ab->a[l].srt>>33; + tl = Get_READ_LENGTH((*rdb), tid); + // tl = rdb?Get_READ_LENGTH((*rdb), tid):udb->ug->u.a[tid].len; + } + if(tid < ti_cut) tcut_n = k; + for (i = l; i < k; i++) { + p = &cl->list[i]; + p->readID = ab->a[i].srt>>33; + p->strand = (ab->a[i].srt>>32)&1; + if(!(p->strand)) { + p->offset = ab->a[i].other_off; + } else { + p->offset = ((uint32_t)-1)-ab->a[i].other_off; + p->offset = tl-p->offset; + } + p->self_offset = ab->a[i].self_off; + if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ + p->cnt = 1; + } else if((ab->a[i].cnt>>8) <= min_cnt) { + p->cnt = 2; + } else{ + p->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); + p->cnt = pow(p->cnt, 1.1); + } + if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; + p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); + } + l = k; + } + } + cl->length = ab->n_a; + return tcut_n; +} + +void minimizers_qgen0_amz(ha_abuf_t *ab, char* rs, int64_t rl, uint64_t mz_w, uint64_t mz_k, Candidates_list *cl, kvec_t_u8_warp* k_flag, +void *ha_flt_tab, ha_pt_t *ha_idx, All_reads* rdb, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ) +{ + // fprintf(stderr, "+[M::%s]\n", __func__); + uint64_t i, k, l, max_cnt = UINT32_MAX, min_cnt = 0; int n, j; ha_mz1_t *z; seed1_t *s; + if(high_occ) { + max_cnt = (*high_occ); + if(max_cnt < 2) max_cnt = 2; + } + if(low_occ) { + min_cnt = (*low_occ); + if(min_cnt < 2) min_cnt = 2; + } + clear_Candidates_list(cl); ab->mz.n = 0, ab->n_a = 0; + + // get the list of anchors + mz1_ha_sketch(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); + + // minimizer of queried read + if (ab->mz.m > ab->old_mz_m) { + ab->old_mz_m = ab->mz.m; + REALLOC(ab->seed, ab->old_mz_m); + } + + for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { + + ab->seed[i].a = ha_pt_get(ha_idx, ab->mz.a[i].x, &n); + ab->seed[i].n = n; + ab->n_a += n; + } + + if (ab->n_a > ab->m_a) { + ab->m_a = ab->n_a; + REALLOC(ab->a, ab->m_a); + } + + for (i = 0, k = 0; i < ab->mz.n; ++i) { + ///z is one of the minimizer + z = &ab->mz.a[i]; s = &ab->seed[i]; + for (j = 0; j < s->n; ++j) { + const ha_idxpos_t *y = &s->a[j]; + anchor1_t *an = &ab->a[k++]; + uint8_t rev = z->rev == y->rev? 0 : 1; + an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; + an->self_off = z->pos; + ///an->cnt: cnt<<8|span + an->cnt = s->n; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; + an->cnt <<= 8; an->cnt |= ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); + an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; + } + } + + // copy over to _cl_ + if (ab->m_a >= (uint64_t)cl->size) { + cl->size = ab->m_a; + REALLOC(cl->list, cl->size); + } + + k_mer_hit *p; uint64_t tid = (uint64_t)-1, tl = (uint64_t)-1; + radix_sort_ha_an1(ab->a, ab->a + ab->n_a); + for (k = 1, l = 0; k <= ab->n_a; ++k) { + if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { + if (k-l>1) radix_sort_ha_an3(ab->a+l, ab->a+k); + if((ab->a[l].srt>>33)!=tid) { + tid = ab->a[l].srt>>33; + tl = Get_READ_LENGTH((*rdb), tid); + // tl = rdb?Get_READ_LENGTH((*rdb), tid):udb->ug->u.a[tid].len; + } + for (i = l; i < k; i++) { + p = &cl->list[i]; + p->readID = ab->a[i].srt>>33; + p->strand = (ab->a[i].srt>>32)&1; + if(!(p->strand)) { + p->offset = ab->a[i].other_off; + } else { + p->offset = ((uint32_t)-1)-ab->a[i].other_off; + p->offset = tl-p->offset; + } + p->self_offset = ab->a[i].self_off; + if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ + p->cnt = 1; + } else if((ab->a[i].cnt>>8) <= min_cnt) { + p->cnt = 2; + } else{ + p->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); + p->cnt = pow(p->cnt, 1.1); + } + if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; + p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); + } + l = k; + } + } + cl->length = ab->n_a; +} + + +uint64_t lchain_qgen_mcopy_fast_re0(ha_abuf_t *ab, ha_pt_t *ha_idx, ha_mz1_t *ra, uint64_t rn, ha_mz1_t *qa, uint64_t qn, uint64_t qid, Candidates_list *cl, uint32_t *high_occ, uint32_t *low_occ) +{ + // fprintf(stderr, "+[M::%s]\n", __func__); + uint64_t i, k, l, max_cnt = UINT32_MAX, min_cnt = 0, ri, qi, sn; anchor1_t *an; k_mer_hit *p; + if(high_occ) { + max_cnt = (*high_occ); + if(max_cnt < 2) max_cnt = 2; + } + if(low_occ) { + min_cnt = (*low_occ); + if(min_cnt < 2) min_cnt = 2; + } + // clear_Candidates_list(cl); + + ///first try + for (k = 1, l = i = ab->n_a = 0; k <= rn; ++k) { + if (k == rn || ra[k].x != ra[l].x) { + for (; i < qn && qa[i].x < ra[l].x; i++); + if(i < qn && qa[i].x == ra[l].x) { + sn = 0; + if(ab->n_a < ab->m_a) sn = ab->seed[l].n;///ha_pt_cnt(ha_idx, ra[l].x); + + for (qi = i; qi < qn && qa[qi].x == ra[l].x; qi++) { + for (ri = l; ri < k; ri++) { + if(qa[qi].rev != ra[ri].rev) continue; + if(ab->n_a < ab->m_a) { + an = &(ab->a[ab->n_a++]); + + an->other_off = qa[qi].pos; + an->self_off = ra[ri].pos; + ///an->cnt: cnt<<8|span + an->cnt = sn; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; + an->cnt <<= 8; an->cnt |= ((ra[ri].span <= ((uint32_t)(0xffu)))?ra[ri].span:((uint32_t)(0xffu))); + an->srt = (((uint64_t)(an->self_off))<<32)|((uint64_t)(an->other_off)); + } else { + ab->n_a++; + } + } + } + } + l = k; + } + } + + + if (ab->n_a > ab->m_a) { + ab->m_a = ab->n_a; REALLOC(ab->a, ab->m_a); + + for (k = 1, l = i = ab->n_a = 0; k <= rn; ++k) { + if (k == rn || ra[k].x != ra[l].x) { + for (; i < qn && qa[i].x < ra[l].x; i++); + if(i < qn && qa[i].x == ra[l].x) { + sn = ab->seed[l].n;///ha_pt_cnt(ha_idx, ra[l].x); + + for (qi = i; qi < qn && qa[qi].x == ra[l].x; qi++) { + for (ri = l; ri < k; ri++) { + if(qa[qi].rev != ra[ri].rev) continue; + + an = &(ab->a[ab->n_a++]); + + an->other_off = qa[qi].pos; + an->self_off = ra[ri].pos; + ///an->cnt: cnt<<8|span + an->cnt = sn; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; + an->cnt <<= 8; an->cnt |= ((ra[ri].span <= ((uint32_t)(0xffu)))?ra[ri].span:((uint32_t)(0xffu))); + an->srt = (((uint64_t)(an->self_off))<<32)|((uint64_t)(an->other_off)); + } + } + } + l = k; + } + } + } + + // copy over to _cl_ + sn = ab->n_a + cl->length; + if (sn > (uint64_t)cl->size) { + cl->size = sn; + REALLOC(cl->list, cl->size); + } + + radix_sort_ha_an1(ab->a, ab->a + ab->n_a); + for (i = 0; i < ab->n_a; i++) { + p = &cl->list[cl->length++]; + p->readID = qid; + p->strand = 0; + p->offset = ab->a[i].other_off; + p->self_offset = ab->a[i].self_off; + + if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ + p->cnt = 1; + } else if((ab->a[i].cnt>>8) <= min_cnt) { + p->cnt = 2; + } else{ + p->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); + p->cnt = pow(p->cnt, 1.1); + } + if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; + p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); + } + // cl->length = ab->n_a; + return ab->n_a; +} + +void gen_pair_chain(ha_abufl_t *ab, uint64_t rid, st_mt_t *tid, uint64_t tid_n, ha_mzl_t *in, uint64_t in_n, ha_mzl_t *idx, int64_t idx_n, uint64_t mzl_cutoff) +{ + if(!tid_n) return; + uint64_t i, l, k, n, m, rev, x, tn, kn; ha_mzl_t *z, *p, *y; int64_t zi, ns, ne; anchor1_t *an; + for (i = tn = 0; i < in_n; ++i) { + ///z is one of the minimizer + z = &in[i]; p = &(idx[z->x]); n = 0; + assert(z->pos == p->pos && z->rid == p->rid && z->span == p->span && z->rev == p->rev); + for (zi = z->x+1; zi < idx_n && idx[zi].x == p->x && n < mzl_cutoff; zi++) { + if(idx[zi].rid == rid) continue; + x = idx[zi].rid; x <<= 1; x |= ((uint64_t)((z->rev == idx[zi].rev)?0:1)); + for (m = 0; m < tid_n; m++) { + if(tid->a[m] == x) { + n++; break; + } + } + } + for (zi = ((int64_t)z->x)-1; zi >= 0 && idx[zi].x == p->x && n < mzl_cutoff; zi--) { + if(idx[zi].rid == rid) continue; + x = idx[zi].rid; x <<= 1; x |= ((uint64_t)((z->rev == idx[zi].rev)?0:1)); + for (m = 0; m < tid_n; m++) { + if(tid->a[m] == x) { + n++; break; + } + } + } + if((!n) || (n >= mzl_cutoff)) continue; + tn += n; + } + if(!tn) return; + ab->n_a += tn; + if (ab->n_a > ab->m_a) { + ab->m_a = ab->n_a; + REALLOC(ab->a, ab->m_a); + } + + + for (i = 0, k = ab->n_a - tn; i < in_n; ++i) { + ///z is one of the minimizer + z = &in[i]; p = &(idx[z->x]); n = 0; ns = 0; ne = -1; + for (zi = z->x+1; zi < idx_n && idx[zi].x == p->x && n < mzl_cutoff; zi++) { + if(idx[zi].rid == rid) continue; + x = idx[zi].rid; x <<= 1; x |= ((uint64_t)((z->rev == idx[zi].rev)?0:1)); + for (m = 0; m < tid_n; m++) { + if(tid->a[m] == x) { + n++; break; + } + } + } + ne = zi; + for (zi = ((int64_t)z->x)-1; zi >= 0 && idx[zi].x == p->x && n < mzl_cutoff; zi--) { + if(idx[zi].rid == rid) continue; + x = idx[zi].rid; x <<= 1; x |= ((uint64_t)((z->rev == idx[zi].rev)?0:1)); + for (m = 0; m < tid_n; m++) { + if(tid->a[m] == x) { + n++; break; + } + } + } + ns = zi + 1; + if((!n) || (n >= mzl_cutoff)) continue; + n = ne - ns; if(n > ((uint32_t)(0xffffffu))) n = 0xffffffu; n<<=8; + + for (zi = z->x+1; zi < idx_n && idx[zi].x == p->x; zi++) { + if(idx[zi].rid == rid) continue; + x = idx[zi].rid; x <<= 1; x |= ((uint64_t)((z->rev == idx[zi].rev)?0:1)); + for (m = 0; m < tid_n; m++) { + if(tid->a[m] == x) break; + } + if(m >= tid_n) continue; + + + y = &(idx[zi]); an = &ab->a[k++]; + rev = z->rev == y->rev? 0 : 1; + an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; + an->self_off = z->pos; + ///an->cnt: cnt<<8|span + an->cnt = ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); an->cnt |= n; + an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; + } + for (zi = ((int64_t)z->x)-1; zi >= 0 && idx[zi].x == p->x; zi--) { + if(idx[zi].rid == rid) continue; + x = idx[zi].rid; x <<= 1; x |= ((uint64_t)((z->rev == idx[zi].rev)?0:1)); + for (m = 0; m < tid_n; m++) { + if(tid->a[m] == x) break; + } + if(m >= tid_n) continue; + + + + y = &(idx[zi]); an = &ab->a[k++]; + rev = z->rev == y->rev? 0 : 1; + an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; + an->self_off = z->pos; + ///an->cnt: cnt<<8|span + an->cnt = ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); an->cnt |= n; + an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; + } + } + assert(k == ab->n_a); + radix_sort_ha_an1(ab->a + ab->n_a - tn, ab->a + ab->n_a); kn = 0; + for (k = ab->n_a - tn + 1, l = ab->n_a - tn; k <= ab->n_a; ++k) { + if (k == ab->n_a || (ab->a[k].srt>>32) != (ab->a[l].srt>>32)) { + for (; kn < tid_n && tid->a[kn] < (ab->a[l].srt>>32); kn++); + if(kn < tid_n && tid->a[kn] == (ab->a[l].srt>>32)) kv_push(uint64_t, *tid, l); + for (; kn < tid_n && tid->a[kn] == (ab->a[l].srt>>32); kn++); + l = k; + } + } +} + +void minimizers_qgen_input(ha_abufl_t *ab, uint64_t rid, char* rs, int64_t rl, uint64_t mz_w, uint64_t mz_k, Candidates_list *cl, kvec_t_u8_warp* k_flag, +void *ha_flt_tab, ha_pt_t *ha_idx, All_reads* rdb, const ul_idx_t *udb, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, +uint32_t *low_occ, ha_mzl_t *in, uint64_t in_n, ha_mzl_t *idx, int64_t idx_n, uint64_t mzl_cutoff, uint64_t chain_cutoff, kv_u_trans_t *kov) +{ + // fprintf(stderr, "+[M::%s]\n", __func__); + uint64_t i, k, l, max_cnt = UINT32_MAX, min_cnt = 0, n; ha_mzl_t *z, *p, *y; anchor1_t *an; + int64_t zi, ns, ne; uint8_t rev; k_mer_hit *s; + if(high_occ) { + max_cnt = (*high_occ); + if(max_cnt < 2) max_cnt = 2; + } + if(low_occ) { + min_cnt = (*low_occ); + if(min_cnt < 2) min_cnt = 2; + } + clear_Candidates_list(cl); + + for (i = 0, ab->n_a = 0; i < in_n; ++i) { + ///z is one of the minimizer + z = &in[i]; p = &(idx[z->x]); n = 0; + assert(z->pos == p->pos && z->rid == p->rid && z->span == p->span && z->rev == p->rev); + for (zi = z->x+1; zi < idx_n && idx[zi].x == p->x && n < mzl_cutoff; zi++) { + if(idx[zi].rid == rid) {continue;} n++; + } + for (zi = ((int64_t)z->x)-1; zi >= 0 && idx[zi].x == p->x && n < mzl_cutoff; zi--) { + if(idx[zi].rid == rid) {continue;} n++; + } + if((!n) || (n >= mzl_cutoff)) continue; + ab->n_a += n; + } + // if(rid == 0) { + // fprintf(stderr, "-0-[M::%s] ab->n_a::%lu, in_n::%lu\n", __func__, ab->n_a, in_n); + // } + + if (ab->n_a > ab->m_a) { + ab->m_a = ab->n_a; + REALLOC(ab->a, ab->m_a); + } + + for (i = 0, k = 0; i < in_n; ++i) { + ///z is one of the minimizer + z = &in[i]; p = &(idx[z->x]); n = 0; ns = 0; ne = -1; + for (zi = z->x+1; zi < idx_n && idx[zi].x == p->x && n < mzl_cutoff; zi++) { + if(idx[zi].rid == rid) {continue;} n++; + } + ne = zi; + for (zi = ((int64_t)z->x)-1; zi >= 0 && idx[zi].x == p->x && n < mzl_cutoff; zi--) { + if(idx[zi].rid == rid) {continue;} n++; + } + ns = zi + 1; + if((!n) || (n >= mzl_cutoff)) continue; + n = ne - ns; if(n > ((uint32_t)(0xffffffu))) n = 0xffffffu; n<<=8; + + for (zi = z->x+1; zi < idx_n && idx[zi].x == p->x; zi++) { + if(idx[zi].rid == rid) continue; + y = &(idx[zi]); an = &ab->a[k++]; + rev = z->rev == y->rev? 0 : 1; + an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; + an->self_off = z->pos; + ///an->cnt: cnt<<8|span + an->cnt = ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); an->cnt |= n; + an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; + } + for (zi = ((int64_t)z->x)-1; zi >= 0 && idx[zi].x == p->x; zi--) { + if(idx[zi].rid == rid) continue; + y = &(idx[zi]); an = &ab->a[k++]; + rev = z->rev == y->rev? 0 : 1; + an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; + an->self_off = z->pos; + ///an->cnt: cnt<<8|span + an->cnt = ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); an->cnt |= n; + an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; + } + } + assert(k == ab->n_a); + + uint64_t kn, spn; u_trans_t *ka; + kn = spn = 0; ka = NULL; sp->n = 0; + if(kov) { + kn = u_trans_n(*kov, rid); ka = u_trans_a(*kov, rid); + } + if(kn > 0) { + kv_resize(uint64_t, *sp, kn); + for (k = 0; k < kn; ++k) { + if(ka[k].del) continue; + l = ka[k].tn; l <<= 1; l |= ka[k].rev; + kv_push(uint64_t, *sp, l); + } + if(sp->n > 1) radix_sort_anc64(sp->a, sp->a + sp->n); + } + + radix_sort_ha_an1(ab->a, ab->a + ab->n_a); kn = 0; + for (k = 1, l = n = 0, spn = sp->n; k <= ab->n_a; ++k) { + if (k == ab->n_a || (ab->a[k].srt>>32) != (ab->a[l].srt>>32)) { + if(k - l >= chain_cutoff) { + for (; kn < spn && sp->a[kn] < (ab->a[l].srt>>32); kn++); + if(kn < spn && sp->a[kn] == (ab->a[l].srt>>32)) kv_push(uint64_t, *sp, n); + for (; kn < spn && sp->a[kn] == (ab->a[l].srt>>32); kn++) sp->a[kn] = (uint64_t)-1; + for (i = l; i < k; i++) ab->a[n++] = ab->a[i]; + } + l = k; + } + } + ab->n_a = n; + for (k = kn = 0; k < spn; k++) { + if(sp->a[k] == (uint64_t)-1) continue; + sp->a[kn++] = sp->a[k]; + } + // sp->n = kn; + if(kn > 0) gen_pair_chain(ab, rid, sp, kn, in, in_n, idx, idx_n, mzl_cutoff); + if(spn > 0) { + for (k = spn, kn = 0; k < sp->n; k++) sp->a[kn++] = sp->a[k]; + sp->n = kn; + } + + + // copy over to _cl_ + if (ab->n_a >= (uint64_t)cl->size) { + cl->size = ab->n_a; + REALLOC(cl->list, cl->size); + } + + uint64_t tid = (uint64_t)-1, tl = (uint64_t)-1; + for (k = 1, l = 0; k <= ab->n_a; ++k) { + if (k == ab->n_a || ab->a[k].srt != ab->a[l].srt) { + if (k-l>1) radix_sort_ha_an3(ab->a+l, ab->a+k); + if((ab->a[l].srt>>33)!=tid) { + tid = ab->a[l].srt>>33; + tl = rdb?Get_READ_LENGTH((*rdb), tid):udb->ug->u.a[tid].len; + } + for (i = l; i < k; i++) { + s = &cl->list[i]; + s->readID = ab->a[i].srt>>33; + s->strand = (ab->a[i].srt>>32)&1; + if(!(s->strand)) { + s->offset = ab->a[i].other_off; + } else { + s->offset = ((uint32_t)-1)-ab->a[i].other_off; + s->offset = tl-s->offset; + } + s->self_offset = ab->a[i].self_off; + if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ + s->cnt = 1; + } else if((ab->a[i].cnt>>8) <= min_cnt) { + s->cnt = 2; + } else{ + s->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); + s->cnt = pow(s->cnt, 1.1); + } + if(s->cnt > ((uint32_t)(0xffffffu))) s->cnt = 0xffffffu; + s->cnt <<= 8; s->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); + } + l = k; + } + } + cl->length = ab->n_a; +} + +void inline reverse_k_mer_hit(k_mer_hit *a, uint64_t a_n, uint64_t xl, uint64_t yl) +{ + uint64_t z, han = a_n>>1; k_mer_hit *ai, *aj, ka; + for (z = 0; z < han; z++) { + ai = &(a[z]); aj = &(a[a_n-z-1]); + ka = (*ai); (*ai) = (*aj); (*aj) = ka; + + ai->self_offset = xl-ai->self_offset-1; + ai->offset = yl-ai->offset-1; + + aj->self_offset = xl-aj->self_offset-1; + aj->offset = yl-aj->offset-1; + } + if(a_n&1) { + a[z].self_offset = xl-a[z].self_offset-1; + a[z].offset = yl-a[z].offset-1; + } +} + + +void inline reset_k_mer_hit(k_mer_hit *a, uint64_t a_n, uint64_t xl, uint64_t yl, uint64_t rev, uint64_t *nid) +{ + uint64_t z, han = a_n>>1; k_mer_hit *ai, *aj, ka; + if(rev) { + for (z = 0; z < han; z++) { + ai = &(a[z]); aj = &(a[a_n-z-1]); + ka = (*ai); (*ai) = (*aj); (*aj) = ka; + + ai->self_offset = xl-ai->self_offset-1; + ai->offset = yl-ai->offset-1; + + aj->self_offset = xl-aj->self_offset-1; + aj->offset = yl-aj->offset-1; + if(nid) ai->readID = aj->readID = (*nid); + } + if(a_n&1) { + a[z].self_offset = xl-a[z].self_offset-1; + a[z].offset = yl-a[z].offset-1; + if(nid) a[z].readID = (*nid); + } + } else if(nid) { + for (z = 0; z < a_n; z++) a[z].readID = (*nid); + } +} + +void lchain_gen(Candidates_list* cl, overlap_region_alloc* ol, uint32_t rid, uint64_t rl, All_reads* rdb, + const ul_idx_t *udb, uint32_t apend_be, overlap_region* tf, uint64_t max_n_chain, + int64_t max_skip, int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, int64_t quick_check, uint32_t gen_off) +{ + // fprintf(stderr, "+[M::%s]\n", __func__); + uint64_t i, k, l, m, sm, cn = cl->length; overlap_region *r; ///srt = 0 + clear_overlap_region_alloc(ol); + clear_fake_cigar(&(tf->f_cigar)); + + for (l = 0, k = 1, m = 0; k <= cn; k++) { + if((k == cn) || (cl->list[k].readID != cl->list[l].readID) + || (cl->list[k].strand != cl->list[l].strand)) { + if(cl->list[l].readID != rid) { + tf->x_id = rid; + tf->x_pos_strand = cl->list[l].strand; + tf->y_id = cl->list[l].readID; + tf->y_pos_strand = 0;///always 0 + // fprintf(stderr, "+[M::%s] l::%lu, k::%lu\n", __func__, l, k); + sm = lchain_dp(cl->list+l, k-l, cl->list+m, &(cl->chainDP), tf, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, + rl, rdb?Get_READ_LENGTH((*rdb), (*tf).y_id):udb->ug->u.a[(*tf).y_id].len, quick_check); + // assert(sm > 0); + if(ovlp_chain_gen(ol, tf, rl, rdb?Get_READ_LENGTH((*rdb), (*tf).y_id):udb->ug->u.a[(*tf).y_id].len, apend_be, cl->list+m, sm)) { + r = &(ol->list[ol->length-1]); r->non_homopolymer_errors = m; + // if(r->y_pos_strand) { + // reverse_k_mer_hit(cl->list+m, sm, rl, rdb?Get_READ_LENGTH((*rdb), r->y_id):udb->ug->u.a[r->y_id].len); + // } + reset_k_mer_hit(cl->list+m, sm, rl, rdb?Get_READ_LENGTH((*rdb), r->y_id):udb->ug->u.a[r->y_id].len, r->y_pos_strand, &(ol->length)); + if(gen_off) gen_fake_cigar(&(r->f_cigar), r, apend_be, cl->list+m, sm); + m += sm; + } + } + l = k; + } + } + cl->length = m; + + + k = ol->length; + if (ol->length > max_n_chain) { + int32_t w, n[4], s[4]; overlap_region t; + n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; + ks_introsort_or_ss(ol->length, ol->list); ///srt = 1; + for (i = 0; i < ol->length; ++i) { + r = &(ol->list[i]); + w = ha_ov_type(r, rl); + ++n[w]; + if (((uint64_t)n[w]) == max_n_chain) s[w] = r->shared_seed; + } + if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { + // n[0] = n[1] = n[2] = n[3] = 0; + for (i = 0, k = 0; i < ol->length; ++i) { + r = &(ol->list[i]); + w = ha_ov_type(r, rl); + // ++n[w]; + // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { + if (r->shared_seed >= s[w]) { + if (k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + ++k; + } + } + ol->length = k; + } + } + /** + if(!gen_off) { + if(srt) ks_introsort_or_id(ol->length, ol->list); + uint64_t cln = cl->length; + for (i = k = m = 0; i < ol->length; ++i) { + r = &(ol->list[i]); + for (;(klist[k].readID!=r->y_id)||(cl->list[k].strand!=r->y_pos_strand)); k++); + // assert(klist[k].readID!=r->y_id)||(cl->list[k].strand!=r->y_pos_strand)) break; + if(m != k) cl->list[m] = cl->list[k]; + } + // assert(m - cn > 0); + if(r->y_pos_strand) { + reverse_k_mer_hit(cl->list+cn, m-cn, rl, rdb?Get_READ_LENGTH((*rdb), r->y_id):udb->ug->u.a[r->y_id].len); + } + // gen_fake_cigar(&(r->f_cigar), r, apend_be, cl->list+cn, m-cn); + } + cl->length = m; + } + **/ + + ks_introsort_or_xs(ol->length, ol->list); +} + +void lchain_qgen(Candidates_list* cl, overlap_region_alloc* ol, uint32_t rid, uint64_t rl, All_reads* rdb, + const ul_idx_t *udb, uint32_t apend_be, overlap_region* tf, uint64_t max_n_chain, + int64_t max_skip, int64_t max_iter, int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, int64_t quick_check, uint32_t gen_off) +{ + uint64_t i, k, l, m, sm, cn = cl->length; overlap_region *r; ///srt = 0 + clear_overlap_region_alloc(ol); + clear_fake_cigar(&(tf->f_cigar)); + + for (l = 0, k = 1, m = 0; k <= cn; k++) { + if((k == cn) || (cl->list[k].readID != cl->list[l].readID) + || (cl->list[k].strand != cl->list[l].strand)) { + if(cl->list[l].readID != rid) { + tf->x_id = rid; + tf->x_pos_strand = cl->list[l].strand; + tf->y_id = cl->list[l].readID; + tf->y_pos_strand = 0;///always 0 + // fprintf(stderr, "+[M::%s] l::%lu, k::%lu\n", __func__, l, k); + sm = lchain_qdp(cl->list+l, k-l, cl->list+m, &(cl->chainDP), tf, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, + rl, rdb?Get_READ_LENGTH((*rdb), (*tf).y_id):udb->ug->u.a[(*tf).y_id].len, quick_check); + // assert(sm > 0); + if(ovlp_chain_qgen(ol, tf, rl, rdb?Get_READ_LENGTH((*rdb), (*tf).y_id):udb->ug->u.a[(*tf).y_id].len, apend_be, cl->list+m, sm)) { + r = &(ol->list[ol->length-1]); r->non_homopolymer_errors = m; + // if(tf->y_id == 66 || tf->y_id == 66) { + // fprintf(stderr, "\n[M::%s::] utg%.6dl(%c), i::%lu\n", + // __func__, (int32_t)tf->y_id+1, "+-"[tf->x_pos_strand], m); + // } + // reset_k_mer_hit(cl->list+m, sm, rl, rdb?Get_READ_LENGTH((*rdb), r->y_id):udb->ug->u.a[r->y_id].len, r->y_pos_strand, &(ol->length)); + for (i = 0; i < sm; i++) { + cl->list[m+i].readID = ol->length; + // if(tf->y_id == 126) fprintf(stderr, "[M::%s::qoff->%u::toff->%u]\n", __func__, cl->list[m+i].self_offset, cl->list[m+i].offset); + } + if(gen_off) gen_fake_cigar(&(r->f_cigar), r, apend_be, cl->list+m, sm); + m += sm; + } + } + l = k; + } + } + cl->length = m; + // fprintf(stderr, "+[M::%s] cn::%lu, m::%lu, ol->length::%lu\n", __func__, cn, m, ol->length); + // for (k = 0; k < ol->length; k++) { + // fprintf(stderr, "---[M::%s::utg%.6dl] q[%d, %d), t[%d, %d), khit_off::%u\n", __func__, + // (int32_t)ol->list[k].y_id+1, ol->list[k].x_pos_s, ol->list[k].x_pos_e+1, + // ol->list[k].y_pos_s, ol->list[k].y_pos_e+1, ol->list[k].non_homopolymer_errors); + // } + + + k = ol->length; + if (ol->length > max_n_chain) { + int32_t w, n[4], s[4]; overlap_region t; + n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; + ks_introsort_or_ss(ol->length, ol->list); ///srt = 1; + for (i = 0; i < ol->length; ++i) { + r = &(ol->list[i]); + w = ha_ov_type(r, rl); + ++n[w]; + if (((uint64_t)n[w]) == max_n_chain) s[w] = r->shared_seed; + } + if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { + // n[0] = n[1] = n[2] = n[3] = 0; + for (i = 0, k = 0; i < ol->length; ++i) { + r = &(ol->list[i]); + w = ha_ov_type(r, rl); + // ++n[w]; + // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { + if (r->shared_seed >= s[w]) { + if (k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + ++k; + } + } + ol->length = k; + } + } + ks_introsort_or_xs(ol->length, ol->list); +} + + +void lchain_qgen_mcopy(Candidates_list* cl, overlap_region_alloc* ol, uint32_t rid, uint64_t rl, All_reads* rdb, + const ul_idx_t *udb, uint32_t apend_be, uint64_t max_n_chain, int64_t max_skip, int64_t max_iter, + int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, int64_t quick_check, + uint32_t gen_off, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut, st_mt_t *sp) +{ + // fprintf(stderr, "+[M::%s]\n", __func__); + uint64_t i, k, l, m, cn = cl->length, yid, ol0, lch; overlap_region *r, t; ///srt = 0 + clear_overlap_region_alloc(ol); + + for (l = 0, k = 1, m = 0, lch = 0; k <= cn; k++) { + if((k == cn) || (cl->list[k].readID != cl->list[l].readID)) { + if(cl->list[l].readID != rid) { + yid = cl->list[l].readID; ol0 = ol->length; + m += lchain_qdp_mcopy(cl, l, k-l, m, &(cl->chainDP), ol, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, + rid, rl, rdb?Get_READ_LENGTH((*rdb), yid):udb->ug->u.a[yid].len, quick_check, apend_be, gen_off, 1, mcopy_rate, mcopy_khit_cut, 1); + if((chain_cutoff >= 2) && (!lch)) { + for (i = ol0; (ilength) && (!lch); i++) { + if(ol->list[i].align_length < chain_cutoff) lch = 1; + } + } + } + l = k; + } + } + cl->length = m; + + // for (k = 0; k < ol->length; k++) { + // fprintf(stderr, "---[M::%s::utg%.6dl] q[%d, %d), t[%d, %d), khit_off::%u\n", __func__, + // (int32_t)ol->list[k].y_id+1, ol->list[k].x_pos_s, ol->list[k].x_pos_e+1, + // ol->list[k].y_pos_s, ol->list[k].y_pos_e+1, ol->list[k].non_homopolymer_errors); + // } + + k = ol->length; + if (ol->length > max_n_chain) { + int32_t w, n[4], s[4]; + n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; + ks_introsort_or_ss(ol->length, ol->list); + for (i = 0; i < ol->length; ++i) { + r = &(ol->list[i]); + w = ha_ov_type(r, rl); + ++n[w]; + if (((uint64_t)n[w]) == max_n_chain) s[w] = r->shared_seed; + } + if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { + // n[0] = n[1] = n[2] = n[3] = 0; + for (i = 0, k = 0, lch = 0; i < ol->length; ++i) { + r = &(ol->list[i]); + w = ha_ov_type(r, rl); + // ++n[w]; + // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { + if (r->shared_seed >= s[w]) { + if (k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + if(ol->list[k].align_length < chain_cutoff) lch = 1; + ++k; + } + } + ol->length = k; + } + } + + ks_introsort_or_xs(ol->length, ol->list); + if(lch) { + //@brief r485 + uint64_t zs, ze, rs, re, ob, os, oe, ocn, pp, kn, ms, me; int64_t osc; + for (i = l = 0, cn = cl->length; i < ol->length; ++i) { + if(ol->list[i].align_length < chain_cutoff) { + zs = ol->list[i].x_pos_s; ze = ol->list[i].x_pos_e + 1; + ob = (ze - zs)*OFL; if(ob < 16) ob = 16; + osc = ol->list[i].shared_seed*CH_SC; + ocn = ol->list[i].align_length<length) && (ze > ol->list[k].x_pos_s); k++) { + if(ol->list[k].align_length < chain_cutoff) continue; + if(ol->list[k].align_length < ocn) continue; + if(ol->list[k].shared_seed < osc) continue; + rs = ol->list[k].x_pos_s; re = ol->list[k].x_pos_e + 1; + os = ((rs>=zs)?rs:zs); oe = ((re<=ze)?re:ze); + if((oe > os) && (oe - os) >= ob) { + m = ol->list[k].non_homopolymer_errors; + pp = cl->list[m].readID; kn = 0; + for (; (m < cn) && (cl->list[m].readID == pp) && (kn < ocn); m++) { + me = cl->list[m].self_offset; ms = me - (cl->list[m].cnt&(0xffu)); + if((ms >= os) && (me <= oe)) kn++; + } + if(kn >= ocn) break; + } + } + if((k < ol->length) && (ze > ol->list[k].x_pos_s)) continue; + } + if (l != i) { + t = ol->list[l]; + ol->list[l] = ol->list[i]; + ol->list[i] = t; + } + l++; + } + // fprintf(stderr, "+[M::%s] rid::%u, ol->length0::%lu, ol->length1::%lu\n", __func__, rid, ol->length, l); + ol->length = l; + + + /** + //@brief r484 + for (i = sp->n = 0; i < ol->length; ++i) { + if(ol->list[i].align_length < chain_cutoff) continue; + os = ol->list[i].x_pos_s; oe = ol->list[i].x_pos_e + 1; + if((sp->n) && (((uint32_t)sp->a[sp->n-1]) >= os)) { + if(oe > ((uint32_t)sp->a[sp->n-1])) { + oe = oe - ((uint32_t)sp->a[sp->n-1]); + sp->a[sp->n-1] += oe; + } + } else { + os = (os<<32)|oe; kv_push(uint64_t, *sp, os); + } + } + + for (i = k = 0; i < ol->length; ++i) { + if(ol->list[i].align_length < chain_cutoff) {///ol has been sorted by x_pos_s + r = &(ol->list[i]); rs = r->x_pos_s; re = r->x_pos_e + 1; + rl = re - rs; ovl = 0; + for (m = 0; (m < sp->n) && (re > (sp->a[m]>>32)); m++) { + os = ((rs>=(sp->a[m]>>32))? rs:(sp->a[m]>>32)); + oe = ((re<=((uint32_t)sp->a[m]))? re:((uint32_t)sp->a[m])); + if(oe > os) { + ovl += (oe - os); if(ovl >= (rl*0.95)) break; + } + } + if(ovl >= (rl*0.95)) continue; + } + if (k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + ol->list[k++].align_length = 0; + } + // fprintf(stderr, "+[M::%s] ol->length0::%lu, ol->length1::%lu\n", __func__, ol->length, k); + ol->length = k; + **/ + } + /**else { + for (i = 0; i < ol->length; ++i) ol->list[i].align_length = 0; + } + **/ + for (i = 0; i < ol->length; ++i) ol->list[i].align_length = 0; +} + +static inline uint64_t mz_pos_bsearch(const ha_mz1_t *a, uint64_t lo, uint64_t hi, uint64_t key) { + uint64_t mid; + if((lo >= hi) || (a[lo].pos > key)) {lo = 0;} + else if(a[lo].pos == key) {return lo;} + + while (lo < hi) { + mid = lo + ((hi - lo) >> 1); + if (a[mid].pos < key) { + lo = mid + 1; + } else if(a[mid].pos > key) { + hi = mid; + } else { + lo = mid; + break; + } + } + if (lo < hi && a[lo].pos == key) { + return lo; + } + return ((uint64_t)-1); +} + +uint8_t cmp_chain_aln(overlap_region *a, /**uint32_t ak0,**/ overlap_region *b, k_mer_hit *ca) +{ + uint64_t ak, bk, al[2], bl[2]/**, af[2], bf[2]**/; + al[0] = a->non_homopolymer_errors; al[1] = a->overlapLen; + bl[0] = b->non_homopolymer_errors; bl[1] = b->overlapLen; + + + for (ak = al[0], bk = bl[0]; (ak < al[1]) && (bk < bl[1]) && (ca[ak].self_offset == ca[bk].self_offset); ak++, bk++); + + // if(ka == 128 && kb == 129) { + // fprintf(stderr, "[M::%s::] al::[%lu,%lu), bl::[%lu,%lu), ak::%lu, bk::%lu\n", __func__, al[0], al[1], bl[0], bl[1], ak, bk); + // } + + if((ak < al[1]) || (bk < bl[1])) return 0; + + /** + af[0] = af[1] = bf[0] = bf[1] = ((uint64_t)-1); + + + + + for (ak = ak0, bk = bl[0]; (bk < bl[1]) && (ca[bk].self_offset < ca[ak].self_offset); bk++); + // if(!((bk < bl[1]) && (ca[ak].self_offset == ca[bk].self_offset))) { + // fprintf(stderr, "[M::%s::]\ta::%.*s->b::%.*s\n", __func__, + // (int32_t)Get_NAME_LENGTH(R_INF, a->y_id), Get_NAME(R_INF, a->y_id), (int32_t)Get_NAME_LENGTH(R_INF, b->y_id), Get_NAME(R_INF, b->y_id)); + // } + assert((bk < bl[1]) && (ca[ak].self_offset == ca[bk].self_offset)); + + + + + + af[0] = ak; af[1] = ++ak; + bf[0] = bk; bf[1] = ++bk; + + for (; (ak < al[1]) && (bk < bl[1]) && (ca[ak].self_offset == ca[bk].self_offset); ak++, bk++); + af[1] = ak; bf[1] = bk; + + if(af[0] > al[0] && bf[0] > bl[0]) return 0; + if(af[1] < al[1] && bf[1] < bl[1]) return 0; + **/ + + return 1; +} + +void debug_chain_aln_de(overlap_region_alloc *ol, Candidates_list *cl) +{ + uint64_t k, z, zn; overlap_region *pk, *pz; + for (k = 0; k < ol->length; k++) { + pk = &(ol->list[k]); + for (z = zn = 0; z < ol->length; z++) { + if(z == k) continue; + pz = &(ol->list[z]); + if(cmp_chain_aln(pk, pz, cl->list)) { + if((pk->x_id != pz->x_id) || (pk->x_id == ((uint32_t)-1)) || (pz->x_id == ((uint32_t)-1))) { + fprintf(stderr, "[M::%s::type0] k::%lu, z::%lu\n", __func__, k, z); + exit(1); + } + zn++; + } + } + if((pk->x_id == ((uint32_t)-1)) && (zn > 0)) { + fprintf(stderr, "[M::%s::type1] k::%lu, zn::%lu\n", __func__, k, zn + 1); + exit(1); + } + } +} + +void chain_aln_de(ha_abuf_t *ab, overlap_region_alloc *ol, Candidates_list *cl, asg32_v *ik) +{ + uint64_t k, l, p, pi, c, z, zn, zk; uint32_t pn/**, ikn0 = ik->n**/; + + // fprintf(stderr, "-0-[M::%s::] ik->n::%lu, ol->length::%lu\n", __func__, (uint64_t)ik->n, ol->length); + + for (k = 0; k < ol->length; k++) { + // fprintf(stderr, "\n---[k::%lu::M::%s::%.*s(qid::%u)] q[%d, %d), t[%d, %d), sc::%d, occ::%u\n", k, __func__, + // (int32_t)Get_NAME_LENGTH(R_INF, ol->list[k].y_id), Get_NAME(R_INF, ol->list[k].y_id), ol->list[k].y_id, + // ol->list[k].x_pos_s, ol->list[k].x_pos_e+1, ol->list[k].y_pos_s, ol->list[k].y_pos_e+1, ol->list[k].shared_seed, ol->list[k].align_length); + if(ol->list[k].x_id != ((uint32_t)-1)) continue; + + /** + for (l = ol->list[k].non_homopolymer_errors, zn = 0; l < ol->list[k].overlapLen; l++) { + + p = cl->list[l].readID; + // pa = ik->a + (ab->mz.a[p].x>>32); + pi = (ab->mz.a[p].x>>32); + pn = ((uint32_t)(ab->mz.a[p].x)); + assert(pn > 0); + fprintf(stderr, "[M::%s::] qpos::%u, tpos::%u, cnt::%u, pn::%u\n", __func__, cl->list[l].self_offset, cl->list[l].offset, cl->list[l].cnt>>8, pn); + for (z = 0; z < pn; z++) { + c = ik->a[pi + z]; + // if(k == 128 && c == 129) fprintf(stderr, "+0+c::%lu\n", c); + if(c == k) continue; + // if(k == 128 && c == 129) fprintf(stderr, "+1+c::%lu\n", c); + if(ol->list[c].x_id != ((uint32_t)-1)) continue; + // if(k == 128 && c == 129) fprintf(stderr, "+2+c::%lu\n", c); + if(ol->list[c].strong) continue; + // if(k == 128 && c == 129) fprintf(stderr, "+3+c::%lu\n", c); + ol->list[c].strong = 1; + kv_push(uint32_t, *ik, c); + if(!cmp_chain_aln(k, &(ol->list[k]), l, c, &(ol->list[c]), cl->list)) continue; + // if(k == 128 && c == 129) fprintf(stderr, "+4+c::%lu\n", c); + ol->list[c].x_id = k; + zn++; + } + } + + if(zn) ol->list[k].x_id = k; + + for (l = ikn0; l < ik->n; l++) { + ol->list[ik->a[l]].strong = 0; + } + ik->n = ikn0; + **/ + for (l = zk = ol->list[k].non_homopolymer_errors, zn = ((uint32_t)-1); l < ol->list[k].overlapLen; l++) { + p = cl->list[l].readID; + pn = ((uint32_t)(ab->mz.a[p].x)); + assert(pn > 0); + if(pn < zn) { + zk = l; zn = pn; + } + // fprintf(stderr, "[M::%s::] qpos::%u, tpos::%u, cnt::%u, pn::%u\n", __func__, cl->list[l].self_offset, cl->list[l].offset, cl->list[l].cnt>>8, pn); + } + + + + l = zk; p = cl->list[l].readID; + pi = (ab->mz.a[p].x>>32); pn = ((uint32_t)(ab->mz.a[p].x)); + assert(pn > 0); + kv_push(uint32_t, *ik, k); + for (z = 0; z < pn; z++) { + c = ik->a[pi + z]; + if(c <= k) continue; + if(ol->list[c].x_id != ((uint32_t)-1)) continue; + if(!cmp_chain_aln(&(ol->list[k]), &(ol->list[c]), cl->list)) continue; + ol->list[c].x_id = k; + zn++; + kv_push(uint32_t, *ik, c); + } + + // if(zn) ol->list[k].x_id = k; + ol->list[k].x_id = k; + // fprintf(stderr, "[M::%s::] zn::%lu\n", __func__, zn); + } + + /** + fprintf(stderr, "-1-[M::%s::] ik->n::%lu, ol->length::%lu\n", __func__, (uint64_t)ik->n, ol->length); + + for (k = 0; k < ol->length; k++) { + if((ol->list[k].x_id != ((uint32_t)-1)) && (ol->list[k].x_id != k)) continue; + + if(k == ol->list[k].x_id) { + fprintf(stderr, "[M::%s::] cs::%lu->", __func__, k); + for (l = zn = 0; l < ol->length; l++) { + if(ol->list[k].x_id == ol->list[l].x_id) { + fprintf(stderr, "%lu,", l); + zn++; + } + } + fprintf(stderr, "(znn::%lu)\n", zn); + } else { + fprintf(stderr, "[M::%s::] cs::%lu->(znn::1)\n", __func__, k); + } + for (l = ol->list[k].non_homopolymer_errors, zn = 0; l < ol->list[k].overlapLen; l++) { + fprintf(stderr, "[M::%s::] qpos::%u, tpos::%u, cnt::%u\n", __func__, cl->list[l].self_offset, cl->list[l].offset, cl->list[l].cnt>>8); + } + } + + debug_chain_aln_de(ol, cl); + + // for (k = ik->n - ol->length; k < ik->n; k++) { + // ik->a[k] + // } + **/ + + +} + + +void gen_chain_clus(ha_abuf_t *ab, overlap_region_alloc *ol, Candidates_list *cl, asg32_v *ik) +{ + if(ol->length <= 0) return; + ks_introsort_or_ss(ol->length, ol->list); + + uint64_t k, l, c, p_b, p_r, cln = cl->length; uint32_t *pa = NULL, pn, xid0 = ol->list[0].x_id; + + for (k = 1, l = 0; k < ol->length; k++) {///sort for merging + if ((k == ol->length) || (ol->list[l].shared_seed != ol->list[k].shared_seed)) { + if (k - l > 1) { + ks_introsort_or_xs(k - l, ol->list + l); + } + l = k; + } + } + + for (k = 0; k < ab->mz.n; k++) ab->mz.a[k].x = 0; + for (k = 0; k < ol->length; k++) { + l = ol->list[k].non_homopolymer_errors; + p_r = cl->list[l].readID; + for (; (l < cln) && (cl->list[l].readID == p_r); l++) {;} + ol->list[k].overlapLen = l; + } + + for (k = ik->n = 0, p_b = ab->mz.n; k < ol->length; k++) { + for (l = ol->list[k].non_homopolymer_errors; l < ol->list[k].overlapLen; l++) { + p_b = mz_pos_bsearch(ab->mz.a, p_b + 1, ab->mz.n, cl->list[l].self_offset); + assert(p_b != ((uint64_t)-1)); + // idx->a[p]++; + ab->mz.a[p_b].x++; ik->n++; + cl->list[l].readID = p_b;///minimizer id + } + // fprintf(stderr, "[M_beg::%s::]\tk::%lu\ty_id::%u\tc_n::%u\tc_beg::%u\n", __func__, k, ol->list[k].y_id, ol->list[k].overlapLen - ol->list[k].non_homopolymer_errors, ol->list[k].non_homopolymer_errors); + } + + /** + for (k = ik->n = 0, p_b = ab->mz.n; k < ol->length; k++) { + l = ol->list[k].non_homopolymer_errors; + p_r = cl->list[l].readID; + for (; (l < cln) && (cl->list[l].readID == p_r); l++) { + p_b = mz_pos_bsearch(ab->mz.a, p_b + 1, ab->mz.n, cl->list[l].self_offset); + assert(p_b != ((uint64_t)-1)); + // idx->a[p]++; + ab->mz.a[p_b].x++; ik->n++; + cl->list[l].readID = p_b;///minimizer id + } + ol->list[k].overlapLen = l; + fprintf(stderr, "[M_beg::%s::]\tk::%lu\ty_id::%u\tc_n::%u\tc_beg::%u\n", __func__, k, ol->list[k].y_id, ol->list[k].overlapLen - ol->list[k].non_homopolymer_errors, ol->list[k].non_homopolymer_errors); + } + **/ + + kv_resize(uint32_t, *ik, ik->n); + memset(ik->a, -1, sizeof((*(ik->a)))*ik->n); + + for (k = l = 0; k < ab->mz.n; k++) { + ab->mz.a[k].x |= (l<<32); + l += (uint32_t)(ab->mz.a[k].x); + if((uint32_t)(ab->mz.a[k].x)) { + ik->a[(ab->mz.a[k].x>>32) + ((uint32_t)(ab->mz.a[k].x)) - 1] = 0; + } + } + assert(l == ik->n); + + for (k = 0; k < ol->length; k++) { + for (l = ol->list[k].non_homopolymer_errors; l < ol->list[k].overlapLen; l++) { + p_b = cl->list[l].readID; + pa = ik->a + (ab->mz.a[p_b].x>>32); + pn = ((uint32_t)(ab->mz.a[p_b].x)); + assert(pn > 0); + c = pa[pn - 1]; + assert(c < pn); + pa[c] = k; ///pa[c] = l; + if(c + 1 < pn) {pa[pn - 1]++;} + // cl->list[l].readID = k; + } + // ol->list[k].overlapLen = 0; + ol->list[k].x_id = ((uint32_t)-1);///mark for clustering + } + + chain_aln_de(ab, ol, cl, ik); + + for (k = ik->n - ol->length, l = 0; k < ik->n; k++) { + ik->a[l++] = ik->a[k]; + } + ik->n = ol->length; + + + + ik->n = ol->length<<1; kv_resize(uint32_t, *ik, ik->n); + memset(ik->a + ol->length, -1, (sizeof((*(ik->a)))*ol->length)); + // ik->n = ol->length; + for (k = 1, l = 0; k <= ol->length; k++) { + if((k == ol->length) || (ol->list[ik->a[l]].x_id != ol->list[ik->a[k]].x_id)) { + for (c = l; c < k; c++) { + ik->a[ik->a[c]+ol->length] = l; + } + l = k; + } + } + + // for (k = 0, ik->n = ol->length; k < ol->length; k++) { + // ik->a[ik->n++] = ((ol->list[k].x_id == ((uint32_t)-1))?k:ol->list[k].x_id); + // } + + ///reset + for (k = 0; k < ol->length; k++) { + // fprintf(stderr, "[M_end::%s::]\tk::%lu\ty_id::%u\tc_n::%u\tc_beg::%u\n", __func__, k, ol->list[k].y_id, ol->list[k].overlapLen - ol->list[k].non_homopolymer_errors, ol->list[k].non_homopolymer_errors); + for (l = ol->list[k].non_homopolymer_errors; l < ol->list[k].overlapLen; l++) { + cl->list[l].readID = k; + } + ol->list[k].overlapLen = 0; + ol->list[k].x_id = xid0; + } +} + +void lchain_qgen_mcopy_fast(ha_abuf_t *ab, Candidates_list* cl, overlap_region_alloc* ol, uint32_t rid, uint64_t rl, All_reads* rdb, + uint32_t apend_be, uint64_t max_n_chain, int64_t max_skip, int64_t max_iter, + int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate_h, uint64_t cl_hn, double bw_rate_l, uint64_t cl_ln, int64_t quick_check, + uint32_t gen_off, int64_t mcopy_num, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut, st_mt_t *sp, uint64_t ocv_w, uint8_t is_raw_chain) +{ + // fprintf(stderr, "+[M::%s] chain_cutoff::%u\n", __func__, chain_cutoff); + uint64_t i, k, l, m, cn = cl->length, yid, ol0, lch, *cc = NULL, cwn = 0, cws, cwe, os, oe, rs, re, cw0, cw1/**, dbgn = 0**/; overlap_region *r, t; ///srt = 0 + clear_overlap_region_alloc(ol); + + // for (l = 0, k = 1, m = 0, lch = 0; k <= cn; k++) { + // if((k == cn) || (cl->list[k].readID != cl->list[l].readID)) { + // if(cl->list[l].readID != rid) { + // yid = cl->list[l].readID; ol0 = ol->length; + // m += lchain_qdp_mcopy_fast(cl, l, k-l, m, &(cl->chainDP), ol, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, + // rid, rl, Get_READ_LENGTH((*rdb), yid), quick_check, apend_be, gen_off, mcopy_num, mcopy_rate, mcopy_khit_cut, 1); + // if((chain_cutoff >= 2) && (!lch)) { + // for (i = ol0; (ilength) && (!lch); i++) { + // if(ol->list[i].align_length < chain_cutoff) lch = 1; + // } + // } + // } + // l = k; + // } + // } + // cl->length = m; + + ///cl->list[0, cl_hn) & cl->list[cl_hn, cl_hn + cl_ln) + cn = cl_hn; + for (l = 0, k = 1, m = 0, lch = 0; k <= cn; k++) { + if((k == cn) || (cl->list[k].readID != cl->list[l].readID)) { + if(cl->list[l].readID != rid) { + yid = cl->list[l].readID; ol0 = ol->length; + m += lchain_qdp_mcopy_fast(cl, l, k-l, m, &(cl->chainDP), ol, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate_h, + rid, rl, Get_READ_LENGTH((*rdb), yid), quick_check, apend_be, gen_off, mcopy_num, mcopy_rate, mcopy_khit_cut, 1); + if((chain_cutoff >= 2) && (!lch)) { + for (i = ol0; (ilength) && (!lch); i++) { + if(ol->list[i].align_length < chain_cutoff) lch = 1; + } + } + } + l = k; + } + } + + cn = cl_hn + cl_ln; + for (; k <= cn; k++) { + if((k == cn) || (cl->list[k].readID != cl->list[l].readID)) { + if(cl->list[l].readID != rid) { + yid = cl->list[l].readID; ol0 = ol->length; + m += lchain_qdp_mcopy_fast(cl, l, k-l, m, &(cl->chainDP), ol, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate_l, + rid, rl, Get_READ_LENGTH((*rdb), yid), quick_check, apend_be, gen_off, mcopy_num, mcopy_rate, mcopy_khit_cut, 1); + if((chain_cutoff >= 2) && (!lch)) { + for (i = ol0; (ilength) && (!lch); i++) { + if(ol->list[i].align_length < chain_cutoff) lch = 1; + } + } + } + l = k; + } + } + + cl->length = m; + + // fprintf(stderr, "\n[M::%s::] rn::%lu\tmax_n_chain::%lu\n", __func__, ol->length, max_n_chain); + + /** + for (k = 0; k < ol->length; k++) { + if(ha_ov_type(&(ol->list[k]), rl) == 1) { + fprintf(stderr, "---[M::%s::%.*s(qid::%u)] q[%d, %d), t[%d, %d), sc::%d, occ::%u, type::%d\n", __func__, + (int32_t)Get_NAME_LENGTH(R_INF, ol->list[k].y_id), Get_NAME(R_INF, ol->list[k].y_id), ol->list[k].y_id, + ol->list[k].x_pos_s, ol->list[k].x_pos_e+1, ol->list[k].y_pos_s, ol->list[k].y_pos_e+1, ol->list[k].shared_seed, ol->list[k].align_length, ha_ov_type(&(ol->list[k]), rl)); + int64_t km; + for (km = ol->list[k].non_homopolymer_errors; (km < cl->length) && (cl->list[km].readID == cl->list[ol->list[k].non_homopolymer_errors].readID); km++) { + fprintf(stderr, "[M::%s::] qpos::%u, tpos::%u, cnt::%u\n", __func__, cl->list[km].self_offset, cl->list[km].offset, cl->list[km].cnt>>8); + } + fprintf(stderr, "[M::%s::]\tk::%lu\tsi::%u\tei::%ld\n", __func__, k, ol->list[k].non_homopolymer_errors, km); + } + } + **/ + + + // gen_chain_clus(ab, ol, cl, v32); + if(is_raw_chain) return; + + + k = ol->length; + if (ol->length > max_n_chain) { + int32_t w, n[4], s[4]; + n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; + ks_introsort_or_ss(ol->length, ol->list); + for (i = 0; i < ol->length; ++i) { + r = &(ol->list[i]); + w = ha_ov_type(r, rl); + ++n[w]; + if (((uint64_t)n[w]) == max_n_chain) s[w] = r->shared_seed; + } + /**fprintf(stderr, "top[M::%s::] s[0]::%d, s[1]::%d, s[2]::%d, s[3]::%d\n", __func__, s[0], s[1], s[2], s[3]);**/ + if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { + if((((uint64_t)n[3]) >= max_n_chain) && (rl >= ocv_w)) { + cwn = (rl/ocv_w) + ((rl % ocv_w)?(1):(0)); + kv_resize(uint64_t, (*sp), (cwn)); + cc = sp->a; + for (i = cws = cwe = 0; i < cwn; i++) { + cwe = cws + ocv_w; if(cwe > rl) cwe = rl; + assert(cwe > cws); + cc[i] = (cwe - cws)*(max_n_chain>>1); + // fprintf(stderr, "[M::%s::] cw::[%lu, %lu), cc::%lu\n", __func__, cws, cwe, cc[i]); + if(cc[i] > UINT32_MAX) {cc[i] = UINT32_MAX;} cc[i] <<= 32; + cws += ocv_w; + } + } + for (i = 0, k = 0, lch = 0; i < ol->length; ++i) { + r = &(ol->list[i]); + w = ha_ov_type(r, rl); + // ++n[w]; + // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { + if (r->shared_seed >= s[w]) { + if(cwn) { + m = (ol->list[i].x_pos_s/ocv_w); + rs = ol->list[i].x_pos_s; re = ol->list[i].x_pos_e + 1; + for (cws = m*ocv_w; m < cwn; m++) { + cwe = cws + ocv_w; if(cwe > rl) cwe = rl; + os = ((rs >= cws)? rs : cws); + oe = ((re <= cwe)? re : cwe); + if(oe <= os) break; + if(((uint32_t)cc[m]) + (oe - os) < UINT32_MAX) { + cc[m] += (oe - os); + } else { + cc[m] >>= 32; cc[m] <<= 32; cc[m] |= UINT32_MAX; + } + cws += ocv_w; + } + } + if (k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + if(ol->list[k].align_length < chain_cutoff) lch = 1; + ++k; + } else if(w == 3 && cwn > 0) { + m = (ol->list[i].x_pos_s/ocv_w); cw0 = cw1 = 0; + rs = ol->list[i].x_pos_s; re = ol->list[i].x_pos_e + 1; + for (cws = m*ocv_w; m < cwn; m++) { + cwe = cws + ocv_w; if(cwe > rl) cwe = rl; + os = ((rs >= cws)? rs : cws); + oe = ((re <= cwe)? re : cwe); + if(oe <= os) break; + // fprintf(stderr, "+++[M::%s::%.*s(qid::%u)] o[%lu, %lu), cur::%lu, max::%lu\n", __func__, + // (int32_t)Get_NAME_LENGTH(R_INF, ol->list[i].y_id), Get_NAME(R_INF, ol->list[i].y_id), ol->list[i].y_id, + // os, oe, ((uint64_t)((uint32_t)cc[m])), (cc[m]>>32)); + if((oe - os) + ((uint64_t)((uint32_t)cc[m])) >= (cc[m]>>32)) { + cw1 += (oe - os); + } else { + cw0 += (oe - os); + } + cws += ocv_w; + } + + if(cw0 >= ((cw0 + cw1)*0.7)) { + m = (ol->list[i].x_pos_s/ocv_w); + rs = ol->list[i].x_pos_s; re = ol->list[i].x_pos_e + 1; + for (cws = m*ocv_w; m < cwn; m++) { + cwe = cws + ocv_w; if(cwe > rl) cwe = rl; + os = ((rs >= cws)? rs : cws); + oe = ((re <= cwe)? re : cwe); + if(oe <= os) break; + if(((uint32_t)cc[m]) + (oe - os) < UINT32_MAX) { + cc[m] += (oe - os); + } else { + cc[m] >>= 32; cc[m] <<= 32; cc[m] |= UINT32_MAX; + } + cws += ocv_w; + } + if (k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + if(ol->list[k].align_length < chain_cutoff) lch = 1; + ++k; + // dbgn++; + // fprintf(stderr, "+++[M::%s::%.*s(qid::%u)] q[%d, %d), t[%d, %d), sc::%d, type::%d, cw0::%lu, cw1::%lu\n", __func__, + // (int32_t)Get_NAME_LENGTH(R_INF, ol->list[k].y_id), Get_NAME(R_INF, ol->list[k].y_id), ol->list[k].y_id, + // ol->list[k].x_pos_s, ol->list[k].x_pos_e+1, ol->list[k].y_pos_s, ol->list[k].y_pos_e+1, ol->list[k].shared_seed, ha_ov_type(&(ol->list[k]), rl), cw0, cw1); + } + } + } + ol->length = k; + } + } + + ks_introsort_or_xs(ol->length, ol->list); + if(lch) { + //@brief r485 + uint64_t zs, ze, rs, re, ob, os, oe, ocn, pp, kn, ms, me; int64_t osc; + for (i = l = 0, cn = cl->length; i < ol->length; ++i) { + if(ol->list[i].align_length < chain_cutoff) { + zs = ol->list[i].x_pos_s; ze = ol->list[i].x_pos_e + 1; + ob = (ze - zs)*OFL; if(ob < 16) ob = 16; + osc = ol->list[i].shared_seed*CH_SC; + ocn = ol->list[i].align_length<length) && (ze > ol->list[k].x_pos_s); k++) { + if(ol->list[k].align_length < chain_cutoff) continue; + if(ol->list[k].align_length < ocn) continue; + if(ol->list[k].shared_seed < osc) continue; + rs = ol->list[k].x_pos_s; re = ol->list[k].x_pos_e + 1; + os = ((rs>=zs)?rs:zs); oe = ((re<=ze)?re:ze); + if((oe > os) && (oe - os) >= ob) { + m = ol->list[k].non_homopolymer_errors; + pp = cl->list[m].readID; kn = 0; + for (; (m < cn) && (cl->list[m].readID == pp) && (kn < ocn); m++) { + me = cl->list[m].self_offset; ms = me - (cl->list[m].cnt&(0xffu)); + if((ms >= os) && (me <= oe)) kn++; + } + if(kn >= ocn) break; + } + } + if((k < ol->length) && (ze > ol->list[k].x_pos_s)) continue; + } + if (l != i) { + t = ol->list[l]; + ol->list[l] = ol->list[i]; + ol->list[i] = t; + } + l++; + } + ol->length = l; + } + + for (i = 0; i < ol->length; ++i) ol->list[i].align_length = 0; + // fprintf(stderr, "+[M::%s] rid::%u, ol->length0::%lu, dbgn::%lu\n", __func__, rid, ol->length, dbgn); +} + +void srt_olst(overlap_region_alloc* ol) +{ + ks_introsort_or_xs(ol->length, ol->list); +} + +void lchain_qgen_mcopy_fast_re1(Candidates_list* cl, uint32_t cl_beg, overlap_region_alloc* ol, uint32_t rid, uint64_t rl, uint64_t tl, + uint32_t apend_be, int64_t max_skip, int64_t max_iter, + int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, int64_t quick_check, + uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut) +{ + uint64_t cn = cl->length, m = cl_beg; + if(cl_beg >= cn) return; + + m += lchain_qdp_mcopy_fast(cl, cl_beg, cn - cl_beg, m, &(cl->chainDP), ol, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, + rid, rl, tl, quick_check, apend_be, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, 1); + cl->length = m; +} + +inline uint64_t special_lchain(Candidates_list* cl, overlap_region_alloc* ol, uint32_t rid, uint64_t rl, All_reads* rdb, + const ul_idx_t *udb, uint32_t apend_be, int64_t max_skip, int64_t max_iter, int64_t max_dis, double chn_pen_gap, + double chn_pen_skip, double bw_rate, int64_t quick_check, uint32_t gen_off, double mcopy_rate, uint32_t mcopy_khit_cut, + st_mt_t *sp, uint64_t *si, uint64_t m, uint64_t l, uint64_t k) +{ + uint64_t z, s, e, yid, ol0 = ol->length, ol1, m0 = m; + if(l >= k) return m; + yid = cl->list[l].readID; + for (z = l; z < k && cl->list[z].strand == cl->list[l].strand; z++); + if(z > l) { + s = l; e = z; ol1 = ol->length; // m0 = m; + m += lchain_qdp_mcopy(cl, s, e-s, m, &(cl->chainDP), ol, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, + rid, rl, rdb?Get_READ_LENGTH((*rdb), yid):udb->ug->u.a[yid].len, quick_check, apend_be, gen_off, 0, mcopy_rate, mcopy_khit_cut, 0); + // if(rid == 7) { + // fprintf(stderr, "+[M::%s::utg%.6ul] inn::[%lu, %lu), (*si)::%lu, ol1::%lu, ol->length::%lu\n", + // __func__, rid+1, s, e, (*si), ol1, ol->length); + // } + if(((*si) < sp->n) && (sp->a[(*si)] == s) && (ol->length > ol1)) { + ol->list[ol->length-1].x_pos_strand = 1; + // fprintf(stderr, "+[M::%s] utg%.6u%c -> utg%.6u%c, n_khits0::%lu, n_khits::%lu\n", __func__, rid+1, "lc"[udb->ug->u.a[rid].circ], + // ol->list[ol->length-1].y_id+1, "lc"[udb->ug->u.a[ol->list[ol->length-1].y_id].circ], e-s, m-m0); + } + for (; (*si) < sp->n && sp->a[(*si)] == s; (*si)++); + } + + if(z < k) { + s = z; e = k; ol1 = ol->length; // m0 = m; + m += lchain_qdp_mcopy(cl, s, e-s, m, &(cl->chainDP), ol, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, + rid, rl, rdb?Get_READ_LENGTH((*rdb), yid):udb->ug->u.a[yid].len, quick_check, apend_be, gen_off, 0, mcopy_rate, mcopy_khit_cut, 0); + // if(rid == 7) { + // fprintf(stderr, "-[M::%s::utg%.6ul] inn::[%lu, %lu), (*si)::%lu, ol1::%lu, ol->length::%lu\n", + // __func__, rid+1, s, e, (*si), ol1, ol->length); + // } + if(((*si) < sp->n) && (sp->a[(*si)] == s) && (ol->length > ol1)) { + ol->list[ol->length-1].x_pos_strand = 1; + // fprintf(stderr, "-[M::%s] utg%.6u%c -> utg%.6u%c, n_khits0::%lu, n_khits::%lu\n", __func__, rid+1, "lc"[udb->ug->u.a[rid].circ], + // ol->list[ol->length-1].y_id+1, "lc"[udb->ug->u.a[ol->list[ol->length-1].y_id].circ], e-s, m-m0); + } + for (; (*si) < sp->n && sp->a[(*si)] == s; (*si)++); + } + if(ol->length > ol0) { + overlap_region *p = &(ol->list[ol0]); uint64_t pi = ol0; overlap_region t; + for (z = ol0; z < ol->length; z++) { + if((p->shared_seed < ol->list[z].shared_seed) || + ((p->shared_seed == ol->list[z].shared_seed) && (ol->list[z].x_pos_strand == 1))) { + p = &(ol->list[z]); pi = z; + } + } + + // if(rid == 7) { + // fprintf(stderr, ">[M::%s::] utg%.6ul\t->\tutg%.6ul\tflag::%u\n", + // __func__, p->x_id+1, p->y_id+1, p->x_pos_strand); + // } + + for (z = s = ol0; z < ol->length; z++) { + if((ol->list[z].x_pos_strand == 0) && (z != pi)) continue; + if(s != z) { + t = ol->list[s]; + ol->list[s] = ol->list[z]; + ol->list[z] = t; + } + s++; + } + + if(s != ol->length) { + ol->length = s; + for (z = ol0; z < ol->length; z++) { + s = ol->list[z].non_homopolymer_errors; + pi = cl->list[s].readID; + ol->list[z].non_homopolymer_errors = m0; + for (; s < m && cl->list[s].readID == pi; s++) { + cl->list[m0] = cl->list[s]; + cl->list[m0].readID = z; m0++; + } + } + m = m0; + } + + } + return m; +} + +void lchain_qgen_mcopy_input(Candidates_list* cl, overlap_region_alloc* ol, uint32_t rid, uint64_t rl, All_reads* rdb, + const ul_idx_t *udb, uint32_t apend_be, uint64_t max_n_chain, int64_t max_skip, int64_t max_iter, + int64_t max_dis, double chn_pen_gap, double chn_pen_skip, double bw_rate, double bw_thres_sec, + int64_t quick_check, uint32_t gen_off, double mcopy_rate, uint32_t mcopy_khit_cut, st_mt_t *sp) +{ + // fprintf(stderr, "+[M::%s]\n", __func__); + uint64_t i, k, l, m, cn = cl->length, yid, si; overlap_region *r; ///srt = 0 + clear_overlap_region_alloc(ol); + + // if(rid == 160) { + // fprintf(stderr, "[M::%s::utg%.6ul] sp->n::%u\n", __func__, rid+1, (uint32_t)sp->n); + // } + for (l = 0, k = 1, m = 0, si = 0; k <= cn; k++) { + if((k == cn) || (cl->list[k].readID != cl->list[l].readID)) { + if(cl->list[l].readID != rid) { + yid = cl->list[l].readID; + // if(rid == 160) { + // fprintf(stderr, "+[M::%s::utg%.6lul] [%lu, %lu), m::%lu, ol->length::%lu\n", __func__, yid+1, l, k, m, ol->length); + // } + for (; si < sp->n && sp->a[si] < l; si++); + if(si >= sp->n || sp->a[si] >= k) {///might be unmatched + m += lchain_qdp_mcopy(cl, l, k-l, m, &(cl->chainDP), ol, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_rate, + rid, rl, rdb?Get_READ_LENGTH((*rdb), yid):udb->ug->u.a[yid].len, quick_check, apend_be, gen_off, 0, mcopy_rate, mcopy_khit_cut, 0); + } else { + m = special_lchain(cl, ol, rid, rl, rdb, udb, apend_be, max_skip, max_iter, max_dis, chn_pen_gap, + chn_pen_skip, bw_thres_sec, quick_check, gen_off, mcopy_rate, mcopy_khit_cut, sp, &si, m, l, k); + } + // if(rid == 160) { + // fprintf(stderr, "-[M::%s::utg%.6lul] [%lu, %lu), m::%lu, ol->length::%lu\n", __func__, yid+1, l, k, m, ol->length); + // } + } + l = k; + } + } + cl->length = m; + + // for (k = 0; k < ol->length; k++) { + // fprintf(stderr, "---[M::%s::utg%.6dl] q[%d, %d), t[%d, %d), khit_off::%u\n", __func__, + // (int32_t)ol->list[k].y_id+1, ol->list[k].x_pos_s, ol->list[k].x_pos_e+1, + // ol->list[k].y_pos_s, ol->list[k].y_pos_e+1, ol->list[k].non_homopolymer_errors); + // } + + k = ol->length; + if (ol->length > max_n_chain) { + int32_t w, n[4], s[4]; overlap_region t; + n[0] = n[1] = n[2] = n[3] = 0, s[0] = s[1] = s[2] = s[3] = 0; + ks_introsort_or_ss(ol->length, ol->list); ///srt = 1; + for (i = 0; i < ol->length; ++i) { + r = &(ol->list[i]); + w = ha_ov_type(r, rl); + ++n[w]; + if (((uint64_t)n[w]) == max_n_chain) s[w] = r->shared_seed; + } + if (s[0] > 0 || s[1] > 0 || s[2] > 0 || s[3] > 0) { + // n[0] = n[1] = n[2] = n[3] = 0; + for (i = 0, k = 0; i < ol->length; ++i) { + r = &(ol->list[i]); + w = ha_ov_type(r, rl); + // ++n[w]; + // if (((int)n[w] <= max_n_chain) || (r->shared_seed >= s[w] && s[w] >= (asm_opt.k_mer_length<<1))) { + if ((r->shared_seed >= s[w]) || (r->x_pos_strand == 1)) { + if (k != i) { + t = ol->list[k]; + ol->list[k] = ol->list[i]; + ol->list[i] = t; + } + ++k; + } + } + ol->length = k; + } + } + ks_introsort_or_xs(ol->length, ol->list); +} + +void set_lchain_dp_op(uint32_t is_accurate, uint32_t mz_k, int64_t *max_skip, int64_t *max_iter, int64_t *max_dis, double *chn_pen_gap, double *chn_pen_skip, int64_t *quick_check) +{ + double div, pen_gap, pen_skip, tmp; + if(is_accurate) { + (*quick_check) = 1; (*max_skip) = 25; (*max_iter) = 5000; (*max_dis) = 5000; div = 0.01; pen_gap = 0.5f; pen_skip = 0.0005f; + } else { + (*quick_check) = 0; (*max_skip) = 25; (*max_iter) = 5000; (*max_dis) = 5000; div = 0.1; pen_gap = 0.5f; pen_skip = 0.0005f; + } + tmp = expf(-div * (double)mz_k);///0.60049557881 -> HiFi; 0.18268352405 -> ont + *chn_pen_gap = pen_gap * tmp;///0.300247789405 -> HiFi; 0.091341762025 -> ont + ///0.000300247789405 -> HiFi (>3330 will be negative); + //0.000091341762025 -> ont (>10947 will be negative); + *chn_pen_skip = pen_skip * tmp; +} + +void ul_map_lchain(ha_abufl_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, + int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut) +{ + extern void *ha_flt_tab; + extern ha_pt_t *ha_idx; + int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; + set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); + // minimizers_gen(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, dbg_ct, sp, high_occ, low_occ); + minimizers_qgen(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, NULL, uref, dbg_ct, sp, high_occ, low_occ); + // lchain_gen(cl, overlap_list, rid, rl, NULL, uref, apend_be, f_cigar, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off); + // lchain_qgen(cl, overlap_list, rid, rl, NULL, uref, apend_be, f_cigar, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off); + ///no need to sort here, overlap_list has been sorted at lchain_gen + lchain_qgen_mcopy(cl, overlap_list, rid, rl, NULL, uref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off, mcopy_rate, chain_cutoff, mcopy_khit_cut, sp); +} + +void h_ec_lchain(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, + int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t mcopy_num, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut, uint64_t ocv_w, uint8_t is_raw_chain) +{ + extern void *ha_flt_tab; + extern ha_pt_t *ha_idx; + int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; + set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); + // minimizers_gen(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, dbg_ct, sp, high_occ, low_occ); + minimizers_qgen0(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, rref, dbg_ct, sp, high_occ, low_occ, ((uint64_t)-1)); + // lchain_gen(cl, overlap_list, rid, rl, NULL, uref, apend_be, f_cigar, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off); + // lchain_qgen(cl, overlap_list, rid, rl, NULL, uref, apend_be, f_cigar, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off); + ///no need to sort here, overlap_list has been sorted at lchain_gen + lchain_qgen_mcopy_fast(ab, cl, overlap_list, rid, rl, rref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, cl->length, bw_thres, 0, quick_check, gen_off, mcopy_num, mcopy_rate, chain_cutoff, mcopy_khit_cut, sp, ocv_w, is_raw_chain); +} + +void h_ec_lchain_hybrid(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres_h, double bw_thres_l, + int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t mcopy_num, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut, uint64_t ocv_w, uint64_t ti_cut, uint8_t is_raw_chain) +{ + extern void *ha_flt_tab; + extern ha_pt_t *ha_idx; + int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; uint64_t tcut_n = 0; + set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); + // minimizers_gen(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, dbg_ct, sp, high_occ, low_occ); + tcut_n = minimizers_qgen0(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, rref, dbg_ct, sp, high_occ, low_occ, ti_cut); + // lchain_gen(cl, overlap_list, rid, rl, NULL, uref, apend_be, f_cigar, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off); + // lchain_qgen(cl, overlap_list, rid, rl, NULL, uref, apend_be, f_cigar, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off); + ///no need to sort here, overlap_list has been sorted at lchain_gen + lchain_qgen_mcopy_fast(ab, cl, overlap_list, rid, rl, rref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres_h, tcut_n, bw_thres_l, cl->length - tcut_n, quick_check, gen_off, mcopy_num, mcopy_rate, chain_cutoff, mcopy_khit_cut, sp, ocv_w, is_raw_chain); +} + +void h_ec_lchain_amz(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, + int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut, uint64_t ocv_w) +{ + extern void *ha_flt_tab; + extern ha_pt_t *ha_idx; + int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; + set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); + // minimizers_gen(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, dbg_ct, sp, high_occ, low_occ); + minimizers_qgen0_amz(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, rref, dbg_ct, sp, high_occ, low_occ); + // lchain_gen(cl, overlap_list, rid, rl, NULL, uref, apend_be, f_cigar, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off); + // lchain_qgen(cl, overlap_list, rid, rl, NULL, uref, apend_be, f_cigar, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off); + ///no need to sort here, overlap_list has been sorted at lchain_gen + lchain_qgen_mcopy_fast(ab, cl, overlap_list, rid, rl, rref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, cl->length, bw_thres, 0, quick_check, gen_off, enable_mcopy, mcopy_rate, chain_cutoff, mcopy_khit_cut, sp, ocv_w, 0); +} + +uint64_t recalu_minimizer0(char *s, uint64_t len, uint64_t is_hpc, int64_t mz_k, uint64_t mz_h, tiny_queue_t *tq, uint64_t *rpos, uint64_t *rspan) +{ + uint64_t k, l, shift1 = mz_k - 1, mask = (1ULL<front = tq->count = 0; + for (k = 1, l = 0, mz_l = mz_span = 0; k <= len; ++k) { + if (k == len || seq_nt4_table[(uint8_t)s[k]] != seq_nt4_table[(uint8_t)s[l]]) { + c = seq_nt4_table[(uint8_t)s[l]]; + if(c < 4) { + kmer[0] = (kmer[0] << 1 | (c&1)) & mask;/**forward k-mer**/ + kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; + kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; /**reverse k-mer**/ + kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; + if (kmer[1] == kmer[3]) continue; /** skip "symmetric k-mers" as we don't know it strand**/ + z = kmer[1] < kmer[3]? 0 : 1; /** strand**/ + mz_l++; mz_span += (k - l); + tq_push(tq, k - l); if (tq->count > mz_k) mz_span -= tq_shift(tq); + if(mz_l >= mz_k && mz_span < 256) { + hs = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); + if(mz_h == hs) { + (*rpos) = k - 1; (*rspan) = mz_span; + return 1; + } + } + } else { + mz_l = mz_span = 0; + } + + l = k; + } + } + } else { + for (k = 0, mz_l = mz_span = 0; k < len; ++k) { + c = seq_nt4_table[(uint8_t)s[k]]; + if(c < 4) { + kmer[0] = (kmer[0] << 1 | (c&1)) & mask;/**forward k-mer**/ + kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; + kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; /**reverse k-mer**/ + kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; + if (kmer[1] == kmer[3]) continue; /** skip "symmetric k-mers" as we don't know it strand**/ + z = kmer[1] < kmer[3]? 0 : 1; /** strand**/ + mz_l++; mz_span++; if(mz_span > mz_k) mz_span = mz_k; + if(mz_l >= mz_k) { + hs = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); + if(mz_h == hs) { + (*rpos) = k; (*rspan) = mz_span; + return 1; + } + } + } else { + mz_l = mz_span = 0; + } + } + } + + return 0; +} + +uint64_t recalu_minimizer0_adv(char *s, uint64_t len, uint64_t is_hpc, int64_t mz_k, uint64_t mz_h, uint64_t rev, tiny_queue_t *tq, uint64_t *rpos, uint64_t *rspan) +{ + uint64_t k, l, shift1 = mz_k - 1, mask = (1ULL<front = tq->count = 0; + for (k = 1, l = 0, mz_l = mz_span = 0; k <= len; ++k) { + if (k == len || seq_nt4_table[(uint8_t)s[k]] != seq_nt4_table[(uint8_t)s[l]]) { + c = seq_nt4_table[(uint8_t)s[l]]; + if(c < 4) { + kmer[0] = (kmer[0] << 1 | (c&1)) & mask;/**forward k-mer**/ + kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; + kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; /**reverse k-mer**/ + kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; + if (kmer[1] == kmer[3]) continue; /** skip "symmetric k-mers" as we don't know it strand**/ + z = kmer[1] < kmer[3]? 0 : 1; /** strand**/ + mz_l++; mz_span += (k - l); + tq_push(tq, k - l); if (tq->count > mz_k) mz_span -= tq_shift(tq); + if(mz_l >= mz_k && mz_span < 256) { + hs = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); + if(mz_h == hs) { + (*rpos) = k - 1; (*rspan) = mz_span; + return 1; + } + } + } else { + mz_l = mz_span = 0; + } + + l = k; + } + } + } else { + for (k = 0, mz_l = mz_span = 0; k < len; ++k) { + c = seq_nt4_table[(uint8_t)s[k]]; + if(c < 4) { + kmer[0] = (kmer[0] << 1 | (c&1)) & mask;/**forward k-mer**/ + kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; + kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; /**reverse k-mer**/ + kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; + if (kmer[1] == kmer[3]) continue; /** skip "symmetric k-mers" as we don't know it strand**/ + z = kmer[1] < kmer[3]? 0 : 1; /** strand**/ + mz_l++; mz_span++; if(mz_span > mz_k) mz_span = mz_k; + if(mz_l >= mz_k) { + hs = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); + if(mz_h == hs) { + (*rpos) = k; (*rspan) = mz_span; + return 1; + } + } + } else { + mz_l = mz_span = 0; + } + } + } + } else { + uint8_t ch[5] = {3, 2, 1, 0, 5}; + if(is_hpc) { + tq->front = tq->count = 0; + for (k = 1, l = 0, mz_l = mz_span = 0; k <= len; ++k) { + if (k == len || seq_nt4_table[(uint8_t)s[len-k-1]] != seq_nt4_table[(uint8_t)s[len-l-1]]) { + c = ch[seq_nt4_table[(uint8_t)s[len-l-1]]]; + if(c < 4) { + kmer[0] = (kmer[0] << 1 | (c&1)) & mask;/**forward k-mer**/ + kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; + kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; /**reverse k-mer**/ + kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; + if (kmer[1] == kmer[3]) continue; /** skip "symmetric k-mers" as we don't know it strand**/ + z = kmer[1] < kmer[3]? 0 : 1; /** strand**/ + mz_l++; mz_span += (k - l); + tq_push(tq, k - l); if (tq->count > mz_k) mz_span -= tq_shift(tq); + if(mz_l >= mz_k && mz_span < 256) { + hs = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); + if(mz_h == hs) { + (*rpos) = k - 1; (*rspan) = mz_span; + return 1; + } + } + } else { + mz_l = mz_span = 0; + } + + l = k; + } + } + } else { + for (k = 0, mz_l = mz_span = 0; k < len; ++k) { + c = ch[seq_nt4_table[(uint8_t)s[len-k-1]]]; + if(c < 4) { + kmer[0] = (kmer[0] << 1 | (c&1)) & mask;/**forward k-mer**/ + kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; + kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; /**reverse k-mer**/ + kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; + if (kmer[1] == kmer[3]) continue; /** skip "symmetric k-mers" as we don't know it strand**/ + z = kmer[1] < kmer[3]? 0 : 1; /** strand**/ + mz_l++; mz_span++; if(mz_span > mz_k) mz_span = mz_k; + if(mz_l >= mz_k) { + hs = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); + if(mz_h == hs) { + (*rpos) = k; (*rspan) = mz_span; + return 1; + } + } + } else { + mz_l = mz_span = 0; + } + } + } + } + + return 0; +} + + +uint64_t recalu_minimizer(uint64_t rid, anchor1_t *z, asg16_v *sc, int64_t *iok, int64_t *ink, int64_t *ick, int64_t *str_s, int64_t *str_e, uint64_t mz_k, uint64_t mz_h, tiny_queue_t *tq, All_reads *rref, UC_Read *tu, char *qstr, uint64_t qs, uint64_t qe) +{ + int64_t id = z->srt>>33; char *str = NULL; uint64_t rpos, rspan; + int64_t ok = *iok, nk = *ink, ck = *ick, cn = sc->n, s0, e0, s1, e1, os, oe, ots, ote, ol, wo[2], wn[2], weo[2], wen[2], ovlp, len = Get_READ_LENGTH((*rref), id); uint16_t op, bq, bt; uint32_t cl; + e0 = ((uint32_t)z->srt) + 1; s0 = e0 - z->other_off; s1 = e1 = -1; weo[0] = weo[1] = wen[0] = wen[1] = -1; + if(e0 <= s0) return 0; + + ///debug + // ok = nk = ck = 0; + + if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed + ck = ok = nk = 0; + } + + // if(id == 1/**s0 == 10260 && e0 == 10334**/) { + // fprintf(stderr, "\n\n-0-qk::%ld,\ttk::%ld,\tck::%ld,\ts0::%ld,\te0::%ld\n", ok, nk, ck, s0, e0); + // } + + while (ck > 0 && ok >= s0) {///x -> t; y -> p; first insertion and then match/mismatch + --ck; + op = sc->a[ck]>>14; + // ol = (((op == 1) || (op == 2))?(sc->a[ck]&(0xfff)):(sc->a[ck]&(0x3fff))); + if((op == 2) || (op == 3)) { + ol = sc->a[ck]&(0xfff); + } else if(op == 1) { + ol = sc->a[ck]&(0x3ff); + } else { + ol = sc->a[ck]&(0x3fff); + } + if(op != 2) ok -= ol; + if(op != 3) nk -= ol; + } + + // char cm[4]; cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; + // if(id == 1/**s0 == 10260 && e0 == 10334**/) { + // fprintf(stderr, "-1-qk::%ld,\ttk::%ld,\tck::%ld\n", ok, nk, ck); + // } + + while (ck < cn && ok < e0) { ///[s0, e0) + wo[0] = ok; wn[0] = nk; + // ck = pop_trace_bp(sc, ck, &op, &b, &cl); + ck = pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); + if(op != 2) ok += cl; + if(op != 3) nk += cl; + wo[1] = ok; wn[1] = nk; + + os = ((s0 >= wo[0])? s0 : wo[0]); + oe = ((e0 <= wo[1])? e0 : wo[1]); + // os = MAX(s0, wo[0]); oe = MIN(e0, wo[1]); + ovlp = ((oe>os)? (oe-os):0); + // if(id == 1/**s0 == 10260 && e0 == 10334**/) { + // fprintf(stderr, "%u%c(q::[%ld,%ld))(t::[%ld,%ld))(ck::%ld)\n", cl, cm[op], wo[0], wo[1], wn[0], wn[1], ck); + // } + + if(op != 2) { + if(!ovlp) continue; + } else {///wo[0] == wo[1] + if(wo[0] < s0 || wo[0] >= e0) continue; + } + + if(op < 2) { + ots = os - wo[0] + wn[0]; ote = oe - wo[0] + wn[0]; + } else {///op == 2: more y; p == 3: more x + ots = wn[0]; ote = wn[1]; + } + + if(s1 == -1) s1 = ots; + e1 = ote; + + if((op == 0) && (ovlp > 0) && (ovlp > weo[1] - weo[0])) { + weo[0] = os; weo[1] = oe; + wen[0] = ots; wen[1] = ote; + } + } + + while (ck < cn && ok <= e0) { ///[s0, e0) + wo[0] = ok; wn[0] = nk; + // pop_trace_bp(sc, ck, &op, &b, &cl); + pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); + if(op != 2) break; + // ck = pop_trace_bp(sc, ck, &op, &b, &cl); + ck = pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); + // if(op != 2) ok += cl; + // if(op != 3) nk += cl; + nk += cl; + wo[1] = ok; wn[1] = nk; + + // if(id == 1/**s0 == 10260 && e0 == 10334**/) { + // fprintf(stderr, "%u%c(q::[%ld,%ld))(t::[%ld,%ld))(ck::%ld)\n", cl, cm[op], wo[0], wo[1], wn[0], wn[1], ck); + // } + + if(wo[0] >= s0 && wo[0] <= e0) { + ots = wn[0]; ote = wn[1]; + if(s1 == -1) s1 = ots; + e1 = ote; + } + } + + assert(wen[1] <= len); + assert(e1 <= len); + + *iok = ok; *ink = nk; *ick = ck; + + if(weo[0] == s0 && weo[1] == e0) { + z->srt >>= 32; z->srt <<= 32; z->srt |= ((uint64_t)(wen[1]-1)); + ///debug + // char sstr[256]; recover_UC_Read_sub_region(sstr, wen[0], wen[1] - wen[0], 0, rref, id); + // if(recalu_minimizer0(sstr, wen[1] - wen[0], !(asm_opt.flag & HA_F_NO_HPC), mz_k, mz_h, tq, &rpos, &rspan) && (rpos + 1 == ((uint64_t)(wen[1] - wen[0]))) && (((uint64_t)(wen[1] - wen[0])) == rspan)) { + // // fprintf(stderr, "-0-[M::%s]\n", __func__); + // } else { + // // if(((z->srt>>32)&1) == 0) { + // fprintf(stderr, "-1-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], wen[0], wen[1], s0, e0, e0 - s0); + // fprintf(stderr, "tstr::%.*s\n", ((uint32_t)(wen[1] - wen[0])), sstr); + // fprintf(stderr, "qstr::%.*s\n", ((uint32_t)(qe - qs)), qstr + qs); + // exit(1); + // // } + // } + // if(rid == 3196 && id == 3199) fprintf(stderr, "-full-[M::%s]\n", __func__); + return 1; + } + + if(e1 <= s1) return 0; + + + + if(s1 >= (*str_s) && e1 <= (*str_e)) { + str = tu->seq + s1 - (*str_s); + } else { + if(s1 >= (*str_s) && (s1 < (*str_e)) && (e1 > (*str_e))) { + UC_Read_resize((*tu), (e1 - (*str_s))); + recover_UC_Read_sub_region(tu->seq + (*str_e) - (*str_s), (*str_e), e1 - (*str_e), 0, rref, id); + str = tu->seq + s1 - (*str_s); (*str_e) = e1; + } else { + UC_Read_resize((*tu), (e1 - s1)); + recover_UC_Read_sub_region(tu->seq, s1, e1 - s1, 0, rref, id); + str = tu->seq; (*str_s) = s1; (*str_e) = e1; + } + } + + if(recalu_minimizer0(str, e1 - s1, !(asm_opt.flag & HA_F_NO_HPC), mz_k, mz_h, tq, &rpos, &rspan)) { + rpos += s1; + z->srt >>= 32; z->srt <<= 32; z->srt |= rpos; z->other_off = rspan; + // fprintf(stderr, "-1-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], s1, e1, s0, e0, e0 - s0); + // if(rid == 3196 && id == 3199) fprintf(stderr, "-part-[M::%s]\n", __func__); + return 1; + } + // fprintf(stderr, "-0-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], s1, e1, s0, e0, e0 - s0); + + return 0; +} + +int64_t hpc_minimizer_test(int64_t id, All_reads *rref, UC_Read *bu, int64_t str_s, int64_t str_e, int64_t z, int64_t len, int64_t rev, int64_t step) +{ + if(z < 0 || z >= len) return 0; + if(z == 0 && rev == 1) return 0; + if(z == len - 1 && rev == 0) return 0; + + int64_t an, sc, ec, k, tn = 0; char c = 0, *a = NULL; + if(z >= str_s && z < str_e) c = bu->seq[z-str_s]; + + if(rev) { + if(c != 0) { + if(z > str_s) { + a = bu->seq; an = z - str_s; + for (k = an - 1; k >= 0 && a[k] == c; k--); + tn += an - k - 1; + if((k >= 0) || (z - tn == 0)) return tn; + ec = str_s; + } else { + ec = z; + } + } else { + ec = z + 1; + } + + sc = ec - step; if(sc < 0) sc = 0; + if(ec <= 0 || ec > len || ec <= sc) return tn; + + UC_Read_resize((*bu), (str_e - str_s) + (step)); + a = bu->seq + str_e - str_s; + + while (1) { + recover_UC_Read_sub_region(a, sc, ec - sc, 0, rref, id); an = ec - sc; + if(c == 0) c = a[--an]; + for (k = an - 1; k >= 0 && a[k] == c; k--); + tn += an - k - 1; + if((k >= 0) || (z - tn == 0)) return tn; + ec = sc; + sc = ec - step; if(sc < 0) sc = 0; + if(ec <= 0 || ec > len || ec <= sc) return tn; + } + } else { + if(c != 0) { + if(z + 1 < str_e) { + a = bu->seq + z + 1 - str_s; an = str_e - z - 1; + for (k = 0; k < an && a[k] == c; k++); + tn += k; + if((k < an) || (z + tn + 1 == len)) return tn; + sc = str_e; + } else { + sc = z + 1; + } + } else { + sc = z; + } + + ec = sc + step; if(ec > len) ec = len; + if(sc < 0 || sc >= len || sc >= ec) return tn; + + UC_Read_resize((*bu), (str_e - str_s) + (step)); + a = bu->seq + str_e - str_s; + + while (1) { + // if(bu->size < (a - bu->seq) + (ec - sc)) { + // fprintf(stderr, "-1-[M::%s]\tid::%ld\n", __func__, id); + // } + recover_UC_Read_sub_region(a, sc, ec - sc, 0, rref, id); an = ec - sc; + a = bu->seq + str_e - str_s; + if(c == 0) { + c = a[0]; a = a + 1; an--; + } + for (k = 0; k < an && a[k] == c; k++); + tn += k; + if((k < an) || (z + tn + 1 == len)) return tn; + sc = ec; + ec = sc + step; if(ec > len) ec = len; + if(sc < 0 || sc >= len || sc >= ec) return tn; + } + } +} + +uint64_t recalu_minimizer_bd(uint64_t rid, anchor1_t *z, asg16_v *sc, int64_t *iok, int64_t *ink, int64_t *ick, int64_t *str_s, int64_t *str_e, uint64_t mz_k, uint64_t mz_h, tiny_queue_t *tq, All_reads *rref, UC_Read *tu, char *qstr, uint64_t qs, uint64_t qe) +{ + int64_t id = z->srt>>33; char *str = NULL; uint64_t rpos, rspan; + int64_t ok = *iok, nk = *ink, ck = *ick, cn = sc->n, s0, e0, s1, e1, si, ei, os, oe, ots, ote, ol, wo[2], wn[2], weo[2], wen[2], ovlp, len = Get_READ_LENGTH((*rref), id); uint16_t op, bq, bt; uint32_t cl; + e0 = ((uint32_t)z->srt) + 1; s0 = e0 - z->other_off; s1 = e1 = si = ei = -1; weo[0] = weo[1] = wen[0] = wen[1] = -1; + if(e0 <= s0) return 0; + + ///debug + // ok = nk = ck = 0; + + if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed + ck = ok = nk = 0; + } + + // if(id == 1/**s0 == 10260 && e0 == 10334**/) { + // fprintf(stderr, "\n\n-0-qk::%ld,\ttk::%ld,\tck::%ld,\ts0::%ld,\te0::%ld\n", ok, nk, ck, s0, e0); + // } + + while (ck > 0 && ok >= s0) {///x -> t; y -> p; first insertion and then match/mismatch + --ck; + op = sc->a[ck]>>14; + // ol = (((op == 1) || (op == 2))?(sc->a[ck]&(0xfff)):(sc->a[ck]&(0x3fff))); + if((op == 2) || (op == 3)) { + ol = sc->a[ck]&(0xfff); + } else if(op == 1) { + ol = sc->a[ck]&(0x3ff); + } else { + ol = sc->a[ck]&(0x3fff); + } + if(op != 2) ok -= ol; + if(op != 3) nk -= ol; + } + + // char cm[4]; cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; + // if(id == 1/**s0 == 10260 && e0 == 10334**/) { + // fprintf(stderr, "-1-qk::%ld,\ttk::%ld,\tck::%ld\n", ok, nk, ck); + // } + while (ck < cn && ok < e0) { ///[s0, e0) + wo[0] = ok; wn[0] = nk; + // ck = pop_trace_bp(sc, ck, &op, &b, &cl); + ck = pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); + if(op != 2) ok += cl; + if(op != 3) nk += cl; + wo[1] = ok; wn[1] = nk; + + os = ((s0 >= wo[0])? s0 : wo[0]); + oe = ((e0 <= wo[1])? e0 : wo[1]); + // os = MAX(s0, wo[0]); oe = MIN(e0, wo[1]); + ovlp = ((oe>os)? (oe-os):0); + // if(id == 1/**s0 == 10260 && e0 == 10334**/) { + // fprintf(stderr, "%u%c(q::[%ld,%ld))(t::[%ld,%ld))(ck::%ld)\n", cl, cm[op], wo[0], wo[1], wn[0], wn[1], ck); + // } + + if(op != 2) { + if(!ovlp) continue; + } else {///wo[0] == wo[1] + if(wo[0] < s0 || wo[0] >= e0) continue; + } + + if(op < 2) { + ots = os - wo[0] + wn[0]; ote = oe - wo[0] + wn[0]; + } else {///op == 2: more y; p == 3: more x + ots = wn[0]; ote = wn[1]; + } + + if(s1 == -1) { + s1 = ots; + // if((op == 0) && (wn[1] > ots) && ((wn[0] < ots) || (ots == 0))) si = 1; + if((op == 0) && (wo[1] > s0) && ((wo[0] < s0) || (s1 == 0))) si = 1; + } + + e1 = ote; + if((op == 0) && (wo[0] < e0) && ((wo[1] > e0) || (e1 == len))) ei = 1; + + if((op == 0) && (ovlp > 0) && (ovlp > weo[1] - weo[0])) { + weo[0] = os; weo[1] = oe; + wen[0] = ots; wen[1] = ote; + } + } + + while (ck < cn && ok <= e0) { ///[s0, e0) + wo[0] = ok; wn[0] = nk; + // pop_trace_bp(sc, ck, &op, &b, &cl); + pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); + if(op != 2) break; + // ck = pop_trace_bp(sc, ck, &op, &b, &cl); + ck = pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); + // if(op != 2) ok += cl; + // if(op != 3) nk += cl; + nk += cl; + wo[1] = ok; wn[1] = nk; + + // if(id == 1/**s0 == 10260 && e0 == 10334**/) { + // fprintf(stderr, "%u%c(q::[%ld,%ld))(t::[%ld,%ld))(ck::%ld)\n", cl, cm[op], wo[0], wo[1], wn[0], wn[1], ck); + // } + + if(wo[0] >= s0 && wo[0] <= e0) { + ots = wn[0]; ote = wn[1]; + if(s1 == -1) s1 = ots; + e1 = ote; + } + } + + assert(wen[1] <= len); + assert(e1 <= len); + + *iok = ok; *ink = nk; *ick = ck; + if(e1 <= s1) return 0; + rpos = rspan = ((uint64_t)-1); + + if(weo[0] == s0 && weo[1] == e0) { + rpos = wen[1]-1; rspan = e0 - s0; + /** + if(si == 1 && ei == 1) { + z->srt >>= 32; z->srt <<= 32; z->srt |= ((uint64_t)(wen[1]-1)); + ///debug + // char sstr[256]; recover_UC_Read_sub_region(sstr, wen[0], wen[1] - wen[0], 0, rref, id); + // if(recalu_minimizer0(sstr, wen[1] - wen[0], !(asm_opt.flag & HA_F_NO_HPC), mz_k, mz_h, tq, &rpos, &rspan) && (rpos + 1 == ((uint64_t)(wen[1] - wen[0]))) && (((uint64_t)(wen[1] - wen[0])) == rspan)) { + // // fprintf(stderr, "-0-[M::%s]\n", __func__); + // } else { + // // if(((z->srt>>32)&1) == 0) { + // fprintf(stderr, "-1-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], wen[0], wen[1], s0, e0, e0 - s0); + // fprintf(stderr, "tstr::%.*s\n", ((uint32_t)(wen[1] - wen[0])), sstr); + // fprintf(stderr, "qstr::%.*s\n", ((uint32_t)(qe - qs)), qstr + qs); + // exit(1); + // // } + // } + // if(rid == 3196 && id == 3199) fprintf(stderr, "-full-[M::%s]\n", __func__); + return 1; + } + **/ + } else { + if(s1 >= (*str_s) && e1 <= (*str_e)) { + str = tu->seq + s1 - (*str_s); + } else { + if(s1 >= (*str_s) && (s1 < (*str_e)) && (e1 > (*str_e))) { + UC_Read_resize((*tu), (e1 - (*str_s))); + recover_UC_Read_sub_region(tu->seq + (*str_e) - (*str_s), (*str_e), e1 - (*str_e), 0, rref, id); + str = tu->seq + s1 - (*str_s); (*str_e) = e1; + } else { + UC_Read_resize((*tu), (e1 - s1)); + recover_UC_Read_sub_region(tu->seq, s1, e1 - s1, 0, rref, id); + str = tu->seq; (*str_s) = s1; (*str_e) = e1; + } + } + + if(recalu_minimizer0(str, e1 - s1, !(asm_opt.flag & HA_F_NO_HPC), mz_k, mz_h, tq, &rpos, &rspan)) { + rpos += s1; + } + } + + if(rpos != ((uint64_t)-1) && rspan != ((uint64_t)-1)) { + e0 = rpos + 1; s0 = e0 - rspan; + if(!(asm_opt.flag & HA_F_NO_HPC)) { + if(si == -1) { + s0 -= hpc_minimizer_test(id, rref, tu, *str_s, *str_e, s0, len, 1, 8); + assert(s0 >= 0 && s0 < len && s0 < e0); + } + + if(ei == -1) { + e0 += hpc_minimizer_test(id, rref, tu, *str_s, *str_e, e0-1, len, 0, 8); + assert(e0 >= 0 && e0 < len && s0 < e0); + } + } + + rpos = e0 - 1; rspan = e0 - s0; + if(rspan < 256) { + z->srt >>= 32; z->srt <<= 32; z->srt |= rpos; z->other_off = rspan; + return 1; + } + } + /** + if(recalu_minimizer0(str, e1 - s1, !(asm_opt.flag & HA_F_NO_HPC), mz_k, mz_h, tq, &rpos, &rspan)) { + rpos += s1; + z->srt >>= 32; z->srt <<= 32; z->srt |= rpos; z->other_off = rspan; + // fprintf(stderr, "-1-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], s1, e1, s0, e0, e0 - s0); + // if(rid == 3196 && id == 3199) fprintf(stderr, "-part-[M::%s]\n", __func__); + return 1; + } + // fprintf(stderr, "-0-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], s1, e1, s0, e0, e0 - s0); + **/ + + return 0; +} + + +uint64_t recalu_minimizer_non_retrieve(uint64_t rid, anchor1_t *z, asg16_v *sc, int64_t *iok, int64_t *ink, int64_t *ick, uint64_t mz_k, uint64_t mz_h, tiny_queue_t *tq, char *tstr, int64_t tl, uint64_t trev/** , char *qstr, uint64_t qs, uint64_t qe**/) +{ + char *str = NULL; uint64_t rpos, rspan; char c; + int64_t ok = *iok, nk = *ink, ck = *ick, cn = sc->n, s0, e0, s1, e1, os, oe, ots, ote, ol, wo[2], wn[2], weo[2], wen[2], ovlp, k; uint16_t op, bq, bt; uint32_t cl; + e0 = ((uint32_t)z->srt) + 1; s0 = e0 - z->other_off; s1 = e1 = -1; weo[0] = weo[1] = wen[0] = wen[1] = -1; + if(e0 <= s0) return 0; + + + if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed + ck = ok = nk = 0; + } + + while (ck > 0 && ok >= s0) {///x -> t; y -> p; first insertion and then match/mismatch + --ck; + op = sc->a[ck]>>14; + // ol = (((op == 1) || (op == 2))?(sc->a[ck]&(0xfff)):(sc->a[ck]&(0x3fff))); + if((op == 2) || (op == 3)) { + ol = sc->a[ck]&(0xfff); + } else if(op == 1) { + ol = sc->a[ck]&(0x3ff); + } else { + ol = sc->a[ck]&(0x3fff); + } + if(op != 2) ok -= ol; + if(op != 3) nk -= ol; + } + + while (ck < cn && ok < e0) { ///[s0, e0) + wo[0] = ok; wn[0] = nk; + // ck = pop_trace_bp(sc, ck, &op, &b, &cl); + ck = pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); + if(op != 2) ok += cl; + if(op != 3) nk += cl; + wo[1] = ok; wn[1] = nk; + + os = ((s0 >= wo[0])? s0 : wo[0]); + oe = ((e0 <= wo[1])? e0 : wo[1]); + // os = MAX(s0, wo[0]); oe = MIN(e0, wo[1]); + ovlp = ((oe>os)? (oe-os):0); + + if(op != 2) { + if(!ovlp) continue; + } else {///wo[0] == wo[1] + if(wo[0] < s0 || wo[0] >= e0) continue; + } + + if(op < 2) { + ots = os - wo[0] + wn[0]; ote = oe - wo[0] + wn[0]; + } else {///op == 2: more y; p == 3: more x + ots = wn[0]; ote = wn[1]; + } + + if(s1 == -1) s1 = ots; + e1 = ote; + + if((op == 0) && (ovlp > 0) && (ovlp > weo[1] - weo[0])) { + weo[0] = os; weo[1] = oe; + wen[0] = ots; wen[1] = ote; + } + } + + while (ck < cn && ok <= e0) { ///[s0, e0) + wo[0] = ok; wn[0] = nk; + // pop_trace_bp(sc, ck, &op, &b, &cl); + pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); + if(op != 2) break; + // ck = pop_trace_bp(sc, ck, &op, &b, &cl); + ck = pop_trace_bp_f(sc, ck, &op, &bq, &bt, &cl); + // if(op != 2) ok += cl; + // if(op != 3) nk += cl; + nk += cl; + wo[1] = ok; wn[1] = nk; + + + if(wo[0] >= s0 && wo[0] <= e0) { + ots = wn[0]; ote = wn[1]; + if(s1 == -1) s1 = ots; + e1 = ote; + } + } + + assert(wen[1] <= tl); + assert(e1 <= tl); + + *iok = ok; *ink = nk; *ick = ck; + + rpos = rspan = ((uint64_t)-1); + if(weo[0] == s0 && weo[1] == e0) { + rpos = wen[1]-1; rspan = e0 - s0; + // z->srt >>= 32; z->srt <<= 32; z->srt |= ((uint64_t)(wen[1]-1)); + ///debug + // char sstr[256]; recover_UC_Read_sub_region(sstr, wen[0], wen[1] - wen[0], 0, rref, id); + // if(recalu_minimizer0(sstr, wen[1] - wen[0], !(asm_opt.flag & HA_F_NO_HPC), mz_k, mz_h, tq, &rpos, &rspan) && (rpos + 1 == ((uint64_t)(wen[1] - wen[0]))) && (((uint64_t)(wen[1] - wen[0])) == rspan)) { + // // fprintf(stderr, "-0-[M::%s]\n", __func__); + // } else { + // // if(((z->srt>>32)&1) == 0) { + // fprintf(stderr, "-1-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], wen[0], wen[1], s0, e0, e0 - s0); + // fprintf(stderr, "tstr::%.*s\n", ((uint32_t)(wen[1] - wen[0])), sstr); + // fprintf(stderr, "qstr::%.*s\n", ((uint32_t)(qe - qs)), qstr + qs); + // exit(1); + // // } + // } + // if(rid == 3196 && id == 3199) fprintf(stderr, "-full-[M::%s]\n", __func__); + // return 1; + } else { + if(e1 <= s1) return 0; + // if(s1 >= tl || e1 >= tl) return 0; + + if(trev) str = tstr + tl - e1; + else str = tstr + s1; + + if(recalu_minimizer0_adv(str, e1 - s1, !(asm_opt.flag & HA_F_NO_HPC), mz_k, mz_h, trev, tq, &rpos, &rspan)) { + rpos += s1; + // z->srt >>= 32; z->srt <<= 32; z->srt |= rpos; z->other_off = rspan; + // fprintf(stderr, "-1-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], s1, e1, s0, e0, e0 - s0); + // if(rid == 3196 && id == 3199) fprintf(stderr, "-part-[M::%s]\n", __func__); + // return 1; + } + } + + if(rpos != ((uint64_t)-1) && rspan != ((uint64_t)-1)) { + e0 = rpos + 1; s0 = e0 - rspan; + if(!(asm_opt.flag & HA_F_NO_HPC)) { + if(!trev) { + s1 = s0; e1 = e0; + } else { + s1 = tl - e0; e1 = tl - s0; + } + + c = tstr[s1]; + for (k = s1 - 1; k >= 0 && tstr[k] == c; k--){;} s1 = k + 1; + + c = tstr[e1-1]; + for (k = e1; k < tl && tstr[k] == c; k++){;} e1 = k; + + if(!trev) { + s0 = s1; e0 = e1; + } else { + s0 = tl - e1; e0 = tl - s1; + } + } + + rpos = e0 - 1; rspan = e0 - s0; + if(rspan < 256) { + z->srt >>= 32; z->srt <<= 32; z->srt |= rpos; z->other_off = rspan; + return 1; + } + } + // fprintf(stderr, "-0-[M::%s]\trid::%lu\ttid::%ld\t%c\trg1::[%ld,%ld)\trg0::[%ld,%ld)\tspan::%ld\n", __func__, rid, id, "+-"[(z->srt>>32)&1], s1, e1, s0, e0, e0 - s0); + + return 0; +} + +void hpc_ext_check(All_reads *rref, uint32_t id, int64_t s0, int64_t e0, int64_t l, uint64_t rev, char *buf) +{ + if(s0 < 0) {s0 = 0;} if(e0 > l) {e0 = l;} + int64_t s = s0 - 256, e = e0 + 256, n, k, os0, oe0, os1, oe1; char c; if(s < 0) s = 0; if(e > l) e = l; + recover_UC_Read_sub_region(buf, s, e - s, rev, rref, id); + os0 = s0 - s; oe0 = e0 - s; n = e - s; os1 = os0; oe1 = oe0; + c = buf[os0]; + for (k = os0 - 1; k >= 0 && buf[k] == c; k--){;} os1 = k + 1; + + c = buf[oe0-1]; + for (k = oe0; k < n && buf[k] == c; k++){;} oe1 = k; + + if(os1 != os0 || oe1 != oe0) { + fprintf(stderr, "[M::%s]\to0::[%ld,%ld)\to1::[%ld,%ld)\n", __func__, os0 + s0, oe0 + s0, os1 + s0, oe1 + s0); + } + +} + +void h_ec_lchain_re_gen(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, ha_pt_t *ha_idx, All_reads *rref, overlap_region_alloc *olst, Candidates_list *cl, double bw_thres, + int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, + int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip, UC_Read *tu, asg64_v *oidx, asg16_v *scc) +{ + uint64_t i, k, l, m, max_cnt = UINT32_MAX, min_cnt = 0; int n, n0, j; ha_mz1_t *z; seed1_t *s; tiny_queue_t tq; memset(&tq, 0, sizeof(tiny_queue_t)); + if(high_occ) { + max_cnt = (*high_occ); + if(max_cnt < 2) max_cnt = 2; + } + if(low_occ) { + min_cnt = (*low_occ); + if(min_cnt < 2) min_cnt = 2; + } + clear_Candidates_list(cl); ab->n_a = 0; + + // minimizer of queried read + if (ab->mz.m > ab->old_mz_m) { + ab->old_mz_m = ab->mz.m; + REALLOC(ab->seed, ab->old_mz_m); + } + + for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { + ab->seed[i].a = ha_pt_get(ha_idx, ab->mz.a[i].x, &n); + ab->seed[i].n = n; + ab->n_a += n; + } + + if (ab->n_a > ab->m_a) { + ab->m_a = ab->n_a; + REALLOC(ab->a, ab->m_a); + } + + for (i = 0, k = 0; i < ab->mz.n; ++i) { + ///z is one of the minimizer + z = &ab->mz.a[i]; s = &ab->seed[i]; + + // uint64_t rpos, rspan; + // if(!recalu_minimizer0(rs + (z->pos+1-z->span), z->span, !(asm_opt.flag & HA_F_NO_HPC), mz_k, z->x, &tq, &rpos, &rspan)) { + // fprintf(stderr, "-1-[M::%s]\t%c\trg0::[%u,%u)\trid::%u\n", __func__, "+-"[z->rev], z->pos+1-z->span, z->pos+1, rid); + // } + // else { + // fprintf(stderr, "-0-[M::%s]\t%c\trg0::[%u,%u)\trid::%u\n", __func__, "+-"[z->rev], z->pos+1-z->span, z->pos+1, rid); + // } + + for (j = 0; j < s->n; ++j) { + const ha_idxpos_t *y = &s->a[j]; + anchor1_t *an = &ab->a[k++]; + uint8_t rev = z->rev == y->rev? 0 : 1; + + // an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; + an->other_off = y->span; + + // an->self_off = z->pos; + an->self_off = i; + + ///an->cnt: cnt<<8|span + an->cnt = s->n; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; + an->cnt <<= 8; an->cnt |= ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); + + // an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; + an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | y->pos; + } + } + + // copy over to _cl_ + if (ab->m_a >= (uint64_t)cl->size) { + cl->size = ab->m_a; + REALLOC(cl->list, cl->size); + } + clear_overlap_region_alloc(olst); + + // char dbg[256]; uint64_t rpos, rspan, thash; + // char dbg[768]; + k_mer_hit *p; uint64_t tid = (uint64_t)-1, tl = (uint64_t)-1, trev, tspan, ol, zn, olst_n; int64_t ok, nk, ck, str_s, str_e; + radix_sort_ha_an1(ab->a, ab->a + ab->n_a); + for (k = 1, l = ol = n = zn = 0; k <= ab->n_a; ++k) { + if (k == ab->n_a || (ab->a[k].srt>>32) != (ab->a[l].srt>>32)) { + for (; (ol < oidx->n) && ((oidx->a[ol]>>32) < (ab->a[l].srt>>32)); ol++); + if((ol < oidx->n) && ((ab->a[l].srt>>32) == (oidx->a[ol]>>32))) { + tl = Get_READ_LENGTH((*rref), ab->a[l].srt>>33); tid = ab->a[l].srt>>33; trev = (ab->a[l].srt>>32) & 1; olst_n = olst->length; + for (i = l, m = 0, ok = nk = ck = str_s = str_e = 0; i < k; i++) { + if(!recalu_minimizer(rid, &(ab->a[i]), &(scc[tid]), &ok, &nk, &ck, &str_s, &str_e, mz_k, ab->mz.a[ab->a[i].self_off].x, &tq, rref, tu, rs, ab->mz.a[ab->a[i].self_off].pos+1-ab->mz.a[ab->a[i].self_off].span, ab->mz.a[ab->a[i].self_off].pos+1)) continue; + ///debug + // recover_UC_Read_sub_region(dbg, ((uint32_t)ab->a[i].srt) + 1 - ab->a[i].other_off, ab->a[i].other_off, 0, rref, tid); + // if(recalu_minimizer0(dbg, ab->a[i].other_off, !(asm_opt.flag & HA_F_NO_HPC), mz_k, ab->mz.a[ab->a[i].self_off].x, &tq, &rpos, &rspan) && (rpos + 1 == ab->a[i].other_off) && (ab->a[i].other_off == rspan)) { + // // fprintf(stderr, "-0-[M::%s]\n", __func__); + // } else { + // fprintf(stderr, "-1-[M::%s]\n", __func__); + // } + // thash = ab->mz.a[ab->a[i].self_off].x; + ab->a[m] = ab->a[i]; tspan = ab->a[m].other_off; + ab->a[m].other_off = (uint32_t)ab->a[m].srt; + if(trev) ab->a[m].other_off = tl - (ab->a[m].other_off+1-tspan) - 1;///looks like a bug + ab->a[m].self_off = ab->mz.a[ab->a[m].self_off].pos; + ab->a[m].srt = ab->a[m].self_off; ab->a[m].srt <<= 32; ab->a[m].srt |= ab->a[m].other_off; + ///debug + // recover_UC_Read_sub_region(dbg, ab->a[m].other_off + 1 - tspan, tspan, trev, rref, tid); + // if(recalu_minimizer0(dbg, tspan, !(asm_opt.flag & HA_F_NO_HPC), mz_k, thash, &tq, &rpos, &rspan) && (rpos + 1 == tspan) && (tspan == rspan)) { + // fprintf(stderr, "-0-[M::%s]\n", __func__); + // } else { + // fprintf(stderr, "-1-[M::%s]\ttrev::%lu\n", __func__, trev); + // } + ///debug + // if(rid == 3196 && tid == 3199) hpc_ext_check(rref, tid, ab->a[m].other_off + 1 - tspan, ab->a[m].other_off + 1, tl, trev, dbg); + + + m++; + } + if(m > 1) radix_sort_ha_an1(ab->a, ab->a + m); + for (i = 0, n0 = n; i < m; i++) { + p = &cl->list[n++]; + p->readID = tid; + p->strand = trev; + p->offset = ab->a[i].other_off; + p->self_offset = ab->a[i].self_off; + if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ + p->cnt = 1; + } else if((ab->a[i].cnt>>8) <= min_cnt) { + p->cnt = 2; + } else{ + p->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); + p->cnt = pow(p->cnt, 1.1); + } + if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; + p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); + } + + // if(rid == 3196 && tid == 3199) fprintf(stderr, "[M::%s]\ttid::%lu\ttrev::%lu\told::%lu\tnew::%lu\n", __func__, tid, trev, k - l, m); + + if(m > 0 && tid != rid) { + zn += lchain_qdp_mcopy_fast(cl, n0, n-n0, zn, &(cl->chainDP), olst, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, + rid, rl, tl, quick_check, apend_be, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, 1); + } + + if(olst->length > olst_n) { + oidx->a[ol] >>= 32; oidx->a[ol] <<= 32; oidx->a[ol] |= ((uint64_t)((uint32_t)-1)); + } + } + + l = k; + } + } + cl->length = zn; + + for (k = m = 0; k < oidx->n; k++) { + if(((uint32_t)oidx->a[k]) == ((uint32_t)-1)) continue; + oidx->a[m++] = oidx->a[k]; + } + // fprintf(stderr, "[M::%s]\ttot::%lu\tremain::%lu\n", __func__, (uint64_t)oidx->n, m); + oidx->n = m; + + for (i = 0; i < olst->length; ++i) olst->list[i].align_length = 0; + + // minimizers_qgen0(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, rref, dbg_ct, sp, high_occ, low_occ); + + // lchain_qgen_mcopy_fast(cl, overlap_list, rid, rl, rref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off, enable_mcopy, mcopy_rate, chain_cutoff, mcopy_khit_cut, sp); +} + + +void h_ec_lchain_re_gen3(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, ha_pt_t *ha_idx, All_reads *rref, overlap_region_alloc *olst, Candidates_list *cl, double bw_thres, + int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, + int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip, UC_Read *tu, asg64_v *oidx, asg16_v *scc) +{ + uint64_t i, k, l, m, max_cnt = UINT32_MAX, min_cnt = 0; int n, n0, j; ha_mz1_t *z; seed1_t *s; tiny_queue_t tq; memset(&tq, 0, sizeof(tiny_queue_t)); + if(high_occ) { + max_cnt = (*high_occ); + if(max_cnt < 2) max_cnt = 2; + } + if(low_occ) { + min_cnt = (*low_occ); + if(min_cnt < 2) min_cnt = 2; + } + clear_Candidates_list(cl); ab->n_a = 0; + + // minimizer of queried read + if (ab->mz.m > ab->old_mz_m) { + ab->old_mz_m = ab->mz.m; + REALLOC(ab->seed, ab->old_mz_m); + } + + for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { + ab->seed[i].a = ha_pt_get(ha_idx, ab->mz.a[i].x, &n); + ab->seed[i].n = n; + ab->n_a += n; + } + + if (ab->n_a > ab->m_a) { + ab->m_a = ab->n_a; + REALLOC(ab->a, ab->m_a); + } + + for (i = 0, k = 0; i < ab->mz.n; ++i) { + ///z is one of the minimizer + z = &ab->mz.a[i]; s = &ab->seed[i]; + + // uint64_t rpos, rspan; + // if(!recalu_minimizer0(rs + (z->pos+1-z->span), z->span, !(asm_opt.flag & HA_F_NO_HPC), mz_k, z->x, &tq, &rpos, &rspan)) { + // fprintf(stderr, "-1-[M::%s]\t%c\trg0::[%u,%u)\trid::%u\n", __func__, "+-"[z->rev], z->pos+1-z->span, z->pos+1, rid); + // } + // else { + // fprintf(stderr, "-0-[M::%s]\t%c\trg0::[%u,%u)\trid::%u\n", __func__, "+-"[z->rev], z->pos+1-z->span, z->pos+1, rid); + // } + + for (j = 0; j < s->n; ++j) { + const ha_idxpos_t *y = &s->a[j]; + anchor1_t *an = &ab->a[k++]; + uint8_t rev = z->rev == y->rev? 0 : 1; + + // an->other_off = rev?((uint32_t)-1)-1-(y->pos+1-y->span):y->pos; + an->other_off = y->span; + + // an->self_off = z->pos; + an->self_off = i; + + ///an->cnt: cnt<<8|span + an->cnt = s->n; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; + an->cnt <<= 8; an->cnt |= ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); + + // an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | an->self_off; + an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | y->pos; + } + } + + // copy over to _cl_ + if (ab->m_a >= (uint64_t)cl->size) { + cl->size = ab->m_a; + REALLOC(cl->list, cl->size); + } + clear_overlap_region_alloc(olst); + + // char dbg[256]; uint64_t rpos, rspan, thash; + // char dbg[768]; uint64_t rpos, rspan, thash; + k_mer_hit *p; uint64_t tid = (uint64_t)-1, tl = (uint64_t)-1, trev, tspan, ol, zn, olst_n, sk, sv; int64_t ok, nk, ck, str_s, str_e; + radix_sort_ha_an1(ab->a, ab->a + ab->n_a); + for (k = 1, l = ol = n = zn = 0; k <= ab->n_a; ++k) { + if (k == ab->n_a || (ab->a[k].srt>>32) != (ab->a[l].srt>>32)) { + + for (sk = sv = 0; (ol < oidx->n) && ((oidx->a[ol]>>33) < (ab->a[l].srt>>33)); ol++); + if((ol < oidx->n) && ((ab->a[l].srt>>33) == (oidx->a[ol]>>33))) { + for (; (ol < oidx->n) && ((oidx->a[ol]>>32) < (ab->a[l].srt>>32)); ol++); + if((ol < oidx->n) && ((ab->a[l].srt>>32) == (oidx->a[ol]>>32))) { + if(((uint32_t)oidx->a[ol]) == ((uint32_t)-1)) sk = 1;///exact match + else sv = 1; + } else {///match in rev + sk = 1; + } + } + + if(!sk) { + tl = Get_READ_LENGTH((*rref), ab->a[l].srt>>33); tid = ab->a[l].srt>>33; trev = (ab->a[l].srt>>32) & 1; olst_n = olst->length; + if(tid != rid) { + for (i = l, m = 0, ok = nk = ck = str_s = str_e = 0; i < k; i++) { + if(!recalu_minimizer_bd(rid, &(ab->a[i]), &(scc[tid]), &ok, &nk, &ck, &str_s, &str_e, mz_k, ab->mz.a[ab->a[i].self_off].x, &tq, rref, tu, rs, ab->mz.a[ab->a[i].self_off].pos+1-ab->mz.a[ab->a[i].self_off].span, ab->mz.a[ab->a[i].self_off].pos+1)) continue; + ///debug + // recover_UC_Read_sub_region(dbg, ((uint32_t)ab->a[i].srt) + 1 - ab->a[i].other_off, ab->a[i].other_off, 0, rref, tid); + // if(recalu_minimizer0(dbg, ab->a[i].other_off, !(asm_opt.flag & HA_F_NO_HPC), mz_k, ab->mz.a[ab->a[i].self_off].x, &tq, &rpos, &rspan) && (rpos + 1 == ab->a[i].other_off) && (ab->a[i].other_off == rspan)) { + // // fprintf(stderr, "-0-[M::%s]\n", __func__); + // } else { + // fprintf(stderr, "-1-[M::%s]\n", __func__); + // } + // thash = ab->mz.a[ab->a[i].self_off].x; + ab->a[m] = ab->a[i]; tspan = ab->a[m].other_off; + ab->a[m].other_off = (uint32_t)ab->a[m].srt; + if(trev) ab->a[m].other_off = tl - (ab->a[m].other_off+1-tspan) - 1;///looks like a bug + ab->a[m].self_off = ab->mz.a[ab->a[m].self_off].pos; + ab->a[m].srt = ab->a[m].self_off; ab->a[m].srt <<= 32; ab->a[m].srt |= ab->a[m].other_off; + ///debug + /** + recover_UC_Read_sub_region(dbg, ab->a[m].other_off + 1 - tspan, tspan, trev, rref, tid); + if(recalu_minimizer0(dbg, tspan, !(asm_opt.flag & HA_F_NO_HPC), mz_k, thash, &tq, &rpos, &rspan) && (rpos + 1 == tspan) && (tspan == rspan)) { + // fprintf(stderr, "-0-[M::%s]\n", __func__); + } else { + fprintf(stderr, "-1-[M::%s]\ttrev::%lu\n", __func__, trev); + } + ///debug + hpc_ext_check(rref, tid, ab->a[m].other_off + 1 - tspan, ab->a[m].other_off + 1, tl, trev, dbg); + **/ + + m++; + } + if(m > 1) radix_sort_ha_an1(ab->a, ab->a + m); + for (i = 0, n0 = n; i < m; i++) { + p = &cl->list[n++]; + p->readID = tid; + p->strand = trev; + p->offset = ab->a[i].other_off; + p->self_offset = ab->a[i].self_off; + if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ + p->cnt = 1; + } else if((ab->a[i].cnt>>8) <= min_cnt) { + p->cnt = 2; + } else{ + p->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); + p->cnt = pow(p->cnt, 1.1); + } + if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; + p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); + } + + if(m > 0) { + zn += lchain_qdp_mcopy_fast(cl, n0, n-n0, zn, &(cl->chainDP), olst, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, + rid, rl, tl, quick_check, apend_be, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, 1); + } + + if(sv && olst->length > olst_n) { + oidx->a[ol] >>= 32; oidx->a[ol] <<= 32; oidx->a[ol] |= ((uint64_t)((uint32_t)-1)); + } + } + } + + l = k; + } + } + cl->length = zn; + + for (k = m = 0; k < oidx->n; k++) { + if(((uint32_t)oidx->a[k]) == ((uint32_t)-1)) continue; + oidx->a[m++] = oidx->a[k]; + } + // fprintf(stderr, "[M::%s]\ttot::%lu\tremain::%lu\n", __func__, (uint64_t)oidx->n, m); + oidx->n = m; + + for (i = 0; i < olst->length; ++i) olst->list[i].align_length = 0; + + // minimizers_qgen0(ab, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, rref, dbg_ct, sp, high_occ, low_occ); + + // lchain_qgen_mcopy_fast(cl, overlap_list, rid, rl, rref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off, enable_mcopy, mcopy_rate, chain_cutoff, mcopy_khit_cut, sp); +} + + +void h_ec_lchain_re_gen_srt(ha_abuf_t *ab, ha_pt_t *ha_idx, overlap_region_alloc *olst, Candidates_list *cl) +{ + uint64_t i, k; int j, n; ha_mz1_t *z; seed1_t *s; + + clear_Candidates_list(cl); ab->n_a = 0; + + // minimizer of queried read + if (ab->mz.m > ab->old_mz_m) { + ab->old_mz_m = ab->mz.m; + REALLOC(ab->seed, ab->old_mz_m); + } + + for (i = 0, ab->n_a = 0; i < ab->mz.n; ++i) { + ab->seed[i].a = ha_pt_get(ha_idx, ab->mz.a[i].x, &n); + ab->seed[i].n = n; + ab->n_a += n; + } + + if (ab->n_a > ab->m_a) { + ab->m_a = ab->n_a; + REALLOC(ab->a, ab->m_a); + } + + for (i = 0, k = 0; i < ab->mz.n; ++i) { + ///z is one of the minimizer + z = &ab->mz.a[i]; s = &ab->seed[i]; + + for (j = 0; j < s->n; ++j) { + const ha_idxpos_t *y = &s->a[j]; + anchor1_t *an = &ab->a[k++]; + uint8_t rev = z->rev == y->rev? 0 : 1; + + an->other_off = y->span; + an->self_off = i; + ///an->cnt: cnt<<8|span + an->cnt = s->n; if(an->cnt > ((uint32_t)(0xffffffu))) an->cnt = 0xffffffu; + an->cnt <<= 8; an->cnt |= ((z->span <= ((uint32_t)(0xffu)))?z->span:((uint32_t)(0xffu))); + an->srt = (uint64_t)y->rid<<33 | (uint64_t)rev<<32 | y->pos; + } + } + + // copy over to _cl_ + if (ab->m_a >= (uint64_t)cl->size) { + cl->size = ab->m_a; + REALLOC(cl->list, cl->size); + } + clear_overlap_region_alloc(olst); + radix_sort_ha_an1(ab->a, ab->a + ab->n_a); +} + +uint64_t h_ec_lchain_re_gen_qry(ha_abuf_t *ab, uint64_t *k, uint64_t *l, uint64_t *i, uint64_t *idx_a, uint64_t idx_n, uint64_t *tid, uint64_t *trev) +{ + while ((*k) <= ab->n_a) { + if ((*k) == ab->n_a || (ab->a[*k].srt>>32) != (ab->a[*l].srt>>32)) { + for (; ((*i) < idx_n) && ((idx_a[*i]>>32) < (ab->a[*l].srt>>32)); (*i)++); + if(((*i) < idx_n) && ((ab->a[*l].srt>>32) == (idx_a[*i]>>32))) { + (*tid) = ab->a[*l].srt>>33; (*trev) = (ab->a[*l].srt>>32) & 1; + + return 1; + } + (*l) = (*k); + } + ++(*k); + } + return 0; +} + +uint64_t h_ec_lchain_re_chn(ha_abuf_t *ab, uint64_t si, uint64_t ei, uint32_t rid, char* rs, uint64_t rl, uint64_t tid, char* ts, uint64_t tl, uint64_t trev, uint64_t mz_w, uint64_t mz_k, overlap_region_alloc *olst, Candidates_list *cl, double bw_thres, + int apend_be, uint64_t max_cnt, uint64_t min_cnt, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip, tiny_queue_t *tq, asg16_v *scc, int64_t *n, int64_t *zn) +{ + // char dbg[768]; uint64_t rpos, rspan, thash; + + int64_t ok, nk, ck, n0; uint64_t i, m, tspan, on0; k_mer_hit *p; + for (i = si, m = ok = nk = ck = 0; i < ei; i++) { + if(!recalu_minimizer_non_retrieve(rid, &(ab->a[i]), &(scc[tid]), &ok, &nk, &ck, mz_k, ab->mz.a[ab->a[i].self_off].x, tq, ts, tl, trev)) continue; + ///debug + // thash = ab->mz.a[ab->a[i].self_off].x; + + ab->a[m] = ab->a[i]; tspan = ab->a[m].other_off; + ab->a[m].other_off = (uint32_t)ab->a[m].srt; + if(trev) ab->a[m].other_off = tl - (ab->a[m].other_off+1-tspan) - 1;///looks like a bug + ab->a[m].self_off = ab->mz.a[ab->a[m].self_off].pos; + ab->a[m].srt = ab->a[m].self_off; ab->a[m].srt <<= 32; ab->a[m].srt |= ab->a[m].other_off; + + + ///debug + // recover_UC_Read_sub_region(dbg, ab->a[m].other_off + 1 - tspan, tspan, trev, &R_INF, tid); + // if(recalu_minimizer0(dbg, tspan, !(asm_opt.flag & HA_F_NO_HPC), mz_k, thash, tq, &rpos, &rspan) && (rpos + 1 == tspan) && (tspan == rspan)) { + // // fprintf(stderr, "-0-[M::%s]\n", __func__); + // } else { + // fprintf(stderr, "-1-[M::%s]\ttrev::%lu\n", __func__, trev); + // } + ///debug + // hpc_ext_check(&R_INF, tid, ab->a[m].other_off + 1 - tspan, ab->a[m].other_off + 1, tl, trev, dbg); + + m++; + } + + if(m > 1) radix_sort_ha_an1(ab->a, ab->a + m); + + for (i = 0, n0 = (*n); i < m; i++) { + p = &cl->list[(*n)++]; + p->readID = tid; + p->strand = trev; + p->offset = ab->a[i].other_off; + p->self_offset = ab->a[i].self_off; + if(((ab->a[i].cnt>>8) < max_cnt) && ((ab->a[i].cnt>>8) > min_cnt)){ + p->cnt = 1; + } else if((ab->a[i].cnt>>8) <= min_cnt) { + p->cnt = 2; + } else{ + p->cnt = 1 + (((ab->a[i].cnt>>8) + (max_cnt<<1) - 1)/(max_cnt<<1)); + p->cnt = pow(p->cnt, 1.1); + } + if(p->cnt > ((uint32_t)(0xffffffu))) p->cnt = 0xffffffu; + p->cnt <<= 8; p->cnt |= (((uint32_t)(0xffu))&(ab->a[i].cnt)); + } + + // if(rid == 3196 && tid == 3199) fprintf(stderr, "[M::%s]\ttid::%lu\ttrev::%lu\told::%lu\tnew::%lu\n", __func__, tid, trev, k - l, m); + // fprintf(stderr, "[M::%s]\ttid::%lu\ttrev::%lu\told::%lu\tnew::%lu\n", __func__, tid, trev, ei - si, m); + + if(m > 0 && tid != rid) { + on0 = olst->length; + *zn += lchain_qdp_mcopy_fast(cl, n0, (*n)-n0, *zn, &(cl->chainDP), olst, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, + rid, rl, tl, quick_check, apend_be, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, 1); + cl->length = *zn; + if(olst->length > on0) return 1; + } + + cl->length = *zn; + return 0; +} + +uint64_t get_mz1(const char *str, int len, int w, int k, uint32_t rid, int is_hpc, ha_abuf_t *ab, const void *hf, ha_pt_t *ha_idx, int sample_dist, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, ha_pt_t *pt, int min_freq, int32_t dp_min_len, float dp_e, st_mt_t *mt, int32_t ws, int32_t is_unique, void *km, uint64_t beg_i) +{ + ab->mz.n = beg_i; + // get the list of anchors + mz1_ha_sketch(str, len, w, k, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, hf, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, mt, asm_opt.mz_rewin, 0, NULL); + + radix_sort_ha_mz1_v_srt(ab->mz.a + beg_i, ab->mz.a + ab->mz.n); + + if(ha_idx) { + uint64_t i; + + if (ab->mz.m > ab->old_mz_m) { + ab->old_mz_m = ab->mz.m; + REALLOC(ab->seed, ab->old_mz_m); + } + + for (i = 0; i < ab->mz.n; ++i) { + ab->seed[i].a = NULL; + ab->seed[i].n = ha_pt_cnt(ha_idx, ab->mz.a[i].x); + } + } + + return ab->mz.n; +} + +void get_pi_ec_chain(ha_abuf_t *ab, uint64_t rid, uint64_t rl, uint32_t tid, char* ts, uint64_t tl, uint64_t mz_w, uint64_t mz_k, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, + int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, /**uint32_t is_accurate,**/ uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, + int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip) +{ + extern void *ha_flt_tab; + extern ha_pt_t *ha_idx; + uint64_t rn = ab->mz.n, tn, cn = 0; + + tn = get_mz1(ts, tl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), ab, ha_flt_tab, NULL, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL, rn); + + cn = lchain_qgen_mcopy_fast_re0(ab, ha_idx, ab->mz.a, rn, ab->mz.a + rn, tn - rn, tid, cl, high_occ, low_occ); + + if(cn) { + lchain_qgen_mcopy_fast_re1(cl, cl->length - cn, overlap_list, rid, rl, tl, apend_be, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut); + } + + ab->mz.n = rn; +} + + +int64_t ug_map_lchain(ha_abufl_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, double bw_thres_sec, + int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, + uint32_t gen_off, double mcopy_rate, uint32_t mcopy_khit_cut, uint32_t is_hpc, ha_mzl_t *res, uint64_t res_n, ha_mzl_t *idx, uint64_t idx_n, uint64_t mzl_cutoff, uint64_t chain_cutoff, kv_u_trans_t *kov) +{ + int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; + set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); + if((!overlap_list) || (!cl)) { + ab->mz.n = 0; + mz2_ha_sketch(rs, rl, mz_w, mz_k, rid, is_hpc, &ab->mz, NULL, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); + if(res) memcpy(res, ab->mz.a, ab->mz.n * (sizeof((*(ab->mz.a))))); + return ab->mz.n; + } else { + sp->n = 0; + minimizers_qgen_input(ab, rid, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, NULL, uref, dbg_ct, sp, high_occ, low_occ, res, res_n, idx, idx_n, mzl_cutoff, chain_cutoff, kov); + lchain_qgen_mcopy_input(cl, overlap_list, rid, rl, NULL, uref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, bw_thres_sec, quick_check, gen_off, mcopy_rate, mcopy_khit_cut, sp); + return 0; + } +} + +int64_t ug_map_lchain_simple(ha_abufl_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, + int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, + uint32_t gen_off, double mcopy_rate, uint32_t mcopy_khit_cut, uint32_t is_hpc, ha_mzl_t *res, uint64_t res_n, ha_mzl_t *idx, uint64_t idx_n, uint64_t mzl_cutoff, uint64_t chain_cutoff) +{ + int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; + set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); + if((!overlap_list) || (!cl)) { + ab->mz.n = 0; + mz2_ha_sketch(rs, rl, mz_w, mz_k, rid, is_hpc, &ab->mz, NULL, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); + if(res) memcpy(res, ab->mz.a, ab->mz.n * (sizeof((*(ab->mz.a))))); + return ab->mz.n; + } else { + sp->n = 0; + minimizers_qgen_input(ab, rid, rs, rl, mz_w, mz_k, cl, k_flag, ha_flt_tab, ha_idx, NULL, uref, dbg_ct, sp, high_occ, low_occ, res, res_n, idx, idx_n, mzl_cutoff, chain_cutoff, NULL); + // lchain_qgen_mcopy_input(cl, overlap_list, rid, rl, NULL, uref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, bw_thres_sec, quick_check, gen_off, mcopy_rate, mcopy_khit_cut, sp); + lchain_qgen_mcopy(cl, overlap_list, rid, rl, NULL, uref, apend_be, max_n_chain, max_skip, max_iter, max_dis, chn_pen_gap, chn_pen_skip, bw_thres, quick_check, gen_off, mcopy_rate, chain_cutoff, mcopy_khit_cut, sp); + return 0; + } } \ No newline at end of file diff --git a/code_of_conduct.md b/code_of_conduct.md index b7175c1..473e42b 100644 --- a/code_of_conduct.md +++ b/code_of_conduct.md @@ -1,30 +1,30 @@ -## Contributor Code of Conduct - -As contributors and maintainers of this project, we pledge to respect all -people who contribute through reporting issues, posting feature requests, -updating documentation, submitting pull requests or patches, and other -activities. - -We are committed to making participation in this project a harassment-free -experience for everyone, regardless of level of experience, gender, gender -identity and expression, sexual orientation, disability, personal appearance, -body size, race, age, or religion. - -Examples of unacceptable behavior by participants include the use of sexual -language or imagery, derogatory comments or personal attacks, trolling, public -or private harassment, insults, or other unprofessional conduct. - -Project maintainers have the right and responsibility to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct. Project maintainers or -contributors who do not follow the Code of Conduct may be removed from the -project team. - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by opening an issue or contacting the maintainer via email. - -This Code of Conduct is adapted from the [Contributor Covenant][cc], [version -1.0.0][v1]. - -[cc]: http://contributor-covenant.org/ -[v1]: http://contributor-covenant.org/version/1/0/0/ +## Contributor Code of Conduct + +As contributors and maintainers of this project, we pledge to respect all +people who contribute through reporting issues, posting feature requests, +updating documentation, submitting pull requests or patches, and other +activities. + +We are committed to making participation in this project a harassment-free +experience for everyone, regardless of level of experience, gender, gender +identity and expression, sexual orientation, disability, personal appearance, +body size, race, age, or religion. + +Examples of unacceptable behavior by participants include the use of sexual +language or imagery, derogatory comments or personal attacks, trolling, public +or private harassment, insults, or other unprofessional conduct. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct. Project maintainers or +contributors who do not follow the Code of Conduct may be removed from the +project team. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by opening an issue or contacting the maintainer via email. + +This Code of Conduct is adapted from the [Contributor Covenant][cc], [version +1.0.0][v1]. + +[cc]: http://contributor-covenant.org/ +[v1]: http://contributor-covenant.org/version/1/0/0/ diff --git a/docs/Makefile b/docs/Makefile index d0c3cbf..26b9422 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,20 +1,20 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = source -BUILDDIR = build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/source/conf.py b/docs/source/conf.py index 21cb778..bc674c9 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -1,257 +1,257 @@ -# -*- coding: utf-8 -*- - -import sys -import os - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ - 'sphinx.ext.todo', - 'sphinx.ext.mathjax', - 'sphinx.ext.ifconfig', -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'hifiasm' -copyright = u'2021, Haoyu Cheng, Heng Li' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '0.16.0-r369' -# The full version, including alpha/beta/rc tags. -release = '0.16.0' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'default' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# Build using the RTD theme, if not on RTD. -# https://read-the-docs.readthedocs.org/en/latest/theme.html -# https://github.com/snide/sphinx_rtd_theme -# -on_rtd = os.environ.get('READTHEDOCS', None) == 'True' - -if not on_rtd: # only import and set the theme if we're building docs locally - import sphinx_rtd_theme - html_theme = 'sphinx_rtd_theme' - html_theme_path = [ "/usr/local/lib/python2.7/site-packages", ] - - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -#html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'hifiasm-doc' - - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ('index', 'hifiasm.tex', u'hifiasm Documentation', - u'Haoyu Cheng, Heng Li', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'hifiasm', u'hifiasm Documentation', - [u'Haoyu Cheng, Heng Li'], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'hifiasm', u'hifiasm Documentation', - u'Haoyu Cheng, Heng Li', 'hifiasm', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. +# -*- coding: utf-8 -*- + +import sys +import os + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.todo', + 'sphinx.ext.mathjax', + 'sphinx.ext.ifconfig', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'hifiasm' +copyright = u'2021, Haoyu Cheng, Heng Li' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.16.0-r369' +# The full version, including alpha/beta/rc tags. +release = '0.16.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# Build using the RTD theme, if not on RTD. +# https://read-the-docs.readthedocs.org/en/latest/theme.html +# https://github.com/snide/sphinx_rtd_theme +# +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' + +if not on_rtd: # only import and set the theme if we're building docs locally + import sphinx_rtd_theme + html_theme = 'sphinx_rtd_theme' + html_theme_path = [ "/usr/local/lib/python2.7/site-packages", ] + + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'hifiasm-doc' + + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + ('index', 'hifiasm.tex', u'hifiasm Documentation', + u'Haoyu Cheng, Heng Li', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'hifiasm', u'hifiasm Documentation', + [u'Haoyu Cheng, Heng Li'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'hifiasm', u'hifiasm Documentation', + u'Haoyu Cheng, Heng Li', 'hifiasm', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. #texinfo_no_detailmenu = False \ No newline at end of file diff --git a/docs/source/faq.rst b/docs/source/faq.rst index c83e5f5..3aabcc1 100644 --- a/docs/source/faq.rst +++ b/docs/source/faq.rst @@ -1,123 +1,123 @@ - -.. _faq: - -Hifiasm FAQ -=========== - - -.. contents:: - :local: - - -How do I get contigs in FASTA? -------------------------------------- - The FASTA file can be produced from GFA as follows: - :: - - awk '/^S/{print ">"$2;print $3}' test.p_ctg.gfa > test.p_ctg.fa - -Which types of assemblies should I use? ----------------------------------------- - If parental data is available, ``*dip.hap*.p_ctg.gfa`` produced in trio-binning mode should be always preferred. Otherwise if Hi-C data is available, ``*hic.hap*.p_ctg.gfa`` produced in Hi-C mode is the best choice. Both trio-binning mode and Hi-C mode generate fully-phased assemblies. - - If you only have HiFi reads, hifiasm in default outputs ``*bp.hap*.p_ctg.gfa``. The primary/alternate assemblies can be also produced by using ``--primary``. All these HiFi-only assemblies are not fully-phased. See `blog `_ here for more details. - -Are inbred/homozygous genomes supported? --------------------------------------------------------------------------- - - Yes, please use the ``-l0`` option to disable purge duplication step. - -Are diploid genomes supported? -------------------------------------- - Yes, most modules of hifiasm are designed for diploid samples, including purge duplication step, partially phased assembly and fully-phased assembly with trio-binning or Hi-C. - -Are polyploid genomes supported? -------------------------------------- - - The ``*r_utg.gfa`` and ``*p_utg.gfa`` are lossless so that they also work for polyploid genomes. However, currently the contig-generation modules of hifiasm are designed for diploid samples, which means both the partially phased assembly and the fully-phased assembly does not directly support polyploid genomes. If it is set to >2, the quality of primary assembly for polyploid genomes might be improved. Please use primary assembly for polyploid samples and run multiple rounds of purging steps using third-party tools such as purge_dups. - -Why one Hi-C integrated assembly is larger than another one? ------------------------------------------------------------- - - For some samples like human male, the paternal haplotype should be larger than the maternal haplotype. However, if one assembly is much larger than another one, it should be the issues of hifiasm. To fix it, please set smaller value for ``-s`` (default: 0.55). - - Another possibility is that hifiasm misidentifies coverage threshold for homozygous reads. For instance, hifiasm prints the following information during assembly: - :: - - [M::purge_dups] homozygous read coverage threshold: 36 - - In this example, hifiasm identifies the coverage threshold for homozygous reads as ``36``. If it is significantly smaller than the homozygous coverage peak, hifiasm will generate two unbalanced assemblies. In this case, please set ``--hom-cov`` to homozygous coverage peak. Please note that tuning ``--hom-cov`` may affect ``*p_utg*gfa`` so that ``*hic*.bin`` should be deleted. Since v0.15.5, hifiasm can detect such changes and renew Hi-C bin files automatically. - - - -For Hi-C integrated assembly, why the assembly size of both haplotypes are much larger than the estimated genome size? ------------------------------------------------------------------------------------------------------------------------------- - It is likely that hifiasm misidentifies coverage threshold for homozygous reads. Hifiasm prints the following information for debugging: - :: - - [M::stat] # heterozygous bases: 645155110; # homozygous bases: 1495396634 - - If most bases of a diploid sample are homozygous, the coverage threshold is wrongly determined by hifiasm. For instance, hifiasm prints the following information during assembly: - :: - - [M::purge_dups] homozygous read coverage threshold: 36 - - In this example, hifiasm identifies the coverage threshold for homozygous reads as ``36``. If it is much smaller than homozygous coverage peak, hifiasm thinks most reads are homozygous and assign them to both assemblies, making both of them much larger than the estimated haploid genome size. In this case, please set ``--hom-cov`` to homozygous coverage peak. Please note that tuning ``--hom-cov`` may affect ``*p_utg*gfa`` so that ``*hic*.bin`` should be deleted. Since v0.15.5, hifiasm can detect such changes and renew Hi-C bin files automatically. - - -.. _hic-iss: - -How can I tweak parameters to improve Hi-C integrated assembly? ---------------------------------------------------------------- - Compared with the HiFi-only assembly or the trio-binning assembly, the Hi-C integrated assembly is a little bit more complex so that you need to take care of the results. See `Why one Hi-C integrated assembly is larger than another one?`_ and `For Hi-C integrated assembly, why the assembly size of both haplotypes are much larger than the estimated genome size?`_ for details on how to fix potential issues. - - There are several other options that may affect the Hi-C integrated assembly. Increasing the values of ``--n-weight``, ``--n-perturb`` and ``--f-perturb`` may improve phasing results but takes longer time. However, tuning ``--l-msjoin`` is tricky. All these options do not affect ``*p_utg*gfa`` so that ``*hic*.bin`` can be reused. - -.. _p-large: - -Why the size of primary assembly or partially phased assembly is much larger than the estimated genome size? ---------------------------------------------------------------------------------------------------------------- - It could be because the estimated genome size is incorrect. Another possibility is that hifiasm does not perform enough purging. Setting smaller value for ``-s`` (default: 0.55) or turning ``--hom-cov`` should be helpful. See :ref:`loginter` for more details. - - -.. _p-hamming: - -Why the hamming error rate or the swith error rate of trio-binning assembly is very high? ---------------------------------------------------------------------------------------------------------------- - In rare cases, a potential issue is that a few contigs may misjoin two haplotypes. For example, half of a contig come from mother while another half come from father. Such misjoined contigs can be fixed by manually breaking. The coordinates of problematic regions can be found by A-lines in GFA file or ``yak trioeval -e`` (see `issue 37 `_ for more details). However, if there are many misjoined contigs or the switch/hamming error rate reported by ``yak trioeval`` is very high, users should check if the parental data is correct (see `issue 130 `_ for more details). - - Another possibility is that there are some unitigs in unitig graph misjoining two haplotypes. Such problematic unitigs might be ignored by the graph-binning strategy. Set smaller value for ``--t-occ`` forcedly remove unitig including unexpected haplotype-specific reads. - -Why does hifiasm stuck or crash? -------------------------------------- - In most cases, it is caused by the low quality HiFi reads. A good HiFi dataset should have a k-mer plot like `issue10 `_ or `issue49 `_. In contrast, low quality HiFi data often lead to weird k-mer plot like `issue93 `_. Such weird k-mer plots usually indicate insufficient coverage or presence of contaminants. See :ref:`loginter` for more details. If the HiFi data look fine, please raise an issue at the `issue page `_. - -What's the usage of different bin files in hifiasm? ----------------------------------------------------- - ``*ec.bin``, ``*ovlp.reverse.bin`` and ``*ovlp.source.bin`` save the results of error correction step. ``*hic*bin`` saves the results of Hi-C alignment. Please note that ``*hic*.bin`` should be deleted when tuning any parameters affecting ``*p_utg*gfa``. There are several parameters which does not change ``*p_utg*gfa``, including ``-s``, ``--seed``, ``--n-weight``, ``--n-perturb``, ``--f-perturb`` and ``--l-msjoin``. Since v0.15.5, hifiasm can detect such changes and renew Hi-C bin files automatically. - -Can I generate HiFi-only assembly first, and then add Hi-C or trio data later? ----------------------------------------------------------------------------------------- - Yes, the HiFi-only assembly, Hi-C phased assembly and trio-binning assembly share the same ``*ec.bin``, ``*ovlp.reverse.bin`` and ``*ovlp.source.bin``. - -What is the minimum read coverage required for hifiasm? -------------------------------------------------------- - Usually >=13x HiFi reads per haplotype. Higher coverage might be able to improve the contiguity of assembly. - -Why the primary assembly is more contiguous than the fully-phased assemblies and the partially phased assemblies (i.e. ``*.hap*.p_ctg.gfa``)? ----------------------------------------------------------------------------------------------------------------------------------------------------- - - For diploid samples, primary assembly usually has greater N50 but at the expense of highly fragmented alternate assembly. From the method view, the primary assembly has an extra joining step, which joins two haplotypes to make primary assembly more contiguous. - - When producing fully-phased assemblies and partially phased assemblies, hifiasm is designed to keep both haplotypes contiguous. It is important for many downstream applications like SV calling. - -My assembly is fragmented or not contiguous enough, how do I improve it? --------------------------------------------------------------------------- - - Raising ``-D`` or ``-N`` may improve the resolution of repetitive regions but takes longer time. These two options affect all types of assemblies and usually do not have a negative impact on the assembly quality. In contrast, ``--purge-max`` only affects primary assembly. Setting larger value for ``--purge-max`` makes primary assembly more contiguous but may collapse repeats or segmental duplications. - - If the assembly is too fragmented, users should check if HiFi data is good enough. See `Why does hifiasm stuck or crash?`_ for details. - -How do I avoid misassemblies? --------------------------------------------------------------------------- + +.. _faq: + +Hifiasm FAQ +=========== + + +.. contents:: + :local: + + +How do I get contigs in FASTA? +------------------------------------- + The FASTA file can be produced from GFA as follows: + :: + + awk '/^S/{print ">"$2;print $3}' test.p_ctg.gfa > test.p_ctg.fa + +Which types of assemblies should I use? +---------------------------------------- + If parental data is available, ``*dip.hap*.p_ctg.gfa`` produced in trio-binning mode should be always preferred. Otherwise if Hi-C data is available, ``*hic.hap*.p_ctg.gfa`` produced in Hi-C mode is the best choice. Both trio-binning mode and Hi-C mode generate fully-phased assemblies. + + If you only have HiFi reads, hifiasm in default outputs ``*bp.hap*.p_ctg.gfa``. The primary/alternate assemblies can be also produced by using ``--primary``. All these HiFi-only assemblies are not fully-phased. See `blog `_ here for more details. + +Are inbred/homozygous genomes supported? +-------------------------------------------------------------------------- + + Yes, please use the ``-l0`` option to disable purge duplication step. + +Are diploid genomes supported? +------------------------------------- + Yes, most modules of hifiasm are designed for diploid samples, including purge duplication step, partially phased assembly and fully-phased assembly with trio-binning or Hi-C. + +Are polyploid genomes supported? +------------------------------------- + + The ``*r_utg.gfa`` and ``*p_utg.gfa`` are lossless so that they also work for polyploid genomes. However, currently the contig-generation modules of hifiasm are designed for diploid samples, which means both the partially phased assembly and the fully-phased assembly does not directly support polyploid genomes. If it is set to >2, the quality of primary assembly for polyploid genomes might be improved. Please use primary assembly for polyploid samples and run multiple rounds of purging steps using third-party tools such as purge_dups. + +Why one Hi-C integrated assembly is larger than another one? +------------------------------------------------------------ + + For some samples like human male, the paternal haplotype should be larger than the maternal haplotype. However, if one assembly is much larger than another one, it should be the issues of hifiasm. To fix it, please set smaller value for ``-s`` (default: 0.55). + + Another possibility is that hifiasm misidentifies coverage threshold for homozygous reads. For instance, hifiasm prints the following information during assembly: + :: + + [M::purge_dups] homozygous read coverage threshold: 36 + + In this example, hifiasm identifies the coverage threshold for homozygous reads as ``36``. If it is significantly smaller than the homozygous coverage peak, hifiasm will generate two unbalanced assemblies. In this case, please set ``--hom-cov`` to homozygous coverage peak. Please note that tuning ``--hom-cov`` may affect ``*p_utg*gfa`` so that ``*hic*.bin`` should be deleted. Since v0.15.5, hifiasm can detect such changes and renew Hi-C bin files automatically. + + + +For Hi-C integrated assembly, why the assembly size of both haplotypes are much larger than the estimated genome size? +------------------------------------------------------------------------------------------------------------------------------ + It is likely that hifiasm misidentifies coverage threshold for homozygous reads. Hifiasm prints the following information for debugging: + :: + + [M::stat] # heterozygous bases: 645155110; # homozygous bases: 1495396634 + + If most bases of a diploid sample are homozygous, the coverage threshold is wrongly determined by hifiasm. For instance, hifiasm prints the following information during assembly: + :: + + [M::purge_dups] homozygous read coverage threshold: 36 + + In this example, hifiasm identifies the coverage threshold for homozygous reads as ``36``. If it is much smaller than homozygous coverage peak, hifiasm thinks most reads are homozygous and assign them to both assemblies, making both of them much larger than the estimated haploid genome size. In this case, please set ``--hom-cov`` to homozygous coverage peak. Please note that tuning ``--hom-cov`` may affect ``*p_utg*gfa`` so that ``*hic*.bin`` should be deleted. Since v0.15.5, hifiasm can detect such changes and renew Hi-C bin files automatically. + + +.. _hic-iss: + +How can I tweak parameters to improve Hi-C integrated assembly? +--------------------------------------------------------------- + Compared with the HiFi-only assembly or the trio-binning assembly, the Hi-C integrated assembly is a little bit more complex so that you need to take care of the results. See `Why one Hi-C integrated assembly is larger than another one?`_ and `For Hi-C integrated assembly, why the assembly size of both haplotypes are much larger than the estimated genome size?`_ for details on how to fix potential issues. + + There are several other options that may affect the Hi-C integrated assembly. Increasing the values of ``--n-weight``, ``--n-perturb`` and ``--f-perturb`` may improve phasing results but takes longer time. However, tuning ``--l-msjoin`` is tricky. All these options do not affect ``*p_utg*gfa`` so that ``*hic*.bin`` can be reused. + +.. _p-large: + +Why the size of primary assembly or partially phased assembly is much larger than the estimated genome size? +--------------------------------------------------------------------------------------------------------------- + It could be because the estimated genome size is incorrect. Another possibility is that hifiasm does not perform enough purging. Setting smaller value for ``-s`` (default: 0.55) or turning ``--hom-cov`` should be helpful. See :ref:`loginter` for more details. + + +.. _p-hamming: + +Why the hamming error rate or the swith error rate of trio-binning assembly is very high? +--------------------------------------------------------------------------------------------------------------- + In rare cases, a potential issue is that a few contigs may misjoin two haplotypes. For example, half of a contig come from mother while another half come from father. Such misjoined contigs can be fixed by manually breaking. The coordinates of problematic regions can be found by A-lines in GFA file or ``yak trioeval -e`` (see `issue 37 `_ for more details). However, if there are many misjoined contigs or the switch/hamming error rate reported by ``yak trioeval`` is very high, users should check if the parental data is correct (see `issue 130 `_ for more details). + + Another possibility is that there are some unitigs in unitig graph misjoining two haplotypes. Such problematic unitigs might be ignored by the graph-binning strategy. Set smaller value for ``--t-occ`` forcedly remove unitig including unexpected haplotype-specific reads. + +Why does hifiasm stuck or crash? +------------------------------------- + In most cases, it is caused by the low quality HiFi reads. A good HiFi dataset should have a k-mer plot like `issue10 `_ or `issue49 `_. In contrast, low quality HiFi data often lead to weird k-mer plot like `issue93 `_. Such weird k-mer plots usually indicate insufficient coverage or presence of contaminants. See :ref:`loginter` for more details. If the HiFi data look fine, please raise an issue at the `issue page `_. + +What's the usage of different bin files in hifiasm? +---------------------------------------------------- + ``*ec.bin``, ``*ovlp.reverse.bin`` and ``*ovlp.source.bin`` save the results of error correction step. ``*hic*bin`` saves the results of Hi-C alignment. Please note that ``*hic*.bin`` should be deleted when tuning any parameters affecting ``*p_utg*gfa``. There are several parameters which does not change ``*p_utg*gfa``, including ``-s``, ``--seed``, ``--n-weight``, ``--n-perturb``, ``--f-perturb`` and ``--l-msjoin``. Since v0.15.5, hifiasm can detect such changes and renew Hi-C bin files automatically. + +Can I generate HiFi-only assembly first, and then add Hi-C or trio data later? +---------------------------------------------------------------------------------------- + Yes, the HiFi-only assembly, Hi-C phased assembly and trio-binning assembly share the same ``*ec.bin``, ``*ovlp.reverse.bin`` and ``*ovlp.source.bin``. + +What is the minimum read coverage required for hifiasm? +------------------------------------------------------- + Usually >=13x HiFi reads per haplotype. Higher coverage might be able to improve the contiguity of assembly. + +Why the primary assembly is more contiguous than the fully-phased assemblies and the partially phased assemblies (i.e. ``*.hap*.p_ctg.gfa``)? +---------------------------------------------------------------------------------------------------------------------------------------------------- + + For diploid samples, primary assembly usually has greater N50 but at the expense of highly fragmented alternate assembly. From the method view, the primary assembly has an extra joining step, which joins two haplotypes to make primary assembly more contiguous. + + When producing fully-phased assemblies and partially phased assemblies, hifiasm is designed to keep both haplotypes contiguous. It is important for many downstream applications like SV calling. + +My assembly is fragmented or not contiguous enough, how do I improve it? +-------------------------------------------------------------------------- + + Raising ``-D`` or ``-N`` may improve the resolution of repetitive regions but takes longer time. These two options affect all types of assemblies and usually do not have a negative impact on the assembly quality. In contrast, ``--purge-max`` only affects primary assembly. Setting larger value for ``--purge-max`` makes primary assembly more contiguous but may collapse repeats or segmental duplications. + + If the assembly is too fragmented, users should check if HiFi data is good enough. See `Why does hifiasm stuck or crash?`_ for details. + +How do I avoid misassemblies? +-------------------------------------------------------------------------- Set smaller value for ``--purge-max``, ``-s`` and ``-O``, or use the ``-u`` option. \ No newline at end of file diff --git a/docs/source/hic-assembly.rst b/docs/source/hic-assembly.rst index 46b7854..bb976ca 100644 --- a/docs/source/hic-assembly.rst +++ b/docs/source/hic-assembly.rst @@ -1,16 +1,16 @@ - -.. _hic-assembly: - -Hi-C Integrated Assembly -======================== - -Hifiasm can generate a pair of haplotype-resolved assemblies with paired-end Hi-C reads:: - - hifiasm -o NA12878.asm -t32 --h1 read1.fq.gz --h2 read2.fq.gz HiFi-reads.fq.gz - -In this mode, each contig is supposed to be a haplotig, which by definition comes from one parental haplotype only. Hifiasm often puts all contigs from the same parental chromosome in one assembly. It has cleanly separated chrX and chrY for a human male dataset. Nonetheless, phasing across centromeres is challenging. Hifiasm is often able to phase entire chromosomes but it may fail in rare cases. Also, contigs from different parental chromosomes are randomly mixed as it is just not possible to phase across chromosomes with Hi-C. Hifiasm does not perform scaffolding for now. You need to run a standalone scaffolder such as SALSA or 3D-DNA to scaffold phased haplotigs. - - -For samples with high heterozygosity rate, a common issue is that one assembly is much larger than another one. To fix this issue, please set smaller value for ``-s`` (default: 0.55). Another possibility is that hifiasm misidentifies coverage threshold for homozygous reads. In this case, please set ``--hom-cov`` to homozygous coverage peak. See :ref:`hic-iss` for more details. - -At the first run, hifiasm saves the alignment of Hi-C reads to disk as ``*hic*.bin``. It reuses the saved results to avoid Hi-C alignment next time. Please note that ``*hic*.bin`` should be deleted when tuning any parameters affecting ``*p_utg*gfa``. Since v0.15.5, hifiasm can detect such changes and renew Hi-C bin files automatically. There are several parameters which do not change ``*p_utg*gfa``, including ``-s``, ``--seed``, ``--n-weight``, ``--n-perturb``, ``--f-perturb`` and ``--l-msjoin``. + +.. _hic-assembly: + +Hi-C Integrated Assembly +======================== + +Hifiasm can generate a pair of haplotype-resolved assemblies with paired-end Hi-C reads:: + + hifiasm -o NA12878.asm -t32 --h1 read1.fq.gz --h2 read2.fq.gz HiFi-reads.fq.gz + +In this mode, each contig is supposed to be a haplotig, which by definition comes from one parental haplotype only. Hifiasm often puts all contigs from the same parental chromosome in one assembly. It has cleanly separated chrX and chrY for a human male dataset. Nonetheless, phasing across centromeres is challenging. Hifiasm is often able to phase entire chromosomes but it may fail in rare cases. Also, contigs from different parental chromosomes are randomly mixed as it is just not possible to phase across chromosomes with Hi-C. Hifiasm does not perform scaffolding for now. You need to run a standalone scaffolder such as SALSA or 3D-DNA to scaffold phased haplotigs. + + +For samples with high heterozygosity rate, a common issue is that one assembly is much larger than another one. To fix this issue, please set smaller value for ``-s`` (default: 0.55). Another possibility is that hifiasm misidentifies coverage threshold for homozygous reads. In this case, please set ``--hom-cov`` to homozygous coverage peak. See :ref:`hic-iss` for more details. + +At the first run, hifiasm saves the alignment of Hi-C reads to disk as ``*hic*.bin``. It reuses the saved results to avoid Hi-C alignment next time. Please note that ``*hic*.bin`` should be deleted when tuning any parameters affecting ``*p_utg*gfa``. Since v0.15.5, hifiasm can detect such changes and renew Hi-C bin files automatically. There are several parameters which do not change ``*p_utg*gfa``, including ``-s``, ``--seed``, ``--n-weight``, ``--n-perturb``, ``--f-perturb`` and ``--l-msjoin``. diff --git a/docs/source/index.rst b/docs/source/index.rst index 4746972..6d821f3 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -1,80 +1,80 @@ -Hifiasm -======= - -.. toctree:: - :hidden: - - pa-assembly - trio-assembly - hic-assembly - interpreting-output - faq - parameter-reference - - - - -`Hifiasm `_ is a fast haplotype-resolved de novo assembler for PacBio HiFi reads. It can assemble a human genome in several hours and assemble a ~30Gb California redwood genome in a few days. Hifiasm emits partially phased assemblies of quality competitive with the best assemblers. Given parental short reads or Hi-C data, it produces arguably the best haplotype-resolved assemblies so far. - -Publications -============ - -Hifiasm - Haoyu Cheng, Gregory T. Concepcion, Xiaowen Feng, Haowen Zhang & Heng Li. - `Haplotype-resolved de novo assembly using phased assembly graphs with hifiasm `_. Nature Methods. (2021). - -Install -======= -The easiest way to get started is to download a `release `_. Please report any issues on `github issues `_ page. - -In addition, the latest unreleased version can be found from github: - -:: - - git clone https://github.com/chhylp123/hifiasm - cd hifiasm && make - -Another way is to install hifiasm via `bioconda `_: - -:: - - conda install -c bioconda hifiasm - -Assembly Concepts -================= -There are different types of assemblies which are commonly used in practice (see -`details `_). -Hifiasm produces primary/alternate assemblies or partially phased assemblies -only with HiFi reads. Given Hi-C data or trio-binning data, hifiasm produces -contiguous fully-phased assemblies, i.e. haplotype-resolved assemblies. - -Why Hifiasm? -============ -* Hifiasm delivers high-quality assemblies. It tends to generate longer contigs - and resolve more segmental duplications than other assemblers. - -* Given Hi-C reads or short reads from the parents, hifiasm can produce overall the best - haplotype-resolved assembly so far. It is the assembler of choice by the - `Human Pangenome Project `_ for the first batch of samples. - -* Hifiasm can purge duplications between haplotigs without relying on - third-party tools such as purge\_dups. Hifiasm does not need polishing tools - like pilon or racon, either. This simplifies the assembly pipeline and saves - running time. - -* Hifiasm is fast. It can assemble a human genome in half a day and assemble a - ~30Gb redwood genome in three days. No genome is too large for hifiasm. - -* Hifiasm is trivial to install and easy to use. It does not required Python, - R or C++11 compilers, and can be compiled into a single executable. The - default setting works well with a variety of genomes. - -Learn -===== - -* :ref:`HiFi-only Assembly ` - Assembling HiFi reads without additional data types -* :ref:`Trio-binning Assembly ` - Producing fully phased assemblies with HiFi and trio-binning data -* :ref:`Hi-C Integrated Assembly ` - Producing fully phased assemblies with HiFi and Hi-C data -* :ref:`Hifiasm Output ` - Interpreting results -* :ref:`Hifiasm FAQ ` - Frequently asked questions -* :ref:`Hifiasm Parameters ` - Parameter reference of hifiasm +Hifiasm +======= + +.. toctree:: + :hidden: + + pa-assembly + trio-assembly + hic-assembly + interpreting-output + faq + parameter-reference + + + + +`Hifiasm `_ is a fast haplotype-resolved de novo assembler for PacBio HiFi reads. It can assemble a human genome in several hours and assemble a ~30Gb California redwood genome in a few days. Hifiasm emits partially phased assemblies of quality competitive with the best assemblers. Given parental short reads or Hi-C data, it produces arguably the best haplotype-resolved assemblies so far. + +Publications +============ + +Hifiasm + Haoyu Cheng, Gregory T. Concepcion, Xiaowen Feng, Haowen Zhang & Heng Li. + `Haplotype-resolved de novo assembly using phased assembly graphs with hifiasm `_. Nature Methods. (2021). + +Install +======= +The easiest way to get started is to download a `release `_. Please report any issues on `github issues `_ page. + +In addition, the latest unreleased version can be found from github: + +:: + + git clone https://github.com/chhylp123/hifiasm + cd hifiasm && make + +Another way is to install hifiasm via `bioconda `_: + +:: + + conda install -c bioconda hifiasm + +Assembly Concepts +================= +There are different types of assemblies which are commonly used in practice (see +`details `_). +Hifiasm produces primary/alternate assemblies or partially phased assemblies +only with HiFi reads. Given Hi-C data or trio-binning data, hifiasm produces +contiguous fully-phased assemblies, i.e. haplotype-resolved assemblies. + +Why Hifiasm? +============ +* Hifiasm delivers high-quality assemblies. It tends to generate longer contigs + and resolve more segmental duplications than other assemblers. + +* Given Hi-C reads or short reads from the parents, hifiasm can produce overall the best + haplotype-resolved assembly so far. It is the assembler of choice by the + `Human Pangenome Project `_ for the first batch of samples. + +* Hifiasm can purge duplications between haplotigs without relying on + third-party tools such as purge\_dups. Hifiasm does not need polishing tools + like pilon or racon, either. This simplifies the assembly pipeline and saves + running time. + +* Hifiasm is fast. It can assemble a human genome in half a day and assemble a + ~30Gb redwood genome in three days. No genome is too large for hifiasm. + +* Hifiasm is trivial to install and easy to use. It does not required Python, + R or C++11 compilers, and can be compiled into a single executable. The + default setting works well with a variety of genomes. + +Learn +===== + +* :ref:`HiFi-only Assembly ` - Assembling HiFi reads without additional data types +* :ref:`Trio-binning Assembly ` - Producing fully phased assemblies with HiFi and trio-binning data +* :ref:`Hi-C Integrated Assembly ` - Producing fully phased assemblies with HiFi and Hi-C data +* :ref:`Hifiasm Output ` - Interpreting results +* :ref:`Hifiasm FAQ ` - Frequently asked questions +* :ref:`Hifiasm Parameters ` - Parameter reference of hifiasm diff --git a/docs/source/interpreting-output.rst b/docs/source/interpreting-output.rst index 0b10c5c..51b88dd 100644 --- a/docs/source/interpreting-output.rst +++ b/docs/source/interpreting-output.rst @@ -1,102 +1,102 @@ - -.. _interpreting-output: - -Hifiasm Output -=============== - -.. _outfile: - -Output files ---------------------------------------- - -In general, hifiasm generates the following assembly graphs in the GFA format: - -* ```prefix`.r_utg.gfa``: haplotype-resolved raw unitig graph. This graph keeps all haplotype information. -* ```prefix`.p_utg.gfa``: haplotype-resolved processed unitig graph without small bubbles. Small bubbles might be caused by somatic mutations or noise in data, which are not the real haplotype information. Hifiasm automatically pops such small bubbles based on coverage. The option ``--hom-cov`` affects the result. See :ref:`homozygous coverage setting ` for more details. In addition, the option ``-p`` forcedly pops bubbles. -* ```prefix`.p_ctg.gfa``: assembly graph of primary contigs. This graph includes a complete assembly with long stretches of phased blocks. -* ```prefix`.a_ctg.gfa``: assembly graph of alternate contigs. This graph consists of all contigs that are discarded in primary contig graph. -* ```prefix`.*hap*.p_ctg.gfa``: phased contig graph. This graph keeps the phased contigs. - - -Hifiasm outputs ``*.r_utg.gfa`` and ``*.p_utg.gfa`` in any cases. Specifically, hifiasm outputs the following assembly graphs in trio-binning mode: - -* ```prefix`.dip.hap1.p_ctg.gfa``: fully phased paternal/haplotype1 contig graph keeping the phased paternal/haplotype1 assembly. -* ```prefix`.dip.hap2.p_ctg.gfa``: fully phased maternal/haplotype2 contig graph keeping the phased maternal/haplotype2 assembly. - -With Hi-C partition options, hifiasm outputs: - -* ```prefix`.hic.p_ctg.gfa``: assembly graph of primary contigs. -* ```prefix`.hic.hap1.p_ctg.gfa``: fully phased contig graph of haplotype1 where each contig is fully phased. -* ```prefix`.hic.hap2.p_ctg.gfa``: fully phased contig graph of haplotype2 where each contig is fully phased. -* ```prefix`.hic.a_ctg.gfa`` (optional with ``--primary``): assembly graph of alternate contigs. - -Hifiasm generates the following assembly graphs only with HiFi reads in default: - -* ```prefix`.bp.p_ctg.gfa``: assembly graph of primary contigs. -* ```prefix`.bp.hap1.p_ctg.gfa``: partially phased contig graph of haplotype1. -* ```prefix`.bp.hap2.p_ctg.gfa``: partially phased contig graph of haplotype2. - -If the option ``--primary`` or ``-l0`` is specified, hifiasm outputs: - -* ```prefix`.p_ctg.gfa``: assembly graph of primary contigs. -* ```prefix`.a_ctg.gfa``: assembly graph of alternate contigs. - -For each graph, hifiasm also outputs a simplified version (``*noseq*gfa``) without sequences for the ease of visualization. The coordinates of low quality regions are written to ``*lowQ.bed`` in BED format. -The concepts of different types of assemblies can be found `here `_. - -.. _outformat: - -Output file formats ---------------------------------------- -Hifiasm broadly follows the specification for `GFA 1.0 `_. There are several fields that are specifically used by hifiasm. For ``S`` segment line: - -* ``rd:i:``: read coverage. It is calculated by the reads coming from the same contig/unitig. - -Hifiasm outputs ``A`` lines including the information of reads which are used to construct contig/unitig. Each ``A`` line is plain-text, tab-separated, and the columns appear in the following order: - -.. list-table:: - :widths: 10 25 50 - :header-rows: 1 - - * - Col - - Type - - Description - * - 1 - - string - - Should be always ``A`` - * - 2 - - string - - Contig/unitig name - * - 3 - - int - - Contig/unitig start coordinate of subregion constructed by read - * - 4 - - char - - Read strand: "+" or "-" - * - 5 - - string - - Read name - * - 6 - - int - - Read start coordinate of subregion which is used to construct contig/unitig - * - 7 - - int - - Read end coordinate of subregion which is used to construct contig/unitig - * - 8 - - id:i:int - - Read ID - * - 9 - - HG:A:char - - Haplotype status of read. ``HG:A:a``, ``HG:A:p``, ``HG:A:m`` indicate read is non-binnable, father/hap1-specific and mother/hap2-specific, respectively. - -.. _loginter: - -Hifiasm log interpretation ---------------------------------------- -Hifiasm prints several information for quick debugging, including: - -.. _homcov: - -* k-mer plot: showing how many k-mers appear a certain number of times. For homozygous samples, there should be one peak around read coverage. For heterozygous samples, there should two peaks, where the smaller peak is around the heterozygous read coverage and the larger peak is around the homozygous read coverage. For example, `issue10 `_ indicates the heterozygous read coverage and the homozygous read coverage are 28 and 57, respectively. `Issue49 `_ is another good example. Weird k-mer plot like `issue93 `_ is often caused by insufficient coverage or presence of contaminants. -* homozygous coverage: coverage threshold for homozygous reads. Hifiasm prints it as: ``[M::purge_dups] homozygous read coverage threshold: X``. If it is not around homozygous coverage, the final assembly might be either too large or too small. To fix this issue, please set ``--hom-cov`` to homozygous coverage. -* number of het/hom bases: how many bases in unitig graph are heterozygous and homozygous during Hi-C phased assembly. Hifiasm prints it as: ``[M::stat] # heterozygous bases: X; # homozygous bases: Y``. Given a heterozygous sample, if there are much more homozygous bases than heterozygous bases, hifiasm fails to identify correct coverage threshold for homozygous reads. In this case, please set ``--hom-cov`` to homozygous coverage. + +.. _interpreting-output: + +Hifiasm Output +=============== + +.. _outfile: + +Output files +--------------------------------------- + +In general, hifiasm generates the following assembly graphs in the GFA format: + +* ```prefix`.r_utg.gfa``: haplotype-resolved raw unitig graph. This graph keeps all haplotype information. +* ```prefix`.p_utg.gfa``: haplotype-resolved processed unitig graph without small bubbles. Small bubbles might be caused by somatic mutations or noise in data, which are not the real haplotype information. Hifiasm automatically pops such small bubbles based on coverage. The option ``--hom-cov`` affects the result. See :ref:`homozygous coverage setting ` for more details. In addition, the option ``-p`` forcedly pops bubbles. +* ```prefix`.p_ctg.gfa``: assembly graph of primary contigs. This graph includes a complete assembly with long stretches of phased blocks. +* ```prefix`.a_ctg.gfa``: assembly graph of alternate contigs. This graph consists of all contigs that are discarded in primary contig graph. +* ```prefix`.*hap*.p_ctg.gfa``: phased contig graph. This graph keeps the phased contigs. + + +Hifiasm outputs ``*.r_utg.gfa`` and ``*.p_utg.gfa`` in any cases. Specifically, hifiasm outputs the following assembly graphs in trio-binning mode: + +* ```prefix`.dip.hap1.p_ctg.gfa``: fully phased paternal/haplotype1 contig graph keeping the phased paternal/haplotype1 assembly. +* ```prefix`.dip.hap2.p_ctg.gfa``: fully phased maternal/haplotype2 contig graph keeping the phased maternal/haplotype2 assembly. + +With Hi-C partition options, hifiasm outputs: + +* ```prefix`.hic.p_ctg.gfa``: assembly graph of primary contigs. +* ```prefix`.hic.hap1.p_ctg.gfa``: fully phased contig graph of haplotype1 where each contig is fully phased. +* ```prefix`.hic.hap2.p_ctg.gfa``: fully phased contig graph of haplotype2 where each contig is fully phased. +* ```prefix`.hic.a_ctg.gfa`` (optional with ``--primary``): assembly graph of alternate contigs. + +Hifiasm generates the following assembly graphs only with HiFi reads in default: + +* ```prefix`.bp.p_ctg.gfa``: assembly graph of primary contigs. +* ```prefix`.bp.hap1.p_ctg.gfa``: partially phased contig graph of haplotype1. +* ```prefix`.bp.hap2.p_ctg.gfa``: partially phased contig graph of haplotype2. + +If the option ``--primary`` or ``-l0`` is specified, hifiasm outputs: + +* ```prefix`.p_ctg.gfa``: assembly graph of primary contigs. +* ```prefix`.a_ctg.gfa``: assembly graph of alternate contigs. + +For each graph, hifiasm also outputs a simplified version (``*noseq*gfa``) without sequences for the ease of visualization. The coordinates of low quality regions are written to ``*lowQ.bed`` in BED format. +The concepts of different types of assemblies can be found `here `_. + +.. _outformat: + +Output file formats +--------------------------------------- +Hifiasm broadly follows the specification for `GFA 1.0 `_. There are several fields that are specifically used by hifiasm. For ``S`` segment line: + +* ``rd:i:``: read coverage. It is calculated by the reads coming from the same contig/unitig. + +Hifiasm outputs ``A`` lines including the information of reads which are used to construct contig/unitig. Each ``A`` line is plain-text, tab-separated, and the columns appear in the following order: + +.. list-table:: + :widths: 10 25 50 + :header-rows: 1 + + * - Col + - Type + - Description + * - 1 + - string + - Should be always ``A`` + * - 2 + - string + - Contig/unitig name + * - 3 + - int + - Contig/unitig start coordinate of subregion constructed by read + * - 4 + - char + - Read strand: "+" or "-" + * - 5 + - string + - Read name + * - 6 + - int + - Read start coordinate of subregion which is used to construct contig/unitig + * - 7 + - int + - Read end coordinate of subregion which is used to construct contig/unitig + * - 8 + - id:i:int + - Read ID + * - 9 + - HG:A:char + - Haplotype status of read. ``HG:A:a``, ``HG:A:p``, ``HG:A:m`` indicate read is non-binnable, father/hap1-specific and mother/hap2-specific, respectively. + +.. _loginter: + +Hifiasm log interpretation +--------------------------------------- +Hifiasm prints several information for quick debugging, including: + +.. _homcov: + +* k-mer plot: showing how many k-mers appear a certain number of times. For homozygous samples, there should be one peak around read coverage. For heterozygous samples, there should two peaks, where the smaller peak is around the heterozygous read coverage and the larger peak is around the homozygous read coverage. For example, `issue10 `_ indicates the heterozygous read coverage and the homozygous read coverage are 28 and 57, respectively. `Issue49 `_ is another good example. Weird k-mer plot like `issue93 `_ is often caused by insufficient coverage or presence of contaminants. +* homozygous coverage: coverage threshold for homozygous reads. Hifiasm prints it as: ``[M::purge_dups] homozygous read coverage threshold: X``. If it is not around homozygous coverage, the final assembly might be either too large or too small. To fix this issue, please set ``--hom-cov`` to homozygous coverage. +* number of het/hom bases: how many bases in unitig graph are heterozygous and homozygous during Hi-C phased assembly. Hifiasm prints it as: ``[M::stat] # heterozygous bases: X; # homozygous bases: Y``. Given a heterozygous sample, if there are much more homozygous bases than heterozygous bases, hifiasm fails to identify correct coverage threshold for homozygous reads. In this case, please set ``--hom-cov`` to homozygous coverage. diff --git a/docs/source/pa-assembly.rst b/docs/source/pa-assembly.rst index c369a09..bbb924c 100644 --- a/docs/source/pa-assembly.rst +++ b/docs/source/pa-assembly.rst @@ -1,47 +1,47 @@ - -.. _pa-assembly: - -HiFi-only Assembly -================== - -A typical hifiasm command line looks like:: - - hifiasm -o NA12878.asm -t 32 NA12878.fq.gz - -where ``NA12878.fq.gz`` provides the input reads, ``-t`` sets the number of CPUs in -use and ``-o`` specifies the prefix of output files. Input sequences should be FASTA -or FASTQ format, uncompressed or compressed with gzip (.gz). The quality scores of reads -in FASTQ are ignored by hifiasm. Hifiasm outputs assemblies in `GFA `_ format. - -At the first run, hifiasm saves corrected reads and overlaps to disk as ``NA12878.asm.*.bin``. It reuses the saved results to avoid the time-consuming all-vs-all overlap calculation next time. You may specify ``-i`` to ignore precomputed overlaps and redo overlapping from raw reads. You can also dump error corrected reads in FASTA and read overlaps in PAF with:: - - hifiasm -o NA12878.asm -t 32 --write-paf --write-ec /dev/null - -Hifiasm purges haplotig duplications by default. For inbred or homozygous genomes, you may disable purging with option ``-l0``. Old HiFi reads may contain short adapter sequences at the ends of reads. You can specify ``-z20`` to trim both ends of reads by 20bp. For small genomes, use ``-f0`` to disable the initial bloom filter which takes 16GB memory at the beginning. For genomes much larger than human, applying ``-f38`` or even ``-f39`` is preferred to save memory on k-mer counting. - - -Produce two partially phased assemblies ---------------------------------------- - - -Since v0.15, hifiasm produces two sets of partially phased contigs in default like:: - - hifiasm -o NA12878.asm -t 32 NA12878.fq.gz - -In this example, the partially phased contigs are written to ``NA12878.asm.bp.hap*.p_ctg.gfa``. -This pair of files can be thought to represent the two haplotypes in a diploid genome, though with occasional switch errors. The frequency of switches is determined by the heterozygosity of the input sample. Hifiasm also writes the primary contigs to ``NA12878.asm.bp.p_ctg.gfa``. - -For samples with high heterozygosity rate, a common issue is that one set of partially phased contigs is much larger than another set. To fix this issue, please set smaller value for ``-s`` (default: 0.55). Another possibility is that hifiasm misidentifies coverage threshold for homozygous reads. -In this case, please set ``--hom-cov`` to homozygous coverage. See :ref:`p-large` for more details. - - -Produce primary/alternate assemblies ------------------------------------- - -To get primary/alternate assemblies, the option ``--primary`` should be set:: - - hifiasm -o NA12878.asm --primary -t 32 NA12878.fq.gz - -The primary contigs and the alternate contigs are written to ``NA12878.asm.p_ctg.gfa`` and ``NA12878.asm.a_ctg.gfa``, respectively. For inbred or homozygous genomes, the primary/alternate assemblies can be also produced by ``-l0``. Similarly, turning ``-s`` or ``--hom-cov`` should -be helpful if the primary assembly is too large. See :ref:`p-large` for more details. - + +.. _pa-assembly: + +HiFi-only Assembly +================== + +A typical hifiasm command line looks like:: + + hifiasm -o NA12878.asm -t 32 NA12878.fq.gz + +where ``NA12878.fq.gz`` provides the input reads, ``-t`` sets the number of CPUs in +use and ``-o`` specifies the prefix of output files. Input sequences should be FASTA +or FASTQ format, uncompressed or compressed with gzip (.gz). The quality scores of reads +in FASTQ are ignored by hifiasm. Hifiasm outputs assemblies in `GFA `_ format. + +At the first run, hifiasm saves corrected reads and overlaps to disk as ``NA12878.asm.*.bin``. It reuses the saved results to avoid the time-consuming all-vs-all overlap calculation next time. You may specify ``-i`` to ignore precomputed overlaps and redo overlapping from raw reads. You can also dump error corrected reads in FASTA and read overlaps in PAF with:: + + hifiasm -o NA12878.asm -t 32 --write-paf --write-ec /dev/null + +Hifiasm purges haplotig duplications by default. For inbred or homozygous genomes, you may disable purging with option ``-l0``. Old HiFi reads may contain short adapter sequences at the ends of reads. You can specify ``-z20`` to trim both ends of reads by 20bp. For small genomes, use ``-f0`` to disable the initial bloom filter which takes 16GB memory at the beginning. For genomes much larger than human, applying ``-f38`` or even ``-f39`` is preferred to save memory on k-mer counting. + + +Produce two partially phased assemblies +--------------------------------------- + + +Since v0.15, hifiasm produces two sets of partially phased contigs in default like:: + + hifiasm -o NA12878.asm -t 32 NA12878.fq.gz + +In this example, the partially phased contigs are written to ``NA12878.asm.bp.hap*.p_ctg.gfa``. +This pair of files can be thought to represent the two haplotypes in a diploid genome, though with occasional switch errors. The frequency of switches is determined by the heterozygosity of the input sample. Hifiasm also writes the primary contigs to ``NA12878.asm.bp.p_ctg.gfa``. + +For samples with high heterozygosity rate, a common issue is that one set of partially phased contigs is much larger than another set. To fix this issue, please set smaller value for ``-s`` (default: 0.55). Another possibility is that hifiasm misidentifies coverage threshold for homozygous reads. +In this case, please set ``--hom-cov`` to homozygous coverage. See :ref:`p-large` for more details. + + +Produce primary/alternate assemblies +------------------------------------ + +To get primary/alternate assemblies, the option ``--primary`` should be set:: + + hifiasm -o NA12878.asm --primary -t 32 NA12878.fq.gz + +The primary contigs and the alternate contigs are written to ``NA12878.asm.p_ctg.gfa`` and ``NA12878.asm.a_ctg.gfa``, respectively. For inbred or homozygous genomes, the primary/alternate assemblies can be also produced by ``-l0``. Similarly, turning ``-s`` or ``--hom-cov`` should +be helpful if the primary assembly is too large. See :ref:`p-large` for more details. + diff --git a/docs/source/parameter-reference.rst b/docs/source/parameter-reference.rst index cac0ed9..02e13cf 100644 --- a/docs/source/parameter-reference.rst +++ b/docs/source/parameter-reference.rst @@ -1,298 +1,298 @@ - -.. _parameter-reference: - -Hifiasm Parameter Reference -============================ - -Synopsis -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Assembly only with HiFi reads: -:: - - hifiasm -o [prefix] -t [nThreads] [options] input1.fq [input2.fq [...]] - -Trio binning assembly with yak dumps: -:: - - yak count -o paternal.yak -b37 [-t nThreads] [-k kmerLen] paternal.fq.gz - yak count -o maternal.yak -b37 [-t nThreads] [-k kmerLen] maternal.fq.gz - hifiasm [-o prefix] [-t nThreads] [options] -1 paternal.yak -2 maternal.yak child.hifi.fq.gz - -Hi-C integrated assembly: -:: - - hifiasm -o [prefix] -t [nThreads] --h1 [hic_r1.fq.gz,...] --h2 [hic_r2.fq.gz,...] [options] HiFi.read.fq.gz - -To get detailed description of options, run: -:: - - hifiasm -h - -or: -:: - - man ./hifiasm.1 - - -General options -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. _oopt: - -**\-o ** - Prefix of output files. See :ref:`outfile` and :ref:`outformat` for more details. - -.. _topt: - -**\-t ** - Number of CPU threads used by hifiasm. - -.. _hopt: - -**\-h** - Show help information. - -.. _versionopt: - -**\-\-version** - Show version number. - - -Error correction options -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. _kopt: - -**\-k ** - K-mer length. This option must be less than 64. - -.. _wopt: - -**\-w ** - Minimizer window size. - -.. _fopt: - -**\-f ** - Number of bits for bloom filter; 0 to disable. This bloom filter is used to filter out singleton k-mers when counting all k-mers. It takes 2\ :sup:`(INT-3)` bytes of memory. A proper setting saves memory. ``-f37`` is recommended for human assembly. For small genomes, use ``-f0`` to disable the initial bloom filter which takes 16GB memory at the beginning. For genomes much larger than human, applying ``-f38`` or even ``-f39`` is preferred to save memory on k-mer counting. - -.. _Dopt: - -**\-D ** - Drop k-mers occurring ``>FLOAT*coverage`` times. Hifiasm discards these high-frequency k-mers during error correction to reduce running time. The ``coverage`` is determined automatically by hifiasm based on k-mer plot, representing homozygous read coverage. Raising this option may improve the resolution of repetitive regions but takes longer time. - -.. _NEopt: - -**\-N ** - Consider up to ``max(-D*coverage,-N)`` overlaps for each oriented read. The ``coverage`` is determined automatically by hifiasm based on k-mer plot, representing homozygous read coverage. Raising this option may improve the resolution of repetitive regions but takes longer time. - -.. _ropt: - -**\-r ** - Rounds of haplotype-aware error correction. This option affects all outputs of hifiasm. Odd rounds of correction are preferred in practice. - - -.. _zopt: - -**\-z ** - Length of adapters that should be removed. This option remove ``INT`` bases from both ends of each read. Some old HiFi reads may consist of short adapters (e.g. 20bp adapter at one end). For such data, trimming short adapters would significantly improve the assembly quality. - -.. _max-kocc-opt: - -**\-\-max-kocc ** - Employ k-mers occurring < ``INT`` times to rescue repetitive overlaps. This option may improve the resolution of repeats. - - -.. _hg-size-opt: - -**\-\-hg-size ** - Estimated haploid genome size used for inferring read coverage. This option is used to get accurate homozygous read coverage during error correction. Common suffices are required, for example, 100m or 3g. - - -.. _min-hist-cnt-opt: - -**\-\-min-hist-cnt ** - When analyzing the k-mer spectrum, ignore counts below ``INT``. For very low coverage of HiFi data, set smaller value for this option. See `issue 45 `_ for example. - - - -Assembly options -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. _aopt: - -**\-a ** - Rounds of assembly graph cleaning. This option is used with ``-x`` and ``-y``. Note that unlike -r, this option does not affect error corrected reads and all-to-all overlaps. - - -.. _mopt: - -**\-m ** - Maximal probing distance for bubble popping when generating primary/alternate contig graphs. Bubbles longer than ``INT`` bases will not be popped. - -.. _popt: - -**\-p ** - Maximal probing distance for bubble popping when generating haplotype-resolved processed unitig graph without small bubbles. Bubbles longer than ``INT`` bases will not be popped. Small bubbles might be caused by somatic mutations or noise in data. Please note that hifiasm automatically pops small bubbles based on coverage, which can be tweaked by ``--hom-cov``. - -.. _nopt: - -**\-n ** - A unitig is considered small if it is composed of less than ``INT`` reads. Hifiasm may try to remove small unitigs at various steps. - -.. _xyopt: - -**\-x , \-y ** - Max and min overlap drop ratio. This option is used with ``-a``. Given a node N in the assembly graph, let max(N) be the length of the longest overlap of N. Hifiasm iteratively drops overlaps of N if their length/max(N) is below a threshold controlled by ``-x`` and ``-y``. Hifiasm applies ``-a`` rounds of short overlap removal with an increasing threshold between ``FLOAT1`` and ``FLOAT2``. - -.. _iopt: - -**\-i** - Ignore all bin files so that hifiasm will start again from scratch. - -.. _uopt: - -**\-u** - Disable post-join step for contigs which may improve N50. The post-join step of hifiasm improves contig N50 but may introduce misassemblies. - - -.. _hom-cov-opt: - -**\-\-hom-cov ** - Homozygous read coverage inferred automatically in default. This option affects different types of outputs, including Hi-C phased assembly and HiFi-only assembly. For more details, see :ref:`hic-iss`, :ref:`p-large` and :ref:`loginter`. - -.. _pri-range-opt: - -**\-\-pri-range ** - Min and max coverage cutoffs of primary contigs. Keep contigs with coverage in this range at p_ctg.gfa. Inferred automatically in default. If ``INT2`` is not specified, it is set to infinity. Set -1 to disable. - -.. _lowQ-opt: - -**\-\-lowQ ** - Output contig regions with ``>=INT%`` inconsistency to the bed file with suffix lowQ.bed. Set 0 to disable. - -.. _b-cov-opt: - -**\-\-b-cov ** - Break contigs at potential misassemblies with ``** - Break contigs at potential misassemblies with ``>INT``-fold coverage. Work with ``--m-rate``. Set -1 to disable. - -.. _m-rate-opt: - -**\-\-m-rate ** - Break contigs with ``<=FLOAT*coverage`` exact overlaps. Only work when ``--b-cov`` and ``--h-cov`` are specified. - -.. _primary-opt: - -**\-\-primary** - Output a primary assembly and an alternate assembly. Enable this option or ``-l0`` outputs a primary assembly and an alternate assembly. - - -Trio-binning options -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. _1opt: - -**\-1 ** - K-mer dump generated by `yak count `_ from the paternal/haplotype1 reads. - -.. _2opt: - -**\-2 ** - K-mer dump generated by `yak count `_ from the maternal/haplotype2 reads. - -.. _3opt: - -**\-3 ** - List of paternal/haplotype1 read names. - -.. _4opt: - -**\-4 ** - List of maternal/haplotype2 read names. - -.. _cdopt: - -**\-c , -d ** - Lower bound and upper bound of the binned k-mer's frequency. When doing trio binning, a k-mer is said to be differentiating if it occurs >= ``INT2`` times in one sample but occurs < ``INT1`` times in the other sample. - - -.. _t-occ-opt: - -**\-\-t-occ ** - Forcedly remove unitig including ``>INT`` unexpected haplotype-specific reads without considering graph topology. For more details, see :ref:`p-hamming`. - - -Purge duplication options -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. _ldopt: - -**\-l ** - Level of purge duplication. 0 to disable, 1 to only purge contained haplotigs, 2 to purge all types of haplotigs, 3 to purge all types of haplotigs in the most aggressive way. In default, 3 for non-trio assembly, 0 for trio-binning assembly. For trio-binning assembly, only level 0 and level 1 are allowed. - -.. _sdopt: - -**\-s ** - Similarity threshold for duplicate haplotigs that should be purged. In default, 0.75 for ``-l1/-l2``, 0.55 for ``-l3``. This option affects both HiFi-only assembly and Hi-C phased assembly. For more details, see :ref:`hic-iss` and :ref:`p-large`. - -.. _ovlpdopt: - -**\-O ** - Min number of overlapped reads for duplicate haplotigs that should be purged. - -.. _purgeopt: - -**\-\-purge-max ** - Coverage upper bound of purge duplication, which is inferred automatically in default. If the coverage of a contig is higher than this bound, don't apply purge duplication. Larger value makes assembly more contiguous but may collapse repeats or segmental duplications. - -.. _nhapopt: - -**\-\-n\-hap ** - Assumption of haplotype number. If it is set to >2, the quality of primary assembly for polyploid genomes might be improved. - - - -Hi-C integration options -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. _h1opt: - -**\-\-h1 ** - File names of input Hi-C R1 ``[r1_1.fq,r1_2.fq,...]``. - -.. _h2opt: - -**\-\-h2 ** - File names of input Hi-C R2 ``[r2_1.fq,r2_2.fq,...]``. - -.. _n-weightopt: - -**\-\-n-weight ** - Rounds of reweighting Hi-C links. Raising this option may improve phasing results but takes longer time. - -.. _n-perturbopt: - -**\-\-n-perturb ** - Rounds of perturbation. Increasing this option may improve phasing results but takes longer time. - -.. _f-perturbopt: - -**\-\-f-perturb ** - Fraction to flip for perturbation. Increasing this option may improve phasing results but takes longer time. - -.. _seedopt: - -**\-\-seed ** - RNG seed. - - -.. _l-msjoin: - -**\-\-l-msjoin ** - Detect misjoined unitigs of ``>=INT`` in size; 0 to disable. + +.. _parameter-reference: + +Hifiasm Parameter Reference +============================ + +Synopsis +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Assembly only with HiFi reads: +:: + + hifiasm -o [prefix] -t [nThreads] [options] input1.fq [input2.fq [...]] + +Trio binning assembly with yak dumps: +:: + + yak count -o paternal.yak -b37 [-t nThreads] [-k kmerLen] paternal.fq.gz + yak count -o maternal.yak -b37 [-t nThreads] [-k kmerLen] maternal.fq.gz + hifiasm [-o prefix] [-t nThreads] [options] -1 paternal.yak -2 maternal.yak child.hifi.fq.gz + +Hi-C integrated assembly: +:: + + hifiasm -o [prefix] -t [nThreads] --h1 [hic_r1.fq.gz,...] --h2 [hic_r2.fq.gz,...] [options] HiFi.read.fq.gz + +To get detailed description of options, run: +:: + + hifiasm -h + +or: +:: + + man ./hifiasm.1 + + +General options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _oopt: + +**\-o ** + Prefix of output files. See :ref:`outfile` and :ref:`outformat` for more details. + +.. _topt: + +**\-t ** + Number of CPU threads used by hifiasm. + +.. _hopt: + +**\-h** + Show help information. + +.. _versionopt: + +**\-\-version** + Show version number. + + +Error correction options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _kopt: + +**\-k ** + K-mer length. This option must be less than 64. + +.. _wopt: + +**\-w ** + Minimizer window size. + +.. _fopt: + +**\-f ** + Number of bits for bloom filter; 0 to disable. This bloom filter is used to filter out singleton k-mers when counting all k-mers. It takes 2\ :sup:`(INT-3)` bytes of memory. A proper setting saves memory. ``-f37`` is recommended for human assembly. For small genomes, use ``-f0`` to disable the initial bloom filter which takes 16GB memory at the beginning. For genomes much larger than human, applying ``-f38`` or even ``-f39`` is preferred to save memory on k-mer counting. + +.. _Dopt: + +**\-D ** + Drop k-mers occurring ``>FLOAT*coverage`` times. Hifiasm discards these high-frequency k-mers during error correction to reduce running time. The ``coverage`` is determined automatically by hifiasm based on k-mer plot, representing homozygous read coverage. Raising this option may improve the resolution of repetitive regions but takes longer time. + +.. _NEopt: + +**\-N ** + Consider up to ``max(-D*coverage,-N)`` overlaps for each oriented read. The ``coverage`` is determined automatically by hifiasm based on k-mer plot, representing homozygous read coverage. Raising this option may improve the resolution of repetitive regions but takes longer time. + +.. _ropt: + +**\-r ** + Rounds of haplotype-aware error correction. This option affects all outputs of hifiasm. Odd rounds of correction are preferred in practice. + + +.. _zopt: + +**\-z ** + Length of adapters that should be removed. This option remove ``INT`` bases from both ends of each read. Some old HiFi reads may consist of short adapters (e.g. 20bp adapter at one end). For such data, trimming short adapters would significantly improve the assembly quality. + +.. _max-kocc-opt: + +**\-\-max-kocc ** + Employ k-mers occurring < ``INT`` times to rescue repetitive overlaps. This option may improve the resolution of repeats. + + +.. _hg-size-opt: + +**\-\-hg-size ** + Estimated haploid genome size used for inferring read coverage. This option is used to get accurate homozygous read coverage during error correction. Common suffices are required, for example, 100m or 3g. + + +.. _min-hist-cnt-opt: + +**\-\-min-hist-cnt ** + When analyzing the k-mer spectrum, ignore counts below ``INT``. For very low coverage of HiFi data, set smaller value for this option. See `issue 45 `_ for example. + + + +Assembly options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _aopt: + +**\-a ** + Rounds of assembly graph cleaning. This option is used with ``-x`` and ``-y``. Note that unlike -r, this option does not affect error corrected reads and all-to-all overlaps. + + +.. _mopt: + +**\-m ** + Maximal probing distance for bubble popping when generating primary/alternate contig graphs. Bubbles longer than ``INT`` bases will not be popped. + +.. _popt: + +**\-p ** + Maximal probing distance for bubble popping when generating haplotype-resolved processed unitig graph without small bubbles. Bubbles longer than ``INT`` bases will not be popped. Small bubbles might be caused by somatic mutations or noise in data. Please note that hifiasm automatically pops small bubbles based on coverage, which can be tweaked by ``--hom-cov``. + +.. _nopt: + +**\-n ** + A unitig is considered small if it is composed of less than ``INT`` reads. Hifiasm may try to remove small unitigs at various steps. + +.. _xyopt: + +**\-x , \-y ** + Max and min overlap drop ratio. This option is used with ``-a``. Given a node N in the assembly graph, let max(N) be the length of the longest overlap of N. Hifiasm iteratively drops overlaps of N if their length/max(N) is below a threshold controlled by ``-x`` and ``-y``. Hifiasm applies ``-a`` rounds of short overlap removal with an increasing threshold between ``FLOAT1`` and ``FLOAT2``. + +.. _iopt: + +**\-i** + Ignore all bin files so that hifiasm will start again from scratch. + +.. _uopt: + +**\-u** + Disable post-join step for contigs which may improve N50. The post-join step of hifiasm improves contig N50 but may introduce misassemblies. + + +.. _hom-cov-opt: + +**\-\-hom-cov ** + Homozygous read coverage inferred automatically in default. This option affects different types of outputs, including Hi-C phased assembly and HiFi-only assembly. For more details, see :ref:`hic-iss`, :ref:`p-large` and :ref:`loginter`. + +.. _pri-range-opt: + +**\-\-pri-range ** + Min and max coverage cutoffs of primary contigs. Keep contigs with coverage in this range at p_ctg.gfa. Inferred automatically in default. If ``INT2`` is not specified, it is set to infinity. Set -1 to disable. + +.. _lowQ-opt: + +**\-\-lowQ ** + Output contig regions with ``>=INT%`` inconsistency to the bed file with suffix lowQ.bed. Set 0 to disable. + +.. _b-cov-opt: + +**\-\-b-cov ** + Break contigs at potential misassemblies with ``** + Break contigs at potential misassemblies with ``>INT``-fold coverage. Work with ``--m-rate``. Set -1 to disable. + +.. _m-rate-opt: + +**\-\-m-rate ** + Break contigs with ``<=FLOAT*coverage`` exact overlaps. Only work when ``--b-cov`` and ``--h-cov`` are specified. + +.. _primary-opt: + +**\-\-primary** + Output a primary assembly and an alternate assembly. Enable this option or ``-l0`` outputs a primary assembly and an alternate assembly. + + +Trio-binning options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _1opt: + +**\-1 ** + K-mer dump generated by `yak count `_ from the paternal/haplotype1 reads. + +.. _2opt: + +**\-2 ** + K-mer dump generated by `yak count `_ from the maternal/haplotype2 reads. + +.. _3opt: + +**\-3 ** + List of paternal/haplotype1 read names. + +.. _4opt: + +**\-4 ** + List of maternal/haplotype2 read names. + +.. _cdopt: + +**\-c , -d ** + Lower bound and upper bound of the binned k-mer's frequency. When doing trio binning, a k-mer is said to be differentiating if it occurs >= ``INT2`` times in one sample but occurs < ``INT1`` times in the other sample. + + +.. _t-occ-opt: + +**\-\-t-occ ** + Forcedly remove unitig including ``>INT`` unexpected haplotype-specific reads without considering graph topology. For more details, see :ref:`p-hamming`. + + +Purge duplication options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _ldopt: + +**\-l ** + Level of purge duplication. 0 to disable, 1 to only purge contained haplotigs, 2 to purge all types of haplotigs, 3 to purge all types of haplotigs in the most aggressive way. In default, 3 for non-trio assembly, 0 for trio-binning assembly. For trio-binning assembly, only level 0 and level 1 are allowed. + +.. _sdopt: + +**\-s ** + Similarity threshold for duplicate haplotigs that should be purged. In default, 0.75 for ``-l1/-l2``, 0.55 for ``-l3``. This option affects both HiFi-only assembly and Hi-C phased assembly. For more details, see :ref:`hic-iss` and :ref:`p-large`. + +.. _ovlpdopt: + +**\-O ** + Min number of overlapped reads for duplicate haplotigs that should be purged. + +.. _purgeopt: + +**\-\-purge-max ** + Coverage upper bound of purge duplication, which is inferred automatically in default. If the coverage of a contig is higher than this bound, don't apply purge duplication. Larger value makes assembly more contiguous but may collapse repeats or segmental duplications. + +.. _nhapopt: + +**\-\-n\-hap ** + Assumption of haplotype number. If it is set to >2, the quality of primary assembly for polyploid genomes might be improved. + + + +Hi-C integration options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _h1opt: + +**\-\-h1 ** + File names of input Hi-C R1 ``[r1_1.fq,r1_2.fq,...]``. + +.. _h2opt: + +**\-\-h2 ** + File names of input Hi-C R2 ``[r2_1.fq,r2_2.fq,...]``. + +.. _n-weightopt: + +**\-\-n-weight ** + Rounds of reweighting Hi-C links. Raising this option may improve phasing results but takes longer time. + +.. _n-perturbopt: + +**\-\-n-perturb ** + Rounds of perturbation. Increasing this option may improve phasing results but takes longer time. + +.. _f-perturbopt: + +**\-\-f-perturb ** + Fraction to flip for perturbation. Increasing this option may improve phasing results but takes longer time. + +.. _seedopt: + +**\-\-seed ** + RNG seed. + + +.. _l-msjoin: + +**\-\-l-msjoin ** + Detect misjoined unitigs of ``>=INT`` in size; 0 to disable. diff --git a/docs/source/trio-assembly.rst b/docs/source/trio-assembly.rst index 17d0391..f164ab7 100644 --- a/docs/source/trio-assembly.rst +++ b/docs/source/trio-assembly.rst @@ -1,29 +1,29 @@ - -.. _trio-assembly: - -Trio-binning Assembly -===================== - -When parental short reads are available, hifiasm can also generate a pair of haplotype-resolved assemblies with trio binning. To perform such assembly, you need to count k-mers first with `yak `_ and then do assembly:: - - yak count -k31 -b37 -t16 -o pat.yak paternal.fq.gz - yak count -k31 -b37 -t16 -o mat.yak maternal.fq.gz - hifiasm -o NA12878.asm -t 32 -1 pat.yak -2 mat.yak NA12878.fq.gz - -Here ``NA12878.asm.hap1.p_ctg.gfa`` and ``NA12878.asm.hap2.p_ctg.gfa`` give the assemblies for two haplotypes. In the binning mode, hifiasm does not purge haplotig duplicates by default. Because hifiasm reuses saved overlaps, you can generate both primary/alternate assemblies and trio binning assemblies with:: - - hifiasm -o NA12878.asm --primary -t 32 NA12878.fq.gz 2> NA12878.asm.pri.log - hifiasm -o NA12878.asm -t 32 -1 pat.yak -2 mat.yak /dev/null 2> NA12878.asm.trio.log - -The second command line will run much faster than the first. The phasing switch error rate and hamming error rate are able to be evaluated quickly by `yak `_:: - - yak trioeval -t16 pat.yak mat.yak assembly.fa - -The W-line and H-line reported by ``yak trioeval`` indicate switch error rate and hamming error rate respectively:: - - W 26714 3029448 0.008818 - H 24315 3029885 0.008025 - -For this example, the switch error rate is 0.8818% and the hamming error rate is 0.8025%. If the hamming error rate or the swith error rate of trio-binning assembly is very high, it might be caused by hifiasm or the incorrect parental data. To fix it, see :ref:`p-hamming` for more details. - - + +.. _trio-assembly: + +Trio-binning Assembly +===================== + +When parental short reads are available, hifiasm can also generate a pair of haplotype-resolved assemblies with trio binning. To perform such assembly, you need to count k-mers first with `yak `_ and then do assembly:: + + yak count -k31 -b37 -t16 -o pat.yak paternal.fq.gz + yak count -k31 -b37 -t16 -o mat.yak maternal.fq.gz + hifiasm -o NA12878.asm -t 32 -1 pat.yak -2 mat.yak NA12878.fq.gz + +Here ``NA12878.asm.hap1.p_ctg.gfa`` and ``NA12878.asm.hap2.p_ctg.gfa`` give the assemblies for two haplotypes. In the binning mode, hifiasm does not purge haplotig duplicates by default. Because hifiasm reuses saved overlaps, you can generate both primary/alternate assemblies and trio binning assemblies with:: + + hifiasm -o NA12878.asm --primary -t 32 NA12878.fq.gz 2> NA12878.asm.pri.log + hifiasm -o NA12878.asm -t 32 -1 pat.yak -2 mat.yak /dev/null 2> NA12878.asm.trio.log + +The second command line will run much faster than the first. The phasing switch error rate and hamming error rate are able to be evaluated quickly by `yak `_:: + + yak trioeval -t16 pat.yak mat.yak assembly.fa + +The W-line and H-line reported by ``yak trioeval`` indicate switch error rate and hamming error rate respectively:: + + W 26714 3029448 0.008818 + H 24315 3029885 0.008025 + +For this example, the switch error rate is 0.8818% and the hamming error rate is 0.8025%. If the hamming error rate or the swith error rate of trio-binning assembly is very high, it might be caused by hifiasm or the incorrect parental data. To fix it, see :ref:`p-hamming` for more details. + + diff --git a/ecovlp.cpp b/ecovlp.cpp index 9b1fd45..9382e95 100644 --- a/ecovlp.cpp +++ b/ecovlp.cpp @@ -1,6513 +1,7204 @@ -#include -#include -#include -#include "Correct.h" -#include "Process_Read.h" -#include "ecovlp.h" -#include "kthread.h" -#include "htab.h" -#define HA_KMER_GOOD_RATIO 0.333 -#define E_KHIT 31 -#define CNS_DEL_E (0x7fffffffu) -#define del_cns_arc(z, arc_i) ((z).arc.a[(arc_i)].v == CNS_DEL_E) -#define CNS_DEL_V (0x1fffffffu) -#define del_cns_nn(z, nn_i) ((z).a[(nn_i)].sc == CNS_DEL_V) -#define REFRESH_N 128 -#define COV_W 3072 -#define RES_K 19 -#define RES_W 19 - -KDQ_INIT(uint32_t) - -typedef struct { - uint32_t v:31, f:1; - uint32_t sc; -} cns_arc; -typedef struct {size_t n, m, nou; cns_arc *a; } cns_arc_v; - -typedef struct { - // uint16_t c:2, t:2, f:1, sc:3; - uint32_t c:2, f:1, sc:29; - cns_arc_v arc; -}cns_t; - -typedef struct { - size_t n, m; - cns_t *a; - uint32_t si, ei, off, bn, bb0, bb1, cns_g_wl; - kdq_t(uint32_t) *q; -}cns_gfa; - -typedef struct { - // chaining and overlapping related buffers - UC_Read self_read, ovlp_read; - Candidates_list clist; - overlap_region_alloc olist; - ha_abuf_t *ab; - // int64_t num_read_base, num_correct_base, num_recorrect_base; - uint64_t cnt[6], rr; - haplotype_evdience_alloc hap; - bit_extz_t exz; - kv_ul_ov_t pidx; - asg64_v v64; - asg32_v v32; - asg16_v v16; - asg8_v v8q, v8t; - - kvec_t_u8_warp k_flag; - st_mt_t sp; - cns_gfa cns; -} ec_ovec_buf_t0; - -typedef struct { - ec_ovec_buf_t0 *a; - uint32_t n, rev; - uint8_t *cr; -} ec_ovec_buf_t; - -typedef struct { - ec_ovec_buf_t *p; - asg64_v idx; - ma_ug_t *ug; -} ec_polish_buf_t; - -typedef struct { - uint32_t n_thread, n_a, chunk_size, cn; - FILE *fp; -} cal_ec_r_dbg_t; - -typedef struct { - ma_hit_t *a; - size_t n, m; - asg16_v ec; -} r_dbg_step_res_t; - -typedef struct { // data structure for each step in kt_pipeline() - ec_ovec_buf_t *buf; - r_dbg_step_res_t *res; - uint32_t si, ei; -} cal_ec_r_dbg_step_t; - -ec_ovec_buf_t* gen_ec_ovec_buf_t(uint32_t n); -void destroy_ec_ovec_buf_t(ec_ovec_buf_t *p); - - -#define generic_key(x) (x) -KRADIX_SORT_INIT(ec16, uint16_t, generic_key, 2) -KRADIX_SORT_INIT(ec32, uint32_t, generic_key, 4) -KRADIX_SORT_INIT(ec64, uint64_t, generic_key, 8) - -#define kdq_clear(q) ((q)->count = (q)->front = 0) - -typedef struct {size_t n, m; asg16_v *a; uint8_t *f; } cc_v; -cc_v scc = {0, 0, NULL, NULL}; -cc_v scb = {0, 0, NULL, NULL}; -cc_v sca = {0, 0, NULL, NULL}; - -typedef struct {size_t n, m; char *a; UC_Read z; asg8_v q;} sl_v; - - -void h_ec_lchain(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, - int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t mcopy_num, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut, uint64_t ocv_w); -void h_ec_lchain_amz(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, - int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut, uint64_t ocv_w); -void h_ec_lchain_re_gen(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, ha_pt_t *ha_idx, All_reads *rref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, - int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, - int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip, UC_Read *tu, asg64_v *oidx, asg16_v *scc); -void h_ec_lchain_re_gen3(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, ha_pt_t *ha_idx, All_reads *rref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, - int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, - int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip, UC_Read *tu, asg64_v *oidx, asg16_v *scc); -uint64_t get_mz1(const char *str, int len, int w, int k, uint32_t rid, int is_hpc, ha_abuf_t *ab, const void *hf, ha_pt_t *ha_idx, int sample_dist, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, ha_pt_t *pt, int min_freq, int32_t dp_min_len, float dp_e, st_mt_t *mt, int32_t ws, int32_t is_unique, void *km, uint64_t beg_i); -void get_pi_ec_chain(ha_abuf_t *ab, uint64_t rid, uint64_t rl, uint32_t tid, char* ts, uint64_t tl, uint64_t mz_w, uint64_t mz_k, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, - int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, /**uint32_t is_accurate,**/ uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, - int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip); -void set_lchain_dp_op(uint32_t is_accurate, uint32_t mz_k, int64_t *max_skip, int64_t *max_iter, int64_t *max_dis, double *chn_pen_gap, double *chn_pen_skip, int64_t *quick_check); -void h_ec_lchain_re_gen_srt(ha_abuf_t *ab, ha_pt_t *ha_idx, overlap_region_alloc *olst, Candidates_list *cl); -uint64_t h_ec_lchain_re_gen_qry(ha_abuf_t *ab, uint64_t *k, uint64_t *l, uint64_t *i, uint64_t *idx_a, uint64_t idx_n, uint64_t *tid, uint64_t *trev); -uint64_t h_ec_lchain_re_chn(ha_abuf_t *ab, uint64_t si, uint64_t ei, uint32_t rid, char* rs, uint64_t rl, uint64_t tid, char* ts, uint64_t tl, uint64_t trev, uint64_t mz_w, uint64_t mz_k, overlap_region_alloc *olst, Candidates_list *cl, double bw_thres, - int apend_be, uint64_t max_cnt, uint64_t min_cnt, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip, tiny_queue_t *tq, asg16_v *scc, int64_t *n, int64_t *zn); -overlap_region* h_ec_lchain_fast(ha_abuf_t *ab, uint32_t rid, UC_Read *qu, UC_Read *tu, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v *buf, asg64_v *srt_i, double bw_thres, - int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1, double sh); -void h_ec_lchain_fast_new(ha_abuf_t *ab, uint32_t rid, UC_Read *qu, UC_Read *tu, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v *buf, asg64_v *srt_i, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1, double sh); - -ec_ovec_buf_t* gen_ec_ovec_buf_t(uint32_t n) -{ - uint32_t k; ec_ovec_buf_t0 *z = NULL; - ec_ovec_buf_t *p = NULL; CALLOC(p, 1); - p->n = n; CALLOC(p->a, p->n); - for (k = 0; k < p->n; k++) { - z = &(p->a[k]); - init_UC_Read(&z->self_read); - init_UC_Read(&z->ovlp_read); - init_Candidates_list(&z->clist); - init_overlap_region_alloc(&z->olist); - - // init_fake_cigar(&(z->tmp.f_cigar)); - // memset(&(z->tmp.w_list), 0, sizeof(z->tmp.w_list)); - // CALLOC(z->tmp.w_list.a, 1); z->tmp.w_list.n = z->tmp.w_list.m = 1; - - // kv_init(z->b_buf.a); - // kv_init(z->r_buf.a); - kv_init(z->k_flag.a); - kv_init(z->sp); - kv_init(z->pidx); - kv_init(z->v64); - kv_init(z->v32); - kv_init(z->v16); - kv_init(z->v8q); - kv_init(z->v8t); - init_bit_extz_t(&(z->exz), 31); - - z->ab = ha_abuf_init(); - - InitHaplotypeEvdience(&z->hap); - z->cns.q = kdq_init(uint32_t); - } - - return p; -} - -void destroy_cns_gfa(cns_gfa *p) -{ - size_t k; - for (k = 0; k < p->m; k++) { - kv_destroy(p->a[k].arc); - } - free(p->a); kdq_destroy(uint32_t, p->q); -} - -void destroy_ec_ovec_buf_t(ec_ovec_buf_t *p) -{ - uint32_t k; ec_ovec_buf_t0 *z = NULL; - for (k = 0; k < p->n; k++) { - z = &(p->a[k]); z->rr = 0; - destory_UC_Read(&z->self_read); - destory_UC_Read(&z->ovlp_read); - destory_Candidates_list(&z->clist); - destory_overlap_region_alloc(&z->olist); - - // destory_fake_cigar(&(z->tmp.f_cigar)); - // free(z->tmp.w_list.a); free(z->tmp.w_list.c.a); - - // kv_destroy(z->r_buf.a); - kv_destroy(z->k_flag.a); - kv_destroy(z->sp); - kv_destroy(z->pidx); - kv_destroy(z->v64); - kv_destroy(z->v32); - kv_destroy(z->v16); - kv_destroy(z->v8q); - kv_destroy(z->v8t); - destroy_bit_extz_t(&(z->exz)); - - ha_abuf_destroy(z->ab); - - destoryHaplotypeEvdience(&z->hap); - destroy_cns_gfa(&(z->cns)); - - } - free(p->a); free(p->cr); free(p); - - // fprintf(stderr, "[M::%s-chains] #->%lld\n", __func__, asm_opt.num_bases); - // fprintf(stderr, "[M::%s-passed-chains-0] #->%lld\n", __func__, asm_opt.num_corrected_bases); - // fprintf(stderr, "[M::%s-cis-chains-1] #->%lld\n", __func__, asm_opt.num_recorrected_bases); -} - -inline void refresh_ec_ovec_buf_t0(ec_ovec_buf_t0 *z, uint64_t n) -{ - z->rr++; - if((z->rr%n) == 0) { - free(z->self_read.seq); memset(&(z->self_read), 0, sizeof(z->self_read)); - free(z->ovlp_read.seq); memset(&(z->ovlp_read), 0, sizeof(z->ovlp_read)); - - destory_Candidates_list(&z->clist); memset(&(z->clist), 0, sizeof(z->clist)); - destory_overlap_region_alloc(&z->olist); memset(&(z->olist), 0, sizeof(z->olist)); init_overlap_region_alloc(&z->olist); - - kv_destroy(z->k_flag.a); kv_init(z->k_flag.a); - kv_destroy(z->sp); kv_init(z->sp); - kv_destroy(z->pidx); kv_init(z->pidx); - kv_destroy(z->v64); kv_init(z->v64); - kv_destroy(z->v32); kv_init(z->v32); - kv_destroy(z->v16); kv_init(z->v16); - kv_destroy(z->v8q); kv_init(z->v8q); - kv_destroy(z->v8t); kv_init(z->v8t); - - destroy_bit_extz_t(&(z->exz)); init_bit_extz_t(&(z->exz), 31); - - ha_abuf_destroy(z->ab); z->ab = ha_abuf_init(); - - destoryHaplotypeEvdience(&z->hap); memset(&(z->hap), 0, sizeof(z->hap)); InitHaplotypeEvdience(&z->hap); - - destroy_cns_gfa(&(z->cns)); memset(&(z->cns), 0, sizeof(z->cns)); z->cns.q = kdq_init(uint32_t); - - // z->rr = 1; - } -} - - -void prt_chain(overlap_region_alloc *o) -{ - uint64_t k; - for (k = 0; k < o->length; k++) { - fprintf(stderr, "[M::%s]\t#%u\tlen::%lu\t%u\t%u\t%c\t#%u\tlen::%lu\t%u\t%u\tsc::%d\taln::%u\terr::%u\n", __func__, o->list[k].x_id, Get_READ_LENGTH(R_INF, o->list[k].x_id), o->list[k].x_pos_s, o->list[k].x_pos_e+1, "+-"[o->list[k].y_pos_strand], - o->list[k].y_id, Get_READ_LENGTH(R_INF, o->list[k].y_id), o->list[k].y_pos_s, o->list[k].y_pos_e+1, o->list[k].shared_seed, o->list[k].align_length, o->list[k].non_homopolymer_errors); - } -} - -overlap_region *fetch_aux_ovlp(overlap_region_alloc* ol) /// exactly same to gen_aux_ovlp -{ - if (ol->length + 1 >= ol->size) { - uint64_t sl = ol->size; - ol->size = ol->length + 1; - kroundup64(ol->size); - REALLOC(ol->list, ol->size); - /// need to set new space to be 0 - memset(ol->list + sl, 0, sizeof(overlap_region)*(ol->size - sl)); - } - ///debug for memory - // if(ol->length + 1 >= ol->size) { - // fprintf(stderr, "[M::%s] length::%lu, size::%lu\n", __func__, ol->length, ol->size); - // } - return &(ol->list[ol->length+1]); -} - -typedef struct { - ul_ov_t *c_idx; - asg64_v *idx; - int64_t i, i0, srt_n, rr, ru; - uint64_t mms, mme; -} cc_idx_t; - - -///[s, e) -int64_t extract_sub_cigar_mm(overlap_region *z, int64_t s, int64_t e, ul_ov_t *p, uint64_t *ct) -{ - int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), yk = ovlp_cur_yoff(*p), ck = ovlp_cur_coff(*p), os, oe, t; - bit_extz_t ez; int64_t bd = ovlp_bd(*p), s0, e0; - s0 = ((int64_t)(z->w_list.a[wk].x_start)) + bd; - e0 = ((int64_t)(z->w_list.a[wk].x_end)) + 1 - bd; - if(s < s0) s = s0; if(e > e0) e = e0;///exclude boundary - if(s >= e) return -1; - os = MAX(s, s0); oe = MIN(e, e0); - if(oe <= os) return -1; - - set_bit_extz_t(ez, (*z), wk); - if(!ez.cigar.n) return -1; - int64_t cn = ez.cigar.n, op; int64_t ws, we, ovlp; - if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed - ck = 0; xk = ez.ts; yk = ez.ps; - } - - while (ck > 0 && xk >= s) {///x -> t; y -> p; first insertion and then match/mismatch - --ck; - op = ez.cigar.a[ck]>>14; - if(op!=2) xk -= (ez.cigar.a[ck]&(0x3fff)); - if(op!=3) yk -= (ez.cigar.a[ck]&(0x3fff)); - } - - //some cigar will span s or e - while (ck < cn && xk < e) {//[s, e) - ws = xk; - op = ez.cigar.a[ck]>>14; - ///op == 3: -> x; op == 2: -> y; - if(op!=2) xk += (ez.cigar.a[ck]&(0x3fff)); - if(op!=3) yk += (ez.cigar.a[ck]&(0x3fff)); - ck++; we = xk; - - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - if(op != 2) { - if(!ovlp) continue; - } else {///ws == we - if(ws < s || ws >= e) continue; - } - - - if(op == 0) { - for (t = os + 1; t < oe; t++) { - ct[(t-s)<<1]++; ct[(t-s)<<1] += ((uint64_t)(0x100000000)); - ct[((t-s)<<1)+1]++; ct[((t-s)<<1)+1] += ((uint64_t)(0x100000000)); - } - - t = os; - if(t < oe) { - ct[(t-s)<<1]++; ct[(t-s)<<1] += ((uint64_t)(0x100000000)); - if(os > ws) { - ct[((t-s)<<1)+1]++; ct[((t-s)<<1)+1] += ((uint64_t)(0x100000000)); - } - } - } else if(op!=2) { - for (t = os + 1; t < oe; t++) { - ct[(t-s)<<1]++; - ct[((t-s)<<1)+1]++; - } - - t = os; - if(t < oe) { - ct[(t-s)<<1]++; - if(os > ws) { - ct[((t-s)<<1)+1]++; - } - } - } else { - ct[((ws-s)<<1)+1]++; ///ct[((ws-s)<<1)+1] += ((uint64_t)(0x100000000)); - } - } - - ovlp_cur_xoff(*p) = xk; ovlp_cur_yoff(*p) = yk; ovlp_cur_coff(*p) = ck; ovlp_cur_ylen(*p) = 0; - - return 1; -} - -#define simp_vote_len 6 - -///[s, e) -uint32_t extract_sub_cigar_ii(overlap_region *z, int64_t ql, All_reads *rref, int64_t s, int64_t e, int64_t iws, int64_t iwe, UC_Read* tu, ul_ov_t *p) -{ - int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), yk = ovlp_cur_yoff(*p), ck = ovlp_cur_coff(*p), os, oe, ol; - bit_extz_t ez; int64_t bd = ovlp_bd(*p), s0, e0, ii[2], it[2]; uint32_t res = (uint32_t)-1; - s0 = ((int64_t)(z->w_list.a[wk].x_start)) + bd; - e0 = ((int64_t)(z->w_list.a[wk].x_end)) + 1 - bd; - if(s < s0) s = s0; if(e > e0) e = e0;///exclude boundary - if(s > e) return -1;///it is possible s == e - os = MAX(s, s0); oe = MIN(e, e0); - if(oe < os) return -1;///it is possible os == oe - // fprintf(stderr, "[M::%s] s0::%ld, e0::%ld, iws::%ld, iwe::%ld\n", __func__, s0, e0, iws, iwe); - ///make sure that this alignment block could cover the whole [iws, iwe) -> s0 < iws && e0 > iwe - // if((s0 >= iws) || (e0 <= iwe)) return -1;///!(s0 < iws && e0 > iwe) -> only consider the alignment that could cover the whole [s, e) - if(!(((s0 < iws) || (s0 == 0)) && ((e0 > iwe) || (e0 == ql)))) return -1;///!(s0 < iws && e0 > iwe) -> only consider the alignment that could cover the whole [s, e) - - set_bit_extz_t(ez, (*z), wk); - if(!ez.cigar.n) return -1; - int64_t cn = ez.cigar.n; uint16_t op; int64_t ws, we, wts, wte, ovlp, cc = 0, cci; - if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed - ck = 0; xk = ez.ts; yk = ez.ps; - } - - while (ck > 0 && xk >= s) {///x -> t; y -> p; first insertion and then match/mismatch - --ck; - op = ez.cigar.a[ck]>>14; - if(op!=2) xk -= (ez.cigar.a[ck]&(0x3fff)); - if(op!=3) yk -= (ez.cigar.a[ck]&(0x3fff)); - } - - // char cm[4]; cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; - //some cigar will span s or e - ii[0] = ii[1] = it[0] = it[1] = -1; res = cc = 0; - while (ck < cn && xk < e) {//[s, e) - ws = xk; wts = yk; - op = ez.cigar.a[ck]>>14; ol = (ez.cigar.a[ck]&(0x3fff)); - ///op == 3: -> x; op == 2: -> y; - if(op!=2) xk += ol; - if(op!=3) yk += ol; - ck++; we = xk; wte = yk; - - // if(s == 10480) { - // fprintf(stderr, "[%ld, %ld)\t%c\n", ws, we, cm[op]); - // } - - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - - if(s == e) {///insertion in comparsion with the reference - if(op != 0 || ws >= s || we <= e || e != iwe || s != iws) continue;///must be a match - } else { - if(op != 2) { - if(!ovlp) continue; - } else {///ws == we - if(ws < s || ws >= e) continue; - } - } - - - if(ii[0] == -1) { - ii[0] = os; - if(op < 2) { - it[0] = os - ws + wts; - } else {///op == 2: more y; p == 3: more x - it[0] = wts; - } - } - - ii[1] = oe; - if(op < 2) { - it[1] = oe - ws + wts; - } else {///op == 2: more y; p == 3: more x - it[1] = wte; - } - - - - - if(op != 2) ol = oe-os; - cc += ol; - // if(s == 11851 && e == 11853) { - // if(!ol) fprintf(stderr, "%ld%c", ol, cm[op]); - // } - if(cc <= simp_vote_len) { - for (cci = 0; cci < ol; cci++) { - res <<= 2; res |= op; - } - } - } - - while (ck < cn && xk <= e) {//[s, e) - ws = xk; wts = yk; - op = ez.cigar.a[ck]>>14; ol = (ez.cigar.a[ck]&(0x3fff)); - if(op != 2) break; - yk += (ez.cigar.a[ck]&(0x3fff)); - ck++; we = xk; wte = yk; - if(ws >= s && ws <= e) { - - if(ii[0] == -1) { - ii[0] = ws; it[0] = wts; - } - ii[1] = we; it[1] = wte; - - cc += ol; - // if(s == 11851 && e == 11853) { - // fprintf(stderr, "%ld%c", ol, cm[op]); - // } - if(cc <= simp_vote_len) { - for (cci = 0; cci < ol; cci++) { - res <<= 2; res |= op; - } - } - } - } - // if(s == 11851 && e == 11853) { - // fprintf(stderr, "\tx::[%ld, %ld)\ty::[%ld, %ld)\tcc::%ld\n", ii[0], ii[1], it[0], it[1], cc); - // } - if((cc <= simp_vote_len) - && (ii[1] >= ii[0]) && (ii[1] - ii[0] <= simp_vote_len) - && (it[1] >= it[0]) && (it[1] - it[0] <= simp_vote_len)) { - // ii[0] = ii[0] - s; ii[1] = e - ii[1]; - if((ii[0] == iws) && (ii[1] == iwe)) { - op = cc; op <<= 12; res |= op; - - char *ystr = NULL; res <<= 16; cc = it[1] - it[0]; op = 0; - if(cc > 0) { - UC_Read_resize(*tu, (it[1] - it[0])); ystr = tu->seq; - recover_UC_Read_sub_region(ystr, it[0], (it[1] - it[0]), z->y_pos_strand, rref, z->y_id); - - for (cci = 0; cci < cc; cci++) { - op <<= 2; op |= seq_nt6_table[(uint32_t)(ystr[cci])]; - } - } - res |= op; - - op = it[1] - it[0]; op <<= 12; res |= op; - } else { - res = (uint32_t)-1; - } - } else { - res = (uint32_t)-1; - } - - - ovlp_cur_xoff(*p) = xk; ovlp_cur_yoff(*p) = yk; ovlp_cur_coff(*p) = ck; ovlp_cur_ylen(*p) = 0; - - return res; -} - -typedef struct { - All_reads *rref; - UC_Read *tu; - uint64_t s, e, n0, n1, id, rev; -} rr_seq_t; - -inline void insert_cns_arc(cns_gfa *cns, uint32_t src, uint32_t des, uint32_t is_ou, uint32_t plus0, uint32_t rid) -{ - if(src >= cns->n) { - fprintf(stderr, "[M::%s] rid::%u, src::%u, des::%u, (*cns).n::%u\n", __func__, rid, src, des, (uint32_t)(*cns).n); - exit(1); - } - cns_arc *p, t; kv_pushp(cns_arc, (*cns).a[src].arc, &p); - p->f = 0; p->sc = plus0; p->v = des; - if(is_ou) { - (*cns).a[src].arc.nou++; - if((*cns).a[src].arc.nou < (*cns).a[src].arc.n) { - t = (*cns).a[src].arc.a[(*cns).a[src].arc.nou-1]; - (*cns).a[src].arc.a[(*cns).a[src].arc.nou-1] = *p; - *p = t; - } - } -} - -inline uint32_t insert_cns_node(cns_gfa *cns) -{ - cns_t *p; uint32_t m0; - if (((*cns)).n == ((*cns)).m) { - m0 = ((*cns)).m; - ((*cns)).m = ((*cns)).m? ((*cns)).m<<1 : 2; - ((*cns)).a = (cns_t*)realloc(((*cns)).a, sizeof(cns_t) * ((*cns)).m); - if(((*cns)).m > m0) { - memset(((*cns)).a + m0, 0, sizeof(cns_t)*(((*cns)).m-m0)); - } - } - *(&p) = &((*cns)).a[((*cns)).n++]; - p->arc.n = p->arc.nou = 0; - p->c = p->f = p->sc = 0; - return ((*cns)).n - 1; -} - -inline uint32_t add_cns_arc(cns_gfa *cns, uint32_t src, uint32_t des, uint32_t is_ou, uint32_t plus) -{ - uint32_t k, s, e; - if(is_ou) { - s = 0; e = (*cns).a[src].arc.nou; - } else { - s = (*cns).a[src].arc.nou; e = (*cns).a[src].arc.n; - } - - for (k = s; k < e; k++) { - if((*cns).a[src].arc.a[k].v == des) { - (*cns).a[src].arc.a[k].sc += plus; - break; - } - } - - return ((k < e)?(1):(0)); -} - -inline void prt_cns_arc(cns_gfa *cns, uint32_t src, const char* cmd) -{ - uint32_t k; - fprintf(stderr, "\n%s\t[M::%s] src::%u, sc::%u, c::%u\n", cmd, __func__, src, (*cns).a[src].sc, (*cns).a[src].c); - for (k = 0; k < (*cns).a[src].arc.n; k++) { - fprintf(stderr, "%s\t[M::%s] des::%u, sc::%u, is_ou::%u\n", cmd, __func__, (*cns).a[src].arc.a[k].v, (*cns).a[src].arc.a[k].sc, k<(*cns).a[src].arc.nou?1:0); - } -} - -inline uint32_t get_cns_arc_bp(cns_gfa *cns, uint32_t src, uint32_t bp, uint32_t is_ou, uint32_t av_bp) -{ - uint32_t k, s, e; - if(is_ou) { - s = 0; e = (*cns).a[src].arc.nou; - } else { - s = (*cns).a[src].arc.nou; e = (*cns).a[src].arc.n; - } - - for (k = s; k < e; k++) { - if((*cns).a[src].arc.a[k].v == 0 || (*cns).a[src].arc.a[k].v == 1) continue; - if(av_bp && (*cns).a[src].arc.a[k].v >= (*cns).bb0 && (*cns).a[src].arc.a[k].v < (*cns).bb1) continue;///no backbone - if((*cns).a[(*cns).a[src].arc.a[k].v].c == bp) { - return k; - } - } - - return ((uint32_t)-1); -} - -inline uint32_t add_cns_arc_bp(cns_gfa *cns, uint32_t src, uint32_t bp, uint32_t plus0, uint32_t rid, uint32_t av_bp) -{ - uint32_t rr, des; - rr = get_cns_arc_bp(cns, src, bp, 1, av_bp); - if(rr != ((uint32_t)-1)) {///find an existing node - des = (*cns).a[src].arc.a[rr].v; - (*cns).a[des].sc++; - (*cns).a[src].arc.a[rr].sc += plus0; - - rr = add_cns_arc(cns, des, src, 0, plus0); - // if(rr == 0) { - // fprintf(stderr, "[M::%s] src::%u -> des::%u\n", __func__, src, des); - // prt_cns_arc(cns, src); - // prt_cns_arc(cns, des); - // } - assert(rr); - - return des; - } else {///create a new node - des = insert_cns_node(cns); - (*cns).a[des].sc++; (*cns).a[des].c = bp; - insert_cns_arc(cns, src, des, 1, plus0, rid); - insert_cns_arc(cns, des, src, 0, plus0, rid); - } - - return des; -} - -void init_cns_g(cns_gfa *cns, char *s, uint64_t sl, uint32_t rid) -{ - uint32_t m0 = cns->m, m1 = sl + 2, k; cns_t *p; - if ((*cns).m < (m1)) { ///equal to kv_resize() - (*cns).m = (m1); - (--((*cns).m), ((*cns).m)|=((*cns).m)>>1, ((*cns).m)|=((*cns).m)>>2, ((*cns).m)|=((*cns).m)>>4, ((*cns).m)|=((*cns).m)>>8, ((*cns).m)|=((*cns).m)>>16, ++((*cns).m)); - (*cns).a = (cns_t*)realloc((*cns).a, sizeof(cns_t) * (*cns).m); - if((*cns).m > m0) { - memset((*cns).a + m0, 0, sizeof(cns_t)*((*cns).m-m0)); - } - } - (*cns).n = 0; (*cns).si = 0; (*cns).ei = 1; (*cns).off = 2; - - p = &((*cns).a[(*cns).n++]); p->arc.nou = p->arc.n = p->c = p->f = p->sc = 0; ///beg - p = &((*cns).a[(*cns).n++]); p->arc.nou = p->arc.n = p->c = p->f = p->sc = 0; ///end - (*cns).bb0 = (*cns).n; - - for (k = 0; k < sl; k++) { - p = &((*cns).a[(*cns).n++]); p->arc.nou = p->arc.n = p->f = 0; - p->c = seq_nt6_table[(uint32_t)(s[k])]; p->sc = 1; - - if(k + 1 < sl) insert_cns_arc(cns, k + (*cns).off, k + 1 + (*cns).off, 1, 1, rid); - - if(k > 0) insert_cns_arc(cns, k + (*cns).off, k - 1 + (*cns).off, 0, 1, rid); - } - - if(sl) { - insert_cns_arc(cns, (*cns).si, 0 + (*cns).off, 1, 1, rid); insert_cns_arc(cns, 0 + (*cns).off, (*cns).si, 0, 1, rid); - insert_cns_arc(cns, sl - 1 + (*cns).off, (*cns).ei, 1, 1, rid); insert_cns_arc(cns, (*cns).ei, sl - 1 + (*cns).off, 0, 1, rid); - } else { - insert_cns_arc(cns, (*cns).si, (*cns).ei, 1, 1, rid); - insert_cns_arc(cns, (*cns).ei, (*cns).si, 0, 1, rid); - } - - // prt_cns_arc(cns, 0, __func__); - // prt_cns_arc(cns, 1, __func__); - - (*cns).bn = (*cns).n; (*cns).bb1 = (*cns).n; -} - -///[s, e) -uint32_t push_cns_c0(cns_gfa *cns, uint64_t s0, uint64_t s, uint64_t e, uint32_t plus0, uint32_t rid) -{ - if(s > e) return s0;///it is possible that s == e - uint32_t rr, k, re; - - // rr = add_cns_arc(cns, s0, s, 1, plus0); assert(rr); - // rr = add_cns_arc(cns, s, s0, 0, plus0); assert(rr); - if(!add_cns_arc(cns, s0, s, 1, plus0)) { - insert_cns_arc(cns, s0, s, 1, plus0, rid); - insert_cns_arc(cns, s, s0, 0, plus0, rid); - } else { - rr = add_cns_arc(cns, s, s0, 0, plus0); assert(rr); - } - (*cns).a[s].sc++; re = s; - - for (k = s + 1; k < e; k++) { - rr = add_cns_arc(cns, k-1, k, 1, 1); - // if(!rr) { - // fprintf(stderr, "[M::%s] s0::%u, s::%u\n", __func__, k-1, k); - // prt_cns_arc(cns, k-1, __func__); prt_cns_arc(cns, k, __func__); - // } - assert(rr); - - - - rr = add_cns_arc(cns, k, k-1, 0, 1); assert(rr); - (*cns).a[k].sc++; re = k; - } - - return re; -} - -uint32_t trace_cns_bp(cns_gfa *cns, uint64_t s0, char *tstr, uint64_t tl, asg32_v* b32, uint32_t plus0, uint32_t *rn, uint64_t max_trace, uint32_t av_bp) -{ - (*rn) = s0; - if(tl <= 0) return 0; - // fprintf(stderr, "\n[M::%s] tl::%lu\n", __func__, tl); - uint32_t k, i, s, e, m, bp, nm, bi, bn0, src, des, ff = 0; b32->n = 0; - - kv_push(uint32_t, (*b32), s0); kv_push(uint32_t, (*b32), ((uint32_t)-1)); nm = 2; - // if(s0 == 2863) { - // fprintf(stderr, "***0***[M::%s] s::%lu\tb32->n::%u\n", __func__, s0, (uint32_t)b32->n); - // } - - for (i = 0; (i < tl) && (!ff); i++) { - bp = seq_nt6_table[(uint32_t)(tstr[i])]; bn0 = b32->n; - for (bi = bn0 - nm; bi < bn0; bi += 2) { - m = b32->a[bi]; s = 0; e = (*cns).a[m].arc.nou; - for (k = s; k < e; k++) { - if((*cns).a[m].arc.a[k].v == 0 || (*cns).a[m].arc.a[k].v == 1) continue; - if(av_bp && (*cns).a[m].arc.a[k].v >= (*cns).bb0 && (*cns).a[m].arc.a[k].v < (*cns).bb1) continue;///no backbone - if((*cns).a[(*cns).a[m].arc.a[k].v].c == bp) { - kv_push(uint32_t, (*b32), (*cns).a[m].arc.a[k].v); - kv_push(uint32_t, (*b32), bi); - - // if(s0 == 2863) { - // fprintf(stderr, "***1***[M::%s] s::%u\tb32->n::%u\n", __func__, (*cns).a[m].arc.a[k].v, (uint32_t)b32->n); - // } - // if((i + 1) == tl) break;///quick end - // if(b32->n > max_trace) break;///redue the size of b32 - if(((i + 1) == tl) || (b32->n > max_trace)) { - ff = 1; break; - } - } - } - if(ff) break; - } - - if(b32->n <= bn0) {///no node - break; - } else { - nm = b32->n - bn0; - } - } - // fprintf(stderr, "[M::%s] b32->n::%u, nm::%u\n", __func__, (uint32_t)b32->n, nm); - - // if(s0 == 2863) { - // fprintf(stderr, "[M::%s] i::%u\tnm::%u\tb32->n::%u\n", __func__, i, nm, (uint32_t)b32->n); - // } - if(i > 0 && nm > 0) { - (*rn) = b32->a[b32->n - nm]; - for (bi = b32->n - nm; b32->a[bi + 1] != ((uint32_t)-1); bi = b32->a[bi + 1]) { - // fprintf(stderr, "[M::%s] bi::%u, p_bi::%u\n", __func__, bi, b32->a[bi + 1]); - des = b32->a[bi]; src = b32->a[b32->a[bi + 1]]; bp = ((src!=s0)?(1):(plus0)); - m = add_cns_arc(cns, src, des, 1, bp); assert(m); - m = add_cns_arc(cns, des, src, 0, bp); assert(m); - (*cns).a[des].sc++; - - // if(s0 == 2863) { - // fprintf(stderr, "***2***[M::%s] src::%u\tdes::%u\n", __func__, src, des); - // } - } - } else { - i = 0; - } - - return i; -} - -///[s, e) -uint32_t push_cns_c1(cns_gfa *cns, uint64_t s0, char *tstr, uint64_t tl, uint32_t plus0, asg32_v* b32, uint64_t max_trace, uint32_t rid) -{ - if(tl <= 0) return s0; - uint32_t rr = plus0, k, re = s0; - k = trace_cns_bp(cns, s0, tstr, tl, b32, plus0, &re, max_trace, 1); - if(k > 0) rr = 1; - - // if(s0 == 2863) { - // fprintf(stderr, "[M::%s] (%.*s)\ts0::%lu\tk::%u\ttl::%lu\tre::%u\n", __func__, tstr?((int)(tl)):0, tstr, s0, k, tl, re); - // } - // fprintf(stderr, "[M::%s] s0::%u, s::%u\n", __func__, k-1, k); - // prt_cns_arc(cns, k-1, __func__); prt_cns_arc(cns, k, __func__); - - for (; k < tl; k++) {///the weight of (s0 -> tstr[0]) might be 0 - re = add_cns_arc_bp(cns, re, seq_nt6_table[(uint32_t)(tstr[k])], rr, rid, 1); rr = 1; - } - - return re; -} - -uint64_t append_cns_g(cns_gfa *cns, char *tstr, uint64_t tl, uint64_t qs, uint64_t qe, uint64_t cp, uint64_t cl, uint64_t pe, asg32_v* b32, uint64_t max_trace, uint32_t rid, int64_t insert_pos) -{ - // fprintf(stderr, ">q::[%lu, %lu)\n", qs, qe); - uint64_t s0 = pe, plus0 = 1, ns = qs + cns->off, ne = qe + cns->off; - if(pe == ((uint64_t)-1)) { - if(qs > 0) { - s0 = qs - 1 + cns->off;///just before node in backbone - } else { - s0 = 0;//beg - } - // plus0 = 0; - } - - // fprintf(stderr, "+n_nodes::%u, tl::%lu, qs::%lu, qe::%lu\n", (uint32_t)cns->n, tl, qs, qe); - - if(cp == 0) { - if((cl == 0) && (cp == 0) && (qs == qe) && (((int64_t)qe) == insert_pos)) { - s0 = 0;//beg - ns = ne = 1;//end - plus0 = 1; - } - // if(cp == 0) { - // fprintf(stderr, "cp::%lu, cl::%lu, qs::%lu, qe::%lu, s0::%lu, ns::%lu, ne::%lu, plus0::%lu\n", cp, cl, qs, qe, s0, ns, ne, plus0); - // } - return push_cns_c0(cns, s0, ns, ne, plus0, rid); - } else if(cp == 1 || cp == 2) { ///cp == 2: more y -> insertion - return push_cns_c1(cns, s0, tstr, tl, plus0, b32, max_trace, rid); - } else { ///more x -> do nothing - return s0; - } -} - -char *get_sub_seq(rr_seq_t *ssq, uint64_t s, uint64_t e) -{ - if(s >= e) return NULL; - - if(s >= ssq->s && e <= ssq->e) { - return ssq->tu->seq + s - ssq->s; - } - - uint64_t l = e - s; - if(ssq->s >= ssq->e) { - if(l < ssq->n0) l = ssq->n0; - } else { - if(l < ssq->n1) l = ssq->n1; - } - - ssq->s = s; ssq->e = s + l; - if(ssq->e > Get_READ_LENGTH((*(ssq->rref)), ssq->id)) { - ssq->e = Get_READ_LENGTH((*(ssq->rref)), ssq->id); - l = ssq->e - ssq->s; - } - UC_Read_resize((*(ssq->tu)), ((int64_t)l)); - recover_UC_Read_sub_region(ssq->tu->seq, ssq->s, l, ssq->rev, ssq->rref, ssq->id); - return ssq->tu->seq; -} - - -///[s, e) -uint32_t extract_sub_cigar_cns(overlap_region *z, int64_t s, int64_t e, int64_t iws, int64_t iwe, int64_t s_end, rr_seq_t *ssq, ul_ov_t *p, cns_gfa *cns, asg32_v* b32, uint64_t max_trace, uint32_t rid) -{ - // if(s == 10539 && e == 10760) { - // fprintf(stderr, "\n>>>>>>iw::[%ld, %ld)\tw::[%ld, %ld)\tox::[%u, %u)<<<<<<\n", iws, iwe, s, e, z->x_pos_s, z->x_pos_e + 1); - // } - - int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), yk = ovlp_cur_yoff(*p), ck = ovlp_cur_coff(*p), os, oe, ots, ote, ol, insert_pos = ((iws == iwe)? (0): (-1)); - bit_extz_t ez; int64_t bd = ovlp_bd(*p), s0, e0, ii[2], it[2]; uint64_t pe = (uint64_t)-1; - s0 = ((int64_t)(z->w_list.a[wk].x_start)) + bd; - e0 = ((int64_t)(z->w_list.a[wk].x_end)) + 1 - bd; - if(s < s0) s = s0; if(e > e0) e = e0;///exclude boundary - if(s > e) return -1;///it is possible s == e - os = MAX(s, s0); oe = MIN(e, e0); - if(oe < os) return -1;///it is possible os == oe - - set_bit_extz_t(ez, (*z), wk); - if(!ez.cigar.n) return -1; - int64_t cn = ez.cigar.n; uint16_t op; int64_t ws, we, wts, wte, ovlp; char *tstr; - if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed - ck = 0; xk = ez.ts; yk = ez.ps; - } - - while (ck > 0 && xk >= s) {///x -> t; y -> p; first insertion and then match/mismatch - --ck; - op = ez.cigar.a[ck]>>14; - if(op!=2) xk -= (ez.cigar.a[ck]&(0x3fff)); - if(op!=3) yk -= (ez.cigar.a[ck]&(0x3fff)); - } - - if(s_end == 0 && s == iws) s_end = 0; - else s_end = 1; - - // if(s_end == 0 || s != iws) {///do not conside the insertion before s - // while (ck < cn && xk < s) { - // } - // } - - // if(s == 10539 && e == 10760) { - // fprintf(stderr, "ck::%ld, cn::%ld, xk::%ld, yk::%ld\n", ck, cn, xk, yk); - // } - - // char cm[4]; cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; - //some cigar will span s or e - ii[0] = ii[1] = it[0] = it[1] = -1; - ssq->s = ssq->e = 0; ssq->n0 = e - s; - ssq->id = z->y_id; ssq->rev = z->y_pos_strand; - if(ssq->n0 == 0) {ssq->n0 = ssq->n1;} - - while (ck < cn && xk < e) {//[s, e) - ws = xk; wts = yk; - op = ez.cigar.a[ck]>>14; ol = (ez.cigar.a[ck]&(0x3fff)); - - for (ck++; (ck < cn) && (op == (ez.cigar.a[ck]>>14)); ck++) { - ol += (ez.cigar.a[ck]&(0x3fff)); - } - ///op == 3: -> x; op == 2: -> y; - if(op!=2) xk += ol; - if(op!=3) yk += ol; - we = xk; wte = yk; - - // fprintf(stderr, "ck::%ld, cn::%ld, op::%u, ol::%ld\n", ck, cn, op, ol); - - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - - if(s == e) {///insertion in comparsion with the reference - if(op != 0 || ws >= s || we <= e || e != iwe || s != iws) continue;///must be a match - } else { - if(op != 2) { - if(!ovlp) continue; - } else {///ws == we - if(ws < s || ws >= e) continue; - } - } - - if((s_end == 0) && (op == 2) && (ws == s)) continue;///skip the insertion just before s - - - - if(op < 2) { - ots = os - ws + wts; ote = oe - ws + wts; - } else {///op == 2: more y; p == 3: more x - ots = wts; ote = wte; - } - - - - if(ii[0] == -1) { - ii[0] = os; it[0] = ots; - // if(op < 2) { - // it[0] = os - ws + wts; - // } else {///op == 2: more y; p == 3: more x - // it[0] = wts; - // } - } - - ii[1] = oe; it[1] = ote; - // if(op < 2) { - // it[1] = oe - ws + wts; - // } else {///op == 2: more y; p == 3: more x - // it[1] = wte; - // } - - - - - if(op != 2) ol = oe-os; - - tstr = NULL; - if(op != 0) tstr = get_sub_seq(ssq, ots, ote); - - // if(s == 10539 && e == 10760) { - // fprintf(stderr, "+0-%ld%c(%.*s)\tpe::%lu", ol, cm[op], tstr?((int)(ote - ots)):0, tstr, pe); - // } - // fprintf(stderr, ">q::[%ld, %ld)\n", ws, we); - // fprintf(stderr, "%ld%c(%.*s)", ol, cm[op], tstr?((int)(ote - ots)):0, tstr); - - pe = append_cns_g(cns, tstr, ote - ots, os - iws, oe - iws, op, ol, pe, b32, max_trace, rid, insert_pos); - - // if(s == 10539 && e == 10760) { - // fprintf(stderr, "+1-pe::%lu\n", pe); - // } - } - - while (ck < cn && xk <= e) {//[s, e) - ws = xk; wts = yk; - op = ez.cigar.a[ck]>>14; ol = (ez.cigar.a[ck]&(0x3fff)); - if(op != 2) break; - - for (ck++; (ck < cn) && (op == (ez.cigar.a[ck]>>14)); ck++) { - ol += (ez.cigar.a[ck]&(0x3fff)); - } - yk += ol;//yk += (ez.cigar.a[ck]&(0x3fff)); - we = xk; wte = yk; - - - if(ws >= s && ws <= e) { - ots = wts; ote = wte; - if(ii[0] == -1) { - ii[0] = ws; it[0] = ots; - } - ii[1] = we; it[1] = ote; - - - tstr = NULL; - if(op != 0) tstr = get_sub_seq(ssq, ots, ote); - // if(s == 10539 && e == 10760) { - // fprintf(stderr, "-0-%ld%c(%.*s)\tpe::%lu", ol, cm[op], tstr?((int)(ote - ots)):0, tstr, pe); - // } - // fprintf(stderr, "%ld%c(%.*s)", ol, cm[op], tstr?((int)(ote - ots)):0, tstr); - - pe = append_cns_g(cns, tstr, ote - ots, ws - iws, we - iws, op, ol, pe, b32, max_trace, rid, insert_pos); - - // if(s == 10539 && e == 10760) { - // fprintf(stderr, "-1-pe::%lu\n", pe); - // } - } - } - - // if(s == 10539 && e == 10760) { - // fprintf(stderr, "\tx::[%ld, %ld)\ty::[%ld, %ld)\tiw::[%ld, %ld)\n", ii[0], ii[1], it[0], it[1], iws, iwe); - // } - - // prt_cns_arc(cns, 0, __func__); - // prt_cns_arc(cns, 1, __func__); - if(ii[1] == -1) return -1;///it is possible when s == e and the cigar here is not a match - - uint64_t ae = 1; - if((ii[1] == iwe)) { - ae = 1;///end node - } else { - ae = ii[1] + cns->off - iws; - } - - // if(s == 10539 && e == 10760) { - // fprintf(stderr, "pe::%lu, ae::%lu, n_nodes::%u, ii[1]::%ld\n", pe, ae, (uint32_t)cns->n, ii[1]); - // } - - if(pe == ((uint64_t)-1)) pe = 0;///start node - - ///if iws == iwe and the cigar is a match, pe will be equal to ae - if(pe != ae) { - if(!add_cns_arc(cns, pe, ae, 1, /**ae==1?1:0**/1)) { - insert_cns_arc(cns, pe, ae, 1, /**ae==1?1:0**/1, rid); - insert_cns_arc(cns, ae, pe, 0, /**ae==1?1:0**/1, rid); - } else { - add_cns_arc(cns, ae, pe, 0, /**ae==1?1:0**/1); - } - } - - - // prt_cns_arc(cns, 0, __func__); - // prt_cns_arc(cns, 1, __func__); - - - // if(s == 10539 && e == 10760) { - // fprintf(stderr, "-end-pe::%lu, ae::%lu\n", pe, ae); - // } - - ovlp_cur_xoff(*p) = xk; ovlp_cur_yoff(*p) = yk; ovlp_cur_coff(*p) = ck; ovlp_cur_ylen(*p) = 0; - - return 1; -} - - -uint64_t iter_cc_idx_t(overlap_region* ol, cc_idx_t *z, int64_t s, int64_t e, uint64_t is_reduce, uint64_t is_insert, uint64_t **ra) -{ - int64_t rm_n, q[2], os, oe; ul_ov_t *cp; uint64_t m; *ra = NULL; - - // if(s == 15816 && e == 15819) { - // fprintf(stderr, "[M::%s] is_reduce::%lu\n", __func__, is_reduce); - // } - if(z->ru == 0) { - if(is_reduce) { - for (m = rm_n = z->srt_n; m < z->idx->n; m++) { - cp = &(z->c_idx[z->idx->a[m]]); - // if(s == 15816 && e == 15819) { - // fprintf(stderr, "-0-[M::%s] ii::%lu, ii0::%ld\n", __func__, z->idx->a[m], z->i0); - // } - - q[0] = ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); - q[1] = ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); - os = MAX(q[0], s); oe = MIN(q[1], e); - if((oe > os) || ((is_insert) && (s == e) && (s >= q[0]) && (s <= q[1]))) { - z->idx->a[rm_n++] = z->idx->a[m]; - } - } - z->idx->n = rm_n; - } - - for (; z->i < z->srt_n; ++z->i) { - cp = &(z->c_idx[(uint32_t)z->idx->a[z->i]]); - // if(s == 15816 && e == 15819) { - // fprintf(stderr, "-1-[M::%s] ii::%u, ii0::%ld\n", __func__, (uint32_t)z->idx->a[z->i], z->i0); - // } - q[0] = ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); - q[1] = ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); - if(q[0] > e) break; - if((!is_insert) && (q[0] >= e)) break; - os = MAX(q[0], s); oe = MIN(q[1], e); - if((oe > os) || ((is_insert) && (s == e) && (s >= q[0]) && (s <= q[1]))) { - kv_push(uint64_t, *(z->idx), ((uint32_t)z->idx->a[z->i])); - } - } - } else { - z->ru = 0; - } - - (*ra) = z->idx->a + z->srt_n; - return z->idx->n - z->srt_n; -} - -void debug_inter0(overlap_region* ol, ul_ov_t *c_idx, uint64_t *idx, int64_t idx_n, uint64_t *res, int64_t res_n, int64_t s, int64_t e, uint64_t is_insert, uint64_t is_hard_check, const char *cmd) -{ - ul_ov_t *cp; int64_t q[2], a_n = 0, i, k = 0, os, oe; - for (i = 0; i < idx_n; i++) { - cp = &(c_idx[(uint32_t)idx[i]]); - q[0] = ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); - q[1] = ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); - - // fprintf(stderr, "%s[M::%s] tid::%u\t%.*s\twid::%u\tq::[%u, %u)\terr::%d\toerr::%u\n", cmd, __func__, ol[ovlp_id(*cp)].y_id, (int)Get_NAME_LENGTH(R_INF, ol[ovlp_id(*cp)].y_id), Get_NAME(R_INF, ol[ovlp_id(*cp)].y_id), - // ovlp_cur_wid(*cp), ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start, ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1, ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].error, ol[ovlp_id(*cp)].non_homopolymer_errors); - - os = MAX(q[0], s); oe = MIN(q[1], e); - if((oe > os) || ((is_insert) && (s == e) && (s >= q[0]) && (s <= q[1]))) { - a_n++; - // if(!(((uint32_t)idx[i]) == res[k])) { - // fprintf(stderr, "[M::%s] a_n::%ld\tres_n::%ld\ts::%ld\te::%ld\ti::%ld\tk::%ld\n", __func__, a_n, res_n, s, e, i, k); - // } - if(is_hard_check) { - assert(((uint32_t)idx[i]) == res[k++]); - } else { - for (; (k < res_n) && (((uint32_t)idx[i]) != res[k]); k++); - assert(k < res_n); - } - } - } - // if(a_n != res_n) { - // fprintf(stderr, "[M::%s] a_n::%ld\tres_n::%ld\ts::%ld\te::%ld\tidx_n::%ld\n", __func__, a_n, res_n, s, e, idx_n); - // } - if(is_hard_check) { - assert(a_n == res_n); - } else { - assert(a_n <= res_n); - } -} - -void prt_cigar0(uint64_t in, int64_t len) -{ - int64_t k; uint64_t mp; - char cm[4]; cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; - for (k = 0; k < len; k++) { - mp = len - 1 - k; mp <<= 1; - fprintf(stderr, "%c", cm[(in >> mp)&3]); - } - fprintf(stderr, "\n"); -} - -void prt_bp0(uint64_t in, int64_t len) -{ - int64_t k; uint64_t mp; - char cm[4]; cm[0] = 'A'; cm[1] = 'C'; cm[2] = 'G'; cm[3] = 'T'; - for (k = 0; k < len; k++) { - mp = len - 1 - k; mp <<= 1; - fprintf(stderr, "%c", cm[(in >> mp)&3]); - } - fprintf(stderr, "\n"); -} - -uint64_t cns_gen0(overlap_region* ol, All_reads *rref, uint64_t s, uint64_t e, uint64_t ql, UC_Read* tu, cc_idx_t *idx, uint64_t occ_tot, double occ_max, asg32_v* b32, uint32_t *rc) -{ - if(e > s + simp_vote_len) return 0;///too long - - uint64_t *id_a = NULL, id_n, an = 0, oc[2]; b32->n = 0; uint32_t m, *a = NULL; - id_n = iter_cc_idx_t(ol, idx, s, e, idx->rr, ((s==e)?1:0), &id_a); - // debug_inter0(ol, idx->c_idx, idx->idx->a + idx->i0, idx->srt_n - idx->i0, id_a, id_n, s, e, ((s==e)?1:0), 0, "-1-"); - uint64_t k, l, q[2], os, oe; ul_ov_t *p; overlap_region *z; idx->rr = 0; - // fprintf(stderr, "[M::%s] [%lu, %lu) id_n::%lu\n", __func__, s, e, id_n); - for (k = 0; k < id_n; k++) { - p = &(idx->c_idx[id_a[k]]); z = &(ol[ovlp_id(*p)]); - q[0] = z->w_list.a[ovlp_cur_wid(*p)].x_start+ovlp_bd(*p); - q[1] = z->w_list.a[ovlp_cur_wid(*p)].x_end+1-ovlp_bd(*p); - - // if(s == 11851 && e == 11853) { - // fprintf(stderr, "[M::%s] tid::%u\t%.*s\twid::%u\tq::[%u, %u)\terr::%d\toerr::%u\n", __func__, ol[ovlp_id(*p)].y_id, (int)Get_NAME_LENGTH(R_INF, ol[ovlp_id(*p)].y_id), Get_NAME(R_INF, ol[ovlp_id(*p)].y_id), - // ovlp_cur_wid(*p), ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].x_start, ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].x_end+1, ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].error, ol[ovlp_id(*p)].non_homopolymer_errors); - // } - - if(q[1] <= e) idx->rr = 1; - os = MAX(q[0], s); oe = MIN(q[1], e); - // if((oe > os) || ((s == e) && (s >= q[0]) && (s <= q[1]))) { - if((oe > os) || ((s == e) && (s > q[0]) && (s < q[1]))) { - // if(oe >= os) { - ///[-4-][-12-][-4-][-12-] - ///[cigar_len][cigar][base_len][base] - m = extract_sub_cigar_ii(z, ql, rref, os, oe, s, e, tu, p); an++; - if(m != ((uint32_t)-1)) {///no gap in both sides - kv_push(uint32_t, *b32, m); - } - } - } - - oc[0] = b32->n; oc[1] = an + 1; //+1 for the reference read - // if(s == 11851 && e == 11853) { - // fprintf(stderr, "-0-[M::%s] oc[0]::%lu, oc[1]::%lu\n", __func__, oc[0], oc[1]); - // } - if(((oc[0] > (oc[1]*occ_max)) && (oc[0] > (oc[1]-oc[0])) && (oc[1] >= occ_tot) && (oc[0] > 1))) { - radix_sort_ec32(b32->a, b32->a+b32->n); an = 0; - for (k = 1, l = 0; k <= b32->n; ++k) { - if (k == b32->n || b32->a[k] != b32->a[l]) { - if(k - l > an) { - an = k - l; a = b32->a + l; - } - l = k; - } - } - oc[0] = an; - // fprintf(stderr, "-1-[M::%s] oc[0]::%lu, oc[1]::%lu\n", __func__, oc[0], oc[1]); - if(((oc[0] > (oc[1]*occ_max)) && (oc[0] > (oc[1]-oc[0])) && (oc[1] >= occ_tot) && (oc[0] > 1))) { - (*rc) = a[0]; - // prt_cigar0((a[0]<<4)>>20, a[0]>>28); - // prt_bp0((a[0]<<20)>>20, (a[0]<<16)>>28); - return 1; - } - } - - idx->ru = 1; - return 0; -} - -inline void gen_mm_cns_arc(cns_gfa *cns, uint32_t src, uint32_t des, uint32_t sc, uint32_t f) -{ - cns_t *av = &((*cns).a[src]), *aw; - uint32_t vk, wk; - for (vk = 0; vk < av->arc.nou; vk++) {///out-edge of src - if((av->arc.a[vk].v != des) || (del_cns_arc((*av), vk))) continue; - // av->arc.a[vk].f = 1; ///not sure if we should set these edges as visited - av->arc.a[vk].f = f; - av->arc.a[vk].sc += sc; - - aw = &((*cns).a[des]); - for (wk = aw->arc.nou; wk < aw->arc.n; wk++) {///in-edge of des - if((aw->arc.a[wk].v != src) || (del_cns_arc((*aw), wk))) continue; - // aw->arc.a[wk].f = 1; ///not sure if we should set these edges as visited - aw->arc.a[wk].f = f; - aw->arc.a[wk].sc += sc; - break; - } - - assert(wk < aw->arc.n); - return; - } - - cns_arc *p, t; - ///src -> des - kv_pushp(cns_arc, (*cns).a[src].arc, &p); - p->sc = sc; p->v = des; - // p->f = 1; ///not sure if we should set these edges as visited - p->f = f; - ///ou-edge - (*cns).a[src].arc.nou++; - if((*cns).a[src].arc.nou < (*cns).a[src].arc.n) { - t = (*cns).a[src].arc.a[(*cns).a[src].arc.nou-1]; - (*cns).a[src].arc.a[(*cns).a[src].arc.nou-1] = *p; - *p = t; - } - - ///src <- des; in-edge - kv_pushp(cns_arc, (*cns).a[des].arc, &p); - p->sc = sc; p->v = src; - // p->f = 1; ///not sure if we should set these edges as visited - p->f = f; -} - -void del_cns_g_nn(cns_gfa *cns, uint32_t v) -{ - uint32_t w, vk, wk; cns_t *av = &((*cns).a[v]), *aw = NULL; - - for (vk = 0; vk < av->arc.nou; vk++) {///out-edge of src - if(del_cns_arc((*av), vk)) continue; - w = av->arc.a[vk].v; av->arc.a[vk].v = CNS_DEL_E; - - aw = &((*cns).a[w]); - for (wk = aw->arc.nou; wk < aw->arc.n; wk++) {///in-edge of des - if((aw->arc.a[wk].v != v) || (del_cns_arc((*aw), wk))) continue; - aw->arc.a[wk].v = CNS_DEL_E; break; - } - assert(wk < aw->arc.n); - } - - for (vk = av->arc.nou; vk < av->arc.n; vk++) {///in-edge of src - if(del_cns_arc((*av), vk)) continue; - w = av->arc.a[vk].v; av->arc.a[vk].v = CNS_DEL_E; - - aw = &((*cns).a[w]); - for (wk = 0; wk < aw->arc.nou; wk++) {///out-edge of des - if((aw->arc.a[wk].v != v) || (del_cns_arc((*aw), wk))) continue; - aw->arc.a[wk].v = CNS_DEL_E; break; - } - assert(wk < aw->arc.n); - } - - - cns->a[v].arc.n = cns->a[v].arc.nou = 0; - cns->a[v].c = cns->a[v].f = 0; cns->a[v].sc = CNS_DEL_V; -} - -void merge_cns_g_in(cns_gfa *cns, uint32_t v0, asg32_v* b32) -{ - cns_t *av, *aw; uint32_t v, bp, vk, wk, wka, w, wn, nn, mn, wh, mn_k[2]; - - b32->n = 0; - kv_push(uint32_t, *b32, v0); - while (b32->n) { - v = b32->a[--b32->n]; - if(del_cns_nn((*cns), v)) continue; - - av = &((*cns).a[v]); - for (bp = 0; bp < 4; bp++) { - //nn: number of node; wh: weight - nn = wh = 0; mn = mn_k[0] = mn_k[1] = wka = (uint32_t)-1; - for (vk = av->arc.nou; vk < av->arc.n; vk++) {///in-edge of v - if(del_cns_arc((*av), vk)) continue; - w = av->arc.a[vk].v; aw = &((*cns).a[w]); - if(aw->c != bp) continue; - if(w == cns->si || w == cns->ei) continue; - - for (wk = wn = 0; wk < aw->arc.nou; wk++) {///out-edge of w - if(del_cns_arc((*aw), wk)) continue; - wn++; wka = wk; if(wn > 1) break; - } - - if(wn != 1) continue; - - assert(aw->arc.a[wka].v == v); - - ///deal with out-edge of w - if(nn == 0) { - mn = w; mn_k[0] = vk; mn_k[1] = wka; - wh = av->arc.a[vk].sc; - ///not sure if we should set these edges as visited - // av->arc.a[vk].f = 1; aw->arc.a[wka].f = 1; - } else { - wh += aw->arc.a[wka].sc; - } - - ///deal with in-edge of w - ///all edges to w, should be move to mn - if(nn > 0) {///not sure if we should set these edges as visited; affect when nn == 0 - for (wk = aw->arc.nou; wk < aw->arc.n; wk++) { - if(del_cns_arc((*aw), wk)) continue; - ///previously, aw->arc.a[wk].v -> w - ///currently, aw->arc.a[wk].v -> mn - /// if(nn == 0), then mn = w - gen_mm_cns_arc(cns, aw->arc.a[wk].v, mn, aw->arc.a[wk].sc/**(nn?(aw->arc.a[wk].sc):(0))**/, aw->arc.a[wk].f);///not sure if we should set these edges as visited - } - } - - ///mn != w - if(nn > 0) del_cns_g_nn(cns, w); - - nn++; - } - - if(nn) { - aw = &((*cns).a[mn]); - av->arc.a[mn_k[0]].sc = aw->arc.a[mn_k[1]].sc = wh; - // merge_cns_g_in(cns_gfa *cns, uint32_t v, asg32_v* b32) - kv_push(uint32_t, *b32, mn); - } - } - } -} - -void merge_cns_g_ou(cns_gfa *cns, uint32_t v0, asg32_v* b32) -{ - cns_t *av, *aw; uint32_t v, bp, vk, wk, wka, w, wn, nn, mn, wh, mn_k[2]; - - b32->n = 0; - kv_push(uint32_t, *b32, v0); - while (b32->n) { - v = b32->a[--b32->n]; - if(del_cns_nn((*cns), v)) continue; - - av = &((*cns).a[v]); - for (bp = 0; bp < 4; bp++) { - //nn: number of node; wh: weight - nn = wh = 0; mn = mn_k[0] = mn_k[1] = wka = (uint32_t)-1; - for (vk = 0; vk < av->arc.nou; vk++) {///ou-edge of v - if(del_cns_arc((*av), vk)) continue; - w = av->arc.a[vk].v; aw = &((*cns).a[w]); - if(aw->c != bp) continue; - if(w == cns->si || w == cns->ei) continue; - - for (wk = aw->arc.nou, wn = 0; wk < aw->arc.n; wk++) {///in-edge of w - if(del_cns_arc((*aw), wk)) continue; - wn++; wka = wk; if(wn > 1) break; - } - - if(wn != 1) continue; - - assert(aw->arc.a[wka].v == v); - - - ///deal with in-edge of w - if(nn == 0) { - mn = w; mn_k[0] = vk; mn_k[1] = wka; - wh = av->arc.a[vk].sc; - ///not sure if we should set these edges as visited - // av->arc.a[vk].f = 1; aw->arc.a[wka].f = 1; - } else { - wh += aw->arc.a[wka].sc; - } - - - ///deal with ou-edge of w - ///all edges from w, should be move to mn - if(nn > 0) {///not sure if we should set these edges as visited; affect when nn == 0 - for (wk = 0; wk < aw->arc.nou; wk++) { - if(del_cns_arc((*aw), wk)) continue; - ///previously, w -> aw->arc.a[wk].v - ///currently, mn -> aw->arc.a[wk].v - /// if(nn == 0), then mn = w - gen_mm_cns_arc(cns, mn, aw->arc.a[wk].v, aw->arc.a[wk].sc/**(nn?(aw->arc.a[wk].sc):(0))**/, aw->arc.a[wk].f);///not sure if we should set these edges as visited - } - } - - ///mn != w - if(nn > 0) del_cns_g_nn(cns, w); - - nn++; - } - - if(nn) { - aw = &((*cns).a[mn]); - // fprintf(stderr, "\n[M::%s] nn::%u, mn::%u\n", __func__, nn, mn); - // fprintf(stderr, "[M::%s] vi::%u, vn::%u\n", __func__, mn_k[0], (uint32_t)av->arc.n); - // fprintf(stderr, "[M::%s] wi::%u, wn::%u\n", __func__, mn_k[1], (uint32_t)aw->arc.n); - - av->arc.a[mn_k[0]].sc = aw->arc.a[mn_k[1]].sc = wh; - // merge_cns_g_in(cns_gfa *cns, uint32_t v, asg32_v* b32) - kv_push(uint32_t, *b32, mn); - } - } - } -} - -void refine_cns_g(cns_gfa *cns, asg32_v *b32) -{ - uint32_t v, w, vk, wk, *p = NULL; cns_t *av = NULL, *aw = NULL; - kdq_clear(cns->q); - kdq_push(uint32_t, cns->q, cns->si); ///in-degree == 0 - - while (1) { - p = kdq_shift(uint32_t, cns->q); - if(!p) break; v = *p; - - if(del_cns_nn((*cns), v)) continue; - ///merge in - merge_cns_g_in(cns, v, b32); - ///merge out - merge_cns_g_ou(cns, v, b32); - - av = &((*cns).a[v]); - ///set arcs - for (vk = 0; vk < av->arc.nou; vk++) {///out-edge of v - if(del_cns_arc((*av), vk)) continue; - if(av->arc.a[vk].f == 0) continue; - - av->arc.a[vk].f = 1; w = av->arc.a[vk].v; aw = &((*cns).a[w]); - - for (wk = aw->arc.nou; wk < aw->arc.n; wk++) {///in-edge of w - if((aw->arc.a[wk].v != v) || (del_cns_arc((*aw), wk))) continue; - aw->arc.a[wk].f = 1; break; - } - } - ///set node - av->f = 1; - - - for (vk = 0; vk < av->arc.nou; vk++) {///out-edge of v - if(del_cns_arc((*av), vk)) continue; - w = av->arc.a[vk].v; - - aw = &((*cns).a[w]); - for (wk = aw->arc.nou; wk < aw->arc.n; wk++) {///in-edge of w - if((del_cns_arc((*aw), wk))) continue; - if(aw->arc.a[wk].f) continue;///test arcs - if(cns->a[aw->arc.a[wk].v].f) continue;///test node - break; - } - if(wk >= aw->arc.n) { - kdq_push(uint32_t, cns->q, w); ///in-degree == 0 - } - } - } -} - -void gseq_cns_g(cns_gfa *cns, asg32_v *b32, uint32_t bl) -{ - b32->n = 0; kv_resize(uint32_t, *b32, cns->n); - uint32_t v, vk, w, mme, mmn, mmk, mmw, *ii = b32->a, *p; cns_t *av; - uint32_t bs = cns->off, be = bl + cns->off, sw; - for (v = 0; v < cns->n; v++) { - ii[v] = 0;///score - if(del_cns_nn((*cns), v)) continue; - cns->a[v].sc = 0; ///in-degree or prefix - cns->a[v].f = 0; - - av = &((*cns).a[v]); - for (vk = av->arc.nou; vk < av->arc.n; vk++) {///in-edge of v - if(del_cns_arc((*av), vk)) continue; - cns->a[v].sc++;///in-degree - } - } - - kdq_clear(cns->q); - kdq_push(uint32_t, cns->q, cns->si); ///in-degree == 0 - assert((cns->a[cns->si].sc == 0) && (!del_cns_nn((*cns), cns->si))); - - while (1) { - p = kdq_shift(uint32_t, cns->q); - if(!p) break; v = *p; - - if(del_cns_nn((*cns), v)) continue; - assert(cns->a[v].sc == 0); ///in-degree == 0 - - av = &((*cns).a[v]); - for (vk = av->arc.nou, mme = mmn = mmw = 0, mmk = (uint32_t)-1; vk < av->arc.n; vk++) {///in-edge of v - if(del_cns_arc((*av), vk)) continue; - w = av->arc.a[vk].v; - assert((*cns).a[w].f); - sw = ((w >= bs && w < be)?1:0); ///backbone - - if((mmk == ((uint32_t)-1)) || (av->arc.a[vk].sc > mme) || - (((av->arc.a[vk].sc == mme) && (ii[w] > mmn))) || - (((av->arc.a[vk].sc == mme) && (ii[w] == mmn) && (sw == 1) && (mmw == 0)))) { - mmk = vk; mme = av->arc.a[vk].sc; mmn = ii[w]; mmw = sw; - } - } - - ii[v] = mme + mmn; cns->a[v].f = 1; - if(mmk != ((uint32_t)-1)) cns->a[v].sc = av->arc.a[mmk].v; - else cns->a[v].sc = v; - - for (vk = 0; vk < av->arc.nou; vk++) {///out-edge of v - if(del_cns_arc((*av), vk)) continue; - w = av->arc.a[vk].v; - assert(cns->a[w].f == 0); - assert(cns->a[w].sc); - cns->a[w].sc--; - if(cns->a[w].sc == 0) { - kdq_push(uint32_t, cns->q, w); ///in-degree == 0 - } - } - - // fprintf(stderr, "[M::%s] sc[%u]::%u\n", __func__, v, ii[v]); - } - - for (v = cns->a[cns->ei].sc, b32->n = 0; v != cns->si; v = cns->a[v].sc) { - // fprintf(stderr, "[M::%s] v::%u\n", __func__, v); - kv_push(uint32_t, *b32, v); - } - assert(v == cns->si); - - mmn = b32->n; mmn >>= 1; - for (vk = 0; vk < mmn; vk++) { - v = b32->a[vk]; b32->a[vk] = b32->a[b32->n-vk-1]; b32->a[b32->n-vk-1] = v; - } -} - -uint64_t push_correct1(window_list *idx, window_list_alloc *res, cns_gfa *cns, asg32_v *rc, uint32_t bl) -{ - // fprintf(stderr, "[M::%s]\t", __func__); - uint64_t nec = 0; uint32_t k, l, i, ff, sl, sk, bs = cns->off, be = bl + cns->off, bend = cns->off;///[bs, be) - if(rc->n) {///it is possible that rc->n == 0, which means there is a deletion - for (k = 1, l = 0; k <= rc->n; ++k) { - ff = 0; sl = sk = 0; - if(k == rc->n) { - if(l < rc->n) sl = ((rc->a[l] >= bs && rc->a[l] < be)?1:0); - ff = 1; - } else { - sl = ((rc->a[l] >= bs && rc->a[l] < be)?1:0); - sk = ((rc->a[k] >= bs && rc->a[k] < be)?1:0); - if(sl != sk) { - ff = 1; - } else if((sl == 1) && ((rc->a[k] - rc->a[l]) != (k - l))) { - ff = 1; - } - } - - if(!ff) continue; - - if(sl) { ///match - if(rc->a[l] > bend) {///deltetion [bend, rc->a[l]) - push_trace_bp(((asg16_v *)(&(res->c))), 3, (uint16_t)-1, rc->a[l] - bend, ((idx->clen>0)?1:0)); - idx->clen = res->c.n - idx->cidx; nec += rc->a[l] - bend; - // fprintf(stderr, "%uD", rc->a[l] - bend); - } - - ///push match - push_trace_bp(((asg16_v *)(&(res->c))), 0, (uint16_t)-1, rc->a[k-1] + 1 - rc->a[l], ((idx->clen>0)?1:0)); - idx->clen = res->c.n - idx->cidx; - - // fprintf(stderr, "%uM", rc->a[k-1] + 1 - rc->a[l]); - - bend = rc->a[k-1] + 1; - } else { ///unmatch - for (i = l; i < k; i++) { - push_trace_bp(((asg16_v *)(&(res->c))), 2, cns->a[rc->a[i]].c, 1, ((idx->clen>0)?1:0)); - idx->clen = res->c.n - idx->cidx; nec++; - // fprintf(stderr, "I"); - } - } - l = k; - } - } - - ///push remaining deletion - if(be > bend) { - push_trace_bp(((asg16_v *)(&(res->c))), 3, (uint16_t)-1, be - bend, ((idx->clen>0)?1:0)); - idx->clen = res->c.n - idx->cidx; nec += be - bend; - // fprintf(stderr, "%uD", be - bend); - } - // fprintf(stderr, "\n"); - return nec; -} - -uint64_t push_correct1_fhc_indel_exz(asg16_v *sc, int64_t sc0, window_list *idx, cns_gfa *cns, char *ostr, UC_Read* tu, bit_extz_t *exz, uint64_t gbeg, uint64_t c0, int64_t cl0, int64_t ok0) -{ - int64_t ck = sc->n, k, ok = 0, nk = 0, cn, cn0, nl, ol, diff, diff0, ml, ml0, e0 = 0; uint32_t on, f = 0, nec = 0; uint16_t bq, bt, op; - assert(c0 == 3); - - ///debug - // char cm[4]; cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; - - // if(c0 != 2) ok += cl0; - // if(c0 != 3) nk += cl0; - ok += cl0; e0 += cl0; - - // fprintf(stderr, "\n%lu%c", cl0, cm[c0]); - - for (ck--; ck >= sc0/**0**/; ck--) { - op = sc->a[ck]>>14; - if(!op) break; - - if((op == 2) || (op == 3)) { - on = sc->a[ck]&(0xfff); - } else if(op == 1) { - on = sc->a[ck]&(0x3ff); - } else { - on = sc->a[ck]&(0x3fff); - } - if(op != 2) ok += on; - if(op != 3) nk += on; - if(op != 0) e0 += on; - if(c0 != op) f = 1; - - // fprintf(stderr, "%u%c(%c)", on, cm[op], "ACGT"[((sc->a[ck]>>12)&3)]); - } - cn0 = ck + 1; cn = sc->n; - // fprintf(stderr, "\n"); - - // fprintf(stderr, "+[M::%s] cn0::%ld, cn::%ld, ok::%ld, sc->n::%u, ok0::%ld, cl0::%ld\n", __func__, cn0, cn, ok, (uint32_t)sc->n, ok0, cl0); - // f = 0; - - if((!f) || (!ok) || (!nk)) { - for (k = 0, ck = ok0 + gbeg; k < cl0; k++, ck++) { - push_trace_bp_f(sc, c0, cns->a[ck].c, (uint16_t)-1, 1, ((idx->clen>0)?1:0)); - idx->clen = sc->n - idx->cidx; nec++; - // fprintf(stderr, "%c\n", "ACGT"[cns->a[ck].c]); - } - } else { - char *oseq = NULL, *nseq = NULL; int64_t wo[2], wn[2]; - UC_Read_resize((*tu), nk); nseq = tu->seq; wo[0] = wo[1] = wn[0] = wn[1] = 0; - // if(c0 != 2) ok0 += cl0; - ok0 += cl0; - - ok0 -= ok; - // if(!(ok0 >= 0)) { - // fprintf(stderr, "+[M::%s] rid::%u, cn0::%ld, cn::%ld, ok0::%ld, ok::%ld, sc->n::%u\n", __func__, rid, cn0, cn, ok0, ok, (uint32_t)sc->n); - // } - assert(ok0 >= 0); - - oseq = ostr + ok0; - ol = ok; nl = nk; - ck = cn0; ok = nk = 0; - while (ck < cn) { - wo[0] = ok; wn[0] = nk; - ck = pop_trace_bp_f(sc, ck, &op, &bq, &bt, &on); - if(op != 2) ok += on; - if(op != 3) nk += on; - wo[1] = ok; wn[1] = nk; - - if(op == 0) { - memcpy(nseq + wn[0], oseq + wo[0], (wo[1]-wo[0])*sizeof((*nseq))); - } else if(op == 1 || op == 2) { - for (k = wn[0]; k < wn[1]; k++) nseq[k] = s_H[bt]; - } - // fprintf(stderr, "[M::%s] ck::%ld, wo::[%ld, %ld), wn::[%ld, %ld)\n", __func__, ck, wo[0], wo[1], wn[0], wn[1]); - } - // fprintf(stderr, "[M::%s] qstr::%.*s*\n", __func__, (int32_t)ol, oseq); - // fprintf(stderr, "[M::%s] tstr::%.*s*\n", __func__, (int32_t)nl, nseq); - - assert(wo[1] + cl0 == ol); - assert(wn[1] == nl); ///since c0 must be 3 - // memcpy(nseq + wn[1], oseq + wo[1], cl0*sizeof((*nseq))); - if(nl == ol && nl == 1) { - sc->n = cn0; - if(oseq[0] == nseq[0]) { - push_trace_bp_f(sc, 0, (uint16_t)-1, (uint16_t)-1, 1, ((idx->clen>0)?1:0)); - idx->clen = sc->n - idx->cidx; - } else { - push_trace_bp_f(sc, 1, seq_nt6_table[(uint32_t)(oseq[0])], seq_nt6_table[(uint32_t)(nseq[0])], 1, ((idx->clen>0)?1:0)); - idx->clen = sc->n - idx->cidx; nec++; - } - } else { - ml = MAX(ol, nl); f = 0; - - diff = 31; - if(diff > ml) diff = ml; - diff0 = diff; clear_align(*exz); - cal_exz_global(nseq, nl, oseq, ol, diff, exz); - if(is_align(*exz)) f = 1; - - if(!f) { - diff = 63; - if(diff > ml) diff = ml; - if(diff > diff0) { - diff0 = diff; clear_align(*exz); - cal_exz_global(nseq, nl, oseq, ol, diff, exz); - if(is_align(*exz)) f = 1; - } - } - - // fprintf(stderr, "[M::%s] f::%u, exz->err::%d, e0::%ld\n", __func__, f, exz->err, e0); - - if(f && exz->err < e0) { - sc->n = cn0; - cn = exz->cigar.n; ok = nk = 0; - for (ck = 0; ck < cn;) { - wo[0] = ok; wn[0] = nk; - ck = pop_trace(&(exz->cigar), ck, &op, &on); - if(op!=2) ok += on; - if(op!=3) nk += on; - wo[1] = ok; wn[1] = nk; - - // fprintf(stderr, "%u%c(", on, cm[op]); - - if(op == 0) { - push_trace_bp_f(sc, op, (uint16_t)-1, (uint16_t)-1, on, ((idx->clen>0)?1:0)); - idx->clen = sc->n - idx->cidx; - } else if(op == 1) { - for (k = 0; k < on; k++) { - push_trace_bp_f(sc, op, seq_nt6_table[(uint32_t)(oseq[wo[0]+k])], seq_nt6_table[(uint32_t)(nseq[wn[0]+k])], 1, ((idx->clen>0)?1:0)); - idx->clen = sc->n - idx->cidx; nec++; - // fprintf(stderr, "<%c|%c>)", oseq[wo[0]+k], nseq[wn[0]+k]); - } - } else if(op == 2) { - for (k = 0; k < on; k++) { - push_trace_bp_f(sc, op, (uint16_t)-1, seq_nt6_table[(uint32_t)(nseq[wn[0]+k])], 1, ((idx->clen>0)?1:0)); - idx->clen = sc->n - idx->cidx; nec++; - // fprintf(stderr, "<|%c>)", nseq[wn[0]+k]); - } - } else if(op == 3) { - for (k = 0; k < on; k++) { - push_trace_bp_f(sc, op, seq_nt6_table[(uint32_t)(oseq[wo[0]+k])], (uint16_t)-1, 1, ((idx->clen>0)?1:0)); - idx->clen = sc->n - idx->cidx; nec++; - // fprintf(stderr, "<%c|>)", oseq[wo[0]+k]); - } - } - // fprintf(stderr, ")"); - } - // fprintf(stderr, "\n"); - } else { - if(ml < e0) { - sc->n = cn0; - ml0 = MIN(ol, nl); op = 1; - for (k = 0; k < ml0; k++) { - push_trace_bp_f(sc, op, seq_nt6_table[(uint32_t)(oseq[k])], seq_nt6_table[(uint32_t)(nseq[k])], 1, ((idx->clen>0)?1:0)); - idx->clen = sc->n - idx->cidx; nec++; - } - - if(ol > ml0) {///op = 3 - for (k = ml0, op = 3; k < ol; k++) { - push_trace_bp_f(sc, op, seq_nt6_table[(uint32_t)(oseq[k])], (uint16_t)-1, 1, ((idx->clen>0)?1:0)); - idx->clen = sc->n - idx->cidx; nec++; - } - } else if(nl > ml0) {///op = 2 - for (k = ml0, op = 2; k < nl; k++) { - push_trace_bp_f(sc, op, (uint16_t)-1, seq_nt6_table[(uint32_t)(nseq[k])], 1, ((idx->clen>0)?1:0)); - idx->clen = sc->n - idx->cidx; nec++; - } - } - } else { - for (k = 0, ck = ok0 + gbeg; k < cl0; k++, ck++) { - push_trace_bp_f(sc, c0, cns->a[ck].c, (uint16_t)-1, 1, ((idx->clen>0)?1:0)); - idx->clen = sc->n - idx->cidx; nec++; - } - } - } - } - } - - // fprintf(stderr, "-[M::%s] cn0::%ld, cn::%ld, ok::%ld, sc->n::%u\n", __func__, cn0, cn, ok, (uint32_t)sc->n); - return nec; -} - -uint64_t push_correct1_fhc(window_list *idx, window_list_alloc *res, cns_gfa *cns, char* qstr, UC_Read* tu, bit_extz_t *exz, asg32_v *rc, uint32_t bl, uint32_t rid) -{ - // fprintf(stderr, "[M::%s]\trc->n::%u\tbl::%u\n", __func__, (uint32_t)rc->n, bl); - uint64_t nec = 0; uint32_t k, l, i, ff, sl, sk, bs = cns->off, be = bl + cns->off, bend = cns->off, is_i = 0, sc0 = res->c.n;///[bs, be) - if(rc->n) {///it is possible that rc->n == 0, which means there is a deletion - for (k = 1, l = 0; k <= rc->n; ++k) { - ff = 0; sl = sk = 0; - if(k == rc->n) { - if(l < rc->n) sl = ((rc->a[l] >= bs && rc->a[l] < be)?1:0); - ff = 1; - } else { - sl = ((rc->a[l] >= bs && rc->a[l] < be)?1:0); - sk = ((rc->a[k] >= bs && rc->a[k] < be)?1:0); - if(sl != sk) { - ff = 1; - } else if((sl == 1) && ((rc->a[k] - rc->a[l]) != (k - l))) { - ff = 1; - } - } - - if(!ff) continue; - - if(sl) { ///match - if(rc->a[l] > bend) {///deltetion [bend, rc->a[l]) - if(is_i && exz) { - nec += push_correct1_fhc_indel_exz(((asg16_v *)(&(res->c))), sc0, idx, cns, qstr, tu, exz, cns->off, 3, rc->a[l] - bend, bend-cns->off); - } else { - for (i = bend; i < rc->a[l]; i++) { - push_trace_bp_f(((asg16_v *)(&(res->c))), 3, cns->a[i].c, (uint16_t)-1, 1, ((idx->clen>0)?1:0)); - idx->clen = res->c.n - idx->cidx; nec++; - } - } - } - - ///push match - push_trace_bp_f(((asg16_v *)(&(res->c))), 0, (uint16_t)-1, (uint16_t)-1, rc->a[k-1] + 1 - rc->a[l], ((idx->clen>0)?1:0)); - idx->clen = res->c.n - idx->cidx; - - bend = rc->a[k-1] + 1; is_i = 0; - } else { ///unmatch - for (i = l; i < k; i++) { - push_trace_bp_f(((asg16_v *)(&(res->c))), 2, (uint16_t)-1, cns->a[rc->a[i]].c, 1, ((idx->clen>0)?1:0)); - idx->clen = res->c.n - idx->cidx; nec++; - } - is_i = 1; - } - l = k; - } - } - - ///push remaining deletion - if(be > bend) { - if(is_i && exz) { - nec += push_correct1_fhc_indel_exz(((asg16_v *)(&(res->c))), sc0, idx, cns, qstr, tu, exz, cns->off, 3, be - bend, bend-cns->off); - } else { - for (i = bend; i < be; i++) { - push_trace_bp_f(((asg16_v *)(&(res->c))), 3, cns->a[i].c, (uint16_t)-1, 1, ((idx->clen>0)?1:0)); - idx->clen = res->c.n - idx->cidx; nec++; - } - } - } - // fprintf(stderr, "\n"); - return nec; -} - -///no e_end since e always covers end; s may not have end -uint64_t cns_gen_full0(overlap_region* ol, All_reads *rref, uint64_t s, uint64_t e, uint64_t s_end, char* qstr, UC_Read* tu, bit_extz_t *exz, cc_idx_t *idx, uint64_t occ_tot, double occ_max, asg32_v* b32, cns_gfa *cns, uint64_t max_trace, window_list *ridx, window_list_alloc *res, uint32_t rid) -{ - init_cns_g(cns, qstr + s, e - s, rid); - // if(e -s > 100) { - // fprintf(stderr, "[M::%s]::[%lu, %lu), cns->n::%u, qstr::%.*s\n", __func__, s, e, (uint32_t)cns->n, (int)(e-s), qstr+s); - // } - // fprintf(stderr, "[M::%s]::[%lu, %lu)\n", __func__, s, e); - - uint64_t *id_a = NULL, id_n, nec = 0; b32->n = 0; - rr_seq_t ssq; ssq.rref = rref; ssq.tu = tu; ssq.s = ssq.e = 0; ssq.n0 = ssq.n1 = 32; ssq.id = ssq.rev = 0; - id_n = iter_cc_idx_t(ol, idx, s, e, idx->rr, ((s==e)?1:0), &id_a); - // debug_inter0(ol, idx->c_idx, idx->idx->a + idx->i0, idx->srt_n - idx->i0, id_a, id_n, s, e, ((s==e)?1:0), 0, "-1-"); - uint64_t k, q[2], os, oe; ul_ov_t *p; overlap_region *z; idx->rr = 0; - // fprintf(stderr, "[M::%s] [%lu, %lu) id_n::%lu\n", __func__, s, e, id_n); - for (k = 0; k < id_n; k++) { - p = &(idx->c_idx[id_a[k]]); z = &(ol[ovlp_id(*p)]); - q[0] = z->w_list.a[ovlp_cur_wid(*p)].x_start+ovlp_bd(*p); - q[1] = z->w_list.a[ovlp_cur_wid(*p)].x_end+1-ovlp_bd(*p); - - // fprintf(stderr, "[M::%s] tid::%u\t%.*s\twid::%u\tq::[%u, %u)\terr::%d\toerr::%u\n", __func__, ol[ovlp_id(*p)].y_id, (int)Get_NAME_LENGTH(R_INF, ol[ovlp_id(*p)].y_id), Get_NAME(R_INF, ol[ovlp_id(*p)].y_id), - // ovlp_cur_wid(*p), ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].x_start, ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].x_end+1, ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].error, ol[ovlp_id(*p)].non_homopolymer_errors); - - if(q[1] <= e) idx->rr = 1; - os = MAX(q[0], s); oe = MIN(q[1], e); - // if((oe > os) || ((s == e) && (s >= q[0]) && (s <= q[1]))) { - if((oe > os) || ((s == e) && (s > q[0]) && (s < q[1]))) { - // if(oe >= os) { - ///[-4-][-12-][-4-][-12-] - ///[cigar_len][cigar][base_len][base] - extract_sub_cigar_cns(z, os, oe, s, e, s_end, &ssq, p, cns, b32, max_trace, rid); - // if(m != ((uint32_t)-1)) {///no gap in both sides - // kv_push(uint32_t, *b32, m); - // } - } - } - - // fprintf(stderr, "-2-[M::%s] cns->n::%u\n", __func__, (uint32_t)cns->n); - - // return; - - refine_cns_g(cns, b32); - - // fprintf(stderr, "-3-[M::%s] cns->n::%u\n", __func__, (uint32_t)cns->n); - - gseq_cns_g(cns, b32, e - s); - - // fprintf(stderr, "-4-[M::%s] cns->n::%u\n", __func__, (uint32_t)cns->n); - - // nec += push_correct1(ridx, res, cns, b32, e - s); - nec += push_correct1_fhc(ridx, res, cns, qstr + s, tu, exz, b32, e - s, rid); - - // fprintf(stderr, "-5-[M::%s] cns->n::%u\n", __func__, (uint32_t)cns->n); - return nec; -} - -uint64_t cns_gen_full(overlap_region* ol, All_reads *rref, uint64_t s0, uint64_t e0, uint64_t wl, char* qstr, UC_Read* tu, bit_extz_t *exz, cc_idx_t *idx, uint64_t occ_tot, double occ_max, asg32_v* b32, cns_gfa *cns, uint64_t max_trace, window_list *ridx, window_list_alloc *res, uint32_t rid) -{ - uint64_t nec = 0; - if(e0 - s0 <= wl) { - nec += cns_gen_full0(ol, rref, s0, e0, 1, qstr, tu, exz, idx, occ_tot, occ_max, b32, cns, max_trace, ridx, res, rid); - } else { - uint64_t s, e; - s = s0; e = s0 + wl; e = ((e<=e0)?e:e0); - for (; s < e0; ) { - // rn = iter_cc_idx_t(ol->list, &ii_a, s, e, rr, 0, &ra); - // debug_inter0(ol->list, ii_a.c_idx, ii_a.idx->a + ii_a.i0, ii_a.srt_n - ii_a.i0, ra, rn, s, e, 0, 1, "-0-"); - // rr = wcns_vote(ol->list, rref, qu->seq, ql, tu, ra, rn, s, e, ii_a.c_idx, &ii_b, occ_tot, occ_exact, aux_o, b32, cns, rid); - nec += cns_gen_full0(ol, rref, s, e, (s==s0)?1:0, qstr, tu, exz, idx, occ_tot, occ_max, b32, cns, max_trace, ridx, res, rid); - s += wl; e += wl; e = ((e<=e0)?e:e0); - } - } - return nec; -} - -uint64_t push_correct0(window_list *idx, window_list_alloc *res, uint32_t len0, uint32_t rc) -{ - uint64_t nec = 0; - // fprintf(stderr, "[M::%s] NULL(idx)::%u\n", __func__, idx?0:1); - if(len0 != ((uint32_t)-1)) { - push_trace_bp(((asg16_v *)(&(res->c))), 0, (uint16_t)-1, len0, ((idx->clen>0)?1:0)); - idx->clen = res->c.n - idx->cidx; - } else if(rc != ((uint32_t)-1)) { - // fprintf(stderr, "[M::%s]\t", __func__); - uint32_t cc = (rc<<4)>>20, cn = rc>>28, ck = 0, cs, cp; - uint32_t bc = (rc<<20)>>20, bn = (rc<<16)>>28, bk = 0, bs, bp; - ///debug - // prt_cigar0(cc, cn); - // prt_bp0(bc, bn); - - for (ck = 0; ck < cn; ck++) { - cs = (cn-1-ck)<<1; cp = (cc>>cs)&3; - - bp = (uint32_t)-1; - if(cp != 3) {///bp == 3: more x - bs = (bn-1-bk)<<1; bp = (bc>>bs)&3; - bk++; - } - // fprintf(stderr, "[M::%s] cp::%u, bp::%u\n", __func__, cp, bp); - - push_trace_bp(((asg16_v *)(&(res->c))), cp, bp, 1, ((idx->clen>0)?1:0)); - idx->clen = res->c.n - idx->cidx; - // fprintf(stderr, "%c", cm[(in >> mp)&3]); - - // fprintf(stderr, "%c", "MSID"[cp]); - if(cp != 0) nec++; - } - - // fprintf(stderr, "\n"); - } - - return nec; -} - -uint64_t push_correct0_fhc(window_list *idx, window_list_alloc *res, uint32_t len0, uint32_t rc, char *qstr) -{ - uint64_t nec = 0; - // fprintf(stderr, "[M::%s] NULL(idx)::%u\n", __func__, idx?0:1); - if(len0 != ((uint32_t)-1)) { - push_trace_bp_f(((asg16_v *)(&(res->c))), 0, (uint16_t)-1, (uint16_t)-1, len0, ((idx->clen>0)?1:0)); - idx->clen = res->c.n - idx->cidx; - } else if(rc != ((uint32_t)-1)) { - // fprintf(stderr, "[M::%s]\t", __func__); - uint32_t cc = (rc<<4)>>20, cn = rc>>28, ck = 0, cs, cp; - uint32_t bc = (rc<<20)>>20, bn = (rc<<16)>>28, btk = 0, bqk = 0, bs, bqp, btp; - ///debug - // prt_cigar0(cc, cn); - // prt_bp0(bc, bn); - - for (ck = 0; ck < cn; ck++) { - cs = (cn-1-ck)<<1; cp = (cc>>cs)&3; - - bqp = btp = (uint32_t)-1; - if(cp != 3) {///bp == 3: more x - bs = (bn-1-btk)<<1; btp = (bc>>bs)&3; btk++; - } - if(cp != 2) {///bp == 2: more y - bqp = seq_nt6_table[(uint32_t)qstr[bqk]]; bqk++; - } - // fprintf(stderr, "[M::%s] cp::%u, btp::%u, bqp::%u\n", __func__, cp, btp, bqp); - - push_trace_bp_f(((asg16_v *)(&(res->c))), cp, bqp, btp, 1, ((idx->clen>0)?1:0)); - idx->clen = res->c.n - idx->cidx; - // fprintf(stderr, "%c", cm[(in >> mp)&3]); - - // fprintf(stderr, "%c", "MSID"[cp]); - if(cp != 0) nec++; - } - - // fprintf(stderr, "\n"); - } - - return nec; -} - -void output_cns_g(cns_gfa *cns, uint64_t s, uint64_t e) -{ - // char *gfa_id = NULL, p; MALLOC(gfa_id, Get_NAME_LENGTH(R_INF, qid) + 128); - // sprintf(gfa_id, "%.*s.%lu_%lu.cns.gfa", (int)Get_NAME_LENGTH(R_INF, qid), Get_NAME(R_INF, qid), s, e); - char *gfa_id = NULL, p, f; MALLOC(gfa_id, 128); - sprintf(gfa_id, "ec.%lu_%lu.cns.gfa", s, e); - - FILE *fp = fopen(gfa_id, "w"); uint64_t k, z; char cm[4]; cm[0] = 'A'; cm[1] = 'C'; cm[2] = 'G'; cm[3] = 'T'; - - sprintf(gfa_id, "s_0_%c", cm[cns->a[0].c]); - fprintf(fp, "S\t%s\t*\tLN:i:%u\trd:i:%c\n", gfa_id, 0/**cns->a[0].sc**/, cm[cns->a[0].c]); - - sprintf(gfa_id, "e_1_%c", cm[cns->a[1].c]); - fprintf(fp, "S\t%s\t*\tLN:i:%u\trd:i:%c\n", gfa_id, 0/**cns->a[1].sc**/, cm[cns->a[1].c]); - - for (k = 2; k < cns->n; k++) { - if(del_cns_nn((*cns), k)) continue; - sprintf(gfa_id, "%c_%lu_%c", ((kbn)?'b':'n'), k, cm[cns->a[k].c]); - fprintf(fp, "S\t%s\t*\tLN:i:%d\trd:i:%c\n", gfa_id, 0/**cns->a[k].sc**/, cm[cns->a[k].c]); - } - - for (k = 0; k < cns->n; k++) { - if(del_cns_nn((*cns), k)) continue; - - if(k == 0) { - p = 's'; - } else if(k == 1) { - p = 'e'; - } else if (kbn) { - p = 'b'; - } else { - p = 'n'; - } - - sprintf(gfa_id, "%c_%lu_%c", p, k, cm[cns->a[k].c]); - for (z = 0; z < cns->a[k].arc.n; z++) { - if(del_cns_arc((cns->a[k]), z)) continue; - - if(cns->a[k].arc.a[z].v == 0) { - p = 's'; - } else if(cns->a[k].arc.a[z].v == 1) { - p = 'e'; - } else if (cns->a[k].arc.a[z].v < cns->bn) { - p = 'b'; - } else { - p = 'n'; - } - - f = ((z < cns->a[k].arc.nou)?('+'):('-')); - fprintf(fp, "L\t%s\t%c\t%c_%u_%c\t%c\t0M\tL1:i:%u\n", - gfa_id, f, - p, cns->a[k].arc.a[z].v, cm[cns->a[cns->a[k].arc.a[z].v].c], f, - cns->a[k].arc.a[z].sc); - } - } - - fclose(fp); free(gfa_id); -} - -uint32_t cal_cigar_xlen(overlap_region *in) -{ - assert(in->w_list.n == 1); - uint32_t cn = in->w_list.a[0].clen; uint16_t *a = in->w_list.c.a + in->w_list.a[0].cidx; - uint32_t ci, len, xk, yk; uint16_t c, b; asg16_v scc; scc.n = scc.m = cn; scc.a = a; - - ci = 0; xk = yk = 0; - while (ci < cn) { - ci = pop_trace_bp(&scc, ci, &c, &b, &len); - if(c != 2) xk += len; - if(c != 3) yk += len; - } - - return xk; -} - -uint32_t cal_cigar_xlen_fhc(overlap_region *in) -{ - assert(in->w_list.n == 1); - uint32_t cn = in->w_list.a[0].clen; uint16_t *a = in->w_list.c.a + in->w_list.a[0].cidx; - uint32_t ci, len, xk, yk; uint16_t c, bq, bt; asg16_v scc; scc.n = scc.m = cn; scc.a = a; - - ci = 0; xk = yk = 0; - while (ci < cn) { - ci = pop_trace_bp_f(&scc, ci, &c, &bq, &bt, &len); - if(c != 2) xk += len; - if(c != 3) yk += len; - } - - return xk; -} - -uint64_t push_cns_anchor(overlap_region* ol, All_reads *rref, uint64_t s, uint64_t e, char* qstr, uint64_t ql, UC_Read* tu, bit_extz_t *exz, cc_idx_t *idx, overlap_region *aux_o, uint64_t is_tail, uint64_t occ_tot, double occ_max, asg32_v* b32, cns_gfa *cns, uint32_t rid) -{ - if((!is_tail) && (s >= e)) return 0;//if s >= e && is_tail = 1, gen the cns of the last a few bases -> s == e == ql - // fprintf(stderr, "\n****************[M::%s::M] [%lu, %lu)****************\n", __func__, s, e); - window_list *p = NULL; uint64_t e0 = 0, nec = 0; uint32_t rc; - if(aux_o->w_list.n > 0) { - p = &(aux_o->w_list.a[aux_o->w_list.n-1]); - e0 = p->x_end+1; - ///make sure e > s - } - assert(s >= e0); - if((s == e) && (is_tail == 1) && (s == e0)) return 0;///in this case, s == e == ql - - if(aux_o->w_list.n == 0) { - kv_pushp(window_list, aux_o->w_list, &p); - p->x_start = -1; p->x_end = -1; - p->clen = p->cidx = 0; - } - - if(((!is_tail) && (s > 0)) || ((is_tail) && (s > e0))) { - // fprintf(stderr, ">>>>>>[M::%s::M] [%lu, %lu), ec::%u\n", __func__, e0, s, cal_cigar_xlen_fhc(aux_o)); - // fprintf(stderr, ">>>>>>[M::%s::M] [%lu, %lu)\n", __func__, e0, s); - if (cns_gen0(ol, rref, e0, s, ql, tu, idx, occ_tot, occ_max, b32, &rc)) { - if(p->x_start == -1 || p->x_end == -1) {///hasn't neem set - p->x_start = e0; p->x_end = s-1; - } - // nec += push_correct0(p, &(aux_o->w_list), (uint32_t)-1, rc); - nec += push_correct0_fhc(p, &(aux_o->w_list), (uint32_t)-1, rc, qstr + e0); - // fprintf(stderr, "-0-[M::%s::M]\n", __func__); - } else { - nec += cns_gen_full(ol, rref, e0, s, cns->cns_g_wl, qstr, tu, exz, idx, occ_tot, occ_max, b32, cns, ql, p, &(aux_o->w_list), rid); - // output_cns_g(cns, e0, s); exit(1); - // fprintf(stderr, "-1-[M::%s::M]\n", __func__); - } - p->x_end = s-1; - - // if((uint32_t)p->x_end + 1 != cal_cigar_xlen_fhc(aux_o)) { - // fprintf(stderr, "sb1::%u\n", cal_cigar_xlen_fhc(aux_o)); - // } - } - - - // fprintf(stderr, "------[M::%s::M] [%lu, %lu), ec::%u\n", __func__, s, e, cal_cigar_xlen_fhc(aux_o)); - // fprintf(stderr, "------[M::%s::M] [%lu, %lu)\n", __func__, s, e); - if(p->x_start == -1 || p->x_end == -1) {///hasn't neem set - p->x_start = s; p->x_end = e-1; - } - // nec += push_correct0(p, &(aux_o->w_list), e-s, (uint32_t)-1); - nec += push_correct0_fhc(p, &(aux_o->w_list), e-s, (uint32_t)-1, NULL); - p->x_end = e-1; - // if((uint32_t)p->x_end + 1 != cal_cigar_xlen_fhc(aux_o)) { - // fprintf(stderr, "ta2::%u\n", cal_cigar_xlen_fhc(aux_o)); - // } - return nec; -} - -void prt_correct0_dbg(overlap_region *in) -{ - int64_t wn = in->w_list.n, k; uint32_t ci, len; asg16_v ff; uint16_t c, b; - char cm[4], cc[4]; - cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; - cc[0] = 'A'; cc[1] = 'C'; cc[2] = 'G'; cc[3] = 'T'; - - for (k = 0; k < wn; k++) { - fprintf(stderr, "\n[M::%s] w[%ld] [%d, %d) clen::%u\n", __func__, k, in->w_list.a[k].x_start, in->w_list.a[k].x_end + 1, in->w_list.a[k].clen); - - ci = 0; ff.n = ff.m = in->w_list.a[k].clen; ff.a = in->w_list.c.a + in->w_list.a[k].cidx; - while (ci < ff.n) { - ci = pop_trace_bp(&ff, ci, &c, &b, &len); - fprintf(stderr, "|%u%c(%c)", len, cm[c], ((c==1)||(c==2))?(cc[b]):('*')); - } - - fprintf(stderr, "|\n"); - } -} - -uint64_t wcns_vote(overlap_region* ol, All_reads *rref, char* qstr, uint64_t ql, UC_Read* tu, bit_extz_t *exz, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, ul_ov_t *c_idx, cc_idx_t *occ, uint64_t occ_tot, double occ_exact, overlap_region *aux_o, asg32_v* b32, cns_gfa *cns, uint32_t rid, uint64_t *nec) -{ - uint64_t k, q[2], rr = 0, os, oe, wl, oc[2], fI; ul_ov_t *p, *gp; overlap_region *z; - // uint64_t *ct = occ->idx->a;///occ->idx->a[0, wl<<1) - for (k = 0; k < id_n; k++) { - p = &(c_idx[id_a[k]]); z = &(ol[ovlp_id(*p)]); - q[0] = z->w_list.a[ovlp_cur_wid(*p)].x_start+ovlp_bd(*p); - q[1] = z->w_list.a[ovlp_cur_wid(*p)].x_end+1-ovlp_bd(*p); - if(q[1] <= e) rr = 1; - os = MAX(q[0], s); oe = MIN(q[1], e); - if(oe > os) { - ///prepare for CNS - gp = &(occ->c_idx[id_a[k]]); - ovlp_cur_xoff(*gp) = ovlp_cur_xoff(*p); ovlp_cur_yoff(*gp) = ovlp_cur_yoff(*p); ovlp_cur_coff(*gp) = ovlp_cur_coff(*p); ovlp_cur_ylen(*gp) = ovlp_cur_ylen(*p); - // assert(ovlp_cur_wid(*p) == ovlp_cur_wid(*gp)); - // assert(ovlp_id(*p) == ovlp_id(*gp)); - // fprintf(stderr, "[M::%s] tid::%u\t%.*s\twid::%u\tq::[%u, %u)\tos::%lu\toe::%lu\n", __func__, ol[ovlp_id(*p)].y_id, (int)Get_NAME_LENGTH(R_INF, ol[ovlp_id(*p)].y_id), Get_NAME(R_INF, ol[ovlp_id(*p)].y_id), - // ovlp_cur_wid(*p), ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].x_start, ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].x_end+1, os, oe); - extract_sub_cigar_mm(z, os, oe, p, occ->idx->a + os - s); - } - } - - wl = e - s; - os = occ->mms; oe = occ->mme; - - // fprintf(stderr, "[M::%s] s::%lu\te::%lu\n", __func__, s, e); - - for (k = 0; k < wl; k++) { - //+1 for the reference read - oc[0] = (occ->idx->a[(k<<1)]>>32) + 1; - oc[1] = ((uint32_t)occ->idx->a[(k<<1)]) + 1; - // fprintf(stderr, "-0-p::%lu\toc[0]::%lu\toc[1]::%lu\tgoc[0]::%lu\tgoc[1]::%u\n", s + k, oc[0], oc[1], (ct[(k<<1)+1]>>32) + 1, ((uint32_t)ct[(k<<1)+1]) + 1); - // if(oc[1] < occ_tot || oc[0] <= 1) { - // ct[(k<<1)] = ct[(k<<1)+1] = 0; - // continue; - // } - // fprintf(stderr, "-1-p::%lu\toc[0]::%lu\toc[1]::%lu\n", s + k, oc[0], oc[1]); - - ///a) pass coverage check; b) no enough coverage - if(((oc[0] > (oc[1]*occ_exact)) && (oc[0] > (oc[1]-oc[0])) && (oc[1] >= occ_tot) && (oc[0] > 1)) || - (oc[1] < occ_tot)) { - ///note: there might be insertions at q[k-1, k], insead if q[k, k+1] - fI = 1; - ///make sure there is no insertion - //+1 for the reference read - oc[0] = (occ->idx->a[(k<<1)+1]>>32) + 1; - oc[1] = ((uint32_t)occ->idx->a[(k<<1)+1]) + 1; - ///a) pass coverage check; b) no enough coverage - if((((oc[0] > (oc[1]*occ_exact)) && (oc[0] > (oc[1]-oc[0])) && (oc[1] >= occ_tot) && (oc[0] > 1))) || - (oc[1] < occ_tot)) { - fI = 0; - } - - if(fI) { - // fprintf(stderr, "-1-p::%lu\toc[0]::%lu\toc[1]::%u\tgoc[0]::%lu\tgoc[1]::%u\n", s + k, (occ->idx->a[(k<<1)]>>32) + 1, ((uint32_t)occ->idx->a[(k<<1)]) + 1, (occ->idx->a[(k<<1)+1]>>32) + 1, ((uint32_t)occ->idx->a[(k<<1)+1]) + 1); - if(oe > os && os != ((uint64_t)-1)) {///push previous intervals - (*nec) += push_cns_anchor(ol, rref, os, oe, qstr, ql, tu, exz, occ, aux_o, 0, occ_tot, occ_exact, b32, cns, rid); - } - os = oe = (uint64_t)-1; - } - - //+1 for the reference read - oc[0] = (occ->idx->a[(k<<1)]>>32) + 1; - oc[1] = ((uint32_t)occ->idx->a[(k<<1)]) + 1; - if((s+k) == oe) { - oe++; - } else { - if(oe > os && os != ((uint64_t)-1)) {///push previous intervals - (*nec) += push_cns_anchor(ol, rref, os, oe, qstr, ql, tu, exz, occ, aux_o, 0, occ_tot, occ_exact, b32, cns, rid); - } - os = s+k; oe = s+k+1; - } - } else { - // fprintf(stderr, "-2-p::%lu\toc[0]::%lu\toc[1]::%u\tgoc[0]::%lu\tgoc[1]::%u\n", s + k, (occ->idx->a[(k<<1)]>>32) + 1, ((uint32_t)occ->idx->a[(k<<1)]) + 1, (occ->idx->a[(k<<1)+1]>>32) + 1, ((uint32_t)occ->idx->a[(k<<1)+1]) + 1); - if(oe > os && os != ((uint64_t)-1)) {///push previous intervals - (*nec) += push_cns_anchor(ol, rref, os, oe, qstr, ql, tu, exz, occ, aux_o, 0, occ_tot, occ_exact, b32, cns, rid); - } - os = oe = (uint64_t)-1; - } - occ->idx->a[(k<<1)] = occ->idx->a[(k<<1)+1] = 0; - } - - occ->mms = occ->mme = (uint64_t)-1; - if(oe > os && os != ((uint64_t)-1)) { - occ->mms = os; occ->mme = oe; - } - return rr; -} - - - -void print_debug_ovlp_cigar(overlap_region_alloc* ol, asg64_v* idx, kv_ul_ov_t *c_idx) -{ - uint64_t k, ci; uint32_t cl; ul_ov_t *cp; bit_extz_t ez; uint16_t c; char cm[4]; - cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; - for (k = 0; k < idx->n; k++) { - cp = &(c_idx->a[(uint32_t)idx->a[k]]); - fprintf(stderr, "**********[M::%s] tid::%u\t%.*s\twid::%u\tq::[%u, %u)\terr::%d\toerr::%u**********\n", __func__, ol->list[ovlp_id(*cp)].y_id, (int)Get_NAME_LENGTH(R_INF, ol->list[ovlp_id(*cp)].y_id), Get_NAME(R_INF, ol->list[ovlp_id(*cp)].y_id), - ovlp_cur_wid(*cp), ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start, ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1, ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].error, ol->list[ovlp_id(*cp)].non_homopolymer_errors); - set_bit_extz_t(ez, ol->list[ovlp_id(*cp)], ovlp_cur_wid(*cp)); ci = 0; - while (ci < ez.cigar.n) { - ci = pop_trace(&(ez.cigar), ci, &c, &cl); - fprintf(stderr, "%u%c", cl, cm[c]); - } - fprintf(stderr, "\n"); - } -} - -uint64_t wcns_gen(overlap_region_alloc* ol, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, int64_t bd, uint64_t wl, int64_t ql, uint64_t occ_tot, double occ_exact, overlap_region *aux_o, asg32_v* b32, cns_gfa *cns, uint64_t cns_g_wl, uint32_t rid) -{ - int64_t on = ol->length, k, i, zwn, q[2]; cns->cns_g_wl = cns_g_wl; - uint64_t m, *ra, rn, nec = 0, n_id, l_nid, p[2], li; overlap_region *z; ul_ov_t *cp; - bit_extz_t ez; uint64_t ci; uint32_t cl; uint16_t c; - - for (k = idx->n = c_idx->n = 0; k < on; k++) { - z = &(ol->list[k]); zwn = z->w_list.n; z->without_large_indel = l_nid = 0; - if((!zwn) || (z->is_match != 1)) continue; - for (i = 0, li = (uint64_t)-1; i < zwn; i++) { - if(is_ualn_win(z->w_list.a[i])) { - n_id = z->w_list.a[i].x_end + 1 - z->w_list.a[i].x_start; - if(n_id >= 6) l_nid = 1; - continue; - } - q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; - q[0] += bd; q[1] -= bd; - if(q[1] >= q[0]) { - m = ((uint64_t)q[0]); m <<= 32; - m += c_idx->n; kv_push(uint64_t, *idx, m); - - kv_pushp(ul_ov_t, *c_idx, &cp); - ovlp_id(*cp) = k; ///ovlp id - // ovlp_min_wid(*cp) = i; ///beg id of windows - // ovlp_max_wid(*cp) = i; ///end id of windows - ovlp_cur_wid(*cp) = i; ///cur id of windows - ovlp_cur_xoff(*cp) = z->w_list.a[i].x_start; ///cur xpos - ovlp_cur_yoff(*cp) = z->w_list.a[i].y_start; ///cur xpos - ovlp_cur_ylen(*cp) = 0; - ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window - ovlp_bd(*cp) = bd; - } - - if(l_nid == 0) { - if(i == 0) { - p[0] = z->w_list.a[i].x_start; p[1] = z->x_pos_s; - n_id = ((p[0] >= p[1])? (p[0] - p[1]): (p[1] - p[0])); - if(n_id >= 6) l_nid = 1; - } - - if(li != (uint64_t)-1) { - p[0] = z->w_list.a[i].x_start; p[1] = z->w_list.a[li].x_end + 1; - n_id = ((p[0] >= p[1])? (p[0] - p[1]): (p[1] - p[0])); - if(n_id >= 6) l_nid = 1; - - p[0] = z->w_list.a[i].y_start; p[1] = z->w_list.a[li].y_end + 1; - n_id = ((p[0] >= p[1])? (p[0] - p[1]): (p[1] - p[0])); - if(n_id >= 6) l_nid = 1; - } - - if(i + 1 == zwn) { - p[0] = z->w_list.a[i].x_end; p[1] = z->x_pos_e; - n_id = ((p[0] >= p[1])? (p[0] - p[1]): (p[1] - p[0])); - if(n_id >= 6) l_nid = 1; - } - - if(l_nid == 0) { - set_bit_extz_t(ez, (*z), i); ci = 0; - while (ci < ez.cigar.n && l_nid == 0) { - ci = pop_trace(&(ez.cigar), ci, &c, &cl); - if(c >= 2 && cl >= 6) l_nid = 1; - } - } - } - - li = i; - } - z->without_large_indel = (l_nid?0:1); - } - - int64_t srt_n = idx->n, s, e, t, rr; i = 0; - radix_sort_ec64(idx->a, idx->a+idx->n); - for (k = 1, i = 0; k < srt_n; k++) { - if (k == srt_n || (idx->a[k]>>32) != (idx->a[i]>>32)) { - if(k - i > 1) { - for (t = i; t < k; t++) { - cp = &(c_idx->a[(uint32_t)idx->a[t]]); - // s = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); - // assert(s == (int64_t)(idx->a[i]>>32)); - m = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); - m <<= 32; m += ((uint32_t)idx->a[t]); idx->a[t] = m; - // fprintf(stderr, "[M::%s] s::%ld\tsi::%lu\n", __func__, s, (idx->a[i]>>32)); - } - radix_sort_ec64(idx->a + i, idx->a + k); - } - i = k; - } - } - - // print_debug_ovlp_cigar(ol, idx, c_idx); - - ///second index - kv_resize(ul_ov_t, *c_idx, (c_idx->n<<1)); - ul_ov_t *idx_a = NULL, *idx_b = NULL; - idx_a = c_idx->a; idx_b = c_idx->a; - memcpy(idx_b, idx_a, c_idx->n * (sizeof((*(idx_a))))); - - kv_resize(uint64_t, *buf, ((wl<<1) + idx->n)); buf->n = ((wl<<1) + idx->n); - memcpy(buf->a + (wl<<1), idx->a, idx->n * (sizeof((*(idx->a))))); - memset(buf->a, 0, (wl<<1)*(sizeof((*(idx->a))))); - - cc_idx_t ii_a, ii_b; memset(&ii_a, 0, sizeof(ii_a)); memset(&ii_b, 0, sizeof(ii_b)); - - ii_a.c_idx = idx_a; ii_a.idx = idx; ii_a.i = ii_a.i0 = 0; ii_a.srt_n = ii_a.idx->n; ii_a.mms = ii_a.mme = (uint64_t)-1; - ii_b.c_idx = idx_b; ii_b.idx = buf; ii_b.i = ii_b.i0 = (wl<<1); ii_b.srt_n = ii_b.idx->n; ii_b.mms = ii_b.mme = (uint64_t)-1; - - s = 0; e = wl; e = ((e<=ql)?e:ql); rr = 0; - aux_o->w_list.n = aux_o->w_list.c.n = 0; ///for cigar - for (; s < ql; ) { - rn = iter_cc_idx_t(ol->list, &ii_a, s, e, rr, 0, &ra); - // debug_inter0(ol->list, ii_a.c_idx, ii_a.idx->a + ii_a.i0, ii_a.srt_n - ii_a.i0, ra, rn, s, e, 0, 1, "-0-"); - rr = wcns_vote(ol->list, rref, qu->seq, ql, tu, exz, ra, rn, s, e, ii_a.c_idx, &ii_b, occ_tot, occ_exact, aux_o, b32, cns, rid, &nec); - s += wl; e += wl; e = ((e<=ql)?e:ql); - } - - if(ii_b.mme > ii_b.mms && ii_b.mms != (uint64_t)-1) { - nec += push_cns_anchor(ol->list, rref, ii_b.mms, ii_b.mme, qu->seq, ql, tu, exz, &ii_b, aux_o, 0, occ_tot, occ_exact, b32, cns, rid); - } - - nec += push_cns_anchor(ol->list, rref, ql, ql, qu->seq, ql, tu, exz, &ii_b, aux_o, 1, occ_tot, occ_exact, b32, cns, rid); - - - - ///for debug - // zwn = aux_o->w_list.n; - // fprintf(stderr, "\n******[M::%s]****** wn::%ld, ql::%ld\n", __func__, zwn, ql); - // prt_correct0_dbg(aux_o); - // for (i = 0; i < zwn; i++) { - // fprintf(stderr, "[M::%s] (%ld)[%d, %d)\n", __func__, i, aux_o->w_list.a[i].x_start, aux_o->w_list.a[i].x_end+1); - // } - return nec; -} - -void push_nec_re(overlap_region *in, asg16_v *ou) -{ - assert(in->w_list.n == 1); - uint32_t n1 = in->w_list.a[0].clen; - if(n1 > ou->m) { - REALLOC(ou->a, n1); ou->m = n1; - } - ou->n = n1; - memcpy(ou->a, in->w_list.c.a + in->w_list.a[0].cidx, n1*sizeof((*(in->w_list.c.a)))); -} - -uint32_t extract_max_exact_sub(asg16_v *in, int64_t xs0, int64_t xe0, int64_t ys0, int64_t ye0, int64_t *exk, int64_t *eyk, int64_t *eck, uint64_t *rxs, uint64_t *rxe, uint64_t *rys, uint64_t *rye) -{ - int64_t xk = *exk, yk = *eyk, ck = *eck, cn = in->n, ol, wx[2], wy[2], os, oe; uint16_t op, bq, bt; uint32_t cl, ovlp; - *rxs = *rxe = *rys = *rye = 0; - - if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed - ck = 0; xk = 0; yk = 0; - } - - while (ck > 0 && xk >= xs0) {///x -> t; y -> p; first insertion and then match/mismatch - --ck; - op = in->a[ck]>>14; - // ol = (((op == 1) || (op == 2))?(in->a[ck]&(0xfff)):(in->a[ck]&(0x3fff))); - if((op == 2) || (op == 3)) { - ol = in->a[ck]&(0xfff); - } else if(op == 1) { - ol = in->a[ck]&(0x3ff); - } else { - ol = in->a[ck]&(0x3fff); - } - if(op != 2) xk -= ol; - if(op != 3) yk -= ol; - } - - while (ck < cn && xk < xe0) { - wx[0] = xk; wy[0] = yk; - // ck = pop_trace_bp(in, ck, &op, &b, &cl); - ck = pop_trace_bp_f(in, ck, &op, &bq, &bt, &cl); - if(op != 2) xk += cl; - if(op != 3) yk += cl; - wx[1] = xk; wy[1] = yk; - if(op == 0) { - os = MAX(xs0, wx[0]); oe = MIN(xe0, wx[1]); - ovlp = ((oe>os)? (oe-os):0); - if((ovlp > 0) && (ovlp > (*rxe) - (*rxs))) { - (*rxs) = wy[0] + os - wx[0]; - (*rxe) = wy[0] + oe - wx[0]; - - (*rys) = ys0 + os - xs0; - (*rye) = ys0 + oe - xs0; - } - } - } - - *exk = xk; *eyk = yk; *eck = ck; - if((*rxe) > (*rxs)) return 1; - return 0; -} - -void debug_extract_max_exact_sub(uint32_t qid, UC_Read* qu, UC_Read* tu) -{ - uint32_t ci = 0, len, xk, yk, wx[2], wy[2], k; uint16_t c, b; - - recover_UC_Read(tu, &R_INF, qid); - - ci = 0; yk = 0; - while (ci < scc.a[qid].n) { - ci = pop_trace_bp(&scc.a[qid], ci, &c, &b, &len); - if(c != 3) yk += len; - } - resize_UC_Read(qu, yk); - - ci = 0; xk = yk = 0; - while (ci < scc.a[qid].n) { - wx[0] = xk; wy[0] = yk; - ci = pop_trace_bp(&scc.a[qid], ci, &c, &b, &len); - if(c != 2) xk += len; - if(c != 3) yk += len; - wx[1] = xk; wy[1] = yk; - if(c == 0) { - // memcpy(p->a + wy[0], p->z.seq + wx[0], (wx[1]-wx[0])*sizeof((*(p->a)))); - for (; wx[0] < wx[1]; wx[0]++, wy[0]++) { - qu->seq[wy[0]] = tu->seq[wx[0]]; - } - } else if(c == 1 || c == 2) { - for (k = wy[0]; k < wy[1]; k++) { - qu->seq[k] = s_H[b]; - } - } - // if(i == 700) fprintf(stderr, "|%u%c(%c)(x::%u)(y::%u)", len, cm[c], ((c==1)||(c==2))?(cc[b]):('*'), wx[1], wy[1]); // s_H - } -} - -uint64_t extract_max_exact(overlap_region *z, asg16_v *ec, /**UC_Read *qu, UC_Read *tu,**/ uint32_t *rxs, uint32_t *rxe, uint32_t *rys, uint32_t *rye) -{ - // if(z->x_id == 75 && z->y_id == 59) { - // fprintf(stderr, "[M::%s]\tz->y_id::%u\n", __func__, z->y_id); - // if(z->y_pos_strand) { - // recover_UC_Read_RC(tu, &R_INF, z->y_id); - // } else { - // recover_UC_Read(tu, &R_INF, z->y_id); ///b->z.length - // } - // } - - *rxs = *rxe = *rys = *rye = (uint32_t)-1; - uint64_t k, rx[2], ry[2], xk, yk, wx[2], wy[2], mx[2], my[2]; - uint32_t cl, ck; uint16_t c; asg16_v ct; int64_t exk, eyk, eck; - exk = eyk = eck = 0; mx[0] = mx[1] = my[0] = my[1] = 0; - for (k = 0; k < z->w_list.n; k++) { - ct.a = z->w_list.c.a + z->w_list.a[k].cidx; - ct.n = ct.m = z->w_list.a[k].clen; ck = 0; - xk = z->w_list.a[k].x_start; yk = z->w_list.a[k].y_start; - while (ck < ct.n) { - wx[0] = xk; wy[0] = yk; - ck = pop_trace(&ct, ck, &c, &cl); - if(c != 2) xk += cl; - if(c != 3) yk += cl; - wx[1] = xk; wy[1] = yk; - // if(c == 0) { - // if(memcmp(qref + wx[0], tu->seq + wy[0], wx[1] - wx[0])) { - // fprintf(stderr, "-0-[M::%s]\teq::[%lu,\t%lu)\tet::[%lu,\t%lu)\t%c\n", __func__, wx[0], wx[1], wy[0], wy[1], "+-"[z->y_pos_strand]); - // // exit(1); - // } - // } - if(wx[1] <= wx[0]) continue; - if((wx[1] - wx[0]) <= (mx[1] - mx[0])) continue; - if((c == 0) && (extract_max_exact_sub(ec, wx[0], wx[1], wy[0], wy[1], &exk, &eyk, &eck, &(rx[0]), &(rx[1]), &(ry[0]), &(ry[1])))) { - // if(z->x_id == 75 && z->y_id == 59) { - // if(memcmp(qu->seq + rx[0], tu->seq + ry[0], rx[1] - rx[0])) { - // fprintf(stderr, "-1-[M::%s]\tzq::[%lu,\t%lu)\tzt::[%lu,\t%lu)\teq::[%lu,\t%lu)\tet::[%lu,\t%lu)\n", - // __func__, wx[0], wx[1], wy[0], wy[1], rx[0], rx[1], ry[0], ry[1]); - // exit(1); - // } - // else { - // fprintf(stderr, "-2-[M::%s]\tzq::[%lu,\t%lu)\tzt::[%lu,\t%lu)\teq::[%lu,\t%lu)\tet::[%lu,\t%lu)\n", - // __func__, wx[0], wx[1], wy[0], wy[1], rx[0], rx[1], ry[0], ry[1]); - - // fprintf(stderr, "[M::%s] qstr::%.*s\n", __func__, ((int)(rx[1] - rx[0])), qu->seq + rx[0]); - // fprintf(stderr, "[M::%s] tstr::%.*s\n", __func__, ((int)(ry[1] - ry[0])), tu->seq + ry[0]); - // } - // } - if((rx[1] - rx[0]) > (mx[1] - mx[0])) { - mx[0] = rx[0]; mx[1] = rx[1]; - my[0] = ry[0]; my[1] = ry[1]; - } - } - } - } - - if(mx[1] > mx[0]) { - *rxs = mx[0]; *rxe = mx[1]; - *rys = my[0]; *rye = my[1]; - return 1; - } - - return 0; -} - -void push_ne_ovlp(ma_hit_t_alloc* paf, overlap_region_alloc* ov, uint32_t flag, All_reads* R_INF, asg16_v *ec/**, uint64_t qid, UC_Read *qu, UC_Read *tu**/) -{ - // if(qu && tu) { - // debug_extract_max_exact_sub(qid, qu, tu); - // } - uint64_t k, n; ma_hit_t *z; uint32_t rxs, rxe, rys, rye; - for (k = n = 0; k < ov->length; k++) { - if(ov->list[k].is_match == flag) n++; - } - - if(n > paf->size) { - paf->size = n; - REALLOC(paf->buffer, paf->size); - } - - for (k = paf->length = 0; k < ov->length; k++) { - if(ov->list[k].is_match == flag) { - // fprintf(stderr, "@%s\tSN:%.*s(id::%u)\terr::%u\n", flag==1?"SQ":"RQ", (int32_t)Get_NAME_LENGTH((*R_INF), ov->list[k].y_id), Get_NAME((*R_INF), ov->list[k].y_id), ov->list[k].y_id, ov->list[k].non_homopolymer_errors); - - z = &(paf->buffer[paf->length++]); - - z->qns = ov->list[k].x_id; - z->qns = z->qns << 32; - z->tn = ov->list[k].y_id; - - z->qns = z->qns | (uint64_t)(ov->list[k].x_pos_s); - z->qe = ov->list[k].x_pos_e + 1; - z->ts = ov->list[k].y_pos_s; - z->te = ov->list[k].y_pos_e + 1; - - ///for overlap_list, the x_strand of all overlaps are 0, so the tmp.rev is the same as the y_strand - z->rev = ov->list[k].y_pos_strand; - - z->bl = Get_READ_LENGTH((*R_INF), ov->list[k].y_id); - z->ml = ov->list[k].strong; - z->no_l_indel = ov->list[k].without_large_indel; - - if(ec) { - extract_max_exact(&ov->list[k], ec, /**qu, tu,**/ &rxs, &rxe, &rys, &rye); - z->el = 0; - // fprintf(stderr, "[M::%s]\tq::[%u,\t%u)\tt::[%u,\t%u)\teq::[%u,\t%u)\tet::[%u,\t%u)\n", __func__, ov->list[k].x_pos_s, ov->list[k].x_pos_e + 1, ov->list[k].y_pos_s, ov->list[k].y_pos_e + 1, rxs, rxe, rys, rye); - if(rxe > rxs) { - z->qns = ov->list[k].x_id; - z->qns = z->qns << 32; - z->qns = z->qns | (uint64_t)(rxs); - z->qe = rxe; - z->ts = rys; - z->te = rye; - - z->el = 1; - } - } - } - } -} - -void push_ff_ovlp(ma_hit_t_alloc* paf, overlap_region_alloc* ov, uint32_t flag, All_reads* R_INF, uint64_t *cnt) -{ - // if(qu && tu) { - // debug_extract_max_exact_sub(qid, qu, tu); - // } - uint64_t k, n; ma_hit_t *z; - for (k = n = 0; k < ov->length; k++) { - if(ov->list[k].is_match == flag) n++; - } - - if(n > paf->size) { - paf->size = n; - REALLOC(paf->buffer, paf->size); - } - - for (k = paf->length = 0; k < ov->length; k++) { - if(ov->list[k].is_match == flag) { - z = &(paf->buffer[paf->length++]); - - z->qns = ov->list[k].x_id; - z->qns = z->qns << 32; - z->tn = ov->list[k].y_id; - - z->qns = z->qns | (uint64_t)(ov->list[k].x_pos_s); - z->qe = ov->list[k].x_pos_e + 1; - z->ts = ov->list[k].y_pos_s; - z->te = ov->list[k].y_pos_e + 1; - - ///for overlap_list, the x_strand of all overlaps are 0, so the tmp.rev is the same as the y_strand - z->rev = ov->list[k].y_pos_strand; - - z->bl = Get_READ_LENGTH((*R_INF), ov->list[k].y_id); - z->ml = ov->list[k].strong; - z->no_l_indel = ov->list[k].without_large_indel; - z->el = ov->list[k].shared_seed; - - if(z->rev) { - z->ts = z->bl - ov->list[k].y_pos_e - 1; - z->te = z->bl - ov->list[k].y_pos_s; - } - - if(flag == 1) { - if(z->ml == 1) cnt[2]++; - if(z->ml == 0) cnt[3]++; - if(z->el == 1) cnt[4]++; - if(z->no_l_indel) cnt[5]++; - } - z->del = 0; - } - } - - if(flag == 1) cnt[0] += paf->length; - if(flag == 2) cnt[1] += paf->length; -} - -void debug_mm_exact_cigar(overlap_region_alloc* ol, uint32_t qid, UC_Read *qu, UC_Read *tu) -{ - int64_t on = ol->length, k, i, zwn, xk, yk; uint32_t cl, ck; ///bit_extz_t ez; - overlap_region *z; asg16_v ct; uint64_t wx[2], wy[2]; uint16_t c; - recover_UC_Read(qu, &R_INF, qid); - - for (i = 0; i < on; i++) { - z = &(ol->list[i]); zwn = z->w_list.n; - if(z->y_pos_strand) { - recover_UC_Read_RC(tu, &R_INF, z->y_id); - } else { - recover_UC_Read(tu, &R_INF, z->y_id); ///b->z.length - } - - // fprintf(stderr, "[M::%s] x_id::%u\ty_id::%u\tx::[%u, %u)\ty::[%u, %u)\tzwn::%ld\n", - // __func__, z->x_id, z->y_id, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, zwn); - // fprintf(stderr, "qstr(%lld)::%.*s\n", qu->length, (int32_t)(qu->length), qu->seq); - // fprintf(stderr, "tstr(%lld)::%.*s\n", tu->length, (int32_t)(tu->length), tu->seq); - - for (k = 0; k < zwn; k++) { - // set_bit_extz_t(ez, (*z), k); - // if(!cigar_check(tu->seq, qu->seq, &ez)) { - // fprintf(stderr, "\n[M::%s] x_id::%u, y_id::%u, x::[%u, %u), y::[%u, %u)\n", __func__, z->x_id, z->y_id, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); - // exit(1); - // } - // continue; - ct.a = z->w_list.c.a + z->w_list.a[k].cidx; - ct.n = ct.m = z->w_list.a[k].clen; ck = 0; - xk = z->w_list.a[k].x_start; yk = z->w_list.a[k].y_start; - while (ck < ct.n) { - wx[0] = xk; wy[0] = yk; - ck = pop_trace(&ct, ck, &c, &cl); - if(c != 2) xk += cl; - if(c != 3) yk += cl; - wx[1] = xk; wy[1] = yk; - if(c == 0) { - if(memcmp(qu->seq + wx[0], tu->seq + wy[0], wx[1] - wx[0])) { - fprintf(stderr, "\n-0-[M::%s]\teq::[%lu,\t%lu)\tet::[%lu,\t%lu)\t%c\n", __func__, wx[0], wx[1], wy[0], wy[1], "+-"[z->y_pos_strand]); - fprintf(stderr, "qstr(%u)::%.*s\n", z->x_id, (int32_t)(wx[1] - wx[0]), qu->seq + wx[0]); - fprintf(stderr, "tstr(%u)::%.*s\n", z->y_id, (int32_t)(wy[1] - wy[0]), tu->seq + wy[0]); - // exit(1); - } - // else { - // fprintf(stderr, "\n-1-[M::%s]\teq::[%lu,\t%lu)\tet::[%lu,\t%lu)\t%c\n", __func__, wx[0], wx[1], wy[0], wy[1], "+-"[z->y_pos_strand]); - // fprintf(stderr, "qstr(%u)::%.*s\n", z->x_id, (int32_t)(wx[1] - wx[0]), qu->seq + wx[0]); - // fprintf(stderr, "tstr(%u)::%.*s\n", z->y_id, (int32_t)(wy[1] - wy[0]), tu->seq + wy[0]); - // } - } - } - } - - } -} - -void check_well_cal(asg16_v *sc, asg64_v *idx, uint8_t *f_ec, uint8_t *abnormal, int64_t len, int64_t min_dp, ma_hit_t_alloc *in) -{ - uint64_t k, s, e; int64_t dp, old_dp, st = 0, ed; ma_hit_t *z; - - (*f_ec) = 1; (*abnormal) = 0; idx->n = 0; - for (k = 0; k < in->length; k++) { - z = &(in->buffer[k]); - s = ((uint32_t)(z->qns)); e = z->qe; - kv_push(uint64_t, (*idx), (s<<1)); - kv_push(uint64_t, (*idx), (e<<1)|1); - } - - radix_sort_ec64(idx->a, idx->a + idx->n); - for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { - old_dp = dp; - ///if a[j] is qe - if (idx->a[k]&1) --dp; - else ++dp; - - ed = idx->a[k]>>1; - if(ed > st) { - if(old_dp < min_dp) (*f_ec) = 0; - if(old_dp == 0) { - if(st > 0 && ed < len) { - (*abnormal) = 1; - }else if((*abnormal)==0){ - (*abnormal) = 2; - } - } - } - - st = ed; - } - - - ed = len; old_dp = dp; - if(ed > st) { - if(old_dp < min_dp) (*f_ec) = 0; - if(old_dp == 0) { - if(st > 0 && ed < len) { - (*abnormal) = 1; - }else if((*abnormal) == 0){ - (*abnormal) = 2; - } - } - } - - if((*f_ec)) { - for (k = 0; (k < sc->n) && ((sc->a[k]>>14) == 0); k++); - if(k < sc->n) (*f_ec) = 0; - } -} - -inline uint64_t exact_ec_check(char *qstr, uint64_t ql, char *tstr, uint64_t tl, int64_t qs, int64_t qe, int64_t ts, int64_t te) -{ - if(qe - qs != te - ts) return 0; - if(memcmp(qstr + qs, tstr + ts, qe - qs) == 0) return 1; - return 0; -} - -void gen_hc_r_alin_ea(overlap_region_alloc* ol, Candidates_list *cl, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t wl, int64_t rid, int64_t khit, int64_t move_gap, asg16_v *buf, asg64_v *srt, ma_hit_t_alloc *in, uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max) -{ - if(ol->length <= 0) return; - - - // uint64_t k, l, i, s, m, mm_k, *ei, en, *oi, on, tid, trev, nec; int64_t sc, mm_sc, plus, minus; overlap_region *z, t; ma_hit_t *p; - uint64_t k, i, m, *ei, en, *oi, on, tid, trev, nec; overlap_region *z; ma_hit_t *p; - srt->n = 0; - for (k = 0; k < in->length; k++) { - if(in->buffer[k].el) { - m = in->buffer[k].tn; m <<= 1; m |= in->buffer[k].rev; - m <<= 32; m |= k; kv_push(uint64_t, (*srt), m); - } - } - - if(!(srt->n)) { - gen_hc_r_alin(ol, cl, rref, qu, tu, exz, aux_o, e_rate, wl, rid, khit, move_gap, buf, chem_drop, align_gap_rate, align_gap_max); - } else { - ///debug for memory - // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); - - kv_resize(uint64_t, *srt, (srt->n + ol->length)); - ei = srt->a; en = srt->n; oi = srt->a + srt->n; on = ol->length; - for (k = 0; k < on; k++) { - z = &(ol->list[k]); z->is_match = z->strong = z->without_large_indel = 0; - oi[k] = z->y_id; oi[k] <<= 1; oi[k] |= z->y_pos_strand; - oi[k] <<= 32; oi[k] |= k; - } - - radix_sort_ec64(ei, ei + en); radix_sort_ec64(oi, oi + on); - for (k = i = nec = 0; k < on; k++) { - z = &(ol->list[(uint32_t)oi[k]]); tid = z->y_id; trev = z->y_pos_strand; - for (; (i < en) && ((ei[i]>>32) < ((tid<<1)|trev)); i++); - if((i < en) && ((ei[i]>>32) == ((tid<<1)|trev))) { - p = &(in->buffer[(uint32_t)ei[i]]); - if((z->x_pos_s == ((uint32_t)p->qns)) && (z->x_pos_e + 1 == p->qe) && - (z->y_pos_s == p->ts) && (z->y_pos_e + 1 == p->te)) { - resize_UC_Read(tu, p->te - p->ts); recover_UC_Read_sub_region(tu->seq, p->ts, p->te - p->ts, trev, rref, tid); - if(exact_ec_check(qu->seq, qu->length, tu->seq, p->te - p->ts, ((uint32_t)p->qns), p->qe, 0, p->te - p->ts)) { - z->is_match = 1; z->shared_seed = z->non_homopolymer_errors;///for index - z->non_homopolymer_errors = 0; z->strong = z->without_large_indel = 0; - set_exact_exz(exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, exz); - nec++; - } - } - } - } - ///debug for memory - // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); - - if(on > nec) { - gen_hc_r_alin_nec(ol, cl, rref, qu, tu, exz, aux_o, e_rate, wl, rid, khit, move_gap, buf, chem_drop, align_gap_rate, align_gap_max); - } - - // fprintf(stderr, "[M::%s] srt->n::%u, nec::%lu, on::%lu\n", __func__, (uint32_t)srt->n, nec, on); - ///debug for memory - // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); - } - - /** - if(ol->length > 1) {///for duplicated chains - overlap_region_sort_y_id(ol->list, ol->length); - for (k = 1, l = m = 0; k <= ol->length; k++) { - if(k == ol->length || ol->list[k].y_id != ol->list[l].y_id) { - // fprintf(stderr, "\n[M::%s::tid->%u] n->%lu\n", __func__, ol->list[l].y_id, k - l); - mm_k = l; - if(k - l > 1) { - for (s = l, mm_sc = INT32_MIN, mm_k = ((uint64_t)-1); s < k; s++) { - z = &(ol->list[s]); - plus = z->x_pos_e + 1 - z->x_pos_s; minus = (z->non_homopolymer_errors) * 12; - sc = plus - minus; - if((sc > mm_sc) || ((sc == mm_sc) && ((ol->list[mm_k].x_pos_e+1-ol->list[mm_k].x_pos_s) < (z->x_pos_e+1-z->x_pos_s)))) { - mm_sc = sc; mm_k = s; - } - // fprintf(stderr, "[M::%s::%c] q::[%u, %u), t::[%u, %u), sc::%ld, err::%u, s::%lu\n", __func__, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, sc, z->non_homopolymer_errors, s); - } - } - // fprintf(stderr, "[M::%s::tid->%u] mm_k::%lu\n", __func__, ol->list[l].y_id, mm_k); - if(mm_k != ((uint64_t)-1)) { - if(mm_k != m) { - t = ol->list[mm_k]; - ol->list[mm_k] = ol->list[m]; - ol->list[m] = t; - } - m++; - } - l = k; - } - } - ol->length = m; - } - **/ -} - -void prt_ovlp_sam_0(char *cm, FILE *fp, char *ref_id, int32_t ref_id_n, char *qry_id, int32_t qry_id_n, char *qry_seq, uint64_t qry_seq_n, uint64_t rs, uint64_t re, uint64_t qs, uint64_t qe, uint64_t flag, uint64_t err0, bit_extz_t *ez) -{ - uint64_t ci = 0, err1 = 0; uint16_t c; uint32_t cl, cl0 = 0; char c0 = (char)-1; - fprintf(fp, "%.*s\t%lu\t%.*s\t%lu\t60\t", qry_id_n, qry_id, flag, ref_id_n, ref_id, rs + 1); - - if(qs) fprintf(fp, "%luS", qs); - while (ci < ez->cigar.n) { - ci = pop_trace(&(ez->cigar), ci, &c, &cl); - if(c0 == cm[c]) { - cl0 += cl; - } else { - if(c0 != ((char)-1)) { - fprintf(fp, "%u%c", cl0, c0); - } - cl0 = cl; c0 = cm[c]; - } - // fprintf(fp, "%u%c", cl, cm[c]); - if(c != 0) err1 += cl; - } - if(cl0) fprintf(fp, "%u%c", cl0, c0); - if(qry_seq_n > qe) fprintf(fp, "%luS", qry_seq_n - qe); - fprintf(fp, "\t*\t0\t0\t%.*s\t", (int32_t)qry_seq_n, qry_seq); - for (ci = 0; ci < qry_seq_n; ci++) fprintf(fp, "~"); - assert(err0 == err1); - fprintf(fp, "\tNM:i:%lu\n", err0); -} - - -void prt_ovlp_sam(overlap_region_alloc* ol, UC_Read* tu, char *ref_seq, int32_t ref_seq_n) -{ - int64_t on = ol->length, k, i, zwn; overlap_region *z; bit_extz_t ez; - char *qry = NULL, *ref = Get_NAME(R_INF, ol->list[0].x_id); - uint64_t qry_n = 0, ref_n = Get_NAME_LENGTH(R_INF, ol->list[0].x_id), qid, rev; - char cm[4]; cm[0] = 'M'; cm[1] = 'M'; cm[2] = 'I'; cm[3] = 'D'; - FILE *fp = fopen("aln.sam", "w"); - fprintf(fp, "@HD\tVN:1.6\tSO:unknown\n"); - fprintf(fp, "@SQ\tSN:%.*s\tLN:%lu\n", (int32_t)ref_n, ref, Get_READ_LENGTH(R_INF, ol->list[0].x_id)); - for (k = 0; k < on; k++) { - z = &(ol->list[k]); zwn = z->w_list.n; - if(!zwn) continue; - qid = ol->list[k].y_id; - if(z->y_pos_strand) { - recover_UC_Read_RC(tu, &R_INF, qid); rev = 16; - } else { - recover_UC_Read(tu, &R_INF, qid); rev = 0; - } - for (i = 0; i < zwn; i++) { - if(is_ualn_win(z->w_list.a[i])) continue; - qry_n = Get_NAME_LENGTH(R_INF, qid); - qry = Get_NAME(R_INF, qid); - set_bit_extz_t(ez, (*z), i); - - prt_ovlp_sam_0(cm, fp, ref, ref_n, qry, qry_n, tu->seq, tu->length, z->w_list.a[i].x_start, z->w_list.a[i].x_end + 1, z->w_list.a[i].y_start, z->w_list.a[i].y_end + 1, rev, z->w_list.a[i].error, &ez); - } - } - fclose(fp); - - fp = fopen("ref.fa", "w"); - fprintf(fp, ">%.*s\n", (int32_t)ref_n, ref); - fprintf(fp, "%.*s\n", ref_seq_n, ref_seq); - fclose(fp); -} - -void stderr_phase_ovlp(overlap_region_alloc* ol) -{ - int64_t on = ol->length, k; overlap_region *z; - if(!on) return; - uint64_t qry_n = 0, rid, ref_n, qid; - rid = ol->list[0].x_id; ref_n = Get_NAME_LENGTH(R_INF, rid); - - for (k = 0; k < on; k++) { - z = &(ol->list[k]); qid = ol->list[k].y_id; - qry_n = Get_NAME_LENGTH(R_INF, qid); - - fprintf(stderr, "%.*s(qid::%lu)\tql::%lu\tq::[%u,\t%u)\t%c\t%.*s(tid::%lu)\ttl::%lu\tt::[%u,\t%u)\ttrans::%u\n", - (int32_t)Get_NAME_LENGTH(R_INF, rid), Get_NAME(R_INF, rid), rid, ref_n, z->x_pos_s, z->x_pos_e + 1, "+-"[z->y_pos_strand], - (int32_t)Get_NAME_LENGTH(R_INF, qid), Get_NAME(R_INF, qid), qid, qry_n, z->y_pos_s, z->y_pos_e + 1, ((z->is_match==1)?(0):(1))); - } -} - -void dedup_chains(overlap_region_alloc* ol) -{ - uint64_t k, l, s, m, mm_k, mm_m, sf; int64_t sc, mm_sc, plus, minus; overlap_region *z, t; - if(ol->length > 1) {///for duplicated chains - overlap_region_sort_y_id(ol->list, ol->length); - for (k = 1, l = m = 0; k <= ol->length; k++) { - if(k == ol->length || ol->list[k].y_id != ol->list[l].y_id) { - // fprintf(stderr, "\n[M::%s::tid->%u] n->%lu\n", __func__, ol->list[l].y_id, k - l); - mm_k = l; - if(k - l > 1) { - for (s = l, mm_sc = INT32_MIN, mm_k = ((uint64_t)-1), mm_m = 3; s < k; s++) { - z = &(ol->list[s]); - plus = z->x_pos_e + 1 - z->x_pos_s; minus = (z->non_homopolymer_errors) * 12; - sc = plus - minus; - - sf = 0; - if(z->is_match < mm_m) { - sf = 1; - } else if(z->is_match == mm_m) { - if(sc > mm_sc) { - sf = 1; - } else if((sc == mm_sc) && ((z->x_pos_e+1-z->x_pos_s) > (ol->list[mm_k].x_pos_e+1-ol->list[mm_k].x_pos_s))) { - sf = 1; - } - } - if(sf) { - mm_sc = sc; mm_k = s; mm_m = z->is_match; - } - - // fprintf(stderr, "[M::%s::%c] q::[%u, %u), t::[%u, %u), sc::%ld, err::%u, mm::%u, s::%lu\n", __func__, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, sc, z->non_homopolymer_errors, z->is_match, s); - } - } - // fprintf(stderr, "[M::%s::tid->%u] mm_k::%lu\n", __func__, ol->list[l].y_id, mm_k); - if(mm_k != ((uint64_t)-1)) { - if(mm_k != m) { - t = ol->list[mm_k]; - ol->list[mm_k] = ol->list[m]; - ol->list[m] = t; - } - m++; - } - l = k; - } - } - ol->length = m; - } -} - -void debug_retrive_bqual(asg8_v *vq, asg8_v *vt, uint64_t id, uint64_t rn) -{ - uint64_t k, n, z[2], s, e, rev; - retrive_bqual(vq, NULL, id, -1, -1, 0, sc_bn); n = vq->n; - retrive_bqual(vt, NULL, id, -1, -1, 1, sc_bn); - assert(vq->n == vt->n); - for (k = 0; k < vq->n && vq->a[k] == vt->a[vt->n - k - 1]; k++); - // if((k == vq->n)) { - // fprintf(stderr, "[M::%s] id::%lu, k::%lu, n::%lu\n", __func__, id, k, ((uint64_t)vq->n)); - // } - assert(k == vq->n); - - // if(id == 0) { - // s = 21519; e = 22332; rev = 0; - // retrive_bqual(vt, NULL, id, s, e, rev, sc_bn); - // if(memcmp(vq->a + s, vt->a, e - s)) { - // fprintf(stderr, "+[M::%s] id::%lu, t::[%lu, %lu), rev::%lu\n", __func__, id, s, e, rev); - // exit(1); - // } - - // } - // return; - - for (k = 0, rev = 0; k < rn; k++) { - z[0] = rand()%(n + 1); - z[1] = rand()%(n + 1); - if(z[0] == z[1]) continue; - s = MIN(z[0], z[1]); e = MAX(z[0], z[1]); - retrive_bqual(vt, NULL, id, s, e, rev, sc_bn); - if(memcmp(vq->a + s, vt->a, e - s)) { - fprintf(stderr, "[M::%s] id::%lu, t::[%lu, %lu), rev::%lu\n", __func__, id, s, e, rev); - exit(1); - } - } - - - retrive_bqual(vq, NULL, id, -1, -1, 1, sc_bn); - for (k = 0, rev = 1; k < rn; k++) { - z[0] = rand()%(n + 1); - z[1] = rand()%(n + 1); - if(z[0] == z[1]) continue; - s = MIN(z[0], z[1]); e = MAX(z[0], z[1]); - retrive_bqual(vt, NULL, id, s, e, rev, sc_bn); - if(memcmp(vq->a + s, vt->a, e - s)) { - fprintf(stderr, "[M::%s] id::%lu, t::[%lu, %lu), rev::%lu\n", __func__, id, s, e, rev); - exit(1); - } - } -} - -uint32_t is_uncorrected_read(overlap_region_alloc* ov, asg64_v *idx, int64_t len, int64_t min_len) -{ - uint64_t k, s, e; int64_t dp, old_dp, st = 0, ed; - for (k = idx->n = 0; k < ov->length; k++) { - s = ov->list[k].x_pos_s; e = ov->list[k].x_pos_e + 1; - kv_push(uint64_t, (*idx), (s<<1)); - kv_push(uint64_t, (*idx), (e<<1)|1); - } - - radix_sort_ec64(idx->a, idx->a + idx->n); - for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { - old_dp = dp; - ///if a[j] is qe - if (idx->a[k]&1) --dp; - else ++dp; - - ed = idx->a[k]>>1; - if(ed > st) { - if(old_dp == 0) { - if((ed - st) >= min_len) return 1; - } - } - st = ed; - } - - - ed = len; old_dp = dp; - if(ed > st) { - if(old_dp == 0) { - if((ed - st) >= min_len) return 1; - if((ed - st) >= len) return 1; - } - } - - return 0; -} - -uint32_t is_chemical_r_qual(overlap_region_alloc *ov, asg64_v *idx, int64_t len, int64_t cov, int64_t frank_len, asg8_v *qv, uint64_t rid) -{ - uint64_t k, s, e; int64_t dp, old_dp, st = 0, ed, s0, s1, e0, e1, rr, qk; - if((frank_len) > (len *0.01)) frank_len = len *0.01; - for (k = idx->n = 0; k < ov->length; k++) { - s = ov->list[k].x_pos_s; e = ov->list[k].x_pos_e + 1; - kv_push(uint64_t, (*idx), (s<<1)); - kv_push(uint64_t, (*idx), (e<<1)|1); - // fprintf(stderr, "[M::%s]\trid::%lu\ts::%lu\te::%lu\n", __func__, rid, s, e); - } - - radix_sort_ec64(idx->a, idx->a + idx->n); s0 = s1 = e0 = e1 = rr = -1; - for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { - old_dp = dp; - ///if a[j] is qe - if (idx->a[k]&1) --dp; - else ++dp; - - ed = idx->a[k]>>1; - if(ed > st) { - if(old_dp <= cov) { - rr = 1; - } else { - if(s0 < 0) { - s0 = st; s1 = ed; - } - e0 = st; e1 = ed; - } - } - st = ed; - } - - - ed = len; old_dp = dp; - if(ed > st) { - if(old_dp <= cov) { - rr = 1; - } else { - if(s0 < 0) { - s0 = st; s1 = ed; - } - e0 = st; e1 = ed; - } - } - - - if((s0 != e0) && (s1 != e1) && (s0 <= frank_len) && ((len - e1) <= frank_len) && (rr > 0)) { - for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { - old_dp = dp; - ///if a[j] is qe - if (idx->a[k]&1) --dp; - else ++dp; - - ed = idx->a[k]>>1; - if(ed > st) { - if((old_dp <= cov) && (st >= s0) && (ed <= e1)) { - retrive_bqual(qv, NULL, rid, -1, -1, 0, sc_bn); - fprintf(stderr, "[M::%s]\tlf::[%ld,%ld)\trt::[%ld,%ld)\tmd::[%ld,%ld)\tcov::%ld\n", __func__, s0, s1, e0, e1, st, ed, old_dp); - for (qk = st; qk < ed; qk++) fprintf(stderr, "%u", qv->a[qk]); - fprintf(stderr, "\n"); - return 1; - } - } - st = ed; - } - - - ed = len; old_dp = dp; - if(ed > st) { - if((old_dp <= cov) && (st >= s0) && (ed <= e1)) { - retrive_bqual(qv, NULL, rid, -1, -1, 0, sc_bn); - fprintf(stderr, "[M::%s]\tlf::[%ld,%ld)\trt::[%ld,%ld)\tmd::[%ld,%ld)\tcov::%ld\n", __func__, s0, s1, e0, e1, st, ed, old_dp); - for (qk = st; qk < ed; qk++) fprintf(stderr, "%u", qv->a[qk]); - fprintf(stderr, "\n"); - return 1; - } - } - } - - - // for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { - // old_dp = dp; - // ///if a[j] is qe - // if (idx->a[k]&1) --dp; - // else ++dp; - - // ed = idx->a[k]>>1; - // if(ed > st) { - // if((old_dp <= cov)) { - // retrive_bqual(qv, NULL, rid, -1, -1, 0, sc_bn); - // fprintf(stderr, "[M::%s]\tlf::[%ld,%ld)\trt::[%ld,%ld)\tmd::[%ld,%ld)\tcov::%ld\n", __func__, s0, s1, e0, e1, st, ed, old_dp); - // for (qk = st; qk < ed; qk++) fprintf(stderr, "%u", qv->a[qk]); - // fprintf(stderr, "\n"); - // return 1; - // } - // } - // st = ed; - // } - - - // ed = len; old_dp = dp; - // if(ed > st) { - // if((old_dp <= cov)) { - // retrive_bqual(qv, NULL, rid, -1, -1, 0, sc_bn); - // fprintf(stderr, "[M::%s]\tlf::[%ld,%ld)\trt::[%ld,%ld)\tmd::[%ld,%ld)\tcov::%ld\n", __func__, s0, s1, e0, e1, st, ed, old_dp); - // for (qk = st; qk < ed; qk++) fprintf(stderr, "%u", qv->a[qk]); - // fprintf(stderr, "\n"); - // return 1; - // } - // } - - return 0; -} - - -static void worker_hap_ec(void *data, long i, int tid) -{ - ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); - uint32_t high_occ = asm_opt.hom_cov * (2.0 - HA_KMER_GOOD_RATIO); - uint32_t low_occ = asm_opt.hom_cov * HA_KMER_GOOD_RATIO; - overlap_region *aux_o = NULL; asg64_v buf0; uint32_t qlen = 0; - - /** - if((i != 1129685) && (i != 1137865) && (i != 1137917) && (i != 1140647) && (i != 1144740) && (i != 1148936) && (i != 1149134) && (i != 1151224) && (i != 1151386) && (i != 1152960) && (i != 1154846) && (i != 1154881) && (i != 1155112) && - (i != 1156823) && (i != 1157099) && (i != 1157393) && (i != 1158300) && (i != 1158368) && (i != 1160411) && (i != 1160659) && (i != 1161458) && (i != 1163595) && (i != 1164084) && (i != 1164230) && (i != 1165050) && (i != 1168249) && - (i != 1168304) && (i != 1168514) && (i != 1170447) && (i != 1171377) && (i != 1171387) && (i != 1172376) && (i != 1173566) && (i != 1174275) && (i != 1174434) && (i != 1174511) && (i != 1174860) && (i != 1175306) && (i != 1175314) && - (i != 1177101) && (i != 1178196) && (i != 1178470) && (i != 1179327) && (i != 1179626) && (i != 1180357) && (i != 1181347) && (i != 1181422) && (i != 1181725) && (i != 1183135) && (i != 1183734) && (i != 1185569) && (i != 1185604) && - (i != 1186192) && (i != 1188441) && (i != 1188487) && (i != 1189865) && (i != 1189943) && (i != 1192819) && (i != 1193133) && (i != 1196908) && (i != 1197590) && (i != 1200549) && (i != 1200757) && (i != 1205500)) return; - - fprintf(stderr, "%ld\t+++\n", i); - **/ - // if(i < 1100000 || i > 1400000) return; - // if(i % 100000 == 0) fprintf(stderr, "-a-[M::%s-beg] rid->%ld\n", __func__, i); - // if (memcmp("c42804f3-0e13-43a0-8a71-b91b40accf9a", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { - // if (memcmp("b2e68ecf-381a-439c-b676-c1e6831d6acf", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { - // if (memcmp("e3f3f43a-e200-4cac-8acd-3f85428f3811", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { - // if (memcmp("b4bd5ccb-2fe3-447e-b7b8-7a7b26fa0f7a", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { - // fprintf(stderr, "-a-[M::%s-beg] rid->%ld\n", __func__, i); - // } else { - // return; - // } - - // if(i != 4080965) return; - // if(i != 4325346) return; - // if(i != 4378784) return; - ///for debug indel - // if(i != 1238) return; - // if(i != 2410) return; - // if(i != 4198005) return; - // if(i != 682) return; - - // debug_retrive_bqual(D, &b->v8t, i, 256); return; - - recover_UC_Read(&b->self_read, &R_INF, i); qlen = b->self_read.length; - - h_ec_lchain(b->ab, i, b->self_read.seq, b->self_read.length, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, ((asm_opt.is_ont)?(0.05):(0.02)), asm_opt.max_n_chain, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 3, 0.7, 2, 32, COV_W);///ONT high error - - // b->num_read_base += b->olist.length; - b->cnt[0] += b->self_read.length; - - aux_o = fetch_aux_ovlp(&b->olist);///must be here - - // stderr_phase_ovlp(&b->olist); - - ///debug for memory - // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); - ///mz1_ha_sketch(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); - // if((asm_opt.is_ont) && (b->olist.length)) get_mz1(qu->seq, qu->length, RES_W, RES_K, 0, !(asm_opt.flag & HA_F_NO_HPC), b->ab, NULL, NULL, asm_opt.mz_sample_dist, NULL, NULL, NULL, -1, asm_opt.dp_min_len, -1, &(b->sp), asm_opt.mz_rewin, 0, NULL, 0); - - gen_hc_r_alin_ea(&b->olist, &b->clist, &R_INF, &b->self_read, &b->ovlp_read, &b->exz, aux_o, asm_opt.max_ov_diff_ec, (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), i, E_KHIT/**asm_opt.k_mer_length**/, 1, &b->v16, &b->v64, &(R_INF.paf[i]), asm_opt.is_ont, (asm_opt.is_ont)?(0.006):(-1), (asm_opt.is_ont)?(64):(-1)); - ///for debug indel - // prt_ovlp_sam(&b->olist, &b->ovlp_read, b->self_read.seq, b->self_read.length); - - - // fprintf(stderr, "\n[M::%s] rid::%ld\t%.*s\tlen::%lld\tocc::%lu\n", __func__, i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i), b->self_read.length, b->olist.length); - - // fprintf(stderr, "[M::%s] rid::%ld\n", __func__, i); - // debug_mm_exact_cigar(&b->olist, i, &b->self_read, &b->ovlp_read); - - // b->num_correct_base += b->olist.length; - - copy_asg_arr(buf0, b->sp); - rphase_hc(&b->olist, &R_INF, &b->hap, &b->self_read, &b->ovlp_read, &b->pidx, &b->v64, &buf0, 0, WINDOW_MAX_SIZE, b->self_read.length, 1/**, 0**/, i, (asm_opt.is_ont)?HPC_PL:0, asm_opt.is_ont, ((asm_opt.is_ont)?&(b->clist.chainDP):NULL), ((asm_opt.is_sc)?&(b->v8q):NULL), ((asm_opt.is_sc)?&(b->v8t):NULL), (asm_opt.is_ont)?1:0); - copy_asg_arr(b->sp, buf0); - ///for debug indel - // stderr_phase_ovlp(&b->olist); - - dedup_chains(&b->olist); - - copy_asg_arr(buf0, b->sp); - b->cnt[1] += wcns_gen(&b->olist, &R_INF, &b->self_read, &b->ovlp_read, &b->exz, &b->pidx, &b->v64, &buf0, 0, 512, b->self_read.length, 3, 0.500001, aux_o, &b->v32, &b->cns, 256, i); - copy_asg_arr(b->sp, buf0); - - push_nec_re(aux_o, &(scc.a[i])); - push_nec_re(aux_o, &(scb.a[i])); - - // if((asm_opt.is_ont) && is_chemical_r_qual(&b->olist, &b->v64, qlen, 1, 16, &(b->v8q), i)/**(is_uncorrected_read(&b->olist, &b->v64, qlen, 1600))**/) { - // // b->olist.length = 0; - // fprintf(stderr, "[M::%s] rid::%ld\t%.*s\n\n", __func__, i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); - // } - - push_ne_ovlp(&(R_INF.paf[i]), &b->olist, 1, &R_INF, &(scc.a[i])/**, i, &b->self_read, &b->ovlp_read**/); - push_ne_ovlp(&(R_INF.reverse_paf[i]), &b->olist, 2, &R_INF, NULL/**, i, NULL, NULL**/); - - - check_well_cal(&(scc.a[i]), &b->v64, &(R_INF.paf[i].is_fully_corrected), &(R_INF.paf[i].is_abnormal), qlen, (MIN_COVERAGE_THRESHOLD*2), &(R_INF.paf[i])); - R_INF.trio_flag[i] = AMBIGU; - - // uint32_t k; - // for (k = 0; k < b->olist.length; k++) { - // if(b->olist.list[k].is_match == 1) b->num_recorrect_base++; - // } - ///for debug indel - // exit(1); - - - - // prt_chain(&b->olist); - - // ul_map_lchain(b->abl, (uint32_t)-1, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->clist, s->opt->bw_thres, - // s->opt->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2/**0.75**/, 2, 3); - - /** - int fully_cov, abnormal; - // if(i != 12578) return; - // fprintf(stderr, "[M::%s-beg] rid->%ld\n", __func__, i); - // if (memcmp("7897e875-76e5-42c8-bc37-94b370c4cc8d", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { - // fprintf(stderr, "[M::%s-beg] rid->%ld\n", __func__, i); - // } else { - // return; - // } - - ha_get_candidates_interface(b->ab, i, &b->self_read, &b->olist, &b->olist_hp, &b->clist, - 0.02, asm_opt.max_n_chain, 1, NULL, &b->r_buf, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), &(b->tmp_region), NULL, &(b->sp)); - - clear_Cigar_record(&b->cigar1); - clear_Round2_alignment(&b->round2); - - correct_overlap(&b->olist, &R_INF, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, - &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 1, &fully_cov, &abnormal); - - b->num_read_base += b->self_read.length; - b->num_correct_base += b->correct.corrected_base; - b->num_recorrect_base += b->round2.dumy.corrected_base; - - push_cigar(R_INF.cigars, i, &b->cigar1); - push_cigar(R_INF.second_round_cigar, i, &b->round2.cigar); - - R_INF.paf[i].is_fully_corrected = 0; - if (fully_cov) { - if (get_cigar_errors(&b->cigar1) == 0 && get_cigar_errors(&b->round2.cigar) == 0) - R_INF.paf[i].is_fully_corrected = 1; - } - R_INF.paf[i].is_abnormal = abnormal; - - R_INF.trio_flag[i] = AMBIGU; - - ///need to be fixed in r305 - // if(ha_idx_hp == NULL) - // { - // R_INF.trio_flag[i] += collect_hp_regions(&b->olist, &R_INF, &(b->k_flag), RESEED_HP_RATE, Get_READ_LENGTH(R_INF, i), NULL); - // } - - if (R_INF.trio_flag[i] != AMBIGU || b->save_ov) { - int is_rev = (asm_opt.number_of_round % 2 == 0); - push_overlaps(&(R_INF.paf[i]), &b->olist, 1, &R_INF, is_rev); - push_overlaps(&(R_INF.reverse_paf[i]), &b->olist, 2, &R_INF, is_rev); - } - - if(het_cnt) het_cnt[i] = get_het_cnt(&b->hap); - // fprintf(stderr, "[M::%s-end] rid->%ld\n", __func__, i); - **/ - // exit(1); - refresh_ec_ovec_buf_t0(b, REFRESH_N); - - /** - fprintf(stderr, "%ld\t---\n", i); - **/ -} - -static void worker_hap_ec_dbg_paf(void *data, long i, int tid) -{ - ec_ovec_buf_t0 *b = &(((cal_ec_r_dbg_step_t*)data)->buf->a[tid]); - r_dbg_step_res_t *rr = &(((cal_ec_r_dbg_step_t*)data)->res[tid]); - uint32_t high_occ = asm_opt.hom_cov * (2.0 - HA_KMER_GOOD_RATIO); - uint32_t low_occ = asm_opt.hom_cov * HA_KMER_GOOD_RATIO; - overlap_region *aux_o = NULL; i += ((cal_ec_r_dbg_step_t*)data)->si; - - // debug_retrive_bqual(D, &b->v8t, i, 256); return; - - recover_UC_Read(&b->self_read, &R_INF, i); - - h_ec_lchain(b->ab, i, b->self_read.seq, b->self_read.length, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, ((asm_opt.is_ont)?(0.05):(0.02)), asm_opt.max_n_chain, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 3, 0.7, 2, 32, COV_W);///ONT high error - - aux_o = fetch_aux_ovlp(&b->olist);///must be here - - // stderr_phase_ovlp(&b->olist); - gen_hc_r_alin_ea(&b->olist, &b->clist, &R_INF, &b->self_read, &b->ovlp_read, &b->exz, aux_o, asm_opt.max_ov_diff_ec, (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), i, E_KHIT, 1, &b->v16, &b->v64, &(R_INF.paf[i]), 0, -1, -1); - - uint32_t k, m, tl; overlap_region *z; bit_extz_t ez; ma_hit_t *t; - for (k = 0; k < b->olist.length; k++) { - z = &(b->olist.list[k]); - if(!(z->w_list.n)) continue; - - tl = Get_READ_LENGTH((R_INF), z->y_id); - for (m = 0; m < z->w_list.n; m++) { - if(is_ualn_win(z->w_list.a[m])) continue; - set_bit_extz_t(ez, (*z), m); - kv_pushp(ma_hit_t, *rr, &t); - - t->qns = z->x_id; t->qns = t->qns << 32; - t->tn = z->y_id; - - t->qns = t->qns | (uint64_t)(z->w_list.a[m].x_start); - t->qe = z->w_list.a[m].x_end + 1; - - t->ts = z->w_list.a[m].y_start; - t->te = z->w_list.a[m].y_end + 1; - - t->rev = z->y_pos_strand; - - t->bl = rr->ec.n; - kv_resize(uint16_t, rr->ec, rr->ec.n + ez.cigar.n); - memcpy(rr->ec.a + rr->ec.n, ez.cigar.a, ez.cigar.n * sizeof((*(rr->ec.a)))); - rr->ec.n += ez.cigar.n; - t->cc = rr->ec.n - t->bl; - - if(t->rev) { - t->ts = tl - z->w_list.a[m].y_end - 1; - t->te = tl - z->w_list.a[m].y_start; - } - } - } -} - -uint32_t adjust_exact_match(asg16_v *in, int64_t xs0, int64_t xe0, int64_t ys0, int64_t ye0, uint64_t *rxs, uint64_t *rxe, uint64_t *rys, uint64_t *rye, uint32_t rev) -{ - *rxs = *rxe = *rys = *rye = 0; - if((xe0 <= xs0) || (ye0 <= ys0)) return 0; - int64_t xk, yk, ck, cn = in->n, wx[2], wy[2], os, oe; uint16_t op, bq, bt; uint32_t cl; uint64_t ovlp; - xk = yk = 0; - - // fprintf(stderr, "[M::%s]\tx0::[%ld,%ld)\ty0::[%ld,%ld)\trev::%u\n", __func__, xs0, xe0, ys0, ye0, rev); - - if(!rev) { - ck = 0; - while (ck < cn && xk < xe0) { - wx[0] = xk; wy[0] = yk; - // ck = pop_trace_bp(in, ck, &op, &b, &cl); - ck = pop_trace_bp_f(in, ck, &op, &bq, &bt, &cl); - if(op != 2) xk += cl; - if(op != 3) yk += cl; - wx[1] = xk; wy[1] = yk; - // fprintf(stderr, "[M::%s]\told::[%ld,%ld]\tnew::[%ld,%ld]\t%u%c\n", __func__, wx[0], wx[1], wy[0], wy[1], cl, "MSID"[op]); - if(op == 0) { - os = MAX(xs0, wx[0]); oe = MIN(xe0, wx[1]); - ovlp = ((oe>os)? (oe-os):0); - if((ovlp > 0) && (ovlp > (*rxe) - (*rxs))) { - // fprintf(stderr, "[M::%s]\to::[%ld,%ld)\n", __func__, os, oe); - (*rxs) = wy[0] + os - wx[0]; - (*rxe) = wy[0] + oe - wx[0]; - - (*rys) = ys0 + os - xs0; - (*rye) = ys0 + oe - xs0; - } - } - // if((op == 0) && (wx[0] <= s) && (wx[1] >= e)) { - // (*rs) = wy[0] + s - wx[0]; - // (*re) = wy[0] + e - wx[0]; - // } - } - } else { - ck = cn - 1; - while (ck >= 0 && xk < xe0) { - wx[0] = xk; wy[0] = yk; - // ck = pop_trace_bp_rev(in, ck, &op, &b, &cl); - ck = pop_trace_bp_rev_f(in, ck, &op, &bq, &bt, &cl); - if(op != 2) xk += cl; - if(op != 3) yk += cl; - wx[1] = xk; wy[1] = yk; - if(op == 0) { - os = MAX(xs0, wx[0]); oe = MIN(xe0, wx[1]); - ovlp = ((oe>os)? (oe-os):0); - if((ovlp > 0) && (ovlp > (*rxe) - (*rxs))) { - (*rxs) = wy[0] + os - wx[0]; - (*rxe) = wy[0] + oe - wx[0]; - - (*rys) = ys0 + os - xs0; - (*rye) = ys0 + oe - xs0; - } - } - // if((op == 0) && (wx[0] <= s) && (wx[1] >= e)) { - // (*rs) = wy[0] + s - wx[0]; - // (*re) = wy[0] + e - wx[0]; - // } - } - } - - - return (*rxe) - (*rxs); -} - -uint32_t quick_exact_match(ma_hit_t *z, All_reads *rref, UC_Read* qu, UC_Read* tu, cc_v *sc) -{ - uint64_t rts, rte, rqs, rqe, f = 0; int64_t ql, tl, qr, tr, qs, qe, ts, te; - - // fprintf(stderr, "-0-[M::%s]\tf::%lu\n", __func__, f); - if(adjust_exact_match(&(sc->a[z->tn]), z->ts, z->te, ((uint32_t)(z->qns)), z->qe, &rts, &rte, &rqs, &rqe, z->rev)) { - z->ts = rts; z->te = rte; f = 1; - z->qns >>= 32; z->qns <<= 32; z->qns |= ((uint64_t)(rqs)); z->qe = rqe; - - ///debug - // qs = rqs; qe = rqe; ts = rts; te = rte; - // resize_UC_Read(tu, te - ts); - // recover_UC_Read_sub_region(tu->seq, ts, te - ts, z->rev, rref, z->tn); - - // fprintf(stderr, "[M::%s]\trq::[%lu,%lu)\trt::[%lu,%lu)\n", __func__, rqs, rqe, rts, rte); - // fprintf(stderr, "-0-[M::%s] qstr::%.*s\n", __func__, ((int)(qe - qs)), qu->seq + qs); - // fprintf(stderr, "-0-[M::%s] tstr::%.*s\n", __func__, ((int)(te - ts)), tu->seq); - - // if(memcmp(qu->seq + qs, tu->seq, qe - qs) == 0) { - // fprintf(stderr, "-0-[M::%s]\tsb\n", __func__); - // } else { - // fprintf(stderr, "-1-[M::%s]\tsa\n", __func__); - // } - } - // fprintf(stderr, "-1-[M::%s]\tf::%lu\n", __func__, f); - ql = qu->length; tl = Get_READ_LENGTH((*rref), z->tn); - qs = ((uint32_t)(z->qns)); qe = z->qe; ts = z->ts; te = z->te; - if(qs >= ql) qs = ql; if(qe > ql) qe = ql; if(qe <= qs) f = 0; - // fprintf(stderr, "-2-[M::%s]\tf::%lu\n", __func__, f); - if(ts >= tl) ts = tl; if(te > tl) te = tl; if(te <= ts) f = 0; - // fprintf(stderr, "-3-[M::%s]\tf::%lu\n", __func__, f); - if((qe - qs) != (te - ts)) f = 0; - // fprintf(stderr, "-4-[M::%s]\tf::%lu\n", __func__, f); - - if(qs <= ts) { - ts -= qs; qs = 0; - } else { - qs -= ts; ts = 0; - } - - - qr = ql - qe; tr = tl - te; - if(qr <= tr) { - qe = ql; te += qr; - } else { - te = tl; qe += tr; - } - - // fprintf(stderr, "-5-[M::%s]\tzq::[%ld,\t%ld)\tzt::[%ld,\t%ld)\teq::[%u,\t%u)\tet::[%u,\t%u)\tql::%ld\ttl::%ld\tf::%lu\n", - // __func__, qs, qe, ts, te, ((uint32_t)(z->qns)), z->qe, z->ts, z->te, ql, tl, f); - - z->qns >>= 32; z->qns <<= 32; z->qns |= ((uint64_t)(qs)); z->qe = qe; - z->ts = ts; z->te = te; - - if((f) && ((te - ts) == (qe - qs)) && (qe > qs)) { - resize_UC_Read(tu, te - ts); - recover_UC_Read_sub_region(tu->seq, ts, te - ts, z->rev, rref, z->tn); - - // fprintf(stderr, "[M::%s] qstr::%.*s\n", __func__, ((int)(qe - qs)), qu->seq + qs); - // fprintf(stderr, "[M::%s] tstr::%.*s\n", __func__, ((int)(te - ts)), tu->seq); - - if(memcmp(qu->seq + qs, tu->seq, qe - qs) == 0) return 1; - } - - return 0; -} - -uint64_t cal_cov_re(asg64_v *idx, int64_t *k, uint64_t s, uint64_t e) -{ - uint64_t *a = idx->a, ws, we, cn, os, oe, ovlp, tot = 0; int64_t n = idx->n; - if(n <= 0) return 0; - if((*k) >= n) (*k) = 0; - while (((*k) > 0) && (((uint32_t)a[*k]) > s)) (*k) -= 2; - if((*k) < 0) (*k) = 0; - - while (((*k) < n) && ((a[*k]>>32) < e)) { - ws = (a[*k]>>32); we = ((uint32_t)a[*k]); cn = a[(*k) + 1]; - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - tot += (ovlp*cn); - (*k) += 2; - } - - return tot; -} - -uint64_t gen_hap_dc_cov(asg64_v *be, asg64_v *ba, ma_hit_t_alloc *paf, All_reads *rref, uint64_t wl, int64_t occ_exact, double occ_exact_rate, UC_Read* qu, UC_Read* tu, cc_v *sc, uint64_t rid) -{ - ma_hit_t *z; be->n = ba->n = 0; uint64_t k, s, e, vn, m; asg64_v *v = NULL; - int64_t dp, old_dp, st = 0, ed, ql = qu->length, qs, qe, ff; - for (k = 0; k < paf->length; k++) { - z = &(paf->buffer[k]); - - // if(rid == 16) { - // fprintf(stderr, "[M::%s]\tqn::%u::%.*s\ttn::%u::%.*s\t%c\tq::[%u,%u)\tq::[%u,%u)\tel::%u\n", __func__, - // (uint32_t)(z->qns>>32), (int)Get_NAME_LENGTH(R_INF, (uint32_t)(z->qns>>32)), Get_NAME(R_INF, (uint32_t)(z->qns>>32)), z->tn, (int)Get_NAME_LENGTH(R_INF, z->tn), Get_NAME(R_INF, z->tn), "+-"[z->rev], - // (uint32_t)z->qns, z->qe, z->ts, z->te, z->el); - // } - - if((z->el) && (quick_exact_match(z, rref, qu, tu, sc))) { - s = ((uint32_t)(z->qns)); e = z->qe; - kv_push(uint64_t, (*be), (s<<1)); - kv_push(uint64_t, (*be), (e<<1)|1); - z->el = 1; - // fprintf(stderr, "-gmm-[M::%s]\tqn::%u::%.*s\ttn::%u::%.*s\t%c\tq::[%u,%u)\tq::[%u,%u)\n", __func__, - // (uint32_t)(z->qns>>32), (int)Get_NAME_LENGTH(R_INF, (uint32_t)(z->qns>>32)), Get_NAME(R_INF, (uint32_t)(z->qns>>32)), z->tn, (int)Get_NAME_LENGTH(R_INF, z->tn), Get_NAME(R_INF, z->tn), "+-"[z->rev], - // (uint32_t)z->qns, z->qe, z->ts, z->te); - } else { - s = ((uint32_t)(z->qns)); e = z->qe; - kv_push(uint64_t, (*ba), (s<<1)); - kv_push(uint64_t, (*ba), (e<<1)|1); - z->el = 0; - // fprintf(stderr, "-gum-[M::%s]\tqn::%u::%.*s\ttn::%u::%.*s\t%c\tq::[%u,%u)\tq::[%u,%u)\n", __func__, - // (uint32_t)(z->qns>>32), (int)Get_NAME_LENGTH(R_INF, (uint32_t)(z->qns>>32)), Get_NAME(R_INF, (uint32_t)(z->qns>>32)), z->tn, (int)Get_NAME_LENGTH(R_INF, z->tn), Get_NAME(R_INF, z->tn), "+-"[z->rev], - // (uint32_t)z->qns, z->qe, z->ts, z->te); - } - /** - s = ((uint32_t)(z->qns)); e = z->qe; - // sc->a[z->tn] - if(z->el) { - // if((z->qns>>32) == 75 && z->tn == 59) { - if(quick_exact_match(z, rref, qu, tu, sc)) { - s = ((uint32_t)(z->qns)); e = z->qe; - // fprintf(stderr, "-mm-[M::%s]\tqn::%u::%.*s\ttn::%u::%.*s\t%c\n", __func__, - // (uint32_t)(z->qns>>32), (int)Get_NAME_LENGTH(R_INF, (uint32_t)(z->qns>>32)), Get_NAME(R_INF, (uint32_t)(z->qns>>32)), z->tn, (int)Get_NAME_LENGTH(R_INF, z->tn), Get_NAME(R_INF, z->tn), "+-"[z->rev]); - } else { - s = ((uint32_t)(z->qns)); e = z->qe; - // fprintf(stderr, "-um-[M::%s]\tqn::%u::%.*s\ttn::%u::%.*s\t%c\n", __func__, - // (uint32_t)(z->qns>>32), (int)Get_NAME_LENGTH(R_INF, (uint32_t)(z->qns>>32)), Get_NAME(R_INF, (uint32_t)(z->qns>>32)), z->tn, (int)Get_NAME_LENGTH(R_INF, z->tn), Get_NAME(R_INF, z->tn), "+-"[z->rev]); - } - // } - } - **/ - } - - - v = be; vn = v->n; - radix_sort_ec64(v->a, v->a+v->n); - for (k = 0, dp = 0, st = ed = 0; k < vn; ++k) { - old_dp = dp; - ///if a[j] is qe - if (v->a[k]&1) --dp; - else ++dp; - - ed = v->a[k]>>1; - if(ed > st) { - m = st; m <<= 32; m |= ((uint64_t)ed); - kv_push(uint64_t, (*v), m); - kv_push(uint64_t, (*v), old_dp); - if((old_dp + 1) < occ_exact) return 0;///+1 for self - } - st = ed; - } - ed = ql; old_dp = dp; - if(ed > st) { - m = st; m <<= 32; m |= ((uint64_t)ed); - kv_push(uint64_t, (*v), m); - kv_push(uint64_t, (*v), old_dp); - if((old_dp + 1) < occ_exact) return 0;///+1 for self - } - - for (k = vn, m = 0; k < v->n; k++) { - v->a[m++] = v->a[k]; - } - v->n = m; - - - v = ba; vn = v->n; - radix_sort_ec64(v->a, v->a+v->n); - for (k = 0, dp = 0, st = ed = 0; k < vn; ++k) { - old_dp = dp; - ///if a[j] is qe - if (v->a[k]&1) --dp; - else ++dp; - - ed = v->a[k]>>1; - if(ed > st) { - m = st; m <<= 32; m |= ((uint64_t)ed); - kv_push(uint64_t, (*v), m); - kv_push(uint64_t, (*v), old_dp); - } - st = ed; - } - ed = ql; old_dp = dp; - if(ed > st) { - m = st; m <<= 32; m |= ((uint64_t)ed); - kv_push(uint64_t, (*v), m); - kv_push(uint64_t, (*v), old_dp); - } - - for (k = vn, m = 0; k < v->n; k++) { - v->a[m++] = v->a[k]; - } - v->n = m; - - - - - - - - ///debug - // v = be; - // for (k = 0; k < v->n; k += 2) { - // fprintf(stderr, "-be-[M::%s]\tq::[%lu,%u)\tocc::%lu\n", __func__, v->a[k]>>32, (uint32_t)v->a[k], v->a[k+1]); - // } - - // v = ba; - // for (k = 0; k < v->n; k += 2) { - // fprintf(stderr, "-ba-[M::%s]\tq::[%lu,%u)\tocc::%lu\n", __func__, v->a[k]>>32, (uint32_t)v->a[k], v->a[k+1]); - // } - - - - - - - - - - int64_t ke = 0, ka = 0, cc[2]; - qs = 0; qe = wl; qe = ((qe<=ql)?qe:ql); - for (; qs < ql; ) { - cc[0] = cal_cov_re(be, &ke, qs, qe); - cc[1] = cal_cov_re(ba, &ka, qs, qe); - - // fprintf(stderr, "[M::%s]\tq::[%ld,%ld)\tcc[0]::%ld\tcc[1]::%ld\n", __func__, qs, qe, cc[0], cc[1]); - - ff = 0; - if((cc[0]) && (cc[0] > cc[1])) { - cc[0] += qe - qs;///+(qe - qs) for self - cc[1] += cc[0]; - if(cc[0] > (cc[1]*occ_exact_rate)) { - ff = 1; - } - } - - if(ff == 0) return 0; - // fprintf(stderr, "[M::%s-beg]\tq::[%ld,%ld)\tcc[0]::%ld\tcc[1]::%ld\n", __func__, qs, qe, cc[0], cc[1]); - qs += wl; qe += wl; qe = ((qe<=ql)?qe:ql); - } - - - return 1; -} - -static void worker_hap_dc_ec(void *data, long i, int tid) -{ - ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); - // fprintf(stderr, "-0-[M::%s-beg] rid->%ld\n", __func__, i); - // if (memcmp("m64012_190921_234837/139067658/ccs", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { - // fprintf(stderr, "-0-[M::%s-beg] rid->%ld\n", __func__, i); - // } else if (memcmp("m64012_190921_234837/28968323/ccs", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { - // fprintf(stderr, "-1-[M::%s-beg] rid->%ld\n", __func__, i); - // } else { - // return; - // } - // if(i != 2851) return; - - // if(scb.a[i].m < scc.a[i].n) { - // scb.a[i].m = scc.a[i].n; - // REALLOC(scb.a[i].a, scb.a[i].m); - // } - // scb.a[i].n = scc.a[i].n; - // memcpy(scb.a[i].a, scc.a[i].a, scc.a[i].n*sizeof((*(scb.a[i].a)))); - - scc.f[i] = 0; - - if(!(R_INF.paf[i].length)) return; - // if(scc.f[i]) return; - asg64_v buf0; - - recover_UC_Read(&b->self_read, &R_INF, i); - - copy_asg_arr(buf0, b->sp); - if(gen_hap_dc_cov(&(b->v64), &buf0, &(R_INF.paf[i]), &R_INF, WINDOW_HC_FAST, 4, 0.7, &b->self_read, &b->ovlp_read, &scc, i)) { - scc.f[i] = 1; b->cnt[0]++; - // fprintf(stderr, "-mm-[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); - } else { - scc.f[i] = 0; b->cnt[1]++; - // fprintf(stderr, "-um-[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); - } - copy_asg_arr(b->sp, buf0); - - refresh_ec_ovec_buf_t0(b, REFRESH_N); -} - -static void worker_update_dc_ec(void *data, long i, int tid) -{ - ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); - uint64_t k; ma_hit_t *z; - // fprintf(stderr, "-0-[M::%s-beg] rid->%ld\n", __func__, i); - // if (memcmp("m64012_190921_234837/139067658/ccs", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { - // fprintf(stderr, "-0-[M::%s-beg] rid->%ld\n", __func__, i); - // } else if (memcmp("m64012_190921_234837/28968323/ccs", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { - // fprintf(stderr, "-1-[M::%s-beg] rid->%ld\n", __func__, i); - // } else { - // return; - // } - // if(i != 2851) return; - - // if(scb.a[i].m < scc.a[i].n) { - // scb.a[i].m = scc.a[i].n; - // REALLOC(scb.a[i].a, scb.a[i].m); - // } - // scb.a[i].n = scc.a[i].n; - // memcpy(scb.a[i].a, scc.a[i].a, scc.a[i].n*sizeof((*(scb.a[i].a)))); - - - if(!(R_INF.paf[i].length)) return; - recover_UC_Read(&b->self_read, &R_INF, i); - for (k = 0; k < R_INF.paf[i].length; k++) { - z = &(R_INF.paf[i].buffer[k]); - if((z->el) && (quick_exact_match(z, &R_INF, &b->self_read, &b->ovlp_read, &scc))) { - z->el = 1; b->cnt[0]++; - } else { - z->el = 0; b->cnt[1]++; - } - } - - refresh_ec_ovec_buf_t0(b, REFRESH_N); -} - - -void flip_paf_rc(uint64_t rid, ma_hit_t_alloc *paf, All_reads *rref) -{ - ma_hit_t *z; uint64_t k, m; int64_t ql = Get_READ_LENGTH((*rref), rid), tl, qs, qe, ts, te; - for (k = m = 0; k < paf->length; k++) { - z = &(paf->buffer[k]); tl = Get_READ_LENGTH((*rref), z->tn); - qs = (uint32_t)z->qns; if(qs < 0) qs = 0; if(qs > ql) qs = ql; - qe = z->qe; if(qe < 0) qe = 0; if(qe > ql) qe = ql; - ts = z->ts; if(ts < 0) ts = 0; if(ts > tl) ts = tl; - te = z->te; if(te < 0) te = 0; if(te > tl) te = tl; - if(qe > qs && te > ts) { - z->qns >>= 32; z->qns <<= 32; - z->qns |= ((uint64_t)(ql - qe)); - z->qe = ql - qs; - z->ts = tl - te; - z->te = tl - ts; - paf->buffer[m++] = *z; - } - } - paf->length = m; -} - -static void worker_hap_post_rev(void *data, long i, int tid) -{ - ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); - uint64_t k, l, kl, nn; char *a, c; - // fprintf(stderr, "-0-[M::%s-beg] rid->%ld\n", __func__, i); - // if (memcmp("m64012_190921_234837/139067658/ccs", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { - // fprintf(stderr, "-0-[M::%s-beg] rid->%ld\n", __func__, i); - // } else if (memcmp("m64012_190921_234837/28968323/ccs", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { - // fprintf(stderr, "-1-[M::%s-beg] rid->%ld\n", __func__, i); - // } else { - // return; - // } - // if(i != 2851) return; - - // if(scb.a[i].m < scc.a[i].n) { - // scb.a[i].m = scc.a[i].n; - // REALLOC(scb.a[i].a, scb.a[i].m); - // } - // scb.a[i].n = scc.a[i].n; - // memcpy(scb.a[i].a, scc.a[i].a, scc.a[i].n*sizeof((*(scb.a[i].a)))); - - flip_paf_rc(i, &(R_INF.paf[i]), &R_INF); - flip_paf_rc(i, &(R_INF.reverse_paf[i]), &R_INF); - - recover_UC_Read(&b->self_read, &R_INF, i); - l = b->self_read.length; kl = l>>1; a = b->self_read.seq; - for (k = nn = 0; k < kl; k++) { - c = a[l-k-1]; a[l-k-1] = RC_CHAR(a[k]); a[k] = RC_CHAR(c); - if(a[k] == 'N') nn++; - if(a[l-k-1] == 'N') nn++; - } - if(l&1) { - a[k] = RC_CHAR(a[k]); - if(a[k] == 'N') nn++; - } - - ha_compress_base(Get_READ(R_INF, i), a, l, &R_INF.N_site[i], nn); - - if(asm_opt.is_sc) { - retrive_bqual(&(b->v8q), NULL, i, -1, -1, 0, sc_bn); - for (k = 0; k < l; k++) a[l - k - 1] = b->v8q.a[k]; - ha_compress_qual_bit(Get_QUAL(R_INF, i), a, l, sc_bn); - } -} - -static void worker_hap_dc_ec_gen(void *data, long i, int tid) -{ - - ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); - uint32_t high_occ = asm_opt.hom_cov * (2.0 - HA_KMER_GOOD_RATIO); - uint32_t low_occ = asm_opt.hom_cov * HA_KMER_GOOD_RATIO; - - recover_UC_Read(&b->self_read, &R_INF, i); - - // overlap_region_sort_y_id(b->olist.list, b->olist.length); - // ma_hit_sort_tn(R_INF.paf[i].buffer, R_INF.paf[i].length); - // ma_hit_sort_tn(R_INF.reverse_paf[i].buffer, R_INF.reverse_paf[i].length); - - // R_INF.paf[i].is_fully_corrected = is_well_cal(&b->v64, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), b->self_read.length, 4); - - // R_INF.paf[i].is_abnormal = abnormal; - // R_INF.trio_flag[i] = AMBIGU; - - h_ec_lchain_fast(b->ab, i, &b->self_read, &b->ovlp_read, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, &b->exz, &b->v16, &b->v64, 0.02, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 0, 2, UINT32_MAX, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), 0.866666); - - push_ff_ovlp(&(R_INF.paf[i]), &b->olist, 1, &R_INF, b->cnt); - push_ff_ovlp(&(R_INF.reverse_paf[i]), &b->olist, 2, &R_INF, b->cnt); - - /** - copy_asg_arr(buf0, b->sp); - if(gen_hap_dc_cov(&(b->v64), &buf0, &(R_INF.paf[i]), &R_INF, WINDOW_HC_FAST, 4, 0.7, &b->self_read, &b->ovlp_read, &scc, i)) { - scc.f[i] = 1; b->num_read_base++; - // fprintf(stderr, "-mm-[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); - } else { - scc.f[i] = 0; b->num_correct_base++; - // fprintf(stderr, "-um-[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); - } - copy_asg_arr(b->sp, buf0); - **/ - refresh_ec_ovec_buf_t0(b, REFRESH_N); -} - -static void worker_hap_dc_ec_gen_new_idx(void *data, long i, int tid) -{ - - ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); - uint32_t high_occ = asm_opt.hom_cov * (2.0 - HA_KMER_GOOD_RATIO); - uint32_t low_occ = asm_opt.hom_cov * HA_KMER_GOOD_RATIO; uint32_t qlen = 0; - - recover_UC_Read(&b->self_read, &R_INF, i); qlen = b->self_read.length; - - h_ec_lchain(b->ab, i, b->self_read.seq, b->self_read.length, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, /**0.02**/0.001, asm_opt.max_n_chain, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 3, 0.7, 2, 32, COV_W); - - overlap_region_sort_y_id(b->olist.list, b->olist.length); - - // overlap_region_sort_y_id(b->olist.list, b->olist.length); - // ma_hit_sort_tn(R_INF.paf[i].buffer, R_INF.paf[i].length); - // ma_hit_sort_tn(R_INF.reverse_paf[i].buffer, R_INF.reverse_paf[i].length); - - // R_INF.paf[i].is_fully_corrected = is_well_cal(&b->v64, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), b->self_read.length, 4); - - // R_INF.paf[i].is_abnormal = abnormal; - // R_INF.trio_flag[i] = AMBIGU; - - h_ec_lchain_fast_new(b->ab, i, &b->self_read, &b->ovlp_read, &R_INF, &b->olist, &b->clist, &b->exz, &b->v16, &b->v64, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), 0.866666); - - if((asm_opt.is_ont) && (is_uncorrected_read(&b->olist, &b->v64, qlen, 1600))) { - b->olist.length = 0; - // fprintf(stderr, "[M::%s] rid::%ld\t%.*s\n", __func__, i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); - } - - push_ff_ovlp(&(R_INF.paf[i]), &b->olist, 1, &R_INF, b->cnt); - push_ff_ovlp(&(R_INF.reverse_paf[i]), &b->olist, 2, &R_INF, b->cnt); - - /** - copy_asg_arr(buf0, b->sp); - if(gen_hap_dc_cov(&(b->v64), &buf0, &(R_INF.paf[i]), &R_INF, WINDOW_HC_FAST, 4, 0.7, &b->self_read, &b->ovlp_read, &scc, i)) { - scc.f[i] = 1; b->num_read_base++; - // fprintf(stderr, "-mm-[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); - } else { - scc.f[i] = 0; b->num_correct_base++; - // fprintf(stderr, "-um-[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); - } - copy_asg_arr(b->sp, buf0); - **/ - refresh_ec_ovec_buf_t0(b, REFRESH_N); -} - -uint32_t is_chemical_r(ma_hit_t_alloc *ov, asg64_v *idx, int64_t len, int64_t cov, int64_t frank_len) -{ - uint64_t k, s, e; int64_t dp, old_dp, st = 0, ed, s0, s1, e0, e1, rr; - if((frank_len) > (len *0.01)) frank_len = len *0.01; - for (k = idx->n = 0; k < ov->length; k++) { - s = (uint32_t)ov->buffer[k].qns; e = ov->buffer[k].qe; - kv_push(uint64_t, (*idx), (s<<1)); - kv_push(uint64_t, (*idx), (e<<1)|1); - } - - radix_sort_ec64(idx->a, idx->a + idx->n); s0 = s1 = e0 = e1 = rr = -1; - for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { - old_dp = dp; - ///if a[j] is qe - if (idx->a[k]&1) --dp; - else ++dp; - - ed = idx->a[k]>>1; - if(ed > st) { - if(old_dp <= cov) { - rr = 1; - } else { - if(s0 < 0) { - s0 = st; s1 = ed; - } - e0 = st; e1 = ed; - } - } - st = ed; - } - - - ed = len; old_dp = dp; - if(ed > st) { - if(old_dp <= cov) { - rr = 1; - } else { - if(s0 < 0) { - s0 = st; s1 = ed; - } - e0 = st; e1 = ed; - } - } - - - if((s0 != e0) && (s1 != e1) && (s0 <= frank_len) && ((len - e1) <= frank_len) && (rr > 0)) { - for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { - old_dp = dp; - ///if a[j] is qe - if (idx->a[k]&1) --dp; - else ++dp; - - ed = idx->a[k]>>1; - if(ed > st) { - if((old_dp <= cov) && (st >= s0) && (ed <= e1)) { - // if((ov->buffer[0].qns>>32) == 3364) fprintf(stderr, "[M::%s]\tlf::[%ld,%ld)\trt::[%ld,%ld)\tmd::[%ld,%ld)\tcov::%ld\n", __func__, s0, s1, e0, e1, st, ed, old_dp); - return 1; - } - } - st = ed; - } - - - ed = len; old_dp = dp; - if(ed > st) { - if((old_dp <= cov) && (st >= s0) && (ed <= e1)) { - // if((ov->buffer[0].qns>>32) == 3364) fprintf(stderr, "[M::%s]\tlf::[%ld,%ld)\trt::[%ld,%ld)\tmd::[%ld,%ld)\tcov::%ld\n", __func__, s0, s1, e0, e1, st, ed, old_dp); - return 1; - } - } - } - - return 0; -} - - -uint32_t is_chemical_r_adv(ma_hit_t_alloc *ov, asg64_v *idx, int64_t len, int64_t cov, int64_t cut_len, double dup_rate, uint64_t is_del) -{ - uint64_t k, s, e; int64_t dp, old_dp, st = 0, ed, s0, e0, rr, lt; - for (k = idx->n = 0; k < ov->length; k++) { - if(is_del && ov->buffer[k].del) continue; - s0 = (uint32_t)ov->buffer[k].qns; e0 = ov->buffer[k].qe; - if(s0 > 0) s0 += cut_len; - if(e0 < len) e0 -= cut_len; - if(e0 <= s0) continue; - s = s0; e = e0; - - lt = Get_READ_LENGTH((R_INF), ov->buffer[k].tn); - rr = (lt >= len)?(lt - len):(len - lt); - if((rr <= (len*dup_rate)) && (rr <= (lt*dup_rate)) && (ov->buffer[k].rev)) { - dp = (ov->buffer[k].qe) - ((uint32_t)ov->buffer[k].qns); dp = len - dp; - old_dp = ov->buffer[k].te - ov->buffer[k].ts; old_dp = lt - old_dp; - if((dp <= (len*dup_rate)) && (old_dp <= (lt*dup_rate))) continue; - } - - kv_push(uint64_t, (*idx), (s<<1)); - kv_push(uint64_t, (*idx), (e<<1)|1); - } - - radix_sort_ec64(idx->a, idx->a + idx->n); s0 = e0 = rr = -1; - for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { - old_dp = dp; - ///if a[j] is qe - if (idx->a[k]&1) --dp; - else ++dp; - - ed = idx->a[k]>>1; - if(ed > st) { - // if(ov->length && ((ov->buffer[0].qns>>32) == 5045637)) { - // fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\tid::%lu\n", __func__, st, ed, old_dp, len, ov->buffer[0].qns>>32); - // } - if(old_dp <= cov) { - // if(ov->length && (ov->buffer[0].qns>>32) == 22344) fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\n", __func__, st, ed, old_dp, len); - return 1; - } - } - st = ed; - } - - - ed = len; old_dp = dp; - if(ed > st) { - // if(ov->length && ((ov->buffer[0].qns>>32) == 5045637)) { - // fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\tid::%lu\n", __func__, st, ed, old_dp, len, ov->buffer[0].qns>>32); - // } - if(old_dp <= cov) { - // if(ov->length && (ov->buffer[0].qns>>32) == 22344) fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\n", __func__, st, ed, old_dp, len); - return 1; - } - } - - return 0; -} - -int64_t cal_chemical_r_adv(ma_hit_t_alloc *ov, asg64_v *idx, int64_t len, int64_t cut_len, double dup_rate, uint64_t is_del) -{ - uint64_t k, s, e; int64_t dp, old_dp, st = 0, ed, s0, e0, rr, lt, min_cov; - for (k = idx->n = 0; k < ov->length; k++) { - if(is_del && ov->buffer[k].del) continue; - s0 = (uint32_t)ov->buffer[k].qns; e0 = ov->buffer[k].qe; - if(s0 > 0) s0 += cut_len; - if(e0 < len) e0 -= cut_len; - if(e0 <= s0) continue; - s = s0; e = e0; - - lt = Get_READ_LENGTH((R_INF), ov->buffer[k].tn); - rr = (lt >= len)?(lt - len):(len - lt); - if((rr <= (len*dup_rate)) && (rr <= (lt*dup_rate)) && (ov->buffer[k].rev)) { - dp = (ov->buffer[k].qe) - ((uint32_t)ov->buffer[k].qns); dp = len - dp; - old_dp = ov->buffer[k].te - ov->buffer[k].ts; old_dp = lt - old_dp; - if((dp <= (len*dup_rate)) && (old_dp <= (lt*dup_rate))) continue; - } - - kv_push(uint64_t, (*idx), (s<<1)); - kv_push(uint64_t, (*idx), (e<<1)|1); - } - - radix_sort_ec64(idx->a, idx->a + idx->n); s0 = e0 = rr = -1; min_cov = INT64_MAX; - for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { - old_dp = dp; - ///if a[j] is qe - if (idx->a[k]&1) --dp; - else ++dp; - - ed = idx->a[k]>>1; - if(ed > st) { - // if(ov->length && ((ov->buffer[0].qns>>32) == 5045637)) { - // fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\tid::%lu\n", __func__, st, ed, old_dp, len, ov->buffer[0].qns>>32); - // } - if(old_dp <= min_cov) { - // if(ov->length && (ov->buffer[0].qns>>32) == 22344) fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\n", __func__, st, ed, old_dp, len); - min_cov = old_dp; - } - } - st = ed; - } - - - ed = len; old_dp = dp; - if(ed > st) { - // if(ov->length && ((ov->buffer[0].qns>>32) == 5045637)) { - // fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\tid::%lu\n", __func__, st, ed, old_dp, len, ov->buffer[0].qns>>32); - // } - if(old_dp <= min_cov) { - // if(ov->length && (ov->buffer[0].qns>>32) == 22344) fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\n", __func__, st, ed, old_dp, len); - min_cov = old_dp; - } - } - - return min_cov; -} - -void prt_dbg_rid_paf(ma_hit_t_alloc *ov, UC_Read *ra, asg8_v *qa) -{ - if(!(ov->length)) return; - uint64_t k, qn = (ov->buffer[0].qns>>32), qn_n, i, m; char *nn = NULL; FILE *fp = NULL; ma_hit_t *h = NULL; - qn_n = Get_NAME_LENGTH((R_INF), qn) + 64; MALLOC(nn, qn_n); - - sprintf(nn, "%.*s.qry.fq", (int)Get_NAME_LENGTH(R_INF, qn), Get_NAME((R_INF), qn)); fp = fopen(nn, "w"); - for (k = 0; k < ov->length; k++) { - i = ov->buffer[k].tn; - recover_UC_Read(ra, &R_INF, i); - fprintf(fp, "@%.*s\n", (int32_t)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); - fprintf(fp, "%.*s\n", (int32_t)ra->length, ra->seq); - fprintf(fp, "+\n"); - retrive_bqual(qa, NULL, i, -1, -1, 0, sc_bn); - for (m = 0; m < qa->n; m++) fprintf(fp, "%c", (char)(sc_tb[qa->a[m]] + 33 - 1)); - fprintf(fp, "\n"); - } - fclose(fp); - - sprintf(nn, "%.*s.ref.fq", (int)Get_NAME_LENGTH(R_INF, qn), Get_NAME((R_INF), qn)); fp = fopen(nn, "w"); - i = qn; - recover_UC_Read(ra, &R_INF, i); - fprintf(fp, "@%.*s\n", (int32_t)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); - fprintf(fp, "%.*s\n", (int32_t)ra->length, ra->seq); - fprintf(fp, "+\n"); - retrive_bqual(qa, NULL, i, -1, -1, 0, sc_bn); - for (m = 0; m < qa->n; m++) fprintf(fp, "%c", (char)(sc_tb[qa->a[m]] + 33 - 1)); - fprintf(fp, "\n"); - fclose(fp); - - sprintf(nn, "%.*s.ref.fa", (int)Get_NAME_LENGTH(R_INF, qn), Get_NAME((R_INF), qn)); fp = fopen(nn, "w"); - i = qn; - recover_UC_Read(ra, &R_INF, i); - fprintf(fp, ">%.*s\n", (int32_t)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); - fprintf(fp, "%.*s\n", (int32_t)ra->length, ra->seq); - // fprintf(fp, "+\n"); - // retrive_bqual(qa, NULL, i, -1, -1, 0, sc_bn); - // for (m = 0; m < qa->n; m++) fprintf(fp, "%c", (char)(sc_tb[qa->a[m]] + 33 - 1)); - // fprintf(fp, "\n"); - fclose(fp); - - sprintf(nn, "%.*s.ov.paf", (int)Get_NAME_LENGTH(R_INF, qn), Get_NAME((R_INF), qn)); fp = fopen(nn, "w"); - for (k = 0; k < ov->length; k++) { - h = &(ov->buffer[k]); - fprintf(fp, "%.*s(qn::%u)\t%u\t%u\t%u\t%c\t%.*s(tn::%u)\t%u\t%u\t%u\t%u\t%u\t255\n", (int)Get_NAME_LENGTH(R_INF, Get_qn(*h)), Get_NAME((R_INF), Get_qn(*h)), Get_qn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_qn(*h)), Get_qs(*h), Get_qe(*h), "+-"[h->rev], - (int)Get_NAME_LENGTH(R_INF, Get_tn(*h)), Get_NAME((R_INF), Get_tn(*h)), Get_tn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_tn(*h)), Get_ts(*h), Get_te(*h), h->ml, h->bl); - } - fclose(fp); - - free(nn); -} - -static void worker_hap_dc_ec_chemical_r(void *data, long i, int tid) -{ - ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); - ma_hit_t_alloc *paf = &(R_INF.paf[i]); uint64_t k, m; - - // if (memcmp("3ed80bc4-1169-4948-a9ff-9c2463b7f7a2", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { - // fprintf(stderr, "-a-[M::%s-beg] rid->%ld, b->rr->%lu\n", __func__, i, b->rr); - // } - if(b->cnt[1] == 0) { - // if(i == 6204620) prt_dbg_rid_paf(&(R_INF.paf[i]), &(b->self_read), &(b->v8q)); - // if(is_chemical_r(&(R_INF.paf[i]), &b->v64, Get_READ_LENGTH((R_INF), i), 3, 16)) { - if(is_chemical_r_adv(&(R_INF.paf[i]), &b->v64, Get_READ_LENGTH((R_INF), i), asm_opt.chemical_cov, asm_opt.chemical_flank, 0.02, 0)) { - // fprintf(stderr, "-um-[M::%s]\tqn::%u::%.*s\n\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); - R_INF.paf[i].length = 0; b->cnt[0]++; - } - } else if(b->cnt[1] == 1) { - for (k = 0; k < paf->length; k++) { - if(R_INF.paf[paf->buffer[k].tn].length == 0) { - paf->buffer[k].tn = (uint32_t)-1; b->cnt[0]++; - } - } - } else { - for (k = m = 0; k < paf->length; k++) { - if(paf->buffer[k].tn == ((uint32_t)-1)) continue; - paf->buffer[m++] = paf->buffer[k]; - } - paf->length = m; - } - - refresh_ec_ovec_buf_t0(b, REFRESH_N); -} - -static void worker_hap_dc_ec_chemical_arc(void *data, long i, int tid) -{ - ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); - ma_hit_t_alloc *paf = &(R_INF.paf[i]), *rev; uint64_t k, z; - - if(b->cnt[1] == 0) { - if(is_chemical_r_adv(&(R_INF.paf[i]), &b->v64, Get_READ_LENGTH((R_INF), i), asm_opt.chemical_cov, asm_opt.chemical_flank, 0.02, 1)) { - // fprintf(stderr, "-um-[M::%s]\tqn::%u::%.*s\n\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); - for (k = 0; k < paf->length; k++) paf->buffer[k].del = 1; b->cnt[0]++; - } - } else if(b->cnt[1] == 1) { - for (k = 0; k < paf->length; k++) { - if((Get_qn(paf->buffer[k])) > (Get_tn(paf->buffer[k]))) continue; - rev = &(R_INF.paf[paf->buffer[k].tn]); - for (z = 0; z < rev->length; z++) { - if((rev->buffer[z].tn == (Get_qn(paf->buffer[k])))) { - if(paf->buffer[k].del != rev->buffer[z].del) { - paf->buffer[k].del = rev->buffer[z].del = 1; - } - } - } - } - } - - refresh_ec_ovec_buf_t0(b, REFRESH_N); -} - -static void worker_hap_dc_ec_chemical_arc_mark(void *data, long i, int tid) -{ - ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); - ma_hit_t_alloc *paf = &(R_INF.paf[i]), *rev; uint64_t k, z; int64_t cov, msk_cut = asm_opt.chemical_cov; - uint8_t *msk = ((ec_ovec_buf_t*)data)->cr; - - if(b->cnt[1] == 0) { - msk[i] = (uint8_t)-1; - cov = cal_chemical_r_adv(&(R_INF.paf[i]), &b->v64, Get_READ_LENGTH((R_INF), i), asm_opt.chemical_flank, 0.02, 1); - if(cov <= msk_cut) msk[i] = cov; - if(cov <= msk_cut/**FORCE_CUT**/) { - // fprintf(stderr, "-um-[M::%s]\tqn::%u::%.*s\n\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); - for (k = 0; k < paf->length; k++) paf->buffer[k].del = 1; b->cnt[0]++; - } - } else if(b->cnt[1] == 1) { - for (k = 0; k < paf->length; k++) { - if((Get_qn(paf->buffer[k])) > (Get_tn(paf->buffer[k]))) continue; - rev = &(R_INF.paf[paf->buffer[k].tn]); - for (z = 0; z < rev->length; z++) { - if((rev->buffer[z].tn == (Get_qn(paf->buffer[k])))) { - if((paf->buffer[k].del != rev->buffer[z].del) || (msk[Get_qn(paf->buffer[k])] <= msk_cut/**FORCE_CUT**/) || (msk[Get_tn(paf->buffer[k])] <= msk_cut/**FORCE_CUT**/)) { - paf->buffer[k].del = rev->buffer[z].del = 1; - } - } - } - } - } - - refresh_ec_ovec_buf_t0(b, REFRESH_N); -} - -uint64_t get_candidate_rrs(ma_utg_t *u, uint64_t rz) -{ - // uint64_t rid, rs, re, rev, k, l[2], lr, ts, te; - // ma_hit_t_alloc *z = NULL; - // ma_hit_t *h = NULL; - - // rid = u->a[rz]>>33; rev = (u->a[rz]>>32)&1; - // rs = 0; re = (uint32_t)u->a[rz]; - // if(!rev) { - // rs = Get_READ_LENGTH(R_INF, rid) - ((uint32_t)u->a[rz]); - // re = Get_READ_LENGTH(R_INF, rid); - // } - - // for (k = lr = 0; k < rz; k++) lr += (uint32_t)u->a[k]; - // ts = lr; te = lr + (uint32_t)u->a[k]; - - // z = &(sources[rid]); - // for (k = 0; k < z->length; k++) { - // h = &(z->buffer[k]); - // if ((Get_qs(*h) <= rs) && (Get_qe(*h) >= re)) { - // l[0] = l[1] = 0; - // if(!(h->rev&rev)) { - // l[0] = Get_ts(*h); l[1] = Get_READ_LENGTH(R_INF, Get_tn(*h)) - Get_te(*h); - // } else { - // l[1] = Get_ts(*h); l[0] = Get_READ_LENGTH(R_INF, Get_tn(*h)) - Get_te(*h); - // } - - // } - // } - - - return 1; -} - -static void worker_ec_polish(void *data, long i, int tid) -{ - ec_ovec_buf_t0 *b = &(((ec_polish_buf_t*)data)->p->a[tid]); - uint64_t *idx = &(((ec_polish_buf_t*)data)->idx.a[i]); - - if(get_candidate_rrs(&(((ec_polish_buf_t*)data)->ug->u.a[(*idx)>>32]), (uint32_t)(*idx))) { - *idx = (uint64_t)-1; - } - - refresh_ec_ovec_buf_t0(b, REFRESH_N); -} - -void gen_ovlst_paf(ma_hit_t_alloc *in_e, ma_hit_t_alloc *in_r, asg64_v *ou) -{ - uint32_t n = 0, k; - - for (k = 0; k < in_e->length; k++) { - if(!(in_e->buffer[k].el)) n++; - } - n += in_r->length; - - kv_resize(uint64_t, *ou, n); ou->n = 0; - - for (k = 0; k < in_e->length; k++) { - if(!(in_e->buffer[k].el)) { - ou->a[ou->n] = in_e->buffer[k].tn; - ou->a[ou->n] <<= 1; ou->a[ou->n] |= in_e->buffer[k].rev; - ou->n++; - } - } - - for (k = 0; k < in_r->length; k++) { - ou->a[ou->n] = in_r->buffer[k].tn; - ou->a[ou->n] <<= 1; ou->a[ou->n] |= in_r->buffer[k].rev; - ou->n++; - } - - radix_sort_ec64(ou->a, ou->a+ou->n); -} - -void dbg_overlap_region_cigar(overlap_region *a, uint64_t a_n, char *qstr, All_reads *rref, UC_Read *tu) -{ - bit_extz_t ez; uint64_t i, k; - for (i = 0; i < a_n; i++) { - if(a[i].y_pos_strand) { - recover_UC_Read_RC(tu, rref, a[i].y_id); - } else { - recover_UC_Read(tu, rref, a[i].y_id); - } - for (k = 0; k < a[i].w_list.n; k++) { - if(is_ualn_win((a[i].w_list.a[k]))) continue; - set_bit_extz_t(ez, a[i], k); - if(!cigar_check(tu->seq, qstr, &ez)) { - fprintf(stderr, "\n-0-[M::%s] x_id::%u, y_id::%u, x::[%u, %u), y::[%u, %u)\n", __func__, a[i].x_id, a[i].y_id, a[i].x_pos_s, a[i].x_pos_e + 1, a[i].y_pos_s, a[i].y_pos_e + 1); - exit(1); - } else { - // fprintf(stderr, "\n-1-[M::%s] x_id::%u, y_id::%u, x::[%u, %u), y::[%u, %u)\n", __func__, a[i].x_id, a[i].y_id, a[i].x_pos_s, a[i].x_pos_e + 1, a[i].y_pos_s, a[i].y_pos_e + 1); - } - } - } -} - -overlap_region* h_ec_lchain_re(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, UC_Read *tu, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v* buf, double bw_thres, - int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1) -{ - // fprintf(stderr, "-mm-[M::%s]\tchain_cutoff::%u\n", __func__, chain_cutoff); - uint64_t on = 0, k, ol0, wl = (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), m; ma_hit_t *oa = NULL; overlap_region *z = NULL, *aux_o = NULL, t; Window_Pool w; double err = asm_opt.max_ov_diff_ec; - - int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; - set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); - - init_Window_Pool(&w, rl, wl, (int)(1.0/err)); - - on = in0->length + in1->length + 1; - clear_overlap_region_alloc(ol); - clear_Candidates_list(cl); - if(on > ol->size) { - REALLOC(ol->list, on); - memset(ol->list+ol->size, 0, sizeof(overlap_region)*(on-ol->size)); - ol->size = on; - } - on = in0->length + in1->length; aux_o = &(ol->list[on]); - ol->length = 0; ol->mapped_overlaps_length = 0; m = 0; - - - // get the list of anchors - get_mz1(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), ab, ha_flt_tab, ha_idx, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL, 0); - - oa = in0->buffer; on = in0->length; - for (k = 0; k < on; k++) { - ol0 = ol->length; - if(oa[k].el) { - z = &(ol->list[ol->length++]); - z->x_id = rid; z->y_id = oa[k].tn; - z->x_pos_strand = 0; z->y_pos_strand = oa[k].rev; - z->x_pos_s = (uint32_t)oa[k].qns; - z->x_pos_e = oa[k].qe - 1; - z->y_pos_s = oa[k].ts; - z->y_pos_e = oa[k].te - 1; - - z->is_match = 1; - z->align_length = z->overlapLen = z->shared_seed = z->x_pos_e + 1 - z->x_pos_s; - z->non_homopolymer_errors = z->strong = 0; - - set_exact_exz(exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, exz); - - // if(oa[k].tn == 15382) fprintf(stderr, "-em-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); - } else { - if(oa[k].rev) recover_UC_Read_RC(tu, rref, oa[k].tn); - else recover_UC_Read(tu, rref, oa[k].tn); - - get_pi_ec_chain(ab, rid, rl, oa[k].tn, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); - assert(ol->length - ol0 <= 1); - if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { - ol->list[ol0].y_pos_strand = oa[k].rev; - // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); - } - } - - if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; - - if(m != ol0) { - t = ol->list[m]; - ol->list[m] = ol->list[ol0]; - ol->list[ol0] = t; - } - - m++; - } - - - oa = in1->buffer; on = in1->length; - for (k = 0; k < on; k++) { - ol0 = ol->length; - - if(oa[k].rev) recover_UC_Read_RC(tu, rref, oa[k].tn); - else recover_UC_Read(tu, rref, oa[k].tn); - - get_pi_ec_chain(ab, rid, rl, oa[k].tn, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); - assert(ol->length - ol0 <= 1); - if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { - ol->list[ol0].y_pos_strand = oa[k].rev; - // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); - } - - if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; - - if(m != ol0) { - t = ol->list[m]; - ol->list[m] = ol->list[ol0]; - ol->list[ol0] = t; - } - - m++; - } - - ol->length = m; - - // fprintf(stderr, "[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); - assert(ol->length <= (in0->length + in1->length)); - - - // dbg_overlap_region_cigar(ol->list, ol->length, rs, rref, tu); - - - return aux_o; -} - - -overlap_region* h_ec_lchain_re1(ha_abuf_t *ab, uint32_t rid, UC_Read *qu, UC_Read *tu, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v *buf, asg64_v *srt_i, double bw_thres, - int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1) -{ - // fprintf(stderr, "-mm-[M::%s]\tchain_cutoff::%u\n", __func__, chain_cutoff); - uint64_t on = 0, k, one = 0, ol0, wl = (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), m, m0, tid, trev; ma_hit_t *oa = NULL, *p = NULL; overlap_region *aux_o = NULL, *z = NULL, t; Window_Pool w; double err = asm_opt.max_ov_diff_ec; - char* rs = qu->seq; uint64_t rl = qu->length; - int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; - set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); - init_Window_Pool(&w, rl, wl, (int)(1.0/err)); - - srt_i->n = 0; - oa = in0->buffer; on = in0->length; m0 = 0; - for (k = 0; k < on; k++) { - if(oa[k].el) { - one++; continue; - } - m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; - kv_push(uint64_t, *srt_i, m); - } - oa = in1->buffer; on = in1->length; m0 = 1; - for (k = 0; k < on; k++) { - // if(oa[k].el) continue; - m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; - kv_push(uint64_t, *srt_i, m); - } - radix_sort_ec64(srt_i->a, srt_i->a + srt_i->n); - - // get the list of anchors - get_mz1(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), ab, ha_flt_tab, NULL/**ha_idx**/, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL, 0); - - h_ec_lchain_re_gen(ab, rid, rs, rl, mz_w, mz_k, ha_idx, rref, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, - max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip, tu, srt_i, scb.a); - - - ///max size - on = ol->length + one + srt_i->n + 1; m0 = on - 1; - if(on > ol->size) { - REALLOC(ol->list, on); - memset(ol->list+ol->size, 0, sizeof(overlap_region)*(on-ol->size)); - ol->size = on; - } - aux_o = &(ol->list[on-1]); ol->mapped_overlaps_length = 0; on = ol->length; - - // fprintf(stderr, "-0-[M::%s]\n", __func__); - - gen_hc_r_alin(ol, cl, rref, qu, tu, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf, 0, -1, -1); rs = qu->seq; - - // fprintf(stderr, "-1-[M::%s]\n", __func__); - - ///handle unmatched chain - for (k = m = ol->length; k < on; k++) { - clear_fake_cigar(&(ol->list[k].f_cigar)); - clear_window_list_alloc(&(ol->list[k].w_list)); - clear_window_list_alloc(&(ol->list[k].boundary_cigars)); - - ol0 = ol->length; - - tid = ol->list[k].y_id; trev = ol->list[k].y_pos_strand; - if(trev) recover_UC_Read_RC(tu, rref, tid); - else recover_UC_Read(tu, rref, tid); - - get_pi_ec_chain(ab, rid, rl, tid, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); - assert(ol->length - ol0 <= 1); - if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { - ol->list[ol0].y_pos_strand = trev; - // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); - } - - if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; - - if(m != ol0) { - t = ol->list[m]; - ol->list[m] = ol->list[ol0]; - ol->list[ol0] = t; - } - - m++; - } - ol->length = m; - - for (k = ol->length; k < on; k++) { - clear_fake_cigar(&(ol->list[k].f_cigar)); - clear_window_list_alloc(&(ol->list[k].w_list)); - clear_window_list_alloc(&(ol->list[k].boundary_cigars)); - } - - // fprintf(stderr, "[M::%s]\tnew::%lu\told::%lu\n", __func__, ol->length, ol0); - - oa = in0->buffer; on = in0->length; - for (k = 0; k < on; k++) { - if(oa[k].el) { - z = &(ol->list[ol->length++]); - z->x_id = rid; z->y_id = oa[k].tn; - z->x_pos_strand = 0; z->y_pos_strand = oa[k].rev; - z->x_pos_s = (uint32_t)oa[k].qns; - z->x_pos_e = oa[k].qe - 1; - z->y_pos_s = oa[k].ts; - z->y_pos_e = oa[k].te - 1; - - z->is_match = 1; - z->align_length = z->overlapLen = z->shared_seed = z->x_pos_e + 1 - z->x_pos_s; - z->non_homopolymer_errors = z->strong = 0; - - set_exact_exz(exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, exz); - - // if(oa[k].tn == 1945) fprintf(stderr, "-em-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); - } - } - m = ol->length; - - for (k = 0; k < srt_i->n; k++) { - ol0 = ol->length; - if(srt_i->a[k]&1) { - p = &(in1->buffer[((uint32_t)srt_i->a[k])>>1]); - } else { - p = &(in0->buffer[((uint32_t)srt_i->a[k])>>1]); - } - - if(p->rev) recover_UC_Read_RC(tu, rref, p->tn); - else recover_UC_Read(tu, rref, p->tn); - - get_pi_ec_chain(ab, rid, rl, p->tn, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); - assert(ol->length - ol0 <= 1); - if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { - ol->list[ol0].y_pos_strand = p->rev; - // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); - } - - if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; - - if(m != ol0) { - t = ol->list[m]; - ol->list[m] = ol->list[ol0]; - ol->list[ol0] = t; - } - - m++; - } - - ol->length = m; - - - // fprintf(stderr, "[M::%s]\tnew_n::%lu\told_n::%lu\n", __func__, ol->length, m0); - // fprintf(stderr, "[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); - // assert(ol->length <= (in0->length + in1->length)); - - - // dbg_overlap_region_cigar(ol->list, ol->length, rs, rref, tu); - - return aux_o; -} - -uint64_t direct_chain_cal(ha_abuf_t *ab, uint64_t qid, char *qs, uint64_t ql, uint64_t tid, char *ts, uint64_t tl, uint64_t trev, uint64_t mz_w, uint64_t mz_k, overlap_region_alloc *olst, Candidates_list *cl, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, double bw_thres, - int apend_be, uint64_t max_cnt, uint64_t min_cnt, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip, - bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t wl, int64_t khit, int64_t move_gap, asg16_v* buf) -{ - uint64_t ol0 = olst->length; - get_pi_ec_chain(ab, qid, ql, tid, ts, tl, mz_w, mz_k, olst, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); - assert(olst->length - ol0 <= 1); - if(olst->length > ol0) { - if(gen_hc_r_alin_re(&(olst->list[ol0]), cl, qs, ql, ts, tl, exz, aux_o, e_rate, wl, qid, E_KHIT, 1, buf)) { - olst->list[ol0].y_pos_strand = trev; - return 1; - } else { - clear_fake_cigar(&(olst->list[ol0].f_cigar)); - clear_window_list_alloc(&(olst->list[ol0].w_list)); - clear_window_list_alloc(&(olst->list[ol0].boundary_cigars)); - olst->length--; - } - } - return 0; -} - - -overlap_region* h_ec_lchain_re2(ha_abuf_t *ab, uint32_t rid, UC_Read *qu, UC_Read *tu, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v *buf, asg64_v *srt_i, double bw_thres, - int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1) -{ - // fprintf(stderr, "-0-[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); - // fprintf(stderr, "-mm-[M::%s]\tchain_cutoff::%u\n", __func__, chain_cutoff); - uint64_t on = 0, k, l, i, one = 0, ol0, wl = (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), m, m0, tid, trev, max_cnt = UINT32_MAX, min_cnt = 0; ma_hit_t *oa = NULL, *p = NULL; overlap_region *aux_o = NULL, *z = NULL, t; Window_Pool w; double err = asm_opt.max_ov_diff_ec; tiny_queue_t tq; memset(&tq, 0, sizeof(tiny_queue_t)); - char* rs = qu->seq; uint64_t rl = qu->length; int64_t n, zn, om; - int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; - set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); - init_Window_Pool(&w, rl, wl, (int)(1.0/err)); - - ///cutoff - if(high_occ) { - max_cnt = (*high_occ); - if(max_cnt < 2) max_cnt = 2; - } - if(low_occ) { - min_cnt = (*low_occ); - if(min_cnt < 2) min_cnt = 2; - } - - ///memory - ol->length = 0; on = in0->length + in1->length + 1; - if(on > ol->size) { - REALLOC(ol->list, on); - memset(ol->list+ol->size, 0, sizeof(overlap_region)*(on-ol->size)); - ol->size = on; - } - aux_o = &(ol->list[on-1]); ol->mapped_overlaps_length = 0; on = in0->length + in1->length; - - ///overlap idx - srt_i->n = 0; - oa = in0->buffer; on = in0->length; m0 = 0; - for (k = 0; k < on; k++) { - if(oa[k].el) { - one++; continue; - } - m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; - kv_push(uint64_t, *srt_i, m); - } - oa = in1->buffer; on = in1->length; m0 = 1; - for (k = 0; k < on; k++) { - // if(oa[k].el) continue; - m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; - kv_push(uint64_t, *srt_i, m); - } - radix_sort_ec64(srt_i->a, srt_i->a + srt_i->n); - - // get the list of anchors - get_mz1(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), ab, ha_flt_tab, NULL/**ha_idx**/, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL, 0); - - h_ec_lchain_re_gen_srt(ab, ha_idx, ol, cl); - - k = 1; l = 0; i = 0; n = zn = 0; - while(h_ec_lchain_re_gen_qry(ab, &k, &l, &i, srt_i->a, srt_i->n, &tid, &trev)) { - - if(trev) recover_UC_Read_RC(tu, rref, tid); - else recover_UC_Read(tu, rref, tid); - - ol0 = ol->length; om = 0; - if(h_ec_lchain_re_chn(ab, l, k, rid, rs, rl, tid, tu->seq, tu->length, trev, mz_w, mz_k, ol, cl, bw_thres, apend_be, max_cnt, min_cnt, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip, &tq, scb.a, &n, &zn)) { - assert(ol->length - ol0 == 1); - ol->list[ol0].y_pos_strand = 0; - if(gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf)) { - ol->list[ol0].y_pos_strand = trev; om = 1; - } else {///unmatch - clear_fake_cigar(&(ol->list[ol0].f_cigar)); - clear_window_list_alloc(&(ol->list[ol0].w_list)); - clear_window_list_alloc(&(ol->list[ol0].boundary_cigars)); - ol->length--; - } - } - - if(om) { - srt_i->a[i] >>= 32; srt_i->a[i] <<= 32; srt_i->a[i] |= ((uint64_t)((uint32_t)-1)); - } - - l = k; k++; - } - - for (k = m = 0; k < srt_i->n; k++) { - if(((uint32_t)srt_i->a[k]) == ((uint32_t)-1)) continue; - srt_i->a[m++] = srt_i->a[k]; - } - // fprintf(stderr, "[M::%s]\ttot::%lu\tremain::%lu\n", __func__, (uint64_t)srt_i->n, m); - srt_i->n = m; - - - - oa = in0->buffer; on = in0->length; - for (k = 0; k < on; k++) { - if(oa[k].el) { - z = &(ol->list[ol->length++]); - z->x_id = rid; z->y_id = oa[k].tn; - z->x_pos_strand = 0; z->y_pos_strand = oa[k].rev; - z->x_pos_s = (uint32_t)oa[k].qns; - z->x_pos_e = oa[k].qe - 1; - z->y_pos_s = oa[k].ts; - z->y_pos_e = oa[k].te - 1; - - z->is_match = 1; - z->align_length = z->overlapLen = z->shared_seed = z->x_pos_e + 1 - z->x_pos_s; - z->non_homopolymer_errors = z->strong = 0; - - set_exact_exz(exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, exz); - - // if(oa[k].tn == 1945) fprintf(stderr, "-em-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); - } - } - m = ol->length; - - - clear_Candidates_list(cl); - for (k = 0; k < srt_i->n; k++) { - ol0 = ol->length; - if(srt_i->a[k]&1) { - p = &(in1->buffer[((uint32_t)srt_i->a[k])>>1]); - } else { - p = &(in0->buffer[((uint32_t)srt_i->a[k])>>1]); - } - - if(p->rev) recover_UC_Read_RC(tu, rref, p->tn); - else recover_UC_Read(tu, rref, p->tn); - - get_pi_ec_chain(ab, rid, rl, p->tn, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); - assert(ol->length - ol0 <= 1); - if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { - ol->list[ol0].y_pos_strand = p->rev; - // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); - } - - if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; - - if(m != ol0) { - t = ol->list[m]; - ol->list[m] = ol->list[ol0]; - ol->list[ol0] = t; - } - - m++; - } - - ol->length = m; - - // fprintf(stderr, "[M::%s]\tnew_n::%lu\told_n::%lu\n", __func__, ol->length, m0); - // fprintf(stderr, "-1-[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); - assert(ol->length <= (in0->length + in1->length)); - - - // dbg_overlap_region_cigar(ol->list, ol->length, rs, rref, tu); - - return aux_o; -} - - -overlap_region* h_ec_lchain_fast(ha_abuf_t *ab, uint32_t rid, UC_Read *qu, UC_Read *tu, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v *buf, asg64_v *srt_i, double bw_thres, - int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1, double sh) -{ - // fprintf(stderr, "-0-[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); - // fprintf(stderr, "-mm-[M::%s]\tchain_cutoff::%u\n", __func__, chain_cutoff); - uint64_t on = 0, k, l, i, one = 0, ol0, wl = (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), m, m0, tid, trev, max_cnt = UINT32_MAX, min_cnt = 0, is_match; ma_hit_t *oa = NULL, *p = NULL; overlap_region *aux_o = NULL, *z = NULL; Window_Pool w; double err = asm_opt.max_ov_diff_ec; tiny_queue_t tq; memset(&tq, 0, sizeof(tiny_queue_t)); - char* rs = qu->seq; uint64_t rl = qu->length; int64_t n, zn, om; uint64_t aq[2], at[2], bq[2], bt[2], ovlp, os, oe; - int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; - set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); - init_Window_Pool(&w, rl, wl, (int)(1.0/err)); - - ///cutoff - if(high_occ) { - max_cnt = (*high_occ); - if(max_cnt < 2) max_cnt = 2; - } - if(low_occ) { - min_cnt = (*low_occ); - if(min_cnt < 2) min_cnt = 2; - } - - ///memory - ol->length = 0; on = in0->length + in1->length + 1; - if(on > ol->size) { - REALLOC(ol->list, on); - memset(ol->list+ol->size, 0, sizeof(overlap_region)*(on-ol->size)); - ol->size = on; - } - aux_o = &(ol->list[on-1]); ol->mapped_overlaps_length = 0; on = in0->length + in1->length; - - ///overlap idx - srt_i->n = 0; - oa = in0->buffer; on = in0->length; m0 = 0; - for (k = 0; k < on; k++) { - if(oa[k].el) { - one++; continue; - } - m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; - kv_push(uint64_t, *srt_i, m); - } - oa = in1->buffer; on = in1->length; m0 = 1; - for (k = 0; k < on; k++) { - // if(oa[k].el) continue; - m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; - kv_push(uint64_t, *srt_i, m); - } - radix_sort_ec64(srt_i->a, srt_i->a + srt_i->n); - - // get the list of anchors - get_mz1(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), ab, ha_flt_tab, NULL/**ha_idx**/, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL, 0); - - h_ec_lchain_re_gen_srt(ab, ha_idx, ol, cl); - - k = 1; l = 0; i = 0; n = zn = 0; - while(h_ec_lchain_re_gen_qry(ab, &k, &l, &i, srt_i->a, srt_i->n, &tid, &trev)) { - - if(trev) recover_UC_Read_RC(tu, rref, tid); - else recover_UC_Read(tu, rref, tid); - - ol0 = ol->length; om = 0; - if(h_ec_lchain_re_chn(ab, l, k, rid, rs, rl, tid, tu->seq, tu->length, trev, mz_w, mz_k, ol, cl, bw_thres, apend_be, max_cnt, min_cnt, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip, &tq, scb.a, &n, &zn)) { - assert(ol->length - ol0 == 1); - ol->list[ol0].y_pos_strand = trev; om = 1; ol->list[ol0].shared_seed = 0; ol->list[ol0].is_match = 0; - - assert(((srt_i->a[i]>>33) == ol->list[ol0].y_id) && (((srt_i->a[i]>>32)&1) == ol->list[ol0].y_pos_strand)); - if(srt_i->a[i]&1) { - p = &(in1->buffer[((uint32_t)srt_i->a[i])>>1]); is_match = 2; - } else { - p = &(in0->buffer[((uint32_t)srt_i->a[i])>>1]); is_match = 1; - } - ol->list[ol0].strong = p->ml; ol->list[ol0].without_large_indel = p->no_l_indel; - - aq[0] = (uint32_t)p->qns; aq[1] = p->qe; - at[0] = p->ts; at[1] = p->te; - - bq[0] = ol->list[ol0].x_pos_s; bq[1] = ol->list[ol0].x_pos_e + 1; - bt[0] = ol->list[ol0].y_pos_s; bt[1] = ol->list[ol0].y_pos_e + 1; - - os = MAX(aq[0], bq[0]); oe = MIN(aq[1], bq[1]); - ovlp = ((oe>os)? (oe-os):0); - if(!((ovlp) && (ovlp >= ((aq[1] - aq[0])*sh)) && ((ovlp >= ((bq[1] - bq[0])*sh))))) om = 0; - - os = MAX(at[0], bt[0]); oe = MIN(at[1], bt[1]); - ovlp = ((oe>os)? (oe-os):0); - if(!((ovlp) && (ovlp >= ((at[1] - at[0])*sh)) && ((ovlp >= ((bt[1] - bt[0])*sh))))) om = 0; - - if(om) { - if(exact_ec_check(rs, rl, tu->seq, tu->length, bq[0], bq[1], bt[0], bt[1])) { - if(is_match == 2) { - ol->list[ol0].strong = 0; ol->list[ol0].without_large_indel = 1; - } - is_match = 1; ol->list[ol0].shared_seed = 1; - } - ol->list[ol0].is_match = is_match; - } else {///unmatch - clear_fake_cigar(&(ol->list[ol0].f_cigar)); - clear_window_list_alloc(&(ol->list[ol0].w_list)); - clear_window_list_alloc(&(ol->list[ol0].boundary_cigars)); - ol->length--; - } - } - - if(om) { - srt_i->a[i] >>= 32; srt_i->a[i] <<= 32; srt_i->a[i] |= ((uint64_t)((uint32_t)-1)); - } - - l = k; k++; - } - - for (k = m = 0; k < srt_i->n; k++) { - if(((uint32_t)srt_i->a[k]) == ((uint32_t)-1)) continue; - srt_i->a[m++] = srt_i->a[k]; - } - // fprintf(stderr, "[M::%s]\ttot::%lu\tremain::%lu\n", __func__, (uint64_t)srt_i->n, m); - srt_i->n = m; - - - - oa = in0->buffer; on = in0->length; - for (k = 0; k < on; k++) { - if(oa[k].el) { - z = &(ol->list[ol->length++]); - z->x_id = rid; z->y_id = oa[k].tn; - z->x_pos_strand = 0; z->y_pos_strand = oa[k].rev; - z->x_pos_s = (uint32_t)oa[k].qns; - z->x_pos_e = oa[k].qe - 1; - z->y_pos_s = oa[k].ts; - z->y_pos_e = oa[k].te - 1; - - z->align_length = z->overlapLen = z->x_pos_e + 1 - z->x_pos_s; - z->non_homopolymer_errors = 0; - - z->is_match = 1; z->shared_seed = 1; - z->strong = oa[k].ml; z->without_large_indel = oa[k].no_l_indel; - - set_exact_exz(exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, exz); - - // if(oa[k].tn == 1945) fprintf(stderr, "-em-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); - } - } - /** - m = ol->length; - - - clear_Candidates_list(cl); - for (k = 0; k < srt_i->n; k++) { - ol0 = ol->length; - if(srt_i->a[k]&1) { - p = &(in1->buffer[((uint32_t)srt_i->a[k])>>1]); - } else { - p = &(in0->buffer[((uint32_t)srt_i->a[k])>>1]); - } - - if(p->rev) recover_UC_Read_RC(tu, rref, p->tn); - else recover_UC_Read(tu, rref, p->tn); - - get_pi_ec_chain(ab, rid, rl, p->tn, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); - assert(ol->length - ol0 <= 1); - if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { - ol->list[ol0].y_pos_strand = p->rev; - // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); - } - - if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; - - if(m != ol0) { - t = ol->list[m]; - ol->list[m] = ol->list[ol0]; - ol->list[ol0] = t; - } - - m++; - } - - ol->length = m; - **/ - - // fprintf(stderr, "[M::%s]\tnew_n::%lu\told_n::%lu\n", __func__, ol->length, m0); - // fprintf(stderr, "-1-[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); - assert(ol->length <= (in0->length + in1->length)); - - - // dbg_overlap_region_cigar(ol->list, ol->length, rs, rref, tu); - - return aux_o; -} - -void h_ec_lchain_fast_new(ha_abuf_t *ab, uint32_t rid, UC_Read *qu, UC_Read *tu, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v *buf, asg64_v *srt_i, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1, double sh) -{ - // fprintf(stderr, "-0-[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); - // fprintf(stderr, "-mm-[M::%s]\tchain_cutoff::%u\n", __func__, chain_cutoff); - uint64_t on = 0, k, i, l, m, m0, tid, trev, is_match, is_usrt = 0; ma_hit_t *oa = NULL, *p = NULL; overlap_region *z = NULL, t; - char* rs = qu->seq; uint64_t rl = qu->length; int64_t om; uint64_t aq[2], at[2], bq[2], bt[2], ovlp, os, oe; - - - - ///overlap idx - srt_i->n = 0; - oa = in0->buffer; on = in0->length; m0 = 0; - for (k = 0; k < on; k++) { - // if(oa[k].el) continue; - m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; - kv_push(uint64_t, *srt_i, m); - } - oa = in1->buffer; on = in1->length; m0 = 1; - for (k = 0; k < on; k++) { - // if(oa[k].el) continue; - m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; - kv_push(uint64_t, *srt_i, m); - } - radix_sort_ec64(srt_i->a, srt_i->a + srt_i->n); - - k = 0; i = 0; - for (k = m = 0; k < ol->length; k++) { - z = &(ol->list[k]); tid = z->y_id; trev = z->y_pos_strand; - z->non_homopolymer_errors = 0; - for (; (i < srt_i->n) && ((srt_i->a[i]>>32) < ((tid<<1)|trev)); i++); - if((i < srt_i->n) && ((srt_i->a[i]>>32) == ((tid<<1)|trev))) { - om = 1; z->shared_seed = 0; z->is_match = 0; - if(srt_i->a[i]&1) { - p = &(in1->buffer[((uint32_t)srt_i->a[i])>>1]); is_match = 2; - } else { - p = &(in0->buffer[((uint32_t)srt_i->a[i])>>1]); is_match = 1; - } - z->strong = p->ml; z->without_large_indel = p->no_l_indel; - - aq[0] = (uint32_t)p->qns; aq[1] = p->qe; - at[0] = p->ts; at[1] = p->te; - - bq[0] = z->x_pos_s; bq[1] = z->x_pos_e + 1; - bt[0] = z->y_pos_s; bt[1] = z->y_pos_e + 1; - - os = MAX(aq[0], bq[0]); oe = MIN(aq[1], bq[1]); - ovlp = ((oe>os)? (oe-os):0); - if(!((ovlp) && (ovlp >= ((aq[1] - aq[0])*sh)) && ((ovlp >= ((bq[1] - bq[0])*sh))))) om = 0; - z->non_homopolymer_errors += ((aq[1] - aq[0]) - ovlp); - - os = MAX(at[0], bt[0]); oe = MIN(at[1], bt[1]); - ovlp = ((oe>os)? (oe-os):0); - if(!((ovlp) && (ovlp >= ((at[1] - at[0])*sh)) && ((ovlp >= ((bt[1] - bt[0])*sh))))) om = 0; - z->non_homopolymer_errors += ((at[1] - at[0]) - ovlp); - - if(om) { - if(is_match == 1 && p->el == 1) p->el = 0; - resize_UC_Read(tu, bt[1] - bt[0]); - recover_UC_Read_sub_region(tu->seq, bt[0], bt[1] - bt[0], trev, rref, tid); - if(exact_ec_check(rs, rl, tu->seq, bt[1] - bt[0], bq[0], bq[1], 0, bt[1] - bt[0])) { - if(is_match == 2) { - z->strong = 0; z->without_large_indel = 1; - } - is_match = 1; z->shared_seed = 1; - } - z->is_match = is_match; - } - } else { - om = 0; - bq[0] = z->x_pos_s; bq[1] = z->x_pos_e + 1; - bt[0] = z->y_pos_s; bt[1] = z->y_pos_e + 1; - resize_UC_Read(tu, bt[1] - bt[0]); - recover_UC_Read_sub_region(tu->seq, bt[0], bt[1] - bt[0], trev, rref, tid); - if(exact_ec_check(rs, rl, tu->seq, bt[1] - bt[0], bq[0], bq[1], 0, bt[1] - bt[0])) { - z->strong = 0; z->without_large_indel = 1; - z->shared_seed = 1; z->is_match = 1; om = 1; - } - } - - if(om) { - if(m != k) { - t = ol->list[m]; - ol->list[m] = ol->list[k]; - ol->list[k] = t; - } - m++; - } - } - ol->length = m; - - - oa = in0->buffer; on = in0->length; - for (k = 0; k < on; k++) { - if(oa[k].el) { - // z = &(ol->list[ol->length++]); - kv_pushp_ol(overlap_region, (*ol), &z); - clear_fake_cigar(&(z->f_cigar)); - clear_window_list_alloc(&(z->w_list)); - clear_window_list_alloc(&(z->boundary_cigars)); - - z->x_id = rid; z->y_id = oa[k].tn; - z->x_pos_strand = 0; z->y_pos_strand = oa[k].rev; - z->x_pos_s = (uint32_t)oa[k].qns; - z->x_pos_e = oa[k].qe - 1; - z->y_pos_s = oa[k].ts; - z->y_pos_e = oa[k].te - 1; - - z->align_length = z->overlapLen = z->x_pos_e + 1 - z->x_pos_s; - z->non_homopolymer_errors = 0; - - z->is_match = 1; z->shared_seed = 1; - z->strong = oa[k].ml; z->without_large_indel = oa[k].no_l_indel; - - set_exact_exz(exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, exz); - - is_usrt = 1; - // if(oa[k].tn == 1945) fprintf(stderr, "-em-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); - } - } - - if(is_usrt) overlap_region_sort_y_id(ol->list, ol->length); - - if(ol->length > 1) {///for duplicated chains - uint64_t mm_k, s; int64_t mm_sc, sc; - for (k = 1, l = m = 0; k <= ol->length; k++) { - if(k == ol->length || ol->list[k].y_id != ol->list[l].y_id) { - mm_k = l; - if(k - l > 1) { - for (s = l, mm_sc = INT32_MIN, mm_k = ((uint64_t)-1); s < k; s++) { - z = &(ol->list[s]); - sc = z->non_homopolymer_errors; sc = - sc; - if((sc > mm_sc) || ((sc == mm_sc) && ((ol->list[mm_k].x_pos_e+1-ol->list[mm_k].x_pos_s) < (z->x_pos_e+1-z->x_pos_s)))) { - mm_sc = sc; mm_k = s; - } - } - } - if(mm_k != ((uint64_t)-1)) { - if(mm_k != m) { - t = ol->list[mm_k]; - ol->list[mm_k] = ol->list[m]; - ol->list[m] = t; - } - m++; - } - l = k; - } - } - ol->length = m; - } -} - -overlap_region* h_ec_lchain_re3(ha_abuf_t *ab, uint32_t rid, UC_Read *qu, UC_Read *tu, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v *buf, asg64_v *srt_i, double bw_thres, - int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1) -{ - // fprintf(stderr, "-mm-[M::%s]\tchain_cutoff::%u\n", __func__, chain_cutoff); - uint64_t on = 0, k, one = 0, ol0, wl = (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), m, m0, tid, trev; ma_hit_t *oa = NULL, *p = NULL; overlap_region *aux_o = NULL, *z = NULL, t; Window_Pool w; double err = asm_opt.max_ov_diff_ec; - char* rs = qu->seq; uint64_t rl = qu->length; - int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; - set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); - init_Window_Pool(&w, rl, wl, (int)(1.0/err)); - - srt_i->n = 0; - oa = in0->buffer; on = in0->length; m0 = 0; - for (k = 0; k < on; k++) { - m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; - if(oa[k].el) { - one++; m |= ((uint32_t)-1); - } else { - m |= (k<<1); m |= m0; - } - kv_push(uint64_t, *srt_i, m); - } - oa = in1->buffer; on = in1->length; m0 = 1; - for (k = 0; k < on; k++) { - // if(oa[k].el) continue; - m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; - kv_push(uint64_t, *srt_i, m); - } - radix_sort_ec64(srt_i->a, srt_i->a + srt_i->n); - - // get the list of anchors - get_mz1(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), ab, ha_flt_tab, NULL/**ha_idx**/, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL, 0); - - h_ec_lchain_re_gen3(ab, rid, rs, rl, mz_w, mz_k, ha_idx, rref, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, - max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip, tu, srt_i, scb.a); - - - ///max size - on = ol->length + one + srt_i->n + 1; m0 = on - 1; - if(on > ol->size) { - REALLOC(ol->list, on); - memset(ol->list+ol->size, 0, sizeof(overlap_region)*(on-ol->size)); - ol->size = on; - } - aux_o = &(ol->list[on-1]); ol->mapped_overlaps_length = 0; on = ol->length; - - // fprintf(stderr, "-0-[M::%s]\n", __func__); - - gen_hc_r_alin(ol, cl, rref, qu, tu, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf, 0, -1, -1); rs = qu->seq; - - // fprintf(stderr, "-1-[M::%s]\n", __func__); - - ///handle unmatched chain - for (k = m = ol->length; k < on; k++) { - clear_fake_cigar(&(ol->list[k].f_cigar)); - clear_window_list_alloc(&(ol->list[k].w_list)); - clear_window_list_alloc(&(ol->list[k].boundary_cigars)); - - ol0 = ol->length; - - tid = ol->list[k].y_id; trev = ol->list[k].y_pos_strand; - if(trev) recover_UC_Read_RC(tu, rref, tid); - else recover_UC_Read(tu, rref, tid); - - get_pi_ec_chain(ab, rid, rl, tid, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); - assert(ol->length - ol0 <= 1); - if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { - ol->list[ol0].y_pos_strand = trev; - // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); - } - - if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; - - if(m != ol0) { - t = ol->list[m]; - ol->list[m] = ol->list[ol0]; - ol->list[ol0] = t; - } - - m++; - } - ol->length = m; - - for (k = ol->length; k < on; k++) { - clear_fake_cigar(&(ol->list[k].f_cigar)); - clear_window_list_alloc(&(ol->list[k].w_list)); - clear_window_list_alloc(&(ol->list[k].boundary_cigars)); - } - - // fprintf(stderr, "[M::%s]\tnew::%lu\told::%lu\n", __func__, ol->length, ol0); - - oa = in0->buffer; on = in0->length; - for (k = 0; k < on; k++) { - if(oa[k].el) { - z = &(ol->list[ol->length++]); - z->x_id = rid; z->y_id = oa[k].tn; - z->x_pos_strand = 0; z->y_pos_strand = oa[k].rev; - z->x_pos_s = (uint32_t)oa[k].qns; - z->x_pos_e = oa[k].qe - 1; - z->y_pos_s = oa[k].ts; - z->y_pos_e = oa[k].te - 1; - - z->is_match = 1; - z->align_length = z->overlapLen = z->shared_seed = z->x_pos_e + 1 - z->x_pos_s; - z->non_homopolymer_errors = z->strong = 0; - - set_exact_exz(exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, exz); - - // if(oa[k].tn == 1945) fprintf(stderr, "-em-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); - } - } - m = ol->length; - - for (k = 0; k < srt_i->n; k++) { - ol0 = ol->length; - if(srt_i->a[k]&1) { - p = &(in1->buffer[((uint32_t)srt_i->a[k])>>1]); - } else { - p = &(in0->buffer[((uint32_t)srt_i->a[k])>>1]); - } - - if(p->rev) recover_UC_Read_RC(tu, rref, p->tn); - else recover_UC_Read(tu, rref, p->tn); - - get_pi_ec_chain(ab, rid, rl, p->tn, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); - assert(ol->length - ol0 <= 1); - if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { - ol->list[ol0].y_pos_strand = p->rev; - // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); - } - - if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; - - if(m != ol0) { - t = ol->list[m]; - ol->list[m] = ol->list[ol0]; - ol->list[ol0] = t; - } - - m++; - } - - ol->length = m; - - - // fprintf(stderr, "[M::%s]\tnew_n::%lu\told_n::%lu\n", __func__, ol->length, m0); - // fprintf(stderr, "[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); - // assert(ol->length <= (in0->length + in1->length)); - - - // dbg_overlap_region_cigar(ol->list, ol->length, rs, rref, tu); - - return aux_o; -} - - -void gen_ori_seq0(char *tstr, uint64_t tl, UC_Read *qu, asg16_v *sc, uint64_t rid) -{ - uint64_t ck, qk, tk, k, wq[2], wt[2]; uint32_t len; uint16_t c, bq, bt; char *qstr = NULL; - - ck = qk = tk = 0; - while (ck < sc->n) { - wq[0] = qk; wt[0] = tk; - ck = pop_trace_bp_f(sc, ck, &c, &bq, &bt, &len); - if(c != 2) qk += len; - if(c != 3) tk += len; - wq[1] = qk; wt[1] = tk; - } - if(!(tk == tl)) { - fprintf(stderr, "[M::%s] rid::%lu, tk::%lu, tl::%lu\n", __func__, rid, tk, tl); - } - assert(tk == tl); - - resize_UC_Read(qu, qk); qstr = qu->seq; qu->length = qk; - ck = qk = tk = 0; - while (ck < sc->n) { - wq[0] = qk; wt[0] = tk; - ck = pop_trace_bp_f(sc, ck, &c, &bq, &bt, &len); - if(c != 2) qk += len; - if(c != 3) tk += len; - wq[1] = qk; wt[1] = tk; - - if(c == 0) { - memcpy(qstr + wq[0], tstr + wt[0], (wq[1]-wq[0])*sizeof((*qstr))); - } else if(c == 1 || c == 3) { - for (k = wq[0]; k < wq[1]; k++) qstr[k] = s_H[bq]; - } - // fprintf(stderr, "%u%c(%c)(x::[%lu,%ld))(y::[%lu,%ld))\n", len, cm[c], ((c==1)||(c==2))?(cc[bt]):('*'), wx[0], wx[1], wy[0], wy[1]); // s_H - } -} - -void gen_cc_fly(asg16_v *sc, char *qstr, uint64_t ql, char *tstr, uint64_t tl, bit_extz_t *exz, double e_rate, uint64_t maxn, uint64_t maxe) -{ - // fprintf(stderr, "[M::%s] ql::%lu, tl::%lu\n", __func__, ql, tl); - if(ql == 0 && tl == 0) return; - uint64_t k, ck, qk, tk, wq[2], wt[2], maxl, minl, diff, f, diff0 = 0; - if(ql > 0 && tl == 0) { - for (k = 0; k < ql; k++) { - push_trace_bp_f(sc, 3, seq_nt6_table[(uint32_t)(qstr[k])], (uint16_t)-1, 1, 1); - } - return; - } - if(ql == 0 && tl > 0) { - for (k = 0; k < tl; k++) { - push_trace_bp_f(sc, 2, (uint16_t)-1, seq_nt6_table[(uint32_t)(tstr[k])], 1, 1); - } - return; - } - if(ql == tl && ql == 1) { - if(qstr[0] == tstr[0]) push_trace_bp_f(sc, 0, (uint16_t)-1, (uint16_t)-1, 1, 1); - else push_trace_bp_f(sc, 1, seq_nt6_table[(uint32_t)(qstr[0])], seq_nt6_table[(uint32_t)(tstr[0])], 1, 1); - return; - } - - - - if(ql >= tl) { - maxl = ql; minl = tl; - } else { - maxl = tl; minl = ql; - } - f = 0; - - diff = 31; - if(diff > (maxl - minl)) { - if(diff > maxl) diff = maxl; - diff0 = diff; clear_align(*exz); - cal_exz_global(tstr, tl, qstr, ql, diff, exz); - if(is_align(*exz)) f = 1; - } - - if(!f) { - diff = 63; - if(diff > (maxl - minl)) { - if(diff > maxl) diff = maxl; - if(diff > diff0) { - diff0 = diff; clear_align(*exz); - cal_exz_global(tstr, tl, qstr, ql, diff, exz); - if(is_align(*exz)) f = 1; - } - } - } - - if(!f) { - if((maxn > maxl) && (maxe > (maxl - minl))) { - diff = maxl * e_rate; - if(diff < 1) diff = 1; - if(diff > maxe) diff = maxe; - if(diff > diff0) { - diff0 = diff; clear_align(*exz); - cal_exz_global(tstr, tl, qstr, ql, diff, exz); - if(is_align(*exz)) f = 1; - } - } - } - - // fprintf(stderr, "[M::%s] f::%lu, err::%d\n", __func__, f, exz->err); - - uint32_t on; uint16_t op; - if(f) { - - for (ck = qk = tk = 0; ck < exz->cigar.n;) { - wq[0] = qk; wt[0] = tk; - ck = pop_trace(&(exz->cigar), ck, &op, &on); - if(op!=2) qk += on; - if(op!=3) tk += on; - wq[1] = qk; wt[1] = tk; - - if(op == 0) { - push_trace_bp_f(sc, op, (uint16_t)-1, (uint16_t)-1, on, 1); - } else if(op == 1) { - for (k = 0; k < on; k++) { - push_trace_bp_f(sc, op, seq_nt6_table[(uint32_t)(qstr[wq[0]+k])], seq_nt6_table[(uint32_t)(tstr[wt[0]+k])], 1, 1); - } - } else if(op == 2) { - for (k = 0; k < on; k++) { - push_trace_bp_f(sc, op, (uint16_t)-1, seq_nt6_table[(uint32_t)(tstr[wt[0]+k])], 1, 1); - } - } else if(op == 3) { - for (k = 0; k < on; k++) { - push_trace_bp_f(sc, op, seq_nt6_table[(uint32_t)(qstr[wq[0]+k])], (uint16_t)-1, 1, 1); - } - } - } - } else { - if(ql > 0) { - op = 3; on = ql; - for (k = 0; k < on; k++) { - push_trace_bp_f(sc, op, seq_nt6_table[(uint32_t)(qstr[k])], (uint16_t)-1, 1, 1); - } - } - - if(tl > 0) { - op = 2; on = tl; - for (k = 0; k < on; k++) { - push_trace_bp_f(sc, op, (uint16_t)-1, seq_nt6_table[(uint32_t)(tstr[k])], 1, 1); - } - } - - } -} - -void cal_updated_trace_len(asg16_v *sc, uint64_t *ql, uint64_t *tl) -{ - uint64_t ck = 0, qk = 0, tk = 0; uint32_t len; uint16_t c, bq, bt; - while (ck < sc->n) { - ck = pop_trace_bp_f(sc, ck, &c, &bq, &bt, &len); - if(c != 2) qk += len; - if(c != 3) tk += len; - } - *ql = qk; *tl = tk; -} - -void gen_updated_trace(asg16_v *qcc, asg16_v *tcc, asg16_v *tcc_res, char *qstr, uint64_t ql, char *tstr, uint64_t tl, asg64_v *srt, bit_extz_t *exz, uint64_t rid) -{ - uint64_t k, ck, qk, tk, wq[2], wt[2], old_dp, dp, s, e, srt_n, si, ei, so, os, oe, *qd, *td, qs, qe, ts, te, q0, t0; - asg16_v *cc; uint32_t len; uint16_t c, bq, bt; - - srt->n = 0; - - cc = qcc; - ck = qk = tk = wq[0] = wq[1] = wt[0] = wt[1] = 0; - while (ck < cc->n) { - wq[0] = qk; wt[0] = tk; - ck = pop_trace_bp_f(cc, ck, &c, &bq, &bt, &len); - if(c != 2) qk += len; - if(c != 3) tk += len; - wq[1] = qk; wt[1] = tk; - if(c != 0) continue; - - kv_push(uint64_t, (*srt), (wq[0]<<1)); - kv_push(uint64_t, (*srt), ((wq[1]<<1)|1)); - } - - cc = tcc; - ck = qk = tk = wq[0] = wq[1] = wt[0] = wt[1] = 0; - while (ck < cc->n) { - wq[0] = qk; wt[0] = tk; - ck = pop_trace_bp_f(cc, ck, &c, &bq, &bt, &len); - if(c != 2) qk += len; - if(c != 3) tk += len; - wq[1] = qk; wt[1] = tk; - if(c != 0) continue; - - kv_push(uint64_t, (*srt), (wt[0]<<1)); - kv_push(uint64_t, (*srt), ((wt[1]<<1)|1)); - } - - // fprintf(stderr, "[M::%s] rid::%lu, ql::%lu, tl::%lu\n", __func__, rid, ql, tl); - - radix_sort_ec64(srt->a, srt->a + srt->n); - for (k = 0, dp = e = srt_n = 0, s = (uint64_t)-1; k < srt->n; k++) { - old_dp = dp; - //if a[k] is qe - if (srt->a[k]&1) --dp; - else ++dp; - - if(old_dp >= 2 && s != (uint64_t)-1) { - e = srt->a[k]>>1; - if(e > s) srt->a[srt_n++] = ((s<<32)|(e)); - } - - s = (uint64_t)-1; - if(dp >= 2) s = srt->a[k]>>1; - // if (old_dp < 2 && dp >= 2) {///old_dp < dp, a[k] is qs - // s = srt->a[k]>>1; - // } else if (old_dp >= 2 && dp < 2) {///old_dp > dp, a[k] is qe - // e = srt->a[k]>>1; - // if(e > s) { - // srt->a[srt_n++] = ((s<<32)|(e)); - // fprintf(stderr, "[M::%s] x::[%lu,\t%lu)\n", __func__, s, e); - // } - // } - } - - - // for (k = 0; k < srt_n; k++) { - // fprintf(stderr, "[M::%s] x[%lu]::[%lu,\t%u)\n", __func__, k, srt->a[k]>>32, (uint32_t)srt->a[k]); - // } - - - if(srt_n > 0) { - srt->n = srt_n; - - cc = qcc; - k = ck = qk = tk = wq[0] = wq[1] = wt[0] = wt[1] = 0; - while (ck < cc->n) { - wq[0] = qk; wt[0] = tk; - ck = pop_trace_bp_f(cc, ck, &c, &bq, &bt, &len); - if(c != 2) qk += len; - if(c != 3) tk += len; - wq[1] = qk; wt[1] = tk; - if(c != 0) continue; - si = wq[0]; ei = wq[1]; - so = wt[0]; ///eo = wt[1]; - - for (; (k > 0) && ((k >= srt_n) || (((uint32_t)(srt->a[k])) > si)); k--); - for (; k < srt_n; k++) { - s = srt->a[k]>>32; e = (uint32_t)(srt->a[k]); - if(s >= ei) break; - if(s >= si && e <= ei) { - os = so + s - si; - oe = so + e - si; - kv_push(uint64_t, (*srt), ((os<<32)|(oe))); - } - } - } - assert(srt->n == (srt_n<<1)); - - cc = tcc; - k = ck = qk = tk = wq[0] = wq[1] = wt[0] = wt[1] = 0; - while (ck < cc->n) { - wq[0] = qk; wt[0] = tk; - ck = pop_trace_bp_f(cc, ck, &c, &bq, &bt, &len); - if(c != 2) qk += len; - if(c != 3) tk += len; - wq[1] = qk; wt[1] = tk; - if(c != 0) continue; - si = wt[0]; ei = wt[1]; - so = wq[0]; ///eo = wq[1]; - - for (; (k > 0) && ((k >= srt_n) || (((uint32_t)(srt->a[k])) > si)); k--); - for (; k < srt_n; k++) { - s = srt->a[k]>>32; e = (uint32_t)(srt->a[k]); - // fprintf(stderr, "######[M::%s] t[%lu]::[%lu,\t%lu) i::[%lu,\t%lu)\n", __func__, k, s, e, si, ei); - if(s >= ei) break; - if(s >= si && e <= ei) { - os = so + s - si; - oe = so + e - si; - kv_push(uint64_t, (*srt), ((os<<32)|(oe))); - // fprintf(stderr, "[M::%s] ******\n", __func__); - } - } - } - // if(!(srt->n == (srt_n*3))) { - // fprintf(stderr, "[M::%s] rid::%lu, srt_n::%lu, srt->n::%lu\n", __func__, rid, srt_n, (uint64_t)srt->n); - // } - assert(srt->n == (srt_n*3)); - - - tcc_res->n = 0; ///reset tcc - qd = srt->a + srt_n; td = srt->a + srt_n + srt_n; uint64_t nl = 0;///, dbg_ql, dbg_tl; - for (k = q0 = t0 = 0; k < srt_n; k++) { - qs = qd[k]>>32; qe = (uint32_t)qd[k]; - ts = td[k]>>32; te = (uint32_t)td[k]; - nl += qs - qe; - // assert((qe - qs) == (te - ts)); - // assert(!memcmp(qstr + qs, tstr + ts, sizeof((*qstr))*(qe - qs))); - - // if(t0 > ts || q0 > qs) { - // fprintf(stderr, "[M::%s] rid::%lu, ql::%lu, tl::%lu\n", __func__, rid, ql, tl); - // } - // fprintf(stderr, "[M::%s] qseq::[%lu,%lu), ql::%lu, tseq::[%lu,%lu), tl::%lu\n", __func__, t0, ts, tl, q0, qs, ql); - - gen_cc_fly(tcc_res, tstr + t0, ts - t0, qstr + q0, qs - q0, exz, 0.25, MAX_SIN_L, MAX_SIN_E); - - // cal_updated_trace_len(tcc_res, &dbg_ql, &dbg_tl); - // assert(dbg_ql == ts && dbg_tl == qs); - - // fprintf(stderr, "******\n"); - - push_trace_bp_f(tcc_res, 0, (uint16_t)-1, (uint16_t)-1, qe - qs, 1); - - // cal_updated_trace_len(tcc_res, &dbg_ql, &dbg_tl); - // assert(dbg_ql == te && dbg_tl == qe); - - q0 = qe; t0 = te; - } - - qs = ql; ts = tl; - // fprintf(stderr, "[M::%s] qseq::[%lu,%lu), ql::%lu, tseq::[%lu,%lu), tl::%lu\n", __func__, t0, ts, tl, q0, qs, ql); - gen_cc_fly(tcc_res, tstr + t0, ts - t0, qstr + q0, qs - q0, exz, 0.25, MAX_SIN_L, MAX_SIN_E); - // if(!(dbg_ql == ts && dbg_tl == qs)) { - // fprintf(stderr, "[M::%s] rid::%lu, qseq::[%lu,%lu), ql::%lu, tseq::[%lu,%lu), tl::%lu\n", __func__, rid, t0, ts, tl, q0, qs, ql); - // } - // cal_updated_trace_len(tcc_res, &dbg_ql, &dbg_tl); - // assert(dbg_ql == ts && dbg_tl == qs); - - // fprintf(stderr, "[M::%s] srt_n::%lu, nl::%lu, ql::%lu, tl::%lu\n", __func__, srt_n, nl, ql, tl); - } else { - gen_cc_fly(tcc_res, tstr, tl, qstr, ql, exz, 0.25, MAX_SIN_L, MAX_SIN_E); - } -} - -void update_scb(All_reads *R_INF, asg16_v *scc, asg16_v *scb, asg16_v *scb_res, UC_Read *qu, UC_Read *tu, asg64_v *srt, bit_extz_t *exz, uint64_t rid) -{ - char *qstr = NULL, *tstr = NULL; uint64_t ql = 0, tl = 0; - uint64_t ck, qk, tk, k, wq[2], wt[2]; uint32_t len; uint16_t c, bq, bt; - gen_ori_seq0(qu->seq, qu->length, tu, scb, rid); ///tstr = tu->seq; tl = tu->length; - - ck = qk = tk = 0; ql = qu->length; - while (ck < scc->n) { - wq[0] = qk; wt[0] = tk; - ck = pop_trace_bp_f(scc, ck, &c, &bq, &bt, &len); - if(c != 2) qk += len; - if(c != 3) tk += len; - wq[1] = qk; wt[1] = tk; - } - assert(qk == ql); - tl = tk; resize_UC_Read(qu, ql + tl); - qstr = qu->seq; tstr = qu->seq + ql; - - ck = 0; qk = tk = 0; - while (ck < scc->n) { - wq[0] = qk; wt[0] = tk; - ck = pop_trace_bp_f(scc, ck, &c, &bq, &bt, &len); - if(c != 2) qk += len; - if(c != 3) tk += len; - wq[1] = qk; wt[1] = tk; - // if(xk > (uint32_t)p->z.length) fprintf(stderr, "[M::%s] xk::%u, len::%u, c::%u, rid::%ld\n", __func__, xk, (uint32_t)p->z.length, c, i); - if(c == 0) { - memcpy(tstr + wt[0], qstr + wq[0], (wq[1]-wq[0])*sizeof((*qstr))); - } else if(c == 1 || c == 2) { - for (k = wt[0]; k < wt[1]; k++) tstr[k] = s_H[bt]; - } - // if(i == 700) fprintf(stderr, "|%u%c(%c)(x::%u)(y::%u)", len, cm[c], ((c==1)||(c==2))?(cc[b]):('*'), wx[1], wy[1]); // s_H - } - - qstr = tstr; ql = tl; - tstr = tu->seq; tl = tu->length; - - // fprintf(stderr, "\n[M::%s] ql::%lu, tl::%lu, rid::%lu\n", __func__, ql, tl, rid); - - gen_updated_trace(scc, scb, scb_res, qstr, ql, tstr, tl, srt, exz, rid); - - - - ///debug - // resize_UC_Read(tu, ql + tl); - // memcpy(tu->seq + tl, qstr, ql); tstr = tu->seq; qstr = tu->seq + tl; - - // resize_UC_Read(qu, ql + tl); - // memcpy(qu->seq, tu->seq, ql + tl); tstr = qu->seq; qstr = qu->seq + tl; - - // gen_ori_seq0(qstr, ql, tu, scb_res, rid); - // assert(memcmp(tstr, tu->seq, tl) == 0); - -} - -uint32_t is_well_cal(asg64_v *idx, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1, int64_t ql, int64_t occ_exact) -{ - ma_hit_t_alloc *paf = NULL; uint64_t k, s, e, vn; ma_hit_t *z; idx->n = 0; - int64_t dp, old_dp, st = 0, ed; - - paf = in0; - for (k = 0; k < paf->length; k++) { - z = &(paf->buffer[k]); - s = ((uint32_t)(z->qns)); e = z->qe; - kv_push(uint64_t, (*idx), (s<<1)); - kv_push(uint64_t, (*idx), (e<<1)|1); - } - - paf = in1; - for (k = 0; k < paf->length; k++) { - z = &(paf->buffer[k]); - s = ((uint32_t)(z->qns)); e = z->qe; - kv_push(uint64_t, (*idx), (s<<1)); - kv_push(uint64_t, (*idx), (e<<1)|1); - } - - radix_sort_ec64(idx->a, idx->a + idx->n); vn = idx->n; - for (k = 0, dp = 0, st = ed = 0; k < vn; ++k) { - old_dp = dp; - ///if a[j] is qe - if (idx->a[k]&1) --dp; - else ++dp; - - ed = idx->a[k]>>1; - if((ed > st) && ((old_dp + 1) < occ_exact)) return 0;///+1 for self - - st = ed; - } - - - ed = ql; old_dp = dp; - if((ed > st) && ((old_dp + 1) < occ_exact)) return 0;///+1 for self - - return 1; -} - -static void worker_hap_dc_ec0(void *data, long i, int tid) -{ - // if(i == 6) fprintf(stderr, "-mm-[M::%s]\tqn::%u::%.*s\tf[i]::%u\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i), scc.f[i]); - if(scc.f[i]) { - scc.a[i].n = 0; sca.a[i].n = 0; - // push_trace_bp(&(scc.a[i]), 0, (uint16_t)-1, Get_READ_LENGTH(R_INF, i), 0); - push_trace_bp_f(&(scc.a[i]), 0, (uint16_t)-1, (uint16_t)-1, Get_READ_LENGTH(R_INF, i), 0); - return; - } - ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); - uint32_t high_occ = asm_opt.hom_cov * (2.0 - HA_KMER_GOOD_RATIO); - uint32_t low_occ = asm_opt.hom_cov * HA_KMER_GOOD_RATIO; - asg64_v buf0; overlap_region *aux_o = NULL; uint32_t qlen = 0; - // overlap_region *aux_o = NULL; asg64_v buf0; - - // gen_ovlst_paf(&(R_INF.paf[i]), &(R_INF.reverse_paf[i]), &(b->v64)); - // if(i != 181) return; - - // fprintf(stderr, "-mm-[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); - - recover_UC_Read(&b->self_read, &R_INF, i); qlen = b->self_read.length; - - - /** - if(is_well_cal(&b->v64, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), b->self_read.length, 4)) { - // aux_o = h_ec_lchain_re1(b->ab, i, &b->self_read, &b->ovlp_read, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, &b->exz, &b->v16, &b->v64, 0.02, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 0, 2, UINT32_MAX, &(R_INF.paf[i]), &(R_INF.reverse_paf[i])); - aux_o = h_ec_lchain_re2(b->ab, i, &b->self_read, &b->ovlp_read, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, &b->exz, &b->v16, &b->v64, 0.02, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 0, 2, UINT32_MAX, &(R_INF.paf[i]), &(R_INF.reverse_paf[i])); - } else { - aux_o = h_ec_lchain_re3(b->ab, i, &b->self_read, &b->ovlp_read, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, &b->exz, &b->v16, &b->v64, 0.02, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 0, 2, UINT32_MAX, &(R_INF.paf[i]), &(R_INF.reverse_paf[i])); - // fprintf(stderr, "[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); - } - **/ - aux_o = h_ec_lchain_re2(b->ab, i, &b->self_read, &b->ovlp_read, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, &b->exz, &b->v16, &b->v64, 0.02, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 0, 2, UINT32_MAX, &(R_INF.paf[i]), &(R_INF.reverse_paf[i])); - - ////for debug - // scc.a[i].n = 0; - // push_trace_bp(&(scc.a[i]), 0, (uint16_t)-1, Get_READ_LENGTH(R_INF, i), 0); - - // return; - - // aux_o = h_ec_lchain_re(b->ab, i, b->self_read.seq, b->self_read.length, &b->ovlp_read, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, &b->exz, &b->v16, 0.02, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 0, 2, UINT32_MAX, &(R_INF.paf[i]), &(R_INF.reverse_paf[i])); - - b->cnt[0] += b->self_read.length; - - copy_asg_arr(buf0, b->sp); - rphase_hc(&b->olist, &R_INF, &b->hap, &b->self_read, &b->ovlp_read, &b->pidx, &b->v64, &buf0, 0, WINDOW_MAX_SIZE, b->self_read.length, 1/**, 1**/, i, (asm_opt.is_ont)?HPC_PL:0, asm_opt.is_ont, ((asm_opt.is_ont)?&(b->clist.chainDP):NULL), ((asm_opt.is_sc)?&(b->v8q):NULL), ((asm_opt.is_sc)?&(b->v8t):NULL), (asm_opt.is_ont)?1:0); - copy_asg_arr(b->sp, buf0); - - copy_asg_arr(buf0, b->sp); - b->cnt[1] += wcns_gen(&b->olist, &R_INF, &b->self_read, &b->ovlp_read, &b->exz, &b->pidx, &b->v64, &buf0, 0, 512, b->self_read.length, 3, 0.500001, aux_o, &b->v32, &b->cns, 256, i); - copy_asg_arr(b->sp, buf0); - - push_nec_re(aux_o, &(scc.a[i])); - update_scb(&R_INF, &(scc.a[i]), &(scb.a[i]), &(sca.a[i]), &b->self_read, &b->ovlp_read, &b->v64, &b->exz, i); - - push_ne_ovlp(&(R_INF.paf[i]), &b->olist, 1, &R_INF, &(scc.a[i])/**, i, &b->self_read, &b->ovlp_read**/); - push_ne_ovlp(&(R_INF.reverse_paf[i]), &b->olist, 2, &R_INF, NULL/**, i, NULL, NULL**/); - - check_well_cal(&(scc.a[i]), &b->v64, &(R_INF.paf[i].is_fully_corrected), &(R_INF.paf[i].is_abnormal), qlen, (MIN_COVERAGE_THRESHOLD*2), &(R_INF.paf[i])); - R_INF.trio_flag[i] = AMBIGU; - - refresh_ec_ovec_buf_t0(b, REFRESH_N); -} - -void get_origin_ec_coor(asg16_v *ec, uint64_t *ts, uint64_t *te) -{ - uint64_t ts0 = *ts, te0 = *te, qk = 0, tk = 0, ck = 0, wq[2], wt[2]; uint16_t op, bq, bt, f = 0; uint32_t cl; - while (ck < ec->n) { - wq[0] = qk; wt[0] = tk; - ck = pop_trace_bp_f(ec, ck, &op, &bq, &bt, &cl); - if(op != 2) qk += cl; - if(op != 3) tk += cl; - wq[1] = qk; wt[1] = tk; - if((op == 0) && (wt[0] <= ts0) && (wt[1] >= te0)) { - (*ts) = wq[0] + ts0 - wt[0]; - (*te) = wq[0] + te0 - wt[0]; - f = 1; - break; - } - } - assert(f); -} - -static void update_scb0(void *data, long i, int tid) -{ - if(sca.a[i].n) { - kv_resize(uint16_t, scb.a[i], sca.a[i].n); scb.a[i].n = sca.a[i].n; - memcpy(scb.a[i].a, sca.a[i].a, scb.a[i].n*sizeof((*(sca.a[i].a)))); - } - - // return; - - if(!scc.f[i]) return; - - ma_hit_t_alloc *ov, *os; uint64_t k, kr, qn, tn, ql, tl, qs, qe, ts, te; ma_hit_t *z, *r; - uint64_t ck; uint16_t op, bq, bt; uint32_t cl; - - ov = &(R_INF.paf[i]); - for (k = 0; k < ov->length; k++) { - z = &(ov->buffer[k]); - qn = z->qns>>32; tn = z->tn; - if(scc.f[tn]) continue; - - os = &(R_INF.paf[tn]); - for (kr = 0; kr < os->length; kr++) { - if(os->buffer[kr].tn == qn) { - r = &(os->buffer[kr]); - break; - } - } - if(kr >= os->length) continue; - // if(!(r->el)) continue; - - qs = r->ts; qe = r->te; - ts = (uint32_t)r->qns; te = r->qe; - z->el = r->el; z->rev = r->rev; z->ml = r->ml; z->no_l_indel = r->no_l_indel; - if(z->el) { - get_origin_ec_coor(&(scc.a[tn]), &ts, &te); - } - - z->qns = qn; - z->qns = z->qns << 32; - if(z->rev) { - ql = Get_READ_LENGTH(R_INF, qn); - tl = ck = 0; - while (ck < scc.a[tn].n) { - ck = pop_trace_bp_f(&(scc.a[tn]), ck, &op, &bq, &bt, &cl); - if(op != 2) tl += cl; - } - z->qns = z->qns | (ql - qe); - z->qe = ql - qs; - z->ts = tl - te; - z->te = tl - ts; - } else { - z->qns = z->qns | qs; - z->qe = qe; - z->ts = ts; - z->te = te; - } - } -} - -void dbg_rsc(char *str0, uint64_t l0, char *str1, uint64_t l1, asg16_v *sc, char *real, uint32_t id) -{ - uint64_t ck, xk, yk, k, wx[2], wy[2]; uint32_t len; uint16_t c, bq, bt; - - ck = xk = yk = 0; - while (ck < sc->n) { - wx[0] = xk; wy[0] = yk; - ck = pop_trace_bp_f(sc, ck, &c, &bq, &bt, &len); - if(c != 2) xk += len; - if(c != 3) yk += len; - wx[1] = xk; wy[1] = yk; - } - assert(xk == l0); - - // char cm[4], cc[4]; - // cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; - // cc[0] = 'A'; cc[1] = 'C'; cc[2] = 'G'; cc[3] = 'T'; - - ck = xk = yk = 0; - while (ck < sc->n) { - wx[0] = xk; wy[0] = yk; - ck = pop_trace_bp_f(sc, ck, &c, &bq, &bt, &len); - if(c != 2) xk += len; - if(c != 3) yk += len; - wx[1] = xk; wy[1] = yk; - - if(c == 0) { - memcpy(str0 + wx[0], str1 + wy[0], (wx[1]-wx[0])*sizeof((*str1))); - } else if(c == 1 || c == 3) { - for (k = wx[0]; k < wx[1]; k++) str0[k] = s_H[bq]; - } - // fprintf(stderr, "%u%c(%c)(x::[%lu,%ld))(y::[%lu,%ld))\n", len, cm[c], ((c==1)||(c==2))?(cc[bt]):('*'), wx[0], wx[1], wy[0], wy[1]); // s_H - } - - if(memcmp(str0, real, l0*sizeof((*str0)))) { - fprintf(stderr, "-0-[M::%s]\tid::%u\n", __func__, id); - // for (k = 0; k < l0 && str0[k] == real[k]; k++); - - // fprintf(stderr, "-0-[M::%s]\tid::%u\tk::%lu\tl0::%lu\tnc::%c\toc::%c\n", __func__, id, k, l0, str0[k], real[k]); - // exit(1); - } else { - // fprintf(stderr, "-1-[M::%s]\tid::%u\n", __func__, id); - } - -} - -static void worker_sl_ec(void *data, long i, int tid) -{ - // if(i != 0) return; - - sl_v *p = &(((sl_v*)data)[tid]); uint8_t *oa = NULL; char *na = NULL; uint64_t tqual, wqual; - uint32_t ci = 0, len, xk, yk, wx[2], wy[2], k, Nn, yn = 0, tot_e; uint16_t c, bq, bt; - - - ci = 0; xk = yk = 0; tot_e = 0; - while (ci < scc.a[i].n) { - // ci = pop_trace_bp(&scc.a[i], ci, &c, &b, &len); - ci = pop_trace_bp_f(&scc.a[i], ci, &c, &bq, &bt, &len); - if(c != 3) yk += len; - if(c != 0) tot_e += len; - // fprintf(stderr, "|%u%c(%c)", len, cm[c], ((c==1)||(c==2))?(cc[b]):('*')); // s_H - } - if(tot_e == 0) return;///no change - - yn = yk; yk++; kv_resize(char, (*p), yk); p->a[yn] = '\0'; - recover_UC_Read(&p->z, &R_INF, i); ///b->z.length - - - // char cm[4], cc[4]; - // cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; - // cc[0] = 'A'; cc[1] = 'C'; cc[2] = 'G'; cc[3] = 'T'; - - ci = 0; xk = yk = 0; Nn = 0; - while (ci < scc.a[i].n) { - wx[0] = xk; wy[0] = yk; - // ci = pop_trace_bp(&scc.a[i], ci, &c, &b, &len); - ci = pop_trace_bp_f(&scc.a[i], ci, &c, &bq, &bt, &len); - if(c != 2) xk += len; - if(c != 3) yk += len; - wx[1] = xk; wy[1] = yk; - // if(xk > (uint32_t)p->z.length) fprintf(stderr, "[M::%s] xk::%u, len::%u, c::%u, rid::%ld\n", __func__, xk, (uint32_t)p->z.length, c, i); - if(c == 0) { - // memcpy(p->a + wy[0], p->z.seq + wx[0], (wx[1]-wx[0])*sizeof((*(p->a)))); - for (; wx[0] < wx[1]; wx[0]++, wy[0]++) { - p->a[wy[0]] = p->z.seq[wx[0]]; - if(p->a[wy[0]] == 'N') Nn++; - } - } else if(c == 1 || c == 2) { - for (k = wy[0]; k < wy[1]; k++) { - p->a[k] = s_H[bt]; - if(p->a[k] == 'N') Nn++; - } - } - - // if(i == 700) fprintf(stderr, "|%u%c(%c)(x::%u)(y::%u)", len, cm[c], ((c==1)||(c==2))?(cc[b]):('*'), wx[1], wy[1]); // s_H - } - - // if(i == 700) fprintf(stderr, "|\n"); - if(asm_opt.is_sc) retrive_bqual(&(p->q), NULL, i, -1, -1, 0, sc_bn); - - - if (R_INF.read_size[i] < yn) { - R_INF.read_size[i] = yn; - REALLOC(R_INF.read_sperate[i], R_INF.read_size[i]/4+1); - if(asm_opt.is_sc) REALLOC(R_INF.rsc[i], ((R_INF.read_size[i]/sc_bn) + ((R_INF.read_size[i]%sc_bn)?1:0))); - } - R_INF.read_length[i] = yn; - // if(Nn > 0) fprintf(stderr, "[M::%s] Nn->%u\n", __func__, Nn); - - // for (k = 0; k < yn; k++) { - // c = seq_nt6_table[(uint8_t)p->a[k]]; - // if (c >= 4) { - // fprintf(stderr, "[M::%s] Nn->%u, yn::%u, xn::%lld, k::%u, str::%c, c::%u, rid::%ld\n", __func__, Nn, yn, p->z.length, k, p->a[k], c, i); - // } - // } - - - ///debug - // resize_UC_Read(&p->z, p->z.length * 2); - // dbg_rsc(p->z.seq + p->z.length, p->z.length, p->a, yn, &(scc.a[i]), p->z.seq, i); - - - ha_compress_base(Get_READ(R_INF, i), p->a, yn, &R_INF.N_site[i], Nn); - if(asm_opt.is_sc) { - oa = p->q.a; na = p->a; - ci = 0; xk = yk = 0; Nn = 0; - while (ci < scc.a[i].n) { - wx[0] = xk; wy[0] = yk; - ci = pop_trace_bp_f(&scc.a[i], ci, &c, &bq, &bt, &len); - if(c != 2) xk += len; - if(c != 3) yk += len; - wx[1] = xk; wy[1] = yk; - if(c == 0 || c == 1) { - memcpy(na + wy[0], oa + wx[0], (wx[1]-wx[0])*sizeof((*oa))); - } else if(c == 2) { - get_wqual(i, wx[0], 0, NULL, oa, sc_wn, &tqual, &wqual); - for (k = wy[0]; k < wy[1]; k++) na[k] = wqual; - } - } - assert(yk == yn); - ha_compress_qual_bit(Get_QUAL(R_INF, i), na, yn, sc_bn); - } -} - -uint64_t cal_ec_multiple(ec_ovec_buf_t *b, uint64_t n_thre, uint64_t n_a, uint64_t *r_base) -{ - double tt0 = yak_realtime_0(); - uint64_t k, num_base = 0, num_correct = 0; (*r_base) = 0; - - if(!(scc.a)) { - scc.n = scc.m = n_a; CALLOC(scc.a, n_a); CALLOC(scc.f, n_a); - } - - if(!(scb.a)) { - scb.n = scb.m = n_a; CALLOC(scb.a, n_a); - } - - for (k = 0; k < n_thre; ++k) b->a[k].cnt[0] = b->a[k].cnt[1] = 0; - - kt_for(n_thre, worker_hap_ec, b, n_a);///debug_for_fix - - for (k = 0; k < n_thre; ++k) { - num_base += b->a[k].cnt[0]; - num_correct += b->a[k].cnt[1]; - } - - // fprintf(stderr, "\n[M::%s] # reads->%lu\n", __func__, n_a); - // fprintf(stderr, "[M::%s] # input bases->%lu\n", __func__, num_base); - // fprintf(stderr, "[M::%s] # corrected bases->%lu\n", __func__, num_correct); - // fprintf(stderr, "[M::%s::%.3f] running time\n", __func__, yak_realtime_0()-tt0); - fprintf(stderr, "[M::pec::%.3f] # bases: %lu; # corrected bases: %lu\n", yak_realtime_0()-tt0, num_base, num_correct); - - (*r_base) = num_base; - return num_correct; -} - -void cal_update_ec_multiple(ec_ovec_buf_t *b, uint64_t n_thre, uint64_t n_a) -{ - double tt0 = yak_realtime_0(); - uint64_t k, num_ec_o = 0, num_nec_o = 0; - - for (k = 0; k < n_thre; ++k) b->a[k].cnt[0] = b->a[k].cnt[1] = 0; - - kt_for(n_thre, worker_update_dc_ec, b, n_a);///debug_for_fix - - for (k = 0; k < n_thre; ++k) { - num_ec_o += b->a[k].cnt[0]; num_nec_o += b->a[k].cnt[1]; - } - - fprintf(stderr, "[M::pec::%.3f] # exact o: %lu; # non-exact o: %lu\n", yak_realtime_0()-tt0, num_ec_o, num_nec_o); -} - - -void ha_print_ovlp_stat_1(ec_ovec_buf_t *b, uint64_t n_thre, uint64_t n_a) -{ - double tt0 = yak_realtime_0(); - uint64_t k, forward, reverse, strong, weak, exact, no_l_indel; - - forward = reverse = strong = weak = exact = no_l_indel = 0; - - ///calculate overlaps - for (k = 0; k < n_thre; ++k) { - b->a[k].cnt[0] = b->a[k].cnt[1] = b->a[k].cnt[2] = b->a[k].cnt[3] = b->a[k].cnt[4] = b->a[k].cnt[5] = 0; - } - - kt_for(n_thre, worker_hap_dc_ec_gen, b, n_a); - - for (k = 0; k < n_thre; ++k) { - forward += b->a[k].cnt[0]; - reverse += b->a[k].cnt[1]; - strong += b->a[k].cnt[2]; - weak += b->a[k].cnt[3]; - exact += b->a[k].cnt[4]; - no_l_indel += b->a[k].cnt[5]; - } - - fprintf(stderr, "[M::%s] # overlaps: %lu\n", __func__, forward); - fprintf(stderr, "[M::%s] # strong overlaps: %lu\n", __func__, strong); - fprintf(stderr, "[M::%s] # weak overlaps: %lu\n", __func__, weak); - fprintf(stderr, "[M::%s] # exact overlaps: %lu\n", __func__, exact); // this seems not right - fprintf(stderr, "[M::%s] # inexact overlaps: %lu\n", __func__, forward - exact); - fprintf(stderr, "[M::%s] # overlaps without large indels: %lu\n", __func__, no_l_indel); - fprintf(stderr, "[M::%s] # reverse overlaps: %lu\n", __func__, reverse); - fprintf(stderr, "[M::%s] # running time: %.3f\n", __func__, yak_realtime_0()-tt0); - - // fprintf(stderr, "\n[M::%s] # reads->%lu\n", __func__, n_a); - // fprintf(stderr, "[M::%s] # corrected reads->%lu\n", __func__, rb); - // fprintf(stderr, "[M::%s] # uncorrected reads->%lu\n", __func__, urb); - // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime_0()-tt0); -} - -void ha_print_ovlp_stat_0(ec_ovec_buf_t *b, uint64_t n_thre, uint64_t n_a) -{ - double tt0 = yak_realtime_0(); - uint64_t k, forward, reverse, strong, weak, exact, no_l_indel; - - forward = reverse = strong = weak = exact = no_l_indel = 0; - - ///calculate overlaps - for (k = 0; k < n_thre; ++k) { - b->a[k].cnt[0] = b->a[k].cnt[1] = b->a[k].cnt[2] = b->a[k].cnt[3] = b->a[k].cnt[4] = b->a[k].cnt[5] = 0; - } - - kt_for(n_thre, worker_hap_dc_ec_gen_new_idx, b, n_a); - - for (k = 0; k < n_thre; ++k) { - forward += b->a[k].cnt[0]; - reverse += b->a[k].cnt[1]; - strong += b->a[k].cnt[2]; - weak += b->a[k].cnt[3]; - exact += b->a[k].cnt[4]; - no_l_indel += b->a[k].cnt[5]; - } - - fprintf(stderr, "[M::%s] # overlaps: %lu\n", __func__, forward); - fprintf(stderr, "[M::%s] # strong overlaps: %lu\n", __func__, strong); - fprintf(stderr, "[M::%s] # weak overlaps: %lu\n", __func__, weak); - fprintf(stderr, "[M::%s] # exact overlaps: %lu\n", __func__, exact); // this seems not right - fprintf(stderr, "[M::%s] # inexact overlaps: %lu\n", __func__, forward - exact); - fprintf(stderr, "[M::%s] # overlaps without large indels: %lu\n", __func__, no_l_indel); - fprintf(stderr, "[M::%s] # reverse overlaps: %lu\n", __func__, reverse); - fprintf(stderr, "[M::%s] # running time: %.3f\n", __func__, yak_realtime_0()-tt0); - - // fprintf(stderr, "\n[M::%s] # reads->%lu\n", __func__, n_a); - // fprintf(stderr, "[M::%s] # corrected reads->%lu\n", __func__, rb); - // fprintf(stderr, "[M::%s] # uncorrected reads->%lu\n", __func__, urb); - // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime_0()-tt0); -} - -uint64_t cal_sec_ec_multiple(ec_ovec_buf_t *b, uint64_t n_thre, uint64_t n_a, int64_t round) -{ - double tt0 = yak_realtime_0(); - uint64_t k, num_base, num_correct, rb, urb; - num_base = num_correct = 0; - - ////counting - rb = urb = 0; - for (k = 0; k < n_thre; ++k) b->a[k].cnt[0] = b->a[k].cnt[1] = 0; - - kt_for(n_thre, worker_hap_dc_ec, b, n_a);///debug_for_fix - - for (k = 0; k < n_thre; ++k) { - rb += b->a[k].cnt[0]; urb += b->a[k].cnt[1]; - } - - if(round >= 0) { - if(!(sca.a)) { - sca.n = sca.m = n_a; CALLOC(sca.a, n_a); - } - ////correct - - for (k = 0; k < n_thre; ++k) b->a[k].cnt[0] = b->a[k].cnt[1] = 0; - - kt_for(n_thre, worker_hap_dc_ec0, b, n_a);///debug_for_fix - - for (k = 0; k < n_thre; ++k) { - num_base += b->a[k].cnt[0]; - num_correct += b->a[k].cnt[1]; - } - - kt_for(n_thre, update_scb0, b, n_a); - } - - if(round >= 0) { - fprintf(stderr, "[M::sec::%.3f] # bases: %lu; # corrected bases: %lu; # reads: %lu; # corrected reads: %lu\n", yak_realtime_0()-tt0, num_base, num_correct, rb, urb); - } else { - fprintf(stderr, "[M::sec::%.3f] # reads: %lu; # corrected reads: %lu\n", yak_realtime_0()-tt0, rb, urb); - } - - // fprintf(stderr, "\n[M::%s] # reads->%lu\n", __func__, n_a); - // fprintf(stderr, "[M::%s] # corrected reads->%lu\n", __func__, rb); - // fprintf(stderr, "[M::%s] # uncorrected reads->%lu\n", __func__, urb); - // if(round >= 0) { - // fprintf(stderr, "[M::%s] # input bases->%lu\n", __func__, num_base); - // fprintf(stderr, "[M::%s] # corrected bases->%lu\n", __func__, num_correct); - // fprintf(stderr, "[M::%s::%.3f] ==> round %ld\n", __func__, yak_realtime_0()-tt0, round); - // } - return num_correct; -} - - -void write_ec_reads(const char *suffix_ou) -{ - uint64_t k, strl; UC_Read qstr, tstr; char *nn = NULL, *str = NULL; - init_UC_Read(&qstr); init_UC_Read(&tstr); - MALLOC(nn, strlen(suffix_ou) + strlen(asm_opt.output_file_name) + 36); - sprintf(nn, "%s.%s", asm_opt.output_file_name, suffix_ou); - FILE *ou = fopen(nn, "w"); - free(nn); - - for (k = 0; k < R_INF.total_reads; k++) { - recover_UC_Read(&qstr, &R_INF, k); - if(scb.a) { - gen_ori_seq0(qstr.seq, qstr.length, &tstr, &(scb.a[k]), k); str = tstr.seq; strl = tstr.length; - } else { - str = qstr.seq; strl = qstr.length; - } - - fwrite(">", 1, 1, ou); - fwrite(Get_NAME(R_INF, k), 1, Get_NAME_LENGTH(R_INF, k), ou); - fwrite("\n", 1, 1, ou); - fwrite(str, 1, strl, ou); - fwrite("\n", 1, 1, ou); - } - - fclose(ou); destory_UC_Read(&qstr); destory_UC_Read(&tstr); -} - - -void cal_ec_r(uint64_t n_thre, uint64_t round, uint64_t n_round, uint64_t n_a, uint64_t is_sv, uint64_t *tot_b, uint64_t *tot_e) -{ - // write_ec_reads("ec0.fa"); - - // fprintf(stderr, "[M::%s]\tn_thre::%lu, round::%lu, n_round::%lu, n_a::%lu, is_sv::%lu\n", __func__, n_thre, round, n_round, n_a, is_sv); - - ec_ovec_buf_t *b = NULL; uint64_t k, is_cr = (round&1); - (*tot_b) = (*tot_e) = 0; - - - b = gen_ec_ovec_buf_t(n_thre); - (*tot_e) += cal_ec_multiple(b, n_thre, n_a, tot_b); ///exit(1); - sl_ec_r(n_thre, n_a); - - for (k = 0; k < n_round; k++) { - (*tot_e) += cal_sec_ec_multiple(b, n_thre, n_a, k); - sl_ec_r(n_thre, n_a); - } - - cal_update_ec_multiple(b, n_thre, n_a);///update overlaps - - // if(is_sv) kt_for(n_thre, worker_hap_dc_ec, b, n_a);///update overlaps - - - if((!is_sv) || (is_sv && is_cr)) { - kt_for(n_thre, worker_hap_post_rev, b, n_a); - } - - // cal_sec_ec_multiple(b, n_thre, n_a, -1); - - // gen_sec_ec_multiple(b, n_thre, n_a); - - destroy_ec_ovec_buf_t(b); - - // write_ec_reads("ec16.fa"); - - // uint64_t z; - // for (z = 0; z < scc.n; z++) { - // if(scc.f[z]) continue; - // fprintf(stderr, "[M::%s]\tid::%lu::%.*s\n", __func__, z, (int)Get_NAME_LENGTH(R_INF, z), Get_NAME((R_INF), z)); - // } -} - -void print_ov_dbg_paf(FILE *fp, char *ref_str, char *ref_id, int32_t ref_id_n, char *qry_str, char *qry_id, int32_t qry_id_n, uint64_t rs, uint64_t re, uint64_t rl, uint64_t qs, uint64_t qe, uint64_t ql, uint64_t rev, bit_extz_t *ez, char *ezh) -{ - uint64_t ci = 0; uint16_t c; uint32_t cl; - fprintf(fp, "%.*s\t%lu\t%lu\t%lu\t", qry_id_n, qry_id, ql, qs, qe); - fprintf(fp, "%c\t", "+-"[rev]); - fprintf(fp, "%.*s\t%lu\t%lu\t%lu\t", ref_id_n, ref_id, rl, rs, re); - fprintf(fp, "255\tcg:Z:"); - while (ci < ez->cigar.n) { - ci = pop_trace(&(ez->cigar), ci, &c, &cl); - fprintf(fp, "%u%c", cl, ezh[c]); - } - fprintf(fp, "\n"); -} - -static void *worker_ov_dbg_pipeline(void *data, int step, void *in) // callback for kt_pipeline() -{ - cal_ec_r_dbg_t *p = (cal_ec_r_dbg_t*)data; char cm[4]; cm[0] = 'M'; cm[1] = 'M'; cm[2] = 'I'; cm[3] = 'D'; - // cal_ec_r_dbg_step_t - if (step == 0) { // step 1: read a block of sequences - cal_ec_r_dbg_step_t *s; CALLOC(s, 1); - s->si = p->cn; p->cn += p->chunk_size; - if(p->cn > p->n_a) p->cn = p->n_a; s->ei = p->cn; - if(s->si >= s->ei) free(s); - else return s; - } else if (step == 1) { // step 2: alignment - cal_ec_r_dbg_step_t *s = (cal_ec_r_dbg_step_t*)in; - s->buf = gen_ec_ovec_buf_t(p->n_thread); CALLOC(s->res, p->n_thread); - kt_for(p->n_thread, worker_hap_ec_dbg_paf, s, (s->ei - s->si)); - destroy_ec_ovec_buf_t(s->buf); - return s; - } else if (step == 2) { // step 3: dump - cal_ec_r_dbg_step_t *s = (cal_ec_r_dbg_step_t*)in; uint64_t k, z; bit_extz_t ez; memset(&ez, 0, sizeof(ez)); - // UC_Read qu; UC_Read tu; init_UC_Read(&qu); init_UC_Read(&tu); - for (k = 0; k < p->n_thread; k++) { - for (z = 0; z < s->res[k].n; z++) { - ez.cigar.a = s->res[k].ec.a + s->res[k].a[z].bl; ez.cigar.n = ez.cigar.m = s->res[k].a[z].cc; - - // UC_Read_resize(qu, (s->res[k].a[z].qe - ((uint32_t)s->res[k].a[z].qns))); - // recover_UC_Read_sub_region(qu.seq, ((uint32_t)s->res[k].a[z].qns), (s->res[k].a[z].qe - ((uint32_t)s->res[k].a[z].qns)), 0, &R_INF, (s->res[k].a[z].qns>>32)); - - // UC_Read_resize(tu, (s->res[k].a[z].te - s->res[k].a[z].ts)); - // recover_UC_Read_sub_region(tu.seq, s->res[k].a[z].ts, s->res[k].a[z].te - s->res[k].a[z].ts, 0, &R_INF, s->res[k].a[z].tn); - - print_ov_dbg_paf(p->fp, NULL/**qu.seq**/, Get_NAME(R_INF, (s->res[k].a[z].qns>>32)), Get_NAME_LENGTH(R_INF, (s->res[k].a[z].qns>>32)), - NULL/**tu.seq**/, Get_NAME(R_INF, (s->res[k].a[z].tn)), Get_NAME_LENGTH(R_INF, (s->res[k].a[z].tn)), (uint32_t)s->res[k].a[z].qns, s->res[k].a[z].qe, Get_READ_LENGTH(R_INF, (s->res[k].a[z].qns>>32)), s->res[k].a[z].ts, s->res[k].a[z].te, Get_READ_LENGTH(R_INF, (s->res[k].a[z].tn)), s->res[k].a[z].rev, &ez, cm); - } - free(s->res[k].a); free(s->res[k].ec.a); - } - free(s->res); free(s); ///destory_UC_Read(&qu); destory_UC_Read(&tu); - } - return 0; -} - -void cal_ec_r_dbg(uint64_t n_thre, uint64_t n_a) -{ - char *paf = NULL; MALLOC(paf, (strlen(asm_opt.output_file_name)+64)); - sprintf(paf, "%s.ovlp.paf", asm_opt.output_file_name); - - cal_ec_r_dbg_t sl; memset(&sl, 0, sizeof(sl)); - sl.n_thread = n_thre; sl.n_a = n_a; sl.chunk_size = 2000; sl.cn = 0; sl.fp = fopen(paf, "w"); - - kt_pipeline(3, worker_ov_dbg_pipeline, &sl, 3); - - fclose(sl.fp); free(paf); -} - -void destroy_cc_v(cc_v *z) -{ - uint64_t k; - for (k = 0; k < z->m; k++) free(z->a[k].a); - free(z->f); free(z->a); - z->n = z->m = 0; z->f = NULL; z->a = NULL; -} - -void cal_ov_r(uint64_t n_thre, uint64_t n_a, uint64_t new_idx) -{ - ec_ovec_buf_t *b = NULL; - b = gen_ec_ovec_buf_t(n_thre); - if(new_idx) { - // kt_for(n_thre, worker_hap_dc_ec, b, n_a);///update overlaps - destroy_cc_v(&scc); destroy_cc_v(&scb); destroy_cc_v(&sca); - - ha_print_ovlp_stat_0(b, n_thre, n_a); - } else { - ha_print_ovlp_stat_1(b, n_thre, n_a); - destroy_cc_v(&scc); destroy_cc_v(&scb); destroy_cc_v(&sca); - } - - destroy_ec_ovec_buf_t(b); -} - -void sl_ec_r(uint64_t n_thre, uint64_t n_a) -{ - sl_v *b = NULL; uint64_t k; MALLOC(b, n_thre); - for (k = 0; k < n_thre; k++) { - b[k].a = NULL; b[k].n = b[k].m = 0; - init_UC_Read(&b[k].z); kv_init(b[k].q); - } - - kt_for(n_thre, worker_sl_ec, b, n_a);///debug_for_fix - - for (k = 0; k < n_thre; k++) { - free(b[k].a); destory_UC_Read(&b[k].z); kv_destroy(b[k].q); - } - free(b); -} - -void handle_chemical_r(uint64_t n_thre, uint64_t n_a) -{ - ec_ovec_buf_t *b = NULL; uint64_t k, chem_n = 0, dedup = 0; - b = gen_ec_ovec_buf_t(n_thre); - for (k = 0; k < n_thre; ++k) { - b->a[k].cnt[0] = 0; b->a[k].cnt[1] = 0; - } - - kt_for(n_thre, worker_hap_dc_ec_chemical_r, b, n_a); - - for (k = 0; k < n_thre; ++k) { - chem_n += b->a[k].cnt[0]; - b->a[k].cnt[0] = 0; b->a[k].cnt[1] = 1; - } - - kt_for(n_thre, worker_hap_dc_ec_chemical_r, b, n_a); - - for (k = 0; k < n_thre; ++k) { - dedup += b->a[k].cnt[0]; - b->a[k].cnt[1] = 2; - } - - kt_for(n_thre, worker_hap_dc_ec_chemical_r, b, n_a); - - fprintf(stderr, "[M::%s] # chimeric reads: %lu, # arcs:: %lu\n", __func__, chem_n, dedup); - - destroy_ec_ovec_buf_t(b); -} - -void handle_chemical_arc(uint64_t n_thre, uint64_t n_a) -{ - ec_ovec_buf_t *b = NULL; uint64_t k, chem_n = 0; - b = gen_ec_ovec_buf_t(n_thre); - for (k = 0; k < n_thre; ++k) { - b->a[k].cnt[0] = 0; b->a[k].cnt[1] = 0; - } - - kt_for(n_thre, worker_hap_dc_ec_chemical_arc, b, n_a); - - for (k = 0; k < n_thre; ++k) { - chem_n += b->a[k].cnt[0]; - b->a[k].cnt[0] = 0; b->a[k].cnt[1] = 1; - } - - kt_for(n_thre, worker_hap_dc_ec_chemical_arc, b, n_a); - - fprintf(stderr, "[M::%s] # chimeric reads: %lu\n", __func__, chem_n); - - destroy_ec_ovec_buf_t(b); -} - -uint8_t* gen_chemical_arc_rf(uint64_t n_thre, uint64_t n_a) -{ - ec_ovec_buf_t *b = NULL; uint64_t k, chem_n = 0; uint8_t *ra = NULL; - b = gen_ec_ovec_buf_t(n_thre); - for (k = 0; k < n_thre; ++k) { - b->a[k].cnt[0] = 0; b->a[k].cnt[1] = 0; - } - MALLOC(ra, n_a); ///memset(ra, -1, sizeof((*ra))*n_a); - b->cr = ra; - - kt_for(n_thre, worker_hap_dc_ec_chemical_arc_mark, b, n_a); - - for (k = 0; k < n_thre; ++k) { - chem_n += b->a[k].cnt[0]; - b->a[k].cnt[0] = 0; b->a[k].cnt[1] = 1; - } - - kt_for(n_thre, worker_hap_dc_ec_chemical_arc_mark, b, n_a); - - fprintf(stderr, "[M::%s] # chimeric reads: %lu\n", __func__, chem_n); - - b->cr = NULL; destroy_ec_ovec_buf_t(b); - return ra; -} - - -void gen_hc_polish(uint64_t n_thre, ma_ug_t *ug) -{ - ec_polish_buf_t b; memset(&b, 0, sizeof(b)); b.ug = ug; - uint64_t k, z, zn; - for (k = b.idx.n = 0; k < ug->u.n; k++) { - b.idx.n += ug->u.a[k].n; - } - MALLOC(b.idx.a, b.idx.n); - for (k = zn = 0; k < ug->u.n; k++) { - for (z = 0; z < ug->u.a[k].n; z++, zn++) { - b.idx.a[zn] = (k<<32)|z; - } - } - b.p = gen_ec_ovec_buf_t(n_thre); - - kt_for(n_thre, worker_ec_polish, &b, b.idx.n); - - destroy_ec_ovec_buf_t(b.p); free(b.idx.a); +#include +#include +#include +#include +#include "Correct.h" +#include "Process_Read.h" +#include "ecovlp.h" +#include "kthread.h" +#include "htab.h" +#define HA_KMER_GOOD_RATIO 0.333 +#define E_KHIT 31 +#define CNS_DEL_E (0x7fffffffu) +#define del_cns_arc(z, arc_i) ((z).arc.a[(arc_i)].v == CNS_DEL_E) +#define CNS_DEL_V (0x1fffffffu) +#define del_cns_nn(z, nn_i) ((z).a[(nn_i)].sc == CNS_DEL_V) +#define REFRESH_N 128 +#define COV_W 3072 +#define COV_W_AC 512 +#define RES_K 19 +#define RES_W 19 +#define HC0_W 6 + +KDQ_INIT(uint32_t) + +typedef struct { + uint32_t v:31, f:1; + uint32_t sc; +} cns_arc; +typedef struct {size_t n, m, nou; cns_arc *a; } cns_arc_v; + +typedef struct { + // uint16_t c:2, t:2, f:1, sc:3; + uint32_t c:2, f:1, sc:29; + cns_arc_v arc; +}cns_t; + +typedef struct { + size_t n, m; + cns_t *a; + uint32_t si, ei, off, bn, bb0, bb1, cns_g_wl; + kdq_t(uint32_t) *q; +}cns_gfa; + +typedef struct { + // chaining and overlapping related buffers + UC_Read self_read, ovlp_read; + Candidates_list clist; + overlap_region_alloc olist; + ha_abuf_t *ab; + // int64_t num_read_base, num_correct_base, num_recorrect_base; + uint64_t cnt[6], rr; + haplotype_evdience_alloc hap; + bit_extz_t exz; + kv_ul_ov_t pidx; + asg64_v v64; + asg32_v v32; + asg16_v v16; + asg8_v v8q, v8t; + + kvec_t_u8_warp k_flag; + st_mt_t sp; + cns_gfa cns; +} ec_ovec_buf_t0; + +typedef struct { + ec_ovec_buf_t0 *a; + uint32_t n, rev; + uint8_t *cr; +} ec_ovec_buf_t; + +typedef struct { + ec_ovec_buf_t *p; + asg64_v idx; + ma_ug_t *ug; +} ec_polish_buf_t; + +typedef struct { + uint32_t n_thread, n_a, chunk_size, cn; + FILE *fp; +} cal_ec_r_dbg_t; + +typedef struct { + ma_hit_t *a; + size_t n, m; + asg16_v ec; +} r_dbg_step_res_t; + +typedef struct { // data structure for each step in kt_pipeline() + ec_ovec_buf_t *buf; + r_dbg_step_res_t *res; + uint32_t si, ei; +} cal_ec_r_dbg_step_t; + +ec_ovec_buf_t* gen_ec_ovec_buf_t(uint32_t n); +void destroy_ec_ovec_buf_t(ec_ovec_buf_t *p); + + +#define generic_key(x) (x) +KRADIX_SORT_INIT(ec16, uint16_t, generic_key, 2) +KRADIX_SORT_INIT(ec32, uint32_t, generic_key, 4) +KRADIX_SORT_INIT(ec64, uint64_t, generic_key, 8) + +#define kdq_clear(q) ((q)->count = (q)->front = 0) + +typedef struct {size_t n, m; asg16_v *a; uint8_t *f; } cc_v; +cc_v scc = {0, 0, NULL, NULL}; +cc_v scb = {0, 0, NULL, NULL}; +cc_v sca = {0, 0, NULL, NULL}; + +typedef struct {size_t n, m; char *a; UC_Read z; asg8_v q;} sl_v; + + +void h_ec_lchain(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, + int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t mcopy_num, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut, uint64_t ocv_w, uint8_t is_raw_chain); +void h_ec_lchain_hybrid(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres_h, double bw_thres_l, + int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t mcopy_num, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut, uint64_t ocv_w, uint64_t ti_cut, uint8_t is_raw_chain); + +void h_ec_lchain_amz(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, + int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut, uint64_t ocv_w); +void h_ec_lchain_re_gen(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, ha_pt_t *ha_idx, All_reads *rref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, + int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, + int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip, UC_Read *tu, asg64_v *oidx, asg16_v *scc); +void h_ec_lchain_re_gen3(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, ha_pt_t *ha_idx, All_reads *rref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, + int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, + int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip, UC_Read *tu, asg64_v *oidx, asg16_v *scc); +uint64_t get_mz1(const char *str, int len, int w, int k, uint32_t rid, int is_hpc, ha_abuf_t *ab, const void *hf, ha_pt_t *ha_idx, int sample_dist, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, ha_pt_t *pt, int min_freq, int32_t dp_min_len, float dp_e, st_mt_t *mt, int32_t ws, int32_t is_unique, void *km, uint64_t beg_i); +void get_pi_ec_chain(ha_abuf_t *ab, uint64_t rid, uint64_t rl, uint32_t tid, char* ts, uint64_t tl, uint64_t mz_w, uint64_t mz_k, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, + int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, /**uint32_t is_accurate,**/ uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, + int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip); +void set_lchain_dp_op(uint32_t is_accurate, uint32_t mz_k, int64_t *max_skip, int64_t *max_iter, int64_t *max_dis, double *chn_pen_gap, double *chn_pen_skip, int64_t *quick_check); +void h_ec_lchain_re_gen_srt(ha_abuf_t *ab, ha_pt_t *ha_idx, overlap_region_alloc *olst, Candidates_list *cl); +uint64_t h_ec_lchain_re_gen_qry(ha_abuf_t *ab, uint64_t *k, uint64_t *l, uint64_t *i, uint64_t *idx_a, uint64_t idx_n, uint64_t *tid, uint64_t *trev); +uint64_t h_ec_lchain_re_chn(ha_abuf_t *ab, uint64_t si, uint64_t ei, uint32_t rid, char* rs, uint64_t rl, uint64_t tid, char* ts, uint64_t tl, uint64_t trev, uint64_t mz_w, uint64_t mz_k, overlap_region_alloc *olst, Candidates_list *cl, double bw_thres, + int apend_be, uint64_t max_cnt, uint64_t min_cnt, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip, tiny_queue_t *tq, asg16_v *scc, int64_t *n, int64_t *zn); +overlap_region* h_ec_lchain_fast(ha_abuf_t *ab, uint32_t rid, UC_Read *qu, UC_Read *tu, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v *buf, asg64_v *srt_i, double bw_thres, + int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1, double sh); +void h_ec_lchain_fast_new(ha_abuf_t *ab, uint32_t rid, UC_Read *qu, UC_Read *tu, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v *buf, asg64_v *srt_i, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1, double sh); +void gen_chain_clus(ha_abuf_t *ab, overlap_region_alloc *ol, Candidates_list *cl, asg32_v *ik); +void srt_olst(overlap_region_alloc* ol); + +ec_ovec_buf_t* gen_ec_ovec_buf_t(uint32_t n) +{ + uint32_t k; ec_ovec_buf_t0 *z = NULL; + ec_ovec_buf_t *p = NULL; CALLOC(p, 1); + p->n = n; CALLOC(p->a, p->n); + for (k = 0; k < p->n; k++) { + z = &(p->a[k]); + init_UC_Read(&z->self_read); + init_UC_Read(&z->ovlp_read); + init_Candidates_list(&z->clist); + init_overlap_region_alloc(&z->olist); + + // init_fake_cigar(&(z->tmp.f_cigar)); + // memset(&(z->tmp.w_list), 0, sizeof(z->tmp.w_list)); + // CALLOC(z->tmp.w_list.a, 1); z->tmp.w_list.n = z->tmp.w_list.m = 1; + + // kv_init(z->b_buf.a); + // kv_init(z->r_buf.a); + kv_init(z->k_flag.a); + kv_init(z->sp); + kv_init(z->pidx); + kv_init(z->v64); + kv_init(z->v32); + kv_init(z->v16); + kv_init(z->v8q); + kv_init(z->v8t); + init_bit_extz_t(&(z->exz), 31); + + z->ab = ha_abuf_init(); + + InitHaplotypeEvdience(&z->hap); + z->cns.q = kdq_init(uint32_t); + } + + return p; +} + +void destroy_cns_gfa(cns_gfa *p) +{ + size_t k; + for (k = 0; k < p->m; k++) { + kv_destroy(p->a[k].arc); + } + free(p->a); kdq_destroy(uint32_t, p->q); +} + +void destroy_ec_ovec_buf_t(ec_ovec_buf_t *p) +{ + uint32_t k; ec_ovec_buf_t0 *z = NULL; + for (k = 0; k < p->n; k++) { + z = &(p->a[k]); z->rr = 0; + destory_UC_Read(&z->self_read); + destory_UC_Read(&z->ovlp_read); + destory_Candidates_list(&z->clist); + destory_overlap_region_alloc(&z->olist); + + // destory_fake_cigar(&(z->tmp.f_cigar)); + // free(z->tmp.w_list.a); free(z->tmp.w_list.c.a); + + // kv_destroy(z->r_buf.a); + kv_destroy(z->k_flag.a); + kv_destroy(z->sp); + kv_destroy(z->pidx); + kv_destroy(z->v64); + kv_destroy(z->v32); + kv_destroy(z->v16); + kv_destroy(z->v8q); + kv_destroy(z->v8t); + destroy_bit_extz_t(&(z->exz)); + + ha_abuf_destroy(z->ab); + + destoryHaplotypeEvdience(&z->hap); + destroy_cns_gfa(&(z->cns)); + + } + free(p->a); free(p->cr); free(p); + + // fprintf(stderr, "[M::%s-chains] #->%lld\n", __func__, asm_opt.num_bases); + // fprintf(stderr, "[M::%s-passed-chains-0] #->%lld\n", __func__, asm_opt.num_corrected_bases); + // fprintf(stderr, "[M::%s-cis-chains-1] #->%lld\n", __func__, asm_opt.num_recorrected_bases); +} + +inline void refresh_ec_ovec_buf_t0(ec_ovec_buf_t0 *z, uint64_t n) +{ + z->rr++; + if((z->rr%n) == 0) { + free(z->self_read.seq); memset(&(z->self_read), 0, sizeof(z->self_read)); + free(z->ovlp_read.seq); memset(&(z->ovlp_read), 0, sizeof(z->ovlp_read)); + + destory_Candidates_list(&z->clist); memset(&(z->clist), 0, sizeof(z->clist)); + destory_overlap_region_alloc(&z->olist); memset(&(z->olist), 0, sizeof(z->olist)); init_overlap_region_alloc(&z->olist); + + kv_destroy(z->k_flag.a); kv_init(z->k_flag.a); + kv_destroy(z->sp); kv_init(z->sp); + kv_destroy(z->pidx); kv_init(z->pidx); + kv_destroy(z->v64); kv_init(z->v64); + kv_destroy(z->v32); kv_init(z->v32); + kv_destroy(z->v16); kv_init(z->v16); + kv_destroy(z->v8q); kv_init(z->v8q); + kv_destroy(z->v8t); kv_init(z->v8t); + + destroy_bit_extz_t(&(z->exz)); init_bit_extz_t(&(z->exz), 31); + + ha_abuf_destroy(z->ab); z->ab = ha_abuf_init(); + + destoryHaplotypeEvdience(&z->hap); memset(&(z->hap), 0, sizeof(z->hap)); InitHaplotypeEvdience(&z->hap); + + destroy_cns_gfa(&(z->cns)); memset(&(z->cns), 0, sizeof(z->cns)); z->cns.q = kdq_init(uint32_t); + + // z->rr = 1; + } +} + + +void prt_chain(overlap_region_alloc *o) +{ + uint64_t k; + for (k = 0; k < o->length; k++) { + fprintf(stderr, "[M::%s]\t#%u\tlen::%lu\t%u\t%u\t%c\t#%u\tlen::%lu\t%u\t%u\tsc::%d\taln::%u\terr::%u\n", __func__, o->list[k].x_id, Get_READ_LENGTH(R_INF, o->list[k].x_id), o->list[k].x_pos_s, o->list[k].x_pos_e+1, "+-"[o->list[k].y_pos_strand], + o->list[k].y_id, Get_READ_LENGTH(R_INF, o->list[k].y_id), o->list[k].y_pos_s, o->list[k].y_pos_e+1, o->list[k].shared_seed, o->list[k].align_length, o->list[k].non_homopolymer_errors); + } +} + +overlap_region *fetch_aux_ovlp(overlap_region_alloc* o, overlap_region **aux) /// exactly same to gen_aux_ovlp +{ + uint64_t nlen = o->length + ((aux)?(2):(1)); + if (nlen >= o->size) { + uint64_t sl = o->size; + o->size = nlen; + kroundup64(o->size); + REALLOC(o->list, o->size); + /// need to set new space to be 0 + memset(o->list + sl, 0, sizeof(overlap_region)*(o->size - sl)); + } + ///debug for memory + // if(ol->length + 1 >= ol->size) { + // fprintf(stderr, "[M::%s] length::%lu, size::%lu\n", __func__, ol->length, ol->size); + // } + if(aux) (*aux) = &(o->list[o->length+2]); + return &(o->list[o->length+1]); +} + +typedef struct { + ul_ov_t *c_idx; + asg64_v *idx; + int64_t i, i0, srt_n, rr, ru; + uint64_t mms, mme; +} cc_idx_t; + +#define extract_sub_cigar_mm_set(fza) do { \ + if(op == 0) {\ + for (t = os + 1; t < oe; t++) {\ + (fza)[(t-s)<<1]++; (fza)[(t-s)<<1] += ((uint64_t)(0x100000000));\ + (fza)[((t-s)<<1)+1]++; (fza)[((t-s)<<1)+1] += ((uint64_t)(0x100000000));\ + }\ + \ + t = os;\ + if(t < oe) {\ + (fza)[(t-s)<<1]++; (fza)[(t-s)<<1] += ((uint64_t)(0x100000000));\ + if(os > ws) {\ + (fza)[((t-s)<<1)+1]++; (fza)[((t-s)<<1)+1] += ((uint64_t)(0x100000000));\ + }\ + }\ + } else if(op!=2) {\ + for (t = os + 1; t < oe; t++) {\ + (fza)[(t-s)<<1]++; \ + (fza)[((t-s)<<1)+1]++;\ + }\ + \ + t = os;\ + if(t < oe) {\ + (fza)[(t-s)<<1]++;\ + if(os > ws) {\ + (fza)[((t-s)<<1)+1]++;\ + }\ + }\ + } else {\ + (fza)[((ws-s)<<1)+1]++;\ + }\ +} while (0) + +///[s, e) +int64_t extract_sub_cigar_mm(overlap_region *z, int64_t s, int64_t e, ul_ov_t *p, uint64_t *ct, uint64_t *hf_ct) +{ + int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), yk = ovlp_cur_yoff(*p), ck = ovlp_cur_coff(*p), os, oe, t; + bit_extz_t ez; int64_t bd = ovlp_bd(*p), s0, e0; + s0 = ((int64_t)(z->w_list.a[wk].x_start)) + bd; + e0 = ((int64_t)(z->w_list.a[wk].x_end)) + 1 - bd; + if(s < s0) {s = s0;} if(e > e0) {e = e0;}///exclude boundary + if(s >= e) return -1; + os = MAX(s, s0); oe = MIN(e, e0); + if(oe <= os) return -1; + + set_bit_extz_t(ez, (*z), wk); + if(!ez.cigar.n) return -1; + int64_t cn = ez.cigar.n, op; int64_t ws, we, ovlp; + if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed + ck = 0; xk = ez.ts; yk = ez.ps; + } + + while (ck > 0 && xk >= s) {///x -> t; y -> p; first insertion and then match/mismatch + --ck; + op = ez.cigar.a[ck]>>14; + if(op!=2) xk -= (ez.cigar.a[ck]&(0x3fff)); + if(op!=3) yk -= (ez.cigar.a[ck]&(0x3fff)); + } + + //some cigar will span s or e + while (ck < cn && xk < e) {//[s, e) + ws = xk; + op = ez.cigar.a[ck]>>14; + ///op == 3: -> x; op == 2: -> y; + if(op!=2) xk += (ez.cigar.a[ck]&(0x3fff)); + if(op!=3) yk += (ez.cigar.a[ck]&(0x3fff)); + ck++; we = xk; + + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + if(op != 2) { + if(!ovlp) continue; + } else {///ws == we + if(ws < s || ws >= e) continue; + } + + extract_sub_cigar_mm_set(ct); + if(hf_ct) { + extract_sub_cigar_mm_set(hf_ct); + } + // if(op == 0) { + // for (t = os + 1; t < oe; t++) { + // ct[(t-s)<<1]++; ct[(t-s)<<1] += ((uint64_t)(0x100000000)); + // ct[((t-s)<<1)+1]++; ct[((t-s)<<1)+1] += ((uint64_t)(0x100000000)); + // } + + // t = os; + // if(t < oe) { + // ct[(t-s)<<1]++; ct[(t-s)<<1] += ((uint64_t)(0x100000000)); + // if(os > ws) { + // ct[((t-s)<<1)+1]++; ct[((t-s)<<1)+1] += ((uint64_t)(0x100000000)); + // } + // } + // } else if(op!=2) { + // for (t = os + 1; t < oe; t++) { + // ct[(t-s)<<1]++; + // ct[((t-s)<<1)+1]++; + // } + + // t = os; + // if(t < oe) { + // ct[(t-s)<<1]++; + // if(os > ws) { + // ct[((t-s)<<1)+1]++; + // } + // } + // } else { + // ct[((ws-s)<<1)+1]++; ///ct[((ws-s)<<1)+1] += ((uint64_t)(0x100000000)); + // } + } + + ovlp_cur_xoff(*p) = xk; ovlp_cur_yoff(*p) = yk; ovlp_cur_coff(*p) = ck; ovlp_cur_ylen(*p) = 0; + + return 1; +} + +#define simp_vote_len 6 + +///[s, e) +uint32_t extract_sub_cigar_ii(overlap_region *z, int64_t ql, All_reads *rref, int64_t s, int64_t e, int64_t iws, int64_t iwe, UC_Read* tu, ul_ov_t *p) +{ + int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), yk = ovlp_cur_yoff(*p), ck = ovlp_cur_coff(*p), os, oe, ol; + bit_extz_t ez; int64_t bd = ovlp_bd(*p), s0, e0, ii[2], it[2]; uint32_t res = (uint32_t)-1; + s0 = ((int64_t)(z->w_list.a[wk].x_start)) + bd; + e0 = ((int64_t)(z->w_list.a[wk].x_end)) + 1 - bd; + if(s < s0) {s = s0;} if(e > e0) {e = e0;}///exclude boundary + if(s > e) return -1;///it is possible s == e + os = MAX(s, s0); oe = MIN(e, e0); + if(oe < os) return -1;///it is possible os == oe + // fprintf(stderr, "[M::%s] s0::%ld, e0::%ld, iws::%ld, iwe::%ld\n", __func__, s0, e0, iws, iwe); + ///make sure that this alignment block could cover the whole [iws, iwe) -> s0 < iws && e0 > iwe + // if((s0 >= iws) || (e0 <= iwe)) return -1;///!(s0 < iws && e0 > iwe) -> only consider the alignment that could cover the whole [s, e) + if(!(((s0 < iws) || (s0 == 0)) && ((e0 > iwe) || (e0 == ql)))) return -1;///!(s0 < iws && e0 > iwe) -> only consider the alignment that could cover the whole [s, e) + + set_bit_extz_t(ez, (*z), wk); + if(!ez.cigar.n) return -1; + int64_t cn = ez.cigar.n; uint16_t op; int64_t ws, we, wts, wte, ovlp, cc = 0, cci; + if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed + ck = 0; xk = ez.ts; yk = ez.ps; + } + + while (ck > 0 && xk >= s) {///x -> t; y -> p; first insertion and then match/mismatch + --ck; + op = ez.cigar.a[ck]>>14; + if(op!=2) xk -= (ez.cigar.a[ck]&(0x3fff)); + if(op!=3) yk -= (ez.cigar.a[ck]&(0x3fff)); + } + + // char cm[4]; cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; + //some cigar will span s or e + ii[0] = ii[1] = it[0] = it[1] = -1; res = cc = 0; + while (ck < cn && xk < e) {//[s, e) + ws = xk; wts = yk; + op = ez.cigar.a[ck]>>14; ol = (ez.cigar.a[ck]&(0x3fff)); + ///op == 3: -> x; op == 2: -> y; + if(op!=2) xk += ol; + if(op!=3) yk += ol; + ck++; we = xk; wte = yk; + + // if(s == 10480) { + // fprintf(stderr, "[%ld, %ld)\t%c\n", ws, we, cm[op]); + // } + + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + + if(s == e) {///insertion in comparsion with the reference + if(op != 0 || ws >= s || we <= e || e != iwe || s != iws) continue;///must be a match + } else { + if(op != 2) { + if(!ovlp) continue; + } else {///ws == we + if(ws < s || ws >= e) continue; + } + } + + + if(ii[0] == -1) { + ii[0] = os; + if(op < 2) { + it[0] = os - ws + wts; + } else {///op == 2: more y; p == 3: more x + it[0] = wts; + } + } + + ii[1] = oe; + if(op < 2) { + it[1] = oe - ws + wts; + } else {///op == 2: more y; p == 3: more x + it[1] = wte; + } + + + + + if(op != 2) ol = oe-os; + cc += ol; + // if(s == 11851 && e == 11853) { + // if(!ol) fprintf(stderr, "%ld%c", ol, cm[op]); + // } + if(cc <= simp_vote_len) { + for (cci = 0; cci < ol; cci++) { + res <<= 2; res |= op; + } + } + } + + while (ck < cn && xk <= e) {//[s, e) + ws = xk; wts = yk; + op = ez.cigar.a[ck]>>14; ol = (ez.cigar.a[ck]&(0x3fff)); + if(op != 2) break; + yk += (ez.cigar.a[ck]&(0x3fff)); + ck++; we = xk; wte = yk; + if(ws >= s && ws <= e) { + + if(ii[0] == -1) { + ii[0] = ws; it[0] = wts; + } + ii[1] = we; it[1] = wte; + + cc += ol; + // if(s == 11851 && e == 11853) { + // fprintf(stderr, "%ld%c", ol, cm[op]); + // } + if(cc <= simp_vote_len) { + for (cci = 0; cci < ol; cci++) { + res <<= 2; res |= op; + } + } + } + } + // if(s == 11851 && e == 11853) { + // fprintf(stderr, "\tx::[%ld, %ld)\ty::[%ld, %ld)\tcc::%ld\n", ii[0], ii[1], it[0], it[1], cc); + // } + if((cc <= simp_vote_len) + && (ii[1] >= ii[0]) && (ii[1] - ii[0] <= simp_vote_len) + && (it[1] >= it[0]) && (it[1] - it[0] <= simp_vote_len)) { + // ii[0] = ii[0] - s; ii[1] = e - ii[1]; + if((ii[0] == iws) && (ii[1] == iwe)) { + op = cc; op <<= 12; res |= op; + + char *ystr = NULL; res <<= 16; cc = it[1] - it[0]; op = 0; + if(cc > 0) { + UC_Read_resize(*tu, (it[1] - it[0])); ystr = tu->seq; + recover_UC_Read_sub_region(ystr, it[0], (it[1] - it[0]), z->y_pos_strand, rref, z->y_id); + + for (cci = 0; cci < cc; cci++) { + op <<= 2; op |= seq_nt6_table[(uint32_t)(ystr[cci])]; + } + } + res |= op; + + op = it[1] - it[0]; op <<= 12; res |= op; + } else { + res = (uint32_t)-1; + } + } else { + res = (uint32_t)-1; + } + + + ovlp_cur_xoff(*p) = xk; ovlp_cur_yoff(*p) = yk; ovlp_cur_coff(*p) = ck; ovlp_cur_ylen(*p) = 0; + + return res; +} + +typedef struct { + All_reads *rref; + UC_Read *tu; + uint64_t s, e, n0, n1, id, rev; +} rr_seq_t; + +inline void insert_cns_arc(cns_gfa *cns, uint32_t src, uint32_t des, uint32_t is_ou, uint32_t plus0, uint32_t rid) +{ + if(src >= cns->n) { + fprintf(stderr, "[M::%s] rid::%u, src::%u, des::%u, (*cns).n::%u\n", __func__, rid, src, des, (uint32_t)(*cns).n); + exit(1); + } + cns_arc *p, t; kv_pushp(cns_arc, (*cns).a[src].arc, &p); + p->f = 0; p->sc = plus0; p->v = des; + if(is_ou) { + (*cns).a[src].arc.nou++; + if((*cns).a[src].arc.nou < (*cns).a[src].arc.n) { + t = (*cns).a[src].arc.a[(*cns).a[src].arc.nou-1]; + (*cns).a[src].arc.a[(*cns).a[src].arc.nou-1] = *p; + *p = t; + } + } +} + +inline uint32_t insert_cns_node(cns_gfa *cns) +{ + cns_t *p; uint32_t m0; + if (((*cns)).n == ((*cns)).m) { + m0 = ((*cns)).m; + ((*cns)).m = ((*cns)).m? ((*cns)).m<<1 : 2; + ((*cns)).a = (cns_t*)realloc(((*cns)).a, sizeof(cns_t) * ((*cns)).m); + if(((*cns)).m > m0) { + memset(((*cns)).a + m0, 0, sizeof(cns_t)*(((*cns)).m-m0)); + } + } + *(&p) = &((*cns)).a[((*cns)).n++]; + p->arc.n = p->arc.nou = 0; + p->c = p->f = p->sc = 0; + return ((*cns)).n - 1; +} + +inline uint32_t add_cns_arc(cns_gfa *cns, uint32_t src, uint32_t des, uint32_t is_ou, uint32_t plus) +{ + uint32_t k, s, e; + if(is_ou) { + s = 0; e = (*cns).a[src].arc.nou; + } else { + s = (*cns).a[src].arc.nou; e = (*cns).a[src].arc.n; + } + + for (k = s; k < e; k++) { + if((*cns).a[src].arc.a[k].v == des) { + (*cns).a[src].arc.a[k].sc += plus; + break; + } + } + + return ((k < e)?(1):(0)); +} + +inline void prt_cns_arc(cns_gfa *cns, uint32_t src, const char* cmd) +{ + uint32_t k; + fprintf(stderr, "\n%s\t[M::%s] src::%u, sc::%u, c::%u\n", cmd, __func__, src, (*cns).a[src].sc, (*cns).a[src].c); + for (k = 0; k < (*cns).a[src].arc.n; k++) { + fprintf(stderr, "%s\t[M::%s] des::%u, sc::%u, is_ou::%u\n", cmd, __func__, (*cns).a[src].arc.a[k].v, (*cns).a[src].arc.a[k].sc, k<(*cns).a[src].arc.nou?1:0); + } +} + +inline uint32_t get_cns_arc_bp(cns_gfa *cns, uint32_t src, uint32_t bp, uint32_t is_ou, uint32_t av_bp) +{ + uint32_t k, s, e; + if(is_ou) { + s = 0; e = (*cns).a[src].arc.nou; + } else { + s = (*cns).a[src].arc.nou; e = (*cns).a[src].arc.n; + } + + for (k = s; k < e; k++) { + if((*cns).a[src].arc.a[k].v == 0 || (*cns).a[src].arc.a[k].v == 1) continue; + if(av_bp && (*cns).a[src].arc.a[k].v >= (*cns).bb0 && (*cns).a[src].arc.a[k].v < (*cns).bb1) continue;///no backbone + if((*cns).a[(*cns).a[src].arc.a[k].v].c == bp) { + return k; + } + } + + return ((uint32_t)-1); +} + +inline uint32_t add_cns_arc_bp(cns_gfa *cns, uint32_t src, uint32_t bp, uint32_t plus0, uint32_t rid, uint32_t av_bp) +{ + uint32_t rr, des; + rr = get_cns_arc_bp(cns, src, bp, 1, av_bp); + if(rr != ((uint32_t)-1)) {///find an existing node + des = (*cns).a[src].arc.a[rr].v; + (*cns).a[des].sc++; + (*cns).a[src].arc.a[rr].sc += plus0; + + rr = add_cns_arc(cns, des, src, 0, plus0); + // if(rr == 0) { + // fprintf(stderr, "[M::%s] src::%u -> des::%u\n", __func__, src, des); + // prt_cns_arc(cns, src); + // prt_cns_arc(cns, des); + // } + assert(rr); + + return des; + } else {///create a new node + des = insert_cns_node(cns); + (*cns).a[des].sc++; (*cns).a[des].c = bp; + insert_cns_arc(cns, src, des, 1, plus0, rid); + insert_cns_arc(cns, des, src, 0, plus0, rid); + } + + return des; +} + +void init_cns_g(cns_gfa *cns, char *s, uint64_t sl, uint32_t ed_w, uint32_t rid) +{ + uint32_t m0 = cns->m, m1 = sl + 2, k; cns_t *p; + if ((*cns).m < (m1)) { ///equal to kv_resize() + (*cns).m = (m1); + (--((*cns).m), ((*cns).m)|=((*cns).m)>>1, ((*cns).m)|=((*cns).m)>>2, ((*cns).m)|=((*cns).m)>>4, ((*cns).m)|=((*cns).m)>>8, ((*cns).m)|=((*cns).m)>>16, ++((*cns).m)); + (*cns).a = (cns_t*)realloc((*cns).a, sizeof(cns_t) * (*cns).m); + if((*cns).m > m0) { + memset((*cns).a + m0, 0, sizeof(cns_t)*((*cns).m-m0)); + } + } + (*cns).n = 0; (*cns).si = 0; (*cns).ei = 1; (*cns).off = 2; + + p = &((*cns).a[(*cns).n++]); p->arc.nou = p->arc.n = p->c = p->f = p->sc = 0; ///beg + p = &((*cns).a[(*cns).n++]); p->arc.nou = p->arc.n = p->c = p->f = p->sc = 0; ///end + (*cns).bb0 = (*cns).n; + + for (k = 0; k < sl; k++) { + p = &((*cns).a[(*cns).n++]); p->arc.nou = p->arc.n = p->f = 0; + p->c = seq_nt6_table[(uint32_t)(s[k])]; p->sc = 1; + + if(k + 1 < sl) insert_cns_arc(cns, k + (*cns).off, k + 1 + (*cns).off, 1, ed_w, rid); + + if(k > 0) insert_cns_arc(cns, k + (*cns).off, k - 1 + (*cns).off, 0, ed_w, rid); + } + + if(sl) { + insert_cns_arc(cns, (*cns).si, 0 + (*cns).off, 1, ed_w, rid); insert_cns_arc(cns, 0 + (*cns).off, (*cns).si, 0, ed_w, rid); + insert_cns_arc(cns, sl - 1 + (*cns).off, (*cns).ei, 1, ed_w, rid); insert_cns_arc(cns, (*cns).ei, sl - 1 + (*cns).off, 0, ed_w, rid); + } else { + insert_cns_arc(cns, (*cns).si, (*cns).ei, 1, ed_w, rid); + insert_cns_arc(cns, (*cns).ei, (*cns).si, 0, ed_w, rid); + } + + // prt_cns_arc(cns, 0, __func__); + // prt_cns_arc(cns, 1, __func__); + + (*cns).bn = (*cns).n; (*cns).bb1 = (*cns).n; +} + +///[s, e) +uint32_t push_cns_c0(cns_gfa *cns, uint64_t s0, uint64_t s, uint64_t e, uint32_t plus0, uint32_t rid) +{ + if(s > e) return s0;///it is possible that s == e + uint32_t rr, k, re; + + // rr = add_cns_arc(cns, s0, s, 1, plus0); assert(rr); + // rr = add_cns_arc(cns, s, s0, 0, plus0); assert(rr); + if(!add_cns_arc(cns, s0, s, 1, plus0)) { + insert_cns_arc(cns, s0, s, 1, plus0, rid); + insert_cns_arc(cns, s, s0, 0, plus0, rid); + } else { + rr = add_cns_arc(cns, s, s0, 0, plus0); assert(rr); + } + (*cns).a[s].sc++; re = s; + + for (k = s + 1; k < e; k++) { + rr = add_cns_arc(cns, k-1, k, 1, /**1**/plus0); + // if(!rr) { + // fprintf(stderr, "[M::%s] s0::%u, s::%u\n", __func__, k-1, k); + // prt_cns_arc(cns, k-1, __func__); prt_cns_arc(cns, k, __func__); + // } + assert(rr); + + + + rr = add_cns_arc(cns, k, k-1, 0, /**1**/plus0); assert(rr); + (*cns).a[k].sc++; re = k; + } + + return re; +} + +uint32_t trace_cns_bp(cns_gfa *cns, uint64_t s0, char *tstr, uint64_t tl, asg32_v* b32, uint32_t plus0, uint32_t *rn, uint64_t max_trace, uint32_t av_bp) +{ + (*rn) = s0; + if(tl <= 0) return 0; + // fprintf(stderr, "\n[M::%s] tl::%lu\n", __func__, tl); + uint32_t k, i, s, e, m, bp, nm, bi, bn0, src, des, ff = 0; b32->n = 0; + + kv_push(uint32_t, (*b32), s0); kv_push(uint32_t, (*b32), ((uint32_t)-1)); nm = 2; + // if(s0 == 2863) { + // fprintf(stderr, "***0***[M::%s] s::%lu\tb32->n::%u\n", __func__, s0, (uint32_t)b32->n); + // } + + for (i = 0; (i < tl) && (!ff); i++) { + bp = seq_nt6_table[(uint32_t)(tstr[i])]; bn0 = b32->n; + for (bi = bn0 - nm; bi < bn0; bi += 2) { + m = b32->a[bi]; s = 0; e = (*cns).a[m].arc.nou; + for (k = s; k < e; k++) { + if((*cns).a[m].arc.a[k].v == 0 || (*cns).a[m].arc.a[k].v == 1) continue; + if(av_bp && (*cns).a[m].arc.a[k].v >= (*cns).bb0 && (*cns).a[m].arc.a[k].v < (*cns).bb1) continue;///no backbone + if((*cns).a[(*cns).a[m].arc.a[k].v].c == bp) { + kv_push(uint32_t, (*b32), (*cns).a[m].arc.a[k].v); + kv_push(uint32_t, (*b32), bi); + + // if(s0 == 2863) { + // fprintf(stderr, "***1***[M::%s] s::%u\tb32->n::%u\n", __func__, (*cns).a[m].arc.a[k].v, (uint32_t)b32->n); + // } + // if((i + 1) == tl) break;///quick end + // if(b32->n > max_trace) break;///redue the size of b32 + if(((i + 1) == tl) || (b32->n > max_trace)) { + ff = 1; break; + } + } + } + if(ff) break; + } + + if(b32->n <= bn0) {///no node + break; + } else { + nm = b32->n - bn0; + } + } + // fprintf(stderr, "[M::%s] b32->n::%u, nm::%u\n", __func__, (uint32_t)b32->n, nm); + + // if(s0 == 2863) { + // fprintf(stderr, "[M::%s] i::%u\tnm::%u\tb32->n::%u\n", __func__, i, nm, (uint32_t)b32->n); + // } + if(i > 0 && nm > 0) { + (*rn) = b32->a[b32->n - nm]; + for (bi = b32->n - nm; b32->a[bi + 1] != ((uint32_t)-1); bi = b32->a[bi + 1]) { + // fprintf(stderr, "[M::%s] bi::%u, p_bi::%u\n", __func__, bi, b32->a[bi + 1]); + des = b32->a[bi]; src = b32->a[b32->a[bi + 1]]; /**bp = ((src!=s0)?(1):(plus0));**/ + m = add_cns_arc(cns, src, des, 1, /**bp**/plus0); assert(m); + m = add_cns_arc(cns, des, src, 0, /**bp**/plus0); assert(m); + (*cns).a[des].sc++; + + // if(s0 == 2863) { + // fprintf(stderr, "***2***[M::%s] src::%u\tdes::%u\n", __func__, src, des); + // } + } + } else { + i = 0; + } + + return i; +} + +///[s, e) +uint32_t push_cns_c1(cns_gfa *cns, uint64_t s0, char *tstr, uint64_t tl, uint32_t plus0, asg32_v* b32, uint64_t max_trace, uint32_t rid) +{ + if(tl <= 0) return s0; + uint32_t /**rr = plus0,**/ k, re = s0; + k = trace_cns_bp(cns, s0, tstr, tl, b32, plus0, &re, max_trace, 1); + /**if(k > 0) rr = 1;**/ + + // if(s0 == 2863) { + // fprintf(stderr, "[M::%s] (%.*s)\ts0::%lu\tk::%u\ttl::%lu\tre::%u\n", __func__, tstr?((int)(tl)):0, tstr, s0, k, tl, re); + // } + // fprintf(stderr, "[M::%s] s0::%u, s::%u\n", __func__, k-1, k); + // prt_cns_arc(cns, k-1, __func__); prt_cns_arc(cns, k, __func__); + + for (; k < tl; k++) {///the weight of (s0 -> tstr[0]) might be 0 + re = add_cns_arc_bp(cns, re, seq_nt6_table[(uint32_t)(tstr[k])], /**rr**/plus0, rid, 1); /**rr = 1;**/ + } + + return re; +} + +uint64_t append_cns_g(cns_gfa *cns, char *tstr, uint64_t tl, uint64_t qs, uint64_t qe, uint64_t cp, uint64_t cl, uint64_t pe, asg32_v* b32, uint64_t max_trace, uint32_t ed_w, uint32_t rid, int64_t insert_pos) +{ + // fprintf(stderr, ">q::[%lu, %lu)\n", qs, qe); + uint64_t s0 = pe, /**plus0 = 1,**/ ns = qs + cns->off, ne = qe + cns->off; + if(pe == ((uint64_t)-1)) { + if(qs > 0) { + s0 = qs - 1 + cns->off;///just before node in backbone + } else { + s0 = 0;//beg + } + // plus0 = 0; + } + + // fprintf(stderr, "+n_nodes::%u, tl::%lu, qs::%lu, qe::%lu\n", (uint32_t)cns->n, tl, qs, qe); + + if(cp == 0) { + if((cl == 0) && (cp == 0) && (qs == qe) && (((int64_t)qe) == insert_pos)) { + s0 = 0;//beg + ns = ne = 1;//end + /**plus0 = 1;**/ + } + // if(cp == 0) { + // fprintf(stderr, "cp::%lu, cl::%lu, qs::%lu, qe::%lu, s0::%lu, ns::%lu, ne::%lu, plus0::%lu\n", cp, cl, qs, qe, s0, ns, ne, plus0); + // } + return push_cns_c0(cns, s0, ns, ne, /**plus0,**/ed_w, rid); + } else if(cp == 1 || cp == 2) { ///cp == 2: more y -> insertion + return push_cns_c1(cns, s0, tstr, tl, /**plus0,**/ed_w, b32, max_trace, rid); + } else { ///more x -> do nothing + return s0; + } +} + +char *get_sub_seq(rr_seq_t *ssq, uint64_t s, uint64_t e) +{ + if(s >= e) return NULL; + + if(s >= ssq->s && e <= ssq->e) { + return ssq->tu->seq + s - ssq->s; + } + + uint64_t l = e - s; + if(ssq->s >= ssq->e) { + if(l < ssq->n0) l = ssq->n0; + } else { + if(l < ssq->n1) l = ssq->n1; + } + + ssq->s = s; ssq->e = s + l; + if(ssq->e > Get_READ_LENGTH((*(ssq->rref)), ssq->id)) { + ssq->e = Get_READ_LENGTH((*(ssq->rref)), ssq->id); + l = ssq->e - ssq->s; + } + UC_Read_resize((*(ssq->tu)), ((int64_t)l)); + recover_UC_Read_sub_region(ssq->tu->seq, ssq->s, l, ssq->rev, ssq->rref, ssq->id); + return ssq->tu->seq; +} + + +///[s, e) +uint32_t extract_sub_cigar_cns(overlap_region *z, int64_t s, int64_t e, int64_t iws, int64_t iwe, int64_t s_end, rr_seq_t *ssq, ul_ov_t *p, cns_gfa *cns, asg32_v* b32, uint64_t max_trace, uint32_t ed_w, uint32_t rid) +{ + // if(s == 10539 && e == 10760) { + // fprintf(stderr, "\n>>>>>>iw::[%ld, %ld)\tw::[%ld, %ld)\tox::[%u, %u)<<<<<<\n", iws, iwe, s, e, z->x_pos_s, z->x_pos_e + 1); + // } + + int64_t wk = ovlp_cur_wid(*p), xk = ovlp_cur_xoff(*p), yk = ovlp_cur_yoff(*p), ck = ovlp_cur_coff(*p), os, oe, ots, ote, ol, insert_pos = ((iws == iwe)? (0): (-1)); + bit_extz_t ez; int64_t bd = ovlp_bd(*p), s0, e0, ii[2], it[2]; uint64_t pe = (uint64_t)-1; + s0 = ((int64_t)(z->w_list.a[wk].x_start)) + bd; + e0 = ((int64_t)(z->w_list.a[wk].x_end)) + 1 - bd; + if(s < s0) {s = s0;} if(e > e0) {e = e0;}///exclude boundary + if(s > e) return -1;///it is possible s == e + os = MAX(s, s0); oe = MIN(e, e0); + if(oe < os) return -1;///it is possible os == oe + + set_bit_extz_t(ez, (*z), wk); + if(!ez.cigar.n) return -1; + int64_t cn = ez.cigar.n; uint16_t op; int64_t ws, we, wts, wte, ovlp; char *tstr; + if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed + ck = 0; xk = ez.ts; yk = ez.ps; + } + + while (ck > 0 && xk >= s) {///x -> t; y -> p; first insertion and then match/mismatch + --ck; + op = ez.cigar.a[ck]>>14; + if(op!=2) xk -= (ez.cigar.a[ck]&(0x3fff)); + if(op!=3) yk -= (ez.cigar.a[ck]&(0x3fff)); + } + + if(s_end == 0 && s == iws) s_end = 0; + else s_end = 1; + + // if(s_end == 0 || s != iws) {///do not conside the insertion before s + // while (ck < cn && xk < s) { + // } + // } + + // if(s == 10539 && e == 10760) { + // fprintf(stderr, "ck::%ld, cn::%ld, xk::%ld, yk::%ld\n", ck, cn, xk, yk); + // } + + // char cm[4]; cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; + //some cigar will span s or e + ii[0] = ii[1] = it[0] = it[1] = -1; + ssq->s = ssq->e = 0; ssq->n0 = e - s; + ssq->id = z->y_id; ssq->rev = z->y_pos_strand; + if(ssq->n0 == 0) {ssq->n0 = ssq->n1;} + + while (ck < cn && xk < e) {//[s, e) + ws = xk; wts = yk; + op = ez.cigar.a[ck]>>14; ol = (ez.cigar.a[ck]&(0x3fff)); + + for (ck++; (ck < cn) && (op == (ez.cigar.a[ck]>>14)); ck++) { + ol += (ez.cigar.a[ck]&(0x3fff)); + } + ///op == 3: -> x; op == 2: -> y; + if(op!=2) xk += ol; + if(op!=3) yk += ol; + we = xk; wte = yk; + + // fprintf(stderr, "ck::%ld, cn::%ld, op::%u, ol::%ld\n", ck, cn, op, ol); + + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + + if(s == e) {///insertion in comparsion with the reference + if(op != 0 || ws >= s || we <= e || e != iwe || s != iws) continue;///must be a match + } else { + if(op != 2) { + if(!ovlp) continue; + } else {///ws == we + if(ws < s || ws >= e) continue; + } + } + + if((s_end == 0) && (op == 2) && (ws == s)) continue;///skip the insertion just before s + + + + if(op < 2) { + ots = os - ws + wts; ote = oe - ws + wts; + } else {///op == 2: more y; p == 3: more x + ots = wts; ote = wte; + } + + + + if(ii[0] == -1) { + ii[0] = os; it[0] = ots; + // if(op < 2) { + // it[0] = os - ws + wts; + // } else {///op == 2: more y; p == 3: more x + // it[0] = wts; + // } + } + + ii[1] = oe; it[1] = ote; + // if(op < 2) { + // it[1] = oe - ws + wts; + // } else {///op == 2: more y; p == 3: more x + // it[1] = wte; + // } + + + + + if(op != 2) ol = oe-os; + + tstr = NULL; + if(op != 0) tstr = get_sub_seq(ssq, ots, ote); + + // if(s == 10539 && e == 10760) { + // fprintf(stderr, "+0-%ld%c(%.*s)\tpe::%lu", ol, cm[op], tstr?((int)(ote - ots)):0, tstr, pe); + // } + // fprintf(stderr, ">q::[%ld, %ld)\n", ws, we); + // fprintf(stderr, "%ld%c(%.*s)", ol, cm[op], tstr?((int)(ote - ots)):0, tstr); + + pe = append_cns_g(cns, tstr, ote - ots, os - iws, oe - iws, op, ol, pe, b32, max_trace, ed_w, rid, insert_pos); + + // if(s == 10539 && e == 10760) { + // fprintf(stderr, "+1-pe::%lu\n", pe); + // } + } + + while (ck < cn && xk <= e) {//[s, e) + ws = xk; wts = yk; + op = ez.cigar.a[ck]>>14; ol = (ez.cigar.a[ck]&(0x3fff)); + if(op != 2) break; + + for (ck++; (ck < cn) && (op == (ez.cigar.a[ck]>>14)); ck++) { + ol += (ez.cigar.a[ck]&(0x3fff)); + } + yk += ol;//yk += (ez.cigar.a[ck]&(0x3fff)); + we = xk; wte = yk; + + + if(ws >= s && ws <= e) { + ots = wts; ote = wte; + if(ii[0] == -1) { + ii[0] = ws; it[0] = ots; + } + ii[1] = we; it[1] = ote; + + + tstr = NULL; + if(op != 0) tstr = get_sub_seq(ssq, ots, ote); + // if(s == 10539 && e == 10760) { + // fprintf(stderr, "-0-%ld%c(%.*s)\tpe::%lu", ol, cm[op], tstr?((int)(ote - ots)):0, tstr, pe); + // } + // fprintf(stderr, "%ld%c(%.*s)", ol, cm[op], tstr?((int)(ote - ots)):0, tstr); + + pe = append_cns_g(cns, tstr, ote - ots, ws - iws, we - iws, op, ol, pe, b32, max_trace, ed_w, rid, insert_pos); + + // if(s == 10539 && e == 10760) { + // fprintf(stderr, "-1-pe::%lu\n", pe); + // } + } + } + + // if(s == 10539 && e == 10760) { + // fprintf(stderr, "\tx::[%ld, %ld)\ty::[%ld, %ld)\tiw::[%ld, %ld)\n", ii[0], ii[1], it[0], it[1], iws, iwe); + // } + + // prt_cns_arc(cns, 0, __func__); + // prt_cns_arc(cns, 1, __func__); + if(ii[1] == -1) return -1;///it is possible when s == e and the cigar here is not a match + + uint64_t ae = 1; + if((ii[1] == iwe)) { + ae = 1;///end node + } else { + ae = ii[1] + cns->off - iws; + } + + // if(s == 10539 && e == 10760) { + // fprintf(stderr, "pe::%lu, ae::%lu, n_nodes::%u, ii[1]::%ld\n", pe, ae, (uint32_t)cns->n, ii[1]); + // } + + if(pe == ((uint64_t)-1)) pe = 0;///start node + + ///if iws == iwe and the cigar is a match, pe will be equal to ae + if(pe != ae) { + if(!add_cns_arc(cns, pe, ae, 1, /**ae==1?1:0**//**1**/ed_w)) { + insert_cns_arc(cns, pe, ae, 1, /**ae==1?1:0**//**1**/ed_w, rid); + insert_cns_arc(cns, ae, pe, 0, /**ae==1?1:0**//**1**/ed_w, rid); + } else { + add_cns_arc(cns, ae, pe, 0, /**ae==1?1:0**//**1**/ed_w); + } + } + + + // prt_cns_arc(cns, 0, __func__); + // prt_cns_arc(cns, 1, __func__); + + + // if(s == 10539 && e == 10760) { + // fprintf(stderr, "-end-pe::%lu, ae::%lu\n", pe, ae); + // } + + ovlp_cur_xoff(*p) = xk; ovlp_cur_yoff(*p) = yk; ovlp_cur_coff(*p) = ck; ovlp_cur_ylen(*p) = 0; + + return 1; +} + + +uint64_t iter_cc_idx_t(overlap_region* ol, cc_idx_t *z, int64_t s, int64_t e, uint64_t is_reduce, uint64_t is_insert, uint64_t **ra) +{ + int64_t rm_n, q[2], os, oe; ul_ov_t *cp; uint64_t m; *ra = NULL; + + // if(s == 15816 && e == 15819) { + // fprintf(stderr, "[M::%s] is_reduce::%lu\n", __func__, is_reduce); + // } + if(z->ru == 0) { + if(is_reduce) { + for (m = rm_n = z->srt_n; m < z->idx->n; m++) { + cp = &(z->c_idx[z->idx->a[m]]); + // if(s == 15816 && e == 15819) { + // fprintf(stderr, "-0-[M::%s] ii::%lu, ii0::%ld\n", __func__, z->idx->a[m], z->i0); + // } + + q[0] = ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); + q[1] = ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + os = MAX(q[0], s); oe = MIN(q[1], e); + if((oe > os) || ((is_insert) && (s == e) && (s >= q[0]) && (s <= q[1]))) { + z->idx->a[rm_n++] = z->idx->a[m]; + } + } + z->idx->n = rm_n; + } + + for (; z->i < z->srt_n; ++z->i) { + cp = &(z->c_idx[(uint32_t)z->idx->a[z->i]]); + // if(s == 15816 && e == 15819) { + // fprintf(stderr, "-1-[M::%s] ii::%u, ii0::%ld\n", __func__, (uint32_t)z->idx->a[z->i], z->i0); + // } + q[0] = ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); + q[1] = ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + if(q[0] > e) break; + if((!is_insert) && (q[0] >= e)) break; + os = MAX(q[0], s); oe = MIN(q[1], e); + if((oe > os) || ((is_insert) && (s == e) && (s >= q[0]) && (s <= q[1]))) { + kv_push(uint64_t, *(z->idx), ((uint32_t)z->idx->a[z->i])); + } + } + } else { + z->ru = 0; + } + + (*ra) = z->idx->a + z->srt_n; + return z->idx->n - z->srt_n; +} + +void debug_inter0(overlap_region* ol, ul_ov_t *c_idx, uint64_t *idx, int64_t idx_n, uint64_t *res, int64_t res_n, int64_t s, int64_t e, uint64_t is_insert, uint64_t is_hard_check, const char *cmd) +{ + ul_ov_t *cp; int64_t q[2], a_n = 0, i, k = 0, os, oe; + for (i = 0; i < idx_n; i++) { + cp = &(c_idx[(uint32_t)idx[i]]); + q[0] = ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); + q[1] = ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + + // fprintf(stderr, "%s[M::%s] tid::%u\t%.*s\twid::%u\tq::[%u, %u)\terr::%d\toerr::%u\n", cmd, __func__, ol[ovlp_id(*cp)].y_id, (int)Get_NAME_LENGTH(R_INF, ol[ovlp_id(*cp)].y_id), Get_NAME(R_INF, ol[ovlp_id(*cp)].y_id), + // ovlp_cur_wid(*cp), ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start, ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1, ol[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].error, ol[ovlp_id(*cp)].non_homopolymer_errors); + + os = MAX(q[0], s); oe = MIN(q[1], e); + if((oe > os) || ((is_insert) && (s == e) && (s >= q[0]) && (s <= q[1]))) { + a_n++; + // if(!(((uint32_t)idx[i]) == res[k])) { + // fprintf(stderr, "[M::%s] a_n::%ld\tres_n::%ld\ts::%ld\te::%ld\ti::%ld\tk::%ld\n", __func__, a_n, res_n, s, e, i, k); + // } + if(is_hard_check) { + assert(((uint32_t)idx[i]) == res[k++]); + } else { + for (; (k < res_n) && (((uint32_t)idx[i]) != res[k]); k++); + assert(k < res_n); + } + } + } + // if(a_n != res_n) { + // fprintf(stderr, "[M::%s] a_n::%ld\tres_n::%ld\ts::%ld\te::%ld\tidx_n::%ld\n", __func__, a_n, res_n, s, e, idx_n); + // } + if(is_hard_check) { + assert(a_n == res_n); + } else { + assert(a_n <= res_n); + } +} + +void prt_cigar0(uint64_t in, int64_t len) +{ + int64_t k; uint64_t mp; + char cm[4]; cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; + for (k = 0; k < len; k++) { + mp = len - 1 - k; mp <<= 1; + fprintf(stderr, "%c", cm[(in >> mp)&3]); + } + fprintf(stderr, "\n"); +} + +void prt_bp0(uint64_t in, int64_t len) +{ + int64_t k; uint64_t mp; + char cm[4]; cm[0] = 'A'; cm[1] = 'C'; cm[2] = 'G'; cm[3] = 'T'; + for (k = 0; k < len; k++) { + mp = len - 1 - k; mp <<= 1; + fprintf(stderr, "%c", cm[(in >> mp)&3]); + } + fprintf(stderr, "\n"); +} + +inline uint64_t cal_occ_w(uint64_t n_hf, uint64_t n_a, uint64_t h_rate, uint64_t o_rate) +{ + return (n_hf * h_rate) + ((n_a - n_hf) * o_rate); +} + +uint64_t cns_gen0(overlap_region* ol, All_reads *rref, uint64_t s, uint64_t e, uint64_t ql, UC_Read* tu, cc_idx_t *idx, uint64_t occ_tot, double occ_max, asg32_v* b32, uint64_t o_rate, uint64_t h_rate, uint64_t q_hf, uint32_t *rc) +{ + if(e > s + simp_vote_len) return 0;///too long + + uint64_t *id_a = NULL, id_n, an = 0, fan = 0, oc[2], och; b32->n = 0; uint32_t m, *a = NULL; uint8_t f_hf = (((o_rate == ((uint64_t)-1)) || (h_rate == ((uint64_t)-1)))?(0):(1)); + id_n = iter_cc_idx_t(ol, idx, s, e, idx->rr, ((s==e)?1:0), &id_a); + // debug_inter0(ol, idx->c_idx, idx->idx->a + idx->i0, idx->srt_n - idx->i0, id_a, id_n, s, e, ((s==e)?1:0), 0, "-1-"); + uint64_t zi, k, l, q[2], os, oe; ul_ov_t *p; overlap_region *z; idx->rr = 0; uint64_t w, mw, ow[2]; + // fprintf(stderr, "[M::%s] [%lu, %lu) id_n::%lu\n", __func__, s, e, id_n); + for (k = 0; k < id_n; k++) { + p = &(idx->c_idx[id_a[k]]); z = &(ol[ovlp_id(*p)]); + q[0] = z->w_list.a[ovlp_cur_wid(*p)].x_start+ovlp_bd(*p); + q[1] = z->w_list.a[ovlp_cur_wid(*p)].x_end+1-ovlp_bd(*p); + + // if(s == 11851 && e == 11853) { + // fprintf(stderr, "[M::%s] tid::%u\t%.*s\twid::%u\tq::[%u, %u)\terr::%d\toerr::%u\n", __func__, ol[ovlp_id(*p)].y_id, (int)Get_NAME_LENGTH(R_INF, ol[ovlp_id(*p)].y_id), Get_NAME(R_INF, ol[ovlp_id(*p)].y_id), + // ovlp_cur_wid(*p), ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].x_start, ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].x_end+1, ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].error, ol[ovlp_id(*p)].non_homopolymer_errors); + // } + + if(q[1] <= e) idx->rr = 1; + os = MAX(q[0], s); oe = MIN(q[1], e); + // if((oe > os) || ((s == e) && (s >= q[0]) && (s <= q[1]))) { + if((oe > os) || ((s == e) && (s > q[0]) && (s < q[1]))) { + // if(oe >= os) { + ///[-4-][-12-][-4-][-12-] + ///[cigar_len][cigar][base_len][base] + m = extract_sub_cigar_ii(z, ql, rref, os, oe, s, e, tu, p); an++; fan += ovlp_hf((*p)); + if(m != ((uint32_t)-1)) {///no gap in both sides + if(f_hf) { + m <<= 1; m |= ((uint32_t)ovlp_hf((*p))); + } + kv_push(uint32_t, *b32, m); + } + } + } + + ow[0] = ow[1] = 1;///for initial + oc[0] = b32->n; oc[1] = an + 1; //+1 for the reference read + // if(s == 11851 && e == 11853) { + // fprintf(stderr, "-0-[M::%s] oc[0]::%lu, oc[1]::%lu\n", __func__, oc[0], oc[1]); + // } + if(((oc[0] > (oc[1]*occ_max)) && (oc[0] > (oc[1]-oc[0])) && (oc[1] >= occ_tot) && (oc[0] > 1))) { + radix_sort_ec32(b32->a, b32->a+b32->n); an = 0; + if(!f_hf) { + for (k = 1, l = 0; k <= b32->n; ++k) { + if (k == b32->n || b32->a[k] != b32->a[l]) { + if(k - l > an) { + an = k - l; a = b32->a + l; + } + l = k; + } + } + } else { + for (k = 1, l = 0, mw = -1; k <= b32->n; ++k) { + if (k == b32->n || (b32->a[k]>>1) != (b32->a[l]>>1)) { + for (zi = l, och = 0; zi < k; zi++) { + och += b32->a[zi] & 1; + } + w = cal_occ_w(och, k - l, h_rate, o_rate); + if(w > mw) { + an = k - l; a = b32->a + l; mw = w; + } + l = k; + } + } + } + + oc[0] = an; + if(f_hf) { + ow[0] = mw; + ow[1] = cal_occ_w(fan + q_hf, an + 1, h_rate, o_rate); + } + // fprintf(stderr, "-1-[M::%s] oc[0]::%lu, oc[1]::%lu\n", __func__, oc[0], oc[1]); + if((oc[0] > (oc[1]*occ_max)) && (oc[0] > (oc[1]-oc[0])) && (oc[1] >= occ_tot) && (oc[0] > 1) && ((!f_hf) || ((ow[0] > (ow[1]*occ_max)) && (ow[0] > (ow[1] - ow[0]))))) { + (*rc) = ((f_hf)?(a[0]>>1):(a[0])); + // prt_cigar0((a[0]<<4)>>20, a[0]>>28); + // prt_bp0((a[0]<<20)>>20, (a[0]<<16)>>28); + return 1; + } + } + + idx->ru = 1; + return 0; +} + +inline void gen_mm_cns_arc(cns_gfa *cns, uint32_t src, uint32_t des, uint32_t sc, uint32_t f) +{ + cns_t *av = &((*cns).a[src]), *aw; + uint32_t vk, wk; + for (vk = 0; vk < av->arc.nou; vk++) {///out-edge of src + if((av->arc.a[vk].v != des) || (del_cns_arc((*av), vk))) continue; + // av->arc.a[vk].f = 1; ///not sure if we should set these edges as visited + av->arc.a[vk].f = f; + av->arc.a[vk].sc += sc; + + aw = &((*cns).a[des]); + for (wk = aw->arc.nou; wk < aw->arc.n; wk++) {///in-edge of des + if((aw->arc.a[wk].v != src) || (del_cns_arc((*aw), wk))) continue; + // aw->arc.a[wk].f = 1; ///not sure if we should set these edges as visited + aw->arc.a[wk].f = f; + aw->arc.a[wk].sc += sc; + break; + } + + assert(wk < aw->arc.n); + return; + } + + cns_arc *p, t; + ///src -> des + kv_pushp(cns_arc, (*cns).a[src].arc, &p); + p->sc = sc; p->v = des; + // p->f = 1; ///not sure if we should set these edges as visited + p->f = f; + ///ou-edge + (*cns).a[src].arc.nou++; + if((*cns).a[src].arc.nou < (*cns).a[src].arc.n) { + t = (*cns).a[src].arc.a[(*cns).a[src].arc.nou-1]; + (*cns).a[src].arc.a[(*cns).a[src].arc.nou-1] = *p; + *p = t; + } + + ///src <- des; in-edge + kv_pushp(cns_arc, (*cns).a[des].arc, &p); + p->sc = sc; p->v = src; + // p->f = 1; ///not sure if we should set these edges as visited + p->f = f; +} + +void del_cns_g_nn(cns_gfa *cns, uint32_t v) +{ + uint32_t w, vk, wk; cns_t *av = &((*cns).a[v]), *aw = NULL; + + for (vk = 0; vk < av->arc.nou; vk++) {///out-edge of src + if(del_cns_arc((*av), vk)) continue; + w = av->arc.a[vk].v; av->arc.a[vk].v = CNS_DEL_E; + + aw = &((*cns).a[w]); + for (wk = aw->arc.nou; wk < aw->arc.n; wk++) {///in-edge of des + if((aw->arc.a[wk].v != v) || (del_cns_arc((*aw), wk))) continue; + aw->arc.a[wk].v = CNS_DEL_E; break; + } + assert(wk < aw->arc.n); + } + + for (vk = av->arc.nou; vk < av->arc.n; vk++) {///in-edge of src + if(del_cns_arc((*av), vk)) continue; + w = av->arc.a[vk].v; av->arc.a[vk].v = CNS_DEL_E; + + aw = &((*cns).a[w]); + for (wk = 0; wk < aw->arc.nou; wk++) {///out-edge of des + if((aw->arc.a[wk].v != v) || (del_cns_arc((*aw), wk))) continue; + aw->arc.a[wk].v = CNS_DEL_E; break; + } + assert(wk < aw->arc.n); + } + + + cns->a[v].arc.n = cns->a[v].arc.nou = 0; + cns->a[v].c = cns->a[v].f = 0; cns->a[v].sc = CNS_DEL_V; +} + +void merge_cns_g_in(cns_gfa *cns, uint32_t v0, asg32_v* b32) +{ + cns_t *av, *aw; uint32_t v, bp, vk, wk, wka, w, wn, nn, mn, wh, mn_k[2]; + + b32->n = 0; + kv_push(uint32_t, *b32, v0); + while (b32->n) { + v = b32->a[--b32->n]; + if(del_cns_nn((*cns), v)) continue; + + av = &((*cns).a[v]); + for (bp = 0; bp < 4; bp++) { + //nn: number of node; wh: weight + nn = wh = 0; mn = mn_k[0] = mn_k[1] = wka = (uint32_t)-1; + for (vk = av->arc.nou; vk < av->arc.n; vk++) {///in-edge of v + if(del_cns_arc((*av), vk)) continue; + w = av->arc.a[vk].v; aw = &((*cns).a[w]); + if(aw->c != bp) continue; + if(w == cns->si || w == cns->ei) continue; + + for (wk = wn = 0; wk < aw->arc.nou; wk++) {///out-edge of w + if(del_cns_arc((*aw), wk)) continue; + wn++; wka = wk; if(wn > 1) break; + } + + if(wn != 1) continue; + + assert(aw->arc.a[wka].v == v); + + ///deal with out-edge of w + if(nn == 0) { + mn = w; mn_k[0] = vk; mn_k[1] = wka; + wh = av->arc.a[vk].sc; + ///not sure if we should set these edges as visited + // av->arc.a[vk].f = 1; aw->arc.a[wka].f = 1; + } else { + wh += aw->arc.a[wka].sc; + } + + ///deal with in-edge of w + ///all edges to w, should be move to mn + if(nn > 0) {///not sure if we should set these edges as visited; affect when nn == 0 + for (wk = aw->arc.nou; wk < aw->arc.n; wk++) { + if(del_cns_arc((*aw), wk)) continue; + ///previously, aw->arc.a[wk].v -> w + ///currently, aw->arc.a[wk].v -> mn + /// if(nn == 0), then mn = w + gen_mm_cns_arc(cns, aw->arc.a[wk].v, mn, aw->arc.a[wk].sc/**(nn?(aw->arc.a[wk].sc):(0))**/, aw->arc.a[wk].f);///not sure if we should set these edges as visited + } + } + + ///mn != w + if(nn > 0) del_cns_g_nn(cns, w); + + nn++; + } + + if(nn) { + aw = &((*cns).a[mn]); + av->arc.a[mn_k[0]].sc = aw->arc.a[mn_k[1]].sc = wh; + // merge_cns_g_in(cns_gfa *cns, uint32_t v, asg32_v* b32) + kv_push(uint32_t, *b32, mn); + } + } + } +} + +void merge_cns_g_ou(cns_gfa *cns, uint32_t v0, asg32_v* b32) +{ + cns_t *av, *aw; uint32_t v, bp, vk, wk, wka, w, wn, nn, mn, wh, mn_k[2]; + + b32->n = 0; + kv_push(uint32_t, *b32, v0); + while (b32->n) { + v = b32->a[--b32->n]; + if(del_cns_nn((*cns), v)) continue; + + av = &((*cns).a[v]); + for (bp = 0; bp < 4; bp++) { + //nn: number of node; wh: weight + nn = wh = 0; mn = mn_k[0] = mn_k[1] = wka = (uint32_t)-1; + for (vk = 0; vk < av->arc.nou; vk++) {///ou-edge of v + if(del_cns_arc((*av), vk)) continue; + w = av->arc.a[vk].v; aw = &((*cns).a[w]); + if(aw->c != bp) continue; + if(w == cns->si || w == cns->ei) continue; + + for (wk = aw->arc.nou, wn = 0; wk < aw->arc.n; wk++) {///in-edge of w + if(del_cns_arc((*aw), wk)) continue; + wn++; wka = wk; if(wn > 1) break; + } + + if(wn != 1) continue; + + assert(aw->arc.a[wka].v == v); + + + ///deal with in-edge of w + if(nn == 0) { + mn = w; mn_k[0] = vk; mn_k[1] = wka; + wh = av->arc.a[vk].sc; + ///not sure if we should set these edges as visited + // av->arc.a[vk].f = 1; aw->arc.a[wka].f = 1; + } else { + wh += aw->arc.a[wka].sc; + } + + + ///deal with ou-edge of w + ///all edges from w, should be move to mn + if(nn > 0) {///not sure if we should set these edges as visited; affect when nn == 0 + for (wk = 0; wk < aw->arc.nou; wk++) { + if(del_cns_arc((*aw), wk)) continue; + ///previously, w -> aw->arc.a[wk].v + ///currently, mn -> aw->arc.a[wk].v + /// if(nn == 0), then mn = w + gen_mm_cns_arc(cns, mn, aw->arc.a[wk].v, aw->arc.a[wk].sc/**(nn?(aw->arc.a[wk].sc):(0))**/, aw->arc.a[wk].f);///not sure if we should set these edges as visited + } + } + + ///mn != w + if(nn > 0) del_cns_g_nn(cns, w); + + nn++; + } + + if(nn) { + aw = &((*cns).a[mn]); + // fprintf(stderr, "\n[M::%s] nn::%u, mn::%u\n", __func__, nn, mn); + // fprintf(stderr, "[M::%s] vi::%u, vn::%u\n", __func__, mn_k[0], (uint32_t)av->arc.n); + // fprintf(stderr, "[M::%s] wi::%u, wn::%u\n", __func__, mn_k[1], (uint32_t)aw->arc.n); + + av->arc.a[mn_k[0]].sc = aw->arc.a[mn_k[1]].sc = wh; + // merge_cns_g_in(cns_gfa *cns, uint32_t v, asg32_v* b32) + kv_push(uint32_t, *b32, mn); + } + } + } +} + +void refine_cns_g(cns_gfa *cns, asg32_v *b32) +{ + uint32_t v, w, vk, wk, *p = NULL; cns_t *av = NULL, *aw = NULL; + kdq_clear(cns->q); + kdq_push(uint32_t, cns->q, cns->si); ///in-degree == 0 + + while (1) { + p = kdq_shift(uint32_t, cns->q); + if(!p) {break;} v = *p; + + if(del_cns_nn((*cns), v)) continue; + ///merge in + merge_cns_g_in(cns, v, b32); + ///merge out + merge_cns_g_ou(cns, v, b32); + + av = &((*cns).a[v]); + ///set arcs + for (vk = 0; vk < av->arc.nou; vk++) {///out-edge of v + if(del_cns_arc((*av), vk)) continue; + if(av->arc.a[vk].f == 0) continue; + + av->arc.a[vk].f = 1; w = av->arc.a[vk].v; aw = &((*cns).a[w]); + + for (wk = aw->arc.nou; wk < aw->arc.n; wk++) {///in-edge of w + if((aw->arc.a[wk].v != v) || (del_cns_arc((*aw), wk))) continue; + aw->arc.a[wk].f = 1; break; + } + } + ///set node + av->f = 1; + + + for (vk = 0; vk < av->arc.nou; vk++) {///out-edge of v + if(del_cns_arc((*av), vk)) continue; + w = av->arc.a[vk].v; + + aw = &((*cns).a[w]); + for (wk = aw->arc.nou; wk < aw->arc.n; wk++) {///in-edge of w + if((del_cns_arc((*aw), wk))) continue; + if(aw->arc.a[wk].f) continue;///test arcs + if(cns->a[aw->arc.a[wk].v].f) continue;///test node + break; + } + if(wk >= aw->arc.n) { + kdq_push(uint32_t, cns->q, w); ///in-degree == 0 + } + } + } +} + +void gseq_cns_g(cns_gfa *cns, asg32_v *b32, uint32_t bl) +{ + b32->n = 0; kv_resize(uint32_t, *b32, cns->n); + uint32_t v, vk, w, mme, mmn, mmk, mmw, *ii = b32->a, *p; cns_t *av; + uint32_t bs = cns->off, be = bl + cns->off, sw; + for (v = 0; v < cns->n; v++) { + ii[v] = 0;///score + if(del_cns_nn((*cns), v)) continue; + cns->a[v].sc = 0; ///in-degree or prefix + cns->a[v].f = 0; + + av = &((*cns).a[v]); + for (vk = av->arc.nou; vk < av->arc.n; vk++) {///in-edge of v + if(del_cns_arc((*av), vk)) continue; + cns->a[v].sc++;///in-degree + } + } + + kdq_clear(cns->q); + kdq_push(uint32_t, cns->q, cns->si); ///in-degree == 0 + assert((cns->a[cns->si].sc == 0) && (!del_cns_nn((*cns), cns->si))); + + while (1) { + p = kdq_shift(uint32_t, cns->q); + if(!p) {break;} v = *p; + + if(del_cns_nn((*cns), v)) continue; + assert(cns->a[v].sc == 0); ///in-degree == 0 + + av = &((*cns).a[v]); + for (vk = av->arc.nou, mme = mmn = mmw = 0, mmk = (uint32_t)-1; vk < av->arc.n; vk++) {///in-edge of v + if(del_cns_arc((*av), vk)) continue; + w = av->arc.a[vk].v; + assert((*cns).a[w].f); + sw = ((w >= bs && w < be)?1:0); ///backbone + + if((mmk == ((uint32_t)-1)) || (av->arc.a[vk].sc > mme) || + (((av->arc.a[vk].sc == mme) && (ii[w] > mmn))) || + (((av->arc.a[vk].sc == mme) && (ii[w] == mmn) && (sw == 1) && (mmw == 0)))) { + mmk = vk; mme = av->arc.a[vk].sc; mmn = ii[w]; mmw = sw; + } + } + + ii[v] = mme + mmn; cns->a[v].f = 1; + if(mmk != ((uint32_t)-1)) cns->a[v].sc = av->arc.a[mmk].v; + else cns->a[v].sc = v; + + for (vk = 0; vk < av->arc.nou; vk++) {///out-edge of v + if(del_cns_arc((*av), vk)) continue; + w = av->arc.a[vk].v; + assert(cns->a[w].f == 0); + assert(cns->a[w].sc); + cns->a[w].sc--; + if(cns->a[w].sc == 0) { + kdq_push(uint32_t, cns->q, w); ///in-degree == 0 + } + } + + // fprintf(stderr, "[M::%s] sc[%u]::%u\n", __func__, v, ii[v]); + } + + for (v = cns->a[cns->ei].sc, b32->n = 0; v != cns->si; v = cns->a[v].sc) { + // fprintf(stderr, "[M::%s] v::%u\n", __func__, v); + kv_push(uint32_t, *b32, v); + } + assert(v == cns->si); + + mmn = b32->n; mmn >>= 1; + for (vk = 0; vk < mmn; vk++) { + v = b32->a[vk]; b32->a[vk] = b32->a[b32->n-vk-1]; b32->a[b32->n-vk-1] = v; + } +} + +uint64_t push_correct1(window_list *idx, window_list_alloc *res, cns_gfa *cns, asg32_v *rc, uint32_t bl) +{ + // fprintf(stderr, "[M::%s]\t", __func__); + uint64_t nec = 0; uint32_t k, l, i, ff, sl, sk, bs = cns->off, be = bl + cns->off, bend = cns->off;///[bs, be) + if(rc->n) {///it is possible that rc->n == 0, which means there is a deletion + for (k = 1, l = 0; k <= rc->n; ++k) { + ff = 0; sl = sk = 0; + if(k == rc->n) { + if(l < rc->n) sl = ((rc->a[l] >= bs && rc->a[l] < be)?1:0); + ff = 1; + } else { + sl = ((rc->a[l] >= bs && rc->a[l] < be)?1:0); + sk = ((rc->a[k] >= bs && rc->a[k] < be)?1:0); + if(sl != sk) { + ff = 1; + } else if((sl == 1) && ((rc->a[k] - rc->a[l]) != (k - l))) { + ff = 1; + } + } + + if(!ff) continue; + + if(sl) { ///match + if(rc->a[l] > bend) {///deltetion [bend, rc->a[l]) + push_trace_bp(((asg16_v *)(&(res->c))), 3, (uint16_t)-1, rc->a[l] - bend, ((idx->clen>0)?1:0)); + idx->clen = res->c.n - idx->cidx; nec += rc->a[l] - bend; + // fprintf(stderr, "%uD", rc->a[l] - bend); + } + + ///push match + push_trace_bp(((asg16_v *)(&(res->c))), 0, (uint16_t)-1, rc->a[k-1] + 1 - rc->a[l], ((idx->clen>0)?1:0)); + idx->clen = res->c.n - idx->cidx; + + // fprintf(stderr, "%uM", rc->a[k-1] + 1 - rc->a[l]); + + bend = rc->a[k-1] + 1; + } else { ///unmatch + for (i = l; i < k; i++) { + push_trace_bp(((asg16_v *)(&(res->c))), 2, cns->a[rc->a[i]].c, 1, ((idx->clen>0)?1:0)); + idx->clen = res->c.n - idx->cidx; nec++; + // fprintf(stderr, "I"); + } + } + l = k; + } + } + + ///push remaining deletion + if(be > bend) { + push_trace_bp(((asg16_v *)(&(res->c))), 3, (uint16_t)-1, be - bend, ((idx->clen>0)?1:0)); + idx->clen = res->c.n - idx->cidx; nec += be - bend; + // fprintf(stderr, "%uD", be - bend); + } + // fprintf(stderr, "\n"); + return nec; +} + +uint64_t push_correct1_fhc_indel_exz(asg16_v *sc, int64_t sc0, window_list *idx, cns_gfa *cns, char *ostr, UC_Read* tu, bit_extz_t *exz, uint64_t gbeg, uint64_t c0, int64_t cl0, int64_t ok0) +{ + int64_t ck = sc->n, k, ok = 0, nk = 0, cn, cn0, nl, ol, diff, diff0, ml, ml0, e0 = 0; uint32_t on, f = 0, nec = 0; uint16_t bq, bt, op; + assert(c0 == 3); + + ///debug + // char cm[4]; cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; + + // if(c0 != 2) ok += cl0; + // if(c0 != 3) nk += cl0; + ok += cl0; e0 += cl0; + + // fprintf(stderr, "\n%lu%c", cl0, cm[c0]); + + for (ck--; ck >= sc0/**0**/; ck--) { + op = sc->a[ck]>>14; + if(!op) break; + + if((op == 2) || (op == 3)) { + on = sc->a[ck]&(0xfff); + } else if(op == 1) { + on = sc->a[ck]&(0x3ff); + } else { + on = sc->a[ck]&(0x3fff); + } + if(op != 2) ok += on; + if(op != 3) nk += on; + if(op != 0) e0 += on; + if(c0 != op) f = 1; + + // fprintf(stderr, "%u%c(%c)", on, cm[op], "ACGT"[((sc->a[ck]>>12)&3)]); + } + cn0 = ck + 1; cn = sc->n; + // fprintf(stderr, "\n"); + + // fprintf(stderr, "+[M::%s] cn0::%ld, cn::%ld, ok::%ld, sc->n::%u, ok0::%ld, cl0::%ld\n", __func__, cn0, cn, ok, (uint32_t)sc->n, ok0, cl0); + // f = 0; + + if((!f) || (!ok) || (!nk)) { + for (k = 0, ck = ok0 + gbeg; k < cl0; k++, ck++) { + push_trace_bp_f(sc, c0, cns->a[ck].c, (uint16_t)-1, 1, ((idx->clen>0)?1:0)); + idx->clen = sc->n - idx->cidx; nec++; + // fprintf(stderr, "%c\n", "ACGT"[cns->a[ck].c]); + } + } else { + char *oseq = NULL, *nseq = NULL; int64_t wo[2], wn[2]; + UC_Read_resize((*tu), nk); nseq = tu->seq; wo[0] = wo[1] = wn[0] = wn[1] = 0; + // if(c0 != 2) ok0 += cl0; + ok0 += cl0; + + ok0 -= ok; + // if(!(ok0 >= 0)) { + // fprintf(stderr, "+[M::%s] rid::%u, cn0::%ld, cn::%ld, ok0::%ld, ok::%ld, sc->n::%u\n", __func__, rid, cn0, cn, ok0, ok, (uint32_t)sc->n); + // } + assert(ok0 >= 0); + + oseq = ostr + ok0; + ol = ok; nl = nk; + ck = cn0; ok = nk = 0; + while (ck < cn) { + wo[0] = ok; wn[0] = nk; + ck = pop_trace_bp_f(sc, ck, &op, &bq, &bt, &on); + if(op != 2) ok += on; + if(op != 3) nk += on; + wo[1] = ok; wn[1] = nk; + + if(op == 0) { + memcpy(nseq + wn[0], oseq + wo[0], (wo[1]-wo[0])*sizeof((*nseq))); + } else if(op == 1 || op == 2) { + for (k = wn[0]; k < wn[1]; k++) nseq[k] = s_H[bt]; + } + // fprintf(stderr, "[M::%s] ck::%ld, wo::[%ld, %ld), wn::[%ld, %ld)\n", __func__, ck, wo[0], wo[1], wn[0], wn[1]); + } + // fprintf(stderr, "[M::%s] qstr::%.*s*\n", __func__, (int32_t)ol, oseq); + // fprintf(stderr, "[M::%s] tstr::%.*s*\n", __func__, (int32_t)nl, nseq); + + assert(wo[1] + cl0 == ol); + assert(wn[1] == nl); ///since c0 must be 3 + // memcpy(nseq + wn[1], oseq + wo[1], cl0*sizeof((*nseq))); + if(nl == ol && nl == 1) { + sc->n = cn0; + if(oseq[0] == nseq[0]) { + push_trace_bp_f(sc, 0, (uint16_t)-1, (uint16_t)-1, 1, ((idx->clen>0)?1:0)); + idx->clen = sc->n - idx->cidx; + } else { + push_trace_bp_f(sc, 1, seq_nt6_table[(uint32_t)(oseq[0])], seq_nt6_table[(uint32_t)(nseq[0])], 1, ((idx->clen>0)?1:0)); + idx->clen = sc->n - idx->cidx; nec++; + } + } else { + ml = MAX(ol, nl); f = 0; + + diff = 31; + if(diff > ml) diff = ml; + diff0 = diff; clear_align(*exz); + cal_exz_global(nseq, nl, oseq, ol, diff, exz); + if(is_align(*exz)) f = 1; + + if(!f) { + diff = 63; + if(diff > ml) diff = ml; + if(diff > diff0) { + diff0 = diff; clear_align(*exz); + cal_exz_global(nseq, nl, oseq, ol, diff, exz); + if(is_align(*exz)) f = 1; + } + } + + // fprintf(stderr, "[M::%s] f::%u, exz->err::%d, e0::%ld\n", __func__, f, exz->err, e0); + + if(f && exz->err < e0) { + sc->n = cn0; + cn = exz->cigar.n; ok = nk = 0; + for (ck = 0; ck < cn;) { + wo[0] = ok; wn[0] = nk; + ck = pop_trace(&(exz->cigar), ck, &op, &on); + if(op!=2) ok += on; + if(op!=3) nk += on; + wo[1] = ok; wn[1] = nk; + + // fprintf(stderr, "%u%c(", on, cm[op]); + + if(op == 0) { + push_trace_bp_f(sc, op, (uint16_t)-1, (uint16_t)-1, on, ((idx->clen>0)?1:0)); + idx->clen = sc->n - idx->cidx; + } else if(op == 1) { + for (k = 0; k < on; k++) { + push_trace_bp_f(sc, op, seq_nt6_table[(uint32_t)(oseq[wo[0]+k])], seq_nt6_table[(uint32_t)(nseq[wn[0]+k])], 1, ((idx->clen>0)?1:0)); + idx->clen = sc->n - idx->cidx; nec++; + // fprintf(stderr, "<%c|%c>)", oseq[wo[0]+k], nseq[wn[0]+k]); + } + } else if(op == 2) { + for (k = 0; k < on; k++) { + push_trace_bp_f(sc, op, (uint16_t)-1, seq_nt6_table[(uint32_t)(nseq[wn[0]+k])], 1, ((idx->clen>0)?1:0)); + idx->clen = sc->n - idx->cidx; nec++; + // fprintf(stderr, "<|%c>)", nseq[wn[0]+k]); + } + } else if(op == 3) { + for (k = 0; k < on; k++) { + push_trace_bp_f(sc, op, seq_nt6_table[(uint32_t)(oseq[wo[0]+k])], (uint16_t)-1, 1, ((idx->clen>0)?1:0)); + idx->clen = sc->n - idx->cidx; nec++; + // fprintf(stderr, "<%c|>)", oseq[wo[0]+k]); + } + } + // fprintf(stderr, ")"); + } + // fprintf(stderr, "\n"); + } else { + if(ml < e0) { + sc->n = cn0; + ml0 = MIN(ol, nl); op = 1; + for (k = 0; k < ml0; k++) { + push_trace_bp_f(sc, op, seq_nt6_table[(uint32_t)(oseq[k])], seq_nt6_table[(uint32_t)(nseq[k])], 1, ((idx->clen>0)?1:0)); + idx->clen = sc->n - idx->cidx; nec++; + } + + if(ol > ml0) {///op = 3 + for (k = ml0, op = 3; k < ol; k++) { + push_trace_bp_f(sc, op, seq_nt6_table[(uint32_t)(oseq[k])], (uint16_t)-1, 1, ((idx->clen>0)?1:0)); + idx->clen = sc->n - idx->cidx; nec++; + } + } else if(nl > ml0) {///op = 2 + for (k = ml0, op = 2; k < nl; k++) { + push_trace_bp_f(sc, op, (uint16_t)-1, seq_nt6_table[(uint32_t)(nseq[k])], 1, ((idx->clen>0)?1:0)); + idx->clen = sc->n - idx->cidx; nec++; + } + } + } else { + for (k = 0, ck = ok0 + gbeg; k < cl0; k++, ck++) { + push_trace_bp_f(sc, c0, cns->a[ck].c, (uint16_t)-1, 1, ((idx->clen>0)?1:0)); + idx->clen = sc->n - idx->cidx; nec++; + } + } + } + } + } + + // fprintf(stderr, "-[M::%s] cn0::%ld, cn::%ld, ok::%ld, sc->n::%u\n", __func__, cn0, cn, ok, (uint32_t)sc->n); + return nec; +} + +uint64_t push_correct1_fhc(window_list *idx, window_list_alloc *res, cns_gfa *cns, char* qstr, UC_Read* tu, bit_extz_t *exz, asg32_v *rc, uint32_t bl, uint32_t rid) +{ + // fprintf(stderr, "[M::%s]\trc->n::%u\tbl::%u\n", __func__, (uint32_t)rc->n, bl); + uint64_t nec = 0; uint32_t k, l, i, ff, sl, sk, bs = cns->off, be = bl + cns->off, bend = cns->off, is_i = 0, sc0 = res->c.n;///[bs, be) + if(rc->n) {///it is possible that rc->n == 0, which means there is a deletion + for (k = 1, l = 0; k <= rc->n; ++k) { + ff = 0; sl = sk = 0; + if(k == rc->n) { + if(l < rc->n) sl = ((rc->a[l] >= bs && rc->a[l] < be)?1:0); + ff = 1; + } else { + sl = ((rc->a[l] >= bs && rc->a[l] < be)?1:0); + sk = ((rc->a[k] >= bs && rc->a[k] < be)?1:0); + if(sl != sk) { + ff = 1; + } else if((sl == 1) && ((rc->a[k] - rc->a[l]) != (k - l))) { + ff = 1; + } + } + + if(!ff) continue; + + if(sl) { ///match + if(rc->a[l] > bend) {///deltetion [bend, rc->a[l]) + if(is_i && exz) { + nec += push_correct1_fhc_indel_exz(((asg16_v *)(&(res->c))), sc0, idx, cns, qstr, tu, exz, cns->off, 3, rc->a[l] - bend, bend-cns->off); + } else { + for (i = bend; i < rc->a[l]; i++) { + push_trace_bp_f(((asg16_v *)(&(res->c))), 3, cns->a[i].c, (uint16_t)-1, 1, ((idx->clen>0)?1:0)); + idx->clen = res->c.n - idx->cidx; nec++; + } + } + } + + ///push match + push_trace_bp_f(((asg16_v *)(&(res->c))), 0, (uint16_t)-1, (uint16_t)-1, rc->a[k-1] + 1 - rc->a[l], ((idx->clen>0)?1:0)); + idx->clen = res->c.n - idx->cidx; + + bend = rc->a[k-1] + 1; is_i = 0; + } else { ///unmatch + for (i = l; i < k; i++) { + push_trace_bp_f(((asg16_v *)(&(res->c))), 2, (uint16_t)-1, cns->a[rc->a[i]].c, 1, ((idx->clen>0)?1:0)); + idx->clen = res->c.n - idx->cidx; nec++; + } + is_i = 1; + } + l = k; + } + } + + ///push remaining deletion + if(be > bend) { + if(is_i && exz) { + nec += push_correct1_fhc_indel_exz(((asg16_v *)(&(res->c))), sc0, idx, cns, qstr, tu, exz, cns->off, 3, be - bend, bend-cns->off); + } else { + for (i = bend; i < be; i++) { + push_trace_bp_f(((asg16_v *)(&(res->c))), 3, cns->a[i].c, (uint16_t)-1, 1, ((idx->clen>0)?1:0)); + idx->clen = res->c.n - idx->cidx; nec++; + } + } + } + // fprintf(stderr, "\n"); + return nec; +} + +///no e_end since e always covers end; s may not have end +uint64_t cns_gen_full0(overlap_region* ol, All_reads *rref, uint64_t s, uint64_t e, uint64_t s_end, char* qstr, UC_Read* tu, bit_extz_t *exz, cc_idx_t *idx, uint64_t occ_tot, double occ_max, asg32_v* b32, cns_gfa *cns, uint64_t max_trace, window_list *ridx, window_list_alloc *res, uint64_t o_rate, uint64_t h_rate, uint64_t q_hf, uint32_t rid) +{ + // if(e -s > 100) { + // fprintf(stderr, "[M::%s]::[%lu, %lu), cns->n::%u, qstr::%.*s\n", __func__, s, e, (uint32_t)cns->n, (int)(e-s), qstr+s); + // } + // fprintf(stderr, "[M::%s]::[%lu, %lu)\n", __func__, s, e); + + uint64_t *id_a = NULL, id_n, nec = 0, hf_f = ((o_rate == ((uint64_t)-1) || h_rate == ((uint64_t)-1))?(0):(1)), hw; b32->n = 0; + rr_seq_t ssq; ssq.rref = rref; ssq.tu = tu; ssq.s = ssq.e = 0; ssq.n0 = ssq.n1 = 32; ssq.id = ssq.rev = 0; + if(!hf_f) { + hw = 1; + } else { + if(q_hf) hw = h_rate; + else hw = o_rate; + } + init_cns_g(cns, qstr + s, e - s, hw, rid); + + id_n = iter_cc_idx_t(ol, idx, s, e, idx->rr, ((s==e)?1:0), &id_a); + // debug_inter0(ol, idx->c_idx, idx->idx->a + idx->i0, idx->srt_n - idx->i0, id_a, id_n, s, e, ((s==e)?1:0), 0, "-1-"); + uint64_t k, q[2], os, oe; ul_ov_t *p; overlap_region *z; idx->rr = 0; + // fprintf(stderr, "[M::%s] [%lu, %lu) id_n::%lu\n", __func__, s, e, id_n); + for (k = 0; k < id_n; k++) { + p = &(idx->c_idx[id_a[k]]); z = &(ol[ovlp_id(*p)]); + q[0] = z->w_list.a[ovlp_cur_wid(*p)].x_start+ovlp_bd(*p); + q[1] = z->w_list.a[ovlp_cur_wid(*p)].x_end+1-ovlp_bd(*p); + + // fprintf(stderr, "[M::%s] tid::%u\t%.*s\twid::%u\tq::[%u, %u)\terr::%d\toerr::%u\n", __func__, ol[ovlp_id(*p)].y_id, (int)Get_NAME_LENGTH(R_INF, ol[ovlp_id(*p)].y_id), Get_NAME(R_INF, ol[ovlp_id(*p)].y_id), + // ovlp_cur_wid(*p), ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].x_start, ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].x_end+1, ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].error, ol[ovlp_id(*p)].non_homopolymer_errors); + + if(q[1] <= e) idx->rr = 1; + os = MAX(q[0], s); oe = MIN(q[1], e); + // if((oe > os) || ((s == e) && (s >= q[0]) && (s <= q[1]))) { + if((oe > os) || ((s == e) && (s > q[0]) && (s < q[1]))) { + // if(oe >= os) { + ///[-4-][-12-][-4-][-12-] + ///[cigar_len][cigar][base_len][base] + if(!hf_f) { + hw = 1; + } else { + if(ovlp_hf((*p))) hw = h_rate; + else hw = o_rate; + } + extract_sub_cigar_cns(z, os, oe, s, e, s_end, &ssq, p, cns, b32, max_trace, hw, rid); + // if(m != ((uint32_t)-1)) {///no gap in both sides + // kv_push(uint32_t, *b32, m); + // } + } + } + + // fprintf(stderr, "-2-[M::%s] cns->n::%u\n", __func__, (uint32_t)cns->n); + + // return; + + refine_cns_g(cns, b32); + + // fprintf(stderr, "-3-[M::%s] cns->n::%u\n", __func__, (uint32_t)cns->n); + + gseq_cns_g(cns, b32, e - s); + + // fprintf(stderr, "-4-[M::%s] cns->n::%u\n", __func__, (uint32_t)cns->n); + + // nec += push_correct1(ridx, res, cns, b32, e - s); + nec += push_correct1_fhc(ridx, res, cns, qstr + s, tu, exz, b32, e - s, rid); + + // fprintf(stderr, "-5-[M::%s] cns->n::%u\n", __func__, (uint32_t)cns->n); + return nec; +} + +uint64_t cns_gen_full(overlap_region* ol, All_reads *rref, uint64_t s0, uint64_t e0, uint64_t wl, char* qstr, UC_Read* tu, bit_extz_t *exz, cc_idx_t *idx, uint64_t occ_tot, double occ_max, asg32_v* b32, cns_gfa *cns, uint64_t max_trace, window_list *ridx, window_list_alloc *res, uint64_t o_rate, uint64_t h_rate, uint64_t q_hf, uint32_t rid) +{ + uint64_t nec = 0; + if(e0 - s0 <= wl) { + nec += cns_gen_full0(ol, rref, s0, e0, 1, qstr, tu, exz, idx, occ_tot, occ_max, b32, cns, max_trace, ridx, res, o_rate, h_rate, q_hf, rid); + } else { + uint64_t s, e; + s = s0; e = s0 + wl; e = ((e<=e0)?e:e0); + for (; s < e0; ) { + // rn = iter_cc_idx_t(ol->list, &ii_a, s, e, rr, 0, &ra); + // debug_inter0(ol->list, ii_a.c_idx, ii_a.idx->a + ii_a.i0, ii_a.srt_n - ii_a.i0, ra, rn, s, e, 0, 1, "-0-"); + // rr = wcns_vote(ol->list, rref, qu->seq, ql, tu, ra, rn, s, e, ii_a.c_idx, &ii_b, occ_tot, occ_exact, aux_o, b32, cns, rid); + nec += cns_gen_full0(ol, rref, s, e, (s==s0)?1:0, qstr, tu, exz, idx, occ_tot, occ_max, b32, cns, max_trace, ridx, res, o_rate, h_rate, q_hf, rid); + s += wl; e += wl; e = ((e<=e0)?e:e0); + } + } + return nec; +} + +uint64_t push_correct0(window_list *idx, window_list_alloc *res, uint32_t len0, uint32_t rc) +{ + uint64_t nec = 0; + // fprintf(stderr, "[M::%s] NULL(idx)::%u\n", __func__, idx?0:1); + if(len0 != ((uint32_t)-1)) { + push_trace_bp(((asg16_v *)(&(res->c))), 0, (uint16_t)-1, len0, ((idx->clen>0)?1:0)); + idx->clen = res->c.n - idx->cidx; + } else if(rc != ((uint32_t)-1)) { + // fprintf(stderr, "[M::%s]\t", __func__); + uint32_t cc = (rc<<4)>>20, cn = rc>>28, ck = 0, cs, cp; + uint32_t bc = (rc<<20)>>20, bn = (rc<<16)>>28, bk = 0, bs, bp; + ///debug + // prt_cigar0(cc, cn); + // prt_bp0(bc, bn); + + for (ck = 0; ck < cn; ck++) { + cs = (cn-1-ck)<<1; cp = (cc>>cs)&3; + + bp = (uint32_t)-1; + if(cp != 3) {///bp == 3: more x + bs = (bn-1-bk)<<1; bp = (bc>>bs)&3; + bk++; + } + // fprintf(stderr, "[M::%s] cp::%u, bp::%u\n", __func__, cp, bp); + + push_trace_bp(((asg16_v *)(&(res->c))), cp, bp, 1, ((idx->clen>0)?1:0)); + idx->clen = res->c.n - idx->cidx; + // fprintf(stderr, "%c", cm[(in >> mp)&3]); + + // fprintf(stderr, "%c", "MSID"[cp]); + if(cp != 0) nec++; + } + + // fprintf(stderr, "\n"); + } + + return nec; +} + +uint64_t push_correct0_fhc(window_list *idx, window_list_alloc *res, uint32_t len0, uint32_t rc, char *qstr) +{ + uint64_t nec = 0; + // fprintf(stderr, "[M::%s] NULL(idx)::%u\n", __func__, idx?0:1); + if(len0 != ((uint32_t)-1)) { + push_trace_bp_f(((asg16_v *)(&(res->c))), 0, (uint16_t)-1, (uint16_t)-1, len0, ((idx->clen>0)?1:0)); + idx->clen = res->c.n - idx->cidx; + } else if(rc != ((uint32_t)-1)) { + // fprintf(stderr, "[M::%s]\t", __func__); + uint32_t cc = (rc<<4)>>20, cn = rc>>28, ck = 0, cs, cp; + uint32_t bc = (rc<<20)>>20, bn = (rc<<16)>>28, btk = 0, bqk = 0, bs, bqp, btp; + ///debug + // prt_cigar0(cc, cn); + // prt_bp0(bc, bn); + + for (ck = 0; ck < cn; ck++) { + cs = (cn-1-ck)<<1; cp = (cc>>cs)&3; + + bqp = btp = (uint32_t)-1; + if(cp != 3) {///bp == 3: more x + bs = (bn-1-btk)<<1; btp = (bc>>bs)&3; btk++; + } + if(cp != 2) {///bp == 2: more y + bqp = seq_nt6_table[(uint32_t)qstr[bqk]]; bqk++; + } + // fprintf(stderr, "[M::%s] cp::%u, btp::%u, bqp::%u\n", __func__, cp, btp, bqp); + + push_trace_bp_f(((asg16_v *)(&(res->c))), cp, bqp, btp, 1, ((idx->clen>0)?1:0)); + idx->clen = res->c.n - idx->cidx; + // fprintf(stderr, "%c", cm[(in >> mp)&3]); + + // fprintf(stderr, "%c", "MSID"[cp]); + if(cp != 0) nec++; + } + + // fprintf(stderr, "\n"); + } + + return nec; +} + +void output_cns_g(cns_gfa *cns, uint64_t s, uint64_t e) +{ + // char *gfa_id = NULL, p; MALLOC(gfa_id, Get_NAME_LENGTH(R_INF, qid) + 128); + // sprintf(gfa_id, "%.*s.%lu_%lu.cns.gfa", (int)Get_NAME_LENGTH(R_INF, qid), Get_NAME(R_INF, qid), s, e); + char *gfa_id = NULL, p, f; MALLOC(gfa_id, 128); + sprintf(gfa_id, "ec.%lu_%lu.cns.gfa", s, e); + + FILE *fp = fopen(gfa_id, "w"); uint64_t k, z; char cm[4]; cm[0] = 'A'; cm[1] = 'C'; cm[2] = 'G'; cm[3] = 'T'; + + sprintf(gfa_id, "s_0_%c", cm[cns->a[0].c]); + fprintf(fp, "S\t%s\t*\tLN:i:%u\trd:i:%c\n", gfa_id, 0/**cns->a[0].sc**/, cm[cns->a[0].c]); + + sprintf(gfa_id, "e_1_%c", cm[cns->a[1].c]); + fprintf(fp, "S\t%s\t*\tLN:i:%u\trd:i:%c\n", gfa_id, 0/**cns->a[1].sc**/, cm[cns->a[1].c]); + + for (k = 2; k < cns->n; k++) { + if(del_cns_nn((*cns), k)) continue; + sprintf(gfa_id, "%c_%lu_%c", ((kbn)?'b':'n'), k, cm[cns->a[k].c]); + fprintf(fp, "S\t%s\t*\tLN:i:%d\trd:i:%c\n", gfa_id, 0/**cns->a[k].sc**/, cm[cns->a[k].c]); + } + + for (k = 0; k < cns->n; k++) { + if(del_cns_nn((*cns), k)) continue; + + if(k == 0) { + p = 's'; + } else if(k == 1) { + p = 'e'; + } else if (kbn) { + p = 'b'; + } else { + p = 'n'; + } + + sprintf(gfa_id, "%c_%lu_%c", p, k, cm[cns->a[k].c]); + for (z = 0; z < cns->a[k].arc.n; z++) { + if(del_cns_arc((cns->a[k]), z)) continue; + + if(cns->a[k].arc.a[z].v == 0) { + p = 's'; + } else if(cns->a[k].arc.a[z].v == 1) { + p = 'e'; + } else if (cns->a[k].arc.a[z].v < cns->bn) { + p = 'b'; + } else { + p = 'n'; + } + + f = ((z < cns->a[k].arc.nou)?('+'):('-')); + fprintf(fp, "L\t%s\t%c\t%c_%u_%c\t%c\t0M\tL1:i:%u\n", + gfa_id, f, + p, cns->a[k].arc.a[z].v, cm[cns->a[cns->a[k].arc.a[z].v].c], f, + cns->a[k].arc.a[z].sc); + } + } + + fclose(fp); free(gfa_id); +} + +uint32_t cal_cigar_xlen(overlap_region *in) +{ + assert(in->w_list.n == 1); + uint32_t cn = in->w_list.a[0].clen; uint16_t *a = in->w_list.c.a + in->w_list.a[0].cidx; + uint32_t ci, len, xk, yk; uint16_t c, b; asg16_v scc; scc.n = scc.m = cn; scc.a = a; + + ci = 0; xk = yk = 0; + while (ci < cn) { + ci = pop_trace_bp(&scc, ci, &c, &b, &len); + if(c != 2) xk += len; + if(c != 3) yk += len; + } + + return xk; +} + +uint32_t cal_cigar_xlen_fhc(overlap_region *in) +{ + assert(in->w_list.n == 1); + uint32_t cn = in->w_list.a[0].clen; uint16_t *a = in->w_list.c.a + in->w_list.a[0].cidx; + uint32_t ci, len, xk, yk; uint16_t c, bq, bt; asg16_v scc; scc.n = scc.m = cn; scc.a = a; + + ci = 0; xk = yk = 0; + while (ci < cn) { + ci = pop_trace_bp_f(&scc, ci, &c, &bq, &bt, &len); + if(c != 2) xk += len; + if(c != 3) yk += len; + } + + return xk; +} + +uint64_t push_cns_anchor(overlap_region* ol, All_reads *rref, uint64_t s, uint64_t e, uint64_t q_hf, char* qstr, uint64_t ql, UC_Read* tu, bit_extz_t *exz, cc_idx_t *idx, overlap_region *aux_o, uint64_t is_tail, uint64_t occ_tot, double occ_max, asg32_v* b32, cns_gfa *cns, uint32_t rid, uint64_t o_rate, uint64_t h_rate) +{ + if((!is_tail) && (s >= e)) return 0;//if s >= e && is_tail = 1, gen the cns of the last a few bases -> s == e == ql + // fprintf(stderr, "\n****************[M::%s::M] [%lu, %lu)****************\n", __func__, s, e); + window_list *p = NULL; uint64_t e0 = 0, nec = 0; uint32_t rc; + if(aux_o->w_list.n > 0) { + p = &(aux_o->w_list.a[aux_o->w_list.n-1]); + e0 = p->x_end+1; + ///make sure e > s + } + assert(s >= e0); + if((s == e) && (is_tail == 1) && (s == e0)) return 0;///in this case, s == e == ql + + if(aux_o->w_list.n == 0) { + kv_pushp(window_list, aux_o->w_list, &p); + p->x_start = -1; p->x_end = -1; + p->clen = p->cidx = 0; + } + + if(((!is_tail) && (s > 0)) || ((is_tail) && (s > e0))) { + // fprintf(stderr, ">>>>>>[M::%s::M] [%lu, %lu), ec::%u\n", __func__, e0, s, cal_cigar_xlen_fhc(aux_o)); + // fprintf(stderr, ">>>>>>[M::%s::M] [%lu, %lu)\n", __func__, e0, s); + if (cns_gen0(ol, rref, e0, s, ql, tu, idx, occ_tot, occ_max, b32, o_rate, h_rate, q_hf, &rc)) { + if(p->x_start == -1 || p->x_end == -1) {///hasn't neem set + p->x_start = e0; p->x_end = s-1; + } + // nec += push_correct0(p, &(aux_o->w_list), (uint32_t)-1, rc); + nec += push_correct0_fhc(p, &(aux_o->w_list), (uint32_t)-1, rc, qstr + e0); + // fprintf(stderr, "-0-[M::%s::M]\n", __func__); + } else { + nec += cns_gen_full(ol, rref, e0, s, cns->cns_g_wl, qstr, tu, exz, idx, occ_tot, occ_max, b32, cns, ql, p, &(aux_o->w_list), o_rate, h_rate, q_hf, rid); + // output_cns_g(cns, e0, s); exit(1); + // fprintf(stderr, "-1-[M::%s::M]\n", __func__); + } + p->x_end = s-1; + + // if((uint32_t)p->x_end + 1 != cal_cigar_xlen_fhc(aux_o)) { + // fprintf(stderr, "sb1::%u\n", cal_cigar_xlen_fhc(aux_o)); + // } + } + + + // fprintf(stderr, "------[M::%s::M] [%lu, %lu), ec::%u\n", __func__, s, e, cal_cigar_xlen_fhc(aux_o)); + // fprintf(stderr, "------[M::%s::M] [%lu, %lu)\n", __func__, s, e); + if(p->x_start == -1 || p->x_end == -1) {///hasn't neem set + p->x_start = s; p->x_end = e-1; + } + // nec += push_correct0(p, &(aux_o->w_list), e-s, (uint32_t)-1); + nec += push_correct0_fhc(p, &(aux_o->w_list), e-s, (uint32_t)-1, NULL); + p->x_end = e-1; + // if((uint32_t)p->x_end + 1 != cal_cigar_xlen_fhc(aux_o)) { + // fprintf(stderr, "ta2::%u\n", cal_cigar_xlen_fhc(aux_o)); + // } + return nec; +} + +void prt_correct0_dbg(overlap_region *in) +{ + int64_t wn = in->w_list.n, k; uint32_t ci, len; asg16_v ff; uint16_t c, b; + char cm[4], cc[4]; + cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; + cc[0] = 'A'; cc[1] = 'C'; cc[2] = 'G'; cc[3] = 'T'; + + for (k = 0; k < wn; k++) { + fprintf(stderr, "\n[M::%s] w[%ld] [%d, %d) clen::%u\n", __func__, k, in->w_list.a[k].x_start, in->w_list.a[k].x_end + 1, in->w_list.a[k].clen); + + ci = 0; ff.n = ff.m = in->w_list.a[k].clen; ff.a = in->w_list.c.a + in->w_list.a[k].cidx; + while (ci < ff.n) { + ci = pop_trace_bp(&ff, ci, &c, &b, &len); + fprintf(stderr, "|%u%c(%c)", len, cm[c], ((c==1)||(c==2))?(cc[b]):('*')); + } + + fprintf(stderr, "|\n"); + } +} + +uint64_t wcns_vote(overlap_region* ol, All_reads *rref, uint64_t q_hf, char* qstr, uint64_t ql, UC_Read* tu, bit_extz_t *exz, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, ul_ov_t *c_idx, cc_idx_t *occ, uint64_t occ_tot, double occ_exact, overlap_region *aux_o, asg32_v* b32, cns_gfa *cns, uint32_t rid, uint64_t *nec, uint64_t o_rate, uint64_t h_rate, asg64_v *hf_idx) +{ + uint64_t k, q[2], rr = 0, os, oe, wl, oc[2], fI, ow[2]; ul_ov_t *p, *gp; overlap_region *z; + // uint64_t *ct = occ->idx->a;///occ->idx->a[0, wl<<1) + for (k = 0; k < id_n; k++) { + p = &(c_idx[id_a[k]]); z = &(ol[ovlp_id(*p)]); + q[0] = z->w_list.a[ovlp_cur_wid(*p)].x_start+ovlp_bd(*p); + q[1] = z->w_list.a[ovlp_cur_wid(*p)].x_end+1-ovlp_bd(*p); + if(q[1] <= e) rr = 1; + os = MAX(q[0], s); oe = MIN(q[1], e); + if(oe > os) { + ///prepare for CNS + gp = &(occ->c_idx[id_a[k]]); + ovlp_cur_xoff(*gp) = ovlp_cur_xoff(*p); ovlp_cur_yoff(*gp) = ovlp_cur_yoff(*p); ovlp_cur_coff(*gp) = ovlp_cur_coff(*p); ovlp_cur_ylen(*gp) = ovlp_cur_ylen(*p); ovlp_hf(*gp) = ovlp_hf(*p); + // assert(ovlp_cur_wid(*p) == ovlp_cur_wid(*gp)); + // assert(ovlp_id(*p) == ovlp_id(*gp)); + // fprintf(stderr, "[M::%s] tid::%u\t%.*s\twid::%u\tq::[%u, %u)\tos::%lu\toe::%lu\n", __func__, ol[ovlp_id(*p)].y_id, (int)Get_NAME_LENGTH(R_INF, ol[ovlp_id(*p)].y_id), Get_NAME(R_INF, ol[ovlp_id(*p)].y_id), + // ovlp_cur_wid(*p), ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].x_start, ol[ovlp_id(*p)].w_list.a[ovlp_cur_wid(*p)].x_end+1, os, oe); + extract_sub_cigar_mm(z, os, oe, p, occ->idx->a + os - s, (((hf_idx) && (ovlp_hf(*p)))?(hf_idx->a + os - s):(NULL))); + } + } + + wl = e - s; + os = occ->mms; oe = occ->mme; + + // fprintf(stderr, "[M::%s] s::%lu\te::%lu\n", __func__, s, e); + + for (k = 0; k < wl; k++) { + //+1 for the reference read + oc[0] = (occ->idx->a[(k<<1)]>>32) + 1; + oc[1] = ((uint32_t)occ->idx->a[(k<<1)]) + 1; + ow[0] = ow[1] = 0; + if(hf_idx) { + ow[0] = cal_occ_w((hf_idx->a[(k<<1)]>>32) + q_hf, oc[0], h_rate, o_rate); + ow[1] = cal_occ_w(((uint32_t)hf_idx->a[(k<<1)]) + q_hf, oc[1], h_rate, o_rate); + } + // fprintf(stderr, "-0-p::%lu\toc[0]::%lu\toc[1]::%lu\tgoc[0]::%lu\tgoc[1]::%u\n", s + k, oc[0], oc[1], (ct[(k<<1)+1]>>32) + 1, ((uint32_t)ct[(k<<1)+1]) + 1); + // if(oc[1] < occ_tot || oc[0] <= 1) { + // ct[(k<<1)] = ct[(k<<1)+1] = 0; + // continue; + // } + // fprintf(stderr, "-1-p::%lu\toc[0]::%lu\toc[1]::%lu\n", s + k, oc[0], oc[1]); + + ///a) pass coverage check; b) no enough coverage + ///occ_exact = 0.500001; occ_tot = 3; + if(((oc[0] > (oc[1]*occ_exact)) && (oc[0] > (oc[1]-oc[0])) && (oc[1] >= occ_tot) && (oc[0] > 1) && ((!hf_idx) || ((ow[0] > (ow[1]*occ_exact)) && (ow[0] > (ow[1] - ow[0]))))) || (oc[1] < occ_tot)) { + ///note: there might be insertions at q[k-1, k], insead if q[k, k+1] + fI = 1; + ///make sure there is no insertion + //+1 for the reference read + oc[0] = (occ->idx->a[(k<<1)+1]>>32) + 1; + oc[1] = ((uint32_t)occ->idx->a[(k<<1)+1]) + 1; + if(hf_idx) { + ow[0] = cal_occ_w((hf_idx->a[(k<<1)+1]>>32) + q_hf, oc[0], h_rate, o_rate); + ow[1] = cal_occ_w(((uint32_t)hf_idx->a[(k<<1)+1]) + q_hf, oc[1], h_rate, o_rate); + } + ///a) pass coverage check; b) no enough coverage + if((((oc[0] > (oc[1]*occ_exact)) && (oc[0] > (oc[1]-oc[0])) && (oc[1] >= occ_tot) && (oc[0] > 1) && ((!hf_idx) || ((ow[0] > (ow[1]*occ_exact)) && (ow[0] > (ow[1] - ow[0])))))) || (oc[1] < occ_tot)) { + fI = 0; + } + + if(fI) { + // fprintf(stderr, "-1-p::%lu\toc[0]::%lu\toc[1]::%u\tgoc[0]::%lu\tgoc[1]::%u\n", s + k, (occ->idx->a[(k<<1)]>>32) + 1, ((uint32_t)occ->idx->a[(k<<1)]) + 1, (occ->idx->a[(k<<1)+1]>>32) + 1, ((uint32_t)occ->idx->a[(k<<1)+1]) + 1); + if(oe > os && os != ((uint64_t)-1)) {///push previous intervals + (*nec) += push_cns_anchor(ol, rref, os, oe, q_hf, qstr, ql, tu, exz, occ, aux_o, 0, occ_tot, occ_exact, b32, cns, rid, o_rate, h_rate); + } + os = oe = (uint64_t)-1; + } + + //+1 for the reference read + oc[0] = (occ->idx->a[(k<<1)]>>32) + 1; + oc[1] = ((uint32_t)occ->idx->a[(k<<1)]) + 1; + if((s+k) == oe) { + oe++; + } else { + if(oe > os && os != ((uint64_t)-1)) {///push previous intervals + (*nec) += push_cns_anchor(ol, rref, os, oe, q_hf, qstr, ql, tu, exz, occ, aux_o, 0, occ_tot, occ_exact, b32, cns, rid, o_rate, h_rate); + } + os = s+k; oe = s+k+1; + } + } else { + // fprintf(stderr, "-2-p::%lu\toc[0]::%lu\toc[1]::%u\tgoc[0]::%lu\tgoc[1]::%u\n", s + k, (occ->idx->a[(k<<1)]>>32) + 1, ((uint32_t)occ->idx->a[(k<<1)]) + 1, (occ->idx->a[(k<<1)+1]>>32) + 1, ((uint32_t)occ->idx->a[(k<<1)+1]) + 1); + if(oe > os && os != ((uint64_t)-1)) {///push previous intervals + (*nec) += push_cns_anchor(ol, rref, os, oe, q_hf, qstr, ql, tu, exz, occ, aux_o, 0, occ_tot, occ_exact, b32, cns, rid, o_rate, h_rate); + } + os = oe = (uint64_t)-1; + } + occ->idx->a[(k<<1)] = occ->idx->a[(k<<1)+1] = 0; + if(hf_idx) { + hf_idx->a[(k<<1)] = hf_idx->a[(k<<1)+1] = 0; + } + } + + occ->mms = occ->mme = (uint64_t)-1; + if(oe > os && os != ((uint64_t)-1)) { + occ->mms = os; occ->mme = oe; + } + return rr; +} + + + +void print_debug_ovlp_cigar(overlap_region_alloc* ol, asg64_v* idx, kv_ul_ov_t *c_idx) +{ + uint64_t k, ci; uint32_t cl; ul_ov_t *cp; bit_extz_t ez; uint16_t c; char cm[4]; + cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; + for (k = 0; k < idx->n; k++) { + cp = &(c_idx->a[(uint32_t)idx->a[k]]); + fprintf(stderr, "**********[M::%s] tid::%u\t%.*s\twid::%u\tq::[%u, %u)\terr::%d\toerr::%u**********\n", __func__, ol->list[ovlp_id(*cp)].y_id, (int)Get_NAME_LENGTH(R_INF, ol->list[ovlp_id(*cp)].y_id), Get_NAME(R_INF, ol->list[ovlp_id(*cp)].y_id), + ovlp_cur_wid(*cp), ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start, ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1, ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].error, ol->list[ovlp_id(*cp)].non_homopolymer_errors); + set_bit_extz_t(ez, ol->list[ovlp_id(*cp)], ovlp_cur_wid(*cp)); ci = 0; + while (ci < ez.cigar.n) { + ci = pop_trace(&(ez.cigar), ci, &c, &cl); + fprintf(stderr, "%u%c", cl, cm[c]); + } + fprintf(stderr, "\n"); + } +} + +uint64_t wcns_gen(overlap_region_alloc* ol, All_reads *rref, uint64_t qid, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, kv_ul_ov_t *c_idx, asg64_v* idx, asg64_v* buf, int64_t bd, uint64_t wl, int64_t ql, uint64_t occ_tot, double occ_exact, overlap_region *aux_o, asg32_v* b32, cns_gfa *cns, uint64_t cns_g_wl, uint32_t rid, uint64_t tcut, asg64_v *hf_idx) +{ + int64_t on = ol->length, k, i, zwn, q[2]; cns->cns_g_wl = cns_g_wl; + uint64_t m, *ra, rn, nec = 0, n_id, l_nid, p[2], li; uint64_t o_rate = ((uint64_t)-1), h_rate = ((uint64_t)-1); overlap_region *z; ul_ov_t *cp; + bit_extz_t ez; uint64_t ci; uint32_t cl; uint16_t c, hf; + if(hf_idx) { + o_rate = asm_opt.ont_rate; + h_rate = ceil(((double)rref->tr[0])/((double)rref->tr[1]))*asm_opt.hf_rate; h_rate = MAX(h_rate, asm_opt.hf_rate_max); + if(o_rate == 0) h_rate = 1; + } + + for (k = idx->n = c_idx->n = 0; k < on; k++) { + z = &(ol->list[k]); zwn = z->w_list.n; z->without_large_indel = l_nid = 0; + if((!zwn) || (z->is_match != 1)) continue; + hf = ((z->y_id >= tcut)?(1):(0)); + for (i = 0, li = (uint64_t)-1; i < zwn; i++) { + if(is_ualn_win(z->w_list.a[i])) { + n_id = z->w_list.a[i].x_end + 1 - z->w_list.a[i].x_start; + if(n_id >= 6) l_nid = 1; + continue; + } + q[0] = z->w_list.a[i].x_start; q[1] = z->w_list.a[i].x_end; + q[0] += bd; q[1] -= bd; + if(q[1] >= q[0]) { + m = ((uint64_t)q[0]); m <<= 32; + m += c_idx->n; kv_push(uint64_t, *idx, m); + + kv_pushp(ul_ov_t, *c_idx, &cp); + ovlp_id(*cp) = k; ///ovlp id + // ovlp_min_wid(*cp) = i; ///beg id of windows + // ovlp_max_wid(*cp) = i; ///end id of windows + ovlp_cur_wid(*cp) = i; ///cur id of windows + ovlp_cur_xoff(*cp) = z->w_list.a[i].x_start; ///cur xpos + ovlp_cur_yoff(*cp) = z->w_list.a[i].y_start; ///cur xpos + ovlp_cur_ylen(*cp) = 0; + ovlp_cur_coff(*cp) = 0; ///cur cigar off in cur window + ovlp_bd(*cp) = bd; + ovlp_hf(*cp) = hf; + } + + if(l_nid == 0) { + if(i == 0) { + p[0] = z->w_list.a[i].x_start; p[1] = z->x_pos_s; + n_id = ((p[0] >= p[1])? (p[0] - p[1]): (p[1] - p[0])); + if(n_id >= 6) l_nid = 1; + } + + if(li != (uint64_t)-1) { + p[0] = z->w_list.a[i].x_start; p[1] = z->w_list.a[li].x_end + 1; + n_id = ((p[0] >= p[1])? (p[0] - p[1]): (p[1] - p[0])); + if(n_id >= 6) l_nid = 1; + + p[0] = z->w_list.a[i].y_start; p[1] = z->w_list.a[li].y_end + 1; + n_id = ((p[0] >= p[1])? (p[0] - p[1]): (p[1] - p[0])); + if(n_id >= 6) l_nid = 1; + } + + if(i + 1 == zwn) { + p[0] = z->w_list.a[i].x_end; p[1] = z->x_pos_e; + n_id = ((p[0] >= p[1])? (p[0] - p[1]): (p[1] - p[0])); + if(n_id >= 6) l_nid = 1; + } + + if(l_nid == 0) { + set_bit_extz_t(ez, (*z), i); ci = 0; + while (ci < ez.cigar.n && l_nid == 0) { + ci = pop_trace(&(ez.cigar), ci, &c, &cl); + if(c >= 2 && cl >= 6) l_nid = 1; + } + } + } + + li = i; + } + z->without_large_indel = (l_nid?0:1); + } + + int64_t srt_n = idx->n, s, e, t, rr; i = 0; + radix_sort_ec64(idx->a, idx->a+idx->n); + for (k = 1, i = 0; k < srt_n; k++) { + if (k == srt_n || (idx->a[k]>>32) != (idx->a[i]>>32)) { + if(k - i > 1) { + for (t = i; t < k; t++) { + cp = &(c_idx->a[(uint32_t)idx->a[t]]); + // s = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_start+ovlp_bd(*cp); + // assert(s == (int64_t)(idx->a[i]>>32)); + m = ol->list[ovlp_id(*cp)].w_list.a[ovlp_cur_wid(*cp)].x_end+1-ovlp_bd(*cp); + m <<= 32; m += ((uint32_t)idx->a[t]); idx->a[t] = m; + // fprintf(stderr, "[M::%s] s::%ld\tsi::%lu\n", __func__, s, (idx->a[i]>>32)); + } + radix_sort_ec64(idx->a + i, idx->a + k); + } + i = k; + } + } + + // print_debug_ovlp_cigar(ol, idx, c_idx); + + ///second index + kv_resize(ul_ov_t, *c_idx, (c_idx->n<<1)); + ul_ov_t *idx_a = NULL, *idx_b = NULL; + idx_a = c_idx->a; idx_b = c_idx->a; + memcpy(idx_b, idx_a, c_idx->n * (sizeof((*(idx_a))))); + + kv_resize(uint64_t, *buf, ((wl<<1) + idx->n)); buf->n = ((wl<<1) + idx->n); + memcpy(buf->a + (wl<<1), idx->a, idx->n * (sizeof((*(idx->a))))); + memset(buf->a, 0, (wl<<1)*(sizeof((*(idx->a))))); + if(hf_idx) { + kv_resize(uint64_t, *hf_idx, (wl<<1)); hf_idx->n = wl<<1; + memset(hf_idx->a, 0, (wl<<1)*(sizeof((*(hf_idx->a))))); + } + + cc_idx_t ii_a, ii_b; memset(&ii_a, 0, sizeof(ii_a)); memset(&ii_b, 0, sizeof(ii_b)); + + ii_a.c_idx = idx_a; ii_a.idx = idx; ii_a.i = ii_a.i0 = 0; ii_a.srt_n = ii_a.idx->n; ii_a.mms = ii_a.mme = (uint64_t)-1; + ii_b.c_idx = idx_b; ii_b.idx = buf; ii_b.i = ii_b.i0 = (wl<<1); ii_b.srt_n = ii_b.idx->n; ii_b.mms = ii_b.mme = (uint64_t)-1; + + s = 0; e = wl; e = ((e<=ql)?e:ql); rr = 0; + aux_o->w_list.n = aux_o->w_list.c.n = 0; ///for cigar + for (; s < ql; ) { + rn = iter_cc_idx_t(ol->list, &ii_a, s, e, rr, 0, &ra); + // debug_inter0(ol->list, ii_a.c_idx, ii_a.idx->a + ii_a.i0, ii_a.srt_n - ii_a.i0, ra, rn, s, e, 0, 1, "-0-"); + rr = wcns_vote(ol->list, rref, ((qid>=tcut)?(1):(0)), qu->seq, ql, tu, exz, ra, rn, s, e, ii_a.c_idx, &ii_b, occ_tot, occ_exact, aux_o, b32, cns, rid, &nec, o_rate, h_rate, hf_idx); + s += wl; e += wl; e = ((e<=ql)?e:ql); + } + + if(ii_b.mme > ii_b.mms && ii_b.mms != (uint64_t)-1) { + nec += push_cns_anchor(ol->list, rref, ii_b.mms, ii_b.mme, ((qid>=tcut)?(1):(0)), qu->seq, ql, tu, exz, &ii_b, aux_o, 0, occ_tot, occ_exact, b32, cns, rid, o_rate, h_rate); + } + + nec += push_cns_anchor(ol->list, rref, ql, ql, ((qid>=tcut)?(1):(0)), qu->seq, ql, tu, exz, &ii_b, aux_o, 1, occ_tot, occ_exact, b32, cns, rid, o_rate, h_rate); + + + + ///for debug + // zwn = aux_o->w_list.n; + // fprintf(stderr, "\n******[M::%s]****** wn::%ld, ql::%ld\n", __func__, zwn, ql); + // prt_correct0_dbg(aux_o); + // for (i = 0; i < zwn; i++) { + // fprintf(stderr, "[M::%s] (%ld)[%d, %d)\n", __func__, i, aux_o->w_list.a[i].x_start, aux_o->w_list.a[i].x_end+1); + // } + return nec; +} + +void push_nec_re(overlap_region *in, asg16_v *ou) +{ + assert(in->w_list.n == 1); + uint32_t n1 = in->w_list.a[0].clen; + if(n1 > ou->m) { + REALLOC(ou->a, n1); ou->m = n1; + } + ou->n = n1; + memcpy(ou->a, in->w_list.c.a + in->w_list.a[0].cidx, n1*sizeof((*(in->w_list.c.a)))); +} + +uint32_t extract_max_exact_sub(asg16_v *in, int64_t xs0, int64_t xe0, int64_t ys0, int64_t ye0, int64_t *exk, int64_t *eyk, int64_t *eck, uint64_t *rxs, uint64_t *rxe, uint64_t *rys, uint64_t *rye) +{ + int64_t xk = *exk, yk = *eyk, ck = *eck, cn = in->n, ol, wx[2], wy[2], os, oe; uint16_t op, bq, bt; uint32_t cl, ovlp; + *rxs = *rxe = *rys = *rye = 0; + + if((ck < 0) || (ck > cn)) {//(*ck) == cn is allowed + ck = 0; xk = 0; yk = 0; + } + + while (ck > 0 && xk >= xs0) {///x -> t; y -> p; first insertion and then match/mismatch + --ck; + op = in->a[ck]>>14; + // ol = (((op == 1) || (op == 2))?(in->a[ck]&(0xfff)):(in->a[ck]&(0x3fff))); + if((op == 2) || (op == 3)) { + ol = in->a[ck]&(0xfff); + } else if(op == 1) { + ol = in->a[ck]&(0x3ff); + } else { + ol = in->a[ck]&(0x3fff); + } + if(op != 2) xk -= ol; + if(op != 3) yk -= ol; + } + + while (ck < cn && xk < xe0) { + wx[0] = xk; wy[0] = yk; + // ck = pop_trace_bp(in, ck, &op, &b, &cl); + ck = pop_trace_bp_f(in, ck, &op, &bq, &bt, &cl); + if(op != 2) xk += cl; + if(op != 3) yk += cl; + wx[1] = xk; wy[1] = yk; + if(op == 0) { + os = MAX(xs0, wx[0]); oe = MIN(xe0, wx[1]); + ovlp = ((oe>os)? (oe-os):0); + if((ovlp > 0) && (ovlp > (*rxe) - (*rxs))) { + (*rxs) = wy[0] + os - wx[0]; + (*rxe) = wy[0] + oe - wx[0]; + + (*rys) = ys0 + os - xs0; + (*rye) = ys0 + oe - xs0; + } + } + } + + *exk = xk; *eyk = yk; *eck = ck; + if((*rxe) > (*rxs)) return 1; + return 0; +} + +void debug_extract_max_exact_sub(uint32_t qid, UC_Read* qu, UC_Read* tu) +{ + uint32_t ci = 0, len, xk, yk, wx[2], wy[2], k; uint16_t c, b; + + recover_UC_Read(tu, &R_INF, qid); + + ci = 0; yk = 0; + while (ci < scc.a[qid].n) { + ci = pop_trace_bp(&scc.a[qid], ci, &c, &b, &len); + if(c != 3) yk += len; + } + resize_UC_Read(qu, yk); + + ci = 0; xk = yk = 0; + while (ci < scc.a[qid].n) { + wx[0] = xk; wy[0] = yk; + ci = pop_trace_bp(&scc.a[qid], ci, &c, &b, &len); + if(c != 2) xk += len; + if(c != 3) yk += len; + wx[1] = xk; wy[1] = yk; + if(c == 0) { + // memcpy(p->a + wy[0], p->z.seq + wx[0], (wx[1]-wx[0])*sizeof((*(p->a)))); + for (; wx[0] < wx[1]; wx[0]++, wy[0]++) { + qu->seq[wy[0]] = tu->seq[wx[0]]; + } + } else if(c == 1 || c == 2) { + for (k = wy[0]; k < wy[1]; k++) { + qu->seq[k] = s_H[b]; + } + } + // if(i == 700) fprintf(stderr, "|%u%c(%c)(x::%u)(y::%u)", len, cm[c], ((c==1)||(c==2))?(cc[b]):('*'), wx[1], wy[1]); // s_H + } +} + +uint64_t extract_max_exact(overlap_region *z, asg16_v *ec, /**UC_Read *qu, UC_Read *tu,**/ uint32_t *rxs, uint32_t *rxe, uint32_t *rys, uint32_t *rye) +{ + // if(z->x_id == 75 && z->y_id == 59) { + // fprintf(stderr, "[M::%s]\tz->y_id::%u\n", __func__, z->y_id); + // if(z->y_pos_strand) { + // recover_UC_Read_RC(tu, &R_INF, z->y_id); + // } else { + // recover_UC_Read(tu, &R_INF, z->y_id); ///b->z.length + // } + // } + + *rxs = *rxe = *rys = *rye = (uint32_t)-1; + uint64_t k, rx[2], ry[2], xk, yk, wx[2], wy[2], mx[2], my[2]; + uint32_t cl, ck; uint16_t c; asg16_v ct; int64_t exk, eyk, eck; + exk = eyk = eck = 0; mx[0] = mx[1] = my[0] = my[1] = 0; + for (k = 0; k < z->w_list.n; k++) { + ct.a = z->w_list.c.a + z->w_list.a[k].cidx; + ct.n = ct.m = z->w_list.a[k].clen; ck = 0; + xk = z->w_list.a[k].x_start; yk = z->w_list.a[k].y_start; + while (ck < ct.n) { + wx[0] = xk; wy[0] = yk; + ck = pop_trace(&ct, ck, &c, &cl); + if(c != 2) xk += cl; + if(c != 3) yk += cl; + wx[1] = xk; wy[1] = yk; + // if(c == 0) { + // if(memcmp(qref + wx[0], tu->seq + wy[0], wx[1] - wx[0])) { + // fprintf(stderr, "-0-[M::%s]\teq::[%lu,\t%lu)\tet::[%lu,\t%lu)\t%c\n", __func__, wx[0], wx[1], wy[0], wy[1], "+-"[z->y_pos_strand]); + // // exit(1); + // } + // } + if(wx[1] <= wx[0]) continue; + if((wx[1] - wx[0]) <= (mx[1] - mx[0])) continue; + if((c == 0) && (extract_max_exact_sub(ec, wx[0], wx[1], wy[0], wy[1], &exk, &eyk, &eck, &(rx[0]), &(rx[1]), &(ry[0]), &(ry[1])))) { + // if(z->x_id == 75 && z->y_id == 59) { + // if(memcmp(qu->seq + rx[0], tu->seq + ry[0], rx[1] - rx[0])) { + // fprintf(stderr, "-1-[M::%s]\tzq::[%lu,\t%lu)\tzt::[%lu,\t%lu)\teq::[%lu,\t%lu)\tet::[%lu,\t%lu)\n", + // __func__, wx[0], wx[1], wy[0], wy[1], rx[0], rx[1], ry[0], ry[1]); + // exit(1); + // } + // else { + // fprintf(stderr, "-2-[M::%s]\tzq::[%lu,\t%lu)\tzt::[%lu,\t%lu)\teq::[%lu,\t%lu)\tet::[%lu,\t%lu)\n", + // __func__, wx[0], wx[1], wy[0], wy[1], rx[0], rx[1], ry[0], ry[1]); + + // fprintf(stderr, "[M::%s] qstr::%.*s\n", __func__, ((int)(rx[1] - rx[0])), qu->seq + rx[0]); + // fprintf(stderr, "[M::%s] tstr::%.*s\n", __func__, ((int)(ry[1] - ry[0])), tu->seq + ry[0]); + // } + // } + if((rx[1] - rx[0]) > (mx[1] - mx[0])) { + mx[0] = rx[0]; mx[1] = rx[1]; + my[0] = ry[0]; my[1] = ry[1]; + } + } + } + } + + if(mx[1] > mx[0]) { + *rxs = mx[0]; *rxe = mx[1]; + *rys = my[0]; *rye = my[1]; + return 1; + } + + return 0; +} + +void push_ne_ovlp(ma_hit_t_alloc* paf, overlap_region_alloc* ov, uint32_t flag, All_reads* R_INF, asg16_v *ec/**, uint64_t qid, UC_Read *qu, UC_Read *tu**/) +{ + // if(qu && tu) { + // debug_extract_max_exact_sub(qid, qu, tu); + // } + uint64_t k, n; ma_hit_t *z; uint32_t rxs, rxe, rys, rye; + for (k = n = 0; k < ov->length; k++) { + if(ov->list[k].is_match == flag) n++; + } + + if(n > paf->size) { + paf->size = n; + REALLOC(paf->buffer, paf->size); + } + + for (k = paf->length = 0; k < ov->length; k++) { + if(ov->list[k].is_match == flag) { + // fprintf(stderr, "@%s\tSN:%.*s(id::%u)\terr::%u\n", flag==1?"SQ":"RQ", (int32_t)Get_NAME_LENGTH((*R_INF), ov->list[k].y_id), Get_NAME((*R_INF), ov->list[k].y_id), ov->list[k].y_id, ov->list[k].non_homopolymer_errors); + + z = &(paf->buffer[paf->length++]); + + z->qns = ov->list[k].x_id; + z->qns = z->qns << 32; + z->tn = ov->list[k].y_id; + + z->qns = z->qns | (uint64_t)(ov->list[k].x_pos_s); + z->qe = ov->list[k].x_pos_e + 1; + z->ts = ov->list[k].y_pos_s; + z->te = ov->list[k].y_pos_e + 1; + + ///for overlap_list, the x_strand of all overlaps are 0, so the tmp.rev is the same as the y_strand + z->rev = ov->list[k].y_pos_strand; + + z->bl = Get_READ_LENGTH((*R_INF), ov->list[k].y_id); + z->ml = ov->list[k].strong; + z->no_l_indel = ov->list[k].without_large_indel; + + if(ec) { + extract_max_exact(&ov->list[k], ec, /**qu, tu,**/ &rxs, &rxe, &rys, &rye); + z->el = 0; + // fprintf(stderr, "[M::%s]\tq::[%u,\t%u)\tt::[%u,\t%u)\teq::[%u,\t%u)\tet::[%u,\t%u)\n", __func__, ov->list[k].x_pos_s, ov->list[k].x_pos_e + 1, ov->list[k].y_pos_s, ov->list[k].y_pos_e + 1, rxs, rxe, rys, rye); + if(rxe > rxs) { + z->qns = ov->list[k].x_id; + z->qns = z->qns << 32; + z->qns = z->qns | (uint64_t)(rxs); + z->qe = rxe; + z->ts = rys; + z->te = rye; + + z->el = 1; + } + } + } + } +} + +void push_ff_ovlp(ma_hit_t_alloc* paf, overlap_region_alloc* ov, uint32_t flag, All_reads* R_INF, uint64_t *cnt) +{ + // if(qu && tu) { + // debug_extract_max_exact_sub(qid, qu, tu); + // } + uint64_t k, n; ma_hit_t *z; + for (k = n = 0; k < ov->length; k++) { + if(ov->list[k].is_match == flag) n++; + } + + if(n > paf->size) { + paf->size = n; + REALLOC(paf->buffer, paf->size); + } + + for (k = paf->length = 0; k < ov->length; k++) { + if(ov->list[k].is_match == flag) { + z = &(paf->buffer[paf->length++]); + + z->qns = ov->list[k].x_id; + z->qns = z->qns << 32; + z->tn = ov->list[k].y_id; + + z->qns = z->qns | (uint64_t)(ov->list[k].x_pos_s); + z->qe = ov->list[k].x_pos_e + 1; + z->ts = ov->list[k].y_pos_s; + z->te = ov->list[k].y_pos_e + 1; + + ///for overlap_list, the x_strand of all overlaps are 0, so the tmp.rev is the same as the y_strand + z->rev = ov->list[k].y_pos_strand; + + z->bl = Get_READ_LENGTH((*R_INF), ov->list[k].y_id); + z->ml = ov->list[k].strong; + z->no_l_indel = ov->list[k].without_large_indel; + z->el = ov->list[k].shared_seed; + + if(z->rev) { + z->ts = z->bl - ov->list[k].y_pos_e - 1; + z->te = z->bl - ov->list[k].y_pos_s; + } + + if(flag == 1) { + if(z->ml == 1) cnt[2]++; + if(z->ml == 0) cnt[3]++; + if(z->el == 1) cnt[4]++; + if(z->no_l_indel) cnt[5]++; + } + z->del = 0; + } + } + + if(flag == 1) cnt[0] += paf->length; + if(flag == 2) cnt[1] += paf->length; +} + +void debug_mm_exact_cigar(overlap_region_alloc* ol, uint32_t qid, UC_Read *qu, UC_Read *tu) +{ + int64_t on = ol->length, k, i, zwn, xk, yk; uint32_t cl, ck; ///bit_extz_t ez; + overlap_region *z; asg16_v ct; uint64_t wx[2], wy[2]; uint16_t c; + recover_UC_Read(qu, &R_INF, qid); + + for (i = 0; i < on; i++) { + z = &(ol->list[i]); zwn = z->w_list.n; + if(z->y_pos_strand) { + recover_UC_Read_RC(tu, &R_INF, z->y_id); + } else { + recover_UC_Read(tu, &R_INF, z->y_id); ///b->z.length + } + + // fprintf(stderr, "[M::%s] x_id::%u\ty_id::%u\tx::[%u, %u)\ty::[%u, %u)\tzwn::%ld\n", + // __func__, z->x_id, z->y_id, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, zwn); + // fprintf(stderr, "qstr(%lld)::%.*s\n", qu->length, (int32_t)(qu->length), qu->seq); + // fprintf(stderr, "tstr(%lld)::%.*s\n", tu->length, (int32_t)(tu->length), tu->seq); + + for (k = 0; k < zwn; k++) { + // set_bit_extz_t(ez, (*z), k); + // if(!cigar_check(tu->seq, qu->seq, &ez)) { + // fprintf(stderr, "\n[M::%s] x_id::%u, y_id::%u, x::[%u, %u), y::[%u, %u)\n", __func__, z->x_id, z->y_id, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); + // exit(1); + // } + // continue; + ct.a = z->w_list.c.a + z->w_list.a[k].cidx; + ct.n = ct.m = z->w_list.a[k].clen; ck = 0; + xk = z->w_list.a[k].x_start; yk = z->w_list.a[k].y_start; + while (ck < ct.n) { + wx[0] = xk; wy[0] = yk; + ck = pop_trace(&ct, ck, &c, &cl); + if(c != 2) xk += cl; + if(c != 3) yk += cl; + wx[1] = xk; wy[1] = yk; + if(c == 0) { + if(memcmp(qu->seq + wx[0], tu->seq + wy[0], wx[1] - wx[0])) { + fprintf(stderr, "\n-0-[M::%s]\teq::[%lu,\t%lu)\tet::[%lu,\t%lu)\t%c\n", __func__, wx[0], wx[1], wy[0], wy[1], "+-"[z->y_pos_strand]); + fprintf(stderr, "qstr(%u)::%.*s\n", z->x_id, (int32_t)(wx[1] - wx[0]), qu->seq + wx[0]); + fprintf(stderr, "tstr(%u)::%.*s\n", z->y_id, (int32_t)(wy[1] - wy[0]), tu->seq + wy[0]); + // exit(1); + } + // else { + // fprintf(stderr, "\n-1-[M::%s]\teq::[%lu,\t%lu)\tet::[%lu,\t%lu)\t%c\n", __func__, wx[0], wx[1], wy[0], wy[1], "+-"[z->y_pos_strand]); + // fprintf(stderr, "qstr(%u)::%.*s\n", z->x_id, (int32_t)(wx[1] - wx[0]), qu->seq + wx[0]); + // fprintf(stderr, "tstr(%u)::%.*s\n", z->y_id, (int32_t)(wy[1] - wy[0]), tu->seq + wy[0]); + // } + } + } + } + + } +} + +void check_well_cal(asg16_v *sc, asg64_v *idx, uint8_t *f_ec, uint8_t *abnormal, int64_t len, int64_t min_dp, ma_hit_t_alloc *in) +{ + uint64_t k, s, e; int64_t dp, old_dp, st = 0, ed; ma_hit_t *z; + + (*f_ec) = 1; (*abnormal) = 0; idx->n = 0; + for (k = 0; k < in->length; k++) { + z = &(in->buffer[k]); + s = ((uint32_t)(z->qns)); e = z->qe; + kv_push(uint64_t, (*idx), (s<<1)); + kv_push(uint64_t, (*idx), (e<<1)|1); + } + + radix_sort_ec64(idx->a, idx->a + idx->n); + for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { + old_dp = dp; + ///if a[j] is qe + if (idx->a[k]&1) --dp; + else ++dp; + + ed = idx->a[k]>>1; + if(ed > st) { + if(old_dp < min_dp) (*f_ec) = 0; + if(old_dp == 0) { + if(st > 0 && ed < len) { + (*abnormal) = 1; + }else if((*abnormal)==0){ + (*abnormal) = 2; + } + } + } + + st = ed; + } + + + ed = len; old_dp = dp; + if(ed > st) { + if(old_dp < min_dp) (*f_ec) = 0; + if(old_dp == 0) { + if(st > 0 && ed < len) { + (*abnormal) = 1; + }else if((*abnormal) == 0){ + (*abnormal) = 2; + } + } + } + + if((*f_ec)) { + for (k = 0; (k < sc->n) && ((sc->a[k]>>14) == 0); k++); + if(k < sc->n) (*f_ec) = 0; + } +} + +inline uint64_t exact_ec_check(char *qstr, uint64_t ql, char *tstr, uint64_t tl, int64_t qs, int64_t qe, int64_t ts, int64_t te) +{ + if(qe - qs != te - ts) return 0; + if(memcmp(qstr + qs, tstr + ts, qe - qs) == 0) return 1; + return 0; +} + +void gen_ff_hpc(asg8_v *fi, char *a, int64_t an, int64_t hpc_rr, int64_t hpc_cutoff) +{ + int64_t p, k, r, rc, zs, ze; + kv_resize(uint8_t, *fi, (uint64_t)an); + memset(fi->a, 0, sizeof((*(fi->a)))*an); + fi->n = an; + + for (p = 0; p < an; ) { + for (r = 1, zs = ze = 0; r <= hpc_rr; r++) { + rc = r * hpc_cutoff/**HPC_CC**/; + ///inlcuding p + for (k = p + r; (k < an) && ((k-r) >= 0) && (a[k] == a[k-r]); k++){;} ze = k; if(ze > an) {ze = an;} + for (k = p - 1; (k >= 0) && ((k+r) < an) && (a[k] == a[k+r]); k--){;} zs = k + 1; if(zs < 0) {zs = 0;} + if(((ze - zs) > r) && ((ze - zs) >= rc)) { + // fprintf(stderr, "+[M::%s]\t[%ld,\t%ld)\tr::%ld\trc::%ld\tp::%ld\n", __func__, zs, ze, r, rc, p); + for (k = zs; k < ze; k++) fi->a[k] |= ((uint8_t)(1<<(r-1))); + break; + } + + ///inlcuding p + for (k = p - r; (k >= 0) && ((k+r) < an) && (a[k] == a[k+r]); k--){;} zs = k + 1; if(zs < 0) {zs = 0;} + for (k = p + 1; (k < an) && ((k-r) >= 0) && (a[k] == a[k-r]); k++){;} ze = k; if(ze > an) {ze = an;} + if(((ze - zs) > r) && ((ze - zs) >= rc)) { + // fprintf(stderr, "-[M::%s]\t[%ld,\t%ld)\tr::%ld\trc::%ld\n", __func__, zs, ze, r, rc); + for (k = zs; k < ze; k++) fi->a[k] |= ((uint8_t)(1<<(r-1))); + break; + } + } + p++; if(p < ze) p = ze; + } + + // for (k = 1, p = 0; k <= an; k++) { + // if((k == an) || ((!!fi->a[p]) != (!!fi->a[k]))) { + // if(fi->a[p]) fprintf(stderr, "[M::%s]\t[%ld,\t%ld)\tan::%ld\n", __func__, p + 1, k + 1, an); + // p = k; + // } + // } + + // for (k = 0; k < an; k++) { + // if(fi->a[k] == 0) continue; + // fprintf(stderr, "p::%ld\t", k + 1); + // for (r = 0; r < 8; r++) { + // if((fi->a[k]>>r)&1) fprintf(stderr, "r::%ld\t", r + 1); + // } + // fprintf(stderr, "\n"); + // } + +} + + + +void ggen_chain_clus_0(overlap_region_alloc* ol, asg32_v *v32, asg64_v *v64, uint32_t **a_cu, uint32_t **a_ci, uint32_t **ocn, uint32_t **osc, uint64_t **idx_cu, uint64_t *n_cu) +{ + uint64_t i, k, l, kc, lc; + (*a_cu) = (*a_ci) = (*ocn) = (*osc) = NULL; (*idx_cu) = NULL; (*n_cu) = 0; + if(v32->n > 0) { + assert(v32->n == (ol->length<<1)); + v32->n = (ol->length<<2); kv_resize(uint32_t, *v32, v32->n); + + (*a_cu) = v32->a; (*a_ci) = v32->a + ol->length; + (*ocn) = v32->a + ol->length + ol->length; + (*osc) = v32->a + ol->length + ol->length + ol->length; + + for (k = 1, l = (*n_cu) = 0; k <= ol->length; k++) { + if((k == ol->length) || (*a_ci)[(*a_cu)[k]] != (*a_ci)[(*a_cu)[l]]) { + (*n_cu)++; + l = k; + } + } + + v64->n = (*n_cu) + 1; + kv_resize(uint64_t, *v64, v64->n); + (*idx_cu) = v64->a; + for (k = 1, l = kc = lc = 0; k <= ol->length; k++) { + if((k == ol->length) || (*a_ci)[(*a_cu)[k]] != (*a_ci)[(*a_cu)[l]]) { + for (i = l; i < k; i++) (*a_ci)[(*a_cu)[i]] = kc; + (*idx_cu)[kc++] = lc; lc += k - l; + l = k; + } + } + assert(kc == (*n_cu)); + (*idx_cu)[kc] = lc; + } else { + v32->n = (ol->length<<1); kv_resize(uint32_t, *v32, v32->n); + (*ocn) = v32->a; + (*osc) = v32->a + ol->length; + } + + for (k = 0; k < ol->length; k++) { + (*ocn)[k] = ol->list[k].align_length; + (*osc)[k] = ol->list[k].shared_seed; + ol->list[k].align_length = 0; + } +} + +void gen_hc_r_alin_ea_flt(ha_abuf_t *ab, overlap_region_alloc* ol, Candidates_list *cl, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, uint64_t max_n_chain, uint64_t max_n_chain_f, uint64_t chain_cutoff, double e_rate, int64_t wl, int64_t rid, int64_t khit, int64_t move_gap, asg16_v *buf, asg64_v *srt, ma_hit_t_alloc *in, uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max, + uint64_t sec_aln_win, uint64_t sec_aln_cov, double sec_aln_err_rate, double sec_aln_max, asg64_v *bp, uint64_t ocw, asg8_v *hpz, asg32_v *v32) +{ + if(ol->length <= 0) return; + + uint32_t *a_cu = NULL, *a_ci = NULL, *ocn = NULL, *osc = NULL; uint64_t k, *idx_cu = NULL, n_cu = 0; v32->n = 0; + if(ol->length > max_n_chain) { + gen_chain_clus(ab, ol, cl, v32);///ol->align_length has not been set to 0 + } + ggen_chain_clus_0(ol, v32, bp, &a_cu, &a_ci, &ocn, &osc, &idx_cu, &n_cu); + + + + uint64_t i, m, *ei, en, *oi, on, tid, trev, nec; overlap_region *z; ma_hit_t *p; + for (k = srt->n = 0; k < in->length; k++) { + if(in->buffer[k].el) { + m = in->buffer[k].tn; m <<= 1; m |= in->buffer[k].rev; + m <<= 32; m |= k; kv_push(uint64_t, (*srt), m); + } + } + + if(!(srt->n)) { + gen_ff_hpc(hpz, qu->seq, qu->length, HPC_RR_Q, HPC_CC_Q); + gen_hc_r_alin_adp_smp(ol, cl, rref, qu, tu, exz, aux_o, e_rate, wl, rid, khit, move_gap, buf, chem_drop, align_gap_rate, align_gap_max, sec_aln_win, sec_aln_cov, sec_aln_err_rate, sec_aln_max, srt, ocw, hpz->a, a_cu, a_ci, ocn, osc, + idx_cu, n_cu, bp, max_n_chain>0?max_n_chain:1, max_n_chain_f>0?max_n_chain_f:1, chain_cutoff, ((asm_opt.hom_cov*HC_AV_MIN)>0)?(asm_opt.hom_cov*HC_AV_MIN):(1), 1); + } else { + kv_resize(uint64_t, *srt, (srt->n + ol->length)); + ei = srt->a; en = srt->n; oi = srt->a + srt->n; on = ol->length; + for (k = 0; k < on; k++) { + z = &(ol->list[k]); z->is_match = z->strong = z->without_large_indel = 0; + oi[k] = z->y_id; oi[k] <<= 1; oi[k] |= z->y_pos_strand; + oi[k] <<= 32; oi[k] |= k; + } + + radix_sort_ec64(ei, ei + en); radix_sort_ec64(oi, oi + on); + for (k = i = nec = 0; k < on; k++) { + z = &(ol->list[(uint32_t)oi[k]]); tid = z->y_id; trev = z->y_pos_strand; + for (; (i < en) && ((ei[i]>>32) < ((tid<<1)|trev)); i++); + if((i < en) && ((ei[i]>>32) == ((tid<<1)|trev))) { + p = &(in->buffer[(uint32_t)ei[i]]); + if((z->x_pos_s == ((uint32_t)p->qns)) && (z->x_pos_e + 1 == p->qe) && + (z->y_pos_s == p->ts) && (z->y_pos_e + 1 == p->te)) { + resize_UC_Read(tu, p->te - p->ts); recover_UC_Read_sub_region(tu->seq, p->ts, p->te - p->ts, trev, rref, tid); + if(exact_ec_check(qu->seq, qu->length, tu->seq, p->te - p->ts, ((uint32_t)p->qns), p->qe, 0, p->te - p->ts)) { + z->is_match = 1; z->shared_seed = z->non_homopolymer_errors;///for index + z->non_homopolymer_errors = 0; z->strong = z->without_large_indel = 0; + set_exact_exz(exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, exz); + nec++; + } + } + } + } + + if(on > nec) { + gen_ff_hpc(hpz, qu->seq, qu->length, HPC_RR_Q, HPC_CC_Q); + gen_hc_r_alin_adp_smp(ol, cl, rref, qu, tu, exz, aux_o, e_rate, wl, rid, khit, move_gap, buf, chem_drop, align_gap_rate, align_gap_max, sec_aln_win, sec_aln_cov, sec_aln_err_rate, sec_aln_max, srt, ocw, hpz->a, a_cu, a_ci, ocn, osc, + idx_cu, n_cu, bp, max_n_chain>0?max_n_chain:1, max_n_chain_f>0?max_n_chain_f:1, chain_cutoff, ((asm_opt.hom_cov*HC_AV_MIN)>0)?(asm_opt.hom_cov*HC_AV_MIN):(1), 0); + } + } + + if(ol->length) srt_olst(ol); +} + +void gen_hc_r_alin_ea(overlap_region_alloc* ol, Candidates_list *cl, All_reads *rref, UC_Read* qu, UC_Read* tu, bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t wl, int64_t rid, int64_t khit, int64_t move_gap, asg16_v *buf, asg64_v *srt, ma_hit_t_alloc *in, uint8_t chem_drop, double align_gap_rate, int64_t align_gap_max, + uint64_t sec_aln_win, uint64_t sec_aln_cov, double sec_aln_err_rate, double sec_aln_max, asg64_v *kp, asg8_v *hpz) +{ + if(ol->length <= 0) return; + + + // uint64_t k, l, i, s, m, mm_k, *ei, en, *oi, on, tid, trev, nec; int64_t sc, mm_sc, plus, minus; overlap_region *z, t; ma_hit_t *p; + uint64_t k, i, m, *ei, en, *oi, on, tid, trev, nec; overlap_region *z; ma_hit_t *p; + srt->n = 0; + for (k = 0; k < in->length; k++) { + if(in->buffer[k].el) { + m = in->buffer[k].tn; m <<= 1; m |= in->buffer[k].rev; + m <<= 32; m |= k; kv_push(uint64_t, (*srt), m); + } + } + + if(!(srt->n)) { + gen_ff_hpc(hpz, qu->seq, qu->length, HPC_RR_Q, HPC_CC_Q); + gen_hc_r_alin(ol, cl, rref, qu, tu, exz, aux_o, e_rate, wl, rid, khit, move_gap, buf, chem_drop, align_gap_rate, align_gap_max, sec_aln_win, sec_aln_cov, sec_aln_err_rate, sec_aln_max, kp, hpz->a); + } else { + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + + kv_resize(uint64_t, *srt, (srt->n + ol->length)); + ei = srt->a; en = srt->n; oi = srt->a + srt->n; on = ol->length; + for (k = 0; k < on; k++) { + z = &(ol->list[k]); z->is_match = z->strong = z->without_large_indel = 0; + oi[k] = z->y_id; oi[k] <<= 1; oi[k] |= z->y_pos_strand; + oi[k] <<= 32; oi[k] |= k; + } + + radix_sort_ec64(ei, ei + en); radix_sort_ec64(oi, oi + on); + for (k = i = nec = 0; k < on; k++) { + z = &(ol->list[(uint32_t)oi[k]]); tid = z->y_id; trev = z->y_pos_strand; + for (; (i < en) && ((ei[i]>>32) < ((tid<<1)|trev)); i++); + if((i < en) && ((ei[i]>>32) == ((tid<<1)|trev))) { + p = &(in->buffer[(uint32_t)ei[i]]); + if((z->x_pos_s == ((uint32_t)p->qns)) && (z->x_pos_e + 1 == p->qe) && + (z->y_pos_s == p->ts) && (z->y_pos_e + 1 == p->te)) { + resize_UC_Read(tu, p->te - p->ts); recover_UC_Read_sub_region(tu->seq, p->ts, p->te - p->ts, trev, rref, tid); + if(exact_ec_check(qu->seq, qu->length, tu->seq, p->te - p->ts, ((uint32_t)p->qns), p->qe, 0, p->te - p->ts)) { + z->is_match = 1; z->shared_seed = z->non_homopolymer_errors;///for index + z->non_homopolymer_errors = 0; z->strong = z->without_large_indel = 0; + set_exact_exz(exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, exz); + nec++; + } + } + } + } + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + + if(on > nec) { + gen_ff_hpc(hpz, qu->seq, qu->length, HPC_RR_Q, HPC_CC_Q); + gen_hc_r_alin_nec(ol, cl, rref, qu, tu, exz, aux_o, e_rate, wl, rid, khit, move_gap, buf, chem_drop, align_gap_rate, align_gap_max, sec_aln_win, sec_aln_cov, sec_aln_err_rate, sec_aln_max, kp, hpz->a); + } + + // fprintf(stderr, "[M::%s] srt->n::%u, nec::%lu, on::%lu\n", __func__, (uint32_t)srt->n, nec, on); + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + } + + /** + if(ol->length > 1) {///for duplicated chains + overlap_region_sort_y_id(ol->list, ol->length); + for (k = 1, l = m = 0; k <= ol->length; k++) { + if(k == ol->length || ol->list[k].y_id != ol->list[l].y_id) { + // fprintf(stderr, "\n[M::%s::tid->%u] n->%lu\n", __func__, ol->list[l].y_id, k - l); + mm_k = l; + if(k - l > 1) { + for (s = l, mm_sc = INT32_MIN, mm_k = ((uint64_t)-1); s < k; s++) { + z = &(ol->list[s]); + plus = z->x_pos_e + 1 - z->x_pos_s; minus = (z->non_homopolymer_errors) * 12; + sc = plus - minus; + if((sc > mm_sc) || ((sc == mm_sc) && ((ol->list[mm_k].x_pos_e+1-ol->list[mm_k].x_pos_s) < (z->x_pos_e+1-z->x_pos_s)))) { + mm_sc = sc; mm_k = s; + } + // fprintf(stderr, "[M::%s::%c] q::[%u, %u), t::[%u, %u), sc::%ld, err::%u, s::%lu\n", __func__, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, sc, z->non_homopolymer_errors, s); + } + } + // fprintf(stderr, "[M::%s::tid->%u] mm_k::%lu\n", __func__, ol->list[l].y_id, mm_k); + if(mm_k != ((uint64_t)-1)) { + if(mm_k != m) { + t = ol->list[mm_k]; + ol->list[mm_k] = ol->list[m]; + ol->list[m] = t; + } + m++; + } + l = k; + } + } + ol->length = m; + } + **/ +} + +void gen_hc_r_alin_ea_adv(gen_hc_aln_t *ez) +{ + if(ez->ol->length <= 0) return; + + uint64_t k, i, m, *ei, en, *oi, on, tid, trev, nec; overlap_region *z; ma_hit_t *p; + ez->srt->n = 0; + for (k = 0; k < ez->in->length; k++) { + if(ez->in->buffer[k].el) { + m = ez->in->buffer[k].tn; m <<= 1; m |= ez->in->buffer[k].rev; + m <<= 32; m |= k; kv_push(uint64_t, (*(ez->srt)), m); + } + } + + if(!(ez->srt->n)) { + gen_ff_hpc(ez->hpz, ez->qu->seq, ez->qu->length, HPC_RR_Q, HPC_CC_Q); + gen_hc_r_alin_adv(ez); + } else { + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + kv_resize(uint64_t, *(ez->srt), (ez->srt->n + ez->ol->length)); + ei = ez->srt->a; en = ez->srt->n; oi = ez->srt->a + ez->srt->n; on = ez->ol->length; + for (k = 0; k < on; k++) { + z = &(ez->ol->list[k]); z->is_match = z->strong = z->without_large_indel = 0; + oi[k] = z->y_id; oi[k] <<= 1; oi[k] |= z->y_pos_strand; + oi[k] <<= 32; oi[k] |= k; + } + + radix_sort_ec64(ei, ei + en); radix_sort_ec64(oi, oi + on); + for (k = i = nec = 0; k < on; k++) { + z = &(ez->ol->list[(uint32_t)oi[k]]); tid = z->y_id; trev = z->y_pos_strand; + for (; (i < en) && ((ei[i]>>32) < ((tid<<1)|trev)); i++); + if((i < en) && ((ei[i]>>32) == ((tid<<1)|trev))) { + p = &(ez->in->buffer[(uint32_t)ei[i]]); + if((z->x_pos_s == ((uint32_t)p->qns)) && (z->x_pos_e + 1 == p->qe) && + (z->y_pos_s == p->ts) && (z->y_pos_e + 1 == p->te)) { + resize_UC_Read(ez->tu, p->te - p->ts); recover_UC_Read_sub_region(ez->tu->seq, p->ts, p->te - p->ts, trev, ez->rref, tid); + if(exact_ec_check(ez->qu->seq, ez->qu->length, ez->tu->seq, p->te - p->ts, ((uint32_t)p->qns), p->qe, 0, p->te - p->ts)) { + z->is_match = 1; z->shared_seed = z->non_homopolymer_errors;///for index + z->non_homopolymer_errors = 0; z->strong = z->without_large_indel = 0; + set_exact_exz(ez->exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, ez->exz); + nec++; + } + } + } + } + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + + if(on > nec) { + gen_ff_hpc(ez->hpz, ez->qu->seq, ez->qu->length, HPC_RR_Q, HPC_CC_Q); + gen_hc_r_alin_nec_adv(ez); + } + // fprintf(stderr, "[M::%s] srt->n::%u, nec::%lu, on::%lu\n", __func__, (uint32_t)srt->n, nec, on); + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + } + + /** + if(ol->length > 1) {///for duplicated chains + overlap_region_sort_y_id(ol->list, ol->length); + for (k = 1, l = m = 0; k <= ol->length; k++) { + if(k == ol->length || ol->list[k].y_id != ol->list[l].y_id) { + // fprintf(stderr, "\n[M::%s::tid->%u] n->%lu\n", __func__, ol->list[l].y_id, k - l); + mm_k = l; + if(k - l > 1) { + for (s = l, mm_sc = INT32_MIN, mm_k = ((uint64_t)-1); s < k; s++) { + z = &(ol->list[s]); + plus = z->x_pos_e + 1 - z->x_pos_s; minus = (z->non_homopolymer_errors) * 12; + sc = plus - minus; + if((sc > mm_sc) || ((sc == mm_sc) && ((ol->list[mm_k].x_pos_e+1-ol->list[mm_k].x_pos_s) < (z->x_pos_e+1-z->x_pos_s)))) { + mm_sc = sc; mm_k = s; + } + // fprintf(stderr, "[M::%s::%c] q::[%u, %u), t::[%u, %u), sc::%ld, err::%u, s::%lu\n", __func__, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, sc, z->non_homopolymer_errors, s); + } + } + // fprintf(stderr, "[M::%s::tid->%u] mm_k::%lu\n", __func__, ol->list[l].y_id, mm_k); + if(mm_k != ((uint64_t)-1)) { + if(mm_k != m) { + t = ol->list[mm_k]; + ol->list[mm_k] = ol->list[m]; + ol->list[m] = t; + } + m++; + } + l = k; + } + } + ol->length = m; + } + **/ +} + + +void gen_hc_r_alin_ea_adv_flt(gen_hc_aln_t *ez) +{ + if(ez->ol->length <= 0) return; + // uint32_t dbg_k; + // for (dbg_k = 0; dbg_k < ez->ol->length; dbg_k++) { + // if(ez->ol->list[dbg_k].y_id == 5931) { + // pp_chn_a(&(ez->ol->list[dbg_k]), ez->cl, 1); + // } + // } + uint32_t *a_cu = NULL, *a_ci = NULL, *ocn = NULL, *osc = NULL; uint64_t *idx_cu = NULL, n_cu = 0; ez->v32->n = 0; + if(ez->ol->length > ez->max_n_chain) { + gen_chain_clus(ez->ab, ez->ol, ez->cl, ez->v32);///ol->align_length has not been set to 0 + } + // for (dbg_k = 0; dbg_k < ez->ol->length; dbg_k++) { + // if(ez->ol->list[dbg_k].y_id == 5931) { + // pp_chn_a(&(ez->ol->list[dbg_k]), ez->cl, 1); + // } + // } + ggen_chain_clus_0(ez->ol, ez->v32, ez->bp, &a_cu, &a_ci, &ocn, &osc, &idx_cu, &n_cu); + // for (dbg_k = 0; dbg_k < ez->ol->length; dbg_k++) { + // if(ez->ol->list[dbg_k].y_id == 5931) { + // pp_chn_a(&(ez->ol->list[dbg_k]), ez->cl, 1); + // } + // } + + + uint64_t k, i, m, *ei, en, *oi, on, tid, trev, nec; overlap_region *z; ma_hit_t *p; + ez->srt->n = 0; + for (k = 0; k < ez->in->length; k++) { + if(ez->in->buffer[k].el) { + m = ez->in->buffer[k].tn; m <<= 1; m |= ez->in->buffer[k].rev; + m <<= 32; m |= k; kv_push(uint64_t, (*(ez->srt)), m); + } + } + + if(!(ez->srt->n)) { + gen_ff_hpc(ez->hpz, ez->qu->seq, ez->qu->length, HPC_RR_Q, HPC_CC_Q); + gen_hc_r_alin_adv_adp_smp(ez, a_cu, a_ci, ocn, osc, idx_cu, n_cu, 1); + // gen_hc_r_alin_adv(ez); + } else { + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + kv_resize(uint64_t, *(ez->srt), (ez->srt->n + ez->ol->length)); + ei = ez->srt->a; en = ez->srt->n; oi = ez->srt->a + ez->srt->n; on = ez->ol->length; + for (k = 0; k < on; k++) { + z = &(ez->ol->list[k]); z->is_match = z->strong = z->without_large_indel = 0; + oi[k] = z->y_id; oi[k] <<= 1; oi[k] |= z->y_pos_strand; + oi[k] <<= 32; oi[k] |= k; + } + + radix_sort_ec64(ei, ei + en); radix_sort_ec64(oi, oi + on); + for (k = i = nec = 0; k < on; k++) { + z = &(ez->ol->list[(uint32_t)oi[k]]); tid = z->y_id; trev = z->y_pos_strand; + for (; (i < en) && ((ei[i]>>32) < ((tid<<1)|trev)); i++); + if((i < en) && ((ei[i]>>32) == ((tid<<1)|trev))) { + p = &(ez->in->buffer[(uint32_t)ei[i]]); + if((z->x_pos_s == ((uint32_t)p->qns)) && (z->x_pos_e + 1 == p->qe) && + (z->y_pos_s == p->ts) && (z->y_pos_e + 1 == p->te)) { + resize_UC_Read(ez->tu, p->te - p->ts); recover_UC_Read_sub_region(ez->tu->seq, p->ts, p->te - p->ts, trev, ez->rref, tid); + if(exact_ec_check(ez->qu->seq, ez->qu->length, ez->tu->seq, p->te - p->ts, ((uint32_t)p->qns), p->qe, 0, p->te - p->ts)) { + z->is_match = 1; z->shared_seed = z->non_homopolymer_errors;///for index + z->non_homopolymer_errors = 0; z->strong = z->without_large_indel = 0; + set_exact_exz(ez->exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, ez->exz); + nec++; + } + } + } + } + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + + if(on > nec) { + gen_ff_hpc(ez->hpz, ez->qu->seq, ez->qu->length, HPC_RR_Q, HPC_CC_Q); + gen_hc_r_alin_adv_adp_smp(ez, a_cu, a_ci, ocn, osc, idx_cu, n_cu, 0); + // gen_hc_r_alin_nec_adv(ez); + } + // fprintf(stderr, "[M::%s] srt->n::%u, nec::%lu, on::%lu\n", __func__, (uint32_t)srt->n, nec, on); + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + } +} + + +void prt_ovlp_sam_0(char *cm, FILE *fp, char *ref_id, int32_t ref_id_n, char *qry_id, int32_t qry_id_n, char *qry_seq, uint64_t qry_seq_n, uint64_t rs, uint64_t re, uint64_t qs, uint64_t qe, uint64_t flag, uint64_t err0, bit_extz_t *ez) +{ + uint64_t ci = 0, err1 = 0; uint16_t c; uint32_t cl, cl0 = 0; char c0 = (char)-1; + fprintf(fp, "%.*s\t%lu\t%.*s\t%lu\t60\t", qry_id_n, qry_id, flag, ref_id_n, ref_id, rs + 1); + + if(qs) fprintf(fp, "%luS", qs); + while (ci < ez->cigar.n) { + ci = pop_trace(&(ez->cigar), ci, &c, &cl); + if(c0 == cm[c]) { + cl0 += cl; + } else { + if(c0 != ((char)-1)) { + fprintf(fp, "%u%c", cl0, c0); + } + cl0 = cl; c0 = cm[c]; + } + // fprintf(fp, "%u%c", cl, cm[c]); + if(c != 0) err1 += cl; + } + if(cl0) fprintf(fp, "%u%c", cl0, c0); + if(qry_seq_n > qe) fprintf(fp, "%luS", qry_seq_n - qe); + fprintf(fp, "\t*\t0\t0\t%.*s\t", (int32_t)qry_seq_n, qry_seq); + for (ci = 0; ci < qry_seq_n; ci++) fprintf(fp, "~"); + assert(err0 == err1); + fprintf(fp, "\tNM:i:%lu\n", err0); +} + + +void prt_ovlp_sam(overlap_region_alloc* ol, UC_Read* tu, char *ref_seq, int32_t ref_seq_n) +{ + int64_t on = ol->length, k, i, zwn; overlap_region *z; bit_extz_t ez; + char *qry = NULL, *ref = Get_NAME(R_INF, ol->list[0].x_id); + uint64_t qry_n = 0, ref_n = Get_NAME_LENGTH(R_INF, ol->list[0].x_id), qid, rev; + char cm[4]; cm[0] = 'M'; cm[1] = 'M'; cm[2] = 'I'; cm[3] = 'D'; + FILE *fp = fopen("aln.sam", "w"); + fprintf(fp, "@HD\tVN:1.6\tSO:unknown\n"); + fprintf(fp, "@SQ\tSN:%.*s\tLN:%lu\n", (int32_t)ref_n, ref, Get_READ_LENGTH(R_INF, ol->list[0].x_id)); + for (k = 0; k < on; k++) { + z = &(ol->list[k]); zwn = z->w_list.n; + if(!zwn) continue; + qid = ol->list[k].y_id; + if(z->y_pos_strand) { + recover_UC_Read_RC(tu, &R_INF, qid); rev = 16; + } else { + recover_UC_Read(tu, &R_INF, qid); rev = 0; + } + for (i = 0; i < zwn; i++) { + if(is_ualn_win(z->w_list.a[i])) continue; + qry_n = Get_NAME_LENGTH(R_INF, qid); + qry = Get_NAME(R_INF, qid); + set_bit_extz_t(ez, (*z), i); + + prt_ovlp_sam_0(cm, fp, ref, ref_n, qry, qry_n, tu->seq, tu->length, z->w_list.a[i].x_start, z->w_list.a[i].x_end + 1, z->w_list.a[i].y_start, z->w_list.a[i].y_end + 1, rev, z->w_list.a[i].error, &ez); + } + } + fclose(fp); + + fp = fopen("ref.fa", "w"); + fprintf(fp, ">%.*s\n", (int32_t)ref_n, ref); + fprintf(fp, "%.*s\n", ref_seq_n, ref_seq); + fclose(fp); +} + +void stderr_phase_ovlp(overlap_region_alloc* ol) +{ + int64_t on = ol->length, k; overlap_region *z; + if(!on) return; + uint64_t qry_n = 0, rid, ref_n, qid; + rid = ol->list[0].x_id; ref_n = Get_NAME_LENGTH(R_INF, rid); + + for (k = 0; k < on; k++) { + z = &(ol->list[k]); qid = ol->list[k].y_id; + qry_n = Get_NAME_LENGTH(R_INF, qid); + + fprintf(stderr, "%.*s(qid::%lu)\tql::%lu\tq::[%u,\t%u)\t%c\t%.*s(tid::%lu)\ttl::%lu\tt::[%u,\t%u)\ttrans::%u\terr::%u\n", + (int32_t)Get_NAME_LENGTH(R_INF, rid), Get_NAME(R_INF, rid), rid, ref_n, z->x_pos_s, z->x_pos_e + 1, "+-"[z->y_pos_strand], + (int32_t)Get_NAME_LENGTH(R_INF, qid), Get_NAME(R_INF, qid), qid, qry_n, z->y_pos_s, z->y_pos_e + 1, ((z->is_match==1)?(0):(1)), z->non_homopolymer_errors); + } +} + +void dedup_chains(overlap_region_alloc* ol) +{ + uint64_t k, l, s, m, mm_k, mm_m, sf; int64_t sc, mm_sc, plus, minus; overlap_region *z, t; + if(ol->length > 1) {///for duplicated chains + overlap_region_sort_y_id(ol->list, ol->length); + for (k = 1, l = m = 0; k <= ol->length; k++) { + if(k == ol->length || ol->list[k].y_id != ol->list[l].y_id) { + // fprintf(stderr, "\n[M::%s::tid->%u] n->%lu\n", __func__, ol->list[l].y_id, k - l); + mm_k = l; + if(k - l > 1) { + for (s = l, mm_sc = INT32_MIN, mm_k = ((uint64_t)-1), mm_m = 3; s < k; s++) { + z = &(ol->list[s]); + plus = z->x_pos_e + 1 - z->x_pos_s; minus = (z->non_homopolymer_errors) * 12; + sc = plus - minus; + + sf = 0; + if(z->is_match < mm_m) { + sf = 1; + } else if(z->is_match == mm_m) { + if(sc > mm_sc) { + sf = 1; + } else if((sc == mm_sc) && ((z->x_pos_e+1-z->x_pos_s) > (ol->list[mm_k].x_pos_e+1-ol->list[mm_k].x_pos_s))) { + sf = 1; + } + } + if(sf) { + mm_sc = sc; mm_k = s; mm_m = z->is_match; + } + + // fprintf(stderr, "[M::%s::%c] q::[%u, %u), t::[%u, %u), sc::%ld, err::%u, mm::%u, s::%lu\n", __func__, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1, sc, z->non_homopolymer_errors, z->is_match, s); + } + } + // fprintf(stderr, "[M::%s::tid->%u] mm_k::%lu\n", __func__, ol->list[l].y_id, mm_k); + if(mm_k != ((uint64_t)-1)) { + if(mm_k != m) { + t = ol->list[mm_k]; + ol->list[mm_k] = ol->list[m]; + ol->list[m] = t; + } + m++; + } + l = k; + } + } + ol->length = m; + } +} + +void debug_retrive_bqual(asg8_v *vq, asg8_v *vt, uint64_t id, uint64_t rn) +{ + uint64_t k, n, z[2], s, e, rev; + retrive_bqual(vq, NULL, id, -1, -1, 0, sc_bn); n = vq->n; + retrive_bqual(vt, NULL, id, -1, -1, 1, sc_bn); + assert(vq->n == vt->n); + for (k = 0; k < vq->n && vq->a[k] == vt->a[vt->n - k - 1]; k++); + // if((k == vq->n)) { + // fprintf(stderr, "[M::%s] id::%lu, k::%lu, n::%lu\n", __func__, id, k, ((uint64_t)vq->n)); + // } + assert(k == vq->n); + + // if(id == 0) { + // s = 21519; e = 22332; rev = 0; + // retrive_bqual(vt, NULL, id, s, e, rev, sc_bn); + // if(memcmp(vq->a + s, vt->a, e - s)) { + // fprintf(stderr, "+[M::%s] id::%lu, t::[%lu, %lu), rev::%lu\n", __func__, id, s, e, rev); + // exit(1); + // } + + // } + // return; + + for (k = 0, rev = 0; k < rn; k++) { + z[0] = rand()%(n + 1); + z[1] = rand()%(n + 1); + if(z[0] == z[1]) continue; + s = MIN(z[0], z[1]); e = MAX(z[0], z[1]); + retrive_bqual(vt, NULL, id, s, e, rev, sc_bn); + if(memcmp(vq->a + s, vt->a, e - s)) { + fprintf(stderr, "[M::%s] id::%lu, t::[%lu, %lu), rev::%lu\n", __func__, id, s, e, rev); + exit(1); + } + } + + + retrive_bqual(vq, NULL, id, -1, -1, 1, sc_bn); + for (k = 0, rev = 1; k < rn; k++) { + z[0] = rand()%(n + 1); + z[1] = rand()%(n + 1); + if(z[0] == z[1]) continue; + s = MIN(z[0], z[1]); e = MAX(z[0], z[1]); + retrive_bqual(vt, NULL, id, s, e, rev, sc_bn); + if(memcmp(vq->a + s, vt->a, e - s)) { + fprintf(stderr, "[M::%s] id::%lu, t::[%lu, %lu), rev::%lu\n", __func__, id, s, e, rev); + exit(1); + } + } +} + +uint32_t is_uncorrected_read(overlap_region_alloc* ov, asg64_v *idx, int64_t len, int64_t min_len) +{ + uint64_t k, s, e; int64_t dp, old_dp, st = 0, ed; + for (k = idx->n = 0; k < ov->length; k++) { + s = ov->list[k].x_pos_s; e = ov->list[k].x_pos_e + 1; + kv_push(uint64_t, (*idx), (s<<1)); + kv_push(uint64_t, (*idx), (e<<1)|1); + } + + radix_sort_ec64(idx->a, idx->a + idx->n); + for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { + old_dp = dp; + ///if a[j] is qe + if (idx->a[k]&1) --dp; + else ++dp; + + ed = idx->a[k]>>1; + if(ed > st) { + if(old_dp == 0) { + if((ed - st) >= min_len) return 1; + } + } + st = ed; + } + + + ed = len; old_dp = dp; + if(ed > st) { + if(old_dp == 0) { + if((ed - st) >= min_len) return 1; + if((ed - st) >= len) return 1; + } + } + + return 0; +} + +uint32_t is_chemical_r_qual(overlap_region_alloc *ov, asg64_v *idx, int64_t len, int64_t cov, int64_t frank_len, asg8_v *qv, uint64_t rid) +{ + uint64_t k, s, e; int64_t dp, old_dp, st = 0, ed, s0, s1, e0, e1, rr, qk; + if((frank_len) > (len *0.01)) frank_len = len *0.01; + for (k = idx->n = 0; k < ov->length; k++) { + s = ov->list[k].x_pos_s; e = ov->list[k].x_pos_e + 1; + kv_push(uint64_t, (*idx), (s<<1)); + kv_push(uint64_t, (*idx), (e<<1)|1); + // fprintf(stderr, "[M::%s]\trid::%lu\ts::%lu\te::%lu\n", __func__, rid, s, e); + } + + radix_sort_ec64(idx->a, idx->a + idx->n); s0 = s1 = e0 = e1 = rr = -1; + for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { + old_dp = dp; + ///if a[j] is qe + if (idx->a[k]&1) --dp; + else ++dp; + + ed = idx->a[k]>>1; + if(ed > st) { + if(old_dp <= cov) { + rr = 1; + } else { + if(s0 < 0) { + s0 = st; s1 = ed; + } + e0 = st; e1 = ed; + } + } + st = ed; + } + + + ed = len; old_dp = dp; + if(ed > st) { + if(old_dp <= cov) { + rr = 1; + } else { + if(s0 < 0) { + s0 = st; s1 = ed; + } + e0 = st; e1 = ed; + } + } + + + if((s0 != e0) && (s1 != e1) && (s0 <= frank_len) && ((len - e1) <= frank_len) && (rr > 0)) { + for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { + old_dp = dp; + ///if a[j] is qe + if (idx->a[k]&1) --dp; + else ++dp; + + ed = idx->a[k]>>1; + if(ed > st) { + if((old_dp <= cov) && (st >= s0) && (ed <= e1)) { + retrive_bqual(qv, NULL, rid, -1, -1, 0, sc_bn); + fprintf(stderr, "[M::%s]\tlf::[%ld,%ld)\trt::[%ld,%ld)\tmd::[%ld,%ld)\tcov::%ld\n", __func__, s0, s1, e0, e1, st, ed, old_dp); + for (qk = st; qk < ed; qk++) fprintf(stderr, "%u", qv->a[qk]); + fprintf(stderr, "\n"); + return 1; + } + } + st = ed; + } + + + ed = len; old_dp = dp; + if(ed > st) { + if((old_dp <= cov) && (st >= s0) && (ed <= e1)) { + retrive_bqual(qv, NULL, rid, -1, -1, 0, sc_bn); + fprintf(stderr, "[M::%s]\tlf::[%ld,%ld)\trt::[%ld,%ld)\tmd::[%ld,%ld)\tcov::%ld\n", __func__, s0, s1, e0, e1, st, ed, old_dp); + for (qk = st; qk < ed; qk++) fprintf(stderr, "%u", qv->a[qk]); + fprintf(stderr, "\n"); + return 1; + } + } + } + + + // for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { + // old_dp = dp; + // ///if a[j] is qe + // if (idx->a[k]&1) --dp; + // else ++dp; + + // ed = idx->a[k]>>1; + // if(ed > st) { + // if((old_dp <= cov)) { + // retrive_bqual(qv, NULL, rid, -1, -1, 0, sc_bn); + // fprintf(stderr, "[M::%s]\tlf::[%ld,%ld)\trt::[%ld,%ld)\tmd::[%ld,%ld)\tcov::%ld\n", __func__, s0, s1, e0, e1, st, ed, old_dp); + // for (qk = st; qk < ed; qk++) fprintf(stderr, "%u", qv->a[qk]); + // fprintf(stderr, "\n"); + // return 1; + // } + // } + // st = ed; + // } + + + // ed = len; old_dp = dp; + // if(ed > st) { + // if((old_dp <= cov)) { + // retrive_bqual(qv, NULL, rid, -1, -1, 0, sc_bn); + // fprintf(stderr, "[M::%s]\tlf::[%ld,%ld)\trt::[%ld,%ld)\tmd::[%ld,%ld)\tcov::%ld\n", __func__, s0, s1, e0, e1, st, ed, old_dp); + // for (qk = st; qk < ed; qk++) fprintf(stderr, "%u", qv->a[qk]); + // fprintf(stderr, "\n"); + // return 1; + // } + // } + + return 0; +} + +void init_gen_hc_aln_t(gen_hc_aln_t *ez, overlap_region_alloc *ol, Candidates_list *cl, All_reads *rref, UC_Read *qu, UC_Read *tu, bit_extz_t *exz, overlap_region *aux_o, overlap_region *rse_o, + asg8_v *hpz, double e_rate_l, double e_rate_h, int64_t wl_l, int64_t wl_h, int64_t rid, int64_t khit, int64_t move_gap, asg16_v *buf, asg64_v *srt, ma_hit_t_alloc *in, + int8_t chem_drop_l, int8_t chem_drop_h, double align_gap_rate_l, double align_gap_rate_h, int64_t align_gap_max_l, int64_t align_gap_max_h, + uint64_t sec_aln_win, uint64_t sec_aln_cov, double sec_aln_err_rate, double sec_aln_max, asg64_v *kp, asg32_v *v32, asg64_v *bp, ha_abuf_t *ab, uint64_t max_n_chain, uint64_t max_n_chain_f, uint64_t chain_cutoff, + uint64_t ave_cov_min, uint64_t ocw, uint64_t t_cut) +{ + ez->ol = ol; + ez->cl = cl; + ez->rref = rref; + ez->qu = qu; + ez->tu = tu; + ez->exz = exz; + ez->aux_o = aux_o; + ez->rse_o = rse_o; + ez->e_rate[0] = e_rate_l; + ez->e_rate[1] = e_rate_h; + ez->wl[0] = wl_l; + ez->wl[1] = wl_h; + ez->rid = rid; + ez->khit = khit; + ez->move_gap = move_gap; + ez->buf = buf; + ez->srt = srt; + ez->in = in; + + ez->chem_drop[0] = chem_drop_l; + ez->chem_drop[1] = chem_drop_h; + ez->align_gap_rate[0] = align_gap_rate_l; + ez->align_gap_rate[1] = align_gap_rate_h; + ez->align_gap_max[0] = align_gap_max_l; + ez->align_gap_max[1] = align_gap_max_h; + + ez->sec_aln_win = sec_aln_win; + ez->sec_aln_cov = sec_aln_cov; + ez->sec_aln_err_rate = sec_aln_err_rate; + ez->sec_aln_max = sec_aln_max; + ez->kp = kp; + + ez->v32 = v32; + ez->bp = bp; + ez->ab = ab; + ez->max_n_chain = max_n_chain; + ez->max_n_chain_f = max_n_chain_f; + ez->chain_cutoff = chain_cutoff; + ez->ave_cov_min = ave_cov_min; + ez->ocw = ocw; + + ez->t_cut = t_cut; + ez->hpz = hpz; +} + + +static void worker_hap_ec(void *data, long i, int tid) +{ + ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); + uint32_t high_occ = asm_opt.hom_cov * (2.0 - HA_KMER_GOOD_RATIO); + uint32_t low_occ = asm_opt.hom_cov * HA_KMER_GOOD_RATIO; ///gen_hc_aln_t ez; + overlap_region *aux_o = NULL/**, *rse_o = NULL**/; asg64_v buf0; uint32_t qlen = 0, qw = 0; + b->v8q.n = b->v8t.n = 0; + + + // 25e396cf-a58d-4f67-a391-33f36fb3891f 0 48396 id:i:1477155 + // 8583bdfa-f38f-4976-be74-2357e1905852 0 43608 id:i:2857459 + + // if (memcmp("9edb4aa1-3a56-40dc-b687-77e4176d1053", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0 || + // memcmp("25e30873-9737-4e6d-bdb6-a504a26ef3de", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0 || + // memcmp("19699b82-2883-43e1-a11e-ec0c95eaccd4", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + // fprintf(stderr, "\n+[M::%s]\trid-target::%ld\t%.*s\n", __func__, i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); + // } + + + + // if(i != 3621590) return;///need to dig into later + + // if(i != 1461185) return; + + // if(i != 27542) return; + // if(i != 25765) return; + // if(i != 898) return; + // if(i != 6843) return; + // if(i != 14627) return; + + // if(i != 7148) return; + + // if(i != 339646) return; + // if(i!=854835) return; + + + + // if(i % 100000 == 0) fprintf(stderr, "-a-[M::%s-beg] rid->%ld\n", __func__, i); + // if (memcmp("c42804f3-0e13-43a0-8a71-b91b40accf9a", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + // if (memcmp("b2e68ecf-381a-439c-b676-c1e6831d6acf", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + // if (memcmp("e3f3f43a-e200-4cac-8acd-3f85428f3811", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + // if (memcmp("4e144e93-4653-4ebf-8920-7943e378cf9a", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + // fprintf(stderr, "-a-[M::%s-beg] rid->%ld\n", __func__, i); + // } else { + // return; + // } + + + // debug_retrive_bqual(D, &b->v8t, i, 256); return; + + recover_UC_Read(&b->self_read, &R_INF, i); qlen = b->self_read.length; + qw = ((qlen < (COV_W_AC<<1))?(qlen>>1):(COV_W_AC)); if(!qw) qw = 1; + // if(qlen <= 0) return; + + + h_ec_lchain(b->ab, i, b->self_read.seq, b->self_read.length, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, ((asm_opt.is_ont)?(0.05):(0.02)), asm_opt.max_n_chain, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 3, 0.7, 2, 32, COV_W, 1);///ONT high error + + // b->num_read_base += b->olist.length; + b->cnt[0] += b->self_read.length; + + aux_o = fetch_aux_ovlp(&b->olist, NULL/**&rse_o**/);///must be here + + + // stderr_phase_ovlp(&b->olist); + + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + ///mz1_ha_sketch(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); + // if((asm_opt.is_ont) && (b->olist.length)) get_mz1(qu->seq, qu->length, RES_W, RES_K, 0, !(asm_opt.flag & HA_F_NO_HPC), b->ab, NULL, NULL, asm_opt.mz_sample_dist, NULL, NULL, NULL, -1, asm_opt.dp_min_len, -1, &(b->sp), asm_opt.mz_rewin, 0, NULL, 0); + + // fprintf(stderr, "\n+[M::%s]\trid::%ld\t%.*s\n", __func__, i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); + + + ///r769: kp (gen_hc_r_alin_ea) -> NULL; site_sc (rphase_hc) -> 0 + ///r770: kp (gen_hc_r_alin_ea) -> buf0; site_sc (rphase_hc) -> 0 + ///r789: kp (gen_hc_r_alin_ea) -> NULL; site_sc (rphase_hc) -> 0 + ///r791: kp (gen_hc_r_alin_ea) -> buf0; site_sc (rphase_hc) -> 0 + copy_asg_arr(buf0, b->sp); + gen_hc_r_alin_ea_flt(b->ab, &b->olist, &b->clist, &R_INF, &b->self_read, &b->ovlp_read, &b->exz, aux_o, asm_opt.max_n_chain, asm_opt.max_n_chain*HC_MF_R, asm_opt.chn_occ, asm_opt.max_ov_diff_ec, (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), i, E_KHIT, + 1, &b->v16, &b->v64, &(R_INF.paf[i]), asm_opt.is_ont, (asm_opt.is_ont)?(0.006):(-1), (asm_opt.is_ont)?(64):(-1), (asm_opt.is_ont)?(512):(0), (asm_opt.is_ont)?(6):(0), + (asm_opt.is_ont)?(1.5):(-1), (asm_opt.is_ont)?(0.1):(-1), &buf0, qw, &b->v8q, &b->v32); + copy_asg_arr(b->sp, buf0); + + /** + copy_asg_arr(buf0, b->sp); + //kp: r763 -> r765: buf0 -> NULL + //kp: r766 -> r767: NULL -> buf0 + gen_hc_r_alin_ea(&b->olist, &b->clist, &R_INF, &b->self_read, &b->ovlp_read, &b->exz, aux_o, asm_opt.max_ov_diff_ec, (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), i, E_KHIT, + 1, &b->v16, &b->v64, &(R_INF.paf[i]), asm_opt.is_ont, (asm_opt.is_ont)?(0.006):(-1), (asm_opt.is_ont)?(64):(-1), (asm_opt.is_ont)?(512):(0), (asm_opt.is_ont)?(6):(0), + (asm_opt.is_ont)?(1.5):(-1), (asm_opt.is_ont)?(0.1):(-1), (asm_opt.is_ont)?(&buf0):(NULL), &b->v8q); + + + // init_gen_hc_aln_t(&ez, &b->olist, &b->clist, &R_INF, &b->self_read, &b->ovlp_read, &b->exz, aux_o, + // asm_opt.max_ov_diff_ec, asm_opt.max_ov_diff_ec, (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), i, E_KHIT, 1, &b->v16, &b->v64, &(R_INF.paf[i]), + // asm_opt.is_ont, asm_opt.is_ont, (asm_opt.is_ont)?(0.006):(-1), (asm_opt.is_ont)?(0.006):(-1), (asm_opt.is_ont)?(64):(-1), (asm_opt.is_ont)?(64):(-1), + // (asm_opt.is_ont)?(512):(0), (asm_opt.is_ont)?(6):(0), (asm_opt.is_ont)?(1.5):(-1), (asm_opt.is_ont)?(0.1):(-1), (asm_opt.is_ont)?(&buf0):(NULL), (uint64_t)-1); + // gen_hc_r_alin_ea_adv(&ez); + copy_asg_arr(b->sp, buf0); + **/ + + // fprintf(stderr, "-[M::%s] rid::%ld\n", __func__, i); + //for debug indel + // prt_ovlp_sam(&b->olist, &b->ovlp_read, b->self_read.seq, b->self_read.length); + // stderr_phase_ovlp(&b->olist); + + + // fprintf(stderr, "\n[M::%s] rid::%ld\t%.*s\tlen::%lld\tocc::%lu\n", __func__, i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i), b->self_read.length, b->olist.length); + + // fprintf(stderr, "[M::%s] rid::%ld\n", __func__, i); + // debug_mm_exact_cigar(&b->olist, i, &b->self_read, &b->ovlp_read); + + // b->num_correct_base += b->olist.length; + /** + * ///r779: enable this + copy_asg_arr(buf0, b->sp); + gen_reseed_re(&b->olist, &b->clist, aux_o, rse_o, &R_INF, &b->self_read, &b->ovlp_read, &b->exz, &b->pidx, &b->v64, &buf0, 0, asm_opt.mz_win, 19, i, asm_opt.max_ov_diff_ec, asm_opt.max_ov_diff_ec, &b->v16, R_INF.tqn, b->v8q.a); + copy_asg_arr(b->sp, buf0); + **/ + + copy_asg_arr(buf0, b->sp); + //site_sc: r765 -> r766: 1 -> 0 + rphase_hc(&b->olist, &R_INF, &b->hap, &b->self_read, &b->ovlp_read, &b->pidx, &b->v64, &buf0, 0, WINDOW_MAX_SIZE, b->self_read.length, 1/**, 0**/, i, (asm_opt.is_ont)?HPC_PL:0, asm_opt.is_ont, ((asm_opt.is_ont)?&(b->clist.chainDP):NULL), ((asm_opt.is_sc)?&(b->v8q):NULL), /**((asm_opt.is_sc)?&(b->v8t):NULL)**/&(b->v8t), (asm_opt.is_ont)?1:0, ((uint64_t)-1), 0, HC0_W, &b->v32); + copy_asg_arr(b->sp, buf0); + ///for debug indel + // stderr_phase_ovlp(&b->olist); + + + dedup_chains(&b->olist); + + + + copy_asg_arr(buf0, b->sp); + b->cnt[1] += wcns_gen(&b->olist, &R_INF, i, &b->self_read, &b->ovlp_read, &b->exz, &b->pidx, &b->v64, &buf0, 0, 512, b->self_read.length, 3, 0.500001, aux_o, &b->v32, &b->cns, 256, i, ((uint64_t)-1), NULL); + copy_asg_arr(b->sp, buf0); + + + push_nec_re(aux_o, &(scc.a[i])); + push_nec_re(aux_o, &(scb.a[i])); + + // if((asm_opt.is_ont) && is_chemical_r_qual(&b->olist, &b->v64, qlen, 1, 16, &(b->v8q), i)/**(is_uncorrected_read(&b->olist, &b->v64, qlen, 1600))**/) { + // // b->olist.length = 0; + // fprintf(stderr, "[M::%s] rid::%ld\t%.*s\n\n", __func__, i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); + // } + + push_ne_ovlp(&(R_INF.paf[i]), &b->olist, 1, &R_INF, &(scc.a[i])/**, i, &b->self_read, &b->ovlp_read**/); + push_ne_ovlp(&(R_INF.reverse_paf[i]), &b->olist, 2, &R_INF, NULL/**, i, NULL, NULL**/); + + + check_well_cal(&(scc.a[i]), &b->v64, &(R_INF.paf[i].is_fully_corrected), &(R_INF.paf[i].is_abnormal), qlen, (MIN_COVERAGE_THRESHOLD*2), &(R_INF.paf[i])); + R_INF.trio_flag[i] = AMBIGU; + + // uint32_t k; + // for (k = 0; k < b->olist.length; k++) { + // if(b->olist.list[k].is_match == 1) b->num_recorrect_base++; + // } + ///for debug indel + // exit(1); + + + + // prt_chain(&b->olist); + + // ul_map_lchain(b->abl, (uint32_t)-1, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->clist, s->opt->bw_thres, + // s->opt->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2/**0.75**/, 2, 3); + + /** + int fully_cov, abnormal; + // if(i != 12578) return; + // fprintf(stderr, "[M::%s-beg] rid->%ld\n", __func__, i); + // if (memcmp("7897e875-76e5-42c8-bc37-94b370c4cc8d", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + // fprintf(stderr, "[M::%s-beg] rid->%ld\n", __func__, i); + // } else { + // return; + // } + + ha_get_candidates_interface(b->ab, i, &b->self_read, &b->olist, &b->olist_hp, &b->clist, + 0.02, asm_opt.max_n_chain, 1, NULL, &b->r_buf, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), &(b->tmp_region), NULL, &(b->sp)); + + clear_Cigar_record(&b->cigar1); + clear_Round2_alignment(&b->round2); + + correct_overlap(&b->olist, &R_INF, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, + &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 1, &fully_cov, &abnormal); + + b->num_read_base += b->self_read.length; + b->num_correct_base += b->correct.corrected_base; + b->num_recorrect_base += b->round2.dumy.corrected_base; + + push_cigar(R_INF.cigars, i, &b->cigar1); + push_cigar(R_INF.second_round_cigar, i, &b->round2.cigar); + + R_INF.paf[i].is_fully_corrected = 0; + if (fully_cov) { + if (get_cigar_errors(&b->cigar1) == 0 && get_cigar_errors(&b->round2.cigar) == 0) + R_INF.paf[i].is_fully_corrected = 1; + } + R_INF.paf[i].is_abnormal = abnormal; + + R_INF.trio_flag[i] = AMBIGU; + + ///need to be fixed in r305 + // if(ha_idx_hp == NULL) + // { + // R_INF.trio_flag[i] += collect_hp_regions(&b->olist, &R_INF, &(b->k_flag), RESEED_HP_RATE, Get_READ_LENGTH(R_INF, i), NULL); + // } + + if (R_INF.trio_flag[i] != AMBIGU || b->save_ov) { + int is_rev = (asm_opt.number_of_round % 2 == 0); + push_overlaps(&(R_INF.paf[i]), &b->olist, 1, &R_INF, is_rev); + push_overlaps(&(R_INF.reverse_paf[i]), &b->olist, 2, &R_INF, is_rev); + } + + if(het_cnt) het_cnt[i] = get_het_cnt(&b->hap); + // fprintf(stderr, "[M::%s-end] rid->%ld\n", __func__, i); + **/ + // exit(1); + refresh_ec_ovec_buf_t0(b, REFRESH_N); + + /** + fprintf(stderr, "%ld\t---\n", i); + **/ +} + +static void worker_hap_ec_hybrid(void *data, long i, int tid) +{ + ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); + uint32_t high_occ = asm_opt.hom_cov * (2.0 - HA_KMER_GOOD_RATIO); + uint32_t low_occ = asm_opt.hom_cov * HA_KMER_GOOD_RATIO; double bw_h, bw_l, e_h, e_l; + gen_hc_aln_t ez; overlap_region *aux_o = NULL, *rse_o = NULL; asg64_v buf0, buf1; uint64_t qlen = 0, qw = 0, qid = i; //uint64_t sk[2], ek[2], fn, qid = i, nec; + if(qid < R_INF.tqn) {///ont + bw_h = 0.05; bw_l = 0.035; e_h = asm_opt.max_ov_diff_ec; e_l = (asm_opt.max_ov_diff_ec + asm_opt.max_ov_diff_ec_sec)/2; + } else { ///HiFi + bw_h = 0.035; bw_l = 0.02; e_h = (asm_opt.max_ov_diff_ec + asm_opt.max_ov_diff_ec_sec)/2; e_l = asm_opt.max_ov_diff_ec_sec; + } + b->v8q.n = b->v8t.n = 0; + + // if(i != 5966) return; + + // fprintf(stderr, "-a-[M::%s] rid::%ld\n", __func__, i); + + //id:i:21102 + // if (memcmp("a59fab4a-892b-4ab7-bf4b-926bed57865b_1", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + //id:i:3504 + // if (memcmp("485f7963-eeb4-4745-ab74-1be4d61460c3", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + // fprintf(stderr, "-a-[M::%s-beg] rid->%ld, rlen->%lu\n", __func__, i, Get_READ_LENGTH((R_INF),i)); + // } else { + // return; + // } + + + // if(i != 9) return; + + // debug_retrive_bqual(D, &b->v8t, i, 256); return; + + recover_UC_Read(&b->self_read, &R_INF, i); qlen = b->self_read.length; + qw = ((qlen < (COV_W_AC<<1))?(qlen>>1):(COV_W_AC)); if(!qw) qw = 1; + // if(qlen <= 0) return; + + h_ec_lchain_hybrid(b->ab, i, b->self_read.seq, b->self_read.length, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, bw_h, bw_l, + /**((asm_opt.is_ont)?(0.05):(0.02)),**/ asm_opt.max_n_chain, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 3, 0.7, 2, 32, COV_W, R_INF.tqn, 1);///ONT high error + + // fprintf(stderr, "-b-[M::%s] rid::%ld\n", __func__, i); + + // b->num_read_base += b->olist.length; + b->cnt[0] += b->self_read.length; + + aux_o = fetch_aux_ovlp(&b->olist, NULL/**&rse_o**/);///must be here + + copy_asg_arr(buf0, b->sp); + init_gen_hc_aln_t(&ez, &b->olist, &b->clist, &R_INF, &b->self_read, &b->ovlp_read, &b->exz, aux_o, rse_o, &b->v8q, + e_l, e_h, (qid < R_INF.tqn)?(WINDOW_OHC):(WINDOW_HC), WINDOW_OHC, i, E_KHIT, 1, &b->v16, &b->v64, &(R_INF.paf[i]), + ((qid < R_INF.tqn)?(1):(0)), 1, (qid < R_INF.tqn)?(0.006):(-1), 0.006, (qid < R_INF.tqn)?(64):(-1), 64, + (qid < R_INF.tqn)?(512):(0), (qid < R_INF.tqn)?(6):(0), (qid < R_INF.tqn)?(1.5):(-1), (qid < R_INF.tqn)?(0.1):(-1), NULL, + &(b->v32), &buf0, b->ab, (asm_opt.max_n_chain>0)?(asm_opt.max_n_chain):(1), ((asm_opt.max_n_chain*HC_MF_R)>0)?(asm_opt.max_n_chain*HC_MF_R):1, + asm_opt.chn_occ, ((asm_opt.hom_cov*HC_AV_MIN)>0)?(asm_opt.hom_cov*HC_AV_MIN):(1), qw, R_INF.tqn); + // gen_hc_r_alin_ea_adv(&ez); + gen_hc_r_alin_ea_adv_flt(&ez); + copy_asg_arr(b->sp, buf0); + + // fprintf(stderr, "-c-[M::%s] rid::%ld\n", __func__, i); + /** + copy_asg_arr(buf0, b->sp); + init_gen_hc_aln_t(&ez, &b->olist, &b->clist, &R_INF, &b->self_read, &b->ovlp_read, &b->exz, aux_o, rse_o, &b->v8q, + e_l, e_h, (qid < R_INF.tqn)?(WINDOW_OHC):(WINDOW_HC), WINDOW_OHC, i, E_KHIT, 1, &b->v16, &b->v64, &(R_INF.paf[i]), + ((qid < R_INF.tqn)?(1):(0)), 1, (qid < R_INF.tqn)?(0.006):(-1), 0.006, (qid < R_INF.tqn)?(64):(-1), 64, + (qid < R_INF.tqn)?(512):(0), (qid < R_INF.tqn)?(6):(0), (qid < R_INF.tqn)?(1.5):(-1), (qid < R_INF.tqn)?(0.1):(-1), (qid < R_INF.tqn)?(&buf0):(NULL), + NULL, NULL, NULL, -1, -1, -1, R_INF.tqn); + gen_hc_r_alin_ea_adv(&ez); + copy_asg_arr(b->sp, buf0); + **/ + + // stderr_phase_ovlp(&b->olist); + + ///debug for memory + // snprintf(NULL, 0, "dwn::%u\tdcn::%u", (uint32_t)aux_o->w_list.n, (uint32_t)aux_o->w_list.c.n); + ///mz1_ha_sketch(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), &ab->mz, ha_flt_tab, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL); + + // fprintf(stderr, "-[M::%s] rid::%ld\n", __func__, i); + + + // fprintf(stderr, "\n[M::%s] rid::%ld\t%.*s\tlen::%lld\tocc::%lu\n", __func__, i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i), b->self_read.length, b->olist.length); + + // fprintf(stderr, "[M::%s] rid::%ld\n", __func__, i); + // debug_mm_exact_cigar(&b->olist, i, &b->self_read, &b->ovlp_read); + + // b->num_correct_base += b->olist.length; + /** + copy_asg_arr(buf0, b->sp); + gen_reseed_re(&b->olist, &b->clist, aux_o, rse_o, &R_INF, &b->self_read, &b->ovlp_read, &b->exz, &b->pidx, &b->v64, &buf0, 0, asm_opt.mz_win, 19, i, e_h, e_l, &b->v16, R_INF.tqn, b->v8q.a); + copy_asg_arr(b->sp, buf0); + **/ + + ///for debug indel + // prt_ovlp_sam(&b->olist, &b->ovlp_read, b->self_read.seq, b->self_read.length); + + copy_asg_arr(buf0, b->sp); + rphase_hc(&b->olist, &R_INF, &b->hap, &b->self_read, &b->ovlp_read, &b->pidx, &b->v64, &buf0, 0, WINDOW_MAX_SIZE, b->self_read.length, 1/**, 0**/, i, (asm_opt.is_ont)?HPC_PL:0, asm_opt.is_ont, ((asm_opt.is_ont)?&(b->clist.chainDP):NULL), /**((asm_opt.is_sc)?&(b->v8q):NULL)**/&(b->v8q), ((asm_opt.is_sc)?&(b->v8t):NULL), (asm_opt.is_ont)?1:0, R_INF.tqn, 0/**1**/, HC0_W, &b->v32); + copy_asg_arr(b->sp, buf0); + ///for debug indel + // stderr_phase_ovlp(&b->olist); + + dedup_chains(&b->olist); + + copy_asg_arr(buf0, b->sp); copy_asg_arr(buf1, b->hap.snp_srt); + b->cnt[1] += wcns_gen(&b->olist, &R_INF, i, &b->self_read, &b->ovlp_read, &b->exz, &b->pidx, &b->v64, &buf0, 0, 512, b->self_read.length, 3, 0.500001, aux_o, &b->v32, &b->cns, 256, i, R_INF.tqn, &buf1); + copy_asg_arr(b->sp, buf0); copy_asg_arr(b->hap.snp_srt, buf1); + + push_nec_re(aux_o, &(scc.a[i])); + push_nec_re(aux_o, &(scb.a[i])); + + // if((asm_opt.is_ont) && is_chemical_r_qual(&b->olist, &b->v64, qlen, 1, 16, &(b->v8q), i)/**(is_uncorrected_read(&b->olist, &b->v64, qlen, 1600))**/) { + // // b->olist.length = 0; + // fprintf(stderr, "[M::%s] rid::%ld\t%.*s\n\n", __func__, i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); + // } + + push_ne_ovlp(&(R_INF.paf[i]), &b->olist, 1, &R_INF, &(scc.a[i])/**, i, &b->self_read, &b->ovlp_read**/); + push_ne_ovlp(&(R_INF.reverse_paf[i]), &b->olist, 2, &R_INF, NULL/**, i, NULL, NULL**/); + + + check_well_cal(&(scc.a[i]), &b->v64, &(R_INF.paf[i].is_fully_corrected), &(R_INF.paf[i].is_abnormal), qlen, (MIN_COVERAGE_THRESHOLD*2), &(R_INF.paf[i])); + R_INF.trio_flag[i] = AMBIGU; + + // prt_chain(&b->olist); + + // ul_map_lchain(b->abl, (uint32_t)-1, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->clist, s->opt->bw_thres, + // s->opt->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2/**0.75**/, 2, 3); + // exit(1); + refresh_ec_ovec_buf_t0(b, REFRESH_N); + // exit(0); +} + + + +static void worker_hap_ec_dbg_paf(void *data, long i, int tid) +{ + ec_ovec_buf_t0 *b = &(((cal_ec_r_dbg_step_t*)data)->buf->a[tid]); + r_dbg_step_res_t *rr = &(((cal_ec_r_dbg_step_t*)data)->res[tid]); + uint32_t high_occ = asm_opt.hom_cov * (2.0 - HA_KMER_GOOD_RATIO); + uint32_t low_occ = asm_opt.hom_cov * HA_KMER_GOOD_RATIO; + overlap_region *aux_o = NULL; i += ((cal_ec_r_dbg_step_t*)data)->si; + + // debug_retrive_bqual(D, &b->v8t, i, 256); return; + + recover_UC_Read(&b->self_read, &R_INF, i); + + h_ec_lchain(b->ab, i, b->self_read.seq, b->self_read.length, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, ((asm_opt.is_ont)?(0.05):(0.02)), asm_opt.max_n_chain, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 3, 0.7, 2, 32, COV_W, 0);///ONT high error + + aux_o = fetch_aux_ovlp(&b->olist, NULL);///must be here + + // stderr_phase_ovlp(&b->olist); + gen_hc_r_alin_ea(&b->olist, &b->clist, &R_INF, &b->self_read, &b->ovlp_read, &b->exz, aux_o, asm_opt.max_ov_diff_ec, (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), i, E_KHIT, 1, &b->v16, &b->v64, &(R_INF.paf[i]), 0, -1, -1, 0, 0, -1, -1, NULL, &b->v8q); + + uint32_t k, m, tl; overlap_region *z; bit_extz_t ez; ma_hit_t *t; + for (k = 0; k < b->olist.length; k++) { + z = &(b->olist.list[k]); + if(!(z->w_list.n)) continue; + + tl = Get_READ_LENGTH((R_INF), z->y_id); + for (m = 0; m < z->w_list.n; m++) { + if(is_ualn_win(z->w_list.a[m])) continue; + set_bit_extz_t(ez, (*z), m); + kv_pushp(ma_hit_t, *rr, &t); + + t->qns = z->x_id; t->qns = t->qns << 32; + t->tn = z->y_id; + + t->qns = t->qns | (uint64_t)(z->w_list.a[m].x_start); + t->qe = z->w_list.a[m].x_end + 1; + + t->ts = z->w_list.a[m].y_start; + t->te = z->w_list.a[m].y_end + 1; + + t->rev = z->y_pos_strand; + + t->bl = rr->ec.n; + kv_resize(uint16_t, rr->ec, rr->ec.n + ez.cigar.n); + memcpy(rr->ec.a + rr->ec.n, ez.cigar.a, ez.cigar.n * sizeof((*(rr->ec.a)))); + rr->ec.n += ez.cigar.n; + t->cc = rr->ec.n - t->bl; + + if(t->rev) { + t->ts = tl - z->w_list.a[m].y_end - 1; + t->te = tl - z->w_list.a[m].y_start; + } + } + } +} + +uint32_t adjust_exact_match(asg16_v *in, int64_t xs0, int64_t xe0, int64_t ys0, int64_t ye0, uint64_t *rxs, uint64_t *rxe, uint64_t *rys, uint64_t *rye, uint32_t rev) +{ + *rxs = *rxe = *rys = *rye = 0; + if((xe0 <= xs0) || (ye0 <= ys0)) return 0; + int64_t xk, yk, ck, cn = in->n, wx[2], wy[2], os, oe; uint16_t op, bq, bt; uint32_t cl; uint64_t ovlp; + xk = yk = 0; + + // fprintf(stderr, "[M::%s]\tx0::[%ld,%ld)\ty0::[%ld,%ld)\trev::%u\n", __func__, xs0, xe0, ys0, ye0, rev); + + if(!rev) { + ck = 0; + while (ck < cn && xk < xe0) { + wx[0] = xk; wy[0] = yk; + // ck = pop_trace_bp(in, ck, &op, &b, &cl); + ck = pop_trace_bp_f(in, ck, &op, &bq, &bt, &cl); + if(op != 2) xk += cl; + if(op != 3) yk += cl; + wx[1] = xk; wy[1] = yk; + // fprintf(stderr, "[M::%s]\told::[%ld,%ld]\tnew::[%ld,%ld]\t%u%c\n", __func__, wx[0], wx[1], wy[0], wy[1], cl, "MSID"[op]); + if(op == 0) { + os = MAX(xs0, wx[0]); oe = MIN(xe0, wx[1]); + ovlp = ((oe>os)? (oe-os):0); + if((ovlp > 0) && (ovlp > (*rxe) - (*rxs))) { + // fprintf(stderr, "[M::%s]\to::[%ld,%ld)\n", __func__, os, oe); + (*rxs) = wy[0] + os - wx[0]; + (*rxe) = wy[0] + oe - wx[0]; + + (*rys) = ys0 + os - xs0; + (*rye) = ys0 + oe - xs0; + } + } + // if((op == 0) && (wx[0] <= s) && (wx[1] >= e)) { + // (*rs) = wy[0] + s - wx[0]; + // (*re) = wy[0] + e - wx[0]; + // } + } + } else { + ck = cn - 1; + while (ck >= 0 && xk < xe0) { + wx[0] = xk; wy[0] = yk; + // ck = pop_trace_bp_rev(in, ck, &op, &b, &cl); + ck = pop_trace_bp_rev_f(in, ck, &op, &bq, &bt, &cl); + if(op != 2) xk += cl; + if(op != 3) yk += cl; + wx[1] = xk; wy[1] = yk; + if(op == 0) { + os = MAX(xs0, wx[0]); oe = MIN(xe0, wx[1]); + ovlp = ((oe>os)? (oe-os):0); + if((ovlp > 0) && (ovlp > (*rxe) - (*rxs))) { + (*rxs) = wy[0] + os - wx[0]; + (*rxe) = wy[0] + oe - wx[0]; + + (*rys) = ys0 + os - xs0; + (*rye) = ys0 + oe - xs0; + } + } + // if((op == 0) && (wx[0] <= s) && (wx[1] >= e)) { + // (*rs) = wy[0] + s - wx[0]; + // (*re) = wy[0] + e - wx[0]; + // } + } + } + + + return (*rxe) - (*rxs); +} + +uint32_t quick_exact_match(ma_hit_t *z, All_reads *rref, UC_Read* qu, UC_Read* tu, cc_v *sc) +{ + uint64_t rts, rte, rqs, rqe, f = 0; int64_t ql, tl, qr, tr, qs, qe, ts, te; + + // fprintf(stderr, "-0-[M::%s]\tf::%lu\n", __func__, f); + if(adjust_exact_match(&(sc->a[z->tn]), z->ts, z->te, ((uint32_t)(z->qns)), z->qe, &rts, &rte, &rqs, &rqe, z->rev)) { + z->ts = rts; z->te = rte; f = 1; + z->qns >>= 32; z->qns <<= 32; z->qns |= ((uint64_t)(rqs)); z->qe = rqe; + + ///debug + // qs = rqs; qe = rqe; ts = rts; te = rte; + // resize_UC_Read(tu, te - ts); + // recover_UC_Read_sub_region(tu->seq, ts, te - ts, z->rev, rref, z->tn); + + // fprintf(stderr, "[M::%s]\trq::[%lu,%lu)\trt::[%lu,%lu)\n", __func__, rqs, rqe, rts, rte); + // fprintf(stderr, "-0-[M::%s] qstr::%.*s\n", __func__, ((int)(qe - qs)), qu->seq + qs); + // fprintf(stderr, "-0-[M::%s] tstr::%.*s\n", __func__, ((int)(te - ts)), tu->seq); + + // if(memcmp(qu->seq + qs, tu->seq, qe - qs) == 0) { + // fprintf(stderr, "-0-[M::%s]\tsb\n", __func__); + // } else { + // fprintf(stderr, "-1-[M::%s]\tsa\n", __func__); + // } + } + // fprintf(stderr, "-1-[M::%s]\tf::%lu\n", __func__, f); + ql = qu->length; tl = Get_READ_LENGTH((*rref), z->tn); + qs = ((uint32_t)(z->qns)); qe = z->qe; ts = z->ts; te = z->te; + if(qs >= ql) {qs = ql;} if(qe > ql) {qe = ql;} if(qe <= qs) {f = 0;} + // fprintf(stderr, "-2-[M::%s]\tf::%lu\n", __func__, f); + if(ts >= tl) {ts = tl;} if(te > tl) {te = tl;} if(te <= ts) {f = 0;} + // fprintf(stderr, "-3-[M::%s]\tf::%lu\n", __func__, f); + if((qe - qs) != (te - ts)) {f = 0;} + // fprintf(stderr, "-4-[M::%s]\tf::%lu\n", __func__, f); + + if(qs <= ts) { + ts -= qs; qs = 0; + } else { + qs -= ts; ts = 0; + } + + + qr = ql - qe; tr = tl - te; + if(qr <= tr) { + qe = ql; te += qr; + } else { + te = tl; qe += tr; + } + + // fprintf(stderr, "-5-[M::%s]\tzq::[%ld,\t%ld)\tzt::[%ld,\t%ld)\teq::[%u,\t%u)\tet::[%u,\t%u)\tql::%ld\ttl::%ld\tf::%lu\n", + // __func__, qs, qe, ts, te, ((uint32_t)(z->qns)), z->qe, z->ts, z->te, ql, tl, f); + + z->qns >>= 32; z->qns <<= 32; z->qns |= ((uint64_t)(qs)); z->qe = qe; + z->ts = ts; z->te = te; + + if((f) && ((te - ts) == (qe - qs)) && (qe > qs)) { + resize_UC_Read(tu, te - ts); + recover_UC_Read_sub_region(tu->seq, ts, te - ts, z->rev, rref, z->tn); + + // fprintf(stderr, "[M::%s] qstr::%.*s\n", __func__, ((int)(qe - qs)), qu->seq + qs); + // fprintf(stderr, "[M::%s] tstr::%.*s\n", __func__, ((int)(te - ts)), tu->seq); + + if(memcmp(qu->seq + qs, tu->seq, qe - qs) == 0) return 1; + } + + return 0; +} + +uint64_t cal_cov_re(asg64_v *idx, int64_t *k, uint64_t s, uint64_t e) +{ + uint64_t *a = idx->a, ws, we, cn, os, oe, ovlp, tot = 0; int64_t n = idx->n; + if(n <= 0) return 0; + if((*k) >= n) (*k) = 0; + while (((*k) > 0) && (((uint32_t)a[*k]) > s)) (*k) -= 2; + if((*k) < 0) (*k) = 0; + + while (((*k) < n) && ((a[*k]>>32) < e)) { + ws = (a[*k]>>32); we = ((uint32_t)a[*k]); cn = a[(*k) + 1]; + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + tot += (ovlp*cn); + (*k) += 2; + } + + return tot; +} + +uint64_t gen_hap_dc_cov(asg64_v *be, asg64_v *ba, ma_hit_t_alloc *paf, All_reads *rref, uint64_t wl, int64_t occ_exact, double occ_exact_rate, UC_Read* qu, UC_Read* tu, cc_v *sc, uint64_t rid) +{ + ma_hit_t *z; be->n = ba->n = 0; uint64_t k, s, e, vn, m; asg64_v *v = NULL; + int64_t dp, old_dp, st = 0, ed, ql = qu->length, qs, qe, ff; + for (k = 0; k < paf->length; k++) { + z = &(paf->buffer[k]); + + // if(rid == 16) { + // fprintf(stderr, "[M::%s]\tqn::%u::%.*s\ttn::%u::%.*s\t%c\tq::[%u,%u)\tq::[%u,%u)\tel::%u\n", __func__, + // (uint32_t)(z->qns>>32), (int)Get_NAME_LENGTH(R_INF, (uint32_t)(z->qns>>32)), Get_NAME(R_INF, (uint32_t)(z->qns>>32)), z->tn, (int)Get_NAME_LENGTH(R_INF, z->tn), Get_NAME(R_INF, z->tn), "+-"[z->rev], + // (uint32_t)z->qns, z->qe, z->ts, z->te, z->el); + // } + + if((z->el) && (quick_exact_match(z, rref, qu, tu, sc))) { + s = ((uint32_t)(z->qns)); e = z->qe; + kv_push(uint64_t, (*be), (s<<1)); + kv_push(uint64_t, (*be), (e<<1)|1); + z->el = 1; + // fprintf(stderr, "-gmm-[M::%s]\tqn::%u::%.*s\ttn::%u::%.*s\t%c\tq::[%u,%u)\tq::[%u,%u)\n", __func__, + // (uint32_t)(z->qns>>32), (int)Get_NAME_LENGTH(R_INF, (uint32_t)(z->qns>>32)), Get_NAME(R_INF, (uint32_t)(z->qns>>32)), z->tn, (int)Get_NAME_LENGTH(R_INF, z->tn), Get_NAME(R_INF, z->tn), "+-"[z->rev], + // (uint32_t)z->qns, z->qe, z->ts, z->te); + } else { + s = ((uint32_t)(z->qns)); e = z->qe; + kv_push(uint64_t, (*ba), (s<<1)); + kv_push(uint64_t, (*ba), (e<<1)|1); + z->el = 0; + // fprintf(stderr, "-gum-[M::%s]\tqn::%u::%.*s\ttn::%u::%.*s\t%c\tq::[%u,%u)\tq::[%u,%u)\n", __func__, + // (uint32_t)(z->qns>>32), (int)Get_NAME_LENGTH(R_INF, (uint32_t)(z->qns>>32)), Get_NAME(R_INF, (uint32_t)(z->qns>>32)), z->tn, (int)Get_NAME_LENGTH(R_INF, z->tn), Get_NAME(R_INF, z->tn), "+-"[z->rev], + // (uint32_t)z->qns, z->qe, z->ts, z->te); + } + /** + s = ((uint32_t)(z->qns)); e = z->qe; + // sc->a[z->tn] + if(z->el) { + // if((z->qns>>32) == 75 && z->tn == 59) { + if(quick_exact_match(z, rref, qu, tu, sc)) { + s = ((uint32_t)(z->qns)); e = z->qe; + // fprintf(stderr, "-mm-[M::%s]\tqn::%u::%.*s\ttn::%u::%.*s\t%c\n", __func__, + // (uint32_t)(z->qns>>32), (int)Get_NAME_LENGTH(R_INF, (uint32_t)(z->qns>>32)), Get_NAME(R_INF, (uint32_t)(z->qns>>32)), z->tn, (int)Get_NAME_LENGTH(R_INF, z->tn), Get_NAME(R_INF, z->tn), "+-"[z->rev]); + } else { + s = ((uint32_t)(z->qns)); e = z->qe; + // fprintf(stderr, "-um-[M::%s]\tqn::%u::%.*s\ttn::%u::%.*s\t%c\n", __func__, + // (uint32_t)(z->qns>>32), (int)Get_NAME_LENGTH(R_INF, (uint32_t)(z->qns>>32)), Get_NAME(R_INF, (uint32_t)(z->qns>>32)), z->tn, (int)Get_NAME_LENGTH(R_INF, z->tn), Get_NAME(R_INF, z->tn), "+-"[z->rev]); + } + // } + } + **/ + } + + + v = be; vn = v->n; + radix_sort_ec64(v->a, v->a+v->n); + for (k = 0, dp = 0, st = ed = 0; k < vn; ++k) { + old_dp = dp; + ///if a[j] is qe + if (v->a[k]&1) --dp; + else ++dp; + + ed = v->a[k]>>1; + if(ed > st) { + m = st; m <<= 32; m |= ((uint64_t)ed); + kv_push(uint64_t, (*v), m); + kv_push(uint64_t, (*v), old_dp); + if((old_dp + 1) < occ_exact) return 0;///+1 for self + } + st = ed; + } + ed = ql; old_dp = dp; + if(ed > st) { + m = st; m <<= 32; m |= ((uint64_t)ed); + kv_push(uint64_t, (*v), m); + kv_push(uint64_t, (*v), old_dp); + if((old_dp + 1) < occ_exact) return 0;///+1 for self + } + + for (k = vn, m = 0; k < v->n; k++) { + v->a[m++] = v->a[k]; + } + v->n = m; + + + v = ba; vn = v->n; + radix_sort_ec64(v->a, v->a+v->n); + for (k = 0, dp = 0, st = ed = 0; k < vn; ++k) { + old_dp = dp; + ///if a[j] is qe + if (v->a[k]&1) --dp; + else ++dp; + + ed = v->a[k]>>1; + if(ed > st) { + m = st; m <<= 32; m |= ((uint64_t)ed); + kv_push(uint64_t, (*v), m); + kv_push(uint64_t, (*v), old_dp); + } + st = ed; + } + ed = ql; old_dp = dp; + if(ed > st) { + m = st; m <<= 32; m |= ((uint64_t)ed); + kv_push(uint64_t, (*v), m); + kv_push(uint64_t, (*v), old_dp); + } + + for (k = vn, m = 0; k < v->n; k++) { + v->a[m++] = v->a[k]; + } + v->n = m; + + + + + + + + ///debug + // v = be; + // for (k = 0; k < v->n; k += 2) { + // fprintf(stderr, "-be-[M::%s]\tq::[%lu,%u)\tocc::%lu\n", __func__, v->a[k]>>32, (uint32_t)v->a[k], v->a[k+1]); + // } + + // v = ba; + // for (k = 0; k < v->n; k += 2) { + // fprintf(stderr, "-ba-[M::%s]\tq::[%lu,%u)\tocc::%lu\n", __func__, v->a[k]>>32, (uint32_t)v->a[k], v->a[k+1]); + // } + + + + + + + + + + int64_t ke = 0, ka = 0, cc[2]; + qs = 0; qe = wl; qe = ((qe<=ql)?qe:ql); + for (; qs < ql; ) { + cc[0] = cal_cov_re(be, &ke, qs, qe); + cc[1] = cal_cov_re(ba, &ka, qs, qe); + + // fprintf(stderr, "[M::%s]\tq::[%ld,%ld)\tcc[0]::%ld\tcc[1]::%ld\n", __func__, qs, qe, cc[0], cc[1]); + + ff = 0; + if((cc[0]) && (cc[0] > cc[1])) { + cc[0] += qe - qs;///+(qe - qs) for self + cc[1] += cc[0]; + if(cc[0] > (cc[1]*occ_exact_rate)) { + ff = 1; + } + } + + if(ff == 0) return 0; + // fprintf(stderr, "[M::%s-beg]\tq::[%ld,%ld)\tcc[0]::%ld\tcc[1]::%ld\n", __func__, qs, qe, cc[0], cc[1]); + qs += wl; qe += wl; qe = ((qe<=ql)?qe:ql); + } + + + return 1; +} + +static void worker_hap_dc_ec(void *data, long i, int tid) +{ + ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); + // fprintf(stderr, "-0-[M::%s-beg] rid->%ld\n", __func__, i); + // if (memcmp("m64012_190921_234837/139067658/ccs", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + // fprintf(stderr, "-0-[M::%s-beg] rid->%ld\n", __func__, i); + // } else if (memcmp("m64012_190921_234837/28968323/ccs", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + // fprintf(stderr, "-1-[M::%s-beg] rid->%ld\n", __func__, i); + // } else { + // return; + // } + // if(i != 2851) return; + + // if(scb.a[i].m < scc.a[i].n) { + // scb.a[i].m = scc.a[i].n; + // REALLOC(scb.a[i].a, scb.a[i].m); + // } + // scb.a[i].n = scc.a[i].n; + // memcpy(scb.a[i].a, scc.a[i].a, scc.a[i].n*sizeof((*(scb.a[i].a)))); + + scc.f[i] = 0; + + if(!(R_INF.paf[i].length)) return; + // if(scc.f[i]) return; + asg64_v buf0; + + recover_UC_Read(&b->self_read, &R_INF, i); + + copy_asg_arr(buf0, b->sp); + if(gen_hap_dc_cov(&(b->v64), &buf0, &(R_INF.paf[i]), &R_INF, WINDOW_HC_FAST, 4, 0.7, &b->self_read, &b->ovlp_read, &scc, i)) { + scc.f[i] = 1; b->cnt[0]++; + // fprintf(stderr, "-mm-[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); + } else { + scc.f[i] = 0; b->cnt[1]++; + // fprintf(stderr, "-um-[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); + } + copy_asg_arr(b->sp, buf0); + + refresh_ec_ovec_buf_t0(b, REFRESH_N); +} + +static void worker_update_dc_ec(void *data, long i, int tid) +{ + ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); + uint64_t k; ma_hit_t *z; + // fprintf(stderr, "-0-[M::%s-beg] rid->%ld\n", __func__, i); + // if (memcmp("m64012_190921_234837/139067658/ccs", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + // fprintf(stderr, "-0-[M::%s-beg] rid->%ld\n", __func__, i); + // } else if (memcmp("m64012_190921_234837/28968323/ccs", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + // fprintf(stderr, "-1-[M::%s-beg] rid->%ld\n", __func__, i); + // } else { + // return; + // } + // if(i != 2851) return; + + // if(scb.a[i].m < scc.a[i].n) { + // scb.a[i].m = scc.a[i].n; + // REALLOC(scb.a[i].a, scb.a[i].m); + // } + // scb.a[i].n = scc.a[i].n; + // memcpy(scb.a[i].a, scc.a[i].a, scc.a[i].n*sizeof((*(scb.a[i].a)))); + + + if(!(R_INF.paf[i].length)) return; + recover_UC_Read(&b->self_read, &R_INF, i); + for (k = 0; k < R_INF.paf[i].length; k++) { + z = &(R_INF.paf[i].buffer[k]); + if((z->el) && (quick_exact_match(z, &R_INF, &b->self_read, &b->ovlp_read, &scc))) { + z->el = 1; b->cnt[0]++; + } else { + z->el = 0; b->cnt[1]++; + } + } + + refresh_ec_ovec_buf_t0(b, REFRESH_N); +} + + +void flip_paf_rc(uint64_t rid, ma_hit_t_alloc *paf, All_reads *rref) +{ + ma_hit_t *z; uint64_t k, m; int64_t ql = Get_READ_LENGTH((*rref), rid), tl, qs, qe, ts, te; + for (k = m = 0; k < paf->length; k++) { + z = &(paf->buffer[k]); tl = Get_READ_LENGTH((*rref), z->tn); + qs = (uint32_t)z->qns; if(qs < 0) qs = 0; if(qs > ql) qs = ql; + qe = z->qe; if(qe < 0) qe = 0; if(qe > ql) qe = ql; + ts = z->ts; if(ts < 0) ts = 0; if(ts > tl) ts = tl; + te = z->te; if(te < 0) te = 0; if(te > tl) te = tl; + if(qe > qs && te > ts) { + z->qns >>= 32; z->qns <<= 32; + z->qns |= ((uint64_t)(ql - qe)); + z->qe = ql - qs; + z->ts = tl - te; + z->te = tl - ts; + paf->buffer[m++] = *z; + } + } + paf->length = m; +} + +static void worker_hap_post_rev(void *data, long i, int tid) +{ + ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); + uint64_t k, l, kl, nn; char *a, c; + // fprintf(stderr, "-0-[M::%s-beg] rid->%ld\n", __func__, i); + // if (memcmp("m64012_190921_234837/139067658/ccs", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + // fprintf(stderr, "-0-[M::%s-beg] rid->%ld\n", __func__, i); + // } else if (memcmp("m64012_190921_234837/28968323/ccs", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + // fprintf(stderr, "-1-[M::%s-beg] rid->%ld\n", __func__, i); + // } else { + // return; + // } + // if(i != 2851) return; + + // if(scb.a[i].m < scc.a[i].n) { + // scb.a[i].m = scc.a[i].n; + // REALLOC(scb.a[i].a, scb.a[i].m); + // } + // scb.a[i].n = scc.a[i].n; + // memcpy(scb.a[i].a, scc.a[i].a, scc.a[i].n*sizeof((*(scb.a[i].a)))); + + flip_paf_rc(i, &(R_INF.paf[i]), &R_INF); + flip_paf_rc(i, &(R_INF.reverse_paf[i]), &R_INF); + + recover_UC_Read(&b->self_read, &R_INF, i); + l = b->self_read.length; kl = l>>1; a = b->self_read.seq; + for (k = nn = 0; k < kl; k++) { + c = a[l-k-1]; a[l-k-1] = RC_CHAR(a[k]); a[k] = RC_CHAR(c); + if(a[k] == 'N') nn++; + if(a[l-k-1] == 'N') nn++; + } + if(l&1) { + a[k] = RC_CHAR(a[k]); + if(a[k] == 'N') nn++; + } + + ha_compress_base(Get_READ(R_INF, i), a, l, &R_INF.N_site[i], nn); + + if((asm_opt.is_sc) && (((uint64_t)i) < R_INF.tqn)) { + retrive_bqual(&(b->v8q), NULL, i, -1, -1, 0, sc_bn); + for (k = 0; k < l; k++) a[l - k - 1] = b->v8q.a[k]; + ha_compress_qual_bit(Get_QUAL(R_INF, i), a, l, sc_bn); + } +} + +static void worker_hap_dc_ec_gen(void *data, long i, int tid) +{ + + ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); + uint32_t high_occ = asm_opt.hom_cov * (2.0 - HA_KMER_GOOD_RATIO); + uint32_t low_occ = asm_opt.hom_cov * HA_KMER_GOOD_RATIO; + + recover_UC_Read(&b->self_read, &R_INF, i); + + // overlap_region_sort_y_id(b->olist.list, b->olist.length); + // ma_hit_sort_tn(R_INF.paf[i].buffer, R_INF.paf[i].length); + // ma_hit_sort_tn(R_INF.reverse_paf[i].buffer, R_INF.reverse_paf[i].length); + + // R_INF.paf[i].is_fully_corrected = is_well_cal(&b->v64, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), b->self_read.length, 4); + + // R_INF.paf[i].is_abnormal = abnormal; + // R_INF.trio_flag[i] = AMBIGU; + + h_ec_lchain_fast(b->ab, i, &b->self_read, &b->ovlp_read, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, &b->exz, &b->v16, &b->v64, 0.02, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 0, 2, UINT32_MAX, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), 0.866666); + + push_ff_ovlp(&(R_INF.paf[i]), &b->olist, 1, &R_INF, b->cnt); + push_ff_ovlp(&(R_INF.reverse_paf[i]), &b->olist, 2, &R_INF, b->cnt); + + /** + copy_asg_arr(buf0, b->sp); + if(gen_hap_dc_cov(&(b->v64), &buf0, &(R_INF.paf[i]), &R_INF, WINDOW_HC_FAST, 4, 0.7, &b->self_read, &b->ovlp_read, &scc, i)) { + scc.f[i] = 1; b->num_read_base++; + // fprintf(stderr, "-mm-[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); + } else { + scc.f[i] = 0; b->num_correct_base++; + // fprintf(stderr, "-um-[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); + } + copy_asg_arr(b->sp, buf0); + **/ + refresh_ec_ovec_buf_t0(b, REFRESH_N); +} + +static void worker_hap_dc_ec_gen_new_idx(void *data, long i, int tid) +{ + + ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); + uint32_t high_occ = asm_opt.hom_cov * (2.0 - HA_KMER_GOOD_RATIO); + uint32_t low_occ = asm_opt.hom_cov * HA_KMER_GOOD_RATIO; uint32_t qlen = 0; + + recover_UC_Read(&b->self_read, &R_INF, i); qlen = b->self_read.length; + + h_ec_lchain(b->ab, i, b->self_read.seq, b->self_read.length, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, /**0.02**/0.001, asm_opt.max_n_chain, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 3, 0.7, 2, 32, COV_W, 0); + + overlap_region_sort_y_id(b->olist.list, b->olist.length); + + // overlap_region_sort_y_id(b->olist.list, b->olist.length); + // ma_hit_sort_tn(R_INF.paf[i].buffer, R_INF.paf[i].length); + // ma_hit_sort_tn(R_INF.reverse_paf[i].buffer, R_INF.reverse_paf[i].length); + + // R_INF.paf[i].is_fully_corrected = is_well_cal(&b->v64, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), b->self_read.length, 4); + + // R_INF.paf[i].is_abnormal = abnormal; + // R_INF.trio_flag[i] = AMBIGU; + + h_ec_lchain_fast_new(b->ab, i, &b->self_read, &b->ovlp_read, &R_INF, &b->olist, &b->clist, &b->exz, &b->v16, &b->v64, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), 0.866666); + + if((asm_opt.is_ont) && (is_uncorrected_read(&b->olist, &b->v64, qlen, 1600))) { + b->olist.length = 0; + // fprintf(stderr, "[M::%s] rid::%ld\t%.*s\n", __func__, i, (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); + } + + push_ff_ovlp(&(R_INF.paf[i]), &b->olist, 1, &R_INF, b->cnt); + push_ff_ovlp(&(R_INF.reverse_paf[i]), &b->olist, 2, &R_INF, b->cnt); + + /** + copy_asg_arr(buf0, b->sp); + if(gen_hap_dc_cov(&(b->v64), &buf0, &(R_INF.paf[i]), &R_INF, WINDOW_HC_FAST, 4, 0.7, &b->self_read, &b->ovlp_read, &scc, i)) { + scc.f[i] = 1; b->num_read_base++; + // fprintf(stderr, "-mm-[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); + } else { + scc.f[i] = 0; b->num_correct_base++; + // fprintf(stderr, "-um-[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); + } + copy_asg_arr(b->sp, buf0); + **/ + refresh_ec_ovec_buf_t0(b, REFRESH_N); +} + +uint32_t is_chemical_r(ma_hit_t_alloc *ov, asg64_v *idx, int64_t len, int64_t cov, int64_t frank_len) +{ + uint64_t k, s, e; int64_t dp, old_dp, st = 0, ed, s0, s1, e0, e1, rr; + if((frank_len) > (len *0.01)) frank_len = len *0.01; + for (k = idx->n = 0; k < ov->length; k++) { + s = (uint32_t)ov->buffer[k].qns; e = ov->buffer[k].qe; + kv_push(uint64_t, (*idx), (s<<1)); + kv_push(uint64_t, (*idx), (e<<1)|1); + } + + radix_sort_ec64(idx->a, idx->a + idx->n); s0 = s1 = e0 = e1 = rr = -1; + for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { + old_dp = dp; + ///if a[j] is qe + if (idx->a[k]&1) --dp; + else ++dp; + + ed = idx->a[k]>>1; + if(ed > st) { + if(old_dp <= cov) { + rr = 1; + } else { + if(s0 < 0) { + s0 = st; s1 = ed; + } + e0 = st; e1 = ed; + } + } + st = ed; + } + + + ed = len; old_dp = dp; + if(ed > st) { + if(old_dp <= cov) { + rr = 1; + } else { + if(s0 < 0) { + s0 = st; s1 = ed; + } + e0 = st; e1 = ed; + } + } + + + if((s0 != e0) && (s1 != e1) && (s0 <= frank_len) && ((len - e1) <= frank_len) && (rr > 0)) { + for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { + old_dp = dp; + ///if a[j] is qe + if (idx->a[k]&1) --dp; + else ++dp; + + ed = idx->a[k]>>1; + if(ed > st) { + if((old_dp <= cov) && (st >= s0) && (ed <= e1)) { + // if((ov->buffer[0].qns>>32) == 3364) fprintf(stderr, "[M::%s]\tlf::[%ld,%ld)\trt::[%ld,%ld)\tmd::[%ld,%ld)\tcov::%ld\n", __func__, s0, s1, e0, e1, st, ed, old_dp); + return 1; + } + } + st = ed; + } + + + ed = len; old_dp = dp; + if(ed > st) { + if((old_dp <= cov) && (st >= s0) && (ed <= e1)) { + // if((ov->buffer[0].qns>>32) == 3364) fprintf(stderr, "[M::%s]\tlf::[%ld,%ld)\trt::[%ld,%ld)\tmd::[%ld,%ld)\tcov::%ld\n", __func__, s0, s1, e0, e1, st, ed, old_dp); + return 1; + } + } + } + + return 0; +} + + +uint32_t is_chemical_r_adv(ma_hit_t_alloc *ov, asg64_v *idx, int64_t len, int64_t cov, int64_t cut_len, double dup_rate, uint64_t is_del) +{ + uint64_t k, s, e; int64_t dp, old_dp, st = 0, ed, s0, e0, rr, lt; + for (k = idx->n = 0; k < ov->length; k++) { + if(is_del && ov->buffer[k].del) continue; + s0 = (uint32_t)ov->buffer[k].qns; e0 = ov->buffer[k].qe; + if(s0 > 0) s0 += cut_len; + if(e0 < len) e0 -= cut_len; + if(e0 <= s0) continue; + s = s0; e = e0; + + lt = Get_READ_LENGTH((R_INF), ov->buffer[k].tn); + rr = (lt >= len)?(lt - len):(len - lt); + if((rr <= (len*dup_rate)) && (rr <= (lt*dup_rate)) && (ov->buffer[k].rev)) { + dp = (ov->buffer[k].qe) - ((uint32_t)ov->buffer[k].qns); dp = len - dp; + old_dp = ov->buffer[k].te - ov->buffer[k].ts; old_dp = lt - old_dp; + if((dp <= (len*dup_rate)) && (old_dp <= (lt*dup_rate))) continue; + } + + kv_push(uint64_t, (*idx), (s<<1)); + kv_push(uint64_t, (*idx), (e<<1)|1); + } + + radix_sort_ec64(idx->a, idx->a + idx->n); s0 = e0 = rr = -1; + for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { + old_dp = dp; + ///if a[j] is qe + if (idx->a[k]&1) --dp; + else ++dp; + + ed = idx->a[k]>>1; + if(ed > st) { + // if(ov->length && ((ov->buffer[0].qns>>32) == 5045637)) { + // fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\tid::%lu\n", __func__, st, ed, old_dp, len, ov->buffer[0].qns>>32); + // } + if(old_dp <= cov) { + // if(ov->length && (ov->buffer[0].qns>>32) == 22344) fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\n", __func__, st, ed, old_dp, len); + return 1; + } + } + st = ed; + } + + + ed = len; old_dp = dp; + if(ed > st) { + // if(ov->length && ((ov->buffer[0].qns>>32) == 5045637)) { + // fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\tid::%lu\n", __func__, st, ed, old_dp, len, ov->buffer[0].qns>>32); + // } + if(old_dp <= cov) { + // if(ov->length && (ov->buffer[0].qns>>32) == 22344) fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\n", __func__, st, ed, old_dp, len); + return 1; + } + } + + return 0; +} + +int64_t cal_chemical_r_adv(ma_hit_t_alloc *ov, asg64_v *idx, int64_t len, int64_t cut_len, double dup_rate, uint64_t is_del) +{ + uint64_t k, s, e; int64_t dp, old_dp, st = 0, ed, s0, e0, rr, lt, min_cov; + for (k = idx->n = 0; k < ov->length; k++) { + if(is_del && ov->buffer[k].del) continue; + s0 = (uint32_t)ov->buffer[k].qns; e0 = ov->buffer[k].qe; + if(s0 > 0) s0 += cut_len; + if(e0 < len) e0 -= cut_len; + if(e0 <= s0) continue; + s = s0; e = e0; + + lt = Get_READ_LENGTH((R_INF), ov->buffer[k].tn); + rr = (lt >= len)?(lt - len):(len - lt); + if((rr <= (len*dup_rate)) && (rr <= (lt*dup_rate)) && (ov->buffer[k].rev)) { + dp = (ov->buffer[k].qe) - ((uint32_t)ov->buffer[k].qns); dp = len - dp; + old_dp = ov->buffer[k].te - ov->buffer[k].ts; old_dp = lt - old_dp; + if((dp <= (len*dup_rate)) && (old_dp <= (lt*dup_rate))) continue; + } + + kv_push(uint64_t, (*idx), (s<<1)); + kv_push(uint64_t, (*idx), (e<<1)|1); + } + + radix_sort_ec64(idx->a, idx->a + idx->n); s0 = e0 = rr = -1; min_cov = INT64_MAX; + for (k = 0, dp = 0, st = ed = 0; k < idx->n; ++k) { + old_dp = dp; + ///if a[j] is qe + if (idx->a[k]&1) --dp; + else ++dp; + + ed = idx->a[k]>>1; + if(ed > st) { + // if(ov->length && ((ov->buffer[0].qns>>32) == 5045637)) { + // fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\tid::%lu\n", __func__, st, ed, old_dp, len, ov->buffer[0].qns>>32); + // } + if(old_dp <= min_cov) { + // if(ov->length && (ov->buffer[0].qns>>32) == 22344) fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\n", __func__, st, ed, old_dp, len); + min_cov = old_dp; + } + } + st = ed; + } + + + ed = len; old_dp = dp; + if(ed > st) { + // if(ov->length && ((ov->buffer[0].qns>>32) == 5045637)) { + // fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\tid::%lu\n", __func__, st, ed, old_dp, len, ov->buffer[0].qns>>32); + // } + if(old_dp <= min_cov) { + // if(ov->length && (ov->buffer[0].qns>>32) == 22344) fprintf(stderr, "[M::%s]\tmd::[%ld,%ld)\tcov::%ld\tlen::%ld\n", __func__, st, ed, old_dp, len); + min_cov = old_dp; + } + } + + return min_cov; +} + +void prt_dbg_rid_paf(ma_hit_t_alloc *ov, UC_Read *ra, asg8_v *qa) +{ + if(!(ov->length)) return; + uint64_t k, qn = (ov->buffer[0].qns>>32), qn_n, i, m; char *nn = NULL; FILE *fp = NULL; ma_hit_t *h = NULL; + qn_n = Get_NAME_LENGTH((R_INF), qn) + 64; MALLOC(nn, qn_n); + + sprintf(nn, "%.*s.qry.fq", (int)Get_NAME_LENGTH(R_INF, qn), Get_NAME((R_INF), qn)); fp = fopen(nn, "w"); + for (k = 0; k < ov->length; k++) { + i = ov->buffer[k].tn; + recover_UC_Read(ra, &R_INF, i); + fprintf(fp, "@%.*s\n", (int32_t)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); + fprintf(fp, "%.*s\n", (int32_t)ra->length, ra->seq); + fprintf(fp, "+\n"); + retrive_bqual(qa, NULL, i, -1, -1, 0, sc_bn); + for (m = 0; m < qa->n; m++) fprintf(fp, "%c", (char)(sc_tb[qa->a[m]] + 33 - 1)); + fprintf(fp, "\n"); + } + fclose(fp); + + sprintf(nn, "%.*s.ref.fq", (int)Get_NAME_LENGTH(R_INF, qn), Get_NAME((R_INF), qn)); fp = fopen(nn, "w"); + i = qn; + recover_UC_Read(ra, &R_INF, i); + fprintf(fp, "@%.*s\n", (int32_t)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); + fprintf(fp, "%.*s\n", (int32_t)ra->length, ra->seq); + fprintf(fp, "+\n"); + retrive_bqual(qa, NULL, i, -1, -1, 0, sc_bn); + for (m = 0; m < qa->n; m++) fprintf(fp, "%c", (char)(sc_tb[qa->a[m]] + 33 - 1)); + fprintf(fp, "\n"); + fclose(fp); + + sprintf(nn, "%.*s.ref.fa", (int)Get_NAME_LENGTH(R_INF, qn), Get_NAME((R_INF), qn)); fp = fopen(nn, "w"); + i = qn; + recover_UC_Read(ra, &R_INF, i); + fprintf(fp, ">%.*s\n", (int32_t)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i)); + fprintf(fp, "%.*s\n", (int32_t)ra->length, ra->seq); + // fprintf(fp, "+\n"); + // retrive_bqual(qa, NULL, i, -1, -1, 0, sc_bn); + // for (m = 0; m < qa->n; m++) fprintf(fp, "%c", (char)(sc_tb[qa->a[m]] + 33 - 1)); + // fprintf(fp, "\n"); + fclose(fp); + + sprintf(nn, "%.*s.ov.paf", (int)Get_NAME_LENGTH(R_INF, qn), Get_NAME((R_INF), qn)); fp = fopen(nn, "w"); + for (k = 0; k < ov->length; k++) { + h = &(ov->buffer[k]); + fprintf(fp, "%.*s(qn::%u)\t%u\t%u\t%u\t%c\t%.*s(tn::%u)\t%u\t%u\t%u\t%u\t%u\t255\n", (int)Get_NAME_LENGTH(R_INF, Get_qn(*h)), Get_NAME((R_INF), Get_qn(*h)), Get_qn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_qn(*h)), Get_qs(*h), Get_qe(*h), "+-"[h->rev], + (int)Get_NAME_LENGTH(R_INF, Get_tn(*h)), Get_NAME((R_INF), Get_tn(*h)), Get_tn(*h), (uint32_t)Get_READ_LENGTH(R_INF, Get_tn(*h)), Get_ts(*h), Get_te(*h), h->ml, h->bl); + } + fclose(fp); + + free(nn); +} + +static void worker_hap_dc_ec_chemical_r(void *data, long i, int tid) +{ + ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); + ma_hit_t_alloc *paf = &(R_INF.paf[i]); uint64_t k, m; + + // if (memcmp("3ed80bc4-1169-4948-a9ff-9c2463b7f7a2", Get_NAME((R_INF), i), Get_NAME_LENGTH((R_INF),i)) == 0) { + // fprintf(stderr, "-a-[M::%s-beg] rid->%ld, b->rr->%lu\n", __func__, i, b->rr); + // } + if(b->cnt[1] == 0) { + // if(i == 6204620) prt_dbg_rid_paf(&(R_INF.paf[i]), &(b->self_read), &(b->v8q)); + // if(is_chemical_r(&(R_INF.paf[i]), &b->v64, Get_READ_LENGTH((R_INF), i), 3, 16)) { + if(is_chemical_r_adv(&(R_INF.paf[i]), &b->v64, Get_READ_LENGTH((R_INF), i), asm_opt.chemical_cov, asm_opt.chemical_flank, 0.02, 0)) { + // fprintf(stderr, "-um-[M::%s]\tqn::%u::%.*s\n\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); + R_INF.paf[i].length = 0; b->cnt[0]++; + } + } else if(b->cnt[1] == 1) { + for (k = 0; k < paf->length; k++) { + if(R_INF.paf[paf->buffer[k].tn].length == 0) { + paf->buffer[k].tn = (uint32_t)-1; b->cnt[0]++; + } + } + } else { + for (k = m = 0; k < paf->length; k++) { + if(paf->buffer[k].tn == ((uint32_t)-1)) continue; + paf->buffer[m++] = paf->buffer[k]; + } + paf->length = m; + } + + refresh_ec_ovec_buf_t0(b, REFRESH_N); +} + +static void worker_hap_dc_ec_chemical_arc(void *data, long i, int tid) +{ + ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); + ma_hit_t_alloc *paf = &(R_INF.paf[i]), *rev; uint64_t k, z; + + if(b->cnt[1] == 0) { + if(is_chemical_r_adv(&(R_INF.paf[i]), &b->v64, Get_READ_LENGTH((R_INF), i), asm_opt.chemical_cov, asm_opt.chemical_flank, 0.02, 1)) { + // fprintf(stderr, "-um-[M::%s]\tqn::%u::%.*s\n\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); + for (k = 0; k < paf->length; k++) {paf->buffer[k].del = 1;} b->cnt[0]++; + } + } else if(b->cnt[1] == 1) { + for (k = 0; k < paf->length; k++) { + if((Get_qn(paf->buffer[k])) > (Get_tn(paf->buffer[k]))) continue; + rev = &(R_INF.paf[paf->buffer[k].tn]); + for (z = 0; z < rev->length; z++) { + if((rev->buffer[z].tn == (Get_qn(paf->buffer[k])))) { + if(paf->buffer[k].del != rev->buffer[z].del) { + paf->buffer[k].del = rev->buffer[z].del = 1; + } + } + } + } + } + + refresh_ec_ovec_buf_t0(b, REFRESH_N); +} + +static void worker_hap_dc_ec_chemical_arc_mark(void *data, long i, int tid) +{ + ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); + ma_hit_t_alloc *paf = &(R_INF.paf[i]), *rev; uint64_t k, z; int64_t cov, msk_cut = asm_opt.chemical_cov; + uint8_t *msk = ((ec_ovec_buf_t*)data)->cr; + + if(b->cnt[1] == 0) { + msk[i] = (uint8_t)-1; + cov = cal_chemical_r_adv(&(R_INF.paf[i]), &b->v64, Get_READ_LENGTH((R_INF), i), asm_opt.chemical_flank, 0.02, 1); + if(cov <= msk_cut) msk[i] = cov; + if(cov <= msk_cut/**FORCE_CUT**/) { + // fprintf(stderr, "-um-[M::%s]\tqn::%u::%.*s\n\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); + for (k = 0; k < paf->length; k++) {paf->buffer[k].del = 1;} b->cnt[0]++; + } + } else if(b->cnt[1] == 1) { + for (k = 0; k < paf->length; k++) { + if((Get_qn(paf->buffer[k])) > (Get_tn(paf->buffer[k]))) continue; + rev = &(R_INF.paf[paf->buffer[k].tn]); + for (z = 0; z < rev->length; z++) { + if((rev->buffer[z].tn == (Get_qn(paf->buffer[k])))) { + if((paf->buffer[k].del != rev->buffer[z].del) || (msk[Get_qn(paf->buffer[k])] <= msk_cut/**FORCE_CUT**/) || (msk[Get_tn(paf->buffer[k])] <= msk_cut/**FORCE_CUT**/)) { + paf->buffer[k].del = rev->buffer[z].del = 1; + } + } + } + } + } + + refresh_ec_ovec_buf_t0(b, REFRESH_N); +} + +uint64_t get_candidate_rrs(ma_utg_t *u, uint64_t rz) +{ + // uint64_t rid, rs, re, rev, k, l[2], lr, ts, te; + // ma_hit_t_alloc *z = NULL; + // ma_hit_t *h = NULL; + + // rid = u->a[rz]>>33; rev = (u->a[rz]>>32)&1; + // rs = 0; re = (uint32_t)u->a[rz]; + // if(!rev) { + // rs = Get_READ_LENGTH(R_INF, rid) - ((uint32_t)u->a[rz]); + // re = Get_READ_LENGTH(R_INF, rid); + // } + + // for (k = lr = 0; k < rz; k++) lr += (uint32_t)u->a[k]; + // ts = lr; te = lr + (uint32_t)u->a[k]; + + // z = &(sources[rid]); + // for (k = 0; k < z->length; k++) { + // h = &(z->buffer[k]); + // if ((Get_qs(*h) <= rs) && (Get_qe(*h) >= re)) { + // l[0] = l[1] = 0; + // if(!(h->rev&rev)) { + // l[0] = Get_ts(*h); l[1] = Get_READ_LENGTH(R_INF, Get_tn(*h)) - Get_te(*h); + // } else { + // l[1] = Get_ts(*h); l[0] = Get_READ_LENGTH(R_INF, Get_tn(*h)) - Get_te(*h); + // } + + // } + // } + + + return 1; +} + +static void worker_ec_polish(void *data, long i, int tid) +{ + ec_ovec_buf_t0 *b = &(((ec_polish_buf_t*)data)->p->a[tid]); + uint64_t *idx = &(((ec_polish_buf_t*)data)->idx.a[i]); + + if(get_candidate_rrs(&(((ec_polish_buf_t*)data)->ug->u.a[(*idx)>>32]), (uint32_t)(*idx))) { + *idx = (uint64_t)-1; + } + + refresh_ec_ovec_buf_t0(b, REFRESH_N); +} + +void gen_ovlst_paf(ma_hit_t_alloc *in_e, ma_hit_t_alloc *in_r, asg64_v *ou) +{ + uint32_t n = 0, k; + + for (k = 0; k < in_e->length; k++) { + if(!(in_e->buffer[k].el)) n++; + } + n += in_r->length; + + kv_resize(uint64_t, *ou, n); ou->n = 0; + + for (k = 0; k < in_e->length; k++) { + if(!(in_e->buffer[k].el)) { + ou->a[ou->n] = in_e->buffer[k].tn; + ou->a[ou->n] <<= 1; ou->a[ou->n] |= in_e->buffer[k].rev; + ou->n++; + } + } + + for (k = 0; k < in_r->length; k++) { + ou->a[ou->n] = in_r->buffer[k].tn; + ou->a[ou->n] <<= 1; ou->a[ou->n] |= in_r->buffer[k].rev; + ou->n++; + } + + radix_sort_ec64(ou->a, ou->a+ou->n); +} + +void dbg_overlap_region_cigar(overlap_region *a, uint64_t a_n, char *qstr, All_reads *rref, UC_Read *tu) +{ + bit_extz_t ez; uint64_t i, k; + for (i = 0; i < a_n; i++) { + if(a[i].y_pos_strand) { + recover_UC_Read_RC(tu, rref, a[i].y_id); + } else { + recover_UC_Read(tu, rref, a[i].y_id); + } + for (k = 0; k < a[i].w_list.n; k++) { + if(is_ualn_win((a[i].w_list.a[k]))) continue; + set_bit_extz_t(ez, a[i], k); + if(!cigar_check(tu->seq, qstr, &ez)) { + fprintf(stderr, "\n-0-[M::%s] x_id::%u, y_id::%u, x::[%u, %u), y::[%u, %u)\n", __func__, a[i].x_id, a[i].y_id, a[i].x_pos_s, a[i].x_pos_e + 1, a[i].y_pos_s, a[i].y_pos_e + 1); + exit(1); + } else { + // fprintf(stderr, "\n-1-[M::%s] x_id::%u, y_id::%u, x::[%u, %u), y::[%u, %u)\n", __func__, a[i].x_id, a[i].y_id, a[i].x_pos_s, a[i].x_pos_e + 1, a[i].y_pos_s, a[i].y_pos_e + 1); + } + } + } +} + +overlap_region* h_ec_lchain_re(ha_abuf_t *ab, uint32_t rid, char* rs, uint64_t rl, UC_Read *tu, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v* buf, double bw_thres, + int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1) +{ + // fprintf(stderr, "-mm-[M::%s]\tchain_cutoff::%u\n", __func__, chain_cutoff); + uint64_t on = 0, k, ol0, wl = (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), m; ma_hit_t *oa = NULL; overlap_region *z = NULL, *aux_o = NULL, t; Window_Pool w; double err = asm_opt.max_ov_diff_ec; + + int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; + set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); + + init_Window_Pool(&w, rl, wl, (int)(1.0/err)); + + on = in0->length + in1->length + 1; + clear_overlap_region_alloc(ol); + clear_Candidates_list(cl); + if(on > ol->size) { + REALLOC(ol->list, on); + memset(ol->list+ol->size, 0, sizeof(overlap_region)*(on-ol->size)); + ol->size = on; + } + on = in0->length + in1->length; aux_o = &(ol->list[on]); + ol->length = 0; ol->mapped_overlaps_length = 0; m = 0; + + + // get the list of anchors + get_mz1(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), ab, ha_flt_tab, ha_idx, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL, 0); + + oa = in0->buffer; on = in0->length; + for (k = 0; k < on; k++) { + ol0 = ol->length; + if(oa[k].el) { + z = &(ol->list[ol->length++]); + z->x_id = rid; z->y_id = oa[k].tn; + z->x_pos_strand = 0; z->y_pos_strand = oa[k].rev; + z->x_pos_s = (uint32_t)oa[k].qns; + z->x_pos_e = oa[k].qe - 1; + z->y_pos_s = oa[k].ts; + z->y_pos_e = oa[k].te - 1; + + z->is_match = 1; + z->align_length = z->overlapLen = z->shared_seed = z->x_pos_e + 1 - z->x_pos_s; + z->non_homopolymer_errors = z->strong = 0; + + set_exact_exz(exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, exz); + + // if(oa[k].tn == 15382) fprintf(stderr, "-em-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); + } else { + if(oa[k].rev) recover_UC_Read_RC(tu, rref, oa[k].tn); + else recover_UC_Read(tu, rref, oa[k].tn); + + get_pi_ec_chain(ab, rid, rl, oa[k].tn, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); + assert(ol->length - ol0 <= 1); + if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { + ol->list[ol0].y_pos_strand = oa[k].rev; + // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); + } + } + + if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; + + if(m != ol0) { + t = ol->list[m]; + ol->list[m] = ol->list[ol0]; + ol->list[ol0] = t; + } + + m++; + } + + + oa = in1->buffer; on = in1->length; + for (k = 0; k < on; k++) { + ol0 = ol->length; + + if(oa[k].rev) recover_UC_Read_RC(tu, rref, oa[k].tn); + else recover_UC_Read(tu, rref, oa[k].tn); + + get_pi_ec_chain(ab, rid, rl, oa[k].tn, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); + assert(ol->length - ol0 <= 1); + if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { + ol->list[ol0].y_pos_strand = oa[k].rev; + // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); + } + + if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; + + if(m != ol0) { + t = ol->list[m]; + ol->list[m] = ol->list[ol0]; + ol->list[ol0] = t; + } + + m++; + } + + ol->length = m; + + // fprintf(stderr, "[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); + assert(ol->length <= (in0->length + in1->length)); + + + // dbg_overlap_region_cigar(ol->list, ol->length, rs, rref, tu); + + + return aux_o; +} + + +overlap_region* h_ec_lchain_re1(ha_abuf_t *ab, uint32_t rid, UC_Read *qu, UC_Read *tu, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v *buf, asg64_v *srt_i, double bw_thres, + int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1) +{ + // fprintf(stderr, "-mm-[M::%s]\tchain_cutoff::%u\n", __func__, chain_cutoff); + uint64_t on = 0, k, one = 0, ol0, wl = (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), m, m0, tid, trev; ma_hit_t *oa = NULL, *p = NULL; overlap_region *aux_o = NULL, *z = NULL, t; Window_Pool w; double err = asm_opt.max_ov_diff_ec; + char* rs = qu->seq; uint64_t rl = qu->length; + int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; + set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); + init_Window_Pool(&w, rl, wl, (int)(1.0/err)); + + srt_i->n = 0; + oa = in0->buffer; on = in0->length; m0 = 0; + for (k = 0; k < on; k++) { + if(oa[k].el) { + one++; continue; + } + m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; + kv_push(uint64_t, *srt_i, m); + } + oa = in1->buffer; on = in1->length; m0 = 1; + for (k = 0; k < on; k++) { + // if(oa[k].el) continue; + m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; + kv_push(uint64_t, *srt_i, m); + } + radix_sort_ec64(srt_i->a, srt_i->a + srt_i->n); + + // get the list of anchors + get_mz1(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), ab, ha_flt_tab, NULL/**ha_idx**/, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL, 0); + + h_ec_lchain_re_gen(ab, rid, rs, rl, mz_w, mz_k, ha_idx, rref, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, + max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip, tu, srt_i, scb.a); + + + ///max size + on = ol->length + one + srt_i->n + 1; m0 = on - 1; + if(on > ol->size) { + REALLOC(ol->list, on); + memset(ol->list+ol->size, 0, sizeof(overlap_region)*(on-ol->size)); + ol->size = on; + } + aux_o = &(ol->list[on-1]); ol->mapped_overlaps_length = 0; on = ol->length; + + // fprintf(stderr, "-0-[M::%s]\n", __func__); + + gen_hc_r_alin(ol, cl, rref, qu, tu, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf, 0, -1, -1, 0, 0, -1, -1, NULL, NULL); rs = qu->seq; + + // fprintf(stderr, "-1-[M::%s]\n", __func__); + + ///handle unmatched chain + for (k = m = ol->length; k < on; k++) { + clear_fake_cigar(&(ol->list[k].f_cigar)); + clear_window_list_alloc(&(ol->list[k].w_list)); + clear_window_list_alloc(&(ol->list[k].boundary_cigars)); + + ol0 = ol->length; + + tid = ol->list[k].y_id; trev = ol->list[k].y_pos_strand; + if(trev) recover_UC_Read_RC(tu, rref, tid); + else recover_UC_Read(tu, rref, tid); + + get_pi_ec_chain(ab, rid, rl, tid, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); + assert(ol->length - ol0 <= 1); + if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { + ol->list[ol0].y_pos_strand = trev; + // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); + } + + if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; + + if(m != ol0) { + t = ol->list[m]; + ol->list[m] = ol->list[ol0]; + ol->list[ol0] = t; + } + + m++; + } + ol->length = m; + + for (k = ol->length; k < on; k++) { + clear_fake_cigar(&(ol->list[k].f_cigar)); + clear_window_list_alloc(&(ol->list[k].w_list)); + clear_window_list_alloc(&(ol->list[k].boundary_cigars)); + } + + // fprintf(stderr, "[M::%s]\tnew::%lu\told::%lu\n", __func__, ol->length, ol0); + + oa = in0->buffer; on = in0->length; + for (k = 0; k < on; k++) { + if(oa[k].el) { + z = &(ol->list[ol->length++]); + z->x_id = rid; z->y_id = oa[k].tn; + z->x_pos_strand = 0; z->y_pos_strand = oa[k].rev; + z->x_pos_s = (uint32_t)oa[k].qns; + z->x_pos_e = oa[k].qe - 1; + z->y_pos_s = oa[k].ts; + z->y_pos_e = oa[k].te - 1; + + z->is_match = 1; + z->align_length = z->overlapLen = z->shared_seed = z->x_pos_e + 1 - z->x_pos_s; + z->non_homopolymer_errors = z->strong = 0; + + set_exact_exz(exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, exz); + + // if(oa[k].tn == 1945) fprintf(stderr, "-em-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); + } + } + m = ol->length; + + for (k = 0; k < srt_i->n; k++) { + ol0 = ol->length; + if(srt_i->a[k]&1) { + p = &(in1->buffer[((uint32_t)srt_i->a[k])>>1]); + } else { + p = &(in0->buffer[((uint32_t)srt_i->a[k])>>1]); + } + + if(p->rev) recover_UC_Read_RC(tu, rref, p->tn); + else recover_UC_Read(tu, rref, p->tn); + + get_pi_ec_chain(ab, rid, rl, p->tn, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); + assert(ol->length - ol0 <= 1); + if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { + ol->list[ol0].y_pos_strand = p->rev; + // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); + } + + if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; + + if(m != ol0) { + t = ol->list[m]; + ol->list[m] = ol->list[ol0]; + ol->list[ol0] = t; + } + + m++; + } + + ol->length = m; + + + // fprintf(stderr, "[M::%s]\tnew_n::%lu\told_n::%lu\n", __func__, ol->length, m0); + // fprintf(stderr, "[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); + // assert(ol->length <= (in0->length + in1->length)); + + + // dbg_overlap_region_cigar(ol->list, ol->length, rs, rref, tu); + + return aux_o; +} + +uint64_t direct_chain_cal(ha_abuf_t *ab, uint64_t qid, char *qs, uint64_t ql, uint64_t tid, char *ts, uint64_t tl, uint64_t trev, uint64_t mz_w, uint64_t mz_k, overlap_region_alloc *olst, Candidates_list *cl, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, double bw_thres, + int apend_be, uint64_t max_cnt, uint64_t min_cnt, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t quick_check, double chn_pen_gap, double chn_pen_skip, + bit_extz_t *exz, overlap_region *aux_o, double e_rate, int64_t wl, int64_t khit, int64_t move_gap, asg16_v* buf) +{ + uint64_t ol0 = olst->length; + get_pi_ec_chain(ab, qid, ql, tid, ts, tl, mz_w, mz_k, olst, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); + assert(olst->length - ol0 <= 1); + if(olst->length > ol0) { + if(gen_hc_r_alin_re(&(olst->list[ol0]), cl, qs, ql, ts, tl, exz, aux_o, e_rate, wl, qid, E_KHIT, 1, buf)) { + olst->list[ol0].y_pos_strand = trev; + return 1; + } else { + clear_fake_cigar(&(olst->list[ol0].f_cigar)); + clear_window_list_alloc(&(olst->list[ol0].w_list)); + clear_window_list_alloc(&(olst->list[ol0].boundary_cigars)); + olst->length--; + } + } + return 0; +} + + +overlap_region* h_ec_lchain_re2(ha_abuf_t *ab, uint32_t rid, UC_Read *qu, UC_Read *tu, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v *buf, asg64_v *srt_i, double bw_thres, + int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1) +{ + // fprintf(stderr, "-0-[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); + // fprintf(stderr, "-mm-[M::%s]\tchain_cutoff::%u\n", __func__, chain_cutoff); + uint64_t on = 0, k, l, i, one = 0, ol0, wl = (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), m, m0, tid, trev, max_cnt = UINT32_MAX, min_cnt = 0; ma_hit_t *oa = NULL, *p = NULL; overlap_region *aux_o = NULL, *z = NULL, t; Window_Pool w; double err = asm_opt.max_ov_diff_ec; tiny_queue_t tq; memset(&tq, 0, sizeof(tiny_queue_t)); + char* rs = qu->seq; uint64_t rl = qu->length; int64_t n, zn, om; + int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; + set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); + init_Window_Pool(&w, rl, wl, (int)(1.0/err)); + + ///cutoff + if(high_occ) { + max_cnt = (*high_occ); + if(max_cnt < 2) max_cnt = 2; + } + if(low_occ) { + min_cnt = (*low_occ); + if(min_cnt < 2) min_cnt = 2; + } + + ///memory + ol->length = 0; on = in0->length + in1->length + 1; + if(on > ol->size) { + REALLOC(ol->list, on); + memset(ol->list+ol->size, 0, sizeof(overlap_region)*(on-ol->size)); + ol->size = on; + } + aux_o = &(ol->list[on-1]); ol->mapped_overlaps_length = 0; on = in0->length + in1->length; + + ///overlap idx + srt_i->n = 0; + oa = in0->buffer; on = in0->length; m0 = 0; + for (k = 0; k < on; k++) { + if(oa[k].el) { + one++; continue; + } + m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; + kv_push(uint64_t, *srt_i, m); + } + oa = in1->buffer; on = in1->length; m0 = 1; + for (k = 0; k < on; k++) { + // if(oa[k].el) continue; + m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; + kv_push(uint64_t, *srt_i, m); + } + radix_sort_ec64(srt_i->a, srt_i->a + srt_i->n); + + // get the list of anchors + get_mz1(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), ab, ha_flt_tab, NULL/**ha_idx**/, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL, 0); + + h_ec_lchain_re_gen_srt(ab, ha_idx, ol, cl); + + k = 1; l = 0; i = 0; n = zn = 0; + while(h_ec_lchain_re_gen_qry(ab, &k, &l, &i, srt_i->a, srt_i->n, &tid, &trev)) { + + if(trev) recover_UC_Read_RC(tu, rref, tid); + else recover_UC_Read(tu, rref, tid); + + ol0 = ol->length; om = 0; + if(h_ec_lchain_re_chn(ab, l, k, rid, rs, rl, tid, tu->seq, tu->length, trev, mz_w, mz_k, ol, cl, bw_thres, apend_be, max_cnt, min_cnt, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip, &tq, scb.a, &n, &zn)) { + assert(ol->length - ol0 == 1); + ol->list[ol0].y_pos_strand = 0; + if(gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf)) { + ol->list[ol0].y_pos_strand = trev; om = 1; + } else {///unmatch + clear_fake_cigar(&(ol->list[ol0].f_cigar)); + clear_window_list_alloc(&(ol->list[ol0].w_list)); + clear_window_list_alloc(&(ol->list[ol0].boundary_cigars)); + ol->length--; + } + } + + if(om) { + srt_i->a[i] >>= 32; srt_i->a[i] <<= 32; srt_i->a[i] |= ((uint64_t)((uint32_t)-1)); + } + + l = k; k++; + } + + for (k = m = 0; k < srt_i->n; k++) { + if(((uint32_t)srt_i->a[k]) == ((uint32_t)-1)) continue; + srt_i->a[m++] = srt_i->a[k]; + } + // fprintf(stderr, "[M::%s]\ttot::%lu\tremain::%lu\n", __func__, (uint64_t)srt_i->n, m); + srt_i->n = m; + + + + oa = in0->buffer; on = in0->length; + for (k = 0; k < on; k++) { + if(oa[k].el) { + z = &(ol->list[ol->length++]); + z->x_id = rid; z->y_id = oa[k].tn; + z->x_pos_strand = 0; z->y_pos_strand = oa[k].rev; + z->x_pos_s = (uint32_t)oa[k].qns; + z->x_pos_e = oa[k].qe - 1; + z->y_pos_s = oa[k].ts; + z->y_pos_e = oa[k].te - 1; + + z->is_match = 1; + z->align_length = z->overlapLen = z->shared_seed = z->x_pos_e + 1 - z->x_pos_s; + z->non_homopolymer_errors = z->strong = 0; + + set_exact_exz(exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, exz); + + // if(oa[k].tn == 1945) fprintf(stderr, "-em-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); + } + } + m = ol->length; + + + clear_Candidates_list(cl); + for (k = 0; k < srt_i->n; k++) { + ol0 = ol->length; + if(srt_i->a[k]&1) { + p = &(in1->buffer[((uint32_t)srt_i->a[k])>>1]); + } else { + p = &(in0->buffer[((uint32_t)srt_i->a[k])>>1]); + } + + if(p->rev) recover_UC_Read_RC(tu, rref, p->tn); + else recover_UC_Read(tu, rref, p->tn); + + get_pi_ec_chain(ab, rid, rl, p->tn, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); + assert(ol->length - ol0 <= 1); + if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { + ol->list[ol0].y_pos_strand = p->rev; + // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); + } + + if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; + + if(m != ol0) { + t = ol->list[m]; + ol->list[m] = ol->list[ol0]; + ol->list[ol0] = t; + } + + m++; + } + + ol->length = m; + + // fprintf(stderr, "[M::%s]\tnew_n::%lu\told_n::%lu\n", __func__, ol->length, m0); + // fprintf(stderr, "-1-[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); + assert(ol->length <= (in0->length + in1->length)); + + + // dbg_overlap_region_cigar(ol->list, ol->length, rs, rref, tu); + + return aux_o; +} + + +overlap_region* h_ec_lchain_fast(ha_abuf_t *ab, uint32_t rid, UC_Read *qu, UC_Read *tu, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v *buf, asg64_v *srt_i, double bw_thres, + int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1, double sh) +{ + // fprintf(stderr, "-0-[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); + // fprintf(stderr, "-mm-[M::%s]\tchain_cutoff::%u\n", __func__, chain_cutoff); + uint64_t on = 0, k, l, i, one = 0, ol0, wl = (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), m, m0, tid, trev, max_cnt = UINT32_MAX, min_cnt = 0, is_match; ma_hit_t *oa = NULL, *p = NULL; overlap_region *aux_o = NULL, *z = NULL; Window_Pool w; double err = asm_opt.max_ov_diff_ec; tiny_queue_t tq; memset(&tq, 0, sizeof(tiny_queue_t)); + char* rs = qu->seq; uint64_t rl = qu->length; int64_t n, zn, om; uint64_t aq[2], at[2], bq[2], bt[2], ovlp, os, oe; + int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; + set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); + init_Window_Pool(&w, rl, wl, (int)(1.0/err)); + + ///cutoff + if(high_occ) { + max_cnt = (*high_occ); + if(max_cnt < 2) max_cnt = 2; + } + if(low_occ) { + min_cnt = (*low_occ); + if(min_cnt < 2) min_cnt = 2; + } + + ///memory + ol->length = 0; on = in0->length + in1->length + 1; + if(on > ol->size) { + REALLOC(ol->list, on); + memset(ol->list+ol->size, 0, sizeof(overlap_region)*(on-ol->size)); + ol->size = on; + } + aux_o = &(ol->list[on-1]); ol->mapped_overlaps_length = 0; on = in0->length + in1->length; + + ///overlap idx + srt_i->n = 0; + oa = in0->buffer; on = in0->length; m0 = 0; + for (k = 0; k < on; k++) { + if(oa[k].el) { + one++; continue; + } + m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; + kv_push(uint64_t, *srt_i, m); + } + oa = in1->buffer; on = in1->length; m0 = 1; + for (k = 0; k < on; k++) { + // if(oa[k].el) continue; + m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; + kv_push(uint64_t, *srt_i, m); + } + radix_sort_ec64(srt_i->a, srt_i->a + srt_i->n); + + // get the list of anchors + get_mz1(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), ab, ha_flt_tab, NULL/**ha_idx**/, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL, 0); + + h_ec_lchain_re_gen_srt(ab, ha_idx, ol, cl); + + k = 1; l = 0; i = 0; n = zn = 0; + while(h_ec_lchain_re_gen_qry(ab, &k, &l, &i, srt_i->a, srt_i->n, &tid, &trev)) { + + if(trev) recover_UC_Read_RC(tu, rref, tid); + else recover_UC_Read(tu, rref, tid); + + ol0 = ol->length; om = 0; + if(h_ec_lchain_re_chn(ab, l, k, rid, rs, rl, tid, tu->seq, tu->length, trev, mz_w, mz_k, ol, cl, bw_thres, apend_be, max_cnt, min_cnt, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip, &tq, scb.a, &n, &zn)) { + assert(ol->length - ol0 == 1); + ol->list[ol0].y_pos_strand = trev; om = 1; ol->list[ol0].shared_seed = 0; ol->list[ol0].is_match = 0; + + assert(((srt_i->a[i]>>33) == ol->list[ol0].y_id) && (((srt_i->a[i]>>32)&1) == ol->list[ol0].y_pos_strand)); + if(srt_i->a[i]&1) { + p = &(in1->buffer[((uint32_t)srt_i->a[i])>>1]); is_match = 2; + } else { + p = &(in0->buffer[((uint32_t)srt_i->a[i])>>1]); is_match = 1; + } + ol->list[ol0].strong = p->ml; ol->list[ol0].without_large_indel = p->no_l_indel; + + aq[0] = (uint32_t)p->qns; aq[1] = p->qe; + at[0] = p->ts; at[1] = p->te; + + bq[0] = ol->list[ol0].x_pos_s; bq[1] = ol->list[ol0].x_pos_e + 1; + bt[0] = ol->list[ol0].y_pos_s; bt[1] = ol->list[ol0].y_pos_e + 1; + + os = MAX(aq[0], bq[0]); oe = MIN(aq[1], bq[1]); + ovlp = ((oe>os)? (oe-os):0); + if(!((ovlp) && (ovlp >= ((aq[1] - aq[0])*sh)) && ((ovlp >= ((bq[1] - bq[0])*sh))))) om = 0; + + os = MAX(at[0], bt[0]); oe = MIN(at[1], bt[1]); + ovlp = ((oe>os)? (oe-os):0); + if(!((ovlp) && (ovlp >= ((at[1] - at[0])*sh)) && ((ovlp >= ((bt[1] - bt[0])*sh))))) om = 0; + + if(om) { + if(exact_ec_check(rs, rl, tu->seq, tu->length, bq[0], bq[1], bt[0], bt[1])) { + if(is_match == 2) { + ol->list[ol0].strong = 0; ol->list[ol0].without_large_indel = 1; + } + is_match = 1; ol->list[ol0].shared_seed = 1; + } + ol->list[ol0].is_match = is_match; + } else {///unmatch + clear_fake_cigar(&(ol->list[ol0].f_cigar)); + clear_window_list_alloc(&(ol->list[ol0].w_list)); + clear_window_list_alloc(&(ol->list[ol0].boundary_cigars)); + ol->length--; + } + } + + if(om) { + srt_i->a[i] >>= 32; srt_i->a[i] <<= 32; srt_i->a[i] |= ((uint64_t)((uint32_t)-1)); + } + + l = k; k++; + } + + for (k = m = 0; k < srt_i->n; k++) { + if(((uint32_t)srt_i->a[k]) == ((uint32_t)-1)) continue; + srt_i->a[m++] = srt_i->a[k]; + } + // fprintf(stderr, "[M::%s]\ttot::%lu\tremain::%lu\n", __func__, (uint64_t)srt_i->n, m); + srt_i->n = m; + + + + oa = in0->buffer; on = in0->length; + for (k = 0; k < on; k++) { + if(oa[k].el) { + z = &(ol->list[ol->length++]); + z->x_id = rid; z->y_id = oa[k].tn; + z->x_pos_strand = 0; z->y_pos_strand = oa[k].rev; + z->x_pos_s = (uint32_t)oa[k].qns; + z->x_pos_e = oa[k].qe - 1; + z->y_pos_s = oa[k].ts; + z->y_pos_e = oa[k].te - 1; + + z->align_length = z->overlapLen = z->x_pos_e + 1 - z->x_pos_s; + z->non_homopolymer_errors = 0; + + z->is_match = 1; z->shared_seed = 1; + z->strong = oa[k].ml; z->without_large_indel = oa[k].no_l_indel; + + set_exact_exz(exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, exz); + + // if(oa[k].tn == 1945) fprintf(stderr, "-em-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); + } + } + /** + m = ol->length; + + + clear_Candidates_list(cl); + for (k = 0; k < srt_i->n; k++) { + ol0 = ol->length; + if(srt_i->a[k]&1) { + p = &(in1->buffer[((uint32_t)srt_i->a[k])>>1]); + } else { + p = &(in0->buffer[((uint32_t)srt_i->a[k])>>1]); + } + + if(p->rev) recover_UC_Read_RC(tu, rref, p->tn); + else recover_UC_Read(tu, rref, p->tn); + + get_pi_ec_chain(ab, rid, rl, p->tn, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); + assert(ol->length - ol0 <= 1); + if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { + ol->list[ol0].y_pos_strand = p->rev; + // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); + } + + if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; + + if(m != ol0) { + t = ol->list[m]; + ol->list[m] = ol->list[ol0]; + ol->list[ol0] = t; + } + + m++; + } + + ol->length = m; + **/ + + // fprintf(stderr, "[M::%s]\tnew_n::%lu\told_n::%lu\n", __func__, ol->length, m0); + // fprintf(stderr, "-1-[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); + assert(ol->length <= (in0->length + in1->length)); + + + // dbg_overlap_region_cigar(ol->list, ol->length, rs, rref, tu); + + return aux_o; +} + +void h_ec_lchain_fast_new(ha_abuf_t *ab, uint32_t rid, UC_Read *qu, UC_Read *tu, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v *buf, asg64_v *srt_i, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1, double sh) +{ + // fprintf(stderr, "-0-[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); + // fprintf(stderr, "-mm-[M::%s]\tchain_cutoff::%u\n", __func__, chain_cutoff); + uint64_t on = 0, k, i, l, m, m0, tid, trev, is_match, is_usrt = 0; ma_hit_t *oa = NULL, *p = NULL; overlap_region *z = NULL, t; + char* rs = qu->seq; uint64_t rl = qu->length; int64_t om; uint64_t aq[2], at[2], bq[2], bt[2], ovlp, os, oe; + + + + ///overlap idx + srt_i->n = 0; + oa = in0->buffer; on = in0->length; m0 = 0; + for (k = 0; k < on; k++) { + // if(oa[k].el) continue; + m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; + kv_push(uint64_t, *srt_i, m); + } + oa = in1->buffer; on = in1->length; m0 = 1; + for (k = 0; k < on; k++) { + // if(oa[k].el) continue; + m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; + kv_push(uint64_t, *srt_i, m); + } + radix_sort_ec64(srt_i->a, srt_i->a + srt_i->n); + + k = 0; i = 0; + for (k = m = 0; k < ol->length; k++) { + z = &(ol->list[k]); tid = z->y_id; trev = z->y_pos_strand; + z->non_homopolymer_errors = 0; + for (; (i < srt_i->n) && ((srt_i->a[i]>>32) < ((tid<<1)|trev)); i++); + if((i < srt_i->n) && ((srt_i->a[i]>>32) == ((tid<<1)|trev))) { + om = 1; z->shared_seed = 0; z->is_match = 0; + if(srt_i->a[i]&1) { + p = &(in1->buffer[((uint32_t)srt_i->a[i])>>1]); is_match = 2; + } else { + p = &(in0->buffer[((uint32_t)srt_i->a[i])>>1]); is_match = 1; + } + z->strong = p->ml; z->without_large_indel = p->no_l_indel; + + aq[0] = (uint32_t)p->qns; aq[1] = p->qe; + at[0] = p->ts; at[1] = p->te; + + bq[0] = z->x_pos_s; bq[1] = z->x_pos_e + 1; + bt[0] = z->y_pos_s; bt[1] = z->y_pos_e + 1; + + os = MAX(aq[0], bq[0]); oe = MIN(aq[1], bq[1]); + ovlp = ((oe>os)? (oe-os):0); + if(!((ovlp) && (ovlp >= ((aq[1] - aq[0])*sh)) && ((ovlp >= ((bq[1] - bq[0])*sh))))) om = 0; + z->non_homopolymer_errors += ((aq[1] - aq[0]) - ovlp); + + os = MAX(at[0], bt[0]); oe = MIN(at[1], bt[1]); + ovlp = ((oe>os)? (oe-os):0); + if(!((ovlp) && (ovlp >= ((at[1] - at[0])*sh)) && ((ovlp >= ((bt[1] - bt[0])*sh))))) om = 0; + z->non_homopolymer_errors += ((at[1] - at[0]) - ovlp); + + if(om) { + if(is_match == 1 && p->el == 1) p->el = 0; + resize_UC_Read(tu, bt[1] - bt[0]); + recover_UC_Read_sub_region(tu->seq, bt[0], bt[1] - bt[0], trev, rref, tid); + if(exact_ec_check(rs, rl, tu->seq, bt[1] - bt[0], bq[0], bq[1], 0, bt[1] - bt[0])) { + if(is_match == 2) { + z->strong = 0; z->without_large_indel = 1; + } + is_match = 1; z->shared_seed = 1; + } + z->is_match = is_match; + } + } else { + om = 0; + bq[0] = z->x_pos_s; bq[1] = z->x_pos_e + 1; + bt[0] = z->y_pos_s; bt[1] = z->y_pos_e + 1; + resize_UC_Read(tu, bt[1] - bt[0]); + recover_UC_Read_sub_region(tu->seq, bt[0], bt[1] - bt[0], trev, rref, tid); + if(exact_ec_check(rs, rl, tu->seq, bt[1] - bt[0], bq[0], bq[1], 0, bt[1] - bt[0])) { + z->strong = 0; z->without_large_indel = 1; + z->shared_seed = 1; z->is_match = 1; om = 1; + } + } + + if(om) { + if(m != k) { + t = ol->list[m]; + ol->list[m] = ol->list[k]; + ol->list[k] = t; + } + m++; + } + } + ol->length = m; + + + oa = in0->buffer; on = in0->length; + for (k = 0; k < on; k++) { + if(oa[k].el) { + // z = &(ol->list[ol->length++]); + kv_pushp_ol(overlap_region, (*ol), &z); + clear_fake_cigar(&(z->f_cigar)); + clear_window_list_alloc(&(z->w_list)); + clear_window_list_alloc(&(z->boundary_cigars)); + + z->x_id = rid; z->y_id = oa[k].tn; + z->x_pos_strand = 0; z->y_pos_strand = oa[k].rev; + z->x_pos_s = (uint32_t)oa[k].qns; + z->x_pos_e = oa[k].qe - 1; + z->y_pos_s = oa[k].ts; + z->y_pos_e = oa[k].te - 1; + + z->align_length = z->overlapLen = z->x_pos_e + 1 - z->x_pos_s; + z->non_homopolymer_errors = 0; + + z->is_match = 1; z->shared_seed = 1; + z->strong = oa[k].ml; z->without_large_indel = oa[k].no_l_indel; + + set_exact_exz(exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, exz); + + is_usrt = 1; + // if(oa[k].tn == 1945) fprintf(stderr, "-em-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); + } + } + + if(is_usrt) overlap_region_sort_y_id(ol->list, ol->length); + + if(ol->length > 1) {///for duplicated chains + uint64_t mm_k, s; int64_t mm_sc, sc; + for (k = 1, l = m = 0; k <= ol->length; k++) { + if(k == ol->length || ol->list[k].y_id != ol->list[l].y_id) { + mm_k = l; + if(k - l > 1) { + for (s = l, mm_sc = INT32_MIN, mm_k = ((uint64_t)-1); s < k; s++) { + z = &(ol->list[s]); + sc = z->non_homopolymer_errors; sc = - sc; + if((sc > mm_sc) || ((sc == mm_sc) && ((ol->list[mm_k].x_pos_e+1-ol->list[mm_k].x_pos_s) < (z->x_pos_e+1-z->x_pos_s)))) { + mm_sc = sc; mm_k = s; + } + } + } + if(mm_k != ((uint64_t)-1)) { + if(mm_k != m) { + t = ol->list[mm_k]; + ol->list[mm_k] = ol->list[m]; + ol->list[m] = t; + } + m++; + } + l = k; + } + } + ol->length = m; + } +} + +overlap_region* h_ec_lchain_re3(ha_abuf_t *ab, uint32_t rid, UC_Read *qu, UC_Read *tu, uint64_t mz_w, uint64_t mz_k, All_reads *rref, overlap_region_alloc *ol, Candidates_list *cl, bit_extz_t *exz, asg16_v *buf, asg64_v *srt_i, double bw_thres, + int apend_be, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, int64_t enable_mcopy, double mcopy_rate, uint32_t mcopy_khit_cut, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1) +{ + // fprintf(stderr, "-mm-[M::%s]\tchain_cutoff::%u\n", __func__, chain_cutoff); + uint64_t on = 0, k, one = 0, ol0, wl = (asm_opt.is_ont)?(WINDOW_OHC):(WINDOW_HC), m, m0, tid, trev; ma_hit_t *oa = NULL, *p = NULL; overlap_region *aux_o = NULL, *z = NULL, t; Window_Pool w; double err = asm_opt.max_ov_diff_ec; + char* rs = qu->seq; uint64_t rl = qu->length; + int64_t max_skip, max_iter, max_dis, quick_check; double chn_pen_gap, chn_pen_skip; + set_lchain_dp_op(is_accurate, mz_k, &max_skip, &max_iter, &max_dis, &chn_pen_gap, &chn_pen_skip, &quick_check); + init_Window_Pool(&w, rl, wl, (int)(1.0/err)); + + srt_i->n = 0; + oa = in0->buffer; on = in0->length; m0 = 0; + for (k = 0; k < on; k++) { + m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; + if(oa[k].el) { + one++; m |= ((uint32_t)-1); + } else { + m |= (k<<1); m |= m0; + } + kv_push(uint64_t, *srt_i, m); + } + oa = in1->buffer; on = in1->length; m0 = 1; + for (k = 0; k < on; k++) { + // if(oa[k].el) continue; + m = oa[k].tn; m <<= 1; m |= ((uint64_t)oa[k].rev); m <<= 32; m |= (k<<1); m |= m0; + kv_push(uint64_t, *srt_i, m); + } + radix_sort_ec64(srt_i->a, srt_i->a + srt_i->n); + + // get the list of anchors + get_mz1(rs, rl, mz_w, mz_k, 0, !(asm_opt.flag & HA_F_NO_HPC), ab, ha_flt_tab, NULL/**ha_idx**/, asm_opt.mz_sample_dist, k_flag, dbg_ct, NULL, -1, asm_opt.dp_min_len, -1, sp, asm_opt.mz_rewin, 0, NULL, 0); + + h_ec_lchain_re_gen3(ab, rid, rs, rl, mz_w, mz_k, ha_idx, rref, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, + max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip, tu, srt_i, scb.a); + + + ///max size + on = ol->length + one + srt_i->n + 1; m0 = on - 1; + if(on > ol->size) { + REALLOC(ol->list, on); + memset(ol->list+ol->size, 0, sizeof(overlap_region)*(on-ol->size)); + ol->size = on; + } + aux_o = &(ol->list[on-1]); ol->mapped_overlaps_length = 0; on = ol->length; + + // fprintf(stderr, "-0-[M::%s]\n", __func__); + + gen_hc_r_alin(ol, cl, rref, qu, tu, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf, 0, -1, -1, 0, 0, -1, -1, NULL, NULL); rs = qu->seq; + + // fprintf(stderr, "-1-[M::%s]\n", __func__); + + ///handle unmatched chain + for (k = m = ol->length; k < on; k++) { + clear_fake_cigar(&(ol->list[k].f_cigar)); + clear_window_list_alloc(&(ol->list[k].w_list)); + clear_window_list_alloc(&(ol->list[k].boundary_cigars)); + + ol0 = ol->length; + + tid = ol->list[k].y_id; trev = ol->list[k].y_pos_strand; + if(trev) recover_UC_Read_RC(tu, rref, tid); + else recover_UC_Read(tu, rref, tid); + + get_pi_ec_chain(ab, rid, rl, tid, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); + assert(ol->length - ol0 <= 1); + if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { + ol->list[ol0].y_pos_strand = trev; + // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); + } + + if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; + + if(m != ol0) { + t = ol->list[m]; + ol->list[m] = ol->list[ol0]; + ol->list[ol0] = t; + } + + m++; + } + ol->length = m; + + for (k = ol->length; k < on; k++) { + clear_fake_cigar(&(ol->list[k].f_cigar)); + clear_window_list_alloc(&(ol->list[k].w_list)); + clear_window_list_alloc(&(ol->list[k].boundary_cigars)); + } + + // fprintf(stderr, "[M::%s]\tnew::%lu\told::%lu\n", __func__, ol->length, ol0); + + oa = in0->buffer; on = in0->length; + for (k = 0; k < on; k++) { + if(oa[k].el) { + z = &(ol->list[ol->length++]); + z->x_id = rid; z->y_id = oa[k].tn; + z->x_pos_strand = 0; z->y_pos_strand = oa[k].rev; + z->x_pos_s = (uint32_t)oa[k].qns; + z->x_pos_e = oa[k].qe - 1; + z->y_pos_s = oa[k].ts; + z->y_pos_e = oa[k].te - 1; + + z->is_match = 1; + z->align_length = z->overlapLen = z->shared_seed = z->x_pos_e + 1 - z->x_pos_s; + z->non_homopolymer_errors = z->strong = 0; + + set_exact_exz(exz, z->x_pos_s, z->x_pos_e + 1, z->y_pos_s, z->y_pos_e + 1); push_alnw(z, exz); + + // if(oa[k].tn == 1945) fprintf(stderr, "-em-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); + } + } + m = ol->length; + + for (k = 0; k < srt_i->n; k++) { + ol0 = ol->length; + if(srt_i->a[k]&1) { + p = &(in1->buffer[((uint32_t)srt_i->a[k])>>1]); + } else { + p = &(in0->buffer[((uint32_t)srt_i->a[k])>>1]); + } + + if(p->rev) recover_UC_Read_RC(tu, rref, p->tn); + else recover_UC_Read(tu, rref, p->tn); + + get_pi_ec_chain(ab, rid, rl, p->tn, tu->seq, tu->length, mz_w, mz_k, ol, cl, bw_thres, apend_be, k_flag, dbg_ct, sp, high_occ, low_occ, gen_off, enable_mcopy, mcopy_rate, mcopy_khit_cut, max_skip, max_iter, max_dis, quick_check, chn_pen_gap, chn_pen_skip); + assert(ol->length - ol0 <= 1); + if((ol->length > ol0) && (gen_hc_r_alin_re(&(ol->list[ol0]), cl, rs, rl, tu->seq, tu->length, exz, aux_o, asm_opt.max_ov_diff_ec, w.window_length, rid, E_KHIT, 1, buf))) { + ol->list[ol0].y_pos_strand = p->rev; + // if(oa[k].tn == 15382) fprintf(stderr, "-mm-[M::%s]\tqn::%u\ttn::%u\terr::%u\n", __func__, rid, oa[k].tn, ol->list[ol->length-1].non_homopolymer_errors); + } + + if((ol->length <= ol0) || (ol->list[ol0].is_match != 1)) continue; + + if(m != ol0) { + t = ol->list[m]; + ol->list[m] = ol->list[ol0]; + ol->list[ol0] = t; + } + + m++; + } + + ol->length = m; + + + // fprintf(stderr, "[M::%s]\tnew_n::%lu\told_n::%lu\n", __func__, ol->length, m0); + // fprintf(stderr, "[M::%s]\tnew_n::%lu\told_n::%u\n", __func__, ol->length, in0->length + in1->length); + // assert(ol->length <= (in0->length + in1->length)); + + + // dbg_overlap_region_cigar(ol->list, ol->length, rs, rref, tu); + + return aux_o; +} + + +void gen_ori_seq0(char *tstr, uint64_t tl, UC_Read *qu, asg16_v *sc, uint64_t rid) +{ + uint64_t ck, qk, tk, k, wq[2], wt[2]; uint32_t len; uint16_t c, bq, bt; char *qstr = NULL; + + ck = qk = tk = 0; + while (ck < sc->n) { + wq[0] = qk; wt[0] = tk; + ck = pop_trace_bp_f(sc, ck, &c, &bq, &bt, &len); + if(c != 2) qk += len; + if(c != 3) tk += len; + wq[1] = qk; wt[1] = tk; + } + if(!(tk == tl)) { + fprintf(stderr, "[M::%s] rid::%lu, tk::%lu, tl::%lu\n", __func__, rid, tk, tl); + } + assert(tk == tl); + + resize_UC_Read(qu, qk); qstr = qu->seq; qu->length = qk; + ck = qk = tk = 0; + while (ck < sc->n) { + wq[0] = qk; wt[0] = tk; + ck = pop_trace_bp_f(sc, ck, &c, &bq, &bt, &len); + if(c != 2) qk += len; + if(c != 3) tk += len; + wq[1] = qk; wt[1] = tk; + + if(c == 0) { + memcpy(qstr + wq[0], tstr + wt[0], (wq[1]-wq[0])*sizeof((*qstr))); + } else if(c == 1 || c == 3) { + for (k = wq[0]; k < wq[1]; k++) qstr[k] = s_H[bq]; + } + // fprintf(stderr, "%u%c(%c)(x::[%lu,%ld))(y::[%lu,%ld))\n", len, cm[c], ((c==1)||(c==2))?(cc[bt]):('*'), wx[0], wx[1], wy[0], wy[1]); // s_H + } +} + +void gen_cc_fly(asg16_v *sc, char *qstr, uint64_t ql, char *tstr, uint64_t tl, bit_extz_t *exz, double e_rate, uint64_t maxn, uint64_t maxe) +{ + // fprintf(stderr, "[M::%s] ql::%lu, tl::%lu\n", __func__, ql, tl); + if(ql == 0 && tl == 0) return; + uint64_t k, ck, qk, tk, wq[2], wt[2], maxl, minl, diff, f, diff0 = 0; + if(ql > 0 && tl == 0) { + for (k = 0; k < ql; k++) { + push_trace_bp_f(sc, 3, seq_nt6_table[(uint32_t)(qstr[k])], (uint16_t)-1, 1, 1); + } + return; + } + if(ql == 0 && tl > 0) { + for (k = 0; k < tl; k++) { + push_trace_bp_f(sc, 2, (uint16_t)-1, seq_nt6_table[(uint32_t)(tstr[k])], 1, 1); + } + return; + } + if(ql == tl && ql == 1) { + if(qstr[0] == tstr[0]) push_trace_bp_f(sc, 0, (uint16_t)-1, (uint16_t)-1, 1, 1); + else push_trace_bp_f(sc, 1, seq_nt6_table[(uint32_t)(qstr[0])], seq_nt6_table[(uint32_t)(tstr[0])], 1, 1); + return; + } + + + + if(ql >= tl) { + maxl = ql; minl = tl; + } else { + maxl = tl; minl = ql; + } + f = 0; + + diff = 31; + if(diff > (maxl - minl)) { + if(diff > maxl) diff = maxl; + diff0 = diff; clear_align(*exz); + cal_exz_global(tstr, tl, qstr, ql, diff, exz); + if(is_align(*exz)) f = 1; + } + + if(!f) { + diff = 63; + if(diff > (maxl - minl)) { + if(diff > maxl) diff = maxl; + if(diff > diff0) { + diff0 = diff; clear_align(*exz); + cal_exz_global(tstr, tl, qstr, ql, diff, exz); + if(is_align(*exz)) f = 1; + } + } + } + + if(!f) { + if((maxn > maxl) && (maxe > (maxl - minl))) { + diff = maxl * e_rate; + if(diff < 1) diff = 1; + if(diff > maxe) diff = maxe; + if(diff > diff0) { + diff0 = diff; clear_align(*exz); + cal_exz_global(tstr, tl, qstr, ql, diff, exz); + if(is_align(*exz)) f = 1; + } + } + } + + // fprintf(stderr, "[M::%s] f::%lu, err::%d\n", __func__, f, exz->err); + + uint32_t on; uint16_t op; + if(f) { + + for (ck = qk = tk = 0; ck < exz->cigar.n;) { + wq[0] = qk; wt[0] = tk; + ck = pop_trace(&(exz->cigar), ck, &op, &on); + if(op!=2) qk += on; + if(op!=3) tk += on; + wq[1] = qk; wt[1] = tk; + + if(op == 0) { + push_trace_bp_f(sc, op, (uint16_t)-1, (uint16_t)-1, on, 1); + } else if(op == 1) { + for (k = 0; k < on; k++) { + push_trace_bp_f(sc, op, seq_nt6_table[(uint32_t)(qstr[wq[0]+k])], seq_nt6_table[(uint32_t)(tstr[wt[0]+k])], 1, 1); + } + } else if(op == 2) { + for (k = 0; k < on; k++) { + push_trace_bp_f(sc, op, (uint16_t)-1, seq_nt6_table[(uint32_t)(tstr[wt[0]+k])], 1, 1); + } + } else if(op == 3) { + for (k = 0; k < on; k++) { + push_trace_bp_f(sc, op, seq_nt6_table[(uint32_t)(qstr[wq[0]+k])], (uint16_t)-1, 1, 1); + } + } + } + } else { + if(ql > 0) { + op = 3; on = ql; + for (k = 0; k < on; k++) { + push_trace_bp_f(sc, op, seq_nt6_table[(uint32_t)(qstr[k])], (uint16_t)-1, 1, 1); + } + } + + if(tl > 0) { + op = 2; on = tl; + for (k = 0; k < on; k++) { + push_trace_bp_f(sc, op, (uint16_t)-1, seq_nt6_table[(uint32_t)(tstr[k])], 1, 1); + } + } + + } +} + +void cal_updated_trace_len(asg16_v *sc, uint64_t *ql, uint64_t *tl) +{ + uint64_t ck = 0, qk = 0, tk = 0; uint32_t len; uint16_t c, bq, bt; + while (ck < sc->n) { + ck = pop_trace_bp_f(sc, ck, &c, &bq, &bt, &len); + if(c != 2) qk += len; + if(c != 3) tk += len; + } + *ql = qk; *tl = tk; +} + +void gen_updated_trace(asg16_v *qcc, asg16_v *tcc, asg16_v *tcc_res, char *qstr, uint64_t ql, char *tstr, uint64_t tl, asg64_v *srt, bit_extz_t *exz, uint64_t rid) +{ + uint64_t k, ck, qk, tk, wq[2], wt[2], old_dp, dp, s, e, srt_n, si, ei, so, os, oe, *qd, *td, qs, qe, ts, te, q0, t0; + asg16_v *cc; uint32_t len; uint16_t c, bq, bt; + + srt->n = 0; + + cc = qcc; + ck = qk = tk = wq[0] = wq[1] = wt[0] = wt[1] = 0; + while (ck < cc->n) { + wq[0] = qk; wt[0] = tk; + ck = pop_trace_bp_f(cc, ck, &c, &bq, &bt, &len); + if(c != 2) qk += len; + if(c != 3) tk += len; + wq[1] = qk; wt[1] = tk; + if(c != 0) continue; + + kv_push(uint64_t, (*srt), (wq[0]<<1)); + kv_push(uint64_t, (*srt), ((wq[1]<<1)|1)); + } + + cc = tcc; + ck = qk = tk = wq[0] = wq[1] = wt[0] = wt[1] = 0; + while (ck < cc->n) { + wq[0] = qk; wt[0] = tk; + ck = pop_trace_bp_f(cc, ck, &c, &bq, &bt, &len); + if(c != 2) qk += len; + if(c != 3) tk += len; + wq[1] = qk; wt[1] = tk; + if(c != 0) continue; + + kv_push(uint64_t, (*srt), (wt[0]<<1)); + kv_push(uint64_t, (*srt), ((wt[1]<<1)|1)); + } + + // fprintf(stderr, "[M::%s] rid::%lu, ql::%lu, tl::%lu\n", __func__, rid, ql, tl); + + radix_sort_ec64(srt->a, srt->a + srt->n); + for (k = 0, dp = e = srt_n = 0, s = (uint64_t)-1; k < srt->n; k++) { + old_dp = dp; + //if a[k] is qe + if (srt->a[k]&1) --dp; + else ++dp; + + if(old_dp >= 2 && s != (uint64_t)-1) { + e = srt->a[k]>>1; + if(e > s) srt->a[srt_n++] = ((s<<32)|(e)); + } + + s = (uint64_t)-1; + if(dp >= 2) s = srt->a[k]>>1; + // if (old_dp < 2 && dp >= 2) {///old_dp < dp, a[k] is qs + // s = srt->a[k]>>1; + // } else if (old_dp >= 2 && dp < 2) {///old_dp > dp, a[k] is qe + // e = srt->a[k]>>1; + // if(e > s) { + // srt->a[srt_n++] = ((s<<32)|(e)); + // fprintf(stderr, "[M::%s] x::[%lu,\t%lu)\n", __func__, s, e); + // } + // } + } + + + // for (k = 0; k < srt_n; k++) { + // fprintf(stderr, "[M::%s] x[%lu]::[%lu,\t%u)\n", __func__, k, srt->a[k]>>32, (uint32_t)srt->a[k]); + // } + + + if(srt_n > 0) { + srt->n = srt_n; + + cc = qcc; + k = ck = qk = tk = wq[0] = wq[1] = wt[0] = wt[1] = 0; + while (ck < cc->n) { + wq[0] = qk; wt[0] = tk; + ck = pop_trace_bp_f(cc, ck, &c, &bq, &bt, &len); + if(c != 2) qk += len; + if(c != 3) tk += len; + wq[1] = qk; wt[1] = tk; + if(c != 0) continue; + si = wq[0]; ei = wq[1]; + so = wt[0]; ///eo = wt[1]; + + for (; (k > 0) && ((k >= srt_n) || (((uint32_t)(srt->a[k])) > si)); k--); + for (; k < srt_n; k++) { + s = srt->a[k]>>32; e = (uint32_t)(srt->a[k]); + if(s >= ei) break; + if(s >= si && e <= ei) { + os = so + s - si; + oe = so + e - si; + kv_push(uint64_t, (*srt), ((os<<32)|(oe))); + } + } + } + assert(srt->n == (srt_n<<1)); + + cc = tcc; + k = ck = qk = tk = wq[0] = wq[1] = wt[0] = wt[1] = 0; + while (ck < cc->n) { + wq[0] = qk; wt[0] = tk; + ck = pop_trace_bp_f(cc, ck, &c, &bq, &bt, &len); + if(c != 2) qk += len; + if(c != 3) tk += len; + wq[1] = qk; wt[1] = tk; + if(c != 0) continue; + si = wt[0]; ei = wt[1]; + so = wq[0]; ///eo = wq[1]; + + for (; (k > 0) && ((k >= srt_n) || (((uint32_t)(srt->a[k])) > si)); k--); + for (; k < srt_n; k++) { + s = srt->a[k]>>32; e = (uint32_t)(srt->a[k]); + // fprintf(stderr, "######[M::%s] t[%lu]::[%lu,\t%lu) i::[%lu,\t%lu)\n", __func__, k, s, e, si, ei); + if(s >= ei) break; + if(s >= si && e <= ei) { + os = so + s - si; + oe = so + e - si; + kv_push(uint64_t, (*srt), ((os<<32)|(oe))); + // fprintf(stderr, "[M::%s] ******\n", __func__); + } + } + } + // if(!(srt->n == (srt_n*3))) { + // fprintf(stderr, "[M::%s] rid::%lu, srt_n::%lu, srt->n::%lu\n", __func__, rid, srt_n, (uint64_t)srt->n); + // } + assert(srt->n == (srt_n*3)); + + + tcc_res->n = 0; ///reset tcc + qd = srt->a + srt_n; td = srt->a + srt_n + srt_n; uint64_t nl = 0;///, dbg_ql, dbg_tl; + for (k = q0 = t0 = 0; k < srt_n; k++) { + qs = qd[k]>>32; qe = (uint32_t)qd[k]; + ts = td[k]>>32; te = (uint32_t)td[k]; + nl += qs - qe; + // assert((qe - qs) == (te - ts)); + // assert(!memcmp(qstr + qs, tstr + ts, sizeof((*qstr))*(qe - qs))); + + // if(t0 > ts || q0 > qs) { + // fprintf(stderr, "[M::%s] rid::%lu, ql::%lu, tl::%lu\n", __func__, rid, ql, tl); + // } + // fprintf(stderr, "[M::%s] qseq::[%lu,%lu), ql::%lu, tseq::[%lu,%lu), tl::%lu\n", __func__, t0, ts, tl, q0, qs, ql); + + gen_cc_fly(tcc_res, tstr + t0, ts - t0, qstr + q0, qs - q0, exz, 0.25, MAX_SIN_L, MAX_SIN_E); + + // cal_updated_trace_len(tcc_res, &dbg_ql, &dbg_tl); + // assert(dbg_ql == ts && dbg_tl == qs); + + // fprintf(stderr, "******\n"); + + push_trace_bp_f(tcc_res, 0, (uint16_t)-1, (uint16_t)-1, qe - qs, 1); + + // cal_updated_trace_len(tcc_res, &dbg_ql, &dbg_tl); + // assert(dbg_ql == te && dbg_tl == qe); + + q0 = qe; t0 = te; + } + + qs = ql; ts = tl; + // fprintf(stderr, "[M::%s] qseq::[%lu,%lu), ql::%lu, tseq::[%lu,%lu), tl::%lu\n", __func__, t0, ts, tl, q0, qs, ql); + gen_cc_fly(tcc_res, tstr + t0, ts - t0, qstr + q0, qs - q0, exz, 0.25, MAX_SIN_L, MAX_SIN_E); + // if(!(dbg_ql == ts && dbg_tl == qs)) { + // fprintf(stderr, "[M::%s] rid::%lu, qseq::[%lu,%lu), ql::%lu, tseq::[%lu,%lu), tl::%lu\n", __func__, rid, t0, ts, tl, q0, qs, ql); + // } + // cal_updated_trace_len(tcc_res, &dbg_ql, &dbg_tl); + // assert(dbg_ql == ts && dbg_tl == qs); + + // fprintf(stderr, "[M::%s] srt_n::%lu, nl::%lu, ql::%lu, tl::%lu\n", __func__, srt_n, nl, ql, tl); + } else { + gen_cc_fly(tcc_res, tstr, tl, qstr, ql, exz, 0.25, MAX_SIN_L, MAX_SIN_E); + } +} + +void update_scb(All_reads *R_INF, asg16_v *scc, asg16_v *scb, asg16_v *scb_res, UC_Read *qu, UC_Read *tu, asg64_v *srt, bit_extz_t *exz, uint64_t rid) +{ + char *qstr = NULL, *tstr = NULL; uint64_t ql = 0, tl = 0; + uint64_t ck, qk, tk, k, wq[2], wt[2]; uint32_t len; uint16_t c, bq, bt; + gen_ori_seq0(qu->seq, qu->length, tu, scb, rid); ///tstr = tu->seq; tl = tu->length; + + ck = qk = tk = 0; ql = qu->length; + while (ck < scc->n) { + wq[0] = qk; wt[0] = tk; + ck = pop_trace_bp_f(scc, ck, &c, &bq, &bt, &len); + if(c != 2) qk += len; + if(c != 3) tk += len; + wq[1] = qk; wt[1] = tk; + } + assert(qk == ql); + tl = tk; resize_UC_Read(qu, ql + tl); + qstr = qu->seq; tstr = qu->seq + ql; + + ck = 0; qk = tk = 0; + while (ck < scc->n) { + wq[0] = qk; wt[0] = tk; + ck = pop_trace_bp_f(scc, ck, &c, &bq, &bt, &len); + if(c != 2) qk += len; + if(c != 3) tk += len; + wq[1] = qk; wt[1] = tk; + // if(xk > (uint32_t)p->z.length) fprintf(stderr, "[M::%s] xk::%u, len::%u, c::%u, rid::%ld\n", __func__, xk, (uint32_t)p->z.length, c, i); + if(c == 0) { + memcpy(tstr + wt[0], qstr + wq[0], (wq[1]-wq[0])*sizeof((*qstr))); + } else if(c == 1 || c == 2) { + for (k = wt[0]; k < wt[1]; k++) tstr[k] = s_H[bt]; + } + // if(i == 700) fprintf(stderr, "|%u%c(%c)(x::%u)(y::%u)", len, cm[c], ((c==1)||(c==2))?(cc[b]):('*'), wx[1], wy[1]); // s_H + } + + qstr = tstr; ql = tl; + tstr = tu->seq; tl = tu->length; + + // fprintf(stderr, "\n[M::%s] ql::%lu, tl::%lu, rid::%lu\n", __func__, ql, tl, rid); + + gen_updated_trace(scc, scb, scb_res, qstr, ql, tstr, tl, srt, exz, rid); + + + + ///debug + // resize_UC_Read(tu, ql + tl); + // memcpy(tu->seq + tl, qstr, ql); tstr = tu->seq; qstr = tu->seq + tl; + + // resize_UC_Read(qu, ql + tl); + // memcpy(qu->seq, tu->seq, ql + tl); tstr = qu->seq; qstr = qu->seq + tl; + + // gen_ori_seq0(qstr, ql, tu, scb_res, rid); + // assert(memcmp(tstr, tu->seq, tl) == 0); + +} + +uint32_t is_well_cal(asg64_v *idx, ma_hit_t_alloc *in0, ma_hit_t_alloc *in1, int64_t ql, int64_t occ_exact) +{ + ma_hit_t_alloc *paf = NULL; uint64_t k, s, e, vn; ma_hit_t *z; idx->n = 0; + int64_t dp, old_dp, st = 0, ed; + + paf = in0; + for (k = 0; k < paf->length; k++) { + z = &(paf->buffer[k]); + s = ((uint32_t)(z->qns)); e = z->qe; + kv_push(uint64_t, (*idx), (s<<1)); + kv_push(uint64_t, (*idx), (e<<1)|1); + } + + paf = in1; + for (k = 0; k < paf->length; k++) { + z = &(paf->buffer[k]); + s = ((uint32_t)(z->qns)); e = z->qe; + kv_push(uint64_t, (*idx), (s<<1)); + kv_push(uint64_t, (*idx), (e<<1)|1); + } + + radix_sort_ec64(idx->a, idx->a + idx->n); vn = idx->n; + for (k = 0, dp = 0, st = ed = 0; k < vn; ++k) { + old_dp = dp; + ///if a[j] is qe + if (idx->a[k]&1) --dp; + else ++dp; + + ed = idx->a[k]>>1; + if((ed > st) && ((old_dp + 1) < occ_exact)) return 0;///+1 for self + + st = ed; + } + + + ed = ql; old_dp = dp; + if((ed > st) && ((old_dp + 1) < occ_exact)) return 0;///+1 for self + + return 1; +} + +static void worker_hap_dc_ec0(void *data, long i, int tid) +{ + // if(i == 6) fprintf(stderr, "-mm-[M::%s]\tqn::%u::%.*s\tf[i]::%u\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i), scc.f[i]); + if(scc.f[i]) { + scc.a[i].n = 0; sca.a[i].n = 0; + // push_trace_bp(&(scc.a[i]), 0, (uint16_t)-1, Get_READ_LENGTH(R_INF, i), 0); + push_trace_bp_f(&(scc.a[i]), 0, (uint16_t)-1, (uint16_t)-1, Get_READ_LENGTH(R_INF, i), 0); + return; + } + ec_ovec_buf_t0 *b = &(((ec_ovec_buf_t*)data)->a[tid]); + uint32_t high_occ = asm_opt.hom_cov * (2.0 - HA_KMER_GOOD_RATIO); + uint32_t low_occ = asm_opt.hom_cov * HA_KMER_GOOD_RATIO; + asg64_v buf0; overlap_region *aux_o = NULL; uint32_t qlen = 0; + // overlap_region *aux_o = NULL; asg64_v buf0; + + // gen_ovlst_paf(&(R_INF.paf[i]), &(R_INF.reverse_paf[i]), &(b->v64)); + // if(i != 181) return; + + // fprintf(stderr, "-mm-[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); + + recover_UC_Read(&b->self_read, &R_INF, i); qlen = b->self_read.length; + + + /** + if(is_well_cal(&b->v64, &(R_INF.paf[i]), &(R_INF.reverse_paf[i]), b->self_read.length, 4)) { + // aux_o = h_ec_lchain_re1(b->ab, i, &b->self_read, &b->ovlp_read, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, &b->exz, &b->v16, &b->v64, 0.02, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 0, 2, UINT32_MAX, &(R_INF.paf[i]), &(R_INF.reverse_paf[i])); + aux_o = h_ec_lchain_re2(b->ab, i, &b->self_read, &b->ovlp_read, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, &b->exz, &b->v16, &b->v64, 0.02, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 0, 2, UINT32_MAX, &(R_INF.paf[i]), &(R_INF.reverse_paf[i])); + } else { + aux_o = h_ec_lchain_re3(b->ab, i, &b->self_read, &b->ovlp_read, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, &b->exz, &b->v16, &b->v64, 0.02, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 0, 2, UINT32_MAX, &(R_INF.paf[i]), &(R_INF.reverse_paf[i])); + // fprintf(stderr, "[M::%s]\tqn::%u::%.*s\n", __func__, (uint32_t)(i), (int)Get_NAME_LENGTH(R_INF, i), Get_NAME((R_INF), i)); + } + **/ + aux_o = h_ec_lchain_re2(b->ab, i, &b->self_read, &b->ovlp_read, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, &b->exz, &b->v16, &b->v64, 0.02, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 0, 2, UINT32_MAX, &(R_INF.paf[i]), &(R_INF.reverse_paf[i])); + + ////for debug + // scc.a[i].n = 0; + // push_trace_bp(&(scc.a[i]), 0, (uint16_t)-1, Get_READ_LENGTH(R_INF, i), 0); + + // return; + + // aux_o = h_ec_lchain_re(b->ab, i, b->self_read.seq, b->self_read.length, &b->ovlp_read, asm_opt.mz_win, asm_opt.k_mer_length, &R_INF, &b->olist, &b->clist, &b->exz, &b->v16, 0.02, 1, NULL, NULL, &(b->sp), &high_occ, &low_occ, 1, 1, 0, 2, UINT32_MAX, &(R_INF.paf[i]), &(R_INF.reverse_paf[i])); + + b->cnt[0] += b->self_read.length; + + copy_asg_arr(buf0, b->sp); + rphase_hc(&b->olist, &R_INF, &b->hap, &b->self_read, &b->ovlp_read, &b->pidx, &b->v64, &buf0, 0, WINDOW_MAX_SIZE, b->self_read.length, 1/**, 1**/, i, (asm_opt.is_ont)?HPC_PL:0, asm_opt.is_ont, ((asm_opt.is_ont)?&(b->clist.chainDP):NULL), /**((asm_opt.is_sc)?&(b->v8q):NULL)**/&(b->v8q), ((asm_opt.is_sc)?&(b->v8t):NULL), (asm_opt.is_ont)?1:0, ((uint64_t)-1), 0, HC0_W, &b->v32); + copy_asg_arr(b->sp, buf0); + + copy_asg_arr(buf0, b->sp); + b->cnt[1] += wcns_gen(&b->olist, &R_INF, i, &b->self_read, &b->ovlp_read, &b->exz, &b->pidx, &b->v64, &buf0, 0, 512, b->self_read.length, 3, 0.500001, aux_o, &b->v32, &b->cns, 256, i, ((uint64_t)-1), NULL); + copy_asg_arr(b->sp, buf0); + + push_nec_re(aux_o, &(scc.a[i])); + update_scb(&R_INF, &(scc.a[i]), &(scb.a[i]), &(sca.a[i]), &b->self_read, &b->ovlp_read, &b->v64, &b->exz, i); + + push_ne_ovlp(&(R_INF.paf[i]), &b->olist, 1, &R_INF, &(scc.a[i])/**, i, &b->self_read, &b->ovlp_read**/); + push_ne_ovlp(&(R_INF.reverse_paf[i]), &b->olist, 2, &R_INF, NULL/**, i, NULL, NULL**/); + + check_well_cal(&(scc.a[i]), &b->v64, &(R_INF.paf[i].is_fully_corrected), &(R_INF.paf[i].is_abnormal), qlen, (MIN_COVERAGE_THRESHOLD*2), &(R_INF.paf[i])); + R_INF.trio_flag[i] = AMBIGU; + + refresh_ec_ovec_buf_t0(b, REFRESH_N); +} + +void get_origin_ec_coor(asg16_v *ec, uint64_t *ts, uint64_t *te) +{ + uint64_t ts0 = *ts, te0 = *te, qk = 0, tk = 0, ck = 0, wq[2], wt[2]; uint16_t op, bq, bt, f = 0; uint32_t cl; + while (ck < ec->n) { + wq[0] = qk; wt[0] = tk; + ck = pop_trace_bp_f(ec, ck, &op, &bq, &bt, &cl); + if(op != 2) qk += cl; + if(op != 3) tk += cl; + wq[1] = qk; wt[1] = tk; + if((op == 0) && (wt[0] <= ts0) && (wt[1] >= te0)) { + (*ts) = wq[0] + ts0 - wt[0]; + (*te) = wq[0] + te0 - wt[0]; + f = 1; + break; + } + } + assert(f); +} + +static void update_scb0(void *data, long i, int tid) +{ + if(sca.a[i].n) { + kv_resize(uint16_t, scb.a[i], sca.a[i].n); scb.a[i].n = sca.a[i].n; + memcpy(scb.a[i].a, sca.a[i].a, scb.a[i].n*sizeof((*(sca.a[i].a)))); + } + + // return; + + if(!scc.f[i]) return; + + ma_hit_t_alloc *ov, *os; uint64_t k, kr, qn, tn, ql, tl, qs, qe, ts, te; ma_hit_t *z, *r; + uint64_t ck; uint16_t op, bq, bt; uint32_t cl; + + ov = &(R_INF.paf[i]); + for (k = 0; k < ov->length; k++) { + z = &(ov->buffer[k]); + qn = z->qns>>32; tn = z->tn; + if(scc.f[tn]) continue; + + os = &(R_INF.paf[tn]); + for (kr = 0; kr < os->length; kr++) { + if(os->buffer[kr].tn == qn) { + r = &(os->buffer[kr]); + break; + } + } + if(kr >= os->length) continue; + // if(!(r->el)) continue; + + qs = r->ts; qe = r->te; + ts = (uint32_t)r->qns; te = r->qe; + z->el = r->el; z->rev = r->rev; z->ml = r->ml; z->no_l_indel = r->no_l_indel; + if(z->el) { + get_origin_ec_coor(&(scc.a[tn]), &ts, &te); + } + + z->qns = qn; + z->qns = z->qns << 32; + if(z->rev) { + ql = Get_READ_LENGTH(R_INF, qn); + tl = ck = 0; + while (ck < scc.a[tn].n) { + ck = pop_trace_bp_f(&(scc.a[tn]), ck, &op, &bq, &bt, &cl); + if(op != 2) tl += cl; + } + z->qns = z->qns | (ql - qe); + z->qe = ql - qs; + z->ts = tl - te; + z->te = tl - ts; + } else { + z->qns = z->qns | qs; + z->qe = qe; + z->ts = ts; + z->te = te; + } + } +} + +void dbg_rsc(char *str0, uint64_t l0, char *str1, uint64_t l1, asg16_v *sc, char *real, uint32_t id) +{ + uint64_t ck, xk, yk, k, wx[2], wy[2]; uint32_t len; uint16_t c, bq, bt; + + ck = xk = yk = 0; + while (ck < sc->n) { + wx[0] = xk; wy[0] = yk; + ck = pop_trace_bp_f(sc, ck, &c, &bq, &bt, &len); + if(c != 2) xk += len; + if(c != 3) yk += len; + wx[1] = xk; wy[1] = yk; + } + assert(xk == l0); + + // char cm[4], cc[4]; + // cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; + // cc[0] = 'A'; cc[1] = 'C'; cc[2] = 'G'; cc[3] = 'T'; + + ck = xk = yk = 0; + while (ck < sc->n) { + wx[0] = xk; wy[0] = yk; + ck = pop_trace_bp_f(sc, ck, &c, &bq, &bt, &len); + if(c != 2) xk += len; + if(c != 3) yk += len; + wx[1] = xk; wy[1] = yk; + + if(c == 0) { + memcpy(str0 + wx[0], str1 + wy[0], (wx[1]-wx[0])*sizeof((*str1))); + } else if(c == 1 || c == 3) { + for (k = wx[0]; k < wx[1]; k++) str0[k] = s_H[bq]; + } + // fprintf(stderr, "%u%c(%c)(x::[%lu,%ld))(y::[%lu,%ld))\n", len, cm[c], ((c==1)||(c==2))?(cc[bt]):('*'), wx[0], wx[1], wy[0], wy[1]); // s_H + } + + if(memcmp(str0, real, l0*sizeof((*str0)))) { + fprintf(stderr, "-0-[M::%s]\tid::%u\n", __func__, id); + // for (k = 0; k < l0 && str0[k] == real[k]; k++); + + // fprintf(stderr, "-0-[M::%s]\tid::%u\tk::%lu\tl0::%lu\tnc::%c\toc::%c\n", __func__, id, k, l0, str0[k], real[k]); + // exit(1); + } else { + // fprintf(stderr, "-1-[M::%s]\tid::%u\n", __func__, id); + } + +} + +static void worker_sl_ec(void *data, long i, int tid) +{ + // if(i != 0) return; + + sl_v *p = &(((sl_v*)data)[tid]); uint8_t *oa = NULL; char *na = NULL; uint64_t tqual, wqual, rid = i; + uint32_t ci = 0, len, xk, yk, wx[2], wy[2], k, Nn, yn = 0, tot_e; uint16_t c, bq, bt; + + + ci = 0; xk = yk = 0; tot_e = 0; + while (ci < scc.a[i].n) { + // ci = pop_trace_bp(&scc.a[i], ci, &c, &b, &len); + ci = pop_trace_bp_f(&scc.a[i], ci, &c, &bq, &bt, &len); + if(c != 3) yk += len; + if(c != 0) tot_e += len; + // fprintf(stderr, "|%u%c(%c)", len, cm[c], ((c==1)||(c==2))?(cc[b]):('*')); // s_H + } + if(tot_e == 0) return;///no change + + yn = yk; yk++; kv_resize(char, (*p), yk); p->a[yn] = '\0'; + recover_UC_Read(&p->z, &R_INF, i); ///b->z.length + + + // char cm[4], cc[4]; + // cm[0] = 'M'; cm[1] = 'S'; cm[2] = 'I'; cm[3] = 'D'; + // cc[0] = 'A'; cc[1] = 'C'; cc[2] = 'G'; cc[3] = 'T'; + + ci = 0; xk = yk = 0; Nn = 0; + while (ci < scc.a[i].n) { + wx[0] = xk; wy[0] = yk; + // ci = pop_trace_bp(&scc.a[i], ci, &c, &b, &len); + ci = pop_trace_bp_f(&scc.a[i], ci, &c, &bq, &bt, &len); + if(c != 2) xk += len; + if(c != 3) yk += len; + wx[1] = xk; wy[1] = yk; + // if(xk > (uint32_t)p->z.length) fprintf(stderr, "[M::%s] xk::%u, len::%u, c::%u, rid::%ld\n", __func__, xk, (uint32_t)p->z.length, c, i); + if(c == 0) { + // memcpy(p->a + wy[0], p->z.seq + wx[0], (wx[1]-wx[0])*sizeof((*(p->a)))); + for (; wx[0] < wx[1]; wx[0]++, wy[0]++) { + p->a[wy[0]] = p->z.seq[wx[0]]; + if(p->a[wy[0]] == 'N') Nn++; + } + } else if(c == 1 || c == 2) { + for (k = wy[0]; k < wy[1]; k++) { + p->a[k] = s_H[bt]; + if(p->a[k] == 'N') Nn++; + } + } + + // if(i == 700) fprintf(stderr, "|%u%c(%c)(x::%u)(y::%u)", len, cm[c], ((c==1)||(c==2))?(cc[b]):('*'), wx[1], wy[1]); // s_H + } + + // if(i == 700) fprintf(stderr, "|\n"); + if((asm_opt.is_sc) && (rid < R_INF.tqn)) retrive_bqual(&(p->q), NULL, i, -1, -1, 0, sc_bn); + + + if (R_INF.read_size[i] < yn) { + R_INF.read_size[i] = yn; + REALLOC(R_INF.read_sperate[i], R_INF.read_size[i]/4+1); + if((asm_opt.is_sc) && (rid < R_INF.tqn)) REALLOC(R_INF.rsc[i], ((R_INF.read_size[i]/sc_bn) + ((R_INF.read_size[i]%sc_bn)?1:0))); + } + R_INF.read_length[i] = yn; + // if(Nn > 0) fprintf(stderr, "[M::%s] Nn->%u\n", __func__, Nn); + + // for (k = 0; k < yn; k++) { + // c = seq_nt6_table[(uint8_t)p->a[k]]; + // if (c >= 4) { + // fprintf(stderr, "[M::%s] Nn->%u, yn::%u, xn::%lld, k::%u, str::%c, c::%u, rid::%ld\n", __func__, Nn, yn, p->z.length, k, p->a[k], c, i); + // } + // } + + + ///debug + // resize_UC_Read(&p->z, p->z.length * 2); + // dbg_rsc(p->z.seq + p->z.length, p->z.length, p->a, yn, &(scc.a[i]), p->z.seq, i); + + + ha_compress_base(Get_READ(R_INF, i), p->a, yn, &R_INF.N_site[i], Nn); + if((asm_opt.is_sc) && (rid < R_INF.tqn)) { + oa = p->q.a; na = p->a; + ci = 0; xk = yk = 0; Nn = 0; + while (ci < scc.a[i].n) { + wx[0] = xk; wy[0] = yk; + ci = pop_trace_bp_f(&scc.a[i], ci, &c, &bq, &bt, &len); + if(c != 2) xk += len; + if(c != 3) yk += len; + wx[1] = xk; wy[1] = yk; + if(c == 0 || c == 1) { + memcpy(na + wy[0], oa + wx[0], (wx[1]-wx[0])*sizeof((*oa))); + } else if(c == 2) { + get_wqual(i, wx[0], 0, NULL, oa, sc_wn, &tqual, &wqual); + for (k = wy[0]; k < wy[1]; k++) na[k] = wqual; + } + } + assert(yk == yn); + ha_compress_qual_bit(Get_QUAL(R_INF, i), na, yn, sc_bn); + } +} + +uint64_t cal_ec_multiple(ec_ovec_buf_t *b, uint64_t n_thre, uint64_t n_a, uint64_t *r_base) +{ + double tt0 = yak_realtime_0(); + uint64_t k, num_base = 0, num_correct = 0; (*r_base) = 0; + + if(!(scc.a)) { + scc.n = scc.m = n_a; CALLOC(scc.a, n_a); CALLOC(scc.f, n_a); + } + + if(!(scb.a)) { + scb.n = scb.m = n_a; CALLOC(scb.a, n_a); + } + + for (k = 0; k < n_thre; ++k) b->a[k].cnt[0] = b->a[k].cnt[1] = 0; + + if(!(asm_opt.hf)) kt_for(n_thre, worker_hap_ec, b, n_a);///debug_for_fix + else kt_for(n_thre, worker_hap_ec_hybrid, b, n_a);///debug_for_fix + + for (k = 0; k < n_thre; ++k) { + num_base += b->a[k].cnt[0]; + num_correct += b->a[k].cnt[1]; + } + + // fprintf(stderr, "\n[M::%s] # reads->%lu\n", __func__, n_a); + // fprintf(stderr, "[M::%s] # input bases->%lu\n", __func__, num_base); + // fprintf(stderr, "[M::%s] # corrected bases->%lu\n", __func__, num_correct); + // fprintf(stderr, "[M::%s::%.3f] running time\n", __func__, yak_realtime_0()-tt0); + fprintf(stderr, "[M::pec::%.3f] # bases: %lu; # corrected bases: %lu\n", yak_realtime_0()-tt0, num_base, num_correct); + + (*r_base) = num_base; + return num_correct; +} + +void cal_update_ec_multiple(ec_ovec_buf_t *b, uint64_t n_thre, uint64_t n_a) +{ + double tt0 = yak_realtime_0(); + uint64_t k, num_ec_o = 0, num_nec_o = 0; + + for (k = 0; k < n_thre; ++k) b->a[k].cnt[0] = b->a[k].cnt[1] = 0; + + kt_for(n_thre, worker_update_dc_ec, b, n_a);///debug_for_fix + + for (k = 0; k < n_thre; ++k) { + num_ec_o += b->a[k].cnt[0]; num_nec_o += b->a[k].cnt[1]; + } + + fprintf(stderr, "[M::pec::%.3f] # exact o: %lu; # non-exact o: %lu\n", yak_realtime_0()-tt0, num_ec_o, num_nec_o); +} + + +void ha_print_ovlp_stat_1(ec_ovec_buf_t *b, uint64_t n_thre, uint64_t n_a) +{ + double tt0 = yak_realtime_0(); + uint64_t k, forward, reverse, strong, weak, exact, no_l_indel; + + forward = reverse = strong = weak = exact = no_l_indel = 0; + + ///calculate overlaps + for (k = 0; k < n_thre; ++k) { + b->a[k].cnt[0] = b->a[k].cnt[1] = b->a[k].cnt[2] = b->a[k].cnt[3] = b->a[k].cnt[4] = b->a[k].cnt[5] = 0; + } + + kt_for(n_thre, worker_hap_dc_ec_gen, b, n_a); + + for (k = 0; k < n_thre; ++k) { + forward += b->a[k].cnt[0]; + reverse += b->a[k].cnt[1]; + strong += b->a[k].cnt[2]; + weak += b->a[k].cnt[3]; + exact += b->a[k].cnt[4]; + no_l_indel += b->a[k].cnt[5]; + } + + fprintf(stderr, "[M::%s] # overlaps: %lu\n", __func__, forward); + fprintf(stderr, "[M::%s] # strong overlaps: %lu\n", __func__, strong); + fprintf(stderr, "[M::%s] # weak overlaps: %lu\n", __func__, weak); + fprintf(stderr, "[M::%s] # exact overlaps: %lu\n", __func__, exact); // this seems not right + fprintf(stderr, "[M::%s] # inexact overlaps: %lu\n", __func__, forward - exact); + fprintf(stderr, "[M::%s] # overlaps without large indels: %lu\n", __func__, no_l_indel); + fprintf(stderr, "[M::%s] # reverse overlaps: %lu\n", __func__, reverse); + fprintf(stderr, "[M::%s] # running time: %.3f\n", __func__, yak_realtime_0()-tt0); + + // fprintf(stderr, "\n[M::%s] # reads->%lu\n", __func__, n_a); + // fprintf(stderr, "[M::%s] # corrected reads->%lu\n", __func__, rb); + // fprintf(stderr, "[M::%s] # uncorrected reads->%lu\n", __func__, urb); + // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime_0()-tt0); +} + +void ha_print_ovlp_stat_0(ec_ovec_buf_t *b, uint64_t n_thre, uint64_t n_a) +{ + double tt0 = yak_realtime_0(); + uint64_t k, forward, reverse, strong, weak, exact, no_l_indel; + + forward = reverse = strong = weak = exact = no_l_indel = 0; + + ///calculate overlaps + for (k = 0; k < n_thre; ++k) { + b->a[k].cnt[0] = b->a[k].cnt[1] = b->a[k].cnt[2] = b->a[k].cnt[3] = b->a[k].cnt[4] = b->a[k].cnt[5] = 0; + } + + kt_for(n_thre, worker_hap_dc_ec_gen_new_idx, b, n_a); + + for (k = 0; k < n_thre; ++k) { + forward += b->a[k].cnt[0]; + reverse += b->a[k].cnt[1]; + strong += b->a[k].cnt[2]; + weak += b->a[k].cnt[3]; + exact += b->a[k].cnt[4]; + no_l_indel += b->a[k].cnt[5]; + } + + fprintf(stderr, "[M::%s] # overlaps: %lu\n", __func__, forward); + fprintf(stderr, "[M::%s] # strong overlaps: %lu\n", __func__, strong); + fprintf(stderr, "[M::%s] # weak overlaps: %lu\n", __func__, weak); + fprintf(stderr, "[M::%s] # exact overlaps: %lu\n", __func__, exact); // this seems not right + fprintf(stderr, "[M::%s] # inexact overlaps: %lu\n", __func__, forward - exact); + fprintf(stderr, "[M::%s] # overlaps without large indels: %lu\n", __func__, no_l_indel); + fprintf(stderr, "[M::%s] # reverse overlaps: %lu\n", __func__, reverse); + fprintf(stderr, "[M::%s] # running time: %.3f\n", __func__, yak_realtime_0()-tt0); + + // fprintf(stderr, "\n[M::%s] # reads->%lu\n", __func__, n_a); + // fprintf(stderr, "[M::%s] # corrected reads->%lu\n", __func__, rb); + // fprintf(stderr, "[M::%s] # uncorrected reads->%lu\n", __func__, urb); + // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime_0()-tt0); +} + +uint64_t cal_sec_ec_multiple(ec_ovec_buf_t *b, uint64_t n_thre, uint64_t n_a, int64_t round) +{ + double tt0 = yak_realtime_0(); + uint64_t k, num_base, num_correct, rb, urb; + num_base = num_correct = 0; + + ////counting + rb = urb = 0; + for (k = 0; k < n_thre; ++k) b->a[k].cnt[0] = b->a[k].cnt[1] = 0; + + kt_for(n_thre, worker_hap_dc_ec, b, n_a);///debug_for_fix + + for (k = 0; k < n_thre; ++k) { + rb += b->a[k].cnt[0]; urb += b->a[k].cnt[1]; + } + + if(round >= 0) { + if(!(sca.a)) { + sca.n = sca.m = n_a; CALLOC(sca.a, n_a); + } + ////correct + + for (k = 0; k < n_thre; ++k) b->a[k].cnt[0] = b->a[k].cnt[1] = 0; + + kt_for(n_thre, worker_hap_dc_ec0, b, n_a);///debug_for_fix + + for (k = 0; k < n_thre; ++k) { + num_base += b->a[k].cnt[0]; + num_correct += b->a[k].cnt[1]; + } + + kt_for(n_thre, update_scb0, b, n_a); + } + + if(round >= 0) { + fprintf(stderr, "[M::sec::%.3f] # bases: %lu; # corrected bases: %lu; # reads: %lu; # corrected reads: %lu\n", yak_realtime_0()-tt0, num_base, num_correct, rb, urb); + } else { + fprintf(stderr, "[M::sec::%.3f] # reads: %lu; # corrected reads: %lu\n", yak_realtime_0()-tt0, rb, urb); + } + + // fprintf(stderr, "\n[M::%s] # reads->%lu\n", __func__, n_a); + // fprintf(stderr, "[M::%s] # corrected reads->%lu\n", __func__, rb); + // fprintf(stderr, "[M::%s] # uncorrected reads->%lu\n", __func__, urb); + // if(round >= 0) { + // fprintf(stderr, "[M::%s] # input bases->%lu\n", __func__, num_base); + // fprintf(stderr, "[M::%s] # corrected bases->%lu\n", __func__, num_correct); + // fprintf(stderr, "[M::%s::%.3f] ==> round %ld\n", __func__, yak_realtime_0()-tt0, round); + // } + return num_correct; +} + + +void write_ec_reads(const char *suffix_ou) +{ + uint64_t k, strl; UC_Read qstr, tstr; char *nn = NULL, *str = NULL; + init_UC_Read(&qstr); init_UC_Read(&tstr); + MALLOC(nn, strlen(suffix_ou) + strlen(asm_opt.output_file_name) + 36); + sprintf(nn, "%s.%s", asm_opt.output_file_name, suffix_ou); + FILE *ou = fopen(nn, "w"); + free(nn); + + for (k = 0; k < R_INF.total_reads; k++) { + recover_UC_Read(&qstr, &R_INF, k); + if(scb.a) { + gen_ori_seq0(qstr.seq, qstr.length, &tstr, &(scb.a[k]), k); str = tstr.seq; strl = tstr.length; + } else { + str = qstr.seq; strl = qstr.length; + } + + fwrite(">", 1, 1, ou); + fwrite(Get_NAME(R_INF, k), 1, Get_NAME_LENGTH(R_INF, k), ou); + fwrite("\n", 1, 1, ou); + fwrite(str, 1, strl, ou); + fwrite("\n", 1, 1, ou); + } + + fclose(ou); destory_UC_Read(&qstr); destory_UC_Read(&tstr); +} + + +void cal_ec_r(uint64_t n_thre, uint64_t round, uint64_t n_round, uint64_t n_a, uint64_t is_sv, uint64_t *tot_b, uint64_t *tot_e) +{ + // write_ec_reads("ec0.fa"); + + // fprintf(stderr, "[M::%s]\tn_thre::%lu, round::%lu, n_round::%lu, n_a::%lu, is_sv::%lu\n", __func__, n_thre, round, n_round, n_a, is_sv); + fprintf(stderr, "-0-[M::%s]\t# tqn::%lu, Ont base::%lu, # HiFi bases::%lu\n", __func__, R_INF.tqn, R_INF.tr[0], R_INF.tr[1]); + + ec_ovec_buf_t *b = NULL; uint64_t k, is_cr = (round&1); + (*tot_b) = (*tot_e) = 0; + + + b = gen_ec_ovec_buf_t(n_thre); + (*tot_e) += cal_ec_multiple(b, n_thre, n_a, tot_b); ///exit(1); + sl_ec_r(n_thre, n_a); + + for (k = 0; k < n_round; k++) { + (*tot_e) += cal_sec_ec_multiple(b, n_thre, n_a, k); + sl_ec_r(n_thre, n_a); + } + + fprintf(stderr, "-1-[M::%s]\t# tqn::%lu, Ont base::%lu, # HiFi bases::%lu\n", __func__, R_INF.tqn, R_INF.tr[0], R_INF.tr[1]); + + cal_update_ec_multiple(b, n_thre, n_a);///update overlaps + + // if(is_sv) kt_for(n_thre, worker_hap_dc_ec, b, n_a);///update overlaps + fprintf(stderr, "-2-[M::%s]\t# tqn::%lu, Ont base::%lu, # HiFi bases::%lu\n", __func__, R_INF.tqn, R_INF.tr[0], R_INF.tr[1]); + + if((!is_sv) || (is_sv && is_cr)) { + kt_for(n_thre, worker_hap_post_rev, b, n_a); + } + + fprintf(stderr, "-3-[M::%s]\t# tqn::%lu, Ont base::%lu, # HiFi bases::%lu\n", __func__, R_INF.tqn, R_INF.tr[0], R_INF.tr[1]); + // cal_sec_ec_multiple(b, n_thre, n_a, -1); + + // gen_sec_ec_multiple(b, n_thre, n_a); + + destroy_ec_ovec_buf_t(b); + + fprintf(stderr, "-4-[M::%s]\t# tqn::%lu, Ont base::%lu, # HiFi bases::%lu\n", __func__, R_INF.tqn, R_INF.tr[0], R_INF.tr[1]); + + // write_ec_reads("ec16.fa"); + + // uint64_t z; + // for (z = 0; z < scc.n; z++) { + // if(scc.f[z]) continue; + // fprintf(stderr, "[M::%s]\tid::%lu::%.*s\n", __func__, z, (int)Get_NAME_LENGTH(R_INF, z), Get_NAME((R_INF), z)); + // } +} + +void print_ov_dbg_paf(FILE *fp, char *ref_str, char *ref_id, int32_t ref_id_n, char *qry_str, char *qry_id, int32_t qry_id_n, uint64_t rs, uint64_t re, uint64_t rl, uint64_t qs, uint64_t qe, uint64_t ql, uint64_t rev, bit_extz_t *ez, char *ezh) +{ + uint64_t ci = 0; uint16_t c; uint32_t cl; + fprintf(fp, "%.*s\t%lu\t%lu\t%lu\t", qry_id_n, qry_id, ql, qs, qe); + fprintf(fp, "%c\t", "+-"[rev]); + fprintf(fp, "%.*s\t%lu\t%lu\t%lu\t", ref_id_n, ref_id, rl, rs, re); + fprintf(fp, "255\tcg:Z:"); + while (ci < ez->cigar.n) { + ci = pop_trace(&(ez->cigar), ci, &c, &cl); + fprintf(fp, "%u%c", cl, ezh[c]); + } + fprintf(fp, "\n"); +} + +static void *worker_ov_dbg_pipeline(void *data, int step, void *in) // callback for kt_pipeline() +{ + cal_ec_r_dbg_t *p = (cal_ec_r_dbg_t*)data; char cm[4]; cm[0] = 'M'; cm[1] = 'M'; cm[2] = 'I'; cm[3] = 'D'; + // cal_ec_r_dbg_step_t + if (step == 0) { // step 1: read a block of sequences + cal_ec_r_dbg_step_t *s; CALLOC(s, 1); + s->si = p->cn; p->cn += p->chunk_size; + if(p->cn > p->n_a) {p->cn = p->n_a;} s->ei = p->cn; + if(s->si >= s->ei) free(s); + else return s; + } else if (step == 1) { // step 2: alignment + cal_ec_r_dbg_step_t *s = (cal_ec_r_dbg_step_t*)in; + s->buf = gen_ec_ovec_buf_t(p->n_thread); CALLOC(s->res, p->n_thread); + kt_for(p->n_thread, worker_hap_ec_dbg_paf, s, (s->ei - s->si)); + destroy_ec_ovec_buf_t(s->buf); + return s; + } else if (step == 2) { // step 3: dump + cal_ec_r_dbg_step_t *s = (cal_ec_r_dbg_step_t*)in; uint64_t k, z; bit_extz_t ez; memset(&ez, 0, sizeof(ez)); + // UC_Read qu; UC_Read tu; init_UC_Read(&qu); init_UC_Read(&tu); + for (k = 0; k < p->n_thread; k++) { + for (z = 0; z < s->res[k].n; z++) { + ez.cigar.a = s->res[k].ec.a + s->res[k].a[z].bl; ez.cigar.n = ez.cigar.m = s->res[k].a[z].cc; + + // UC_Read_resize(qu, (s->res[k].a[z].qe - ((uint32_t)s->res[k].a[z].qns))); + // recover_UC_Read_sub_region(qu.seq, ((uint32_t)s->res[k].a[z].qns), (s->res[k].a[z].qe - ((uint32_t)s->res[k].a[z].qns)), 0, &R_INF, (s->res[k].a[z].qns>>32)); + + // UC_Read_resize(tu, (s->res[k].a[z].te - s->res[k].a[z].ts)); + // recover_UC_Read_sub_region(tu.seq, s->res[k].a[z].ts, s->res[k].a[z].te - s->res[k].a[z].ts, 0, &R_INF, s->res[k].a[z].tn); + + print_ov_dbg_paf(p->fp, NULL/**qu.seq**/, Get_NAME(R_INF, (s->res[k].a[z].qns>>32)), Get_NAME_LENGTH(R_INF, (s->res[k].a[z].qns>>32)), + NULL/**tu.seq**/, Get_NAME(R_INF, (s->res[k].a[z].tn)), Get_NAME_LENGTH(R_INF, (s->res[k].a[z].tn)), (uint32_t)s->res[k].a[z].qns, s->res[k].a[z].qe, Get_READ_LENGTH(R_INF, (s->res[k].a[z].qns>>32)), s->res[k].a[z].ts, s->res[k].a[z].te, Get_READ_LENGTH(R_INF, (s->res[k].a[z].tn)), s->res[k].a[z].rev, &ez, cm); + } + free(s->res[k].a); free(s->res[k].ec.a); + } + free(s->res); free(s); ///destory_UC_Read(&qu); destory_UC_Read(&tu); + } + return 0; +} + +void cal_ec_r_dbg(uint64_t n_thre, uint64_t n_a) +{ + char *paf = NULL; MALLOC(paf, (strlen(asm_opt.output_file_name)+64)); + sprintf(paf, "%s.ovlp.paf", asm_opt.output_file_name); + + cal_ec_r_dbg_t sl; memset(&sl, 0, sizeof(sl)); + sl.n_thread = n_thre; sl.n_a = n_a; sl.chunk_size = 2000; sl.cn = 0; sl.fp = fopen(paf, "w"); + + kt_pipeline(3, worker_ov_dbg_pipeline, &sl, 3); + + fclose(sl.fp); free(paf); +} + +void destroy_cc_v(cc_v *z) +{ + uint64_t k; + for (k = 0; k < z->m; k++) free(z->a[k].a); + free(z->f); free(z->a); + z->n = z->m = 0; z->f = NULL; z->a = NULL; +} + +void cal_ov_r(uint64_t n_thre, uint64_t n_a, uint64_t new_idx) +{ + ec_ovec_buf_t *b = NULL; + b = gen_ec_ovec_buf_t(n_thre); + if(new_idx) { + // kt_for(n_thre, worker_hap_dc_ec, b, n_a);///update overlaps + destroy_cc_v(&scc); destroy_cc_v(&scb); destroy_cc_v(&sca); + + ha_print_ovlp_stat_0(b, n_thre, n_a); + } else { + ha_print_ovlp_stat_1(b, n_thre, n_a); + destroy_cc_v(&scc); destroy_cc_v(&scb); destroy_cc_v(&sca); + } + + destroy_ec_ovec_buf_t(b); +} + +void sl_ec_r(uint64_t n_thre, uint64_t n_a) +{ + sl_v *b = NULL; uint64_t k; MALLOC(b, n_thre); + for (k = 0; k < n_thre; k++) { + b[k].a = NULL; b[k].n = b[k].m = 0; + init_UC_Read(&b[k].z); kv_init(b[k].q); + } + + kt_for(n_thre, worker_sl_ec, b, n_a);///debug_for_fix + + for (k = 0; k < n_thre; k++) { + free(b[k].a); destory_UC_Read(&b[k].z); kv_destroy(b[k].q); + } + free(b); +} + +void handle_chemical_r(uint64_t n_thre, uint64_t n_a) +{ + ec_ovec_buf_t *b = NULL; uint64_t k, chem_n = 0, dedup = 0; + b = gen_ec_ovec_buf_t(n_thre); + for (k = 0; k < n_thre; ++k) { + b->a[k].cnt[0] = 0; b->a[k].cnt[1] = 0; + } + + kt_for(n_thre, worker_hap_dc_ec_chemical_r, b, n_a); + + for (k = 0; k < n_thre; ++k) { + chem_n += b->a[k].cnt[0]; + b->a[k].cnt[0] = 0; b->a[k].cnt[1] = 1; + } + + kt_for(n_thre, worker_hap_dc_ec_chemical_r, b, n_a); + + for (k = 0; k < n_thre; ++k) { + dedup += b->a[k].cnt[0]; + b->a[k].cnt[1] = 2; + } + + kt_for(n_thre, worker_hap_dc_ec_chemical_r, b, n_a); + + fprintf(stderr, "[M::%s] # chimeric reads: %lu, # arcs:: %lu\n", __func__, chem_n, dedup); + + destroy_ec_ovec_buf_t(b); +} + +void handle_chemical_arc(uint64_t n_thre, uint64_t n_a) +{ + ec_ovec_buf_t *b = NULL; uint64_t k, chem_n = 0; + b = gen_ec_ovec_buf_t(n_thre); + for (k = 0; k < n_thre; ++k) { + b->a[k].cnt[0] = 0; b->a[k].cnt[1] = 0; + } + + kt_for(n_thre, worker_hap_dc_ec_chemical_arc, b, n_a); + + for (k = 0; k < n_thre; ++k) { + chem_n += b->a[k].cnt[0]; + b->a[k].cnt[0] = 0; b->a[k].cnt[1] = 1; + } + + kt_for(n_thre, worker_hap_dc_ec_chemical_arc, b, n_a); + + fprintf(stderr, "[M::%s] # chimeric reads: %lu\n", __func__, chem_n); + + destroy_ec_ovec_buf_t(b); +} + +uint8_t* gen_chemical_arc_rf(uint64_t n_thre, uint64_t n_a) +{ + ec_ovec_buf_t *b = NULL; uint64_t k, chem_n = 0; uint8_t *ra = NULL; + b = gen_ec_ovec_buf_t(n_thre); + for (k = 0; k < n_thre; ++k) { + b->a[k].cnt[0] = 0; b->a[k].cnt[1] = 0; + } + MALLOC(ra, n_a); ///memset(ra, -1, sizeof((*ra))*n_a); + b->cr = ra; + + kt_for(n_thre, worker_hap_dc_ec_chemical_arc_mark, b, n_a); + + for (k = 0; k < n_thre; ++k) { + chem_n += b->a[k].cnt[0]; + b->a[k].cnt[0] = 0; b->a[k].cnt[1] = 1; + } + + kt_for(n_thre, worker_hap_dc_ec_chemical_arc_mark, b, n_a); + + fprintf(stderr, "[M::%s] # chimeric reads: %lu\n", __func__, chem_n); + + b->cr = NULL; destroy_ec_ovec_buf_t(b); + return ra; +} + + +void gen_hc_polish(uint64_t n_thre, ma_ug_t *ug) +{ + ec_polish_buf_t b; memset(&b, 0, sizeof(b)); b.ug = ug; + uint64_t k, z, zn; + for (k = b.idx.n = 0; k < ug->u.n; k++) { + b.idx.n += ug->u.a[k].n; + } + MALLOC(b.idx.a, b.idx.n); + for (k = zn = 0; k < ug->u.n; k++) { + for (z = 0; z < ug->u.a[k].n; z++, zn++) { + b.idx.a[zn] = (k<<32)|z; + } + } + b.p = gen_ec_ovec_buf_t(n_thre); + + kt_for(n_thre, worker_ec_polish, &b, b.idx.n); + + destroy_ec_ovec_buf_t(b.p); free(b.idx.a); } \ No newline at end of file diff --git a/ecovlp.h b/ecovlp.h index 5e00910..3e1fad8 100644 --- a/ecovlp.h +++ b/ecovlp.h @@ -1,20 +1,20 @@ -#ifndef __ECOVLP_PARSER__ -#define __ECOVLP_PARSER__ - -#define __STDC_LIMIT_MACROS -#include -#include "Hash_Table.h" -#include "Process_Read.h" -#include "kdq.h" - - -void prt_chain(overlap_region_alloc *o); -void cal_ec_r(uint64_t n_thre, uint64_t round, uint64_t n_round, uint64_t n_a, uint64_t is_sv, uint64_t *tot_b, uint64_t *tot_e); -void sl_ec_r(uint64_t n_thre, uint64_t n_a); -void cal_ov_r(uint64_t n_thre, uint64_t n_a, uint64_t new_idx); -void handle_chemical_r(uint64_t n_thre, uint64_t n_a); -void handle_chemical_arc(uint64_t n_thre, uint64_t n_a); -uint8_t* gen_chemical_arc_rf(uint64_t n_thre, uint64_t n_a); -void cal_ec_r_dbg(uint64_t n_thre, uint64_t n_a); - +#ifndef __ECOVLP_PARSER__ +#define __ECOVLP_PARSER__ + +#define __STDC_LIMIT_MACROS +#include +#include "Hash_Table.h" +#include "Process_Read.h" +#include "kdq.h" + + +void prt_chain(overlap_region_alloc *o); +void cal_ec_r(uint64_t n_thre, uint64_t round, uint64_t n_round, uint64_t n_a, uint64_t is_sv, uint64_t *tot_b, uint64_t *tot_e); +void sl_ec_r(uint64_t n_thre, uint64_t n_a); +void cal_ov_r(uint64_t n_thre, uint64_t n_a, uint64_t new_idx); +void handle_chemical_r(uint64_t n_thre, uint64_t n_a); +void handle_chemical_arc(uint64_t n_thre, uint64_t n_a); +uint8_t* gen_chemical_arc_rf(uint64_t n_thre, uint64_t n_a); +void cal_ec_r_dbg(uint64_t n_thre, uint64_t n_a); + #endif \ No newline at end of file diff --git a/extract.cpp b/extract.cpp index b739a30..5b08d1f 100644 --- a/extract.cpp +++ b/extract.cpp @@ -1,173 +1,173 @@ -#include -#include -#include "Process_Read.h" -#include "khashl.h" -#include "kseq.h" - -typedef const char *cstr_t; -KHASHL_CSET_INIT(KH_LOCAL, strset_t, ss, cstr_t, kh_hash_str, kh_eq_str) -KHASHL_MAP_INIT(KH_LOCAL, hm64_t, h64, uint64_t, int, kh_hash_uint64, kh_eq_generic) -KSTREAM_INIT(gzFile, gzread, 65536) - -#define GFA_MALLOC(ptr, len) ((ptr) = (__typeof__(ptr))malloc((len) * sizeof(*(ptr)))) -#define GFA_REALLOC(ptr, len) ((ptr) = (__typeof__(ptr))realloc((ptr), (len) * sizeof(*(ptr)))) - -char *gfa_strdup(const char *src) -{ - int32_t len; - char *dst; - len = strlen(src); - GFA_MALLOC(dst, len + 1); - memcpy(dst, src, len + 1); - return dst; -} - -char *gfa_strndup(const char *src, size_t n) -{ - char *dst; - GFA_MALLOC(dst, n + 1); - strncpy(dst, src, n); - dst[n] = 0; - return dst; -} - -char **gv_read_list(const char *o, int *n_) -{ - int n = 0, m = 0; - char **s = 0; - *n_ = 0; - if (*o != '@') { - const char *q = o, *p; - for (p = q;; ++p) { - if (*p == ',' || *p == 0) { - if (n == m) { - m = m? m<<1 : 16; - GFA_REALLOC(s, m); - } - s[n++] = gfa_strndup(q, p - q); - if (*p == 0) break; - q = p + 1; - } - } - } else { - gzFile fp; - kstream_t *ks; - kstring_t str = {0,0,0}; - int dret; - - fp = gzopen(o + 1, "r"); - if (fp == 0) return 0; - ks = ks_init(fp); - while (ks_getuntil(ks, KS_SEP_LINE, &str, &dret) >= 0) { - char *p; - for (p = str.s; *p && !isspace(*p); ++p); - if (n == m) { - m = m? m<<1 : 16; - GFA_REALLOC(s, m); - } - s[n++] = gfa_strndup(str.s, p - str.s); - } - ks_destroy(ks); - gzclose(fp); - } - if (s) s = (char**)realloc(s, n * sizeof(char*)); - *n_ = n; - return s; -} - -void ha_extract_print(const All_reads *rs, int n_rounds, int n, char **list) -{ - hm64_t *h; - khint_t k; - int i, absent, m, l; - uint64_t j; - const ma_hit_t_alloc *ov[2] = { rs->paf, rs->reverse_paf }; - FILE *fp = stdout; - - if (n > 0) { - int max_len = 0; - char *s = 0; - strset_t *ss; - ss = ss_init(); - for (i = 0; i < n; ++i) - ss_put(ss, list[i], &absent); - for (j = 0; j < rs->total_reads; ++j) - if (max_len < (int)Get_NAME_LENGTH(*rs, j)) - max_len = Get_NAME_LENGTH(*rs, j); - GFA_MALLOC(s, max_len + 1); - h = h64_init(); - for (j = 0; j < rs->total_reads; ++j) { - strncpy(s, Get_NAME(*rs, j), Get_NAME_LENGTH(*rs, j)); - s[Get_NAME_LENGTH(*rs, j)] = 0; - if (ss_get(ss, s) != kh_end(ss)) { - k = h64_put(h, j, &absent); - kh_val(h, k) = -1; - } - } - free(s); - ss_destroy(ss); - } else return; - - for (m = 0; m < n_rounds; ++m) { - for (j = 0; j < rs->total_reads; ++j) { - for (l = 0; l < 2; ++l) { - const ma_hit_t_alloc *o = &ov[l][j]; - for (i = 0; i < (int)o->length; ++i) { - uint64_t q = Get_qn(o->buffer[i]); - uint64_t t = Get_tn(o->buffer[i]); - int q_hit = 0, t_hit = 0; - k = h64_get(h, q); - q_hit = (k < kh_end(h) && kh_val(h, k) < m); - k = h64_get(h, t); - t_hit = (k < kh_end(h) && kh_val(h, k) < m); - if ((!q_hit && !t_hit) || (q_hit && t_hit)) continue; - if (!q_hit) { - k = h64_put(h, q, &absent); - if (absent) kh_val(h, k) = m; - } - if (!t_hit) { - k = h64_put(h, t, &absent); - if (absent) kh_val(h, k) = m; - } - } - } - } - } - - for (j = 0; j < rs->total_reads; ++j) { - for (l = 0; l < 2; ++l) { - const ma_hit_t_alloc *o = &ov[l][j]; - for (i = 0; i < (int)o->length; ++i) { - uint64_t q = Get_qn(o->buffer[i]); - uint64_t t = Get_tn(o->buffer[i]); - int q_hit = 0, t_hit = 0; - q_hit = (h64_get(h, q) < kh_end(h)); - t_hit = (h64_get(h, t) < kh_end(h)); - if (!q_hit && !t_hit) continue; - fwrite(Get_NAME(*rs, q), 1, Get_NAME_LENGTH(*rs, q), fp); - fwrite("\t", 1, 1, fp); - fprintf(fp, "%lu\t", (unsigned long)Get_READ_LENGTH(*rs, q)); - fprintf(fp, "%d\t", Get_qs(o->buffer[i])); - fprintf(fp, "%d\t", Get_qe(o->buffer[i])); - fputs(o->buffer[i].rev? "-\t" : "+\t", fp); - fwrite(Get_NAME(*rs, t), 1, Get_NAME_LENGTH(*rs, t), fp); - fwrite("\t", 1, 1, fp); - fprintf(fp, "%lu\t", (unsigned long)Get_READ_LENGTH(*rs, t)); - fprintf(fp, "%d\t", Get_ts(o->buffer[i])); - fprintf(fp, "%d\t%d\t%d\t%d\n", Get_te(o->buffer[i]), o->buffer[i].ml, o->buffer[i].bl, !l); - } - } - } - - h64_destroy(h); -} - -void ha_extract_print_list(const All_reads *rs, int n_rounds, const char *o) -{ - int i, n; - char **list; - list = gv_read_list(o, &n); - ha_extract_print(rs, n_rounds, n, list); - for (i = 0; i < n; ++i) free(list[i]); - free(list); -} +#include +#include +#include "Process_Read.h" +#include "khashl.h" +#include "kseq.h" + +typedef const char *cstr_t; +KHASHL_CSET_INIT(KH_LOCAL, strset_t, ss, cstr_t, kh_hash_str, kh_eq_str) +KHASHL_MAP_INIT(KH_LOCAL, hm64_t, h64, uint64_t, int, kh_hash_uint64, kh_eq_generic) +KSTREAM_INIT(gzFile, gzread, 65536) + +#define GFA_MALLOC(ptr, len) ((ptr) = (__typeof__(ptr))malloc((len) * sizeof(*(ptr)))) +#define GFA_REALLOC(ptr, len) ((ptr) = (__typeof__(ptr))realloc((ptr), (len) * sizeof(*(ptr)))) + +char *gfa_strdup(const char *src) +{ + int32_t len; + char *dst; + len = strlen(src); + GFA_MALLOC(dst, len + 1); + memcpy(dst, src, len + 1); + return dst; +} + +char *gfa_strndup(const char *src, size_t n) +{ + char *dst; + GFA_MALLOC(dst, n + 1); + strncpy(dst, src, n); + dst[n] = 0; + return dst; +} + +char **gv_read_list(const char *o, int *n_) +{ + int n = 0, m = 0; + char **s = 0; + *n_ = 0; + if (*o != '@') { + const char *q = o, *p; + for (p = q;; ++p) { + if (*p == ',' || *p == 0) { + if (n == m) { + m = m? m<<1 : 16; + GFA_REALLOC(s, m); + } + s[n++] = gfa_strndup(q, p - q); + if (*p == 0) break; + q = p + 1; + } + } + } else { + gzFile fp; + kstream_t *ks; + kstring_t str = {0,0,0}; + int dret; + + fp = gzopen(o + 1, "r"); + if (fp == 0) return 0; + ks = ks_init(fp); + while (ks_getuntil(ks, KS_SEP_LINE, &str, &dret) >= 0) { + char *p; + for (p = str.s; *p && !isspace(*p); ++p); + if (n == m) { + m = m? m<<1 : 16; + GFA_REALLOC(s, m); + } + s[n++] = gfa_strndup(str.s, p - str.s); + } + ks_destroy(ks); + gzclose(fp); + } + if (s) s = (char**)realloc(s, n * sizeof(char*)); + *n_ = n; + return s; +} + +void ha_extract_print(const All_reads *rs, int n_rounds, int n, char **list) +{ + hm64_t *h; + khint_t k; + int i, absent, m, l; + uint64_t j; + const ma_hit_t_alloc *ov[2] = { rs->paf, rs->reverse_paf }; + FILE *fp = stdout; + + if (n > 0) { + int max_len = 0; + char *s = 0; + strset_t *ss; + ss = ss_init(); + for (i = 0; i < n; ++i) + ss_put(ss, list[i], &absent); + for (j = 0; j < rs->total_reads; ++j) + if (max_len < (int)Get_NAME_LENGTH(*rs, j)) + max_len = Get_NAME_LENGTH(*rs, j); + GFA_MALLOC(s, max_len + 1); + h = h64_init(); + for (j = 0; j < rs->total_reads; ++j) { + strncpy(s, Get_NAME(*rs, j), Get_NAME_LENGTH(*rs, j)); + s[Get_NAME_LENGTH(*rs, j)] = 0; + if (ss_get(ss, s) != kh_end(ss)) { + k = h64_put(h, j, &absent); + kh_val(h, k) = -1; + } + } + free(s); + ss_destroy(ss); + } else return; + + for (m = 0; m < n_rounds; ++m) { + for (j = 0; j < rs->total_reads; ++j) { + for (l = 0; l < 2; ++l) { + const ma_hit_t_alloc *o = &ov[l][j]; + for (i = 0; i < (int)o->length; ++i) { + uint64_t q = Get_qn(o->buffer[i]); + uint64_t t = Get_tn(o->buffer[i]); + int q_hit = 0, t_hit = 0; + k = h64_get(h, q); + q_hit = (k < kh_end(h) && kh_val(h, k) < m); + k = h64_get(h, t); + t_hit = (k < kh_end(h) && kh_val(h, k) < m); + if ((!q_hit && !t_hit) || (q_hit && t_hit)) continue; + if (!q_hit) { + k = h64_put(h, q, &absent); + if (absent) kh_val(h, k) = m; + } + if (!t_hit) { + k = h64_put(h, t, &absent); + if (absent) kh_val(h, k) = m; + } + } + } + } + } + + for (j = 0; j < rs->total_reads; ++j) { + for (l = 0; l < 2; ++l) { + const ma_hit_t_alloc *o = &ov[l][j]; + for (i = 0; i < (int)o->length; ++i) { + uint64_t q = Get_qn(o->buffer[i]); + uint64_t t = Get_tn(o->buffer[i]); + int q_hit = 0, t_hit = 0; + q_hit = (h64_get(h, q) < kh_end(h)); + t_hit = (h64_get(h, t) < kh_end(h)); + if (!q_hit && !t_hit) continue; + fwrite(Get_NAME(*rs, q), 1, Get_NAME_LENGTH(*rs, q), fp); + fwrite("\t", 1, 1, fp); + fprintf(fp, "%lu\t", (unsigned long)Get_READ_LENGTH(*rs, q)); + fprintf(fp, "%d\t", Get_qs(o->buffer[i])); + fprintf(fp, "%d\t", Get_qe(o->buffer[i])); + fputs(o->buffer[i].rev? "-\t" : "+\t", fp); + fwrite(Get_NAME(*rs, t), 1, Get_NAME_LENGTH(*rs, t), fp); + fwrite("\t", 1, 1, fp); + fprintf(fp, "%lu\t", (unsigned long)Get_READ_LENGTH(*rs, t)); + fprintf(fp, "%d\t", Get_ts(o->buffer[i])); + fprintf(fp, "%d\t%d\t%d\t%d\n", Get_te(o->buffer[i]), o->buffer[i].ml, o->buffer[i].bl, !l); + } + } + } + + h64_destroy(h); +} + +void ha_extract_print_list(const All_reads *rs, int n_rounds, const char *o) +{ + int i, n; + char **list; + list = gv_read_list(o, &n); + ha_extract_print(rs, n_rounds, n, list); + for (i = 0; i < n; ++i) free(list[i]); + free(list); +} diff --git a/gchain_map.cpp b/gchain_map.cpp index 41bb0fb..d6a254e 100644 --- a/gchain_map.cpp +++ b/gchain_map.cpp @@ -1,204 +1,204 @@ -#include -#include -#include -#include -#include -#include "kseq.h" // FASTA/Q parser -#include "kavl.h" -#include "khash.h" -#include "kalloc.h" -#include "kthread.h" -#include "inter.h" -#include "Overlaps.h" -#include "CommandLines.h" -#include "htab.h" -#include "Hash_Table.h" -#include "Correct.h" -#include "Process_Read.h" -#include "Assembly.h" -#include "gchain_map.h" -KSEQ_INIT(gzFile, gzread) -void ul_map_lchain(ha_abufl_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, - int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut); - -typedef struct { // global data structure for kt_pipeline() - const void *ha_flt_tab; - const ha_pt_t *ha_idx; - const mg_idxopt_t *opt; - const ma_ug_t *ug; - const asg_t *rg; - const ug_opt_t *uopt; - const ul_idx_t *uu; - ucr_file_t *ucr_s; - kseq_t *ks; - int64_t chunk_size; - uint64_t n_thread; - uint64_t total_base; - uint64_t total_pair; - uint64_t num_bases, num_corrected_bases, num_recorrected_bases; - uint64_t remap, mini_cut; -} gmap_t; - -typedef struct { // data structure for each step in kt_pipeline() - const mg_idxopt_t *opt; - const void *ha_flt_tab; - const ha_pt_t *ha_idx; - const ma_ug_t *ug; - const asg_t *rg; - const ug_opt_t *uopt; - const ul_idx_t *uu; - int n, m, sum_len; - uint64_t *len, id; - char **seq; - // ha_mzl_v *mzs;///useless - // st_mt_t *sps;///useless - // mg_gchains_t **gcs;///useless - mg_tbuf_t **buf;///useless - ha_ovec_buf_t **hab; - kv_ul_ov_t *res; - // glchain_t *ll; - // gdpchain_t *gdp; - // glchain_t *sec_ll; - uint64_t num_bases, num_corrected_bases, num_recorrected_bases, mini_cut; - int64_t n_thread; -} sstep_t; - -/** -static void worker_ul_map(void *data, long i, int tid) // callback for kt_for() -{ - sstep_t *s = (sstep_t*)data; - ha_ovec_buf_t *b = s->hab[tid]; - kv_ul_ov_t *res = (s->res?(&(s->res[tid])):(NULL)); - mg_tbuf_t *buf = (s->buf?s->buf[tid]:NULL); - int64_t winLen = MIN((((double)THRESHOLD_MAX_SIZE)/s->opt->diff_ec_ul), WINDOW); - int fully_cov, abnormal; - assert(UL_INF.a[s->id+i].rlen == s->len[i]); - // if(s->id+i!=43) return; - - ul_map_lchain(b->abl, i, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->olist_hp, &b->clist, s->opt->bw_thres, - s->opt->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), s->mini_cut, 0); - - clear_Cigar_record(&b->cigar1); - clear_Round2_alignment(&b->round2); - - b->self_read.seq = s->seq[i]; b->self_read.length = s->len[i]; b->self_read.size = 0; - lchain_align(&b->olist, s->uu, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, - &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 1, &fully_cov, &abnormal, s->opt->diff_ec_ul, winLen, NULL); - - // gl_chain_refine(&b->olist, &b->correct, &b->hap, bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], km); - gl_chain_refine_advance_combine(s->buf[tid], &(UL_INF.a[s->id+i]), &b->olist, &b->correct, &b->hap, &(s->sps[tid]), bl, &(s->gdp[tid]), s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, tid, NULL); - - memset(&b->self_read, 0, sizeof(b->self_read)); - if(UL_INF.a[s->id+i].dd) { - free(s->seq[i]); s->seq[i] = NULL; b->num_correct_base++; - } - s->hab[tid]->num_read_base++; -} - -static void *worker_gmap_work_ovec_pip(void *data, int step, void *in) // callback for kt_pipeline() -{ - gmap_t *p = (gmap_t*)data; - if (step == 0) { // step 1: read a block of sequences - int32_t ret; uint64_t l; sstep_t *s; CALLOC(s, 1); - s->ha_flt_tab = p->ha_flt_tab; s->ha_idx = p->ha_idx; s->id = p->total_pair; - s->opt = p->opt; s->uu = p->uu; s->uopt = p->uopt; s->rg = p->rg; s->mini_cut = p->mini_cut;///need set - while ((ret = kseq_read(p->ks)) >= 0) { - if (p->ks->seq.l < (uint64_t)p->opt->k) continue; - if (s->n == s->m) { - s->m = s->m < 16? 16 : s->m + (s->n>>1); - REALLOC(s->len, s->m); - REALLOC(s->seq, s->m); - } - if(!(p->remap)) { - append_ul_t(&UL_INF, NULL, p->ks->name.s, p->ks->name.l, NULL, 0, NULL, 0, P_CHAIN_COV, s->uopt, 0); - } - l = p->ks->seq.l; - MALLOC(s->seq[s->n], l); - s->sum_len += l; - memcpy(s->seq[s->n], p->ks->seq.s, l); - s->len[s->n++] = l; - if (s->sum_len >= p->chunk_size) break; - } - p->total_pair += s->n; - if (s->sum_len == 0) free(s); - else return s; - } - else if (step == 1) { // step 2: alignment - sstep_t *s = (sstep_t*)in; uint64_t i; - CALLOC(s->hab, p->n_thread); - CALLOC(s->buf, p->n_thread); - if(!(p->remap)) CALLOC(s->res, p->n_thread);//for results - for (i = 0; i < p->n_thread; ++i) { - s->hab[i] = ha_ovec_init(0, 0, 1); s->buf[i] = mg_tbuf_init(); - } - // kt_for(p->n_thread, worker_for_ul_scall_alignment, s, s->n); - - for (i = 0; i < p->n_thread; ++i) { - s->num_bases += s->hab[i]->num_read_base; - s->num_corrected_bases += s->hab[i]->num_correct_base; - s->num_recorrected_bases += s->hab[i]->num_recorrect_base; - ha_ovec_destroy(s->hab[i]); mg_tbuf_destroy(s->buf[i]); - } - free(s->hab); free(s->buf); - return s; - } - else if (step == 2) { // step 3: dump - sstep_t *s = (sstep_t*)in; - uint64_t i, rid, sn = s->n; - p->num_bases += s->num_bases; - p->num_corrected_bases += s->num_corrected_bases; - p->num_recorrected_bases += s->num_recorrected_bases; - if(!(p->remap)) { - for (i = 0; i < p->n_thread; ++i) { - push_uc_block_t(s->uopt, &(s->res[i]), s->seq, s->len, s->id); - kv_destroy(s->res[i]); - } - free(s->res); - - for (i = 0; i < sn; ++i) { - rid = s->id + i; - if((UL_INF.n <= rid) || (UL_INF.n > rid && UL_INF.a[rid].rlen != s->len[i])) {///reads without alignment - append_ul_t(&UL_INF, &rid, NULL, 0, s->seq[i], s->len[i], NULL, 0, P_CHAIN_COV, s->uopt, 0); - } - free(s->seq[i]); - } - } else { - for (i = 0; i < sn; ++i) { - rid = s->id + i; - if(UL_INF.a[rid].dd == 0 && p->ucr_s && p->ucr_s->flag == 1) { - assert(s->seq[i]); - ///for debug interval - write_compress_base_disk(p->ucr_s->fp, rid, s->seq[i], s->len[i], &(p->ucr_s->u)); - } - free(s->seq[i]); - } - } - free(s->len); free(s->seq); free(s); - } - return 0; -} -**/ - -// int gmap_work_ovec(gmap_t* sl, const enzyme *fn) -// { -// double index_time = yak_realtime(); -// int i; - -// init_all_ul_t(&UL_INF, &R_INF); -// for (i = 0; i < fn->n; i++){ -// gzFile fp; -// if ((fp = gzopen(fn->a[i], "r")) == 0) return 0; -// sl->ks = kseq_init(fp); -// kt_pipeline(3, worker_gmap_work_ovec_pip, sl, 3); -// kseq_destroy(sl->ks); -// gzclose(fp); -// } -// sl->hits.total_base = sl->total_base; -// sl->hits.total_pair = sl->total_pair; -// fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); -// fprintf(stderr, "[M::%s::] ==> # reads: %lu, # bases: %lu\n", __func__, UL_INF.n, sl->total_base); -// fprintf(stderr, "[M::%s::] ==> # bases: %lu; # corrected bases: %lu; # recorrected bases: %lu\n", -// __func__, sl->num_bases, sl->num_corrected_bases, sl->num_recorrected_bases); -// gen_ul_vec_rid_t(&UL_INF, &R_INF, NULL); -// return 1; +#include +#include +#include +#include +#include +#include "kseq.h" // FASTA/Q parser +#include "kavl.h" +#include "khash.h" +#include "kalloc.h" +#include "kthread.h" +#include "inter.h" +#include "Overlaps.h" +#include "CommandLines.h" +#include "htab.h" +#include "Hash_Table.h" +#include "Correct.h" +#include "Process_Read.h" +#include "Assembly.h" +#include "gchain_map.h" +KSEQ_INIT(gzFile, gzread) +void ul_map_lchain(ha_abufl_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, + int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut); + +typedef struct { // global data structure for kt_pipeline() + const void *ha_flt_tab; + const ha_pt_t *ha_idx; + const mg_idxopt_t *opt; + const ma_ug_t *ug; + const asg_t *rg; + const ug_opt_t *uopt; + const ul_idx_t *uu; + ucr_file_t *ucr_s; + kseq_t *ks; + int64_t chunk_size; + uint64_t n_thread; + uint64_t total_base; + uint64_t total_pair; + uint64_t num_bases, num_corrected_bases, num_recorrected_bases; + uint64_t remap, mini_cut; +} gmap_t; + +typedef struct { // data structure for each step in kt_pipeline() + const mg_idxopt_t *opt; + const void *ha_flt_tab; + const ha_pt_t *ha_idx; + const ma_ug_t *ug; + const asg_t *rg; + const ug_opt_t *uopt; + const ul_idx_t *uu; + int n, m, sum_len; + uint64_t *len, id; + char **seq; + // ha_mzl_v *mzs;///useless + // st_mt_t *sps;///useless + // mg_gchains_t **gcs;///useless + mg_tbuf_t **buf;///useless + ha_ovec_buf_t **hab; + kv_ul_ov_t *res; + // glchain_t *ll; + // gdpchain_t *gdp; + // glchain_t *sec_ll; + uint64_t num_bases, num_corrected_bases, num_recorrected_bases, mini_cut; + int64_t n_thread; +} sstep_t; + +/** +static void worker_ul_map(void *data, long i, int tid) // callback for kt_for() +{ + sstep_t *s = (sstep_t*)data; + ha_ovec_buf_t *b = s->hab[tid]; + kv_ul_ov_t *res = (s->res?(&(s->res[tid])):(NULL)); + mg_tbuf_t *buf = (s->buf?s->buf[tid]:NULL); + int64_t winLen = MIN((((double)THRESHOLD_MAX_SIZE)/s->opt->diff_ec_ul), WINDOW); + int fully_cov, abnormal; + assert(UL_INF.a[s->id+i].rlen == s->len[i]); + // if(s->id+i!=43) return; + + ul_map_lchain(b->abl, i, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->olist_hp, &b->clist, s->opt->bw_thres, + s->opt->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), s->mini_cut, 0); + + clear_Cigar_record(&b->cigar1); + clear_Round2_alignment(&b->round2); + + b->self_read.seq = s->seq[i]; b->self_read.length = s->len[i]; b->self_read.size = 0; + lchain_align(&b->olist, s->uu, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, + &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 1, &fully_cov, &abnormal, s->opt->diff_ec_ul, winLen, NULL); + + // gl_chain_refine(&b->olist, &b->correct, &b->hap, bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], km); + gl_chain_refine_advance_combine(s->buf[tid], &(UL_INF.a[s->id+i]), &b->olist, &b->correct, &b->hap, &(s->sps[tid]), bl, &(s->gdp[tid]), s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, tid, NULL); + + memset(&b->self_read, 0, sizeof(b->self_read)); + if(UL_INF.a[s->id+i].dd) { + free(s->seq[i]); s->seq[i] = NULL; b->num_correct_base++; + } + s->hab[tid]->num_read_base++; +} + +static void *worker_gmap_work_ovec_pip(void *data, int step, void *in) // callback for kt_pipeline() +{ + gmap_t *p = (gmap_t*)data; + if (step == 0) { // step 1: read a block of sequences + int32_t ret; uint64_t l; sstep_t *s; CALLOC(s, 1); + s->ha_flt_tab = p->ha_flt_tab; s->ha_idx = p->ha_idx; s->id = p->total_pair; + s->opt = p->opt; s->uu = p->uu; s->uopt = p->uopt; s->rg = p->rg; s->mini_cut = p->mini_cut;///need set + while ((ret = kseq_read(p->ks)) >= 0) { + if (p->ks->seq.l < (uint64_t)p->opt->k) continue; + if (s->n == s->m) { + s->m = s->m < 16? 16 : s->m + (s->n>>1); + REALLOC(s->len, s->m); + REALLOC(s->seq, s->m); + } + if(!(p->remap)) { + append_ul_t(&UL_INF, NULL, p->ks->name.s, p->ks->name.l, NULL, 0, NULL, 0, P_CHAIN_COV, s->uopt, 0); + } + l = p->ks->seq.l; + MALLOC(s->seq[s->n], l); + s->sum_len += l; + memcpy(s->seq[s->n], p->ks->seq.s, l); + s->len[s->n++] = l; + if (s->sum_len >= p->chunk_size) break; + } + p->total_pair += s->n; + if (s->sum_len == 0) free(s); + else return s; + } + else if (step == 1) { // step 2: alignment + sstep_t *s = (sstep_t*)in; uint64_t i; + CALLOC(s->hab, p->n_thread); + CALLOC(s->buf, p->n_thread); + if(!(p->remap)) CALLOC(s->res, p->n_thread);//for results + for (i = 0; i < p->n_thread; ++i) { + s->hab[i] = ha_ovec_init(0, 0, 1); s->buf[i] = mg_tbuf_init(); + } + // kt_for(p->n_thread, worker_for_ul_scall_alignment, s, s->n); + + for (i = 0; i < p->n_thread; ++i) { + s->num_bases += s->hab[i]->num_read_base; + s->num_corrected_bases += s->hab[i]->num_correct_base; + s->num_recorrected_bases += s->hab[i]->num_recorrect_base; + ha_ovec_destroy(s->hab[i]); mg_tbuf_destroy(s->buf[i]); + } + free(s->hab); free(s->buf); + return s; + } + else if (step == 2) { // step 3: dump + sstep_t *s = (sstep_t*)in; + uint64_t i, rid, sn = s->n; + p->num_bases += s->num_bases; + p->num_corrected_bases += s->num_corrected_bases; + p->num_recorrected_bases += s->num_recorrected_bases; + if(!(p->remap)) { + for (i = 0; i < p->n_thread; ++i) { + push_uc_block_t(s->uopt, &(s->res[i]), s->seq, s->len, s->id); + kv_destroy(s->res[i]); + } + free(s->res); + + for (i = 0; i < sn; ++i) { + rid = s->id + i; + if((UL_INF.n <= rid) || (UL_INF.n > rid && UL_INF.a[rid].rlen != s->len[i])) {///reads without alignment + append_ul_t(&UL_INF, &rid, NULL, 0, s->seq[i], s->len[i], NULL, 0, P_CHAIN_COV, s->uopt, 0); + } + free(s->seq[i]); + } + } else { + for (i = 0; i < sn; ++i) { + rid = s->id + i; + if(UL_INF.a[rid].dd == 0 && p->ucr_s && p->ucr_s->flag == 1) { + assert(s->seq[i]); + ///for debug interval + write_compress_base_disk(p->ucr_s->fp, rid, s->seq[i], s->len[i], &(p->ucr_s->u)); + } + free(s->seq[i]); + } + } + free(s->len); free(s->seq); free(s); + } + return 0; +} +**/ + +// int gmap_work_ovec(gmap_t* sl, const enzyme *fn) +// { +// double index_time = yak_realtime(); +// int i; + +// init_all_ul_t(&UL_INF, &R_INF); +// for (i = 0; i < fn->n; i++){ +// gzFile fp; +// if ((fp = gzopen(fn->a[i], "r")) == 0) return 0; +// sl->ks = kseq_init(fp); +// kt_pipeline(3, worker_gmap_work_ovec_pip, sl, 3); +// kseq_destroy(sl->ks); +// gzclose(fp); +// } +// sl->hits.total_base = sl->total_base; +// sl->hits.total_pair = sl->total_pair; +// fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); +// fprintf(stderr, "[M::%s::] ==> # reads: %lu, # bases: %lu\n", __func__, UL_INF.n, sl->total_base); +// fprintf(stderr, "[M::%s::] ==> # bases: %lu; # corrected bases: %lu; # recorrected bases: %lu\n", +// __func__, sl->num_bases, sl->num_corrected_bases, sl->num_recorrected_bases); +// gen_ul_vec_rid_t(&UL_INF, &R_INF, NULL); +// return 1; // } \ No newline at end of file diff --git a/gchain_map.h b/gchain_map.h index c2d53a4..284d59a 100644 --- a/gchain_map.h +++ b/gchain_map.h @@ -1,6 +1,6 @@ -#ifndef __INTER__ -#define __INTER__ -#include "Overlaps.h" -#include "Process_Read.h" - -#endif +#ifndef __INTER__ +#define __INTER__ +#include "Overlaps.h" +#include "Process_Read.h" + +#endif diff --git a/gfa_ut.cpp b/gfa_ut.cpp index 00ff109..54d5ab4 100644 --- a/gfa_ut.cpp +++ b/gfa_ut.cpp @@ -1,18220 +1,18238 @@ -#include -#include -#include -#include -#include -#include "kdq.h" -#include "kthread.h" -#include "gfa_ut.h" -#include "CommandLines.h" -#include "Correct.h" -#include "inter.h" -#include "Overlaps.h" -#include "hic.h" -#include "Purge_Dups.h" - -#define generic_key(x) (x) -KRADIX_SORT_INIT(srt64, uint64_t, generic_key, 8) -#define OU_NOISY 2 -#define ASG_ET_MERGEABLE 0 -#define ASG_ET_TIP 1 -#define ASG_ET_MULTI_OUT 2 -#define ASG_ET_MULTI_NEI 3 -#define UL_TRAV_HERATE 0.2 -#define UL_TRAV_FT_RATE 0.8 - -KDQ_INIT(uint64_t) - -typedef struct { size_t n, m; char *a; } asgc8_v; - -typedef struct { - asg64_v cnt; - asg64_v idx_a; - uint64_t idx_n; - asg_t *ext; - uint64_t a_n; -} asg_ext_t; - -typedef struct { - uint32_t v, uid, off; -} usg_arc_mm_t; - -typedef struct { - size_t n, m; - usg_arc_mm_t *a; -} usg_arc_mm_warp; - -typedef struct { - uint64_t ul; - uint32_t v; - uint32_t ol:31, del:1; - uint32_t ou; - uint64_t idx; -} usg_arc_t; - -typedef struct { - size_t n, m; - usg_arc_t *a; -} usg_arc_warp; - -typedef struct { - uint32_t mm, occ; - uint32_t len; - usg_arc_warp arc[2]; - usg_arc_mm_warp arc_mm[2]; - uint8_t del, telo; -} usg_seq_t; - -#define usg_arc_key(p) ((p).v) -KRADIX_SORT_INIT(usg_arc_srt, usg_arc_t, usg_arc_key, member_size(usg_arc_t, v)) - -#define usg_arc_mm_key(p) ((p).v) -KRADIX_SORT_INIT(usg_arc_mm_srt, usg_arc_mm_t, usg_arc_mm_key, member_size(usg_arc_mm_t, v)) - -typedef struct { - uint32_t *a; - size_t n, m; -} mmap_t; - -typedef struct { - usg_seq_t *a; - size_t n, m; - kvec_t(mmap_t) mp; -} usg_t; - -#define usg_arc_a(g, v) ((g)->a[(v)>>1].arc[(v)&1].a) -#define usg_arc_n(g, v) ((g)->a[(v)>>1].arc[(v)&1].n) - -typedef struct{ - int64_t tipsLen; - float tip_drop_ratio; - int64_t stops_threshold; - float chimeric_rate; - float drop_ratio; - - bub_label_t* b_mask_t; - int64_t clean_round; - double min_ovlp_drop_ratio; - double max_ovlp_drop_ratio; - double hom_check_drop_rate; - double min_path_drop_ratio; - double max_path_drop_ratio; - int64_t max_tip, max_tip_hifi; - uint32_t is_trio; -}ulg_opt_t; - -typedef struct { - uint32_t hid; - uint32_t qs, qe, ts, te; - uint32_t qs_k, qe_k, ts_k, te_k; - uint8_t is_rev:6, is_del:1, is_ct:1; -} ul2ul_t; - -typedef struct { - ul2ul_t *a; - size_t n, m; - uint32_t id:31, is_del:1; - uint32_t cn; - // uint8_t is_consist; -} ul2ul_item_t; - -typedef struct { - uint32_t v, s, e, n; -} uinfo_srt_t; - -typedef struct { - size_t n, m; - uinfo_srt_t *a; -} uinfo_srt_warp_t; - -typedef struct { - uint32_t *uc, *hc, *raw_uc; - uinfo_srt_warp_t *iug_a; - uint32_t *iug_idx; - uint64_t *iug_b; -} ul_cov_t; - - -typedef struct { - asg_t *bg; - uint32_t *w_n, *a_n; -} ul_bg_t; - -// typedef struct { -// uint32_t v, n, wn; -// } ul_tra_t; - -// typedef struct { -// kvec_t(ul_tra_t) arc; -// kvec_t(uint32_t) idx; -// } ul_tra_idx_t; - -// #define iug_tra_arc_n(z, v) ((z)->idx.a[(v)+1]-(z)->idx.a[(v)]) -// #define iug_tra_arc_a(z, v) ((z)->arc.a + (z)->idx.a[(v)]) - -typedef struct { - ul2ul_item_t *a; - size_t n, m; - uint64_t uln, gn, tot; - uint32_t *item_idx; - asg_t *i_g; ma_ug_t *i_ug; - ma_ug_t *hybrid_ug; - usg_t *h_usg; - ul_cov_t cc; - ul_bg_t bg; - asg64_v *iug_tra; - uinfo_srt_warp_t *iug_seq; uint64_t iug_cov_thre; - uint8_t *telo; -} ul2ul_idx_t; - -#define ul2ul_srt_key(p) ((p).hid) -KRADIX_SORT_INIT(ul2ul_srt, ul2ul_t, ul2ul_srt_key, member_size(ul2ul_t, hid)) - -typedef struct { - kvec_t(uint64_t) ref; - kvec_t(uint64_t) pat; - kvec_t(uint64_t) pat_cor; - kvec_t(uint8_t) g_flt; - kvec_t(uint8_t) m_dir; - kvec_t(int64_t) m_score; - uint64_t n, m; -} path_dp_t; - -typedef struct { - uint32_t p; // the optimal parent vertex - uint32_t d; // the shortest distance from the initial vertex - uint64_t c; // max count of positive reads - uint64_t m; // max count of negative reads - // uint32_t np; // max count of non-positive reads - uint32_t nc; // max count of reads, no matter positive or negative - uint32_t r:31, s:1; // r: the number of remaining incoming arc; s: state - //s: state, s=0, this edge has not been visited, otherwise, s=1 -} uinfo_t; - - - -// #define uinfo_srt_t_c_key(p) ((p).se) -// KRADIX_SORT_INIT(uinfo_srt_t_c, uinfo_srt_t, uinfo_srt_t_c_key, member_size(uinfo_srt_t, se)) - -typedef struct { - ///all information for each node - kvec_t(uinfo_t) a; - // kvec_t(uint32_t) u; - kvec_t(uint32_t) S; // set of vertices without parents, nodes with all incoming edges visited - kvec_t(uint32_t) T; // set of tips - kvec_t(uint32_t) b; // visited vertices - kvec_t(uint32_t) e; // visited edges/arcs - // kvec_t(uinfo_srt_t) srt; - kvec_t(uint8_t) us; - path_dp_t dp; -} ubuf_t; - -typedef struct{ - uint32_t bid, beg, occ; - uint32_t n_path, path_idx, path_occ; -}ul_sub_path_t; - - -typedef struct{ - ma_ug_t *buf_ug; - kvec_t(uint64_t) buf; -}ul_path_t; - -typedef struct{ - kvec_t(uint64_t) idx; - kvec_t(uint64_t) srt; - uint64_t ul_n; -}ul_path_srt_t; - -typedef struct{ - size_t n, m; - uint64_t *a; - uint32_t cn:31, is_cir:1; -}ul_str_t; - -typedef struct{ - kvec_t(uint64_t) idx; - kvec_t(uint64_t) occ; - kvec_t(ul_str_t) str; -}ul_str_idx_t; - -typedef struct{ - uint32_t v, pi, ai; - uint32_t k:31, is_gc:1; - int32_t dis; -} integer_seq_t; - -typedef struct{ - size_t n, m; - integer_seq_t *a; -} kv_integer_seq_t; - -typedef struct{ - uint32_t tk, vq, sc; - uint64_t tn_rev_qk; -} integer_aln_t; - -#define integer_aln_t_vqk_key(x) ((x).tn_rev_qk) -KRADIX_SORT_INIT(integer_aln_t_srt, integer_aln_t, integer_aln_t_vqk_key, member_size(integer_aln_t, tn_rev_qk)) - -typedef struct { - size_t n, m; - integer_aln_t *a; -} integer_aln_vec_t; - -typedef struct{ - uint32_t s, e, v; - uint64_t sc; - uint32_t q_sidx, q_eidx; - uint32_t t_sidx, t_eidx; -} ul_chain_t; - - - -typedef struct{ - uint64_t qidx_occ; - uint32_t tidx_occ; - uint32_t chain_id:31, is_rev:1; -} ul_snp_t; - -#define ul_snp_t_srt_key(x) ((x).qidx_occ) -KRADIX_SORT_INIT(ul_snp_t_srt, ul_snp_t, ul_snp_t_srt_key, member_size(ul_snp_t, qidx_occ)) - - -typedef struct { - uint32_t occ, nid; -} poa_nid_t; - -typedef struct { - uint64_t ul; - uint32_t v; -} poa_arc_t; - -#define poa_arc_key(a) ((a).ul) -KRADIX_SORT_INIT(poa_arc_srt, poa_arc_t, poa_arc_key, member_size(poa_arc_t, ul)) - -typedef struct { - kvec_t(uint32_t) ind; - kvec_t(uint32_t) stack; - kvec_t(uint32_t) res; - kvec_t(uint32_t) res2nid; - kvec_t(uint64_t) aln; -} topo_srt_t; - -typedef struct { - kvec_t(int64_t) sc; - kvec_t(uint8_t) dir; - kvec_t(uint64_t) prefix; - uint64_t n, m; -} poa_dp_t; - -#define poa_dp_idx(dp, x, y) ((dp).m*(x)+(y)) -#define e_pdp 0 -#define ue_pdp 1 -#define lstr_dp 2 -#define lg_dp 3 - -typedef struct{ - uint64_t pge, ule; - uint32_t ulid; -} emap_t; - -#define emap_t_srt_key(x) ((x).pge) -KRADIX_SORT_INIT(emap_t_srt, emap_t, emap_t_srt_key, member_size(emap_t, pge)) - -typedef struct { - kvec_t(poa_nid_t) seq; - kvec_t(poa_arc_t) arc; - kvec_t(uint64_t) idx; - uint32_t update_seq; - uint32_t update_arc; - topo_srt_t srt_b; - // poa_dp_t dp; - kvec_t(emap_t) e_idx; - ubuf_t bb; -} poa_g_t; - -typedef struct { - kv_integer_seq_t q; - kv_integer_seq_t t; - integer_aln_vec_t b; - kvec_t(int64_t) f; - kvec_t(int64_t) p; - kvec_t(uint64_t) o; - kvec_t(uint64_t) u; - kvec_t(uint32_t) vis; - // kvec_t(uint64_t) srt; - // kvec_t(uint64_t) v; - // kvec_t(uint64_t) u; - // kvec_t(uint64_t) d; - kvec_t(ul_chain_t) sc; - kvec_t(ul_snp_t) snp; - poa_g_t pg; - kvec_t(uint64_t) res_dump; - uint64_t n_correct, n_circle; -}integer_t; - -typedef struct { - // ul_resolve_t *u; - integer_t *buf; - uint64_t n_thread; -}integer_ml_t; - -typedef struct { - asg_t *g; - uint64_t n[2], tot; -} cul_g_t; - -typedef struct{ - ug_opt_t *uopt; - ma_ug_t *init_ug; - ma_ug_t *l0_ug; - ma_ug_t *l1_ug; - asg_t *sg; - bubble_type *bub; - all_ul_t *idx; - ul_path_t path; - uint8_t *r_het; - ubuf_t buf; - ul_str_idx_t pstr; - integer_ml_t str_b; - cul_g_t *cg; - ul2ul_idx_t uovl; - // ul_path_srt_t psrt; -}ul_resolve_t; - -typedef struct{ - ug_opt_t *uopt; - asg_t *sg; - ma_ug_t *ug; - buf_t b; - uint32_t *idx, *bid; - uint32_t idx_n, bid_n; - uint8_t is_ou; - uint8_t is_trio; - int64_t max_ext; - uint64_t tlen; - double len_rat; - double ou_rat; - int64_t min_ou; -}ug_clean_t; - -void deep_graph_clean(ug_opt_t *uopt, asg_t *sg, uint8_t is_ou, uint8_t is_trio, int64_t max_ext, -double min_ovlp_drop_ratio, double max_ovlp_drop_ratio, double ou_rat, int64_t min_ou, int64_t clean_round, int64_t long_tip); - -void init_integer_ml_t(integer_ml_t *x, ul_resolve_t *u, uint64_t n_thread) -{ - memset(x, 0, sizeof((*x))); - x->n_thread = n_thread; ///x->u = u; - CALLOC(x->buf, n_thread); -} - -int32_t if_sup_chimeric(ma_hit_t_alloc* src, uint64_t rLen, asg64_v *b, int if_exact); - -void print_edge(asg_arc_t *t, const char *cmd) -{ - uint32_t v = t->ul>>32, w = t->v; - fprintf(stderr, "%s: v->%u(%c)[%u], w->%u(%c)[%u], el->%u, del->%u\n", cmd, v>>1, "+-"[v&1], v, w>>1, "+-"[w&1], w, t->el, t->del); -} - -void stats_chimeric(asg_t *g, ma_hit_t_alloc* src, asg64_v *in) -{ - asg64_v tx = {0,0,0}, *b = NULL; - uint32_t v, s[2] = {0}; - if(in) b = in; - else b = &tx; - b->n = 0; - - for (v = 0; v < g->n_seq; ++v) { - if (g->seq[v].del) continue; - s[if_sup_chimeric(&(src[v]), g->seq[v].len, b, 1)]++; - } - - fprintf(stderr, "[M::%s::] ==> # non-chimeric:%u, # chimeric:%u\n", __func__, s[0], s[1]); - if(!in) free(tx.a); -} - -static void stats_sysm_worker(void *_data, long eid, int tid) -{ - asg_t *g = (asg_t*)_data; - asg_arc_t *p = &(g->arc[eid]); - if(p->del) return; - uint32_t k, v = p->v^1, w = (p->ul>>32)^1, nv; asg_arc_t *av; - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (k = 0; k < nv; k++) { - if (av[k].del || av[k].v!=w) continue; - break; - } - assert(k < nv); - - v = p->ul>>32; w = p->v; - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (k = 0; k < nv; k++) { - if (av[k].del || av[k].v!=w) continue; - assert((uint32_t)eid == av-g->arc+k); - } -} - -void stats_sysm(asg_t *g) { - kt_for(asm_opt.thread_num, stats_sysm_worker, g, g->n_arc); - fprintf(stderr, "[M::%s::]", __func__); -} - -uint32_t get_arcs(asg_t *g, uint32_t v, uint32_t* idx, uint32_t idx_n) -{ - uint32_t i, kv = 0, an = asg_arc_n(g, v), beg = g->idx[v]>>32; - for (i = 0, kv = 0; i < an; i++) { - if(g->arc[beg+i].del) continue; - if(idx && kvarc[(id)])):(&((fg).a[(id)-(((uint32_t)(0x80000000)))])))); - -uint32_t get_flex_arcs(flex_asg_t *fg, uint32_t v, uint32_t* idx, uint32_t idx_n) -{ - asg_t *g = fg->g; uint32_t i, kv = 0; - uint32_t an = asg_arc_n(g, v), beg = g->idx[v]>>32; - for (i = 0, kv = 0; i < an; i++) { - if(g->arc[beg+i].del) continue; - if(idx && kvidx[v]; i != ((uint32_t)-1); i = fg->pi.a[i]) { - if(fg->a[i].del) continue; - if(idx && kvb, v>>1); - if(b) kv_push(uint64_t, *b, v); - - if(kv == 0) return END_TIPS; - if(kv == 2) return TWO_OUTPUT; - if(kv > 2) return MUL_OUTPUT; - if((*occ) > lim) return LONG_TIPS; - w = g->arc[w].v; - ///up to here, kv=1 - ///kw must >= 1 - kw = get_arcs(g, w^1, NULL, 0); - v = w; - - if(kw == 2) return TWO_INPUT; - if(kw > 2) return MUL_INPUT; - if(v == s) return LOOP; - } - - return LONG_TIPS; -} - -static inline int asg_end(const asg_t *g, uint32_t v, uint64_t *lw, uint32_t *ou) -{ - ///v^1 is the another direction of v - uint32_t w, nv, nw, nw0, nv0 = asg_arc_n(g, v^1); - int i, i0 = -1; - asg_arc_t *aw, *av = asg_arc_a(g, v^1); - - ///if this arc has not been deleted - for (i = nv = 0; i < (int)nv0; ++i) - if (!av[i].del) i0 = i, ++nv; - - ///end without any out-degree - if (nv == 0) return ASG_ET_TIP; // tip - if (nv > 1) return ASG_ET_MULTI_OUT; // multiple outgoing arcs - ///until here, nv == 1 - if (lw) *lw = av[i0].ul<<32 | av[i0].v; - if (ou) *ou = av[i0].ou; - w = av[i0].v ^ 1; - nw0 = asg_arc_n(g, w); - aw = asg_arc_a(g, w); - for (i = nw = 0; i < (int)nw0; ++i) - if (!aw[i].del) ++nw; - - if (nw != 1) return ASG_ET_MULTI_NEI; - return ASG_ET_MERGEABLE; -} - -uint32_t asg_arc_cut_tips(asg_t *g, uint32_t max_ext, asg64_v *in, uint32_t is_ou, R_to_U *ru, telo_end_t *te) -{ - asg64_v tx = {0,0,0}, *b = NULL; - uint32_t n_vtx = g->n_seq<<1, v, w, i, k, cnt = 0, nv, kv, pb, ou, mm_ou, rr, is_u, is_telo; - asg_arc_t *av = NULL; uint64_t lw; - if(in) b = in; - else b = &tx; - b->n = 0; - for (v = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - if(te && te->hh[v>>1]) continue; - - av = asg_arc_a(g, v^1); nv = asg_arc_n(g, v^1); - for (i = kv = 0; i < nv; i++) { - if (av[i].del) continue; - kv++; break; - } - if(kv) continue; - - kv = 1; mm_ou = (uint32_t)-1; ou = 0; is_telo = 0; - if(te && te->hh[v>>1]) is_telo = 1; - for (i = 0, w = v; i < max_ext; i++) { - if(asg_end(g, w^1, &lw, is_ou?&ou:NULL)!=0) break; - w = (uint32_t)lw; kv++; mm_ou = MIN(mm_ou, ou); - if(te && te->hh[w>>1]) is_telo = 1; - } - - if(mm_ou == (uint32_t)-1) mm_ou = 0; - kv += mm_ou; i += mm_ou; - if((i < max_ext/** + (!!is_ou)**/) && (!is_telo)) kv_push(uint64_t, *b, (((uint64_t)kv)<<32)|v); - } - - radix_sort_srt64(b->a, b->a + b->n); - - for (k = 0; k < b->n; k++) { - v = (uint32_t)(b->a[k]); - - if (g->seq[v>>1].del) continue; - if(te && te->hh[v>>1]) continue; - - av = asg_arc_a(g, v^1); nv = asg_arc_n(g, v^1); - for (i = kv = 0; i < nv; i++) { - if (av[i].del) continue; - kv++; break; - } - - if(kv) continue; - - pb = b->n; kv_push(uint64_t, *b, v); mm_ou = (uint32_t)-1; ou = 0; is_telo = 0; - if(te && te->hh[v>>1]) is_telo = 1; - for (i = 0, w = v; i < max_ext; i++) { - if(asg_end(g, w^1, &lw, is_ou?&ou:NULL)!=0) break; - w = (uint32_t)lw; kv_push(uint64_t, *b, lw); mm_ou = MIN(mm_ou, ou); - if(te && te->hh[w>>1]) is_telo = 1; - } - if(mm_ou == (uint32_t)-1) mm_ou = 0; - i += mm_ou; - - if((i < max_ext/** + (!!is_ou)**/) && (!is_telo)) { - for (i = pb; i < b->n; i++) asg_seq_del(g, ((uint32_t)b->a[i])>>1); - cnt++; - } - b->n = pb; - } - - if(ru && is_ou) { - for (v = b->n = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - av = asg_arc_a(g, v^1); nv = asg_arc_n(g, v^1); - for (i = kv = 0; i < nv; i++) { - if (av[i].del) continue; - kv++; break; - } - if(kv) continue; - - - get_R_to_U(ru, v>>1, &rr, &is_u); - if(rr == (uint32_t)-1 || is_u == 1) continue; - if(te && te->hh[v>>1]) continue; - kv_push(uint64_t, *b, v); - - for (i = 0, w = v; i < max_ext; i++) { - if(asg_end(g, w^1, &lw, NULL)!=0) break; - w = (uint32_t)lw; - - get_R_to_U(ru, w>>1, &rr, &is_u); - if(rr == (uint32_t)-1 || is_u == 1) break; - if(te && te->hh[w>>1]) break; - - kv_push(uint64_t, *b, lw); - } - - for (i = 0; i < b->n; i++) { - asg_seq_del(g, ((uint32_t)b->a[i])>>1); - } - if(b->n) cnt++; - } - } - - - /** - for (v = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - - av = asg_arc_a(g, v^1); nv = asg_arc_n(g, v^1); - for (i = kv = 0; i < nv; i++) { - if (av[i].del) continue; - kv++; - } - - if(kv) continue; - pb = b->n; kv_push(uint64_t, *b, v); - for (i = 0, w = v; i < max_ext; i++) { - if(asg_is_utg_end(g, w^1, &lw)!=0) break; - w = (uint32_t)lw; kv_push(uint64_t, *b, lw); - } - - if(i < max_ext) { - for (i = pb; i < b->n; i++) asg_seq_del(g, ((uint32_t)b->a[i])>>1); - cnt++; - } - b->n = pb; - } - **/ - // stats_sysm(g); - if(!in) free(tx.a); - if (cnt > 0) asg_cleanup(g); - - return cnt; -} - -static void update_sg_contain(void *data, long i, int tid) -{ - sset_aux *sl = (sset_aux *)data; ma_hit_t *h, *z; asg_arc_t t; - ma_hit_t_alloc *src = sl->src; asg_t *g = sl->g; int64_t r, idx; - R_to_U *ridx = sl->ruIndex; uint32_t k, rr, qn, tn, is_u; - g->seq_vis[i] = 0; - if(!(g->seq[i].del)) return; - get_R_to_U(ridx, i, &rr, &is_u); - if(rr == (uint32_t)-1 || is_u == 1) return; - ma_hit_t_alloc *x = &(src[i]); - for (k = 0; k < x->length; k++) { - h = &(x->buffer[k]); - qn = Get_qn((*h)); tn = Get_tn((*h)); - if(h->bl < sl->ul_occ) continue; - if(g->seq[tn].del) { - get_R_to_U(ridx, tn, &rr, &is_u); - if(rr == (uint32_t)-1 || is_u == 1) continue; - } - r = ma_hit2arc(h, g->seq[qn].len, g->seq[tn].len, sl->max_hang, asm_opt.max_hang_rate, sl->min_ovlp, &t); - if(r < 0) continue; - idx = get_specific_overlap(&(src[tn]), tn, qn); - z = &(src[tn].buffer[idx]); - assert(z->bl == h->bl); - r = ma_hit2arc(z, g->seq[tn].len, g->seq[qn].len, sl->max_hang, asm_opt.max_hang_rate, sl->min_ovlp, &t); - if(r < 0) continue; - h->del = 0; if(!(g->seq[tn].del)) z->del = 0; - g->seq_vis[i] = 1; - } -} - -void recover_contain_g(asg_t *g, ma_hit_t_alloc *src, R_to_U* ruIndex, int64_t max_hang, int64_t min_ovlp, int64_t ul_occ) -{ - sset_aux s; s.g = g; s.src = src; s.ruIndex = ruIndex; - s.max_hang = max_hang; s.min_ovlp = min_ovlp; s.ul_occ = ul_occ; - kt_for(asm_opt.thread_num, update_sg_contain, &s, g->n_seq); - uint32_t k; - for (k = 0; k < g->n_seq; k++) { - if(g->seq_vis[k]) g->seq[k].del = 0; - } - memset(g->seq_vis, 0, (sizeof(*(g->seq_vis))*(g->n_seq<<1))); -} - -// static void update_norm_arc(void *data, long i, int tid) -// { -// sset_aux *sl = (sset_aux *)data; ma_hit_t *h, *z; asg_arc_t t; -// ma_hit_t_alloc *src = sl->src; int64_t r, idx; -// uint32_t k, rr, qn, tn, is_u; -// ma_hit_t_alloc *x = &(src[i]); -// for (k = 0; k < x->length; k++) { -// h = &(x->buffer[k]); -// qn = Get_qn((*h)); tn = Get_tn((*h)); -// if(h->bl < sl->ul_occ) continue; -// if(g->seq[tn].del) { -// get_R_to_U(ridx, tn, &rr, &is_u); -// if(rr == (uint32_t)-1 || is_u == 1) continue; -// } -// r = ma_hit2arc(h, g->seq[qn].len, g->seq[tn].len, sl->max_hang, asm_opt.max_hang_rate, sl->min_ovlp, &t); -// if(r < 0) continue; -// idx = get_specific_overlap(&(src[tn]), tn, qn); -// z = &(src[tn].buffer[idx]); -// assert(z->bl == h->bl); -// r = ma_hit2arc(z, g->seq[tn].len, g->seq[qn].len, sl->max_hang, asm_opt.max_hang_rate, sl->min_ovlp, &t); -// if(r < 0) continue; -// h->del = 0; if(!(g->seq[tn].del)) z->del = 0; -// g->seq_vis[i] = 1; -// } -// } - -// void normalize_ma_hit_t_mul(ma_hit_t_alloc *src, uint32_t n_src) -// { -// sset_aux s; s.src = src; -// kt_for(asm_opt.thread_num, update_norm_arc, &s, n_src); -// } - -static void normalize_gou0(void *data, long i, int tid) -{ - sset_aux *sl = (sset_aux *)data; - asg_t *g = sl->g; - asg_arc_t *e = &(g->arc[i]); - if(e->v > (e->ul>>32)) return; - uint32_t k, v = e->v^1, w = (e->ul>>32)^1, ou; - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - for (k = 0; k < nv; ++k) { - if (av[k].v == w) { - ou = MAX(av[k].ou, e->ou); - av[k].ou = e->ou = ou; - break; - } - } -} - -void normalize_gou(asg_t *g) -{ - sset_aux s; s.g = g; - kt_for(asm_opt.thread_num, normalize_gou0, &s, g->n_arc); -} - -static void update_sg_uo_t(void *data, long i, int tid) -{ - sset_aux *sl = (sset_aux *)data; - ma_hit_t_alloc *src = sl->src; asg_t *g = sl->g; - asg_arc_t *e = &(g->arc[i]); uint32_t k, qn, tn; - ma_hit_t_alloc *x = &(src[e->ul>>33]); - e->ou = 0; - if(e->del) return; - for (k = 0; k < x->length; k++) { - qn = Get_qn(x->buffer[k]); - tn = Get_tn(x->buffer[k]); - if(qn == (e->ul>>33) && tn == (e->v>>1)) { - e->ou = (x->buffer[k].bl>OU_MASK?OU_MASK:x->buffer[k].bl); - break; - } - } - assert(k < x->length); -} - -void update_sg_uo(asg_t *g, ma_hit_t_alloc *src) -{ - sset_aux s; s.g = g; s.src = src; - kt_for(asm_opt.thread_num, update_sg_uo_t, &s, g->n_arc); - uint32_t k, z, nv, occ_a = 0, occ_n = 0; asg_arc_t *av = NULL; - for (k = 0; k < g->n_seq; k++) { - if(g->seq[k].del) continue; - occ_n++; - - av = asg_arc_a(g, (k<<1)); nv = asg_arc_n(g, (k<<1)); - for (z = 0; z < nv; z++) { - if(av[z].del || av[z].ou == 0) continue; - break; - } - if(z < nv) { - occ_a++; - continue; - } - - av = asg_arc_a(g, ((k<<1)+1)); nv = asg_arc_n(g, ((k<<1)+1)); - for (z = 0; z < nv; z++) { - if(av[z].del || av[z].ou == 0) continue; - break; - } - if(z < nv) { - occ_a++; - } - } - - fprintf(stderr, "[M::%s::] ==> # gfa reads:%u, # covered gfa reads:%u\n", __func__, occ_n, occ_a); - - // asg_arc_t *e; uint32_t v, w; - // for (k = 0; k < g->n_arc; k++) { - // e = &(g->arc[k]); - // v = e->v^1; w = (e->ul>>32)^1; - // av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - // for (z = 0; z < nv; z++) { - // if(av[z].v == w) break; - // } - // if(z >= nv || av[z].ou != e->ou) fprintf(stderr, "[M::%s::asymmetry]\n", __func__); - // } -} - -int32_t if_sup_chimeric(ma_hit_t_alloc* src, uint64_t rLen, asg64_v *b, int if_exact) -{ - uint32_t k, qs, qe, l[2], r[2], st, bn; - int32_t dp, op; - l[0] = r[0] = rLen; l[1] = r[1] = 0; - for (k = 0; k < src->length; k++){ - if(src->buffer[k].del) continue; - if(if_exact && !(src->buffer[k].el)) continue; - - qs = Get_qs(src->buffer[k]); qe = Get_qe(src->buffer[k]); - - ///overlaps from left side - if(qs == 0){ - if(qs < l[0]) l[0] = qs; - if(qe > l[1]) l[1] = qe; - } - - ///overlaps from right side - if(qe == rLen){ - if(qs < r[0]) r[0] = qs; - if(qe > r[1]) r[1] = qe; - } - - ///note: if (qs == 0 && qe == rLen) - ///this overlap would be added to both b_left and b_right - ///that is what we want - } - if (l[1] > r[0]) return 0; - if (l[1] <= l[0] || r[1] <= r[0]) return 1; - - bn = b->n; - if(l[1] > l[0]) { - kv_push(uint64_t, *b, (l[0]<<1)); kv_push(uint64_t, *b, (l[1]<<1)|1); - } - if(r[1] > r[0]) { - kv_push(uint64_t, *b, (r[0]<<1)); kv_push(uint64_t, *b, (r[1]<<1)|1); - } - - ///check contained overlaps - for (k = 0; k < src->length; k++) { - if(src->buffer[k].del) continue; - if(if_exact && !(src->buffer[k].el)) continue; - - qs = Get_qs(src->buffer[k]); qe = Get_qe(src->buffer[k]); - if(qs == 0 || qe == rLen) continue; - - kv_push(uint64_t, *b, (qs<<1)); kv_push(uint64_t, *b, (qe<<1)|1); - } - radix_sort_srt64(b->a + bn, b->a + b->n); - l[0] = r[0] = rLen; l[1] = r[1] = 0; - - for (k = bn, dp = st = 0; k < b->n; k++) { - op = dp; - ///if a[j] is qe - if (b->a[k]&1) --dp; - else ++dp; - - if(op < 1 && dp >= 1) { - st = b->a[k]>>1; - } else if(op >= 1 && dp < 1) { - if(st == 0) l[0] = st, l[1] = b->a[k]>>1; - if((b->a[k]>>1) == rLen) r[0] = st, r[1] = b->a[k]>>1; - } - } - - b->n = bn; - if (l[1] > r[0]) return 0; - - return 1; -} - -///remove single node -void asg_arc_cut_chimeric(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, uint32_t ou_thres, telo_end_t *te) -{ - asg64_v tx = {0,0,0}, *b = NULL; - uint32_t v, w, ei[2] = {0}, k, i, n_vtx = g->n_seq<<1; - uint32_t nw, el_n, cnt = 0; asg_arc_t *aw; - if(in) b = in; - else b = &tx; - b->n = 0; - - for (v = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - if (te && te->hh[v>>1]) continue; - if(g->seq_vis[v] == 0) { - if((get_arcs(g, v, &(ei[0]), 1)!=1) || (get_arcs(g, v^1, &(ei[1]), 1)!=1)) continue; - assert((g->arc[ei[0]].ul>>32) == v && (g->arc[ei[1]].ul>>32) == (v^1)); - if((get_arcs(g, g->arc[ei[0]].v^1, NULL, 0)<2) || (get_arcs(g, g->arc[ei[1]].v^1, NULL, 0)<2)) continue; - if(g->arc[ei[0]].el) continue; - if(ou_thres!=(uint32_t)-1&&g->arc[ei[0]].ou>=ou_thres&&g->arc[ei[1]].ou>=ou_thres) continue;///UL - if(!if_sup_chimeric(&(src[v>>1]), g->seq[v>>1].len, b, 1)) continue;///HiFi - kv_push(uint64_t, *b, (((uint64_t)(g->arc[ei[0]].ol))<<32)|((uint64_t)(ei[0]))); - } - } - - radix_sort_srt64(b->a, b->a + b->n); - ///here all edges are inexact matches - for (k = 0; k < b->n; k++) { - if(g->arc[(uint32_t)b->a[k]].del) continue; - v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; - if(g->seq[v>>1].del || g->seq[w>>1].del) continue; - aw = asg_arc_a(g, w); nw = asg_arc_n(g, w); - if((get_arcs(g, v, &(ei[0]), 1)!=1) || (get_arcs(g, v^1, &(ei[1]), 1)!=1)) continue; - if((get_arcs(g, g->arc[ei[0]].v^1, NULL, 0)<2) || (get_arcs(g, g->arc[ei[1]].v^1, NULL, 0)<2)) continue; - - for (i = el_n = 0; i < nw; i++) { - if ((aw[i].del) || (aw[i].v==(v^1)) || (!aw[i].el)) continue; - el_n++; break; - } - - if(!el_n) continue; - if(te && te->hh[v>>1]) continue; - asg_seq_del(g, v>>1); - cnt++; - } - // stats_sysm(g); - if(!in) free(tx.a); - if (cnt > 0) asg_cleanup(g); -} - -void asg_arc_cut_inexact(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, int32_t max_ext, uint32_t is_ou, uint32_t is_trio, uint32_t min_diff, float ou_rat/**, asg64_v *dbg**/) -{ - asg64_v tx = {0,0,0}, *b = NULL; - uint32_t v, w, i, k, n_vtx = g->n_seq<<1; - asg_arc_t *av, *aw, *ve, *vmax, *we; uint32_t nv, nw, kv, kw, ol_max, ou_max, to_del, cnt = 0, mm_ol, mm_ou; - uint32_t trioF = (uint32_t)-1, ntrioF = (uint32_t)-1; - if(in) b = in; - else b = &tx; - b->n = 0; - - for (v = 0; v < n_vtx; ++v) { - if(g->seq[v>>1].del) continue; - if(g->seq_vis[v] == 0) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if (nv < 2) continue; - - for (i = kv = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - } - if(kv < 2) continue; - - for (i = 0; i < nv; ++i) { - if(av[i].del || av[i].el) continue; - kv_push(uint64_t, *b, (uint64_t)((((uint64_t)av[i].ol)<<32)|((uint64_t)(av-g->arc+i)))); - } - } - } - - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - if(g->arc[(uint32_t)b->a[k]].del) continue; - assert((!g->arc[(uint32_t)b->a[k]].el)); - - v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; - if(g->seq[v>>1].del || g->seq[w>>1].del) continue; - nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); - av = asg_arc_a(g, v); aw = asg_arc_a(g, w); - // if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { - // fprintf(stderr, "[0]v->%u, w->%u, nv->%u, nw->%u\n", v, w, nv, nw); - // } - if(nv<=1 && nw <= 1) continue; - if(is_trio) { - if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup - trioF = get_tip_trio_infor(g, v^1); - ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); - } - ve = &(g->arc[(uint32_t)b->a[k]]); - for (i = 0; i < nw; ++i) { - if (aw[i].v == (v^1)) { - we = &(aw[i]); - break; - } - } - ///mm_ol and mm_ou are used to make edge with long indel more easy to be cutted - mm_ol = MIN(ve->ol, we->ol); mm_ou = MIN(ve->ou, we->ou); - for (i = kv = ol_max = ou_max = 0, vmax = NULL; i < nv; ++i) { - if(av[i].del) continue; - kv++; - if(is_trio && get_tip_trio_infor(g, av[i].v) == ntrioF) continue; - if(ol_max < av[i].ol) ol_max = av[i].ol, vmax = &(av[i]); - if(ou_max < av[i].ou) ou_max = av[i].ou; - } - // if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { - // fprintf(stderr, "[1]v->%u, w->%u, kv->%u, ve->ol->%u, ol_max->%u\n", v, w, kv, ve->ol, ol_max); - // } - if (kv < 1) continue; - if (kv >= 2) { - if (mm_ol >= ol_max) continue; - if (is_ou && mm_ou > ou_max*ou_rat) continue; - if ((mm_ol + min_diff) > ol_max) continue; - } - - for (i = kw = ol_max = ou_max = 0; i < nw; ++i) { - if(aw[i].del) continue; - kw++; - if(is_trio && get_tip_trio_infor(g, aw[i].v) == ntrioF) continue; - if(ol_max < aw[i].ol) ol_max = aw[i].ol; - if(ou_max < aw[i].ou) ou_max = aw[i].ou; - } - // if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { - // fprintf(stderr, "[1]v->%u, w->%u, kw->%u, we->ol->%u, ol_max->%u\n", v, w, kw, we->ol, ol_max); - // } - if (kw < 1) continue; - if (kw >= 2) { - if (mm_ol >= ol_max) continue; - if (is_ou && mm_ou > ou_max*ou_rat) continue; - if ((mm_ol + min_diff) > ol_max) continue; - } - if (kv <= 1 && kw <= 1) continue; - - to_del = 0; - ///if there is an inexact edge between two good reads - if(src[v>>1].is_fully_corrected == 1 && src[w>>1].is_fully_corrected == 1) { - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - } - } - ///TODO: should check if the edge wmax also works - if(src[v>>1].is_fully_corrected == 1 && src[w>>1].is_fully_corrected == 0) { - if(vmax && vmax->v != ve->v && vmax->el == 1 && src[vmax->v>>1].is_fully_corrected == 1) { - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - } - } - } - - // if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { - // fprintf(stderr, "[3]v->%u, w->%u, to_del->%u, el->%u, src[v>>1].is_fully_corrected->%u, src[w>>1].is_fully_corrected->%u\n", - // v, w, to_del, g->arc[(uint32_t)b->a[k]].el, src[v>>1].is_fully_corrected, src[w>>1].is_fully_corrected); - // fprintf(stderr, "[4]v->%u, w->%u, to_del->%u, vmax->v->%u, vmax->el->%u, src[vmax->v>>1].is_fully_corrected->%u\n", - // v, w, to_del, vmax->v, vmax->el, src[vmax->v>>1].is_fully_corrected); - // } - - if (to_del) { - ve->del = we->del = 1, ++cnt; - /** - if(dbg) { - kv_push(uint64_t, *dbg, ve - g->arc); - kv_push(uint64_t, *dbg, we - g->arc); - // if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { - // fprintf(stderr, "[5]v->%u, w->%u, (ve - g->arc)->%u, (we - g->arc)->%u\n", - // v, w, (uint32_t)(ve - g->arc), (uint32_t)(we - g->arc)); - // } - } - **/ - } - - } - // stats_sysm(g); - if(!in) free(tx.a); - if (cnt > 0) asg_cleanup(g); -} - -void asg_arc_cut_inexact_debug(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, int32_t max_ext, uint32_t is_ou, uint32_t is_trio, asg64_v *dbg) -{ - asg64_v tx = {0,0,0}, *b = NULL; - uint32_t v, w, i, k, nv, nw, kv, kw, iv, iw, n_vtx = g->n_seq<<1, to_del, cnt = 0, ov_max = 0, ow_max = 0, ov_max_i = 0; - asg_arc_t *av = NULL, *aw = NULL, *a = NULL; - if(in) b = in; - else b = &tx; - b->n = 0; - - for (v = 0; v < n_vtx; ++v) { - if(g->seq[v>>1].del) continue; - if(g->seq_vis[v] == 0) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if (nv < 2) continue; - for (i = kv = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - } - if(kv < 2) continue; - - for (i = 0; i < nv; ++i) { - if(av[i].del || av[i].el) continue; - kv_push(uint64_t, *b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); - } - } - } - radix_sort_srt64(b->a, b->a + b->n); - - for (k = 0; k < b->n; k++) { - a = &g->arc[(uint32_t)b->a[k]]; - if(a->del) continue; - v = (a->ul)>>32, w = a->v^1; to_del = 0; - nv = asg_arc_n(g, v), nw = asg_arc_n(g, w); - if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { - fprintf(stderr, "[0]v->%u, w->%u, nv->%u, nw->%u\n", v, w, nv, nw); - } - if (nv == 1 && nw == 1) continue; - av = asg_arc_a(g, v), aw = asg_arc_a(g, w); - ov_max = ow_max = ov_max_i = 0; - - for (i = 0, kv = 0; i < nv; ++i) { - if (av[i].del) continue; - if (ov_max < av[i].ol) { - ov_max = av[i].ol; - ov_max_i = i; - } - ++kv; - } - if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { - fprintf(stderr, "[1]v->%u, w->%u, kv->%u, a->ol->%u, ov_max->%u\n", v, w, kv, a->ol, ov_max); - } - if (kv >= 2 && a->ol == ov_max) continue; - - for (i = 0, kw = 0; i < nw; ++i) { - if (aw[i].del) continue; - if (ow_max < aw[i].ol) { - ow_max = aw[i].ol; - } - ++kw; - } - if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { - fprintf(stderr, "[2]v->%u, w->%u, kw->%u, a->ol->%u, ow_max->%u\n", v, w, kw, a->ol, ow_max); - } - if (kw >= 2 && a->ol == ow_max) continue; - - if (kv <= 1 && kw <= 1) continue; - - ///to see which one is the current edge (from v and w) - for (iv = 0; iv < nv; ++iv) - if (av[iv].v == (w^1)) break; - for (iw = 0; iw < nw; ++iw) - if (aw[iw].v == (v^1)) break; - ///if one edge has been deleted, it should be deleted in both direction - if (av[iv].del && aw[iw].del) continue; - - ///if this edge is an inexact edge - if(a->el == 0 && src[v>>1].is_fully_corrected == 1 && src[w>>1].is_fully_corrected == 1) { - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - } - } - - if(a->el == 0 && src[v>>1].is_fully_corrected == 1 && src[w>>1].is_fully_corrected == 0) { - if(av[ov_max_i].el == 1 && src[av[ov_max_i].v>>1].is_fully_corrected == 1) { - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - } - } - } - - if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { - fprintf(stderr, "[3]v->%u, w->%u, to_del->%u, el->%u, src[v>>1].is_fully_corrected->%u, src[w>>1].is_fully_corrected->%u\n", - v, w, to_del, a->el, src[v>>1].is_fully_corrected, src[w>>1].is_fully_corrected); - fprintf(stderr, "[4]v->%u, w->%u, to_del->%u, av[ov_max_i].v->%u, av[ov_max_i].el->%u, src[av[ov_max_i].v>>1].is_fully_corrected->%u\n", - v, w, to_del, av[ov_max_i].v, av[ov_max_i].el, src[av[ov_max_i].v>>1].is_fully_corrected); - } - - if (to_del) { - av[iv].del = aw[iw].del = 1, ++cnt; - if(dbg) { - kv_push(uint64_t, *dbg, (av - g->arc + iv)); - kv_push(uint64_t, *dbg, (aw - g->arc + iw)); - if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { - fprintf(stderr, "[5]v->%u, w->%u, (av-g->arc+iv)->%u, (aw-g->arc+iw)->%u\n", - v, w, (uint32_t)(av - g->arc + iv), (uint32_t)(aw - g->arc + iw)); - } - } - } - } - - if(!in) free(tx.a); - if(dbg) { - for (i = 0; i < dbg->n; i++) g->arc[dbg->a[i]].del = 0; - } - // if (cnt > 0) asg_cleanup(g); -} - -uint32_t trans_path_check(uint32_t a, uint32_t b, asg_t *g, ma_hit_t_alloc *rev, R_to_U* rI, -uint32_t minLen, asg64_v *t) -{ - if(a == b) return -1; - uint32_t tn = t->n, m, e, l[2] = {0}; - uint64_t *x[2]; - m = follow_limit_path(g, a, &e, &(l[0]), t, (uint32_t)-1); - if(m == LOOP || l[0] <= minLen) { - t->n = tn; return -1; - } - - m = follow_limit_path(g, b, &e, &(l[1]), t, (uint32_t)-1); - if(m == LOOP || l[1] <= minLen) { - t->n = tn; return -1; - } - - x[0] = t->a + tn; x[1] = t->a + tn + l[0]; - if(l[0] > l[1]) { - x[0] = t->a + tn + l[0]; x[1] = t->a + tn; - m = l[0]; l[0] = l[1]; l[1] = m; - } - assert(l[0]+l[1]+tn==t->n); - - uint32_t i, k, qi, ti, isU; double max_count = 0, min_count = 0; - for (i = 0; i < l[1]; i++) g->seq_vis[x[1][i]>>1] = 1; - for (i = 0; i < l[0]; i++) { - qi = x[0][i]>>1; - for (k = 0; k < rev[qi].length; k++) { - ti = Get_tn(rev[qi].buffer[k]); - if(g->seq[ti].del == 1) { - get_R_to_U(rI, ti, &ti, &isU); - if(ti == (uint32_t)-1 || isU == 1 || g->seq[ti].del == 1) continue; - } - min_count++; max_count += g->seq_vis[ti]; - } - } - - for (i = 0; i < l[1]; i++) g->seq_vis[x[1][i]>>1] = 0; - t->n = tn; - - if(min_count == 0) return -1; - if(max_count == 0) return 0; - if((max_count/min_count)>0.3) return 1; - return 0; -} - -void asg_arc_cut_length(asg_t *g, asg64_v *in, int32_t max_ext, float len_rat, float ou_rat, uint32_t is_ou, uint32_t is_trio, -uint32_t is_topo, uint32_t min_diff, uint32_t min_ou, ma_hit_t_alloc *rev, R_to_U* rI, uint32_t *max_drop_len) -{ - asg64_v tx = {0,0,0}, *b = NULL; - uint32_t i, k, v, w, n_vtx = g->n_seq<<1, nv, nw, kv, kw, trioF = (uint32_t)-1, ntrioF = (uint32_t)-1, ol_max, ou_max, to_del, cnt = 0, mm_ol, mm_ou; - asg_arc_t *av, *aw, *ve, *we, *vl_max, *wl_max; - - if(in) b = in; - else b = &tx; - b->n = 0; - - for (v = 0; v < n_vtx; ++v) { - // if((v>>1)==17078) fprintf(stderr, "[M::%s::] v:%u, del:%u, seq_vis:%u\n", __func__, v, g->seq[v>>1].del, g->seq_vis[v]); - if (g->seq[v>>1].del) continue; - if(g->seq_vis[v] == 0) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if (nv < 2) continue; - - for (i = kv = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - } - if(kv < 2) continue; - - for (i = 0; i < nv; ++i) { - if(av[i].del) continue; - // if((av[i].ul>>33)==287) { - // fprintf(stderr, "++++++%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\n", - // (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], - // (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].ol, av[i].ou); - // } - if(max_drop_len && av[i].ol >= (*max_drop_len)) continue; - kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); - } - } - } - - if(rev && rI) memset(g->seq_vis, 0, g->n_seq*2*sizeof(uint8_t)); - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - if(g->arc[(uint32_t)b->a[k]].del) continue; - - v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; - if(g->seq[v>>1].del || g->seq[w>>1].del) continue; - nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); - av = asg_arc_a(g, v); aw = asg_arc_a(g, w); - if(nv<=1 && nw <= 1) continue; - - if(is_trio) { - if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup - trioF = get_tip_trio_infor(g, v^1); - ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); - } - - ve = &(g->arc[(uint32_t)b->a[k]]); - for (i = 0; i < nw; ++i) { - if (aw[i].v == (v^1)) { - we = &(aw[i]); - break; - } - } - ///mm_ol and mm_ou are used to make edge with long indel more easy to be cutted - mm_ol = MIN(ve->ol, we->ol); mm_ou = MIN(ve->ou, we->ou); - - for (i = kv = ol_max = ou_max = 0, /**ve =**/ vl_max = NULL; i < nv; ++i) { - if(av[i].del) continue; - // if(av[i].v == (w^1)) ve = &(av[i]); - // if((av[i].ul>>33)==287) { - // fprintf(stderr, "++++++%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\n", - // (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], - // (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].ol, av[i].ou); - // } - kv++; - if(is_trio && get_tip_trio_infor(g, av[i].v) == ntrioF) continue; - if(ol_max < av[i].ol) ol_max = av[i].ol, vl_max = &(av[i]); - if(ou_max < av[i].ou) ou_max = av[i].ou; - } - if (kv < 1) continue; - if (kv >= 2) { - if (mm_ol > ol_max*len_rat) continue; - if (is_ou && mm_ou > ou_max*ou_rat && mm_ou > min_ou) continue; - if ((mm_ol + min_diff) > ol_max) continue; - } - - - for (i = kw = ol_max = ou_max = 0, wl_max = NULL; i < nw; ++i) { - if(aw[i].del) continue; - kw++; - if(is_trio && get_tip_trio_infor(g, aw[i].v) == ntrioF) continue; - if(ol_max < aw[i].ol) ol_max = aw[i].ol, wl_max = &(aw[i]); - if(ou_max < aw[i].ou) ou_max = aw[i].ou; - } - if (kw < 1) continue; - if (kw >= 2) { - if (mm_ol > ol_max*len_rat) continue; - if (is_ou && mm_ou > ou_max*ou_rat && mm_ou > min_ou) continue; - if ((mm_ol + min_diff) > ol_max) continue; - } - - if (kv <= 1 && kw <= 1) continue; - - to_del = 0; - if(is_topo) { - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - } - } - - if(rev && rI) { - if((to_del == 0) && vl_max && (ve->v!=vl_max->v) && (trans_path_check(ve->v, vl_max->v, g, rev, rI, max_ext, b)==0)) { - to_del = 1; - } - if((to_del == 0) && wl_max && (we->v!=wl_max->v) && (trans_path_check(we->v, wl_max->v, g, rev, rI, max_ext, b)==0)) { - to_del = 1; - } - if(vl_max && wl_max) assert(ve->v!=vl_max->v||we->v!=wl_max->v); - } - - - if (to_del) { - ve->del = we->del = 1, ++cnt; - } - } - // stats_sysm(g); - if(!in) free(tx.a); - if (cnt > 0) asg_cleanup(g); -} - -uint32_t is_dedup_weak_arc(asg_arc_t *av, uint32_t an, uint32_t ak, ma_hit_t_alloc *rev) -{ - uint32_t k, w, m; ma_hit_t_alloc *z = NULL; - for (k = 0; k < an; k++) { - if((k == ak) || (av[k].del) || (!av[k].strong)) continue; - if(av[k].ol > av[ak].ol) { - z = &(rev[av[k].v>>1]); w = (av[ak].v^(av[k].v&1)); - for (m = 0; m < z->length; m++) { - if((z->buffer[m].tn<<1|(z->buffer[m].rev)) == w) break; - } - if(m < z->length) return 1; - } - } - - return 0; -} - -void asg_arc_cut_weak(asg_t *g, asg64_v *in, int32_t max_ext, float len_rat, float ou_rat, uint32_t is_ou, uint32_t is_trio, -uint32_t is_topo, uint32_t min_diff, uint32_t min_ou, uint32_t test_bub, ma_hit_t_alloc *rev, R_to_U* rI, uint32_t *max_drop_len) -{ - asg64_v tx = {0,0,0}, *b = NULL; - uint32_t i, k, v, w, wz, n_vtx = g->n_seq<<1, nv, nw, kv, kw, trioF = (uint32_t)-1, ntrioF = (uint32_t)-1, ol_max, ou_max, to_del, cnt = 0, mm_ol, mm_ou, olw[2], m; - asg_arc_t *av, *aw, *ve, *we, *vl_max, *wl_max; ma_hit_t_alloc *z = NULL; - - if(in) b = in; - else b = &tx; - b->n = 0; - - for (v = 0; v < n_vtx; ++v) { - // if((v>>1)==17078) fprintf(stderr, "[M::%s::] v:%u, del:%u, seq_vis:%u\n", __func__, v, g->seq[v>>1].del, g->seq_vis[v]); - if (g->seq[v>>1].del) continue; - if((test_bub == 0) || (g->seq_vis[v] == 0)) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if (nv < 2) continue; - - for (i = kv = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - } - if(kv < 2) continue; - - for (i = olw[1] = 0, olw[0] = (uint32_t)-1; i < nv; ++i) { - if(av[i].del) continue; - if(av[i].strong) { - if(av[i].ol > olw[av[i].strong]) olw[av[i].strong] = av[i].ol; - } else { - if(av[i].ol < olw[av[i].strong]) olw[av[i].strong] = av[i].ol; - } - } - if(olw[1] <= olw[0]) continue; - for (i = 0; i < nv; ++i) { - if(av[i].del || av[i].strong) continue; - if(av[i].ol >= olw[1]) continue; - if(max_drop_len && av[i].ol >= (*max_drop_len)) continue; - if(is_dedup_weak_arc(av, nv, i, rev)) { - kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); - } - } - } - } - - if(rev && rI) memset(g->seq_vis, 0, g->n_seq*2*sizeof(uint8_t)); - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - if(g->arc[(uint32_t)b->a[k]].del) continue; - - v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; - if(g->seq[v>>1].del || g->seq[w>>1].del) continue; - nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); - av = asg_arc_a(g, v); aw = asg_arc_a(g, w); - if(nv<=1 && nw <= 1) continue; - - if(is_trio) { - if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup - trioF = get_tip_trio_infor(g, v^1); - ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); - } - - ve = &(g->arc[(uint32_t)b->a[k]]); - for (i = 0; i < nw; ++i) { - if (aw[i].v == (v^1)) { - we = &(aw[i]); - break; - } - } - ///mm_ol and mm_ou are used to make edge with long indel more easy to be cutted - mm_ol = MIN(ve->ol, we->ol); mm_ou = MIN(ve->ou, we->ou); - - for (i = kv = ol_max = ou_max = 0, vl_max = NULL; i < nv; ++i) { - if(av[i].del) continue; - kv++; - if((av[i].v == ve->v) || (!av[i].strong) || (av[i].ol <= ve->ol)) continue; - if(is_trio && get_tip_trio_infor(g, av[i].v) == ntrioF) continue; - - z = &(rev[av[i].v>>1]); wz = (ve->v^(av[i].v&1)); - for (m = 0; m < z->length; m++) { - if((z->buffer[m].tn<<1|(z->buffer[m].rev)) == wz) break; - } - if(m >= z->length) continue; - - if(ol_max < av[i].ol) ol_max = av[i].ol, vl_max = &(av[i]); - if(ou_max < av[i].ou) ou_max = av[i].ou; - } - if (kv < 1) continue; - if (kv >= 2) { - if (mm_ol > ol_max*len_rat) continue; - if (is_ou && mm_ou > ou_max*ou_rat && mm_ou > min_ou) continue; - if ((mm_ol + min_diff) > ol_max) continue; - } - - - for (i = kw = ol_max = ou_max = 0, wl_max = NULL; i < nw; ++i) { - if(aw[i].del) continue; - kw++; - if((aw[i].v == we->v) || (!aw[i].strong) || (aw[i].ol <= we->ol)) continue; - if(is_trio && get_tip_trio_infor(g, aw[i].v) == ntrioF) continue; - - z = &(rev[aw[i].v>>1]); wz = (we->v^(aw[i].v&1)); - for (m = 0; m < z->length; m++) { - if((z->buffer[m].tn<<1|(z->buffer[m].rev)) == wz) break; - } - if(m >= z->length) continue; - - if(ol_max < aw[i].ol) ol_max = aw[i].ol, wl_max = &(aw[i]); - if(ou_max < aw[i].ou) ou_max = aw[i].ou; - } - if (kw < 1) continue; - if (kw >= 2) { - if (mm_ol > ol_max*len_rat) continue; - if (is_ou && mm_ou > ou_max*ou_rat && mm_ou > min_ou) continue; - if ((mm_ol + min_diff) > ol_max) continue; - } - - if (kv <= 1 && kw <= 1) continue; - - to_del = 0; - if(is_topo) { - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - } - } - - if(rev && rI) { - if((to_del == 0) && vl_max && (ve->v!=vl_max->v) && (trans_path_check(ve->v, vl_max->v, g, rev, rI, max_ext, b)==0)) { - to_del = 1; - } - if((to_del == 0) && wl_max && (we->v!=wl_max->v) && (trans_path_check(we->v, wl_max->v, g, rev, rI, max_ext, b)==0)) { - to_del = 1; - } - if(vl_max && wl_max) assert(ve->v!=vl_max->v||we->v!=wl_max->v); - } - - - if (to_del) { - ve->del = we->del = 1, ++cnt; - } - } - // stats_sysm(g); - if(!in) free(tx.a); - if (cnt > 0) asg_cleanup(g); -} - - -void asg_arc_cut_chimeric_cmk(asg_t *g, asg64_v *in, int32_t max_ext, float len_rat, float ou_rat, uint32_t is_ou, uint32_t is_topo, uint32_t min_ou, uint32_t test_bub, uint8_t *cmk, uint32_t cmk_cut) -{ - asg64_v tx = {0,0,0}, *b = NULL; asg_arc_t *av, *aw, *ve, *we; - uint32_t i, k, v, w, n_vtx = g->n_seq<<1, nv, nw, kv, kw, ol_max, ou_max, to_del, cnt = 0, mm_ol, mm_ou; - - if(in) b = in; - else b = &tx; - b->n = 0; - - for (v = 0; v < n_vtx; ++v) { - // if((v>>1)==17078) fprintf(stderr, "[M::%s::] v:%u, del:%u, seq_vis:%u\n", __func__, v, g->seq[v>>1].del, g->seq_vis[v]); - if (g->seq[v>>1].del) continue; - if (cmk[v>>1] > cmk_cut) continue; - if((test_bub == 0) || (g->seq_vis[v] == 0)) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if (nv < 2) continue; - - for (i = kv = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - } - if(kv < 2) continue; - - for (i = 0; i < nv; ++i) { - if(av[i].del) continue; - kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); - } - } - } - - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - if(g->arc[(uint32_t)b->a[k]].del) continue; - - v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; - if(g->seq[v>>1].del || g->seq[w>>1].del) continue; - nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); - av = asg_arc_a(g, v); aw = asg_arc_a(g, w); - if(nv<=1 && nw <= 1) continue; - - ve = &(g->arc[(uint32_t)b->a[k]]); - for (i = 0; i < nw; ++i) { - if (aw[i].v == (v^1)) { - we = &(aw[i]); - break; - } - } - ///mm_ol and mm_ou are used to make edge with long indel more easy to be cutted - mm_ol = MIN(ve->ol, we->ol); mm_ou = MIN(ve->ou, we->ou); - - for (i = kv = ol_max = ou_max = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - - if(ol_max < av[i].ol) ol_max = av[i].ol; - if(ou_max < av[i].ou) ou_max = av[i].ou; - } - if (kv < 1) continue; - if (kv >= 2) { - if (mm_ol > ol_max*len_rat) continue; - if (is_ou && mm_ou > ou_max*ou_rat && mm_ou > min_ou) continue; - } - - - for (i = kw = ol_max = ou_max = 0; i < nw; ++i) { - if(aw[i].del) continue; - kw++; - - if(ol_max < aw[i].ol) ol_max = aw[i].ol; - if(ou_max < aw[i].ou) ou_max = aw[i].ou; - } - if (kw < 1) continue; - if (kw >= 2) { - if (mm_ol > ol_max*len_rat) continue; - if (is_ou && mm_ou > ou_max*ou_rat && mm_ou > min_ou) continue; - } - - if (kv <= 1 && kw <= 1) continue; - - to_del = 0; - if(is_topo) { - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext + 1) < max_ext + 1) to_del = 1; - } - } - - if (to_del) { - asg_seq_del(g, v>>1); ++cnt; - } - } - // stats_sysm(g); - if(!in) free(tx.a); - if (cnt > 0) asg_cleanup(g); - - // fprintf(stderr, "[M::%s::] cnt:%u\n", __func__, cnt); -} - - -void asg_arc_cut_length_adv(asg_t *g, asg64_v *in, int32_t max_ext, float len_rat, float ou_rat, uint32_t is_ou, uint32_t is_trio, -uint32_t is_topo, uint32_t min_diff, ma_hit_t_alloc *rev, R_to_U* rI, uint32_t *max_drop_len) -{ - asg64_v tx = {0,0,0}, *b = NULL; - uint32_t i, k, v, w, n_vtx = g->n_seq<<1, nv, nw, kv, kw, trioF = (uint32_t)-1, ntrioF = (uint32_t)-1, ol_max, ou_max, to_del, cnt = 0, mm_ol, mm_ou; - asg_arc_t *av, *aw, *ve, *we, *vl_max, *wl_max; - - if(in) b = in; - else b = &tx; - b->n = 0; - - for (v = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - if(g->seq_vis[v] == 0) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if (nv < 2) continue; - - for (i = kv = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - } - if(kv < 2) continue; - - for (i = 0; i < nv; ++i) { - if(av[i].del) continue; - if(max_drop_len && av[i].ol >= (*max_drop_len)) continue; - kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); - } - } - } - - if(rev && rI) memset(g->seq_vis, 0, g->n_seq*2*sizeof(uint8_t)); - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - if(g->arc[(uint32_t)b->a[k]].del) continue; - - v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; - if(g->seq[v>>1].del || g->seq[w>>1].del) continue; - nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); - av = asg_arc_a(g, v); aw = asg_arc_a(g, w); - if(nv<=1 && nw <= 1) continue; - - if(is_trio) { - if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup - trioF = get_tip_trio_infor(g, v^1); - ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); - } - - ve = &(g->arc[(uint32_t)b->a[k]]); - for (i = 0; i < nw; ++i) { - if (aw[i].v == (v^1)) { - we = &(aw[i]); - break; - } - } - ///mm_ol and mm_ou are used to make edge with long indel more easy to be cutted - mm_ol = MIN(ve->ol, we->ol); mm_ou = MIN(ve->ou, we->ou); - - for (i = kv = ol_max = ou_max = 0, /**ve =**/ vl_max = NULL; i < nv; ++i) { - if(av[i].del) continue; - kv++; - if(is_trio && get_tip_trio_infor(g, av[i].v) == ntrioF) continue; - if(ol_max < av[i].ol) ol_max = av[i].ol, vl_max = &(av[i]); - if(ou_max < av[i].ou) ou_max = av[i].ou; - } - if (kv < 1) continue; - if (kv >= 2) { - if (mm_ol > ol_max*len_rat) continue; - if (is_ou && mm_ou > ou_max*ou_rat) continue; - if ((mm_ol + min_diff) > ol_max) continue; - } - - - for (i = kw = ol_max = ou_max = 0, wl_max = NULL; i < nw; ++i) { - if(aw[i].del) continue; - kw++; - if(is_trio && get_tip_trio_infor(g, aw[i].v) == ntrioF) continue; - if(ol_max < aw[i].ol) ol_max = aw[i].ol, wl_max = &(aw[i]); - if(ou_max < aw[i].ou) ou_max = aw[i].ou; - } - if (kw < 1) continue; - if (kw >= 2) { - if (mm_ol > ol_max*len_rat) continue; - if (is_ou && mm_ou > ou_max*ou_rat) continue; - if ((mm_ol + min_diff) > ol_max) continue; - } - - if (kv <= 1 && kw <= 1) continue; - - to_del = 0; - if(is_topo) { - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - } - } - - if(rev && rI) { - if((to_del == 0) && vl_max && (ve->v!=vl_max->v) && (trans_path_check(ve->v, vl_max->v, g, rev, rI, max_ext, b)==0)) { - to_del = 1; - } - if((to_del == 0) && wl_max && (we->v!=wl_max->v) && (trans_path_check(we->v, wl_max->v, g, rev, rI, max_ext, b)==0)) { - to_del = 1; - } - if(vl_max && wl_max) assert(ve->v!=vl_max->v||we->v!=wl_max->v); - } - - - if (to_del) { - ve->del = we->del = 1, ++cnt; - } - } - // stats_sysm(g); - if(!in) free(tx.a); - if (cnt > 0) asg_cleanup(g); -} - -uint8_t get_ug_tip_trio_infor(ma_ug_t *ug, uint32_t begNode) -{ - uint32_t v = begNode, w, k, s; - uint32_t kv; - uint32_t eLen = 0, uLen = 0; - uint32_t father_occ = 0, mother_occ = 0, ambigious_occ = 0; - ma_utg_t *u; - - while (1) { - kv = get_real_length(ug->g, v, NULL); - u = &(ug->u.a[v>>1]); eLen += u->n; - - for (k = 0; k < u->n; k++) { - s = u->a[k]>>33; - if(R_INF.trio_flag[s]==FATHER) father_occ++; - else if(R_INF.trio_flag[s]==MOTHER) mother_occ++; - else if((R_INF.trio_flag[s]==AMBIGU) || (R_INF.trio_flag[s]==DROP)) ambigious_occ++; - } - if(kv!=1) break; - ///kv must be 1 here - kv = get_real_length(ug->g, v, &w); - if(get_real_length(ug->g, w^1, NULL)!=1) break; - v = w; - if(v == begNode) break; - } - - uLen = eLen;///how many nodes - eLen = father_occ + mother_occ;///haplotype-sepcific nodes - if(eLen == 0) return AMBIGU; - if(father_occ >= mother_occ) { - if((father_occ > TRIO_THRES*eLen) && (father_occ >= DOUBLE_CHECK_THRES*uLen)) return FATHER; - } else { - if((mother_occ > TRIO_THRES*eLen) && (mother_occ >= DOUBLE_CHECK_THRES*uLen)) return MOTHER; - } - return AMBIGU; -} - - -asg_arc_t *iter_flex_asg(flex_asg_t *fg, flex_asg_e_retrive_t *rr, uint32_t v) -{ - asg_arc_t *av; uint32_t nv; asg_arc_t *z; - av = asg_arc_a(fg->g, v); nv = asg_arc_n(fg->g, v); - while(rr->i[0] < nv) { - return &(av[rr->i[0]++]); - } - - if(rr->i[0] >= nv && rr->i[0] != ((uint32_t)-1)) { - rr->i[0] = ((uint32_t)-1); rr->i[1] = fg->idx[v]; - } - while (rr->i[1] != ((uint32_t)-1)) { - z = &(fg->a[rr->i[1]]); rr->i[1] = fg->pi.a[rr->i[1]]; - return z; - } - return NULL; -} - -uint32_t detect_tip2(flex_asg_t *fg, uint32_t id, asg64_v *st, float ou_rat) -{ - uint32_t v, w, kw, ou_max, mm_ou; asg_arc_t *sv, *sw; - flex_asg_e_retrive_t rv, rw; - v = id<<1; rv.i[0] = 0; rv.i[1] = (uint32_t)-1; - while(1) { - sv = iter_flex_asg(fg, &rv, v); - if(!sv) break; - if(sv->del) continue; - w = sv->v^1; - if(fg->g->seq_vis[w]&128) continue; - if(fg->g->seq_vis[w>>1]&2) continue; - - rw.i[0] = 0; rw.i[1] = (uint32_t)-1; kw = 0; ou_max = mm_ou = 0; - while(1) { - sw = iter_flex_asg(fg, &rw, w); - if(!sw) break; - if(sw->del) continue; - if(ou_max < sw->ou) ou_max = sw->ou; - if(fg->g->seq_vis[sw->v>>1]&2) { - if(mm_ou < sw->ou) mm_ou = sw->ou; - continue; - } - kw++; - } - if(kw < 1) return 1; - if(ou_rat >= 0 && mm_ou > ou_max*ou_rat) return 1; - fg->g->seq_vis[w] |= 128; kv_push(uint64_t, *st, w); - } - - v = (id<<1)+1; rv.i[0] = 0; rv.i[1] = (uint32_t)-1; - while(1) { - sv = iter_flex_asg(fg, &rv, v); - if(!sv) break; - if(sv->del) continue; - w = sv->v^1; - if(fg->g->seq_vis[w]&128) continue; - if(fg->g->seq_vis[w>>1]&2) continue; - - rw.i[0] = 0; rw.i[1] = (uint32_t)-1; kw = 0; ou_max = mm_ou = 0; - while(1) { - sw = iter_flex_asg(fg, &rw, w); - if(!sw) break; - if(sw->del) continue; - if(ou_max < sw->ou) ou_max = sw->ou; - if(fg->g->seq_vis[sw->v>>1]&2) { - if(mm_ou < sw->ou) mm_ou = sw->ou; - continue; - } - kw++; - } - if(kw < 1) return 1; - if(ou_rat >= 0 && mm_ou > ou_max*ou_rat) return 1; - fg->g->seq_vis[w] |= 128; kv_push(uint64_t, *st, w); - } - - // av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - // for (i = 0; i < nv; ++i) { - // if(av[i].del) continue; - // w = av[i].v^1; - // if(g->seq_vis[w]&128) continue; - // if((g->seq_vis[w>>1]&3)==2) continue; - // aw = asg_arc_a(g, w); nw = asg_arc_n(g, w); - // for (k = kw = 0; k < nw && kw < 1; k++) { - // if(aw[k].del) continue; - // if((g->seq_vis[aw[k].v>>1]&3)==2) continue; - // kw++; - // } - // if(kw < 1) return 1; - // g->seq_vis[w] |= 128; kv_push(uint64_t, *st, w); - // } - - - // v = (id<<1)+1; - // av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - // for (i = 0; i < nv; ++i) { - // if(av[i].del) continue; - // w = av[i].v^1; - // if(g->seq_vis[w]&128) continue; - // if((g->seq_vis[w>>1]&3)==2) continue; - // aw = asg_arc_a(g, w); nw = asg_arc_n(g, w); - // for (k = kw = 0; k < nw && kw < 1; k++) { - // if(aw[k].del) continue; - // if((g->seq_vis[aw[k].v>>1]&3)==2) continue; - // kw++; - // } - // if(kw < 1) return 1; - // g->seq_vis[w] |= 128; kv_push(uint64_t, *st, w); - // } - - return 0; -} - -uint32_t trans_check(flex_asg_t *fg, asg_arc_t *z, asg64_v *b) -{ - flex_asg_e_retrive_t rv, rw; asg_arc_t *sv, *sw; - uint32_t v = z->ul>>32, w; - - rv.i[0] = 0; rv.i[1] = (uint32_t)-1; - while(1) { - sv = iter_flex_asg(fg, &rv, v); - if(!sv) break; - if(sv->del) continue; - if(sv->v == z->v) return 0; - w = sv->v; - // if((z->ul>>33) == 8340 && (z->v>>1) == 8352) { - // fprintf(stderr, "+[M::%s] v>>1::%u(%c), w>>1::%u(%c), sv->v::%u\n", - // __func__, (z->ul>>33), "+-"[(z->ul>>32)&1], (z->v>>1), "+-"[z->v&1], sv->v); - // } - - rw.i[0] = 0; rw.i[1] = (uint32_t)-1; - while (1) { - sw = iter_flex_asg(fg, &rw, w); - if(!sw) break; - if(sw->del) continue; - if(sw->v == z->v) return 0; - } - } - - - uint32_t bn = b->n; uint64_t vl, d, L = asg_arc_len((*z)) + fg->gap_fuzz; - kv_push(uint64_t, *b, v); - while (b->n > bn) { - vl = kv_pop(*b); v = (uint32_t)vl; vl >>= 32; - rv.i[0] = 0; rv.i[1] = (uint32_t)-1; - while(1) { - sv = iter_flex_asg(fg, &rv, v); - if(!sv) break; - if(sv->del) continue; - d = vl + asg_arc_len((*sv)); - if(d > L) continue; - if(sv->v == z->v) { - b->n = bn; - return 0; - } - d <<= 32; d |= sv->v; - kv_push(uint64_t, *b, d); - } - } - - b->n = bn; - return 1; -} - -void push_flex_asg_t(flex_asg_t *fg, asg_arc_t *z) -{ - asg_arc_t *av; uint32_t nv, k, v = z->ul>>32; - av = asg_arc_a(fg->g, v); nv = asg_arc_n(fg->g, v); - for (k = 0; k < nv; k++) { - if(av[k].del) { - av[k] = *z; - if(!(fg->need_srt)) { - if(k > 0 && av[k].ul < av[k-1].ul) fg->need_srt = 1; - if(k+1 < nv && av[k].ul > av[k+1].ul) fg->need_srt = 1; - } - return; - } - } - - k = fg->n; fg->need_srt = 1; - kv_push(asg_arc_t, *fg, *z); - kv_push(uint32_t, fg->pi, fg->idx[v]); fg->idx[v] = k; -} - -void append_notrans_e(flex_asg_t *fg, uint64_t *a, uint64_t a_n, asg64_v *b) -{ - ma_hit_t_alloc* src = fg->src; int32_t idx, r; - uint32_t i, k, v, w; ma_hit_t_alloc *z; asg_arc_t t0, t1; - for (i = 0; i < a_n; i++) { - v = a[i]; - z = &(src[v>>1]); - for (k = i + 1; k < a_n; k++) { - w = a[k]^1; - idx = get_specific_overlap(z, v>>1, w>>1); - if(idx < 0 || z->buffer[idx].del) continue; - r = ma_hit2arc(&(z->buffer[idx]), Get_READ_LENGTH(R_INF, v>>1), Get_READ_LENGTH(R_INF, w>>1), - fg->max_hang, fg->max_hang_rate, fg->min_ovlp, &t0); - if(r < 0) continue; - if((t0.ul>>32) != v || t0.v != w) continue; - t0.ou = ((z->buffer[idx].bl>OU_MASK)?OU_MASK:z->buffer[idx].bl); - // if((v>>1) == 8340 && (w>>1) == 8352) { - // fprintf(stderr, "[M::%s] v>>1::%u(%c), w>>1::%u(%c), t0.ou::%u\n", - // __func__, (v>>1), "+-"[v&1], (w>>1), "+-"[w&1], t0.ou); - // } - - - idx = get_specific_overlap(&(src[w>>1]), w>>1, v>>1); - if(idx < 0 || src[w>>1].buffer[idx].del) continue; - r = ma_hit2arc(&(src[w>>1].buffer[idx]), Get_READ_LENGTH(R_INF, w>>1), Get_READ_LENGTH(R_INF, v>>1), - fg->max_hang, fg->max_hang_rate, fg->min_ovlp, &t1); - if(r < 0) continue; - if((t1.ul>>32) != (w^1) || t1.v != (v^1)) continue; - t1.ou = ((src[w>>1].buffer[idx].bl>OU_MASK)?OU_MASK:src[w>>1].buffer[idx].bl); - // if((v>>1) == 8340 && (w>>1) == 8352) { - // fprintf(stderr, "[M::%s] v>>1::%u(%c), w>>1::%u(%c), t1.ou::%u\n", - // __func__, (v>>1), "+-"[v&1], (w>>1), "+-"[w&1], t1.ou); - // } - - if(trans_check(fg, &t0, b) && trans_check(fg, &t1, b)) { - push_flex_asg_t(fg, &t0); push_flex_asg_t(fg, &t1); - } - } - } -} - -uint32_t append_trans_check(flex_asg_t *fg, uint64_t *a, uint64_t a_n) -{ - ma_hit_t_alloc* src = fg->src; int32_t idx, r; - uint32_t i, k, v, w; ma_hit_t_alloc *z; asg_arc_t t0, t1; - for (i = 0; i < a_n; i++) { - v = a[i]; - z = &(src[v>>1]); - for (k = i + 1; k < a_n; k++) { - w = a[k]^1; - idx = get_specific_overlap(z, v>>1, w>>1); - if(idx < 0 || z->buffer[idx].del) return 0; - r = ma_hit2arc(&(z->buffer[idx]), Get_READ_LENGTH(R_INF, v>>1), Get_READ_LENGTH(R_INF, w>>1), - fg->max_hang, fg->max_hang_rate, fg->min_ovlp, &t0); - if(r < 0) return 0; - if((t0.ul>>32) != v || t0.v != w) return 0; - t0.ou = ((z->buffer[idx].bl>OU_MASK)?OU_MASK:z->buffer[idx].bl); - // if((v>>1) == 8340 && (w>>1) == 8352) { - // fprintf(stderr, "[M::%s] v>>1::%u(%c), w>>1::%u(%c), t0.ou::%u\n", - // __func__, (v>>1), "+-"[v&1], (w>>1), "+-"[w&1], t0.ou); - // } - - - idx = get_specific_overlap(&(src[w>>1]), w>>1, v>>1); - if(idx < 0 || src[w>>1].buffer[idx].del) return 0; - r = ma_hit2arc(&(src[w>>1].buffer[idx]), Get_READ_LENGTH(R_INF, w>>1), Get_READ_LENGTH(R_INF, v>>1), - fg->max_hang, fg->max_hang_rate, fg->min_ovlp, &t1); - if(r < 0) return 0; - if((t1.ul>>32) != (w^1) || t1.v != (v^1)) return 0; - t1.ou = ((src[w>>1].buffer[idx].bl>OU_MASK)?OU_MASK:src[w>>1].buffer[idx].bl); - } - } - return 1; -} - -uint32_t iter_contain_g(R_to_U* rI, flex_asg_t *fg, uint32_t v0, asg64_v *b, asg64_v *st, float ou_rat, uint32_t only_trans_nn) -{ - uint32_t v, w = (uint32_t)-1, x, i, kv, kw, ulen, cnt = 0, st_n, m, is_purge; - asg_arc_t *s; flex_asg_e_retrive_t rr; - b->n = st->n = ulen = 0; kv_push(uint64_t, *st, v0); - while (st->n) { - v = kv_pop(*st); kv = kw = (uint32_t)-1; ulen = 0; - if(fg->g->seq_vis[v>>1]) continue; - while ((!(fg->g->seq_vis[v>>1])) && (is_contain_r((*rI), (v>>1)))) {///push a unitig - kv = get_flex_arcs(fg, v, &w, 1); ulen++; - kv_push(uint64_t, *b, v); - if(kv == 1) { - flex_arcs0(s, (*fg), w); - w = s->v; - kw = get_flex_arcs(fg, w^1, NULL, 0); - if(kw == 1) v = w; - else break; - } else { - break; - } - } - // if((v0>>1) == 12321 || (v0>>1) == 12334) { - // fprintf(stderr, "0[M::%s] v0>>1::%u(%c), b->n::%u, ulen::%u\n", - // __func__, (v0>>1), "+-"[v0&1], (uint32_t)b->n, ulen); - // } - if((!ulen) || (fg->g->seq_vis[v>>1]) || (!(is_contain_r((*rI), (v>>1))))) { - for (i = b->n - ulen; i < b->n; i++) { - fg->g->seq_vis[b->a[i]>>1] = 1; b->a[i] |= ((uint64_t)0x100000000); - } - continue; - } - // fprintf(stderr, "1[M::%s] v0>>1::%u(%c), b->n::%u, ulen::%u\n", - // __func__, (v0>>1), "+-"[v0&1], (uint32_t)b->n, ulen); - - for (i = 0; i < b->n; i++) { - if(b->a[i]&(0x100000000)) continue; - fg->g->seq_vis[b->a[i]>>1] = 2; - } - // fprintf(stderr, "2[M::%s] v0>>1::%u(%c), b->n::%u, ulen::%u\n", - // __func__, (v0>>1), "+-"[v0&1], (uint32_t)b->n, ulen); - for (i = 0, st_n = st->n; i < b->n; i++) { - if(b->a[i]&(0x100000000)) continue; - if(detect_tip2(fg, b->a[i]>>1, st, ou_rat)) break; - } - if(i >= b->n) is_purge = 1; - else is_purge = 0; - // fprintf(stderr, "3[M::%s] v0>>1::%u(%c), b->n::%u, ulen::%u\n", - // __func__, (v0>>1), "+-"[v0&1], (uint32_t)b->n, ulen); - for (i = m = st_n; i < st->n; i++) { - if(fg->g->seq_vis[st->a[i]]&128) fg->g->seq_vis[st->a[i]] -= 128; - ///append edges to all nodes, instead of non-contained only - // if(is_contain_r((*rI), (st->a[i]>>1))) continue; - st->a[m++] = st->a[i]; - } - st->n = m; - // if((v0>>1) == 12321 || (v0>>1) == 12334) { - // fprintf(stderr, "4[M::%s] v0>>1::%u(%c), b->n::%u, i::%u\n", - // __func__, (v0>>1), "+-"[v0&1], (uint32_t)b->n, i); - // } - if(is_purge && only_trans_nn) { - is_purge = append_trans_check(fg, st->a + st_n, st->n-st_n); - } - - if(is_purge) { - for (i = 0; i < b->n; i++) { - x = ((uint32_t)b->a[i])>>1; - // if((v0>>1) == 12321 || (v0>>1) == 12334) { - // fprintf(stderr, "del::[M::%s] x::%u, seq_vis::%u\n", __func__, x, fg->g->seq_vis[x]); - // } - if(fg->g->seq_vis[x]&2) { - asg_seq_del(fg->g, x); cnt++; - } - fg->g->seq_vis[x] = 0; - } - append_notrans_e(fg, st->a + st_n, st->n-st_n, b); - st->n = st_n; - return cnt; - } - for (i = 0; i < b->n; i++) { - if(b->a[i]&(0x100000000)) continue; - fg->g->seq_vis[b->a[i]>>1] = 1; - } - st->n = st_n; - - rr.i[0] = 0; rr.i[1] = (uint32_t)-1; - while(1) { - s = iter_flex_asg(fg, &rr, v); - if(!s) break; - if(s->del) continue; - if(fg->g->seq_vis[s->v>>1]) continue; - if(!is_contain_r((*rI), (s->v>>1))) continue; - kv_push(uint64_t, *st, s->v); - } - } - for (i = 0; i < b->n; i++) fg->g->seq_vis[((uint32_t)b->a[i])>>1] = 0; - return cnt; -} - -void flex_asg_t_cleanup(flex_asg_t *fg) -{ - asg_arc_t *p; uint32_t i; - if(fg->n) { - for (i = 0; i < fg->n; i++) { - if(fg->a[i].del) continue; - p = asg_arc_pushp(fg->g); - *p = fg->a[i]; - } - free(fg->g->idx); - fg->g->idx = 0; - fg->g->is_srt = 0; - } else if(fg->need_srt){ - fg->g->is_srt = 0; - } - asg_cleanup(fg->g); - // asg_symm(fg->g); - // asg_arc_del_trans_ul(fg->g, fg->gap_fuzz); -} - -void asg_arc_cut_contain(flex_asg_t *fg, asg64_v *in, asg64_v *in0, R_to_U* rI, float ou_rat, uint32_t only_trans_nn) -{ - // fprintf(stderr, "+[M::%s]\n", __func__); - asg64_v tx = {0,0,0}, tx0 = {0,0,0}, *b = NULL, *b0 = NULL; - uint32_t v, w = (uint32_t)-1, n_vtx = fg->g->n_seq<<1, cnt = 0; asg_arc_t *s; - b = in?in:&tx; b0 = in0?in0:&tx0; b->n = b0->n = 0; - fg->pi.n = fg->n = 0; memset(fg->idx, -1, (fg->g->n_seq<<1)*sizeof(*(fg->idx))); - fg->need_srt = 0; - - memset(fg->g->seq_vis, 0, sizeof(*(fg->g->seq_vis))*n_vtx); - for (v = 0; v < n_vtx; ++v) { - // if((v>>1) == 6236) { - // fprintf(stderr, "[M::%s] v>>1::%u(%c), del::%u, contain::%u, get_arcs(v)::%u, get_arcs(v^1)::%u\n", - // __func__, (v>>1), "+-"[v&1], g->seq[v>>1].del, is_contain_r((*rI), (v>>1)), - // get_arcs(g, v, NULL, 0), get_arcs(g, v^1, NULL, 0)); - // } - // if((v>>1) == 749651) { - // fprintf(stderr, "+[M::%s] v>>1::%u(%c), del::%u, contain::%u, fg->n::%u, fg->need_srt::%u\n", - // __func__, (v>>1), "+-"[v&1], fg->g->seq[v>>1].del, is_contain_r((*rI), (v>>1)), (uint32_t)fg->n, (uint32_t)fg->need_srt); - // } - if (fg->g->seq[v>>1].del) continue; - if(!is_contain_r((*rI), (v>>1))) continue; - if(get_flex_arcs(fg, v^1, &w, 1) == 1) { - flex_arcs0(s, (*fg), w); - if(get_flex_arcs(fg, s->v^1, NULL, 0) == 1) continue; - } - // if((v>>1) == 12321 || (v>>1) == 12334) { - // fprintf(stderr, "-[M::%s] v>>1::%u(%c), del::%u, contain::%u, fg->n::%u, fg->need_srt::%u\n", - // __func__, (v>>1), "+-"[v&1], fg->g->seq[v>>1].del, is_contain_r((*rI), (v>>1)), (uint32_t)fg->n, (uint32_t)fg->need_srt); - // } - - cnt += iter_contain_g(rI, fg, v, b, b0, ou_rat, only_trans_nn); - // if((v>>1) == 12321 || (v>>1) == 12334) { - // fprintf(stderr, "*[M::%s] v>>1::%u(%c), del::%u, contain::%u, fg->n::%u, fg->need_srt::%u\n", - // __func__, (v>>1), "+-"[v&1], fg->g->seq[v>>1].del, is_contain_r((*rI), (v>>1)), (uint32_t)fg->n, (uint32_t)fg->need_srt); - // } - } - // stats_sysm(g); - if(!in) free(tx.a); if(!in0) free(tx0.a); - if(cnt > 0) flex_asg_t_cleanup(fg); - // fprintf(stderr, "-[M::%s]\n", __func__); -} - -void label_contain_dup(asg_t *g, R_to_U* rI, uint32_t v0, asg64_v *b, asg64_v *dump) -{ - asg_arc_t *av; uint32_t nv, v, i; - if(!is_contain_r((*rI), (v0>>1))) return; - b->n = 0; kv_push(uint64_t, *b, v0); - while (b->n) { - v = kv_pop(*b); - if(g->seq_vis[v]&1) continue; - kv_push(uint64_t, *dump, v); - g->seq_vis[v] |= 1; - av = asg_arc_a(g, v); - nv = asg_arc_n(g, v); - for (i = 0; i < nv; ++i) { - if(av[i].del || (g->seq_vis[av[i].v]&1) || (!is_contain_r((*rI), (av[i].v>>1)))) continue; - kv_push(uint64_t, *b, av[i].v); - } - } -} - -/** -void asg_arc_contain_trans_del(asg_t *g, asg64_v *in, asg64_v *in0, R_to_U* rI, float ou_rat) -{ - uint64_t n_vtx = g->n_seq<<1, i, k, v, w, nv, kv; asg_arc_t *av; - memset(g->seq_vis, 0, sizeof((*g->seq_vis))*n_vtx); - for (v = 0; v < n_vtx; ++v) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (i = kv = 0; i < nv; i++) { - if(av[i].del) continue; - if(is_contain_r((*rI), (av[i].v>>1))) kv++; - g->seq_vis[av[i].v] = 1; - } - if(kv <= 0) { - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - g->seq_vis[av[i].v] = 0; - } - continue; - } - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - if(!(is_contain_r((*rI), (av[i].v>>1)))) continue; - - } - - - - if ((g->seq[v>>1].del) || (g->seq_vis[v]&1)) continue; - if(!is_contain_r((*rI), (v>>1))) continue; - // if(get_arcs(g, v, &w, 1) == 1) { - // w = g->arc[w].v; - // if(get_arcs(g, w^1, NULL, 0) == 1) continue; - // } - in0->n = 0; - label_contain_dup(g, rI, v, in, in0); - label_contain_dup(g, rI, v^1, in, in0); - } -} -**/ - -uint32_t if_false_bub_links(uint32_t v, asg_t *g, buf_t *x, asg64_v *b, uint32_t bs, int32_t check_dist) -{ - uint32_t i, mm = 1; - if (g->seq[v>>1].del) return 0; - for (i = bs; i < b->n; i++) { - g->arc[b->a[i]].del = 1; - asg_arc_del(g, g->arc[b->a[i]].v^1, (g->arc[b->a[i]].ul>>32)^1, 1); - } - if (asg_arc_n(g, v) < 2 || get_arcs(g, v, NULL, 0) < 2) mm = 0; - - if(mm) { - mm = 0; - if(asg_bub_pop1_primary_trio(g, NULL, v, check_dist, x, (uint32_t)-1, (uint32_t)-1, 0, - NULL, NULL, NULL, 0, 0, NULL)) { - - for (i = bs; i < b->n; i++) { - g->arc[b->a[i]].del = 0; - asg_arc_del(g, g->arc[b->a[i]].v^1, (g->arc[b->a[i]].ul>>32)^1, 0); - } - - asg_arc_t *av = asg_arc_a(g, v); uint32_t nv = asg_arc_n(g, v); - for (i = 0, b->n = bs; i < nv; i++) { - if (av[i].del) continue; - av[i].del = 1; asg_arc_del(g, av[i].v^1, (av[i].ul>>32)^1, 1); - kv_push(uint64_t, *b, ((uint64_t)(av-g->arc+i))); - } - - if(asg_bub_pop1_primary_trio(g, NULL, x->S.a[0]^1, check_dist, x, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { - mm = 1; - } - } - } - - for (i = bs; i < b->n; i++) { - g->arc[b->a[i]].del = 0; - asg_arc_del(g, g->arc[b->a[i]].v^1, (g->arc[b->a[i]].ul>>32)^1, 0); - } - - return mm; -} - -void asg_arc_cut_bub_links(asg_t *g, asg64_v *in, float len_rat, float sec_len_rat, float ou_rat, uint32_t is_ou, uint64_t check_dist, ma_hit_t_alloc *rev, R_to_U* rI, int32_t max_ext) -{ - asg64_v tx = {0,0,0}, *b = NULL; - uint32_t v, w, t, k, i, n_vtx = g->n_seq<<1, nv, nw, kv, kw, kol, bn, me, mu, cnt = 0, sec_check; - asg_arc_t *av, *aw, *ref; - buf_t x; memset(&x, 0, sizeof(x)); x.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - - if(in) b = in; - else b = &tx; - b->n = 0; - - for (v = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - if(g->seq_vis[v] == 0) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if (nv < 2) continue; - - for (i = kv = kol = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; kol += av[i].ol; - } - if(kv < 2) continue;//must have at least one exact and one inexact - - kv_push(uint64_t, *b, ((((uint64_t)(kol))<<32) | v)); - } - } - - if(rev && rI) memset(g->seq_vis, 0, g->n_seq*2*sizeof(uint8_t)); - radix_sort_srt64(b->a, b->a + b->n); bn = b->n; - for (k = 0; k < bn; k++) { - v = (uint32_t)b->a[k]; - if (g->seq[v>>1].del) continue; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - if (nv < 2 || get_arcs(g, v, NULL, 0) < 2) continue; - - for (i = 0, b->n = bn, sec_check = 0; i < nv; i++) { - if (av[i].del) continue; - - w = av[i].v^1; nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); - if(nw < 2) break; - - for (t = kw = 0, me = mu = (uint32_t)-1; t < nw; t++) { - if(aw[t].del) continue; - kw++; - if(aw[t].v == (v^1)) continue;//note: me is the shortest edge except aw[t], so here is continue - if(aw[t].ol < me) me = aw[t].ol; - if(aw[t].ou < mu) mu = aw[t].ou; - kv_push(uint64_t, *b, ((uint64_t)(aw-g->arc+t))); - } - if(kw < 2) break; - - if(av[i].ol > me*len_rat && av[i].ol > me*sec_len_rat) break; - if(av[i].ol > me*len_rat) sec_check++; - if(is_ou && av[i].ou > mu*ou_rat) break; - } - - if(i < nv) continue; - - if(sec_check) { - for (i = 0, ref = NULL; i < nv; i++) {//forward - if (av[i].del) continue; - if(!ref) { - ref = &(av[i]); - } else { - if(trans_path_check(ref->v, av[i].v, g, rev, rI, max_ext, b)!=1) break; - } - } - - if(i < nv) { - if (b->n < bn + 2) continue;///less than two edges - for (i = bn, ref = NULL; i < b->n; i++) { - if(g->arc[b->a[i]].del) continue; - if(get_arcs(g, g->arc[b->a[i]].ul>>32, NULL, 0)!=2) break; - if(!ref) { - ref = &(g->arc[b->a[i]]); - } else { - if(trans_path_check(ref->v, g->arc[b->a[i]].v, g, rev, rI, max_ext, b)!=1) break; - } - } - if(i < b->n) continue; - } - } - - if(if_false_bub_links(v, g, &x, b, bn, check_dist)) { - for (i = 0; i < nv; ++i) { - if (av[i].del) continue; - av[i].del = 1; asg_arc_del(g, av[i].v^1, (av[i].ul>>32)^1, 1); - } - cnt++; - } - } - - // stats_sysm(g); - if(!in) free(tx.a); - free(x.a); free(x.S.a); free(x.T.a); free(x.b.a); free(x.e.a); - if(cnt > 0) asg_cleanup(g); -} - -void asg_arc_cut_complex_bub_links(asg_t *g, asg64_v *in, float len_rat, float ou_rat, uint32_t is_ou, bub_label_t *b_mask_t) -{ - asg64_v tx = {0,0,0}, *b = NULL; - uint32_t v, w, t, k, i, n_vtx = g->n_seq<<1, nv, nw, kv, kw, kol, me, mu, cnt = 0, bn; - asg_arc_t *av, *aw; - - if(in) b = in; - else b = &tx; - b->n = 0; - - for (v = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - if(g->seq_vis[v] == 0) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if (nv < 2) continue; - - for (i = kv = kol = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; kol += av[i].ol; - } - if(kv < 2) continue;//must have at least one exact and one inexact - - kv_push(uint64_t, *b, ((((uint64_t)(kol))<<32) | v)); - } - } - - radix_sort_srt64(b->a, b->a + b->n); bn = b->n; - for (k = 0; k < bn; k++) { - v = (uint32_t)b->a[k]; - if (g->seq[v>>1].del) continue; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - if (nv < 2 || get_arcs(g, v, NULL, 0) < 2) continue; - - for (i = 0; i < nv; i++) { - if (av[i].del) continue; - - w = av[i].v^1; nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); - if(nw < 2) break; - - for (t = kw = 0, me = mu = (uint32_t)-1; t < nw; t++) { - if(aw[t].del) continue; - kw++; - if(aw[t].v == (v^1)) continue;//note: me is the shortest edge except aw[t], so here is continue - if(aw[t].ol < me) me = aw[t].ol; - if(aw[t].ou < mu) mu = aw[t].ou; - } - if(kw < 2) break; - - if(av[i].ol > me*len_rat) break; - if(is_ou && av[i].ou > mu*ou_rat) break; - } - - if(i < nv) continue; - - for (i = 0; i < nv; ++i) { - if (av[i].del) continue; - av[i].del = 1; asg_arc_del(g, av[i].v^1, (av[i].ul>>32)^1, 1); - kv_push(uint64_t, *b, ((uint64_t)(av-g->arc+i))); - } - // b->a[cnt++] = v; - } - - if(b->n > bn) { - asg_arc_identify_simple_bubbles_multi(g, b_mask_t, 0); - for (k = bn, cnt = 0; k < b->n; k++) { - // if(g->arc[b->a[k]].del) continue; - v = g->arc[b->a[k]].ul>>32; w = g->arc[b->a[k]].v; - if(g->seq_vis[v] || g->seq_vis[v^1] || g->seq_vis[w] || g->seq_vis[w^1]) { - cnt++; continue; - } - g->arc[b->a[k]].del = 0; asg_arc_del(g, g->arc[b->a[k]].v^1, (g->arc[b->a[k]].ul>>32)^1, 0); - } - } - // stats_sysm(g); - if(!in) free(tx.a); - if(cnt > 0) asg_cleanup(g); -} - -#define LIM_LEN 100 - -uint32_t asg_cut_semi_circ(asg_t *g, uint32_t lim_len, uint32_t is_clean) -{ - uint32_t v, t, k, e, ss, i, n_vtx = g->n_seq<<1, nv, kv, nw, cnt = 0; - asg_arc_t *av, *aw; - - for (v = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - - av = asg_arc_a(g, v^1); nv = asg_arc_n(g, v^1); - if(nv <= 1) continue; - for (i = kv = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; if(kv > 1) break; - } - if(kv <= 1) continue; - - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if(nv < 1) continue; - for (i = kv = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; if(kv > 1) break; - } - if(kv != 1) continue; - - for (i = 0; i < nv; ++i) { - if(av[i].del) continue; - t = follow_limit_path(g, v, &e, &ss, NULL, lim_len); - if(ss > lim_len || t == LONG_TIPS || t == LOOP || t == END_TIPS) break;//as kv == 1 - aw = asg_arc_a(g, v^1); nw = asg_arc_n(g, v^1); - for (k = 0; k < nw; k++) { - if (aw[k].del) continue; - if (aw[k].v == (e^1)) { - aw[k].del = 1; - asg_arc_del(g, aw[k].v^1, (aw[k].ul>>32)^1, 1); - cnt++; - } - } - break; //as kv == 1 - } - } - - if(cnt > 0 && is_clean) asg_cleanup(g); - return cnt; -} - -uint32_t asg_cut_chimeric_bub(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, uint32_t normal_len, uint32_t is_clean, telo_end_t *te) -{ - asg64_v tx = {0,0,0}, *b = NULL; - uint32_t v, w, nw, k, n_vtx = g->n_seq<<1, ei[2] = {0}, e, ss, cnt = 0; - asg_arc_t *aw; - if(in) b = in; - else b = &tx; - b->n = 0; - // fprintf(stderr, "[M::%s]\n", __func__); - for (v = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - if(te && te->hh[v>>1]) continue; - ///note: ei[0] and ei[1] are the edge idx - if((get_arcs(g, v, &(ei[0]), 1)!=1) || (get_arcs(g, v^1, &(ei[1]), 1)!=1)) continue; - assert((g->arc[ei[0]].ul>>32) == v && (g->arc[ei[1]].ul>>32) == (v^1)); - if((get_arcs(g, g->arc[ei[0]].v^1, NULL, 0)!=2) || (get_arcs(g, g->arc[ei[1]].v^1, NULL, 0)!=2)) continue; - if(!if_sup_chimeric(&(src[v>>1]), g->seq[v>>1].len, b, 1)) continue; - w = g->arc[ei[0]].v^1; - aw = asg_arc_a(g, w); nw = asg_arc_n(g, w); - for (k = 0; k < nw; k++) { - if (aw[k].del) continue; - if (aw[k].v == (v^1)) { - ss = k; continue; - } - break; - } - // assert(aw[ss].v == (v^1));//this assert does not work, just ignore - if(follow_limit_path(g, aw[k].v, &e, &ss, NULL, (uint32_t)-1) != TWO_INPUT) continue; - if(ss > normal_len) { - w = e; - aw = asg_arc_a(g, w); nw = asg_arc_n(g, w); - for (k = ss = 0; k < nw; k++) { - if (aw[k].del) continue; - ss++; e = aw[k].v; - if(ss > 1) break; - } - if(ss == 1 && e == g->arc[ei[1]].v) asg_seq_del(g, v>>1), cnt++; - } - } - - if(!in) free(tx.a); - if (is_clean && cnt > 0) asg_cleanup(g); - return cnt; -} - -void asg_iterative_semi_circ(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, uint32_t normal_len, uint32_t pop_chimer, telo_end_t *te) -{ - uint64_t occ = 0, s = 1; - while (s) { - s = asg_cut_semi_circ(g, LIM_LEN, 0); - if(pop_chimer) s = s + asg_cut_chimeric_bub(g, src, in, normal_len, 0, te); - occ += s; - } - - // stats_sysm(g); - if(occ) asg_cleanup(g); -} - -uint32_t asg_cut_large_indel(asg_t *g, asg64_v *in, int32_t max_ext, float ou_rat, uint32_t is_ou, uint32_t min_diff) -{ - asg64_v tx = {0,0,0}, *b = NULL; - uint32_t v, w, n_vtx = g->n_seq<<1, i, k, kv, kw, nv, nw, ou_max, ol_max, to_del, cnt = 0; - asg_arc_t *av, *aw, *ve, *we; - if(in) b = in; - else b = &tx; - b->n = 0; - - for (v = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - if(g->seq_vis[v] == 0) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if (nv < 2) continue; - - for (i = kv = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - } - if(kv < 2) continue; - - for (i = 0; i < nv; ++i) { - if(av[i].del || av[i].no_l_indel) continue; - ///means there is a large indel at this edge - kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); - } - } - } - - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - if(g->arc[(uint32_t)b->a[k]].del) continue; - - v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; - if(g->seq[v>>1].del || g->seq[w>>1].del) continue; - nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); - av = asg_arc_a(g, v); aw = asg_arc_a(g, w); - if(nv<=1 && nw <= 1) continue; - - for (i = kv = ou_max = ol_max = 0, ve = NULL; i < nv; ++i) { - if(av[i].del) continue; - if(av[i].v == (w^1)) ve = &(av[i]); - kv++; - if(ou_max < av[i].ou) ou_max = av[i].ou; - if(ol_max < av[i].ol) ol_max = av[i].ol; - } - if (kv < 1) continue; - if (kv >= 2) { - if (is_ou && ve->ou > ou_max*ou_rat) continue; - if ((ve->ol + min_diff) > ol_max) continue; - } - - - for (i = kw = ou_max = ol_max = 0, we = NULL; i < nw; ++i) { - if(aw[i].del) continue; - if(aw[i].v == (v^1)) we = &(aw[i]); - kw++; - if(ou_max < aw[i].ou) ou_max = aw[i].ou; - if(ol_max < aw[i].ol) ol_max = aw[i].ol; - } - if (kw < 1) continue; - if (kw >= 2) { - if (is_ou && we->ou > ou_max*ou_rat) continue; - if ((we->ol + min_diff) > ol_max) continue; - } - - if (kv <= 1 && kw <= 1) continue; - - to_del = 0; - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; - } else if (kv == 1) { - if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; - } - - if (to_del) { - ve->del = we->del = 1, ++cnt; - } - } - // stats_sysm(g); - if(!in) free(tx.a); - if (cnt > 0) asg_cleanup(g); - return cnt; -} - -void debug_edges(asg64_v *dbg, uint32_t *l, uint32_t l_n) { - uint32_t k, k_n, i, m; - for (i = k = 0; i < l_n; i++) { - fprintf(stderr, "# gid-%u: %u\n", i, l[i]); - for (k_n = k + l[i]; k < k_n; k++) { - dbg->a[k] <<= 32; dbg->a[k] += i; - } - } - fprintf(stderr, "# dbg->n: %u\n", (uint32_t)dbg->n); - - radix_sort_srt64(dbg->a, dbg->a + dbg->n); - for (k = 1, i = 0; k <= dbg->n; k++) { - if(k == dbg->n || (dbg->a[k]>>32) != (dbg->a[i]>>32)) { - if(k - i < l_n) { - - for (m = i; m < k; m++) { - fprintf(stderr, "eid->%lu, gid->%u\n", dbg->a[m]>>32, (uint32_t)dbg->a[m]); - } - } - i = k; - } - } -} - -void print_node(asg_t *sg, uint32_t src) -{ - asg_arc_t *av; uint32_t nv, v, i; - v = src<<1; - av = asg_arc_a(sg, v); nv = asg_arc_n(sg, v); - fprintf(stderr, "\n%.*s(%c)\tnv:%u\n", - (int32_t)Get_NAME_LENGTH(R_INF, v>>1), Get_NAME(R_INF, v>>1), "+-"[v&1], nv); - for (i = 0; i < nv; i++) { - fprintf(stderr, "++++++%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\tdel:%u\n", - (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], av[i].ul>>33, - (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].v>>1, av[i].ol, av[i].ou, av[i].del); - } - - v = (src<<1)+1; - av = asg_arc_a(sg, v); nv = asg_arc_n(sg, v); - fprintf(stderr, "\n%.*s(%c)\tnv:%u\n", - (int32_t)Get_NAME_LENGTH(R_INF, v>>1), Get_NAME(R_INF, v>>1), "+-"[v&1], nv); - for (i = 0; i < nv; i++) { - fprintf(stderr, "------%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\tdel:%u\n", - (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], av[i].ul>>33, - (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].v>>1, av[i].ol, av[i].ou, av[i].del); - } -} - -void print_vw_edge(asg_t *sg, uint32_t vid, uint32_t wid, const char *cmd) -{ - asg_arc_t *av; uint32_t nv, i, sid, eid; - if(vid >= sg->n_seq || wid >= sg->n_seq) return; - - sid = vid; eid = wid; - av = asg_arc_a(sg, (sid<<1)); nv = asg_arc_n(sg, (sid<<1)); - for (i = 0; i < nv; i++) { - if((av[i].v>>1) == eid) { - fprintf(stderr, "[%s]\t%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\tdel:%u\n", cmd, - (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], av[i].ul>>33, - (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].v>>1, av[i].ol, av[i].ou, av[i].del); - break; - } - } - av = asg_arc_a(sg, ((sid<<1)+1)); nv = asg_arc_n(sg, ((sid<<1)+1)); - for (i = 0; i < nv; i++) { - if((av[i].v>>1) == eid) { - fprintf(stderr, "[%s]\t%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\tdel:%u\n", cmd, - (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], av[i].ul>>33, - (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].v>>1, av[i].ol, av[i].ou, av[i].del); - break; - } - } - - sid = wid; eid = vid; - av = asg_arc_a(sg, (sid<<1)); nv = asg_arc_n(sg, (sid<<1)); - for (i = 0; i < nv; i++) { - if((av[i].v>>1) == eid) { - fprintf(stderr, "[%s]\t%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\tdel:%u\n", cmd, - (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], av[i].ul>>33, - (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].v>>1, av[i].ol, av[i].ou, av[i].del); - break; - } - } - av = asg_arc_a(sg, ((sid<<1)+1)); nv = asg_arc_n(sg, ((sid<<1)+1)); - for (i = 0; i < nv; i++) { - if((av[i].v>>1) == eid) { - fprintf(stderr, "[%s]\t%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\tdel:%u\n", cmd, - (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], av[i].ul>>33, - (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].v>>1, av[i].ol, av[i].ou, av[i].del); - break; - } - } - // if(i >= nv) fprintf(stderr, "[%s]\tno edges\n", cmd); -} - -void prt_spec_edge(asg_t *rg, ma_hit_t_alloc *src, uint32_t tot_rid, uint32_t vid, uint32_t wid, ug_opt_t *uopt, const char *cmd) -{ - if(vid >= tot_rid) return; - uint32_t k, qn, tn; int32_t r; asg_arc_t p; ma_hit_t_alloc *s = &(src[vid]); - for (k = 0; k < s->length; k++) { - qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); - if(qn == vid && tn == wid) { - r = ma_hit2arc(&(s->buffer[k]), rg->seq[qn].len, rg->seq[tn].len, uopt->max_hang, asm_opt.max_hang_rate, uopt->min_ovlp, &p); - fprintf(stderr, "[M::%s::]%s\tqn::%u(%c)\tq::[%u,\t%u)\t%c\ttn::%u(%c)\tt::[%u,\t%u)\n", - __func__, cmd, qn, (r>=0)?("+-"[(p.ul>>32)&1]):('*'), Get_qs(s->buffer[k]), Get_qe(s->buffer[k]), - "+-"[s->buffer[k].rev], - tn, (r>=0)?("+-"[p.v&1]):('*'), Get_ts(s->buffer[k]), Get_te(s->buffer[k])); - } - } -} - -int32_t gen_spec_edge(asg_t *rg, ug_opt_t *uopt, uint32_t v, uint32_t w, asg_arc_t *t) -{ - uint32_t k, qn, tn; int32_t r; ma_hit_t_alloc *s = &(uopt->sources[v>>1]); asg_arc_t p; - for (k = 0; k < s->length; k++) { - qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); - if(tn != (w>>1)) continue; - r = ma_hit2arc(&(s->buffer[k]), rg->seq[qn].len, rg->seq[tn].len, uopt->max_hang, asm_opt.max_hang_rate, uopt->min_ovlp, &p); - if(r < 0) continue; - if((p.ul>>32) != v || p.v != w) continue; - *t = p; t->ou = 0; - return 1; - } - return -1; -} - -void filter_sg_by_ug(asg_t *rg, ma_ug_t *ug, ug_opt_t *uopt) -{ - uint32_t i, m, v, w, nv, n_vx, vx, wx; int32_t r; - asg_arc_t *av = NULL; ma_utg_t *u = NULL; asg_arc_t *p, t; - n_vx = rg->n_seq; rg->n_arc = 0; - for (v = 0; v < n_vx; v++) rg->seq[v].del = (!!1); - - for (i = 0; i < ug->g->n_seq; ++i) { - ug->g->seq[i].c = PRIMARY_LABLE;; - if(ug->g->seq[i].del) continue; - u = &(ug->u.a[i]); - for (m = 0; m < u->n; m++) rg->seq[u->a[m]>>33].del = (!!0); - for (m = 0; (m + 1) < u->n; m++) { - v = u->a[m]>>32; w = u->a[m+1]>>32; - r = gen_spec_edge(rg, uopt, v, w, &t); - assert(r >= 0); p = asg_arc_pushp(rg); *p = t; - - r = gen_spec_edge(rg, uopt, w^1, v^1, &t); - assert(r >= 0); p = asg_arc_pushp(rg); *p = t; - } - - - v = i<<1; nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); - for (m = 0; m < nv; m++) { - if(av[m].del) continue; - w = av[m].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)); - - r = gen_spec_edge(rg, uopt, vx, wx, &t); - assert(r >= 0); p = asg_arc_pushp(rg); *p = t; - - // r = gen_spec_edge(rg, uopt, wx^1, vx^1, &t); - // assert(r >= 0); p = asg_arc_pushp(rg); *p = t; - } - - v = (i<<1)+1; nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); - for (m = 0; m < nv; m++) { - if(av[m].del) continue; - w = av[m].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)); - - r = gen_spec_edge(rg, uopt, vx, wx, &t); - assert(r >= 0); p = asg_arc_pushp(rg); *p = t; - - // r = gen_spec_edge(rg, uopt, wx^1, vx^1, &t); - // assert(r >= 0); p = asg_arc_pushp(rg); *p = t; - } - - if(u->circ) { - v = w = i<<1; - 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)); - r = gen_spec_edge(rg, uopt, vx, wx, &t); - assert(r >= 0); p = asg_arc_pushp(rg); *p = t; - - v = w = (i<<1)^1; - 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)); - r = gen_spec_edge(rg, uopt, vx, wx, &t); - assert(r >= 0); p = asg_arc_pushp(rg); *p = t; - } - } - - free(rg->idx); - rg->idx = 0; - rg->is_srt = 0; - asg_cleanup(rg); - asg_symm(rg); - - - /*******************************for debug************************************/ - // ma_ug_t *dbg = ma_ug_gen(rg); - // for (i = 0; i < dbg->g->n_seq; ++i) dbg->g->seq[i].c = PRIMARY_LABLE; - // cmp_untig_graph(dbg, ug); - /*******************************for debug************************************/ -} - -void prt_specfic_sge(asg_t *g, uint32_t src, uint32_t dst, const char* cmd) -{ - uint32_t k, v, w, nv; asg_arc_t *av; - fprintf(stderr, "[M::%s::%s] src::%.*s(id::%u), dst::%.*s(id::%u)\n", __func__, cmd, - (int)Get_NAME_LENGTH(R_INF, src), Get_NAME(R_INF, src), src, - (int)Get_NAME_LENGTH(R_INF, dst), Get_NAME(R_INF, dst), dst); - v = src<<1; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (k = 0; k < nv; ++k) { - if ((av[k].v>>1) == dst) { - w = av[k].v; - fprintf(stderr, "[M::%s::]\t%.*s(%c)\t%.*s(%c)\tou::%u\n", __func__, - (int)Get_NAME_LENGTH(R_INF, (v>>1)), Get_NAME(R_INF, (v>>1)), "+-"[v&1], - (int)Get_NAME_LENGTH(R_INF, (w>>1)), Get_NAME(R_INF, (w>>1)), "+-"[w&1], av[k].ou); - } - } - - v = (src<<1)+1; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (k = 0; k < nv; ++k) { - if ((av[k].v>>1) == dst) { - w = av[k].v; - fprintf(stderr, "[M::%s::]\t%.*s(%c)\t%.*s(%c)\tou::%u\n", __func__, - (int)Get_NAME_LENGTH(R_INF, (v>>1)), Get_NAME(R_INF, (v>>1)), "+-"[v&1], - (int)Get_NAME_LENGTH(R_INF, (w>>1)), Get_NAME(R_INF, (w>>1)), "+-"[w&1], av[k].ou); - } - } -} - -flex_asg_t *init_flex_asg_t(asg_t *g, ma_hit_t_alloc* src, int64_t min_ovlp, int64_t max_hang, int64_t max_hang_rate, int64_t gap_fuzz) -{ - flex_asg_t *z; CALLOC(z, 1); - z->g = g; z->src = src; z->min_ovlp = min_ovlp; z->gap_fuzz = gap_fuzz; - z->max_hang = max_hang; z->max_hang_rate = max_hang_rate; - MALLOC(z->idx, (z->g->n_seq<<1)); memset(z->idx, -1, (z->g->n_seq<<1)*sizeof(*(z->idx))); - return z; -} - -void des_flex_asg_t(flex_asg_t *z) -{ - free(z->idx); free(z->pi.a); free(z->a); -} - - -void print_raw_u2rgfa_seq(all_ul_t *aln, R_to_U* rI, uint32_t is_detail) -{ - uint64_t id, a_n, k, z; uc_block_t *a = NULL; - kvec_t(uint8_t) ff; kv_init(ff); - for (id = 0; id < aln->n; id++) { - a = aln->a[id].bb.a; a_n = aln->a[id].bb.n; - if(a_n == 0) continue; - fprintf(stderr,"\n%.*s\tid::%lu\trlen::%u", (int32_t)aln->nid.a[id].n, aln->nid.a[id].a, id, aln->a[id].rlen); - kv_resize(uint8_t, ff, a_n); memset(ff.a, 0, a_n*sizeof((*(ff.a)))); - if(is_detail) { - fprintf(stderr, "\n"); - for (k = 0; k < a_n; k++) { - if(ff.a[k]) continue; - for (z = k; z != (uint32_t)-1; z = a[z].aidx) { - fprintf(stderr, "%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tid::%u\ttl::%lu\tc::%u\n", - (int)Get_NAME_LENGTH(R_INF, a[z].hid), Get_NAME(R_INF, a[z].hid), "+-"[a[z].rev], - a[z].qs, a[z].qe, a[z].ts, a[z].te, a[z].hid, Get_READ_LENGTH(R_INF, a[z].hid), - rI?is_contain_r((*rI), a[z].hid):0); - assert(ff.a[z] == 0); - ff.a[z] = 1; - } - fprintf(stderr, "************\n"); - } - } else { - fprintf(stderr, "\t"); - for (k = 0; k < a_n; k++) { - if(ff.a[k]) continue; - for (z = k; z != (uint32_t)-1; z = a[z].aidx) { - fprintf(stderr, "%.*s\t", - (int)Get_NAME_LENGTH(R_INF, a[z].hid), Get_NAME(R_INF, a[z].hid)); - assert(ff.a[z] == 0); - ff.a[z] = 1; - } - fprintf(stderr, "\n"); - } - } - } - kv_destroy(ff); -} - - -void post_rescue(ug_opt_t *uopt, asg_t *sg, ma_hit_t_alloc *src, ma_hit_t_alloc *rev, R_to_U* rI, bub_label_t *b_mask_t, long long no_trio_recover, uint8_t *cmk) -{ - rescue_contained_reads_aggressive(NULL, sg, src, uopt->coverage_cut, rI, uopt->max_hang, uopt->min_ovlp, 10, 1, 0, NULL, NULL, b_mask_t); - rescue_missing_overlaps_aggressive(NULL, sg, src, uopt->coverage_cut, rI, uopt->max_hang, uopt->min_ovlp, 1, 0, NULL, b_mask_t); - rescue_missing_overlaps_backward(NULL, sg, src, uopt->coverage_cut, rI, uopt->max_hang, uopt->min_ovlp, 10, 1, 0, b_mask_t); - if(cmk) rescue_chimeric_reads_aggressive(NULL, sg, src, uopt->coverage_cut, rI, uopt->max_hang, uopt->min_ovlp, 10, 1, 0, NULL, NULL, b_mask_t, cmk); - // rescue_wrong_overlaps_to_unitigs(NULL, sg, sources, reverse_sources, coverage_cut, ruIndex, - // max_hang_length, mini_overlap_length, bubble_dist, NULL); - // rescue_no_coverage_aggressive(sg, sources, reverse_sources, &coverage_cut, ruIndex, max_hang_length, - // mini_overlap_length, bubble_dist, 10); - set_hom_global_coverage(&asm_opt, sg, uopt->coverage_cut, src, rev, rI, uopt->max_hang, uopt->min_ovlp); - rescue_bubble_by_chain(sg, uopt->coverage_cut, src, rev, (asm_opt.max_short_tip*2), 0.15, 3, rI, 0.05, 0.9, uopt->max_hang, uopt->min_ovlp, 10, uopt->gap_fuzz, b_mask_t, no_trio_recover, cmk); -} - -void ul_clean_gfa(ug_opt_t *uopt, asg_t *sg, ma_hit_t_alloc *src, ma_hit_t_alloc *rev, R_to_U* rI, int64_t clean_round, double min_ovlp_drop_ratio, double max_ovlp_drop_ratio, -double ou_drop_rate, int64_t max_tip, int64_t gap_fuzz, bub_label_t *b_mask_t, int32_t is_ou, int32_t is_trio, uint32_t ou_thres, uint8_t *cmk, char *o_file) -{ - #define HARD_OU_DROP 0.75 - #define HARD_OL_DROP 0.6 - #define HARD_OL_SEC_DROP 0.85 - #define HARD_ORTHOLOGY_DROP 0.4 - double step = - (clean_round==1?max_ovlp_drop_ratio:((max_ovlp_drop_ratio-min_ovlp_drop_ratio)/(clean_round-1))); - double drop = min_ovlp_drop_ratio; - int64_t i; asg64_v bu = {0,0,0}, ba = {0,0,0}; uint32_t l_drop = 2000; flex_asg_t *fg = NULL; uint32_t min_diff = 0, step_diff = 2000; - if(is_ou) fg = init_flex_asg_t(sg, uopt->sources, uopt->min_ovlp, uopt->max_hang, asm_opt.max_hang_rate, gap_fuzz); - // if(is_ou) update_sg_uo(sg, src);///do not do it here - // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.dirty.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); - // exit(1); - // print_raw_u2rgfa_seq(&UL_INF, rI, 1); - // exit(1); - // fprintf(stderr, "%.*s\tid::%u\tis_c::%u\n", - // (int)Get_NAME_LENGTH(R_INF, 10785), Get_NAME(R_INF, 10785), 10785, is_contain_r((*rI), 10785)); - // fprintf(stderr, "%.*s\tid::%u\tis_c::%u\n", - // (int)Get_NAME_LENGTH(R_INF, 10790), Get_NAME(R_INF, 10790), 10790, is_contain_r((*rI), 10790)); - // fprintf(stderr, "%.*s\tid::%u\tis_c::%u\n", - // (int)Get_NAME_LENGTH(R_INF, 10805), Get_NAME(R_INF, 10805), 10805, is_contain_r((*rI), 10805)); - // fprintf(stderr, "%.*s\tid::%u\tis_c::%u\n", - // (int)Get_NAME_LENGTH(R_INF, 10809), Get_NAME(R_INF, 10809), 10809, is_contain_r((*rI), 10809)); - // fprintf(stderr, "%.*s\tid::%u\tis_c::%u\n", - // (int)Get_NAME_LENGTH(R_INF, 10819), Get_NAME(R_INF, 10819), 10819, is_contain_r((*rI), 10819)); - // debug_info_of_specfic_node("m64011_190830_220126/47516220/ccs", sg, rI, "beg-0"); - // debug_info_of_specfic_node("bcb40bcc-d9cf-48e6-88ee-47ac3dde22ff", sg, rI, "beg-0"); - - if(asm_opt.is_ont) asg_arc_cut_weak(sg, &bu, max_tip, 0.975, 0, is_ou, 0, 1, 16, UL_COV_THRES-1, 0, rev, NULL, NULL); - - asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te);///p_telo - // fprintf(stderr, "[M::%s] count_edges_v_w(sg, 49778, 49847)->%ld\n", __func__, count_edges_v_w(sg, 49778, 49847)); - // if(is_ou) dedup_contain_g(uopt, sg); - for (i = 0; i < clean_round; i++, drop += step) { - if(drop > max_ovlp_drop_ratio) drop = max_ovlp_drop_ratio; - if(is_ou) { - if(drop <= 0.500001) min_diff = step_diff>>1; - else min_diff = step_diff; - } - - if(asm_opt.is_ont) { - asg_arc_cut_weak(sg, &bu, max_tip, 0.975, 0, is_ou, 0, 1, 16, UL_COV_THRES-1, 0, rev, NULL, NULL); - asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); - } - // fprintf(stderr, "(0):i->%ld, drop->%f\n", i, drop); - // prt_specfic_sge(sg, 10531, 10519, "--0--"); - - // print_vw_edge(sg, 34156, 34090, "0"); - // stats_chimeric(sg, src, &bu); - if(!is_ou) asg_iterative_semi_circ(sg, src, &bu, max_tip, 1, uopt->te);///p_telo - asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 1); - asg_arc_cut_chimeric(sg, src, &bu, is_ou?ou_thres:(uint32_t)-1, uopt->te);///p_telo - - asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); - // prt_specfic_sge(sg, 10531, 10519, "--1--"); - asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 0); - asg_arc_cut_inexact(sg, src, &bu, max_tip, is_ou, is_trio, min_diff, ou_drop_rate/**, NULL**//**&dbg**/); - // debug_edges(&dbg, d, 2); - asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); - // prt_specfic_sge(sg, 10531, 10519, "--2--"); - - asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 1); - asg_arc_cut_length(sg, &bu, max_tip, drop, ou_drop_rate, is_ou, is_trio, 1, min_diff, 1, NULL, NULL, NULL); - asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); - - // prt_specfic_sge(sg, 10531, 10519, "--3--"); - // if(is_ou) asg_arc_cut_contain(fg, &bu, &ba, rI, ((i+1)te); - // prt_specfic_sge(sg, 10531, 10519, "--5--"); - - // if(i == 3) { - // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.dirty3.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); - // // exit(1); - // } - /** - if(cmk && asm_opt.chemical_cov > FORCE_CUT) { - asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 0); - asg_arc_cut_chimeric_cmk(sg, &bu, max_tip, 1.1, 1.1, is_ou, 1, 1, 1, cmk, asm_opt.chemical_cov); - asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); - } - **/ - - - if(is_ou) { - if(ul_refine_alignment(uopt, sg)) update_sg_uo(sg, src); - if(clean_contain_g(uopt, sg, 1)) update_sg_uo(sg, src); - } - } - - if(asm_opt.is_ont) { - asg_arc_cut_weak(sg, &bu, max_tip, 0.975, 0, is_ou, 0, 1, 16, UL_COV_THRES-1, 0, rev, NULL, NULL); - asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); - } - - if(is_ou) min_diff = step_diff; - // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.dirty4.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); - // debug_info_of_specfic_node("m64012_190921_234837/111673711/ccs", sg, rI, "end"); - // debug_info_of_specfic_node("m64011_190830_220126/95028102/ccs", sg, rI, "end"); - if(is_ou) { - asg_arc_cut_contain(fg, &bu, &ba, rI, ou_drop_rate, 0); - asg_arc_cut_contain(fg, &bu, &ba, rI, -1, 1); - // dedup_contain_g(uopt, sg); - if(clean_contain_g(uopt, sg, 1)) update_sg_uo(sg, src); - } - if(!is_ou) asg_iterative_semi_circ(sg, src, &bu, max_tip, 1, uopt->te); - - // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.dirty5.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); - - asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 0); - asg_cut_large_indel(sg, &bu, max_tip, HARD_OU_DROP, is_ou, min_diff);///shoule we ignore ou here? - asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); - - // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.dirty6.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); - - if(!is_ou) { - ///asg_arc_del_triangular_directly might be unnecessary - asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 0); - asg_arc_cut_length(sg, &bu, max_tip, HARD_ORTHOLOGY_DROP/**min_ovlp_drop_ratio**/, ou_drop_rate, is_ou, 0/**is_trio**/, is_ou?1:0, min_diff, 1, rev, rI, NULL); - asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); - - // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.dirty7.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); - - asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 0); - asg_arc_cut_length(sg, &bu, max_tip, min_ovlp_drop_ratio, ou_drop_rate, is_ou, 0/**is_trio**/, is_ou?1:0, min_diff, 1, rev, rI, &l_drop); - asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); - } else { - min_diff = step_diff; l_drop = 6000; - asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 0); - asg_arc_cut_length(sg, &bu, max_tip, 0.3, 0.9, is_ou, is_trio, 1, min_diff, 8, NULL, NULL, &l_drop); - asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); - } - - // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.dirty8.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); - - if(!is_ou) asg_cut_semi_circ(sg, LIM_LEN, 1); - /** - rescue_contained_reads_aggressive(NULL, sg, src, uopt->coverage_cut, rI, uopt->max_hang, uopt->min_ovlp, 10, 1, 0, NULL, NULL, b_mask_t); - rescue_missing_overlaps_aggressive(NULL, sg, src, uopt->coverage_cut, rI, uopt->max_hang, uopt->min_ovlp, 1, 0, NULL, b_mask_t); - rescue_missing_overlaps_backward(NULL, sg, src, uopt->coverage_cut, rI, uopt->max_hang, uopt->min_ovlp, 10, 1, 0, b_mask_t); - // rescue_wrong_overlaps_to_unitigs(NULL, sg, sources, reverse_sources, coverage_cut, ruIndex, - // max_hang_length, mini_overlap_length, bubble_dist, NULL); - // rescue_no_coverage_aggressive(sg, sources, reverse_sources, &coverage_cut, ruIndex, max_hang_length, - // mini_overlap_length, bubble_dist, 10); - set_hom_global_coverage(&asm_opt, sg, uopt->coverage_cut, src, rev, rI, uopt->max_hang, uopt->min_ovlp); - rescue_bubble_by_chain(sg, uopt->coverage_cut, src, rev, (asm_opt.max_short_tip*2), 0.15, 3, rI, 0.05, 0.9, uopt->max_hang, uopt->min_ovlp, 10, uopt->gap_fuzz, b_mask_t); - **/ - post_rescue(uopt, sg, src, rev, rI, b_mask_t, is_ou, cmk); - - ug_ext_gfa(uopt, sg, ug_ext_len); - - // if(is_ou) dedup_contain_g(uopt, sg); - // exit(1) - - output_unitig_graph(sg, uopt->coverage_cut, o_file, src, rI, uopt->max_hang, uopt->min_ovlp); - // exit(1); - // flat_bubbles(sg, ruIndex->is_het); free(ruIndex->is_het); ruIndex->is_het = NULL; - flat_soma_v(sg, src, rI); - - ///note: although the above functions will not change the UL part, but it will change the read graph - ///so it is necessary to run update_sg_uo - if(is_ou) { - update_sg_uo(sg, src); - } - if(is_ou) { - des_flex_asg_t(fg); free(fg); - } - // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); - // exit(1); - // print_node(sg, 17078); //print_node(sg, 8311); print_node(sg, 8294); - - free(bu.a); free(ba.a); -} - -int32_t gen_ext_tip(uint32_t v, asg_t *sg, ug_opt_t *uopt, uint8_t *ff, uint32_t min_ovlp, uint64_t *res, uint64_t *path_len) -{ - uint32_t k, qn, tn, cc, ccu; int32_t r; asg_arc_t p, pmax; - ma_hit_t_alloc *s = &(uopt->sources[v>>1]); memset(&pmax, 0, sizeof(pmax)); pmax.ol = 0; - for (k = 0; k < s->length; k++) { - qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); - r = ma_hit2arc(&(s->buffer[k]), sg->seq[qn].len, sg->seq[tn].len, uopt->max_hang, asm_opt.max_hang_rate, uopt->min_ovlp, &p); - if(r < 0) continue; - if((p.ul>>32) != v) continue; - if(p.ol < min_ovlp) continue; - if(p.ol > pmax.ol) pmax = p; - } - if(pmax.ol == 0) return 0; - - tn = pmax.v>>1; - if((!(sg->seq[tn].del)) || (ff[tn])) return -1;///not a tip - get_R_to_U(uopt->ruIndex, tn, &cc, &ccu); - if(ccu == 1) return -1; - if((cc != (uint32_t)-1) && - ((!(sg->seq[cc].del)) || (ff[cc]))) { - return -1;///contained in an existing read - } - - if((*path_len) >= sg->seq[v>>1].len) (*path_len) -= sg->seq[v>>1].len; - else (*path_len) = 0; - (*path_len) += (uint32_t)(pmax.ul) + sg->seq[pmax.v>>1].len; - - uint32_t v0 = v; (*res) = pmax.v; - v = (pmax.v^1); s = &(uopt->sources[v>>1]); pmax.ol = 0; - for (k = 0; k < s->length; k++) { - qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); - r = ma_hit2arc(&(s->buffer[k]), sg->seq[qn].len, sg->seq[tn].len, uopt->max_hang, asm_opt.max_hang_rate, uopt->min_ovlp, &p); - if(r < 0) continue; - if((p.ul>>32) != v) continue; - if(p.ol < min_ovlp) continue; - if(p.ol > pmax.ol) pmax = p; - } - if((pmax.v^1) == v0) { - ff[(*res)>>1] = 1; return 1; - } - (*res) = (uint64_t)-1; return -1;///not the longest overlap -} - -void ug_ext_gfa(ug_opt_t *uopt, asg_t *sg, uint32_t max_len) -{ - asg_arc_t *av; asg64_v res, idx; kv_init(res); kv_init(idx); - uint32_t v, nv, k, z, nvtx = sg->n_seq<<1, tip_n = uopt->tipsLen + 1, s, e; - uint8_t *ff; CALLOC(ff, sg->n_seq); int32_t rr; uint64_t v0, w, bn, plen; - asg_arc_t t, *p; - for (v = 0; v < nvtx; v++) { - if(sg->seq[v>>1].del) continue; - av = asg_arc_a(sg, v); nv = asg_arc_n(sg, v); - for (k = 0; k < nv && av[k].del; k++); - if(k < nv) continue; - for (z = 0, v0 = v, rr = 0, bn = res.n, plen = sg->seq[v0>>1].len; z < tip_n || plen < max_len; z++) { - rr = gen_ext_tip(v0, sg, uopt, ff, 2000, &w, &plen); - if(rr <= 0) break; - kv_push(uint64_t, res, (v0<<32)|w); v0 = w; - } - if(rr < 0 || (z >= tip_n && plen >= max_len)) { - for (z = bn; z < res.n; z++) { - ff[((uint32_t)res.a[z])>>1] = 0; - } - res.n = bn; - } - if(res.n > bn) { - bn <<= 32; bn |= (uint64_t)res.n; - kv_push(uint64_t, idx, bn); - } - } - - if(idx.n > 0) { - for (k = 0; k < idx.n; k++) { - s = idx.a[k]>>32; e = (uint32_t)idx.a[k]; - for (z = s; z < e; z++) { - v = res.a[z]>>32; w = (uint32_t)res.a[z]; - assert((!sg->seq[v>>1].del) && (sg->seq[w>>1].del)); - sg->seq[w>>1].del = 0; - rr = gen_spec_edge(sg, uopt, v, w, &t); assert(rr >= 0); - p = asg_arc_pushp(sg); *p = t; - rr = gen_spec_edge(sg, uopt, w^1, v^1, &t); assert(rr >= 0); - p = asg_arc_pushp(sg); *p = t; - } - } - - free(sg->idx); sg->idx = 0; sg->is_srt = 0; asg_cleanup(sg); - fprintf(stderr, "[M::%s::] # tips::%u\n", __func__, (uint32_t)idx.n); - } - - free(ff); kv_destroy(res); kv_destroy(idx); -} - - -bubble_type *gen_bubble_chain(asg_t *sg, ma_ug_t *ug, ug_opt_t *uopt, uint8_t **ir_het, uint8_t avoid_het) -{ - kvec_asg_arc_t_warp new_rtg_edges; - kv_init(new_rtg_edges.a); - hap_cov_t *cov = NULL; - bubble_type *bub = NULL; - - asg_t *copy_sg = copy_read_graph(sg); - ma_ug_t *copy_ug = copy_untig_graph(ug); - // fprintf(stderr, "0[M::%s]\n", __func__); - adjust_utg_by_primary(©_ug, copy_sg, TRIO_THRES, uopt->sources, uopt->reverse_sources, uopt->coverage_cut, - uopt->tipsLen, uopt->tip_drop_ratio, uopt->stops_threshold, uopt->ruIndex, uopt->chimeric_rate, uopt->drop_ratio, - uopt->max_hang, uopt->min_ovlp, &new_rtg_edges, &cov, uopt->b_mask_t, 0, 0); - ma_ug_destroy(copy_ug); copy_ug = NULL; - asg_destroy(copy_sg); copy_sg = NULL; - // fprintf(stderr, "1[M::%s]\n", __func__); - CALLOC(bub, 1); (*ir_het) = cov->t_ch->ir_het; - cov->t_ch->ir_het = NULL; cov->is_r_het = NULL; - if(!avoid_het) { - identify_bubbles(ug, bub, (*ir_het), NULL); - } else { - uint8_t *pr_het; CALLOC(pr_het, sg->n_seq); - identify_bubbles_recal_poy(sg, ug, bub, pr_het, uopt->sources, uopt->ruIndex, NULL); - free(pr_het); - } - - // fprintf(stderr, "2[M::%s]\n", __func__); - kv_destroy(new_rtg_edges.a); destory_hap_cov_t(&cov); - if(asm_opt.purge_level_primary == 0) {///all nodes are het - uint32_t k; - for (k = 0; k < ug->g->n_seq; k++) { - if(IF_HOM(k, *bub)) bub->index[k] = bub->f_bub+1; - } - } - // fprintf(stderr, "3[M::%s]\n", __func__); - return bub; -} - -void clear_path_dp_t(path_dp_t *x, asg_t *g) -{ - uint32_t n_vx = g->n_seq<<1; - x->ref.n = x->pat.n = x->pat_cor.n = 0; - kv_resize(uint8_t, x->g_flt, n_vx); x->g_flt.n = n_vx; - memset(x->g_flt.a, 0, sizeof(*(x->g_flt.a))*x->g_flt.n); -} - -void clear_ubuf_t(ubuf_t *x, asg_t *g, all_ul_t *ul_idx, int32_t up_dp) -{ - uint32_t n_vx = g->n_seq<<1; - x->a.n = x->S.n = x->T.n = x->b.n = x->e.n = 0; - kv_resize(uinfo_t, x->a, n_vx); x->a.n = n_vx; memset(x->a.a, 0, sizeof(*(x->a.a))*x->a.n); - if(up_dp) clear_path_dp_t(&(x->dp), g); -} - -uint64_t get_ul_read_weight(all_ul_t *ul, uint32_t *prg, uinfo_t *g_idx, ul_vec_t *p, uint32_t ii, uint32_t v, uint32_t w) -{ - assert((!p->bb.a[ii].base)&&(p->bb.a[ii].hid == (v>>1))&&(p->bb.a[ii].el)&&(p->bb.a[ii].pchain)); - if(p->bb.a[ii].aidx == (uint32_t)-1) return 0; ///not connected - uc_block_t *li = NULL, *lk = NULL; uint32_t li_v, lk_v; - li = &(p->bb.a[ii]); li_v = (((uint32_t)(li->hid))<<1)|((uint32_t)(li->rev)); //li_v^=1; - if(li_v != v) return 0; - - for (lk = &(p->bb.a[li->aidx]), w^=1; lk; ) { - lk_v = (((uint32_t)(lk->hid))<<1)|((uint32_t)(lk->rev)); //lk_v^=1; - while (lk_v != (w^1)) { - if(g_idx[w].p==(uint32_t)-1) break; - w = g_idx[w].p; - } - - if(lk_v == (w^1)) { - - } - - lk = ((lk->aidx==(uint32_t)-1)?NULL:&(p->bb.a[lk->aidx])); - - } - return 1; -} - -#define arc_first(g, v) ((g)->arc[(g)->idx[(v)]>>32]) -#define arc_cnt(g, v) ((uint32_t)(g)->idx[(v)]) - -uint64_t ulg_len_check(asg_t *g, uint32_t v, uc_block_t *p) -{ - // if(!(((v&1) && (p->ts==0)) || (((v&1)==0) && (p->te==g->seq[v>>1].len)))) { - // fprintf(stderr, "\n[M::%s::] v>>1:%u, v&1:%u, ts:%u, te:%u, tlen:%u, qs:%u, qe:%u, pidx:%u, aidx:%u, flag:%u\n", - // __func__, v>>1, v&1, p->ts, p->te, g->seq[v>>1].len, p->qs, p->qe, p->pidx, p->aidx, flag); - // } - // assert(((v&1) && (p->ts==0)) || (((v&1)==0) && (p->te==g->seq[v>>1].len))); - if(!(((v&1) && (p->ts==0)) || (((v&1)==0) && (p->te==g->seq[v>>1].len)))) return 0; - // if((v&1) && (p->ts!=0)) return 0; - // if(((v&1)==0) && (p->te!=g->seq[v>>1].len)) return 0; - if(p->ts==0 && p->te==g->seq[v>>1].len) return 1; - int32_t ol = arc_first(g, v).ol;///max len - int32_t tl = p->te - p->ts; - tl -= ol; - if(tl > 20000 || tl > (g->seq[v>>1].len*0.2)) return 1; - return 0; -} - -void update_l_coord(asg_t *g, uint64_t o_s, uint32_t v, uc_block_t *p, uint64_t *s, uint64_t *e) -{ - // if(!(((v&1) && (p->ts==0)) || (((v&1)==0) && (p->te==g->seq[v>>1].len)))) { - // fprintf(stderr, "\n[M::%s::] v>>1:%u, v&1:%u, ts:%u, te:%u, tlen:%u\n", - // __func__, v>>1, v&1, p->ts, p->te, g->seq[v>>1].len); - // } - // assert(((v&1) && (p->ts==0)) || (((v&1)==0) && (p->te==g->seq[v>>1].len))); - // assert((v&1) && (p->ts==0)); - // assert(((v&1)==0) && (p->te==g->seq[v>>1].len)); - if(((v&1)==0)) { - (*s) = o_s + p->ts; (*e) = o_s + p->te; - } else { - (*s) = o_s + g->seq[v>>1].len - p->te; - (*e) = o_s + g->seq[v>>1].len - p->ts; - } -} - -int64_t gen_ul_pat_seq(uc_block_t *a, path_dp_t *b, all_ul_t *ul, uint64_t idx, asg_t *g, uint32_t v, uint32_t is_backward, uint64_t *rl) -{ - uint32_t m = 0, pv, ai, pi; uint64_t *t, l = 0, tt, s, e; b->pat.n = 0; b->pat_cor.n = 0; - if(is_backward) { - for (ai = idx, l = 0; ai != (uint32_t)-1; ai = a[ai].pidx) { - pv = (((uint32_t)(a[ai].hid))<<1)|((uint32_t)(a[ai].rev)); pv^=1; - if((a[ai].pidx != (uint32_t)-1) && (!ulg_len_check(g, pv, &(a[ai])))) break; - if((b->pat.n > 0) && (!ulg_len_check(g, pv^1, &(a[ai])))) break; - if(pv == v) m++; - kv_pushp(uint64_t, b->pat, &t); - update_l_coord(g, l, pv, &(a[ai]), &s, &e); - kv_push(uint64_t, b->pat_cor, ((s<<32)|e)); - (*t) = pv; (*t) |= (l<<32); - - if(a[ai].pidx != (uint32_t)-1) l += a[ai].pdis; - else l += g->seq[pv>>1].len; - } - } else { - for (ai = idx, pi = 0; ai != (uint32_t)-1; ai = a[ai].aidx) { - pv = (((uint32_t)(a[ai].hid))<<1)|((uint32_t)(a[ai].rev)); - if((a[ai].aidx != (uint32_t)-1) && (!ulg_len_check(g, pv, &(a[ai])))) break; - if((pi > 0) && (!ulg_len_check(g, pv^1, &(a[ai])))) break; - l = ai; pi++; - } - - ai = l; - kv_resize(uint64_t, b->pat, pi); b->pat.n = pi; - kv_resize(uint64_t, b->pat_cor, pi); b->pat_cor.n = pi; - for (l = 0; ai != (uint32_t)-1 && ai >= idx; ai = a[ai].pidx) { - pv = (((uint32_t)(a[ai].hid))<<1)|((uint32_t)(a[ai].rev)); - pi--; if(pv == v) m++; - b->pat.a[pi] = pv; b->pat.a[pi] |= (l<<32); - update_l_coord(g, l, pv, &(a[ai]), &s, &e); - b->pat_cor.a[pi] = ((s<<32)|e); - if(a[ai].pidx != (uint32_t)-1 && a[ai].pidx >= idx) l += a[ai].pdis; - else l += g->seq[pv>>1].len; - } - assert(pi == 0); - - for (ai = 0; ai < b->pat.n; ai++) { - tt = (b->pat.a[ai]>>32) + g->seq[((uint32_t)b->pat.a[ai])>>1].len; - // if(l < tt) { - // fprintf(stderr, "\n[M::%s::] ai::%u, b->pat.n::%u, l::%lu, tt::%lu, beg::%lu\n", - // __func__, ai, (uint32_t)b->pat.n, l, tt, (b->pat.a[ai]>>32)); - // } - assert(l >= tt); - tt = l - tt; - b->pat.a[ai] = (uint32_t)b->pat.a[ai]; - b->pat.a[ai] += (tt<<32); - } - } - (*rl) = l; - - assert(m > 0); - return m; -} - -uint32_t get_arch_len(asg_t *g, uint32_t v, uint32_t w) -{ - - uint32_t i, an; asg_arc_t *av; - av = asg_arc_a(g, v); an = asg_arc_n(g, v); - for (i = 0; i < an; i++) { - if(av[i].del) continue; - if(av[i].v == w) return ((uint32_t)av[i].ul); - } - return (uint32_t)-1; -} - -void gen_ref_pat_seq(asg_t *g, ubuf_t *b, uint64_t rul, double diff_rate, uint32_t v, uint32_t w/**, uint32_t is_debug**/) -{ - int64_t ref_n = b->dp.ref.n, k; uint64_t x, l; uint32_t p, arc_l; - if(ref_n >= 2 && ((uint32_t)b->dp.ref.a[0]) == v && ((uint32_t)b->dp.ref.a[1]) == w) { - // if(is_debug) fprintf(stderr, "+[M::%s::] ref_n::%ld, rul::%lu\n", __func__, ref_n, rul); - if((ref_n) > 0 && ((b->dp.ref.a[ref_n-1]>>32) >= (rul*(1.0+diff_rate)))) { - for (k = ref_n-1; k >= 0; k--) { - if((b->dp.ref.a[k]>>32) < (rul*(1.0+diff_rate))) break; - b->dp.g_flt.a[(uint32_t)b->dp.ref.a[k]] = 0; - } - ref_n = k + 1; b->dp.ref.n = ref_n; - } else { - p = (uint32_t)b->dp.ref.a[ref_n-1]; p ^= 1; p = b->a.a[p].p; - for (l = b->dp.ref.a[ref_n-1]>>32; p != (uint32_t)-1; p = b->a.a[p].p) { - x = p^1; arc_l = get_arch_len(g, ((uint32_t)b->dp.ref.a[b->dp.ref.n-1]), x); - assert(arc_l != (uint32_t)-1); l += arc_l; - if(l >= (rul*(1.0+diff_rate))) break; - b->dp.g_flt.a[x] = 1; x += (l<<32); kv_push(uint64_t, b->dp.ref, x); - } - ref_n = b->dp.ref.n; - } - } else { - // if(is_debug) fprintf(stderr, "-[M::%s::] ref_n::%ld, rul::%lu\n", __func__, ref_n, rul); - b->dp.ref.n = 0; - for (k = 0; k < ref_n; k++) { - b->dp.g_flt.a[(uint32_t)b->dp.ref.a[k]] = 0; - } - - x = v; kv_push(uint64_t, b->dp.ref, x); b->dp.g_flt.a[x] = 1; - for (p = w^1, l = 0; p != (uint32_t)-1; p = b->a.a[p].p) { - x = p^1; arc_l = get_arch_len(g, ((uint32_t)b->dp.ref.a[b->dp.ref.n-1]), x); - assert(arc_l != (uint32_t)-1); l += arc_l; - if(l >= (rul*(1.0+diff_rate))) break; - b->dp.g_flt.a[x] = 1; x += (l<<32); kv_push(uint64_t, b->dp.ref, x); - } - ref_n = b->dp.ref.n; - } -} - -uint32_t quick_check(uc_block_t *a, asg_t *g, path_dp_t *b, double diff_rate, double filter_rate) -{ - uint64_t ref_l = 0, pat_l = 0, mm, min, max, l, k, s, e, match_s, match_e, unmatch_s, unmatch_e, match_l, unmatch_l; - if(b->ref.n == 0 || b->pat.n == 0) return 0; - assert(b->g_flt.a[(uint32_t)b->pat.a[0]]); - for (k = 1; k < b->pat.n; k++) {///k = 0, must be matched - if(b->g_flt.a[(uint32_t)b->pat.a[k]]) break; - } - if(k >= b->pat.n) return 0; - - ref_l = (b->ref.a[b->ref.n-1]>>32) + g->seq[((uint32_t)b->ref.a[b->ref.n-1])>>1].len; - pat_l = (b->pat.a[b->pat.n-1]>>32) + g->seq[((uint32_t)b->pat.a[b->pat.n-1])>>1].len; - mm = MIN(ref_l, pat_l); min = mm * (1.0 - diff_rate); max = mm * (1.0 + diff_rate); - - match_s = match_e = unmatch_s = unmatch_e = (uint64_t)-1; match_l = unmatch_l = 0; - for (k = 0; k < b->pat.n; k++) { - l = (b->pat.a[k]>>32) + g->seq[((uint32_t)b->pat.a[k])>>1].len; - s = b->pat_cor.a[k]>>32; e = (uint32_t)b->pat_cor.a[k]; - if(l <= min) { - if(unmatch_e == (uint64_t)-1 || s >= unmatch_e) { - if(unmatch_e != (uint64_t)-1) unmatch_l += unmatch_e - unmatch_s; - unmatch_s = s; unmatch_e = e; - } else { - if(e > unmatch_e) unmatch_e = e; - } - } - - if(l <= max) { - if(b->g_flt.a[(uint32_t)b->pat.a[k]]) { - if(match_e == (uint64_t)-1 || s >= match_e) { - if(match_e != (uint64_t)-1) match_l += match_e - match_s; - match_s = s; match_e = e; - } else { - if(e > match_e) match_e = e; - } - } - } - if(l > max) break; - } - - if(unmatch_e != (uint64_t)-1) unmatch_l += unmatch_e - unmatch_s; - if(match_e != (uint64_t)-1) match_l += match_e - match_s; - // fprintf(stderr, "[M::%s::] min::%lu, max::%lu, match_l::%lu, unmatch_l::%lu\n", __func__, - // min, max, match_l, unmatch_l); - if(match_l >= unmatch_l*filter_rate) return 1; - return 0; -} - -#define ul_dp_idx(dp, x, y) ((dp).m*(x)+(y)) -#define e_mdp 0 -#define ue_mdp 1 -#define lpat_dp 2 -#define lref_dp 3 -//0->match; 1->mismatch; 2->up (longer pat); 3->left (longer ref) -void init_ul_dp(asg_t *g, path_dp_t *dp) -{ - kv_resize(uint8_t, dp->m_dir, (dp->pat.n+1)*(dp->ref.n+1)); - kv_resize(int64_t, dp->m_score, (dp->pat.n+1)*(dp->ref.n+1)); - dp->n = dp->pat.n+1; dp->m = dp->ref.n+1; - /** - uint64_t k, s, e, sp, ep, sc; - dp->m_dir.a[0] = dp->m_score.a[0] = 0; ///[0, 0] - for (k = 1, sp = ep = (uint64_t)-1; k < dp->n; k++) {///pat; ul read - s = dp->pat.a[k-1]>>32; e = (dp->pat.a[k-1]>>32) + g->seq[(uint32_t)dp->pat.a[k-1]].len; sc = 0; - if(ep == (uint64_t)-1 || s >= ep) { - sc = e - s; sp = s; ep = e; - } else { - if(e > ep) sc = e - ep; - } - if(((uint32_t)dp->pat.a[k-1]) == ((uint32_t)dp->ref.a[0])) { - dp->m_score.a[ul_dp_idx(*dp, k, 0)] = dp->m_dir.a[ul_dp_idx(*dp, k, 0)] = 0; - } else { - dp->m_score.a[ul_dp_idx(*dp, k, 0)] = dp->m_score.a[ul_dp_idx(*dp, k-1, 0)] + sc; - dp->m_dir.a[ul_dp_idx(*dp, k, 0)] = lpat_dp; - } - } - - for (k = 1, sp = ep = (uint64_t)-1; k < dp->m; k++) {///ref; graph - s = dp->ref.a[k-1]>>32; e = (dp->ref.a[k-1]>>32) + g->seq[(uint32_t)dp->ref.a[k-1]].len; sc = 0; - if(ep == (uint64_t)-1 || s >= ep) { - sc = e - s; sp = s; ep = e; - } else { - if(e > ep) sc = e - ep; - } - dp->m_score.a[ul_dp_idx(*dp, 0, k)] = dp->m_score.a[ul_dp_idx(*dp, 0, k-1)] + sc; - dp->m_dir.a[ul_dp_idx(*dp, 0, k)] = lref_dp; - } - **/ - uint64_t k; int64_t min_weight = -1*((int64_t)(0xffffffff)); dp->m_dir.a[0] = dp->m_score.a[0] = 0; ///[0, 0] - - for (k = 1; k < dp->n; k++) {///pat; ul read - if(((uint32_t)dp->pat.a[k-1]) == ((uint32_t)dp->ref.a[0])) { - dp->m_score.a[ul_dp_idx(*dp, k, 0)] = dp->m_dir.a[ul_dp_idx(*dp, k, 0)] = 0; - } else { - dp->m_score.a[ul_dp_idx(*dp, k, 0)] = min_weight; - // dp->m_score.a[ul_dp_idx(*dp, k-1, 0)] - g->seq[((uint32_t)dp->pat.a[k-1])>>1].len; - dp->m_dir.a[ul_dp_idx(*dp, k, 0)] = lpat_dp; - } - } - - for (k = 1; k < dp->m; k++) {///ref; graph - dp->m_score.a[ul_dp_idx(*dp, 0, k)] = min_weight; - // dp->m_score.a[ul_dp_idx(*dp, 0, k-1)] - g->seq[((uint32_t)dp->ref.a[k-1])>>1].len; - dp->m_dir.a[ul_dp_idx(*dp, 0, k)] = lref_dp; - } -} - -uint64_t node_check(uint32_t ul_v, uint32_t g_v, uint32_t ul_v_len, uint32_t g_v_len, double diff_len, uint32_t ul_weight) -{ - if(ul_v != g_v) return 0; - uint32_t x = ((ul_v_len >= g_v_len)? (ul_v_len - g_v_len): (g_v_len - ul_v_len)); - if(x > g_v_len*diff_len) return 0; - if(g_v_len == 0) { - return ul_weight; - } else { - return (((double)(g_v_len-x))/((double)g_v_len))*ul_weight; - } -} - -void print_dp_matrix(path_dp_t *dp) -{ - uint64_t i, j; - for (i = 0; i < dp->n; i++) {//pat - for (j = 0; j < dp->m; j++) {//mat - fprintf(stderr, "%ld<%u>,\t", dp->m_score.a[ul_dp_idx(*dp, i, j)], dp->m_dir.a[ul_dp_idx(*dp, i, j)]); - } - fprintf(stderr, "\n"); - } - -} - -int64_t ul_dp0(bubble_type* bub, asg_t *g, path_dp_t *dp, double pass_thres/**, uint64_t is_debug**/) -{ - if(dp->pat.n < 2 || dp->ref.n < 2) return -1; - uint64_t i, j, d, w; int64_t sc0, sc1, sc2, sc, sc_i, sc_j; - init_ul_dp(g, dp); - // if(is_debug) { - // print_dp_matrix(dp); - // } - for (i = 1; i < dp->n; i++) {//pat - for (j = 1; j < dp->m; j++) {//mat - w = node_check(((uint32_t)dp->pat.a[i-1]), ((uint32_t)dp->ref.a[j-1]), - dp->pat.a[i-1]>>32, dp->ref.a[j-1]>>32, 0.04, g->seq[((uint32_t)dp->pat.a[i-1])>>1].len); - - if(w) { - // if(is_debug) fprintf(stderr, "\n[M::%s::] i::%lu, j::%lu, w::%lu\n", __func__, i, j, w); - dp->m_score.a[ul_dp_idx(*dp, i, j)] = dp->m_score.a[ul_dp_idx(*dp, i-1, j-1)] + w; - dp->m_dir.a[ul_dp_idx(*dp, i, j)] = e_mdp; - } else { - sc0 = dp->m_score.a[ul_dp_idx(*dp, i-1, j-1)] - - (int64_t)(MIN(g->seq[((uint32_t)dp->pat.a[i-1])>>1].len, g->seq[((uint32_t)dp->ref.a[j-1])>>1].len)); - sc1 = dp->m_score.a[ul_dp_idx(*dp, i-1, j)] - (int64_t)(g->seq[((uint32_t)dp->ref.a[j-1])>>1].len); - sc2 = dp->m_score.a[ul_dp_idx(*dp, i, j-1)] - (int64_t)(g->seq[((uint32_t)dp->pat.a[i-1])>>1].len); - - d = ue_mdp; sc = sc0; - if(sc < sc1) { - sc = sc1; d = lref_dp; - } - if(sc < sc2) { - sc = sc2; d = lpat_dp; - } - dp->m_score.a[ul_dp_idx(*dp, i, j)] = sc; - dp->m_dir.a[ul_dp_idx(*dp, i, j)] = d; - } - } - } - - sc = 0; sc_i = sc_j = -1; - for (j = 1, i = dp->n - 1; j < dp->m; j++) { - if(sc_i < 0 || sc < dp->m_score.a[ul_dp_idx(*dp, i, j)]) { - sc_i = i; sc_j = j; sc = dp->m_score.a[ul_dp_idx(*dp, i, j)]; - } - } - for (i = 1, j = dp->m - 1; i < dp->n; i++) { - if(sc_i < 0 || sc < dp->m_score.a[ul_dp_idx(*dp, i, j)]) { - sc_i = i; sc_j = j; sc = dp->m_score.a[ul_dp_idx(*dp, i, j)]; - } - } - - // if(is_debug) { - // fprintf(stderr, "[M::%s::] sc_i::%ld, sc_j::%ld, sc::%ld\n", __func__, sc_i, sc_j, sc); - // // print_dp_matrix(dp); - // } - - if (sc_i < 0 || sc_i == 1 || sc_j == 1) return 0; - int64_t match_all = 0, unmatch_all = 0, het_match_all = 0, het_unmatch_all = 0, het_occ = 0; - //pat_s = sc_i - 1; ref_s = ref_e = sc_j - 1; - for(i = sc_i, j = sc_j; i > 0 && j > 0;) { - d = dp->m_dir.a[ul_dp_idx(*dp, i, j)]; - //pat_s = i - 1; ref_s = j - 1; - // if(is_debug) fprintf(stderr, "[M::%s::] i::%lu, j::%lu, dir::%lu\n", __func__, i, j, d); - // if(pat_s == 0) continue; - if(d == e_mdp) { - // if(i != 1 || j != 1) {//skip (i == 1 && j == 1) - match_all += g->seq[((uint32_t)dp->pat.a[i-1])>>1].len; - if(!IF_HOM((((uint32_t)dp->pat.a[i-1])>>1), *bub)) { - het_match_all += g->seq[((uint32_t)dp->pat.a[i-1])>>1].len; - het_occ++; - } - i--; j--; - // if(is_debug) { - // fprintf(stderr, "[M::%s::] PAT::utg%.6dl(%c::len->%lu), REF::utg%.6dl(%c::len->%lu)\n", __func__, - // ((((uint32_t)dp->pat.a[i])>>1))+1, "+-"[((uint32_t)dp->pat.a[i])&1], dp->pat.a[i]>>32, - // ((((uint32_t)dp->ref.a[j])>>1))+1, "+-"[((uint32_t)dp->ref.a[j])&1], dp->ref.a[j]>>32); - // } - } - if(d == ue_mdp) { - unmatch_all += g->seq[((uint32_t)dp->pat.a[i-1])>>1].len; - if(!IF_HOM((((uint32_t)dp->pat.a[i-1])>>1), *bub)) { - het_unmatch_all += g->seq[((uint32_t)dp->pat.a[i-1])>>1].len; - } - i--; j--; - } - if(d == lpat_dp) { - j--; - } - if(d == lref_dp) { - unmatch_all += g->seq[((uint32_t)dp->pat.a[i-1])>>1].len; - if(!IF_HOM((((uint32_t)dp->pat.a[i-1])>>1), *bub)) { - het_unmatch_all += g->seq[((uint32_t)dp->pat.a[i-1])>>1].len; - } - i--; - } - } - // if(is_debug) { - // fprintf(stderr, "[M::%s::] het_occ::%ld, match_all::%ld, unmatch_all::%ld, het_match_all::%ld, het_unmatch_all::%ld\n", __func__, - // het_occ, match_all, unmatch_all, het_match_all, het_unmatch_all); - // } - - assert((j == 0) && (((uint32_t)dp->pat.a[i]) == ((uint32_t)dp->ref.a[j]))); - ///skip the beg node - match_all -= g->seq[((uint32_t)dp->pat.a[i])>>1].len; - if(!IF_HOM((((uint32_t)dp->pat.a[i])>>1), *bub)) { - het_match_all -= g->seq[((uint32_t)dp->pat.a[i])>>1].len; het_occ--; - } - - - if(het_occ < 1 || match_all == 0 || het_match_all == 0) return -1; - if(match_all <= (match_all + unmatch_all)*pass_thres) return -1; - if(het_match_all <= (het_match_all + het_unmatch_all)*pass_thres) return -1; - return (((double)het_match_all)/((double)(het_match_all + het_unmatch_all)))* - (((uint32_t)dp->pat_cor.a[i]) - (dp->pat_cor.a[i]>>32)); -} -uint64_t ul_dp(bubble_type* bub, all_ul_t *ul, ubuf_t *b, uint64_t *a, int64_t a_n, asg_t *g, uint32_t v, uint32_t w, uint32_t is_backward) -{ - int64_t i, m, a_i = -1; uc_block_t *p; uint32_t gv; uint64_t url; int64_t we; - for (i = m = 0; i < a_n; i++) { - p = &(ul->a[a[i]>>32].bb.a[(uint32_t)(a[i])]); - assert((!p->base)&&(p->hid == (v>>1))&&(p->el)/**&&(p->pchain)**/); - if(!p->pchain) continue; - gv = (((uint32_t)(p->hid))<<1)|((uint32_t)(p->rev)); - if(is_backward) { - gv ^= 1; - if(p->pidx == (uint32_t)-1) continue; - } else { - if(p->aidx == (uint32_t)-1) continue; - } - if(gv != v) continue; - // fprintf(stderr, "[M::%s::] i:%ld, a_n:%lu, v:%u, w:%u, ulid:%lu, uidx:%u, is_backward:%u\n", - // __func__, i, a_n, v, w, a[i]>>32, (uint32_t)(a[i]), is_backward); - // if(v == 6 && w == 5 && (a[i]>>32) == 95) { - // int64_t z; - // for (z = 0; z < ul->a[a[i]>>32].bb.n; z++) { - // fprintf(stderr, "[M::%s::vid->%u] qs:%u, qe:%u, qlen:%u, ts:%u, te:%u, tlen:%u\n", __func__, - // (((uint32_t)(ul->a[a[i]>>32].bb.a[z].hid))<<1)|((uint32_t)(ul->a[a[i]>>32].bb.a[z].rev)), - // ul->a[a[i]>>32].bb.a[z].qs, ul->a[a[i]>>32].bb.a[z].qe, ul->a[a[i]>>32].rlen, - // ul->a[a[i]>>32].bb.a[z].ts, ul->a[a[i]>>32].bb.a[z].te, g->seq[ul->a[a[i]>>32].bb.a[z].hid].len); - // } - // } - if(ulg_len_check(g, v, p) == 0) continue;///too short - m++; a_i = i; - } - - if(m == 0) return 0; - // uint32_t is_debug = (v == 231); - // if(is_debug) { - // fprintf(stderr, "\n+[M::%s::] m->%ld, ulid->%lu\n", __func__, m, a[a_i]>>32); - // } - - p = &(ul->a[a[a_i]>>32].bb.a[(uint32_t)(a[a_i])]);//longest one - m = gen_ul_pat_seq(ul->a[a[a_i]>>32].bb.a, &(b->dp), ul, (uint32_t)(a[a_i]), g, v, is_backward, &url); - assert(b->dp.pat.n > 0); - - // if(is_debug) { - // for (i = 0; i < (int64_t)b->dp.pat.n; i++) { - // fprintf(stderr, "pat[M::%s::] utg%.6dl(%c), d::%lu\n", __func__, - // (((uint32_t)b->dp.pat.a[i])>>1)+1, "+-"[((uint32_t)b->dp.pat.a[i])&1], b->dp.pat.a[i]>>32); - // } - // } - if(b->dp.pat.n == 1) return 0; - gen_ref_pat_seq(g, b, url, UL_TRAV_HERATE, v, w/**, is_debug**/); - - // if(is_debug) { - // for (i = 0; i < (int64_t)b->dp.ref.n; i++) { - // fprintf(stderr, "ref[M::%s::] utg%.6dl(%c), d::%lu\n", __func__, - // (((uint32_t)b->dp.ref.a[i])>>1)+1, "+-"[((uint32_t)b->dp.ref.a[i])&1], b->dp.ref.a[i]>>32); - // } - // } - - if(!quick_check(ul->a[a[a_i]>>32].bb.a, g, &(b->dp), UL_TRAV_HERATE, UL_TRAV_FT_RATE)) return 0; - we = ul_dp0(bub, g, &(b->dp), 0.9/**, is_debug**/); - if(we < 0) return 0; - return we; -} - -uint64_t get_eul_weight(bubble_type* bub, uint32_t v, uint32_t w, uinfo_t *g_idx, ubuf_t *b, all_ul_t *ul, asg_t *g) -{ - uint64_t *a, to = 0; int64_t a_n, l, k; - a = ul->ridx.occ.a + ul->ridx.idx.a[v>>1]; - a_n = ul->ridx.idx.a[(v>>1)+1] - ul->ridx.idx.a[v>>1]; - b->dp.pat.n = b->dp.pat_cor.n = b->dp.ref.n = 0; - for (l = 0, k = 1; k <= a_n; k++) { - if((k == a_n) || ((a[k]>>32) != (a[l]>>32))) { - // if((v == 106 && w == 103) || (v == 24 && w == 23)) { - // fprintf(stderr, "+[M::%s::] l->%ld, k->%ld, a_n->%ld\n", __func__, l, k, a_n); - // } - to += ul_dp(bub, ul, b, a + l, k - l, g, v, w, 1); - // if((v == 106 && w == 103) || (v == 24 && w == 23)) { - // fprintf(stderr, "-[M::%s::] l->%ld, k->%ld, a_n->%ld\n", __func__, l, k, a_n); - // } - to += ul_dp(bub, ul, b, a + l, k - l, g, v, w, 0); - // if((v == 106 && w == 103) || (v == 24 && w == 23)) { - // fprintf(stderr, "*[M::%s::] l->%ld, k->%ld, a_n->%ld\n", __func__, l, k, a_n); - // } - l = k; - } - } - - return to; -} - -void extract_paths(ubuf_t *b, ma_utg_v *gu, ul_path_t *res, uint32_t src, uint32_t dest) -{ - uint32_t i, v; uinfo_t *t; uint64_t m = 0, mi = (uint64_t)-1, avn; ///kv_resize(uinfo_srt_t, b->srt, b->b.n); b->srt.n = b->b.n; - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - t = &b->a.a[b->b.a[i]]; ///memset(t, 0, sizeof(*(t))); - //b->srt.a[i].c = ((uint64_t)-1) - t->c; b->srt.a[i].i = i; - if(m < t->c) { - m = t->c; mi = i; ///b->b.a[i]; - } - } - //radix_sort_uinfo_srt_t_c(b->srt.a, b->srt.a + b->srt.n); - // fprintf(stderr, "\n[M::%s::]->beg\n", __func__); - if(mi != (uint64_t)-1) { - ma_utg_t *p; kv_pushp(ma_utg_t, res->buf_ug->u, &p); - p->len = p->circ = p->n = 0; p->start = p->end = UINT32_MAX; p->a = NULL; p->s = NULL; - for(v = b->b.a[mi], avn = 0; v != (uint32_t)-1; v = b->a.a[v].p) { - if(b->a.a[v].c == 0 && avn == 0) break; - b->us.a[v>>1] = 1; - if(v != src && v != dest) kv_push(uint64_t, (*p), v); - // fprintf(stderr, "[M::%s::] utg%.6d%c(%c)\tC::%lu\n", __func__, (v>>1)+1, "lc"[gu->a[v>>1].circ], "+-"[v&1], b->a.a[v].c); - avn = b->a.a[v].c; - } - - if(p->n == 0) res->buf_ug->u.n = 0; - } -} - -uint32_t hc_simple_traversal(bubble_type* bub, asg_t *g, ma_utg_v *gu, ubuf_t *b, all_ul_t *ul, uint32_t src, uint32_t dest, ul_path_t *res) -{ - uint32_t v, nv, i, w, n_pending = 0, is_update = 0; uint64_t l, d, c, cc, nc, c_nc; asg_arc_t *av; uinfo_t *t; - if (g->seq[src>>1].del || g->seq[dest>>1].del) return 0; - clear_ubuf_t(b, g, ul, 1); b->a.a[src].p = (uint32_t)-1; - kv_push(uint32_t, b->S, src); - while (b->S.n > 0) { - v = kv_pop(b->S); d = b->a.a[v].d; c = b->a.a[v].c; nc = b->a.a[v].nc; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (i = 0; i < nv; ++i) { - if (av[i].del || g->seq[av[i].v>>1].del) continue; - w = av[i].v; l = (uint32_t)av[i].ul; t = &b->a.a[w]; - kv_push(uint32_t, b->e, ((g->idx[v]>>32)+i)); ///push the edge - // fprintf(stderr, "+[M::%s::] utg%.6d%c(%c:%u) -> utg%.6d%c(%c:%u)\n", __func__, - // (v>>1)+1, "lc"[gu->a[v>>1].circ], "+-"[v&1], v, - // (w>>1)+1, "lc"[gu->a[w>>1].circ], "+-"[w&1], w); - cc = c + get_eul_weight(bub, w^1, v^1, b->a.a, b, ul, g); - c_nc = nc + (gu?gu->a[w>>1].n:1); - // fprintf(stderr, "-[M::%s::] utg%.6d%c(%c:%u) -> utg%.6d%c(%c:%u)\n", __func__, - // (v>>1)+1, "lc"[gu->a[v>>1].circ], "+-"[v&1], v, - // (w>>1)+1, "lc"[gu->a[w>>1].circ], "+-"[w&1], w); - - if (t->s == 0) {///a new node - kv_push(uint32_t, b->b, w); // save it for revert - t->p = v; t->s = 1; t->d = d + l; - t->r = get_arcs(g, w^1, NULL, 0); - t->nc = c_nc; t->c = cc; - ++n_pending; - } else { - is_update = 0; - if(b->us.a[t->p>>1] == b->us.a[v>>1]) { - if(cc > t->c) is_update = 1; - if(cc == t->c && c_nc > t->nc) is_update = 1; - } else { - if(b->us.a[t->p>>1]) is_update = 1; - else is_update = 0; - } - - if(is_update) { - t->p = v; t->s = 1; t->d = d + l; t->nc = c_nc; t->c = cc; - } - } - - if (--(t->r) == 0) { - if(get_arcs(g, w, NULL, 0) > 0) kv_push(uint32_t, b->S, w); - --n_pending; - if(w == dest && n_pending == 0) goto pp_end; - } - } - } - pp_end: - extract_paths(b, gu, res, src, dest); - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - t = &b->a.a[b->b.a[i]]; memset(t, 0, sizeof(*(t))); - } - return 1; -} - - -// void clean_path_g(ul_path_t *p, asg_t *ref) -// { -// if(!(p->pg)) CALLOC(p->pg, 1); -// free(p->pg->idx); p->pg->idx = 0; p->pg->is_srt = 0; p->pg->is_symm = 0; -// REALLOC(p->pg->seq, ref->n_seq); p->pg->n_seq = ref->n_seq; p->pg->n_arc = 0; -// memcpy(p->pg->seq, ref->seq, p->pg->n_seq*sizeof(*(p->pg->seq))); -// asg_cleanup(p->pg); -// } - -void build_sub_graph(ul_resolve_t *uidx, ul_path_t *res) -{ - -} - -uint64_t get_chain_ul_cov(ul_resolve_t *uidx, uint64_t *a, uint64_t a_n, uint64_t bub_id, uint64_t inner_beg) -{ - if(a_n <= 0) return 0; - uint64_t w = 0, bid, rev; uint32_t rt, beg, sink; - uidx->path.buf.n = 0; - // kv_pushp(ul_sub_path_t, uidx->path, &p); memset(p, 0, sizeof((*p))); - // p->bid = bub_id; p->beg = inner_beg; p->occ = a_n; - - bid = a[0]>>33; rev = (a[0]>>32)&1; - get_bubbles(uidx->bub, bid, rev==0?&rt:NULL, rev==1?&rt:NULL, NULL, NULL, NULL); beg = rt; - - bid = a[a_n-1]>>33; rev = (a[a_n-1]>>32)&1; - get_bubbles(uidx->bub, bid, rev==1?&rt:NULL, rev==0?&rt:NULL, NULL, NULL, NULL); sink = rt^1; - - - - - - - - - // fprintf(stderr, "\n[M::%s::] # bubbles->%lu\n", __func__, a_n); - // uint64_t k - // for (k = 0; k < a_n; k++) { - // bid = a[k]>>33; rev = (a[k]>>32)&1; - // get_bubbles(uidx->bub, bid, rev==0?&rt:NULL, rev==1?&rt:NULL, NULL, NULL, NULL); - // // w += get_bub_ul_cov(a[k]>>33, ug, idx); - // fprintf(stderr, "[M::%s::] utg%.6d%c(%c)\n", __func__, (rt>>1)+1, "lc"[uidx->l1_ug->u.a[rt>>1].circ], "+-"[rt&1]); - // } - // if (a_n > 0) { - // bid = a[k-1]>>33; rev = (a[k-1]>>32)&1; - // get_bubbles(uidx->bub, bid, rev==1?&rt:NULL, rev==0?&rt:NULL, NULL, NULL, NULL); rt ^= 1; - // fprintf(stderr, "[M::%s::] utg%.6d%c(%c)\n", __func__, (rt>>1)+1, "lc"[uidx->l1_ug->u.a[rt>>1].circ], "+-"[rt&1]); - // } - // clean_path_g(&(uidx->path), uidx->l1_ug->g); - ma_utg_t *p; - kv_resize(uint8_t, uidx->buf.us, uidx->l1_ug->g->n_seq); uidx->buf.us.n = uidx->l1_ug->g->n_seq; memset(uidx->buf.us.a, 0, uidx->buf.us.n*sizeof(*(uidx->buf.us.a))); - hc_simple_traversal(uidx->bub, uidx->l1_ug->g, &(uidx->l1_ug->u), &(uidx->buf), uidx->idx, beg, sink, &(uidx->path)); - hc_simple_traversal(uidx->bub, uidx->l1_ug->g, &(uidx->l1_ug->u), &(uidx->buf), uidx->idx, beg, sink, &(uidx->path)); - - kv_pushp(ma_utg_t, uidx->path.buf_ug->u, &p); p->len = p->circ = p->n = 0; - p->start = p->end = UINT32_MAX; p->a = NULL; p->s = NULL; kv_push(uint64_t, *p, beg); - - kv_pushp(ma_utg_t, uidx->path.buf_ug->u, &p); p->len = p->circ = p->n = 0; - p->start = p->end = UINT32_MAX; p->a = NULL; p->s = NULL; kv_push(uint64_t, *p, sink); - - return w; -} - -void phrase_exact_chains(ul_resolve_t *uidx, uint64_t *a, int64_t a_n, asg_t *bg, uint64_t bub_id, uint64_t inner_beg) -{ - int64_t k, l; - for (k = l = 0; k < a_n; k++) { - if(k+1 >= a_n) continue; - if((arc_first(bg, a[k]>>32)).el) continue; - get_chain_ul_cov(uidx, a+l, k+1-l, bub_id, inner_beg + l); - l = k + 1; - } - if(l < a_n) get_chain_ul_cov(uidx, a+l, a_n-l, bub_id, inner_beg + l); -} -void resolve_dip_bub_chains(ul_resolve_t *uidx) -{ - bubble_type *bub = uidx->bub; - uint32_t i; int32_t k, l, un; ma_utg_t *u; - for (i = 0; i < bub->b_ug->u.n; i++) { - u = &(bub->b_ug->u.a[i]); un = u->n; - if(un <= 1) continue;///single bubble - for (l = -1, k = 0; k <= un; k++) { - if((k == un) || ((u->a[k]>>33) >= bub->f_bub)) {///not a complete bubble - // if(k < un) { - // fprintf(stderr, "++++++[M::%s::] l->%d, k->%d, bid->%lu, f_bub->%lu\n", - // __func__, l, k, (u->a[k]>>33), bub->f_bub); - // } - if(k - l > 1) {///at least a complete bubble - // fprintf(stderr, "\n[M::%s::] l->%d, k->%d\n", __func__, l, k); - phrase_exact_chains(uidx, u->a+l+1, k-l-1, bub->b_g, i, l+1); - } - l = k; - } - } - - } -} - -/** -static void fill_ul_path_srt_t(void *data, long i, int tid) // callback for kt_for() -{ - all_ul_t *idx = ((ul_resolve_t *)data)->idx; - ul_path_srt_t *idx_srt = &(((ul_resolve_t *)data)->psrt); - uc_block_t *a = NULL; uc_block_t *p; int64_t k, a_n, b_n, occ; uint64_t *b = NULL; - - a = idx->a[i].bb.a; a_n = idx->a[i].bb.n; - if(idx_srt->ul_n == 0) { - for (k = occ = 0; k < a_n; k++) { - p = &(a[k]); - if(p->base || (!p->el) || (!p->pchain)) continue; - occ++; - } - if(occ == 1) occ = 0;///UL read is too short - idx_srt->idx.a[i] = occ; - } else { - b_n = idx_srt->idx.a[i]>>33; b = idx_srt->srt.a + (uint32_t)idx_srt->idx.a[i]; - if(b_n == 0) return;//UL covers 0 or 1 node; not useful - for (k = occ = 0; k < a_n; k++) { - p = &(a[k]); - if(p->base || (!p->el) || (!p->pchain)) continue; - b[occ] = p->hid; b[occ] <<= 1; b[occ] |= p->rev; b[occ] <<= 32; b[occ] += (uint64_t)k; - occ++; - } - assert(occ == b_n); - radix_sort_srt64(b, b + b_n); - for (k = 1; k < b_n; k++) { - if((b[k]>>32) == (b[k-1]>>32)) break; - } - - if(k < b_n) idx_srt->idx.a[i] |= (uint64_t)(0x100000000); - } -} - - -void init_ul_path_srt_t(ul_resolve_t *p, all_ul_t *idx, ul_path_srt_t *idx_srt) -{ - idx_srt->ul_n = 0; - idx_srt->idx.n = idx_srt->idx.m = idx->n; CALLOC(idx_srt->idx.a, idx_srt->idx.n); - - kt_for(asm_opt.thread_num, fill_ul_path_srt_t, p, idx->n); - uint64_t l, k; - for (k = l = 0; k < idx_srt->idx.n; k++) { - idx_srt->idx.a[k] <<= 33; idx_srt->idx.a[k] += l; l += (idx_srt->idx.a[k]>>33); - } - MALLOC(idx_srt->srt.a, l); idx_srt->srt.n = idx_srt->srt.m = l; - - idx_srt->ul_n = idx->n; - kt_for(asm_opt.thread_num, fill_ul_path_srt_t, p, idx->n); -} -**/ - -uint64_t ug_occ_w(uint64_t is, uint64_t ie, ma_utg_t *u) -{ - if(is == 0 && ie == u->len) return u->n; - uint64_t l, i, us, ue, occ; - for (i = l = occ = 0; i < u->n; i++) { - us = l; ue = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); - // if(is == 15390 && ie == 31730) { - // fprintf(stderr, "[M::%s::i->%lu] is->%lu, ie->%lu, us->%lu, ue->%lu, u->len->%u\n", - // __func__, i, is, ie, us, ue, u->len); - // } - if(is <= us && ie >= ue) occ++; - if(us >= ie) break; - l += (uint32_t)u->a[i]; - } - return occ; -} - -// static void gen_ul_str_idx_t(void *data, long i, int tid) // callback for kt_for() -// { -// all_ul_t *idx = ((ul_resolve_t *)data)->idx; -// ma_ug_t *ug = ((ul_resolve_t *)data)->l1_ug; -// ul_str_t *str = &(((ul_resolve_t *)data)->pstr.str.a[i]); -// // uint64_t *str_idx = ((ul_resolve_t *)data)->pstr.idx.a; -// uc_block_t *a = NULL; uc_block_t *xk; uint64_t t; -// uint64_t k, a_n; - -// str->n = str->m = 0; str->a = NULL; -// a = idx->a[i].bb.a; a_n = idx->a[i].bb.n; -// kv_resize(uint64_t, *str, idx->a[i].bb.n); -// for (k = 0; k < a_n; k++) { -// xk = &(a[k]); -// if(xk->base || (!xk->el) || (!xk->pchain)) continue; -// t = k; t <<= 32; t += (xk->hid<<1); t += xk->rev; -// kv_push(uint64_t, *str, t); -// } -// str->cn = str->n; str->is_cir = 0; -// } - -void init_ul_str_idx_t(ul_resolve_t *p) -{ - uint64_t k, l, i, m, *a, a_n, x_n; uc_block_t *x_a; - all_ul_t *idx = p->idx; ul_str_idx_t *str = &(p->pstr); ul_str_t *z; uint32_t v0, v1; - MALLOC(str->str.a, idx->n); str->str.n = str->str.m = idx->n; - CALLOC(str->idx.a, p->l1_ug->u.n+1); str->idx.n = str->idx.m = p->l1_ug->u.n+1; - for (i = 0; i < str->str.n; i++) { - x_a = idx->a[i].bb.a; x_n = idx->a[i].bb.n; - memset(&(str->str.a[i]), 0, sizeof(str->str.a[i])); - for (k = 0; k < x_n; k++) { - if(x_a[k].base || (!x_a[k].el) || (!x_a[k].pchain)) continue; - l = k; l <<= 32; l += (x_a[k].hid<<1); l += x_a[k].rev; str->idx.a[x_a[k].hid]++; - kv_push(uint64_t, str->str.a[i], l);///idx|hid|rev - } - str->str.a[i].cn = str->str.a[i].n; str->str.a[i].is_cir = 0; - } - - // kt_for(asm_opt.thread_num, gen_ul_str_idx_t, p, str->str.n); - for (k = l = 0; k < str->idx.n; k++) { - m = str->idx.a[k]; - str->idx.a[k] = l; - l += m; - } - - MALLOC(str->occ.a, l); str->occ.n = str->occ.m = l; - for (k = 0; k < p->l1_ug->u.n; k++) { - a = str->occ.a + str->idx.a[k]; - a_n = str->idx.a[k+1] - str->idx.a[k]; - if(a_n) a[a_n-1] = 0; - } - - for (k = 0; k < str->str.n; k++) { - z = &(str->str.a[k]); - for (i = 0; i < z->cn; i++) { - a = str->occ.a + str->idx.a[((uint32_t)z->a[i])>>1]; - a_n = str->idx.a[(((uint32_t)z->a[i])>>1)+1] - str->idx.a[((uint32_t)z->a[i])>>1]; - if(a_n) { - if(a[a_n-1] == a_n-1) { - m = a_n-1; a[a_n-1] = (k<<32)|i; - } else { - m = a[a_n-1]; a[a[a_n-1]++] = (k<<32)|i; - } - - v0 = (uint32_t)z->a[(uint32_t)a[m]]; - while (m > 0 && z->is_cir == 0) { - m--; - if((a[m]>>32) != k) break; - v1 = (uint32_t)z->a[(uint32_t)a[m]]; - if(v0 == v1) z->is_cir = 1; - } - } - } - } -} - -ul_resolve_t *init_ul_resolve_t(asg_t *sg, ma_ug_t *init_ug, bubble_type* bub, all_ul_t *idx, ug_opt_t *uopt, uint8_t *r_het) -{ - ul_resolve_t *p = NULL; CALLOC(p, 1); - p->sg = sg; p->init_ug = init_ug; p->bub = bub; p->idx = idx; p->r_het = r_het; p->uopt = uopt; - p->l1_ug = copy_untig_graph(p->init_ug); - init_integer_ml_t(&p->str_b, p, asm_opt.thread_num); - // init_ul_path_srt_t(p); - init_ul_str_idx_t(p); - return p; -} - -void print_bubble_gfa(FILE *fp, bubble_type *bub, const char* utg_pre, const char* bub_pre, const char* chain_pre) -{ - uint32_t i, k, m, *a, n, beg, sink, x; ma_utg_t *p; uint64_t occ; - ma_ug_t *b_ug = bub->b_ug; char name[32], bname[32]; uint8_t *f; CALLOC(f, bub->ug->u.n); - for (i = 0; i < b_ug->u.n; i++) { - p = &b_ug->u.a[i]; - if(p->n == 0) continue; - for (k = occ = 0; k < p->n; k++){ - x = p->a[k]>>33; - get_bubbles(bub, x, &beg, &sink, &a, &n, NULL); - - for (m = 0; m < n; m++) { - occ += bub->ug->u.a[a[m]>>1].n; f[a[m]>>1] = 1; - } - if(beg != (uint32_t)-1 && f[beg>>1] == 0) { - occ += bub->ug->u.a[beg>>1].n; f[beg>>1] = 1; - } - if(sink != (uint32_t)-1 && f[sink>>1] == 0) { - occ += bub->ug->u.a[sink>>1].n; f[sink>>1] = 1; - } - } - - sprintf(name, "%s%.6d%c", chain_pre, i + 1, "lc"[p->circ]); - fprintf(fp, "S\t%s\t*\tLN:i:%lu\n", name, occ); - for (k = 0; k < p->n; k++) { - x = p->a[k]>>33; - sprintf(bname, "%s%.6d", bub_pre, x + 1); - fprintf(fp, "B\t%s\t%c\tcid:i:%s\tsm:%c\n", bname, "+-"[(p->a[k]>>32)&1], name, "01"[xf_bub]); - - get_bubbles(bub, x, &beg, &sink, &a, &n, NULL); - if(beg != (uint32_t)-1) { - fprintf(fp, "U\t%s%.6d%c\t%c\tcid:i:%s\tbid:b:%s\thom:%c\n", - utg_pre, (beg>>1)+1, "lc"[bub->ug->u.a[(beg>>1)].circ], "+-"[beg&1], name, bname, "10"[IF_HOM((beg>>1), *bub)]); - } - - if(sink != (uint32_t)-1) { - fprintf(fp, "U\t%s%.6d%c\t%c\tcid:i:%s\tbid:s:%s\thom:%c\n", - utg_pre, (sink>>1)+1, "lc"[bub->ug->u.a[(sink>>1)].circ], "+-"[sink&1], name, bname, "10"[IF_HOM((sink>>1), *bub)]); - } - for (m = 0; m < n; m++) { - occ += bub->ug->u.a[a[m]>>1].n; - fprintf(fp, "U\t%s%.6d%c\t%c\tcid:i:%s\tbid:c:%s\thom:%c\n", - utg_pre, (a[m]>>1)+1, "lc"[bub->ug->u.a[(a[m]>>1)].circ], "+-"[a[m]&1], name, bname, "10"[IF_HOM((a[m]>>1), *bub)]); - } - } - } - - asg_arc_t* au = NULL; - uint32_t nu, u, v, j; - for (i = 0; i < b_ug->u.n; ++i) { - if(b_ug->u.a[i].m == 0) continue; - if(b_ug->u.a[i].circ) - { - fprintf(fp, "L\t%s%.6dc\t+\t%s%.6dc\t+\t%dM\tL1:i:%d\n", - chain_pre, i+1, chain_pre, i+1, 0, 0); - fprintf(fp, "L\t%s%.6dc\t-\t%s%.6dc\t-\t%dM\tL1:i:%d\n", - chain_pre, i+1, chain_pre, i+1, 0, 0); - } - u = i<<1; - au = asg_arc_a(b_ug->g, u); - nu = asg_arc_n(b_ug->g, u); - for (j = 0; j < nu; j++) - { - if(au[j].del) continue; - v = au[j].v; - fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", - chain_pre, (u>>1)+1, "lc"[b_ug->u.a[u>>1].circ], "+-"[u&1], - chain_pre, (v>>1)+1, "lc"[b_ug->u.a[v>>1].circ], "+-"[v&1], 0, 0); - } - - - u = (i<<1) + 1; - au = asg_arc_a(b_ug->g, u); - nu = asg_arc_n(b_ug->g, u); - for (j = 0; j < nu; j++) - { - if(au[j].del) continue; - v = au[j].v; - fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", - chain_pre, (u>>1)+1, "lc"[b_ug->u.a[u>>1].circ], "+-"[u&1], - chain_pre, (v>>1)+1, "lc"[b_ug->u.a[v>>1].circ], "+-"[v&1], 0, 0); - } - } - - for (i = 0; i < bub->ug->u.n; i++) { - if(f[i]) continue; - fprintf(fp, "U\t%s%.6d%c\t+\tcid:i:*\tbid:c:*\thom:%c\n", - utg_pre, i+1, "lc"[bub->ug->u.a[i].circ], "10"[IF_HOM(i, *bub)]); - } - free(f); -} - -void print_uls_ovlp(FILE *fp, all_ul_t *uls, const char* utg_pre, ma_ug_t *ug) -{ - ul_vec_t *p = NULL; nid_t *z = NULL; uc_block_t *m = NULL; uint64_t k, i; uint32_t a, la, occ; - kvec_t(uint8_t) f; kv_init(f); - for (k = 0; k < uls->n; k++) { - z = &(uls->nid.a[k]); - p = &(uls->a[k]); - for (i = 0; i < p->bb.n; i++) { - m = &(p->bb.a[i]); - if(m->base || (!m->el)) continue; - if(m->pchain) break; - } - if(i >= p->bb.n) continue; - kv_resize(uint8_t, f, p->bb.n); memset(f.a, 0, sizeof(*(f.a))*p->bb.n); - fprintf(fp, ">\t%.*s\n", (int32_t)z->n, z->a); - for (i = 0; i < p->bb.n; i++) { - if(f.a[i]) continue; - m = &(p->bb.a[i]); - if(m->base || (!m->el) || (!m->pchain)) continue; - for (a = i, la = i, occ = 0; a != (uint32_t)-1; a = p->bb.a[a].aidx) { - la = a; f.a[a] = 1; occ++; - } - fprintf(fp, "C\tLEN:%u\tS:%u\tE:%u\tOCC:%u\n", p->rlen, p->bb.a[i].qs, p->bb.a[la].qe, occ); - for (a = i; a != (uint32_t)-1; a = p->bb.a[a].aidx) { - m = &(p->bb.a[a]); - fprintf(fp, "%s%.6d%c[%c::", utg_pre, m->hid+1, "lc"[ug->u.a[(m->hid>>1)].circ], "+-"[m->rev]); - if(m->pdis == (uint32_t)-1) fprintf(fp, "*]\t"); - else fprintf(fp, "%u]\t", m->pdis); - } - fprintf(fp, "\n"); - } - } - - free(f.a); -} - -void print_debug_ul(const char* o_n, ma_ug_t *ug, asg_t *rg, const ma_sub_t *cov, ma_hit_t_alloc* src, R_to_U* ridx, -bubble_type *bub, all_ul_t *uls) -{ - char* gfa_name = (char*)malloc(strlen(o_n)+50); FILE *fn; - - if(ug && rg && cov && src && ridx) { - uint32_t k, m, v, w, an; asg_arc_t *p, *av; - for (k = 0; k < ug->g->n_arc; k++) { - p = &(ug->g->arc[k]); v = p->v^1; w = (p->ul>>32)^1; - av = asg_arc_a(ug->g, v); an = asg_arc_n(ug->g, v); - for (m = 0; m < an; m++) { - if(av[m].del == 0 && av[m].v == w) break; - } - assert(m < an && av[m].ou == p->ou); - } - sprintf(gfa_name, "%s.r_utg.noseq.gfa", o_n); fn = fopen(gfa_name, "w"); - ma_ug_print_simple(ug, rg, cov, src, ridx, "utg", fn); - fclose(fn); - } - - if(bub) { - sprintf(gfa_name, "%s.bub.noseq.gfa", o_n); fn = fopen(gfa_name, "w"); - print_bubble_gfa(fn, bub, "utg", "btg", "ctg"); - fclose(fn); - } - - if(uls && ug) { - sprintf(gfa_name, "%s.uls.ovlp", o_n); fn = fopen(gfa_name, "w"); - print_uls_ovlp(fn, uls, "utg", ug); - fclose(fn); - } - - free(gfa_name); - fprintf(stderr, "[M::%s::] done\n", __func__); - exit(1); -} - -int64_t normlize_gdis(ma_ug_t *ug, uc_block_t *i, uc_block_t *k, int64_t is_i2k_forward) -{ - int64_t i_len, k_len; - ///i > k - // if(is_i2k_forward == 0){ - // if(!i->rev) { - // i_len = i->qe + (ug->g->seq[i->hid].len - i->te); - // } else { - // i_len = i->qe + i->ts; - // } - - // if(!k->rev) { - // k_len = k->qe + (ug->g->seq[k->hid].len - k->te); - // } else { - // k_len = k->qe + k->ts; - // } - // } else { - // if(!i->rev) { - // i_len = (int64_t)i->qs - (int64_t)i->ts; - // } else { - // i_len = (int64_t)i->qs - (int64_t)(ug->g->seq[i->hid].len - i->te); - // } - // if(i_len < 0) i_len = 0; - - // if(!k->rev) { - // k_len = (int64_t)k->qs - (int64_t)k->ts; - // } else { - // k_len = (int64_t)k->qs - (int64_t)(ug->g->seq[k->hid].len - k->te); - // } - // if(k_len < 0) k_len = 0; - // } - - if(!i->rev) { - i_len = i->qe + (ug->g->seq[i->hid].len - i->te); - } else { - i_len = i->qe + i->ts; - } - - - if(!k->rev) { - k_len = k->qe + (ug->g->seq[k->hid].len - k->te); - } else { - k_len = k->qe + k->ts; - } - - if(is_i2k_forward) { - i_len -= ug->g->seq[i->hid].len; - k_len -= ug->g->seq[k->hid].len; - } - - - if(i_len >= k_len) return i_len - k_len; - // assert(i_len >= k_len); - return 0; -} - -int64_t normlize_gdis_exact(ma_ug_t *ug, uc_block_t *a, uint32_t i, uint32_t k, int64_t is_i2k_forward) -{ - assert(i > k); - uint32_t li, lk, pk, bi = i; int64_t l; - for (li = i, l = 0; i != (uint32_t)-1 && i >= k; i = a[i].pidx) { - li = i; - if(a[i].pidx != (uint32_t)-1 && i > k) l += a[i].pdis; - } - - if(is_i2k_forward) { - l += (int64_t)(ug->g->seq[a[li].hid].len); - l -= (int64_t)(ug->g->seq[a[bi].hid].len); - } - i = li; - if(i == k) return l; - assert(i > k); pk = k; - for (lk = k; k != (uint32_t)-1 && k <= i; k = a[k].aidx) lk = k; - for (k = lk; k != (uint32_t)-1 && k != pk; k = a[k].pidx) l += a[k].pdis; - // assert(k == pk); - if(is_i2k_forward) { - l += (int64_t)(ug->g->seq[a[pk].hid].len); - l -= (int64_t)(ug->g->seq[a[lk].hid].len); - } - if(l < 0) l = 0; - k = lk; - assert(i > k); - return l + normlize_gdis(ug, &(a[i]), &(a[k]), is_i2k_forward); -} - -uint32_t dis_check_integer_aln_t(all_ul_t *ul_idx, ul_str_idx_t *str_idx, ma_ug_t *ug, integer_aln_t *li, integer_aln_t *lk, -uint32_t qid, uint32_t tid, uint32_t is_rev, double diff_rate, int64_t hard_thres) -{ - assert(((uint32_t)li->tn_rev_qk) >= ((uint32_t)lk->tn_rev_qk)); - if(((uint32_t)li->tn_rev_qk) == ((uint32_t)lk->tn_rev_qk)) return 0; - if(li->tk <= lk->tk) return 0; - ul_str_t *q = &(str_idx->str.a[qid]), *t = &(str_idx->str.a[tid]); - uc_block_t *iq, *it, *kq, *kt; int64_t qlen, tlen, mm, dd, i_qk, k_qk, i_tk, k_tk; - i_qk = ((uint32_t)li->tn_rev_qk); k_qk = ((uint32_t)lk->tn_rev_qk); - if(!is_rev) { - i_tk = li->tk; k_tk = lk->tk; - } else { - i_tk = t->cn - lk->tk - 1; k_tk = t->cn - li->tk - 1; - } - iq = &(ul_idx->a[qid].bb.a[(q->a[i_qk]>>32)]); - it = &(ul_idx->a[tid].bb.a[(t->a[i_tk]>>32)]); - - kq = &(ul_idx->a[qid].bb.a[(q->a[k_qk]>>32)]); - kt = &(ul_idx->a[tid].bb.a[(t->a[k_tk]>>32)]); - qlen = normlize_gdis(ug, iq, kq, 0); tlen = normlize_gdis(ug, it, kt, is_rev); - if(qlen < tlen) { - mm = qlen; dd = tlen - qlen; - } else { - mm = tlen; dd = qlen - tlen; - } - - // if(tid == 3074) { - // fprintf(stderr, "\n+++[M::%s::] qlen::%ld, tlen::%ld, iq->hid::%u, kq->hid::%u, (q->a[i_qk]>>32)::%lu, (q->a[k_qk]>>32)::%lu, (t->a[i_tk]>>32)::%lu, (t->a[k_tk]>>32)::%lu\n", - // __func__, qlen, tlen, iq->hid, kq->hid, - // (q->a[i_qk]>>32), (q->a[k_qk]>>32), (t->a[i_tk]>>32), (t->a[k_tk]>>32)); - // } - - if(dd <= (mm*diff_rate) || dd < hard_thres) return 1; - - qlen = normlize_gdis_exact(ug, ul_idx->a[qid].bb.a, (q->a[i_qk]>>32), (q->a[k_qk]>>32), 0); - tlen = normlize_gdis_exact(ug, ul_idx->a[tid].bb.a, (t->a[i_tk]>>32), (t->a[k_tk]>>32), is_rev); - if(qlen < tlen) { - mm = qlen; dd = tlen - qlen; - } else { - mm = tlen; dd = qlen - tlen; - } - - if(dd <= (mm*diff_rate) || dd < hard_thres) return 1; - - // if(tid == 3074) { - // fprintf(stderr, "---[M::%s::] qlen::%ld, tlen::%ld, iq->hid::%u, kq->hid::%u\n", - // __func__, qlen, tlen, iq->hid, kq->hid); - // } - - - return 0; -} - -uint32_t integer_chain(uint32_t qid, integer_aln_t *a, int64_t a_n, int64_t offset, integer_t *buf, -ma_ug_t *ug, ul_str_idx_t *str_idx, all_ul_t *ul_idx, ul_chain_t *res) -{ - res->v = res->s = res->e = (uint32_t)-1; res->sc = (uint64_t)-1; - res->q_sidx = res->q_eidx = res->t_sidx = res->t_eidx = (uint32_t)-1; - if(a_n <= 0) return 0; - ///already sorted by qe - int64_t i, k, max_f, max_k, sc, csc, *p, *f, tf, ti/**, is_circle**/; - integer_aln_t *li, *lk; uint32_t tid = a[0].tn_rev_qk>>33; uint32_t is_rev = (a[0].tn_rev_qk>>32)&1; - for (i = 1, sc = 0; i < a_n; ++i) { - sc += a[i].sc; - if(a[i].tk <= a[i-1].tk) break;///== means there is a circle - if(((uint32_t)a[i].tn_rev_qk) <= ((uint32_t)a[i-1].tn_rev_qk)) break; - if(str_idx && ul_idx && (!dis_check_integer_aln_t(ul_idx, str_idx, - ug, &(a[i]), &(a[i-1]), qid, tid, is_rev, 0.08, 2000))) { - break; - } - } - // if(tid == 269 || tid == 276 || tid == 277 || tid == 278) fprintf(stderr, "tid->%u, i->%ld, an->%ld\n", tid, i, a_n); - if(i >= a_n) {//the whole chain is co-inear - sc += a[0].sc; - res->v = a[0].tn_rev_qk>>32; res->s = offset; res->e = offset + a_n; res->sc = sc; - return 1; - } - // is_circle = 1; - // if(str_idx->str.a[qid].is_cir == 0 && str_idx->str.a[tid].is_cir == 0) is_circle = 0; - - buf->p.n = buf->f.n = 0; - kv_resize(int64_t, buf->p, (uint64_t)a_n); p = buf->p.a; - kv_resize(int64_t, buf->f, (uint64_t)a_n); f = buf->f.a; - - tf = ti = -1; - for (i = 0; i < a_n; ++i) { - li = &(a[i]); csc = a[i].sc; - max_f = csc; max_k = -1; - for (k = i-1; k >= 0; --k) { - lk = &(a[k]); - ///qk of lk and li might be equal - if(lk->tk >= li->tk || ((uint32_t)lk->tn_rev_qk) >= ((uint32_t)li->tn_rev_qk)) continue; - // if(is_circle && (!dis_check_integer_aln_t(ul_idx, str_idx, ug, li, lk, qid, tid, is_rev, 0.08))) continue; - if(str_idx && ul_idx && (!dis_check_integer_aln_t(ul_idx, str_idx, - ug, li, lk, qid, tid, is_rev, 0.08, 2000))) { - continue; - } - sc = csc + f[k]; - if(sc > max_f) { - max_f = sc; max_k = k; - } - } - f[i] = max_f; p[i] = max_k; - if(tf < max_f) { - tf = max_f; ti = i; - } - } - - if(ti < 0) return 0; - - for (i = ti, k = 0; i >= 0; i = p[i]) f[k++] = i; - assert(k > 0); - for (i = sc = 0, k--; k >= 0; k--, i++) { - a[i] = a[f[k]]; sc += a[i].sc; - // if(tid == 269) { - // fprintf(stderr, "[%ld] qk->%u, tk->%u\n", i, (uint32_t)a[i].tn_rev_qk, a[i].tk); - // } - } - res->v = a[0].tn_rev_qk>>32; res->s = offset; res->e = offset + i; res->sc = sc; - return 1; -} - -/** -void calculate_boundary_integer_length(all_ul_t *ul_idx, ul_str_t *str, int64_t qid, int64_t tid, int64_t qk, int64_t tk, -int64_t is_rev, int64_t is_prefix, int64_t is_suffix, int64_t *r_qoff, int64_t *r_toff) -{ - (*r_qoff) = (*r_toff) = -1; - int64_t qlen = ul_idx->a[qid].rlen, tlen = ul_idx->a[tid].rlen, qoff, toff, q_ext, t_ext; - ul_str_t *qstr = &(str[qid]), *tstr = &(str[tid]); - if(is_rev) tk = tstr->cn - tk; - uc_block_t *q_b = &(ul_idx->a[qid].bb.a[qstr->a[qk]>>32]); - uc_block_t *t_b = &(ul_idx->a[tid].bb.a[tstr->a[tk]>>32]); - if(is_prefix) { - qoff = q_b->qs; toff = (is_rev?(tlen-t_b->qe):(t_b->qs)); - } - if(is_suffix) { - qoff = qlen - q_b->qe; toff = (is_rev?(t_b->qs):(tlen-t_b->qe)); - } - - if(qoff <= toff) { - t_ext = qoff; q_ext = -1; - } else { - q_ext = toff; t_ext = -1; - } - - if(q_ext == -1) { - if(is_prefix) (*r_qoff) = 0; - if(is_suffix) (*r_qoff) = (int64_t)(qstr->cn); - } - -} - -void push_ul_snp_t(int64_t chain_id, ul_str_t *str, integer_t *buf, integer_aln_t *a, int64_t a_n, int64_t qid, int64_t tid, int64_t is_rev) -{ - if(a_n <= 0) return; - int64_t k, qk, tk, p_qk, p_tk; ul_snp_t *p; - ul_str_t *qstr = &(str[qid]), *tstr = &(str[tid]); - for (k = 0, p_qk = 0, p_tk = 0; k < a_n; k++) { - qk = (uint32_t)a[k].tn_rev_qk; tk = a[k].tk; - if(qk - p_qk > 0 || tk - p_tk > 0) { - if(p_qk == 0 && p_tk == 0) {///first window - ///qk == 0 || tk == 0 means we already reach the end - if(qk > 0 && tk > 0) { - ; - } - } else { - kv_pushp(ul_snp_t, buf->snp, &p); - p->chain_id = chain_id; p->is_rev = is_rev; - p->qidx_occ = p_qk; p->qidx_occ += (qk - p_qk); - p->tidx_occ = p_tk; p->tidx_occ += (tk - p_tk); - } - } - p_qk = qk + 1; p_tk = tk + 1; - } - - qk = qstr->cn; tk = tstr->cn; - if(qk - p_qk > 0 || tk - p_tk > 0) { - kv_pushp(ul_snp_t, buf->snp, &p); - p->chain_id = chain_id; p->is_rev = is_rev; - p->qidx_occ = p_qk; p->qidx_occ += (qk - p_qk); - p->tidx_occ = p_tk; p->tidx_occ += (tk - p_tk); - } -} - -void integer_variant_call(integer_t *buf, ul_snp_t *a, int64_t a_n) -{ - kv_resize(int64_t, buf->f, (uint64_t)a_n); - int64_t *f = buf->f.a; int64_t k, m; ul_snp_t *p; - memset(f, -1, sizeof((*f))*a_n); - for (k = 0; k < a_n; k++) { - if(f[k] != (uint64_t)-1) continue; - for (m = k+1, p = &(a[k]); m < a_n; m++) { - - } - } - - -} - -void integer_phase(ul_str_t *str, integer_t *buf, ul_chain_t *idx, int64_t idx_n, integer_aln_t *aln, int64_t qid) -{ - int64_t k; integer_aln_t *a; buf->snp.n = 0; - for (k = 0; k < idx_n; k++) { - push_ul_snp_t(k, str, buf, aln + idx[k].s, idx[k].e - idx[k].s, qid, idx[k].v>>1, idx[k].v&1); - } - - int64_t z, snp_n = buf->snp.n; - radix_sort_ul_snp_t_srt(buf->snp.a, buf->snp.a + buf->snp.n); - for (z = 0, k = 1; k <= snp_n; k++) { - if(k == snp_n || buf->snp.a[z].qidx_occ != buf->snp.a[k].qidx_occ) { - integer_variant_call(buf, buf->snp.a + z, k - z); - z = k; - } - } -} -**/ - -int64_t append_connective(integer_aln_t *aln, ul_chain_t *idx, int64_t str_i, uint64_t occ_thres, uint64_t *res) -{ - int64_t k, kl = idx->e - idx->s, str_k = -1, fp = 0; integer_aln_t *a = aln + idx->s; - assert(idx->sc <= (uint64_t)kl); - for (k = idx->sc; k < kl; k++) { - str_k = (uint32_t)a[k].tn_rev_qk; - if(str_k >= str_i) break; - } - idx->sc = k; - if(k >= kl || str_k != str_i) return 0; - - for (k -= 1; k >= 0; k--) { - str_k = (uint32_t)a[k].tn_rev_qk; - if(res[str_k] < occ_thres) { - res[str_k]++; - if(res[str_k] == occ_thres) fp++; - } - } - return fp; -} - -int64_t connective_conform(integer_aln_t *aln, ul_chain_t *idx_a, int64_t idx_n, int64_t str_i0, int64_t occ_thres, uint64_t is_cov_check) -{ - if(str_i0 == 0) return 1; - int64_t z; ul_chain_t *x; int64_t k, kl, str_k, match, exact; integer_aln_t *a; - for (z = match = exact = 0; z < idx_n; z++) { - x = &(idx_a[z]); - kl = x->e - x->s; str_k = -1; a = aln + x->s; - assert(x->sc <= (uint64_t)kl); - for (k = x->sc; k < kl; k++) { - str_k = (uint32_t)a[k].tn_rev_qk; - if(str_k >= str_i0) break; - } - x->sc = k; - if(k >= kl || str_k != str_i0) continue; - k--; - if(k >= 0) { - str_k = (uint32_t)a[k].tn_rev_qk; - if(str_k+1 == str_i0) { - match++; - if(a[k].tk+1 == a[k+1].tk) exact++; - } - } - } - - if(is_cov_check) { - if(match < occ_thres) return 0; - } else { - assert(match >= occ_thres); - } - - if(exact == match) return 1; - if(exact > (match*0.51) && exact > (match/2)) return 1; - return 0; -} - -///occ_thres does not consider reference read itself; so the real coverage is (occ_thres+1) -int64_t integer_chain_dp(bubble_type *bub, integer_t *buf, ul_str_t *str, integer_aln_t *aln, ul_chain_t *idx, int64_t idx_n, int64_t qid, uint32_t is_hom, -uint64_t occ_thres, uint64_t *corrected) -{ - ul_str_t *qstr = &(str[qid]); int64_t k, q_n = qstr->cn, *f, *p, z, max_f, tf, tk, max_p, done_z, sc, csc, n_skip; - kv_resize(int64_t, buf->f, qstr->cn); kv_resize(int64_t, buf->p, qstr->cn); - kv_resize(uint64_t, buf->o, qstr->cn); uint64_t *o; - f = buf->f.a; p = buf->p.a; o = buf->o.a; if(corrected) (*corrected) = 0; - - // radix_sort_ul_chain_t_srt(idx, idx + idx_n); - for (k = 0; k < idx_n; k++) idx[k].sc = 0; - - for (k = 0, tf = tk = -1, n_skip = 0; k < q_n; k++) { - csc = buf->u.a[k]; - if((!is_hom) && (IF_HOM((((uint32_t)qstr->a[k])>>1), (*bub)))) { - csc = -1; n_skip++; - } - max_p = -1; max_f = csc; - if(k > 0 && max_f >= 0) { - done_z = 0; - if(is_hom) {//check all nodes - memset(o, 0, sizeof((*o))*k); - } else {///mask hom nodes - for (z = 0; z < k; z++) { - o[z] = 0; - if(f[z] == -1) { - o[z] = occ_thres; ///if node is hom, ignore it - done_z++; - } - } - } - - for (z = 0; z < idx_n && done_z < k; z++) { - done_z += append_connective(aln, &(idx[z]), k, occ_thres, o); - } - assert(done_z <= k); - for (z = k - 1; z >= 0; z--) { - if(o[z] < occ_thres) continue; - if(f[z] == -1) continue;///masked hom nodes - sc = csc + f[z]; - if(sc > max_f) { - max_f = sc; max_p = z; - } - } - } - f[k] = max_f; p[k] = max_p; - if(tf < max_f && max_f >= 0) { - tf = max_f; tk = k; - } - - // fprintf(stderr, "[M::%s::k->%ld] f[k]->%ld, p[k]->%ld, csc->%ld\n", __func__, k, f[k], p[k], csc); - } - if(tk < 0) return 0; - for (k = tk, done_z = 0; k >= 0; k = p[k]) done_z++; - ///might be fully corrected; but some of hom nodes have been skipped - if((corrected) && ((n_skip+done_z) == q_n) ) { - for (k = 0; k < idx_n; k++) idx[k].sc = 0; - for (k = 1, (*corrected) = 0; k < q_n; k++) { - if(!connective_conform(aln, idx, idx_n, k, occ_thres, (f[k] >= 0 && f[k-1] >= 0)?0:1)) break; - } - if(k >= q_n) (*corrected) = 1; - } - - for (k = tk, sc = done_z; k >= 0; k = p[k]) o[--done_z] = k; - return sc; -} - -void print_integer_seq(ma_ug_t *ug, ul_str_t *str, int64_t id, int64_t is_header) -{ - uint64_t i; - if(is_header) { - fprintf(stderr,"[M::%s::tid->%ld] occ::%u\n", __func__, id, str[id].cn); - } - for (i = 0; i < str[id].cn; i++) { - fprintf(stderr, "utg%.6d%c(%c)\t", (((uint32_t)str[id].a[i])>>1)+1, - "lc"[ug->u.a[(((uint32_t)str[id].a[i])>>1)].circ], "+-"[(((uint32_t)str[id].a[i])&1)]); - } - fprintf(stderr,"\n"); -} - - -#define poa_arc_n(g, v) ((uint32_t)(g)->idx.a[(v)]) -#define poa_arc_a(g, v) (&(g)->arc.a[(g)->idx.a[(v)]>>32]) - -void print_integer_g(poa_g_t *g, ma_ug_t *ug, uint64_t is_gfa) -{ - uint64_t i, v, w; - if(!is_gfa) { - for (i = 0; i < g->seq.n; i++) { - fprintf(stderr, "Node::[M::%s::i->%lu] utg%.6d%c(%c)\n", __func__, i, (int32_t)(g->seq.a[i].nid>>1)+1, - "lc"[ug->u.a[g->seq.a[i].nid>>1].circ], "+-"[g->seq.a[i].nid&1]); - } - for (i = 0; i < g->arc.n; i++) { - v = g->arc.a[i].ul>>32; w = g->arc.a[i].v; - if(v&1) continue; - v = g->seq.a[v>>1].nid; w = g->seq.a[w>>1].nid; - fprintf(stderr, "Arch::[M::%s::w->%u] utg%.6d%c(%c) -> utg%.6d%c(%c)\n", __func__, (uint32_t)g->arc.a[i].ul, - (int32_t)(v>>1)+1, "lc"[ug->u.a[v>>1].circ], "+-"[v&1], g->arc.a[i].ul>>33, - (int32_t)(w>>1)+1, "lc"[ug->u.a[w>>1].circ], "+-"[w&1], g->arc.a[i].v>>1); - } - for (i = 0; i < g->seq.n; i++) { - fprintf(stderr, "Srt::[M::%s::i->%lu] utg%.6d%c(%c)\n", __func__, i, - (int32_t)(g->seq.a[g->srt_b.res.a[i]].nid>>1)+1, - "lc"[ug->u.a[g->seq.a[g->srt_b.res.a[i]].nid>>1].circ], "+-"[g->seq.a[g->srt_b.res.a[i]].nid&1], g->srt_b.res.a[i]); - } - } else { - char name[32]; - for (i = 0; i < g->seq.n; i++) { - sprintf(name, "dtg%.6d", (int)i); - fprintf(stderr, "S\t%s\t*\tLN:i:%u\trd:i:utg%.6d%c(%c)\n", name, g->srt_b.res2nid.a[i], - (int32_t)(g->seq.a[i].nid>>1)+1, "lc"[ug->u.a[g->seq.a[i].nid>>1].circ], "+-"[g->seq.a[i].nid&1]); - } - uint32_t u, nu, j; poa_arc_t *au; - for (i = 0; i < g->seq.n; ++i) { - u = i<<1; - au = poa_arc_a(g, u); nu = poa_arc_n(g, u); - for (j = 0; j < nu; j++) { - v = au[j].v; - fprintf(stderr, "L\tdtg%.6d\t%c\tdtg%.6d\t%c\t%dM\n", - (int)(u>>1), "+-"[u&1], (int)(v>>1), "+-"[v&1], asg_arc_len(au[j])); - } - - u = (i<<1) + 1; - au = poa_arc_a(g, u); nu = poa_arc_n(g, u); - for (j = 0; j < nu; j++) { - v = au[j].v; - fprintf(stderr, "L\tdtg%.6d\t%c\tdtg%.6d\t%c\t%dM\n", - (int)(u>>1), "+-"[u&1], (int)(v>>1), "+-"[v&1], asg_arc_len(au[j])); - } - } - } -} - -void print_cns_seq(ma_ug_t *ug, ul_str_t *str, uint64_t *cns_seq, uint64_t cns_occ) -{ - fprintf(stderr,"[M::%s::]\t", __func__); - uint64_t k, ck; - for (k = ck = 0; k < str->cn; k++) { - for (; ck < cns_occ; ck++) { - if(cns_seq[ck] >= k) break; - } - if(ck < cns_occ && cns_seq[ck] == k) { - fprintf(stderr, "utg%.6d%c(%c)\t", (((uint32_t)str->a[k])>>1)+1, - "lc"[ug->u.a[(((uint32_t)str->a[k])>>1)].circ], "+-"[(((uint32_t)str->a[k])&1)]); - } else { - fprintf(stderr, "*\t"); - } - } - fprintf(stderr,"\n"); -} - -void print_res_seq(poa_g_t *pg, ma_ug_t *ug, uint32_t *cns_seq, uint32_t cns_occ) -{ - fprintf(stderr,"[M::%s::]\t", __func__); - uint64_t k; - for (k = 0; k < cns_occ; k++) { - fprintf(stderr, "utg%.6d%c(%c)\t", (pg->seq.a[(cns_seq[k]>>1)].nid>>1)+1, - "lc"[ug->u.a[(pg->seq.a[(cns_seq[k]>>1)].nid>>1)].circ], - "+-"[(pg->seq.a[(cns_seq[k]>>1)].nid&1)]); - - } - fprintf(stderr,"\n"); -} - -int64_t utg_cover_read_occ_by_qs(ma_ug_t *ug, int64_t oqs, int64_t oqe, uc_block_t *x) -{ - assert(oqs >= (int64_t)x->qs && oqs <= (int64_t)x->qe); - assert(oqe >= (int64_t)x->qs && oqe <= (int64_t)x->qe); - assert(oqe > oqs); - int64_t s_off, e_off, k; - s_off = get_offset_adjust(oqs-x->qs, x->qe-x->qs, x->te-x->ts); - e_off = get_offset_adjust(x->qe-oqe, x->qe-x->qs, x->te-x->ts); - if(x->rev) { - k = s_off; s_off = e_off; e_off = k; - } - - return ug_occ_w(x->ts + s_off, x->te - e_off, &(ug->u.a[x->hid])); -} - -int64_t estimate_ul_len(ma_ug_t *ug, ul_vec_t *raw_ov, ul_str_t *str, int64_t idx, int64_t ext_len, uint64_t *cov_buf) -{ - if(ext_len == 0) return idx; - int64_t aim_s, aim_e, k = idx, qs, qe, ovlp_s, ovlp_e, cov_occ, str_n = str->cn; - if(ext_len < 0) { - aim_s = ((int64_t)(raw_ov->bb.a[str->a[idx]>>32].qs)) + ext_len; - if(aim_s < 0) aim_s = 0; - aim_e = raw_ov->bb.a[str->a[idx]>>32].qe; - for (k = idx - 1; k >= 0; k--) { - qs = raw_ov->bb.a[str->a[k]>>32].qs; qe = raw_ov->bb.a[str->a[k]>>32].qe; - // if(qe <= aim_s) break; - ovlp_s = MAX(aim_s, qs); ovlp_e = MIN(aim_e, qe); - if(ovlp_e <= ovlp_s) { - k++; - break; - } - cov_occ = utg_cover_read_occ_by_qs(ug, ovlp_s, ovlp_e, &(raw_ov->bb.a[str->a[k]>>32])); - if(cov_occ == 0) { - k++; - break; - } - cov_buf[k] = cov_occ; - } - if(k < 0) k++; - } else { - aim_s = raw_ov->bb.a[str->a[idx]>>32].qs; - aim_e = ((int64_t)(raw_ov->bb.a[str->a[idx]>>32].qe)) + ext_len; - if(aim_e > (int64_t)(raw_ov->rlen)) aim_e = raw_ov->rlen; - for (k = idx + 1; k < str_n; k++) { - qs = raw_ov->bb.a[str->a[k]>>32].qs; qe = raw_ov->bb.a[str->a[k]>>32].qe; - // if(qs >= aim_e) - ovlp_s = MAX(aim_s, qs); ovlp_e = MIN(aim_e, qe); - if(ovlp_e <= ovlp_s) { - k--; - break; - } - cov_occ = utg_cover_read_occ_by_qs(ug, ovlp_s, ovlp_e, &(raw_ov->bb.a[str->a[k]>>32])); - if(cov_occ == 0) { - k--; - break; - } - cov_buf[k] = cov_occ; - } - if(k >= str_n) k--; - } - return k; -} - -void print_integer_ovlps(ma_ug_t *ug, ul_str_t *str, integer_aln_t *aln, int64_t aln_occ, ul_chain_t *idx, int64_t idx_n, int64_t qid, int64_t consenus_occ) -{ - fprintf(stderr, "\n[M::%s::qid->%ld] qstr->cn::%u, aln_occ::%ld, idx_n::%ld, consenus_occ::%ld\n", - __func__, qid, str[qid].cn, aln_occ, idx_n, consenus_occ); - // print_integer_seq(ug, str, qid, 0); - int64_t k, z, z_n, qk, tk, is_rev, tid; //uint64_t z; - for (k = 0; k < idx_n; k++) { - fprintf(stderr, "\n[M::%s::tid->%lu] rev->%lu, aln_n->%u\n", __func__, aln[idx[k].s].tn_rev_qk>>33, (aln[idx[k].s].tn_rev_qk>>32)&1, idx[k].e - idx[k].s); - print_integer_seq(ug, str, aln[idx[k].s].tn_rev_qk>>33, 0); - z = idx[k].s; z_n = idx[k].e; tid = aln[idx[k].s].tn_rev_qk>>33; - for (; z < z_n; z++) { - qk = (uint32_t)aln[z].tn_rev_qk; is_rev = ((aln[z].tn_rev_qk>>32)&1); - tk = ((is_rev == 0)? (aln[z].tk):(str[tid].cn - aln[z].tk - 1)); - fprintf(stderr, "[qk::%ld]utg%.6d%c(%c) <---> [tk::%ld]utg%.6d%c(%c)\n", - qk, (((uint32_t)str[qid].a[qk])>>1)+1, "lc"[ug->u.a[(((uint32_t)str[qid].a[qk])>>1)].circ], "+-"[(((uint32_t)str[qid].a[qk])&1)], - tk, (((uint32_t)str[tid].a[tk])>>1)+1, "lc"[ug->u.a[(((uint32_t)str[tid].a[tk])>>1)].circ], "+-"[(((uint32_t)str[tid].a[tk])&1)]); - } - - // for (z = idx[k].s; z < idx[k].e; z++) { - // aln[z].tn_rev_qk - // } - } -} - -void integer_align_extention(ma_ug_t *ug, all_ul_t *ul_idx, int64_t qid, ul_str_t *q_str, int64_t tid, ul_str_t *t_str, int64_t is_rev, -uint64_t *q_cov_buf, uint64_t *t_cov_buf, integer_aln_t *aln_pair, int64_t is_backward, int64_t *r_q_end, int64_t *r_t_end) -{ - int64_t qk, tk, qoff, toff, qlen, tlen, ext, q_end, t_end; uc_block_t *q_b, *t_b; - qk = (uint32_t)(aln_pair->tn_rev_qk); tk = ((is_rev == 0)? (aln_pair->tk):(t_str->cn - aln_pair->tk - 1)); - q_b = &(ul_idx->a[qid].bb.a[q_str->a[qk]>>32]); t_b = &(ul_idx->a[tid].bb.a[t_str->a[tk]>>32]); - qlen = ul_idx->a[qid].rlen; tlen = ul_idx->a[tid].rlen; - - if(is_backward) { - qoff = q_b->qs; toff = (is_rev?(tlen-t_b->qe):(t_b->qs)); - } else { - qoff = qlen - q_b->qe; toff = (is_rev?(t_b->qs):(tlen-t_b->qe)); - } - - if (qoff <= toff) ext = qoff; - else ext = toff; - - if(is_backward) { - q_end = estimate_ul_len(ug, &(ul_idx->a[qid]), q_str, qk, -ext, q_cov_buf); - t_end = estimate_ul_len(ug, &(ul_idx->a[tid]), t_str, tk, ((is_rev)?(ext):(-ext)), t_cov_buf); - } else { - q_end = estimate_ul_len(ug, &(ul_idx->a[qid]), q_str, qk, ext, q_cov_buf); - t_end = estimate_ul_len(ug, &(ul_idx->a[tid]), t_str, tk, ((is_rev)?(-ext):(ext)), t_cov_buf); - } - - (*r_q_end) = q_end; (*r_t_end) = t_end; -} - -int64_t gap_chain_check(ma_ug_t *ug, integer_aln_t *i0, integer_aln_t *i1, int64_t is_rev, ul_str_t *q_str, ul_str_t *t_str, -uc_block_t *q_block, uc_block_t *t_block, int64_t qid, int64_t tid, double diff_rate, int64_t hard_thres) -{ - int64_t i0_qk, i0_tk, i1_qk, i1_tk, q_near, t_near, lq, lt, min, max, dif; uint32_t e, k; - i0_qk = (uint32_t)(i0->tn_rev_qk); i1_qk = (uint32_t)(i1->tn_rev_qk); - if(is_rev == 0) { - i0_tk = i0->tk; i1_tk = i1->tk; - } else { - i1_tk = t_str->cn - i0->tk - 1; i0_tk = t_str->cn - i1->tk - 1; - } - assert(i0_qk < i1_qk); assert(i0_tk < i1_tk); - q_near = t_near = 0; - if((i0_qk + 1) == i1_qk) q_near = 1; - if((i0_tk + 1) == i1_tk) t_near = 1; - if((q_near + t_near) != 1) return 0; - - i0_qk = q_str->a[i0_qk]>>32; i1_qk = q_str->a[i1_qk]>>32; - i0_tk = t_str->a[i0_tk]>>32; i1_tk = t_str->a[i1_tk]>>32; - - k = i1_qk; e = i0_qk; lq = 0; - while ((k != (uint32_t)-1) && (k != e)) { - if(q_block[k].pidx != (uint32_t)-1) lq += q_block[k].pdis; - k = q_block[k].pidx; - } - if(k != e) return 0; - - k = i1_tk; e = i0_tk; lt = 0; - while ((k != (uint32_t)-1) && (k != e)) { - if(t_block[k].pidx != (uint32_t)-1) lt += t_block[k].pdis; - k = t_block[k].pidx; - } - if(k != e) return 0; - if(is_rev) { - lt += (int64_t)ug->g->seq[t_block[i0_tk].hid].len; - lt -= (int64_t)ug->g->seq[t_block[i1_tk].hid].len; - } - if(lt < 0) lt = 0; - if(lq <= lt) { - min = lq; max = lt; - } else { - min = lt; max = lq; - } - - dif = max - min; - if(dif >= (min*diff_rate)) { - // fprintf(stderr, "+[M::%s] qid::%ld, tid::%ld, i0_qk::%ld, i1_qk::%ld, lq::%ld, lt::%ld\n", - // __func__, qid, tid, i0_qk, i1_qk, lq, lt); - lq = normlize_gdis(ug, &(q_block[i1_qk]), &(q_block[i0_qk]), 0); - lt = normlize_gdis(ug, &(t_block[i1_tk]), &(t_block[i0_tk]), is_rev); - // fprintf(stderr, "-[M::%s] qid::%ld, tid::%ld, i0_qk::%ld, i1_qk::%ld, lq::%ld, lt::%ld\n", - // __func__, qid, tid, i0_qk, i1_qk, lq, lt); - // fprintf(stderr, "[M::%s] q_block[i0_qk].qs::%u, q_block[i0_qk].qe::%u, q_block[i1_qk].qs::%u, q_block[i1_qk].qe::%u\n", - // __func__, q_block[i0_qk].qs, q_block[i0_qk].qe, q_block[i1_qk].qs, q_block[i1_qk].qe); - - // fprintf(stderr, "[M::%s] t_block[i0_tk].qs::%u, t_block[i0_tk].qe::%u, t_block[i1_tk].qs::%u, t_block[i1_tk].qe::%u\n", - // __func__, t_block[i0_tk].qs, t_block[i0_tk].qe, t_block[i1_tk].qs, t_block[i1_tk].qe); - if(lq <= lt) { - min = lq; max = lt; - } else { - min = lt; max = lq; - } - - dif = max - min; - if(dif >= (min*diff_rate) || dif < hard_thres) return 0; - } - return 1; -} - -int64_t refine_integer_ovlps(all_ul_t *ul_idx, bubble_type *bub, ma_ug_t *ug, ul_str_t *str, integer_aln_t *aln, ul_chain_t *idx, int64_t qid, integer_t *buf, -uint64_t *cns, uint64_t cns_occ) -{ - if(idx->e<=idx->s) return 0; - int64_t qk, tk, is_rev, tid, q_end, t_end, z; - ul_str_t *q_str, *t_str; uc_block_t *t_b; integer_aln_t *x, *y; - tid = aln[idx->s].tn_rev_qk>>33; is_rev = ((aln[idx->s].tn_rev_qk>>32)&1); - q_str = &(str[qid]); t_str = &(str[tid]); - kv_resize(uint64_t, buf->u, buf->u.n + q_str->cn + t_str->cn); - uint64_t *q_cov_buf = buf->u.a + buf->u.n, *t_cov_buf = buf->u.a + buf->u.n + q_str->cn, k, rg_occ, cn_k, mm; - memset(q_cov_buf, -1, sizeof((*q_cov_buf))*q_str->cn); memset(t_cov_buf, -1, sizeof((*t_cov_buf))*t_str->cn); - // if(tid != 392) return 0; - //beg - x = &(aln[idx->s]); - qk = (uint32_t)(x->tn_rev_qk); tk = ((is_rev == 0)? (x->tk):(t_str->cn - x->tk - 1)); - - ///direction - if((qk > 0) && (x->tk > 0)) { - integer_align_extention(ug, ul_idx, qid, q_str, tid, t_str, is_rev, q_cov_buf, t_cov_buf, x, 1, &q_end, &t_end); - idx->q_sidx = q_end; idx->t_sidx = ((is_rev == 0)? (t_end):(t_str->cn - t_end - 1)); - } else { - idx->q_sidx = (uint32_t)(x->tn_rev_qk); idx->t_sidx = x->tk; - } - // if(!((idx->q_sidx <= ((uint32_t)(x->tn_rev_qk))) && (idx->t_sidx <= x->tk))) { - // fprintf(stderr, "[M::%s] qid::%ld, tid::%ld\n", __func__, qid, tid); - // } - assert((idx->q_sidx <= ((uint32_t)(x->tn_rev_qk)))); assert(idx->t_sidx <= x->tk); - // assert((is_rev && idx->t_sidx >= x->tk) || (is_rev == 0 && idx->t_sidx <= x->tk)); - - //end - x = &(aln[idx->e-1]); - qk = (uint32_t)(x->tn_rev_qk); tk = ((is_rev == 0)? (x->tk):(t_str->cn - x->tk - 1)); - // if(tid == 316) { - // fprintf(stderr, "[end-M::%s::tid->%ld] qk::%ld, tk::%ld, x->tk::%u, t_str->cn::%u\n", - // __func__, tid, qk, tk, x->tk, t_str->cn); - // } - ///direction - if((((uint32_t)qk + 1) < q_str->cn) && ((x->tk + 1) < t_str->cn)) { - integer_align_extention(ug, ul_idx, qid, q_str, tid, t_str, is_rev, q_cov_buf, t_cov_buf, x, 0, &q_end, &t_end); - idx->q_eidx = q_end + 1; idx->t_eidx = ((is_rev == 0)? (t_end + 1):(t_str->cn - t_end)); - } else { - idx->q_eidx = (uint32_t)(x->tn_rev_qk)+1; idx->t_eidx = x->tk+1; - } - - assert(idx->q_eidx > ((uint32_t)(x->tn_rev_qk))); assert(idx->t_eidx > x->tk); - // assert((is_rev && idx->t_eidx < x->tk) || (is_rev == 0 && idx->t_eidx > x->tk)); - - assert(idx->q_eidx > idx->q_sidx); assert(idx->t_eidx > idx->t_sidx); - // assert((is_rev && idx->t_eidx < idx->t_sidx) || (is_rev == 0 && idx->t_eidx > idx->t_sidx)); - // if(tid == 284) { - // fprintf(stderr, "[M::%s::tid->%ld] idx->q_sidx::%u, idx->q_eidx::%u, idx->t_sidx::%u, idx->t_eidx::%u\n", - // __func__, tid, idx->q_sidx, idx->q_eidx, idx->t_sidx, idx->t_eidx); - // } - - ///mid - for (k = idx->s; k < idx->e; k++) {///go through all alignment pairs - // if(qid == 3113 && tid == 3075) { - // fprintf(stderr, "+[M::%s] qid::%ld, tid::%ld, idx->s::%u, idx->e::%u, k::%lu, qk::%u, tk::%u, (idx->v>>1)::%u\n", - // __func__, qid, tid, idx->s, idx->e, k, (uint32_t)(aln[k].tn_rev_qk), aln[k].tk, idx->v>>1); - // } - - x = &(aln[k]); y = ((k > idx->s)? (&(aln[k-1])):(NULL)); - qk = (uint32_t)(x->tn_rev_qk); - q_cov_buf[qk] = buf->u.a[qk]; - - tk = ((is_rev == 0)? (x->tk):(t_str->cn - x->tk - 1)); - t_b = &(ul_idx->a[tid].bb.a[t_str->a[tk]>>32]); - assert(((t_b->hid<<1)+t_b->rev)==((uint32_t)t_str->a[tk])); - t_cov_buf[tk] = ug_occ_w(t_b->ts, t_b->te, &(ug->u.a[t_b->hid])); - - q_cov_buf[qk] += ((uint64_t)(0x8000000000000000)); - t_cov_buf[tk] += ((uint64_t)(0x8000000000000000)); - - if(!y) continue; - mm = 0; - if(gap_chain_check(ug, y, x, is_rev, q_str, t_str, ul_idx->a[qid].bb.a, ul_idx->a[tid].bb.a, qid, tid, 0.08, 2000)) { - mm = ((uint64_t)(0x8000000000000000)); - } - for (z = ((uint32_t)(y->tn_rev_qk)) + 1; z < qk; z++) { - q_cov_buf[z] = buf->u.a[z] + mm; - } - - z = ((is_rev == 0)? (y->tk):(t_str->cn - x->tk - 1)) + 1; - tk = ((is_rev == 0)? (x->tk):(t_str->cn - y->tk - 1)); - assert(z <= tk); - for (; z < tk; z++) { - t_b = &(ul_idx->a[tid].bb.a[t_str->a[z]>>32]); - assert(((t_b->hid<<1)+t_b->rev)==((uint32_t)t_str->a[z])); - t_cov_buf[z] = ug_occ_w(t_b->ts, t_b->te, &(ug->u.a[t_b->hid])) + mm; - } - } - - if(cns) { - int64_t cns_cov_occ = 0, cns_het_occ = 0, match_cns_occ = 0, match_cns_het_occ = 0, hm; - rg_occ = idx->q_eidx; - for (k = idx->q_sidx, cn_k = 0; k < rg_occ; k++) { - assert((q_cov_buf[k]!=(uint64_t)-1) && (q_cov_buf[k] > 0)); - hm = ((q_cov_buf[k]<<1)>>1); - for (; cn_k < cns_occ; cn_k++) { - if(cns[cn_k] == k) { - cns_cov_occ += hm; - if(q_cov_buf[k]&((uint64_t)(0x8000000000000000))) match_cns_occ += hm; - if(!IF_HOM((((uint32_t)q_str->a[k])>>1), (*bub))) { - cns_het_occ += hm; - if(q_cov_buf[k]&((uint64_t)(0x8000000000000000))) match_cns_het_occ += hm; - } - } else if(cns[cn_k] > k) { - break; - } - } - } - - if(cns_cov_occ <= 0) return 0; - if((cns_het_occ > 0) && (match_cns_het_occ <= (cns_het_occ*0.5))) return 0; - if(match_cns_occ <= (cns_cov_occ*0.5)) return 0; - - k = idx->t_sidx; rg_occ = idx->t_eidx; - if(is_rev) { - k = t_str->cn - idx->t_eidx; rg_occ = t_str->cn - idx->t_sidx; - } - cns_cov_occ = match_cns_occ = 0; - assert(k < rg_occ); - for (; k < rg_occ; k++) { - assert((t_cov_buf[k]!=(uint64_t)-1) && (t_cov_buf[k] > 0)); - hm = ((t_cov_buf[k]<<1)>>1); - cns_cov_occ += hm; - if(t_cov_buf[k]&((uint64_t)(0x8000000000000000))) match_cns_occ += hm; - } - - if(cns_cov_occ <= 0 || match_cns_occ <= 0) return 0; - if(match_cns_occ <= (cns_cov_occ*0.5)) return 0; - } - ///not useful for correction - if((idx->q_sidx + 1 == idx->q_eidx) && (idx->t_sidx + 1 == idx->t_eidx)) {///must matched with at least one cns node - return 0; - } - - // /**if(tid == 3074)**/ { - // print_integer_ovlps(ug, str, buf->b.a, buf->b.n, idx, 1, qid, buf->o.n); - // fprintf(stderr, "[M::%s::tid->%ld] idx->q_sidx::%u, idx->q_eidx::%u, idx->t_sidx::%u, idx->t_eidx::%u\n******************************************************\n", - // __func__, tid, idx->q_sidx, idx->q_eidx, idx->t_sidx, idx->t_eidx); - // } - - return 1; -} - - -void uc_block_qse_cutoff(uint32_t c_ts, uint32_t c_te, uc_block_t *x, uint32_t *nqs, uint32_t *nqe) -{ - uint32_t l, r; - assert(c_ts >= x->ts && c_te <= x->te); - if(!(x->rev)) { - l = c_ts - x->ts; r = x->te - c_te; - } else { - r = c_ts - x->ts; l = x->te - c_te; - } - - (*nqs) = x->qs + get_offset_adjust(l, x->te - x->ts, x->qe - x->qs); - (*nqe) = x->qe - get_offset_adjust(r, x->te - x->ts, x->qe - x->qs); - assert((*nqs) >= x->qs && (*nqe) <= x->qe); -} - -int64_t update_exact_ul_ovlps(all_ul_t *ul_idx, ma_ug_t *ug, ul_str_t *str, integer_aln_t *aln, ul_chain_t *idx, int64_t qid, -integer_t *buf, ul2ul_t *res) -{ - if(idx->e<=idx->s) return 0; - int64_t qk, tk, is_rev, tid, q_end, t_end; - ul_str_t *q_str, *t_str; integer_aln_t *x; - tid = aln[idx->s].tn_rev_qk>>33; is_rev = ((aln[idx->s].tn_rev_qk>>32)&1); - q_str = &(str[qid]); t_str = &(str[tid]); - uint64_t os, oe; uint32_t v, w, q_ns, q_ne, t_ns, t_ne, acc, chained, qbs, qbe, tbs, tbe; - // if(qid == 95 || qid == 36) { - // fprintf(stderr,"[M::%s::qid->%ld::tid->%ld] qs_idx::%u, qe_idx::%u, ts_idx::%u, te_idx::%u\n", __func__, qid, tid, - // (uint32_t)(aln[idx->s].tn_rev_qk), (uint32_t)(aln[idx->e-1].tn_rev_qk), - // aln[idx->s].tk, aln[idx->e-1].tk); - // } - //beg - x = &(aln[idx->s]); - qk = (uint32_t)(x->tn_rev_qk); tk = ((is_rev == 0)? (x->tk):(t_str->cn - x->tk - 1)); - if((qk > 0) && (x->tk > 0)) return 0; - idx->q_sidx = (uint32_t)(x->tn_rev_qk); idx->t_sidx = x->tk; - - //end - x = &(aln[idx->e-1]); - qk = (uint32_t)(x->tn_rev_qk); tk = ((is_rev == 0)? (x->tk):(t_str->cn - x->tk - 1)); - if((((uint32_t)qk + 1) < q_str->cn) && ((x->tk + 1) < t_str->cn)) return 0; - idx->q_eidx = (uint32_t)(x->tn_rev_qk)+1; idx->t_eidx = x->tk+1; - - if((idx->q_eidx - idx->q_sidx) != (idx->t_eidx - idx->t_sidx)) return 0; - if(idx->q_eidx <= idx->q_sidx) return 0; - - qk = idx->q_sidx; q_end = idx->q_eidx; - tk = idx->t_sidx; t_end = idx->t_eidx; - for (; qk < q_end && tk < t_end; qk++, tk++){ - v = ((uint32_t)q_str->a[qk]); - if(!is_rev) w = ((uint32_t)t_str->a[tk]); - else w = ((uint32_t)t_str->a[t_str->cn-tk-1])^1; - if(v != w) break; - } - if(qk!=q_end || tk!=t_end) return 0; - - uc_block_t *qi, *ti; - qk = idx->q_sidx; q_end = idx->q_eidx; - tk = idx->t_sidx; t_end = idx->t_eidx; - - buf->p.n = buf->f.n = buf->o.n = buf->u.n = 0; - kv_resize(int64_t, buf->p, idx->q_eidx - idx->q_sidx); int64_t *p = buf->p.a; - kv_resize(int64_t, buf->f, idx->q_eidx - idx->q_sidx); int64_t *f = buf->f.a; - kv_resize(uint64_t, buf->o, idx->q_eidx - idx->q_sidx); uint64_t *qc = buf->o.a; - kv_resize(uint64_t, buf->u, idx->q_eidx - idx->q_sidx); uint64_t *tc = buf->u.a; - int64_t max_f, max_z, csc, ps, sc, tf, tz, z; - for (acc = 0, chained = 1, tf = tz = -1; qk < q_end && tk < t_end; qk++, tk++) { - qi = &(ul_idx->a[qid].bb.a[q_str->a[qk]>>32]); - if(!is_rev) ti = &(ul_idx->a[tid].bb.a[t_str->a[tk]>>32]); - else ti = &(ul_idx->a[tid].bb.a[t_str->a[t_str->cn-tk-1]>>32]); - assert(qi->hid == ti->hid); - os = MAX(qi->ts, ti->ts); oe = MIN(qi->te, ti->te); - if(oe <= os) continue; - uc_block_qse_cutoff(os, oe, qi, &q_ns, &q_ne); - uc_block_qse_cutoff(os, oe, ti, &t_ns, &t_ne); - qc[acc] = q_ns; qc[acc] <<= 32; qc[acc] |= q_ne; - tc[acc] = t_ns; tc[acc] <<= 32; tc[acc] |= t_ne; - - z = acc; z -= 1; csc = q_ne - q_ns; if(csc <= 0) csc = 1; - max_f = csc; max_z = -1; ps = 0; - if(chained && z >= 0) { - qbs = qc[z]>>32; qbe = (uint32_t)qc[z]; - tbs = tc[z]>>32; tbe = (uint32_t)tc[z]; - if(!is_rev) { - if(qbs <= q_ns && qbe <= q_ne && tbs <= t_ns && tbe <= t_ne) ps = 1; - } else { - if(qbs <= q_ns && qbe <= q_ne && tbs >= t_ns && tbe >= t_ne) ps = 1; - } - if(ps) { - sc = csc + f[z]; - if(sc > max_f) { - max_f = sc; max_z = z; - } - } else { - chained = 0; - } - } - - if((!ps) || (!chained)) { - for (; z >= 0; z--) { - qbs = qc[z]>>32; qbe = (uint32_t)qc[z]; - tbs = tc[z]>>32; tbe = (uint32_t)tc[z]; - ps = 0; - if(!is_rev) { - if(qbs <= q_ns && qbe <= q_ne && tbs <= t_ns && tbe <= t_ne) ps = 1; - } else { - if(qbs <= q_ns && qbe <= q_ne && tbs >= t_ns && tbe >= t_ne) ps = 1; - } - if(!ps) continue; - sc = csc + f[z]; - if(sc > max_f) { - max_f = sc; max_z = z; - } - } - } - - f[acc] = max_f; p[acc] = max_z; - if(tf < max_f) { - tf = max_f; tz = acc; - } - acc++; - } - if(acc <= 0) return 0; - assert(tz >= 0); - res->hid = res->qs = res->qe = res->ts = res->te = (uint32_t)-1; - res->hid = tid; res->is_rev = !!is_rev; res->is_del = 0; res->is_ct = 0; - res->qs_k = idx->q_sidx; res->qe_k = idx->q_eidx; - if(!is_rev) { - res->ts_k = idx->t_sidx; res->te_k = idx->t_eidx; - } else { - res->ts_k = t_str->cn - idx->t_eidx; res->te_k = t_str->cn - idx->t_sidx; - } - - - res->qe = (uint32_t)qc[tz]; - if(!is_rev) res->te = (uint32_t)tc[tz]; - else res->ts = tc[tz]>>32; - - for (z = tz; z >= 0; z = p[z]) { - res->qs = qc[z]>>32; - if(!is_rev) res->ts = tc[z]>>32; - else res->te = (uint32_t)tc[z]; - } - assert(res->qs <= res->qe && res->ts <= res->te); - - - int64_t qs = 0, qe = 0, rs = 0, re = 0, qtail = 0, rtail = 0; - qs = res->qs; qe = res->qe; rs = res->ts; re = res->te; - if(is_rev) { - rs = ul_idx->a[tid].rlen - res->te; re = ul_idx->a[tid].rlen - res->ts; - } - if(qs <= rs) { - rs -= qs; qs = 0; - } else { - qs -= rs; rs = 0; - } - - qtail = ul_idx->a[qid].rlen - qe; rtail = ul_idx->a[tid].rlen - re; - if(qtail <= rtail) { - qe = ul_idx->a[qid].rlen; re += qtail; - } - else { - re = ul_idx->a[tid].rlen; qe += rtail; - } - res->qs = qs; res->qe = qe; - res->ts = rs; res->te = re; - if(is_rev) { - res->ts = ul_idx->a[tid].rlen - re; - res->te = ul_idx->a[tid].rlen - rs; - } - return 1; -} - - - -void reset_poa_g_t(poa_g_t *g) -{ - g->seq.n = g->arc.n = g->idx.n = 0; g->update_arc = g->update_seq = g->e_idx.n = 0; -} - -void clean_poa_g_t(poa_g_t *g) -{ - uint64_t set_n = g->seq.n<<1; - assert(g->arc.n >= g->update_arc); assert(g->seq.n >= g->update_seq); - if(g->seq.n > g->update_seq) { - kv_resize(uint64_t, g->idx, (g->seq.n<<1)); set_n = g->update_seq<<1; - memset(g->idx.a + (g->update_seq<<1), 0, sizeof((*g->idx.a))*((g->seq.n<<1)-(g->update_seq<<1))); - g->update_seq = g->seq.n; g->idx.n = (g->seq.n<<1); - } - - if(g->arc.n > g->update_arc) { - radix_sort_poa_arc_srt(g->arc.a, g->arc.a + g->arc.n); - memset(g->idx.a, 0, sizeof((*g->idx.a))*set_n); - int64_t k, last, n = g->arc.n; - for (k = 1, last = 0; k <= n; ++k){ - if (k == n || g->arc.a[k-1].ul>>32 != g->arc.a[k].ul>>32) { - g->idx.a[g->arc.a[k-1].ul>>32] = (((uint64_t)last<<32)) | (k - last), last = k; - } - } - g->update_arc = g->arc.n; - } -} - -void append_unmatch_integer_seq(poa_g_t *g, ma_ug_t *ug, uc_block_t *raw, ul_str_t *str, int64_t s, int64_t e, int64_t is_rev, int64_t str_id) -{ - int64_t k; poa_nid_t *nn; poa_arc_t *ae; uint32_t v; uc_block_t *z; emap_t *em; - for (k = s; k < e; k++) { - if(is_rev) { - v = (((uint32_t)str->a[str->cn-k-1])^1); - z = &(raw[str->a[str->cn-k-1]>>32]); - } - else { - v = ((uint32_t)str->a[k]); z = &(raw[str->a[k]>>32]); - } - kv_pushp(poa_nid_t, g->seq, &nn); - nn->nid = v; nn->occ = ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); - - // ug->u.a[v>>1].n; - if(k > s) { - kv_pushp(poa_arc_t, g->arc, &ae); - ae->ul = g->seq.n-1; ae->ul <<= 33; ae->ul += ((uint64_t)(0x100000000)); ae->ul += 1; - ae->v = g->seq.n-2; ae->v <<= 1; ae->v += 1; - - kv_pushp(poa_arc_t, g->arc, &ae); - ae->ul = g->seq.n-2; ae->ul <<= 33; ae->ul += 1; - ae->v = g->seq.n-1; ae->v <<= 1; - - kv_pushp(emap_t, g->e_idx, &em); - em->pge = g->seq.n-2; em->pge <<= 32; em->pge += g->seq.n-1; - em->ule = (is_rev?(str->cn-k):(k-1)); em->ule <<= 32; em->ule += (is_rev?(str->cn-k-1):(k)); - em->ulid = str_id; - // assert((g->seq.a[em->pge>>32].nid^(is_rev?1:0)) == ((uint32_t)str->a[em->ule>>32])); - // assert((g->seq.a[(uint32_t)em->pge].nid^(is_rev?1:0)) == ((uint32_t)str->a[(uint32_t)em->ule])); - } - } -} - -void update_poa_nid_occ(ma_ug_t *ug, uc_block_t *raw, poa_g_t *g, int64_t gidx, uint64_t *str, int64_t str_idx, int64_t is_rev) -{ - uint32_t g_v, str_v, new_occ; uc_block_t *z; - ///update - g_v = g->seq.a[gidx].nid; - z = &(raw[str[str_idx]>>32]); str_v = ((uint32_t)str[str_idx]); if(is_rev) str_v ^= 1; - assert(g_v == str_v); assert(g->seq.a[gidx].occ <= ug->u.a[g->seq.a[gidx].nid>>1].n); - if(g->seq.a[gidx].occ != ug->u.a[g->seq.a[gidx].nid>>1].n) { - new_occ = ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); - if(new_occ > g->seq.a[gidx].occ) g->seq.a[gidx].occ = new_occ; - } -} - -void insert_poa_nodes_0(ma_ug_t *ug, uc_block_t *raw, poa_g_t *g, uint64_t *str, int64_t str_occ, uint64_t is_rev, int64_t str_id, int64_t str_off) -{ - int64_t k; poa_nid_t *nn; poa_arc_t *ae; uint32_t v; uc_block_t *z; emap_t *em; - for (k = 0; k < str_occ; k++) { - if(is_rev == 0) { - v = ((uint32_t)str[k]); z = &(raw[str[k]>>32]); - } else { - v = ((uint32_t)str[str_occ-k-1])^1; z = &(raw[str[str_occ-k-1]>>32]); - } - - kv_pushp(poa_nid_t, g->seq, &nn); - nn->nid = v; nn->occ = ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); - - if(k > 0) { - kv_pushp(poa_arc_t, g->arc, &ae); - ae->ul = g->seq.n-1; ae->ul <<= 33; ae->ul += ((uint64_t)(0x100000000)); ae->ul += 1; - ae->v = g->seq.n-2; ae->v <<= 1; ae->v += 1; - - kv_pushp(poa_arc_t, g->arc, &ae); - ae->ul = g->seq.n-2; ae->ul <<= 33; ae->ul += 1; - ae->v = g->seq.n-1; ae->v <<= 1; - - kv_pushp(emap_t, g->e_idx, &em); - em->pge = g->seq.n-2; em->pge <<= 32; em->pge += g->seq.n-1; - em->ule = str_off + (is_rev?(str_occ-k):(k-1)); em->ule <<= 32; - em->ule += str_off + (is_rev?(str_occ-k-1):(k)); - em->ulid = str_id; - - // if(!((g->seq.a[em->pge>>32].nid^(is_rev?1:0)) == ((uint32_t)debug_str->a[em->ule>>32]))) { - // fprintf(stderr, "[M::%s::k->%ld::str_occ->%ld] is_rev->%lu, pg_v->%u, str_v->%u, str_off->%ld, str_k->%lu, str_cn->%u, address_diff->%u\n", - // __func__, k, str_occ, is_rev, (g->seq.a[em->pge>>32].nid^(is_rev?1:0)), - // ((uint32_t)debug_str->a[em->ule>>32]), str_off, em->ule>>32, debug_str->cn, (uint32_t)(str - debug_str->a)); - // uint64_t debug_k; - // for (debug_k = 0; debug_k < debug_str->cn; debug_k++) { - // fprintf(stderr, "[M::%s::debug_k->%lu] str_v->%u\n", - // __func__, debug_k, ((uint32_t)debug_str->a[debug_k])); - // } - - // } - // assert((g->seq.a[em->pge>>32].nid^(is_rev?1:0)) == ((uint32_t)debug_str->a[em->ule>>32])); - // assert((g->seq.a[(uint32_t)em->pge].nid^(is_rev?1:0)) == ((uint32_t)debug_str->a[(uint32_t)em->ule])); - } - } -} - -void push_poa_arch_0(poa_g_t *g, uint32_t src, uint32_t des, int64_t str_id, int64_t str_src, int64_t str_des) -{ - poa_arc_t *ae; emap_t *em; - kv_pushp(poa_arc_t, g->arc, &ae); - ae->ul = des; ae->ul <<= 33; ae->ul += ((uint64_t)(0x100000000)); ae->ul += 1; - ae->v = src; ae->v <<= 1; ae->v += 1; - - kv_pushp(poa_arc_t, g->arc, &ae); - ae->ul = src; ae->ul <<= 33; ae->ul += 1; - ae->v = des; ae->v <<= 1; - - kv_pushp(emap_t, g->e_idx, &em); - em->pge = src; em->pge <<= 32; em->pge += des; - em->ule = str_src; em->ule <<= 32; em->ule += str_des; - em->ulid = str_id; - - // assert((g->seq.a[em->pge>>32].nid^(debug_is_rev?1:0)) == ((uint32_t)debug_str->a[em->ule>>32])); - // assert((g->seq.a[(uint32_t)em->pge].nid^(debug_is_rev?1:0)) == ((uint32_t)debug_str->a[(uint32_t)em->ule])); -} - -void update_poa_arch_0(poa_g_t *g, uint32_t src, uint32_t des, int64_t str_id, int64_t str_src, int64_t str_des) -{ - uint32_t k, v, w, a_n; poa_arc_t *a; emap_t *em; - v = src<<1; w = des<<1; - a_n = poa_arc_n(g, v); a = poa_arc_a(g, v); - for (k = 0; k < a_n; k++) { - if(a[k].v == w) break; - } - if(k >= a_n) { - push_poa_arch_0(g, src, des, str_id, str_src, str_des); - } else { - a[k].ul++; - v = des<<1; v^=1; - w = src<<1; w^=1; - a_n = poa_arc_n(g, v); a = poa_arc_a(g, v); - for (k = 0; k < a_n; k++) { - if(a[k].v == w) break; - } - assert(k < a_n); - a[k].ul++; - - kv_pushp(emap_t, g->e_idx, &em); - em->pge = src; em->pge <<= 32; em->pge += des; - em->ule = str_src; em->ule <<= 32; em->ule += str_des; - em->ulid = str_id; - - // assert((g->seq.a[em->pge>>32].nid^(debug_is_rev?1:0)) == ((uint32_t)debug_str->a[em->ule>>32])); - // assert((g->seq.a[(uint32_t)em->pge].nid^(debug_is_rev?1:0)) == ((uint32_t)debug_str->a[(uint32_t)em->ule])); - } -} - -void append_integer_seq_frag(ma_ug_t *ug, uc_block_t *raw, poa_g_t *g, int64_t g_beg, int64_t g_end, uint64_t *str, int64_t str_occ, uint64_t is_rev, int64_t str_id, int64_t str_off) -{ - // if(str_occ <= 0) return; - uint32_t nid; - // if((g_beg >= 0 || g_end >= 0) && str_occ < 2) return; - if(g_beg < 0 && g_end < 0) {//add new nodes - insert_poa_nodes_0(ug, raw, g, str, str_occ, is_rev, str_id, str_off); - return; - } - - if(g_beg < 0 && g_end >= 0) {///add nodes to the left end - assert(str_occ >= 1); - update_poa_nid_occ(ug, raw, g, g_end, str, (is_rev?(0):(str_occ-1)), is_rev); - if(str_occ < 2) return; - insert_poa_nodes_0(ug, raw, g, (is_rev?(str+1):(str)), str_occ-1, is_rev, str_id, str_off+(is_rev?(1):(0))); - - push_poa_arch_0(g, g->seq.n-1, g_end, str_id, str_off + (is_rev?(1):(str_occ-2)), - str_off + (is_rev?(0):(str_occ-1))); - return; - } - - if(g_beg >= 0 && g_end < 0) {///add nodes to the right end - assert(str_occ >= 1); - update_poa_nid_occ(ug, raw, g, g_beg, str, (is_rev?(str_occ-1):(0)), is_rev); - if(str_occ < 2) return; - nid = g->seq.n;///backup - insert_poa_nodes_0(ug, raw, g, (is_rev?(str):(str+1)), str_occ-1, is_rev, str_id, str_off+(is_rev?(0):(1))); - push_poa_arch_0(g, g_beg, nid, str_id, str_off + (is_rev?(str_occ-1):(0)), - str_off + (is_rev?(str_occ-2):(1))); - return; - } - - if(g_beg >= 0 && g_end >= 0) {///add nodes to the middle - assert(str_occ >= 2); - update_poa_nid_occ(ug, raw, g, g_beg, str, (is_rev?(str_occ-1):(0)), is_rev); - update_poa_nid_occ(ug, raw, g, g_end, str, (is_rev?(0):(str_occ-1)), is_rev); - if(str_occ > 2) {///insert new nodes - nid = g->seq.n;///backup - insert_poa_nodes_0(ug, raw, g, str+1, str_occ-2, is_rev, str_id, str_off+1); - push_poa_arch_0(g, g_beg, nid, str_id, str_off + (is_rev?(str_occ-1):(0)), - str_off + (is_rev?(str_occ-2):(1))); - push_poa_arch_0(g, g->seq.n-1, g_end, str_id, str_off + (is_rev?(1):(str_occ-2)), - str_off + (is_rev?(0):(str_occ-1))); - } else { - ///add an edge between g_beg and g_end - update_poa_arch_0(g, g_beg, g_end, str_id, str_off + (is_rev?(str_occ-1):(0)), - str_off + (is_rev?(0):(str_occ-1))); - } - } -} - -void append_aligned_integer_seq(ma_ug_t *ug, uc_block_t *raw, poa_g_t *g, int64_t g_occ, uint64_t *str, int64_t str_occ, uint64_t is_rev, -uint32_t *match_g, uint32_t *match_str, int64_t match_occ) -{ - if(str_occ <= 0) return; - int64_t k, p_str, p_g; - - if(is_rev == 0) { - for (k = match_occ-1, p_str = 0, p_g = -1; k >= 0; k--) { - fprintf(stderr, "+[M::%s::] match_str[%ld]::%u, match_occ::%ld, p_g::%ld\n", - __func__, k, match_str[k], match_occ, p_g); - assert(((int64_t)match_str[k]) >= p_str); - // append_integer_seq_frag(ug, raw, g, p_g, match_g[k], str+p_str, match_str[k]+1-p_str, is_rev); - p_str = match_str[k]; p_g = match_g[k]; - } - // append_integer_seq_frag(ug, raw, g, p_g, -1, str+p_str, str_occ-p_str, is_rev); - } else { - for (k = match_occ-1, p_str = str_occ-1, p_g = -1; k >= 0; k--) { - fprintf(stderr, "-[M::%s::] match_str[%ld]::%u, match_occ::%ld\n", - __func__, k, match_str[k], match_occ); - assert(((int64_t)match_str[k]) <= p_str); - // append_integer_seq_frag(ug, raw, g, p_g, match_g[k], str+match_str[k], p_str+1-match_str[k], is_rev); - p_str = match_str[k]; p_g = match_g[k]; - } - // append_integer_seq_frag(ug, raw, g, p_g, -1, str, p_str+1, is_rev); - } -} - - -#define poa_str_idx(i, occ, is_rev) (((is_rev))?((occ)-(i)-1):(i)) -void append_aligned_integer_seq_by_aln_pair(ma_ug_t *ug, uc_block_t *raw, poa_g_t *g, int64_t g_occ, uint64_t *str, int64_t str_occ, uint64_t is_rev, integer_aln_t *a, int64_t a_n, int64_t str_id, int64_t str_off) -{ - if(str_occ <= 0 || a_n <= 0) return; - int64_t k, p_str, p_g; uint64_t *qstr_a, qstr_n, qoff; uint32_t *gidx = g->srt_b.res.a; - - for (k = 0, p_g = -1, p_str = (is_rev?(str_occ-1):(0)); k < a_n; k++) { - if(!is_rev) { - qstr_a = str+p_str; qstr_n = ((uint32_t)a[k].tn_rev_qk)+1-p_str; qoff = p_str + str_off; - } else { - qstr_a = str+poa_str_idx(((uint32_t)a[k].tn_rev_qk), str_occ, is_rev); - qstr_n = p_str+1-(poa_str_idx(((uint32_t)a[k].tn_rev_qk), str_occ, is_rev)); - qoff = poa_str_idx(((uint32_t)a[k].tn_rev_qk), str_occ, is_rev) + str_off; - } - // if(str_id == 47072) { - // fprintf(stderr, "+[M::%s::k->%ld] p_g::%ld, c_g::%u, p_str::%ld, c_str::%ld, str_off::%ld, qoff::%lu, qstr_n::%lu\n", - // __func__, k, p_g, gidx[a[k].tk], p_str, poa_str_idx(((uint32_t)a[k].tn_rev_qk), str_occ, is_rev), - // str_off, qoff, qstr_n); - // } - - append_integer_seq_frag(ug, raw, g, p_g, gidx[a[k].tk], qstr_a, qstr_n, is_rev, str_id, qoff); - - p_str = (uint32_t)a[k].tn_rev_qk; - if(is_rev) p_str = poa_str_idx(p_str, str_occ, is_rev); - p_g = gidx[a[k].tk]; - } - if(!is_rev) { - qstr_a = str+p_str; qstr_n = str_occ-p_str; qoff = p_str + str_off; - } else { - qstr_a = str; qstr_n = p_str+1; qoff = str_off; - } - append_integer_seq_frag(ug, raw, g, p_g, -1, qstr_a, qstr_n, is_rev, str_id, qoff); -} - - -uint32_t topo_srt_gen(poa_g_t *g, uint32_t debug_qid, ma_ug_t *ug) -{ - uint32_t k, v, w, a_n; poa_arc_t *a; - kv_resize(uint32_t, g->srt_b.ind, g->seq.n); - kv_resize(uint32_t, g->srt_b.stack, g->seq.n); - kv_resize(uint32_t, g->srt_b.res, g->seq.n); - kv_resize(uint32_t, g->srt_b.res2nid, g->seq.n); - // kv_resize(uint64_t, g->srt_b.aln, g->seq.n); g->srt_b.aln.n = 0; - g->srt_b.ind.n = g->srt_b.stack.n = g->srt_b.res.n = g->srt_b.res2nid.n = 0; - - for (k = 0; k < g->seq.n; k++) { - v = (k<<1) + 1; - g->srt_b.ind.a[k] = poa_arc_n(g, v); - if(g->srt_b.ind.a[k] == 0) kv_push(uint32_t, g->srt_b.stack, k); - } - - while (g->srt_b.stack.n > 0) { - v = g->srt_b.stack.a[--g->srt_b.stack.n]; kv_push(uint32_t, g->srt_b.res, v); v <<= 1; - a_n = poa_arc_n(g, v); a = poa_arc_a(g, v); - for (k = 0; k < a_n; k++) { - w = a[k].v>>1; - g->srt_b.ind.a[w]--; - if(g->srt_b.ind.a[w] == 0) kv_push(uint32_t, g->srt_b.stack, w); - } - } - // if(!(g->srt_b.res.n == g->seq.n)) { - // fprintf(stderr, "[M::%s::] debug_qid::%u, g->seq.n::%u, g->srt_b.res.n::%u\n", - // __func__, debug_qid, (uint32_t)g->seq.n, (uint32_t)g->srt_b.res.n); - // print_integer_g(g, ug, 1); - // for (k = 0; k < g->seq.n; k++) { - // if(g->srt_b.ind.a[k] > 0) fprintf(stderr, "circle->nid::%u\n", k); - // } - // } - if(g->srt_b.res.n != g->seq.n) return 0;///there is a circle - assert(g->srt_b.res.n == g->seq.n); - for (k = 0; k < g->seq.n; k++) { - g->srt_b.res2nid.a[g->srt_b.res.a[k]] = k; - // g->srt_b.aln.a[k] = g->seq.a[g->srt_b.res.a[k]].nid; - // g->srt_b.aln.a[k] <<= 32; g->srt_b.aln.a[k] += k; - } - // radix_sort_srt64(g->srt_b.aln.a, g->srt_b.aln.a + g->srt_b.aln.n); - return 1; -} - -void init_poa_dp(ma_ug_t *ug, poa_dp_t *dp, poa_g_t *g, uint64_t g_occ, uint64_t *str, uint64_t str_occ, uint64_t is_rev, uc_block_t *raw, integer_t *buf) -{ - kv_resize(uint8_t, dp->dir, (str_occ+1)*(g_occ+1)); - kv_resize(int64_t, dp->sc, (str_occ+1)*(g_occ+1)); - kv_resize(uint64_t, dp->prefix, (str_occ+1)*(g_occ+1)); - dp->n = str_occ+1; dp->m = g_occ+1; - kv_resize(uint64_t, buf->u, str_occ); - int64_t *sc = dp->sc.a, bsc, ss; uint8_t *dir = dp->dir.a; uint64_t k, l, *str_w = buf->u.a, *prefix = dp->prefix.a, m; - uc_block_t *z; uint32_t *g_idx = g->srt_b.res.a, *n2gidx = g->srt_b.res2nid.a, v, w, a_n, bsc_i; poa_arc_t *a; - for (k = 0; k < str_occ; k++) { - z = &(raw[str[k]>>32]); str_w[k] = ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); - } - - sc[poa_dp_idx(*dp, 0, 0)] = dir[poa_dp_idx(*dp, 0, 0)] = 0; - for (k = 1, l = 0; k < dp->n; k++) {///pat; new ul read - l += str_w[poa_str_idx(k-1, str_occ, is_rev)]; - sc[poa_dp_idx(*dp, k, 0)] = l; - dir[poa_dp_idx(*dp, k, 0)] = lstr_dp; - prefix[poa_dp_idx(*dp, k, 0)] = ((k - 1)<<32); - } - - for (k = 1; k < dp->m; k++) {///ref; graph - v = (g_idx[k-1]<<1) + 1; - a_n = poa_arc_n(g, v); a = poa_arc_a(g, v); - for (m = 0, bsc = bsc_i = 0; m < a_n; m++) { - w = n2gidx[a[m].v>>1]; assert(w+1 < k); - ss = sc[poa_dp_idx(*dp, 0, w+1)]; - if(ss < bsc || bsc_i == 0) { - bsc = ss; bsc_i = w + 1; - } - } - sc[poa_dp_idx(*dp, 0, k)] = bsc + g->seq.a[v>>1].occ; - dir[poa_dp_idx(*dp, 0, k)] = lref_dp; - prefix[poa_dp_idx(*dp, 0, k)] = bsc_i; - } -} - -uint32_t update_poa_dp(poa_g_t *g, uint32_t debug_qid, ma_ug_t *debug_ug) -{ - uint32_t is_srt = 0/**, is_up_aln = 0**/, k, is_circle = 0; - if(g->seq.n > g->update_seq || g->arc.n > g->update_arc) { - if(g->seq.n > g->update_seq) { - kv_resize(uint32_t, g->srt_b.res, g->seq.n); - kv_resize(uint32_t, g->srt_b.res2nid, g->seq.n); - // kv_resize(uint64_t, g->srt_b.aln, g->seq.n); g->srt_b.aln.n = g->seq.n; - g->srt_b.res.n = g->srt_b.res2nid.n = g->seq.n; - for (k = g->update_seq; k < g->seq.n; k++) { - g->srt_b.res.a[k] = g->srt_b.res2nid.a[k] = k; - // g->srt_b.aln.a[k] = (((uint64_t)(g->seq.a[k].nid))<<32)+k; - // if(k > 0 && is_up_aln == 0) { - // if((g->srt_b.aln.a[k]>>32) < (g->srt_b.aln.a[k-1]>>32)) is_up_aln = 1; - // } - } - } - if(g->arc.n > g->update_arc) { ///check if it is necessary to resort - for (k = g->update_arc; k < g->arc.n; k++) { - if((g->arc.a[k].ul>>32)&1) continue; - if(g->srt_b.res2nid.a[g->arc.a[k].ul>>33] >= g->srt_b.res2nid.a[g->arc.a[k].v>>1]) break; - } - if(k < g->arc.n) is_srt = 1; - } - // fprintf(stderr, "[M::%s::] is_srt::%u\n", __func__, is_srt); - clean_poa_g_t(g); - if(is_srt) { - is_circle = 1 - topo_srt_gen(g, debug_qid, debug_ug); - } - // else if(is_up_aln) { - // radix_sort_srt64(g->srt_b.aln.a, g->srt_b.aln.a + g->srt_b.aln.n); - // } - } - - return is_circle; -} - -/** -void poa_dp(poa_g_t *g, ma_ug_t *ug, uc_block_t *raw, ul_str_t *str, int64_t s, int64_t e, int64_t is_rev, integer_t *buf) -{ - if(e <= s) return; - - - - uint32_t *g_idx = g->srt_b.res.a, *n2gidx = g->srt_b.res2nid.a, gnid, v, a_n, pat_v, g_v; - uint64_t *pat = (is_rev?(str->a + str->cn - e):(str->a + s)), pat_n = e - s, pp; - init_poa_dp(ug, &(g->dp), g, g->seq.n, pat, pat_n, is_rev, raw, buf); - int64_t *sc = g->dp.sc.a, min_w, c_w; uint8_t *dir = g->dp.dir.a; - uint64_t *str_w = buf->u.a, *prefix = g->dp.prefix.a; - poa_arc_t *a; poa_dp_t *dp = &(g->dp); - int64_t min_i, min_k, min_d, i, k, n = g->dp.n - 1, m = g->dp.m - 1, match_sc, z, pidx, g_k, pat_k; - fprintf(stderr, "[M::%s::] ts::%ld, te::%ld, is_rev::%ld, m::%ld(g->seq.n::%u), n::%ld(pat_n::%lu)\n", - __func__, s, e, is_rev, m, (uint32_t)g->seq.n, n, pat_n); - for (i = 0; i < m; i++) {///graph - gnid = g_idx[i]; v = (gnid<<1) + 1; g_v = g->seq.a[gnid].nid; - a_n = poa_arc_n(g, v); a = poa_arc_a(g, v); - for (k = 0; k < n; k++) {//read - pat_v = (uint32_t)pat[poa_str_idx(k, pat_n, is_rev)]; if(is_rev) pat_v ^= 1; - if(g_v == pat_v) { - match_sc = str_w[poa_str_idx(k, pat_n, is_rev)]; match_sc *= -1; - } else { - match_sc = str_w[poa_str_idx(k, pat_n, is_rev)]; - if(match_sc < g->seq.a[gnid].occ) match_sc = g->seq.a[gnid].occ; - } - - ///longer graph/shorter read - min_w = sc[poa_dp_idx(*dp, k, i+1)] + g->seq.a[gnid].occ; - min_i = i + 1; min_k = k; min_d = lg_dp; - - for (z = 0; z < a_n; z++) { - pidx = n2gidx[a[z].v>>1]; assert(pidx < i); - ///match - c_w = sc[poa_dp_idx(*dp, k, pidx+1)] + match_sc; - if(c_w < min_w) { - min_w = c_w; min_i = pidx+1; min_k = k; - if(match_sc <= 0) min_d = e_pdp; - else min_d = ue_pdp; - } - ///longer read/shorter graph - c_w = sc[poa_dp_idx(*dp, k+1, pidx+1)] + str_w[poa_str_idx(k, pat_n, is_rev)]; - if(c_w < min_w) { - min_w = c_w; min_i = pidx+1; min_k = k + 1; min_d = lstr_dp; - } - } - - if(a_n == 0) {///no prefix - pidx = -1; - ///match - c_w = sc[poa_dp_idx(*dp, k, pidx+1)] + match_sc; - if(c_w < min_w) { - min_w = c_w; min_i = pidx+1; min_k = k; - if(match_sc <= 0) min_d = e_pdp; - else min_d = ue_pdp; - } - ///longer read/shorter graph - c_w = sc[poa_dp_idx(*dp, k+1, pidx+1)] + str_w[poa_str_idx(k, pat_n, is_rev)]; - if(c_w < min_w) { - min_w = c_w; min_i = pidx+1; min_k = k + 1; min_d = lstr_dp; - } - } - - sc[poa_dp_idx(*dp, k+1, i+1)] = min_w; dir[poa_dp_idx(*dp, k+1, i+1)] = min_d; - prefix[poa_dp_idx(*dp, k+1, i+1)] = (((uint64_t)min_k)<<32)|((uint64_t)min_i); - fprintf(stderr, "[M::%s::] i::%ld(graph->utg%.6d%c, min_i->%ld), k::%ld(str->utg%.6d%c, min_k->%ld), match_sc::%ld, min_w::%ld, min_d::%ld\n", - __func__, i+1, (int32_t)(g_v>>1)+1, "lc"[ug->u.a[g_v>>1].circ], min_i, - k+1, (int32_t)(pat_v>>1)+1, "lc"[ug->u.a[pat_v>>1].circ], min_k, match_sc, min_w, min_d); - } - } - - ///backtrack; global alignment - min_i = -1; min_k = n; min_w = 0; - for (i = 0; i < m; i++) {///go through graph - // gnid = g_idx[i]; v = (gnid<<1); - // if(poa_arc_n(g, v) > 0) continue; - c_w = sc[poa_dp_idx(*dp, min_k, i+1)]; - if(min_i < 0 || c_w < min_w) { - min_w = c_w; min_i = i+1; - } - } - assert(min_i > 0); - - g->srt_b.ind.n = g->srt_b.stack.n = 0; - while (min_i > 0 || min_k > 0) { - pat_k = poa_str_idx((min_k-1), pat_n, is_rev);///read - g_k = g_idx[min_i-1];///graph - fprintf(stderr, "******[M::%s::] min_i::%ld(gid->%ld, m->%ld), min_k::%ld(str_id->%ld, n->%ld), dir::%u, sc::%ld\n", - __func__, min_i, g_k, m, min_k, pat_k, n, - dir[poa_dp_idx(*dp, min_k, min_i)], sc[poa_dp_idx(*dp, min_k, min_i)]); - if(dir[poa_dp_idx(*dp, min_k, min_i)] == e_pdp) { - assert(g->seq.a[g_k].nid == (((uint32_t)pat[pat_k])^(is_rev?1:0))); - kv_push(uint32_t, g->srt_b.ind, pat_k); ///read - kv_push(uint32_t, g->srt_b.stack, g_k); ///graph - } - pp = prefix[poa_dp_idx(*dp, min_k, min_i)]; - assert((int64_t)(pp>>32)<=min_k); assert((int64_t)((uint32_t)pp)<=min_i); - min_k = pp >> 32; min_i = (uint32_t)pp; - } - if(!(g->srt_b.ind.n > 0 && g->srt_b.ind.n == g->srt_b.stack.n)) { - fprintf(stderr, "[M::%s::] g->srt_b.ind.n::%u, g->srt_b.stack.n::%u, ts::%ld, te::%ld\n", - __func__, (uint32_t)g->srt_b.ind.n, (uint32_t)g->srt_b.stack.n, s, e); - } - assert(g->srt_b.ind.n > 0 && g->srt_b.ind.n == g->srt_b.stack.n); - append_aligned_integer_seq(ug, raw, g, g->seq.n, pat, pat_n, is_rev, g->srt_b.stack.a, g->srt_b.ind.a, g->srt_b.ind.n); - update_poa_dp(g); -} - - -void poa_cns_dp(poa_g_t *g, all_ul_t *ul_idx, ma_ug_t *ug, ul_str_t *str, integer_aln_t *aln, -ul_chain_t *idx, int64_t idx_n, int64_t qid, integer_t *buf) -{ - int64_t k, tid, is_rev; - reset_poa_g_t(g); - - append_unmatch_integer_seq(g, ug, ul_idx->a[qid].bb.a, &(str[qid]), 0, str[qid].cn, 0, qid, 0); - clean_poa_g_t(g); topo_srt_gen(g); - - for (k = 0; k < idx_n; k++) { - tid = aln[idx[k].s].tn_rev_qk>>33; is_rev = ((aln[idx[k].s].tn_rev_qk>>32)&1); - fprintf(stderr, "\n[M::%s::] k::%ld, tid::%ld, is_rev::%ld\n", __func__, k, tid, is_rev); - print_integer_seq(ug, str, tid, 1); - poa_dp(g, ug, ul_idx->a[tid].bb.a, &(str[tid]), idx[k].t_sidx, idx[k].t_eidx, is_rev, buf); - } - - gen_cns_by_poa(g); -} -**/ - -int64_t suffix_gorder_check(poa_g_t *g, integer_t *buf, uint64_t gk_0, uint64_t gk_1, int64_t update_vis, uint64_t set_flag) -{ - uint32_t *g_idx = g->srt_b.res.a, *n2gidx = g->srt_b.res2nid.a, a_n, v, init_n, k; - poa_arc_t *a; - if(buf->vis.n != g->seq.n) { - kv_resize(uint32_t, buf->vis, g->seq.n); buf->vis.n = g->seq.n; - memset(buf->vis.a, -1, sizeof((*buf->vis.a))*buf->vis.n); - } - - if(update_vis) { - v = g_idx[gk_0]<<1; init_n = buf->vis.n; - kv_push(uint32_t, buf->vis, v); - while (buf->vis.n > init_n) { - v = buf->vis.a[--buf->vis.n]; - buf->vis.a[n2gidx[v>>1]] = set_flag; - a_n = poa_arc_n(g, v); a = poa_arc_a(g, v); - for (k = 0; k < a_n; k++) { - if(buf->vis.a[n2gidx[a[k].v>>1]] == set_flag) continue; - kv_push(uint32_t, buf->vis, a[k].v); - } - } - assert(buf->vis.n == init_n); - } - - if(buf->vis.a[gk_1] == set_flag) return 1; - return 0; -} - -int64_t integer_g_chain(poa_g_t *g, ma_ug_t *ug, integer_aln_t *a, int64_t a_n, integer_t *buf, ul_chain_t *res) -{ - res->v = res->s = res->e = (uint32_t)-1; res->sc = (uint64_t)-1; - res->q_sidx = res->q_eidx = res->t_sidx = res->t_eidx = (uint32_t)-1; - if(a_n <= 0) return 0; - int64_t i, k, *p, *f, tf, ti, csc, sc, max_f, max_k, vis_i, pas; integer_aln_t *li, *lk; - buf->vis.n = 0; vis_i = -1; - for (i = 1; i < a_n; ++i) {//already sorted by qk - if(((uint32_t)a[i].tn_rev_qk) <= ((uint32_t)a[i-1].tn_rev_qk)) break; ///== means there is a circle - if(a[i].tk == a[i-1].tk) break; - if(a[i].tk < a[i-1].tk) { - pas = suffix_gorder_check(g, buf, a[i].tk, a[i-1].tk, vis_i==i?0:1, i); vis_i = i; - if(pas) break; - } - } - // fprintf(stderr, "[M::%s::] i::%ld, a_n::%ld\n", __func__, i, a_n); - - if(i >= a_n) { - res->s = 0; res->e = a_n; - return 1; - } - - buf->p.n = buf->f.n = 0; - kv_resize(int64_t, buf->p, (uint64_t)a_n); p = buf->p.a; - kv_resize(int64_t, buf->f, (uint64_t)a_n); f = buf->f.a; - - tf = ti = -1; buf->vis.n = 0; vis_i = -1; - for (i = 0; i < a_n; ++i) { - li = &(a[i]); csc = li->sc; - max_f = csc; max_k = -1; - - for (k = i-1; k >= 0; --k) { - lk = &(a[k]); - ///qk of lk and li might be equal - if(((uint32_t)lk->tn_rev_qk) >= ((uint32_t)li->tn_rev_qk)) continue; - if(lk->tk == li->tk) continue; - if(lk->tk > li->tk) { - pas = suffix_gorder_check(g, buf, a[i].tk, a[k].tk, vis_i==i?0:1, i); - // if(i == 17 && a[i].tk == 6 && k == 16 && a[k].tk == 60) { - // fprintf(stderr, "******i::%ld, a[i].tk::%u, k::%ld, a[k].tk::%u, vis_i::%ld, pas::%ld\n", - // i, a[i].tk, k, a[k].tk, vis_i, pas); - // } - vis_i = i; if(pas) continue; - } - sc = csc + f[k]; - if(sc > max_f) { - max_f = sc; max_k = k; - } - } - f[i] = max_f; p[i] = max_k; - if(tf < max_f) { - tf = max_f; ti = i; - } - // fprintf(stderr, "[M::%s::i->%ld] qk::%u, tk::%u, max_k::%ld, max_f::%ld, ti::%ld\n", - // __func__, i, (uint32_t)li->tn_rev_qk, li->tk, max_k, max_f, ti); - } - - if(ti < 0) return 0; - for (i = ti, k = 0; i >= 0; i = p[i]) f[k++] = i; - assert(k > 0); - for (i = 0, k--; k >= 0; k--) { - a[i] = a[f[k]]; i++; - } - res->s = 0; res->e = i; - return 1; -} - - -void poa_chain_0(poa_g_t *g, ma_ug_t *ug, uc_block_t *raw, ul_str_t *str, int64_t s, int64_t e, int64_t is_rev, integer_t *buf, int64_t str_id, int64_t debug_qid, uint32_t *is_circle) -{ - (*is_circle) = 0; - if(e <= s) return; - uint32_t *g_idx = g->srt_b.res.a; uc_block_t *z; integer_aln_t *b; ul_chain_t rr; int64_t i, k, n; - uint64_t *pat = (is_rev?(str->a + str->cn - e):(str->a + s)), pp; int64_t pat_n = e - s; - // fprintf(stderr, "[M::%s::] ts::%ld, te::%ld, is_rev::%ld, g->seq.n::%u, pat_n::%lu\n", - // __func__, s, e, is_rev, (uint32_t)g->seq.n, pat_n); - - g->srt_b.aln.n = 0; n = g->seq.n; - for (k = 0; k < n; k++) {///graph - pp = (((uint64_t)(g->seq.a[g_idx[k]].nid))<<32); pp += ((uint64_t)(k)); pp += ((uint64_t)(0x80000000)); - kv_push(uint64_t, g->srt_b.aln, pp); - } - for (k = 0; k < pat_n; k++) { - pp = (uint32_t)pat[poa_str_idx(k, pat_n, is_rev)]; if(is_rev) pp ^= 1; pp <<= 32; pp += ((uint64_t)(k)); - kv_push(uint64_t, g->srt_b.aln, pp); - } - - radix_sort_srt64(g->srt_b.aln.a, g->srt_b.aln.a + g->srt_b.aln.n); n = g->srt_b.aln.n; - for (k = 0, buf->b.n = 0; k < n; k++) { - if(g->srt_b.aln.a[k]&((uint64_t)(0x80000000))) continue;///skip nodes in the graph - for (i = k+1; (i < n) && ((g->srt_b.aln.a[k]>>32) == (g->srt_b.aln.a[i]>>32)); i++) { - if((g->srt_b.aln.a[i]&((uint64_t)(0x80000000))) == 0) continue;///skip nodes in the read - ///a[k] is read (q); a[i] is graph (t) - kv_pushp(integer_aln_t, buf->b, &b); - b->vq = g->srt_b.aln.a[k]>>32; - b->tn_rev_qk = (uint32_t)g->srt_b.aln.a[k]; - b->tk = ((g->srt_b.aln.a[i]<<33)>>33); - z = &(raw[pat[poa_str_idx(b->tn_rev_qk, pat_n, is_rev)]>>32]); - b->sc = ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); - } - } - - n = buf->b.n; - radix_sort_integer_aln_t_srt(buf->b.a, buf->b.a + buf->b.n); ///sorted by qk - // fprintf(stderr, "[M::%s::] # align pairs::%ld\n", __func__, n); - - // for (i = 0; i < n; i++) {///sort score - // b = &(buf->b.a[i]); z = &(raw[pat[poa_str_idx(b->tn_rev_qk, pat_n, is_rev)]>>32]); - // pp = ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); - // b->tn_rev_qk += (pp<<32); - // } - - - i = integer_g_chain(g, ug, buf->b.a, buf->b.n, buf, &rr); assert(i); - if(!i) return; buf->b.n = rr.e; assert(buf->b.n); - append_aligned_integer_seq_by_aln_pair(ug, raw, g, g->seq.n, pat, pat_n, is_rev, buf->b.a, buf->b.n, str_id, (is_rev?(str->cn - e):(s))); - (*is_circle) = update_poa_dp(g, debug_qid, ug); -} - -void gen_cns_by_poa(poa_g_t *g) -{ - uint32_t n_vx = g->seq.n<<1, i, k, v, nv, w; uint64_t c, cc, n_pending = 0; - ubuf_t *b = &(g->bb); poa_arc_t *av; uinfo_t *t; - b->a.n = b->S.n = b->T.n = b->b.n = b->e.n = 0; - kv_resize(uinfo_t, b->a, n_vx); b->a.n = n_vx; memset(b->a.a, 0, sizeof(*(b->a.a))*b->a.n); - for (k = 0; k < g->seq.n; k++) { - v = (k<<1) + 1; - if(poa_arc_n(g, v)) continue; - v ^= 1; kv_push(uint32_t, b->S, v); b->a.a[v].p = (uint32_t)-1; - } - assert(b->S.n); - while (b->S.n > 0) { - v = kv_pop(b->S); c = b->a.a[v].c; - nv = poa_arc_n(g, v); av = poa_arc_a(g, v); - for (i = 0; i < nv; ++i) { - w = av[i].v; t = &b->a.a[w]; - kv_push(uint32_t, b->e, ((g->idx.a[v]>>32)+i)); ///push the edge - cc = c + (uint32_t)av[i].ul; - if (t->s == 0) {///a new node - kv_push(uint32_t, b->b, w); // save it for revert - t->p = v; t->s = 1; //t->d = d + l; - t->r = poa_arc_n(g, w^1); t->c = cc; ///t->nc = c_nc; - ++n_pending; - } else { - if(cc > t->c) { - t->p = v; t->c = cc; //t->s = 1; t->d = d + l; t->nc = c_nc; - } - } - - if (--(t->r) == 0) { - if(poa_arc_n(g, w) > 0) kv_push(uint32_t, b->S, w); - --n_pending; - // if(w == dest && n_pending == 0) goto pp_end; - } - } - } - assert(!n_pending); - uint64_t m = 0, mi = (uint64_t)-1; - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - t = &b->a.a[b->b.a[i]]; ///memset(t, 0, sizeof(*(t))); - //b->srt.a[i].c = ((uint64_t)-1) - t->c; b->srt.a[i].i = i; - if(m < t->c) { - m = t->c; mi = i; ///b->b.a[i]; - } - } - - if(mi != (uint64_t)-1) { - g->srt_b.res.n = 0; - for(v = b->b.a[mi]; v != (uint32_t)-1; v = b->a.a[v].p) { - kv_push(uint32_t, g->srt_b.res, v); - } - m = g->srt_b.res.n>>1; - for (i = 0; i < m; i++) { - v = g->srt_b.res.a[i]; - g->srt_b.res.a[i] = g->srt_b.res.a[g->srt_b.res.n-i-1]; - g->srt_b.res.a[g->srt_b.res.n-i-1] = v; - } - } - - // for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - // t = &b->a.a[b->b.a[i]]; memset(t, 0, sizeof(*(t))); - // } -} - -void poa_cns_chain(poa_g_t *g, all_ul_t *ul_idx, ma_ug_t *ug, ul_str_t *str, ul_chain_t *idx, int64_t idx_n, int64_t qid, integer_t *buf, uint32_t *is_circle) -{ - (*is_circle) = 0; - int64_t k, tid, is_rev; - reset_poa_g_t(g); - - append_unmatch_integer_seq(g, ug, ul_idx->a[qid].bb.a, &(str[qid]), 0, str[qid].cn, 0, qid); - clean_poa_g_t(g); (*is_circle) = 1 - topo_srt_gen(g, qid, ug); - if((*is_circle)) return; - - for (k = 0; k < idx_n; k++) { - tid = idx[k].v>>1; is_rev = idx[k].v&1; - // fprintf(stderr, "\n[M::%s::] k::%ld, tid::%ld, is_rev::%ld\n", __func__, k, tid, is_rev); - // print_integer_seq(ug, str, tid, 1); - poa_chain_0(g, ug, ul_idx->a[tid].bb.a, &(str[tid]), idx[k].t_sidx, idx[k].t_eidx, is_rev, buf, tid, qid, is_circle); - if((*is_circle)) return; - // print_integer_g(g, ug, 1); - } - - gen_cns_by_poa(g); -} - -uint64_t cal_forward_dis(asg_t *g, uc_block_t *a, uint32_t s, uint32_t e) -{ - uint32_t i, v, w, nv, z; int64_t l; asg_arc_t *av; - //fprintf(stderr, "\n[M::%s::] s::%u, e::%u\n", __func__, s, e); - ///TODO: a[i].aidx might be < i; if s == e, then i <= e might be wrong, cannot pass the assert(li == e); - for(i = s, l = 0, v = w = (uint32_t)-1; i != (uint32_t)-1 && i != e; i = a[i].aidx) { - w = (((uint32_t)(a[i].hid))<<1)|((uint32_t)(a[i].rev)); - if(v != (uint32_t)-1) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (z = 0; z < nv; z++) { - if(av[z].del) continue; - if(av[z].v == w) break; - } - if(z < nv) {//found - l += (uint32_t)av[z].ul; - } else { - l += a[i].pdis + g->seq[v>>1].len - g->seq[w>>1].len; - } - } - v = w; - // fprintf(stderr, "[M::%s::] i::%u, a[i].aidx::%u, a[i].qs::%u, a[i].qe::%u\n", __func__, i, a[i].aidx, a[i].qs, a[i].qe); - } - - - assert(i == e); - w = (((uint32_t)(a[i].hid))<<1)|((uint32_t)(a[i].rev)); - if(v != (uint32_t)-1) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (z = 0; z < nv; z++) { - if(av[z].del) continue; - if(av[z].v == w) break; - } - if(z < nv) {//found - l += (uint32_t)av[z].ul; - } else { - l += a[i].pdis + g->seq[v>>1].len - g->seq[w>>1].len; - } - } - v = w; - - - if(l < 0) l = 0; - return l; -} - -uint64_t cal_integer_match_dis(ma_ug_t *ug, uc_block_t *a, int64_t k_0, int64_t k_1, int64_t is_rev, uint32_t *is_g_connect) -{ - uint32_t i, k; - assert((is_rev && k_1 < k_0) || ((!is_rev) && k_1 > k_0)); (*is_g_connect) = 0; - if(is_rev) { - i = k_0; k = k_1; - } else { - i = k_1; k = k_0; - } - // fprintf(stderr, "k_0::%ld, k_1::%ld\n", k_0, k_1); - uint32_t li, lk, pk, bi = i; int64_t l; - for (li = i, l = 0; i != (uint32_t)-1 && i >= k; i = a[i].pidx) { - li = i; if(a[i].pidx != (uint32_t)-1 && i > k) l += a[i].pdis; - } - // fprintf(stderr, "+bi::%u, li::%u, i::%u, l::%ld\n", bi, li, i, l); - if(is_rev) l = cal_forward_dis(ug->g, a, li, bi); - // fprintf(stderr, "++bi::%u, li::%u, i::%u, l::%ld\n", bi, li, i, l); - if(li == k) {///direct path - (*is_g_connect) = 1; - return l; - } - i = li; - assert(i > k); pk = k; - for (lk = k; k != (uint32_t)-1 && k <= i; k = a[k].aidx) lk = k; - // fprintf(stderr, "-pk::%u, lk::%u, k::%u\n", pk, lk, k); - if(!is_rev) { - for (k = lk; k != (uint32_t)-1 && k != pk; k = a[k].pidx) l += a[k].pdis; - } else { - l += cal_forward_dis(ug->g, a, pk, lk); - } - // fprintf(stderr, "--pk::%u, lk::%u, k::%u, l::%ld\n", pk, lk, k, l); - if(l < 0) l = 0; - k = lk; - assert(i > k); - return l + normlize_gdis(ug, &(a[i]), &(a[k]), is_rev); -} - -uint64_t cal_integer_most_dis(uint32_t qid, uint64_t *a, uint64_t a_n, double cluster_rate) -{ - if(a_n <= 0) return (uint64_t)-1; - // fprintf(stderr, "\n[M::%s::] a_n::%lu\n", __func__, a_n); - uint64_t k, l, i, m, r_an = a_n, max_m, max_i, cc, cd, nd; int64_t z; - for (k = 1, l = m = max_m = 0, max_i = (uint64_t)-1; k <= a_n; k++) { - a[k-1] <<= 1; a[k-1] >>= 1; - // fprintf(stderr, "[k->%lu] d::%lu, rev::%lu\n", k-1, a[k-1]>>1, a[k-1]&1); - if((k == a_n) || (((a[k]&((uint64_t)(0x7fffffffffffffff)))>>1) - != ((a[l]&((uint64_t)(0x7fffffffffffffff)))>>1))) { - for (i = l; i < k; i++) { - if(!(a[i]&1)) break; - } - a[m] = a[l]; a[m] >>= 1; a[m] <<= 1; - ///if all integer sequence are mapped reversely - if(i >= k) a[m] += 1; - a[m] |= ((uint64_t)(k-l))<<32; - if((k-l) > max_m) { - max_m = k - l; max_i = m; - } else if((k-l) == max_m && i < k) {///i < k means this distance is supported by forward sequences - max_m = k - l; max_i = m; - } - l = k; m++; - } - } - a_n = m; assert(a_n > 0); - // fprintf(stderr, "[M::%s::] m::%lu\n", __func__, m); - if(max_m > 0 && max_m > (r_an>>1)) { - // fprintf(stderr, "[M::%s::] dis::%u\n", __func__, ((uint32_t)a[max_i])>>1); - return ((uint32_t)a[max_i])>>1; - } - - for (k = 0, max_m = 0, max_i = (uint64_t)-1; k < a_n; k++) { - cd = (((uint32_t)a[k])>>1); z = k; - // fprintf(stderr, "[mk->%lu] cd::%lu\n", k, cd); - for (cc = cd, z--; z >= 0; z--) { - nd = (((uint32_t)a[z])>>1); assert(nd < cd); - if(((cd-nd) > (nd*cluster_rate)) && ((cd-nd) > 512)) break; - cc += (a[z]>>32); - } - for (i = k+1; i < a_n; i++) { - nd = (((uint32_t)a[i])>>1); - // if(!(nd > cd)) { - // fprintf(stderr, "[M::%s::] qid::%u, a_n::%lu, i::%lu, k::%lu, cd::%lu, nd::%lu\n", - // __func__, qid, a_n, i, k, cd, nd); - // } - assert(nd > cd); - if(((nd-cd) > (nd*cluster_rate)) && ((nd-cd) > 512)) break; - cc += (a[i]>>32); - } - - if(cc > max_m) { - max_m = cc; max_i = k; - } else if(cc == max_m && (!(a[k]&1))) {///means this distance is supported by forward sequences - max_m = cc; max_i = k; - } - } - - k = max_i; - cd = (((uint32_t)a[k])>>1); z = k; - for (max_m = cd, max_i = k, z--; z >= 0; z--) { - nd = (((uint32_t)a[z])>>1); assert(nd < cd); - if(((cd-nd) > (nd*cluster_rate)) && ((cd-nd) > 512)) break; - cc = (a[z]>>32); - if(cc > max_m) { - max_m = cc; max_i = z; - } else if(cc == max_m && (!(a[z]&1))) {///means this distance is supported by forward sequences - max_m = cc; max_i = z; - } - } - for (i = k+1; i < a_n; i++) { - nd = (((uint32_t)a[i])>>1); assert(nd > cd); - if(((nd-cd) > (nd*cluster_rate)) && ((nd-cd) > 512)) break; - cc = (a[i]>>32); - if(cc > max_m) { - max_m = cc; max_i = i; - } else if(cc == max_m && (!(a[i]&1))) {///means this distance is supported by forward sequences - max_m = cc; max_i = i; - } - } - - // fprintf(stderr, "[M::%s::] dis::%u\n", __func__, ((uint32_t)a[max_i])>>1); - return ((uint32_t)a[max_i])>>1; -} - -uint32_t poa_g_arc_w(poa_g_t *pg, uint32_t v, uint32_t w) -{ - poa_arc_t *av; uint32_t an, k; - an = poa_arc_n(pg, v); av = poa_arc_a(pg, v); - for (k = 0; k < an; k++) { - if(av[k].v == w) return (uint32_t)av[k].ul; - } - return 0; -} - -void dump_cns_res(poa_g_t *pg, ma_ug_t *ug, uint32_t *cns_seq, uint32_t cns_occ, all_ul_t *ul_idx, ul_str_t *str, uint32_t qid, integer_t *buf, -uint64_t *arc_idx, uint64_t arc_idx_n) -{ - uint64_t t, dd, k, i; uint32_t e_s, e_e, is_rev, is_g_connect, con_occ; emap_t *g_arc; - if(cns_occ > 0) { - t = qid; t <<= 32; t |= ((uint64_t)(0xffffffff)); - kv_push(uint64_t, buf->res_dump, t); - - t = pg->seq.a[cns_seq[0]>>1].nid; - // t = pg->seq.a[cns_seq[0]>>1].nid; t |= ((uint64_t)(0xffffffff00000000)); - t |= ((uint64_t)(ug->g->seq[pg->seq.a[cns_seq[0]>>1].nid>>1].len))<<32; - kv_push(uint64_t, buf->res_dump, t); - buf->n_correct++; - } - for (k = 0; k < arc_idx_n; k++) { - // csn_v = pg->seq.a[cns_seq[k]>>1].nid; cns_w = pg->seq.a[cns_seq[k+1]>>1].nid; - e_s = arc_idx[k]>>32; e_e = (uint32_t)arc_idx[k]; - // fprintf(stderr, "[M::%s::] k::%lu, arc_idx_n::%lu, e_s::%u, e_e::%u\n", __func__, k, arc_idx_n, e_s, e_e); - assert(poa_g_arc_w(pg, cns_seq[k], cns_seq[k+1]) == (e_e - e_s)); assert(e_e > e_s); - buf->o.n = 0; kv_resize(uint64_t, buf->o, e_e - e_s); con_occ = 0; - for (i = e_s; i < e_e; i++) { - g_arc = &(pg->e_idx.a[i]); - assert((g_arc->pge>>32) == (cns_seq[k]>>1) && ((uint32_t)g_arc->pge) == (cns_seq[k+1]>>1)); - is_rev = ((g_arc->ule>>32) > ((uint32_t)g_arc->ule)?1:0); - assert((pg->seq.a[g_arc->pge>>32].nid^(is_rev?1:0)) == ((uint32_t)str[g_arc->ulid].a[g_arc->ule>>32])); - assert((pg->seq.a[(uint32_t)g_arc->pge].nid^(is_rev?1:0)) == ((uint32_t)str[g_arc->ulid].a[(uint32_t)g_arc->ule])); - // fprintf(stderr, "+++i::%lu, target_ulid::%u, str_sidx::%u, str_eidx::%u, str_cn::%u, ul_idx->a[g_arc->ulid].bb.n::%u\n", - // i - e_s, g_arc->ulid, (uint32_t)(g_arc->ule>>32), (uint32_t)g_arc->ule, str[g_arc->ulid].cn, (uint32_t)ul_idx->a[g_arc->ulid].bb.n); - dd = cal_integer_match_dis(ug, ul_idx->a[g_arc->ulid].bb.a, str[g_arc->ulid].a[g_arc->ule>>32]>>32, - str[g_arc->ulid].a[(uint32_t)g_arc->ule]>>32, is_rev, &is_g_connect); - // fprintf(stderr, "---i::%lu, dd::%lu, is_g_connect::%u\n", i - e_s, dd, is_g_connect); - dd <<= 1; if(is_rev) dd += 1; - if(is_g_connect) { - con_occ++; buf->o.a[buf->o.n] = dd; - } else { - buf->o.a[buf->o.n] = dd; buf->o.a[buf->o.n] |= ((uint64_t)(0x8000000000000000)); - } - buf->o.n++; - } - - radix_sort_srt64(buf->o.a, buf->o.a + buf->o.n); - if(con_occ > 0) buf->o.n = con_occ; - dd = cal_integer_most_dis(qid, buf->o.a, buf->o.n, 0.08); - - - t = pg->seq.a[cns_seq[k+1]>>1].nid; t |= ((uint64_t)(dd<<32)); - if(con_occ > 0) t |= ((uint64_t)(0x8000000000000000)); - kv_push(uint64_t, buf->res_dump, t); - } - -} - -void update_raw_integer_seq(poa_g_t *pg, ma_ug_t *ug, uint32_t *cns_seq, uint32_t cns_occ, all_ul_t *ul_idx, ul_str_t *str, uint32_t qid, integer_t *buf, ul_chain_t *idx_a, uint64_t idx_n) -{ - if(cns_occ <= 0) return; - ///no need to check edges if there is just one node -> no dege - if(cns_occ > 1) radix_sort_emap_t_srt(pg->e_idx.a, pg->e_idx.a + pg->e_idx.n); - kv_resize(uint64_t, buf->u, cns_occ); buf->u.n = cns_occ - 1; memset(buf->u.a, 0, sizeof(*(buf->u.a)*buf->u.n)); - uint64_t *arc_idx = buf->u.a, arc_idx_n = buf->u.n, x; uint64_t k, l, i, n = pg->e_idx.n, fe = cns_occ - 1; - for (k = 1, l = 0; k <= n && fe > 0; k++) { - if(k == n || pg->e_idx.a[k].pge != pg->e_idx.a[l].pge) { - if(k > l) { - for (i = 0; i < arc_idx_n; i++) { - x = (cns_seq[i]>>1); x <<= 32; x += (cns_seq[i+1]>>1); - if(x == pg->e_idx.a[l].pge) { - arc_idx[i] = l; arc_idx[i] <<= 32; arc_idx[i] += k; fe--; - break; - } - } - } - l = k; - } - } - assert(fe == 0); - // for (k = 0; k < pg->e_idx.n; k++) { - // assert((pg->seq.a[pg->e_idx.a[k].pge>>32].nid>>1) == - // (((uint32_t)str[pg->e_idx.a[k].ulid].a[pg->e_idx.a[k].ule>>32])>>1)); - // assert((pg->seq.a[(uint32_t)pg->e_idx.a[k].pge].nid>>1) == - // (((uint32_t)str[pg->e_idx.a[k].ulid].a[(uint32_t)pg->e_idx.a[k].ule])>>1)); - // assert(((pg->seq.a[pg->e_idx.a[k].pge>>32].nid&1)^(((uint32_t)str[pg->e_idx.a[k].ulid].a[pg->e_idx.a[k].ule>>32])&1)) == - // ((pg->seq.a[(uint32_t)pg->e_idx.a[k].pge].nid&1)^(((uint32_t)str[pg->e_idx.a[k].ulid].a[(uint32_t)pg->e_idx.a[k].ule])&1))); - // } - - uint32_t e_s, e_e; emap_t *g_arc; uint64_t l_clip = 0, r_clip = 0; int64_t e_occ; - if(arc_idx_n > 0) { - ///clip unreliable left/right end - for (l_clip = 0; l_clip < arc_idx_n; l_clip++) { - k = l_clip; - e_s = arc_idx[k]>>32; e_e = (uint32_t)arc_idx[k]; - assert(poa_g_arc_w(pg, cns_seq[k], cns_seq[k+1]) == (e_e - e_s)); - e_occ = ((int64_t)e_e) - ((int64_t)e_s); - if(e_occ > 1) break;///more than one read supporting this edge - for (i = e_s; i < e_e; i++) { - g_arc = &(pg->e_idx.a[i]); - if(g_arc->ulid == qid) break; - } - if(i < e_e) break;///the query read itself supports this edge - } - - for (r_clip = 0; r_clip < arc_idx_n; r_clip++) { - k = arc_idx_n - r_clip - 1; - e_s = arc_idx[k]>>32; e_e = (uint32_t)arc_idx[k]; - assert(poa_g_arc_w(pg, cns_seq[k], cns_seq[k+1]) == (e_e - e_s)); - e_occ = ((int64_t)e_e) - ((int64_t)e_s); - if(e_occ > 1) break;///more than one read supporting this edge - for (i = e_s; i < e_e; i++) { - g_arc = &(pg->e_idx.a[i]); - if(g_arc->ulid == qid) break; - } - if(i < e_e) break;///the query read itself supports this edge - } - } - if(l_clip+r_clip >= cns_occ) return; - dump_cns_res(pg, ug, cns_seq+l_clip, cns_occ-l_clip-r_clip, ul_idx, str, qid, buf, arc_idx+l_clip, arc_idx_n-l_clip-r_clip); -} - -void integer_candidate(ul_resolve_t *uidx, integer_t *buf, uint32_t qid, uint32_t is_hom) -{ - uint64_t k, z, m_het, m_het_occ, ref_occ, b_n, m; uint32_t vk, vz, is_circle = 0; integer_aln_t *p; ul_chain_t sc; - ul_str_idx_t *str_idx = &(uidx->pstr); ma_ug_t *ug = uidx->l1_ug; - uint64_t *hid_a, hid_n; uc_block_t *xi; - ul_str_t *str = &(str_idx->str.a[qid]); - if(str->cn < 2) return; ///directly filter out too short UL - kv_resize(uint64_t, buf->u, str->cn); buf->u.n = str->cn; - for (k = m_het = m_het_occ = ref_occ = 0; k < str->cn; k++) { - xi = &(uidx->idx->a[qid].bb.a[str->a[k]>>32]); - assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[k])); - buf->u.a[k] = ug_occ_w(xi->ts, xi->te, &(ug->u.a[xi->hid])); - assert(buf->u.a[k] > 0); - if((!is_hom) && (!IF_HOM((((uint32_t)str->a[k])>>1), (*uidx->bub)))) { - m_het++; m_het_occ += buf->u.a[k];///m_het_occ: how many het HiFi reads - } - ref_occ += buf->u.a[k]; - // fprintf(stderr, "[M::%s::k->%lu] buf->u.a[k]->%lu, ts->%u, te->%u, pchain->%u\n", __func__, k, buf->u.a[k], xi->ts, xi->te, xi->pchain); - } - // if((!is_hom) && (m_het < 2) && (m_het > 0)) return;///if all matched unitigs are hom, is ok - if(m_het == 0 || m_het_occ == 0) is_hom = 1; - // print_ul_alignment(ug, &UL_INF, 27512, "inner-0"); - for (k = 0, buf->b.n = 0; k < str->cn; k++) { - vk = (uint32_t)str->a[k]; - hid_a = str_idx->occ.a + str_idx->idx.a[vk>>1]; - hid_n = str_idx->idx.a[(vk>>1)+1] - str_idx->idx.a[vk>>1]; - for (z = 0; z < hid_n; z++) { - if((hid_a[z]>>32) == qid) continue; - if(str_idx->str.a[hid_a[z]>>32].cn < 2) continue; - vz = (uint32_t)(str_idx->str.a[hid_a[z]>>32].a[(uint32_t)hid_a[z]]); - assert((vk>>1) == (vz>>1)); - kv_pushp(integer_aln_t, buf->b, &p); - p->vq = vk; p->tk = (uint32_t)hid_a[z]; - if((vk^vz)&1) p->tk = str_idx->str.a[hid_a[z]>>32].cn - p->tk - 1;///rev - p->tn_rev_qk = (hid_a[z]>>32); p->tn_rev_qk <<= 1; p->tn_rev_qk |= ((vk^vz)&1); - p->tn_rev_qk <<= 32; p->tn_rev_qk += k; - ///set score of this pair - p->sc = buf->u.a[k]; - xi = &(uidx->idx->a[hid_a[z]>>32].bb.a[(str_idx->str.a[hid_a[z]>>32].a[(uint32_t)hid_a[z]])>>32]); - assert(((xi->hid<<1)+xi->rev)==vz); m = ug_occ_w(xi->ts, xi->te, &(ug->u.a[xi->hid])); - if(p->sc > m) p->sc = m; - } - } - // print_ul_alignment(ug, &UL_INF, 27512, "inner-1"); - radix_sort_integer_aln_t_srt(buf->b.a, buf->b.a + buf->b.n); - b_n = buf->b.n; buf->sc.n = 0; - for (k = 1, z = 0; k <= b_n; k++) { - if(k == b_n || (buf->b.a[z].tn_rev_qk>>32) != (buf->b.a[k].tn_rev_qk>>32)) { - ///get the chain for - if(integer_chain(qid, buf->b.a + z, k - z, z, buf, ug, str_idx, uidx->idx, &sc) && sc.v != (uint32_t)-1) { - if((buf->sc.n > 0) && ((buf->sc.a[buf->sc.n-1].v>>1) == (sc.v>>1))) { - if(buf->sc.a[buf->sc.n-1].sc < sc.sc) { - buf->sc.a[buf->sc.n-1] = sc; - } - } else { - kv_push(ul_chain_t, buf->sc, sc); - } - } - z = k; - } - } - // print_ul_alignment(ug, &UL_INF, 27512, "inner-2"); - uint64_t *o, o_n, cns_het, cns_het_occ, ref_cns_occ, corrected = 0; - o_n = integer_chain_dp(uidx->bub, buf, str_idx->str.a, buf->b.a, buf->sc.a, buf->sc.n, qid, is_hom, 2, &corrected); - assert(o_n <= str->cn); - // if(qid == 2062 || qid == 2093) fprintf(stderr,"[M::%s::] o_n::%lu, str->cn::%u, corrected::%lu\n", __func__, o_n, str->cn, corrected); - if(o_n <= 0) return; - if(corrected) return; - // print_ul_alignment(ug, &UL_INF, 27512, "inner-3"); - - for (k = cns_het = cns_het_occ = ref_cns_occ = 0, o = buf->o.a; k < o_n; k++) { - if((!is_hom) && (!IF_HOM((((uint32_t)str->a[o[k]])>>1), (*uidx->bub)))) { - cns_het++; cns_het_occ += buf->u.a[o[k]]; - } - ref_cns_occ += buf->u.a[o[k]]; - } - buf->o.n = o_n; - ///1. if the ref read only has hom unitigs, is fine - ///2. otherwise need to have consenus het untigs - if(!is_hom) { - if((cns_het <= 0) || (cns_het_occ <= 0) || (cns_het_occ <= (m_het_occ*0.25))) return; - } else { - if(ref_cns_occ <= (ref_occ*0.25)) return; - } - // print_ul_alignment(ug, &UL_INF, 27512, "inner-4"); - // fprintf(stderr, "\n"); - // print_integer_seq(ug, str_idx->str.a, qid, 1); - // print_aln_seq(ug, uidx->idx, qid, 1); - // if(qid == 2062 || qid == 2093) print_cns_seq(ug, str, o, o_n); - // print_ul_alignment(ug, &UL_INF, 27512, "inner-5"); - - for (k = m = 0; k < buf->sc.n; k++) { - // fprintf(stderr, "[M::%s::k->%lu] m::%lu\n", __func__, k, m); - // if(k == 72) { - // print_integer_ovlps(ug, str_idx->str.a, buf->b.a, buf->b.n, buf->sc.a+k, 1, qid, o_n); - // } - if(refine_integer_ovlps(uidx->idx, uidx->bub, ug, str_idx->str.a, buf->b.a, - &(buf->sc.a[k]), qid, buf, o, o_n)) { - buf->sc.a[m++] = buf->sc.a[k]; - } - // else { - // print_integer_ovlps(ug, str_idx->str.a, buf->b.a, buf->b.n, buf->sc.a+k, 1, qid, o_n); - // fprintf(stderr, "[M::%s::] idx->q_sidx::%u, idx->q_eidx::%u, idx->t_sidx::%u, idx->t_eidx::%u\n******************************************************\n", - // __func__, buf->sc.a[k].q_sidx, buf->sc.a[k].q_eidx, buf->sc.a[k].t_sidx, buf->sc.a[k].t_eidx); - // } - } - buf->sc.n = m; - if(m <= 0) return; - // print_ul_alignment(ug, &UL_INF, 27512, "inner-6"); - // if(m != str->cn) print_integer_ovlps(uidx->l1_ug, str_idx->str.a, buf->b.a, buf->b.n, buf->sc.a, buf->sc.n, qid, m); - poa_cns_chain(&(buf->pg), uidx->idx, ug, str_idx->str.a, buf->sc.a, buf->sc.n, qid, buf, &is_circle); - if(is_circle) { - buf->n_circle++; - return; - } - // print_ul_alignment(ug, &UL_INF, 27512, "inner-7"); - // print_res_seq(&(buf->pg), ug, buf->pg.srt_b.res.a, buf->pg.srt_b.res.n); - // radix_sort_ul_chain_t_srt(buf->sc.a, buf->sc.a + buf->sc.n); - - // integer_phase(str_idx->str.a, buf, buf->sc.a, buf->sc.n, buf->b.a, qid); - - // radix_sort_ul_chain_t_srt(buf->sc.a, buf->sc.a + buf->sc.n); - o = NULL; o_n = 0; - update_raw_integer_seq(&(buf->pg), ug, buf->pg.srt_b.res.a, buf->pg.srt_b.res.n, uidx->idx, str_idx->str.a, qid, buf, buf->sc.a, buf->sc.n); -} - -ul2ul_item_t *get_ul_ovlp(ul2ul_idx_t *z, uint64_t id, uint64_t is_ul) -{ - uint64_t x = (is_ul?(id):(id+z->uln)); - if(z->item_idx[x] == (uint32_t)-1) return NULL; - return &(z->a[z->item_idx[x]]); -} - -ul2ul_t *get_ul_o(ul2ul_idx_t *idx, uint32_t qid, uint32_t is_q_ul, uint32_t tid, uint32_t is_t_ul) -{ - ul2ul_item_t *z = get_ul_ovlp(idx, qid, is_q_ul); uint64_t k; - if(!is_t_ul) tid += idx->uln; - for (k = 0; k < z->n; k++) { - if(z->a[k].hid == tid) return &(z->a[k]); - } - return NULL; -} - -void integer_gen_ovlp(ul_resolve_t *uidx, integer_t *buf, uint32_t qid, ul2ul_item_t *o, uint32_t ug_offset) -{ - ul_str_idx_t *str_idx = &(uidx->pstr); ma_ug_t *ug = uidx->l1_ug; ul2ul_t res; - ul_str_t *str = &(str_idx->str.a[qid]); integer_aln_t *p; ul_chain_t sc; - uint64_t k, z, *hid_a, hid_n, sck, b_n, m/**, ovn = 0**/; uint32_t vk, vz; uc_block_t *xi; - o->n = o->cn = 0; o->id = qid; o->is_del = 0; ///o->is_consist = 0; - // if(qid == 95 || qid == 36) print_integer_seq(ug, str_idx->str.a, qid, 1); - if(str->cn < 2) return; - for (k = 0, buf->b.n = 0; k < str->cn; k++) { - xi = &(uidx->idx->a[qid].bb.a[str->a[k]>>32]); - assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[k])); - sck = ug_occ_w(xi->ts, xi->te, &(ug->u.a[xi->hid])); - - vk = (uint32_t)str->a[k]; - hid_a = str_idx->occ.a + str_idx->idx.a[vk>>1]; - hid_n = str_idx->idx.a[(vk>>1)+1] - str_idx->idx.a[vk>>1]; - for (z = 0; z < hid_n; z++) { - // if(qid == 95 || qid == 36) { - // fprintf(stderr,"[M::%s::qid->%u::tid->%lu] k->%lu, tid_occ->%u\n", - // __func__, qid, (hid_a[z]>>32), k, str_idx->str.a[hid_a[z]>>32].cn); - // } - if((hid_a[z]>>32) == qid) continue; - if(str_idx->str.a[hid_a[z]>>32].cn < 2) continue; - vz = (uint32_t)(str_idx->str.a[hid_a[z]>>32].a[(uint32_t)hid_a[z]]); - assert((vk>>1) == (vz>>1)); - kv_pushp(integer_aln_t, buf->b, &p); - p->vq = vk; p->tk = (uint32_t)hid_a[z]; - if((vk^vz)&1) p->tk = str_idx->str.a[hid_a[z]>>32].cn - p->tk - 1;///rev - p->tn_rev_qk = (hid_a[z]>>32); p->tn_rev_qk <<= 1; p->tn_rev_qk |= ((vk^vz)&1); - p->tn_rev_qk <<= 32; p->tn_rev_qk += k; - ///set score of this pair - p->sc = sck; - xi = &(uidx->idx->a[hid_a[z]>>32].bb.a[(str_idx->str.a[hid_a[z]>>32].a[(uint32_t)hid_a[z]])>>32]); - assert(((xi->hid<<1)+xi->rev)==vz); m = ug_occ_w(xi->ts, xi->te, &(ug->u.a[xi->hid])); - if(p->sc > m) p->sc = m; - } - } - - radix_sort_integer_aln_t_srt(buf->b.a, buf->b.a + buf->b.n); - - // b_n = buf->b.n; - // for (k = 1, z = ovn = 0; k <= b_n; k++) { - // if(k == b_n || (buf->b.a[z].tn_rev_qk>>33) != (buf->b.a[k].tn_rev_qk>>33)) { - // ovn++; z = k; - // } - // } - - b_n = buf->b.n; buf->sc.n = 0; - for (k = 1, z = 0; k <= b_n; k++) { - if(k == b_n || (buf->b.a[z].tn_rev_qk>>32) != (buf->b.a[k].tn_rev_qk>>32)) { - // if(qid == 95 || qid == 36) { - // fprintf(stderr,"[M::%s::qid->%u::tid->%lu]\n", __func__, qid, buf->b.a[z].tn_rev_qk>>33); - // } - if(integer_chain(qid, buf->b.a + z, k - z, z, buf, ug, str_idx, uidx->idx, &sc) && sc.v != (uint32_t)-1) { - if((buf->sc.n > 0) && ((buf->sc.a[buf->sc.n-1].v>>1) == (sc.v>>1))) { - if(buf->sc.a[buf->sc.n-1].sc < sc.sc) { - buf->sc.a[buf->sc.n-1] = sc; - } - } else { - kv_push(ul_chain_t, buf->sc, sc); - } - } - z = k; - } - } - - for (k = o->n = 0; k < buf->sc.n; k++) { - if(update_exact_ul_ovlps(uidx->idx, ug, str_idx->str.a, buf->b.a, &(buf->sc.a[k]), qid, buf, &res)) { - kv_push(ul2ul_t, *o, res); - } - } - // if(str->cn > 0) { - // for (k = 0, buf->b.n = 0; k < str->cn; k++) { - // xi = &(uidx->idx->a[qid].bb.a[str->a[k]>>32]); - - // // if(xi->ts) - // } - // // uint32_t v, nv; asg_arc_t *av; asg_t *g = ug->g; ul2ul_t *r; - // // v = ((uint32_t)str->a[0])^1; - // // nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - // // for (k = 0; k < nv; k++) { - // // if(av[k].del) continue; - // // kv_pushp(ul2ul_t, *o, &r); - // // r->hid = (av[k].v>>1) + ug_offset; - // // r->is_rev = (av[k].v^v)&1; - // // r->qs = 0; r->qe = av[k].ol; - - // // } - // // v = ((uint32_t)str->a[str->cn-1]); - // // nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - // } - o->cn = o->n; - // if(ovn == o->cn) o->is_consist = 1; - if(o->n <= 0) return; -} - -#define ulg_id(ul2, i) (((i)>=(ul2).uln)?((i)-(ul2).uln):(i)) -#define ulg_type(ul2, i) (((i)>=(ul2).uln)?(0):(1)) -#define ulg_len(uidx, i) (ulg_type((uidx).uovl,(i))?((uidx).idx->a[ulg_id((uidx).uovl,(i))].rlen):((uidx).l1_ug->u.a[ulg_id((uidx).uovl,(i))].len)) -#define ulg_occ(uidx, i) (ulg_type((uidx).uovl,(i))?((uidx).pstr.str.a[ulg_id((uidx).uovl,(i))].cn):(1)) - -void integer_normalize_ovlp(ul_resolve_t *uidx, uint32_t qid, ul2ul_item_t *o, ul2ul_idx_t *ul2) -{ - ul2ul_t *z; uint64_t k; ul2ul_item_t *t; - for (k = 0; k < o->n; k++) { - assert(ul2->item_idx[o->a[k].hid] != (uint32_t)-1); - z = get_ul_o(ul2, ulg_id(*ul2, o->a[k].hid), ulg_type(*ul2, o->a[k].hid), - ulg_id(*ul2, qid), ulg_type(*ul2, qid)); - // assert(z && z->hid == qid); - // if(o->a[k].is_rev == z->is_rev && (*z).qs == o->a[k].ts && (*z).qe == o->a[k].te && - // (*z).ts == o->a[k].qs && (*z).te == o->a[k].qe) { - // fprintf(stderr, "good::[M::%s] fn::%u(%c), fqs::%u, fqe::%u, fts::%u, fte::%u, rn::%u(%c), rqs::%u, rqe::%u, rts::%u, rte::%u\n", __func__, - // o->a[k].hid, "+-"[o->a[k].is_rev], o->a[k].qs, o->a[k].qe, o->a[k].ts, o->a[k].te, - // z->hid, "+-"[z->is_rev], z->qs, z->qe, z->ts, z->te); - // } else { - // fprintf(stderr, "bad::[M::%s] fn::%u(%c), fqs::%u, fqe::%u, fts::%u, fte::%u, rn::%u(%c), rqs::%u, rqe::%u, rts::%u, rte::%u\n", __func__, - // o->a[k].hid, "+-"[o->a[k].is_rev], o->a[k].qs, o->a[k].qe, o->a[k].ts, o->a[k].te, - // z->hid, "+-"[z->is_rev], z->qs, z->qe, z->ts, z->te); - // } - // continue; - if(z && o->a[k].hid < qid) continue; - if(!z) { - t = get_ul_ovlp(ul2, ulg_id(*ul2, o->a[k].hid), ulg_type(*ul2, o->a[k].hid)); - assert(t); - kv_pushp(ul2ul_t, *t, &z); - (*z).hid = qid; - (*z).qs = o->a[k].ts; (*z).qe = o->a[k].te; - (*z).ts = o->a[k].qs; (*z).te = o->a[k].qe; - (*z).qs_k = o->a[k].ts_k; (*z).qe_k = o->a[k].te_k; - (*z).ts_k = o->a[k].qs_k; (*z).te_k = o->a[k].qe_k; - (*z).is_rev = o->a[k].is_rev; (*z).is_del = o->a[k].is_del; - (*z).is_ct = o->a[k].is_ct; - if(!((*z).is_del)) { - t->cn++; - } - } else { - if((o->a[k].qe - o->a[k].qs) >= (z->te - z->ts)) { - (*z).qs = o->a[k].ts; (*z).qe = o->a[k].te; - (*z).ts = o->a[k].qs; (*z).te = o->a[k].qe; - (*z).qs_k = o->a[k].ts_k; (*z).qe_k = o->a[k].te_k; - (*z).ts_k = o->a[k].qs_k; (*z).te_k = o->a[k].qe_k; - (*z).is_rev = o->a[k].is_rev; (*z).is_del = o->a[k].is_del; - (*z).is_ct = o->a[k].is_ct; - } else { - o->a[k].qs = (*z).ts; o->a[k].qe = (*z).te; - o->a[k].ts = (*z).qs; o->a[k].te = (*z).qe; - o->a[k].qs_k = (*z).ts_k; o->a[k].qe_k = (*z).te_k; - o->a[k].ts_k = (*z).qs_k; o->a[k].te_k = (*z).qe_k; - o->a[k].is_rev = (*z).is_rev; o->a[k].is_del = (*z).is_del; - o->a[k].is_ct = (*z).is_ct; - } - } - } -} - - -void integer_normalize_ovlp_purge(ul_resolve_t *uidx, uint32_t qid, ul2ul_item_t *o, ul2ul_idx_t *ul2) -{ - if(o->is_del) return; - ul2ul_t *z; uint64_t k, is_del; - for (k = is_del = 0; k < o->n; k++) { - if(o->a[k].is_del) continue; - z = get_ul_o(ul2, o->a[k].hid, 1, qid, 1); - if((!z) || (z->is_del)) { - o->a[k].is_del = 1; is_del++; - } - } - - if(is_del) { - for (k = o->cn = 0; k < o->n; k++) { - if(o->a[k].is_del) o->a[k].hid |= ((uint32_t)(0x80000000)); - else o->cn++; - } - - radix_sort_ul2ul_srt(o->a, o->a + o->n); - - for (k = 0; k < o->n; k++) { - if(o->a[k].hid&((uint32_t)(0x80000000))) { - o->a[k].hid -= ((uint32_t)(0x80000000)); - } - } - } - - if(o->cn == 0) o->is_del = 1; -} - -static inline int64_t integer_hit2arc_idx_contain(const ul2ul_t *z, int64_t qn, int64_t tn, uint64_t *dir) -{ - int64_t tn5, tn3, extn5, extn3, qsn = z->qs_k, qen = qn - ((int64_t)z->qe_k); - if (z->is_rev) tn5 = tn - z->te_k, tn3 = z->ts_k; - else tn5 = z->ts_k, tn3 = tn - z->te_k; - (*dir) = (uint64_t)-1; - - extn5 = ((qsn 0 || extn3 > 0) return MA_HT_INT;///overhang - if (qsn < tn5 && qen < tn3) { // query contained in target - return MA_HT_QCONT; - } else if (qsn > tn5 && qen > tn3) { // target contained in query - return MA_HT_TCONT; - } else if(qsn == tn5 && qen == tn3) { - (*dir) = (uint64_t)-1; - } else if (qsn > tn5) { ///query-to-target overlap - (*dir) = 0; - } else if(qsn < tn5) { ///target-to-query overlaps - (*dir) = 1; - } else if(qen > tn3) { ///target-to-query overlaps - (*dir) = 1; - } else if(qen < tn3) { ///query-to-target overlap - (*dir) = 0; - } - return MA_HT_DOUBLE; -} - -static inline int integer_hit2arc(const ul2ul_t *z, int64_t ql, int64_t tl, int64_t qocc, int64_t tocc, uint64_t qid, uint64_t tid, -int64_t min_ovlp, asg_arc_t *p) -{ - int64_t tl5, tl3, ext5, ext3, qs = z->qs, rf; - uint64_t u, v, l, rr; // u: query end; v: target end; l: length from u to v - - ///if query and target are in different strand - if (z->is_rev) tl5 = tl - z->te, tl3 = z->ts; // tl5: 5'-end overhang (on the query strand); tl3: similar - else tl5 = z->ts, tl3 = tl - z->te; - - ///ext5 and ext3 is the hang on left side and right side, respectively - ext5 = qs < tl5? qs : tl5; - ext3 = (((ql - ((int64_t)z->qe)) < tl3)? (ql - ((int64_t)z->qe)) : tl3); - - if(ext5 > 0 || ext3 > 0) return MA_HT_INT;///overhang - if (qs <= tl5 && (ql - (int64_t)z->qe) <= tl3) { // query contained in target - return MA_HT_QCONT; - } else if (qs >= tl5 && (ql - (int64_t)z->qe) >= tl3) { // target contained in query - return MA_HT_TCONT; - } else if (qs > tl5) { ///u = 0 means query-to-target overlap, l is the length of node in string graph (not the overlap length) - u = 0, v = !!(z->is_rev), l = qs - tl5; - } else { ///u = 1 means target-to-query overlaps, l is the length of node in string graph (not the overlap length) - u = 1, v = !(z->is_rev), l = (ql - z->qe) - tl3; - } - if ((int64_t)z->qe - qs + ext5 + ext3 < min_ovlp || (int64_t)z->te - (int64_t)z->ts + ext5 + ext3 < min_ovlp) { - return MA_HT_SHORT_OVLP; // short overlap - } - rf = integer_hit2arc_idx_contain(z, qocc, tocc, &rr); - if(rf != MA_HT_DOUBLE) return rf; - if(rr != (uint64_t)-1 && rr != u) { - // fprintf(stderr, "[M::%s::] z->is_rev::%u, z->qs::%u, z->qe::%u, z->ts::%u, z->te::%u, z->qs_k::%u, z->qe_k::%u, z->ts_k::%u, z->te_k::%u, ql::%ld, tl::%ld, qocc::%ld, tocc::%ld\n", __func__, - // z->is_rev, z->qs, z->qe, z->ts, z->te, z->qs_k, z->qe_k, z->ts_k, z->te_k, ql, tl, qocc, tocc); - return MA_HT_INT;///overhang - } - ///u = 0 / 1 means query-to-target / target-to-query overlaps, - ///l is the length of node in string graph (not the overlap length between two reads) - u |= qid<<1, v |= tid<<1; - /** - p->ul: |____________31__________|__________1___________|______________32_____________| - qn direction of overlap length of this node (not overlap length) - (in the view of query) - p->v : |___________31___________|__________1___________| - tn reverse direction of overlap - (in the view of target) - p->ol: overlap length - **/ - if(p) { - p->ul = (uint64_t)u<<32 | l, p->v = v, p->ol = ql - l, p->del = 0; - ///l is the length of node in string graph (not the overlap length) - - p->strong = 1; p->el = 1; p->no_l_indel = 1; - } - return l; -} - - -void integer_append_ug_ovlp(ul_resolve_t *uidx, uint32_t qid, ul2ul_item_t *o, ul2ul_idx_t *ul2) -{ - // if(o->is_del) return; - uint64_t k; uc_block_t *xi; ul2ul_t *z; ul2ul_item_t *t; int32_t r; - ma_ug_t *ug = uidx->l1_ug; ul_str_t *str = &(uidx->pstr.str.a[qid]); - for (k = 0; k < str->cn; k++) { - xi = &(uidx->idx->a[qid].bb.a[str->a[k]>>32]); - assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[k])); - - ///ul side - kv_pushp(ul2ul_t, *o, &z); - z->hid = xi->hid + ul2->uln; z->is_rev = xi->rev; z->is_del = o->is_del; z->is_ct = 0; - z->qs = xi->qs; z->qe = xi->qe; z->ts = xi->ts; z->te = xi->te; - z->qs_k = k; z->qe_k = k + 1; z->ts_k = 0; z->te_k = 1; - - r = integer_hit2arc(z, uidx->idx->a[qid].rlen, ug->u.a[xi->hid].len, uidx->pstr.str.a[qid].cn, - 1, qid, z->hid, 0, NULL); - if(r == MA_HT_INT) { - o->n--; continue; - } - ///ug side - t = get_ul_ovlp(ul2, xi->hid, 0); - assert(t); - kv_pushp(ul2ul_t, *t, &z); - z->hid = qid; z->is_rev = xi->rev; z->is_del = o->is_del; z->is_ct = 0; - z->qs = xi->ts; z->qe = xi->te; z->ts = xi->qs; z->te = xi->qe; - z->qs_k = 0; z->qe_k = 1; z->ts_k = k; z->te_k = k + 1; - } -} - -void integer_node_del(ul2ul_idx_t *ul2, uint64_t id, uint64_t is_ct) -{ - ul2ul_item_t *o = get_ul_ovlp(ul2, ulg_id(*ul2, id), ulg_type(*ul2, id)); - if(o) { - uint64_t k; ul2ul_t *z; - for (k = 0; k < o->cn; k++) { - if(is_ct) o->a[k].is_ct = 1; - else o->a[k].is_del = 1; - z = get_ul_o(ul2, ulg_id(*ul2, o->a[k].hid), ulg_type(*ul2, o->a[k].hid), ulg_id(*ul2, id), ulg_type(*ul2, id)); - if(is_ct) z->is_ct = 1; - else z->is_del = 1; - } - o->is_del = 1; - } -} - -void integer_containment_purge(ul_resolve_t *uidx, uint32_t qid, ul2ul_item_t *q, ul2ul_idx_t *ul2, uint32_t keep_raw_utg) -{ - if(q->is_del) return; - uint64_t k; int32_t r; ul2ul_item_t *t; ul2ul_t *z; assert(qid == q->id); - for (k = 0; k < q->cn; k++) { - if(q->a[k].is_del || q->a[k].is_ct) continue; - t = get_ul_ovlp(ul2, ulg_id(*ul2, q->a[k].hid), ulg_type(*ul2, q->a[k].hid)); - assert(t); - if(t->is_del) continue; - r = integer_hit2arc(&(q->a[k]), ulg_len(*uidx, qid), ulg_len(*uidx, q->a[k].hid), - ulg_occ(*uidx, qid), ulg_occ(*uidx, q->a[k].hid), qid, q->a[k].hid, 0, NULL); - // assert(r != MA_HT_INT); - if (r == MA_HT_QCONT) { - q->a[k].is_ct = 1; - z = get_ul_o(ul2, ulg_id(*ul2, q->a[k].hid), ulg_type(*ul2, q->a[k].hid), ulg_id(*ul2, qid), ulg_type(*ul2, qid)); - assert(z && (!z->is_del) && (!z->is_ct)); z->is_ct = 1; - if((!keep_raw_utg) || ulg_type(*ul2, qid)) integer_node_del(ul2, qid, 1); - } else if (r == MA_HT_TCONT) { - q->a[k].is_ct = 1; - z = get_ul_o(ul2, ulg_id(*ul2, q->a[k].hid), ulg_type(*ul2, q->a[k].hid), ulg_id(*ul2, qid), ulg_type(*ul2, qid)); - assert(z && (!z->is_del) && (!z->is_ct)); z->is_ct = 1; - if((!keep_raw_utg) || ulg_type(*ul2, q->a[k].hid)) integer_node_del(ul2, q->a[k].hid, 1); - } - } - - // if(ulg_type(*ul2, k)) { - // for (k = 0; k < q->cn; k++) { - // if((!(q->a[k].is_del)) && (!(q->a[k].is_ct))) break; - // } - // if(k >= q->cn) q->is_del = 1; - // } -} - - -static void worker_integer_correction(void *data, long i, int tid) // callback for kt_for() -{ - ul_resolve_t *uidx = (ul_resolve_t *)data; - integer_ml_t *sl = &(uidx->str_b); - integer_t *buf = &(sl->buf[tid]); - // uc_block_t *uls; uint64_t uls_n; uint32_t v; - // uint64_t *srt_a, srt_n, is_circle = ((uidx->psrt.idx.a[i]&((uint64_t)(0x100000000)))?1:0); - // srt_a = uidx->psrt.srt.a + (uint32_t)uidx->psrt.idx.a[i]; srt_n = uidx->psrt.idx.a[i]>>33; - // if(srt_n == 0) return; - // integer_candidate(uidx, srt_a, srt_n, is_circle, buf); - integer_candidate(uidx, buf, i, (asm_opt.purge_level_primary == 0?1:0)); -} - -static void worker_integer_postprecess(void *data, long i, int tid) // callback for kt_for() -{ - ul_resolve_t *uidx = (ul_resolve_t *)data; - integer_ml_t *sl = &(uidx->str_b); - integer_t *buf = &(sl->buf[tid]); - ul2ul_item_t *it = get_ul_ovlp(&(uidx->uovl), i, 1); - if(!it) return; - assert(uidx->pstr.str.a[i].cn > 1); - // uc_block_t *uls; uint64_t uls_n; uint32_t v; - // uint64_t *srt_a, srt_n, is_circle = ((uidx->psrt.idx.a[i]&((uint64_t)(0x100000000)))?1:0); - // srt_a = uidx->psrt.srt.a + (uint32_t)uidx->psrt.idx.a[i]; srt_n = uidx->psrt.idx.a[i]>>33; - // if(srt_n == 0) return; - // integer_candidate(uidx, srt_a, srt_n, is_circle, buf); - integer_gen_ovlp(uidx, buf, i, it, uidx->uovl.uln); -} - - -void gen_integer_normalize(ul_resolve_t *uidx) -{ - uint64_t k; ul2ul_idx_t *u2o = &(uidx->uovl); ul2ul_item_t *it; - for (k = 0; k < u2o->uln; k++) { - it = get_ul_ovlp(u2o, k, 1); - if(!it) continue; - assert(uidx->pstr.str.a[k].cn > 1); - if(it->is_del) continue; - integer_normalize_ovlp(uidx, k, it, u2o); - } -} - -uint64_t dd_path_connect(asg_t *g, ul_str_t *str) -{ - if(str->cn < 2) return 1;///actually should return 1, doesn't matter - uint64_t i, v, w, nv, k; asg_arc_t *av; - v = ((uint32_t)str->a[0]); - for (i = 1; i < str->cn; i++) { - w = ((uint32_t)str->a[i]); - - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == w) break; - } - if(k >= nv) return 0; - - nv = asg_arc_n(g, w^1); av = asg_arc_a(g, w^1); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == (v^1)) break; - } - if(k >= nv) return 0; - - v = w; - } - return 1; -} - -void clip_integer_chimeric(ul_resolve_t *uidx, uint32_t qid, ul2ul_item_t *o, ul2ul_idx_t *ul2, integer_t *buf, int64_t min_dp) -{ - uint64_t k, is_srt = 0, is_del = 0/**, rid, zs, ze**/; assert(o->id == qid); - ul_str_t *str = &(uidx->pstr.str.a[qid]); ///int64_t z, z_n; - for (k = 0; k < o->cn; k++) { - if(o->a[k].is_del) break; - if(k > 0 && o->a[k].hid < o->a[k-1].hid) break; - } - if(k < o->cn) { - is_srt = 1; - } else { - for (; k < o->n; k++) { - if(!(o->a[k].is_del)) break; - if(k > o->cn && o->a[k].hid < o->a[k-1].hid) break; - } - if(k < o->n) is_srt = 1; - } - - if(is_srt) { - for (k = o->cn = 0; k < o->n; k++) { - if(o->a[k].is_del) o->a[k].hid |= ((uint32_t)(0x80000000)); - else o->cn++; - } - - radix_sort_ul2ul_srt(o->a, o->a + o->n); - - for (k = 0; k < o->n; k++) { - if(o->a[k].hid&((uint32_t)(0x80000000))) { - o->a[k].hid -= ((uint32_t)(0x80000000)); - } - } - } - - for (k = 0, buf->u.n = 0; k < o->cn; k++) { - // kv_push(uint64_t, buf->u, (o->a[k].qs<<1)); - kv_push(uint64_t, buf->u, (o->a[k].qs_k<<1)); - // kv_push(uint64_t, buf->u, (o->a[k].qe<<1)|1); - kv_push(uint64_t, buf->u, (o->a[k].qe_k<<1)|1); - } - radix_sort_srt64(buf->u.a, buf->u.a + buf->u.n); - - int64_t dp, old_dp; uint64_t start, end, b_n = buf->u.n; - for (k = 0, dp = 0, start = 0; k < b_n; ++k) { - old_dp = dp; - ///if a[j] is qe - if (buf->u.a[k]&1) --dp; - else ++dp; - - if (old_dp < min_dp && dp >= min_dp) {///old_dp < dp, b.a[j] is qs - start = buf->u.a[k]>>1; - } else if (old_dp >= min_dp && dp < min_dp) {///old_dp > min_dp, b.a[j] is qe - end = buf->u.a[k]>>1; - kv_push(uint64_t, buf->u, ((start<<32)|(end))); - } - } - - is_del = 0; - if(buf->u.n == b_n) { - is_del = 1; - } else { - uint32_t is_left = 0, is_right = 0, is_middle = 0; - for (k = b_n; k < buf->u.n; ++k) { - start = buf->u.a[k]>>32; end = (uint32_t)buf->u.a[k]; - if(start == 0) is_left = 1; - else is_middle = 1; - if(end == str->cn/**uidx->idx->a[qid].rlen**/) is_right = 1; - else is_middle = 1; - } - if(is_left == 0 && is_right == 0) is_del = 1; - if(is_left && is_right && is_middle) is_del = 1; - } - - // if(is_del && str->cn > 1 && o->is_consist && dd_path_connect(uidx->l1_ug->g, str)) { - // is_del = 0; - // } - - // fprintf(stderr, "[M::%s] qid::%u, o->is_consist::%u, str->cn::%u, is_connect::%lu\n", - // __func__, qid, o->is_consist, str->cn, dd_path_connect(uidx->l1_ug->g, str)); - - /** - if(!is_del) { - for (k = 0; k < str->cn; k++) { - rid = (((uint32_t)str->a[k])>>1); - if(!IF_HOM(rid, *(uidx->bub))) break; - } - - if(k < str->cn) {///at least a het node covered - for (k = 0, buf->u.n = 0; k < o->cn; k++) { - z = o->a[k].qs_k; z_n = o->a[k].qe_k; - for (; z < z_n; z++) { - rid = (((uint32_t)str->a[z])>>1); - if(!IF_HOM(rid, *(uidx->bub))) break; - } - if(z >= z_n) continue; - zs = z; - - for (z = z_n - 1; z >= (int64_t)zs; z--) { - rid = (((uint32_t)str->a[z])>>1); - if(!IF_HOM(rid, *(uidx->bub))) break; - } - ze = z + 1; - assert(zs < ze); - - kv_push(uint64_t, buf->u, (zs<<1)); - kv_push(uint64_t, buf->u, (ze<<1)|1); - - } - radix_sort_srt64(buf->u.a, buf->u.a + buf->u.n); - - b_n = buf->u.n; - for (k = 0, dp = 0, start = 0; k < b_n; ++k) { - old_dp = dp; - ///if a[j] is qe - if (buf->u.a[k]&1) --dp; - else ++dp; - - if (old_dp < min_dp && dp >= min_dp) {///old_dp < dp, b.a[j] is qs - start = buf->u.a[k]>>1; - } else if (old_dp >= min_dp && dp < min_dp) {///old_dp > min_dp, b.a[j] is qe - end = buf->u.a[k]>>1; - kv_push(uint64_t, buf->u, ((start<<32)|(end))); - } - } - - is_del = 0; - if(buf->u.n == b_n) { - is_del = 1; - } else { - uint32_t is_left = 0, is_right = 0, is_middle = 0; - for (k = b_n; k < buf->u.n; ++k) { - start = buf->u.a[k]>>32; end = (uint32_t)buf->u.a[k]; - if(start == 0) is_left = 1; - else is_middle = 1; - if(end == str->cn) is_right = 1; - else is_middle = 1; - } - if(is_left == 0 && is_right == 0) is_del = 1; - if(is_left && is_right && is_middle) is_del = 1; - } - } - } - **/ - - if(is_del) { - o->is_del = 1; - for (k = 0; k < o->cn; k++) o->a[k].is_del = 1; - if(o->cn && o->n > o->cn) radix_sort_ul2ul_srt(o->a, o->a + o->n); - o->cn = 0; - } -} - -void clean_srt_integer(ul_resolve_t *uidx, uint32_t qid, ul2ul_item_t *o, ul2ul_idx_t *ul2) -{ - uint64_t k, l, i, m; ul2ul_t *p; - radix_sort_ul2ul_srt(o->a, o->a + o->n); - for(k = 1, l = m = o->cn = 0; k <= o->n; k++) { - if(k == o->n || o->a[k].hid != o->a[l].hid) { - for (i = l, p = &(o->a[l]); i < k; i++) { - if(((p->is_del) && (!o->a[i].is_del)) || - ((o->a[i].qe - o->a[i].qs + o->a[i].te - o->a[i].ts) > (p->qe - p->qs + p->te - p->ts))) { - p = &(o->a[i]); - } - } - if(!(p->is_del)) o->cn++; - o->a[m++] = *p; - l = k; - } - } - o->n = m; - if(o->n == o->cn) return; - - for (k = o->cn = 0; k < o->n; k++) { - if(o->a[k].is_del) o->a[k].hid |= ((uint32_t)(0x80000000)); - else o->cn++; - } - radix_sort_ul2ul_srt(o->a, o->a + o->n); - - for (k = 0; k < o->n; k++) { - if(o->a[k].hid&((uint32_t)(0x80000000))) { - o->a[k].hid -= ((uint32_t)(0x80000000)); - } - } -} - - -static void worker_detect_chimeric(void *data, long i, int tid) // callback for kt_for() -{ - ul_resolve_t *uidx = (ul_resolve_t *)data; - integer_ml_t *sl = &(uidx->str_b); - integer_t *buf = &(sl->buf[tid]); - ul2ul_item_t *it = get_ul_ovlp(&(uidx->uovl), i, 1); - if(!it) return; - assert(uidx->pstr.str.a[i].cn > 1); - if(it->is_del) return; - clip_integer_chimeric(uidx, i, it, &(uidx->uovl), buf, 1); -} - - -void chimeric_integer_deal(ul_resolve_t *uidx) -{ - uint64_t k; ul2ul_idx_t *u2o = &(uidx->uovl); ul2ul_item_t *it; - kt_for(uidx->str_b.n_thread, worker_detect_chimeric, uidx, uidx->idx->n); - for (k = 0; k < u2o->uln; k++) { - it = get_ul_ovlp(u2o, k, 1); - if(!it) continue; - assert(uidx->pstr.str.a[k].cn > 1); - integer_normalize_ovlp_purge(uidx, k, it, u2o); - } -} - - - - -static void worker_integert_clean(void *data, long i, int tid) // callback for kt_for() -{ - ul_resolve_t *uidx = (ul_resolve_t *)data; - ul2ul_item_t *it = get_ul_ovlp(&(uidx->uovl), ulg_id(uidx->uovl, (uint32_t)i), - ulg_type(uidx->uovl, (uint32_t)i)); - if(!it) return; - if((uint32_t)i >= uidx->uovl.uln) it->id = i; - clean_srt_integer(uidx, i, it, &(uidx->uovl)); -} - -static void worker_integert_debug_sym(void *data, long i, int tid) // callback for kt_for() -{ - ul_resolve_t *uidx = (ul_resolve_t *)data; - ul2ul_item_t *o = get_ul_ovlp(&(uidx->uovl), ulg_id(uidx->uovl, (uint32_t)i), - ulg_type(uidx->uovl, (uint32_t)i)); - if(!o) return; - ul2ul_idx_t *ul2 = &(uidx->uovl); - // if(o->is_del) { - // assert(o->cn == 0); - // } - - ul2ul_t *z; uint64_t k, qid = i, ct_n = 0, del_n = 0; assert(o->id == qid); - for (k = 0; k < o->n; k++) { - if(o->a[k].is_del) del_n++; - else if(o->a[k].is_ct) ct_n++; - assert(ul2->item_idx[o->a[k].hid] != (uint32_t)-1); - z = get_ul_o(ul2, ulg_id(*ul2, o->a[k].hid), ulg_type(*ul2, o->a[k].hid), - ulg_id(*ul2, qid), ulg_type(*ul2, qid)); - assert(z && z->hid == qid && z->is_del == o->a[k].is_del && z->is_ct == o->a[k].is_ct); - - // if(!(o->a[k].is_rev == z->is_rev && (*z).qs == o->a[k].ts && (*z).qe == o->a[k].te && - // (*z).ts == o->a[k].qs && (*z).te == o->a[k].qe)){ - // fprintf(stderr, "uln::%u[M::%s] fn::%u(%c), fqs::%u, fqe::%u, fts::%u, fte::%u, fdel::%u, rn::%u(%c), rqs::%u, rqe::%u, rts::%u, rte::%u, rdel::%u\n", ul2->uln, __func__, - // o->a[k].hid, "+-"[o->a[k].is_rev], o->a[k].qs, o->a[k].qe, o->a[k].ts, o->a[k].te, o->a[k].is_del, - // z->hid, "+-"[z->is_rev], z->qs, z->qe, z->ts, z->te, z->is_del); - // } - // if(o->a[k].is_rev == z->is_rev && (*z).qs == o->a[k].ts && (*z).qe == o->a[k].te && - // (*z).ts == o->a[k].qs && (*z).te == o->a[k].qe) { - // fprintf(stderr, "good::[M::%s] fn::%u(%c), fqs::%u, fqe::%u, fts::%u, fte::%u, rn::%u(%c), rqs::%u, rqe::%u, rts::%u, rte::%u\n", __func__, - // o->a[k].hid, "+-"[o->a[k].is_rev], o->a[k].qs, o->a[k].qe, o->a[k].ts, o->a[k].te, - // z->hid, "+-"[z->is_rev], z->qs, z->qe, z->ts, z->te); - // } else { - // fprintf(stderr, "bad::[M::%s] fn::%u(%c), fqs::%u, fqe::%u, fts::%u, fte::%u, rn::%u(%c), rqs::%u, rqe::%u, rts::%u, rte::%u\n", __func__, - // o->a[k].hid, "+-"[o->a[k].is_rev], o->a[k].qs, o->a[k].qe, o->a[k].ts, o->a[k].te, - // z->hid, "+-"[z->is_rev], z->qs, z->qe, z->ts, z->te); - // } - assert(o->a[k].is_rev == z->is_rev && (*z).qs == o->a[k].ts && (*z).qe == o->a[k].te && - (*z).ts == o->a[k].qs && (*z).te == o->a[k].qe); - if(kcn) assert(!o->a[k].is_del); - else assert(o->a[k].is_del); - } - - if(o->is_del) assert((ct_n + del_n) == o->n); -} - -void print_primary_ul_chain(ul_str_t *p_str, ul_vec_t *ul, ma_ug_t *ug) -{ - uc_block_t *z; uint64_t k, dd = 0; - if(p_str) { - for (k = 0; k < p_str->cn; k++) { - z = &(ul->bb.a[p_str->a[k]>>32]); - fprintf(stderr, "[M::%s::pk->%lu] utg%.6d%c(%c::len->%u), qs::%u, qe::%u, ts::%u, te::%u\n", __func__, k, - z->hid+1, "lc"[ug->u.a[z->hid].circ], "+-"[z->rev], ug->u.a[z->hid].len, - z->qs, z->qe, z->ts, z->te); - dd++; - } - } else { - for (k = 0; k < ul->bb.n; k++) { - z = &(ul->bb.a[k]); - if(!z->pchain) continue; - fprintf(stderr, "[M::%s::rk->%lu] utg%.6d%c(%c::len->%u), qs::%u, qe::%u, ts::%u, te::%u\n", __func__, k, - z->hid+1, "lc"[ug->u.a[z->hid].circ], "+-"[z->rev], ug->u.a[z->hid].len, - z->qs, z->qe, z->ts, z->te); - dd++; - } - } - - if(dd) fprintf(stderr, "*******************************************\n"); -} - -void push_integer_seq_exact(ul_vec_t *res, ma_ug_t *ug, uint64_t *seq, uint64_t seq_n, uint64_t *off, uint32_t tid) -{ - if(seq_n <= 0) return; - uint64_t k, v, ql, ul; uc_block_t *x; - // fprintf(stderr, "[M::%s::] old_len::%u, new_len::%u\n", __func__, res->rlen, (uint32_t)off[seq_n-1]); - res->rlen = (uint32_t)off[seq_n-1]; res->bb.n = 0; kv_resize(uc_block_t, res->bb, seq_n); - for (k = 0; k < seq_n; k++) { - v = (uint32_t)seq[k]; - kv_pushp(uc_block_t, res->bb, &x); - x->hid = v>>1; x->rev = !!(v&1); x->pchain = 1; x->el = 1; x->base = 0; - x->qs = off[k]>>32; x->qe = (uint32_t)off[k]; - ql = x->qe - x->qs; ul = ug->g->seq[x->hid].len; - if((ul == ql) || (k > 0 && k + 1 < seq_n)) { - x->ts = 0; x->te = ul; - } else { - // if(!(k == 0 || k + 1 == seq_n)){ - // fprintf(stderr, "[M::%s::] k::%lu, ql::%lu, ul::%lu\n", __func__, k, ql, ul); - // } - // assert(k == 0 || k + 1 == seq_n); - if(k == 0) { - if(x->rev) { - x->ts = 0; x->te = MIN(ql, ul); - } else { - x->ts = ul - MIN(ql, ul); x->te = ul; - } - } - - if(k + 1 == seq_n) { - if(!x->rev) { - x->ts = 0; x->te = MIN(ql, ul); - } else { - x->ts = ul - MIN(ql, ul); x->te = ul; - } - } - } - x->pidx = x->aidx = x->pdis = (uint32_t)-1; - if(k > 0 && (seq[k]&((uint64_t)(0x8000000000000000)))) { - x->pidx = k - 1; x->pdis = (seq[k]<<1)>>33; - res->bb.a[x->pidx].aidx = k; - } - } - assert(res->rlen == x->qe); - // res->rlen = ((uint32_t)-1) - tid; - // print_primary_ul_chain(NULL, res, ug); -} - -uint32_t double_check_gconnect(asg_t *g, uint32_t v, uint32_t w, uint32_t v2w_d) -{ - asg_arc_t *av = asg_arc_a(g, v); uint32_t nv = asg_arc_n(g, v), k; - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == w) break; - } - if(k < nv) return 1; - return 0; -} - - -void update_integer_seq(ul_resolve_t *uidx, integer_t *buf, uint32_t id, uint64_t *seq, uint64_t seq_n, uint32_t tid) -{ - // if((((uint32_t)-1) - uidx->idx->a[id].rlen) < asm_opt.thread_num) { - // fprintf(stderr, "id->%u, c_tid->%u, l_tid->%u\n", id, tid, (((uint32_t)-1) - uidx->idx->a[id].rlen)); - // exit(0); - // } - // assert(uidx->idx->a[id].rlen!=(uint32_t)-1); - // fprintf(stderr, "dd->%u\n", uidx->idx->a[id].dd); - // if(id != 1487) return; - if(seq_n <= 0) return; - buf->n_correct++; - ul_str_t *str = &(uidx->pstr.str.a[id]); uc_block_t *z; ul_chain_t sc, msc; - uint64_t k, i, pp; integer_aln_t *b; ma_ug_t *ug = uidx->l1_ug; - assert((seq[0]>>32) == (ug->g->seq[((uint32_t)seq[0])>>1].len)); - // fprintf(stderr, "\n[M::%s::id->%u] seq_n::%lu\n", __func__, id, seq_n); - // print_primary_ul_chain(str, &(uidx->idx->a[id]), ug); - if(seq_n == 1) { - pp = ug->g->seq[((uint32_t)seq[0])>>1].len; - push_integer_seq_exact(&(uidx->idx->a[id]), ug, seq, seq_n, &pp, tid); - return; - } - - buf->u.n = 0; - for (k = 0; k < str->cn; k++) {///old seq - pp = ((uint32_t)str->a[k])>>1; pp <<= 33; pp += ((uint64_t)(0x100000000)); - pp += (k<<1); pp += ((uint32_t)str->a[k])&1; - kv_push(uint64_t, buf->u, pp); - // fprintf(stderr, "ok::%lu, ov::%u\n", k, ((uint32_t)str->a[k])); - } - for (k = 0; k < seq_n; k++) {///new seq - pp = ((uint32_t)seq[k])>>1; pp <<= 33; - pp += (k<<1); pp += ((uint32_t)seq[k])&1; - kv_push(uint64_t, buf->u, pp); - // fprintf(stderr, "nk::%lu, nv::%u\n", k, ((uint32_t)seq[k])); - - // fprintf(stderr, ">>>>>>[M::%s::c_k->%lu] utg%.6d%c(%c::len->%u)\n", __func__, k, - // (((uint32_t)seq[k])>>1)+1, "lc"[ug->u.a[(((uint32_t)seq[k])>>1)].circ], - // "+-"[((uint32_t)seq[k])&1], ug->u.a[(((uint32_t)seq[k])>>1)].len); - } - - radix_sort_srt64(buf->u.a, buf->u.a + buf->u.n); - for (k = 0, buf->b.n = 0; k < buf->u.n; k++) { - if(buf->u.a[k]&((uint64_t)(0x100000000))) continue;///skip nodes in the old seq - for (i = k+1; (i < buf->u.n) && ((buf->u.a[k]>>33) == (buf->u.a[i]>>33)); i++) { - if((buf->u.a[i]&((uint64_t)(0x100000000))) == 0) continue;///skip nodes in the new seq - if((buf->u.a[k]&1) != (buf->u.a[i]&1)) continue;///ignore reverse alignment; - ///a[k] is the new seq (q); a[i] is old seq (t) - kv_pushp(integer_aln_t, buf->b, &b); - b->vq = ((buf->u.a[k]>>33)<<1) + (buf->u.a[k]&1); - b->tn_rev_qk = ((uint32_t)buf->u.a[k])>>1; - b->tk = ((uint32_t)buf->u.a[i])>>1; - z = &(uidx->idx->a[id].bb.a[str->a[b->tk]>>32]); - assert(((z->hid<<1)+z->rev)==(((buf->u.a[i]>>33)<<1) + (buf->u.a[i]&1))); - if((buf->u.a[k]&1) != (buf->u.a[i]&1)) { - b->tk = str->cn - b->tk - 1; - b->tn_rev_qk |= ((uint64_t)(0x100000000)); - } - b->sc = ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); - assert(b->sc > 0); - } - } - - msc.v = msc.s = msc.e = (uint32_t)-1; msc.sc = 0; - if(buf->b.n > 0) { - radix_sort_integer_aln_t_srt(buf->b.a, buf->b.a + buf->b.n); ///sorted by rev|qk - for (k = 1, i = 0; k <= buf->b.n; k++) { - // fprintf(stderr, "[M::%s::z->%lu] rev::%u, qk::%u, tk::%u\n", - // __func__, k-1, (uint32_t)(!!(buf->b.a[k-1].tn_rev_qk>>32)), (uint32_t)buf->b.a[k-1].tn_rev_qk, buf->b.a[k-1].tk); - if(k == buf->b.n || (buf->b.a[i].tn_rev_qk>>32) != (buf->b.a[k].tn_rev_qk>>32)) { - if(integer_chain(id, buf->b.a + i, k - i, i, buf, ug, NULL, NULL, &sc) && sc.v != (uint32_t)-1) { - if(msc.s == (uint32_t)-1 || msc.sc < sc.sc) msc = sc; - } - i = k; - } - } - } - // fprintf(stderr, "[M::%s::id->%u] seq_n::%lu, align_n::%u, buf->b.n::%u\n", - // __func__, id, seq_n, msc.e - msc.s, (uint32_t)buf->b.n); - - - uint64_t l, v, pd, uls, ule, p_ls, p_le, is_rev, qk, tk, bc; integer_aln_t *x; uc_block_t *tb; - buf->u.n = 0; kv_resize(uint64_t, buf->u, seq_n); - // assert((seq[0]>>32) == (ug->g->seq[((uint32_t)seq[0])>>1].len)); - for (k = l = 0, p_ls = p_le = (uint64_t)-1; k < seq_n; k++) { - v = (uint32_t)seq[k]; pd = (seq[k]<<1)>>33; - ule = l + pd; uls = ((ule >= ug->g->seq[v>>1].len)?(ule - ug->g->seq[v>>1].len):(0)); - bc = 0; - if(k > 0){ - bc = (!!(seq[k]&((uint64_t)(0x8000000000000000))));///if connected in the graph - if(bc) bc = double_check_gconnect(ug->g, ((uint32_t)seq[k])^1, ((uint32_t)seq[k-1])^1, pd); - // fprintf(stderr, "bc->%lu\n", bc); - } - if(p_ls != (uint64_t)-1) { - ///uls should uls>=p_ls && uls<=p_le - if(uls < p_ls) uls = p_ls; - if(bc && uls > p_le) uls = p_le; - ///ule should ule > p_le - if(ule <= p_le) ule = p_le + 1; - } - buf->u.a[k] = uls; buf->u.a[k] <<= 32; buf->u.a[k] |= ule; - p_ls = uls; p_le = ule; - l = ule; - // fprintf(stderr, "[init_k->%lu] uls::%lu, ule::%lu, pd::%lu\n", k, uls, ule, pd); - } - buf->u.n = seq_n; - - int64_t beg_nl, end_nl; ma_utg_t *u; - v = (uint32_t)seq[0]; u = &(ug->u.a[v>>1]); beg_nl = u->len; - v = (uint32_t)seq[seq_n-1]; u = &(ug->u.a[v>>1]); end_nl = u->len; - // fprintf(stderr, "+[M::%s] beg_nl::%lu, end_nl::%lu\n", __func__, beg_nl, end_nl); - - ///q -> new seq; t -> old seq - if(msc.s != (uint32_t)-1 && msc.e > msc.s) { - int64_t qoff, toff, beg_cut = 0, end_cut = 0; uint32_t r_end; - is_rev = ((buf->b.a[msc.s].tn_rev_qk>>32)&1); - - ///beg - x = &(buf->b.a[msc.s]); - qk = (uint32_t)(x->tn_rev_qk); tk = ((is_rev == 0)? (x->tk):(str->cn - x->tk - 1)); - tb = &(uidx->idx->a[id].bb.a[str->a[tk]>>32]); - if((!!tb->rev) == (!!is_rev)) { - if(tb->te == ug->u.a[tb->hid].len) r_end = 1; - else r_end = 0; - } else { - if(tb->ts == 0) r_end = 1; - else r_end = 0; - } - if(r_end) {///start from right end - qoff = (uint32_t)buf->u.a[qk]; toff = (is_rev?(uidx->idx->a[id].rlen-tb->qs):(tb->qe)); - } else {///start from left end - qoff = buf->u.a[qk]>>32; toff = (is_rev?(uidx->idx->a[id].rlen-tb->qe):(tb->qs)); - } - - if(qk == 0) toff = tb->te - tb->ts; - if(toff < qoff) beg_cut = qoff - toff; - // fprintf(stderr, "[M::%s::beg::is_rev->%lu] qoff::%ld, toff::%ld, r_end::%u\n", __func__, is_rev, qoff, toff, r_end); - - - ///end - x = &(buf->b.a[msc.e-1]); - qk = (uint32_t)(x->tn_rev_qk); tk = ((is_rev == 0)? (x->tk):(str->cn - x->tk - 1)); - tb = &(uidx->idx->a[id].bb.a[str->a[tk]>>32]); - if((!!tb->rev) == (!!is_rev)) { - if(tb->ts == 0) r_end = 0; - else r_end = 1; - } else { - if(tb->te == ug->u.a[tb->hid].len) r_end = 0; - else r_end = 1; - } - if(!r_end) { - qoff = l - (buf->u.a[qk]>>32); toff = (is_rev?(tb->qe):(uidx->idx->a[id].rlen-tb->qs)); - } else { - qoff = l - (uint32_t)(buf->u.a[qk]); toff = (is_rev?(tb->qs):(uidx->idx->a[id].rlen-tb->qe)); - } - if(qk+1==seq_n) toff = tb->te - tb->ts; - if(toff < qoff) end_cut = qoff - toff; - // fprintf(stderr, "[M::%s::end::is_rev->%lu] qoff::%ld, toff::%ld, r_end::%u\n", __func__, is_rev, qoff, toff, r_end); - - if(beg_cut > 0) { - v = (uint32_t)seq[0]; u = &(ug->u.a[v>>1]); - if(beg_cut < u->len) beg_cut = u->len - beg_cut; - else beg_cut = 0; - if(v&1) { - beg_nl = (int64_t)(Get_READ_LENGTH(R_INF, (u->a[0]>>33))); - } else { - beg_nl = (int64_t)(Get_READ_LENGTH(R_INF, (u->a[u->n-1]>>33))); - } - if(beg_cut > beg_nl) beg_nl = beg_cut; - if(beg_nl == u->len) beg_cut = 0; - else beg_cut = 1; - } - - - if(end_cut > 0) { - v = (uint32_t)seq[seq_n-1]; u = &(ug->u.a[v>>1]); - if(end_cut < u->len) end_cut = u->len - end_cut; - else end_cut = 0; - if(v&1) { - end_nl = Get_READ_LENGTH(R_INF, (u->a[u->n-1]>>33)); - } else { - end_nl = Get_READ_LENGTH(R_INF, (u->a[0]>>33)); - } - if(end_cut > end_nl) end_nl = end_cut; - if(end_nl == u->len) end_cut = 0; - else end_cut = 1; - } - // fprintf(stderr, "++[M::%s] beg_nl::%lu, end_nl::%lu\n", __func__, beg_nl, end_nl); - if(beg_cut || end_cut) { - k = 0; uls = 0; ule = beg_nl; - buf->u.a[k] = uls; buf->u.a[k] <<= 32; buf->u.a[k] |= ule; - l = ule; p_ls = uls; p_le = ule; - for (k += 1; k + 1 < seq_n; k++) { - v = (uint32_t)seq[k]; pd = (seq[k]<<1)>>33; - ule = l + pd; uls = ((ule >= ug->g->seq[v>>1].len)?(ule - ug->g->seq[v>>1].len):(0)); - bc = 0; - if(k > 0){ - bc = (!!(seq[k]&((uint64_t)(0x8000000000000000))));///if connected in the graph - if(bc) bc = double_check_gconnect(ug->g, ((uint32_t)seq[k])^1, ((uint32_t)seq[k-1])^1, pd); - // fprintf(stderr, "bc->%lu\n", bc); - } - if(p_ls != (uint64_t)-1) { - ///uls should uls>=p_ls && uls<=p_le - if(uls < p_ls) uls = p_ls; - if(bc && uls > p_le) uls = p_le; - ///ule should ule > p_le - if(ule <= p_le) ule = p_le + 1; - } - buf->u.a[k] = uls; buf->u.a[k] <<= 32; buf->u.a[k] |= ule; - p_ls = uls; p_le = ule; - l = ule; - } - - assert(k < seq_n); - v = (uint32_t)seq[k]; pd = (seq[k]<<1)>>33; - ule = l + pd; uls = ((ule >= ug->g->seq[v>>1].len)?(ule - ug->g->seq[v>>1].len):(0)); - ule = uls + end_nl; - bc = 0; - if(k > 0){ - bc = (!!(seq[k]&((uint64_t)(0x8000000000000000))));///if connected in the graph - if(bc) bc = double_check_gconnect(ug->g, ((uint32_t)seq[k])^1, ((uint32_t)seq[k-1])^1, pd); - // fprintf(stderr, "bc->%lu\n", bc); - } - if(p_ls != (uint64_t)-1) { - ///uls should uls>=p_ls && uls<=p_le - if(uls < p_ls) uls = p_ls; - if(bc && uls > p_le) uls = p_le; - ///ule should ule > p_le - if(ule <= p_le) ule = p_le + 1; - } - if(ule - uls < (uint64_t)end_nl) ule = uls + end_nl; - buf->u.a[k] = uls; buf->u.a[k] <<= 32; buf->u.a[k] |= ule; - p_ls = uls; p_le = ule; - l = ule; - } - } - - push_integer_seq_exact(&(uidx->idx->a[id]), ug, seq, seq_n, buf->u.a, tid); -} - -static void worker_integer_update(void *data, long i, int tid) // callback for kt_for() -{ - ul_resolve_t *uidx = (ul_resolve_t *)data; - integer_ml_t *sl = &(uidx->str_b); - integer_t *buf = &(sl->buf[i]);///normally should be buf = &(sl->buf[tid]) - uint64_t k, l; - for (k = 0, l = (uint64_t)-1; k <= buf->res_dump.n; k++) { - if(k == buf->res_dump.n || (buf->res_dump.a[k]&((uint64_t)(0xffffffff))) == ((uint64_t)(0xffffffff))) { - if(l != (uint64_t)-1 && k - l > 1) { - update_integer_seq(uidx, buf, buf->res_dump.a[l]>>32, buf->res_dump.a + l + 1, k - l - 1, tid); - } - l = k; - } - } -} - - -void integer_correction(ul_resolve_t *uidx) -{ - integer_ml_t sl; - init_integer_ml_t(&sl, uidx, asm_opt.thread_num); -} - -uint64_t clean_ul_re_correct_buf(ul_resolve_t *uidx, uint64_t clean_dump, uint64_t *tot_circle) -{ - uint64_t k, occ, n_circle; - for (k = occ = n_circle = 0; k < uidx->str_b.n_thread; k++) { - occ += uidx->str_b.buf[k].n_correct; - n_circle += uidx->str_b.buf[k].n_circle; - uidx->str_b.buf[k].n_correct = 0; - uidx->str_b.buf[k].n_circle = 0; - if(clean_dump) uidx->str_b.buf[k].res_dump.n = 0; - uidx->str_b.buf[k].q.n = 0; - uidx->str_b.buf[k].t.n = 0; - uidx->str_b.buf[k].b.n = 0; - uidx->str_b.buf[k].f.n = 0; - uidx->str_b.buf[k].p.n = 0; - uidx->str_b.buf[k].o.n = 0; - uidx->str_b.buf[k].u.n = 0; - uidx->str_b.buf[k].vis.n = 0; - uidx->str_b.buf[k].sc.n = 0; - uidx->str_b.buf[k].snp.n = 0; - } - (*tot_circle) = n_circle; - return occ; -} - - -void rebuid_idx(ul_resolve_t *uidx) -{ - uint32_t k; - free(uidx->idx->ridx.idx.a); free(uidx->idx->ridx.occ.a); - memset(&(uidx->idx->ridx), 0, sizeof((uidx->idx->ridx))); - filter_ul_ug(uidx->l1_ug); - gen_ul_vec_rid_t(uidx->idx, NULL, uidx->l1_ug); - update_ug_arch_ul_mul(uidx->l1_ug); - - free(uidx->pstr.idx.a); free(uidx->pstr.occ.a); - for (k = 0; k < uidx->pstr.str.n; k++) { - free(uidx->pstr.str.a[k].a); - } - free(uidx->pstr.str.a); - memset(&(uidx->pstr), 0, sizeof(uidx->pstr)); - init_ul_str_idx_t(uidx); -} - -void shrink_1b(ma_ug_t *ug, uc_block_t *z, uc_block_t *lim, uint32_t is_forward) -{ - if(z->ts != 0 || z->te != ug->g->seq[z->hid].len) return; - uc_block_t bc = *z; - if(z->ts + 1 < z->te && z->qs + 1 < z->qe) { - uint32_t off = get_offset_adjust(1, z->te-z->ts, z->qe-z->qs); - if(is_forward) { - if((!z->rev)) { - z->ts += 1; z->qs += off; - } else { - z->te -= 1; z->qs += off; - } - if((lim) && (!((z->qs <= lim->qs) && (z->qe <= lim->qe)))) *z = bc; - } else { - if((!z->rev)) { - z->te -= 1; z->qe -= off; - } else { - z->ts += 1; z->qe -= off; - } - if((lim) && (!((z->qs >= lim->qs) && (z->qe >= lim->qe)))) *z = bc; - } - if((ugl_cover_check(bc.ts, bc.te, &(ug->u.a[bc.hid]))) && - (!ugl_cover_check(z->ts, z->te, &(ug->u.a[z->hid])))) { - *z = bc; - } - } - -} - -void renew_ul_vec_t(ul_vec_t *x, ma_ug_t *ug) -{ - if(x->bb.n <= 0) return; - int64_t l, k, z, bn = x->bb.n, dd; int64_t qs = x->bb.a[0].qs, qe; - for (l = 0, k = 1, qs = 0; k <= bn; k++) { - if(k == bn || x->bb.a[k].pidx == (uint32_t)-1) { - if(k - l > 0) { - for (z = k - 1, dd = 0; z >= l; z--) { - if(z > l) { - assert(x->bb.a[z].pidx == z-1); - dd += x->bb.a[z].pdis; - } else { - assert(x->bb.a[z].pidx == (uint32_t)-1); - dd += ug->g->seq[x->bb.a[z].hid].len; - } - dd -= (int64_t)(ug->g->seq[x->bb.a[z].hid].len - (x->bb.a[z].te - x->bb.a[z].ts)); - } - if(dd < 0) dd = 0; - qe = qs + dd; - if(k < bn) { - dd = qe + (int64_t)(x->bb.a[k].qs) - (int64_t)(x->bb.a[k-1].qe); - if(dd < 0) dd = 0; - } - for (z = k - 1; z >= l; z--) { - qs = qe - (int64_t)(x->bb.a[z].te - x->bb.a[z].ts); - if(qs < 0) qs = 0; - x->bb.a[z].qs = qs; x->bb.a[z].qe = qe; - if(z > l) { - qe += (int64_t)(ug->g->seq[x->bb.a[z].hid].len - (x->bb.a[z].te - x->bb.a[z].ts)); - qe -= (int64_t)(x->bb.a[z].pdis); - if(qe < 0) qe = 0; - } - } - - if(k < bn) qs = dd; - } - l = k; - } - } - x->rlen = x->bb.a[bn-1].qe; -} - -void shrink_ul0(all_ul_t *uls, ul_str_t *str, uint64_t id, integer_t *buf, ma_ug_t *ug) -{ - uint32_t k, c_k, p_k, cv, pv, bl, i; uc_block_t *xi, *yi; buf->u.n = 0; nid_t *np = NULL; - asg_arc_t *av; uint32_t nv, s, e, m, d, mm, is_conn; uint64_t *z; ul_vec_t *x; - if(str->cn < 2) return; - for (k = 0, bl = 0, c_k = p_k = pv = (uint32_t)-1; k < str->cn; k++) { - xi = &(uls->a[id].bb.a[str->a[k]>>32]); is_conn = 0; - c_k = k; cv = ((uint32_t)str->a[k])^1; - assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[k])); - if(p_k != (uint32_t)-1) { - if(xi->pidx == (str->a[p_k]>>32)) { - av = asg_arc_a(ug->g, cv); nv = asg_arc_n(ug->g, cv); - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - if(av[i].v == pv) break; - } - if(i < nv) { - s = (uint32_t)av[i].ul; - if(s == xi->pdis) { - is_conn = 1; - } else { - d = (s>=xi->pdis?s-xi->pdis:xi->pdis-s); - mm = MAX(s, xi->pdis); - if((d <= (mm*0.08)) || (d <= 512)) is_conn = 1; - } - } - } else if(xi->pidx == (uint32_t)-1) { - is_conn = 1; - } - } - if(is_conn) { - is_conn = 0; assert(k); - yi = &(uls->a[id].bb.a[str->a[k-1]>>32]); - if((xi->qs >= yi->qs) && (xi->qe >= yi->qe)) is_conn = 1; - } - if(is_conn) { - bl++; - } else { - if(bl > 0) { - kv_pushp(uint64_t, buf->u, &z); - (*z) = k - 1 - bl; (*z) <<= 32; (*z) += bl + 1; - } - bl = 0; - } - p_k = c_k; pv = cv; - } - - if(bl > 0) { - kv_pushp(uint64_t, buf->u, &z); - (*z) = k - 1 - bl; (*z) <<= 32; (*z) += bl + 1; - } - // fprintf(stderr, "[M::%s::] buf->u.n::%u, str->cn::%u\n", __func__, buf->u.n, str->cn); - if(buf->u.n <= 0) { - str->cn = str->n = 0; - } else if(buf->u.n > 0) { - uint32_t pidx, aidx, pdis; - for (i = 0; i + 1 < buf->u.n; i++) { - s = (buf->u.a[i]>>32); e = s + ((uint32_t)buf->u.a[i]); - ///new id - kv_pushp(nid_t, uls->nid, &np); - np->n = uls->nid.a[id].n; MALLOC(np->a, np->n+1); - memcpy(np->a, uls->nid.a[id].a, np->n); np->a[np->n] = '\0'; - ///new ovlps - kv_pushp(ul_vec_t, *uls, &x); memset(x, 0, sizeof(*x)); - MALLOC(x->bb.a, e - s); x->bb.n = x->bb.m = e - s; - - for (k = s, m = 0; k < e; k++, m++) { - pidx = uls->a[id].bb.a[str->a[k]>>32].pidx; - aidx = uls->a[id].bb.a[str->a[k]>>32].aidx; - pdis = uls->a[id].bb.a[str->a[k]>>32].pdis; - x->bb.a[m] = uls->a[id].bb.a[str->a[k]>>32]; - if(k == s) { - x->bb.a[m].pidx = x->bb.a[m].pdis = (uint32_t)-1; - } else if(pidx != (uint32_t)-1) { - x->bb.a[m].pidx = m - 1; x->bb.a[m].pdis = pdis; - } - if(k + 1 == e) { - x->bb.a[m].aidx = (uint32_t)-1; - } else if(aidx != (uint32_t)-1) { - x->bb.a[m].aidx = m + 1; - } - } - x->bb.n = m; - assert(x->bb.n > 1); - - shrink_1b(ug, &(x->bb.a[0]), ((x->bb.n>=2)?&(x->bb.a[1]):(NULL)), 1); - shrink_1b(ug, &(x->bb.a[x->bb.n-1]), ((x->bb.n>=2)?&(x->bb.a[x->bb.n-2]):(NULL)), 0); - - d = x->bb.a[0].qs; - for (k = 0; k < x->bb.n; k++) { - x->bb.a[k].qs -= d; x->bb.a[k].qe -= d; - } - x->rlen = x->bb.a[x->bb.n-1].qe; - renew_ul_vec_t(x, ug); - } - - ///the last one; update in-place - s = (buf->u.a[i]>>32); e = s + ((uint32_t)buf->u.a[i]); x = &(uls->a[id]); - for (k = s, m = 0; k < e; k++, m++) { - pidx = x->bb.a[str->a[k]>>32].pidx; - aidx = x->bb.a[str->a[k]>>32].aidx; - pdis = x->bb.a[str->a[k]>>32].pdis; - x->bb.a[m] = x->bb.a[str->a[k]>>32]; - if(k == s) { - x->bb.a[m].pidx = x->bb.a[m].pdis = (uint32_t)-1; - } else if(pidx != (uint32_t)-1) { - x->bb.a[m].pidx = m - 1; x->bb.a[m].pdis = pdis; - } - if(k + 1 == e) { - x->bb.a[m].aidx = (uint32_t)-1; - } else if(aidx != (uint32_t)-1) { - x->bb.a[m].aidx = m + 1; - } - } - x->bb.n = m; - assert(x->bb.n > 1); - shrink_1b(ug, &(x->bb.a[0]), ((x->bb.n>=2)?&(x->bb.a[1]):(NULL)), 1); - shrink_1b(ug, &(x->bb.a[x->bb.n-1]), ((x->bb.n>=2)?&(x->bb.a[x->bb.n-2]):(NULL)), 0); - d = x->bb.a[0].qs; - for (k = 0; k < x->bb.n; k++) { - x->bb.a[k].qs -= d; x->bb.a[k].qe -= d; - } - x->rlen = x->bb.a[x->bb.n-1].qe; - renew_ul_vec_t(x, ug); - } -} - -void shrink_uls(ul_resolve_t *uidx) -{ - all_ul_t *uls = uidx->idx; uint64_t k, ul_n = uls->n; - for (k = 0; k < ul_n; k++) { - // fprintf(stderr, "+[M::%s::k->%lu] ul_n::%lu, uls->n::%u\n", __func__, k, ul_n, uls->n); - shrink_ul0(uls, &(uidx->pstr.str.a[k]), k, &(uidx->str_b.buf[0]), uidx->l1_ug); - // fprintf(stderr, "-[M::%s::k->%lu] ul_n::%lu, uls->n::%u\n", __func__, k, ul_n, uls->n); - } - rebuid_idx(uidx); -} - -void print_ul_seq(ul_resolve_t *uidx, uint64_t id) -{ - uint64_t i; ul_str_t *str = &(uidx->pstr.str.a[id]); ma_ug_t *ug = uidx->init_ug; - fprintf(stderr, "%.*s\tid::%lu\t", (int32_t)uidx->idx->nid.a[id].n, - uidx->idx->nid.a[id].a, id); - for (i = 0; i < str->cn; i++) { - fprintf(stderr, "utg%.6d%c(%c)\t", (((uint32_t)str->a[i])>>1)+1, - "lc"[ug->u.a[(((uint32_t)str->a[i])>>1)].circ], "+-"[(((uint32_t)str->a[i])&1)]); - } - fprintf(stderr,"\n"); -} - -void ul_re_correct(ul_resolve_t *uidx, uint64_t n_r) -{ - // print_ul_seq(uidx, 2062); print_ul_seq(uidx, 2093); - uint64_t k, occ, n_circle; ///uidx->str_b.n_thread = 1; - for (k = 0; k < n_r; k++) { - kt_for(uidx->str_b.n_thread, worker_integer_correction, uidx, uidx->idx->n); - occ = clean_ul_re_correct_buf(uidx, 0, &n_circle); - fprintf(stderr, "+[M::%s::round->%lu] # corrected UL reads::%lu, # circle UL reads::%lu\n", - __func__, k, occ, n_circle); - kt_for(uidx->str_b.n_thread, worker_integer_update, uidx, uidx->str_b.n_thread); - occ = clean_ul_re_correct_buf(uidx, 1, &n_circle); - fprintf(stderr, "-[M::%s::round->%lu] # corrected UL reads::%lu, # circle UL reads::%lu\n", - __func__, k, occ, n_circle); - rebuid_idx(uidx); - // print_ul_seq(uidx, 2062); print_ul_seq(uidx, 2093); - // exit(1); - } - - shrink_uls(uidx); -} - -void append_utg_es(ul_resolve_t *uidx) -{ - uint64_t k; ul2ul_idx_t *u2o = &(uidx->uovl); ul2ul_item_t *it; - for (k = 0; k < u2o->uln; k++) { - it = get_ul_ovlp(u2o, k, 1); - if(!it) continue; - assert(uidx->pstr.str.a[k].cn > 1); - integer_append_ug_ovlp(uidx, k, it, u2o); - } - - kt_for(uidx->str_b.n_thread, worker_integert_clean, uidx, u2o->tot);///all ul + ug - - for (k = 0; k < u2o->tot; k++) { - it = get_ul_ovlp(u2o, ulg_id(*u2o, k), ulg_type(*u2o, k)); - if(!it) continue; - integer_normalize_ovlp(uidx, k, it, u2o); - } - - kt_for(uidx->str_b.n_thread, worker_integert_clean, uidx, u2o->tot);///all ul + ug -} - - -void remove_integert_containment(ul_resolve_t *uidx, uint32_t keep_raw_utg) -{ - ul2ul_idx_t *u2o = &(uidx->uovl); ul2ul_item_t *o; - uint64_t k, kn = keep_raw_utg?u2o->uln:u2o->tot; - for (k = 0; k < kn; k++) { - o = get_ul_ovlp(u2o, ulg_id(*u2o, k), ulg_type(*u2o, k)); - if(!o) continue; - integer_containment_purge(uidx, k, o, u2o, keep_raw_utg); - } - - kt_for(uidx->str_b.n_thread, worker_integert_clean, uidx, u2o->tot);///all ul + ug -} - -void print_integert_ovlp_stat(ul2ul_idx_t *ul2) -{ - uint64_t i, k, occ_r = 0, occ_o = 0; ul2ul_item_t *o; - for (i = 0; i < ul2->uln; i++) { - o = get_ul_ovlp(ul2, ulg_id(*ul2, i), ulg_type(*ul2, i)); - if((!o) || (o->is_del)) continue; - occ_r++; - for (k = 0; k < o->n; k++) { - if(o->a[k].is_del || o->a[k].is_ct || (!ulg_type(*ul2, o->a[k].hid))) continue; - occ_o++; - } - } - fprintf(stderr, "[M::%s::] # UL reads::%lu, # UL ovlps::%lu\n", __func__, occ_r, occ_o); -} - -asg_t *integer_sg_gen(ul_resolve_t *uidx, uint64_t min_ovlp) -{ - ul2ul_idx_t *ul2 = &(uidx->uovl); ma_ug_t *ug = uidx->l1_ug; asg_t *raw_g = ug->g; ///uc_block_t *xi; - uint64_t i, k, is_del, v, w, nv, z; ul2ul_item_t *o, *ow; int32_t r; asg_arc_t t, *p; asg_arc_t *av; - // ul_str_t *str; - asg_t *g = asg_init(); - for (i = 0; i < ul2->tot; i++) { - is_del = 0; - o = get_ul_ovlp(ul2, ulg_id(*ul2, i), ulg_type(*ul2, i)); - if((!o) || (o->is_del)) is_del = 1; - asg_seq_set(g, i, ulg_len(*uidx, i), is_del); - g->seq[i].c = 0; - } - // CALLOC(g->seq_vis, g->n_seq*2); - - for (i = 0; i < ul2->tot; ++i) { - o = get_ul_ovlp(ul2, ulg_id(*ul2, i), ulg_type(*ul2, i)); - if((!o) || (o->is_del)) continue; - for (k = 0; k < o->n; k++) { - if(o->a[k].is_del || o->a[k].is_ct) continue; - r = integer_hit2arc(&(o->a[k]), ulg_len(*uidx, i), ulg_len(*uidx, o->a[k].hid), - ulg_occ(*uidx, i), ulg_occ(*uidx, o->a[k].hid), i, o->a[k].hid, min_ovlp, &t); - if (r >= 0) { - p = asg_arc_pushp(g); - *p = t; - } - } - if(i >= ul2->uln) {///is a node of ug - v = (i-ul2->uln)<<1; - nv = asg_arc_n(raw_g, v); av = asg_arc_a(raw_g, v); - for (z = 0; z < nv; z++) { - if(av[z].del) continue; - w = av[z].v + (ul2->uln<<1); - ow = get_ul_ovlp(ul2, ulg_id(*ul2, (w>>1)), ulg_type(*ul2, (w>>1))); - if((!ow) || (ow->is_del)) continue; - p = asg_arc_pushp(g); - *p = av[z]; p->ul += (((uint64_t)ul2->uln)<<33); p->v += (ul2->uln<<1); - } - - v = ((i-ul2->uln)<<1)+1; - nv = asg_arc_n(raw_g, v); av = asg_arc_a(raw_g, v); - for (z = 0; z < nv; z++) { - if(av[z].del) continue; - w = av[z].v + (ul2->uln<<1); - ow = get_ul_ovlp(ul2, ulg_id(*ul2, (w>>1)), ulg_type(*ul2, (w>>1))); - if((!ow) || (ow->is_del)) continue; - p = asg_arc_pushp(g); - *p = av[z]; p->ul += (((uint64_t)ul2->uln)<<33); p->v += (ul2->uln<<1); - } - } - // else { ///is a node of ug - // str = &(uidx->pstr.str.a[i]); - // if(str->cn > 0) { - // xi = &(uidx->idx->a[i].bb.a[str->a[0]>>32]); v = ((uint32_t)str->a[0])^1; - // ow = get_ul_ovlp(ul2, ulg_id(*ul2, (v>>1)), ulg_type(*ul2, (v>>1))); - // if((!ow) || (ow->is_del)) { - // nv = asg_arc_n(raw_g, v); av = asg_arc_a(raw_g, v); - // } - - // xi = &(uidx->idx->a[i].bb.a[str->a[str->cn-1]>>32]); v = ((uint32_t)str->a[str->cn-1]); - // ow = get_ul_ovlp(ul2, ulg_id(*ul2, (v>>1)), ulg_type(*ul2, (v>>1))); - // if((!ow) || (ow->is_del)) { - - // } - // } - // } - } - asg_cleanup(g); - g->r_seq = g->n_seq; - // fprintf(stderr, "[M::%s::] # ig nodes::%u, # ig archs::%u\n", __func__, g->n_seq, g->n_arc); - return g; -} - -inline uint64_t get_ul_occ(ul_resolve_t *uidx, uint64_t id) -{ - return uidx->uovl.cc.uc[id]; -} - -inline void get_iug_u_raw_occ(ul_resolve_t *uidx, uint32_t id, uint32_t *ul_occ, uint32_t *raw_ug_occ) -{ - if(ul_occ) *ul_occ = uidx->uovl.cc.raw_uc[id]; - if(raw_ug_occ) *raw_ug_occ = uidx->uovl.i_ug->u.a[id].n - uidx->uovl.cc.raw_uc[id]; -} - -inline asg_arc_t* get_specfic_edge(asg_t *g, uint32_t v, uint32_t w) -{ - asg_arc_t *av = asg_arc_a(g, v); uint32_t nv = asg_arc_n(g, v), k; - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == w) break; - } - - if(k < nv) return (&av[k]); - return NULL; -} - - -void gen_ul_seq(ul_resolve_t *uidx, uint64_t iug_id, asgc8_v * res) -{ - ul2ul_idx_t *idx = &(uidx->uovl); ma_ug_t *raw = uidx->l1_ug; uint64_t k, m, s, e, ol, rev, Ns; - uinfo_srt_warp_t *seq = &(idx->cc.iug_a[iug_id]); ma_utg_t *ru; asg_arc_t *z; - for (k = res->n = 0; k < seq->n; k++) { - s = seq->a[k].s; e = seq->a[k].e; rev = seq->a[k].v&1; - ru = &(raw->u.a[seq->a[k].v>>1]); Ns = 0; - if(k + 1 < seq->n) { - z = get_specfic_edge(raw->g, seq->a[k].v, seq->a[k+1].v); - if(z) { - ol = z->ol; - if(!rev) { - // assert(seq->a[k].e == ru->len); - e = (ru->len > ol)?(ru->len-ol):(0); - } else { - // assert(seq->a[k].s == 0); - s = ol; - } - } else { - Ns = 50; - } - } - if(s < e) { - kv_resize(char, (*res), res->n + e - s); - retrieve_u_seq(NULL, res->a + res->n, ru, rev, (rev)?(ru->len-e):(s), e - s, NULL); - res->n += e - s; - } - - if(Ns) { - kv_resize(char, (*res), res->n + Ns); - for (m = 0; m < Ns; m++) res->a[res->n++] = 'N'; - } - } - - kv_push(char, *res, '\0'); - // fprintf(stderr, "[M::%s::iug_id->%lu] # u->len::%u, # res->n::%u, # strlen(res->a)::%u\n", - // __func__, iug_id, idx->i_ug->u.a[iug_id].len, (uint32_t)res->n, (uint32_t)strlen(res->a)); -} - - -void ma_integer_ug_print0(const ma_ug_t *ug, ul_resolve_t *uidx, int print_seq, const char* prefix, FILE *fp, uint32_t is_seq) -{ - uint32_t i, j, l, x; ma_utg_t *p, *s; ul2ul_idx_t *idx = &(uidx->uovl); - char name[32]; uinfo_srt_warp_t *seq; asgc8_v t; kv_init(t); //uint64_t tot = 0; - for (i = 0; i < ug->u.n; ++i) { // the Segment lines in GFA - p = &ug->u.a[i]; - if(p->m == 0) continue; - if(ug->g && ug->g->seq[i].del) continue; - sprintf(name, "%s%.6d%c", prefix, i + 1, "lc"[p->circ]); - if(is_seq) { - gen_ul_seq(uidx, i, &t); - fprintf(fp, "S\t%s\t%s\tLN:i:%d\trd:i:%lu\n", name, t.a, p->len, get_ul_occ(uidx, i)); - } else { - fprintf(fp, "S\t%s\t*\tLN:i:%d\trd:i:%lu\n", name, p->len, get_ul_occ(uidx, i)); - } - // tot += p->len; - - for (j = l = 0; j < p->n; j++) { - if(p->a[j] != (uint64_t)-1) { - x = p->a[j]>>33; - if(ulg_type(uidx->uovl, x)) {//read - x = ulg_id(uidx->uovl, x); - fprintf(fp, "A\t%s\t%d\t%c\t%.*s\t%d\t%d\tid:i:%d\tHG:A:*\n", name, l, "+-"[p->a[j]>>32&1], - (int32_t)uidx->idx->nid.a[x].n, uidx->idx->nid.a[x].a, 0, uidx->idx->a[x].rlen, x); - } else { ///node - x = ulg_id(uidx->uovl, x); s = &(uidx->init_ug->u.a[x]); - fprintf(fp, "A\t%s\t%d\t%c\tutg%.6d%c\t%d\t%d\tid:i:%d\tHG:A:*\n", name, l, "+-"[p->a[j]>>32&1], - x + 1, "lc"[s->circ], 0, s->len, x); - } - } - else - { - fprintf(fp, "A\t%s\t%d\t*\t*\t*\t*\tid:i:*\tHG:A:*\n", name, l); - } - l += (uint32_t)p->a[j]; - } - - seq = &(idx->cc.iug_a[i]); - for (j = 0; j < seq->n; j++) { - x = seq->a[j].v>>1; s = &(uidx->init_ug->u.a[x]); - fprintf(fp, "U\t%s\t%c\tutg%.6d%c\t%d\t%d\tHG:A:*\n", - name, "+-"[seq->a[j].v&1], x + 1, "lc"[s->circ], seq->a[j].s, seq->a[j].e); - } - - } - - if(ug->g) - { - asg_arc_t* au = NULL; - uint32_t nu, u, v; - for (i = 0; i < ug->u.n; ++i) { - if(ug->u.a[i].m == 0) continue; - if(ug->u.a[i].circ) - { - fprintf(fp, "L\t%s%.6dc\t+\t%s%.6dc\t+\t%dM\tL1:i:%d\n", - prefix, i+1, prefix, i+1, 0, ug->u.a[i].len); - fprintf(fp, "L\t%s%.6dc\t-\t%s%.6dc\t-\t%dM\tL1:i:%d\n", - prefix, i+1, prefix, i+1, 0, ug->u.a[i].len); - } - u = i<<1; - au = asg_arc_a(ug->g, u); - nu = asg_arc_n(ug->g, u); - for (j = 0; j < nu; j++) - { - if(au[j].del) continue; - v = au[j].v; - fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", - prefix, (u>>1)+1, "lc"[ug->u.a[u>>1].circ], "+-"[u&1], - prefix, (v>>1)+1, "lc"[ug->u.a[v>>1].circ], "+-"[v&1], au[j].ol, asg_arc_len(au[j]), au[j].ou); - } - - - u = (i<<1) + 1; - au = asg_arc_a(ug->g, u); - nu = asg_arc_n(ug->g, u); - for (j = 0; j < nu; j++) - { - if(au[j].del) continue; - v = au[j].v; - fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", - prefix, (u>>1)+1, "lc"[ug->u.a[u>>1].circ], "+-"[u&1], - prefix, (v>>1)+1, "lc"[ug->u.a[v>>1].circ], "+-"[v&1], au[j].ol, asg_arc_len(au[j]), au[j].ou); - } - } - } - kv_destroy(t); - // fprintf(stderr, "[M::%s::] tot::%lu\n", __func__, tot); -} - - -void gen_u2g_seq(ul_resolve_t *uidx, uint64_t iug_id, asgc8_v * res) -{ - ul2ul_idx_t *idx = &(uidx->uovl); ma_ug_t *raw = uidx->l1_ug; uint64_t k, m, s, e, ol, rev, Ns; - uinfo_srt_warp_t *seq = &(idx->cc.iug_a[iug_id]); ma_utg_t *ru; asg_arc_t *z; - for (k = res->n = 0; k < seq->n; k++) { - s = seq->a[k].s; e = seq->a[k].e; rev = seq->a[k].v&1; - ru = &(raw->u.a[seq->a[k].v>>1]); Ns = 0; - if(k + 1 < seq->n) { - z = get_specfic_edge(raw->g, seq->a[k].v, seq->a[k+1].v); - if(z) { - ol = z->ol; - if(!rev) { - // assert(seq->a[k].e == ru->len); - e = (ru->len > ol)?(ru->len-ol):(0); - } else { - // assert(seq->a[k].s == 0); - s = ol; - } - } else { - Ns = 50; - } - } - if(s < e) { - kv_resize(char, (*res), res->n + e - s); - retrieve_u_seq(NULL, res->a + res->n, ru, rev, (rev)?(ru->len-e):(s), e - s, NULL); - res->n += e - s; - } - - if(Ns) { - kv_resize(char, (*res), res->n + Ns); - for (m = 0; m < Ns; m++) res->a[res->n++] = 'N'; - } - } - - kv_push(char, *res, '\0'); - // fprintf(stderr, "[M::%s::iug_id->%lu] # u->len::%u, # res->n::%u, # strlen(res->a)::%u\n", - // __func__, iug_id, idx->i_ug->u.a[iug_id].len, (uint32_t)res->n, (uint32_t)strlen(res->a)); -} - - -void output_integer_graph(ul_resolve_t *uidx, ma_ug_t *iug, const char *nn, uint32_t is_seq) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+50); - sprintf(gfa_name, "%s.integer.noseq.gfa", nn); - FILE* fp = fopen(gfa_name, "w"); free(gfa_name); - if (!fp) return; - ma_integer_ug_print0(iug, uidx, 0, "itg", fp, is_seq); - fclose(fp); -} - - -void print_raw_uls_seq(ul_resolve_t *uidx, const char *nn) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+70); - sprintf(gfa_name, "%s.raw.integer.seq.log", nn); - FILE* fp = fopen(gfa_name, "w"); free(gfa_name); - if (!fp) return; - ma_ug_t *ug = uidx->init_ug; all_ul_t *aln = uidx->idx; - uint64_t id; uc_block_t *a = NULL; int64_t k, a_n; - for (id = 0; id < aln->n; id++) { - a = aln->a[id].bb.a; a_n = aln->a[id].bb.n; k = 0; - if(a_n == 0) continue; - fprintf(fp,"%.*s\tid::%lu\t", (int32_t)aln->nid.a[id].n, aln->nid.a[id].a, id); - // for (k = 0; k < a_n && ug_occ_w(a[k].ts, a[k].te, &(ug->u.a[a[k].hid])) == 0; k++); - for (; k < a_n; k++) { - // if(ug_occ_w(a[k].ts, a[k].te, &(ug->u.a[a[k].hid])) == 0) break; - fprintf(fp, "utg%.6d%c(%c)(n::%lu)\t", a[k].hid + 1, "lc"[ug->u.a[a[k].hid].circ], "+-"[a[k].rev], ug_occ_w(a[k].ts, a[k].te, &(ug->u.a[a[k].hid]))); - } - fprintf(fp,"\n"); - } - fclose(fp); -} - -void print_raw_uls_aln(ul_resolve_t *uidx, const char *nn) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+70); - sprintf(gfa_name, "%s.raw.aln.log", nn); - FILE* fp = fopen(gfa_name, "w"); free(gfa_name); - if (!fp) return; - ma_ug_t *ug = uidx->init_ug; all_ul_t *aln = uidx->idx; - uint64_t id; uc_block_t *a = NULL; int64_t k, a_n; - for (id = 0; id < aln->n; id++) { - a = aln->a[id].bb.a; a_n = aln->a[id].bb.n; k = 0; - if(a_n == 0) continue; - fprintf(fp,"%.*s\tid::%lu\tdd::%u\t", (int32_t)aln->nid.a[id].n, aln->nid.a[id].a, id, aln->a[id].dd); - // for (k = 0; k < a_n && ug_occ_w(a[k].ts, a[k].te, &(ug->u.a[a[k].hid])) == 0; k++); - for (; k < a_n; k++) { - // if(ug_occ_w(a[k].ts, a[k].te, &(ug->u.a[a[k].hid])) == 0) break; - fprintf(fp, "utg%.6d%c(%c)q::[%u, %u)\t", a[k].hid + 1, "lc"[ug->u.a[a[k].hid].circ], "+-"[a[k].rev], a[k].qs, a[k].qe); - } - fprintf(fp,"\n"); - } - fclose(fp); -} - - -void print_uls_seq(ul_resolve_t *uidx, const char *nn) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+50); - sprintf(gfa_name, "%s.integer.seq.log", nn); - FILE* fp = fopen(gfa_name, "w"); free(gfa_name); - if (!fp) return; - uint64_t k, i; all_ul_t *uls = uidx->idx; ul2ul_item_t *o; - ul_str_idx_t *str_idx = &(uidx->pstr); ma_ug_t *ug = uidx->init_ug; - for (k = 0; k < uls->n; k++) { - if(str_idx->str.a[k].cn < 2) continue; - o = get_ul_ovlp(&(uidx->uovl), ulg_id(uidx->uovl, k), ulg_type(uidx->uovl, k)); - if(!o) continue; - fprintf(fp,"%.*s\tid::%lu\tdel::%u\t", (int32_t)uidx->idx->nid.a[k].n, uidx->idx->nid.a[k].a, k, o->is_del); - for (i = 0; i < str_idx->str.a[k].cn; i++) { - fprintf(fp, "utg%.6d%c(%c)\t", (((uint32_t)str_idx->str.a[k].a[i])>>1)+1, - "lc"[ug->u.a[(((uint32_t)str_idx->str.a[k].a[i])>>1)].circ], "+-"[(((uint32_t)str_idx->str.a[k].a[i])&1)]); - } - fprintf(fp,"\n"); - } - fclose(fp); -} - - -void print_uls_ovs(ul_resolve_t *uidx, const char *nn) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+50); - sprintf(gfa_name, "%s.integer.ovlp.log", nn); - FILE* fp = fopen(gfa_name, "w"); free(gfa_name); - if (!fp) return; - uint64_t i, k, qv, tv; ma_ug_t *ug = uidx->l1_ug; ul2ul_idx_t *ul2 = &(uidx->uovl); ul2ul_item_t *o; - for (i = 0; i < ul2->uln; ++i) { - o = get_ul_ovlp(ul2, ulg_id(*ul2, i), ulg_type(*ul2, i)); - if(!o) continue; - for (k = 0; k < o->n; k++) { - qv = i; tv = o->a[k].hid; - if(ulg_type(uidx->uovl, qv)) {//ul read - qv = ulg_id(uidx->uovl, qv); - fprintf(fp, "%.*s(id::%lu)\t%u\t%u(i::%u)\t%u(i::%u)\t%c\t", (int32_t)uidx->idx->nid.a[qv].n, uidx->idx->nid.a[qv].a, - i, uidx->idx->a[qv].rlen, o->a[k].qs, o->a[k].qs_k, o->a[k].qe, o->a[k].qe_k, "+-"[o->a[k].is_rev]); - } else {///ug node - qv = ulg_id(uidx->uovl, qv); - fprintf(fp, "utg%.6d%c(id::%lu)\t%u\t%u(i::%u)\t%u(i::%u)\t%c\t", (int32_t)qv + 1, "lc"[ug->u.a[qv].circ], - i, ug->u.a[qv].len, o->a[k].qs, o->a[k].qs_k, o->a[k].qe, o->a[k].qe_k, "+-"[o->a[k].is_rev]); - } - - if(ulg_type(uidx->uovl, tv)) {//ul read - tv = ulg_id(uidx->uovl, tv); - fprintf(fp, "%.*s(id::%u)\t%u\t%u(i::%u)\t%u(i::%u)\t", (int32_t)uidx->idx->nid.a[tv].n, uidx->idx->nid.a[tv].a, - o->a[k].hid, uidx->idx->a[tv].rlen, o->a[k].ts, o->a[k].ts_k, o->a[k].te, o->a[k].te_k); - - } else { - tv = ulg_id(uidx->uovl, tv); - fprintf(fp, "utg%.6d%c(id::%u)\t%u\t%u(i::%u)\t%u(i::%u)\t\t", (int32_t)tv + 1, "lc"[ug->u.a[tv].circ], - o->a[k].hid, ug->u.a[tv].len, o->a[k].ts, o->a[k].ts_k, o->a[k].te, o->a[k].te_k); - } - - fprintf(fp, "del::%u\tct::%u\n", o->a[k].is_del, o->a[k].is_ct); - } - } - fclose(fp); -} - - - -uint64_t gen_srt_cov_interval(uint64_t *b, uint64_t b_n) -{ - uint64_t i, m, start, end; int64_t dp, old_dp; - radix_sort_srt64(b, b + b_n); - for (i = m = 0, dp = 0, start = 0; i < b_n; ++i) { - old_dp = dp; - if (b[i]&1) --dp; - else ++dp; - - if (old_dp < 1 && dp >= 1) {///old_dp < dp, b.a[j] is qs - start = b[i]>>1; - } else if (old_dp >= 1 && dp < 1){ - end = b[i]>>1; - b[m] = start; b[m] <<= 32; b[m] += end; m++; - } - } - - return m; -} - -inline uint64_t get_remove_hifi_occ_back(ul_resolve_t *uidx, uint64_t thres, uint64_t *v_a, uint64_t v_n, asg64_v *buf) -{ - ul2ul_idx_t *idx = &(uidx->uovl); - ma_ug_t *iug = idx->i_ug, *raw = uidx->l1_ug; - uint64_t k, l, z, m, p, *raw_a, raw_n, raw_id, iug_id, iug_off, del_n, keep_ns[2], dup_raw, n_mask, pn, fn, full_del, is, ie; - uinfo_srt_warp_t *iu; uint64_t *s_a, s_n, ms, me; uinfo_srt_t *ps; - for (k = del_n = fn = 0, buf->n = dup_raw = 0; k < v_n; k++) { - iu = &(idx->cc.iug_a[v_a[k]]); ///integer unitigs - for (z = 0; z < iu->n; z++) { - raw_id = (iu->a[z].v>>1); - raw_a = idx->cc.iug_b + idx->cc.iug_idx[raw_id]; - raw_n = idx->cc.iug_idx[raw_id+1] - idx->cc.iug_idx[raw_id]; - assert(raw_n > 0); - for (m = keep_ns[0] = keep_ns[1] = 0, pn = buf->n, n_mask = 0; m < raw_n; m++) { - iug_id = raw_a[m]>>32; iug_off = (uint32_t)raw_a[m]; - if(iug->g->seq[iug_id].del) continue; - if(raw_a[m]&((uint64_t)(0x8000000000000000))) { - n_mask++; - continue; - } - if(iug_id == v_a[k] && iug_off == z) {///query itself - raw_a[m] |= ((uint64_t)(0x8000000000000000)); - p = (uint32_t)-1; p <<= 32; p += idx->cc.iug_idx[raw_id] + m; - kv_push(uint64_t, *buf, p); - } else { - if(!(idx->cc.iug_a[iug_id].a[iug_off].v&1)) { - keep_ns[0] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, keep_ns[0]); - } else { - keep_ns[1] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, keep_ns[1]); - } - } - } - assert(buf->n == pn + 1); - if(keep_ns[0] + keep_ns[1] >= raw->u.a[raw_id].n) { - keep_ns[0] = keep_ns[1] = raw->u.a[raw_id].n; - } - - is = keep_ns[0]; ie = raw->u.a[raw_id].n - keep_ns[1];///[is, ie) -> uncovered coordinates - if(ie > is) { - if(!(iu->a[z].v&1)) { - ms = 0; me = iu->a[z].n; - } else { - ms = raw->u.a[raw_id].n - iu->a[z].n; me = raw->u.a[raw_id].n; - } - if(MAX(is, ms) < MIN(ie, me)) { - del_n += MIN(ie, me) - MAX(is, ms); - buf->a[pn] <<= 32; buf->a[pn] >>= 32; buf->a[pn] |= (raw_id<<32); fn++; - if(n_mask) dup_raw = 1; - } - } - } - } - - if(del_n > thres && dup_raw) { - radix_sort_srt64(buf->a, buf->a + buf->n); del_n = 0; - for (l = 0, k = 1; k <= fn; k++) { - if(k == fn || (buf->a[k]>>32) != (buf->a[l]>>32)) { - raw_id = (buf->a[l]>>32); pn = buf->n; - raw_a = idx->cc.iug_b + idx->cc.iug_idx[raw_id]; - raw_n = idx->cc.iug_idx[raw_id+1] - idx->cc.iug_idx[raw_id]; - assert(raw_n > 0); - for (m = full_del = 0; m < raw_n; m++) { - iug_id = raw_a[m]>>32; iug_off = (uint32_t)raw_a[m]; - if(iug->g->seq[iug_id].del) continue; - if(raw_a[m]&((uint64_t)(0x8000000000000000))) { - kv_push(uint64_t, *buf, (idx->cc.iug_a[iug_id].a[iug_off].s<<1)); - kv_push(uint64_t, *buf, (idx->cc.iug_a[iug_id].a[iug_off].e<<1)+1); - if(idx->cc.iug_a[iug_id].a[iug_off].s == 0 && - idx->cc.iug_a[iug_id].a[iug_off].e == raw->u.a[raw_id].len) { - full_del = 1; break; - } - } - } - - s_a = buf->a + buf->n; s_n = buf->n - pn; - assert(s_n > 0); - - if(s_n > 2 && full_del == 0) { - s_n = gen_srt_cov_interval(s_a, s_n); - } else if(full_del) {///an interval has already cover the whole unitig - s_a[0] = raw->u.a[raw_id].len; s_n = 1; - } else {///sn == 2; - s_a[0] >>= 1; s_a[0] <<= 32; s_a[0] += (s_a[1]>>1); s_n = 1; - } - - - for (m = full_del = 0; m < raw_n && full_del < s_n; m++) { - iug_id = raw_a[m]>>32; iug_off = (uint32_t)raw_a[m]; - if(iug->g->seq[iug_id].del) continue; - if(raw_a[m]&((uint64_t)(0x8000000000000000))) continue; - ps = &(idx->cc.iug_a[iug_id].a[iug_off]); - for (z = 0; z < s_n; z++) { - if(s_a[z] == ((uint64_t)-1)) continue; - is = s_a[z]>>32; ie = (uint32_t)s_a[z]; - ms = MAX(is, ps->s); me = MIN(ie, ps->e); - if(ms >= me) continue; - ///[ms, me) is unlikely to be contained in the [is, ie) - assert(ms == is || me == ie); - if(ms == is) is = me; - else if(me == ie) ie = ms; - if(is >= ie) { - s_a[z] = ((uint64_t)-1); full_del++; - } else { - s_a[z] = is; s_a[z] <<= 32; s_a[z] += ie; - } - } - } - - for (z = 0; z < s_n; z++) { - if(s_a[z] == ((uint64_t)-1)) continue; - is = s_a[z]>>32; ie = (uint32_t)s_a[z]; - del_n += ug_occ_w(is, ie, &(raw->u.a[raw_id])); - } - if(del_n > thres) break; - l = k; buf->n = pn; - } - } - } - - for (k = 0; k < buf->n; k++) { - assert(idx->cc.iug_b[(uint32_t)buf->a[k]]&((uint64_t)(0x8000000000000000))); - idx->cc.iug_b[(uint32_t)buf->a[k]] <<= 1; idx->cc.iug_b[(uint32_t)buf->a[k]] >>= 1; - } - - - return ((del_n > thres)?0:1); -} - - -inline uint64_t get_remove_hifi_occ(ul_resolve_t *uidx, uint64_t thres, uint64_t *v_a, uint64_t v_n, asg64_v *buf, uint32_t *del_occ) -{ - ul2ul_idx_t *idx = &(uidx->uovl); - ma_ug_t *iug = idx->i_ug, *raw = uidx->l1_ug; - uint64_t k, l, z, m, p, *raw_a, raw_n, raw_id, iug_id, iug_off, del_n, keep_ns[2], del_ns[2], dup_raw, n_mask, pn, fn, is, ie; - uinfo_srt_warp_t *iu; uint64_t ms, me; - for (k = del_n = fn = 0, buf->n = dup_raw = 0; k < v_n; k++) { - iu = &(idx->cc.iug_a[v_a[k]>>1]); ///integer unitigs - for (z = 0; z < iu->n; z++) { - raw_id = (iu->a[z].v>>1); - raw_a = idx->cc.iug_b + idx->cc.iug_idx[raw_id]; - raw_n = idx->cc.iug_idx[raw_id+1] - idx->cc.iug_idx[raw_id]; - assert(raw_n > 0); - for (m = keep_ns[0] = keep_ns[1] = 0, pn = buf->n, n_mask = 0; m < raw_n; m++) { - iug_id = (raw_a[m]<<1)>>33; iug_off = (uint32_t)raw_a[m]; - // if(iug_id >= iug->g->n_seq){ - // fprintf(stderr, ">>>[M::%s::] v_a[%lu]>>1::%lu, raw_id::%lu, raw_n::%lu, m::%lu, raw_a[m]::%lu, uidx->uovl.cc.iug_b[455]::%lu, iug_id::%lu, iug_off::%lu, iug->g->n_seq::%u\n", __func__, - // k, v_a[k]>>1, raw_id, raw_n, m, raw_a[m], uidx->uovl.cc.iug_b[455], iug_id, iug_off, (uint32_t)iug->g->n_seq); - // } - if(iug->g->seq[iug_id].del) continue; - if(raw_a[m]&((uint64_t)(0x8000000000000000))) { - n_mask++; - continue; - } - if(iug_id == (v_a[k]>>1) && iug_off == z) {///query itself - raw_a[m] |= ((uint64_t)(0x8000000000000000)); - p = (uint32_t)-1; p <<= 32; p += idx->cc.iug_idx[raw_id] + m; - kv_push(uint64_t, *buf, p); - } else { - if(!(idx->cc.iug_a[iug_id].a[iug_off].v&1)) { - keep_ns[0] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, keep_ns[0]); - } else { - keep_ns[1] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, keep_ns[1]); - } - } - } - assert(buf->n == pn + 1); - if(keep_ns[0] + keep_ns[1] >= raw->u.a[raw_id].n) { - keep_ns[0] = keep_ns[1] = raw->u.a[raw_id].n; - } - - is = keep_ns[0]; ie = raw->u.a[raw_id].n - keep_ns[1];///[is, ie) -> uncovered coordinates - if(ie > is) { - if(!(iu->a[z].v&1)) { - ms = 0; me = iu->a[z].n; - } else { - ms = raw->u.a[raw_id].n - iu->a[z].n; me = raw->u.a[raw_id].n; - } - if(MAX(is, ms) < MIN(ie, me)) { - del_n += MIN(ie, me) - MAX(is, ms); - buf->a[pn] <<= 32; buf->a[pn] >>= 32; buf->a[pn] |= (raw_id<<32); fn++; - if(n_mask) dup_raw = 1; - } - } - } - } - - if(del_n > thres && dup_raw) { - radix_sort_srt64(buf->a, buf->a + buf->n); del_n = 0; - for (l = 0, k = 1; k <= fn; k++) { - if(k == fn || (buf->a[k]>>32) != (buf->a[l]>>32)) { - raw_id = (buf->a[l]>>32); - raw_a = idx->cc.iug_b + idx->cc.iug_idx[raw_id]; - raw_n = idx->cc.iug_idx[raw_id+1] - idx->cc.iug_idx[raw_id]; - assert(raw_n > 0); - for (m = del_ns[0] = del_ns[1] = keep_ns[0] = keep_ns[1] = 0; m < raw_n; m++) { - iug_id = (raw_a[m]<<1)>>33; iug_off = (uint32_t)raw_a[m]; - if(iug->g->seq[iug_id].del) continue; - if(raw_a[m]&((uint64_t)(0x8000000000000000))) { - if(!(idx->cc.iug_a[iug_id].a[iug_off].v&1)) { - del_ns[0] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, del_ns[0]); - } else { - del_ns[1] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, del_ns[1]); - } - } else { - if(!(idx->cc.iug_a[iug_id].a[iug_off].v&1)) { - keep_ns[0] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, keep_ns[0]); - } else { - keep_ns[1] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, keep_ns[1]); - } - } - } - assert(del_ns[0] + del_ns[1] > 0); - if(keep_ns[0] + keep_ns[1] >= raw->u.a[raw_id].n) { - keep_ns[0] = keep_ns[1] = raw->u.a[raw_id].n; - } - - - is = keep_ns[0]; ie = raw->u.a[raw_id].n - keep_ns[1];///[is, ie) -> uncovered coordinates - if(ie > is) { - if(del_ns[0] + del_ns[1] >= raw->u.a[raw_id].n) { - del_n += ie - is; - } else { - ms = 0; me = del_ns[0]; - if(ms < me && MAX(is, ms) < MIN(ie, me)) { - del_n += MIN(ie, me) - MAX(is, ms); - } - - ms = raw->u.a[raw_id].n - del_ns[1]; me = raw->u.a[raw_id].n; - if(ms < me && MAX(is, ms) < MIN(ie, me)) { - del_n += MIN(ie, me) - MAX(is, ms); - } - } - } - if(del_n > thres) break; - l = k; - } - } - } - - for (k = 0; k < buf->n; k++) { - assert(idx->cc.iug_b[(uint32_t)buf->a[k]]&((uint64_t)(0x8000000000000000))); - idx->cc.iug_b[(uint32_t)buf->a[k]] <<= 1; idx->cc.iug_b[(uint32_t)buf->a[k]] >>= 1; - } - // fprintf(stderr, "*[M::%s::] del_n::%lu\n", __func__, del_n); - if(del_occ) *del_occ = del_n; - return ((del_n > thres)?0:1); -} -#define bg_correct (1) -#define bg_wrong (2) -#define bg_ambiguous (3) -#define bg_unavailable ((uint32_t)-1) -inline uint32_t get_bg_flag(ul_resolve_t *uidx, uint32_t v, uint32_t w) -{ - asg_t *g = uidx->uovl.bg.bg; asg_arc_t *av; uint32_t k, nv; - if(g->seq[v>>1].del || g->seq[w>>1].del) return bg_unavailable; - - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (k = 0; k < nv; k++) { - if(av[k].v == w) break; - } - if(k >= nv) return bg_unavailable; - if(av[k].ou == 3) return bg_correct; - if(av[k].ou == 2) return bg_wrong; - return bg_ambiguous; -} - -inline void get_bridges(ul_resolve_t *uidx, uint64_t *v_a, uint64_t v_n, uint32_t *w_occ, uint32_t *am_occ) -{ - ul_bg_t *bg = &(uidx->uovl.bg); uint64_t k, w, am, l; uint32_t uv, uw, bv, bw; - for (k = w = am = 0, uv = uw = (uint32_t)-1; k < v_n; k++) { - w += bg->w_n[v_a[k]>>1]; am += bg->a_n[v_a[k]>>1]; uw = v_a[k]; - if(uv != (uint32_t)-1) { - bv = uidx->uovl.cc.iug_a[uv>>1].a[((uv&1)?(0):(uidx->uovl.cc.iug_a[uv>>1].n-1))].v; if(uv&1) bv ^= 1; - bw = uidx->uovl.cc.iug_a[uw>>1].a[((uw&1)?(uidx->uovl.cc.iug_a[uw>>1].n-1):(0))].v; if(uw&1) bw ^= 1; - if((ulg_type(uidx->uovl, (bv>>1))) && (ulg_type(uidx->uovl, (bw>>1)))) { - l = get_bg_flag(uidx, bv, bw); - if(l == bg_wrong) w++; - if(l == bg_ambiguous) am++; - } - } - uv = uw; - } - if(w_occ) *w_occ = w; - if(am_occ) *am_occ = am; -} - -static inline void ulg_seq_del(ma_ug_t *ug, uint32_t s) -{ - uint32_t k; asg_t *g = ug->g; - g->seq[s].del = 1; - for (k = 0; k < 2; ++k) { - uint32_t i, v = s<<1 | k; - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - for (i = 0; i < nv; ++i) { - av[i].del = 1; - asg_arc_del(g, av[i].v^1, v^1, 1); - } - } - free(ug->u.a[s].a); memset(&(ug->u.a[s]), 0, sizeof(ug->u.a[s])); -} - - -uint32_t ulg_arc_cut_tips(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t max_ext, uint32_t max_ext_hifi, uint32_t is_double_check, asg64_v *in, asg64_v *ib) -{ - asg64_v tx = {0,0,0}, tb = {0,0,0}, *b = NULL, *ub = NULL; asg_t *g = ug->g; - uint32_t n_vtx = g->n_seq<<1, v, w, i, k, cnt = 0, nv, kv, pb, w_occ, a_occ, ul_occ, del_occ, is_telo; - asg_arc_t *av = NULL; uint64_t lw; - b = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); - for (v = 0, b->n = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - - av = asg_arc_a(g, v^1); nv = asg_arc_n(g, v^1); - for (i = kv = 0; i < nv; i++) { - if (av[i].del) continue; - kv++; break; - } - - if(kv) continue; - // kv = ug->u.a[v>>1].n;/// get_ul_occ(uidx, v>>1); - get_iug_u_raw_occ(uidx, v>>1, &ul_occ, NULL); kv = ul_occ; - is_telo = 0; if(uidx->uovl.telo && uidx->uovl.telo[v>>1]) is_telo = 1; - for (i = 0, w = v; i < max_ext; i++) { - if(asg_end(g, w^1, &lw, NULL)!=0) break; - w = (uint32_t)lw; - // kv += ug->u.a[w>>1].n; ///get_ul_occ(uidx, w>>1); - get_iug_u_raw_occ(uidx, w>>1, &ul_occ, NULL); kv += ul_occ; - if(uidx->uovl.telo && uidx->uovl.telo[w>>1]) is_telo = 1; - } - - if((kv <= max_ext) && (!is_telo)) kv_push(uint64_t, *b, (((uint64_t)kv)<<32)|v); - } - - radix_sort_srt64(b->a, b->a + b->n); - - for (k = 0; k < b->n; k++) { - v = (uint32_t)(b->a[k]); - if (g->seq[v>>1].del) continue; - - av = asg_arc_a(g, v^1); nv = asg_arc_n(g, v^1); - for (i = kv = 0; i < nv; i++) { - if (av[i].del) continue; - kv++; break; - } - - if(kv) continue; - - pb = b->n; kv_push(uint64_t, *b, v); - // kv = ug->u.a[v>>1].n;/// get_ul_occ(uidx, v>>1); - get_iug_u_raw_occ(uidx, v>>1, &ul_occ, NULL); kv = ul_occ; - is_telo = 0; if(uidx->uovl.telo && uidx->uovl.telo[v>>1]) is_telo = 1; - for (i = 0, w = v; i < max_ext; i++) { - if(asg_end(g, w^1, &lw, NULL)!=0) break; - w = (uint32_t)lw; kv_push(uint64_t, *b, w); - // kv += ug->u.a[w>>1].n; ///get_ul_occ(uidx, w>>1); - get_iug_u_raw_occ(uidx, w>>1, &ul_occ, NULL); kv += ul_occ; - if(uidx->uovl.telo && uidx->uovl.telo[w>>1]) is_telo = 1; - } - - - - if((!is_telo) && (kv <= max_ext) && (get_remove_hifi_occ(uidx, max_ext_hifi, b->a + pb, b->n - pb, ub, &del_occ))) { - // fprintf(stderr, "*[M::%s::] k::%u, v>>1::%u, v&1::%u, kv::%u, max_ext::%u, max_ext_hifi::%u\n\n", - // __func__, k, v>>1, v&1, kv, max_ext, max_ext_hifi); - if(is_double_check) get_bridges(uidx, b->a + pb, b->n - pb, &w_occ, &a_occ); - if(is_double_check == 0 || w_occ > 0 || a_occ > 0 || kv == 0 || del_occ == 0) { - for (i = pb; i < b->n; i++) ulg_seq_del(ug, (b->a[i]>>1)); - cnt += b->n - pb; - } - } - b->n = pb; - } - - // stats_sysm(g); - if(!in) free(tx.a); if(!ib) free(tb.a); - if (cnt > 0) asg_cleanup(g); - - return cnt; -} - -uint32_t is_het_ulg_edge(ul_resolve_t *uidx, uint32_t uv, uint32_t uw) -{ - ma_ug_t *iug = uidx->uovl.i_ug; bubble_type *bub = uidx->bub; uint32_t qid, tid; - qid = iug->u.a[uv>>1].a[((uv&1)?(0):(iug->u.a[uv>>1].n-1))]>>33; - tid = iug->u.a[uw>>1].a[((uw&1)?(iug->u.a[uw>>1].n-1):(0))]>>33; - - if(!ulg_type(uidx->uovl, qid)) return (!IF_HOM(ulg_id(uidx->uovl, qid), *bub)); - if(!ulg_type(uidx->uovl, tid)) return (!IF_HOM(ulg_id(uidx->uovl, tid), *bub)); - - if(uidx->uovl.item_idx[qid] == (uint32_t)-1) return (uint32_t)-1; - ul2ul_item_t *o = &(uidx->uovl.a[uidx->uovl.item_idx[qid]]); - ul2ul_t *z; uint64_t k, n_hom, n_het; ul_str_t *str; - for (k = 0, z = NULL; k < o->cn; k++) { - if(o->a[k].hid != tid) continue; - z = &(o->a[k]); - break; - } - if(!z) return (uint32_t)-1; - str = &(uidx->pstr.str.a[ulg_id(uidx->uovl, qid)]); - - for (k = z->qs_k, n_hom = n_het = 0; k < z->qe_k; k++) { - if(IF_HOM((((uint32_t)str->a[k])>>1), *bub)) { - n_hom++; - } else { - n_het++; break; - } - } - - if(n_het) return 1; - if(n_hom) return 0; - return (uint32_t)-1; -} - - -int32_t usg_topocut_aux(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t v, int32_t max_ext, int32_t max_ext_hifi, asg64_v *b, asg64_v *ub) -{ - int32_t n_ext; asg_arc_t *av; uint32_t w = v, nv, i, kv, ul_occ, pn = b->n; - for (n_ext = 0; n_ext < max_ext; v = w) { - av = asg_arc_a(ug->g, v^1); nv = asg_arc_n(ug->g, v^1); - for (i = kv = 0; i < nv && kv <= 1; i++) { - if (av[i].del) continue; - kv++; - } - if(kv!=1) break; - get_iug_u_raw_occ(uidx, v>>1, &ul_occ, NULL); n_ext += ul_occ; kv_push(uint64_t, *b, v); - - av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); - for (i = kv = 0; i < nv && kv <= 1; i++) { - if (av[i].del) continue; - kv++; w = av[i].v; - } - if(kv!=1) break; - } - - if(n_ext < max_ext) { - if(get_remove_hifi_occ(uidx, max_ext_hifi, b->a + pn, b->n - pn, ub, NULL)) { - b->n = pn; - return 1; - } - } - - b->n = pn; - return 0; -} - -uint32_t ulg_arc_cut_length(ul_resolve_t *uidx, ma_ug_t *ug, int32_t max_ext, uint32_t max_ext_hifi, -float len_rat, uint32_t is_trio, uint32_t topo_level, uint32_t hom_check, uint32_t *max_drop_len, asg64_v *in, asg64_v *ib) -{ - asg64_v tx = {0,0,0}, tb = {0,0,0}, *b = NULL, *ub = NULL; asg_t *g = ug->g; - uint32_t v, w, i, k, kv, kw, nv, nw, cnt = 0, n_vtx = g->n_seq<<1, n_het, n_hom, ff, ol_max, mm_ol, to_del; - asg_arc_t *av, *aw, *ve, *we, *vl_max, *wl_max; - - b = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); - for (v = b->n = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - if(g->seq_vis[v] == 0) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if (nv < 2) continue; - - for (i = kv = 0; i < nv && kv < 2; ++i) { - if(av[i].del) continue; - kv++; - } - if(kv < 2) continue; - if(hom_check) { - for (i = n_het = n_hom = 0; i < nv; ++i) { - if(av[i].del) continue; - ff = is_het_ulg_edge(uidx, av[i].ul>>32, av[i].v); assert(ff != (uint32_t)-1); - if(ff) n_het++; - else n_hom++; - if(n_het > 0 && n_hom > 0) break; - } - if(n_het == 0 || n_hom == 0) continue; - } - - for (i = 0; i < nv; ++i) { - if(av[i].del) continue; - kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); - } - } - } - - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - if(g->arc[(uint32_t)b->a[k]].del) continue; - v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; - if(g->seq[v>>1].del || g->seq[w>>1].del) continue; - nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); - av = asg_arc_a(g, v); aw = asg_arc_a(g, w); - if(nv<=1 && nw <= 1) continue; - if(hom_check) { - ff = is_het_ulg_edge(uidx, g->arc[(uint32_t)b->a[k]].ul>>32, g->arc[(uint32_t)b->a[k]].v); - assert(ff != (uint32_t)-1); - if(ff) continue; - } - - ve = &(g->arc[(uint32_t)b->a[k]]); - for (i = 0; i < nw; ++i) { - if (aw[i].v == (v^1)) { - we = &(aw[i]); - break; - } - } - mm_ol = MIN(ve->ol, we->ol); ///ve and we are hom edges - - for (i = kv = ol_max = 0, vl_max = NULL; i < nv; ++i) { - if(av[i].del) continue; - kv++; - if(hom_check) { - ff = is_het_ulg_edge(uidx, av[i].ul>>32, av[i].v); assert(ff != (uint32_t)-1); - if(!ff) continue;///vl_max must be a het edge - } - if(ol_max < av[i].ol) ol_max = av[i].ol, vl_max = &(av[i]); - } - if (kv < 1 || (!vl_max)) continue; - if (kv >= 2) { - if (mm_ol > ol_max*len_rat) continue; - } - - for (i = kw = ol_max = 0, wl_max = NULL; i < nw; ++i) { - if(aw[i].del) continue; - kw++; - if(hom_check) { - ff = is_het_ulg_edge(uidx, aw[i].ul>>32, aw[i].v); assert(ff != (uint32_t)-1); - if(!ff) continue;///wl_max must be a het edge - } - if(ol_max < aw[i].ol) ol_max = aw[i].ol, wl_max = &(aw[i]); - } - if (kw < 1 || (!wl_max)) continue; - if (kw >= 2) { - if (mm_ol > ol_max*len_rat) continue; - } - - if (kv <= 1 && kw <= 1) continue; - - to_del = 0; - if(topo_level == 0) { - to_del = 1; - } else if(topo_level == 2) { - if (kv > 1 && kw > 1) to_del = 1; - } else { - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (usg_topocut_aux(uidx, ug, w^1, max_ext, max_ext_hifi, b, ub)) to_del = 1; - } else if (kv == 1) { - if (usg_topocut_aux(uidx, ug, v^1, max_ext, max_ext_hifi, b, ub)) to_del = 1; - } - } - - if (to_del) { - ve->del = we->del = 1, ++cnt; - } - } - - - if(!in) free(tx.a); if(!ib) free(tb.a); - if (cnt > 0) asg_cleanup(g); - - return cnt; -} - -uint32_t is_ul_edge(ul_resolve_t *uidx, uint32_t uv, uint32_t uw) -{ - ma_ug_t *iug = uidx->uovl.i_ug; uint32_t qid, tid; - qid = iug->u.a[uv>>1].a[((uv&1)?(0):(iug->u.a[uv>>1].n-1))]>>33; - tid = iug->u.a[uw>>1].a[((uw&1)?(iug->u.a[uw>>1].n-1):(0))]>>33; - if((qid != tid) && (!ulg_type(uidx->uovl, qid)) && (!ulg_type(uidx->uovl, tid))) return 0; - return 1; -} - -uint32_t ulg_arc_cut_occ(ul_resolve_t *uidx, ma_ug_t *ug, int32_t max_ext, uint32_t max_ext_hifi, -uint32_t is_trio, uint32_t topo_level, asg64_v *in, asg64_v *ib) -{ - asg_t *g = ug->g; asg64_v tx = {0,0,0}, tb = {0,0,0}, *b = NULL, *ub = NULL; - uint32_t v, w, i, z, kv, kw, nv, nw, cnt = 0, n_vtx = g->n_seq<<1, to_del, n_ul, n_ug; - asg_arc_t *av, *aw; b = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); - - for (v = b->n = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if (nv < 2) continue; - - for (i = n_ul = n_ug = kv = 0; i < nv; ++i) { - if(av[i].del) continue; - if(is_ul_edge(uidx, av[i].ul>>32, av[i].v)) n_ul++; - else n_ug++; - kv++; - } - if(n_ul == 0 || n_ug == 0 || kv < 2) continue; - - for (i = 0; i < nv; ++i) { - if(av[i].del) continue; - if(is_ul_edge(uidx, av[i].ul>>32, av[i].v)) continue; - w = av[i].v^1; if(g->seq[w>>1].del) continue; - kw = get_arcs(g, w, NULL, 0); - if (kv <= 1 && kw <= 1) continue; - - to_del = 0; - if(topo_level == 0) { - to_del = 1; - } else if(topo_level == 2) { - if (kv > 1 && kw > 1) to_del = 1; - } else { - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (usg_topocut_aux(uidx, ug, w^1, max_ext, max_ext_hifi, b, ub)) to_del = 1; - } else if (kv == 1) { - if (usg_topocut_aux(uidx, ug, v^1, max_ext, max_ext_hifi, b, ub)) to_del = 1; - } - } - - if (to_del) { - ++cnt; av[i].del = 1; - aw = asg_arc_a(g, w); nw = asg_arc_n(g, w); - for (z = 0; z < nw; ++z) { - if (aw[z].v == (v^1)) { - aw[z].del = 1; - break; - } - } - assert(z < nw); - } - } - } - - if(!in) free(tx.a); if(!ib) free(tb.a); - if (cnt > 0) asg_cleanup(g); - - return cnt; -} - - -uint32_t get_ul_path_info(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t s, uint32_t *e, uint32_t *occ, -uint32_t *ul_cnt, uint32_t *bridge_w, uint32_t *bridge_am, asg64_v *b) -{ - uint32_t v = s, w = (uint32_t)-1, kv, kw, uv = (uint32_t)-1, uw = (uint32_t)-1, bv, bw, l; - ul_bg_t *bg = &(uidx->uovl.bg); - if(occ) (*occ) = 0; if(ul_cnt) (*ul_cnt) = 0; if(bridge_w) (*bridge_w) = 0; if(bridge_am) (*bridge_am) = 0; - - while (1) { - if(occ) (*occ)++; - kv = get_arcs(ug->g, v, &w, 1); - if(e) (*e) = v; - - ///if(b) kv_push(uint32_t, b->b, v>>1); - if(b) kv_push(uint64_t, *b, v); - if(ul_cnt) (*ul_cnt) += get_ul_occ(uidx, v>>1); - if(bridge_w || bridge_am) { - uw = v; - if(bridge_w) (*bridge_w) += bg->w_n[v>>1]; - if(bridge_am) (*bridge_am) += bg->a_n[v>>1]; - if(uv != (uint32_t)-1) { - bv = uidx->uovl.cc.iug_a[uv>>1].a[((uv&1)?(0):(uidx->uovl.cc.iug_a[uv>>1].n-1))].v; if(uv&1) bv ^= 1; - bw = uidx->uovl.cc.iug_a[uw>>1].a[((uw&1)?(uidx->uovl.cc.iug_a[uw>>1].n-1):(0))].v; if(uw&1) bw ^= 1; - if((ulg_type(uidx->uovl, (bv>>1))) && (ulg_type(uidx->uovl, (bw>>1)))) { - l = get_bg_flag(uidx, bv, bw); - if(l == bg_wrong && bridge_w) (*bridge_w)++; - if(l == bg_ambiguous && bridge_am) (*bridge_am)++; - } - } - uv = uw; - } - - if(kv == 0) return END_TIPS; - if(kv == 2) return TWO_OUTPUT; - if(kv > 2) return MUL_OUTPUT; - w = ug->g->arc[w].v; - ///up to here, kv=1 - ///kw must >= 1 - kw = get_arcs(ug->g, w^1, NULL, 0); - v = w; - - if(kw == 2) return TWO_INPUT; - if(kw > 2) return MUL_INPUT; - if(v == s) return LOOP; - } - - return LONG_TIPS; -} - -#define ul_path_w(ul_cnt, bridge_w, bridge_am) (((bridge_w)+(bridge_w))==0?((uint32_t)-1):((ul_cnt)/((bridge_w)+(bridge_w)))) - - -uint32_t usg_bridge_topocut_aux(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t v, uint32_t max_ext, uint32_t max_ext_hifi, uint32_t topo_level, uint32_t double_check, asg64_v *b, asg64_v *ub) -{ - uint32_t k, z, bn = b->n, w, bridge_w = 1, bridge_am = 1, raw_ul, ul, del_occ, is_del = 0, kk; - asg_arc_t *av; uint32_t nv; - get_ul_path_info(uidx, ug, v, &w, NULL, NULL, (double_check?(&bridge_w):(NULL)), - (double_check?(&bridge_am):(NULL)), b); - for (k = bn, raw_ul = 0; k < b->n; k++) { - get_iug_u_raw_occ(uidx, b->a[k]>>1, &ul, NULL); raw_ul += ul; - } - - if(raw_ul <= max_ext && get_remove_hifi_occ(uidx, max_ext_hifi, b->a + bn, b->n - bn, ub, &del_occ)) { - b->n = bn; - if(topo_level == 0) { - is_del = 1; - } else if(double_check == 0 || bridge_w > 0 || bridge_am > 0 || raw_ul == 0 || del_occ == 0) { - av = asg_arc_a(ug->g, v^1); nv = asg_arc_n(ug->g, v^1); - for (z = 0; z < nv; z++) { - if(av[z].del) continue; - kk = get_arcs(ug->g, av[z].v^1, NULL, 0); - if(topo_level == 2 && kk > 1) continue; - ///==1, might be a tip - if (topo_level == 1 && usg_topocut_aux(uidx, ug, av[z].v, max_ext, max_ext_hifi, b, ub)) continue; - break; - } - - if(z >= nv) { - av = asg_arc_a(ug->g, w); nv = asg_arc_n(ug->g, w); - for (z = 0; z < nv; z++) { - if(av[z].del) continue; - kk = get_arcs(ug->g, av[z].v^1, NULL, 0); - if(topo_level == 2 && kk > 1) continue; - ///==1, might be a tip - if (topo_level == 1 && usg_topocut_aux(uidx, ug, av[z].v, max_ext, max_ext_hifi, b, ub)) continue; - break; - } - - if(z >= nv) is_del = 1; - } - } - } - b->n = bn; - - return is_del; -} - -uint32_t ulg_arc_cut_bridge(ul_resolve_t *uidx, ma_ug_t *ug, int32_t max_ext, uint32_t max_ext_hifi, -float len_rat, uint32_t is_trio, uint32_t topo_level, uint32_t *max_drop_len, asg64_v *in, asg64_v *ib) -{ - asg64_v tx = {0,0,0}, tb = {0,0,0}, *b = NULL, *ub = NULL; asg_t *g = ug->g; - uint32_t v, w, i, k, kv, nv, cnt = 0, n_vtx = g->n_seq<<1, ff, ol_max, ul_max, mm_ol; - asg_arc_t *av, *ve, *vl_max; uint32_t ul_cnt, bridge_w, bridge_am, pb; - // fprintf(stderr, "+++[M::%s::] idx->cc.iug_b[455]::%lu\n", __func__, uidx->uovl.cc.iug_b[455]); - b = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); - for (v = b->n = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - if(g->seq_vis[v] == 0) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if (nv < 2) continue; - - for (i = kv = 0; i < nv && kv < 2; ++i) { - if(av[i].del) continue; - kv++; - } - if(kv < 2) continue; - - for (i = 0; i < nv; ++i) { - if(av[i].del) continue; - get_ul_path_info(uidx, ug, av[i].v, NULL, NULL, &ul_cnt, &bridge_w, &bridge_am, NULL); - ff = ul_path_w(ul_cnt, bridge_w, bridge_am); - // if((v>>1) == 5) { - // fprintf(stderr, "+[M::%s::] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, ul_cnt::%u, bridge_w::%u, bridge_am::%u, ff::%u\n", __func__, - // v>>1, v&1, av[i].v>>1, av[i].v&1, ul_cnt, bridge_w, bridge_am, ff); - // } - kv_push(uint64_t, *b, (((uint64_t)ff)<<32) | ((uint64_t)(av-g->arc+i))); - } - } - } - - // fprintf(stderr, "---[M::%s::] idx->cc.iug_b[455]::%lu\n", __func__, uidx->uovl.cc.iug_b[455]); - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - if(g->arc[(uint32_t)b->a[k]].del) continue; - v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; - if(g->seq[v>>1].del || g->seq[w>>1].del) continue; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - if(nv<=1 && asg_arc_n(g, w) <= 1) continue; - if(get_arcs(ug->g, w, NULL, 0) != 1) continue; - - ve = &(g->arc[(uint32_t)b->a[k]]); - get_ul_path_info(uidx, ug, ve->v, NULL, NULL, &ul_cnt, &bridge_w, &bridge_am, NULL); - ff = ul_path_w(ul_cnt, bridge_w, bridge_am); - if(ff == (uint32_t)-1) continue; - mm_ol = ff; - - for (i = kv = ol_max = ul_max = 0, vl_max = NULL; i < nv; ++i) { - if(av[i].del) continue; - kv++; - get_ul_path_info(uidx, ug, av[i].v, NULL, NULL, &ul_cnt, &bridge_w, &bridge_am, NULL); - ff = ul_path_w(ul_cnt, bridge_w, bridge_am); - if((ol_max < ff) || (ol_max == ff && ul_max < ul_cnt)) { - ol_max = ff; ul_max = ul_cnt; vl_max = &(av[i]); - } - } - - // if((v>>1) == 5) { - // fprintf(stderr, "***[M::%s::] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, ul_cnt::%u, bridge_w::%u, bridge_am::%u, ff::%u, mm_ol::%u, ol_max::%u, kv::%u\n", __func__, - // v>>1, v&1, w>>1, w&1, ul_cnt, bridge_w, bridge_am, ff, mm_ol, ol_max, kv); - // } - - if (kv <= 1 || (!vl_max)) continue; - if (kv >= 2) { - if (mm_ol > ol_max*len_rat) continue; - } - - // if((v>>1) == 5) { - // fprintf(stderr, "###[M::%s::] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, ul_cnt::%u, bridge_w::%u, bridge_am::%u, ff::%u, mm_ol::%u, ol_max::%u\n", __func__, - // v>>1, v&1, w>>1, w&1, ul_cnt, bridge_w, bridge_am, ff, mm_ol, ol_max); - // } - - - if(usg_bridge_topocut_aux(uidx, ug, ve->v, max_ext, max_ext_hifi, topo_level, 1, b, ub)) { - pb = b->n; - get_ul_path_info(uidx, ug, ve->v, NULL, NULL, NULL, NULL, NULL, b); - for (i = pb; i < b->n; i++) ulg_seq_del(ug, (b->a[i]>>1)); - cnt += b->n - pb; b->n = pb; - } - } - - - if(!in) free(tx.a); if(!ib) free(tb.a); - if (cnt > 0) asg_cleanup(g); - return cnt; -} - - - -ul2ul_t* get_ul_spec_ovlp(ul2ul_idx_t *z, uint64_t qid, uint64_t tid) -{ - // uint64_t x = (is_qul?(qid):(qid+z->uln)); - if(z->item_idx[qid] == (uint32_t)-1) return NULL; - ul2ul_item_t *o = &(z->a[z->item_idx[qid]]); uint64_t k; - for (k = 0; k < o->cn; k++) { - if(o->a[k].hid != tid) continue; - return &(o->a[k]); - } - return NULL; -} - -uint64_t gen_ug_integer_seq_on_fly(ul_resolve_t *uidx, uint64_t *u_a, uint64_t u_n, asg64_v *res) -{ - ul2ul_idx_t *idx = &(uidx->uovl); ma_ug_t *raw = uidx->l1_ug; - uint64_t k, rn = res->n, nn, u_rev, uv, uw, bv, bw, is_bv_ul, is_bw_ul, x; int64_t z, zn; - ma_ug_t *iug = idx->i_ug; uinfo_srt_warp_t *seq; ul2ul_t *m; - for (k = 0; k < u_n; k++) { - seq = &(idx->cc.iug_a[u_a[k]>>1]); u_rev = u_a[k]&1; - // if(u_n == 6 && u_a[0] == 37683 && u_a[5] == 45894) { - // fprintf(stderr, "\n[M::%s::] k::%lu, u_a[k]>>1::%lu, u_a[k]&1::%lu\n", __func__, k, u_a[k]>>1, u_a[k]&1); - // for (z = 0, zn = seq->n; z < zn; z++) { - // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u\n", __func__, seq->a[z].v>>1, seq->a[z].v&1); - // } - // } - if(k > 0) { - uv = u_a[k-1]; uw = u_a[k]; - bv = iug->u.a[uv>>1].a[((uv&1)?(0):(iug->u.a[uv>>1].n-1))]>>32; if(uv&1) bv ^= 1; //pre - bw = iug->u.a[uw>>1].a[((uw&1)?(iug->u.a[uw>>1].n-1):(0))]>>32; if(uw&1) bw ^= 1; //current - is_bv_ul = ulg_type((*idx), (bv>>1)); is_bw_ul = ulg_type((*idx), (bw>>1)); - if(is_bw_ul) { - m = get_ul_spec_ovlp(idx, bv>>1, bw>>1); - assert(m && (!m->is_del)); - nn = res->n + seq->n - (m->te_k - m->ts_k); - kv_resize(uint64_t, *res, nn); - nn = m->te_k - m->ts_k; ///skipped length - zn = seq->n; - // fprintf(stderr, "[M::%s::] bv>>1::%lu, bv&1::%lu, bw>>1::%lu, bw&1::%lu, m->qs_k::%u, m->qe_k::%u, m->ts_k::%u, m->te_k::%u\n", __func__, - // bv>>1, bv&1, bw>>1, bw&1, m->qs_k, m->qe_k, m->ts_k, m->te_k); - if(!u_rev) { - ///debug - for (z = 0; z < ((int64_t)nn); z++) { - // if(res->a[res->n-nn+z] != seq->a[z].v) { - // fprintf(stderr, "****[M::%s::] k::%lu, z::%ld, nn::%lu, res->n::%u, res->v>>1::%lu, res->v&1::%lu, seq->a[z].v>>1::%u, seq->a[z].v&1::%u\n", - // __func__, k, z, nn, (uint32_t)res->n, res->a[res->n-nn+z]>>1, res->a[res->n-nn+z]&1, seq->a[z].v>>1, seq->a[z].v&1); - // } - assert(res->a[res->n-nn+z] == seq->a[z].v); - } - - for (z = nn; z < zn; z++) { - res->a[res->n++] = seq->a[z].v; - } - } else { - ///debug - for (z = zn - 1; z >= zn - ((int64_t)nn); z--) { - // fprintf(stderr, "[M::%s::z->%ld::idx->%ld] nn::%lu, zn::%ld, res->n::%ld, res>>1::%lu, res&1::%lu, seq>>1::%u, seq&1::%u\n", - // __func__, z, (int64_t)(res->n-nn+(zn-1-z)), nn, zn, (int64_t)(res->n), res->a[res->n-nn+(zn-1-z)]>>1, res->a[res->n-nn+(zn-1-z)]&1, seq->a[z].v>>1, seq->a[z].v&1); - assert(res->a[res->n-nn+(zn-1-z)] == (seq->a[z].v^1)); - } - - for (z = zn - 1 - ((int64_t)nn); z >= 0; z--) { - res->a[res->n++] = seq->a[z].v^1; - } - } - } else { - x = ulg_id(uidx->uovl, (bw>>1)); x <<= 1; x += (bw&1); - if(!is_bv_ul) {///if previous ul is also a raw utg node - assert(get_specfic_edge(raw->g, res->a[res->n-1], x)); - } else { - // assert(((res->a[res->n-1].v) == x)); - if(((res->a[res->n-1]) == x)) { - res->n--; - } else { - assert(get_specfic_edge(raw->g, res->a[res->n-1], x)); - } - } - nn = res->n + seq->n; zn = seq->n; - kv_resize(uint64_t, *res, nn); - if(!u_rev) { - for (z = 0; z < zn; z++) { - res->a[res->n++] = seq->a[z].v; - } - } else { - for (z = zn - 1; z >= 0; z--) { - res->a[res->n++] = seq->a[z].v^1; - } - } - } - } else { - nn = res->n + seq->n; zn = seq->n; - kv_resize(uint64_t, *res, nn); - if(!u_rev) { - for (z = 0; z < zn; z++) { - // fprintf(stderr, ">+<[M::%s::res->n->%ld] a>>1::%u, a&1::%u\n", - // __func__, (int64_t)res->n, seq->a[z].v>>1, seq->a[z].v&1); - res->a[res->n++] = seq->a[z].v; - } - } else { - for (z = zn - 1; z >= 0; z--) { - // fprintf(stderr, ">-<[M::%s::res->n->%ld] a>>1::%u, a&1::%u\n", - // __func__, (int64_t)res->n, seq->a[z].v>>1, (seq->a[z].v^1)&1); - res->a[res->n++] = seq->a[z].v^1; - } - } - } - } - - return res->n - rn; -} - -uint32_t get_integer_seq_ovlps(ul_resolve_t *uidx, uint64_t *p_a, int64_t p_n, int64_t match_bound, uint64_t skip_hom, asg64_v *res, uint64_t *r_w) -{ - ul_str_idx_t *str_idx = &(uidx->pstr); uint32_t v = p_a[match_bound]; uc_block_t *xi; - uint64_t *hid_a, hid_n, z, vz, ps, pe, ww[2], sw[2], occ; ul_str_t *str; int64_t s_n, s, p; - bubble_type *bub = uidx->bub; - - hid_a = str_idx->occ.a + str_idx->idx.a[v>>1]; - hid_n = str_idx->idx.a[(v>>1)+1] - str_idx->idx.a[v>>1]; - for (z = ww[0] = ww[1] = (*r_w) = occ = 0; z < hid_n; z++) { - str = &(str_idx->str.a[hid_a[z]>>32]); s_n = str->cn; - if(s_n < 2) continue; - vz = (uint32_t)(str->a[(uint32_t)hid_a[z]]); - assert((v>>1) == (vz>>1)); ps = pe = (uint64_t)-1; - sw[0] = sw[1] = 0; - if(v == vz) { - s = ((uint32_t)hid_a[z]) + 1; p = match_bound + 1; - for (; (s < s_n) && (p < p_n) && ((uint32_t)(str->a[s]) == p_a[p]); s++, p++) { - xi = &(uidx->idx->a[hid_a[z]>>32].bb.a[str->a[s]>>32]); - assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[s])); - if(skip_hom && IF_HOM(xi->hid, *bub)) continue; - sw[1] += ug_occ_w(xi->ts, xi->te, &(uidx->l1_ug->u.a[xi->hid])); - } - if(s < s_n && p < p_n) continue; - if(p <= match_bound + 1) continue;///bridging the two sides of the breakpoint - if(sw[1] == 0) continue; - pe = p; - - s = (uint32_t)hid_a[z]; p = match_bound; - for (; (s >= 0) && (p >= 0) && ((uint32_t)(str->a[s]) == p_a[p]); s--, p--) { - xi = &(uidx->idx->a[hid_a[z]>>32].bb.a[str->a[s]>>32]); - assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[s])); - if(skip_hom && IF_HOM(xi->hid, *bub)) continue; - sw[0] += ug_occ_w(xi->ts, xi->te, &(uidx->l1_ug->u.a[xi->hid])); - } - assert(p < match_bound); - if(s >= 0 && p >= 0) continue; - if(sw[0] == 0) continue; - ps = p + 1; - } else { - s = ((int32_t)((uint32_t)hid_a[z]))-1; p = match_bound + 1; - for (; (s >= 0) && (p < p_n) && ((uint32_t)(str->a[s]) == (p_a[p]^1)); s--, p++) { - xi = &(uidx->idx->a[hid_a[z]>>32].bb.a[str->a[s]>>32]); - assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[s])); - if(skip_hom && IF_HOM(xi->hid, *bub)) continue; - sw[1] += ug_occ_w(xi->ts, xi->te, &(uidx->l1_ug->u.a[xi->hid])); - } - if(s >= 0 && p < p_n) continue; - if(p <= match_bound + 1) continue;///bridging the two sides of the breakpoint - if(sw[1] == 0) continue; - pe = p; - - s = (uint32_t)hid_a[z]; p = match_bound; - for (; (s < s_n) && (p >= 0) && ((uint32_t)(str->a[s]) == (p_a[p]^1)); s++, p--) { - xi = &(uidx->idx->a[hid_a[z]>>32].bb.a[str->a[s]>>32]); - assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[s])); - if(skip_hom && IF_HOM(xi->hid, *bub)) continue; - sw[0] += ug_occ_w(xi->ts, xi->te, &(uidx->l1_ug->u.a[xi->hid])); - } - assert(p < match_bound); - if(s < s_n && p >= 0) continue; - if(sw[0] == 0) continue; - ps = p + 1; - } - if(res) kv_push(uint64_t, *res, ((ps<<32)|(pe))); - occ++; - ww[0] += sw[0]; ww[1] += sw[1]; - // if(match_bound == 15 && p_n == 36) { - // fprintf(stderr, "[M::%s::] z::%lu, ulid::%lu, ps::%lu, pe::%lu\n", __func__, z, hid_a[z]>>32, ps, pe); - // } - } - - (*r_w) = MIN(ww[0], ww[1]); - return occ; -} - -uint32_t usg_misjoin_topocut_aux(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t v, uint32_t ref_v, uint32_t beg_v, -asg64_v *b, asg64_v *ub) -{ - #define cut_rate 0.49999 - uint32_t k, bn = b->n, is_del = 0, kk, ks, ke; - uint64_t n_ref, n_v, *a_ref, *a_v, n_min, n_ref_ov, n_v_ov, *a_ref_ov, *a_v_ov, l_occ, r_occ, ref_occ, v_occ, ww[2]; - ub->n = 0; kv_push(uint64_t, *ub, beg_v); - get_ul_path_info(uidx, ug, ref_v, NULL, NULL, NULL, NULL, NULL, ub); - // fprintf(stderr, "+++[M::%s::] start..., v>>1::%u, v&1::%u, ref_v>>1::%u, ref_v&1::%u, beg_v>>1::%u, beg_v&1::%u\n", __func__, v>>1, v&1, ref_v>>1, ref_v&1, beg_v>>1, beg_v&1); - n_ref = gen_ug_integer_seq_on_fly(uidx, ub->a, ub->n, b); - // fprintf(stderr, "+++[M::%s::] done...\n", __func__); - - ub->n = 0; kv_push(uint64_t, *ub, beg_v); - get_ul_path_info(uidx, ug, v, NULL, NULL, NULL, NULL, NULL, ub); - // fprintf(stderr, "---[M::%s::] start...\n", __func__); - n_v = gen_ug_integer_seq_on_fly(uidx, ub->a, ub->n, b); - // fprintf(stderr, "---[M::%s::] done...\n", __func__); - - a_ref = b->a + bn; a_v = b->a + bn + n_ref; n_min = MIN(n_ref, n_v); ub->n = 0; - for (k = 0; k < n_min && a_ref[k] == a_v[k]; k++); - - // if((beg_v>>1) == 5958) { - // fprintf(stderr, "[M::%s::] beg_v>>1::%u, beg_v&1::%u, v>>1::%u, v&1::%u, n_v::%lu, ref_v>>1::%u, ref_v&1::%u, n_ref::%lu, # prefix::%u\n", - // __func__, beg_v>>1, beg_v&1, v>>1, v&1, n_v, ref_v>>1, ref_v&1, n_ref, k); - // for (kk = 0; kk < n_v; kk++) { - // fprintf(stderr, "+[M::%s::] a_v[%u]>>1::%lu, a_v[%u]&1::%lu\n", - // __func__, kk, a_v[kk]>>1, kk, a_v[kk]&1); - // } - - // for (kk = 0; kk < n_ref; kk++) { - // fprintf(stderr, "+[M::%s::] a_ref[%u]>>1::%lu, a_ref[%u]&1::%lu\n", - // __func__, kk, a_ref[kk]>>1, kk, a_ref[kk]&1); - // } - // } - - - if(k > 0) { - n_ref_ov = get_integer_seq_ovlps(uidx, a_ref, n_ref, k - 1, 1, ub, &ww[0]); - n_v_ov = get_integer_seq_ovlps(uidx, a_v, n_v, k - 1, 1, ub, &ww[1]); - if(n_v_ov <= (n_ref_ov*cut_rate)) { - is_del = 1; - } else { - a_ref_ov = ub->a; a_v_ov = ub->a + n_ref_ov; kk = k; - - for (k = ref_occ = 0; k < n_ref_ov; k++) { - ks = a_ref_ov[k]>>32; ke = (uint32_t)a_ref_ov[k]; - l_occ = kk - ks; r_occ = ke - kk; - ref_occ += MIN(l_occ, r_occ); - } - - for (k = v_occ = 0; k < n_v_ov; k++) { - ks = a_v_ov[k]>>32; ke = (uint32_t)a_v_ov[k]; - l_occ = kk - ks; r_occ = ke - kk; - v_occ += MIN(l_occ, r_occ); - } - - if(v_occ <= (ref_occ*cut_rate)) is_del = 1; - } - } - b->n = bn; - return is_del; -} - - -uint32_t ulg_arc_cut_misjoin(ul_resolve_t *uidx, ma_ug_t *ug, int32_t max_ext, uint32_t max_ext_hifi, -float len_rat, uint32_t is_trio, uint32_t topo_level, uint32_t *max_drop_len, asg64_v *in, asg64_v *ib) -{ - asg64_v tx = {0,0,0}, tb = {0,0,0}, *b = NULL, *ub = NULL; asg_t *g = ug->g; - uint32_t v, w, i, k, kv, nv, kw, nw, cnt = 0, n_vtx = g->n_seq<<1, mm_ul, ul_max, to_del; - asg_arc_t *av, *aw, *ve, *we; uint32_t ul_cnt, pb; - - b = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); - for (v = b->n = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - - if(g->seq_vis[v] == 0) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if (nv < 2) continue; - - for (i = kv = 0, ul_max = -1; i < nv; ++i) { - if(av[i].del) continue; kv++; - get_ul_path_info(uidx, ug, av[i].v, NULL, NULL, &ul_cnt, NULL, NULL, NULL); - if(ul_cnt > ul_max) ul_max = ul_cnt; - } - // if((v>>1) == 5958) { - // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, kv::%u, ul_max::%u\n", - // __func__, v>>1, v&1, kv, ul_max); - // } - if(kv < 2 || ul_max == 0) continue; //note: ul_cnt/ul_max might be 0 - - for (i = 0; i < nv; ++i) { - if(av[i].del) continue; - get_ul_path_info(uidx, ug, av[i].v, NULL, NULL, &ul_cnt, NULL, NULL, NULL); - // if((v>>1) == 5958) { - // fprintf(stderr, "+++[M::%s::] v>>1::%u, v&1::%u, av[i].v>>1::%u, av[i].v&1::%u, ul_cnt::%u\n", - // __func__, v>>1, v&1, av[i].v>>1, av[i].v&1, ul_cnt); - // } - if(ul_cnt > 0) ul_cnt = ul_max/ul_cnt; - else ul_cnt = ul_max<<2; - ul_cnt = ((uint32_t)-1) - ul_cnt; - kv_push(uint64_t, *b, (((uint64_t)ul_cnt)<<32) | ((uint64_t)(av-g->arc+i))); - } - } - } - - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - if(g->arc[(uint32_t)b->a[k]].del) continue; - v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; - if(g->seq[v>>1].del || g->seq[w>>1].del) continue; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - if(nv<=1 && asg_arc_n(g, w) <= 1) continue; - - ve = &(g->arc[(uint32_t)b->a[k]]); pb = b->n; ub->n = 0; - get_ul_path_info(uidx, ug, ve->v, NULL, NULL, &mm_ul, NULL, NULL, NULL); - // if((v>>1) == 5958 && (w>>1) == 11105) { - // fprintf(stderr, ">>>[M::%s::] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, mm_ul::%u\n", - // __func__, v>>1, v&1, w>>1, w&1, mm_ul); - // } - if(mm_ul == 0) continue;///no UL read support this path - - for (i = kv = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - if(av[i].v == ve->v) continue; - get_ul_path_info(uidx, ug, av[i].v, NULL, NULL, &ul_cnt, NULL, NULL, NULL); - // if((v>>1) == 5958 && (w>>1) == 11105) { - // fprintf(stderr, "*[M::%s::i->%u] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, av[i].v>>1::%u, av[i].v&1::%u, ul_cnt::%u\n", - // __func__, i, v>>1, v&1, w>>1, w&1, av[i].v>>1, av[i].v&1, ul_cnt); - // } - if (mm_ul <= ul_cnt*len_rat) { - ul_cnt = ((uint32_t)-1) - ul_cnt; - kv_push(uint64_t, *b, (((uint64_t)ul_cnt)<<32)|((uint64_t)(i))); - } - } - if(b->n == pb) continue; - to_del = 0; assert(kv >= 2); - - aw = asg_arc_a(g, w); nw = asg_arc_n(g, w); - for (i = kw = 0, we = NULL; i < nw; ++i) { - if (aw[i].del) continue; - if (aw[i].v == (v^1)) we = &(aw[i]); - kw++; - } - - if((kv > 1 && kw > 1) || (usg_bridge_topocut_aux(uidx, ug, ve->v, max_ext, max_ext_hifi, topo_level, 0, b, ub))) { - radix_sort_srt64(b->a + pb, b->a + b->n); - for (i = pb; i < b->n; i++) { - // if((v>>1) == 5958 && (w>>1) == 11105) { - // fprintf(stderr, "#[M::%s::srt_i->%u] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, av[(uint32_t)b->a[i]].v>>1::%u, av[(uint32_t)b->a[i]].v&1::%u\n", - // __func__, (uint32_t)b->a[i], v>>1, v&1, w>>1, w&1, av[(uint32_t)b->a[i]].v>>1, av[(uint32_t)b->a[i]].v&1); - // } - if(usg_misjoin_topocut_aux(uidx, ug, ve->v, av[(uint32_t)b->a[i]].v, v, b, ub)) { - to_del = 1; - break; - } - } - } - - b->n = pb; - if(to_del) { - if(kv > 1 && kw > 1) { - ve->del = we->del = 1; ++cnt; - } else { - pb = b->n; - get_ul_path_info(uidx, ug, ve->v, NULL, NULL, NULL, NULL, NULL, b); - for (i = pb; i < b->n; i++) ulg_seq_del(ug, (b->a[i]>>1)); - cnt += b->n - pb; b->n = pb; - } - } - } - - - if(!in) free(tx.a); if(!ib) free(tb.a); - if (cnt > 0) asg_cleanup(g); - return cnt; -} - -uint32_t is_het_bridge(ul_resolve_t *uidx, uint64_t *p_a, int64_t p_n, int64_t match_bound) -{ - bubble_type *bub = uidx->bub; int64_t z; - for (z = match_bound; z >= 0 && IF_HOM((p_a[z]>>1), *bub); z--) { - // if(is_debug){ - // fprintf(stderr, "+[M::%s::] match_bound::%ld, p_n::%ld, (p_a[%ld]>>1)::%lu, IF_HOM::%u\n", - // __func__, match_bound, p_n, z, (p_a[z]>>1), IF_HOM((p_a[z]>>1), *bub)); - // } - } - if(z < 0) return 0; - for (z = match_bound + 1; z < p_n && IF_HOM((p_a[z]>>1), *bub); z++) { - // if(is_debug){ - // fprintf(stderr, "-[M::%s::] match_bound::%ld, p_n::%ld, (p_a[%ld]>>1)::%lu, IF_HOM::%u\n", - // __func__, match_bound, p_n, z, (p_a[z]>>1), IF_HOM((p_a[z]>>1), *bub)); - // } - } - // if(is_debug) { - // fprintf(stderr, "*[M::%s::] z::%ld, p_n::%ld\n", __func__, z, p_n); - // } - if(z >= p_n) return 0; - return 1; -} - -uint32_t get_ul_arc_supports(ul_resolve_t *uidx, asg_arc_t *ve, asg64_v *b_int, asg64_v *b_raw, uint64_t skip_hom, uint64_t *retrun_w_v, uint64_t *retrun_w_r) -{ - ma_ug_t *iug = uidx->uovl.i_ug; asg_t *g = iug->g; uint32_t v, k, z, zn, nv, n_pre, l_v, l_r, skip_hom_local; - asg_arc_t *av; v = ve->ul>>32; uint32_t b_int_s = b_int->n, b_raw_s = b_raw->n, is_collapse = 0, v_occ, r_occ; - (*retrun_w_v) = (*retrun_w_r) = (uint64_t)-1; uint64_t *raw_v, *raw_r, w_v, w_r, min_w_v, min_w_r; - - get_ul_path_info(uidx, iug, v^1, NULL, NULL, NULL, NULL, NULL, b_int); nv = b_int->n-b_int_s; - for (k = 0, n_pre = b_int->n; k < (nv>>1); k++) { - v = b_int->a[k+b_int_s]; - b_int->a[k+b_int_s] = b_int->a[b_int_s+nv-k-1]^1; - b_int->a[b_int_s+nv-k-1] = v^1; - } - if(nv&1) b_int->a[k+b_int_s] ^= 1; - v = ve->ul>>32; - - get_ul_path_info(uidx, iug, ve->v, NULL, NULL, &v_occ, NULL, NULL, b_int); - // if(((ve->ul>>32) == 24093) && (ve->v == 61472)) { - // for (z = 0; z < b_int->n-b_int_s; z++) { - // fprintf(stderr, "[M::%s::] integ_v[%u]>>1:%lu, integ_v[%u]&1:%lu\n", __func__, - // z, b_int->a[b_int_s+z]>>1, z, b_int->a[b_int_s+z]&1); - // } - // } - l_v = gen_ug_integer_seq_on_fly(uidx, b_int->a+b_int_s, b_int->n-b_int_s, b_raw); - - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (k = 0, min_w_v = min_w_r = (uint64_t)-1; k < nv; k++) { - if(av[k].del || av[k].v == ve->v) continue;///skip ve->v - - b_int->n = n_pre; b_raw->n = b_raw_s + l_v; - get_ul_path_info(uidx, iug, av[k].v, NULL, NULL, &r_occ, NULL, NULL, b_int); - // if(((ve->ul>>32) == 24093) && (ve->v == 61472)) { - // for (z = 0; z < b_int->n-b_int_s; z++) { - // fprintf(stderr, "[M::%s::k->%u] integ_r[%u]>>1:%lu, integ_r[%u]&1:%lu\n", __func__, - // k, z, b_int->a[b_int_s+z]>>1, z, b_int->a[b_int_s+z]&1); - // } - // } - - l_r = gen_ug_integer_seq_on_fly(uidx, b_int->a+b_int_s, b_int->n-b_int_s, b_raw); - ///raw_v -> ve->v; raw_r -> av[k].v - raw_v = b_raw->a + b_raw_s; raw_r = b_raw->a + b_raw_s + l_v; zn = MIN(l_v, l_r); - // if((v>>1) == 77 && (ve->v>>1) == 78) { - // fprintf(stderr, "[M::%s::] l_v::%u\n", __func__, l_v); - // for (z = 0; z < l_v; z++) { - // fprintf(stderr, "raw_v[%u]>>1::utg%.6dl, raw_v[%u]&1::%lu\n", - // z, (int32_t)(raw_v[z]>>1)+1, z , raw_v[z]&1); - // } - // fprintf(stderr, "[M::%s::] l_r::%u\n", __func__, l_r); - // for (z = 0; z < l_r; z++) { - // fprintf(stderr, "raw_r[%u]>>1::utg%.6dl, raw_r[%u]&1::%lu\n", - // z, (int32_t)(raw_r[z]>>1)+1, z, raw_r[z]&1); - // } - // } - for (z = 0; z < zn && raw_v[z] == raw_r[z]; z++); ///z: first raw unitig that is different between two paths - skip_hom_local = skip_hom; - if(skip_hom_local && z < l_v) { - skip_hom_local = is_het_bridge(uidx, raw_v, l_v, z - 1);///, (v>>1) == 191 && (ve->v>>1) == 450); - } - if(skip_hom_local && z < l_r) { - skip_hom_local = is_het_bridge(uidx, raw_r, l_r, z - 1);///, (v>>1) == 191 && (ve->v>>1) == 450); - } - - assert(z > 0); w_v = w_r = (uint64_t)-1; - if(z < l_v) get_integer_seq_ovlps(uidx, raw_v, l_v, z - 1, skip_hom_local, NULL, &w_v); - if(z < l_r) get_integer_seq_ovlps(uidx, raw_r, l_r, z - 1, skip_hom_local, NULL, &w_r); - if(w_v == (uint64_t)-1) w_v = 0; - if(w_r == (uint64_t)-1) w_r = 0; - // if((v>>1) == 409 && (ve->v>>1) == 407) { - // fprintf(stderr, "[M::%s::v>>1::%u] l_v::%u, l_r::%u, z::%u, w_v::%lu, w_r::%lu, skip_hom_local::%u\n", - // __func__, av[k].v>>1, l_v, l_r, z, w_v, w_r, skip_hom_local); - // } - ///z == zn: -> prefer collapse - if((min_w_v == (uint64_t)-1) || (z == zn) || (min_w_v > w_v) || (min_w_v == w_v && min_w_r < w_r)) { - min_w_v = w_v; min_w_r = w_r; - if(z == zn && v_occ < r_occ) is_collapse = 1; - } - } - if(is_collapse) min_w_v = 0; - - (*retrun_w_v) = min_w_v; (*retrun_w_r) = min_w_r; - return is_collapse; -} - -static void worker_update_ul_arc_supports(void *data, long i, int tid) // callback for kt_for() -{ - ul_resolve_t *uidx = (ul_resolve_t *)data; integer_t *buf = &(uidx->str_b.buf[tid]); - uint64_t *x = &(uidx->uovl.iug_tra->a[i]); asg_arc_t *ve = &(uidx->uovl.i_ug->g->arc[*x]); - asg64_v b_v, b_r; uint64_t w_v, w_r; - b_v.a = buf->u.a; b_v.n = buf->u.n; b_v.m = buf->u.m; - b_r.a = buf->o.a; b_r.n = buf->o.n; b_r.m = buf->o.m; - - b_v.n = b_r.n = 0; - get_ul_arc_supports(uidx, ve, &b_v, &b_r, 1, &w_v, &w_r); - - buf->u.a = b_v.a; buf->u.n = b_v.n; buf->u.m = b_v.m; - buf->o.a = b_r.a; buf->o.n = b_r.n; buf->o.m = b_r.m; - - (*x) |= (w_v<<32); -} - - -uint32_t check_ul_contain_arc_supports(ul_resolve_t *uidx, asg_arc_t *ve, asg64_v *b_int, asg64_v *b_raw, uint64_t skip_hom, uint64_t *retrun_w_v, uint64_t *retrun_w_r) -{ - ma_ug_t *iug = uidx->uovl.i_ug; asg_t *g = iug->g; uint32_t v, k, z, zn, nv, n_pre, l_v, l_r, skip_hom_local; - asg_arc_t *av; v = ve->ul>>32; uint32_t b_int_s = b_int->n, b_raw_s = b_raw->n, is_collapse = 0, v_occ, r_occ; - (*retrun_w_v) = (*retrun_w_r) = (uint64_t)-1; uint64_t *raw_v, *raw_r, w_v, w_r, min_w_v, min_w_r; - - get_ul_path_info(uidx, iug, v^1, NULL, NULL, NULL, NULL, NULL, b_int); nv = b_int->n-b_int_s; - for (k = 0, n_pre = b_int->n; k < (nv>>1); k++) { - v = b_int->a[k+b_int_s]; - b_int->a[k+b_int_s] = b_int->a[b_int_s+nv-k-1]^1; - b_int->a[b_int_s+nv-k-1] = v^1; - } - if(nv&1) b_int->a[k+b_int_s] ^= 1; - v = ve->ul>>32; - - get_ul_path_info(uidx, iug, ve->v, NULL, NULL, &v_occ, NULL, NULL, b_int); - l_v = gen_ug_integer_seq_on_fly(uidx, b_int->a+b_int_s, b_int->n-b_int_s, b_raw); - - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - for (k = 0, min_w_v = min_w_r = (uint64_t)-1; k < nv; k++) { - if(av[k].del || av[k].v == ve->v) continue; - - b_int->n = n_pre; b_raw->n = b_raw_s + l_v; - get_ul_path_info(uidx, iug, av[k].v, NULL, NULL, &r_occ, NULL, NULL, b_int); - l_r = gen_ug_integer_seq_on_fly(uidx, b_int->a+b_int_s, b_int->n-b_int_s, b_raw); - - raw_v = b_raw->a + b_raw_s; raw_r = b_raw->a + b_raw_s + l_v; zn = MIN(l_v, l_r); - for (z = 0; z < zn && raw_v[z] == raw_r[z]; z++); - skip_hom_local = skip_hom; - if(skip_hom_local && z < l_v) { - skip_hom_local = is_het_bridge(uidx, raw_v, l_v, z - 1);///, (v>>1) == 191 && (ve->v>>1) == 450); - } - if(skip_hom_local && z < l_r) { - skip_hom_local = is_het_bridge(uidx, raw_r, l_r, z - 1);///, (v>>1) == 191 && (ve->v>>1) == 450); - } - - assert(z > 0); w_v = w_r = (uint64_t)-1; - if(z < l_v) get_integer_seq_ovlps(uidx, raw_v, l_v, z - 1, skip_hom_local, NULL, &w_v); - if(z < l_r) get_integer_seq_ovlps(uidx, raw_r, l_r, z - 1, skip_hom_local, NULL, &w_r); - if(w_v == (uint64_t)-1) w_v = 0; - if(w_r == (uint64_t)-1) w_r = 0; - // if((v>>1) == 409 && (ve->v>>1) == 407) { - // fprintf(stderr, "[M::%s::v>>1::%u] l_v::%u, l_r::%u, z::%u, w_v::%lu, w_r::%lu, v_occ::%u, r_occ::%u, skip_hom_local::%u\n", - // __func__, av[k].v>>1, l_v, l_r, z, w_v, w_r, v_occ, r_occ, skip_hom_local); - // } - ///z == zn: -> prefer collapse - if((min_w_v == (uint64_t)-1) || (z == zn) || (min_w_v > w_v) || (min_w_v == w_v && min_w_r < w_r)) { - min_w_v = w_v; min_w_r = w_r; - if(z == zn && v_occ < r_occ) { - is_collapse = 1; - } - } - } - - (*retrun_w_v) = min_w_v; (*retrun_w_r) = min_w_r; - return is_collapse; -} - -uint32_t check_ulg_to_del(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t v, uint32_t w, uint32_t kv, uint32_t kw, -uint32_t max_ext, uint32_t max_ext_hifi, uint32_t topo_level, uint32_t collapse, asg64_v *b, asg64_v *ub) -{ - uint32_t to_del = 0; - if(collapse) topo_level = 3; - if(topo_level == 0) { - to_del = 1; - } else if(topo_level == 2) { - if (kv > 1 && kw > 1) to_del = 1; - } else { - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (usg_topocut_aux(uidx, ug, w^1, max_ext, max_ext_hifi, b, ub)) to_del = 1; - } else if (kv == 1) { - if (usg_topocut_aux(uidx, ug, v^1, max_ext, max_ext_hifi, b, ub)) to_del = 1; - } - } - - return to_del; -} - -uint32_t ulg_arc_cut_supports(ul_resolve_t *uidx, ma_ug_t *ug, int32_t max_ext, uint32_t max_ext_hifi, -float len_rat, uint32_t is_trio, uint32_t topo_level, uint32_t skip_hom, uint32_t *max_drop_len, uint32_t collapse_check, -asg64_v *in, asg64_v *ib) -{ - // fprintf(stderr, "\n[M::%s::] max_ext::%d, max_ext_hifi::%d, len_rat::%f, is_trio::%u, topo_level::%u, skip_hom::%u, collapse_check::%u\n", - // __func__, max_ext, max_ext_hifi, len_rat, is_trio, topo_level, skip_hom, collapse_check); - - asg64_v tx = {0,0,0}, tb = {0,0,0}, *b = NULL, *ub = NULL; asg_t *g = ug->g; - uint32_t v, w, i, k, kv, nv, kw, nw, cnt = 0, n_vtx = g->n_seq<<1, to_del, collapse; - asg_arc_t *av, *aw, *ve, *we; uint64_t w_q, w_t, pb; - - b = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); - for (v = b->n = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - - if(g->seq_vis[v] == 0) { - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if (nv < 2) continue; - - for (i = kv = 0; i < nv && kv < 2; ++i) { - if(av[i].del) continue; kv++; - } - if(kv < 2) continue; - - for (i = 0; i < nv; ++i) { - if(av[i].del) continue; - kv_push(uint64_t, *b, ((uint64_t)(av-g->arc+i))); - } - } - } - - // fprintf(stderr, "\n#[M::%s::] Starting...\n", __func__); - uidx->uovl.iug_tra = b; - kt_for(uidx->str_b.n_thread, worker_update_ul_arc_supports, uidx, b->n);///all ul + ug - uidx->uovl.iug_tra = NULL; - // fprintf(stderr, "#[M::%s::] Done\n", __func__); - // fprintf(stderr, "#[M::%s::] collapse_check::%u, len_rat::%f\n", __func__, collapse_check, len_rat); - - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - if(g->arc[(uint32_t)b->a[k]].del) continue; - v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; - if(g->seq[v>>1].del || g->seq[w>>1].del) continue; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); - if(nv <= 1 && nw <= 1) continue; - ve = &(g->arc[(uint32_t)b->a[k]]); - for (i = kv = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - } - for (i = kw = 0, we = NULL; i < nw; ++i) { - if (aw[i].del) continue; - if (aw[i].v == (v^1)) we = &(aw[i]); - kw++; - } - if(kv <= 1 && kw <= 1) continue; - collapse = 0; - - if(collapse_check) { - if(kv > 1) { - pb = b->n; ub->n = 0; - collapse = check_ul_contain_arc_supports(uidx, ve, b, ub, skip_hom, &w_q, &w_t); - b->n = pb; ub->n = 0; - } - - if(collapse == 0 && kw > 1) { - pb = b->n; ub->n = 0; - collapse = check_ul_contain_arc_supports(uidx, we, b, ub, skip_hom, &w_q, &w_t); - b->n = pb; ub->n = 0; - } - } - - // if(((v>>1) == 6788 && (w>>1) == 17213) || ((w>>1) == 6788 && (v>>1) == 17213)) { - // fprintf(stderr, "#[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, collapse::%u\n", - // __func__, v>>1, v&1, kv, w>>1, w&1, kw, collapse); - // } - - if(collapse == 0) { - if(kv > 1) { - pb = b->n; ub->n = 0; - get_ul_arc_supports(uidx, ve, b, ub, skip_hom, &w_q, &w_t); - b->n = pb; ub->n = 0; - // if((v>>1) == 409 && (w>>1) == 407) { - // fprintf(stderr, "+[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, w_q::%lu, w_t::%lu\n", - // __func__, v>>1, v&1, kv, w>>1, w&1, kw, w_q, w_t); - // } - // if(((v>>1) == 6788 && (w>>1) == 17213) || ((w>>1) == 6788 && (v>>1) == 17213)) { - // fprintf(stderr, "+[M::%s::] v>>1::%u, v&1::%u, w_q::%lu, w>>1::%u, w&1::%u, w_t::%lu\n", - // __func__, v>>1, v&1, w_q, w>>1, w&1, w_t); - // } - if(w_q == (uint64_t)-1) continue; - if(w_q > w_t*len_rat) continue; - } - - if(kw > 1) { - pb = b->n; ub->n = 0; - get_ul_arc_supports(uidx, we, b, ub, skip_hom, &w_q, &w_t); - b->n = pb; ub->n = 0; - // if((v>>1) == 409 && (w>>1) == 407) { - // fprintf(stderr, "-[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, w_q::%lu, w_t::%lu\n", - // __func__, v>>1, v&1, kv, w>>1, w&1, kw, w_q, w_t); - // } - // if(((v>>1) == 6788 && (w>>1) == 17213) || ((w>>1) == 6788 && (v>>1) == 17213)) { - // fprintf(stderr, "-[M::%s::] v>>1::%u, v&1::%u, w_q::%lu, w>>1::%u, w&1::%u, w_t::%lu\n", - // __func__, v>>1, v&1, w_q, w>>1, w&1, w_t); - // } - if(w_q == (uint64_t)-1) continue; - if(w_q > w_t*len_rat) continue; - } - } - - to_del = check_ulg_to_del(uidx, ug, v, w, kv, kw, max_ext, max_ext_hifi, topo_level, collapse, b, ub); - - // if(((v>>1) == 6788 && (w>>1) == 17213) || ((w>>1) == 6788 && (v>>1) == 17213)) { - // fprintf(stderr, "#[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, to_del::%u\n", - // __func__, v>>1, v&1, kv, w>>1, w&1, kw, to_del); - // } - if (to_del) { - ve->del = we->del = 1, ++cnt; - } - } - - if(!in) free(tx.a); if(!ib) free(tb.a); - if (cnt > 0) asg_cleanup(g); - return cnt; -} - -uint64_t ulg_bub_pop_cut_aux(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t v0, buf_t *x, uint32_t max_ext, uint32_t max_ext_hifi, asg64_v *b, asg64_v *ub) -{ - uint32_t i, v, u, bn = b->n, n_ext, ul_occ, r = 0; binfo_t *t; - v = x->S.a[0]; - do { - u = x->a[v].p; // u->v - x->a[v].d = (uint32_t)-1; - v = u; - } while (v != v0); - - for (i = n_ext = 0; i < x->b.n; ++i) { // clear the states of visited vertices - t = &x->a[x->b.a[i]]; - if(t->d == (uint32_t)-1) continue; - get_iug_u_raw_occ(uidx, x->b.a[i]>>1, &ul_occ, NULL); - n_ext += ul_occ; kv_push(uint64_t, *b, x->b.a[i]); - } - - if(n_ext <= max_ext) { - if(get_remove_hifi_occ(uidx, max_ext_hifi, b->a + bn, b->n - bn, ub, NULL)) r = 1; - } - b->n = bn; - return r; -} - -uint32_t ulg_bub_pop_backtrack(ma_ug_t *ug, uint32_t v0, buf_t *b) -{ - uint32_t i, v, u, cnt = b->e.n; asg_t *g = ug->g; - - ///b->S.a[0] is the sink of this bubble - for (i = 0; i < b->b.n; ++i) g->seq[b->b.a[i]>>1].del = 1; - - ///remove all edges (self/reverse for each edge) in this bubble - for (i = 0; i < b->e.n; ++i) { - g->arc[b->e.a[i]].del = 1; - asg_arc_del(g, g->arc[b->e.a[i]].v^1, (g->arc[b->e.a[i]].ul>>32)^1, 1); - } - - ///v is the sink of this bubble - v = b->S.a[0]; - do { - u = b->a[v].p; // u->v - g->seq[v>>1].del = 0; - asg_arc_del(g, u, v, 0); - asg_arc_del(g, v^1, u^1, 0); - cnt--; - v = u; - } while (v != v0); - - for (i = 0; i < b->b.n; ++i) { - if(!g->seq[b->b.a[i]>>1].del) continue; - ulg_seq_del(ug, (b->b.a[i]>>1)); - } - - return cnt; -} - -uint64_t ulg_bub_pop1(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t v0, uint64_t max_dist, buf_t *x, -uint32_t max_ext, uint32_t max_ext_hifi, uint32_t check_bubble_only, uint32_t is_pop, uint32_t skip_hom, -asg64_v *b, asg64_v *ub, uint32_t *r_w_c, uint32_t *r_w_m) -{ - asg_t *g = ug->g; uint32_t pb = b->n; uint64_t w_q, w_t, wc, wm, ww; (*r_w_c) = (*r_w_m) = (uint32_t)-1; - uint32_t v, w, i, kv, nv, kw, cnt = 0, fail_b = 0, n_tips = 0, tip_end = (uint32_t)-1; - uint32_t l, d, c, m, n_pending = 0, z, to_replace; asg_arc_t *av, *ve, *we; binfo_t *t; - if(g->seq[v0>>1].del || get_arcs(g, v0, NULL, 0) < 2) return 0; // already deleted - // fprintf(stderr, "sbsbsbsbsbsbsb[M::%s::(v0>>1)->%u::(v0&1)->%u] check_bubble_only::%u, is_pop::%u\n", - // __func__, v0>>1, v0&1, check_bubble_only, is_pop); - - x->S.n = x->T.n = x->b.n = x->e.n = 0; - x->a[v0].c = x->a[v0].d = x->a[v0].m = x->a[v0].nc = x->a[v0].np = 0; - kv_push(uint32_t, x->S, v0); - - do { - v = kv_pop(x->S); d = x->a[v].d; c = x->a[v].c; m = x->a[v].m; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); kv = get_arcs(g, v, NULL, 0); - for (i = 0; i < nv; ++i) { - if (av[i].del) continue; - w = av[i].v; t = &(x->a[w]); l = ((v == v0)?(0):((uint32_t)av[i].ul)); - if ((w>>1) == (v0>>1)) { - fail_b = 1; - break; - } - kv_push(uint32_t, x->e, (g->idx[v]>>32) + i); ///for backtracking - if (d + l > max_dist) { - fail_b = 1; - break; - } - kw = get_arcs(g, w^1, NULL, 0); - wc = 0; wm = get_ul_occ(uidx, w>>1); - if(!check_bubble_only) { - if(kv > 1) { - pb = b->n; ub->n = 0; ve = &(av[i]); - // fprintf(stderr, "[M::%s::] ve->v>>1::%lu, ve->v&1::%lu, ve->w>>1::%u, ve->w&1::%u\n", - // __func__, ve->ul>>33, (ve->ul>>32)&1, ve->v>>1, ve->v&1); - get_ul_arc_supports(uidx, ve, b, ub, skip_hom, &w_q, &w_t); - b->n = pb; ub->n = 0; - if(w_q < w_t) { - if(w_q == 0) { - ww = 10; - } else { - if(w_t != 0) ww = ((w_t - w_q)*10)/w_t; - else ww = 0; - } - if(ww > wc) wc = ww; - } - } - - if(kw > 1) { - pb = b->n; ub->n = 0; we = get_specfic_edge(g, w^1, v^1); assert(we); - // fprintf(stderr, "[M::%s::] we->v>>1::%lu, we->v&1::%lu, we->w>>1::%u, we->w&1::%u\n", - // __func__, we->ul>>33, (we->ul>>32)&1, we->v>>1, we->v&1); - get_ul_arc_supports(uidx, we, b, ub, skip_hom, &w_q, &w_t); - b->n = pb; ub->n = 0; - if(w_q < w_t) { - if(w_q == 0) { - ww = 10; - } else { - if(w_t != 0) ww = ((w_t - w_q)*10)/w_t; - else ww = 0; - } - if(ww > wc) wc = ww; - } - } - } - - if (t->s == 0) { - kv_push(uint32_t, x->b, w); - t->p = v, t->s = 1, t->d = d + l; - t->c = c + wc; t->m = m + wm; - t->r = kw; - ++n_pending; - } else { - to_replace = 0; - if((c + wc) < t->c) { - to_replace = 1; - } else if(((c + wc) == t->c) && (m + wm > t->m)) { - to_replace = 1; - } else if(((c + wc) == t->c) && (m + wm == t->m) && (d + l > t->d)) { - to_replace = 1; - } - if(to_replace) { - t->p = v; t->c = c + wc; t->m = m + wm; - } - if (d + l < t->d) t->d = d + l; // update dist - } - - if (--(t->r) == 0) { - z = get_arcs(g, w, NULL, 0); - if(z > 0) { - kv_push(uint32_t, x->S, w); - } - else { - ///at most one tip - if(n_tips != 0) { - fail_b = 1; - break; - } - n_tips++; tip_end = w; - } - --n_pending; - } - } - if(fail_b) break; - if(n_tips == 1) { - if(tip_end != (uint32_t)-1 && n_pending == 0 && x->S.n == 0) { - kv_push(uint32_t, x->S, tip_end); - break; - } - fail_b = 1; - break; - } - - if (i < nv || x->S.n == 0) { - fail_b = 1; - break; - } - } while (x->S.n > 1 || n_pending); - - if(!fail_b) {//there is a bubble - cnt = 1; (*r_w_c) = x->a[x->S.a[0]].c; (*r_w_m) = x->a[x->S.a[0]].m; - if(!check_bubble_only) { - if(is_pop) { - cnt = ulg_bub_pop_backtrack(ug, v0, x); - } else { - cnt = ulg_bub_pop_cut_aux(uidx, ug, v0, x, max_ext, max_ext_hifi, b, ub); - } - } - } - for (i = 0; i < x->b.n; ++i) { // clear the states of visited vertices - // if(v0 == 119) { - // fprintf(stderr, "-[M::%s::(v0>>1)->%u::(v0&1)->%u] v[%u]>>1::%u, v[%u]&1::%u, cnt::%u, is_pop::%u\n", - // __func__, v0>>1, v0&1, i, x->b.a[i]>>1, i, x->b.a[i]&1, cnt, is_pop); - // } - t = &x->a[x->b.a[i]]; - t->s = t->c = t->d = t->m = t->nc = t->np = 0; - } - if(!cnt) (*r_w_c) = (*r_w_m) = (uint32_t)-1; - return cnt; -} - -uint64_t ulg_pop_bubble(ul_resolve_t *uidx, ma_ug_t *ug, uint64_t* i_max_dist, uint32_t max_ext, uint32_t max_ext_hifi, uint32_t skip_hom, asg64_v *in, asg64_v *ib) -{ - // fprintf(stderr, "[M::%s::] Starting...\n", __func__); - asg_t *g = ug->g; - asg64_v tx = {0,0,0}, tb = {0,0,0}, *ob = NULL, *ub = NULL; - uint32_t v, w, n_vtx = g->n_seq<<1, n_arc, nv, i, wc[2], wm[2], mm_c, mm_m, mm_v; - uint64_t n_pop = 0, max_dist; - asg_arc_t *av = NULL; if (!g->is_symm) asg_symm(g); - buf_t b; memset(&b, 0, sizeof(buf_t)); - b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - if(i_max_dist) max_dist = (*i_max_dist); - else max_dist = get_bub_pop_max_dist_advance(g, &b); - ob = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); ob->n = ub->n = 0; - - if(max_dist > 0) { - for (v = 0; v < n_vtx; ++v) { - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - if (nv < 2 || g->seq[v>>1].del) continue; - for (i = n_arc = 0; i < nv; ++i) { - if (!av[i].del) ++n_arc; - } - if (n_arc < 2) continue; - ///find a bubble - ob->n = ub->n = 0; - if(ulg_bub_pop1(uidx, ug, v, max_dist, &b, max_ext, max_ext_hifi, 1, 0, skip_hom, ob, ub, &(wc[0]), &(wm[0]))) { - w = b.S.a[0]^1; mm_c = mm_m = mm_v = (uint32_t)-1; - - ob->n = ub->n = 0; - if(ulg_bub_pop1(uidx, ug, v, max_dist, &b, max_ext, max_ext_hifi, 0, 0, skip_hom, - ob, ub, &(wc[0]), &(wm[0]))) { - mm_c = wc[0]; mm_m = wm[0]; mm_v = v; - } - - ob->n = ub->n = 0; - if(ulg_bub_pop1(uidx, ug, w, max_dist, &b, max_ext, max_ext_hifi, 0, 0, skip_hom, - ob, ub, &(wc[1]), &(wm[1]))) { - if((wc[1] < mm_c) && (wc[1] == mm_c && wm[1] > mm_m)) { - mm_c = wc[1]; mm_m = wm[1]; mm_v = w; - } - } - - if(mm_v != (uint32_t)-1) { - ob->n = ub->n = 0; - w = ulg_bub_pop1(uidx, ug, mm_v, max_dist, &b, max_ext, max_ext_hifi, 0, 1, skip_hom, ob, ub, &(wc[0]), &(wm[0])); - assert(w); - n_pop += w; - } - } - } - } - - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - if(n_pop) asg_cleanup(g); - if(!in) free(tx.a); if(!ib) free(tb.a); - // fprintf(stderr, "[M::%s::] Done...\n", __func__); - return n_pop; -} - -/** -void infer_reliable_regions(ul_resolve_t *uidx, asg64_v *b) -{ - ul2ul_idx_t *idx = &(uidx->uovl); ma_ug_t *iug = idx->i_ug; ma_ug_t *raw = uidx->l1_ug; - uint64_t k, z, v, l, nv, uv, uw, bv, bw, is_bv_ul, is_bw_ul; ma_utg_t *iu; uinfo_srt_warp_t *seq; - uint8_t *raw_idx; CALLOC(raw_idx, raw->u.n<<1); - uint64_t *iu_idx; CALLOC(iu_idx, iug->u.n); uint32_t *iu_a; - asg_t *g = asg_init(); asg_arc_t *av; - - - for (k = l = 0; k < iug->u.n; k++) { - seq = &(idx->cc.iug_a[k]); - iu_idx[k] = l; iu_idx[k] <<= 32; iu_idx[k] += (l + seq->n); - l += seq->n; - } - - MALLOC(iu_a, l); - for (k = b->n = 0; k < iug->u.n; k++) { - seq = &(idx->cc.iug_a[k]); - v = k<<1; uv = v; - bv = iug->u.a[uv>>1].a[((uv&1)?(0):(iug->u.a[uv>>1].n-1))]>>32; if(uv&1) bv ^= 1; - is_bv_ul = ulg_type((*idx), (bv>>1)); av = asg_arc_a(iug->g, v); nv = asg_arc_n(iug->g, v); - for (z = 0; z < nv; z++) { - if(av[z].del || (av[z].v>>1) >= k) continue; - uw = av[z].v; bw = iug->u.a[uw>>1].a[((uw&1)?(iug->u.a[uw>>1].n-1):(0))]>>32; - if(uw&1) bw ^= 1; is_bw_ul = ulg_type((*idx), (bw>>1)); - } - - - - - v = (k<<1)+1; uv = v; - bv = iug->u.a[uv>>1].a[((uv&1)?(0):(iug->u.a[uv>>1].n-1))]>>32; if(uv&1) bv ^= 1; - is_bv_ul = ulg_type((*idx), (bv>>1)); av = asg_arc_a(iug->g, v); nv = asg_arc_n(iug->g, v); - for (z = 0; z < nv; z++) { - if(av[z].del || (av[z].v>>1) >= k) continue; - uw = av[z].v; bw = iug->u.a[uw>>1].a[((uw&1)?(iug->u.a[uw>>1].n-1):(0))]>>32; - if(uw&1) bw ^= 1; is_bw_ul = ulg_type((*idx), (bw>>1)); - } - } - -} - -void fill_u2g(ul_resolve_t *uidx, asg64_v *b, asg64_v *ub) -{ - renew_ul2_utg(uidx); - infer_reliable_regions(uidx); -} -**/ - -uint64_t get_ug_integer_seq_occ(ul_resolve_t *uidx, uint64_t *u_a, uint64_t u_n, asg64_v *b) -{ - uint32_t bn = b->n, k, occ; ma_ug_t *raw = uidx->l1_ug; - gen_ug_integer_seq_on_fly(uidx, u_a, u_n, b); - for (k = bn, occ = 0; k < b->n; k++) occ += raw->u.a[b->a[k]>>1].n; - b->n = bn; - return occ; -} - -uint32_t ul_occ_check(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t qocc_ul, uint32_t qocc_hifi, uint32_t tv, float occ_rate, asg64_v *b, asg64_v *ub) -{ - uint32_t bn = b->n, z, tocc_ul, tocc_hifi, ul; - get_ul_path_info(uidx, ug, tv, NULL, NULL, NULL, NULL, NULL, b); - for (z = bn, tocc_ul = 0; z < b->n; z++) { - get_iug_u_raw_occ(uidx, b->a[z]>>1, &ul, NULL); tocc_ul += ul; - } - tocc_hifi = get_ug_integer_seq_occ(uidx, b->a + bn, b->n - bn, ub); - b->n = bn; - if((qocc_ul <= (tocc_ul*occ_rate)) && (qocc_hifi <= (tocc_hifi*occ_rate))) return 1; - return 0; -} - -uint32_t idx_check_rate(uint64_t *a, uint64_t a_n, uint64_t tot, uint64_t winlen, float match_rate) -{ - if(a_n == 0) return 0; - if(tot < winlen) winlen = tot; - uint64_t k, mm = a[0]>>32, ks, s, e; int64_t p; - s = 0; e = winlen; - for (k = ks = 0; k < a_n; k++) { - assert(a[k] != (uint64_t)-1); - // if(mm != (a[k]>>32)) { - // fprintf(stderr, "***[M::%s::] mm::%lu, (a[%lu]>>32)::%lu\n", - // __func__, mm, k, (a[k]>>32)); - // } - assert(mm == (a[k]>>32)); - if(((uint32_t)a[k]) >= s && ((uint32_t)a[k]) < e) continue; - break; - } - p = k; - if(p > 0 && p >= (int64_t)(winlen*match_rate)) return 1; - - for (; k < a_n; k++) { - assert(a[k] != (uint64_t)-1); - assert(mm == (a[k]>>32)); - e = ((uint32_t)a[k]) + 1; p++; - for (; ks < k; ks++) { - if(e - ((uint32_t)a[ks]) <= winlen) break; - p--; - } - assert(p >= 0); - if(p > 0 && p >= (int64_t)(winlen*match_rate)) return 1; - } - return 0; -} - -uint32_t ul_homo_path_check(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t v, uint32_t w, uint32_t raw_ug_occ, float match_rate, asg64_v *b, asg64_v *rb) -{ - // if(((v>>1) == 8158 && (w>>1) == 22318) || ((v>>1) == 16783 && (w>>1) == 28464)) { - // fprintf(stderr, "\n++++++[M::%s::] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u\n", - // __func__, v>>1, v&1, w>>1, w&1); - // } - - bubble_type *bub = uidx->bub; - uint64_t k, l, z, bn = b->n, vn = 0, wn = 0, *va, *wa, rbn = rb->n, *rva, *rwa, rvn, rwn, rid, x; - get_ul_path_info(uidx, ug, v, NULL, NULL, NULL, NULL, NULL, b); vn = b->n - bn; - get_ul_path_info(uidx, ug, w, NULL, NULL, NULL, NULL, NULL, b); wn = b->n - bn - vn; - va = b->a + bn; wa = b->a + bn + vn; - // if(((v>>1) == 8158 && (w>>1) == 22318) || ((v>>1) == 16783 && (w>>1) == 28464)) { - // fprintf(stderr, "[M::%s::] vn::%lu, wn::%lu\n", __func__, vn, wn); - // } - - gen_ug_integer_seq_on_fly(uidx, va, vn, rb); rvn = rb->n - rbn; - gen_ug_integer_seq_on_fly(uidx, wa, wn, rb); rwn = rb->n - rbn - rvn; - rva = rb->a + rbn; rwa = rb->a + rbn + rvn; - // if(((v>>1) == 8158 && (w>>1) == 22318) || ((v>>1) == 16783 && (w>>1) == 28464)) { - // fprintf(stderr, "[M::%s::] rvn::%lu, rwn::%lu, raw_ug_occ::%u\n", __func__, rvn, rwn, raw_ug_occ); - // } - - b->n = bn; - for (k = 0; k < rvn; k++) { - rid = rva[k]>>1; - if(IF_BUB(rid, *bub)) { - x = bub->index[rid]; - x |= ((uint64_t)(0x80000000)); x <<= 32; ///bubble id - } else { - x = rid; ///node id - x <<= 32; - } - x |= (k<<1); kv_push(uint64_t, *b, x); - } - - for (k = 0; k < rwn; k++) { - rid = rwa[k]>>1; - if(IF_BUB(rid, *bub)) { - x = bub->index[rid]; - x |= ((uint64_t)(0x80000000)); x <<= 32; ///bubble id - } else { - x = rid; ///node id - x <<= 32; - } - x |= 1; x |= (k<<1); kv_push(uint64_t, *b, x); - } - radix_sort_srt64(b->a + bn, b->a + b->n); - - uint64_t o[2], c[2]; - for (l = bn, k = bn + 1, o[0] = o[1] = 0; k <= b->n; k++) { - if (k == b->n || (b->a[k]>>32) != (b->a[l]>>32)) { - if((k - l > 1)) { - for (z = l, c[0] = c[1] = 0; z < k; z++) { - c[b->a[z]&1]++; - if(c[0] > 0 && c[1] > 0) break; - } - if(c[0] > 0 && c[1] > 0) { - for (z = l; z < k; z++) { - o[b->a[z]&1]++; - - x = b->a[z]; - x <<= 32; x >>= 32; x >>= 1; - if(b->a[z]&1) x|= ((uint64_t)(0x100000000)); - b->a[z] = x; - } - } else { - for (z = l; z < k; z++) b->a[z] = (uint64_t)-1; - } - } else { - for (z = l; z < k; z++) b->a[z] = (uint64_t)-1; - } - l = k; - } - } - // fprintf(stderr, "\n[M::%s::] rvn::%lu, rwn::%lu, bn::%lu, b->n::%lu, o[0]::%lu, o[1]::%lu\n", __func__, - // rvn, rwn, bn, (uint64_t)b->n, o[0], o[1]); - radix_sort_srt64(b->a + bn, b->a + b->n); b->n = bn + o[0] + o[1]; - b->n = bn; rb->n = rbn; - - if(idx_check_rate(b->a + bn, o[0], rvn, raw_ug_occ, match_rate)) return 1; - if(idx_check_rate(b->a + bn + o[0], o[1], rwn, raw_ug_occ, match_rate)) return 1; - - // if(o[0] >= (rvn*match_rate)) return 1; - // if(o[1] >= (rwn*match_rate)) return 1; - - return 0; -} - -///small_occ_rate = 0.15; len_rat = 1.5 -uint32_t ulg_arc_cut_z(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t max_ext, uint32_t max_ext_hifi, -float len_rat, float small_occ_rate, uint32_t raw_ug_occ, float raw_match_rate, uint32_t is_trio, -uint32_t skip_hom, uint32_t *max_drop_len, asg64_v *in, asg64_v *ib) -{ - asg64_v tx = {0,0,0}, tb = {0,0,0}, *b = NULL, *ub = NULL; asg_t *g = ug->g; - uint32_t v, w, wt, z, i, k, kv, nv, kw, kwt, nw, cnt = 0, n_vtx = g->n_seq<<1, ul, vp[2], wp[2]; - asg_arc_t *av, *aw, *ve, *we, *wte; uint64_t w_q, w_t, pb, raw_ul, raw_hifi; - - b = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); - for (v = b->n = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - av = asg_arc_a(g, v); nv = asg_arc_n(g, v); - if (nv < 2) continue; - for (i = kv = 0; i < nv && kv <= 2; ++i) { - if(av[i].del) continue; kv++; - } - if(kv != 2) continue; - for (i = 0; i < nv; ++i) { - if(av[i].del) continue; - kw = get_arcs(ug->g, av[i].v^1, NULL, 0); - // if((v>>1) == 16783) { - // fprintf(stderr, "sss[M::%s::] v>>1::%u, v&1::%u, av[i].v>>1::%u, av[i].v&1::%u, kw::%u\n", - // __func__, v>>1, v&1, av[i].v>>1, av[i].v&1, kw); - // } - if(kw == 2) { - kv_push(uint64_t, *b, ((uint64_t)(av-g->arc+i))); - } else if(kw == 1) { - ub->n = 0; - if(get_ul_path_info(uidx, ug, av[i].v, NULL, NULL, NULL, NULL, NULL, ub)==TWO_INPUT) { - for (z = raw_ul = 0; z < ub->n; z++) { - get_iug_u_raw_occ(uidx, ub->a[z]>>1, &ul, NULL); raw_ul += ul; - } - kv_push(uint64_t, *b, ((raw_ul<<32)|((uint64_t)(av-g->arc+i)))); - } - } - } - } - - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - if(g->arc[(uint32_t)b->a[k]].del) continue; - v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; - if(g->seq[v>>1].del || g->seq[w>>1].del) continue; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); - if(nv <= 1 && nw <= 1) continue; - - vp[0] = v^1; vp[1] = (uint32_t)-1; - ve = &(g->arc[(uint32_t)b->a[k]]); - for (i = kv = 0; i < nv; ++i) { - if(av[i].del) continue; - if(av[i].v != (w^1)) vp[1] = av[i].v; - kv++; - } - - wp[0] = w^1; wp[1] = (uint32_t)-1; - for (i = kw = 0, we = NULL; i < nw; ++i) { - if (aw[i].del) continue; - if (aw[i].v == (v^1)) we = &(aw[i]); - else wp[1] = aw[i].v; - kw++; - } - if(kv <= 1 && kw <= 1) continue; - if(kv != 2 || kw > 2) continue; - // if((v>>1) == 16783) { - // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, kv::%u, kw::%u\n", - // __func__, v>>1, v&1, w>>1, w&1, kv, kw); - // } - raw_ul = 0; wt = w; wte = we; kwt = kw; pb = b->n; ub->n = 0; - if(kw == 1) { - if(get_ul_path_info(uidx, ug, w^1, &wt, NULL, NULL, NULL, NULL, b)==TWO_INPUT) { - for (z = pb, raw_ul = 0; z < b->n; z++) { - get_iug_u_raw_occ(uidx, b->a[z]>>1, &ul, NULL); raw_ul += ul; - } - ul = wt; get_arcs(ug->g, wt, &wt, 1); wt = ug->g->arc[wt].v^1; - wp[0] = wt^1; wp[1] = (uint32_t)-1; - nw = asg_arc_n(g, wt); aw = asg_arc_a(g, wt); - for (i = kwt = 0; i < nw; ++i) { - if (aw[i].del) continue; - if (aw[i].v == (ul^1)) wte = &(aw[i]); - else wp[1] = aw[i].v; - kwt++; - } - // if((v>>1) == 16783) { - // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, wt>>1::%u, wt&1::%u, kwt::%u\n", - // __func__, v>>1, v&1, w>>1, w&1, wt>>1, wt&1, kwt); - // } - nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); - } else { - b->n = pb; - continue; - } - } - // if((v>>1) == 16783) { - // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, raw_ul::%lu, max_ext::%u, ***1***\n", - // __func__, v>>1, v&1, raw_ul, max_ext); - // } - assert(kv == 2 && kwt == 2); - if(raw_ul <= max_ext && get_remove_hifi_occ(uidx, max_ext_hifi, b->a + pb, b->n - pb, ub, NULL)) { - raw_hifi = get_ug_integer_seq_occ(uidx, b->a + pb, b->n - pb, ub); - // if((v>>1) == 16783) { - // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, ***2***\n", - // __func__, v>>1, v&1); - // } - - b->n = pb; - if(raw_ul > 0) { - if(!ul_occ_check(uidx, ug, raw_ul, raw_hifi, vp[0], small_occ_rate, b, ub)) continue; - if(!ul_occ_check(uidx, ug, raw_ul, raw_hifi, vp[1], small_occ_rate, b, ub)) continue; - if(!ul_occ_check(uidx, ug, raw_ul, raw_hifi, wp[0], small_occ_rate, b, ub)) continue; - if(!ul_occ_check(uidx, ug, raw_ul, raw_hifi, wp[1], small_occ_rate, b, ub)) continue; - } - - // if((v>>1) == 16783) { - // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, ***3***\n", - // __func__, v>>1, v&1); - // } - pb = b->n; ub->n = 0; - get_ul_arc_supports(uidx, ve, b, ub, skip_hom, &w_q, &w_t); - b->n = pb; ub->n = 0; - if((w_q == (uint64_t)-1) || (w_q > w_t*len_rat)) continue; - - // if((v>>1) == 16783) { - // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, ***4***\n", - // __func__, v>>1, v&1); - // } - - pb = b->n; ub->n = 0; - get_ul_arc_supports(uidx, wte, b, ub, skip_hom, &w_q, &w_t); - b->n = pb; ub->n = 0; - if((w_q == (uint64_t)-1) || (w_q > w_t*len_rat)) continue; - - // if((v>>1) == 16783) { - // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, ***5***\n", - // __func__, v>>1, v&1); - // } - - if(!ul_homo_path_check(uidx, ug, vp[0], wp[1], raw_ug_occ, raw_match_rate, b, ub)) continue; - - - // if((v>>1) == 16783) { - // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, ***6***\n", - // __func__, v>>1, v&1); - // } - if(!ul_homo_path_check(uidx, ug, wp[0], vp[1], raw_ug_occ, raw_match_rate, b, ub)) continue; - - // if((v>>1) == 16783) { - // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, ***7***\n", - // __func__, v>>1, v&1); - // } - - if(kw == 1) { - get_ul_path_info(uidx, ug, w^1, &wt, NULL, NULL, NULL, NULL, b); - for (z = pb; z < b->n; z++) ulg_seq_del(ug, (b->a[z]>>1)); - } - ve->del = we->del = 1; cnt++; - } - - b->n = pb; - } - - - - if(!in) free(tx.a); if(!ib) free(tb.a); - if (cnt > 0) asg_cleanup(g); - // fprintf(stderr, "[M::%s::] cnt::%u\n", __func__, cnt); - return cnt; -} - - -usg_seq_t *push_usg_t_node(usg_t *ng, uint64_t id) -{ - if(id >= ng->m) { - uint64_t m = ng->m; - kv_resize(usg_seq_t, *ng, id + 1); - memset(ng->a + m, 0, (ng->m - m)*(sizeof((*ng->a)))); - } - if(id >= ng->n) ng->n = id + 1; - - return ng->a + id; -} - -static void worker_update_ul_arc_drop(void *data, long i, int tid) // callback for kt_for() -{ - ul_resolve_t *uidx = (ul_resolve_t *)data; integer_t *buf = &(uidx->str_b.buf[tid]); - ul_str_idx_t *str_idx = &(uidx->pstr); uinfo_srt_warp_t *seq = uidx->uovl.iug_seq; - uint32_t v = seq->a[i].v, z, vz; uint64_t *hid_a, hid_n; ul_str_t *str; - int64_t s_n, s, p, p_n = seq->n; uint64_t cutoff = uidx->uovl.iug_cov_thre, occ; - - hid_a = str_idx->occ.a + str_idx->idx.a[v>>1]; - hid_n = str_idx->idx.a[(v>>1)+1] - str_idx->idx.a[v>>1]; - for (z = occ = 0; z < hid_n; z++) { - str = &(str_idx->str.a[hid_a[z]>>32]); s_n = str->cn; - if(s_n < 2) continue; - vz = (uint32_t)(str->a[(uint32_t)hid_a[z]]); - assert((v>>1) == (vz>>1)); - - if(v == vz) { - s = ((uint32_t)hid_a[z]) + 1; p = i + 1; - if((s < s_n) && (p < p_n) && ((uint32_t)(str->a[s]) == seq->a[p].v)) { - occ++; - } - } else { - s = ((int32_t)((uint32_t)hid_a[z]))-1; p = i + 1; - if((s >= 0) && (p < p_n) && ((uint32_t)(str->a[s]) == (seq->a[p].v^1))) { - occ++; - } - } - if(occ >= cutoff) break; - } - - if(occ < cutoff) kv_push(uint64_t, buf->res_dump, i); -} - -inline usg_arc_t* get_usg_arc(usg_t *g, uint32_t v, uint32_t w) -{ - usg_arc_t *av = usg_arc_a(g, v); uint32_t nv = usg_arc_n(g, v), k; - for (k = 0; k < nv; k++) { - if(av[k].v == w) break; - } - - if(k < nv) return (&av[k]); - return NULL; -} - -void pushp_usg_arc_mm(usg_t *g, uint32_t v, uint32_t w, uint32_t uid, uint32_t off) -{ - usg_arc_mm_t *pm; - kv_pushp(usg_arc_mm_t, g->a[v>>1].arc_mm[v&1], &pm); - pm->v = w; pm->uid = uid; pm->off = off; -} - -static inline void usg_seq_del(usg_t *g, uint32_t s) -{ - uint32_t i, nv, v; usg_arc_t *av, *p; - g->a[s].del = 1; - // fprintf(stderr, "\n#[M::%s::] s::%u\n", __func__, s); - v = s<<1; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (i = 0; i < nv; ++i) { - av[i].del = 1; - p = get_usg_arc(g, av[i].v^1, v^1); - // if(!p) { - // fprintf(stderr, "**+**[M::%s::] v>>1::%u, v&1::%u, av[i].v>>1::%u, av[i].v&1::%u\n", - // __func__, v>>1, v&1, av[i].v>>1, av[i].v&1); - // } - p->del = 1; - } - - v = (s<<1)+1; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (i = 0; i < nv; ++i) { - av[i].del = 1; - p = get_usg_arc(g, av[i].v^1, v^1); - // if(!p) { - // fprintf(stderr, "**-**[M::%s::] v>>1::%u, v&1::%u, av[i].v>>1::%u, av[i].v&1::%u\n", - // __func__, v>>1, v&1, av[i].v>>1, av[i].v&1); - // } - p->del = 1; - } - - // g->a[s].arc[0].n = g->a[s].arc[1].n = 0; -} - -static void worker_clean_usg(void *data, long i, int tid) // callback for kt_for() -{ - usg_t *g = (usg_t *)data; usg_seq_t *z = g->a + i; uint32_t k, m, l, srt; - usg_arc_warp *x; usg_arc_mm_warp *y; - if(z->del) z->arc[0].n = z->arc[1].n = 0; - - x = &(z->arc[0]); y = &(z->arc_mm[0]); - for (k = m = srt = 0; k < x->n; k++) { - if(x->a[k].del) continue; - x->a[m] = x->a[k]; x->a[m].idx = 0; - if(m > 0 && x->a[m].v < x->a[m-1].v) srt = 1; - m++; - } - x->n = m; if(srt) radix_sort_usg_arc_srt(x->a, x->a + x->n); - - radix_sort_usg_arc_mm_srt(y->a, y->a + y->n); k = l = m = 0; - while (k < y->n && l < x->n) { - if(y->a[k].v < x->a[l].v) { - k++; - } else if(y->a[k].v > x->a[l].v) { - l++; - } else { - y->a[m].v = y->a[k].v; - if(m > 0 && y->a[m].v == y->a[m-1].v) { - x->a[l].idx++; - } else { - x->a[l].idx = m; x->a[l].idx <<= 32; x->a[l].idx++; - } - m++; k++; - } - } - y->n = m; - - - - x = &(z->arc[1]); y = &(z->arc_mm[1]); - for (k = m = srt = 0; k < x->n; k++) { - if(x->a[k].del) continue; - x->a[m] = x->a[k]; x->a[m].idx = 0; - if(m > 0 && x->a[m].v < x->a[m-1].v) srt = 1; - m++; - } - x->n = m; if(srt) radix_sort_usg_arc_srt(x->a, x->a + x->n); - - radix_sort_usg_arc_mm_srt(y->a, y->a + y->n); k = l = m = 0; - while (k < y->n && l < x->n) { - if(y->a[k].v < x->a[l].v) { - k++; - } else if(y->a[k].v > x->a[l].v) { - l++; - } else { - y->a[m].v = y->a[k].v; - if(m > 0 && y->a[m].v == y->a[m-1].v) { - x->a[l].idx++; - } else { - x->a[l].idx = m; x->a[l].idx <<= 32; x->a[l].idx++; - } - m++; k++; - } - } - y->n = m; - -} - -void usg_cleanup(usg_t *g) -{ - kt_for(asm_opt.thread_num, worker_clean_usg, g, g->n); -} - -static inline int usg_end(const usg_t *g, uint32_t v, uint64_t *lw) -{ - ///v^1 is the another direction of v - uint32_t w, nv, nw, nw0, nv0 = usg_arc_n(g, v^1); - int i, i0 = -1; - usg_arc_t *aw, *av = usg_arc_a(g, v^1); - - ///if this arc has not been deleted - for (i = nv = 0; i < (int)nv0; ++i) - if (!av[i].del) i0 = i, ++nv; - - ///end without any out-degree - if (nv == 0) return ASG_ET_TIP; // tip - if (nv > 1) return ASG_ET_MULTI_OUT; // multiple outgoing arcs - ///until here, nv == 1 - if (lw) *lw = ((uint64_t)(v^1))<<32 | av[i0].v; - w = av[i0].v^1; - nw0 = usg_arc_n(g, w); aw = usg_arc_a(g, w); - for (i = nw = 0; i < (int)nw0; ++i) - if (!aw[i].del) ++nw; - - if (nw != 1) return ASG_ET_MULTI_NEI; - return ASG_ET_MERGEABLE; -} - -uint32_t usg_real_tip(usg_t *g, uint32_t v0, double rate) -{ - usg_arc_t *av, *aw; uint32_t nv, nw, i, k, ov, ow; - av = usg_arc_a(g, v0); - nv = usg_arc_n(g, v0); - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - aw = usg_arc_a(g, (av[i].v^1)); - nw = usg_arc_n(g, (av[i].v^1)); - for (k = ov = ow = 0; k < nw; k++) { - if(aw[k].del) continue; - if((aw[k].v>>1) == (v0>>1)) { - if(aw[k].ol > ov) ov = aw[k].ol; - } else { - if(aw[k].ol > ow) ow = aw[k].ol; - } - } - if(ow == 0 || ov >= ow) return 0; - if(ov > (ow*rate)) return 0; - } - return 1; -} - - -uint32_t usg_arc_cut_tips(usg_t *g, uint32_t max_ext, uint32_t ignore_ul, asg64_v *in) -{ - asg64_v tx = {0,0,0}, *b = NULL; - uint32_t n_vtx = g->n<<1, v, w, i, k, cnt = 0, nv, kv, pb, ff, is_telo; - usg_arc_t *av = NULL, *p; uint64_t lw; - if(in) b = in; - else b = &tx; - - for (v = b->n = 0; v < n_vtx; ++v) { - if (g->a[v>>1].del) continue; - - av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); - for (i = kv = 0; i < nv; i++) { - if (av[i].del) continue; - kv++; break; - } - - if(kv) continue; - - is_telo = 0; if(g->a[v>>1].telo) is_telo = 1; - for (i = 0, w = v, kv = g->a[v>>1].occ; i < max_ext; i++) { - if(usg_end(g, w^1, &lw)!=0) break; - w = (uint32_t)lw; kv += g->a[w>>1].occ; - if(g->a[w>>1].telo) is_telo = 1; - } - if((kv <= max_ext) && (!is_telo)) kv_push(uint64_t, *b, (((uint64_t)kv)<<32)|v); - } - - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - v = (uint32_t)(b->a[k]); - if (g->a[v>>1].del) continue; - - av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); - for (i = kv = 0; i < nv; i++) { - if (av[i].del) continue; - kv++; break; - } - - if(kv) continue; - pb = b->n; kv_push(uint64_t, *b, v); - is_telo = 0; if(g->a[v>>1].telo) is_telo = 1; - for (i = 0, w = v, kv = g->a[v>>1].occ; i < max_ext; i++) { - if(usg_end(g, w^1, &lw)!=0) break; - w = (uint32_t)lw; kv += g->a[w>>1].occ; kv_push(uint64_t, *b, lw); - if(g->a[w>>1].telo) is_telo = 1; - } - // if((v>>1) == 308) { - // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, kv::%u\n", - // __func__, v>>1, v&1, kv); - // } - - - if((kv <= max_ext) && (!is_telo)) { - ff = 0; - if(!ignore_ul) {///consider UL - for (i = pb; i + 1 < b->n; i++) { - p = get_usg_arc(g, ((uint32_t)b->a[i]), ((uint32_t)b->a[i+1])); assert(p); - if(p->ou > 1) {//ignore ou == 1 - ff = 1; - break; - } - } - - if(ff == 0 && i < b->n) { - av = usg_arc_a(g, ((uint32_t)b->a[i])); nv = usg_arc_n(g, ((uint32_t)b->a[i])); - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - if(av[i].ou > 1) {//ignore ou == 1 - ff = 1; - break; - } - } - } - } - - // if((v>>1) == 139131) { - // fprintf(stderr, "+[M::%s::] v>>1::%u, v&1::%u, kv::%u, ff::%u, pb::%u, b->n::%u, w>>1::%u, w&1::%u\n", __func__, v>>1, v&1, kv, - // ff, pb, (uint32_t)b->n, ((uint32_t)b->a[b->n-1])>>1, ((uint32_t)b->a[b->n-1])&1); - // } - - if((ff == 0) && (pb < b->n) && (!usg_real_tip(g, ((uint32_t)b->a[b->n-1]), 0.75))) { - ff = 1; - } - - // if((v>>1) == 139131) { - // fprintf(stderr, "-[M::%s::] v>>1::%u, v&1::%u, kv::%u, ff::%u, pb::%u, b->n::%u, w>>1::%u, w&1::%u\n", __func__, v>>1, v&1, kv, - // ff, pb, (uint32_t)b->n, ((uint32_t)b->a[b->n-1])>>1, ((uint32_t)b->a[b->n-1])&1); - // } - - if(ff == 0) { - for (i = pb; i < b->n; i++) usg_seq_del(g, ((uint32_t)b->a[i])>>1); - cnt++; - } - - // if((v>>1) == 139131) { - // fprintf(stderr, ">[M::%s::] v>>1::%u, v&1::%u, kv::%u, ff::%u, pb::%u, b->n::%u, w>>1::%u, w&1::%u, del::%u\n", __func__, v>>1, v&1, kv, - // ff, pb, (uint32_t)b->n, ((uint32_t)b->a[b->n-1])>>1, ((uint32_t)b->a[b->n-1])&1, - // g->a[((uint32_t)b->a[b->n-1])>>1].del); - // } - } - b->n = pb; - } - - if(!in) free(tx.a); - if(cnt > 0) usg_cleanup(g); - - return cnt; -} - -///check if v has only one branch - -int32_t usg_tip_detect(usg_t *g, uint32_t v0, int max_ext, uint8_t *f, asg64_v *z_a, asg64_v *z_b) -{ - uint64_t a_n = z_a->n, b_n = z_b->n, v = v0, kv, nv, i; - int32_t n_ext = 0; usg_arc_t *av; - - av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); - for (i = kv = 0; i < nv && kv <= 1; i++) { - if (av[i].del || f[av[i].v>>1]) continue; - kv++; - } - if(kv > 1) return 0; - n_ext += g->a[v>>1].occ; f[v>>1] = 1; kv_push(uint64_t, *z_b, v>>1); - - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (i = 0; i < nv; i++) { - if (av[i].del || f[av[i].v>>1]) continue; - kv_push(uint64_t, *z_a, av[i].v); - } - - while (z_a->n > a_n && n_ext < max_ext) { - v = z_a->a[--z_a->n]; if(f[v>>1]) continue; - - av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); - for (i = kv = 0; i < nv && kv < 1; i++) { - if (av[i].del || f[av[i].v>>1]) continue; - kv++; - } - if(kv > 0) continue; - n_ext += g->a[v>>1].occ; f[v>>1] = 1; kv_push(uint64_t, *z_b, v>>1); - - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (i = 0; i < nv; i++) { - if (av[i].del || f[av[i].v>>1]) continue; - kv_push(uint64_t, *z_a, av[i].v); - } - } - - for (i = b_n; i < z_b->n; i++) f[z_b->a[i]] = 0; - z_b->n = b_n; z_a->n = a_n; - return n_ext; -} - -int usg_naive_topocut_aux(usg_t *g, uint32_t v, int max_ext, uint8_t *f, asg64_v *b0, asg64_v *b1) -{ - int32_t n_ext; usg_arc_t *av; uint32_t w = v, v0 = v, nv, i, kv, tip; - for (n_ext = tip = 0; n_ext < max_ext; v = w) { - tip = 0; - av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); - for (i = kv = 0; i < nv && kv <= 1; i++) { - if (av[i].del) continue; - kv++; - } - if(kv!=1) break; - n_ext += g->a[v>>1].occ; - - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (i = kv = 0; i < nv && kv <= 1; i++) { - if (av[i].del) continue; - kv++; w = av[i].v; - } - if(kv!=1) { - if(kv > 1) tip = 1; - break; - } - } - - if(n_ext < max_ext && tip) { - n_ext = usg_tip_detect(g, v0, max_ext, f, b0, b1); - } - return n_ext; -} - - -int usg_naive_topocut_aux_sec(usg_t *g, uint32_t v0, int max_ext) -{ - int32_t n_ext = 0; usg_arc_t *av; uint32_t w = (uint32_t)-1, v = v0, nv, i, kv, tip[2] = {0}; - v = v0; - while (1) { - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (i = kv = 0; i < nv; i++) { - if (av[i].del) continue; - kv++; w = av[i].v; - } - n_ext += g->a[v>>1].occ; - // if((v0>>1) == 306) { - // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, n_ext::%d\n", __func__, v>>1, v&1, n_ext); - // } - if(kv != 1) { - if(kv == 0) tip[0] = 1; - break; - } - v = w; - - av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); - for (i = kv = 0; i < nv; i++) { - if (av[i].del) continue; - kv++; - } - if(kv != 1) break; - if(v == v0) return 0;///circle, it is ok to remove it - } - - v = v0^1; - while (1) { - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (i = kv = 0; i < nv; i++) { - if (av[i].del) continue; - kv++; w = av[i].v; - } - n_ext += g->a[v>>1].occ; - // if((v0>>1) == 306) { - // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, n_ext::%d\n", __func__, v>>1, v&1, n_ext); - // } - if(kv != 1) { - if(kv == 0) tip[1] = 1; - break; - } - v = w; - - av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); - for (i = kv = 0; i < nv; i++) { - if (av[i].del) continue; - kv++; - } - if(kv != 1) break; - if(v == (v0^1)) return 0;///circle, it is ok to remove it - } - - n_ext -= g->a[v0>>1].occ; - // if((v0>>1) == 306) { - // fprintf(stderr, "[M::%s::] n_ext::%d, tip[0]::%u, tip[1]::%u\n", __func__, n_ext, tip[0], tip[1]); - // } - if((tip[0] || tip[1]) && (n_ext >= max_ext)) return n_ext; - - return 0; -} - -void usg_arc_cut_length(usg_t *g, asg64_v *in_0, asg64_v *in_1, int32_t max_ext, float len_rat, uint32_t is_trio, -uint32_t is_topo, uint32_t *max_drop_len) -{ - // if(len_rat > 0.7) { - // fprintf(stderr, "+[M::%s::] max_ext::%d, len_rat::%f\n", __func__, max_ext, len_rat); - // } - asg64_v tx = {0,0,0}, tz = {0,0,0}, *b = NULL, *ub = NULL; - uint32_t i, k, v, w, n_vtx = g->n<<1, nv, nw, kv, kw, /**trioF = (uint32_t)-1, ntrioF = (uint32_t)-1,**/ ol_max, ou_max, to_del, cnt = 0, mm_ol; - usg_arc_t *av, *aw, *ve, *we; uint64_t x, kocc[2], ou; uint8_t *f; CALLOC(f, g->n); - b = ((in_0)?(in_0):(&tx)); ub = ((in_1)?(in_1):(&tz)); - - for (v = 0, b->n = ub->n = 0; v < n_vtx; ++v) { - if (g->a[v>>1].del) continue; - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - if (nv < 2) continue; - for (i = kv = kocc[0] = kocc[1] = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - if((av[i].ou>>1) > 0) { ///if av[i].ou == 1, ignore it - if(kocc[1] < (av[i].ou>>1)) kocc[1] = (av[i].ou>>1); - } else if(av[i].ou == 0) { - kocc[0]++; - } - } - if(kv < 2 || kocc[0] == 0 || kocc[1] == 0) continue; - ou = kocc[1]; - for (i = 0; i < nv; ++i) { - if(av[i].del || av[i].ou) continue; - if(max_drop_len && av[i].ol >= (*max_drop_len)) continue; - x = (((uint64_t)av[i].ol)*10)/ou; x <<= 32; - kv_push(uint64_t, *b, ((x)|((uint64_t)(ub->n)))); - kv_push(uint64_t, *ub, ((((uint64_t)(v))<<32)|((uint64_t)(i)))); - } - } - // if(len_rat > 0.7) { - // fprintf(stderr, "[M::%s::] max_ext::%d, len_rat::%f, b->n::%u, ub->n::%u\n", - // __func__, max_ext, len_rat, (uint32_t)b->n, (uint32_t)ub->n); - // } - - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - v = ub->a[(uint32_t)b->a[k]]>>32; - ve = &(usg_arc_a(g, v)[(uint32_t)(ub->a[(uint32_t)b->a[k]])]); - w = ve->v^1; - if(ve->del || g->a[v>>1].del || g->a[w>>1].del || ve->ou) continue; - nv = usg_arc_n(g, v); nw = usg_arc_n(g, w); - av = usg_arc_a(g, v); aw = usg_arc_a(g, w); - if(nv<=1 && nw <= 1) continue; - - // if(is_trio) { - // if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup - // trioF = get_tip_trio_infor(g, v^1); - // ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); - // } - for (i = 0; i < nw; ++i) { - if (aw[i].v == (v^1)) { - we = &(aw[i]); - break; - } - } - mm_ol = MIN(ve->ol, we->ol); kocc[0] = kocc[1] = 0; - - for (i = kv = ol_max = ou_max = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - if(av[i].ou != 1) kocc[!!(av[i].ou)]++; ///if av[i].ou == 1, ignore it - // if(is_trio && get_tip_trio_infor(g, av[i].v) == ntrioF) continue; - if(ol_max < av[i].ol) ol_max = av[i].ol; - } - if (kv < 1 || kocc[0] < 1 || kocc[1] < 1) continue; - if (kv >= 2) { - if (mm_ol > ol_max*len_rat) continue; - } - - - for (i = kw = ol_max = ou_max = 0; i < nw; ++i) { - if(aw[i].del) continue; - kw++; - // if(is_trio && get_tip_trio_infor(g, aw[i].v) == ntrioF) continue; - if(ol_max < aw[i].ol) ol_max = aw[i].ol; - } - if (kw < 1) continue; - if (kw >= 2) { - if (mm_ol > ol_max*len_rat) continue; - } - - if (kv <= 1 && kw <= 1) continue; - // if(len_rat > 0.7) { - // fprintf(stderr, "0[M::%s::] v>>1::%u(%c), w>>1::%u(%c), kv::%u, kw::%u\n", - // __func__, v>>1, "+-"[v&1], w>>1, "+-"[w&1], kv, kw); - // } - - to_del = 1; - if(is_topo) { - to_del = 0; - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (usg_naive_topocut_aux(g, w^1, max_ext, f, b, ub) < max_ext) to_del = 1; - } else if (kv == 1) { - if (usg_naive_topocut_aux(g, v^1, max_ext, f, b, ub) < max_ext) to_del = 1; - } - } - // if(len_rat > 0.7) { - // fprintf(stderr, "1[M::%s::] v>>1::%u(%c), w>>1::%u(%c), kv::%u, kw::%u, to_del::%u\n", - // __func__, v>>1, "+-"[v&1], w>>1, "+-"[w&1], kv, kw, to_del); - // } - - if (to_del) { - ve->del = we->del = 1; - if((usg_naive_topocut_aux_sec(g, v, max_ext) < max_ext) && - (usg_naive_topocut_aux_sec(g, w, max_ext) < max_ext)) { - // if((((v>>1) == 308) && ((w>>1) == 311)) || (((w>>1) == 308) && ((v>>1) == 311))) { - // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, max_ext::%d\n", - // __func__, v>>1, v&1, kv, w>>1, w&1, kw, max_ext); - // } - // if((((v>>1) == 306) && ((w>>1) == 310)) || (((w>>1) == 306) && ((v>>1) == 310))) { - // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, max_ext::%d\n", - // __func__, v>>1, v&1, kv, w>>1, w&1, kw, max_ext); - // } - ++cnt; - } else { - ve->del = we->del = 0; - } - - } - // if(len_rat > 0.7) { - // fprintf(stderr, "2[M::%s::] v>>1::%u(%c), w>>1::%u(%c), kv::%u, kw::%u, to_del::%u\n", - // __func__, v>>1, "+-"[v&1], w>>1, "+-"[w&1], kv, kw, to_del); - // } - } - - if(in_0) free(tx.a); if(in_1) free(tz.a); - if (cnt > 0) usg_cleanup(g); - free(f); - // fprintf(stderr, "-[M::%s::] max_ext::%d, len_rat::%f\n", __func__, max_ext, len_rat); -} - -void usg_arc_cut_srt_length(usg_t *g, asg64_v *in_0, asg64_v *in_1, int32_t max_ext, float len_rat, uint32_t is_trio, -uint32_t is_topo, uint32_t *max_drop_len, uint8_t *ff) -{ - asg64_v tx = {0,0,0}, tz = {0,0,0}, *b = NULL, *ub = NULL; - uint32_t i, k, v, w, n_vtx = g->n<<1, nv, nw, kv, kw, /**trioF = (uint32_t)-1, ntrioF = (uint32_t)-1,**/ ol_max, ou_max, to_del, cnt = 0, mm_ol; - usg_arc_t *av, *aw, *ve, *we; uint64_t x, kocc[2]; uint8_t *f; CALLOC(f, g->n); - b = ((in_0)?(in_0):(&tx)); ub = ((in_1)?(in_1):(&tz)); - - for (v = 0, b->n = ub->n = 0; v < n_vtx; ++v) { - if (g->a[v>>1].del || ff[v]) continue; - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - if (nv < 2) continue; - for (i = kv = kocc[0] = kocc[1] = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - if((av[i].ou>>1) > 0) { ///if av[i].ou == 1, ignore it - if(kocc[1] < (av[i].ou>>1)) kocc[1] = (av[i].ou>>1); - } else if(av[i].ou == 0) { - kocc[0]++; - } - } - if(kv < 2 || kocc[0] == 0 || kocc[1] == 0) continue; - for (i = 0; i < nv; ++i) { - if(av[i].del || av[i].ou) continue; - if(max_drop_len && av[i].ol >= (*max_drop_len)) continue; - x = av[i].ol; x <<= 32; - kv_push(uint64_t, *b, ((x)|((uint64_t)(ub->n)))); - kv_push(uint64_t, *ub, ((((uint64_t)(v))<<32)|((uint64_t)(i)))); - } - } - - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - v = ub->a[(uint32_t)b->a[k]]>>32; - ve = &(usg_arc_a(g, v)[(uint32_t)(ub->a[(uint32_t)b->a[k]])]); - w = ve->v^1; - if(ve->del || g->a[v>>1].del || g->a[w>>1].del || ve->ou) continue; - nv = usg_arc_n(g, v); nw = usg_arc_n(g, w); - av = usg_arc_a(g, v); aw = usg_arc_a(g, w); - if(nv<=1 && nw <= 1) continue; - - // if(is_trio) { - // if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup - // trioF = get_tip_trio_infor(g, v^1); - // ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); - // } - for (i = 0; i < nw; ++i) { - if (aw[i].v == (v^1)) { - we = &(aw[i]); - break; - } - } - mm_ol = MIN(ve->ol, we->ol); kocc[0] = kocc[1] = 0; - - for (i = kv = ol_max = ou_max = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - if(av[i].ou != 1) kocc[!!(av[i].ou)]++; ///if av[i].ou == 1, ignore it - // if(is_trio && get_tip_trio_infor(g, av[i].v) == ntrioF) continue; - if(ol_max < av[i].ol) ol_max = av[i].ol; - } - if (kv < 1 || kocc[0] < 1 || kocc[1] < 1) continue; - if (kv >= 2) { - if (mm_ol > ol_max*len_rat) continue; - } - - - for (i = kw = ol_max = ou_max = 0; i < nw; ++i) { - if(aw[i].del) continue; - kw++; - // if(is_trio && get_tip_trio_infor(g, aw[i].v) == ntrioF) continue; - if(ol_max < aw[i].ol) ol_max = aw[i].ol; - } - if (kw < 1) continue; - if (kw >= 2) { - if (mm_ol > ol_max*len_rat) continue; - } - - if (kv <= 1 && kw <= 1) continue; - // if(len_rat > 0.7) { - // fprintf(stderr, "0[M::%s::] v>>1::%u(%c), w>>1::%u(%c), kv::%u, kw::%u\n", - // __func__, v>>1, "+-"[v&1], w>>1, "+-"[w&1], kv, kw); - // } - - to_del = 1; - if(is_topo) { - to_del = 0; - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - if (usg_naive_topocut_aux(g, w^1, max_ext, f, b, ub) < max_ext) to_del = 1; - } else if (kv == 1) { - if (usg_naive_topocut_aux(g, v^1, max_ext, f, b, ub) < max_ext) to_del = 1; - } - } - // if(len_rat > 0.7) { - // fprintf(stderr, "1[M::%s::] v>>1::%u(%c), w>>1::%u(%c), kv::%u, kw::%u, to_del::%u\n", - // __func__, v>>1, "+-"[v&1], w>>1, "+-"[w&1], kv, kw, to_del); - // } - - if (to_del) { - ve->del = we->del = 1; - if((usg_naive_topocut_aux_sec(g, v, max_ext) < max_ext) && - (usg_naive_topocut_aux_sec(g, w, max_ext) < max_ext)) { - // if((((v>>1) == 308) && ((w>>1) == 311)) || (((w>>1) == 308) && ((v>>1) == 311))) { - // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, max_ext::%d\n", - // __func__, v>>1, v&1, kv, w>>1, w&1, kw, max_ext); - // } - // if((((v>>1) == 306) && ((w>>1) == 310)) || (((w>>1) == 306) && ((v>>1) == 310))) { - // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, max_ext::%d\n", - // __func__, v>>1, v&1, kv, w>>1, w&1, kw, max_ext); - // } - ++cnt; - } else { - ve->del = we->del = 0; - } - - } - // if(len_rat > 0.7) { - // fprintf(stderr, "2[M::%s::] v>>1::%u(%c), w>>1::%u(%c), kv::%u, kw::%u, to_del::%u\n", - // __func__, v>>1, "+-"[v&1], w>>1, "+-"[w&1], kv, kw, to_del); - // } - } - - if(in_0) free(tx.a); if(in_1) free(tz.a); - if (cnt > 0) usg_cleanup(g); - free(f); - // fprintf(stderr, "-[M::%s::] max_ext::%d, len_rat::%f\n", __func__, max_ext, len_rat); -} - - -inline int undel_arcs(usg_t *g, uint32_t v, uint32_t* v_s) -{ - uint32_t i, nv = usg_arc_n(g, v), kv; - usg_arc_t *av = usg_arc_a(g, v); - for (i = kv = 0; i < nv; i++) { - if(av[i].del) continue; - if(v_s) v_s[kv] = av[i].v; - kv++; - } - return kv; -} - -inline uint32_t get_usg_unitig(usg_t *g, uint32_t begNode, uint32_t* endNode, -uint64_t* nodeLen, uint64_t* baseLen, uint64_t *occ, asg64_v* b) -{ - uint32_t v = begNode, w, k; usg_arc_t *av; - uint32_t nv, kv, return_flag; - if(endNode) (*endNode) = (uint32_t)-1; - if(nodeLen) (*nodeLen) = 0; - if(baseLen) (*baseLen) = 0; - if(occ) (*occ) = 0; - - while (1) { - kv = undel_arcs(g, v, NULL); - if(endNode) (*endNode) = v; - if(nodeLen) (*nodeLen) += g->a[v>>1].occ; - - if(b) kv_push(uint64_t, *b, v); - if(occ) (*occ)++; - ///means reach the end of a unitig - if(kv!=1 && baseLen) (*baseLen) += g->a[v>>1].len; - if(kv==0) { - return_flag = END_TIPS; break; - } - if(kv>1) { - return_flag = MUL_OUTPUT; break; - } - ///kv must be 1 here - kv = undel_arcs(g, v, &w); - ///means reach the end of a unitig - if(undel_arcs(g, w^1, NULL)!=1) { - if(baseLen) (*baseLen) += g->a[v>>1].len; - return_flag = MUL_INPUT; break; - } else if(baseLen) { - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - ///here is just one undeleted edge - (*baseLen) += asg_arc_len(av[k]); - break; - } - } - v = w; - if(v == begNode){ - return_flag = LOOP; break; - } - } - - return return_flag; -} - -uint64_t dfs_max_bub(usg_t *g, buf_t *b, uint32_t x, asg64_v *nb, uint32_t *p_bub) -{ - uint64_t len = 0, baseLen, uLen; uint32_t c_v, e_v, nv, convex, v, i, kv_0, kv_1, flag_0 = 0, flag_1 = 0, op; - usg_arc_t *av = NULL; (*p_bub) = 0; b->S.n = 0; - if(b->a[x>>1].s || g->a[x>>1].del) return 0; - kv_push(uint32_t, b->S, x); - // fprintf(stderr, "\n[M::%s::] g->n::%u, x::%u\n", __func__, (uint32_t)g->n, x); - while (b->S.n > 0) { - c_v = b->S.a[--b->S.n]; - // fprintf(stderr, "[M::%s::] b->S.n::%u, c_v::%u\n", __func__, (uint32_t)b->S.n, c_v); - // if(c_v >= g->n) { - // fprintf(stderr, "+++++[M::%s::] g->n::%u, c_v::%u\n", __func__, (uint32_t)g->n, c_v); - // } - if(b->a[c_v>>1].s) continue; - - nb->n = 0; op = get_usg_unitig(g, c_v, &convex, NULL, &baseLen, NULL, nb); - uLen = baseLen; - for(i = 0; i < nb->n; i++) b->a[nb->a[i]>>1].s = 1; - if(op == LOOP) return 0; - - e_v = convex^1; - nb->n = 0; op = get_usg_unitig(g, e_v, &convex, NULL, &baseLen, NULL, nb); - - uLen = MAX(uLen, baseLen); len += uLen; - - - v = c_v^1; nv = usg_arc_n(g, v); av = usg_arc_a(g, v); - for (i = kv_0 = 0; i < nv; i++) { - if(av[i].del) continue; - kv_0++; - if(b->a[av[i].v>>1].s) continue; - kv_push(uint32_t, b->S, av[i].v); - } - - v = e_v^1; nv = usg_arc_n(g, v); av = usg_arc_a(g, v); - for (i = kv_1 = 0; i < nv; i++) { - if(av[i].del) continue; - kv_1++; - if(b->a[av[i].v>>1].s) continue; - kv_push(uint32_t, b->S, av[i].v); - } - - if(kv_0 > 0 && kv_1 > 0) flag_0++; - if(kv_0 > 1) flag_1++; - if(kv_1 > 1) flag_1++; - } - - if(flag_0 > 0 && flag_1 > 1) (*p_bub) = 1; - return len; -} - -uint64_t usg_max_bub(usg_t *g, buf_t *b, asg64_v *nb) -{ - usg_arc_t *av, *aw; uint64_t cLen = 0, mLen = 0; - uint32_t n_vtx = g->n<<1, k, v, w, kv, nv, kw, nw, p_bub; - for (v = 0; v < n_vtx; ++v) { - if(b->a[v>>1].s || g->a[v>>1].del) continue; - - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (k = kv = 0; k < nv && kv <= 1; k++) { - if(av[k].del) continue; - w = av[k].v^1; kv++; - } - - if(kv == 1) { - aw = usg_arc_a(g, w); nw = usg_arc_n(g, w); - for (k = kw = 0; k < nw && kw <= 1; k++) { - if(aw[k].del) continue; - kw++; - } - if(kw == 1) continue; - } - - cLen = dfs_max_bub(g, b, v^1, nb, &p_bub); - if(p_bub == 0) continue;///no bubble - if(cLen > mLen) mLen = cLen; - } - - for (k = 0; k < g->n; ++k) b->a[k].s = 0; - - b->S.n = b->b.n = 0; - return mLen; -} - -uint64_t usg_bub_pop1(usg_t *g, uint32_t v0, uint64_t max_dist, buf_t *x) -{ - uint32_t v, w, i, nv, kw, cnt = 0, fail_b = 0, n_tips = 0, tip_end = (uint32_t)-1; - uint32_t l, d, c, n_pending = 0, z, to_replace, wc; usg_arc_t *av; binfo_t *t; - if(g->a[v0>>1].del || undel_arcs(g, v0, NULL) < 2) return 0; // already deleted - - x->S.n = x->T.n = x->b.n = x->e.n = 0; - x->a[v0].c = x->a[v0].d = x->a[v0].m = x->a[v0].nc = x->a[v0].np = 0; - kv_push(uint32_t, x->S, v0); - - do { - v = kv_pop(x->S); d = x->a[v].d; c = x->a[v].c; - nv = usg_arc_n(g, v); av = usg_arc_a(g, v); - for (i = 0; i < nv; ++i) { - if (av[i].del) continue; - w = av[i].v; t = &(x->a[w]); l = ((v == v0)?(0):((uint32_t)av[i].ul)); - if ((w>>1) == (v0>>1)) { - fail_b = 1; - break; - } - // kv_push(uint32_t, x->e, (g->idx[v]>>32) + i); ///for backtracking - if (d + l > max_dist) { - fail_b = 1; - break; - } - kw = undel_arcs(g, w^1, NULL); wc = g->a[w>>1].occ; - if (t->s == 0) { - kv_push(uint32_t, x->b, w); - t->p = v, t->s = 1, t->d = d + l; - t->c = c + wc; - t->r = kw; - ++n_pending; - } else { - to_replace = 0; - if((c + wc) < t->c) { - to_replace = 1; - } else if(((c + wc) == t->c) && (d + l > t->d)) { - to_replace = 1; - } - if(to_replace) { - t->p = v; t->c = c + wc; - } - if (d + l < t->d) t->d = d + l; // update dist - } - - if (--(t->r) == 0) { - z = undel_arcs(g, w, NULL); - if(z > 0) { - kv_push(uint32_t, x->S, w); - } - else { - ///at most one tip - if(n_tips != 0) { - fail_b = 1; - break; - } - n_tips++; tip_end = w; - } - --n_pending; - } - } - if(fail_b) break; - if(n_tips == 1) { - if(tip_end != (uint32_t)-1 && n_pending == 0 && x->S.n == 0) { - kv_push(uint32_t, x->S, tip_end); - break; - } - fail_b = 1; - break; - } - - if (i < nv || x->S.n == 0) { - fail_b = 1; - break; - } - } while (x->S.n > 1 || n_pending); - - if(!fail_b) {//there is a bubble - cnt = 1; - } - for (i = 0; i < x->b.n; ++i) { // clear the states of visited vertices - t = &x->a[x->b.a[i]]; - t->s = t->c = t->d = t->m = t->nc = t->np = 0; - } - return cnt; -} - -uint32_t get_usg_arc_mm(usg_t *g, usg_arc_t *z, usg_arc_mm_t **res) -{ - uint32_t v = z->ul>>32; (*res) = NULL; - if(((uint32_t)z->idx) == 0) return 0; - - // fprintf(stderr, "[M::%s::] g->n::%u, v>>1::%u, v&1::%u, idx::%u, idx_n::%u, arc_mm.n::%u\n", __func__, - // (uint32_t)g->n, v>>1, v&1, (uint32_t)(z->idx>>32), (uint32_t)(z->idx), (uint32_t)(g->a[v>>1].arc_mm[v&1].n)); - - (*res) = g->a[v>>1].arc_mm[v&1].a + (z->idx>>32); - return ((uint32_t)z->idx); -} - -uint32_t usg_arc_mm_consist(usg_t *g, usg_arc_t *v, usg_arc_t *w, uint32_t *inconsist, asg64_v *b) -{ - usg_arc_mm_t *v_a = NULL, *w_a = NULL; uint32_t v_n, w_n, v_k, w_k, occ = 0, n_occ = 0, cov; uint64_t l = 0; - get_usg_unitig(g, (v->ul>>32)^1, &cov, NULL, NULL, &l, NULL); assert(cov == (w->ul>>32)); - - v_n = get_usg_arc_mm(g, v, &v_a); w_n = get_usg_arc_mm(g, w, &w_a); - // if((v->ul>>33) == 257 || (v->ul>>33) == 256) { - // fprintf(stderr, "****[M::%s::] v>>1::%u, v&1::%u, v->des::%u, v_n::%u, v_ou::%u, w>>1::%u, w&1::%u, w->des::%u, w_n::%u, w_ou::%u\n", - // __func__, (uint32_t)(v->ul>>33), (uint32_t)(v->ul>>32)&1, v->v>>1, v_n, v->ou, cov>>1, cov&1, w->v>>1, w_n, w->ou); - // } - - for (v_k = 0; v_k < v_n; v_k++) { - for (w_k = 0; w_k < w_n; w_k++) { - // if((v->ul>>33) == 257 || (v->ul>>33) == 256) { - // fprintf(stderr, "[M::%s::] v_a->uid::%u, v_a->off::%u, w_a->uid::%u, w_a->off::%u\n", - // __func__, v_a[v_k].uid, v_a[v_k].off, w_a[w_k].uid, w_a[w_k].off); - // } - if(v_a[v_k].uid != w_a[w_k].uid) continue; - if(v_a[v_k].off + l == w_a[w_k].off) { - if(b) kv_push(uint64_t, *b, (((uint64_t)v_a[v_k].uid)<<32)|((uint64_t)v_a[v_k].off)); - occ++; - } else if(v_a[v_k].off == w_a[w_k].off + l) { - if(b) kv_push(uint64_t, *b, (((uint64_t)v_a[v_k].uid)<<32)|((uint64_t)w_a[w_k].off)); - occ++; - } else { - n_occ++; - } - } - } - - if(inconsist) (*inconsist) = n_occ; - return occ; -} - -uint32_t is_junction_circle(usg_t *g, uint32_t v, uint32_t w) -{ - uint32_t k, nv, cov, op, cov_w; usg_arc_t *av; - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - - for (k = 0; k < nv; k++){ - if(av[k].del) continue; - if(av[k].v == (w^1)) return 1;///circle - op = get_usg_unitig(g, av[k].v, &cov, NULL, NULL, NULL, NULL); - if(op == LOOP || cov == (w^1)) return 1;///circle - if(op == MUL_INPUT) { - undel_arcs(g, cov, &cov_w); - if(cov_w == (w^1)) return 1;///circle - } - } - - return 0; -} - -uint32_t get_junction_w(usg_t *g, uint32_t v0, uint32_t v1, uint32_t no_inconsist, asg64_v *res) -{ - uint32_t k, i, v[2], nv[2], ou[2], i0, i1, k0, k1, occ, ff, is_mul, nn[2], *c, ww, inconsist; - usg_arc_t *av[2]; uint64_t m = 0; - - if(is_junction_circle(g, v0, v1)) return (uint32_t)-1; - // if((v0>>1) == 257 || (v1>>1) == 256) { - // fprintf(stderr, "[M::%s::] v0>>1::%u, v0&1::%u, v0pid::%u, v1>>1::%u, v1&1::%u, v1pid::%u\n", - // __func__, v0>>1, v0&1, g->a[v0>>1].mm, v1>>1, v1&1, g->a[v1>>1].mm); - // } - - v[0] = v0; v[1] = v1; - nv[0] = usg_arc_n(g, v[0]); nv[1] = usg_arc_n(g, v[1]); - av[0] = usg_arc_a(g, v[0]); av[1] = usg_arc_a(g, v[1]); - - i = 0; - for (k = 0, ou[i] = 0; k < nv[i]; k++) { - if(!av[i][k].ou) continue; - if(av[i][k].del) continue; - ou[i]++; - } - // if((v0>>1) == 257 || (v1>>1) == 256) { - // fprintf(stderr, "[M::%s::] ou[0]::%u\n", __func__, ou[0]); - // } - if(!ou[i]) return (uint32_t)-1; - - i = 1; - for (k = 0, ou[i] = 0; k < nv[i]; k++) { - if(!av[i][k].ou) continue; - if(av[i][k].del) continue; - ou[i]++; - } - // if((v0>>1) == 257 || (v1>>1) == 256) { - // fprintf(stderr, "[M::%s::] ou[1]::%u\n", __func__, ou[1]); - // } - if(!ou[i]) return (uint32_t)-1; - - //this is not ture; some UL may not be able to go through nid - // if(ou[0] != ou[1]) return (uint32_t)-1; - nn[0] = nn[1] = ww = 0; - - i0 = 0; i1 = 1; is_mul = 0; c = &(nn[0]); - for (k0 = 0; k0 < nv[i0]; k0++) { - if(!av[i0][k0].ou) continue; - if(av[i0][k0].del) continue; - for (k1 = 0, ff = 0; k1 < nv[i1] && ff <= 1; k1++) { - if(!av[i1][k1].ou) continue; - if(av[i1][k1].del) continue; - occ = usg_arc_mm_consist(g, &(av[i0][k0]), &(av[i1][k1]), &inconsist, NULL); - if(occ == 0) continue; - if(no_inconsist && inconsist > 0) { - ff = 2; break; - } - ff++; - } - - if(ff > 1) { - is_mul = 1; break; - } else if(ff == 1) { - (*c) += 1; - } - } - // if((v0>>1) == 257 || (v1>>1) == 256) { - // fprintf(stderr, "[M::%s::] c[0]::%u\n", __func__, *c); - // } - if((*c) == 0 || is_mul) return (uint32_t)-1; - - - i0 = 1; i1 = 0; is_mul = 0; c = &(nn[1]); - for (k0 = 0; k0 < nv[i0]; k0++) { - if(!av[i0][k0].ou) continue; - if(av[i0][k0].del) continue; - for (k1 = 0, ff = 0; k1 < nv[i1] && ff <= 1; k1++) { - if(!av[i1][k1].ou) continue; - if(av[i1][k1].del) continue; - occ = usg_arc_mm_consist(g, &(av[i0][k0]), &(av[i1][k1]), &inconsist, NULL); - if(occ == 0) continue; - if(no_inconsist && inconsist > 0) { - ff = 2; break; - } - ff++; ww += MIN((av[i0][k0].ou>>1), (av[i1][k1].ou>>1)); - m = k0; m <<= 32; m |= k1; - } - - if(ff > 1) { - is_mul = 1; break; - } else if(ff == 1) { - (*c) += 1; - if(res) { - kv_push(uint64_t, *res, (((uint64_t)v[i0])<<32)|(((uint64_t)(m>>32)))); - kv_push(uint64_t, *res, (((uint64_t)v[i1])<<32)|(((uint64_t)((uint32_t)m)))); - } - } - } - // if((v0>>1) == 257 || (v1>>1) == 256) { - // fprintf(stderr, "[M::%s::] c[1]::%u\n", __func__, *c); - // } - if((*c) == 0 || is_mul) return (uint32_t)-1; - assert(nn[0] == nn[1]); - - return ww; -} - -void remap_gen_arcs(usg_t *g, uint32_t ov, uint32_t ow, uint32_t nv, uint32_t nw) -{ - usg_arc_t *op = NULL, *np = NULL; usg_arc_warp *sv; uint32_t k; usg_arc_mm_t *v_a, *pm; uint32_t v_n; - sv = &(g->a[nv>>1].arc[nv&1]); kv_pushp(usg_arc_t, *sv, &np); - op = get_usg_arc(g, ov, ow); assert(op);///must get op ater since op might be changed by kv_pushp - - np->ul = (uint32_t)op->ul; np->ul |= (((uint64_t)nv)<<32); np->v = nw; - np->ol = op->ol; np->del = 0; np->ou = op->ou; - np->idx = g->a[nv>>1].arc_mm[nv&1].n; np->idx <<= 32; np->idx |= (uint32_t)op->idx; - - v_n = (uint32_t)op->idx; - for (k = 0; k < v_n; k++) { - kv_pushp(usg_arc_mm_t, g->a[nv>>1].arc_mm[nv&1], &pm); - v_a = g->a[op->ul>>33].arc_mm[(op->ul>>32)&1].a + (op->idx>>32);//va might be changed - pm->v = nw; pm->uid = v_a[k].uid; pm->off = v_a[k].off; - } -} - -void update_dual_junction(usg_t *g, uint32_t v, uint32_t v_id, uint32_t w, uint32_t w_id, asg64_v *buf) -{ - usg_arc_t *av, *aw, *z; uint32_t k, nv, nw, kv, kw, nid, pnid; usg_seq_t *s; - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (k = kv = 0; k < nv; k++) { - if(av[k].del) continue; - kv++; - } - - aw = usg_arc_a(g, w); nw = usg_arc_n(g, w); - for (k = kw = 0; k < nw; k++) { - if(aw[k].del) continue; - kw++; - } - assert(kv && kw); - assert((!av[v_id].del) && (!aw[w_id].del)); - assert(av[v_id].ou && aw[w_id].ou); - if(kv == 1 && kw == 1) return;///no need to - - buf->n = 0; pnid = g->n; - get_usg_unitig(g, v^1, NULL, NULL, NULL, NULL, buf); - // if(!(buf->n > 0 && buf->a[buf->n-1] == w)) { - // fprintf(stderr, "[M::%s::] buf->n::%u, v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u\n", __func__, - // (uint32_t)buf->n, v>>1, v&1, kv, w>>1, w&1, kw); - // } - assert(buf->n > 0 && buf->a[buf->n-1] == w); - - for (k = 0; k < buf->n; k++) { - nid = buf->a[k]>>1; - kv_push(uint32_t, g->mp.a[g->a[nid].mm], g->n); s = push_usg_t_node(g, g->n); - s->mm = g->a[nid].mm; s->occ = g->a[nid].occ; s->len = g->a[nid].len; s->telo = g->a[nid].telo; s->del = 0; - s->arc[0].n = s->arc[1].n = 0; s->arc_mm[0].n = s->arc_mm[1].n = 0; - } - - for (k = 0; k + 1 < buf->n; k++) { - remap_gen_arcs(g, buf->a[k], buf->a[k+1], (((pnid+k)<<1)|(buf->a[k]&1)), (((pnid+k+1)<<1)|(buf->a[k+1]&1))); - remap_gen_arcs(g, buf->a[k+1]^1, buf->a[k]^1, (((pnid+k+1)<<1)|(buf->a[k+1]&1))^1, (((pnid+k)<<1)|(buf->a[k]&1))^1); - } - - //av might be changed - av = usg_arc_a(g, v); - remap_gen_arcs(g, av[v_id].ul>>32, av[v_id].v, (pnid<<1)|((av[v_id].ul>>32)&1), av[v_id].v); - av = usg_arc_a(g, v); - remap_gen_arcs(g, av[v_id].v^1, (av[v_id].ul>>32)^1, av[v_id].v^1, ((pnid<<1)|((av[v_id].ul>>32)&1))^1); - - pnid = pnid + buf->n - 1; - //aw might be changed - aw = usg_arc_a(g, w); - remap_gen_arcs(g, aw[w_id].ul>>32, aw[w_id].v, (pnid<<1)|((aw[w_id].ul>>32)&1), aw[w_id].v); - aw = usg_arc_a(g, w); - remap_gen_arcs(g, aw[w_id].v^1, (aw[w_id].ul>>32)^1, aw[w_id].v^1, ((pnid<<1)|((aw[w_id].ul>>32)&1))^1); - - ///drop edges from the current node - av[v_id].del = 1; z = get_usg_arc(g, av[v_id].v^1, (av[v_id].ul>>32)^1); z->del = 1; - aw[w_id].del = 1; z = get_usg_arc(g, aw[w_id].v^1, (aw[w_id].ul>>32)^1); z->del = 1; -} - -uint32_t u2g_n_hybrid_thread(usg_t *ng, uint32_t no_inconsist, asg64_v *in, asg64_v *buf) -{ - if(in->n < 1) return 0; - uint32_t k, i, v, w, in_n = in->n, mm, ov[2], kv[2], cnt = 0; uint64_t *a, a_n; - for (k = 0; k < in->n; k++) { - v = (uint32_t)in->a[k]; in_n = in->n; - if(get_usg_unitig(ng, v^1, &w, NULL, NULL, NULL, NULL) == LOOP) continue; - mm = get_junction_w(ng, v, w, no_inconsist, in); - if(mm == (uint32_t)-1) { - in->n = in_n; continue; - } - if(in->n == in_n) continue; - - ov[0] = ov[1] = 0; a = in->a + in_n; a_n = in->n - in_n; - for (i = 0; i < a_n; i++) { - if((a[i]>>32) == v) ov[0]++; - if((a[i]>>32) == w) ov[1]++; - } - - kv[0] = undel_arcs(ng, v, NULL); kv[1] = undel_arcs(ng, w, NULL); - assert(ov[0] == ov[1] && ov[0] <= kv[0] && ov[1] <= kv[1]); - if((ov[0] == kv[0] && ov[1] < kv[1]) || (ov[0] < kv[0] && ov[1] == kv[1])) { - in->n = in_n; continue; - } - - for (i = 0; i < a_n; i += 2) { - update_dual_junction(ng, a[i]>>32, (uint32_t)a[i], a[i+1]>>32, (uint32_t)a[i+1], buf); - } - cnt++; in->n = in_n; - } - - return cnt; -} - - -void u2g_hybrid_extend(usg_t *ng, uint64_t* i_max_dist, asg64_v *in, asg64_v *ib) -{ - uint32_t v, w, n_vtx = ng->n<<1, n_arc, nv, i, mm; - uint64_t n_pop = 0, max_dist; usg_arc_t *av = NULL; - asg64_v tx = {0,0,0}, tb = {0,0,0}, *ob = NULL, *ub = NULL; - ob = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); ob->n = ub->n = 0; - buf_t b; memset(&b, 0, sizeof(buf_t)); CALLOC(b.a, n_vtx); - if(i_max_dist) max_dist = (*i_max_dist); - else max_dist = usg_max_bub(ng, &b, ob); - uint8_t* bs_flag = NULL; CALLOC(bs_flag, n_vtx); - - if(max_dist > 0) { - for(v = 0; v < n_vtx; ++v) { - if(bs_flag[v] != 0) continue; - nv = usg_arc_n(ng, v); av = usg_arc_a(ng, v); - if(nv < 2 || ng->a[v>>1].del) continue; - for (i = n_arc = 0; i < nv; ++i) { - if (!av[i].del) ++n_arc; - } - if (n_arc < 2) continue; - if(usg_bub_pop1(ng, v, max_dist, &b)) { - //beg is v, end is b.S.a[0]; note b.b include end, does not include beg - for (i = 0; i < b.b.n; i++) { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - bs_flag[b.b.a[i]] = bs_flag[b.b.a[i]^1] = 1; - } - bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 3; - } - } - - for(v = ob->n = 0; v < n_vtx; ++v) { - if(bs_flag[v] <= 1) continue; - if(get_usg_unitig(ng, v^1, &w, NULL, NULL, NULL, NULL) != LOOP && bs_flag[w] > 1) { - mm = get_junction_w(ng, v, w, 0, NULL); - if(mm == (uint32_t)-1) continue; - mm = ((uint32_t)-1) - mm; - kv_push(uint64_t, *ob, ((((uint64_t)mm)<<32)|((uint64_t)v))); - bs_flag[v] = bs_flag[w] = 0; - } - } - - radix_sort_srt64(ob->a, ob->a + ob->n); - n_pop += u2g_n_hybrid_thread(ng, 0, ob, ub); - } - - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - if(n_pop) usg_cleanup(ng); - if(!in) free(tx.a); if(!ib) free(tb.a); -} - - - -// uint32_t usg_path_pop_1(ul_resolve_t *uidx, usg_t *g, uint32_t v0, buf_t *x, asg64_v *arc_b) -// { -// uint32_t v, w, i, nv, kv, kw, cnt = 0, fail_b = 0, n_tips = 0, tip_end = (uint32_t)-1; -// uint32_t l, d, c, n_pending = 0, z, to_replace, wc, i_id, i_off, i_rev; -// usg_arc_t *av; binfo_t *t; usg_arc_mm_t *arc_a; uint32_t arc_n; -// if(g->a[v0>>1].del) return 0; // already deleted -// if(undel_arcs(g, v0, NULL) != 1) return 0; -// undel_arcs(g, v0, &w); w ^= 1; -// if(undel_arcs(g, w, NULL) < 2) return 0; - -// x->S.n = x->T.n = x->b.n = x->e.n = 0; -// x->a[v0].c = x->a[v0].d = x->a[v0].m = x->a[v0].nc = x->a[v0].np = 0; -// kv_push(uint32_t, x->S, v0); arc_b->n = 0; i_id = i_off = i_rev = (uint32_t)-1; - -// do { -// v = kv_pop(x->S); d = x->a[v].d; c = x->a[v].c; -// nv = usg_arc_n(g, v); av = usg_arc_a(g, v); kv = undel_arcs(g, v, NULL); -// for (i = 0; i < nv; ++i) { -// if (av[i].del) continue; -// w = av[i].v; t = &(x->a[w]); l = ((v == v0)?(0):((uint32_t)av[i].ul)); -// if ((w>>1) == (v0>>1)) { -// fail_b = 1; -// break; -// } -// kw = undel_arcs(g, w^1, NULL); wc = g->a[w>>1].occ; -// kv_push(uint64_t, *arc_b, (((uint64_t)v)<<32)|((uint64_t)i)); ///for backtracking -// arc_n = get_usg_arc_mm(g, &(av[i]), &arc_a); -// if(v == v0 && arc_n == 0) { -// fail_b = 1; -// break; -// } -// if(arc_n > 0) { - -// } else if(kv == 1) { - -// } - - - - - -// kw = undel_arcs(g, w^1, NULL); wc = g->a[w>>1].occ; -// if (t->s == 0) { -// kv_push(uint32_t, x->b, w); -// t->p = v, t->s = 1, t->d = d + l; -// t->c = c + wc; -// t->r = kw; -// ++n_pending; -// } else { -// to_replace = 0; -// if((c + wc) < t->c) { -// to_replace = 1; -// } else if(((c + wc) == t->c) && (d + l > t->d)) { -// to_replace = 1; -// } -// if(to_replace) { -// t->p = v; t->c = c + wc; -// } -// if (d + l < t->d) t->d = d + l; // update dist -// } - -// if (--(t->r) == 0) { -// z = undel_arcs(g, w, NULL); -// if(z > 0) { -// kv_push(uint32_t, x->S, w); -// } -// else { -// ///at most one tip -// if(n_tips != 0) { -// fail_b = 1; -// break; -// } -// n_tips++; tip_end = w; -// } -// --n_pending; -// } -// } -// if(fail_b) break; -// if(n_tips == 1) { -// if(tip_end != (uint32_t)-1 && n_pending == 0 && x->S.n == 0) { -// kv_push(uint32_t, x->S, tip_end); -// break; -// } -// fail_b = 1; -// break; -// } - -// if (i < nv || x->S.n == 0) { -// fail_b = 1; -// break; -// } -// } while (x->S.n > 1 || n_pending); -// } - - -///***debug-hybrid*** -uint32_t check_hybrid_connect(usg_t *ng, uint32_t i_uid, uint32_t v, uint32_t vidx, uint32_t w, uint32_t widx) -{ - usg_arc_mm_t *z_a = NULL; uint32_t z_n, k; - usg_arc_t *z = get_usg_arc(ng, v, w); - if(!z) return 0; - z_n = get_usg_arc_mm(ng, z, &z_a); - if(!z_n) return 0; - for (k = 0; k < z_n; k++) { - if(z_a[k].uid != i_uid || z_a[k].off != vidx) continue; - return 1; - } - return 0; -} - -uint32_t usg_arc_occ(usg_t *ng, uint32_t v) -{ - usg_arc_t *p; uint32_t nv, kv, i; - p = usg_arc_a(ng, v); nv = usg_arc_n(ng, v); - for (i = kv = 0; i < nv; i++) { - if(p[i].del) continue; - kv++; - } - return kv; -} - -void integer_realign_g(ul_resolve_t *uidx, usg_t *ng, uinfo_srt_warp_t *seq, uint32_t seq_id, integer_t *buf) -{ - if(seq->n < 2) return; - // if(seq_id != 1137) return; - uint64_t *srt, *track, k, z, m, t, i, l, seq_n, j, sc, csc, mm_sc, mm_idx, n_v, n_u, n_v0, *p, lin, pn; - uint32_t vi, vj; mmap_t *zm, *zt; - ///ng->map: the nodes in the new graph that are mapped to the initial HiFi graph - for (i = seq_n = 0; i < seq->n; ++i) seq_n += ng->mp.a[seq->a[i].v>>1].n; - // fprintf(stderr, "[M::%s::] seq_id::%u, seq_n::%u, seq->n::%u\n", - // __func__, seq_id, (uint32_t)seq_n, (uint32_t)seq->n); - - buf->o.n = buf->u.n = 0; - kv_resize(uint64_t, buf->o, (seq_n<<1)); - srt = buf->o.a; track = buf->o.a + seq_n; - - for (z = l = 0; z < seq->n; ++z) { - csc = seq->a[z].n; - zm = &(ng->mp.a[seq->a[z].v>>1]);///current - zt = ((z>0)?(&(ng->mp.a[seq->a[z-1].v>>1])):(NULL));///prefix - for (m = 0; m < zm->n; m++) { - i = l + m; mm_sc = csc; mm_idx = ((uint64_t)0x7FFFFFFF); - vi = (zm->a[m]<<1)|(seq->a[z].v&1); - if(zt && zt->n > 0) { - for (t = 0; t < zt->n; t++) { - j = l + t - zt->n; - vj = (zt->a[t]<<1)|(seq->a[z-1].v&1); - if(check_hybrid_connect(ng, seq_id, vj, z-1, vi, z)) {///seq_id:: integer contig id - sc = csc + (((uint32_t)-1) - (track[j]>>32)); - if(sc > mm_sc) { - mm_sc = sc; mm_idx = j; - } - } - } - } - mm_sc = ((uint32_t)-1) - mm_sc; - track[i] = mm_sc; track[i] <<= 32; track[i] |= mm_idx; - srt[i] = track[i]>>32; srt[i] <<= 32; srt[i] |= i; - } - l += zm->n; - } - assert(l == seq_n); - - radix_sort_srt64(srt, srt + seq_n); - kv_resize(uint64_t, buf->res_dump, buf->res_dump.n + seq_n); - l = buf->res_dump.n; m = buf->u.n; - for (k = n_v = n_u = 0; k < seq_n; k++) { - n_v0 = n_v; i = (uint32_t)srt[k]; - for (; i != ((uint64_t)0x7FFFFFFF) && (!(track[i]&((uint64_t)0x80000000)));) { - kv_push(uint64_t, buf->res_dump, i); n_v++; - track[i] |= ((uint64_t)0x80000000); - i = track[i]&((uint64_t)0x7FFFFFFF); - } - if(n_v - n_v0 <= 1) {///not useful to resolve anything if the UL covers less than 1 nodes - buf->res_dump.n -= (n_v-n_v0); n_v = n_v0; - continue; - } - kv_pushp(uint64_t, buf->u, &p); n_u++; - (*p) = n_v-n_v0; (*p) = ((uint32_t)-1) - (*p); (*p) <<= 32; (*p) |= ((uint64_t)(l+n_v0)); - } - - for (z = i = 0; z < seq->n; ++z) { - zm = &(ng->mp.a[seq->a[z].v>>1]); - for (k = 0; k < zm->n; k++, i++) { - srt[i] = z; srt[i] <<= 32; srt[i] |= ((zm->a[k]<<1)|(seq->a[z].v&1)); - } - } - assert(i == seq_n); - ///srt[]: (idx in seq)|(node id) - uint64_t *r, nt; - for (k = n_u = nt = 0; k < buf->u.n; k++) { - n_v0 = (uint32_t)buf->u.a[k]; r = buf->res_dump.a + n_v0; - n_v = (((uint32_t)-1) - (buf->u.a[k]>>32)); - // if(n_v < 2) continue; - // fprintf(stderr, "+[M::%s::k->%lu] buf->u.n::%u, n_v0::%lu, n_v::%lu, nt::%lu\n", - // __func__, k, (uint32_t)buf->u.n, n_v0, n_v, nt); - assert(n_v >= 2); - buf->u.a[n_u] = nt<<32; - for (i = 0; i < n_v; i++, nt++) { - // fprintf(stderr, ">[M::%s::] i::%lu, nt::%lu, n_v-i-1::%lu, r[n_v-i-1]::%lu\n", - // __func__, i, nt, n_v-i-1, r[n_v-i-1]); - track[nt] = srt[r[n_v-i-1]]; - } - buf->u.a[n_u] |= nt; n_u++; - // fprintf(stderr, "-[M::%s::k->%lu] buf->u.n::%u, n_v0::%lu, n_v::%lu, nt::%lu\n", - // __func__, k, (uint32_t)buf->u.n, n_v0, n_v, nt); - } - buf->u.n = n_u; - - uint64_t ceq_s, ceq_e, peq_s, peq_e, min_e, max_s; - for (k = n_u = 0; k < buf->u.n; k++) { - n_v0 = buf->u.a[k]>>32; n_v = (uint32_t)buf->u.a[k];///[n_v0, n_v) - ceq_s = track[n_v0]>>32; ceq_e = (track[n_v-1]>>32) + 1; - assert((ceq_e-ceq_s) == (n_v-n_v0)); - for (z = 0; z < n_u; z++) { - n_v0 = buf->u.a[z]>>32; n_v = (uint32_t)buf->u.a[z]; - peq_s = track[n_v0]>>32; peq_e = (track[n_v-1]>>32) + 1; - assert((peq_e-peq_s) == (n_v-n_v0)); - max_s = MAX(peq_s, ceq_s); min_e = MIN(peq_e, ceq_e); - if(min_e > max_s) break; - } - if(z < n_u) continue; - buf->u.a[n_u++] = buf->u.a[k]; - } - buf->u.n = n_u; buf->res_dump.n = l; - for (k = n_u = 0; k < buf->u.n; k++) { - // t = (uint32_t)-1; t <<= 32; - t = seq_id; t <<= 32; t |= ((uint64_t)0x8000000000000000); - t |= (((uint32_t)buf->u.a[k])-(buf->u.a[k]>>32)); - pn = buf->res_dump.n; kv_push(uint64_t, buf->res_dump, t); - n_v0 = buf->u.a[k]>>32; n_v = (uint32_t)buf->u.a[k]; - for (z = n_v0, lin = 1; z < n_v; z++) { - if(lin && (z > n_v0)) { - if((usg_arc_occ(ng, ((uint32_t)track[z])^1) > 1) || - (usg_arc_occ(ng, ((uint32_t)track[z-1])) > 1)) { - lin = 0; - } - } - kv_push(uint64_t, buf->res_dump, (uint32_t)track[z]); - } - - if(lin == 1) buf->res_dump.n = pn; - } -} - -static void worker_integer_realign_g(void *data, long i, int tid) // callback for kt_for() -{ - ul_resolve_t *uidx = (ul_resolve_t *)data; - integer_realign_g(uidx, uidx->uovl.h_usg, &(uidx->uovl.cc.iug_a[i]), i, &(uidx->str_b.buf[tid])); -} - -uint64_t get_ug_occ_v(uint32_t i_ug_occ) -{ - uint64_t v = (uint64_t)-1; - if(!(i_ug_occ&((uint32_t)0x80000000))) return v; - if(!(i_ug_occ&3)) return v; - if((i_ug_occ&1)&&(i_ug_occ&2)) { - v = (((i_ug_occ<<1)>>3)<<1); - v <<= 32; v |= ((((i_ug_occ<<1)>>3)<<1)|1); - return v; - } - if(i_ug_occ&1) { - v <<= 32; v |= (((i_ug_occ<<1)>>3)<<1); - return v; - } - if(i_ug_occ&2) { - v <<= 32; v |= ((((i_ug_occ<<1)>>3)<<1)|1); - return v; - } - return v; -} - -///this function might be wrong -uint32_t usg_unique_arcs_cluster(asg64_v *b64, uint64_t a_n, uint64_t *idx, uint64_t *integ_seq) -{ - uint64_t bn = b64->n, k, v; - kv_resize(uint64_t, *b64, b64->n + a_n); b64->n += a_n; - memset(b64->a + bn, -1, sizeof((*(b64->a)))*a_n); - uint64_t *cidx = b64->a + bn, s, e, i, zs, ze, z; - - ///b64.a[0, a_n]:: all resolvable paths with unique beg && end - ///b64.a[a_n, bn]:: (raw unitig/non-unqiue node id)|(resolvable path id) - ///idx:: the idx for b64.a[a_n, bn] - for (i = 0; i < a_n; i++) {///available interval with beg/end with unique arcs - s = b64->a[i]>>32; e = (uint32_t)(b64->a[i]); assert(e > s); - if(cidx[i] != (uint64_t)-1) continue; - for (k = s + 1; k < e; k++) {///note: here is [s, e] - v = integ_seq[k];///v is the raw unitig id - zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; - for (z = zs; z < ze; z++) { - // if((b64->a[z]>>32)!=v) { - // fprintf(stderr, "[M::%s::] v::%lu, b64->a[z]::%lu, zs::%lu, ze::%lu, a_n::%lu\n", - // __func__, v, b64->a[z]>>32, zs, ze, a_n); - // } - ///(b64->a[z]>>32):: raw unitig id - ///(uint32_t)b64->a[z]:: available interval id - assert((b64->a[z]>>32)==v); - cidx[((uint32_t)b64->a[z])] = (i<<32)|((uint32_t)b64->a[z]); - } - - v = integ_seq[k]^1; - zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; - for (z = zs; z < ze; z++) { - assert((b64->a[z]>>32)==v); - cidx[((uint32_t)b64->a[z])] = (i<<32)|((uint32_t)b64->a[z]); - } - } - v = integ_seq[s]; - zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; - for (z = zs; z < ze; z++) { - assert((b64->a[z]>>32)==v); - cidx[((uint32_t)b64->a[z])] = (i<<32)|((uint32_t)b64->a[z]); - } - - v = integ_seq[e]^1; - zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; - for (z = zs; z < ze; z++) { - assert((b64->a[z]>>32)==v); - cidx[((uint32_t)b64->a[z])] = (i<<32)|((uint32_t)b64->a[z]); - } - } - - radix_sort_srt64(cidx, cidx + a_n); b64->n = a_n; - for (i = 0, k = 1, v = 0; k <= a_n; k++) { - if(k == a_n || (cidx[i]>>32) != (cidx[k]>>32)) { - for (z = i; z < k; z++) { - assert(cidx[z] != (uint64_t)-1); - ///cluest integer seqs-> (cluster id)|(available interval id) - b64->a[b64->n++] = (v<<32)|((uint32_t)cidx[z]); - } - i = k; v++; - } - } - - assert(b64->n == (a_n<<1)); - return v;///how many cluster -} - -void iter_unique_arcs(asg64_v *buf, asg64_v *b64, uint64_t a_n, uint64_t *idx, uint64_t *integ_seq, uint64_t *cidx, uint64_t i0) -{ - uint64_t s, e, x, k, v, zs, ze, z; - buf->n = 0; - kv_push(uint64_t, *buf, i0); - while(buf->n) { - x = kv_pop(*buf); - if(cidx[x] != (uint64_t)-1) continue; - cidx[x] = (i0<<32)|(x); - s = b64->a[x]>>32; e = (uint32_t)(b64->a[x]); assert(e > s); - for (k = s + 1; k < e; k++) {///note: here is [s, e] - v = integ_seq[k];///v is the raw unitig id - zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; - for (z = zs; z < ze; z++) { - ///(b64->a[z]>>32):: raw unitig id - ///(uint32_t)b64->a[z]:: available interval id - assert((b64->a[z]>>32)==v); - if(cidx[((uint32_t)b64->a[z])] != (uint64_t)-1) { - assert((cidx[((uint32_t)b64->a[z])]>>32)==i0); - continue; - } - // cidx[((uint32_t)b64->a[z])] = (i0<<32)|((uint32_t)b64->a[z]); - kv_push(uint64_t, *buf, ((uint32_t)b64->a[z])); - } - - v = integ_seq[k]^1; - zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; - for (z = zs; z < ze; z++) { - ///(b64->a[z]>>32):: raw unitig id - ///(uint32_t)b64->a[z]:: available interval id - assert((b64->a[z]>>32)==v); - if(cidx[((uint32_t)b64->a[z])] != (uint64_t)-1) { - assert((cidx[((uint32_t)b64->a[z])]>>32)==i0); - continue; - } - // cidx[((uint32_t)b64->a[z])] = (i0<<32)|((uint32_t)b64->a[z]); - kv_push(uint64_t, *buf, ((uint32_t)b64->a[z])); - } - } - - v = integ_seq[s]; - zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; - for (z = zs; z < ze; z++) { - assert((b64->a[z]>>32)==v); - if(cidx[((uint32_t)b64->a[z])] != (uint64_t)-1) { - assert((cidx[((uint32_t)b64->a[z])]>>32)==i0); - continue; - } - // cidx[((uint32_t)b64->a[z])] = (i0<<32)|((uint32_t)b64->a[z]); - kv_push(uint64_t, *buf, ((uint32_t)b64->a[z])); - } - - v = integ_seq[e]^1; - zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; - for (z = zs; z < ze; z++) { - assert((b64->a[z]>>32)==v); - if(cidx[((uint32_t)b64->a[z])] != (uint64_t)-1) { - assert((cidx[((uint32_t)b64->a[z])]>>32)==i0); - continue; - } - // cidx[((uint32_t)b64->a[z])] = (i0<<32)|((uint32_t)b64->a[z]); - kv_push(uint64_t, *buf, ((uint32_t)b64->a[z])); - } - } -} - -uint32_t usg_unique_arcs_cluster_adv(asg64_v *b64, uint64_t a_n, uint64_t *idx, uint64_t *integ_seq, asg64_v *buf) -{ - uint64_t bn = b64->n, k, z, v; buf->n = 0; - kv_resize(uint64_t, *b64, b64->n + a_n); b64->n += a_n; - memset(b64->a + bn, -1, sizeof((*(b64->a)))*a_n); - uint64_t *cidx = b64->a + bn, i; - - ///b64.a[0, a_n]:: all resolvable paths with unique beg && end - ///b64.a[a_n, bn]:: (raw unitig/non-unqiue node id)|(resolvable path id) - ///idx:: the idx for b64.a[a_n, bn] - for (i = 0; i < a_n; i++) {///available interval with beg/end with unique arcs - if(cidx[i] != (uint64_t)-1) continue; - iter_unique_arcs(buf, b64, a_n, idx, integ_seq, cidx, i); - } - - radix_sort_srt64(cidx, cidx + a_n); b64->n = a_n; - for (i = 0, k = 1, v = 0; k <= a_n; k++) { - if(k == a_n || (cidx[i]>>32) != (cidx[k]>>32)) { - for (z = i; z < k; z++) { - assert(cidx[z] != (uint64_t)-1); - ///cluest integer seqs-> (cluster id)|(available interval id) - b64->a[b64->n++] = (v<<32)|((uint32_t)cidx[z]); - } - i = k; v++; - } - } - - buf->n = 0; - assert(b64->n == (a_n<<1)); - return v;///how many cluster -} - -uint32_t ava_pass_unique_bridge(uint64_t *idx, uint64_t *integer_seq, uint64_t s, uint64_t e) -{ - uint64_t k; - for (k = s + 1; k < e; k++) {///note: here is [s, e] - if((idx[integer_seq[k]]&((uint64_t)0x8000000000000000)) || - (idx[integer_seq[k]^1]&((uint64_t)0x8000000000000000))) { - return 0; - } - } - if((idx[integer_seq[s]]&((uint64_t)0x8000000000000000)) || - (idx[integer_seq[e]^1]&((uint64_t)0x8000000000000000))) { - return 0; - } - return 1; -} - -uint32_t ava_pass_unique_bridge_tips(usg_t *g, asg64_v *b64, uint64_t g_s, uint64_t g_e, uint64_t *integer_seq, uint8_t *f, uint64_t max_ext, double max_ext_rate, uint64_t ext_up) -{ - uint64_t i, k, z, s, e, v, nv, bn = b64->n, kv, kv_t, n_ext = 0, nkeep = 0, ncut = 0, is_telo; usg_arc_t *av; - for (i = g_s; i < g_e; i++) {///available intervals within the same cluster - s = b64->a[((uint32_t)b64->a[i])]>>32; e = ((uint32_t)b64->a[((uint32_t)b64->a[i])]); assert(s < e); - for (k = s + 1; k < e; k++) {///note: here is [s, e] - f[integer_seq[k]] = f[integer_seq[k]^1] = 1; - nkeep += g->a[integer_seq[k]>>1].occ; - } - f[integer_seq[s]] = f[integer_seq[e]^1] = 1; - } - nkeep = nkeep*max_ext_rate; - - ///collect nodes within raw unitig graph that are linked by the clusters but not in the cluster - for (i = g_s; i < g_e; i++) { - s = b64->a[((uint32_t)b64->a[i])]>>32; e = ((uint32_t)b64->a[((uint32_t)b64->a[i])]); assert(s < e); - for (k = s + 1; k < e; k++) {///note: here is [s, e] - v = integer_seq[k]; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (z = 0; z < nv; z++) { - if(av[z].del || f[av[z].v^1]) continue; - kv_push(uint64_t, *b64, av[z].v); - } - - v = integer_seq[k]^1; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (z = 0; z < nv; z++) { - if(av[z].del || f[av[z].v^1]) continue; - kv_push(uint64_t, *b64, av[z].v); - } - } - - v = integer_seq[s]; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (z = 0; z < nv; z++) { - if(av[z].del || f[av[z].v^1]) continue; - kv_push(uint64_t, *b64, av[z].v); - } - - v = integer_seq[e]^1; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (z = 0; z < nv; z++) { - if(av[z].del || f[av[z].v^1]) continue; - kv_push(uint64_t, *b64, av[z].v); - } - } - - ncut = MAX(nkeep, max_ext); is_telo = 0; - if(ncut > ext_up) ncut = ext_up; - if(ncut < max_ext) ncut = max_ext; - while ((b64->n > bn) && (n_ext < ncut) && (!is_telo)) { - v = b64->a[--b64->n]; if(f[v]) continue; - av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); - for (i = kv = 0; i < nv && kv < 1; i++) { - if (av[i].del || f[av[i].v^1]) continue; - kv++; - } - if(kv > 0) continue; - n_ext += g->a[v>>1].occ; f[v] = f[v^1] = 1; - - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (i = kv_t = 0; i < nv; i++) { - if(av[i].del) continue; - kv_t++; - if (f[av[i].v^1]) continue; - kv_push(uint64_t, *b64, av[i].v); - } - if((!kv_t) && (g->a[v>>1].telo)) is_telo = 1; - } - - ///reset f[] to 0 - for (i = g_s; i < g_e; i++) { - s = b64->a[((uint32_t)b64->a[i])]>>32; e = ((uint32_t)b64->a[((uint32_t)b64->a[i])]); assert(s < e); - for (k = s + 1; k < e; k++) {///note: here is [s, e] - kv_push(uint64_t, *b64, integer_seq[k]); - kv_push(uint64_t, *b64, (integer_seq[k]^1)); - f[integer_seq[k]] = f[integer_seq[k]^1] = 0; - } - kv_push(uint64_t, *b64, integer_seq[s]); - kv_push(uint64_t, *b64, (integer_seq[e]^1)); - f[integer_seq[s]] = f[integer_seq[e]^1] = 0; - } - - while (b64->n > bn) { - v = b64->a[--b64->n]; - f[v] = f[v^1] = 0; - - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (i = 0; i < nv; i++) { - if (av[i].del) continue; - if(f[av[i].v] || f[av[i].v^1]) { - kv_push(uint64_t, *b64, av[i].v); - } - } - - av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); - for (i = 0; i < nv; i++) { - if (av[i].del) continue; - if(f[av[i].v] || f[av[i].v^1]) { - kv_push(uint64_t, *b64, av[i].v); - } - } - } - if((n_ext < ncut) && (n_ext > max_ext - 1)) n_ext = max_ext - 1; - if(is_telo) n_ext = max_ext + 1; - return n_ext; -} - -void debug_sysm_usg_t(usg_t *ng, const char *cmd) -{ - uint32_t v, i; usg_arc_t *p, *q; uint32_t nv; - for (v = 0; v < (ng->n<<1); v++) { - p = usg_arc_a(ng, v); nv = usg_arc_n(ng, v); - for (i = 0; i < nv; i++) { - q = get_usg_arc(ng, p[i].v^1, v^1); - if((!q) || (p[i].del != q->del)) { - fprintf(stderr, "[M::%s::%s] utg%.6dl(%c)%u -> utg%.6dl(%c)%u, p->del::%u, q->del::%u\n", - __func__, cmd, - (int32_t)(v>>1)+1, "+-"[v&1], v, - (int32_t)(p[i].v>>1)+1, "+-"[p[i].v&1], p[i].v, - p[i].del, q?q->del:1); - } - } - } -} - -void update_usg_t_threading_0(ul_resolve_t *uidx, usg_t *ng, uint64_t *a, uint64_t a_n, uint32_t *occ, asg64_v *b) -{ - uint64_t k, i, *p, nid, nnid, v, w; b->n = 0; usg_seq_t *s; - - // fprintf(stderr, "[M::%s::] a_n::%lu\n", __func__, a_n); - // for (k = 0; k < a_n; k++) { - // fprintf(stderr, "utg%.6dl(%c)(hom::%u)\t", (int32_t)(a[k]>>1)+1, "+-"[a[k]&1], (IF_HOM((a[k]>>1), (*(uidx->bub))))); - // } - // fprintf(stderr, "\n"); - - assert(a_n > 1); - assert(occ[a[0]] == 1); - kv_pushp(uint64_t, *b, &p); (*p) = a[0]; (*p) <<= 32; (*p) |= a[0]; occ[a[0]]--; - - for (k = 1; k + 1 < a_n; k++) { - assert(occ[a[k]] == occ[a[k]^1]); assert(occ[a[k]] > 0); - if(occ[a[k]] > 1) {///copy a node - nid = a[k]>>1; nnid = ng->n; - kv_push(uint32_t, ng->mp.a[ng->a[nid].mm], nnid); - s = push_usg_t_node(ng, nnid); - s->mm = ng->a[nid].mm; s->occ = ng->a[nid].occ; s->len = ng->a[nid].len; s->telo = ng->a[nid].telo; s->del = 0; - s->arc[0].n = s->arc[1].n = 0; s->arc_mm[0].n = s->arc_mm[1].n = 0; - nnid <<= 1; nnid |= a[k]&1; - kv_pushp(uint64_t, *b, &p); (*p) = a[k]^1; (*p) <<= 32; (*p) |= nnid^1; - kv_pushp(uint64_t, *b, &p); (*p) = a[k]; (*p) <<= 32; (*p) |= nnid; - } else { - kv_pushp(uint64_t, *b, &p); (*p) = a[k]^1; (*p) <<= 32; (*p) |= a[k]^1; - kv_pushp(uint64_t, *b, &p); (*p) = a[k]; (*p) <<= 32; (*p) |= a[k]; - } - occ[a[k]]--; occ[a[k]^1]--; - } - // if(occ[a[a_n-1]^1] != 1) { - // fprintf(stderr, "[M::%s] utg%.6dl(%c)(occ::%u)\n", __func__, - // (int32_t)((a[a_n-1]^1)>>1)+1, "+-"[(a[a_n-1]^1)&1], occ[a[a_n-1]^1]); - // } - assert(occ[a[a_n-1]^1] == 1); - kv_pushp(uint64_t, *b, &p); (*p) = a[a_n-1]^1; (*p) <<= 32; (*p) |= a[a_n-1]^1; occ[a[a_n-1]^1]--; - - for (k = 0; k < b->n; k += 2) { - v = b->a[k]; w = b->a[k+1]; - if(((v>>32) == ((uint32_t)v)) && ((w>>32) == ((uint32_t)w))) continue;//no need arc - remap_gen_arcs(ng, v>>32, (w>>32)^1, ((uint32_t)v), ((uint32_t)w)^1);///v>>32: old id; ((uint32_t)v): new id - remap_gen_arcs(ng, w>>32, (v>>32)^1, ((uint32_t)w), ((uint32_t)v)^1); - } - - // usg_arc_t *z = get_usg_arc(ng, 220, 157075), *q = get_usg_arc(ng, 157074, 221); - // fprintf(stderr, "\n+[M::%s::a_n->%lu] p->del::%u, q->del::%u\n", - // __func__, a_n, z?z->del:1, q?q->del:1); - - usg_arc_t *av, *aw, *z; uint32_t kv, kw, nv, nw, v0, v1, w0, w1; - for (k = 0; k < b->n; k += 2) { - v0 = b->a[k]>>32; v1 = (uint32_t)b->a[k]; - w0 = b->a[k+1]>>32; w1 = (uint32_t)b->a[k+1]; - - av = usg_arc_a(ng, v1); nv = usg_arc_n(ng, v1); - for (i = kv = 0; i < nv; i++) { - if(av[i].v == (w1^1)) { - av[i].del = 0; kv++; - } else if(av[i].del == 0) { - av[i].del = 1; - z = get_usg_arc(ng, av[i].v^1, (av[i].ul>>32)^1); - // if(!(z && (!z->del))) { - // fprintf(stderr, "[M::%s::] z::%u, z->del::%u\n", __func__, z?1:0, z?z->del:1); - // fprintf(stderr, "[M::%s::arc] utg%.6dl(%c)->utg%.6dl(%c)\n", - // __func__, (int32_t)(av[i].ul>>33)+1, "+-"[(av[i].ul>>32)&1], - // (int32_t)(av[i].v>>1)+1, "+-"[(av[i].v)&1]); - // fprintf(stderr, "[M::%s::new] utg%.6dl(%c)->utg%.6dl(%c)\n", - // __func__, (int32_t)(v1>>1)+1, "+-"[v1&1], - // (int32_t)(w1>>1)+1, "+-"[w1&1]); - // fprintf(stderr, "[M::%s::old] utg%.6dl(%c)->utg%.6dl(%c)\n", - // __func__, (int32_t)(v0>>1)+1, "+-"[v0&1], - // (int32_t)(w0>>1)+1, "+-"[w0&1]); - // } - assert(z && (!z->del)); z->del = 1; - } - } - assert(kv == 1); - - aw = usg_arc_a(ng, w1); nw = usg_arc_n(ng, w1); - for (i = kw = 0; i < nw; i++) { - if(aw[i].v == (v1^1)) { - aw[i].del = 0; kw++; - } else if(aw[i].del == 0) { - aw[i].del = 1; - z = get_usg_arc(ng, aw[i].v^1, (aw[i].ul>>32)^1); - assert(z && (!z->del)); z->del = 1; - } - } - assert(kw == 1); - - if(v0 == v1 && w0 == w1) continue; - - av = usg_arc_a(ng, v0); nv = usg_arc_n(ng, v0); - for (i = 0; i < nv; i++) { - if(av[i].v == (w0^1)) { - av[i].del = 1; break; - } - } - assert(i < nv); - - aw = usg_arc_a(ng, w0); nw = usg_arc_n(ng, w0); - for (i = 0; i < nw; i++) { - if(aw[i].v == (v0^1)) { - aw[i].del = 1; break; - } - } - assert(i < nw); - } - - // z = get_usg_arc(ng, 220, 157075), q = get_usg_arc(ng, 157074, 221); - // fprintf(stderr, "-[M::%s::a_n->%lu] p->del::%u, q->del::%u\n", - // __func__, a_n, z?z->del:1, q?q->del:1); - -} - -void update_usg_t_threading(ul_resolve_t *uidx, usg_t *ng, uint64_t *arcs, uint64_t *arcs_g, uint64_t arcs_gn, uint64_t *integ_seq, uint32_t *occ, asg64_v *b) -{ - uint64_t i, k, s, e, nvtx = ng->n<<1; memset(occ, 0, sizeof((*occ))*nvtx); - for (i = 0; i < arcs_gn; i++) {///set cluster - // prt = 0; - s = arcs[((uint32_t)arcs_g[i])]>>32; e = ((uint32_t)arcs[((uint32_t)arcs_g[i])]); assert(s < e); - for (k = s + 1; k < e; k++) {///note: here is [s, e] - occ[integ_seq[k]]++; occ[integ_seq[k]^1]++; - // if((integ_seq[k]>>1) == 2736) prt = 1; - } - occ[integ_seq[s]]++; occ[integ_seq[e]^1]++; - // if((integ_seq[s]>>1) == 2736) prt = 1; - // if(((integ_seq[e]^1)>>1) == 2736) prt = 1; - // if(occ[integ_seq[s]] > 1 || occ[integ_seq[e]^1] > 1) { - // fprintf(stderr, "s::utg%.6dl(%c)(occ::%u), e::utg%.6dl(%c)(occ::%u)\n", - // (int32_t)(integ_seq[s]>>1)+1, "+-"[integ_seq[s]&1], occ[integ_seq[s]], - // (int32_t)((integ_seq[e]^1)>>1)+1, "+-"[((integ_seq[e]^1)&1)], occ[integ_seq[e]^1]); - // } - // if(prt) { - // fprintf(stderr, "[M::%s::] a_n::%lu\n", __func__, e + 1 - s); - // for (k = s; k <= e; k++) { - // fprintf(stderr, "utg%.6dl(%c)(hom::%u)\t", - // (int32_t)(integ_seq[k]>>1)+1, "+-"[integ_seq[k]&1], - // (IF_HOM((integ_seq[k]>>1), (*(uidx->bub))))); - // } - // fprintf(stderr, "\n"); - // } - } - - for (i = 0; i < nvtx; i++) { - if(!occ[i]) occ[i] = (uint32_t)-1; - } - for (i = 0; i < arcs_gn; i++) {///arcs_g[]>>32 is the group id; (uint32_t)arcs_g[] - s = arcs[((uint32_t)arcs_g[i])]>>32; e = ((uint32_t)arcs[((uint32_t)arcs_g[i])]); - update_usg_t_threading_0(uidx, ng, integ_seq + s, e + 1 - s, occ, b); - } -} - -ma_ug_t *ma_ug_hybrid_gen(usg_t *g) -{ - int32_t *mark; uint32_t i, v, n_vtx = g->n<<1; - uint32_t w, x, l, start, end, len; ma_utg_t *p; - kdq_t(uint64_t) *q; ///is a queue - ma_ug_t *ug; - - ug = (ma_ug_t*)calloc(1, sizeof(ma_ug_t)); - ug->g = asg_init(); - ///each node has two directions - mark = (int32_t*)calloc(n_vtx, 4); - - q = kdq_init(uint64_t); - for (v = 0; v < n_vtx; ++v) { - // fprintf(stderr, "+[M::%s::] v::%u, n_vtx::%u\n", __func__, v, n_vtx); - if (g->a[v>>1].del || mark[v]) continue; - if (usg_arc_n(g, v) == 0 && usg_arc_n(g, (v^1)) != 0) continue; - // fprintf(stderr, "-[M::%s::] v::%u, n_vtx::%u\n", __func__, v, n_vtx); - mark[v] = 1; q->count = 0, start = v, end = v^1, len = 0; - // forward - w = v; - while (1) { - /** - * w----->x - * w<-----x - * that means the only suffix of w is x, and the only prefix of x is w - **/ - if (usg_arc_n(g, w) != 1) break; - x = usg_arc_a(g, w)[0].v; // w->x - if (usg_arc_n(g, x^1) != 1) break; - - /** - * another direction of w would be marked as used (since w has been used) - **/ - mark[x] = mark[w^1] = 1; - ///l is the edge length, instead of overlap length - ///note: edge length is different with overlap length - l = asg_arc_len(usg_arc_a(g, w)[0]); - kdq_push(uint64_t, q, (uint64_t)w<<32 | l); - end = x^1, len += l; - w = x; - if (x == v) break; - } - if (start != (end^1) || kdq_size(q) == 0) { // linear unitig - ///length of seq, instead of edge - l = g->a[end>>1].len; - kdq_push(uint64_t, q, (uint64_t)(end^1)<<32 | l); - len += l; - } else { // circular unitig - start = end = UINT32_MAX; - goto add_usg_unitig; // then it is not necessary to do the backward - } - - // backward - x = v; - while (1) { // similar to forward but not the same - if (usg_arc_n(g, x^1) != 1) break; - w = usg_arc_a(g, x^1)[0].v ^ 1; // w->x - if (usg_arc_n(g, w) != 1) break; - mark[x] = mark[w^1] = 1; - l = asg_arc_len(usg_arc_a(g, w)[0]); - ///w is the seq id + direction, l is the length of edge - ///push element to the front of a queue - kdq_unshift(uint64_t, q, (uint64_t)w<<32 | l); - - // fprintf(stderr, "uId: %u, >%.*s (%u)\n", - // ug->u.n, (int)Get_NAME_LENGTH((R_INF), w>>1), Get_NAME((R_INF), w>>1), w>>1); - - start = w, len += l; - x = w; - } - - add_usg_unitig: - if (start != UINT32_MAX) mark[start] = mark[end] = 1; - kv_pushp(ma_utg_t, ug->u, &p); - p->s = 0, p->start = start, p->end = end, p->len = len, p->n = kdq_size(q), p->circ = (start == UINT32_MAX); - p->m = p->n; - kv_roundup32(p->m); - p->a = (uint64_t*)malloc(8 * p->m); - //all elements are saved here - for (i = 0; i < kdq_size(q); ++i) - p->a[i] = kdq_at(q, i); - // fprintf(stderr, "*[M::%s::] v::%u, n_vtx::%u\n", __func__, v, n_vtx); - } - kdq_destroy(uint64_t, q); - // fprintf(stderr, "-1-[M::%s::] **************\n", __func__); - // add arcs between unitigs; reusing mark for a different purpose - //ug saves all unitigs - for (v = 0; v < n_vtx; ++v) mark[v] = -1; - // fprintf(stderr, "-2-[M::%s::] **************\n", __func__); - - //mark all start nodes and end nodes of all unitigs - for (i = 0; i < ug->u.n; ++i) { - if (ug->u.a[i].circ) continue; - mark[ug->u.a[i].start] = i<<1 | 0; - mark[ug->u.a[i].end] = i<<1 | 1; - } - // fprintf(stderr, "-3-[M::%s::] **************\n", __func__); - //scan all edges - usg_arc_t *av; uint32_t nv; - for (v = 0; v < n_vtx; v++) { - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - if (mark[av[i].ul>>32^1] >= 0 && mark[av[i].v] >= 0) { - uint32_t u = mark[(av[i].ul>>32)^1]^1; - int l = ug->u.a[u>>1].len - av[i].ol; - if (l < 0) l = 1; - asg_arc_t *q = asg_arc_pushp(ug->g); - q->ol = av[i].ol, q->del = 0; - q->ul = (uint64_t)u<<32 | l; - q->v = mark[av[i].v]; q->ou = 0; - } - } - } - // fprintf(stderr, "-4-[M::%s::] **************\n", __func__); - for (i = 0; i < ug->u.n; ++i) - asg_seq_set(ug->g, i, ug->u.a[i].len, 0); - // fprintf(stderr, "-5-[M::%s::] **************\n", __func__); - asg_cleanup(ug->g); - free(mark); - return ug; -} - - -// ma_ug_t *gen_unique_g(ul_resolve_t *uidx, usg_t *ng, uint32_t *hg_occ, uint64_t *integ_seq_idx, uint64_t integ_seq_n, uint64_t *integ_seq_a, uint32_t max_ext) -// { -// ma_ug_t *un_g = ma_ug_hybrid_gen(ng); ma_utg_t *u; uint64_t v, w, pi, ei, *pz, bn, a_n, ua_n; -// uint32_t i, k, n_vtx = un_g->g->n_seq<<1, s, e, vw[2], rev, sid, arc_id, z, zs, ze, mm; -// uint8_t *arc_del; MALLOC(arc_del, n_vtx); asg_arc_t *p; asg64_v b64; kv_init(b64); -// asg64_v b_za, b_zb; kv_init(b_za); kv_init(b_zb); uint8_t *ff; CALLOC(ff, ng->n<<1); -// for (i = 0; i < un_g->u.n; i++) { -// un_g->g->seq[i].c = PRIMARY_LABLE; -// u = &(un_g->u.a[i]); -// arc_del[i<<1] = arc_del[(i<<1)+1] = 1; -// if(u->n > 0) { -// if(hg_occ[u->a[u->n-1]>>32]==1) arc_del[i<<1] = 0; -// if(hg_occ[(u->a[0]>>32)^1]==1) arc_del[(i<<1)+1] = 0; -// } -// if(arc_del[i<<1] && arc_del[(i<<1)+1]) un_g->g->seq[i].del = 1; -// } -// free(un_g->g->idx); un_g->g->idx = 0; un_g->g->is_srt = 0; un_g->g->n_arc = 0;///release all edges - -// for (i = 0; i < un_g->u.n; i++) { -// if(un_g->g->seq[i].del) continue; -// if(arc_del[i<<1] && arc_del[(i<<1)+1]) continue; -// u = &(un_g->u.a[i]); -// if(!arc_del[i<<1]) { -// assert(hg_occ[u->a[u->n-1]>>32] == 1); -// hg_occ[u->a[u->n-1]>>32] = ((uint32_t)0x80000000); -// hg_occ[u->a[u->n-1]>>32] |= (i<<1); -// } - -// if(!arc_del[(i<<1)+1]) { -// assert(hg_occ[(u->a[0]>>32)^1] == 1); -// hg_occ[(u->a[0]>>32)^1] = ((uint32_t)0x80000000); -// hg_occ[(u->a[0]>>32)^1] |= ((i<<1)|1); -// } -// } - -// for (i = b64.n = ua_n = a_n = 0; i < integ_seq_n; i++) { -// s = integ_seq_idx[i]; e = s + ((uint32_t)integ_seq_idx[i]); -// assert(e > s + 1); -// for (k = s, bn = b64.n, pi = (uint64_t)-1; k < e; k++) { -// v = integ_seq_a[k]; -// if((!(hg_occ[v]&((uint32_t)0x80000000)))&&(!(hg_occ[v^1]&((uint32_t)0x80000000)))) { -// continue;///it must be a unique node -// } -// if((pi != (uint64_t)-1) && (hg_occ[v^1]&((uint32_t)0x80000000))) { -// kv_pushp(uint64_t, b64, &pz); *pz = pi; (*pz) <<= 32; (*pz) |= k; a_n++; -// } -// if(hg_occ[v]&((uint32_t)0x80000000)) pi = k; -// } - -// for (k = bn, pi = s; k < b64.n; k++) {///note here is [s, e] -// ei = b64.a[k]>>32; -// if(pi < ei) { -// kv_pushp(uint64_t, b64, &pz); ua_n++; -// (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); -// } -// pi = (uint32_t)b64.a[k]; -// } -// if(pi < e) {///note here is [s, e] -// ei = e - 1; -// if(pi < ei) { -// kv_pushp(uint64_t, b64, &pz); ua_n++; -// (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); -// } -// } -// } -// assert(a_n + ua_n == b64.n); - -// uint64_t *i_idx, b64_n, iid, n_clus; CALLOC(i_idx, ng->n<<1); -// radix_sort_srt64(b64.a, b64.a + b64.n); -// for (i = ua_n; i < b64.n; i++) {///unavailable intervals; mask all unavailable nodes -// assert(b64.a[i]&((uint64_t)0x8000000000000000)); -// s = (b64.a[i]<<1)>>33; e = (uint32_t)b64.a[i]; assert(e > s);//[s, e] -// for (k = s + 1; k < e; k++) {///note: here is [s, e] -// i_idx[integ_seq_a[k]] |= ((uint64_t)0x8000000000000000); -// i_idx[integ_seq_a[k]^1] |= ((uint64_t)0x8000000000000000); -// } -// i_idx[integ_seq_a[s]] |= ((uint64_t)0x8000000000000000); -// i_idx[integ_seq_a[e]^1] |= ((uint64_t)0x8000000000000000); -// } -// ///unavailable intervals are useless -// b64.n = a_n; ua_n = 0; -// for (i = 0; i < a_n; i++) { ///available intervals -// s = b64.a[i]>>32; e = (uint32_t)b64.a[i]; assert(e > s);///[s, e] -// assert(!(b64.a[i]&((uint64_t)0x8000000000000000))); -// for (k = s + 1; k < e; k++) {///note: here is [s, e] -// kv_pushp(uint64_t, b64, &pz); i_idx[integ_seq_a[k]]++; -// (*pz) = integ_seq_a[k]; (*pz) <<= 32; (*pz) |= i; - -// kv_pushp(uint64_t, b64, &pz); i_idx[integ_seq_a[k]^1]++; -// (*pz) = integ_seq_a[k]^1; (*pz) <<= 32; (*pz) |= i; -// } -// kv_pushp(uint64_t, b64, &pz); i_idx[integ_seq_a[s]]++; -// (*pz) = integ_seq_a[s]; (*pz) <<= 32; (*pz) |= i; - -// kv_pushp(uint64_t, b64, &pz); i_idx[integ_seq_a[e]^1]++; -// (*pz) = integ_seq_a[e]^1; (*pz) <<= 32; (*pz) |= i; -// } - -// ///index -// radix_sort_srt64(b64.a + a_n, b64.a + b64.n); -// for (k = a_n + 1, i = a_n; k <= b64.n; k++) { -// if(k == b64.n || (b64.a[k]>>32) != (b64.a[i]>>32)) { -// v = b64.a[i]>>32; -// i_idx[v] |= (((uint64_t)i)<<32)|((uint64_t)k); -// i = k; -// } -// } - -// n_clus = usg_unique_arcs_cluster(&b64, a_n, i_idx, integ_seq_a); -// assert(b64.n == (a_n<<1)); -// for (k = a_n + 1, i = a_n, mm = a_n; k <= b64.n; k++) { -// if(k == b64.n || (b64.a[k]>>32) != (b64.a[i]>>32)) { -// for (z = i; z < k; z++) { -// s = b64.a[((uint32_t)b64.a[z])]>>32; e = ((uint32_t)b64.a[((uint32_t)b64.a[z])]); assert(e > s); -// if(!ava_pass_unique_bridge(i_idx, integ_seq_a, s, e)) break; -// } -// if(z >= k) {///all arcs in this cluster is fine -// for (z = i; z < k; z++) b64.a[mm++] = b64.a[z]; -// } -// i = k; n_clus--; -// } -// } -// assert(n_clus == 0); -// b64.n = mm; n_clus = 0; -// for (k = a_n + 1, i = a_n, mm = a_n; k <= b64.n; k++) { -// if(k == b64.n || (b64.a[k]>>32) != (b64.a[i]>>32)) { -// if(ava_pass_unique_bridge_tips(ng, &b64, i, k, integ_seq_a, ff, max_ext) < max_ext) {///no long tip -// for (z = i; z < k; z++) b64.a[mm++] = b64.a[z]; -// n_clus++; -// } -// i = k; -// } -// } -// b64.n = mm; - -// if(n_clus > 0) { -// update_usg_t_threading(uidx, ng, b64.a, b64.a + a_n, b64.n - a_n, integ_seq_a, hg_occ, NULL); -// } - -// free(arc_del); free(i_idx); kv_destroy(b64); -// } - - - - - - - - - -void prt_thread_info(uint64_t *interval, uint64_t interval_n, uint64_t *cluster, uint64_t cluster_n, -const char *nn) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+70); - sprintf(gfa_name, "%s.thread_info.log", nn); - FILE* fp = fopen(gfa_name, "w"); free(gfa_name); - if (!fp) return; - uint64_t k; - if(interval) { - for (k = 0; k < interval_n; k++) fprintf(fp,"it_val::[%lu, %u)\n", interval[k]>>32, (uint32_t)interval[k]); - } - if(cluster) { - for (k = 0; k < cluster_n; k++) fprintf(fp,"cluster::%lu\tit_id::%u)\n", cluster[k]>>32, (uint32_t)cluster[k]); - } - fclose(fp); -} - -void prt_intg_info(uint64_t *int_idx, uint64_t int_idx_n, uint64_t *int_a, const char *nn) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+70); - sprintf(gfa_name, "%s.intg_info.log", nn); - FILE* fp = fopen(gfa_name, "w"); free(gfa_name); - if (!fp) return; - uint64_t k, i, s, e; - for (i = 0; i < int_idx_n; i++) {///scan all integer contigs - s = int_idx[i]>>32; e = s + ((uint32_t)int_idx[i]); - assert(e > s + 1);//the length is at least 2 - fprintf(fp,"idx::[%lu, %lu)\n", s, e); - for (k = s; k < e; k++) { - fprintf(fp,"%lu\n", int_a[k]); - } - } - fclose(fp); -} - - -void prt_usg_t(ul_resolve_t *uidx, usg_t *ng, const char *cmd); - - -#define occ_m(x) ((x)&((uint32_t)0x7fffffff)) -#define c_unqiue_m(v, occ) (occ_m((occ)[(v)]) == 1 && occ_m((occ)[(v)^1]) <= 1) -#define reli_pass(x) (!((x)&((uint64_t)0x8000000000000000))) - -uint64_t get_ext_tip(usg_t *g, uint64_t *seq, uint64_t s, uint64_t e, asg64_v *buf, asg64_v *set, uint8_t *f, uint64_t max_ext) -{ - uint64_t bn = buf->n, sn = set->n, v, k, nv, z, n_ext = 0, i, kv; usg_arc_t *av; - for (k = s + 1; k < e; k++) {///note: here is [s, e] - v = seq[k]; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (z = 0; z < nv; z++) { - if(av[z].del || f[av[z].v^1]) continue; - kv_push(uint64_t, *buf, av[z].v); - } - - v = seq[k]^1; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (z = 0; z < nv; z++) { - if(av[z].del || f[av[z].v^1]) continue; - kv_push(uint64_t, *buf, av[z].v); - } - } - - v = seq[s]; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (z = 0; z < nv; z++) { - if(av[z].del || f[av[z].v^1]) continue; - kv_push(uint64_t, *buf, av[z].v); - } - - v = seq[e]^1; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (z = 0; z < nv; z++) { - if(av[z].del || f[av[z].v^1]) continue; - kv_push(uint64_t, *buf, av[z].v); - } - - - while (buf->n > bn && n_ext < max_ext) { - v = buf->a[--buf->n]; if(f[v]) continue; - av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); - for (i = kv = 0; i < nv && kv < 1; i++) { - if (av[i].del || f[av[i].v^1]) continue; - kv++; - } - if(kv > 0) continue; - n_ext += g->a[v>>1].occ; - if(!(f[v])) { - f[v] = 1; kv_push(uint64_t, *set, v); - } - if(!(f[v^1])) { - f[v^1] = 1; kv_push(uint64_t, *set, (v^1)); - } - - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (i = 0; i < nv; i++) { - if (av[i].del || f[av[i].v^1]) continue; - kv_push(uint64_t, *buf, av[i].v); - } - } - buf->n = bn; - for (k = sn; k < set->n; k++) f[set->a[k]] = 0; - return n_ext; -} - -void select_unqiue_path_on_fly(usg_t *g, uint64_t s, uint64_t e, asg64_v *b64, asg64_v *ub64, -uint64_t *integer_seq, uint32_t *ng_occ, uint64_t *is_reli, uint8_t *f, uint64_t max_ext, asg64_v *res) -{ - uint64_t k, sk = (uint64_t)-1, ek = (uint64_t)-1, *p = NULL; ub64->n = 0; - assert(occ_m(ng_occ[integer_seq[s]]) == 1); - assert(occ_m(ng_occ[integer_seq[e]^1]) == 1); - - if(reli_pass(is_reli[integer_seq[s]])) { - sk = s; - } else { - for (k = s + 1; k < e; k++) { - if((reli_pass(is_reli[integer_seq[k]])) && (occ_m(ng_occ[integer_seq[k]]) == 1)) { - sk = k; - break; - } - } - } - if((sk == ((uint64_t)-1)) || (sk >= e)) return; - - for (k = sk + 1; k <= e; k++) { - if(sk != ((uint64_t)-1)) { - if(reli_pass(is_reli[(integer_seq[k]^1)])) { - if(occ_m((ng_occ[integer_seq[k]]^1)) == 1) { - ek = k; ///check and extend [sk, ek] - if((ek > sk) && (get_ext_tip(g, integer_seq, sk, ek, b64, ub64, f, max_ext) < max_ext)) { - p = ((res->n > 0)? (&(res->a[res->n-1])):NULL); - if(p && (((uint32_t)(*p)) == sk)) { - (*p) >>= 32; (*p) <<= 32; (*p) |= ek; - } else { - kv_pushp(uint64_t, *res, &p); *p = sk; (*p) <<= 32; (*p) |= ek; - } - } - sk = ek = ((uint64_t)-1); - } - } else { - sk = ek = ((uint64_t)-1); - } - } - - ///case2: sk != (uint64_t)-1 && ek == (uint64_t)-1 -> wait for an available ek - ///case3: sk == (uint64_t)-1 && ek == (uint64_t)-1 -> not available - if(k < e) { - if((!(reli_pass(is_reli[integer_seq[k]])))) { - sk = ek = (uint64_t)-1; continue; - } - if((sk == (uint64_t)-1) && (occ_m(ng_occ[integer_seq[k]]) == 1)) { - sk = k; - } - } - } -} - -void select_unqiue_path_on_fly_raw(usg_t *g, uint64_t s, uint64_t e, asg64_v *b64, asg64_v *ub64, -uint64_t *integer_seq, uint32_t *ng_occ, uint64_t *is_reli, uint8_t *f, uint64_t max_ext, asg64_v *res) -{ - uint64_t k, sk = (uint64_t)-1, ek = (uint64_t)-1, *p = NULL; ub64->n = 0; - assert(occ_m(ng_occ[integer_seq[s]]) == 1); - assert(occ_m(ng_occ[integer_seq[e]^1]) == 1); - sk = s; ek = e; - if(get_ext_tip(g, integer_seq, sk, ek, b64, ub64, f, max_ext) < max_ext) { - kv_pushp(uint64_t, *res, &p); *p = sk; (*p) <<= 32; (*p) |= ek; - // fprintf(stderr, "+ext_k::[%lu, %lu]\ts::%lu\te::%lu\n", sk, ek, s, e); - // fprintf(stderr, "occ[sk]::%u\tocc[ek]::%u\tocc[s]::%u\tocc[e]::%u\n", - // occ_m(ng_occ[integer_seq[sk]]), occ_m(ng_occ[integer_seq[ek]^1]), - // occ_m(ng_occ[integer_seq[s]]), occ_m(ng_occ[integer_seq[e]^1])); - } - return; - - - - for (k = sk + 1; k <= e; k++) { - if(sk != ((uint64_t)-1)) { - if(reli_pass(is_reli[(integer_seq[k]^1)])) { - if(occ_m((ng_occ[integer_seq[k]]^1)) == 1) { - ek = k; ///check and extend [sk, ek] - if((ek > sk) && (get_ext_tip(g, integer_seq, sk, ek, b64, ub64, f, max_ext) < max_ext)) { - p = ((res->n > 0)? (&(res->a[res->n-1])):NULL); - if(p && (((uint32_t)(*p)) == sk)) { - (*p) >>= 32; (*p) <<= 32; (*p) |= ek; - } else { - kv_pushp(uint64_t, *res, &p); *p = sk; (*p) <<= 32; (*p) |= ek; - } - } - sk = ek = ((uint64_t)-1); - } - } else { - sk = ek = ((uint64_t)-1); - } - } - - ///case2: sk != (uint64_t)-1 && ek == (uint64_t)-1 -> wait for an available ek - ///case3: sk == (uint64_t)-1 && ek == (uint64_t)-1 -> not available - if(k < e) { - if((!(reli_pass(is_reli[integer_seq[k]])))) { - sk = ek = (uint64_t)-1; continue; - } - if((sk == (uint64_t)-1) && (occ_m(ng_occ[integer_seq[k]]) == 1)) { - sk = k; - } - } - } -} - -void update_thread_path(usg_t *g, asg64_v *b64, asg64_v *ub64, uint64_t g_s, uint64_t g_e, uint64_t *integer_seq, -uint32_t *ng_occ, uint64_t *reliable_idx, uint8_t *f, uint64_t max_ext, asg64_v *res) -{ - uint64_t i, k, s, e; - for (i = g_s; i < g_e; i++) {///available intervals within the same cluster - s = b64->a[((uint32_t)b64->a[i])]>>32; e = ((uint32_t)b64->a[((uint32_t)b64->a[i])]); assert(s < e); - for (k = s + 1; k < e; k++) {///note: here is [s, e] - f[integer_seq[k]] = f[integer_seq[k]^1] = 1; - } - f[integer_seq[s]] = f[integer_seq[e]^1] = 1; - } - - for (i = g_s; i < g_e; i++) {///available intervals within the same cluster - s = b64->a[((uint32_t)b64->a[i])]>>32; e = ((uint32_t)b64->a[((uint32_t)b64->a[i])]); assert(s < e); - // fprintf(stderr, "[M::%s::] i::%lu, chain_id::%u\n", __func__, i, ((uint32_t)b64->a[i])); - // select_unqiue_path_on_fly(g, s, e, b64, ub64, integer_seq, ng_occ, reliable_idx, f, max_ext, res); - select_unqiue_path_on_fly_raw(g, s, e, b64, ub64, integer_seq, ng_occ, reliable_idx, f, max_ext, res); - } - - for (i = g_s; i < g_e; i++) {///available intervals within the same cluster - s = b64->a[((uint32_t)b64->a[i])]>>32; e = ((uint32_t)b64->a[((uint32_t)b64->a[i])]); assert(s < e); - for (k = s + 1; k < e; k++) {///note: here is [s, e] - f[integer_seq[k]] = f[integer_seq[k]^1] = 0; - } - f[integer_seq[s]] = f[integer_seq[e]^1] = 0; - } -} - - -typedef struct { - ul_resolve_t *uidx; - uint64_t *integer_seq; - uint64_t *gidx; - uint64_t *interval_idx; - uint64_t gidx_n; - uint8_t *f; - usg_t *ng; - uint64_t *int_idx; - uint64_t int_idx_n; - uint64_t *int_a; - uint64_t int_an; - uint64_t *ridx_a; - uint64_t *ridx; - // uint8_t is_double_check; -} unique_bridge_check_t; - -uint64_t get_arc_support(ul_resolve_t *uidx, uint64_t v, uint64_t w) -{ - uint64_t *hid_a, hid_n; ul_str_idx_t *str_idx = &(uidx->pstr); - uint64_t z, vz, occ = 0; ul_str_t *str; int64_t s, s_n; - hid_a = str_idx->occ.a + str_idx->idx.a[v>>1]; - hid_n = str_idx->idx.a[(v>>1)+1] - str_idx->idx.a[v>>1]; - - for (z = occ = 0; z < hid_n; z++) { - str = &(str_idx->str.a[hid_a[z]>>32]); s_n = str->cn; - if(s_n < 2) continue; - vz = (uint32_t)(str->a[(uint32_t)hid_a[z]]); - assert((v>>1) == (vz>>1)); - - if(v == vz) { - for(s = ((uint32_t)hid_a[z]) + 1; s < s_n; s++) { - if(((uint32_t)(str->a[s])) == w) { - occ++; break; - } - } - } else { - for(s = ((int32_t)((uint32_t)hid_a[z]))-1; s >= 0; s--) { - if(((uint32_t)(str->a[s])) == (w^1)) { - occ++; break; - } - } - } - } - return occ; -} -#define unique_bridge_occ 2 -#define unique_bridge_rate 0.499999 - -// static void worker_unique_bridge_check(void *data, long i, int tid) // callback for kt_for() -// { -// unique_bridge_check_t *uaux = (unique_bridge_check_t *)data; -// uint64_t *integer_seq = uaux->integer_seq, s, e, v, w, nse, self_k = i, k, kv; -// uint64_t *gidx = uaux->gidx, *interval = uaux->interval_idx; -// uint8_t *f = uaux->f; - -// s = interval[((uint32_t)gidx[i])]>>32; v = integer_seq[s]; -// e = ((uint32_t)interval[((uint32_t)gidx[i])]); w = integer_seq[e]^1; -// assert(s < e); - -// nse = get_arc_support(uaux->uidx, v, w^1); -// if(nse < unique_bridge_occ) { -// f[v] = f[w] = 1; return; -// } - -// for (k = 0; k < uaux->gidx_n; k++) { -// if(k == self_k) continue; -// s = interval[((uint32_t)gidx[k])]>>32; -// e = ((uint32_t)interval[((uint32_t)gidx[k])]); -// kv = get_arc_support(uaux->uidx, v, integer_seq[s]^1); -// if((kv > 0) && (kv >= (nse*unique_bridge_rate))) { -// f[v] = f[w] = 1; return; -// } - -// kv = get_arc_support(uaux->uidx, v, integer_seq[e]); -// if((kv > 0) && (kv >= (nse*unique_bridge_rate))) { -// f[v] = f[w] = 1; return; -// } - -// kv = get_arc_support(uaux->uidx, w, integer_seq[s]^1); -// if((kv > 0) && (kv >= (nse*unique_bridge_rate))) { -// f[v] = f[w] = 1; return; -// } - -// kv = get_arc_support(uaux->uidx, w, integer_seq[e]); -// if((kv > 0) && (kv >= (nse*unique_bridge_rate))) { -// f[v] = f[w] = 1; return; -// } -// } -// } - -uint64_t get_arc_support_chain(ul_resolve_t *uidx, uint64_t *a, uint64_t a_n, usg_t *ng) -{ - if(a_n <= 0) return 0; - uint64_t *hid_a, hid_n; ul_str_idx_t *str_idx = &(uidx->pstr); - uint64_t z, vz, occ = 0, v, w, ai; ul_str_t *str; int64_t s, s_n; - v = (ng->a[a[0]>>1].mm<<1)|(a[0]&1); - hid_a = str_idx->occ.a + str_idx->idx.a[v>>1]; - hid_n = str_idx->idx.a[(v>>1)+1] - str_idx->idx.a[v>>1]; - - for (z = occ = 0; z < hid_n; z++) { - str = &(str_idx->str.a[hid_a[z]>>32]); s_n = str->cn; - if(s_n < 2) continue; - vz = (uint32_t)(str->a[(uint32_t)hid_a[z]]); - assert((v>>1) == (vz>>1)); - - if(v == vz) { - for(s = ((uint32_t)hid_a[z]) + 1, ai = 1; s < s_n && ai < a_n; s++, ai++) { - w = (ng->a[a[ai]>>1].mm<<1)|(a[ai]&1); - if(((uint32_t)(str->a[s])) != w) break; - } - if(ai >= a_n) occ++; - } else { - for(s = ((int32_t)((uint32_t)hid_a[z]))-1, ai = 1; s >= 0 && ai < a_n; s--, ai++) { - w = (ng->a[a[ai]>>1].mm<<1)|(a[ai]&1); - if(((uint32_t)(str->a[s])) != (w^1)) break; - } - if(ai >= a_n) occ++; - } - } - return occ; -} - -// uint64_t is_consist_ul(ul_resolve_t *uidx, uint64_t *a, uint64_t a_n, usg_t *ng) -// { -// if(a_n <= 0) return 0; -// uint64_t k, v, w, z, *hid_a, hid_n, ulid, i; ul2ul_item_t *it;; -// ul_str_idx_t *str_idx = &(uidx->pstr); -// for (k = 0; k < a_n; k++) { -// v = (ng->a[a[k]>>1].mm<<1)|(a[k]&1); -// hid_a = str_idx->occ.a + str_idx->idx.a[v>>1]; -// hid_n = str_idx->idx.a[(v>>1)+1] - str_idx->idx.a[v>>1]; -// for (z = 0; z < hid_n; z++) { -// ulid = hid_a[z]>>32; -// if(ulid < uidx->uovl.uln) { -// it = get_ul_ovlp(&(uidx->uovl), ulid, 1); -// if(!it) continue; -// assert(uidx->pstr.str.a[ulid].cn > 1); -// if(it->is_consist == 0) return 0; -// } -// } -// } - -// uint64_t nv; asg_arc_t *av; -// v = (ng->a[a[0]>>1].mm<<1)|(a[0]&1); -// for (i = 1; i < a_n; i++) { -// w = (ng->a[a[i]>>1].mm<<1)|(a[i]&1); - -// nv = asg_arc_n(uidx->l1_ug->g, v); -// av = asg_arc_a(uidx->l1_ug->g, v); -// for (k = 0; k < nv; k++) { -// if(av[k].del) continue; -// if(av[k].v == w) break; -// } -// if(k >= nv) return 0; - -// nv = asg_arc_n(uidx->l1_ug->g, w^1); -// av = asg_arc_a(uidx->l1_ug->g, w^1); -// for (k = 0; k < nv; k++) { -// if(av[k].del) continue; -// if(av[k].v == (v^1)) break; -// } -// if(k >= nv) return 0; - -// v = w; -// } - -// return 1; -// } - -static void worker_unique_bridge_check_s(void *data, long i, int tid) // callback for kt_for() -{ - unique_bridge_check_t *uaux = (unique_bridge_check_t *)data; - uint64_t *integer_seq = uaux->integer_seq, s, e, vk, wk, nse, k; - uint64_t *gidx = uaux->gidx, *interval = uaux->interval_idx; - bubble_type *bub = uaux->uidx->bub; usg_t *ng = uaux->ng; - - s = interval[((uint32_t)gidx[i])]>>32; - e = ((uint32_t)interval[((uint32_t)gidx[i])]); - assert(s < e); - for (k = s, vk = wk = (uint32_t)-1; k <= e; k++) { - if(k > s) { - // nse = get_arc_support(uaux->uidx, (ng->a[integer_seq[k-1]>>1].mm<<1)|(integer_seq[k-1]&1), - // (ng->a[integer_seq[k]>>1].mm<<1)|(integer_seq[k]&1)); - nse = get_arc_support_chain(uaux->uidx, integer_seq+k-1, 2, ng); - if(nse < unique_bridge_occ) { - // if((!(uaux->is_double_check)) || (!is_consist_ul(uaux->uidx, integer_seq+k-1, 2, ng))) { - gidx[i] |= ((uint64_t)0x8000000000000000); return; - // } - } - } - if(IF_HOM((integer_seq[k]>>1), *bub)) continue; - // w = (ng->a[integer_seq[k]>>1].mm<<1)|(integer_seq[k]&1); - wk = k; - if(vk != (uint32_t)-1) { - // nse = get_arc_support(uaux->uidx, v, w); - nse = get_arc_support_chain(uaux->uidx, integer_seq+vk, wk+1-vk, ng); - if(nse < unique_bridge_occ) { - // if((!(uaux->is_double_check)) || (!is_consist_ul(uaux->uidx, integer_seq+vk, wk+1-vk, ng))) { - gidx[i] |= ((uint64_t)0x8000000000000000); return; - // } - } - } - vk = wk; - } -} - -uint32_t ava_pass_unique_bridge_cov(ul_resolve_t *uidx, usg_t *g, asg64_v *b64, uint64_t g_s, uint64_t g_e, uint64_t *integer_seq, uint64_t tip_l) -{ - if((tip_l == 0) && (g_e - g_s == 1)) return 1; ///if only one path, go through in anyway - uint64_t i, is_del = 0; unique_bridge_check_t uaux; - - uaux.uidx = uidx; uaux.integer_seq = integer_seq; - uaux.gidx = b64->a + g_s; uaux.gidx_n = g_e - g_s; - uaux.interval_idx = b64->a; uaux.ng = g; - ///if tip_l == 0, it is more likely to be right, so give more chance by double checking - // if(!tip_l) uaux.is_double_check = 1; - // else uaux.is_double_check = 0; - - kt_for(uidx->str_b.n_thread, worker_unique_bridge_check_s, (&uaux), g_e-g_s);///seq->n > 1 - - for (i = g_s; i < g_e; i++) {///available intervals within the same cluster - if(b64->a[i]&((uint64_t)0x8000000000000000)) { - b64->a[i] -= ((uint64_t)0x8000000000000000); is_del = 1; - } - } - return (!is_del); -} - - - -uint64_t old_path_ext(ul_resolve_t *uidx, usg_t *ng, asg64_v *b64, asg64_v *ub64, uint64_t a_n, uint64_t n_clus, uint64_t *i_idx, uint64_t *int_a, -uint8_t *ff, uint32_t *ng_occ, uint32_t max_ext) -{ - uint64_t k, i, z, /**s, e,**/ mm, tip_l; - /** - for (k = a_n + 1, i = a_n, mm = a_n; k <= b64->n; k++) { - if(k == b64->n || (b64->a[k]>>32) != (b64->a[i]>>32)) { - for (z = i; z < k; z++) {///all intger seqs within the same cluster - s = b64->a[((uint32_t)b64->a[z])]>>32; - e = ((uint32_t)b64->a[((uint32_t)b64->a[z])]); assert(e > s); - ///[s, e]:: available interval - if(!ava_pass_unique_bridge(i_idx, int_a, s, e)) break; - } - if(z >= k) {///all arcs in this cluster is fine -> each of arch is reliable - for (z = i; z < k; z++) b64->a[mm++] = b64->a[z]; - } - i = k; n_clus--; - } - } - assert(n_clus == 0); - b64->n = mm; - **/ - // prt_thread_info(b64.a, a_n, NULL, 0, "tt5"); - // fprintf(stderr, "**4**[M::%s::] a_n::%lu, n_clus::%lu\n", __func__, a_n, n_clus); - n_clus = 0; - for (k = a_n + 1, i = a_n, mm = a_n; k <= b64->n; k++) { - if(k == b64->n || (b64->a[k]>>32) != (b64->a[i]>>32)) { - tip_l = ava_pass_unique_bridge_tips(ng, b64, i, k, int_a, ff, max_ext, 0.03, 16); - if(tip_l < max_ext) {///no long tip - if(/**(!tip_l) || (**/ava_pass_unique_bridge_cov(uidx, ng, b64, i, k, int_a, tip_l)) { - for (z = i; z < k; z++) { - b64->a[mm++] = b64->a[z]; - } - n_clus++; - } - } - i = k; - } - } - // prt_thread_info(b64.a, a_n, NULL, 0, "tt6"); - b64->n = mm; - // fprintf(stderr, "**5**[M::%s::] a_n::%lu, n_clus::%lu, ng->n::%lu\n", __func__, a_n, n_clus, ng->n); - // prt_thread_info(b64.a, a_n, b64.a + a_n, b64.n - a_n, "thred"); - if(n_clus > 0) { - update_usg_t_threading(uidx, ng, b64->a, b64->a + a_n, b64->n - a_n, int_a, ng_occ, ub64); - } - // fprintf(stderr, "**6**[M::%s::] a_n::%lu, n_clus::%lu, ng->n::%lu\n", __func__, a_n, n_clus, ng->n); - return n_clus; -} - - - -void new_path_ext(ul_resolve_t *uidx, usg_t *ng, asg64_v *b64, asg64_v *ub64, uint64_t a_n, uint64_t n_clus, uint64_t *i_idx, uint64_t *int_a, -uint8_t *ff, uint32_t *ng_occ, uint32_t max_ext) -{ - asg64_v res; kv_init(res); uint64_t k, i, s, e, nvtx = ng->n<<1; - for (k = a_n + 1, i = a_n, res.n = 0; k <= b64->n; k++) { - if(k == b64->n || (b64->a[k]>>32) != (b64->a[i]>>32)) { - update_thread_path(ng, b64, ub64, i, k, int_a, ng_occ, i_idx, ff, max_ext, &res); - i = k; n_clus--; - } - } - assert(n_clus == 0); - - - if(res.n > 0) { - memset(ng_occ, 0, sizeof((*ng_occ))*nvtx); - for (i = 0; i < res.n; i++) { - s = res.a[i]>>32; e = ((uint32_t)res.a[i]); assert(s < e); - for (k = s + 1; k < e; k++) {///note: here is [s, e] - ng_occ[int_a[k]]++; ng_occ[int_a[k]^1]++; - } - ng_occ[int_a[s]]++; ng_occ[int_a[e]^1]++; - } - for (i = 0; i < nvtx; i++) { - if(!ng_occ[i]) ng_occ[i] = (uint32_t)-1; - } - - for (i = 0, ub64->n = 0; i < res.n; i++) { - s = res.a[i]>>32; e = ((uint32_t)res.a[i]); - update_usg_t_threading_0(uidx, ng, int_a + s, e + 1 - s, ng_occ, ub64); - } - } - kv_destroy(res); -} - -uint64_t gen_unique_g_adv_old(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t int_idx_n, uint64_t *int_a, uint32_t max_ext) -{ - uint64_t pi, ei, *pz, bn, a_n, ua_n, *r_a, r_n; uint8_t *ff; CALLOC(ff, ng->n<<1); - uint32_t i, k, n_vtx = ng->n<<1, s, e, zs, ze, v, b64_n; - uint32_t *ng_occ; CALLOC(ng_occ, n_vtx); - asg64_v b64, ub64; kv_init(b64); kv_init(ub64); - - for (k = 0; k < int_idx_n; k++) {///scan all integer contigs - r_a = int_a + (int_idx[k]>>32); r_n = (uint32_t)int_idx[k]; - assert(r_n >= 2); - for (i = 1; i + 1 < r_n; i++) { - ng_occ[r_a[i]]++; ng_occ[r_a[i]^1]++; - } - ng_occ[r_a[0]]++; ng_occ[r_a[r_n-1]^1]++; - } - - ma_ug_t *un_g = ma_ug_hybrid_gen(ng); ma_utg_t *u; - // print_debug_gfa(uidx->sg, un_g, uidx->uopt->coverage_cut, "iig0", uidx->uopt->sources, - // uidx->uopt->ruIndex, uidx->uopt->max_hang, uidx->uopt->min_ovlp, 0, 0, 0); - int32_t ui, un; - for (k = 0; k < un_g->u.n; k++) {///all unitigs of raw utg - u = &(un_g->u.a[k]); - zs = ze = (uint32_t)-1; un = u->n; - for (ui = 0; ui < un; ui++) { - if(occ_m(ng_occ[(u->a[ui]>>32)^1]) == 1) { - zs = ui; break; - } - } - - for (ui = ((int32_t)un)-1; ui >= 0; ui--) { - if(occ_m(ng_occ[u->a[ui]>>32]) == 1) { - ze = ui; break; - } - } - if(zs != (uint32_t)-1 && ze != (uint32_t)-1 && zs > ze) continue; - if(zs != (uint32_t)-1) ng_occ[(u->a[zs]>>32)^1] |= ((uint32_t)0x80000000); - if(ze != (uint32_t)-1) ng_occ[(u->a[ze]>>32)] |= ((uint32_t)0x80000000); - } - ma_ug_destroy(un_g); - - // fprintf(stderr, ">>>>>>[M::%s::] int_idx[0]::%lu, int_idx[1]::%lu\n", __func__, int_idx[0], int_idx[1]); - // prt_intg_info(int_idx, int_idx_n, int_a, "intg"); - for (i = b64.n = ua_n = a_n = 0; i < int_idx_n; i++) {///scan all integer contigs - s = int_idx[i]>>32; e = s + ((uint32_t)int_idx[i]); - assert(e > s + 1);//the length is at least 2 - for (k = s, bn = b64.n, pi = (uint64_t)-1; k < e; k++) { - v = int_a[k]; - if((!(ng_occ[v]&((uint32_t)0x80000000)))&&(!(ng_occ[v^1]&((uint32_t)0x80000000)))) { - continue;///it must be a unique node - } - if((pi != (uint64_t)-1) && (ng_occ[v^1]&((uint32_t)0x80000000))) { - // fprintf(stderr, "+++[M::%s::i->%u::s->%u::e->%u] pi::%lu, k::%u\n", __func__, i, s, e, pi, k); - kv_pushp(uint64_t, b64, &pz); *pz = pi; (*pz) <<= 32; (*pz) |= k; a_n++; - } - if(ng_occ[v]&((uint32_t)0x80000000)) pi = k; - } - - b64_n = b64.n; - for (k = bn, pi = s; k < b64_n; k++) { - ei = b64.a[k]>>32; - if(pi < ei) { - kv_pushp(uint64_t, b64, &pz); ua_n++; - (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); - } - pi = (uint32_t)b64.a[k]; - } - - ei = e - 1; - if(pi < ei) { - kv_pushp(uint64_t, b64, &pz); ua_n++; - (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); - } - } - assert(a_n + ua_n == b64.n); - // prt_thread_info(b64.a, a_n+ua_n, NULL, 0, "tt_minus"); - // fprintf(stderr, "**0**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); - - uint64_t *i_idx, n_clus; CALLOC(i_idx, ng->n<<1); - radix_sort_srt64(b64.a, b64.a + b64.n);///keeps the coordinates within int_a[] - - // prt_thread_info(b64.a, a_n, NULL, 0, "tt0"); - /*********debugging*********/ - // for (i = 0; i < a_n; i++) { ///available intervals - // s = b64.a[i]>>32; e = (uint32_t)b64.a[i]; - // fprintf(stderr, "[M::%s::ava->%u] s::%u, e::%u\n", __func__, i, s, e); - // for (k = s; k <= e; k++) { - // fprintf(stderr, "utg%.6dl(%c)\n", ((int32_t)(int_a[k]>>1))+1, "+-"[int_a[k]&1]); - // } - // } - // for (i = a_n; i < b64.n; i++) {///unavailable intervals - // s = (b64.a[i]<<1)>>33; e = (uint32_t)b64.a[i]; - // fprintf(stderr, "[M::%s::uava->%u] s::%u, e::%u\n", __func__, i - (uint32_t)a_n, s, e); - // for (k = s; k <= e; k++) { - // fprintf(stderr, "utg%.6dl(%c)\n", ((int32_t)(int_a[k]>>1))+1, "+-"[int_a[k]&1]); - // } - // } - /*********debugging*********/ - - - - - - - for (i = a_n; i < b64.n; i++) {///unavailable intervals; mask all unavailable nodes - assert(b64.a[i]&((uint64_t)0x8000000000000000)); ua_n--; - s = (b64.a[i]<<1)>>33; e = (uint32_t)b64.a[i]; assert(e > s);//[s, e] - for (k = s + 1; k < e; k++) {///note: here is [s, e] - i_idx[int_a[k]] |= ((uint64_t)0x8000000000000000); - i_idx[int_a[k]^1] |= ((uint64_t)0x8000000000000000); - } - i_idx[int_a[s]] |= ((uint64_t)0x8000000000000000); - i_idx[int_a[e]^1] |= ((uint64_t)0x8000000000000000); - } - // prt_thread_info(b64.a, a_n, NULL, 0, "tt1"); - ///unavailable intervals are useless - b64.n = a_n; assert(ua_n == 0); - for (i = 0; i < a_n; i++) { ///available intervals - s = b64.a[i]>>32; e = (uint32_t)b64.a[i]; assert(e > s);///[s, e] -> coordinates within int_a[] - if(i == 3201 || i == 3202) { - fprintf(stderr, "[M::%s::] s::%u, e::%u, int_a[s]::%lu(occ::%u), int_a[e]^1::%lu(occ::%u)\n", - __func__, s, e, int_a[s], occ_m(ng_occ[int_a[s]]), - int_a[e]^1, occ_m(ng_occ[int_a[e]^1])); - } - - assert(!(b64.a[i]&((uint64_t)0x8000000000000000))); - for (k = s + 1; k < e; k++) {///note: here is [s, e]; s && e are unique, but [s+1, e-1] are not unique - kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[k]]++; - (*pz) = int_a[k]; (*pz) <<= 32; (*pz) |= i;///(raw unitig/non-unqiue node id)|(integer contig id) - - kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[k]^1]++; - (*pz) = int_a[k]^1; (*pz) <<= 32; (*pz) |= i; - } - kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[s]]++; - (*pz) = int_a[s]; (*pz) <<= 32; (*pz) |= i; - - kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[e]^1]++; - (*pz) = int_a[e]^1; (*pz) <<= 32; (*pz) |= i; - } - // prt_thread_info(b64.a, a_n, NULL, 0, "tt2"); - // fprintf(stderr, "**1**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); - ///index - radix_sort_srt64(b64.a + a_n, b64.a + b64.n);///(raw unitig node id)|(integer contig id) - for (k = a_n + 1, i = a_n; k <= b64.n; k++) { - if(k == b64.n || (b64.a[k]>>32) != (b64.a[i]>>32)) { - i_idx[b64.a[i]>>32] |= (((uint64_t)i)<<32)|((uint64_t)k);///b64.a[i]>>32 appear once (unique ends)/multipe times - i = k; - } - } - // prt_thread_info(b64.a, a_n, NULL, 0, "tt3"); - // fprintf(stderr, "**2**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); - ///b64.a[0, a_n]:: all resolvable paths with unique beg && end - ///b64.a[a_n, b64.n]:: (raw unitig/non-unqiue node id)|(resolvable path id) - // n_clus = usg_unique_arcs_cluster(&b64, a_n, i_idx, int_a);///this function might be wrong - n_clus = usg_unique_arcs_cluster_adv(&b64, a_n, i_idx, int_a, &ub64); - fprintf(stderr, "**3**[M::%s::] a_n::%lu, n_clus::%lu\n", __func__, a_n, n_clus); - // prt_thread_info(b64.a, a_n, NULL, 0, "tt4"); - assert(b64.n == (a_n<<1)); - old_path_ext(uidx, ng, &b64, &ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext); - // new_path_ext(uidx, ng, &b64, &ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext); - - free(ng_occ); free(i_idx); free(ff); kv_destroy(b64); kv_destroy(ub64); - return b64.n - a_n; -} - -uint64_t gen_unique_g_adv(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t int_idx_n, uint64_t *int_a, uint32_t max_ext) -{ - uint64_t pi, ei, *pz, bn, a_n, ua_n, *r_a, r_n; uint8_t *ff; CALLOC(ff, ng->n<<1); - uint32_t i, k, n_vtx = ng->n<<1, s, e, zs, ze, v, b64_n; - uint32_t *ng_occ; CALLOC(ng_occ, n_vtx); - asg64_v b64, ub64; kv_init(b64); kv_init(ub64); - uint64_t *i_idx, n_clus; CALLOC(i_idx, ng->n<<1); - - for (k = 0; k < int_idx_n; k++) {///scan all integer contigs - r_a = int_a + (int_idx[k]>>32); r_n = (uint32_t)int_idx[k]; - assert(r_n >= 2); - for (i = 1; i + 1 < r_n; i++) { - ng_occ[r_a[i]]++; ng_occ[r_a[i]^1]++; - } - ng_occ[r_a[0]]++; ng_occ[r_a[r_n-1]^1]++; - } - - ma_ug_t *un_g = ma_ug_hybrid_gen(ng); ma_utg_t *u; - // print_debug_gfa(uidx->sg, un_g, uidx->uopt->coverage_cut, "iig0", uidx->uopt->sources, - // uidx->uopt->ruIndex, uidx->uopt->max_hang, uidx->uopt->min_ovlp, 0, 0, 0); - int32_t ui, un; - for (k = 0; k < un_g->u.n; k++) {///all unitigs of raw utg - u = &(un_g->u.a[k]); - zs = ze = (uint32_t)-1; un = u->n; - for (ui = 0; ui < un; ui++) { - if(occ_m(ng_occ[(u->a[ui]>>32)^1]) == 1) { - zs = ui; break; - } - } - - for (ui = ((int32_t)un)-1; ui >= 0; ui--) { - if(occ_m(ng_occ[u->a[ui]>>32]) == 1) { - ze = ui; break; - } - } - if(zs != (uint32_t)-1 && ze != (uint32_t)-1 && zs > ze) continue; - if(zs != (uint32_t)-1) ng_occ[(u->a[zs]>>32)^1] |= ((uint32_t)0x80000000); - if(ze != (uint32_t)-1) ng_occ[(u->a[ze]>>32)] |= ((uint32_t)0x80000000); - } - ma_ug_destroy(un_g); - - // fprintf(stderr, ">>>>>>[M::%s::] int_idx[0]::%lu, int_idx[1]::%lu\n", __func__, int_idx[0], int_idx[1]); - // prt_intg_info(int_idx, int_idx_n, int_a, "intg"); - for (i = b64.n = ua_n = a_n = 0; i < int_idx_n; i++) {///scan all integer contigs - s = int_idx[i]>>32; e = s + ((uint32_t)int_idx[i]); - assert(e > s + 1);//the length is at least 2 - for (k = s, bn = b64.n, pi = (uint64_t)-1; k < e; k++) { - v = int_a[k]; - if((!(ng_occ[v]&((uint32_t)0x80000000)))&&(!(ng_occ[v^1]&((uint32_t)0x80000000)))) { - continue;///it must be a unique node - } - if((pi != (uint64_t)-1) && (ng_occ[v^1]&((uint32_t)0x80000000))) { - // fprintf(stderr, "+++[M::%s::i->%u::s->%u::e->%u] pi::%lu, k::%u\n", __func__, i, s, e, pi, k); - pz = (b64.n>0)? &(b64.a[b64.n-1]):(NULL); - if((!pz) || (((*pz)>>32) != pi)) {//keep the shortest pi<->k - kv_pushp(uint64_t, b64, &pz); - *pz = pi; (*pz) <<= 32; (*pz) |= k; - a_n++; - } - } - if(ng_occ[v]&((uint32_t)0x80000000)) pi = k;//keep the shortest pi<->k - } - - b64_n = b64.n; - for (k = bn, pi = s; k < b64_n; k++) { - ei = b64.a[k]>>32; - if(pi < ei) { - kv_pushp(uint64_t, b64, &pz); ua_n++; - (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); - } - pi = (uint32_t)b64.a[k]; - } - - ei = e - 1; - if(pi < ei) { - kv_pushp(uint64_t, b64, &pz); ua_n++; - (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); - } - } - assert(a_n + ua_n == b64.n); - // prt_thread_info(b64.a, a_n+ua_n, NULL, 0, "tt_minus"); - // fprintf(stderr, "**0**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); - radix_sort_srt64(b64.a, b64.a + b64.n);///keeps the coordinates within int_a[] - - for (i = a_n; i < b64.n; i++) {///unavailable intervals; mask all unavailable nodes - assert(b64.a[i]&((uint64_t)0x8000000000000000)); ua_n--; - s = (b64.a[i]<<1)>>33; e = (uint32_t)b64.a[i]; assert(e > s);//[s, e] - for (k = s + 1; k < e; k++) {///note: here is [s, e] - i_idx[int_a[k]] |= ((uint64_t)0x8000000000000000); - i_idx[int_a[k]^1] |= ((uint64_t)0x8000000000000000); - } - i_idx[int_a[s]] |= ((uint64_t)0x8000000000000000); - i_idx[int_a[e]^1] |= ((uint64_t)0x8000000000000000); - } - // prt_thread_info(b64.a, a_n, NULL, 0, "tt1"); - ///unavailable intervals are useless - b64.n = a_n; assert(ua_n == 0); - for (i = 0; i < a_n; i++) { ///available intervals - s = b64.a[i]>>32; e = (uint32_t)b64.a[i]; assert(e > s);///[s, e] -> coordinates within int_a[] - assert(!(b64.a[i]&((uint64_t)0x8000000000000000))); - - for (k = s + 1; k < e; k++) {///note: here is [s, e]; s && e are unique, but [s+1, e-1] are not unique - kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[k]]++; - (*pz) = int_a[k]; (*pz) <<= 32; (*pz) |= i;///(raw unitig/non-unqiue node id)|(integer contig id) - - kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[k]^1]++; - (*pz) = int_a[k]^1; (*pz) <<= 32; (*pz) |= i; - } - kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[s]]++; - (*pz) = int_a[s]; (*pz) <<= 32; (*pz) |= i; - - kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[e]^1]++; - (*pz) = int_a[e]^1; (*pz) <<= 32; (*pz) |= i; - } - // prt_thread_info(b64.a, a_n, NULL, 0, "tt2"); - // fprintf(stderr, "**1**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); - ///index - radix_sort_srt64(b64.a + a_n, b64.a + b64.n);///(raw unitig node id)|(integer contig id) - for (k = a_n + 1, i = a_n; k <= b64.n; k++) { - if(k == b64.n || (b64.a[k]>>32) != (b64.a[i]>>32)) { - i_idx[b64.a[i]>>32] |= (((uint64_t)i)<<32)|((uint64_t)k);///b64.a[i]>>32 appear once (unique ends)/multipe times - i = k; - } - } - // prt_thread_info(b64.a, a_n, NULL, 0, "tt3"); - // fprintf(stderr, "**2**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); - ///b64.a[0, a_n]:: all resolvable paths with unique beg && end - ///b64.a[a_n, b64.n]:: (raw unitig/non-unqiue node id)|(resolvable path id) - // n_clus = usg_unique_arcs_cluster(&b64, a_n, i_idx, int_a);///this function might be wrong - n_clus = usg_unique_arcs_cluster_adv(&b64, a_n, i_idx, int_a, &ub64); - // fprintf(stderr, "**3**[M::%s::] a_n::%lu, n_clus::%lu\n", __func__, a_n, n_clus); - // prt_thread_info(b64.a, a_n, NULL, 0, "tt4"); - assert(b64.n == (a_n<<1)); - old_path_ext(uidx, ng, &b64, &ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext); - // new_path_ext(uidx, ng, &b64, &ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext);//wrong - - free(ng_occ); free(i_idx); free(ff); kv_destroy(b64); kv_destroy(ub64); - return b64.n - a_n; -} - -void u2g_hybrid_detan(ul_resolve_t *uidx, usg_t *ng, uint32_t max_ext, asg64_v *in, asg64_v *ib) -{ - uint64_t k, i, x, m, *tmp, sn; asg64_v tx = {0,0,0}, tb = {0,0,0}, *ob = NULL, *ub = NULL; - ob = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); ob->n = ub->n = 0; - - for (k = 0; k < uidx->str_b.n_thread; k++) { - uidx->str_b.buf[k].res_dump.n = uidx->str_b.buf[k].u.n = uidx->str_b.buf[k].o.n = 0; - } - kt_for(uidx->str_b.n_thread, worker_integer_realign_g, uidx, uidx->uovl.i_ug->u.n); - - for (k = ob->n = ub->n = m = 0; k < uidx->str_b.n_thread; k++) { - for (i = 0; i < uidx->str_b.buf[k].res_dump.n; i++) { - x = uidx->str_b.buf[k].res_dump.a[i]; - kv_push(uint64_t, *ob, x);//aln details - if(x&((uint64_t)0x8000000000000000)) { - x -= ((uint64_t)0x8000000000000000); x >>= 32; x <<= 32;//seq_id - x |= ob->n;//offset - kv_push(uint64_t, *ub, x);///idx:: seq_id|offset_in_ob - } else { - m++; - } - } - } - - radix_sort_srt64(ub->a, ub->a + ub->n); - kv_resize(uint64_t, *ub, ub->n+m); tmp = ub->a + ub->n; m = 0; - for (k = 0; k < ub->n; k++) { - sn = ((uint32_t)(ob->a[((uint32_t)ub->a[k])-1])); - memcpy(tmp + m, ob->a + ((uint32_t)ub->a[k]), sn*sizeof((*tmp))); - ub->a[k] = m; ub->a[k] <<= 32; ub->a[k] |= sn;//offset_in_ob|occ - m += sn; - } - assert(m <= ob->n); - memcpy(ob->a, tmp, m*sizeof((*tmp))); ob->n = m; - - - // for (k = 0, p = NULL; k < ub->n; k++) { - // p = &(ob->a[((uint32_t)ub->a[k])-1]); - // x = ub->a[k]<<32;//offset - // x |= ((uint32_t)(*p));///occ - // ub->a[k] = x; - // (*p) >>= 32; (*p) <<= 32; (*p) |= k; - // } - // for (k = m = 0; k < ob->n; k++) { - // if(ob->a[k]&((uint64_t)0x8000000000000000)) { - // x = m; x <<= 32; x |= ((uint32_t)ub->a[(uint32_t)ob->a[k]]); - // ub->a[(uint32_t)ob->a[k]] = x; - // } else { - // ob->a[m++] = ob->a[k]; - // } - // } - // ob->n = m; - - // for (k = ob->n = ub->n = 0; k < uidx->str_b.n_thread; k++) { - // for (i = 0; i < uidx->str_b.buf[k].res_dump.n; i++) { - // if((uidx->str_b.buf[k].res_dump.a[i]>>32)==((uint32_t)-1)) { - // x = ob->n; x <<= 32; x |= ((uint32_t)uidx->str_b.buf[k].res_dump.a[i]); - // kv_push(uint64_t, *ub, x);///idx:: offset_in_ob|occ - // } else { - // kv_push(uint64_t, *ob, uidx->str_b.buf[k].res_dump.a[i]);//aln details - // } - // } - // } - - /*********debugging*********/ - fprintf(stderr, "[M::%s::] # iug::%u, # gchain::%u\n", __func__, (uint32_t)uidx->uovl.i_ug->u.n, (uint32_t)ub->n); - // for (k = 0; k < ub->n; k++) { - // // fprintf(stderr, "[M::%s::k->%lu] # iug::%u, # chain::%u, off chain::%u\n", - // // __func__, k, (uint32_t)uidx->uovl.cc.iug_a[k].n, (uint32_t)ub->a[k], (uint32_t)(ub->a[k]>>32)); - // for (i = 0; i < (uint32_t)ub->a[k]; i++) { - // // fprintf(stderr, "utg%.6dl(%c) <------> utg%.6dl(%c)\n", - // // ((int32_t)(uidx->uovl.cc.iug_a[k].a[i].v>>1))+1, "+-"[uidx->uovl.cc.iug_a[k].a[i].v&1], - // // ((int32_t)(ob->a[(ub->a[k]>>32)+i]>>1))+1, "+-"[ob->a[(ub->a[k]>>32)+i]&1]); - // assert(uidx->uovl.cc.iug_a[k].a[i].v == ob->a[(ub->a[k]>>32)+i]); - // } - // } - /*********debugging*********/ - - ///ub->idx; ob->nodes - // u_ug = gen_unique_g(uidx, ng, ng_occ, ub->a, ub->n, ob->a);//ma_ug_hybrid_gen(ng); - ///debug - debug_sysm_usg_t(ng, __func__); - // prt_usg_t(uidx, ng, "ng4"); - if(gen_unique_g_adv(uidx, ng, ub->a, ub->n, ob->a, max_ext)) { - // usg_arc_t *z = get_usg_arc(ng, 2, 576), *q = get_usg_arc(ng, 577, 3); - // fprintf(stderr, "xxxx0xxx[M::%s::] p->del::%u, q->del::%u\n", - // __func__, z?z->del:1, q?q->del:1); - ///debug - debug_sysm_usg_t(ng, __func__); - // z = get_usg_arc(ng, 2, 576); q = get_usg_arc(ng, 577, 3); - // fprintf(stderr, "xxxx1xxx[M::%s::] p->del::%u, q->del::%u\n", - // __func__, z?z->del:1, q?q->del:1); - // fprintf(stderr, "+[M::%s::] ng->n::%u\n", __func__, (uint32_t)ng->n); - usg_cleanup(ng); - ///debug - debug_sysm_usg_t(ng, __func__); - // fprintf(stderr, "-[M::%s::] ng->n::%u\n", __func__, (uint32_t)ng->n); - } - // prt_usg_t(uidx, ng, "ng_dbg"); - if(!in) free(tx.a); if(!ib) free(tb.a); -} - -void u2g_hybrid_aln(ul_resolve_t *uidx, usg_t *ng, asg64_v *ob, asg64_v *ub) -{ - uint64_t k, m, i, x, *tmp, sn; - ob->n = ub->n = 0; - for (k = 0; k < uidx->str_b.n_thread; k++) { - uidx->str_b.buf[k].res_dump.n = uidx->str_b.buf[k].u.n = uidx->str_b.buf[k].o.n = 0; - } - kt_for(uidx->str_b.n_thread, worker_integer_realign_g, uidx, uidx->uovl.i_ug->u.n); - - for (k = ob->n = ub->n = m = 0; k < uidx->str_b.n_thread; k++) { - for (i = 0; i < uidx->str_b.buf[k].res_dump.n; i++) { - x = uidx->str_b.buf[k].res_dump.a[i]; - kv_push(uint64_t, *ob, x);//aln details - if(x&((uint64_t)0x8000000000000000)) { - x -= ((uint64_t)0x8000000000000000); x >>= 32; x <<= 32;//seq_id - x |= ob->n;//offset - kv_push(uint64_t, *ub, x);///idx:: seq_id|offset_in_ob - } else { - m++; - } - } - } - - radix_sort_srt64(ub->a, ub->a + ub->n); - kv_resize(uint64_t, *ub, ub->n+m); tmp = ub->a + ub->n; m = 0; - for (k = 0; k < ub->n; k++) { - sn = ((uint32_t)(ob->a[((uint32_t)ub->a[k])-1])); - memcpy(tmp + m, ob->a + ((uint32_t)ub->a[k]), sn*sizeof((*tmp))); - ub->a[k] = m; ub->a[k] <<= 32; ub->a[k] |= sn;//offset_in_ob|occ - m += sn; - } - assert(m <= ob->n); - memcpy(ob->a, tmp, m*sizeof((*tmp))); ob->n = m; -} - -uint32_t ug_ext(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t int_idx_n, uint64_t *int_a, uint32_t max_ext, -uint8_t *ff, uint32_t *ng_occ, uint64_t *i_idx, asg64_v *b64, asg64_v *ub64) -{ - uint32_t n_vtx = ng->n<<1, k, i; uint64_t pi, ei, *pz, v, b64_n; - uint64_t *r_a, r_n, zs, ze, s, e, a_n, ua_n, bn, n_clus; - memset(ff, 0, sizeof((*ff))*n_vtx); - memset(ng_occ, 0, sizeof((*ng_occ))*n_vtx); - memset(i_idx, 0, sizeof((*i_idx))*n_vtx); - b64->n = ub64->n = 0; - - for (k = 0; k < int_idx_n; k++) {///scan all integer contigs - r_a = int_a + (int_idx[k]>>32); r_n = (uint32_t)int_idx[k]; - assert(r_n >= 2); - for (i = 1; i + 1 < r_n; i++) { - ng_occ[r_a[i]]++; ng_occ[r_a[i]^1]++; - } - ng_occ[r_a[0]]++; ng_occ[r_a[r_n-1]^1]++; - } - - ma_ug_t *un_g = ma_ug_hybrid_gen(ng); - int32_t ui, un; ma_utg_t *u = NULL; - for (k = 0; k < un_g->u.n; k++) {///all unitigs of raw utg - u = &(un_g->u.a[k]); - zs = ze = (uint32_t)-1; un = u->n; - for (ui = 0; ui < un; ui++) { - if(occ_m(ng_occ[(u->a[ui]>>32)^1]) == 1) { - zs = ui; break; - } - } - - for (ui = ((int32_t)un)-1; ui >= 0; ui--) { - if(occ_m(ng_occ[u->a[ui]>>32]) == 1) { - ze = ui; break; - } - } - if(zs != (uint32_t)-1 && ze != (uint32_t)-1 && zs > ze) continue; - if(zs != (uint32_t)-1) ng_occ[(u->a[zs]>>32)^1] |= ((uint32_t)0x80000000); - if(ze != (uint32_t)-1) ng_occ[(u->a[ze]>>32)] |= ((uint32_t)0x80000000); - } - ma_ug_destroy(un_g); - - // fprintf(stderr, ">>>>>>[M::%s::] int_idx[0]::%lu, int_idx[1]::%lu\n", __func__, int_idx[0], int_idx[1]); - // prt_intg_info(int_idx, int_idx_n, int_a, "intg"); - for (i = b64->n = ua_n = a_n = 0; i < int_idx_n; i++) {///scan all integer contigs - s = int_idx[i]>>32; e = s + ((uint32_t)int_idx[i]); - assert(e > s + 1);//the length is at least 2 - for (k = s, bn = b64->n, pi = (uint64_t)-1; k < e; k++) { - v = int_a[k]; - if((!(ng_occ[v]&((uint32_t)0x80000000)))&&(!(ng_occ[v^1]&((uint32_t)0x80000000)))) { - continue;///it must be a unique node - } - if((pi != (uint64_t)-1) && (ng_occ[v^1]&((uint32_t)0x80000000))) { - pz = (b64->n>0)? &(b64->a[b64->n-1]):(NULL); - if((!pz) || (((*pz)>>32) != pi)) {//keep the shortest pi<->k - kv_pushp(uint64_t, *b64, &pz); - *pz = pi; (*pz) <<= 32; (*pz) |= k; - a_n++; - } - } - if(ng_occ[v]&((uint32_t)0x80000000)) pi = k;//keep the shortest pi<->k - } - - b64_n = b64->n; - for (k = bn, pi = s; k < b64_n; k++) { - ei = b64->a[k]>>32; - if(pi < ei) { - kv_pushp(uint64_t, *b64, &pz); ua_n++; - (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); - } - pi = (uint32_t)b64->a[k]; - } - - ei = e - 1; - if(pi < ei) { - kv_pushp(uint64_t, *b64, &pz); ua_n++; - (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); - } - } - assert(a_n + ua_n == b64->n); - // prt_thread_info(b64.a, a_n+ua_n, NULL, 0, "tt_minus"); - // fprintf(stderr, "**0**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); - radix_sort_srt64(b64->a, b64->a + b64->n);///keeps the coordinates within int_a[] - - - for (i = a_n; i < b64->n; i++) {///unavailable intervals; mask all unavailable nodes - assert(b64->a[i]&((uint64_t)0x8000000000000000)); ua_n--; - s = (b64->a[i]<<1)>>33; e = (uint32_t)b64->a[i]; assert(e > s);//[s, e] - for (k = s + 1; k < e; k++) {///note: here is [s, e] - i_idx[int_a[k]] |= ((uint64_t)0x8000000000000000); - i_idx[int_a[k]^1] |= ((uint64_t)0x8000000000000000); - } - i_idx[int_a[s]] |= ((uint64_t)0x8000000000000000); - i_idx[int_a[e]^1] |= ((uint64_t)0x8000000000000000); - } - // prt_thread_info(b64.a, a_n, NULL, 0, "tt1"); - ///unavailable intervals are useless - b64->n = a_n; assert(ua_n == 0); - for (i = 0; i < a_n; i++) { ///available intervals - s = b64->a[i]>>32; e = (uint32_t)b64->a[i]; assert(e > s);///[s, e] -> coordinates within int_a[] - assert(!(b64->a[i]&((uint64_t)0x8000000000000000))); - - for (k = s + 1; k < e; k++) {///note: here is [s, e]; s && e are unique, but [s+1, e-1] are not unique - kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[k]]++; - (*pz) = int_a[k]; (*pz) <<= 32; (*pz) |= i;///(raw unitig/non-unqiue node id)|(integer contig id) - - kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[k]^1]++; - (*pz) = int_a[k]^1; (*pz) <<= 32; (*pz) |= i; - } - kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[s]]++; - (*pz) = int_a[s]; (*pz) <<= 32; (*pz) |= i; - - kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[e]^1]++; - (*pz) = int_a[e]^1; (*pz) <<= 32; (*pz) |= i; - } - // prt_thread_info(b64.a, a_n, NULL, 0, "tt2"); - // fprintf(stderr, "**1**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); - ///index - radix_sort_srt64(b64->a + a_n, b64->a + b64->n);///(raw unitig node id)|(integer contig id) - for (k = a_n + 1, i = a_n; k <= b64->n; k++) { - if(k == b64->n || (b64->a[k]>>32) != (b64->a[i]>>32)) { - i_idx[b64->a[i]>>32] |= (((uint64_t)i)<<32)|((uint64_t)k);///b64.a[i]>>32 appear once (unique ends)/multipe times - i = k; - } - } - // prt_thread_info(b64.a, a_n, NULL, 0, "tt3"); - // fprintf(stderr, "**2**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); - ///b64.a[0, a_n]:: all resolvable paths with unique beg && end - ///b64.a[a_n, b64.n]:: (raw unitig/non-unqiue node id)|(resolvable path id) - // n_clus = usg_unique_arcs_cluster(&b64, a_n, i_idx, int_a);///this function might be wrong - n_clus = usg_unique_arcs_cluster_adv(b64, a_n, i_idx, int_a, ub64); - // fprintf(stderr, "**3**[M::%s::] a_n::%lu, n_clus::%lu\n", __func__, a_n, n_clus); - // prt_thread_info(b64.a, a_n, NULL, 0, "tt4"); - assert(b64->n == (a_n<<1)); - old_path_ext(uidx, ng, b64, ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext); - // new_path_ext(uidx, ng, &b64, &ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext);//wrong - return b64->n - a_n; -} - -void merge_hybrid_utg_content(ma_utg_t* cc, ma_ug_t* raw, asg_t* rg, usg_t *ng, kvec_asg_arc_t_warp* edge); -void renew_usg_t_bub(ul_resolve_t *uidx, usg_t *ng, uint32_t *id_map, uint8_t *ff, uint32_t rocc_cut) -{ - ma_ug_t *ug = ma_ug_hybrid_gen(ng); - uint32_t i, k, v, p[2]; ma_utg_t *u; p[0] = 1; p[1] = 2; - memset(id_map, -1, sizeof((*id_map))*ng->n); - memset(ff, 0, sizeof((*ff))*(ng->n<<1)); - kvec_asg_arc_t_warp e; kv_init(e.a); e.i = 0; - // for (i = dn = 0; i < ng->n; i++) { - // if(ng->a[i].del) continue; - // dn++; - // } - // fprintf(stderr, "ng->n::%u, ug->u.n::%u, dn::%u\n", (uint32_t)ng->n, (uint32_t)ug->u.n, dn); - // dn = 0 - for (i = 0; i < ug->u.n; i++) { - ug->g->seq[i].c = PRIMARY_LABLE; - u = &(ug->u.a[i]); - if(u->m == 0) continue; - for (k = 0; k < u->n; k++) { - v = u->a[k]>>32; - id_map[v>>1] = i<<2; - if(k == 0) id_map[v>>1] |= p[(v^1)&1]; - if(k + 1 == u->n) id_map[v>>1] |= p[(v)&1]; - // dn++; - } - // fprintf(stderr, "+[M::%s] i::%u\n", __func__, i); - merge_hybrid_utg_content(u, uidx->l1_ug, uidx->sg, ng, &e); - // fprintf(stderr, "-[M::%s] i::%u\n", __func__, i); - ug->g->seq[i].len = u->len; - } - kv_destroy(e.a); - - destory_bubbles(uidx->bub); free(uidx->bub); CALLOC(uidx->bub, 1); - // fprintf(stderr, "[M::%s] homozygous read coverage threshold: %d\n", __func__, asm_opt.hom_global_coverage_set? - // asm_opt.hom_global_coverage:(int)(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); - // identify_bubbles(ug, uidx->bub, uidx->r_het, NULL); - if(asm_opt.polyploidy <= 2) { - identify_bubbles_recal(uidx->sg, ug, uidx->bub, uidx->r_het, uidx->uopt->sources, uidx->uopt->ruIndex, NULL); - } else { - identify_bubbles_recal_poy(uidx->sg, ug, uidx->bub, uidx->r_het, uidx->uopt->sources, uidx->uopt->ruIndex, NULL); - } - - // fprintf(stderr, "0[M::%s::] f[51]::%u\n", __func__, ff[51]); - for (i = 0; i < ng->n; i++) { - if(id_map[i] != (uint32_t)-1) { - k = id_map[i]>>2; - // fprintf(stderr, "k::%u, ng->n::%u, ug->u.n::%u, dn::%u\n", k, (uint32_t)ng->n, (uint32_t)ug->u.n, dn); - // if(i == 7075 || i == 28174 || i == 77111 || i == 3826 || i == 12150 || i == 58312 || i == 59190 || i == 72134) { - // fprintf(stderr, "[M::%s::k->%u] utg%.6dl(%c), ug->u.a[k].n::%u, rocc_cut::%u, is_hom::%u\n", __func__, k, - // i+1, "+-"[0], (uint32_t)ug->u.a[k].n, rocc_cut, IF_HOM(k, (*(uidx->bub)))); - // } - if((ug->u.a[k].n >= rocc_cut) && - ((!(IF_HOM(k, (*(uidx->bub))))) || (asm_opt.purge_level_primary == 0))) { - if(id_map[i]&p[0]) { - ff[i<<1] = 2; - // fprintf(stderr, "[M::%s::] utg%.6dl(%c), ug->u.a[k].n::%u, rocc_cut::%u\n", __func__, - // i+1, "+-"[0], (uint32_t)ug->u.a[k].n, rocc_cut); - } - if(id_map[i]&p[1]) { - ff[(i<<1)+1] = 2; - // fprintf(stderr, "[M::%s::] utg%.6dl(%c), ug->u.a[k].n::%u, rocc_cut::%u\n", __func__, - // i+1, "+-"[1], (uint32_t)ug->u.a[k].n, rocc_cut); - } - } - id_map[i] = uidx->bub->index[k]; - } - } - // fprintf(stderr, "1[M::%s::] f[51]::%u\n", __func__, ff[51]); - free(uidx->bub->index); MALLOC(uidx->bub->index, ng->n); - memcpy(uidx->bub->index, id_map, sizeof((*id_map))*ng->n); - if(asm_opt.purge_level_primary == 0) {///all nodes are het - for (k = 0; k < ug->g->n_seq; k++) { - if(IF_HOM(k, *(uidx->bub))) uidx->bub->index[k] = uidx->bub->f_bub+1; - } - } - ma_ug_destroy(ug); -} - -void gen_hybrid_aln_idx(usg_t *ng, uint64_t *int_idx, uint64_t int_idx_n, uint64_t *int_a, uint64_t int_an, asg64_v *b64, uint64_t *ridx) -{ - uint64_t k, i, l, m, v, s, e, *a, a_n; - kv_resize(uint64_t, *b64, int_an); b64->n = int_an; - memset(ridx, 0, sizeof((*ridx))*ng->n); - for (k = 0; k < int_idx_n; k++) {///scan all integer contigs - s = int_idx[k]>>32; e = s + ((uint32_t)int_idx[k]); assert(e > s + 1);//the length is at least 2 - for (i = s; i < e; i++) ridx[int_a[i]>>1]++; - } - - for (k = l = 0; k < ng->n; k++) { - m = ridx[k]; - ridx[k] = l; ridx[k] <<= 32; ridx[k] |= m; - l += m; - } - - for (k = 0; k < ng->n; k++) { - a = b64->a + (ridx[k]>>32); a_n = (uint32_t)ridx[k]; - if(a_n) a[a_n-1] = 0; - } - - for (k = 0; k < int_idx_n; k++) { - s = int_idx[k]>>32; e = s + ((uint32_t)int_idx[k]); assert(e > s + 1);//the length is at least 2 - for (i = s; i < e; i++) { - v = int_a[i]>>1; - a = b64->a + (ridx[v]>>32); - a_n = (uint32_t)ridx[v]; - if(a_n) { - if(a[a_n-1] == a_n-1) { - a[a_n-1] = (k<<32)|i; - } else { - a[a[a_n-1]++] = (k<<32)|i; - } - } - } - } -} - -void gen_sub_integer_path(uint64_t *int_a, int64_t s, int64_t e, int64_t it, uint64_t v, asg64_v *res) -{ - int64_t k; res->n = 0; assert((int_a[it]>>1) == (v>>1)); - if(int_a[it] == v) {///forward - kv_resize(uint64_t, *res, (uint64_t)(e - it)); - for (k = it; k < e; k++) res->a[res->n++] = int_a[k]; - } else {//reverse - kv_resize(uint64_t, *res, (uint64_t)(it - s)); - for (k = it; k >= s; k--) res->a[res->n++] = int_a[k]^1; - } -} - -void prt_sub_integer_path(asg64_v *res, uint64_t it, uint64_t w0, uint64_t w1, uint64_t z_n, uint64_t z) -{ - uint64_t k; - fprintf(stderr, "(it::%lu) res->n::%u, w0::%lu, w1::%lu, z_n::%lu, z::%lu\n", it, (uint32_t)res->n, - w0, w1, z_n, z); - for (k = 0; k < res->n; k++) { - fprintf(stderr, "(it::%lu) utg%.6dl,", it, (int32_t)(res->a[k]>>1)+1); - } - fprintf(stderr, "\n"); -} - -uint64_t is_best_path(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t *int_a, -uint64_t s, uint64_t e, uint64_t it, uint64_t v, uint64_t *ridx_a, uint64_t *ridx, -asg64_v *b0, asg64_v *b1, double cutoff) -{ - uint64_t *arc_a, arc_n, k, is, ie, z, zn, w0, w1, min_w0, min_w1, alt_n = 0, is_contain = 1; - gen_sub_integer_path(int_a, s, e, it, v, b0); - - arc_a = ridx_a + (ridx[v>>1]>>32); - arc_n = (uint32_t)ridx[v>>1]; - - - // uint64_t is_debug = 0; - // if((((v>>1) == 2736) && (v&1))/** && (b0->n > 1 && (b0->a[b0->n-1]>>1) == 34944)**/) { - // // is_debug = 1; - // fprintf(stderr, "[M::%s::] utg%.6dl(%c)\n", __func__, - // (int32_t)(v>>1)+1, "+-"[v&1]); - // prt_sub_integer_path(b0, it, (uint64_t)-1, (uint64_t)-1, (uint64_t)-1, (uint64_t)-1); - // } - - - for (k = 0, min_w0 = min_w1 = (uint64_t)-1, is_contain = 1; k < arc_n; k++) { - if(it == ((uint32_t)arc_a[k])) continue; - is = int_idx[arc_a[k]>>32]>>32; alt_n++; - ie = is + ((uint32_t)(int_idx[arc_a[k]>>32])); - gen_sub_integer_path(int_a, is, ie, ((uint32_t)arc_a[k]), v, b1); - zn = MIN(b0->n, b1->n); - for (z = 0; z < zn && b0->a[z] == b1->a[z]; z++); ///z: first raw unitig that is different between two paths - assert(z > 0); w0 = w1 = (uint64_t)-1; - if(z < b0->n) get_integer_seq_ovlps(uidx, b0->a, b0->n, z - 1, 0, NULL, &w0); - else return 0;///b0 is contained - if(z < b1->n) get_integer_seq_ovlps(uidx, b1->a, b1->n, z - 1, 0, NULL, &w1); - else continue;///b1 is contained - // if(((v>>1) == 2736) && (v&1)) { - // prt_sub_integer_path(b0, it, w0, w1, zn, z); - // prt_sub_integer_path(b1, it, w0, w1, zn, z); - // } - if(w0 == (uint64_t)-1) w0 = 0; - if(w1 == (uint64_t)-1) w1 = 0; - if((w0 <= w1) || (w1 > (w0*cutoff))) return 0; - // if(b0->n == zn) return 0;///b0 is shorter - // if(b1->n == zn) continue;///b1 is shorter - if((min_w0 == (uint64_t)-1) || (z == zn) || (min_w0 > w0) || (min_w0 == w0 && min_w1 < w1)) { - min_w0 = w0; min_w1 = w1; - } - is_contain = 0; - } - - // if(((v>>1) == 2736) && (v&1)) { - // fprintf(stderr, "[M::%s::] min_w0::%lu, min_w1::%lu\n\n", __func__, min_w0, min_w1); - // } - // fprintf(stderr, "[M::%s::] utg%.6dl(%c)->utg%.6dl(%c)\n", __func__, - // (int32_t)(v>>1)+1, "+-"[v&1], (int32_t)(int_a[k]>>1)+1, "+-"[int_a[k]&1]); - if(alt_n == 0) return 1; - if(is_contain) return 1; - - if(min_w0 == (uint64_t)-1) min_w0 = 0; - if(min_w1 == (uint64_t)-1) min_w1 = 0; - if((min_w0 > min_w1) && (min_w1 <= (min_w0*cutoff))) return 1; - return 0; -} - - -void get_best_path(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t *int_a, -uint8_t *f, uint64_t s, uint64_t e, asg64_v *b0, asg64_v *b1, uint64_t *ridx_a, -uint64_t *ridx, asg64_v *res) -{ - uint64_t pi, v, k, res_n = res->n, *pz; - b0->n = b1->n = 0; - for (k = s, pi = (uint64_t)-1; k < e; k++) { - v = int_a[k]; - if((!f[v])&&(!f[v^1])) continue; - if((pi != (uint64_t)-1) && (f[v^1])) { - // if(((v>>1) == 2736)) { - // fprintf(stderr, "+[M::%s::ii[%lu, %lu)] utg%.6dl(%c), f[v^1]::%u, v^1::%lu, putg%.6dl(%c), f[pv]::%u, pv::%lu\n", - // __func__, s, e, (int32_t)(int_a[k]>>1)+1, "+-"[int_a[k]&1], f[v^1], v^1, - // (int32_t)(int_a[pi]>>1)+1, "+-"[int_a[pi]&1], f[int_a[pi]], int_a[pi]); - // } - if(is_best_path(uidx, ng, int_idx, int_a, s, e, k, v^1, ridx_a, ridx, b0, b1, 0.51)) { - // if(((v>>1) == 2736)) { - // fprintf(stderr, "-[M::%s::ii[%lu, %lu)] utg%.6dl(%c), f[v^1]::%u, v^1::%lu, putg%.6dl(%c), f[pv]::%u, pv::%lu\n", - // __func__, s, e, (int32_t)(int_a[k]>>1)+1, "+-"[int_a[k]&1], f[v^1], v^1, - // (int32_t)(int_a[pi]>>1)+1, "+-"[int_a[pi]&1], f[int_a[pi]], int_a[pi]); - // } - // fprintf(stderr, "[M::%s::] utg%.6dl(%c)->utg%.6dl(%c)\n", __func__, - // (int32_t)(int_a[pi]>>1)+1, "+-"[int_a[pi]&1], (int32_t)(int_a[k]>>1)+1, "+-"[int_a[k]&1]); - pz = (res->n > res_n)? &(res->a[res->n-1]):(NULL); - if((!pz) || (((*pz)>>32) != pi)) {//keep the shortest pi<->k - kv_pushp(uint64_t, *res, &pz); - *pz = pi; (*pz) <<= 32; (*pz) |= k; - } - } else { - pi = (uint64_t)-1; - } - } - if(f[v]) { - // fprintf(stderr, "-[M::%s::] utg%.6dl(%c), f[v]::%u, v::%lu\n", - // __func__, (int32_t)(int_a[k]>>1)+1, "+-"[int_a[k]&1], f[v], v); - if(is_best_path(uidx, ng, int_idx, int_a, s, e, k, v, ridx_a, ridx, b0, b1, 0.51)) { - pi = k;//keep the shortest pi<->k - } else { - pi = (uint64_t)-1; - } - } - } -} - - -uint64_t gen_sub_integer_path_ff(uint64_t *int_a, int64_t s, int64_t e, int64_t it, uint64_t v, uint8_t *f, asg64_v *res) -{ - int64_t k; res->n = 0; assert((int_a[it]>>1) == (v>>1)); - if(int_a[it] == v) {///forward - kv_resize(uint64_t, *res, (uint64_t)(e - it)); - for (k = it; k < e; k++) { - res->a[res->n++] = int_a[k]; - if(res->n > 1 && f[res->a[res->n-1]^1]) return res->n; - } - } else {//reverse - kv_resize(uint64_t, *res, (uint64_t)(it - s)); - for (k = it; k >= s; k--) { - res->a[res->n++] = int_a[k]^1; - if(res->n > 1 && f[res->a[res->n-1]^1]) return res->n; - } - } - res->n = 0; return 0; -} - -uint64_t is_best_pair(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t *int_a, -uint64_t s, uint64_t e, uint64_t it, uint64_t v, uint64_t *ridx_a, uint64_t *ridx, -asg64_v *b0, asg64_v *b1, uint8_t *f, double cutoff) -{ - uint64_t *arc_a, arc_n, k, is, ie, w0 = 0, w1 = 0, sup_cut = 3; - if(!gen_sub_integer_path_ff(int_a, s, e, it, v, f, b0)) return 0; - assert(b0->n >= 2); assert(f[b0->a[0]] && f[b0->a[b0->n-1]^1]); - w0 = get_arc_support_chain(uidx, b0->a, b0->n, ng); - if(w0 < sup_cut) return 0; - - arc_a = ridx_a + (ridx[v>>1]>>32); - arc_n = (uint32_t)ridx[v>>1]; - for (k = 0; k < arc_n; k++) { - if(it == ((uint32_t)arc_a[k])) continue; - is = int_idx[arc_a[k]>>32]>>32; - ie = is + ((uint32_t)(int_idx[arc_a[k]>>32])); - if(!gen_sub_integer_path_ff(int_a, is, ie, ((uint32_t)arc_a[k]), v, f, b1)) continue; - assert(b1->n >= 2); assert(f[b1->a[0]] && f[b1->a[b1->n-1]^1]); - if((b0->n == b1->n) && (memcmp(b0->a, b1->a, sizeof((*(b0->a)))*b0->n) == 0)) { - if(it < ((uint32_t)arc_a[k])) continue; - else return 0;///only keep 1 equal interval - } - w1 = get_arc_support_chain(uidx, b1->a, b1->n, ng); - // fprintf(stderr, "[M::%s::] w0::%lu, w1::%lu\n", __func__, w0, w1); - if((w0 <= w1) || (w1 > (w0*cutoff))) return 0; - } - return 1; -} - -void get_best_pair(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t *int_a, -uint8_t *f, uint64_t s, uint64_t e, asg64_v *b0, asg64_v *b1, uint64_t *ridx_a, -uint64_t *ridx, asg64_v *res) -{ - uint64_t pi, v, k, *pz; - b0->n = b1->n = 0; - for (k = s, pi = (uint64_t)-1; k < e; k++) { - v = int_a[k]; - if((f[v^1])) { - if(pi != (uint64_t)-1) { - if(is_best_pair(uidx, ng, int_idx, int_a, s, e, k, v^1, ridx_a, ridx, b0, b1, f, 0.51)) { - kv_pushp(uint64_t, *res, &pz); - *pz = pi; (*pz) <<= 32; (*pz) |= k; - } - } - pi = (uint64_t)-1; - } - if(f[v]) { - pi = (uint64_t)-1; - if(is_best_pair(uidx, ng, int_idx, int_a, s, e, k, v, ridx_a, ridx, b0, b1, f, 0.51)) { - pi = k;//keep the shortest pi<->k - } - } - } -} - -static void worker_ul_aln_path(void *data, long i, int tid) // callback for kt_for() -{ - unique_bridge_check_t *u_aux = (unique_bridge_check_t*)data; - ul_resolve_t *uidx = u_aux->uidx; - integer_t *buf = &(uidx->str_b.buf[tid]); - uint64_t s, e; - // uint64_t *x = &(uidx->uovl.iug_tra->a[i]); - // asg_arc_t *ve = &(uidx->uovl.i_ug->g->arc[*x]); - - asg64_v b_v, b_r, res; - b_v.a = buf->u.a; b_v.n = buf->u.n; b_v.m = buf->u.m; - b_r.a = buf->o.a; b_r.n = buf->o.n; b_r.m = buf->o.m; - res.a = buf->res_dump.a; res.n = buf->res_dump.n; res.m = buf->res_dump.m; - - b_v.n = b_r.n = 0; - s = u_aux->int_idx[i]>>32; ///the i-th integer contig/path - e = s + ((uint32_t)(u_aux->int_idx[i])); - assert(e > s + 1);//the length is at least 2 - - get_best_path(uidx, u_aux->ng, u_aux->int_idx, u_aux->int_a, u_aux->f, s, e, &b_v, &b_r, u_aux->ridx_a, u_aux->ridx, &res); - // get_ul_arc_supports(uidx, ve, &b_v, &b_r, 1, &w_v, &w_r); - - buf->u.a = b_v.a; buf->u.n = b_v.n; buf->u.m = b_v.m; - buf->o.a = b_r.a; buf->o.n = b_r.n; buf->o.m = b_r.m; - buf->res_dump.a = res.a; buf->res_dump.n = res.n; buf->res_dump.m = res.m; -} - -static void worker_ul_aln_pair(void *data, long i, int tid) // callback for kt_for() -{ - unique_bridge_check_t *u_aux = (unique_bridge_check_t*)data; - ul_resolve_t *uidx = u_aux->uidx; - integer_t *buf = &(uidx->str_b.buf[tid]); - uint64_t s, e; - // uint64_t *x = &(uidx->uovl.iug_tra->a[i]); - // asg_arc_t *ve = &(uidx->uovl.i_ug->g->arc[*x]); - - asg64_v b_v, b_r, res; - b_v.a = buf->u.a; b_v.n = buf->u.n; b_v.m = buf->u.m; - b_r.a = buf->o.a; b_r.n = buf->o.n; b_r.m = buf->o.m; - res.a = buf->res_dump.a; res.n = buf->res_dump.n; res.m = buf->res_dump.m; - - b_v.n = b_r.n = 0; - s = u_aux->int_idx[i]>>32; ///the i-th integer contig/path - e = s + ((uint32_t)(u_aux->int_idx[i])); - assert(e > s + 1);//the length is at least 2 - - get_best_pair(uidx, u_aux->ng, u_aux->int_idx, u_aux->int_a, u_aux->f, s, e, &b_v, &b_r, u_aux->ridx_a, u_aux->ridx, &res); - // get_ul_arc_supports(uidx, ve, &b_v, &b_r, 1, &w_v, &w_r); - - buf->u.a = b_v.a; buf->u.n = b_v.n; buf->u.m = b_v.m; - buf->o.a = b_r.a; buf->o.n = b_r.n; buf->o.m = b_r.m; - buf->res_dump.a = res.a; buf->res_dump.n = res.n; buf->res_dump.m = res.m; -} - -uint32_t ug_ext_0(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t int_idx_n, uint64_t *int_a, uint32_t max_ext, -uint8_t *ff, uint32_t *ng_occ, uint64_t *i_idx, asg64_v *b64, asg64_v *ub64, uint64_t a_n) -{ - uint32_t n_vtx = ng->n<<1, k, i; uint64_t *pz; - uint64_t s, e, n_clus; - memset(ff, 0, sizeof((*ff))*n_vtx); - // memset(ng_occ, 0, sizeof((*ng_occ))*n_vtx); - memset(i_idx, 0, sizeof((*i_idx))*n_vtx); - ub64->n = 0; - - for (i = 0; i < a_n; i++) { ///available intervals - s = b64->a[i]>>32; e = (uint32_t)b64->a[i]; assert(e > s);///[s, e] -> coordinates within int_a[] - assert(!(b64->a[i]&((uint64_t)0x8000000000000000))); - // fprintf(stderr, "\n[M::%s::] occ::%lu\n", __func__, e - s); - // for (k = s; k <= e; k++) { - // // fprintf(stderr, "utg%.6dl(%c),", (int32_t)(int_a[k]>>1)+1, "+-"[int_a[k]&1]); - // fprintf(stderr, "utg%.6dl,", (int32_t)(int_a[k]>>1)+1); - // } - // fprintf(stderr, "\n"); - - for (k = s + 1; k < e; k++) {///note: here is [s, e]; s && e are unique, but [s+1, e-1] are not unique - kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[k]]++; - (*pz) = int_a[k]; (*pz) <<= 32; (*pz) |= i;///(raw unitig/non-unqiue node id)|(integer contig id) - - kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[k]^1]++; - (*pz) = int_a[k]^1; (*pz) <<= 32; (*pz) |= i; - } - kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[s]]++; - (*pz) = int_a[s]; (*pz) <<= 32; (*pz) |= i; - - kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[e]^1]++; - (*pz) = int_a[e]^1; (*pz) <<= 32; (*pz) |= i; - } - // prt_thread_info(b64.a, a_n, NULL, 0, "tt2"); - // fprintf(stderr, "**1**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); - ///index - radix_sort_srt64(b64->a + a_n, b64->a + b64->n);///(raw unitig node id)|(integer contig id) - for (k = a_n + 1, i = a_n; k <= b64->n; k++) { - if(k == b64->n || (b64->a[k]>>32) != (b64->a[i]>>32)) { - i_idx[b64->a[i]>>32] |= (((uint64_t)i)<<32)|((uint64_t)k);///b64.a[i]>>32 appear once (unique ends)/multipe times - i = k; - } - } - - n_clus = usg_unique_arcs_cluster_adv(b64, a_n, i_idx, int_a, ub64); - // fprintf(stderr, "**3**[M::%s::] a_n::%lu, n_clus::%lu\n", __func__, a_n, n_clus); - // prt_thread_info(b64.a, a_n, NULL, 0, "tt4"); - assert(b64->n == (a_n<<1)); - - // new_path_ext(uidx, ng, &b64, &ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext);//wrong - return old_path_ext(uidx, ng, b64, ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext); -} - -void debug_prt_renew_aln(usg_t *ng, uint64_t *int_idx, uint64_t int_idx_n, uint64_t *int_a, uint64_t int_an, asg64_v *b64, uint64_t *ridx) -{ - uint64_t k, s, e, i; - for (i = 0; i < int_idx_n; i++) {///scan all integer contigs - s = int_idx[i]>>32; e = s + ((uint32_t)int_idx[i]); assert(e > s + 1);//the length is at least 2 - fprintf(stderr, "\n[M::%s::] occ::%lu\n", __func__, e - s); - for (k = s; k <= e; k++) { - // fprintf(stderr, "utg%.6dl(%c),", (int32_t)(int_a[k]>>1)+1, "+-"[int_a[k]&1]); - fprintf(stderr, "utg%.6dl,", (int32_t)(int_a[k]>>1)+1); - } - fprintf(stderr, "\n"); - } -} - -uint32_t ug_ext_free(asg64_v *ob, asg64_v *ub, ul_resolve_t *uidx, usg_t *ng, uint32_t max_ext, -uint8_t **ff, uint32_t **ng_occ, uint64_t **i_idx, asg64_v *b64, asg64_v *ub64, uint32_t rocc_cut, -uint32_t thread_path) -{ - // fprintf(stderr, "[M::%s::] rocc_cut::%u\n", __func__, rocc_cut); - uint32_t k, n_vtx = ng->n<<1, a_n; unique_bridge_check_t u_aux; - REALLOC((*ff), n_vtx); REALLOC((*ng_occ), n_vtx); REALLOC((*i_idx), n_vtx); - renew_usg_t_bub(uidx, ng, *ng_occ, *ff, rocc_cut); - u2g_hybrid_aln(uidx, ng, ob, ub); - gen_hybrid_aln_idx(ng, ub->a, ub->n, ob->a, ob->n, b64, *i_idx); - // if(rocc_cut == 10) - // { - // fprintf(stderr, "\n[M::%s::] rocc_cut::%u\n", __func__, rocc_cut); - // debug_prt_renew_aln(ng, ub->a, ub->n, ob->a, ob->n, b64, *i_idx); - // } - - u_aux.f = *ff; u_aux.ng = ng; u_aux.int_idx = ub->a; u_aux.int_idx_n = ub->n; u_aux.uidx = uidx; - u_aux.int_a = ob->a; u_aux.int_an = ob->n; u_aux.ridx_a = b64->a; u_aux.ridx = *i_idx; - for (k = 0; k < uidx->str_b.n_thread; k++) { - uidx->str_b.buf[k].res_dump.n = uidx->str_b.buf[k].u.n = uidx->str_b.buf[k].o.n = 0; - } - - if(thread_path) { - kt_for(uidx->str_b.n_thread, worker_ul_aln_path, &u_aux, u_aux.int_idx_n); - } else { - kt_for(uidx->str_b.n_thread, worker_ul_aln_pair, &u_aux, u_aux.int_idx_n); - } - - for (k = b64->n = a_n = 0; k < uidx->str_b.n_thread; k++) { - a_n += uidx->str_b.buf[k].res_dump.n; - kv_resize(uint64_t, *b64, a_n); - memcpy(b64->a+b64->n, uidx->str_b.buf[k].res_dump.a, uidx->str_b.buf[k].res_dump.n*(sizeof(*(b64->a)))); - b64->n = a_n; - } - radix_sort_srt64(b64->a, b64->a + b64->n);///keeps the coordinates within int_a[] - // fprintf(stderr, "[M::%s::] a_n::%u, int_idx_n::%u, int_n::%u\n", - // __func__, a_n, (uint32_t)ub->n, (uint32_t)ob->n); - a_n = ug_ext_0(uidx, ng, ub->a, ub->n, ob->a, max_ext, *ff, *ng_occ, *i_idx, b64, ub64, a_n); - // if(a_n) usg_cleanup(ng); - return a_n; -} - -uint32_t ug_ext_strict(asg64_v *ob, asg64_v *ub, ul_resolve_t *uidx, usg_t *ng, uint32_t max_ext, -uint8_t **ff, uint32_t **ng_occ, uint64_t **i_idx, asg64_v *b64, asg64_v *ub64) -{ - // fprintf(stderr, "[M::%s::]\n", __func__); - uint32_t k, i, n_vtx = ng->n<<1, a_n; - REALLOC((*ff), n_vtx); REALLOC((*ng_occ), n_vtx); REALLOC((*i_idx), n_vtx); - u2g_hybrid_aln(uidx, ng, ob, ub); b64->n = ub64->n = 0; - uint64_t *int_idx = ub->a, int_idx_n = ub->n, *int_a = ob->a; - uint64_t *r_a, r_n, zs, ze, s, e, pi, v, *pz; - - memset((*ng_occ), 0, sizeof((*(*ng_occ)))*n_vtx); - for (k = 0; k < int_idx_n; k++) {///scan all integer contigs - r_a = int_a + (int_idx[k]>>32); r_n = (uint32_t)int_idx[k]; - assert(r_n >= 2); - for (i = 1; i + 1 < r_n; i++) { - (*ng_occ)[r_a[i]]++; (*ng_occ)[r_a[i]^1]++; - } - (*ng_occ)[r_a[0]]++; (*ng_occ)[r_a[r_n-1]^1]++; - } - - ma_ug_t *un_g = ma_ug_hybrid_gen(ng); - int32_t ui, un; ma_utg_t *u = NULL; - for (k = 0; k < un_g->u.n; k++) {///all unitigs of raw utg - u = &(un_g->u.a[k]); - zs = ze = (uint32_t)-1; un = u->n; - for (ui = 0; ui < un; ui++) { - if(occ_m((*ng_occ)[(u->a[ui]>>32)^1]) == 1) { - zs = ui; break; - } - } - - for (ui = ((int32_t)un)-1; ui >= 0; ui--) { - if(occ_m((*ng_occ)[u->a[ui]>>32]) == 1) { - ze = ui; break; - } - } - if(zs != (uint32_t)-1 && ze != (uint32_t)-1 && zs > ze) continue; - if(zs != (uint32_t)-1) (*ng_occ)[(u->a[zs]>>32)^1] |= ((uint32_t)0x80000000); - if(ze != (uint32_t)-1) (*ng_occ)[(u->a[ze]>>32)] |= ((uint32_t)0x80000000); - } - ma_ug_destroy(un_g); - - // fprintf(stderr, ">>>>>>[M::%s::] int_idx[0]::%lu, int_idx[1]::%lu\n", __func__, int_idx[0], int_idx[1]); - // prt_intg_info(int_idx, int_idx_n, int_a, "intg"); - for (i = b64->n = a_n = 0; i < int_idx_n; i++) {///scan all integer contigs - s = int_idx[i]>>32; e = s + ((uint32_t)int_idx[i]); - assert(e > s + 1);//the length is at least 2 - for (k = s, pi = (uint64_t)-1; k < e; k++) { - v = int_a[k]; - if((!((*ng_occ)[v]&((uint32_t)0x80000000)))&&(!((*ng_occ)[v^1]&((uint32_t)0x80000000)))) { - continue;///it must be a unique node - } - if((pi != (uint64_t)-1) && ((*ng_occ)[v^1]&((uint32_t)0x80000000))) { - pz = (b64->n>0)? &(b64->a[b64->n-1]):(NULL); - if((!pz) || (((*pz)>>32) != pi)) {//keep the shortest pi<->k - kv_pushp(uint64_t, *b64, &pz); - *pz = pi; (*pz) <<= 32; (*pz) |= k; - a_n++; - } - } - if((*ng_occ)[v]&((uint32_t)0x80000000)) pi = k;//keep the shortest pi<->k - } - } - // prt_thread_info(b64.a, a_n+ua_n, NULL, 0, "tt_minus"); - // fprintf(stderr, "**0**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); - radix_sort_srt64(b64->a, b64->a + b64->n);///keeps the coordinates within int_a[] - - a_n = ug_ext_0(uidx, ng, ub->a, ub->n, ob->a, max_ext, *ff, *ng_occ, *i_idx, b64, ub64, a_n); - // if(a_n) usg_cleanup(ng); - return a_n; -} - -typedef struct { - uint32_t nid, ulid; - uint32_t raw_sid, raw_eid; - uint32_t raw_sof, raw_eof; -} usc_t; - -typedef struct { - usc_t *a; - size_t n, m; -} usc_vec_t; - -typedef struct { - // ul_resolve_t *uidx; - usc_t *a; - uint64_t a_n; - ma_ug_t *ug; -} scaf_mul_t; - - - -#define B4Lg(x) (((x)>>2)+(((x)&3)?1:0)) -uint32_t load_scaf_base(all_ul_t *x, char* file_name, const char *bin_file) -{ - char *gfa_name = (char*)malloc(strlen(file_name)+50); - sprintf(gfa_name, "%s.%s.uidx.ucr.bin", file_name, bin_file); - // fprintf(stderr, "[M::%s] open %s...\n", __func__, gfa_name); - FILE *fp = fopen(gfa_name, "r"); free(gfa_name); - if (!fp) return 0; - // fprintf(stderr, "[M::%s] open sucess\n", __func__); - uint64_t rid; uint32_t len; ul_vec_t ss, *z; memset(&ss, 0, sizeof(ss)); - while(1) { - fread(&rid, sizeof(rid), 1, fp); - if(feof(fp)) break; - z = &(x->a[rid]); - fread(&len, sizeof(len), 1, fp); assert(z->rlen == len); - fread(&(ss.N_site.n), sizeof(ss.N_site.n), 1, fp); - kv_resize(uint32_t, ss.N_site, ss.N_site.n); - fread(ss.N_site.a, sizeof((*(ss.N_site.a))), ss.N_site.n, fp); - ss.r_base.n = B4Lg(len); kv_resize(uint8_t, ss.r_base, ss.r_base.n); - fread(ss.r_base.a, sizeof((*(ss.r_base.a))), ss.r_base.n, fp); - // if(rid == 37238) { - // fprintf(stderr, "[M::%s::37238] z->dd::%u\n", __func__, z->dd); - // } - // fprintf(stderr, "[M::%s::rid->%lu] z->dd::%u\n", __func__, rid, z->dd); - if(z->dd != 4) continue; - - - kv_resize(uint32_t, z->N_site, ss.N_site.n); z->N_site.n = ss.N_site.n; - memcpy(z->N_site.a, ss.N_site.a, sizeof((*(z->N_site.a)))*z->N_site.n); - - kv_resize(uint8_t, z->r_base, ss.r_base.n); z->r_base.n = ss.r_base.n; - memcpy(z->r_base.a, ss.r_base.a, sizeof((*(z->r_base.a)))*z->r_base.n); - } - // load_compress_base_disk(fp, &rid, des.a, &ulen, &(sl->ucr_s->u)); - - fclose(fp); free(ss.N_site.a); free(ss.r_base.a); - return 1; -} - - -uint64_t reset_scaf_node_uinfo_srt_t(usc_t *z, int64_t min_arc_len, int64_t scaf_len, int64_t *nlen) -{ - (*nlen) = scaf_len + (min_arc_len<<1); - if(z->ulid == ((uint32_t)-1)) return 0;///a scaffold node - if(z->raw_eof + min_arc_len <= z->raw_sof) {///has an overlap longer than min_arc_len; - return 1;///a scaffold node; no need this node, could directly use existing nodes - } - int64_t s, e; - s = z->raw_sof; e = z->raw_eof; - (*nlen) = (min_arc_len<<1) + (e - s); ///(e - s)>=(-min_arc_len) - return 2; -} - - -void get_end_hifi(char *des, uint32_t v, All_reads* rdb, uint32_t len, uint32_t is_beg) -{ - uint32_t rlen = Get_READ_LENGTH((*rdb), (v>>1)); - assert(rlen >= len); - recover_UC_Read_sub_region(des, ((is_beg)?(rlen-len):(0)), len, v&1, rdb, v>>1); -} - -void get_ul_subregion(all_ul_t *x, char *des, uint32_t id, uint32_t rev, int64_t ssp, int64_t sep, uint32_t reset_Ns) -{ - ul_vec_t *z = &(x->a[id]); - int64_t sl, slr, offset, begLen, tailLen, a_n, src_i, des_i, i; - sl = sep - ssp; - offset = ssp&3; begLen = 4-offset; - if(begLen > sl) begLen = sl; - tailLen = (sl-begLen)&3; - a_n = (sl - begLen - tailLen)>>2; - - // fprintf(stderr, "[M::%s] z->r_base.n::%u, begLen::%ld, tailLen::%ld, a_n::%ld\n", - // __func__, (uint32_t)z->r_base.n, begLen, tailLen, a_n); - src_i = ssp; i = 0; des_i = 0; - if(begLen > 0) { - // fprintf(stderr, "[M::%s] des_i::%ld, src_i>>2::%ld\n", __func__, des_i, src_i>>2); - memcpy(des+des_i, bit_t_seq_table[z->r_base.a[src_i>>2]]+offset, begLen); - des_i += begLen; src_i += begLen; - } - - for (i = 0; i < a_n; i++) { - // fprintf(stderr, "[M::%s] des_i::%ld, src_i>>2::%ld\n", __func__, des_i, src_i>>2); - memcpy(des+des_i, bit_t_seq_table[z->r_base.a[src_i>>2]], 4); - des_i += 4; src_i += 4; - } - - if(tailLen > 0) { - // fprintf(stderr, "[M::%s] des_i::%ld, src_i>>2::%ld\n", __func__, des_i, src_i>>2); - memcpy(des+des_i, bit_t_seq_table[z->r_base.a[src_i>>2]], tailLen); - des_i += tailLen; src_i += tailLen; - } - - uint64_t k, sk = ssp, ek = sep; - for (k = 0; k < z->N_site.n; k++) { - if(z->N_site.a[k] >= sk && z->N_site.a[k] < ek){ - des[z->N_site.a[k]-sk] = 'N'; - } else if(z->N_site.a[k] >= ek) { - break; - } - } - - if(reset_Ns) { - for (i = 0; i < sl; i++) { - if (seq_nt4_table[(uint8_t)des[i]] >= 4) des[i] = 'A'; - } - } - - if(rev) { - char t; slr = sl>>1; - for (i = 0; i < slr; i++) { - t = des[sl-i-1]; - des[sl-i-1] = RC_CHAR(des[i]); - des[i] = RC_CHAR(t); - } - if(sl&1) des[i] = RC_CHAR(des[i]); - } -} - -int64_t push_scaf_bases(uint8_t *des, uint64_t** N_site, All_reads* rdb, all_ul_t *x, usc_t *z, int64_t min_arc_len, int64_t scaf_len, int64_t nlen, UC_Read *tu, -uint64_t *rmap, ma_ug_t *raw_g) -{ - int64_t nlen0, ff, Nocc, i; char *da = NULL; - ff = reset_scaf_node_uinfo_srt_t(z, min_arc_len, scaf_len, &nlen0); assert(nlen0 == nlen); - if(ff == 1) {///has an overlap longer than min_arc_len between z->raw_sid and z->raw_eid - memset(des, 0, sizeof((*(des)))*(nlen/4+1)); - return ff; - } - uint32_t uv, uw, sv, sw; int64_t s, e, ul; - uv = z->raw_sid; uw = z->raw_eid; - - sv = (uv&1?((raw_g->u.a[uv>>1].a[0]>>32)^1):(raw_g->u.a[uv>>1].a[raw_g->u.a[uv>>1].n-1]>>32)); - sw = (uw&1?((raw_g->u.a[uw>>1].a[raw_g->u.a[uw>>1].n-1]>>32)^1):(raw_g->u.a[uw>>1].a[0]>>32)); - resize_UC_Read(tu, nlen); da = tu->seq; - assert((Get_READ_LENGTH((*rdb), (sv>>1))) > ((uint32_t)min_arc_len)); - assert((Get_READ_LENGTH((*rdb), (sw>>1))) > ((uint32_t)min_arc_len)); - ///need introduce some UL bases; - ///or the overlap length between sv and sw is shorter than min_arc_len - if(ff == 2) { - s = z->raw_sof; e = z->raw_eof; ul = e - s; - assert(ul>=(-min_arc_len)); - // assert((Get_READ_LENGTH((*rdb), (sv>>1))) > ul); - // assert((Get_READ_LENGTH((*rdb), (sw>>1))) > ul); - get_end_hifi(da, sv, rdb, min_arc_len, 1); - get_end_hifi(da+min_arc_len+ul, sw, rdb, min_arc_len, 0); - if(ul > 0) {///need UL - // fprintf(stderr, "[M::%s] ulid::%u(%c), s::%ld, e::%ld, nlen::%ld, min_arc_len::%ld\n", __func__, - // z->ulid>>1, "+-"[z->ulid&1], s, e, nlen, min_arc_len); - get_ul_subregion(x, da+min_arc_len, z->ulid>>1, z->ulid&1, s, e, 1); - } - } else {///no UL found; ff = 0 - get_end_hifi(da, sv, rdb, min_arc_len, 1); - memset(da+min_arc_len, 'A', scaf_len); - get_end_hifi(da+min_arc_len+scaf_len, sw, rdb, min_arc_len, 0); - } - for (i = Nocc = 0; i < nlen; i++) { - if(seq_nt6_table[(uint8_t)da[i]] >= 4) Nocc++; - } - ha_compress_base(des, da, nlen, N_site, Nocc); - return ff; -} - -void realloc_rdb_adv(All_reads* rdb, all_ul_t *x, ma_sub_t **cov, R_to_U *ruI, uint64_t *rmap, -uint64_t rid_n, uint64_t scaf_len, char *scaf_id, asg_t *ng, ug_opt_t *uopt, ma_ug_t *raw_g, usc_t *a) -{ - uint64_t i, rid_n0 = rdb->total_reads, tname, cname; usc_t *z; - uint64_t scaf_id_len = strlen(scaf_id); char *des, *src; int64_t nlen, ff; - UC_Read g_read; init_UC_Read(&g_read); - rdb->total_reads = rid_n; - tname = rdb->name_index[rid_n0]; - fprintf(stderr, "+[M::%s] rid_n0::%lu, rid_n::%lu\n", __func__, rid_n0, rid_n); - ///for read bases - REALLOC(rdb->N_site, rdb->total_reads); - REALLOC(rdb->read_length, rdb->total_reads); - REALLOC(rdb->read_size, rdb->total_reads); - REALLOC(rdb->read_sperate, rdb->total_reads); - REALLOC(rdb->trio_flag, rdb->total_reads); - REALLOC(rdb->name_index, rdb->total_reads+1);///total_reads+1 - REALLOC((*cov), rdb->total_reads); - if(uopt->te) { - assert(uopt->te->n == rid_n0); - uopt->te->n = rdb->total_reads; - REALLOC(uopt->te->hh, rdb->total_reads); - } - for (i = rid_n0; i < rdb->total_reads; i++) { - // fprintf(stderr, "[M::%s] i::%lu\n", __func__, i); - rdb->N_site[i] = NULL; - rdb->trio_flag[i] = AMBIGU; - (*cov)[i].c = (*cov)[i].del = 0; - // rdb->read_length[i] = scaf_len; - // rdb->read_size[i] = scaf_len; - // (*cov)[i].s = 0; (*cov)[i].e = scaf_len; - // cname = scaf_id_len; - if(rmap[i] != ((uint64_t)-1)) {///not a scaffold node - if(rdb->N_site[rmap[i]] != NULL) { - MALLOC(rdb->N_site[i], rdb->N_site[rmap[i]][0]+1); - memcpy(rdb->N_site[i], rdb->N_site[rmap[i]], - sizeof((*(rdb->N_site[i])))*(rdb->N_site[rmap[i]][0]+1)); - } - rdb->read_length[i] = rdb->read_length[rmap[i]]; - rdb->read_size[i] = rdb->read_length[rmap[i]]; - (*cov)[i].s = (*cov)[rmap[i]].s; - (*cov)[i].e = (*cov)[rmap[i]].e; - rdb->trio_flag[i] = rdb->trio_flag[rmap[i]]; - (*cov)[i] = (*cov)[rmap[i]]; - cname = Get_NAME_LENGTH((*rdb), (rmap[i])); - if(uopt->te) uopt->te->hh[i] = uopt->te->hh[rmap[i]]; - } else { - z = &(a[(i-ng->r_seq)]); assert(z->nid == i); cname = scaf_id_len; - if(reset_scaf_node_uinfo_srt_t(z, uopt->min_ovlp, scaf_len, &nlen) == 2) { - cname = UL_INF.nid.a[z->ulid>>1].n;///ul name length - } - rdb->read_length[i] = nlen; - rdb->read_size[i] = nlen; - (*cov)[i].s = 0; (*cov)[i].e = nlen; - ng->seq[i].len = nlen;///update length for the scaffold node - if(uopt->te) uopt->te->hh[i] = 0; - } - rdb->name_index[i] = tname; tname += cname; - rdb->total_reads_bases += rdb->read_length[i]; - - MALLOC(rdb->read_sperate[i], (rdb->read_length[i]/4+1)); - if(rmap[i] != ((uint64_t)-1)) {///not a scaffold node - memcpy(rdb->read_sperate[i], rdb->read_sperate[rmap[i]], - sizeof((*(rdb->read_sperate[i])))*(rdb->read_length[i]/4+1)); - } else { - ///set to A - z = &(a[(i-ng->r_seq)]); assert(z->nid == i); - ff = push_scaf_bases(rdb->read_sperate[i], &(rdb->N_site[i]), rdb, x, z, uopt->min_ovlp, scaf_len, rdb->read_length[i], &g_read, rmap, raw_g); - if(ff == 1) ng->seq[i].del = 1;///could directly reuse HiFi; no need new node - // memset(rdb->read_sperate[i], 0, sizeof((*(rdb->read_sperate[i])))*(rdb->read_length[i]/4+1)); - } - ng->seq[i].len = rdb->read_length[i]; - } - - rdb->index_size = rdb->total_reads; - rdb->name_index[i] = tname; - rdb->total_name_length = tname; - rdb->name_index_size = rdb->total_reads+1; - REALLOC(rdb->name, tname); - for (i = rid_n0; i < rdb->total_reads; i++) {///only need to update names for new reads - des = Get_NAME((*rdb), i); - if(rmap[i] != ((uint64_t)-1)) { - src = Get_NAME((*rdb), rmap[i]); cname = Get_NAME_LENGTH((*rdb), (rmap[i])); - } else { - z = &(a[(i-ng->r_seq)]); assert(z->nid == i); - if(reset_scaf_node_uinfo_srt_t(z, uopt->min_ovlp, scaf_len, &nlen) == 2) { - cname = UL_INF.nid.a[z->ulid>>1].n;///ul name length - src = UL_INF.nid.a[z->ulid>>1].a; - } else { - src = scaf_id; cname = scaf_id_len; - } - // assert(nlen == (int64_t)cname); - } - memcpy(des, src, sizeof((*(des)))*cname); - } - - REALLOC(rdb->paf, rdb->total_reads); - memset(rdb->paf+rid_n0, 0, (rdb->total_reads-rid_n0)*sizeof((*rdb->paf))); - REALLOC(rdb->reverse_paf, rdb->total_reads); - memset(rdb->reverse_paf+rid_n0, 0, (rdb->total_reads-rid_n0)*sizeof((*rdb->reverse_paf))); - - ruI->len = rdb->total_reads; - REALLOC(ruI->index, ruI->len); - memset(ruI->index, -1, sizeof((*(ruI->index)))*(ruI->len)); - - reset_bub_label_t(uopt->b_mask_t, ng, 0, 0); - uopt->coverage_cut = (*cov); - uopt->reverse_sources = rdb->reverse_paf; - uopt->sources = rdb->paf; - destory_UC_Read(&g_read); - fprintf(stderr, "-[M::%s] rid_n0::%lu, rid_n::%lu\n", __func__, rid_n0, rid_n); -} - - -int64_t reload_uovl(all_ul_t *x, char* file_name) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(file_name)+100); - sprintf(gfa_name, "%s.%s.ul.ovlp.bin", file_name, "re"); - FILE* fp = fopen(gfa_name, "r"); free(gfa_name); - if (!fp) return 0; - uint64_t k; size_t kn; ul_vec_t *p = NULL; - - ///skip test ug - size_t tt, i; uint32_t t; ma_utg_t ua; - fread(&tt, sizeof(tt), 1, fp); - for (i = 0; i < tt; i++) { - fread(&t, sizeof(t), 1, fp); - fread(&t, sizeof(t), 1, fp); - fread(&(ua.start), sizeof(ua.start), 1, fp); - fread(&(ua.end), sizeof(ua.end), 1, fp); - fread(&(ua.n), sizeof(ua.n), 1, fp); - fseek(fp, sizeof(uint64_t)*ua.n, SEEK_CUR); - // fread(ua.a, sizeof(uint64_t), ua.n, fp); - } - - - - fseek(fp, sizeof(x->nid.n), SEEK_CUR); - for (k = 0; k < x->nid.n; k++) { - fseek(fp, sizeof(x->nid.a[k].n), SEEK_CUR); - fseek(fp, sizeof((*(x->nid.a[k].a)))*x->nid.a[k].n, SEEK_CUR); - } - - // free(x->ridx.idx.a); x->ridx.idx.a = NULL; - fread(&kn, sizeof(kn), 1, fp); - fseek(fp, sizeof((*(x->ridx.idx.a)))*kn, SEEK_CUR); - - // free(x->ridx.occ.a); x->ridx.occ.a = NULL; - fread(&kn, sizeof(kn), 1, fp); - fseek(fp, sizeof((*(x->ridx.occ.a)))*kn, SEEK_CUR); - - fread(&x->n, sizeof(x->n), 1, fp); assert(x->nid.n == x->n); - if(x->n > x->m) kv_resize(ul_vec_t, *x, x->n); - fprintf(stderr, "[M::%s] x->n::%u, x->nid.n::%u\n", __func__, (uint32_t)x->n, (uint32_t)x->nid.n); - for (k = 0; k < x->n; k++) { - p = &(x->a[k]); - fread(&p->dd, sizeof(p->dd), 1, fp); - fread(&p->rlen, sizeof(p->rlen), 1, fp); - - fread(&p->r_base.n, sizeof(p->r_base.n), 1, fp); - if(p->r_base.n > p->r_base.m) kv_resize(uint8_t, p->r_base, p->r_base.n); - fread(p->r_base.a, sizeof((*(p->r_base.a))), p->r_base.n, fp); - - fread(&p->bb.n, sizeof(p->bb.n), 1, fp); - if(p->bb.n > p->bb.m) kv_resize(uc_block_t, p->bb, p->bb.n); - fread(p->bb.a, sizeof((*(p->bb.a))), p->bb.n, fp); - - fread(&p->N_site.n, sizeof(p->N_site.n), 1, fp); - if(p->N_site.n > p->N_site.m) kv_resize(uint32_t, p->N_site, p->N_site.n); - fread(p->N_site.a, sizeof((*(p->N_site.a))), p->N_site.n, fp); - } - fclose(fp); - return 1; -} - -static void gen_scaffold_id(void *data, long i, int tid) // callback for kt_for() -{ - scaf_mul_t *ss = (scaf_mul_t *)data; - ma_ug_t *ug = ss->ug; - usc_t *z = &(ss->a[i]); - uint32_t v = z->raw_sid, w = z->raw_eid, sv, sw; - uint64_t *a, a_n, k; int64_t ql, mmql, max_ql; - uc_block_t *p, *n, *m0, *m1; - sv = (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)); - sw = (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)); - // if((((v>>1) == 15016) && ((w>>1) == 2778)) || (((v>>1) == 2778) && ((w>>1) == 15016))) { - // fprintf(stderr, "[M::%s::]\t%.*s(%c)(sv>>1::%u)(utg%.6ul(%c))\t%.*s(%c)(sw>>1::%u)(utg%.6ul(%c))\n", __func__, - // (int)Get_NAME_LENGTH(R_INF, (sv>>1)), Get_NAME(R_INF, (sv>>1)), "+-"[sv&1], sv>>1, (v>>1)+1, "+-"[v&1], - // (int)Get_NAME_LENGTH(R_INF, (sw>>1)), Get_NAME(R_INF, (sw>>1)), "+-"[sw&1], sw>>1, (w>>1)+1, "+-"[w&1]); - // } - sv = Get_READ_LENGTH(R_INF, (sv>>1)); sw = Get_READ_LENGTH(R_INF, (sw>>1)); - max_ql = MIN(sv, sw); max_ql = -max_ql; - // if((((v>>1) == 235) && ((w>>1) == 153)) || (((v>>1) == 153) && ((w>>1) == 235))) { - // fprintf(stderr, "[M::%s] sv::%u, sw::%u, max_ql::%ld, v>>1::%u(%c), w>>1::%u(%c)\n", - // __func__, sv, sw, max_ql, v>>1, "+-"[v&1], w>>1, "+-"[w&1]); - // } - // if((((v>>1) == 235) && ((w>>1) == 153)) || (((v>>1) == 153) && ((w>>1) == 235))) { - // print_ul_alignment(ug, &UL_INF, 5625, "+++"); - // } - uint32_t uv, uw, rev = 0, id = (uint32_t)-1; - p = n = m0 = m1 = NULL; - a = UL_INF.ridx.occ.a + UL_INF.ridx.idx.a[v>>1]; - a_n = UL_INF.ridx.idx.a[(v>>1)+1] - UL_INF.ridx.idx.a[v>>1]; - for (k = 0, mmql = INT32_MAX; k < a_n; k++) { - p = &(UL_INF.a[a[k]>>32].bb.a[(uint32_t)(a[k])]); assert(p->hid == (v>>1)); - if(UL_INF.a[a[k]>>32].dd != 3) continue;///dd = 3 is saved - if(p->base || (!p->el) || (!p->pchain)) continue; - uv = (((uint32_t)(p->hid))<<1)|((uint32_t)(p->rev)); - - // if((uv == v) && (p->aidx != (uint32_t)-1)) { - if((uv == v) && (p->aidx == (uint32_t)-1) && (((uint32_t)(a[k]))+1 < UL_INF.a[a[k]>>32].bb.n)) { - n = &(UL_INF.a[a[k]>>32].bb.a[((uint32_t)(a[k]))+1]); - if(n->base || (!n->el) || (!n->pchain) || (n->pidx != (uint32_t)-1)) continue; - uw = (((uint32_t)(n->hid))<<1)|((uint32_t)(n->rev)); - if(uw == w) { - // if((((v>>1) == 15016) && ((w>>1) == 2778)) || (((v>>1) == 2778) && ((w>>1) == 15016))) { - // fprintf(stderr, "+[M::%s] ul_id::%lu, qs::%u, qe::%u\n", __func__, a[k]>>32, n->qs, n->qe); - // // print_ul_alignment(ug, &UL_INF, a[k]>>32, "+++"); - // } - ql = ((int64_t)n->qs) - ((int64_t)p->qe); - if(ql > max_ql && n->qe > p->qe && n->qs > p->qs) { - if(ql < mmql) { - mmql = ql; rev = 0; m0 = p; m1 = n; id = a[k]>>32; - } - } - } - } - - // if(((uv^1) == v) && (p->pidx != (uint32_t)-1)) { - if(((uv^1) == v) && (p->pidx == (uint32_t)-1) && (((uint32_t)(a[k])) > 0)) { - n = &(UL_INF.a[a[k]>>32].bb.a[((uint32_t)(a[k]))-1]); - if(n->base || (!n->el) || (!n->pchain) || (n->aidx != (uint32_t)-1)) continue; - uw = (((uint32_t)(n->hid))<<1)|((uint32_t)(n->rev)); uw ^= 1; - if(uw == w) { - // if((((v>>1) == 15016) && ((w>>1) == 2778)) || (((v>>1) == 2778) && ((w>>1) == 15016))) { - // fprintf(stderr, "-[M::%s] ul_id::%lu, qs::%u, qe::%u\n", __func__, a[k]>>32, n->qs, n->qe); - // // print_ul_alignment(ug, &UL_INF, a[k]>>32, "+++"); - // } - ql = ((int64_t)p->qs) - ((int64_t)n->qe); - if(ql > max_ql && n->qe < p->qe && n->qs < p->qs) { - if(ql < mmql) { - mmql = ql; rev = 1; m0 = n; m1 = p; id = a[k]>>32; - } - } - } - } - } - - if(m0 && m1 && id != ((uint32_t)-1)) { - z->ulid = (id<<1)|rev; - z->raw_sof = m0->qe; - z->raw_eof = m1->qs; - // if((((v>>1) == 15016) && ((w>>1) == 2778)) || (((v>>1) == 2778) && ((w>>1) == 15016))) { - // fprintf(stderr, "[M::%s] id::%u, v>>1::%u(%c), w>>1::%u(%c), raw_sof::%u, raw_eof::%u\n", - // __func__, id, v>>1, "+-"[v&1], w>>1, "+-"[w&1], z->raw_sof, z->raw_eof); - // } - } -} - -void reload_uu(all_ul_t *x, ma_ug_t *raw_g, char* file_name, const char *bin_file) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(asm_opt.output_file_name)+50); - sprintf(gfa_name, "%s.%s", asm_opt.output_file_name, bin_file); - clear_all_ul_t(x); - load_all_ul_t(x, gfa_name, &R_INF, raw_g); - // filter_ul_ug(raw_g);//no filter since we would like to use all alignments - gen_ul_vec_rid_t(x, NULL, raw_g); - free(gfa_name); -} - -void fill_scaffolds(usc_t *a, uint64_t a_n, ma_ug_t *raw_g, int64_t min_arc_len, const char *bin_file) -{ - scaf_mul_t ss; uint32_t k, occ = 0; - reload_uu(&UL_INF, raw_g, asm_opt.output_file_name, bin_file); - // reload_uovl(&UL_INF, asm_opt.output_file_name); - // filter_ul_ug(raw_g); - // free(UL_INF.ridx.idx.a); UL_INF.ridx.idx.n = UL_INF.ridx.idx.m = 0; - // free(UL_INF.ridx.occ.a); UL_INF.ridx.occ.n = UL_INF.ridx.occ.m = 0; - // gen_ul_vec_rid_t(&UL_INF, NULL, raw_g); - ss.a = a; ss.a_n = a_n; ss.ug = raw_g; - kt_for(asm_opt.thread_num, gen_scaffold_id, &ss, a_n); - for (k = 0; k < a_n; k++) { - if(a[k].ulid == ((uint32_t)-1)) continue; - // if(a[k].raw_eof + min_arc_len <= a[k].raw_sof) {///has an overlap longer than min_arc_len; - if(a[k].raw_eof <= a[k].raw_sof) { - continue;///no need ul, could directly use hifi - } - // if(a[k].raw_eof <= a[k].raw_sof) continue;///no need UL reads - // fprintf(stderr, "[M::%s] ulid::%u(%c), dd::%u\n", - // __func__, a[k].ulid>>1, "+-"[a[k].ulid&1], UL_INF.a[a[k].ulid>>1].dd); - UL_INF.a[a[k].ulid>>1].dd = 4;///load - occ++; - } - - // fprintf(stderr, "[M::%s] occ::%u\n", __func__, occ); - if(occ) load_scaf_base(&UL_INF, asm_opt.output_file_name, bin_file); -} - -void update_paf(ma_hit_t_alloc *src, ma_hit_t_alloc *r_src, uint64_t *rmap, uint64_t rid_n, uint64_t pre_gn, asg_t *ng); -void push_scaff_node(ma_hit_t_alloc *src, uint64_t v, uint64_t w, uint64_t ol, asg_t *ng); - -ma_ug_t *convert_usg_t(usg_t *ng, ma_ug_t *ref) -{ - ma_ug_t *ug = NULL; uint32_t k, nv, z; usg_arc_t *av; asg_arc_t *p; - ma_utg_t *des, *src; - CALLOC(ug, 1); ug->g = asg_init(); - ug->u.n = ug->u.m = ng->n; CALLOC(ug->u.a, ug->u.n); - for (k = 0; k < ng->n; k++) { - asg_seq_set(ug->g, k, ng->a[k].len, ng->a[k].del); - ug->g->seq[k].c = ref->g->seq[ng->a[k].mm].c; - - av = usg_arc_a(ng, (k<<1)); nv = usg_arc_n(ng, (k<<1)); - for (z = 0; z < nv; z++) { - if(av[z].del) continue; - p = asg_arc_pushp(ug->g); memset(p, 0, sizeof((*p))); - p->ul = av[z].ul; p->v = av[z].v; p->ol = av[z].ol; p->del = av[z].del; - } - - av = usg_arc_a(ng, (k<<1)+1); nv = usg_arc_n(ng, (k<<1)+1); - for (z = 0; z < nv; z++) { - if(av[z].del) continue; - p = asg_arc_pushp(ug->g); memset(p, 0, sizeof((*p))); - p->ul = av[z].ul; p->v = av[z].v; p->ol = av[z].ol; p->del = av[z].del; - } - - des = &(ug->u.a[k]); src = &(ref->u.a[ng->a[k].mm]); - (*des) = (*src); des->a = NULL; des->s = NULL; - if(src->a) { - MALLOC(des->a, des->m); - memcpy(des->a, src->a, src->n*sizeof((*(src->a)))); - } - - if(src->s) { - MALLOC(des->s, des->len); - memcpy(des->s, src->s, src->len*sizeof((*(src->s)))); - } - } - - asg_cleanup(ug->g); - return ug; -} - -int32_t gen_spec_rc_edge(asg_t *rg, ug_opt_t *uopt, uint32_t v, uint32_t w, asg_arc_t *t, ma_hit_t **te) -{ - uint32_t k, qn, tn; int32_t r; ma_hit_t_alloc *s = &(uopt->reverse_sources[v>>1]); asg_arc_t p; - for (k = 0; k < s->length; k++) { - qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); - if(tn != (w>>1)) continue; - r = ma_hit2arc(&(s->buffer[k]), rg->seq[qn].len, rg->seq[tn].len, uopt->max_hang, asm_opt.max_hang_rate, uopt->min_ovlp, &p); - if(r < 0) continue; - if((p.ul>>32) != v || p.v != w) continue; - *t = p; t->ou = 0; if(te) (*te) = &(s->buffer[k]); - return 1; - } - return -1; -} - -void push_direct_scaff_node(usc_t *psa, asg_t *ng, ug_opt_t *uopt, uint64_t vx, uint64_t wx) -{ - uint64_t uol, dif; int32_t r; asg_arc_t t, *p; ma_hit_t *rc0, *rc1; - uol = psa->raw_sof - psa->raw_eof; - assert(uol >= (uint64_t)uopt->min_ovlp); - r = gen_spec_rc_edge(ng, uopt, vx, wx, &t, &rc0); - if(r >= 0) { - if(uol > t.ol) dif = uol - t.ol; - else dif = t.ol - uol; - if((dif > (uol*0.05)) || (dif > (t.ol*0.05))) { - if(dif > 16) r = -1; - } - } - if(r >= 0) { - r = gen_spec_rc_edge(ng, uopt, wx^1, vx^1, &t, &rc1); - if(uol > t.ol) dif = uol - t.ol; - else dif = t.ol - uol; - if((dif > (uol*0.05)) || (dif > (t.ol*0.05))) { - if(dif > 16) r = -1; - } - } - - if(r >= 0) { - r = gen_spec_rc_edge(ng, uopt, vx, wx, &t, &rc0); assert(r >= 0); - p = asg_arc_pushp(ng); *p = t; - - r = gen_spec_rc_edge(ng, uopt, wx^1, vx^1, &t, &rc1); assert(r >= 0); - p = asg_arc_pushp(ng); *p = t; - - add_ma_hit_t_alloc(&(R_INF.paf[Get_qn((*rc0))]), rc0); - add_ma_hit_t_alloc(&(R_INF.paf[Get_qn((*rc1))]), rc1); - } else { - push_scaff_node(R_INF.paf, vx, wx, psa->raw_sof-psa->raw_eof, ng); - - r = gen_spec_edge(ng, uopt, vx, wx, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, wx^1, vx^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - } -} - -void print_debug_scaffold_nodes(ug_opt_t *uopt, usc_t *a, uint32_t a_n, asg_t *ng) -{ - uint32_t i, k, z, qn, tn, rl, hrl; usc_t *psa = NULL; ma_hit_t_alloc *s = NULL; - UC_Read r0, r1; init_UC_Read(&r0); init_UC_Read(&r1); - fprintf(stderr, "[M::%s] a_n::%u\n", __func__, a_n); - for (i = 0; i < a_n; i++) { - psa = &(a[i]); - s = &(uopt->sources[psa->nid]); - fprintf(stderr, "[M::%s::%u]%.*s(id::%u)\tlen::%lu\tulid::%u\trev::%u\tdel::%u\n", - __func__, i, (int32_t)Get_NAME_LENGTH(R_INF, psa->nid), - Get_NAME(R_INF, psa->nid), psa->nid, Get_READ_LENGTH(R_INF, psa->nid), psa->ulid>>1, psa->ulid&1, - ng->seq[psa->nid].del); - - recover_UC_Read(&r0, &R_INF, psa->nid); - fprintf(stderr, "%.*s\n", (int32_t)Get_READ_LENGTH(R_INF, psa->nid), r0.seq); - - for (k = 0; k < s->length; k++) { - qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); assert(qn == psa->nid); - fprintf(stderr, "q::[%u, %u)\t%c\tt::[%u, %u)\t%.*s(id::%u)\tlen::%lu\n", - Get_qs(s->buffer[k]), Get_qe(s->buffer[k]), "+-"[s->buffer[k].rev], - Get_ts(s->buffer[k]), Get_te(s->buffer[k]), - (int32_t)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, Get_READ_LENGTH(R_INF, tn)); - if(psa->raw_eof >= psa->raw_sof) { - resize_UC_Read(&r0, Get_qe(s->buffer[k])-Get_qs(s->buffer[k])); - recover_UC_Read_sub_region(r0.seq, Get_qs(s->buffer[k]), Get_qe(s->buffer[k])-Get_qs(s->buffer[k]), 0, &R_INF, qn); - - resize_UC_Read(&r1, Get_te(s->buffer[k])-Get_ts(s->buffer[k])); - recover_UC_Read_sub_region(r1.seq, Get_ts(s->buffer[k]), Get_te(s->buffer[k])-Get_ts(s->buffer[k]), 0, &R_INF, tn); - - assert(Get_te(s->buffer[k])-Get_ts(s->buffer[k]) == Get_qe(s->buffer[k])-Get_qs(s->buffer[k])); - rl = Get_te(s->buffer[k])-Get_ts(s->buffer[k]); - if(s->buffer[k].rev) { - char t; hrl = rl>>1; - for (z = 0; z < hrl; z++) { - t = r1.seq[rl-z-1]; - r1.seq[rl-z-1] = RC_CHAR(r1.seq[z]); - r1.seq[z] = RC_CHAR(t); - } - if(rl&1) r1.seq[z] = RC_CHAR(r1.seq[z]); - } - assert(memcmp(r0.seq, r1.seq, rl) == 0); - } - } - } - destory_UC_Read(&r0); destory_UC_Read(&r1); -} - -asg_t *renew_ng(usg_t *eg, ma_ug_t *rug, asg_t *sg, ug_opt_t *uopt, ma_sub_t **cov, R_to_U *ruI, uint64_t scaffold_len, const char *bin_file) -{ - init_aux_table(); - ma_utg_t *u; uint64_t i, v, w, m, h, z, raw_v, raw_w, nocc, nv, vx, wx; int32_t r; - asg_arc_t t, *p; usg_arc_t *av = NULL; usc_t *psa; ma_ug_t *ug1 = NULL; - asg_ext_t ext; memset(&ext, 0, sizeof(ext)); ext.ext = asg_init(); asg_t *ng = ext.ext; - usc_vec_t sa; memset(&sa, 0, sizeof(sa)); - ext.a_n = sg->n_seq; - ext.cnt.n = ext.cnt.m = ext.a_n; - CALLOC(ext.cnt.a, ext.cnt.n);///count - - ext.idx_a.n = ext.idx_a.m = sg->n_seq; - MALLOC(ext.idx_a.a, ext.idx_a.n); - memset(ext.idx_a.a, -1, sizeof(*(ext.idx_a.a))*ext.idx_a.n);//map - ug1 = convert_usg_t(eg, rug); - - // fprintf(stderr, "-0-[M::%s]\n", __func__); - // print_vw_edge(sg, 681356, 73351, __func__); - // prt_spec_edge(sg, R_INF.paf, R_INF.total_reads, 681356, 73351, uopt, "src"); - // // prt_spec_edge(sg, R_INF.reverse_paf, R_INF.total_reads, 681356, 73351, uopt, "rsrc"); - - for (i = 0; i < ug1->u.n; ++i) { - if(ug1->g->seq[i].del) continue; - u = &(ug1->u.a[i]); - for (m = 0; m < u->n; m++) { - v = u->a[m]>>32; - ext.cnt.a[v>>1]++; - if(ext.cnt.a[v>>1] == 1) { - h = v>>1; ext.idx_a.a[h] = v>>1; - } else { - h = ext.idx_a.n; - kv_push(uint64_t, ext.idx_a, (v>>1)); - } - - z = (h<<1)|(v&1); z <<= 32; z |= ((uint32_t)u->a[m]); - u->a[m] = z; - } - } - - for (i = 0; i < sg->n_seq; ++i) { - asg_seq_set(ng, i, sg->seq[i].len, ext.idx_a.a[i]==((uint64_t)-1)?1:0); - ng->seq[i].c = 0; - if(ext.idx_a.a[i]!=((uint64_t)-1)) assert(ext.idx_a.a[i] == i); - ext.idx_a.a[i] = i;///set for the deleted read - } - for (; i < ext.idx_a.n; i++) { - asg_seq_set(ng, i, sg->seq[ext.idx_a.a[i]].len, 0); - ng->seq[i].c = 0; assert(!(ng->seq[ext.idx_a.a[i]].del)); - } - ng->r_seq = ng->n_seq; - assert(ng->n_seq == ext.idx_a.n); - - - for (i = 0, nocc = ng->r_seq, sa.n = 0; i < eg->n; ++i) { - if(ug1->g->seq[i].del) continue; - ///there shouldn't any scaffolding within the nodes - v = i<<1; nv = usg_arc_n(eg, v); av = usg_arc_a(eg, v); - for (m = 0; m < nv; m++) { - if(av[m].del || eg->a[av[m].v>>1].del) continue; - w = av[m].v; - vx = (v&1?((ug1->u.a[v>>1].a[0]>>32)^1):(ug1->u.a[v>>1].a[ug1->u.a[v>>1].n-1]>>32)); - wx = (w&1?((ug1->u.a[w>>1].a[ug1->u.a[w>>1].n-1]>>32)^1):(ug1->u.a[w>>1].a[0]>>32)); - raw_v = (ext.idx_a.a[vx>>1]<<1)|(vx&1); - raw_w = (ext.idx_a.a[wx>>1]<<1)|(wx&1); - assert((raw_v>>1) < sg->n_seq); - assert((raw_w>>1) < sg->n_seq); - if(vx > wx) continue; - if((vx == wx) && (vx&1)) continue; - if(gen_spec_edge(sg, uopt, raw_v, raw_w, &t) < 0) { - asg_seq_set(ng, nocc, 0, 0);///this is a scaffold node - ng->seq[nocc].c = 0; - kv_push(uint64_t, ext.idx_a, ((uint64_t)-1)); - - kv_pushp(usc_t, sa, &psa); - psa->ulid = (uint32_t)-1; psa->nid = nocc; - psa->raw_sid = (eg->a[v>>1].mm<<1)|(v&1);///raw unitig id - psa->raw_eid = (eg->a[w>>1].mm<<1)|(w&1);///raw unitig id - psa->raw_sof = psa->raw_eof = (uint32_t)-1; - nocc++;///a scaffold node - } - } - - v = (i<<1)+1; nv = usg_arc_n(eg, v); av = usg_arc_a(eg, v); - for (m = 0; m < nv; m++) { - if(av[m].del || eg->a[av[m].v>>1].del) continue; - w = av[m].v; - vx = (v&1?((ug1->u.a[v>>1].a[0]>>32)^1):(ug1->u.a[v>>1].a[ug1->u.a[v>>1].n-1]>>32)); - wx = (w&1?((ug1->u.a[w>>1].a[ug1->u.a[w>>1].n-1]>>32)^1):(ug1->u.a[w>>1].a[0]>>32)); - raw_v = (ext.idx_a.a[vx>>1]<<1)|(vx&1); - raw_w = (ext.idx_a.a[wx>>1]<<1)|(wx&1); - assert((raw_v>>1) < sg->n_seq); - assert((raw_w>>1) < sg->n_seq); - if(vx > wx) continue; - if((vx == wx) && (vx&1)) continue; - if(gen_spec_edge(sg, uopt, raw_v, raw_w, &t) < 0) { - asg_seq_set(ng, nocc, 0, 0);///this is a scaffold node - ng->seq[nocc].c = 0; - kv_push(uint64_t, ext.idx_a, ((uint64_t)-1)); - - kv_pushp(usc_t, sa, &psa); - psa->ulid = (uint32_t)-1; psa->nid = nocc; - psa->raw_sid = (eg->a[v>>1].mm<<1)|(v&1);///raw unitig id - psa->raw_eid = (eg->a[w>>1].mm<<1)|(w&1);///raw unitig id - psa->raw_sof = psa->raw_eof = (uint32_t)-1; - nocc++;///a scaffold node - } - } - } - - assert(ng->n_seq == ext.idx_a.n); - CALLOC(ng->seq_vis, (ng->n_seq<<1)); - ///# scaffolding nodes - if(sa.n > 0) fill_scaffolds(sa.a, sa.n, rug, uopt->min_ovlp, bin_file); - realloc_rdb_adv(&(R_INF), &UL_INF, cov, ruI, ext.idx_a.a, ext.idx_a.n, scaffold_len, (char *)"scaf", ng, uopt, rug, sa.a); - update_paf(R_INF.paf, R_INF.reverse_paf, ext.idx_a.a, ext.idx_a.n, sg->n_seq, ng); - - for (i = 0, nocc = ng->r_seq; i < eg->n; ++i) { - if(ug1->g->seq[i].del) continue; - u = &(ug1->u.a[i]); - for (m = 1; m < u->n; m++) { - // fprintf(stderr, "[M::%s] i::%lu, m::%lu\n", __func__, i, m); - v = u->a[m-1]>>32; w = u->a[m]>>32; - r = gen_spec_edge(ng, uopt, v, w, &t); - ///there shouldn't any scaffolding within the nodes - assert(r >= 0); - p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, w^1, v^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - } - - v = i<<1; nv = usg_arc_n(eg, v); av = usg_arc_a(eg, v); - for (m = 0; m < nv; m++) { - if(av[m].del || eg->a[av[m].v>>1].del) continue; - w = av[m].v; - vx = (v&1?((ug1->u.a[v>>1].a[0]>>32)^1):(ug1->u.a[v>>1].a[ug1->u.a[v>>1].n-1]>>32)); - wx = (w&1?((ug1->u.a[w>>1].a[ug1->u.a[w>>1].n-1]>>32)^1):(ug1->u.a[w>>1].a[0]>>32)); - if(vx > wx) continue; - if((vx == wx) && (vx&1)) continue;///it is possible - - r = gen_spec_edge(ng, uopt, vx, wx, &t); - if(r >= 0) { - p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, wx^1, vx^1, &t); - // if(!(r >= 0)) { - // fprintf(stderr, "[M::%s]\tvx>>1::%lu(%c)\twx>>1::%lu(%c)\n", - // __func__, vx>>1, "+-"[vx&1], wx>>1, "+-"[wx&1]); - // fprintf(stderr, "[M::%s]\t%.*s(%c)->%.*s(%c)\n", - // __func__, (int)Get_NAME_LENGTH(R_INF, (vx>>1)), Get_NAME(R_INF, (vx>>1)), "+-"[vx&1], - // (int)Get_NAME_LENGTH(R_INF, (wx>>1)), Get_NAME(R_INF, (wx>>1)), "+-"[wx&1]); - // } - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - } else { - psa = &(sa.a[nocc-ng->r_seq]); z = nocc<<1; - assert(psa->nid == nocc); - assert(psa->raw_sid == ((eg->a[v>>1].mm<<1)|(v&1))); - assert(psa->raw_eid == ((eg->a[w>>1].mm<<1)|(w&1))); - if(ng->seq[nocc].del) {///direct link vx and wx - push_direct_scaff_node(psa, ng, uopt, vx, wx); - } else { - push_scaff_node(R_INF.paf, vx, z, uopt->min_ovlp, ng); - push_scaff_node(R_INF.paf, z, wx, uopt->min_ovlp, ng); - - r = gen_spec_edge(ng, uopt, vx, z, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, z^1, vx^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - - r = gen_spec_edge(ng, uopt, z, wx, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, wx^1, z^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - } - nocc++; - } - } - - v = (i<<1)+1; nv = usg_arc_n(eg, v); av = usg_arc_a(eg, v); - for (m = 0; m < nv; m++) { - if(av[m].del || eg->a[av[m].v>>1].del) continue; - w = av[m].v; - vx = (v&1?((ug1->u.a[v>>1].a[0]>>32)^1):(ug1->u.a[v>>1].a[ug1->u.a[v>>1].n-1]>>32)); - wx = (w&1?((ug1->u.a[w>>1].a[ug1->u.a[w>>1].n-1]>>32)^1):(ug1->u.a[w>>1].a[0]>>32)); - if(vx > wx) continue; - if((vx == wx) && (vx&1)) continue;///it is possible - - r = gen_spec_edge(ng, uopt, vx, wx, &t); - if(r >= 0) { - p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, wx^1, vx^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - } else { - psa = &(sa.a[nocc-ng->r_seq]); z = nocc<<1; - assert(psa->nid == nocc); - assert(psa->raw_sid == ((eg->a[v>>1].mm<<1)|(v&1))); - assert(psa->raw_eid == ((eg->a[w>>1].mm<<1)|(w&1))); - if(ng->seq[nocc].del) {///direct link vx and wx - push_direct_scaff_node(psa, ng, uopt, vx, wx); - } else { - push_scaff_node(R_INF.paf, vx, z, uopt->min_ovlp, ng); - push_scaff_node(R_INF.paf, z, wx, uopt->min_ovlp, ng); - - r = gen_spec_edge(ng, uopt, vx, z, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, z^1, vx^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - - r = gen_spec_edge(ng, uopt, z, wx, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, wx^1, z^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - } - nocc++; - } - } - } - - asg_cleanup(ng); ng->r_seq = ng->n_seq; - free(ext.cnt.a); free(ext.idx_a.a); free(sa.a); ma_ug_destroy(ug1); - - fprintf(stderr, "[M::%s] nocc::%lu, ng->n_seq::%u, sg->n_seq::%u\n", - __func__, nocc, (uint32_t)ng->n_seq, (uint32_t)sg->n_seq); - assert(nocc == ng->n_seq); - return ng; -} - -void u2g_hybrid_detan_iter(ul_resolve_t *uidx, usg_t *ng, uint32_t max_ext, uint32_t clean_round, asg64_v *in, asg64_v *ib) -{ - uint32_t n_vtx = ng->n<<1, ncut = 0, k; - uint8_t *ff; CALLOC(ff, n_vtx); - uint32_t *ng_occ; CALLOC(ng_occ, n_vtx); - uint64_t *i_idx; CALLOC(i_idx, n_vtx); - asg64_v b64, ub64; kv_init(b64); kv_init(ub64); - asg64_v tx = {0,0,0}, tb = {0,0,0}, *ob = NULL, *ub = NULL; - ob = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); ob->n = ub->n = 0; - // fprintf(stderr, "\n[M::%s::] asm_opt.is_low_het_ul::%u, max_ext::%u\n", - // __func__, asm_opt.is_low_het_ul, max_ext); - // prt_usg_t(uidx, ng, "ng0"); - for (k = 0; k < clean_round; k++) { - ncut += ug_ext_strict(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64); - // if(asm_opt.is_low_het_ul) break; - ncut += ug_ext_free(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64, 48, 1); - // prt_usg_t(uidx, ng, "ng_python"); - ncut += ug_ext_free(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64, 16, 1); - - ncut += ug_ext_free(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64, 0, 0); - ///renew bubble for ug_ext_strict - n_vtx = ng->n<<1; - REALLOC(ff, n_vtx); REALLOC(ng_occ, n_vtx); REALLOC(i_idx, n_vtx); - renew_usg_t_bub(uidx, ng, ng_occ, ff, 0); - } - // // ug_ext_strict(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64); - // ncut += ug_ext_free(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64, 50); - // prt_usg_t(uidx, ng, "ng.db"); - // ncut += ug_ext_free(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64, 10); - // ncut += ug_ext_strict(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64); - // prt_usg_t(uidx, ng, "ng.db"); - if(ncut) { - usg_cleanup(ng); - // if((max_ext>>1) > 0) usg_arc_cut_tips(ng, (max_ext>>1), 1, ub); - usg_arc_cut_tips(ng, max_ext, 1, ub); - - // if(ng->n > 139131) { - // fprintf(stderr, ">[M::%s::] ng->a[139131].del::%u\n", __func__, - // ng->a[139131].del); - // } - } - // prt_usg_t(uidx, ng, "ng2"); - // u2g_hybrid_aln(uidx, ng, ob, ub); - // if(ug_ext(uidx, ng, ub->a, ub->n, ob->a, max_ext, ff, ng_occ, i_idx, &b64, &ub64)) { - // // debug_sysm_usg_t(ng, __func__); - // usg_cleanup(ng); - // // debug_sysm_usg_t(ng, __func__); - // } - - // prt_usg_t(uidx, ng, "ng0"); - // if(ug_ext_free(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64, 50)) { - // usg_cleanup(ng); - // } - // prt_usg_t(uidx, ng, "ng1"); - - if(!in) free(tx.a); if(!ib) free(tb.a); - free(ng_occ); free(i_idx); free(ff); kv_destroy(b64); kv_destroy(ub64); -} - - -/** - -void u2g_hybrid_detan(ul_resolve_t *uidx, usg_t *ng, uint32_t max_ext, asg64_v *in, asg64_v *ib) -{ - uint64_t k, i, x, m, *tmp, sn; asg64_v tx = {0,0,0}, tb = {0,0,0}, *ob = NULL, *ub = NULL; - ob = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); ob->n = ub->n = 0; - - for (k = 0; k < uidx->str_b.n_thread; k++) { - uidx->str_b.buf[k].res_dump.n = uidx->str_b.buf[k].u.n = uidx->str_b.buf[k].o.n = 0; - } - kt_for(uidx->str_b.n_thread, worker_integer_realign_g, uidx, uidx->uovl.i_ug->u.n); - - for (k = ob->n = ub->n = m = 0; k < uidx->str_b.n_thread; k++) { - for (i = 0; i < uidx->str_b.buf[k].res_dump.n; i++) { - x = uidx->str_b.buf[k].res_dump.a[i]; - kv_push(uint64_t, *ob, x);//aln details - if(x&((uint64_t)0x8000000000000000)) { - x -= ((uint64_t)0x8000000000000000); x >>= 32; x <<= 32;//seq_id - x |= ob->n;//offset - kv_push(uint64_t, *ub, x);///idx:: seq_id|offset_in_ob - } else { - m++; - } - } - } - - radix_sort_srt64(ub->a, ub->a + ub->n); - kv_resize(uint64_t, *ub, ub->n+m); tmp = ub->a + ub->n; m = 0; - for (k = 0; k < ub->n; k++) { - sn = ((uint32_t)(ob->a[((uint32_t)ub->a[k])-1])); - memcpy(tmp + m, ob->a + ((uint32_t)ub->a[k]), sn*sizeof((*tmp))); - ub->a[k] = m; ub->a[k] <<= 32; ub->a[k] |= sn;//offset_in_ob|occ - m += sn; - } - assert(m <= ob->n); - memcpy(ob->a, tmp, m*sizeof((*tmp))); ob->n = m; - - debug_sysm_usg_t(ng, __func__); - // prt_usg_t(uidx, ng, "ng4"); - if(gen_unique_g_adv(uidx, ng, ub->a, ub->n, ob->a, max_ext)) { - // usg_arc_t *z = get_usg_arc(ng, 2, 576), *q = get_usg_arc(ng, 577, 3); - // fprintf(stderr, "xxxx0xxx[M::%s::] p->del::%u, q->del::%u\n", - // __func__, z?z->del:1, q?q->del:1); - ///debug - debug_sysm_usg_t(ng, __func__); - // z = get_usg_arc(ng, 2, 576); q = get_usg_arc(ng, 577, 3); - // fprintf(stderr, "xxxx1xxx[M::%s::] p->del::%u, q->del::%u\n", - // __func__, z?z->del:1, q?q->del:1); - // fprintf(stderr, "+[M::%s::] ng->n::%u\n", __func__, (uint32_t)ng->n); - usg_cleanup(ng); - ///debug - debug_sysm_usg_t(ng, __func__); - // fprintf(stderr, "-[M::%s::] ng->n::%u\n", __func__, (uint32_t)ng->n); - } - // prt_usg_t(uidx, ng, "ng_dbg"); - if(!in) free(tx.a); if(!ib) free(tb.a); -} -**/ - -ma_ug_t *gen_debug_hybrid_ug(ul_resolve_t *uidx, usg_t *ng) -{ - ma_ug_t *ug = NULL; uint32_t k, nv, z; usg_arc_t *av; asg_arc_t *p; - CALLOC(ug, 1); ug->g = asg_init(); - ug->u.n = ug->u.m = ng->n; CALLOC(ug->u.a, ug->u.n); - for (k = 0; k < ng->n; k++) { - asg_seq_set(ug->g, k, ng->a[k].len, ng->a[k].del); - ug->g->seq[k].c = 0; - - av = usg_arc_a(ng, (k<<1)); nv = usg_arc_n(ng, (k<<1)); - for (z = 0; z < nv; z++) { - if(av[z].del) continue; - p = asg_arc_pushp(ug->g); memset(p, 0, sizeof((*p))); - p->ul = av[z].ul; p->v = av[z].v; p->ol = av[z].ol; p->del = av[z].del; - } - - av = usg_arc_a(ng, (k<<1)+1); nv = usg_arc_n(ng, (k<<1)+1); - for (z = 0; z < nv; z++) { - if(av[z].del) continue; - p = asg_arc_pushp(ug->g); memset(p, 0, sizeof((*p))); - p->ul = av[z].ul; p->v = av[z].v; p->ol = av[z].ol; p->del = av[z].del; - } - - ug->u.a[k].len = ug->g->seq[k].len; - ug->u.a[k].n = ug->u.a[k].m = 1; CALLOC(ug->u.a[k].a, 1); - ug->u.a[k].a[0] = (((uint64_t)k)<<33)|((uint64_t)(ug->u.a[k].len)); - } - asg_cleanup(ug->g); - - - uint32_t i; ma_utg_t *u; kvec_asg_arc_t_warp e; kv_init(e.a); e.i = 0; - for (i = 0; i < ug->u.n; i++) { - ug->g->seq[i].c = PRIMARY_LABLE; - u = &(ug->u.a[i]); - if(u->m == 0) continue; - merge_hybrid_utg_content(u, uidx->l1_ug, uidx->sg, ng, &e); - ug->g->seq[i].len = u->len; - } - kv_destroy(e.a); - return ug; -} - - -void prt_usg_t(ul_resolve_t *uidx, usg_t *ng, const char *cmd) -{ - ma_ug_t *ug = gen_debug_hybrid_ug(uidx, ng); - print_debug_gfa(uidx->sg, ug, uidx->uopt->coverage_cut, cmd, - uidx->uopt->sources, uidx->uopt->ruIndex, uidx->uopt->max_hang, uidx->uopt->min_ovlp, 0, 0, 0); - ma_ug_destroy(ug); - // exit(1); -} - -inline uint32_t usg_arc_occ(usg_t *g, uint32_t v, uint32_t *res) -{ - uint32_t i, kv, nv = usg_arc_n(g, v);; - usg_arc_t *av = usg_arc_a(g, v); - for (i = kv = 0; i < nv; i++) { - if(av[i].del) continue; - if(res) res[kv] = av[i].v; - kv++; - } - return kv; -} - -inline uint32_t gen_usg_tig(usg_t *g, uint32_t sid, uint32_t *eid, int64_t *baseLen, buf_t* b) -{ - uint32_t v = sid, w, k, kv, nv, return_flag; - usg_arc_t *av; - (*baseLen) = 0; (*eid) = (uint32_t)-1; - while (1) { - kv = usg_arc_occ(g, v, NULL); - (*eid) = v; - if(b) kv_push(uint32_t, b->b, v); - ///means reach the end of a unitig - if(kv!=1) (*baseLen) += g->a[v>>1].len; - if(kv==0) { - return_flag = END_TIPS; - break; - } else if(kv>1) { - return_flag = MUL_OUTPUT; - break; - } - - ///kv must be 1 here - kv = usg_arc_occ(g, v, &w); - if(usg_arc_occ(g, w^1, NULL)!=1) { - (*baseLen) += g->a[v>>1].len; - return_flag = MUL_INPUT; - break; - } else { - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - ///here is just one undeleted edge - (*baseLen) += asg_arc_len(av[k]); - break; - } - } - - v = w; - if(v == sid) { - return_flag = LOOP; - break; - } - } - return return_flag; -} - -uint64_t dfs_usg_t_dis(usg_t *g, buf_t *b, uint32_t x, uint32_t *p_bub) -{ - uint64_t len = 0; usg_arc_t *av = NULL; int64_t baseLen, uLen; - uint32_t c_v, e_v, nv, convex, v, i, kv_0, kv_1, flag_0 = 0, flag_1 = 0, op; - - (*p_bub) = 0; - if(b->a[x>>1].s || g->a[x>>1].del) return 0; - b->S.n = 0; - kv_push(uint32_t, b->S, x); - - while (b->S.n > 0) { - b->S.n--; - c_v = b->S.a[b->S.n]; - if(b->a[c_v>>1].s) continue; - - b->b.n = 0; //uint32_t gen_usg_tig(usg_t *g, uint32_t sid, uint32_t *eid, int64_t *baseLen, buf_t* b) - op = gen_usg_tig(g, c_v, &convex, &baseLen, b); - uLen = baseLen; - for(i = 0; i < b->b.n; i++) b->a[b->b.a[i]>>1].s = 1; - if(op == LOOP) return 0; - - - e_v = convex^1; - b->b.n = 0; - op = gen_usg_tig(g, e_v, &convex, &baseLen, b); - uLen = MAX(uLen, baseLen); - - len += uLen; - - - v = c_v^1; - nv = usg_arc_n(g, v); av = usg_arc_a(g, v); - for (i = kv_0 = 0; i < nv; i++) { - if(av[i].del) continue; - kv_0++; - if(b->a[av[i].v>>1].s) continue; - kv_push(uint32_t, b->S, av[i].v); - } - - v = e_v^1; - nv = usg_arc_n(g, v); av = usg_arc_a(g, v); - for (i = kv_1 = 0; i < nv; i++) { - if(av[i].del) continue; - kv_1++; - if(b->a[av[i].v>>1].s) continue; - kv_push(uint32_t, b->S, av[i].v); - } - - if(kv_0 > 0 && kv_1 > 0) flag_0++; - if(kv_0 > 1) flag_1++; - if(kv_1 > 1) flag_1++; - } - - if(flag_0 > 0 && flag_1 > 1) (*p_bub) = 1; - return len; -} - -uint64_t usg_bub_dis(usg_t *g, buf_t *b) -{ - usg_arc_t *av = NULL; uint64_t cLen = 0, mLen = 0; - uint32_t n_vtx = g->n<<1, k, v, w, kv, nv, p_bub; - - for (v = 0; v < n_vtx; ++v) { - if(b->a[v>>1].s || g->a[v>>1].del) continue; - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (k = kv = 0; k < nv && kv <= 1; k++) { - if(av[k].del) continue; - w = av[k].v^1; kv++; - } - if(kv == 1) { - av = usg_arc_a(g, w); nv = usg_arc_n(g, w); - for (k = kv = 0; k < nv && kv <= 1; k++) { - if(av[k].del) continue; - w = av[k].v^1; kv++; - } - if(kv == 1) continue; - } - - cLen = dfs_usg_t_dis(g, b, v^1, &p_bub); - if(p_bub == 0) continue;///no bubble - if(cLen > mLen) mLen = cLen; - } - - for (k = 0; k < g->n; ++k) b->a[k].s = 0; - b->S.n = b->b.n = 0; - return mLen; -} - -uint64_t usg_bub_identify(usg_t *g, uint32_t v0, uint64_t max_dist, uint64_t max_occ, buf_t *b) -{ - uint32_t i, n_pending = 0, is_first = 1, n_tips, tip_end; - uint64_t n_pop = 0; uint32_t v, nv, d, x; usg_arc_t *av; - if (g->a[v0>>1].del) return 0; // already deleted - if(usg_arc_occ(g, v0, NULL) < 2) return 0; - ///S saves nodes with all incoming edges visited - b->S.n = b->T.n = b->b.n = b->e.n = 0; - ///for each node, b->a saves all related information - b->a[v0].c = b->a[v0].d = b->a[v0].m = b->a[v0].nc = b->a[v0].np = 0; - ///b->S is the nodes with all incoming edges visited - kv_push(uint32_t, b->S, v0); - n_tips = 0; tip_end = (uint32_t)-1; - - do { - ///v is a node that all incoming edges have been visited - ///d is the distance from v0 to v - v = kv_pop(b->S); d = b->a[v].d; - nv = usg_arc_n(g, v); av = usg_arc_a(g, v); - ///why we have this assert? - ///assert(nv > 0); - ///all out-edges of v - for (i = 0; i < nv; ++i) { // loop through v's neighbors - /** - p->ul: |____________31__________|__________1___________|______________32_____________| - qn direction of overlap length of this node (not overlap length) - (in the view of query) - p->v : |___________31___________|__________1___________| - tn reverse direction of overlap - (in the view of target) - p->ol: overlap length - **/ - ///if this edge has been deleted - if (av[i].del) continue; - - uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l - binfo_t *t = &b->a[w]; - ///that means there is a circle, directly terminate the whole bubble poping - ///if (w == v0) goto pop_reset; - if ((w>>1) == (v0>>1)) goto usg_clean_reset; - /****************************may have bugs********************************/ - ///important when poping at long untig graph - if(is_first) l = 0; - /****************************may have bugs********************************/ - - ///push the edge - ///high 32-bit of g->idx[v] is the start point of v's edges - //so here is the point of this specfic edge - // kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); - ///find a too far path? directly terminate the whole bubble poping - if (d + l > max_dist) break; // too far - if (b->b.n > max_occ) break; // too far - - ///if this node - if (t->s == 0) { // this vertex has never been visited - kv_push(uint32_t, b->b, w); // save it for revert - ///t->p is the parent node of - ///t->s = 1 means w has been visited - ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) - t->p = v, t->s = 1, t->d = d + l; - ///incoming edges of w - t->r = usg_arc_occ(g, w^1, NULL); - ++n_pending; - } else { // visited before - if (d + l < t->d) t->d = d + l; // update dist - } - ///assert(t->r > 0); - //if all incoming edges of w have visited - //push it to b->S - if (--(t->r) == 0) { - x = usg_arc_occ(g, w, NULL); - /****************************may have bugs for bubble********************************/ - if(x > 0) { - kv_push(uint32_t, b->S, w); - } - else { - ///at most one tip - if(n_tips != 0) goto usg_clean_reset; - n_tips++; tip_end = w; - } - /****************************may have bugs for bubble********************************/ - --n_pending; - } - } - is_first = 0; - //if found a tip - /****************************may have bugs for bubble********************************/ - if(n_tips == 1) { - if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) { - kv_push(uint32_t, b->S, tip_end); - break; - } else { - goto usg_clean_reset; - } - } - /****************************may have bugs for bubble********************************/ - ///if i < nv, that means (d + l > max_dist) - if (i < nv || b->S.n == 0) goto usg_clean_reset; - } while (b->S.n > 1 || n_pending); - - n_pop = 1; - usg_clean_reset: - - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - binfo_t *t = &b->a[b->b.a[i]]; - t->s = t->c = t->d = t->m = t->nc = t->np = 0; - } - return n_pop; -} - -void extracr_clean_arc(usg_t *g, uint32_t v, asg64_v *b, asg64_v *ub) -{ - usg_arc_t *av; uint32_t i, kv, nv; uint64_t x, kocc[2]; - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - if (nv < 2) return; - for (i = kv = kocc[0] = kocc[1] = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - if((av[i].ou>>1) > 0) { ///if av[i].ou == 1, ignore it - if(kocc[1] < (av[i].ou>>1)) kocc[1] = (av[i].ou>>1); - } else if(av[i].ou == 0) { - kocc[0]++; - } - } - if(kv < 2 || kocc[0] == 0 || kocc[1] == 0) return; - for (i = 0; i < nv; ++i) { - if(av[i].del || av[i].ou) continue; - // if(max_drop_len && av[i].ol >= (*max_drop_len)) continue; - x = av[i].ol; x <<= 32; - kv_push(uint64_t, *b, ((x)|((uint64_t)(ub->n)))); - kv_push(uint64_t, *ub, ((((uint64_t)(v))<<32)|((uint64_t)(i)))); - } -} - - -int usg_tip_del(usg_t *g, uint32_t v, asg64_v *z_a, asg64_v *z_b) -{ - uint64_t a_n = z_a->n, b_n = z_b->n, kv, nv, i; - int32_t n_ext = 0; usg_arc_t *av; - - av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); - for (i = kv = 0; i < nv && kv <= 1; i++) { - if (av[i].del || g->a[av[i].v>>1].del) continue; - kv++; - } - if(kv > 1) return 0; - n_ext += g->a[v>>1].occ; g->a[v>>1].del = 1; kv_push(uint64_t, *z_b, v>>1); - - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (i = 0; i < nv; i++) { - if (av[i].del || g->a[av[i].v>>1].del) continue; - kv_push(uint64_t, *z_a, av[i].v); - } - - while (z_a->n > a_n) { - v = z_a->a[--z_a->n]; if(g->a[v>>1].del) continue; - - av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); - for (i = kv = 0; i < nv && kv < 1; i++) { - if (av[i].del || g->a[av[i].v>>1].del) continue; - kv++; - } - if(kv > 0) continue; - n_ext += g->a[v>>1].occ; g->a[v>>1].del = 1; kv_push(uint64_t, *z_b, v>>1); - - av = usg_arc_a(g, v); nv = usg_arc_n(g, v); - for (i = 0; i < nv; i++) { - if (av[i].del || g->a[av[i].v>>1].del) continue; - kv_push(uint64_t, *z_a, av[i].v); - } - } - - for (i = b_n; i < z_b->n; i++) usg_seq_del(g, z_b->a[i]); - z_b->n = b_n; z_a->n = a_n; - return n_ext; -} - -uint64_t usg_bub_clean0(usg_t *g, uint32_t *a, uint32_t a_n, uint32_t sid, uint32_t eid, -uint32_t is_topo, int32_t max_ext, float len_rat, uint8_t *f, asg64_v *in_0, asg64_v *in_1) -{ - uint32_t i, k, v, w, nv, nw, kv, kw, ol_max, ou_max, to_del, cnt = 0, tip_v, mm_ol; - asg64_v tx = {0,0,0}, tz = {0,0,0}, *b = NULL, *ub = NULL; int32_t n_tip, r_tip; - uint64_t kocc[2]; usg_arc_t *av, *aw, *ve, *we; - b = ((in_0)?(in_0):(&tx)); ub = ((in_1)?(in_1):(&tz)); - - for (k = b->n = ub->n = 0; k < a_n; ++k) { - extracr_clean_arc(g, a[k], b, ub); - extracr_clean_arc(g, a[k]^1, b, ub); - } - extracr_clean_arc(g, sid, b, ub); - extracr_clean_arc(g, eid, b, ub); - - - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - v = ub->a[(uint32_t)b->a[k]]>>32; - ve = &(usg_arc_a(g, v)[(uint32_t)(ub->a[(uint32_t)b->a[k]])]); - w = ve->v^1; - if(ve->del || g->a[v>>1].del || g->a[w>>1].del || ve->ou) continue; - nv = usg_arc_n(g, v); nw = usg_arc_n(g, w); - av = usg_arc_a(g, v); aw = usg_arc_a(g, w); - if(nv<=1 && nw <= 1) continue; - - // if(is_trio) { - // if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup - // trioF = get_tip_trio_infor(g, v^1); - // ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); - // } - for (i = 0; i < nw; ++i) { - if (aw[i].v == (v^1)) { - we = &(aw[i]); - break; - } - } - mm_ol = MIN(ve->ol, we->ol); kocc[0] = kocc[1] = 0; - - for (i = kv = ol_max = ou_max = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - if(av[i].ou != 1) kocc[!!(av[i].ou)]++; ///if av[i].ou == 1, ignore it - // if(is_trio && get_tip_trio_infor(g, av[i].v) == ntrioF) continue; - if(ol_max < av[i].ol) ol_max = av[i].ol; - } - if (kv < 1 || kocc[0] < 1 || kocc[1] < 1) continue; - if (kv >= 2) { - if (mm_ol > ol_max*len_rat) continue; - } - - - for (i = kw = ol_max = ou_max = 0; i < nw; ++i) { - if(aw[i].del) continue; - kw++; - // if(is_trio && get_tip_trio_infor(g, aw[i].v) == ntrioF) continue; - if(ol_max < aw[i].ol) ol_max = aw[i].ol; - } - if (kw < 1) continue; - if (kw >= 2) { - if (mm_ol > ol_max*len_rat) continue; - } - - if (kv <= 1 && kw <= 1) continue; - - to_del = 1; n_tip = 0; tip_v = (uint32_t)-1; - if(is_topo) { - to_del = 0; - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - n_tip = usg_naive_topocut_aux(g, w^1, max_ext, f, b, ub); - if (n_tip < max_ext) to_del = 1; tip_v = w^1; - } else if (kv == 1) { - n_tip = usg_naive_topocut_aux(g, v^1, max_ext, f, b, ub); - if (n_tip < max_ext) to_del = 1; tip_v = v^1; - } - } - - if (to_del) { - // ve->del = we->del = 1; - if(n_tip > 0 && tip_v != ((uint32_t)-1)) { - r_tip = usg_tip_del(g, tip_v, b, ub); - assert(n_tip == r_tip); - } - cnt++; - } - } - - if(in_0) free(tx.a); if(in_1) free(tz.a); - return cnt; -} - -uint64_t usg_bub_clean(usg_t *g, buf_t *b, asg64_v *in_0, asg64_v *in_1, int32_t max_ext, float len_rat, -uint32_t is_topo, uint8_t *bs, uint8_t *f) -{ - uint32_t v, m, n_vtx = g->n<<1, n_arc, nv, i, n_cut = 0; - uint64_t max_dist; usg_arc_t *av = NULL; - // for (i = 0; i < g->n; ++i) b->a[i].s = 0; - max_dist = usg_bub_dis(g, b); - memset(bs, 0, sizeof((*bs))*n_vtx); - - if(max_dist > 0) { - for (v = 0; v < n_vtx; ++v) { - if(bs[v]) continue; - nv = usg_arc_n(g, v); av = usg_arc_a(g, v); - if (nv < 2 || g->a[v>>1].del) continue; - for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs - if (!av[i].del) ++n_arc; - if (n_arc < 2) continue; - if(usg_bub_identify(g, v, max_dist, (uint64_t)-1, b)) { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (i = 0; i < b->b.n; i++) { - if(b->b.a[i]==v || b->b.a[i]==b->S.a[0]) continue; - bs[b->b.a[i]] = bs[b->b.a[i]^1] = 1; - } - bs[v] = 2; bs[b->S.a[0]^1] = 3; - } - } - - //traverse all node with two directions - for (v = 0; v < n_vtx; ++v) { - if(bs[v] != 2) continue; - nv = usg_arc_n(g, v); av = usg_arc_a(g, v); - for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs - if (!av[i].del) ++n_arc; - if (n_arc < 2) continue; - if(usg_bub_identify(g, v, max_dist, (uint64_t)-1, b)) { - for (i = m = 0; i < b->b.n; i++) { - if(b->b.a[i]==v || b->b.a[i]==b->S.a[0]) continue; - bs[b->b.a[i]] = bs[b->b.a[i]^1] = 1; - b->b.a[m++] = b->b.a[i]; - } - b->b.n = m; bs[v] = 2; bs[b->S.a[0]^1] = 3; - n_cut += usg_bub_clean0(g, b->b.a, b->b.n, v, b->S.a[0]^1, is_topo, max_ext, len_rat, f, in_0, in_1); - } - } - } - if (n_cut > 0) usg_cleanup(g); - return n_cut; -} - -void u2g_hybrid_clean(ul_resolve_t *uidx, ulg_opt_t *ulopt, usg_t *ng, asg64_v *b, asg64_v *ub) -{ - int64_t i, ss, mm_tip = ulopt->max_tip_hifi;///ulopt->max_tip; - double step = (ulopt->clean_round==1?ulopt->max_ovlp_drop_ratio: - ((ulopt->max_ovlp_drop_ratio-ulopt->min_ovlp_drop_ratio)/(ulopt->clean_round-1))); - double drop = ulopt->min_ovlp_drop_ratio; ///CALLOC(iug->g->seq_vis, iug->g->n_seq*2); - buf_t bb; memset(&bb, 0, sizeof(buf_t)); CALLOC(bb.a, ng->n<<1); - uint8_t *bs, *f; CALLOC(bs, ng->n<<1); CALLOC(f, ng->n); - // fprintf(stderr, "\n[M::%s::] Starting hybrid clean, mm_tip::%ld\n", __func__, mm_tip); - // prt_usg_t(uidx, ng, "ng_h0"); - usg_arc_cut_tips(ng, mm_tip, 0, b);///p_telo - // prt_usg_t(uidx, ng, "ng_h1"); - // char sb[1000]; - - for (ss = 1; ss <= 1/**6**/; ss++) { - mm_tip = ulopt->max_tip_hifi*ss; - // fprintf(stderr, "\n[M::%s::] ss::%ld, mm_tip::%ld, ulopt->clean_round::%ld\n", - // __func__, ss, mm_tip, ulopt->clean_round); - for (i = 0, drop = ulopt->min_ovlp_drop_ratio; i < ulopt->clean_round; i++, drop += step) { - if(drop > ulopt->max_ovlp_drop_ratio) drop = ulopt->max_ovlp_drop_ratio; - // fprintf(stderr, "-0-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); - // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_a", ss, i, drop); - // prt_usg_t(uidx, ng, sb); - // usg_arc_cut_length(ng, b, ub, mm_tip>>1, drop, ulopt->is_trio, 1, NULL); - usg_bub_clean(ng, &bb, b, ub, mm_tip>>1, drop, 1, bs, f); - usg_arc_cut_srt_length(ng, b, ub, mm_tip>>1, drop, ulopt->is_trio, 1, NULL, bs); - // fprintf(stderr, "-1-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); - // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_b", ss, i, drop); - // prt_usg_t(uidx, ng, sb); - usg_arc_cut_tips(ng, mm_tip, 0, b); - // fprintf(stderr, "-2-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); - // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_c", ss, i, drop); - // prt_usg_t(uidx, ng, sb); - // usg_arc_cut_length(ng, b, ub, mm_tip, drop, ulopt->is_trio, 1, NULL); - usg_bub_clean(ng, &bb, b, ub, mm_tip, drop, 1, bs, f); - usg_arc_cut_srt_length(ng, b, ub, mm_tip, drop, ulopt->is_trio, 1, NULL, bs); - // fprintf(stderr, "-3-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); - // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_d", ss, i, drop); - // prt_usg_t(uidx, ng, sb); - usg_arc_cut_tips(ng, mm_tip, 1, b); - // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_e", ss, i, drop); - // prt_usg_t(uidx, ng, sb); - // fprintf(stderr, "-4-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); - } - - drop = 1; - // fprintf(stderr, "-0-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); - // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_a", ss, i, drop); - // prt_usg_t(uidx, ng, sb); - // usg_arc_cut_length(ng, b, ub, mm_tip>>1, drop, ulopt->is_trio, 1, NULL); - usg_bub_clean(ng, &bb, b, ub, mm_tip>>1, drop, 1, bs, f); - // fprintf(stderr, "-1bub-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); - // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_b::bub", ss, i, drop); - // prt_usg_t(uidx, ng, sb); - usg_arc_cut_srt_length(ng, b, ub, mm_tip>>1, drop, ulopt->is_trio, 1, NULL, bs); - // fprintf(stderr, "-1-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); - // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_b", ss, i, drop); - // prt_usg_t(uidx, ng, sb); - usg_arc_cut_tips(ng, mm_tip, 0, b); - // fprintf(stderr, "-2-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); - // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_c", ss, i, drop); - // prt_usg_t(uidx, ng, sb); - // usg_arc_cut_length(ng, b, ub, mm_tip, drop, ulopt->is_trio, 1, NULL); - usg_bub_clean(ng, &bb, b, ub, mm_tip, drop, 1, bs, f); - usg_arc_cut_srt_length(ng, b, ub, mm_tip, drop, ulopt->is_trio, 1, NULL, bs); - // fprintf(stderr, "-3-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); - // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_d", ss, i, drop); - // prt_usg_t(uidx, ng, sb); - usg_arc_cut_tips(ng, mm_tip, 1, b); - // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_e", ss, i, drop); - // prt_usg_t(uidx, ng, sb); - // fprintf(stderr, "-4-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); - } - free(bb.a); free(bb.S.a); free(bb.T.a); free(bb.b.a); free(bb.e.a); free(bs); free(f); - // prt_usg_t(uidx, ng, "ng_h2"); - ///debug - debug_sysm_usg_t(ng, __func__); - - /******for debug******/ - // prt_usg_t(uidx, ng, "ng_dbg"); - /******for debug******/ - - // u2g_hybrid_extend(ng, NULL, b, ub); - // u2g_hybrid_detan(uidx, ng, mm_tip, b, ub); - u2g_hybrid_detan_iter(uidx, ng, mm_tip, ulopt->clean_round, b, ub); -} - -void merge_hybrid_utg_content(ma_utg_t* cc, ma_ug_t* raw, asg_t* rg, usg_t *ng, kvec_asg_arc_t_warp* edge) -{ - if(cc->m == 0) return; - uint32_t i, j, index, uId, ori, uv, uw, bv, bw; - uint64_t tot, z; asg_arc_t *p; - ma_utg_t* q = NULL; - for (i = index = 0; i < cc->n; i++) { - z = (ng->a[cc->a[i]>>33].mm<<1)|((cc->a[i]>>32)&1); z <<= 32; z += ((uint32_t)cc->a[i]); - index += ng->a[cc->a[i]>>33].occ; cc->a[i] = z; - } - - uint64_t *buffer, *aim = NULL; MALLOC(buffer, index); - for (i = index = edge->a.n = 0; i < cc->n; i++) { - uId = cc->a[i]>>33; ori = cc->a[i]>>32&1; - q = &(raw->u.a[uId]); aim = buffer + index; - if(ori == 1) { - for (j = 0; j < q->n; j++) { - aim[q->n - j - 1] = (q->a[j])^(uint64_t)(0x100000000); - } - } else { - for (j = 0; j < q->n; j++) { - aim[j] = q->a[j]; - } - } - index += q->n; - if(i > 0) { - uv = cc->a[i-1]>>32; uw = cc->a[i]>>32; - p = get_specfic_edge(raw->g, uv, uw); - if(!p) { - uv = cc->a[i-1]>>32; uw = cc->a[i]>>32; - bv = raw->u.a[uv>>1].a[((uv&1)?(0):(raw->u.a[uv>>1].n-1))]>>32; if(uv&1) bv ^= 1; - bw = raw->u.a[uw>>1].a[((uw&1)?(raw->u.a[uw>>1].n-1):(0))]>>32; if(uw&1) bw ^= 1; - kv_pushp(asg_arc_t, edge->a, &p); memset(p, 0, sizeof((*p))); - p->ul = bv; p->ul <<= 32; p->ul += rg->seq[bv>>1].len; p->v = bw; - - uv = (cc->a[i]>>32)^1; uw = (cc->a[i-1]>>32)^1; - bv = raw->u.a[uv>>1].a[((uv&1)?(0):(raw->u.a[uv>>1].n-1))]>>32; if(uv&1) bv ^= 1; - bw = raw->u.a[uw>>1].a[((uw&1)?(raw->u.a[uw>>1].n-1):(0))]>>32; if(uw&1) bw ^= 1; - kv_pushp(asg_arc_t, edge->a, &p); memset(p, 0, sizeof((*p))); - p->ul = bv; p->ul <<= 32; p->ul += rg->seq[bv>>1].len; p->v = bw; - } - } - } - - if(index == 0) return; - - fill_unitig(buffer, index, rg, edge, (cc->n == 1 && raw->u.a[cc->a[0]>>33].circ), &tot); - - ///important. must be here - if(cc->n == 1 && raw->u.a[cc->a[0]>>33].circ) cc->circ = 1; - - free(cc->a); - cc->a = buffer; cc->n = cc->m = index; cc->len = tot; - if(!cc->circ) { - cc->start = cc->a[0]>>32; - cc->end = (cc->a[cc->n-1]>>32)^1; - } - else { - cc->start = cc->end = UINT32_MAX; - } -} - -ma_ug_t *gen_hybrid_ug(ul_resolve_t *uidx, usg_t *ng) -{ - // fprintf(stderr, "[M::%s::] ng->n::%u\n", __func__, (uint32_t)ng->n); - ma_ug_t *ug = ma_ug_hybrid_gen(ng); - // fprintf(stderr, "[M::%s::] ug->g->n_seq::%u\n", __func__, (uint32_t)ug->g->n_seq); - uint32_t i; ma_utg_t *u; kvec_asg_arc_t_warp e; kv_init(e.a); e.i = 0; - for (i = 0; i < ug->u.n; i++) { - ug->g->seq[i].c = PRIMARY_LABLE; - u = &(ug->u.a[i]); - if(u->m == 0) continue; - // fprintf(stderr, "+[M::%s::] i::%u\n", __func__, i); - merge_hybrid_utg_content(u, uidx->l1_ug, uidx->sg, ng, &e); - // fprintf(stderr, "-[M::%s::] i::%u\n", __func__, i); - ug->g->seq[i].len = u->len; - } - kv_destroy(e.a); - return ug; -} - -uint32_t gen_utg_telo(ma_utg_t *u, telo_end_t *te) -{ - uint32_t i; - for (i = 0; i < u->n; ++i) { - if(te->hh[u->a[i]>>33]) return 1; - } - return 0; -} - -void renew_ul2_utg(ul_resolve_t *uidx); - -void u2g_threading(ul_resolve_t *uidx, ulg_opt_t *ulopt, uint64_t cov_cutoff, uint64_t is_bridg, asg64_v *b, asg64_v *ub) -{ - renew_ul2_utg(uidx); - ul2ul_idx_t *idx = &(uidx->uovl); ma_ug_t *iug = idx->i_ug; ma_ug_t *raw = uidx->l1_ug; - uint64_t k, z, i, t_s, t_e; uinfo_srt_warp_t *seq; - usg_t *ng; CALLOC(ng, 1); usg_seq_t *s; usg_arc_warp *sv; usg_arc_t *p; - asg_arc_t *av; uint32_t nv, v, w, vx, wx; int64_t tt, tl, tm; - - ng->mp.n = ng->mp.m = raw->g->n_seq; MALLOC(ng->mp.a, ng->mp.n); - for (k = 0; k < raw->g->n_seq; k++) { - s = push_usg_t_node(ng, k); - s->mm = k; s->arc[0].n = s->arc[1].n = 0; s->occ = raw->u.a[k].n; - s->arc_mm[0].n = s->arc_mm[1].n; - s->del = raw->g->seq[k].del; s->len = raw->g->seq[k].len; - s->telo = 0; - if(uidx->uopt->te) { - s->telo = gen_utg_telo(&(raw->u.a[k]), uidx->uopt->te); - } - - av = asg_arc_a(raw->g, (k<<1)); nv = asg_arc_n(raw->g, (k<<1)); sv = &(s->arc[0]); - for (z = 0; z < nv; z++) { - if(av[z].del) continue; - kv_pushp(usg_arc_t, *sv, &p); - p->del = 0; p->ou = 0; p->v = av[z].v; p->ol = av[z].ol; p->ul = av[z].ul; p->idx = 0; - } - - av = asg_arc_a(raw->g, ((k<<1)+1)); nv = asg_arc_n(raw->g, ((k<<1)+1)); sv = &(s->arc[1]); - for (z = 0; z < nv; z++) { - if(av[z].del) continue; - kv_pushp(usg_arc_t, *sv, &p); - p->del = 0; p->ou = 0; p->v = av[z].v; p->ol = av[z].ol; p->ul = av[z].ul; p->idx = 0; - } - ///map: ng id -> raw id - ng->mp.a[k].n = ng->mp.a[k].m = 1; MALLOC(ng->mp.a[k].a, 1); ng->mp.a[k].a[0] = k; - } - - for (k = b->n = 0; k < iug->u.n; k++) { - seq = &(idx->cc.iug_a[k]); - if(seq->n <= 1) continue; - - uidx->uovl.iug_seq = seq; uidx->uovl.iug_cov_thre = cov_cutoff; - for (z = 0; z < uidx->str_b.n_thread; z++) { - uidx->str_b.buf[z].res_dump.n = 0; - } - kt_for(uidx->str_b.n_thread, worker_update_ul_arc_drop, uidx, seq->n-1);///seq->n > 1 - for (z = ub->n = 0; z < uidx->str_b.n_thread; z++) { - for (i = 0; i < uidx->str_b.buf[z].res_dump.n; i++) { - kv_push(uint64_t, *ub, uidx->str_b.buf[z].res_dump.a[i]); - } - } - - for (z = 0; z < ub->n; z++) {///all unreliable arcs - i = ub->a[z]; tm = 1; p = get_usg_arc(ng, seq->a[i].v, seq->a[i+1].v); - if(p) { - if(p->ou < (uint64_t)tm) p->ou = tm;///since the initial ou is 0, p->ou = 1 - pushp_usg_arc_mm(ng, seq->a[i].v, seq->a[i+1].v, k, i); - - p = get_usg_arc(ng, seq->a[i+1].v^1, seq->a[i].v^1); - if(p->ou < (uint64_t)tm) p->ou = tm;///since the initial ou is 0, p->ou = 1 - pushp_usg_arc_mm(ng, seq->a[i+1].v^1, seq->a[i].v^1, k, i); - } - ///give up unreliable arcs if they are not adjacent - } - - radix_sort_srt64(ub->a, ub->a + ub->n); - if(ub->n == 0 || ub->a[ub->n-1] < seq->n-1) kv_push(uint64_t, *ub, seq->n-1); - for (z = t_s = t_e = 0; z < ub->n; z++) { - t_e = ub->a[z]; - if(t_s < t_e) { - for (i = t_s, tt = seq->a[t_e].n; i < t_e; i++) { - tt += seq->a[i].n;///how many HiFi reads are covered - } - for (i = t_s, tl = 0; i < t_e; i++) { - tl += seq->a[i].n; - tm = tt - tl; if(tm > tl) tm = tl; assert(tm > 0); tm <<= 1; tm += 1; - p = get_usg_arc(ng, seq->a[i].v, seq->a[i+1].v); - if(p) { - if(p->ou < (uint64_t)tm) p->ou = tm; - p = get_usg_arc(ng, seq->a[i+1].v^1, seq->a[i].v^1); - if(p->ou < (uint64_t)tm) p->ou = tm; - } else if(is_bridg) { - v = seq->a[i].v; w = seq->a[i+1].v; p = NULL; - vx = (v&1?((raw->u.a[v>>1].a[0]>>32)^1):(raw->u.a[v>>1].a[raw->u.a[v>>1].n-1]>>32)); - wx = (w&1?((raw->u.a[w>>1].a[raw->u.a[w>>1].n-1]>>32)^1):(raw->u.a[w>>1].a[0]>>32)); - ///(v>>1) != (w>>1) or v == w, need to handle (v>>1) == (w>>1) && (v&1) != (w&1) later - if(((v^w) != 1) && (uidx->sg->seq[vx>>1].len > uidx->uopt->min_ovlp) && - (uidx->sg->seq[wx>>1].len > uidx->uopt->min_ovlp)) { - kv_pushp(usg_arc_t, (ng->a[v>>1].arc[v&1]), &p); - p->del = 0; p->ou = tm; p->v = w; p->ol = 0; p->idx = 0; - p->ul = (((uint64_t)v)<<32)|(raw->g->seq[v>>1].len); - - v = seq->a[i+1].v^1; w = seq->a[i].v^1; - kv_pushp(usg_arc_t, (ng->a[v>>1].arc[v&1]), &p); - p->del = 0; p->ou = tm; p->v = w; p->ol = 0; p->idx = 0; - p->ul = (((uint64_t)v)<<32)|(raw->g->seq[v>>1].len); - } - } - if(p) { - pushp_usg_arc_mm(ng, seq->a[i].v, seq->a[i+1].v, k, i); - pushp_usg_arc_mm(ng, seq->a[i+1].v^1, seq->a[i].v^1, k, i); - } - } - } - t_s = ub->a[z] + 1; - } - } - - // for (v = 0; v < (ng->n<<1); v++) { - // p = usg_arc_a(ng, v); nv = usg_arc_n(ng, v); - // for (i = 0; i < nv; i++) { - // assert(get_usg_arc(ng, p[i].v^1, v^1)); - // } - // } - - usg_cleanup(ng); - - ///debug - debug_sysm_usg_t(ng, __func__); - - idx->h_usg = ng; - - /******for debug******/ - // prt_usg_t(uidx, ng, "ng0"); - /******for debug******/ - - - - u2g_hybrid_clean(uidx, ulopt, ng, b, ub); - // idx->hybrid_ug = gen_hybrid_ug(uidx, ng); - - - // idx->hybrid_ug = gen_debug_hybrid_ug(uidx, ng); - // fprintf(stderr, "-[M::%s::] idx->hybrid_ug->g->n_seq::%u\n", __func__, (uint32_t)idx->hybrid_ug->g->n_seq); -} - -void u2g_clean(ul_resolve_t *uidx, ulg_opt_t *ulopt, uint32_t keep_raw_utg, uint64_t is_bridg) -{ - ul2ul_idx_t *idx = &(uidx->uovl); asg64_v bu = {0,0,0}, uu = {0,0,0}; int64_t max_tip_hifi0 = ulopt->max_tip_hifi; - ma_ug_t *iug = idx->i_ug; int64_t i, mm_tip = ulopt->max_tip; uint64_t cnt = 1, topo_level, ss = 0; - double step = (ulopt->clean_round==1?ulopt->max_path_drop_ratio: - ((ulopt->max_path_drop_ratio-ulopt->min_path_drop_ratio)/(ulopt->clean_round-1))); - double drop = ulopt->min_path_drop_ratio; CALLOC(iug->g->seq_vis, iug->g->n_seq*2); - - - // char sb[1000]; - // output_integer_graph(uidx, iug, "ig_h0", 0); - - // fprintf(stderr, "\n[M::%s::] max_path_drop_ratio::%f, min_path_drop_ratio::%f, max_tip_hifi::%ld, max_tip::%ld\n", - // __func__, ulopt->max_path_drop_ratio, ulopt->min_path_drop_ratio, - // ulopt->max_tip_hifi, ulopt->max_tip); - for (ss = 0; ss < 2; ss++) { - for (i = 0, drop = ulopt->min_path_drop_ratio; i < ulopt->clean_round; i++, drop += step) { - if(drop > ulopt->max_path_drop_ratio) drop = ulopt->max_path_drop_ratio; - // fprintf(stderr, "[M::%s::] Starting round-%ld, drop::%f, max_tip_hifi::%ld\n", - // __func__, i, drop, ulopt->max_tip_hifi); - cnt = 1; topo_level = 2; mm_tip = ulopt->max_tip; - while (cnt) { - cnt = 0; - asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); - cnt += ulg_arc_cut_supports(uidx, iug, mm_tip, ulopt->max_tip_hifi, drop, ulopt->is_trio, topo_level, 1, NULL, keep_raw_utg, &bu, &uu); - cnt += ulg_arc_cut_tips(uidx, iug, mm_tip, ulopt->max_tip_hifi, 1, &bu, &uu);///p_telo - } - - cnt = 1; topo_level = 1; mm_tip = ulopt->max_tip; - while (cnt) { - cnt = 0; - asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); - cnt += ulg_arc_cut_supports(uidx, iug, mm_tip, ulopt->max_tip_hifi, drop, ulopt->is_trio, topo_level, 1, NULL, keep_raw_utg, &bu, &uu); - cnt += ulg_arc_cut_tips(uidx, iug, mm_tip, ulopt->max_tip_hifi, 1, &bu, &uu); - } - - cnt = 1; topo_level = 1; mm_tip = ((int64_t)0x7fffffff); - while (cnt) { - cnt = 0; - asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); - cnt += ulg_arc_cut_supports(uidx, iug, mm_tip, ulopt->max_tip_hifi, drop, ulopt->is_trio, topo_level, 1, NULL, keep_raw_utg, &bu, &uu); - cnt += ulg_arc_cut_tips(uidx, iug, mm_tip, ulopt->max_tip_hifi, 0, &bu, &uu); - } - // fprintf(stderr, "[M::%s::] Done round-%ld, drop::%f\n", __func__, i, drop); - // sprintf(sb, "ig_ss_%lu_i_%ld", ss, i); - // output_integer_graph(uidx, iug, sb, 0); - } - - ulg_pop_bubble(uidx, iug, NULL, ((int64_t)0x7fffffff), ulopt->max_tip_hifi, 1, &bu, &uu); - - while(ulg_arc_cut_z(uidx, iug, ((int64_t)0x7fffffff), ulopt->max_tip_hifi, 1.5, 0.15, 100, 0.8, ulopt->is_trio, 1, NULL, &bu, &uu));///non_p_telo - - // sprintf(sb, "ig_ss_%lu_i_%ld", ss, i); - // output_integer_graph(uidx, iug, sb, 0); - - ulopt->max_tip_hifi <<= 1; - } - ulopt->max_tip_hifi = max_tip_hifi0; - - // output_integer_graph(uidx, iug, "ig_h1", 0); - - u2g_threading(uidx, ulopt, 3, is_bridg, &bu, &uu); - - - // fill_u2g(uidx, &bu, &uu); - - // while (cnt) { - // for (i = cnt = 0, mm_tip = ulopt->max_tip, drop = ulopt->min_ovlp_drop_ratio; i < ulopt->clean_round; i++, drop += step) { - // if(drop > ulopt->max_ovlp_drop_ratio) drop = ulopt->max_ovlp_drop_ratio; - // cnt += ulg_arc_cut_occ(uidx, iug, mm_tip, ulopt->max_tip_hifi, ulopt->is_trio, 2, &bu, &uu); - // asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); - // cnt += ulg_arc_cut_length(uidx, iug, mm_tip, ulopt->max_tip_hifi, drop/**MIN(drop, ulopt->hom_check_drop_rate)**/, ulopt->is_trio, 2, 1, NULL, &bu, &uu); - // cnt += ulg_arc_cut_tips(uidx, iug, mm_tip, ulopt->max_tip_hifi, &bu, &uu); - - // asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); - // cnt += ulg_arc_cut_bridge(uidx, iug, mm_tip, ulopt->max_tip_hifi, 0.5, ulopt->is_trio, 2, NULL, &bu, &uu); - - // asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); - // cnt += ulg_arc_cut_misjoin(uidx, iug, mm_tip, ulopt->max_tip_hifi, 0.5, ulopt->is_trio, 2, NULL, &bu, &uu); - // } - - // for (i = cnt = 0, mm_tip = ((int64_t)0x7fffffff), drop = ulopt->min_ovlp_drop_ratio; i < ulopt->clean_round; i++, drop += step) { - // if(drop > ulopt->max_ovlp_drop_ratio) drop = ulopt->max_ovlp_drop_ratio; - // cnt += ulg_arc_cut_occ(uidx, iug, mm_tip, ulopt->max_tip_hifi, ulopt->is_trio, 2, &bu, &uu); - // asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); - // cnt += ulg_arc_cut_length(uidx, iug, mm_tip, ulopt->max_tip_hifi, drop/**MIN(drop, ulopt->hom_check_drop_rate)**/, ulopt->is_trio, 2, 1, NULL, &bu, &uu); - // cnt += ulg_arc_cut_tips(uidx, iug, mm_tip, ulopt->max_tip_hifi, &bu, &uu); - - // asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); - // cnt += ulg_arc_cut_bridge(uidx, iug, mm_tip, ulopt->max_tip_hifi, 0.5, ulopt->is_trio, 2, NULL, &bu, &uu); - - // asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); - // cnt += ulg_arc_cut_misjoin(uidx, iug, mm_tip, ulopt->max_tip_hifi, 0.5, ulopt->is_trio, 2, NULL, &bu, &uu); - // } - // } - - free(bu.a); free(uu.a); -} - -void clc_contain(ul_resolve_t *uidx, uint64_t id, uint64_t is_ul, integer_t *buf) -{ - ma_ug_t *raw = uidx->l1_ug; ma_utg_t *ru; ug_opt_t *uopt = uidx->uopt; - uint64_t k, m, qn, tn; ma_hit_t_alloc *x; asg_arc_t e; ul2ul_item_t *o; - int64_t min_ovlp = uopt->min_ovlp, max_hang = uopt->max_hang, r; - - if(is_ul) { - o = get_ul_ovlp(&(uidx->uovl), id, 1); - assert(o && (!o->is_del)); - for (k = 0; k < o->cn; k++) { - if((o->a[k].is_del) || (!ulg_type(uidx->uovl, o->a[k].hid))) continue; - r = integer_hit2arc(&(o->a[k]), ulg_len(*uidx, id), ulg_len(*uidx, o->a[k].hid), - ulg_occ(*uidx, id), ulg_occ(*uidx, o->a[k].hid), id, o->a[k].hid, 0, NULL); - if(r != MA_HT_TCONT) continue; - kv_push(uint64_t, buf->o, o->a[k].hid); - } - } else { - ru = &(raw->u.a[id]); - for (k = 0; k < ru->n; k++) { - x = &(uopt->sources[ru->a[k]>>33]); - for (m = 0; m < x->length; m++) { - qn = Get_qn(x->buffer[m]); tn = Get_tn(x->buffer[m]); - r = ma_hit2arc(&(x->buffer[m]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), - max_hang, asm_opt.max_hang_rate, min_ovlp, &e); - if(r != MA_HT_TCONT) continue; - kv_push(uint64_t, buf->u, tn); - } - } - } -} - -static void worker_renew_u2g_cov(void *data, long i, int tid) // callback for kt_for() -{ - ul_resolve_t *uidx = (ul_resolve_t *)data; - integer_t *buf = &(uidx->str_b.buf[tid]); - ma_utg_t *iu = &(uidx->uovl.i_ug->u.a[i]); - uint64_t z, ri, k, ul_n, ug_n, *a, a_n; ma_ug_t *raw = uidx->l1_ug; - ul_cov_t *idx = &(uidx->uovl.cc); - - idx->uc[i] = idx->raw_uc[i] = idx->hc[i] = ul_n = ug_n = 0; buf->u.n = buf->o.n = 0; - for (z = 0; z < iu->n; z++) { - ri = iu->a[z]>>33; - if(ulg_type(uidx->uovl, ri)) {///ul - clc_contain(uidx, ulg_id(uidx->uovl, ri), 1, buf); ul_n++; - } else {///ug node - clc_contain(uidx, ulg_id(uidx->uovl, ri), 0, buf); - ug_n += raw->u.a[ulg_id(uidx->uovl, ri)].n;///HiFi reads occ - } - } - idx->raw_uc[i] = ul_n; - - ///buf->o: UL contained reads - ///buf->u: HiFi reads - if(buf->o.n > 0) { - a = buf->o.a; a_n = buf->o.n; - radix_sort_srt64(a, a + a_n); - for (z = 0, k = 1; k <= a_n; k++) { - if(k == a_n || a[z] != a[k]) { - ul_n++; z = k; - } - } - } - if(buf->u.n > 0) { - a = buf->u.a; a_n = buf->u.n; - radix_sort_srt64(a, a + a_n); - for (z = 0, k = 1; k <= a_n; k++) { - if(k == a_n || a[z] != a[k]) { - ug_n++; z = k; - } - } - } - idx->uc[i] = ul_n; idx->hc[i] = ug_n; -} - -ul2ul_t* get_ulg_spec_ovlp(ul_resolve_t *uidx, uint64_t uv, uint64_t uw) -{ - ma_ug_t *iug = uidx->uovl.i_ug; uint32_t qid, tid; - qid = iug->u.a[uv>>1].a[((uv&1)?(0):(iug->u.a[uv>>1].n-1))]>>33; - tid = iug->u.a[uw>>1].a[((uw&1)?(iug->u.a[uw>>1].n-1):(0))]>>33; - - if(uidx->uovl.item_idx[qid] == (uint32_t)-1) return NULL; - ul2ul_item_t *o = &(uidx->uovl.a[uidx->uovl.item_idx[qid]]); uint64_t k; - for (k = 0; k < o->cn; k++) { - if(o->a[k].hid != tid) continue; - return &(o->a[k]); - } - return NULL; -} - - - - - -void gen_raw_ug_seq(ul_resolve_t *uidx, ul_str_t *str, ma_utg_t *u, ma_ug_t *raw, uinfo_srt_warp_t *res, uint64_t iug_id) -{ - uint64_t k, cd, nd, rev, x, os, oe; uinfo_srt_t *p; ma_utg_t *ru; - uc_block_t *xi; ul2ul_t *z = NULL; ul_str_t *c_str; int64_t m, cs, ce; - for (k = 0, res->n = 0; k < u->n; k++) { - cd = u->a[k]>>33; rev = ((u->a[k]>>32)&1); ru = NULL; c_str = NULL; - if(ulg_type(uidx->uovl, cd)) c_str = &(str[ulg_id(uidx->uovl, cd)]); ///ul - else ru = &(raw->u.a[ulg_id(uidx->uovl, cd)]); //ug - - if(c_str) { - if(k + 1 < u->n) { - nd = u->a[k+1]>>33; - z = get_ul_spec_ovlp(&(uidx->uovl), cd, nd); - assert(z && (!z->is_del)); - if(!rev) { - cs = 0; ce = z->qs_k + 1; - } else { - cs = z->qe_k - 1; ce = c_str->cn; - } - } else { - cs = 0; ce = c_str->cn; - } - - if(!rev) { - xi = &(uidx->idx->a[cd].bb.a[c_str->a[cs]>>32]); - x = (uint32_t)c_str->a[cs]; - } else { - xi = &(uidx->idx->a[cd].bb.a[c_str->a[ce-1]>>32]); - x = (uint32_t)c_str->a[ce-1]; x ^= 1; - } - - if(res->n) { - assert((res->a[res->n-1].v) == x); - os = MAX(xi->ts, res->a[res->n-1].s); oe = MIN(xi->te, res->a[res->n-1].e); - assert(oe > os); - os = MIN(xi->ts, res->a[res->n-1].s); oe = MAX(xi->te, res->a[res->n-1].e); - res->a[res->n-1].s = os; res->a[res->n-1].e = oe; - if(!rev) cs++; - else ce--; - } - - if(!rev) { - for (m = cs; m < ce; m++) { - xi = &(uidx->idx->a[cd].bb.a[c_str->a[m]>>32]); - x = (uint32_t)c_str->a[m]; - kv_pushp(uinfo_srt_t, *res, &p); - p->v = x; p->s = xi->ts; p->e = xi->te; - } - } else { - for (m = ce-1; m >= cs; m--) { - xi = &(uidx->idx->a[cd].bb.a[c_str->a[m]>>32]); - x = ((uint32_t)c_str->a[m])^1; - kv_pushp(uinfo_srt_t, *res, &p); - p->v = x; p->s = xi->ts; p->e = xi->te; - } - } - } else if(ru) { - x = ulg_id(uidx->uovl, cd); x <<= 1; if(rev) x^=1; - if(res->n) { - if((!ulg_type(uidx->uovl, (u->a[k-1]>>33)))) {///in previous ul is also a raw utg node - assert(get_specfic_edge(raw->g, res->a[res->n-1].v, x)); - kv_pushp(uinfo_srt_t, *res, &p); - p->v = x; p->s = 0; p->e = ru->len; - } else { - // assert(((res->a[res->n-1].v) == x)); - if(((res->a[res->n-1].v) == x)) { - res->a[res->n-1].s = 0; res->a[res->n-1].e = ru->len; - } else { - assert(get_specfic_edge(raw->g, res->a[res->n-1].v, x)); - kv_pushp(uinfo_srt_t, *res, &p); - p->v = x; p->s = 0; p->e = ru->len; - } - } - } else { - kv_pushp(uinfo_srt_t, *res, &p); - p->v = x; p->s = 0; p->e = ru->len; - } - } - } - - - for (k = 0; k < res->n; k++) { - res->a[k].n = ug_occ_w(res->a[k].s, res->a[k].e, &(raw->u.a[res->a[k].v>>1])); - } -} - - -void renew_u2g_cov(ul_resolve_t *uidx, telo_end_t *te) -{ - ul2ul_idx_t *idx = &(uidx->uovl); uinfo_srt_warp_t *x; - ma_ug_t *i_ug = idx->i_ug, *raw = uidx->l1_ug; uint64_t k, z, iug_occ, m, l, *a, a_n; - free(idx->cc.uc); free(idx->cc.hc); free(idx->cc.raw_uc); - free(idx->cc.iug_idx); free(idx->cc.iug_b); free(idx->cc.iug_a); - if(te) { - free(idx->telo); idx->telo = NULL; - } - memset(&(idx->cc), 0, sizeof(idx->cc)); - - MALLOC(idx->cc.uc, i_ug->u.n); ///number of ul (contained+non-contained) - MALLOC(idx->cc.raw_uc, i_ug->u.n); ///number of ul (non-contained) - MALLOC(idx->cc.hc, i_ug->u.n); ///number of HiFi reads - if(te) MALLOC(idx->telo, i_ug->u.n); ///is telo - - kt_for(uidx->str_b.n_thread, worker_renew_u2g_cov, uidx, i_ug->u.n); - - CALLOC(idx->cc.iug_a, i_ug->u.n); ///integer sequence of each integer unitig - CALLOC(idx->cc.iug_idx, raw->u.n+1); ///idx for integer sequences - // fprintf(stderr, "malloc::[M::%s::] i_ug->u.n:%u\n", __func__, (uint32_t)i_ug->u.n); - for (k = iug_occ = 0; k < i_ug->u.n; k++) { - // fprintf(stderr, "-[M::%s::] k::%lu, i_ug->u.n:%u\n", __func__, k, (uint32_t)i_ug->u.n); - gen_raw_ug_seq(uidx, uidx->pstr.str.a, &(i_ug->u.a[k]), raw, &(idx->cc.iug_a[k]), k); - iug_occ += idx->cc.iug_a[k].n; x = &(idx->cc.iug_a[k]); - for (z = 0; z < x->n; z++) idx->cc.iug_idx[x->a[z].v>>1]++; - - if(te) { - idx->telo[k] = 0; - for (z = 0; z < x->n; z++) { - if(gen_utg_telo(&(raw->u.a[x->a[z].v>>1]), te)) break; - } - if(z < x->n) idx->telo[k] = 1; - } - } - - MALLOC(idx->cc.iug_b, iug_occ); ///idx for integer sequences - for (k = l = 0; k < raw->u.n+1; k++) { - m = idx->cc.iug_idx[k]; - idx->cc.iug_idx[k] = l; - l += m; - if(m > 0) idx->cc.iug_b[l-1] = 0; - } - assert(l == iug_occ); - - for (k = 0; k < i_ug->u.n; k++) { - x = &(idx->cc.iug_a[k]); - for (z = 0; z < x->n; z++) { - a = idx->cc.iug_b + idx->cc.iug_idx[x->a[z].v>>1]; - a_n = idx->cc.iug_idx[(x->a[z].v>>1)+1] - idx->cc.iug_idx[x->a[z].v>>1]; - if(a_n) { - if(a[a_n-1] == a_n-1) a[a_n-1] = (k<<32)|z;///id of unitig | offset within the unitig - else a[a[a_n-1]++] = (k<<32)|z; - } - } - } -} - -static void worker_renew_integer_bridge(void *data, long i, int tid) // callback for kt_for() -{ - ul_resolve_t *uidx = (ul_resolve_t *)data; bubble_type *bub = uidx->bub; - asg_t *bg = uidx->uovl.bg.bg; ul_str_idx_t *str_idx = &(uidx->pstr); - asg_arc_t *p = &(bg->arc[i]); uint64_t *hid_a, hid_n, z; ul_str_t *str; - uint32_t v = p->ul>>32, w = p->v, vz, wz; int64_t s, s_n, occ = 0; - - hid_a = str_idx->occ.a + str_idx->idx.a[v>>1]; - hid_n = str_idx->idx.a[(v>>1)+1] - str_idx->idx.a[v>>1]; - for (z = 0; z < hid_n; z++) { - str = &(str_idx->str.a[hid_a[z]>>32]); s_n = str->cn; - if(s_n < 2) continue; - vz = (uint32_t)(str->a[(uint32_t)hid_a[z]]); - assert((v>>1) == (vz>>1)); - s = (uint32_t)hid_a[z]; s -= 1; vz = ((uint32_t)(str->a[(uint32_t)hid_a[z]]))^1; - for (; s >= 0; s--) { - wz = (uint32_t)(str->a[s]); wz ^= 1; - if(IF_HOM((wz>>1), *bub)) continue; - if(vz == v && wz == w) occ++; - else if(vz == (v^1) && wz == (w^1)) occ++; - break; - } - - s = (uint32_t)hid_a[z]; s += 1; vz = (uint32_t)(str->a[(uint32_t)hid_a[z]]); - for (; s < s_n; s++) { - wz = (uint32_t)(str->a[s]); - if(IF_HOM((wz>>1), *bub)) continue; - if(vz == v && wz == w) occ++; - else if(vz == (v^1) && wz == (w^1)) occ++; - break; - } - } - p->ol = occ; p->ul >>= 32; p->ul <<= 32; p->ul += (((uint32_t)-1) - p->ol); -} - -void renew_u2g_bg(ul_resolve_t *uidx) -{ - ul2ul_idx_t *idx = &(uidx->uovl); ul_bg_t *bg = &(idx->bg); - ma_ug_t *iug = idx->i_ug, *raw = uidx->l1_ug; bubble_type *bub = uidx->bub; - uint64_t k, z, l, *raw_a, raw_n, raw_id, iug_id, iug_off, v, w, nv, nw, n_vtx; - uinfo_srt_warp_t *x; asg64_v buf = {0,0,0}; int64_t s, s_n; asg_arc_t *p, *av, *aw; - asg_destroy(bg->bg); free(bg->w_n); free(bg->a_n); memset(bg, 0, sizeof((*bg))); - - bg->bg = asg_init(); - bg->bg->n_seq = 0; bg->bg->m_seq = raw->g->n_seq; MALLOC(bg->bg->seq, bg->bg->m_seq); - for (k = 0; k < raw->g->n_seq; k++) { - raw_id = k; - if(IF_HOM(raw_id, *bub)) {///updated-line - // asg_seq_set(bg->bg, k, raw->g->seq[k].len, 1); - // bg->bg->seq[k].c = 0; - continue; - } - raw_a = idx->cc.iug_b + idx->cc.iug_idx[raw_id]; - raw_n = idx->cc.iug_idx[raw_id+1] - idx->cc.iug_idx[raw_id]; - for (z = 0, buf.n = 0; z < raw_n; z++) { - iug_id = raw_a[z]>>32; iug_off = (uint32_t)raw_a[z]; - x = &(idx->cc.iug_a[iug_id]); s_n = x->n; - assert(raw_id == (x->a[iug_off].v>>1)); - if(iug->g->seq[iug_id].del) continue; - for (s = ((int64_t)iug_off) - 1, v = x->a[iug_off].v^1; s >= 0; s--) { - if(IF_HOM((x->a[s].v>>1), *bub)) continue; - kv_push(uint64_t, buf, ((v<<32)|((uint64_t)(x->a[s].v^1)))); - break; - } - for (s = ((int64_t)iug_off) + 1, v = x->a[iug_off].v; s < s_n; s++) { - if(IF_HOM((x->a[s].v>>1), *bub)) continue; - kv_push(uint64_t, buf, ((v<<32)|((uint64_t)(x->a[s].v)))); - break; - } - } - - asg_seq_set(bg->bg, k, raw->g->seq[k].len, ((buf.n>0)?0:1)); - bg->bg->seq[k].c = 0; - - radix_sort_srt64(buf.a, buf.a + buf.n); - for (l = 0, z = 1; z <= buf.n; z++) { - if(z == buf.n || buf.a[l] != buf.a[z]) { - p = asg_arc_pushp(bg->bg); memset(p, 0, sizeof(*p)); - p->v = (uint32_t)buf.a[l]; p->ol = z - l; - p->ul = buf.a[l]>>32; p->ul <<= 32; - p->ul += (((uint32_t)-1) - p->ol); - l = z; - } - } - } - - kt_for(uidx->str_b.n_thread, worker_renew_integer_bridge, uidx, bg->bg->n_arc); - asg_cleanup(bg->bg); bg->bg->r_seq = bg->bg->n_seq; - - /***********debug***********/ - for (k = 0; k < bg->bg->n_arc; k++) { - p = &(bg->bg->arc[k]); v = p->v^1; w = (p->ul>>32)^1; - av = asg_arc_a(bg->bg, v); nv = asg_arc_n(bg->bg, v); - for (z = 0; z < nv; z++) { - if(av[z].v == w) break; - } - assert(z < nv && p->ol == av[z].ol); - } - /***********debug***********/ - - uint64_t v_occ[2], w_occ[2]; double ss = 0.500001; - for (v = 0, n_vtx = bg->bg->n_seq<<1; v < n_vtx; v++) { - if(bg->bg->seq[v>>1].del) continue; - av = asg_arc_a(bg->bg, v); nv = asg_arc_n(bg->bg, v); - if(!nv) continue; w = av[0].v; - v_occ[0] = v_occ[1] = w_occ[0] = w_occ[1] = (uint32_t)-1; - - av = asg_arc_a(bg->bg, v); nv = asg_arc_n(bg->bg, v); - for (k = 0; k < nv && k < 2; k++) { - v_occ[k] = av[k].ol; v_occ[k] <<= 32; v_occ[k] += av[k].v; - } - - aw = asg_arc_a(bg->bg, (w^1)); nw = asg_arc_n(bg->bg, (w^1)); - for (k = 0; k < nw && k < 2; k++) { - w_occ[k] = aw[k].ol; w_occ[k] <<= 32; w_occ[k] += aw[k].v; - } - - if((((uint32_t)v_occ[0]) == w) && (((uint32_t)w_occ[0]) == (v^1))) { - if(((((v_occ[0]>>32)*ss) >= (v_occ[1]>>32)) && (((w_occ[0]>>32)*ss) >= (w_occ[1]>>32))) || - ((((v_occ[0]>>32)+(w_occ[0]>>32))*ss) >= ((v_occ[1]>>32)+(w_occ[1]>>32)))) { - for (k = 0; k < nv; k++) av[k].ou = 2;///wrong - for (k = 0; k < nw; k++) aw[k].ou = 2;///wrong - av[0].ou = aw[0].ou = 3;//correct - } else { - for (k = 0; k < nv; k++) av[k].ou = 1;///ambg - for (k = 0; k < nw; k++) aw[k].ou = 1;///ambg - } - } - } - - for (k = 0; k < bg->bg->n_arc; k++) { - p = &(bg->bg->arc[k]); v = p->v^1; w = (p->ul>>32)^1; - av = asg_arc_a(bg->bg, v); nv = asg_arc_n(bg->bg, v); - for (z = 0; z < nv; z++) { - if(av[z].v == w) break; - } - assert(z < nv && p->ol == av[z].ol); - l = MAX(p->ou, av[z].ou); if(l == 0) l = 1; - p->ou = av[z].ou = l; - } - - - MALLOC(bg->w_n, iug->u.n); MALLOC(bg->a_n, iug->u.n); - for (k = 0; k < iug->u.n; k++) { - x = &(idx->cc.iug_a[k]); bg->w_n[k] = bg->a_n[k] = 0; - for (z = nv = 0; z < x->n; z++) { - if(IF_HOM((x->a[z].v>>1), *bub)) continue; - v_occ[nv&1] = x->a[z].v; nv++; - if(nv < 2) continue; - l = get_bg_flag(uidx, v_occ[(nv-2)&1], v_occ[(nv-1)&1]); - assert(l != bg_unavailable); - if(l == bg_wrong) bg->w_n[k]++; - if(l == bg_ambiguous) bg->a_n[k]++; - } - // fprintf(stderr, "-[M::%s::] k::%lu, x->n::%u, w_n[k]::%u, a_n[k]::%u\n", - // __func__, k, (uint32_t)x->n, bg->w_n[k], bg->a_n[k]); - } - - kv_destroy(buf); -} - -/** -static void worker_update_ul_tra_idx(void *data, long i, int tid) // callback for kt_for() -{ - ul_resolve_t *uidx = (ul_resolve_t *)data; integer_t *buf = &(uidx->str_b.buf[tid]); - ma_ug_t *iug = uidx->uovl.i_ug; ul_tra_idx_t *iug_tra = &(uidx->uovl.iug_tra); - uint32_t v = i, n_tra = iug_tra_arc_n(iug_tra, v), nv, k; - if(n_tra == 0) return; - ul_tra_t *a_tra = iug_tra_arc_a(iug_tra, v); asg_arc_t *av; - - av = asg_arc_a(iug->g, v); nv = asg_arc_n(iug->g, v); kv_resize(uint64_t, buf->u, 2); - for (k = 0; k < nv; k++) { - buf->u.n = 0; buf->u.a[buf->u.n++] = v; buf->u.a[buf->u.n++] = av[k].v; - } -} - -void update_ul_tra_idx_t(ul_resolve_t *uidx) -{ - ma_ug_t *iug = uidx->uovl.i_ug; ul_tra_idx_t *iug_tra = &(uidx->uovl.iug_tra); - uint64_t v, n_vtx = iug->g->n_seq<<1, l, m; - iug_tra->arc.n = iug_tra->idx.n = 0; - kv_resize(uint32_t, iug_tra->idx, n_vtx + 1); iug_tra->idx.n = n_vtx + 1; - memset(iug_tra->idx.a, 0, iug_tra->idx.n *sizeof(*(iug_tra->idx.a))); - for (v = l = 0; v < n_vtx; v++) { - m = asg_arc_n(iug->g, v); - if(m < 2) m = 0; - iug_tra->idx.a[v] = l; - l += m; - } - iug_tra->idx.a[v] = l; - kv_resize(ul_tra_t, iug_tra->arc, l); iug_tra->arc.n = l; - - kt_for(uidx->str_b.n_thread, worker_update_ul_tra_idx, uidx, n_vtx);///all ul + ug -} -**/ -void renew_ul2_utg(ul_resolve_t *uidx) -{ - ul2ul_idx_t *z = &(uidx->uovl); - if(uidx->uovl.cc.iug_a) { - uint32_t k; - for (k = 0; k < z->i_ug->u.n; k++) free(uidx->uovl.cc.iug_a[k].a); - } - renew_utg(&(z->i_ug), z->i_g, NULL); - free(z->i_ug->g->seq_vis); CALLOC(z->i_ug->g->seq_vis, z->i_ug->g->n_seq*2); - renew_u2g_cov(uidx, uidx->uopt->te); - renew_u2g_bg(uidx); -} - - -ul2ul_idx_t *gen_ul2ul(ul_resolve_t *uidx, ug_opt_t *uopt, ulg_opt_t *ulopt, uint32_t keep_raw_utg, uint64_t is_bridg) -{ - uint64_t k, m; - ma_ug_t *ug = uidx->l1_ug; all_ul_t *uls = uidx->idx; - ul2ul_idx_t *z = &(uidx->uovl); ul_str_idx_t *str_idx = &(uidx->pstr); - z->uln = uls->n; z->gn = ug->g->n_seq; - z->tot = uls->n + ug->g->n_seq; MALLOC(z->item_idx, z->tot); - for (k = m = 0; k < z->tot; k++) { - z->item_idx[k] = (uint32_t)-1; - if(k < z->uln) {///is a ul read - if(str_idx->str.a[k].cn > 1) { - z->item_idx[k] = m; m++; - } - } else {//is a node in graph - z->item_idx[k] = m; m++; - } - } - CALLOC(z->a, m); z->n = z->m = m; - - kt_for(uidx->str_b.n_thread, worker_integer_postprecess, uidx, uls->n); - gen_integer_normalize(uidx); - - chimeric_integer_deal(uidx); - append_utg_es(uidx); - - - kt_for(uidx->str_b.n_thread, worker_integert_debug_sym, uidx, z->tot);///all ul + ug - print_integert_ovlp_stat(z); - remove_integert_containment(uidx, keep_raw_utg); - - kt_for(uidx->str_b.n_thread, worker_integert_debug_sym, uidx, z->tot);///all ul + ug - print_integert_ovlp_stat(z); - // print_uls_seq(uidx, asm_opt.output_file_name); - // print_uls_ovs(uidx, asm_opt.output_file_name); - - z->i_g = integer_sg_gen(uidx, uopt->min_ovlp); - asg_arc_del_trans(z->i_g, uopt->gap_fuzz); - - z->i_ug = ma_ug_gen(z->i_g); - // CALLOC(z->i_ug->g->seq_vis, z->i_ug->g->n_seq*2); - renew_u2g_cov(uidx, uidx->uopt->te); - renew_u2g_bg(uidx); - - // output_integer_graph(uidx, z->i_ug, asm_opt.output_file_name); - u2g_clean(uidx, ulopt, keep_raw_utg, is_bridg); - // renew_ul2_utg(uidx); - - // output_integer_graph(uidx, z->i_ug, asm_opt.output_file_name, 0); - return z; -} - -uint64_t str_occ_w(ul_str_t *str, ul_vec_t *raw, ma_ug_t *ug) -{ - uint64_t occ, k; uc_block_t *z; - for (k = occ = 0; k < str->cn; k++) { - z = &(raw->bb.a[str->a[k]>>32]); - assert(((z->hid<<1)+z->rev)==((uint32_t)str->a[k])); - occ += ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); - } - return occ; -} - -void gen_cul_g_t(ul_resolve_t *uidx) -{ - ma_ug_t *ug = uidx->l1_ug; uint64_t k; ul_str_idx_t *str_idx = &(uidx->pstr); - CALLOC(uidx->cg, 1); - uidx->cg->n[0] = uidx->idx->n; uidx->cg->n[1] = ug->g->n_seq; - uidx->cg->tot = uidx->cg->n[0] + uidx->cg->n[1]; - uidx->cg->g = asg_init(); - for (k = 0; k < uidx->cg->tot; k++) { - if(k < uidx->cg->n[0]) { - asg_seq_set(uidx->cg->g, k, str_occ_w(&(str_idx->str.a[k]), &(uidx->idx->a[k]), ug), - ((str_idx->str.a[k].cn>1)?0:1)); - } else { - asg_seq_set(uidx->cg->g, k, ug->u.a[k-uidx->cg->n[0]].n, 0); - } - } -} - -void init_ulg_opt_t(ulg_opt_t *z, ug_opt_t *uopt, int64_t clean_round, -double min_path_drop_ratio, double max_path_drop_ratio, -double min_ovlp_drop_ratio, double max_ovlp_drop_ratio, double hom_check_drop_rate, -int64_t max_tip, int64_t max_tip_hifi, bub_label_t *b_mask_t, uint32_t is_trio) -{ - z->tipsLen = uopt->tipsLen; - z->tip_drop_ratio = uopt->tip_drop_ratio; - z->stops_threshold = uopt->stops_threshold; - z->chimeric_rate = uopt->chimeric_rate; - z->drop_ratio = uopt->drop_ratio; - - - z->b_mask_t = b_mask_t; - z->clean_round = clean_round; - z->min_path_drop_ratio = min_path_drop_ratio; - z->max_path_drop_ratio = max_path_drop_ratio; - z->min_ovlp_drop_ratio = min_ovlp_drop_ratio; - z->max_ovlp_drop_ratio = max_ovlp_drop_ratio; - z->hom_check_drop_rate = hom_check_drop_rate; - z->max_tip = max_tip; - z->max_tip_hifi = max_tip_hifi; - z->is_trio = is_trio; -} - -ma_ug_t* output_trio_unitig_graph_ul(ug_opt_t *uopt, ul_resolve_t *uidx, char* ou, uint8_t flag) -{ - char* gfa_name; MALLOC(gfa_name, strlen(ou)+100); - sprintf(gfa_name, "%s.%s.p_ctg.gfa", ou, (flag==FATHER?"hap1":"hap2")); - FILE* output_file = fopen(gfa_name, "w"); - - ma_ug_t *ug = copy_untig_graph(uidx->uovl.hybrid_ug); - kvec_asg_arc_t_warp ne; kv_init(ne.a); - - adjust_utg_by_trio(&ug, uidx->sg, flag, TRIO_THRES, uopt->sources, uopt->reverse_sources, - uopt->coverage_cut, uopt->tipsLen, uopt->tip_drop_ratio, uopt->stops_threshold, uopt->ruIndex, - uopt->chimeric_rate, uopt->drop_ratio, uopt->max_hang, uopt->min_ovlp, uopt->gap_fuzz, &ne, uopt->b_mask_t); - - // if(asm_opt.b_low_cov > 0) { - // break_ug_contig(&ug, uidx->sg, &R_INF, uopt->coverage_cut, uopt->sources, uopt->ruIndex, &ne, - // uopt->max_hang, uopt->min_ovlp, &asm_opt.b_low_cov, NULL, asm_opt.m_rate); - // } - - // if(asm_opt.b_high_cov > 0) - // { - // break_ug_contig(&ug, uidx->sg, &R_INF, uopt->coverage_cut, uopt->sources, uopt->ruIndex, &ne, - // uopt->max_hang, uopt->min_ovlp, NULL, &asm_opt.b_high_cov, asm_opt.m_rate); - // } - - fprintf(stderr, "Writing %s to disk... \n", gfa_name); - ma_ug_seq(ug, uidx->sg, uopt->coverage_cut, uopt->sources, &ne, uopt->max_hang, uopt->min_ovlp, 0, 1); - - ma_ug_print(ug, uidx->sg, uopt->coverage_cut, uopt->sources, uopt->ruIndex, (flag==FATHER?"h1tg":"h2tg"), output_file); - fclose(output_file); - - sprintf(gfa_name, "%s.%s.p_ctg.noseq.gfa", ou, (flag==FATHER?"hap1":"hap2")); - output_file = fopen(gfa_name, "w"); - ma_ug_print_simple(ug, uidx->sg, uopt->coverage_cut, uopt->sources, uopt->ruIndex, (flag==FATHER?"h1tg":"h2tg"), output_file); - fclose(output_file); - // if(asm_opt.bed_inconsist_rate != 0) - // { - // sprintf(gfa_name, "%s.%s.p_ctg.lowQ.bed", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); - // output_file = fopen(gfa_name, "w"); - // ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, - // max_hang, min_ovlp, asm_opt.bed_inconsist_rate, (flag==FATHER?"h1tg":"h2tg"), output_file, NULL); - // fclose(output_file); - // } - - free(gfa_name); - ma_ug_destroy(ug); - kv_destroy(ne.a); - return NULL; -} - - - -void realloc_rdb(All_reads* rdb, ma_sub_t **cov, R_to_U *ruI, uint64_t *rmap, uint64_t rid_n, uint64_t scaf_len, char *scaf_id, -asg_t *ng, ug_opt_t *uopt) -{ - uint64_t i, rid_n0 = rdb->total_reads, tname, cname; - uint64_t scaf_id_len = strlen(scaf_id); char *des, *src; - rdb->total_reads = rid_n; - tname = rdb->name_index[rid_n0]; - fprintf(stderr, "+[M::%s] rid_n0::%lu, rid_n::%lu\n", __func__, rid_n0, rid_n); - ///for read bases - REALLOC(rdb->N_site, rdb->total_reads); - REALLOC(rdb->read_length, rdb->total_reads); - REALLOC(rdb->read_size, rdb->total_reads); - REALLOC(rdb->read_sperate, rdb->total_reads); - REALLOC(rdb->trio_flag, rdb->total_reads); - REALLOC(rdb->name_index, rdb->total_reads+1);///total_reads+1 - REALLOC((*cov), rdb->total_reads); - for (i = rid_n0; i < rdb->total_reads; i++) { - // fprintf(stderr, "[M::%s] i::%lu\n", __func__, i); - rdb->N_site[i] = NULL; - rdb->read_length[i] = scaf_len; - rdb->read_size[i] = scaf_len; - rdb->trio_flag[i] = AMBIGU; - (*cov)[i].c = (*cov)[i].del = 0; - (*cov)[i].s = 0; (*cov)[i].e = scaf_len; - cname = scaf_id_len; - if(rmap[i] != ((uint64_t)-1)) {///not a scaffold node - if(rdb->N_site[rmap[i]] != NULL) { - MALLOC(rdb->N_site[i], rdb->N_site[rmap[i]][0]+1); - memcpy(rdb->N_site[i], rdb->N_site[rmap[i]], - sizeof((*(rdb->N_site[i])))*(rdb->N_site[rmap[i]][0]+1)); - } - rdb->read_length[i] = rdb->read_length[rmap[i]]; - rdb->read_size[i] = rdb->read_length[rmap[i]]; - rdb->trio_flag[i] = rdb->trio_flag[rmap[i]]; - (*cov)[i] = (*cov)[rmap[i]]; - cname = Get_NAME_LENGTH((*rdb), (rmap[i])); - } - rdb->name_index[i] = tname; tname += cname; - rdb->total_reads_bases += rdb->read_length[i]; - - MALLOC(rdb->read_sperate[i], (rdb->read_length[i]/4+1)); - if(rmap[i] != ((uint64_t)-1)) {///not a scaffold node - memcpy(rdb->read_sperate[i], rdb->read_sperate[rmap[i]], - sizeof((*(rdb->read_sperate[i])))*(rdb->read_length[i]/4+1)); - } else { - ///set to A - memset(rdb->read_sperate[i], 0, sizeof((*(rdb->read_sperate[i])))*(rdb->read_length[i]/4+1)); - } - } - - rdb->index_size = rdb->total_reads; - rdb->name_index[i] = tname; - rdb->total_name_length = tname; - rdb->name_index_size = rdb->total_reads+1; - REALLOC(rdb->name, tname); - for (i = rid_n0; i < rdb->total_reads; i++) { - des = Get_NAME((*rdb), i); src = scaf_id; cname = scaf_id_len; - if(rmap[i] != ((uint64_t)-1)) { - src = Get_NAME((*rdb), rmap[i]); cname = Get_NAME_LENGTH((*rdb), (rmap[i])); - } - memcpy(des, src, sizeof((*(des)))*cname); - } - - REALLOC(rdb->paf, rdb->total_reads); - memset(rdb->paf+rid_n0, 0, (rdb->total_reads-rid_n0)*sizeof((*rdb->paf))); - REALLOC(rdb->reverse_paf, rdb->total_reads); - memset(rdb->reverse_paf+rid_n0, 0, (rdb->total_reads-rid_n0)*sizeof((*rdb->reverse_paf))); - - ruI->len = rdb->total_reads; - REALLOC(ruI->index, ruI->len); - memset(ruI->index, -1, sizeof((*(ruI->index)))*(ruI->len)); - - reset_bub_label_t(uopt->b_mask_t, ng, 0, 0); - uopt->coverage_cut = (*cov); - uopt->reverse_sources = rdb->reverse_paf; - uopt->sources = rdb->paf; - fprintf(stderr, "-[M::%s] rid_n0::%lu, rid_n::%lu\n", __func__, rid_n0, rid_n); -} - -inline void update_qtn(ma_hit_t *z, uint64_t qn, uint64_t tn) -{ - z->qns <<= 32; z->qns >>= 32; z->qns |= (qn<<32); z->tn = tn; -} - -inline uint64_t dup_paf_check(ma_hit_t_alloc *x, ma_hit_t *p) -{ - int64_t i; ma_hit_t *z; - for (i = 0; i < x->length; i++) { - z = &(x->buffer[i]); - if((z->qns == p->qns) && (z->tn == p->tn) && (z->qe == p->qe) && (z->ts == p->ts) && (z->te == p->te) && - (z->cc == p->cc) && (z->ml == p->ml) && (z->rev == p->rev) && (z->bl == p->bl) && (z->del == p->del) && - (z->el == p->el) && (z->no_l_indel == p->no_l_indel)) { - return 0; - } - } - return 1; -} - -void renew_paf0(ma_hit_t_alloc *paf, uint64_t *a0, uint64_t a0n, uint64_t *a1, uint64_t a1n, asg64_v *buf) -{ - if(a0n <= 1 && a1n <= 1) return; - uint64_t qn = ((uint32_t)a0[0]), tn = ((uint32_t)a1[0]), i, k, sf = 0; - ma_hit_t e01, e10; uint64_t qi, ti, *qa, *ta, qlen, tlen; buf->n = 0; ma_hit_t_alloc *qo, *to; - if(qn == tn) sf = 1; - qo = &(paf[qn]); qi = qo->length; - for (i = qlen = 0, qa = NULL; i < qi; i++) { - if(qo->buffer[i].tn == tn) kv_push(uint64_t, *buf, i); - } - qlen = buf->n; - - to = &(paf[tn]); ti = to->length; - for (i = tlen = 0, ta = NULL; i < ti; i++) { - if(to->buffer[i].tn == qn) kv_push(uint64_t, *buf, i); - } - tlen = buf->n - qlen; - assert(qlen && tlen); - qa = buf->a; ta = buf->a + qlen; - - for (qi = 0; qi < qlen; qi++) { - e01 = qo->buffer[qa[qi]]; - for (ti = 0; ti < tlen; ti++) { - e10 = to->buffer[ta[ti]]; - - for (i = 0; i < a0n; i++) { - qn = ((uint32_t)a0[i]); - for (k = 0; k < a1n; k++) { - if(i == 0 && k == 0) continue; - tn = ((uint32_t)a1[k]); - - update_qtn(&e01, qn, tn); - if((!sf) || (dup_paf_check(&(paf[qn]), &e01))) { - add_ma_hit_t_alloc(&(paf[qn]), &e01); - } - - update_qtn(&e10, tn, qn); - if((!sf) || (dup_paf_check(&(paf[tn]), &e10))) { - add_ma_hit_t_alloc(&(paf[tn]), &e10); - } - } - } - } - } - - /** - idx = get_specific_overlap(&(paf[qn]), qn, tn); - if(idx < 0) return; - e01 = paf[qn].buffer[idx]; - idx = get_specific_overlap(&(paf[tn]), tn, qn); - e10 = paf[tn].buffer[idx]; - - for (i = 0; i < a0n; i++) { - qn = ((uint32_t)a0[i]); - for (k = 0; k < a1n; k++) { - if(i == 0 && k == 0) continue; - tn = ((uint32_t)a1[k]); - if((qn == 5619628 && tn == 5619629) || (tn == 5619628 && qn == 5619629)) { - fprintf(stderr, "[M::%s]\tqn::%lu(qg::%u)\ttn::%lu(tg::%u)\n", __func__, - qn, ((uint32_t)a0[0]), tn, ((uint32_t)a1[0])); - } - update_qtn(&e01, qn, tn); add_ma_hit_t_alloc(&(paf[qn]), &e01); - update_qtn(&e10, tn, qn); add_ma_hit_t_alloc(&(paf[tn]), &e10); - } - } - **/ -} - -void renew_paf1(ma_hit_t_alloc *paf, uint64_t *a, uint64_t an, uint64_t len) -{ - uint64_t i, k, qn, tn; ma_hit_t arc; - arc.qns = 0; arc.qe = len; - arc.tn = 0; arc.ts = 0; arc.te = len; - arc.rev = arc.el = arc.ml = arc.no_l_indel = arc.bl = 0; - - for (i = 0; i < an; i++) { - qn = ((uint32_t)a[i]); - for (k = 0; k < an; k++) { - tn = ((uint32_t)a[k]); - update_qtn(&arc, qn, tn); - add_ma_hit_t_alloc(&(paf[qn]), &arc); - } - } -} - -void update_paf(ma_hit_t_alloc *src, ma_hit_t_alloc *r_src, uint64_t *rmap, uint64_t rid_n, uint64_t pre_gn, asg_t *ng) -{ - asg64_v clus, bb; uint64_t k, l, dn = 0, j, qn, tn; - uint64_t *idx; ma_hit_t_alloc *z; - uint64_t *a0, *a1, a0n, a1n; - CALLOC(idx, pre_gn); kv_init(bb); - kv_init(clus); kv_resize(uint64_t, clus, rid_n); - for (k = 0; k < rid_n; k++) { - if(rmap[k] == ((uint64_t)-1)) continue;///scaffold - clus.a[clus.n++] = (rmap[k]<<32)|k; - } - radix_sort_srt64(clus.a, clus.a+clus.n); - for (k = 1, l = 0; k <= clus.n; k++) { - if(k == clus.n || (clus.a[k]>>32) != (clus.a[l]>>32)) { - idx[(clus.a[l]>>32)] = (l<<32)|k; - l = k; dn++; - } - } - assert(dn == pre_gn); - fprintf(stderr, "+[M::%s] dn::%lu\n", __func__, dn); - - for (k = 0; k < dn; k++) { - a0 = clus.a + (idx[k]>>32); a0n = ((uint32_t)idx[k]) - (idx[k]>>32); - assert(a0n > 0 && ((uint32_t)a0[0]) == k); - // if(k == 4265018) { - // fprintf(stderr, "\n[M::%s]\tgroup::%lu\n", __func__, k); - // for (j = 0; j < a0n; j++) { - // fprintf(stderr, "[M::%s]\tnid::%uu\n", __func__, (uint32_t)a0[j]); - // } - // } - z = &(src[k]); - for (j = 0; j < z->length; j++) { - qn = Get_qn(z->buffer[j]); - tn = Get_tn(z->buffer[j]); - if(tn >= dn) continue; - if(qn > tn) continue; - a1 = clus.a + (idx[tn]>>32); - a1n = ((uint32_t)idx[tn]) - (idx[tn]>>32); - // fprintf(stderr, "+[M::%s] qn::%lu, tn::%lu, a0n::%lu, a1n::%lu\n", __func__, qn, tn, a0n, a1n); - assert(a1n > 0 && ((uint32_t)a1[0]) == tn); - renew_paf0(src, a0, a0n, a1, a1n, &bb); - } - - z = &(r_src[k]); - for (j = 0; j < z->length; j++) { - qn = Get_qn(z->buffer[j]); - tn = Get_tn(z->buffer[j]); - if(tn >= dn) continue; - if(qn > tn) continue; - a1 = clus.a + (idx[tn]>>32); - a1n = ((uint32_t)idx[tn]) - (idx[tn]>>32); - // fprintf(stderr, "-[M::%s] qn::%lu, tn::%lu, a0n::%lu, a1n::%lu\n", __func__, qn, tn, a0n, a1n); - assert(a1n > 0 && ((uint32_t)a1[0]) == tn); - renew_paf0(r_src, a0, a0n, a1, a1n, &bb); - } - - - - // for (l = k; l < dn; l++) { - // a1 = clus.a + (idx[l]>>32); a1n = ((uint32_t)idx[l]) - (idx[l]>>32); - // fprintf(stderr, "[M::%s] k::%lu, l::%lu, a0n::%lu, a1n::%lu\n", __func__, k, l, a0n, a1n); - // assert(a1n > 0 && ((uint32_t)a1[0]) == l); - // renew_paf0(src, a0, a0n, a1, a1n); - // renew_paf0(r_src, a0, a0n, a1, a1n); - // } - if(a0n > 1) renew_paf1(r_src, a0, a0n, ng->seq[k].len); - } - free(idx); free(clus.a); free(bb.a); -} - -void push_scaff_node(ma_hit_t_alloc *src, uint64_t v, uint64_t w, uint64_t ol, asg_t *ng) -{ - uint64_t vl = ng->seq[v>>1].len, wl = ng->seq[w>>1].len; - ma_hit_t arc, arc1; - arc.qns = (v>>1)<<32; - if(!(v&1)) { - arc.qns += vl - ol; arc.qe = vl; - } else { - arc.qns += 0; arc.qe = ol; - } - arc.tn = w>>1; - if(!(w&1)) { - arc.ts = 0; arc.te = ol; - } else { - arc.ts = wl - ol; arc.te = wl; - } - - arc.rev = (v^w)&1; arc.el = 0; - arc.ml = arc.no_l_indel = arc.bl = 0; - - add_ma_hit_t_alloc(&(src[v>>1]), &arc); - set_reverse_overlap(&arc1, &arc); - add_ma_hit_t_alloc(&(src[w>>1]), &arc1); -} - -asg_t *gen_ng(ma_ug_t *ug, asg_t *sg, ug_opt_t *uopt, ma_sub_t **cov, R_to_U *ruI, -uint64_t scaffold_len) -{ - ma_utg_t *u; uint64_t i, v, w, m, h, z, raw_v, raw_w, nocc, nv, vx, wx; int32_t r; - asg_arc_t t, *p; asg_arc_t *av = NULL; uint64_t slen = scaffold_len + (uopt->min_ovlp*2); - asg_ext_t ext; memset(&ext, 0, sizeof(ext)); ext.ext = asg_init(); asg_t *ng = ext.ext; - ext.a_n = sg->n_seq; - ext.cnt.n = ext.cnt.m = ext.a_n; - CALLOC(ext.cnt.a, ext.cnt.n);///count - - ext.idx_a.n = ext.idx_a.m = sg->n_seq; - MALLOC(ext.idx_a.a, ext.idx_a.n); - memset(ext.idx_a.a, -1, sizeof(*(ext.idx_a.a))*ext.idx_a.n);//map - fprintf(stderr, "\n+[M::%s] 0\n", __func__); - - for (i = 0; i < ug->g->n_seq; ++i) { - u = &(ug->u.a[i]); - for (m = 0; m < u->n; m++) { - v = u->a[m]>>32; - ext.cnt.a[v>>1]++; - if(ext.cnt.a[v>>1] == 1) { - h = v>>1; ext.idx_a.a[h] = v>>1; - } else { - h = ext.idx_a.n; - kv_push(uint64_t, ext.idx_a, (v>>1)); - } - - z = (h<<1)|(v&1); z <<= 32; z |= ((uint32_t)u->a[m]); - u->a[m] = z; - } - } - - for (i = 0; i < sg->n_seq; ++i) { - asg_seq_set(ng, i, sg->seq[i].len, ext.idx_a.a[i]==((uint64_t)-1)?1:0); - ng->seq[i].c = 0; - if(ext.idx_a.a[i]!=((uint64_t)-1)) assert(ext.idx_a.a[i] == i); - ext.idx_a.a[i] = i;///set for delted read - } - for (; i < ext.idx_a.n; i++) { - asg_seq_set(ng, i, sg->seq[ext.idx_a.a[i]].len, 0); - ng->seq[i].c = 0; assert(!(ng->seq[ext.idx_a.a[i]].del)); - } - ng->r_seq = ng->n_seq; - // fprintf(stderr, "+[M::%s] ng->n_seq::%u, ext.idx_a.n::%u\n", - // __func__, (uint32_t)ng->n_seq, (uint32_t)ext.idx_a.n); - assert(ng->n_seq == ext.idx_a.n); - fprintf(stderr, "\n+[M::%s] 1\n", __func__); - - for (i = 0, nocc = ng->r_seq; i < ug->g->n_seq; ++i) { - u = &(ug->u.a[i]); - for (m = 1; m < u->n; m++) { - v = u->a[m-1]>>32; w = u->a[m]>>32; - raw_v = (ext.idx_a.a[v>>1]<<1)|(v&1); - raw_w = (ext.idx_a.a[w>>1]<<1)|(w&1); - assert((raw_v>>1) < sg->n_seq); - assert((raw_w>>1) < sg->n_seq); - if(gen_spec_edge(sg, uopt, raw_v, raw_w, &t) < 0) { - asg_seq_set(ng, nocc, slen, 0); - ng->seq[nocc].c = 0; - kv_push(uint64_t, ext.idx_a, ((uint64_t)-1)); - nocc++;///a scaffold node - } - } - - v = i<<1; nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); - for (m = 0; m < nv; m++) { - if(av[m].del) continue; - w = av[m].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)); - raw_v = (ext.idx_a.a[vx>>1]<<1)|(vx&1); - raw_w = (ext.idx_a.a[wx>>1]<<1)|(wx&1); - assert((raw_v>>1) < sg->n_seq); - assert((raw_w>>1) < sg->n_seq); - if(vx > wx) continue; - if((vx == wx) && (vx&1)) continue; - if(gen_spec_edge(sg, uopt, raw_v, raw_w, &t) < 0) { - asg_seq_set(ng, nocc, slen, 0); - ng->seq[nocc].c = 0; - kv_push(uint64_t, ext.idx_a, ((uint64_t)-1)); - nocc++;///a scaffold node - } - } - - v = (i<<1)+1; nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); - for (m = 0; m < nv; m++) { - if(av[m].del) continue; - w = av[m].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)); - raw_v = (ext.idx_a.a[vx>>1]<<1)|(vx&1); - raw_w = (ext.idx_a.a[wx>>1]<<1)|(wx&1); - assert((raw_v>>1) < sg->n_seq); - assert((raw_w>>1) < sg->n_seq); - if(vx > wx) continue; - if((vx == wx) && (vx&1)) continue; - if(gen_spec_edge(sg, uopt, raw_v, raw_w, &t) < 0) { - asg_seq_set(ng, nocc, slen, 0); - ng->seq[nocc].c = 0; - kv_push(uint64_t, ext.idx_a, ((uint64_t)-1)); - nocc++;///a scaffold node - } - } - } - fprintf(stderr, "\n+[M::%s] 2\n", __func__); - // fprintf(stderr, "+[M::%s] ng->n_seq::%u, ext.idx_a.n::%u\n", - // __func__, (uint32_t)ng->n_seq, (uint32_t)ext.idx_a.n); - assert(ng->n_seq == ext.idx_a.n); - CALLOC(ng->seq_vis, (ng->n_seq<<1)); - realloc_rdb(&(R_INF), cov, ruI, ext.idx_a.a, ext.idx_a.n, slen, (char *)"scaf", ng, uopt); - - fprintf(stderr, "\n+[M::%s] 3\n", __func__); - update_paf(R_INF.paf, R_INF.reverse_paf, ext.idx_a.a, ext.idx_a.n, sg->n_seq, ng); - fprintf(stderr, "\n+[M::%s] 4\n", __func__); - - for (i = 0, nocc = ng->r_seq; i < ug->g->n_seq; ++i) { - u = &(ug->u.a[i]); - for (m = 1; m < u->n; m++) { - // fprintf(stderr, "[M::%s] i::%lu, m::%lu\n", __func__, i, m); - v = u->a[m-1]>>32; w = u->a[m]>>32; - r = gen_spec_edge(ng, uopt, v, w, &t); - if(r >= 0) { - p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, w^1, v^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - } else { - z = nocc<<1; nocc++; - push_scaff_node(R_INF.paf, v, z, uopt->min_ovlp, ng); - push_scaff_node(R_INF.paf, z, w, uopt->min_ovlp, ng); - - r = gen_spec_edge(ng, uopt, v, z, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, z^1, v^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - - r = gen_spec_edge(ng, uopt, z, w, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, w^1, z^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - } - } - - v = i<<1; nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); - for (m = 0; m < nv; m++) { - if(av[m].del) continue; - w = av[m].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)); - if(vx > wx) continue; - if((vx == wx) && (vx&1)) continue;///it is possible - - r = gen_spec_edge(ng, uopt, vx, wx, &t); - if(r >= 0) { - p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, wx^1, vx^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - } else { - z = nocc<<1; nocc++; - push_scaff_node(R_INF.paf, vx, z, uopt->min_ovlp, ng); - push_scaff_node(R_INF.paf, z, wx, uopt->min_ovlp, ng); - - r = gen_spec_edge(ng, uopt, vx, z, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, z^1, vx^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - - r = gen_spec_edge(ng, uopt, z, wx, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, wx^1, z^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - } - } - - v = (i<<1)+1; nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); - for (m = 0; m < nv; m++) { - if(av[m].del) continue; - w = av[m].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)); - if(vx > wx) continue; - if((vx == wx) && (vx&1)) continue;///it is possible - - r = gen_spec_edge(ng, uopt, vx, wx, &t); - if(r >= 0) { - p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, wx^1, vx^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - } else { - z = nocc<<1; nocc++; - push_scaff_node(R_INF.paf, vx, z, uopt->min_ovlp, ng); - push_scaff_node(R_INF.paf, z, wx, uopt->min_ovlp, ng); - - r = gen_spec_edge(ng, uopt, vx, z, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, z^1, vx^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - - r = gen_spec_edge(ng, uopt, z, wx, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - r = gen_spec_edge(ng, uopt, wx^1, z^1, &t); - assert(r >= 0); p = asg_arc_pushp(ng); *p = t; - } - } - } - fprintf(stderr, "\n+[M::%s] 5\n", __func__); - asg_cleanup(ng); ng->r_seq = ng->n_seq; - free(ext.cnt.a); free(ext.idx_a.a); - fprintf(stderr, "[M::%s] nocc::%lu, ng->n_seq::%u, sg->n_seq::%u\n", - __func__, nocc, (uint32_t)ng->n_seq, (uint32_t)sg->n_seq); - assert(nocc == ng->n_seq); - return ng; -} - -void gen_ul_trio_graph(ug_opt_t *uopt, ul_resolve_t *uidx, char *o_file) -{ - output_trio_unitig_graph_ul(uopt, uidx, o_file, FATHER); - output_trio_unitig_graph_ul(uopt, uidx, o_file, MOTHER); -} - -void destroy_integer_t(integer_t *z) -{ - free(z->f.a); free(z->p.a); free(z->o.a); free(z->u.a); - free(z->vis.a); free(z->sc.a); free(z->snp.a); free(z->res_dump.a); - free(z->q.a); free(z->t.a); free(z->b.a); - - free(z->pg.seq.a); free(z->pg.arc.a); free(z->pg.idx.a); free(z->pg.e_idx.a); - free(z->pg.srt_b.ind.a); - free(z->pg.srt_b.stack.a); - free(z->pg.srt_b.res.a); - free(z->pg.srt_b.res2nid.a); - free(z->pg.srt_b.aln.a); - - free(z->pg.bb.a.a); - free(z->pg.bb.S.a); - free(z->pg.bb.T.a); - free(z->pg.bb.b.a); - free(z->pg.bb.e.a); - free(z->pg.bb.us.a); - - free(z->pg.bb.dp.ref.a); - free(z->pg.bb.dp.pat.a); - free(z->pg.bb.dp.pat_cor.a); - free(z->pg.bb.dp.g_flt.a); - free(z->pg.bb.dp.m_dir.a); - free(z->pg.bb.dp.m_score.a); -} - -void usg_t_destroy(usg_t *g) { - uint32_t k; - for (k = 0; k < g->mp.n; k++) { - free(g->mp.a[k].a); - } - free(g->mp.a); - - for (k = 0; k < g->n; k++) { - free(g->a[k].arc[0].a); free(g->a[k].arc[1].a); - free(g->a[k].arc_mm[0].a); free(g->a[k].arc_mm[1].a); - } - free(g->a); - - free(g); -} - - -void destroy_ul_resolve_t(ul_resolve_t *uidx) -{ - ma_ug_destroy(uidx->l1_ug); - uint32_t k; - for (k = 0; k < uidx->str_b.n_thread; k++) { - destroy_integer_t(&(uidx->str_b.buf[k])); - } - free(uidx->str_b.buf); - - for (k = 0; k < uidx->pstr.str.n; k++) { - free(uidx->pstr.str.a[k].a); - } - free(uidx->pstr.str.a); - free(uidx->pstr.occ.a); - free(uidx->pstr.idx.a); - - - free(uidx->uovl.telo); - for (k = 0; k < uidx->uovl.n; k++) { - free(uidx->uovl.a[k].a); - } - free(uidx->uovl.a); - free(uidx->uovl.item_idx); - asg_destroy(uidx->uovl.i_g); - - - free(uidx->uovl.cc.uc); - free(uidx->uovl.cc.hc); - free(uidx->uovl.cc.raw_uc); - if(uidx->uovl.cc.iug_a) { - for (k = 0; k < uidx->uovl.i_ug->u.n; k++) free(uidx->uovl.cc.iug_a[k].a); - } - free(uidx->uovl.cc.iug_a); - free(uidx->uovl.cc.iug_idx); - free(uidx->uovl.cc.iug_b); - - asg_destroy(uidx->uovl.bg.bg); - free(uidx->uovl.bg.w_n); - free(uidx->uovl.bg.a_n); - ma_ug_destroy(uidx->uovl.i_ug); - usg_t_destroy(uidx->uovl.h_usg); - - free(uidx); -} - -static void clear_ma_hit_t_alloc(void *data, long i, int tid) -{ - ma_hit_t_alloc *src = (ma_hit_t_alloc *)data; - ma_hit_t_alloc *z = &(src[i]); uint32_t k; - for (k = 0; k < z->length; k++) z->buffer[k].del = 0; -} - -static void reset_ma_sub_t(void *data, long i, int tid) -{ - sset_aux *s = (sset_aux *)data; - if(s->g && s->g->seq[i].del) s->cov[i].del = 1; - else s->cov[i].del = 0; -} - -void renew_R_to_U(asg_t *ng, ma_hit_t_alloc* src, ma_hit_t_alloc* r_src, int64_t n_read, ma_sub_t *coverage_cut, -R_to_U* ruIndex, int max_hang, int min_ovlp) -{ - sset_aux s; memset(&s, 0, sizeof(s)); - kt_for(asm_opt.thread_num, clear_ma_hit_t_alloc, src, n_read); - kt_for(asm_opt.thread_num, clear_ma_hit_t_alloc, r_src, n_read); - - s.g = NULL; s.cov = coverage_cut; - kt_for(asm_opt.thread_num, reset_ma_sub_t, &s, n_read); - - ma_hit_contained_advance(src, n_read, coverage_cut, ruIndex, max_hang, min_ovlp); - - // s.g = ng; s.cov = coverage_cut; - // kt_for(asm_opt.thread_num, reset_ma_sub_t, &s, n_read); -} - -void ul_realignment_gfa(ug_opt_t *uopt, asg_t *sg, int64_t clean_round, double min_ovlp_drop_ratio, -double max_ovlp_drop_ratio, int64_t max_tip, int64_t max_ul_tip, bub_label_t *b_mask_t, uint32_t is_trio, char *o_file, -ul_renew_t *ropt, const char *bin_file, uint64_t free_uld, uint64_t is_bridg, uint64_t deep_clean) -{ - uint64_t i, bn = 0, idn = 0; uint32_t *bl = NULL; uint8_t *r_het = NULL; bubble_type *bub = NULL; ulg_opt_t uu; - for (i = 0; i < sg->n_seq; ++i) { - if(sg->seq[i].del) continue; - sg->seq[i].c = PRIMARY_LABLE; - } - // fprintf(stderr, "0[M::%s]\n", __func__); - hic_clean(sg); - if(deep_clean) { - // print_debug_gfa(sg, NULL, uopt->coverage_cut, "bclean", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 0); - deep_graph_clean(uopt, sg, 1, is_trio, asm_opt.max_short_tip, asm_opt.min_drop_rate, - MIN(asm_opt.max_drop_rate, 0.7), 0.75, 1, asm_opt.clean_round, 10/**20**/); - // print_debug_gfa(sg, NULL, uopt->coverage_cut, "aclean", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 0); - } - - // fprintf(stderr, "1[M::%s]\n", __func__); - ma_ug_t *init_ug = ul_realignment(uopt, sg, 0, bin_file); - // fprintf(stderr, "2[M::%s]\n", __func__); - // exit(1); - - // char* gfa_name = NULL; MALLOC(gfa_name, strlen(o_file)+strlen(bin_file)+50); - // sprintf(gfa_name, "%s.%s", o_file, bin_file); - // print_debug_gfa(sg, init_ug, uopt->coverage_cut, gfa_name, uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 0); - // print_debug_gfa(sg, init_ug, uopt->coverage_cut, gfa_name, uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 1); - // free(gfa_name); - - - filter_sg_by_ug(sg, init_ug, uopt); - // fprintf(stderr, "-0-[M::%s]\tUL_INF.a[25].rlen::%u\n", __func__, UL_INF.a[25].rlen); - // print_debug_gfa(sg, init_ug, uopt->coverage_cut, "UL.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 0); - // print_ul_alignment(init_ug, &UL_INF, 47072, "after-0"); - bub = gen_bubble_chain(sg, init_ug, uopt, &r_het, ((asm_opt.polyploidy>2)?1:0)); - // fprintf(stderr, "4[M::%s]\n", __func__); - // print_ul_alignment(init_ug, &UL_INF, 47072, "after-1"); - ul_resolve_t *uidx = init_ul_resolve_t(sg, init_ug, bub, &UL_INF, uopt, r_het); - if(!free_uld) {///backup - bn = UL_INF.n; idn = UL_INF.nid.n; MALLOC(bl, bn); - for (i = 0; i < bn; i++) bl[i] = UL_INF.a[i].rlen; - } - // fprintf(stderr, "5[M::%s]\n", __func__); - // print_ul_alignment(init_ug, &UL_INF, 47072, "after-2"); - // exit(1); - // if(free_uld) { - // print_raw_uls_seq(uidx, asm_opt.output_file_name); - // print_raw_uls_aln(uidx, asm_opt.output_file_name); - // } - - ul_re_correct(uidx, asm_opt.integer_correct_round/**3**/); - init_ulg_opt_t(&uu, uopt, clean_round, asm_opt.min_path_drop_rate, asm_opt.max_path_drop_rate, min_ovlp_drop_ratio, max_ovlp_drop_ratio, 0.55, max_tip, max_ul_tip, b_mask_t, is_trio); - // print_debug_gfa(sg, init_ug, uopt->coverage_cut, "UL.debug0", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 1); - /**ul2ul_idx_t *u2o = **/gen_ul2ul(uidx, uopt, &uu, 0, is_bridg); - // print_ul_alignment(init_ug, &UL_INF, 47072, "after-3"); - - // print_debug_ul("UL.debug", init_ug, sg, uopt->coverage_cut, uopt->sources, uopt->ruIndex, bub, &UL_INF); - - // resolve_dip_bub_chains(uidx); - - // free(r_het); destory_bubbles(bub); free(bub); - // if(free_uld) { - // uidx->uovl.hybrid_ug = gen_hybrid_ug(uidx, uidx->uovl.h_usg); - // // print_debug_gfa(sg, uidx->uovl.hybrid_ug, uopt->coverage_cut, "hybrid_ug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 1); - // print_debug_gfa(sg, uidx->uovl.hybrid_ug, uopt->coverage_cut, "hybrid_ug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 0); - // // print_debug_gfa(sg, init_ug, uopt->coverage_cut, bin_file, uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 0); - // } - // if(is_trio) gen_ul_trio_graph(uopt, uidx, o_file); - // exit(0); - // return uidx->uovl.hybrid_ug; - - asg_t *ng = renew_ng(uidx->uovl.h_usg, init_ug, sg, uopt, ropt->cov, ropt->ruIndex, 16, bin_file); - destory_bubbles(uidx->bub); free(uidx->bub); ma_ug_destroy(init_ug); free(r_het); - destroy_ul_resolve_t(uidx); - if(free_uld) { - destory_all_ul_t(&UL_INF); memset((&UL_INF), 0, sizeof(UL_INF)); - } else { - for (i = 0; i < bn; i++) UL_INF.a[i].rlen = bl[i]; - for (i = bn; i < UL_INF.n; i++) { - free(UL_INF.a[i].N_site.a); free(UL_INF.a[i].r_base.a); - free(UL_INF.a[i].bb.a); memset(&(UL_INF.a[i]), 0, sizeof(UL_INF.a[i])); - } - UL_INF.n = bn; - - for (i = idn; i < UL_INF.nid.n; i++) { - free(UL_INF.nid.a[i].a); memset(&(UL_INF.nid.a[i]), 0, sizeof(UL_INF.nid.a[i])); - } - UL_INF.nid.n = idn; free(bl); - } - - asg_destroy((*(ropt->sg))); (*(ropt->sg)) = ng; - (*(ropt->src)) = R_INF.paf; (*(ropt->r_src)) = R_INF.reverse_paf; - (*(ropt->n_read)) = R_INF.total_reads; (*(ropt->readLen)) = R_INF.read_length; - renew_R_to_U(ng, (*(ropt->src)), (*(ropt->r_src)), (*(ropt->n_read)), (*(ropt->cov)), ropt->ruIndex, ropt->max_hang, ropt->mini_ovlp); - post_rescue(uopt, (*(ropt->sg)), (*(ropt->src)), (*(ropt->r_src)), ropt->ruIndex, ropt->b_mask_t, 0, NULL); - // print_raw_uls_aln(uidx, asm_opt.output_file_name); - // exit(0); -} - -ug_clean_t *init_ug_clean_t(ug_opt_t *uopt, asg_t *sg, uint8_t is_ou, uint8_t is_trio, int64_t max_ext, double len_rat, double ou_rat, int64_t min_ou) -{ - uint64_t i; - ug_clean_t *sl; CALLOC(sl, 1); - ma_ug_t *ug = ma_ug_gen(sg); - for (i = 0; i < ug->g->n_seq; ++i) { - if(ug->g->seq[i].del) continue; - ug->g->seq[i].c = PRIMARY_LABLE; - } - MALLOC(sl->idx, (ug->g->n_seq<<1)); memset(sl->idx, -1, sizeof((*(sl->idx)))*(ug->g->n_seq<<1)); - MALLOC(sl->bid, (ug->g->n_seq<<1)); memset(sl->bid, -1, sizeof((*(sl->bid)))*(ug->g->n_seq<<1)); - sl->uopt = uopt; sl->sg = sg; sl->ug = ug; sl->idx_n = sl->bid_n = ug->g->n_seq<<1; - memset(&(sl->b), 0, sizeof(sl->b)); CALLOC(sl->b.a, (ug->g->n_seq<<1)); - sl->is_ou = is_ou; - sl->is_trio = is_trio; - sl->max_ext = max_ext; - sl->len_rat = len_rat; - sl->ou_rat = ou_rat; - sl->min_ou = min_ou; - if(is_ou) update_ug_ou(sl->ug, sl->sg); - return sl; -} - -void destroy_ug_clean_t(ug_clean_t *sl) -{ - free(sl->idx); free(sl->bid); ma_ug_destroy(sl->ug); - free(sl->b.a); free(sl->b.S.a); free(sl->b.T.a); free(sl->b.b.a); free(sl->b.e.a); -} - -void update_ug_clean_t(ug_clean_t *sl) -{ - uint32_t v, k, i, n_vtx = sl->ug->g->n_seq<<1; - sl->tlen = get_bub_pop_max_dist_advance(sl->ug->g, &(sl->b)); - for (k = 0; k < sl->ug->g->n_seq; ++k) { - sl->idx[k<<1] = sl->idx[(k<<1)+1] = sl->bid[k<<1] = sl->bid[(k<<1)+1] = (uint32_t)-1; - if(sl->ug->g->seq[k].del) continue; - sl->ug->g->seq[k].c = PRIMARY_LABLE; - } - - for (v = 0; v < n_vtx; ++v) { - if(sl->ug->g->seq[v>>1].del) continue; - if(asg_arc_n(sl->ug->g, v) < 2) continue; - if(sl->bid[v] != ((uint32_t)-1)) continue; - if(asg_bub_pop1_primary_trio(sl->ug->g, NULL, v, sl->tlen, &(sl->b), (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (i = 0; i < sl->b.b.n; i++) { - if(sl->b.b.a[i]==v || sl->b.b.a[i]==sl->b.S.a[0]) continue; - sl->bid[sl->b.b.a[i]] = sl->bid[sl->b.b.a[i]^1] = 1; - } - sl->bid[v] = 2; sl->bid[sl->b.S.a[0]^1] = 3; - } - } - - for (v = 0; v < n_vtx; ++v) { - if(sl->bid[v] !=2) continue; - if(asg_bub_pop1_primary_trio(sl->ug->g, NULL, v, sl->tlen, &(sl->b), (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { - //note b.b include end, does not include beg - for (i = 0; i < sl->b.b.n; i++) { - if(sl->b.b.a[i]==v || sl->b.b.a[i]==sl->b.S.a[0]) continue; - sl->idx[sl->b.b.a[i]] = v; - sl->idx[sl->b.b.a[i]^1] = sl->b.S.a[0]^1; - } - sl->idx[v] = v; sl->idx[sl->b.S.a[0]^1] = sl->b.S.a[0]^1; - } - } - memcpy(sl->bid, sl->idx, sizeof((*(sl->bid)))*n_vtx); - // memset(sl->idx, -1, sizeof((*(sl->idx)))*n_vtx); -} - -uint32_t get_best_het_node(ma_ug_t *ug, uint32_t v, uint32_t *bid, uint8_t is_ou, uint8_t is_trio, double len_rat, double ou_rat, uint32_t min_ou) -{ - uint32_t w = (uint32_t)-1, k, nv, kv, ol_max, ol_k; - asg_arc_t *av; uint32_t trioF = (uint32_t)-1, ntrioF = (uint32_t)-1; - if(ug->g->seq[v>>1].del) return (uint32_t)-1; - av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); - for (k = kv = 0; k < nv; k++) { - if(av[k].del) continue; - ///could not connect to the beg/sink node - if((av[k].v>>1)==(bid[v]>>1) || (av[k].v>>1)==(bid[v^1]>>1)) return (uint32_t)-1; - kv++; w = av[k].v; - } - if(kv < 2) return w;///kv == 0, return (uint32_t)-1; kv == 1, return node; - // if(v == 351) fprintf(stderr, "-0-[M::%s]\tutg%.6ul(%c)\tv::%u\tkv::%u\n", __func__, (v>>1)+1, "+-"[v&1], v, kv); - - if(is_trio) { - trioF = get_ug_tip_trio_infor(ug, v^1); - ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); - } - - ol_max = 0; ol_k = (uint32_t)-1; - for (k = 0; k < nv; ++k) { - if(av[k].del) continue; - // if(is_trio && get_ug_tip_trio_infor(ug, av[k].v) == ntrioF) continue; - if(ol_max < av[k].ol) ol_max = av[k].ol, ol_k = k; - } - // if(v == 351) fprintf(stderr, "-1-[M::%s]\tutg%.6ul(%c)\tv::%u\tol_k::%u\n", __func__, (v>>1)+1, "+-"[v&1], v, ol_k); - if(ol_k == (uint32_t)-1) return (uint32_t)-1; - for (k = 0; k < nv; ++k) { - if(av[k].del || k == ol_k) continue; - // if(is_trio && get_ug_tip_trio_infor(ug, av[k].v) == ntrioF) continue; - if(av[k].ol > av[ol_k].ol*len_rat) return (uint32_t)-1; - if((is_ou) && (av[k].ou > min_ou) && ((av[k].ou) > (av[ol_k].ou*ou_rat))) return (uint32_t)-1; - } - if(is_trio && get_ug_tip_trio_infor(ug, av[ol_k].v) == ntrioF) return (uint32_t)-1; - // if(v == 351) fprintf(stderr, "-2-[M::%s]\tutg%.6ul(%c)\tv::%u\tav[ol_k].v::%u\n", __func__, (v>>1)+1, "+-"[v&1], v, av[ol_k].v); - return av[ol_k].v; -} - -static void cal_bub_best(void *data, long i, int tid) -{ - ug_clean_t *sl = (ug_clean_t *)data; - ma_ug_t *ug = sl->ug; uint32_t v, w; - sl->idx[i<<1] = sl->idx[(i<<1)+1] = (uint32_t)-1; - if(ug->g->seq[i].del) return; - if((sl->bid[i<<1] == (uint32_t)-1) || (sl->bid[(i<<1)+1] == (uint32_t)-1)) return;///not within a bubble - - v = i<<1; - if(sl->bid[v] != v) {///not the beg/sink node - w = get_best_het_node(ug, v, sl->bid, sl->is_ou, sl->is_trio, sl->len_rat, sl->ou_rat, sl->min_ou); - // if(v == 352) fprintf(stderr, "-v-[M::%s]\tutg%.6ul(%c)\tv::%u\tw::%u\n", __func__, (v>>1)+1, "+-"[v&1], v, w); - if((w != (uint32_t)-1) && ((v^1) == get_best_het_node(ug, w^1, sl->bid, sl->is_ou, sl->is_trio, sl->len_rat, sl->ou_rat, sl->min_ou))) { - sl->idx[v] = w; - } - } - - v = (i<<1)+1; - if(sl->bid[v] != v) {///not the beg/sink node - w = get_best_het_node(ug, v, sl->bid, sl->is_ou, sl->is_trio, sl->len_rat, sl->ou_rat, sl->min_ou); - if((w != (uint32_t)-1) && ((v^1) == get_best_het_node(ug, w^1, sl->bid, sl->is_ou, sl->is_trio, sl->len_rat, sl->ou_rat, sl->min_ou))) { - sl->idx[v] = w; - } - } -} - -uint32_t usg_topocut_aux_unambi1(asg_t *g, uint32_t v) -{ - asg_arc_t *av = asg_arc_a(g, v); - uint32_t i, nv = asg_arc_n(g, v); - uint32_t k = nv, kv; - for (i = 0, kv = 0; i < nv; ++i) - if (!av[i].del) ++kv, k = i; - if (kv != 1) return (uint32_t)-1; - return av[k].v; -} - -int usg_topocut_aux_del(ma_ug_t *ug, uint32_t v, int max_ext, asg64_v *b) -{ - int32_t n_ext; - for (n_ext = 0; n_ext < max_ext && v != (uint32_t)-1; ) { - if (usg_topocut_aux_unambi1(ug->g, v^1) == (uint32_t)-1) break; - if(b) kv_push(uint64_t, *b, v); n_ext += ug->u.a[v>>1].n; - v = usg_topocut_aux_unambi1(ug->g, v); - } - return n_ext; -} - -#define is_best_arc(sl, v, w) (((sl).idx[(v)]==(w))&&((sl).idx[((w)^1)]==((v)^1))) - -inline void asg_arc_del_by_ug(asg_t *sg, ma_ug_t *ug, uint32_t uv, uint32_t uw, uint32_t del) -{ - uint32_t rv, rw, i, nv; asg_arc_t *av; - if(uv&1) rv = ug->u.a[uv>>1].start^1; - else rv = ug->u.a[uv>>1].end^1; - - if(uw&1) rw = ug->u.a[uw>>1].end; - else rw = ug->u.a[uw>>1].start; - - av = asg_arc_a(sg, rv); - nv = asg_arc_n(sg, rv); - for (i = 0; i < nv; i++) { - if(av[i].v == rw) break; - } - assert(i < nv); - av[i].del = del; -} - -uint32_t cal_utg_occ(ma_ug_t *ug, uint32_t begNode) -{ - uint32_t v = begNode, w, kv, occ = 0; ma_utg_t *u; - - while (1) { - kv = get_real_length(ug->g, v, NULL); - u = &(ug->u.a[v>>1]); occ += u->n; - if(kv!=1) break; - ///kv must be 1 here - kv = get_real_length(ug->g, v, &w); - if(get_real_length(ug->g, w^1, NULL)!=1) break; - v = w; - if(v == begNode) break; - } - return occ; -} - -void cal_bub_best_by_len(ug_clean_t *sl, asg64_v *in, uint32_t max_ext, uint32_t is_trio, uint32_t is_ou, double len_rat, double ou_rat, uint32_t min_ou, -uint32_t min_node) -{ - // fprintf(stderr, "[M::%s]\tStart\n", __func__); - ma_ug_t *ug = sl->ug; asg_t *g = sl->ug->g; uint32_t ol_max, ou_max, lnid; - uint32_t v, w, n_vtx = (g->n_seq<<1), nv, nw, i, k, z, kv, kw, bb, to_del, bn, tip; - asg64_v tx = {0,0,0}, *b = NULL; asg_arc_t *av, *aw, *ve, *we; ma_utg_t *u; - uint32_t trioF = (uint32_t)-1, ntrioF = (uint32_t)-1, mm_ol, mm_ou, cnt = 0, del_v, del_w; - - if(in) b = in; - else b = &tx; - b->n = 0; - - for (v = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - av = asg_arc_a(g, v); - nv = asg_arc_n(g, v); - if (nv < 2) continue; - - for (i = kv = bb = 0; i < nv; ++i) { - if(av[i].del) continue; - if(is_best_arc((*sl), v, av[i].v)) bb++; - kv++; - } - if((kv < 2) || (!bb) || (kv<=bb)) continue;///it is impossible that kv <= bv - - for (i = 0; i < nv; ++i) { - if(av[i].del) continue; - if(is_best_arc((*sl), v, av[i].v)) continue; - kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); - } - } - - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - if(g->arc[(uint32_t)b->a[k]].del) continue; - - v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; - if(g->seq[v>>1].del || g->seq[w>>1].del) continue; - nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); - av = asg_arc_a(g, v); aw = asg_arc_a(g, w); - if(nv<=1 && nw <= 1) continue; - - if(is_trio) { - if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup - trioF = get_ug_tip_trio_infor(ug, v^1); - ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); - } - - ve = &(g->arc[(uint32_t)b->a[k]]); - for (i = 0; i < nw; ++i) { - if (aw[i].v == (v^1)) { - we = &(aw[i]); - break; - } - } - ///mm_ol and mm_ou are used to make edge with long indel more easy to be cutted - mm_ol = MIN(ve->ol, we->ol); mm_ou = MIN(ve->ou, we->ou); lnid = 0; - - for (i = kv = ol_max = ou_max = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - if(is_trio && get_ug_tip_trio_infor(ug, av[i].v) == ntrioF) continue; - if(ol_max < av[i].ol) ol_max = av[i].ol; - if(ou_max < av[i].ou) ou_max = av[i].ou; - if((!lnid) && ((is_best_arc((*sl), v, av[i].v)))) { - if((cal_utg_occ(ug, v^1) >= min_node) || (cal_utg_occ(ug, av[i].v) >= min_node)) lnid = 1; - } - } - if (kv < 1) continue; - if (kv >= 2) { - if (mm_ol > ol_max*len_rat) continue; - if ((is_ou) && (mm_ou > min_ou) && (mm_ou > (ou_max*ou_rat))) continue; - } - - - for (i = kw = ol_max = ou_max = 0; i < nw; ++i) { - if(aw[i].del) continue; - kw++; - if(is_trio && get_ug_tip_trio_infor(ug, aw[i].v) == ntrioF) continue; - if(ol_max < aw[i].ol) ol_max = aw[i].ol; - if(ou_max < aw[i].ou) ou_max = aw[i].ou; - if((!lnid) && ((is_best_arc((*sl), w, aw[i].v)))) { - if((cal_utg_occ(ug, w^1) >= min_node) || (cal_utg_occ(ug, aw[i].v) >= min_node)) lnid = 1; - } - } - if (kw < 1) continue; - if (kw >= 2) { - if (mm_ol > ol_max*len_rat) continue; - if ((is_ou) && (mm_ou > min_ou) && (mm_ou > (ou_max*ou_rat))) continue; - } - - if (kv <= 1 && kw <= 1) continue; - if(!lnid) continue; - - to_del = 0; del_v = del_w = (uint32_t)-1; tip = 0; - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - // tip = asg_topocut_aux(g, w^1, max_ext); - tip = usg_topocut_aux_del(ug, w^1, max_ext, NULL); - if (tip < max_ext) { - to_del = 1; del_w = w^1; - } - } else if (kv == 1) { - // tip = asg_topocut_aux(g, v^1, max_ext); - tip = usg_topocut_aux_del(ug, v^1, max_ext, NULL); - if (tip < max_ext) { - to_del = 1; del_v = v^1; - } - } - - - if (to_del) { - bn = b->n; - if(del_v != ((uint32_t)-1)) usg_topocut_aux_del(ug, del_v, max_ext, b); - if(del_w != ((uint32_t)-1)) usg_topocut_aux_del(ug, del_w, max_ext, b); - for (i = bn; i < b->n; i++) { - u = &(ug->u.a[b->a[i]>>1]); - if(u->m == 0) continue; - for (z = 0; z < u->n; z++) asg_seq_del(sl->sg, u->a[z]>>33); - asg_seq_del(ug->g, (b->a[i]>>1)); - if(u->m) { - u->m = u->n = 0; free(u->a); u->a = NULL; - } - } - // assert(tip == (b->n-bn)); - b->n = bn; - - ve->del = we->del = 1, ++cnt; - asg_arc_del_by_ug(sl->sg, ug, ve->ul>>32, ve->v, 1); - asg_arc_del_by_ug(sl->sg, ug, we->ul>>32, we->v, 1); - - } - } - - if(!in) free(tx.a); - if (cnt > 0) { - asg_cleanup(g); asg_cleanup(sl->sg); - } - // fprintf(stderr, "[M::%s]\tEnd\n", __func__); -} - -/** -void cal_bub_best_by_topo(ug_clean_t *sl, asg64_v *in, uint32_t max_ext, uint32_t is_trio, uint32_t is_ou, double len_rat, double ou_rat, uint32_t min_ou, uint32_t long_tip) -{ - // fprintf(stderr, "[M::%s]\tStart\n", __func__); - ma_ug_t *ug = sl->ug; asg_t *g = sl->ug->g; uint32_t ol_max, ou_max; - uint32_t v, w, n_vtx = (g->n_seq<<1), nv, nw, i, k, z, kv, kw, to_del, bn, tip, avi, awi; - asg64_v tx = {0,0,0}, *b = NULL; asg_arc_t *av, *aw, *ve, *we; ma_utg_t *u; - uint32_t trioF = (uint32_t)-1, mm_ol, mm_ou, cnt = 0, del_v, del_w; - - if(in) b = in; - else b = &tx; - b->n = 0; - - for (v = 0; v < n_vtx; ++v) { - if (g->seq[v>>1].del) continue; - if((sl->bid[v] == (uint32_t)-1) || (sl->bid[v^1] == (uint32_t)-1)) continue;///not within a bubble - - av = asg_arc_a(g, v); - nv = asg_arc_n(g, v); - if (nv < 2) continue; - - for (i = kv = 0; i < nv; ++i) { - if(av[i].del) continue; - ///could not connect to the beg/sink node - if((av[k].v>>1)==(sl->bid[v]>>1) || (av[k].v>>1)==(sl->bid[v^1]>>1)) break; - kv++; - } - if(kv < 2 || i < nv) continue;///it is impossible that kv <= bv - - for (i = 0; i < nv; ++i) { - if(av[i].del) continue; - kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); - } - } - - radix_sort_srt64(b->a, b->a + b->n); - for (k = 0; k < b->n; k++) { - if(g->arc[(uint32_t)b->a[k]].del) continue; - - v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; - if(g->seq[v>>1].del || g->seq[w>>1].del) continue; - nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); - av = asg_arc_a(g, v); aw = asg_arc_a(g, w); - if(nv < 2 || nw < 2) continue; - kv = get_arcs(g, v, NULL, 0); kw = get_arcs(g, w, NULL, 0); - if(kv < 2 || kw < 2) continue; - - if(is_trio) { - trioF = get_ug_tip_trio_infor(ug, v^1); - if(trioF == FATHER || trioF == MOTHER) { - if(get_ug_tip_trio_infor(ug, w^1) == trioF) continue; - } - } - - avi = awi = (uint32_t)-1; - - avi = ((uint32_t)b->a[k]) - ((uint64_t)(av-g->arc)); - ve = &(g->arc[(uint32_t)b->a[k]]); - - for (i = 0; i < nw; ++i) { - if (aw[i].v == (v^1)) { - we = &(aw[i]); awi = i; - break; - } - } - - for (i = kv = ol_max = ou_max = 0; i < nv; ++i) { - if(av[i].del) continue; - } - - ///mm_ol and mm_ou are used to make edge with long indel more easy to be cutted - mm_ol = MIN(ve->ol, we->ol); mm_ou = MIN(ve->ou, we->ou); - - for (i = kv = ol_max = ou_max = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - if(is_trio && get_ug_tip_trio_infor(ug, av[i].v) == ntrioF) continue; - if(ol_max < av[i].ol) ol_max = av[i].ol; - if(ou_max < av[i].ou) ou_max = av[i].ou; - } - if (kv < 1) continue; - if (kv >= 2) { - if (mm_ol > ol_max*len_rat) continue; - if ((is_ou) && (mm_ou > min_ou) && (mm_ou > (ou_max*ou_rat))) continue; - } - - - for (i = kw = ol_max = ou_max = 0; i < nw; ++i) { - if(aw[i].del) continue; - kw++; - if(is_trio && get_ug_tip_trio_infor(ug, aw[i].v) == ntrioF) continue; - if(ol_max < aw[i].ol) ol_max = aw[i].ol; - if(ou_max < aw[i].ou) ou_max = aw[i].ou; - } - if (kw < 1) continue; - if (kw >= 2) { - if (mm_ol > ol_max*len_rat) continue; - if ((is_ou) && (mm_ou > min_ou) && (mm_ou > (ou_max*ou_rat))) continue; - } - - if (kv <= 1 && kw <= 1) continue; - - to_del = 0; del_v = del_w = (uint32_t)-1; tip = 0; - if (kv > 1 && kw > 1) { - to_del = 1; - } else if (kw == 1) { - tip = asg_topocut_aux(g, w^1, max_ext); - if (tip < max_ext) { - to_del = 1; del_w = w^1; - } - } else if (kv == 1) { - tip = asg_topocut_aux(g, v^1, max_ext); - if (tip < max_ext) { - to_del = 1; del_v = v^1; - } - } - - if (to_del) { - bn = b->n; - if(del_v != ((uint32_t)-1)) usg_topocut_aux_del(ug, del_v, max_ext, b); - if(del_w != ((uint32_t)-1)) usg_topocut_aux_del(ug, del_w, max_ext, b); - for (i = bn; i < b->n; i++) { - u = &(ug->u.a[b->a[i]>>1]); - if(u->m == 0) continue; - for (z = 0; z < u->n; z++) asg_seq_del(sl->sg, u->a[z]>>33); - asg_seq_del(ug->g, (b->a[i]>>1)); - if(u->m) { - u->m = u->n = 0; free(u->a); u->a = NULL; - } - } - // assert(tip == (b->n-bn)); - b->n = bn; - - ve->del = we->del = 1, ++cnt; - asg_arc_del_by_ug(sl->sg, ug, ve->ul>>32, ve->v, 1); - asg_arc_del_by_ug(sl->sg, ug, we->ul>>32, we->v, 1); - - } - } - - if(!in) free(tx.a); - if (cnt > 0) { - asg_cleanup(g); asg_cleanup(sl->sg); - } - // fprintf(stderr, "[M::%s]\tEnd\n", __func__); -} -**/ - - - -void deep_graph_clean(ug_opt_t *uopt, asg_t *sg, uint8_t is_ou, uint8_t is_trio, int64_t max_ext, -double min_ovlp_drop_ratio, double max_ovlp_drop_ratio, double ou_rat, int64_t min_ou, int64_t clean_round, int64_t long_tip) -{ - ug_clean_t *sl; asg64_v b; double step; int64_t i; - kv_init(b); hic_clean_adv(sg, uopt); - step = (clean_round==1?max_ovlp_drop_ratio:((max_ovlp_drop_ratio-min_ovlp_drop_ratio)/(clean_round-1))); - sl = init_ug_clean_t(uopt, sg, is_ou, is_trio, max_ext, min_ovlp_drop_ratio, ou_rat, min_ou); - - // print_debug_gfa(sg, NULL, uopt->coverage_cut, "debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 0); - for (i = 0, sl->len_rat = min_ovlp_drop_ratio; i < clean_round; i++, sl->len_rat += step) { - if(sl->len_rat > max_ovlp_drop_ratio) sl->len_rat = max_ovlp_drop_ratio; - update_ug_clean_t(sl); - kt_for(asm_opt.thread_num, cal_bub_best, sl, sl->ug->g->n_seq); - cal_bub_best_by_len(sl, &b, max_ext, is_trio, sl->is_ou, sl->len_rat, sl->ou_rat, min_ou, long_tip); - } - - // if(is_ou) { - // uint64_t k; sl->is_ou = 0; - // for (k = 0; k < sl->ug->g->n_arc; k++) sl->ug->g->arc[k].ou = 0; - // max_ovlp_drop_ratio = 0.6; - // if(max_ovlp_drop_ratio > min_ovlp_drop_ratio) { - // step = (clean_round==1?max_ovlp_drop_ratio:((max_ovlp_drop_ratio-min_ovlp_drop_ratio)/(clean_round-1))); - // for (i = 0, sl->len_rat = min_ovlp_drop_ratio; i < clean_round; i++, sl->len_rat += step) { - // if(sl->len_rat > max_ovlp_drop_ratio) sl->len_rat = max_ovlp_drop_ratio; - // update_ug_clean_t(sl); - // kt_for(asm_opt.thread_num, cal_bub_best, sl, sl->ug->g->n_seq); - // cal_bub_best_by_len(sl, &b, max_ext, is_trio, sl->is_ou, sl->len_rat, sl->ou_rat, min_ou); - // } - // } - // } - - // update_ug_clean_t(sl); - // cal_bub_best_by_topo(sl, &b, max_ext, is_trio, sl->is_ou, sl->len_rat, sl->ou_rat, min_ou, long_tip); - - kv_destroy(b); destroy_ug_clean_t(sl); free(sl); - hic_clean_adv(sg, uopt); -} +#include +#include +#include +#include +#include +#include "kdq.h" +#include "kthread.h" +#include "gfa_ut.h" +#include "CommandLines.h" +#include "Correct.h" +#include "inter.h" +#include "Overlaps.h" +#include "hic.h" +#include "Purge_Dups.h" + +#define generic_key(x) (x) +KRADIX_SORT_INIT(srt64, uint64_t, generic_key, 8) +#define OU_NOISY 2 +#define ASG_ET_MERGEABLE 0 +#define ASG_ET_TIP 1 +#define ASG_ET_MULTI_OUT 2 +#define ASG_ET_MULTI_NEI 3 +#define UL_TRAV_HERATE 0.2 +#define UL_TRAV_FT_RATE 0.8 + +KDQ_INIT(uint64_t) + +typedef struct { size_t n, m; char *a; } asgc8_v; + +typedef struct { + asg64_v cnt; + asg64_v idx_a; + uint64_t idx_n; + asg_t *ext; + uint64_t a_n; +} asg_ext_t; + +typedef struct { + uint32_t v, uid, off; +} usg_arc_mm_t; + +typedef struct { + size_t n, m; + usg_arc_mm_t *a; +} usg_arc_mm_warp; + +typedef struct { + uint64_t ul; + uint32_t v; + uint32_t ol:31, del:1; + uint32_t ou; + uint64_t idx; +} usg_arc_t; + +typedef struct { + size_t n, m; + usg_arc_t *a; +} usg_arc_warp; + +typedef struct { + uint32_t mm, occ; + uint32_t len; + usg_arc_warp arc[2]; + usg_arc_mm_warp arc_mm[2]; + uint8_t del, telo; +} usg_seq_t; + +#define usg_arc_key(p) ((p).v) +KRADIX_SORT_INIT(usg_arc_srt, usg_arc_t, usg_arc_key, member_size(usg_arc_t, v)) + +#define usg_arc_mm_key(p) ((p).v) +KRADIX_SORT_INIT(usg_arc_mm_srt, usg_arc_mm_t, usg_arc_mm_key, member_size(usg_arc_mm_t, v)) + +typedef struct { + uint32_t *a; + size_t n, m; +} mmap_t; + +typedef struct { + usg_seq_t *a; + size_t n, m; + kvec_t(mmap_t) mp; +} usg_t; + +#define usg_arc_a(g, v) ((g)->a[(v)>>1].arc[(v)&1].a) +#define usg_arc_n(g, v) ((g)->a[(v)>>1].arc[(v)&1].n) + +typedef struct{ + int64_t tipsLen; + float tip_drop_ratio; + int64_t stops_threshold; + float chimeric_rate; + float drop_ratio; + + bub_label_t* b_mask_t; + int64_t clean_round; + double min_ovlp_drop_ratio; + double max_ovlp_drop_ratio; + double hom_check_drop_rate; + double min_path_drop_ratio; + double max_path_drop_ratio; + int64_t max_tip, max_tip_hifi; + uint32_t is_trio; +}ulg_opt_t; + +typedef struct { + uint32_t hid; + uint32_t qs, qe, ts, te; + uint32_t qs_k, qe_k, ts_k, te_k; + uint8_t is_rev:6, is_del:1, is_ct:1; +} ul2ul_t; + +typedef struct { + ul2ul_t *a; + size_t n, m; + uint32_t id:31, is_del:1; + uint32_t cn; + // uint8_t is_consist; +} ul2ul_item_t; + +typedef struct { + uint32_t v, s, e, n; +} uinfo_srt_t; + +typedef struct { + size_t n, m; + uinfo_srt_t *a; +} uinfo_srt_warp_t; + +typedef struct { + uint32_t *uc, *hc, *raw_uc; + uinfo_srt_warp_t *iug_a; + uint32_t *iug_idx; + uint64_t *iug_b; +} ul_cov_t; + + +typedef struct { + asg_t *bg; + uint32_t *w_n, *a_n; +} ul_bg_t; + +// typedef struct { +// uint32_t v, n, wn; +// } ul_tra_t; + +// typedef struct { +// kvec_t(ul_tra_t) arc; +// kvec_t(uint32_t) idx; +// } ul_tra_idx_t; + +// #define iug_tra_arc_n(z, v) ((z)->idx.a[(v)+1]-(z)->idx.a[(v)]) +// #define iug_tra_arc_a(z, v) ((z)->arc.a + (z)->idx.a[(v)]) + +typedef struct { + ul2ul_item_t *a; + size_t n, m; + uint64_t uln, gn, tot; + uint32_t *item_idx; + asg_t *i_g; ma_ug_t *i_ug; + ma_ug_t *hybrid_ug; + usg_t *h_usg; + ul_cov_t cc; + ul_bg_t bg; + asg64_v *iug_tra; + uinfo_srt_warp_t *iug_seq; uint64_t iug_cov_thre; + uint8_t *telo; +} ul2ul_idx_t; + +#define ul2ul_srt_key(p) ((p).hid) +KRADIX_SORT_INIT(ul2ul_srt, ul2ul_t, ul2ul_srt_key, member_size(ul2ul_t, hid)) + +typedef struct { + kvec_t(uint64_t) ref; + kvec_t(uint64_t) pat; + kvec_t(uint64_t) pat_cor; + kvec_t(uint8_t) g_flt; + kvec_t(uint8_t) m_dir; + kvec_t(int64_t) m_score; + uint64_t n, m; +} path_dp_t; + +typedef struct { + uint32_t p; // the optimal parent vertex + uint32_t d; // the shortest distance from the initial vertex + uint64_t c; // max count of positive reads + uint64_t m; // max count of negative reads + // uint32_t np; // max count of non-positive reads + uint32_t nc; // max count of reads, no matter positive or negative + uint32_t r:31, s:1; // r: the number of remaining incoming arc; s: state + //s: state, s=0, this edge has not been visited, otherwise, s=1 +} uinfo_t; + + + +// #define uinfo_srt_t_c_key(p) ((p).se) +// KRADIX_SORT_INIT(uinfo_srt_t_c, uinfo_srt_t, uinfo_srt_t_c_key, member_size(uinfo_srt_t, se)) + +typedef struct { + ///all information for each node + kvec_t(uinfo_t) a; + // kvec_t(uint32_t) u; + kvec_t(uint32_t) S; // set of vertices without parents, nodes with all incoming edges visited + kvec_t(uint32_t) T; // set of tips + kvec_t(uint32_t) b; // visited vertices + kvec_t(uint32_t) e; // visited edges/arcs + // kvec_t(uinfo_srt_t) srt; + kvec_t(uint8_t) us; + path_dp_t dp; +} ubuf_t; + +typedef struct{ + uint32_t bid, beg, occ; + uint32_t n_path, path_idx, path_occ; +}ul_sub_path_t; + + +typedef struct{ + ma_ug_t *buf_ug; + kvec_t(uint64_t) buf; +}ul_path_t; + +typedef struct{ + kvec_t(uint64_t) idx; + kvec_t(uint64_t) srt; + uint64_t ul_n; +}ul_path_srt_t; + +typedef struct{ + size_t n, m; + uint64_t *a; + uint32_t cn:31, is_cir:1; +}ul_str_t; + +typedef struct{ + kvec_t(uint64_t) idx; + kvec_t(uint64_t) occ; + kvec_t(ul_str_t) str; +}ul_str_idx_t; + +typedef struct{ + uint32_t v, pi, ai; + uint32_t k:31, is_gc:1; + int32_t dis; +} integer_seq_t; + +typedef struct{ + size_t n, m; + integer_seq_t *a; +} kv_integer_seq_t; + +typedef struct{ + uint32_t tk, vq, sc; + uint64_t tn_rev_qk; +} integer_aln_t; + +#define integer_aln_t_vqk_key(x) ((x).tn_rev_qk) +KRADIX_SORT_INIT(integer_aln_t_srt, integer_aln_t, integer_aln_t_vqk_key, member_size(integer_aln_t, tn_rev_qk)) + +typedef struct { + size_t n, m; + integer_aln_t *a; +} integer_aln_vec_t; + +typedef struct{ + uint32_t s, e, v; + uint64_t sc; + uint32_t q_sidx, q_eidx; + uint32_t t_sidx, t_eidx; +} ul_chain_t; + + + +typedef struct{ + uint64_t qidx_occ; + uint32_t tidx_occ; + uint32_t chain_id:31, is_rev:1; +} ul_snp_t; + +#define ul_snp_t_srt_key(x) ((x).qidx_occ) +KRADIX_SORT_INIT(ul_snp_t_srt, ul_snp_t, ul_snp_t_srt_key, member_size(ul_snp_t, qidx_occ)) + + +typedef struct { + uint32_t occ, nid; +} poa_nid_t; + +typedef struct { + uint64_t ul; + uint32_t v; +} poa_arc_t; + +#define poa_arc_key(a) ((a).ul) +KRADIX_SORT_INIT(poa_arc_srt, poa_arc_t, poa_arc_key, member_size(poa_arc_t, ul)) + +typedef struct { + kvec_t(uint32_t) ind; + kvec_t(uint32_t) stack; + kvec_t(uint32_t) res; + kvec_t(uint32_t) res2nid; + kvec_t(uint64_t) aln; +} topo_srt_t; + +typedef struct { + kvec_t(int64_t) sc; + kvec_t(uint8_t) dir; + kvec_t(uint64_t) prefix; + uint64_t n, m; +} poa_dp_t; + +#define poa_dp_idx(dp, x, y) ((dp).m*(x)+(y)) +#define e_pdp 0 +#define ue_pdp 1 +#define lstr_dp 2 +#define lg_dp 3 + +typedef struct{ + uint64_t pge, ule; + uint32_t ulid; +} emap_t; + +#define emap_t_srt_key(x) ((x).pge) +KRADIX_SORT_INIT(emap_t_srt, emap_t, emap_t_srt_key, member_size(emap_t, pge)) + +typedef struct { + kvec_t(poa_nid_t) seq; + kvec_t(poa_arc_t) arc; + kvec_t(uint64_t) idx; + uint32_t update_seq; + uint32_t update_arc; + topo_srt_t srt_b; + // poa_dp_t dp; + kvec_t(emap_t) e_idx; + ubuf_t bb; +} poa_g_t; + +typedef struct { + kv_integer_seq_t q; + kv_integer_seq_t t; + integer_aln_vec_t b; + kvec_t(int64_t) f; + kvec_t(int64_t) p; + kvec_t(uint64_t) o; + kvec_t(uint64_t) u; + kvec_t(uint32_t) vis; + // kvec_t(uint64_t) srt; + // kvec_t(uint64_t) v; + // kvec_t(uint64_t) u; + // kvec_t(uint64_t) d; + kvec_t(ul_chain_t) sc; + kvec_t(ul_snp_t) snp; + poa_g_t pg; + kvec_t(uint64_t) res_dump; + uint64_t n_correct, n_circle; +}integer_t; + +typedef struct { + // ul_resolve_t *u; + integer_t *buf; + uint64_t n_thread; +}integer_ml_t; + +typedef struct { + asg_t *g; + uint64_t n[2], tot; +} cul_g_t; + +typedef struct{ + ug_opt_t *uopt; + ma_ug_t *init_ug; + ma_ug_t *l0_ug; + ma_ug_t *l1_ug; + asg_t *sg; + bubble_type *bub; + all_ul_t *idx; + ul_path_t path; + uint8_t *r_het; + ubuf_t buf; + ul_str_idx_t pstr; + integer_ml_t str_b; + cul_g_t *cg; + ul2ul_idx_t uovl; + // ul_path_srt_t psrt; +}ul_resolve_t; + +typedef struct{ + ug_opt_t *uopt; + asg_t *sg; + ma_ug_t *ug; + buf_t b; + uint32_t *idx, *bid; + uint32_t idx_n, bid_n; + uint8_t is_ou; + uint8_t is_trio; + int64_t max_ext; + uint64_t tlen; + double len_rat; + double ou_rat; + int64_t min_ou; +}ug_clean_t; + +void deep_graph_clean(ug_opt_t *uopt, asg_t *sg, uint8_t is_ou, uint8_t is_trio, int64_t max_ext, +double min_ovlp_drop_ratio, double max_ovlp_drop_ratio, double ou_rat, int64_t min_ou, int64_t clean_round, int64_t long_tip); + +void init_integer_ml_t(integer_ml_t *x, ul_resolve_t *u, uint64_t n_thread) +{ + memset(x, 0, sizeof((*x))); + x->n_thread = n_thread; ///x->u = u; + CALLOC(x->buf, n_thread); +} + +int32_t if_sup_chimeric(ma_hit_t_alloc* src, uint64_t rLen, asg64_v *b, int if_exact); + +void print_edge(asg_arc_t *t, const char *cmd) +{ + uint32_t v = t->ul>>32, w = t->v; + fprintf(stderr, "%s: v->%u(%c)[%u], w->%u(%c)[%u], el->%u, del->%u\n", cmd, v>>1, "+-"[v&1], v, w>>1, "+-"[w&1], w, t->el, t->del); +} + +void stats_chimeric(asg_t *g, ma_hit_t_alloc* src, asg64_v *in) +{ + asg64_v tx = {0,0,0}, *b = NULL; + uint32_t v, s[2] = {0}; + if(in) b = in; + else b = &tx; + b->n = 0; + + for (v = 0; v < g->n_seq; ++v) { + if (g->seq[v].del) continue; + s[if_sup_chimeric(&(src[v]), g->seq[v].len, b, 1)]++; + } + + fprintf(stderr, "[M::%s::] ==> # non-chimeric:%u, # chimeric:%u\n", __func__, s[0], s[1]); + if(!in) free(tx.a); +} + +static void stats_sysm_worker(void *_data, long eid, int tid) +{ + asg_t *g = (asg_t*)_data; + asg_arc_t *p = &(g->arc[eid]); + if(p->del) return; + uint32_t k, v = p->v^1, w = (p->ul>>32)^1, nv; asg_arc_t *av; + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (k = 0; k < nv; k++) { + if (av[k].del || av[k].v!=w) continue; + break; + } + assert(k < nv); + + v = p->ul>>32; w = p->v; + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (k = 0; k < nv; k++) { + if (av[k].del || av[k].v!=w) continue; + assert((uint32_t)eid == av-g->arc+k); + } +} + +void stats_sysm(asg_t *g) { + kt_for(asm_opt.thread_num, stats_sysm_worker, g, g->n_arc); + fprintf(stderr, "[M::%s::]", __func__); +} + +uint32_t get_arcs(asg_t *g, uint32_t v, uint32_t* idx, uint32_t idx_n) +{ + uint32_t i, kv = 0, an = asg_arc_n(g, v), beg = g->idx[v]>>32; + for (i = 0, kv = 0; i < an; i++) { + if(g->arc[beg+i].del) continue; + if(idx && kvarc[(id)])):(&((fg).a[(id)-(((uint32_t)(0x80000000)))])))); + +uint32_t get_flex_arcs(flex_asg_t *fg, uint32_t v, uint32_t* idx, uint32_t idx_n) +{ + asg_t *g = fg->g; uint32_t i, kv = 0; + uint32_t an = asg_arc_n(g, v), beg = g->idx[v]>>32; + for (i = 0, kv = 0; i < an; i++) { + if(g->arc[beg+i].del) continue; + if(idx && kvidx[v]; i != ((uint32_t)-1); i = fg->pi.a[i]) { + if(fg->a[i].del) continue; + if(idx && kvb, v>>1); + if(b) kv_push(uint64_t, *b, v); + + if(kv == 0) return END_TIPS; + if(kv == 2) return TWO_OUTPUT; + if(kv > 2) return MUL_OUTPUT; + if((*occ) > lim) return LONG_TIPS; + w = g->arc[w].v; + ///up to here, kv=1 + ///kw must >= 1 + kw = get_arcs(g, w^1, NULL, 0); + v = w; + + if(kw == 2) return TWO_INPUT; + if(kw > 2) return MUL_INPUT; + if(v == s) return LOOP; + } + + return LONG_TIPS; +} + +static inline int asg_end(const asg_t *g, uint32_t v, uint64_t *lw, uint32_t *ou) +{ + ///v^1 is the another direction of v + uint32_t w, nv, nw, nw0, nv0 = asg_arc_n(g, v^1); + int i, i0 = -1; + asg_arc_t *aw, *av = asg_arc_a(g, v^1); + + ///if this arc has not been deleted + for (i = nv = 0; i < (int)nv0; ++i) + if (!av[i].del) i0 = i, ++nv; + + ///end without any out-degree + if (nv == 0) return ASG_ET_TIP; // tip + if (nv > 1) return ASG_ET_MULTI_OUT; // multiple outgoing arcs + ///until here, nv == 1 + if (lw) *lw = av[i0].ul<<32 | av[i0].v; + if (ou) *ou = av[i0].ou; + w = av[i0].v ^ 1; + nw0 = asg_arc_n(g, w); + aw = asg_arc_a(g, w); + for (i = nw = 0; i < (int)nw0; ++i) + if (!aw[i].del) ++nw; + + if (nw != 1) return ASG_ET_MULTI_NEI; + return ASG_ET_MERGEABLE; +} + +uint32_t asg_arc_cut_tips(asg_t *g, uint32_t max_ext, asg64_v *in, uint32_t is_ou, R_to_U *ru, telo_end_t *te) +{ + asg64_v tx = {0,0,0}, *b = NULL; + uint32_t n_vtx = g->n_seq<<1, v, w, i, k, cnt = 0, nv, kv, pb, ou, mm_ou, rr, is_u, is_telo; + asg_arc_t *av = NULL; uint64_t lw; + if(in) b = in; + else b = &tx; + b->n = 0; + for (v = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + if(te && te->hh[v>>1]) continue; + + av = asg_arc_a(g, v^1); nv = asg_arc_n(g, v^1); + for (i = kv = 0; i < nv; i++) { + if (av[i].del) continue; + kv++; break; + } + if(kv) continue; + + kv = 1; mm_ou = (uint32_t)-1; ou = 0; is_telo = 0; + if(te && te->hh[v>>1]) is_telo = 1; + for (i = 0, w = v; i < max_ext; i++) { + if(asg_end(g, w^1, &lw, is_ou?&ou:NULL)!=0) break; + w = (uint32_t)lw; kv++; mm_ou = MIN(mm_ou, ou); + if(te && te->hh[w>>1]) is_telo = 1; + } + + if(mm_ou == (uint32_t)-1) mm_ou = 0; + kv += mm_ou; i += mm_ou; + if((i < max_ext/** + (!!is_ou)**/) && (!is_telo)) kv_push(uint64_t, *b, (((uint64_t)kv)<<32)|v); + } + + radix_sort_srt64(b->a, b->a + b->n); + + for (k = 0; k < b->n; k++) { + v = (uint32_t)(b->a[k]); + + if (g->seq[v>>1].del) continue; + if(te && te->hh[v>>1]) continue; + + av = asg_arc_a(g, v^1); nv = asg_arc_n(g, v^1); + for (i = kv = 0; i < nv; i++) { + if (av[i].del) continue; + kv++; break; + } + + if(kv) continue; + + pb = b->n; kv_push(uint64_t, *b, v); mm_ou = (uint32_t)-1; ou = 0; is_telo = 0; + if(te && te->hh[v>>1]) is_telo = 1; + for (i = 0, w = v; i < max_ext; i++) { + if(asg_end(g, w^1, &lw, is_ou?&ou:NULL)!=0) break; + w = (uint32_t)lw; kv_push(uint64_t, *b, lw); mm_ou = MIN(mm_ou, ou); + if(te && te->hh[w>>1]) is_telo = 1; + } + if(mm_ou == (uint32_t)-1) mm_ou = 0; + i += mm_ou; + + if((i < max_ext/** + (!!is_ou)**/) && (!is_telo)) { + for (i = pb; i < b->n; i++) asg_seq_del(g, ((uint32_t)b->a[i])>>1); + cnt++; + } + b->n = pb; + } + + if(ru && is_ou) { + for (v = b->n = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + av = asg_arc_a(g, v^1); nv = asg_arc_n(g, v^1); + for (i = kv = 0; i < nv; i++) { + if (av[i].del) continue; + kv++; break; + } + if(kv) continue; + + + get_R_to_U(ru, v>>1, &rr, &is_u); + if(rr == (uint32_t)-1 || is_u == 1) continue; + if(te && te->hh[v>>1]) continue; + kv_push(uint64_t, *b, v); + + for (i = 0, w = v; i < max_ext; i++) { + if(asg_end(g, w^1, &lw, NULL)!=0) break; + w = (uint32_t)lw; + + get_R_to_U(ru, w>>1, &rr, &is_u); + if(rr == (uint32_t)-1 || is_u == 1) break; + if(te && te->hh[w>>1]) break; + + kv_push(uint64_t, *b, lw); + } + + for (i = 0; i < b->n; i++) { + asg_seq_del(g, ((uint32_t)b->a[i])>>1); + } + if(b->n) cnt++; + } + } + + + /** + for (v = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + + av = asg_arc_a(g, v^1); nv = asg_arc_n(g, v^1); + for (i = kv = 0; i < nv; i++) { + if (av[i].del) continue; + kv++; + } + + if(kv) continue; + pb = b->n; kv_push(uint64_t, *b, v); + for (i = 0, w = v; i < max_ext; i++) { + if(asg_is_utg_end(g, w^1, &lw)!=0) break; + w = (uint32_t)lw; kv_push(uint64_t, *b, lw); + } + + if(i < max_ext) { + for (i = pb; i < b->n; i++) asg_seq_del(g, ((uint32_t)b->a[i])>>1); + cnt++; + } + b->n = pb; + } + **/ + // stats_sysm(g); + if(!in) free(tx.a); + if (cnt > 0) asg_cleanup(g); + + return cnt; +} + +static void update_sg_contain(void *data, long i, int tid) +{ + sset_aux *sl = (sset_aux *)data; ma_hit_t *h, *z; asg_arc_t t; + ma_hit_t_alloc *src = sl->src; asg_t *g = sl->g; int64_t r, idx; + R_to_U *ridx = sl->ruIndex; uint32_t k, rr, qn, tn, is_u; + g->seq_vis[i] = 0; + if(!(g->seq[i].del)) return; + get_R_to_U(ridx, i, &rr, &is_u); + if(rr == (uint32_t)-1 || is_u == 1) return; + ma_hit_t_alloc *x = &(src[i]); + for (k = 0; k < x->length; k++) { + h = &(x->buffer[k]); + qn = Get_qn((*h)); tn = Get_tn((*h)); + if(h->bl < sl->ul_occ) continue; + if(g->seq[tn].del) { + get_R_to_U(ridx, tn, &rr, &is_u); + if(rr == (uint32_t)-1 || is_u == 1) continue; + } + r = ma_hit2arc(h, g->seq[qn].len, g->seq[tn].len, sl->max_hang, asm_opt.max_hang_rate, sl->min_ovlp, &t); + if(r < 0) continue; + idx = get_specific_overlap(&(src[tn]), tn, qn); + z = &(src[tn].buffer[idx]); + assert(z->bl == h->bl); + r = ma_hit2arc(z, g->seq[tn].len, g->seq[qn].len, sl->max_hang, asm_opt.max_hang_rate, sl->min_ovlp, &t); + if(r < 0) continue; + h->del = 0; if(!(g->seq[tn].del)) z->del = 0; + g->seq_vis[i] = 1; + } +} + +void recover_contain_g(asg_t *g, ma_hit_t_alloc *src, R_to_U* ruIndex, int64_t max_hang, int64_t min_ovlp, int64_t ul_occ) +{ + sset_aux s; s.g = g; s.src = src; s.ruIndex = ruIndex; + s.max_hang = max_hang; s.min_ovlp = min_ovlp; s.ul_occ = ul_occ; + kt_for(asm_opt.thread_num, update_sg_contain, &s, g->n_seq); + uint32_t k; + for (k = 0; k < g->n_seq; k++) { + if(g->seq_vis[k]) g->seq[k].del = 0; + } + memset(g->seq_vis, 0, (sizeof(*(g->seq_vis))*(g->n_seq<<1))); +} + +// static void update_norm_arc(void *data, long i, int tid) +// { +// sset_aux *sl = (sset_aux *)data; ma_hit_t *h, *z; asg_arc_t t; +// ma_hit_t_alloc *src = sl->src; int64_t r, idx; +// uint32_t k, rr, qn, tn, is_u; +// ma_hit_t_alloc *x = &(src[i]); +// for (k = 0; k < x->length; k++) { +// h = &(x->buffer[k]); +// qn = Get_qn((*h)); tn = Get_tn((*h)); +// if(h->bl < sl->ul_occ) continue; +// if(g->seq[tn].del) { +// get_R_to_U(ridx, tn, &rr, &is_u); +// if(rr == (uint32_t)-1 || is_u == 1) continue; +// } +// r = ma_hit2arc(h, g->seq[qn].len, g->seq[tn].len, sl->max_hang, asm_opt.max_hang_rate, sl->min_ovlp, &t); +// if(r < 0) continue; +// idx = get_specific_overlap(&(src[tn]), tn, qn); +// z = &(src[tn].buffer[idx]); +// assert(z->bl == h->bl); +// r = ma_hit2arc(z, g->seq[tn].len, g->seq[qn].len, sl->max_hang, asm_opt.max_hang_rate, sl->min_ovlp, &t); +// if(r < 0) continue; +// h->del = 0; if(!(g->seq[tn].del)) z->del = 0; +// g->seq_vis[i] = 1; +// } +// } + +// void normalize_ma_hit_t_mul(ma_hit_t_alloc *src, uint32_t n_src) +// { +// sset_aux s; s.src = src; +// kt_for(asm_opt.thread_num, update_norm_arc, &s, n_src); +// } + +static void normalize_gou0(void *data, long i, int tid) +{ + sset_aux *sl = (sset_aux *)data; + asg_t *g = sl->g; + asg_arc_t *e = &(g->arc[i]); + if(e->v > (e->ul>>32)) return; + uint32_t k, v = e->v^1, w = (e->ul>>32)^1, ou; + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + for (k = 0; k < nv; ++k) { + if (av[k].v == w) { + ou = MAX(av[k].ou, e->ou); + av[k].ou = e->ou = ou; + break; + } + } +} + +void normalize_gou(asg_t *g) +{ + sset_aux s; s.g = g; + kt_for(asm_opt.thread_num, normalize_gou0, &s, g->n_arc); +} + +static void update_sg_uo_t(void *data, long i, int tid) +{ + sset_aux *sl = (sset_aux *)data; + ma_hit_t_alloc *src = sl->src; asg_t *g = sl->g; + asg_arc_t *e = &(g->arc[i]); uint32_t k, qn, tn; + ma_hit_t_alloc *x = &(src[e->ul>>33]); + e->ou = 0; + if(e->del) return; + for (k = 0; k < x->length; k++) { + qn = Get_qn(x->buffer[k]); + tn = Get_tn(x->buffer[k]); + if(qn == (e->ul>>33) && tn == (e->v>>1)) { + e->ou = (x->buffer[k].bl>OU_MASK?OU_MASK:x->buffer[k].bl); + break; + } + } + assert(k < x->length); +} + +void update_sg_uo(asg_t *g, ma_hit_t_alloc *src) +{ + sset_aux s; s.g = g; s.src = src; + kt_for(asm_opt.thread_num, update_sg_uo_t, &s, g->n_arc); + uint32_t k, z, nv, occ_a = 0, occ_n = 0; asg_arc_t *av = NULL; + for (k = 0; k < g->n_seq; k++) { + if(g->seq[k].del) continue; + occ_n++; + + av = asg_arc_a(g, (k<<1)); nv = asg_arc_n(g, (k<<1)); + for (z = 0; z < nv; z++) { + if(av[z].del || av[z].ou == 0) continue; + break; + } + if(z < nv) { + occ_a++; + continue; + } + + av = asg_arc_a(g, ((k<<1)+1)); nv = asg_arc_n(g, ((k<<1)+1)); + for (z = 0; z < nv; z++) { + if(av[z].del || av[z].ou == 0) continue; + break; + } + if(z < nv) { + occ_a++; + } + } + + fprintf(stderr, "[M::%s::] ==> # gfa reads:%u, # covered gfa reads:%u\n", __func__, occ_n, occ_a); + + // asg_arc_t *e; uint32_t v, w; + // for (k = 0; k < g->n_arc; k++) { + // e = &(g->arc[k]); + // v = e->v^1; w = (e->ul>>32)^1; + // av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + // for (z = 0; z < nv; z++) { + // if(av[z].v == w) break; + // } + // if(z >= nv || av[z].ou != e->ou) fprintf(stderr, "[M::%s::asymmetry]\n", __func__); + // } +} + +int32_t if_sup_chimeric(ma_hit_t_alloc* src, uint64_t rLen, asg64_v *b, int if_exact) +{ + uint32_t k, qs, qe, l[2], r[2], st, bn; + int32_t dp, op; + l[0] = r[0] = rLen; l[1] = r[1] = 0; + for (k = 0; k < src->length; k++){ + if(src->buffer[k].del) continue; + if(if_exact && !(src->buffer[k].el)) continue; + + qs = Get_qs(src->buffer[k]); qe = Get_qe(src->buffer[k]); + + ///overlaps from left side + if(qs == 0){ + if(qs < l[0]) l[0] = qs; + if(qe > l[1]) l[1] = qe; + } + + ///overlaps from right side + if(qe == rLen){ + if(qs < r[0]) r[0] = qs; + if(qe > r[1]) r[1] = qe; + } + + ///note: if (qs == 0 && qe == rLen) + ///this overlap would be added to both b_left and b_right + ///that is what we want + } + if (l[1] > r[0]) return 0; + if (l[1] <= l[0] || r[1] <= r[0]) return 1; + + bn = b->n; + if(l[1] > l[0]) { + kv_push(uint64_t, *b, (l[0]<<1)); kv_push(uint64_t, *b, (l[1]<<1)|1); + } + if(r[1] > r[0]) { + kv_push(uint64_t, *b, (r[0]<<1)); kv_push(uint64_t, *b, (r[1]<<1)|1); + } + + ///check contained overlaps + for (k = 0; k < src->length; k++) { + if(src->buffer[k].del) continue; + if(if_exact && !(src->buffer[k].el)) continue; + + qs = Get_qs(src->buffer[k]); qe = Get_qe(src->buffer[k]); + if(qs == 0 || qe == rLen) continue; + + kv_push(uint64_t, *b, (qs<<1)); kv_push(uint64_t, *b, (qe<<1)|1); + } + radix_sort_srt64(b->a + bn, b->a + b->n); + l[0] = r[0] = rLen; l[1] = r[1] = 0; + + for (k = bn, dp = st = 0; k < b->n; k++) { + op = dp; + ///if a[j] is qe + if (b->a[k]&1) --dp; + else ++dp; + + if(op < 1 && dp >= 1) { + st = b->a[k]>>1; + } else if(op >= 1 && dp < 1) { + if(st == 0) l[0] = st, l[1] = b->a[k]>>1; + if((b->a[k]>>1) == rLen) r[0] = st, r[1] = b->a[k]>>1; + } + } + + b->n = bn; + if (l[1] > r[0]) return 0; + + return 1; +} + +///remove single node +void asg_arc_cut_chimeric(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, uint32_t ou_thres, telo_end_t *te) +{ + asg64_v tx = {0,0,0}, *b = NULL; + uint32_t v, w, ei[2] = {0}, k, i, n_vtx = g->n_seq<<1; + uint32_t nw, el_n, cnt = 0; asg_arc_t *aw; + if(in) b = in; + else b = &tx; + b->n = 0; + + for (v = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + if (te && te->hh[v>>1]) continue; + if(g->seq_vis[v] == 0) { + if((get_arcs(g, v, &(ei[0]), 1)!=1) || (get_arcs(g, v^1, &(ei[1]), 1)!=1)) continue; + assert((g->arc[ei[0]].ul>>32) == v && (g->arc[ei[1]].ul>>32) == (v^1)); + if((get_arcs(g, g->arc[ei[0]].v^1, NULL, 0)<2) || (get_arcs(g, g->arc[ei[1]].v^1, NULL, 0)<2)) continue; + if(g->arc[ei[0]].el) continue; + if(ou_thres!=(uint32_t)-1&&g->arc[ei[0]].ou>=ou_thres&&g->arc[ei[1]].ou>=ou_thres) continue;///UL + if(!if_sup_chimeric(&(src[v>>1]), g->seq[v>>1].len, b, 1)) continue;///HiFi + kv_push(uint64_t, *b, (((uint64_t)(g->arc[ei[0]].ol))<<32)|((uint64_t)(ei[0]))); + } + } + + radix_sort_srt64(b->a, b->a + b->n); + ///here all edges are inexact matches + for (k = 0; k < b->n; k++) { + if(g->arc[(uint32_t)b->a[k]].del) continue; + v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; + if(g->seq[v>>1].del || g->seq[w>>1].del) continue; + aw = asg_arc_a(g, w); nw = asg_arc_n(g, w); + if((get_arcs(g, v, &(ei[0]), 1)!=1) || (get_arcs(g, v^1, &(ei[1]), 1)!=1)) continue; + if((get_arcs(g, g->arc[ei[0]].v^1, NULL, 0)<2) || (get_arcs(g, g->arc[ei[1]].v^1, NULL, 0)<2)) continue; + + for (i = el_n = 0; i < nw; i++) { + if ((aw[i].del) || (aw[i].v==(v^1)) || (!aw[i].el)) continue; + el_n++; break; + } + + if(!el_n) continue; + if(te && te->hh[v>>1]) continue; + asg_seq_del(g, v>>1); + cnt++; + } + // stats_sysm(g); + if(!in) free(tx.a); + if (cnt > 0) asg_cleanup(g); +} + +void asg_arc_cut_inexact(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, int32_t max_ext, uint32_t is_ou, uint32_t is_trio, uint32_t min_diff, float ou_rat/**, asg64_v *dbg**/) +{ + asg64_v tx = {0,0,0}, *b = NULL; + uint32_t v, w, i, k, n_vtx = g->n_seq<<1; + asg_arc_t *av = NULL, *aw = NULL, *ve = NULL, *vmax, *we = NULL; uint32_t nv, nw, kv, kw, ol_max, ou_max, to_del, cnt = 0, mm_ol, mm_ou; + uint32_t trioF = (uint32_t)-1, ntrioF = (uint32_t)-1; + if(in) b = in; + else b = &tx; + b->n = 0; + + for (v = 0; v < n_vtx; ++v) { + if(g->seq[v>>1].del) continue; + if(g->seq_vis[v] == 0) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if (nv < 2) continue; + + for (i = kv = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + } + if(kv < 2) continue; + + for (i = 0; i < nv; ++i) { + if(av[i].del || av[i].el) continue; + kv_push(uint64_t, *b, (uint64_t)((((uint64_t)av[i].ol)<<32)|((uint64_t)(av-g->arc+i)))); + } + } + } + + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + if(g->arc[(uint32_t)b->a[k]].del) continue; + assert((!g->arc[(uint32_t)b->a[k]].el)); + + v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; + if(g->seq[v>>1].del || g->seq[w>>1].del) continue; + nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); + av = asg_arc_a(g, v); aw = asg_arc_a(g, w); + // if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { + // fprintf(stderr, "[0]v->%u, w->%u, nv->%u, nw->%u\n", v, w, nv, nw); + // } + if(nv<=1 && nw <= 1) continue; + if(is_trio) { + if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup + trioF = get_tip_trio_infor(g, v^1); + ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); + } + ve = &(g->arc[(uint32_t)b->a[k]]); + for (i = 0; i < nw; ++i) { + if (aw[i].v == (v^1)) { + we = &(aw[i]); + break; + } + } + ///mm_ol and mm_ou are used to make edge with long indel more easy to be cutted + mm_ol = MIN(ve->ol, we->ol); mm_ou = MIN(ve->ou, we->ou); + for (i = kv = ol_max = ou_max = 0, vmax = NULL; i < nv; ++i) { + if(av[i].del) continue; + kv++; + if(is_trio && get_tip_trio_infor(g, av[i].v) == ntrioF) continue; + if(ol_max < av[i].ol) ol_max = av[i].ol, vmax = &(av[i]); + if(ou_max < av[i].ou) ou_max = av[i].ou; + } + // if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { + // fprintf(stderr, "[1]v->%u, w->%u, kv->%u, ve->ol->%u, ol_max->%u\n", v, w, kv, ve->ol, ol_max); + // } + if (kv < 1) continue; + if (kv >= 2) { + if (mm_ol >= ol_max) continue; + if (is_ou && mm_ou > ou_max*ou_rat) continue; + if ((mm_ol + min_diff) > ol_max) continue; + } + + for (i = kw = ol_max = ou_max = 0; i < nw; ++i) { + if(aw[i].del) continue; + kw++; + if(is_trio && get_tip_trio_infor(g, aw[i].v) == ntrioF) continue; + if(ol_max < aw[i].ol) ol_max = aw[i].ol; + if(ou_max < aw[i].ou) ou_max = aw[i].ou; + } + // if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { + // fprintf(stderr, "[1]v->%u, w->%u, kw->%u, we->ol->%u, ol_max->%u\n", v, w, kw, we->ol, ol_max); + // } + if (kw < 1) continue; + if (kw >= 2) { + if (mm_ol >= ol_max) continue; + if (is_ou && mm_ou > ou_max*ou_rat) continue; + if ((mm_ol + min_diff) > ol_max) continue; + } + if (kv <= 1 && kw <= 1) continue; + + to_del = 0; + ///if there is an inexact edge between two good reads + if(src[v>>1].is_fully_corrected == 1 && src[w>>1].is_fully_corrected == 1) { + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + } + } + ///TODO: should check if the edge wmax also works + if(src[v>>1].is_fully_corrected == 1 && src[w>>1].is_fully_corrected == 0) { + if(vmax && vmax->v != ve->v && vmax->el == 1 && src[vmax->v>>1].is_fully_corrected == 1) { + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + } + } + } + + // if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { + // fprintf(stderr, "[3]v->%u, w->%u, to_del->%u, el->%u, src[v>>1].is_fully_corrected->%u, src[w>>1].is_fully_corrected->%u\n", + // v, w, to_del, g->arc[(uint32_t)b->a[k]].el, src[v>>1].is_fully_corrected, src[w>>1].is_fully_corrected); + // fprintf(stderr, "[4]v->%u, w->%u, to_del->%u, vmax->v->%u, vmax->el->%u, src[vmax->v>>1].is_fully_corrected->%u\n", + // v, w, to_del, vmax->v, vmax->el, src[vmax->v>>1].is_fully_corrected); + // } + + if (to_del) { + ve->del = we->del = 1, ++cnt; + /** + if(dbg) { + kv_push(uint64_t, *dbg, ve - g->arc); + kv_push(uint64_t, *dbg, we - g->arc); + // if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { + // fprintf(stderr, "[5]v->%u, w->%u, (ve - g->arc)->%u, (we - g->arc)->%u\n", + // v, w, (uint32_t)(ve - g->arc), (uint32_t)(we - g->arc)); + // } + } + **/ + } + + } + // stats_sysm(g); + if(!in) free(tx.a); + if (cnt > 0) asg_cleanup(g); +} + +void asg_arc_cut_inexact_debug(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, int32_t max_ext, uint32_t is_ou, uint32_t is_trio, asg64_v *dbg) +{ + asg64_v tx = {0,0,0}, *b = NULL; + uint32_t v, w, i, k, nv, nw, kv, kw, iv, iw, n_vtx = g->n_seq<<1, to_del, cnt = 0, ov_max = 0, ow_max = 0, ov_max_i = 0; + asg_arc_t *av = NULL, *aw = NULL, *a = NULL; + if(in) b = in; + else b = &tx; + b->n = 0; + + for (v = 0; v < n_vtx; ++v) { + if(g->seq[v>>1].del) continue; + if(g->seq_vis[v] == 0) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if (nv < 2) continue; + for (i = kv = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + } + if(kv < 2) continue; + + for (i = 0; i < nv; ++i) { + if(av[i].del || av[i].el) continue; + kv_push(uint64_t, *b, (uint64_t)((uint64_t)av[i].ol << 32 | (av - g->arc + i))); + } + } + } + radix_sort_srt64(b->a, b->a + b->n); + + for (k = 0; k < b->n; k++) { + a = &g->arc[(uint32_t)b->a[k]]; + if(a->del) continue; + v = (a->ul)>>32, w = a->v^1; to_del = 0; + nv = asg_arc_n(g, v), nw = asg_arc_n(g, w); + if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { + fprintf(stderr, "[0]v->%u, w->%u, nv->%u, nw->%u\n", v, w, nv, nw); + } + if (nv == 1 && nw == 1) continue; + av = asg_arc_a(g, v), aw = asg_arc_a(g, w); + ov_max = ow_max = ov_max_i = 0; + + for (i = 0, kv = 0; i < nv; ++i) { + if (av[i].del) continue; + if (ov_max < av[i].ol) { + ov_max = av[i].ol; + ov_max_i = i; + } + ++kv; + } + if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { + fprintf(stderr, "[1]v->%u, w->%u, kv->%u, a->ol->%u, ov_max->%u\n", v, w, kv, a->ol, ov_max); + } + if (kv >= 2 && a->ol == ov_max) continue; + + for (i = 0, kw = 0; i < nw; ++i) { + if (aw[i].del) continue; + if (ow_max < aw[i].ol) { + ow_max = aw[i].ol; + } + ++kw; + } + if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { + fprintf(stderr, "[2]v->%u, w->%u, kw->%u, a->ol->%u, ow_max->%u\n", v, w, kw, a->ol, ow_max); + } + if (kw >= 2 && a->ol == ow_max) continue; + + if (kv <= 1 && kw <= 1) continue; + + ///to see which one is the current edge (from v and w) + for (iv = 0; iv < nv; ++iv) + if (av[iv].v == (w^1)) break; + for (iw = 0; iw < nw; ++iw) + if (aw[iw].v == (v^1)) break; + ///if one edge has been deleted, it should be deleted in both direction + if (av[iv].del && aw[iw].del) continue; + + ///if this edge is an inexact edge + if(a->el == 0 && src[v>>1].is_fully_corrected == 1 && src[w>>1].is_fully_corrected == 1) { + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + } + } + + if(a->el == 0 && src[v>>1].is_fully_corrected == 1 && src[w>>1].is_fully_corrected == 0) { + if(av[ov_max_i].el == 1 && src[av[ov_max_i].v>>1].is_fully_corrected == 1) { + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + } + } + } + + if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { + fprintf(stderr, "[3]v->%u, w->%u, to_del->%u, el->%u, src[v>>1].is_fully_corrected->%u, src[w>>1].is_fully_corrected->%u\n", + v, w, to_del, a->el, src[v>>1].is_fully_corrected, src[w>>1].is_fully_corrected); + fprintf(stderr, "[4]v->%u, w->%u, to_del->%u, av[ov_max_i].v->%u, av[ov_max_i].el->%u, src[av[ov_max_i].v>>1].is_fully_corrected->%u\n", + v, w, to_del, av[ov_max_i].v, av[ov_max_i].el, src[av[ov_max_i].v>>1].is_fully_corrected); + } + + if (to_del) { + av[iv].del = aw[iw].del = 1, ++cnt; + if(dbg) { + kv_push(uint64_t, *dbg, (av - g->arc + iv)); + kv_push(uint64_t, *dbg, (aw - g->arc + iw)); + if(((v>>1) == 50356 && (w>>1) == 1276292)||((v>>1) == 1276292 && (w>>1) == 50356)) { + fprintf(stderr, "[5]v->%u, w->%u, (av-g->arc+iv)->%u, (aw-g->arc+iw)->%u\n", + v, w, (uint32_t)(av - g->arc + iv), (uint32_t)(aw - g->arc + iw)); + } + } + } + } + + if(!in) free(tx.a); + if(dbg) { + for (i = 0; i < dbg->n; i++) g->arc[dbg->a[i]].del = 0; + } + // if (cnt > 0) asg_cleanup(g); +} + +uint32_t trans_path_check(uint32_t a, uint32_t b, asg_t *g, ma_hit_t_alloc *rev, R_to_U* rI, +uint32_t minLen, asg64_v *t) +{ + if(a == b) return -1; + uint32_t tn = t->n, m, e, l[2] = {0}; + uint64_t *x[2]; + m = follow_limit_path(g, a, &e, &(l[0]), t, (uint32_t)-1); + if(m == LOOP || l[0] <= minLen) { + t->n = tn; return -1; + } + + m = follow_limit_path(g, b, &e, &(l[1]), t, (uint32_t)-1); + if(m == LOOP || l[1] <= minLen) { + t->n = tn; return -1; + } + + x[0] = t->a + tn; x[1] = t->a + tn + l[0]; + if(l[0] > l[1]) { + x[0] = t->a + tn + l[0]; x[1] = t->a + tn; + m = l[0]; l[0] = l[1]; l[1] = m; + } + assert(l[0]+l[1]+tn==t->n); + + uint32_t i, k, qi, ti, isU; double max_count = 0, min_count = 0; + for (i = 0; i < l[1]; i++) g->seq_vis[x[1][i]>>1] = 1; + for (i = 0; i < l[0]; i++) { + qi = x[0][i]>>1; + for (k = 0; k < rev[qi].length; k++) { + ti = Get_tn(rev[qi].buffer[k]); + if(g->seq[ti].del == 1) { + get_R_to_U(rI, ti, &ti, &isU); + if(ti == (uint32_t)-1 || isU == 1 || g->seq[ti].del == 1) continue; + } + min_count++; max_count += g->seq_vis[ti]; + } + } + + for (i = 0; i < l[1]; i++) g->seq_vis[x[1][i]>>1] = 0; + t->n = tn; + + if(min_count == 0) return -1; + if(max_count == 0) return 0; + if((max_count/min_count)>0.3) return 1; + return 0; +} + +void asg_arc_cut_length(asg_t *g, asg64_v *in, int32_t max_ext, float len_rat, float ou_rat, uint32_t is_ou, uint32_t is_trio, +uint32_t is_topo, uint32_t min_diff, uint32_t min_ou, ma_hit_t_alloc *rev, R_to_U* rI, uint32_t *max_drop_len) +{ + asg64_v tx = {0,0,0}, *b = NULL; + uint32_t i, k, v, w, n_vtx = g->n_seq<<1, nv, nw, kv, kw, trioF = (uint32_t)-1, ntrioF = (uint32_t)-1, ol_max, ou_max, to_del, cnt = 0, mm_ol, mm_ou; + asg_arc_t *av = NULL, *aw = NULL, *ve = NULL, *we = NULL, *vl_max = NULL, *wl_max = NULL; + + if(in) b = in; + else b = &tx; + b->n = 0; + + for (v = 0; v < n_vtx; ++v) { + // if((v>>1)==17078) fprintf(stderr, "[M::%s::] v:%u, del:%u, seq_vis:%u\n", __func__, v, g->seq[v>>1].del, g->seq_vis[v]); + if (g->seq[v>>1].del) continue; + if(g->seq_vis[v] == 0) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if (nv < 2) continue; + + for (i = kv = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + } + if(kv < 2) continue; + + for (i = 0; i < nv; ++i) { + if(av[i].del) continue; + // if((av[i].ul>>33)==287) { + // fprintf(stderr, "++++++%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\n", + // (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], + // (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].ol, av[i].ou); + // } + if(max_drop_len && av[i].ol >= (*max_drop_len)) continue; + kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); + } + } + } + + if(rev && rI) memset(g->seq_vis, 0, g->n_seq*2*sizeof(uint8_t)); + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + if(g->arc[(uint32_t)b->a[k]].del) continue; + + v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; + if(g->seq[v>>1].del || g->seq[w>>1].del) continue; + nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); + av = asg_arc_a(g, v); aw = asg_arc_a(g, w); + if(nv<=1 && nw <= 1) continue; + + if(is_trio) { + if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup + trioF = get_tip_trio_infor(g, v^1); + ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); + } + + ve = &(g->arc[(uint32_t)b->a[k]]); + for (i = 0; i < nw; ++i) { + if (aw[i].v == (v^1)) { + we = &(aw[i]); + break; + } + } + ///mm_ol and mm_ou are used to make edge with long indel more easy to be cutted + mm_ol = MIN(ve->ol, we->ol); mm_ou = MIN(ve->ou, we->ou); + + for (i = kv = ol_max = ou_max = 0, /**ve =**/ vl_max = NULL; i < nv; ++i) { + if(av[i].del) continue; + // if(av[i].v == (w^1)) ve = &(av[i]); + // if((av[i].ul>>33)==287) { + // fprintf(stderr, "++++++%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\n", + // (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], + // (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].ol, av[i].ou); + // } + kv++; + if(is_trio && get_tip_trio_infor(g, av[i].v) == ntrioF) continue; + if(ol_max < av[i].ol) ol_max = av[i].ol, vl_max = &(av[i]); + if(ou_max < av[i].ou) ou_max = av[i].ou; + } + if (kv < 1) continue; + if (kv >= 2) { + if (mm_ol > ol_max*len_rat) continue; + if (is_ou && mm_ou > ou_max*ou_rat && mm_ou > min_ou) continue; + if ((mm_ol + min_diff) > ol_max) continue; + } + + + for (i = kw = ol_max = ou_max = 0, wl_max = NULL; i < nw; ++i) { + if(aw[i].del) continue; + kw++; + if(is_trio && get_tip_trio_infor(g, aw[i].v) == ntrioF) continue; + if(ol_max < aw[i].ol) ol_max = aw[i].ol, wl_max = &(aw[i]); + if(ou_max < aw[i].ou) ou_max = aw[i].ou; + } + if (kw < 1) continue; + if (kw >= 2) { + if (mm_ol > ol_max*len_rat) continue; + if (is_ou && mm_ou > ou_max*ou_rat && mm_ou > min_ou) continue; + if ((mm_ol + min_diff) > ol_max) continue; + } + + if (kv <= 1 && kw <= 1) continue; + + to_del = 0; + if(is_topo) { + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + } + } + + if(rev && rI) { + if((to_del == 0) && vl_max && (ve->v!=vl_max->v) && (trans_path_check(ve->v, vl_max->v, g, rev, rI, max_ext, b)==0)) { + to_del = 1; + } + if((to_del == 0) && wl_max && (we->v!=wl_max->v) && (trans_path_check(we->v, wl_max->v, g, rev, rI, max_ext, b)==0)) { + to_del = 1; + } + if(vl_max && wl_max) assert(ve->v!=vl_max->v||we->v!=wl_max->v); + } + + + if (to_del) { + ve->del = we->del = 1, ++cnt; + } + } + // stats_sysm(g); + if(!in) free(tx.a); + if (cnt > 0) asg_cleanup(g); +} + +uint32_t is_dedup_weak_arc(asg_arc_t *av, uint32_t an, uint32_t ak, ma_hit_t_alloc *rev) +{ + uint32_t k, w, m; ma_hit_t_alloc *z = NULL; + for (k = 0; k < an; k++) { + if((k == ak) || (av[k].del) || (!av[k].strong)) continue; + if(av[k].ol > av[ak].ol) { + z = &(rev[av[k].v>>1]); w = (av[ak].v^(av[k].v&1)); + for (m = 0; m < z->length; m++) { + if((z->buffer[m].tn<<1|(z->buffer[m].rev)) == w) break; + } + if(m < z->length) return 1; + } + } + + return 0; +} + +void asg_arc_cut_weak(asg_t *g, asg64_v *in, int32_t max_ext, float len_rat, float ou_rat, uint32_t is_ou, uint32_t is_trio, +uint32_t is_topo, uint32_t min_diff, uint32_t min_ou, uint32_t test_bub, ma_hit_t_alloc *rev, R_to_U* rI, uint32_t *max_drop_len) +{ + asg64_v tx = {0,0,0}, *b = NULL; + uint32_t i, k, v, w, wz, n_vtx = g->n_seq<<1, nv, nw, kv, kw, trioF = (uint32_t)-1, ntrioF = (uint32_t)-1, ol_max, ou_max, to_del, cnt = 0, mm_ol, mm_ou, olw[2], m; + asg_arc_t *av = NULL, *aw = NULL, *ve = NULL, *we = NULL, *vl_max = NULL, *wl_max = NULL; ma_hit_t_alloc *z = NULL; + + if(in) b = in; + else b = &tx; + b->n = 0; + + for (v = 0; v < n_vtx; ++v) { + // if((v>>1)==17078) fprintf(stderr, "[M::%s::] v:%u, del:%u, seq_vis:%u\n", __func__, v, g->seq[v>>1].del, g->seq_vis[v]); + if (g->seq[v>>1].del) continue; + if((test_bub == 0) || (g->seq_vis[v] == 0)) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if (nv < 2) continue; + + for (i = kv = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + } + if(kv < 2) continue; + + for (i = olw[1] = 0, olw[0] = (uint32_t)-1; i < nv; ++i) { + if(av[i].del) continue; + if(av[i].strong) { + if(av[i].ol > olw[av[i].strong]) olw[av[i].strong] = av[i].ol; + } else { + if(av[i].ol < olw[av[i].strong]) olw[av[i].strong] = av[i].ol; + } + } + if(olw[1] <= olw[0]) continue; + for (i = 0; i < nv; ++i) { + if(av[i].del || av[i].strong) continue; + if(av[i].ol >= olw[1]) continue; + if(max_drop_len && av[i].ol >= (*max_drop_len)) continue; + if(is_dedup_weak_arc(av, nv, i, rev)) { + kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); + } + } + } + } + + if(rev && rI) memset(g->seq_vis, 0, g->n_seq*2*sizeof(uint8_t)); + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + if(g->arc[(uint32_t)b->a[k]].del) continue; + + v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; + if(g->seq[v>>1].del || g->seq[w>>1].del) continue; + nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); + av = asg_arc_a(g, v); aw = asg_arc_a(g, w); + if(nv<=1 && nw <= 1) continue; + + if(is_trio) { + if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup + trioF = get_tip_trio_infor(g, v^1); + ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); + } + + ve = &(g->arc[(uint32_t)b->a[k]]); + for (i = 0; i < nw; ++i) { + if (aw[i].v == (v^1)) { + we = &(aw[i]); + break; + } + } + ///mm_ol and mm_ou are used to make edge with long indel more easy to be cutted + mm_ol = MIN(ve->ol, we->ol); mm_ou = MIN(ve->ou, we->ou); + + for (i = kv = ol_max = ou_max = 0, vl_max = NULL; i < nv; ++i) { + if(av[i].del) continue; + kv++; + if((av[i].v == ve->v) || (!av[i].strong) || (av[i].ol <= ve->ol)) continue; + if(is_trio && get_tip_trio_infor(g, av[i].v) == ntrioF) continue; + + z = &(rev[av[i].v>>1]); wz = (ve->v^(av[i].v&1)); + for (m = 0; m < z->length; m++) { + if((z->buffer[m].tn<<1|(z->buffer[m].rev)) == wz) break; + } + if(m >= z->length) continue; + + if(ol_max < av[i].ol) ol_max = av[i].ol, vl_max = &(av[i]); + if(ou_max < av[i].ou) ou_max = av[i].ou; + } + if (kv < 1) continue; + if (kv >= 2) { + if (mm_ol > ol_max*len_rat) continue; + if (is_ou && mm_ou > ou_max*ou_rat && mm_ou > min_ou) continue; + if ((mm_ol + min_diff) > ol_max) continue; + } + + + for (i = kw = ol_max = ou_max = 0, wl_max = NULL; i < nw; ++i) { + if(aw[i].del) continue; + kw++; + if((aw[i].v == we->v) || (!aw[i].strong) || (aw[i].ol <= we->ol)) continue; + if(is_trio && get_tip_trio_infor(g, aw[i].v) == ntrioF) continue; + + z = &(rev[aw[i].v>>1]); wz = (we->v^(aw[i].v&1)); + for (m = 0; m < z->length; m++) { + if((z->buffer[m].tn<<1|(z->buffer[m].rev)) == wz) break; + } + if(m >= z->length) continue; + + if(ol_max < aw[i].ol) ol_max = aw[i].ol, wl_max = &(aw[i]); + if(ou_max < aw[i].ou) ou_max = aw[i].ou; + } + if (kw < 1) continue; + if (kw >= 2) { + if (mm_ol > ol_max*len_rat) continue; + if (is_ou && mm_ou > ou_max*ou_rat && mm_ou > min_ou) continue; + if ((mm_ol + min_diff) > ol_max) continue; + } + + if (kv <= 1 && kw <= 1) continue; + + to_del = 0; + if(is_topo) { + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + } + } + + if(rev && rI) { + if((to_del == 0) && vl_max && (ve->v!=vl_max->v) && (trans_path_check(ve->v, vl_max->v, g, rev, rI, max_ext, b)==0)) { + to_del = 1; + } + if((to_del == 0) && wl_max && (we->v!=wl_max->v) && (trans_path_check(we->v, wl_max->v, g, rev, rI, max_ext, b)==0)) { + to_del = 1; + } + if(vl_max && wl_max) assert(ve->v!=vl_max->v||we->v!=wl_max->v); + } + + + if (to_del) { + ve->del = we->del = 1, ++cnt; + } + } + // stats_sysm(g); + if(!in) free(tx.a); + if (cnt > 0) asg_cleanup(g); +} + + +void asg_arc_cut_chimeric_cmk(asg_t *g, asg64_v *in, int32_t max_ext, float len_rat, float ou_rat, uint32_t is_ou, uint32_t is_topo, uint32_t min_ou, uint32_t test_bub, uint8_t *cmk, uint32_t cmk_cut) +{ + asg64_v tx = {0,0,0}, *b = NULL; asg_arc_t *av = NULL, *aw = NULL, *ve = NULL, *we = NULL; + uint32_t i, k, v, w, n_vtx = g->n_seq<<1, nv, nw, kv, kw, ol_max, ou_max, to_del, cnt = 0, mm_ol, mm_ou; + + if(in) b = in; + else b = &tx; + b->n = 0; + + for (v = 0; v < n_vtx; ++v) { + // if((v>>1)==17078) fprintf(stderr, "[M::%s::] v:%u, del:%u, seq_vis:%u\n", __func__, v, g->seq[v>>1].del, g->seq_vis[v]); + if (g->seq[v>>1].del) continue; + if (cmk[v>>1] > cmk_cut) continue; + if((test_bub == 0) || (g->seq_vis[v] == 0)) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if (nv < 2) continue; + + for (i = kv = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + } + if(kv < 2) continue; + + for (i = 0; i < nv; ++i) { + if(av[i].del) continue; + kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); + } + } + } + + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + if(g->arc[(uint32_t)b->a[k]].del) continue; + + v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; + if(g->seq[v>>1].del || g->seq[w>>1].del) continue; + nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); + av = asg_arc_a(g, v); aw = asg_arc_a(g, w); + if(nv<=1 && nw <= 1) continue; + + ve = &(g->arc[(uint32_t)b->a[k]]); + for (i = 0; i < nw; ++i) { + if (aw[i].v == (v^1)) { + we = &(aw[i]); + break; + } + } + ///mm_ol and mm_ou are used to make edge with long indel more easy to be cutted + mm_ol = MIN(ve->ol, we->ol); mm_ou = MIN(ve->ou, we->ou); + + for (i = kv = ol_max = ou_max = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + + if(ol_max < av[i].ol) ol_max = av[i].ol; + if(ou_max < av[i].ou) ou_max = av[i].ou; + } + if (kv < 1) continue; + if (kv >= 2) { + if (mm_ol > ol_max*len_rat) continue; + if (is_ou && mm_ou > ou_max*ou_rat && mm_ou > min_ou) continue; + } + + + for (i = kw = ol_max = ou_max = 0; i < nw; ++i) { + if(aw[i].del) continue; + kw++; + + if(ol_max < aw[i].ol) ol_max = aw[i].ol; + if(ou_max < aw[i].ou) ou_max = aw[i].ou; + } + if (kw < 1) continue; + if (kw >= 2) { + if (mm_ol > ol_max*len_rat) continue; + if (is_ou && mm_ou > ou_max*ou_rat && mm_ou > min_ou) continue; + } + + if (kv <= 1 && kw <= 1) continue; + + to_del = 0; + if(is_topo) { + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext + 1) < max_ext + 1) to_del = 1; + } + } + + if (to_del) { + asg_seq_del(g, v>>1); ++cnt; + } + } + // stats_sysm(g); + if(!in) free(tx.a); + if (cnt > 0) asg_cleanup(g); + + // fprintf(stderr, "[M::%s::] cnt:%u\n", __func__, cnt); +} + + +void asg_arc_cut_length_adv(asg_t *g, asg64_v *in, int32_t max_ext, float len_rat, float ou_rat, uint32_t is_ou, uint32_t is_trio, +uint32_t is_topo, uint32_t min_diff, ma_hit_t_alloc *rev, R_to_U* rI, uint32_t *max_drop_len) +{ + asg64_v tx = {0,0,0}, *b = NULL; + uint32_t i, k, v, w, n_vtx = g->n_seq<<1, nv, nw, kv, kw, trioF = (uint32_t)-1, ntrioF = (uint32_t)-1, ol_max, ou_max, to_del, cnt = 0, mm_ol, mm_ou; + asg_arc_t *av = NULL, *aw = NULL, *ve = NULL, *we = NULL, *vl_max = NULL, *wl_max = NULL; + + if(in) b = in; + else b = &tx; + b->n = 0; + + for (v = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + if(g->seq_vis[v] == 0) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if (nv < 2) continue; + + for (i = kv = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + } + if(kv < 2) continue; + + for (i = 0; i < nv; ++i) { + if(av[i].del) continue; + if(max_drop_len && av[i].ol >= (*max_drop_len)) continue; + kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); + } + } + } + + if(rev && rI) memset(g->seq_vis, 0, g->n_seq*2*sizeof(uint8_t)); + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + if(g->arc[(uint32_t)b->a[k]].del) continue; + + v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; + if(g->seq[v>>1].del || g->seq[w>>1].del) continue; + nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); + av = asg_arc_a(g, v); aw = asg_arc_a(g, w); + if(nv<=1 && nw <= 1) continue; + + if(is_trio) { + if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup + trioF = get_tip_trio_infor(g, v^1); + ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); + } + + ve = &(g->arc[(uint32_t)b->a[k]]); + for (i = 0; i < nw; ++i) { + if (aw[i].v == (v^1)) { + we = &(aw[i]); + break; + } + } + ///mm_ol and mm_ou are used to make edge with long indel more easy to be cutted + mm_ol = MIN(ve->ol, we->ol); mm_ou = MIN(ve->ou, we->ou); + + for (i = kv = ol_max = ou_max = 0, /**ve =**/ vl_max = NULL; i < nv; ++i) { + if(av[i].del) continue; + kv++; + if(is_trio && get_tip_trio_infor(g, av[i].v) == ntrioF) continue; + if(ol_max < av[i].ol) ol_max = av[i].ol, vl_max = &(av[i]); + if(ou_max < av[i].ou) ou_max = av[i].ou; + } + if (kv < 1) continue; + if (kv >= 2) { + if (mm_ol > ol_max*len_rat) continue; + if (is_ou && mm_ou > ou_max*ou_rat) continue; + if ((mm_ol + min_diff) > ol_max) continue; + } + + + for (i = kw = ol_max = ou_max = 0, wl_max = NULL; i < nw; ++i) { + if(aw[i].del) continue; + kw++; + if(is_trio && get_tip_trio_infor(g, aw[i].v) == ntrioF) continue; + if(ol_max < aw[i].ol) ol_max = aw[i].ol, wl_max = &(aw[i]); + if(ou_max < aw[i].ou) ou_max = aw[i].ou; + } + if (kw < 1) continue; + if (kw >= 2) { + if (mm_ol > ol_max*len_rat) continue; + if (is_ou && mm_ou > ou_max*ou_rat) continue; + if ((mm_ol + min_diff) > ol_max) continue; + } + + if (kv <= 1 && kw <= 1) continue; + + to_del = 0; + if(is_topo) { + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + } + } + + if(rev && rI) { + if((to_del == 0) && vl_max && (ve->v!=vl_max->v) && (trans_path_check(ve->v, vl_max->v, g, rev, rI, max_ext, b)==0)) { + to_del = 1; + } + if((to_del == 0) && wl_max && (we->v!=wl_max->v) && (trans_path_check(we->v, wl_max->v, g, rev, rI, max_ext, b)==0)) { + to_del = 1; + } + if(vl_max && wl_max) assert(ve->v!=vl_max->v||we->v!=wl_max->v); + } + + + if (to_del) { + ve->del = we->del = 1, ++cnt; + } + } + // stats_sysm(g); + if(!in) free(tx.a); + if (cnt > 0) asg_cleanup(g); +} + +uint8_t get_ug_tip_trio_infor(ma_ug_t *ug, uint32_t begNode) +{ + uint32_t v = begNode, w, k, s; + uint32_t kv; + uint32_t eLen = 0, uLen = 0; + uint32_t father_occ = 0, mother_occ = 0, ambigious_occ = 0; + ma_utg_t *u; + + while (1) { + kv = get_real_length(ug->g, v, NULL); + u = &(ug->u.a[v>>1]); eLen += u->n; + + for (k = 0; k < u->n; k++) { + s = u->a[k]>>33; + if(R_INF.trio_flag[s]==FATHER) father_occ++; + else if(R_INF.trio_flag[s]==MOTHER) mother_occ++; + else if((R_INF.trio_flag[s]==AMBIGU) || (R_INF.trio_flag[s]==DROP)) ambigious_occ++; + } + if(kv!=1) break; + ///kv must be 1 here + kv = get_real_length(ug->g, v, &w); + if(get_real_length(ug->g, w^1, NULL)!=1) break; + v = w; + if(v == begNode) break; + } + + uLen = eLen;///how many nodes + eLen = father_occ + mother_occ;///haplotype-sepcific nodes + if(eLen == 0) return AMBIGU; + if(father_occ >= mother_occ) { + if((father_occ > TRIO_THRES*eLen) && (father_occ >= DOUBLE_CHECK_THRES*uLen)) return FATHER; + } else { + if((mother_occ > TRIO_THRES*eLen) && (mother_occ >= DOUBLE_CHECK_THRES*uLen)) return MOTHER; + } + return AMBIGU; +} + + +asg_arc_t *iter_flex_asg(flex_asg_t *fg, flex_asg_e_retrive_t *rr, uint32_t v) +{ + asg_arc_t *av; uint32_t nv; asg_arc_t *z; + av = asg_arc_a(fg->g, v); nv = asg_arc_n(fg->g, v); + while(rr->i[0] < nv) { + return &(av[rr->i[0]++]); + } + + if(rr->i[0] >= nv && rr->i[0] != ((uint32_t)-1)) { + rr->i[0] = ((uint32_t)-1); rr->i[1] = fg->idx[v]; + } + while (rr->i[1] != ((uint32_t)-1)) { + z = &(fg->a[rr->i[1]]); rr->i[1] = fg->pi.a[rr->i[1]]; + return z; + } + return NULL; +} + +uint32_t detect_tip2(flex_asg_t *fg, uint32_t id, asg64_v *st, float ou_rat) +{ + uint32_t v, w, kw, ou_max, mm_ou; asg_arc_t *sv, *sw; + flex_asg_e_retrive_t rv, rw; + v = id<<1; rv.i[0] = 0; rv.i[1] = (uint32_t)-1; + while(1) { + sv = iter_flex_asg(fg, &rv, v); + if(!sv) break; + if(sv->del) continue; + w = sv->v^1; + if(fg->g->seq_vis[w]&128) continue; + if(fg->g->seq_vis[w>>1]&2) continue; + + rw.i[0] = 0; rw.i[1] = (uint32_t)-1; kw = 0; ou_max = mm_ou = 0; + while(1) { + sw = iter_flex_asg(fg, &rw, w); + if(!sw) break; + if(sw->del) continue; + if(ou_max < sw->ou) ou_max = sw->ou; + if(fg->g->seq_vis[sw->v>>1]&2) { + if(mm_ou < sw->ou) mm_ou = sw->ou; + continue; + } + kw++; + } + if(kw < 1) return 1; + if(ou_rat >= 0 && mm_ou > ou_max*ou_rat) return 1; + fg->g->seq_vis[w] |= 128; kv_push(uint64_t, *st, w); + } + + v = (id<<1)+1; rv.i[0] = 0; rv.i[1] = (uint32_t)-1; + while(1) { + sv = iter_flex_asg(fg, &rv, v); + if(!sv) break; + if(sv->del) continue; + w = sv->v^1; + if(fg->g->seq_vis[w]&128) continue; + if(fg->g->seq_vis[w>>1]&2) continue; + + rw.i[0] = 0; rw.i[1] = (uint32_t)-1; kw = 0; ou_max = mm_ou = 0; + while(1) { + sw = iter_flex_asg(fg, &rw, w); + if(!sw) break; + if(sw->del) continue; + if(ou_max < sw->ou) ou_max = sw->ou; + if(fg->g->seq_vis[sw->v>>1]&2) { + if(mm_ou < sw->ou) mm_ou = sw->ou; + continue; + } + kw++; + } + if(kw < 1) return 1; + if(ou_rat >= 0 && mm_ou > ou_max*ou_rat) return 1; + fg->g->seq_vis[w] |= 128; kv_push(uint64_t, *st, w); + } + + // av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + // for (i = 0; i < nv; ++i) { + // if(av[i].del) continue; + // w = av[i].v^1; + // if(g->seq_vis[w]&128) continue; + // if((g->seq_vis[w>>1]&3)==2) continue; + // aw = asg_arc_a(g, w); nw = asg_arc_n(g, w); + // for (k = kw = 0; k < nw && kw < 1; k++) { + // if(aw[k].del) continue; + // if((g->seq_vis[aw[k].v>>1]&3)==2) continue; + // kw++; + // } + // if(kw < 1) return 1; + // g->seq_vis[w] |= 128; kv_push(uint64_t, *st, w); + // } + + + // v = (id<<1)+1; + // av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + // for (i = 0; i < nv; ++i) { + // if(av[i].del) continue; + // w = av[i].v^1; + // if(g->seq_vis[w]&128) continue; + // if((g->seq_vis[w>>1]&3)==2) continue; + // aw = asg_arc_a(g, w); nw = asg_arc_n(g, w); + // for (k = kw = 0; k < nw && kw < 1; k++) { + // if(aw[k].del) continue; + // if((g->seq_vis[aw[k].v>>1]&3)==2) continue; + // kw++; + // } + // if(kw < 1) return 1; + // g->seq_vis[w] |= 128; kv_push(uint64_t, *st, w); + // } + + return 0; +} + +uint32_t trans_check(flex_asg_t *fg, asg_arc_t *z, asg64_v *b) +{ + flex_asg_e_retrive_t rv, rw; asg_arc_t *sv, *sw; + uint32_t v = z->ul>>32, w; + + rv.i[0] = 0; rv.i[1] = (uint32_t)-1; + while(1) { + sv = iter_flex_asg(fg, &rv, v); + if(!sv) break; + if(sv->del) continue; + if(sv->v == z->v) return 0; + w = sv->v; + // if((z->ul>>33) == 8340 && (z->v>>1) == 8352) { + // fprintf(stderr, "+[M::%s] v>>1::%u(%c), w>>1::%u(%c), sv->v::%u\n", + // __func__, (z->ul>>33), "+-"[(z->ul>>32)&1], (z->v>>1), "+-"[z->v&1], sv->v); + // } + + rw.i[0] = 0; rw.i[1] = (uint32_t)-1; + while (1) { + sw = iter_flex_asg(fg, &rw, w); + if(!sw) break; + if(sw->del) continue; + if(sw->v == z->v) return 0; + } + } + + + uint32_t bn = b->n; uint64_t vl, d, L = asg_arc_len((*z)) + fg->gap_fuzz; + kv_push(uint64_t, *b, v); + while (b->n > bn) { + vl = kv_pop(*b); v = (uint32_t)vl; vl >>= 32; + rv.i[0] = 0; rv.i[1] = (uint32_t)-1; + while(1) { + sv = iter_flex_asg(fg, &rv, v); + if(!sv) break; + if(sv->del) continue; + d = vl + asg_arc_len((*sv)); + if(d > L) continue; + if(sv->v == z->v) { + b->n = bn; + return 0; + } + d <<= 32; d |= sv->v; + kv_push(uint64_t, *b, d); + } + } + + b->n = bn; + return 1; +} + +void push_flex_asg_t(flex_asg_t *fg, asg_arc_t *z) +{ + asg_arc_t *av; uint32_t nv, k, v = z->ul>>32; + av = asg_arc_a(fg->g, v); nv = asg_arc_n(fg->g, v); + for (k = 0; k < nv; k++) { + if(av[k].del) { + av[k] = *z; + if(!(fg->need_srt)) { + if(k > 0 && av[k].ul < av[k-1].ul) fg->need_srt = 1; + if(k+1 < nv && av[k].ul > av[k+1].ul) fg->need_srt = 1; + } + return; + } + } + + k = fg->n; fg->need_srt = 1; + kv_push(asg_arc_t, *fg, *z); + kv_push(uint32_t, fg->pi, fg->idx[v]); fg->idx[v] = k; +} + +void append_notrans_e(flex_asg_t *fg, uint64_t *a, uint64_t a_n, asg64_v *b) +{ + ma_hit_t_alloc* src = fg->src; int32_t idx, r; + uint32_t i, k, v, w; ma_hit_t_alloc *z; asg_arc_t t0, t1; + for (i = 0; i < a_n; i++) { + v = a[i]; + z = &(src[v>>1]); + for (k = i + 1; k < a_n; k++) { + w = a[k]^1; + idx = get_specific_overlap(z, v>>1, w>>1); + if(idx < 0 || z->buffer[idx].del) continue; + r = ma_hit2arc(&(z->buffer[idx]), Get_READ_LENGTH(R_INF, v>>1), Get_READ_LENGTH(R_INF, w>>1), + fg->max_hang, fg->max_hang_rate, fg->min_ovlp, &t0); + if(r < 0) continue; + if((t0.ul>>32) != v || t0.v != w) continue; + t0.ou = ((z->buffer[idx].bl>OU_MASK)?OU_MASK:z->buffer[idx].bl); + // if((v>>1) == 8340 && (w>>1) == 8352) { + // fprintf(stderr, "[M::%s] v>>1::%u(%c), w>>1::%u(%c), t0.ou::%u\n", + // __func__, (v>>1), "+-"[v&1], (w>>1), "+-"[w&1], t0.ou); + // } + + + idx = get_specific_overlap(&(src[w>>1]), w>>1, v>>1); + if(idx < 0 || src[w>>1].buffer[idx].del) continue; + r = ma_hit2arc(&(src[w>>1].buffer[idx]), Get_READ_LENGTH(R_INF, w>>1), Get_READ_LENGTH(R_INF, v>>1), + fg->max_hang, fg->max_hang_rate, fg->min_ovlp, &t1); + if(r < 0) continue; + if((t1.ul>>32) != (w^1) || t1.v != (v^1)) continue; + t1.ou = ((src[w>>1].buffer[idx].bl>OU_MASK)?OU_MASK:src[w>>1].buffer[idx].bl); + // if((v>>1) == 8340 && (w>>1) == 8352) { + // fprintf(stderr, "[M::%s] v>>1::%u(%c), w>>1::%u(%c), t1.ou::%u\n", + // __func__, (v>>1), "+-"[v&1], (w>>1), "+-"[w&1], t1.ou); + // } + + if(trans_check(fg, &t0, b) && trans_check(fg, &t1, b)) { + push_flex_asg_t(fg, &t0); push_flex_asg_t(fg, &t1); + } + } + } +} + +uint32_t append_trans_check(flex_asg_t *fg, uint64_t *a, uint64_t a_n) +{ + ma_hit_t_alloc* src = fg->src; int32_t idx, r; + uint32_t i, k, v, w; ma_hit_t_alloc *z; asg_arc_t t0, t1; + for (i = 0; i < a_n; i++) { + v = a[i]; + z = &(src[v>>1]); + for (k = i + 1; k < a_n; k++) { + w = a[k]^1; + idx = get_specific_overlap(z, v>>1, w>>1); + if(idx < 0 || z->buffer[idx].del) return 0; + r = ma_hit2arc(&(z->buffer[idx]), Get_READ_LENGTH(R_INF, v>>1), Get_READ_LENGTH(R_INF, w>>1), + fg->max_hang, fg->max_hang_rate, fg->min_ovlp, &t0); + if(r < 0) return 0; + if((t0.ul>>32) != v || t0.v != w) return 0; + t0.ou = ((z->buffer[idx].bl>OU_MASK)?OU_MASK:z->buffer[idx].bl); + // if((v>>1) == 8340 && (w>>1) == 8352) { + // fprintf(stderr, "[M::%s] v>>1::%u(%c), w>>1::%u(%c), t0.ou::%u\n", + // __func__, (v>>1), "+-"[v&1], (w>>1), "+-"[w&1], t0.ou); + // } + + + idx = get_specific_overlap(&(src[w>>1]), w>>1, v>>1); + if(idx < 0 || src[w>>1].buffer[idx].del) return 0; + r = ma_hit2arc(&(src[w>>1].buffer[idx]), Get_READ_LENGTH(R_INF, w>>1), Get_READ_LENGTH(R_INF, v>>1), + fg->max_hang, fg->max_hang_rate, fg->min_ovlp, &t1); + if(r < 0) return 0; + if((t1.ul>>32) != (w^1) || t1.v != (v^1)) return 0; + t1.ou = ((src[w>>1].buffer[idx].bl>OU_MASK)?OU_MASK:src[w>>1].buffer[idx].bl); + } + } + return 1; +} + +uint32_t iter_contain_g(R_to_U* rI, flex_asg_t *fg, uint32_t v0, asg64_v *b, asg64_v *st, float ou_rat, uint32_t only_trans_nn) +{ + uint32_t v, w = (uint32_t)-1, x, i, kv, kw, ulen, cnt = 0, st_n, m, is_purge; + asg_arc_t *s; flex_asg_e_retrive_t rr; + b->n = st->n = ulen = 0; kv_push(uint64_t, *st, v0); + while (st->n) { + v = kv_pop(*st); kv = kw = (uint32_t)-1; ulen = 0; + if(fg->g->seq_vis[v>>1]) continue; + while ((!(fg->g->seq_vis[v>>1])) && (is_contain_r((*rI), (v>>1)))) {///push a unitig + kv = get_flex_arcs(fg, v, &w, 1); ulen++; + kv_push(uint64_t, *b, v); + if(kv == 1) { + flex_arcs0(s, (*fg), w); + w = s->v; + kw = get_flex_arcs(fg, w^1, NULL, 0); + if(kw == 1) v = w; + else break; + } else { + break; + } + } + // if((v0>>1) == 12321 || (v0>>1) == 12334) { + // fprintf(stderr, "0[M::%s] v0>>1::%u(%c), b->n::%u, ulen::%u\n", + // __func__, (v0>>1), "+-"[v0&1], (uint32_t)b->n, ulen); + // } + if((!ulen) || (fg->g->seq_vis[v>>1]) || (!(is_contain_r((*rI), (v>>1))))) { + for (i = b->n - ulen; i < b->n; i++) { + fg->g->seq_vis[b->a[i]>>1] = 1; b->a[i] |= ((uint64_t)0x100000000); + } + continue; + } + // fprintf(stderr, "1[M::%s] v0>>1::%u(%c), b->n::%u, ulen::%u\n", + // __func__, (v0>>1), "+-"[v0&1], (uint32_t)b->n, ulen); + + for (i = 0; i < b->n; i++) { + if(b->a[i]&(0x100000000)) continue; + fg->g->seq_vis[b->a[i]>>1] = 2; + } + // fprintf(stderr, "2[M::%s] v0>>1::%u(%c), b->n::%u, ulen::%u\n", + // __func__, (v0>>1), "+-"[v0&1], (uint32_t)b->n, ulen); + for (i = 0, st_n = st->n; i < b->n; i++) { + if(b->a[i]&(0x100000000)) continue; + if(detect_tip2(fg, b->a[i]>>1, st, ou_rat)) break; + } + if(i >= b->n) is_purge = 1; + else is_purge = 0; + // fprintf(stderr, "3[M::%s] v0>>1::%u(%c), b->n::%u, ulen::%u\n", + // __func__, (v0>>1), "+-"[v0&1], (uint32_t)b->n, ulen); + for (i = m = st_n; i < st->n; i++) { + if(fg->g->seq_vis[st->a[i]]&128) fg->g->seq_vis[st->a[i]] -= 128; + ///append edges to all nodes, instead of non-contained only + // if(is_contain_r((*rI), (st->a[i]>>1))) continue; + st->a[m++] = st->a[i]; + } + st->n = m; + // if((v0>>1) == 12321 || (v0>>1) == 12334) { + // fprintf(stderr, "4[M::%s] v0>>1::%u(%c), b->n::%u, i::%u\n", + // __func__, (v0>>1), "+-"[v0&1], (uint32_t)b->n, i); + // } + if(is_purge && only_trans_nn) { + is_purge = append_trans_check(fg, st->a + st_n, st->n-st_n); + } + + if(is_purge) { + for (i = 0; i < b->n; i++) { + x = ((uint32_t)b->a[i])>>1; + // if((v0>>1) == 12321 || (v0>>1) == 12334) { + // fprintf(stderr, "del::[M::%s] x::%u, seq_vis::%u\n", __func__, x, fg->g->seq_vis[x]); + // } + if(fg->g->seq_vis[x]&2) { + asg_seq_del(fg->g, x); cnt++; + } + fg->g->seq_vis[x] = 0; + } + append_notrans_e(fg, st->a + st_n, st->n-st_n, b); + st->n = st_n; + return cnt; + } + for (i = 0; i < b->n; i++) { + if(b->a[i]&(0x100000000)) continue; + fg->g->seq_vis[b->a[i]>>1] = 1; + } + st->n = st_n; + + rr.i[0] = 0; rr.i[1] = (uint32_t)-1; + while(1) { + s = iter_flex_asg(fg, &rr, v); + if(!s) break; + if(s->del) continue; + if(fg->g->seq_vis[s->v>>1]) continue; + if(!is_contain_r((*rI), (s->v>>1))) continue; + kv_push(uint64_t, *st, s->v); + } + } + for (i = 0; i < b->n; i++) fg->g->seq_vis[((uint32_t)b->a[i])>>1] = 0; + return cnt; +} + +void flex_asg_t_cleanup(flex_asg_t *fg) +{ + asg_arc_t *p; uint32_t i; + if(fg->n) { + for (i = 0; i < fg->n; i++) { + if(fg->a[i].del) continue; + p = asg_arc_pushp(fg->g); + *p = fg->a[i]; + } + free(fg->g->idx); + fg->g->idx = 0; + fg->g->is_srt = 0; + } else if(fg->need_srt){ + fg->g->is_srt = 0; + } + asg_cleanup(fg->g); + // asg_symm(fg->g); + // asg_arc_del_trans_ul(fg->g, fg->gap_fuzz); +} + +void asg_arc_cut_contain(flex_asg_t *fg, asg64_v *in, asg64_v *in0, R_to_U* rI, float ou_rat, uint32_t only_trans_nn) +{ + // fprintf(stderr, "+[M::%s]\n", __func__); + asg64_v tx = {0,0,0}, tx0 = {0,0,0}, *b = NULL, *b0 = NULL; + uint32_t v, w = (uint32_t)-1, n_vtx = fg->g->n_seq<<1, cnt = 0; asg_arc_t *s; + b = in?in:&tx; b0 = in0?in0:&tx0; b->n = b0->n = 0; + fg->pi.n = fg->n = 0; memset(fg->idx, -1, (fg->g->n_seq<<1)*sizeof(*(fg->idx))); + fg->need_srt = 0; + + memset(fg->g->seq_vis, 0, sizeof(*(fg->g->seq_vis))*n_vtx); + for (v = 0; v < n_vtx; ++v) { + // if((v>>1) == 6236) { + // fprintf(stderr, "[M::%s] v>>1::%u(%c), del::%u, contain::%u, get_arcs(v)::%u, get_arcs(v^1)::%u\n", + // __func__, (v>>1), "+-"[v&1], g->seq[v>>1].del, is_contain_r((*rI), (v>>1)), + // get_arcs(g, v, NULL, 0), get_arcs(g, v^1, NULL, 0)); + // } + // if((v>>1) == 749651) { + // fprintf(stderr, "+[M::%s] v>>1::%u(%c), del::%u, contain::%u, fg->n::%u, fg->need_srt::%u\n", + // __func__, (v>>1), "+-"[v&1], fg->g->seq[v>>1].del, is_contain_r((*rI), (v>>1)), (uint32_t)fg->n, (uint32_t)fg->need_srt); + // } + if (fg->g->seq[v>>1].del) continue; + if(!is_contain_r((*rI), (v>>1))) continue; + if(get_flex_arcs(fg, v^1, &w, 1) == 1) { + flex_arcs0(s, (*fg), w); + if(get_flex_arcs(fg, s->v^1, NULL, 0) == 1) continue; + } + // if((v>>1) == 12321 || (v>>1) == 12334) { + // fprintf(stderr, "-[M::%s] v>>1::%u(%c), del::%u, contain::%u, fg->n::%u, fg->need_srt::%u\n", + // __func__, (v>>1), "+-"[v&1], fg->g->seq[v>>1].del, is_contain_r((*rI), (v>>1)), (uint32_t)fg->n, (uint32_t)fg->need_srt); + // } + + cnt += iter_contain_g(rI, fg, v, b, b0, ou_rat, only_trans_nn); + // if((v>>1) == 12321 || (v>>1) == 12334) { + // fprintf(stderr, "*[M::%s] v>>1::%u(%c), del::%u, contain::%u, fg->n::%u, fg->need_srt::%u\n", + // __func__, (v>>1), "+-"[v&1], fg->g->seq[v>>1].del, is_contain_r((*rI), (v>>1)), (uint32_t)fg->n, (uint32_t)fg->need_srt); + // } + } + // stats_sysm(g); + if(!in) {free(tx.a);} if(!in0) {free(tx0.a);} + if(cnt > 0) flex_asg_t_cleanup(fg); + // fprintf(stderr, "-[M::%s]\n", __func__); +} + +void label_contain_dup(asg_t *g, R_to_U* rI, uint32_t v0, asg64_v *b, asg64_v *dump) +{ + asg_arc_t *av; uint32_t nv, v, i; + if(!is_contain_r((*rI), (v0>>1))) return; + b->n = 0; kv_push(uint64_t, *b, v0); + while (b->n) { + v = kv_pop(*b); + if(g->seq_vis[v]&1) continue; + kv_push(uint64_t, *dump, v); + g->seq_vis[v] |= 1; + av = asg_arc_a(g, v); + nv = asg_arc_n(g, v); + for (i = 0; i < nv; ++i) { + if(av[i].del || (g->seq_vis[av[i].v]&1) || (!is_contain_r((*rI), (av[i].v>>1)))) continue; + kv_push(uint64_t, *b, av[i].v); + } + } +} + +/** +void asg_arc_contain_trans_del(asg_t *g, asg64_v *in, asg64_v *in0, R_to_U* rI, float ou_rat) +{ + uint64_t n_vtx = g->n_seq<<1, i, k, v, w, nv, kv; asg_arc_t *av; + memset(g->seq_vis, 0, sizeof((*g->seq_vis))*n_vtx); + for (v = 0; v < n_vtx; ++v) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (i = kv = 0; i < nv; i++) { + if(av[i].del) continue; + if(is_contain_r((*rI), (av[i].v>>1))) kv++; + g->seq_vis[av[i].v] = 1; + } + if(kv <= 0) { + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + g->seq_vis[av[i].v] = 0; + } + continue; + } + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + if(!(is_contain_r((*rI), (av[i].v>>1)))) continue; + + } + + + + if ((g->seq[v>>1].del) || (g->seq_vis[v]&1)) continue; + if(!is_contain_r((*rI), (v>>1))) continue; + // if(get_arcs(g, v, &w, 1) == 1) { + // w = g->arc[w].v; + // if(get_arcs(g, w^1, NULL, 0) == 1) continue; + // } + in0->n = 0; + label_contain_dup(g, rI, v, in, in0); + label_contain_dup(g, rI, v^1, in, in0); + } +} +**/ + +uint32_t if_false_bub_links(uint32_t v, asg_t *g, buf_t *x, asg64_v *b, uint32_t bs, int32_t check_dist) +{ + uint32_t i, mm = 1; + if (g->seq[v>>1].del) return 0; + for (i = bs; i < b->n; i++) { + g->arc[b->a[i]].del = 1; + asg_arc_del(g, g->arc[b->a[i]].v^1, (g->arc[b->a[i]].ul>>32)^1, 1); + } + if (asg_arc_n(g, v) < 2 || get_arcs(g, v, NULL, 0) < 2) mm = 0; + + if(mm) { + mm = 0; + if(asg_bub_pop1_primary_trio(g, NULL, v, check_dist, x, (uint32_t)-1, (uint32_t)-1, 0, + NULL, NULL, NULL, 0, 0, NULL)) { + + for (i = bs; i < b->n; i++) { + g->arc[b->a[i]].del = 0; + asg_arc_del(g, g->arc[b->a[i]].v^1, (g->arc[b->a[i]].ul>>32)^1, 0); + } + + asg_arc_t *av = asg_arc_a(g, v); uint32_t nv = asg_arc_n(g, v); + for (i = 0, b->n = bs; i < nv; i++) { + if (av[i].del) continue; + av[i].del = 1; asg_arc_del(g, av[i].v^1, (av[i].ul>>32)^1, 1); + kv_push(uint64_t, *b, ((uint64_t)(av-g->arc+i))); + } + + if(asg_bub_pop1_primary_trio(g, NULL, x->S.a[0]^1, check_dist, x, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { + mm = 1; + } + } + } + + for (i = bs; i < b->n; i++) { + g->arc[b->a[i]].del = 0; + asg_arc_del(g, g->arc[b->a[i]].v^1, (g->arc[b->a[i]].ul>>32)^1, 0); + } + + return mm; +} + +void asg_arc_cut_bub_links(asg_t *g, asg64_v *in, float len_rat, float sec_len_rat, float ou_rat, uint32_t is_ou, uint64_t check_dist, ma_hit_t_alloc *rev, R_to_U* rI, int32_t max_ext) +{ + asg64_v tx = {0,0,0}, *b = NULL; + uint32_t v, w, t, k, i, n_vtx = g->n_seq<<1, nv, nw, kv, kw, kol, bn, me, mu, cnt = 0, sec_check; + asg_arc_t *av, *aw, *ref; + buf_t x; memset(&x, 0, sizeof(x)); x.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + + if(in) b = in; + else b = &tx; + b->n = 0; + + for (v = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + if(g->seq_vis[v] == 0) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if (nv < 2) continue; + + for (i = kv = kol = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; kol += av[i].ol; + } + if(kv < 2) continue;//must have at least one exact and one inexact + + kv_push(uint64_t, *b, ((((uint64_t)(kol))<<32) | v)); + } + } + + if(rev && rI) memset(g->seq_vis, 0, g->n_seq*2*sizeof(uint8_t)); + radix_sort_srt64(b->a, b->a + b->n); bn = b->n; + for (k = 0; k < bn; k++) { + v = (uint32_t)b->a[k]; + if (g->seq[v>>1].del) continue; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + if (nv < 2 || get_arcs(g, v, NULL, 0) < 2) continue; + + for (i = 0, b->n = bn, sec_check = 0; i < nv; i++) { + if (av[i].del) continue; + + w = av[i].v^1; nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); + if(nw < 2) break; + + for (t = kw = 0, me = mu = (uint32_t)-1; t < nw; t++) { + if(aw[t].del) continue; + kw++; + if(aw[t].v == (v^1)) continue;//note: me is the shortest edge except aw[t], so here is continue + if(aw[t].ol < me) me = aw[t].ol; + if(aw[t].ou < mu) mu = aw[t].ou; + kv_push(uint64_t, *b, ((uint64_t)(aw-g->arc+t))); + } + if(kw < 2) break; + + if(av[i].ol > me*len_rat && av[i].ol > me*sec_len_rat) break; + if(av[i].ol > me*len_rat) sec_check++; + if(is_ou && av[i].ou > mu*ou_rat) break; + } + + if(i < nv) continue; + + if(sec_check) { + for (i = 0, ref = NULL; i < nv; i++) {//forward + if (av[i].del) continue; + if(!ref) { + ref = &(av[i]); + } else { + if(trans_path_check(ref->v, av[i].v, g, rev, rI, max_ext, b)!=1) break; + } + } + + if(i < nv) { + if (b->n < bn + 2) continue;///less than two edges + for (i = bn, ref = NULL; i < b->n; i++) { + if(g->arc[b->a[i]].del) continue; + if(get_arcs(g, g->arc[b->a[i]].ul>>32, NULL, 0)!=2) break; + if(!ref) { + ref = &(g->arc[b->a[i]]); + } else { + if(trans_path_check(ref->v, g->arc[b->a[i]].v, g, rev, rI, max_ext, b)!=1) break; + } + } + if(i < b->n) continue; + } + } + + if(if_false_bub_links(v, g, &x, b, bn, check_dist)) { + for (i = 0; i < nv; ++i) { + if (av[i].del) continue; + av[i].del = 1; asg_arc_del(g, av[i].v^1, (av[i].ul>>32)^1, 1); + } + cnt++; + } + } + + // stats_sysm(g); + if(!in) free(tx.a); + free(x.a); free(x.S.a); free(x.T.a); free(x.b.a); free(x.e.a); + if(cnt > 0) asg_cleanup(g); +} + +void asg_arc_cut_complex_bub_links(asg_t *g, asg64_v *in, float len_rat, float ou_rat, uint32_t is_ou, bub_label_t *b_mask_t) +{ + asg64_v tx = {0,0,0}, *b = NULL; + uint32_t v, w, t, k, i, n_vtx = g->n_seq<<1, nv, nw, kv, kw, kol, me, mu, cnt = 0, bn; + asg_arc_t *av, *aw; + + if(in) b = in; + else b = &tx; + b->n = 0; + + for (v = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + if(g->seq_vis[v] == 0) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if (nv < 2) continue; + + for (i = kv = kol = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; kol += av[i].ol; + } + if(kv < 2) continue;//must have at least one exact and one inexact + + kv_push(uint64_t, *b, ((((uint64_t)(kol))<<32) | v)); + } + } + + radix_sort_srt64(b->a, b->a + b->n); bn = b->n; + for (k = 0; k < bn; k++) { + v = (uint32_t)b->a[k]; + if (g->seq[v>>1].del) continue; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + if (nv < 2 || get_arcs(g, v, NULL, 0) < 2) continue; + + for (i = 0; i < nv; i++) { + if (av[i].del) continue; + + w = av[i].v^1; nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); + if(nw < 2) break; + + for (t = kw = 0, me = mu = (uint32_t)-1; t < nw; t++) { + if(aw[t].del) continue; + kw++; + if(aw[t].v == (v^1)) continue;//note: me is the shortest edge except aw[t], so here is continue + if(aw[t].ol < me) me = aw[t].ol; + if(aw[t].ou < mu) mu = aw[t].ou; + } + if(kw < 2) break; + + if(av[i].ol > me*len_rat) break; + if(is_ou && av[i].ou > mu*ou_rat) break; + } + + if(i < nv) continue; + + for (i = 0; i < nv; ++i) { + if (av[i].del) continue; + av[i].del = 1; asg_arc_del(g, av[i].v^1, (av[i].ul>>32)^1, 1); + kv_push(uint64_t, *b, ((uint64_t)(av-g->arc+i))); + } + // b->a[cnt++] = v; + } + + if(b->n > bn) { + asg_arc_identify_simple_bubbles_multi(g, b_mask_t, 0); + for (k = bn, cnt = 0; k < b->n; k++) { + // if(g->arc[b->a[k]].del) continue; + v = g->arc[b->a[k]].ul>>32; w = g->arc[b->a[k]].v; + if(g->seq_vis[v] || g->seq_vis[v^1] || g->seq_vis[w] || g->seq_vis[w^1]) { + cnt++; continue; + } + g->arc[b->a[k]].del = 0; asg_arc_del(g, g->arc[b->a[k]].v^1, (g->arc[b->a[k]].ul>>32)^1, 0); + } + } + // stats_sysm(g); + if(!in) free(tx.a); + if(cnt > 0) asg_cleanup(g); +} + +#define LIM_LEN 100 + +uint32_t asg_cut_semi_circ(asg_t *g, uint32_t lim_len, uint32_t is_clean) +{ + uint32_t v, t, k, e, ss, i, n_vtx = g->n_seq<<1, nv, kv, nw, cnt = 0; + asg_arc_t *av, *aw; + + for (v = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + + av = asg_arc_a(g, v^1); nv = asg_arc_n(g, v^1); + if(nv <= 1) continue; + for (i = kv = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; if(kv > 1) break; + } + if(kv <= 1) continue; + + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if(nv < 1) continue; + for (i = kv = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; if(kv > 1) break; + } + if(kv != 1) continue; + + for (i = 0; i < nv; ++i) { + if(av[i].del) continue; + t = follow_limit_path(g, v, &e, &ss, NULL, lim_len); + if(ss > lim_len || t == LONG_TIPS || t == LOOP || t == END_TIPS) break;//as kv == 1 + aw = asg_arc_a(g, v^1); nw = asg_arc_n(g, v^1); + for (k = 0; k < nw; k++) { + if (aw[k].del) continue; + if (aw[k].v == (e^1)) { + aw[k].del = 1; + asg_arc_del(g, aw[k].v^1, (aw[k].ul>>32)^1, 1); + cnt++; + } + } + break; //as kv == 1 + } + } + + if(cnt > 0 && is_clean) asg_cleanup(g); + return cnt; +} + +uint32_t asg_cut_chimeric_bub(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, uint32_t normal_len, uint32_t is_clean, telo_end_t *te) +{ + asg64_v tx = {0,0,0}, *b = NULL; + uint32_t v, w, nw, k, n_vtx = g->n_seq<<1, ei[2] = {0}, e, ss, cnt = 0; + asg_arc_t *aw; + if(in) b = in; + else b = &tx; + b->n = 0; + // fprintf(stderr, "[M::%s]\n", __func__); + for (v = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + if(te && te->hh[v>>1]) continue; + ///note: ei[0] and ei[1] are the edge idx + if((get_arcs(g, v, &(ei[0]), 1)!=1) || (get_arcs(g, v^1, &(ei[1]), 1)!=1)) continue; + assert((g->arc[ei[0]].ul>>32) == v && (g->arc[ei[1]].ul>>32) == (v^1)); + if((get_arcs(g, g->arc[ei[0]].v^1, NULL, 0)!=2) || (get_arcs(g, g->arc[ei[1]].v^1, NULL, 0)!=2)) continue; + if(!if_sup_chimeric(&(src[v>>1]), g->seq[v>>1].len, b, 1)) continue; + w = g->arc[ei[0]].v^1; + aw = asg_arc_a(g, w); nw = asg_arc_n(g, w); + for (k = 0; k < nw; k++) { + if (aw[k].del) continue; + if (aw[k].v == (v^1)) { + ss = k; continue; + } + break; + } + // assert(aw[ss].v == (v^1));//this assert does not work, just ignore + if(follow_limit_path(g, aw[k].v, &e, &ss, NULL, (uint32_t)-1) != TWO_INPUT) continue; + if(ss > normal_len) { + w = e; + aw = asg_arc_a(g, w); nw = asg_arc_n(g, w); + for (k = ss = 0; k < nw; k++) { + if (aw[k].del) continue; + ss++; e = aw[k].v; + if(ss > 1) break; + } + if(ss == 1 && e == g->arc[ei[1]].v) asg_seq_del(g, v>>1), cnt++; + } + } + + if(!in) free(tx.a); + if (is_clean && cnt > 0) asg_cleanup(g); + return cnt; +} + +void asg_iterative_semi_circ(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, uint32_t normal_len, uint32_t pop_chimer, telo_end_t *te) +{ + uint64_t occ = 0, s = 1; + while (s) { + s = asg_cut_semi_circ(g, LIM_LEN, 0); + if(pop_chimer) s = s + asg_cut_chimeric_bub(g, src, in, normal_len, 0, te); + occ += s; + } + + // stats_sysm(g); + if(occ) asg_cleanup(g); +} + +uint32_t asg_cut_large_indel(asg_t *g, asg64_v *in, int32_t max_ext, float ou_rat, uint32_t is_ou, uint32_t min_diff) +{ + asg64_v tx = {0,0,0}, *b = NULL; + uint32_t v, w, n_vtx = g->n_seq<<1, i, k, kv, kw, nv, nw, ou_max, ol_max, to_del, cnt = 0; + asg_arc_t *av, *aw, *ve, *we; + if(in) b = in; + else b = &tx; + b->n = 0; + + for (v = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + if(g->seq_vis[v] == 0) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if (nv < 2) continue; + + for (i = kv = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + } + if(kv < 2) continue; + + for (i = 0; i < nv; ++i) { + if(av[i].del || av[i].no_l_indel) continue; + ///means there is a large indel at this edge + kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); + } + } + } + + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + if(g->arc[(uint32_t)b->a[k]].del) continue; + + v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; + if(g->seq[v>>1].del || g->seq[w>>1].del) continue; + nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); + av = asg_arc_a(g, v); aw = asg_arc_a(g, w); + if(nv<=1 && nw <= 1) continue; + + for (i = kv = ou_max = ol_max = 0, ve = NULL; i < nv; ++i) { + if(av[i].del) continue; + if(av[i].v == (w^1)) ve = &(av[i]); + kv++; + if(ou_max < av[i].ou) ou_max = av[i].ou; + if(ol_max < av[i].ol) ol_max = av[i].ol; + } + if (kv < 1) continue; + if (kv >= 2) { + if (is_ou && ve->ou > ou_max*ou_rat) continue; + if ((ve->ol + min_diff) > ol_max) continue; + } + + + for (i = kw = ou_max = ol_max = 0, we = NULL; i < nw; ++i) { + if(aw[i].del) continue; + if(aw[i].v == (v^1)) we = &(aw[i]); + kw++; + if(ou_max < aw[i].ou) ou_max = aw[i].ou; + if(ol_max < aw[i].ol) ol_max = aw[i].ol; + } + if (kw < 1) continue; + if (kw >= 2) { + if (is_ou && we->ou > ou_max*ou_rat) continue; + if ((we->ol + min_diff) > ol_max) continue; + } + + if (kv <= 1 && kw <= 1) continue; + + to_del = 0; + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (asg_topocut_aux(g, w^1, max_ext) < max_ext) to_del = 1; + } else if (kv == 1) { + if (asg_topocut_aux(g, v^1, max_ext) < max_ext) to_del = 1; + } + + if (to_del) { + ve->del = we->del = 1, ++cnt; + } + } + // stats_sysm(g); + if(!in) free(tx.a); + if (cnt > 0) asg_cleanup(g); + return cnt; +} + +void debug_edges(asg64_v *dbg, uint32_t *l, uint32_t l_n) { + uint32_t k, k_n, i, m; + for (i = k = 0; i < l_n; i++) { + fprintf(stderr, "# gid-%u: %u\n", i, l[i]); + for (k_n = k + l[i]; k < k_n; k++) { + dbg->a[k] <<= 32; dbg->a[k] += i; + } + } + fprintf(stderr, "# dbg->n: %u\n", (uint32_t)dbg->n); + + radix_sort_srt64(dbg->a, dbg->a + dbg->n); + for (k = 1, i = 0; k <= dbg->n; k++) { + if(k == dbg->n || (dbg->a[k]>>32) != (dbg->a[i]>>32)) { + if(k - i < l_n) { + + for (m = i; m < k; m++) { + fprintf(stderr, "eid->%lu, gid->%u\n", dbg->a[m]>>32, (uint32_t)dbg->a[m]); + } + } + i = k; + } + } +} + +void print_node(asg_t *sg, uint32_t src) +{ + asg_arc_t *av; uint32_t nv, v, i; + v = src<<1; + av = asg_arc_a(sg, v); nv = asg_arc_n(sg, v); + fprintf(stderr, "\n%.*s(%c)\tnv:%u\n", + (int32_t)Get_NAME_LENGTH(R_INF, v>>1), Get_NAME(R_INF, v>>1), "+-"[v&1], nv); + for (i = 0; i < nv; i++) { + fprintf(stderr, "++++++%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\tdel:%u\n", + (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], av[i].ul>>33, + (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].v>>1, av[i].ol, av[i].ou, av[i].del); + } + + v = (src<<1)+1; + av = asg_arc_a(sg, v); nv = asg_arc_n(sg, v); + fprintf(stderr, "\n%.*s(%c)\tnv:%u\n", + (int32_t)Get_NAME_LENGTH(R_INF, v>>1), Get_NAME(R_INF, v>>1), "+-"[v&1], nv); + for (i = 0; i < nv; i++) { + fprintf(stderr, "------%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\tdel:%u\n", + (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], av[i].ul>>33, + (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].v>>1, av[i].ol, av[i].ou, av[i].del); + } +} + +void print_vw_edge(asg_t *sg, uint32_t vid, uint32_t wid, const char *cmd) +{ + asg_arc_t *av; uint32_t nv, i, sid, eid; + if(vid >= sg->n_seq || wid >= sg->n_seq) return; + + sid = vid; eid = wid; + av = asg_arc_a(sg, (sid<<1)); nv = asg_arc_n(sg, (sid<<1)); + for (i = 0; i < nv; i++) { + if((av[i].v>>1) == eid) { + fprintf(stderr, "[%s]\t%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\tdel:%u\n", cmd, + (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], av[i].ul>>33, + (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].v>>1, av[i].ol, av[i].ou, av[i].del); + break; + } + } + av = asg_arc_a(sg, ((sid<<1)+1)); nv = asg_arc_n(sg, ((sid<<1)+1)); + for (i = 0; i < nv; i++) { + if((av[i].v>>1) == eid) { + fprintf(stderr, "[%s]\t%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\tdel:%u\n", cmd, + (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], av[i].ul>>33, + (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].v>>1, av[i].ol, av[i].ou, av[i].del); + break; + } + } + + sid = wid; eid = vid; + av = asg_arc_a(sg, (sid<<1)); nv = asg_arc_n(sg, (sid<<1)); + for (i = 0; i < nv; i++) { + if((av[i].v>>1) == eid) { + fprintf(stderr, "[%s]\t%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\tdel:%u\n", cmd, + (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], av[i].ul>>33, + (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].v>>1, av[i].ol, av[i].ou, av[i].del); + break; + } + } + av = asg_arc_a(sg, ((sid<<1)+1)); nv = asg_arc_n(sg, ((sid<<1)+1)); + for (i = 0; i < nv; i++) { + if((av[i].v>>1) == eid) { + fprintf(stderr, "[%s]\t%.*s(%c)\t%.*s(%c)\tol:%u\tou:%u\tdel:%u\n", cmd, + (int32_t)Get_NAME_LENGTH(R_INF, (av[i].ul>>33)), Get_NAME(R_INF, (av[i].ul>>33)), "+-"[(av[i].ul>>32)&1], av[i].ul>>33, + (int32_t)Get_NAME_LENGTH(R_INF, (av[i].v>>1)), Get_NAME(R_INF, (av[i].v>>1)), "+-"[av[i].v&1], av[i].v>>1, av[i].ol, av[i].ou, av[i].del); + break; + } + } + // if(i >= nv) fprintf(stderr, "[%s]\tno edges\n", cmd); +} + +void prt_spec_edge(asg_t *rg, ma_hit_t_alloc *src, uint32_t tot_rid, uint32_t vid, uint32_t wid, ug_opt_t *uopt, const char *cmd) +{ + if(vid >= tot_rid) return; + uint32_t k, qn, tn; int32_t r; asg_arc_t p; ma_hit_t_alloc *s = &(src[vid]); + for (k = 0; k < s->length; k++) { + qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); + if(qn == vid && tn == wid) { + r = ma_hit2arc(&(s->buffer[k]), rg->seq[qn].len, rg->seq[tn].len, uopt->max_hang, asm_opt.max_hang_rate, uopt->min_ovlp, &p); + fprintf(stderr, "[M::%s::]%s\tqn::%u(%c)\tq::[%u,\t%u)\t%c\ttn::%u(%c)\tt::[%u,\t%u)\n", + __func__, cmd, qn, (r>=0)?("+-"[(p.ul>>32)&1]):('*'), Get_qs(s->buffer[k]), Get_qe(s->buffer[k]), + "+-"[s->buffer[k].rev], + tn, (r>=0)?("+-"[p.v&1]):('*'), Get_ts(s->buffer[k]), Get_te(s->buffer[k])); + } + } +} + +int32_t gen_spec_edge(asg_t *rg, ug_opt_t *uopt, uint32_t v, uint32_t w, asg_arc_t *t) +{ + uint32_t k, qn, tn; int32_t r; ma_hit_t_alloc *s = &(uopt->sources[v>>1]); asg_arc_t p; + for (k = 0; k < s->length; k++) { + qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); + if(tn != (w>>1)) continue; + r = ma_hit2arc(&(s->buffer[k]), rg->seq[qn].len, rg->seq[tn].len, uopt->max_hang, asm_opt.max_hang_rate, uopt->min_ovlp, &p); + if(r < 0) continue; + if((p.ul>>32) != v || p.v != w) continue; + *t = p; t->ou = 0; + return 1; + } + return -1; +} + +void filter_sg_by_ug(asg_t *rg, ma_ug_t *ug, ug_opt_t *uopt) +{ + uint32_t i, m, v, w, nv, n_vx, vx, wx; int32_t r; + asg_arc_t *av = NULL; ma_utg_t *u = NULL; asg_arc_t *p, t; + n_vx = rg->n_seq; rg->n_arc = 0; + for (v = 0; v < n_vx; v++) rg->seq[v].del = (!!1); + + for (i = 0; i < ug->g->n_seq; ++i) { + ug->g->seq[i].c = PRIMARY_LABLE;; + if(ug->g->seq[i].del) continue; + u = &(ug->u.a[i]); + for (m = 0; m < u->n; m++) rg->seq[u->a[m]>>33].del = (!!0); + for (m = 0; (m + 1) < u->n; m++) { + v = u->a[m]>>32; w = u->a[m+1]>>32; + r = gen_spec_edge(rg, uopt, v, w, &t); + assert(r >= 0); p = asg_arc_pushp(rg); *p = t; + + r = gen_spec_edge(rg, uopt, w^1, v^1, &t); + assert(r >= 0); p = asg_arc_pushp(rg); *p = t; + } + + + v = i<<1; nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); + for (m = 0; m < nv; m++) { + if(av[m].del) continue; + w = av[m].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)); + + r = gen_spec_edge(rg, uopt, vx, wx, &t); + assert(r >= 0); p = asg_arc_pushp(rg); *p = t; + + // r = gen_spec_edge(rg, uopt, wx^1, vx^1, &t); + // assert(r >= 0); p = asg_arc_pushp(rg); *p = t; + } + + v = (i<<1)+1; nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); + for (m = 0; m < nv; m++) { + if(av[m].del) continue; + w = av[m].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)); + + r = gen_spec_edge(rg, uopt, vx, wx, &t); + assert(r >= 0); p = asg_arc_pushp(rg); *p = t; + + // r = gen_spec_edge(rg, uopt, wx^1, vx^1, &t); + // assert(r >= 0); p = asg_arc_pushp(rg); *p = t; + } + + if(u->circ) { + v = w = i<<1; + 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)); + r = gen_spec_edge(rg, uopt, vx, wx, &t); + assert(r >= 0); p = asg_arc_pushp(rg); *p = t; + + v = w = (i<<1)^1; + 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)); + r = gen_spec_edge(rg, uopt, vx, wx, &t); + assert(r >= 0); p = asg_arc_pushp(rg); *p = t; + } + } + + free(rg->idx); + rg->idx = 0; + rg->is_srt = 0; + asg_cleanup(rg); + asg_symm(rg); + + + /*******************************for debug************************************/ + // ma_ug_t *dbg = ma_ug_gen(rg); + // for (i = 0; i < dbg->g->n_seq; ++i) dbg->g->seq[i].c = PRIMARY_LABLE; + // cmp_untig_graph(dbg, ug); + /*******************************for debug************************************/ +} + +void prt_specfic_sge(asg_t *g, uint32_t src, uint32_t dst, const char* cmd) +{ + uint32_t k, v, w, nv; asg_arc_t *av; + fprintf(stderr, "[M::%s::%s] src::%.*s(id::%u), dst::%.*s(id::%u)\n", __func__, cmd, + (int)Get_NAME_LENGTH(R_INF, src), Get_NAME(R_INF, src), src, + (int)Get_NAME_LENGTH(R_INF, dst), Get_NAME(R_INF, dst), dst); + v = src<<1; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (k = 0; k < nv; ++k) { + if ((av[k].v>>1) == dst) { + w = av[k].v; + fprintf(stderr, "[M::%s::]\t%.*s(%c)\t%.*s(%c)\tou::%u\tdel::%u\n", __func__, + (int)Get_NAME_LENGTH(R_INF, (v>>1)), Get_NAME(R_INF, (v>>1)), "+-"[v&1], + (int)Get_NAME_LENGTH(R_INF, (w>>1)), Get_NAME(R_INF, (w>>1)), "+-"[w&1], av[k].ou, av[k].del); + } + } + + v = (src<<1)+1; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (k = 0; k < nv; ++k) { + if ((av[k].v>>1) == dst) { + w = av[k].v; + fprintf(stderr, "[M::%s::]\t%.*s(%c)\t%.*s(%c)\tou::%u\tdel::%u\n", __func__, + (int)Get_NAME_LENGTH(R_INF, (v>>1)), Get_NAME(R_INF, (v>>1)), "+-"[v&1], + (int)Get_NAME_LENGTH(R_INF, (w>>1)), Get_NAME(R_INF, (w>>1)), "+-"[w&1], av[k].ou, av[k].del); + } + } +} + +flex_asg_t *init_flex_asg_t(asg_t *g, ma_hit_t_alloc* src, int64_t min_ovlp, int64_t max_hang, int64_t max_hang_rate, int64_t gap_fuzz) +{ + flex_asg_t *z; CALLOC(z, 1); + z->g = g; z->src = src; z->min_ovlp = min_ovlp; z->gap_fuzz = gap_fuzz; + z->max_hang = max_hang; z->max_hang_rate = max_hang_rate; + MALLOC(z->idx, (z->g->n_seq<<1)); memset(z->idx, -1, (z->g->n_seq<<1)*sizeof(*(z->idx))); + return z; +} + +void des_flex_asg_t(flex_asg_t *z) +{ + free(z->idx); free(z->pi.a); free(z->a); +} + + +void print_raw_u2rgfa_seq(all_ul_t *aln, R_to_U* rI, uint32_t is_detail) +{ + uint64_t id, a_n, k, z; uc_block_t *a = NULL; + kvec_t(uint8_t) ff; kv_init(ff); + for (id = 0; id < aln->n; id++) { + a = aln->a[id].bb.a; a_n = aln->a[id].bb.n; + if(a_n == 0) continue; + fprintf(stderr,"\n%.*s\tid::%lu\trlen::%u", (int32_t)aln->nid.a[id].n, aln->nid.a[id].a, id, aln->a[id].rlen); + kv_resize(uint8_t, ff, a_n); memset(ff.a, 0, a_n*sizeof((*(ff.a)))); + if(is_detail) { + fprintf(stderr, "\n"); + for (k = 0; k < a_n; k++) { + if(ff.a[k]) continue; + for (z = k; z != (uint32_t)-1; z = a[z].aidx) { + fprintf(stderr, "%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tid::%u\ttl::%lu\tc::%u\n", + (int)Get_NAME_LENGTH(R_INF, a[z].hid), Get_NAME(R_INF, a[z].hid), "+-"[a[z].rev], + a[z].qs, a[z].qe, a[z].ts, a[z].te, a[z].hid, Get_READ_LENGTH(R_INF, a[z].hid), + rI?is_contain_r((*rI), a[z].hid):0); + assert(ff.a[z] == 0); + ff.a[z] = 1; + } + fprintf(stderr, "************\n"); + } + } else { + fprintf(stderr, "\t"); + for (k = 0; k < a_n; k++) { + if(ff.a[k]) continue; + for (z = k; z != (uint32_t)-1; z = a[z].aidx) { + fprintf(stderr, "%.*s\t", + (int)Get_NAME_LENGTH(R_INF, a[z].hid), Get_NAME(R_INF, a[z].hid)); + assert(ff.a[z] == 0); + ff.a[z] = 1; + } + fprintf(stderr, "\n"); + } + } + } + kv_destroy(ff); +} + + +void post_rescue(ug_opt_t *uopt, asg_t *sg, ma_hit_t_alloc *src, ma_hit_t_alloc *rev, R_to_U* rI, bub_label_t *b_mask_t, long long no_trio_recover, uint8_t *cmk) +{ + rescue_contained_reads_aggressive(NULL, sg, src, uopt->coverage_cut, rI, uopt->max_hang, uopt->min_ovlp, 10, 1, 0, NULL, NULL, b_mask_t); + rescue_missing_overlaps_aggressive(NULL, sg, src, uopt->coverage_cut, rI, uopt->max_hang, uopt->min_ovlp, 1, 0, NULL, b_mask_t); + rescue_missing_overlaps_backward(NULL, sg, src, uopt->coverage_cut, rI, uopt->max_hang, uopt->min_ovlp, 10, 1, 0, b_mask_t); + if(cmk) rescue_chimeric_reads_aggressive(NULL, sg, src, uopt->coverage_cut, rI, uopt->max_hang, uopt->min_ovlp, 10, 1, 0, NULL, NULL, b_mask_t, cmk); + // rescue_wrong_overlaps_to_unitigs(NULL, sg, sources, reverse_sources, coverage_cut, ruIndex, + // max_hang_length, mini_overlap_length, bubble_dist, NULL); + // rescue_no_coverage_aggressive(sg, sources, reverse_sources, &coverage_cut, ruIndex, max_hang_length, + // mini_overlap_length, bubble_dist, 10); + set_hom_global_coverage(&asm_opt, sg, uopt->coverage_cut, src, rev, rI, uopt->max_hang, uopt->min_ovlp); + rescue_bubble_by_chain(sg, uopt->coverage_cut, src, rev, (asm_opt.max_short_tip*2), 0.15, 3, rI, 0.05, 0.9, uopt->max_hang, uopt->min_ovlp, 10, uopt->gap_fuzz, b_mask_t, no_trio_recover, cmk); +} + +void ul_clean_gfa(ug_opt_t *uopt, asg_t *sg, ma_hit_t_alloc *src, ma_hit_t_alloc *rev, R_to_U* rI, int64_t clean_round, double min_ovlp_drop_ratio, double max_ovlp_drop_ratio, +double ou_drop_rate, int64_t max_tip, int64_t gap_fuzz, bub_label_t *b_mask_t, int32_t is_ou, int32_t is_trio, uint32_t ou_thres, uint8_t *cmk, char *o_file) +{ + #define HARD_OU_DROP 0.75 + #define HARD_OL_DROP 0.6 + #define HARD_OL_SEC_DROP 0.85 + #define HARD_ORTHOLOGY_DROP 0.4 + double step = + (clean_round==1?max_ovlp_drop_ratio:((max_ovlp_drop_ratio-min_ovlp_drop_ratio)/(clean_round-1))); + double drop = min_ovlp_drop_ratio; + int64_t i; asg64_v bu = {0,0,0}, ba = {0,0,0}; uint32_t l_drop = 2000; flex_asg_t *fg = NULL; uint32_t min_diff = 0, step_diff = 2000; + if(is_ou) fg = init_flex_asg_t(sg, uopt->sources, uopt->min_ovlp, uopt->max_hang, asm_opt.max_hang_rate, gap_fuzz); + // prt_specfic_sge(sg, 22708, 22646, "--sa--"); + // if(is_ou) update_sg_uo(sg, src);///do not do it here + // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.dirty.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); + // exit(1); + // print_raw_u2rgfa_seq(&UL_INF, rI, 1); + // exit(1); + // fprintf(stderr, "%.*s\tid::%u\tis_c::%u\n", + // (int)Get_NAME_LENGTH(R_INF, 10785), Get_NAME(R_INF, 10785), 10785, is_contain_r((*rI), 10785)); + // fprintf(stderr, "%.*s\tid::%u\tis_c::%u\n", + // (int)Get_NAME_LENGTH(R_INF, 10790), Get_NAME(R_INF, 10790), 10790, is_contain_r((*rI), 10790)); + // fprintf(stderr, "%.*s\tid::%u\tis_c::%u\n", + // (int)Get_NAME_LENGTH(R_INF, 10805), Get_NAME(R_INF, 10805), 10805, is_contain_r((*rI), 10805)); + // fprintf(stderr, "%.*s\tid::%u\tis_c::%u\n", + // (int)Get_NAME_LENGTH(R_INF, 10809), Get_NAME(R_INF, 10809), 10809, is_contain_r((*rI), 10809)); + // fprintf(stderr, "%.*s\tid::%u\tis_c::%u\n", + // (int)Get_NAME_LENGTH(R_INF, 10819), Get_NAME(R_INF, 10819), 10819, is_contain_r((*rI), 10819)); + // debug_info_of_specfic_node("m64011_190830_220126/47516220/ccs", sg, rI, "beg-0"); + // debug_info_of_specfic_node("bcb40bcc-d9cf-48e6-88ee-47ac3dde22ff", sg, rI, "beg-0"); + + if(asm_opt.is_ont) asg_arc_cut_weak(sg, &bu, max_tip, 0.975, 0, is_ou, 0, 1, 16, UL_COV_THRES-1, 0, rev, NULL, NULL); + + asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te);///p_telo + // fprintf(stderr, "[M::%s] count_edges_v_w(sg, 49778, 49847)->%ld\n", __func__, count_edges_v_w(sg, 49778, 49847)); + // if(is_ou) dedup_contain_g(uopt, sg); + for (i = 0; i < clean_round; i++, drop += step) { + if(drop > max_ovlp_drop_ratio) drop = max_ovlp_drop_ratio; + if(is_ou) { + if(drop <= 0.500001) min_diff = step_diff>>1; + else min_diff = step_diff; + } + + if(asm_opt.is_ont) { + asg_arc_cut_weak(sg, &bu, max_tip, 0.975, 0, is_ou, 0, 1, 16, UL_COV_THRES-1, 0, rev, NULL, NULL); + asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); + } + // fprintf(stderr, "(0):i->%ld, drop->%f\n", i, drop); + // prt_specfic_sge(sg, 22708, 22646, "--0--"); + + // print_vw_edge(sg, 34156, 34090, "0"); + // stats_chimeric(sg, src, &bu); + if(!is_ou) asg_iterative_semi_circ(sg, src, &bu, max_tip, 1, uopt->te);///p_telo + asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 1); + asg_arc_cut_chimeric(sg, src, &bu, is_ou?ou_thres:(uint32_t)-1, uopt->te);///p_telo + + asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); + // prt_specfic_sge(sg, 22708, 22646, "--1--"); + asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 0); + asg_arc_cut_inexact(sg, src, &bu, max_tip, is_ou, is_trio, min_diff, ou_drop_rate/**, NULL**//**&dbg**/); + // debug_edges(&dbg, d, 2); + asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); + // prt_specfic_sge(sg, 22708, 22646, "--2--"); + + asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 1); + asg_arc_cut_length(sg, &bu, max_tip, drop, ou_drop_rate, is_ou, is_trio, 1, min_diff, 1, NULL, NULL, NULL); + asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); + + // if(i == 0) { + // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.dirty3.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); + // // exit(1); + // } + + // prt_specfic_sge(sg, 22708, 22646, "--3--"); + // if(is_ou) asg_arc_cut_contain(fg, &bu, &ba, rI, ((i+1)te); + // prt_specfic_sge(sg, 22708, 22646, "--5--"); + + /** + if(cmk && asm_opt.chemical_cov > FORCE_CUT) { + asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 0); + asg_arc_cut_chimeric_cmk(sg, &bu, max_tip, 1.1, 1.1, is_ou, 1, 1, 1, cmk, asm_opt.chemical_cov); + asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); + } + **/ + + + if(is_ou) { + if(ul_refine_alignment(uopt, sg)) update_sg_uo(sg, src); + if(clean_contain_g(uopt, sg, 1)) update_sg_uo(sg, src); + } + } + + // prt_specfic_sge(sg, 22708, 22646, "--sb--"); + + if(asm_opt.is_ont) { + asg_arc_cut_weak(sg, &bu, max_tip, 0.975, 0, is_ou, 0, 1, 16, UL_COV_THRES-1, 0, rev, NULL, NULL); + asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); + } + + if(is_ou) min_diff = step_diff; + // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.dirty4.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); + // debug_info_of_specfic_node("7b70a587-f56c-48ac-adf8-b98a67365063_2", sg, rI, "end"); + // debug_info_of_specfic_node("m64011_190830_220126/95028102/ccs", sg, rI, "end"); + if(is_ou) { + asg_arc_cut_contain(fg, &bu, &ba, rI, ou_drop_rate, 0); + asg_arc_cut_contain(fg, &bu, &ba, rI, -1, 1); + // dedup_contain_g(uopt, sg); + if(clean_contain_g(uopt, sg, 1)) update_sg_uo(sg, src); + } + if(!is_ou) asg_iterative_semi_circ(sg, src, &bu, max_tip, 1, uopt->te); + + // prt_specfic_sge(sg, 22708, 22646, "--sb-0---"); + + + // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.dirty5.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); + + asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 0); + asg_cut_large_indel(sg, &bu, max_tip, HARD_OU_DROP, is_ou, min_diff);///shoule we ignore ou here? + asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); + + // prt_specfic_sge(sg, 22708, 22646, "--sb-1---"); + + // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.dirty6.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); + + if(!is_ou) { + ///asg_arc_del_triangular_directly might be unnecessary + asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 0); + asg_arc_cut_length(sg, &bu, max_tip, HARD_ORTHOLOGY_DROP/**min_ovlp_drop_ratio**/, ou_drop_rate, is_ou, 0/**is_trio**/, is_ou?1:0, min_diff, 1, rev, rI, NULL); + asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); + + // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.dirty7.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); + + asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 0); + asg_arc_cut_length(sg, &bu, max_tip, min_ovlp_drop_ratio, ou_drop_rate, is_ou, 0/**is_trio**/, is_ou?1:0, min_diff, 1, rev, rI, &l_drop); + asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); + } else { + min_diff = step_diff; l_drop = 6000; + asg_arc_identify_simple_bubbles_multi(sg, b_mask_t, 0); + asg_arc_cut_length(sg, &bu, max_tip, 0.3, 0.9, is_ou, is_trio, 1, min_diff, 8, NULL, NULL, &l_drop); + asg_arc_cut_tips(sg, max_tip, &bu, is_ou, is_ou?rI:NULL, uopt->te); + } + + // prt_specfic_sge(sg, 22708, 22646, "--sb-2---"); + + // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.dirty8.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); + + if(!is_ou) asg_cut_semi_circ(sg, LIM_LEN, 1); + + // prt_specfic_sge(sg, 22708, 22646, "--sb-3---"); + /** + rescue_contained_reads_aggressive(NULL, sg, src, uopt->coverage_cut, rI, uopt->max_hang, uopt->min_ovlp, 10, 1, 0, NULL, NULL, b_mask_t); + rescue_missing_overlaps_aggressive(NULL, sg, src, uopt->coverage_cut, rI, uopt->max_hang, uopt->min_ovlp, 1, 0, NULL, b_mask_t); + rescue_missing_overlaps_backward(NULL, sg, src, uopt->coverage_cut, rI, uopt->max_hang, uopt->min_ovlp, 10, 1, 0, b_mask_t); + // rescue_wrong_overlaps_to_unitigs(NULL, sg, sources, reverse_sources, coverage_cut, ruIndex, + // max_hang_length, mini_overlap_length, bubble_dist, NULL); + // rescue_no_coverage_aggressive(sg, sources, reverse_sources, &coverage_cut, ruIndex, max_hang_length, + // mini_overlap_length, bubble_dist, 10); + set_hom_global_coverage(&asm_opt, sg, uopt->coverage_cut, src, rev, rI, uopt->max_hang, uopt->min_ovlp); + rescue_bubble_by_chain(sg, uopt->coverage_cut, src, rev, (asm_opt.max_short_tip*2), 0.15, 3, rI, 0.05, 0.9, uopt->max_hang, uopt->min_ovlp, 10, uopt->gap_fuzz, b_mask_t); + **/ + post_rescue(uopt, sg, src, rev, rI, b_mask_t, is_ou, cmk); + + // prt_specfic_sge(sg, 22708, 22646, "--sb-4---"); + + ug_ext_gfa(uopt, sg, ug_ext_len); + + // if(is_ou) dedup_contain_g(uopt, sg); + + // prt_specfic_sge(sg, 22708, 22646, "--sb-5---"); + // exit(1) + + output_unitig_graph(sg, uopt->coverage_cut, o_file, src, rI, uopt->max_hang, uopt->min_ovlp); + // exit(1); + // flat_bubbles(sg, ruIndex->is_het); free(ruIndex->is_het); ruIndex->is_het = NULL; + flat_soma_v(sg, src, rI); + + ///note: although the above functions will not change the UL part, but it will change the read graph + ///so it is necessary to run update_sg_uo + if(is_ou) { + update_sg_uo(sg, src); + } + if(is_ou) { + des_flex_asg_t(fg); free(fg); + } + // prt_specfic_sge(sg, 22708, 22646, "--sb-6---"); + // print_debug_gfa(sg, NULL, uopt->coverage_cut, "UL.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 1, 0, 0); + // exit(1); + // print_node(sg, 17078); //print_node(sg, 8311); print_node(sg, 8294); + + free(bu.a); free(ba.a); +} + +int32_t gen_ext_tip(uint32_t v, asg_t *sg, ug_opt_t *uopt, uint8_t *ff, uint32_t min_ovlp, uint64_t *res, uint64_t *path_len) +{ + uint32_t k, qn, tn, cc, ccu; int32_t r; asg_arc_t p, pmax; + ma_hit_t_alloc *s = &(uopt->sources[v>>1]); memset(&pmax, 0, sizeof(pmax)); pmax.ol = 0; + for (k = 0; k < s->length; k++) { + qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); + r = ma_hit2arc(&(s->buffer[k]), sg->seq[qn].len, sg->seq[tn].len, uopt->max_hang, asm_opt.max_hang_rate, uopt->min_ovlp, &p); + if(r < 0) continue; + if((p.ul>>32) != v) continue; + if(p.ol < min_ovlp) continue; + if(p.ol > pmax.ol) pmax = p; + } + if(pmax.ol == 0) return 0; + + tn = pmax.v>>1; + if((!(sg->seq[tn].del)) || (ff[tn])) return -1;///not a tip + get_R_to_U(uopt->ruIndex, tn, &cc, &ccu); + if(ccu == 1) return -1; + if((cc != (uint32_t)-1) && + ((!(sg->seq[cc].del)) || (ff[cc]))) { + return -1;///contained in an existing read + } + + if((*path_len) >= sg->seq[v>>1].len) (*path_len) -= sg->seq[v>>1].len; + else (*path_len) = 0; + (*path_len) += (uint32_t)(pmax.ul) + sg->seq[pmax.v>>1].len; + + uint32_t v0 = v; (*res) = pmax.v; + v = (pmax.v^1); s = &(uopt->sources[v>>1]); pmax.ol = 0; + for (k = 0; k < s->length; k++) { + qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); + r = ma_hit2arc(&(s->buffer[k]), sg->seq[qn].len, sg->seq[tn].len, uopt->max_hang, asm_opt.max_hang_rate, uopt->min_ovlp, &p); + if(r < 0) continue; + if((p.ul>>32) != v) continue; + if(p.ol < min_ovlp) continue; + if(p.ol > pmax.ol) pmax = p; + } + if((pmax.v^1) == v0) { + ff[(*res)>>1] = 1; return 1; + } + (*res) = (uint64_t)-1; return -1;///not the longest overlap +} + +void ug_ext_gfa(ug_opt_t *uopt, asg_t *sg, uint32_t max_len) +{ + asg_arc_t *av; asg64_v res, idx; kv_init(res); kv_init(idx); + uint32_t v, nv, k, z, nvtx = sg->n_seq<<1, tip_n = uopt->tipsLen + 1, s, e; + uint8_t *ff; CALLOC(ff, sg->n_seq); int32_t rr; uint64_t v0, w, bn, plen; + asg_arc_t t, *p; + for (v = 0; v < nvtx; v++) { + if(sg->seq[v>>1].del) continue; + av = asg_arc_a(sg, v); nv = asg_arc_n(sg, v); + for (k = 0; k < nv && av[k].del; k++); + if(k < nv) continue; + for (z = 0, v0 = v, rr = 0, bn = res.n, plen = sg->seq[v0>>1].len; z < tip_n || plen < max_len; z++) { + rr = gen_ext_tip(v0, sg, uopt, ff, 2000, &w, &plen); + if(rr <= 0) break; + kv_push(uint64_t, res, (v0<<32)|w); v0 = w; + } + if(rr < 0 || (z >= tip_n && plen >= max_len)) { + for (z = bn; z < res.n; z++) { + ff[((uint32_t)res.a[z])>>1] = 0; + } + res.n = bn; + } + if(res.n > bn) { + bn <<= 32; bn |= (uint64_t)res.n; + kv_push(uint64_t, idx, bn); + } + } + + if(idx.n > 0) { + for (k = 0; k < idx.n; k++) { + s = idx.a[k]>>32; e = (uint32_t)idx.a[k]; + for (z = s; z < e; z++) { + v = res.a[z]>>32; w = (uint32_t)res.a[z]; + assert((!sg->seq[v>>1].del) && (sg->seq[w>>1].del)); + sg->seq[w>>1].del = 0; + rr = gen_spec_edge(sg, uopt, v, w, &t); assert(rr >= 0); + p = asg_arc_pushp(sg); *p = t; + rr = gen_spec_edge(sg, uopt, w^1, v^1, &t); assert(rr >= 0); + p = asg_arc_pushp(sg); *p = t; + } + } + + free(sg->idx); sg->idx = 0; sg->is_srt = 0; asg_cleanup(sg); + fprintf(stderr, "[M::%s::] # tips::%u\n", __func__, (uint32_t)idx.n); + } + + free(ff); kv_destroy(res); kv_destroy(idx); +} + + +bubble_type *gen_bubble_chain(asg_t *sg, ma_ug_t *ug, ug_opt_t *uopt, uint8_t **ir_het, uint8_t avoid_het) +{ + kvec_asg_arc_t_warp new_rtg_edges; + kv_init(new_rtg_edges.a); + hap_cov_t *cov = NULL; + bubble_type *bub = NULL; + + asg_t *copy_sg = copy_read_graph(sg); + ma_ug_t *copy_ug = copy_untig_graph(ug); + // fprintf(stderr, "0[M::%s]\n", __func__); + adjust_utg_by_primary(©_ug, copy_sg, TRIO_THRES, uopt->sources, uopt->reverse_sources, uopt->coverage_cut, + uopt->tipsLen, uopt->tip_drop_ratio, uopt->stops_threshold, uopt->ruIndex, uopt->chimeric_rate, uopt->drop_ratio, + uopt->max_hang, uopt->min_ovlp, &new_rtg_edges, &cov, uopt->b_mask_t, 0, 0); + ma_ug_destroy(copy_ug); copy_ug = NULL; + asg_destroy(copy_sg); copy_sg = NULL; + // fprintf(stderr, "1[M::%s]\n", __func__); + CALLOC(bub, 1); (*ir_het) = cov->t_ch->ir_het; + cov->t_ch->ir_het = NULL; cov->is_r_het = NULL; + if(!avoid_het) { + identify_bubbles(ug, bub, (*ir_het), NULL); + } else { + uint8_t *pr_het; CALLOC(pr_het, sg->n_seq); + identify_bubbles_recal_poy(sg, ug, bub, pr_het, uopt->sources, uopt->ruIndex, NULL); + free(pr_het); + } + + // fprintf(stderr, "2[M::%s]\n", __func__); + kv_destroy(new_rtg_edges.a); destory_hap_cov_t(&cov); + if(asm_opt.purge_level_primary == 0) {///all nodes are het + uint32_t k; + for (k = 0; k < ug->g->n_seq; k++) { + if(IF_HOM(k, *bub)) bub->index[k] = bub->f_bub+1; + } + } + // fprintf(stderr, "3[M::%s]\n", __func__); + return bub; +} + +void clear_path_dp_t(path_dp_t *x, asg_t *g) +{ + uint32_t n_vx = g->n_seq<<1; + x->ref.n = x->pat.n = x->pat_cor.n = 0; + kv_resize(uint8_t, x->g_flt, n_vx); x->g_flt.n = n_vx; + memset(x->g_flt.a, 0, sizeof(*(x->g_flt.a))*x->g_flt.n); +} + +void clear_ubuf_t(ubuf_t *x, asg_t *g, all_ul_t *ul_idx, int32_t up_dp) +{ + uint32_t n_vx = g->n_seq<<1; + x->a.n = x->S.n = x->T.n = x->b.n = x->e.n = 0; + kv_resize(uinfo_t, x->a, n_vx); x->a.n = n_vx; memset(x->a.a, 0, sizeof(*(x->a.a))*x->a.n); + if(up_dp) clear_path_dp_t(&(x->dp), g); +} + +uint64_t get_ul_read_weight(all_ul_t *ul, uint32_t *prg, uinfo_t *g_idx, ul_vec_t *p, uint32_t ii, uint32_t v, uint32_t w) +{ + assert((!p->bb.a[ii].base)&&(p->bb.a[ii].hid == (v>>1))&&(p->bb.a[ii].el)&&(p->bb.a[ii].pchain)); + if(p->bb.a[ii].aidx == (uint32_t)-1) return 0; ///not connected + uc_block_t *li = NULL, *lk = NULL; uint32_t li_v, lk_v; + li = &(p->bb.a[ii]); li_v = (((uint32_t)(li->hid))<<1)|((uint32_t)(li->rev)); //li_v^=1; + if(li_v != v) return 0; + + for (lk = &(p->bb.a[li->aidx]), w^=1; lk; ) { + lk_v = (((uint32_t)(lk->hid))<<1)|((uint32_t)(lk->rev)); //lk_v^=1; + while (lk_v != (w^1)) { + if(g_idx[w].p==(uint32_t)-1) break; + w = g_idx[w].p; + } + + if(lk_v == (w^1)) { + + } + + lk = ((lk->aidx==(uint32_t)-1)?NULL:&(p->bb.a[lk->aidx])); + + } + return 1; +} + +#define arc_first(g, v) ((g)->arc[(g)->idx[(v)]>>32]) +#define arc_cnt(g, v) ((uint32_t)(g)->idx[(v)]) + +uint64_t ulg_len_check(asg_t *g, uint32_t v, uc_block_t *p) +{ + // if(!(((v&1) && (p->ts==0)) || (((v&1)==0) && (p->te==g->seq[v>>1].len)))) { + // fprintf(stderr, "\n[M::%s::] v>>1:%u, v&1:%u, ts:%u, te:%u, tlen:%u, qs:%u, qe:%u, pidx:%u, aidx:%u, flag:%u\n", + // __func__, v>>1, v&1, p->ts, p->te, g->seq[v>>1].len, p->qs, p->qe, p->pidx, p->aidx, flag); + // } + // assert(((v&1) && (p->ts==0)) || (((v&1)==0) && (p->te==g->seq[v>>1].len))); + if(!(((v&1) && (p->ts==0)) || (((v&1)==0) && (p->te==g->seq[v>>1].len)))) return 0; + // if((v&1) && (p->ts!=0)) return 0; + // if(((v&1)==0) && (p->te!=g->seq[v>>1].len)) return 0; + if(p->ts==0 && p->te==g->seq[v>>1].len) return 1; + int32_t ol = arc_first(g, v).ol;///max len + int32_t tl = p->te - p->ts; + tl -= ol; + if(tl > 20000 || tl > (g->seq[v>>1].len*0.2)) return 1; + return 0; +} + +void update_l_coord(asg_t *g, uint64_t o_s, uint32_t v, uc_block_t *p, uint64_t *s, uint64_t *e) +{ + // if(!(((v&1) && (p->ts==0)) || (((v&1)==0) && (p->te==g->seq[v>>1].len)))) { + // fprintf(stderr, "\n[M::%s::] v>>1:%u, v&1:%u, ts:%u, te:%u, tlen:%u\n", + // __func__, v>>1, v&1, p->ts, p->te, g->seq[v>>1].len); + // } + // assert(((v&1) && (p->ts==0)) || (((v&1)==0) && (p->te==g->seq[v>>1].len))); + // assert((v&1) && (p->ts==0)); + // assert(((v&1)==0) && (p->te==g->seq[v>>1].len)); + if(((v&1)==0)) { + (*s) = o_s + p->ts; (*e) = o_s + p->te; + } else { + (*s) = o_s + g->seq[v>>1].len - p->te; + (*e) = o_s + g->seq[v>>1].len - p->ts; + } +} + +int64_t gen_ul_pat_seq(uc_block_t *a, path_dp_t *b, all_ul_t *ul, uint64_t idx, asg_t *g, uint32_t v, uint32_t is_backward, uint64_t *rl) +{ + uint32_t m = 0, pv, ai, pi; uint64_t *t, l = 0, tt, s, e; b->pat.n = 0; b->pat_cor.n = 0; + if(is_backward) { + for (ai = idx, l = 0; ai != (uint32_t)-1; ai = a[ai].pidx) { + pv = (((uint32_t)(a[ai].hid))<<1)|((uint32_t)(a[ai].rev)); pv^=1; + if((a[ai].pidx != (uint32_t)-1) && (!ulg_len_check(g, pv, &(a[ai])))) break; + if((b->pat.n > 0) && (!ulg_len_check(g, pv^1, &(a[ai])))) break; + if(pv == v) m++; + kv_pushp(uint64_t, b->pat, &t); + update_l_coord(g, l, pv, &(a[ai]), &s, &e); + kv_push(uint64_t, b->pat_cor, ((s<<32)|e)); + (*t) = pv; (*t) |= (l<<32); + + if(a[ai].pidx != (uint32_t)-1) l += a[ai].pdis; + else l += g->seq[pv>>1].len; + } + } else { + for (ai = idx, pi = 0; ai != (uint32_t)-1; ai = a[ai].aidx) { + pv = (((uint32_t)(a[ai].hid))<<1)|((uint32_t)(a[ai].rev)); + if((a[ai].aidx != (uint32_t)-1) && (!ulg_len_check(g, pv, &(a[ai])))) break; + if((pi > 0) && (!ulg_len_check(g, pv^1, &(a[ai])))) break; + l = ai; pi++; + } + + ai = l; + kv_resize(uint64_t, b->pat, pi); b->pat.n = pi; + kv_resize(uint64_t, b->pat_cor, pi); b->pat_cor.n = pi; + for (l = 0; ai != (uint32_t)-1 && ai >= idx; ai = a[ai].pidx) { + pv = (((uint32_t)(a[ai].hid))<<1)|((uint32_t)(a[ai].rev)); + pi--; if(pv == v) m++; + b->pat.a[pi] = pv; b->pat.a[pi] |= (l<<32); + update_l_coord(g, l, pv, &(a[ai]), &s, &e); + b->pat_cor.a[pi] = ((s<<32)|e); + if(a[ai].pidx != (uint32_t)-1 && a[ai].pidx >= idx) l += a[ai].pdis; + else l += g->seq[pv>>1].len; + } + assert(pi == 0); + + for (ai = 0; ai < b->pat.n; ai++) { + tt = (b->pat.a[ai]>>32) + g->seq[((uint32_t)b->pat.a[ai])>>1].len; + // if(l < tt) { + // fprintf(stderr, "\n[M::%s::] ai::%u, b->pat.n::%u, l::%lu, tt::%lu, beg::%lu\n", + // __func__, ai, (uint32_t)b->pat.n, l, tt, (b->pat.a[ai]>>32)); + // } + assert(l >= tt); + tt = l - tt; + b->pat.a[ai] = (uint32_t)b->pat.a[ai]; + b->pat.a[ai] += (tt<<32); + } + } + (*rl) = l; + + assert(m > 0); + return m; +} + +uint32_t get_arch_len(asg_t *g, uint32_t v, uint32_t w) +{ + + uint32_t i, an; asg_arc_t *av; + av = asg_arc_a(g, v); an = asg_arc_n(g, v); + for (i = 0; i < an; i++) { + if(av[i].del) continue; + if(av[i].v == w) return ((uint32_t)av[i].ul); + } + return (uint32_t)-1; +} + +void gen_ref_pat_seq(asg_t *g, ubuf_t *b, uint64_t rul, double diff_rate, uint32_t v, uint32_t w/**, uint32_t is_debug**/) +{ + int64_t ref_n = b->dp.ref.n, k; uint64_t x, l; uint32_t p, arc_l; + if(ref_n >= 2 && ((uint32_t)b->dp.ref.a[0]) == v && ((uint32_t)b->dp.ref.a[1]) == w) { + // if(is_debug) fprintf(stderr, "+[M::%s::] ref_n::%ld, rul::%lu\n", __func__, ref_n, rul); + if((ref_n) > 0 && ((b->dp.ref.a[ref_n-1]>>32) >= (rul*(1.0+diff_rate)))) { + for (k = ref_n-1; k >= 0; k--) { + if((b->dp.ref.a[k]>>32) < (rul*(1.0+diff_rate))) break; + b->dp.g_flt.a[(uint32_t)b->dp.ref.a[k]] = 0; + } + ref_n = k + 1; b->dp.ref.n = ref_n; + } else { + p = (uint32_t)b->dp.ref.a[ref_n-1]; p ^= 1; p = b->a.a[p].p; + for (l = b->dp.ref.a[ref_n-1]>>32; p != (uint32_t)-1; p = b->a.a[p].p) { + x = p^1; arc_l = get_arch_len(g, ((uint32_t)b->dp.ref.a[b->dp.ref.n-1]), x); + assert(arc_l != (uint32_t)-1); l += arc_l; + if(l >= (rul*(1.0+diff_rate))) break; + b->dp.g_flt.a[x] = 1; x += (l<<32); kv_push(uint64_t, b->dp.ref, x); + } + ref_n = b->dp.ref.n; + } + } else { + // if(is_debug) fprintf(stderr, "-[M::%s::] ref_n::%ld, rul::%lu\n", __func__, ref_n, rul); + b->dp.ref.n = 0; + for (k = 0; k < ref_n; k++) { + b->dp.g_flt.a[(uint32_t)b->dp.ref.a[k]] = 0; + } + + x = v; kv_push(uint64_t, b->dp.ref, x); b->dp.g_flt.a[x] = 1; + for (p = w^1, l = 0; p != (uint32_t)-1; p = b->a.a[p].p) { + x = p^1; arc_l = get_arch_len(g, ((uint32_t)b->dp.ref.a[b->dp.ref.n-1]), x); + assert(arc_l != (uint32_t)-1); l += arc_l; + if(l >= (rul*(1.0+diff_rate))) break; + b->dp.g_flt.a[x] = 1; x += (l<<32); kv_push(uint64_t, b->dp.ref, x); + } + ref_n = b->dp.ref.n; + } +} + +uint32_t quick_check(uc_block_t *a, asg_t *g, path_dp_t *b, double diff_rate, double filter_rate) +{ + uint64_t ref_l = 0, pat_l = 0, mm, min, max, l, k, s, e, match_s, match_e, unmatch_s, unmatch_e, match_l, unmatch_l; + if(b->ref.n == 0 || b->pat.n == 0) return 0; + assert(b->g_flt.a[(uint32_t)b->pat.a[0]]); + for (k = 1; k < b->pat.n; k++) {///k = 0, must be matched + if(b->g_flt.a[(uint32_t)b->pat.a[k]]) break; + } + if(k >= b->pat.n) return 0; + + ref_l = (b->ref.a[b->ref.n-1]>>32) + g->seq[((uint32_t)b->ref.a[b->ref.n-1])>>1].len; + pat_l = (b->pat.a[b->pat.n-1]>>32) + g->seq[((uint32_t)b->pat.a[b->pat.n-1])>>1].len; + mm = MIN(ref_l, pat_l); min = mm * (1.0 - diff_rate); max = mm * (1.0 + diff_rate); + + match_s = match_e = unmatch_s = unmatch_e = (uint64_t)-1; match_l = unmatch_l = 0; + for (k = 0; k < b->pat.n; k++) { + l = (b->pat.a[k]>>32) + g->seq[((uint32_t)b->pat.a[k])>>1].len; + s = b->pat_cor.a[k]>>32; e = (uint32_t)b->pat_cor.a[k]; + if(l <= min) { + if(unmatch_e == (uint64_t)-1 || s >= unmatch_e) { + if(unmatch_e != (uint64_t)-1) unmatch_l += unmatch_e - unmatch_s; + unmatch_s = s; unmatch_e = e; + } else { + if(e > unmatch_e) unmatch_e = e; + } + } + + if(l <= max) { + if(b->g_flt.a[(uint32_t)b->pat.a[k]]) { + if(match_e == (uint64_t)-1 || s >= match_e) { + if(match_e != (uint64_t)-1) match_l += match_e - match_s; + match_s = s; match_e = e; + } else { + if(e > match_e) match_e = e; + } + } + } + if(l > max) break; + } + + if(unmatch_e != (uint64_t)-1) unmatch_l += unmatch_e - unmatch_s; + if(match_e != (uint64_t)-1) match_l += match_e - match_s; + // fprintf(stderr, "[M::%s::] min::%lu, max::%lu, match_l::%lu, unmatch_l::%lu\n", __func__, + // min, max, match_l, unmatch_l); + if(match_l >= unmatch_l*filter_rate) return 1; + return 0; +} + +#define ul_dp_idx(dp, x, y) ((dp).m*(x)+(y)) +#define e_mdp 0 +#define ue_mdp 1 +#define lpat_dp 2 +#define lref_dp 3 +//0->match; 1->mismatch; 2->up (longer pat); 3->left (longer ref) +void init_ul_dp(asg_t *g, path_dp_t *dp) +{ + kv_resize(uint8_t, dp->m_dir, (dp->pat.n+1)*(dp->ref.n+1)); + kv_resize(int64_t, dp->m_score, (dp->pat.n+1)*(dp->ref.n+1)); + dp->n = dp->pat.n+1; dp->m = dp->ref.n+1; + /** + uint64_t k, s, e, sp, ep, sc; + dp->m_dir.a[0] = dp->m_score.a[0] = 0; ///[0, 0] + for (k = 1, sp = ep = (uint64_t)-1; k < dp->n; k++) {///pat; ul read + s = dp->pat.a[k-1]>>32; e = (dp->pat.a[k-1]>>32) + g->seq[(uint32_t)dp->pat.a[k-1]].len; sc = 0; + if(ep == (uint64_t)-1 || s >= ep) { + sc = e - s; sp = s; ep = e; + } else { + if(e > ep) sc = e - ep; + } + if(((uint32_t)dp->pat.a[k-1]) == ((uint32_t)dp->ref.a[0])) { + dp->m_score.a[ul_dp_idx(*dp, k, 0)] = dp->m_dir.a[ul_dp_idx(*dp, k, 0)] = 0; + } else { + dp->m_score.a[ul_dp_idx(*dp, k, 0)] = dp->m_score.a[ul_dp_idx(*dp, k-1, 0)] + sc; + dp->m_dir.a[ul_dp_idx(*dp, k, 0)] = lpat_dp; + } + } + + for (k = 1, sp = ep = (uint64_t)-1; k < dp->m; k++) {///ref; graph + s = dp->ref.a[k-1]>>32; e = (dp->ref.a[k-1]>>32) + g->seq[(uint32_t)dp->ref.a[k-1]].len; sc = 0; + if(ep == (uint64_t)-1 || s >= ep) { + sc = e - s; sp = s; ep = e; + } else { + if(e > ep) sc = e - ep; + } + dp->m_score.a[ul_dp_idx(*dp, 0, k)] = dp->m_score.a[ul_dp_idx(*dp, 0, k-1)] + sc; + dp->m_dir.a[ul_dp_idx(*dp, 0, k)] = lref_dp; + } + **/ + uint64_t k; int64_t min_weight = -1*((int64_t)(0xffffffff)); dp->m_dir.a[0] = dp->m_score.a[0] = 0; ///[0, 0] + + for (k = 1; k < dp->n; k++) {///pat; ul read + if(((uint32_t)dp->pat.a[k-1]) == ((uint32_t)dp->ref.a[0])) { + dp->m_score.a[ul_dp_idx(*dp, k, 0)] = dp->m_dir.a[ul_dp_idx(*dp, k, 0)] = 0; + } else { + dp->m_score.a[ul_dp_idx(*dp, k, 0)] = min_weight; + // dp->m_score.a[ul_dp_idx(*dp, k-1, 0)] - g->seq[((uint32_t)dp->pat.a[k-1])>>1].len; + dp->m_dir.a[ul_dp_idx(*dp, k, 0)] = lpat_dp; + } + } + + for (k = 1; k < dp->m; k++) {///ref; graph + dp->m_score.a[ul_dp_idx(*dp, 0, k)] = min_weight; + // dp->m_score.a[ul_dp_idx(*dp, 0, k-1)] - g->seq[((uint32_t)dp->ref.a[k-1])>>1].len; + dp->m_dir.a[ul_dp_idx(*dp, 0, k)] = lref_dp; + } +} + +uint64_t node_check(uint32_t ul_v, uint32_t g_v, uint32_t ul_v_len, uint32_t g_v_len, double diff_len, uint32_t ul_weight) +{ + if(ul_v != g_v) return 0; + uint32_t x = ((ul_v_len >= g_v_len)? (ul_v_len - g_v_len): (g_v_len - ul_v_len)); + if(x > g_v_len*diff_len) return 0; + if(g_v_len == 0) { + return ul_weight; + } else { + return (((double)(g_v_len-x))/((double)g_v_len))*ul_weight; + } +} + +void print_dp_matrix(path_dp_t *dp) +{ + uint64_t i, j; + for (i = 0; i < dp->n; i++) {//pat + for (j = 0; j < dp->m; j++) {//mat + fprintf(stderr, "%ld<%u>,\t", dp->m_score.a[ul_dp_idx(*dp, i, j)], dp->m_dir.a[ul_dp_idx(*dp, i, j)]); + } + fprintf(stderr, "\n"); + } + +} + +int64_t ul_dp0(bubble_type* bub, asg_t *g, path_dp_t *dp, double pass_thres/**, uint64_t is_debug**/) +{ + if(dp->pat.n < 2 || dp->ref.n < 2) return -1; + uint64_t i, j, d, w; int64_t sc0, sc1, sc2, sc, sc_i, sc_j; + init_ul_dp(g, dp); + // if(is_debug) { + // print_dp_matrix(dp); + // } + for (i = 1; i < dp->n; i++) {//pat + for (j = 1; j < dp->m; j++) {//mat + w = node_check(((uint32_t)dp->pat.a[i-1]), ((uint32_t)dp->ref.a[j-1]), + dp->pat.a[i-1]>>32, dp->ref.a[j-1]>>32, 0.04, g->seq[((uint32_t)dp->pat.a[i-1])>>1].len); + + if(w) { + // if(is_debug) fprintf(stderr, "\n[M::%s::] i::%lu, j::%lu, w::%lu\n", __func__, i, j, w); + dp->m_score.a[ul_dp_idx(*dp, i, j)] = dp->m_score.a[ul_dp_idx(*dp, i-1, j-1)] + w; + dp->m_dir.a[ul_dp_idx(*dp, i, j)] = e_mdp; + } else { + sc0 = dp->m_score.a[ul_dp_idx(*dp, i-1, j-1)] - + (int64_t)(MIN(g->seq[((uint32_t)dp->pat.a[i-1])>>1].len, g->seq[((uint32_t)dp->ref.a[j-1])>>1].len)); + sc1 = dp->m_score.a[ul_dp_idx(*dp, i-1, j)] - (int64_t)(g->seq[((uint32_t)dp->ref.a[j-1])>>1].len); + sc2 = dp->m_score.a[ul_dp_idx(*dp, i, j-1)] - (int64_t)(g->seq[((uint32_t)dp->pat.a[i-1])>>1].len); + + d = ue_mdp; sc = sc0; + if(sc < sc1) { + sc = sc1; d = lref_dp; + } + if(sc < sc2) { + sc = sc2; d = lpat_dp; + } + dp->m_score.a[ul_dp_idx(*dp, i, j)] = sc; + dp->m_dir.a[ul_dp_idx(*dp, i, j)] = d; + } + } + } + + sc = 0; sc_i = sc_j = -1; + for (j = 1, i = dp->n - 1; j < dp->m; j++) { + if(sc_i < 0 || sc < dp->m_score.a[ul_dp_idx(*dp, i, j)]) { + sc_i = i; sc_j = j; sc = dp->m_score.a[ul_dp_idx(*dp, i, j)]; + } + } + for (i = 1, j = dp->m - 1; i < dp->n; i++) { + if(sc_i < 0 || sc < dp->m_score.a[ul_dp_idx(*dp, i, j)]) { + sc_i = i; sc_j = j; sc = dp->m_score.a[ul_dp_idx(*dp, i, j)]; + } + } + + // if(is_debug) { + // fprintf(stderr, "[M::%s::] sc_i::%ld, sc_j::%ld, sc::%ld\n", __func__, sc_i, sc_j, sc); + // // print_dp_matrix(dp); + // } + + if (sc_i < 0 || sc_i == 1 || sc_j == 1) return 0; + int64_t match_all = 0, unmatch_all = 0, het_match_all = 0, het_unmatch_all = 0, het_occ = 0; + //pat_s = sc_i - 1; ref_s = ref_e = sc_j - 1; + for(i = sc_i, j = sc_j; i > 0 && j > 0;) { + d = dp->m_dir.a[ul_dp_idx(*dp, i, j)]; + //pat_s = i - 1; ref_s = j - 1; + // if(is_debug) fprintf(stderr, "[M::%s::] i::%lu, j::%lu, dir::%lu\n", __func__, i, j, d); + // if(pat_s == 0) continue; + if(d == e_mdp) { + // if(i != 1 || j != 1) {//skip (i == 1 && j == 1) + match_all += g->seq[((uint32_t)dp->pat.a[i-1])>>1].len; + if(!IF_HOM((((uint32_t)dp->pat.a[i-1])>>1), *bub)) { + het_match_all += g->seq[((uint32_t)dp->pat.a[i-1])>>1].len; + het_occ++; + } + i--; j--; + // if(is_debug) { + // fprintf(stderr, "[M::%s::] PAT::utg%.6dl(%c::len->%lu), REF::utg%.6dl(%c::len->%lu)\n", __func__, + // ((((uint32_t)dp->pat.a[i])>>1))+1, "+-"[((uint32_t)dp->pat.a[i])&1], dp->pat.a[i]>>32, + // ((((uint32_t)dp->ref.a[j])>>1))+1, "+-"[((uint32_t)dp->ref.a[j])&1], dp->ref.a[j]>>32); + // } + } + if(d == ue_mdp) { + unmatch_all += g->seq[((uint32_t)dp->pat.a[i-1])>>1].len; + if(!IF_HOM((((uint32_t)dp->pat.a[i-1])>>1), *bub)) { + het_unmatch_all += g->seq[((uint32_t)dp->pat.a[i-1])>>1].len; + } + i--; j--; + } + if(d == lpat_dp) { + j--; + } + if(d == lref_dp) { + unmatch_all += g->seq[((uint32_t)dp->pat.a[i-1])>>1].len; + if(!IF_HOM((((uint32_t)dp->pat.a[i-1])>>1), *bub)) { + het_unmatch_all += g->seq[((uint32_t)dp->pat.a[i-1])>>1].len; + } + i--; + } + } + // if(is_debug) { + // fprintf(stderr, "[M::%s::] het_occ::%ld, match_all::%ld, unmatch_all::%ld, het_match_all::%ld, het_unmatch_all::%ld\n", __func__, + // het_occ, match_all, unmatch_all, het_match_all, het_unmatch_all); + // } + + assert((j == 0) && (((uint32_t)dp->pat.a[i]) == ((uint32_t)dp->ref.a[j]))); + ///skip the beg node + match_all -= g->seq[((uint32_t)dp->pat.a[i])>>1].len; + if(!IF_HOM((((uint32_t)dp->pat.a[i])>>1), *bub)) { + het_match_all -= g->seq[((uint32_t)dp->pat.a[i])>>1].len; het_occ--; + } + + + if(het_occ < 1 || match_all == 0 || het_match_all == 0) return -1; + if(match_all <= (match_all + unmatch_all)*pass_thres) return -1; + if(het_match_all <= (het_match_all + het_unmatch_all)*pass_thres) return -1; + return (((double)het_match_all)/((double)(het_match_all + het_unmatch_all)))* + (((uint32_t)dp->pat_cor.a[i]) - (dp->pat_cor.a[i]>>32)); +} +uint64_t ul_dp(bubble_type* bub, all_ul_t *ul, ubuf_t *b, uint64_t *a, int64_t a_n, asg_t *g, uint32_t v, uint32_t w, uint32_t is_backward) +{ + int64_t i, m, a_i = -1; uc_block_t *p; uint32_t gv; uint64_t url; int64_t we; + for (i = m = 0; i < a_n; i++) { + p = &(ul->a[a[i]>>32].bb.a[(uint32_t)(a[i])]); + assert((!p->base)&&(p->hid == (v>>1))&&(p->el)/**&&(p->pchain)**/); + if(!p->pchain) continue; + gv = (((uint32_t)(p->hid))<<1)|((uint32_t)(p->rev)); + if(is_backward) { + gv ^= 1; + if(p->pidx == (uint32_t)-1) continue; + } else { + if(p->aidx == (uint32_t)-1) continue; + } + if(gv != v) continue; + // fprintf(stderr, "[M::%s::] i:%ld, a_n:%lu, v:%u, w:%u, ulid:%lu, uidx:%u, is_backward:%u\n", + // __func__, i, a_n, v, w, a[i]>>32, (uint32_t)(a[i]), is_backward); + // if(v == 6 && w == 5 && (a[i]>>32) == 95) { + // int64_t z; + // for (z = 0; z < ul->a[a[i]>>32].bb.n; z++) { + // fprintf(stderr, "[M::%s::vid->%u] qs:%u, qe:%u, qlen:%u, ts:%u, te:%u, tlen:%u\n", __func__, + // (((uint32_t)(ul->a[a[i]>>32].bb.a[z].hid))<<1)|((uint32_t)(ul->a[a[i]>>32].bb.a[z].rev)), + // ul->a[a[i]>>32].bb.a[z].qs, ul->a[a[i]>>32].bb.a[z].qe, ul->a[a[i]>>32].rlen, + // ul->a[a[i]>>32].bb.a[z].ts, ul->a[a[i]>>32].bb.a[z].te, g->seq[ul->a[a[i]>>32].bb.a[z].hid].len); + // } + // } + if(ulg_len_check(g, v, p) == 0) continue;///too short + m++; a_i = i; + } + + if(m == 0) return 0; + // uint32_t is_debug = (v == 231); + // if(is_debug) { + // fprintf(stderr, "\n+[M::%s::] m->%ld, ulid->%lu\n", __func__, m, a[a_i]>>32); + // } + + p = &(ul->a[a[a_i]>>32].bb.a[(uint32_t)(a[a_i])]);//longest one + m = gen_ul_pat_seq(ul->a[a[a_i]>>32].bb.a, &(b->dp), ul, (uint32_t)(a[a_i]), g, v, is_backward, &url); + assert(b->dp.pat.n > 0); + + // if(is_debug) { + // for (i = 0; i < (int64_t)b->dp.pat.n; i++) { + // fprintf(stderr, "pat[M::%s::] utg%.6dl(%c), d::%lu\n", __func__, + // (((uint32_t)b->dp.pat.a[i])>>1)+1, "+-"[((uint32_t)b->dp.pat.a[i])&1], b->dp.pat.a[i]>>32); + // } + // } + if(b->dp.pat.n == 1) return 0; + gen_ref_pat_seq(g, b, url, UL_TRAV_HERATE, v, w/**, is_debug**/); + + // if(is_debug) { + // for (i = 0; i < (int64_t)b->dp.ref.n; i++) { + // fprintf(stderr, "ref[M::%s::] utg%.6dl(%c), d::%lu\n", __func__, + // (((uint32_t)b->dp.ref.a[i])>>1)+1, "+-"[((uint32_t)b->dp.ref.a[i])&1], b->dp.ref.a[i]>>32); + // } + // } + + if(!quick_check(ul->a[a[a_i]>>32].bb.a, g, &(b->dp), UL_TRAV_HERATE, UL_TRAV_FT_RATE)) return 0; + we = ul_dp0(bub, g, &(b->dp), 0.9/**, is_debug**/); + if(we < 0) return 0; + return we; +} + +uint64_t get_eul_weight(bubble_type* bub, uint32_t v, uint32_t w, uinfo_t *g_idx, ubuf_t *b, all_ul_t *ul, asg_t *g) +{ + uint64_t *a, to = 0; int64_t a_n, l, k; + a = ul->ridx.occ.a + ul->ridx.idx.a[v>>1]; + a_n = ul->ridx.idx.a[(v>>1)+1] - ul->ridx.idx.a[v>>1]; + b->dp.pat.n = b->dp.pat_cor.n = b->dp.ref.n = 0; + for (l = 0, k = 1; k <= a_n; k++) { + if((k == a_n) || ((a[k]>>32) != (a[l]>>32))) { + // if((v == 106 && w == 103) || (v == 24 && w == 23)) { + // fprintf(stderr, "+[M::%s::] l->%ld, k->%ld, a_n->%ld\n", __func__, l, k, a_n); + // } + to += ul_dp(bub, ul, b, a + l, k - l, g, v, w, 1); + // if((v == 106 && w == 103) || (v == 24 && w == 23)) { + // fprintf(stderr, "-[M::%s::] l->%ld, k->%ld, a_n->%ld\n", __func__, l, k, a_n); + // } + to += ul_dp(bub, ul, b, a + l, k - l, g, v, w, 0); + // if((v == 106 && w == 103) || (v == 24 && w == 23)) { + // fprintf(stderr, "*[M::%s::] l->%ld, k->%ld, a_n->%ld\n", __func__, l, k, a_n); + // } + l = k; + } + } + + return to; +} + +void extract_paths(ubuf_t *b, ma_utg_v *gu, ul_path_t *res, uint32_t src, uint32_t dest) +{ + uint32_t i, v; uinfo_t *t; uint64_t m = 0, mi = (uint64_t)-1, avn; ///kv_resize(uinfo_srt_t, b->srt, b->b.n); b->srt.n = b->b.n; + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + t = &b->a.a[b->b.a[i]]; ///memset(t, 0, sizeof(*(t))); + //b->srt.a[i].c = ((uint64_t)-1) - t->c; b->srt.a[i].i = i; + if(m < t->c) { + m = t->c; mi = i; ///b->b.a[i]; + } + } + //radix_sort_uinfo_srt_t_c(b->srt.a, b->srt.a + b->srt.n); + // fprintf(stderr, "\n[M::%s::]->beg\n", __func__); + if(mi != (uint64_t)-1) { + ma_utg_t *p; kv_pushp(ma_utg_t, res->buf_ug->u, &p); + p->len = p->circ = p->n = 0; p->start = p->end = UINT32_MAX; p->a = NULL; p->s = NULL; + for(v = b->b.a[mi], avn = 0; v != (uint32_t)-1; v = b->a.a[v].p) { + if(b->a.a[v].c == 0 && avn == 0) break; + b->us.a[v>>1] = 1; + if(v != src && v != dest) kv_push(uint64_t, (*p), v); + // fprintf(stderr, "[M::%s::] utg%.6d%c(%c)\tC::%lu\n", __func__, (v>>1)+1, "lc"[gu->a[v>>1].circ], "+-"[v&1], b->a.a[v].c); + avn = b->a.a[v].c; + } + + if(p->n == 0) res->buf_ug->u.n = 0; + } +} + +uint32_t hc_simple_traversal(bubble_type* bub, asg_t *g, ma_utg_v *gu, ubuf_t *b, all_ul_t *ul, uint32_t src, uint32_t dest, ul_path_t *res) +{ + uint32_t v, nv, i, w, n_pending = 0, is_update = 0; uint64_t l, d, c, cc, nc, c_nc; asg_arc_t *av; uinfo_t *t; + if (g->seq[src>>1].del || g->seq[dest>>1].del) return 0; + clear_ubuf_t(b, g, ul, 1); b->a.a[src].p = (uint32_t)-1; + kv_push(uint32_t, b->S, src); + while (b->S.n > 0) { + v = kv_pop(b->S); d = b->a.a[v].d; c = b->a.a[v].c; nc = b->a.a[v].nc; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (i = 0; i < nv; ++i) { + if (av[i].del || g->seq[av[i].v>>1].del) continue; + w = av[i].v; l = (uint32_t)av[i].ul; t = &b->a.a[w]; + kv_push(uint32_t, b->e, ((g->idx[v]>>32)+i)); ///push the edge + // fprintf(stderr, "+[M::%s::] utg%.6d%c(%c:%u) -> utg%.6d%c(%c:%u)\n", __func__, + // (v>>1)+1, "lc"[gu->a[v>>1].circ], "+-"[v&1], v, + // (w>>1)+1, "lc"[gu->a[w>>1].circ], "+-"[w&1], w); + cc = c + get_eul_weight(bub, w^1, v^1, b->a.a, b, ul, g); + c_nc = nc + (gu?gu->a[w>>1].n:1); + // fprintf(stderr, "-[M::%s::] utg%.6d%c(%c:%u) -> utg%.6d%c(%c:%u)\n", __func__, + // (v>>1)+1, "lc"[gu->a[v>>1].circ], "+-"[v&1], v, + // (w>>1)+1, "lc"[gu->a[w>>1].circ], "+-"[w&1], w); + + if (t->s == 0) {///a new node + kv_push(uint32_t, b->b, w); // save it for revert + t->p = v; t->s = 1; t->d = d + l; + t->r = get_arcs(g, w^1, NULL, 0); + t->nc = c_nc; t->c = cc; + ++n_pending; + } else { + is_update = 0; + if(b->us.a[t->p>>1] == b->us.a[v>>1]) { + if(cc > t->c) is_update = 1; + if(cc == t->c && c_nc > t->nc) is_update = 1; + } else { + if(b->us.a[t->p>>1]) is_update = 1; + else is_update = 0; + } + + if(is_update) { + t->p = v; t->s = 1; t->d = d + l; t->nc = c_nc; t->c = cc; + } + } + + if (--(t->r) == 0) { + if(get_arcs(g, w, NULL, 0) > 0) kv_push(uint32_t, b->S, w); + --n_pending; + if(w == dest && n_pending == 0) goto pp_end; + } + } + } + pp_end: + extract_paths(b, gu, res, src, dest); + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + t = &b->a.a[b->b.a[i]]; memset(t, 0, sizeof(*(t))); + } + return 1; +} + + +// void clean_path_g(ul_path_t *p, asg_t *ref) +// { +// if(!(p->pg)) CALLOC(p->pg, 1); +// free(p->pg->idx); p->pg->idx = 0; p->pg->is_srt = 0; p->pg->is_symm = 0; +// REALLOC(p->pg->seq, ref->n_seq); p->pg->n_seq = ref->n_seq; p->pg->n_arc = 0; +// memcpy(p->pg->seq, ref->seq, p->pg->n_seq*sizeof(*(p->pg->seq))); +// asg_cleanup(p->pg); +// } + +void build_sub_graph(ul_resolve_t *uidx, ul_path_t *res) +{ + +} + +uint64_t get_chain_ul_cov(ul_resolve_t *uidx, uint64_t *a, uint64_t a_n, uint64_t bub_id, uint64_t inner_beg) +{ + if(a_n <= 0) return 0; + uint64_t w = 0, bid, rev; uint32_t rt, beg, sink; + uidx->path.buf.n = 0; + // kv_pushp(ul_sub_path_t, uidx->path, &p); memset(p, 0, sizeof((*p))); + // p->bid = bub_id; p->beg = inner_beg; p->occ = a_n; + + bid = a[0]>>33; rev = (a[0]>>32)&1; + get_bubbles(uidx->bub, bid, rev==0?&rt:NULL, rev==1?&rt:NULL, NULL, NULL, NULL); beg = rt; + + bid = a[a_n-1]>>33; rev = (a[a_n-1]>>32)&1; + get_bubbles(uidx->bub, bid, rev==1?&rt:NULL, rev==0?&rt:NULL, NULL, NULL, NULL); sink = rt^1; + + + + + + + + + // fprintf(stderr, "\n[M::%s::] # bubbles->%lu\n", __func__, a_n); + // uint64_t k + // for (k = 0; k < a_n; k++) { + // bid = a[k]>>33; rev = (a[k]>>32)&1; + // get_bubbles(uidx->bub, bid, rev==0?&rt:NULL, rev==1?&rt:NULL, NULL, NULL, NULL); + // // w += get_bub_ul_cov(a[k]>>33, ug, idx); + // fprintf(stderr, "[M::%s::] utg%.6d%c(%c)\n", __func__, (rt>>1)+1, "lc"[uidx->l1_ug->u.a[rt>>1].circ], "+-"[rt&1]); + // } + // if (a_n > 0) { + // bid = a[k-1]>>33; rev = (a[k-1]>>32)&1; + // get_bubbles(uidx->bub, bid, rev==1?&rt:NULL, rev==0?&rt:NULL, NULL, NULL, NULL); rt ^= 1; + // fprintf(stderr, "[M::%s::] utg%.6d%c(%c)\n", __func__, (rt>>1)+1, "lc"[uidx->l1_ug->u.a[rt>>1].circ], "+-"[rt&1]); + // } + // clean_path_g(&(uidx->path), uidx->l1_ug->g); + ma_utg_t *p; + kv_resize(uint8_t, uidx->buf.us, uidx->l1_ug->g->n_seq); uidx->buf.us.n = uidx->l1_ug->g->n_seq; memset(uidx->buf.us.a, 0, uidx->buf.us.n*sizeof(*(uidx->buf.us.a))); + hc_simple_traversal(uidx->bub, uidx->l1_ug->g, &(uidx->l1_ug->u), &(uidx->buf), uidx->idx, beg, sink, &(uidx->path)); + hc_simple_traversal(uidx->bub, uidx->l1_ug->g, &(uidx->l1_ug->u), &(uidx->buf), uidx->idx, beg, sink, &(uidx->path)); + + kv_pushp(ma_utg_t, uidx->path.buf_ug->u, &p); p->len = p->circ = p->n = 0; + p->start = p->end = UINT32_MAX; p->a = NULL; p->s = NULL; kv_push(uint64_t, *p, beg); + + kv_pushp(ma_utg_t, uidx->path.buf_ug->u, &p); p->len = p->circ = p->n = 0; + p->start = p->end = UINT32_MAX; p->a = NULL; p->s = NULL; kv_push(uint64_t, *p, sink); + + return w; +} + +void phrase_exact_chains(ul_resolve_t *uidx, uint64_t *a, int64_t a_n, asg_t *bg, uint64_t bub_id, uint64_t inner_beg) +{ + int64_t k, l; + for (k = l = 0; k < a_n; k++) { + if(k+1 >= a_n) continue; + if((arc_first(bg, a[k]>>32)).el) continue; + get_chain_ul_cov(uidx, a+l, k+1-l, bub_id, inner_beg + l); + l = k + 1; + } + if(l < a_n) get_chain_ul_cov(uidx, a+l, a_n-l, bub_id, inner_beg + l); +} +void resolve_dip_bub_chains(ul_resolve_t *uidx) +{ + bubble_type *bub = uidx->bub; + uint32_t i; int32_t k, l, un; ma_utg_t *u; + for (i = 0; i < bub->b_ug->u.n; i++) { + u = &(bub->b_ug->u.a[i]); un = u->n; + if(un <= 1) continue;///single bubble + for (l = -1, k = 0; k <= un; k++) { + if((k == un) || ((u->a[k]>>33) >= bub->f_bub)) {///not a complete bubble + // if(k < un) { + // fprintf(stderr, "++++++[M::%s::] l->%d, k->%d, bid->%lu, f_bub->%lu\n", + // __func__, l, k, (u->a[k]>>33), bub->f_bub); + // } + if(k - l > 1) {///at least a complete bubble + // fprintf(stderr, "\n[M::%s::] l->%d, k->%d\n", __func__, l, k); + phrase_exact_chains(uidx, u->a+l+1, k-l-1, bub->b_g, i, l+1); + } + l = k; + } + } + + } +} + +/** +static void fill_ul_path_srt_t(void *data, long i, int tid) // callback for kt_for() +{ + all_ul_t *idx = ((ul_resolve_t *)data)->idx; + ul_path_srt_t *idx_srt = &(((ul_resolve_t *)data)->psrt); + uc_block_t *a = NULL; uc_block_t *p; int64_t k, a_n, b_n, occ; uint64_t *b = NULL; + + a = idx->a[i].bb.a; a_n = idx->a[i].bb.n; + if(idx_srt->ul_n == 0) { + for (k = occ = 0; k < a_n; k++) { + p = &(a[k]); + if(p->base || (!p->el) || (!p->pchain)) continue; + occ++; + } + if(occ == 1) occ = 0;///UL read is too short + idx_srt->idx.a[i] = occ; + } else { + b_n = idx_srt->idx.a[i]>>33; b = idx_srt->srt.a + (uint32_t)idx_srt->idx.a[i]; + if(b_n == 0) return;//UL covers 0 or 1 node; not useful + for (k = occ = 0; k < a_n; k++) { + p = &(a[k]); + if(p->base || (!p->el) || (!p->pchain)) continue; + b[occ] = p->hid; b[occ] <<= 1; b[occ] |= p->rev; b[occ] <<= 32; b[occ] += (uint64_t)k; + occ++; + } + assert(occ == b_n); + radix_sort_srt64(b, b + b_n); + for (k = 1; k < b_n; k++) { + if((b[k]>>32) == (b[k-1]>>32)) break; + } + + if(k < b_n) idx_srt->idx.a[i] |= (uint64_t)(0x100000000); + } +} + + +void init_ul_path_srt_t(ul_resolve_t *p, all_ul_t *idx, ul_path_srt_t *idx_srt) +{ + idx_srt->ul_n = 0; + idx_srt->idx.n = idx_srt->idx.m = idx->n; CALLOC(idx_srt->idx.a, idx_srt->idx.n); + + kt_for(asm_opt.thread_num, fill_ul_path_srt_t, p, idx->n); + uint64_t l, k; + for (k = l = 0; k < idx_srt->idx.n; k++) { + idx_srt->idx.a[k] <<= 33; idx_srt->idx.a[k] += l; l += (idx_srt->idx.a[k]>>33); + } + MALLOC(idx_srt->srt.a, l); idx_srt->srt.n = idx_srt->srt.m = l; + + idx_srt->ul_n = idx->n; + kt_for(asm_opt.thread_num, fill_ul_path_srt_t, p, idx->n); +} +**/ + +uint64_t ug_occ_w(uint64_t is, uint64_t ie, ma_utg_t *u) +{ + if(is == 0 && ie == u->len) return u->n; + uint64_t l, i, us, ue, occ; + for (i = l = occ = 0; i < u->n; i++) { + us = l; ue = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); + // if(is == 15390 && ie == 31730) { + // fprintf(stderr, "[M::%s::i->%lu] is->%lu, ie->%lu, us->%lu, ue->%lu, u->len->%u\n", + // __func__, i, is, ie, us, ue, u->len); + // } + if(is <= us && ie >= ue) occ++; + if(us >= ie) break; + l += (uint32_t)u->a[i]; + } + return occ; +} + +// static void gen_ul_str_idx_t(void *data, long i, int tid) // callback for kt_for() +// { +// all_ul_t *idx = ((ul_resolve_t *)data)->idx; +// ma_ug_t *ug = ((ul_resolve_t *)data)->l1_ug; +// ul_str_t *str = &(((ul_resolve_t *)data)->pstr.str.a[i]); +// // uint64_t *str_idx = ((ul_resolve_t *)data)->pstr.idx.a; +// uc_block_t *a = NULL; uc_block_t *xk; uint64_t t; +// uint64_t k, a_n; + +// str->n = str->m = 0; str->a = NULL; +// a = idx->a[i].bb.a; a_n = idx->a[i].bb.n; +// kv_resize(uint64_t, *str, idx->a[i].bb.n); +// for (k = 0; k < a_n; k++) { +// xk = &(a[k]); +// if(xk->base || (!xk->el) || (!xk->pchain)) continue; +// t = k; t <<= 32; t += (xk->hid<<1); t += xk->rev; +// kv_push(uint64_t, *str, t); +// } +// str->cn = str->n; str->is_cir = 0; +// } + +void init_ul_str_idx_t(ul_resolve_t *p) +{ + uint64_t k, l, i, m, *a, a_n, x_n; uc_block_t *x_a; + all_ul_t *idx = p->idx; ul_str_idx_t *str = &(p->pstr); ul_str_t *z; uint32_t v0, v1; + MALLOC(str->str.a, idx->n); str->str.n = str->str.m = idx->n; + CALLOC(str->idx.a, p->l1_ug->u.n+1); str->idx.n = str->idx.m = p->l1_ug->u.n+1; + for (i = 0; i < str->str.n; i++) { + x_a = idx->a[i].bb.a; x_n = idx->a[i].bb.n; + memset(&(str->str.a[i]), 0, sizeof(str->str.a[i])); + for (k = 0; k < x_n; k++) { + if(x_a[k].base || (!x_a[k].el) || (!x_a[k].pchain)) continue; + l = k; l <<= 32; l += (x_a[k].hid<<1); l += x_a[k].rev; str->idx.a[x_a[k].hid]++; + kv_push(uint64_t, str->str.a[i], l);///idx|hid|rev + } + str->str.a[i].cn = str->str.a[i].n; str->str.a[i].is_cir = 0; + } + + // kt_for(asm_opt.thread_num, gen_ul_str_idx_t, p, str->str.n); + for (k = l = 0; k < str->idx.n; k++) { + m = str->idx.a[k]; + str->idx.a[k] = l; + l += m; + } + + MALLOC(str->occ.a, l); str->occ.n = str->occ.m = l; + for (k = 0; k < p->l1_ug->u.n; k++) { + a = str->occ.a + str->idx.a[k]; + a_n = str->idx.a[k+1] - str->idx.a[k]; + if(a_n) a[a_n-1] = 0; + } + + for (k = 0; k < str->str.n; k++) { + z = &(str->str.a[k]); + for (i = 0; i < z->cn; i++) { + a = str->occ.a + str->idx.a[((uint32_t)z->a[i])>>1]; + a_n = str->idx.a[(((uint32_t)z->a[i])>>1)+1] - str->idx.a[((uint32_t)z->a[i])>>1]; + if(a_n) { + if(a[a_n-1] == a_n-1) { + m = a_n-1; a[a_n-1] = (k<<32)|i; + } else { + m = a[a_n-1]; a[a[a_n-1]++] = (k<<32)|i; + } + + v0 = (uint32_t)z->a[(uint32_t)a[m]]; + while (m > 0 && z->is_cir == 0) { + m--; + if((a[m]>>32) != k) break; + v1 = (uint32_t)z->a[(uint32_t)a[m]]; + if(v0 == v1) z->is_cir = 1; + } + } + } + } +} + +ul_resolve_t *init_ul_resolve_t(asg_t *sg, ma_ug_t *init_ug, bubble_type* bub, all_ul_t *idx, ug_opt_t *uopt, uint8_t *r_het) +{ + ul_resolve_t *p = NULL; CALLOC(p, 1); + p->sg = sg; p->init_ug = init_ug; p->bub = bub; p->idx = idx; p->r_het = r_het; p->uopt = uopt; + p->l1_ug = copy_untig_graph(p->init_ug); + init_integer_ml_t(&p->str_b, p, asm_opt.thread_num); + // init_ul_path_srt_t(p); + init_ul_str_idx_t(p); + return p; +} + +void print_bubble_gfa(FILE *fp, bubble_type *bub, const char* utg_pre, const char* bub_pre, const char* chain_pre) +{ + uint32_t i, k, m, *a, n, beg, sink, x; ma_utg_t *p; uint64_t occ; + ma_ug_t *b_ug = bub->b_ug; char name[32], bname[32]; uint8_t *f; CALLOC(f, bub->ug->u.n); + for (i = 0; i < b_ug->u.n; i++) { + p = &b_ug->u.a[i]; + if(p->n == 0) continue; + for (k = occ = 0; k < p->n; k++){ + x = p->a[k]>>33; + get_bubbles(bub, x, &beg, &sink, &a, &n, NULL); + + for (m = 0; m < n; m++) { + occ += bub->ug->u.a[a[m]>>1].n; f[a[m]>>1] = 1; + } + if(beg != (uint32_t)-1 && f[beg>>1] == 0) { + occ += bub->ug->u.a[beg>>1].n; f[beg>>1] = 1; + } + if(sink != (uint32_t)-1 && f[sink>>1] == 0) { + occ += bub->ug->u.a[sink>>1].n; f[sink>>1] = 1; + } + } + + sprintf(name, "%s%.6d%c", chain_pre, i + 1, "lc"[p->circ]); + fprintf(fp, "S\t%s\t*\tLN:i:%lu\n", name, occ); + for (k = 0; k < p->n; k++) { + x = p->a[k]>>33; + sprintf(bname, "%s%.6d", bub_pre, x + 1); + fprintf(fp, "B\t%s\t%c\tcid:i:%s\tsm:%c\n", bname, "+-"[(p->a[k]>>32)&1], name, "01"[xf_bub]); + + get_bubbles(bub, x, &beg, &sink, &a, &n, NULL); + if(beg != (uint32_t)-1) { + fprintf(fp, "U\t%s%.6d%c\t%c\tcid:i:%s\tbid:b:%s\thom:%c\n", + utg_pre, (beg>>1)+1, "lc"[bub->ug->u.a[(beg>>1)].circ], "+-"[beg&1], name, bname, "10"[IF_HOM((beg>>1), *bub)]); + } + + if(sink != (uint32_t)-1) { + fprintf(fp, "U\t%s%.6d%c\t%c\tcid:i:%s\tbid:s:%s\thom:%c\n", + utg_pre, (sink>>1)+1, "lc"[bub->ug->u.a[(sink>>1)].circ], "+-"[sink&1], name, bname, "10"[IF_HOM((sink>>1), *bub)]); + } + for (m = 0; m < n; m++) { + occ += bub->ug->u.a[a[m]>>1].n; + fprintf(fp, "U\t%s%.6d%c\t%c\tcid:i:%s\tbid:c:%s\thom:%c\n", + utg_pre, (a[m]>>1)+1, "lc"[bub->ug->u.a[(a[m]>>1)].circ], "+-"[a[m]&1], name, bname, "10"[IF_HOM((a[m]>>1), *bub)]); + } + } + } + + asg_arc_t* au = NULL; + uint32_t nu, u, v, j; + for (i = 0; i < b_ug->u.n; ++i) { + if(b_ug->u.a[i].m == 0) continue; + if(b_ug->u.a[i].circ) + { + fprintf(fp, "L\t%s%.6dc\t+\t%s%.6dc\t+\t%dM\tL1:i:%d\n", + chain_pre, i+1, chain_pre, i+1, 0, 0); + fprintf(fp, "L\t%s%.6dc\t-\t%s%.6dc\t-\t%dM\tL1:i:%d\n", + chain_pre, i+1, chain_pre, i+1, 0, 0); + } + u = i<<1; + au = asg_arc_a(b_ug->g, u); + nu = asg_arc_n(b_ug->g, u); + for (j = 0; j < nu; j++) + { + if(au[j].del) continue; + v = au[j].v; + fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", + chain_pre, (u>>1)+1, "lc"[b_ug->u.a[u>>1].circ], "+-"[u&1], + chain_pre, (v>>1)+1, "lc"[b_ug->u.a[v>>1].circ], "+-"[v&1], 0, 0); + } + + + u = (i<<1) + 1; + au = asg_arc_a(b_ug->g, u); + nu = asg_arc_n(b_ug->g, u); + for (j = 0; j < nu; j++) + { + if(au[j].del) continue; + v = au[j].v; + fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", + chain_pre, (u>>1)+1, "lc"[b_ug->u.a[u>>1].circ], "+-"[u&1], + chain_pre, (v>>1)+1, "lc"[b_ug->u.a[v>>1].circ], "+-"[v&1], 0, 0); + } + } + + for (i = 0; i < bub->ug->u.n; i++) { + if(f[i]) continue; + fprintf(fp, "U\t%s%.6d%c\t+\tcid:i:*\tbid:c:*\thom:%c\n", + utg_pre, i+1, "lc"[bub->ug->u.a[i].circ], "10"[IF_HOM(i, *bub)]); + } + free(f); +} + +void print_uls_ovlp(FILE *fp, all_ul_t *uls, const char* utg_pre, ma_ug_t *ug) +{ + ul_vec_t *p = NULL; nid_t *z = NULL; uc_block_t *m = NULL; uint64_t k, i; uint32_t a, la, occ; + kvec_t(uint8_t) f; kv_init(f); + for (k = 0; k < uls->n; k++) { + z = &(uls->nid.a[k]); + p = &(uls->a[k]); + for (i = 0; i < p->bb.n; i++) { + m = &(p->bb.a[i]); + if(m->base || (!m->el)) continue; + if(m->pchain) break; + } + if(i >= p->bb.n) continue; + kv_resize(uint8_t, f, p->bb.n); memset(f.a, 0, sizeof(*(f.a))*p->bb.n); + fprintf(fp, ">\t%.*s\n", (int32_t)z->n, z->a); + for (i = 0; i < p->bb.n; i++) { + if(f.a[i]) continue; + m = &(p->bb.a[i]); + if(m->base || (!m->el) || (!m->pchain)) continue; + for (a = i, la = i, occ = 0; a != (uint32_t)-1; a = p->bb.a[a].aidx) { + la = a; f.a[a] = 1; occ++; + } + fprintf(fp, "C\tLEN:%u\tS:%u\tE:%u\tOCC:%u\n", p->rlen, p->bb.a[i].qs, p->bb.a[la].qe, occ); + for (a = i; a != (uint32_t)-1; a = p->bb.a[a].aidx) { + m = &(p->bb.a[a]); + fprintf(fp, "%s%.6d%c[%c::", utg_pre, m->hid+1, "lc"[ug->u.a[(m->hid>>1)].circ], "+-"[m->rev]); + if(m->pdis == (uint32_t)-1) fprintf(fp, "*]\t"); + else fprintf(fp, "%u]\t", m->pdis); + } + fprintf(fp, "\n"); + } + } + + free(f.a); +} + +void print_debug_ul(const char* o_n, ma_ug_t *ug, asg_t *rg, const ma_sub_t *cov, ma_hit_t_alloc* src, R_to_U* ridx, +bubble_type *bub, all_ul_t *uls) +{ + char* gfa_name = (char*)malloc(strlen(o_n)+50); FILE *fn; + + if(ug && rg && cov && src && ridx) { + uint32_t k, m, v, w, an; asg_arc_t *p, *av; + for (k = 0; k < ug->g->n_arc; k++) { + p = &(ug->g->arc[k]); v = p->v^1; w = (p->ul>>32)^1; + av = asg_arc_a(ug->g, v); an = asg_arc_n(ug->g, v); + for (m = 0; m < an; m++) { + if(av[m].del == 0 && av[m].v == w) break; + } + assert(m < an && av[m].ou == p->ou); + } + sprintf(gfa_name, "%s.r_utg.noseq.gfa", o_n); fn = fopen(gfa_name, "w"); + ma_ug_print_simple(ug, rg, cov, src, ridx, "utg", fn); + fclose(fn); + } + + if(bub) { + sprintf(gfa_name, "%s.bub.noseq.gfa", o_n); fn = fopen(gfa_name, "w"); + print_bubble_gfa(fn, bub, "utg", "btg", "ctg"); + fclose(fn); + } + + if(uls && ug) { + sprintf(gfa_name, "%s.uls.ovlp", o_n); fn = fopen(gfa_name, "w"); + print_uls_ovlp(fn, uls, "utg", ug); + fclose(fn); + } + + free(gfa_name); + fprintf(stderr, "[M::%s::] done\n", __func__); + exit(1); +} + +int64_t normlize_gdis(ma_ug_t *ug, uc_block_t *i, uc_block_t *k, int64_t is_i2k_forward) +{ + int64_t i_len, k_len; + ///i > k + // if(is_i2k_forward == 0){ + // if(!i->rev) { + // i_len = i->qe + (ug->g->seq[i->hid].len - i->te); + // } else { + // i_len = i->qe + i->ts; + // } + + // if(!k->rev) { + // k_len = k->qe + (ug->g->seq[k->hid].len - k->te); + // } else { + // k_len = k->qe + k->ts; + // } + // } else { + // if(!i->rev) { + // i_len = (int64_t)i->qs - (int64_t)i->ts; + // } else { + // i_len = (int64_t)i->qs - (int64_t)(ug->g->seq[i->hid].len - i->te); + // } + // if(i_len < 0) i_len = 0; + + // if(!k->rev) { + // k_len = (int64_t)k->qs - (int64_t)k->ts; + // } else { + // k_len = (int64_t)k->qs - (int64_t)(ug->g->seq[k->hid].len - k->te); + // } + // if(k_len < 0) k_len = 0; + // } + + if(!i->rev) { + i_len = i->qe + (ug->g->seq[i->hid].len - i->te); + } else { + i_len = i->qe + i->ts; + } + + + if(!k->rev) { + k_len = k->qe + (ug->g->seq[k->hid].len - k->te); + } else { + k_len = k->qe + k->ts; + } + + if(is_i2k_forward) { + i_len -= ug->g->seq[i->hid].len; + k_len -= ug->g->seq[k->hid].len; + } + + + if(i_len >= k_len) return i_len - k_len; + // assert(i_len >= k_len); + return 0; +} + +int64_t normlize_gdis_exact(ma_ug_t *ug, uc_block_t *a, uint32_t i, uint32_t k, int64_t is_i2k_forward) +{ + assert(i > k); + uint32_t li, lk, pk, bi = i; int64_t l; + for (li = i, l = 0; i != (uint32_t)-1 && i >= k; i = a[i].pidx) { + li = i; + if(a[i].pidx != (uint32_t)-1 && i > k) l += a[i].pdis; + } + + if(is_i2k_forward) { + l += (int64_t)(ug->g->seq[a[li].hid].len); + l -= (int64_t)(ug->g->seq[a[bi].hid].len); + } + i = li; + if(i == k) return l; + assert(i > k); pk = k; + for (lk = k; k != (uint32_t)-1 && k <= i; k = a[k].aidx) lk = k; + for (k = lk; k != (uint32_t)-1 && k != pk; k = a[k].pidx) l += a[k].pdis; + // assert(k == pk); + if(is_i2k_forward) { + l += (int64_t)(ug->g->seq[a[pk].hid].len); + l -= (int64_t)(ug->g->seq[a[lk].hid].len); + } + if(l < 0) l = 0; + k = lk; + assert(i > k); + return l + normlize_gdis(ug, &(a[i]), &(a[k]), is_i2k_forward); +} + +uint32_t dis_check_integer_aln_t(all_ul_t *ul_idx, ul_str_idx_t *str_idx, ma_ug_t *ug, integer_aln_t *li, integer_aln_t *lk, +uint32_t qid, uint32_t tid, uint32_t is_rev, double diff_rate, int64_t hard_thres) +{ + assert(((uint32_t)li->tn_rev_qk) >= ((uint32_t)lk->tn_rev_qk)); + if(((uint32_t)li->tn_rev_qk) == ((uint32_t)lk->tn_rev_qk)) return 0; + if(li->tk <= lk->tk) return 0; + ul_str_t *q = &(str_idx->str.a[qid]), *t = &(str_idx->str.a[tid]); + uc_block_t *iq, *it, *kq, *kt; int64_t qlen, tlen, mm, dd, i_qk, k_qk, i_tk, k_tk; + i_qk = ((uint32_t)li->tn_rev_qk); k_qk = ((uint32_t)lk->tn_rev_qk); + if(!is_rev) { + i_tk = li->tk; k_tk = lk->tk; + } else { + i_tk = t->cn - lk->tk - 1; k_tk = t->cn - li->tk - 1; + } + iq = &(ul_idx->a[qid].bb.a[(q->a[i_qk]>>32)]); + it = &(ul_idx->a[tid].bb.a[(t->a[i_tk]>>32)]); + + kq = &(ul_idx->a[qid].bb.a[(q->a[k_qk]>>32)]); + kt = &(ul_idx->a[tid].bb.a[(t->a[k_tk]>>32)]); + qlen = normlize_gdis(ug, iq, kq, 0); tlen = normlize_gdis(ug, it, kt, is_rev); + if(qlen < tlen) { + mm = qlen; dd = tlen - qlen; + } else { + mm = tlen; dd = qlen - tlen; + } + + // if(tid == 3074) { + // fprintf(stderr, "\n+++[M::%s::] qlen::%ld, tlen::%ld, iq->hid::%u, kq->hid::%u, (q->a[i_qk]>>32)::%lu, (q->a[k_qk]>>32)::%lu, (t->a[i_tk]>>32)::%lu, (t->a[k_tk]>>32)::%lu\n", + // __func__, qlen, tlen, iq->hid, kq->hid, + // (q->a[i_qk]>>32), (q->a[k_qk]>>32), (t->a[i_tk]>>32), (t->a[k_tk]>>32)); + // } + + if(dd <= (mm*diff_rate) || dd < hard_thres) return 1; + + qlen = normlize_gdis_exact(ug, ul_idx->a[qid].bb.a, (q->a[i_qk]>>32), (q->a[k_qk]>>32), 0); + tlen = normlize_gdis_exact(ug, ul_idx->a[tid].bb.a, (t->a[i_tk]>>32), (t->a[k_tk]>>32), is_rev); + if(qlen < tlen) { + mm = qlen; dd = tlen - qlen; + } else { + mm = tlen; dd = qlen - tlen; + } + + if(dd <= (mm*diff_rate) || dd < hard_thres) return 1; + + // if(tid == 3074) { + // fprintf(stderr, "---[M::%s::] qlen::%ld, tlen::%ld, iq->hid::%u, kq->hid::%u\n", + // __func__, qlen, tlen, iq->hid, kq->hid); + // } + + + return 0; +} + +uint32_t integer_chain(uint32_t qid, integer_aln_t *a, int64_t a_n, int64_t offset, integer_t *buf, +ma_ug_t *ug, ul_str_idx_t *str_idx, all_ul_t *ul_idx, ul_chain_t *res) +{ + res->v = res->s = res->e = (uint32_t)-1; res->sc = (uint64_t)-1; + res->q_sidx = res->q_eidx = res->t_sidx = res->t_eidx = (uint32_t)-1; + if(a_n <= 0) return 0; + ///already sorted by qe + int64_t i, k, max_f, max_k, sc, csc, *p, *f, tf, ti/**, is_circle**/; + integer_aln_t *li, *lk; uint32_t tid = a[0].tn_rev_qk>>33; uint32_t is_rev = (a[0].tn_rev_qk>>32)&1; + for (i = 1, sc = 0; i < a_n; ++i) { + sc += a[i].sc; + if(a[i].tk <= a[i-1].tk) break;///== means there is a circle + if(((uint32_t)a[i].tn_rev_qk) <= ((uint32_t)a[i-1].tn_rev_qk)) break; + if(str_idx && ul_idx && (!dis_check_integer_aln_t(ul_idx, str_idx, + ug, &(a[i]), &(a[i-1]), qid, tid, is_rev, 0.08, 2000))) { + break; + } + } + // if(tid == 269 || tid == 276 || tid == 277 || tid == 278) fprintf(stderr, "tid->%u, i->%ld, an->%ld\n", tid, i, a_n); + if(i >= a_n) {//the whole chain is co-inear + sc += a[0].sc; + res->v = a[0].tn_rev_qk>>32; res->s = offset; res->e = offset + a_n; res->sc = sc; + return 1; + } + // is_circle = 1; + // if(str_idx->str.a[qid].is_cir == 0 && str_idx->str.a[tid].is_cir == 0) is_circle = 0; + + buf->p.n = buf->f.n = 0; + kv_resize(int64_t, buf->p, (uint64_t)a_n); p = buf->p.a; + kv_resize(int64_t, buf->f, (uint64_t)a_n); f = buf->f.a; + + tf = ti = -1; + for (i = 0; i < a_n; ++i) { + li = &(a[i]); csc = a[i].sc; + max_f = csc; max_k = -1; + for (k = i-1; k >= 0; --k) { + lk = &(a[k]); + ///qk of lk and li might be equal + if(lk->tk >= li->tk || ((uint32_t)lk->tn_rev_qk) >= ((uint32_t)li->tn_rev_qk)) continue; + // if(is_circle && (!dis_check_integer_aln_t(ul_idx, str_idx, ug, li, lk, qid, tid, is_rev, 0.08))) continue; + if(str_idx && ul_idx && (!dis_check_integer_aln_t(ul_idx, str_idx, + ug, li, lk, qid, tid, is_rev, 0.08, 2000))) { + continue; + } + sc = csc + f[k]; + if(sc > max_f) { + max_f = sc; max_k = k; + } + } + f[i] = max_f; p[i] = max_k; + if(tf < max_f) { + tf = max_f; ti = i; + } + } + + if(ti < 0) return 0; + + for (i = ti, k = 0; i >= 0; i = p[i]) f[k++] = i; + assert(k > 0); + for (i = sc = 0, k--; k >= 0; k--, i++) { + a[i] = a[f[k]]; sc += a[i].sc; + // if(tid == 269) { + // fprintf(stderr, "[%ld] qk->%u, tk->%u\n", i, (uint32_t)a[i].tn_rev_qk, a[i].tk); + // } + } + res->v = a[0].tn_rev_qk>>32; res->s = offset; res->e = offset + i; res->sc = sc; + return 1; +} + +/** +void calculate_boundary_integer_length(all_ul_t *ul_idx, ul_str_t *str, int64_t qid, int64_t tid, int64_t qk, int64_t tk, +int64_t is_rev, int64_t is_prefix, int64_t is_suffix, int64_t *r_qoff, int64_t *r_toff) +{ + (*r_qoff) = (*r_toff) = -1; + int64_t qlen = ul_idx->a[qid].rlen, tlen = ul_idx->a[tid].rlen, qoff, toff, q_ext, t_ext; + ul_str_t *qstr = &(str[qid]), *tstr = &(str[tid]); + if(is_rev) tk = tstr->cn - tk; + uc_block_t *q_b = &(ul_idx->a[qid].bb.a[qstr->a[qk]>>32]); + uc_block_t *t_b = &(ul_idx->a[tid].bb.a[tstr->a[tk]>>32]); + if(is_prefix) { + qoff = q_b->qs; toff = (is_rev?(tlen-t_b->qe):(t_b->qs)); + } + if(is_suffix) { + qoff = qlen - q_b->qe; toff = (is_rev?(t_b->qs):(tlen-t_b->qe)); + } + + if(qoff <= toff) { + t_ext = qoff; q_ext = -1; + } else { + q_ext = toff; t_ext = -1; + } + + if(q_ext == -1) { + if(is_prefix) (*r_qoff) = 0; + if(is_suffix) (*r_qoff) = (int64_t)(qstr->cn); + } + +} + +void push_ul_snp_t(int64_t chain_id, ul_str_t *str, integer_t *buf, integer_aln_t *a, int64_t a_n, int64_t qid, int64_t tid, int64_t is_rev) +{ + if(a_n <= 0) return; + int64_t k, qk, tk, p_qk, p_tk; ul_snp_t *p; + ul_str_t *qstr = &(str[qid]), *tstr = &(str[tid]); + for (k = 0, p_qk = 0, p_tk = 0; k < a_n; k++) { + qk = (uint32_t)a[k].tn_rev_qk; tk = a[k].tk; + if(qk - p_qk > 0 || tk - p_tk > 0) { + if(p_qk == 0 && p_tk == 0) {///first window + ///qk == 0 || tk == 0 means we already reach the end + if(qk > 0 && tk > 0) { + ; + } + } else { + kv_pushp(ul_snp_t, buf->snp, &p); + p->chain_id = chain_id; p->is_rev = is_rev; + p->qidx_occ = p_qk; p->qidx_occ += (qk - p_qk); + p->tidx_occ = p_tk; p->tidx_occ += (tk - p_tk); + } + } + p_qk = qk + 1; p_tk = tk + 1; + } + + qk = qstr->cn; tk = tstr->cn; + if(qk - p_qk > 0 || tk - p_tk > 0) { + kv_pushp(ul_snp_t, buf->snp, &p); + p->chain_id = chain_id; p->is_rev = is_rev; + p->qidx_occ = p_qk; p->qidx_occ += (qk - p_qk); + p->tidx_occ = p_tk; p->tidx_occ += (tk - p_tk); + } +} + +void integer_variant_call(integer_t *buf, ul_snp_t *a, int64_t a_n) +{ + kv_resize(int64_t, buf->f, (uint64_t)a_n); + int64_t *f = buf->f.a; int64_t k, m; ul_snp_t *p; + memset(f, -1, sizeof((*f))*a_n); + for (k = 0; k < a_n; k++) { + if(f[k] != (uint64_t)-1) continue; + for (m = k+1, p = &(a[k]); m < a_n; m++) { + + } + } + + +} + +void integer_phase(ul_str_t *str, integer_t *buf, ul_chain_t *idx, int64_t idx_n, integer_aln_t *aln, int64_t qid) +{ + int64_t k; integer_aln_t *a; buf->snp.n = 0; + for (k = 0; k < idx_n; k++) { + push_ul_snp_t(k, str, buf, aln + idx[k].s, idx[k].e - idx[k].s, qid, idx[k].v>>1, idx[k].v&1); + } + + int64_t z, snp_n = buf->snp.n; + radix_sort_ul_snp_t_srt(buf->snp.a, buf->snp.a + buf->snp.n); + for (z = 0, k = 1; k <= snp_n; k++) { + if(k == snp_n || buf->snp.a[z].qidx_occ != buf->snp.a[k].qidx_occ) { + integer_variant_call(buf, buf->snp.a + z, k - z); + z = k; + } + } +} +**/ + +int64_t append_connective(integer_aln_t *aln, ul_chain_t *idx, int64_t str_i, uint64_t occ_thres, uint64_t *res) +{ + int64_t k, kl = idx->e - idx->s, str_k = -1, fp = 0; integer_aln_t *a = aln + idx->s; + assert(idx->sc <= (uint64_t)kl); + for (k = idx->sc; k < kl; k++) { + str_k = (uint32_t)a[k].tn_rev_qk; + if(str_k >= str_i) break; + } + idx->sc = k; + if(k >= kl || str_k != str_i) return 0; + + for (k -= 1; k >= 0; k--) { + str_k = (uint32_t)a[k].tn_rev_qk; + if(res[str_k] < occ_thres) { + res[str_k]++; + if(res[str_k] == occ_thres) fp++; + } + } + return fp; +} + +int64_t connective_conform(integer_aln_t *aln, ul_chain_t *idx_a, int64_t idx_n, int64_t str_i0, int64_t occ_thres, uint64_t is_cov_check) +{ + if(str_i0 == 0) return 1; + int64_t z; ul_chain_t *x; int64_t k, kl, str_k, match, exact; integer_aln_t *a; + for (z = match = exact = 0; z < idx_n; z++) { + x = &(idx_a[z]); + kl = x->e - x->s; str_k = -1; a = aln + x->s; + assert(x->sc <= (uint64_t)kl); + for (k = x->sc; k < kl; k++) { + str_k = (uint32_t)a[k].tn_rev_qk; + if(str_k >= str_i0) break; + } + x->sc = k; + if(k >= kl || str_k != str_i0) continue; + k--; + if(k >= 0) { + str_k = (uint32_t)a[k].tn_rev_qk; + if(str_k+1 == str_i0) { + match++; + if(a[k].tk+1 == a[k+1].tk) exact++; + } + } + } + + if(is_cov_check) { + if(match < occ_thres) return 0; + } else { + assert(match >= occ_thres); + } + + if(exact == match) return 1; + if(exact > (match*0.51) && exact > (match/2)) return 1; + return 0; +} + +///occ_thres does not consider reference read itself; so the real coverage is (occ_thres+1) +int64_t integer_chain_dp(bubble_type *bub, integer_t *buf, ul_str_t *str, integer_aln_t *aln, ul_chain_t *idx, int64_t idx_n, int64_t qid, uint32_t is_hom, +uint64_t occ_thres, uint64_t *corrected) +{ + ul_str_t *qstr = &(str[qid]); int64_t k, q_n = qstr->cn, *f, *p, z, max_f, tf, tk, max_p, done_z, sc, csc, n_skip; + kv_resize(int64_t, buf->f, qstr->cn); kv_resize(int64_t, buf->p, qstr->cn); + kv_resize(uint64_t, buf->o, qstr->cn); uint64_t *o; + f = buf->f.a; p = buf->p.a; o = buf->o.a; if(corrected) (*corrected) = 0; + + // radix_sort_ul_chain_t_srt(idx, idx + idx_n); + for (k = 0; k < idx_n; k++) idx[k].sc = 0; + + for (k = 0, tf = tk = -1, n_skip = 0; k < q_n; k++) { + csc = buf->u.a[k]; + if((!is_hom) && (IF_HOM((((uint32_t)qstr->a[k])>>1), (*bub)))) { + csc = -1; n_skip++; + } + max_p = -1; max_f = csc; + if(k > 0 && max_f >= 0) { + done_z = 0; + if(is_hom) {//check all nodes + memset(o, 0, sizeof((*o))*k); + } else {///mask hom nodes + for (z = 0; z < k; z++) { + o[z] = 0; + if(f[z] == -1) { + o[z] = occ_thres; ///if node is hom, ignore it + done_z++; + } + } + } + + for (z = 0; z < idx_n && done_z < k; z++) { + done_z += append_connective(aln, &(idx[z]), k, occ_thres, o); + } + assert(done_z <= k); + for (z = k - 1; z >= 0; z--) { + if(o[z] < occ_thres) continue; + if(f[z] == -1) continue;///masked hom nodes + sc = csc + f[z]; + if(sc > max_f) { + max_f = sc; max_p = z; + } + } + } + f[k] = max_f; p[k] = max_p; + if(tf < max_f && max_f >= 0) { + tf = max_f; tk = k; + } + + // fprintf(stderr, "[M::%s::k->%ld] f[k]->%ld, p[k]->%ld, csc->%ld\n", __func__, k, f[k], p[k], csc); + } + if(tk < 0) return 0; + for (k = tk, done_z = 0; k >= 0; k = p[k]) done_z++; + ///might be fully corrected; but some of hom nodes have been skipped + if((corrected) && ((n_skip+done_z) == q_n) ) { + for (k = 0; k < idx_n; k++) idx[k].sc = 0; + for (k = 1, (*corrected) = 0; k < q_n; k++) { + if(!connective_conform(aln, idx, idx_n, k, occ_thres, (f[k] >= 0 && f[k-1] >= 0)?0:1)) break; + } + if(k >= q_n) (*corrected) = 1; + } + + for (k = tk, sc = done_z; k >= 0; k = p[k]) o[--done_z] = k; + return sc; +} + +void print_integer_seq(ma_ug_t *ug, ul_str_t *str, int64_t id, int64_t is_header) +{ + uint64_t i; + if(is_header) { + fprintf(stderr,"[M::%s::tid->%ld] occ::%u\n", __func__, id, str[id].cn); + } + for (i = 0; i < str[id].cn; i++) { + fprintf(stderr, "utg%.6d%c(%c)\t", (((uint32_t)str[id].a[i])>>1)+1, + "lc"[ug->u.a[(((uint32_t)str[id].a[i])>>1)].circ], "+-"[(((uint32_t)str[id].a[i])&1)]); + } + fprintf(stderr,"\n"); +} + + +#define poa_arc_n(g, v) ((uint32_t)(g)->idx.a[(v)]) +#define poa_arc_a(g, v) (&(g)->arc.a[(g)->idx.a[(v)]>>32]) + +void print_integer_g(poa_g_t *g, ma_ug_t *ug, uint64_t is_gfa) +{ + uint64_t i, v, w; + if(!is_gfa) { + for (i = 0; i < g->seq.n; i++) { + fprintf(stderr, "Node::[M::%s::i->%lu] utg%.6d%c(%c)\n", __func__, i, (int32_t)(g->seq.a[i].nid>>1)+1, + "lc"[ug->u.a[g->seq.a[i].nid>>1].circ], "+-"[g->seq.a[i].nid&1]); + } + for (i = 0; i < g->arc.n; i++) { + v = g->arc.a[i].ul>>32; w = g->arc.a[i].v; + if(v&1) continue; + v = g->seq.a[v>>1].nid; w = g->seq.a[w>>1].nid; + fprintf(stderr, "Arch::[M::%s::w->%u] utg%.6d%c(%c) -> utg%.6d%c(%c)\n", __func__, (uint32_t)g->arc.a[i].ul, + (int32_t)(v>>1)+1, "lc"[ug->u.a[v>>1].circ], "+-"[v&1], g->arc.a[i].ul>>33, + (int32_t)(w>>1)+1, "lc"[ug->u.a[w>>1].circ], "+-"[w&1], g->arc.a[i].v>>1); + } + for (i = 0; i < g->seq.n; i++) { + fprintf(stderr, "Srt::[M::%s::i->%lu] utg%.6d%c(%c)\n", __func__, i, + (int32_t)(g->seq.a[g->srt_b.res.a[i]].nid>>1)+1, + "lc"[ug->u.a[g->seq.a[g->srt_b.res.a[i]].nid>>1].circ], "+-"[g->seq.a[g->srt_b.res.a[i]].nid&1], g->srt_b.res.a[i]); + } + } else { + char name[32]; + for (i = 0; i < g->seq.n; i++) { + sprintf(name, "dtg%.6d", (int)i); + fprintf(stderr, "S\t%s\t*\tLN:i:%u\trd:i:utg%.6d%c(%c)\n", name, g->srt_b.res2nid.a[i], + (int32_t)(g->seq.a[i].nid>>1)+1, "lc"[ug->u.a[g->seq.a[i].nid>>1].circ], "+-"[g->seq.a[i].nid&1]); + } + uint32_t u, nu, j; poa_arc_t *au; + for (i = 0; i < g->seq.n; ++i) { + u = i<<1; + au = poa_arc_a(g, u); nu = poa_arc_n(g, u); + for (j = 0; j < nu; j++) { + v = au[j].v; + fprintf(stderr, "L\tdtg%.6d\t%c\tdtg%.6d\t%c\t%dM\n", + (int)(u>>1), "+-"[u&1], (int)(v>>1), "+-"[v&1], asg_arc_len(au[j])); + } + + u = (i<<1) + 1; + au = poa_arc_a(g, u); nu = poa_arc_n(g, u); + for (j = 0; j < nu; j++) { + v = au[j].v; + fprintf(stderr, "L\tdtg%.6d\t%c\tdtg%.6d\t%c\t%dM\n", + (int)(u>>1), "+-"[u&1], (int)(v>>1), "+-"[v&1], asg_arc_len(au[j])); + } + } + } +} + +void print_cns_seq(ma_ug_t *ug, ul_str_t *str, uint64_t *cns_seq, uint64_t cns_occ) +{ + fprintf(stderr,"[M::%s::]\t", __func__); + uint64_t k, ck; + for (k = ck = 0; k < str->cn; k++) { + for (; ck < cns_occ; ck++) { + if(cns_seq[ck] >= k) break; + } + if(ck < cns_occ && cns_seq[ck] == k) { + fprintf(stderr, "utg%.6d%c(%c)\t", (((uint32_t)str->a[k])>>1)+1, + "lc"[ug->u.a[(((uint32_t)str->a[k])>>1)].circ], "+-"[(((uint32_t)str->a[k])&1)]); + } else { + fprintf(stderr, "*\t"); + } + } + fprintf(stderr,"\n"); +} + +void print_res_seq(poa_g_t *pg, ma_ug_t *ug, uint32_t *cns_seq, uint32_t cns_occ) +{ + fprintf(stderr,"[M::%s::]\t", __func__); + uint64_t k; + for (k = 0; k < cns_occ; k++) { + fprintf(stderr, "utg%.6d%c(%c)\t", (pg->seq.a[(cns_seq[k]>>1)].nid>>1)+1, + "lc"[ug->u.a[(pg->seq.a[(cns_seq[k]>>1)].nid>>1)].circ], + "+-"[(pg->seq.a[(cns_seq[k]>>1)].nid&1)]); + + } + fprintf(stderr,"\n"); +} + +int64_t utg_cover_read_occ_by_qs(ma_ug_t *ug, int64_t oqs, int64_t oqe, uc_block_t *x) +{ + assert(oqs >= (int64_t)x->qs && oqs <= (int64_t)x->qe); + assert(oqe >= (int64_t)x->qs && oqe <= (int64_t)x->qe); + assert(oqe > oqs); + int64_t s_off, e_off, k; + s_off = get_offset_adjust(oqs-x->qs, x->qe-x->qs, x->te-x->ts); + e_off = get_offset_adjust(x->qe-oqe, x->qe-x->qs, x->te-x->ts); + if(x->rev) { + k = s_off; s_off = e_off; e_off = k; + } + + return ug_occ_w(x->ts + s_off, x->te - e_off, &(ug->u.a[x->hid])); +} + +int64_t estimate_ul_len(ma_ug_t *ug, ul_vec_t *raw_ov, ul_str_t *str, int64_t idx, int64_t ext_len, uint64_t *cov_buf) +{ + if(ext_len == 0) return idx; + int64_t aim_s, aim_e, k = idx, qs, qe, ovlp_s, ovlp_e, cov_occ, str_n = str->cn; + if(ext_len < 0) { + aim_s = ((int64_t)(raw_ov->bb.a[str->a[idx]>>32].qs)) + ext_len; + if(aim_s < 0) aim_s = 0; + aim_e = raw_ov->bb.a[str->a[idx]>>32].qe; + for (k = idx - 1; k >= 0; k--) { + qs = raw_ov->bb.a[str->a[k]>>32].qs; qe = raw_ov->bb.a[str->a[k]>>32].qe; + // if(qe <= aim_s) break; + ovlp_s = MAX(aim_s, qs); ovlp_e = MIN(aim_e, qe); + if(ovlp_e <= ovlp_s) { + k++; + break; + } + cov_occ = utg_cover_read_occ_by_qs(ug, ovlp_s, ovlp_e, &(raw_ov->bb.a[str->a[k]>>32])); + if(cov_occ == 0) { + k++; + break; + } + cov_buf[k] = cov_occ; + } + if(k < 0) k++; + } else { + aim_s = raw_ov->bb.a[str->a[idx]>>32].qs; + aim_e = ((int64_t)(raw_ov->bb.a[str->a[idx]>>32].qe)) + ext_len; + if(aim_e > (int64_t)(raw_ov->rlen)) aim_e = raw_ov->rlen; + for (k = idx + 1; k < str_n; k++) { + qs = raw_ov->bb.a[str->a[k]>>32].qs; qe = raw_ov->bb.a[str->a[k]>>32].qe; + // if(qs >= aim_e) + ovlp_s = MAX(aim_s, qs); ovlp_e = MIN(aim_e, qe); + if(ovlp_e <= ovlp_s) { + k--; + break; + } + cov_occ = utg_cover_read_occ_by_qs(ug, ovlp_s, ovlp_e, &(raw_ov->bb.a[str->a[k]>>32])); + if(cov_occ == 0) { + k--; + break; + } + cov_buf[k] = cov_occ; + } + if(k >= str_n) k--; + } + return k; +} + +void print_integer_ovlps(ma_ug_t *ug, ul_str_t *str, integer_aln_t *aln, int64_t aln_occ, ul_chain_t *idx, int64_t idx_n, int64_t qid, int64_t consenus_occ) +{ + fprintf(stderr, "\n[M::%s::qid->%ld] qstr->cn::%u, aln_occ::%ld, idx_n::%ld, consenus_occ::%ld\n", + __func__, qid, str[qid].cn, aln_occ, idx_n, consenus_occ); + // print_integer_seq(ug, str, qid, 0); + int64_t k, z, z_n, qk, tk, is_rev, tid; //uint64_t z; + for (k = 0; k < idx_n; k++) { + fprintf(stderr, "\n[M::%s::tid->%lu] rev->%lu, aln_n->%u\n", __func__, aln[idx[k].s].tn_rev_qk>>33, (aln[idx[k].s].tn_rev_qk>>32)&1, idx[k].e - idx[k].s); + print_integer_seq(ug, str, aln[idx[k].s].tn_rev_qk>>33, 0); + z = idx[k].s; z_n = idx[k].e; tid = aln[idx[k].s].tn_rev_qk>>33; + for (; z < z_n; z++) { + qk = (uint32_t)aln[z].tn_rev_qk; is_rev = ((aln[z].tn_rev_qk>>32)&1); + tk = ((is_rev == 0)? (aln[z].tk):(str[tid].cn - aln[z].tk - 1)); + fprintf(stderr, "[qk::%ld]utg%.6d%c(%c) <---> [tk::%ld]utg%.6d%c(%c)\n", + qk, (((uint32_t)str[qid].a[qk])>>1)+1, "lc"[ug->u.a[(((uint32_t)str[qid].a[qk])>>1)].circ], "+-"[(((uint32_t)str[qid].a[qk])&1)], + tk, (((uint32_t)str[tid].a[tk])>>1)+1, "lc"[ug->u.a[(((uint32_t)str[tid].a[tk])>>1)].circ], "+-"[(((uint32_t)str[tid].a[tk])&1)]); + } + + // for (z = idx[k].s; z < idx[k].e; z++) { + // aln[z].tn_rev_qk + // } + } +} + +void integer_align_extention(ma_ug_t *ug, all_ul_t *ul_idx, int64_t qid, ul_str_t *q_str, int64_t tid, ul_str_t *t_str, int64_t is_rev, +uint64_t *q_cov_buf, uint64_t *t_cov_buf, integer_aln_t *aln_pair, int64_t is_backward, int64_t *r_q_end, int64_t *r_t_end) +{ + int64_t qk, tk, qoff, toff, qlen, tlen, ext, q_end, t_end; uc_block_t *q_b, *t_b; + qk = (uint32_t)(aln_pair->tn_rev_qk); tk = ((is_rev == 0)? (aln_pair->tk):(t_str->cn - aln_pair->tk - 1)); + q_b = &(ul_idx->a[qid].bb.a[q_str->a[qk]>>32]); t_b = &(ul_idx->a[tid].bb.a[t_str->a[tk]>>32]); + qlen = ul_idx->a[qid].rlen; tlen = ul_idx->a[tid].rlen; + + if(is_backward) { + qoff = q_b->qs; toff = (is_rev?(tlen-t_b->qe):(t_b->qs)); + } else { + qoff = qlen - q_b->qe; toff = (is_rev?(t_b->qs):(tlen-t_b->qe)); + } + + if (qoff <= toff) ext = qoff; + else ext = toff; + + if(is_backward) { + q_end = estimate_ul_len(ug, &(ul_idx->a[qid]), q_str, qk, -ext, q_cov_buf); + t_end = estimate_ul_len(ug, &(ul_idx->a[tid]), t_str, tk, ((is_rev)?(ext):(-ext)), t_cov_buf); + } else { + q_end = estimate_ul_len(ug, &(ul_idx->a[qid]), q_str, qk, ext, q_cov_buf); + t_end = estimate_ul_len(ug, &(ul_idx->a[tid]), t_str, tk, ((is_rev)?(-ext):(ext)), t_cov_buf); + } + + (*r_q_end) = q_end; (*r_t_end) = t_end; +} + +int64_t gap_chain_check(ma_ug_t *ug, integer_aln_t *i0, integer_aln_t *i1, int64_t is_rev, ul_str_t *q_str, ul_str_t *t_str, +uc_block_t *q_block, uc_block_t *t_block, int64_t qid, int64_t tid, double diff_rate, int64_t hard_thres) +{ + int64_t i0_qk, i0_tk, i1_qk, i1_tk, q_near, t_near, lq, lt, min, max, dif; uint32_t e, k; + i0_qk = (uint32_t)(i0->tn_rev_qk); i1_qk = (uint32_t)(i1->tn_rev_qk); + if(is_rev == 0) { + i0_tk = i0->tk; i1_tk = i1->tk; + } else { + i1_tk = t_str->cn - i0->tk - 1; i0_tk = t_str->cn - i1->tk - 1; + } + assert(i0_qk < i1_qk); assert(i0_tk < i1_tk); + q_near = t_near = 0; + if((i0_qk + 1) == i1_qk) q_near = 1; + if((i0_tk + 1) == i1_tk) t_near = 1; + if((q_near + t_near) != 1) return 0; + + i0_qk = q_str->a[i0_qk]>>32; i1_qk = q_str->a[i1_qk]>>32; + i0_tk = t_str->a[i0_tk]>>32; i1_tk = t_str->a[i1_tk]>>32; + + k = i1_qk; e = i0_qk; lq = 0; + while ((k != (uint32_t)-1) && (k != e)) { + if(q_block[k].pidx != (uint32_t)-1) lq += q_block[k].pdis; + k = q_block[k].pidx; + } + if(k != e) return 0; + + k = i1_tk; e = i0_tk; lt = 0; + while ((k != (uint32_t)-1) && (k != e)) { + if(t_block[k].pidx != (uint32_t)-1) lt += t_block[k].pdis; + k = t_block[k].pidx; + } + if(k != e) return 0; + if(is_rev) { + lt += (int64_t)ug->g->seq[t_block[i0_tk].hid].len; + lt -= (int64_t)ug->g->seq[t_block[i1_tk].hid].len; + } + if(lt < 0) lt = 0; + if(lq <= lt) { + min = lq; max = lt; + } else { + min = lt; max = lq; + } + + dif = max - min; + if(dif >= (min*diff_rate)) { + // fprintf(stderr, "+[M::%s] qid::%ld, tid::%ld, i0_qk::%ld, i1_qk::%ld, lq::%ld, lt::%ld\n", + // __func__, qid, tid, i0_qk, i1_qk, lq, lt); + lq = normlize_gdis(ug, &(q_block[i1_qk]), &(q_block[i0_qk]), 0); + lt = normlize_gdis(ug, &(t_block[i1_tk]), &(t_block[i0_tk]), is_rev); + // fprintf(stderr, "-[M::%s] qid::%ld, tid::%ld, i0_qk::%ld, i1_qk::%ld, lq::%ld, lt::%ld\n", + // __func__, qid, tid, i0_qk, i1_qk, lq, lt); + // fprintf(stderr, "[M::%s] q_block[i0_qk].qs::%u, q_block[i0_qk].qe::%u, q_block[i1_qk].qs::%u, q_block[i1_qk].qe::%u\n", + // __func__, q_block[i0_qk].qs, q_block[i0_qk].qe, q_block[i1_qk].qs, q_block[i1_qk].qe); + + // fprintf(stderr, "[M::%s] t_block[i0_tk].qs::%u, t_block[i0_tk].qe::%u, t_block[i1_tk].qs::%u, t_block[i1_tk].qe::%u\n", + // __func__, t_block[i0_tk].qs, t_block[i0_tk].qe, t_block[i1_tk].qs, t_block[i1_tk].qe); + if(lq <= lt) { + min = lq; max = lt; + } else { + min = lt; max = lq; + } + + dif = max - min; + if(dif >= (min*diff_rate) || dif < hard_thres) return 0; + } + return 1; +} + +int64_t refine_integer_ovlps(all_ul_t *ul_idx, bubble_type *bub, ma_ug_t *ug, ul_str_t *str, integer_aln_t *aln, ul_chain_t *idx, int64_t qid, integer_t *buf, +uint64_t *cns, uint64_t cns_occ) +{ + if(idx->e<=idx->s) return 0; + int64_t qk, tk, is_rev, tid, q_end, t_end, z; + ul_str_t *q_str, *t_str; uc_block_t *t_b; integer_aln_t *x, *y; + tid = aln[idx->s].tn_rev_qk>>33; is_rev = ((aln[idx->s].tn_rev_qk>>32)&1); + q_str = &(str[qid]); t_str = &(str[tid]); + kv_resize(uint64_t, buf->u, buf->u.n + q_str->cn + t_str->cn); + uint64_t *q_cov_buf = buf->u.a + buf->u.n, *t_cov_buf = buf->u.a + buf->u.n + q_str->cn, k, rg_occ, cn_k, mm; + memset(q_cov_buf, -1, sizeof((*q_cov_buf))*q_str->cn); memset(t_cov_buf, -1, sizeof((*t_cov_buf))*t_str->cn); + // if(tid != 392) return 0; + //beg + x = &(aln[idx->s]); + qk = (uint32_t)(x->tn_rev_qk); tk = ((is_rev == 0)? (x->tk):(t_str->cn - x->tk - 1)); + + ///direction + if((qk > 0) && (x->tk > 0)) { + integer_align_extention(ug, ul_idx, qid, q_str, tid, t_str, is_rev, q_cov_buf, t_cov_buf, x, 1, &q_end, &t_end); + idx->q_sidx = q_end; idx->t_sidx = ((is_rev == 0)? (t_end):(t_str->cn - t_end - 1)); + } else { + idx->q_sidx = (uint32_t)(x->tn_rev_qk); idx->t_sidx = x->tk; + } + // if(!((idx->q_sidx <= ((uint32_t)(x->tn_rev_qk))) && (idx->t_sidx <= x->tk))) { + // fprintf(stderr, "[M::%s] qid::%ld, tid::%ld\n", __func__, qid, tid); + // } + assert((idx->q_sidx <= ((uint32_t)(x->tn_rev_qk)))); assert(idx->t_sidx <= x->tk); + // assert((is_rev && idx->t_sidx >= x->tk) || (is_rev == 0 && idx->t_sidx <= x->tk)); + + //end + x = &(aln[idx->e-1]); + qk = (uint32_t)(x->tn_rev_qk); tk = ((is_rev == 0)? (x->tk):(t_str->cn - x->tk - 1)); + // if(tid == 316) { + // fprintf(stderr, "[end-M::%s::tid->%ld] qk::%ld, tk::%ld, x->tk::%u, t_str->cn::%u\n", + // __func__, tid, qk, tk, x->tk, t_str->cn); + // } + ///direction + if((((uint32_t)qk + 1) < q_str->cn) && ((x->tk + 1) < t_str->cn)) { + integer_align_extention(ug, ul_idx, qid, q_str, tid, t_str, is_rev, q_cov_buf, t_cov_buf, x, 0, &q_end, &t_end); + idx->q_eidx = q_end + 1; idx->t_eidx = ((is_rev == 0)? (t_end + 1):(t_str->cn - t_end)); + } else { + idx->q_eidx = (uint32_t)(x->tn_rev_qk)+1; idx->t_eidx = x->tk+1; + } + + assert(idx->q_eidx > ((uint32_t)(x->tn_rev_qk))); assert(idx->t_eidx > x->tk); + // assert((is_rev && idx->t_eidx < x->tk) || (is_rev == 0 && idx->t_eidx > x->tk)); + + assert(idx->q_eidx > idx->q_sidx); assert(idx->t_eidx > idx->t_sidx); + // assert((is_rev && idx->t_eidx < idx->t_sidx) || (is_rev == 0 && idx->t_eidx > idx->t_sidx)); + // if(tid == 284) { + // fprintf(stderr, "[M::%s::tid->%ld] idx->q_sidx::%u, idx->q_eidx::%u, idx->t_sidx::%u, idx->t_eidx::%u\n", + // __func__, tid, idx->q_sidx, idx->q_eidx, idx->t_sidx, idx->t_eidx); + // } + + ///mid + for (k = idx->s; k < idx->e; k++) {///go through all alignment pairs + // if(qid == 3113 && tid == 3075) { + // fprintf(stderr, "+[M::%s] qid::%ld, tid::%ld, idx->s::%u, idx->e::%u, k::%lu, qk::%u, tk::%u, (idx->v>>1)::%u\n", + // __func__, qid, tid, idx->s, idx->e, k, (uint32_t)(aln[k].tn_rev_qk), aln[k].tk, idx->v>>1); + // } + + x = &(aln[k]); y = ((k > idx->s)? (&(aln[k-1])):(NULL)); + qk = (uint32_t)(x->tn_rev_qk); + q_cov_buf[qk] = buf->u.a[qk]; + + tk = ((is_rev == 0)? (x->tk):(t_str->cn - x->tk - 1)); + t_b = &(ul_idx->a[tid].bb.a[t_str->a[tk]>>32]); + assert(((t_b->hid<<1)+t_b->rev)==((uint32_t)t_str->a[tk])); + t_cov_buf[tk] = ug_occ_w(t_b->ts, t_b->te, &(ug->u.a[t_b->hid])); + + q_cov_buf[qk] += ((uint64_t)(0x8000000000000000)); + t_cov_buf[tk] += ((uint64_t)(0x8000000000000000)); + + if(!y) continue; + mm = 0; + if(gap_chain_check(ug, y, x, is_rev, q_str, t_str, ul_idx->a[qid].bb.a, ul_idx->a[tid].bb.a, qid, tid, 0.08, 2000)) { + mm = ((uint64_t)(0x8000000000000000)); + } + for (z = ((uint32_t)(y->tn_rev_qk)) + 1; z < qk; z++) { + q_cov_buf[z] = buf->u.a[z] + mm; + } + + z = ((is_rev == 0)? (y->tk):(t_str->cn - x->tk - 1)) + 1; + tk = ((is_rev == 0)? (x->tk):(t_str->cn - y->tk - 1)); + assert(z <= tk); + for (; z < tk; z++) { + t_b = &(ul_idx->a[tid].bb.a[t_str->a[z]>>32]); + assert(((t_b->hid<<1)+t_b->rev)==((uint32_t)t_str->a[z])); + t_cov_buf[z] = ug_occ_w(t_b->ts, t_b->te, &(ug->u.a[t_b->hid])) + mm; + } + } + + if(cns) { + int64_t cns_cov_occ = 0, cns_het_occ = 0, match_cns_occ = 0, match_cns_het_occ = 0, hm; + rg_occ = idx->q_eidx; + for (k = idx->q_sidx, cn_k = 0; k < rg_occ; k++) { + assert((q_cov_buf[k]!=(uint64_t)-1) && (q_cov_buf[k] > 0)); + hm = ((q_cov_buf[k]<<1)>>1); + for (; cn_k < cns_occ; cn_k++) { + if(cns[cn_k] == k) { + cns_cov_occ += hm; + if(q_cov_buf[k]&((uint64_t)(0x8000000000000000))) match_cns_occ += hm; + if(!IF_HOM((((uint32_t)q_str->a[k])>>1), (*bub))) { + cns_het_occ += hm; + if(q_cov_buf[k]&((uint64_t)(0x8000000000000000))) match_cns_het_occ += hm; + } + } else if(cns[cn_k] > k) { + break; + } + } + } + + if(cns_cov_occ <= 0) return 0; + if((cns_het_occ > 0) && (match_cns_het_occ <= (cns_het_occ*0.5))) return 0; + if(match_cns_occ <= (cns_cov_occ*0.5)) return 0; + + k = idx->t_sidx; rg_occ = idx->t_eidx; + if(is_rev) { + k = t_str->cn - idx->t_eidx; rg_occ = t_str->cn - idx->t_sidx; + } + cns_cov_occ = match_cns_occ = 0; + assert(k < rg_occ); + for (; k < rg_occ; k++) { + assert((t_cov_buf[k]!=(uint64_t)-1) && (t_cov_buf[k] > 0)); + hm = ((t_cov_buf[k]<<1)>>1); + cns_cov_occ += hm; + if(t_cov_buf[k]&((uint64_t)(0x8000000000000000))) match_cns_occ += hm; + } + + if(cns_cov_occ <= 0 || match_cns_occ <= 0) return 0; + if(match_cns_occ <= (cns_cov_occ*0.5)) return 0; + } + ///not useful for correction + if((idx->q_sidx + 1 == idx->q_eidx) && (idx->t_sidx + 1 == idx->t_eidx)) {///must matched with at least one cns node + return 0; + } + + // /**if(tid == 3074)**/ { + // print_integer_ovlps(ug, str, buf->b.a, buf->b.n, idx, 1, qid, buf->o.n); + // fprintf(stderr, "[M::%s::tid->%ld] idx->q_sidx::%u, idx->q_eidx::%u, idx->t_sidx::%u, idx->t_eidx::%u\n******************************************************\n", + // __func__, tid, idx->q_sidx, idx->q_eidx, idx->t_sidx, idx->t_eidx); + // } + + return 1; +} + + +void uc_block_qse_cutoff(uint32_t c_ts, uint32_t c_te, uc_block_t *x, uint32_t *nqs, uint32_t *nqe) +{ + uint32_t l, r; + assert(c_ts >= x->ts && c_te <= x->te); + if(!(x->rev)) { + l = c_ts - x->ts; r = x->te - c_te; + } else { + r = c_ts - x->ts; l = x->te - c_te; + } + + (*nqs) = x->qs + get_offset_adjust(l, x->te - x->ts, x->qe - x->qs); + (*nqe) = x->qe - get_offset_adjust(r, x->te - x->ts, x->qe - x->qs); + assert((*nqs) >= x->qs && (*nqe) <= x->qe); +} + +int64_t update_exact_ul_ovlps(all_ul_t *ul_idx, ma_ug_t *ug, ul_str_t *str, integer_aln_t *aln, ul_chain_t *idx, int64_t qid, +integer_t *buf, ul2ul_t *res) +{ + if(idx->e<=idx->s) return 0; + int64_t qk, tk, is_rev, tid, q_end, t_end; + ul_str_t *q_str, *t_str; integer_aln_t *x; + tid = aln[idx->s].tn_rev_qk>>33; is_rev = ((aln[idx->s].tn_rev_qk>>32)&1); + q_str = &(str[qid]); t_str = &(str[tid]); + uint64_t os, oe; uint32_t v, w, q_ns, q_ne, t_ns, t_ne, acc, chained, qbs, qbe, tbs, tbe; + // if(qid == 95 || qid == 36) { + // fprintf(stderr,"[M::%s::qid->%ld::tid->%ld] qs_idx::%u, qe_idx::%u, ts_idx::%u, te_idx::%u\n", __func__, qid, tid, + // (uint32_t)(aln[idx->s].tn_rev_qk), (uint32_t)(aln[idx->e-1].tn_rev_qk), + // aln[idx->s].tk, aln[idx->e-1].tk); + // } + //beg + x = &(aln[idx->s]); + qk = (uint32_t)(x->tn_rev_qk); tk = ((is_rev == 0)? (x->tk):(t_str->cn - x->tk - 1)); + if((qk > 0) && (x->tk > 0)) return 0; + idx->q_sidx = (uint32_t)(x->tn_rev_qk); idx->t_sidx = x->tk; + + //end + x = &(aln[idx->e-1]); + qk = (uint32_t)(x->tn_rev_qk); tk = ((is_rev == 0)? (x->tk):(t_str->cn - x->tk - 1)); + if((((uint32_t)qk + 1) < q_str->cn) && ((x->tk + 1) < t_str->cn)) return 0; + idx->q_eidx = (uint32_t)(x->tn_rev_qk)+1; idx->t_eidx = x->tk+1; + + if((idx->q_eidx - idx->q_sidx) != (idx->t_eidx - idx->t_sidx)) return 0; + if(idx->q_eidx <= idx->q_sidx) return 0; + + qk = idx->q_sidx; q_end = idx->q_eidx; + tk = idx->t_sidx; t_end = idx->t_eidx; + for (; qk < q_end && tk < t_end; qk++, tk++){ + v = ((uint32_t)q_str->a[qk]); + if(!is_rev) w = ((uint32_t)t_str->a[tk]); + else w = ((uint32_t)t_str->a[t_str->cn-tk-1])^1; + if(v != w) break; + } + if(qk!=q_end || tk!=t_end) return 0; + + uc_block_t *qi, *ti; + qk = idx->q_sidx; q_end = idx->q_eidx; + tk = idx->t_sidx; t_end = idx->t_eidx; + + buf->p.n = buf->f.n = buf->o.n = buf->u.n = 0; + kv_resize(int64_t, buf->p, idx->q_eidx - idx->q_sidx); int64_t *p = buf->p.a; + kv_resize(int64_t, buf->f, idx->q_eidx - idx->q_sidx); int64_t *f = buf->f.a; + kv_resize(uint64_t, buf->o, idx->q_eidx - idx->q_sidx); uint64_t *qc = buf->o.a; + kv_resize(uint64_t, buf->u, idx->q_eidx - idx->q_sidx); uint64_t *tc = buf->u.a; + int64_t max_f, max_z, csc, ps, sc, tf, tz, z; + for (acc = 0, chained = 1, tf = tz = -1; qk < q_end && tk < t_end; qk++, tk++) { + qi = &(ul_idx->a[qid].bb.a[q_str->a[qk]>>32]); + if(!is_rev) ti = &(ul_idx->a[tid].bb.a[t_str->a[tk]>>32]); + else ti = &(ul_idx->a[tid].bb.a[t_str->a[t_str->cn-tk-1]>>32]); + assert(qi->hid == ti->hid); + os = MAX(qi->ts, ti->ts); oe = MIN(qi->te, ti->te); + if(oe <= os) continue; + uc_block_qse_cutoff(os, oe, qi, &q_ns, &q_ne); + uc_block_qse_cutoff(os, oe, ti, &t_ns, &t_ne); + qc[acc] = q_ns; qc[acc] <<= 32; qc[acc] |= q_ne; + tc[acc] = t_ns; tc[acc] <<= 32; tc[acc] |= t_ne; + + z = acc; z -= 1; csc = q_ne - q_ns; if(csc <= 0) csc = 1; + max_f = csc; max_z = -1; ps = 0; + if(chained && z >= 0) { + qbs = qc[z]>>32; qbe = (uint32_t)qc[z]; + tbs = tc[z]>>32; tbe = (uint32_t)tc[z]; + if(!is_rev) { + if(qbs <= q_ns && qbe <= q_ne && tbs <= t_ns && tbe <= t_ne) ps = 1; + } else { + if(qbs <= q_ns && qbe <= q_ne && tbs >= t_ns && tbe >= t_ne) ps = 1; + } + if(ps) { + sc = csc + f[z]; + if(sc > max_f) { + max_f = sc; max_z = z; + } + } else { + chained = 0; + } + } + + if((!ps) || (!chained)) { + for (; z >= 0; z--) { + qbs = qc[z]>>32; qbe = (uint32_t)qc[z]; + tbs = tc[z]>>32; tbe = (uint32_t)tc[z]; + ps = 0; + if(!is_rev) { + if(qbs <= q_ns && qbe <= q_ne && tbs <= t_ns && tbe <= t_ne) ps = 1; + } else { + if(qbs <= q_ns && qbe <= q_ne && tbs >= t_ns && tbe >= t_ne) ps = 1; + } + if(!ps) continue; + sc = csc + f[z]; + if(sc > max_f) { + max_f = sc; max_z = z; + } + } + } + + f[acc] = max_f; p[acc] = max_z; + if(tf < max_f) { + tf = max_f; tz = acc; + } + acc++; + } + if(acc <= 0) return 0; + assert(tz >= 0); + res->hid = res->qs = res->qe = res->ts = res->te = (uint32_t)-1; + res->hid = tid; res->is_rev = !!is_rev; res->is_del = 0; res->is_ct = 0; + res->qs_k = idx->q_sidx; res->qe_k = idx->q_eidx; + if(!is_rev) { + res->ts_k = idx->t_sidx; res->te_k = idx->t_eidx; + } else { + res->ts_k = t_str->cn - idx->t_eidx; res->te_k = t_str->cn - idx->t_sidx; + } + + + res->qe = (uint32_t)qc[tz]; + if(!is_rev) res->te = (uint32_t)tc[tz]; + else res->ts = tc[tz]>>32; + + for (z = tz; z >= 0; z = p[z]) { + res->qs = qc[z]>>32; + if(!is_rev) res->ts = tc[z]>>32; + else res->te = (uint32_t)tc[z]; + } + assert(res->qs <= res->qe && res->ts <= res->te); + + + int64_t qs = 0, qe = 0, rs = 0, re = 0, qtail = 0, rtail = 0; + qs = res->qs; qe = res->qe; rs = res->ts; re = res->te; + if(is_rev) { + rs = ul_idx->a[tid].rlen - res->te; re = ul_idx->a[tid].rlen - res->ts; + } + if(qs <= rs) { + rs -= qs; qs = 0; + } else { + qs -= rs; rs = 0; + } + + qtail = ul_idx->a[qid].rlen - qe; rtail = ul_idx->a[tid].rlen - re; + if(qtail <= rtail) { + qe = ul_idx->a[qid].rlen; re += qtail; + } + else { + re = ul_idx->a[tid].rlen; qe += rtail; + } + res->qs = qs; res->qe = qe; + res->ts = rs; res->te = re; + if(is_rev) { + res->ts = ul_idx->a[tid].rlen - re; + res->te = ul_idx->a[tid].rlen - rs; + } + return 1; +} + + + +void reset_poa_g_t(poa_g_t *g) +{ + g->seq.n = g->arc.n = g->idx.n = 0; g->update_arc = g->update_seq = g->e_idx.n = 0; +} + +void clean_poa_g_t(poa_g_t *g) +{ + uint64_t set_n = g->seq.n<<1; + assert(g->arc.n >= g->update_arc); assert(g->seq.n >= g->update_seq); + if(g->seq.n > g->update_seq) { + kv_resize(uint64_t, g->idx, (g->seq.n<<1)); set_n = g->update_seq<<1; + memset(g->idx.a + (g->update_seq<<1), 0, sizeof((*g->idx.a))*((g->seq.n<<1)-(g->update_seq<<1))); + g->update_seq = g->seq.n; g->idx.n = (g->seq.n<<1); + } + + if(g->arc.n > g->update_arc) { + radix_sort_poa_arc_srt(g->arc.a, g->arc.a + g->arc.n); + memset(g->idx.a, 0, sizeof((*g->idx.a))*set_n); + int64_t k, last, n = g->arc.n; + for (k = 1, last = 0; k <= n; ++k){ + if (k == n || g->arc.a[k-1].ul>>32 != g->arc.a[k].ul>>32) { + g->idx.a[g->arc.a[k-1].ul>>32] = (((uint64_t)last<<32)) | (k - last), last = k; + } + } + g->update_arc = g->arc.n; + } +} + +void append_unmatch_integer_seq(poa_g_t *g, ma_ug_t *ug, uc_block_t *raw, ul_str_t *str, int64_t s, int64_t e, int64_t is_rev, int64_t str_id) +{ + int64_t k; poa_nid_t *nn; poa_arc_t *ae; uint32_t v; uc_block_t *z; emap_t *em; + for (k = s; k < e; k++) { + if(is_rev) { + v = (((uint32_t)str->a[str->cn-k-1])^1); + z = &(raw[str->a[str->cn-k-1]>>32]); + } + else { + v = ((uint32_t)str->a[k]); z = &(raw[str->a[k]>>32]); + } + kv_pushp(poa_nid_t, g->seq, &nn); + nn->nid = v; nn->occ = ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); + + // ug->u.a[v>>1].n; + if(k > s) { + kv_pushp(poa_arc_t, g->arc, &ae); + ae->ul = g->seq.n-1; ae->ul <<= 33; ae->ul += ((uint64_t)(0x100000000)); ae->ul += 1; + ae->v = g->seq.n-2; ae->v <<= 1; ae->v += 1; + + kv_pushp(poa_arc_t, g->arc, &ae); + ae->ul = g->seq.n-2; ae->ul <<= 33; ae->ul += 1; + ae->v = g->seq.n-1; ae->v <<= 1; + + kv_pushp(emap_t, g->e_idx, &em); + em->pge = g->seq.n-2; em->pge <<= 32; em->pge += g->seq.n-1; + em->ule = (is_rev?(str->cn-k):(k-1)); em->ule <<= 32; em->ule += (is_rev?(str->cn-k-1):(k)); + em->ulid = str_id; + // assert((g->seq.a[em->pge>>32].nid^(is_rev?1:0)) == ((uint32_t)str->a[em->ule>>32])); + // assert((g->seq.a[(uint32_t)em->pge].nid^(is_rev?1:0)) == ((uint32_t)str->a[(uint32_t)em->ule])); + } + } +} + +void update_poa_nid_occ(ma_ug_t *ug, uc_block_t *raw, poa_g_t *g, int64_t gidx, uint64_t *str, int64_t str_idx, int64_t is_rev) +{ + uint32_t g_v, str_v, new_occ; uc_block_t *z; + ///update + g_v = g->seq.a[gidx].nid; + z = &(raw[str[str_idx]>>32]); str_v = ((uint32_t)str[str_idx]); if(is_rev) str_v ^= 1; + assert(g_v == str_v); assert(g->seq.a[gidx].occ <= ug->u.a[g->seq.a[gidx].nid>>1].n); + if(g->seq.a[gidx].occ != ug->u.a[g->seq.a[gidx].nid>>1].n) { + new_occ = ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); + if(new_occ > g->seq.a[gidx].occ) g->seq.a[gidx].occ = new_occ; + } +} + +void insert_poa_nodes_0(ma_ug_t *ug, uc_block_t *raw, poa_g_t *g, uint64_t *str, int64_t str_occ, uint64_t is_rev, int64_t str_id, int64_t str_off) +{ + int64_t k; poa_nid_t *nn; poa_arc_t *ae; uint32_t v; uc_block_t *z; emap_t *em; + for (k = 0; k < str_occ; k++) { + if(is_rev == 0) { + v = ((uint32_t)str[k]); z = &(raw[str[k]>>32]); + } else { + v = ((uint32_t)str[str_occ-k-1])^1; z = &(raw[str[str_occ-k-1]>>32]); + } + + kv_pushp(poa_nid_t, g->seq, &nn); + nn->nid = v; nn->occ = ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); + + if(k > 0) { + kv_pushp(poa_arc_t, g->arc, &ae); + ae->ul = g->seq.n-1; ae->ul <<= 33; ae->ul += ((uint64_t)(0x100000000)); ae->ul += 1; + ae->v = g->seq.n-2; ae->v <<= 1; ae->v += 1; + + kv_pushp(poa_arc_t, g->arc, &ae); + ae->ul = g->seq.n-2; ae->ul <<= 33; ae->ul += 1; + ae->v = g->seq.n-1; ae->v <<= 1; + + kv_pushp(emap_t, g->e_idx, &em); + em->pge = g->seq.n-2; em->pge <<= 32; em->pge += g->seq.n-1; + em->ule = str_off + (is_rev?(str_occ-k):(k-1)); em->ule <<= 32; + em->ule += str_off + (is_rev?(str_occ-k-1):(k)); + em->ulid = str_id; + + // if(!((g->seq.a[em->pge>>32].nid^(is_rev?1:0)) == ((uint32_t)debug_str->a[em->ule>>32]))) { + // fprintf(stderr, "[M::%s::k->%ld::str_occ->%ld] is_rev->%lu, pg_v->%u, str_v->%u, str_off->%ld, str_k->%lu, str_cn->%u, address_diff->%u\n", + // __func__, k, str_occ, is_rev, (g->seq.a[em->pge>>32].nid^(is_rev?1:0)), + // ((uint32_t)debug_str->a[em->ule>>32]), str_off, em->ule>>32, debug_str->cn, (uint32_t)(str - debug_str->a)); + // uint64_t debug_k; + // for (debug_k = 0; debug_k < debug_str->cn; debug_k++) { + // fprintf(stderr, "[M::%s::debug_k->%lu] str_v->%u\n", + // __func__, debug_k, ((uint32_t)debug_str->a[debug_k])); + // } + + // } + // assert((g->seq.a[em->pge>>32].nid^(is_rev?1:0)) == ((uint32_t)debug_str->a[em->ule>>32])); + // assert((g->seq.a[(uint32_t)em->pge].nid^(is_rev?1:0)) == ((uint32_t)debug_str->a[(uint32_t)em->ule])); + } + } +} + +void push_poa_arch_0(poa_g_t *g, uint32_t src, uint32_t des, int64_t str_id, int64_t str_src, int64_t str_des) +{ + poa_arc_t *ae; emap_t *em; + kv_pushp(poa_arc_t, g->arc, &ae); + ae->ul = des; ae->ul <<= 33; ae->ul += ((uint64_t)(0x100000000)); ae->ul += 1; + ae->v = src; ae->v <<= 1; ae->v += 1; + + kv_pushp(poa_arc_t, g->arc, &ae); + ae->ul = src; ae->ul <<= 33; ae->ul += 1; + ae->v = des; ae->v <<= 1; + + kv_pushp(emap_t, g->e_idx, &em); + em->pge = src; em->pge <<= 32; em->pge += des; + em->ule = str_src; em->ule <<= 32; em->ule += str_des; + em->ulid = str_id; + + // assert((g->seq.a[em->pge>>32].nid^(debug_is_rev?1:0)) == ((uint32_t)debug_str->a[em->ule>>32])); + // assert((g->seq.a[(uint32_t)em->pge].nid^(debug_is_rev?1:0)) == ((uint32_t)debug_str->a[(uint32_t)em->ule])); +} + +void update_poa_arch_0(poa_g_t *g, uint32_t src, uint32_t des, int64_t str_id, int64_t str_src, int64_t str_des) +{ + uint32_t k, v, w, a_n; poa_arc_t *a; emap_t *em; + v = src<<1; w = des<<1; + a_n = poa_arc_n(g, v); a = poa_arc_a(g, v); + for (k = 0; k < a_n; k++) { + if(a[k].v == w) break; + } + if(k >= a_n) { + push_poa_arch_0(g, src, des, str_id, str_src, str_des); + } else { + a[k].ul++; + v = des<<1; v^=1; + w = src<<1; w^=1; + a_n = poa_arc_n(g, v); a = poa_arc_a(g, v); + for (k = 0; k < a_n; k++) { + if(a[k].v == w) break; + } + assert(k < a_n); + a[k].ul++; + + kv_pushp(emap_t, g->e_idx, &em); + em->pge = src; em->pge <<= 32; em->pge += des; + em->ule = str_src; em->ule <<= 32; em->ule += str_des; + em->ulid = str_id; + + // assert((g->seq.a[em->pge>>32].nid^(debug_is_rev?1:0)) == ((uint32_t)debug_str->a[em->ule>>32])); + // assert((g->seq.a[(uint32_t)em->pge].nid^(debug_is_rev?1:0)) == ((uint32_t)debug_str->a[(uint32_t)em->ule])); + } +} + +void append_integer_seq_frag(ma_ug_t *ug, uc_block_t *raw, poa_g_t *g, int64_t g_beg, int64_t g_end, uint64_t *str, int64_t str_occ, uint64_t is_rev, int64_t str_id, int64_t str_off) +{ + // if(str_occ <= 0) return; + uint32_t nid; + // if((g_beg >= 0 || g_end >= 0) && str_occ < 2) return; + if(g_beg < 0 && g_end < 0) {//add new nodes + insert_poa_nodes_0(ug, raw, g, str, str_occ, is_rev, str_id, str_off); + return; + } + + if(g_beg < 0 && g_end >= 0) {///add nodes to the left end + assert(str_occ >= 1); + update_poa_nid_occ(ug, raw, g, g_end, str, (is_rev?(0):(str_occ-1)), is_rev); + if(str_occ < 2) return; + insert_poa_nodes_0(ug, raw, g, (is_rev?(str+1):(str)), str_occ-1, is_rev, str_id, str_off+(is_rev?(1):(0))); + + push_poa_arch_0(g, g->seq.n-1, g_end, str_id, str_off + (is_rev?(1):(str_occ-2)), + str_off + (is_rev?(0):(str_occ-1))); + return; + } + + if(g_beg >= 0 && g_end < 0) {///add nodes to the right end + assert(str_occ >= 1); + update_poa_nid_occ(ug, raw, g, g_beg, str, (is_rev?(str_occ-1):(0)), is_rev); + if(str_occ < 2) return; + nid = g->seq.n;///backup + insert_poa_nodes_0(ug, raw, g, (is_rev?(str):(str+1)), str_occ-1, is_rev, str_id, str_off+(is_rev?(0):(1))); + push_poa_arch_0(g, g_beg, nid, str_id, str_off + (is_rev?(str_occ-1):(0)), + str_off + (is_rev?(str_occ-2):(1))); + return; + } + + if(g_beg >= 0 && g_end >= 0) {///add nodes to the middle + assert(str_occ >= 2); + update_poa_nid_occ(ug, raw, g, g_beg, str, (is_rev?(str_occ-1):(0)), is_rev); + update_poa_nid_occ(ug, raw, g, g_end, str, (is_rev?(0):(str_occ-1)), is_rev); + if(str_occ > 2) {///insert new nodes + nid = g->seq.n;///backup + insert_poa_nodes_0(ug, raw, g, str+1, str_occ-2, is_rev, str_id, str_off+1); + push_poa_arch_0(g, g_beg, nid, str_id, str_off + (is_rev?(str_occ-1):(0)), + str_off + (is_rev?(str_occ-2):(1))); + push_poa_arch_0(g, g->seq.n-1, g_end, str_id, str_off + (is_rev?(1):(str_occ-2)), + str_off + (is_rev?(0):(str_occ-1))); + } else { + ///add an edge between g_beg and g_end + update_poa_arch_0(g, g_beg, g_end, str_id, str_off + (is_rev?(str_occ-1):(0)), + str_off + (is_rev?(0):(str_occ-1))); + } + } +} + +void append_aligned_integer_seq(ma_ug_t *ug, uc_block_t *raw, poa_g_t *g, int64_t g_occ, uint64_t *str, int64_t str_occ, uint64_t is_rev, +uint32_t *match_g, uint32_t *match_str, int64_t match_occ) +{ + if(str_occ <= 0) return; + int64_t k, p_str, p_g; + + if(is_rev == 0) { + for (k = match_occ-1, p_str = 0, p_g = -1; k >= 0; k--) { + fprintf(stderr, "+[M::%s::] match_str[%ld]::%u, match_occ::%ld, p_g::%ld\n", + __func__, k, match_str[k], match_occ, p_g); + assert(((int64_t)match_str[k]) >= p_str); + // append_integer_seq_frag(ug, raw, g, p_g, match_g[k], str+p_str, match_str[k]+1-p_str, is_rev); + p_str = match_str[k]; p_g = match_g[k]; + } + // append_integer_seq_frag(ug, raw, g, p_g, -1, str+p_str, str_occ-p_str, is_rev); + } else { + for (k = match_occ-1, p_str = str_occ-1, p_g = -1; k >= 0; k--) { + fprintf(stderr, "-[M::%s::] match_str[%ld]::%u, match_occ::%ld\n", + __func__, k, match_str[k], match_occ); + assert(((int64_t)match_str[k]) <= p_str); + // append_integer_seq_frag(ug, raw, g, p_g, match_g[k], str+match_str[k], p_str+1-match_str[k], is_rev); + p_str = match_str[k]; p_g = match_g[k]; + } + // append_integer_seq_frag(ug, raw, g, p_g, -1, str, p_str+1, is_rev); + } +} + + +#define poa_str_idx(i, occ, is_rev) (((is_rev))?((occ)-(i)-1):(i)) +void append_aligned_integer_seq_by_aln_pair(ma_ug_t *ug, uc_block_t *raw, poa_g_t *g, int64_t g_occ, uint64_t *str, int64_t str_occ, uint64_t is_rev, integer_aln_t *a, int64_t a_n, int64_t str_id, int64_t str_off) +{ + if(str_occ <= 0 || a_n <= 0) return; + int64_t k, p_str, p_g; uint64_t *qstr_a, qstr_n, qoff; uint32_t *gidx = g->srt_b.res.a; + + for (k = 0, p_g = -1, p_str = (is_rev?(str_occ-1):(0)); k < a_n; k++) { + if(!is_rev) { + qstr_a = str+p_str; qstr_n = ((uint32_t)a[k].tn_rev_qk)+1-p_str; qoff = p_str + str_off; + } else { + qstr_a = str+poa_str_idx(((uint32_t)a[k].tn_rev_qk), str_occ, is_rev); + qstr_n = p_str+1-(poa_str_idx(((uint32_t)a[k].tn_rev_qk), str_occ, is_rev)); + qoff = poa_str_idx(((uint32_t)a[k].tn_rev_qk), str_occ, is_rev) + str_off; + } + // if(str_id == 47072) { + // fprintf(stderr, "+[M::%s::k->%ld] p_g::%ld, c_g::%u, p_str::%ld, c_str::%ld, str_off::%ld, qoff::%lu, qstr_n::%lu\n", + // __func__, k, p_g, gidx[a[k].tk], p_str, poa_str_idx(((uint32_t)a[k].tn_rev_qk), str_occ, is_rev), + // str_off, qoff, qstr_n); + // } + + append_integer_seq_frag(ug, raw, g, p_g, gidx[a[k].tk], qstr_a, qstr_n, is_rev, str_id, qoff); + + p_str = (uint32_t)a[k].tn_rev_qk; + if(is_rev) p_str = poa_str_idx(p_str, str_occ, is_rev); + p_g = gidx[a[k].tk]; + } + if(!is_rev) { + qstr_a = str+p_str; qstr_n = str_occ-p_str; qoff = p_str + str_off; + } else { + qstr_a = str; qstr_n = p_str+1; qoff = str_off; + } + append_integer_seq_frag(ug, raw, g, p_g, -1, qstr_a, qstr_n, is_rev, str_id, qoff); +} + + +uint32_t topo_srt_gen(poa_g_t *g, uint32_t debug_qid, ma_ug_t *ug) +{ + uint32_t k, v, w, a_n; poa_arc_t *a; + kv_resize(uint32_t, g->srt_b.ind, g->seq.n); + kv_resize(uint32_t, g->srt_b.stack, g->seq.n); + kv_resize(uint32_t, g->srt_b.res, g->seq.n); + kv_resize(uint32_t, g->srt_b.res2nid, g->seq.n); + // kv_resize(uint64_t, g->srt_b.aln, g->seq.n); g->srt_b.aln.n = 0; + g->srt_b.ind.n = g->srt_b.stack.n = g->srt_b.res.n = g->srt_b.res2nid.n = 0; + + for (k = 0; k < g->seq.n; k++) { + v = (k<<1) + 1; + g->srt_b.ind.a[k] = poa_arc_n(g, v); + if(g->srt_b.ind.a[k] == 0) kv_push(uint32_t, g->srt_b.stack, k); + } + + while (g->srt_b.stack.n > 0) { + v = g->srt_b.stack.a[--g->srt_b.stack.n]; kv_push(uint32_t, g->srt_b.res, v); v <<= 1; + a_n = poa_arc_n(g, v); a = poa_arc_a(g, v); + for (k = 0; k < a_n; k++) { + w = a[k].v>>1; + g->srt_b.ind.a[w]--; + if(g->srt_b.ind.a[w] == 0) kv_push(uint32_t, g->srt_b.stack, w); + } + } + // if(!(g->srt_b.res.n == g->seq.n)) { + // fprintf(stderr, "[M::%s::] debug_qid::%u, g->seq.n::%u, g->srt_b.res.n::%u\n", + // __func__, debug_qid, (uint32_t)g->seq.n, (uint32_t)g->srt_b.res.n); + // print_integer_g(g, ug, 1); + // for (k = 0; k < g->seq.n; k++) { + // if(g->srt_b.ind.a[k] > 0) fprintf(stderr, "circle->nid::%u\n", k); + // } + // } + if(g->srt_b.res.n != g->seq.n) return 0;///there is a circle + assert(g->srt_b.res.n == g->seq.n); + for (k = 0; k < g->seq.n; k++) { + g->srt_b.res2nid.a[g->srt_b.res.a[k]] = k; + // g->srt_b.aln.a[k] = g->seq.a[g->srt_b.res.a[k]].nid; + // g->srt_b.aln.a[k] <<= 32; g->srt_b.aln.a[k] += k; + } + // radix_sort_srt64(g->srt_b.aln.a, g->srt_b.aln.a + g->srt_b.aln.n); + return 1; +} + +void init_poa_dp(ma_ug_t *ug, poa_dp_t *dp, poa_g_t *g, uint64_t g_occ, uint64_t *str, uint64_t str_occ, uint64_t is_rev, uc_block_t *raw, integer_t *buf) +{ + kv_resize(uint8_t, dp->dir, (str_occ+1)*(g_occ+1)); + kv_resize(int64_t, dp->sc, (str_occ+1)*(g_occ+1)); + kv_resize(uint64_t, dp->prefix, (str_occ+1)*(g_occ+1)); + dp->n = str_occ+1; dp->m = g_occ+1; + kv_resize(uint64_t, buf->u, str_occ); + int64_t *sc = dp->sc.a, bsc, ss; uint8_t *dir = dp->dir.a; uint64_t k, l, *str_w = buf->u.a, *prefix = dp->prefix.a, m; + uc_block_t *z; uint32_t *g_idx = g->srt_b.res.a, *n2gidx = g->srt_b.res2nid.a, v, w, a_n, bsc_i; poa_arc_t *a; + for (k = 0; k < str_occ; k++) { + z = &(raw[str[k]>>32]); str_w[k] = ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); + } + + sc[poa_dp_idx(*dp, 0, 0)] = dir[poa_dp_idx(*dp, 0, 0)] = 0; + for (k = 1, l = 0; k < dp->n; k++) {///pat; new ul read + l += str_w[poa_str_idx(k-1, str_occ, is_rev)]; + sc[poa_dp_idx(*dp, k, 0)] = l; + dir[poa_dp_idx(*dp, k, 0)] = lstr_dp; + prefix[poa_dp_idx(*dp, k, 0)] = ((k - 1)<<32); + } + + for (k = 1; k < dp->m; k++) {///ref; graph + v = (g_idx[k-1]<<1) + 1; + a_n = poa_arc_n(g, v); a = poa_arc_a(g, v); + for (m = 0, bsc = bsc_i = 0; m < a_n; m++) { + w = n2gidx[a[m].v>>1]; assert(w+1 < k); + ss = sc[poa_dp_idx(*dp, 0, w+1)]; + if(ss < bsc || bsc_i == 0) { + bsc = ss; bsc_i = w + 1; + } + } + sc[poa_dp_idx(*dp, 0, k)] = bsc + g->seq.a[v>>1].occ; + dir[poa_dp_idx(*dp, 0, k)] = lref_dp; + prefix[poa_dp_idx(*dp, 0, k)] = bsc_i; + } +} + +uint32_t update_poa_dp(poa_g_t *g, uint32_t debug_qid, ma_ug_t *debug_ug) +{ + uint32_t is_srt = 0/**, is_up_aln = 0**/, k, is_circle = 0; + if(g->seq.n > g->update_seq || g->arc.n > g->update_arc) { + if(g->seq.n > g->update_seq) { + kv_resize(uint32_t, g->srt_b.res, g->seq.n); + kv_resize(uint32_t, g->srt_b.res2nid, g->seq.n); + // kv_resize(uint64_t, g->srt_b.aln, g->seq.n); g->srt_b.aln.n = g->seq.n; + g->srt_b.res.n = g->srt_b.res2nid.n = g->seq.n; + for (k = g->update_seq; k < g->seq.n; k++) { + g->srt_b.res.a[k] = g->srt_b.res2nid.a[k] = k; + // g->srt_b.aln.a[k] = (((uint64_t)(g->seq.a[k].nid))<<32)+k; + // if(k > 0 && is_up_aln == 0) { + // if((g->srt_b.aln.a[k]>>32) < (g->srt_b.aln.a[k-1]>>32)) is_up_aln = 1; + // } + } + } + if(g->arc.n > g->update_arc) { ///check if it is necessary to resort + for (k = g->update_arc; k < g->arc.n; k++) { + if((g->arc.a[k].ul>>32)&1) continue; + if(g->srt_b.res2nid.a[g->arc.a[k].ul>>33] >= g->srt_b.res2nid.a[g->arc.a[k].v>>1]) break; + } + if(k < g->arc.n) is_srt = 1; + } + // fprintf(stderr, "[M::%s::] is_srt::%u\n", __func__, is_srt); + clean_poa_g_t(g); + if(is_srt) { + is_circle = 1 - topo_srt_gen(g, debug_qid, debug_ug); + } + // else if(is_up_aln) { + // radix_sort_srt64(g->srt_b.aln.a, g->srt_b.aln.a + g->srt_b.aln.n); + // } + } + + return is_circle; +} + +/** +void poa_dp(poa_g_t *g, ma_ug_t *ug, uc_block_t *raw, ul_str_t *str, int64_t s, int64_t e, int64_t is_rev, integer_t *buf) +{ + if(e <= s) return; + + + + uint32_t *g_idx = g->srt_b.res.a, *n2gidx = g->srt_b.res2nid.a, gnid, v, a_n, pat_v, g_v; + uint64_t *pat = (is_rev?(str->a + str->cn - e):(str->a + s)), pat_n = e - s, pp; + init_poa_dp(ug, &(g->dp), g, g->seq.n, pat, pat_n, is_rev, raw, buf); + int64_t *sc = g->dp.sc.a, min_w, c_w; uint8_t *dir = g->dp.dir.a; + uint64_t *str_w = buf->u.a, *prefix = g->dp.prefix.a; + poa_arc_t *a; poa_dp_t *dp = &(g->dp); + int64_t min_i, min_k, min_d, i, k, n = g->dp.n - 1, m = g->dp.m - 1, match_sc, z, pidx, g_k, pat_k; + fprintf(stderr, "[M::%s::] ts::%ld, te::%ld, is_rev::%ld, m::%ld(g->seq.n::%u), n::%ld(pat_n::%lu)\n", + __func__, s, e, is_rev, m, (uint32_t)g->seq.n, n, pat_n); + for (i = 0; i < m; i++) {///graph + gnid = g_idx[i]; v = (gnid<<1) + 1; g_v = g->seq.a[gnid].nid; + a_n = poa_arc_n(g, v); a = poa_arc_a(g, v); + for (k = 0; k < n; k++) {//read + pat_v = (uint32_t)pat[poa_str_idx(k, pat_n, is_rev)]; if(is_rev) pat_v ^= 1; + if(g_v == pat_v) { + match_sc = str_w[poa_str_idx(k, pat_n, is_rev)]; match_sc *= -1; + } else { + match_sc = str_w[poa_str_idx(k, pat_n, is_rev)]; + if(match_sc < g->seq.a[gnid].occ) match_sc = g->seq.a[gnid].occ; + } + + ///longer graph/shorter read + min_w = sc[poa_dp_idx(*dp, k, i+1)] + g->seq.a[gnid].occ; + min_i = i + 1; min_k = k; min_d = lg_dp; + + for (z = 0; z < a_n; z++) { + pidx = n2gidx[a[z].v>>1]; assert(pidx < i); + ///match + c_w = sc[poa_dp_idx(*dp, k, pidx+1)] + match_sc; + if(c_w < min_w) { + min_w = c_w; min_i = pidx+1; min_k = k; + if(match_sc <= 0) min_d = e_pdp; + else min_d = ue_pdp; + } + ///longer read/shorter graph + c_w = sc[poa_dp_idx(*dp, k+1, pidx+1)] + str_w[poa_str_idx(k, pat_n, is_rev)]; + if(c_w < min_w) { + min_w = c_w; min_i = pidx+1; min_k = k + 1; min_d = lstr_dp; + } + } + + if(a_n == 0) {///no prefix + pidx = -1; + ///match + c_w = sc[poa_dp_idx(*dp, k, pidx+1)] + match_sc; + if(c_w < min_w) { + min_w = c_w; min_i = pidx+1; min_k = k; + if(match_sc <= 0) min_d = e_pdp; + else min_d = ue_pdp; + } + ///longer read/shorter graph + c_w = sc[poa_dp_idx(*dp, k+1, pidx+1)] + str_w[poa_str_idx(k, pat_n, is_rev)]; + if(c_w < min_w) { + min_w = c_w; min_i = pidx+1; min_k = k + 1; min_d = lstr_dp; + } + } + + sc[poa_dp_idx(*dp, k+1, i+1)] = min_w; dir[poa_dp_idx(*dp, k+1, i+1)] = min_d; + prefix[poa_dp_idx(*dp, k+1, i+1)] = (((uint64_t)min_k)<<32)|((uint64_t)min_i); + fprintf(stderr, "[M::%s::] i::%ld(graph->utg%.6d%c, min_i->%ld), k::%ld(str->utg%.6d%c, min_k->%ld), match_sc::%ld, min_w::%ld, min_d::%ld\n", + __func__, i+1, (int32_t)(g_v>>1)+1, "lc"[ug->u.a[g_v>>1].circ], min_i, + k+1, (int32_t)(pat_v>>1)+1, "lc"[ug->u.a[pat_v>>1].circ], min_k, match_sc, min_w, min_d); + } + } + + ///backtrack; global alignment + min_i = -1; min_k = n; min_w = 0; + for (i = 0; i < m; i++) {///go through graph + // gnid = g_idx[i]; v = (gnid<<1); + // if(poa_arc_n(g, v) > 0) continue; + c_w = sc[poa_dp_idx(*dp, min_k, i+1)]; + if(min_i < 0 || c_w < min_w) { + min_w = c_w; min_i = i+1; + } + } + assert(min_i > 0); + + g->srt_b.ind.n = g->srt_b.stack.n = 0; + while (min_i > 0 || min_k > 0) { + pat_k = poa_str_idx((min_k-1), pat_n, is_rev);///read + g_k = g_idx[min_i-1];///graph + fprintf(stderr, "******[M::%s::] min_i::%ld(gid->%ld, m->%ld), min_k::%ld(str_id->%ld, n->%ld), dir::%u, sc::%ld\n", + __func__, min_i, g_k, m, min_k, pat_k, n, + dir[poa_dp_idx(*dp, min_k, min_i)], sc[poa_dp_idx(*dp, min_k, min_i)]); + if(dir[poa_dp_idx(*dp, min_k, min_i)] == e_pdp) { + assert(g->seq.a[g_k].nid == (((uint32_t)pat[pat_k])^(is_rev?1:0))); + kv_push(uint32_t, g->srt_b.ind, pat_k); ///read + kv_push(uint32_t, g->srt_b.stack, g_k); ///graph + } + pp = prefix[poa_dp_idx(*dp, min_k, min_i)]; + assert((int64_t)(pp>>32)<=min_k); assert((int64_t)((uint32_t)pp)<=min_i); + min_k = pp >> 32; min_i = (uint32_t)pp; + } + if(!(g->srt_b.ind.n > 0 && g->srt_b.ind.n == g->srt_b.stack.n)) { + fprintf(stderr, "[M::%s::] g->srt_b.ind.n::%u, g->srt_b.stack.n::%u, ts::%ld, te::%ld\n", + __func__, (uint32_t)g->srt_b.ind.n, (uint32_t)g->srt_b.stack.n, s, e); + } + assert(g->srt_b.ind.n > 0 && g->srt_b.ind.n == g->srt_b.stack.n); + append_aligned_integer_seq(ug, raw, g, g->seq.n, pat, pat_n, is_rev, g->srt_b.stack.a, g->srt_b.ind.a, g->srt_b.ind.n); + update_poa_dp(g); +} + + +void poa_cns_dp(poa_g_t *g, all_ul_t *ul_idx, ma_ug_t *ug, ul_str_t *str, integer_aln_t *aln, +ul_chain_t *idx, int64_t idx_n, int64_t qid, integer_t *buf) +{ + int64_t k, tid, is_rev; + reset_poa_g_t(g); + + append_unmatch_integer_seq(g, ug, ul_idx->a[qid].bb.a, &(str[qid]), 0, str[qid].cn, 0, qid, 0); + clean_poa_g_t(g); topo_srt_gen(g); + + for (k = 0; k < idx_n; k++) { + tid = aln[idx[k].s].tn_rev_qk>>33; is_rev = ((aln[idx[k].s].tn_rev_qk>>32)&1); + fprintf(stderr, "\n[M::%s::] k::%ld, tid::%ld, is_rev::%ld\n", __func__, k, tid, is_rev); + print_integer_seq(ug, str, tid, 1); + poa_dp(g, ug, ul_idx->a[tid].bb.a, &(str[tid]), idx[k].t_sidx, idx[k].t_eidx, is_rev, buf); + } + + gen_cns_by_poa(g); +} +**/ + +int64_t suffix_gorder_check(poa_g_t *g, integer_t *buf, uint64_t gk_0, uint64_t gk_1, int64_t update_vis, uint64_t set_flag) +{ + uint32_t *g_idx = g->srt_b.res.a, *n2gidx = g->srt_b.res2nid.a, a_n, v, init_n, k; + poa_arc_t *a; + if(buf->vis.n != g->seq.n) { + kv_resize(uint32_t, buf->vis, g->seq.n); buf->vis.n = g->seq.n; + memset(buf->vis.a, -1, sizeof((*buf->vis.a))*buf->vis.n); + } + + if(update_vis) { + v = g_idx[gk_0]<<1; init_n = buf->vis.n; + kv_push(uint32_t, buf->vis, v); + while (buf->vis.n > init_n) { + v = buf->vis.a[--buf->vis.n]; + buf->vis.a[n2gidx[v>>1]] = set_flag; + a_n = poa_arc_n(g, v); a = poa_arc_a(g, v); + for (k = 0; k < a_n; k++) { + if(buf->vis.a[n2gidx[a[k].v>>1]] == set_flag) continue; + kv_push(uint32_t, buf->vis, a[k].v); + } + } + assert(buf->vis.n == init_n); + } + + if(buf->vis.a[gk_1] == set_flag) return 1; + return 0; +} + +int64_t integer_g_chain(poa_g_t *g, ma_ug_t *ug, integer_aln_t *a, int64_t a_n, integer_t *buf, ul_chain_t *res) +{ + res->v = res->s = res->e = (uint32_t)-1; res->sc = (uint64_t)-1; + res->q_sidx = res->q_eidx = res->t_sidx = res->t_eidx = (uint32_t)-1; + if(a_n <= 0) return 0; + int64_t i, k, *p, *f, tf, ti, csc, sc, max_f, max_k, vis_i, pas; integer_aln_t *li, *lk; + buf->vis.n = 0; vis_i = -1; + for (i = 1; i < a_n; ++i) {//already sorted by qk + if(((uint32_t)a[i].tn_rev_qk) <= ((uint32_t)a[i-1].tn_rev_qk)) break; ///== means there is a circle + if(a[i].tk == a[i-1].tk) break; + if(a[i].tk < a[i-1].tk) { + pas = suffix_gorder_check(g, buf, a[i].tk, a[i-1].tk, vis_i==i?0:1, i); vis_i = i; + if(pas) break; + } + } + // fprintf(stderr, "[M::%s::] i::%ld, a_n::%ld\n", __func__, i, a_n); + + if(i >= a_n) { + res->s = 0; res->e = a_n; + return 1; + } + + buf->p.n = buf->f.n = 0; + kv_resize(int64_t, buf->p, (uint64_t)a_n); p = buf->p.a; + kv_resize(int64_t, buf->f, (uint64_t)a_n); f = buf->f.a; + + tf = ti = -1; buf->vis.n = 0; vis_i = -1; + for (i = 0; i < a_n; ++i) { + li = &(a[i]); csc = li->sc; + max_f = csc; max_k = -1; + + for (k = i-1; k >= 0; --k) { + lk = &(a[k]); + ///qk of lk and li might be equal + if(((uint32_t)lk->tn_rev_qk) >= ((uint32_t)li->tn_rev_qk)) continue; + if(lk->tk == li->tk) continue; + if(lk->tk > li->tk) { + pas = suffix_gorder_check(g, buf, a[i].tk, a[k].tk, vis_i==i?0:1, i); + // if(i == 17 && a[i].tk == 6 && k == 16 && a[k].tk == 60) { + // fprintf(stderr, "******i::%ld, a[i].tk::%u, k::%ld, a[k].tk::%u, vis_i::%ld, pas::%ld\n", + // i, a[i].tk, k, a[k].tk, vis_i, pas); + // } + vis_i = i; if(pas) continue; + } + sc = csc + f[k]; + if(sc > max_f) { + max_f = sc; max_k = k; + } + } + f[i] = max_f; p[i] = max_k; + if(tf < max_f) { + tf = max_f; ti = i; + } + // fprintf(stderr, "[M::%s::i->%ld] qk::%u, tk::%u, max_k::%ld, max_f::%ld, ti::%ld\n", + // __func__, i, (uint32_t)li->tn_rev_qk, li->tk, max_k, max_f, ti); + } + + if(ti < 0) return 0; + for (i = ti, k = 0; i >= 0; i = p[i]) f[k++] = i; + assert(k > 0); + for (i = 0, k--; k >= 0; k--) { + a[i] = a[f[k]]; i++; + } + res->s = 0; res->e = i; + return 1; +} + + +void poa_chain_0(poa_g_t *g, ma_ug_t *ug, uc_block_t *raw, ul_str_t *str, int64_t s, int64_t e, int64_t is_rev, integer_t *buf, int64_t str_id, int64_t debug_qid, uint32_t *is_circle) +{ + (*is_circle) = 0; + if(e <= s) return; + uint32_t *g_idx = g->srt_b.res.a; uc_block_t *z; integer_aln_t *b; ul_chain_t rr; int64_t i, k, n; + uint64_t *pat = (is_rev?(str->a + str->cn - e):(str->a + s)), pp; int64_t pat_n = e - s; + // fprintf(stderr, "[M::%s::] ts::%ld, te::%ld, is_rev::%ld, g->seq.n::%u, pat_n::%lu\n", + // __func__, s, e, is_rev, (uint32_t)g->seq.n, pat_n); + + g->srt_b.aln.n = 0; n = g->seq.n; + for (k = 0; k < n; k++) {///graph + pp = (((uint64_t)(g->seq.a[g_idx[k]].nid))<<32); pp += ((uint64_t)(k)); pp += ((uint64_t)(0x80000000)); + kv_push(uint64_t, g->srt_b.aln, pp); + } + for (k = 0; k < pat_n; k++) { + pp = (uint32_t)pat[poa_str_idx(k, pat_n, is_rev)]; if(is_rev) pp ^= 1; pp <<= 32; pp += ((uint64_t)(k)); + kv_push(uint64_t, g->srt_b.aln, pp); + } + + radix_sort_srt64(g->srt_b.aln.a, g->srt_b.aln.a + g->srt_b.aln.n); n = g->srt_b.aln.n; + for (k = 0, buf->b.n = 0; k < n; k++) { + if(g->srt_b.aln.a[k]&((uint64_t)(0x80000000))) continue;///skip nodes in the graph + for (i = k+1; (i < n) && ((g->srt_b.aln.a[k]>>32) == (g->srt_b.aln.a[i]>>32)); i++) { + if((g->srt_b.aln.a[i]&((uint64_t)(0x80000000))) == 0) continue;///skip nodes in the read + ///a[k] is read (q); a[i] is graph (t) + kv_pushp(integer_aln_t, buf->b, &b); + b->vq = g->srt_b.aln.a[k]>>32; + b->tn_rev_qk = (uint32_t)g->srt_b.aln.a[k]; + b->tk = ((g->srt_b.aln.a[i]<<33)>>33); + z = &(raw[pat[poa_str_idx(b->tn_rev_qk, pat_n, is_rev)]>>32]); + b->sc = ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); + } + } + + n = buf->b.n; + radix_sort_integer_aln_t_srt(buf->b.a, buf->b.a + buf->b.n); ///sorted by qk + // fprintf(stderr, "[M::%s::] # align pairs::%ld\n", __func__, n); + + // for (i = 0; i < n; i++) {///sort score + // b = &(buf->b.a[i]); z = &(raw[pat[poa_str_idx(b->tn_rev_qk, pat_n, is_rev)]>>32]); + // pp = ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); + // b->tn_rev_qk += (pp<<32); + // } + + + i = integer_g_chain(g, ug, buf->b.a, buf->b.n, buf, &rr); assert(i); + if(!i) {return;} buf->b.n = rr.e; assert(buf->b.n); + append_aligned_integer_seq_by_aln_pair(ug, raw, g, g->seq.n, pat, pat_n, is_rev, buf->b.a, buf->b.n, str_id, (is_rev?(str->cn - e):(s))); + (*is_circle) = update_poa_dp(g, debug_qid, ug); +} + +void gen_cns_by_poa(poa_g_t *g) +{ + uint32_t n_vx = g->seq.n<<1, i, k, v, nv, w; uint64_t c, cc, n_pending = 0; + ubuf_t *b = &(g->bb); poa_arc_t *av; uinfo_t *t; + b->a.n = b->S.n = b->T.n = b->b.n = b->e.n = 0; + kv_resize(uinfo_t, b->a, n_vx); b->a.n = n_vx; memset(b->a.a, 0, sizeof(*(b->a.a))*b->a.n); + for (k = 0; k < g->seq.n; k++) { + v = (k<<1) + 1; + if(poa_arc_n(g, v)) continue; + v ^= 1; kv_push(uint32_t, b->S, v); b->a.a[v].p = (uint32_t)-1; + } + assert(b->S.n); + while (b->S.n > 0) { + v = kv_pop(b->S); c = b->a.a[v].c; + nv = poa_arc_n(g, v); av = poa_arc_a(g, v); + for (i = 0; i < nv; ++i) { + w = av[i].v; t = &b->a.a[w]; + kv_push(uint32_t, b->e, ((g->idx.a[v]>>32)+i)); ///push the edge + cc = c + (uint32_t)av[i].ul; + if (t->s == 0) {///a new node + kv_push(uint32_t, b->b, w); // save it for revert + t->p = v; t->s = 1; //t->d = d + l; + t->r = poa_arc_n(g, w^1); t->c = cc; ///t->nc = c_nc; + ++n_pending; + } else { + if(cc > t->c) { + t->p = v; t->c = cc; //t->s = 1; t->d = d + l; t->nc = c_nc; + } + } + + if (--(t->r) == 0) { + if(poa_arc_n(g, w) > 0) kv_push(uint32_t, b->S, w); + --n_pending; + // if(w == dest && n_pending == 0) goto pp_end; + } + } + } + assert(!n_pending); + uint64_t m = 0, mi = (uint64_t)-1; + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + t = &b->a.a[b->b.a[i]]; ///memset(t, 0, sizeof(*(t))); + //b->srt.a[i].c = ((uint64_t)-1) - t->c; b->srt.a[i].i = i; + if(m < t->c) { + m = t->c; mi = i; ///b->b.a[i]; + } + } + + if(mi != (uint64_t)-1) { + g->srt_b.res.n = 0; + for(v = b->b.a[mi]; v != (uint32_t)-1; v = b->a.a[v].p) { + kv_push(uint32_t, g->srt_b.res, v); + } + m = g->srt_b.res.n>>1; + for (i = 0; i < m; i++) { + v = g->srt_b.res.a[i]; + g->srt_b.res.a[i] = g->srt_b.res.a[g->srt_b.res.n-i-1]; + g->srt_b.res.a[g->srt_b.res.n-i-1] = v; + } + } + + // for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + // t = &b->a.a[b->b.a[i]]; memset(t, 0, sizeof(*(t))); + // } +} + +void poa_cns_chain(poa_g_t *g, all_ul_t *ul_idx, ma_ug_t *ug, ul_str_t *str, ul_chain_t *idx, int64_t idx_n, int64_t qid, integer_t *buf, uint32_t *is_circle) +{ + (*is_circle) = 0; + int64_t k, tid, is_rev; + reset_poa_g_t(g); + + append_unmatch_integer_seq(g, ug, ul_idx->a[qid].bb.a, &(str[qid]), 0, str[qid].cn, 0, qid); + clean_poa_g_t(g); (*is_circle) = 1 - topo_srt_gen(g, qid, ug); + if((*is_circle)) return; + + for (k = 0; k < idx_n; k++) { + tid = idx[k].v>>1; is_rev = idx[k].v&1; + // fprintf(stderr, "\n[M::%s::] k::%ld, tid::%ld, is_rev::%ld\n", __func__, k, tid, is_rev); + // print_integer_seq(ug, str, tid, 1); + poa_chain_0(g, ug, ul_idx->a[tid].bb.a, &(str[tid]), idx[k].t_sidx, idx[k].t_eidx, is_rev, buf, tid, qid, is_circle); + if((*is_circle)) return; + // print_integer_g(g, ug, 1); + } + + gen_cns_by_poa(g); +} + +uint64_t cal_forward_dis(asg_t *g, uc_block_t *a, uint32_t s, uint32_t e) +{ + uint32_t i, v, w, nv, z; int64_t l; asg_arc_t *av; + //fprintf(stderr, "\n[M::%s::] s::%u, e::%u\n", __func__, s, e); + ///TODO: a[i].aidx might be < i; if s == e, then i <= e might be wrong, cannot pass the assert(li == e); + for(i = s, l = 0, v = w = (uint32_t)-1; i != (uint32_t)-1 && i != e; i = a[i].aidx) { + w = (((uint32_t)(a[i].hid))<<1)|((uint32_t)(a[i].rev)); + if(v != (uint32_t)-1) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (z = 0; z < nv; z++) { + if(av[z].del) continue; + if(av[z].v == w) break; + } + if(z < nv) {//found + l += (uint32_t)av[z].ul; + } else { + l += a[i].pdis + g->seq[v>>1].len - g->seq[w>>1].len; + } + } + v = w; + // fprintf(stderr, "[M::%s::] i::%u, a[i].aidx::%u, a[i].qs::%u, a[i].qe::%u\n", __func__, i, a[i].aidx, a[i].qs, a[i].qe); + } + + + assert(i == e); + w = (((uint32_t)(a[i].hid))<<1)|((uint32_t)(a[i].rev)); + if(v != (uint32_t)-1) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (z = 0; z < nv; z++) { + if(av[z].del) continue; + if(av[z].v == w) break; + } + if(z < nv) {//found + l += (uint32_t)av[z].ul; + } else { + l += a[i].pdis + g->seq[v>>1].len - g->seq[w>>1].len; + } + } + v = w; + + + if(l < 0) l = 0; + return l; +} + +uint64_t cal_integer_match_dis(ma_ug_t *ug, uc_block_t *a, int64_t k_0, int64_t k_1, int64_t is_rev, uint32_t *is_g_connect) +{ + uint32_t i, k; + assert((is_rev && k_1 < k_0) || ((!is_rev) && k_1 > k_0)); (*is_g_connect) = 0; + if(is_rev) { + i = k_0; k = k_1; + } else { + i = k_1; k = k_0; + } + // fprintf(stderr, "k_0::%ld, k_1::%ld\n", k_0, k_1); + uint32_t li, lk, pk, bi = i; int64_t l; + for (li = i, l = 0; i != (uint32_t)-1 && i >= k; i = a[i].pidx) { + li = i; if(a[i].pidx != (uint32_t)-1 && i > k) l += a[i].pdis; + } + // fprintf(stderr, "+bi::%u, li::%u, i::%u, l::%ld\n", bi, li, i, l); + if(is_rev) l = cal_forward_dis(ug->g, a, li, bi); + // fprintf(stderr, "++bi::%u, li::%u, i::%u, l::%ld\n", bi, li, i, l); + if(li == k) {///direct path + (*is_g_connect) = 1; + return l; + } + i = li; + assert(i > k); pk = k; + for (lk = k; k != (uint32_t)-1 && k <= i; k = a[k].aidx) lk = k; + // fprintf(stderr, "-pk::%u, lk::%u, k::%u\n", pk, lk, k); + if(!is_rev) { + for (k = lk; k != (uint32_t)-1 && k != pk; k = a[k].pidx) l += a[k].pdis; + } else { + l += cal_forward_dis(ug->g, a, pk, lk); + } + // fprintf(stderr, "--pk::%u, lk::%u, k::%u, l::%ld\n", pk, lk, k, l); + if(l < 0) l = 0; + k = lk; + assert(i > k); + return l + normlize_gdis(ug, &(a[i]), &(a[k]), is_rev); +} + +uint64_t cal_integer_most_dis(uint32_t qid, uint64_t *a, uint64_t a_n, double cluster_rate) +{ + if(a_n <= 0) return (uint64_t)-1; + // fprintf(stderr, "\n[M::%s::] a_n::%lu\n", __func__, a_n); + uint64_t k, l, i, m, r_an = a_n, max_m, max_i, cc, cd, nd; int64_t z; + for (k = 1, l = m = max_m = 0, max_i = (uint64_t)-1; k <= a_n; k++) { + a[k-1] <<= 1; a[k-1] >>= 1; + // fprintf(stderr, "[k->%lu] d::%lu, rev::%lu\n", k-1, a[k-1]>>1, a[k-1]&1); + if((k == a_n) || (((a[k]&((uint64_t)(0x7fffffffffffffff)))>>1) + != ((a[l]&((uint64_t)(0x7fffffffffffffff)))>>1))) { + for (i = l; i < k; i++) { + if(!(a[i]&1)) break; + } + a[m] = a[l]; a[m] >>= 1; a[m] <<= 1; + ///if all integer sequence are mapped reversely + if(i >= k) a[m] += 1; + a[m] |= ((uint64_t)(k-l))<<32; + if((k-l) > max_m) { + max_m = k - l; max_i = m; + } else if((k-l) == max_m && i < k) {///i < k means this distance is supported by forward sequences + max_m = k - l; max_i = m; + } + l = k; m++; + } + } + a_n = m; assert(a_n > 0); + // fprintf(stderr, "[M::%s::] m::%lu\n", __func__, m); + if(max_m > 0 && max_m > (r_an>>1)) { + // fprintf(stderr, "[M::%s::] dis::%u\n", __func__, ((uint32_t)a[max_i])>>1); + return ((uint32_t)a[max_i])>>1; + } + + for (k = 0, max_m = 0, max_i = (uint64_t)-1; k < a_n; k++) { + cd = (((uint32_t)a[k])>>1); z = k; + // fprintf(stderr, "[mk->%lu] cd::%lu\n", k, cd); + for (cc = cd, z--; z >= 0; z--) { + nd = (((uint32_t)a[z])>>1); assert(nd < cd); + if(((cd-nd) > (nd*cluster_rate)) && ((cd-nd) > 512)) break; + cc += (a[z]>>32); + } + for (i = k+1; i < a_n; i++) { + nd = (((uint32_t)a[i])>>1); + // if(!(nd > cd)) { + // fprintf(stderr, "[M::%s::] qid::%u, a_n::%lu, i::%lu, k::%lu, cd::%lu, nd::%lu\n", + // __func__, qid, a_n, i, k, cd, nd); + // } + assert(nd > cd); + if(((nd-cd) > (nd*cluster_rate)) && ((nd-cd) > 512)) break; + cc += (a[i]>>32); + } + + if(cc > max_m) { + max_m = cc; max_i = k; + } else if(cc == max_m && (!(a[k]&1))) {///means this distance is supported by forward sequences + max_m = cc; max_i = k; + } + } + + k = max_i; + cd = (((uint32_t)a[k])>>1); z = k; + for (max_m = cd, max_i = k, z--; z >= 0; z--) { + nd = (((uint32_t)a[z])>>1); assert(nd < cd); + if(((cd-nd) > (nd*cluster_rate)) && ((cd-nd) > 512)) break; + cc = (a[z]>>32); + if(cc > max_m) { + max_m = cc; max_i = z; + } else if(cc == max_m && (!(a[z]&1))) {///means this distance is supported by forward sequences + max_m = cc; max_i = z; + } + } + for (i = k+1; i < a_n; i++) { + nd = (((uint32_t)a[i])>>1); assert(nd > cd); + if(((nd-cd) > (nd*cluster_rate)) && ((nd-cd) > 512)) break; + cc = (a[i]>>32); + if(cc > max_m) { + max_m = cc; max_i = i; + } else if(cc == max_m && (!(a[i]&1))) {///means this distance is supported by forward sequences + max_m = cc; max_i = i; + } + } + + // fprintf(stderr, "[M::%s::] dis::%u\n", __func__, ((uint32_t)a[max_i])>>1); + return ((uint32_t)a[max_i])>>1; +} + +uint32_t poa_g_arc_w(poa_g_t *pg, uint32_t v, uint32_t w) +{ + poa_arc_t *av; uint32_t an, k; + an = poa_arc_n(pg, v); av = poa_arc_a(pg, v); + for (k = 0; k < an; k++) { + if(av[k].v == w) return (uint32_t)av[k].ul; + } + return 0; +} + +void dump_cns_res(poa_g_t *pg, ma_ug_t *ug, uint32_t *cns_seq, uint32_t cns_occ, all_ul_t *ul_idx, ul_str_t *str, uint32_t qid, integer_t *buf, +uint64_t *arc_idx, uint64_t arc_idx_n) +{ + uint64_t t, dd, k, i; uint32_t e_s, e_e, is_rev, is_g_connect, con_occ; emap_t *g_arc; + if(cns_occ > 0) { + t = qid; t <<= 32; t |= ((uint64_t)(0xffffffff)); + kv_push(uint64_t, buf->res_dump, t); + + t = pg->seq.a[cns_seq[0]>>1].nid; + // t = pg->seq.a[cns_seq[0]>>1].nid; t |= ((uint64_t)(0xffffffff00000000)); + t |= ((uint64_t)(ug->g->seq[pg->seq.a[cns_seq[0]>>1].nid>>1].len))<<32; + kv_push(uint64_t, buf->res_dump, t); + buf->n_correct++; + } + for (k = 0; k < arc_idx_n; k++) { + // csn_v = pg->seq.a[cns_seq[k]>>1].nid; cns_w = pg->seq.a[cns_seq[k+1]>>1].nid; + e_s = arc_idx[k]>>32; e_e = (uint32_t)arc_idx[k]; + // fprintf(stderr, "[M::%s::] k::%lu, arc_idx_n::%lu, e_s::%u, e_e::%u\n", __func__, k, arc_idx_n, e_s, e_e); + assert(poa_g_arc_w(pg, cns_seq[k], cns_seq[k+1]) == (e_e - e_s)); assert(e_e > e_s); + buf->o.n = 0; kv_resize(uint64_t, buf->o, e_e - e_s); con_occ = 0; + for (i = e_s; i < e_e; i++) { + g_arc = &(pg->e_idx.a[i]); + assert((g_arc->pge>>32) == (cns_seq[k]>>1) && ((uint32_t)g_arc->pge) == (cns_seq[k+1]>>1)); + is_rev = ((g_arc->ule>>32) > ((uint32_t)g_arc->ule)?1:0); + assert((pg->seq.a[g_arc->pge>>32].nid^(is_rev?1:0)) == ((uint32_t)str[g_arc->ulid].a[g_arc->ule>>32])); + assert((pg->seq.a[(uint32_t)g_arc->pge].nid^(is_rev?1:0)) == ((uint32_t)str[g_arc->ulid].a[(uint32_t)g_arc->ule])); + // fprintf(stderr, "+++i::%lu, target_ulid::%u, str_sidx::%u, str_eidx::%u, str_cn::%u, ul_idx->a[g_arc->ulid].bb.n::%u\n", + // i - e_s, g_arc->ulid, (uint32_t)(g_arc->ule>>32), (uint32_t)g_arc->ule, str[g_arc->ulid].cn, (uint32_t)ul_idx->a[g_arc->ulid].bb.n); + dd = cal_integer_match_dis(ug, ul_idx->a[g_arc->ulid].bb.a, str[g_arc->ulid].a[g_arc->ule>>32]>>32, + str[g_arc->ulid].a[(uint32_t)g_arc->ule]>>32, is_rev, &is_g_connect); + // fprintf(stderr, "---i::%lu, dd::%lu, is_g_connect::%u\n", i - e_s, dd, is_g_connect); + dd <<= 1; if(is_rev) dd += 1; + if(is_g_connect) { + con_occ++; buf->o.a[buf->o.n] = dd; + } else { + buf->o.a[buf->o.n] = dd; buf->o.a[buf->o.n] |= ((uint64_t)(0x8000000000000000)); + } + buf->o.n++; + } + + radix_sort_srt64(buf->o.a, buf->o.a + buf->o.n); + if(con_occ > 0) buf->o.n = con_occ; + dd = cal_integer_most_dis(qid, buf->o.a, buf->o.n, 0.08); + + + t = pg->seq.a[cns_seq[k+1]>>1].nid; t |= ((uint64_t)(dd<<32)); + if(con_occ > 0) t |= ((uint64_t)(0x8000000000000000)); + kv_push(uint64_t, buf->res_dump, t); + } + +} + +void update_raw_integer_seq(poa_g_t *pg, ma_ug_t *ug, uint32_t *cns_seq, uint32_t cns_occ, all_ul_t *ul_idx, ul_str_t *str, uint32_t qid, integer_t *buf, ul_chain_t *idx_a, uint64_t idx_n) +{ + if(cns_occ <= 0) return; + ///no need to check edges if there is just one node -> no dege + if(cns_occ > 1) radix_sort_emap_t_srt(pg->e_idx.a, pg->e_idx.a + pg->e_idx.n); + kv_resize(uint64_t, buf->u, cns_occ); buf->u.n = cns_occ - 1; memset(buf->u.a, 0, sizeof(*(buf->u.a)*buf->u.n)); + uint64_t *arc_idx = buf->u.a, arc_idx_n = buf->u.n, x; uint64_t k, l, i, n = pg->e_idx.n, fe = cns_occ - 1; + for (k = 1, l = 0; k <= n && fe > 0; k++) { + if(k == n || pg->e_idx.a[k].pge != pg->e_idx.a[l].pge) { + if(k > l) { + for (i = 0; i < arc_idx_n; i++) { + x = (cns_seq[i]>>1); x <<= 32; x += (cns_seq[i+1]>>1); + if(x == pg->e_idx.a[l].pge) { + arc_idx[i] = l; arc_idx[i] <<= 32; arc_idx[i] += k; fe--; + break; + } + } + } + l = k; + } + } + assert(fe == 0); + // for (k = 0; k < pg->e_idx.n; k++) { + // assert((pg->seq.a[pg->e_idx.a[k].pge>>32].nid>>1) == + // (((uint32_t)str[pg->e_idx.a[k].ulid].a[pg->e_idx.a[k].ule>>32])>>1)); + // assert((pg->seq.a[(uint32_t)pg->e_idx.a[k].pge].nid>>1) == + // (((uint32_t)str[pg->e_idx.a[k].ulid].a[(uint32_t)pg->e_idx.a[k].ule])>>1)); + // assert(((pg->seq.a[pg->e_idx.a[k].pge>>32].nid&1)^(((uint32_t)str[pg->e_idx.a[k].ulid].a[pg->e_idx.a[k].ule>>32])&1)) == + // ((pg->seq.a[(uint32_t)pg->e_idx.a[k].pge].nid&1)^(((uint32_t)str[pg->e_idx.a[k].ulid].a[(uint32_t)pg->e_idx.a[k].ule])&1))); + // } + + uint32_t e_s, e_e; emap_t *g_arc; uint64_t l_clip = 0, r_clip = 0; int64_t e_occ; + if(arc_idx_n > 0) { + ///clip unreliable left/right end + for (l_clip = 0; l_clip < arc_idx_n; l_clip++) { + k = l_clip; + e_s = arc_idx[k]>>32; e_e = (uint32_t)arc_idx[k]; + assert(poa_g_arc_w(pg, cns_seq[k], cns_seq[k+1]) == (e_e - e_s)); + e_occ = ((int64_t)e_e) - ((int64_t)e_s); + if(e_occ > 1) break;///more than one read supporting this edge + for (i = e_s; i < e_e; i++) { + g_arc = &(pg->e_idx.a[i]); + if(g_arc->ulid == qid) break; + } + if(i < e_e) break;///the query read itself supports this edge + } + + for (r_clip = 0; r_clip < arc_idx_n; r_clip++) { + k = arc_idx_n - r_clip - 1; + e_s = arc_idx[k]>>32; e_e = (uint32_t)arc_idx[k]; + assert(poa_g_arc_w(pg, cns_seq[k], cns_seq[k+1]) == (e_e - e_s)); + e_occ = ((int64_t)e_e) - ((int64_t)e_s); + if(e_occ > 1) break;///more than one read supporting this edge + for (i = e_s; i < e_e; i++) { + g_arc = &(pg->e_idx.a[i]); + if(g_arc->ulid == qid) break; + } + if(i < e_e) break;///the query read itself supports this edge + } + } + if(l_clip+r_clip >= cns_occ) return; + dump_cns_res(pg, ug, cns_seq+l_clip, cns_occ-l_clip-r_clip, ul_idx, str, qid, buf, arc_idx+l_clip, arc_idx_n-l_clip-r_clip); +} + +void integer_candidate(ul_resolve_t *uidx, integer_t *buf, uint32_t qid, uint32_t is_hom) +{ + uint64_t k, z, m_het, m_het_occ, ref_occ, b_n, m; uint32_t vk, vz, is_circle = 0; integer_aln_t *p; ul_chain_t sc; + ul_str_idx_t *str_idx = &(uidx->pstr); ma_ug_t *ug = uidx->l1_ug; + uint64_t *hid_a, hid_n; uc_block_t *xi; + ul_str_t *str = &(str_idx->str.a[qid]); + if(str->cn < 2) return; ///directly filter out too short UL + kv_resize(uint64_t, buf->u, str->cn); buf->u.n = str->cn; + for (k = m_het = m_het_occ = ref_occ = 0; k < str->cn; k++) { + xi = &(uidx->idx->a[qid].bb.a[str->a[k]>>32]); + assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[k])); + buf->u.a[k] = ug_occ_w(xi->ts, xi->te, &(ug->u.a[xi->hid])); + assert(buf->u.a[k] > 0); + if((!is_hom) && (!IF_HOM((((uint32_t)str->a[k])>>1), (*uidx->bub)))) { + m_het++; m_het_occ += buf->u.a[k];///m_het_occ: how many het HiFi reads + } + ref_occ += buf->u.a[k]; + // fprintf(stderr, "[M::%s::k->%lu] buf->u.a[k]->%lu, ts->%u, te->%u, pchain->%u\n", __func__, k, buf->u.a[k], xi->ts, xi->te, xi->pchain); + } + // if((!is_hom) && (m_het < 2) && (m_het > 0)) return;///if all matched unitigs are hom, is ok + if(m_het == 0 || m_het_occ == 0) is_hom = 1; + // print_ul_alignment(ug, &UL_INF, 27512, "inner-0"); + for (k = 0, buf->b.n = 0; k < str->cn; k++) { + vk = (uint32_t)str->a[k]; + hid_a = str_idx->occ.a + str_idx->idx.a[vk>>1]; + hid_n = str_idx->idx.a[(vk>>1)+1] - str_idx->idx.a[vk>>1]; + for (z = 0; z < hid_n; z++) { + if((hid_a[z]>>32) == qid) continue; + if(str_idx->str.a[hid_a[z]>>32].cn < 2) continue; + vz = (uint32_t)(str_idx->str.a[hid_a[z]>>32].a[(uint32_t)hid_a[z]]); + assert((vk>>1) == (vz>>1)); + kv_pushp(integer_aln_t, buf->b, &p); + p->vq = vk; p->tk = (uint32_t)hid_a[z]; + if((vk^vz)&1) p->tk = str_idx->str.a[hid_a[z]>>32].cn - p->tk - 1;///rev + p->tn_rev_qk = (hid_a[z]>>32); p->tn_rev_qk <<= 1; p->tn_rev_qk |= ((vk^vz)&1); + p->tn_rev_qk <<= 32; p->tn_rev_qk += k; + ///set score of this pair + p->sc = buf->u.a[k]; + xi = &(uidx->idx->a[hid_a[z]>>32].bb.a[(str_idx->str.a[hid_a[z]>>32].a[(uint32_t)hid_a[z]])>>32]); + assert(((xi->hid<<1)+xi->rev)==vz); m = ug_occ_w(xi->ts, xi->te, &(ug->u.a[xi->hid])); + if(p->sc > m) p->sc = m; + } + } + // print_ul_alignment(ug, &UL_INF, 27512, "inner-1"); + radix_sort_integer_aln_t_srt(buf->b.a, buf->b.a + buf->b.n); + b_n = buf->b.n; buf->sc.n = 0; + for (k = 1, z = 0; k <= b_n; k++) { + if(k == b_n || (buf->b.a[z].tn_rev_qk>>32) != (buf->b.a[k].tn_rev_qk>>32)) { + ///get the chain for + if(integer_chain(qid, buf->b.a + z, k - z, z, buf, ug, str_idx, uidx->idx, &sc) && sc.v != (uint32_t)-1) { + if((buf->sc.n > 0) && ((buf->sc.a[buf->sc.n-1].v>>1) == (sc.v>>1))) { + if(buf->sc.a[buf->sc.n-1].sc < sc.sc) { + buf->sc.a[buf->sc.n-1] = sc; + } + } else { + kv_push(ul_chain_t, buf->sc, sc); + } + } + z = k; + } + } + // print_ul_alignment(ug, &UL_INF, 27512, "inner-2"); + uint64_t *o, o_n, cns_het, cns_het_occ, ref_cns_occ, corrected = 0; + o_n = integer_chain_dp(uidx->bub, buf, str_idx->str.a, buf->b.a, buf->sc.a, buf->sc.n, qid, is_hom, 2, &corrected); + assert(o_n <= str->cn); + // if(qid == 2062 || qid == 2093) fprintf(stderr,"[M::%s::] o_n::%lu, str->cn::%u, corrected::%lu\n", __func__, o_n, str->cn, corrected); + if(o_n <= 0) return; + if(corrected) return; + // print_ul_alignment(ug, &UL_INF, 27512, "inner-3"); + + for (k = cns_het = cns_het_occ = ref_cns_occ = 0, o = buf->o.a; k < o_n; k++) { + if((!is_hom) && (!IF_HOM((((uint32_t)str->a[o[k]])>>1), (*uidx->bub)))) { + cns_het++; cns_het_occ += buf->u.a[o[k]]; + } + ref_cns_occ += buf->u.a[o[k]]; + } + buf->o.n = o_n; + ///1. if the ref read only has hom unitigs, is fine + ///2. otherwise need to have consenus het untigs + if(!is_hom) { + if((cns_het <= 0) || (cns_het_occ <= 0) || (cns_het_occ <= (m_het_occ*0.25))) return; + } else { + if(ref_cns_occ <= (ref_occ*0.25)) return; + } + // print_ul_alignment(ug, &UL_INF, 27512, "inner-4"); + // fprintf(stderr, "\n"); + // print_integer_seq(ug, str_idx->str.a, qid, 1); + // print_aln_seq(ug, uidx->idx, qid, 1); + // if(qid == 2062 || qid == 2093) print_cns_seq(ug, str, o, o_n); + // print_ul_alignment(ug, &UL_INF, 27512, "inner-5"); + + for (k = m = 0; k < buf->sc.n; k++) { + // fprintf(stderr, "[M::%s::k->%lu] m::%lu\n", __func__, k, m); + // if(k == 72) { + // print_integer_ovlps(ug, str_idx->str.a, buf->b.a, buf->b.n, buf->sc.a+k, 1, qid, o_n); + // } + if(refine_integer_ovlps(uidx->idx, uidx->bub, ug, str_idx->str.a, buf->b.a, + &(buf->sc.a[k]), qid, buf, o, o_n)) { + buf->sc.a[m++] = buf->sc.a[k]; + } + // else { + // print_integer_ovlps(ug, str_idx->str.a, buf->b.a, buf->b.n, buf->sc.a+k, 1, qid, o_n); + // fprintf(stderr, "[M::%s::] idx->q_sidx::%u, idx->q_eidx::%u, idx->t_sidx::%u, idx->t_eidx::%u\n******************************************************\n", + // __func__, buf->sc.a[k].q_sidx, buf->sc.a[k].q_eidx, buf->sc.a[k].t_sidx, buf->sc.a[k].t_eidx); + // } + } + buf->sc.n = m; + if(m <= 0) return; + // print_ul_alignment(ug, &UL_INF, 27512, "inner-6"); + // if(m != str->cn) print_integer_ovlps(uidx->l1_ug, str_idx->str.a, buf->b.a, buf->b.n, buf->sc.a, buf->sc.n, qid, m); + poa_cns_chain(&(buf->pg), uidx->idx, ug, str_idx->str.a, buf->sc.a, buf->sc.n, qid, buf, &is_circle); + if(is_circle) { + buf->n_circle++; + return; + } + // print_ul_alignment(ug, &UL_INF, 27512, "inner-7"); + // print_res_seq(&(buf->pg), ug, buf->pg.srt_b.res.a, buf->pg.srt_b.res.n); + // radix_sort_ul_chain_t_srt(buf->sc.a, buf->sc.a + buf->sc.n); + + // integer_phase(str_idx->str.a, buf, buf->sc.a, buf->sc.n, buf->b.a, qid); + + // radix_sort_ul_chain_t_srt(buf->sc.a, buf->sc.a + buf->sc.n); + o = NULL; o_n = 0; + update_raw_integer_seq(&(buf->pg), ug, buf->pg.srt_b.res.a, buf->pg.srt_b.res.n, uidx->idx, str_idx->str.a, qid, buf, buf->sc.a, buf->sc.n); +} + +ul2ul_item_t *get_ul_ovlp(ul2ul_idx_t *z, uint64_t id, uint64_t is_ul) +{ + uint64_t x = (is_ul?(id):(id+z->uln)); + if(z->item_idx[x] == (uint32_t)-1) return NULL; + return &(z->a[z->item_idx[x]]); +} + +ul2ul_t *get_ul_o(ul2ul_idx_t *idx, uint32_t qid, uint32_t is_q_ul, uint32_t tid, uint32_t is_t_ul) +{ + ul2ul_item_t *z = get_ul_ovlp(idx, qid, is_q_ul); uint64_t k; + if(!is_t_ul) tid += idx->uln; + for (k = 0; k < z->n; k++) { + if(z->a[k].hid == tid) return &(z->a[k]); + } + return NULL; +} + +void integer_gen_ovlp(ul_resolve_t *uidx, integer_t *buf, uint32_t qid, ul2ul_item_t *o, uint32_t ug_offset) +{ + ul_str_idx_t *str_idx = &(uidx->pstr); ma_ug_t *ug = uidx->l1_ug; ul2ul_t res; + ul_str_t *str = &(str_idx->str.a[qid]); integer_aln_t *p; ul_chain_t sc; + uint64_t k, z, *hid_a, hid_n, sck, b_n, m/**, ovn = 0**/; uint32_t vk, vz; uc_block_t *xi; + o->n = o->cn = 0; o->id = qid; o->is_del = 0; ///o->is_consist = 0; + // if(qid == 95 || qid == 36) print_integer_seq(ug, str_idx->str.a, qid, 1); + if(str->cn < 2) return; + for (k = 0, buf->b.n = 0; k < str->cn; k++) { + xi = &(uidx->idx->a[qid].bb.a[str->a[k]>>32]); + assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[k])); + sck = ug_occ_w(xi->ts, xi->te, &(ug->u.a[xi->hid])); + + vk = (uint32_t)str->a[k]; + hid_a = str_idx->occ.a + str_idx->idx.a[vk>>1]; + hid_n = str_idx->idx.a[(vk>>1)+1] - str_idx->idx.a[vk>>1]; + for (z = 0; z < hid_n; z++) { + // if(qid == 95 || qid == 36) { + // fprintf(stderr,"[M::%s::qid->%u::tid->%lu] k->%lu, tid_occ->%u\n", + // __func__, qid, (hid_a[z]>>32), k, str_idx->str.a[hid_a[z]>>32].cn); + // } + if((hid_a[z]>>32) == qid) continue; + if(str_idx->str.a[hid_a[z]>>32].cn < 2) continue; + vz = (uint32_t)(str_idx->str.a[hid_a[z]>>32].a[(uint32_t)hid_a[z]]); + assert((vk>>1) == (vz>>1)); + kv_pushp(integer_aln_t, buf->b, &p); + p->vq = vk; p->tk = (uint32_t)hid_a[z]; + if((vk^vz)&1) p->tk = str_idx->str.a[hid_a[z]>>32].cn - p->tk - 1;///rev + p->tn_rev_qk = (hid_a[z]>>32); p->tn_rev_qk <<= 1; p->tn_rev_qk |= ((vk^vz)&1); + p->tn_rev_qk <<= 32; p->tn_rev_qk += k; + ///set score of this pair + p->sc = sck; + xi = &(uidx->idx->a[hid_a[z]>>32].bb.a[(str_idx->str.a[hid_a[z]>>32].a[(uint32_t)hid_a[z]])>>32]); + assert(((xi->hid<<1)+xi->rev)==vz); m = ug_occ_w(xi->ts, xi->te, &(ug->u.a[xi->hid])); + if(p->sc > m) p->sc = m; + } + } + + radix_sort_integer_aln_t_srt(buf->b.a, buf->b.a + buf->b.n); + + // b_n = buf->b.n; + // for (k = 1, z = ovn = 0; k <= b_n; k++) { + // if(k == b_n || (buf->b.a[z].tn_rev_qk>>33) != (buf->b.a[k].tn_rev_qk>>33)) { + // ovn++; z = k; + // } + // } + + b_n = buf->b.n; buf->sc.n = 0; + for (k = 1, z = 0; k <= b_n; k++) { + if(k == b_n || (buf->b.a[z].tn_rev_qk>>32) != (buf->b.a[k].tn_rev_qk>>32)) { + // if(qid == 95 || qid == 36) { + // fprintf(stderr,"[M::%s::qid->%u::tid->%lu]\n", __func__, qid, buf->b.a[z].tn_rev_qk>>33); + // } + if(integer_chain(qid, buf->b.a + z, k - z, z, buf, ug, str_idx, uidx->idx, &sc) && sc.v != (uint32_t)-1) { + if((buf->sc.n > 0) && ((buf->sc.a[buf->sc.n-1].v>>1) == (sc.v>>1))) { + if(buf->sc.a[buf->sc.n-1].sc < sc.sc) { + buf->sc.a[buf->sc.n-1] = sc; + } + } else { + kv_push(ul_chain_t, buf->sc, sc); + } + } + z = k; + } + } + + for (k = o->n = 0; k < buf->sc.n; k++) { + if(update_exact_ul_ovlps(uidx->idx, ug, str_idx->str.a, buf->b.a, &(buf->sc.a[k]), qid, buf, &res)) { + kv_push(ul2ul_t, *o, res); + } + } + // if(str->cn > 0) { + // for (k = 0, buf->b.n = 0; k < str->cn; k++) { + // xi = &(uidx->idx->a[qid].bb.a[str->a[k]>>32]); + + // // if(xi->ts) + // } + // // uint32_t v, nv; asg_arc_t *av; asg_t *g = ug->g; ul2ul_t *r; + // // v = ((uint32_t)str->a[0])^1; + // // nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + // // for (k = 0; k < nv; k++) { + // // if(av[k].del) continue; + // // kv_pushp(ul2ul_t, *o, &r); + // // r->hid = (av[k].v>>1) + ug_offset; + // // r->is_rev = (av[k].v^v)&1; + // // r->qs = 0; r->qe = av[k].ol; + + // // } + // // v = ((uint32_t)str->a[str->cn-1]); + // // nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + // } + o->cn = o->n; + // if(ovn == o->cn) o->is_consist = 1; + if(o->n <= 0) return; +} + +#define ulg_id(ul2, i) (((i)>=(ul2).uln)?((i)-(ul2).uln):(i)) +#define ulg_type(ul2, i) (((i)>=(ul2).uln)?(0):(1)) +#define ulg_len(uidx, i) (ulg_type((uidx).uovl,(i))?((uidx).idx->a[ulg_id((uidx).uovl,(i))].rlen):((uidx).l1_ug->u.a[ulg_id((uidx).uovl,(i))].len)) +#define ulg_occ(uidx, i) (ulg_type((uidx).uovl,(i))?((uidx).pstr.str.a[ulg_id((uidx).uovl,(i))].cn):(1)) + +void integer_normalize_ovlp(ul_resolve_t *uidx, uint32_t qid, ul2ul_item_t *o, ul2ul_idx_t *ul2) +{ + ul2ul_t *z; uint64_t k; ul2ul_item_t *t; + for (k = 0; k < o->n; k++) { + assert(ul2->item_idx[o->a[k].hid] != (uint32_t)-1); + z = get_ul_o(ul2, ulg_id(*ul2, o->a[k].hid), ulg_type(*ul2, o->a[k].hid), + ulg_id(*ul2, qid), ulg_type(*ul2, qid)); + // assert(z && z->hid == qid); + // if(o->a[k].is_rev == z->is_rev && (*z).qs == o->a[k].ts && (*z).qe == o->a[k].te && + // (*z).ts == o->a[k].qs && (*z).te == o->a[k].qe) { + // fprintf(stderr, "good::[M::%s] fn::%u(%c), fqs::%u, fqe::%u, fts::%u, fte::%u, rn::%u(%c), rqs::%u, rqe::%u, rts::%u, rte::%u\n", __func__, + // o->a[k].hid, "+-"[o->a[k].is_rev], o->a[k].qs, o->a[k].qe, o->a[k].ts, o->a[k].te, + // z->hid, "+-"[z->is_rev], z->qs, z->qe, z->ts, z->te); + // } else { + // fprintf(stderr, "bad::[M::%s] fn::%u(%c), fqs::%u, fqe::%u, fts::%u, fte::%u, rn::%u(%c), rqs::%u, rqe::%u, rts::%u, rte::%u\n", __func__, + // o->a[k].hid, "+-"[o->a[k].is_rev], o->a[k].qs, o->a[k].qe, o->a[k].ts, o->a[k].te, + // z->hid, "+-"[z->is_rev], z->qs, z->qe, z->ts, z->te); + // } + // continue; + if(z && o->a[k].hid < qid) continue; + if(!z) { + t = get_ul_ovlp(ul2, ulg_id(*ul2, o->a[k].hid), ulg_type(*ul2, o->a[k].hid)); + assert(t); + kv_pushp(ul2ul_t, *t, &z); + (*z).hid = qid; + (*z).qs = o->a[k].ts; (*z).qe = o->a[k].te; + (*z).ts = o->a[k].qs; (*z).te = o->a[k].qe; + (*z).qs_k = o->a[k].ts_k; (*z).qe_k = o->a[k].te_k; + (*z).ts_k = o->a[k].qs_k; (*z).te_k = o->a[k].qe_k; + (*z).is_rev = o->a[k].is_rev; (*z).is_del = o->a[k].is_del; + (*z).is_ct = o->a[k].is_ct; + if(!((*z).is_del)) { + t->cn++; + } + } else { + if((o->a[k].qe - o->a[k].qs) >= (z->te - z->ts)) { + (*z).qs = o->a[k].ts; (*z).qe = o->a[k].te; + (*z).ts = o->a[k].qs; (*z).te = o->a[k].qe; + (*z).qs_k = o->a[k].ts_k; (*z).qe_k = o->a[k].te_k; + (*z).ts_k = o->a[k].qs_k; (*z).te_k = o->a[k].qe_k; + (*z).is_rev = o->a[k].is_rev; (*z).is_del = o->a[k].is_del; + (*z).is_ct = o->a[k].is_ct; + } else { + o->a[k].qs = (*z).ts; o->a[k].qe = (*z).te; + o->a[k].ts = (*z).qs; o->a[k].te = (*z).qe; + o->a[k].qs_k = (*z).ts_k; o->a[k].qe_k = (*z).te_k; + o->a[k].ts_k = (*z).qs_k; o->a[k].te_k = (*z).qe_k; + o->a[k].is_rev = (*z).is_rev; o->a[k].is_del = (*z).is_del; + o->a[k].is_ct = (*z).is_ct; + } + } + } +} + + +void integer_normalize_ovlp_purge(ul_resolve_t *uidx, uint32_t qid, ul2ul_item_t *o, ul2ul_idx_t *ul2) +{ + if(o->is_del) return; + ul2ul_t *z; uint64_t k, is_del; + for (k = is_del = 0; k < o->n; k++) { + if(o->a[k].is_del) continue; + z = get_ul_o(ul2, o->a[k].hid, 1, qid, 1); + if((!z) || (z->is_del)) { + o->a[k].is_del = 1; is_del++; + } + } + + if(is_del) { + for (k = o->cn = 0; k < o->n; k++) { + if(o->a[k].is_del) o->a[k].hid |= ((uint32_t)(0x80000000)); + else o->cn++; + } + + radix_sort_ul2ul_srt(o->a, o->a + o->n); + + for (k = 0; k < o->n; k++) { + if(o->a[k].hid&((uint32_t)(0x80000000))) { + o->a[k].hid -= ((uint32_t)(0x80000000)); + } + } + } + + if(o->cn == 0) o->is_del = 1; +} + +static inline int64_t integer_hit2arc_idx_contain(const ul2ul_t *z, int64_t qn, int64_t tn, uint64_t *dir) +{ + int64_t tn5, tn3, extn5, extn3, qsn = z->qs_k, qen = qn - ((int64_t)z->qe_k); + if (z->is_rev) tn5 = tn - z->te_k, tn3 = z->ts_k; + else tn5 = z->ts_k, tn3 = tn - z->te_k; + (*dir) = (uint64_t)-1; + + extn5 = ((qsn 0 || extn3 > 0) return MA_HT_INT;///overhang + if (qsn < tn5 && qen < tn3) { // query contained in target + return MA_HT_QCONT; + } else if (qsn > tn5 && qen > tn3) { // target contained in query + return MA_HT_TCONT; + } else if(qsn == tn5 && qen == tn3) { + (*dir) = (uint64_t)-1; + } else if (qsn > tn5) { ///query-to-target overlap + (*dir) = 0; + } else if(qsn < tn5) { ///target-to-query overlaps + (*dir) = 1; + } else if(qen > tn3) { ///target-to-query overlaps + (*dir) = 1; + } else if(qen < tn3) { ///query-to-target overlap + (*dir) = 0; + } + return MA_HT_DOUBLE; +} + +static inline int integer_hit2arc(const ul2ul_t *z, int64_t ql, int64_t tl, int64_t qocc, int64_t tocc, uint64_t qid, uint64_t tid, +int64_t min_ovlp, asg_arc_t *p) +{ + int64_t tl5, tl3, ext5, ext3, qs = z->qs, rf; + uint64_t u, v, l, rr; // u: query end; v: target end; l: length from u to v + + ///if query and target are in different strand + if (z->is_rev) tl5 = tl - z->te, tl3 = z->ts; // tl5: 5'-end overhang (on the query strand); tl3: similar + else tl5 = z->ts, tl3 = tl - z->te; + + ///ext5 and ext3 is the hang on left side and right side, respectively + ext5 = qs < tl5? qs : tl5; + ext3 = (((ql - ((int64_t)z->qe)) < tl3)? (ql - ((int64_t)z->qe)) : tl3); + + if(ext5 > 0 || ext3 > 0) return MA_HT_INT;///overhang + if (qs <= tl5 && (ql - (int64_t)z->qe) <= tl3) { // query contained in target + return MA_HT_QCONT; + } else if (qs >= tl5 && (ql - (int64_t)z->qe) >= tl3) { // target contained in query + return MA_HT_TCONT; + } else if (qs > tl5) { ///u = 0 means query-to-target overlap, l is the length of node in string graph (not the overlap length) + u = 0, v = !!(z->is_rev), l = qs - tl5; + } else { ///u = 1 means target-to-query overlaps, l is the length of node in string graph (not the overlap length) + u = 1, v = !(z->is_rev), l = (ql - z->qe) - tl3; + } + if ((int64_t)z->qe - qs + ext5 + ext3 < min_ovlp || (int64_t)z->te - (int64_t)z->ts + ext5 + ext3 < min_ovlp) { + return MA_HT_SHORT_OVLP; // short overlap + } + rf = integer_hit2arc_idx_contain(z, qocc, tocc, &rr); + if(rf != MA_HT_DOUBLE) return rf; + if(rr != (uint64_t)-1 && rr != u) { + // fprintf(stderr, "[M::%s::] z->is_rev::%u, z->qs::%u, z->qe::%u, z->ts::%u, z->te::%u, z->qs_k::%u, z->qe_k::%u, z->ts_k::%u, z->te_k::%u, ql::%ld, tl::%ld, qocc::%ld, tocc::%ld\n", __func__, + // z->is_rev, z->qs, z->qe, z->ts, z->te, z->qs_k, z->qe_k, z->ts_k, z->te_k, ql, tl, qocc, tocc); + return MA_HT_INT;///overhang + } + ///u = 0 / 1 means query-to-target / target-to-query overlaps, + ///l is the length of node in string graph (not the overlap length between two reads) + u |= qid<<1, v |= tid<<1; + /** + p->ul: |____________31__________|__________1___________|______________32_____________| + qn direction of overlap length of this node (not overlap length) + (in the view of query) + p->v : |___________31___________|__________1___________| + tn reverse direction of overlap + (in the view of target) + p->ol: overlap length + **/ + if(p) { + p->ul = (uint64_t)u<<32 | l, p->v = v, p->ol = ql - l, p->del = 0; + ///l is the length of node in string graph (not the overlap length) + + p->strong = 1; p->el = 1; p->no_l_indel = 1; + } + return l; +} + + +void integer_append_ug_ovlp(ul_resolve_t *uidx, uint32_t qid, ul2ul_item_t *o, ul2ul_idx_t *ul2) +{ + // if(o->is_del) return; + uint64_t k; uc_block_t *xi; ul2ul_t *z; ul2ul_item_t *t; int32_t r; + ma_ug_t *ug = uidx->l1_ug; ul_str_t *str = &(uidx->pstr.str.a[qid]); + for (k = 0; k < str->cn; k++) { + xi = &(uidx->idx->a[qid].bb.a[str->a[k]>>32]); + assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[k])); + + ///ul side + kv_pushp(ul2ul_t, *o, &z); + z->hid = xi->hid + ul2->uln; z->is_rev = xi->rev; z->is_del = o->is_del; z->is_ct = 0; + z->qs = xi->qs; z->qe = xi->qe; z->ts = xi->ts; z->te = xi->te; + z->qs_k = k; z->qe_k = k + 1; z->ts_k = 0; z->te_k = 1; + + r = integer_hit2arc(z, uidx->idx->a[qid].rlen, ug->u.a[xi->hid].len, uidx->pstr.str.a[qid].cn, + 1, qid, z->hid, 0, NULL); + if(r == MA_HT_INT) { + o->n--; continue; + } + ///ug side + t = get_ul_ovlp(ul2, xi->hid, 0); + assert(t); + kv_pushp(ul2ul_t, *t, &z); + z->hid = qid; z->is_rev = xi->rev; z->is_del = o->is_del; z->is_ct = 0; + z->qs = xi->ts; z->qe = xi->te; z->ts = xi->qs; z->te = xi->qe; + z->qs_k = 0; z->qe_k = 1; z->ts_k = k; z->te_k = k + 1; + } +} + +void integer_node_del(ul2ul_idx_t *ul2, uint64_t id, uint64_t is_ct) +{ + ul2ul_item_t *o = get_ul_ovlp(ul2, ulg_id(*ul2, id), ulg_type(*ul2, id)); + if(o) { + uint64_t k; ul2ul_t *z; + for (k = 0; k < o->cn; k++) { + if(is_ct) o->a[k].is_ct = 1; + else o->a[k].is_del = 1; + z = get_ul_o(ul2, ulg_id(*ul2, o->a[k].hid), ulg_type(*ul2, o->a[k].hid), ulg_id(*ul2, id), ulg_type(*ul2, id)); + if(is_ct) z->is_ct = 1; + else z->is_del = 1; + } + o->is_del = 1; + } +} + +void integer_containment_purge(ul_resolve_t *uidx, uint32_t qid, ul2ul_item_t *q, ul2ul_idx_t *ul2, uint32_t keep_raw_utg) +{ + if(q->is_del) return; + uint64_t k; int32_t r; ul2ul_item_t *t; ul2ul_t *z; assert(qid == q->id); + for (k = 0; k < q->cn; k++) { + if(q->a[k].is_del || q->a[k].is_ct) continue; + t = get_ul_ovlp(ul2, ulg_id(*ul2, q->a[k].hid), ulg_type(*ul2, q->a[k].hid)); + assert(t); + if(t->is_del) continue; + r = integer_hit2arc(&(q->a[k]), ulg_len(*uidx, qid), ulg_len(*uidx, q->a[k].hid), + ulg_occ(*uidx, qid), ulg_occ(*uidx, q->a[k].hid), qid, q->a[k].hid, 0, NULL); + // assert(r != MA_HT_INT); + if (r == MA_HT_QCONT) { + q->a[k].is_ct = 1; + z = get_ul_o(ul2, ulg_id(*ul2, q->a[k].hid), ulg_type(*ul2, q->a[k].hid), ulg_id(*ul2, qid), ulg_type(*ul2, qid)); + assert(z && (!z->is_del) && (!z->is_ct)); z->is_ct = 1; + if((!keep_raw_utg) || ulg_type(*ul2, qid)) integer_node_del(ul2, qid, 1); + } else if (r == MA_HT_TCONT) { + q->a[k].is_ct = 1; + z = get_ul_o(ul2, ulg_id(*ul2, q->a[k].hid), ulg_type(*ul2, q->a[k].hid), ulg_id(*ul2, qid), ulg_type(*ul2, qid)); + assert(z && (!z->is_del) && (!z->is_ct)); z->is_ct = 1; + if((!keep_raw_utg) || ulg_type(*ul2, q->a[k].hid)) integer_node_del(ul2, q->a[k].hid, 1); + } + } + + // if(ulg_type(*ul2, k)) { + // for (k = 0; k < q->cn; k++) { + // if((!(q->a[k].is_del)) && (!(q->a[k].is_ct))) break; + // } + // if(k >= q->cn) q->is_del = 1; + // } +} + + +static void worker_integer_correction(void *data, long i, int tid) // callback for kt_for() +{ + ul_resolve_t *uidx = (ul_resolve_t *)data; + integer_ml_t *sl = &(uidx->str_b); + integer_t *buf = &(sl->buf[tid]); + // uc_block_t *uls; uint64_t uls_n; uint32_t v; + // uint64_t *srt_a, srt_n, is_circle = ((uidx->psrt.idx.a[i]&((uint64_t)(0x100000000)))?1:0); + // srt_a = uidx->psrt.srt.a + (uint32_t)uidx->psrt.idx.a[i]; srt_n = uidx->psrt.idx.a[i]>>33; + // if(srt_n == 0) return; + // integer_candidate(uidx, srt_a, srt_n, is_circle, buf); + integer_candidate(uidx, buf, i, (asm_opt.purge_level_primary == 0?1:0)); +} + +static void worker_integer_postprecess(void *data, long i, int tid) // callback for kt_for() +{ + ul_resolve_t *uidx = (ul_resolve_t *)data; + integer_ml_t *sl = &(uidx->str_b); + integer_t *buf = &(sl->buf[tid]); + ul2ul_item_t *it = get_ul_ovlp(&(uidx->uovl), i, 1); + if(!it) return; + assert(uidx->pstr.str.a[i].cn > 1); + // uc_block_t *uls; uint64_t uls_n; uint32_t v; + // uint64_t *srt_a, srt_n, is_circle = ((uidx->psrt.idx.a[i]&((uint64_t)(0x100000000)))?1:0); + // srt_a = uidx->psrt.srt.a + (uint32_t)uidx->psrt.idx.a[i]; srt_n = uidx->psrt.idx.a[i]>>33; + // if(srt_n == 0) return; + // integer_candidate(uidx, srt_a, srt_n, is_circle, buf); + integer_gen_ovlp(uidx, buf, i, it, uidx->uovl.uln); +} + + +void gen_integer_normalize(ul_resolve_t *uidx) +{ + uint64_t k; ul2ul_idx_t *u2o = &(uidx->uovl); ul2ul_item_t *it; + for (k = 0; k < u2o->uln; k++) { + it = get_ul_ovlp(u2o, k, 1); + if(!it) continue; + assert(uidx->pstr.str.a[k].cn > 1); + if(it->is_del) continue; + integer_normalize_ovlp(uidx, k, it, u2o); + } +} + +uint64_t dd_path_connect(asg_t *g, ul_str_t *str) +{ + if(str->cn < 2) return 1;///actually should return 1, doesn't matter + uint64_t i, v, w, nv, k; asg_arc_t *av; + v = ((uint32_t)str->a[0]); + for (i = 1; i < str->cn; i++) { + w = ((uint32_t)str->a[i]); + + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == w) break; + } + if(k >= nv) return 0; + + nv = asg_arc_n(g, w^1); av = asg_arc_a(g, w^1); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == (v^1)) break; + } + if(k >= nv) return 0; + + v = w; + } + return 1; +} + +void clip_integer_chimeric(ul_resolve_t *uidx, uint32_t qid, ul2ul_item_t *o, ul2ul_idx_t *ul2, integer_t *buf, int64_t min_dp) +{ + uint64_t k, is_srt = 0, is_del = 0/**, rid, zs, ze**/; assert(o->id == qid); + ul_str_t *str = &(uidx->pstr.str.a[qid]); ///int64_t z, z_n; + for (k = 0; k < o->cn; k++) { + if(o->a[k].is_del) break; + if(k > 0 && o->a[k].hid < o->a[k-1].hid) break; + } + if(k < o->cn) { + is_srt = 1; + } else { + for (; k < o->n; k++) { + if(!(o->a[k].is_del)) break; + if(k > o->cn && o->a[k].hid < o->a[k-1].hid) break; + } + if(k < o->n) is_srt = 1; + } + + if(is_srt) { + for (k = o->cn = 0; k < o->n; k++) { + if(o->a[k].is_del) o->a[k].hid |= ((uint32_t)(0x80000000)); + else o->cn++; + } + + radix_sort_ul2ul_srt(o->a, o->a + o->n); + + for (k = 0; k < o->n; k++) { + if(o->a[k].hid&((uint32_t)(0x80000000))) { + o->a[k].hid -= ((uint32_t)(0x80000000)); + } + } + } + + for (k = 0, buf->u.n = 0; k < o->cn; k++) { + // kv_push(uint64_t, buf->u, (o->a[k].qs<<1)); + kv_push(uint64_t, buf->u, (o->a[k].qs_k<<1)); + // kv_push(uint64_t, buf->u, (o->a[k].qe<<1)|1); + kv_push(uint64_t, buf->u, (o->a[k].qe_k<<1)|1); + } + radix_sort_srt64(buf->u.a, buf->u.a + buf->u.n); + + int64_t dp, old_dp; uint64_t start, end, b_n = buf->u.n; + for (k = 0, dp = 0, start = 0; k < b_n; ++k) { + old_dp = dp; + ///if a[j] is qe + if (buf->u.a[k]&1) --dp; + else ++dp; + + if (old_dp < min_dp && dp >= min_dp) {///old_dp < dp, b.a[j] is qs + start = buf->u.a[k]>>1; + } else if (old_dp >= min_dp && dp < min_dp) {///old_dp > min_dp, b.a[j] is qe + end = buf->u.a[k]>>1; + kv_push(uint64_t, buf->u, ((start<<32)|(end))); + } + } + + is_del = 0; + if(buf->u.n == b_n) { + is_del = 1; + } else { + uint32_t is_left = 0, is_right = 0, is_middle = 0; + for (k = b_n; k < buf->u.n; ++k) { + start = buf->u.a[k]>>32; end = (uint32_t)buf->u.a[k]; + if(start == 0) is_left = 1; + else is_middle = 1; + if(end == str->cn/**uidx->idx->a[qid].rlen**/) is_right = 1; + else is_middle = 1; + } + if(is_left == 0 && is_right == 0) is_del = 1; + if(is_left && is_right && is_middle) is_del = 1; + } + + // if(is_del && str->cn > 1 && o->is_consist && dd_path_connect(uidx->l1_ug->g, str)) { + // is_del = 0; + // } + + // fprintf(stderr, "[M::%s] qid::%u, o->is_consist::%u, str->cn::%u, is_connect::%lu\n", + // __func__, qid, o->is_consist, str->cn, dd_path_connect(uidx->l1_ug->g, str)); + + /** + if(!is_del) { + for (k = 0; k < str->cn; k++) { + rid = (((uint32_t)str->a[k])>>1); + if(!IF_HOM(rid, *(uidx->bub))) break; + } + + if(k < str->cn) {///at least a het node covered + for (k = 0, buf->u.n = 0; k < o->cn; k++) { + z = o->a[k].qs_k; z_n = o->a[k].qe_k; + for (; z < z_n; z++) { + rid = (((uint32_t)str->a[z])>>1); + if(!IF_HOM(rid, *(uidx->bub))) break; + } + if(z >= z_n) continue; + zs = z; + + for (z = z_n - 1; z >= (int64_t)zs; z--) { + rid = (((uint32_t)str->a[z])>>1); + if(!IF_HOM(rid, *(uidx->bub))) break; + } + ze = z + 1; + assert(zs < ze); + + kv_push(uint64_t, buf->u, (zs<<1)); + kv_push(uint64_t, buf->u, (ze<<1)|1); + + } + radix_sort_srt64(buf->u.a, buf->u.a + buf->u.n); + + b_n = buf->u.n; + for (k = 0, dp = 0, start = 0; k < b_n; ++k) { + old_dp = dp; + ///if a[j] is qe + if (buf->u.a[k]&1) --dp; + else ++dp; + + if (old_dp < min_dp && dp >= min_dp) {///old_dp < dp, b.a[j] is qs + start = buf->u.a[k]>>1; + } else if (old_dp >= min_dp && dp < min_dp) {///old_dp > min_dp, b.a[j] is qe + end = buf->u.a[k]>>1; + kv_push(uint64_t, buf->u, ((start<<32)|(end))); + } + } + + is_del = 0; + if(buf->u.n == b_n) { + is_del = 1; + } else { + uint32_t is_left = 0, is_right = 0, is_middle = 0; + for (k = b_n; k < buf->u.n; ++k) { + start = buf->u.a[k]>>32; end = (uint32_t)buf->u.a[k]; + if(start == 0) is_left = 1; + else is_middle = 1; + if(end == str->cn) is_right = 1; + else is_middle = 1; + } + if(is_left == 0 && is_right == 0) is_del = 1; + if(is_left && is_right && is_middle) is_del = 1; + } + } + } + **/ + + if(is_del) { + o->is_del = 1; + for (k = 0; k < o->cn; k++) o->a[k].is_del = 1; + if(o->cn && o->n > o->cn) radix_sort_ul2ul_srt(o->a, o->a + o->n); + o->cn = 0; + } +} + +void clean_srt_integer(ul_resolve_t *uidx, uint32_t qid, ul2ul_item_t *o, ul2ul_idx_t *ul2) +{ + uint64_t k, l, i, m; ul2ul_t *p; + radix_sort_ul2ul_srt(o->a, o->a + o->n); + for(k = 1, l = m = o->cn = 0; k <= o->n; k++) { + if(k == o->n || o->a[k].hid != o->a[l].hid) { + for (i = l, p = &(o->a[l]); i < k; i++) { + if(((p->is_del) && (!o->a[i].is_del)) || + ((o->a[i].qe - o->a[i].qs + o->a[i].te - o->a[i].ts) > (p->qe - p->qs + p->te - p->ts))) { + p = &(o->a[i]); + } + } + if(!(p->is_del)) o->cn++; + o->a[m++] = *p; + l = k; + } + } + o->n = m; + if(o->n == o->cn) return; + + for (k = o->cn = 0; k < o->n; k++) { + if(o->a[k].is_del) o->a[k].hid |= ((uint32_t)(0x80000000)); + else o->cn++; + } + radix_sort_ul2ul_srt(o->a, o->a + o->n); + + for (k = 0; k < o->n; k++) { + if(o->a[k].hid&((uint32_t)(0x80000000))) { + o->a[k].hid -= ((uint32_t)(0x80000000)); + } + } +} + + +static void worker_detect_chimeric(void *data, long i, int tid) // callback for kt_for() +{ + ul_resolve_t *uidx = (ul_resolve_t *)data; + integer_ml_t *sl = &(uidx->str_b); + integer_t *buf = &(sl->buf[tid]); + ul2ul_item_t *it = get_ul_ovlp(&(uidx->uovl), i, 1); + if(!it) return; + assert(uidx->pstr.str.a[i].cn > 1); + if(it->is_del) return; + clip_integer_chimeric(uidx, i, it, &(uidx->uovl), buf, 1); +} + + +void chimeric_integer_deal(ul_resolve_t *uidx) +{ + uint64_t k; ul2ul_idx_t *u2o = &(uidx->uovl); ul2ul_item_t *it; + kt_for(uidx->str_b.n_thread, worker_detect_chimeric, uidx, uidx->idx->n); + for (k = 0; k < u2o->uln; k++) { + it = get_ul_ovlp(u2o, k, 1); + if(!it) continue; + assert(uidx->pstr.str.a[k].cn > 1); + integer_normalize_ovlp_purge(uidx, k, it, u2o); + } +} + + + + +static void worker_integert_clean(void *data, long i, int tid) // callback for kt_for() +{ + ul_resolve_t *uidx = (ul_resolve_t *)data; + ul2ul_item_t *it = get_ul_ovlp(&(uidx->uovl), ulg_id(uidx->uovl, (uint32_t)i), + ulg_type(uidx->uovl, (uint32_t)i)); + if(!it) return; + if((uint32_t)i >= uidx->uovl.uln) it->id = i; + clean_srt_integer(uidx, i, it, &(uidx->uovl)); +} + +static void worker_integert_debug_sym(void *data, long i, int tid) // callback for kt_for() +{ + ul_resolve_t *uidx = (ul_resolve_t *)data; + ul2ul_item_t *o = get_ul_ovlp(&(uidx->uovl), ulg_id(uidx->uovl, (uint32_t)i), + ulg_type(uidx->uovl, (uint32_t)i)); + if(!o) return; + ul2ul_idx_t *ul2 = &(uidx->uovl); + // if(o->is_del) { + // assert(o->cn == 0); + // } + + ul2ul_t *z; uint64_t k, qid = i, ct_n = 0, del_n = 0; assert(o->id == qid); + for (k = 0; k < o->n; k++) { + if(o->a[k].is_del) del_n++; + else if(o->a[k].is_ct) ct_n++; + assert(ul2->item_idx[o->a[k].hid] != (uint32_t)-1); + z = get_ul_o(ul2, ulg_id(*ul2, o->a[k].hid), ulg_type(*ul2, o->a[k].hid), + ulg_id(*ul2, qid), ulg_type(*ul2, qid)); + assert(z && z->hid == qid && z->is_del == o->a[k].is_del && z->is_ct == o->a[k].is_ct); + + // if(!(o->a[k].is_rev == z->is_rev && (*z).qs == o->a[k].ts && (*z).qe == o->a[k].te && + // (*z).ts == o->a[k].qs && (*z).te == o->a[k].qe)){ + // fprintf(stderr, "uln::%u[M::%s] fn::%u(%c), fqs::%u, fqe::%u, fts::%u, fte::%u, fdel::%u, rn::%u(%c), rqs::%u, rqe::%u, rts::%u, rte::%u, rdel::%u\n", ul2->uln, __func__, + // o->a[k].hid, "+-"[o->a[k].is_rev], o->a[k].qs, o->a[k].qe, o->a[k].ts, o->a[k].te, o->a[k].is_del, + // z->hid, "+-"[z->is_rev], z->qs, z->qe, z->ts, z->te, z->is_del); + // } + // if(o->a[k].is_rev == z->is_rev && (*z).qs == o->a[k].ts && (*z).qe == o->a[k].te && + // (*z).ts == o->a[k].qs && (*z).te == o->a[k].qe) { + // fprintf(stderr, "good::[M::%s] fn::%u(%c), fqs::%u, fqe::%u, fts::%u, fte::%u, rn::%u(%c), rqs::%u, rqe::%u, rts::%u, rte::%u\n", __func__, + // o->a[k].hid, "+-"[o->a[k].is_rev], o->a[k].qs, o->a[k].qe, o->a[k].ts, o->a[k].te, + // z->hid, "+-"[z->is_rev], z->qs, z->qe, z->ts, z->te); + // } else { + // fprintf(stderr, "bad::[M::%s] fn::%u(%c), fqs::%u, fqe::%u, fts::%u, fte::%u, rn::%u(%c), rqs::%u, rqe::%u, rts::%u, rte::%u\n", __func__, + // o->a[k].hid, "+-"[o->a[k].is_rev], o->a[k].qs, o->a[k].qe, o->a[k].ts, o->a[k].te, + // z->hid, "+-"[z->is_rev], z->qs, z->qe, z->ts, z->te); + // } + assert(o->a[k].is_rev == z->is_rev && (*z).qs == o->a[k].ts && (*z).qe == o->a[k].te && + (*z).ts == o->a[k].qs && (*z).te == o->a[k].qe); + if(kcn) assert(!o->a[k].is_del); + else assert(o->a[k].is_del); + } + + if(o->is_del) assert((ct_n + del_n) == o->n); +} + +void print_primary_ul_chain(ul_str_t *p_str, ul_vec_t *ul, ma_ug_t *ug) +{ + uc_block_t *z; uint64_t k, dd = 0; + if(p_str) { + for (k = 0; k < p_str->cn; k++) { + z = &(ul->bb.a[p_str->a[k]>>32]); + fprintf(stderr, "[M::%s::pk->%lu] utg%.6d%c(%c::len->%u), qs::%u, qe::%u, ts::%u, te::%u\n", __func__, k, + z->hid+1, "lc"[ug->u.a[z->hid].circ], "+-"[z->rev], ug->u.a[z->hid].len, + z->qs, z->qe, z->ts, z->te); + dd++; + } + } else { + for (k = 0; k < ul->bb.n; k++) { + z = &(ul->bb.a[k]); + if(!z->pchain) continue; + fprintf(stderr, "[M::%s::rk->%lu] utg%.6d%c(%c::len->%u), qs::%u, qe::%u, ts::%u, te::%u\n", __func__, k, + z->hid+1, "lc"[ug->u.a[z->hid].circ], "+-"[z->rev], ug->u.a[z->hid].len, + z->qs, z->qe, z->ts, z->te); + dd++; + } + } + + if(dd) fprintf(stderr, "*******************************************\n"); +} + +void push_integer_seq_exact(ul_vec_t *res, ma_ug_t *ug, uint64_t *seq, uint64_t seq_n, uint64_t *off, uint32_t tid) +{ + if(seq_n <= 0) return; + uint64_t k, v, ql, ul; uc_block_t *x; + // fprintf(stderr, "[M::%s::] old_len::%u, new_len::%u\n", __func__, res->rlen, (uint32_t)off[seq_n-1]); + res->rlen = (uint32_t)off[seq_n-1]; res->bb.n = 0; kv_resize(uc_block_t, res->bb, seq_n); + for (k = 0; k < seq_n; k++) { + v = (uint32_t)seq[k]; + kv_pushp(uc_block_t, res->bb, &x); + x->hid = v>>1; x->rev = !!(v&1); x->pchain = 1; x->el = 1; x->base = 0; + x->qs = off[k]>>32; x->qe = (uint32_t)off[k]; + ql = x->qe - x->qs; ul = ug->g->seq[x->hid].len; + if((ul == ql) || (k > 0 && k + 1 < seq_n)) { + x->ts = 0; x->te = ul; + } else { + // if(!(k == 0 || k + 1 == seq_n)){ + // fprintf(stderr, "[M::%s::] k::%lu, ql::%lu, ul::%lu\n", __func__, k, ql, ul); + // } + // assert(k == 0 || k + 1 == seq_n); + if(k == 0) { + if(x->rev) { + x->ts = 0; x->te = MIN(ql, ul); + } else { + x->ts = ul - MIN(ql, ul); x->te = ul; + } + } + + if(k + 1 == seq_n) { + if(!x->rev) { + x->ts = 0; x->te = MIN(ql, ul); + } else { + x->ts = ul - MIN(ql, ul); x->te = ul; + } + } + } + x->pidx = x->aidx = x->pdis = (uint32_t)-1; + if(k > 0 && (seq[k]&((uint64_t)(0x8000000000000000)))) { + x->pidx = k - 1; x->pdis = (seq[k]<<1)>>33; + res->bb.a[x->pidx].aidx = k; + } + } + assert(res->rlen == x->qe); + // res->rlen = ((uint32_t)-1) - tid; + // print_primary_ul_chain(NULL, res, ug); +} + +uint32_t double_check_gconnect(asg_t *g, uint32_t v, uint32_t w, uint32_t v2w_d) +{ + asg_arc_t *av = asg_arc_a(g, v); uint32_t nv = asg_arc_n(g, v), k; + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == w) break; + } + if(k < nv) return 1; + return 0; +} + + +void update_integer_seq(ul_resolve_t *uidx, integer_t *buf, uint32_t id, uint64_t *seq, uint64_t seq_n, uint32_t tid) +{ + // if((((uint32_t)-1) - uidx->idx->a[id].rlen) < asm_opt.thread_num) { + // fprintf(stderr, "id->%u, c_tid->%u, l_tid->%u\n", id, tid, (((uint32_t)-1) - uidx->idx->a[id].rlen)); + // exit(0); + // } + // assert(uidx->idx->a[id].rlen!=(uint32_t)-1); + // fprintf(stderr, "dd->%u\n", uidx->idx->a[id].dd); + // if(id != 1487) return; + if(seq_n <= 0) return; + buf->n_correct++; + ul_str_t *str = &(uidx->pstr.str.a[id]); uc_block_t *z; ul_chain_t sc, msc; + uint64_t k, i, pp; integer_aln_t *b; ma_ug_t *ug = uidx->l1_ug; + assert((seq[0]>>32) == (ug->g->seq[((uint32_t)seq[0])>>1].len)); + // fprintf(stderr, "\n[M::%s::id->%u] seq_n::%lu\n", __func__, id, seq_n); + // print_primary_ul_chain(str, &(uidx->idx->a[id]), ug); + if(seq_n == 1) { + pp = ug->g->seq[((uint32_t)seq[0])>>1].len; + push_integer_seq_exact(&(uidx->idx->a[id]), ug, seq, seq_n, &pp, tid); + return; + } + + buf->u.n = 0; + for (k = 0; k < str->cn; k++) {///old seq + pp = ((uint32_t)str->a[k])>>1; pp <<= 33; pp += ((uint64_t)(0x100000000)); + pp += (k<<1); pp += ((uint32_t)str->a[k])&1; + kv_push(uint64_t, buf->u, pp); + // fprintf(stderr, "ok::%lu, ov::%u\n", k, ((uint32_t)str->a[k])); + } + for (k = 0; k < seq_n; k++) {///new seq + pp = ((uint32_t)seq[k])>>1; pp <<= 33; + pp += (k<<1); pp += ((uint32_t)seq[k])&1; + kv_push(uint64_t, buf->u, pp); + // fprintf(stderr, "nk::%lu, nv::%u\n", k, ((uint32_t)seq[k])); + + // fprintf(stderr, ">>>>>>[M::%s::c_k->%lu] utg%.6d%c(%c::len->%u)\n", __func__, k, + // (((uint32_t)seq[k])>>1)+1, "lc"[ug->u.a[(((uint32_t)seq[k])>>1)].circ], + // "+-"[((uint32_t)seq[k])&1], ug->u.a[(((uint32_t)seq[k])>>1)].len); + } + + radix_sort_srt64(buf->u.a, buf->u.a + buf->u.n); + for (k = 0, buf->b.n = 0; k < buf->u.n; k++) { + if(buf->u.a[k]&((uint64_t)(0x100000000))) continue;///skip nodes in the old seq + for (i = k+1; (i < buf->u.n) && ((buf->u.a[k]>>33) == (buf->u.a[i]>>33)); i++) { + if((buf->u.a[i]&((uint64_t)(0x100000000))) == 0) continue;///skip nodes in the new seq + if((buf->u.a[k]&1) != (buf->u.a[i]&1)) continue;///ignore reverse alignment; + ///a[k] is the new seq (q); a[i] is old seq (t) + kv_pushp(integer_aln_t, buf->b, &b); + b->vq = ((buf->u.a[k]>>33)<<1) + (buf->u.a[k]&1); + b->tn_rev_qk = ((uint32_t)buf->u.a[k])>>1; + b->tk = ((uint32_t)buf->u.a[i])>>1; + z = &(uidx->idx->a[id].bb.a[str->a[b->tk]>>32]); + assert(((z->hid<<1)+z->rev)==(((buf->u.a[i]>>33)<<1) + (buf->u.a[i]&1))); + if((buf->u.a[k]&1) != (buf->u.a[i]&1)) { + b->tk = str->cn - b->tk - 1; + b->tn_rev_qk |= ((uint64_t)(0x100000000)); + } + b->sc = ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); + assert(b->sc > 0); + } + } + + msc.v = msc.s = msc.e = (uint32_t)-1; msc.sc = 0; + if(buf->b.n > 0) { + radix_sort_integer_aln_t_srt(buf->b.a, buf->b.a + buf->b.n); ///sorted by rev|qk + for (k = 1, i = 0; k <= buf->b.n; k++) { + // fprintf(stderr, "[M::%s::z->%lu] rev::%u, qk::%u, tk::%u\n", + // __func__, k-1, (uint32_t)(!!(buf->b.a[k-1].tn_rev_qk>>32)), (uint32_t)buf->b.a[k-1].tn_rev_qk, buf->b.a[k-1].tk); + if(k == buf->b.n || (buf->b.a[i].tn_rev_qk>>32) != (buf->b.a[k].tn_rev_qk>>32)) { + if(integer_chain(id, buf->b.a + i, k - i, i, buf, ug, NULL, NULL, &sc) && sc.v != (uint32_t)-1) { + if(msc.s == (uint32_t)-1 || msc.sc < sc.sc) msc = sc; + } + i = k; + } + } + } + // fprintf(stderr, "[M::%s::id->%u] seq_n::%lu, align_n::%u, buf->b.n::%u\n", + // __func__, id, seq_n, msc.e - msc.s, (uint32_t)buf->b.n); + + + uint64_t l, v, pd, uls, ule, p_ls, p_le, is_rev, qk, tk, bc; integer_aln_t *x; uc_block_t *tb; + buf->u.n = 0; kv_resize(uint64_t, buf->u, seq_n); + // assert((seq[0]>>32) == (ug->g->seq[((uint32_t)seq[0])>>1].len)); + for (k = l = 0, p_ls = p_le = (uint64_t)-1; k < seq_n; k++) { + v = (uint32_t)seq[k]; pd = (seq[k]<<1)>>33; + ule = l + pd; uls = ((ule >= ug->g->seq[v>>1].len)?(ule - ug->g->seq[v>>1].len):(0)); + bc = 0; + if(k > 0){ + bc = (!!(seq[k]&((uint64_t)(0x8000000000000000))));///if connected in the graph + if(bc) bc = double_check_gconnect(ug->g, ((uint32_t)seq[k])^1, ((uint32_t)seq[k-1])^1, pd); + // fprintf(stderr, "bc->%lu\n", bc); + } + if(p_ls != (uint64_t)-1) { + ///uls should uls>=p_ls && uls<=p_le + if(uls < p_ls) uls = p_ls; + if(bc && uls > p_le) uls = p_le; + ///ule should ule > p_le + if(ule <= p_le) ule = p_le + 1; + } + buf->u.a[k] = uls; buf->u.a[k] <<= 32; buf->u.a[k] |= ule; + p_ls = uls; p_le = ule; + l = ule; + // fprintf(stderr, "[init_k->%lu] uls::%lu, ule::%lu, pd::%lu\n", k, uls, ule, pd); + } + buf->u.n = seq_n; + + int64_t beg_nl, end_nl; ma_utg_t *u; + v = (uint32_t)seq[0]; u = &(ug->u.a[v>>1]); beg_nl = u->len; + v = (uint32_t)seq[seq_n-1]; u = &(ug->u.a[v>>1]); end_nl = u->len; + // fprintf(stderr, "+[M::%s] beg_nl::%lu, end_nl::%lu\n", __func__, beg_nl, end_nl); + + ///q -> new seq; t -> old seq + if(msc.s != (uint32_t)-1 && msc.e > msc.s) { + int64_t qoff, toff, beg_cut = 0, end_cut = 0; uint32_t r_end; + is_rev = ((buf->b.a[msc.s].tn_rev_qk>>32)&1); + + ///beg + x = &(buf->b.a[msc.s]); + qk = (uint32_t)(x->tn_rev_qk); tk = ((is_rev == 0)? (x->tk):(str->cn - x->tk - 1)); + tb = &(uidx->idx->a[id].bb.a[str->a[tk]>>32]); + if((!!tb->rev) == (!!is_rev)) { + if(tb->te == ug->u.a[tb->hid].len) r_end = 1; + else r_end = 0; + } else { + if(tb->ts == 0) r_end = 1; + else r_end = 0; + } + if(r_end) {///start from right end + qoff = (uint32_t)buf->u.a[qk]; toff = (is_rev?(uidx->idx->a[id].rlen-tb->qs):(tb->qe)); + } else {///start from left end + qoff = buf->u.a[qk]>>32; toff = (is_rev?(uidx->idx->a[id].rlen-tb->qe):(tb->qs)); + } + + if(qk == 0) toff = tb->te - tb->ts; + if(toff < qoff) beg_cut = qoff - toff; + // fprintf(stderr, "[M::%s::beg::is_rev->%lu] qoff::%ld, toff::%ld, r_end::%u\n", __func__, is_rev, qoff, toff, r_end); + + + ///end + x = &(buf->b.a[msc.e-1]); + qk = (uint32_t)(x->tn_rev_qk); tk = ((is_rev == 0)? (x->tk):(str->cn - x->tk - 1)); + tb = &(uidx->idx->a[id].bb.a[str->a[tk]>>32]); + if((!!tb->rev) == (!!is_rev)) { + if(tb->ts == 0) r_end = 0; + else r_end = 1; + } else { + if(tb->te == ug->u.a[tb->hid].len) r_end = 0; + else r_end = 1; + } + if(!r_end) { + qoff = l - (buf->u.a[qk]>>32); toff = (is_rev?(tb->qe):(uidx->idx->a[id].rlen-tb->qs)); + } else { + qoff = l - (uint32_t)(buf->u.a[qk]); toff = (is_rev?(tb->qs):(uidx->idx->a[id].rlen-tb->qe)); + } + if(qk+1==seq_n) toff = tb->te - tb->ts; + if(toff < qoff) end_cut = qoff - toff; + // fprintf(stderr, "[M::%s::end::is_rev->%lu] qoff::%ld, toff::%ld, r_end::%u\n", __func__, is_rev, qoff, toff, r_end); + + if(beg_cut > 0) { + v = (uint32_t)seq[0]; u = &(ug->u.a[v>>1]); + if(beg_cut < u->len) beg_cut = u->len - beg_cut; + else beg_cut = 0; + if(v&1) { + beg_nl = (int64_t)(Get_READ_LENGTH(R_INF, (u->a[0]>>33))); + } else { + beg_nl = (int64_t)(Get_READ_LENGTH(R_INF, (u->a[u->n-1]>>33))); + } + if(beg_cut > beg_nl) beg_nl = beg_cut; + if(beg_nl == u->len) beg_cut = 0; + else beg_cut = 1; + } + + + if(end_cut > 0) { + v = (uint32_t)seq[seq_n-1]; u = &(ug->u.a[v>>1]); + if(end_cut < u->len) end_cut = u->len - end_cut; + else end_cut = 0; + if(v&1) { + end_nl = Get_READ_LENGTH(R_INF, (u->a[u->n-1]>>33)); + } else { + end_nl = Get_READ_LENGTH(R_INF, (u->a[0]>>33)); + } + if(end_cut > end_nl) end_nl = end_cut; + if(end_nl == u->len) end_cut = 0; + else end_cut = 1; + } + // fprintf(stderr, "++[M::%s] beg_nl::%lu, end_nl::%lu\n", __func__, beg_nl, end_nl); + if(beg_cut || end_cut) { + k = 0; uls = 0; ule = beg_nl; + buf->u.a[k] = uls; buf->u.a[k] <<= 32; buf->u.a[k] |= ule; + l = ule; p_ls = uls; p_le = ule; + for (k += 1; k + 1 < seq_n; k++) { + v = (uint32_t)seq[k]; pd = (seq[k]<<1)>>33; + ule = l + pd; uls = ((ule >= ug->g->seq[v>>1].len)?(ule - ug->g->seq[v>>1].len):(0)); + bc = 0; + if(k > 0){ + bc = (!!(seq[k]&((uint64_t)(0x8000000000000000))));///if connected in the graph + if(bc) bc = double_check_gconnect(ug->g, ((uint32_t)seq[k])^1, ((uint32_t)seq[k-1])^1, pd); + // fprintf(stderr, "bc->%lu\n", bc); + } + if(p_ls != (uint64_t)-1) { + ///uls should uls>=p_ls && uls<=p_le + if(uls < p_ls) uls = p_ls; + if(bc && uls > p_le) uls = p_le; + ///ule should ule > p_le + if(ule <= p_le) ule = p_le + 1; + } + buf->u.a[k] = uls; buf->u.a[k] <<= 32; buf->u.a[k] |= ule; + p_ls = uls; p_le = ule; + l = ule; + } + + assert(k < seq_n); + v = (uint32_t)seq[k]; pd = (seq[k]<<1)>>33; + ule = l + pd; uls = ((ule >= ug->g->seq[v>>1].len)?(ule - ug->g->seq[v>>1].len):(0)); + ule = uls + end_nl; + bc = 0; + if(k > 0){ + bc = (!!(seq[k]&((uint64_t)(0x8000000000000000))));///if connected in the graph + if(bc) bc = double_check_gconnect(ug->g, ((uint32_t)seq[k])^1, ((uint32_t)seq[k-1])^1, pd); + // fprintf(stderr, "bc->%lu\n", bc); + } + if(p_ls != (uint64_t)-1) { + ///uls should uls>=p_ls && uls<=p_le + if(uls < p_ls) uls = p_ls; + if(bc && uls > p_le) uls = p_le; + ///ule should ule > p_le + if(ule <= p_le) ule = p_le + 1; + } + if(ule - uls < (uint64_t)end_nl) ule = uls + end_nl; + buf->u.a[k] = uls; buf->u.a[k] <<= 32; buf->u.a[k] |= ule; + p_ls = uls; p_le = ule; + l = ule; + } + } + + push_integer_seq_exact(&(uidx->idx->a[id]), ug, seq, seq_n, buf->u.a, tid); +} + +static void worker_integer_update(void *data, long i, int tid) // callback for kt_for() +{ + ul_resolve_t *uidx = (ul_resolve_t *)data; + integer_ml_t *sl = &(uidx->str_b); + integer_t *buf = &(sl->buf[i]);///normally should be buf = &(sl->buf[tid]) + uint64_t k, l; + for (k = 0, l = (uint64_t)-1; k <= buf->res_dump.n; k++) { + if(k == buf->res_dump.n || (buf->res_dump.a[k]&((uint64_t)(0xffffffff))) == ((uint64_t)(0xffffffff))) { + if(l != (uint64_t)-1 && k - l > 1) { + update_integer_seq(uidx, buf, buf->res_dump.a[l]>>32, buf->res_dump.a + l + 1, k - l - 1, tid); + } + l = k; + } + } +} + + +void integer_correction(ul_resolve_t *uidx) +{ + integer_ml_t sl; + init_integer_ml_t(&sl, uidx, asm_opt.thread_num); +} + +uint64_t clean_ul_re_correct_buf(ul_resolve_t *uidx, uint64_t clean_dump, uint64_t *tot_circle) +{ + uint64_t k, occ, n_circle; + for (k = occ = n_circle = 0; k < uidx->str_b.n_thread; k++) { + occ += uidx->str_b.buf[k].n_correct; + n_circle += uidx->str_b.buf[k].n_circle; + uidx->str_b.buf[k].n_correct = 0; + uidx->str_b.buf[k].n_circle = 0; + if(clean_dump) uidx->str_b.buf[k].res_dump.n = 0; + uidx->str_b.buf[k].q.n = 0; + uidx->str_b.buf[k].t.n = 0; + uidx->str_b.buf[k].b.n = 0; + uidx->str_b.buf[k].f.n = 0; + uidx->str_b.buf[k].p.n = 0; + uidx->str_b.buf[k].o.n = 0; + uidx->str_b.buf[k].u.n = 0; + uidx->str_b.buf[k].vis.n = 0; + uidx->str_b.buf[k].sc.n = 0; + uidx->str_b.buf[k].snp.n = 0; + } + (*tot_circle) = n_circle; + return occ; +} + + +void rebuid_idx(ul_resolve_t *uidx) +{ + uint32_t k; + free(uidx->idx->ridx.idx.a); free(uidx->idx->ridx.occ.a); + memset(&(uidx->idx->ridx), 0, sizeof((uidx->idx->ridx))); + filter_ul_ug(uidx->l1_ug); + gen_ul_vec_rid_t(uidx->idx, NULL, uidx->l1_ug); + update_ug_arch_ul_mul(uidx->l1_ug); + + free(uidx->pstr.idx.a); free(uidx->pstr.occ.a); + for (k = 0; k < uidx->pstr.str.n; k++) { + free(uidx->pstr.str.a[k].a); + } + free(uidx->pstr.str.a); + memset(&(uidx->pstr), 0, sizeof(uidx->pstr)); + init_ul_str_idx_t(uidx); +} + +void shrink_1b(ma_ug_t *ug, uc_block_t *z, uc_block_t *lim, uint32_t is_forward) +{ + if(z->ts != 0 || z->te != ug->g->seq[z->hid].len) return; + uc_block_t bc = *z; + if(z->ts + 1 < z->te && z->qs + 1 < z->qe) { + uint32_t off = get_offset_adjust(1, z->te-z->ts, z->qe-z->qs); + if(is_forward) { + if((!z->rev)) { + z->ts += 1; z->qs += off; + } else { + z->te -= 1; z->qs += off; + } + if((lim) && (!((z->qs <= lim->qs) && (z->qe <= lim->qe)))) *z = bc; + } else { + if((!z->rev)) { + z->te -= 1; z->qe -= off; + } else { + z->ts += 1; z->qe -= off; + } + if((lim) && (!((z->qs >= lim->qs) && (z->qe >= lim->qe)))) *z = bc; + } + if((ugl_cover_check(bc.ts, bc.te, &(ug->u.a[bc.hid]))) && + (!ugl_cover_check(z->ts, z->te, &(ug->u.a[z->hid])))) { + *z = bc; + } + } + +} + +void renew_ul_vec_t(ul_vec_t *x, ma_ug_t *ug) +{ + if(x->bb.n <= 0) return; + int64_t l, k, z, bn = x->bb.n, dd; int64_t qs = x->bb.a[0].qs, qe; + for (l = 0, k = 1, qs = 0; k <= bn; k++) { + if(k == bn || x->bb.a[k].pidx == (uint32_t)-1) { + if(k - l > 0) { + for (z = k - 1, dd = 0; z >= l; z--) { + if(z > l) { + assert(x->bb.a[z].pidx == z-1); + dd += x->bb.a[z].pdis; + } else { + assert(x->bb.a[z].pidx == (uint32_t)-1); + dd += ug->g->seq[x->bb.a[z].hid].len; + } + dd -= (int64_t)(ug->g->seq[x->bb.a[z].hid].len - (x->bb.a[z].te - x->bb.a[z].ts)); + } + if(dd < 0) dd = 0; + qe = qs + dd; + if(k < bn) { + dd = qe + (int64_t)(x->bb.a[k].qs) - (int64_t)(x->bb.a[k-1].qe); + if(dd < 0) dd = 0; + } + for (z = k - 1; z >= l; z--) { + qs = qe - (int64_t)(x->bb.a[z].te - x->bb.a[z].ts); + if(qs < 0) qs = 0; + x->bb.a[z].qs = qs; x->bb.a[z].qe = qe; + if(z > l) { + qe += (int64_t)(ug->g->seq[x->bb.a[z].hid].len - (x->bb.a[z].te - x->bb.a[z].ts)); + qe -= (int64_t)(x->bb.a[z].pdis); + if(qe < 0) qe = 0; + } + } + + if(k < bn) qs = dd; + } + l = k; + } + } + x->rlen = x->bb.a[bn-1].qe; +} + +void shrink_ul0(all_ul_t *uls, ul_str_t *str, uint64_t id, integer_t *buf, ma_ug_t *ug) +{ + uint32_t k, c_k, p_k, cv, pv, bl, i; uc_block_t *xi, *yi; buf->u.n = 0; nid_t *np = NULL; + asg_arc_t *av; uint32_t nv, s, e, m, d, mm, is_conn; uint64_t *z; ul_vec_t *x; + if(str->cn < 2) return; + for (k = 0, bl = 0, c_k = p_k = pv = (uint32_t)-1; k < str->cn; k++) { + xi = &(uls->a[id].bb.a[str->a[k]>>32]); is_conn = 0; + c_k = k; cv = ((uint32_t)str->a[k])^1; + assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[k])); + if(p_k != (uint32_t)-1) { + if(xi->pidx == (str->a[p_k]>>32)) { + av = asg_arc_a(ug->g, cv); nv = asg_arc_n(ug->g, cv); + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + if(av[i].v == pv) break; + } + if(i < nv) { + s = (uint32_t)av[i].ul; + if(s == xi->pdis) { + is_conn = 1; + } else { + d = (s>=xi->pdis?s-xi->pdis:xi->pdis-s); + mm = MAX(s, xi->pdis); + if((d <= (mm*0.08)) || (d <= 512)) is_conn = 1; + } + } + } else if(xi->pidx == (uint32_t)-1) { + is_conn = 1; + } + } + if(is_conn) { + is_conn = 0; assert(k); + yi = &(uls->a[id].bb.a[str->a[k-1]>>32]); + if((xi->qs >= yi->qs) && (xi->qe >= yi->qe)) is_conn = 1; + } + if(is_conn) { + bl++; + } else { + if(bl > 0) { + kv_pushp(uint64_t, buf->u, &z); + (*z) = k - 1 - bl; (*z) <<= 32; (*z) += bl + 1; + } + bl = 0; + } + p_k = c_k; pv = cv; + } + + if(bl > 0) { + kv_pushp(uint64_t, buf->u, &z); + (*z) = k - 1 - bl; (*z) <<= 32; (*z) += bl + 1; + } + // fprintf(stderr, "[M::%s::] buf->u.n::%u, str->cn::%u\n", __func__, buf->u.n, str->cn); + if(buf->u.n <= 0) { + str->cn = str->n = 0; + } else if(buf->u.n > 0) { + uint32_t pidx, aidx, pdis; + for (i = 0; i + 1 < buf->u.n; i++) { + s = (buf->u.a[i]>>32); e = s + ((uint32_t)buf->u.a[i]); + ///new id + kv_pushp(nid_t, uls->nid, &np); + np->n = uls->nid.a[id].n; MALLOC(np->a, np->n+1); + memcpy(np->a, uls->nid.a[id].a, np->n); np->a[np->n] = '\0'; + ///new ovlps + kv_pushp(ul_vec_t, *uls, &x); memset(x, 0, sizeof(*x)); + MALLOC(x->bb.a, e - s); x->bb.n = x->bb.m = e - s; + + for (k = s, m = 0; k < e; k++, m++) { + pidx = uls->a[id].bb.a[str->a[k]>>32].pidx; + aidx = uls->a[id].bb.a[str->a[k]>>32].aidx; + pdis = uls->a[id].bb.a[str->a[k]>>32].pdis; + x->bb.a[m] = uls->a[id].bb.a[str->a[k]>>32]; + if(k == s) { + x->bb.a[m].pidx = x->bb.a[m].pdis = (uint32_t)-1; + } else if(pidx != (uint32_t)-1) { + x->bb.a[m].pidx = m - 1; x->bb.a[m].pdis = pdis; + } + if(k + 1 == e) { + x->bb.a[m].aidx = (uint32_t)-1; + } else if(aidx != (uint32_t)-1) { + x->bb.a[m].aidx = m + 1; + } + } + x->bb.n = m; + assert(x->bb.n > 1); + + shrink_1b(ug, &(x->bb.a[0]), ((x->bb.n>=2)?&(x->bb.a[1]):(NULL)), 1); + shrink_1b(ug, &(x->bb.a[x->bb.n-1]), ((x->bb.n>=2)?&(x->bb.a[x->bb.n-2]):(NULL)), 0); + + d = x->bb.a[0].qs; + for (k = 0; k < x->bb.n; k++) { + x->bb.a[k].qs -= d; x->bb.a[k].qe -= d; + } + x->rlen = x->bb.a[x->bb.n-1].qe; + renew_ul_vec_t(x, ug); + } + + ///the last one; update in-place + s = (buf->u.a[i]>>32); e = s + ((uint32_t)buf->u.a[i]); x = &(uls->a[id]); + for (k = s, m = 0; k < e; k++, m++) { + pidx = x->bb.a[str->a[k]>>32].pidx; + aidx = x->bb.a[str->a[k]>>32].aidx; + pdis = x->bb.a[str->a[k]>>32].pdis; + x->bb.a[m] = x->bb.a[str->a[k]>>32]; + if(k == s) { + x->bb.a[m].pidx = x->bb.a[m].pdis = (uint32_t)-1; + } else if(pidx != (uint32_t)-1) { + x->bb.a[m].pidx = m - 1; x->bb.a[m].pdis = pdis; + } + if(k + 1 == e) { + x->bb.a[m].aidx = (uint32_t)-1; + } else if(aidx != (uint32_t)-1) { + x->bb.a[m].aidx = m + 1; + } + } + x->bb.n = m; + assert(x->bb.n > 1); + shrink_1b(ug, &(x->bb.a[0]), ((x->bb.n>=2)?&(x->bb.a[1]):(NULL)), 1); + shrink_1b(ug, &(x->bb.a[x->bb.n-1]), ((x->bb.n>=2)?&(x->bb.a[x->bb.n-2]):(NULL)), 0); + d = x->bb.a[0].qs; + for (k = 0; k < x->bb.n; k++) { + x->bb.a[k].qs -= d; x->bb.a[k].qe -= d; + } + x->rlen = x->bb.a[x->bb.n-1].qe; + renew_ul_vec_t(x, ug); + } +} + +void shrink_uls(ul_resolve_t *uidx) +{ + all_ul_t *uls = uidx->idx; uint64_t k, ul_n = uls->n; + for (k = 0; k < ul_n; k++) { + // fprintf(stderr, "+[M::%s::k->%lu] ul_n::%lu, uls->n::%u\n", __func__, k, ul_n, uls->n); + shrink_ul0(uls, &(uidx->pstr.str.a[k]), k, &(uidx->str_b.buf[0]), uidx->l1_ug); + // fprintf(stderr, "-[M::%s::k->%lu] ul_n::%lu, uls->n::%u\n", __func__, k, ul_n, uls->n); + } + rebuid_idx(uidx); +} + +void print_ul_seq(ul_resolve_t *uidx, uint64_t id) +{ + uint64_t i; ul_str_t *str = &(uidx->pstr.str.a[id]); ma_ug_t *ug = uidx->init_ug; + fprintf(stderr, "%.*s\tid::%lu\t", (int32_t)uidx->idx->nid.a[id].n, + uidx->idx->nid.a[id].a, id); + for (i = 0; i < str->cn; i++) { + fprintf(stderr, "utg%.6d%c(%c)\t", (((uint32_t)str->a[i])>>1)+1, + "lc"[ug->u.a[(((uint32_t)str->a[i])>>1)].circ], "+-"[(((uint32_t)str->a[i])&1)]); + } + fprintf(stderr,"\n"); +} + +void ul_re_correct(ul_resolve_t *uidx, uint64_t n_r) +{ + // print_ul_seq(uidx, 2062); print_ul_seq(uidx, 2093); + uint64_t k, occ, n_circle; ///uidx->str_b.n_thread = 1; + for (k = 0; k < n_r; k++) { + kt_for(uidx->str_b.n_thread, worker_integer_correction, uidx, uidx->idx->n); + occ = clean_ul_re_correct_buf(uidx, 0, &n_circle); + fprintf(stderr, "+[M::%s::round->%lu] # corrected UL reads::%lu, # circle UL reads::%lu\n", + __func__, k, occ, n_circle); + kt_for(uidx->str_b.n_thread, worker_integer_update, uidx, uidx->str_b.n_thread); + occ = clean_ul_re_correct_buf(uidx, 1, &n_circle); + fprintf(stderr, "-[M::%s::round->%lu] # corrected UL reads::%lu, # circle UL reads::%lu\n", + __func__, k, occ, n_circle); + rebuid_idx(uidx); + // print_ul_seq(uidx, 2062); print_ul_seq(uidx, 2093); + // exit(1); + } + + shrink_uls(uidx); +} + +void append_utg_es(ul_resolve_t *uidx) +{ + uint64_t k; ul2ul_idx_t *u2o = &(uidx->uovl); ul2ul_item_t *it; + for (k = 0; k < u2o->uln; k++) { + it = get_ul_ovlp(u2o, k, 1); + if(!it) continue; + assert(uidx->pstr.str.a[k].cn > 1); + integer_append_ug_ovlp(uidx, k, it, u2o); + } + + kt_for(uidx->str_b.n_thread, worker_integert_clean, uidx, u2o->tot);///all ul + ug + + for (k = 0; k < u2o->tot; k++) { + it = get_ul_ovlp(u2o, ulg_id(*u2o, k), ulg_type(*u2o, k)); + if(!it) continue; + integer_normalize_ovlp(uidx, k, it, u2o); + } + + kt_for(uidx->str_b.n_thread, worker_integert_clean, uidx, u2o->tot);///all ul + ug +} + + +void remove_integert_containment(ul_resolve_t *uidx, uint32_t keep_raw_utg) +{ + ul2ul_idx_t *u2o = &(uidx->uovl); ul2ul_item_t *o; + uint64_t k, kn = keep_raw_utg?u2o->uln:u2o->tot; + for (k = 0; k < kn; k++) { + o = get_ul_ovlp(u2o, ulg_id(*u2o, k), ulg_type(*u2o, k)); + if(!o) continue; + integer_containment_purge(uidx, k, o, u2o, keep_raw_utg); + } + + kt_for(uidx->str_b.n_thread, worker_integert_clean, uidx, u2o->tot);///all ul + ug +} + +void print_integert_ovlp_stat(ul2ul_idx_t *ul2) +{ + uint64_t i, k, occ_r = 0, occ_o = 0; ul2ul_item_t *o; + for (i = 0; i < ul2->uln; i++) { + o = get_ul_ovlp(ul2, ulg_id(*ul2, i), ulg_type(*ul2, i)); + if((!o) || (o->is_del)) continue; + occ_r++; + for (k = 0; k < o->n; k++) { + if(o->a[k].is_del || o->a[k].is_ct || (!ulg_type(*ul2, o->a[k].hid))) continue; + occ_o++; + } + } + fprintf(stderr, "[M::%s::] # UL reads::%lu, # UL ovlps::%lu\n", __func__, occ_r, occ_o); +} + +asg_t *integer_sg_gen(ul_resolve_t *uidx, uint64_t min_ovlp) +{ + ul2ul_idx_t *ul2 = &(uidx->uovl); ma_ug_t *ug = uidx->l1_ug; asg_t *raw_g = ug->g; ///uc_block_t *xi; + uint64_t i, k, is_del, v, w, nv, z; ul2ul_item_t *o, *ow; int32_t r; asg_arc_t t, *p; asg_arc_t *av; + // ul_str_t *str; + asg_t *g = asg_init(); + for (i = 0; i < ul2->tot; i++) { + is_del = 0; + o = get_ul_ovlp(ul2, ulg_id(*ul2, i), ulg_type(*ul2, i)); + if((!o) || (o->is_del)) is_del = 1; + asg_seq_set(g, i, ulg_len(*uidx, i), is_del); + g->seq[i].c = 0; + } + // CALLOC(g->seq_vis, g->n_seq*2); + + for (i = 0; i < ul2->tot; ++i) { + o = get_ul_ovlp(ul2, ulg_id(*ul2, i), ulg_type(*ul2, i)); + if((!o) || (o->is_del)) continue; + for (k = 0; k < o->n; k++) { + if(o->a[k].is_del || o->a[k].is_ct) continue; + r = integer_hit2arc(&(o->a[k]), ulg_len(*uidx, i), ulg_len(*uidx, o->a[k].hid), + ulg_occ(*uidx, i), ulg_occ(*uidx, o->a[k].hid), i, o->a[k].hid, min_ovlp, &t); + if (r >= 0) { + p = asg_arc_pushp(g); + *p = t; + } + } + if(i >= ul2->uln) {///is a node of ug + v = (i-ul2->uln)<<1; + nv = asg_arc_n(raw_g, v); av = asg_arc_a(raw_g, v); + for (z = 0; z < nv; z++) { + if(av[z].del) continue; + w = av[z].v + (ul2->uln<<1); + ow = get_ul_ovlp(ul2, ulg_id(*ul2, (w>>1)), ulg_type(*ul2, (w>>1))); + if((!ow) || (ow->is_del)) continue; + p = asg_arc_pushp(g); + *p = av[z]; p->ul += (((uint64_t)ul2->uln)<<33); p->v += (ul2->uln<<1); + } + + v = ((i-ul2->uln)<<1)+1; + nv = asg_arc_n(raw_g, v); av = asg_arc_a(raw_g, v); + for (z = 0; z < nv; z++) { + if(av[z].del) continue; + w = av[z].v + (ul2->uln<<1); + ow = get_ul_ovlp(ul2, ulg_id(*ul2, (w>>1)), ulg_type(*ul2, (w>>1))); + if((!ow) || (ow->is_del)) continue; + p = asg_arc_pushp(g); + *p = av[z]; p->ul += (((uint64_t)ul2->uln)<<33); p->v += (ul2->uln<<1); + } + } + // else { ///is a node of ug + // str = &(uidx->pstr.str.a[i]); + // if(str->cn > 0) { + // xi = &(uidx->idx->a[i].bb.a[str->a[0]>>32]); v = ((uint32_t)str->a[0])^1; + // ow = get_ul_ovlp(ul2, ulg_id(*ul2, (v>>1)), ulg_type(*ul2, (v>>1))); + // if((!ow) || (ow->is_del)) { + // nv = asg_arc_n(raw_g, v); av = asg_arc_a(raw_g, v); + // } + + // xi = &(uidx->idx->a[i].bb.a[str->a[str->cn-1]>>32]); v = ((uint32_t)str->a[str->cn-1]); + // ow = get_ul_ovlp(ul2, ulg_id(*ul2, (v>>1)), ulg_type(*ul2, (v>>1))); + // if((!ow) || (ow->is_del)) { + + // } + // } + // } + } + asg_cleanup(g); + g->r_seq = g->n_seq; + // fprintf(stderr, "[M::%s::] # ig nodes::%u, # ig archs::%u\n", __func__, g->n_seq, g->n_arc); + return g; +} + +inline uint64_t get_ul_occ(ul_resolve_t *uidx, uint64_t id) +{ + return uidx->uovl.cc.uc[id]; +} + +inline void get_iug_u_raw_occ(ul_resolve_t *uidx, uint32_t id, uint32_t *ul_occ, uint32_t *raw_ug_occ) +{ + if(ul_occ) *ul_occ = uidx->uovl.cc.raw_uc[id]; + if(raw_ug_occ) *raw_ug_occ = uidx->uovl.i_ug->u.a[id].n - uidx->uovl.cc.raw_uc[id]; +} + +inline asg_arc_t* get_specfic_edge(asg_t *g, uint32_t v, uint32_t w) +{ + asg_arc_t *av = asg_arc_a(g, v); uint32_t nv = asg_arc_n(g, v), k; + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == w) break; + } + + if(k < nv) return (&av[k]); + return NULL; +} + + +void gen_ul_seq(ul_resolve_t *uidx, uint64_t iug_id, asgc8_v * res) +{ + ul2ul_idx_t *idx = &(uidx->uovl); ma_ug_t *raw = uidx->l1_ug; uint64_t k, m, s, e, ol, rev, Ns; + uinfo_srt_warp_t *seq = &(idx->cc.iug_a[iug_id]); ma_utg_t *ru; asg_arc_t *z; + for (k = res->n = 0; k < seq->n; k++) { + s = seq->a[k].s; e = seq->a[k].e; rev = seq->a[k].v&1; + ru = &(raw->u.a[seq->a[k].v>>1]); Ns = 0; + if(k + 1 < seq->n) { + z = get_specfic_edge(raw->g, seq->a[k].v, seq->a[k+1].v); + if(z) { + ol = z->ol; + if(!rev) { + // assert(seq->a[k].e == ru->len); + e = (ru->len > ol)?(ru->len-ol):(0); + } else { + // assert(seq->a[k].s == 0); + s = ol; + } + } else { + Ns = 50; + } + } + if(s < e) { + kv_resize(char, (*res), res->n + e - s); + retrieve_u_seq(NULL, res->a + res->n, ru, rev, (rev)?(ru->len-e):(s), e - s, NULL); + res->n += e - s; + } + + if(Ns) { + kv_resize(char, (*res), res->n + Ns); + for (m = 0; m < Ns; m++) res->a[res->n++] = 'N'; + } + } + + kv_push(char, *res, '\0'); + // fprintf(stderr, "[M::%s::iug_id->%lu] # u->len::%u, # res->n::%u, # strlen(res->a)::%u\n", + // __func__, iug_id, idx->i_ug->u.a[iug_id].len, (uint32_t)res->n, (uint32_t)strlen(res->a)); +} + + +void ma_integer_ug_print0(const ma_ug_t *ug, ul_resolve_t *uidx, int print_seq, const char* prefix, FILE *fp, uint32_t is_seq) +{ + uint32_t i, j, l, x; ma_utg_t *p, *s; ul2ul_idx_t *idx = &(uidx->uovl); + char name[32]; uinfo_srt_warp_t *seq; asgc8_v t; kv_init(t); //uint64_t tot = 0; + for (i = 0; i < ug->u.n; ++i) { // the Segment lines in GFA + p = &ug->u.a[i]; + if(p->m == 0) continue; + if(ug->g && ug->g->seq[i].del) continue; + sprintf(name, "%s%.6d%c", prefix, i + 1, "lc"[p->circ]); + if(is_seq) { + gen_ul_seq(uidx, i, &t); + fprintf(fp, "S\t%s\t%s\tLN:i:%d\trd:i:%lu\n", name, t.a, p->len, get_ul_occ(uidx, i)); + } else { + fprintf(fp, "S\t%s\t*\tLN:i:%d\trd:i:%lu\n", name, p->len, get_ul_occ(uidx, i)); + } + // tot += p->len; + + for (j = l = 0; j < p->n; j++) { + if(p->a[j] != (uint64_t)-1) { + x = p->a[j]>>33; + if(ulg_type(uidx->uovl, x)) {//read + x = ulg_id(uidx->uovl, x); + fprintf(fp, "A\t%s\t%d\t%c\t%.*s\t%d\t%d\tid:i:%d\tHG:A:*\n", name, l, "+-"[p->a[j]>>32&1], + (int32_t)uidx->idx->nid.a[x].n, uidx->idx->nid.a[x].a, 0, uidx->idx->a[x].rlen, x); + } else { ///node + x = ulg_id(uidx->uovl, x); s = &(uidx->init_ug->u.a[x]); + fprintf(fp, "A\t%s\t%d\t%c\tutg%.6d%c\t%d\t%d\tid:i:%d\tHG:A:*\n", name, l, "+-"[p->a[j]>>32&1], + x + 1, "lc"[s->circ], 0, s->len, x); + } + } + else + { + fprintf(fp, "A\t%s\t%d\t*\t*\t*\t*\tid:i:*\tHG:A:*\n", name, l); + } + l += (uint32_t)p->a[j]; + } + + seq = &(idx->cc.iug_a[i]); + for (j = 0; j < seq->n; j++) { + x = seq->a[j].v>>1; s = &(uidx->init_ug->u.a[x]); + fprintf(fp, "U\t%s\t%c\tutg%.6d%c\t%d\t%d\tHG:A:*\n", + name, "+-"[seq->a[j].v&1], x + 1, "lc"[s->circ], seq->a[j].s, seq->a[j].e); + } + + } + + if(ug->g) + { + asg_arc_t* au = NULL; + uint32_t nu, u, v; + for (i = 0; i < ug->u.n; ++i) { + if(ug->u.a[i].m == 0) continue; + if(ug->u.a[i].circ) + { + fprintf(fp, "L\t%s%.6dc\t+\t%s%.6dc\t+\t%dM\tL1:i:%d\n", + prefix, i+1, prefix, i+1, 0, ug->u.a[i].len); + fprintf(fp, "L\t%s%.6dc\t-\t%s%.6dc\t-\t%dM\tL1:i:%d\n", + prefix, i+1, prefix, i+1, 0, ug->u.a[i].len); + } + u = i<<1; + au = asg_arc_a(ug->g, u); + nu = asg_arc_n(ug->g, u); + for (j = 0; j < nu; j++) + { + if(au[j].del) continue; + v = au[j].v; + fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", + prefix, (u>>1)+1, "lc"[ug->u.a[u>>1].circ], "+-"[u&1], + prefix, (v>>1)+1, "lc"[ug->u.a[v>>1].circ], "+-"[v&1], au[j].ol, asg_arc_len(au[j]), au[j].ou); + } + + + u = (i<<1) + 1; + au = asg_arc_a(ug->g, u); + nu = asg_arc_n(ug->g, u); + for (j = 0; j < nu; j++) + { + if(au[j].del) continue; + v = au[j].v; + fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\tL2:i:%u\n", + prefix, (u>>1)+1, "lc"[ug->u.a[u>>1].circ], "+-"[u&1], + prefix, (v>>1)+1, "lc"[ug->u.a[v>>1].circ], "+-"[v&1], au[j].ol, asg_arc_len(au[j]), au[j].ou); + } + } + } + kv_destroy(t); + // fprintf(stderr, "[M::%s::] tot::%lu\n", __func__, tot); +} + + +void gen_u2g_seq(ul_resolve_t *uidx, uint64_t iug_id, asgc8_v * res) +{ + ul2ul_idx_t *idx = &(uidx->uovl); ma_ug_t *raw = uidx->l1_ug; uint64_t k, m, s, e, ol, rev, Ns; + uinfo_srt_warp_t *seq = &(idx->cc.iug_a[iug_id]); ma_utg_t *ru; asg_arc_t *z; + for (k = res->n = 0; k < seq->n; k++) { + s = seq->a[k].s; e = seq->a[k].e; rev = seq->a[k].v&1; + ru = &(raw->u.a[seq->a[k].v>>1]); Ns = 0; + if(k + 1 < seq->n) { + z = get_specfic_edge(raw->g, seq->a[k].v, seq->a[k+1].v); + if(z) { + ol = z->ol; + if(!rev) { + // assert(seq->a[k].e == ru->len); + e = (ru->len > ol)?(ru->len-ol):(0); + } else { + // assert(seq->a[k].s == 0); + s = ol; + } + } else { + Ns = 50; + } + } + if(s < e) { + kv_resize(char, (*res), res->n + e - s); + retrieve_u_seq(NULL, res->a + res->n, ru, rev, (rev)?(ru->len-e):(s), e - s, NULL); + res->n += e - s; + } + + if(Ns) { + kv_resize(char, (*res), res->n + Ns); + for (m = 0; m < Ns; m++) res->a[res->n++] = 'N'; + } + } + + kv_push(char, *res, '\0'); + // fprintf(stderr, "[M::%s::iug_id->%lu] # u->len::%u, # res->n::%u, # strlen(res->a)::%u\n", + // __func__, iug_id, idx->i_ug->u.a[iug_id].len, (uint32_t)res->n, (uint32_t)strlen(res->a)); +} + + +void output_integer_graph(ul_resolve_t *uidx, ma_ug_t *iug, const char *nn, uint32_t is_seq) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+50); + sprintf(gfa_name, "%s.integer.noseq.gfa", nn); + FILE* fp = fopen(gfa_name, "w"); free(gfa_name); + if (!fp) return; + ma_integer_ug_print0(iug, uidx, 0, "itg", fp, is_seq); + fclose(fp); +} + + +void print_raw_uls_seq(ul_resolve_t *uidx, const char *nn) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+70); + sprintf(gfa_name, "%s.raw.integer.seq.log", nn); + FILE* fp = fopen(gfa_name, "w"); free(gfa_name); + if (!fp) return; + ma_ug_t *ug = uidx->init_ug; all_ul_t *aln = uidx->idx; + uint64_t id; uc_block_t *a = NULL; int64_t k, a_n; + for (id = 0; id < aln->n; id++) { + a = aln->a[id].bb.a; a_n = aln->a[id].bb.n; k = 0; + if(a_n == 0) continue; + fprintf(fp,"%.*s\tid::%lu\t", (int32_t)aln->nid.a[id].n, aln->nid.a[id].a, id); + // for (k = 0; k < a_n && ug_occ_w(a[k].ts, a[k].te, &(ug->u.a[a[k].hid])) == 0; k++); + for (; k < a_n; k++) { + // if(ug_occ_w(a[k].ts, a[k].te, &(ug->u.a[a[k].hid])) == 0) break; + fprintf(fp, "utg%.6d%c(%c)(n::%lu)\t", a[k].hid + 1, "lc"[ug->u.a[a[k].hid].circ], "+-"[a[k].rev], ug_occ_w(a[k].ts, a[k].te, &(ug->u.a[a[k].hid]))); + } + fprintf(fp,"\n"); + } + fclose(fp); +} + +void print_raw_uls_aln(ul_resolve_t *uidx, const char *nn) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+70); + sprintf(gfa_name, "%s.raw.aln.log", nn); + FILE* fp = fopen(gfa_name, "w"); free(gfa_name); + if (!fp) return; + ma_ug_t *ug = uidx->init_ug; all_ul_t *aln = uidx->idx; + uint64_t id; uc_block_t *a = NULL; int64_t k, a_n; + for (id = 0; id < aln->n; id++) { + a = aln->a[id].bb.a; a_n = aln->a[id].bb.n; k = 0; + if(a_n == 0) continue; + fprintf(fp,"%.*s\tid::%lu\tdd::%u\t", (int32_t)aln->nid.a[id].n, aln->nid.a[id].a, id, aln->a[id].dd); + // for (k = 0; k < a_n && ug_occ_w(a[k].ts, a[k].te, &(ug->u.a[a[k].hid])) == 0; k++); + for (; k < a_n; k++) { + // if(ug_occ_w(a[k].ts, a[k].te, &(ug->u.a[a[k].hid])) == 0) break; + fprintf(fp, "utg%.6d%c(%c)q::[%u, %u)\t", a[k].hid + 1, "lc"[ug->u.a[a[k].hid].circ], "+-"[a[k].rev], a[k].qs, a[k].qe); + } + fprintf(fp,"\n"); + } + fclose(fp); +} + + +void print_uls_seq(ul_resolve_t *uidx, const char *nn) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+50); + sprintf(gfa_name, "%s.integer.seq.log", nn); + FILE* fp = fopen(gfa_name, "w"); free(gfa_name); + if (!fp) return; + uint64_t k, i; all_ul_t *uls = uidx->idx; ul2ul_item_t *o; + ul_str_idx_t *str_idx = &(uidx->pstr); ma_ug_t *ug = uidx->init_ug; + for (k = 0; k < uls->n; k++) { + if(str_idx->str.a[k].cn < 2) continue; + o = get_ul_ovlp(&(uidx->uovl), ulg_id(uidx->uovl, k), ulg_type(uidx->uovl, k)); + if(!o) continue; + fprintf(fp,"%.*s\tid::%lu\tdel::%u\t", (int32_t)uidx->idx->nid.a[k].n, uidx->idx->nid.a[k].a, k, o->is_del); + for (i = 0; i < str_idx->str.a[k].cn; i++) { + fprintf(fp, "utg%.6d%c(%c)\t", (((uint32_t)str_idx->str.a[k].a[i])>>1)+1, + "lc"[ug->u.a[(((uint32_t)str_idx->str.a[k].a[i])>>1)].circ], "+-"[(((uint32_t)str_idx->str.a[k].a[i])&1)]); + } + fprintf(fp,"\n"); + } + fclose(fp); +} + + +void print_uls_ovs(ul_resolve_t *uidx, const char *nn) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+50); + sprintf(gfa_name, "%s.integer.ovlp.log", nn); + FILE* fp = fopen(gfa_name, "w"); free(gfa_name); + if (!fp) return; + uint64_t i, k, qv, tv; ma_ug_t *ug = uidx->l1_ug; ul2ul_idx_t *ul2 = &(uidx->uovl); ul2ul_item_t *o; + for (i = 0; i < ul2->uln; ++i) { + o = get_ul_ovlp(ul2, ulg_id(*ul2, i), ulg_type(*ul2, i)); + if(!o) continue; + for (k = 0; k < o->n; k++) { + qv = i; tv = o->a[k].hid; + if(ulg_type(uidx->uovl, qv)) {//ul read + qv = ulg_id(uidx->uovl, qv); + fprintf(fp, "%.*s(id::%lu)\t%u\t%u(i::%u)\t%u(i::%u)\t%c\t", (int32_t)uidx->idx->nid.a[qv].n, uidx->idx->nid.a[qv].a, + i, uidx->idx->a[qv].rlen, o->a[k].qs, o->a[k].qs_k, o->a[k].qe, o->a[k].qe_k, "+-"[o->a[k].is_rev]); + } else {///ug node + qv = ulg_id(uidx->uovl, qv); + fprintf(fp, "utg%.6d%c(id::%lu)\t%u\t%u(i::%u)\t%u(i::%u)\t%c\t", (int32_t)qv + 1, "lc"[ug->u.a[qv].circ], + i, ug->u.a[qv].len, o->a[k].qs, o->a[k].qs_k, o->a[k].qe, o->a[k].qe_k, "+-"[o->a[k].is_rev]); + } + + if(ulg_type(uidx->uovl, tv)) {//ul read + tv = ulg_id(uidx->uovl, tv); + fprintf(fp, "%.*s(id::%u)\t%u\t%u(i::%u)\t%u(i::%u)\t", (int32_t)uidx->idx->nid.a[tv].n, uidx->idx->nid.a[tv].a, + o->a[k].hid, uidx->idx->a[tv].rlen, o->a[k].ts, o->a[k].ts_k, o->a[k].te, o->a[k].te_k); + + } else { + tv = ulg_id(uidx->uovl, tv); + fprintf(fp, "utg%.6d%c(id::%u)\t%u\t%u(i::%u)\t%u(i::%u)\t\t", (int32_t)tv + 1, "lc"[ug->u.a[tv].circ], + o->a[k].hid, ug->u.a[tv].len, o->a[k].ts, o->a[k].ts_k, o->a[k].te, o->a[k].te_k); + } + + fprintf(fp, "del::%u\tct::%u\n", o->a[k].is_del, o->a[k].is_ct); + } + } + fclose(fp); +} + + + +uint64_t gen_srt_cov_interval(uint64_t *b, uint64_t b_n) +{ + uint64_t i, m, start, end; int64_t dp, old_dp; + radix_sort_srt64(b, b + b_n); + for (i = m = 0, dp = 0, start = 0; i < b_n; ++i) { + old_dp = dp; + if (b[i]&1) --dp; + else ++dp; + + if (old_dp < 1 && dp >= 1) {///old_dp < dp, b.a[j] is qs + start = b[i]>>1; + } else if (old_dp >= 1 && dp < 1){ + end = b[i]>>1; + b[m] = start; b[m] <<= 32; b[m] += end; m++; + } + } + + return m; +} + +inline uint64_t get_remove_hifi_occ_back(ul_resolve_t *uidx, uint64_t thres, uint64_t *v_a, uint64_t v_n, asg64_v *buf) +{ + ul2ul_idx_t *idx = &(uidx->uovl); + ma_ug_t *iug = idx->i_ug, *raw = uidx->l1_ug; + uint64_t k, l, z, m, p, *raw_a, raw_n, raw_id, iug_id, iug_off, del_n, keep_ns[2], dup_raw, n_mask, pn, fn, full_del, is, ie; + uinfo_srt_warp_t *iu; uint64_t *s_a, s_n, ms, me; uinfo_srt_t *ps; + for (k = del_n = fn = 0, buf->n = dup_raw = 0; k < v_n; k++) { + iu = &(idx->cc.iug_a[v_a[k]]); ///integer unitigs + for (z = 0; z < iu->n; z++) { + raw_id = (iu->a[z].v>>1); + raw_a = idx->cc.iug_b + idx->cc.iug_idx[raw_id]; + raw_n = idx->cc.iug_idx[raw_id+1] - idx->cc.iug_idx[raw_id]; + assert(raw_n > 0); + for (m = keep_ns[0] = keep_ns[1] = 0, pn = buf->n, n_mask = 0; m < raw_n; m++) { + iug_id = raw_a[m]>>32; iug_off = (uint32_t)raw_a[m]; + if(iug->g->seq[iug_id].del) continue; + if(raw_a[m]&((uint64_t)(0x8000000000000000))) { + n_mask++; + continue; + } + if(iug_id == v_a[k] && iug_off == z) {///query itself + raw_a[m] |= ((uint64_t)(0x8000000000000000)); + p = (uint32_t)-1; p <<= 32; p += idx->cc.iug_idx[raw_id] + m; + kv_push(uint64_t, *buf, p); + } else { + if(!(idx->cc.iug_a[iug_id].a[iug_off].v&1)) { + keep_ns[0] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, keep_ns[0]); + } else { + keep_ns[1] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, keep_ns[1]); + } + } + } + assert(buf->n == pn + 1); + if(keep_ns[0] + keep_ns[1] >= raw->u.a[raw_id].n) { + keep_ns[0] = keep_ns[1] = raw->u.a[raw_id].n; + } + + is = keep_ns[0]; ie = raw->u.a[raw_id].n - keep_ns[1];///[is, ie) -> uncovered coordinates + if(ie > is) { + if(!(iu->a[z].v&1)) { + ms = 0; me = iu->a[z].n; + } else { + ms = raw->u.a[raw_id].n - iu->a[z].n; me = raw->u.a[raw_id].n; + } + if(MAX(is, ms) < MIN(ie, me)) { + del_n += MIN(ie, me) - MAX(is, ms); + buf->a[pn] <<= 32; buf->a[pn] >>= 32; buf->a[pn] |= (raw_id<<32); fn++; + if(n_mask) dup_raw = 1; + } + } + } + } + + if(del_n > thres && dup_raw) { + radix_sort_srt64(buf->a, buf->a + buf->n); del_n = 0; + for (l = 0, k = 1; k <= fn; k++) { + if(k == fn || (buf->a[k]>>32) != (buf->a[l]>>32)) { + raw_id = (buf->a[l]>>32); pn = buf->n; + raw_a = idx->cc.iug_b + idx->cc.iug_idx[raw_id]; + raw_n = idx->cc.iug_idx[raw_id+1] - idx->cc.iug_idx[raw_id]; + assert(raw_n > 0); + for (m = full_del = 0; m < raw_n; m++) { + iug_id = raw_a[m]>>32; iug_off = (uint32_t)raw_a[m]; + if(iug->g->seq[iug_id].del) continue; + if(raw_a[m]&((uint64_t)(0x8000000000000000))) { + kv_push(uint64_t, *buf, (idx->cc.iug_a[iug_id].a[iug_off].s<<1)); + kv_push(uint64_t, *buf, (idx->cc.iug_a[iug_id].a[iug_off].e<<1)+1); + if(idx->cc.iug_a[iug_id].a[iug_off].s == 0 && + idx->cc.iug_a[iug_id].a[iug_off].e == raw->u.a[raw_id].len) { + full_del = 1; break; + } + } + } + + s_a = buf->a + buf->n; s_n = buf->n - pn; + assert(s_n > 0); + + if(s_n > 2 && full_del == 0) { + s_n = gen_srt_cov_interval(s_a, s_n); + } else if(full_del) {///an interval has already cover the whole unitig + s_a[0] = raw->u.a[raw_id].len; s_n = 1; + } else {///sn == 2; + s_a[0] >>= 1; s_a[0] <<= 32; s_a[0] += (s_a[1]>>1); s_n = 1; + } + + + for (m = full_del = 0; m < raw_n && full_del < s_n; m++) { + iug_id = raw_a[m]>>32; iug_off = (uint32_t)raw_a[m]; + if(iug->g->seq[iug_id].del) continue; + if(raw_a[m]&((uint64_t)(0x8000000000000000))) continue; + ps = &(idx->cc.iug_a[iug_id].a[iug_off]); + for (z = 0; z < s_n; z++) { + if(s_a[z] == ((uint64_t)-1)) continue; + is = s_a[z]>>32; ie = (uint32_t)s_a[z]; + ms = MAX(is, ps->s); me = MIN(ie, ps->e); + if(ms >= me) continue; + ///[ms, me) is unlikely to be contained in the [is, ie) + assert(ms == is || me == ie); + if(ms == is) is = me; + else if(me == ie) ie = ms; + if(is >= ie) { + s_a[z] = ((uint64_t)-1); full_del++; + } else { + s_a[z] = is; s_a[z] <<= 32; s_a[z] += ie; + } + } + } + + for (z = 0; z < s_n; z++) { + if(s_a[z] == ((uint64_t)-1)) continue; + is = s_a[z]>>32; ie = (uint32_t)s_a[z]; + del_n += ug_occ_w(is, ie, &(raw->u.a[raw_id])); + } + if(del_n > thres) break; + l = k; buf->n = pn; + } + } + } + + for (k = 0; k < buf->n; k++) { + assert(idx->cc.iug_b[(uint32_t)buf->a[k]]&((uint64_t)(0x8000000000000000))); + idx->cc.iug_b[(uint32_t)buf->a[k]] <<= 1; idx->cc.iug_b[(uint32_t)buf->a[k]] >>= 1; + } + + + return ((del_n > thres)?0:1); +} + + +inline uint64_t get_remove_hifi_occ(ul_resolve_t *uidx, uint64_t thres, uint64_t *v_a, uint64_t v_n, asg64_v *buf, uint32_t *del_occ) +{ + ul2ul_idx_t *idx = &(uidx->uovl); + ma_ug_t *iug = idx->i_ug, *raw = uidx->l1_ug; + uint64_t k, l, z, m, p, *raw_a, raw_n, raw_id, iug_id, iug_off, del_n, keep_ns[2], del_ns[2], dup_raw, n_mask, pn, fn, is, ie; + uinfo_srt_warp_t *iu; uint64_t ms, me; + for (k = del_n = fn = 0, buf->n = dup_raw = 0; k < v_n; k++) { + iu = &(idx->cc.iug_a[v_a[k]>>1]); ///integer unitigs + for (z = 0; z < iu->n; z++) { + raw_id = (iu->a[z].v>>1); + raw_a = idx->cc.iug_b + idx->cc.iug_idx[raw_id]; + raw_n = idx->cc.iug_idx[raw_id+1] - idx->cc.iug_idx[raw_id]; + assert(raw_n > 0); + for (m = keep_ns[0] = keep_ns[1] = 0, pn = buf->n, n_mask = 0; m < raw_n; m++) { + iug_id = (raw_a[m]<<1)>>33; iug_off = (uint32_t)raw_a[m]; + // if(iug_id >= iug->g->n_seq){ + // fprintf(stderr, ">>>[M::%s::] v_a[%lu]>>1::%lu, raw_id::%lu, raw_n::%lu, m::%lu, raw_a[m]::%lu, uidx->uovl.cc.iug_b[455]::%lu, iug_id::%lu, iug_off::%lu, iug->g->n_seq::%u\n", __func__, + // k, v_a[k]>>1, raw_id, raw_n, m, raw_a[m], uidx->uovl.cc.iug_b[455], iug_id, iug_off, (uint32_t)iug->g->n_seq); + // } + if(iug->g->seq[iug_id].del) continue; + if(raw_a[m]&((uint64_t)(0x8000000000000000))) { + n_mask++; + continue; + } + if(iug_id == (v_a[k]>>1) && iug_off == z) {///query itself + raw_a[m] |= ((uint64_t)(0x8000000000000000)); + p = (uint32_t)-1; p <<= 32; p += idx->cc.iug_idx[raw_id] + m; + kv_push(uint64_t, *buf, p); + } else { + if(!(idx->cc.iug_a[iug_id].a[iug_off].v&1)) { + keep_ns[0] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, keep_ns[0]); + } else { + keep_ns[1] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, keep_ns[1]); + } + } + } + assert(buf->n == pn + 1); + if(keep_ns[0] + keep_ns[1] >= raw->u.a[raw_id].n) { + keep_ns[0] = keep_ns[1] = raw->u.a[raw_id].n; + } + + is = keep_ns[0]; ie = raw->u.a[raw_id].n - keep_ns[1];///[is, ie) -> uncovered coordinates + if(ie > is) { + if(!(iu->a[z].v&1)) { + ms = 0; me = iu->a[z].n; + } else { + ms = raw->u.a[raw_id].n - iu->a[z].n; me = raw->u.a[raw_id].n; + } + if(MAX(is, ms) < MIN(ie, me)) { + del_n += MIN(ie, me) - MAX(is, ms); + buf->a[pn] <<= 32; buf->a[pn] >>= 32; buf->a[pn] |= (raw_id<<32); fn++; + if(n_mask) dup_raw = 1; + } + } + } + } + + if(del_n > thres && dup_raw) { + radix_sort_srt64(buf->a, buf->a + buf->n); del_n = 0; + for (l = 0, k = 1; k <= fn; k++) { + if(k == fn || (buf->a[k]>>32) != (buf->a[l]>>32)) { + raw_id = (buf->a[l]>>32); + raw_a = idx->cc.iug_b + idx->cc.iug_idx[raw_id]; + raw_n = idx->cc.iug_idx[raw_id+1] - idx->cc.iug_idx[raw_id]; + assert(raw_n > 0); + for (m = del_ns[0] = del_ns[1] = keep_ns[0] = keep_ns[1] = 0; m < raw_n; m++) { + iug_id = (raw_a[m]<<1)>>33; iug_off = (uint32_t)raw_a[m]; + if(iug->g->seq[iug_id].del) continue; + if(raw_a[m]&((uint64_t)(0x8000000000000000))) { + if(!(idx->cc.iug_a[iug_id].a[iug_off].v&1)) { + del_ns[0] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, del_ns[0]); + } else { + del_ns[1] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, del_ns[1]); + } + } else { + if(!(idx->cc.iug_a[iug_id].a[iug_off].v&1)) { + keep_ns[0] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, keep_ns[0]); + } else { + keep_ns[1] = MAX(idx->cc.iug_a[iug_id].a[iug_off].n, keep_ns[1]); + } + } + } + assert(del_ns[0] + del_ns[1] > 0); + if(keep_ns[0] + keep_ns[1] >= raw->u.a[raw_id].n) { + keep_ns[0] = keep_ns[1] = raw->u.a[raw_id].n; + } + + + is = keep_ns[0]; ie = raw->u.a[raw_id].n - keep_ns[1];///[is, ie) -> uncovered coordinates + if(ie > is) { + if(del_ns[0] + del_ns[1] >= raw->u.a[raw_id].n) { + del_n += ie - is; + } else { + ms = 0; me = del_ns[0]; + if(ms < me && MAX(is, ms) < MIN(ie, me)) { + del_n += MIN(ie, me) - MAX(is, ms); + } + + ms = raw->u.a[raw_id].n - del_ns[1]; me = raw->u.a[raw_id].n; + if(ms < me && MAX(is, ms) < MIN(ie, me)) { + del_n += MIN(ie, me) - MAX(is, ms); + } + } + } + if(del_n > thres) break; + l = k; + } + } + } + + for (k = 0; k < buf->n; k++) { + assert(idx->cc.iug_b[(uint32_t)buf->a[k]]&((uint64_t)(0x8000000000000000))); + idx->cc.iug_b[(uint32_t)buf->a[k]] <<= 1; idx->cc.iug_b[(uint32_t)buf->a[k]] >>= 1; + } + // fprintf(stderr, "*[M::%s::] del_n::%lu\n", __func__, del_n); + if(del_occ) *del_occ = del_n; + return ((del_n > thres)?0:1); +} +#define bg_correct (1) +#define bg_wrong (2) +#define bg_ambiguous (3) +#define bg_unavailable ((uint32_t)-1) +inline uint32_t get_bg_flag(ul_resolve_t *uidx, uint32_t v, uint32_t w) +{ + asg_t *g = uidx->uovl.bg.bg; asg_arc_t *av; uint32_t k, nv; + if(g->seq[v>>1].del || g->seq[w>>1].del) return bg_unavailable; + + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (k = 0; k < nv; k++) { + if(av[k].v == w) break; + } + if(k >= nv) return bg_unavailable; + if(av[k].ou == 3) return bg_correct; + if(av[k].ou == 2) return bg_wrong; + return bg_ambiguous; +} + +inline void get_bridges(ul_resolve_t *uidx, uint64_t *v_a, uint64_t v_n, uint32_t *w_occ, uint32_t *am_occ) +{ + ul_bg_t *bg = &(uidx->uovl.bg); uint64_t k, w, am, l; uint32_t uv, uw, bv, bw; + for (k = w = am = 0, uv = uw = (uint32_t)-1; k < v_n; k++) { + w += bg->w_n[v_a[k]>>1]; am += bg->a_n[v_a[k]>>1]; uw = v_a[k]; + if(uv != (uint32_t)-1) { + bv = uidx->uovl.cc.iug_a[uv>>1].a[((uv&1)?(0):(uidx->uovl.cc.iug_a[uv>>1].n-1))].v; if(uv&1) bv ^= 1; + bw = uidx->uovl.cc.iug_a[uw>>1].a[((uw&1)?(uidx->uovl.cc.iug_a[uw>>1].n-1):(0))].v; if(uw&1) bw ^= 1; + if((ulg_type(uidx->uovl, (bv>>1))) && (ulg_type(uidx->uovl, (bw>>1)))) { + l = get_bg_flag(uidx, bv, bw); + if(l == bg_wrong) w++; + if(l == bg_ambiguous) am++; + } + } + uv = uw; + } + if(w_occ) *w_occ = w; + if(am_occ) *am_occ = am; +} + +static inline void ulg_seq_del(ma_ug_t *ug, uint32_t s) +{ + uint32_t k; asg_t *g = ug->g; + g->seq[s].del = 1; + for (k = 0; k < 2; ++k) { + uint32_t i, v = s<<1 | k; + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + for (i = 0; i < nv; ++i) { + av[i].del = 1; + asg_arc_del(g, av[i].v^1, v^1, 1); + } + } + free(ug->u.a[s].a); memset(&(ug->u.a[s]), 0, sizeof(ug->u.a[s])); +} + + +uint32_t ulg_arc_cut_tips(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t max_ext, uint32_t max_ext_hifi, uint32_t is_double_check, asg64_v *in, asg64_v *ib) +{ + asg64_v tx = {0,0,0}, tb = {0,0,0}, *b = NULL, *ub = NULL; asg_t *g = ug->g; + uint32_t n_vtx = g->n_seq<<1, v, w, i, k, cnt = 0, nv, kv, pb, w_occ, a_occ, ul_occ, del_occ, is_telo; + asg_arc_t *av = NULL; uint64_t lw; + b = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); + for (v = 0, b->n = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + + av = asg_arc_a(g, v^1); nv = asg_arc_n(g, v^1); + for (i = kv = 0; i < nv; i++) { + if (av[i].del) continue; + kv++; break; + } + + if(kv) continue; + // kv = ug->u.a[v>>1].n;/// get_ul_occ(uidx, v>>1); + get_iug_u_raw_occ(uidx, v>>1, &ul_occ, NULL); kv = ul_occ; + is_telo = 0; if(uidx->uovl.telo && uidx->uovl.telo[v>>1]) is_telo = 1; + for (i = 0, w = v; i < max_ext; i++) { + if(asg_end(g, w^1, &lw, NULL)!=0) break; + w = (uint32_t)lw; + // kv += ug->u.a[w>>1].n; ///get_ul_occ(uidx, w>>1); + get_iug_u_raw_occ(uidx, w>>1, &ul_occ, NULL); kv += ul_occ; + if(uidx->uovl.telo && uidx->uovl.telo[w>>1]) is_telo = 1; + } + + if((kv <= max_ext) && (!is_telo)) kv_push(uint64_t, *b, (((uint64_t)kv)<<32)|v); + } + + radix_sort_srt64(b->a, b->a + b->n); + + for (k = 0; k < b->n; k++) { + v = (uint32_t)(b->a[k]); + if (g->seq[v>>1].del) continue; + + av = asg_arc_a(g, v^1); nv = asg_arc_n(g, v^1); + for (i = kv = 0; i < nv; i++) { + if (av[i].del) continue; + kv++; break; + } + + if(kv) continue; + + pb = b->n; kv_push(uint64_t, *b, v); + // kv = ug->u.a[v>>1].n;/// get_ul_occ(uidx, v>>1); + get_iug_u_raw_occ(uidx, v>>1, &ul_occ, NULL); kv = ul_occ; + is_telo = 0; if(uidx->uovl.telo && uidx->uovl.telo[v>>1]) is_telo = 1; + for (i = 0, w = v; i < max_ext; i++) { + if(asg_end(g, w^1, &lw, NULL)!=0) break; + w = (uint32_t)lw; kv_push(uint64_t, *b, w); + // kv += ug->u.a[w>>1].n; ///get_ul_occ(uidx, w>>1); + get_iug_u_raw_occ(uidx, w>>1, &ul_occ, NULL); kv += ul_occ; + if(uidx->uovl.telo && uidx->uovl.telo[w>>1]) is_telo = 1; + } + + + + if((!is_telo) && (kv <= max_ext) && (get_remove_hifi_occ(uidx, max_ext_hifi, b->a + pb, b->n - pb, ub, &del_occ))) { + // fprintf(stderr, "*[M::%s::] k::%u, v>>1::%u, v&1::%u, kv::%u, max_ext::%u, max_ext_hifi::%u\n\n", + // __func__, k, v>>1, v&1, kv, max_ext, max_ext_hifi); + if(is_double_check) get_bridges(uidx, b->a + pb, b->n - pb, &w_occ, &a_occ); + if(is_double_check == 0 || w_occ > 0 || a_occ > 0 || kv == 0 || del_occ == 0) { + for (i = pb; i < b->n; i++) ulg_seq_del(ug, (b->a[i]>>1)); + cnt += b->n - pb; + } + } + b->n = pb; + } + + // stats_sysm(g); + if(!in) {free(tx.a);} if(!ib) {free(tb.a);} + if (cnt > 0) asg_cleanup(g); + + return cnt; +} + +uint32_t is_het_ulg_edge(ul_resolve_t *uidx, uint32_t uv, uint32_t uw) +{ + ma_ug_t *iug = uidx->uovl.i_ug; bubble_type *bub = uidx->bub; uint32_t qid, tid; + qid = iug->u.a[uv>>1].a[((uv&1)?(0):(iug->u.a[uv>>1].n-1))]>>33; + tid = iug->u.a[uw>>1].a[((uw&1)?(iug->u.a[uw>>1].n-1):(0))]>>33; + + if(!ulg_type(uidx->uovl, qid)) return (!IF_HOM(ulg_id(uidx->uovl, qid), *bub)); + if(!ulg_type(uidx->uovl, tid)) return (!IF_HOM(ulg_id(uidx->uovl, tid), *bub)); + + if(uidx->uovl.item_idx[qid] == (uint32_t)-1) return (uint32_t)-1; + ul2ul_item_t *o = &(uidx->uovl.a[uidx->uovl.item_idx[qid]]); + ul2ul_t *z; uint64_t k, n_hom, n_het; ul_str_t *str; + for (k = 0, z = NULL; k < o->cn; k++) { + if(o->a[k].hid != tid) continue; + z = &(o->a[k]); + break; + } + if(!z) return (uint32_t)-1; + str = &(uidx->pstr.str.a[ulg_id(uidx->uovl, qid)]); + + for (k = z->qs_k, n_hom = n_het = 0; k < z->qe_k; k++) { + if(IF_HOM((((uint32_t)str->a[k])>>1), *bub)) { + n_hom++; + } else { + n_het++; break; + } + } + + if(n_het) return 1; + if(n_hom) return 0; + return (uint32_t)-1; +} + + +int32_t usg_topocut_aux(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t v, int32_t max_ext, int32_t max_ext_hifi, asg64_v *b, asg64_v *ub) +{ + int32_t n_ext; asg_arc_t *av; uint32_t w = v, nv, i, kv, ul_occ, pn = b->n; + for (n_ext = 0; n_ext < max_ext; v = w) { + av = asg_arc_a(ug->g, v^1); nv = asg_arc_n(ug->g, v^1); + for (i = kv = 0; i < nv && kv <= 1; i++) { + if (av[i].del) continue; + kv++; + } + if(kv!=1) break; + get_iug_u_raw_occ(uidx, v>>1, &ul_occ, NULL); n_ext += ul_occ; kv_push(uint64_t, *b, v); + + av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); + for (i = kv = 0; i < nv && kv <= 1; i++) { + if (av[i].del) continue; + kv++; w = av[i].v; + } + if(kv!=1) break; + } + + if(n_ext < max_ext) { + if(get_remove_hifi_occ(uidx, max_ext_hifi, b->a + pn, b->n - pn, ub, NULL)) { + b->n = pn; + return 1; + } + } + + b->n = pn; + return 0; +} + +uint32_t ulg_arc_cut_length(ul_resolve_t *uidx, ma_ug_t *ug, int32_t max_ext, uint32_t max_ext_hifi, +float len_rat, uint32_t is_trio, uint32_t topo_level, uint32_t hom_check, uint32_t *max_drop_len, asg64_v *in, asg64_v *ib) +{ + asg64_v tx = {0,0,0}, tb = {0,0,0}, *b = NULL, *ub = NULL; asg_t *g = ug->g; + uint32_t v, w, i, k, kv, kw, nv, nw, cnt = 0, n_vtx = g->n_seq<<1, n_het, n_hom, ff, ol_max, mm_ol, to_del; + asg_arc_t *av = NULL, *aw = NULL, *ve = NULL, *we = NULL, *vl_max = NULL, *wl_max = NULL; + + b = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); + for (v = b->n = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + if(g->seq_vis[v] == 0) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if (nv < 2) continue; + + for (i = kv = 0; i < nv && kv < 2; ++i) { + if(av[i].del) continue; + kv++; + } + if(kv < 2) continue; + if(hom_check) { + for (i = n_het = n_hom = 0; i < nv; ++i) { + if(av[i].del) continue; + ff = is_het_ulg_edge(uidx, av[i].ul>>32, av[i].v); assert(ff != (uint32_t)-1); + if(ff) n_het++; + else n_hom++; + if(n_het > 0 && n_hom > 0) break; + } + if(n_het == 0 || n_hom == 0) continue; + } + + for (i = 0; i < nv; ++i) { + if(av[i].del) continue; + kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); + } + } + } + + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + if(g->arc[(uint32_t)b->a[k]].del) continue; + v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; + if(g->seq[v>>1].del || g->seq[w>>1].del) continue; + nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); + av = asg_arc_a(g, v); aw = asg_arc_a(g, w); + if(nv<=1 && nw <= 1) continue; + if(hom_check) { + ff = is_het_ulg_edge(uidx, g->arc[(uint32_t)b->a[k]].ul>>32, g->arc[(uint32_t)b->a[k]].v); + assert(ff != (uint32_t)-1); + if(ff) continue; + } + + ve = &(g->arc[(uint32_t)b->a[k]]); + for (i = 0; i < nw; ++i) { + if (aw[i].v == (v^1)) { + we = &(aw[i]); + break; + } + } + mm_ol = MIN(ve->ol, we->ol); ///ve and we are hom edges + + for (i = kv = ol_max = 0, vl_max = NULL; i < nv; ++i) { + if(av[i].del) continue; + kv++; + if(hom_check) { + ff = is_het_ulg_edge(uidx, av[i].ul>>32, av[i].v); assert(ff != (uint32_t)-1); + if(!ff) continue;///vl_max must be a het edge + } + if(ol_max < av[i].ol) ol_max = av[i].ol, vl_max = &(av[i]); + } + if (kv < 1 || (!vl_max)) continue; + if (kv >= 2) { + if (mm_ol > ol_max*len_rat) continue; + } + + for (i = kw = ol_max = 0, wl_max = NULL; i < nw; ++i) { + if(aw[i].del) continue; + kw++; + if(hom_check) { + ff = is_het_ulg_edge(uidx, aw[i].ul>>32, aw[i].v); assert(ff != (uint32_t)-1); + if(!ff) continue;///wl_max must be a het edge + } + if(ol_max < aw[i].ol) ol_max = aw[i].ol, wl_max = &(aw[i]); + } + if (kw < 1 || (!wl_max)) continue; + if (kw >= 2) { + if (mm_ol > ol_max*len_rat) continue; + } + + if (kv <= 1 && kw <= 1) continue; + + to_del = 0; + if(topo_level == 0) { + to_del = 1; + } else if(topo_level == 2) { + if (kv > 1 && kw > 1) to_del = 1; + } else { + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (usg_topocut_aux(uidx, ug, w^1, max_ext, max_ext_hifi, b, ub)) to_del = 1; + } else if (kv == 1) { + if (usg_topocut_aux(uidx, ug, v^1, max_ext, max_ext_hifi, b, ub)) to_del = 1; + } + } + + if (to_del) { + ve->del = we->del = 1, ++cnt; + } + } + + + if(!in) {free(tx.a);} if(!ib) {free(tb.a);} + if (cnt > 0) asg_cleanup(g); + + return cnt; +} + +uint32_t is_ul_edge(ul_resolve_t *uidx, uint32_t uv, uint32_t uw) +{ + ma_ug_t *iug = uidx->uovl.i_ug; uint32_t qid, tid; + qid = iug->u.a[uv>>1].a[((uv&1)?(0):(iug->u.a[uv>>1].n-1))]>>33; + tid = iug->u.a[uw>>1].a[((uw&1)?(iug->u.a[uw>>1].n-1):(0))]>>33; + if((qid != tid) && (!ulg_type(uidx->uovl, qid)) && (!ulg_type(uidx->uovl, tid))) return 0; + return 1; +} + +uint32_t ulg_arc_cut_occ(ul_resolve_t *uidx, ma_ug_t *ug, int32_t max_ext, uint32_t max_ext_hifi, +uint32_t is_trio, uint32_t topo_level, asg64_v *in, asg64_v *ib) +{ + asg_t *g = ug->g; asg64_v tx = {0,0,0}, tb = {0,0,0}, *b = NULL, *ub = NULL; + uint32_t v, w, i, z, kv, kw, nv, nw, cnt = 0, n_vtx = g->n_seq<<1, to_del, n_ul, n_ug; + asg_arc_t *av, *aw; b = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); + + for (v = b->n = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if (nv < 2) continue; + + for (i = n_ul = n_ug = kv = 0; i < nv; ++i) { + if(av[i].del) continue; + if(is_ul_edge(uidx, av[i].ul>>32, av[i].v)) n_ul++; + else n_ug++; + kv++; + } + if(n_ul == 0 || n_ug == 0 || kv < 2) continue; + + for (i = 0; i < nv; ++i) { + if(av[i].del) continue; + if(is_ul_edge(uidx, av[i].ul>>32, av[i].v)) continue; + w = av[i].v^1; if(g->seq[w>>1].del) continue; + kw = get_arcs(g, w, NULL, 0); + if (kv <= 1 && kw <= 1) continue; + + to_del = 0; + if(topo_level == 0) { + to_del = 1; + } else if(topo_level == 2) { + if (kv > 1 && kw > 1) to_del = 1; + } else { + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (usg_topocut_aux(uidx, ug, w^1, max_ext, max_ext_hifi, b, ub)) to_del = 1; + } else if (kv == 1) { + if (usg_topocut_aux(uidx, ug, v^1, max_ext, max_ext_hifi, b, ub)) to_del = 1; + } + } + + if (to_del) { + ++cnt; av[i].del = 1; + aw = asg_arc_a(g, w); nw = asg_arc_n(g, w); + for (z = 0; z < nw; ++z) { + if (aw[z].v == (v^1)) { + aw[z].del = 1; + break; + } + } + assert(z < nw); + } + } + } + + if(!in) {free(tx.a);} if(!ib) {free(tb.a);} + if (cnt > 0) asg_cleanup(g); + + return cnt; +} + + +uint32_t get_ul_path_info(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t s, uint32_t *e, uint32_t *occ, +uint32_t *ul_cnt, uint32_t *bridge_w, uint32_t *bridge_am, asg64_v *b) +{ + uint32_t v = s, w = (uint32_t)-1, kv, kw, uv = (uint32_t)-1, uw = (uint32_t)-1, bv, bw, l; + ul_bg_t *bg = &(uidx->uovl.bg); + if(occ) {(*occ) = 0;} if(ul_cnt) {(*ul_cnt) = 0;} if(bridge_w) {(*bridge_w) = 0;} if(bridge_am) {(*bridge_am) = 0;} + + while (1) { + if(occ) (*occ)++; + kv = get_arcs(ug->g, v, &w, 1); + if(e) (*e) = v; + + ///if(b) kv_push(uint32_t, b->b, v>>1); + if(b) kv_push(uint64_t, *b, v); + if(ul_cnt) (*ul_cnt) += get_ul_occ(uidx, v>>1); + if(bridge_w || bridge_am) { + uw = v; + if(bridge_w) (*bridge_w) += bg->w_n[v>>1]; + if(bridge_am) (*bridge_am) += bg->a_n[v>>1]; + if(uv != (uint32_t)-1) { + bv = uidx->uovl.cc.iug_a[uv>>1].a[((uv&1)?(0):(uidx->uovl.cc.iug_a[uv>>1].n-1))].v; if(uv&1) bv ^= 1; + bw = uidx->uovl.cc.iug_a[uw>>1].a[((uw&1)?(uidx->uovl.cc.iug_a[uw>>1].n-1):(0))].v; if(uw&1) bw ^= 1; + if((ulg_type(uidx->uovl, (bv>>1))) && (ulg_type(uidx->uovl, (bw>>1)))) { + l = get_bg_flag(uidx, bv, bw); + if(l == bg_wrong && bridge_w) (*bridge_w)++; + if(l == bg_ambiguous && bridge_am) (*bridge_am)++; + } + } + uv = uw; + } + + if(kv == 0) return END_TIPS; + if(kv == 2) return TWO_OUTPUT; + if(kv > 2) return MUL_OUTPUT; + w = ug->g->arc[w].v; + ///up to here, kv=1 + ///kw must >= 1 + kw = get_arcs(ug->g, w^1, NULL, 0); + v = w; + + if(kw == 2) return TWO_INPUT; + if(kw > 2) return MUL_INPUT; + if(v == s) return LOOP; + } + + return LONG_TIPS; +} + +#define ul_path_w(ul_cnt, bridge_w, bridge_am) (((bridge_w)+(bridge_w))==0?((uint32_t)-1):((ul_cnt)/((bridge_w)+(bridge_w)))) + + +uint32_t usg_bridge_topocut_aux(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t v, uint32_t max_ext, uint32_t max_ext_hifi, uint32_t topo_level, uint32_t double_check, asg64_v *b, asg64_v *ub) +{ + uint32_t k, z, bn = b->n, w, bridge_w = 1, bridge_am = 1, raw_ul, ul, del_occ, is_del = 0, kk; + asg_arc_t *av; uint32_t nv; + get_ul_path_info(uidx, ug, v, &w, NULL, NULL, (double_check?(&bridge_w):(NULL)), + (double_check?(&bridge_am):(NULL)), b); + for (k = bn, raw_ul = 0; k < b->n; k++) { + get_iug_u_raw_occ(uidx, b->a[k]>>1, &ul, NULL); raw_ul += ul; + } + + if(raw_ul <= max_ext && get_remove_hifi_occ(uidx, max_ext_hifi, b->a + bn, b->n - bn, ub, &del_occ)) { + b->n = bn; + if(topo_level == 0) { + is_del = 1; + } else if(double_check == 0 || bridge_w > 0 || bridge_am > 0 || raw_ul == 0 || del_occ == 0) { + av = asg_arc_a(ug->g, v^1); nv = asg_arc_n(ug->g, v^1); + for (z = 0; z < nv; z++) { + if(av[z].del) continue; + kk = get_arcs(ug->g, av[z].v^1, NULL, 0); + if(topo_level == 2 && kk > 1) continue; + ///==1, might be a tip + if (topo_level == 1 && usg_topocut_aux(uidx, ug, av[z].v, max_ext, max_ext_hifi, b, ub)) continue; + break; + } + + if(z >= nv) { + av = asg_arc_a(ug->g, w); nv = asg_arc_n(ug->g, w); + for (z = 0; z < nv; z++) { + if(av[z].del) continue; + kk = get_arcs(ug->g, av[z].v^1, NULL, 0); + if(topo_level == 2 && kk > 1) continue; + ///==1, might be a tip + if (topo_level == 1 && usg_topocut_aux(uidx, ug, av[z].v, max_ext, max_ext_hifi, b, ub)) continue; + break; + } + + if(z >= nv) is_del = 1; + } + } + } + b->n = bn; + + return is_del; +} + +uint32_t ulg_arc_cut_bridge(ul_resolve_t *uidx, ma_ug_t *ug, int32_t max_ext, uint32_t max_ext_hifi, +float len_rat, uint32_t is_trio, uint32_t topo_level, uint32_t *max_drop_len, asg64_v *in, asg64_v *ib) +{ + asg64_v tx = {0,0,0}, tb = {0,0,0}, *b = NULL, *ub = NULL; asg_t *g = ug->g; + uint32_t v, w, i, k, kv, nv, cnt = 0, n_vtx = g->n_seq<<1, ff, ol_max, ul_max, mm_ol; + asg_arc_t *av, *ve, *vl_max; uint32_t ul_cnt, bridge_w, bridge_am, pb; + // fprintf(stderr, "+++[M::%s::] idx->cc.iug_b[455]::%lu\n", __func__, uidx->uovl.cc.iug_b[455]); + b = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); + for (v = b->n = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + if(g->seq_vis[v] == 0) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if (nv < 2) continue; + + for (i = kv = 0; i < nv && kv < 2; ++i) { + if(av[i].del) continue; + kv++; + } + if(kv < 2) continue; + + for (i = 0; i < nv; ++i) { + if(av[i].del) continue; + get_ul_path_info(uidx, ug, av[i].v, NULL, NULL, &ul_cnt, &bridge_w, &bridge_am, NULL); + ff = ul_path_w(ul_cnt, bridge_w, bridge_am); + // if((v>>1) == 5) { + // fprintf(stderr, "+[M::%s::] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, ul_cnt::%u, bridge_w::%u, bridge_am::%u, ff::%u\n", __func__, + // v>>1, v&1, av[i].v>>1, av[i].v&1, ul_cnt, bridge_w, bridge_am, ff); + // } + kv_push(uint64_t, *b, (((uint64_t)ff)<<32) | ((uint64_t)(av-g->arc+i))); + } + } + } + + // fprintf(stderr, "---[M::%s::] idx->cc.iug_b[455]::%lu\n", __func__, uidx->uovl.cc.iug_b[455]); + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + if(g->arc[(uint32_t)b->a[k]].del) continue; + v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; + if(g->seq[v>>1].del || g->seq[w>>1].del) continue; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + if(nv<=1 && asg_arc_n(g, w) <= 1) continue; + if(get_arcs(ug->g, w, NULL, 0) != 1) continue; + + ve = &(g->arc[(uint32_t)b->a[k]]); + get_ul_path_info(uidx, ug, ve->v, NULL, NULL, &ul_cnt, &bridge_w, &bridge_am, NULL); + ff = ul_path_w(ul_cnt, bridge_w, bridge_am); + if(ff == (uint32_t)-1) continue; + mm_ol = ff; + + for (i = kv = ol_max = ul_max = 0, vl_max = NULL; i < nv; ++i) { + if(av[i].del) continue; + kv++; + get_ul_path_info(uidx, ug, av[i].v, NULL, NULL, &ul_cnt, &bridge_w, &bridge_am, NULL); + ff = ul_path_w(ul_cnt, bridge_w, bridge_am); + if((ol_max < ff) || (ol_max == ff && ul_max < ul_cnt)) { + ol_max = ff; ul_max = ul_cnt; vl_max = &(av[i]); + } + } + + // if((v>>1) == 5) { + // fprintf(stderr, "***[M::%s::] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, ul_cnt::%u, bridge_w::%u, bridge_am::%u, ff::%u, mm_ol::%u, ol_max::%u, kv::%u\n", __func__, + // v>>1, v&1, w>>1, w&1, ul_cnt, bridge_w, bridge_am, ff, mm_ol, ol_max, kv); + // } + + if (kv <= 1 || (!vl_max)) continue; + if (kv >= 2) { + if (mm_ol > ol_max*len_rat) continue; + } + + // if((v>>1) == 5) { + // fprintf(stderr, "###[M::%s::] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, ul_cnt::%u, bridge_w::%u, bridge_am::%u, ff::%u, mm_ol::%u, ol_max::%u\n", __func__, + // v>>1, v&1, w>>1, w&1, ul_cnt, bridge_w, bridge_am, ff, mm_ol, ol_max); + // } + + + if(usg_bridge_topocut_aux(uidx, ug, ve->v, max_ext, max_ext_hifi, topo_level, 1, b, ub)) { + pb = b->n; + get_ul_path_info(uidx, ug, ve->v, NULL, NULL, NULL, NULL, NULL, b); + for (i = pb; i < b->n; i++) ulg_seq_del(ug, (b->a[i]>>1)); + cnt += b->n - pb; b->n = pb; + } + } + + + if(!in) {free(tx.a);} if(!ib) {free(tb.a);} + if (cnt > 0) asg_cleanup(g); + return cnt; +} + + + +ul2ul_t* get_ul_spec_ovlp(ul2ul_idx_t *z, uint64_t qid, uint64_t tid) +{ + // uint64_t x = (is_qul?(qid):(qid+z->uln)); + if(z->item_idx[qid] == (uint32_t)-1) return NULL; + ul2ul_item_t *o = &(z->a[z->item_idx[qid]]); uint64_t k; + for (k = 0; k < o->cn; k++) { + if(o->a[k].hid != tid) continue; + return &(o->a[k]); + } + return NULL; +} + +uint64_t gen_ug_integer_seq_on_fly(ul_resolve_t *uidx, uint64_t *u_a, uint64_t u_n, asg64_v *res) +{ + ul2ul_idx_t *idx = &(uidx->uovl); ma_ug_t *raw = uidx->l1_ug; + uint64_t k, rn = res->n, nn, u_rev, uv, uw, bv, bw, is_bv_ul, is_bw_ul, x; int64_t z, zn; + ma_ug_t *iug = idx->i_ug; uinfo_srt_warp_t *seq; ul2ul_t *m; + for (k = 0; k < u_n; k++) { + seq = &(idx->cc.iug_a[u_a[k]>>1]); u_rev = u_a[k]&1; + // if(u_n == 6 && u_a[0] == 37683 && u_a[5] == 45894) { + // fprintf(stderr, "\n[M::%s::] k::%lu, u_a[k]>>1::%lu, u_a[k]&1::%lu\n", __func__, k, u_a[k]>>1, u_a[k]&1); + // for (z = 0, zn = seq->n; z < zn; z++) { + // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u\n", __func__, seq->a[z].v>>1, seq->a[z].v&1); + // } + // } + if(k > 0) { + uv = u_a[k-1]; uw = u_a[k]; + bv = iug->u.a[uv>>1].a[((uv&1)?(0):(iug->u.a[uv>>1].n-1))]>>32; if(uv&1) bv ^= 1; //pre + bw = iug->u.a[uw>>1].a[((uw&1)?(iug->u.a[uw>>1].n-1):(0))]>>32; if(uw&1) bw ^= 1; //current + is_bv_ul = ulg_type((*idx), (bv>>1)); is_bw_ul = ulg_type((*idx), (bw>>1)); + if(is_bw_ul) { + m = get_ul_spec_ovlp(idx, bv>>1, bw>>1); + assert(m && (!m->is_del)); + nn = res->n + seq->n - (m->te_k - m->ts_k); + kv_resize(uint64_t, *res, nn); + nn = m->te_k - m->ts_k; ///skipped length + zn = seq->n; + // fprintf(stderr, "[M::%s::] bv>>1::%lu, bv&1::%lu, bw>>1::%lu, bw&1::%lu, m->qs_k::%u, m->qe_k::%u, m->ts_k::%u, m->te_k::%u\n", __func__, + // bv>>1, bv&1, bw>>1, bw&1, m->qs_k, m->qe_k, m->ts_k, m->te_k); + if(!u_rev) { + ///debug + for (z = 0; z < ((int64_t)nn); z++) { + // if(res->a[res->n-nn+z] != seq->a[z].v) { + // fprintf(stderr, "****[M::%s::] k::%lu, z::%ld, nn::%lu, res->n::%u, res->v>>1::%lu, res->v&1::%lu, seq->a[z].v>>1::%u, seq->a[z].v&1::%u\n", + // __func__, k, z, nn, (uint32_t)res->n, res->a[res->n-nn+z]>>1, res->a[res->n-nn+z]&1, seq->a[z].v>>1, seq->a[z].v&1); + // } + assert(res->a[res->n-nn+z] == seq->a[z].v); + } + + for (z = nn; z < zn; z++) { + res->a[res->n++] = seq->a[z].v; + } + } else { + ///debug + for (z = zn - 1; z >= zn - ((int64_t)nn); z--) { + // fprintf(stderr, "[M::%s::z->%ld::idx->%ld] nn::%lu, zn::%ld, res->n::%ld, res>>1::%lu, res&1::%lu, seq>>1::%u, seq&1::%u\n", + // __func__, z, (int64_t)(res->n-nn+(zn-1-z)), nn, zn, (int64_t)(res->n), res->a[res->n-nn+(zn-1-z)]>>1, res->a[res->n-nn+(zn-1-z)]&1, seq->a[z].v>>1, seq->a[z].v&1); + assert(res->a[res->n-nn+(zn-1-z)] == (seq->a[z].v^1)); + } + + for (z = zn - 1 - ((int64_t)nn); z >= 0; z--) { + res->a[res->n++] = seq->a[z].v^1; + } + } + } else { + x = ulg_id(uidx->uovl, (bw>>1)); x <<= 1; x += (bw&1); + if(!is_bv_ul) {///if previous ul is also a raw utg node + assert(get_specfic_edge(raw->g, res->a[res->n-1], x)); + } else { + // assert(((res->a[res->n-1].v) == x)); + if(((res->a[res->n-1]) == x)) { + res->n--; + } else { + assert(get_specfic_edge(raw->g, res->a[res->n-1], x)); + } + } + nn = res->n + seq->n; zn = seq->n; + kv_resize(uint64_t, *res, nn); + if(!u_rev) { + for (z = 0; z < zn; z++) { + res->a[res->n++] = seq->a[z].v; + } + } else { + for (z = zn - 1; z >= 0; z--) { + res->a[res->n++] = seq->a[z].v^1; + } + } + } + } else { + nn = res->n + seq->n; zn = seq->n; + kv_resize(uint64_t, *res, nn); + if(!u_rev) { + for (z = 0; z < zn; z++) { + // fprintf(stderr, ">+<[M::%s::res->n->%ld] a>>1::%u, a&1::%u\n", + // __func__, (int64_t)res->n, seq->a[z].v>>1, seq->a[z].v&1); + res->a[res->n++] = seq->a[z].v; + } + } else { + for (z = zn - 1; z >= 0; z--) { + // fprintf(stderr, ">-<[M::%s::res->n->%ld] a>>1::%u, a&1::%u\n", + // __func__, (int64_t)res->n, seq->a[z].v>>1, (seq->a[z].v^1)&1); + res->a[res->n++] = seq->a[z].v^1; + } + } + } + } + + return res->n - rn; +} + +uint32_t get_integer_seq_ovlps(ul_resolve_t *uidx, uint64_t *p_a, int64_t p_n, int64_t match_bound, uint64_t skip_hom, asg64_v *res, uint64_t *r_w) +{ + ul_str_idx_t *str_idx = &(uidx->pstr); uint32_t v = p_a[match_bound]; uc_block_t *xi; + uint64_t *hid_a, hid_n, z, vz, ps, pe, ww[2], sw[2], occ; ul_str_t *str; int64_t s_n, s, p; + bubble_type *bub = uidx->bub; + + hid_a = str_idx->occ.a + str_idx->idx.a[v>>1]; + hid_n = str_idx->idx.a[(v>>1)+1] - str_idx->idx.a[v>>1]; + for (z = ww[0] = ww[1] = (*r_w) = occ = 0; z < hid_n; z++) { + str = &(str_idx->str.a[hid_a[z]>>32]); s_n = str->cn; + if(s_n < 2) continue; + vz = (uint32_t)(str->a[(uint32_t)hid_a[z]]); + assert((v>>1) == (vz>>1)); ps = pe = (uint64_t)-1; + sw[0] = sw[1] = 0; + if(v == vz) { + s = ((uint32_t)hid_a[z]) + 1; p = match_bound + 1; + for (; (s < s_n) && (p < p_n) && ((uint32_t)(str->a[s]) == p_a[p]); s++, p++) { + xi = &(uidx->idx->a[hid_a[z]>>32].bb.a[str->a[s]>>32]); + assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[s])); + if(skip_hom && IF_HOM(xi->hid, *bub)) continue; + sw[1] += ug_occ_w(xi->ts, xi->te, &(uidx->l1_ug->u.a[xi->hid])); + } + if(s < s_n && p < p_n) continue; + if(p <= match_bound + 1) continue;///bridging the two sides of the breakpoint + if(sw[1] == 0) continue; + pe = p; + + s = (uint32_t)hid_a[z]; p = match_bound; + for (; (s >= 0) && (p >= 0) && ((uint32_t)(str->a[s]) == p_a[p]); s--, p--) { + xi = &(uidx->idx->a[hid_a[z]>>32].bb.a[str->a[s]>>32]); + assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[s])); + if(skip_hom && IF_HOM(xi->hid, *bub)) continue; + sw[0] += ug_occ_w(xi->ts, xi->te, &(uidx->l1_ug->u.a[xi->hid])); + } + assert(p < match_bound); + if(s >= 0 && p >= 0) continue; + if(sw[0] == 0) continue; + ps = p + 1; + } else { + s = ((int32_t)((uint32_t)hid_a[z]))-1; p = match_bound + 1; + for (; (s >= 0) && (p < p_n) && ((uint32_t)(str->a[s]) == (p_a[p]^1)); s--, p++) { + xi = &(uidx->idx->a[hid_a[z]>>32].bb.a[str->a[s]>>32]); + assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[s])); + if(skip_hom && IF_HOM(xi->hid, *bub)) continue; + sw[1] += ug_occ_w(xi->ts, xi->te, &(uidx->l1_ug->u.a[xi->hid])); + } + if(s >= 0 && p < p_n) continue; + if(p <= match_bound + 1) continue;///bridging the two sides of the breakpoint + if(sw[1] == 0) continue; + pe = p; + + s = (uint32_t)hid_a[z]; p = match_bound; + for (; (s < s_n) && (p >= 0) && ((uint32_t)(str->a[s]) == (p_a[p]^1)); s++, p--) { + xi = &(uidx->idx->a[hid_a[z]>>32].bb.a[str->a[s]>>32]); + assert(((xi->hid<<1)+xi->rev)==((uint32_t)str->a[s])); + if(skip_hom && IF_HOM(xi->hid, *bub)) continue; + sw[0] += ug_occ_w(xi->ts, xi->te, &(uidx->l1_ug->u.a[xi->hid])); + } + assert(p < match_bound); + if(s < s_n && p >= 0) continue; + if(sw[0] == 0) continue; + ps = p + 1; + } + if(res) kv_push(uint64_t, *res, ((ps<<32)|(pe))); + occ++; + ww[0] += sw[0]; ww[1] += sw[1]; + // if(match_bound == 15 && p_n == 36) { + // fprintf(stderr, "[M::%s::] z::%lu, ulid::%lu, ps::%lu, pe::%lu\n", __func__, z, hid_a[z]>>32, ps, pe); + // } + } + + (*r_w) = MIN(ww[0], ww[1]); + return occ; +} + +uint32_t usg_misjoin_topocut_aux(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t v, uint32_t ref_v, uint32_t beg_v, +asg64_v *b, asg64_v *ub) +{ + #define cut_rate 0.49999 + uint32_t k, bn = b->n, is_del = 0, kk, ks, ke; + uint64_t n_ref, n_v, *a_ref, *a_v, n_min, n_ref_ov, n_v_ov, *a_ref_ov, *a_v_ov, l_occ, r_occ, ref_occ, v_occ, ww[2]; + ub->n = 0; kv_push(uint64_t, *ub, beg_v); + get_ul_path_info(uidx, ug, ref_v, NULL, NULL, NULL, NULL, NULL, ub); + // fprintf(stderr, "+++[M::%s::] start..., v>>1::%u, v&1::%u, ref_v>>1::%u, ref_v&1::%u, beg_v>>1::%u, beg_v&1::%u\n", __func__, v>>1, v&1, ref_v>>1, ref_v&1, beg_v>>1, beg_v&1); + n_ref = gen_ug_integer_seq_on_fly(uidx, ub->a, ub->n, b); + // fprintf(stderr, "+++[M::%s::] done...\n", __func__); + + ub->n = 0; kv_push(uint64_t, *ub, beg_v); + get_ul_path_info(uidx, ug, v, NULL, NULL, NULL, NULL, NULL, ub); + // fprintf(stderr, "---[M::%s::] start...\n", __func__); + n_v = gen_ug_integer_seq_on_fly(uidx, ub->a, ub->n, b); + // fprintf(stderr, "---[M::%s::] done...\n", __func__); + + a_ref = b->a + bn; a_v = b->a + bn + n_ref; n_min = MIN(n_ref, n_v); ub->n = 0; + for (k = 0; k < n_min && a_ref[k] == a_v[k]; k++); + + // if((beg_v>>1) == 5958) { + // fprintf(stderr, "[M::%s::] beg_v>>1::%u, beg_v&1::%u, v>>1::%u, v&1::%u, n_v::%lu, ref_v>>1::%u, ref_v&1::%u, n_ref::%lu, # prefix::%u\n", + // __func__, beg_v>>1, beg_v&1, v>>1, v&1, n_v, ref_v>>1, ref_v&1, n_ref, k); + // for (kk = 0; kk < n_v; kk++) { + // fprintf(stderr, "+[M::%s::] a_v[%u]>>1::%lu, a_v[%u]&1::%lu\n", + // __func__, kk, a_v[kk]>>1, kk, a_v[kk]&1); + // } + + // for (kk = 0; kk < n_ref; kk++) { + // fprintf(stderr, "+[M::%s::] a_ref[%u]>>1::%lu, a_ref[%u]&1::%lu\n", + // __func__, kk, a_ref[kk]>>1, kk, a_ref[kk]&1); + // } + // } + + + if(k > 0) { + n_ref_ov = get_integer_seq_ovlps(uidx, a_ref, n_ref, k - 1, 1, ub, &ww[0]); + n_v_ov = get_integer_seq_ovlps(uidx, a_v, n_v, k - 1, 1, ub, &ww[1]); + if(n_v_ov <= (n_ref_ov*cut_rate)) { + is_del = 1; + } else { + a_ref_ov = ub->a; a_v_ov = ub->a + n_ref_ov; kk = k; + + for (k = ref_occ = 0; k < n_ref_ov; k++) { + ks = a_ref_ov[k]>>32; ke = (uint32_t)a_ref_ov[k]; + l_occ = kk - ks; r_occ = ke - kk; + ref_occ += MIN(l_occ, r_occ); + } + + for (k = v_occ = 0; k < n_v_ov; k++) { + ks = a_v_ov[k]>>32; ke = (uint32_t)a_v_ov[k]; + l_occ = kk - ks; r_occ = ke - kk; + v_occ += MIN(l_occ, r_occ); + } + + if(v_occ <= (ref_occ*cut_rate)) is_del = 1; + } + } + b->n = bn; + return is_del; +} + + +uint32_t ulg_arc_cut_misjoin(ul_resolve_t *uidx, ma_ug_t *ug, int32_t max_ext, uint32_t max_ext_hifi, +float len_rat, uint32_t is_trio, uint32_t topo_level, uint32_t *max_drop_len, asg64_v *in, asg64_v *ib) +{ + asg64_v tx = {0,0,0}, tb = {0,0,0}, *b = NULL, *ub = NULL; asg_t *g = ug->g; + uint32_t v, w, i, k, kv, nv, kw, nw, cnt = 0, n_vtx = g->n_seq<<1, mm_ul, ul_max, to_del; + asg_arc_t *av, *aw, *ve, *we; uint32_t ul_cnt, pb; + + b = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); + for (v = b->n = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + + if(g->seq_vis[v] == 0) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if (nv < 2) continue; + + for (i = kv = 0, ul_max = -1; i < nv; ++i) { + if(av[i].del) {continue;} kv++; + get_ul_path_info(uidx, ug, av[i].v, NULL, NULL, &ul_cnt, NULL, NULL, NULL); + if(ul_cnt > ul_max) ul_max = ul_cnt; + } + // if((v>>1) == 5958) { + // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, kv::%u, ul_max::%u\n", + // __func__, v>>1, v&1, kv, ul_max); + // } + if(kv < 2 || ul_max == 0) continue; //note: ul_cnt/ul_max might be 0 + + for (i = 0; i < nv; ++i) { + if(av[i].del) continue; + get_ul_path_info(uidx, ug, av[i].v, NULL, NULL, &ul_cnt, NULL, NULL, NULL); + // if((v>>1) == 5958) { + // fprintf(stderr, "+++[M::%s::] v>>1::%u, v&1::%u, av[i].v>>1::%u, av[i].v&1::%u, ul_cnt::%u\n", + // __func__, v>>1, v&1, av[i].v>>1, av[i].v&1, ul_cnt); + // } + if(ul_cnt > 0) ul_cnt = ul_max/ul_cnt; + else ul_cnt = ul_max<<2; + ul_cnt = ((uint32_t)-1) - ul_cnt; + kv_push(uint64_t, *b, (((uint64_t)ul_cnt)<<32) | ((uint64_t)(av-g->arc+i))); + } + } + } + + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + if(g->arc[(uint32_t)b->a[k]].del) continue; + v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; + if(g->seq[v>>1].del || g->seq[w>>1].del) continue; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + if(nv<=1 && asg_arc_n(g, w) <= 1) continue; + + ve = &(g->arc[(uint32_t)b->a[k]]); pb = b->n; ub->n = 0; + get_ul_path_info(uidx, ug, ve->v, NULL, NULL, &mm_ul, NULL, NULL, NULL); + // if((v>>1) == 5958 && (w>>1) == 11105) { + // fprintf(stderr, ">>>[M::%s::] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, mm_ul::%u\n", + // __func__, v>>1, v&1, w>>1, w&1, mm_ul); + // } + if(mm_ul == 0) continue;///no UL read support this path + + for (i = kv = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + if(av[i].v == ve->v) continue; + get_ul_path_info(uidx, ug, av[i].v, NULL, NULL, &ul_cnt, NULL, NULL, NULL); + // if((v>>1) == 5958 && (w>>1) == 11105) { + // fprintf(stderr, "*[M::%s::i->%u] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, av[i].v>>1::%u, av[i].v&1::%u, ul_cnt::%u\n", + // __func__, i, v>>1, v&1, w>>1, w&1, av[i].v>>1, av[i].v&1, ul_cnt); + // } + if (mm_ul <= ul_cnt*len_rat) { + ul_cnt = ((uint32_t)-1) - ul_cnt; + kv_push(uint64_t, *b, (((uint64_t)ul_cnt)<<32)|((uint64_t)(i))); + } + } + if(b->n == pb) continue; + to_del = 0; assert(kv >= 2); + + aw = asg_arc_a(g, w); nw = asg_arc_n(g, w); + for (i = kw = 0, we = NULL; i < nw; ++i) { + if (aw[i].del) continue; + if (aw[i].v == (v^1)) we = &(aw[i]); + kw++; + } + + if((kv > 1 && kw > 1) || (usg_bridge_topocut_aux(uidx, ug, ve->v, max_ext, max_ext_hifi, topo_level, 0, b, ub))) { + radix_sort_srt64(b->a + pb, b->a + b->n); + for (i = pb; i < b->n; i++) { + // if((v>>1) == 5958 && (w>>1) == 11105) { + // fprintf(stderr, "#[M::%s::srt_i->%u] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, av[(uint32_t)b->a[i]].v>>1::%u, av[(uint32_t)b->a[i]].v&1::%u\n", + // __func__, (uint32_t)b->a[i], v>>1, v&1, w>>1, w&1, av[(uint32_t)b->a[i]].v>>1, av[(uint32_t)b->a[i]].v&1); + // } + if(usg_misjoin_topocut_aux(uidx, ug, ve->v, av[(uint32_t)b->a[i]].v, v, b, ub)) { + to_del = 1; + break; + } + } + } + + b->n = pb; + if(to_del) { + if(kv > 1 && kw > 1) { + ve->del = we->del = 1; ++cnt; + } else { + pb = b->n; + get_ul_path_info(uidx, ug, ve->v, NULL, NULL, NULL, NULL, NULL, b); + for (i = pb; i < b->n; i++) ulg_seq_del(ug, (b->a[i]>>1)); + cnt += b->n - pb; b->n = pb; + } + } + } + + + if(!in) {free(tx.a);} if(!ib) {free(tb.a);} + if (cnt > 0) asg_cleanup(g); + return cnt; +} + +uint32_t is_het_bridge(ul_resolve_t *uidx, uint64_t *p_a, int64_t p_n, int64_t match_bound) +{ + bubble_type *bub = uidx->bub; int64_t z; + for (z = match_bound; z >= 0 && IF_HOM((p_a[z]>>1), *bub); z--) { + // if(is_debug){ + // fprintf(stderr, "+[M::%s::] match_bound::%ld, p_n::%ld, (p_a[%ld]>>1)::%lu, IF_HOM::%u\n", + // __func__, match_bound, p_n, z, (p_a[z]>>1), IF_HOM((p_a[z]>>1), *bub)); + // } + } + if(z < 0) return 0; + for (z = match_bound + 1; z < p_n && IF_HOM((p_a[z]>>1), *bub); z++) { + // if(is_debug){ + // fprintf(stderr, "-[M::%s::] match_bound::%ld, p_n::%ld, (p_a[%ld]>>1)::%lu, IF_HOM::%u\n", + // __func__, match_bound, p_n, z, (p_a[z]>>1), IF_HOM((p_a[z]>>1), *bub)); + // } + } + // if(is_debug) { + // fprintf(stderr, "*[M::%s::] z::%ld, p_n::%ld\n", __func__, z, p_n); + // } + if(z >= p_n) return 0; + return 1; +} + +uint32_t get_ul_arc_supports(ul_resolve_t *uidx, asg_arc_t *ve, asg64_v *b_int, asg64_v *b_raw, uint64_t skip_hom, uint64_t *retrun_w_v, uint64_t *retrun_w_r) +{ + ma_ug_t *iug = uidx->uovl.i_ug; asg_t *g = iug->g; uint32_t v, k, z, zn, nv, n_pre, l_v, l_r, skip_hom_local; + asg_arc_t *av; v = ve->ul>>32; uint32_t b_int_s = b_int->n, b_raw_s = b_raw->n, is_collapse = 0, v_occ, r_occ; + (*retrun_w_v) = (*retrun_w_r) = (uint64_t)-1; uint64_t *raw_v, *raw_r, w_v, w_r, min_w_v, min_w_r; + + get_ul_path_info(uidx, iug, v^1, NULL, NULL, NULL, NULL, NULL, b_int); nv = b_int->n-b_int_s; + for (k = 0, n_pre = b_int->n; k < (nv>>1); k++) { + v = b_int->a[k+b_int_s]; + b_int->a[k+b_int_s] = b_int->a[b_int_s+nv-k-1]^1; + b_int->a[b_int_s+nv-k-1] = v^1; + } + if(nv&1) b_int->a[k+b_int_s] ^= 1; + v = ve->ul>>32; + + get_ul_path_info(uidx, iug, ve->v, NULL, NULL, &v_occ, NULL, NULL, b_int); + // if(((ve->ul>>32) == 24093) && (ve->v == 61472)) { + // for (z = 0; z < b_int->n-b_int_s; z++) { + // fprintf(stderr, "[M::%s::] integ_v[%u]>>1:%lu, integ_v[%u]&1:%lu\n", __func__, + // z, b_int->a[b_int_s+z]>>1, z, b_int->a[b_int_s+z]&1); + // } + // } + l_v = gen_ug_integer_seq_on_fly(uidx, b_int->a+b_int_s, b_int->n-b_int_s, b_raw); + + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (k = 0, min_w_v = min_w_r = (uint64_t)-1; k < nv; k++) { + if(av[k].del || av[k].v == ve->v) continue;///skip ve->v + + b_int->n = n_pre; b_raw->n = b_raw_s + l_v; + get_ul_path_info(uidx, iug, av[k].v, NULL, NULL, &r_occ, NULL, NULL, b_int); + // if(((ve->ul>>32) == 24093) && (ve->v == 61472)) { + // for (z = 0; z < b_int->n-b_int_s; z++) { + // fprintf(stderr, "[M::%s::k->%u] integ_r[%u]>>1:%lu, integ_r[%u]&1:%lu\n", __func__, + // k, z, b_int->a[b_int_s+z]>>1, z, b_int->a[b_int_s+z]&1); + // } + // } + + l_r = gen_ug_integer_seq_on_fly(uidx, b_int->a+b_int_s, b_int->n-b_int_s, b_raw); + ///raw_v -> ve->v; raw_r -> av[k].v + raw_v = b_raw->a + b_raw_s; raw_r = b_raw->a + b_raw_s + l_v; zn = MIN(l_v, l_r); + // if((v>>1) == 77 && (ve->v>>1) == 78) { + // fprintf(stderr, "[M::%s::] l_v::%u\n", __func__, l_v); + // for (z = 0; z < l_v; z++) { + // fprintf(stderr, "raw_v[%u]>>1::utg%.6dl, raw_v[%u]&1::%lu\n", + // z, (int32_t)(raw_v[z]>>1)+1, z , raw_v[z]&1); + // } + // fprintf(stderr, "[M::%s::] l_r::%u\n", __func__, l_r); + // for (z = 0; z < l_r; z++) { + // fprintf(stderr, "raw_r[%u]>>1::utg%.6dl, raw_r[%u]&1::%lu\n", + // z, (int32_t)(raw_r[z]>>1)+1, z, raw_r[z]&1); + // } + // } + for (z = 0; z < zn && raw_v[z] == raw_r[z]; z++); ///z: first raw unitig that is different between two paths + skip_hom_local = skip_hom; + if(skip_hom_local && z < l_v) { + skip_hom_local = is_het_bridge(uidx, raw_v, l_v, z - 1);///, (v>>1) == 191 && (ve->v>>1) == 450); + } + if(skip_hom_local && z < l_r) { + skip_hom_local = is_het_bridge(uidx, raw_r, l_r, z - 1);///, (v>>1) == 191 && (ve->v>>1) == 450); + } + + assert(z > 0); w_v = w_r = (uint64_t)-1; + if(z < l_v) get_integer_seq_ovlps(uidx, raw_v, l_v, z - 1, skip_hom_local, NULL, &w_v); + if(z < l_r) get_integer_seq_ovlps(uidx, raw_r, l_r, z - 1, skip_hom_local, NULL, &w_r); + if(w_v == (uint64_t)-1) w_v = 0; + if(w_r == (uint64_t)-1) w_r = 0; + // if((v>>1) == 409 && (ve->v>>1) == 407) { + // fprintf(stderr, "[M::%s::v>>1::%u] l_v::%u, l_r::%u, z::%u, w_v::%lu, w_r::%lu, skip_hom_local::%u\n", + // __func__, av[k].v>>1, l_v, l_r, z, w_v, w_r, skip_hom_local); + // } + ///z == zn: -> prefer collapse + if((min_w_v == (uint64_t)-1) || (z == zn) || (min_w_v > w_v) || (min_w_v == w_v && min_w_r < w_r)) { + min_w_v = w_v; min_w_r = w_r; + if(z == zn && v_occ < r_occ) is_collapse = 1; + } + } + if(is_collapse) min_w_v = 0; + + (*retrun_w_v) = min_w_v; (*retrun_w_r) = min_w_r; + return is_collapse; +} + +static void worker_update_ul_arc_supports(void *data, long i, int tid) // callback for kt_for() +{ + ul_resolve_t *uidx = (ul_resolve_t *)data; integer_t *buf = &(uidx->str_b.buf[tid]); + uint64_t *x = &(uidx->uovl.iug_tra->a[i]); asg_arc_t *ve = &(uidx->uovl.i_ug->g->arc[*x]); + asg64_v b_v, b_r; uint64_t w_v, w_r; + b_v.a = buf->u.a; b_v.n = buf->u.n; b_v.m = buf->u.m; + b_r.a = buf->o.a; b_r.n = buf->o.n; b_r.m = buf->o.m; + + b_v.n = b_r.n = 0; + get_ul_arc_supports(uidx, ve, &b_v, &b_r, 1, &w_v, &w_r); + + buf->u.a = b_v.a; buf->u.n = b_v.n; buf->u.m = b_v.m; + buf->o.a = b_r.a; buf->o.n = b_r.n; buf->o.m = b_r.m; + + (*x) |= (w_v<<32); +} + + +uint32_t check_ul_contain_arc_supports(ul_resolve_t *uidx, asg_arc_t *ve, asg64_v *b_int, asg64_v *b_raw, uint64_t skip_hom, uint64_t *retrun_w_v, uint64_t *retrun_w_r) +{ + ma_ug_t *iug = uidx->uovl.i_ug; asg_t *g = iug->g; uint32_t v, k, z, zn, nv, n_pre, l_v, l_r, skip_hom_local; + asg_arc_t *av; v = ve->ul>>32; uint32_t b_int_s = b_int->n, b_raw_s = b_raw->n, is_collapse = 0, v_occ, r_occ; + (*retrun_w_v) = (*retrun_w_r) = (uint64_t)-1; uint64_t *raw_v, *raw_r, w_v, w_r, min_w_v, min_w_r; + + get_ul_path_info(uidx, iug, v^1, NULL, NULL, NULL, NULL, NULL, b_int); nv = b_int->n-b_int_s; + for (k = 0, n_pre = b_int->n; k < (nv>>1); k++) { + v = b_int->a[k+b_int_s]; + b_int->a[k+b_int_s] = b_int->a[b_int_s+nv-k-1]^1; + b_int->a[b_int_s+nv-k-1] = v^1; + } + if(nv&1) b_int->a[k+b_int_s] ^= 1; + v = ve->ul>>32; + + get_ul_path_info(uidx, iug, ve->v, NULL, NULL, &v_occ, NULL, NULL, b_int); + l_v = gen_ug_integer_seq_on_fly(uidx, b_int->a+b_int_s, b_int->n-b_int_s, b_raw); + + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + for (k = 0, min_w_v = min_w_r = (uint64_t)-1; k < nv; k++) { + if(av[k].del || av[k].v == ve->v) continue; + + b_int->n = n_pre; b_raw->n = b_raw_s + l_v; + get_ul_path_info(uidx, iug, av[k].v, NULL, NULL, &r_occ, NULL, NULL, b_int); + l_r = gen_ug_integer_seq_on_fly(uidx, b_int->a+b_int_s, b_int->n-b_int_s, b_raw); + + raw_v = b_raw->a + b_raw_s; raw_r = b_raw->a + b_raw_s + l_v; zn = MIN(l_v, l_r); + for (z = 0; z < zn && raw_v[z] == raw_r[z]; z++); + skip_hom_local = skip_hom; + if(skip_hom_local && z < l_v) { + skip_hom_local = is_het_bridge(uidx, raw_v, l_v, z - 1);///, (v>>1) == 191 && (ve->v>>1) == 450); + } + if(skip_hom_local && z < l_r) { + skip_hom_local = is_het_bridge(uidx, raw_r, l_r, z - 1);///, (v>>1) == 191 && (ve->v>>1) == 450); + } + + assert(z > 0); w_v = w_r = (uint64_t)-1; + if(z < l_v) get_integer_seq_ovlps(uidx, raw_v, l_v, z - 1, skip_hom_local, NULL, &w_v); + if(z < l_r) get_integer_seq_ovlps(uidx, raw_r, l_r, z - 1, skip_hom_local, NULL, &w_r); + if(w_v == (uint64_t)-1) w_v = 0; + if(w_r == (uint64_t)-1) w_r = 0; + // if((v>>1) == 409 && (ve->v>>1) == 407) { + // fprintf(stderr, "[M::%s::v>>1::%u] l_v::%u, l_r::%u, z::%u, w_v::%lu, w_r::%lu, v_occ::%u, r_occ::%u, skip_hom_local::%u\n", + // __func__, av[k].v>>1, l_v, l_r, z, w_v, w_r, v_occ, r_occ, skip_hom_local); + // } + ///z == zn: -> prefer collapse + if((min_w_v == (uint64_t)-1) || (z == zn) || (min_w_v > w_v) || (min_w_v == w_v && min_w_r < w_r)) { + min_w_v = w_v; min_w_r = w_r; + if(z == zn && v_occ < r_occ) { + is_collapse = 1; + } + } + } + + (*retrun_w_v) = min_w_v; (*retrun_w_r) = min_w_r; + return is_collapse; +} + +uint32_t check_ulg_to_del(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t v, uint32_t w, uint32_t kv, uint32_t kw, +uint32_t max_ext, uint32_t max_ext_hifi, uint32_t topo_level, uint32_t collapse, asg64_v *b, asg64_v *ub) +{ + uint32_t to_del = 0; + if(collapse) topo_level = 3; + if(topo_level == 0) { + to_del = 1; + } else if(topo_level == 2) { + if (kv > 1 && kw > 1) to_del = 1; + } else { + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (usg_topocut_aux(uidx, ug, w^1, max_ext, max_ext_hifi, b, ub)) to_del = 1; + } else if (kv == 1) { + if (usg_topocut_aux(uidx, ug, v^1, max_ext, max_ext_hifi, b, ub)) to_del = 1; + } + } + + return to_del; +} + +uint32_t ulg_arc_cut_supports(ul_resolve_t *uidx, ma_ug_t *ug, int32_t max_ext, uint32_t max_ext_hifi, +float len_rat, uint32_t is_trio, uint32_t topo_level, uint32_t skip_hom, uint32_t *max_drop_len, uint32_t collapse_check, +asg64_v *in, asg64_v *ib) +{ + // fprintf(stderr, "\n[M::%s::] max_ext::%d, max_ext_hifi::%d, len_rat::%f, is_trio::%u, topo_level::%u, skip_hom::%u, collapse_check::%u\n", + // __func__, max_ext, max_ext_hifi, len_rat, is_trio, topo_level, skip_hom, collapse_check); + + asg64_v tx = {0,0,0}, tb = {0,0,0}, *b = NULL, *ub = NULL; asg_t *g = ug->g; + uint32_t v, w, i, k, kv, nv, kw, nw, cnt = 0, n_vtx = g->n_seq<<1, to_del, collapse; + asg_arc_t *av, *aw, *ve, *we; uint64_t w_q, w_t, pb; + + b = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); + for (v = b->n = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + + if(g->seq_vis[v] == 0) { + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if (nv < 2) continue; + + for (i = kv = 0; i < nv && kv < 2; ++i) { + if(av[i].del) {continue;} kv++; + } + if(kv < 2) continue; + + for (i = 0; i < nv; ++i) { + if(av[i].del) continue; + kv_push(uint64_t, *b, ((uint64_t)(av-g->arc+i))); + } + } + } + + // fprintf(stderr, "\n#[M::%s::] Starting...\n", __func__); + uidx->uovl.iug_tra = b; + kt_for(uidx->str_b.n_thread, worker_update_ul_arc_supports, uidx, b->n);///all ul + ug + uidx->uovl.iug_tra = NULL; + // fprintf(stderr, "#[M::%s::] Done\n", __func__); + // fprintf(stderr, "#[M::%s::] collapse_check::%u, len_rat::%f\n", __func__, collapse_check, len_rat); + + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + if(g->arc[(uint32_t)b->a[k]].del) continue; + v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; + if(g->seq[v>>1].del || g->seq[w>>1].del) continue; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); + if(nv <= 1 && nw <= 1) continue; + ve = &(g->arc[(uint32_t)b->a[k]]); + for (i = kv = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + } + for (i = kw = 0, we = NULL; i < nw; ++i) { + if (aw[i].del) continue; + if (aw[i].v == (v^1)) we = &(aw[i]); + kw++; + } + if(kv <= 1 && kw <= 1) continue; + collapse = 0; + + if(collapse_check) { + if(kv > 1) { + pb = b->n; ub->n = 0; + collapse = check_ul_contain_arc_supports(uidx, ve, b, ub, skip_hom, &w_q, &w_t); + b->n = pb; ub->n = 0; + } + + if(collapse == 0 && kw > 1) { + pb = b->n; ub->n = 0; + collapse = check_ul_contain_arc_supports(uidx, we, b, ub, skip_hom, &w_q, &w_t); + b->n = pb; ub->n = 0; + } + } + + // if(((v>>1) == 6788 && (w>>1) == 17213) || ((w>>1) == 6788 && (v>>1) == 17213)) { + // fprintf(stderr, "#[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, collapse::%u\n", + // __func__, v>>1, v&1, kv, w>>1, w&1, kw, collapse); + // } + + if(collapse == 0) { + if(kv > 1) { + pb = b->n; ub->n = 0; + get_ul_arc_supports(uidx, ve, b, ub, skip_hom, &w_q, &w_t); + b->n = pb; ub->n = 0; + // if((v>>1) == 409 && (w>>1) == 407) { + // fprintf(stderr, "+[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, w_q::%lu, w_t::%lu\n", + // __func__, v>>1, v&1, kv, w>>1, w&1, kw, w_q, w_t); + // } + // if(((v>>1) == 6788 && (w>>1) == 17213) || ((w>>1) == 6788 && (v>>1) == 17213)) { + // fprintf(stderr, "+[M::%s::] v>>1::%u, v&1::%u, w_q::%lu, w>>1::%u, w&1::%u, w_t::%lu\n", + // __func__, v>>1, v&1, w_q, w>>1, w&1, w_t); + // } + if(w_q == (uint64_t)-1) continue; + if(w_q > w_t*len_rat) continue; + } + + if(kw > 1) { + pb = b->n; ub->n = 0; + get_ul_arc_supports(uidx, we, b, ub, skip_hom, &w_q, &w_t); + b->n = pb; ub->n = 0; + // if((v>>1) == 409 && (w>>1) == 407) { + // fprintf(stderr, "-[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, w_q::%lu, w_t::%lu\n", + // __func__, v>>1, v&1, kv, w>>1, w&1, kw, w_q, w_t); + // } + // if(((v>>1) == 6788 && (w>>1) == 17213) || ((w>>1) == 6788 && (v>>1) == 17213)) { + // fprintf(stderr, "-[M::%s::] v>>1::%u, v&1::%u, w_q::%lu, w>>1::%u, w&1::%u, w_t::%lu\n", + // __func__, v>>1, v&1, w_q, w>>1, w&1, w_t); + // } + if(w_q == (uint64_t)-1) continue; + if(w_q > w_t*len_rat) continue; + } + } + + to_del = check_ulg_to_del(uidx, ug, v, w, kv, kw, max_ext, max_ext_hifi, topo_level, collapse, b, ub); + + // if(((v>>1) == 6788 && (w>>1) == 17213) || ((w>>1) == 6788 && (v>>1) == 17213)) { + // fprintf(stderr, "#[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, to_del::%u\n", + // __func__, v>>1, v&1, kv, w>>1, w&1, kw, to_del); + // } + if (to_del) { + ve->del = we->del = 1, ++cnt; + } + } + + if(!in) {free(tx.a);} if(!ib) {free(tb.a);} + if (cnt > 0) asg_cleanup(g); + return cnt; +} + +uint64_t ulg_bub_pop_cut_aux(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t v0, buf_t *x, uint32_t max_ext, uint32_t max_ext_hifi, asg64_v *b, asg64_v *ub) +{ + uint32_t i, v, u, bn = b->n, n_ext, ul_occ, r = 0; binfo_t *t; + v = x->S.a[0]; + do { + u = x->a[v].p; // u->v + x->a[v].d = (uint32_t)-1; + v = u; + } while (v != v0); + + for (i = n_ext = 0; i < x->b.n; ++i) { // clear the states of visited vertices + t = &x->a[x->b.a[i]]; + if(t->d == (uint32_t)-1) continue; + get_iug_u_raw_occ(uidx, x->b.a[i]>>1, &ul_occ, NULL); + n_ext += ul_occ; kv_push(uint64_t, *b, x->b.a[i]); + } + + if(n_ext <= max_ext) { + if(get_remove_hifi_occ(uidx, max_ext_hifi, b->a + bn, b->n - bn, ub, NULL)) r = 1; + } + b->n = bn; + return r; +} + +uint32_t ulg_bub_pop_backtrack(ma_ug_t *ug, uint32_t v0, buf_t *b) +{ + uint32_t i, v, u, cnt = b->e.n; asg_t *g = ug->g; + + ///b->S.a[0] is the sink of this bubble + for (i = 0; i < b->b.n; ++i) g->seq[b->b.a[i]>>1].del = 1; + + ///remove all edges (self/reverse for each edge) in this bubble + for (i = 0; i < b->e.n; ++i) { + g->arc[b->e.a[i]].del = 1; + asg_arc_del(g, g->arc[b->e.a[i]].v^1, (g->arc[b->e.a[i]].ul>>32)^1, 1); + } + + ///v is the sink of this bubble + v = b->S.a[0]; + do { + u = b->a[v].p; // u->v + g->seq[v>>1].del = 0; + asg_arc_del(g, u, v, 0); + asg_arc_del(g, v^1, u^1, 0); + cnt--; + v = u; + } while (v != v0); + + for (i = 0; i < b->b.n; ++i) { + if(!g->seq[b->b.a[i]>>1].del) continue; + ulg_seq_del(ug, (b->b.a[i]>>1)); + } + + return cnt; +} + +uint64_t ulg_bub_pop1(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t v0, uint64_t max_dist, buf_t *x, +uint32_t max_ext, uint32_t max_ext_hifi, uint32_t check_bubble_only, uint32_t is_pop, uint32_t skip_hom, +asg64_v *b, asg64_v *ub, uint32_t *r_w_c, uint32_t *r_w_m) +{ + asg_t *g = ug->g; uint32_t pb = b->n; uint64_t w_q, w_t, wc, wm, ww; (*r_w_c) = (*r_w_m) = (uint32_t)-1; + uint32_t v, w, i, kv, nv, kw, cnt = 0, fail_b = 0, n_tips = 0, tip_end = (uint32_t)-1; + uint32_t l, d, c, m, n_pending = 0, z, to_replace; asg_arc_t *av, *ve, *we; binfo_t *t; + if(g->seq[v0>>1].del || get_arcs(g, v0, NULL, 0) < 2) return 0; // already deleted + // fprintf(stderr, "sbsbsbsbsbsbsb[M::%s::(v0>>1)->%u::(v0&1)->%u] check_bubble_only::%u, is_pop::%u\n", + // __func__, v0>>1, v0&1, check_bubble_only, is_pop); + + x->S.n = x->T.n = x->b.n = x->e.n = 0; + x->a[v0].c = x->a[v0].d = x->a[v0].m = x->a[v0].nc = x->a[v0].np = 0; + kv_push(uint32_t, x->S, v0); + + do { + v = kv_pop(x->S); d = x->a[v].d; c = x->a[v].c; m = x->a[v].m; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); kv = get_arcs(g, v, NULL, 0); + for (i = 0; i < nv; ++i) { + if (av[i].del) continue; + w = av[i].v; t = &(x->a[w]); l = ((v == v0)?(0):((uint32_t)av[i].ul)); + if ((w>>1) == (v0>>1)) { + fail_b = 1; + break; + } + kv_push(uint32_t, x->e, (g->idx[v]>>32) + i); ///for backtracking + if (d + l > max_dist) { + fail_b = 1; + break; + } + kw = get_arcs(g, w^1, NULL, 0); + wc = 0; wm = get_ul_occ(uidx, w>>1); + if(!check_bubble_only) { + if(kv > 1) { + pb = b->n; ub->n = 0; ve = &(av[i]); + // fprintf(stderr, "[M::%s::] ve->v>>1::%lu, ve->v&1::%lu, ve->w>>1::%u, ve->w&1::%u\n", + // __func__, ve->ul>>33, (ve->ul>>32)&1, ve->v>>1, ve->v&1); + get_ul_arc_supports(uidx, ve, b, ub, skip_hom, &w_q, &w_t); + b->n = pb; ub->n = 0; + if(w_q < w_t) { + if(w_q == 0) { + ww = 10; + } else { + if(w_t != 0) ww = ((w_t - w_q)*10)/w_t; + else ww = 0; + } + if(ww > wc) wc = ww; + } + } + + if(kw > 1) { + pb = b->n; ub->n = 0; we = get_specfic_edge(g, w^1, v^1); assert(we); + // fprintf(stderr, "[M::%s::] we->v>>1::%lu, we->v&1::%lu, we->w>>1::%u, we->w&1::%u\n", + // __func__, we->ul>>33, (we->ul>>32)&1, we->v>>1, we->v&1); + get_ul_arc_supports(uidx, we, b, ub, skip_hom, &w_q, &w_t); + b->n = pb; ub->n = 0; + if(w_q < w_t) { + if(w_q == 0) { + ww = 10; + } else { + if(w_t != 0) ww = ((w_t - w_q)*10)/w_t; + else ww = 0; + } + if(ww > wc) wc = ww; + } + } + } + + if (t->s == 0) { + kv_push(uint32_t, x->b, w); + t->p = v, t->s = 1, t->d = d + l; + t->c = c + wc; t->m = m + wm; + t->r = kw; + ++n_pending; + } else { + to_replace = 0; + if((c + wc) < t->c) { + to_replace = 1; + } else if(((c + wc) == t->c) && (m + wm > t->m)) { + to_replace = 1; + } else if(((c + wc) == t->c) && (m + wm == t->m) && (d + l > t->d)) { + to_replace = 1; + } + if(to_replace) { + t->p = v; t->c = c + wc; t->m = m + wm; + } + if (d + l < t->d) t->d = d + l; // update dist + } + + if (--(t->r) == 0) { + z = get_arcs(g, w, NULL, 0); + if(z > 0) { + kv_push(uint32_t, x->S, w); + } + else { + ///at most one tip + if(n_tips != 0) { + fail_b = 1; + break; + } + n_tips++; tip_end = w; + } + --n_pending; + } + } + if(fail_b) break; + if(n_tips == 1) { + if(tip_end != (uint32_t)-1 && n_pending == 0 && x->S.n == 0) { + kv_push(uint32_t, x->S, tip_end); + break; + } + fail_b = 1; + break; + } + + if (i < nv || x->S.n == 0) { + fail_b = 1; + break; + } + } while (x->S.n > 1 || n_pending); + + if(!fail_b) {//there is a bubble + cnt = 1; (*r_w_c) = x->a[x->S.a[0]].c; (*r_w_m) = x->a[x->S.a[0]].m; + if(!check_bubble_only) { + if(is_pop) { + cnt = ulg_bub_pop_backtrack(ug, v0, x); + } else { + cnt = ulg_bub_pop_cut_aux(uidx, ug, v0, x, max_ext, max_ext_hifi, b, ub); + } + } + } + for (i = 0; i < x->b.n; ++i) { // clear the states of visited vertices + // if(v0 == 119) { + // fprintf(stderr, "-[M::%s::(v0>>1)->%u::(v0&1)->%u] v[%u]>>1::%u, v[%u]&1::%u, cnt::%u, is_pop::%u\n", + // __func__, v0>>1, v0&1, i, x->b.a[i]>>1, i, x->b.a[i]&1, cnt, is_pop); + // } + t = &x->a[x->b.a[i]]; + t->s = t->c = t->d = t->m = t->nc = t->np = 0; + } + if(!cnt) (*r_w_c) = (*r_w_m) = (uint32_t)-1; + return cnt; +} + +uint64_t ulg_pop_bubble(ul_resolve_t *uidx, ma_ug_t *ug, uint64_t* i_max_dist, uint32_t max_ext, uint32_t max_ext_hifi, uint32_t skip_hom, asg64_v *in, asg64_v *ib) +{ + // fprintf(stderr, "[M::%s::] Starting...\n", __func__); + asg_t *g = ug->g; + asg64_v tx = {0,0,0}, tb = {0,0,0}, *ob = NULL, *ub = NULL; + uint32_t v, w, n_vtx = g->n_seq<<1, n_arc, nv, i, wc[2], wm[2], mm_c, mm_m, mm_v; + uint64_t n_pop = 0, max_dist; + asg_arc_t *av = NULL; if (!g->is_symm) asg_symm(g); + buf_t b; memset(&b, 0, sizeof(buf_t)); + b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + if(i_max_dist) max_dist = (*i_max_dist); + else max_dist = get_bub_pop_max_dist_advance(g, &b); + ob = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); ob->n = ub->n = 0; + + if(max_dist > 0) { + for (v = 0; v < n_vtx; ++v) { + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + if (nv < 2 || g->seq[v>>1].del) continue; + for (i = n_arc = 0; i < nv; ++i) { + if (!av[i].del) ++n_arc; + } + if (n_arc < 2) continue; + ///find a bubble + ob->n = ub->n = 0; + if(ulg_bub_pop1(uidx, ug, v, max_dist, &b, max_ext, max_ext_hifi, 1, 0, skip_hom, ob, ub, &(wc[0]), &(wm[0]))) { + w = b.S.a[0]^1; mm_c = mm_m = mm_v = (uint32_t)-1; + + ob->n = ub->n = 0; + if(ulg_bub_pop1(uidx, ug, v, max_dist, &b, max_ext, max_ext_hifi, 0, 0, skip_hom, + ob, ub, &(wc[0]), &(wm[0]))) { + mm_c = wc[0]; mm_m = wm[0]; mm_v = v; + } + + ob->n = ub->n = 0; + if(ulg_bub_pop1(uidx, ug, w, max_dist, &b, max_ext, max_ext_hifi, 0, 0, skip_hom, + ob, ub, &(wc[1]), &(wm[1]))) { + if((wc[1] < mm_c) && (wc[1] == mm_c && wm[1] > mm_m)) { + mm_c = wc[1]; mm_m = wm[1]; mm_v = w; + } + } + + if(mm_v != (uint32_t)-1) { + ob->n = ub->n = 0; + w = ulg_bub_pop1(uidx, ug, mm_v, max_dist, &b, max_ext, max_ext_hifi, 0, 1, skip_hom, ob, ub, &(wc[0]), &(wm[0])); + assert(w); + n_pop += w; + } + } + } + } + + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + if(n_pop) asg_cleanup(g); + if(!in) {free(tx.a);} if(!ib) {free(tb.a);} + // fprintf(stderr, "[M::%s::] Done...\n", __func__); + return n_pop; +} + +/** +void infer_reliable_regions(ul_resolve_t *uidx, asg64_v *b) +{ + ul2ul_idx_t *idx = &(uidx->uovl); ma_ug_t *iug = idx->i_ug; ma_ug_t *raw = uidx->l1_ug; + uint64_t k, z, v, l, nv, uv, uw, bv, bw, is_bv_ul, is_bw_ul; ma_utg_t *iu; uinfo_srt_warp_t *seq; + uint8_t *raw_idx; CALLOC(raw_idx, raw->u.n<<1); + uint64_t *iu_idx; CALLOC(iu_idx, iug->u.n); uint32_t *iu_a; + asg_t *g = asg_init(); asg_arc_t *av; + + + for (k = l = 0; k < iug->u.n; k++) { + seq = &(idx->cc.iug_a[k]); + iu_idx[k] = l; iu_idx[k] <<= 32; iu_idx[k] += (l + seq->n); + l += seq->n; + } + + MALLOC(iu_a, l); + for (k = b->n = 0; k < iug->u.n; k++) { + seq = &(idx->cc.iug_a[k]); + v = k<<1; uv = v; + bv = iug->u.a[uv>>1].a[((uv&1)?(0):(iug->u.a[uv>>1].n-1))]>>32; if(uv&1) bv ^= 1; + is_bv_ul = ulg_type((*idx), (bv>>1)); av = asg_arc_a(iug->g, v); nv = asg_arc_n(iug->g, v); + for (z = 0; z < nv; z++) { + if(av[z].del || (av[z].v>>1) >= k) continue; + uw = av[z].v; bw = iug->u.a[uw>>1].a[((uw&1)?(iug->u.a[uw>>1].n-1):(0))]>>32; + if(uw&1) bw ^= 1; is_bw_ul = ulg_type((*idx), (bw>>1)); + } + + + + + v = (k<<1)+1; uv = v; + bv = iug->u.a[uv>>1].a[((uv&1)?(0):(iug->u.a[uv>>1].n-1))]>>32; if(uv&1) bv ^= 1; + is_bv_ul = ulg_type((*idx), (bv>>1)); av = asg_arc_a(iug->g, v); nv = asg_arc_n(iug->g, v); + for (z = 0; z < nv; z++) { + if(av[z].del || (av[z].v>>1) >= k) continue; + uw = av[z].v; bw = iug->u.a[uw>>1].a[((uw&1)?(iug->u.a[uw>>1].n-1):(0))]>>32; + if(uw&1) bw ^= 1; is_bw_ul = ulg_type((*idx), (bw>>1)); + } + } + +} + +void fill_u2g(ul_resolve_t *uidx, asg64_v *b, asg64_v *ub) +{ + renew_ul2_utg(uidx); + infer_reliable_regions(uidx); +} +**/ + +uint64_t get_ug_integer_seq_occ(ul_resolve_t *uidx, uint64_t *u_a, uint64_t u_n, asg64_v *b) +{ + uint32_t bn = b->n, k, occ; ma_ug_t *raw = uidx->l1_ug; + gen_ug_integer_seq_on_fly(uidx, u_a, u_n, b); + for (k = bn, occ = 0; k < b->n; k++) occ += raw->u.a[b->a[k]>>1].n; + b->n = bn; + return occ; +} + +uint32_t ul_occ_check(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t qocc_ul, uint32_t qocc_hifi, uint32_t tv, float occ_rate, asg64_v *b, asg64_v *ub) +{ + uint32_t bn = b->n, z, tocc_ul, tocc_hifi, ul; + get_ul_path_info(uidx, ug, tv, NULL, NULL, NULL, NULL, NULL, b); + for (z = bn, tocc_ul = 0; z < b->n; z++) { + get_iug_u_raw_occ(uidx, b->a[z]>>1, &ul, NULL); tocc_ul += ul; + } + tocc_hifi = get_ug_integer_seq_occ(uidx, b->a + bn, b->n - bn, ub); + b->n = bn; + if((qocc_ul <= (tocc_ul*occ_rate)) && (qocc_hifi <= (tocc_hifi*occ_rate))) return 1; + return 0; +} + +uint32_t idx_check_rate(uint64_t *a, uint64_t a_n, uint64_t tot, uint64_t winlen, float match_rate) +{ + if(a_n == 0) return 0; + if(tot < winlen) winlen = tot; + uint64_t k, mm = a[0]>>32, ks, s, e; int64_t p; + s = 0; e = winlen; + for (k = ks = 0; k < a_n; k++) { + assert(a[k] != (uint64_t)-1); + // if(mm != (a[k]>>32)) { + // fprintf(stderr, "***[M::%s::] mm::%lu, (a[%lu]>>32)::%lu\n", + // __func__, mm, k, (a[k]>>32)); + // } + assert(mm == (a[k]>>32)); + if(((uint32_t)a[k]) >= s && ((uint32_t)a[k]) < e) continue; + break; + } + p = k; + if(p > 0 && p >= (int64_t)(winlen*match_rate)) return 1; + + for (; k < a_n; k++) { + assert(a[k] != (uint64_t)-1); + assert(mm == (a[k]>>32)); + e = ((uint32_t)a[k]) + 1; p++; + for (; ks < k; ks++) { + if(e - ((uint32_t)a[ks]) <= winlen) break; + p--; + } + assert(p >= 0); + if(p > 0 && p >= (int64_t)(winlen*match_rate)) return 1; + } + return 0; +} + +uint32_t ul_homo_path_check(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t v, uint32_t w, uint32_t raw_ug_occ, float match_rate, asg64_v *b, asg64_v *rb) +{ + // if(((v>>1) == 8158 && (w>>1) == 22318) || ((v>>1) == 16783 && (w>>1) == 28464)) { + // fprintf(stderr, "\n++++++[M::%s::] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u\n", + // __func__, v>>1, v&1, w>>1, w&1); + // } + + bubble_type *bub = uidx->bub; + uint64_t k, l, z, bn = b->n, vn = 0, wn = 0, *va, *wa, rbn = rb->n, *rva, *rwa, rvn, rwn, rid, x; + get_ul_path_info(uidx, ug, v, NULL, NULL, NULL, NULL, NULL, b); vn = b->n - bn; + get_ul_path_info(uidx, ug, w, NULL, NULL, NULL, NULL, NULL, b); wn = b->n - bn - vn; + va = b->a + bn; wa = b->a + bn + vn; + // if(((v>>1) == 8158 && (w>>1) == 22318) || ((v>>1) == 16783 && (w>>1) == 28464)) { + // fprintf(stderr, "[M::%s::] vn::%lu, wn::%lu\n", __func__, vn, wn); + // } + + gen_ug_integer_seq_on_fly(uidx, va, vn, rb); rvn = rb->n - rbn; + gen_ug_integer_seq_on_fly(uidx, wa, wn, rb); rwn = rb->n - rbn - rvn; + rva = rb->a + rbn; rwa = rb->a + rbn + rvn; + // if(((v>>1) == 8158 && (w>>1) == 22318) || ((v>>1) == 16783 && (w>>1) == 28464)) { + // fprintf(stderr, "[M::%s::] rvn::%lu, rwn::%lu, raw_ug_occ::%u\n", __func__, rvn, rwn, raw_ug_occ); + // } + + b->n = bn; + for (k = 0; k < rvn; k++) { + rid = rva[k]>>1; + if(IF_BUB(rid, *bub)) { + x = bub->index[rid]; + x |= ((uint64_t)(0x80000000)); x <<= 32; ///bubble id + } else { + x = rid; ///node id + x <<= 32; + } + x |= (k<<1); kv_push(uint64_t, *b, x); + } + + for (k = 0; k < rwn; k++) { + rid = rwa[k]>>1; + if(IF_BUB(rid, *bub)) { + x = bub->index[rid]; + x |= ((uint64_t)(0x80000000)); x <<= 32; ///bubble id + } else { + x = rid; ///node id + x <<= 32; + } + x |= 1; x |= (k<<1); kv_push(uint64_t, *b, x); + } + radix_sort_srt64(b->a + bn, b->a + b->n); + + uint64_t o[2], c[2]; + for (l = bn, k = bn + 1, o[0] = o[1] = 0; k <= b->n; k++) { + if (k == b->n || (b->a[k]>>32) != (b->a[l]>>32)) { + if((k - l > 1)) { + for (z = l, c[0] = c[1] = 0; z < k; z++) { + c[b->a[z]&1]++; + if(c[0] > 0 && c[1] > 0) break; + } + if(c[0] > 0 && c[1] > 0) { + for (z = l; z < k; z++) { + o[b->a[z]&1]++; + + x = b->a[z]; + x <<= 32; x >>= 32; x >>= 1; + if(b->a[z]&1) x|= ((uint64_t)(0x100000000)); + b->a[z] = x; + } + } else { + for (z = l; z < k; z++) b->a[z] = (uint64_t)-1; + } + } else { + for (z = l; z < k; z++) b->a[z] = (uint64_t)-1; + } + l = k; + } + } + // fprintf(stderr, "\n[M::%s::] rvn::%lu, rwn::%lu, bn::%lu, b->n::%lu, o[0]::%lu, o[1]::%lu\n", __func__, + // rvn, rwn, bn, (uint64_t)b->n, o[0], o[1]); + radix_sort_srt64(b->a + bn, b->a + b->n); b->n = bn + o[0] + o[1]; + b->n = bn; rb->n = rbn; + + if(idx_check_rate(b->a + bn, o[0], rvn, raw_ug_occ, match_rate)) return 1; + if(idx_check_rate(b->a + bn + o[0], o[1], rwn, raw_ug_occ, match_rate)) return 1; + + // if(o[0] >= (rvn*match_rate)) return 1; + // if(o[1] >= (rwn*match_rate)) return 1; + + return 0; +} + +///small_occ_rate = 0.15; len_rat = 1.5 +uint32_t ulg_arc_cut_z(ul_resolve_t *uidx, ma_ug_t *ug, uint32_t max_ext, uint32_t max_ext_hifi, +float len_rat, float small_occ_rate, uint32_t raw_ug_occ, float raw_match_rate, uint32_t is_trio, +uint32_t skip_hom, uint32_t *max_drop_len, asg64_v *in, asg64_v *ib) +{ + asg64_v tx = {0,0,0}, tb = {0,0,0}, *b = NULL, *ub = NULL; asg_t *g = ug->g; + uint32_t v, w, wt, z, i, k, kv, nv, kw, kwt, nw, cnt = 0, n_vtx = g->n_seq<<1, ul, vp[2], wp[2]; + asg_arc_t *av, *aw, *ve, *we, *wte; uint64_t w_q, w_t, pb, raw_ul, raw_hifi; + + b = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); + for (v = b->n = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + av = asg_arc_a(g, v); nv = asg_arc_n(g, v); + if (nv < 2) continue; + for (i = kv = 0; i < nv && kv <= 2; ++i) { + if(av[i].del) {continue;} kv++; + } + if(kv != 2) continue; + for (i = 0; i < nv; ++i) { + if(av[i].del) continue; + kw = get_arcs(ug->g, av[i].v^1, NULL, 0); + // if((v>>1) == 16783) { + // fprintf(stderr, "sss[M::%s::] v>>1::%u, v&1::%u, av[i].v>>1::%u, av[i].v&1::%u, kw::%u\n", + // __func__, v>>1, v&1, av[i].v>>1, av[i].v&1, kw); + // } + if(kw == 2) { + kv_push(uint64_t, *b, ((uint64_t)(av-g->arc+i))); + } else if(kw == 1) { + ub->n = 0; + if(get_ul_path_info(uidx, ug, av[i].v, NULL, NULL, NULL, NULL, NULL, ub)==TWO_INPUT) { + for (z = raw_ul = 0; z < ub->n; z++) { + get_iug_u_raw_occ(uidx, ub->a[z]>>1, &ul, NULL); raw_ul += ul; + } + kv_push(uint64_t, *b, ((raw_ul<<32)|((uint64_t)(av-g->arc+i)))); + } + } + } + } + + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + if(g->arc[(uint32_t)b->a[k]].del) continue; + v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; + if(g->seq[v>>1].del || g->seq[w>>1].del) continue; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); + if(nv <= 1 && nw <= 1) continue; + + vp[0] = v^1; vp[1] = (uint32_t)-1; + ve = &(g->arc[(uint32_t)b->a[k]]); + for (i = kv = 0; i < nv; ++i) { + if(av[i].del) continue; + if(av[i].v != (w^1)) vp[1] = av[i].v; + kv++; + } + + wp[0] = w^1; wp[1] = (uint32_t)-1; + for (i = kw = 0, we = NULL; i < nw; ++i) { + if (aw[i].del) continue; + if (aw[i].v == (v^1)) we = &(aw[i]); + else wp[1] = aw[i].v; + kw++; + } + if(kv <= 1 && kw <= 1) continue; + if(kv != 2 || kw > 2) continue; + // if((v>>1) == 16783) { + // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, kv::%u, kw::%u\n", + // __func__, v>>1, v&1, w>>1, w&1, kv, kw); + // } + raw_ul = 0; wt = w; wte = we; kwt = kw; pb = b->n; ub->n = 0; + if(kw == 1) { + if(get_ul_path_info(uidx, ug, w^1, &wt, NULL, NULL, NULL, NULL, b)==TWO_INPUT) { + for (z = pb, raw_ul = 0; z < b->n; z++) { + get_iug_u_raw_occ(uidx, b->a[z]>>1, &ul, NULL); raw_ul += ul; + } + ul = wt; get_arcs(ug->g, wt, &wt, 1); wt = ug->g->arc[wt].v^1; + wp[0] = wt^1; wp[1] = (uint32_t)-1; + nw = asg_arc_n(g, wt); aw = asg_arc_a(g, wt); + for (i = kwt = 0; i < nw; ++i) { + if (aw[i].del) continue; + if (aw[i].v == (ul^1)) wte = &(aw[i]); + else wp[1] = aw[i].v; + kwt++; + } + // if((v>>1) == 16783) { + // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, w>>1::%u, w&1::%u, wt>>1::%u, wt&1::%u, kwt::%u\n", + // __func__, v>>1, v&1, w>>1, w&1, wt>>1, wt&1, kwt); + // } + nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); + } else { + b->n = pb; + continue; + } + } + // if((v>>1) == 16783) { + // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, raw_ul::%lu, max_ext::%u, ***1***\n", + // __func__, v>>1, v&1, raw_ul, max_ext); + // } + assert(kv == 2 && kwt == 2); + if(raw_ul <= max_ext && get_remove_hifi_occ(uidx, max_ext_hifi, b->a + pb, b->n - pb, ub, NULL)) { + raw_hifi = get_ug_integer_seq_occ(uidx, b->a + pb, b->n - pb, ub); + // if((v>>1) == 16783) { + // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, ***2***\n", + // __func__, v>>1, v&1); + // } + + b->n = pb; + if(raw_ul > 0) { + if(!ul_occ_check(uidx, ug, raw_ul, raw_hifi, vp[0], small_occ_rate, b, ub)) continue; + if(!ul_occ_check(uidx, ug, raw_ul, raw_hifi, vp[1], small_occ_rate, b, ub)) continue; + if(!ul_occ_check(uidx, ug, raw_ul, raw_hifi, wp[0], small_occ_rate, b, ub)) continue; + if(!ul_occ_check(uidx, ug, raw_ul, raw_hifi, wp[1], small_occ_rate, b, ub)) continue; + } + + // if((v>>1) == 16783) { + // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, ***3***\n", + // __func__, v>>1, v&1); + // } + pb = b->n; ub->n = 0; + get_ul_arc_supports(uidx, ve, b, ub, skip_hom, &w_q, &w_t); + b->n = pb; ub->n = 0; + if((w_q == (uint64_t)-1) || (w_q > w_t*len_rat)) continue; + + // if((v>>1) == 16783) { + // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, ***4***\n", + // __func__, v>>1, v&1); + // } + + pb = b->n; ub->n = 0; + get_ul_arc_supports(uidx, wte, b, ub, skip_hom, &w_q, &w_t); + b->n = pb; ub->n = 0; + if((w_q == (uint64_t)-1) || (w_q > w_t*len_rat)) continue; + + // if((v>>1) == 16783) { + // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, ***5***\n", + // __func__, v>>1, v&1); + // } + + if(!ul_homo_path_check(uidx, ug, vp[0], wp[1], raw_ug_occ, raw_match_rate, b, ub)) continue; + + + // if((v>>1) == 16783) { + // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, ***6***\n", + // __func__, v>>1, v&1); + // } + if(!ul_homo_path_check(uidx, ug, wp[0], vp[1], raw_ug_occ, raw_match_rate, b, ub)) continue; + + // if((v>>1) == 16783) { + // fprintf(stderr, "bbb[M::%s::] v>>1::%u, v&1::%u, ***7***\n", + // __func__, v>>1, v&1); + // } + + if(kw == 1) { + get_ul_path_info(uidx, ug, w^1, &wt, NULL, NULL, NULL, NULL, b); + for (z = pb; z < b->n; z++) ulg_seq_del(ug, (b->a[z]>>1)); + } + ve->del = we->del = 1; cnt++; + } + + b->n = pb; + } + + + + if(!in) {free(tx.a);} if(!ib) {free(tb.a);} + if (cnt > 0) asg_cleanup(g); + // fprintf(stderr, "[M::%s::] cnt::%u\n", __func__, cnt); + return cnt; +} + + +usg_seq_t *push_usg_t_node(usg_t *ng, uint64_t id) +{ + if(id >= ng->m) { + uint64_t m = ng->m; + kv_resize(usg_seq_t, *ng, id + 1); + memset(ng->a + m, 0, (ng->m - m)*(sizeof((*ng->a)))); + } + if(id >= ng->n) ng->n = id + 1; + + return ng->a + id; +} + +static void worker_update_ul_arc_drop(void *data, long i, int tid) // callback for kt_for() +{ + ul_resolve_t *uidx = (ul_resolve_t *)data; integer_t *buf = &(uidx->str_b.buf[tid]); + ul_str_idx_t *str_idx = &(uidx->pstr); uinfo_srt_warp_t *seq = uidx->uovl.iug_seq; + uint32_t v = seq->a[i].v, z, vz; uint64_t *hid_a, hid_n; ul_str_t *str; + int64_t s_n, s, p, p_n = seq->n; uint64_t cutoff = uidx->uovl.iug_cov_thre, occ; + + hid_a = str_idx->occ.a + str_idx->idx.a[v>>1]; + hid_n = str_idx->idx.a[(v>>1)+1] - str_idx->idx.a[v>>1]; + for (z = occ = 0; z < hid_n; z++) { + str = &(str_idx->str.a[hid_a[z]>>32]); s_n = str->cn; + if(s_n < 2) continue; + vz = (uint32_t)(str->a[(uint32_t)hid_a[z]]); + assert((v>>1) == (vz>>1)); + + if(v == vz) { + s = ((uint32_t)hid_a[z]) + 1; p = i + 1; + if((s < s_n) && (p < p_n) && ((uint32_t)(str->a[s]) == seq->a[p].v)) { + occ++; + } + } else { + s = ((int32_t)((uint32_t)hid_a[z]))-1; p = i + 1; + if((s >= 0) && (p < p_n) && ((uint32_t)(str->a[s]) == (seq->a[p].v^1))) { + occ++; + } + } + if(occ >= cutoff) break; + } + + if(occ < cutoff) kv_push(uint64_t, buf->res_dump, i); +} + +inline usg_arc_t* get_usg_arc(usg_t *g, uint32_t v, uint32_t w) +{ + usg_arc_t *av = usg_arc_a(g, v); uint32_t nv = usg_arc_n(g, v), k; + for (k = 0; k < nv; k++) { + if(av[k].v == w) break; + } + + if(k < nv) return (&av[k]); + return NULL; +} + +void pushp_usg_arc_mm(usg_t *g, uint32_t v, uint32_t w, uint32_t uid, uint32_t off) +{ + usg_arc_mm_t *pm; + kv_pushp(usg_arc_mm_t, g->a[v>>1].arc_mm[v&1], &pm); + pm->v = w; pm->uid = uid; pm->off = off; +} + +static inline void usg_seq_del(usg_t *g, uint32_t s) +{ + uint32_t i, nv, v; usg_arc_t *av, *p; + g->a[s].del = 1; + // fprintf(stderr, "\n#[M::%s::] s::%u\n", __func__, s); + v = s<<1; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (i = 0; i < nv; ++i) { + av[i].del = 1; + p = get_usg_arc(g, av[i].v^1, v^1); + // if(!p) { + // fprintf(stderr, "**+**[M::%s::] v>>1::%u, v&1::%u, av[i].v>>1::%u, av[i].v&1::%u\n", + // __func__, v>>1, v&1, av[i].v>>1, av[i].v&1); + // } + p->del = 1; + } + + v = (s<<1)+1; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (i = 0; i < nv; ++i) { + av[i].del = 1; + p = get_usg_arc(g, av[i].v^1, v^1); + // if(!p) { + // fprintf(stderr, "**-**[M::%s::] v>>1::%u, v&1::%u, av[i].v>>1::%u, av[i].v&1::%u\n", + // __func__, v>>1, v&1, av[i].v>>1, av[i].v&1); + // } + p->del = 1; + } + + // g->a[s].arc[0].n = g->a[s].arc[1].n = 0; +} + +static void worker_clean_usg(void *data, long i, int tid) // callback for kt_for() +{ + usg_t *g = (usg_t *)data; usg_seq_t *z = g->a + i; uint32_t k, m, l, srt; + usg_arc_warp *x; usg_arc_mm_warp *y; + if(z->del) z->arc[0].n = z->arc[1].n = 0; + + x = &(z->arc[0]); y = &(z->arc_mm[0]); + for (k = m = srt = 0; k < x->n; k++) { + if(x->a[k].del) continue; + x->a[m] = x->a[k]; x->a[m].idx = 0; + if(m > 0 && x->a[m].v < x->a[m-1].v) srt = 1; + m++; + } + x->n = m; if(srt) radix_sort_usg_arc_srt(x->a, x->a + x->n); + + radix_sort_usg_arc_mm_srt(y->a, y->a + y->n); k = l = m = 0; + while (k < y->n && l < x->n) { + if(y->a[k].v < x->a[l].v) { + k++; + } else if(y->a[k].v > x->a[l].v) { + l++; + } else { + y->a[m].v = y->a[k].v; + if(m > 0 && y->a[m].v == y->a[m-1].v) { + x->a[l].idx++; + } else { + x->a[l].idx = m; x->a[l].idx <<= 32; x->a[l].idx++; + } + m++; k++; + } + } + y->n = m; + + + + x = &(z->arc[1]); y = &(z->arc_mm[1]); + for (k = m = srt = 0; k < x->n; k++) { + if(x->a[k].del) continue; + x->a[m] = x->a[k]; x->a[m].idx = 0; + if(m > 0 && x->a[m].v < x->a[m-1].v) srt = 1; + m++; + } + x->n = m; if(srt) radix_sort_usg_arc_srt(x->a, x->a + x->n); + + radix_sort_usg_arc_mm_srt(y->a, y->a + y->n); k = l = m = 0; + while (k < y->n && l < x->n) { + if(y->a[k].v < x->a[l].v) { + k++; + } else if(y->a[k].v > x->a[l].v) { + l++; + } else { + y->a[m].v = y->a[k].v; + if(m > 0 && y->a[m].v == y->a[m-1].v) { + x->a[l].idx++; + } else { + x->a[l].idx = m; x->a[l].idx <<= 32; x->a[l].idx++; + } + m++; k++; + } + } + y->n = m; + +} + +void usg_cleanup(usg_t *g) +{ + kt_for(asm_opt.thread_num, worker_clean_usg, g, g->n); +} + +static inline int usg_end(const usg_t *g, uint32_t v, uint64_t *lw) +{ + ///v^1 is the another direction of v + uint32_t w, nv, nw, nw0, nv0 = usg_arc_n(g, v^1); + int i, i0 = -1; + usg_arc_t *aw, *av = usg_arc_a(g, v^1); + + ///if this arc has not been deleted + for (i = nv = 0; i < (int)nv0; ++i) + if (!av[i].del) i0 = i, ++nv; + + ///end without any out-degree + if (nv == 0) return ASG_ET_TIP; // tip + if (nv > 1) return ASG_ET_MULTI_OUT; // multiple outgoing arcs + ///until here, nv == 1 + if (lw) *lw = ((uint64_t)(v^1))<<32 | av[i0].v; + w = av[i0].v^1; + nw0 = usg_arc_n(g, w); aw = usg_arc_a(g, w); + for (i = nw = 0; i < (int)nw0; ++i) + if (!aw[i].del) ++nw; + + if (nw != 1) return ASG_ET_MULTI_NEI; + return ASG_ET_MERGEABLE; +} + +uint32_t usg_real_tip(usg_t *g, uint32_t v0, double rate) +{ + usg_arc_t *av, *aw; uint32_t nv, nw, i, k, ov, ow; + av = usg_arc_a(g, v0); + nv = usg_arc_n(g, v0); + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + aw = usg_arc_a(g, (av[i].v^1)); + nw = usg_arc_n(g, (av[i].v^1)); + for (k = ov = ow = 0; k < nw; k++) { + if(aw[k].del) continue; + if((aw[k].v>>1) == (v0>>1)) { + if(aw[k].ol > ov) ov = aw[k].ol; + } else { + if(aw[k].ol > ow) ow = aw[k].ol; + } + } + if(ow == 0 || ov >= ow) return 0; + if(ov > (ow*rate)) return 0; + } + return 1; +} + + +uint32_t usg_arc_cut_tips(usg_t *g, uint32_t max_ext, uint32_t ignore_ul, asg64_v *in) +{ + asg64_v tx = {0,0,0}, *b = NULL; + uint32_t n_vtx = g->n<<1, v, w, i, k, cnt = 0, nv, kv, pb, ff, is_telo; + usg_arc_t *av = NULL, *p; uint64_t lw; + if(in) b = in; + else b = &tx; + + for (v = b->n = 0; v < n_vtx; ++v) { + if (g->a[v>>1].del) continue; + + av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); + for (i = kv = 0; i < nv; i++) { + if (av[i].del) continue; + kv++; break; + } + + if(kv) continue; + + is_telo = 0; if(g->a[v>>1].telo) is_telo = 1; + for (i = 0, w = v, kv = g->a[v>>1].occ; i < max_ext; i++) { + if(usg_end(g, w^1, &lw)!=0) break; + w = (uint32_t)lw; kv += g->a[w>>1].occ; + if(g->a[w>>1].telo) is_telo = 1; + } + if((kv <= max_ext) && (!is_telo)) kv_push(uint64_t, *b, (((uint64_t)kv)<<32)|v); + } + + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + v = (uint32_t)(b->a[k]); + if (g->a[v>>1].del) continue; + + av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); + for (i = kv = 0; i < nv; i++) { + if (av[i].del) continue; + kv++; break; + } + + if(kv) continue; + pb = b->n; kv_push(uint64_t, *b, v); + is_telo = 0; if(g->a[v>>1].telo) is_telo = 1; + for (i = 0, w = v, kv = g->a[v>>1].occ; i < max_ext; i++) { + if(usg_end(g, w^1, &lw)!=0) break; + w = (uint32_t)lw; kv += g->a[w>>1].occ; kv_push(uint64_t, *b, lw); + if(g->a[w>>1].telo) is_telo = 1; + } + // if((v>>1) == 308) { + // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, kv::%u\n", + // __func__, v>>1, v&1, kv); + // } + + + if((kv <= max_ext) && (!is_telo)) { + ff = 0; + if(!ignore_ul) {///consider UL + for (i = pb; i + 1 < b->n; i++) { + p = get_usg_arc(g, ((uint32_t)b->a[i]), ((uint32_t)b->a[i+1])); assert(p); + if(p->ou > 1) {//ignore ou == 1 + ff = 1; + break; + } + } + + if(ff == 0 && i < b->n) { + av = usg_arc_a(g, ((uint32_t)b->a[i])); nv = usg_arc_n(g, ((uint32_t)b->a[i])); + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + if(av[i].ou > 1) {//ignore ou == 1 + ff = 1; + break; + } + } + } + } + + // if((v>>1) == 139131) { + // fprintf(stderr, "+[M::%s::] v>>1::%u, v&1::%u, kv::%u, ff::%u, pb::%u, b->n::%u, w>>1::%u, w&1::%u\n", __func__, v>>1, v&1, kv, + // ff, pb, (uint32_t)b->n, ((uint32_t)b->a[b->n-1])>>1, ((uint32_t)b->a[b->n-1])&1); + // } + + if((ff == 0) && (pb < b->n) && (!usg_real_tip(g, ((uint32_t)b->a[b->n-1]), 0.75))) { + ff = 1; + } + + // if((v>>1) == 139131) { + // fprintf(stderr, "-[M::%s::] v>>1::%u, v&1::%u, kv::%u, ff::%u, pb::%u, b->n::%u, w>>1::%u, w&1::%u\n", __func__, v>>1, v&1, kv, + // ff, pb, (uint32_t)b->n, ((uint32_t)b->a[b->n-1])>>1, ((uint32_t)b->a[b->n-1])&1); + // } + + if(ff == 0) { + for (i = pb; i < b->n; i++) usg_seq_del(g, ((uint32_t)b->a[i])>>1); + cnt++; + } + + // if((v>>1) == 139131) { + // fprintf(stderr, ">[M::%s::] v>>1::%u, v&1::%u, kv::%u, ff::%u, pb::%u, b->n::%u, w>>1::%u, w&1::%u, del::%u\n", __func__, v>>1, v&1, kv, + // ff, pb, (uint32_t)b->n, ((uint32_t)b->a[b->n-1])>>1, ((uint32_t)b->a[b->n-1])&1, + // g->a[((uint32_t)b->a[b->n-1])>>1].del); + // } + } + b->n = pb; + } + + if(!in) free(tx.a); + if(cnt > 0) usg_cleanup(g); + + return cnt; +} + +///check if v has only one branch + +int32_t usg_tip_detect(usg_t *g, uint32_t v0, int max_ext, uint8_t *f, asg64_v *z_a, asg64_v *z_b) +{ + uint64_t a_n = z_a->n, b_n = z_b->n, v = v0, kv, nv, i; + int32_t n_ext = 0; usg_arc_t *av; + + av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); + for (i = kv = 0; i < nv && kv <= 1; i++) { + if (av[i].del || f[av[i].v>>1]) continue; + kv++; + } + if(kv > 1) return 0; + n_ext += g->a[v>>1].occ; f[v>>1] = 1; kv_push(uint64_t, *z_b, v>>1); + + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (i = 0; i < nv; i++) { + if (av[i].del || f[av[i].v>>1]) continue; + kv_push(uint64_t, *z_a, av[i].v); + } + + while (z_a->n > a_n && n_ext < max_ext) { + v = z_a->a[--z_a->n]; if(f[v>>1]) continue; + + av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); + for (i = kv = 0; i < nv && kv < 1; i++) { + if (av[i].del || f[av[i].v>>1]) continue; + kv++; + } + if(kv > 0) continue; + n_ext += g->a[v>>1].occ; f[v>>1] = 1; kv_push(uint64_t, *z_b, v>>1); + + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (i = 0; i < nv; i++) { + if (av[i].del || f[av[i].v>>1]) continue; + kv_push(uint64_t, *z_a, av[i].v); + } + } + + for (i = b_n; i < z_b->n; i++) f[z_b->a[i]] = 0; + z_b->n = b_n; z_a->n = a_n; + return n_ext; +} + +int usg_naive_topocut_aux(usg_t *g, uint32_t v, int max_ext, uint8_t *f, asg64_v *b0, asg64_v *b1) +{ + int32_t n_ext; usg_arc_t *av; uint32_t w = v, v0 = v, nv, i, kv, tip; + for (n_ext = tip = 0; n_ext < max_ext; v = w) { + tip = 0; + av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); + for (i = kv = 0; i < nv && kv <= 1; i++) { + if (av[i].del) continue; + kv++; + } + if(kv!=1) break; + n_ext += g->a[v>>1].occ; + + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (i = kv = 0; i < nv && kv <= 1; i++) { + if (av[i].del) continue; + kv++; w = av[i].v; + } + if(kv!=1) { + if(kv > 1) tip = 1; + break; + } + } + + if(n_ext < max_ext && tip) { + n_ext = usg_tip_detect(g, v0, max_ext, f, b0, b1); + } + return n_ext; +} + + +int usg_naive_topocut_aux_sec(usg_t *g, uint32_t v0, int max_ext) +{ + int32_t n_ext = 0; usg_arc_t *av; uint32_t w = (uint32_t)-1, v = v0, nv, i, kv, tip[2] = {0}; + v = v0; + while (1) { + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (i = kv = 0; i < nv; i++) { + if (av[i].del) continue; + kv++; w = av[i].v; + } + n_ext += g->a[v>>1].occ; + // if((v0>>1) == 306) { + // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, n_ext::%d\n", __func__, v>>1, v&1, n_ext); + // } + if(kv != 1) { + if(kv == 0) tip[0] = 1; + break; + } + v = w; + + av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); + for (i = kv = 0; i < nv; i++) { + if (av[i].del) continue; + kv++; + } + if(kv != 1) break; + if(v == v0) return 0;///circle, it is ok to remove it + } + + v = v0^1; + while (1) { + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (i = kv = 0; i < nv; i++) { + if (av[i].del) continue; + kv++; w = av[i].v; + } + n_ext += g->a[v>>1].occ; + // if((v0>>1) == 306) { + // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, n_ext::%d\n", __func__, v>>1, v&1, n_ext); + // } + if(kv != 1) { + if(kv == 0) tip[1] = 1; + break; + } + v = w; + + av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); + for (i = kv = 0; i < nv; i++) { + if (av[i].del) continue; + kv++; + } + if(kv != 1) break; + if(v == (v0^1)) return 0;///circle, it is ok to remove it + } + + n_ext -= g->a[v0>>1].occ; + // if((v0>>1) == 306) { + // fprintf(stderr, "[M::%s::] n_ext::%d, tip[0]::%u, tip[1]::%u\n", __func__, n_ext, tip[0], tip[1]); + // } + if((tip[0] || tip[1]) && (n_ext >= max_ext)) return n_ext; + + return 0; +} + +void usg_arc_cut_length(usg_t *g, asg64_v *in_0, asg64_v *in_1, int32_t max_ext, float len_rat, uint32_t is_trio, +uint32_t is_topo, uint32_t *max_drop_len) +{ + // if(len_rat > 0.7) { + // fprintf(stderr, "+[M::%s::] max_ext::%d, len_rat::%f\n", __func__, max_ext, len_rat); + // } + asg64_v tx = {0,0,0}, tz = {0,0,0}, *b = NULL, *ub = NULL; + uint32_t i, k, v, w, n_vtx = g->n<<1, nv, nw, kv, kw, /**trioF = (uint32_t)-1, ntrioF = (uint32_t)-1,**/ ol_max, ou_max, to_del, cnt = 0, mm_ol; + usg_arc_t *av = NULL, *aw = NULL, *ve = NULL, *we = NULL; uint64_t x, kocc[2], ou; uint8_t *f; CALLOC(f, g->n); + b = ((in_0)?(in_0):(&tx)); ub = ((in_1)?(in_1):(&tz)); + + for (v = 0, b->n = ub->n = 0; v < n_vtx; ++v) { + if (g->a[v>>1].del) continue; + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + if (nv < 2) continue; + for (i = kv = kocc[0] = kocc[1] = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + if((av[i].ou>>1) > 0) { ///if av[i].ou == 1, ignore it + if(kocc[1] < (av[i].ou>>1)) kocc[1] = (av[i].ou>>1); + } else if(av[i].ou == 0) { + kocc[0]++; + } + } + if(kv < 2 || kocc[0] == 0 || kocc[1] == 0) continue; + ou = kocc[1]; + for (i = 0; i < nv; ++i) { + if(av[i].del || av[i].ou) continue; + if(max_drop_len && av[i].ol >= (*max_drop_len)) continue; + x = (((uint64_t)av[i].ol)*10)/ou; x <<= 32; + kv_push(uint64_t, *b, ((x)|((uint64_t)(ub->n)))); + kv_push(uint64_t, *ub, ((((uint64_t)(v))<<32)|((uint64_t)(i)))); + } + } + // if(len_rat > 0.7) { + // fprintf(stderr, "[M::%s::] max_ext::%d, len_rat::%f, b->n::%u, ub->n::%u\n", + // __func__, max_ext, len_rat, (uint32_t)b->n, (uint32_t)ub->n); + // } + + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + v = ub->a[(uint32_t)b->a[k]]>>32; + ve = &(usg_arc_a(g, v)[(uint32_t)(ub->a[(uint32_t)b->a[k]])]); + w = ve->v^1; + if(ve->del || g->a[v>>1].del || g->a[w>>1].del || ve->ou) continue; + nv = usg_arc_n(g, v); nw = usg_arc_n(g, w); + av = usg_arc_a(g, v); aw = usg_arc_a(g, w); + if(nv<=1 && nw <= 1) continue; + + // if(is_trio) { + // if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup + // trioF = get_tip_trio_infor(g, v^1); + // ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); + // } + for (i = 0; i < nw; ++i) { + if (aw[i].v == (v^1)) { + we = &(aw[i]); + break; + } + } + mm_ol = MIN(ve->ol, we->ol); kocc[0] = kocc[1] = 0; + + for (i = kv = ol_max = ou_max = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + if(av[i].ou != 1) kocc[!!(av[i].ou)]++; ///if av[i].ou == 1, ignore it + // if(is_trio && get_tip_trio_infor(g, av[i].v) == ntrioF) continue; + if(ol_max < av[i].ol) ol_max = av[i].ol; + } + if (kv < 1 || kocc[0] < 1 || kocc[1] < 1) continue; + if (kv >= 2) { + if (mm_ol > ol_max*len_rat) continue; + } + + + for (i = kw = ol_max = ou_max = 0; i < nw; ++i) { + if(aw[i].del) continue; + kw++; + // if(is_trio && get_tip_trio_infor(g, aw[i].v) == ntrioF) continue; + if(ol_max < aw[i].ol) ol_max = aw[i].ol; + } + if (kw < 1) continue; + if (kw >= 2) { + if (mm_ol > ol_max*len_rat) continue; + } + + if (kv <= 1 && kw <= 1) continue; + // if(len_rat > 0.7) { + // fprintf(stderr, "0[M::%s::] v>>1::%u(%c), w>>1::%u(%c), kv::%u, kw::%u\n", + // __func__, v>>1, "+-"[v&1], w>>1, "+-"[w&1], kv, kw); + // } + + to_del = 1; + if(is_topo) { + to_del = 0; + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (usg_naive_topocut_aux(g, w^1, max_ext, f, b, ub) < max_ext) to_del = 1; + } else if (kv == 1) { + if (usg_naive_topocut_aux(g, v^1, max_ext, f, b, ub) < max_ext) to_del = 1; + } + } + // if(len_rat > 0.7) { + // fprintf(stderr, "1[M::%s::] v>>1::%u(%c), w>>1::%u(%c), kv::%u, kw::%u, to_del::%u\n", + // __func__, v>>1, "+-"[v&1], w>>1, "+-"[w&1], kv, kw, to_del); + // } + + if (to_del) { + ve->del = we->del = 1; + if((usg_naive_topocut_aux_sec(g, v, max_ext) < max_ext) && + (usg_naive_topocut_aux_sec(g, w, max_ext) < max_ext)) { + // if((((v>>1) == 308) && ((w>>1) == 311)) || (((w>>1) == 308) && ((v>>1) == 311))) { + // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, max_ext::%d\n", + // __func__, v>>1, v&1, kv, w>>1, w&1, kw, max_ext); + // } + // if((((v>>1) == 306) && ((w>>1) == 310)) || (((w>>1) == 306) && ((v>>1) == 310))) { + // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, max_ext::%d\n", + // __func__, v>>1, v&1, kv, w>>1, w&1, kw, max_ext); + // } + ++cnt; + } else { + ve->del = we->del = 0; + } + + } + // if(len_rat > 0.7) { + // fprintf(stderr, "2[M::%s::] v>>1::%u(%c), w>>1::%u(%c), kv::%u, kw::%u, to_del::%u\n", + // __func__, v>>1, "+-"[v&1], w>>1, "+-"[w&1], kv, kw, to_del); + // } + } + + if(in_0) {free(tx.a);} if(in_1) {free(tz.a);} + if (cnt > 0) usg_cleanup(g); + free(f); + // fprintf(stderr, "-[M::%s::] max_ext::%d, len_rat::%f\n", __func__, max_ext, len_rat); +} + +void usg_arc_cut_srt_length(usg_t *g, asg64_v *in_0, asg64_v *in_1, int32_t max_ext, float len_rat, uint32_t is_trio, +uint32_t is_topo, uint32_t *max_drop_len, uint8_t *ff) +{ + asg64_v tx = {0,0,0}, tz = {0,0,0}, *b = NULL, *ub = NULL; + uint32_t i, k, v, w, n_vtx = g->n<<1, nv, nw, kv, kw, /**trioF = (uint32_t)-1, ntrioF = (uint32_t)-1,**/ ol_max, ou_max, to_del, cnt = 0, mm_ol; + usg_arc_t *av = NULL, *aw = NULL, *ve = NULL, *we = NULL; uint64_t x, kocc[2]; uint8_t *f; CALLOC(f, g->n); + b = ((in_0)?(in_0):(&tx)); ub = ((in_1)?(in_1):(&tz)); + + for (v = 0, b->n = ub->n = 0; v < n_vtx; ++v) { + if (g->a[v>>1].del || ff[v]) continue; + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + if (nv < 2) continue; + for (i = kv = kocc[0] = kocc[1] = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + if((av[i].ou>>1) > 0) { ///if av[i].ou == 1, ignore it + if(kocc[1] < (av[i].ou>>1)) kocc[1] = (av[i].ou>>1); + } else if(av[i].ou == 0) { + kocc[0]++; + } + } + if(kv < 2 || kocc[0] == 0 || kocc[1] == 0) continue; + for (i = 0; i < nv; ++i) { + if(av[i].del || av[i].ou) continue; + if(max_drop_len && av[i].ol >= (*max_drop_len)) continue; + x = av[i].ol; x <<= 32; + kv_push(uint64_t, *b, ((x)|((uint64_t)(ub->n)))); + kv_push(uint64_t, *ub, ((((uint64_t)(v))<<32)|((uint64_t)(i)))); + } + } + + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + v = ub->a[(uint32_t)b->a[k]]>>32; + ve = &(usg_arc_a(g, v)[(uint32_t)(ub->a[(uint32_t)b->a[k]])]); + w = ve->v^1; + if(ve->del || g->a[v>>1].del || g->a[w>>1].del || ve->ou) continue; + nv = usg_arc_n(g, v); nw = usg_arc_n(g, w); + av = usg_arc_a(g, v); aw = usg_arc_a(g, w); + if(nv<=1 && nw <= 1) continue; + + // if(is_trio) { + // if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup + // trioF = get_tip_trio_infor(g, v^1); + // ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); + // } + for (i = 0; i < nw; ++i) { + if (aw[i].v == (v^1)) { + we = &(aw[i]); + break; + } + } + mm_ol = MIN(ve->ol, we->ol); kocc[0] = kocc[1] = 0; + + for (i = kv = ol_max = ou_max = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + if(av[i].ou != 1) kocc[!!(av[i].ou)]++; ///if av[i].ou == 1, ignore it + // if(is_trio && get_tip_trio_infor(g, av[i].v) == ntrioF) continue; + if(ol_max < av[i].ol) ol_max = av[i].ol; + } + if (kv < 1 || kocc[0] < 1 || kocc[1] < 1) continue; + if (kv >= 2) { + if (mm_ol > ol_max*len_rat) continue; + } + + + for (i = kw = ol_max = ou_max = 0; i < nw; ++i) { + if(aw[i].del) continue; + kw++; + // if(is_trio && get_tip_trio_infor(g, aw[i].v) == ntrioF) continue; + if(ol_max < aw[i].ol) ol_max = aw[i].ol; + } + if (kw < 1) continue; + if (kw >= 2) { + if (mm_ol > ol_max*len_rat) continue; + } + + if (kv <= 1 && kw <= 1) continue; + // if(len_rat > 0.7) { + // fprintf(stderr, "0[M::%s::] v>>1::%u(%c), w>>1::%u(%c), kv::%u, kw::%u\n", + // __func__, v>>1, "+-"[v&1], w>>1, "+-"[w&1], kv, kw); + // } + + to_del = 1; + if(is_topo) { + to_del = 0; + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + if (usg_naive_topocut_aux(g, w^1, max_ext, f, b, ub) < max_ext) to_del = 1; + } else if (kv == 1) { + if (usg_naive_topocut_aux(g, v^1, max_ext, f, b, ub) < max_ext) to_del = 1; + } + } + // if(len_rat > 0.7) { + // fprintf(stderr, "1[M::%s::] v>>1::%u(%c), w>>1::%u(%c), kv::%u, kw::%u, to_del::%u\n", + // __func__, v>>1, "+-"[v&1], w>>1, "+-"[w&1], kv, kw, to_del); + // } + + if (to_del) { + ve->del = we->del = 1; + if((usg_naive_topocut_aux_sec(g, v, max_ext) < max_ext) && + (usg_naive_topocut_aux_sec(g, w, max_ext) < max_ext)) { + // if((((v>>1) == 308) && ((w>>1) == 311)) || (((w>>1) == 308) && ((v>>1) == 311))) { + // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, max_ext::%d\n", + // __func__, v>>1, v&1, kv, w>>1, w&1, kw, max_ext); + // } + // if((((v>>1) == 306) && ((w>>1) == 310)) || (((w>>1) == 306) && ((v>>1) == 310))) { + // fprintf(stderr, "[M::%s::] v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u, max_ext::%d\n", + // __func__, v>>1, v&1, kv, w>>1, w&1, kw, max_ext); + // } + ++cnt; + } else { + ve->del = we->del = 0; + } + + } + // if(len_rat > 0.7) { + // fprintf(stderr, "2[M::%s::] v>>1::%u(%c), w>>1::%u(%c), kv::%u, kw::%u, to_del::%u\n", + // __func__, v>>1, "+-"[v&1], w>>1, "+-"[w&1], kv, kw, to_del); + // } + } + + if(in_0) {free(tx.a);} if(in_1) {free(tz.a);} + if (cnt > 0) usg_cleanup(g); + free(f); + // fprintf(stderr, "-[M::%s::] max_ext::%d, len_rat::%f\n", __func__, max_ext, len_rat); +} + + +inline int undel_arcs(usg_t *g, uint32_t v, uint32_t* v_s) +{ + uint32_t i, nv = usg_arc_n(g, v), kv; + usg_arc_t *av = usg_arc_a(g, v); + for (i = kv = 0; i < nv; i++) { + if(av[i].del) continue; + if(v_s) v_s[kv] = av[i].v; + kv++; + } + return kv; +} + +inline uint32_t get_usg_unitig(usg_t *g, uint32_t begNode, uint32_t* endNode, +uint64_t* nodeLen, uint64_t* baseLen, uint64_t *occ, asg64_v* b) +{ + uint32_t v = begNode, w, k; usg_arc_t *av; + uint32_t nv, kv, return_flag; + if(endNode) (*endNode) = (uint32_t)-1; + if(nodeLen) (*nodeLen) = 0; + if(baseLen) (*baseLen) = 0; + if(occ) (*occ) = 0; + + while (1) { + kv = undel_arcs(g, v, NULL); + if(endNode) (*endNode) = v; + if(nodeLen) (*nodeLen) += g->a[v>>1].occ; + + if(b) kv_push(uint64_t, *b, v); + if(occ) {(*occ)++;} + ///means reach the end of a unitig + if((kv!=1) && (baseLen)) {(*baseLen) += g->a[v>>1].len;} + if(kv==0) { + return_flag = END_TIPS; break; + } + if(kv>1) { + return_flag = MUL_OUTPUT; break; + } + ///kv must be 1 here + kv = undel_arcs(g, v, &w); + ///means reach the end of a unitig + if(undel_arcs(g, w^1, NULL)!=1) { + if(baseLen) (*baseLen) += g->a[v>>1].len; + return_flag = MUL_INPUT; break; + } else if(baseLen) { + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + ///here is just one undeleted edge + (*baseLen) += asg_arc_len(av[k]); + break; + } + } + v = w; + if(v == begNode){ + return_flag = LOOP; break; + } + } + + return return_flag; +} + +uint64_t dfs_max_bub(usg_t *g, buf_t *b, uint32_t x, asg64_v *nb, uint32_t *p_bub) +{ + uint64_t len = 0, baseLen, uLen; uint32_t c_v, e_v, nv, convex, v, i, kv_0, kv_1, flag_0 = 0, flag_1 = 0, op; + usg_arc_t *av = NULL; (*p_bub) = 0; b->S.n = 0; + if(b->a[x>>1].s || g->a[x>>1].del) return 0; + kv_push(uint32_t, b->S, x); + // fprintf(stderr, "\n[M::%s::] g->n::%u, x::%u\n", __func__, (uint32_t)g->n, x); + while (b->S.n > 0) { + c_v = b->S.a[--b->S.n]; + // fprintf(stderr, "[M::%s::] b->S.n::%u, c_v::%u\n", __func__, (uint32_t)b->S.n, c_v); + // if(c_v >= g->n) { + // fprintf(stderr, "+++++[M::%s::] g->n::%u, c_v::%u\n", __func__, (uint32_t)g->n, c_v); + // } + if(b->a[c_v>>1].s) continue; + + nb->n = 0; op = get_usg_unitig(g, c_v, &convex, NULL, &baseLen, NULL, nb); + uLen = baseLen; + for(i = 0; i < nb->n; i++) b->a[nb->a[i]>>1].s = 1; + if(op == LOOP) return 0; + + e_v = convex^1; + nb->n = 0; op = get_usg_unitig(g, e_v, &convex, NULL, &baseLen, NULL, nb); + + uLen = MAX(uLen, baseLen); len += uLen; + + + v = c_v^1; nv = usg_arc_n(g, v); av = usg_arc_a(g, v); + for (i = kv_0 = 0; i < nv; i++) { + if(av[i].del) continue; + kv_0++; + if(b->a[av[i].v>>1].s) continue; + kv_push(uint32_t, b->S, av[i].v); + } + + v = e_v^1; nv = usg_arc_n(g, v); av = usg_arc_a(g, v); + for (i = kv_1 = 0; i < nv; i++) { + if(av[i].del) continue; + kv_1++; + if(b->a[av[i].v>>1].s) continue; + kv_push(uint32_t, b->S, av[i].v); + } + + if(kv_0 > 0 && kv_1 > 0) flag_0++; + if(kv_0 > 1) flag_1++; + if(kv_1 > 1) flag_1++; + } + + if(flag_0 > 0 && flag_1 > 1) (*p_bub) = 1; + return len; +} + +uint64_t usg_max_bub(usg_t *g, buf_t *b, asg64_v *nb) +{ + usg_arc_t *av, *aw; uint64_t cLen = 0, mLen = 0; + uint32_t n_vtx = g->n<<1, k, v, w, kv, nv, kw, nw, p_bub; + for (v = 0; v < n_vtx; ++v) { + if(b->a[v>>1].s || g->a[v>>1].del) continue; + + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (k = kv = 0; k < nv && kv <= 1; k++) { + if(av[k].del) continue; + w = av[k].v^1; kv++; + } + + if(kv == 1) { + aw = usg_arc_a(g, w); nw = usg_arc_n(g, w); + for (k = kw = 0; k < nw && kw <= 1; k++) { + if(aw[k].del) continue; + kw++; + } + if(kw == 1) continue; + } + + cLen = dfs_max_bub(g, b, v^1, nb, &p_bub); + if(p_bub == 0) continue;///no bubble + if(cLen > mLen) mLen = cLen; + } + + for (k = 0; k < g->n; ++k) b->a[k].s = 0; + + b->S.n = b->b.n = 0; + return mLen; +} + +uint64_t usg_bub_pop1(usg_t *g, uint32_t v0, uint64_t max_dist, buf_t *x) +{ + uint32_t v, w, i, nv, kw, cnt = 0, fail_b = 0, n_tips = 0, tip_end = (uint32_t)-1; + uint32_t l, d, c, n_pending = 0, z, to_replace, wc; usg_arc_t *av; binfo_t *t; + if(g->a[v0>>1].del || undel_arcs(g, v0, NULL) < 2) return 0; // already deleted + + x->S.n = x->T.n = x->b.n = x->e.n = 0; + x->a[v0].c = x->a[v0].d = x->a[v0].m = x->a[v0].nc = x->a[v0].np = 0; + kv_push(uint32_t, x->S, v0); + + do { + v = kv_pop(x->S); d = x->a[v].d; c = x->a[v].c; + nv = usg_arc_n(g, v); av = usg_arc_a(g, v); + for (i = 0; i < nv; ++i) { + if (av[i].del) continue; + w = av[i].v; t = &(x->a[w]); l = ((v == v0)?(0):((uint32_t)av[i].ul)); + if ((w>>1) == (v0>>1)) { + fail_b = 1; + break; + } + // kv_push(uint32_t, x->e, (g->idx[v]>>32) + i); ///for backtracking + if (d + l > max_dist) { + fail_b = 1; + break; + } + kw = undel_arcs(g, w^1, NULL); wc = g->a[w>>1].occ; + if (t->s == 0) { + kv_push(uint32_t, x->b, w); + t->p = v, t->s = 1, t->d = d + l; + t->c = c + wc; + t->r = kw; + ++n_pending; + } else { + to_replace = 0; + if((c + wc) < t->c) { + to_replace = 1; + } else if(((c + wc) == t->c) && (d + l > t->d)) { + to_replace = 1; + } + if(to_replace) { + t->p = v; t->c = c + wc; + } + if (d + l < t->d) t->d = d + l; // update dist + } + + if (--(t->r) == 0) { + z = undel_arcs(g, w, NULL); + if(z > 0) { + kv_push(uint32_t, x->S, w); + } + else { + ///at most one tip + if(n_tips != 0) { + fail_b = 1; + break; + } + n_tips++; tip_end = w; + } + --n_pending; + } + } + if(fail_b) break; + if(n_tips == 1) { + if(tip_end != (uint32_t)-1 && n_pending == 0 && x->S.n == 0) { + kv_push(uint32_t, x->S, tip_end); + break; + } + fail_b = 1; + break; + } + + if (i < nv || x->S.n == 0) { + fail_b = 1; + break; + } + } while (x->S.n > 1 || n_pending); + + if(!fail_b) {//there is a bubble + cnt = 1; + } + for (i = 0; i < x->b.n; ++i) { // clear the states of visited vertices + t = &x->a[x->b.a[i]]; + t->s = t->c = t->d = t->m = t->nc = t->np = 0; + } + return cnt; +} + +uint32_t get_usg_arc_mm(usg_t *g, usg_arc_t *z, usg_arc_mm_t **res) +{ + uint32_t v = z->ul>>32; (*res) = NULL; + if(((uint32_t)z->idx) == 0) return 0; + + // fprintf(stderr, "[M::%s::] g->n::%u, v>>1::%u, v&1::%u, idx::%u, idx_n::%u, arc_mm.n::%u\n", __func__, + // (uint32_t)g->n, v>>1, v&1, (uint32_t)(z->idx>>32), (uint32_t)(z->idx), (uint32_t)(g->a[v>>1].arc_mm[v&1].n)); + + (*res) = g->a[v>>1].arc_mm[v&1].a + (z->idx>>32); + return ((uint32_t)z->idx); +} + +uint32_t usg_arc_mm_consist(usg_t *g, usg_arc_t *v, usg_arc_t *w, uint32_t *inconsist, asg64_v *b) +{ + usg_arc_mm_t *v_a = NULL, *w_a = NULL; uint32_t v_n, w_n, v_k, w_k, occ = 0, n_occ = 0, cov; uint64_t l = 0; + get_usg_unitig(g, (v->ul>>32)^1, &cov, NULL, NULL, &l, NULL); assert(cov == (w->ul>>32)); + + v_n = get_usg_arc_mm(g, v, &v_a); w_n = get_usg_arc_mm(g, w, &w_a); + // if((v->ul>>33) == 257 || (v->ul>>33) == 256) { + // fprintf(stderr, "****[M::%s::] v>>1::%u, v&1::%u, v->des::%u, v_n::%u, v_ou::%u, w>>1::%u, w&1::%u, w->des::%u, w_n::%u, w_ou::%u\n", + // __func__, (uint32_t)(v->ul>>33), (uint32_t)(v->ul>>32)&1, v->v>>1, v_n, v->ou, cov>>1, cov&1, w->v>>1, w_n, w->ou); + // } + + for (v_k = 0; v_k < v_n; v_k++) { + for (w_k = 0; w_k < w_n; w_k++) { + // if((v->ul>>33) == 257 || (v->ul>>33) == 256) { + // fprintf(stderr, "[M::%s::] v_a->uid::%u, v_a->off::%u, w_a->uid::%u, w_a->off::%u\n", + // __func__, v_a[v_k].uid, v_a[v_k].off, w_a[w_k].uid, w_a[w_k].off); + // } + if(v_a[v_k].uid != w_a[w_k].uid) continue; + if(v_a[v_k].off + l == w_a[w_k].off) { + if(b) kv_push(uint64_t, *b, (((uint64_t)v_a[v_k].uid)<<32)|((uint64_t)v_a[v_k].off)); + occ++; + } else if(v_a[v_k].off == w_a[w_k].off + l) { + if(b) kv_push(uint64_t, *b, (((uint64_t)v_a[v_k].uid)<<32)|((uint64_t)w_a[w_k].off)); + occ++; + } else { + n_occ++; + } + } + } + + if(inconsist) (*inconsist) = n_occ; + return occ; +} + +uint32_t is_junction_circle(usg_t *g, uint32_t v, uint32_t w) +{ + uint32_t k, nv, cov, op, cov_w; usg_arc_t *av; + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + + for (k = 0; k < nv; k++){ + if(av[k].del) continue; + if(av[k].v == (w^1)) return 1;///circle + op = get_usg_unitig(g, av[k].v, &cov, NULL, NULL, NULL, NULL); + if(op == LOOP || cov == (w^1)) return 1;///circle + if(op == MUL_INPUT) { + undel_arcs(g, cov, &cov_w); + if(cov_w == (w^1)) return 1;///circle + } + } + + return 0; +} + +uint32_t get_junction_w(usg_t *g, uint32_t v0, uint32_t v1, uint32_t no_inconsist, asg64_v *res) +{ + uint32_t k, i, v[2], nv[2], ou[2], i0, i1, k0, k1, occ, ff, is_mul, nn[2], *c, ww, inconsist; + usg_arc_t *av[2]; uint64_t m = 0; + + if(is_junction_circle(g, v0, v1)) return (uint32_t)-1; + // if((v0>>1) == 257 || (v1>>1) == 256) { + // fprintf(stderr, "[M::%s::] v0>>1::%u, v0&1::%u, v0pid::%u, v1>>1::%u, v1&1::%u, v1pid::%u\n", + // __func__, v0>>1, v0&1, g->a[v0>>1].mm, v1>>1, v1&1, g->a[v1>>1].mm); + // } + + v[0] = v0; v[1] = v1; + nv[0] = usg_arc_n(g, v[0]); nv[1] = usg_arc_n(g, v[1]); + av[0] = usg_arc_a(g, v[0]); av[1] = usg_arc_a(g, v[1]); + + i = 0; + for (k = 0, ou[i] = 0; k < nv[i]; k++) { + if(!av[i][k].ou) continue; + if(av[i][k].del) continue; + ou[i]++; + } + // if((v0>>1) == 257 || (v1>>1) == 256) { + // fprintf(stderr, "[M::%s::] ou[0]::%u\n", __func__, ou[0]); + // } + if(!ou[i]) return (uint32_t)-1; + + i = 1; + for (k = 0, ou[i] = 0; k < nv[i]; k++) { + if(!av[i][k].ou) continue; + if(av[i][k].del) continue; + ou[i]++; + } + // if((v0>>1) == 257 || (v1>>1) == 256) { + // fprintf(stderr, "[M::%s::] ou[1]::%u\n", __func__, ou[1]); + // } + if(!ou[i]) return (uint32_t)-1; + + //this is not ture; some UL may not be able to go through nid + // if(ou[0] != ou[1]) return (uint32_t)-1; + nn[0] = nn[1] = ww = 0; + + i0 = 0; i1 = 1; is_mul = 0; c = &(nn[0]); + for (k0 = 0; k0 < nv[i0]; k0++) { + if(!av[i0][k0].ou) continue; + if(av[i0][k0].del) continue; + for (k1 = 0, ff = 0; k1 < nv[i1] && ff <= 1; k1++) { + if(!av[i1][k1].ou) continue; + if(av[i1][k1].del) continue; + occ = usg_arc_mm_consist(g, &(av[i0][k0]), &(av[i1][k1]), &inconsist, NULL); + if(occ == 0) continue; + if(no_inconsist && inconsist > 0) { + ff = 2; break; + } + ff++; + } + + if(ff > 1) { + is_mul = 1; break; + } else if(ff == 1) { + (*c) += 1; + } + } + // if((v0>>1) == 257 || (v1>>1) == 256) { + // fprintf(stderr, "[M::%s::] c[0]::%u\n", __func__, *c); + // } + if((*c) == 0 || is_mul) return (uint32_t)-1; + + + i0 = 1; i1 = 0; is_mul = 0; c = &(nn[1]); + for (k0 = 0; k0 < nv[i0]; k0++) { + if(!av[i0][k0].ou) continue; + if(av[i0][k0].del) continue; + for (k1 = 0, ff = 0; k1 < nv[i1] && ff <= 1; k1++) { + if(!av[i1][k1].ou) continue; + if(av[i1][k1].del) continue; + occ = usg_arc_mm_consist(g, &(av[i0][k0]), &(av[i1][k1]), &inconsist, NULL); + if(occ == 0) continue; + if(no_inconsist && inconsist > 0) { + ff = 2; break; + } + ff++; ww += MIN((av[i0][k0].ou>>1), (av[i1][k1].ou>>1)); + m = k0; m <<= 32; m |= k1; + } + + if(ff > 1) { + is_mul = 1; break; + } else if(ff == 1) { + (*c) += 1; + if(res) { + kv_push(uint64_t, *res, (((uint64_t)v[i0])<<32)|(((uint64_t)(m>>32)))); + kv_push(uint64_t, *res, (((uint64_t)v[i1])<<32)|(((uint64_t)((uint32_t)m)))); + } + } + } + // if((v0>>1) == 257 || (v1>>1) == 256) { + // fprintf(stderr, "[M::%s::] c[1]::%u\n", __func__, *c); + // } + if((*c) == 0 || is_mul) return (uint32_t)-1; + assert(nn[0] == nn[1]); + + return ww; +} + +void remap_gen_arcs(usg_t *g, uint32_t ov, uint32_t ow, uint32_t nv, uint32_t nw) +{ + usg_arc_t *op = NULL, *np = NULL; usg_arc_warp *sv; uint32_t k; usg_arc_mm_t *v_a, *pm; uint32_t v_n; + sv = &(g->a[nv>>1].arc[nv&1]); kv_pushp(usg_arc_t, *sv, &np); + op = get_usg_arc(g, ov, ow); assert(op);///must get op ater since op might be changed by kv_pushp + + np->ul = (uint32_t)op->ul; np->ul |= (((uint64_t)nv)<<32); np->v = nw; + np->ol = op->ol; np->del = 0; np->ou = op->ou; + np->idx = g->a[nv>>1].arc_mm[nv&1].n; np->idx <<= 32; np->idx |= (uint32_t)op->idx; + + v_n = (uint32_t)op->idx; + for (k = 0; k < v_n; k++) { + kv_pushp(usg_arc_mm_t, g->a[nv>>1].arc_mm[nv&1], &pm); + v_a = g->a[op->ul>>33].arc_mm[(op->ul>>32)&1].a + (op->idx>>32);//va might be changed + pm->v = nw; pm->uid = v_a[k].uid; pm->off = v_a[k].off; + } +} + +void update_dual_junction(usg_t *g, uint32_t v, uint32_t v_id, uint32_t w, uint32_t w_id, asg64_v *buf) +{ + usg_arc_t *av, *aw, *z; uint32_t k, nv, nw, kv, kw, nid, pnid; usg_seq_t *s; + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (k = kv = 0; k < nv; k++) { + if(av[k].del) continue; + kv++; + } + + aw = usg_arc_a(g, w); nw = usg_arc_n(g, w); + for (k = kw = 0; k < nw; k++) { + if(aw[k].del) continue; + kw++; + } + assert(kv && kw); + assert((!av[v_id].del) && (!aw[w_id].del)); + assert(av[v_id].ou && aw[w_id].ou); + if(kv == 1 && kw == 1) return;///no need to + + buf->n = 0; pnid = g->n; + get_usg_unitig(g, v^1, NULL, NULL, NULL, NULL, buf); + // if(!(buf->n > 0 && buf->a[buf->n-1] == w)) { + // fprintf(stderr, "[M::%s::] buf->n::%u, v>>1::%u, v&1::%u, kv::%u, w>>1::%u, w&1::%u, kw::%u\n", __func__, + // (uint32_t)buf->n, v>>1, v&1, kv, w>>1, w&1, kw); + // } + assert(buf->n > 0 && buf->a[buf->n-1] == w); + + for (k = 0; k < buf->n; k++) { + nid = buf->a[k]>>1; + kv_push(uint32_t, g->mp.a[g->a[nid].mm], g->n); s = push_usg_t_node(g, g->n); + s->mm = g->a[nid].mm; s->occ = g->a[nid].occ; s->len = g->a[nid].len; s->telo = g->a[nid].telo; s->del = 0; + s->arc[0].n = s->arc[1].n = 0; s->arc_mm[0].n = s->arc_mm[1].n = 0; + } + + for (k = 0; k + 1 < buf->n; k++) { + remap_gen_arcs(g, buf->a[k], buf->a[k+1], (((pnid+k)<<1)|(buf->a[k]&1)), (((pnid+k+1)<<1)|(buf->a[k+1]&1))); + remap_gen_arcs(g, buf->a[k+1]^1, buf->a[k]^1, (((pnid+k+1)<<1)|(buf->a[k+1]&1))^1, (((pnid+k)<<1)|(buf->a[k]&1))^1); + } + + //av might be changed + av = usg_arc_a(g, v); + remap_gen_arcs(g, av[v_id].ul>>32, av[v_id].v, (pnid<<1)|((av[v_id].ul>>32)&1), av[v_id].v); + av = usg_arc_a(g, v); + remap_gen_arcs(g, av[v_id].v^1, (av[v_id].ul>>32)^1, av[v_id].v^1, ((pnid<<1)|((av[v_id].ul>>32)&1))^1); + + pnid = pnid + buf->n - 1; + //aw might be changed + aw = usg_arc_a(g, w); + remap_gen_arcs(g, aw[w_id].ul>>32, aw[w_id].v, (pnid<<1)|((aw[w_id].ul>>32)&1), aw[w_id].v); + aw = usg_arc_a(g, w); + remap_gen_arcs(g, aw[w_id].v^1, (aw[w_id].ul>>32)^1, aw[w_id].v^1, ((pnid<<1)|((aw[w_id].ul>>32)&1))^1); + + ///drop edges from the current node + av[v_id].del = 1; z = get_usg_arc(g, av[v_id].v^1, (av[v_id].ul>>32)^1); z->del = 1; + aw[w_id].del = 1; z = get_usg_arc(g, aw[w_id].v^1, (aw[w_id].ul>>32)^1); z->del = 1; +} + +uint32_t u2g_n_hybrid_thread(usg_t *ng, uint32_t no_inconsist, asg64_v *in, asg64_v *buf) +{ + if(in->n < 1) return 0; + uint32_t k, i, v, w, in_n = in->n, mm, ov[2], kv[2], cnt = 0; uint64_t *a, a_n; + for (k = 0; k < in->n; k++) { + v = (uint32_t)in->a[k]; in_n = in->n; + if(get_usg_unitig(ng, v^1, &w, NULL, NULL, NULL, NULL) == LOOP) continue; + mm = get_junction_w(ng, v, w, no_inconsist, in); + if(mm == (uint32_t)-1) { + in->n = in_n; continue; + } + if(in->n == in_n) continue; + + ov[0] = ov[1] = 0; a = in->a + in_n; a_n = in->n - in_n; + for (i = 0; i < a_n; i++) { + if((a[i]>>32) == v) ov[0]++; + if((a[i]>>32) == w) ov[1]++; + } + + kv[0] = undel_arcs(ng, v, NULL); kv[1] = undel_arcs(ng, w, NULL); + assert(ov[0] == ov[1] && ov[0] <= kv[0] && ov[1] <= kv[1]); + if((ov[0] == kv[0] && ov[1] < kv[1]) || (ov[0] < kv[0] && ov[1] == kv[1])) { + in->n = in_n; continue; + } + + for (i = 0; i < a_n; i += 2) { + update_dual_junction(ng, a[i]>>32, (uint32_t)a[i], a[i+1]>>32, (uint32_t)a[i+1], buf); + } + cnt++; in->n = in_n; + } + + return cnt; +} + + +void u2g_hybrid_extend(usg_t *ng, uint64_t* i_max_dist, asg64_v *in, asg64_v *ib) +{ + uint32_t v, w, n_vtx = ng->n<<1, n_arc, nv, i, mm; + uint64_t n_pop = 0, max_dist; usg_arc_t *av = NULL; + asg64_v tx = {0,0,0}, tb = {0,0,0}, *ob = NULL, *ub = NULL; + ob = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); ob->n = ub->n = 0; + buf_t b; memset(&b, 0, sizeof(buf_t)); CALLOC(b.a, n_vtx); + if(i_max_dist) max_dist = (*i_max_dist); + else max_dist = usg_max_bub(ng, &b, ob); + uint8_t* bs_flag = NULL; CALLOC(bs_flag, n_vtx); + + if(max_dist > 0) { + for(v = 0; v < n_vtx; ++v) { + if(bs_flag[v] != 0) continue; + nv = usg_arc_n(ng, v); av = usg_arc_a(ng, v); + if(nv < 2 || ng->a[v>>1].del) continue; + for (i = n_arc = 0; i < nv; ++i) { + if (!av[i].del) ++n_arc; + } + if (n_arc < 2) continue; + if(usg_bub_pop1(ng, v, max_dist, &b)) { + //beg is v, end is b.S.a[0]; note b.b include end, does not include beg + for (i = 0; i < b.b.n; i++) { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + bs_flag[b.b.a[i]] = bs_flag[b.b.a[i]^1] = 1; + } + bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 3; + } + } + + for(v = ob->n = 0; v < n_vtx; ++v) { + if(bs_flag[v] <= 1) continue; + if(get_usg_unitig(ng, v^1, &w, NULL, NULL, NULL, NULL) != LOOP && bs_flag[w] > 1) { + mm = get_junction_w(ng, v, w, 0, NULL); + if(mm == (uint32_t)-1) continue; + mm = ((uint32_t)-1) - mm; + kv_push(uint64_t, *ob, ((((uint64_t)mm)<<32)|((uint64_t)v))); + bs_flag[v] = bs_flag[w] = 0; + } + } + + radix_sort_srt64(ob->a, ob->a + ob->n); + n_pop += u2g_n_hybrid_thread(ng, 0, ob, ub); + } + + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + if(n_pop) usg_cleanup(ng); + if(!in) {free(tx.a);} if(!ib) {free(tb.a);} +} + + + +// uint32_t usg_path_pop_1(ul_resolve_t *uidx, usg_t *g, uint32_t v0, buf_t *x, asg64_v *arc_b) +// { +// uint32_t v, w, i, nv, kv, kw, cnt = 0, fail_b = 0, n_tips = 0, tip_end = (uint32_t)-1; +// uint32_t l, d, c, n_pending = 0, z, to_replace, wc, i_id, i_off, i_rev; +// usg_arc_t *av; binfo_t *t; usg_arc_mm_t *arc_a; uint32_t arc_n; +// if(g->a[v0>>1].del) return 0; // already deleted +// if(undel_arcs(g, v0, NULL) != 1) return 0; +// undel_arcs(g, v0, &w); w ^= 1; +// if(undel_arcs(g, w, NULL) < 2) return 0; + +// x->S.n = x->T.n = x->b.n = x->e.n = 0; +// x->a[v0].c = x->a[v0].d = x->a[v0].m = x->a[v0].nc = x->a[v0].np = 0; +// kv_push(uint32_t, x->S, v0); arc_b->n = 0; i_id = i_off = i_rev = (uint32_t)-1; + +// do { +// v = kv_pop(x->S); d = x->a[v].d; c = x->a[v].c; +// nv = usg_arc_n(g, v); av = usg_arc_a(g, v); kv = undel_arcs(g, v, NULL); +// for (i = 0; i < nv; ++i) { +// if (av[i].del) continue; +// w = av[i].v; t = &(x->a[w]); l = ((v == v0)?(0):((uint32_t)av[i].ul)); +// if ((w>>1) == (v0>>1)) { +// fail_b = 1; +// break; +// } +// kw = undel_arcs(g, w^1, NULL); wc = g->a[w>>1].occ; +// kv_push(uint64_t, *arc_b, (((uint64_t)v)<<32)|((uint64_t)i)); ///for backtracking +// arc_n = get_usg_arc_mm(g, &(av[i]), &arc_a); +// if(v == v0 && arc_n == 0) { +// fail_b = 1; +// break; +// } +// if(arc_n > 0) { + +// } else if(kv == 1) { + +// } + + + + + +// kw = undel_arcs(g, w^1, NULL); wc = g->a[w>>1].occ; +// if (t->s == 0) { +// kv_push(uint32_t, x->b, w); +// t->p = v, t->s = 1, t->d = d + l; +// t->c = c + wc; +// t->r = kw; +// ++n_pending; +// } else { +// to_replace = 0; +// if((c + wc) < t->c) { +// to_replace = 1; +// } else if(((c + wc) == t->c) && (d + l > t->d)) { +// to_replace = 1; +// } +// if(to_replace) { +// t->p = v; t->c = c + wc; +// } +// if (d + l < t->d) t->d = d + l; // update dist +// } + +// if (--(t->r) == 0) { +// z = undel_arcs(g, w, NULL); +// if(z > 0) { +// kv_push(uint32_t, x->S, w); +// } +// else { +// ///at most one tip +// if(n_tips != 0) { +// fail_b = 1; +// break; +// } +// n_tips++; tip_end = w; +// } +// --n_pending; +// } +// } +// if(fail_b) break; +// if(n_tips == 1) { +// if(tip_end != (uint32_t)-1 && n_pending == 0 && x->S.n == 0) { +// kv_push(uint32_t, x->S, tip_end); +// break; +// } +// fail_b = 1; +// break; +// } + +// if (i < nv || x->S.n == 0) { +// fail_b = 1; +// break; +// } +// } while (x->S.n > 1 || n_pending); +// } + + +///***debug-hybrid*** +uint32_t check_hybrid_connect(usg_t *ng, uint32_t i_uid, uint32_t v, uint32_t vidx, uint32_t w, uint32_t widx) +{ + usg_arc_mm_t *z_a = NULL; uint32_t z_n, k; + usg_arc_t *z = get_usg_arc(ng, v, w); + if(!z) return 0; + z_n = get_usg_arc_mm(ng, z, &z_a); + if(!z_n) return 0; + for (k = 0; k < z_n; k++) { + if(z_a[k].uid != i_uid || z_a[k].off != vidx) continue; + return 1; + } + return 0; +} + +uint32_t usg_arc_occ(usg_t *ng, uint32_t v) +{ + usg_arc_t *p; uint32_t nv, kv, i; + p = usg_arc_a(ng, v); nv = usg_arc_n(ng, v); + for (i = kv = 0; i < nv; i++) { + if(p[i].del) continue; + kv++; + } + return kv; +} + +void integer_realign_g(ul_resolve_t *uidx, usg_t *ng, uinfo_srt_warp_t *seq, uint32_t seq_id, integer_t *buf) +{ + if(seq->n < 2) return; + // if(seq_id != 1137) return; + uint64_t *srt, *track, k, z, m, t, i, l, seq_n, j, sc, csc, mm_sc, mm_idx, n_v, n_u, n_v0, *p, lin, pn; + uint32_t vi, vj; mmap_t *zm, *zt; + ///ng->map: the nodes in the new graph that are mapped to the initial HiFi graph + for (i = seq_n = 0; i < seq->n; ++i) seq_n += ng->mp.a[seq->a[i].v>>1].n; + // fprintf(stderr, "[M::%s::] seq_id::%u, seq_n::%u, seq->n::%u\n", + // __func__, seq_id, (uint32_t)seq_n, (uint32_t)seq->n); + + buf->o.n = buf->u.n = 0; + kv_resize(uint64_t, buf->o, (seq_n<<1)); + srt = buf->o.a; track = buf->o.a + seq_n; + + for (z = l = 0; z < seq->n; ++z) { + csc = seq->a[z].n; + zm = &(ng->mp.a[seq->a[z].v>>1]);///current + zt = ((z>0)?(&(ng->mp.a[seq->a[z-1].v>>1])):(NULL));///prefix + for (m = 0; m < zm->n; m++) { + i = l + m; mm_sc = csc; mm_idx = ((uint64_t)0x7FFFFFFF); + vi = (zm->a[m]<<1)|(seq->a[z].v&1); + if(zt && zt->n > 0) { + for (t = 0; t < zt->n; t++) { + j = l + t - zt->n; + vj = (zt->a[t]<<1)|(seq->a[z-1].v&1); + if(check_hybrid_connect(ng, seq_id, vj, z-1, vi, z)) {///seq_id:: integer contig id + sc = csc + (((uint32_t)-1) - (track[j]>>32)); + if(sc > mm_sc) { + mm_sc = sc; mm_idx = j; + } + } + } + } + mm_sc = ((uint32_t)-1) - mm_sc; + track[i] = mm_sc; track[i] <<= 32; track[i] |= mm_idx; + srt[i] = track[i]>>32; srt[i] <<= 32; srt[i] |= i; + } + l += zm->n; + } + assert(l == seq_n); + + radix_sort_srt64(srt, srt + seq_n); + kv_resize(uint64_t, buf->res_dump, buf->res_dump.n + seq_n); + l = buf->res_dump.n; m = buf->u.n; + for (k = n_v = n_u = 0; k < seq_n; k++) { + n_v0 = n_v; i = (uint32_t)srt[k]; + for (; i != ((uint64_t)0x7FFFFFFF) && (!(track[i]&((uint64_t)0x80000000)));) { + kv_push(uint64_t, buf->res_dump, i); n_v++; + track[i] |= ((uint64_t)0x80000000); + i = track[i]&((uint64_t)0x7FFFFFFF); + } + if(n_v - n_v0 <= 1) {///not useful to resolve anything if the UL covers less than 1 nodes + buf->res_dump.n -= (n_v-n_v0); n_v = n_v0; + continue; + } + kv_pushp(uint64_t, buf->u, &p); n_u++; + (*p) = n_v-n_v0; (*p) = ((uint32_t)-1) - (*p); (*p) <<= 32; (*p) |= ((uint64_t)(l+n_v0)); + } + + for (z = i = 0; z < seq->n; ++z) { + zm = &(ng->mp.a[seq->a[z].v>>1]); + for (k = 0; k < zm->n; k++, i++) { + srt[i] = z; srt[i] <<= 32; srt[i] |= ((zm->a[k]<<1)|(seq->a[z].v&1)); + } + } + assert(i == seq_n); + ///srt[]: (idx in seq)|(node id) + uint64_t *r, nt; + for (k = n_u = nt = 0; k < buf->u.n; k++) { + n_v0 = (uint32_t)buf->u.a[k]; r = buf->res_dump.a + n_v0; + n_v = (((uint32_t)-1) - (buf->u.a[k]>>32)); + // if(n_v < 2) continue; + // fprintf(stderr, "+[M::%s::k->%lu] buf->u.n::%u, n_v0::%lu, n_v::%lu, nt::%lu\n", + // __func__, k, (uint32_t)buf->u.n, n_v0, n_v, nt); + assert(n_v >= 2); + buf->u.a[n_u] = nt<<32; + for (i = 0; i < n_v; i++, nt++) { + // fprintf(stderr, ">[M::%s::] i::%lu, nt::%lu, n_v-i-1::%lu, r[n_v-i-1]::%lu\n", + // __func__, i, nt, n_v-i-1, r[n_v-i-1]); + track[nt] = srt[r[n_v-i-1]]; + } + buf->u.a[n_u] |= nt; n_u++; + // fprintf(stderr, "-[M::%s::k->%lu] buf->u.n::%u, n_v0::%lu, n_v::%lu, nt::%lu\n", + // __func__, k, (uint32_t)buf->u.n, n_v0, n_v, nt); + } + buf->u.n = n_u; + + uint64_t ceq_s, ceq_e, peq_s, peq_e, min_e, max_s; + for (k = n_u = 0; k < buf->u.n; k++) { + n_v0 = buf->u.a[k]>>32; n_v = (uint32_t)buf->u.a[k];///[n_v0, n_v) + ceq_s = track[n_v0]>>32; ceq_e = (track[n_v-1]>>32) + 1; + assert((ceq_e-ceq_s) == (n_v-n_v0)); + for (z = 0; z < n_u; z++) { + n_v0 = buf->u.a[z]>>32; n_v = (uint32_t)buf->u.a[z]; + peq_s = track[n_v0]>>32; peq_e = (track[n_v-1]>>32) + 1; + assert((peq_e-peq_s) == (n_v-n_v0)); + max_s = MAX(peq_s, ceq_s); min_e = MIN(peq_e, ceq_e); + if(min_e > max_s) break; + } + if(z < n_u) continue; + buf->u.a[n_u++] = buf->u.a[k]; + } + buf->u.n = n_u; buf->res_dump.n = l; + for (k = n_u = 0; k < buf->u.n; k++) { + // t = (uint32_t)-1; t <<= 32; + t = seq_id; t <<= 32; t |= ((uint64_t)0x8000000000000000); + t |= (((uint32_t)buf->u.a[k])-(buf->u.a[k]>>32)); + pn = buf->res_dump.n; kv_push(uint64_t, buf->res_dump, t); + n_v0 = buf->u.a[k]>>32; n_v = (uint32_t)buf->u.a[k]; + for (z = n_v0, lin = 1; z < n_v; z++) { + if(lin && (z > n_v0)) { + if((usg_arc_occ(ng, ((uint32_t)track[z])^1) > 1) || + (usg_arc_occ(ng, ((uint32_t)track[z-1])) > 1)) { + lin = 0; + } + } + kv_push(uint64_t, buf->res_dump, (uint32_t)track[z]); + } + + if(lin == 1) buf->res_dump.n = pn; + } +} + +static void worker_integer_realign_g(void *data, long i, int tid) // callback for kt_for() +{ + ul_resolve_t *uidx = (ul_resolve_t *)data; + integer_realign_g(uidx, uidx->uovl.h_usg, &(uidx->uovl.cc.iug_a[i]), i, &(uidx->str_b.buf[tid])); +} + +uint64_t get_ug_occ_v(uint32_t i_ug_occ) +{ + uint64_t v = (uint64_t)-1; + if(!(i_ug_occ&((uint32_t)0x80000000))) return v; + if(!(i_ug_occ&3)) return v; + if((i_ug_occ&1)&&(i_ug_occ&2)) { + v = (((i_ug_occ<<1)>>3)<<1); + v <<= 32; v |= ((((i_ug_occ<<1)>>3)<<1)|1); + return v; + } + if(i_ug_occ&1) { + v <<= 32; v |= (((i_ug_occ<<1)>>3)<<1); + return v; + } + if(i_ug_occ&2) { + v <<= 32; v |= ((((i_ug_occ<<1)>>3)<<1)|1); + return v; + } + return v; +} + +///this function might be wrong +uint32_t usg_unique_arcs_cluster(asg64_v *b64, uint64_t a_n, uint64_t *idx, uint64_t *integ_seq) +{ + uint64_t bn = b64->n, k, v; + kv_resize(uint64_t, *b64, b64->n + a_n); b64->n += a_n; + memset(b64->a + bn, -1, sizeof((*(b64->a)))*a_n); + uint64_t *cidx = b64->a + bn, s, e, i, zs, ze, z; + + ///b64.a[0, a_n]:: all resolvable paths with unique beg && end + ///b64.a[a_n, bn]:: (raw unitig/non-unqiue node id)|(resolvable path id) + ///idx:: the idx for b64.a[a_n, bn] + for (i = 0; i < a_n; i++) {///available interval with beg/end with unique arcs + s = b64->a[i]>>32; e = (uint32_t)(b64->a[i]); assert(e > s); + if(cidx[i] != (uint64_t)-1) continue; + for (k = s + 1; k < e; k++) {///note: here is [s, e] + v = integ_seq[k];///v is the raw unitig id + zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; + for (z = zs; z < ze; z++) { + // if((b64->a[z]>>32)!=v) { + // fprintf(stderr, "[M::%s::] v::%lu, b64->a[z]::%lu, zs::%lu, ze::%lu, a_n::%lu\n", + // __func__, v, b64->a[z]>>32, zs, ze, a_n); + // } + ///(b64->a[z]>>32):: raw unitig id + ///(uint32_t)b64->a[z]:: available interval id + assert((b64->a[z]>>32)==v); + cidx[((uint32_t)b64->a[z])] = (i<<32)|((uint32_t)b64->a[z]); + } + + v = integ_seq[k]^1; + zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; + for (z = zs; z < ze; z++) { + assert((b64->a[z]>>32)==v); + cidx[((uint32_t)b64->a[z])] = (i<<32)|((uint32_t)b64->a[z]); + } + } + v = integ_seq[s]; + zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; + for (z = zs; z < ze; z++) { + assert((b64->a[z]>>32)==v); + cidx[((uint32_t)b64->a[z])] = (i<<32)|((uint32_t)b64->a[z]); + } + + v = integ_seq[e]^1; + zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; + for (z = zs; z < ze; z++) { + assert((b64->a[z]>>32)==v); + cidx[((uint32_t)b64->a[z])] = (i<<32)|((uint32_t)b64->a[z]); + } + } + + radix_sort_srt64(cidx, cidx + a_n); b64->n = a_n; + for (i = 0, k = 1, v = 0; k <= a_n; k++) { + if(k == a_n || (cidx[i]>>32) != (cidx[k]>>32)) { + for (z = i; z < k; z++) { + assert(cidx[z] != (uint64_t)-1); + ///cluest integer seqs-> (cluster id)|(available interval id) + b64->a[b64->n++] = (v<<32)|((uint32_t)cidx[z]); + } + i = k; v++; + } + } + + assert(b64->n == (a_n<<1)); + return v;///how many cluster +} + +void iter_unique_arcs(asg64_v *buf, asg64_v *b64, uint64_t a_n, uint64_t *idx, uint64_t *integ_seq, uint64_t *cidx, uint64_t i0) +{ + uint64_t s, e, x, k, v, zs, ze, z; + buf->n = 0; + kv_push(uint64_t, *buf, i0); + while(buf->n) { + x = kv_pop(*buf); + if(cidx[x] != (uint64_t)-1) continue; + cidx[x] = (i0<<32)|(x); + s = b64->a[x]>>32; e = (uint32_t)(b64->a[x]); assert(e > s); + for (k = s + 1; k < e; k++) {///note: here is [s, e] + v = integ_seq[k];///v is the raw unitig id + zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; + for (z = zs; z < ze; z++) { + ///(b64->a[z]>>32):: raw unitig id + ///(uint32_t)b64->a[z]:: available interval id + assert((b64->a[z]>>32)==v); + if(cidx[((uint32_t)b64->a[z])] != (uint64_t)-1) { + assert((cidx[((uint32_t)b64->a[z])]>>32)==i0); + continue; + } + // cidx[((uint32_t)b64->a[z])] = (i0<<32)|((uint32_t)b64->a[z]); + kv_push(uint64_t, *buf, ((uint32_t)b64->a[z])); + } + + v = integ_seq[k]^1; + zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; + for (z = zs; z < ze; z++) { + ///(b64->a[z]>>32):: raw unitig id + ///(uint32_t)b64->a[z]:: available interval id + assert((b64->a[z]>>32)==v); + if(cidx[((uint32_t)b64->a[z])] != (uint64_t)-1) { + assert((cidx[((uint32_t)b64->a[z])]>>32)==i0); + continue; + } + // cidx[((uint32_t)b64->a[z])] = (i0<<32)|((uint32_t)b64->a[z]); + kv_push(uint64_t, *buf, ((uint32_t)b64->a[z])); + } + } + + v = integ_seq[s]; + zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; + for (z = zs; z < ze; z++) { + assert((b64->a[z]>>32)==v); + if(cidx[((uint32_t)b64->a[z])] != (uint64_t)-1) { + assert((cidx[((uint32_t)b64->a[z])]>>32)==i0); + continue; + } + // cidx[((uint32_t)b64->a[z])] = (i0<<32)|((uint32_t)b64->a[z]); + kv_push(uint64_t, *buf, ((uint32_t)b64->a[z])); + } + + v = integ_seq[e]^1; + zs = (idx[v]<<1)>>33; ze = (uint32_t)idx[v]; + for (z = zs; z < ze; z++) { + assert((b64->a[z]>>32)==v); + if(cidx[((uint32_t)b64->a[z])] != (uint64_t)-1) { + assert((cidx[((uint32_t)b64->a[z])]>>32)==i0); + continue; + } + // cidx[((uint32_t)b64->a[z])] = (i0<<32)|((uint32_t)b64->a[z]); + kv_push(uint64_t, *buf, ((uint32_t)b64->a[z])); + } + } +} + +uint32_t usg_unique_arcs_cluster_adv(asg64_v *b64, uint64_t a_n, uint64_t *idx, uint64_t *integ_seq, asg64_v *buf) +{ + uint64_t bn = b64->n, k, z, v; buf->n = 0; + kv_resize(uint64_t, *b64, b64->n + a_n); b64->n += a_n; + memset(b64->a + bn, -1, sizeof((*(b64->a)))*a_n); + uint64_t *cidx = b64->a + bn, i; + + ///b64.a[0, a_n]:: all resolvable paths with unique beg && end + ///b64.a[a_n, bn]:: (raw unitig/non-unqiue node id)|(resolvable path id) + ///idx:: the idx for b64.a[a_n, bn] + for (i = 0; i < a_n; i++) {///available interval with beg/end with unique arcs + if(cidx[i] != (uint64_t)-1) continue; + iter_unique_arcs(buf, b64, a_n, idx, integ_seq, cidx, i); + } + + radix_sort_srt64(cidx, cidx + a_n); b64->n = a_n; + for (i = 0, k = 1, v = 0; k <= a_n; k++) { + if(k == a_n || (cidx[i]>>32) != (cidx[k]>>32)) { + for (z = i; z < k; z++) { + assert(cidx[z] != (uint64_t)-1); + ///cluest integer seqs-> (cluster id)|(available interval id) + b64->a[b64->n++] = (v<<32)|((uint32_t)cidx[z]); + } + i = k; v++; + } + } + + buf->n = 0; + assert(b64->n == (a_n<<1)); + return v;///how many cluster +} + +uint32_t ava_pass_unique_bridge(uint64_t *idx, uint64_t *integer_seq, uint64_t s, uint64_t e) +{ + uint64_t k; + for (k = s + 1; k < e; k++) {///note: here is [s, e] + if((idx[integer_seq[k]]&((uint64_t)0x8000000000000000)) || + (idx[integer_seq[k]^1]&((uint64_t)0x8000000000000000))) { + return 0; + } + } + if((idx[integer_seq[s]]&((uint64_t)0x8000000000000000)) || + (idx[integer_seq[e]^1]&((uint64_t)0x8000000000000000))) { + return 0; + } + return 1; +} + +uint32_t ava_pass_unique_bridge_tips(usg_t *g, asg64_v *b64, uint64_t g_s, uint64_t g_e, uint64_t *integer_seq, uint8_t *f, uint64_t max_ext, double max_ext_rate, uint64_t ext_up) +{ + uint64_t i, k, z, s, e, v, nv, bn = b64->n, kv, kv_t, n_ext = 0, nkeep = 0, ncut = 0, is_telo; usg_arc_t *av; + for (i = g_s; i < g_e; i++) {///available intervals within the same cluster + s = b64->a[((uint32_t)b64->a[i])]>>32; e = ((uint32_t)b64->a[((uint32_t)b64->a[i])]); assert(s < e); + for (k = s + 1; k < e; k++) {///note: here is [s, e] + f[integer_seq[k]] = f[integer_seq[k]^1] = 1; + nkeep += g->a[integer_seq[k]>>1].occ; + } + f[integer_seq[s]] = f[integer_seq[e]^1] = 1; + } + nkeep = nkeep*max_ext_rate; + + ///collect nodes within raw unitig graph that are linked by the clusters but not in the cluster + for (i = g_s; i < g_e; i++) { + s = b64->a[((uint32_t)b64->a[i])]>>32; e = ((uint32_t)b64->a[((uint32_t)b64->a[i])]); assert(s < e); + for (k = s + 1; k < e; k++) {///note: here is [s, e] + v = integer_seq[k]; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (z = 0; z < nv; z++) { + if(av[z].del || f[av[z].v^1]) continue; + kv_push(uint64_t, *b64, av[z].v); + } + + v = integer_seq[k]^1; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (z = 0; z < nv; z++) { + if(av[z].del || f[av[z].v^1]) continue; + kv_push(uint64_t, *b64, av[z].v); + } + } + + v = integer_seq[s]; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (z = 0; z < nv; z++) { + if(av[z].del || f[av[z].v^1]) continue; + kv_push(uint64_t, *b64, av[z].v); + } + + v = integer_seq[e]^1; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (z = 0; z < nv; z++) { + if(av[z].del || f[av[z].v^1]) continue; + kv_push(uint64_t, *b64, av[z].v); + } + } + + ncut = MAX(nkeep, max_ext); is_telo = 0; + if(ncut > ext_up) ncut = ext_up; + if(ncut < max_ext) ncut = max_ext; + while ((b64->n > bn) && (n_ext < ncut) && (!is_telo)) { + v = b64->a[--b64->n]; if(f[v]) continue; + av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); + for (i = kv = 0; i < nv && kv < 1; i++) { + if (av[i].del || f[av[i].v^1]) continue; + kv++; + } + if(kv > 0) continue; + n_ext += g->a[v>>1].occ; f[v] = f[v^1] = 1; + + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (i = kv_t = 0; i < nv; i++) { + if(av[i].del) continue; + kv_t++; + if (f[av[i].v^1]) continue; + kv_push(uint64_t, *b64, av[i].v); + } + if((!kv_t) && (g->a[v>>1].telo)) is_telo = 1; + } + + ///reset f[] to 0 + for (i = g_s; i < g_e; i++) { + s = b64->a[((uint32_t)b64->a[i])]>>32; e = ((uint32_t)b64->a[((uint32_t)b64->a[i])]); assert(s < e); + for (k = s + 1; k < e; k++) {///note: here is [s, e] + kv_push(uint64_t, *b64, integer_seq[k]); + kv_push(uint64_t, *b64, (integer_seq[k]^1)); + f[integer_seq[k]] = f[integer_seq[k]^1] = 0; + } + kv_push(uint64_t, *b64, integer_seq[s]); + kv_push(uint64_t, *b64, (integer_seq[e]^1)); + f[integer_seq[s]] = f[integer_seq[e]^1] = 0; + } + + while (b64->n > bn) { + v = b64->a[--b64->n]; + f[v] = f[v^1] = 0; + + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (i = 0; i < nv; i++) { + if (av[i].del) continue; + if(f[av[i].v] || f[av[i].v^1]) { + kv_push(uint64_t, *b64, av[i].v); + } + } + + av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); + for (i = 0; i < nv; i++) { + if (av[i].del) continue; + if(f[av[i].v] || f[av[i].v^1]) { + kv_push(uint64_t, *b64, av[i].v); + } + } + } + if((n_ext < ncut) && (n_ext > max_ext - 1)) n_ext = max_ext - 1; + if(is_telo) n_ext = max_ext + 1; + return n_ext; +} + +void debug_sysm_usg_t(usg_t *ng, const char *cmd) +{ + uint32_t v, i; usg_arc_t *p, *q; uint32_t nv; + for (v = 0; v < (ng->n<<1); v++) { + p = usg_arc_a(ng, v); nv = usg_arc_n(ng, v); + for (i = 0; i < nv; i++) { + q = get_usg_arc(ng, p[i].v^1, v^1); + if((!q) || (p[i].del != q->del)) { + fprintf(stderr, "[M::%s::%s] utg%.6dl(%c)%u -> utg%.6dl(%c)%u, p->del::%u, q->del::%u\n", + __func__, cmd, + (int32_t)(v>>1)+1, "+-"[v&1], v, + (int32_t)(p[i].v>>1)+1, "+-"[p[i].v&1], p[i].v, + p[i].del, q?q->del:1); + } + } + } +} + +void update_usg_t_threading_0(ul_resolve_t *uidx, usg_t *ng, uint64_t *a, uint64_t a_n, uint32_t *occ, asg64_v *b) +{ + uint64_t k, i, *p, nid, nnid, v, w; b->n = 0; usg_seq_t *s; + + // fprintf(stderr, "[M::%s::] a_n::%lu\n", __func__, a_n); + // for (k = 0; k < a_n; k++) { + // fprintf(stderr, "utg%.6dl(%c)(hom::%u)\t", (int32_t)(a[k]>>1)+1, "+-"[a[k]&1], (IF_HOM((a[k]>>1), (*(uidx->bub))))); + // } + // fprintf(stderr, "\n"); + + assert(a_n > 1); + assert(occ[a[0]] == 1); + kv_pushp(uint64_t, *b, &p); (*p) = a[0]; (*p) <<= 32; (*p) |= a[0]; occ[a[0]]--; + + for (k = 1; k + 1 < a_n; k++) { + assert(occ[a[k]] == occ[a[k]^1]); assert(occ[a[k]] > 0); + if(occ[a[k]] > 1) {///copy a node + nid = a[k]>>1; nnid = ng->n; + kv_push(uint32_t, ng->mp.a[ng->a[nid].mm], nnid); + s = push_usg_t_node(ng, nnid); + s->mm = ng->a[nid].mm; s->occ = ng->a[nid].occ; s->len = ng->a[nid].len; s->telo = ng->a[nid].telo; s->del = 0; + s->arc[0].n = s->arc[1].n = 0; s->arc_mm[0].n = s->arc_mm[1].n = 0; + nnid <<= 1; nnid |= a[k]&1; + kv_pushp(uint64_t, *b, &p); (*p) = a[k]^1; (*p) <<= 32; (*p) |= nnid^1; + kv_pushp(uint64_t, *b, &p); (*p) = a[k]; (*p) <<= 32; (*p) |= nnid; + } else { + kv_pushp(uint64_t, *b, &p); (*p) = a[k]^1; (*p) <<= 32; (*p) |= a[k]^1; + kv_pushp(uint64_t, *b, &p); (*p) = a[k]; (*p) <<= 32; (*p) |= a[k]; + } + occ[a[k]]--; occ[a[k]^1]--; + } + // if(occ[a[a_n-1]^1] != 1) { + // fprintf(stderr, "[M::%s] utg%.6dl(%c)(occ::%u)\n", __func__, + // (int32_t)((a[a_n-1]^1)>>1)+1, "+-"[(a[a_n-1]^1)&1], occ[a[a_n-1]^1]); + // } + assert(occ[a[a_n-1]^1] == 1); + kv_pushp(uint64_t, *b, &p); (*p) = a[a_n-1]^1; (*p) <<= 32; (*p) |= a[a_n-1]^1; occ[a[a_n-1]^1]--; + + for (k = 0; k < b->n; k += 2) { + v = b->a[k]; w = b->a[k+1]; + if(((v>>32) == ((uint32_t)v)) && ((w>>32) == ((uint32_t)w))) continue;//no need arc + remap_gen_arcs(ng, v>>32, (w>>32)^1, ((uint32_t)v), ((uint32_t)w)^1);///v>>32: old id; ((uint32_t)v): new id + remap_gen_arcs(ng, w>>32, (v>>32)^1, ((uint32_t)w), ((uint32_t)v)^1); + } + + // usg_arc_t *z = get_usg_arc(ng, 220, 157075), *q = get_usg_arc(ng, 157074, 221); + // fprintf(stderr, "\n+[M::%s::a_n->%lu] p->del::%u, q->del::%u\n", + // __func__, a_n, z?z->del:1, q?q->del:1); + + usg_arc_t *av, *aw, *z; uint32_t kv, kw, nv, nw, v0, v1, w0, w1; + for (k = 0; k < b->n; k += 2) { + v0 = b->a[k]>>32; v1 = (uint32_t)b->a[k]; + w0 = b->a[k+1]>>32; w1 = (uint32_t)b->a[k+1]; + + av = usg_arc_a(ng, v1); nv = usg_arc_n(ng, v1); + for (i = kv = 0; i < nv; i++) { + if(av[i].v == (w1^1)) { + av[i].del = 0; kv++; + } else if(av[i].del == 0) { + av[i].del = 1; + z = get_usg_arc(ng, av[i].v^1, (av[i].ul>>32)^1); + // if(!(z && (!z->del))) { + // fprintf(stderr, "[M::%s::] z::%u, z->del::%u\n", __func__, z?1:0, z?z->del:1); + // fprintf(stderr, "[M::%s::arc] utg%.6dl(%c)->utg%.6dl(%c)\n", + // __func__, (int32_t)(av[i].ul>>33)+1, "+-"[(av[i].ul>>32)&1], + // (int32_t)(av[i].v>>1)+1, "+-"[(av[i].v)&1]); + // fprintf(stderr, "[M::%s::new] utg%.6dl(%c)->utg%.6dl(%c)\n", + // __func__, (int32_t)(v1>>1)+1, "+-"[v1&1], + // (int32_t)(w1>>1)+1, "+-"[w1&1]); + // fprintf(stderr, "[M::%s::old] utg%.6dl(%c)->utg%.6dl(%c)\n", + // __func__, (int32_t)(v0>>1)+1, "+-"[v0&1], + // (int32_t)(w0>>1)+1, "+-"[w0&1]); + // } + assert(z && (!z->del)); z->del = 1; + } + } + assert(kv == 1); + + aw = usg_arc_a(ng, w1); nw = usg_arc_n(ng, w1); + for (i = kw = 0; i < nw; i++) { + if(aw[i].v == (v1^1)) { + aw[i].del = 0; kw++; + } else if(aw[i].del == 0) { + aw[i].del = 1; + z = get_usg_arc(ng, aw[i].v^1, (aw[i].ul>>32)^1); + assert(z && (!z->del)); z->del = 1; + } + } + assert(kw == 1); + + if(v0 == v1 && w0 == w1) continue; + + av = usg_arc_a(ng, v0); nv = usg_arc_n(ng, v0); + for (i = 0; i < nv; i++) { + if(av[i].v == (w0^1)) { + av[i].del = 1; break; + } + } + assert(i < nv); + + aw = usg_arc_a(ng, w0); nw = usg_arc_n(ng, w0); + for (i = 0; i < nw; i++) { + if(aw[i].v == (v0^1)) { + aw[i].del = 1; break; + } + } + assert(i < nw); + } + + // z = get_usg_arc(ng, 220, 157075), q = get_usg_arc(ng, 157074, 221); + // fprintf(stderr, "-[M::%s::a_n->%lu] p->del::%u, q->del::%u\n", + // __func__, a_n, z?z->del:1, q?q->del:1); + +} + +void update_usg_t_threading(ul_resolve_t *uidx, usg_t *ng, uint64_t *arcs, uint64_t *arcs_g, uint64_t arcs_gn, uint64_t *integ_seq, uint32_t *occ, asg64_v *b) +{ + uint64_t i, k, s, e, nvtx = ng->n<<1; memset(occ, 0, sizeof((*occ))*nvtx); + for (i = 0; i < arcs_gn; i++) {///set cluster + // prt = 0; + s = arcs[((uint32_t)arcs_g[i])]>>32; e = ((uint32_t)arcs[((uint32_t)arcs_g[i])]); assert(s < e); + for (k = s + 1; k < e; k++) {///note: here is [s, e] + occ[integ_seq[k]]++; occ[integ_seq[k]^1]++; + // if((integ_seq[k]>>1) == 2736) prt = 1; + } + occ[integ_seq[s]]++; occ[integ_seq[e]^1]++; + // if((integ_seq[s]>>1) == 2736) prt = 1; + // if(((integ_seq[e]^1)>>1) == 2736) prt = 1; + // if(occ[integ_seq[s]] > 1 || occ[integ_seq[e]^1] > 1) { + // fprintf(stderr, "s::utg%.6dl(%c)(occ::%u), e::utg%.6dl(%c)(occ::%u)\n", + // (int32_t)(integ_seq[s]>>1)+1, "+-"[integ_seq[s]&1], occ[integ_seq[s]], + // (int32_t)((integ_seq[e]^1)>>1)+1, "+-"[((integ_seq[e]^1)&1)], occ[integ_seq[e]^1]); + // } + // if(prt) { + // fprintf(stderr, "[M::%s::] a_n::%lu\n", __func__, e + 1 - s); + // for (k = s; k <= e; k++) { + // fprintf(stderr, "utg%.6dl(%c)(hom::%u)\t", + // (int32_t)(integ_seq[k]>>1)+1, "+-"[integ_seq[k]&1], + // (IF_HOM((integ_seq[k]>>1), (*(uidx->bub))))); + // } + // fprintf(stderr, "\n"); + // } + } + + for (i = 0; i < nvtx; i++) { + if(!occ[i]) occ[i] = (uint32_t)-1; + } + for (i = 0; i < arcs_gn; i++) {///arcs_g[]>>32 is the group id; (uint32_t)arcs_g[] + s = arcs[((uint32_t)arcs_g[i])]>>32; e = ((uint32_t)arcs[((uint32_t)arcs_g[i])]); + update_usg_t_threading_0(uidx, ng, integ_seq + s, e + 1 - s, occ, b); + } +} + +ma_ug_t *ma_ug_hybrid_gen(usg_t *g) +{ + int32_t *mark; uint32_t i, v, n_vtx = g->n<<1; + uint32_t w, x, l, start, end, len; ma_utg_t *p; + kdq_t(uint64_t) *q; ///is a queue + ma_ug_t *ug; + + ug = (ma_ug_t*)calloc(1, sizeof(ma_ug_t)); + ug->g = asg_init(); + ///each node has two directions + mark = (int32_t*)calloc(n_vtx, 4); + + q = kdq_init(uint64_t); + for (v = 0; v < n_vtx; ++v) { + // fprintf(stderr, "+[M::%s::] v::%u, n_vtx::%u\n", __func__, v, n_vtx); + if (g->a[v>>1].del || mark[v]) continue; + if (usg_arc_n(g, v) == 0 && usg_arc_n(g, (v^1)) != 0) continue; + // fprintf(stderr, "-[M::%s::] v::%u, n_vtx::%u\n", __func__, v, n_vtx); + mark[v] = 1; q->count = 0, start = v, end = v^1, len = 0; + // forward + w = v; + while (1) { + /** + * w----->x + * w<-----x + * that means the only suffix of w is x, and the only prefix of x is w + **/ + if (usg_arc_n(g, w) != 1) break; + x = usg_arc_a(g, w)[0].v; // w->x + if (usg_arc_n(g, x^1) != 1) break; + + /** + * another direction of w would be marked as used (since w has been used) + **/ + mark[x] = mark[w^1] = 1; + ///l is the edge length, instead of overlap length + ///note: edge length is different with overlap length + l = asg_arc_len(usg_arc_a(g, w)[0]); + kdq_push(uint64_t, q, (uint64_t)w<<32 | l); + end = x^1, len += l; + w = x; + if (x == v) break; + } + if (start != (end^1) || kdq_size(q) == 0) { // linear unitig + ///length of seq, instead of edge + l = g->a[end>>1].len; + kdq_push(uint64_t, q, (uint64_t)(end^1)<<32 | l); + len += l; + } else { // circular unitig + start = end = UINT32_MAX; + goto add_usg_unitig; // then it is not necessary to do the backward + } + + // backward + x = v; + while (1) { // similar to forward but not the same + if (usg_arc_n(g, x^1) != 1) break; + w = usg_arc_a(g, x^1)[0].v ^ 1; // w->x + if (usg_arc_n(g, w) != 1) break; + mark[x] = mark[w^1] = 1; + l = asg_arc_len(usg_arc_a(g, w)[0]); + ///w is the seq id + direction, l is the length of edge + ///push element to the front of a queue + kdq_unshift(uint64_t, q, (uint64_t)w<<32 | l); + + // fprintf(stderr, "uId: %u, >%.*s (%u)\n", + // ug->u.n, (int)Get_NAME_LENGTH((R_INF), w>>1), Get_NAME((R_INF), w>>1), w>>1); + + start = w, len += l; + x = w; + } + + add_usg_unitig: + if (start != UINT32_MAX) mark[start] = mark[end] = 1; + kv_pushp(ma_utg_t, ug->u, &p); + p->s = 0, p->start = start, p->end = end, p->len = len, p->n = kdq_size(q), p->circ = (start == UINT32_MAX); + p->m = p->n; + kv_roundup32(p->m); + p->a = (uint64_t*)malloc(8 * p->m); + //all elements are saved here + for (i = 0; i < kdq_size(q); ++i) + p->a[i] = kdq_at(q, i); + // fprintf(stderr, "*[M::%s::] v::%u, n_vtx::%u\n", __func__, v, n_vtx); + } + kdq_destroy(uint64_t, q); + // fprintf(stderr, "-1-[M::%s::] **************\n", __func__); + // add arcs between unitigs; reusing mark for a different purpose + //ug saves all unitigs + for (v = 0; v < n_vtx; ++v) mark[v] = -1; + // fprintf(stderr, "-2-[M::%s::] **************\n", __func__); + + //mark all start nodes and end nodes of all unitigs + for (i = 0; i < ug->u.n; ++i) { + if (ug->u.a[i].circ) continue; + mark[ug->u.a[i].start] = i<<1 | 0; + mark[ug->u.a[i].end] = i<<1 | 1; + } + // fprintf(stderr, "-3-[M::%s::] **************\n", __func__); + //scan all edges + usg_arc_t *av; uint32_t nv; + for (v = 0; v < n_vtx; v++) { + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + if (mark[av[i].ul>>32^1] >= 0 && mark[av[i].v] >= 0) { + uint32_t u = mark[(av[i].ul>>32)^1]^1; + int l = ug->u.a[u>>1].len - av[i].ol; + if (l < 0) l = 1; + asg_arc_t *q = asg_arc_pushp(ug->g); + q->ol = av[i].ol, q->del = 0; + q->ul = (uint64_t)u<<32 | l; + q->v = mark[av[i].v]; q->ou = 0; + } + } + } + // fprintf(stderr, "-4-[M::%s::] **************\n", __func__); + for (i = 0; i < ug->u.n; ++i) + asg_seq_set(ug->g, i, ug->u.a[i].len, 0); + // fprintf(stderr, "-5-[M::%s::] **************\n", __func__); + asg_cleanup(ug->g); + free(mark); + return ug; +} + + +// ma_ug_t *gen_unique_g(ul_resolve_t *uidx, usg_t *ng, uint32_t *hg_occ, uint64_t *integ_seq_idx, uint64_t integ_seq_n, uint64_t *integ_seq_a, uint32_t max_ext) +// { +// ma_ug_t *un_g = ma_ug_hybrid_gen(ng); ma_utg_t *u; uint64_t v, w, pi, ei, *pz, bn, a_n, ua_n; +// uint32_t i, k, n_vtx = un_g->g->n_seq<<1, s, e, vw[2], rev, sid, arc_id, z, zs, ze, mm; +// uint8_t *arc_del; MALLOC(arc_del, n_vtx); asg_arc_t *p; asg64_v b64; kv_init(b64); +// asg64_v b_za, b_zb; kv_init(b_za); kv_init(b_zb); uint8_t *ff; CALLOC(ff, ng->n<<1); +// for (i = 0; i < un_g->u.n; i++) { +// un_g->g->seq[i].c = PRIMARY_LABLE; +// u = &(un_g->u.a[i]); +// arc_del[i<<1] = arc_del[(i<<1)+1] = 1; +// if(u->n > 0) { +// if(hg_occ[u->a[u->n-1]>>32]==1) arc_del[i<<1] = 0; +// if(hg_occ[(u->a[0]>>32)^1]==1) arc_del[(i<<1)+1] = 0; +// } +// if(arc_del[i<<1] && arc_del[(i<<1)+1]) un_g->g->seq[i].del = 1; +// } +// free(un_g->g->idx); un_g->g->idx = 0; un_g->g->is_srt = 0; un_g->g->n_arc = 0;///release all edges + +// for (i = 0; i < un_g->u.n; i++) { +// if(un_g->g->seq[i].del) continue; +// if(arc_del[i<<1] && arc_del[(i<<1)+1]) continue; +// u = &(un_g->u.a[i]); +// if(!arc_del[i<<1]) { +// assert(hg_occ[u->a[u->n-1]>>32] == 1); +// hg_occ[u->a[u->n-1]>>32] = ((uint32_t)0x80000000); +// hg_occ[u->a[u->n-1]>>32] |= (i<<1); +// } + +// if(!arc_del[(i<<1)+1]) { +// assert(hg_occ[(u->a[0]>>32)^1] == 1); +// hg_occ[(u->a[0]>>32)^1] = ((uint32_t)0x80000000); +// hg_occ[(u->a[0]>>32)^1] |= ((i<<1)|1); +// } +// } + +// for (i = b64.n = ua_n = a_n = 0; i < integ_seq_n; i++) { +// s = integ_seq_idx[i]; e = s + ((uint32_t)integ_seq_idx[i]); +// assert(e > s + 1); +// for (k = s, bn = b64.n, pi = (uint64_t)-1; k < e; k++) { +// v = integ_seq_a[k]; +// if((!(hg_occ[v]&((uint32_t)0x80000000)))&&(!(hg_occ[v^1]&((uint32_t)0x80000000)))) { +// continue;///it must be a unique node +// } +// if((pi != (uint64_t)-1) && (hg_occ[v^1]&((uint32_t)0x80000000))) { +// kv_pushp(uint64_t, b64, &pz); *pz = pi; (*pz) <<= 32; (*pz) |= k; a_n++; +// } +// if(hg_occ[v]&((uint32_t)0x80000000)) pi = k; +// } + +// for (k = bn, pi = s; k < b64.n; k++) {///note here is [s, e] +// ei = b64.a[k]>>32; +// if(pi < ei) { +// kv_pushp(uint64_t, b64, &pz); ua_n++; +// (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); +// } +// pi = (uint32_t)b64.a[k]; +// } +// if(pi < e) {///note here is [s, e] +// ei = e - 1; +// if(pi < ei) { +// kv_pushp(uint64_t, b64, &pz); ua_n++; +// (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); +// } +// } +// } +// assert(a_n + ua_n == b64.n); + +// uint64_t *i_idx, b64_n, iid, n_clus; CALLOC(i_idx, ng->n<<1); +// radix_sort_srt64(b64.a, b64.a + b64.n); +// for (i = ua_n; i < b64.n; i++) {///unavailable intervals; mask all unavailable nodes +// assert(b64.a[i]&((uint64_t)0x8000000000000000)); +// s = (b64.a[i]<<1)>>33; e = (uint32_t)b64.a[i]; assert(e > s);//[s, e] +// for (k = s + 1; k < e; k++) {///note: here is [s, e] +// i_idx[integ_seq_a[k]] |= ((uint64_t)0x8000000000000000); +// i_idx[integ_seq_a[k]^1] |= ((uint64_t)0x8000000000000000); +// } +// i_idx[integ_seq_a[s]] |= ((uint64_t)0x8000000000000000); +// i_idx[integ_seq_a[e]^1] |= ((uint64_t)0x8000000000000000); +// } +// ///unavailable intervals are useless +// b64.n = a_n; ua_n = 0; +// for (i = 0; i < a_n; i++) { ///available intervals +// s = b64.a[i]>>32; e = (uint32_t)b64.a[i]; assert(e > s);///[s, e] +// assert(!(b64.a[i]&((uint64_t)0x8000000000000000))); +// for (k = s + 1; k < e; k++) {///note: here is [s, e] +// kv_pushp(uint64_t, b64, &pz); i_idx[integ_seq_a[k]]++; +// (*pz) = integ_seq_a[k]; (*pz) <<= 32; (*pz) |= i; + +// kv_pushp(uint64_t, b64, &pz); i_idx[integ_seq_a[k]^1]++; +// (*pz) = integ_seq_a[k]^1; (*pz) <<= 32; (*pz) |= i; +// } +// kv_pushp(uint64_t, b64, &pz); i_idx[integ_seq_a[s]]++; +// (*pz) = integ_seq_a[s]; (*pz) <<= 32; (*pz) |= i; + +// kv_pushp(uint64_t, b64, &pz); i_idx[integ_seq_a[e]^1]++; +// (*pz) = integ_seq_a[e]^1; (*pz) <<= 32; (*pz) |= i; +// } + +// ///index +// radix_sort_srt64(b64.a + a_n, b64.a + b64.n); +// for (k = a_n + 1, i = a_n; k <= b64.n; k++) { +// if(k == b64.n || (b64.a[k]>>32) != (b64.a[i]>>32)) { +// v = b64.a[i]>>32; +// i_idx[v] |= (((uint64_t)i)<<32)|((uint64_t)k); +// i = k; +// } +// } + +// n_clus = usg_unique_arcs_cluster(&b64, a_n, i_idx, integ_seq_a); +// assert(b64.n == (a_n<<1)); +// for (k = a_n + 1, i = a_n, mm = a_n; k <= b64.n; k++) { +// if(k == b64.n || (b64.a[k]>>32) != (b64.a[i]>>32)) { +// for (z = i; z < k; z++) { +// s = b64.a[((uint32_t)b64.a[z])]>>32; e = ((uint32_t)b64.a[((uint32_t)b64.a[z])]); assert(e > s); +// if(!ava_pass_unique_bridge(i_idx, integ_seq_a, s, e)) break; +// } +// if(z >= k) {///all arcs in this cluster is fine +// for (z = i; z < k; z++) b64.a[mm++] = b64.a[z]; +// } +// i = k; n_clus--; +// } +// } +// assert(n_clus == 0); +// b64.n = mm; n_clus = 0; +// for (k = a_n + 1, i = a_n, mm = a_n; k <= b64.n; k++) { +// if(k == b64.n || (b64.a[k]>>32) != (b64.a[i]>>32)) { +// if(ava_pass_unique_bridge_tips(ng, &b64, i, k, integ_seq_a, ff, max_ext) < max_ext) {///no long tip +// for (z = i; z < k; z++) b64.a[mm++] = b64.a[z]; +// n_clus++; +// } +// i = k; +// } +// } +// b64.n = mm; + +// if(n_clus > 0) { +// update_usg_t_threading(uidx, ng, b64.a, b64.a + a_n, b64.n - a_n, integ_seq_a, hg_occ, NULL); +// } + +// free(arc_del); free(i_idx); kv_destroy(b64); +// } + + + + + + + + + +void prt_thread_info(uint64_t *interval, uint64_t interval_n, uint64_t *cluster, uint64_t cluster_n, +const char *nn) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+70); + sprintf(gfa_name, "%s.thread_info.log", nn); + FILE* fp = fopen(gfa_name, "w"); free(gfa_name); + if (!fp) return; + uint64_t k; + if(interval) { + for (k = 0; k < interval_n; k++) fprintf(fp,"it_val::[%lu, %u)\n", interval[k]>>32, (uint32_t)interval[k]); + } + if(cluster) { + for (k = 0; k < cluster_n; k++) fprintf(fp,"cluster::%lu\tit_id::%u)\n", cluster[k]>>32, (uint32_t)cluster[k]); + } + fclose(fp); +} + +void prt_intg_info(uint64_t *int_idx, uint64_t int_idx_n, uint64_t *int_a, const char *nn) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+70); + sprintf(gfa_name, "%s.intg_info.log", nn); + FILE* fp = fopen(gfa_name, "w"); free(gfa_name); + if (!fp) return; + uint64_t k, i, s, e; + for (i = 0; i < int_idx_n; i++) {///scan all integer contigs + s = int_idx[i]>>32; e = s + ((uint32_t)int_idx[i]); + assert(e > s + 1);//the length is at least 2 + fprintf(fp,"idx::[%lu, %lu)\n", s, e); + for (k = s; k < e; k++) { + fprintf(fp,"%lu\n", int_a[k]); + } + } + fclose(fp); +} + + +void prt_usg_t(ul_resolve_t *uidx, usg_t *ng, const char *cmd); + + +#define occ_m(x) ((x)&((uint32_t)0x7fffffff)) +#define c_unqiue_m(v, occ) (occ_m((occ)[(v)]) == 1 && occ_m((occ)[(v)^1]) <= 1) +#define reli_pass(x) (!((x)&((uint64_t)0x8000000000000000))) + +uint64_t get_ext_tip(usg_t *g, uint64_t *seq, uint64_t s, uint64_t e, asg64_v *buf, asg64_v *set, uint8_t *f, uint64_t max_ext) +{ + uint64_t bn = buf->n, sn = set->n, v, k, nv, z, n_ext = 0, i, kv; usg_arc_t *av; + for (k = s + 1; k < e; k++) {///note: here is [s, e] + v = seq[k]; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (z = 0; z < nv; z++) { + if(av[z].del || f[av[z].v^1]) continue; + kv_push(uint64_t, *buf, av[z].v); + } + + v = seq[k]^1; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (z = 0; z < nv; z++) { + if(av[z].del || f[av[z].v^1]) continue; + kv_push(uint64_t, *buf, av[z].v); + } + } + + v = seq[s]; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (z = 0; z < nv; z++) { + if(av[z].del || f[av[z].v^1]) continue; + kv_push(uint64_t, *buf, av[z].v); + } + + v = seq[e]^1; av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (z = 0; z < nv; z++) { + if(av[z].del || f[av[z].v^1]) continue; + kv_push(uint64_t, *buf, av[z].v); + } + + + while (buf->n > bn && n_ext < max_ext) { + v = buf->a[--buf->n]; if(f[v]) continue; + av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); + for (i = kv = 0; i < nv && kv < 1; i++) { + if (av[i].del || f[av[i].v^1]) continue; + kv++; + } + if(kv > 0) continue; + n_ext += g->a[v>>1].occ; + if(!(f[v])) { + f[v] = 1; kv_push(uint64_t, *set, v); + } + if(!(f[v^1])) { + f[v^1] = 1; kv_push(uint64_t, *set, (v^1)); + } + + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (i = 0; i < nv; i++) { + if (av[i].del || f[av[i].v^1]) continue; + kv_push(uint64_t, *buf, av[i].v); + } + } + buf->n = bn; + for (k = sn; k < set->n; k++) f[set->a[k]] = 0; + return n_ext; +} + +void select_unqiue_path_on_fly(usg_t *g, uint64_t s, uint64_t e, asg64_v *b64, asg64_v *ub64, +uint64_t *integer_seq, uint32_t *ng_occ, uint64_t *is_reli, uint8_t *f, uint64_t max_ext, asg64_v *res) +{ + uint64_t k, sk = (uint64_t)-1, ek = (uint64_t)-1, *p = NULL; ub64->n = 0; + assert(occ_m(ng_occ[integer_seq[s]]) == 1); + assert(occ_m(ng_occ[integer_seq[e]^1]) == 1); + + if(reli_pass(is_reli[integer_seq[s]])) { + sk = s; + } else { + for (k = s + 1; k < e; k++) { + if((reli_pass(is_reli[integer_seq[k]])) && (occ_m(ng_occ[integer_seq[k]]) == 1)) { + sk = k; + break; + } + } + } + if((sk == ((uint64_t)-1)) || (sk >= e)) return; + + for (k = sk + 1; k <= e; k++) { + if(sk != ((uint64_t)-1)) { + if(reli_pass(is_reli[(integer_seq[k]^1)])) { + if(occ_m((ng_occ[integer_seq[k]]^1)) == 1) { + ek = k; ///check and extend [sk, ek] + if((ek > sk) && (get_ext_tip(g, integer_seq, sk, ek, b64, ub64, f, max_ext) < max_ext)) { + p = ((res->n > 0)? (&(res->a[res->n-1])):NULL); + if(p && (((uint32_t)(*p)) == sk)) { + (*p) >>= 32; (*p) <<= 32; (*p) |= ek; + } else { + kv_pushp(uint64_t, *res, &p); *p = sk; (*p) <<= 32; (*p) |= ek; + } + } + sk = ek = ((uint64_t)-1); + } + } else { + sk = ek = ((uint64_t)-1); + } + } + + ///case2: sk != (uint64_t)-1 && ek == (uint64_t)-1 -> wait for an available ek + ///case3: sk == (uint64_t)-1 && ek == (uint64_t)-1 -> not available + if(k < e) { + if((!(reli_pass(is_reli[integer_seq[k]])))) { + sk = ek = (uint64_t)-1; continue; + } + if((sk == (uint64_t)-1) && (occ_m(ng_occ[integer_seq[k]]) == 1)) { + sk = k; + } + } + } +} + +void select_unqiue_path_on_fly_raw(usg_t *g, uint64_t s, uint64_t e, asg64_v *b64, asg64_v *ub64, +uint64_t *integer_seq, uint32_t *ng_occ, uint64_t *is_reli, uint8_t *f, uint64_t max_ext, asg64_v *res) +{ + uint64_t k, sk = (uint64_t)-1, ek = (uint64_t)-1, *p = NULL; ub64->n = 0; + assert(occ_m(ng_occ[integer_seq[s]]) == 1); + assert(occ_m(ng_occ[integer_seq[e]^1]) == 1); + sk = s; ek = e; + if(get_ext_tip(g, integer_seq, sk, ek, b64, ub64, f, max_ext) < max_ext) { + kv_pushp(uint64_t, *res, &p); *p = sk; (*p) <<= 32; (*p) |= ek; + // fprintf(stderr, "+ext_k::[%lu, %lu]\ts::%lu\te::%lu\n", sk, ek, s, e); + // fprintf(stderr, "occ[sk]::%u\tocc[ek]::%u\tocc[s]::%u\tocc[e]::%u\n", + // occ_m(ng_occ[integer_seq[sk]]), occ_m(ng_occ[integer_seq[ek]^1]), + // occ_m(ng_occ[integer_seq[s]]), occ_m(ng_occ[integer_seq[e]^1])); + } + return; + + + + for (k = sk + 1; k <= e; k++) { + if(sk != ((uint64_t)-1)) { + if(reli_pass(is_reli[(integer_seq[k]^1)])) { + if(occ_m((ng_occ[integer_seq[k]]^1)) == 1) { + ek = k; ///check and extend [sk, ek] + if((ek > sk) && (get_ext_tip(g, integer_seq, sk, ek, b64, ub64, f, max_ext) < max_ext)) { + p = ((res->n > 0)? (&(res->a[res->n-1])):NULL); + if(p && (((uint32_t)(*p)) == sk)) { + (*p) >>= 32; (*p) <<= 32; (*p) |= ek; + } else { + kv_pushp(uint64_t, *res, &p); *p = sk; (*p) <<= 32; (*p) |= ek; + } + } + sk = ek = ((uint64_t)-1); + } + } else { + sk = ek = ((uint64_t)-1); + } + } + + ///case2: sk != (uint64_t)-1 && ek == (uint64_t)-1 -> wait for an available ek + ///case3: sk == (uint64_t)-1 && ek == (uint64_t)-1 -> not available + if(k < e) { + if((!(reli_pass(is_reli[integer_seq[k]])))) { + sk = ek = (uint64_t)-1; continue; + } + if((sk == (uint64_t)-1) && (occ_m(ng_occ[integer_seq[k]]) == 1)) { + sk = k; + } + } + } +} + +void update_thread_path(usg_t *g, asg64_v *b64, asg64_v *ub64, uint64_t g_s, uint64_t g_e, uint64_t *integer_seq, +uint32_t *ng_occ, uint64_t *reliable_idx, uint8_t *f, uint64_t max_ext, asg64_v *res) +{ + uint64_t i, k, s, e; + for (i = g_s; i < g_e; i++) {///available intervals within the same cluster + s = b64->a[((uint32_t)b64->a[i])]>>32; e = ((uint32_t)b64->a[((uint32_t)b64->a[i])]); assert(s < e); + for (k = s + 1; k < e; k++) {///note: here is [s, e] + f[integer_seq[k]] = f[integer_seq[k]^1] = 1; + } + f[integer_seq[s]] = f[integer_seq[e]^1] = 1; + } + + for (i = g_s; i < g_e; i++) {///available intervals within the same cluster + s = b64->a[((uint32_t)b64->a[i])]>>32; e = ((uint32_t)b64->a[((uint32_t)b64->a[i])]); assert(s < e); + // fprintf(stderr, "[M::%s::] i::%lu, chain_id::%u\n", __func__, i, ((uint32_t)b64->a[i])); + // select_unqiue_path_on_fly(g, s, e, b64, ub64, integer_seq, ng_occ, reliable_idx, f, max_ext, res); + select_unqiue_path_on_fly_raw(g, s, e, b64, ub64, integer_seq, ng_occ, reliable_idx, f, max_ext, res); + } + + for (i = g_s; i < g_e; i++) {///available intervals within the same cluster + s = b64->a[((uint32_t)b64->a[i])]>>32; e = ((uint32_t)b64->a[((uint32_t)b64->a[i])]); assert(s < e); + for (k = s + 1; k < e; k++) {///note: here is [s, e] + f[integer_seq[k]] = f[integer_seq[k]^1] = 0; + } + f[integer_seq[s]] = f[integer_seq[e]^1] = 0; + } +} + + +typedef struct { + ul_resolve_t *uidx; + uint64_t *integer_seq; + uint64_t *gidx; + uint64_t *interval_idx; + uint64_t gidx_n; + uint8_t *f; + usg_t *ng; + uint64_t *int_idx; + uint64_t int_idx_n; + uint64_t *int_a; + uint64_t int_an; + uint64_t *ridx_a; + uint64_t *ridx; + // uint8_t is_double_check; +} unique_bridge_check_t; + +uint64_t get_arc_support(ul_resolve_t *uidx, uint64_t v, uint64_t w) +{ + uint64_t *hid_a, hid_n; ul_str_idx_t *str_idx = &(uidx->pstr); + uint64_t z, vz, occ = 0; ul_str_t *str; int64_t s, s_n; + hid_a = str_idx->occ.a + str_idx->idx.a[v>>1]; + hid_n = str_idx->idx.a[(v>>1)+1] - str_idx->idx.a[v>>1]; + + for (z = occ = 0; z < hid_n; z++) { + str = &(str_idx->str.a[hid_a[z]>>32]); s_n = str->cn; + if(s_n < 2) continue; + vz = (uint32_t)(str->a[(uint32_t)hid_a[z]]); + assert((v>>1) == (vz>>1)); + + if(v == vz) { + for(s = ((uint32_t)hid_a[z]) + 1; s < s_n; s++) { + if(((uint32_t)(str->a[s])) == w) { + occ++; break; + } + } + } else { + for(s = ((int32_t)((uint32_t)hid_a[z]))-1; s >= 0; s--) { + if(((uint32_t)(str->a[s])) == (w^1)) { + occ++; break; + } + } + } + } + return occ; +} +#define unique_bridge_occ 2 +#define unique_bridge_rate 0.499999 + +// static void worker_unique_bridge_check(void *data, long i, int tid) // callback for kt_for() +// { +// unique_bridge_check_t *uaux = (unique_bridge_check_t *)data; +// uint64_t *integer_seq = uaux->integer_seq, s, e, v, w, nse, self_k = i, k, kv; +// uint64_t *gidx = uaux->gidx, *interval = uaux->interval_idx; +// uint8_t *f = uaux->f; + +// s = interval[((uint32_t)gidx[i])]>>32; v = integer_seq[s]; +// e = ((uint32_t)interval[((uint32_t)gidx[i])]); w = integer_seq[e]^1; +// assert(s < e); + +// nse = get_arc_support(uaux->uidx, v, w^1); +// if(nse < unique_bridge_occ) { +// f[v] = f[w] = 1; return; +// } + +// for (k = 0; k < uaux->gidx_n; k++) { +// if(k == self_k) continue; +// s = interval[((uint32_t)gidx[k])]>>32; +// e = ((uint32_t)interval[((uint32_t)gidx[k])]); +// kv = get_arc_support(uaux->uidx, v, integer_seq[s]^1); +// if((kv > 0) && (kv >= (nse*unique_bridge_rate))) { +// f[v] = f[w] = 1; return; +// } + +// kv = get_arc_support(uaux->uidx, v, integer_seq[e]); +// if((kv > 0) && (kv >= (nse*unique_bridge_rate))) { +// f[v] = f[w] = 1; return; +// } + +// kv = get_arc_support(uaux->uidx, w, integer_seq[s]^1); +// if((kv > 0) && (kv >= (nse*unique_bridge_rate))) { +// f[v] = f[w] = 1; return; +// } + +// kv = get_arc_support(uaux->uidx, w, integer_seq[e]); +// if((kv > 0) && (kv >= (nse*unique_bridge_rate))) { +// f[v] = f[w] = 1; return; +// } +// } +// } + +uint64_t get_arc_support_chain(ul_resolve_t *uidx, uint64_t *a, uint64_t a_n, usg_t *ng) +{ + if(a_n <= 0) return 0; + uint64_t *hid_a, hid_n; ul_str_idx_t *str_idx = &(uidx->pstr); + uint64_t z, vz, occ = 0, v, w, ai; ul_str_t *str; int64_t s, s_n; + v = (ng->a[a[0]>>1].mm<<1)|(a[0]&1); + hid_a = str_idx->occ.a + str_idx->idx.a[v>>1]; + hid_n = str_idx->idx.a[(v>>1)+1] - str_idx->idx.a[v>>1]; + + for (z = occ = 0; z < hid_n; z++) { + str = &(str_idx->str.a[hid_a[z]>>32]); s_n = str->cn; + if(s_n < 2) continue; + vz = (uint32_t)(str->a[(uint32_t)hid_a[z]]); + assert((v>>1) == (vz>>1)); + + if(v == vz) { + for(s = ((uint32_t)hid_a[z]) + 1, ai = 1; s < s_n && ai < a_n; s++, ai++) { + w = (ng->a[a[ai]>>1].mm<<1)|(a[ai]&1); + if(((uint32_t)(str->a[s])) != w) break; + } + if(ai >= a_n) occ++; + } else { + for(s = ((int32_t)((uint32_t)hid_a[z]))-1, ai = 1; s >= 0 && ai < a_n; s--, ai++) { + w = (ng->a[a[ai]>>1].mm<<1)|(a[ai]&1); + if(((uint32_t)(str->a[s])) != (w^1)) break; + } + if(ai >= a_n) occ++; + } + } + return occ; +} + +// uint64_t is_consist_ul(ul_resolve_t *uidx, uint64_t *a, uint64_t a_n, usg_t *ng) +// { +// if(a_n <= 0) return 0; +// uint64_t k, v, w, z, *hid_a, hid_n, ulid, i; ul2ul_item_t *it;; +// ul_str_idx_t *str_idx = &(uidx->pstr); +// for (k = 0; k < a_n; k++) { +// v = (ng->a[a[k]>>1].mm<<1)|(a[k]&1); +// hid_a = str_idx->occ.a + str_idx->idx.a[v>>1]; +// hid_n = str_idx->idx.a[(v>>1)+1] - str_idx->idx.a[v>>1]; +// for (z = 0; z < hid_n; z++) { +// ulid = hid_a[z]>>32; +// if(ulid < uidx->uovl.uln) { +// it = get_ul_ovlp(&(uidx->uovl), ulid, 1); +// if(!it) continue; +// assert(uidx->pstr.str.a[ulid].cn > 1); +// if(it->is_consist == 0) return 0; +// } +// } +// } + +// uint64_t nv; asg_arc_t *av; +// v = (ng->a[a[0]>>1].mm<<1)|(a[0]&1); +// for (i = 1; i < a_n; i++) { +// w = (ng->a[a[i]>>1].mm<<1)|(a[i]&1); + +// nv = asg_arc_n(uidx->l1_ug->g, v); +// av = asg_arc_a(uidx->l1_ug->g, v); +// for (k = 0; k < nv; k++) { +// if(av[k].del) continue; +// if(av[k].v == w) break; +// } +// if(k >= nv) return 0; + +// nv = asg_arc_n(uidx->l1_ug->g, w^1); +// av = asg_arc_a(uidx->l1_ug->g, w^1); +// for (k = 0; k < nv; k++) { +// if(av[k].del) continue; +// if(av[k].v == (v^1)) break; +// } +// if(k >= nv) return 0; + +// v = w; +// } + +// return 1; +// } + +static void worker_unique_bridge_check_s(void *data, long i, int tid) // callback for kt_for() +{ + unique_bridge_check_t *uaux = (unique_bridge_check_t *)data; + uint64_t *integer_seq = uaux->integer_seq, s, e, vk, wk, nse, k; + uint64_t *gidx = uaux->gidx, *interval = uaux->interval_idx; + bubble_type *bub = uaux->uidx->bub; usg_t *ng = uaux->ng; + + s = interval[((uint32_t)gidx[i])]>>32; + e = ((uint32_t)interval[((uint32_t)gidx[i])]); + assert(s < e); + for (k = s, vk = wk = (uint32_t)-1; k <= e; k++) { + if(k > s) { + // nse = get_arc_support(uaux->uidx, (ng->a[integer_seq[k-1]>>1].mm<<1)|(integer_seq[k-1]&1), + // (ng->a[integer_seq[k]>>1].mm<<1)|(integer_seq[k]&1)); + nse = get_arc_support_chain(uaux->uidx, integer_seq+k-1, 2, ng); + if(nse < unique_bridge_occ) { + // if((!(uaux->is_double_check)) || (!is_consist_ul(uaux->uidx, integer_seq+k-1, 2, ng))) { + gidx[i] |= ((uint64_t)0x8000000000000000); return; + // } + } + } + if(IF_HOM((integer_seq[k]>>1), *bub)) continue; + // w = (ng->a[integer_seq[k]>>1].mm<<1)|(integer_seq[k]&1); + wk = k; + if(vk != (uint32_t)-1) { + // nse = get_arc_support(uaux->uidx, v, w); + nse = get_arc_support_chain(uaux->uidx, integer_seq+vk, wk+1-vk, ng); + if(nse < unique_bridge_occ) { + // if((!(uaux->is_double_check)) || (!is_consist_ul(uaux->uidx, integer_seq+vk, wk+1-vk, ng))) { + gidx[i] |= ((uint64_t)0x8000000000000000); return; + // } + } + } + vk = wk; + } +} + +uint32_t ava_pass_unique_bridge_cov(ul_resolve_t *uidx, usg_t *g, asg64_v *b64, uint64_t g_s, uint64_t g_e, uint64_t *integer_seq, uint64_t tip_l) +{ + if((tip_l == 0) && (g_e - g_s == 1)) return 1; ///if only one path, go through in anyway + uint64_t i, is_del = 0; unique_bridge_check_t uaux; + + uaux.uidx = uidx; uaux.integer_seq = integer_seq; + uaux.gidx = b64->a + g_s; uaux.gidx_n = g_e - g_s; + uaux.interval_idx = b64->a; uaux.ng = g; + ///if tip_l == 0, it is more likely to be right, so give more chance by double checking + // if(!tip_l) uaux.is_double_check = 1; + // else uaux.is_double_check = 0; + + kt_for(uidx->str_b.n_thread, worker_unique_bridge_check_s, (&uaux), g_e-g_s);///seq->n > 1 + + for (i = g_s; i < g_e; i++) {///available intervals within the same cluster + if(b64->a[i]&((uint64_t)0x8000000000000000)) { + b64->a[i] -= ((uint64_t)0x8000000000000000); is_del = 1; + } + } + return (!is_del); +} + + + +uint64_t old_path_ext(ul_resolve_t *uidx, usg_t *ng, asg64_v *b64, asg64_v *ub64, uint64_t a_n, uint64_t n_clus, uint64_t *i_idx, uint64_t *int_a, +uint8_t *ff, uint32_t *ng_occ, uint32_t max_ext) +{ + uint64_t k, i, z, /**s, e,**/ mm, tip_l; + /** + for (k = a_n + 1, i = a_n, mm = a_n; k <= b64->n; k++) { + if(k == b64->n || (b64->a[k]>>32) != (b64->a[i]>>32)) { + for (z = i; z < k; z++) {///all intger seqs within the same cluster + s = b64->a[((uint32_t)b64->a[z])]>>32; + e = ((uint32_t)b64->a[((uint32_t)b64->a[z])]); assert(e > s); + ///[s, e]:: available interval + if(!ava_pass_unique_bridge(i_idx, int_a, s, e)) break; + } + if(z >= k) {///all arcs in this cluster is fine -> each of arch is reliable + for (z = i; z < k; z++) b64->a[mm++] = b64->a[z]; + } + i = k; n_clus--; + } + } + assert(n_clus == 0); + b64->n = mm; + **/ + // prt_thread_info(b64.a, a_n, NULL, 0, "tt5"); + // fprintf(stderr, "**4**[M::%s::] a_n::%lu, n_clus::%lu\n", __func__, a_n, n_clus); + n_clus = 0; + for (k = a_n + 1, i = a_n, mm = a_n; k <= b64->n; k++) { + if(k == b64->n || (b64->a[k]>>32) != (b64->a[i]>>32)) { + tip_l = ava_pass_unique_bridge_tips(ng, b64, i, k, int_a, ff, max_ext, 0.03, 16); + if(tip_l < max_ext) {///no long tip + if(/**(!tip_l) || (**/ava_pass_unique_bridge_cov(uidx, ng, b64, i, k, int_a, tip_l)) { + for (z = i; z < k; z++) { + b64->a[mm++] = b64->a[z]; + } + n_clus++; + } + } + i = k; + } + } + // prt_thread_info(b64.a, a_n, NULL, 0, "tt6"); + b64->n = mm; + // fprintf(stderr, "**5**[M::%s::] a_n::%lu, n_clus::%lu, ng->n::%lu\n", __func__, a_n, n_clus, ng->n); + // prt_thread_info(b64.a, a_n, b64.a + a_n, b64.n - a_n, "thred"); + if(n_clus > 0) { + update_usg_t_threading(uidx, ng, b64->a, b64->a + a_n, b64->n - a_n, int_a, ng_occ, ub64); + } + // fprintf(stderr, "**6**[M::%s::] a_n::%lu, n_clus::%lu, ng->n::%lu\n", __func__, a_n, n_clus, ng->n); + return n_clus; +} + + + +void new_path_ext(ul_resolve_t *uidx, usg_t *ng, asg64_v *b64, asg64_v *ub64, uint64_t a_n, uint64_t n_clus, uint64_t *i_idx, uint64_t *int_a, +uint8_t *ff, uint32_t *ng_occ, uint32_t max_ext) +{ + asg64_v res; kv_init(res); uint64_t k, i, s, e, nvtx = ng->n<<1; + for (k = a_n + 1, i = a_n, res.n = 0; k <= b64->n; k++) { + if(k == b64->n || (b64->a[k]>>32) != (b64->a[i]>>32)) { + update_thread_path(ng, b64, ub64, i, k, int_a, ng_occ, i_idx, ff, max_ext, &res); + i = k; n_clus--; + } + } + assert(n_clus == 0); + + + if(res.n > 0) { + memset(ng_occ, 0, sizeof((*ng_occ))*nvtx); + for (i = 0; i < res.n; i++) { + s = res.a[i]>>32; e = ((uint32_t)res.a[i]); assert(s < e); + for (k = s + 1; k < e; k++) {///note: here is [s, e] + ng_occ[int_a[k]]++; ng_occ[int_a[k]^1]++; + } + ng_occ[int_a[s]]++; ng_occ[int_a[e]^1]++; + } + for (i = 0; i < nvtx; i++) { + if(!ng_occ[i]) ng_occ[i] = (uint32_t)-1; + } + + for (i = 0, ub64->n = 0; i < res.n; i++) { + s = res.a[i]>>32; e = ((uint32_t)res.a[i]); + update_usg_t_threading_0(uidx, ng, int_a + s, e + 1 - s, ng_occ, ub64); + } + } + kv_destroy(res); +} + +uint64_t gen_unique_g_adv_old(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t int_idx_n, uint64_t *int_a, uint32_t max_ext) +{ + uint64_t pi, ei, *pz, bn, a_n, ua_n, *r_a, r_n; uint8_t *ff; CALLOC(ff, ng->n<<1); + uint32_t i, k, n_vtx = ng->n<<1, s, e, zs, ze, v, b64_n; + uint32_t *ng_occ; CALLOC(ng_occ, n_vtx); + asg64_v b64, ub64; kv_init(b64); kv_init(ub64); + + for (k = 0; k < int_idx_n; k++) {///scan all integer contigs + r_a = int_a + (int_idx[k]>>32); r_n = (uint32_t)int_idx[k]; + assert(r_n >= 2); + for (i = 1; i + 1 < r_n; i++) { + ng_occ[r_a[i]]++; ng_occ[r_a[i]^1]++; + } + ng_occ[r_a[0]]++; ng_occ[r_a[r_n-1]^1]++; + } + + ma_ug_t *un_g = ma_ug_hybrid_gen(ng); ma_utg_t *u; + // print_debug_gfa(uidx->sg, un_g, uidx->uopt->coverage_cut, "iig0", uidx->uopt->sources, + // uidx->uopt->ruIndex, uidx->uopt->max_hang, uidx->uopt->min_ovlp, 0, 0, 0); + int32_t ui, un; + for (k = 0; k < un_g->u.n; k++) {///all unitigs of raw utg + u = &(un_g->u.a[k]); + zs = ze = (uint32_t)-1; un = u->n; + for (ui = 0; ui < un; ui++) { + if(occ_m(ng_occ[(u->a[ui]>>32)^1]) == 1) { + zs = ui; break; + } + } + + for (ui = ((int32_t)un)-1; ui >= 0; ui--) { + if(occ_m(ng_occ[u->a[ui]>>32]) == 1) { + ze = ui; break; + } + } + if(zs != (uint32_t)-1 && ze != (uint32_t)-1 && zs > ze) continue; + if(zs != (uint32_t)-1) ng_occ[(u->a[zs]>>32)^1] |= ((uint32_t)0x80000000); + if(ze != (uint32_t)-1) ng_occ[(u->a[ze]>>32)] |= ((uint32_t)0x80000000); + } + ma_ug_destroy(un_g); + + // fprintf(stderr, ">>>>>>[M::%s::] int_idx[0]::%lu, int_idx[1]::%lu\n", __func__, int_idx[0], int_idx[1]); + // prt_intg_info(int_idx, int_idx_n, int_a, "intg"); + for (i = b64.n = ua_n = a_n = 0; i < int_idx_n; i++) {///scan all integer contigs + s = int_idx[i]>>32; e = s + ((uint32_t)int_idx[i]); + assert(e > s + 1);//the length is at least 2 + for (k = s, bn = b64.n, pi = (uint64_t)-1; k < e; k++) { + v = int_a[k]; + if((!(ng_occ[v]&((uint32_t)0x80000000)))&&(!(ng_occ[v^1]&((uint32_t)0x80000000)))) { + continue;///it must be a unique node + } + if((pi != (uint64_t)-1) && (ng_occ[v^1]&((uint32_t)0x80000000))) { + // fprintf(stderr, "+++[M::%s::i->%u::s->%u::e->%u] pi::%lu, k::%u\n", __func__, i, s, e, pi, k); + kv_pushp(uint64_t, b64, &pz); *pz = pi; (*pz) <<= 32; (*pz) |= k; a_n++; + } + if(ng_occ[v]&((uint32_t)0x80000000)) pi = k; + } + + b64_n = b64.n; + for (k = bn, pi = s; k < b64_n; k++) { + ei = b64.a[k]>>32; + if(pi < ei) { + kv_pushp(uint64_t, b64, &pz); ua_n++; + (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); + } + pi = (uint32_t)b64.a[k]; + } + + ei = e - 1; + if(pi < ei) { + kv_pushp(uint64_t, b64, &pz); ua_n++; + (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); + } + } + assert(a_n + ua_n == b64.n); + // prt_thread_info(b64.a, a_n+ua_n, NULL, 0, "tt_minus"); + // fprintf(stderr, "**0**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); + + uint64_t *i_idx, n_clus; CALLOC(i_idx, ng->n<<1); + radix_sort_srt64(b64.a, b64.a + b64.n);///keeps the coordinates within int_a[] + + // prt_thread_info(b64.a, a_n, NULL, 0, "tt0"); + /*********debugging*********/ + // for (i = 0; i < a_n; i++) { ///available intervals + // s = b64.a[i]>>32; e = (uint32_t)b64.a[i]; + // fprintf(stderr, "[M::%s::ava->%u] s::%u, e::%u\n", __func__, i, s, e); + // for (k = s; k <= e; k++) { + // fprintf(stderr, "utg%.6dl(%c)\n", ((int32_t)(int_a[k]>>1))+1, "+-"[int_a[k]&1]); + // } + // } + // for (i = a_n; i < b64.n; i++) {///unavailable intervals + // s = (b64.a[i]<<1)>>33; e = (uint32_t)b64.a[i]; + // fprintf(stderr, "[M::%s::uava->%u] s::%u, e::%u\n", __func__, i - (uint32_t)a_n, s, e); + // for (k = s; k <= e; k++) { + // fprintf(stderr, "utg%.6dl(%c)\n", ((int32_t)(int_a[k]>>1))+1, "+-"[int_a[k]&1]); + // } + // } + /*********debugging*********/ + + + + + + + for (i = a_n; i < b64.n; i++) {///unavailable intervals; mask all unavailable nodes + assert(b64.a[i]&((uint64_t)0x8000000000000000)); ua_n--; + s = (b64.a[i]<<1)>>33; e = (uint32_t)b64.a[i]; assert(e > s);//[s, e] + for (k = s + 1; k < e; k++) {///note: here is [s, e] + i_idx[int_a[k]] |= ((uint64_t)0x8000000000000000); + i_idx[int_a[k]^1] |= ((uint64_t)0x8000000000000000); + } + i_idx[int_a[s]] |= ((uint64_t)0x8000000000000000); + i_idx[int_a[e]^1] |= ((uint64_t)0x8000000000000000); + } + // prt_thread_info(b64.a, a_n, NULL, 0, "tt1"); + ///unavailable intervals are useless + b64.n = a_n; assert(ua_n == 0); + for (i = 0; i < a_n; i++) { ///available intervals + s = b64.a[i]>>32; e = (uint32_t)b64.a[i]; assert(e > s);///[s, e] -> coordinates within int_a[] + if(i == 3201 || i == 3202) { + fprintf(stderr, "[M::%s::] s::%u, e::%u, int_a[s]::%lu(occ::%u), int_a[e]^1::%lu(occ::%u)\n", + __func__, s, e, int_a[s], occ_m(ng_occ[int_a[s]]), + int_a[e]^1, occ_m(ng_occ[int_a[e]^1])); + } + + assert(!(b64.a[i]&((uint64_t)0x8000000000000000))); + for (k = s + 1; k < e; k++) {///note: here is [s, e]; s && e are unique, but [s+1, e-1] are not unique + kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[k]]++; + (*pz) = int_a[k]; (*pz) <<= 32; (*pz) |= i;///(raw unitig/non-unqiue node id)|(integer contig id) + + kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[k]^1]++; + (*pz) = int_a[k]^1; (*pz) <<= 32; (*pz) |= i; + } + kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[s]]++; + (*pz) = int_a[s]; (*pz) <<= 32; (*pz) |= i; + + kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[e]^1]++; + (*pz) = int_a[e]^1; (*pz) <<= 32; (*pz) |= i; + } + // prt_thread_info(b64.a, a_n, NULL, 0, "tt2"); + // fprintf(stderr, "**1**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); + ///index + radix_sort_srt64(b64.a + a_n, b64.a + b64.n);///(raw unitig node id)|(integer contig id) + for (k = a_n + 1, i = a_n; k <= b64.n; k++) { + if(k == b64.n || (b64.a[k]>>32) != (b64.a[i]>>32)) { + i_idx[b64.a[i]>>32] |= (((uint64_t)i)<<32)|((uint64_t)k);///b64.a[i]>>32 appear once (unique ends)/multipe times + i = k; + } + } + // prt_thread_info(b64.a, a_n, NULL, 0, "tt3"); + // fprintf(stderr, "**2**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); + ///b64.a[0, a_n]:: all resolvable paths with unique beg && end + ///b64.a[a_n, b64.n]:: (raw unitig/non-unqiue node id)|(resolvable path id) + // n_clus = usg_unique_arcs_cluster(&b64, a_n, i_idx, int_a);///this function might be wrong + n_clus = usg_unique_arcs_cluster_adv(&b64, a_n, i_idx, int_a, &ub64); + fprintf(stderr, "**3**[M::%s::] a_n::%lu, n_clus::%lu\n", __func__, a_n, n_clus); + // prt_thread_info(b64.a, a_n, NULL, 0, "tt4"); + assert(b64.n == (a_n<<1)); + old_path_ext(uidx, ng, &b64, &ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext); + // new_path_ext(uidx, ng, &b64, &ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext); + + free(ng_occ); free(i_idx); free(ff); kv_destroy(b64); kv_destroy(ub64); + return b64.n - a_n; +} + +uint64_t gen_unique_g_adv(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t int_idx_n, uint64_t *int_a, uint32_t max_ext) +{ + uint64_t pi, ei, *pz, bn, a_n, ua_n, *r_a, r_n; uint8_t *ff; CALLOC(ff, ng->n<<1); + uint32_t i, k, n_vtx = ng->n<<1, s, e, zs, ze, v, b64_n; + uint32_t *ng_occ; CALLOC(ng_occ, n_vtx); + asg64_v b64, ub64; kv_init(b64); kv_init(ub64); + uint64_t *i_idx, n_clus; CALLOC(i_idx, ng->n<<1); + + for (k = 0; k < int_idx_n; k++) {///scan all integer contigs + r_a = int_a + (int_idx[k]>>32); r_n = (uint32_t)int_idx[k]; + assert(r_n >= 2); + for (i = 1; i + 1 < r_n; i++) { + ng_occ[r_a[i]]++; ng_occ[r_a[i]^1]++; + } + ng_occ[r_a[0]]++; ng_occ[r_a[r_n-1]^1]++; + } + + ma_ug_t *un_g = ma_ug_hybrid_gen(ng); ma_utg_t *u; + // print_debug_gfa(uidx->sg, un_g, uidx->uopt->coverage_cut, "iig0", uidx->uopt->sources, + // uidx->uopt->ruIndex, uidx->uopt->max_hang, uidx->uopt->min_ovlp, 0, 0, 0); + int32_t ui, un; + for (k = 0; k < un_g->u.n; k++) {///all unitigs of raw utg + u = &(un_g->u.a[k]); + zs = ze = (uint32_t)-1; un = u->n; + for (ui = 0; ui < un; ui++) { + if(occ_m(ng_occ[(u->a[ui]>>32)^1]) == 1) { + zs = ui; break; + } + } + + for (ui = ((int32_t)un)-1; ui >= 0; ui--) { + if(occ_m(ng_occ[u->a[ui]>>32]) == 1) { + ze = ui; break; + } + } + if(zs != (uint32_t)-1 && ze != (uint32_t)-1 && zs > ze) continue; + if(zs != (uint32_t)-1) ng_occ[(u->a[zs]>>32)^1] |= ((uint32_t)0x80000000); + if(ze != (uint32_t)-1) ng_occ[(u->a[ze]>>32)] |= ((uint32_t)0x80000000); + } + ma_ug_destroy(un_g); + + // fprintf(stderr, ">>>>>>[M::%s::] int_idx[0]::%lu, int_idx[1]::%lu\n", __func__, int_idx[0], int_idx[1]); + // prt_intg_info(int_idx, int_idx_n, int_a, "intg"); + for (i = b64.n = ua_n = a_n = 0; i < int_idx_n; i++) {///scan all integer contigs + s = int_idx[i]>>32; e = s + ((uint32_t)int_idx[i]); + assert(e > s + 1);//the length is at least 2 + for (k = s, bn = b64.n, pi = (uint64_t)-1; k < e; k++) { + v = int_a[k]; + if((!(ng_occ[v]&((uint32_t)0x80000000)))&&(!(ng_occ[v^1]&((uint32_t)0x80000000)))) { + continue;///it must be a unique node + } + if((pi != (uint64_t)-1) && (ng_occ[v^1]&((uint32_t)0x80000000))) { + // fprintf(stderr, "+++[M::%s::i->%u::s->%u::e->%u] pi::%lu, k::%u\n", __func__, i, s, e, pi, k); + pz = (b64.n>0)? &(b64.a[b64.n-1]):(NULL); + if((!pz) || (((*pz)>>32) != pi)) {//keep the shortest pi<->k + kv_pushp(uint64_t, b64, &pz); + *pz = pi; (*pz) <<= 32; (*pz) |= k; + a_n++; + } + } + if(ng_occ[v]&((uint32_t)0x80000000)) pi = k;//keep the shortest pi<->k + } + + b64_n = b64.n; + for (k = bn, pi = s; k < b64_n; k++) { + ei = b64.a[k]>>32; + if(pi < ei) { + kv_pushp(uint64_t, b64, &pz); ua_n++; + (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); + } + pi = (uint32_t)b64.a[k]; + } + + ei = e - 1; + if(pi < ei) { + kv_pushp(uint64_t, b64, &pz); ua_n++; + (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); + } + } + assert(a_n + ua_n == b64.n); + // prt_thread_info(b64.a, a_n+ua_n, NULL, 0, "tt_minus"); + // fprintf(stderr, "**0**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); + radix_sort_srt64(b64.a, b64.a + b64.n);///keeps the coordinates within int_a[] + + for (i = a_n; i < b64.n; i++) {///unavailable intervals; mask all unavailable nodes + assert(b64.a[i]&((uint64_t)0x8000000000000000)); ua_n--; + s = (b64.a[i]<<1)>>33; e = (uint32_t)b64.a[i]; assert(e > s);//[s, e] + for (k = s + 1; k < e; k++) {///note: here is [s, e] + i_idx[int_a[k]] |= ((uint64_t)0x8000000000000000); + i_idx[int_a[k]^1] |= ((uint64_t)0x8000000000000000); + } + i_idx[int_a[s]] |= ((uint64_t)0x8000000000000000); + i_idx[int_a[e]^1] |= ((uint64_t)0x8000000000000000); + } + // prt_thread_info(b64.a, a_n, NULL, 0, "tt1"); + ///unavailable intervals are useless + b64.n = a_n; assert(ua_n == 0); + for (i = 0; i < a_n; i++) { ///available intervals + s = b64.a[i]>>32; e = (uint32_t)b64.a[i]; assert(e > s);///[s, e] -> coordinates within int_a[] + assert(!(b64.a[i]&((uint64_t)0x8000000000000000))); + + for (k = s + 1; k < e; k++) {///note: here is [s, e]; s && e are unique, but [s+1, e-1] are not unique + kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[k]]++; + (*pz) = int_a[k]; (*pz) <<= 32; (*pz) |= i;///(raw unitig/non-unqiue node id)|(integer contig id) + + kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[k]^1]++; + (*pz) = int_a[k]^1; (*pz) <<= 32; (*pz) |= i; + } + kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[s]]++; + (*pz) = int_a[s]; (*pz) <<= 32; (*pz) |= i; + + kv_pushp(uint64_t, b64, &pz); //i_idx[int_a[e]^1]++; + (*pz) = int_a[e]^1; (*pz) <<= 32; (*pz) |= i; + } + // prt_thread_info(b64.a, a_n, NULL, 0, "tt2"); + // fprintf(stderr, "**1**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); + ///index + radix_sort_srt64(b64.a + a_n, b64.a + b64.n);///(raw unitig node id)|(integer contig id) + for (k = a_n + 1, i = a_n; k <= b64.n; k++) { + if(k == b64.n || (b64.a[k]>>32) != (b64.a[i]>>32)) { + i_idx[b64.a[i]>>32] |= (((uint64_t)i)<<32)|((uint64_t)k);///b64.a[i]>>32 appear once (unique ends)/multipe times + i = k; + } + } + // prt_thread_info(b64.a, a_n, NULL, 0, "tt3"); + // fprintf(stderr, "**2**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); + ///b64.a[0, a_n]:: all resolvable paths with unique beg && end + ///b64.a[a_n, b64.n]:: (raw unitig/non-unqiue node id)|(resolvable path id) + // n_clus = usg_unique_arcs_cluster(&b64, a_n, i_idx, int_a);///this function might be wrong + n_clus = usg_unique_arcs_cluster_adv(&b64, a_n, i_idx, int_a, &ub64); + // fprintf(stderr, "**3**[M::%s::] a_n::%lu, n_clus::%lu\n", __func__, a_n, n_clus); + // prt_thread_info(b64.a, a_n, NULL, 0, "tt4"); + assert(b64.n == (a_n<<1)); + old_path_ext(uidx, ng, &b64, &ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext); + // new_path_ext(uidx, ng, &b64, &ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext);//wrong + + free(ng_occ); free(i_idx); free(ff); kv_destroy(b64); kv_destroy(ub64); + return b64.n - a_n; +} + +void u2g_hybrid_detan(ul_resolve_t *uidx, usg_t *ng, uint32_t max_ext, asg64_v *in, asg64_v *ib) +{ + uint64_t k, i, x, m, *tmp, sn; asg64_v tx = {0,0,0}, tb = {0,0,0}, *ob = NULL, *ub = NULL; + ob = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); ob->n = ub->n = 0; + + for (k = 0; k < uidx->str_b.n_thread; k++) { + uidx->str_b.buf[k].res_dump.n = uidx->str_b.buf[k].u.n = uidx->str_b.buf[k].o.n = 0; + } + kt_for(uidx->str_b.n_thread, worker_integer_realign_g, uidx, uidx->uovl.i_ug->u.n); + + for (k = ob->n = ub->n = m = 0; k < uidx->str_b.n_thread; k++) { + for (i = 0; i < uidx->str_b.buf[k].res_dump.n; i++) { + x = uidx->str_b.buf[k].res_dump.a[i]; + kv_push(uint64_t, *ob, x);//aln details + if(x&((uint64_t)0x8000000000000000)) { + x -= ((uint64_t)0x8000000000000000); x >>= 32; x <<= 32;//seq_id + x |= ob->n;//offset + kv_push(uint64_t, *ub, x);///idx:: seq_id|offset_in_ob + } else { + m++; + } + } + } + + radix_sort_srt64(ub->a, ub->a + ub->n); + kv_resize(uint64_t, *ub, ub->n+m); tmp = ub->a + ub->n; m = 0; + for (k = 0; k < ub->n; k++) { + sn = ((uint32_t)(ob->a[((uint32_t)ub->a[k])-1])); + memcpy(tmp + m, ob->a + ((uint32_t)ub->a[k]), sn*sizeof((*tmp))); + ub->a[k] = m; ub->a[k] <<= 32; ub->a[k] |= sn;//offset_in_ob|occ + m += sn; + } + assert(m <= ob->n); + memcpy(ob->a, tmp, m*sizeof((*tmp))); ob->n = m; + + + // for (k = 0, p = NULL; k < ub->n; k++) { + // p = &(ob->a[((uint32_t)ub->a[k])-1]); + // x = ub->a[k]<<32;//offset + // x |= ((uint32_t)(*p));///occ + // ub->a[k] = x; + // (*p) >>= 32; (*p) <<= 32; (*p) |= k; + // } + // for (k = m = 0; k < ob->n; k++) { + // if(ob->a[k]&((uint64_t)0x8000000000000000)) { + // x = m; x <<= 32; x |= ((uint32_t)ub->a[(uint32_t)ob->a[k]]); + // ub->a[(uint32_t)ob->a[k]] = x; + // } else { + // ob->a[m++] = ob->a[k]; + // } + // } + // ob->n = m; + + // for (k = ob->n = ub->n = 0; k < uidx->str_b.n_thread; k++) { + // for (i = 0; i < uidx->str_b.buf[k].res_dump.n; i++) { + // if((uidx->str_b.buf[k].res_dump.a[i]>>32)==((uint32_t)-1)) { + // x = ob->n; x <<= 32; x |= ((uint32_t)uidx->str_b.buf[k].res_dump.a[i]); + // kv_push(uint64_t, *ub, x);///idx:: offset_in_ob|occ + // } else { + // kv_push(uint64_t, *ob, uidx->str_b.buf[k].res_dump.a[i]);//aln details + // } + // } + // } + + /*********debugging*********/ + fprintf(stderr, "[M::%s::] # iug::%u, # gchain::%u\n", __func__, (uint32_t)uidx->uovl.i_ug->u.n, (uint32_t)ub->n); + // for (k = 0; k < ub->n; k++) { + // // fprintf(stderr, "[M::%s::k->%lu] # iug::%u, # chain::%u, off chain::%u\n", + // // __func__, k, (uint32_t)uidx->uovl.cc.iug_a[k].n, (uint32_t)ub->a[k], (uint32_t)(ub->a[k]>>32)); + // for (i = 0; i < (uint32_t)ub->a[k]; i++) { + // // fprintf(stderr, "utg%.6dl(%c) <------> utg%.6dl(%c)\n", + // // ((int32_t)(uidx->uovl.cc.iug_a[k].a[i].v>>1))+1, "+-"[uidx->uovl.cc.iug_a[k].a[i].v&1], + // // ((int32_t)(ob->a[(ub->a[k]>>32)+i]>>1))+1, "+-"[ob->a[(ub->a[k]>>32)+i]&1]); + // assert(uidx->uovl.cc.iug_a[k].a[i].v == ob->a[(ub->a[k]>>32)+i]); + // } + // } + /*********debugging*********/ + + ///ub->idx; ob->nodes + // u_ug = gen_unique_g(uidx, ng, ng_occ, ub->a, ub->n, ob->a);//ma_ug_hybrid_gen(ng); + ///debug + debug_sysm_usg_t(ng, __func__); + // prt_usg_t(uidx, ng, "ng4"); + if(gen_unique_g_adv(uidx, ng, ub->a, ub->n, ob->a, max_ext)) { + // usg_arc_t *z = get_usg_arc(ng, 2, 576), *q = get_usg_arc(ng, 577, 3); + // fprintf(stderr, "xxxx0xxx[M::%s::] p->del::%u, q->del::%u\n", + // __func__, z?z->del:1, q?q->del:1); + ///debug + debug_sysm_usg_t(ng, __func__); + // z = get_usg_arc(ng, 2, 576); q = get_usg_arc(ng, 577, 3); + // fprintf(stderr, "xxxx1xxx[M::%s::] p->del::%u, q->del::%u\n", + // __func__, z?z->del:1, q?q->del:1); + // fprintf(stderr, "+[M::%s::] ng->n::%u\n", __func__, (uint32_t)ng->n); + usg_cleanup(ng); + ///debug + debug_sysm_usg_t(ng, __func__); + // fprintf(stderr, "-[M::%s::] ng->n::%u\n", __func__, (uint32_t)ng->n); + } + // prt_usg_t(uidx, ng, "ng_dbg"); + if(!in) {free(tx.a);} if(!ib) {free(tb.a);} +} + +void u2g_hybrid_aln(ul_resolve_t *uidx, usg_t *ng, asg64_v *ob, asg64_v *ub) +{ + uint64_t k, m, i, x, *tmp, sn; + ob->n = ub->n = 0; + for (k = 0; k < uidx->str_b.n_thread; k++) { + uidx->str_b.buf[k].res_dump.n = uidx->str_b.buf[k].u.n = uidx->str_b.buf[k].o.n = 0; + } + kt_for(uidx->str_b.n_thread, worker_integer_realign_g, uidx, uidx->uovl.i_ug->u.n); + + for (k = ob->n = ub->n = m = 0; k < uidx->str_b.n_thread; k++) { + for (i = 0; i < uidx->str_b.buf[k].res_dump.n; i++) { + x = uidx->str_b.buf[k].res_dump.a[i]; + kv_push(uint64_t, *ob, x);//aln details + if(x&((uint64_t)0x8000000000000000)) { + x -= ((uint64_t)0x8000000000000000); x >>= 32; x <<= 32;//seq_id + x |= ob->n;//offset + kv_push(uint64_t, *ub, x);///idx:: seq_id|offset_in_ob + } else { + m++; + } + } + } + + radix_sort_srt64(ub->a, ub->a + ub->n); + kv_resize(uint64_t, *ub, ub->n+m); tmp = ub->a + ub->n; m = 0; + for (k = 0; k < ub->n; k++) { + sn = ((uint32_t)(ob->a[((uint32_t)ub->a[k])-1])); + memcpy(tmp + m, ob->a + ((uint32_t)ub->a[k]), sn*sizeof((*tmp))); + ub->a[k] = m; ub->a[k] <<= 32; ub->a[k] |= sn;//offset_in_ob|occ + m += sn; + } + assert(m <= ob->n); + memcpy(ob->a, tmp, m*sizeof((*tmp))); ob->n = m; +} + +uint32_t ug_ext(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t int_idx_n, uint64_t *int_a, uint32_t max_ext, +uint8_t *ff, uint32_t *ng_occ, uint64_t *i_idx, asg64_v *b64, asg64_v *ub64) +{ + uint32_t n_vtx = ng->n<<1, k, i; uint64_t pi, ei, *pz, v, b64_n; + uint64_t *r_a, r_n, zs, ze, s, e, a_n, ua_n, bn, n_clus; + memset(ff, 0, sizeof((*ff))*n_vtx); + memset(ng_occ, 0, sizeof((*ng_occ))*n_vtx); + memset(i_idx, 0, sizeof((*i_idx))*n_vtx); + b64->n = ub64->n = 0; + + for (k = 0; k < int_idx_n; k++) {///scan all integer contigs + r_a = int_a + (int_idx[k]>>32); r_n = (uint32_t)int_idx[k]; + assert(r_n >= 2); + for (i = 1; i + 1 < r_n; i++) { + ng_occ[r_a[i]]++; ng_occ[r_a[i]^1]++; + } + ng_occ[r_a[0]]++; ng_occ[r_a[r_n-1]^1]++; + } + + ma_ug_t *un_g = ma_ug_hybrid_gen(ng); + int32_t ui, un; ma_utg_t *u = NULL; + for (k = 0; k < un_g->u.n; k++) {///all unitigs of raw utg + u = &(un_g->u.a[k]); + zs = ze = (uint32_t)-1; un = u->n; + for (ui = 0; ui < un; ui++) { + if(occ_m(ng_occ[(u->a[ui]>>32)^1]) == 1) { + zs = ui; break; + } + } + + for (ui = ((int32_t)un)-1; ui >= 0; ui--) { + if(occ_m(ng_occ[u->a[ui]>>32]) == 1) { + ze = ui; break; + } + } + if(zs != (uint32_t)-1 && ze != (uint32_t)-1 && zs > ze) continue; + if(zs != (uint32_t)-1) ng_occ[(u->a[zs]>>32)^1] |= ((uint32_t)0x80000000); + if(ze != (uint32_t)-1) ng_occ[(u->a[ze]>>32)] |= ((uint32_t)0x80000000); + } + ma_ug_destroy(un_g); + + // fprintf(stderr, ">>>>>>[M::%s::] int_idx[0]::%lu, int_idx[1]::%lu\n", __func__, int_idx[0], int_idx[1]); + // prt_intg_info(int_idx, int_idx_n, int_a, "intg"); + for (i = b64->n = ua_n = a_n = 0; i < int_idx_n; i++) {///scan all integer contigs + s = int_idx[i]>>32; e = s + ((uint32_t)int_idx[i]); + assert(e > s + 1);//the length is at least 2 + for (k = s, bn = b64->n, pi = (uint64_t)-1; k < e; k++) { + v = int_a[k]; + if((!(ng_occ[v]&((uint32_t)0x80000000)))&&(!(ng_occ[v^1]&((uint32_t)0x80000000)))) { + continue;///it must be a unique node + } + if((pi != (uint64_t)-1) && (ng_occ[v^1]&((uint32_t)0x80000000))) { + pz = (b64->n>0)? &(b64->a[b64->n-1]):(NULL); + if((!pz) || (((*pz)>>32) != pi)) {//keep the shortest pi<->k + kv_pushp(uint64_t, *b64, &pz); + *pz = pi; (*pz) <<= 32; (*pz) |= k; + a_n++; + } + } + if(ng_occ[v]&((uint32_t)0x80000000)) pi = k;//keep the shortest pi<->k + } + + b64_n = b64->n; + for (k = bn, pi = s; k < b64_n; k++) { + ei = b64->a[k]>>32; + if(pi < ei) { + kv_pushp(uint64_t, *b64, &pz); ua_n++; + (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); + } + pi = (uint32_t)b64->a[k]; + } + + ei = e - 1; + if(pi < ei) { + kv_pushp(uint64_t, *b64, &pz); ua_n++; + (*pz) = pi; (*pz) <<= 32; (*pz) |= ei; (*pz) |= ((uint64_t)0x8000000000000000); + } + } + assert(a_n + ua_n == b64->n); + // prt_thread_info(b64.a, a_n+ua_n, NULL, 0, "tt_minus"); + // fprintf(stderr, "**0**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); + radix_sort_srt64(b64->a, b64->a + b64->n);///keeps the coordinates within int_a[] + + + for (i = a_n; i < b64->n; i++) {///unavailable intervals; mask all unavailable nodes + assert(b64->a[i]&((uint64_t)0x8000000000000000)); ua_n--; + s = (b64->a[i]<<1)>>33; e = (uint32_t)b64->a[i]; assert(e > s);//[s, e] + for (k = s + 1; k < e; k++) {///note: here is [s, e] + i_idx[int_a[k]] |= ((uint64_t)0x8000000000000000); + i_idx[int_a[k]^1] |= ((uint64_t)0x8000000000000000); + } + i_idx[int_a[s]] |= ((uint64_t)0x8000000000000000); + i_idx[int_a[e]^1] |= ((uint64_t)0x8000000000000000); + } + // prt_thread_info(b64.a, a_n, NULL, 0, "tt1"); + ///unavailable intervals are useless + b64->n = a_n; assert(ua_n == 0); + for (i = 0; i < a_n; i++) { ///available intervals + s = b64->a[i]>>32; e = (uint32_t)b64->a[i]; assert(e > s);///[s, e] -> coordinates within int_a[] + assert(!(b64->a[i]&((uint64_t)0x8000000000000000))); + + for (k = s + 1; k < e; k++) {///note: here is [s, e]; s && e are unique, but [s+1, e-1] are not unique + kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[k]]++; + (*pz) = int_a[k]; (*pz) <<= 32; (*pz) |= i;///(raw unitig/non-unqiue node id)|(integer contig id) + + kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[k]^1]++; + (*pz) = int_a[k]^1; (*pz) <<= 32; (*pz) |= i; + } + kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[s]]++; + (*pz) = int_a[s]; (*pz) <<= 32; (*pz) |= i; + + kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[e]^1]++; + (*pz) = int_a[e]^1; (*pz) <<= 32; (*pz) |= i; + } + // prt_thread_info(b64.a, a_n, NULL, 0, "tt2"); + // fprintf(stderr, "**1**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); + ///index + radix_sort_srt64(b64->a + a_n, b64->a + b64->n);///(raw unitig node id)|(integer contig id) + for (k = a_n + 1, i = a_n; k <= b64->n; k++) { + if(k == b64->n || (b64->a[k]>>32) != (b64->a[i]>>32)) { + i_idx[b64->a[i]>>32] |= (((uint64_t)i)<<32)|((uint64_t)k);///b64.a[i]>>32 appear once (unique ends)/multipe times + i = k; + } + } + // prt_thread_info(b64.a, a_n, NULL, 0, "tt3"); + // fprintf(stderr, "**2**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); + ///b64.a[0, a_n]:: all resolvable paths with unique beg && end + ///b64.a[a_n, b64.n]:: (raw unitig/non-unqiue node id)|(resolvable path id) + // n_clus = usg_unique_arcs_cluster(&b64, a_n, i_idx, int_a);///this function might be wrong + n_clus = usg_unique_arcs_cluster_adv(b64, a_n, i_idx, int_a, ub64); + // fprintf(stderr, "**3**[M::%s::] a_n::%lu, n_clus::%lu\n", __func__, a_n, n_clus); + // prt_thread_info(b64.a, a_n, NULL, 0, "tt4"); + assert(b64->n == (a_n<<1)); + old_path_ext(uidx, ng, b64, ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext); + // new_path_ext(uidx, ng, &b64, &ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext);//wrong + return b64->n - a_n; +} + +void merge_hybrid_utg_content(ma_utg_t* cc, ma_ug_t* raw, asg_t* rg, usg_t *ng, kvec_asg_arc_t_warp* edge); +void renew_usg_t_bub(ul_resolve_t *uidx, usg_t *ng, uint32_t *id_map, uint8_t *ff, uint32_t rocc_cut) +{ + ma_ug_t *ug = ma_ug_hybrid_gen(ng); + uint32_t i, k, v, p[2]; ma_utg_t *u; p[0] = 1; p[1] = 2; + memset(id_map, -1, sizeof((*id_map))*ng->n); + memset(ff, 0, sizeof((*ff))*(ng->n<<1)); + kvec_asg_arc_t_warp e; kv_init(e.a); e.i = 0; + // for (i = dn = 0; i < ng->n; i++) { + // if(ng->a[i].del) continue; + // dn++; + // } + // fprintf(stderr, "ng->n::%u, ug->u.n::%u, dn::%u\n", (uint32_t)ng->n, (uint32_t)ug->u.n, dn); + // dn = 0 + for (i = 0; i < ug->u.n; i++) { + ug->g->seq[i].c = PRIMARY_LABLE; + u = &(ug->u.a[i]); + if(u->m == 0) continue; + for (k = 0; k < u->n; k++) { + v = u->a[k]>>32; + id_map[v>>1] = i<<2; + if(k == 0) id_map[v>>1] |= p[(v^1)&1]; + if(k + 1 == u->n) id_map[v>>1] |= p[(v)&1]; + // dn++; + } + // fprintf(stderr, "+[M::%s] i::%u\n", __func__, i); + merge_hybrid_utg_content(u, uidx->l1_ug, uidx->sg, ng, &e); + // fprintf(stderr, "-[M::%s] i::%u\n", __func__, i); + ug->g->seq[i].len = u->len; + } + kv_destroy(e.a); + + destory_bubbles(uidx->bub); free(uidx->bub); CALLOC(uidx->bub, 1); + // fprintf(stderr, "[M::%s] homozygous read coverage threshold: %d\n", __func__, asm_opt.hom_global_coverage_set? + // asm_opt.hom_global_coverage:(int)(((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE))); + // identify_bubbles(ug, uidx->bub, uidx->r_het, NULL); + if(asm_opt.polyploidy <= 2) { + identify_bubbles_recal(uidx->sg, ug, uidx->bub, uidx->r_het, uidx->uopt->sources, uidx->uopt->ruIndex, NULL); + } else { + identify_bubbles_recal_poy(uidx->sg, ug, uidx->bub, uidx->r_het, uidx->uopt->sources, uidx->uopt->ruIndex, NULL); + } + + // fprintf(stderr, "0[M::%s::] f[51]::%u\n", __func__, ff[51]); + for (i = 0; i < ng->n; i++) { + if(id_map[i] != (uint32_t)-1) { + k = id_map[i]>>2; + // fprintf(stderr, "k::%u, ng->n::%u, ug->u.n::%u, dn::%u\n", k, (uint32_t)ng->n, (uint32_t)ug->u.n, dn); + // if(i == 7075 || i == 28174 || i == 77111 || i == 3826 || i == 12150 || i == 58312 || i == 59190 || i == 72134) { + // fprintf(stderr, "[M::%s::k->%u] utg%.6dl(%c), ug->u.a[k].n::%u, rocc_cut::%u, is_hom::%u\n", __func__, k, + // i+1, "+-"[0], (uint32_t)ug->u.a[k].n, rocc_cut, IF_HOM(k, (*(uidx->bub)))); + // } + if((ug->u.a[k].n >= rocc_cut) && + ((!(IF_HOM(k, (*(uidx->bub))))) || (asm_opt.purge_level_primary == 0))) { + if(id_map[i]&p[0]) { + ff[i<<1] = 2; + // fprintf(stderr, "[M::%s::] utg%.6dl(%c), ug->u.a[k].n::%u, rocc_cut::%u\n", __func__, + // i+1, "+-"[0], (uint32_t)ug->u.a[k].n, rocc_cut); + } + if(id_map[i]&p[1]) { + ff[(i<<1)+1] = 2; + // fprintf(stderr, "[M::%s::] utg%.6dl(%c), ug->u.a[k].n::%u, rocc_cut::%u\n", __func__, + // i+1, "+-"[1], (uint32_t)ug->u.a[k].n, rocc_cut); + } + } + id_map[i] = uidx->bub->index[k]; + } + } + // fprintf(stderr, "1[M::%s::] f[51]::%u\n", __func__, ff[51]); + free(uidx->bub->index); MALLOC(uidx->bub->index, ng->n); + memcpy(uidx->bub->index, id_map, sizeof((*id_map))*ng->n); + if(asm_opt.purge_level_primary == 0) {///all nodes are het + for (k = 0; k < ug->g->n_seq; k++) { + if(IF_HOM(k, *(uidx->bub))) uidx->bub->index[k] = uidx->bub->f_bub+1; + } + } + ma_ug_destroy(ug); +} + +void gen_hybrid_aln_idx(usg_t *ng, uint64_t *int_idx, uint64_t int_idx_n, uint64_t *int_a, uint64_t int_an, asg64_v *b64, uint64_t *ridx) +{ + uint64_t k, i, l, m, v, s, e, *a, a_n; + kv_resize(uint64_t, *b64, int_an); b64->n = int_an; + memset(ridx, 0, sizeof((*ridx))*ng->n); + for (k = 0; k < int_idx_n; k++) {///scan all integer contigs + s = int_idx[k]>>32; e = s + ((uint32_t)int_idx[k]); assert(e > s + 1);//the length is at least 2 + for (i = s; i < e; i++) ridx[int_a[i]>>1]++; + } + + for (k = l = 0; k < ng->n; k++) { + m = ridx[k]; + ridx[k] = l; ridx[k] <<= 32; ridx[k] |= m; + l += m; + } + + for (k = 0; k < ng->n; k++) { + a = b64->a + (ridx[k]>>32); a_n = (uint32_t)ridx[k]; + if(a_n) a[a_n-1] = 0; + } + + for (k = 0; k < int_idx_n; k++) { + s = int_idx[k]>>32; e = s + ((uint32_t)int_idx[k]); assert(e > s + 1);//the length is at least 2 + for (i = s; i < e; i++) { + v = int_a[i]>>1; + a = b64->a + (ridx[v]>>32); + a_n = (uint32_t)ridx[v]; + if(a_n) { + if(a[a_n-1] == a_n-1) { + a[a_n-1] = (k<<32)|i; + } else { + a[a[a_n-1]++] = (k<<32)|i; + } + } + } + } +} + +void gen_sub_integer_path(uint64_t *int_a, int64_t s, int64_t e, int64_t it, uint64_t v, asg64_v *res) +{ + int64_t k; res->n = 0; assert((int_a[it]>>1) == (v>>1)); + if(int_a[it] == v) {///forward + kv_resize(uint64_t, *res, (uint64_t)(e - it)); + for (k = it; k < e; k++) res->a[res->n++] = int_a[k]; + } else {//reverse + kv_resize(uint64_t, *res, (uint64_t)(it - s)); + for (k = it; k >= s; k--) res->a[res->n++] = int_a[k]^1; + } +} + +void prt_sub_integer_path(asg64_v *res, uint64_t it, uint64_t w0, uint64_t w1, uint64_t z_n, uint64_t z) +{ + uint64_t k; + fprintf(stderr, "(it::%lu) res->n::%u, w0::%lu, w1::%lu, z_n::%lu, z::%lu\n", it, (uint32_t)res->n, + w0, w1, z_n, z); + for (k = 0; k < res->n; k++) { + fprintf(stderr, "(it::%lu) utg%.6dl,", it, (int32_t)(res->a[k]>>1)+1); + } + fprintf(stderr, "\n"); +} + +uint64_t is_best_path(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t *int_a, +uint64_t s, uint64_t e, uint64_t it, uint64_t v, uint64_t *ridx_a, uint64_t *ridx, +asg64_v *b0, asg64_v *b1, double cutoff) +{ + uint64_t *arc_a, arc_n, k, is, ie, z, zn, w0, w1, min_w0, min_w1, alt_n = 0, is_contain = 1; + gen_sub_integer_path(int_a, s, e, it, v, b0); + + arc_a = ridx_a + (ridx[v>>1]>>32); + arc_n = (uint32_t)ridx[v>>1]; + + + // uint64_t is_debug = 0; + // if((((v>>1) == 2736) && (v&1))/** && (b0->n > 1 && (b0->a[b0->n-1]>>1) == 34944)**/) { + // // is_debug = 1; + // fprintf(stderr, "[M::%s::] utg%.6dl(%c)\n", __func__, + // (int32_t)(v>>1)+1, "+-"[v&1]); + // prt_sub_integer_path(b0, it, (uint64_t)-1, (uint64_t)-1, (uint64_t)-1, (uint64_t)-1); + // } + + + for (k = 0, min_w0 = min_w1 = (uint64_t)-1, is_contain = 1; k < arc_n; k++) { + if(it == ((uint32_t)arc_a[k])) continue; + is = int_idx[arc_a[k]>>32]>>32; alt_n++; + ie = is + ((uint32_t)(int_idx[arc_a[k]>>32])); + gen_sub_integer_path(int_a, is, ie, ((uint32_t)arc_a[k]), v, b1); + zn = MIN(b0->n, b1->n); + for (z = 0; z < zn && b0->a[z] == b1->a[z]; z++); ///z: first raw unitig that is different between two paths + assert(z > 0); w0 = w1 = (uint64_t)-1; + if(z < b0->n) get_integer_seq_ovlps(uidx, b0->a, b0->n, z - 1, 0, NULL, &w0); + else return 0;///b0 is contained + if(z < b1->n) get_integer_seq_ovlps(uidx, b1->a, b1->n, z - 1, 0, NULL, &w1); + else continue;///b1 is contained + // if(((v>>1) == 2736) && (v&1)) { + // prt_sub_integer_path(b0, it, w0, w1, zn, z); + // prt_sub_integer_path(b1, it, w0, w1, zn, z); + // } + if(w0 == (uint64_t)-1) w0 = 0; + if(w1 == (uint64_t)-1) w1 = 0; + if((w0 <= w1) || (w1 > (w0*cutoff))) return 0; + // if(b0->n == zn) return 0;///b0 is shorter + // if(b1->n == zn) continue;///b1 is shorter + if((min_w0 == (uint64_t)-1) || (z == zn) || (min_w0 > w0) || (min_w0 == w0 && min_w1 < w1)) { + min_w0 = w0; min_w1 = w1; + } + is_contain = 0; + } + + // if(((v>>1) == 2736) && (v&1)) { + // fprintf(stderr, "[M::%s::] min_w0::%lu, min_w1::%lu\n\n", __func__, min_w0, min_w1); + // } + // fprintf(stderr, "[M::%s::] utg%.6dl(%c)->utg%.6dl(%c)\n", __func__, + // (int32_t)(v>>1)+1, "+-"[v&1], (int32_t)(int_a[k]>>1)+1, "+-"[int_a[k]&1]); + if(alt_n == 0) return 1; + if(is_contain) return 1; + + if(min_w0 == (uint64_t)-1) min_w0 = 0; + if(min_w1 == (uint64_t)-1) min_w1 = 0; + if((min_w0 > min_w1) && (min_w1 <= (min_w0*cutoff))) return 1; + return 0; +} + + +void get_best_path(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t *int_a, +uint8_t *f, uint64_t s, uint64_t e, asg64_v *b0, asg64_v *b1, uint64_t *ridx_a, +uint64_t *ridx, asg64_v *res) +{ + uint64_t pi, v, k, res_n = res->n, *pz; + b0->n = b1->n = 0; + for (k = s, pi = (uint64_t)-1; k < e; k++) { + v = int_a[k]; + if((!f[v])&&(!f[v^1])) continue; + if((pi != (uint64_t)-1) && (f[v^1])) { + // if(((v>>1) == 2736)) { + // fprintf(stderr, "+[M::%s::ii[%lu, %lu)] utg%.6dl(%c), f[v^1]::%u, v^1::%lu, putg%.6dl(%c), f[pv]::%u, pv::%lu\n", + // __func__, s, e, (int32_t)(int_a[k]>>1)+1, "+-"[int_a[k]&1], f[v^1], v^1, + // (int32_t)(int_a[pi]>>1)+1, "+-"[int_a[pi]&1], f[int_a[pi]], int_a[pi]); + // } + if(is_best_path(uidx, ng, int_idx, int_a, s, e, k, v^1, ridx_a, ridx, b0, b1, 0.51)) { + // if(((v>>1) == 2736)) { + // fprintf(stderr, "-[M::%s::ii[%lu, %lu)] utg%.6dl(%c), f[v^1]::%u, v^1::%lu, putg%.6dl(%c), f[pv]::%u, pv::%lu\n", + // __func__, s, e, (int32_t)(int_a[k]>>1)+1, "+-"[int_a[k]&1], f[v^1], v^1, + // (int32_t)(int_a[pi]>>1)+1, "+-"[int_a[pi]&1], f[int_a[pi]], int_a[pi]); + // } + // fprintf(stderr, "[M::%s::] utg%.6dl(%c)->utg%.6dl(%c)\n", __func__, + // (int32_t)(int_a[pi]>>1)+1, "+-"[int_a[pi]&1], (int32_t)(int_a[k]>>1)+1, "+-"[int_a[k]&1]); + pz = (res->n > res_n)? &(res->a[res->n-1]):(NULL); + if((!pz) || (((*pz)>>32) != pi)) {//keep the shortest pi<->k + kv_pushp(uint64_t, *res, &pz); + *pz = pi; (*pz) <<= 32; (*pz) |= k; + } + } else { + pi = (uint64_t)-1; + } + } + if(f[v]) { + // fprintf(stderr, "-[M::%s::] utg%.6dl(%c), f[v]::%u, v::%lu\n", + // __func__, (int32_t)(int_a[k]>>1)+1, "+-"[int_a[k]&1], f[v], v); + if(is_best_path(uidx, ng, int_idx, int_a, s, e, k, v, ridx_a, ridx, b0, b1, 0.51)) { + pi = k;//keep the shortest pi<->k + } else { + pi = (uint64_t)-1; + } + } + } +} + + +uint64_t gen_sub_integer_path_ff(uint64_t *int_a, int64_t s, int64_t e, int64_t it, uint64_t v, uint8_t *f, asg64_v *res) +{ + int64_t k; res->n = 0; assert((int_a[it]>>1) == (v>>1)); + if(int_a[it] == v) {///forward + kv_resize(uint64_t, *res, (uint64_t)(e - it)); + for (k = it; k < e; k++) { + res->a[res->n++] = int_a[k]; + if(res->n > 1 && f[res->a[res->n-1]^1]) return res->n; + } + } else {//reverse + kv_resize(uint64_t, *res, (uint64_t)(it - s)); + for (k = it; k >= s; k--) { + res->a[res->n++] = int_a[k]^1; + if(res->n > 1 && f[res->a[res->n-1]^1]) return res->n; + } + } + res->n = 0; return 0; +} + +uint64_t is_best_pair(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t *int_a, +uint64_t s, uint64_t e, uint64_t it, uint64_t v, uint64_t *ridx_a, uint64_t *ridx, +asg64_v *b0, asg64_v *b1, uint8_t *f, double cutoff) +{ + uint64_t *arc_a, arc_n, k, is, ie, w0 = 0, w1 = 0, sup_cut = 3; + if(!gen_sub_integer_path_ff(int_a, s, e, it, v, f, b0)) return 0; + assert(b0->n >= 2); assert(f[b0->a[0]] && f[b0->a[b0->n-1]^1]); + w0 = get_arc_support_chain(uidx, b0->a, b0->n, ng); + if(w0 < sup_cut) return 0; + + arc_a = ridx_a + (ridx[v>>1]>>32); + arc_n = (uint32_t)ridx[v>>1]; + for (k = 0; k < arc_n; k++) { + if(it == ((uint32_t)arc_a[k])) continue; + is = int_idx[arc_a[k]>>32]>>32; + ie = is + ((uint32_t)(int_idx[arc_a[k]>>32])); + if(!gen_sub_integer_path_ff(int_a, is, ie, ((uint32_t)arc_a[k]), v, f, b1)) continue; + assert(b1->n >= 2); assert(f[b1->a[0]] && f[b1->a[b1->n-1]^1]); + if((b0->n == b1->n) && (memcmp(b0->a, b1->a, sizeof((*(b0->a)))*b0->n) == 0)) { + if(it < ((uint32_t)arc_a[k])) continue; + else return 0;///only keep 1 equal interval + } + w1 = get_arc_support_chain(uidx, b1->a, b1->n, ng); + // fprintf(stderr, "[M::%s::] w0::%lu, w1::%lu\n", __func__, w0, w1); + if((w0 <= w1) || (w1 > (w0*cutoff))) return 0; + } + return 1; +} + +void get_best_pair(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t *int_a, +uint8_t *f, uint64_t s, uint64_t e, asg64_v *b0, asg64_v *b1, uint64_t *ridx_a, +uint64_t *ridx, asg64_v *res) +{ + uint64_t pi, v, k, *pz; + b0->n = b1->n = 0; + for (k = s, pi = (uint64_t)-1; k < e; k++) { + v = int_a[k]; + if((f[v^1])) { + if(pi != (uint64_t)-1) { + if(is_best_pair(uidx, ng, int_idx, int_a, s, e, k, v^1, ridx_a, ridx, b0, b1, f, 0.51)) { + kv_pushp(uint64_t, *res, &pz); + *pz = pi; (*pz) <<= 32; (*pz) |= k; + } + } + pi = (uint64_t)-1; + } + if(f[v]) { + pi = (uint64_t)-1; + if(is_best_pair(uidx, ng, int_idx, int_a, s, e, k, v, ridx_a, ridx, b0, b1, f, 0.51)) { + pi = k;//keep the shortest pi<->k + } + } + } +} + +static void worker_ul_aln_path(void *data, long i, int tid) // callback for kt_for() +{ + unique_bridge_check_t *u_aux = (unique_bridge_check_t*)data; + ul_resolve_t *uidx = u_aux->uidx; + integer_t *buf = &(uidx->str_b.buf[tid]); + uint64_t s, e; + // uint64_t *x = &(uidx->uovl.iug_tra->a[i]); + // asg_arc_t *ve = &(uidx->uovl.i_ug->g->arc[*x]); + + asg64_v b_v, b_r, res; + b_v.a = buf->u.a; b_v.n = buf->u.n; b_v.m = buf->u.m; + b_r.a = buf->o.a; b_r.n = buf->o.n; b_r.m = buf->o.m; + res.a = buf->res_dump.a; res.n = buf->res_dump.n; res.m = buf->res_dump.m; + + b_v.n = b_r.n = 0; + s = u_aux->int_idx[i]>>32; ///the i-th integer contig/path + e = s + ((uint32_t)(u_aux->int_idx[i])); + assert(e > s + 1);//the length is at least 2 + + get_best_path(uidx, u_aux->ng, u_aux->int_idx, u_aux->int_a, u_aux->f, s, e, &b_v, &b_r, u_aux->ridx_a, u_aux->ridx, &res); + // get_ul_arc_supports(uidx, ve, &b_v, &b_r, 1, &w_v, &w_r); + + buf->u.a = b_v.a; buf->u.n = b_v.n; buf->u.m = b_v.m; + buf->o.a = b_r.a; buf->o.n = b_r.n; buf->o.m = b_r.m; + buf->res_dump.a = res.a; buf->res_dump.n = res.n; buf->res_dump.m = res.m; +} + +static void worker_ul_aln_pair(void *data, long i, int tid) // callback for kt_for() +{ + unique_bridge_check_t *u_aux = (unique_bridge_check_t*)data; + ul_resolve_t *uidx = u_aux->uidx; + integer_t *buf = &(uidx->str_b.buf[tid]); + uint64_t s, e; + // uint64_t *x = &(uidx->uovl.iug_tra->a[i]); + // asg_arc_t *ve = &(uidx->uovl.i_ug->g->arc[*x]); + + asg64_v b_v, b_r, res; + b_v.a = buf->u.a; b_v.n = buf->u.n; b_v.m = buf->u.m; + b_r.a = buf->o.a; b_r.n = buf->o.n; b_r.m = buf->o.m; + res.a = buf->res_dump.a; res.n = buf->res_dump.n; res.m = buf->res_dump.m; + + b_v.n = b_r.n = 0; + s = u_aux->int_idx[i]>>32; ///the i-th integer contig/path + e = s + ((uint32_t)(u_aux->int_idx[i])); + assert(e > s + 1);//the length is at least 2 + + get_best_pair(uidx, u_aux->ng, u_aux->int_idx, u_aux->int_a, u_aux->f, s, e, &b_v, &b_r, u_aux->ridx_a, u_aux->ridx, &res); + // get_ul_arc_supports(uidx, ve, &b_v, &b_r, 1, &w_v, &w_r); + + buf->u.a = b_v.a; buf->u.n = b_v.n; buf->u.m = b_v.m; + buf->o.a = b_r.a; buf->o.n = b_r.n; buf->o.m = b_r.m; + buf->res_dump.a = res.a; buf->res_dump.n = res.n; buf->res_dump.m = res.m; +} + +uint32_t ug_ext_0(ul_resolve_t *uidx, usg_t *ng, uint64_t *int_idx, uint64_t int_idx_n, uint64_t *int_a, uint32_t max_ext, +uint8_t *ff, uint32_t *ng_occ, uint64_t *i_idx, asg64_v *b64, asg64_v *ub64, uint64_t a_n) +{ + uint32_t n_vtx = ng->n<<1, k, i; uint64_t *pz; + uint64_t s, e, n_clus; + memset(ff, 0, sizeof((*ff))*n_vtx); + // memset(ng_occ, 0, sizeof((*ng_occ))*n_vtx); + memset(i_idx, 0, sizeof((*i_idx))*n_vtx); + ub64->n = 0; + + for (i = 0; i < a_n; i++) { ///available intervals + s = b64->a[i]>>32; e = (uint32_t)b64->a[i]; assert(e > s);///[s, e] -> coordinates within int_a[] + assert(!(b64->a[i]&((uint64_t)0x8000000000000000))); + // fprintf(stderr, "\n[M::%s::] occ::%lu\n", __func__, e - s); + // for (k = s; k <= e; k++) { + // // fprintf(stderr, "utg%.6dl(%c),", (int32_t)(int_a[k]>>1)+1, "+-"[int_a[k]&1]); + // fprintf(stderr, "utg%.6dl,", (int32_t)(int_a[k]>>1)+1); + // } + // fprintf(stderr, "\n"); + + for (k = s + 1; k < e; k++) {///note: here is [s, e]; s && e are unique, but [s+1, e-1] are not unique + kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[k]]++; + (*pz) = int_a[k]; (*pz) <<= 32; (*pz) |= i;///(raw unitig/non-unqiue node id)|(integer contig id) + + kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[k]^1]++; + (*pz) = int_a[k]^1; (*pz) <<= 32; (*pz) |= i; + } + kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[s]]++; + (*pz) = int_a[s]; (*pz) <<= 32; (*pz) |= i; + + kv_pushp(uint64_t, *b64, &pz); //i_idx[int_a[e]^1]++; + (*pz) = int_a[e]^1; (*pz) <<= 32; (*pz) |= i; + } + // prt_thread_info(b64.a, a_n, NULL, 0, "tt2"); + // fprintf(stderr, "**1**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); + ///index + radix_sort_srt64(b64->a + a_n, b64->a + b64->n);///(raw unitig node id)|(integer contig id) + for (k = a_n + 1, i = a_n; k <= b64->n; k++) { + if(k == b64->n || (b64->a[k]>>32) != (b64->a[i]>>32)) { + i_idx[b64->a[i]>>32] |= (((uint64_t)i)<<32)|((uint64_t)k);///b64.a[i]>>32 appear once (unique ends)/multipe times + i = k; + } + } + + n_clus = usg_unique_arcs_cluster_adv(b64, a_n, i_idx, int_a, ub64); + // fprintf(stderr, "**3**[M::%s::] a_n::%lu, n_clus::%lu\n", __func__, a_n, n_clus); + // prt_thread_info(b64.a, a_n, NULL, 0, "tt4"); + assert(b64->n == (a_n<<1)); + + // new_path_ext(uidx, ng, &b64, &ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext);//wrong + return old_path_ext(uidx, ng, b64, ub64, a_n, n_clus, i_idx, int_a, ff, ng_occ, max_ext); +} + +void debug_prt_renew_aln(usg_t *ng, uint64_t *int_idx, uint64_t int_idx_n, uint64_t *int_a, uint64_t int_an, asg64_v *b64, uint64_t *ridx) +{ + uint64_t k, s, e, i; + for (i = 0; i < int_idx_n; i++) {///scan all integer contigs + s = int_idx[i]>>32; e = s + ((uint32_t)int_idx[i]); assert(e > s + 1);//the length is at least 2 + fprintf(stderr, "\n[M::%s::] occ::%lu\n", __func__, e - s); + for (k = s; k <= e; k++) { + // fprintf(stderr, "utg%.6dl(%c),", (int32_t)(int_a[k]>>1)+1, "+-"[int_a[k]&1]); + fprintf(stderr, "utg%.6dl,", (int32_t)(int_a[k]>>1)+1); + } + fprintf(stderr, "\n"); + } +} + +uint32_t ug_ext_free(asg64_v *ob, asg64_v *ub, ul_resolve_t *uidx, usg_t *ng, uint32_t max_ext, +uint8_t **ff, uint32_t **ng_occ, uint64_t **i_idx, asg64_v *b64, asg64_v *ub64, uint32_t rocc_cut, +uint32_t thread_path) +{ + // fprintf(stderr, "[M::%s::] rocc_cut::%u\n", __func__, rocc_cut); + uint32_t k, n_vtx = ng->n<<1, a_n; unique_bridge_check_t u_aux; + REALLOC((*ff), n_vtx); REALLOC((*ng_occ), n_vtx); REALLOC((*i_idx), n_vtx); + renew_usg_t_bub(uidx, ng, *ng_occ, *ff, rocc_cut); + u2g_hybrid_aln(uidx, ng, ob, ub); + gen_hybrid_aln_idx(ng, ub->a, ub->n, ob->a, ob->n, b64, *i_idx); + // if(rocc_cut == 10) + // { + // fprintf(stderr, "\n[M::%s::] rocc_cut::%u\n", __func__, rocc_cut); + // debug_prt_renew_aln(ng, ub->a, ub->n, ob->a, ob->n, b64, *i_idx); + // } + + u_aux.f = *ff; u_aux.ng = ng; u_aux.int_idx = ub->a; u_aux.int_idx_n = ub->n; u_aux.uidx = uidx; + u_aux.int_a = ob->a; u_aux.int_an = ob->n; u_aux.ridx_a = b64->a; u_aux.ridx = *i_idx; + for (k = 0; k < uidx->str_b.n_thread; k++) { + uidx->str_b.buf[k].res_dump.n = uidx->str_b.buf[k].u.n = uidx->str_b.buf[k].o.n = 0; + } + + if(thread_path) { + kt_for(uidx->str_b.n_thread, worker_ul_aln_path, &u_aux, u_aux.int_idx_n); + } else { + kt_for(uidx->str_b.n_thread, worker_ul_aln_pair, &u_aux, u_aux.int_idx_n); + } + + for (k = b64->n = a_n = 0; k < uidx->str_b.n_thread; k++) { + a_n += uidx->str_b.buf[k].res_dump.n; + kv_resize(uint64_t, *b64, a_n); + memcpy(b64->a+b64->n, uidx->str_b.buf[k].res_dump.a, uidx->str_b.buf[k].res_dump.n*(sizeof(*(b64->a)))); + b64->n = a_n; + } + radix_sort_srt64(b64->a, b64->a + b64->n);///keeps the coordinates within int_a[] + // fprintf(stderr, "[M::%s::] a_n::%u, int_idx_n::%u, int_n::%u\n", + // __func__, a_n, (uint32_t)ub->n, (uint32_t)ob->n); + a_n = ug_ext_0(uidx, ng, ub->a, ub->n, ob->a, max_ext, *ff, *ng_occ, *i_idx, b64, ub64, a_n); + // if(a_n) usg_cleanup(ng); + return a_n; +} + +uint32_t ug_ext_strict(asg64_v *ob, asg64_v *ub, ul_resolve_t *uidx, usg_t *ng, uint32_t max_ext, +uint8_t **ff, uint32_t **ng_occ, uint64_t **i_idx, asg64_v *b64, asg64_v *ub64) +{ + // fprintf(stderr, "[M::%s::]\n", __func__); + uint32_t k, i, n_vtx = ng->n<<1, a_n; + REALLOC((*ff), n_vtx); REALLOC((*ng_occ), n_vtx); REALLOC((*i_idx), n_vtx); + u2g_hybrid_aln(uidx, ng, ob, ub); b64->n = ub64->n = 0; + uint64_t *int_idx = ub->a, int_idx_n = ub->n, *int_a = ob->a; + uint64_t *r_a, r_n, zs, ze, s, e, pi, v, *pz; + + memset((*ng_occ), 0, sizeof((*(*ng_occ)))*n_vtx); + for (k = 0; k < int_idx_n; k++) {///scan all integer contigs + r_a = int_a + (int_idx[k]>>32); r_n = (uint32_t)int_idx[k]; + assert(r_n >= 2); + for (i = 1; i + 1 < r_n; i++) { + (*ng_occ)[r_a[i]]++; (*ng_occ)[r_a[i]^1]++; + } + (*ng_occ)[r_a[0]]++; (*ng_occ)[r_a[r_n-1]^1]++; + } + + ma_ug_t *un_g = ma_ug_hybrid_gen(ng); + int32_t ui, un; ma_utg_t *u = NULL; + for (k = 0; k < un_g->u.n; k++) {///all unitigs of raw utg + u = &(un_g->u.a[k]); + zs = ze = (uint32_t)-1; un = u->n; + for (ui = 0; ui < un; ui++) { + if(occ_m((*ng_occ)[(u->a[ui]>>32)^1]) == 1) { + zs = ui; break; + } + } + + for (ui = ((int32_t)un)-1; ui >= 0; ui--) { + if(occ_m((*ng_occ)[u->a[ui]>>32]) == 1) { + ze = ui; break; + } + } + if(zs != (uint32_t)-1 && ze != (uint32_t)-1 && zs > ze) continue; + if(zs != (uint32_t)-1) (*ng_occ)[(u->a[zs]>>32)^1] |= ((uint32_t)0x80000000); + if(ze != (uint32_t)-1) (*ng_occ)[(u->a[ze]>>32)] |= ((uint32_t)0x80000000); + } + ma_ug_destroy(un_g); + + // fprintf(stderr, ">>>>>>[M::%s::] int_idx[0]::%lu, int_idx[1]::%lu\n", __func__, int_idx[0], int_idx[1]); + // prt_intg_info(int_idx, int_idx_n, int_a, "intg"); + for (i = b64->n = a_n = 0; i < int_idx_n; i++) {///scan all integer contigs + s = int_idx[i]>>32; e = s + ((uint32_t)int_idx[i]); + assert(e > s + 1);//the length is at least 2 + for (k = s, pi = (uint64_t)-1; k < e; k++) { + v = int_a[k]; + if((!((*ng_occ)[v]&((uint32_t)0x80000000)))&&(!((*ng_occ)[v^1]&((uint32_t)0x80000000)))) { + continue;///it must be a unique node + } + if((pi != (uint64_t)-1) && ((*ng_occ)[v^1]&((uint32_t)0x80000000))) { + pz = (b64->n>0)? &(b64->a[b64->n-1]):(NULL); + if((!pz) || (((*pz)>>32) != pi)) {//keep the shortest pi<->k + kv_pushp(uint64_t, *b64, &pz); + *pz = pi; (*pz) <<= 32; (*pz) |= k; + a_n++; + } + } + if((*ng_occ)[v]&((uint32_t)0x80000000)) pi = k;//keep the shortest pi<->k + } + } + // prt_thread_info(b64.a, a_n+ua_n, NULL, 0, "tt_minus"); + // fprintf(stderr, "**0**[M::%s::] a_n::%lu, ua_n::%lu\n", __func__, a_n, ua_n); + radix_sort_srt64(b64->a, b64->a + b64->n);///keeps the coordinates within int_a[] + + a_n = ug_ext_0(uidx, ng, ub->a, ub->n, ob->a, max_ext, *ff, *ng_occ, *i_idx, b64, ub64, a_n); + // if(a_n) usg_cleanup(ng); + return a_n; +} + +typedef struct { + uint32_t nid, ulid; + uint32_t raw_sid, raw_eid; + uint32_t raw_sof, raw_eof; +} usc_t; + +typedef struct { + usc_t *a; + size_t n, m; +} usc_vec_t; + +typedef struct { + // ul_resolve_t *uidx; + usc_t *a; + uint64_t a_n; + ma_ug_t *ug; +} scaf_mul_t; + + + +#define B4Lg(x) (((x)>>2)+(((x)&3)?1:0)) +uint32_t load_scaf_base(all_ul_t *x, char* file_name, const char *bin_file) +{ + char *gfa_name = (char*)malloc(strlen(file_name)+50); + sprintf(gfa_name, "%s.%s.uidx.ucr.bin", file_name, bin_file); + // fprintf(stderr, "[M::%s] open %s...\n", __func__, gfa_name); + FILE *fp = fopen(gfa_name, "r"); free(gfa_name); + if (!fp) return 0; + // fprintf(stderr, "[M::%s] open sucess\n", __func__); + uint64_t rid; uint32_t len; ul_vec_t ss, *z; memset(&ss, 0, sizeof(ss)); + while(1) { + fread(&rid, sizeof(rid), 1, fp); + if(feof(fp)) break; + z = &(x->a[rid]); + fread(&len, sizeof(len), 1, fp); assert(z->rlen == len); + fread(&(ss.N_site.n), sizeof(ss.N_site.n), 1, fp); + kv_resize(uint32_t, ss.N_site, ss.N_site.n); + fread(ss.N_site.a, sizeof((*(ss.N_site.a))), ss.N_site.n, fp); + ss.r_base.n = B4Lg(len); kv_resize(uint8_t, ss.r_base, ss.r_base.n); + fread(ss.r_base.a, sizeof((*(ss.r_base.a))), ss.r_base.n, fp); + // if(rid == 37238) { + // fprintf(stderr, "[M::%s::37238] z->dd::%u\n", __func__, z->dd); + // } + // fprintf(stderr, "[M::%s::rid->%lu] z->dd::%u\n", __func__, rid, z->dd); + if(z->dd != 4) continue; + + + kv_resize(uint32_t, z->N_site, ss.N_site.n); z->N_site.n = ss.N_site.n; + memcpy(z->N_site.a, ss.N_site.a, sizeof((*(z->N_site.a)))*z->N_site.n); + + kv_resize(uint8_t, z->r_base, ss.r_base.n); z->r_base.n = ss.r_base.n; + memcpy(z->r_base.a, ss.r_base.a, sizeof((*(z->r_base.a)))*z->r_base.n); + } + // load_compress_base_disk(fp, &rid, des.a, &ulen, &(sl->ucr_s->u)); + + fclose(fp); free(ss.N_site.a); free(ss.r_base.a); + return 1; +} + + +uint64_t reset_scaf_node_uinfo_srt_t(usc_t *z, int64_t min_arc_len, int64_t scaf_len, int64_t *nlen) +{ + (*nlen) = scaf_len + (min_arc_len<<1); + if(z->ulid == ((uint32_t)-1)) return 0;///a scaffold node + if(z->raw_eof + min_arc_len <= z->raw_sof) {///has an overlap longer than min_arc_len; + return 1;///a scaffold node; no need this node, could directly use existing nodes + } + int64_t s, e; + s = z->raw_sof; e = z->raw_eof; + (*nlen) = (min_arc_len<<1) + (e - s); ///(e - s)>=(-min_arc_len) + return 2; +} + + +void get_end_hifi(char *des, uint32_t v, All_reads* rdb, uint32_t len, uint32_t is_beg) +{ + uint32_t rlen = Get_READ_LENGTH((*rdb), (v>>1)); + assert(rlen >= len); + recover_UC_Read_sub_region(des, ((is_beg)?(rlen-len):(0)), len, v&1, rdb, v>>1); +} + +void get_ul_subregion(all_ul_t *x, char *des, uint32_t id, uint32_t rev, int64_t ssp, int64_t sep, uint32_t reset_Ns) +{ + ul_vec_t *z = &(x->a[id]); + int64_t sl, slr, offset, begLen, tailLen, a_n, src_i, des_i, i; + sl = sep - ssp; + offset = ssp&3; begLen = 4-offset; + if(begLen > sl) begLen = sl; + tailLen = (sl-begLen)&3; + a_n = (sl - begLen - tailLen)>>2; + + // fprintf(stderr, "[M::%s] z->r_base.n::%u, begLen::%ld, tailLen::%ld, a_n::%ld\n", + // __func__, (uint32_t)z->r_base.n, begLen, tailLen, a_n); + src_i = ssp; i = 0; des_i = 0; + if(begLen > 0) { + // fprintf(stderr, "[M::%s] des_i::%ld, src_i>>2::%ld\n", __func__, des_i, src_i>>2); + memcpy(des+des_i, bit_t_seq_table[z->r_base.a[src_i>>2]]+offset, begLen); + des_i += begLen; src_i += begLen; + } + + for (i = 0; i < a_n; i++) { + // fprintf(stderr, "[M::%s] des_i::%ld, src_i>>2::%ld\n", __func__, des_i, src_i>>2); + memcpy(des+des_i, bit_t_seq_table[z->r_base.a[src_i>>2]], 4); + des_i += 4; src_i += 4; + } + + if(tailLen > 0) { + // fprintf(stderr, "[M::%s] des_i::%ld, src_i>>2::%ld\n", __func__, des_i, src_i>>2); + memcpy(des+des_i, bit_t_seq_table[z->r_base.a[src_i>>2]], tailLen); + des_i += tailLen; src_i += tailLen; + } + + uint64_t k, sk = ssp, ek = sep; + for (k = 0; k < z->N_site.n; k++) { + if(z->N_site.a[k] >= sk && z->N_site.a[k] < ek){ + des[z->N_site.a[k]-sk] = 'N'; + } else if(z->N_site.a[k] >= ek) { + break; + } + } + + if(reset_Ns) { + for (i = 0; i < sl; i++) { + if (seq_nt4_table[(uint8_t)des[i]] >= 4) des[i] = 'A'; + } + } + + if(rev) { + char t; slr = sl>>1; + for (i = 0; i < slr; i++) { + t = des[sl-i-1]; + des[sl-i-1] = RC_CHAR(des[i]); + des[i] = RC_CHAR(t); + } + if(sl&1) des[i] = RC_CHAR(des[i]); + } +} + +int64_t push_scaf_bases(uint8_t *des, uint64_t** N_site, All_reads* rdb, all_ul_t *x, usc_t *z, int64_t min_arc_len, int64_t scaf_len, int64_t nlen, UC_Read *tu, +uint64_t *rmap, ma_ug_t *raw_g) +{ + int64_t nlen0, ff, Nocc, i; char *da = NULL; + ff = reset_scaf_node_uinfo_srt_t(z, min_arc_len, scaf_len, &nlen0); assert(nlen0 == nlen); + if(ff == 1) {///has an overlap longer than min_arc_len between z->raw_sid and z->raw_eid + memset(des, 0, sizeof((*(des)))*(nlen/4+1)); + return ff; + } + uint32_t uv, uw, sv, sw; int64_t s, e, ul; + uv = z->raw_sid; uw = z->raw_eid; + + sv = (uv&1?((raw_g->u.a[uv>>1].a[0]>>32)^1):(raw_g->u.a[uv>>1].a[raw_g->u.a[uv>>1].n-1]>>32)); + sw = (uw&1?((raw_g->u.a[uw>>1].a[raw_g->u.a[uw>>1].n-1]>>32)^1):(raw_g->u.a[uw>>1].a[0]>>32)); + resize_UC_Read(tu, nlen); da = tu->seq; + assert((Get_READ_LENGTH((*rdb), (sv>>1))) > ((uint32_t)min_arc_len)); + assert((Get_READ_LENGTH((*rdb), (sw>>1))) > ((uint32_t)min_arc_len)); + ///need introduce some UL bases; + ///or the overlap length between sv and sw is shorter than min_arc_len + if(ff == 2) { + s = z->raw_sof; e = z->raw_eof; ul = e - s; + assert(ul>=(-min_arc_len)); + // assert((Get_READ_LENGTH((*rdb), (sv>>1))) > ul); + // assert((Get_READ_LENGTH((*rdb), (sw>>1))) > ul); + get_end_hifi(da, sv, rdb, min_arc_len, 1); + get_end_hifi(da+min_arc_len+ul, sw, rdb, min_arc_len, 0); + if(ul > 0) {///need UL + // fprintf(stderr, "[M::%s] ulid::%u(%c), s::%ld, e::%ld, nlen::%ld, min_arc_len::%ld\n", __func__, + // z->ulid>>1, "+-"[z->ulid&1], s, e, nlen, min_arc_len); + get_ul_subregion(x, da+min_arc_len, z->ulid>>1, z->ulid&1, s, e, 1); + } + } else {///no UL found; ff = 0 + get_end_hifi(da, sv, rdb, min_arc_len, 1); + memset(da+min_arc_len, 'A', scaf_len); + get_end_hifi(da+min_arc_len+scaf_len, sw, rdb, min_arc_len, 0); + } + for (i = Nocc = 0; i < nlen; i++) { + if(seq_nt6_table[(uint8_t)da[i]] >= 4) Nocc++; + } + ha_compress_base(des, da, nlen, N_site, Nocc); + return ff; +} + +void realloc_rdb_adv(All_reads* rdb, all_ul_t *x, ma_sub_t **cov, R_to_U *ruI, uint64_t *rmap, +uint64_t rid_n, uint64_t scaf_len, char *scaf_id, asg_t *ng, ug_opt_t *uopt, ma_ug_t *raw_g, usc_t *a) +{ + uint64_t i, rid_n0 = rdb->total_reads, tname, cname; usc_t *z; + uint64_t scaf_id_len = strlen(scaf_id); char *des, *src; int64_t nlen, ff; + UC_Read g_read; init_UC_Read(&g_read); + rdb->total_reads = rid_n; + tname = rdb->name_index[rid_n0]; + fprintf(stderr, "+[M::%s] rid_n0::%lu, rid_n::%lu\n", __func__, rid_n0, rid_n); + ///for read bases + REALLOC(rdb->N_site, rdb->total_reads); + REALLOC(rdb->read_length, rdb->total_reads); + REALLOC(rdb->read_size, rdb->total_reads); + REALLOC(rdb->read_sperate, rdb->total_reads); + REALLOC(rdb->trio_flag, rdb->total_reads); + REALLOC(rdb->name_index, rdb->total_reads+1);///total_reads+1 + REALLOC((*cov), rdb->total_reads); + if(uopt->te) { + assert(uopt->te->n == rid_n0); + uopt->te->n = rdb->total_reads; + REALLOC(uopt->te->hh, rdb->total_reads); + } + for (i = rid_n0; i < rdb->total_reads; i++) { + // fprintf(stderr, "[M::%s] i::%lu\n", __func__, i); + rdb->N_site[i] = NULL; + rdb->trio_flag[i] = AMBIGU; + (*cov)[i].c = (*cov)[i].del = 0; + // rdb->read_length[i] = scaf_len; + // rdb->read_size[i] = scaf_len; + // (*cov)[i].s = 0; (*cov)[i].e = scaf_len; + // cname = scaf_id_len; + if(rmap[i] != ((uint64_t)-1)) {///not a scaffold node + if(rdb->N_site[rmap[i]] != NULL) { + MALLOC(rdb->N_site[i], rdb->N_site[rmap[i]][0]+1); + memcpy(rdb->N_site[i], rdb->N_site[rmap[i]], + sizeof((*(rdb->N_site[i])))*(rdb->N_site[rmap[i]][0]+1)); + } + rdb->read_length[i] = rdb->read_length[rmap[i]]; + rdb->read_size[i] = rdb->read_length[rmap[i]]; + (*cov)[i].s = (*cov)[rmap[i]].s; + (*cov)[i].e = (*cov)[rmap[i]].e; + rdb->trio_flag[i] = rdb->trio_flag[rmap[i]]; + (*cov)[i] = (*cov)[rmap[i]]; + cname = Get_NAME_LENGTH((*rdb), (rmap[i])); + if(uopt->te) uopt->te->hh[i] = uopt->te->hh[rmap[i]]; + } else { + z = &(a[(i-ng->r_seq)]); assert(z->nid == i); cname = scaf_id_len; + if(reset_scaf_node_uinfo_srt_t(z, uopt->min_ovlp, scaf_len, &nlen) == 2) { + cname = UL_INF.nid.a[z->ulid>>1].n;///ul name length + } + rdb->read_length[i] = nlen; + rdb->read_size[i] = nlen; + (*cov)[i].s = 0; (*cov)[i].e = nlen; + ng->seq[i].len = nlen;///update length for the scaffold node + if(uopt->te) uopt->te->hh[i] = 0; + } + rdb->name_index[i] = tname; tname += cname; + rdb->total_reads_bases += rdb->read_length[i]; + + MALLOC(rdb->read_sperate[i], (rdb->read_length[i]/4+1)); + if(rmap[i] != ((uint64_t)-1)) {///not a scaffold node + memcpy(rdb->read_sperate[i], rdb->read_sperate[rmap[i]], + sizeof((*(rdb->read_sperate[i])))*(rdb->read_length[i]/4+1)); + } else { + ///set to A + z = &(a[(i-ng->r_seq)]); assert(z->nid == i); + ff = push_scaf_bases(rdb->read_sperate[i], &(rdb->N_site[i]), rdb, x, z, uopt->min_ovlp, scaf_len, rdb->read_length[i], &g_read, rmap, raw_g); + if(ff == 1) ng->seq[i].del = 1;///could directly reuse HiFi; no need new node + // memset(rdb->read_sperate[i], 0, sizeof((*(rdb->read_sperate[i])))*(rdb->read_length[i]/4+1)); + } + ng->seq[i].len = rdb->read_length[i]; + } + + rdb->index_size = rdb->total_reads; + rdb->name_index[i] = tname; + rdb->total_name_length = tname; + rdb->name_index_size = rdb->total_reads+1; + REALLOC(rdb->name, tname); + for (i = rid_n0; i < rdb->total_reads; i++) {///only need to update names for new reads + des = Get_NAME((*rdb), i); + if(rmap[i] != ((uint64_t)-1)) { + src = Get_NAME((*rdb), rmap[i]); cname = Get_NAME_LENGTH((*rdb), (rmap[i])); + } else { + z = &(a[(i-ng->r_seq)]); assert(z->nid == i); + if(reset_scaf_node_uinfo_srt_t(z, uopt->min_ovlp, scaf_len, &nlen) == 2) { + cname = UL_INF.nid.a[z->ulid>>1].n;///ul name length + src = UL_INF.nid.a[z->ulid>>1].a; + } else { + src = scaf_id; cname = scaf_id_len; + } + // assert(nlen == (int64_t)cname); + } + memcpy(des, src, sizeof((*(des)))*cname); + } + + REALLOC(rdb->paf, rdb->total_reads); + memset(rdb->paf+rid_n0, 0, (rdb->total_reads-rid_n0)*sizeof((*rdb->paf))); + REALLOC(rdb->reverse_paf, rdb->total_reads); + memset(rdb->reverse_paf+rid_n0, 0, (rdb->total_reads-rid_n0)*sizeof((*rdb->reverse_paf))); + + ruI->len = rdb->total_reads; + REALLOC(ruI->index, ruI->len); + memset(ruI->index, -1, sizeof((*(ruI->index)))*(ruI->len)); + + reset_bub_label_t(uopt->b_mask_t, ng, 0, 0); + uopt->coverage_cut = (*cov); + uopt->reverse_sources = rdb->reverse_paf; + uopt->sources = rdb->paf; + destory_UC_Read(&g_read); + fprintf(stderr, "-[M::%s] rid_n0::%lu, rid_n::%lu\n", __func__, rid_n0, rid_n); +} + + +int64_t reload_uovl(all_ul_t *x, char* file_name) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(file_name)+100); + sprintf(gfa_name, "%s.%s.ul.ovlp.bin", file_name, "re"); + FILE* fp = fopen(gfa_name, "r"); free(gfa_name); + if (!fp) return 0; + uint64_t k; size_t kn; ul_vec_t *p = NULL; + + ///skip test ug + size_t tt, i; uint32_t t; ma_utg_t ua; + fread(&tt, sizeof(tt), 1, fp); + for (i = 0; i < tt; i++) { + fread(&t, sizeof(t), 1, fp); + fread(&t, sizeof(t), 1, fp); + fread(&(ua.start), sizeof(ua.start), 1, fp); + fread(&(ua.end), sizeof(ua.end), 1, fp); + fread(&(ua.n), sizeof(ua.n), 1, fp); + fseek(fp, sizeof(uint64_t)*ua.n, SEEK_CUR); + // fread(ua.a, sizeof(uint64_t), ua.n, fp); + } + + + + fseek(fp, sizeof(x->nid.n), SEEK_CUR); + for (k = 0; k < x->nid.n; k++) { + fseek(fp, sizeof(x->nid.a[k].n), SEEK_CUR); + fseek(fp, sizeof((*(x->nid.a[k].a)))*x->nid.a[k].n, SEEK_CUR); + } + + // free(x->ridx.idx.a); x->ridx.idx.a = NULL; + fread(&kn, sizeof(kn), 1, fp); + fseek(fp, sizeof((*(x->ridx.idx.a)))*kn, SEEK_CUR); + + // free(x->ridx.occ.a); x->ridx.occ.a = NULL; + fread(&kn, sizeof(kn), 1, fp); + fseek(fp, sizeof((*(x->ridx.occ.a)))*kn, SEEK_CUR); + + fread(&x->n, sizeof(x->n), 1, fp); assert(x->nid.n == x->n); + if(x->n > x->m) kv_resize(ul_vec_t, *x, x->n); + fprintf(stderr, "[M::%s] x->n::%u, x->nid.n::%u\n", __func__, (uint32_t)x->n, (uint32_t)x->nid.n); + for (k = 0; k < x->n; k++) { + p = &(x->a[k]); + fread(&p->dd, sizeof(p->dd), 1, fp); + fread(&p->rlen, sizeof(p->rlen), 1, fp); + + fread(&p->r_base.n, sizeof(p->r_base.n), 1, fp); + if(p->r_base.n > p->r_base.m) kv_resize(uint8_t, p->r_base, p->r_base.n); + fread(p->r_base.a, sizeof((*(p->r_base.a))), p->r_base.n, fp); + + fread(&p->bb.n, sizeof(p->bb.n), 1, fp); + if(p->bb.n > p->bb.m) kv_resize(uc_block_t, p->bb, p->bb.n); + fread(p->bb.a, sizeof((*(p->bb.a))), p->bb.n, fp); + + fread(&p->N_site.n, sizeof(p->N_site.n), 1, fp); + if(p->N_site.n > p->N_site.m) kv_resize(uint32_t, p->N_site, p->N_site.n); + fread(p->N_site.a, sizeof((*(p->N_site.a))), p->N_site.n, fp); + } + fclose(fp); + return 1; +} + +static void gen_scaffold_id(void *data, long i, int tid) // callback for kt_for() +{ + scaf_mul_t *ss = (scaf_mul_t *)data; + ma_ug_t *ug = ss->ug; + usc_t *z = &(ss->a[i]); + uint32_t v = z->raw_sid, w = z->raw_eid, sv, sw; + uint64_t *a, a_n, k; int64_t ql, mmql, max_ql; + uc_block_t *p, *n, *m0, *m1; + sv = (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)); + sw = (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)); + // if((((v>>1) == 15016) && ((w>>1) == 2778)) || (((v>>1) == 2778) && ((w>>1) == 15016))) { + // fprintf(stderr, "[M::%s::]\t%.*s(%c)(sv>>1::%u)(utg%.6ul(%c))\t%.*s(%c)(sw>>1::%u)(utg%.6ul(%c))\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, (sv>>1)), Get_NAME(R_INF, (sv>>1)), "+-"[sv&1], sv>>1, (v>>1)+1, "+-"[v&1], + // (int)Get_NAME_LENGTH(R_INF, (sw>>1)), Get_NAME(R_INF, (sw>>1)), "+-"[sw&1], sw>>1, (w>>1)+1, "+-"[w&1]); + // } + sv = Get_READ_LENGTH(R_INF, (sv>>1)); sw = Get_READ_LENGTH(R_INF, (sw>>1)); + max_ql = MIN(sv, sw); max_ql = -max_ql; + // if((((v>>1) == 235) && ((w>>1) == 153)) || (((v>>1) == 153) && ((w>>1) == 235))) { + // fprintf(stderr, "[M::%s] sv::%u, sw::%u, max_ql::%ld, v>>1::%u(%c), w>>1::%u(%c)\n", + // __func__, sv, sw, max_ql, v>>1, "+-"[v&1], w>>1, "+-"[w&1]); + // } + // if((((v>>1) == 235) && ((w>>1) == 153)) || (((v>>1) == 153) && ((w>>1) == 235))) { + // print_ul_alignment(ug, &UL_INF, 5625, "+++"); + // } + uint32_t uv, uw, rev = 0, id = (uint32_t)-1; + p = n = m0 = m1 = NULL; + a = UL_INF.ridx.occ.a + UL_INF.ridx.idx.a[v>>1]; + a_n = UL_INF.ridx.idx.a[(v>>1)+1] - UL_INF.ridx.idx.a[v>>1]; + for (k = 0, mmql = INT32_MAX; k < a_n; k++) { + p = &(UL_INF.a[a[k]>>32].bb.a[(uint32_t)(a[k])]); assert(p->hid == (v>>1)); + if(UL_INF.a[a[k]>>32].dd != 3) continue;///dd = 3 is saved + if(p->base || (!p->el) || (!p->pchain)) continue; + uv = (((uint32_t)(p->hid))<<1)|((uint32_t)(p->rev)); + + // if((uv == v) && (p->aidx != (uint32_t)-1)) { + if((uv == v) && (p->aidx == (uint32_t)-1) && (((uint32_t)(a[k]))+1 < UL_INF.a[a[k]>>32].bb.n)) { + n = &(UL_INF.a[a[k]>>32].bb.a[((uint32_t)(a[k]))+1]); + if(n->base || (!n->el) || (!n->pchain) || (n->pidx != (uint32_t)-1)) continue; + uw = (((uint32_t)(n->hid))<<1)|((uint32_t)(n->rev)); + if(uw == w) { + // if((((v>>1) == 15016) && ((w>>1) == 2778)) || (((v>>1) == 2778) && ((w>>1) == 15016))) { + // fprintf(stderr, "+[M::%s] ul_id::%lu, qs::%u, qe::%u\n", __func__, a[k]>>32, n->qs, n->qe); + // // print_ul_alignment(ug, &UL_INF, a[k]>>32, "+++"); + // } + ql = ((int64_t)n->qs) - ((int64_t)p->qe); + if(ql > max_ql && n->qe > p->qe && n->qs > p->qs) { + if(ql < mmql) { + mmql = ql; rev = 0; m0 = p; m1 = n; id = a[k]>>32; + } + } + } + } + + // if(((uv^1) == v) && (p->pidx != (uint32_t)-1)) { + if(((uv^1) == v) && (p->pidx == (uint32_t)-1) && (((uint32_t)(a[k])) > 0)) { + n = &(UL_INF.a[a[k]>>32].bb.a[((uint32_t)(a[k]))-1]); + if(n->base || (!n->el) || (!n->pchain) || (n->aidx != (uint32_t)-1)) continue; + uw = (((uint32_t)(n->hid))<<1)|((uint32_t)(n->rev)); uw ^= 1; + if(uw == w) { + // if((((v>>1) == 15016) && ((w>>1) == 2778)) || (((v>>1) == 2778) && ((w>>1) == 15016))) { + // fprintf(stderr, "-[M::%s] ul_id::%lu, qs::%u, qe::%u\n", __func__, a[k]>>32, n->qs, n->qe); + // // print_ul_alignment(ug, &UL_INF, a[k]>>32, "+++"); + // } + ql = ((int64_t)p->qs) - ((int64_t)n->qe); + if(ql > max_ql && n->qe < p->qe && n->qs < p->qs) { + if(ql < mmql) { + mmql = ql; rev = 1; m0 = n; m1 = p; id = a[k]>>32; + } + } + } + } + } + + if(m0 && m1 && id != ((uint32_t)-1)) { + z->ulid = (id<<1)|rev; + z->raw_sof = m0->qe; + z->raw_eof = m1->qs; + // if((((v>>1) == 15016) && ((w>>1) == 2778)) || (((v>>1) == 2778) && ((w>>1) == 15016))) { + // fprintf(stderr, "[M::%s] id::%u, v>>1::%u(%c), w>>1::%u(%c), raw_sof::%u, raw_eof::%u\n", + // __func__, id, v>>1, "+-"[v&1], w>>1, "+-"[w&1], z->raw_sof, z->raw_eof); + // } + } +} + +void reload_uu(all_ul_t *x, ma_ug_t *raw_g, char* file_name, const char *bin_file) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(asm_opt.output_file_name)+50); + sprintf(gfa_name, "%s.%s", asm_opt.output_file_name, bin_file); + clear_all_ul_t(x); + load_all_ul_t(x, gfa_name, &R_INF, raw_g); + // filter_ul_ug(raw_g);//no filter since we would like to use all alignments + gen_ul_vec_rid_t(x, NULL, raw_g); + free(gfa_name); +} + +void fill_scaffolds(usc_t *a, uint64_t a_n, ma_ug_t *raw_g, int64_t min_arc_len, const char *bin_file) +{ + scaf_mul_t ss; uint32_t k, occ = 0; + reload_uu(&UL_INF, raw_g, asm_opt.output_file_name, bin_file); + // reload_uovl(&UL_INF, asm_opt.output_file_name); + // filter_ul_ug(raw_g); + // free(UL_INF.ridx.idx.a); UL_INF.ridx.idx.n = UL_INF.ridx.idx.m = 0; + // free(UL_INF.ridx.occ.a); UL_INF.ridx.occ.n = UL_INF.ridx.occ.m = 0; + // gen_ul_vec_rid_t(&UL_INF, NULL, raw_g); + ss.a = a; ss.a_n = a_n; ss.ug = raw_g; + kt_for(asm_opt.thread_num, gen_scaffold_id, &ss, a_n); + for (k = 0; k < a_n; k++) { + if(a[k].ulid == ((uint32_t)-1)) continue; + // if(a[k].raw_eof + min_arc_len <= a[k].raw_sof) {///has an overlap longer than min_arc_len; + if(a[k].raw_eof <= a[k].raw_sof) { + continue;///no need ul, could directly use hifi + } + // if(a[k].raw_eof <= a[k].raw_sof) continue;///no need UL reads + // fprintf(stderr, "[M::%s] ulid::%u(%c), dd::%u\n", + // __func__, a[k].ulid>>1, "+-"[a[k].ulid&1], UL_INF.a[a[k].ulid>>1].dd); + UL_INF.a[a[k].ulid>>1].dd = 4;///load + occ++; + } + + // fprintf(stderr, "[M::%s] occ::%u\n", __func__, occ); + if(occ) load_scaf_base(&UL_INF, asm_opt.output_file_name, bin_file); +} + +void update_paf(ma_hit_t_alloc *src, ma_hit_t_alloc *r_src, uint64_t *rmap, uint64_t rid_n, uint64_t pre_gn, asg_t *ng); +void push_scaff_node(ma_hit_t_alloc *src, uint64_t v, uint64_t w, uint64_t ol, asg_t *ng); + +ma_ug_t *convert_usg_t(usg_t *ng, ma_ug_t *ref) +{ + ma_ug_t *ug = NULL; uint32_t k, nv, z; usg_arc_t *av; asg_arc_t *p; + ma_utg_t *des, *src; + CALLOC(ug, 1); ug->g = asg_init(); + ug->u.n = ug->u.m = ng->n; CALLOC(ug->u.a, ug->u.n); + for (k = 0; k < ng->n; k++) { + asg_seq_set(ug->g, k, ng->a[k].len, ng->a[k].del); + ug->g->seq[k].c = ref->g->seq[ng->a[k].mm].c; + + av = usg_arc_a(ng, (k<<1)); nv = usg_arc_n(ng, (k<<1)); + for (z = 0; z < nv; z++) { + if(av[z].del) continue; + p = asg_arc_pushp(ug->g); memset(p, 0, sizeof((*p))); + p->ul = av[z].ul; p->v = av[z].v; p->ol = av[z].ol; p->del = av[z].del; + } + + av = usg_arc_a(ng, (k<<1)+1); nv = usg_arc_n(ng, (k<<1)+1); + for (z = 0; z < nv; z++) { + if(av[z].del) continue; + p = asg_arc_pushp(ug->g); memset(p, 0, sizeof((*p))); + p->ul = av[z].ul; p->v = av[z].v; p->ol = av[z].ol; p->del = av[z].del; + } + + des = &(ug->u.a[k]); src = &(ref->u.a[ng->a[k].mm]); + (*des) = (*src); des->a = NULL; des->s = NULL; + if(src->a) { + MALLOC(des->a, des->m); + memcpy(des->a, src->a, src->n*sizeof((*(src->a)))); + } + + if(src->s) { + MALLOC(des->s, des->len); + memcpy(des->s, src->s, src->len*sizeof((*(src->s)))); + } + } + + asg_cleanup(ug->g); + return ug; +} + +int32_t gen_spec_rc_edge(asg_t *rg, ug_opt_t *uopt, uint32_t v, uint32_t w, asg_arc_t *t, ma_hit_t **te) +{ + uint32_t k, qn, tn; int32_t r; ma_hit_t_alloc *s = &(uopt->reverse_sources[v>>1]); asg_arc_t p; + for (k = 0; k < s->length; k++) { + qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); + if(tn != (w>>1)) continue; + r = ma_hit2arc(&(s->buffer[k]), rg->seq[qn].len, rg->seq[tn].len, uopt->max_hang, asm_opt.max_hang_rate, uopt->min_ovlp, &p); + if(r < 0) continue; + if((p.ul>>32) != v || p.v != w) continue; + *t = p; t->ou = 0; if(te) (*te) = &(s->buffer[k]); + return 1; + } + return -1; +} + +void push_direct_scaff_node(usc_t *psa, asg_t *ng, ug_opt_t *uopt, uint64_t vx, uint64_t wx) +{ + uint64_t uol, dif; int32_t r; asg_arc_t t, *p; ma_hit_t *rc0, *rc1; + uol = psa->raw_sof - psa->raw_eof; + assert(uol >= (uint64_t)uopt->min_ovlp); + r = gen_spec_rc_edge(ng, uopt, vx, wx, &t, &rc0); + if(r >= 0) { + if(uol > t.ol) dif = uol - t.ol; + else dif = t.ol - uol; + if((dif > (uol*0.05)) || (dif > (t.ol*0.05))) { + if(dif > 16) r = -1; + } + } + if(r >= 0) { + r = gen_spec_rc_edge(ng, uopt, wx^1, vx^1, &t, &rc1); + if(uol > t.ol) dif = uol - t.ol; + else dif = t.ol - uol; + if((dif > (uol*0.05)) || (dif > (t.ol*0.05))) { + if(dif > 16) r = -1; + } + } + + if(r >= 0) { + r = gen_spec_rc_edge(ng, uopt, vx, wx, &t, &rc0); assert(r >= 0); + p = asg_arc_pushp(ng); *p = t; + + r = gen_spec_rc_edge(ng, uopt, wx^1, vx^1, &t, &rc1); assert(r >= 0); + p = asg_arc_pushp(ng); *p = t; + + add_ma_hit_t_alloc(&(R_INF.paf[Get_qn((*rc0))]), rc0); + add_ma_hit_t_alloc(&(R_INF.paf[Get_qn((*rc1))]), rc1); + } else { + push_scaff_node(R_INF.paf, vx, wx, psa->raw_sof-psa->raw_eof, ng); + + r = gen_spec_edge(ng, uopt, vx, wx, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, wx^1, vx^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + } +} + +void print_debug_scaffold_nodes(ug_opt_t *uopt, usc_t *a, uint32_t a_n, asg_t *ng) +{ + uint32_t i, k, z, qn, tn, rl, hrl; usc_t *psa = NULL; ma_hit_t_alloc *s = NULL; + UC_Read r0, r1; init_UC_Read(&r0); init_UC_Read(&r1); + fprintf(stderr, "[M::%s] a_n::%u\n", __func__, a_n); + for (i = 0; i < a_n; i++) { + psa = &(a[i]); + s = &(uopt->sources[psa->nid]); + fprintf(stderr, "[M::%s::%u]%.*s(id::%u)\tlen::%lu\tulid::%u\trev::%u\tdel::%u\n", + __func__, i, (int32_t)Get_NAME_LENGTH(R_INF, psa->nid), + Get_NAME(R_INF, psa->nid), psa->nid, Get_READ_LENGTH(R_INF, psa->nid), psa->ulid>>1, psa->ulid&1, + ng->seq[psa->nid].del); + + recover_UC_Read(&r0, &R_INF, psa->nid); + fprintf(stderr, "%.*s\n", (int32_t)Get_READ_LENGTH(R_INF, psa->nid), r0.seq); + + for (k = 0; k < s->length; k++) { + qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); assert(qn == psa->nid); + fprintf(stderr, "q::[%u, %u)\t%c\tt::[%u, %u)\t%.*s(id::%u)\tlen::%lu\n", + Get_qs(s->buffer[k]), Get_qe(s->buffer[k]), "+-"[s->buffer[k].rev], + Get_ts(s->buffer[k]), Get_te(s->buffer[k]), + (int32_t)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), tn, Get_READ_LENGTH(R_INF, tn)); + if(psa->raw_eof >= psa->raw_sof) { + resize_UC_Read(&r0, Get_qe(s->buffer[k])-Get_qs(s->buffer[k])); + recover_UC_Read_sub_region(r0.seq, Get_qs(s->buffer[k]), Get_qe(s->buffer[k])-Get_qs(s->buffer[k]), 0, &R_INF, qn); + + resize_UC_Read(&r1, Get_te(s->buffer[k])-Get_ts(s->buffer[k])); + recover_UC_Read_sub_region(r1.seq, Get_ts(s->buffer[k]), Get_te(s->buffer[k])-Get_ts(s->buffer[k]), 0, &R_INF, tn); + + assert(Get_te(s->buffer[k])-Get_ts(s->buffer[k]) == Get_qe(s->buffer[k])-Get_qs(s->buffer[k])); + rl = Get_te(s->buffer[k])-Get_ts(s->buffer[k]); + if(s->buffer[k].rev) { + char t; hrl = rl>>1; + for (z = 0; z < hrl; z++) { + t = r1.seq[rl-z-1]; + r1.seq[rl-z-1] = RC_CHAR(r1.seq[z]); + r1.seq[z] = RC_CHAR(t); + } + if(rl&1) r1.seq[z] = RC_CHAR(r1.seq[z]); + } + assert(memcmp(r0.seq, r1.seq, rl) == 0); + } + } + } + destory_UC_Read(&r0); destory_UC_Read(&r1); +} + +asg_t *renew_ng(usg_t *eg, ma_ug_t *rug, asg_t *sg, ug_opt_t *uopt, ma_sub_t **cov, R_to_U *ruI, uint64_t scaffold_len, const char *bin_file) +{ + init_aux_table(); + ma_utg_t *u; uint64_t i, v, w, m, h, z, raw_v, raw_w, nocc, nv, vx, wx; int32_t r; + asg_arc_t t, *p; usg_arc_t *av = NULL; usc_t *psa; ma_ug_t *ug1 = NULL; + asg_ext_t ext; memset(&ext, 0, sizeof(ext)); ext.ext = asg_init(); asg_t *ng = ext.ext; + usc_vec_t sa; memset(&sa, 0, sizeof(sa)); + ext.a_n = sg->n_seq; + ext.cnt.n = ext.cnt.m = ext.a_n; + CALLOC(ext.cnt.a, ext.cnt.n);///count + + ext.idx_a.n = ext.idx_a.m = sg->n_seq; + MALLOC(ext.idx_a.a, ext.idx_a.n); + memset(ext.idx_a.a, -1, sizeof(*(ext.idx_a.a))*ext.idx_a.n);//map + ug1 = convert_usg_t(eg, rug); + + // fprintf(stderr, "-0-[M::%s]\n", __func__); + // print_vw_edge(sg, 681356, 73351, __func__); + // prt_spec_edge(sg, R_INF.paf, R_INF.total_reads, 681356, 73351, uopt, "src"); + // // prt_spec_edge(sg, R_INF.reverse_paf, R_INF.total_reads, 681356, 73351, uopt, "rsrc"); + + for (i = 0; i < ug1->u.n; ++i) { + if(ug1->g->seq[i].del) continue; + u = &(ug1->u.a[i]); + for (m = 0; m < u->n; m++) { + v = u->a[m]>>32; + ext.cnt.a[v>>1]++; + if(ext.cnt.a[v>>1] == 1) { + h = v>>1; ext.idx_a.a[h] = v>>1; + } else { + h = ext.idx_a.n; + kv_push(uint64_t, ext.idx_a, (v>>1)); + } + + z = (h<<1)|(v&1); z <<= 32; z |= ((uint32_t)u->a[m]); + u->a[m] = z; + } + } + + for (i = 0; i < sg->n_seq; ++i) { + asg_seq_set(ng, i, sg->seq[i].len, ext.idx_a.a[i]==((uint64_t)-1)?1:0); + ng->seq[i].c = 0; + if(ext.idx_a.a[i]!=((uint64_t)-1)) assert(ext.idx_a.a[i] == i); + ext.idx_a.a[i] = i;///set for the deleted read + } + for (; i < ext.idx_a.n; i++) { + asg_seq_set(ng, i, sg->seq[ext.idx_a.a[i]].len, 0); + ng->seq[i].c = 0; assert(!(ng->seq[ext.idx_a.a[i]].del)); + } + ng->r_seq = ng->n_seq; + assert(ng->n_seq == ext.idx_a.n); + + + for (i = 0, nocc = ng->r_seq, sa.n = 0; i < eg->n; ++i) { + if(ug1->g->seq[i].del) continue; + ///there shouldn't any scaffolding within the nodes + v = i<<1; nv = usg_arc_n(eg, v); av = usg_arc_a(eg, v); + for (m = 0; m < nv; m++) { + if(av[m].del || eg->a[av[m].v>>1].del) continue; + w = av[m].v; + vx = (v&1?((ug1->u.a[v>>1].a[0]>>32)^1):(ug1->u.a[v>>1].a[ug1->u.a[v>>1].n-1]>>32)); + wx = (w&1?((ug1->u.a[w>>1].a[ug1->u.a[w>>1].n-1]>>32)^1):(ug1->u.a[w>>1].a[0]>>32)); + raw_v = (ext.idx_a.a[vx>>1]<<1)|(vx&1); + raw_w = (ext.idx_a.a[wx>>1]<<1)|(wx&1); + assert((raw_v>>1) < sg->n_seq); + assert((raw_w>>1) < sg->n_seq); + if(vx > wx) continue; + if((vx == wx) && (vx&1)) continue; + if(gen_spec_edge(sg, uopt, raw_v, raw_w, &t) < 0) { + asg_seq_set(ng, nocc, 0, 0);///this is a scaffold node + ng->seq[nocc].c = 0; + kv_push(uint64_t, ext.idx_a, ((uint64_t)-1)); + + kv_pushp(usc_t, sa, &psa); + psa->ulid = (uint32_t)-1; psa->nid = nocc; + psa->raw_sid = (eg->a[v>>1].mm<<1)|(v&1);///raw unitig id + psa->raw_eid = (eg->a[w>>1].mm<<1)|(w&1);///raw unitig id + psa->raw_sof = psa->raw_eof = (uint32_t)-1; + nocc++;///a scaffold node + } + } + + v = (i<<1)+1; nv = usg_arc_n(eg, v); av = usg_arc_a(eg, v); + for (m = 0; m < nv; m++) { + if(av[m].del || eg->a[av[m].v>>1].del) continue; + w = av[m].v; + vx = (v&1?((ug1->u.a[v>>1].a[0]>>32)^1):(ug1->u.a[v>>1].a[ug1->u.a[v>>1].n-1]>>32)); + wx = (w&1?((ug1->u.a[w>>1].a[ug1->u.a[w>>1].n-1]>>32)^1):(ug1->u.a[w>>1].a[0]>>32)); + raw_v = (ext.idx_a.a[vx>>1]<<1)|(vx&1); + raw_w = (ext.idx_a.a[wx>>1]<<1)|(wx&1); + assert((raw_v>>1) < sg->n_seq); + assert((raw_w>>1) < sg->n_seq); + if(vx > wx) continue; + if((vx == wx) && (vx&1)) continue; + if(gen_spec_edge(sg, uopt, raw_v, raw_w, &t) < 0) { + asg_seq_set(ng, nocc, 0, 0);///this is a scaffold node + ng->seq[nocc].c = 0; + kv_push(uint64_t, ext.idx_a, ((uint64_t)-1)); + + kv_pushp(usc_t, sa, &psa); + psa->ulid = (uint32_t)-1; psa->nid = nocc; + psa->raw_sid = (eg->a[v>>1].mm<<1)|(v&1);///raw unitig id + psa->raw_eid = (eg->a[w>>1].mm<<1)|(w&1);///raw unitig id + psa->raw_sof = psa->raw_eof = (uint32_t)-1; + nocc++;///a scaffold node + } + } + } + + assert(ng->n_seq == ext.idx_a.n); + CALLOC(ng->seq_vis, (ng->n_seq<<1)); + ///# scaffolding nodes + if(sa.n > 0) fill_scaffolds(sa.a, sa.n, rug, uopt->min_ovlp, bin_file); + realloc_rdb_adv(&(R_INF), &UL_INF, cov, ruI, ext.idx_a.a, ext.idx_a.n, scaffold_len, (char *)"scaf", ng, uopt, rug, sa.a); + update_paf(R_INF.paf, R_INF.reverse_paf, ext.idx_a.a, ext.idx_a.n, sg->n_seq, ng); + + for (i = 0, nocc = ng->r_seq; i < eg->n; ++i) { + if(ug1->g->seq[i].del) continue; + u = &(ug1->u.a[i]); + for (m = 1; m < u->n; m++) { + // fprintf(stderr, "[M::%s] i::%lu, m::%lu\n", __func__, i, m); + v = u->a[m-1]>>32; w = u->a[m]>>32; + r = gen_spec_edge(ng, uopt, v, w, &t); + ///there shouldn't any scaffolding within the nodes + assert(r >= 0); + p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, w^1, v^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + } + + v = i<<1; nv = usg_arc_n(eg, v); av = usg_arc_a(eg, v); + for (m = 0; m < nv; m++) { + if(av[m].del || eg->a[av[m].v>>1].del) continue; + w = av[m].v; + vx = (v&1?((ug1->u.a[v>>1].a[0]>>32)^1):(ug1->u.a[v>>1].a[ug1->u.a[v>>1].n-1]>>32)); + wx = (w&1?((ug1->u.a[w>>1].a[ug1->u.a[w>>1].n-1]>>32)^1):(ug1->u.a[w>>1].a[0]>>32)); + if(vx > wx) continue; + if((vx == wx) && (vx&1)) continue;///it is possible + + r = gen_spec_edge(ng, uopt, vx, wx, &t); + if(r >= 0) { + p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, wx^1, vx^1, &t); + // if(!(r >= 0)) { + // fprintf(stderr, "[M::%s]\tvx>>1::%lu(%c)\twx>>1::%lu(%c)\n", + // __func__, vx>>1, "+-"[vx&1], wx>>1, "+-"[wx&1]); + // fprintf(stderr, "[M::%s]\t%.*s(%c)->%.*s(%c)\n", + // __func__, (int)Get_NAME_LENGTH(R_INF, (vx>>1)), Get_NAME(R_INF, (vx>>1)), "+-"[vx&1], + // (int)Get_NAME_LENGTH(R_INF, (wx>>1)), Get_NAME(R_INF, (wx>>1)), "+-"[wx&1]); + // } + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + } else { + psa = &(sa.a[nocc-ng->r_seq]); z = nocc<<1; + assert(psa->nid == nocc); + assert(psa->raw_sid == ((eg->a[v>>1].mm<<1)|(v&1))); + assert(psa->raw_eid == ((eg->a[w>>1].mm<<1)|(w&1))); + if(ng->seq[nocc].del) {///direct link vx and wx + push_direct_scaff_node(psa, ng, uopt, vx, wx); + } else { + push_scaff_node(R_INF.paf, vx, z, uopt->min_ovlp, ng); + push_scaff_node(R_INF.paf, z, wx, uopt->min_ovlp, ng); + + r = gen_spec_edge(ng, uopt, vx, z, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, z^1, vx^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + + r = gen_spec_edge(ng, uopt, z, wx, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, wx^1, z^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + } + nocc++; + } + } + + v = (i<<1)+1; nv = usg_arc_n(eg, v); av = usg_arc_a(eg, v); + for (m = 0; m < nv; m++) { + if(av[m].del || eg->a[av[m].v>>1].del) continue; + w = av[m].v; + vx = (v&1?((ug1->u.a[v>>1].a[0]>>32)^1):(ug1->u.a[v>>1].a[ug1->u.a[v>>1].n-1]>>32)); + wx = (w&1?((ug1->u.a[w>>1].a[ug1->u.a[w>>1].n-1]>>32)^1):(ug1->u.a[w>>1].a[0]>>32)); + if(vx > wx) continue; + if((vx == wx) && (vx&1)) continue;///it is possible + + r = gen_spec_edge(ng, uopt, vx, wx, &t); + if(r >= 0) { + p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, wx^1, vx^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + } else { + psa = &(sa.a[nocc-ng->r_seq]); z = nocc<<1; + assert(psa->nid == nocc); + assert(psa->raw_sid == ((eg->a[v>>1].mm<<1)|(v&1))); + assert(psa->raw_eid == ((eg->a[w>>1].mm<<1)|(w&1))); + if(ng->seq[nocc].del) {///direct link vx and wx + push_direct_scaff_node(psa, ng, uopt, vx, wx); + } else { + push_scaff_node(R_INF.paf, vx, z, uopt->min_ovlp, ng); + push_scaff_node(R_INF.paf, z, wx, uopt->min_ovlp, ng); + + r = gen_spec_edge(ng, uopt, vx, z, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, z^1, vx^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + + r = gen_spec_edge(ng, uopt, z, wx, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, wx^1, z^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + } + nocc++; + } + } + } + + asg_cleanup(ng); ng->r_seq = ng->n_seq; + free(ext.cnt.a); free(ext.idx_a.a); free(sa.a); ma_ug_destroy(ug1); + + fprintf(stderr, "[M::%s] nocc::%lu, ng->n_seq::%u, sg->n_seq::%u\n", + __func__, nocc, (uint32_t)ng->n_seq, (uint32_t)sg->n_seq); + assert(nocc == ng->n_seq); + return ng; +} + +void u2g_hybrid_detan_iter(ul_resolve_t *uidx, usg_t *ng, uint32_t max_ext, uint32_t clean_round, asg64_v *in, asg64_v *ib) +{ + uint32_t n_vtx = ng->n<<1, ncut = 0, k; + uint8_t *ff; CALLOC(ff, n_vtx); + uint32_t *ng_occ; CALLOC(ng_occ, n_vtx); + uint64_t *i_idx; CALLOC(i_idx, n_vtx); + asg64_v b64, ub64; kv_init(b64); kv_init(ub64); + asg64_v tx = {0,0,0}, tb = {0,0,0}, *ob = NULL, *ub = NULL; + ob = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); ob->n = ub->n = 0; + // fprintf(stderr, "\n[M::%s::] asm_opt.is_low_het_ul::%u, max_ext::%u\n", + // __func__, asm_opt.is_low_het_ul, max_ext); + // prt_usg_t(uidx, ng, "ng0"); + for (k = 0; k < clean_round; k++) { + ncut += ug_ext_strict(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64); + // if(asm_opt.is_low_het_ul) break; + ncut += ug_ext_free(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64, 48, 1); + // prt_usg_t(uidx, ng, "ng_python"); + ncut += ug_ext_free(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64, 16, 1); + + ncut += ug_ext_free(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64, 0, 0); + ///renew bubble for ug_ext_strict + n_vtx = ng->n<<1; + REALLOC(ff, n_vtx); REALLOC(ng_occ, n_vtx); REALLOC(i_idx, n_vtx); + renew_usg_t_bub(uidx, ng, ng_occ, ff, 0); + } + // // ug_ext_strict(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64); + // ncut += ug_ext_free(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64, 50); + // prt_usg_t(uidx, ng, "ng.db"); + // ncut += ug_ext_free(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64, 10); + // ncut += ug_ext_strict(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64); + // prt_usg_t(uidx, ng, "ng.db"); + if(ncut) { + usg_cleanup(ng); + // if((max_ext>>1) > 0) usg_arc_cut_tips(ng, (max_ext>>1), 1, ub); + usg_arc_cut_tips(ng, max_ext, 1, ub); + + // if(ng->n > 139131) { + // fprintf(stderr, ">[M::%s::] ng->a[139131].del::%u\n", __func__, + // ng->a[139131].del); + // } + } + // prt_usg_t(uidx, ng, "ng2"); + // u2g_hybrid_aln(uidx, ng, ob, ub); + // if(ug_ext(uidx, ng, ub->a, ub->n, ob->a, max_ext, ff, ng_occ, i_idx, &b64, &ub64)) { + // // debug_sysm_usg_t(ng, __func__); + // usg_cleanup(ng); + // // debug_sysm_usg_t(ng, __func__); + // } + + // prt_usg_t(uidx, ng, "ng0"); + // if(ug_ext_free(ob, ub, uidx, ng, max_ext, &ff, &ng_occ, &i_idx, &b64, &ub64, 50)) { + // usg_cleanup(ng); + // } + // prt_usg_t(uidx, ng, "ng1"); + + if(!in) {free(tx.a);} if(!ib) {free(tb.a);} + free(ng_occ); free(i_idx); free(ff); kv_destroy(b64); kv_destroy(ub64); +} + + +/** + +void u2g_hybrid_detan(ul_resolve_t *uidx, usg_t *ng, uint32_t max_ext, asg64_v *in, asg64_v *ib) +{ + uint64_t k, i, x, m, *tmp, sn; asg64_v tx = {0,0,0}, tb = {0,0,0}, *ob = NULL, *ub = NULL; + ob = (in?(in):(&tx)); ub = (ib?(ib):(&tb)); ob->n = ub->n = 0; + + for (k = 0; k < uidx->str_b.n_thread; k++) { + uidx->str_b.buf[k].res_dump.n = uidx->str_b.buf[k].u.n = uidx->str_b.buf[k].o.n = 0; + } + kt_for(uidx->str_b.n_thread, worker_integer_realign_g, uidx, uidx->uovl.i_ug->u.n); + + for (k = ob->n = ub->n = m = 0; k < uidx->str_b.n_thread; k++) { + for (i = 0; i < uidx->str_b.buf[k].res_dump.n; i++) { + x = uidx->str_b.buf[k].res_dump.a[i]; + kv_push(uint64_t, *ob, x);//aln details + if(x&((uint64_t)0x8000000000000000)) { + x -= ((uint64_t)0x8000000000000000); x >>= 32; x <<= 32;//seq_id + x |= ob->n;//offset + kv_push(uint64_t, *ub, x);///idx:: seq_id|offset_in_ob + } else { + m++; + } + } + } + + radix_sort_srt64(ub->a, ub->a + ub->n); + kv_resize(uint64_t, *ub, ub->n+m); tmp = ub->a + ub->n; m = 0; + for (k = 0; k < ub->n; k++) { + sn = ((uint32_t)(ob->a[((uint32_t)ub->a[k])-1])); + memcpy(tmp + m, ob->a + ((uint32_t)ub->a[k]), sn*sizeof((*tmp))); + ub->a[k] = m; ub->a[k] <<= 32; ub->a[k] |= sn;//offset_in_ob|occ + m += sn; + } + assert(m <= ob->n); + memcpy(ob->a, tmp, m*sizeof((*tmp))); ob->n = m; + + debug_sysm_usg_t(ng, __func__); + // prt_usg_t(uidx, ng, "ng4"); + if(gen_unique_g_adv(uidx, ng, ub->a, ub->n, ob->a, max_ext)) { + // usg_arc_t *z = get_usg_arc(ng, 2, 576), *q = get_usg_arc(ng, 577, 3); + // fprintf(stderr, "xxxx0xxx[M::%s::] p->del::%u, q->del::%u\n", + // __func__, z?z->del:1, q?q->del:1); + ///debug + debug_sysm_usg_t(ng, __func__); + // z = get_usg_arc(ng, 2, 576); q = get_usg_arc(ng, 577, 3); + // fprintf(stderr, "xxxx1xxx[M::%s::] p->del::%u, q->del::%u\n", + // __func__, z?z->del:1, q?q->del:1); + // fprintf(stderr, "+[M::%s::] ng->n::%u\n", __func__, (uint32_t)ng->n); + usg_cleanup(ng); + ///debug + debug_sysm_usg_t(ng, __func__); + // fprintf(stderr, "-[M::%s::] ng->n::%u\n", __func__, (uint32_t)ng->n); + } + // prt_usg_t(uidx, ng, "ng_dbg"); + if(!in) free(tx.a); if(!ib) free(tb.a); +} +**/ + +ma_ug_t *gen_debug_hybrid_ug(ul_resolve_t *uidx, usg_t *ng) +{ + ma_ug_t *ug = NULL; uint32_t k, nv, z; usg_arc_t *av; asg_arc_t *p; + CALLOC(ug, 1); ug->g = asg_init(); + ug->u.n = ug->u.m = ng->n; CALLOC(ug->u.a, ug->u.n); + for (k = 0; k < ng->n; k++) { + asg_seq_set(ug->g, k, ng->a[k].len, ng->a[k].del); + ug->g->seq[k].c = 0; + + av = usg_arc_a(ng, (k<<1)); nv = usg_arc_n(ng, (k<<1)); + for (z = 0; z < nv; z++) { + if(av[z].del) continue; + p = asg_arc_pushp(ug->g); memset(p, 0, sizeof((*p))); + p->ul = av[z].ul; p->v = av[z].v; p->ol = av[z].ol; p->del = av[z].del; + } + + av = usg_arc_a(ng, (k<<1)+1); nv = usg_arc_n(ng, (k<<1)+1); + for (z = 0; z < nv; z++) { + if(av[z].del) continue; + p = asg_arc_pushp(ug->g); memset(p, 0, sizeof((*p))); + p->ul = av[z].ul; p->v = av[z].v; p->ol = av[z].ol; p->del = av[z].del; + } + + ug->u.a[k].len = ug->g->seq[k].len; + ug->u.a[k].n = ug->u.a[k].m = 1; CALLOC(ug->u.a[k].a, 1); + ug->u.a[k].a[0] = (((uint64_t)k)<<33)|((uint64_t)(ug->u.a[k].len)); + } + asg_cleanup(ug->g); + + + uint32_t i; ma_utg_t *u; kvec_asg_arc_t_warp e; kv_init(e.a); e.i = 0; + for (i = 0; i < ug->u.n; i++) { + ug->g->seq[i].c = PRIMARY_LABLE; + u = &(ug->u.a[i]); + if(u->m == 0) continue; + merge_hybrid_utg_content(u, uidx->l1_ug, uidx->sg, ng, &e); + ug->g->seq[i].len = u->len; + } + kv_destroy(e.a); + return ug; +} + + +void prt_usg_t(ul_resolve_t *uidx, usg_t *ng, const char *cmd) +{ + ma_ug_t *ug = gen_debug_hybrid_ug(uidx, ng); + print_debug_gfa(uidx->sg, ug, uidx->uopt->coverage_cut, cmd, + uidx->uopt->sources, uidx->uopt->ruIndex, uidx->uopt->max_hang, uidx->uopt->min_ovlp, 0, 0, 0); + ma_ug_destroy(ug); + // exit(1); +} + +inline uint32_t usg_arc_occ(usg_t *g, uint32_t v, uint32_t *res) +{ + uint32_t i, kv, nv = usg_arc_n(g, v);; + usg_arc_t *av = usg_arc_a(g, v); + for (i = kv = 0; i < nv; i++) { + if(av[i].del) continue; + if(res) res[kv] = av[i].v; + kv++; + } + return kv; +} + +inline uint32_t gen_usg_tig(usg_t *g, uint32_t sid, uint32_t *eid, int64_t *baseLen, buf_t* b) +{ + uint32_t v = sid, w, k, kv, nv, return_flag; + usg_arc_t *av; + (*baseLen) = 0; (*eid) = (uint32_t)-1; + while (1) { + kv = usg_arc_occ(g, v, NULL); + (*eid) = v; + if(b) kv_push(uint32_t, b->b, v); + ///means reach the end of a unitig + if(kv!=1) (*baseLen) += g->a[v>>1].len; + if(kv==0) { + return_flag = END_TIPS; + break; + } else if(kv>1) { + return_flag = MUL_OUTPUT; + break; + } + + ///kv must be 1 here + kv = usg_arc_occ(g, v, &w); + if(usg_arc_occ(g, w^1, NULL)!=1) { + (*baseLen) += g->a[v>>1].len; + return_flag = MUL_INPUT; + break; + } else { + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + ///here is just one undeleted edge + (*baseLen) += asg_arc_len(av[k]); + break; + } + } + + v = w; + if(v == sid) { + return_flag = LOOP; + break; + } + } + return return_flag; +} + +uint64_t dfs_usg_t_dis(usg_t *g, buf_t *b, uint32_t x, uint32_t *p_bub) +{ + uint64_t len = 0; usg_arc_t *av = NULL; int64_t baseLen, uLen; + uint32_t c_v, e_v, nv, convex, v, i, kv_0, kv_1, flag_0 = 0, flag_1 = 0, op; + + (*p_bub) = 0; + if(b->a[x>>1].s || g->a[x>>1].del) return 0; + b->S.n = 0; + kv_push(uint32_t, b->S, x); + + while (b->S.n > 0) { + b->S.n--; + c_v = b->S.a[b->S.n]; + if(b->a[c_v>>1].s) continue; + + b->b.n = 0; //uint32_t gen_usg_tig(usg_t *g, uint32_t sid, uint32_t *eid, int64_t *baseLen, buf_t* b) + op = gen_usg_tig(g, c_v, &convex, &baseLen, b); + uLen = baseLen; + for(i = 0; i < b->b.n; i++) b->a[b->b.a[i]>>1].s = 1; + if(op == LOOP) return 0; + + + e_v = convex^1; + b->b.n = 0; + op = gen_usg_tig(g, e_v, &convex, &baseLen, b); + uLen = MAX(uLen, baseLen); + + len += uLen; + + + v = c_v^1; + nv = usg_arc_n(g, v); av = usg_arc_a(g, v); + for (i = kv_0 = 0; i < nv; i++) { + if(av[i].del) continue; + kv_0++; + if(b->a[av[i].v>>1].s) continue; + kv_push(uint32_t, b->S, av[i].v); + } + + v = e_v^1; + nv = usg_arc_n(g, v); av = usg_arc_a(g, v); + for (i = kv_1 = 0; i < nv; i++) { + if(av[i].del) continue; + kv_1++; + if(b->a[av[i].v>>1].s) continue; + kv_push(uint32_t, b->S, av[i].v); + } + + if(kv_0 > 0 && kv_1 > 0) flag_0++; + if(kv_0 > 1) flag_1++; + if(kv_1 > 1) flag_1++; + } + + if(flag_0 > 0 && flag_1 > 1) (*p_bub) = 1; + return len; +} + +uint64_t usg_bub_dis(usg_t *g, buf_t *b) +{ + usg_arc_t *av = NULL; uint64_t cLen = 0, mLen = 0; + uint32_t n_vtx = g->n<<1, k, v, w, kv, nv, p_bub; + + for (v = 0; v < n_vtx; ++v) { + if(b->a[v>>1].s || g->a[v>>1].del) continue; + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (k = kv = 0; k < nv && kv <= 1; k++) { + if(av[k].del) continue; + w = av[k].v^1; kv++; + } + if(kv == 1) { + av = usg_arc_a(g, w); nv = usg_arc_n(g, w); + for (k = kv = 0; k < nv && kv <= 1; k++) { + if(av[k].del) continue; + w = av[k].v^1; kv++; + } + if(kv == 1) continue; + } + + cLen = dfs_usg_t_dis(g, b, v^1, &p_bub); + if(p_bub == 0) continue;///no bubble + if(cLen > mLen) mLen = cLen; + } + + for (k = 0; k < g->n; ++k) b->a[k].s = 0; + b->S.n = b->b.n = 0; + return mLen; +} + +uint64_t usg_bub_identify(usg_t *g, uint32_t v0, uint64_t max_dist, uint64_t max_occ, buf_t *b) +{ + uint32_t i, n_pending = 0, is_first = 1, n_tips, tip_end; + uint64_t n_pop = 0; uint32_t v, nv, d, x; usg_arc_t *av; + if (g->a[v0>>1].del) return 0; // already deleted + if(usg_arc_occ(g, v0, NULL) < 2) return 0; + ///S saves nodes with all incoming edges visited + b->S.n = b->T.n = b->b.n = b->e.n = 0; + ///for each node, b->a saves all related information + b->a[v0].c = b->a[v0].d = b->a[v0].m = b->a[v0].nc = b->a[v0].np = 0; + ///b->S is the nodes with all incoming edges visited + kv_push(uint32_t, b->S, v0); + n_tips = 0; tip_end = (uint32_t)-1; + + do { + ///v is a node that all incoming edges have been visited + ///d is the distance from v0 to v + v = kv_pop(b->S); d = b->a[v].d; + nv = usg_arc_n(g, v); av = usg_arc_a(g, v); + ///why we have this assert? + ///assert(nv > 0); + ///all out-edges of v + for (i = 0; i < nv; ++i) { // loop through v's neighbors + /** + p->ul: |____________31__________|__________1___________|______________32_____________| + qn direction of overlap length of this node (not overlap length) + (in the view of query) + p->v : |___________31___________|__________1___________| + tn reverse direction of overlap + (in the view of target) + p->ol: overlap length + **/ + ///if this edge has been deleted + if (av[i].del) continue; + + uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l + binfo_t *t = &b->a[w]; + ///that means there is a circle, directly terminate the whole bubble poping + ///if (w == v0) goto pop_reset; + if ((w>>1) == (v0>>1)) goto usg_clean_reset; + /****************************may have bugs********************************/ + ///important when poping at long untig graph + if(is_first) l = 0; + /****************************may have bugs********************************/ + + ///push the edge + ///high 32-bit of g->idx[v] is the start point of v's edges + //so here is the point of this specfic edge + // kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); + ///find a too far path? directly terminate the whole bubble poping + if (d + l > max_dist) break; // too far + if (b->b.n > max_occ) break; // too far + + ///if this node + if (t->s == 0) { // this vertex has never been visited + kv_push(uint32_t, b->b, w); // save it for revert + ///t->p is the parent node of + ///t->s = 1 means w has been visited + ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) + t->p = v, t->s = 1, t->d = d + l; + ///incoming edges of w + t->r = usg_arc_occ(g, w^1, NULL); + ++n_pending; + } else { // visited before + if (d + l < t->d) t->d = d + l; // update dist + } + ///assert(t->r > 0); + //if all incoming edges of w have visited + //push it to b->S + if (--(t->r) == 0) { + x = usg_arc_occ(g, w, NULL); + /****************************may have bugs for bubble********************************/ + if(x > 0) { + kv_push(uint32_t, b->S, w); + } + else { + ///at most one tip + if(n_tips != 0) goto usg_clean_reset; + n_tips++; tip_end = w; + } + /****************************may have bugs for bubble********************************/ + --n_pending; + } + } + is_first = 0; + //if found a tip + /****************************may have bugs for bubble********************************/ + if(n_tips == 1) { + if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) { + kv_push(uint32_t, b->S, tip_end); + break; + } else { + goto usg_clean_reset; + } + } + /****************************may have bugs for bubble********************************/ + ///if i < nv, that means (d + l > max_dist) + if (i < nv || b->S.n == 0) goto usg_clean_reset; + } while (b->S.n > 1 || n_pending); + + n_pop = 1; + usg_clean_reset: + + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + binfo_t *t = &b->a[b->b.a[i]]; + t->s = t->c = t->d = t->m = t->nc = t->np = 0; + } + return n_pop; +} + +void extracr_clean_arc(usg_t *g, uint32_t v, asg64_v *b, asg64_v *ub) +{ + usg_arc_t *av; uint32_t i, kv, nv; uint64_t x, kocc[2]; + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + if (nv < 2) return; + for (i = kv = kocc[0] = kocc[1] = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + if((av[i].ou>>1) > 0) { ///if av[i].ou == 1, ignore it + if(kocc[1] < (av[i].ou>>1)) kocc[1] = (av[i].ou>>1); + } else if(av[i].ou == 0) { + kocc[0]++; + } + } + if(kv < 2 || kocc[0] == 0 || kocc[1] == 0) return; + for (i = 0; i < nv; ++i) { + if(av[i].del || av[i].ou) continue; + // if(max_drop_len && av[i].ol >= (*max_drop_len)) continue; + x = av[i].ol; x <<= 32; + kv_push(uint64_t, *b, ((x)|((uint64_t)(ub->n)))); + kv_push(uint64_t, *ub, ((((uint64_t)(v))<<32)|((uint64_t)(i)))); + } +} + + +int usg_tip_del(usg_t *g, uint32_t v, asg64_v *z_a, asg64_v *z_b) +{ + uint64_t a_n = z_a->n, b_n = z_b->n, kv, nv, i; + int32_t n_ext = 0; usg_arc_t *av; + + av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); + for (i = kv = 0; i < nv && kv <= 1; i++) { + if (av[i].del || g->a[av[i].v>>1].del) continue; + kv++; + } + if(kv > 1) return 0; + n_ext += g->a[v>>1].occ; g->a[v>>1].del = 1; kv_push(uint64_t, *z_b, v>>1); + + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (i = 0; i < nv; i++) { + if (av[i].del || g->a[av[i].v>>1].del) continue; + kv_push(uint64_t, *z_a, av[i].v); + } + + while (z_a->n > a_n) { + v = z_a->a[--z_a->n]; if(g->a[v>>1].del) continue; + + av = usg_arc_a(g, v^1); nv = usg_arc_n(g, v^1); + for (i = kv = 0; i < nv && kv < 1; i++) { + if (av[i].del || g->a[av[i].v>>1].del) continue; + kv++; + } + if(kv > 0) continue; + n_ext += g->a[v>>1].occ; g->a[v>>1].del = 1; kv_push(uint64_t, *z_b, v>>1); + + av = usg_arc_a(g, v); nv = usg_arc_n(g, v); + for (i = 0; i < nv; i++) { + if (av[i].del || g->a[av[i].v>>1].del) continue; + kv_push(uint64_t, *z_a, av[i].v); + } + } + + for (i = b_n; i < z_b->n; i++) usg_seq_del(g, z_b->a[i]); + z_b->n = b_n; z_a->n = a_n; + return n_ext; +} + +uint64_t usg_bub_clean0(usg_t *g, uint32_t *a, uint32_t a_n, uint32_t sid, uint32_t eid, +uint32_t is_topo, int32_t max_ext, float len_rat, uint8_t *f, asg64_v *in_0, asg64_v *in_1) +{ + uint32_t i, k, v, w, nv, nw, kv, kw, ol_max, ou_max, to_del, cnt = 0, tip_v, mm_ol; + asg64_v tx = {0,0,0}, tz = {0,0,0}, *b = NULL, *ub = NULL; int32_t n_tip, r_tip; + uint64_t kocc[2]; usg_arc_t *av = NULL, *aw = NULL, *ve = NULL, *we = NULL; + b = ((in_0)?(in_0):(&tx)); ub = ((in_1)?(in_1):(&tz)); + + for (k = b->n = ub->n = 0; k < a_n; ++k) { + extracr_clean_arc(g, a[k], b, ub); + extracr_clean_arc(g, a[k]^1, b, ub); + } + extracr_clean_arc(g, sid, b, ub); + extracr_clean_arc(g, eid, b, ub); + + + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + v = ub->a[(uint32_t)b->a[k]]>>32; + ve = &(usg_arc_a(g, v)[(uint32_t)(ub->a[(uint32_t)b->a[k]])]); + w = ve->v^1; + if(ve->del || g->a[v>>1].del || g->a[w>>1].del || ve->ou) continue; + nv = usg_arc_n(g, v); nw = usg_arc_n(g, w); + av = usg_arc_a(g, v); aw = usg_arc_a(g, w); + if(nv<=1 && nw <= 1) continue; + + // if(is_trio) { + // if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup + // trioF = get_tip_trio_infor(g, v^1); + // ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); + // } + for (i = 0; i < nw; ++i) { + if (aw[i].v == (v^1)) { + we = &(aw[i]); + break; + } + } + mm_ol = MIN(ve->ol, we->ol); kocc[0] = kocc[1] = 0; + + for (i = kv = ol_max = ou_max = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + if(av[i].ou != 1) kocc[!!(av[i].ou)]++; ///if av[i].ou == 1, ignore it + // if(is_trio && get_tip_trio_infor(g, av[i].v) == ntrioF) continue; + if(ol_max < av[i].ol) ol_max = av[i].ol; + } + if (kv < 1 || kocc[0] < 1 || kocc[1] < 1) continue; + if (kv >= 2) { + if (mm_ol > ol_max*len_rat) continue; + } + + + for (i = kw = ol_max = ou_max = 0; i < nw; ++i) { + if(aw[i].del) continue; + kw++; + // if(is_trio && get_tip_trio_infor(g, aw[i].v) == ntrioF) continue; + if(ol_max < aw[i].ol) ol_max = aw[i].ol; + } + if (kw < 1) continue; + if (kw >= 2) { + if (mm_ol > ol_max*len_rat) continue; + } + + if (kv <= 1 && kw <= 1) continue; + + to_del = 1; n_tip = 0; tip_v = (uint32_t)-1; + if(is_topo) { + to_del = 0; + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + n_tip = usg_naive_topocut_aux(g, w^1, max_ext, f, b, ub); + if (n_tip < max_ext) {to_del = 1;} tip_v = w^1; + } else if (kv == 1) { + n_tip = usg_naive_topocut_aux(g, v^1, max_ext, f, b, ub); + if (n_tip < max_ext) {to_del = 1;} tip_v = v^1; + } + } + + if (to_del) { + // ve->del = we->del = 1; + if(n_tip > 0 && tip_v != ((uint32_t)-1)) { + r_tip = usg_tip_del(g, tip_v, b, ub); + assert(n_tip == r_tip); + } + cnt++; + } + } + + if(in_0) {free(tx.a);} if(in_1) {free(tz.a);} + return cnt; +} + +uint64_t usg_bub_clean(usg_t *g, buf_t *b, asg64_v *in_0, asg64_v *in_1, int32_t max_ext, float len_rat, +uint32_t is_topo, uint8_t *bs, uint8_t *f) +{ + uint32_t v, m, n_vtx = g->n<<1, n_arc, nv, i, n_cut = 0; + uint64_t max_dist; usg_arc_t *av = NULL; + // for (i = 0; i < g->n; ++i) b->a[i].s = 0; + max_dist = usg_bub_dis(g, b); + memset(bs, 0, sizeof((*bs))*n_vtx); + + if(max_dist > 0) { + for (v = 0; v < n_vtx; ++v) { + if(bs[v]) continue; + nv = usg_arc_n(g, v); av = usg_arc_a(g, v); + if (nv < 2 || g->a[v>>1].del) continue; + for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs + if (!av[i].del) ++n_arc; + if (n_arc < 2) continue; + if(usg_bub_identify(g, v, max_dist, (uint64_t)-1, b)) { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (i = 0; i < b->b.n; i++) { + if(b->b.a[i]==v || b->b.a[i]==b->S.a[0]) continue; + bs[b->b.a[i]] = bs[b->b.a[i]^1] = 1; + } + bs[v] = 2; bs[b->S.a[0]^1] = 3; + } + } + + //traverse all node with two directions + for (v = 0; v < n_vtx; ++v) { + if(bs[v] != 2) continue; + nv = usg_arc_n(g, v); av = usg_arc_a(g, v); + for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs + if (!av[i].del) ++n_arc; + if (n_arc < 2) continue; + if(usg_bub_identify(g, v, max_dist, (uint64_t)-1, b)) { + for (i = m = 0; i < b->b.n; i++) { + if(b->b.a[i]==v || b->b.a[i]==b->S.a[0]) continue; + bs[b->b.a[i]] = bs[b->b.a[i]^1] = 1; + b->b.a[m++] = b->b.a[i]; + } + b->b.n = m; bs[v] = 2; bs[b->S.a[0]^1] = 3; + n_cut += usg_bub_clean0(g, b->b.a, b->b.n, v, b->S.a[0]^1, is_topo, max_ext, len_rat, f, in_0, in_1); + } + } + } + if (n_cut > 0) usg_cleanup(g); + return n_cut; +} + +void u2g_hybrid_clean(ul_resolve_t *uidx, ulg_opt_t *ulopt, usg_t *ng, asg64_v *b, asg64_v *ub) +{ + int64_t i, ss, mm_tip = ulopt->max_tip_hifi;///ulopt->max_tip; + double step = (ulopt->clean_round==1?ulopt->max_ovlp_drop_ratio: + ((ulopt->max_ovlp_drop_ratio-ulopt->min_ovlp_drop_ratio)/(ulopt->clean_round-1))); + double drop = ulopt->min_ovlp_drop_ratio; ///CALLOC(iug->g->seq_vis, iug->g->n_seq*2); + buf_t bb; memset(&bb, 0, sizeof(buf_t)); CALLOC(bb.a, ng->n<<1); + uint8_t *bs, *f; CALLOC(bs, ng->n<<1); CALLOC(f, ng->n); + // fprintf(stderr, "\n[M::%s::] Starting hybrid clean, mm_tip::%ld\n", __func__, mm_tip); + // prt_usg_t(uidx, ng, "ng_h0"); + usg_arc_cut_tips(ng, mm_tip, 0, b);///p_telo + // prt_usg_t(uidx, ng, "ng_h1"); + // char sb[1000]; + + for (ss = 1; ss <= 1/**6**/; ss++) { + mm_tip = ulopt->max_tip_hifi*ss; + // fprintf(stderr, "\n[M::%s::] ss::%ld, mm_tip::%ld, ulopt->clean_round::%ld\n", + // __func__, ss, mm_tip, ulopt->clean_round); + for (i = 0, drop = ulopt->min_ovlp_drop_ratio; i < ulopt->clean_round; i++, drop += step) { + if(drop > ulopt->max_ovlp_drop_ratio) drop = ulopt->max_ovlp_drop_ratio; + // fprintf(stderr, "-0-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); + // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_a", ss, i, drop); + // prt_usg_t(uidx, ng, sb); + // usg_arc_cut_length(ng, b, ub, mm_tip>>1, drop, ulopt->is_trio, 1, NULL); + usg_bub_clean(ng, &bb, b, ub, mm_tip>>1, drop, 1, bs, f); + usg_arc_cut_srt_length(ng, b, ub, mm_tip>>1, drop, ulopt->is_trio, 1, NULL, bs); + // fprintf(stderr, "-1-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); + // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_b", ss, i, drop); + // prt_usg_t(uidx, ng, sb); + usg_arc_cut_tips(ng, mm_tip, 0, b); + // fprintf(stderr, "-2-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); + // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_c", ss, i, drop); + // prt_usg_t(uidx, ng, sb); + // usg_arc_cut_length(ng, b, ub, mm_tip, drop, ulopt->is_trio, 1, NULL); + usg_bub_clean(ng, &bb, b, ub, mm_tip, drop, 1, bs, f); + usg_arc_cut_srt_length(ng, b, ub, mm_tip, drop, ulopt->is_trio, 1, NULL, bs); + // fprintf(stderr, "-3-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); + // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_d", ss, i, drop); + // prt_usg_t(uidx, ng, sb); + usg_arc_cut_tips(ng, mm_tip, 1, b); + // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_e", ss, i, drop); + // prt_usg_t(uidx, ng, sb); + // fprintf(stderr, "-4-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); + } + + drop = 1; + // fprintf(stderr, "-0-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); + // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_a", ss, i, drop); + // prt_usg_t(uidx, ng, sb); + // usg_arc_cut_length(ng, b, ub, mm_tip>>1, drop, ulopt->is_trio, 1, NULL); + usg_bub_clean(ng, &bb, b, ub, mm_tip>>1, drop, 1, bs, f); + // fprintf(stderr, "-1bub-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); + // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_b::bub", ss, i, drop); + // prt_usg_t(uidx, ng, sb); + usg_arc_cut_srt_length(ng, b, ub, mm_tip>>1, drop, ulopt->is_trio, 1, NULL, bs); + // fprintf(stderr, "-1-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); + // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_b", ss, i, drop); + // prt_usg_t(uidx, ng, sb); + usg_arc_cut_tips(ng, mm_tip, 0, b); + // fprintf(stderr, "-2-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); + // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_c", ss, i, drop); + // prt_usg_t(uidx, ng, sb); + // usg_arc_cut_length(ng, b, ub, mm_tip, drop, ulopt->is_trio, 1, NULL); + usg_bub_clean(ng, &bb, b, ub, mm_tip, drop, 1, bs, f); + usg_arc_cut_srt_length(ng, b, ub, mm_tip, drop, ulopt->is_trio, 1, NULL, bs); + // fprintf(stderr, "-3-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); + // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_d", ss, i, drop); + // prt_usg_t(uidx, ng, sb); + usg_arc_cut_tips(ng, mm_tip, 1, b); + // sprintf(sb, "ng_ss::%ld_i::%ld_drop::%f_e", ss, i, drop); + // prt_usg_t(uidx, ng, sb); + // fprintf(stderr, "-4-[M::%s::] i::%ld, drop::%f\n", __func__, i, drop); + } + free(bb.a); free(bb.S.a); free(bb.T.a); free(bb.b.a); free(bb.e.a); free(bs); free(f); + // prt_usg_t(uidx, ng, "ng_h2"); + ///debug + debug_sysm_usg_t(ng, __func__); + + /******for debug******/ + // prt_usg_t(uidx, ng, "ng_dbg"); + /******for debug******/ + + // u2g_hybrid_extend(ng, NULL, b, ub); + // u2g_hybrid_detan(uidx, ng, mm_tip, b, ub); + u2g_hybrid_detan_iter(uidx, ng, mm_tip, ulopt->clean_round, b, ub); +} + +void merge_hybrid_utg_content(ma_utg_t* cc, ma_ug_t* raw, asg_t* rg, usg_t *ng, kvec_asg_arc_t_warp* edge) +{ + if(cc->m == 0) return; + uint32_t i, j, index, uId, ori, uv, uw, bv, bw; + uint64_t tot, z; asg_arc_t *p; + ma_utg_t* q = NULL; + for (i = index = 0; i < cc->n; i++) { + z = (ng->a[cc->a[i]>>33].mm<<1)|((cc->a[i]>>32)&1); z <<= 32; z += ((uint32_t)cc->a[i]); + index += ng->a[cc->a[i]>>33].occ; cc->a[i] = z; + } + + uint64_t *buffer, *aim = NULL; MALLOC(buffer, index); + for (i = index = edge->a.n = 0; i < cc->n; i++) { + uId = cc->a[i]>>33; ori = cc->a[i]>>32&1; + q = &(raw->u.a[uId]); aim = buffer + index; + if(ori == 1) { + for (j = 0; j < q->n; j++) { + aim[q->n - j - 1] = (q->a[j])^(uint64_t)(0x100000000); + } + } else { + for (j = 0; j < q->n; j++) { + aim[j] = q->a[j]; + } + } + index += q->n; + if(i > 0) { + uv = cc->a[i-1]>>32; uw = cc->a[i]>>32; + p = get_specfic_edge(raw->g, uv, uw); + if(!p) { + uv = cc->a[i-1]>>32; uw = cc->a[i]>>32; + bv = raw->u.a[uv>>1].a[((uv&1)?(0):(raw->u.a[uv>>1].n-1))]>>32; if(uv&1) bv ^= 1; + bw = raw->u.a[uw>>1].a[((uw&1)?(raw->u.a[uw>>1].n-1):(0))]>>32; if(uw&1) bw ^= 1; + kv_pushp(asg_arc_t, edge->a, &p); memset(p, 0, sizeof((*p))); + p->ul = bv; p->ul <<= 32; p->ul += rg->seq[bv>>1].len; p->v = bw; + + uv = (cc->a[i]>>32)^1; uw = (cc->a[i-1]>>32)^1; + bv = raw->u.a[uv>>1].a[((uv&1)?(0):(raw->u.a[uv>>1].n-1))]>>32; if(uv&1) bv ^= 1; + bw = raw->u.a[uw>>1].a[((uw&1)?(raw->u.a[uw>>1].n-1):(0))]>>32; if(uw&1) bw ^= 1; + kv_pushp(asg_arc_t, edge->a, &p); memset(p, 0, sizeof((*p))); + p->ul = bv; p->ul <<= 32; p->ul += rg->seq[bv>>1].len; p->v = bw; + } + } + } + + if(index == 0) return; + + fill_unitig(buffer, index, rg, edge, (cc->n == 1 && raw->u.a[cc->a[0]>>33].circ), &tot); + + ///important. must be here + if(cc->n == 1 && raw->u.a[cc->a[0]>>33].circ) cc->circ = 1; + + free(cc->a); + cc->a = buffer; cc->n = cc->m = index; cc->len = tot; + if(!cc->circ) { + cc->start = cc->a[0]>>32; + cc->end = (cc->a[cc->n-1]>>32)^1; + } + else { + cc->start = cc->end = UINT32_MAX; + } +} + +ma_ug_t *gen_hybrid_ug(ul_resolve_t *uidx, usg_t *ng) +{ + // fprintf(stderr, "[M::%s::] ng->n::%u\n", __func__, (uint32_t)ng->n); + ma_ug_t *ug = ma_ug_hybrid_gen(ng); + // fprintf(stderr, "[M::%s::] ug->g->n_seq::%u\n", __func__, (uint32_t)ug->g->n_seq); + uint32_t i; ma_utg_t *u; kvec_asg_arc_t_warp e; kv_init(e.a); e.i = 0; + for (i = 0; i < ug->u.n; i++) { + ug->g->seq[i].c = PRIMARY_LABLE; + u = &(ug->u.a[i]); + if(u->m == 0) continue; + // fprintf(stderr, "+[M::%s::] i::%u\n", __func__, i); + merge_hybrid_utg_content(u, uidx->l1_ug, uidx->sg, ng, &e); + // fprintf(stderr, "-[M::%s::] i::%u\n", __func__, i); + ug->g->seq[i].len = u->len; + } + kv_destroy(e.a); + return ug; +} + +uint32_t gen_utg_telo(ma_utg_t *u, telo_end_t *te) +{ + uint32_t i; + for (i = 0; i < u->n; ++i) { + if(te->hh[u->a[i]>>33]) return 1; + } + return 0; +} + +void renew_ul2_utg(ul_resolve_t *uidx); + +void u2g_threading(ul_resolve_t *uidx, ulg_opt_t *ulopt, uint64_t cov_cutoff, uint64_t is_bridg, asg64_v *b, asg64_v *ub) +{ + renew_ul2_utg(uidx); + ul2ul_idx_t *idx = &(uidx->uovl); ma_ug_t *iug = idx->i_ug; ma_ug_t *raw = uidx->l1_ug; + uint64_t k, z, i, t_s, t_e; uinfo_srt_warp_t *seq; + usg_t *ng; CALLOC(ng, 1); usg_seq_t *s; usg_arc_warp *sv; usg_arc_t *p; + asg_arc_t *av; uint32_t nv, v, w, vx, wx; int64_t tt, tl, tm; + + ng->mp.n = ng->mp.m = raw->g->n_seq; MALLOC(ng->mp.a, ng->mp.n); + for (k = 0; k < raw->g->n_seq; k++) { + s = push_usg_t_node(ng, k); + s->mm = k; s->arc[0].n = s->arc[1].n = 0; s->occ = raw->u.a[k].n; + s->arc_mm[0].n = s->arc_mm[1].n; + s->del = raw->g->seq[k].del; s->len = raw->g->seq[k].len; + s->telo = 0; + if(uidx->uopt->te) { + s->telo = gen_utg_telo(&(raw->u.a[k]), uidx->uopt->te); + } + + av = asg_arc_a(raw->g, (k<<1)); nv = asg_arc_n(raw->g, (k<<1)); sv = &(s->arc[0]); + for (z = 0; z < nv; z++) { + if(av[z].del) continue; + kv_pushp(usg_arc_t, *sv, &p); + p->del = 0; p->ou = 0; p->v = av[z].v; p->ol = av[z].ol; p->ul = av[z].ul; p->idx = 0; + } + + av = asg_arc_a(raw->g, ((k<<1)+1)); nv = asg_arc_n(raw->g, ((k<<1)+1)); sv = &(s->arc[1]); + for (z = 0; z < nv; z++) { + if(av[z].del) continue; + kv_pushp(usg_arc_t, *sv, &p); + p->del = 0; p->ou = 0; p->v = av[z].v; p->ol = av[z].ol; p->ul = av[z].ul; p->idx = 0; + } + ///map: ng id -> raw id + ng->mp.a[k].n = ng->mp.a[k].m = 1; MALLOC(ng->mp.a[k].a, 1); ng->mp.a[k].a[0] = k; + } + + for (k = b->n = 0; k < iug->u.n; k++) { + seq = &(idx->cc.iug_a[k]); + if(seq->n <= 1) continue; + + uidx->uovl.iug_seq = seq; uidx->uovl.iug_cov_thre = cov_cutoff; + for (z = 0; z < uidx->str_b.n_thread; z++) { + uidx->str_b.buf[z].res_dump.n = 0; + } + kt_for(uidx->str_b.n_thread, worker_update_ul_arc_drop, uidx, seq->n-1);///seq->n > 1 + for (z = ub->n = 0; z < uidx->str_b.n_thread; z++) { + for (i = 0; i < uidx->str_b.buf[z].res_dump.n; i++) { + kv_push(uint64_t, *ub, uidx->str_b.buf[z].res_dump.a[i]); + } + } + + for (z = 0; z < ub->n; z++) {///all unreliable arcs + i = ub->a[z]; tm = 1; p = get_usg_arc(ng, seq->a[i].v, seq->a[i+1].v); + if(p) { + if(p->ou < (uint64_t)tm) p->ou = tm;///since the initial ou is 0, p->ou = 1 + pushp_usg_arc_mm(ng, seq->a[i].v, seq->a[i+1].v, k, i); + + p = get_usg_arc(ng, seq->a[i+1].v^1, seq->a[i].v^1); + if(p->ou < (uint64_t)tm) p->ou = tm;///since the initial ou is 0, p->ou = 1 + pushp_usg_arc_mm(ng, seq->a[i+1].v^1, seq->a[i].v^1, k, i); + } + ///give up unreliable arcs if they are not adjacent + } + + radix_sort_srt64(ub->a, ub->a + ub->n); + if(ub->n == 0 || ub->a[ub->n-1] < seq->n-1) kv_push(uint64_t, *ub, seq->n-1); + for (z = t_s = t_e = 0; z < ub->n; z++) { + t_e = ub->a[z]; + if(t_s < t_e) { + for (i = t_s, tt = seq->a[t_e].n; i < t_e; i++) { + tt += seq->a[i].n;///how many HiFi reads are covered + } + for (i = t_s, tl = 0; i < t_e; i++) { + tl += seq->a[i].n; + tm = tt - tl; if(tm > tl) tm = tl; assert(tm > 0); tm <<= 1; tm += 1; + p = get_usg_arc(ng, seq->a[i].v, seq->a[i+1].v); + if(p) { + if(p->ou < (uint64_t)tm) p->ou = tm; + p = get_usg_arc(ng, seq->a[i+1].v^1, seq->a[i].v^1); + if(p->ou < (uint64_t)tm) p->ou = tm; + } else if(is_bridg) { + v = seq->a[i].v; w = seq->a[i+1].v; p = NULL; + vx = (v&1?((raw->u.a[v>>1].a[0]>>32)^1):(raw->u.a[v>>1].a[raw->u.a[v>>1].n-1]>>32)); + wx = (w&1?((raw->u.a[w>>1].a[raw->u.a[w>>1].n-1]>>32)^1):(raw->u.a[w>>1].a[0]>>32)); + ///(v>>1) != (w>>1) or v == w, need to handle (v>>1) == (w>>1) && (v&1) != (w&1) later + if(((v^w) != 1) && (uidx->sg->seq[vx>>1].len > uidx->uopt->min_ovlp) && + (uidx->sg->seq[wx>>1].len > uidx->uopt->min_ovlp)) { + kv_pushp(usg_arc_t, (ng->a[v>>1].arc[v&1]), &p); + p->del = 0; p->ou = tm; p->v = w; p->ol = 0; p->idx = 0; + p->ul = (((uint64_t)v)<<32)|(raw->g->seq[v>>1].len); + + v = seq->a[i+1].v^1; w = seq->a[i].v^1; + kv_pushp(usg_arc_t, (ng->a[v>>1].arc[v&1]), &p); + p->del = 0; p->ou = tm; p->v = w; p->ol = 0; p->idx = 0; + p->ul = (((uint64_t)v)<<32)|(raw->g->seq[v>>1].len); + } + } + if(p) { + pushp_usg_arc_mm(ng, seq->a[i].v, seq->a[i+1].v, k, i); + pushp_usg_arc_mm(ng, seq->a[i+1].v^1, seq->a[i].v^1, k, i); + } + } + } + t_s = ub->a[z] + 1; + } + } + + // for (v = 0; v < (ng->n<<1); v++) { + // p = usg_arc_a(ng, v); nv = usg_arc_n(ng, v); + // for (i = 0; i < nv; i++) { + // assert(get_usg_arc(ng, p[i].v^1, v^1)); + // } + // } + + usg_cleanup(ng); + + ///debug + debug_sysm_usg_t(ng, __func__); + + idx->h_usg = ng; + + /******for debug******/ + // prt_usg_t(uidx, ng, "ng0"); + /******for debug******/ + + + + u2g_hybrid_clean(uidx, ulopt, ng, b, ub); + // idx->hybrid_ug = gen_hybrid_ug(uidx, ng); + + + // idx->hybrid_ug = gen_debug_hybrid_ug(uidx, ng); + // fprintf(stderr, "-[M::%s::] idx->hybrid_ug->g->n_seq::%u\n", __func__, (uint32_t)idx->hybrid_ug->g->n_seq); +} + +void u2g_clean(ul_resolve_t *uidx, ulg_opt_t *ulopt, uint32_t keep_raw_utg, uint64_t is_bridg) +{ + ul2ul_idx_t *idx = &(uidx->uovl); asg64_v bu = {0,0,0}, uu = {0,0,0}; int64_t max_tip_hifi0 = ulopt->max_tip_hifi; + ma_ug_t *iug = idx->i_ug; int64_t i, mm_tip = ulopt->max_tip; uint64_t cnt = 1, topo_level, ss = 0; + double step = (ulopt->clean_round==1?ulopt->max_path_drop_ratio: + ((ulopt->max_path_drop_ratio-ulopt->min_path_drop_ratio)/(ulopt->clean_round-1))); + double drop = ulopt->min_path_drop_ratio; CALLOC(iug->g->seq_vis, iug->g->n_seq*2); + + + // char sb[1000]; + // output_integer_graph(uidx, iug, "ig_h0", 0); + + // fprintf(stderr, "\n[M::%s::] max_path_drop_ratio::%f, min_path_drop_ratio::%f, max_tip_hifi::%ld, max_tip::%ld\n", + // __func__, ulopt->max_path_drop_ratio, ulopt->min_path_drop_ratio, + // ulopt->max_tip_hifi, ulopt->max_tip); + for (ss = 0; ss < 2; ss++) { + for (i = 0, drop = ulopt->min_path_drop_ratio; i < ulopt->clean_round; i++, drop += step) { + if(drop > ulopt->max_path_drop_ratio) drop = ulopt->max_path_drop_ratio; + // fprintf(stderr, "[M::%s::] Starting round-%ld, drop::%f, max_tip_hifi::%ld\n", + // __func__, i, drop, ulopt->max_tip_hifi); + cnt = 1; topo_level = 2; mm_tip = ulopt->max_tip; + while (cnt) { + cnt = 0; + asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); + cnt += ulg_arc_cut_supports(uidx, iug, mm_tip, ulopt->max_tip_hifi, drop, ulopt->is_trio, topo_level, 1, NULL, keep_raw_utg, &bu, &uu); + cnt += ulg_arc_cut_tips(uidx, iug, mm_tip, ulopt->max_tip_hifi, 1, &bu, &uu);///p_telo + } + + cnt = 1; topo_level = 1; mm_tip = ulopt->max_tip; + while (cnt) { + cnt = 0; + asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); + cnt += ulg_arc_cut_supports(uidx, iug, mm_tip, ulopt->max_tip_hifi, drop, ulopt->is_trio, topo_level, 1, NULL, keep_raw_utg, &bu, &uu); + cnt += ulg_arc_cut_tips(uidx, iug, mm_tip, ulopt->max_tip_hifi, 1, &bu, &uu); + } + + cnt = 1; topo_level = 1; mm_tip = ((int64_t)0x7fffffff); + while (cnt) { + cnt = 0; + asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); + cnt += ulg_arc_cut_supports(uidx, iug, mm_tip, ulopt->max_tip_hifi, drop, ulopt->is_trio, topo_level, 1, NULL, keep_raw_utg, &bu, &uu); + cnt += ulg_arc_cut_tips(uidx, iug, mm_tip, ulopt->max_tip_hifi, 0, &bu, &uu); + } + // fprintf(stderr, "[M::%s::] Done round-%ld, drop::%f\n", __func__, i, drop); + // sprintf(sb, "ig_ss_%lu_i_%ld", ss, i); + // output_integer_graph(uidx, iug, sb, 0); + } + + ulg_pop_bubble(uidx, iug, NULL, ((int64_t)0x7fffffff), ulopt->max_tip_hifi, 1, &bu, &uu); + + while(ulg_arc_cut_z(uidx, iug, ((int64_t)0x7fffffff), ulopt->max_tip_hifi, 1.5, 0.15, 100, 0.8, ulopt->is_trio, 1, NULL, &bu, &uu));///non_p_telo + + // sprintf(sb, "ig_ss_%lu_i_%ld", ss, i); + // output_integer_graph(uidx, iug, sb, 0); + + ulopt->max_tip_hifi <<= 1; + } + ulopt->max_tip_hifi = max_tip_hifi0; + + // output_integer_graph(uidx, iug, "ig_h1", 0); + + u2g_threading(uidx, ulopt, 3, is_bridg, &bu, &uu); + + + // fill_u2g(uidx, &bu, &uu); + + // while (cnt) { + // for (i = cnt = 0, mm_tip = ulopt->max_tip, drop = ulopt->min_ovlp_drop_ratio; i < ulopt->clean_round; i++, drop += step) { + // if(drop > ulopt->max_ovlp_drop_ratio) drop = ulopt->max_ovlp_drop_ratio; + // cnt += ulg_arc_cut_occ(uidx, iug, mm_tip, ulopt->max_tip_hifi, ulopt->is_trio, 2, &bu, &uu); + // asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); + // cnt += ulg_arc_cut_length(uidx, iug, mm_tip, ulopt->max_tip_hifi, drop/**MIN(drop, ulopt->hom_check_drop_rate)**/, ulopt->is_trio, 2, 1, NULL, &bu, &uu); + // cnt += ulg_arc_cut_tips(uidx, iug, mm_tip, ulopt->max_tip_hifi, &bu, &uu); + + // asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); + // cnt += ulg_arc_cut_bridge(uidx, iug, mm_tip, ulopt->max_tip_hifi, 0.5, ulopt->is_trio, 2, NULL, &bu, &uu); + + // asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); + // cnt += ulg_arc_cut_misjoin(uidx, iug, mm_tip, ulopt->max_tip_hifi, 0.5, ulopt->is_trio, 2, NULL, &bu, &uu); + // } + + // for (i = cnt = 0, mm_tip = ((int64_t)0x7fffffff), drop = ulopt->min_ovlp_drop_ratio; i < ulopt->clean_round; i++, drop += step) { + // if(drop > ulopt->max_ovlp_drop_ratio) drop = ulopt->max_ovlp_drop_ratio; + // cnt += ulg_arc_cut_occ(uidx, iug, mm_tip, ulopt->max_tip_hifi, ulopt->is_trio, 2, &bu, &uu); + // asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); + // cnt += ulg_arc_cut_length(uidx, iug, mm_tip, ulopt->max_tip_hifi, drop/**MIN(drop, ulopt->hom_check_drop_rate)**/, ulopt->is_trio, 2, 1, NULL, &bu, &uu); + // cnt += ulg_arc_cut_tips(uidx, iug, mm_tip, ulopt->max_tip_hifi, &bu, &uu); + + // asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); + // cnt += ulg_arc_cut_bridge(uidx, iug, mm_tip, ulopt->max_tip_hifi, 0.5, ulopt->is_trio, 2, NULL, &bu, &uu); + + // asg_arc_identify_simple_bubbles_multi(iug->g, ulopt->b_mask_t, 0); + // cnt += ulg_arc_cut_misjoin(uidx, iug, mm_tip, ulopt->max_tip_hifi, 0.5, ulopt->is_trio, 2, NULL, &bu, &uu); + // } + // } + + free(bu.a); free(uu.a); +} + +void clc_contain(ul_resolve_t *uidx, uint64_t id, uint64_t is_ul, integer_t *buf) +{ + ma_ug_t *raw = uidx->l1_ug; ma_utg_t *ru; ug_opt_t *uopt = uidx->uopt; + uint64_t k, m, qn, tn; ma_hit_t_alloc *x; asg_arc_t e; ul2ul_item_t *o; + int64_t min_ovlp = uopt->min_ovlp, max_hang = uopt->max_hang, r; + + if(is_ul) { + o = get_ul_ovlp(&(uidx->uovl), id, 1); + assert(o && (!o->is_del)); + for (k = 0; k < o->cn; k++) { + if((o->a[k].is_del) || (!ulg_type(uidx->uovl, o->a[k].hid))) continue; + r = integer_hit2arc(&(o->a[k]), ulg_len(*uidx, id), ulg_len(*uidx, o->a[k].hid), + ulg_occ(*uidx, id), ulg_occ(*uidx, o->a[k].hid), id, o->a[k].hid, 0, NULL); + if(r != MA_HT_TCONT) continue; + kv_push(uint64_t, buf->o, o->a[k].hid); + } + } else { + ru = &(raw->u.a[id]); + for (k = 0; k < ru->n; k++) { + x = &(uopt->sources[ru->a[k]>>33]); + for (m = 0; m < x->length; m++) { + qn = Get_qn(x->buffer[m]); tn = Get_tn(x->buffer[m]); + r = ma_hit2arc(&(x->buffer[m]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), + max_hang, asm_opt.max_hang_rate, min_ovlp, &e); + if(r != MA_HT_TCONT) continue; + kv_push(uint64_t, buf->u, tn); + } + } + } +} + +static void worker_renew_u2g_cov(void *data, long i, int tid) // callback for kt_for() +{ + ul_resolve_t *uidx = (ul_resolve_t *)data; + integer_t *buf = &(uidx->str_b.buf[tid]); + ma_utg_t *iu = &(uidx->uovl.i_ug->u.a[i]); + uint64_t z, ri, k, ul_n, ug_n, *a, a_n; ma_ug_t *raw = uidx->l1_ug; + ul_cov_t *idx = &(uidx->uovl.cc); + + idx->uc[i] = idx->raw_uc[i] = idx->hc[i] = ul_n = ug_n = 0; buf->u.n = buf->o.n = 0; + for (z = 0; z < iu->n; z++) { + ri = iu->a[z]>>33; + if(ulg_type(uidx->uovl, ri)) {///ul + clc_contain(uidx, ulg_id(uidx->uovl, ri), 1, buf); ul_n++; + } else {///ug node + clc_contain(uidx, ulg_id(uidx->uovl, ri), 0, buf); + ug_n += raw->u.a[ulg_id(uidx->uovl, ri)].n;///HiFi reads occ + } + } + idx->raw_uc[i] = ul_n; + + ///buf->o: UL contained reads + ///buf->u: HiFi reads + if(buf->o.n > 0) { + a = buf->o.a; a_n = buf->o.n; + radix_sort_srt64(a, a + a_n); + for (z = 0, k = 1; k <= a_n; k++) { + if(k == a_n || a[z] != a[k]) { + ul_n++; z = k; + } + } + } + if(buf->u.n > 0) { + a = buf->u.a; a_n = buf->u.n; + radix_sort_srt64(a, a + a_n); + for (z = 0, k = 1; k <= a_n; k++) { + if(k == a_n || a[z] != a[k]) { + ug_n++; z = k; + } + } + } + idx->uc[i] = ul_n; idx->hc[i] = ug_n; +} + +ul2ul_t* get_ulg_spec_ovlp(ul_resolve_t *uidx, uint64_t uv, uint64_t uw) +{ + ma_ug_t *iug = uidx->uovl.i_ug; uint32_t qid, tid; + qid = iug->u.a[uv>>1].a[((uv&1)?(0):(iug->u.a[uv>>1].n-1))]>>33; + tid = iug->u.a[uw>>1].a[((uw&1)?(iug->u.a[uw>>1].n-1):(0))]>>33; + + if(uidx->uovl.item_idx[qid] == (uint32_t)-1) return NULL; + ul2ul_item_t *o = &(uidx->uovl.a[uidx->uovl.item_idx[qid]]); uint64_t k; + for (k = 0; k < o->cn; k++) { + if(o->a[k].hid != tid) continue; + return &(o->a[k]); + } + return NULL; +} + + + + + +void gen_raw_ug_seq(ul_resolve_t *uidx, ul_str_t *str, ma_utg_t *u, ma_ug_t *raw, uinfo_srt_warp_t *res, uint64_t iug_id) +{ + uint64_t k, cd, nd, rev, x, os, oe; uinfo_srt_t *p; ma_utg_t *ru; + uc_block_t *xi; ul2ul_t *z = NULL; ul_str_t *c_str; int64_t m, cs, ce; + for (k = 0, res->n = 0; k < u->n; k++) { + cd = u->a[k]>>33; rev = ((u->a[k]>>32)&1); ru = NULL; c_str = NULL; + if(ulg_type(uidx->uovl, cd)) c_str = &(str[ulg_id(uidx->uovl, cd)]); ///ul + else ru = &(raw->u.a[ulg_id(uidx->uovl, cd)]); //ug + + if(c_str) { + if(k + 1 < u->n) { + nd = u->a[k+1]>>33; + z = get_ul_spec_ovlp(&(uidx->uovl), cd, nd); + assert(z && (!z->is_del)); + if(!rev) { + cs = 0; ce = z->qs_k + 1; + } else { + cs = z->qe_k - 1; ce = c_str->cn; + } + } else { + cs = 0; ce = c_str->cn; + } + + if(!rev) { + xi = &(uidx->idx->a[cd].bb.a[c_str->a[cs]>>32]); + x = (uint32_t)c_str->a[cs]; + } else { + xi = &(uidx->idx->a[cd].bb.a[c_str->a[ce-1]>>32]); + x = (uint32_t)c_str->a[ce-1]; x ^= 1; + } + + if(res->n) { + assert((res->a[res->n-1].v) == x); + os = MAX(xi->ts, res->a[res->n-1].s); oe = MIN(xi->te, res->a[res->n-1].e); + assert(oe > os); + os = MIN(xi->ts, res->a[res->n-1].s); oe = MAX(xi->te, res->a[res->n-1].e); + res->a[res->n-1].s = os; res->a[res->n-1].e = oe; + if(!rev) cs++; + else ce--; + } + + if(!rev) { + for (m = cs; m < ce; m++) { + xi = &(uidx->idx->a[cd].bb.a[c_str->a[m]>>32]); + x = (uint32_t)c_str->a[m]; + kv_pushp(uinfo_srt_t, *res, &p); + p->v = x; p->s = xi->ts; p->e = xi->te; + } + } else { + for (m = ce-1; m >= cs; m--) { + xi = &(uidx->idx->a[cd].bb.a[c_str->a[m]>>32]); + x = ((uint32_t)c_str->a[m])^1; + kv_pushp(uinfo_srt_t, *res, &p); + p->v = x; p->s = xi->ts; p->e = xi->te; + } + } + } else if(ru) { + x = ulg_id(uidx->uovl, cd); x <<= 1; if(rev) x^=1; + if(res->n) { + if((!ulg_type(uidx->uovl, (u->a[k-1]>>33)))) {///in previous ul is also a raw utg node + assert(get_specfic_edge(raw->g, res->a[res->n-1].v, x)); + kv_pushp(uinfo_srt_t, *res, &p); + p->v = x; p->s = 0; p->e = ru->len; + } else { + // assert(((res->a[res->n-1].v) == x)); + if(((res->a[res->n-1].v) == x)) { + res->a[res->n-1].s = 0; res->a[res->n-1].e = ru->len; + } else { + assert(get_specfic_edge(raw->g, res->a[res->n-1].v, x)); + kv_pushp(uinfo_srt_t, *res, &p); + p->v = x; p->s = 0; p->e = ru->len; + } + } + } else { + kv_pushp(uinfo_srt_t, *res, &p); + p->v = x; p->s = 0; p->e = ru->len; + } + } + } + + + for (k = 0; k < res->n; k++) { + res->a[k].n = ug_occ_w(res->a[k].s, res->a[k].e, &(raw->u.a[res->a[k].v>>1])); + } +} + + +void renew_u2g_cov(ul_resolve_t *uidx, telo_end_t *te) +{ + ul2ul_idx_t *idx = &(uidx->uovl); uinfo_srt_warp_t *x; + ma_ug_t *i_ug = idx->i_ug, *raw = uidx->l1_ug; uint64_t k, z, iug_occ, m, l, *a, a_n; + free(idx->cc.uc); free(idx->cc.hc); free(idx->cc.raw_uc); + free(idx->cc.iug_idx); free(idx->cc.iug_b); free(idx->cc.iug_a); + if(te) { + free(idx->telo); idx->telo = NULL; + } + memset(&(idx->cc), 0, sizeof(idx->cc)); + + MALLOC(idx->cc.uc, i_ug->u.n); ///number of ul (contained+non-contained) + MALLOC(idx->cc.raw_uc, i_ug->u.n); ///number of ul (non-contained) + MALLOC(idx->cc.hc, i_ug->u.n); ///number of HiFi reads + if(te) MALLOC(idx->telo, i_ug->u.n); ///is telo + + kt_for(uidx->str_b.n_thread, worker_renew_u2g_cov, uidx, i_ug->u.n); + + CALLOC(idx->cc.iug_a, i_ug->u.n); ///integer sequence of each integer unitig + CALLOC(idx->cc.iug_idx, raw->u.n+1); ///idx for integer sequences + // fprintf(stderr, "malloc::[M::%s::] i_ug->u.n:%u\n", __func__, (uint32_t)i_ug->u.n); + for (k = iug_occ = 0; k < i_ug->u.n; k++) { + // fprintf(stderr, "-[M::%s::] k::%lu, i_ug->u.n:%u\n", __func__, k, (uint32_t)i_ug->u.n); + gen_raw_ug_seq(uidx, uidx->pstr.str.a, &(i_ug->u.a[k]), raw, &(idx->cc.iug_a[k]), k); + iug_occ += idx->cc.iug_a[k].n; x = &(idx->cc.iug_a[k]); + for (z = 0; z < x->n; z++) idx->cc.iug_idx[x->a[z].v>>1]++; + + if(te) { + idx->telo[k] = 0; + for (z = 0; z < x->n; z++) { + if(gen_utg_telo(&(raw->u.a[x->a[z].v>>1]), te)) break; + } + if(z < x->n) idx->telo[k] = 1; + } + } + + MALLOC(idx->cc.iug_b, iug_occ); ///idx for integer sequences + for (k = l = 0; k < raw->u.n+1; k++) { + m = idx->cc.iug_idx[k]; + idx->cc.iug_idx[k] = l; + l += m; + if(m > 0) idx->cc.iug_b[l-1] = 0; + } + assert(l == iug_occ); + + for (k = 0; k < i_ug->u.n; k++) { + x = &(idx->cc.iug_a[k]); + for (z = 0; z < x->n; z++) { + a = idx->cc.iug_b + idx->cc.iug_idx[x->a[z].v>>1]; + a_n = idx->cc.iug_idx[(x->a[z].v>>1)+1] - idx->cc.iug_idx[x->a[z].v>>1]; + if(a_n) { + if(a[a_n-1] == a_n-1) a[a_n-1] = (k<<32)|z;///id of unitig | offset within the unitig + else a[a[a_n-1]++] = (k<<32)|z; + } + } + } +} + +static void worker_renew_integer_bridge(void *data, long i, int tid) // callback for kt_for() +{ + ul_resolve_t *uidx = (ul_resolve_t *)data; bubble_type *bub = uidx->bub; + asg_t *bg = uidx->uovl.bg.bg; ul_str_idx_t *str_idx = &(uidx->pstr); + asg_arc_t *p = &(bg->arc[i]); uint64_t *hid_a, hid_n, z; ul_str_t *str; + uint32_t v = p->ul>>32, w = p->v, vz, wz; int64_t s, s_n, occ = 0; + + hid_a = str_idx->occ.a + str_idx->idx.a[v>>1]; + hid_n = str_idx->idx.a[(v>>1)+1] - str_idx->idx.a[v>>1]; + for (z = 0; z < hid_n; z++) { + str = &(str_idx->str.a[hid_a[z]>>32]); s_n = str->cn; + if(s_n < 2) continue; + vz = (uint32_t)(str->a[(uint32_t)hid_a[z]]); + assert((v>>1) == (vz>>1)); + s = (uint32_t)hid_a[z]; s -= 1; vz = ((uint32_t)(str->a[(uint32_t)hid_a[z]]))^1; + for (; s >= 0; s--) { + wz = (uint32_t)(str->a[s]); wz ^= 1; + if(IF_HOM((wz>>1), *bub)) continue; + if(vz == v && wz == w) occ++; + else if(vz == (v^1) && wz == (w^1)) occ++; + break; + } + + s = (uint32_t)hid_a[z]; s += 1; vz = (uint32_t)(str->a[(uint32_t)hid_a[z]]); + for (; s < s_n; s++) { + wz = (uint32_t)(str->a[s]); + if(IF_HOM((wz>>1), *bub)) continue; + if(vz == v && wz == w) occ++; + else if(vz == (v^1) && wz == (w^1)) occ++; + break; + } + } + p->ol = occ; p->ul >>= 32; p->ul <<= 32; p->ul += (((uint32_t)-1) - p->ol); +} + +void renew_u2g_bg(ul_resolve_t *uidx) +{ + ul2ul_idx_t *idx = &(uidx->uovl); ul_bg_t *bg = &(idx->bg); + ma_ug_t *iug = idx->i_ug, *raw = uidx->l1_ug; bubble_type *bub = uidx->bub; + uint64_t k, z, l, *raw_a, raw_n, raw_id, iug_id, iug_off, v, w, nv, nw, n_vtx; + uinfo_srt_warp_t *x; asg64_v buf = {0,0,0}; int64_t s, s_n; asg_arc_t *p, *av, *aw; + asg_destroy(bg->bg); free(bg->w_n); free(bg->a_n); memset(bg, 0, sizeof((*bg))); + + bg->bg = asg_init(); + bg->bg->n_seq = 0; bg->bg->m_seq = raw->g->n_seq; MALLOC(bg->bg->seq, bg->bg->m_seq); + for (k = 0; k < raw->g->n_seq; k++) { + raw_id = k; + if(IF_HOM(raw_id, *bub)) {///updated-line + // asg_seq_set(bg->bg, k, raw->g->seq[k].len, 1); + // bg->bg->seq[k].c = 0; + continue; + } + raw_a = idx->cc.iug_b + idx->cc.iug_idx[raw_id]; + raw_n = idx->cc.iug_idx[raw_id+1] - idx->cc.iug_idx[raw_id]; + for (z = 0, buf.n = 0; z < raw_n; z++) { + iug_id = raw_a[z]>>32; iug_off = (uint32_t)raw_a[z]; + x = &(idx->cc.iug_a[iug_id]); s_n = x->n; + assert(raw_id == (x->a[iug_off].v>>1)); + if(iug->g->seq[iug_id].del) continue; + for (s = ((int64_t)iug_off) - 1, v = x->a[iug_off].v^1; s >= 0; s--) { + if(IF_HOM((x->a[s].v>>1), *bub)) continue; + kv_push(uint64_t, buf, ((v<<32)|((uint64_t)(x->a[s].v^1)))); + break; + } + for (s = ((int64_t)iug_off) + 1, v = x->a[iug_off].v; s < s_n; s++) { + if(IF_HOM((x->a[s].v>>1), *bub)) continue; + kv_push(uint64_t, buf, ((v<<32)|((uint64_t)(x->a[s].v)))); + break; + } + } + + asg_seq_set(bg->bg, k, raw->g->seq[k].len, ((buf.n>0)?0:1)); + bg->bg->seq[k].c = 0; + + radix_sort_srt64(buf.a, buf.a + buf.n); + for (l = 0, z = 1; z <= buf.n; z++) { + if(z == buf.n || buf.a[l] != buf.a[z]) { + p = asg_arc_pushp(bg->bg); memset(p, 0, sizeof(*p)); + p->v = (uint32_t)buf.a[l]; p->ol = z - l; + p->ul = buf.a[l]>>32; p->ul <<= 32; + p->ul += (((uint32_t)-1) - p->ol); + l = z; + } + } + } + + kt_for(uidx->str_b.n_thread, worker_renew_integer_bridge, uidx, bg->bg->n_arc); + asg_cleanup(bg->bg); bg->bg->r_seq = bg->bg->n_seq; + + /***********debug***********/ + for (k = 0; k < bg->bg->n_arc; k++) { + p = &(bg->bg->arc[k]); v = p->v^1; w = (p->ul>>32)^1; + av = asg_arc_a(bg->bg, v); nv = asg_arc_n(bg->bg, v); + for (z = 0; z < nv; z++) { + if(av[z].v == w) break; + } + assert(z < nv && p->ol == av[z].ol); + } + /***********debug***********/ + + uint64_t v_occ[2], w_occ[2]; double ss = 0.500001; + for (v = 0, n_vtx = bg->bg->n_seq<<1; v < n_vtx; v++) { + if(bg->bg->seq[v>>1].del) continue; + av = asg_arc_a(bg->bg, v); nv = asg_arc_n(bg->bg, v); + if(!nv) {continue;} w = av[0].v; + v_occ[0] = v_occ[1] = w_occ[0] = w_occ[1] = (uint32_t)-1; + + av = asg_arc_a(bg->bg, v); nv = asg_arc_n(bg->bg, v); + for (k = 0; k < nv && k < 2; k++) { + v_occ[k] = av[k].ol; v_occ[k] <<= 32; v_occ[k] += av[k].v; + } + + aw = asg_arc_a(bg->bg, (w^1)); nw = asg_arc_n(bg->bg, (w^1)); + for (k = 0; k < nw && k < 2; k++) { + w_occ[k] = aw[k].ol; w_occ[k] <<= 32; w_occ[k] += aw[k].v; + } + + if((((uint32_t)v_occ[0]) == w) && (((uint32_t)w_occ[0]) == (v^1))) { + if(((((v_occ[0]>>32)*ss) >= (v_occ[1]>>32)) && (((w_occ[0]>>32)*ss) >= (w_occ[1]>>32))) || + ((((v_occ[0]>>32)+(w_occ[0]>>32))*ss) >= ((v_occ[1]>>32)+(w_occ[1]>>32)))) { + for (k = 0; k < nv; k++) av[k].ou = 2;///wrong + for (k = 0; k < nw; k++) aw[k].ou = 2;///wrong + av[0].ou = aw[0].ou = 3;//correct + } else { + for (k = 0; k < nv; k++) av[k].ou = 1;///ambg + for (k = 0; k < nw; k++) aw[k].ou = 1;///ambg + } + } + } + + for (k = 0; k < bg->bg->n_arc; k++) { + p = &(bg->bg->arc[k]); v = p->v^1; w = (p->ul>>32)^1; + av = asg_arc_a(bg->bg, v); nv = asg_arc_n(bg->bg, v); + for (z = 0; z < nv; z++) { + if(av[z].v == w) break; + } + assert(z < nv && p->ol == av[z].ol); + l = MAX(p->ou, av[z].ou); if(l == 0) l = 1; + p->ou = av[z].ou = l; + } + + + MALLOC(bg->w_n, iug->u.n); MALLOC(bg->a_n, iug->u.n); + for (k = 0; k < iug->u.n; k++) { + x = &(idx->cc.iug_a[k]); bg->w_n[k] = bg->a_n[k] = 0; + for (z = nv = 0; z < x->n; z++) { + if(IF_HOM((x->a[z].v>>1), *bub)) continue; + v_occ[nv&1] = x->a[z].v; nv++; + if(nv < 2) continue; + l = get_bg_flag(uidx, v_occ[(nv-2)&1], v_occ[(nv-1)&1]); + assert(l != bg_unavailable); + if(l == bg_wrong) bg->w_n[k]++; + if(l == bg_ambiguous) bg->a_n[k]++; + } + // fprintf(stderr, "-[M::%s::] k::%lu, x->n::%u, w_n[k]::%u, a_n[k]::%u\n", + // __func__, k, (uint32_t)x->n, bg->w_n[k], bg->a_n[k]); + } + + kv_destroy(buf); +} + +/** +static void worker_update_ul_tra_idx(void *data, long i, int tid) // callback for kt_for() +{ + ul_resolve_t *uidx = (ul_resolve_t *)data; integer_t *buf = &(uidx->str_b.buf[tid]); + ma_ug_t *iug = uidx->uovl.i_ug; ul_tra_idx_t *iug_tra = &(uidx->uovl.iug_tra); + uint32_t v = i, n_tra = iug_tra_arc_n(iug_tra, v), nv, k; + if(n_tra == 0) return; + ul_tra_t *a_tra = iug_tra_arc_a(iug_tra, v); asg_arc_t *av; + + av = asg_arc_a(iug->g, v); nv = asg_arc_n(iug->g, v); kv_resize(uint64_t, buf->u, 2); + for (k = 0; k < nv; k++) { + buf->u.n = 0; buf->u.a[buf->u.n++] = v; buf->u.a[buf->u.n++] = av[k].v; + } +} + +void update_ul_tra_idx_t(ul_resolve_t *uidx) +{ + ma_ug_t *iug = uidx->uovl.i_ug; ul_tra_idx_t *iug_tra = &(uidx->uovl.iug_tra); + uint64_t v, n_vtx = iug->g->n_seq<<1, l, m; + iug_tra->arc.n = iug_tra->idx.n = 0; + kv_resize(uint32_t, iug_tra->idx, n_vtx + 1); iug_tra->idx.n = n_vtx + 1; + memset(iug_tra->idx.a, 0, iug_tra->idx.n *sizeof(*(iug_tra->idx.a))); + for (v = l = 0; v < n_vtx; v++) { + m = asg_arc_n(iug->g, v); + if(m < 2) m = 0; + iug_tra->idx.a[v] = l; + l += m; + } + iug_tra->idx.a[v] = l; + kv_resize(ul_tra_t, iug_tra->arc, l); iug_tra->arc.n = l; + + kt_for(uidx->str_b.n_thread, worker_update_ul_tra_idx, uidx, n_vtx);///all ul + ug +} +**/ +void renew_ul2_utg(ul_resolve_t *uidx) +{ + ul2ul_idx_t *z = &(uidx->uovl); + if(uidx->uovl.cc.iug_a) { + uint32_t k; + for (k = 0; k < z->i_ug->u.n; k++) free(uidx->uovl.cc.iug_a[k].a); + } + renew_utg(&(z->i_ug), z->i_g, NULL); + free(z->i_ug->g->seq_vis); CALLOC(z->i_ug->g->seq_vis, z->i_ug->g->n_seq*2); + renew_u2g_cov(uidx, uidx->uopt->te); + renew_u2g_bg(uidx); +} + + +ul2ul_idx_t *gen_ul2ul(ul_resolve_t *uidx, ug_opt_t *uopt, ulg_opt_t *ulopt, uint32_t keep_raw_utg, uint64_t is_bridg) +{ + uint64_t k, m; + ma_ug_t *ug = uidx->l1_ug; all_ul_t *uls = uidx->idx; + ul2ul_idx_t *z = &(uidx->uovl); ul_str_idx_t *str_idx = &(uidx->pstr); + z->uln = uls->n; z->gn = ug->g->n_seq; + z->tot = uls->n + ug->g->n_seq; MALLOC(z->item_idx, z->tot); + for (k = m = 0; k < z->tot; k++) { + z->item_idx[k] = (uint32_t)-1; + if(k < z->uln) {///is a ul read + if(str_idx->str.a[k].cn > 1) { + z->item_idx[k] = m; m++; + } + } else {//is a node in graph + z->item_idx[k] = m; m++; + } + } + CALLOC(z->a, m); z->n = z->m = m; + + kt_for(uidx->str_b.n_thread, worker_integer_postprecess, uidx, uls->n); + gen_integer_normalize(uidx); + + chimeric_integer_deal(uidx); + append_utg_es(uidx); + + + kt_for(uidx->str_b.n_thread, worker_integert_debug_sym, uidx, z->tot);///all ul + ug + print_integert_ovlp_stat(z); + remove_integert_containment(uidx, keep_raw_utg); + + kt_for(uidx->str_b.n_thread, worker_integert_debug_sym, uidx, z->tot);///all ul + ug + print_integert_ovlp_stat(z); + // print_uls_seq(uidx, asm_opt.output_file_name); + // print_uls_ovs(uidx, asm_opt.output_file_name); + + z->i_g = integer_sg_gen(uidx, uopt->min_ovlp); + asg_arc_del_trans(z->i_g, uopt->gap_fuzz); + + z->i_ug = ma_ug_gen(z->i_g); + // CALLOC(z->i_ug->g->seq_vis, z->i_ug->g->n_seq*2); + renew_u2g_cov(uidx, uidx->uopt->te); + renew_u2g_bg(uidx); + + // output_integer_graph(uidx, z->i_ug, asm_opt.output_file_name); + u2g_clean(uidx, ulopt, keep_raw_utg, is_bridg); + // renew_ul2_utg(uidx); + + // output_integer_graph(uidx, z->i_ug, asm_opt.output_file_name, 0); + return z; +} + +uint64_t str_occ_w(ul_str_t *str, ul_vec_t *raw, ma_ug_t *ug) +{ + uint64_t occ, k; uc_block_t *z; + for (k = occ = 0; k < str->cn; k++) { + z = &(raw->bb.a[str->a[k]>>32]); + assert(((z->hid<<1)+z->rev)==((uint32_t)str->a[k])); + occ += ug_occ_w(z->ts, z->te, &(ug->u.a[z->hid])); + } + return occ; +} + +void gen_cul_g_t(ul_resolve_t *uidx) +{ + ma_ug_t *ug = uidx->l1_ug; uint64_t k; ul_str_idx_t *str_idx = &(uidx->pstr); + CALLOC(uidx->cg, 1); + uidx->cg->n[0] = uidx->idx->n; uidx->cg->n[1] = ug->g->n_seq; + uidx->cg->tot = uidx->cg->n[0] + uidx->cg->n[1]; + uidx->cg->g = asg_init(); + for (k = 0; k < uidx->cg->tot; k++) { + if(k < uidx->cg->n[0]) { + asg_seq_set(uidx->cg->g, k, str_occ_w(&(str_idx->str.a[k]), &(uidx->idx->a[k]), ug), + ((str_idx->str.a[k].cn>1)?0:1)); + } else { + asg_seq_set(uidx->cg->g, k, ug->u.a[k-uidx->cg->n[0]].n, 0); + } + } +} + +void init_ulg_opt_t(ulg_opt_t *z, ug_opt_t *uopt, int64_t clean_round, +double min_path_drop_ratio, double max_path_drop_ratio, +double min_ovlp_drop_ratio, double max_ovlp_drop_ratio, double hom_check_drop_rate, +int64_t max_tip, int64_t max_tip_hifi, bub_label_t *b_mask_t, uint32_t is_trio) +{ + z->tipsLen = uopt->tipsLen; + z->tip_drop_ratio = uopt->tip_drop_ratio; + z->stops_threshold = uopt->stops_threshold; + z->chimeric_rate = uopt->chimeric_rate; + z->drop_ratio = uopt->drop_ratio; + + + z->b_mask_t = b_mask_t; + z->clean_round = clean_round; + z->min_path_drop_ratio = min_path_drop_ratio; + z->max_path_drop_ratio = max_path_drop_ratio; + z->min_ovlp_drop_ratio = min_ovlp_drop_ratio; + z->max_ovlp_drop_ratio = max_ovlp_drop_ratio; + z->hom_check_drop_rate = hom_check_drop_rate; + z->max_tip = max_tip; + z->max_tip_hifi = max_tip_hifi; + z->is_trio = is_trio; +} + +ma_ug_t* output_trio_unitig_graph_ul(ug_opt_t *uopt, ul_resolve_t *uidx, char* ou, uint8_t flag) +{ + char* gfa_name; MALLOC(gfa_name, strlen(ou)+100); + sprintf(gfa_name, "%s.%s.p_ctg.gfa", ou, (flag==FATHER?"hap1":"hap2")); + FILE* output_file = fopen(gfa_name, "w"); + + ma_ug_t *ug = copy_untig_graph(uidx->uovl.hybrid_ug); + kvec_asg_arc_t_warp ne; kv_init(ne.a); + + adjust_utg_by_trio(&ug, uidx->sg, flag, TRIO_THRES, uopt->sources, uopt->reverse_sources, + uopt->coverage_cut, uopt->tipsLen, uopt->tip_drop_ratio, uopt->stops_threshold, uopt->ruIndex, + uopt->chimeric_rate, uopt->drop_ratio, uopt->max_hang, uopt->min_ovlp, uopt->gap_fuzz, &ne, uopt->b_mask_t); + + // if(asm_opt.b_low_cov > 0) { + // break_ug_contig(&ug, uidx->sg, &R_INF, uopt->coverage_cut, uopt->sources, uopt->ruIndex, &ne, + // uopt->max_hang, uopt->min_ovlp, &asm_opt.b_low_cov, NULL, asm_opt.m_rate); + // } + + // if(asm_opt.b_high_cov > 0) + // { + // break_ug_contig(&ug, uidx->sg, &R_INF, uopt->coverage_cut, uopt->sources, uopt->ruIndex, &ne, + // uopt->max_hang, uopt->min_ovlp, NULL, &asm_opt.b_high_cov, asm_opt.m_rate); + // } + + fprintf(stderr, "Writing %s to disk... \n", gfa_name); + ma_ug_seq(ug, uidx->sg, uopt->coverage_cut, uopt->sources, &ne, uopt->max_hang, uopt->min_ovlp, 0, 1); + + ma_ug_print(ug, uidx->sg, uopt->coverage_cut, uopt->sources, uopt->ruIndex, (flag==FATHER?"h1tg":"h2tg"), output_file); + fclose(output_file); + + sprintf(gfa_name, "%s.%s.p_ctg.noseq.gfa", ou, (flag==FATHER?"hap1":"hap2")); + output_file = fopen(gfa_name, "w"); + ma_ug_print_simple(ug, uidx->sg, uopt->coverage_cut, uopt->sources, uopt->ruIndex, (flag==FATHER?"h1tg":"h2tg"), output_file); + fclose(output_file); + // if(asm_opt.bed_inconsist_rate != 0) + // { + // sprintf(gfa_name, "%s.%s.p_ctg.lowQ.bed", output_file_name, f_prefix?f_prefix:(flag==FATHER?"hap1":"hap2")); + // output_file = fopen(gfa_name, "w"); + // ma_ug_print_bed(ug, sg, &R_INF, coverage_cut, sources, &new_rtg_edges, + // max_hang, min_ovlp, asm_opt.bed_inconsist_rate, (flag==FATHER?"h1tg":"h2tg"), output_file, NULL); + // fclose(output_file); + // } + + free(gfa_name); + ma_ug_destroy(ug); + kv_destroy(ne.a); + return NULL; +} + + + +void realloc_rdb(All_reads* rdb, ma_sub_t **cov, R_to_U *ruI, uint64_t *rmap, uint64_t rid_n, uint64_t scaf_len, char *scaf_id, +asg_t *ng, ug_opt_t *uopt) +{ + uint64_t i, rid_n0 = rdb->total_reads, tname, cname; + uint64_t scaf_id_len = strlen(scaf_id); char *des, *src; + rdb->total_reads = rid_n; + tname = rdb->name_index[rid_n0]; + fprintf(stderr, "+[M::%s] rid_n0::%lu, rid_n::%lu\n", __func__, rid_n0, rid_n); + ///for read bases + REALLOC(rdb->N_site, rdb->total_reads); + REALLOC(rdb->read_length, rdb->total_reads); + REALLOC(rdb->read_size, rdb->total_reads); + REALLOC(rdb->read_sperate, rdb->total_reads); + REALLOC(rdb->trio_flag, rdb->total_reads); + REALLOC(rdb->name_index, rdb->total_reads+1);///total_reads+1 + REALLOC((*cov), rdb->total_reads); + for (i = rid_n0; i < rdb->total_reads; i++) { + // fprintf(stderr, "[M::%s] i::%lu\n", __func__, i); + rdb->N_site[i] = NULL; + rdb->read_length[i] = scaf_len; + rdb->read_size[i] = scaf_len; + rdb->trio_flag[i] = AMBIGU; + (*cov)[i].c = (*cov)[i].del = 0; + (*cov)[i].s = 0; (*cov)[i].e = scaf_len; + cname = scaf_id_len; + if(rmap[i] != ((uint64_t)-1)) {///not a scaffold node + if(rdb->N_site[rmap[i]] != NULL) { + MALLOC(rdb->N_site[i], rdb->N_site[rmap[i]][0]+1); + memcpy(rdb->N_site[i], rdb->N_site[rmap[i]], + sizeof((*(rdb->N_site[i])))*(rdb->N_site[rmap[i]][0]+1)); + } + rdb->read_length[i] = rdb->read_length[rmap[i]]; + rdb->read_size[i] = rdb->read_length[rmap[i]]; + rdb->trio_flag[i] = rdb->trio_flag[rmap[i]]; + (*cov)[i] = (*cov)[rmap[i]]; + cname = Get_NAME_LENGTH((*rdb), (rmap[i])); + } + rdb->name_index[i] = tname; tname += cname; + rdb->total_reads_bases += rdb->read_length[i]; + + MALLOC(rdb->read_sperate[i], (rdb->read_length[i]/4+1)); + if(rmap[i] != ((uint64_t)-1)) {///not a scaffold node + memcpy(rdb->read_sperate[i], rdb->read_sperate[rmap[i]], + sizeof((*(rdb->read_sperate[i])))*(rdb->read_length[i]/4+1)); + } else { + ///set to A + memset(rdb->read_sperate[i], 0, sizeof((*(rdb->read_sperate[i])))*(rdb->read_length[i]/4+1)); + } + } + + rdb->index_size = rdb->total_reads; + rdb->name_index[i] = tname; + rdb->total_name_length = tname; + rdb->name_index_size = rdb->total_reads+1; + REALLOC(rdb->name, tname); + for (i = rid_n0; i < rdb->total_reads; i++) { + des = Get_NAME((*rdb), i); src = scaf_id; cname = scaf_id_len; + if(rmap[i] != ((uint64_t)-1)) { + src = Get_NAME((*rdb), rmap[i]); cname = Get_NAME_LENGTH((*rdb), (rmap[i])); + } + memcpy(des, src, sizeof((*(des)))*cname); + } + + REALLOC(rdb->paf, rdb->total_reads); + memset(rdb->paf+rid_n0, 0, (rdb->total_reads-rid_n0)*sizeof((*rdb->paf))); + REALLOC(rdb->reverse_paf, rdb->total_reads); + memset(rdb->reverse_paf+rid_n0, 0, (rdb->total_reads-rid_n0)*sizeof((*rdb->reverse_paf))); + + ruI->len = rdb->total_reads; + REALLOC(ruI->index, ruI->len); + memset(ruI->index, -1, sizeof((*(ruI->index)))*(ruI->len)); + + reset_bub_label_t(uopt->b_mask_t, ng, 0, 0); + uopt->coverage_cut = (*cov); + uopt->reverse_sources = rdb->reverse_paf; + uopt->sources = rdb->paf; + fprintf(stderr, "-[M::%s] rid_n0::%lu, rid_n::%lu\n", __func__, rid_n0, rid_n); +} + +inline void update_qtn(ma_hit_t *z, uint64_t qn, uint64_t tn) +{ + z->qns <<= 32; z->qns >>= 32; z->qns |= (qn<<32); z->tn = tn; +} + +inline uint64_t dup_paf_check(ma_hit_t_alloc *x, ma_hit_t *p) +{ + int64_t i; ma_hit_t *z; + for (i = 0; i < x->length; i++) { + z = &(x->buffer[i]); + if((z->qns == p->qns) && (z->tn == p->tn) && (z->qe == p->qe) && (z->ts == p->ts) && (z->te == p->te) && + (z->cc == p->cc) && (z->ml == p->ml) && (z->rev == p->rev) && (z->bl == p->bl) && (z->del == p->del) && + (z->el == p->el) && (z->no_l_indel == p->no_l_indel)) { + return 0; + } + } + return 1; +} + +void renew_paf0(ma_hit_t_alloc *paf, uint64_t *a0, uint64_t a0n, uint64_t *a1, uint64_t a1n, asg64_v *buf) +{ + if(a0n <= 1 && a1n <= 1) return; + uint64_t qn = ((uint32_t)a0[0]), tn = ((uint32_t)a1[0]), i, k, sf = 0; + ma_hit_t e01, e10; uint64_t qi, ti, *qa, *ta, qlen, tlen; buf->n = 0; ma_hit_t_alloc *qo, *to; + if(qn == tn) sf = 1; + qo = &(paf[qn]); qi = qo->length; + for (i = qlen = 0, qa = NULL; i < qi; i++) { + if(qo->buffer[i].tn == tn) kv_push(uint64_t, *buf, i); + } + qlen = buf->n; + + to = &(paf[tn]); ti = to->length; + for (i = tlen = 0, ta = NULL; i < ti; i++) { + if(to->buffer[i].tn == qn) kv_push(uint64_t, *buf, i); + } + tlen = buf->n - qlen; + assert(qlen && tlen); + qa = buf->a; ta = buf->a + qlen; + + for (qi = 0; qi < qlen; qi++) { + e01 = qo->buffer[qa[qi]]; + for (ti = 0; ti < tlen; ti++) { + e10 = to->buffer[ta[ti]]; + + for (i = 0; i < a0n; i++) { + qn = ((uint32_t)a0[i]); + for (k = 0; k < a1n; k++) { + if(i == 0 && k == 0) continue; + tn = ((uint32_t)a1[k]); + + update_qtn(&e01, qn, tn); + if((!sf) || (dup_paf_check(&(paf[qn]), &e01))) { + add_ma_hit_t_alloc(&(paf[qn]), &e01); + } + + update_qtn(&e10, tn, qn); + if((!sf) || (dup_paf_check(&(paf[tn]), &e10))) { + add_ma_hit_t_alloc(&(paf[tn]), &e10); + } + } + } + } + } + + /** + idx = get_specific_overlap(&(paf[qn]), qn, tn); + if(idx < 0) return; + e01 = paf[qn].buffer[idx]; + idx = get_specific_overlap(&(paf[tn]), tn, qn); + e10 = paf[tn].buffer[idx]; + + for (i = 0; i < a0n; i++) { + qn = ((uint32_t)a0[i]); + for (k = 0; k < a1n; k++) { + if(i == 0 && k == 0) continue; + tn = ((uint32_t)a1[k]); + if((qn == 5619628 && tn == 5619629) || (tn == 5619628 && qn == 5619629)) { + fprintf(stderr, "[M::%s]\tqn::%lu(qg::%u)\ttn::%lu(tg::%u)\n", __func__, + qn, ((uint32_t)a0[0]), tn, ((uint32_t)a1[0])); + } + update_qtn(&e01, qn, tn); add_ma_hit_t_alloc(&(paf[qn]), &e01); + update_qtn(&e10, tn, qn); add_ma_hit_t_alloc(&(paf[tn]), &e10); + } + } + **/ +} + +void renew_paf1(ma_hit_t_alloc *paf, uint64_t *a, uint64_t an, uint64_t len) +{ + uint64_t i, k, qn, tn; ma_hit_t arc; + arc.qns = 0; arc.qe = len; + arc.tn = 0; arc.ts = 0; arc.te = len; + arc.rev = arc.el = arc.ml = arc.no_l_indel = arc.bl = 0; + + for (i = 0; i < an; i++) { + qn = ((uint32_t)a[i]); + for (k = 0; k < an; k++) { + tn = ((uint32_t)a[k]); + update_qtn(&arc, qn, tn); + add_ma_hit_t_alloc(&(paf[qn]), &arc); + } + } +} + +void update_paf(ma_hit_t_alloc *src, ma_hit_t_alloc *r_src, uint64_t *rmap, uint64_t rid_n, uint64_t pre_gn, asg_t *ng) +{ + asg64_v clus, bb; uint64_t k, l, dn = 0, j, qn, tn; + uint64_t *idx; ma_hit_t_alloc *z; + uint64_t *a0, *a1, a0n, a1n; + CALLOC(idx, pre_gn); kv_init(bb); + kv_init(clus); kv_resize(uint64_t, clus, rid_n); + for (k = 0; k < rid_n; k++) { + if(rmap[k] == ((uint64_t)-1)) continue;///scaffold + clus.a[clus.n++] = (rmap[k]<<32)|k; + } + radix_sort_srt64(clus.a, clus.a+clus.n); + for (k = 1, l = 0; k <= clus.n; k++) { + if(k == clus.n || (clus.a[k]>>32) != (clus.a[l]>>32)) { + idx[(clus.a[l]>>32)] = (l<<32)|k; + l = k; dn++; + } + } + assert(dn == pre_gn); + fprintf(stderr, "+[M::%s] dn::%lu\n", __func__, dn); + + for (k = 0; k < dn; k++) { + a0 = clus.a + (idx[k]>>32); a0n = ((uint32_t)idx[k]) - (idx[k]>>32); + assert(a0n > 0 && ((uint32_t)a0[0]) == k); + // if(k == 4265018) { + // fprintf(stderr, "\n[M::%s]\tgroup::%lu\n", __func__, k); + // for (j = 0; j < a0n; j++) { + // fprintf(stderr, "[M::%s]\tnid::%uu\n", __func__, (uint32_t)a0[j]); + // } + // } + z = &(src[k]); + for (j = 0; j < z->length; j++) { + qn = Get_qn(z->buffer[j]); + tn = Get_tn(z->buffer[j]); + if(tn >= dn) continue; + if(qn > tn) continue; + a1 = clus.a + (idx[tn]>>32); + a1n = ((uint32_t)idx[tn]) - (idx[tn]>>32); + // fprintf(stderr, "+[M::%s] qn::%lu, tn::%lu, a0n::%lu, a1n::%lu\n", __func__, qn, tn, a0n, a1n); + assert(a1n > 0 && ((uint32_t)a1[0]) == tn); + renew_paf0(src, a0, a0n, a1, a1n, &bb); + } + + z = &(r_src[k]); + for (j = 0; j < z->length; j++) { + qn = Get_qn(z->buffer[j]); + tn = Get_tn(z->buffer[j]); + if(tn >= dn) continue; + if(qn > tn) continue; + a1 = clus.a + (idx[tn]>>32); + a1n = ((uint32_t)idx[tn]) - (idx[tn]>>32); + // fprintf(stderr, "-[M::%s] qn::%lu, tn::%lu, a0n::%lu, a1n::%lu\n", __func__, qn, tn, a0n, a1n); + assert(a1n > 0 && ((uint32_t)a1[0]) == tn); + renew_paf0(r_src, a0, a0n, a1, a1n, &bb); + } + + + + // for (l = k; l < dn; l++) { + // a1 = clus.a + (idx[l]>>32); a1n = ((uint32_t)idx[l]) - (idx[l]>>32); + // fprintf(stderr, "[M::%s] k::%lu, l::%lu, a0n::%lu, a1n::%lu\n", __func__, k, l, a0n, a1n); + // assert(a1n > 0 && ((uint32_t)a1[0]) == l); + // renew_paf0(src, a0, a0n, a1, a1n); + // renew_paf0(r_src, a0, a0n, a1, a1n); + // } + if(a0n > 1) renew_paf1(r_src, a0, a0n, ng->seq[k].len); + } + free(idx); free(clus.a); free(bb.a); +} + +void push_scaff_node(ma_hit_t_alloc *src, uint64_t v, uint64_t w, uint64_t ol, asg_t *ng) +{ + uint64_t vl = ng->seq[v>>1].len, wl = ng->seq[w>>1].len; + ma_hit_t arc, arc1; + arc.qns = (v>>1)<<32; + if(!(v&1)) { + arc.qns += vl - ol; arc.qe = vl; + } else { + arc.qns += 0; arc.qe = ol; + } + arc.tn = w>>1; + if(!(w&1)) { + arc.ts = 0; arc.te = ol; + } else { + arc.ts = wl - ol; arc.te = wl; + } + + arc.rev = (v^w)&1; arc.el = 0; + arc.ml = arc.no_l_indel = arc.bl = 0; + + add_ma_hit_t_alloc(&(src[v>>1]), &arc); + set_reverse_overlap(&arc1, &arc); + add_ma_hit_t_alloc(&(src[w>>1]), &arc1); +} + +asg_t *gen_ng(ma_ug_t *ug, asg_t *sg, ug_opt_t *uopt, ma_sub_t **cov, R_to_U *ruI, +uint64_t scaffold_len) +{ + ma_utg_t *u; uint64_t i, v, w, m, h, z, raw_v, raw_w, nocc, nv, vx, wx; int32_t r; + asg_arc_t t, *p; asg_arc_t *av = NULL; uint64_t slen = scaffold_len + (uopt->min_ovlp*2); + asg_ext_t ext; memset(&ext, 0, sizeof(ext)); ext.ext = asg_init(); asg_t *ng = ext.ext; + ext.a_n = sg->n_seq; + ext.cnt.n = ext.cnt.m = ext.a_n; + CALLOC(ext.cnt.a, ext.cnt.n);///count + + ext.idx_a.n = ext.idx_a.m = sg->n_seq; + MALLOC(ext.idx_a.a, ext.idx_a.n); + memset(ext.idx_a.a, -1, sizeof(*(ext.idx_a.a))*ext.idx_a.n);//map + fprintf(stderr, "\n+[M::%s] 0\n", __func__); + + for (i = 0; i < ug->g->n_seq; ++i) { + u = &(ug->u.a[i]); + for (m = 0; m < u->n; m++) { + v = u->a[m]>>32; + ext.cnt.a[v>>1]++; + if(ext.cnt.a[v>>1] == 1) { + h = v>>1; ext.idx_a.a[h] = v>>1; + } else { + h = ext.idx_a.n; + kv_push(uint64_t, ext.idx_a, (v>>1)); + } + + z = (h<<1)|(v&1); z <<= 32; z |= ((uint32_t)u->a[m]); + u->a[m] = z; + } + } + + for (i = 0; i < sg->n_seq; ++i) { + asg_seq_set(ng, i, sg->seq[i].len, ext.idx_a.a[i]==((uint64_t)-1)?1:0); + ng->seq[i].c = 0; + if(ext.idx_a.a[i]!=((uint64_t)-1)) assert(ext.idx_a.a[i] == i); + ext.idx_a.a[i] = i;///set for delted read + } + for (; i < ext.idx_a.n; i++) { + asg_seq_set(ng, i, sg->seq[ext.idx_a.a[i]].len, 0); + ng->seq[i].c = 0; assert(!(ng->seq[ext.idx_a.a[i]].del)); + } + ng->r_seq = ng->n_seq; + // fprintf(stderr, "+[M::%s] ng->n_seq::%u, ext.idx_a.n::%u\n", + // __func__, (uint32_t)ng->n_seq, (uint32_t)ext.idx_a.n); + assert(ng->n_seq == ext.idx_a.n); + fprintf(stderr, "\n+[M::%s] 1\n", __func__); + + for (i = 0, nocc = ng->r_seq; i < ug->g->n_seq; ++i) { + u = &(ug->u.a[i]); + for (m = 1; m < u->n; m++) { + v = u->a[m-1]>>32; w = u->a[m]>>32; + raw_v = (ext.idx_a.a[v>>1]<<1)|(v&1); + raw_w = (ext.idx_a.a[w>>1]<<1)|(w&1); + assert((raw_v>>1) < sg->n_seq); + assert((raw_w>>1) < sg->n_seq); + if(gen_spec_edge(sg, uopt, raw_v, raw_w, &t) < 0) { + asg_seq_set(ng, nocc, slen, 0); + ng->seq[nocc].c = 0; + kv_push(uint64_t, ext.idx_a, ((uint64_t)-1)); + nocc++;///a scaffold node + } + } + + v = i<<1; nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); + for (m = 0; m < nv; m++) { + if(av[m].del) continue; + w = av[m].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)); + raw_v = (ext.idx_a.a[vx>>1]<<1)|(vx&1); + raw_w = (ext.idx_a.a[wx>>1]<<1)|(wx&1); + assert((raw_v>>1) < sg->n_seq); + assert((raw_w>>1) < sg->n_seq); + if(vx > wx) continue; + if((vx == wx) && (vx&1)) continue; + if(gen_spec_edge(sg, uopt, raw_v, raw_w, &t) < 0) { + asg_seq_set(ng, nocc, slen, 0); + ng->seq[nocc].c = 0; + kv_push(uint64_t, ext.idx_a, ((uint64_t)-1)); + nocc++;///a scaffold node + } + } + + v = (i<<1)+1; nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); + for (m = 0; m < nv; m++) { + if(av[m].del) continue; + w = av[m].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)); + raw_v = (ext.idx_a.a[vx>>1]<<1)|(vx&1); + raw_w = (ext.idx_a.a[wx>>1]<<1)|(wx&1); + assert((raw_v>>1) < sg->n_seq); + assert((raw_w>>1) < sg->n_seq); + if(vx > wx) continue; + if((vx == wx) && (vx&1)) continue; + if(gen_spec_edge(sg, uopt, raw_v, raw_w, &t) < 0) { + asg_seq_set(ng, nocc, slen, 0); + ng->seq[nocc].c = 0; + kv_push(uint64_t, ext.idx_a, ((uint64_t)-1)); + nocc++;///a scaffold node + } + } + } + fprintf(stderr, "\n+[M::%s] 2\n", __func__); + // fprintf(stderr, "+[M::%s] ng->n_seq::%u, ext.idx_a.n::%u\n", + // __func__, (uint32_t)ng->n_seq, (uint32_t)ext.idx_a.n); + assert(ng->n_seq == ext.idx_a.n); + CALLOC(ng->seq_vis, (ng->n_seq<<1)); + realloc_rdb(&(R_INF), cov, ruI, ext.idx_a.a, ext.idx_a.n, slen, (char *)"scaf", ng, uopt); + + fprintf(stderr, "\n+[M::%s] 3\n", __func__); + update_paf(R_INF.paf, R_INF.reverse_paf, ext.idx_a.a, ext.idx_a.n, sg->n_seq, ng); + fprintf(stderr, "\n+[M::%s] 4\n", __func__); + + for (i = 0, nocc = ng->r_seq; i < ug->g->n_seq; ++i) { + u = &(ug->u.a[i]); + for (m = 1; m < u->n; m++) { + // fprintf(stderr, "[M::%s] i::%lu, m::%lu\n", __func__, i, m); + v = u->a[m-1]>>32; w = u->a[m]>>32; + r = gen_spec_edge(ng, uopt, v, w, &t); + if(r >= 0) { + p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, w^1, v^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + } else { + z = nocc<<1; nocc++; + push_scaff_node(R_INF.paf, v, z, uopt->min_ovlp, ng); + push_scaff_node(R_INF.paf, z, w, uopt->min_ovlp, ng); + + r = gen_spec_edge(ng, uopt, v, z, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, z^1, v^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + + r = gen_spec_edge(ng, uopt, z, w, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, w^1, z^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + } + } + + v = i<<1; nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); + for (m = 0; m < nv; m++) { + if(av[m].del) continue; + w = av[m].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)); + if(vx > wx) continue; + if((vx == wx) && (vx&1)) continue;///it is possible + + r = gen_spec_edge(ng, uopt, vx, wx, &t); + if(r >= 0) { + p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, wx^1, vx^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + } else { + z = nocc<<1; nocc++; + push_scaff_node(R_INF.paf, vx, z, uopt->min_ovlp, ng); + push_scaff_node(R_INF.paf, z, wx, uopt->min_ovlp, ng); + + r = gen_spec_edge(ng, uopt, vx, z, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, z^1, vx^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + + r = gen_spec_edge(ng, uopt, z, wx, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, wx^1, z^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + } + } + + v = (i<<1)+1; nv = asg_arc_n(ug->g, v); av = asg_arc_a(ug->g, v); + for (m = 0; m < nv; m++) { + if(av[m].del) continue; + w = av[m].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)); + if(vx > wx) continue; + if((vx == wx) && (vx&1)) continue;///it is possible + + r = gen_spec_edge(ng, uopt, vx, wx, &t); + if(r >= 0) { + p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, wx^1, vx^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + } else { + z = nocc<<1; nocc++; + push_scaff_node(R_INF.paf, vx, z, uopt->min_ovlp, ng); + push_scaff_node(R_INF.paf, z, wx, uopt->min_ovlp, ng); + + r = gen_spec_edge(ng, uopt, vx, z, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, z^1, vx^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + + r = gen_spec_edge(ng, uopt, z, wx, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + r = gen_spec_edge(ng, uopt, wx^1, z^1, &t); + assert(r >= 0); p = asg_arc_pushp(ng); *p = t; + } + } + } + fprintf(stderr, "\n+[M::%s] 5\n", __func__); + asg_cleanup(ng); ng->r_seq = ng->n_seq; + free(ext.cnt.a); free(ext.idx_a.a); + fprintf(stderr, "[M::%s] nocc::%lu, ng->n_seq::%u, sg->n_seq::%u\n", + __func__, nocc, (uint32_t)ng->n_seq, (uint32_t)sg->n_seq); + assert(nocc == ng->n_seq); + return ng; +} + +void gen_ul_trio_graph(ug_opt_t *uopt, ul_resolve_t *uidx, char *o_file) +{ + output_trio_unitig_graph_ul(uopt, uidx, o_file, FATHER); + output_trio_unitig_graph_ul(uopt, uidx, o_file, MOTHER); +} + +void destroy_integer_t(integer_t *z) +{ + free(z->f.a); free(z->p.a); free(z->o.a); free(z->u.a); + free(z->vis.a); free(z->sc.a); free(z->snp.a); free(z->res_dump.a); + free(z->q.a); free(z->t.a); free(z->b.a); + + free(z->pg.seq.a); free(z->pg.arc.a); free(z->pg.idx.a); free(z->pg.e_idx.a); + free(z->pg.srt_b.ind.a); + free(z->pg.srt_b.stack.a); + free(z->pg.srt_b.res.a); + free(z->pg.srt_b.res2nid.a); + free(z->pg.srt_b.aln.a); + + free(z->pg.bb.a.a); + free(z->pg.bb.S.a); + free(z->pg.bb.T.a); + free(z->pg.bb.b.a); + free(z->pg.bb.e.a); + free(z->pg.bb.us.a); + + free(z->pg.bb.dp.ref.a); + free(z->pg.bb.dp.pat.a); + free(z->pg.bb.dp.pat_cor.a); + free(z->pg.bb.dp.g_flt.a); + free(z->pg.bb.dp.m_dir.a); + free(z->pg.bb.dp.m_score.a); +} + +void usg_t_destroy(usg_t *g) { + uint32_t k; + for (k = 0; k < g->mp.n; k++) { + free(g->mp.a[k].a); + } + free(g->mp.a); + + for (k = 0; k < g->n; k++) { + free(g->a[k].arc[0].a); free(g->a[k].arc[1].a); + free(g->a[k].arc_mm[0].a); free(g->a[k].arc_mm[1].a); + } + free(g->a); + + free(g); +} + + +void destroy_ul_resolve_t(ul_resolve_t *uidx) +{ + ma_ug_destroy(uidx->l1_ug); + uint32_t k; + for (k = 0; k < uidx->str_b.n_thread; k++) { + destroy_integer_t(&(uidx->str_b.buf[k])); + } + free(uidx->str_b.buf); + + for (k = 0; k < uidx->pstr.str.n; k++) { + free(uidx->pstr.str.a[k].a); + } + free(uidx->pstr.str.a); + free(uidx->pstr.occ.a); + free(uidx->pstr.idx.a); + + + free(uidx->uovl.telo); + for (k = 0; k < uidx->uovl.n; k++) { + free(uidx->uovl.a[k].a); + } + free(uidx->uovl.a); + free(uidx->uovl.item_idx); + asg_destroy(uidx->uovl.i_g); + + + free(uidx->uovl.cc.uc); + free(uidx->uovl.cc.hc); + free(uidx->uovl.cc.raw_uc); + if(uidx->uovl.cc.iug_a) { + for (k = 0; k < uidx->uovl.i_ug->u.n; k++) free(uidx->uovl.cc.iug_a[k].a); + } + free(uidx->uovl.cc.iug_a); + free(uidx->uovl.cc.iug_idx); + free(uidx->uovl.cc.iug_b); + + asg_destroy(uidx->uovl.bg.bg); + free(uidx->uovl.bg.w_n); + free(uidx->uovl.bg.a_n); + ma_ug_destroy(uidx->uovl.i_ug); + usg_t_destroy(uidx->uovl.h_usg); + + free(uidx); +} + +static void clear_ma_hit_t_alloc(void *data, long i, int tid) +{ + ma_hit_t_alloc *src = (ma_hit_t_alloc *)data; + ma_hit_t_alloc *z = &(src[i]); uint32_t k; + for (k = 0; k < z->length; k++) z->buffer[k].del = 0; +} + +static void reset_ma_sub_t(void *data, long i, int tid) +{ + sset_aux *s = (sset_aux *)data; + if(s->g && s->g->seq[i].del) s->cov[i].del = 1; + else s->cov[i].del = 0; +} + +void renew_R_to_U(asg_t *ng, ma_hit_t_alloc* src, ma_hit_t_alloc* r_src, int64_t n_read, ma_sub_t *coverage_cut, +R_to_U* ruIndex, int max_hang, int min_ovlp) +{ + sset_aux s; memset(&s, 0, sizeof(s)); + kt_for(asm_opt.thread_num, clear_ma_hit_t_alloc, src, n_read); + kt_for(asm_opt.thread_num, clear_ma_hit_t_alloc, r_src, n_read); + + s.g = NULL; s.cov = coverage_cut; + kt_for(asm_opt.thread_num, reset_ma_sub_t, &s, n_read); + + ma_hit_contained_advance(src, n_read, coverage_cut, ruIndex, max_hang, min_ovlp); + + // s.g = ng; s.cov = coverage_cut; + // kt_for(asm_opt.thread_num, reset_ma_sub_t, &s, n_read); +} + +void ul_realignment_gfa(ug_opt_t *uopt, asg_t *sg, int64_t clean_round, double min_ovlp_drop_ratio, +double max_ovlp_drop_ratio, int64_t max_tip, int64_t max_ul_tip, bub_label_t *b_mask_t, uint32_t is_trio, char *o_file, +ul_renew_t *ropt, const char *bin_file, uint64_t free_uld, uint64_t is_bridg, uint64_t deep_clean) +{ + uint64_t i, bn = 0, idn = 0; uint32_t *bl = NULL; uint8_t *r_het = NULL; bubble_type *bub = NULL; ulg_opt_t uu; + for (i = 0; i < sg->n_seq; ++i) { + if(sg->seq[i].del) continue; + sg->seq[i].c = PRIMARY_LABLE; + } + // fprintf(stderr, "0[M::%s]\n", __func__); + hic_clean(sg); + if(deep_clean) { + // print_debug_gfa(sg, NULL, uopt->coverage_cut, "bclean", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 0); + deep_graph_clean(uopt, sg, 1, is_trio, asm_opt.max_short_tip, asm_opt.min_drop_rate, + MIN(asm_opt.max_drop_rate, 0.7), 0.75, 1, asm_opt.clean_round, 10/**20**/); + // print_debug_gfa(sg, NULL, uopt->coverage_cut, "aclean", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 0); + } + + // fprintf(stderr, "1[M::%s]\n", __func__); + ma_ug_t *init_ug = ul_realignment(uopt, sg, 0, bin_file); + // fprintf(stderr, "2[M::%s]\n", __func__); + // exit(1); + + // char* gfa_name = NULL; MALLOC(gfa_name, strlen(o_file)+strlen(bin_file)+50); + // sprintf(gfa_name, "%s.%s", o_file, bin_file); + // print_debug_gfa(sg, init_ug, uopt->coverage_cut, gfa_name, uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 0); + // print_debug_gfa(sg, init_ug, uopt->coverage_cut, gfa_name, uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 1); + // free(gfa_name); + + + filter_sg_by_ug(sg, init_ug, uopt); + // fprintf(stderr, "-0-[M::%s]\tUL_INF.a[25].rlen::%u\n", __func__, UL_INF.a[25].rlen); + // print_debug_gfa(sg, init_ug, uopt->coverage_cut, "UL.debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 0); + // print_ul_alignment(init_ug, &UL_INF, 47072, "after-0"); + bub = gen_bubble_chain(sg, init_ug, uopt, &r_het, ((asm_opt.polyploidy>2)?1:0)); + // fprintf(stderr, "4[M::%s]\n", __func__); + // print_ul_alignment(init_ug, &UL_INF, 47072, "after-1"); + ul_resolve_t *uidx = init_ul_resolve_t(sg, init_ug, bub, &UL_INF, uopt, r_het); + if(!free_uld) {///backup + bn = UL_INF.n; idn = UL_INF.nid.n; MALLOC(bl, bn); + for (i = 0; i < bn; i++) bl[i] = UL_INF.a[i].rlen; + } + // fprintf(stderr, "5[M::%s]\n", __func__); + // print_ul_alignment(init_ug, &UL_INF, 47072, "after-2"); + // exit(1); + // if(free_uld) { + // print_raw_uls_seq(uidx, asm_opt.output_file_name); + // print_raw_uls_aln(uidx, asm_opt.output_file_name); + // } + + ul_re_correct(uidx, asm_opt.integer_correct_round/**3**/); + init_ulg_opt_t(&uu, uopt, clean_round, asm_opt.min_path_drop_rate, asm_opt.max_path_drop_rate, min_ovlp_drop_ratio, max_ovlp_drop_ratio, 0.55, max_tip, max_ul_tip, b_mask_t, is_trio); + // print_debug_gfa(sg, init_ug, uopt->coverage_cut, "UL.debug0", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 1); + /**ul2ul_idx_t *u2o = **/gen_ul2ul(uidx, uopt, &uu, 0, is_bridg); + // print_ul_alignment(init_ug, &UL_INF, 47072, "after-3"); + + // print_debug_ul("UL.debug", init_ug, sg, uopt->coverage_cut, uopt->sources, uopt->ruIndex, bub, &UL_INF); + + // resolve_dip_bub_chains(uidx); + + // free(r_het); destory_bubbles(bub); free(bub); + // if(free_uld) { + // uidx->uovl.hybrid_ug = gen_hybrid_ug(uidx, uidx->uovl.h_usg); + // // print_debug_gfa(sg, uidx->uovl.hybrid_ug, uopt->coverage_cut, "hybrid_ug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 1); + // print_debug_gfa(sg, uidx->uovl.hybrid_ug, uopt->coverage_cut, "hybrid_ug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 0); + // // print_debug_gfa(sg, init_ug, uopt->coverage_cut, bin_file, uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 0); + // } + // if(is_trio) gen_ul_trio_graph(uopt, uidx, o_file); + // exit(0); + // return uidx->uovl.hybrid_ug; + + asg_t *ng = renew_ng(uidx->uovl.h_usg, init_ug, sg, uopt, ropt->cov, ropt->ruIndex, 16, bin_file); + destory_bubbles(uidx->bub); free(uidx->bub); ma_ug_destroy(init_ug); free(r_het); + destroy_ul_resolve_t(uidx); + if(free_uld) { + destory_all_ul_t(&UL_INF); memset((&UL_INF), 0, sizeof(UL_INF)); + } else { + for (i = 0; i < bn; i++) UL_INF.a[i].rlen = bl[i]; + for (i = bn; i < UL_INF.n; i++) { + free(UL_INF.a[i].N_site.a); free(UL_INF.a[i].r_base.a); + free(UL_INF.a[i].bb.a); memset(&(UL_INF.a[i]), 0, sizeof(UL_INF.a[i])); + } + UL_INF.n = bn; + + for (i = idn; i < UL_INF.nid.n; i++) { + free(UL_INF.nid.a[i].a); memset(&(UL_INF.nid.a[i]), 0, sizeof(UL_INF.nid.a[i])); + } + UL_INF.nid.n = idn; free(bl); + } + + asg_destroy((*(ropt->sg))); (*(ropt->sg)) = ng; + (*(ropt->src)) = R_INF.paf; (*(ropt->r_src)) = R_INF.reverse_paf; + (*(ropt->n_read)) = R_INF.total_reads; (*(ropt->readLen)) = R_INF.read_length; + renew_R_to_U(ng, (*(ropt->src)), (*(ropt->r_src)), (*(ropt->n_read)), (*(ropt->cov)), ropt->ruIndex, ropt->max_hang, ropt->mini_ovlp); + post_rescue(uopt, (*(ropt->sg)), (*(ropt->src)), (*(ropt->r_src)), ropt->ruIndex, ropt->b_mask_t, 0, NULL); + // print_raw_uls_aln(uidx, asm_opt.output_file_name); + // exit(0); +} + +ug_clean_t *init_ug_clean_t(ug_opt_t *uopt, asg_t *sg, uint8_t is_ou, uint8_t is_trio, int64_t max_ext, double len_rat, double ou_rat, int64_t min_ou) +{ + uint64_t i; + ug_clean_t *sl; CALLOC(sl, 1); + ma_ug_t *ug = ma_ug_gen(sg); + for (i = 0; i < ug->g->n_seq; ++i) { + if(ug->g->seq[i].del) continue; + ug->g->seq[i].c = PRIMARY_LABLE; + } + MALLOC(sl->idx, (ug->g->n_seq<<1)); memset(sl->idx, -1, sizeof((*(sl->idx)))*(ug->g->n_seq<<1)); + MALLOC(sl->bid, (ug->g->n_seq<<1)); memset(sl->bid, -1, sizeof((*(sl->bid)))*(ug->g->n_seq<<1)); + sl->uopt = uopt; sl->sg = sg; sl->ug = ug; sl->idx_n = sl->bid_n = ug->g->n_seq<<1; + memset(&(sl->b), 0, sizeof(sl->b)); CALLOC(sl->b.a, (ug->g->n_seq<<1)); + sl->is_ou = is_ou; + sl->is_trio = is_trio; + sl->max_ext = max_ext; + sl->len_rat = len_rat; + sl->ou_rat = ou_rat; + sl->min_ou = min_ou; + if(is_ou) update_ug_ou(sl->ug, sl->sg); + return sl; +} + +void destroy_ug_clean_t(ug_clean_t *sl) +{ + free(sl->idx); free(sl->bid); ma_ug_destroy(sl->ug); + free(sl->b.a); free(sl->b.S.a); free(sl->b.T.a); free(sl->b.b.a); free(sl->b.e.a); +} + +void update_ug_clean_t(ug_clean_t *sl) +{ + uint32_t v, k, i, n_vtx = sl->ug->g->n_seq<<1; + sl->tlen = get_bub_pop_max_dist_advance(sl->ug->g, &(sl->b)); + for (k = 0; k < sl->ug->g->n_seq; ++k) { + sl->idx[k<<1] = sl->idx[(k<<1)+1] = sl->bid[k<<1] = sl->bid[(k<<1)+1] = (uint32_t)-1; + if(sl->ug->g->seq[k].del) continue; + sl->ug->g->seq[k].c = PRIMARY_LABLE; + } + + for (v = 0; v < n_vtx; ++v) { + if(sl->ug->g->seq[v>>1].del) continue; + if(asg_arc_n(sl->ug->g, v) < 2) continue; + if(sl->bid[v] != ((uint32_t)-1)) continue; + if(asg_bub_pop1_primary_trio(sl->ug->g, NULL, v, sl->tlen, &(sl->b), (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (i = 0; i < sl->b.b.n; i++) { + if(sl->b.b.a[i]==v || sl->b.b.a[i]==sl->b.S.a[0]) continue; + sl->bid[sl->b.b.a[i]] = sl->bid[sl->b.b.a[i]^1] = 1; + } + sl->bid[v] = 2; sl->bid[sl->b.S.a[0]^1] = 3; + } + } + + for (v = 0; v < n_vtx; ++v) { + if(sl->bid[v] !=2) continue; + if(asg_bub_pop1_primary_trio(sl->ug->g, NULL, v, sl->tlen, &(sl->b), (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { + //note b.b include end, does not include beg + for (i = 0; i < sl->b.b.n; i++) { + if(sl->b.b.a[i]==v || sl->b.b.a[i]==sl->b.S.a[0]) continue; + sl->idx[sl->b.b.a[i]] = v; + sl->idx[sl->b.b.a[i]^1] = sl->b.S.a[0]^1; + } + sl->idx[v] = v; sl->idx[sl->b.S.a[0]^1] = sl->b.S.a[0]^1; + } + } + memcpy(sl->bid, sl->idx, sizeof((*(sl->bid)))*n_vtx); + // memset(sl->idx, -1, sizeof((*(sl->idx)))*n_vtx); +} + +uint32_t get_best_het_node(ma_ug_t *ug, uint32_t v, uint32_t *bid, uint8_t is_ou, uint8_t is_trio, double len_rat, double ou_rat, uint32_t min_ou) +{ + uint32_t w = (uint32_t)-1, k, nv, kv, ol_max, ol_k; + asg_arc_t *av; uint32_t trioF = (uint32_t)-1, ntrioF = (uint32_t)-1; + if(ug->g->seq[v>>1].del) return (uint32_t)-1; + av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); + for (k = kv = 0; k < nv; k++) { + if(av[k].del) continue; + ///could not connect to the beg/sink node + if((av[k].v>>1)==(bid[v]>>1) || (av[k].v>>1)==(bid[v^1]>>1)) return (uint32_t)-1; + kv++; w = av[k].v; + } + if(kv < 2) return w;///kv == 0, return (uint32_t)-1; kv == 1, return node; + // if(v == 351) fprintf(stderr, "-0-[M::%s]\tutg%.6ul(%c)\tv::%u\tkv::%u\n", __func__, (v>>1)+1, "+-"[v&1], v, kv); + + if(is_trio) { + trioF = get_ug_tip_trio_infor(ug, v^1); + ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); + } + + ol_max = 0; ol_k = (uint32_t)-1; + for (k = 0; k < nv; ++k) { + if(av[k].del) continue; + // if(is_trio && get_ug_tip_trio_infor(ug, av[k].v) == ntrioF) continue; + if(ol_max < av[k].ol) ol_max = av[k].ol, ol_k = k; + } + // if(v == 351) fprintf(stderr, "-1-[M::%s]\tutg%.6ul(%c)\tv::%u\tol_k::%u\n", __func__, (v>>1)+1, "+-"[v&1], v, ol_k); + if(ol_k == (uint32_t)-1) return (uint32_t)-1; + for (k = 0; k < nv; ++k) { + if(av[k].del || k == ol_k) continue; + // if(is_trio && get_ug_tip_trio_infor(ug, av[k].v) == ntrioF) continue; + if(av[k].ol > av[ol_k].ol*len_rat) return (uint32_t)-1; + if((is_ou) && (av[k].ou > min_ou) && ((av[k].ou) > (av[ol_k].ou*ou_rat))) return (uint32_t)-1; + } + if(is_trio && get_ug_tip_trio_infor(ug, av[ol_k].v) == ntrioF) return (uint32_t)-1; + // if(v == 351) fprintf(stderr, "-2-[M::%s]\tutg%.6ul(%c)\tv::%u\tav[ol_k].v::%u\n", __func__, (v>>1)+1, "+-"[v&1], v, av[ol_k].v); + return av[ol_k].v; +} + +static void cal_bub_best(void *data, long i, int tid) +{ + ug_clean_t *sl = (ug_clean_t *)data; + ma_ug_t *ug = sl->ug; uint32_t v, w; + sl->idx[i<<1] = sl->idx[(i<<1)+1] = (uint32_t)-1; + if(ug->g->seq[i].del) return; + if((sl->bid[i<<1] == (uint32_t)-1) || (sl->bid[(i<<1)+1] == (uint32_t)-1)) return;///not within a bubble + + v = i<<1; + if(sl->bid[v] != v) {///not the beg/sink node + w = get_best_het_node(ug, v, sl->bid, sl->is_ou, sl->is_trio, sl->len_rat, sl->ou_rat, sl->min_ou); + // if(v == 352) fprintf(stderr, "-v-[M::%s]\tutg%.6ul(%c)\tv::%u\tw::%u\n", __func__, (v>>1)+1, "+-"[v&1], v, w); + if((w != (uint32_t)-1) && ((v^1) == get_best_het_node(ug, w^1, sl->bid, sl->is_ou, sl->is_trio, sl->len_rat, sl->ou_rat, sl->min_ou))) { + sl->idx[v] = w; + } + } + + v = (i<<1)+1; + if(sl->bid[v] != v) {///not the beg/sink node + w = get_best_het_node(ug, v, sl->bid, sl->is_ou, sl->is_trio, sl->len_rat, sl->ou_rat, sl->min_ou); + if((w != (uint32_t)-1) && ((v^1) == get_best_het_node(ug, w^1, sl->bid, sl->is_ou, sl->is_trio, sl->len_rat, sl->ou_rat, sl->min_ou))) { + sl->idx[v] = w; + } + } +} + +uint32_t usg_topocut_aux_unambi1(asg_t *g, uint32_t v) +{ + asg_arc_t *av = asg_arc_a(g, v); + uint32_t i, nv = asg_arc_n(g, v); + uint32_t k = nv, kv; + for (i = 0, kv = 0; i < nv; ++i) + if (!av[i].del) ++kv, k = i; + if (kv != 1) return (uint32_t)-1; + return av[k].v; +} + +int usg_topocut_aux_del(ma_ug_t *ug, uint32_t v, int max_ext, asg64_v *b) +{ + int32_t n_ext; + for (n_ext = 0; n_ext < max_ext && v != (uint32_t)-1; ) { + if (usg_topocut_aux_unambi1(ug->g, v^1) == (uint32_t)-1) break; + if(b) {kv_push(uint64_t, *b, v);} n_ext += ug->u.a[v>>1].n; + v = usg_topocut_aux_unambi1(ug->g, v); + } + return n_ext; +} + +#define is_best_arc(sl, v, w) (((sl).idx[(v)]==(w))&&((sl).idx[((w)^1)]==((v)^1))) + +inline void asg_arc_del_by_ug(asg_t *sg, ma_ug_t *ug, uint32_t uv, uint32_t uw, uint32_t del) +{ + uint32_t rv, rw, i, nv; asg_arc_t *av; + if(uv&1) rv = ug->u.a[uv>>1].start^1; + else rv = ug->u.a[uv>>1].end^1; + + if(uw&1) rw = ug->u.a[uw>>1].end; + else rw = ug->u.a[uw>>1].start; + + av = asg_arc_a(sg, rv); + nv = asg_arc_n(sg, rv); + for (i = 0; i < nv; i++) { + if(av[i].v == rw) break; + } + assert(i < nv); + av[i].del = del; +} + +uint32_t cal_utg_occ(ma_ug_t *ug, uint32_t begNode) +{ + uint32_t v = begNode, w, kv, occ = 0; ma_utg_t *u; + + while (1) { + kv = get_real_length(ug->g, v, NULL); + u = &(ug->u.a[v>>1]); occ += u->n; + if(kv!=1) break; + ///kv must be 1 here + kv = get_real_length(ug->g, v, &w); + if(get_real_length(ug->g, w^1, NULL)!=1) break; + v = w; + if(v == begNode) break; + } + return occ; +} + +void cal_bub_best_by_len(ug_clean_t *sl, asg64_v *in, uint32_t max_ext, uint32_t is_trio, uint32_t is_ou, double len_rat, double ou_rat, uint32_t min_ou, +uint32_t min_node) +{ + // fprintf(stderr, "[M::%s]\tStart\n", __func__); + ma_ug_t *ug = sl->ug; asg_t *g = sl->ug->g; uint32_t ol_max, ou_max, lnid; + uint32_t v, w, n_vtx = (g->n_seq<<1), nv, nw, i, k, z, kv, kw, bb, to_del, bn, tip; + asg64_v tx = {0,0,0}, *b = NULL; asg_arc_t *av = NULL, *aw = NULL, *ve = NULL, *we = NULL; ma_utg_t *u; + uint32_t trioF = (uint32_t)-1, ntrioF = (uint32_t)-1, mm_ol, mm_ou, cnt = 0, del_v, del_w; + + if(in) b = in; + else b = &tx; + b->n = 0; + + for (v = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + av = asg_arc_a(g, v); + nv = asg_arc_n(g, v); + if (nv < 2) continue; + + for (i = kv = bb = 0; i < nv; ++i) { + if(av[i].del) continue; + if(is_best_arc((*sl), v, av[i].v)) bb++; + kv++; + } + if((kv < 2) || (!bb) || (kv<=bb)) continue;///it is impossible that kv <= bv + + for (i = 0; i < nv; ++i) { + if(av[i].del) continue; + if(is_best_arc((*sl), v, av[i].v)) continue; + kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); + } + } + + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + if(g->arc[(uint32_t)b->a[k]].del) continue; + + v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; + if(g->seq[v>>1].del || g->seq[w>>1].del) continue; + nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); + av = asg_arc_a(g, v); aw = asg_arc_a(g, w); + if(nv<=1 && nw <= 1) continue; + + if(is_trio) { + if(get_arcs(g, v, NULL, 0)<=1 && get_arcs(g, w, NULL, 0)<=1) continue;///speedup + trioF = get_ug_tip_trio_infor(ug, v^1); + ntrioF = (trioF==FATHER? MOTHER : (trioF==MOTHER? FATHER : (uint32_t)-1)); + } + + ve = &(g->arc[(uint32_t)b->a[k]]); + for (i = 0; i < nw; ++i) { + if (aw[i].v == (v^1)) { + we = &(aw[i]); + break; + } + } + ///mm_ol and mm_ou are used to make edge with long indel more easy to be cutted + mm_ol = MIN(ve->ol, we->ol); mm_ou = MIN(ve->ou, we->ou); lnid = 0; + + for (i = kv = ol_max = ou_max = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + if(is_trio && get_ug_tip_trio_infor(ug, av[i].v) == ntrioF) continue; + if(ol_max < av[i].ol) ol_max = av[i].ol; + if(ou_max < av[i].ou) ou_max = av[i].ou; + if((!lnid) && ((is_best_arc((*sl), v, av[i].v)))) { + if((cal_utg_occ(ug, v^1) >= min_node) || (cal_utg_occ(ug, av[i].v) >= min_node)) lnid = 1; + } + } + if (kv < 1) continue; + if (kv >= 2) { + if (mm_ol > ol_max*len_rat) continue; + if ((is_ou) && (mm_ou > min_ou) && (mm_ou > (ou_max*ou_rat))) continue; + } + + + for (i = kw = ol_max = ou_max = 0; i < nw; ++i) { + if(aw[i].del) continue; + kw++; + if(is_trio && get_ug_tip_trio_infor(ug, aw[i].v) == ntrioF) continue; + if(ol_max < aw[i].ol) ol_max = aw[i].ol; + if(ou_max < aw[i].ou) ou_max = aw[i].ou; + if((!lnid) && ((is_best_arc((*sl), w, aw[i].v)))) { + if((cal_utg_occ(ug, w^1) >= min_node) || (cal_utg_occ(ug, aw[i].v) >= min_node)) lnid = 1; + } + } + if (kw < 1) continue; + if (kw >= 2) { + if (mm_ol > ol_max*len_rat) continue; + if ((is_ou) && (mm_ou > min_ou) && (mm_ou > (ou_max*ou_rat))) continue; + } + + if (kv <= 1 && kw <= 1) continue; + if(!lnid) continue; + + to_del = 0; del_v = del_w = (uint32_t)-1; tip = 0; + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + // tip = asg_topocut_aux(g, w^1, max_ext); + tip = usg_topocut_aux_del(ug, w^1, max_ext, NULL); + if (tip < max_ext) { + to_del = 1; del_w = w^1; + } + } else if (kv == 1) { + // tip = asg_topocut_aux(g, v^1, max_ext); + tip = usg_topocut_aux_del(ug, v^1, max_ext, NULL); + if (tip < max_ext) { + to_del = 1; del_v = v^1; + } + } + + + if (to_del) { + bn = b->n; + if(del_v != ((uint32_t)-1)) usg_topocut_aux_del(ug, del_v, max_ext, b); + if(del_w != ((uint32_t)-1)) usg_topocut_aux_del(ug, del_w, max_ext, b); + for (i = bn; i < b->n; i++) { + u = &(ug->u.a[b->a[i]>>1]); + if(u->m == 0) continue; + for (z = 0; z < u->n; z++) asg_seq_del(sl->sg, u->a[z]>>33); + asg_seq_del(ug->g, (b->a[i]>>1)); + if(u->m) { + u->m = u->n = 0; free(u->a); u->a = NULL; + } + } + // assert(tip == (b->n-bn)); + b->n = bn; + + ve->del = we->del = 1, ++cnt; + asg_arc_del_by_ug(sl->sg, ug, ve->ul>>32, ve->v, 1); + asg_arc_del_by_ug(sl->sg, ug, we->ul>>32, we->v, 1); + + } + } + + if(!in) free(tx.a); + if (cnt > 0) { + asg_cleanup(g); asg_cleanup(sl->sg); + } + // fprintf(stderr, "[M::%s]\tEnd\n", __func__); +} + +/** +void cal_bub_best_by_topo(ug_clean_t *sl, asg64_v *in, uint32_t max_ext, uint32_t is_trio, uint32_t is_ou, double len_rat, double ou_rat, uint32_t min_ou, uint32_t long_tip) +{ + // fprintf(stderr, "[M::%s]\tStart\n", __func__); + ma_ug_t *ug = sl->ug; asg_t *g = sl->ug->g; uint32_t ol_max, ou_max; + uint32_t v, w, n_vtx = (g->n_seq<<1), nv, nw, i, k, z, kv, kw, to_del, bn, tip, avi, awi; + asg64_v tx = {0,0,0}, *b = NULL; asg_arc_t *av, *aw, *ve, *we; ma_utg_t *u; + uint32_t trioF = (uint32_t)-1, mm_ol, mm_ou, cnt = 0, del_v, del_w; + + if(in) b = in; + else b = &tx; + b->n = 0; + + for (v = 0; v < n_vtx; ++v) { + if (g->seq[v>>1].del) continue; + if((sl->bid[v] == (uint32_t)-1) || (sl->bid[v^1] == (uint32_t)-1)) continue;///not within a bubble + + av = asg_arc_a(g, v); + nv = asg_arc_n(g, v); + if (nv < 2) continue; + + for (i = kv = 0; i < nv; ++i) { + if(av[i].del) continue; + ///could not connect to the beg/sink node + if((av[k].v>>1)==(sl->bid[v]>>1) || (av[k].v>>1)==(sl->bid[v^1]>>1)) break; + kv++; + } + if(kv < 2 || i < nv) continue;///it is impossible that kv <= bv + + for (i = 0; i < nv; ++i) { + if(av[i].del) continue; + kv_push(uint64_t, *b, (((uint64_t)av[i].ol)<<32) | ((uint64_t)(av-g->arc+i))); + } + } + + radix_sort_srt64(b->a, b->a + b->n); + for (k = 0; k < b->n; k++) { + if(g->arc[(uint32_t)b->a[k]].del) continue; + + v = g->arc[(uint32_t)b->a[k]].ul>>32; w = g->arc[(uint32_t)b->a[k]].v^1; + if(g->seq[v>>1].del || g->seq[w>>1].del) continue; + nv = asg_arc_n(g, v); nw = asg_arc_n(g, w); + av = asg_arc_a(g, v); aw = asg_arc_a(g, w); + if(nv < 2 || nw < 2) continue; + kv = get_arcs(g, v, NULL, 0); kw = get_arcs(g, w, NULL, 0); + if(kv < 2 || kw < 2) continue; + + if(is_trio) { + trioF = get_ug_tip_trio_infor(ug, v^1); + if(trioF == FATHER || trioF == MOTHER) { + if(get_ug_tip_trio_infor(ug, w^1) == trioF) continue; + } + } + + avi = awi = (uint32_t)-1; + + avi = ((uint32_t)b->a[k]) - ((uint64_t)(av-g->arc)); + ve = &(g->arc[(uint32_t)b->a[k]]); + + for (i = 0; i < nw; ++i) { + if (aw[i].v == (v^1)) { + we = &(aw[i]); awi = i; + break; + } + } + + for (i = kv = ol_max = ou_max = 0; i < nv; ++i) { + if(av[i].del) continue; + } + + ///mm_ol and mm_ou are used to make edge with long indel more easy to be cutted + mm_ol = MIN(ve->ol, we->ol); mm_ou = MIN(ve->ou, we->ou); + + for (i = kv = ol_max = ou_max = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + if(is_trio && get_ug_tip_trio_infor(ug, av[i].v) == ntrioF) continue; + if(ol_max < av[i].ol) ol_max = av[i].ol; + if(ou_max < av[i].ou) ou_max = av[i].ou; + } + if (kv < 1) continue; + if (kv >= 2) { + if (mm_ol > ol_max*len_rat) continue; + if ((is_ou) && (mm_ou > min_ou) && (mm_ou > (ou_max*ou_rat))) continue; + } + + + for (i = kw = ol_max = ou_max = 0; i < nw; ++i) { + if(aw[i].del) continue; + kw++; + if(is_trio && get_ug_tip_trio_infor(ug, aw[i].v) == ntrioF) continue; + if(ol_max < aw[i].ol) ol_max = aw[i].ol; + if(ou_max < aw[i].ou) ou_max = aw[i].ou; + } + if (kw < 1) continue; + if (kw >= 2) { + if (mm_ol > ol_max*len_rat) continue; + if ((is_ou) && (mm_ou > min_ou) && (mm_ou > (ou_max*ou_rat))) continue; + } + + if (kv <= 1 && kw <= 1) continue; + + to_del = 0; del_v = del_w = (uint32_t)-1; tip = 0; + if (kv > 1 && kw > 1) { + to_del = 1; + } else if (kw == 1) { + tip = asg_topocut_aux(g, w^1, max_ext); + if (tip < max_ext) { + to_del = 1; del_w = w^1; + } + } else if (kv == 1) { + tip = asg_topocut_aux(g, v^1, max_ext); + if (tip < max_ext) { + to_del = 1; del_v = v^1; + } + } + + if (to_del) { + bn = b->n; + if(del_v != ((uint32_t)-1)) usg_topocut_aux_del(ug, del_v, max_ext, b); + if(del_w != ((uint32_t)-1)) usg_topocut_aux_del(ug, del_w, max_ext, b); + for (i = bn; i < b->n; i++) { + u = &(ug->u.a[b->a[i]>>1]); + if(u->m == 0) continue; + for (z = 0; z < u->n; z++) asg_seq_del(sl->sg, u->a[z]>>33); + asg_seq_del(ug->g, (b->a[i]>>1)); + if(u->m) { + u->m = u->n = 0; free(u->a); u->a = NULL; + } + } + // assert(tip == (b->n-bn)); + b->n = bn; + + ve->del = we->del = 1, ++cnt; + asg_arc_del_by_ug(sl->sg, ug, ve->ul>>32, ve->v, 1); + asg_arc_del_by_ug(sl->sg, ug, we->ul>>32, we->v, 1); + + } + } + + if(!in) free(tx.a); + if (cnt > 0) { + asg_cleanup(g); asg_cleanup(sl->sg); + } + // fprintf(stderr, "[M::%s]\tEnd\n", __func__); +} +**/ + + + +void deep_graph_clean(ug_opt_t *uopt, asg_t *sg, uint8_t is_ou, uint8_t is_trio, int64_t max_ext, +double min_ovlp_drop_ratio, double max_ovlp_drop_ratio, double ou_rat, int64_t min_ou, int64_t clean_round, int64_t long_tip) +{ + ug_clean_t *sl; asg64_v b; double step; int64_t i; + kv_init(b); hic_clean_adv(sg, uopt); + step = (clean_round==1?max_ovlp_drop_ratio:((max_ovlp_drop_ratio-min_ovlp_drop_ratio)/(clean_round-1))); + sl = init_ug_clean_t(uopt, sg, is_ou, is_trio, max_ext, min_ovlp_drop_ratio, ou_rat, min_ou); + + // print_debug_gfa(sg, NULL, uopt->coverage_cut, "debug", uopt->sources, uopt->ruIndex, uopt->max_hang, uopt->min_ovlp, 0, 0, 0); + for (i = 0, sl->len_rat = min_ovlp_drop_ratio; i < clean_round; i++, sl->len_rat += step) { + if(sl->len_rat > max_ovlp_drop_ratio) sl->len_rat = max_ovlp_drop_ratio; + update_ug_clean_t(sl); + kt_for(asm_opt.thread_num, cal_bub_best, sl, sl->ug->g->n_seq); + cal_bub_best_by_len(sl, &b, max_ext, is_trio, sl->is_ou, sl->len_rat, sl->ou_rat, min_ou, long_tip); + } + + // if(is_ou) { + // uint64_t k; sl->is_ou = 0; + // for (k = 0; k < sl->ug->g->n_arc; k++) sl->ug->g->arc[k].ou = 0; + // max_ovlp_drop_ratio = 0.6; + // if(max_ovlp_drop_ratio > min_ovlp_drop_ratio) { + // step = (clean_round==1?max_ovlp_drop_ratio:((max_ovlp_drop_ratio-min_ovlp_drop_ratio)/(clean_round-1))); + // for (i = 0, sl->len_rat = min_ovlp_drop_ratio; i < clean_round; i++, sl->len_rat += step) { + // if(sl->len_rat > max_ovlp_drop_ratio) sl->len_rat = max_ovlp_drop_ratio; + // update_ug_clean_t(sl); + // kt_for(asm_opt.thread_num, cal_bub_best, sl, sl->ug->g->n_seq); + // cal_bub_best_by_len(sl, &b, max_ext, is_trio, sl->is_ou, sl->len_rat, sl->ou_rat, min_ou); + // } + // } + // } + + // update_ug_clean_t(sl); + // cal_bub_best_by_topo(sl, &b, max_ext, is_trio, sl->is_ou, sl->len_rat, sl->ou_rat, min_ou, long_tip); + + kv_destroy(b); destroy_ug_clean_t(sl); free(sl); + hic_clean_adv(sg, uopt); +} diff --git a/gfa_ut.h b/gfa_ut.h index 9c73fa8..57c6f68 100644 --- a/gfa_ut.h +++ b/gfa_ut.h @@ -1,45 +1,45 @@ -#ifndef __GFA_UT__ -#define __GFA_UT__ -#include "Overlaps.h" -#include "hic.h" - -#define is_contain_r(ri, z) (((z)<(ri).len)&&((ri).index[(z)]!=(uint32_t)(-1))&&(!((ri).index[(z)]>>31))) - -typedef struct { - asg_t *g; - ma_hit_t_alloc *src; - ma_sub_t *cov; - R_to_U* ruIndex; - int64_t max_hang; - int64_t min_ovlp; - int64_t ul_occ; -} sset_aux; - -void ul_clean_gfa(ug_opt_t *uopt, asg_t *sg, ma_hit_t_alloc *src, ma_hit_t_alloc *rev, R_to_U* rI, int64_t clean_round, double min_ovlp_drop_ratio, double max_ovlp_drop_ratio, -double ou_drop_rate, int64_t max_tip, int64_t gap_fuzz, bub_label_t *b_mask_t, int32_t is_ou, int32_t is_trio, uint32_t ou_thres, uint8_t *cmk, char *o_file); -uint32_t asg_arc_cut_tips(asg_t *g, uint32_t max_ext, asg64_v *in, uint32_t is_ou, R_to_U *ru, telo_end_t *te); -void asg_iterative_semi_circ(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, uint32_t normal_len, uint32_t pop_chimer, asg64_v *dbg, telo_end_t *te); -void asg_arc_cut_chimeric(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, uint32_t ou_thres, telo_end_t *te); -void asg_arc_cut_inexact(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, int32_t max_ext, uint32_t is_ou, uint32_t is_trio, uint32_t min_diff, float ou_rat/**, asg64_v *dbg**/); -void asg_arc_cut_length(asg_t *g, asg64_v *in, int32_t max_ext, float len_rat, float ou_rat, uint32_t is_ou, uint32_t is_trio, -uint32_t is_topo, uint32_t min_diff, uint32_t min_ou, ma_hit_t_alloc *rev, R_to_U* rI, uint32_t *max_drop_len); -void asg_arc_cut_bub_links(asg_t *g, asg64_v *in, float len_rat, float sec_len_rat, float ou_rat, uint32_t is_ou, uint64_t check_dist, ma_hit_t_alloc *rev, R_to_U* rI, int32_t max_ext); -void asg_arc_cut_complex_bub_links(asg_t *g, asg64_v *in, float len_rat, float ou_rat, uint32_t is_ou, bub_label_t *b_mask_t); -uint32_t asg_cut_large_indel(asg_t *g, asg64_v *in, int32_t max_ext, float ou_rat, uint32_t is_ou, uint32_t min_diff); -uint32_t asg_cut_semi_circ(asg_t *g, uint32_t lim_len, uint32_t is_clean); -void ul_realignment_gfa(ug_opt_t *uopt, asg_t *sg, int64_t clean_round, double min_ovlp_drop_ratio, -double max_ovlp_drop_ratio, int64_t max_tip, int64_t max_ul_tip, bub_label_t *b_mask_t, uint32_t is_trio, char *o_file, ul_renew_t *ropt, const char *bin_file, uint64_t free_uld, uint64_t is_bridg, uint64_t deep_clean); -void recover_contain_g(asg_t *g, ma_hit_t_alloc *src, R_to_U* ruIndex, int64_t max_hang, int64_t min_ovlp, int64_t ul_occ); -void normalize_gou(asg_t *g); -void prt_specfic_sge(asg_t *g, uint32_t src, uint32_t dst, const char* cmd); -asg_t *gen_ng(ma_ug_t *ug, asg_t *sg, ug_opt_t *uopt, ma_sub_t **cov, R_to_U *ruI, uint64_t scaffold_len); -void post_rescue(ug_opt_t *uopt, asg_t *sg, ma_hit_t_alloc *src, ma_hit_t_alloc *rev, R_to_U* rI, bub_label_t *b_mask_t, long long no_trio_recover, uint8_t *cmk); -// void print_raw_u2rgfa_seq(all_ul_t *aln, R_to_U* rI, uint32_t is_detail); -bubble_type *gen_bubble_chain(asg_t *sg, ma_ug_t *ug, ug_opt_t *uopt, uint8_t **ir_het, uint8_t avoid_het); -void filter_sg_by_ug(asg_t *rg, ma_ug_t *ug, ug_opt_t *uopt); -void ug_ext_gfa(ug_opt_t *uopt, asg_t *sg, uint32_t max_len); -void update_sg_uo(asg_t *g, ma_hit_t_alloc *src); -uint32_t get_arcs(asg_t *g, uint32_t v, uint32_t* idx, uint32_t idx_n); -uint64_t ug_occ_w(uint64_t is, uint64_t ie, ma_utg_t *u); - -#endif +#ifndef __GFA_UT__ +#define __GFA_UT__ +#include "Overlaps.h" +#include "hic.h" + +#define is_contain_r(ri, z) (((z)<(ri).len)&&((ri).index[(z)]!=(uint32_t)(-1))&&(!((ri).index[(z)]>>31))) + +typedef struct { + asg_t *g; + ma_hit_t_alloc *src; + ma_sub_t *cov; + R_to_U* ruIndex; + int64_t max_hang; + int64_t min_ovlp; + int64_t ul_occ; +} sset_aux; + +void ul_clean_gfa(ug_opt_t *uopt, asg_t *sg, ma_hit_t_alloc *src, ma_hit_t_alloc *rev, R_to_U* rI, int64_t clean_round, double min_ovlp_drop_ratio, double max_ovlp_drop_ratio, +double ou_drop_rate, int64_t max_tip, int64_t gap_fuzz, bub_label_t *b_mask_t, int32_t is_ou, int32_t is_trio, uint32_t ou_thres, uint8_t *cmk, char *o_file); +uint32_t asg_arc_cut_tips(asg_t *g, uint32_t max_ext, asg64_v *in, uint32_t is_ou, R_to_U *ru, telo_end_t *te); +void asg_iterative_semi_circ(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, uint32_t normal_len, uint32_t pop_chimer, asg64_v *dbg, telo_end_t *te); +void asg_arc_cut_chimeric(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, uint32_t ou_thres, telo_end_t *te); +void asg_arc_cut_inexact(asg_t *g, ma_hit_t_alloc* src, asg64_v *in, int32_t max_ext, uint32_t is_ou, uint32_t is_trio, uint32_t min_diff, float ou_rat/**, asg64_v *dbg**/); +void asg_arc_cut_length(asg_t *g, asg64_v *in, int32_t max_ext, float len_rat, float ou_rat, uint32_t is_ou, uint32_t is_trio, +uint32_t is_topo, uint32_t min_diff, uint32_t min_ou, ma_hit_t_alloc *rev, R_to_U* rI, uint32_t *max_drop_len); +void asg_arc_cut_bub_links(asg_t *g, asg64_v *in, float len_rat, float sec_len_rat, float ou_rat, uint32_t is_ou, uint64_t check_dist, ma_hit_t_alloc *rev, R_to_U* rI, int32_t max_ext); +void asg_arc_cut_complex_bub_links(asg_t *g, asg64_v *in, float len_rat, float ou_rat, uint32_t is_ou, bub_label_t *b_mask_t); +uint32_t asg_cut_large_indel(asg_t *g, asg64_v *in, int32_t max_ext, float ou_rat, uint32_t is_ou, uint32_t min_diff); +uint32_t asg_cut_semi_circ(asg_t *g, uint32_t lim_len, uint32_t is_clean); +void ul_realignment_gfa(ug_opt_t *uopt, asg_t *sg, int64_t clean_round, double min_ovlp_drop_ratio, +double max_ovlp_drop_ratio, int64_t max_tip, int64_t max_ul_tip, bub_label_t *b_mask_t, uint32_t is_trio, char *o_file, ul_renew_t *ropt, const char *bin_file, uint64_t free_uld, uint64_t is_bridg, uint64_t deep_clean); +void recover_contain_g(asg_t *g, ma_hit_t_alloc *src, R_to_U* ruIndex, int64_t max_hang, int64_t min_ovlp, int64_t ul_occ); +void normalize_gou(asg_t *g); +void prt_specfic_sge(asg_t *g, uint32_t src, uint32_t dst, const char* cmd); +asg_t *gen_ng(ma_ug_t *ug, asg_t *sg, ug_opt_t *uopt, ma_sub_t **cov, R_to_U *ruI, uint64_t scaffold_len); +void post_rescue(ug_opt_t *uopt, asg_t *sg, ma_hit_t_alloc *src, ma_hit_t_alloc *rev, R_to_U* rI, bub_label_t *b_mask_t, long long no_trio_recover, uint8_t *cmk); +// void print_raw_u2rgfa_seq(all_ul_t *aln, R_to_U* rI, uint32_t is_detail); +bubble_type *gen_bubble_chain(asg_t *sg, ma_ug_t *ug, ug_opt_t *uopt, uint8_t **ir_het, uint8_t avoid_het); +void filter_sg_by_ug(asg_t *rg, ma_ug_t *ug, ug_opt_t *uopt); +void ug_ext_gfa(ug_opt_t *uopt, asg_t *sg, uint32_t max_len); +void update_sg_uo(asg_t *g, ma_hit_t_alloc *src); +uint32_t get_arcs(asg_t *g, uint32_t v, uint32_t* idx, uint32_t idx_n); +uint64_t ug_occ_w(uint64_t is, uint64_t ie, ma_utg_t *u); + +#endif diff --git a/hic.cpp b/hic.cpp index fa1b3e6..10bcab3 100644 --- a/hic.cpp +++ b/hic.cpp @@ -1,18396 +1,18396 @@ -#define __STDC_LIMIT_MACROS -#include "float.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" -#include "horder.h" -#include "gfa_ut.h" -KSEQ_INIT(gzFile, gzread) -KDQ_INIT(uint64_t) - - -#define OFFSET_RATE 0.000000001 -#define OFFSET_SECOND_RATE 0.0000000001 -#define SCALL 10000 -#define OFFSET_RATE_MAX_W 6.90675477865*SCALL -#define OFFSET_RATE_MIN_W 4.0000003e-10*SCALL - -#define HIC_COUNTER_BITS 12 -#define HIC_MAX_COUNT ((1<>HIC_COUNTER_BITS == (b)>>HIC_COUNTER_BITS) -#define hic_ct_hash(a) ((a)>>HIC_COUNTER_BITS) -KHASHL_MAP_INIT(static klib_unused, hc_pt_t, hc_pt, uint64_t, uint64_t, hic_ct_hash, hic_ct_eq) - -#define u_trans_m_key(a) (((uint64_t)((a).qn)<<32) | ((uint64_t)((a).tn))) -KRADIX_SORT_INIT(u_trans_m, u_trans_t, u_trans_m_key, 8) - -#define u_trans_occ_key(a) ((a).occ) -KRADIX_SORT_INIT(u_trans_occ, u_trans_t, u_trans_occ_key, member_size(u_trans_t, occ)) - -#define is_hom_hit(a) ((a).id == (uint64_t)-1) -#define HC_PT_MA 65 - -typedef struct { - kv_gg_status sg; - uint64_t xs; -} psg_t; - -typedef struct{ - kvec_t(char) name; - kvec_t(uint64_t) name_Len; - kvec_t(char) r; - kvec_t(uint64_t) r_Len; - uint64_t idx; -} reads_t; - - -typedef struct{ - kvec_t(hc_edge_warp) rGraph; - kvec_t(uint64_t) order; - pdq pq; - kvec_t(uint8_t) rGraphSet; - kvec_t(uint8_t) rGraphVis; - kvec_t(uint8_t) utgVis; - kvec_t(uint8_t) bmerVis; - kdq_t(uint64_t) *q; - kvec_t(uint32_t) parent; - kvec_t(double) p_weight; - const uint64_t* enzymes; - uint64_t uID_mode, uID_shift, n, src, dest, n_e, c_e; - int p_mer, a_mer, b_mer; -} min_cut_t; - - -typedef struct{ - kvec_t(uint32_t) a; - uint32_t h[2]; - uint8_t full_bub; - int status[2]; - double weight[2], weight_convex; -}partition_warp; - -typedef struct{ - size_t n, m; - partition_warp* a; - uint32_t* index; -}G_partition; - -typedef struct{ - kvec_t(uint8_t) vis; - double weight; - long long bid, uid, chainID; -}block_phase_type; - -typedef struct{ - uint64_t n; - uint8_t* lock; - uint32_t* hap; - uint32_t m[3]; - uint32_t label, label_add, label_shift; - hc_links* link; - G_partition g_p; - G_partition group_g_p; - kvec_t(double) label_buffer; - block_phase_type b; -}H_partition; - -typedef struct { - uint32_t p; // the optimal parent vertex - uint32_t d; // the shortest distance from the initial vertex - uint32_t nc; // max count of reads, no matter positive or negative - double nh, w[2]; - uint32_t uc, ac; // used vertex/allowed vertex - uint32_t r:31, s:1; // r: the number of remaining incoming arc; s: state - //s: state, s=0, this edge has not been visited, otherwise, s=1 -} bub_p_t; - -typedef struct { - ///all information for each node - bub_p_t *a; - kvec_t(uint32_t) S; // set of vertices without parents, nodes with all incoming edges visited - kvec_t(uint32_t) T; // set of tips - kvec_t(uint32_t) b; // visited vertices - kvec_t(uint32_t) e; // visited edges/arcs - uint32_t exist_hap_label; -} bub_p_t_warp; - - -typedef struct { - hc_pt_t *h; - uint64_t n; - uint64_t *a; - khint_t end;///end of total idx -} hc_pt1_t; - -typedef struct { - ma_ug_t* ug; - asg_t* read_g; - ///hc_links* link; - trans_chain* t_ch; - uint64_t uID_bits; - uint64_t uID_mode; - uint64_t pos_bits; - uint64_t pos_mode; - uint64_t rev_mode; - uint64_t k; - uint64_t hap_cnt; - - - uint64_t pre; - uint64_t tot; - uint64_t tot_pos; - uint64_t up_bound, low_bound; - hc_pt1_t* idx_buf; - long double a, b, frac, max_d; -} ha_ug_index; - -typedef struct { // data structure for each step in kt_pipeline() - uint64_t key, pos; -} ch_buf_t; - -typedef struct { - kvec_t(uint64_t) a; -} kvec_cnt; - -typedef struct { - kvec_t(ch_buf_t) a; -} kvec_pos; - -typedef struct { // global data structure for kt_pipeline() - int is_cnt; - uint64_t buf_bytes; - ha_ug_index *h; - kvec_cnt* cnt; - kvec_pos* buf; - uint64_t n_thread; -} pldat_t; - -typedef struct { - uint64_t *a, id; - uint16_t occ1, occ2; -} pe_hit_hap; - -typedef struct { - pe_hit_hap* a; - size_t n, m; - uint64_t n_u; -} kvec_pe_hit_hap; - -typedef struct { - kvec_t(hc_edge) a; -}kvec_hc_edge; - -#define pe_hit_an1_key(x) ((x).s) -KRADIX_SORT_INIT(pe_hit_an1, pe_hit, pe_hit_an1_key, member_size(pe_hit, s)) -#define pe_hit_an2_key(x) ((x).e) -KRADIX_SORT_INIT(pe_hit_an2, pe_hit, pe_hit_an2_key, member_size(pe_hit, e)) - -#define pe_hit_an1_idx_key(x) ((x).s<<1) -KRADIX_SORT_INIT(pe_hit_idx_an1, 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_an2, pe_hit, pe_hit_an2_idx_key, member_size(pe_hit, e)) - -#define generic_key(x) (x) -KRADIX_SORT_INIT(hc64, uint64_t, generic_key, 8) -KRADIX_SORT_INIT(u32, uint32_t, generic_key, 4) -#define g_partition_key(x) (((x)>>1)+((x)<<63)) -KRADIX_SORT_INIT(g_partition, uint64_t, g_partition_key, 8) - -#define get_pe_s(x) ((x).a[0]) -#define get_pe_e(x) ((x).a[(x).occ1]) -KRADIX_SORT_INIT(pe_an1, pe_hit_hap, get_pe_s, 8) -KRADIX_SORT_INIT(pe_an2, pe_hit_hap, get_pe_e, 8) - -#define pe_occ_key_1(x) ((x).occ1) -KRADIX_SORT_INIT(pe_occ1, pe_hit_hap, pe_occ_key_1, member_size(pe_hit_hap, occ1)) -#define pe_occ_key_2(x) ((x).occ2) -KRADIX_SORT_INIT(pe_occ2, pe_hit_hap, pe_occ_key_2, member_size(pe_hit_hap, occ2)) -#define pe_occ_key_t(x) (((uint64_t)((x).occ1))+((uint64_t)((x).occ2))) -KRADIX_SORT_INIT(pe_occ_t, pe_hit_hap, pe_occ_key_t, 8) - -#define asg_arc_key(a) ((a).ul) -KRADIX_SORT_INIT(asg_e, asg_arc_t, asg_arc_key, 8) - -typedef struct { // global data structure for kt_pipeline() - const ha_ug_index* idx; - kseq_t *ks1, *ks2; - int64_t chunk_size; - uint64_t n_thread; - uint64_t total_base; - uint64_t total_pair; - kvec_pe_hit hits; - ///kvec_pe_hit_hap hits; - trans_chain* t_ch; -} sldat_t; - -typedef struct { - uint64_t ref; - uint64_t off_cnt; -} s_hit; - -typedef struct { - kvec_t(s_hit) a; -} kvec_vote; - -typedef struct { // data structure for each step in kt_pipeline() - const ha_ug_index* idx; - int n, m, sum_len; - uint64_t *len, id; - char **seq; - ch_buf_t *buf; - kvec_vote* pos_buf; - pe_hit* pos; - ///pe_hit_hap* pos; - trans_chain* t_ch; -} stepdat_t; - -#define generic_key(x) (x) -KRADIX_SORT_INIT(b64, uint64_t, generic_key, 8) -#define ch_buf_t_key(a) ((a).key) -KRADIX_SORT_INIT(ch_buf, ch_buf_t, ch_buf_t_key, member_size(ch_buf_t, key)) -#define hc_pos_key(x) ((x)<<1) -KRADIX_SORT_INIT(hc_pos, uint64_t, hc_pos_key, 8) -#define hc_s_hit_an1_key(a) ((a).ref) -KRADIX_SORT_INIT(hc_s_hit_an1, s_hit, hc_s_hit_an1_key, 8) -#define hc_s_hit_an2_key(a) ((uint32_t)(a).off_cnt) -KRADIX_SORT_INIT(hc_s_hit_an2, s_hit, hc_s_hit_an2_key, 8) -#define hc_s_hit_off_cnt_key(a) ((a).off_cnt) -KRADIX_SORT_INIT(hc_s_hit_off_cnt, s_hit, hc_s_hit_off_cnt_key, 8) -#define hc_edge_key_u(a) ((a).uID) -KRADIX_SORT_INIT(hc_edge_u, hc_edge, hc_edge_key_u, 4) -#define hc_edge_key_d(a) ((a).dis) -KRADIX_SORT_INIT(hc_edge_d, hc_edge, hc_edge_key_d, member_size(hc_edge, dis)) - -#define k_trans_qs_key(a) ((a).qs) -KRADIX_SORT_INIT(k_trans_qs, u_trans_t, k_trans_qs_key, member_size(u_trans_t, qs)) - -#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_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) - -typedef struct { - kvec_t(kvec_t_u64_warp) matrix; - uint64_t uID_shift, dis_mode; -} MT; - -typedef struct{ - uint64_t beg, end, dis, cnt_0, cnt_1; -} trans_p_t; - -typedef struct{ - trans_p_t* a; - size_t n, m; - uint64_t max, med; -} trans_idx; - -reads_t R1, R2; -ha_ug_index* ug_index; - -void print_debug_bubble_graph(bubble_type* bub, ma_ug_t* ug, const char *fn); - -void build_bub_graph(ma_ug_t* ug, bubble_type* bub); - -void init_ha_ug_index_opt(ha_ug_index* idx, ma_ug_t *ug, int k, pldat_t* p, uint64_t up_occ, -uint64_t low_occ, uint64_t thread_num) -{ - uint64_t i, n; - for (idx->uID_bits=1; (uint64_t)(1<uID_bits)<(uint64_t)ug->u.n; idx->uID_bits++); - idx->pos_bits = 64 - idx->uID_bits - 1; - idx->uID_mode = (((uint64_t)-1) << (64-idx->uID_bits))>>1; - idx->pos_mode = ((uint64_t)-1) >> (64-idx->pos_bits); - idx->rev_mode = ((uint64_t)1) << 63; - idx->ug = ug; - idx->k = k; - idx->pre = HIC_COUNTER_BITS; - idx->tot = 1 << idx->pre; - idx->tot_pos = 0; - ///idx->up_bound = 1; - idx->up_bound = up_occ; - idx->low_bound = low_occ; - CALLOC(idx->idx_buf, idx->tot); - for (i = 0; i < idx->tot; i++) - { - idx->idx_buf[i].h = hc_pt_init(); - } - for (i = n = 0; i < ug->u.n; i++) - { - n += ug->u.a[i].len; - } - n = n << 3; - p->h = idx; - p->buf_bytes = n>>7; - CALLOC(p->cnt, idx->tot); - CALLOC(p->buf, idx->tot); - for (i = 0; i < idx->tot; i++) - { - kv_init(p->cnt[i].a); - kv_init(p->buf[i].a); - } - p->n_thread = thread_num; -} - -inline uint64_t get_k_direction(uint64_t x[4]) -{ - if(x[1] != x[3]) - { - return x[1] < x[3]? 0 : 1; - } - else if(x[0] != x[2]) - { - return x[0] < x[2]? 0 : 1; - } - else - { - return (uint64_t)-1; - } -} - -inline uint64_t hc_hash_long(uint64_t x[4], uint64_t* skip, uint64_t k) -{ - ///compare forward k-mer and reverse complementary strand - (*skip) = get_k_direction(x); - if((*skip) == (uint64_t)-1) return (*skip); - if (k <= 32) return ((x[(*skip)<<1|0]<<32)|(x[(*skip)<<1|1])); - return yak_hash64_64(x[(*skip)<<1|0]) + yak_hash64_64(x[(*skip)<<1|1]); -} - -inline uint64_t get_hc_pt1_count(ha_ug_index* index, uint64_t key, uint64_t** pos_list) -{ - uint64_t bucket_mask = (1ULL<pre) - 1; - hc_pt1_t* h = &(index->idx_buf[key & bucket_mask]); - uint64_t beg; - khint_t k; - k = hc_pt_get(h->h, key); - if (k == kh_end(h->h)) - { - return 0; - } - beg = kh_val(h->h, k); - if(pos_list) *pos_list = h->a + beg; - if((kh_key(h->h, k)&HIC_MAX_COUNT)h, k)&HIC_MAX_COUNT; - if(k == h->end) return h->n - beg; - for (k++; k != kh_end(h->h); ++k) - { - if (kh_exist(h->h, k)) - { - return kh_val(h->h, k) - beg; - } - } - return h->n - beg; -} - -void test_hc_pt1(char* seq, uint64_t len, uint64_t uID, ha_ug_index* idx) -{ - uint64_t i, l, k, pos, *pos_list = NULL, cnt; - uint64_t x[4], mask = (1ULL<k) - 1, shift = idx->k - 1, hash, skip; - for (i = l = 0, x[0] = x[1] = x[2] = x[3] = 0; i < len; ++i) { - int c = seq_nt4_table[(uint8_t)seq[i]]; - ///c = 00, 01, 10, 11 - if (c < 4) { // not an "N" base - ///x[0] & x[1] are the forward k-mer - ///x[2] & x[3] are the reverse complementary k-mer - x[0] = (x[0] << 1 | (c&1)) & mask; - x[1] = (x[1] << 1 | (c>>1)) & mask; - x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; - x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; - if (++l >= idx->k) - { - hash = hc_hash_long(x, &skip, idx->k); - if(skip == (uint64_t)-1) continue; - pos = (skip << 63) | ((uID << (64-idx->uID_bits))>>1) | (i & idx->pos_mode); - cnt = get_hc_pt1_count(idx, hash, &pos_list); - if(cnt == 0) fprintf(stderr, "ERROR cnt, uID: %lu\n", uID); - for (k = 0; k < cnt; k++) - { - if(pos_list[k]==pos) - { - pos_list[k] = (uint64_t)-1; - break; - } - } - if(k == cnt) fprintf(stderr, "ERROR k\n"); - - } - } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; // if there is an "N", restart - } -} - -void test_unitig_index(ha_ug_index* idx, ma_ug_t *ug) -{ - double index_time = yak_realtime(); - uint32_t i, j; - ma_utg_t *u = NULL; - hc_pt1_t *h = NULL; - idx->ug = ug; - for (i = 0; i < idx->ug->u.n; i++) - { - u = &(idx->ug->u.a[i]); - if(u->m == 0) continue; - test_hc_pt1(u->s, u->len, i, idx); - } - - for (i = 0; i < idx->tot; i++) - { - h = &(idx->idx_buf[i]); - for (j = 0; j < h->n; j++) - { - if(h->a[j] != (uint64_t)-1) - { - fprintf(stderr, "ERROR j\n"); - } - } - - } - - fprintf(stderr, "[M::%s::%.3f] ==> Test has been passed\n", __func__, yak_realtime()-index_time); -} - -void hc_pt_t_gen_single(hc_pt1_t* pt, uint64_t* up_bound, uint64_t* low_bound) -{ - khint_t k; - uint64_t c; - - if(up_bound || low_bound) - { - for (k = 0; k != kh_end(pt->h); ++k) { - if (kh_exist(pt->h, k)) { - if((up_bound && kh_val(pt->h, k) > (*up_bound)) || - (low_bound && kh_val(pt->h, k) < (*low_bound))) - { - kh_val(pt->h, k) = 0; - kh_key(pt->h, k) = (kh_key(pt->h, k)&HIC_KEY_MODE)| - (kh_val(pt->h, k)h, k):HIC_MAX_COUNT); - } - } - } - } - - - for (k = 0, pt->n = 0; k != kh_end(pt->h); ++k) { - if (kh_exist(pt->h, k)) { - c = kh_val(pt->h, k); - kh_val(pt->h, k) = pt->n; - pt->n += c; - pt->end = k; - } - } - CALLOC(pt->a, pt->n); -} - - -int write_hc_pt_index(ha_ug_index* idx, char* file_name) -{ - char* gfa_name = (char*)malloc(strlen(file_name)+25); - sprintf(gfa_name, "%s.hic.tlb.bin", file_name); - FILE* fp = fopen(gfa_name, "w"); - if (!fp) { - free(gfa_name); - return 0; - } - uint64_t i = HC_PT_MA; - - fwrite(&i, sizeof(i), 1, fp); - fwrite(&idx->uID_bits, sizeof(idx->uID_bits), 1, fp); - fwrite(&idx->uID_mode, sizeof(idx->uID_mode), 1, fp); - fwrite(&idx->pos_bits, sizeof(idx->pos_bits), 1, fp); - fwrite(&idx->pos_mode, sizeof(idx->pos_mode), 1, fp); - fwrite(&idx->rev_mode, sizeof(idx->rev_mode), 1, fp); - fwrite(&idx->k, sizeof(idx->k), 1, fp); - fwrite(&idx->pre, sizeof(idx->pre), 1, fp); - fwrite(&idx->tot, sizeof(idx->tot), 1, fp); - fwrite(&idx->tot_pos, sizeof(idx->tot_pos), 1, fp); - - for (i = 0; i < idx->tot; i++) - { - fwrite(&idx->idx_buf[i].n, sizeof(idx->idx_buf[i].n), 1, fp); - fwrite(&idx->idx_buf[i].end, sizeof(idx->idx_buf[i].end), 1, fp); - fwrite(idx->idx_buf[i].a, sizeof(uint64_t), idx->idx_buf[i].n, fp); - hc_pt_save(idx->idx_buf[i].h, fp); - } - - write_dbug(idx->ug, fp); - - fprintf(stderr, "[M::%s] Index has been written.\n", __func__); - free(gfa_name); - fclose(fp); - return 1; -} - -void destory_hc_pt_index(ha_ug_index* idx); -int load_hc_pt_index(ha_ug_index** r_idx, ma_ug_t *ug, char* file_name) -{ - uint64_t flag = 0; - // double index_time = yak_realtime(); - char* gfa_name = (char*)malloc(strlen(file_name)+25); - sprintf(gfa_name, "%s.hic.tlb.bin", file_name); - FILE* fp = fopen(gfa_name, "r"); - if (!fp) { - free(gfa_name); - return 0; - } - ha_ug_index* idx = NULL; CALLOC(idx, 1); - uint64_t i; - - flag += fread(&i, sizeof(i), 1, fp); - if(i != HC_PT_MA) - { - free(gfa_name); - destory_hc_pt_index(idx); - free(idx); - (*r_idx) = NULL; - fclose(fp); - fprintf(stderr, "[M::%s::] ==> Renew Hi-C index\n", __func__); - return 0; - } - flag += fread(&idx->uID_bits, sizeof(idx->uID_bits), 1, fp); - flag += fread(&idx->uID_mode, sizeof(idx->uID_mode), 1, fp); - flag += fread(&idx->pos_bits, sizeof(idx->pos_bits), 1, fp); - flag += fread(&idx->pos_mode, sizeof(idx->pos_mode), 1, fp); - flag += fread(&idx->rev_mode, sizeof(idx->rev_mode), 1, fp); - flag += fread(&idx->k, sizeof(idx->k), 1, fp); - flag += fread(&idx->pre, sizeof(idx->pre), 1, fp); - flag += fread(&idx->tot, sizeof(idx->tot), 1, fp); - flag += fread(&idx->tot_pos, sizeof(idx->tot_pos), 1, fp); - MALLOC(idx->idx_buf, idx->tot); - - for (i = 0; i < idx->tot; i++) - { - flag += fread(&idx->idx_buf[i].n, sizeof(idx->idx_buf[i].n), 1, fp); - flag += fread(&idx->idx_buf[i].end, sizeof(idx->idx_buf[i].end), 1, fp); - MALLOC(idx->idx_buf[i].a, idx->idx_buf[i].n); - flag += fread(idx->idx_buf[i].a, sizeof(uint64_t), idx->idx_buf[i].n, fp); - hc_pt_load(&(idx->idx_buf[i].h), fp); - } - - - (*r_idx) = idx; - - free(gfa_name); - if(!test_dbug(ug, fp)) - { - destory_hc_pt_index(idx); - free(idx); - (*r_idx) = NULL; - fclose(fp); - fprintf(stderr, "[M::%s::] ==> Renew Hi-C index\n", __func__); - return 0; - } - - fclose(fp); - // fprintf(stderr, "[M::%s::%.3f] ==> HiC index has been loaded\n", __func__, yak_realtime()-index_time); - return 1; -} - -static void worker_for_sort(void *data, long i, int tid) // callback for kt_for() -{ - pldat_t *pl = (pldat_t*)data; - hc_pt1_t *h = &(pl->h->idx_buf[i]); - khint_t k; - uint64_t beg, cnt = 0; - uint64_t* pos_list; - for (k = 0; k != kh_end(h->h); ++k) { - if (kh_exist(h->h, k)) { - beg = kh_val(h->h, k); - pos_list = h->a + beg; - if((kh_key(h->h, k)&HIC_MAX_COUNT)h, k)&HIC_MAX_COUNT; - } - else if(k == h->end) - { - cnt = h->n - beg; - } - else - { - for (k++; k != kh_end(h->h); ++k) - { - if (kh_exist(h->h, k)) - { - cnt = kh_val(h->h, k) - beg; - break; - } - } - } - if(cnt > 0) radix_sort_hc_pos(pos_list, pos_list+cnt); - } - } - -} - -void hc_pt_t_gen(ha_ug_index* idx, pldat_t* pl) -{ - if(pl == NULL) - { - uint64_t i; - for (i = 0; i < idx->tot; i++) - { - hc_pt_t_gen_single(&(idx->idx_buf[i]), &(idx->up_bound), &(idx->low_bound)); - } - } - else - { - kt_for(pl->n_thread, worker_for_sort, pl, pl->h->tot); - } -} - -static void worker_for(void *data, long i, int tid) // callback for kt_for() -{ - pldat_t *pl = (pldat_t*)data; - hc_pt1_t *h = &(pl->h->idx_buf[i]); - uint64_t m = 0, beg, end, occ; - khint_t key; - int absent; - - - if(pl->is_cnt) - { - uint64_t* cnt = NULL; - if(pl->cnt[i].a.n > 2) radix_sort_b64(pl->cnt[i].a.a, pl->cnt[i].a.a + pl->cnt[i].a.n); - cnt = pl->cnt[i].a.a; - occ = pl->cnt[i].a.n; - for (m = beg = end = 0; m < occ; m++) - { - if(cnt[beg] == cnt[m]) - { - end = m; - } - else - { - key = hc_pt_put(h->h, cnt[beg], &absent); - if(absent) kh_val(h->h, key) = 0; - kh_val(h->h, key) += (end - beg + 1); - kh_key(h->h, key) = (kh_key(h->h, key)&HIC_KEY_MODE)| - (kh_val(h->h, key)h, key):HIC_MAX_COUNT); - beg = end = m; - } - } - if(occ > 0) - { - key = hc_pt_put(h->h, cnt[beg], &absent); - if(absent) kh_val(h->h, key) = 0; - kh_val(h->h, key) += (end - beg + 1); - kh_key(h->h, key) = (kh_key(h->h, key)&HIC_KEY_MODE)| - (kh_val(h->h, key)h, key):HIC_MAX_COUNT); - } - pl->cnt[i].a.n = 0; - } - - if(!pl->is_cnt) - { - ch_buf_t* pos = NULL; - uint64_t num, *pos_list = NULL, k, k_n, pos_k; - if(pl->buf[i].a.n > 2) radix_sort_ch_buf(pl->buf[i].a.a, pl->buf[i].a.a + pl->buf[i].a.n); - pos = pl->buf[i].a.a; - occ = pl->buf[i].a.n; - for (m = beg = end = 0; m < occ; m++) - { - if(pos[beg].key == pos[m].key) - { - end = m; - } - else - { - num = get_hc_pt1_count(pl->h, pos[beg].key, &pos_list); - if(num > 0) - { - k_n=(end-beg+1);pos_k=pos_list[num-1];pos_list[num-1]+=k_n; - for (k = 0; k < k_n; k++) - { - pos_list[pos_k+k] = pos[beg+k].pos; - } - } - - beg = end = m; - } - - } - if(occ > 0) - { - num = get_hc_pt1_count(pl->h, pos[beg].key, &pos_list); - if(num > 0) - { - k_n=(end-beg+1);pos_k=pos_list[num-1];pos_list[num-1]+=k_n; - for (k = 0; k < k_n; k++) - { - pos_list[pos_k+k] = pos[beg+k].pos; - } - } - } - pl->buf[i].a.n = 0; - } -} - -void parallel_count_hc_pt1(pldat_t* pl) -{ - uint64_t i, l = 0, uID, num_pos = 0, pos_thre; - uint64_t x[4], mask = (1ULL<h->k) - 1, shift = pl->h->k - 1, hash, pos, skip, bucket_mask = (1ULL<h->pre) - 1; - ma_utg_t *u = NULL; - ch_buf_t k_pos; - if(pl->is_cnt) l = ((pl->buf_bytes>>3)/pl->h->tot) + 1, pos_thre = pl->buf_bytes>>3; - if(!pl->is_cnt) l = ((pl->buf_bytes>>4)/pl->h->tot) + 1, pos_thre = pl->buf_bytes>>4; - for (i = 0; i < pl->h->tot; i++) - { - if(pl->is_cnt) - { - kv_resize(uint64_t, pl->cnt[i].a, l); - pl->cnt[i].a.n = 0; - } - - if(!pl->is_cnt) - { - kv_resize(ch_buf_t, pl->buf[i].a, l); - pl->buf[i].a.n = 0; - } - } - - - for (uID = 0; uID < pl->h->ug->u.n; uID++) - { - u = &(pl->h->ug->u.a[uID]); - if(u->m == 0) continue; - - for (i = l = 0, x[0] = x[1] = x[2] = x[3] = 0; i < u->len; ++i) { - int c = seq_nt4_table[(uint8_t)u->s[i]]; - ///c = 00, 01, 10, 11 - if (c < 4) { // not an "N" base - ///x[0] & x[1] are the forward k-mer - ///x[2] & x[3] are the reverse complementary k-mer - x[0] = (x[0] << 1 | (c&1)) & mask; - x[1] = (x[1] << 1 | (c>>1)) & mask; - x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; - x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; - if (++l >= pl->h->k) - { - hash = hc_hash_long(x, &skip, pl->h->k); - if(skip == (uint64_t)-1) continue; - if(pl->is_cnt) - { - kv_push(uint64_t, pl->cnt[hash & bucket_mask].a, hash); - } - else - { - pos = (skip << 63) | ((uID << (64-pl->h->uID_bits))>>1) | (i & pl->h->pos_mode); - k_pos.key = hash; k_pos.pos = pos; - kv_push(ch_buf_t, pl->buf[hash & bucket_mask].a, k_pos); - } - num_pos++; - - if(num_pos >= pos_thre) - { - num_pos = 0; - kt_for(pl->n_thread, worker_for, pl, pl->h->tot); - } - } - - } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; // if there is an "N", restart - } - } - - if(num_pos > 0) kt_for(pl->n_thread, worker_for, pl, pl->h->tot); - - for (i = 0; i < pl->h->tot; i++) - { - if(pl->cnt[i].a.m > 0) kv_destroy(pl->cnt[i].a), kv_init(pl->cnt[i].a); - if(pl->buf[i].a.m > 0) kv_destroy(pl->buf[i].a), kv_init(pl->buf[i].a); - } -} - -ha_ug_index* build_unitig_index(ma_ug_t *ug, int k, uint64_t up_occ, uint64_t low_occ, uint64_t thread_num) -{ - ha_ug_index* idx = NULL; CALLOC(idx, 1); - pldat_t pl; pl.h = idx; pl.is_cnt = 1; - double index_time = yak_realtime(), beg_time; - init_ha_ug_index_opt(idx, ug, k, &pl, up_occ, low_occ, thread_num); - - beg_time = yak_realtime(); - pl.is_cnt = 1; - parallel_count_hc_pt1(&pl); - fprintf(stderr, "[M::%s::%.3f] ==> Counting\n", __func__, yak_realtime()-beg_time); - - beg_time = yak_realtime(); - hc_pt_t_gen(pl.h, NULL); - fprintf(stderr, "[M::%s::%.3f] ==> Memory allocating\n", __func__, yak_realtime()-beg_time); - - beg_time = yak_realtime(); - pl.is_cnt = 0; - parallel_count_hc_pt1(&pl); - fprintf(stderr, "[M::%s::%.3f] ==> Filling pos\n", __func__, yak_realtime()-beg_time); - - beg_time = yak_realtime(); - hc_pt_t_gen(pl.h, &pl); - fprintf(stderr, "[M::%s::%.3f] ==> Sorting pos\n", __func__, yak_realtime()-beg_time); - - fprintf(stderr, "[M::%s::%.3f] ==> HiC index has been built\n", __func__, yak_realtime()-index_time); - - uint64_t i; - for (i = 0; i < idx->tot; i++) - { - kv_destroy(pl.cnt[i].a); - kv_destroy(pl.buf[i].a); - } - free(pl.cnt); free(pl.buf); - - return idx; -} - -void destory_hc_pt_index(ha_ug_index* idx) -{ - if(idx->idx_buf) - { - uint64_t i = 0; - for (i = 0; i < idx->tot; i++) - { - if(idx->idx_buf[i].a) free(idx->idx_buf[i].a); - if(idx->idx_buf[i].h) hc_pt_destroy(idx->idx_buf[i].h); - } - free(idx->idx_buf); - } -} - -inline void interpret_pos(const ha_ug_index* idx, s_hit *p, uint64_t* rev, uint64_t* uID, -uint64_t* ref_p, uint64_t* self_p, uint64_t* exact_len, uint64_t* total_len) -{ - (*rev) = p->ref>>63; - (*uID) = (p->ref << 1) >> (64 - idx->uID_bits); - (*self_p) = (uint32_t)p->off_cnt; - ///(*exact_len) = p->off_cnt >> 32; - (*exact_len) = (p->off_cnt>>32) & ((uint64_t)65535); - if(total_len != NULL) - { - ///(*exact_len) = (p->off_cnt>>32) & ((uint64_t)65535); - (*total_len) = (p->off_cnt>>48) + (*exact_len); - } - if((p->ref & idx->pos_mode)>>(idx->pos_bits - 1)) - { - (*ref_p) = (*self_p) - (p->ref&(idx->pos_mode>>1)); - } - else - { - (*ref_p) = (*self_p) + (p->ref&(idx->pos_mode)); - } -} - - -inline uint64_t check_exact_match(char* a, long long a_beg, long long a_total, char* b, long long b_beg, -long long b_total, long long Len, uint64_t rev, uint64_t dir) -{ - long long i = 0; - if(rev == 0) - { - if(dir == 0) - { - for (i = 0; i < Len && a_beg < a_total && b_beg < b_total; i++) - { - if(a[a_beg++] != b[b_beg++]) return i; - } - } - else - { - for (i = 0; i < Len && a_beg >= 0 && b_beg >= 0; i++) - { - if(a[a_beg--] != b[b_beg--]) return i; - } - } - } - else - { - - if(dir == 0) - { - for (i = 0; i < Len && a_beg < a_total && b_beg < b_total; i++) - { - if(a[a_beg] != b2rc[seq_nt4_table[(uint8_t)b[b_total - b_beg - 1]]]) return i; - a_beg++; b_beg++; - } - } - else - { - for (i = 0; i < Len && a_beg >= 0 && b_beg >= 0; i++) - { - if(a[a_beg] != b2rc[seq_nt4_table[(uint8_t)b[b_total - b_beg - 1]]]) return i; - a_beg--; b_beg--; - } - } - } - - return i; -} - -uint64_t debug_hash_value(char *r, uint64_t end, uint64_t k_mer) -{ - uint64_t i; - uint64_t x[4], mask = (1ULL<>1)) & mask; - x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; - x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; - } - } - - return hc_hash_long(x, &skip, k_mer); - -} - -inline uint64_t collect_votes(s_hit* a, uint64_t n) -{ - if(n == 0) return 0; - if(n == 1) return (a[0].off_cnt>>32); //seed length, is right - long long i = 0; - uint64_t cur_beg, cur_end, beg, end, ovlp = 0, tLen = 0; - cur_end = (uint32_t)a[n-1].off_cnt; - cur_beg = cur_end + 1 - (a[n-1].off_cnt>>32); - - if(n >= 2) - { - for (i = n - 2; i >= 0; i--) - { - end = (uint32_t)a[i].off_cnt; - beg = end + 1 - (a[i].off_cnt>>32); - if(MAX(cur_beg, beg) <= MIN(cur_end, end)) - { - cur_beg = MIN(cur_beg, beg); - ///cur_end = MAX(cur_end, end); - } - else - { - ovlp += (cur_end + 1 - cur_beg); - cur_beg = beg; - cur_end = end; - } - } - } - - ovlp += (cur_end + 1 - cur_beg); - tLen = (uint32_t)a[n-1].off_cnt + 1 - cur_beg; - tLen = tLen - ovlp; - tLen = tLen << 16; - return ovlp | tLen; -} - -inline void compress_mapped_pos(const ha_ug_index* idx, kvec_vote* buf, uint64_t buf_iter, uint64_t max_i, uint64_t thres) -{ - if(buf_iter >= buf->a.n) - { - buf->a.n = buf_iter; - return; - } - uint64_t rev, uID, ref_p, self_p, eLen, tLen, i, max_beg, max_end, cur_beg, cur_end, ovlp, max_eLen; - uint64_t secondLen = 0, second_i = (uint64_t)-1; - interpret_pos((ha_ug_index*)idx, &buf->a.a[max_i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - max_end = self_p; - max_beg = self_p + 1 - tLen; - max_eLen = eLen; - for (i = buf_iter; i < buf->a.n; i++) - { - if(i == max_i) continue; - interpret_pos(idx, &buf->a.a[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - cur_end = self_p; - cur_beg = self_p + 1 - tLen; - if(MAX(cur_beg, max_beg) <= MIN(cur_end, max_end)) - { - ovlp = MIN(cur_end, max_end) - MAX(cur_beg, max_beg) + 1; - if(ovlp > thres) - { - if(eLen >= max_eLen * 0.8) - { - buf->a.n = buf_iter; - return; - } - continue; - } - } - if(secondLen < eLen) secondLen = eLen, second_i = i; - } - - if(second_i == (uint64_t)-1) - { - buf->a.a[buf_iter] = buf->a.a[max_i]; - buf->a.n = buf_iter + 1; - } - else - { - buf->a.a[buf_iter] = buf->a.a[MIN(max_i, second_i)]; - buf->a.a[buf_iter+1] = buf->a.a[MAX(max_i, second_i)]; - buf->a.n = buf_iter + 2; - } -} - -inline void print_pos_list(const ha_ug_index* idx, s_hit *l, uint64_t occ, uint64_t rid, uint64_t r1) -{ - if(rid == 33045391 || rid == 4239289 || rid == 5267597 || rid == 34474764 || rid == 35016489 - || rid == 36002255 || rid == 37811694 || rid == 46805824) - { - uint64_t i, rev, uID, ref_p, self_p, cnt; - for (i = 0; i < occ; i++) - { - interpret_pos(idx, &l[i], &rev, &uID, &ref_p, &self_p, &cnt, NULL); - fprintf(stderr, "(r%lu) rid: %lu, i: %lu, rev: %lu, uID: %lu, ref_p: %lu, self_p: %lu\n", - r1, rid, i, rev, uID, ref_p, self_p); - } - - } -} - -uint64_t get_longest_hit(char *r, uint64_t len, uint64_t k_mer, uint64_t self_p, uint64_t self_rev, kvec_vote* buf, const ha_ug_index* idx, -uint64_t *pos_list, uint64_t cnt, uint64_t* c_sfx) -{ - uint64_t max_p, map_p_occ, i, j, m, rev, ref_p, u_len, uID, k_len; - s_hit *p = NULL; - ///each k-mer at different unitigs - ///rev:uID:pos - if(c_sfx) (*c_sfx) = (uint64_t)-1; - for (j = 0; j < cnt; j++) - { - ///get - kv_pushp(s_hit, buf->a, &p); - rev = (pos_list[j]>>63) != self_rev; - ref_p = pos_list[j] & idx->pos_mode; - uID = (pos_list[j] << 1) >> (64 - idx->uID_bits); - u_len = idx->ug->u.a[uID].len; - if(rev) ref_p = u_len - 1 - (ref_p + 1 - k_mer); - p->off_cnt = self_p | ((uint64_t)k_mer << 32); ///high bits should be the legnth - - p->ref = ref_p >= self_p? (ref_p-self_p) - : (self_p-ref_p) + ((uint64_t)1 << (idx->pos_bits - 1)); - p->ref = (rev << 63)|(pos_list[j] & idx->uID_mode)|(p->ref&idx->pos_mode); - - - ///extend - k_len = check_exact_match(r, self_p + 1, len, idx->ug->u.a[uID].s, ref_p + 1, u_len, len, rev, 0); - if(c_sfx && cnt == idx->hap_cnt && k_len < (*c_sfx)) (*c_sfx) = k_len; - - p->off_cnt += ((uint64_t)k_len << 32) + k_len; - - if(self_p >= k_mer && ref_p >= k_mer) - { - k_len = check_exact_match(r, self_p - k_mer, len, idx->ug->u.a[uID].s, - ref_p - k_mer, u_len, len, rev, 1); - p->off_cnt += ((uint64_t)k_len << 32); - } - // if(cnt > 0) fprintf(stderr, "inner j: %lu, rev: %lu, uID: %lu, ref_p: %lu, self_p: %u, len: %lu\n", j, rev, uID, ref_p, (uint32_t)p->off_cnt, p->off_cnt>>32); - } - - p = buf->a.a + buf->a.n - cnt; - if(cnt > 1) radix_sort_hc_s_hit_off_cnt(p, p + cnt); - max_p = map_p_occ = 0; - for (j = 1, i = 0; j <= cnt; ++j) - { - if(j == cnt || p[j].off_cnt != p[i].off_cnt) - { - if((max_p>>32) < (p[i].off_cnt>>32)) - { - max_p = p[i].off_cnt; - map_p_occ = j - i; - } - else if(((max_p>>32) == (p[i].off_cnt>>32)) && ((j - i) > map_p_occ)) - { - max_p = p[i].off_cnt; - map_p_occ = j - i; - } - i = j;///must - } - } - - buf->a.n -= cnt; - for (j = m = 0; j < cnt; j++) - { - if(p[j].off_cnt == max_p) - { - p[m] = p[j]; - m++; - } - } - cnt = m; - buf->a.n += cnt; - - // if(cnt > 0) fprintf(stderr, "max_p_offset: %u, max_p_len: %lu, map_p_occ: %lu\n", (uint32_t)max_p, max_p>>32, map_p_occ); - return max_p; -} - -#define is_update_hit(mL, mR, cL, cR) (((mL)<(cL))||((mL)==(cL)&&(mR)<(cR))) -inline void compress_mapped_pos_advance(const ha_ug_index* idx, kvec_vote* buf, uint64_t buf_iter, uint64_t ovlp_thre) -{ - if(buf_iter >= buf->a.n) - { - buf->a.n = buf_iter; - return; - } - s_hit *p = NULL; - uint64_t rev, uID, ref_p, self_p, eLen, tLen, i, j, cnt; - uint64_t max_beg = 0, max_end = 0, max_i, max_occ, cur_beg, cur_end, ovlp; - uint64_t second_i = (uint64_t)-1, second_occ; - uint64_t max_eLen, sec_eLen; - double max_eRate, sec_eRate, eRate; - p = buf->a.a + buf_iter; - cnt = buf->a.n - buf_iter; - if(cnt > 1) radix_sort_hc_s_hit_off_cnt(p, p + cnt); ///buf save all hits, here sort by offset in reads - max_eLen = 0; max_i = (uint64_t)-1; max_occ = 0; max_eRate = -1; - for (j = 1, i = 0; j <= cnt; ++j) - { - if(j == cnt || p[j].off_cnt != p[i].off_cnt) - { - ///occ = j - i; - interpret_pos((ha_ug_index*)idx, &p[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - eRate = (double)(eLen)/(double)(tLen); - if(is_update_hit(max_eLen, max_eRate, eLen, eRate)) - { - max_eLen = eLen; max_eRate = eRate; - max_end = self_p; max_beg = self_p + 1 - tLen; - max_i = i; max_occ = j - i; - } - // fprintf(stderr, "\n++++++[%lu, %lu] uID: %lu, ref_p: %lu, self_p: %lu, eLen: %lu, tLen: %lu, max_i: %lu\n", - // i, j, uID, ref_p, self_p, eLen, tLen, max_i); - i = j;///must - } - } - - - sec_eLen = 0; second_i = (uint64_t)-1; second_occ = 0; sec_eRate = -1; - for (j = 1, i = 0; j <= cnt; ++j) - { - if(j == cnt || p[j].off_cnt != p[i].off_cnt) - { - if(i != max_i) - { - interpret_pos((ha_ug_index*)idx, &p[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - eRate = (double)(eLen)/(double)(tLen); - cur_end = self_p; - cur_beg = self_p + 1 - tLen; - // fprintf(stderr, "\n----[%lu, %lu] uID: %lu, ref_p: %lu, self_p: %lu, eLen: %lu, tLen: %lu, max_i: %lu\n", - // i, j, uID, ref_p, self_p, eLen, tLen, max_i); - // fprintf(stderr, "max_beg: %lu, max_end: %lu, cur_beg: %lu, cur_end: %lu\n", - // max_beg, max_end, cur_beg, cur_end); - ///overlap with max interval - if(MAX(cur_beg, max_beg) <= MIN(cur_end, max_end)) - { - ovlp = MIN(cur_end, max_end) - MAX(cur_beg, max_beg) + 1; - /*******************************for debug************************************/ - if(ovlp == MIN(max_end+1-max_end, tLen))///for non-unique k-mer - { - i = j;///must - continue;///fully contain - } - if(ovlp > ((max_end+1-max_end)*0.8) && eLen > (max_eLen*0.8))///best is not unique - { - buf->a.n = buf_iter; - return; - } - if(ovlp > ((max_end+1-max_end)*0.15) + 1) - { - i = j;///must - continue;///fully contain - } - - // if(ovlp > (MIN((max_end+1-max_end), (cur_end+1-cur_end))*0.15) + 1) - // { - // if(eLen > (max_eLen*0.8))///best is not unique - // { - // buf->a.n = buf_iter; - // return; - // } - // i = j;///must - // continue; - // } - /*******************************for debug************************************/ - } - - if(is_update_hit(sec_eLen, sec_eRate, eLen, eRate)) - { - sec_eLen = eLen; sec_eRate = eRate; - second_i = i; second_occ = j - i; - } - } - i = j;///must - } - } - - // fprintf(stderr, "max_i: %lu, max_occ: %lu, second_i: %lu, second_occ: %lu\n", - // max_i, max_occ, second_i, second_occ); - - if(second_i == (uint64_t)-1) - { - i = 0; - for (j = max_i; j < max_i + max_occ; j++, i++) p[i] = p[j]; - } - else ///be carful about overwritten - { - i = 0; - if(max_i <= second_i) - { - for (j = max_i; j < max_i + max_occ; j++, i++) p[i] = p[j]; - for (j = second_i; j < second_i + second_occ; j++, i++) p[i] = p[j]; - } - else - { - for (j = second_i; j < second_i + second_occ; j++, i++) p[i] = p[j]; - for (j = max_i; j < max_i + max_occ; j++, i++) p[i] = p[j]; - } - } - - buf->a.n = buf_iter + max_occ + second_occ; -} - -void get_alignment(char *r, uint64_t len, uint64_t k_mer, kvec_vote* buf, const ha_ug_index* idx, uint64_t buf_iter, uint64_t rid) -{ - uint64_t i, j, k, l = 0, k_len, c_sfx, m, skip, *pos_list = NULL, cnt, rev, self_p, ref_p, uID; - uint64_t x[4], mask = (1ULL<a.n = 0; - for (i = l = 0, x[0] = x[1] = x[2] = x[3] = 0; i < len; ++i) { - int c = seq_nt4_table[(uint8_t)r[i]]; - ///c = 00, 01, 10, 11 - if (c < 4) { // not an "N" base - ///x[0] & x[1] are the forward k-mer - ///x[2] & x[3] are the reverse complementary k-mer - x[0] = (x[0] << 1 | (c&1)) & mask; - x[1] = (x[1] << 1 | (c>>1)) & mask; - x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; - x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; - if (++l >= k_mer) - { - hash = hc_hash_long(x, &skip, k_mer); - if(skip == (uint64_t)-1) continue; - cnt = get_hc_pt1_count((ha_ug_index*)idx, hash, &pos_list); - if(cnt > idx->hap_cnt || cnt <= 0) continue; - - if(cnt > 1) - { - for (j = 0; j < cnt; j++) - { - uID = (pos_list[j] << 1) >> (64 - idx->uID_bits); - for (k = j + 1; k < cnt; k++) - { - if(uID == ((pos_list[k] << 1) >> (64 - idx->uID_bits))) break; - } - if(k < cnt) break; - } - - if(j < cnt) continue; - } - // if(cnt > 0) fprintf(stderr, "+i: %lu, l: %lu, cnt: %lu\n", i, l, cnt); - get_longest_hit(r, len, k_mer, i, skip, buf, idx, pos_list, cnt, &c_sfx); - // if(cnt > 0) fprintf(stderr, "c_sfx: %lu\n", c_sfx); - if(c_sfx != (uint64_t)-1) - { - k_len = c_sfx; - if((k_len + 1) >= k_mer) - { - l = 0, x[0] = x[1] = x[2] = x[3] = 0; - i = i + k_len - (k_mer - 1); - } - else - { - ///l = i - (i + k_len - (k_mer - 1)); - l = k_mer - k_len - 1; - } - } - // if(cnt > 0) fprintf(stderr, "-i: %lu, l: %lu\n", i, l); - } - - } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; // if there is an "N", restart - } - - if(buf->a.n - buf_iter == 0) return; - if(buf->a.n - buf_iter > 1) radix_sort_hc_s_hit_an1(buf->a.a + buf_iter, buf->a.a + buf->a.n); - - - uint64_t cur_ref_p, thres = (len * HIC_R_E_RATE) + 1, index_beg, ovlp; - i = m = buf_iter; - while (i < buf->a.n) - { - interpret_pos(idx, &buf->a.a[i], &rev, &uID, &ref_p, &self_p, &cnt, NULL); - ///fprintf(stderr, "after-i: %lu, uID: %lu, ref_p: %lu, self_p: %lu\n", i, uID, ref_p, self_p); - cur_ref_p = buf->a.a[i].ref; - index_beg = i; - ///ref>>(idx->pos_bits-1) = (rev:1):(uID:uID-bits):(ref_pos>=self_pos:1) - while ((i < buf->a.n) && - ((buf->a.a[i].ref>>(idx->pos_bits-1)) == (cur_ref_p>>(idx->pos_bits-1))) && - (buf->a.a[i].ref - cur_ref_p <= thres)) - { - i++; - } - if(i - index_beg > 1) - { - radix_sort_hc_s_hit_an2(buf->a.a + index_beg, buf->a.a + i);//sort by self_p - } - ovlp = collect_votes(buf->a.a + index_beg, i - index_beg); - ///fprintf(stderr, "i-1: %lu, self_p: %u\n", i-1, (uint32_t)buf->a.a[i - 1].off_cnt); - buf->a.a[m] = buf->a.a[i - 1]; - buf->a.a[m].off_cnt = (buf->a.a[m].off_cnt << 32)>>32; - buf->a.a[m].off_cnt += ((uint64_t)ovlp<<32); - ///fprintf(stderr, "m: %lu, self_p: %u\n", m, (uint32_t)buf->a.a[m].off_cnt); - m++; - } - buf->a.n = m; - - /*******************************for debug************************************/ - // for (i = buf_iter; i < buf->a.n; i++) - // { - // uint64_t eLen, tLen; - // interpret_pos(idx, &buf->a.a[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - // if(maxLen < eLen) fprintf(stderr, "ERROR1\n"); - // if(i == max_i && maxLen != eLen) fprintf(stderr, "ERROR2\n"); - // } - /*******************************for debug************************************/ - ///select the best alignment at [buf_iter, m) - - /*******************************for debug************************************/ - // fprintf(stderr, "len1:%lu, max_i: %lu\n", buf->a.n - buf_iter, max_i); - // for (i = buf_iter; i < buf->a.n; i++) - // { - // uint64_t eLen, tLen; - // interpret_pos(idx, &buf->a.a[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - // fprintf(stderr, "(%lu) rev: %lu, uID: %lu, ref_p: %lu, self_p: %lu, eLen: %lu, tLen: %lu\n", - // i, rev, uID, ref_p, self_p, eLen, tLen); - // } - /*******************************for debug************************************/ - compress_mapped_pos_advance(idx, buf, buf_iter, (k_mer * 0.1) > 0? (k_mer * 0.1) : 1); - /*******************************for debug************************************/ - // fprintf(stderr, "len2:%lu, max_i: %lu\n", buf->a.n - buf_iter, max_i); - // for (i = buf_iter; i < buf->a.n; i++) - // { - // uint64_t eLen, tLen; - // interpret_pos(idx, &buf->a.a[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - // fprintf(stderr, "(%lu) rev: %lu, uID: %lu, ref_p: %lu, self_p: %lu, eLen: %lu, tLen: %lu\n", - // i, rev, uID, ref_p, self_p, eLen, tLen); - // } - // if(buf->a.n != m) fprintf(stderr, "Changed\n"); - // fprintf(stderr, "\n"); - /*******************************for debug************************************/ -} - -inline void compress_mapped_pos_debug(const ha_ug_index* idx, kvec_vote* buf, uint64_t buf_iter, uint64_t max_i, uint64_t thres) -{ - if(buf_iter >= buf->a.n) - { - buf->a.n = buf_iter; - return; - } - uint64_t rev, uID, ref_p, self_p, eLen, tLen, i, max_beg, max_end, cur_beg, cur_end, ovlp, max_eLen; - uint64_t secondLen = 0, second_i = (uint64_t)-1; - interpret_pos((ha_ug_index*)idx, &buf->a.a[max_i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - max_end = self_p; - max_beg = self_p + 1 - tLen; - max_eLen = eLen; - for (i = buf_iter; i < buf->a.n; i++) - { - if(i == max_i) continue; - interpret_pos(idx, &buf->a.a[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - cur_end = self_p; - cur_beg = self_p + 1 - tLen; - if(MAX(cur_beg, max_beg) <= MIN(cur_end, max_end)) - { - ovlp = MIN(cur_end, max_end) - MAX(cur_beg, max_beg) + 1; - if(ovlp > thres) - { - if(eLen >= max_eLen * 0.8) - { - buf->a.n = buf_iter; - return; - } - continue; - } - } - if(secondLen < eLen) secondLen = eLen, second_i = i; - } - - if(second_i == (uint64_t)-1) - { - buf->a.a[buf_iter] = buf->a.a[max_i]; - buf->a.n = buf_iter + 1; - } - else - { - buf->a.a[buf_iter] = buf->a.a[MIN(max_i, second_i)]; - buf->a.a[buf_iter+1] = buf->a.a[MAX(max_i, second_i)]; - buf->a.n = buf_iter + 2; - } -} - -void get_alignment_debug(char *r, uint64_t len, uint64_t k_mer, kvec_vote* buf, const ha_ug_index* idx, uint64_t buf_iter, uint64_t rid) -{ - uint64_t i, j, l = 0, m, skip, *pos_list = NULL, cnt, rev, self_p, ref_p, uID; - uint64_t x[4], mask = (1ULL<a.n = 0; - uint64_t k_len, c_sfx, k; - for (i = l = 0, x[0] = x[1] = x[2] = x[3] = 0; i < len; ++i) { - int c = seq_nt4_table[(uint8_t)r[i]]; - ///c = 00, 01, 10, 11 - if (c < 4) { // not an "N" base - ///x[0] & x[1] are the forward k-mer - ///x[2] & x[3] are the reverse complementary k-mer - x[0] = (x[0] << 1 | (c&1)) & mask; - x[1] = (x[1] << 1 | (c>>1)) & mask; - x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; - x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; - if (++l >= k_mer) - { - hash = hc_hash_long(x, &skip, k_mer); - if(skip == (uint64_t)-1) continue; - cnt = get_hc_pt1_count((ha_ug_index*)idx, hash, &pos_list); - if(cnt > idx->hap_cnt || cnt <= 0) continue; - - if(cnt > 1) - { - for (j = 0; j < cnt; j++) - { - uID = (pos_list[j] << 1) >> (64 - idx->uID_bits); - for (k = j + 1; k < cnt; k++) - { - if(uID == ((pos_list[k] << 1) >> (64 - idx->uID_bits))) break; - } - if(k < cnt) break; - } - - if(j < cnt) continue; - } - // if(cnt > 0) fprintf(stderr, "+i: %lu, l: %lu, cnt: %lu\n", i, l, cnt); - get_longest_hit(r, len, k_mer, i, skip, buf, idx, pos_list, cnt, &c_sfx); - // if(cnt > 0) fprintf(stderr, "c_sfx: %lu\n", c_sfx); - if(c_sfx != (uint64_t)-1) - { - k_len = c_sfx; - if((k_len + 1) >= k_mer) - { - l = 0, x[0] = x[1] = x[2] = x[3] = 0; - i = i + k_len - (k_mer - 1); - } - else - { - ///l = i - (i + k_len - (k_mer - 1)); - l = k_mer - k_len - 1; - } - } - // if(cnt > 0) fprintf(stderr, "-i: %lu, l: %lu\n", i, l); - } - - } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; // if there is an "N", restart - } - **/ - - s_hit *p = NULL; uint64_t u_len; - ///buf->a.n = 0; - for (i = l = 0, x[0] = x[1] = x[2] = x[3] = 0; i < len; ++i) { - int c = seq_nt4_table[(uint8_t)r[i]]; - ///c = 00, 01, 10, 11 - if (c < 4) { // not an "N" base - ///x[0] & x[1] are the forward k-mer - ///x[2] & x[3] are the reverse complementary k-mer - x[0] = (x[0] << 1 | (c&1)) & mask; - x[1] = (x[1] << 1 | (c>>1)) & mask; - x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; - x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; - if (++l >= k_mer) - { - hash = hc_hash_long(x, &skip, k_mer); - if(skip == (uint64_t)-1) continue; - /*******************************for debug************************************/ - // if(debug_hash_value(r, i, k_mer) != hash) - // { - // fprintf(stderr, "ERROR\n"); - // } - /*******************************for debug************************************/ - cnt = get_hc_pt1_count((ha_ug_index*)idx, hash, &pos_list); - if(cnt > idx->hap_cnt) continue; - if(cnt != 1) continue; ///might be able to be disabled in future - - - for (j = 0; j < cnt; j++) - { - kv_pushp(s_hit, buf->a, &p); - rev = (pos_list[j]>>63) != skip; - self_p = i; - ref_p = pos_list[j] & idx->pos_mode; - uID = (pos_list[j] << 1) >> (64 - idx->uID_bits); - u_len = idx->ug->u.a[uID].len; - if(rev) ref_p = u_len - 1 - (ref_p + 1 - k_mer); - p->off_cnt = self_p | ((uint64_t)k_mer << 32); ///high bits should be the legnth - - p->ref = ref_p >= self_p? (ref_p-self_p) - : (self_p-ref_p) + ((uint64_t)1 << (idx->pos_bits - 1)); - p->ref = (rev << 63)|(pos_list[j] & idx->uID_mode)|(p->ref&idx->pos_mode); - - - /*******************************for debug************************************/ - // if(check_exact_match(r, i + 1 - k_mer, len, - // idx->ug->u.a[uID].s, ref_p + 1 - k_mer, u_len, k_mer, rev, 0) != k_mer - // || - // check_exact_match(r, i, len, - // idx->ug->u.a[uID].s, ref_p, u_len, k_mer, rev, 1) != k_mer) - // { - // fprintf(stderr, "ERROR\n"); - // } - /*******************************for debug************************************/ - } - - if(cnt == 1) - { - ///uint64_t debug_right = 0, debug_left = 0, debug_len; - - j = check_exact_match(r, self_p + 1, len, idx->ug->u.a[uID].s, ref_p + 1, u_len, len, rev, 0); - - ///debug_right = j; - ///if(j == 0) continue; - if((j + 1) >= k_mer) - { - l = 0, x[0] = x[1] = x[2] = x[3] = 0; - i = i + j - (k_mer - 1); - } - else - { - ///l = i - (i + j - (k_mer - 1)); - l = k_mer - j -1; - } - buf->a.a[buf->a.n-1].off_cnt += ((uint64_t)j << 32) + j; - - if(self_p >= k_mer && ref_p >= k_mer) - { - j = check_exact_match(r, self_p - k_mer, len, idx->ug->u.a[uID].s, - ref_p - k_mer, u_len, len, rev, 1); - buf->a.a[buf->a.n-1].off_cnt += ((uint64_t)j << 32); - ///debug_left = j; - } - - - // debug_len = check_exact_match(r, self_p + debug_right, len, idx->ug->u.a[uID].s, - // ref_p + debug_right, u_len, len, rev, 1); - // if(debug_len!= (debug_left + debug_right + k_mer)) - // { - // fprintf(stderr, "debug_len: %lu, debug_left: %lu, debug_right: %lu\n", - // debug_len, debug_left, debug_right); - // } - } - - } - - } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; // if there is an "N", restart - } - /****************************may have bugs********************************/ - - if(buf->a.n - buf_iter == 0) return; - if(buf->a.n - buf_iter > 1) radix_sort_hc_s_hit_an1(buf->a.a + buf_iter, buf->a.a + buf->a.n); - - - uint64_t cur_ref_p, thres = (len * HIC_R_E_RATE) + 1, index_beg, ovlp; - /****************************may have bugs********************************/ - uint64_t maxLen = 0, max_i = (uint64_t)-1; - /****************************may have bugs********************************/ - i = m = buf_iter; - while (i < buf->a.n) - { - interpret_pos(idx, &buf->a.a[i], &rev, &uID, &ref_p, &self_p, &cnt, NULL); - cur_ref_p = buf->a.a[i].ref; - index_beg = i; - while ((i < buf->a.n) && - ((buf->a.a[i].ref>>(idx->pos_bits-1)) == (cur_ref_p>>(idx->pos_bits-1))) && - (buf->a.a[i].ref - cur_ref_p <= thres)) - { - i++; - } - if(i - index_beg > 1) - { - radix_sort_hc_s_hit_an2(buf->a.a + index_beg, buf->a.a + i);//sort by self_p - } - ovlp = collect_votes(buf->a.a + index_beg, i - index_beg); - buf->a.a[m] = buf->a.a[i - 1]; - buf->a.a[m].off_cnt = (buf->a.a[m].off_cnt << 32)>>32; - buf->a.a[m].off_cnt += ((uint64_t)ovlp<<32); - m++; - /****************************may have bugs********************************/ - if(maxLen < (ovlp&((uint64_t)65535))) maxLen = (ovlp&((uint64_t)65535)), max_i = m; - /****************************may have bugs********************************/ - } - buf->a.n = m; - /****************************may have bugs********************************/ - ///compress_mapped_pos_advance(idx, buf, buf_iter, (k_mer * 0.1) > 0? (k_mer * 0.1) : 1); - compress_mapped_pos_debug(idx, buf, buf_iter, max_i, thres); - /****************************may have bugs********************************/ -} - -inline int is_unreliable_hits(long long rev, long long ref_p, long long tLen, uint64_t uID, trans_chain* t_ch) -{ - uint64_t i; - long long p_beg, p_end; - bed_in* p = NULL; - if(rev) - { - p_end = ref_p; - p_beg = p_end + 1 - tLen; - } - else - { - p_beg = ref_p; - p_end = p_beg + tLen - 1; - } - if(p_beg < 0) p_beg = 0; - if(p_end < 0) p_end = 0; - - p = &(t_ch->bed.a[uID]); - for (i = 0; i < p->n; i++) - { - if(inter_interval(p_beg, p_end, p->a[i].beg, p->a[i].end, NULL, NULL)) break; - } - if(p->n > 0 && i < p->n) return 1; - - return 0; -} - - -void get_5_3_list(ha_ug_index* idx, s_hit* p, uint64_t cnt, s_hit** l5, uint64_t* l5_occ, -s_hit** l3, uint64_t* l3_occ) -{ - (*l5) = (*l3) = NULL; - (*l5_occ) = (*l3_occ) = 0; - uint64_t i, j, rev, uID, ref_p, self_p, eLen, tLen, cur_beg, num; - uint64_t beg_5 = (uint64_t)-1; - for (j = 1, i = 0, num = 0; j <= cnt; ++j) - { - if(j == cnt || p[j].off_cnt != p[i].off_cnt) - { - interpret_pos((ha_ug_index*)idx, &p[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - ///cur_end = self_p; - cur_beg = self_p + 1 - tLen; - num++; - if(cur_beg <= beg_5) - { - (*l3_occ) = (*l5_occ); (*l3) = (*l5); - beg_5 = cur_beg; (*l5_occ) = j - i; (*l5) = p + i; - } - else - { - (*l3_occ) = j - i; (*l3) = p + i; - } - i = j;///must - } - } - - ///if(num > 2) fprintf(stderr, "ERROR: get_5_3_list\n"); -} - -inline void set_pe_pos_hap(ha_ug_index* idx, s_hit *l1, uint64_t occ1, s_hit *l2, uint64_t occ2, -pe_hit_hap* x, uint64_t rid, trans_chain *t_ch) -{ - if(occ1 == 0 || occ2 == 0) return; - uint64_t rev, uID, ref_p, self_p, eLen, tLen, i, is_unreliable = 0; - s_hit *l1_5 = NULL, *l1_3 = NULL, *l2_5 = NULL, *l2_3 = NULL; - uint64_t l1_5_occ = 0, l1_3_occ = 0, l2_5_occ = 0, l2_3_occ = 0; - - /***************************for debug******************************/ - // fprintf(stderr, "\nrid: %lu, occ1: %lu, occ2: %lu\n", rid, occ1, occ2); - // for (i = 0; i < occ1; i++) - // { - // interpret_pos(idx, &l1[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - // fprintf(stderr, "***-1-rev: %lu, uID: %lu, ref_p: %lu, self_p: %lu\n", - // rev, uID, ref_p, self_p); - // } - - // for (i = 0; i < occ2; i++) - // { - // interpret_pos(idx, &l2[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - // fprintf(stderr, "***-2-rev: %lu, uID: %lu, ref_p: %lu, self_p: %lu\n", - // rev, uID, ref_p, self_p); - // } - /***************************for debug******************************/ - - - get_5_3_list(idx, l1, occ1, &l1_5, &l1_5_occ, &l1_3, &l1_3_occ); - get_5_3_list(idx, l2, occ2, &l2_5, &l2_5_occ, &l2_3, &l2_3_occ); - if(l1_5_occ == 0 || l2_5_occ == 0) return; - x->id = rid; - MALLOC(x->a, l1_5_occ + l2_5_occ); - - x->occ1 = 0; - for (i = 0; i < l1_5_occ; i++) - { - interpret_pos(idx, &l1_5[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - if(ref_p < self_p) continue; - ref_p -= self_p; - if(rev) ref_p = idx->ug->u.a[uID].len - 1 - ref_p; - if(t_ch && (is_unreliable_hits(rev, ref_p, tLen, uID, t_ch))) - { - is_unreliable = 1; - continue; - } - x->a[x->occ1++] = (rev<<63) | ((uID << (64-idx->uID_bits))>>1) | (ref_p & idx->pos_mode); - } - - x->occ2 = x->occ1; - for (i = 0; i < l2_5_occ; i++) - { - interpret_pos(idx, &l2_5[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - if(ref_p < self_p) continue; - ref_p -= self_p; - if(rev) ref_p = idx->ug->u.a[uID].len - 1 - ref_p; - if(t_ch && (is_unreliable_hits(rev, ref_p, tLen, uID, t_ch))) - { - is_unreliable = 1; - continue; - } - x->a[x->occ2++] = (rev<<63) | ((uID << (64-idx->uID_bits))>>1) | (ref_p & idx->pos_mode); - } - x->occ2 -= x->occ1; - - if(x->occ1 == 0 || x->occ2 == 0 || is_unreliable) - { - free(x->a); x->occ1 = x->occ2 = 0; x->a = NULL; x->id = (uint64_t)-1; - return; - } - - - if(x->occ1 > 1) radix_sort_hc64(x->a, x->a + x->occ1); - if(x->occ2 > 1) radix_sort_hc64(x->a + x->occ1, x->a + x->occ1 + x->occ2); - - - /***************************for debug******************************/ - // fprintf(stderr, "-------------saved: x->occ1: %u, x->occ2: %u-------------\n", x->occ1, x->occ2); - // for (i = 0; i < x->occ1; i++) - // { - // fprintf(stderr, "###-1-rev: %lu, uID: %lu, ref_p: %lu\n", - // x->a[i]>>63, (x->a[i]<<1)>>(64-idx->uID_bits), x->a[i] & idx->pos_mode); - // } - - // for (i = 0; i < x->occ2; i++) - // { - // fprintf(stderr, "###-2-rev: %lu, uID: %lu, ref_p: %lu\n", - // x->a[i+x->occ1]>>63, (x->a[i+x->occ1]<<1)>>(64-idx->uID_bits), x->a[i+x->occ1] & idx->pos_mode); - // } - // fprintf(stderr, "-------------get_pe_s-rev: %lu, uID: %lu, ref_p: %lu-------------\n", - // get_pe_s(*x)>>63, (get_pe_s(*x)<<1)>>(64-idx->uID_bits), get_pe_s(*x) & idx->pos_mode); - // fprintf(stderr, "-------------get_pe_e-rev: %lu, uID: %lu, ref_p: %lu-------------\n", - // get_pe_e(*x)>>63, (get_pe_e(*x)<<1)>>(64-idx->uID_bits), get_pe_e(*x) & idx->pos_mode); - /***************************for debug******************************/ -} - -inline void set_pe_pos(ha_ug_index* idx, s_hit *l1, uint64_t occ1, s_hit *l2, uint64_t occ2, -pe_hit* x, uint64_t rid, trans_chain* t_ch) -{ - if(occ1 == 0 || occ2 == 0) return; - uint64_t rev, uID, ref_p, self_p, eLen, tLen, i, is_unreliable = 0; - s_hit *l1_5 = NULL, *l1_3 = NULL, *l2_5 = NULL, *l2_3 = NULL; - uint64_t l1_5_occ = 0, l1_3_occ = 0, l2_5_occ = 0, l2_3_occ = 0; - - /***************************for debug******************************/ - // fprintf(stderr, "\nrid: %lu, occ1: %lu, occ2: %lu\n", rid, occ1, occ2); - // for (i = 0; i < occ1; i++) - // { - // interpret_pos(idx, &l1[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - // fprintf(stderr, "***-1-rev: %lu, uID: %lu, ref_p: %lu, self_p: %lu\n", - // rev, uID, ref_p, self_p); - // } - - // for (i = 0; i < occ2; i++) - // { - // interpret_pos(idx, &l2[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - // fprintf(stderr, "***-2-rev: %lu, uID: %lu, ref_p: %lu, self_p: %lu\n", - // rev, uID, ref_p, self_p); - // } - /***************************for debug******************************/ - - - get_5_3_list(idx, l1, occ1, &l1_5, &l1_5_occ, &l1_3, &l1_3_occ); - get_5_3_list(idx, l2, occ2, &l2_5, &l2_5_occ, &l2_3, &l2_3_occ); - if(l1_5_occ == 0 || l2_5_occ == 0) return; - x->id = rid; x->len = 0; - - ///if(l1_5_occ != 1 || l2_5_occ != 1) fprintf(stderr, "ERROR\n"); - - for (i = 0; i < l1_5_occ; i++) - { - interpret_pos(idx, &l1_5[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - if((ref_p + 1) < tLen) continue; - ref_p = ref_p + 1 - tLen; - if(rev) ref_p = idx->ug->u.a[uID].len - 1 - ref_p; - - if(t_ch && (is_unreliable_hits(rev, ref_p, tLen, uID, t_ch))) - { - is_unreliable = 1; - continue; - } - x->s = (rev<<63) | ((uID << (64-idx->uID_bits))>>1) | (ref_p & idx->pos_mode); - x->len = tLen; x->len <<= 32; - } - - for (i = 0; i < l2_5_occ; i++) - { - interpret_pos(idx, &l2_5[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - if((ref_p + 1) < tLen) continue; - ref_p = ref_p + 1 - tLen; - if(rev) ref_p = idx->ug->u.a[uID].len - 1 - ref_p; - - if(t_ch && (is_unreliable_hits(rev, ref_p, tLen, uID, t_ch))) - { - is_unreliable = 1; - continue; - } - x->e = (rev<<63) | ((uID << (64-idx->uID_bits))>>1) | (ref_p & idx->pos_mode); - x->len |= tLen; - } - - if(is_unreliable || x->s == (uint64_t)-1 || x->e == (uint64_t)-1) - { - x->id = x->s = x->e = x->len = (uint64_t)-1; - return; - } - - - /****************************may have bugs********************************/ - // for (i = 0; i < l1_3_occ; i++) - // { - // interpret_pos(idx, &l1_3[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - // if(uID != ((x->s << 1) >> (64 - idx->uID_bits)) && - // uID != ((x->e << 1) >> (64 - idx->uID_bits))) - // { - // x->id = x->s = x->e = x->len = (uint64_t)-1; - // return; - // } - // } - - // for (i = 0; i < l2_3_occ; i++) - // { - // interpret_pos(idx, &l2_3[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - // if(uID != ((x->s << 1) >> (64 - idx->uID_bits)) && - // uID != ((x->e << 1) >> (64 - idx->uID_bits))) - // { - // x->id = x->s = x->e = x->len = (uint64_t)-1; - // return; - // } - // } - /****************************may have bugs********************************/ - - - - - /***************************for debug******************************/ - // fprintf(stderr, "-------------saved: x->occ1: %u, x->occ2: %u-------------\n", x->occ1, x->occ2); - // for (i = 0; i < x->occ1; i++) - // { - // fprintf(stderr, "###-1-rev: %lu, uID: %lu, ref_p: %lu\n", - // x->a[i]>>63, (x->a[i]<<1)>>(64-idx->uID_bits), x->a[i] & idx->pos_mode); - // } - - // for (i = 0; i < x->occ2; i++) - // { - // fprintf(stderr, "###-2-rev: %lu, uID: %lu, ref_p: %lu\n", - // x->a[i+x->occ1]>>63, (x->a[i+x->occ1]<<1)>>(64-idx->uID_bits), x->a[i+x->occ1] & idx->pos_mode); - // } - // fprintf(stderr, "-------------get_pe_s-rev: %lu, uID: %lu, ref_p: %lu-------------\n", - // get_pe_s(*x)>>63, (get_pe_s(*x)<<1)>>(64-idx->uID_bits), get_pe_s(*x) & idx->pos_mode); - // fprintf(stderr, "-------------get_pe_e-rev: %lu, uID: %lu, ref_p: %lu-------------\n", - // get_pe_e(*x)>>63, (get_pe_e(*x)<<1)>>(64-idx->uID_bits), get_pe_e(*x) & idx->pos_mode); - /***************************for debug******************************/ -} - - -uint64_t if_debug_read(uint64_t rid) -{ - if(rid == 1169718 || rid == 2665829 || rid == 4239289) - { - return 1; - } - return 0; -} - -static void worker_for_alignment(void *data, long i, int tid) // callback for kt_for() -{ - stepdat_t *s = (stepdat_t*)data; - ///s->pos[i].id = (uint64_t)-1; s->pos[i].occ1 = s->pos[i].occ2 = 0; s->pos[i].a = NULL; - s->pos[i].id = s->pos[i].s = s->pos[i].e = s->pos[i].len = (uint64_t)-1; - - /*******************************for debug************************************/ - // if(!if_debug_read(s->id+i)) return; - // fprintf(stderr, "work-rid: %lu\n", (uint64_t)(s->id+i)); - /*******************************for debug************************************/ - - uint64_t len1 = s->len[i]>>32, len2 = (uint32_t)s->len[i], occ1, occ2; - char *r1 = s->seq[i], *r2 = s->seq[i] + len1; - - - // fprintf(stderr, "**********R1**********\n"); - s->pos_buf[tid].a.n = 0; - get_alignment(r1, len1, s->idx->k, &s->pos_buf[tid], s->idx, 0, s->id+i); - occ1 = s->pos_buf[tid].a.n; - if(occ1 == 0) return; - - - // fprintf(stderr, "**********R2**********\n"); - get_alignment(r2, len2, s->idx->k, &s->pos_buf[tid], s->idx, occ1, s->id+i); - occ2 = s->pos_buf[tid].a.n - occ1; - if(occ2 == 0) return; - - set_pe_pos((ha_ug_index*)s->idx, s->pos_buf[tid].a.a, occ1, s->pos_buf[tid].a.a + occ1, occ2, &(s->pos[i]), s->id+i, s->t_ch); - - /*******************************for debug************************************/ - // if(memcmp(r1, R1.r.a + R1.r_Len.a[s->id+i], len1) != 0) - // { - // fprintf(stderr, "haha1\n"); - // } - // if(memcmp(r2, R2.r.a + R2.r_Len.a[s->id+i], len2) != 0) - // { - // fprintf(stderr, "haha2\n"); - // } - // uint64_t j, rev, uID, ref_p, self_p, eLen, tLen; - // char dir[2] = {'+', '-'}; - // fprintf(stderr, "(R1) %.*s\n", (int)(R1.name_Len.a[s->id + i + 1] - R1.name_Len.a[s->id+i]), - // R1.name.a + R1.name_Len.a[s->id+i]); - // for (j = 0; j < occ1; j++) - // { - // interpret_pos(s->idx, &s->pos_buf[tid].a.a[j], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - // fprintf(stderr, "utg%.6lu\t%c\t%lu\t%lu-%lu\n", uID+1, dir[rev], ref_p, self_p + 1 - tLen, self_p); - // } - // fprintf(stderr, "(R2) %.*s\n", (int)(R2.name_Len.a[s->id + i + 1] - R2.name_Len.a[s->id+i]), - // R2.name.a + R2.name_Len.a[s->id+i]); - // for (j = 0; j < occ2; j++) - // { - // interpret_pos(s->idx, &s->pos_buf[tid].a.a[j+occ1], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); - // fprintf(stderr, "utg%.6lu\t%c\t%lu\t%lu-%lu\n", uID+1, dir[rev], ref_p, self_p + 1 - tLen, self_p); - // } - // fprintf(stderr, "\n"); - /*******************************for debug************************************/ -} - -static void *worker_pipeline(void *data, int step, void *in) // callback for kt_pipeline() -{ - sldat_t *p = (sldat_t*)data; - ///uint64_t total_base = 0, total_pair = 0; - if (step == 0) { // step 1: read a block of sequences - int ret1, ret2; - uint64_t l1, l2; - stepdat_t *s; - CALLOC(s, 1); - s->idx = p->idx; s->id = p->total_pair; s->t_ch = p->t_ch; - while (((ret1 = kseq_read(p->ks1)) >= 0)&&((ret2 = kseq_read(p->ks2)) >= 0)) - { - if (p->ks1->seq.l < p->idx->k || p->ks2->seq.l < p->idx->k) continue; - if (s->n == s->m) { - s->m = s->m < 16? 16 : s->m + (s->n>>1); - REALLOC(s->len, s->m); - REALLOC(s->seq, s->m); - } - - l1 = p->ks1->seq.l; l2 = p->ks2->seq.l; - MALLOC(s->seq[s->n], l1+l2); - s->sum_len += l1+l2; - memcpy(s->seq[s->n], p->ks1->seq.s, l1); - memcpy(s->seq[s->n]+l1, p->ks2->seq.s, l2); - s->len[s->n++] = (uint64_t)(l1<<32)|(uint64_t)l2; - - if (s->sum_len >= p->chunk_size) break; - } - p->total_pair += s->n; - if (s->sum_len == 0) free(s); - else return s; - } - else if (step == 1) { // step 2: alignment - stepdat_t *s = (stepdat_t*)in; - CALLOC(s->pos_buf, p->n_thread); - CALLOC(s->pos, s->n); - int i; - kt_for(p->n_thread, worker_for_alignment, s, s->n); - for (i = 0; i < s->n; ++i) { - free(s->seq[i]); - p->total_base += (s->len[i]>>32) + (uint32_t)s->len[i]; - } - - free(s->seq); free(s->len); - for (i = 0; i < (int)p->n_thread; ++i) { - free(s->pos_buf[i].a.a); - } - free(s->pos_buf); - return s; - } - else if (step == 2) { // step 3: dump - stepdat_t *s = (stepdat_t*)in; - int i; - for (i = 0; i < s->n; ++i) { - // if(s->pos[i].a == NULL) continue; - // kv_push(pe_hit_hap, p->hits, s->pos[i]); - if(s->pos[i].s == (uint64_t)-1) continue; - kv_push(pe_hit, p->hits.a, s->pos[i]); - } - free(s->pos); - free(s); - } - return 0; -} - - -int load_reads(reads_t* x, const enzyme *fn1, const enzyme *fn2) -{ - kv_init(x->name); - kv_init(x->name_Len); - kv_init(x->r); - kv_init(x->r_Len); - - int ret; - uint64_t name_tot, base_total; - int i; - name_tot = base_total = 0; - - for (i = 0; i < fn1->n && i < fn2->n; i++) - { - gzFile fp; - if ((fp = gzopen(fn1->a[i], "r")) == 0) - { - kv_destroy(x->name); - kv_destroy(x->name_Len); - kv_destroy(x->r); - kv_destroy(x->r_Len); - return 0; - } - - kseq_t *ks; - ks = kseq_init(fp); - - while (((ret = kseq_read(ks)) >= 0)) - { - kv_push(uint64_t, x->name_Len, name_tot); - kv_resize(char, x->name, name_tot + ks->name.l); - memcpy(x->name.a + name_tot, ks->name.s, ks->name.l); - name_tot += ks->name.l; - - kv_push(uint64_t, x->r_Len, base_total); - kv_resize(char, x->r, base_total + ks->seq.l); - memcpy(x->r.a + base_total, ks->seq.s, ks->seq.l); - base_total += ks->seq.l; - } - - kseq_destroy(ks); - gzclose(fp); - } - kv_push(uint64_t, x->name_Len, name_tot); - kv_push(uint64_t, x->r_Len, base_total); - x->idx = 0; - return 1; -} - - -void test_reads(reads_t* x, const char *fn) -{ - gzFile fp; - kseq_t *ks; - int ret, i = 0; - - if ((fp = gzopen(fn, "r")) == 0) return; - ks = kseq_init(fp); - while (((ret = kseq_read(ks)) >= 0)) - { - if(memcmp(ks->name.s, x->name.a + x->name_Len.a[i], ks->name.l) != 0) - { - fprintf(stderr, "ERROR222: i: %d, len: %lu\n", i, x->name_Len.a[i]); - } - i++; - } - - kseq_destroy(ks); - gzclose(fp); -} - -void destory_reads(reads_t* x) -{ - kv_destroy(x->name); - kv_destroy(x->name_Len); - kv_destroy(x->r); - kv_destroy(x->r_Len); -} - -void print_hits(ha_ug_index* idx, kvec_pe_hit* hits, const enzyme *fn1, const enzyme *fn2) -{ - uint64_t k, shif = 64 - idx->uID_bits; - reads_t r1; - load_reads(&r1, fn1, fn2); - char dir[2] = {'+', '-'}; - for (k = 0; k < hits->a.n; ++k) - { - fprintf(stderr, "%.*s\t%c\ts-utg%.6dl\t%lu\t%c\te-utg%.6dl\t%lu\ti:%lu\n", - (int)(r1.name_Len.a[hits->a.a[k].id + 1] - r1.name_Len.a[hits->a.a[k].id]), - r1.name.a + r1.name_Len.a[hits->a.a[k].id], - dir[hits->a.a[k].s>>63], (int)((hits->a.a[k].s<<1)>>shif)+1, hits->a.a[k].s&idx->pos_mode, - dir[hits->a.a[k].e>>63], (int)((hits->a.a[k].e<<1)>>shif)+1, hits->a.a[k].e&idx->pos_mode, - hits->a.a[k].id); - } - destory_reads(&r1); -} - -void print_hits_simp(ha_ug_index* idx, kvec_pe_hit* hits) -{ - uint64_t k, shif = 64 - idx->uID_bits; - char dir[2] = {'+', '-'}; - for (k = 0; k < hits->a.n; ++k) - { - if(((hits->a.a[k].s<<1)>>shif) == ((hits->a.a[k].e<<1)>>shif)) continue; - fprintf(stderr, "r-%lu-th\t%c\trs-utg%.6dl\t%lu\t%c\tre-utg%.6dl\t%lu\n", - hits->a.a[k].id, - dir[hits->a.a[k].s>>63], (int)((hits->a.a[k].s<<1)>>shif)+1, hits->a.a[k].s&idx->pos_mode, - dir[hits->a.a[k].e>>63], (int)((hits->a.a[k].e<<1)>>shif)+1, hits->a.a[k].e&idx->pos_mode); - } -} - -inline void swap_pe_hit_hap(pe_hit_hap* x, pe_hit_hap* y) -{ - pe_hit_hap tmp; - tmp = (*x); (*x) = (*y); (*y) = tmp; -} - -void dedup_hits(kvec_pe_hit* hits, uint64_t is_dup) -{ - double index_time = yak_realtime(); - uint64_t k, l, m = 0, cur; - radix_sort_pe_hit_an1(hits->a.a, hits->a.a + hits->a.n); - for (k = 1, l = 0; k <= hits->a.n; ++k) - { - if (k == hits->a.n || hits->a.a[k].s != hits->a.a[l].s) - { - if (k - l > 1) radix_sort_pe_hit_an2(hits->a.a + l, hits->a.a + k); - if(is_dup) - { - cur = (uint64_t)-1; - while (l < k) - { - if(hits->a.a[l].e != cur) - { - cur = hits->a.a[l].e; - hits->a.a[m++] = hits->a.a[l]; - } - l++; - } - } - l = k; - } - } - if(is_dup) hits->a.n = m; - fprintf(stderr, "[M::%s::%.3f] ==> Dedup\n", __func__, yak_realtime()-index_time); -} - -void sort_hits(kvec_pe_hit* hits) -{ - double index_time = yak_realtime(); - uint64_t k, l; - radix_sort_pe_hit_an1(hits->a.a, hits->a.a + hits->a.n); - for (k = 1, l = 0; k <= hits->a.n; ++k) - { - if (k == hits->a.n || (hits->a.a[k].s<<1) != (hits->a.a[l].s<<1)) - { - if (k - l > 1) radix_sort_pe_hit_an2(hits->a.a + l, hits->a.a + k); - l = k; - } - } - fprintf(stderr, "[M::%s::%.3f] ==> Sort\n", __func__, yak_realtime()-index_time); -} - -void destory_bubbles(bubble_type* bub) -{ - if(bub->index) free(bub->index); - kv_destroy(bub->list); - kv_destroy(bub->num); - kv_destroy(bub->pathLen); - kv_destroy(bub->b_s_idx); - kv_destroy(bub->chain_weight); - asg_destroy(bub->b_g); - ma_ug_destroy(bub->b_ug); -} - -void get_bubbles(bubble_type* bub, uint64_t id, uint32_t* beg, uint32_t* sink, uint32_t** a, uint32_t* n, uint64_t* pathBase) -{ - if(a) (*a) = bub->list.a + bub->num.a[id] + 2; - if(n) (*n) = bub->num.a[id+1] - bub->num.a[id] - 2; - if(beg) (*beg) = bub->list.a[bub->num.a[id]]; - if(sink) (*sink) = bub->list.a[bub->num.a[id] + 1]; - if(pathBase) (*pathBase) = bub->pathLen.a[id]; -} - -void dfs_bubble_broken(asg_t *g, kvec_t_u32_warp* stack, kvec_t_u32_warp* result, uint8_t* vis_flag, -uint32_t vis_flag_n, uint32_t v_d, uint32_t beg_d, uint32_t sink_d) -{ - memset(vis_flag, 0, vis_flag_n); - asg_arc_t *acur = NULL; - uint32_t cur, ncur, i, p_beg = (uint32_t)-1, p_sink = (uint32_t)-1, v; - stack->a.n = result->a.n = 0; - v = v_d; - if(v != (beg_d^1) && v != (sink_d^1)) kv_push(uint32_t, stack->a, v); - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - vis_flag[cur] = 1; - if((v>>1) != (cur>>1)) kv_push(uint32_t, result->a, cur>>1); - ncur = asg_arc_n(g, cur); - acur = asg_arc_a(g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if(vis_flag[acur[i].v]) continue; - if((acur[i].v>>1) == (beg_d>>1) || (acur[i].v>>1) == (sink_d>>1)) - { - if((acur[i].v>>1) == (beg_d>>1)) p_beg = acur[i].v; - if((acur[i].v>>1) == (sink_d>>1)) p_sink = acur[i].v; - continue; - } - kv_push(uint32_t, stack->a, acur[i].v); - } - } - - memset(vis_flag, 0, vis_flag_n); - v ^= 1; - if(v != (beg_d^1) && v != (sink_d^1)) kv_push(uint32_t, stack->a, v); - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - vis_flag[cur] = 1; - if((v>>1) != (cur>>1)) kv_push(uint32_t, result->a, cur>>1); - ncur = asg_arc_n(g, cur); - acur = asg_arc_a(g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if(vis_flag[acur[i].v]) continue; - if((acur[i].v>>1) == (beg_d>>1) || (acur[i].v>>1) == (sink_d>>1)) - { - if((acur[i].v>>1) == (beg_d>>1)) p_beg = acur[i].v; - if((acur[i].v>>1) == (sink_d>>1)) p_sink = acur[i].v; - continue; - } - kv_push(uint32_t, stack->a, acur[i].v); - } - } - - if(p_beg != (uint32_t)-1) kv_push(uint32_t, result->a, beg_d>>1); - if(p_sink != (uint32_t)-1) kv_push(uint32_t, result->a, sink_d>>1); -} - -void dfs_bubble(asg_t *g, kvec_t_u32_warp* stack, kvec_t_u32_warp* result, uint32_t v, uint32_t beg, uint32_t sink) -{ - asg_arc_t *acur = NULL; - uint32_t cur, ncur, i; - stack->a.n = result->a.n = 0; - v = v << 1; - kv_push(uint32_t, stack->a, v); - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - if((v>>1) != (cur>>1)) kv_push(uint32_t, result->a, cur>>1); - ncur = asg_arc_n(g, cur); - acur = asg_arc_a(g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if((acur[i].v>>1) == beg || (acur[i].v>>1) == sink) continue; - kv_push(uint32_t, stack->a, acur[i].v); - } - } - - - v = v + 1; - kv_push(uint32_t, stack->a, v); - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - if((v>>1) != (cur>>1)) kv_push(uint32_t, result->a, cur>>1); - ncur = asg_arc_n(g, cur); - acur = asg_arc_a(g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if((acur[i].v>>1) == beg || (acur[i].v>>1) == sink) continue; - kv_push(uint32_t, stack->a, acur[i].v); - } - } -} - -uint32_t get_unitig_het_arb(ma_ug_t* ug, uint32_t uid, uint8_t *r_het_flag, kv_u_trans_t *ref, uint32_t m_het_occ, -uint32_t m_het_label, uint32_t p_het_label, uint32_t n_het_label) -{ - if(ref && ref->idx.n > 0 && u_trans_n(*ref, uid) > 0) return m_het_label; - ma_utg_t *u = &(ug->u.a[uid]); - uint32_t k, rId; - uint32_t het_occ, hom_occ; - for (k = 0, het_occ = hom_occ = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - if((r_het_flag[rId] & P_HET)) return m_het_label; - if((r_het_flag[rId] & C_HET) || (r_het_flag[rId] & P_HET)) - { - het_occ++; - } - else - { - hom_occ++; - } - } - - if((het_occ+hom_occ) == 0) return n_het_label; ///hom - if((het_occ > ((het_occ+hom_occ)*0.8)) && ((het_occ+hom_occ) > m_het_occ)) return m_het_label; ///must het - if(het_occ >= hom_occ) return p_het_label; ///potential het - return n_het_label; ///hom -} -void update_bub_b_s_idx(bubble_type* bub); -void identify_bubbles(ma_ug_t* ug, bubble_type* bub, uint8_t *r_het_flag, kv_u_trans_t *ref) -{ - asg_cleanup(ug->g); - if (!ug->g->is_symm) asg_symm(ug->g); - uint32_t v, n_vtx = ug->g->n_seq * 2, i, k, mode = (((uint32_t)-1)<<2); - uint32_t beg, sink, n, *a, n_occ; - uint64_t pathLen; - bub->ug = ug; - bub->b_bub = bub->b_end_bub = bub->tangle_bub = bub->cross_bub = bub->mess_bub = 0; - if(bub->round_id == 0) - { - buf_t b; memset(&b, 0, sizeof(buf_t)); b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - uint64_t tLen = get_bub_pop_max_dist_advance(ug->g, &b); - kv_init(bub->list); kv_init(bub->num); kv_init(bub->pathLen); - kv_init(bub->b_s_idx); kv_malloc(bub->b_s_idx, ug->g->n_seq); - bub->b_ug = NULL; kv_init(bub->chain_weight); - bub->b_s_idx.n = ug->g->n_seq; - memset(bub->b_s_idx.a, -1, bub->b_s_idx.n * sizeof(uint64_t)); - CALLOC(bub->index, n_vtx); - for (i = 0; i < ug->g->n_seq; i++) ug->g->seq[i].c = 0; - for (v = 0; v < n_vtx; ++v) - { - if(ug->g->seq[v>>1].del) continue; - if(asg_arc_n(ug->g, v) < 2) continue; - if((bub->index[v]&(uint32_t)3) != 0) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) - { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (i = 0; i < b.b.n; i++) - { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - bub->index[b.b.a[i]] &= mode; bub->index[b.b.a[i]] += 1; - bub->index[b.b.a[i]^1] &= mode; bub->index[b.b.a[i]^1] += 1; - } - bub->index[v] &= mode; bub->index[v] += 2; - bub->index[b.S.a[0]^1] &= mode; bub->index[b.S.a[0]^1] += 3; - } - } - - kvec_t_u32_warp stack, result; - kv_init(stack.a); kv_init(result.a); - for (v = 0; v < n_vtx; ++v) - { - if((bub->index[v]&(uint32_t)3) !=2) continue; - if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, &pathLen, NULL, NULL, 0, 0, NULL)) - { - //note b.b include end, does not include beg - i = b.b.n + 1; - if(b.b.n == 2 || b.b.n == 3 || b.b.n == 5) - { - for (i = 0; i < b.b.n; i++) - { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - dfs_bubble(ug->g, &stack, &result, b.b.a[i]>>1, v>>1, b.S.a[0]>>1); - if((result.a.n + 3) != b.b.n && (result.a.n + 2) != b.b.n) break; - } - } - - if(i == b.b.n) - { - kv_push(uint32_t, bub->num, v); - } - else - { - kv_push(uint32_t, bub->num, v + (1<<31)); - } - } - } - kv_destroy(stack.a); kv_destroy(result.a); - radix_sort_u32(bub->num.a, bub->num.a + bub->num.n); - bub->s_bub = 0; - for (k = 0; k < bub->num.n; k++) - { - if((bub->num.a[k]>>31) == 0) bub->s_bub++; - v = (bub->num.a[k]<<1)>>1; - bub->num.a[k] = bub->list.n; - if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, &pathLen, NULL, NULL, 0, 0, NULL)) - { - kv_push(uint64_t, bub->pathLen, pathLen); - //beg is v, end is b.S.a[0] - kv_push(uint32_t, bub->list, v); - kv_push(uint32_t, bub->list, b.S.a[0]^1); - - //note b.b include end, does not include beg - for (i = 0; i < b.b.n; i++) - { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - kv_push(uint32_t, bub->list, b.b.a[i]); - } - } - } - kv_push(uint32_t, bub->num, bub->list.n); - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - bub->f_bub = bub->num.n - 1; ///bub->s_bub = bub->num.n - 1; - - for (i = 0; i < ug->g->n_seq; i++) - { - bub->index[i] = get_unitig_het_arb(ug, i, r_het_flag, ref, 20, M_het(*bub), P_het(*bub), (uint32_t)-1); - } - for (i = 0; i < bub->f_bub; i++) - { - get_bubbles(bub, i, &beg, &sink, &a, &n, &pathLen); - for (v = n_occ = 0; v < n; v++) - { - bub->index[(a[v]>>1)] = i; - n_occ += ug->u.a[a[v]>>1].n; - } - - // if((pathLen*2) >= ug->g->seq[beg>>1].len && (pathLen*2) >= ug->g->seq[sink>>1].len) - // { - // bub->index[(beg>>1)] = (uint32_t)-1; - // bub->index[(sink>>1)] = (uint32_t)-1; - // } - - if(n_occ > 3) - { - if(bub->index[(beg>>1)] != M_het(*bub)) bub->index[(beg>>1)] = (uint32_t)-1; - if(bub->index[(sink>>1)] != M_het(*bub)) bub->index[(sink>>1)] = (uint32_t)-1; - } - - - v = beg>>1; - if(bub->b_s_idx.a[v] == (uint64_t)-1) - { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } - else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) - { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } - - - v = sink>>1; - if(bub->b_s_idx.a[v] == (uint64_t)-1) - { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } - else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) - { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } - } - for (i = 0; i < ug->g->n_seq; i++) - { - if(bub->index[i] == M_het(*bub)) bub->index[i] = P_het(*bub); - } - } - else - { - bub->num.n = bub->f_bub + 1; - bub->pathLen.n = bub->f_bub; - bub->list.n = bub->num.a[bub->num.n-1]; - update_bub_b_s_idx(bub); - bub->check_het = 0; - asg_destroy(bub->b_g); bub->b_g = NULL; - ma_ug_destroy(bub->b_ug); bub->b_ug = NULL; - kv_destroy(bub->chain_weight); kv_init(bub->chain_weight); - } - bub->b_g = NULL; - bub->b_ug = NULL; - build_bub_graph(ug, bub); - // fprintf(stderr, "-bub->index[18759]: %u, bub->num.n: %u\n", (uint32_t)bub->index[18759], bub->num.n); -} - -uint32_t get_unitig_het_fly(ma_ug_t* ug, uint32_t uid, asg_t* sg, /**int64_t het_cov_thres,**/ -int64_t m_het_cov_thres, int64_t m_hom_cov_thres, -ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag, uint32_t m_het_occ, uint32_t m_het_label, -uint32_t p_het_label, uint32_t n_het_label) -{ - ma_utg_t *u = &(ug->u.a[uid]); - uint32_t k, i, j, rId, nv, tn, is_Unitig; - asg_arc_t *av = NULL; ma_hit_t *h; - int64_t R_bases = 0, C_bases = 0, cov; - - ///set - u = &(ug->u.a[uid]); - for (k = 0; k < u->n; k++) { - rId = u->a[k]>>33; - r_flag[rId] = 1; - } - for (i = 0; i < 2; i++) { - nv = asg_arc_n(ug->g, (uid<<1)+i); - av = asg_arc_a(ug->g, (uid<<1)+i); - for (j = 0; j < nv; j++) { - u = &(ug->u.a[av[j].v>>1]); - for (k = 0; k < u->n; k++) { - rId = u->a[k]>>33; - r_flag[rId] = 2; - } - } - } - - u = &(ug->u.a[uid]); - for (k = 0; k < u->n; k++) { - if(u->a[k] == (uint64_t)-1) continue; - rId = u->a[k]>>33; - R_bases += sg->seq[rId].len; - for (j = 0; j < (uint64_t)(sources[rId].length); j++) { - h = &(sources[rId].buffer[j]); - if(h->el != 1) continue; - tn = Get_tn((*h)); - if(sg->seq[tn].del == 1) { - ///get the id of read that contains it - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || sg->seq[tn].del == 1) continue; - } - if(sg->seq[tn].del == 1) continue; - if(r_flag[tn] == 0) continue; - if(r_flag[tn] == 1) { - C_bases += (Get_qe((*h)) - Get_qs((*h))); - } - if(r_flag[tn] == 2) { - C_bases += ((Get_qe((*h)) - Get_qs((*h)))/2); - } - } - } - - ///reset - u = &(ug->u.a[uid]); - for (k = 0; k < u->n; k++) { - rId = u->a[k]>>33; - r_flag[rId] = 0; - } - for (i = 0; i < 2; i++) { - nv = asg_arc_n(ug->g, (uid<<1)+i); - av = asg_arc_a(ug->g, (uid<<1)+i); - for (j = 0; j < nv; j++) { - u = &(ug->u.a[av[j].v>>1]); - for (k = 0; k < u->n; k++) { - rId = u->a[k]>>33; - r_flag[rId] = 0; - } - } - } - - u = &(ug->u.a[uid]); cov = 0; - if(R_bases > 0) cov = C_bases/R_bases; - // if(uid == 9253) { - // fprintf(stderr, "[M::%s::uid->%u] u->n::%u, C_bases::%ld, R_bases::%ld, het_cov_thres::%ld, m_het_occ::%u\n", - // __func__, uid, (uint32_t)u->n, C_bases, R_bases, het_cov_thres, m_het_occ); - // } - // if((cov <= (het_cov_thres*1.333333)) && (u->n >= m_het_occ)) return m_het_label; ///must het - // if((cov >= (het_cov_thres*1.6))) return n_het_label; ///hom - if((cov <= m_het_cov_thres) && (u->n >= m_het_occ)) return m_het_label; ///must het - if(cov >= m_hom_cov_thres) return n_het_label; ///hom - return p_het_label; ///potential het -} - -void identify_bubbles_recal(asg_t* sg, ma_ug_t* ug, bubble_type* bub, uint8_t *r_het_flag, ma_hit_t_alloc* sources, R_to_U* ruIndex, -kv_u_trans_t *ref) -{ - asg_cleanup(ug->g); - if (!ug->g->is_symm) asg_symm(ug->g); - uint32_t v, n_vtx = ug->g->n_seq * 2, i, k, mode = (((uint32_t)-1)<<2); - uint32_t beg, sink, n, *a, n_occ; - uint64_t pathLen, hom_cov, het_cov, m_het_cov, m_hom_cov; - bub->ug = ug; - bub->b_bub = bub->b_end_bub = bub->tangle_bub = bub->cross_bub = bub->mess_bub = 0; - - if(asm_opt.hom_global_coverage_set) { - hom_cov = asm_opt.hom_global_coverage; - } else { - hom_cov = ((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE); - } - het_cov = hom_cov/asm_opt.polyploidy; - m_het_cov = hom_cov - het_cov + (het_cov*0.333333); - m_hom_cov = hom_cov - het_cov + (het_cov*0.6); - // fprintf(stderr, "hom_cov::%lu, het_cov::%lu, m_het_cov::%lu, m_hom_cov::%lu\n", hom_cov, het_cov, m_het_cov, m_hom_cov); - - if(bub->round_id == 0) - { - buf_t b; memset(&b, 0, sizeof(buf_t)); b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - uint64_t tLen = get_bub_pop_max_dist_advance(ug->g, &b); - kv_init(bub->list); kv_init(bub->num); kv_init(bub->pathLen); - kv_init(bub->b_s_idx); kv_malloc(bub->b_s_idx, ug->g->n_seq); - bub->b_ug = NULL; kv_init(bub->chain_weight); - bub->b_s_idx.n = ug->g->n_seq; - memset(bub->b_s_idx.a, -1, bub->b_s_idx.n * sizeof(uint64_t)); - CALLOC(bub->index, n_vtx); - for (i = 0; i < ug->g->n_seq; i++) ug->g->seq[i].c = 0; - for (v = 0; v < n_vtx; ++v) - { - if(ug->g->seq[v>>1].del) continue; - if(asg_arc_n(ug->g, v) < 2) continue; - if((bub->index[v]&(uint32_t)3) != 0) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) - { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (i = 0; i < b.b.n; i++) - { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - bub->index[b.b.a[i]] &= mode; bub->index[b.b.a[i]] += 1; - bub->index[b.b.a[i]^1] &= mode; bub->index[b.b.a[i]^1] += 1; - } - bub->index[v] &= mode; bub->index[v] += 2; - bub->index[b.S.a[0]^1] &= mode; bub->index[b.S.a[0]^1] += 3; - } - } - - kvec_t_u32_warp stack, result; - kv_init(stack.a); kv_init(result.a); - for (v = 0; v < n_vtx; ++v) - { - if((bub->index[v]&(uint32_t)3) !=2) continue; - if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, &pathLen, NULL, NULL, 0, 0, NULL)) - { - //note b.b include end, does not include beg - i = b.b.n + 1; - if(b.b.n == 2 || b.b.n == 3 || b.b.n == 5) - { - for (i = 0; i < b.b.n; i++) - { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - dfs_bubble(ug->g, &stack, &result, b.b.a[i]>>1, v>>1, b.S.a[0]>>1); - if((result.a.n + 3) != b.b.n && (result.a.n + 2) != b.b.n) break; - } - } - - if(i == b.b.n) - { - kv_push(uint32_t, bub->num, v); - } - else - { - kv_push(uint32_t, bub->num, v + (1<<31)); - } - } - } - kv_destroy(stack.a); kv_destroy(result.a); - radix_sort_u32(bub->num.a, bub->num.a + bub->num.n); - bub->s_bub = 0; - for (k = 0; k < bub->num.n; k++) - { - if((bub->num.a[k]>>31) == 0) bub->s_bub++; - v = (bub->num.a[k]<<1)>>1; - bub->num.a[k] = bub->list.n; - if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, &pathLen, NULL, NULL, 0, 0, NULL)) - { - kv_push(uint64_t, bub->pathLen, pathLen); - //beg is v, end is b.S.a[0] - kv_push(uint32_t, bub->list, v); - kv_push(uint32_t, bub->list, b.S.a[0]^1); - - //note b.b include end, does not include beg - for (i = 0; i < b.b.n; i++) - { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - kv_push(uint32_t, bub->list, b.b.a[i]); - } - } - } - kv_push(uint32_t, bub->num, bub->list.n); - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - bub->f_bub = bub->num.n - 1; ///bub->s_bub = bub->num.n - 1; - - memset(r_het_flag, 0, sizeof((*r_het_flag))*sg->n_seq); - for (i = 0; i < ug->g->n_seq; i++) { - bub->index[i] = get_unitig_het_fly(ug, i, sg, m_het_cov, m_hom_cov, - sources, ruIndex, r_het_flag, 20, M_het(*bub), P_het(*bub), (uint32_t)-1); - } - - for (i = 0; i < bub->f_bub; i++) - { - get_bubbles(bub, i, &beg, &sink, &a, &n, &pathLen); - for (v = n_occ = 0; v < n; v++) - { - bub->index[(a[v]>>1)] = i; - n_occ += ug->u.a[a[v]>>1].n; - } - - // if((pathLen*2) >= ug->g->seq[beg>>1].len && (pathLen*2) >= ug->g->seq[sink>>1].len) - // { - // bub->index[(beg>>1)] = (uint32_t)-1; - // bub->index[(sink>>1)] = (uint32_t)-1; - // } - - if(n_occ > 3) - { - if(bub->index[(beg>>1)] != M_het(*bub)) bub->index[(beg>>1)] = (uint32_t)-1; - if(bub->index[(sink>>1)] != M_het(*bub)) bub->index[(sink>>1)] = (uint32_t)-1; - } - - - v = beg>>1; - if(bub->b_s_idx.a[v] == (uint64_t)-1) - { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } - else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) - { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } - - - v = sink>>1; - if(bub->b_s_idx.a[v] == (uint64_t)-1) - { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } - else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) - { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } - } - for (i = 0; i < ug->g->n_seq; i++) - { - if(bub->index[i] == M_het(*bub)) bub->index[i] = P_het(*bub); - } - } - else - { - bub->num.n = bub->f_bub + 1; - bub->pathLen.n = bub->f_bub; - bub->list.n = bub->num.a[bub->num.n-1]; - update_bub_b_s_idx(bub); - bub->check_het = 0; - asg_destroy(bub->b_g); bub->b_g = NULL; - ma_ug_destroy(bub->b_ug); bub->b_ug = NULL; - kv_destroy(bub->chain_weight); kv_init(bub->chain_weight); - } - bub->b_g = NULL; - bub->b_ug = NULL; - build_bub_graph(ug, bub); - // fprintf(stderr, "-bub->index[18759]: %u, bub->num.n: %u\n", (uint32_t)bub->index[18759], bub->num.n); -} - -void reset_inner_bub_het_poy(asg_t* sg, ma_ug_t* ug, bubble_type* bub, uint32_t bid, uint64_t tLen, buf_t *b, -uint64_t m_het_cov, uint64_t m_hom_cov, uint8_t *r_het_flag, ma_hit_t_alloc* sources, R_to_U* ruIndex) -{ - uint32_t beg, sink, *ba, bn, m, v, z, socc; - get_bubbles(bub, bid, &beg, &sink, &ba, &bn, NULL); - for (m = 0; m < bn; m++) { - v = ba[m]; - if(IF_HOM((v>>1), *bub)) continue; - if(ug->g->seq[v>>1].del) continue; - if(bub->index[v>>1] == (uint32_t)-1) continue; - - if(get_unitig_het_fly(ug, v>>1, sg, m_het_cov, m_hom_cov, sources, ruIndex, r_het_flag, 20, 1, 0, (uint32_t)-1) == 1) { - continue; - } - - if(asg_arc_n(ug->g, v) < 2) continue; - if(get_real_length(ug->g, v, NULL) < 2) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (z = socc = 0; z < b->b.n; z++) { - if(b->b.a[z]==v || b->b.a[z]==b->S.a[0]) continue; - socc += ug->u.a[b->b.a[z]>>1].n; - } - if((socc > 10) && (socc > (ug->u.a[v>>1].n*3))) { - bub->index[v>>1] = (uint32_t)-1; - } - } - - - v ^= 1; - if(bub->index[v>>1] == (uint32_t)-1) continue; - if(asg_arc_n(ug->g, v) < 2) continue; - if(get_real_length(ug->g, v, NULL) < 2) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (z = socc = 0; z < b->b.n; z++) { - if(b->b.a[z]==v || b->b.a[z]==b->S.a[0]) continue; - socc += ug->u.a[b->b.a[z]>>1].n; - } - if((socc > 10) && (socc > (ug->u.a[v>>1].n*3))) { - bub->index[v>>1] = (uint32_t)-1; - } - } - } -} - -uint32_t deter_unitig_het_fly(ma_ug_t* ug, uint32_t uid, asg_t* sg, int64_t het_cov_thres, -ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag) -{ - ma_utg_t *u = &(ug->u.a[uid]); - uint32_t k, i, j, rId, nv, tn, is_Unitig; - asg_arc_t *av = NULL; ma_hit_t *h; - int64_t R_bases = 0, C_bases = 0, cov; - - ///set - u = &(ug->u.a[uid]); - for (k = 0; k < u->n; k++) { - rId = u->a[k]>>33; - r_flag[rId] = 1; - } - for (i = 0; i < 2; i++) { - nv = asg_arc_n(ug->g, (uid<<1)+i); - av = asg_arc_a(ug->g, (uid<<1)+i); - for (j = 0; j < nv; j++) { - u = &(ug->u.a[av[j].v>>1]); - for (k = 0; k < u->n; k++) { - rId = u->a[k]>>33; - r_flag[rId] = 2; - } - } - } - - u = &(ug->u.a[uid]); - for (k = 0; k < u->n; k++) { - if(u->a[k] == (uint64_t)-1) continue; - rId = u->a[k]>>33; - R_bases += sg->seq[rId].len; - for (j = 0; j < (uint64_t)(sources[rId].length); j++) { - h = &(sources[rId].buffer[j]); - if(h->el != 1) continue; - tn = Get_tn((*h)); - if(sg->seq[tn].del == 1) { - ///get the id of read that contains it - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || sg->seq[tn].del == 1) continue; - } - if(sg->seq[tn].del == 1) continue; - if(r_flag[tn] == 0) continue; - if(r_flag[tn] == 1) { - C_bases += (Get_qe((*h)) - Get_qs((*h))); - } - if(r_flag[tn] == 2) { - C_bases += ((Get_qe((*h)) - Get_qs((*h)))/2); - } - } - } - - ///reset - u = &(ug->u.a[uid]); - for (k = 0; k < u->n; k++) { - rId = u->a[k]>>33; - r_flag[rId] = 0; - } - for (i = 0; i < 2; i++) { - nv = asg_arc_n(ug->g, (uid<<1)+i); - av = asg_arc_a(ug->g, (uid<<1)+i); - for (j = 0; j < nv; j++) { - u = &(ug->u.a[av[j].v>>1]); - for (k = 0; k < u->n; k++) { - rId = u->a[k]>>33; - r_flag[rId] = 0; - } - } - } - - u = &(ug->u.a[uid]); cov = 0; - if(R_bases > 0) cov = C_bases/R_bases; - if(cov <= het_cov_thres) return 1; - return 0; -} - -void identify_bubbles_recal_poy(asg_t* sg, ma_ug_t* ug, bubble_type* bub, uint8_t *r_het_flag, ma_hit_t_alloc* sources, R_to_U* ruIndex, -kv_u_trans_t *ref) -{ - asg_cleanup(ug->g); - if (!ug->g->is_symm) asg_symm(ug->g); - uint32_t v, n_vtx = ug->g->n_seq * 2, i, k, mode = (((uint32_t)-1)<<2); - uint32_t beg, sink, n, *a, n_occ; - uint64_t pathLen, hom_cov, het_cov, m_het_cov, m_hom_cov; - bub->ug = ug; - bub->b_bub = bub->b_end_bub = bub->tangle_bub = bub->cross_bub = bub->mess_bub = 0; - if(asm_opt.hom_global_coverage_set) { - hom_cov = asm_opt.hom_global_coverage; - } else { - hom_cov = ((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE); - } - het_cov = hom_cov/asm_opt.polyploidy; - m_het_cov = het_cov + (het_cov*0.333333);///hom_cov - het_cov + (het_cov*0.333333); - m_hom_cov = het_cov + (het_cov*0.6);///hom_cov - het_cov + (het_cov*0.6); - // fprintf(stderr, "hom_cov::%lu, het_cov::%lu, m_het_cov::%lu, m_hom_cov::%lu\n", hom_cov, het_cov, m_het_cov, m_hom_cov); - - buf_t b; memset(&b, 0, sizeof(buf_t)); b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - uint64_t tLen = get_bub_pop_max_dist_advance(ug->g, &b); - kv_init(bub->list); kv_init(bub->num); kv_init(bub->pathLen); - kv_init(bub->b_s_idx); kv_malloc(bub->b_s_idx, ug->g->n_seq); - bub->b_ug = NULL; kv_init(bub->chain_weight); - bub->b_s_idx.n = ug->g->n_seq; - memset(bub->b_s_idx.a, -1, bub->b_s_idx.n * sizeof(uint64_t)); - CALLOC(bub->index, n_vtx); - for (i = 0; i < ug->g->n_seq; i++) ug->g->seq[i].c = 0; - for (v = 0; v < n_vtx; ++v) - { - if(ug->g->seq[v>>1].del) continue; - if(asg_arc_n(ug->g, v) < 2) continue; - if((bub->index[v]&(uint32_t)3) != 0) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) - { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (i = 0; i < b.b.n; i++) - { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - bub->index[b.b.a[i]] &= mode; bub->index[b.b.a[i]] += 1; - bub->index[b.b.a[i]^1] &= mode; bub->index[b.b.a[i]^1] += 1; - } - bub->index[v] &= mode; bub->index[v] += 2; - bub->index[b.S.a[0]^1] &= mode; bub->index[b.S.a[0]^1] += 3; - } - } - - kvec_t_u32_warp stack, result; - kv_init(stack.a); kv_init(result.a); - for (v = 0; v < n_vtx; ++v) - { - if((bub->index[v]&(uint32_t)3) !=2) continue; - if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, &pathLen, NULL, NULL, 0, 0, NULL)) - { - //note b.b include end, does not include beg - i = b.b.n + 1; - if(b.b.n == 2 || b.b.n == 3 || b.b.n == 5) - { - for (i = 0; i < b.b.n; i++) - { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - dfs_bubble(ug->g, &stack, &result, b.b.a[i]>>1, v>>1, b.S.a[0]>>1); - if((result.a.n + 3) != b.b.n && (result.a.n + 2) != b.b.n) break; - } - } - - if(i == b.b.n) - { - kv_push(uint32_t, bub->num, v); - } - else - { - kv_push(uint32_t, bub->num, v + (1<<31)); - } - } - } - kv_destroy(stack.a); kv_destroy(result.a); - radix_sort_u32(bub->num.a, bub->num.a + bub->num.n); - bub->s_bub = 0; - for (k = 0; k < bub->num.n; k++) - { - if((bub->num.a[k]>>31) == 0) bub->s_bub++; - v = (bub->num.a[k]<<1)>>1; - bub->num.a[k] = bub->list.n; - if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, &pathLen, NULL, NULL, 0, 0, NULL)) - { - kv_push(uint64_t, bub->pathLen, pathLen); - //beg is v, end is b.S.a[0] - kv_push(uint32_t, bub->list, v); - kv_push(uint32_t, bub->list, b.S.a[0]^1); - - //note b.b include end, does not include beg - for (i = 0; i < b.b.n; i++) - { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - kv_push(uint32_t, bub->list, b.b.a[i]); - } - } - } - kv_push(uint32_t, bub->num, bub->list.n); - // free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - bub->f_bub = bub->num.n - 1; ///bub->s_bub = bub->num.n - 1; - - - memset(r_het_flag, 0, sizeof((*r_het_flag))*sg->n_seq); - for (i = 0; i < ug->g->n_seq; i++) { - bub->index[i] = get_unitig_het_fly(ug, i, sg, m_het_cov, m_hom_cov, - sources, ruIndex, r_het_flag, 20, M_het(*bub), P_het(*bub), (uint32_t)-1); - } - - for (i = 0; i < bub->f_bub; i++) { - get_bubbles(bub, i, &beg, &sink, &a, &n, &pathLen); - for (v = n_occ = 0; v < n; v++) { - bub->index[(a[v]>>1)] = i; - n_occ += ug->u.a[a[v]>>1].n; - } - - if(n_occ > 3) { - if(bub->index[(beg>>1)] != M_het(*bub)) bub->index[(beg>>1)] = (uint32_t)-1; - if(bub->index[(sink>>1)] != M_het(*bub)) bub->index[(sink>>1)] = (uint32_t)-1; - } - - - v = beg>>1; - if(bub->b_s_idx.a[v] == (uint64_t)-1) { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } - - - v = sink>>1; - if(bub->b_s_idx.a[v] == (uint64_t)-1) { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } - } - for (i = 0; i < ug->g->n_seq; i++) { - if(bub->index[i] == M_het(*bub)) bub->index[i] = P_het(*bub); - } - - bub->b_g = NULL; - bub->b_ug = NULL; - build_bub_graph(ug, bub); - - - ///make het nodes to be hom - ma_utg_t *u = NULL; - for (i = 0; i < bub->b_ug->u.n; i++) { - u = &(bub->b_ug->u.a[i]); - if(u->n == 0) continue; - for (k = 0; k < u->n; k++) { - reset_inner_bub_het_poy(sg, ug, bub, u->a[k]>>33, tLen, &b, m_het_cov, m_hom_cov, r_het_flag, sources, ruIndex); - } - } - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - - for (i = 0; i < ug->g->n_seq; i++) { - if(IF_HOM(i, *bub)) continue; - if(deter_unitig_het_fly(ug, i, sg, het_cov*1.15, sources, ruIndex, r_het_flag)) continue; - bub->index[i] = (uint32_t)-1; - } - // fprintf(stderr, "-bub->index[18759]: %u, bub->num.n: %u\n", (uint32_t)bub->index[18759], bub->num.n); -} - -void print_bubbles(ma_ug_t* ug, bubble_type* bub, kvec_pe_hit* hits, hc_links* link, ha_ug_index* idx) -{ - uint64_t tLen, t_utg, i, k; - uint32_t beg, sink, n, *a; - for (i = 0, tLen = 0; i < bub->ug->u.n; i++) tLen += bub->ug->u.a[i].len; - fprintf(stderr, "[M::%s] # unitigs: %lu, # bases: %lu\n", __func__, bub->ug->u.n, tLen); - for (i = 0, tLen = 0, t_utg = 0; i < bub->f_bub; i++) - { - get_bubbles(bub, i, &beg, &sink, &a, &n, NULL); - t_utg += n; - for (k = 0; k < n; k++) - { - tLen +=bub->ug->u.a[(a[k]>>1)].len; - } - } - fprintf(stderr, "[M::%s] # bubbles: %lu, # unitigs: %lu, # bases: %lu\n", __func__, - Get_bub_num(*bub), t_utg, tLen); - - - for (i = 0, tLen = 0, t_utg = 0; i < ug->g->n_seq; i++) - { - if(IF_BUB(i, *bub)) - { - t_utg++; - tLen +=bub->ug->u.a[i].len; - } - } - fprintf(stderr, "[M::%s] # bubbles: %lu, # unitigs: %lu, # bases: %lu\n", __func__, - Get_bub_num(*bub), t_utg, tLen); - - for (i = 0, tLen = 0, t_utg = 0; i < ug->g->n_seq; i++) - { - if(IF_HET(i, *bub)) - { - t_utg++; - tLen +=bub->ug->u.a[i].len; - } - } - fprintf(stderr, "[M::%s] # het unitigs: %lu, # het bases: %lu\n", __func__, t_utg, tLen); - - uint8_t* flag; CALLOC(flag, ug->g->n_seq); - uint64_t s_uid, e_uid, shif = 64 - idx->uID_bits; - if(hits) - { - for (k = 0; k < hits->a.n; ++k) - { - s_uid = ((hits->a.a[k].s<<1)>>shif); - e_uid = ((hits->a.a[k].e<<1)>>shif); - if(bub->index[s_uid] == (uint32_t)-1 || bub->index[e_uid] == (uint32_t)-1) continue; - if(IF_BUB(s_uid, *bub) && IF_BUB(e_uid, *bub)) - { - flag[s_uid] |= 1; - flag[e_uid] |= 1; - continue; - } - if(IF_HET(s_uid, *bub) && IF_HET(e_uid, *bub)) - { - flag[s_uid] |= 4; - flag[e_uid] |= 4; - continue; - } - if(IF_BUB(s_uid, *bub)) flag[s_uid] |= 2, flag[e_uid] |= 2; - if(IF_BUB(e_uid, *bub)) flag[e_uid] |= 2, flag[s_uid] |= 2; - } - } - else if(link) - { - for (i = 0; i < link->a.n; i++) - { - for (k = 0; k < link->a.a[i].e.n; ++k) - { - if(link->a.a[i].e.a[k].del) continue; - s_uid = i; - e_uid = link->a.a[i].e.a[k].uID; - if(bub->index[s_uid] == (uint32_t)-1 || bub->index[e_uid] == (uint32_t)-1) continue; - if(IF_BUB(s_uid, *bub) && IF_BUB(e_uid, *bub)) - { - flag[s_uid] |= 1; - flag[e_uid] |= 1; - continue; - } - if(IF_HET(s_uid, *bub) && IF_HET(e_uid, *bub)) - { - flag[s_uid] |= 4; - flag[e_uid] |= 4; - continue; - } - if(IF_BUB(s_uid, *bub)) flag[s_uid] |= 2, flag[e_uid] |= 2; - if(IF_BUB(e_uid, *bub)) flag[e_uid] |= 2, flag[s_uid] |= 2; - } - } - } - - - - - for (i = 0, tLen = 0, t_utg = 0; i < ug->g->n_seq; i++) - { - if(flag[i] & (uint32_t)1) - { - t_utg++; - tLen +=bub->ug->u.a[i].len; - } - } - fprintf(stderr, "[M::%s] # bubble-chained unitigs: %lu, # bubble-chained bases: %lu\n", - __func__, t_utg, tLen); - - for (i = 0, tLen = 0, t_utg = 0; i < ug->g->n_seq; i++) - { - if((flag[i] & (uint32_t)1) || (flag[i] & (uint32_t)2)) - { - t_utg++; - tLen +=bub->ug->u.a[i].len; - } - } - fprintf(stderr, "[M::%s] # (bubble && het)-chained unitigs: %lu, # (bubble && het)-chained bases: %lu\n", - __func__, t_utg, tLen); - - - for (i = 0, tLen = 0, t_utg = 0; i < ug->g->n_seq; i++) - { - if((flag[i] & (uint32_t)1) || (flag[i] & (uint32_t)2) || (flag[i] & (uint32_t)4)) - { - t_utg++; - tLen +=bub->ug->u.a[i].len; - } - } - fprintf(stderr, "[M::%s] # (bubble || het)-chained unitigs: %lu, # (bubble || het)-chained bases: %lu\n", - __func__, t_utg, tLen); - free(flag); - - - fprintf(stderr, "************bubble utgs************\n"); - uint64_t pathLen; - for (i = 0, tLen = 0, t_utg = 0; i < bub->f_bub; i++) - { - get_bubbles(bub, i, &beg, &sink, &a, &n, &pathLen); - t_utg += n; - fprintf(stderr, "(full-%lu)\tbeg:utg%.6u\tsink:utg%.6u\tpathLen:%lu\t%s\n", - i, (beg>>1)+1, (sink>>1)+1, pathLen, i < bub->s_bub? "s-bub":(if_bub?"f-bub":"b-bub")); - for (k = 0; k < n; k++) - { - tLen +=bub->ug->u.a[(a[k]>>1)].len; - fprintf(stderr, "utg%.6u,", (a[k]>>1)+1); - } - fprintf(stderr, "\n"); - ///if(i < bub->s_bub && (n != 4 && n != 2 && n != 1)) fprintf(stderr, "weird\n"); - } - - for (i = bub->f_bub, tLen = 0, t_utg = 0; i < bub->f_bub + bub->b_bub; i++) - { - get_bubbles(bub, i, &beg, &sink, &a, &n, &pathLen); - t_utg += n; - fprintf(stderr, "(broken-%lu)\tbeg:utg%.6u\tsink:utg%.6u\tpathLen:%lu\t%s\n", - i, (beg>>1)+1, (sink>>1)+1, pathLen, i < bub->s_bub? "s-bub":(if_bub?"f-bub":"b-bub")); - for (k = 0; k < n; k++) - { - tLen +=bub->ug->u.a[(a[k]>>1)].len; - fprintf(stderr, "utg%.6u,", (a[k]>>1)+1); - } - fprintf(stderr, "\n"); - } - - // fprintf(stderr, "************het utgs************\n"); - // for (i = 0; i < ug->g->n_seq; i++) - // { - // if(IF_HET(i, *bub)) fprintf(stderr, "utg%.6lu\n", i+1); - // } - // fprintf(stderr, "************het utgs************\n"); -} - -hc_edge* push_hc_edge(hc_linkeage* x, uint64_t uID, double weight, int dir, uint64_t* d) -{ - uint64_t k, n; - hc_edge* a = NULL; - hc_edge* p = NULL; - if(dir == 0) - { - a = x->e.a; - n = x->e.n; - } - else - { - a = x->f.a; - n = x->f.n; - } - - for (k = 0; k < n; k++) - { - if(a[k].del) continue; - if(a[k].uID == uID) - { - a[k].weight += weight; - if(d) a[k].dis = (*d); - return &(a[k]); - } - } - - if(dir == 0) - { - kv_pushp(hc_edge, x->e, &p); - } - else - { - kv_pushp(hc_edge, x->f, &p); - } - - ///p->del = p->enzyme = 0; - p->del = 0; - p->uID = uID; - p->weight = weight; - if(d) p->dis = (*d); - return p; -} - -long long get_enzyme_occ_debug(char* t, long long tlen, char* p, long long plen) -{ - long long s = 0, j, occ = 0; - while(s <= (tlen - plen)) - { - j = plen-1; - - while(j >= 0) - { - if(seq_nt4_table[(uint8_t)t[s+j]] >= 4) break; - if((p[j] != t[s+j]) && seq_nt4_table[(uint8_t)p[j]] < 4) break; - j--; - } - - if (j < 0) occ++; - s++; - } - - return occ; -} - -int check_exact_match(char* x, long long xlen, char* y, long long ylen) -{ - long long i; - if(xlen != ylen) return 0; - for (i = 0; i < xlen; i++) - { - if(seq_nt4_table[(uint8_t)x[i]] >= 4) return 0; - if((x[i] != y[i]) && seq_nt4_table[(uint8_t)y[i]] < 4) return 0; - } - - return 1; -} - -long long get_enzyme_occ(char* t, long long tlen, char* p, long long plen) -{ - long long i, c, s = 0, j, occ = 0; - int badchar[5]; badchar[0] = badchar[1] = badchar[2] = badchar[3] = badchar[4] = -1; - for (i = 0; i < plen; i++) - { - c = seq_nt4_table[(uint8_t)p[i]]; - badchar[c] = i; - if(c == 4) badchar[0] = badchar[1] = badchar[2] = badchar[3] = i; - } - badchar[4] = -1; - - while(s <= (tlen - plen)) - { - j = plen-1; - - while(j >= 0) - { - if(seq_nt4_table[(uint8_t)t[s+j]] >= 4) break; - if((p[j] != t[s+j]) && seq_nt4_table[(uint8_t)p[j]] < 4) break; - j--; - } - - - if (j < 0) - { - occ++; - ///s += (s+m < n)? m-badchar[txt[s+m]] : 1; - s++; - } - else - { - /*******************************for debug************************************/ - // long long f, end = s + MAX(1, j - badchar[seq_nt4_table[(uint8_t)t[s+j]]]); - // for (f = s+1; f < end; f++) - // { - // if(check_exact_match(t+f, plen, p, plen)) - // { - // fprintf(stderr, "s: %lld, end: %lld, s+j: %lld, t[s+j]: %c, badchar: %d, j: %lld\n", - // s, end, s+j, t[s+j], badchar[seq_nt4_table[(uint8_t)t[s+j]]], j); - // } - // } - /*******************************for debug************************************/ - - s += MAX(1, j - badchar[seq_nt4_table[(uint8_t)t[s+j]]]); - } - } - - return occ; -} - -#define pdq_cnt(q) ((q).x.a[0]) - -void init_pdq(pdq* q, uint64_t utg_num) -{ - kv_init(q->x); kv_push(uint64_t, q->x, 0); - kv_malloc(q->dis, utg_num); q->dis.n = utg_num; - kv_malloc(q->vis, utg_num); q->vis.n = utg_num; - - uint64_t i; - for (i = 1; (uint64_t)(1<uID_mode = ((uint64_t)-1) >> (64-i); - q->uID_shift = i; -} - -void destory_pdq(pdq* q) -{ - kv_destroy(q->x); - kv_destroy(q->dis); - kv_destroy(q->vis); -} - -void reset_pdq(pdq* q) -{ - q->x.n = 1; pdq_cnt(*q) = 0; - memset(q->dis.a, -1, sizeof(uint64_t)*q->dis.n); - memset(q->vis.a, 0, sizeof(uint8_t)*q->vis.n); -} - -void swap_pdq(uint64_t* i, uint64_t* j) -{ - uint64_t k; - k = (*i); - (*i) = (*j); - (*j) = k; -} - -#define weight(q, i) (get_dv_adv((q).x.a[i], (q).uID_mode, (q).uID_shift, &(q).tmp_v, &(q).tmp_d)) - -uint64_t inline set_dv_adv(uint64_t v, uint64_t dis, uint64_t v_mode, uint64_t v_shift) -{ - dis <<= v_shift; dis |= (v&v_mode); - return dis; -} - -uint64_t inline get_dv_adv(uint64_t x, uint64_t v_mode, uint64_t v_shift, uint64_t* v, uint64_t* dis) -{ - (*v) = x & v_mode; - (*dis) = x >> v_shift; - return (*dis); -} - -void push_pdq(pdq* q, uint64_t v, uint64_t dis) -{ - kv_push(uint64_t, q->x, set_dv_adv(v, dis, q->uID_mode, q->uID_shift)); - pdq_cnt(*q)++; - int c_i = pdq_cnt(*q), p_i = c_i>>1; - - while ((p_i > 0) && (weight(*q, c_i) < weight(*q, p_i))) - { - swap_pdq(&(q->x.a[c_i]), &(q->x.a[p_i])); - c_i = p_i; - p_i = c_i >> 1; - } -} - -void pop_pdq(pdq* q, uint64_t* min_v, uint64_t* min_dis) -{ - (*min_v) = (*min_dis) = (uint64_t)-1; - if(pdq_cnt(*q) == 0) return; - get_dv_adv((*q).x.a[1], (*q).uID_mode, (*q).uID_shift, min_v, min_dis); - /*******************************for debug************************************/ - // uint64_t i; - // for (i = 1; i < q->x.n; i++) - // { - // if(weight(*q, i) < (*min_dis)) fprintf(stderr, "ERROR\n"); - // } - /*******************************for debug************************************/ - ///min = q->x.a[1]; - swap_pdq(&(q->x.a[1]), &(q->x.a[pdq_cnt(*q)])); - pdq_cnt(*q)--; - q->x.n--; - - int c_i = 1, left_i, right_i, min_i, flag = 1; - while(flag == 1) - { - flag = 0; - left_i = c_i << 1; - right_i = left_i + 1; - if(left_i > (int)(pdq_cnt(*q))) - { - break; // both children are null - } - else if(right_i > (int)(pdq_cnt(*q))) - { - min_i = left_i; // right children is null - } - else - { - min_i = (weight(*q, left_i) < weight(*q, right_i))? left_i : right_i; - } - - if(weight(*q, c_i) > weight(*q, min_i)) - { - swap_pdq(&(q->x.a[c_i]), &(q->x.a[min_i])); - c_i = min_i; - flag = 1; - } - } -} - -void get_shortest_path(uint32_t src, pdq* pq, asg_t *sg, uint32_t* pre) -{ - uint64_t v, u, i, nv, w; - asg_arc_t *av = NULL; - reset_pdq(pq); - pq->dis.a[src] = 0; - if(pre) pre[src] = (uint32_t)-1; - push_pdq(pq, src, 0); - while (pdq_cnt(*pq) > 0) - { - pop_pdq(pq, &v, &w); - pq->vis.a[v] = 1; - - av = asg_arc_a(sg, v); - nv = asg_arc_n(sg, v); - - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - u = av[i].v; - w = (uint32_t)av[i].ul; - - if(pq->vis.a[u] == 0 && pq->dis.a[u] > pq->dis.a[v] + w) - { - pq->dis.a[u] = pq->dis.a[v] + w; - push_pdq(pq, u, pq->dis.a[u]); - if(pre) pre[u] = v; - } - } - } -} - -void all_pair_shortest_path(asg_t *sg, hc_links* link, MT* M) -{ - hc_linkeage* t = NULL; - pdq pq; - init_pdq(&pq, sg->n_seq<<1); - uint32_t n_vtx = sg->n_seq<<1, v; - uint64_t k, *p = NULL; - - for (v = 0; v < n_vtx; ++v) - { - if (sg->seq[v>>1].del) continue; - t = &(link->a.a[v>>1]); - if (t->e.n == 0) continue; - get_shortest_path(v, &pq, sg, NULL); - for (k = 0; k < pq.dis.n; k++) - { - if(pq.dis.a[k] == (uint64_t)-1) continue; - kv_pushp(uint64_t, M->matrix.a[v].a, &p); - (*p) = k << M->uID_shift; - (*p) = (*p) | pq.dis.a[k]; - } - } - - destory_pdq(&pq); -} - -typedef struct{ - pdq* pq; - uint32_t src; - asg_t *sg; - uint8_t *dest, flag; - uint64_t occ, df_occ, v; - uint32_t* pre; -}pdq_spec; - -uint32_t get_specific_shortest_path(pdq_spec *p) -{ - uint64_t u, i, nv, w; - asg_arc_t *av = NULL; - if(p->v == (uint64_t)-1) - { - // reset_pdq(p->pq); - p->pq->dis.a[p->src] = 0; - if(p->pre) p->pre[p->src] = (uint32_t)-1; - push_pdq(p->pq, p->src, 0); - p->occ = 0; - } - if(p->occ >= p->df_occ) return 0; - - while (pdq_cnt(*(p->pq)) > 0) - { - pop_pdq(p->pq, &(p->v), &w); - p->pq->vis.a[p->v] = 1; - if(p->dest && p->dest[p->v] == p->flag) p->occ++; - if(p->occ > p->df_occ) return 0; - - av = asg_arc_a(p->sg, p->v); - nv = asg_arc_n(p->sg, p->v); - - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - u = av[i].v; - w = (uint32_t)av[i].ul; - - if(p->pq->vis.a[u] == 0 && p->pq->dis.a[u] > p->pq->dis.a[p->v] + w) - { - p->pq->dis.a[u] = p->pq->dis.a[p->v] + w; - push_pdq(p->pq, u, p->pq->dis.a[u]); - if(p->pre) p->pre[u] = p->v; - } - } - if(p->dest && p->dest[p->v] == p->flag) return 1; - if(!p->dest) return 1; - } - - return 0; -} -void get_utg_path(uint64_t s, uint64_t e, uint32_t *path, buf_t *res) -{ - uint64_t p = path[e], i; - res->b.n = 0; - kv_push(uint32_t, res->b, e); - while (p != s) - { - kv_push(uint32_t, res->b, p); - p = path[p]; - } - kv_push(uint32_t, res->b, s); - for (i = 0; i < (res->b.n>>1); i++) - { - p = res->b.a[i]; - res->b.a[i] = res->b.a[res->b.n-i-1]; - res->b.a[res->b.n-i-1] = p; - } - res->b.n--; -} -uint32_t check_trans_relation_by_path(uint32_t v, uint32_t w, pdq* pqv, uint32_t* path_v, buf_t *resv, -pdq* pqw, uint32_t* path_w, buf_t *resw, asg_t *sg, uint8_t *dest, uint8_t df, uint32_t df_occ, -double rate, long long *dis) -{ - uint64_t r1, r2, d1, d2; - pdq_spec p1, p2, *p = NULL; - p1.v = (uint64_t)-1; p1.src = v; p1.pq = pqv; p1.sg = sg; p1.df_occ = df_occ; - p1.occ = df_occ; p1.flag = df; p1.dest = dest; p1.pre = path_v; if(resv) resv->b.n = 0; - reset_pdq(p1.pq); - - p2.v = (uint64_t)-1; p2.src = w; p2.pq = pqw; p2.sg = sg; p2.df_occ = df_occ; - p2.occ = df_occ; p2.flag = df; p2.dest = dest; p2.pre = path_w; if(resw) resw->b.n = 0; - reset_pdq(p2.pq); - - if(dis) (*dis) = 0; - - while (1) - { - p = &p1; - r1 = get_specific_shortest_path(p); - if(r1 && p1.pq->vis.a[p->v] && p2.pq->vis.a[p->v]) - { - d1 = p1.pq->dis.a[p->v]; d2 = p2.pq->dis.a[p->v]; - if(d1 != (uint64_t)-1 && d2 != (uint64_t)-1) - { - if(d2 <= d1*(1+rate) && d2 >= d1*(1-rate)) - { - if(resv) get_utg_path(p1.src, p->v, p1.pre, resv); - if(resw) get_utg_path(p2.src, p->v, p2.pre, resw); - if(dis) - { - (*dis) = d1 + d2; - (*dis) -= (sg->seq[p1.src>>1].len + sg->seq[p2.src>>1].len); - } - - // fprintf(stderr, "p-utg%.6ul(d1-%lu), a-utg%.6ul(d2-%lu), conver-utg%.6lul\n", - // (v>>1) + 1, d1, (w>>1) + 1, d2, (p->v>>1) + 1); - - - return 1; - } - } - } - p = &p2; - r2 = get_specific_shortest_path(p); - if(r2 && p1.pq->vis.a[p->v] && p2.pq->vis.a[p->v]) - { - d1 = p1.pq->dis.a[p->v]; d2 = p2.pq->dis.a[p->v]; - if(d1 != (uint64_t)-1 && d2 != (uint64_t)-1) - { - if(d2 <= d1*(1+rate) && d2 >= d1*(1-rate)) - { - if(resv) get_utg_path(p1.src, p->v, p1.pre, resv); - if(resw) get_utg_path(p2.src, p->v, p2.pre, resw); - if(dis) - { - (*dis) = d1 + d2; - (*dis) -= (sg->seq[p1.src>>1].len + sg->seq[p2.src>>1].len); - } - // fprintf(stderr, "p-utg%.6ul(d1-%lu), a-utg%.6ul(d2-%lu), conver-utg%.6lul\n", - // (v>>1) + 1, d1, (w>>1) + 1, d2, (p->v>>1) + 1); - return 1; - } - } - } - if(!r1 && !r2) return 0; - } - -} - -void set_utg_by_dis(uint32_t v, pdq* pq, asg_t *g, kvec_t_u32_warp *res, uint32_t dis) -{ - uint64_t r; - pdq_spec a; - a.v = (uint64_t)-1; a.src = v; a.pq = pq; a.sg = g; a.df_occ = (uint64_t)-1; - a.occ = 0; a.flag = (uint8_t)-1; a.dest = NULL; a.pre = NULL; - reset_pdq(a.pq); - while (1) - { - r = get_specific_shortest_path(&a); - if(!r) return; - if(a.pq->dis.a[a.v] <= dis) kv_push(uint32_t, res->a, a.v); - else return; - } -} - -uint64_t LCA_distance(long long d_x, long long d_y, long long xLen, long long yLen, uint8_t* rev) -{ - (*rev) = 0; - long long x_beg, x_end, y_beg, y_end, t_beg, t_end; - x_end = d_x; x_beg = x_end - xLen + 1; - y_end = d_y; y_beg = y_end - yLen + 1; - if(x_end >= y_end) - { - t_end = x_end; (*rev) = 0; - t_beg = y_beg; - } - else - { - t_end = y_end; (*rev) = 1; - t_beg = x_beg; - } - - return t_end + 1 - t_beg; -} - -uint64_t get_LCA_bubble(uint32_t x, uint64_t xLen, uint32_t y, uint64_t yLen, uint8_t* dis, uint64_t n, MT* M, bubble_type* bub, uint64_t* min_rev) -{ - uint32_t j, v, k; - uint64_t u, d = (uint64_t)-1, tmp; - uint8_t rev; - uint32_t root[2], a_n, *a; - get_bubbles(bub, bub->index[x>>1], &root[0], &root[1], &a, &a_n, NULL); - root[0] ^= 1; root[1] ^= 1; - if(root[0] > root[1]) - { - k = root[0]; - root[0] = root[1]; - root[1] = k; - } - - dis[root[0]] = (uint8_t)-1; - dis[root[1]] = (uint8_t)-1; - - v = x; - for (j = 0; j < M->matrix.a[v].a.n; j++) - { - u = M->matrix.a[v].a.a[j] >> M->uID_shift; - d = M->matrix.a[v].a.a[j] & M->dis_mode; - dis[u] = dis[u] >> 4; - } - - v = y; - for (j = 0; j < M->matrix.a[v].a.n; j++) - { - u = M->matrix.a[v].a.a[j] >> M->uID_shift; - d = M->matrix.a[v].a.a[j] & M->dis_mode; - dis[u] = dis[u] >> 4; - } - uint64_t x_i = 0, y_i = 0, d_x, d_y, min_d = (uint64_t)-1; - uint32_t min_j = (uint32_t)-1; - (*min_rev) = (uint64_t)-1; - - - for (k = 0; k < 2; k++) - { - j = root[k]; - if(dis[j] != 0) - { - dis[j] = (uint8_t)-1; - continue; - } - - for (; x_i < M->matrix.a[x].a.n; x_i++) - { - u = M->matrix.a[x].a.a[x_i] >> M->uID_shift; - d = M->matrix.a[x].a.a[x_i] & M->dis_mode; - if(u == j) break; - } - if(x_i == M->matrix.a[x].a.n && M->matrix.a[x].a.n != 0) fprintf(stderr, "ERROR X\n"); - d_x = d; - - for (; y_i < M->matrix.a[y].a.n; y_i++) - { - u = M->matrix.a[y].a.a[y_i] >> M->uID_shift; - d = M->matrix.a[y].a.a[y_i] & M->dis_mode; - if(u == j) break; - } - if(y_i == M->matrix.a[y].a.n && M->matrix.a[y].a.n != 0) fprintf(stderr, "ERROR Y\n"); - d_y = d; - - tmp = LCA_distance(d_x, d_y, xLen, yLen, &rev); - if(tmp < min_d) min_d = tmp, (*min_rev) = rev, min_j = j; - } - - if(min_j == x || min_j == y) return (uint64_t)-1; - - return min_d; - - -} - -uint64_t get_LCA(uint32_t x, uint64_t xLen, uint32_t y, uint64_t yLen, uint8_t* dis, uint64_t n, MT* M, bubble_type* bub, uint64_t* min_rev) -{ - if(IF_BUB(x>>1, *bub) && IF_BUB(y>>1, *bub) && bub->index[x>>1] == bub->index[y>>1]) - { - return get_LCA_bubble(x, xLen, y, yLen, dis, n, M, bub, min_rev); - } - else - { - memset(dis, -1, sizeof(uint8_t)*n); - } - - uint32_t j, v; - uint64_t u, d = (uint64_t)-1, tmp; - uint8_t rev; - - v = x; - for (j = 0; j < M->matrix.a[v].a.n; j++) - { - u = M->matrix.a[v].a.a[j] >> M->uID_shift; - d = M->matrix.a[v].a.a[j] & M->dis_mode; - dis[u] = dis[u] >> 4; - } - - v = y; - for (j = 0; j < M->matrix.a[v].a.n; j++) - { - u = M->matrix.a[v].a.a[j] >> M->uID_shift; - d = M->matrix.a[v].a.a[j] & M->dis_mode; - dis[u] = dis[u] >> 4; - } - - uint64_t x_i = 0, y_i = 0, d_x, d_y, min_d = (uint64_t)-1; - uint32_t min_j = (uint32_t)-1; - (*min_rev) = (uint64_t)-1; - for (j = 0; j < n; j++) - { - if(dis[j] != 0) - { - dis[j] = (uint8_t)-1; - continue; - } - - for (; x_i < M->matrix.a[x].a.n; x_i++) - { - u = M->matrix.a[x].a.a[x_i] >> M->uID_shift; - d = M->matrix.a[x].a.a[x_i] & M->dis_mode; - if(u == j) break; - } - if(x_i == M->matrix.a[x].a.n && M->matrix.a[x].a.n != 0) fprintf(stderr, "ERROR X\n"); - d_x = d; - - for (; y_i < M->matrix.a[y].a.n; y_i++) - { - u = M->matrix.a[y].a.a[y_i] >> M->uID_shift; - d = M->matrix.a[y].a.a[y_i] & M->dis_mode; - if(u == j) break; - } - if(y_i == M->matrix.a[y].a.n && M->matrix.a[y].a.n != 0) fprintf(stderr, "ERROR Y\n"); - d_y = d; - - - tmp = LCA_distance(d_x, d_y, xLen, yLen, &rev); - if(tmp < min_d) min_d = tmp, (*min_rev) = rev, min_j = j; - } - - if(min_j == x || min_j == y) return (uint64_t)-1; - - return min_d; -} - -typedef struct { // data structure for each step in kt_pipeline() - asg_t *sg; - hc_links* link; - MT* M; - bubble_type* bub; - uint8_t** dis_buf; -} utg_d_t; - -static void worker_for_dis(void *data, long i, int tid) -{ - utg_d_t* s = (utg_d_t*)data; - hc_links* link = s->link; - MT* M = s->M; - bubble_type* bub = s->bub; - uint8_t* dis_buf = s->dis_buf[tid]; - asg_t *sg = s->sg; - hc_linkeage* t = NULL; - uint32_t n_vtx = sg->n_seq<<1, v, u, k, j; - uint64_t d[2], db[2], q_u, min, min_i, min_b, rev[2], min_rev; - - if (sg->seq[i].del) return; - t = &(link->a.a[i]); - if (t->e.n == 0) return; - - for (k = 0; k < t->e.n; k++) - { - if(t->e.a[k].del) continue; - if(i == t->e.a[k].uID) continue; - u = t->e.a[k].uID; - - for (v = ((uint64_t)(i)<<1); v < ((uint64_t)(i+1)<<1); v++)///two directions - { - d[0] = d[1] = db[0] = db[1] = (uint64_t)-1; - for (j = 0; j < M->matrix.a[v].a.n; j++) - { - q_u = M->matrix.a[v].a.a[j] >> M->uID_shift; - if((q_u>>1) == u) d[q_u&1] = (M->matrix.a[v].a.a[j] & M->dis_mode) + sg->seq[q_u>>1].len; - if((q_u>>1) > u) break;///just for speeding up, doesn't affect results - } - - min = min_i = min_b = (uint64_t)-1; - if(t->e.a[k].dis != (uint64_t)-1) min = t->e.a[k].dis >> 3; - - if(d[0] < min) min = d[0], min_i = 0, min_b = 0; - if(d[1] < min) min = d[1], min_i = 1, min_b = 0; - - if(min_i != (uint64_t)-1 && min != (uint64_t)-1) - { - t->e.a[k].dis = min<<1; - t->e.a[k].dis += min_b; - t->e.a[k].dis <<=1; - t->e.a[k].dis += v&1;//s-direction - t->e.a[k].dis <<=1; - t->e.a[k].dis += min_i;//e-direction - } - } - - - ///might be wrong - if(IF_BUB(i, *bub) && IF_BUB(u, *bub) - && bub->index[i] != bub->index[u] && t->e.a[k].dis != (uint64_t)-1) - { - continue; - } - - for (v = ((uint64_t)(i)<<1); v < ((uint64_t)(i+1)<<1); v++) - { - d[0] = d[1] = db[0] = db[1] = (uint64_t)-1; - db[0] = get_LCA(v, sg->seq[v>>1].len, u<<1, sg->seq[u].len, - dis_buf, n_vtx, M, bub, &rev[0]); - db[1] = get_LCA(v, sg->seq[v>>1].len, (u<<1) + 1, sg->seq[u].len, - dis_buf, n_vtx, M, bub, &rev[1]); - - min = min_i = min_b = min_rev = (uint64_t)-1; - if(t->e.a[k].dis != (uint64_t)-1) min = t->e.a[k].dis >> 3; - - if(db[0] < min) min = db[0], min_i = 0, min_b = 1, min_rev = rev[0]; - if(db[1] < min) min = db[1], min_i = 1, min_b = 1, min_rev = rev[1]; - - if(min_i != (uint64_t)-1 && min != (uint64_t)-1) - { - t->e.a[k].dis = min<<1; - t->e.a[k].dis += min_b; - t->e.a[k].dis <<=1; - t->e.a[k].dis += ((v&1)^min_rev);//s-direction - t->e.a[k].dis <<=1; - t->e.a[k].dis += (min_i^min_rev);//e-direction - } - } - } -} - -void fill_utg_distance_multi(asg_t *sg, hc_links* link, MT* M, bubble_type* bub) -{ - // double index_time = yak_realtime(); - uint32_t i; - utg_d_t s; - s.sg = sg; s.link = link; s.M = M; s.bub = bub; - s.dis_buf = (uint8_t**)malloc(sizeof(uint8_t*)*asm_opt.thread_num); - for (i = 0; i < (uint32_t)asm_opt.thread_num; i++) - { - s.dis_buf[i] = (uint8_t*)malloc(sizeof(uint8_t)*(s.sg->n_seq<<1)); - } - - kt_for(asm_opt.thread_num, worker_for_dis, &s, s.sg->n_seq); - - - for (i = 0; i < (uint32_t)asm_opt.thread_num; i++) - { - free(s.dis_buf[i]); - } - free(s.dis_buf); - // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); -} - -void init_MT(MT* M, uint32_t n_vtx) -{ - uint32_t v; - kv_init(M->matrix); kv_malloc(M->matrix, n_vtx); M->matrix.n = n_vtx; - for (v = 0; v < n_vtx; ++v) kv_init(M->matrix.a[v].a); - for (v = 1; (uint64_t)(1<uID_shift = 64 - v; M->dis_mode = ((uint64_t)-1) >> v; -} - -void destory_MT(MT* M) -{ - uint32_t v; - for (v = 0; v < M->matrix.n; ++v) kv_destroy(M->matrix.a[v].a); - kv_destroy(M->matrix); -} - -int get_trans_ug_arch(uint32_t qn, uint32_t qs, uint32_t qe, uint32_t qLen, -uint32_t tn, uint32_t ts, uint32_t te, uint32_t tLen, uint32_t rev, asg_arc_t* t) -{ - ma_hit_t h; - h.qns = qn; - h.qns = h.qns << 32; - h.qns = h.qns | qs; - h.qe = qe; - h.tn = tn; - h.ts = ts; - h.te = te; - h.rev = rev; - h.del = 0; - h.bl = h.el = h.ml = h.no_l_indel = 0; - return ma_hit2arc(&h, qLen, tLen, MAX(qLen, tLen) + 1, 0, 0, t); -} - -void update_ug_by_trans(asg_t *sg, kv_u_trans_t *ta) -{ - u_trans_t *a = NULL, *p = NULL; - uint32_t i, k, st, occ, n, m; - uint32_t qn, tn, qs, qe, ts, te, rev; - asg_arc_t t, *e = NULL; - long long r_qs, r_qe, r_ts, r_te; - int r; - - for (k = occ = 0; k < ta->idx.n; k++) - { - a = u_trans_a(*ta, k); - n = u_trans_n(*ta, k); - for (st = 0, i = 1; i <= n; ++i) - { - if (i == n || a[i].tn != a[st].tn) - { - for (m = st, p = &(a[st]); m < i; m++) - { - if(a[m].nw > p->nw) p = &(a[m]); - } - - if(p->f == RC_2)///dis-connected - { - rev = p->rev; - qn = p->qn; - qs = p->qs; - qe = p->qe - 1; - if(rev) - { - tn = p->tn; - ts = sg->seq[tn].len - (p->te - 1) - 1; - te = sg->seq[tn].len - p->ts - 1; - } - else - { - tn = p->tn; - ts = p->ts; - te = p->te - 1; - } - - classify_hap_overlap(qs, qe, sg->seq[qn].len, ts, te, sg->seq[tn].len, - &r_qs, &r_qe, &r_ts, &r_te); - - qs = r_qs; qe = r_qe + 1; - if(rev) - { - ts = sg->seq[tn].len - r_te - 1; - te = sg->seq[tn].len - r_ts - 1 + 1; - } - else - { - ts = r_ts; te = r_te + 1; - } - - r = get_trans_ug_arch(qn, qs, qe, sg->seq[qn].len, - tn, ts, te, sg->seq[tn].len, rev, &t); - if(r >= 0) - { - e = asg_arc_pushp(sg); - *e = t; - occ++; - } - } - st = i; - } - } - } - - if(occ > 0) - { - free(sg->idx); - sg->idx = 0; - sg->is_srt = 0; - asg_cleanup(sg); - } - asg_arc_del_trans(sg, asm_opt.gap_fuzz); - -} - -void push_LCA_edges(long long d_x, long long d_y, long long xLen, long long yLen, -uint32_t v, uint32_t w, uint64_t *e0, uint64_t *e1) -{ - long long x_beg, x_end, y_beg, y_end; - uint64_t d, rev; - x_end = d_x; x_beg = x_end - xLen + 1; - y_end = d_y; y_beg = y_end - yLen + 1; - - long long ovlp = ((MIN(x_end, y_end) >= MAX(x_beg, y_beg))? - MIN(x_end, y_end) - MAX(x_beg, y_beg) + 1 : 0); - if(ovlp != xLen && ovlp != yLen) - { - d = MAX(x_end, y_end) - MIN(x_beg, y_beg) + 1; - if(x_end >= y_end) rev = 1; - else rev = 0; - - (*e0) = d; - (*e0) <<= 1; - (*e0) += 1; - (*e0) <<= 1; - (*e0) += ((v&1)^rev);//s-direction - (*e0) <<= 1; - (*e0) += ((w&1)^rev);//e-direction - - rev ^= 1; - (*e1) = d; - (*e1) <<= 1; - (*e1) += 1; - (*e1) <<= 1; - (*e1) += ((w&1)^rev);//s-direction - (*e1) <<= 1; - (*e1) += ((v&1)^rev);//e-direction - } - else - { - if(xLen >= yLen) d = (x_beg + 1) + (y_end - y_beg + 1); - else d = (x_end - x_beg + 1) + (yLen - y_end - 1); - - (*e0) = d; - (*e0) <<= 1; - (*e0) += 1; - (*e0) <<= 1; - (*e0) += (v&1);//s-direction - (*e0) <<= 1; - (*e0) += (w&1);//e-direction - - if(xLen >= yLen) d = (y_end - y_beg + 1) + (xLen - x_end - 1); - else d = (y_beg + 1) + (x_end - x_beg + 1); - (*e1) = d; - (*e1) <<= 1; - (*e1) += 1; - (*e1) <<= 1; - (*e1) += (w&1);//s-direction - (*e1) <<= 1; - (*e1) += (v&1);//e-direction - } -} - -void push_LCA_edges_rev(hc_edge *hx, hc_edge *hy, -long long xLen, long long yLen, long long rLen, -uint32_t v, uint32_t w, uint64_t *e0, uint64_t *e1) -{ - long long x_beg, x_end, y_beg, y_end, dx, dy; - uint64_t d, rev; - dx = (hx->dis>>3); - if((hx->dis&(uint64_t)2)) - { - x_beg = rLen - dx - 1; x_end = x_beg + xLen - 1; - } - else - { - x_end = dx; x_beg = x_end - xLen + 1; - } - - dy = (hy->dis>>3); - if((hy->dis&(uint64_t)2)) - { - y_beg = rLen - dy - 1; y_end = y_beg + yLen - 1; - } - else - { - y_end = dy; y_beg = y_end - yLen + 1; - } - - long long ovlp = ((MIN(x_end, y_end) >= MAX(x_beg, y_beg))? - MIN(x_end, y_end) - MAX(x_beg, y_beg) + 1 : 0); - if(ovlp != xLen && ovlp != yLen) - { - d = MAX(x_end, y_end) - MIN(x_beg, y_beg) + 1; - if(x_end >= y_end) rev = 1; - else rev = 0; - - (*e0) = d; - (*e0) <<= 1; - (*e0) += 1; - (*e0) <<= 1; - (*e0) += ((v&1)^rev);//s-direction - (*e0) <<= 1; - (*e0) += ((w&1)^rev);//e-direction - - rev ^= 1; - (*e1) = d; - (*e1) <<= 1; - (*e1) += 1; - (*e1) <<= 1; - (*e1) += ((w&1)^rev);//s-direction - (*e1) <<= 1; - (*e1) += ((v&1)^rev);//e-direction - } - else - { - if(xLen >= yLen) d = (x_beg + 1) + (y_end - y_beg + 1); - else d = (x_end - x_beg + 1) + (yLen - y_end - 1); - (*e0) = d; - (*e0) <<= 1; - (*e0) += 1; - (*e0) <<= 1; - (*e0) += (v&1);//s-direction - (*e0) <<= 1; - (*e0) += (w&1);//e-direction - - if(xLen >= yLen) d = (y_end - y_beg + 1) + (xLen - x_end - 1); - else d = (y_beg + 1) + (x_end - x_beg + 1); - (*e1) = d; - (*e1) <<= 1; - (*e1) += 1; - (*e1) <<= 1; - (*e1) += (w&1);//s-direction - (*e1) <<= 1; - (*e1) += (v&1);//e-direction - } -} - -uint32_t up_contain(kv_u_trans_t *ta, hc_links* link, uint8_t *uc_idx, asg_t *sg, kvec_t_u64_warp *buf) -{ - hc_edge *he = NULL, *ht = NULL, *hx = NULL; - uint64_t t_d = (uint64_t)-1, hd; - uint32_t qn, tn, qs, qe, ts, te, rev, is_c; - u_trans_t *a = NULL, *p = NULL; - asg_arc_t t; - uint32_t i, k, st, occ, n, m; - long long r_qs, r_qe, r_ts, r_te; - int r; - - for (k = 0, buf->a.n = 0; k < ta->idx.n; k++) - { - if((uc_idx[k]&2)&&(!(uc_idx[k]&1)))///contain others - { - if(link->a.a[k].e.n == 0) - { - uc_idx[k] -= 2; - continue; - } - a = u_trans_a(*ta, k); - n = u_trans_n(*ta, k); - for (st = 0, i = 1; i <= n; ++i) - { - if (i == n || a[i].tn != a[st].tn) - { - for (m = st, p = &(a[st]); m < i; m++) - { - if(a[m].nw > p->nw) p = &(a[m]); - } - - if(p->f == RC_2)///dis-connected - { - rev = p->rev; - qn = p->qn; - qs = p->qs; - qe = p->qe - 1; - if(rev) - { - tn = p->tn; - ts = sg->seq[tn].len - (p->te - 1) - 1; - te = sg->seq[tn].len - p->ts - 1; - } - else - { - tn = p->tn; - ts = p->ts; - te = p->te - 1; - } - - classify_hap_overlap(qs, qe, sg->seq[qn].len, ts, te, sg->seq[tn].len, - &r_qs, &r_qe, &r_ts, &r_te); - - qs = r_qs; qe = r_qe + 1; - if(rev) - { - ts = sg->seq[tn].len - r_te - 1; - te = sg->seq[tn].len - r_ts - 1 + 1; - } - else - { - ts = r_ts; te = r_te + 1; - } - - r = get_trans_ug_arch(qn, qs, qe, sg->seq[qn].len, - tn, ts, te, sg->seq[tn].len, rev, &t); - if(r == MA_HT_TCONT)//q contains t - { - hd = tn; hd <<= 32; hd |= qn; - kv_push(uint64_t, buf->a, hd); - ///qn->tn - he = get_hc_edge(link, qn, tn, 0); - if(!he) - { - push_hc_edge(&(link->a.a[qn]), tn, 0, 0, &t_d); - he = get_hc_edge(link, qn, tn, 0); - } - hd = (te - ts) + qs; - if(hd < he->dis) - { - he->dis = hd << 1; - he->dis += 1; - he->dis <<= 1; - he->dis += 0;//s-direction - he->dis <<= 1; - he->dis += rev;//e-direction - } - - ///tn->qn - he = get_hc_edge(link, tn, qn, 0); - if(!he) - { - push_hc_edge(&(link->a.a[tn]), qn, 0, 0, &t_d); - he = get_hc_edge(link, tn, qn, 0); - } - hd = (te - ts) + sg->seq[qn].len - qe; - if(hd < he->dis) - { - he->dis = hd << 1; - he->dis += 1; - he->dis <<= 1; - he->dis += 0;//s-direction - he->dis <<= 1; - he->dis += rev;//e-direction - } - } - } - st = i; - } - } - uc_idx[k] -= 2; - } - } - - uint64_t e0, e1; - for (k = 0; k < buf->a.n; k++) - { - qn = buf->a.a[k] >> 32; - tn = (uint32_t)buf->a.a[k]; - - he = get_hc_edge(link, tn, qn, 0); //tn contains qn - for (i = 0; i < link->a.a[tn].e.n; i++) - { - if(link->a.a[tn].e.a[i].del) continue; - if(link->a.a[tn].e.a[i].uID == qn) continue; - ht = &(link->a.a[tn].e.a[i]); - if(ht->dis == (uint64_t)-1) continue; - - if((he->dis&(uint64_t)2) == (ht->dis&(uint64_t)2))///s in same direction - { - push_LCA_edges(he->dis>>3, ht->dis>>3, sg->seq[he->uID].len, sg->seq[ht->uID].len, - he->dis&1, ht->dis&1, &e0, &e1); - - ///forward - hx = get_hc_edge(link, he->uID, ht->uID, 0); - if(!hx) - { - push_hc_edge(&(link->a.a[he->uID]), ht->uID, 0, 0, &t_d); - hx = get_hc_edge(link, he->uID, ht->uID, 0); - } - if ((e0>>3) < (hx->dis>>3)) hx->dis = e0; - - ///backward - hx = get_hc_edge(link, ht->uID, he->uID, 0); - if(!hx) - { - push_hc_edge(&(link->a.a[ht->uID]), he->uID, 0, 0, &t_d); - hx = get_hc_edge(link, ht->uID, he->uID, 0); - } - if ((e1>>3) < (hx->dis>>3)) hx->dis = e1; - } - else - { - push_LCA_edges_rev(he, ht, sg->seq[he->uID].len, sg->seq[ht->uID].len, - sg->seq[tn].len, he->dis&1, ht->dis&1, &e0, &e1); - - ///forward - hx = get_hc_edge(link, he->uID, ht->uID, 0); - if(!hx) - { - push_hc_edge(&(link->a.a[he->uID]), ht->uID, 0, 0, &t_d); - hx = get_hc_edge(link, he->uID, ht->uID, 0); - } - if ((e0>>3) < (hx->dis>>3)) hx->dis = e0; - - ///backward - hx = get_hc_edge(link, ht->uID, he->uID, 0); - if(!hx) - { - push_hc_edge(&(link->a.a[ht->uID]), he->uID, 0, 0, &t_d); - hx = get_hc_edge(link, ht->uID, he->uID, 0); - } - if ((e1>>3) < (hx->dis>>3)) hx->dis = e1; - } - } - } - - - for (k = 0, occ = 0; k < ta->idx.n; k++) - { - if((uc_idx[k]&1) && (uc_idx[k]&2)) - { - is_c = 0; - a = u_trans_a(*ta, k); - n = u_trans_n(*ta, k); - for (st = 0, i = 1; i <= n; ++i) - { - if (i == n || a[i].tn != a[st].tn) - { - for (m = st, p = &(a[st]); m < i; m++) - { - if(a[m].nw > p->nw) p = &(a[m]); - } - - if(p->f == RC_2)///dis-connected - { - rev = p->rev; - qn = p->qn; - qs = p->qs; - qe = p->qe - 1; - if(rev) - { - tn = p->tn; - ts = sg->seq[tn].len - (p->te - 1) - 1; - te = sg->seq[tn].len - p->ts - 1; - } - else - { - tn = p->tn; - ts = p->ts; - te = p->te - 1; - } - - classify_hap_overlap(qs, qe, sg->seq[qn].len, ts, te, sg->seq[tn].len, - &r_qs, &r_qe, &r_ts, &r_te); - - qs = r_qs; qe = r_qe + 1; - if(rev) - { - ts = sg->seq[tn].len - r_te - 1; - te = sg->seq[tn].len - r_ts - 1 + 1; - } - else - { - ts = r_ts; te = r_te + 1; - } - - r = get_trans_ug_arch(qn, qs, qe, sg->seq[qn].len, - tn, ts, te, sg->seq[tn].len, rev, &t); - if(r == MA_HT_QCONT && (uc_idx[tn]&2))//t contains q - { - is_c = 1; - } - } - st = i; - } - } - if(is_c == 0) uc_idx[k] -= 1; - } - if(uc_idx[k]&2) occ++; - } - - return occ; -} - -void print_u_trans_t(u_trans_t *p) -{ - fprintf(stderr, "q-utg%.6ul\tqs(%u)\tqe(%u)\tt-utg%.6ul\tts(%u)\tte(%u)\trev(%u)\tw(%f)\n", p->qn+1, p->qs, p->qe, p->tn+1, p->ts, p->te, p->rev, p->nw); -} - -void update_containment_distance(asg_t *sg, kv_u_trans_t *ta, hc_links* link) -{ - uint8_t *uc_idx = NULL; - CALLOC(uc_idx, sg->n_seq); - - u_trans_t *a = NULL, *p = NULL; - uint32_t i, k, st, n, m; - uint32_t qn, tn, qs, qe, ts, te, rev; - asg_arc_t t; - long long r_qs, r_qe, r_ts, r_te; - int r; - - for (k = 0; k < ta->idx.n; k++) - { - a = u_trans_a(*ta, k); - n = u_trans_n(*ta, k); - for (st = 0, i = 1; i <= n; ++i) - { - if (i == n || a[i].tn != a[st].tn) - { - for (m = st, p = &(a[st]); m < i; m++) - { - if(a[m].nw > p->nw) p = &(a[m]); - } - - if(p->f == RC_2)///dis-connected - { - rev = p->rev; - qn = p->qn; - qs = p->qs; - qe = p->qe - 1; - if(rev) - { - tn = p->tn; - ts = sg->seq[tn].len - (p->te - 1) - 1; - te = sg->seq[tn].len - p->ts - 1; - } - else - { - tn = p->tn; - ts = p->ts; - te = p->te - 1; - } - - classify_hap_overlap(qs, qe, sg->seq[qn].len, ts, te, sg->seq[tn].len, - &r_qs, &r_qe, &r_ts, &r_te); - - qs = r_qs; qe = r_qe + 1; - if(rev) - { - ts = sg->seq[tn].len - r_te - 1; - te = sg->seq[tn].len - r_ts - 1 + 1; - } - else - { - ts = r_ts; te = r_te + 1; - } - - r = get_trans_ug_arch(qn, qs, qe, sg->seq[qn].len, - tn, ts, te, sg->seq[tn].len, rev, &t); - if(r == MA_HT_QCONT) uc_idx[qn] |= 1; - else if(r == MA_HT_TCONT) uc_idx[qn] |= 2; - - // if(r < 0) print_u_trans_t(p); - } - st = i; - } - } - } - - kvec_t_u64_warp buf; kv_init(buf.a); - while(up_contain(ta, link, uc_idx, sg, &buf)) - { - if(buf.a.n != 0) continue; - for (k = 0; k < ta->idx.n; k++) - { - if((uc_idx[k]&1) && (uc_idx[k]&2)) - { - uc_idx[k] = 2; - break; - } - } - } - - kv_destroy(buf.a); - free(uc_idx); -} - - -void collect_hc_links(const ha_ug_index* idx, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, MT* M) -{ - double index_time = yak_realtime(); - uint64_t k, i, shif = 64 - idx->uID_bits, beg, end, t_d; - for (k = 0; k < hits->a.n; ++k) - { - beg = ((hits->a.a[k].s<<1)>>shif); - end = ((hits->a.a[k].e<<1)>>shif); - - if(beg == end) continue; - if(IF_HOM(beg, *bub)) continue; - if(IF_HOM(end, *bub)) continue; - - t_d = (uint64_t)-1; - push_hc_edge(&(link->a.a[beg]), end, 0, 0, &t_d); - push_hc_edge(&(link->a.a[end]), beg, 0, 0, &t_d); - } - asg_t *copy_sg = copy_read_graph(idx->ug->g); - - - update_ug_by_trans(copy_sg, &(idx->t_ch->k_trans)); - all_pair_shortest_path(copy_sg, link, M); - fill_utg_distance_multi(copy_sg, link, M, bub); - update_containment_distance(copy_sg, &(idx->t_ch->k_trans), link); - asg_destroy(copy_sg); - - fprintf(stderr, "[M::%s::%.3f] ==> Hi-C linkages have been counted\n", __func__, yak_realtime()-index_time); - return; - - - - - - index_time = yak_realtime(); - for (k = 0; k < link->enzymes.n; k++) - { - link->enzymes.a[k] = 0; - for (i = 0; i < (uint64_t)asm_opt.hic_enzymes->n; i++) - { - link->enzymes.a[k] += get_enzyme_occ(idx->ug->u.a[k].s, idx->ug->u.a[k].len, - asm_opt.hic_enzymes->a[i], asm_opt.hic_enzymes->l[i]); - } - } - fprintf(stderr, "[M::%s::%.3f] ==> Enzymes have been counted\n", __func__, yak_realtime()-index_time); -} - - -void update_dis_connected_gfa(asg_t *sg, hc_links *link, MT *M) -{ - uint32_t i, m, v, nv, x, y; - asg_arc_t *av = NULL; - kvec_t(uint32_t) stack; kv_init(stack); - uint32_t *flag = NULL; MALLOC(flag, sg->n_seq); - uint64_t *group = NULL; MALLOC(group, sg->n_seq); - - for (i = 0; i < link->a.n; i++) - { - for (m = 0; m < link->a.a[i].e.n; m++) - { - if(link->a.a[i].e.a[m].dis == (uint64_t)-1) - { - if(link->a.a[i].e.a[m].is_cc != 0) - { - fprintf(stderr, "ERROR 1\n"); - } - } - - if(link->a.a[i].e.a[m].occ == (uint64_t)-1) - { - if(link->a.a[i].e.a[m].is_cc != 0 || link->a.a[i].e.a[m].dis == (uint64_t)-1) - { - fprintf(stderr, "ERROR 2\n"); - } - } - } - } - - - memset(flag, -1, sg->n_seq*sizeof(uint32_t)); - // connected componets - for (i = 0; i < sg->n_seq; ++i) { - if (flag[i] != (uint32_t)-1) continue; - stack.n = 0; - kv_push(uint32_t, stack, i); - while (stack.n > 0) { - stack.n--; - flag[stack.a[stack.n]] = i;///group id - - v = (stack.a[stack.n])<<1; - av = asg_arc_a(sg, v); - nv = asg_arc_n(sg, v); - for (m = 0; m < nv; ++m) { - if (flag[av[m].v>>1] != (uint32_t)-1) continue; - kv_push(uint32_t, stack, av[m].v>>1); - } - - v++; - av = asg_arc_a(sg, v); - nv = asg_arc_n(sg, v); - for (m = 0; m < nv; ++m) { - if (flag[av[m].v>>1] != (uint32_t)-1) continue; - kv_push(uint32_t, stack, av[m].v>>1); - } - } - } - kv_destroy(stack); - - - - // precalculate the size of each group - for (i = 0; i < sg->n_seq; ++i) - group[i] = (uint64_t)flag[i] << 32 | i; - radix_sort_hc64(group, group + sg->n_seq); - for (i = 1, x = y = 0; i <= sg->n_seq; ++i) { - if (i == sg->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; - } - } - - memset(flag, 0, sg->n_seq*sizeof(uint32_t)); - for (i = 1, x = y = 0; i <= sg->n_seq; ++i) - { - if (i == sg->n_seq || (group[i]>>32) != (group[x]>>32)) - { - x = i; - } - } - - - free(flag); -} - -void append_tig_link(uint64_t *cc, uint32_t cc_off, uint32_t cc_size, hc_links *link, asg_t *sg, kvec_t_u32_warp *buf) -{ - uint32_t i, k, id, tig_occ, b_cc_occ, *tig, *b_cc, qn, tn; - uint64_t t_d = (uint64_t)-1; - hc_edge *p = NULL; - for (i = 0; i < cc_size; ++i) ///how many nodes - { - id = (uint32_t)cc[cc_off + i];///node id - for (k = 0; k < link->a.a[id].e.n; k++) - { - if(link->a.a[id].e.a[k].is_cc == 0) break; - } - if(k < link->a.a[id].e.n) break; - } - if(i >= cc_size) return; - - buf->a.n = 0; tig_occ = 0; - for (i = 0; i < cc_size; ++i) ///how many nodes - { - id = (uint32_t)cc[cc_off + i];///node id - - if(asg_arc_n(sg, (id<<1)) == 0 || asg_arc_n(sg, ((id<<1)+1)) == 0)///tig - { - kv_push(uint32_t, buf->a, id); - tig_occ++; - } - } - - if(tig_occ == 0) return; - - b_cc_occ = 0; - for (i = 0; i < cc_size; ++i) ///how many nodes - { - id = (uint32_t)cc[cc_off + i];///node id - if(link->a.a[id].e.n == 0) continue; - - for (k = 0; k < link->a.a[id].e.n; k++) - { - if(link->a.a[id].e.a[k].is_cc == 0) break; - } - if(k < link->a.a[id].e.n)///disconnected - { - kv_push(uint32_t, buf->a, id); - b_cc_occ++; - } - } - - if(b_cc_occ == 0) return; - - tig = buf->a.a; - b_cc = buf->a.a + tig_occ; - for (i = 0; i < tig_occ; i++) - { - qn = tig[i]; - for (k = 0; k < b_cc_occ; k++) - { - tn = b_cc[k]; - if(qn == tn) continue; - p = get_hc_edge(link, qn, tn, 0); - if(p) continue; - - t_d = (uint64_t)-1; - p = push_hc_edge(&(link->a.a[qn]), tn, 0, 0, &t_d); - p->is_cc = 0; p->occ = (uint64_t)-1; - p = push_hc_edge(&(link->a.a[tn]), qn, 0, 0, &t_d); - p->is_cc = 0; p->occ = (uint64_t)-1; - } - } -} - -void update_ug_by_tigs(asg_t *sg, hc_links *link) -{ - uint32_t i, m, v, nv, x, y, qn, tn; - asg_arc_t *av = NULL; - kvec_t(uint32_t) stack; kv_init(stack); - uint32_t *flag = NULL; MALLOC(flag, sg->n_seq); - uint64_t *group = NULL; MALLOC(group, sg->n_seq); - kvec_t_u32_warp buf; kv_init(buf.a); - - - memset(flag, -1, sg->n_seq*sizeof(uint32_t)); - // connected componets - for (i = 0; i < sg->n_seq; ++i) { - if (flag[i] != (uint32_t)-1) continue; - stack.n = 0; - kv_push(uint32_t, stack, i); - while (stack.n > 0) { - stack.n--; - flag[stack.a[stack.n]] = i;///group id - - v = (stack.a[stack.n])<<1; - av = asg_arc_a(sg, v); - nv = asg_arc_n(sg, v); - for (m = 0; m < nv; ++m) { - if (flag[av[m].v>>1] != (uint32_t)-1) continue; - kv_push(uint32_t, stack, av[m].v>>1); - } - - v++; - av = asg_arc_a(sg, v); - nv = asg_arc_n(sg, v); - for (m = 0; m < nv; ++m) { - if (flag[av[m].v>>1] != (uint32_t)-1) continue; - kv_push(uint32_t, stack, av[m].v>>1); - } - } - } - kv_destroy(stack); - - - - // precalculate the size of each group - for (i = 0; i < sg->n_seq; ++i) - group[i] = (uint64_t)flag[i] << 32 | i; - radix_sort_hc64(group, group + sg->n_seq); - for (i = 1, x = y = 0; i <= sg->n_seq; ++i) { - if (i == sg->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; - } - } - - - for (i = 0; i < link->a.n; i++) - { - qn = i; - for (m = 0; m < link->a.a[i].e.n; m++) - { - link->a.a[i].e.a[m].occ = 0; - link->a.a[i].e.a[m].is_cc = 0; - tn = link->a.a[i].e.a[m].uID; - if((group[qn]>>32) == (group[tn]>>32)) - { - link->a.a[i].e.a[m].is_cc = 1; - } - } - } - - - for (i = 1, x = 0; i <= sg->n_seq; ++i) - { - if (i == sg->n_seq || (group[i]>>32) != (group[x]>>32)) - { - append_tig_link(group, x, i - x, link, sg, &buf); - x = i; - } - } - - free(flag); kv_destroy(buf.a); -} - -void idx_hc_links(kvec_pe_hit* hits, ha_ug_index* idx, bubble_type* bub); -void filter_disconnect_edges(ha_ug_index* idx, kvec_pe_hit *hits, hc_links *link, bubble_type *bub, uint32_t thres, double rate) -{ - uint32_t k, l, i, m, h_occ, *occ = NULL; - uint64_t shif = 64 - idx->uID_bits, qn, tn, u_dis; - pe_hit *h_a = NULL; - hc_linkeage *t = NULL; - u_trans_t *p = NULL; - hc_edge *e = NULL; - kv_u_trans_t k_trans; - kv_init(k_trans); - - if(hits->idx.n == 0) idx_hc_links(hits, idx, bub); - CALLOC(occ, hits->idx.n); - for (qn = 0; qn < hits->idx.n; qn++) - { - if(IF_HOM(qn, *bub)) continue; - h_a = hits->a.a + (hits->idx.a[qn]>>32); - h_occ = (uint32_t)(hits->idx.a[qn]); - - for (k = 1, l = 0; k <= h_occ; ++k) ///same qn - { - if (k == h_occ || ((h_a[k].e<<1)>>shif) != ((h_a[l].e<<1)>>shif)) //same qn and tn - { - tn = ((h_a[l].e<<1)>>shif); - if(!IF_HOM(tn, *bub) && tn != qn) - { - t = &(link->a.a[qn]); - for (i = 0, u_dis = (uint64_t)-1; i < t->e.n; i++) - { - if(t->e.a[i].del || t->e.a[i].uID != tn) continue; - u_dis = (t->e.a[i].dis ==(uint64_t)-1? (uint64_t)-1 : t->e.a[i].dis>>3); - break; - } - - if(u_dis == (uint64_t)-1) - { - kv_pushp(u_trans_t, k_trans, &p); - p->qn = qn; p->tn = tn; p->occ = (k-l); - kv_pushp(u_trans_t, k_trans, &p); - p->qn = tn; p->tn = qn; p->occ = (k-l); - } - else - { - occ[qn] += (k-l); occ[tn] += (k-l); - } - } - l = k; - } - } - } - - - radix_sort_u_trans_m(k_trans.a, k_trans.a + k_trans.n); - - for (k = 1, l = 0, m = 0; k <= k_trans.n; ++k) - { - if (k == k_trans.n || k_trans.a[l].qn != k_trans.a[k].qn || k_trans.a[l].tn != k_trans.a[k].tn) //same qn and tn - { - if(k - l > 2) fprintf(stderr, "ERROR-3\n"); - for (i = l, h_occ = 0; i < k; i++) - { - h_occ += k_trans.a[i].occ; - } - - k_trans.a[m] = k_trans.a[l]; - // k_trans.a[m].occ = ((uint32_t)-1) - h_occ; - k_trans.a[m].occ = h_occ; - - if(h_occ > thres || h_occ >= (occ[k_trans.a[m].qn]*rate) || h_occ >= (occ[k_trans.a[m].tn]*rate)) - { - e = get_hc_edge(link, k_trans.a[m].qn, k_trans.a[m].tn, 0); - if(e->dis != (uint64_t)-1) fprintf(stderr, "ERROR-3-0\n"); - e->is_cc = 1; - - e = get_hc_edge(link, k_trans.a[m].tn, k_trans.a[m].qn, 0); - if(e->dis != (uint64_t)-1) fprintf(stderr, "ERROR-3-0\n"); - e->is_cc = 1; - } - m++; - l = k; - } - } - k_trans.n = m; - - kv_destroy(k_trans); free(occ); -} - -void measure_distance(ha_ug_index* idx, const ma_ug_t* ug, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, kv_u_trans_t *ta) -{ - // double index_time = yak_realtime(); - MT M; - init_MT(&M, ug->g->n_seq<<1); - uint64_t uID_bits; - for (uID_bits=1; (uint64_t)(1<u.n; uID_bits++); - uint64_t k, i, shif = 64 - uID_bits, beg, end, t_d; - if(hits) - { - for (k = 0; k < hits->a.n; ++k) - { - beg = ((hits->a.a[k].s<<1)>>shif); - end = ((hits->a.a[k].e<<1)>>shif); - - if(beg == end) continue; - if(IF_HOM(beg, *bub)) continue; - if(IF_HOM(end, *bub)) continue; - - t_d = (uint64_t)-1; - push_hc_edge(&(link->a.a[beg]), end, 0, 0, &t_d); - push_hc_edge(&(link->a.a[end]), beg, 0, 0, &t_d); - } - } - else - { - for (k = 0; k < ug->g->n_seq; ++k) - { - if(IF_HOM(k, *bub)) continue; - for (i = 0; i < ug->g->n_seq; ++i) - { - if(i == k || IF_HOM(i, *bub)) continue; - t_d = (uint64_t)-1; - push_hc_edge(&(link->a.a[i]), k, 0, 0, &t_d); - push_hc_edge(&(link->a.a[k]), i, 0, 0, &t_d); - } - } - } - - asg_t *copy_sg = copy_read_graph(ug->g); - - update_ug_by_trans(copy_sg, ta); - // update_ug_by_tigs(copy_sg, link); - all_pair_shortest_path(copy_sg, link, &M); - fill_utg_distance_multi(copy_sg, link, &M, bub); - update_containment_distance(copy_sg, ta, link); - // update_dis_connected_gfa(copy_sg, link, &M); - asg_destroy(copy_sg); - destory_MT(&M); - - for (i = 0; i < link->a.n; i++) - { - for (k = 0; k < link->a.a[i].e.n; k++) - { - link->a.a[i].e.a[k].is_cc = 0; - if(link->a.a[i].e.a[k].del) continue; - if(link->a.a[i].e.a[k].dis == (uint64_t)-1) continue; - link->a.a[i].e.a[k].is_cc = 1; - } - } - - // filter_disconnect_edges(idx, hits, link, bub, 1, 0.01); - // fprintf(stderr, "[M::%s::%.3f] ==> Hi-C linkages have been counted\n", __func__, yak_realtime()-index_time); - return; -} - -void set_reverse_links(uint32_t* bub, uint32_t n, kvec_t_u32_warp* reach, uint32_t root, hc_links* link) -{ - uint64_t i, k, d = RC_0; - uint32_t v; - for (i = 0; i < n; i++) - { - v = bub[i]>>1; - if(v == root) continue; - for (k = 0; k < reach->a.n; k++) - { - if(v == reach->a.a[k]) break; - } - - ///if(k == reach->a.n && reach->a.n > 0) - if(k == reach->a.n) - { - push_hc_edge(&(link->a.a[root]), v, 1, 1, &d); - push_hc_edge(&(link->a.a[v]), root, 1, 1, &d); - } - } - -} - -void collect_hc_reverse_links(hc_links* link, ma_ug_t* ug, bubble_type* bub) -{ - uint64_t i, j, k, d = RC_0, m, pre; - uint32_t beg, sink, n, v, *a = NULL; - kvec_t_u32_warp stack, result; - hc_edge *e = NULL; - kv_init(stack.a); kv_init(result.a); - ///clean all reverse overlaps within bubbles - ///might be wrong - for (i = 0; i < bub->f_bub; i++) - { - get_bubbles(bub, i, &beg, &sink, &a, &n, NULL); - for (k = 0; k < n; k++) - { - v = a[k]>>1; - for (j = 0; j < link->a.a[v].f.n; j++) - { - if(link->a.a[v].f.a[j].del) continue; - e = get_hc_edge(link, link->a.a[v].f.a[j].uID, v, 1); - e->del = 1; - } - link->a.a[v].f.n = 0; - } - - v = beg>>1; - if(IF_HOM(v, *bub)) - { - for (j = 0; j < link->a.a[v].f.n; j++) - { - if(link->a.a[v].f.a[j].del) continue; - e = get_hc_edge(link, link->a.a[v].f.a[j].uID, v, 1); - e->del = 1; - } - link->a.a[v].f.n = 0; - } - - v = sink>>1; - if(IF_HOM(v, *bub)) - { - for (j = 0; j < link->a.a[v].f.n; j++) - { - if(link->a.a[v].f.a[j].del) continue; - e = get_hc_edge(link, link->a.a[v].f.a[j].uID, v, 1); - e->del = 1; - } - link->a.a[v].f.n = 0; - } - } - - for (i = 0; i < bub->f_bub; i++) - { - get_bubbles(bub, i, &beg, &sink, &a, &n, NULL); - if(n == 2) - { - push_hc_edge(&(link->a.a[a[0]>>1]), a[1]>>1, 1, 1, &d); - push_hc_edge(&(link->a.a[a[1]>>1]), a[0]>>1, 1, 1, &d); - continue; - } - ///for complex bubbles, shouldn't have any assumption - ///if(i >= bub->s_bub) continue; - - beg = beg>>1; sink = sink>>1; - for (k = 0; k < n; k++) - { - v = a[k]>>1; - dfs_bubble(ug->g, &stack, &result, v, beg, sink); - set_reverse_links(a, n, &result, v, link); - } - } - - uint8_t* vis_flag = NULL; - MALLOC(vis_flag, ug->g->n_seq*2); - ///for broken bubbles - for (i = bub->f_bub; i < bub->f_bub + bub->b_bub; i++) - { - get_bubbles(bub, i, &beg, &sink, &a, &n, NULL); - - for (k = 0; k < n; k++) - { - v = a[k]; - dfs_bubble_broken(ug->g, &stack, &result, vis_flag, ug->g->n_seq*2, v, beg, sink); - set_reverse_links(a, n, &result, v>>1, link); - } - } - - kv_destroy(stack.a); kv_destroy(result.a); free(vis_flag); - - - for (i = 0; i < link->a.n; i++) - { - for (k = m = 0; k < link->a.a[i].f.n; k++) - { - if(link->a.a[i].f.a[k].del) continue; - link->a.a[i].f.a[m] = link->a.a[i].f.a[k]; - m++; - } - link->a.a[i].f.n = m; - radix_sort_hc_edge_u(link->a.a[i].f.a, link->a.a[i].f.a + link->a.a[i].f.n); - - for (k = m = 0, pre = (uint64_t)-1; k < link->a.a[i].f.n; k++) - { - if(link->a.a[i].f.a[k].del) continue; - if(link->a.a[i].f.a[k].uID == pre) - { - if(link->a.a[i].f.a[k].dis == RC_0) link->a.a[i].f.a[m-1].dis = RC_0; - continue; - } - - pre = link->a.a[i].f.a[k].uID; - link->a.a[i].f.a[m] = link->a.a[i].f.a[k]; - m++; - } - link->a.a[i].f.n = m; - radix_sort_hc_edge_d(link->a.a[i].f.a, link->a.a[i].f.a + link->a.a[i].f.n); - } - - - // hc_edge *e = NULL; - // for (i = 0; i < link->a.n; i++) - // { - // for (k = 0; k < link->a.a[i].f.n; k++) - // { - // if(link->a.a[i].f.a[k].del) continue; - // e = get_hc_edge(link, link->a.a[i].f.a[k].uID, i, 1); - // if(e == NULL) fprintf(stderr, "ERROR\n"); - // } - // } - -} - -void write_hc_links(hc_links* link, const char *fn) -{ - uint64_t k; - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.hic.link.bin", fn); - FILE* fp = fopen(buf, "w"); - - fwrite(&link->a.n, sizeof(link->a.n), 1, fp); - for (k = 0; k < link->a.n; k++) - { - fwrite(&link->a.a[k].e.n, sizeof(link->a.a[k].e.n), 1, fp); - fwrite(link->a.a[k].e.a, sizeof(hc_edge), link->a.a[k].e.n, fp); - - fwrite(&link->a.a[k].f.n, sizeof(link->a.a[k].f.n), 1, fp); - fwrite(link->a.a[k].f.a, sizeof(hc_edge), link->a.a[k].f.n, fp); - } - - fwrite(&link->enzymes.n, sizeof(link->enzymes.n), 1, fp); - fwrite(link->enzymes.a, sizeof(uint64_t), link->enzymes.n, fp); - - fclose(fp); - free(buf); - fprintf(stderr, "[M::%s::] ==> Hi-C linkages have been written\n", __func__); -} - -int load_hc_links(hc_links* link, const char *fn) -{ - uint64_t k, flag = 0; - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.hic.link.bin", fn); - - FILE* fp = NULL; - fp = fopen(buf, "r"); - if(!fp) - { - free(buf); - return 0; - } - - - kv_init(link->a); - flag += fread(&link->a.n, sizeof(link->a.n), 1, fp); - link->a.m = link->a.n; CALLOC(link->a.a, link->a.n); - for (k = 0; k < link->a.n; k++) - { - flag += fread(&link->a.a[k].e.n, sizeof(link->a.a[k].e.n), 1, fp); - link->a.a[k].e.m = link->a.a[k].e.n; MALLOC(link->a.a[k].e.a, link->a.a[k].e.n); - flag += fread(link->a.a[k].e.a, sizeof(hc_edge), link->a.a[k].e.n, fp); - - flag += fread(&link->a.a[k].f.n, sizeof(link->a.a[k].f.n), 1, fp); - link->a.a[k].f.m = link->a.a[k].f.n; MALLOC(link->a.a[k].f.a, link->a.a[k].f.n); - flag += fread(link->a.a[k].f.a, sizeof(hc_edge), link->a.a[k].f.n, fp); - } - - kv_init(link->enzymes); - flag += fread(&link->enzymes.n, sizeof(link->enzymes.n), 1, fp); - link->enzymes.m = link->enzymes.n; MALLOC(link->enzymes.a, link->enzymes.n); - flag += fread(link->enzymes.a, sizeof(uint64_t), link->enzymes.n, fp); - - fclose(fp); - free(buf); - fprintf(stderr, "[M::%s::] ==> Hi-C linkages have been loaded\n", __func__); - return 1; -} - -void write_hc_hits(kvec_pe_hit* hits, ma_ug_t* ug, const char *fn) -{ - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.hic.lk.bin", fn); - FILE* fp = fopen(buf, "w"); - - fwrite(&hits->a.n, sizeof(hits->a.n), 1, fp); - fwrite(hits->a.a, sizeof(pe_hit), hits->a.n, fp); - write_dbug(ug, fp); - - fclose(fp); - free(buf); -} - -void write_hc_hits_v14(kvec_pe_hit_hap* i_hits, const char *fn) -{ - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.v14.hic.lk.bin", fn); - FILE* fp = fopen(buf, "w"); - kvec_pe_hit hits; - kv_init(hits.a); - uint64_t i, m_u = (uint64_t)-1, m_m = (uint64_t)-1; - pe_hit* p = NULL; - for (i = 0; i < i_hits->n; i++) - { - if(i_hits->a[i].occ1 == 1 && i_hits->a[i].occ2 == 1) - { - kv_pushp(pe_hit, hits.a, &p); - p->id = i_hits->a[i].id; - p->s = i_hits->a[i].a[0]; - p->e = i_hits->a[i].a[1]; - m_u = i; - } - else - { - if(m_m == (uint64_t)-1) m_m = i; - } - } - fprintf(stderr, "m_u: %lu, m_m: %lu, n_u: %lu\n", m_u, m_m, i_hits->n_u); - - fwrite(&hits.a.n, sizeof(hits.a.n), 1, fp); - fwrite(hits.a.a, sizeof(pe_hit), hits.a.n, fp); - - kv_destroy(hits.a); - fclose(fp); - free(buf); - exit(1); -} - -#define pe_hit_hap_id_key(x) ((x).id) -KRADIX_SORT_INIT(pe_hit_hap_id, pe_hit_hap, pe_hit_hap_id_key, member_size(pe_hit_hap, id)) - -#define pe_hit_id_key(x) ((x).id) -KRADIX_SORT_INIT(pe_hit_id, pe_hit, pe_hit_id_key, member_size(pe_hit, id)) - -void debug_hc_hits_v14(kvec_pe_hit_hap* i_hits, const char *fn, const ha_ug_index* idx) -{ - uint64_t flag = 0; - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.v14.hic.lk.bin", fn); - kvec_pe_hit hits; - kv_init(hits.a); - FILE* fp = NULL; - fp = fopen(buf, "r"); - - kv_init(hits.a); - flag += fread(&hits.a.n, sizeof(hits.a.n), 1, fp); - hits.a.m = hits.a.n; MALLOC(hits.a.a, hits.a.n); - flag += fread(hits.a.a, sizeof(pe_hit), hits.a.n, fp); - - radix_sort_pe_hit_id(hits.a.a, hits.a.a + hits.a.n); - radix_sort_pe_hit_hap_id(i_hits->a, i_hits->a + i_hits->n_u); - - fprintf(stderr, "i_hits->n_u: %lu, hits.a.n: %lu\n", (uint64_t)i_hits->n_u, (uint64_t)hits.a.n); - - uint64_t i, k; - uint64_t i_beg_utg, i_beg_pos, i_beg_rev; - uint64_t i_end_utg, i_end_pos, i_end_rev; - uint64_t k_beg_utg, k_beg_pos, k_beg_rev; - uint64_t k_end_utg, k_end_pos, k_end_rev; - uint64_t i_id, k_id; - uint64_t same_occ = 0, diff_occ = 0, miss_occ = 0; - for (i = 0, k = 0; i < i_hits->n_u; i++) - { - i_beg_rev = get_pe_s(i_hits->a[i])>>63; - i_beg_utg = ((get_pe_s(i_hits->a[i])<<1)>>(64 - idx->uID_bits)); - i_beg_pos = get_pe_s(i_hits->a[i]) & idx->pos_mode; - - i_end_rev = get_pe_e(i_hits->a[i])>>63; - i_end_utg = ((get_pe_e(i_hits->a[i])<<1)>>(64 - idx->uID_bits)); - i_end_pos = get_pe_e(i_hits->a[i]) & idx->pos_mode; - - i_id = i_hits->a[i].id; - for (; k < hits.a.n; k++) - { - k_beg_rev = hits.a.a[k].s>>63; - k_beg_utg = ((hits.a.a[k].s<<1)>>(64 - idx->uID_bits)); - k_beg_pos = hits.a.a[k].s & idx->pos_mode; - - k_end_rev = hits.a.a[k].e>>63; - k_end_utg = ((hits.a.a[k].e<<1)>>(64 - idx->uID_bits)); - k_end_pos = hits.a.a[k].e & idx->pos_mode; - - k_id = hits.a.a[k].id; - - if(k_id > i_id) - { - miss_occ++; - fprintf(stderr, "\n[MISS]rid=%lu\n", i_id); - fprintf(stderr, "********v0.15********\n"); - fprintf(stderr, "beg_rev: %lu, beg_utg: %lu, beg_pos: %lu\n", - i_beg_rev, i_beg_utg, i_beg_pos); - fprintf(stderr, "end_rev: %lu, end_utg: %lu, end_pos: %lu\n", - i_end_rev, i_end_utg, i_end_pos); - break; - } - - if(k_id == i_id) - { - if(get_pe_s(i_hits->a[i]) == hits.a.a[k].s && get_pe_e(i_hits->a[i]) == hits.a.a[k].e) - { - same_occ++; - // fprintf(stderr, "\n[SAME]rid=%lu\n", i_id); - // fprintf(stderr, "********v0.15********\n"); - // fprintf(stderr, "beg_rev: %lu, beg_utg: %lu, beg_pos: %lu\n", - // i_beg_rev, i_beg_utg, i_beg_pos); - // fprintf(stderr, "end_rev: %lu, end_utg: %lu, end_pos: %lu\n", - // i_end_rev, i_end_utg, i_end_pos); - // fprintf(stderr, "********v0.14********\n"); - // fprintf(stderr, "beg_rev: %lu, beg_utg: %lu, beg_pos: %lu\n", - // k_beg_rev, k_beg_utg, k_beg_pos); - // fprintf(stderr, "end_rev: %lu, end_utg: %lu, end_pos: %lu\n", - // k_end_rev, k_end_utg, k_end_pos); - } - else - { - diff_occ++; - fprintf(stderr, "\n[DIFF]rid=%lu\n", i_id); - fprintf(stderr, "********v0.15********\n"); - fprintf(stderr, "beg_rev: %lu, beg_utg: %lu, beg_pos: %lu\n", - i_beg_rev, i_beg_utg, i_beg_pos); - fprintf(stderr, "end_rev: %lu, end_utg: %lu, end_pos: %lu\n", - i_end_rev, i_end_utg, i_end_pos); - fprintf(stderr, "********v0.14********\n"); - fprintf(stderr, "beg_rev: %lu, beg_utg: %lu, beg_pos: %lu\n", - k_beg_rev, k_beg_utg, k_beg_pos); - fprintf(stderr, "end_rev: %lu, end_utg: %lu, end_pos: %lu\n", - k_end_rev, k_end_utg, k_end_pos); - } - break; - } - } - } - - fprintf(stderr, "same_occ: %lu, diff_occ: %lu, miss_occ: %lu", same_occ, diff_occ, miss_occ); - - - kv_destroy(hits.a); - fclose(fp); - free(buf); - exit(1); -} - -int load_hc_hits(kvec_pe_hit* hits, ma_ug_t* ug, const char *fn) -{ - uint64_t flag = 0; - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.hic.lk.bin", fn); - - FILE* fp = NULL; - fp = fopen(buf, "r"); - if(!fp) - { - free(buf); - return 0; - } - - - kv_init(hits->a); - flag += fread(&hits->a.n, sizeof(hits->a.n), 1, fp); - hits->a.m = hits->a.n; MALLOC(hits->a.a, hits->a.n); - flag += fread(hits->a.a, sizeof(pe_hit), hits->a.n, fp); - free(buf); - - if(!test_dbug(ug, fp)) - { - free(hits->a.a); - kv_init(hits->a); - fclose(fp); - fprintf(stderr, "[M::%s::] ==> Renew Hi-C linkages\n", __func__); - return 0; - } - - fclose(fp); - fprintf(stderr, "[M::%s::] ==> Hi-C linkages have been loaded\n", __func__); - return 1; -} - -inline int get_phase_status(H_partition* hap, uint32_t uID) -{ - int d = -2; - if(hap->hap[uID] & hap->m[0]) d = 1; - if(hap->hap[uID] & hap->m[1]) d = -1; - if(hap->hap[uID] & hap->m[2]) d = 0; - return d; -} - -inline uint32_t get_phase_group(H_partition* hap, uint32_t uID) -{ - return hap->hap[uID]>>hap->label_shift; -} - -void print_hc_links(hc_links* link, int dir, H_partition* hap) -{ - uint64_t i, k; - if(dir == 0) - { - double f_w, r_w; - for (i = 0; i < link->a.n; ++i) - { - f_w = r_w = 0; - for (k = 0; k < link->a.a[i].e.n; k++) - { - if(link->a.a[i].e.a[k].del) continue; - fprintf(stderr, "s-utg%.6dl(%c)\tCLU:%d:%u\td-utg%.6dl(%c)\tCLU:%d:%u\t%lu\t%c\t%f\te\n", - (int)(i+1), "01"[!!(link->a.a[i].e.a[k].dis&(uint64_t)2)], - get_phase_status(hap, i), hap->hap[i]>>3, - (int)(link->a.a[i].e.a[k].uID+1), "01"[!!(link->a.a[i].e.a[k].dis&(uint64_t)1)], - get_phase_status(hap, link->a.a[i].e.a[k].uID), hap->hap[link->a.a[i].e.a[k].uID]>>3, - link->a.a[i].e.a[k].dis == (uint64_t)-1? (uint64_t)-1 : link->a.a[i].e.a[k].dis>>3, - "fb"[!!(link->a.a[i].e.a[k].dis&(uint64_t)4)], link->a.a[i].e.a[k].weight); - if(get_phase_status(hap, i) == get_phase_status(hap, link->a.a[i].e.a[k].uID)) - { - f_w += link->a.a[i].e.a[k].weight; - } - else - { - r_w += link->a.a[i].e.a[k].weight; - } - } - - // fprintf(stderr, "self-utg%.6dl\tFW:%f\tRW:%f\tRT:%f\n**************************************************\n", - // (int)(i+1), f_w, r_w, (f_w+r_w) != 0? r_w/(f_w+r_w):0); - } - } - - - if(dir == 1) - { - for (i = 0; i < link->a.n; ++i) - { - for (k = 0; k < link->a.a[i].f.n; k++) - { - if(link->a.a[i].f.a[k].del) continue; - fprintf(stderr, "s-utg%.6d\td-utg%.6d\t%lu\te\n", - (int)(i+1), (int)(link->a.a[i].f.a[k].uID+1), link->a.a[i].f.a[k].dis); - } - } - } -} - -void normalize_hc_links(hc_links* link) -{ - uint64_t i, k; - for (i = 0; i < link->a.n; ++i) - { - for (k = 0; k < link->a.a[i].e.n; k++) - { - if(link->a.a[i].e.a[k].del) continue; - link->a.a[i].e.a[k].weight *= 100; - link->a.a[i].e.a[k].weight /= (double)(MIN(link->enzymes.a[i], link->enzymes.a[link->a.a[i].e.a[k].uID])); - ///link->a.a[i].e.a[k].weight /= (double)(link->enzymes.a[i] + link->enzymes.a[link->a.a[i].e.a[k].uID]); - } - } -} - -hc_edge* get_rGraph_edge(min_cut_t* x, uint64_t src, uint64_t dest) -{ - if(src >= x->rGraph.n) return NULL; - uint64_t i; - for (i = 0; i < x->rGraph.a[src].n; i++) - { - if(x->rGraph.a[src].a[i].del) continue; - if(x->rGraph.a[src].a[i].uID == dest) return &(x->rGraph.a[src].a[i]); - } - return NULL; -} - -void init_min_cut_t(min_cut_t* x, hc_links* link, const bubble_type* bub, const ma_ug_t *ug) -{ - uint64_t utg_num = link->a.n, i, k, u, v; - x->n = utg_num; - x->n_e = x->c_e = 0; - - kv_malloc(x->rGraphSet, utg_num); x->rGraphSet.n = utg_num; - ///must utg_num<<1) - kv_malloc(x->rGraphVis, utg_num); x->rGraphVis.n = utg_num; - kv_malloc(x->utgVis, utg_num); x->utgVis.n = utg_num; - kv_malloc(x->bmerVis, utg_num); x->bmerVis.n = utg_num; - kv_malloc(x->order, utg_num); x->order.n = utg_num; - kv_malloc(x->parent, utg_num); x->parent.n = utg_num; - kv_malloc(x->p_weight, utg_num); x->p_weight.n = utg_num; - ///uresolved BUGs, if use kv_resize segfault; if use kv_malloc, work????? - kv_malloc(x->rGraph, utg_num); x->rGraph.n = utg_num; - // kv_init(x->rGraph); kv_resize(hc_edge_warp, x->rGraph, utg_num); x->rGraph.n = utg_num; - x->enzymes = link->enzymes.a; - init_pdq(&(x->pq), utg_num<<1); - - //must be utg_num + 2 since we may need to add fake nodes - for (i = 1; (uint64_t)(1<uID_mode = ((uint64_t)-1) >> (64-i); - x->uID_shift = i; - for (i = 0; i < utg_num; i++) - { - ///x->order.a[i] = link->a.a[i].f.n; - ///x->order.a[i] = ug->u.a[i].len; - x->order.a[i] = x->enzymes[i]; - x->order.a[i] <<= x->uID_shift; - x->order.a[i] |= (uint64_t)(i & x->uID_mode); - - x->rGraphSet.a[i] = 0; - x->rGraphVis.a[i] = 0; - x->utgVis.a[i] = 0; - x->bmerVis.a[i] = 0; - x->parent.a[i] = (uint32_t)-1; - - ///uresolved BUGs, if use kv_resize segfault; if use kv_malloc, work????? - // kv_init(x->rGraph.a[i]); kv_resize(hc_edge, x->rGraph.a[i], link->a.a[i].e.n); - kv_malloc(x->rGraph.a[i], link->a.a[i].e.n); - x->rGraph.a[i].n = link->a.a[i].e.n; - - if(x->rGraph.a[i].n) - { - for (k = 0; k < x->rGraph.a[i].n; k++) - { - ///kv_push(hc_edge, x->rGraph.a[i], link->a.a[i].e.a[k]); - x->rGraph.a[i].a[k] = link->a.a[i].e.a[k]; - x->n_e++; - - if((x->rGraph.a[i].a[k].weight == 0) || IF_HOM(x->rGraph.a[i].a[k].uID, *bub) - || IF_HOM(i, *bub) || (x->rGraph.a[i].a[k].del)) - { - x->rGraph.a[i].a[k].del = 1; - x->n_e--; - } - } - } - } - - hc_edge *p = NULL; - for (i = 0; i < utg_num; i++) - { - v = i; - for (k = 0; k < link->a.a[v].f.n; k++) - { - if(link->a.a[v].f.a[k].del) continue; - u = link->a.a[v].f.a[k].uID; - - - p = get_rGraph_edge(x, v, u); - if(p) - { - p->del = 1; - x->n_e--; - } - - - p = get_rGraph_edge(x, u, v); - if(p) - { - p->del = 1; - x->n_e--; - } - } - } - - x->q = kdq_init(uint64_t); - radix_sort_hc64(x->order.a, x->order.a + x->order.n); - - x->b_mer = asm_opt.bub_mer_length; - ///fprintf(stderr, "[M::%s]\n", __func__); - ///exit(0); -} - -void destory_min_cut_t(min_cut_t* x) -{ - kv_destroy(x->order); - kv_destroy(x->parent); - kv_destroy(x->p_weight); - kv_destroy(x->rGraphSet); - kv_destroy(x->rGraphVis); - kv_destroy(x->utgVis); - kv_destroy(x->bmerVis); - destory_pdq(&(x->pq)); - uint64_t i; - for (i = 0; i < x->rGraph.m; i++) - { - kv_destroy(x->rGraph.a[i]); - } - kv_destroy(x->rGraph); - kdq_destroy(uint64_t, x->q); -} - -void reset_min_cut_t(min_cut_t* x, hc_links* link) -{ - ///no need to reset parent[] and q - uint64_t i, j; - ///important to have this line - x->bmerVis.n = x->parent.n = x->p_weight.n = x->order.n = x->rGraph.n = x->rGraphVis.n = x->rGraphSet.n = link->a.n; - kdq_clear(x->q); - - for (i = 0; i < x->rGraphSet.n; i++) - { - x->rGraphVis.a[i] = 0; - ///x->bmerVis.a[i] = 0; - ///important to have this line - x->rGraph.a[i].n = link->a.a[i].e.n; - - if(x->rGraphSet.a[i] == 0) continue; - for (j = 0; j < x->rGraph.a[i].n; j++) - { - x->rGraph.a[i].a[j].weight = link->a.a[i].e.a[j].weight; - } - x->rGraphSet.a[i] = 0; - } -} - -void update_link_by_min_cut_t(min_cut_t* x, hc_links* link) -{ - uint64_t i, j; - - for (i = 0; i < link->a.n; i++) - { - for (j = 0; j < link->a.a[i].e.n; j++) - { - link->a.a[i].e.a[j].del = x->rGraph.a[i].a[j].del; - } - } -} - -uint64_t add_mul_convex(min_cut_t* x, uint64_t* a, uint64_t n) -{ - if(n == 0) return (uint64_t)-1; - if(n == 1) return a[0]; - kv_push(uint8_t, x->rGraphSet, 0); - kv_push(uint8_t, x->rGraphVis, 0); - kv_push(uint8_t, x->bmerVis, 0); - kv_push(uint32_t, x->parent, 0); - kv_push(double, x->p_weight, 0); - kv_resize(hc_edge_warp, x->rGraph, x->rGraph.n+1); - kv_init(x->rGraph.a[x->rGraph.n]); - uint64_t i, k; - hc_edge t; - for (i = 0; i < n; i++) - { - ///t.uID = a[i]; t.del = t.enzyme = t.weight = 0; - t.uID = a[i]; t.del = t.weight = 0; - for (k = 0; k < x->rGraph.a[a[i]].n; k++) - { - if(x->rGraph.a[a[i]].a[k].del) continue; - t.weight += x->rGraph.a[a[i]].a[k].weight; - } - kv_push(hc_edge, x->rGraph.a[x->rGraph.n], t); - t.uID = x->rGraph.n; - kv_push(hc_edge, x->rGraph.a[a[i]], t); - } - - x->rGraph.n++; - return x->rGraph.n - 1; -} - -void get_s_t(min_cut_t* x, hc_links* link, uint64_t uID, uint64_t* src, uint64_t* dest, kvec_t_u64_warp* buff) -{ - buff->a.n = 0; (*src) = (*dest) = (uint64_t)-1; - if(link->a.a[uID].f.n == 0) return; - (*src) = uID; - - uint64_t i, n; - for (i = 0, n = 0; i < link->a.a[uID].f.n; i++) - { - if(link->a.a[uID].f.a[i].del) continue; - kv_push(uint64_t, buff->a, link->a.a[uID].f.a[i].uID); - (*dest) = link->a.a[uID].f.a[i].uID; - n++; - } - if(n == 1 || n == 0) return; - (*dest) = add_mul_convex(x, buff->a.a, buff->a.n); -} - -uint64_t bfs_flow(uint64_t src, uint64_t dest, min_cut_t* x, kvec_t_u64_warp* buff) -{ - uint64_t *p = NULL, v, u, i; - if(dest != (uint64_t)-1) memset(x->rGraphVis.a, 0, x->rGraphVis.n); - - kdq_push(uint64_t, x->q, src); - if(buff) kv_push(uint64_t, buff->a, src); - - x->rGraphVis.a[src] = 1; - x->parent.a[src] = (uint32_t)-1; - - while (1) - { - p = kdq_shift(uint64_t, x->q); - if(!p) break; - v = *p; - if(v == dest) return 1; - for (i = 0; i < x->rGraph.a[v].n; i++) - { - if(x->rGraph.a[v].a[i].del) continue; - if(x->rGraph.a[v].a[i].weight == 0) continue; - u = x->rGraph.a[v].a[i].uID; - if(x->rGraphVis.a[u]) continue; - if(!x->bmerVis.a[u]) continue; - - x->parent.a[u] = v; - x->p_weight.a[u] = x->rGraph.a[v].a[i].weight; - - kdq_push(uint64_t, x->q, u); - if(buff) kv_push(uint64_t, buff->a, u); - ///set u or v to be 1? doesn't matter - x->rGraphVis.a[u] = 1; - } - } - - return 0; -} - -uint64_t maxFlow(uint64_t src, uint64_t dest, min_cut_t* x) -{ - double flow = 0, max_flow = 0; - uint64_t v, u; - hc_edge *p; - - while (bfs_flow(src, dest, x, NULL)) - { - kdq_clear(x->q); - flow = DBL_MAX; - for (v = dest; v != src; v = x->parent.a[v]) - { - flow = MIN(flow, x->p_weight.a[v]); - } - - /*******************************for debug************************************/ - // if(src == 26818) fprintf(stderr, "***********flow: %f*********\n", flow); - /*******************************for debug************************************/ - - for (v = dest; v != src; v = x->parent.a[v]) - { - u = x->parent.a[v]; - p = get_rGraph_edge(x, u, v); - - /*******************************for debug************************************/ - // if(src == 26818) fprintf(stderr, "utg%.6lul (%f)\n", u+1, p->weight); - /*******************************for debug************************************/ - - p->weight -= flow; - p = get_rGraph_edge(x, v, u); - p->weight += flow; - x->rGraphSet.a[u] = x->rGraphSet.a[v] = 1; - } - - max_flow += flow; - } - - return (max_flow != 0); -} - -uint64_t print_path(uint64_t src, uint64_t dest, min_cut_t* x) -{ - double flow = 0, max_flow = 0; - uint64_t v, u; - hc_edge *p; - - if(bfs_flow(src, dest, x, NULL)) - { - kdq_clear(x->q); - flow = DBL_MAX; - for (v = dest; v != src; v = x->parent.a[v]) - { - flow = MIN(flow, x->p_weight.a[v]); - } - - /*******************************for debug************************************/ - fprintf(stderr, "***********flow: %f*********\n", flow); - /*******************************for debug************************************/ - - for (v = dest; v != src; v = x->parent.a[v]) - { - u = x->parent.a[v]; - p = get_rGraph_edge(x, u, v); - - /*******************************for debug************************************/ - fprintf(stderr, "utg%.6lul (%f)\n", u+1, p->weight); - /*******************************for debug************************************/ - } - - max_flow += flow; - } - - return (max_flow != 0); -} - -void print_src_dest(uint64_t src, min_cut_t* x, const char* command) -{ - uint64_t i; - fprintf(stderr, "********************\n%s\n", command); - if(src >= x->n) - { - for (i = 0; i < x->rGraph.a[src].n; i++) - { - if(x->rGraph.a[src].a[i].del) continue; - fprintf(stderr, "utg%.6ul\n", x->rGraph.a[src].a[i].uID + 1); - } - - } - else - { - fprintf(stderr, "utg%.6lul\n", src+1); - } - fprintf(stderr, "!!!!!!!!!!!!!!!!!!!!\n"); - -} - -void print_debug_rGraph(min_cut_t* x) -{ - fprintf(stderr, "******rGraph******\n"); - uint64_t i, j, u; - for (i = 0; i < x->rGraphVis.n; i++) - { - if(!x->bmerVis.a[i]) continue; - for (j = 0; j < x->rGraph.a[i].n; j++) - { - if(x->rGraph.a[i].a[j].del) continue; - u = x->rGraph.a[i].a[j].uID; - if(!x->bmerVis.a[u]) continue; - fprintf(stderr, "***utg%.6lul\tutg%.6lul\t%f\n", i+1, u+1, x->rGraph.a[i].a[j].weight); - } - } - fprintf(stderr, "******rGraph******\n"); -} - -void graph_cut(uint64_t src, uint64_t dest, min_cut_t* x) -{ - /*******************************for debug************************************/ - ///if(src == 45179) print_debug_rGraph(x); - /*******************************for debug************************************/ - if(maxFlow(src, dest, x)) - { - ///in the last time bfs of maxFlow, rGraphVis has already been set - uint64_t i, j, v, u; - hc_edge *p; - /*******************************for debug************************************/ - if(src == 45179) - ///if(src == 26818) - { - ///print_debug_rGraph(x); - print_src_dest(src, x, "src utg:"); - print_src_dest(dest, x, "dest utg:"); - } - /*******************************for debug************************************/ - for (i = 0; i < x->rGraphVis.n; i++) - { - if(x->rGraphVis.a[i] == 0) continue; - if(!x->bmerVis.a[i]) continue; - v = i; - for (j = 0; j < x->rGraph.a[i].n; j++) - { - if(x->rGraph.a[i].a[j].del) continue; - u = x->rGraph.a[i].a[j].uID; - if(x->rGraphVis.a[u]) continue; - if(!x->bmerVis.a[u]) continue; - /*******************************for debug************************************/ - if(src == 45179) fprintf(stderr, "utg%.6lul\tutg%.6lul\t%f\n", v+1, u+1, x->rGraph.a[i].a[j].weight); - /*******************************for debug************************************/ - ///delete - x->rGraph.a[i].a[j].del = 1; - ///delete - p = get_rGraph_edge(x, u, v); - p->del = 1; - x->c_e += 2; - } - - } - - /*******************************for debug************************************/ - ///if(src == 45179 || src == 31635) - // if(src == 26818) - // { - // fprintf(stderr, "hahahaha\n"); - // print_path(26818, 1143, x); - // } - /*******************************for debug************************************/ - } - /*******************************for debug************************************/ - ///if(src == 45179 || src == 31635) - // { - // print_src_dest(src, x, "++++++src utg:"); - // uint64_t m; - // for (m = 0; m < x->rGraph.a[src].n; m++) - // { - // if(x->rGraph.a[src].a[m].del) continue; - // fprintf(stderr, "src(utg%.6dl, enz:%lu)\tdes(utg%.6dl, enz:%lu)\t%f\n", - // (int)(src+1), x->enzymes[src], - // (int)(x->rGraph.a[src].a[m].uID+1), x->enzymes[x->rGraph.a[src].a[m].uID], - // x->rGraph.a[src].a[m].weight); - // } - // } - /*******************************for debug************************************/ -} - -void check_connective(min_cut_t* x, hc_links* link) -{ - double index_time = yak_realtime(); - kvec_t_u64_warp buff; - kv_init(buff.a); - uint64_t i, k, uID; - for (i = 0; i < x->n; i++) - { - uID = x->order.a[i] & x->uID_mode; - if(link->a.a[uID].f.n == 0) continue; - for (k = 0; k < link->a.a[uID].f.n; k++) - { - if(link->a.a[uID].f.a[k].del) continue; - if(x->utgVis.a[link->a.a[uID].f.a[k].uID] == 0) break; - } - if(k == link->a.a[uID].f.n) continue; - reset_min_cut_t(x, link); - get_s_t(x, link, uID, &(x->src), &(x->dest), &buff); - - bfs_flow(x->src, x->dest, x, NULL); - - x->utgVis.a[uID] = 1; - } - - //reset x.utgVis - memset(x->utgVis.a, 0, x->utgVis.n); - kv_destroy(buff.a); - fprintf(stderr, "[M::%s::%.3f] \n", __func__, yak_realtime()-index_time); -} - -void get_Connected_Components(min_cut_t* x) -{ - double index_time = yak_realtime(); - uint64_t i, j, k = 0, uID, e; - kvec_t_u64_warp buff; - kv_init(buff.a); - while (1) - { - for (i = 0; i < x->n; i++) - { - uID = x->order.a[i] & x->uID_mode; - if(x->rGraphVis.a[uID] == 0) break; - } - if(i < x->n) - { - e = buff.a.n = 0; - bfs_flow(uID, (uint64_t)-1, x, &buff); - for (i = 0; i < buff.a.n; i++) - { - for (j = 0; j < x->rGraph.a[buff.a.a[i]].n; j++) - { - if(x->rGraph.a[buff.a.a[i]].a[j].del == 0) e++; - } - } - e >>= 1; - if(buff.a.n > 1) - { - fprintf(stderr, "(%lu) Component: # nodes: %lu, # edges: %lu\n", - k, (uint64_t)buff.a.n, e); - } - k++; - } - else - { - break; - } - } - - kv_destroy(buff.a); - fprintf(stderr, "[M::%s::%.3f] # Connected Components: %lu\n", - __func__, yak_realtime()-index_time, k); -} - -void print_rGraph(min_cut_t* x) -{ - uint64_t i, k; - for (i = 0; i < x->rGraph.n; ++i) - { - for (k = 0; k < x->rGraph.a[i].n; k++) - { - if(x->rGraph.a[i].a[k].del) continue; - fprintf(stderr, "src(utg%.6dl, enz:%lu)\tdes(utg%.6dl, enz:%lu)\t%f\n", - (int)(i+1), x->enzymes[i], - (int)(x->rGraph.a[i].a[k].uID+1), x->enzymes[x->rGraph.a[i].a[k].uID], - x->rGraph.a[i].a[k].weight); - } - } -} - -int select_large_node(const ma_ug_t *ug, min_cut_t* x, -uint64_t src, uint64_t dest, uint64_t utg_thres, int weight_thres) -{ - if(src >= ug->u.n || dest >= ug->u.n) return 0; - if(ug->u.a[src].n < utg_thres || ug->u.a[dest].n < utg_thres) return 0; - - uint64_t k; - for (k = 0; k < x->rGraph.a[src].n; k++) - { - if(x->rGraph.a[src].a[k].del) continue; - if(x->rGraph.a[src].a[k].weight >= weight_thres) break; - } - if(k == x->rGraph.a[src].n) return 0; - - src = dest; - for (k = 0; k < x->rGraph.a[src].n; k++) - { - if(x->rGraph.a[src].a[k].del) continue; - if(x->rGraph.a[src].a[k].weight >= weight_thres) break; - } - if(k == x->rGraph.a[src].n) return 0; - - return 1; -} - -uint64_t inline set_dv(uint64_t v, uint64_t dis) -{ - dis <<= 32; dis |= v; - return dis; -} - -uint64_t select_bmer(uint32_t src, uint64_t k, const bubble_type* bub, min_cut_t* x, uint32_t bub_only) -{ - uint32_t beg, sink, n, *a; - uint32_t v, d, u, i, nv, b_mer_d, j; - asg_t *sg = bub->ug->g; - uint64_t *p = NULL; - asg_arc_t *av = NULL; - - memset(x->rGraphVis.a, 0, x->rGraphVis.n); - kdq_push(uint64_t, x->q, set_dv(src , 0)); - b_mer_d = 0; - - x->rGraphVis.a[src] = 1; - x->bmerVis.a[src] = 1; - - while (1) - { - p = kdq_shift(uint64_t, x->q); - if(!p) break; - v = (uint32_t)(*p); d = ((uint64_t)(*p))>>32; - - v = v<<1; - av = asg_arc_a(sg, v); - nv = asg_arc_n(sg, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - u = av[i].v>>1; - if(x->rGraphVis.a[u]) continue; - x->rGraphVis.a[u] = 1; - if(IF_HOM(u, *bub)) - { - if(d < k) kdq_push(uint64_t, x->q, set_dv(u, d+1)); - } - else - { - kdq_push(uint64_t, x->q, set_dv(u , d)); - b_mer_d = d; - if(IF_BUB(u, *bub) && x->bmerVis.a[u] == 0) - { - get_bubbles((bubble_type*)bub, bub->index[u], &beg, &sink, &a, &n, NULL); - for (j = 0; j < n; j++) x->bmerVis.a[(a[j]>>1)] = 1; - } - //must be here - if(bub_only == 0) x->bmerVis.a[u] = 1; - } - } - - - v = v + 1; - av = asg_arc_a(sg, v); - nv = asg_arc_n(sg, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - u = av[i].v>>1; - if(x->rGraphVis.a[u]) continue; - x->rGraphVis.a[u] = 1; - if(IF_HOM(u, *bub)) - { - if(d < k) kdq_push(uint64_t, x->q, set_dv(u, d+1)); - } - else - { - kdq_push(uint64_t, x->q, set_dv(u , d)); - b_mer_d = d; - if(IF_BUB(u, *bub) && x->bmerVis.a[u] == 0) - { - get_bubbles((bubble_type*)bub, bub->index[u], &beg, &sink, &a, &n, NULL); - for (j = 0; j < n; j++) x->bmerVis.a[(a[j]>>1)] = 1; - } - //must be here - if(bub_only == 0) x->bmerVis.a[u] = 1; - } - } - } - - return b_mer_d; -} - -void select_bmer_distance(uint32_t src, uint64_t k, const bubble_type* bub, min_cut_t* x, -uint32_t bub_only, uint32_t bub_extend) -{ - uint32_t beg, sink, n, *a; - asg_t *sg = bub->ug->g; - uint64_t v, u, i, j, nv, w, first = 1; - asg_arc_t *av = NULL; - reset_pdq(&(x->pq)); - - x->bmerVis.a[src>>1] = 1; - x->pq.dis.a[src] = 0; - push_pdq(&(x->pq), src, 0); - - while (pdq_cnt(x->pq) > 0) - { - pop_pdq(&(x->pq), &v, &w); - x->pq.vis.a[v] = 1; - if(x->pq.dis.a[v] > k) break; - - ///fprintf(stderr, "******utg%.6dl, dis: %lu\n", (int)((v>>1)+1), x->pq.dis.a[v]); - - if(IF_BUB(v>>1, *bub)) - { - if(bub_extend && x->bmerVis.a[v>>1] == 0) - { - get_bubbles((bubble_type*)bub, bub->index[v>>1], &beg, &sink, &a, &n, NULL); - for (j = 0; j < n; j++) x->bmerVis.a[(a[j]>>1)] = 1; - } - x->bmerVis.a[v>>1] = 1; - } - - if(IF_HET(v>>1, *bub) && bub_only == 0) x->bmerVis.a[v>>1] = 1; - - av = asg_arc_a(sg, v); - nv = asg_arc_n(sg, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - u = av[i].v; - w = (uint32_t)av[i].ul; - if(first) w = 0; - - if(x->pq.vis.a[u] == 0 && x->pq.dis.a[u] > x->pq.dis.a[v] + w) - { - x->pq.dis.a[u] = x->pq.dis.a[v] + w; - push_pdq(&(x->pq), u, x->pq.dis.a[u]); - } - } - - first = 0; - } -} - -void get_bmer_unitgs(min_cut_t* x, const bubble_type* bub, uint64_t k, uint64_t src) -{ - uint32_t beg, sink, n, *a; - if(!IF_BUB(src, *bub)) return; - get_bubbles((bubble_type*)bub, bub->index[src], &beg, &sink, &a, &n, NULL); - memset(x->bmerVis.a, 0, x->bmerVis.n); - ///select_bmer(src, k, bub, x, 1); - select_bmer_distance(beg^1, k, bub, x, 1, 1); - select_bmer_distance(sink^1, k, bub, x, 1, 1); -} - -min_cut_t* clean_hap(hc_links* link, bubble_type* bub, const ma_ug_t *ug) -{ - double index_time = yak_realtime(); - min_cut_t* x; CALLOC(x, 1); - kvec_t_u64_warp buff; - kv_init(buff.a); - init_min_cut_t(x, link, (const bubble_type*)bub, ug); - - // get_Connected_Components(&x); - // check_connective(&x, link); - // print_rGraph(&x); - - long long i; - uint64_t k, uID; - - ///for (i = 0; (uint64_t)i < x.n; i++) - for (i = x->n - 1; i >= 0; i--) - { - uID = x->order.a[i] & x->uID_mode; - ///fprintf(stderr, "uID: %lu, f.n: %lu\n", uID, (uint64_t)link->a.a[uID].f.n); - if(link->a.a[uID].f.n == 0) continue; - for (k = 0; k < link->a.a[uID].f.n; k++) - { - if(link->a.a[uID].f.a[k].del) continue; - if(x->utgVis.a[link->a.a[uID].f.a[k].uID] == 0) break; - } - ///fprintf(stderr, "k: %lu\n", k); - if(k == link->a.a[uID].f.n) continue; - reset_min_cut_t(x, link); - ///fprintf(stderr, "reset\n"); - get_s_t(x, link, uID, &(x->src), &(x->dest), &buff); - ///fprintf(stderr, "x.src: %lu, x.dest: %lu\n", x.src, x.dest); - ///Note: should only consider edges betweem bubbles, ignore edges to homo untigs - - /*******************************for debug************************************/ - ///if(!select_large_node(ug, &x, x.src, x.dest, 10, 0)) continue; - ///if(uID != 26818) continue; - //if(uID != 45179) continue; - ///memset(x.bmerVis.a, 1, x.bmerVis.n); - get_bmer_unitgs(x, bub, x->b_mer, x->src); - x->bmerVis.a[x->src] = x->bmerVis.a[x->dest] = 1; - /*******************************for debug************************************/ - - graph_cut(x->src, x->dest, x); - ///fprintf(stderr, "graph_cut\n"); - x->utgVis.a[uID] = 1; - ///exit(0); - } - - reset_min_cut_t(x, link); - - fprintf(stderr, "[M::%s::%.3f] # edges: %lu, # cutted edges: %lu\n", - __func__, yak_realtime()-index_time, x->n_e, x->c_e); - update_link_by_min_cut_t(x, link); - ///destory_min_cut_t(x); - kv_destroy(buff.a); - return x; -} - -void init_G_partition(G_partition* x, uint64_t n_utg) -{ - uint64_t i; - kv_init(*x); - MALLOC(x->index, n_utg); - for (i = 0; i < n_utg; i++) - { - x->index[i] = (uint32_t)-1; - } -} - -void reset_G_partition(G_partition* x, uint64_t n_utg) -{ - uint64_t i; - x->n = 0; - for (i = 0; i < n_utg; i++) - { - x->index[i] = (uint32_t)-1; - } -} - -void destory_G_partition(G_partition* x) -{ - uint64_t i; - for (i = 0; i < x->n; i++) - { - kv_destroy(x->a[i].a); - } - kv_destroy(*x); - free(x->index); -} - -double get_hc_weight(uint32_t query, uint32_t v0, uint32_t root, bub_p_t_warp *b, min_cut_t* x) -{ - if(v0 == root) return 0; - uint32_t v, u; - hc_edge *p = NULL; - double weight = 0; - v = v0; - do { - u = b->a[v].p; // u->v - p = get_rGraph_edge(x, query>>1, v>>1); - if(p) weight += p->weight; - v = u; - } while (v != root); - - return weight; -} - -void set_path(bub_p_t_warp *b, uint32_t root, uint8_t* flag, uint8_t label) -{ - uint32_t v, u; - ///v is the sink of this bubble - v = b->S.a[0]; - do { - u = b->a[v].p; // u->v - flag[v>>1] |= label; - v = u; - } while (v != root); - flag[b->S.a[0]>>1] = 0; -} - -uint64_t trace_phase_path(ma_ug_t *ug, uint32_t s, uint32_t d, bub_p_t_warp *b, min_cut_t* x, uint8_t* flag, uint8_t label) -{ - asg_t *g = ug->g; - if(g->seq[s>>1].del) return 0; // already deleted - if(get_real_length(g, s, NULL)<2) return 0; - uint32_t i, n_pending, is_first, to_replace, cur_nc, cur_uc, cur_ac, n_tips, tip_end, n_pop; - double cur_nh, cur_rate, max_rate; - ///S saves nodes with all incoming edges visited - b->S.n = b->T.n = b->b.n = b->e.n = 0; - ///for each node, b->a saves all related information - b->a[s].d = b->a[s].nc = b->a[s].ac = b->a[s].uc = 0; b->a[s].nh = 0; - ///b->S is the nodes with all incoming edges visited - kv_push(uint32_t, b->S, s); - n_pop = n_tips = n_pending = 0; - tip_end = (uint32_t)-1; - is_first = 1; - - do { - ///v is a node that all incoming edges have been visited - ///d is the distance from v0 to v - uint32_t v = kv_pop(b->S); - uint32_t d = b->a[v].d, nc = b->a[v].nc, uc = b->a[v].uc, ac = b->a[v].ac; - double nh = b->a[v].nh; - - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - for (i = 0; i < nv; ++i) { - uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l, not overlap length - bub_p_t *t = &b->a[w]; - //got a circle - if ((w>>1) == (s>>1)) goto pop_reset; - //important when poping at long untig graph - if(is_first) l = 0; - if (av[i].del) continue; - ///push the edge - kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); - - if (t->s == 0) - { // this vertex has never been visited - kv_push(uint32_t, b->b, w); // save it for revert - ///t->p is the parent node of - ///t->s = 1 means w has been visited - ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) - t->p = v, t->s = 1, t->d = d + l, t->nc = nc + ug->u.a[(w>>1)].n; - t->r = get_real_length(g, w^1, NULL); - /**need fix**/ - t->nh = nh + get_hc_weight(w, v, s, b, x); - t->ac = ac + (flag[(w>>1)] == 0? ug->u.a[(w>>1)].n : 0); - t->uc = uc + (flag[(w>>1)] != 0? ug->u.a[(w>>1)].n : 0); - ++n_pending; - } - else { - to_replace = 0; - - cur_nc = nc + ug->u.a[(w>>1)].n; - /**need fix**/ - cur_nh = nh + get_hc_weight(w, v, s, b, x); - cur_ac = ac + (flag[(w>>1)] == 0? ug->u.a[(w>>1)].n : 0); - cur_uc = uc + (flag[(w>>1)] != 0? ug->u.a[(w>>1)].n : 0); - cur_rate = ((double)(cur_ac)/(double)(cur_ac+cur_uc)); - max_rate = ((double)(t->ac)/(double)(t->ac+t->uc)); - - if(cur_rate > max_rate) - { - to_replace = 1; - } - else if(cur_rate == max_rate) - { - if(cur_nh > t->nh) - { - to_replace = 1; - } - else if(cur_nh == t->nh) - { - if(cur_nc > t->nc) - { - to_replace = 1; - } - else if(cur_nc == t->nc) - { - if(d + l > t->d) - { - to_replace = 1; - } - } - } - } - - - if(to_replace) - { - t->p = v; - t->nc = cur_nc; - t->nh = cur_nh; - t->ac = cur_ac; - t->uc = cur_uc; - } - - - if (d + l < t->d) t->d = d + l; // update dist - } - - if (--(t->r) == 0) { - uint32_t x = get_real_length(g, w, NULL); - if(x > 0) - { - kv_push(uint32_t, b->S, w); - } - else - { - ///at most one tip - if(n_tips != 0) goto pop_reset; - n_tips++; - tip_end = w; - } - --n_pending; - } - } - is_first = 0; - - - if(n_tips == 1) - { - if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) - { - ///sink is b.S.a[0] - kv_push(uint32_t, b->S, tip_end); - break; - } - else - { - goto pop_reset; - } - } - - if (i < nv || b->S.n == 0) goto pop_reset; - }while (b->S.n > 1 || n_pending); - - - n_pop = 1; - /**need fix**/ - set_path(b, s, flag, label); - pop_reset: - - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - bub_p_t *t = &b->a[b->b.a[i]]; - t->p = t->d = t->nc = t->ac = t->uc = t->r = t->s = 0; - t->nh = 0; - } - - return n_pop; -} - -inline void get_phased_block(G_partition* x, bubble_type* bub, uint64_t id, -uint32_t* beg, uint32_t* sink, uint32_t** h0, uint32_t* h0_n, uint32_t** h1, uint32_t* h1_n, -uint32_t* phased, uint32_t* bub_id) -{ - if(bub && beg && sink && bub_id) - { - (*bub_id) = (*beg) = (*sink) = (uint32_t)-1; - if(x->a[id].a.n > 0) - { - (*bub_id) = bub->index[x->a[id].a.a[0]]; - if(IF_BUB(x->a[id].a.a[0], *bub)) - { - (*beg) = bub->list.a[bub->num.a[(*bub_id)]]; - (*sink) = bub->list.a[bub->num.a[(*bub_id)] + 1]; - } - } - } - - (*h0) = x->a[id].a.a; - (*h0_n) = x->a[id].h[0]; - - (*h1) = x->a[id].a.a + x->a[id].h[0]; - (*h1_n) = x->a[id].h[1]; - if(phased) (*phased) = x->a[id].full_bub; - if((*h0_n) == 0) (*h0) = NULL; - if((*h1_n) == 0) (*h1) = NULL; -} - -double get_co_weight(uint32_t *query, uint32_t query_n, uint32_t *target, uint32_t target_n, min_cut_t* m) -{ - double weight = 0; - hc_edge *p = NULL; - uint32_t i, k; - for (i = 0; i < query_n; i++) - { - for (k = 0; k < target_n; k++) - { - p = get_rGraph_edge(m, query[i], target[k]); - if(p) weight += p->weight; - } - } - - return weight; -} - -void phase_bubble(uint64_t bid, bub_p_t_warp *b, bubble_type* bub, uint8_t* flag, const ma_ug_t *ug, -min_cut_t* m, hc_links* link, G_partition* x) -{ - #define HAP1_LAB 1 - #define HAP2_LAB 2 - - partition_warp* res = NULL; - kv_pushp(partition_warp, *x, &res); - memset(flag, 0, ug->g->n_seq); - uint32_t beg, sink, n, *a, i, k; - get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); - res->full_bub = 0; - trace_phase_path((ma_ug_t *)ug, beg, sink, b, m, flag, HAP1_LAB); - trace_phase_path((ma_ug_t *)ug, beg, sink, b, m, flag, HAP2_LAB); - kv_init(res->a); - for (i = 0; i < ug->g->n_seq; i++) - { - if(flag[i] & (uint8_t)HAP1_LAB) kv_push(uint32_t, res->a, i); - } - res->h[0] = res->a.n; - for (i = 0; i < ug->g->n_seq; i++) - { - if(flag[i] & (uint8_t)HAP2_LAB) kv_push(uint32_t, res->a, i); - } - res->h[1] = res->a.n - res->h[0]; - if(n == 2) res->full_bub = 1; - if(res->full_bub == 0) - { - double self = 0, intersec = 0; - uint32_t *h0 = NULL, *h1 = NULL; - h0 = res->a.a; h1 = res->a.a + res->h[0]; - self += get_co_weight(h0, res->h[0], h0, res->h[0], m); - self += get_co_weight(h1, res->h[1], h1, res->h[1], m); - - intersec += get_co_weight(h0, res->h[0], h1, res->h[1], m); - intersec = intersec * 2; - - if(self > intersec) res->full_bub = 1; - } - - if(res->full_bub == 0) - { - res->a.n = 0; - uint32_t v, u = 0, uv, k_n, pre_n = x->n; - hc_linkeage* t = NULL; - x->n--; - for (i = 0; i < n; i++) - { - v = a[i]>>1; - t = &(link->a.a[v]); - for (k = k_n = 0; k < t->f.n; k++) - { - if(t->f.a[k].del) continue; - k_n++; - u = t->f.a[k].uID; - } - if(k_n != 1) continue; - - t = &(link->a.a[u]); - for (k = k_n = 0; k < t->f.n; k++) - { - if(t->f.a[k].del) continue; - k_n++; - uv = t->f.a[k].uID; - } - if(k_n != 1) continue; - if(uv != v) continue; - - ///avoid dups - for (k = 0; k < i; k++) - { - if((a[k]>>1) == u) break; - } - if(k < i) continue; - - - kv_pushp(partition_warp, *x, &res); - if(x->n > pre_n) kv_init(res->a); - res->full_bub = 0; - res->h[0] = res->h[1] = 1; - kv_push(uint32_t, res->a, v); - kv_push(uint32_t, res->a, u); - - for (k = 0; k < res->a.n; k++) - { - x->index[res->a.a[k]] = x->n-1; - } - } - } - else - { - for (k = 0; k < res->a.n; k++) - { - x->index[res->a.a[k]] = x->n-1; - } - } - - /*******************************for debug************************************/ - // for (i = 0; i < ug->g->n_seq; i++) - // { - // if(flag[i] & (uint8_t)3) - // { - // uint32_t k; - // for (k = 0; k < n; k++) - // { - // if((a[k]>>1) == i) - // { - // break; - // } - // } - - // if(k == n) fprintf(stderr, "ERROR5\n"); - // } - // } - /*******************************for debug************************************/ -} - -void print_phased_bubble(G_partition* x, bubble_type* bub, uint32_t utg_n) -{ - uint64_t i, k; - uint32_t beg = 0, sink = 0, h0_n, h1_n, *h0, *h1, full_bub = 0, bubID = 0; - - for (i = 0; i < x->n; i++) - { - get_phased_block(x, bub, i, &beg, &sink, &h0, &h0_n, &h1, &h1_n, &full_bub, &bubID); - - fprintf(stderr, "\n[%lu]\tbeg:utg%.6ul\tsink:utg%.6ul\tphased=%u\n", i, (beg>>1)+1, (sink>>1)+1, full_bub); - for (k = 0; k < h0_n; k++) - { - fprintf(stderr, "(0) utg%.6ul\n", h0[k] + 1); - } - - for (k = 0; k < h1_n; k++) - { - fprintf(stderr, "(1) utg%.6ul\n", h1[k] + 1); - } - - uint32_t n, *a; - get_bubbles(bub, bubID, &beg, &sink, &a, &n, NULL); - if(n > 2) fprintf(stderr, "complex\n"); - } - - /*******************************for debug************************************/ - for (i = 0; i < utg_n; i++) - { - if(x->index[i] == (uint32_t)-1) continue; - partition_warp* p = &(x->a[x->index[i]]); - for (k = 0; k < p->a.n; k++) - { - if(p->a.a[k] != i) break; - } - - if(k == p->a.n) fprintf(stderr, "ERROR\n"); - } - /*******************************for debug************************************/ -} - -G_partition* clean_bubbles(hc_links* link, bubble_type* bub, min_cut_t* m, const ma_ug_t *ug) -{ - double index_time = yak_realtime(); - uint64_t i; - bub_p_t_warp b; - memset(&b, 0, sizeof(bub_p_t_warp)); - CALLOC(b.a, ug->g->n_seq*2); - uint8_t* flag = NULL; - CALLOC(flag, ug->g->n_seq); - G_partition* x; CALLOC(x, 1); - init_G_partition(x, ug->g->n_seq); - - for (i = 0; i < bub->f_bub; i++) - { - phase_bubble(i, &b, bub, flag, ug, m, link, x); - } - - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - free(flag); - fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); - ///print_phased_bubble(x, bub, ug->g->n_seq); - - return x; -} - -uint64_t get_hic_distance(pe_hit* hit, hc_links* link, const ha_ug_index* idx, uint32_t *is_cc) -{ - uint64_t s_uid, s_dir, e_uid, e_dir, u_dis, k; - long long s_pos, e_pos; - s_uid = ((hit->s<<1)>>(64 - idx->uID_bits)); s_pos = hit->s & idx->pos_mode; - e_uid = ((hit->e<<1)>>(64 - idx->uID_bits)); e_pos = hit->e & idx->pos_mode; - if(s_uid == e_uid) - { - if(is_cc) (*is_cc) = 1; - return MAX(s_pos, e_pos) - MIN(s_pos, e_pos); - } - hc_linkeage* t = &(link->a.a[s_uid]); - for (k = 0; k < t->e.n; k++) - { - if(t->e.a[k].del || t->e.a[k].uID != e_uid) continue; - if(is_cc) (*is_cc) = t->e.a[k].is_cc; - s_dir = (!!(t->e.a[k].dis&(uint64_t)2)); - e_dir = (!!(t->e.a[k].dis&(uint64_t)1)); - u_dis = (t->e.a[k].dis ==(uint64_t)-1? (uint64_t)-1 : t->e.a[k].dis>>3); - // if(s_uid == 24684 && s_pos == 124953 && e_uid == 16950 && e_pos == 93039) - // { - // fprintf(stderr, "*****************s_dir: %lu, e_dir: %lu, u_dis: %lu\n", s_dir, e_dir, u_dis); - // } - if(u_dis == (uint64_t)-1) return (uint64_t)-1; - if(s_dir == 1) s_pos = (long long)idx->ug->g->seq[s_uid].len - s_pos - 1; - if(e_dir == 1) e_pos = (long long)idx->ug->g->seq[e_uid].len - e_pos - 1; - e_pos = e_pos + u_dis - (long long)idx->ug->g->seq[e_uid].len; - return MAX(s_pos, e_pos) - MIN(s_pos, e_pos); - } - - return (uint64_t)-1; -} - -hc_edge* get_hc_edge(hc_links* link, uint64_t src, uint64_t dest, uint64_t dir) -{ - if(src >= link->a.n) return NULL; - uint64_t i, n; - hc_edge* a = NULL; - if(dir == 0) - { - n = link->a.a[src].e.n; - a = link->a.a[src].e.a; - } - else - { - n = link->a.a[src].f.n; - a = link->a.a[src].f.a; - } - - for (i = 0; i < n; i++) - { - if(a[i].del) continue; - if(a[i].uID == dest) return &(a[i]); - } - - return NULL; -} - -inline double get_trans(const ha_ug_index* idx, uint64_t x) -{ - return idx->a*(x/idx->frac) + idx->b; -} - -inline double get_trans_weight_advance(const ha_ug_index* idx, uint64_t x, trans_idx* dis) -{ - long double rate = 0; - - ///if(x == (uint64_t)-1) x = dis->med; - if(x != (uint64_t)-1) - { - if(x < dis->max) - { - uint64_t i; - for (i = 0; i < dis->n; i++) - { - if(x < dis->a[i].end && x >= dis->a[i].beg) break; - } - if(i < dis->n) - { - rate = ((double)(dis->a[i].cnt_1))/((double)(dis->a[i].cnt_0 + dis->a[i].cnt_1)); - } - else - { - rate = get_trans(idx, x); - } - } - else - { - rate = get_trans(idx, x); - } - } - else - { - // rate = 0.2; - rate = 0.4; - } - - - if(rate < 0) rate = 0; - rate += OFFSET_RATE; - if(rate > 0.5) rate = 0.5; - rate -= OFFSET_SECOND_RATE; //[OFFSET_RATE - OFFSET_SECOND_RATE, 0.5 - OFFSET_SECOND_RATE] - - long double w = logl((1/rate)-1)*SCALL; - if(w < OFFSET_RATE_MIN_W) w = OFFSET_RATE_MIN_W; - if(w > OFFSET_RATE_MAX_W) w = OFFSET_RATE_MAX_W; - return w; -} - -void LeastSquare_advance(trans_idx* dis, ha_ug_index* idx, uint64_t med) -{ - #define SCAL_RATE 1000 - long double t1=0, t2=0, t3=0, t4=0, x, y; - uint64_t i, m, ava_size; - - for (i = m = 0; i < dis->n; i++) - { - x = ((double)(dis->a[i].beg + dis->a[i].end))/2; - y = ((double)(dis->a[i].cnt_1))/((double)(dis->a[i].cnt_0 + dis->a[i].cnt_1)); - if(dis->a[i].beg >= med) break; - - t1 += x*x; - t2 += x; - t3 += x*y; - t4 += y; - m++; - } - - if(i < dis->n) - { - uint64_t beg, end, cnt_0, cnt_1; - for (beg = dis->a[i].beg, end = dis->a[i].end, cnt_0 = cnt_1 = 0; i < dis->n; i++) - { - cnt_0 += dis->a[i].cnt_0; - cnt_1 += dis->a[i].cnt_1; - beg = MIN(beg, dis->a[i].beg); - end = MAX(end, dis->a[i].end); - } - - x = ((double)(beg + end))/2; - y = ((double)(cnt_1))/((double)(cnt_0 + cnt_1)); - - t1 += x*x; - t2 += x; - t3 += x*y; - t4 += y; - m++; - } - - - - if(t2 > t4) - { - idx->frac = t2/t4; - if(idx->frac > SCAL_RATE) idx->frac = idx->frac / SCAL_RATE; - if(idx->frac < 1) idx->frac = 1; - } - - ava_size = m; - t1 /= (idx->frac*idx->frac); - t2 /= idx->frac; - t3 /= idx->frac; - if((t1*ava_size - t2*t2) != 0) - { - idx->a = (t3*ava_size - t2*t4) / (t1*ava_size - t2*t2); - } - if((t1*ava_size - t2*t2) != 0) - { - idx->b = (t1*t4 - t2*t3) / (t1*ava_size - t2*t2); - } -} - -void weight_edges_advance(ha_ug_index* idx, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, trans_idx* dis) -{ - uint64_t k, i, shif = 64 - idx->uID_bits, beg, end, t_d; - hc_edge *e1 = NULL, *e2 = NULL; - long double weight; - - for (i = 0; i < link->a.n; i++) - { - for (k = 0; k < link->a.a[i].e.n; k++) - { - if(link->a.a[i].e.a[k].del) continue; - link->a.a[i].e.a[k].weight = 0; - } - } - - for (k = 0; k < hits->a.n; ++k) - { - beg = ((hits->a.a[k].s<<1)>>shif); - end = ((hits->a.a[k].e<<1)>>shif); - - if(beg == end) continue; - if(IF_HOM(beg, *bub)) continue; - if(IF_HOM(end, *bub)) continue; - - t_d = get_hic_distance(&(hits->a.a[k]), link, idx, NULL); - if(t_d == (uint64_t)-1) continue; - - e1 = get_hc_edge(link, beg, end, 0); - e2 = get_hc_edge(link, end, beg, 0); - if(e1 == NULL || e2 == NULL) continue; - weight = 1; - if(dis) - { - weight = get_trans_weight_advance(idx, t_d, dis); - } - - e1->weight += weight; e1->occ++; - e2->weight += weight; e2->occ++; - } -} - -void get_bub_id(bubble_type* bub, uint32_t root, uint64_t* id0, uint64_t* id1, uint32_t check_het) -{ - if(id0) (*id0) = (uint64_t)-1; - if(id1) (*id1) = (uint64_t)-1; - uint64_t b_id0 = (uint64_t)-1, b_id1 = (uint64_t)-1; - uint32_t beg, sink; - - if((bub->b_s_idx.a[root]&0xffffffff) != 0xffffffff) - { - b_id0 = bub->b_s_idx.a[root]&0xffffffff; - if(check_het) - { - get_bubbles(bub, b_id0, &beg, &sink, NULL, NULL, NULL); - if(((beg == (uint32_t)-1) || IF_HET(beg>>1, *bub)) && ((sink == (uint32_t)-1) || IF_HET(sink>>1, *bub))) b_id0 = (uint64_t)-1; - } - } - - if((bub->b_s_idx.a[root]&0xffffffff00000000) != 0xffffffff00000000) - { - b_id1 = bub->b_s_idx.a[root]&0xffffffff00000000; b_id1 >>= 32; - if(check_het) - { - get_bubbles(bub, b_id1, &beg, &sink, NULL, NULL, NULL); - if(((beg == (uint32_t)-1) || IF_HET(beg>>1, *bub)) && ((sink == (uint32_t)-1) || IF_HET(sink>>1, *bub))) b_id1 = (uint64_t)-1; - } - } - - if(b_id0 == (uint64_t)-1 && b_id1 != (uint64_t)-1) - { - b_id0 = b_id1; - b_id1 = (uint64_t)-1; - } - - if(id0) (*id0) = b_id0; - if(id1) (*id1) = b_id1; -} - -///return how many bubbles linked by this node -uint32_t connect_bub_occ(bubble_type* bub, uint32_t root_id, uint32_t check_het) -{ - uint64_t id0, id1, occ = 2; - get_bub_id(bub, root_id, &id0, &id1, check_het); - if(id0 == (uint64_t)-1) occ--; - if(id1 == (uint64_t)-1) occ--; - return occ; -} -///x_0 and x_1 are the ids of unitigs; -///x_0_b_id and x_1_b_id are the ids of bubble graph; -int ma_2_bub_arc(bubble_type* bub, uint32_t x_0, uint32_t* x_0_b_id, uint32_t x_1, uint32_t* x_1_b_id, -asg_arc_t *p, uint32_t check_het) -{ - uint64_t id0, ori_0, id1, ori_1, tmp_id; - uint32_t beg, sink, n, *a, x; - uint32_t beg_0, sink_0, beg_1, sink_1; - if(x_0_b_id) id0 = (*x_0_b_id); - if(x_1_b_id) id1 = (*x_1_b_id); - if((x_0 != (uint32_t)-1) && (x_1 != (uint32_t)-1)) - { - if(((x_0>>1) == (x_1>>1)))///if we would like to find a edge bridging two nearby bubbles - { - if(x_0_b_id == NULL && x_1_b_id == NULL) - { - get_bub_id(bub, x_0>>1, &id0, &id1, check_het); - } - - get_bubbles(bub, id0, &beg_0, &sink_0, &a, &n, NULL);//first bubble - get_bubbles(bub, id1, &beg_1, &sink_1, &a, &n, NULL);//second bubble - - - ori_0 = (uint64_t)-1; - if(x_0 == (beg_0^1)) - { - ori_0 = 1; - } - else if(x_0 == (sink_0^1)) - { - ori_0 = 0; - } - else if(x_0 == (beg_1^1)) - { - ori_0 = 1+2; - } - else if(x_0 == (sink_1^1)) - { - ori_0 = 0+2; - } - else - { - fprintf(stderr, "error 0\n"); - return 0; - } - - - ori_1 = (uint64_t)-1; - if(x_1 == (beg_0^1)) - { - ori_1 = 1; - } - else if(x_1 == (sink_0^1)) - { - ori_1 = 0; - } - else if(x_1 == (beg_1^1)) - { - ori_1 = 1 + 2; - } - else if(x_1 == (sink_1^1)) - { - ori_1 = 0 + 2; - } - else - { - fprintf(stderr, "error 1\n"); - return 0; - } - - - - if((((ori_0>>1)^(ori_1>>1))&1) != 1) - { - fprintf(stderr, "error 10\n"); - fprintf(stderr, "x_0: %u, id0: %lu, beg_0: %u, sink_0: %u, ori_0: %lu\n", - x_0, id0, beg_0, sink_0, ori_0); - fprintf(stderr, "x_1: %u, id1: %lu, beg_1: %u, sink_1: %u, ori_1: %lu\n", - x_1, id1, beg_1, sink_1, ori_1); - return 0; - } - - if(ori_0 & 2) - { - tmp_id = id0; id0 = id1; id1 = tmp_id; - } - - ori_0 &= 1; ori_1 &= 1; ori_1 ^= 1; - - - - p->ul = (id0<<1) | ori_0; p->ul <<= 32; p->ul += 0; - p->v = (id1<<1) | ori_1; - p->ol = 0; p->del = 0; p->el = p->no_l_indel = p->strong = 1; - } - else - { - if(x_0_b_id == NULL) get_bub_id(bub, x_0>>1, &id0, NULL, check_het); - if(x_1_b_id == NULL) get_bub_id(bub, x_1>>1, &id1, NULL, check_het); - - - get_bubbles(bub, id0, &beg, &sink, &a, &n, NULL); - ori_0 = (uint64_t)-1; - if(x_0 == (beg^1)) - { - ori_0 = 1; - } - else if(x_0 == (sink^1)) - { - ori_0 = 0; - } - else - { - fprintf(stderr, "error 0\n"); - return 0; - } - - - - get_bubbles(bub, id1, &beg, &sink, &a, &n, NULL); - ori_1 = (uint64_t)-1; - if(x_1 == (beg^1)) - { - ori_1 = 1; - } - else if(x_1 == (sink^1)) - { - ori_1 = 0; - } - else - { - fprintf(stderr, "error 1\n"); - return 0; - } - ori_0 &= 1; ori_1 &= 1; ori_1 ^= 1; - - p->ul = (id0<<1) | ori_0; p->ul <<= 32; p->ul += 0; - p->v = (id1<<1) | ori_1; - p->ol = 0; p->del = 0; p->el = p->no_l_indel = p->strong = 1; - } - } - else - { - x = (uint32_t)-1; - if(x_0 != (uint32_t)-1) x = x_0; - if(x_1 != (uint32_t)-1) x = x_1; - if(x == (uint32_t)-1) return 0; - if(x_0_b_id == NULL && x_1_b_id == NULL) - { - get_bub_id(bub, x>>1, &id0, &id1, check_het); - } - - if(id0 != (uint64_t)-1) - { - get_bubbles(bub, id0, &beg, &sink, &a, &n, NULL); - if(x == (beg^1)) - { - return 1; - } - else if(x == (sink^1)) - { - return 1; - } - - return 0; - } - - if(id1 != (uint64_t)-1) - { - get_bubbles(bub, id1, &beg, &sink, &a, &n, NULL); - if(x == (beg^1)) - { - return 1; - } - else if(x == (sink^1)) - { - return 1; - } - - return 0; - } - } - - return 1; -} - -#define arc_first(g, v) ((g)->arc[(g)->idx[(v)]>>32]) -#define arc_cnt(g, v) ((uint32_t)(g)->idx[(v)]) -void debug_bub_utg(bubble_type* bub, ma_ug_t *bug, asg_t *bsg, uint32_t check_het) -{ - uint32_t i, k, rId, rId_next, ori, ori_next, root, beg, end; - uint64_t id0, id1; - ma_utg_t *u = NULL; - asg_arc_t *t = NULL; - for (i = 0; i < bug->u.n; i++) - { - u = &(bug->u.a[i]); - if(u->n == 0) continue; - for (k = 0; k < u->n; k++) - { - if(k+1 >= u->n) continue; - rId = u->a[k]>>33; - ori = u->a[k]>>32&1; - get_bubbles(bub, rId, ori == 1?&root:NULL, ori == 0?&root:NULL, NULL, NULL, NULL); - - t = &(arc_first(bsg, u->a[k]>>32)); - get_bub_id(bub, root>>1, &id0, &id1, check_het); - if(id0 == (uint64_t)-1 || (t->el == 1 && id1 == (uint64_t)-1) || (t->el == 0 && id1 != (uint64_t)-1)) - { - fprintf(stderr, "sbsbsb0sbsbsb-utg%.6d, check_het: %u\n", (int)((root>>1)+1), check_het); - fprintf(stderr, "id0: %lu, id1: %lu, t->el: %u\n", id0, id1, t->el); - continue; - } - - ///fprintf(stderr, "aaaaaaaa10aaaaaaaa-utg%.6d\n", (int)((root>>1)+1)); - - rId_next = u->a[k+1]>>33; - ori_next = u->a[k+1]>>32&1; - - - get_bubbles(bub, rId, &beg, &end, NULL, NULL, NULL); - if(ori == 1) - { - if(root != beg) fprintf(stderr, "sbsbsb1sbsbsb, root: %u, beg: %u, end: %u\n", root, beg, end); - } - else - { - if(root != end) fprintf(stderr, "sbsbsb2sbsbsb, root: %u, beg: %u, end: %u\n", root, beg, end); - } - - if(t->el == 1) - { - get_bubbles(bub, rId_next, &beg, &end, NULL, NULL, NULL); - if(ori_next == 0) - { - if(root != (beg^1)) fprintf(stderr, "sbsbsb3sbsbsb, root: %u, beg: %u, end: %u\n", root, beg, end); - } - else - { - if(root != (end^1)) fprintf(stderr, "sbsbsb4sbsbsb, root: %u, beg: %u, end: %u\n", root, beg, end); - } - } - } - } - - fprintf(stderr, "[M::%s]\n", __func__); -} - -///just change the hap status of beg/sink, but they are are still at a chain of bubble -///might be ok -inline void set_bub_idx(bubble_type* bub, ma_utg_t *bu, asg_t *untig_sg, int beg_idx, int end_idx, -uint32_t is_to_hom, uint32_t check_het) -{ - int k; - uint32_t rId, ori, root; - uint64_t id0, id1, len0, len1; - for (k = beg_idx; k <= end_idx; k++) - { - rId = bu->a[k]>>33; - ori = bu->a[k]>>32&1; - get_bubbles(bub, rId, ori == 1?&root:NULL, ori == 0?&root:NULL, NULL, NULL, NULL); - - if(is_to_hom && IF_HOM(root>>1, *bub)) continue; - if(!is_to_hom && IF_HET(root>>1, *bub)) continue; - - - get_bub_id(bub, root>>1, &id0, &id1, check_het); - if(id0 == (uint64_t)-1 || id1 == (uint64_t)-1) continue; - get_bubbles(bub, id0, NULL, NULL, NULL, NULL, &len0); - get_bubbles(bub, id1, NULL, NULL, NULL, NULL, &len1); - - if(is_to_hom) - { - if(untig_sg->seq[root>>1].len > (MIN(len0, len1)*3)) continue; - bub->index[root>>1] = (uint32_t)-1; - } - else - { - bub->index[root>>1] = bub->f_bub+1; - } - - } -} - -void determine_bub_idx(bubble_type* bub, ma_utg_t *bu, asg_t *untig_sg, uint64_t pLen, -uint64_t rLEN, uint64_t r_hetLen, int beg_idx, int end_idx, uint32_t check_het) -{ - if(beg_idx > end_idx) return; - - uint64_t r_homLen = rLEN - r_hetLen; - ///pLen: total length, rLEN: beg/sink length - if(pLen > 0 && rLEN > 0 && r_hetLen > 0 && rLEN < pLen*0.5 && r_hetLen < rLEN * 0.2) ///set het to hom - { - set_bub_idx(bub, bu, untig_sg, beg_idx, end_idx, 1, bub->check_het); - } - else if(pLen > 0 && rLEN > 0 && r_homLen > 0 && rLEN > pLen*0.9 && r_homLen < rLEN * 0.1) ///set hom to het - { - set_bub_idx(bub, bu, untig_sg, beg_idx, end_idx, 0, bub->check_het); - } -} - -void detect_bub_graph(bubble_type* bub, asg_t *untig_sg) -{ - asg_t *bg = bub->b_g; - ma_ug_t *ug = NULL; - ug = ma_ug_gen(bub->b_g); - ///debug_bub_utg(bub, ug, bg, bub->check_het); - uint32_t i, k, rId, ori, root, r_root; - int beg_idx, end_idx; - uint64_t pLen, rLEN, r_hetLen; - ma_utg_t *u = NULL; - asg_arc_t *t = NULL; - for (i = 0; i < ug->u.n; i++)///bubble chain graph; bubbles within the same chain have been merged - { - u = &(ug->u.a[i]); - if(u->n == 0) continue; - ///u is a bubble chain - for (k = pLen = rLEN = r_hetLen = beg_idx = 0, end_idx = -1; k < u->n; k++) - { - rId = u->a[k]>>33; - ori = u->a[k]>>32&1; - get_bubbles(bub, rId, ori == 1?&root:&r_root, ori == 0?&root:&r_root, NULL, NULL, NULL); - - t = NULL; - if(k+1 < u->n) t = &(arc_first(bg, u->a[k]>>32));//edge between two bubbles within the same chain - - pLen += bg->seq[rId].len;///path length in bubble - if(end_idx < beg_idx) ///first bubble - { - pLen += untig_sg->seq[r_root>>1].len; - rLEN += untig_sg->seq[r_root>>1].len; - if(IF_HET(r_root>>1, *bub)) r_hetLen += untig_sg->seq[r_root>>1].len; - } - - if(t) - { - if(t->el == 0)///there is tangle between two bubbles - { - if(end_idx >= beg_idx) - { - pLen += untig_sg->seq[root>>1].len; - rLEN += untig_sg->seq[root>>1].len; - if(IF_HET(root>>1, *bub)) r_hetLen += untig_sg->seq[root>>1].len; - determine_bub_idx(bub, u, untig_sg, pLen, rLEN, r_hetLen, beg_idx, end_idx, bub->check_het); - } - - pLen = rLEN = r_hetLen = 0; - beg_idx = k + 1; end_idx = k; - } - else///two bubbles directly connected with each other - { - pLen += t->ol; - rLEN += t->ol; - if(IF_HET(root>>1, *bub)) r_hetLen += t->ol; - end_idx = k; - } - } - } - - if(end_idx >= beg_idx) - { - pLen += untig_sg->seq[root>>1].len; - rLEN += untig_sg->seq[root>>1].len; - if(IF_HET(root>>1, *bub)) r_hetLen += untig_sg->seq[root>>1].len; - determine_bub_idx(bub, u, untig_sg, pLen, rLEN, r_hetLen, beg_idx, end_idx, bub->check_het); - } - } - - ma_ug_destroy(ug); -} - -void get_bub_graph(ma_ug_t* ug, bubble_type* bub) -{ - asg_t *sg = ug->g; - asg_arc_t t, *p = NULL; - pdq pq; - init_pdq(&pq, sg->n_seq<<1); - uint32_t n_vtx = sg->n_seq<<1, v, k; - uint32_t *pre = NULL; MALLOC(pre, n_vtx); - uint32_t pre_id, adjecent, bub_occ; - asg_t *bub_g = asg_init(); - for (v = 0; v < bub->f_bub; v++)///all bubbles - { - uint64_t pathbase; - uint32_t beg, sink; - get_bubbles(bub, v, &beg, &sink, NULL, NULL, &pathbase); - asg_seq_set(bub_g, v, pathbase, (bub->check_het && IF_HET(beg>>1, *bub) && IF_HET(sink>>1, *bub))?1:0); - bub_g->seq[v].c = PRIMARY_LABLE; - } - - //check all unitigs, instead of bubble nodes - for (v = 0; v < n_vtx; ++v) - { - if(sg->seq[v>>1].del) continue; - if(bub->b_s_idx.a[v>>1] == (uint64_t)-1) continue; ///if (v>>1) is not a beg or sink of bubbles - ///one node might be the beg/sink node of at most two bubbles - bub_occ = connect_bub_occ(bub, v>>1, bub->check_het); - if(bub_occ == 0) continue; - if(bub_occ == 2) - { - if(ma_2_bub_arc(bub, v, NULL, v^1, NULL, &t, bub->check_het)) - { - t.ol = sg->seq[v>>1].len; - p = asg_arc_pushp(bub_g); - *p = t; - } - continue; - } - if(ma_2_bub_arc(bub, v, NULL, (uint32_t)-1, NULL, &t, bub->check_het) == 0) continue; - - ///v is the beg/sink node of only one bubble - get_shortest_path(v, &pq, sg, pre); - for (k = 0; k < pq.dis.n; k++) - { - if(pq.dis.a[k] == (uint64_t)-1) continue; - if(bub->b_s_idx.a[k>>1] == (uint64_t)-1) continue; - if(connect_bub_occ(bub, k>>1, bub->check_het) == 0) continue; - if((k>>1) == (v>>1)) continue; - pre_id = pre[k]; - adjecent = 0; - while (pre_id != v) - { - if(connect_bub_occ(bub, pre_id>>1, bub->check_het) > 0)///some bubbles between v and k - { - adjecent = 1; - break; - } - pre_id = pre[pre_id]; - } - - if(adjecent == 0) - { - if(ma_2_bub_arc(bub, v, NULL, k^1, NULL, &t, bub->check_het))///edges spanning tangles - { - t.el = 0; t.ol = pq.dis.a[k] + sg->seq[k>>1].len; - p = asg_arc_pushp(bub_g); - *p = t; - } - } - } - } - - free(pre); - destory_pdq(&pq); - - asg_cleanup(bub_g); - bub_g->r_seq = bub_g->n_seq; - bub->b_g = bub_g; -} - -void print_bubble_chain(bubble_type* bub, const char* command) -{ - ma_ug_t *ug = NULL; - ug = ma_ug_gen(bub->b_g); - uint32_t i, k, j, rId, beg, sink, *a, n; - ma_utg_t *u = NULL; - asg_arc_t *t = NULL; - for (i = 0; i < ug->u.n; i++) - { - u = &(ug->u.a[i]); - if(u->n == 0) continue; - fprintf(stderr,"\n%s: chain-%u\n", command, i); - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - get_bubbles(bub, rId, &beg, &sink, &a, &n, NULL); - t = NULL; - if(k+1 < u->n) t = &(arc_first(bub->b_g, u->a[k]>>32)); - fprintf(stderr, "[utg%.6dl, utg%.6dl] el=%u no_long_indel=%u, rId=%u, nv: %u, nv^: %u\n", - (int)((beg>>1)+1), (int)((sink>>1)+1), t?t->el:16, t?t->no_l_indel:16, rId, arc_cnt(bub->b_g, u->a[k]>>32), arc_cnt(bub->b_g, (u->a[k]>>32)^1)); - // if((u->a[k]>>33) == 9658) - // { - // asg_arc_t *av; - // uint32_t nv, nv_i; - // av = asg_arc_a(bub->b_g, u->a[k]>>32); - // nv = asg_arc_n(bub->b_g, u->a[k]>>32); - // for (nv_i = 0; nv_i < nv; nv_i++) - // { - // if(av[nv_i].del) continue; - // fprintf(stderr, "v--->%u\n", av[nv_i].v>>1); - // } - - - - // av = asg_arc_a(bub->b_g, (u->a[k]>>32)^1); - // nv = asg_arc_n(bub->b_g, (u->a[k]>>32)^1); - // for (nv_i = 0; nv_i < nv; nv_i++) - // { - // if(av[nv_i].del) continue; - // fprintf(stderr, "v^1--->%u\n", av[nv_i].v>>1); - // } - - // } - if(bub->b_g->seq[rId].c == HAP_LABLE) - { - for (j = 0; j < n; j++) - { - fprintf(stderr, ">>>utg%.6dl\n", (int)((a[j]>>1)+1)); - } - } - } - } - - ma_ug_destroy(ug); -} - -int is_simple_broken_bubble(ma_ug_t *unitig_ug, uint32_t x, uint32_t beg, uint32_t sink, uint32_t* new_het) -{ - uint32_t nv, v = (uint32_t)-1, u_s = (uint32_t)-1, u_e = (uint32_t)-1, i; - asg_arc_t *av = NULL; - (*new_het) = (uint32_t)-1; - - if((asg_arc_n(unitig_ug->g, x) == 1) - && (asg_arc_n(unitig_ug->g, x^1) == 0)) - { - v = x; - } - - if((asg_arc_n(unitig_ug->g, x^1) == 1) - && (asg_arc_n(unitig_ug->g, x) == 0)) - { - v = x^1; - } - - if(v == (uint32_t)-1) return 0; - - - av = asg_arc_a(unitig_ug->g, v); - nv = asg_arc_n(unitig_ug->g, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - if((av[i].v>>1) == (beg>>1)) u_s = beg, u_e = sink; - if((av[i].v>>1) == (sink>>1)) u_s = sink, u_e = beg; - } - - if(u_s == (uint32_t)-1 || u_e == (uint32_t)-1) return 0; - - av = asg_arc_a(unitig_ug->g, u_s); - nv = asg_arc_n(unitig_ug->g, u_s); - if(nv != 2) return 0; - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - if(av[i].v == (v^1)) continue; - if(av[i].v == (u_e^1)) - { - (*new_het) = u_e; - return 1; - } - } - - return 0; -} - -int double_check_broken_bubble(asg_t *g, kvec_t_u32_warp* broken, uint32_t beg, uint32_t sink, -uint8_t* vis_flag, uint32_t vis_flag_n, kvec_t_u32_warp* stack, asg_t *bsg, asg_arc_t *p_t) -{ - uint32_t cur, ncur, i, n, pre, occ; - radix_sort_u32(broken->a.a, broken->a.a + broken->a.n); - for (i = n = 0, pre = (uint32_t)-1; i < broken->a.n; i++) - { - if((broken->a.a[i]>>1) == (pre>>1)) continue;///skip same node like v and v^1 - pre = broken->a.a[i]; - broken->a.a[n] = pre; - n++; - } - broken->a.n = n; - - asg_arc_t *acur = NULL; - memset(vis_flag, 0, vis_flag_n); - stack->a.n = 0; - kv_push(uint32_t, stack->a, beg); - occ = 0; - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - if(vis_flag[cur] == 0 && vis_flag[cur^1] == 0) occ++; - if(vis_flag[cur] == 0 && cur != (beg^1) && (sink == (uint32_t)-1 || cur != (sink^1))) - { - vis_flag[cur] = 1; - ncur = asg_arc_n(g, cur); - acur = asg_arc_a(g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if(vis_flag[acur[i].v]) continue; - kv_push(uint32_t, stack->a, acur[i].v); - } - } - vis_flag[cur] = 1; - - - cur^=1; - if(vis_flag[cur] == 0 && cur != (beg^1) && (sink == (uint32_t)-1 || cur != (sink^1))) - { - vis_flag[cur] = 1; - ncur = asg_arc_n(g, cur); - acur = asg_arc_a(g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if(vis_flag[acur[i].v]) continue; - kv_push(uint32_t, stack->a, acur[i].v); - } - } - vis_flag[cur] = 1; - } - - n = broken->a.n; - if(beg != (uint32_t)-1) n++; - if(sink != (uint32_t)-1) n++; - - if(occ > n) - { - ///fprintf(stderr, "\n+++++sb+++++beg-utg%.6ul, sink-utg%.6ul, occ: %u, n: %u\n", (beg>>1)+1, (sink>>1)+1, occ, n); - if(bsg && p_t && beg != (uint32_t)-1 && sink != (uint32_t)-1) - { - p_t->del = 1; - asg_arc_del(bsg, (p_t->v)^1, (p_t->ul>>32)^1, 1); - } - /*******************************for debug************************************/ - // memset(vis_flag, 0, vis_flag_n); - // stack->a.n = 0; - // kv_push(uint32_t, stack->a, beg); - // occ = 0; - // while (stack->a.n > 0) - // { - // occ++; - // stack->a.n--; - // cur = stack->a.a[stack->a.n]; - - // fprintf(stderr, "cur-utg%.6ul\n", (cur>>1)+1); - - // vis_flag[cur] = 1; - // if(cur == (beg^1) || cur == (sink^1)) continue; - // ncur = asg_arc_n(g, cur); - // acur = asg_arc_a(g, cur); - // for (i = 0; i < ncur; i++) - // { - // if(acur[i].del) continue; - // if(vis_flag[acur[i].v]) continue; - // kv_push(uint32_t, stack->a, acur[i].v); - // } - - // cur^=1; - // if(vis_flag[cur]) continue; - // vis_flag[cur] = 1; - // if(cur == (beg^1) || cur == (sink^1)) continue; - // ncur = asg_arc_n(g, cur); - // acur = asg_arc_a(g, cur); - // for (i = 0; i < ncur; i++) - // { - // if(acur[i].del) continue; - // if(vis_flag[acur[i].v]) continue; - // kv_push(uint32_t, stack->a, acur[i].v); - // } - // } - - // for (i = 0; i < broken->a.n; i++) - // { - // fprintf(stderr, "*****cur-utg%.6ul\n", (broken->a.a[i]>>1)+1); - // } - /*******************************for debug************************************/ - return 0; - } - - return 1; -} - -int is_local_simple_circle(asg_t *g, uint32_t v) -{ - if(asg_arc_n(g, v) != asg_arc_n(g, v^1)) return 0; - if(asg_arc_n(g, v) == 1) v = arc_first(g, v).v; - if(asg_arc_n(g, v) != asg_arc_n(g, v^1)) return 0; - if(asg_arc_n(g, v) != 2) return 0; - uint32_t ncur, i, u; - asg_arc_t *acur = NULL; - ncur = asg_arc_n(g, v); - acur = asg_arc_a(g, v); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - u = acur[i].v; - if(asg_arc_n(g, u) != 1 || asg_arc_n(g, u^1) != 1) continue; - if(arc_first(g, u).v != v) continue; - return 1; - } - return 0; -} - -///actually not useful, and may have bug when one bubble at multipe chains -void update_bub_b_s_idx(bubble_type* bub) -{ - memset(bub->b_s_idx.a, -1, bub->b_s_idx.n * sizeof(uint64_t)); - uint32_t i, v, beg, sink, n_bub = bub->num.n - 1; - for (i = 0; i < n_bub; i++) - { - get_bubbles(bub, i, &beg, &sink, NULL, NULL, NULL); - - if(beg != (uint32_t)-1) - { - v = beg>>1; - if(bub->b_s_idx.a[v] == (uint64_t)-1) - { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } - else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) - { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } - } - - - - if(sink != (uint32_t)-1) - { - v = sink>>1; - if(bub->b_s_idx.a[v] == (uint64_t)-1) - { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } - else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) - { - bub->b_s_idx.a[v] <<= 32; - bub->b_s_idx.a[v] |= i; - } - } - } -} - -void update_bubble_graph(kvec_t_u32_warp* broken, uint32_t beg, uint32_t beg_bub_id, -uint32_t sink, uint32_t sink_bub_id, bubble_type* bub, kvec_asg_arc_t_warp* edges, asg_t *bsg, -asg_arc_t *p_t, uint8_t *bsg_idx, ma_ug_t *unitig_ug, uint64_t* occ_thres, uint64_t is_b_bub) -{ - uint32_t i, pre, n, bub_id, v; - uint64_t occ; - asg_arc_t t_f, t_r; - - radix_sort_u32(broken->a.a, broken->a.a + broken->a.n); - for (i = n = occ = 0, pre = (uint32_t)-1; i < broken->a.n; i++) - { - if((broken->a.a[i]>>1) == (pre>>1)) continue; - if(IF_HOM((broken->a.a[i]>>1), *bub)) - { - if(is_local_simple_circle(unitig_ug->g, broken->a.a[i])) - { - bub->index[broken->a.a[i]>>1] = bub->f_bub+1; - } - else - { - continue; - } - } - - pre = broken->a.a[i]; - broken->a.a[n] = pre; - occ += unitig_ug->u.a[broken->a.a[n]>>1].n; - n++; - } - broken->a.n = n; - ///if(broken->a.n == 0) return; - if(broken->a.n == 1) - { - ///fprintf(stderr, "+++++sb+++++utg%.6ul\n", (broken->a.a[0]>>1)+1); - if(beg != (uint32_t)-1 && sink != (uint32_t)-1 && - is_simple_broken_bubble(unitig_ug, broken->a.a[0], beg, sink, &v)) - { - if((v>>1) != (broken->a.a[0]>>1)) - { - ///fprintf(stderr, "-----sb-----utg%.6ul\n", (v>>1)+1); - kv_push(uint32_t, broken->a, v); - occ += unitig_ug->u.a[v>>1].n; - if(occ_thres && occ > (*occ_thres)) return; - bub->index[v>>1] = bub->f_bub+1; ///set to het - } - } - } - - - if(occ_thres && occ > (*occ_thres)) return; - /********************push graph node********************/ - bub_id = bub->b_g->n_seq; - asg_seq_set(bub->b_g, bub_id, 0, 0); - bub->b_g->seq[bub_id].c = HAP_LABLE; - if(is_b_bub) bub->b_bub++; - /********************push graph node********************/ - - /********************push bubble********************/ - kv_push(uint32_t, bub->num, bub->list.n); - kv_push(uint64_t, bub->pathLen, 0); - kv_push(uint32_t, bub->list, beg); - kv_push(uint32_t, bub->list, sink); - - for (i = 0; i < broken->a.n; i++) - { - kv_push(uint32_t, bub->list, broken->a.a[i]); - if(bsg_idx) bsg_idx[broken->a.a[i]>>1] = 1; - } - /********************push bubble********************/ - if(beg != (uint32_t)-1) ///beg_bub_id ----> bub_id - { - if(ma_2_bub_arc(bub, beg, &beg_bub_id, beg^1, &bub_id, &t_f, bub->check_het) && - ma_2_bub_arc(bub, beg^1, &bub_id, beg, &beg_bub_id, &t_r, bub->check_het)) - { - t_f.el = 0; t_f.no_l_indel = 0; t_f.del = 0; - kv_push(asg_arc_t, edges->a, t_f); - - t_r.el = 0; t_r.no_l_indel = 0; t_r.del = 0; - kv_push(asg_arc_t, edges->a, t_r); - } - } - - if(sink != (uint32_t)-1) ///bub_id ----> sink_bub_id - { - if(ma_2_bub_arc(bub, sink^1, &bub_id, sink, &sink_bub_id, &t_f, bub->check_het) && - ma_2_bub_arc(bub, sink, &sink_bub_id, sink^1, &bub_id, &t_r, bub->check_het)) - { - t_f.el = 0; t_f.no_l_indel = 0; t_f.del = 0; - kv_push(asg_arc_t, edges->a, t_f); - - t_r.el = 0; t_r.no_l_indel = 0; t_r.del = 0; - kv_push(asg_arc_t, edges->a, t_r); - } - } - - if(beg != (uint32_t)-1 && sink != (uint32_t)-1 && p_t) - { - p_t->del = 1; - asg_arc_del(bsg, (p_t->v)^1, (p_t->ul>>32)^1, 1); - } -} - -void get_related_bub_nodes(kvec_t_u32_warp* broken, bubble_type* bub, pdq* pq, asg_t *unitig_g, - uint32_t *pre, uint32_t src, uint32_t dest, uint8_t *bsg_idx) -{ - uint32_t j_i, pre_id, adjecent; - src ^= 1; - get_shortest_path(src, pq, unitig_g, pre); - - for (j_i = 0; j_i < pq->dis.n; j_i++) - { - if(pq->dis.a[j_i] == (uint64_t)-1) continue; - ///if(IF_HOM(j_i>>1, *bub)) continue; - if((j_i>>1) == (src>>1)) continue; - if((dest != (uint32_t)-1) && ((j_i>>1) == (dest>>1))) continue; - - pre_id = pre[j_i]; - adjecent = 0; - while (pre_id != src) - { - if(((dest != (uint32_t)-1) && ((pre_id>>1) == (dest>>1))) - || ((pre_id>>1) == (src>>1))) - { - adjecent = 1; - break; - } - pre_id = pre[pre_id]; - } - - if(adjecent == 0) - { - if(broken->a.n == 0 || (broken->a.n > 0 && (j_i>>1) != (broken->a.a[broken->a.n - 1]>>1))) - { - if(bsg_idx && bsg_idx[(j_i>>1)]) - { - broken->a.n = 0; - return; - } - kv_push(uint32_t, broken->a, j_i); - } - } - } -} - -uint64_t calculate_chain_weight(ma_utg_t *u, bubble_type* bub, ma_ug_t *unitig_ug, chain_w_type* x) -{ - x->b_occ = x->g_occ = 0; - uint32_t i, j, *a, n; - uint64_t occ, occ_n, thres; - for (i = occ = occ_n = 0; i < u->n; i++) - { - if(bub->b_g->seq[u->a[i]>>33].c != HAP_LABLE) - { - get_bubbles(bub, u->a[i]>>33, NULL, NULL, &a, &n, NULL); - for (j = 0; j < n; j++) - { - occ += unitig_ug->u.a[a[j]>>1].n; - } - occ_n++; - } - } - - thres = (uint64_t)-1; - if(occ_n > 0) thres = (occ*6)/occ_n; - - for (i = 0; i < u->n; i++) - { - occ = 0; - get_bubbles(bub, u->a[i]>>33, NULL, NULL, &a, &n, NULL); - for (j = 0; j < n; j++) - { - occ += unitig_ug->u.a[a[j]>>1].n; - } - - if(bub->b_g->seq[u->a[i]>>33].c != HAP_LABLE || occ < thres) - { - x->g_occ += occ; - } - else - { - x->b_occ += occ; - } - } - - return thres; -} - -int cmp_chain_weight(const void * a, const void * b) -{ - if((*(chain_w_type*)a).del != (*(chain_w_type*)b).del) - { - return (*(chain_w_type*)a).del > (*(chain_w_type*)b).del? 1 : -1; - } - else - { - long long a_occ = (*(chain_w_type*)a).g_occ - (*(chain_w_type*)a).b_occ; - long long b_occ = (*(chain_w_type*)b).g_occ - (*(chain_w_type*)b).b_occ; - if(a_occ != b_occ) - { - return a_occ > b_occ? -1 : 1; - } - else - { - return 0; - } - } -} - -void resolve_bubble_chain_tangle_back(ma_ug_t* ug, bubble_type* bub, hc_links* link) -{ - ma_ug_t *copy_ug = copy_untig_graph(bub->b_ug); - asg_arc_t *av = NULL; - uint32_t i, j, k, v, w, w1, w2, nw1, nw2, nv, occ_e_1, occ_e_2, occ_c; - ma_ug_t *bub_ug = copy_ug; - ///ma_utg_t *u = NULL; - buf_t b; memset(&b, 0, sizeof(buf_t)); - kvec_t_u32_warp stack, result; - kv_init(stack.a); kv_init(result.a); - uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq<<1); - uint8_t *is_vis = NULL; CALLOC(is_vis, ug->g->n_seq<<1); - kvec_t(uint64_t) occ_idx; kv_init(occ_idx); uint64_t tmp, *p = NULL; - - for (k = occ_idx.n = 0; k < bub_ug->g->n_seq; k++) - { - v = (k<<1); - av = asg_arc_a(bub_ug->g, v); - nv = asg_arc_n(bub_ug->g, v); - for (i = 0, w = (uint32_t)-1, nw1 = 0; i < nv; i++) - { - if(av[i].del) continue; - nw1++; - if((av[i].v>>1) == (v>>1)) continue; - if(w != (uint32_t)-1) break; - w = av[i].v; - } - if(i < nv) continue; - w1 = w; - - - v = (k<<1)+1; - av = asg_arc_a(bub_ug->g, v); - nv = asg_arc_n(bub_ug->g, v); - for (i = 0, w = (uint32_t)-1, nw2 = 0; i < nv; i++) - { - if(av[i].del) continue; - nw2++; - if((av[i].v>>1) == (v>>1)) continue; - if(w != (uint32_t)-1) break; - w = av[i].v; - } - if(i < nv) continue; - w2 = w; - - if(nw1 <= 1 && nw2 <= 1) continue; - if(w1 == (uint32_t)-1 && w2 == (uint32_t)-1) continue; - if(w1 != (uint32_t)-1) w1 ^=1; - if(w2 != (uint32_t)-1) w2 ^=1; - - if(w1 != (uint32_t)-1) - { - w = (uint32_t)-1; - if(w2 != (uint32_t)-1) w = w2^1; - - av = asg_arc_a(bub_ug->g, w1); - nv = asg_arc_n(bub_ug->g, w1); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - if((av[i].v>>1) == k) continue; - if(av[i].v == w) continue; - break; - } - if(i < nv) continue; - } - - - if(w2 != (uint32_t)-1) - { - w = (uint32_t)-1; - if(w1 != (uint32_t)-1) w = w1^1; - - av = asg_arc_a(bub_ug->g, w2); - nv = asg_arc_n(bub_ug->g, w2); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - if((av[i].v>>1) == k) continue; - if(av[i].v == w) continue; - break; - } - if(i < nv) continue; - } - - - if(w1 == (uint32_t)-1 && w2 != (uint32_t)-1) w1 = w2; - if(w1 == w2) w2 = (uint32_t)-1; - - occ_c = occ_e_1 = occ_e_2 = (uint32_t)-1; - set_b_utg_weight_flag(bub, &b, k<<1, NULL, 0, &occ_c); - if(w1 != (uint32_t)-1) set_b_utg_weight_flag(bub, &b, w1^1, NULL, 0, &occ_e_1); - if(w2 != (uint32_t)-1) set_b_utg_weight_flag(bub, &b, w2^1, NULL, 0, &occ_e_2); - - fprintf(stderr, "\n>>>>>>k=btg%.6ul (n=%u), w1=btg%.6ul (n=%u), w2=utg%.6ul (n=%u)\n", k+1, occ_c, - (w1>>1)+1, occ_e_1, (w2>>1)+1, occ_e_2); - - if(occ_c*5 >= occ_e_1) continue; - if(occ_c*5 >= occ_e_2) continue; - if(occ_c*10 >= (occ_e_1 + occ_e_2)) continue; - kv_pushp(uint64_t, occ_idx, &p); - (*p) = occ_e_1 + occ_e_2 - occ_c; - (*p) <<= 32; (*p) += k; - fprintf(stderr, "passed\n"); - } - - radix_sort_hc64(occ_idx.a, occ_idx.a + occ_idx.n); - - for (k = 0; k < occ_idx.n; ++k) - { - tmp = occ_idx.a[k]; - occ_idx.a[k] = occ_idx.a[occ_idx.n - k - 1]; - occ_idx.a[occ_idx.n - k - 1] = tmp; - } - - for (j = 0; j < occ_idx.n; j++) - { - k = (uint32_t)occ_idx.a[j]; - - v = (k<<1); - av = asg_arc_a(bub_ug->g, v); - nv = asg_arc_n(bub_ug->g, v); - for (i = 0, w = (uint32_t)-1, nw1 = 0; i < nv; i++) - { - if(av[i].del) continue; - nw1++; - if((av[i].v>>1) == (v>>1)) continue; - if(w != (uint32_t)-1) break; - w = av[i].v; - } - if(i < nv) continue; - w1 = w; - - - v = (k<<1)+1; - av = asg_arc_a(bub_ug->g, v); - nv = asg_arc_n(bub_ug->g, v); - for (i = 0, w = (uint32_t)-1, nw2 = 0; i < nv; i++) - { - if(av[i].del) continue; - nw2++; - if((av[i].v>>1) == (v>>1)) continue; - if(w != (uint32_t)-1) break; - w = av[i].v; - } - if(i < nv) continue; - w2 = w; - - if(nw1 <= 1 && nw2 <= 1) continue; - if(w1 == (uint32_t)-1 && w2 == (uint32_t)-1) continue; - if(w1 != (uint32_t)-1) w1 ^=1; - if(w2 != (uint32_t)-1) w2 ^=1; - - - - } - - free(vis); free(is_vis); free(b.b.a); kv_destroy(occ_idx); kv_destroy(stack.a); kv_destroy(result.a); - ma_ug_destroy(copy_ug); -} - -uint32_t get_btg_occ(bubble_type* bub, uint32_t v) -{ - ma_ug_t *bub_ug = bub->b_ug; - ma_utg_t *u = NULL; - uint32_t k_i, k_j, *a = NULL, n, tan_occ = 0; - - u = &(bub_ug->u.a[v]); - for (k_i = 0; k_i < u->n; k_i++) - { - get_bubbles(bub, u->a[k_i]>>33, NULL, NULL, &a, &n, NULL); - for (k_j = 0; k_j < n; k_j++) - { - tan_occ += bub->ug->u.a[a[k_j]>>1].n; - } - } - return tan_occ; -} - -int check_bubble_tangle(bubble_type* bub, ma_ug_t* ug, uint32_t beg, uint32_t sink, -double side_rate, double total_rate, uint32_t beg_occ, uint32_t sink_occ, -uint8_t* is_vis, kvec_t_u32_warp* stack, kvec_t_u32_warp* res, uint8_t* chain_flag, -uint32_t* extra_check) -{ - if(extra_check) (*extra_check) = 1; - uint32_t cur, tan_occ = 0, ncur, i, no_first = 0; - asg_arc_t *acur = NULL; - memset(is_vis, 0, ug->g->n_seq<<1); - stack->a.n = 0; - kv_push(uint32_t, stack->a, beg); - if(res) res->a.n = 0; - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - - if(no_first && cur == beg) return 0; - if(sink != (uint32_t)-1 && cur == sink) return 0; - - - if(is_vis[cur] == 0 && is_vis[cur^1] == 0) - { - if((cur>>1) != (beg>>1) && (sink == (uint32_t)-1 || (cur>>1) != (sink>>1))) - { - if(res) kv_push(uint32_t, res->a, cur); - if(chain_flag && chain_flag[cur>>1] != 0 && extra_check) - { - (*extra_check) = 0; - } - - if(bub) - { - tan_occ += get_btg_occ(bub, cur>>1); - if(tan_occ*side_rate >= beg_occ) return 0; - if(sink != (uint32_t)-1 && (tan_occ*side_rate >= sink_occ)) return 0; - if(tan_occ*total_rate >= (beg_occ + ((sink != (uint32_t)-1)?sink_occ : 0))) return 0; - } - } - } - - - if(is_vis[cur] == 0 && cur != (beg^1) && (sink == (uint32_t)-1 || cur != (sink^1))) - { - is_vis[cur] = 1; - ncur = asg_arc_n(ug->g, cur); - acur = asg_arc_a(ug->g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - - if(acur[i].v == beg) return 0; - if(sink != (uint32_t)-1 && acur[i].v == sink) return 0; - - if(is_vis[acur[i].v]) continue; - kv_push(uint32_t, stack->a, acur[i].v); - } - } - is_vis[cur] = 1; - - - cur^=1; - if(is_vis[cur] == 0 && cur != (beg^1) && (sink == (uint32_t)-1 || cur != (sink^1))) - { - is_vis[cur] = 1; - ncur = asg_arc_n(ug->g, cur); - acur = asg_arc_a(ug->g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - - if(acur[i].v == beg) return 0; - if(sink != (uint32_t)-1 && acur[i].v == sink) return 0; - - if(is_vis[acur[i].v]) continue; - kv_push(uint32_t, stack->a, acur[i].v); - } - } - is_vis[cur] = 1; - no_first = 1; - } - - if(bub) - { - if(tan_occ*side_rate >= beg_occ) return 0; - if(sink != (uint32_t)-1 && (tan_occ*side_rate >= sink_occ)) return 0; - if(tan_occ*total_rate >= (beg_occ + ((sink != (uint32_t)-1)?sink_occ : 0))) return 0; - } - - return 1; -} - - -int find_bubble_tangle(bubble_type* bub, ma_ug_t* ug, uint8_t* is_vis, uint8_t* is_vis2, -uint32_t v, double side_rate, double total_rate, kvec_t_u32_warp* stack, -kvec_t_u32_warp* stack2, kvec_t_u32_warp* res_btg, kvec_t_u32_warp* res_utg, uint8_t* chain_flag, -uint32_t* r_b_utg_beg, uint32_t* r_b_utg_sink, uint32_t* r_b_tg_beg, uint32_t* r_b_tg_sink, -uint32_t* r_utg_beg, uint32_t* r_utg_sink) -{ - (*r_b_utg_beg) = (*r_b_utg_sink) = (*r_b_tg_beg) = (*r_b_tg_sink) = (*r_utg_beg) = (*r_utg_sink) = (uint32_t)-1; - ma_ug_t *bub_ug = bub->b_ug; - ma_utg_t *u = NULL; - uint32_t tan_occ = 0, cur, ncur, i, k, no_root = 0, v_occ, c_occ, utg_occ, w, btg_beg, btg_sink, utg_beg, utg_sink, is_t, extra_check; - stack->a.n = 0; - asg_arc_t *acur = NULL; - - memset(is_vis, 0, bub_ug->g->n_seq<<1); - stack->a.n = 0; - kv_push(uint32_t, stack->a, v); - v_occ = get_btg_occ(bub, v>>1); - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - if(is_vis[cur]) continue; - - c_occ = 0; - if(no_root && cur == v) return 0; - if(no_root && is_vis[cur] == 0 && is_vis[cur^1] == 0) - { - c_occ = get_btg_occ(bub, cur>>1); - ///assume v_occ is the beg node, c_occ is the end node, which means tan_occ cannot be too large - if((tan_occ*side_rate) < c_occ && (tan_occ*total_rate) < (c_occ + v_occ)) - { - if(check_bubble_tangle(bub, bub->b_ug, v, cur^1, side_rate, total_rate, v_occ, c_occ, - is_vis2, stack2, NULL, NULL, NULL)) - { - check_bubble_tangle(bub, bub->b_ug, v, cur^1, side_rate, total_rate, v_occ, c_occ, - is_vis2, stack2, res_btg, NULL, NULL); - - for (k = 0; k < res_btg->a.n; k++) - { - set_b_utg_weight_flag(bub, NULL, res_btg->a.a[k], chain_flag, 0, NULL); - } - btg_beg = v; btg_sink = cur^1;///b_utg id - - u = &(bub_ug->u.a[btg_beg>>1]); - if((btg_beg&1)==1) - { - get_bubbles(bub, (u->a[0]>>32)>>1, (((u->a[0]>>32)&1)^1)==1?&w:NULL, - (((u->a[0]>>32)&1)^1) == 0?&w:NULL, NULL, NULL, NULL); - (*r_b_tg_beg) = u->a[0]>>32; - } - else - { - get_bubbles(bub, (u->a[u->n-1]>>32)>>1, ((u->a[u->n-1]>>32)&1)==1?&w:NULL, - ((u->a[u->n-1]>>32)&1) == 0?&w:NULL, NULL, NULL, NULL); - (*r_b_tg_beg) = u->a[u->n-1]>>32; - } - utg_beg = w^1; ///ug id - - - u = &(bub_ug->u.a[btg_sink>>1]); - if((btg_sink&1)==1) - { - get_bubbles(bub, (u->a[0]>>32)>>1, (((u->a[0]>>32)&1)^1)==1?&w:NULL, - (((u->a[0]>>32)&1)^1) == 0?&w:NULL, NULL, NULL, NULL); - (*r_b_tg_sink) = u->a[0]>>32; - } - else - { - get_bubbles(bub, (u->a[u->n-1]>>32)>>1, ((u->a[u->n-1]>>32)&1)==1?&w:NULL, - ((u->a[u->n-1]>>32)&1) == 0?&w:NULL, NULL, NULL, NULL); - (*r_b_tg_sink) = u->a[u->n-1]>>32; - } - utg_sink = w^1; ///ug id - - is_t = check_bubble_tangle(NULL, ug, utg_beg, utg_sink, side_rate, total_rate, - (uint32_t)-1, (uint32_t)-1, is_vis2, stack2, res_utg, chain_flag, &extra_check); - - if(is_t == 1 && extra_check == 0) - { - for (k = utg_occ = 0; k < res_utg->a.n; k++) - { - if(IF_HOM((res_utg->a.a[k]>>1), *bub)) continue; - utg_occ += ug->u.a[res_utg->a.a[k]>>1].n; - } - - if(utg_occ*total_rate >= (v_occ+c_occ)) is_t = 0; - } - - for (k = 0; k < res_btg->a.n; k++) - { - set_b_utg_weight_flag(bub, NULL, res_btg->a.a[k], chain_flag, 1, NULL); - } - - if(is_t) - { - (*r_b_utg_beg) = btg_beg; - (*r_b_utg_sink) = btg_sink; - (*r_utg_beg) = utg_beg; - (*r_utg_sink) = utg_sink; - return is_t; - } - } - } - } - - is_vis[cur] = 1; - if(cur != (v^1)) - { - ncur = asg_arc_n(bub_ug->g, cur); - acur = asg_arc_a(bub_ug->g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if(acur[i].v == v) return 0; - if(is_vis[acur[i].v]) continue; - kv_push(uint32_t, stack->a, acur[i].v); - } - } - - - if(no_root) tan_occ += c_occ; - if((tan_occ*side_rate) >= v_occ) return 0; - no_root = 1; - } - - if(tan_occ*side_rate >= v_occ) return 0; - if(tan_occ*total_rate >= v_occ) return 0; - //let one end as a tangle - if(check_bubble_tangle(bub, bub->b_ug, v, (uint32_t)-1, side_rate, total_rate, v_occ, (uint32_t)-1, - is_vis2, stack2, res_btg, NULL, NULL) == 0) - { - return 0; - } - - for (k = 0; k < res_btg->a.n; k++) - { - set_b_utg_weight_flag(bub, NULL, res_btg->a.a[k], chain_flag, 0, NULL); - } - - btg_beg = v; - u = &(bub_ug->u.a[btg_beg>>1]); - if((btg_beg&1)==1) - { - get_bubbles(bub, (u->a[0]>>32)>>1, (((u->a[0]>>32)&1)^1)==1?&w:NULL, - (((u->a[0]>>32)&1)^1) == 0?&w:NULL, NULL, NULL, NULL); - (*r_b_tg_beg) = u->a[0]>>32; - } - else - { - get_bubbles(bub, (u->a[u->n-1]>>32)>>1, ((u->a[u->n-1]>>32)&1)==1?&w:NULL, - ((u->a[u->n-1]>>32)&1) == 0?&w:NULL, NULL, NULL, NULL); - (*r_b_tg_beg) = u->a[u->n-1]>>32; - } - utg_beg = w^1; - - is_t = check_bubble_tangle(NULL, ug, utg_beg, (uint32_t)-1, side_rate, total_rate, - (uint32_t)-1, (uint32_t)-1, is_vis2, stack2, res_utg, chain_flag, &extra_check); - - if(is_t == 1 && extra_check == 0) - { - for (k = utg_occ = 0; k < res_utg->a.n; k++) - { - if(IF_HOM((res_utg->a.a[k]>>1), *bub)) continue; - utg_occ += ug->u.a[res_utg->a.a[k]>>1].n; - } - - if(utg_occ*total_rate >= v_occ) is_t = 0; - } - - for (k = 0; k < res_btg->a.n; k++) - { - set_b_utg_weight_flag(bub, NULL, res_btg->a.a[k], chain_flag, 1, NULL); - } - - if(is_t) - { - (*r_b_utg_beg) = btg_beg; - (*r_utg_beg) = utg_beg; - } - return is_t; -} - -uint32_t get_utg_end_from_btg(bubble_type* bub, ma_ug_t *bub_ug, uint32_t v) -{ - ma_utg_t *u = &(bub_ug->u.a[v>>1]); - - if((v&1)==1) - { - return (u->a[0]>>32)^1; - } - else - { - return u->a[u->n-1]>>32; - } -} - -void drop_g_edges_by_utg(bubble_type* bub, asg_t *bsg, ma_ug_t *bub_ug, kvec_t_u32_warp* res_btg, -uint32_t b_utg_beg, uint32_t b_utg_sink) -{ - uint32_t i, k, v, root, nv; - asg_arc_t *av = NULL; - if(b_utg_beg != (uint32_t)-1) - { - root = b_utg_beg; - v = get_utg_end_from_btg(bub, bub_ug, root); - nv = asg_arc_n(bsg, v); - av = asg_arc_a(bsg, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - av[i].del = 1; - asg_arc_del(bsg, (av[i].v)^1, (av[i].ul>>32)^1, 1); - } - } - - if(b_utg_sink != (uint32_t)-1) - { - root = b_utg_sink; - v = get_utg_end_from_btg(bub, bub_ug, root); - nv = asg_arc_n(bsg, v); - av = asg_arc_a(bsg, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - av[i].del = 1; - asg_arc_del(bsg, (av[i].v)^1, (av[i].ul>>32)^1, 1); - } - } - - - if(res_btg == NULL) return; - - for (k = 0; k < res_btg->a.n; k++) - { - root = res_btg->a.a[k]; - v = get_utg_end_from_btg(bub, bub_ug, root); - nv = asg_arc_n(bsg, v); - av = asg_arc_a(bsg, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - av[i].del = 1; - asg_arc_del(bsg, (av[i].v)^1, (av[i].ul>>32)^1, 1); - } - - - root = res_btg->a.a[k]^1; - v = get_utg_end_from_btg(bub, bub_ug, root); - nv = asg_arc_n(bsg, v); - av = asg_arc_a(bsg, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - av[i].del = 1; - asg_arc_del(bsg, (av[i].v)^1, (av[i].ul>>32)^1, 1); - } - } -} - -void debug_tangle_bubble(bubble_type* bub, long long beg_idx, long long end_idx, const char* command) -{ - // long long beg_idx = (long long)bub->b_g->n_seq - bub->tangle_bub; - // long long end_idx = (long long)bub->b_g->n_seq - 1; - long long i, j, k; - ma_utg_t *u = NULL; - uint32_t beg_utg, sink_utg, *a = NULL, n, btg_left, ori_left, btg_right, ori_right, root_0, root_1; - for (i = beg_idx; i <= end_idx; i++) - { - get_bubbles(bub, i, &beg_utg, &sink_utg, &a, &n, NULL); - fprintf(stderr, "\n(%lld) %s: beg=utg%.6ul, sink=utg%.6ul, n: %u\n", i, command, (beg_utg>>1)+1, (sink_utg>>1)+1, n); - for (k = 0; k < n; k++) - { - fprintf(stderr, "mid=utg%.6ul\n", (a[k]>>1)+1); - } - - for (j = 0; j < bub->b_ug->g->n_seq; j++) - { - u = &(bub->b_ug->u.a[j]); - if(u->n) continue; - for (k = 0; k < u->n; k++) - { - if((long long)(u->a[k]>>33) != i) continue; - fprintf(stderr, "is the %lld-th bubble at btg%.6lldl\n", k, j+1); - if(k > 0) - { - btg_left = u->a[k-1]>>33; - ori_left = u->a[k-1]>>32&1; - get_bubbles(bub, btg_left, ori_left == 1?&root_0:NULL, ori_left == 0?&root_0:NULL, NULL, NULL, NULL); - fprintf(stderr, "left-utg%.6ul\n", (ori_left>>1)+1); - } - - if(k + 1 < u->n) - { - btg_right = u->a[k+1]>>33; - ori_right = (u->a[k+1]>>32&1)^1; - get_bubbles(bub, btg_right, ori_right == 1?&root_1:NULL, ori_right == 0?&root_1:NULL, NULL, NULL, NULL); - fprintf(stderr, "right-utg%.6ul\n", (ori_right>>1)+1); - } - } - } - - } -} - -uint32_t print_b_utg_occ(bubble_type* bub, uint32_t v) -{ - ma_ug_t *bub_ug = bub->b_ug; - ma_utg_t *u = NULL; - uint32_t k_i, k_j, *a = NULL, n, tan_occ = 0, beg, sink; - - - u = &(bub_ug->u.a[v]); - fprintf(stderr, "\nstart: %u-th bubble-utg-start (# bubbles: %u)\n", v, (uint32_t)u->n); - for (k_i = 0; k_i < u->n; k_i++) - { - get_bubbles(bub, u->a[k_i]>>33, &beg, &sink, &a, &n, NULL); - for (k_j = 0; k_j < n; k_j++) - { - tan_occ += bub->ug->u.a[a[k_j]>>1].n; - } - - fprintf(stderr, "bid: %lu, n: %u, beg-utg%.6dl(%u), sink-utg%.6dl(%u)\n", u->a[k_i]>>33, n, (beg>>1)+1, beg&1, (sink>>1)+1, sink&1); - } - - fprintf(stderr, "end: %u-th bubble-utg-end\n\n", v); - return tan_occ; -} - -void update_bsg(asg_t *bsg, kvec_asg_arc_t_warp* edges) -{ - asg_arc_t *t = NULL; - uint32_t k, l, i, convex, max_i; - long long max, nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - - for (k = 0; k < edges->a.n; k++) - { - t = asg_arc_pushp(bsg); - *t = edges->a.a[k]; - } - bsg->is_srt = 0; free(bsg->idx); bsg->idx = 0; - asg_cleanup(bsg); - - - - radix_sort_asg_e(edges->a.a, edges->a.a + edges->a.n); - for (k = 1, l = 0; k <= edges->a.n; ++k) - { - if (k == edges->a.n || (edges->a.a[k].ul>>32) != (edges->a.a[l].ul>>32)) - { - if(k - l > 1) - { - for (i = l, max = -1, max_i = (uint32_t)-1; i < k; i++) - { - get_unitig(bsg, NULL, edges->a.a[i].v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, - &max_stop_baseLen, 1, NULL); - if(max < nodeLen) max = nodeLen, max_i = i; - } - - ///fprintf(stderr, "k - l: %u, max_i: %u\n", k - l, max_i); - for (i = l; i < k; i++) - { - // fprintf(stderr, "i: %u, +t->ul>>32: %lu, t->v: %u\n", - // i, edges->a.a[i].ul>>32, edges->a.a[i].v); - if(i == max_i) continue; - asg_arc_del(bsg, (edges->a.a[i].ul>>32), (edges->a.a[i].v), 1); - asg_arc_del(bsg, (edges->a.a[i].v)^1, (edges->a.a[i].ul>>32)^1, 1); - ///edges->a.a[i].del = 1; - } - } - l = k; - } - } - - asg_cleanup(bsg); - -} - -void resolve_bubble_chain_tangle(ma_ug_t* ug, bubble_type* bub) -{ - // double index_time = yak_realtime(); - ma_ug_t *bub_ug = bub->b_ug; - asg_t *bsg = bub->b_g; - uint32_t k, i, v, n_vx, new_bub; - n_vx = MAX((MAX(ug->g->n_seq<<1, bub->b_ug->g->n_seq<<1)), bub->b_g->n_seq<<1); - buf_t b; memset(&b, 0, sizeof(buf_t)); - kvec_t_u32_warp stack, stack2, res_btg, res_utg; - kv_init(stack.a); kv_init(stack2.a); kv_init(res_btg.a); kv_init(res_utg.a); - kvec_asg_arc_t_warp edges; kv_init(edges.a); - uint8_t *is_vis = NULL; CALLOC(is_vis, n_vx); - uint8_t *is_vis2 = NULL; CALLOC(is_vis2, n_vx); - uint8_t *is_used = NULL; CALLOC(is_used, n_vx); - uint8_t *chain_flag = NULL; CALLOC(chain_flag, n_vx); - kvec_t(uint64_t) occ_idx; kv_init(occ_idx); uint64_t tmp, *p = NULL; - double side_rate = 2.5, total_rate = 8; - uint32_t b_utg_beg, b_utg_sink, b_tg_beg, b_tg_sink, utg_beg, utg_sink; - - - while(1) - { - occ_idx.n = 0; edges.a.n = 0; - if(n_vx < (uint32_t)(MAX((MAX(ug->g->n_seq<<1, bub->b_ug->g->n_seq<<1)), bub->b_g->n_seq<<1))) - { - n_vx = MAX((MAX(ug->g->n_seq<<1, bub->b_ug->g->n_seq<<1)), bub->b_g->n_seq<<1); - is_vis = (uint8_t*)realloc(is_vis, n_vx); - is_vis2 = (uint8_t*)realloc(is_vis2, n_vx); - is_used = (uint8_t*)realloc(is_used, n_vx); - chain_flag = (uint8_t*)realloc(chain_flag, n_vx); - } - memset(is_vis, 0, n_vx); - memset(is_vis2, 0, n_vx); - memset(is_used, 0, n_vx); - memset(chain_flag, 0, n_vx); - if(bub->num.n > 0) bub->num.n--; - new_bub = bub->b_g->n_seq; - //label all unitigs in bubble chain - for (k = 0; k < bub_ug->g->n_seq; k++) - { - kv_pushp(uint64_t, occ_idx, &p); - (*p) = get_btg_occ(bub, k); - (*p) <<= 32; (*p) += k; - set_b_utg_weight_flag(bub, NULL, k<<1, chain_flag, 1, NULL); - } - radix_sort_hc64(occ_idx.a, occ_idx.a + occ_idx.n); - for (k = 0; k < occ_idx.n>>1; ++k) - { - tmp = occ_idx.a[k]; - occ_idx.a[k] = occ_idx.a[occ_idx.n - k - 1]; - occ_idx.a[occ_idx.n - k - 1] = tmp; - } - - for (k = 0; k < bub_ug->g->n_seq; k++)///start from the longest chain - { - v = ((uint32_t)(occ_idx.a[k]))<<1; - if(is_used[v] == 0 && asg_arc_n(bub_ug->g, v) > 0) - { - if(find_bubble_tangle(bub, ug, is_vis, is_vis2, v, side_rate, total_rate, &stack, &stack2, - &res_btg, &res_utg, chain_flag, &b_utg_beg, &b_utg_sink, &b_tg_beg, &b_tg_sink, - &utg_beg, &utg_sink)) - { - if(utg_beg != (uint32_t)-1 && (!IF_HOM(utg_beg>>1, *bub))) - { - kv_push(uint32_t, res_utg.a, utg_beg); - } - if(utg_sink != (uint32_t)-1 && (!IF_HOM(utg_sink>>1, *bub))) - { - kv_push(uint32_t, res_utg.a, utg_sink); - } - - for (i = 0; i < res_btg.a.n; i++) - { - is_used[res_btg.a.a[i]] = 1; - is_used[res_btg.a.a[i]^1] = 1; - } - if(b_utg_beg != (uint32_t)-1) is_used[b_utg_beg] = 1; - if(b_utg_sink != (uint32_t)-1) is_used[b_utg_sink] = 1; - if(b_tg_beg != (uint32_t)-1) b_tg_beg>>=1; - if(b_tg_sink != (uint32_t)-1) b_tg_sink>>=1; - update_bubble_graph(&res_utg, utg_beg, b_tg_beg, utg_sink, b_tg_sink, - bub, &edges, bsg, NULL, NULL, ug, NULL, 0); - drop_g_edges_by_utg(bub, bsg, bub_ug, &res_btg, b_utg_beg, b_utg_sink); - } - } - - - v ^= 1; - if(is_used[v] == 0 && asg_arc_n(bub_ug->g, v) > 0) - { - - if(find_bubble_tangle(bub, ug, is_vis, is_vis2, v, side_rate, total_rate, &stack, &stack2, - &res_btg, &res_utg, chain_flag, &b_utg_beg, &b_utg_sink, &b_tg_beg, &b_tg_sink, - &utg_beg, &utg_sink)) - { - if(utg_beg != (uint32_t)-1 && (!IF_HOM(utg_beg>>1, *bub))) - { - kv_push(uint32_t, res_utg.a, utg_beg); - } - if(utg_sink != (uint32_t)-1 && (!IF_HOM(utg_sink>>1, *bub))) - { - kv_push(uint32_t, res_utg.a, utg_sink); - } - - for (i = 0; i < res_btg.a.n; i++) - { - is_used[res_btg.a.a[i]] = 1; - is_used[res_btg.a.a[i]^1] = 1; - } - - if(b_utg_beg != (uint32_t)-1) is_used[b_utg_beg] = 1; - if(b_utg_sink != (uint32_t)-1) is_used[b_utg_sink] = 1; - if(b_tg_beg != (uint32_t)-1) b_tg_beg>>=1; - if(b_tg_sink != (uint32_t)-1) b_tg_sink>>=1; - /*******************************for debug************************************/ - // if(utg_beg == (utg_sink^1)) - // { - // print_b_utg_occ(bub, b_utg_beg>>1); - // print_b_utg_occ(bub, b_utg_sink>>1); - // print_b_utg_occ(bub, 42); - // ///print_debug_bubble_graph(bub, ug, asm_opt.output_file_name); - // } - /*******************************for debug************************************/ - update_bubble_graph(&res_utg, utg_beg, b_tg_beg, utg_sink, b_tg_sink, bub, &edges, bsg, NULL, NULL, ug, NULL, 0); - drop_g_edges_by_utg(bub, bsg, bub_ug, &res_btg, b_utg_beg, b_utg_sink); - ///fprintf(stderr, "->>>>>>beg=btg%.6ul, sink=btg%.6ul\n", (b_utg_beg>>1)+1, (b_utg_sink>>1)+1); - } - } - } - kv_push(uint32_t, bub->num, bub->list.n); - new_bub = bub->b_g->n_seq - new_bub; - bub->tangle_bub += new_bub; - ///actually not useful, and may have bug when one bubble at multipe chains - if(new_bub) update_bub_b_s_idx(bub); - update_bsg(bsg, &edges); - - ma_ug_destroy(bub_ug); - bub_ug = ma_ug_gen(bub->b_g); - bub->b_ug = bub_ug; - ///fprintf(stderr, "new_bub: %u, bub->tangle_bub: %lu\n", new_bub, bub->tangle_bub); - if(new_bub == 0) break; - } - - kv_destroy(bub->chain_weight); - ma_utg_t *u = NULL; - bub_ug = bub->b_ug; - kv_malloc(bub->chain_weight, bub_ug->u.n); bub->chain_weight.n = bub_ug->u.n; - for (i = 0; i < bub_ug->u.n; i++) - { - u = &(bub_ug->u.a[i]); - bub->chain_weight.a[i].id = i; - // if(u->n <= 1) ///not a chain - // { - // bub->chain_weight.a[i].b_occ = bub->chain_weight.a[i].g_occ = 0; - // bub->chain_weight.a[i].del = 1; - // } - // else - { - bub->chain_weight.a[i].del = 0; - calculate_chain_weight(u, bub, ug, &(bub->chain_weight.a[i])); - } - } - qsort(bub->chain_weight.a, bub->chain_weight.n, sizeof(chain_w_type), cmp_chain_weight); - - ///debug_tangle_bubble(bub); - - free(is_vis); free(is_vis2); free(is_used); free(chain_flag); free(b.b.a); - kv_destroy(occ_idx); kv_destroy(stack.a); kv_destroy(stack2.a); - kv_destroy(res_btg.a); kv_destroy(res_utg.a); kv_destroy(edges.a); - - ///print_debug_bubble_graph(bub, ug, asm_opt.output_file_name); - // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); -} - -void update_bubble_chain(ma_ug_t* ug, bubble_type* bub, uint32_t is_middle, uint32_t is_end) -{ - // double index_time = yak_realtime(); - if(bub->b_ug) ma_ug_destroy(bub->b_ug); - if(bub->chain_weight.a) kv_destroy(bub->chain_weight); - kvec_t_u32_warp broken; - kv_init(broken.a); - kvec_asg_arc_t_warp edges; - kv_init(edges.a); - ma_utg_t *u = NULL; - asg_arc_t *t = NULL; - asg_t *sg = ug->g; - pdq pq; - init_pdq(&pq, sg->n_seq<<1); - asg_t *bsg = bub->b_g; - ma_ug_t *bub_ug = NULL; - bub_ug = ma_ug_gen(bub->b_g); - uint32_t i, j, k_i, rId_0, ori_0, root_0, rId_1, ori_1, root_1, n_vtx = sg->n_seq<<1, new_bub; - uint32_t *pre = NULL; MALLOC(pre, n_vtx); - uint8_t* vis_flag = NULL; MALLOC(vis_flag, ug->g->n_seq*2); - kvec_t_u32_warp stack; kv_init(stack.a); - ///chain_w_type x; - ///uint64_t end_thres; - - uint8_t *bsg_idx = NULL; CALLOC(bsg_idx, n_vtx>>1); - for (i = 0; i < bub_ug->u.n; i++)///label all unitigs within the bubble chains - { - u = &(bub_ug->u.a[i]);///a bubble chain - if(u->n == 0) continue; - for (k_i = 0; k_i < u->n; k_i++) - { - uint32_t *a, n; - get_bubbles(bub, u->a[k_i]>>33, &root_0, &root_1, &a, &n, NULL); - for (j = 0; j < n; j++) - { - bsg_idx[a[j]>>1] = 1; - } - bsg_idx[root_0>>1] = 1; - bsg_idx[root_1>>1] = 1; - } - } - - if(bub->num.n > 0) bub->num.n--; - new_bub = bub->b_g->n_seq; - for (i = 0; i < bub_ug->u.n; i++) - { - u = &(bub_ug->u.a[i]);///bubble chain - if(u->n == 0) continue; - ///end_thres = calculate_chain_weight(u, bub, ug, &x); - if(is_middle) - { - for (k_i = 0; k_i < u->n; k_i++) - { - if(k_i+1 >= u->n) continue; - ///note: must igore .del here, since bsg might be changed - t = &(arc_first(bsg, u->a[k_i]>>32)); - if(t->el == 1) continue;///if a[k_i] and a[k_i+1] are directly connected without any tangle involoved - - rId_0 = u->a[k_i]>>33; - ori_0 = u->a[k_i]>>32&1; - get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); - - rId_1 = u->a[k_i+1]>>33; - ori_1 = (u->a[k_i+1]>>32&1)^1; - get_bubbles(bub, rId_1, ori_1 == 1?&root_1:NULL, ori_1 == 0?&root_1:NULL, NULL, NULL, NULL); - - broken.a.n = 0;///just collect all nodes between root_0 and root_1 - get_related_bub_nodes(&broken, bub, &pq, sg, pre, root_0, root_1, NULL); - get_related_bub_nodes(&broken, bub, &pq, sg, pre, root_1, root_0, NULL); - ///no need to cut the edge, we still have chance to flip by chain - if(double_check_broken_bubble(ug->g, &broken, root_0^1, root_1^1, vis_flag, - ug->g->n_seq*2, &stack, NULL, NULL/**bsg, t**/) == 0) - { - continue; - } - if(!IF_HOM(root_0>>1, *bub)) kv_push(uint32_t, broken.a, root_0); - if(!IF_HOM(root_1>>1, *bub)) kv_push(uint32_t, broken.a, root_1); - if(broken.a.n > 0) - { - update_bubble_graph(&broken, root_0^1, rId_0, root_1^1, rId_1, bub, &edges, bsg, t, bsg_idx, ug, NULL, 1); - } - } - } - - - if(is_end) - { - if(u->n >0 && arc_cnt(bub_ug->g, (i<<1)+1) == 0) - { - rId_0 = u->a[0]>>33; - ori_0 = (u->a[0]>>32&1)^1; - get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); - broken.a.n = 0; - get_related_bub_nodes(&broken, bub, &pq, sg, pre, root_0, (uint32_t)-1, NULL); - - if(double_check_broken_bubble(ug->g, &broken, root_0^1, (uint32_t)-1, vis_flag, - ug->g->n_seq*2, &stack, NULL, NULL)) - { - if(!IF_HOM(root_0>>1, *bub)) kv_push(uint32_t, broken.a, root_0); - if(broken.a.n > 0) - { - ///fprintf(stderr, "root_0: utg%.6ul, broken.a.n: %u\n", (root_0>>1)+1, (uint32_t)broken.a.n); - update_bubble_graph(&broken, root_0^1, rId_0, (uint32_t)-1, (uint32_t)-1, bub, &edges, bsg, NULL, bsg_idx, ug, NULL, 0); - } - } - } - - - if(u->n >0 && arc_cnt(bub_ug->g, i<<1) == 0) - { - rId_1 = u->a[u->n-1]>>33; - ori_1 = u->a[u->n-1]>>32&1; - get_bubbles(bub, rId_1, ori_1 == 1?&root_1:NULL, ori_1 == 0?&root_1:NULL, NULL, NULL, NULL); - broken.a.n = 0; - get_related_bub_nodes(&broken, bub, &pq, sg, pre, root_1, (uint32_t)-1, bsg_idx); - - if(double_check_broken_bubble(ug->g, &broken, root_1^1, (uint32_t)-1, vis_flag, - ug->g->n_seq*2, &stack, NULL, NULL)) - { - if(!IF_HOM(root_1>>1, *bub)) kv_push(uint32_t, broken.a, root_1); - if(broken.a.n > 0) - { - ///fprintf(stderr, "root_1: utg%.6ul, broken.a.n: %u\n", (root_1>>1)+1, (uint32_t)broken.a.n); - update_bubble_graph(&broken, (uint32_t)-1, (uint32_t)-1, root_1^1, rId_1, bub, &edges, bsg, NULL, bsg_idx, ug, NULL, 0); - } - - } - } - } - } - kv_push(uint32_t, bub->num, bub->list.n); - new_bub = bub->b_g->n_seq - new_bub; - if(is_end) bub->b_end_bub += new_bub; - ///actually not useful, and may have bug when one bubble at multipe chains - if(new_bub) update_bub_b_s_idx(bub); - - - for (i = 0; i < edges.a.n; i++) - { - t = asg_arc_pushp(bsg); - *t = edges.a.a[i]; - } - - bsg->is_srt = 0; free(bsg->idx); bsg->idx = 0; - asg_cleanup(bsg); - ma_ug_destroy(bub_ug); - destory_pdq(&pq); - free(pre); - kv_destroy(broken.a); - kv_destroy(edges.a); - free(bsg_idx); - kv_destroy(stack.a); - free(vis_flag); - - bub->b_ug = ma_ug_gen(bub->b_g); - bub_ug = bub->b_ug; - kv_malloc(bub->chain_weight, bub_ug->u.n); bub->chain_weight.n = bub_ug->u.n; - for (i = 0; i < bub_ug->u.n; i++) - { - u = &(bub_ug->u.a[i]); - bub->chain_weight.a[i].id = i; - // if(u->n <= 1) ///not a chain - // { - // bub->chain_weight.a[i].b_occ = bub->chain_weight.a[i].g_occ = 0; - // bub->chain_weight.a[i].del = 1; - // } - // else - { - bub->chain_weight.a[i].del = 0; - calculate_chain_weight(u, bub, ug, &(bub->chain_weight.a[i])); - } - } - - qsort(bub->chain_weight.a, bub->chain_weight.n, sizeof(chain_w_type), cmp_chain_weight); - - - - /** - uint32_t d_v, d_u, v; - for (i = 0; i < bsg->n_arc; i++) - { - d_v = (uint32_t)(bsg->arc[i].ul>>32); - d_u = bsg->arc[i].v; - for (v = 0; v < bsg->n_arc; v++) - { - if(((bsg->arc[v].ul>>32) == (d_u^1)) && (bsg->arc[v].v == (d_v^1))) break; - } - - if(v == bsg->n_arc) - { - fprintf(stderr, "hahaha, el: %u, ul>>33: %lu, ul&1: %lu, v>>1: %u, v&1: %u\n", - bsg->arc[i].el, bsg->arc[i].ul>>33, (bsg->arc[i].ul>>32)&1, bsg->arc[i].v>>1, bsg->arc[i].v&1); - } - // else - // { - // fprintf(stderr, "hehehe, el: %u, ul>>33: %lu, ul&1: %lu, v>>1: %u, v&1: %u\n", - // bsg->arc[i].el, bsg->arc[i].ul>>33, (bsg->arc[i].ul>>32)&1, bsg->arc[i].v>>1, bsg->arc[i].v&1); - // } - } - - asg_arc_t *av = NULL, *au = NULL; - uint32_t nv, nu; - for (v = 0; v < (uint32_t)(bsg->n_seq<<1); v++) - { - av = asg_arc_a(bsg, v); - nv = asg_arc_n(bsg, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - - au = asg_arc_a(bsg, av[i].v^1); - nu = asg_arc_n(bsg, av[i].v^1); - for (k_i = 0; k_i < nu; k_i++) - { - if(au[k_i].del) continue; - if(au[k_i].v == (v^1)) break; - } - if(k_i == nu) fprintf(stderr, "hahaha: v: %u, u: %u\n", v, av[i].v); - } - } - **/ - // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); -} - -void set_b_utg_weight_flag(bubble_type* bub, buf_t* b, uint32_t v, uint8_t* vis_flag, uint32_t flag, uint32_t* occ) -{ - ma_ug_t *bub_ug = bub->b_ug; - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - ma_utg_t *u = NULL; - uint32_t convex, k, k_i, k_j, *a, n, beg, sink; - if(b) - { - b->b.n = 0; - get_unitig(bub_ug->g, NULL, v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, - &max_stop_baseLen, 1, b); - } - - if(occ) (*occ) = 0; - for (k = 0; k < (b?b->b.n:1); k++) - { - u = &(bub_ug->u.a[b?(b->b.a[k]>>1):(v>>1)]); - if(u->n == 0) continue; - for (k_i = 0; k_i < u->n; k_i++) - { - get_bubbles(bub, u->a[k_i]>>33, &beg, &sink, &a, &n, NULL); - - for (k_j = 0; k_j < n; k_j++) - { - if(vis_flag) vis_flag[a[k_j]>>1] = flag; - if(occ) (*occ) += bub->ug->u.a[a[k_j]>>1].n; - } - if(beg != (uint32_t)-1 && vis_flag) vis_flag[beg>>1] = flag; - if(sink != (uint32_t)-1 && vis_flag) vis_flag[sink>>1] = flag; - } - } -} - -void set_b_utg_weight_flag_xor(bubble_type* bub, ma_ug_t *bub_ug, buf_t* b, uint32_t v, uint8_t* vis_flag, uint32_t flag, uint32_t* occ) -{ - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - ma_utg_t *u = NULL; - uint32_t convex, k, k_i, k_j, *a, n, beg, sink; - if(b) - { - b->b.n = 0; - get_unitig(bub_ug->g, NULL, v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, - &max_stop_baseLen, 1, b); - } - - if(occ) (*occ) = 0; - for (k = 0; k < (b?b->b.n:1); k++) - { - u = &(bub_ug->u.a[b?(b->b.a[k]>>1):(v>>1)]); - if(u->n == 0) continue; - for (k_i = 0; k_i < u->n; k_i++) - { - get_bubbles(bub, u->a[k_i]>>33, &beg, &sink, &a, &n, NULL); - - for (k_j = 0; k_j < n; k_j++) - { - if(vis_flag) vis_flag[a[k_j]>>1] ^= flag; - if(occ) (*occ) += bub->ug->u.a[a[k_j]>>1].n; - } - if(beg != (uint32_t)-1 && vis_flag) vis_flag[beg>>1] ^= flag; - if(sink != (uint32_t)-1 && vis_flag) vis_flag[sink>>1] ^= flag; - } - } -} - -double dfs_weight(uint32_t v, uint8_t* vis_flag, uint8_t* is_vis, hc_links* link, -kvec_t_u32_warp* stack, kvec_t_u32_warp* result, uint32_t e_flag, uint32_t ava_flag, -uint32_t* link_occ) -{ - uint32_t cur, i, next = (uint32_t)-1; - stack->a.n = 0; - kv_push(uint32_t, stack->a, v); - double w = 0; - if(link_occ) (*link_occ) = 0; - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - if(is_vis[cur]) continue; - is_vis[cur] = 1; - if(cur!=v && vis_flag[cur] != ava_flag) continue; - for (i = 0; i < link->a.a[cur].e.n; i++) - { - if(link->a.a[cur].e.a[i].del) continue; - next = link->a.a[cur].e.a[i].uID; - ///if(vis_flag[next] == e_flag) - if(vis_flag[next]&e_flag) - { - w += link->a.a[cur].e.a[i].weight; - if(link_occ) (*link_occ) += link->a.a[cur].e.a[i].occ; - continue; - } - if(is_vis[next]) continue; - if(vis_flag[next] != ava_flag) continue; - kv_push(uint32_t, stack->a, next); - } - } - return w; -} - -void if_conflict_utg(uint32_t root, uint32_t* aim_0, uint32_t* aim_1, ma_ug_t* ug, uint8_t* vis_flag, -uint8_t* is_vis_2, uint32_t ava_flag, kvec_t_u32_warp* stack) -{ - uint32_t n_vx = ug->g->n_seq<<1, k, cur, ncur; - asg_arc_t *acur = NULL; - memset(is_vis_2, 0, n_vx); - - stack->a.n = 0; - kv_push(uint32_t, stack->a, root); - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - if(is_vis_2[cur]) continue; - is_vis_2[cur] = 1; - - ncur = asg_arc_n(ug->g, cur); - acur = asg_arc_a(ug->g, cur); - for (k = 0; k < ncur; k++) - { - if(acur[k].del) continue; - if(is_vis_2[acur[k].v]) continue; - if(vis_flag[acur[k].v>>1] != 0 && vis_flag[acur[k].v>>1] != ava_flag) - { - if(aim_0 && (acur[k].v>>1) == (*aim_0)) continue; - if(aim_1 && (acur[k].v>>1) == (*aim_1)) continue; - break; - } - kv_push(uint32_t, stack->a, acur[k].v); - } - - if(k < ncur) return; - } - - for (k = 0; k < n_vx; k++) - { - if(is_vis_2[k] && vis_flag[k>>1] == 0) - { - ///fprintf(stderr, "******************k=utg%.6ul, vis_flag: %u\n", (k>>1)+1, vis_flag[k>>1]); - vis_flag[k>>1] = ava_flag; - } - - } -} - -double get_chain_weight(bubble_type* bub, ma_ug_t *bub_ug, buf_t* b, uint32_t v, uint32_t convex_source, hc_links* link, -uint8_t* vis_flag, uint8_t* is_vis, ma_ug_t* ug, kvec_t_u32_warp* stack, kvec_t_u32_warp* result, -uint32_t e_flag, uint32_t ava_flag, kvec_t_u32_warp* res_utg, uint32_t* link_occ) -{ - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - ma_utg_t *u = NULL; - uint32_t convex, k, k_i, k_j, *a, n, beg, sink, uID, root, cur, ncur, n_vx = ug->g->n_seq<<1, occ; - asg_arc_t *acur = NULL; - double w = 0; - b->b.n = 0; - get_unitig(bub_ug->g, NULL, v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, - &max_stop_baseLen, 1, b); - memset(is_vis, 0, n_vx); - - for (k = 0; k < b->b.n; k++) - { - u = &(bub_ug->u.a[b->b.a[k]>>1]); - if(u->n == 0) continue; - - for (k_i = 0; k_i < u->n; k_i++) - { - get_bubbles(bub, u->a[k_i]>>33, &beg, &sink, &a, &n, NULL); - for(k_j = 0; k_j < n; k_j++) is_vis[a[k_j]] = is_vis[a[k_j]^1] = 1; - if(beg != (uint32_t)-1) is_vis[beg] = is_vis[beg^1] = 1; - if(sink != (uint32_t)-1) is_vis[sink] = is_vis[sink^1] = 1; - } - } - - u = &(bub_ug->u.a[v>>1]); - if((v&1)==0) - { - get_bubbles(bub, (u->a[0]>>32)>>1, (((u->a[0]>>32)&1)^1)==1?&root:NULL, - (((u->a[0]>>32)&1)^1) == 0?&root:NULL, NULL, NULL, NULL); - } - else - { - get_bubbles(bub, (u->a[u->n-1]>>32)>>1, ((u->a[u->n-1]>>32)&1)==1?&root:NULL, - ((u->a[u->n-1]>>32)&1) == 0?&root:NULL, NULL, NULL, NULL); - } - - root ^= 1; - ///fprintf(stderr, "root=utg%.6dl\n", (root>>1)+1); - is_vis[root] = 0; - stack->a.n = 0; - kv_push(uint32_t, stack->a, root); - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - if(is_vis[cur]) continue; - is_vis[cur] = 1; - if(vis_flag[cur>>1] == 0) vis_flag[cur>>1] = ava_flag; - - ncur = asg_arc_n(ug->g, cur); - acur = asg_arc_a(ug->g, cur); - for (k = 0; k < ncur; k++) - { - if(acur[k].del) continue; - if(is_vis[acur[k].v]) continue; - if(vis_flag[acur[k].v>>1] != 0 && vis_flag[acur[k].v>>1] != ava_flag) continue; - kv_push(uint32_t, stack->a, acur[k].v); - } - } - - - - uint32_t aim_0, aim_1, root_source; - aim_0 = root>>1; - u = &(bub_ug->u.a[convex_source>>1]); - if((convex_source&1)==1) - { - get_bubbles(bub, (u->a[0]>>32)>>1, (((u->a[0]>>32)&1)^1)==1?&root_source:NULL, - (((u->a[0]>>32)&1)^1) == 0?&root_source:NULL, NULL, NULL, NULL); - } - else - { - get_bubbles(bub, (u->a[u->n-1]>>32)>>1, ((u->a[u->n-1]>>32)&1)==1?&root_source:NULL, - ((u->a[u->n-1]>>32)&1) == 0?&root_source:NULL, NULL, NULL, NULL); - } - root_source ^= 1; - aim_1 = root_source>>1; - - ///fprintf(stderr, "aim_0=utg%.6ul, aim_1=utg%.6ul\n", aim_0+1, aim_1+1); - - cur = root_source; - ncur = asg_arc_n(ug->g, cur); - acur = asg_arc_a(ug->g, cur); - for (k_i = 0; k_i < ncur; k_i++) - { - if(acur[k_i].del) continue; - if(vis_flag[acur[k_i].v>>1] != 0) continue; - if_conflict_utg(acur[k_i].v, &aim_0, &aim_1, ug, vis_flag, is_vis, ava_flag, stack); - } - - - for (k = 0; k < ug->g->n_seq; k++) - { - if(vis_flag[k] == ava_flag) - { - cur = k<<1; - ncur = asg_arc_n(ug->g, cur); - acur = asg_arc_a(ug->g, cur); - for (k_i = 0; k_i < ncur; k_i++) - { - if(acur[k_i].del) continue; - if(vis_flag[acur[k_i].v>>1] != 0) continue; - if_conflict_utg(acur[k_i].v, &aim_0, &aim_1, ug, vis_flag, is_vis, ava_flag, stack); - } - - - - cur = (k<<1)+1; - ncur = asg_arc_n(ug->g, cur); - acur = asg_arc_a(ug->g, cur); - for (k_i = 0; k_i < ncur; k_i++) - { - if(acur[k_i].del) continue; - if(vis_flag[acur[k_i].v>>1] != 0) continue; - if_conflict_utg(acur[k_i].v, &aim_0, &aim_1, ug, vis_flag, is_vis, ava_flag, stack); - } - } - } - - - - - - - - memset(is_vis, 0, n_vx); - if(link_occ) (*link_occ) = 0; - for (k = result->a.n = 0, w = 0; k < b->b.n; k++) - { - u = &(bub_ug->u.a[b->b.a[k]>>1]); - if(u->n == 0) continue; - for (k_i = 0; k_i < u->n; k_i++) - { - get_bubbles(bub, u->a[k_i]>>33, NULL, NULL, &a, &n, NULL); - - for (k_j = 0; k_j < n; k_j++) - { - uID = a[k_j]>>1; - w += dfs_weight(uID, vis_flag, is_vis, link, stack, result, e_flag, ava_flag, &occ); - if(link_occ) (*link_occ) += occ; - } - } - } - - - for (k = 0; k < ug->g->n_seq; k++) - { - if(vis_flag[k] == ava_flag) - { - vis_flag[k] = 0; - if(res_utg && (!IF_HOM(k, *bub))) - { - kv_push(uint32_t, res_utg->a, k<<1); - } - } - } - - - return w; -} - -int double_check_bub_branch(asg_arc_t *t, ma_ug_t *bs_ug, double *e_w, uint32_t *e_occ, double cutoff, uint32_t max_w_occ) -{ - uint32_t v = t->v^1, w = (t->ul>>32)^1, i, nv, rv, max_i, w_i, *a_occ = NULL; - asg_arc_t *av = NULL; - double *aw = NULL, max_w = cutoff - 1, w_w = 1; - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - aw = (&e_w[bs_ug->g->idx[v]>>32]); - a_occ = (&e_occ[bs_ug->g->idx[v]>>32]); - - if(nv <= 1) return 1; - - for (i = rv = 0, max_i = w_i = (uint32_t)-1; i < nv; i++) - { - if(av[i].del) continue; - rv++; - if(av[i].v == w) - { - w_i = i; - w_w = aw[i]; - continue; - } - if(max_i == (uint32_t)-1) - { - max_i = i; - max_w = aw[i]; - } - else if(max_w < aw[i]) - { - max_i = i; - max_w = aw[i]; - } - } - - if(rv <= 1) return 1; ///must be here - - if(max_i == (uint32_t)-1 || w_i == (uint32_t)-1) return 0; - ///if(max_w <= max_w_cutoff) return 0; //must be <= - if(a_occ[max_i] <= max_w_occ) return 0; //must be <= - - if(w_w*cutoff < max_w) return 1; - return 0; -} - -void clean_bubble_chain_by_HiC(ma_ug_t* ug, hc_links* link, bubble_type* bub) -{ - double index_time = yak_realtime(); - ma_ug_t *bs_ug = bub->b_ug; - uint32_t v, u, i, m, max_i, nv, rv, n_vx, root, flag_pri = 1, flag_aux = 2, flag_ava = 4, occ; - double w, cutoff = 2/**, max_w_cutoff = MAX(MIN(100*OFFSET_RATE_MIN_W, OFFSET_RATE_MAX_W/100), OFFSET_RATE_MIN_W)**/; - uint32_t max_w_occ = 4; - asg_arc_t *av = NULL; - n_vx = bs_ug->g->n_seq << 1; - uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq<<1); - uint8_t *is_vis = NULL; CALLOC(is_vis, ug->g->n_seq<<1); - uint8_t *is_used = NULL; CALLOC(is_used, n_vx); - uint8_t *dedup = NULL; CALLOC(dedup, ug->g->n_seq<<1); - buf_t b; memset(&b, 0, sizeof(buf_t)); - kvec_t_u32_warp stack, result, res_utg; - kv_init(stack.a); kv_init(result.a); kv_init(res_utg.a); - double *e_w = NULL; MALLOC(e_w, bs_ug->g->n_arc); - uint32_t *e_occ = NULL, *a_occ = NULL; CALLOC(e_occ, bs_ug->g->n_arc); - double *aw = NULL, max_w = 0; - kvec_asg_arc_t_warp edges; kv_init(edges.a); - ma_ug_t *back_bs_ug = copy_untig_graph(bs_ug); - - for (i = 0; i < bs_ug->g->n_arc; i++)///weight of bs_ug's edges - { - e_w[i] = -1; - } - - for (i = 0; i < bs_ug->g->n_seq; i++)///init all chain with flag_aux - { - set_b_utg_weight_flag(bub, &b, i<<1, vis, flag_aux, NULL); - } - - - for (v = 0; v < n_vx; v++) - { - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - aw = (&e_w[bs_ug->g->idx[v]>>32]); - a_occ = (&e_occ[bs_ug->g->idx[v]>>32]); - if(nv <= 1 || get_real_length(bs_ug->g, v, NULL) <= 1) continue; - set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); - - ///fprintf(stderr, "\n******pri>btg%.6dl\n", (v>>1)+1); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - //fprintf(stderr, "aux>btg%.6dl\n", (av[i].v>>1)+1); - w = get_chain_weight(bub, bs_ug, &b, av[i].v, v, link, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, NULL, &occ); - ///fprintf(stderr, "aux>btg%.6dl, w: %f\n", (av[i].v>>1)+1, w); - aw[i] = w; - a_occ[i] = occ; - } - - set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); - } - - - for (v = 0; v < n_vx; v++) - { - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - aw = (&e_w[bs_ug->g->idx[v]>>32]); - a_occ = (&e_occ[bs_ug->g->idx[v]>>32]); - if(nv <= 1 || get_real_length(bs_ug->g, v, NULL) <= 1) continue; - - for (i = rv = 0, max_i = (uint32_t)-1; i < nv; i++) - { - if(av[i].del) continue; - if(max_i == (uint32_t)-1) - { - max_i = i; - max_w = aw[i]; - } - else if(max_w < aw[i]) - { - max_i = i; - max_w = aw[i]; - } - rv++; - } - - if(max_i == (uint32_t)-1) continue; - ///if(max_w <= max_w_cutoff) continue; //must be <= - if(a_occ[max_i] <= max_w_occ) continue; //must be <= - if(rv < 2) continue; - - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - if(i == max_i) continue; - ///if((av[i].v>>1) == (v>>1) && aw[i] <= max_w_cutoff) continue; ///might be not reasonable - if((av[i].v>>1) == (v>>1) && a_occ[i] <= max_w_occ) continue; ///might be not reasonable - if(aw[i]*cutoff < max_w && double_check_bub_branch(&av[i], bs_ug, e_w, e_occ, cutoff, max_w_occ)) - { - av[i].del = 1; asg_arc_del(bs_ug->g, (av[i].v)^1, (av[i].ul>>32)^1, 1); - } - } - } - - uint32_t rId_0, ori_0, rId_1, ori_1, root_0, root_1, new_bub; - if(bub->num.n > 0) bub->num.n--; - new_bub = bub->b_g->n_seq; - - for (v = 0; v < n_vx; v++) - { - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - rv = get_real_length(bs_ug->g, v, NULL); - if(nv == rv) continue; - if(rv != 1 || nv <= 1) continue; - get_real_length(bs_ug->g, v, &u); - u ^= 1; - if(get_real_length(bs_ug->g, u, NULL) != 1) continue; - drop_g_edges_by_utg(bub, bub->b_g, bs_ug, NULL, v, u); - if(is_used[v] || is_used[u]) continue; - - is_used[v] = is_used[u] = 1; - root = get_utg_end_from_btg(bub, bs_ug, v); - rId_0 = root>>1; - ori_0 = root&1; - get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); - - root = get_utg_end_from_btg(bub, bs_ug, u); - rId_1 = root>>1; - ori_1 = root&1; - get_bubbles(bub, rId_1, ori_1 == 1?&root_1:NULL, ori_1 == 0?&root_1:NULL, NULL, NULL, NULL); - - res_utg.a.n = 0; - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); - get_chain_weight(bub, back_bs_ug, &b, u^1, v, link, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); - for (i = 0; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 1; - - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); - get_chain_weight(bub, back_bs_ug, &b, v^1, u, link, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); - for (; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 2; - - - for (i = m = 0; i < res_utg.a.n; i++) - { - if(dedup[res_utg.a.a[i]>>1] == 3) - { - res_utg.a.a[m] = res_utg.a.a[i]; - m++; - } - dedup[res_utg.a.a[i]>>1] = 0; - } - res_utg.a.n = m; - - // fprintf(stderr, "res_utg.a.n: %u, m: %u, beg-utg%.6ul, sink-utg%.6ul\n", - // res_utg.a.n, m, (root_0>>1)+1, (root_1>>1)+1); - - if(!IF_HOM(root_0>>1, *bub)) kv_push(uint32_t, res_utg.a, root_0); - if(!IF_HOM(root_1>>1, *bub)) kv_push(uint32_t, res_utg.a, root_1); - - update_bubble_graph(&res_utg, root_0^1, rId_0, root_1^1, rId_1, bub, &edges, bub->b_g, NULL, NULL, ug, NULL, 0); - - ///fprintf(stderr, "\n******src-btg%.6ul------>dest-btg%.6ul\n", (v>>1)+1, (u>>1)+1); - } - - kv_push(uint32_t, bub->num, bub->list.n); - new_bub = bub->b_g->n_seq - new_bub; - bub->cross_bub += new_bub; - ///actually not useful, and may have bug when one bubble at multipe chains - if(new_bub) update_bub_b_s_idx(bub); - - ///debug_tangle_bubble(bub, bub->b_g->n_seq - bub->cross_bub, bub->b_g->n_seq - 1, "Cross-tangle"); - update_bsg(bub->b_g, &edges); - - ma_ug_destroy(bs_ug); - bs_ug = ma_ug_gen(bub->b_g); - bub->b_ug = bs_ug; - kv_destroy(bub->chain_weight); - ma_utg_t *u_x = NULL; - bs_ug = bub->b_ug; - kv_malloc(bub->chain_weight, bs_ug->u.n); bub->chain_weight.n = bs_ug->u.n; - for (i = 0; i < bs_ug->u.n; i++) - { - u_x = &(bs_ug->u.a[i]); - bub->chain_weight.a[i].id = i; - // if(u->n <= 1) ///not a chain - // { - // bub->chain_weight.a[i].b_occ = bub->chain_weight.a[i].g_occ = 0; - // bub->chain_weight.a[i].del = 1; - // } - // else - { - bub->chain_weight.a[i].del = 0; - calculate_chain_weight(u_x, bub, ug, &(bub->chain_weight.a[i])); - } - } - qsort(bub->chain_weight.a, bub->chain_weight.n, sizeof(chain_w_type), cmp_chain_weight); - - - - free(vis); free(is_vis); free(is_used); free(dedup); free(b.b.a); free(e_w); free(e_occ); - kv_destroy(stack.a); kv_destroy(result.a); kv_destroy(res_utg.a); kv_destroy(edges.a); - ma_ug_destroy(back_bs_ug); - fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); -} - -void append_boundary_chain(ma_ug_t* ug, hc_links* link, bubble_type* bub) -{ - double index_time = yak_realtime(); - ma_ug_t *bs_ug = bub->b_ug; - uint32_t v, u, i, k, beg_idx, m, nv, n_vx, flag_pri = 1, flag_aux = 2, flag_ava = 4; - uint32_t root, rId_0, ori_0, root_0, new_bub; - asg_arc_t *av = NULL; - n_vx = bs_ug->g->n_seq << 1; - uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq<<1); - uint8_t *is_vis = NULL; CALLOC(is_vis, ug->g->n_seq<<1); - uint8_t *is_used = NULL; CALLOC(is_used, n_vx); - uint8_t *dedup = NULL; CALLOC(dedup, ug->g->n_seq<<1); - buf_t b; memset(&b, 0, sizeof(buf_t)); - kvec_t_u32_warp stack, result, res_utg; - kv_init(stack.a); kv_init(result.a); kv_init(res_utg.a); - kvec_asg_arc_t_warp edges; kv_init(edges.a); - - for (i = 0; i < bs_ug->g->n_seq; i++) - { - set_b_utg_weight_flag(bub, &b, i<<1, vis, flag_aux, NULL); - } - - if(bub->num.n > 0) bub->num.n--; - new_bub = bub->b_g->n_seq; - for (v = 0; v < n_vx; v++) - { - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - if(nv == 0 || get_real_length(bs_ug->g, v, NULL) == 0) continue; - res_utg.a.n = 0; - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - u = av[i].v^1; - /** - beg_idx = res_utg.a.n; - set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); - get_chain_weight(bub, bs_ug, &b, u^1, v, link, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); - set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); - for (k = m = beg_idx; k < res_utg.a.n; k++) - { - if(dedup[res_utg.a.a[k]>>1] != 0) continue; - dedup[res_utg.a.a[k]>>1] = 1; - res_utg.a.a[m] = res_utg.a.a[k]; - m++; - } - res_utg.a.n = m; - **/ - beg_idx = res_utg.a.n; - set_b_utg_weight_flag_xor(bub, bs_ug, &b, u^1, vis, flag_pri, NULL); - get_chain_weight(bub, bs_ug, &b, v^1, u, link, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); - set_b_utg_weight_flag_xor(bub, bs_ug, &b, u^1, vis, flag_pri, NULL); - for (k = m = beg_idx; k < res_utg.a.n; k++) - { - if(dedup[res_utg.a.a[k]>>1] != 0) continue; - dedup[res_utg.a.a[k]>>1] = 1; - res_utg.a.a[m] = res_utg.a.a[k]; - m++; - } - res_utg.a.n = m; - } - - for (k = 0; k < res_utg.a.n; k++) dedup[res_utg.a.a[k]>>1] = 0; - /*******************************for debug************************************/ - // for (i = 0; i < res_utg.a.n; i++) - // { - // for (k = 0; k < res_utg.a.n; k++) - // { - // if(k == i) continue; - // if((res_utg.a.a[i]>>1) == (res_utg.a.a[k]>>1)) fprintf(stderr, "ERROR\n"); - // } - // } - /*******************************for debug************************************/ - - root = get_utg_end_from_btg(bub, bs_ug, v); - rId_0 = root>>1; - ori_0 = root&1; - get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); - - if(root_0 != (uint32_t)-1 && (!IF_HOM(root_0>>1, *bub))) kv_push(uint32_t, res_utg.a, root_0); - - if(v&1) - { - update_bubble_graph(&res_utg, root_0^1, rId_0, (uint32_t)-1, (uint32_t)-1, bub, &edges, bub->b_g, NULL, NULL, ug, NULL, 0); - } - else - { - update_bubble_graph(&res_utg, (uint32_t)-1, (uint32_t)-1, root_0^1, rId_0, bub, &edges, bub->b_g, NULL, NULL, ug, NULL, 0); - } - } - kv_push(uint32_t, bub->num, bub->list.n); - new_bub = bub->b_g->n_seq - new_bub; - bub->mess_bub += new_bub; - ///actually not useful, and may have bug when one bubble at multipe chains - if(new_bub) update_bub_b_s_idx(bub); - - - for (v = 0; v < n_vx; v++) - { - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - if(nv == 0 || get_real_length(bs_ug->g, v, NULL) == 0) continue; - drop_g_edges_by_utg(bub, bub->b_g, bs_ug, NULL, v, (uint32_t)-1); - } - - update_bsg(bub->b_g, &edges); - - ma_ug_destroy(bs_ug); - bs_ug = ma_ug_gen(bub->b_g); - bub->b_ug = bs_ug; - kv_destroy(bub->chain_weight); - ma_utg_t *u_x = NULL; - bs_ug = bub->b_ug; - kv_malloc(bub->chain_weight, bs_ug->u.n); bub->chain_weight.n = bs_ug->u.n; - for (i = 0; i < bs_ug->u.n; i++) - { - u_x = &(bs_ug->u.a[i]); - bub->chain_weight.a[i].id = i; - // if(u->n <= 1) ///not a chain - // { - // bub->chain_weight.a[i].b_occ = bub->chain_weight.a[i].g_occ = 0; - // bub->chain_weight.a[i].del = 1; - // } - // else - { - bub->chain_weight.a[i].del = 0; - calculate_chain_weight(u_x, bub, ug, &(bub->chain_weight.a[i])); - } - } - qsort(bub->chain_weight.a, bub->chain_weight.n, sizeof(chain_w_type), cmp_chain_weight); - - - - free(vis); free(is_vis); free(is_used); free(dedup); free(b.b.a); - kv_destroy(stack.a); kv_destroy(result.a); kv_destroy(res_utg.a); - kv_destroy(edges.a); - - - /*******************************for debug************************************/ - // for (v = 0; v < (uint32_t)(bs_ug->g->n_seq<<1); v++) - // { - // if(asg_arc_n(bs_ug->g, v) > 0) fprintf(stderr, "ERROR, btg%.6ul\n", (v>>1)+1); - // ma_utg_t *utg = &(bs_ug->u.a[v>>1]); - // for (i = 0; i < utg->n; i++) - // { - // if((utg->a[i]>>33) >= - // (bub->f_bub + bub->b_bub + bub->b_end_bub + bub->tangle_bub + bub->cross_bub)) - // { - // if(i != 0 && i != utg->n - 1) fprintf(stderr, "ERROR, btg%.6ul, i: %u\n", (v>>1)+1, i); - // } - // } - // } - /*******************************for debug************************************/ - fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); -} - -int cmp_chain_hic_w_weight(const void * a, const void * b) -{ - if((*(chain_hic_w_type*)a).w != (*(chain_hic_w_type*)b).w) - { - return (*(chain_hic_w_type*)a).w > (*(chain_hic_w_type*)b).w? -1 : 1; - } - else - { - return 0; - } -} - - -#define is_useful_bub(ID, B) (((ID)>=((B).f_bub + (B).b_bub + (B).b_end_bub + (B).tangle_bub + (B).cross_bub))\ - && ((ID)<((B).f_bub + (B).b_bub + (B).b_end_bub + (B).tangle_bub + (B).cross_bub + (B).mess_bub))) -void init_chain_hic_warp(ma_ug_t* ug, hc_links* link, bubble_type* bub, chain_hic_warp* c_w) -{ - ma_ug_t *bs_ug = bub->b_ug; - uint32_t *a = NULL, n, occ, i, k_i, k_j, k_k, uID, is_del, m, bub_mess; - double w; - ma_utg_t *u_x = NULL; - - kv_init((*c_w)); - kv_malloc((*c_w), bs_ug->u.n); - (*c_w).n = bs_ug->u.n; - (*c_w).max_bub_id = 0; - (*c_w).u_n = ug->u.n; - (*c_w).chain_idx = NULL; - MALLOC((*c_w).chain_idx, ug->u.n); - memset((*c_w).chain_idx, -1, sizeof(uint32_t)*ug->u.n); - - for (i = bub_mess = 0; i < bs_ug->u.n; i++) - { - u_x = &(bs_ug->u.a[i]); - (*c_w).a[i].id = i; - (*c_w).a[i].w = 0; - (*c_w).a[i].occ = 0; - (*c_w).a[i].u = NULL; - for (k_i = 0, w = 0, occ = 0; k_i < u_x->n; k_i++) - { - if(is_useful_bub(u_x->a[k_i]>>33, *bub)) - { - bub_mess++; - continue; - } - get_bubbles(bub, u_x->a[k_i]>>33, NULL, NULL, &a, &n, NULL); - - for (k_j = 0; k_j < n; k_j++) - { - uID = a[k_j]>>1; - occ += ug->u.a[uID].n; - for (k_k = 0; k_k < link->a.a[uID].e.n; k_k++) - { - if(link->a.a[uID].e.a[k_k].del) continue; - w += link->a.a[uID].e.a[k_k].weight; - } - } - } - (*c_w).a[i].w = w; - (*c_w).a[i].occ = occ; - } - if(bub_mess != bub->mess_bub) fprintf(stderr, "ERROR\n"); - ///fprintf(stderr, "bub_mess: %u, bub->mess_bub: %lu\n", bub_mess, bub->mess_bub); - - for (i = 0; i < bs_ug->u.n; i++) - { - u_x = &(bs_ug->u.a[i]); - for (k_i = 0; k_i < u_x->n; k_i++) - { - if(is_useful_bub(u_x->a[k_i]>>33, *bub)) - { - continue; - } - - get_bubbles(bub, u_x->a[k_i]>>33, NULL, NULL, &a, &n, NULL); - for (k_j = 0; k_j < n; k_j++) - { - uID = a[k_j]>>1; - if((*c_w).chain_idx[uID] == (uint32_t)-1) - { - (*c_w).chain_idx[uID] = i; - } - else - { - if((*c_w).a[i].occ > (*c_w).a[(*c_w).chain_idx[uID]].occ) - { - (*c_w).chain_idx[uID] = i; - } - } - } - } - } - - for (i = m = 0; i < (*c_w).n; i++) - { - u_x = &(bs_ug->u.a[(*c_w).a[i].id]); - is_del = 1; - for (k_i = 0; k_i < u_x->n; k_i++) - { - if(is_useful_bub(u_x->a[k_i]>>33, *bub)) - { - continue; - } - - get_bubbles(bub, u_x->a[k_i]>>33, NULL, NULL, &a, &n, NULL); - for (k_j = 0; k_j < n; k_j++) - { - uID = a[k_j]>>1; - if((*c_w).chain_idx[uID] == (*c_w).a[i].id) - { - is_del = 0; - break; - } - } - if(is_del == 0) break; - } - if(is_del == 0) - { - (*c_w).a[m] = (*c_w).a[i]; - m++; - } - } - - ///fprintf(stderr, "# chain: %u, # pre chain: %u\n", m, (uint32_t)(*c_w).n); - (*c_w).n = m; - for (i = 0; i < (*c_w).n; i++) - { - u_x = &(bs_ug->u.a[(*c_w).a[i].id]); - CALLOC((*c_w).a[i].u, 1); - for (k_i = (*c_w).a[i].u->n = 0; k_i < u_x->n; k_i++) - { - if(is_useful_bub(u_x->a[k_i]>>33, *bub)) continue; - (*c_w).a[i].u->n++; - } - (*c_w).a[i].u->m = (*c_w).a[i].u->n; - MALLOC((*c_w).a[i].u->a, (*c_w).a[i].u->m); - for (k_i = (*c_w).a[i].u->n = 0; k_i < u_x->n; k_i++) - { - if(is_useful_bub(u_x->a[k_i]>>33, *bub)) continue; - (*c_w).a[i].u->a[(*c_w).a[i].u->n] = u_x->a[k_i]; - (*c_w).a[i].u->n++; - } - } - (*c_w).max_bub_id = (*c_w).n; - - if(bub->num.n > 0) bub->num.n--; - chain_hic_w_type* p = NULL; - for (i = 0; i < ug->u.n; i++) - { - uID = i; - if(IF_HOM(uID, *bub)) continue; - if((*c_w).chain_idx[uID] == (uint32_t)-1) - { - kv_pushp(chain_hic_w_type, (*c_w), &p); - CALLOC(p->u, 1); - p->u->n = p->u->m = 1; - MALLOC(p->u->a, p->u->m); - p->u->a[0] = (bub->pathLen.n)<<33; - /********************push bubble********************/ - kv_push(uint32_t, bub->num, bub->list.n); - kv_push(uint64_t, bub->pathLen, 0); - kv_push(uint32_t, bub->list, uID<<1); - kv_push(uint32_t, bub->list, uID<<1); - kv_push(uint32_t, bub->list, uID<<1); - /********************push bubble********************/ - p->occ = ug->u.a[uID].n; - p->w = 0; - for (k_k = 0; k_k < link->a.a[uID].e.n; k_k++) - { - if(link->a.a[uID].e.a[k_k].del) continue; - p->w += link->a.a[uID].e.a[k_k].weight; - } - p->id = (*c_w).n - 1; - (*c_w).chain_idx[uID] = p->id; - } - } - kv_push(uint32_t, bub->num, bub->list.n); - - - - - memset((*c_w).chain_idx, -1, sizeof(uint32_t)*ug->u.n); - for (i = 0; i < (*c_w).n; i++) - { - (*c_w).a[i].id = i; - u_x = (*c_w).a[i].u; - for (k_i = 0; k_i < u_x->n; k_i++) - { - get_bubbles(bub, u_x->a[k_i]>>33, NULL, NULL, &a, &n, NULL); - for (k_j = 0; k_j < n; k_j++) - { - uID = a[k_j]>>1; - if((*c_w).chain_idx[uID] == (uint32_t)-1) - { - (*c_w).chain_idx[uID] = (*c_w).a[i].id; - } - else - { - if((*c_w).a[i].occ > (*c_w).a[(*c_w).chain_idx[uID]].occ) - { - (*c_w).chain_idx[uID] = (*c_w).a[i].id; - } - } - } - } - } - - /** - uint32_t rId_0, ori_0, root_0, rId_1, ori_1, root_1; - for (i = 0; i < (*c_w).n; i++) - { - (*c_w).a[i].l_d = (*c_w).a[i].r_d = (uint64_t)-1; - u_x = (*c_w).a[i].u; - if(u_x->n == 0) continue; - - rId_0 = u_x->a[0]>>33; - ori_0 = (u_x->a[0]>>32&1)^1; - get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); - root_0 ^= 1; - } - **/ - - ///fprintf(stderr, "# chain: %u, # c_w.max_bub_id: %u\n", (uint32_t)(*c_w).n, (*c_w).max_bub_id); - ///qsort((*c_w).a, (*c_w).n, sizeof(chain_hic_w_type), cmp_chain_hic_w_weight); -} - -void destory_chain_hic_warp(chain_hic_warp* c_w) -{ - uint32_t i; - for (i = 0; i < c_w->n; i++) - { - free(c_w->a[i].u->a); - free(c_w->a[i].u); - } - kv_destroy((*c_w)); - free((*c_w).chain_idx); -} - -void build_bub_graph(ma_ug_t* ug, bubble_type* bub) -{ - bub->check_het = 0; - get_bub_graph(ug, bub); ///just create nodes/edges from f_bub - detect_bub_graph(bub, ug->g); - asg_destroy(bub->b_g); - bub->check_het = 1; - get_bub_graph(ug, bub); - ///print_bubble_chain(bub, "first round"); - // detect_bub_graph(bub, ug->g, 1); - update_bubble_chain(ug, bub, 1, 0); - ///print_bubble_chain(bub, "second round"); - update_bubble_chain(ug, bub, 0, 1);///resolve tangles within bubble chains - resolve_bubble_chain_tangle(ug, bub);///resolve tangles between bubble chains -} - -void get_forward_distance(uint32_t src, uint32_t dest, asg_t *sg, hc_links* link, MT* M) -{ - hc_edge *e = NULL; - e = get_hc_edge(link, src, dest, 0); - if(e == NULL) return; - uint32_t v, j; - uint64_t d[2], db[2], q_u, min, min_i, min_b; - e->dis = (uint64_t)-1; - - for (v = ((uint64_t)(src)<<1); v < ((uint64_t)(src+1)<<1); v++) - { - d[0] = d[1] = db[0] = db[1] = (uint64_t)-1; - for (j = 0; j < M->matrix.a[v].a.n; j++) - { - q_u = M->matrix.a[v].a.a[j] >> M->uID_shift; - if((q_u>>1) == dest) d[q_u&1] = (M->matrix.a[v].a.a[j] & M->dis_mode) + sg->seq[q_u>>1].len; - if((q_u>>1) > dest) break;///just for speeding up, doesn't affect results - } - - min = min_i = min_b = (uint64_t)-1; - if(e->dis != (uint64_t)-1) min = e->dis >> 3; - - if(d[0] < min) min = d[0], min_i = 0, min_b = 0; - if(d[1] < min) min = d[1], min_i = 1, min_b = 0; - if(min_i != (uint64_t)-1 && min != (uint64_t)-1) - { - e->dis = min<<1; - e->dis += min_b; - e->dis <<=1; - e->dis += v&1; - e->dis <<=1; - e->dis += min_i; - } - } - // fprintf(stderr, "%s\t%s\tdis(%lu)\n", e->dis == (uint64_t)-1? "unreach cur": "**reach cur", - // ((e->dis>>2)&1)?"back":"forw", e->dis>>3); -} - -uint32_t is_same_phase(uint64_t bid, uint64_t eid, H_partition* hap, int8_t *s, mc_gg_status *sa) -{ - if(bid == eid) return 1; - if(hap || s) - { - int beg_status, end_status; - beg_status = (hap? get_phase_status(hap, bid):s[bid]); - if(beg_status != 1 && beg_status != -1) return (uint32_t)-1; - end_status = (hap? get_phase_status(hap, eid):s[eid]); - if(end_status != 1 && end_status != -1) return (uint32_t)-1; - if(beg_status == end_status) return 1; - return 0; - } - - if(sa) - { - if(sa[bid].s == 0 || sa[eid].s == 0) return (uint32_t)-1; - return !!(sa[bid].s&sa[eid].s); - } - return (uint32_t)-1; -} - -int get_trans_rate_function_advance(ha_ug_index* idx, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, -H_partition* hap, int8_t *s, mc_gg_status *sa, trans_idx* dis) -{ - kvec_t(uint64_t) buf; - kv_init(buf); - uint64_t beg, end, cnt[2]; - uint64_t k, i, t_d, r_idx, f_idx, med = (uint64_t)-1; - uint32_t is_s; - // int beg_status, end_status; - - buf.n = 0; - for (k = 0; k < hits->a.n; ++k) - { - beg = ((hits->a.a[k].s<<1)>>(64 - idx->uID_bits)); - end = ((hits->a.a[k].e<<1)>>(64 - idx->uID_bits)); - - if(IF_HOM(beg, *bub)) continue; - if(IF_HOM(end, *bub)) continue; - if(is_hom_hit(hits->a.a[k])) continue; - - - t_d = get_hic_distance(&(hits->a.a[k]), link, idx, NULL); - if(t_d == (uint64_t)-1) continue; - // if(beg == end) - // { - // t_d = (t_d << 1); - // } - // else - // { - // beg_status = (hap? get_phase_status(hap, beg):s[beg]); - // if(beg_status != 1 && beg_status != -1) continue; - // end_status = (hap? get_phase_status(hap, end):s[end]); - // if(end_status != 1 && end_status != -1) continue; - // if(beg_status != end_status) - // { - // t_d = (t_d << 1) + 1; - // } - // else - // { - // t_d = (t_d << 1); - // } - // } - is_s = is_same_phase(beg, end, hap, s, sa); - if(is_s == (uint32_t)-1) continue; - t_d = (t_d << 1) + 1 - is_s; - - kv_push(uint64_t, buf, t_d); - } - - ///might have bias, we may not use right linkage larger than trans rc linkage - radix_sort_hc64(buf.a, buf.a+buf.n); - - for (k = 0, r_idx = f_idx = (uint64_t)-1; k < buf.n; k++) - { - if((buf.a[k]&1) == 0) r_idx = k; - if((buf.a[k]&1) == 1) f_idx = k; - } - buf.n = MIN(r_idx, f_idx); - - - trans_p_t* p = NULL; - dis->n = 0; - uint64_t bin_size = MIN(2250, buf.n>>8), m; - if(bin_size == 0) - { - for (i = 8; i > 0; i--) - { - bin_size = buf.n>>i; - if(bin_size > 0) break; - } - if(bin_size == 0) bin_size = buf.n; - } - i = 0; - while (i < buf.n) - { - kv_pushp(trans_p_t, *dis, &p); - p->beg = i; - - cnt[0] = cnt[1] = 0; - k = MIN(i+bin_size, buf.n); - for (; i < k; i++) - { - cnt[buf.a[i]&1]++; - } - p->end = i; - p->cnt_0 = cnt[0]; - p->cnt_1 = cnt[1]; - } - - i = m = 0; med = (uint64_t)-1; - while(i < dis->n) - { - if(dis->a[i].cnt_0 > 0 && dis->a[i].cnt_1 > 0) - { - dis->a[m] = dis->a[i]; - m++; - i++; - continue; - } - - if(med == (uint64_t)-1) med = buf.a[dis->a[i].beg]>>1; - k = i; cnt[0] = cnt[1] = 0; - for (; i < dis->n; i++) - { - cnt[0] += dis->a[i].cnt_0; - cnt[1] += dis->a[i].cnt_1; - if(cnt[0] > 0 && cnt[1] > 0) break; - } - - if(i < dis->n) - { - dis->a[m].cnt_0 = cnt[0]; - dis->a[m].cnt_1 = cnt[1]; - dis->a[m].beg = dis->a[k].beg; - dis->a[m].end = dis->a[i].end; - m++; - i++; - continue; - } - - cnt[0] -= dis->a[k].cnt_0; - cnt[1] -= dis->a[k].cnt_1; - while (1) - { - cnt[0] += dis->a[k].cnt_0; - cnt[1] += dis->a[k].cnt_1; - if(cnt[0] > 0 && cnt[1] > 0) break; - - if(k == 0) - { - k = (uint64_t)-1; - break; - } - k--; - } - - if(k != (uint64_t)-1) - { - dis->a[m].cnt_0 = cnt[0]; - dis->a[m].cnt_1 = cnt[1]; - dis->a[m].end = dis->a[i-1].end; - continue; - } - m = 0; - break; - } - dis->n = m; - if(dis->n == 0) - { - kv_destroy(buf); - return 0; - } - - for (i = 0; i < dis->n; i++) - { - dis->a[i].beg = buf.a[dis->a[i].beg]>>1; - dis->a[i].end = (buf.a[dis->a[i].end-1]>>1); - } - - for (i = 0; i < dis->n - 1; i++) - { - dis->a[i].end += ((dis->a[i+1].beg - dis->a[i].end)/2); - dis->a[i+1].beg = dis->a[i].end; - } - - // for (i = 0; i < dis->n; i++) - // { - // if(i > 0 && dis->a[i].beg != dis->a[i-1].end) fprintf(stderr, "ERROR: dis->a[i].beg: %lu, dis->a[i-1].end: %lu\n", dis->a[i].beg, dis->a[i-1].end); - // fprintf(stderr, "beg: %lu, end: %lu, cnt_0: %lu, cnt_1: %lu, error_rate: %f\n", - // dis->a[i].beg, dis->a[i].end, dis->a[i].cnt_0, dis->a[i].cnt_1, (double)(dis->a[i].cnt_1)/(double)(dis->a[i].cnt_1 + dis->a[i].cnt_0)); - // } - - LeastSquare_advance(dis, idx, med); - // fprintf(stderr, "idx->a: %f, idx->b: %f, idx->frac: %f, med: %lu\n", - // (double)idx->a, (double)idx->b, (double)idx->frac, med); - - dis->max = dis->a[dis->n-1].end; - - - - if(idx->a < 0) idx->a = 0; - if(idx->a == 0) - { - idx->b = MAX((((double)(dis->a[dis->n-1].cnt_1))/((double)(dis->a[dis->n-1].cnt_0 + dis->a[dis->n-1].cnt_1))), idx->b); - } - if(idx->b < 0 && get_trans(idx, dis->max) < 0) - { - idx->b = ((double)(dis->a[dis->n-1].cnt_1))/((double)(dis->a[dis->n-1].cnt_0 + dis->a[dis->n-1].cnt_1)); - } - - // fprintf(stderr, "idx->a: %f, idx->b: %f, idx->frac: %f, med: %lu\n", - // (double)idx->a, (double)idx->b, (double)idx->frac, med); - - - - - - buf.n = 0; - for (k = 0; k < hits->a.n; ++k) - { - beg = ((hits->a.a[k].s<<1)>>(64 - idx->uID_bits)); - end = ((hits->a.a[k].e<<1)>>(64 - idx->uID_bits)); - - if(IF_HOM(beg, *bub)) continue; - if(IF_HOM(end, *bub)) continue; - if(is_hom_hit(hits->a.a[k])) continue; - if(beg == end) continue; - - t_d = get_hic_distance(&(hits->a.a[k]), link, idx, NULL); - if(t_d == (uint64_t)-1) continue; - kv_push(uint64_t, buf, t_d); - } - - ///might have bias, we may not use right linkage larger than trans rc linkage - radix_sort_hc64(buf.a, buf.a+buf.n); - if(buf.n == 0) - { - dis->med = 0; - } - else - { - dis->med = ((buf.n&1)?buf.a[buf.n>>1]:((buf.a[buf.n>>1]+buf.a[(buf.n>>1)-1])/2)); - } - - // fprintf(stderr, "dis->med: %lu\n", dis->med); - - kv_destroy(buf); - return 1; -} - -void init_hic_advance(ha_ug_index* idx, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, H_partition* hap, uint32_t ignore_dis) -{ - uint64_t k, i, m, is_comples_weight = 0; - trans_idx dis; - kv_init(dis); - - if(bub->round_id > 0 && ignore_dis == 0) - { - is_comples_weight = get_trans_rate_function_advance(idx, hits, link, bub, hap, NULL, NULL, &dis); - } - - - hc_edge *e = NULL; - for (i = 0; i < link->a.n; i++) - { - for (k = 0; k < link->a.a[i].e.n; k++) - { - if(link->a.a[i].e.a[k].del) continue; - if(link->a.a[i].e.a[k].dis == (uint64_t)-1) - { - e = get_hc_edge(link, link->a.a[i].e.a[k].uID, i, 0); - if(!e) fprintf(stderr, "ERROR\n"); - e->del = link->a.a[i].e.a[k].del = 1; - } - } - } - - for (i = 0; i < link->a.n; i++) - { - for (k = m = 0; k < link->a.a[i].e.n; k++) - { - if(link->a.a[i].e.a[k].del) continue; - link->a.a[i].e.a[m] = link->a.a[i].e.a[k]; - link->a.a[i].e.a[m].weight = 0; - link->a.a[i].e.a[m].occ = 0; - m++; - } - link->a.a[i].e.n = m; - } - - weight_edges_advance(idx, hits, link, bub, is_comples_weight == 1? &dis : NULL); - - for (i = 0; i < link->a.n; i++) - { - for (k = 0; k < link->a.a[i].e.n; k++) - { - if(link->a.a[i].e.a[k].del) continue; - if(link->a.a[i].e.a[k].weight <= 0) - { - e = get_hc_edge(link, link->a.a[i].e.a[k].uID, i, 0); - e->del = link->a.a[i].e.a[k].del = 1; - } - } - } - - for (i = 0; i < link->a.n; i++) - { - for (k = m = 0; k < link->a.a[i].e.n; k++) - { - if(link->a.a[i].e.a[k].del) continue; - link->a.a[i].e.a[m] = link->a.a[i].e.a[k]; - m++; - } - link->a.a[i].e.n = m; - } - kv_destroy(dis); -} - - -#define is_hap_set(i, Hap) (!!((Hap).hap[(i)]&((Hap).m[0]|(Hap).m[1]|(Hap).m[2]))) -#define is_hap_set_label(i, Hap, label) (is_hap_set((i), (Hap))&&((Hap).hap[(i)]>>(Hap).label_shift)==((label)>>(Hap).label_shift)) - -double get_path_weight(uint32_t query, uint32_t v0, uint32_t root, bub_p_t_warp *b, hc_links* x) -{ - if(v0 == root) return 0; - uint32_t v, u; - hc_edge *p = NULL; - double weight = 0; - v = v0; - do { - u = b->a[v].p; // u->v - p = get_hc_edge(x, query>>1, v>>1, 0); - if(p) weight += p->weight; - v = u; - } while (v != root); - - return weight; -} - -uint32_t get_related_weight(uint32_t x, H_partition* hap, double* w0, double* w1, uint32_t* hap_label) -{ - (*w0) = (*w1) = 0; - if(x >= hap->link->a.n) return 0; - uint32_t i, a_n = hap->link->a.a[x].e.n, occ; - hc_edge* a = hap->link->a.a[x].e.a; - for (i = occ = 0; i < a_n; i++) - { - if(a[i].del) continue; - if(hap_label && (!is_hap_set_label(a[i].uID, *hap, *hap_label))) continue; - if(is_hap_set(a[i].uID, *hap)) occ++; - if((hap->hap[a[i].uID] & hap->m[0])) (*w0)+= a[i].weight; - if((hap->hap[a[i].uID] & hap->m[1])) (*w1)+= a[i].weight; - } - return occ; -} - -void set_path_hap(bub_p_t_warp *b, uint32_t root, H_partition* hap, uint32_t max_hap_label) -{ - uint32_t v, u, label; - double w0 = 0, w1 = 0, cur_w0, cur_w1; - ///v is the sink of this bubble - v = b->S.a[0]; - do { - u = b->a[v].p; // u->v - if(v != b->S.a[0]) - { - get_related_weight(v>>1, hap, &cur_w0, &cur_w1, &max_hap_label); - w0 += cur_w0; w1 += cur_w1; - } - v = u; - } while (v != root); - - if(w0 > w1) - { - label = max_hap_label | hap->m[0]; - b->exist_hap_label = hap->m[0]; - } - else if(w0 < w1) - { - label = max_hap_label | hap->m[1]; - b->exist_hap_label = hap->m[1]; - } - else - { - if(b->exist_hap_label == (uint32_t)-1) - { - label = max_hap_label | hap->m[0]; - b->exist_hap_label = hap->m[0]; - } - else - { - if(b->exist_hap_label == hap->m[0]) - { - label = max_hap_label | hap->m[1]; - b->exist_hap_label = hap->m[1]; - } - else - { - label = max_hap_label | hap->m[0]; - b->exist_hap_label = hap->m[0]; - } - } - } - - - v = b->S.a[0]; - do { - u = b->a[v].p; // u->v - if(v != b->S.a[0]) hap->hap[v>>1] |= label; - v = u; - } while (v != root); -} - - -uint64_t get_phase_path(ma_ug_t *ug, uint32_t s, uint32_t d, bub_p_t_warp *b, H_partition* hap, uint32_t max_hap_label) -{ - asg_t *g = ug->g; - if(g->seq[s>>1].del) return 0; // already deleted - if(get_real_length(g, s, NULL)<2) return 0; - uint32_t i, n_pending, is_first, to_replace, cur_nc, cur_uc, cur_ac, n_tips, tip_end, n_pop; - double cur_nh, cur_w0, cur_w1, cur_rate, max_rate, cur_weight, max_weight; - ///S saves nodes with all incoming edges visited - b->S.n = b->T.n = b->b.n = b->e.n = 0; - ///for each node, b->a saves all related information - b->a[s].d = b->a[s].nc = b->a[s].ac = b->a[s].uc = 0; b->a[s].nh = b->a[s].w[0] = b->a[s].w[1] = 0; - ///b->S is the nodes with all incoming edges visited - kv_push(uint32_t, b->S, s); - n_pop = n_tips = n_pending = 0; - tip_end = (uint32_t)-1; - is_first = 1; - - do { - ///v is a node that all incoming edges have been visited - ///d is the distance from v0 to v - uint32_t v = kv_pop(b->S); - uint32_t d = b->a[v].d, nc = b->a[v].nc, uc = b->a[v].uc, ac = b->a[v].ac; - double nh = b->a[v].nh; - double nw_0 = b->a[v].w[0], nw_1 = b->a[v].w[1]; - - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - for (i = 0; i < nv; ++i) { - uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l, not overlap length - bub_p_t *t = &b->a[w]; - //got a circle - if ((w>>1) == (s>>1)) goto pop_reset; - //important when poping at long untig graph - if(is_first) l = 0; - if (av[i].del) continue; - ///push the edge - kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); - - if (t->s == 0) - { // this vertex has never been visited - kv_push(uint32_t, b->b, w); // save it for revert - ///t->p is the parent node of - ///t->s = 1 means w has been visited - ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) - t->p = v, t->s = 1, t->d = d + l, t->nc = nc + ug->u.a[(w>>1)].n; - t->r = get_real_length(g, w^1, NULL); - /**need fix**/ - t->nh = nh + get_path_weight(w, v, s, b, hap->link); - - get_related_weight(w>>1, hap, &(t->w[0]), &(t->w[1]), &max_hap_label); - t->w[0] += nw_0; t->w[1] += nw_1; - - t->ac = ac + ((!is_hap_set_label(w>>1, *hap, max_hap_label))?ug->u.a[(w>>1)].n : 0); - t->uc = uc + ((is_hap_set_label(w>>1, *hap, max_hap_label))?ug->u.a[(w>>1)].n : 0); - - ++n_pending; - } - else { - to_replace = 0; - - cur_nc = nc + ug->u.a[(w>>1)].n; - /**need fix**/ - cur_nh = nh + get_path_weight(w, v, s, b, hap->link); - get_related_weight(w>>1, hap, &cur_w0, &cur_w1, &max_hap_label); - cur_w0 += nw_0; cur_w1 += nw_1; - cur_weight = cur_nh + MAX(cur_w0, cur_w1) - MIN(cur_w0, cur_w1); - max_weight = t->nh + MAX(t->w[0], t->w[1]) - MIN(t->w[0], t->w[1]); - - cur_ac = ac + ((!is_hap_set_label(w>>1, *hap, max_hap_label))?ug->u.a[(w>>1)].n : 0);; - cur_uc = uc + ((is_hap_set_label(w>>1, *hap, max_hap_label))?ug->u.a[(w>>1)].n : 0); - cur_rate = ((double)(cur_ac)/(double)(cur_ac+cur_uc)); - max_rate = ((double)(t->ac)/(double)(t->ac+t->uc)); - - if(cur_rate > max_rate) - { - to_replace = 1; - } - else if(cur_rate == max_rate) - { - ///if(cur_nh > t->nh) - if(cur_weight > max_weight) - { - to_replace = 1; - } - else if(cur_weight == max_weight)///(cur_nh == t->nh) - { - if(cur_nc > t->nc) - { - to_replace = 1; - } - else if(cur_nc == t->nc) - { - if(d + l > t->d) - { - to_replace = 1; - } - } - } - } - - - if(to_replace) - { - t->p = v; - t->nc = cur_nc; - t->nh = cur_nh; - t->ac = cur_ac; - t->uc = cur_uc; - t->w[0] = cur_w0; - t->w[1] = cur_w1; - } - - - if (d + l < t->d) t->d = d + l; // update dist - } - - if (--(t->r) == 0) { - uint32_t x = get_real_length(g, w, NULL); - if(x > 0) - { - kv_push(uint32_t, b->S, w); - } - else - { - ///at most one tip - if(n_tips != 0) goto pop_reset; - n_tips++; - tip_end = w; - } - --n_pending; - } - } - is_first = 0; - - - if(n_tips == 1) - { - if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) - { - ///sink is b.S.a[0] - kv_push(uint32_t, b->S, tip_end); - break; - } - else - { - goto pop_reset; - } - } - - if (i < nv || b->S.n == 0) goto pop_reset; - }while (b->S.n > 1 || n_pending); - - - n_pop = 1; - /**need fix**/ - set_path_hap(b, s, hap, max_hap_label); - pop_reset: - - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - bub_p_t *t = &b->a[b->b.a[i]]; - t->p = t->d = t->nc = t->ac = t->uc = t->r = t->s = 0; - t->nh = t->w[0] = t->w[1] = 0; - } - - return n_pop; -} - -uint32_t get_weightest_hap_label_from_uid(uint64_t x, H_partition* hap, uint8_t* hap_label_flag, -uint32_t* max_hap_label, double* max_hap_weight) -{ - (*max_hap_label) = (uint32_t)-1; - kv_resize(double, hap->label_buffer, (hap->label>>hap->label_shift)+1); - hap->label_buffer.n = (hap->label>>hap->label_shift)+1; - uint32_t i, is_set_ava, is_unset_ava, a_n; - hc_edge* a = NULL; - for (i = 0; i < hap->label_buffer.n; i++) - { - hap->label_buffer.a[i] = 0; - } - - is_set_ava = is_unset_ava = 0; - a_n = hap->link->a.a[x].e.n; - a = hap->link->a.a[x].e.a; - for (i = 0; i < a_n; i++) - { - if(a[i].del) continue; - if(is_hap_set(a[i].uID, *hap)) - { - if(hap_label_flag && hap_label_flag[hap->hap[a[i].uID]] == 0) continue; - hap->label_buffer.a[hap->hap[a[i].uID]>>hap->label_shift] += a[i].weight; - is_set_ava = 1; - } - is_unset_ava = 1; - } - - if(hap_label_flag && is_set_ava == 0) return 0; - if(is_unset_ava == 0) return 0; - if(is_set_ava == 0 && is_unset_ava > 0) - { - hap->label += hap->label_add; - (*max_hap_label) = hap->label; - return 1; - } - - double max_weight; - uint32_t max_i; - for (i = 0, max_weight = -1, max_i = (uint32_t)-1; i < hap->label_buffer.n; i++) - { - if(hap->label_buffer.a[i] > max_weight) - { - max_weight = hap->label_buffer.a[i]; - max_i = i; - } - } - - (*max_hap_label) = max_i<label_shift; - if(max_hap_weight) (*max_hap_weight) = max_weight; - return 1; - -} - -uint32_t get_weightest_hap_label_from_bubble(uint64_t bid, H_partition* hap, bubble_type* bub, -uint8_t* hap_label_flag, uint32_t* max_hap_label, double* max_hap_weight) -{ - (*max_hap_label) = (uint32_t)-1; - - kv_resize(double, hap->label_buffer, (hap->label>>hap->label_shift)+1); - hap->label_buffer.n = (hap->label>>hap->label_shift)+1; - uint32_t i, m, is_set_ava, is_unset_ava, a_n, *x_a, x_n, x; - hc_edge* a = NULL; - for (i = 0; i < hap->label_buffer.n; i++) - { - hap->label_buffer.a[i] = 0; - } - - ///bid might be bubble or non-bubble - get_bubbles(bub, bid, NULL, NULL, &x_a, &x_n, NULL); - for (m = is_set_ava = is_unset_ava = 0; m < x_n; m++) - { - ///x is uid - x = x_a[m]>>1; - a_n = hap->link->a.a[x].e.n; - a = hap->link->a.a[x].e.a; - for (i = 0; i < a_n; i++) - { - if(a[i].del) continue; - if(is_hap_set(a[i].uID, *hap)) - { - if(hap_label_flag && hap_label_flag[hap->hap[a[i].uID]] == 0) continue; ///not at current chain - hap->label_buffer.a[hap->hap[a[i].uID]>>hap->label_shift] += a[i].weight; - is_set_ava = 1; - } - is_unset_ava = 1; - } - } - if(hap_label_flag && is_set_ava == 0) return 0; ///no connection in current chain - - if(is_unset_ava == 0) return 0; ///no any connection - if(is_set_ava == 0 && is_unset_ava > 0) ///update hap->label - { - hap->label += hap->label_add; - (*max_hap_label) = hap->label; - return 1; - } - - double max_weight; - uint32_t max_i; - for (i = 0, max_weight = -1, max_i = (uint32_t)-1; i < hap->label_buffer.n; i++) - { - if(hap->label_buffer.a[i] > max_weight) - { - max_weight = hap->label_buffer.a[i]; - max_i = i; - } - } - - (*max_hap_label) = max_i<label_shift; - if(max_hap_weight) (*max_hap_weight) = max_weight; - return 1; -} - - -uint32_t get_available_com(H_partition* hap, bubble_type* bub, ma_ug_t *ug, uint32_t check_self, uint32_t check_others, -uint8_t* hap_label_flag, uint32_t* max_hap_label) -{ - hc_links* link = hap->link; - uint32_t beg, sink, n, *a, i, j, k, uID, max_bub_i, max_non_bub_i, max_i, is_ava; - uint32_t hap_label, max_bub_label = (uint32_t)-1, max_non_bub_label = (uint32_t)-1; - double w, max_bub_w, max_non_bub_w; - max_i = (uint32_t)-1; - - for (i = 0, max_bub_w = -1, max_bub_i = (uint32_t)-1; i < bub->f_bub/**bub->s_bub**/; i++) - { - get_bubbles(bub, i, &beg, &sink, &a, &n, NULL); - for (j = 0, w = 0; j < n; j++) - { - uID = a[j]>>1; - if(check_self && is_hap_set(uID, *hap)) break; - } - if(j != n) continue; - - is_ava = 0; - hap_label = (uint32_t)-1; - if(check_others) - { - if(get_weightest_hap_label_from_bubble(i, hap, bub, - hap_label_flag, &hap_label, &w)>0) - { - is_ava = 1; - } - } - else - { - for (j = 0, w = 0, is_ava = 0; j < n; j++) - { - uID = a[j]>>1; - for (k = 0; k < link->a.a[uID].e.n; k++) - { - if(link->a.a[uID].e.a[k].del) continue; - w += link->a.a[uID].e.a[k].weight; - is_ava = 1; - } - } - } - - if(is_ava == 0) continue; - - if(w > max_bub_w) - { - max_bub_w = w; - max_bub_i = i; - max_bub_label = hap_label; - } - } - - for (i = 0, max_non_bub_w = -1, max_non_bub_i = (uint32_t)-1; i < ug->u.n; i++) - { - if(IF_HET(i, *bub)/** || (bub->index[i] >= bub->s_bub && bub->index[i] < bub->f_bub)**/) - { - uID = i; - is_ava = 0; - if(check_self && is_hap_set(uID, *hap)) continue; - hap_label = (uint32_t)-1; - if(check_others) - { - if(get_weightest_hap_label_from_uid(uID, hap, hap_label_flag, &hap_label, &w)>0) - { - is_ava = 1; - } - } - else - { - for (k = 0, w = 0, is_ava = 0; k < link->a.a[uID].e.n; k++) - { - if(link->a.a[uID].e.a[k].del) continue; - w += link->a.a[uID].e.a[k].weight; - is_ava = 1; - } - } - - if(is_ava == 0) continue; - - if(w > max_non_bub_w) - { - max_non_bub_w = w; - max_non_bub_i = i; - max_non_bub_label = hap_label; - } - } - } - - if(max_bub_i != (uint32_t)-1 && max_non_bub_i != (uint32_t)-1) - { - if(max_non_bub_w > max_bub_w) - { - max_i = (max_non_bub_i << 1) + 1; - w = max_non_bub_w; - (*max_hap_label) = max_non_bub_label; - } - else - { - max_i = (max_bub_i << 1); - w = max_bub_w; - (*max_hap_label) = max_bub_label; - } - } - else if(max_bub_i != (uint32_t)-1) - { - max_i = (max_bub_i << 1); - w = max_bub_w; - (*max_hap_label) = max_bub_label; - } - else if(max_non_bub_i != (uint32_t)-1) - { - max_i = (max_non_bub_i << 1) + 1; - w = max_non_bub_w; - (*max_hap_label) = max_non_bub_label; - } - - if(max_i == (uint32_t)-1) - { - for (i = 0, max_non_bub_w = -1, max_non_bub_i = (uint32_t)-1; i < ug->u.n; i++) - { - ///if(bub->index[i] < bub->s_bub) - if(IF_BUB(i, *bub)) - { - - uID = i; - is_ava = 0; - if(check_self && is_hap_set(uID, *hap)) continue; - hap_label = (uint32_t)-1; - if(check_others) - { - if(get_weightest_hap_label_from_uid(uID, hap, hap_label_flag, &hap_label, &w)>0) - { - is_ava = 1; - } - } - else - { - for (k = 0, w = 0, is_ava = 0; k < link->a.a[uID].e.n; k++) - { - if(link->a.a[uID].e.a[k].del) continue; - w += link->a.a[uID].e.a[k].weight; - is_ava = 1; - } - } - - if(is_ava == 0) continue; - - if(w > max_non_bub_w) - { - max_non_bub_w = w; - max_non_bub_i = i; - max_non_bub_label = hap_label; - } - - } - } - - if(max_non_bub_i != (uint32_t)-1) - { - max_i = (max_non_bub_i << 1) + 1; - w = max_non_bub_w; - (*max_hap_label) = max_non_bub_label; - } - } - - // if(max_i == (uint32_t)-1) - // { - // fprintf(stderr, "-Cannot find!\n"); - // } - // else if(max_i & 1) - // { - // fprintf(stderr, "-utg-%uth, phasing ID: %u, w: %f, max_bub_i: %u, max_bub_w: %f, max_non_bub_i: %u, max_non_bub_w: %f\n", - // max_i>>1, hap->label>>3, w, max_bub_i, max_bub_w, max_non_bub_i, max_non_bub_w); - // } - // else - // { - // fprintf(stderr, "-bubble-%uth, phasing ID: %u, w: %f, max_bub_i: %u, max_bub_w: %f, max_non_bub_i: %u, max_non_bub_w: %f\n", - // max_i>>1, hap->label>>3, w, max_bub_i, max_bub_w, max_non_bub_i, max_non_bub_w); - // } - - return max_i; -} - -void reset_ambiguous_label(H_partition* hap, uint8_t* hap_label_flag, uint32_t uID) -{ - uint32_t hap_label = (uint32_t)-1; - if(get_weightest_hap_label_from_uid(uID, hap, hap_label_flag, &hap_label, NULL)>0) - { - double cur_w0, cur_w1; - get_related_weight(uID, hap, &cur_w0, &cur_w1, &hap_label); - if(cur_w0 >= cur_w1) - { - hap->hap[uID] |= (hap_label | hap->m[0]); - } - else - { - hap->hap[uID] |= (hap_label | hap->m[1]); - } - } -} - -uint32_t get_unset_com(H_partition* hap, bubble_type* bub, ma_ug_t *ug, uint8_t* hap_label_flag, uint32_t* max_hap_label) -{ - uint32_t max_i = get_available_com(hap, bub, ug, 1, 1, hap_label_flag, max_hap_label); - - if(max_i == (uint32_t)-1) - { - max_i = get_available_com(hap, bub, ug, 1, 0, hap_label_flag, max_hap_label); - if(max_i != (uint32_t)-1) - { - hap->label += hap->label_add; - (*max_hap_label) = hap->label; - } - } - - return max_i; -} - -void phase_com(H_partition* hap, ma_ug_t *ug, bub_p_t_warp* b, bubble_type* bub, uint32_t bid, uint32_t max_hap_label) -{ - - if((bid & 1) == 0) ///bubble - { - uint32_t beg = (uint32_t)-1, sink = (uint32_t)-1, n, *a; - get_bubbles(bub, bid>>1, &beg, &sink, &a, &n, NULL); - ///fprintf(stderr, "+bubble-%uth, beg: %u, sink: %u, phasing ID: %u\n", bid>>1, beg>>1, sink>>1, hap->label>>3); - b->exist_hap_label = (uint32_t)-1; - get_phase_path(ug, beg, sink, b, hap, max_hap_label); - get_phase_path(ug, beg, sink, b, hap, max_hap_label); - ///fprintf(stderr, "-bubble-%uth, beg: %u, sink: %u, phasing ID: %u\n", bid>>1, beg>>1, sink>>1, hap->label>>3); - } - else - { - double cur_w0, cur_w1; - get_related_weight(bid>>1, hap, &cur_w0, &cur_w1, &max_hap_label); - ///fprintf(stderr, "utg-%uth, phasing ID: %u\n", bid>>1, hap->label>>3); - if(cur_w0 >= cur_w1) - { - hap->hap[bid>>1] |= (max_hap_label | hap->m[0]); - } - else - { - hap->hap[bid>>1] |= (max_hap_label | hap->m[1]); - } - } -} - - -double get_cluster_weight(H_partition* hap, hc_links* link, uint32_t *h, uint32_t h_n) -{ - int o_d = 0; - double weight = 0; - uint32_t j, k, m; - for (j = 0, weight = 0; j < h_n; j++) - { - for (k = 0; k < link->a.a[h[j]].e.n; k++) - { - if(link->a.a[h[j]].e.a[k].del) continue; - for (m = 0; m < h_n; m++) - { - if(h[m] == link->a.a[h[j]].e.a[k].uID) break; - } - if(m < h_n) continue; - - o_d = get_phase_status(hap, link->a.a[h[j]].e.a[k].uID); - if(o_d < -1) continue; - ///if(o_d < -1) fprintf(stderr, "ERROR\n"); - weight += (o_d*link->a.a[h[j]].e.a[k].weight); - } - } - - return weight; -} - - -double get_cluster_inner_weight(H_partition* hap, hc_links* link, uint32_t *h0, uint32_t h0_n, -uint32_t *h1, uint32_t h1_n) -{ - double weight = 0; - uint32_t j, k, m; - for (j = 0, weight = 0; j < h0_n; j++) - { - for (k = 0; k < link->a.a[h0[j]].e.n; k++) - { - if(link->a.a[h0[j]].e.a[k].del) continue; - for (m = 0; m < h1_n; m++) - { - if(h1[m] == link->a.a[h0[j]].e.a[k].uID) break; - } - if(m == h1_n) continue; - - weight += link->a.a[h0[j]].e.a[k].weight; - } - } - - return weight * 2; -} - -void update_partition_flag(H_partition* h, G_partition* g_p, hc_links* link, uint32_t id) -{ - uint32_t k, *h0, h0_n, *h1, h1_n, uID, flag = 0; - int status; - get_phased_block(g_p, NULL, id, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); - - status = g_p->a[id].status[0]; - if(status == 1) flag = h->m[0]; - else if(status == -1) flag = h->m[1]; - else if(status == 0) flag = h->m[2]; - else if(status == -2) flag = 0; - for (k = 0; k < h0_n; k++) - { - uID = h0[k]; - h->hap[uID] >>= 3; - h->hap[uID] <<= 3; - h->hap[uID] |= flag; - } - - status = g_p->a[id].status[1]; - if(status == 1) flag = h->m[0]; - else if(status == -1) flag = h->m[1]; - else if(status == 0) flag = h->m[2]; - else if(status == -2) flag = 0; - for (k = 0; k < h1_n; k++) - { - uID = h1[k]; - h->hap[uID] >>= 3; - h->hap[uID] <<= 3; - h->hap[uID] |= flag; - } -} - - -void update_partition_flag_debug(H_partition* h, G_partition* g_p, hc_links* link, uint32_t id) -{ - uint32_t k, *h0, h0_n, *h1, h1_n, uID, flag = 0; - int status; - get_phased_block(g_p, NULL, id, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); - - status = g_p->a[id].status[0]; - if(status == 1) flag = h->m[0]; - else if(status == -1) flag = h->m[1]; - else if(status == 0) flag = h->m[2]; - else if(status == -2) flag = 0; - for (k = 0; k < h0_n; k++) - { - uID = h0[k]; - if(flag != (h->hap[uID]&7)) fprintf(stderr, "h0, id: %u, uID: %u, pre_flag: %u, cur_flag: %u\n", id, uID, (h->hap[uID]&7), flag); - h->hap[uID] >>= 3; - h->hap[uID] <<= 3; - h->hap[uID] |= flag; - } - - status = g_p->a[id].status[1]; - if(status == 1) flag = h->m[0]; - else if(status == -1) flag = h->m[1]; - else if(status == 0) flag = h->m[2]; - else if(status == -2) flag = 0; - for (k = 0; k < h1_n; k++) - { - uID = h1[k]; - if(flag != (h->hap[uID]&7)) fprintf(stderr, "h1, id: %u, uID: %u, pre_flag: %u, cur_flag: %u\n", id, uID, (h->hap[uID]&7), flag); - h->hap[uID] >>= 3; - h->hap[uID] <<= 3; - h->hap[uID] |= flag; - } -} - -void print_contig_partition(H_partition* hap, const char* debug) -{ - uint32_t i; - int status; - for (i = 0; i < hap->n; i++) - { - status = get_phase_status(hap, i); - fprintf(stderr, "%s\tutg%.6d\tP:%u\tHG:A:%d\n", debug, (int)(i+1), hap->hap[i]>>3, status); - } -} - -void adjust_contig_partition(H_partition* hap, hc_links* link) -{ - double index_time = yak_realtime(); - uint32_t i, k, *h0, h0_n, *h1, h1_n; - uint32_t h0_status[4], h1_status[4], h0_status_max; - int h0_h, h1_h; - for (i = 0; i < hap->g_p.n; i++) - { - - get_phased_block(&(hap->g_p), NULL, i, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); - hap->g_p.a[i].status[0] = hap->g_p.a[i].status[1] = -2; - hap->g_p.a[i].weight[0] = hap->g_p.a[i].weight[1] = hap->g_p.a[i].weight_convex = 0; - - - h0_status[0] = h0_status[1] = h0_status[2] = h0_status[3] = 0; - for (k = 0; k < h0_n; k++) - { - h0_status[get_phase_status(hap, h0[k])+2]++; - } - - hap->g_p.a[i].weight[0] = get_cluster_weight(hap, link, h0, h0_n); - if(h1_n == 0) - { - if(h0_status[0] == h0_n) ///unset, flag = -2 - { - hap->g_p.a[i].status[0] = -2; - } - else - { - if(h0_status[1] > 0 || h0_status[3] > 0) ///phased flag = 1/-1 - { - h0_status[0] = h0_status[2] = 0; - - h0_h = -2; - h0_status_max = 0; - for (k = 0; k < 4; k++) - { - if(h0_status[k] > h0_status_max) - { - h0_status_max = h0_status[k]; - h0_h = (int)(k) - 2; - } - } - hap->g_p.a[i].status[0] = h0_h; - } - else if(h0_status[2] > 0) ///hom flag - { - hap->g_p.a[i].status[0] = 0; - } - else //unset flag - { - hap->g_p.a[i].status[0] = -2; - } - } - } - else - { - hap->g_p.a[i].weight[1] = get_cluster_weight( hap, link, h1, h1_n); - h1_status[0] = h1_status[1] = h1_status[2] = h1_status[3] = 0; - for (k = 0; k < h1_n; k++) - { - h1_status[get_phase_status(hap, h1[k])+2]++; - } - - - h0_h = h1_h = 0; - for (k = 0; k < 4; k++) - { - if(h0_status[k] == h0_n) h0_h = (int)(k) - 2; - if(h1_status[k] == h1_n) h1_h = (int)(k) - 2; - } - - if(h0_h * h1_h == -1) - { - hap->g_p.a[i].status[0] = h0_h; - hap->g_p.a[i].status[1] = h1_h; - } - else - { - if(hap->g_p.a[i].weight[0] >= hap->g_p.a[i].weight[1]) - { - hap->g_p.a[i].status[0] = 1; - hap->g_p.a[i].status[1] = -1; - } - else - { - hap->g_p.a[i].status[0] = -1; - hap->g_p.a[i].status[1] = 1; - } - } - } - hap->g_p.a[i].weight_convex = get_cluster_inner_weight(hap, link, h0, h0_n, h1, h1_n); - update_partition_flag(hap, &(hap->g_p), link, i); - ///update_partition_flag_debug(hap, &(hap->g_p), link, i); - } - - for (i = 0; i < hap->g_p.n; i++) - { - get_phased_block(&(hap->g_p), NULL, i, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); - hap->g_p.a[i].weight[0] = get_cluster_weight(hap, link, h0, h0_n); - hap->g_p.a[i].weight[1] = get_cluster_weight(hap, link, h1, h1_n); - hap->g_p.a[i].weight_convex = get_cluster_inner_weight(hap, link, h0, h0_n, h1, h1_n); - } - fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); -} - -uint32_t get_weightest_uid(uint32_t* a, uint32_t n, H_partition* hap, uint8_t* hap_label_flag, -uint32_t* max_hap_label) -{ - double cur_w0, cur_w1, max_weight; - uint32_t j, max_i, is_ava, hap_label; - - for (j = is_ava = 0, max_i = (uint32_t)-1; j < n; j++) - { - if(is_hap_set(a[j]>>1, *hap)) ///avoid repeat phasing - { - continue; - } - - get_weightest_hap_label_from_uid(a[j]>>1, hap, hap_label_flag, &hap_label, NULL); - - if(hap_label == (uint32_t)-1) - { - continue; - } - - if(get_related_weight(a[j]>>1, hap, &cur_w0, &cur_w1, &hap_label) > 0) - { - if(max_i == (uint32_t)-1) - { - max_i = j; - max_weight = cur_w0 + cur_w1; - (*max_hap_label) = hap_label; - } - else if((cur_w0 + cur_w1) > max_weight) - { - max_i = j; - max_weight = cur_w0 + cur_w1; - (*max_hap_label) = hap_label; - } - is_ava++; - } - } - - ///no useful unitig - if(is_ava == 0) - { - for (j = is_ava = 0, max_i = (uint32_t)-1; j < n; j++) - { - if(is_hap_set(a[j]>>1, *hap)) - { - continue; - } - - if(get_weightest_hap_label_from_uid(a[j]>>1, hap, NULL, &hap_label, NULL)==0) continue; - - if(get_related_weight(a[j]>>1, hap, &cur_w0, &cur_w1, &hap_label) > 0) - { - if(max_i == (uint32_t)-1) - { - max_i = j; - max_weight = cur_w0 + cur_w1; - (*max_hap_label) = hap_label; - } - else if((cur_w0 + cur_w1) > max_weight) - { - max_i = j; - max_weight = cur_w0 + cur_w1; - (*max_hap_label) = hap_label; - } - is_ava++; - } - } - } - if(max_i == (uint32_t)-1) return max_i; - - return a[max_i]>>1; -} - - -void get_weightest_hap_label_from_chain(ma_utg_t *u, H_partition* hap, bubble_type* bub, -uint32_t* max_hap_label, uint32_t* max_bid_idx, uint32_t* is_forward_first) -{ - (*max_hap_label) = (uint32_t)-1; - if(max_bid_idx) (*max_bid_idx) = 0; - if(is_forward_first) (*is_forward_first) = 1; - - if(u->n == 0) return; - kv_resize(double, hap->label_buffer, (hap->label>>hap->label_shift)+1);///how many group - hap->label_buffer.n = (hap->label>>hap->label_shift)+1; - uint32_t i, k, m, is_ava, a_n, *x_a, x_n, x; - uint64_t bid; - hc_edge* a = NULL; - for (i = 0; i < hap->label_buffer.n; i++) - { - hap->label_buffer.a[i] = 0;///count weight for each group - } - - for (k = is_ava = 0; k < u->n; k++) - { - bid = u->a[k]>>33; - ///bid might be bubble or non-bubble - get_bubbles(bub, bid, NULL, NULL, &x_a, &x_n, NULL); - for (m = 0; m < x_n; m++) - { - ///x is uid - x = x_a[m]>>1; - a_n = hap->link->a.a[x].e.n; - a = hap->link->a.a[x].e.a; - for (i = 0; i < a_n; i++) - { - if(a[i].del) continue; - if(is_hap_set(a[i].uID, *hap)) - { - hap->label_buffer.a[hap->hap[a[i].uID]>>hap->label_shift] += a[i].weight; - is_ava = 1; - } - } - } - } - - if(is_ava == 0) return; ///totally new chain - double max_weight; - uint32_t max_i; - ///select the best exsiting group to u - for (i = 0, max_weight = -1, max_i = (uint32_t)-1; i < hap->label_buffer.n; i++) - { - if(hap->label_buffer.a[i] > max_weight) - { - max_weight = hap->label_buffer.a[i]; - max_i = i; - } - } - - (*max_hap_label) = max_i<label_shift; - if(max_bid_idx) - { - double current_weight, tot_w = 0, half_w = 0; - for (k = 0, max_weight = -1, max_i = (uint32_t)-1; k < u->n; k++) - { - bid = u->a[k]>>33; - ///bid might be bubble or non-bubble - get_bubbles(bub, bid, NULL, NULL, &x_a, &x_n, NULL); - for (m = 0, current_weight = 0; m < x_n; m++) - { - x = x_a[m]>>1; - a_n = hap->link->a.a[x].e.n; - a = hap->link->a.a[x].e.a; - for (i = 0; i < a_n; i++) - { - if(a[i].del) continue; - if(is_hap_set_label(a[i].uID, *hap, *max_hap_label)) - { - current_weight += a[i].weight; - } - } - } - - if(current_weight > max_weight) /// the weight of each bubble - { - max_weight = current_weight; - max_i = k; - half_w = 0; - } - tot_w += current_weight; - half_w += current_weight; - } - - (*max_bid_idx) = max_i; - if(is_forward_first) - { - if(half_w >= (tot_w - half_w)) - { - (*is_forward_first) = 1; - } - else - { - (*is_forward_first) = 0; - } - } - } - - return; -} - -void phase_bubble_chain_dir(H_partition* hap, ma_ug_t *ug, bub_p_t_warp* b, bubble_type* bub, -ma_utg_t *u, uint8_t* hap_label_flag, uint32_t beg_idx, uint32_t end_idx, uint32_t is_forward) -{ - uint32_t i, j, beg, sink, *a, n, max_hap_label, max_uid; - uint64_t bid; - double cur_w0, cur_w1; - for (i = beg_idx; i <= end_idx; i++) - { - bid = is_forward? u->a[i]>>33:u->a[u->n-i-1]>>33; - get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); - - if(bub->b_g->seq[bid].c != HAP_LABLE/** && bid < bub->s_bub**/) ///simple bubble - { - for (j = 0; j < n; j++) ///avoiding repeat phasing - { - if(is_hap_set(a[j]>>1, *hap)) break; - } - - if(j < n) goto complete; - - ///get current max_hap_label from current chain - get_weightest_hap_label_from_bubble(bid, hap, bub, hap_label_flag, &max_hap_label, NULL); - - - ///three levels: - ///1. has setted weight with same hap label (using current max_hap_label) - ///2. has setted weight but with different hap labels (using max max_hap_label from current weight) - ///3. has unsetted weight (add hap->hap_label) - ///4. skip, do nothing - if(max_hap_label == (uint32_t)-1 && - get_weightest_hap_label_from_bubble(bid, hap, bub, NULL, &max_hap_label, NULL) == 0) - { - goto complete; - } - - ///phase bubble - b->exist_hap_label = (uint32_t)-1; - get_phase_path(ug, beg, sink, b, hap, max_hap_label); - get_phase_path(ug, beg, sink, b, hap, max_hap_label); - for (j = 0; j < n; j++) ///set bubble as visited - { - hap_label_flag[a[j]>>1] = 1; - } - } - else - { - ///select unitig with highest related weight at one time - while (1) - { - max_uid = get_weightest_uid(a, n, hap, hap_label_flag, &max_hap_label); - if(max_uid == (uint32_t)-1) break; - - get_related_weight(max_uid, hap, &cur_w0, &cur_w1, &max_hap_label); - if(cur_w0 >= cur_w1) - { - hap->hap[max_uid] |= (max_hap_label | hap->m[0]); - } - else - { - hap->hap[max_uid] |= (max_hap_label | hap->m[1]); - } - - hap_label_flag[max_uid] = 1; - } - } - - complete:; - } -} -///ignore unitigs wihci have already been labeled in current chain (might happen) -void phase_bubble_chain(H_partition* hap, ma_ug_t *ug, bub_p_t_warp* b, bubble_type* bub, - uint8_t* hap_label_flag, uint32_t chain_id) -{ - ma_utg_t *u = &(bub->b_ug->u.a[chain_id]); - if(u->n == 0) return; - uint32_t is_forward = 1, i, max_hap_label, max_bid_idx; - memset(hap_label_flag, 0, ug->g->n_seq); - - get_weightest_hap_label_from_chain(u, hap, bub, &max_hap_label, &max_bid_idx, &is_forward); - - if(max_hap_label != (uint32_t)-1) ///means this is not a new chain - { - for (i = 0; i < hap->n; i++) - { - if(is_hap_set_label(i, *hap, max_hap_label)) hap_label_flag[i] = 1; - } - } - - if(max_hap_label == (uint32_t)-1) ///a totally new chain - { - phase_bubble_chain_dir(hap, ug, b, bub, u, hap_label_flag, 0, u->n - 1, 1); - } - else - { - if(max_bid_idx == 0) - { - phase_bubble_chain_dir(hap, ug, b, bub, u, hap_label_flag, 0, u->n - 1, 1); - } - else - { - if(is_forward) - { - phase_bubble_chain_dir(hap, ug, b, bub, u, hap_label_flag, max_bid_idx, u->n - 1, 1); - phase_bubble_chain_dir(hap, ug, b, bub, u, hap_label_flag, 0, max_bid_idx-1, 0); - } - else - { - phase_bubble_chain_dir(hap, ug, b, bub, u, hap_label_flag, 0, max_bid_idx-1, 0); - phase_bubble_chain_dir(hap, ug, b, bub, u, hap_label_flag, max_bid_idx, u->n - 1, 1); - } - } - } -} - - -uint32_t if_flip(H_partition* h, G_partition* g_p, hc_links* link, -bubble_type* bub, uint32_t gid) -{ - double weight = 0; - if(h->lock[gid]) return 0; - if(g_p->a[gid].h[0] > 0 && (g_p->a[gid].status[0] == 1 || g_p->a[gid].status[0] == -1)) - { - weight += (g_p->a[gid].weight[0] * g_p->a[gid].status[0]); - } - - if(g_p->a[gid].h[1] > 0 && (g_p->a[gid].status[1] == 1 || g_p->a[gid].status[1] == -1)) - { - weight += (g_p->a[gid].weight[1] * g_p->a[gid].status[1]); - } - weight += g_p->a[gid].weight_convex*2; - if(weight >= 0) return 0; - return 1; -} -void flip_unitig(G_partition* g_p, hc_links* link, bubble_type* bub, uint32_t id); -uint32_t phasing_improvement(H_partition* h, G_partition* g_p, ha_ug_index* idx, bubble_type* bub, hc_links* link); -uint32_t get_max_unitig(H_partition* h, G_partition* g_p, hc_links* link, bubble_type* bub); -double get_cluster_weight_debug(G_partition* g_p, hc_links* link, uint32_t *h, uint32_t h_n); - -void debug_flip(G_partition* g_p, hc_links* link, bubble_type* bub, uint32_t id) -{ - fprintf(stderr, "33333333333\n"); - uint32_t *h0, h0_n, *h1, h1_n, k, wrong; - double hw0, hw1; - for (k = wrong = 0; k < g_p->n; k++) - { - hw0 = hw1 = 0; - get_phased_block(g_p, NULL, k, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); - if(h0_n >0) hw0 = get_cluster_weight_debug(g_p, link, h0, h0_n); - if(h1_n >0) hw1 = get_cluster_weight_debug(g_p, link, h1, h1_n); - if(hw0 != g_p->a[k].weight[0]) - { - if((uint32_t)hw0 != (uint32_t)g_p->a[k].weight[0]) wrong = 1; - fprintf(stderr, "k: %u, ERROR(id: %u): hw0: %f, weight[0]: %f\n", k, id, hw0, g_p->a[k].weight[0]); - } - - if(hw1 != g_p->a[k].weight[1]) - { - if((uint32_t)hw1 != (uint32_t)g_p->a[k].weight[1]) wrong = 1; - fprintf(stderr, "k: %u, ERROR(id: %u): hw1: %f, weight[1]: %f\n", k, id, hw1, g_p->a[k].weight[1]); - } - - if(wrong) break; - } -} -void merge_phase_group_by_chain(H_partition* hap, G_partition* g_p, bubble_type* bub, uint32_t chain_id) -{ - uint32_t i, k; - uint32_t beg, sink, *a, n, pre_id, hap_label_id; - uint64_t bid, uid; - ma_utg_t *u = &(bub->b_ug->u.a[chain_id]); - - for (i = 0, pre_id = (uint32_t)-1; i < u->n; i++) - { - // fprintf(stderr, "inner i: %u, u->n: %u\n", i, (uint32_t)u->n); - bid = u->a[i]>>33; ///here is a bubble - // fprintf(stderr, "bid: %lu\n", bid); - get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); - for (k = 0; k < n; k++) - { - // fprintf(stderr, "k: %u, n: %u\n", k, n); - uid = a[k]>>1; - // fprintf(stderr, "uid: %lu\n", uid); - if(g_p->index[uid] == (uint32_t)-1) ///mean this unitig doesn't have hap label - { - pre_id = (uint32_t)-1; - continue; - } - hap_label_id = g_p->index[uid]>>1; - // fprintf(stderr, "hap_label_id: %u, hap->n: %lu\n", hap_label_id, hap->n); - if(hap_label_id == pre_id) continue; - pre_id = hap_label_id; - if(hap->lock[hap_label_id] == 1) continue; - if(if_flip(hap, g_p, hap->link, bub, hap_label_id)) - { - // fprintf(stderr, "2222222222\n"); - flip_unitig(g_p, hap->link, bub, hap_label_id); - ///debug_flip(g_p, hap->link, bub, hap_label_id); - } - } - } -} - -void print_phase_group(G_partition* g_p, bubble_type* bub, const char* command) -{ - uint32_t i, k; - partition_warp *res = NULL; - for (i = 0; i < g_p->n; i++) - { - res = &(g_p->a[i]); - fprintf(stderr, "\n%s: %u-th group: # %d = %u (weight: %f), # %d = %u (weight: %f), inner_weight: %f\n", command, i, - res->status[0], res->h[0], res->weight[0], res->status[1], res->h[1], res->weight[1], res->weight_convex); - for (k = 0; k < res->h[0]; k++) - { - fprintf(stderr, "%d: utg%.6ul\n", res->status[0], int(res->a.a[k]+1)); - } - - for (; k < res->a.n; k++) - { - fprintf(stderr, "%d: utg%.6ul\n", res->status[1], int(res->a.a[k]+1)); - } - } -} - -void set_bubble(H_partition* hap, G_partition* g_p, bubble_type* bub, block_phase_type* block, -uint64_t bid) -{ - uint32_t beg, sink, k, uid, *a, n, gid; - block->weight = 0; - get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); - for (k = 0; k < n; k++) - { - uid = a[k]>>1; - if(g_p->index[uid] == (uint32_t)-1) continue; - gid = g_p->index[uid]>>1; - block->vis.a[gid] = 1; - } -} - -uint32_t next_hap_label_id(block_phase_type* b, G_partition* g_p, bubble_type* bub, ma_utg_t *u, -int is_forward, long long* c_bid, long long* c_uid) -{ - uint32_t beg, sink, uid, *a, n, gid, pre_gid; - while (1) ///while(b->bid < (long long)u->n) - { - if(is_forward == 1 && b->bid >= (long long)u->n) break; - if(is_forward == 0 && b->bid < 0) break; - - get_bubbles(bub, u->a[b->bid]>>33, &beg, &sink, &a, &n, NULL); - while (1) ///while (b->uid < (long long)n) - { - if(is_forward == 1 && b->uid >= (long long)n) break; - if(is_forward == 0 && b->uid < 0) break; - - uid = a[b->uid]>>1; - gid = (uint32_t)-1; - if(g_p->index[uid] != (uint32_t)-1) - { - gid = g_p->index[uid]>>1; - } - if(c_bid) (*c_bid) = b->bid; - if(c_uid) (*c_uid) = b->uid; - - if(is_forward == 1) b->uid++; - if(is_forward == 0) b->uid--; - if(gid == (uint32_t)-1) continue; - - - pre_gid = uid = (uint32_t)-1; - if(is_forward == 1 && (b->uid >= 2)) uid = a[b->uid - 2]>>1; - if(is_forward == 0 && (b->uid + 2 < n)) uid = a[b->uid + 2]>>1; - if(uid != (uint32_t)-1 && g_p->index[uid] != (uint32_t)-1) pre_gid = g_p->index[uid]>>1; - - if(pre_gid == gid) continue; - - return gid; - } - - if(is_forward == 1) b->bid++, b->uid = 0; - if(is_forward == 0) b->bid--, b->uid = (long long)n - (long long)1; - } - - return (uint32_t)-1; -} - -double get_new_weight(G_partition* g_p, uint8_t* flag, hc_links* link, uint32_t gid) -{ - double total_weight = 0, weight; - int status, o_d; - uint32_t *h0, h0_n, *h1, h1_n, *h, h_n, j, k, uID; - - if(g_p->a[gid].h[0] > 0 && (g_p->a[gid].status[0] == 1 || g_p->a[gid].status[0] == -1)) - { - total_weight += (g_p->a[gid].weight[0] * g_p->a[gid].status[0]); - } - - if(g_p->a[gid].h[1] > 0 && (g_p->a[gid].status[1] == 1 || g_p->a[gid].status[1] == -1)) - { - total_weight += (g_p->a[gid].weight[1] * g_p->a[gid].status[1]); - } - total_weight += g_p->a[gid].weight_convex*2; - - - - get_phased_block(g_p, NULL, gid, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); - - h = h0; h_n = h0_n; status = g_p->a[gid].status[0]; - for (j = 0, weight = 0; j < h_n; j++) - { - for (k = 0; k < link->a.a[h[j]].e.n; k++) - { - if(link->a.a[h[j]].e.a[k].del) continue; - uID = link->a.a[h[j]].e.a[k].uID; - if(g_p->index[uID] == (uint32_t)-1) continue; - if(flag[g_p->index[uID]>>1] == 0) continue; - if((g_p->index[uID]>>1) == gid) continue; - o_d = g_p->a[g_p->index[uID]>>1].status[g_p->index[uID]&1]; - weight += (status*o_d*link->a.a[h[j]].e.a[k].weight); - } - } - total_weight -= (2*weight); - - - - - h = h1; h_n = h1_n; status = g_p->a[gid].status[1]; - for (j = 0, weight = 0; j < h_n; j++) - { - for (k = 0; k < link->a.a[h[j]].e.n; k++) - { - if(link->a.a[h[j]].e.a[k].del) continue; - uID = link->a.a[h[j]].e.a[k].uID; - if(g_p->index[uID] == (uint32_t)-1) continue; - if(flag[g_p->index[uID]>>1] == 0) continue; - if((g_p->index[uID]>>1) == gid) continue; - o_d = g_p->a[g_p->index[uID]>>1].status[g_p->index[uID]&1]; - weight += (status*o_d*link->a.a[h[j]].e.a[k].weight); - } - } - total_weight -= (2*weight); - - - - return total_weight; -} - -int identify_best_interval(block_phase_type* i_buf, uint8_t* lock, G_partition* g_p, bubble_type* bub, -ma_utg_t *u, hc_links* link, long long f_bid, long long f_uid, long long* l_bid, long long* l_uid) -{ - long long c_bid, c_uid, min_bid, min_uid; - double w = 0, min_w = 1; - uint32_t gid, val = 0; - block_phase_type b; - b.bid = f_bid; b.uid = f_uid; - memset(i_buf->vis.a, 0, g_p->n); - i_buf->weight = min_w = 1; min_bid = min_uid = -1; - (*l_bid) = (*l_uid) = -1; - - while (1) - { - gid = next_hap_label_id(&b, g_p, bub, u, 1, &c_bid, &c_uid); - if(gid == (uint32_t)-1) break; - if(i_buf->vis.a[gid] == 1) continue; - w += get_new_weight(g_p, i_buf->vis.a, link, gid); - i_buf->vis.a[gid] = 1; - if(lock[gid] == 0) val = 1; - if(val == 0) continue; - - if(min_w > w) - { - min_w = w; - min_bid = c_bid; - min_uid = c_uid; - } - } - - if(min_w < 0 && min_bid != -1 && min_uid != -1) - { - (*l_bid) = min_bid; (*l_uid) = min_uid; - i_buf->weight = min_w; - ///fprintf(stderr, "+min_w: %f, min_bid: %lld, min_uid: %lld\n", min_w, min_bid, min_uid); - } - - if(val == 0) return 1; - - return 0; -} - -void identify_best_interval_debug(block_phase_type* i_buf, G_partition* g_p, bubble_type* bub, -ma_utg_t *u, hc_links* link, long long f_bid, long long f_uid, long long* l_bid, long long* l_uid) -{ - long long c_bid, c_uid, min_bid, min_uid; - double w = 0, min_w = 1; - uint32_t gid; - block_phase_type b; - b.bid = f_bid; b.uid = f_uid; - memset(i_buf->vis.a, 0, g_p->n); - min_w = 1; min_bid = min_uid = -1; - (*l_bid) = (*l_uid) = -1; - - while (1) - { - gid = next_hap_label_id(&b, g_p, bub, u, 1, &c_bid, &c_uid); - if(gid == (uint32_t)-1) break; - if(i_buf->vis.a[gid] == 1) continue; - w += get_new_weight(g_p, i_buf->vis.a, link, gid); - if(f_bid == 689 && f_uid == 1) - { - fprintf(stderr, "gid: %u, w: %f\n", gid, w); - } - - if(min_w > w) - { - min_w = w; - min_bid = c_bid; - min_uid = c_uid; - } - i_buf->vis.a[gid] = 1; - } - - if(min_w < 0 && min_bid != -1 && min_uid != -1) - { - (*l_bid) = min_bid; (*l_uid) = min_uid; - i_buf->weight = min_w; - b.bid = min_bid; b.uid = min_uid; - - - gid = next_hap_label_id(&b, g_p, bub, u, 1, &c_bid, &c_uid); - fprintf(stderr, "-min_w: %f, f_bid: %lld, f_uid: %lld, min_bid: %lld, min_uid: %lld, gid: %u\n", - min_w, f_bid, f_uid, min_bid, min_uid, gid); - - } -} - -int flip_block(block_phase_type* i_buf, G_partition* g_p, bubble_type* bub, -ma_utg_t *u, hc_links* link, uint8_t* lock, long long f_bid, long long f_uid, long long l_bid, long long l_uid) -{ - long long c_bid = l_bid, c_uid = l_uid; - uint32_t gid, val = 0; - block_phase_type b; - b.bid = f_bid; b.uid = f_uid; - memset(i_buf->vis.a, 0, g_p->n); - val = 0; - while (1) - { - gid = next_hap_label_id(&b, g_p, bub, u, 1, &c_bid, &c_uid); - ////fprintf(stderr, "+gid: %u\n", gid); - if(gid == (uint32_t)-1) break; - ///fprintf(stderr, "lock[gid]: %u\n", lock[gid]); - if(lock[gid] == 0) - { - val = 1; - break; - } - if(c_bid == l_bid && c_uid == l_uid) break; - } - - if(val == 0) return 0; - - b.bid = f_bid; b.uid = f_uid; - while (1) - { - gid = next_hap_label_id(&b, g_p, bub, u, 1, &c_bid, &c_uid); - ///fprintf(stderr, "-gid: %u\n", gid); - if(gid == (uint32_t)-1) break; - ///fprintf(stderr, "vis[gid]: %u\n", i_buf->vis.a[gid]); - if(i_buf->vis.a[gid] == 1) continue; - lock[gid] = 1; - i_buf->vis.a[gid] = 1; - // if(f_bid == 689 && f_uid == 1) - // { - // fprintf(stderr, "sssssssssssssssssssss\n"); - // print_phase_group(g_p, bub, "Small-1"); - // fprintf(stderr, "sbsbsbsb-gid: %u\n", gid); - // } - flip_unitig(g_p, link, bub, gid); - ///flip_unitig_debug(g_p, link, bub, gid); - // if(f_bid == 689 && f_uid == 1) - // { - // fprintf(stderr, "sasasasa-gid: %u\n", gid); - // print_phase_group(g_p, bub, "Small-2"); - // fprintf(stderr, "eeeeeeeeeeeeeeeeeeeeee\n"); - // } - if(c_bid == l_bid && c_uid == l_uid) break; - } - - return 1; -} - -double get_total_weight(H_partition* h, G_partition* g_p) -{ - uint32_t i, k, uID; - hc_links* link = h->link; - int o_d = 0, o_f = 0; - double w, t_w; - for (i = 0, t_w = 0; i < h->n; i++) - { - if(g_p->index[i] == (uint32_t)-1) continue; - o_f = g_p->a[g_p->index[i]>>1].status[g_p->index[i]&1]; - for (k = 0; k < link->a.a[i].e.n; k++) - { - if(link->a.a[i].e.a[k].del) continue; - uID = link->a.a[i].e.a[k].uID; - w = link->a.a[i].e.a[k].weight; - if(g_p->index[uID] == (uint32_t)-1) continue; - o_d = g_p->a[g_p->index[uID]>>1].status[g_p->index[uID]&1]; - t_w += (o_f*o_d*w); - } - } - - return t_w; -} - -void hap_label_fliping(H_partition* hap, G_partition* g_p, bubble_type* bub, hc_links* link, uint32_t chain_id) -{ - long long c_bid, c_uid, l_bid, l_uid; - uint32_t gid; - ma_utg_t *u = &(bub->b_ug->u.a[chain_id]); - hap->b.bid = hap->b.uid = 0; - while (1) - { - gid = next_hap_label_id(&(hap->b), g_p, bub, u, 1, &c_bid, &c_uid); - if(gid == (uint32_t)-1) break; - identify_best_interval(&(hap->b), hap->lock, g_p, bub, u, link, c_bid, c_uid, &l_bid, &l_uid); - if(l_bid == -1 || l_uid == -1) continue; - - // fprintf(stderr, "\nbefore weight: %f\n", get_total_weight(hap, g_p)); - // identify_best_interval_debug(&(hap->b), g_p, bub, u, link, c_bid, c_uid, &l_bid, &l_uid); - if(flip_block(&(hap->b), g_p, bub, u, link, hap->lock, c_bid, c_uid, l_bid, l_uid)) - { - ///fprintf(stderr, "after weight +: %f\n", get_total_weight(hap, g_p)); - hap->b.bid = l_bid; - hap->b.uid = l_uid; - gid = next_hap_label_id(&(hap->b), g_p, bub, u, 1, &c_bid, &c_uid); - if(gid == (uint32_t)-1) break; - } - ///fprintf(stderr, "after weight -: %f\n", get_total_weight(hap, g_p)); - // exit(0); - } -} - -typedef struct{ - long long min_chain_id; - long long min_f_bid; - long long min_f_uid; - long long min_l_bid; - long long min_l_uid; - long long min_idx; - double min_w; -}block_res_type; - -typedef struct{ - block_phase_type* x; - uint32_t n_thread; - bubble_type* bub; - uint64_t* chain_idx;///index of each chain - uint64_t chain_idx_n; - uint64_t chain_ele_occ; - block_res_type* res; - H_partition* h; - G_partition* g_p; -}mul_block_phase_type; - -uint32_t shift_block_phase_type(ma_utg_t *u, G_partition* g_p, bubble_type* bub, -block_phase_type* b, uint32_t offset) -{ - long long c_bid, c_uid; - uint32_t gid, occ = 0; - b->bid = b->uid = 0; - while (1) - { - if(occ == offset) break; - gid = next_hap_label_id(b, g_p, bub, u, 1, &c_bid, &c_uid); - if(gid == (uint32_t)-1) break; - occ++; - } - return occ; -} - -void get_block_phase_type(uint64_t* chain_idx, G_partition* g_p, bubble_type* bub, uint32_t id, block_phase_type* i_b) -{ - uint64_t i; - ma_utg_t *u = NULL; - for (i = 0; i < bub->chain_weight.n; i++) - { - if(id >= chain_idx[i] && id < chain_idx[i+1]) break; - } - - u = &(bub->b_ug->u.a[bub->chain_weight.a[i].id]); - shift_block_phase_type(u, g_p, bub, i_b, id - chain_idx[i]); - i_b->chainID = bub->chain_weight.a[i].id; -} - -void init_mul_block_phase_type(mul_block_phase_type* x, G_partition* g_p, bubble_type* bub, uint32_t n_thread, H_partition* hap) -{ - ma_utg_t *u = NULL; - uint32_t i, n; - block_phase_type b; - x->bub = bub; - x->n_thread = n_thread; - CALLOC(x->res, x->n_thread); - CALLOC(x->x, x->n_thread); - for (i = 0; i < x->n_thread; i++) - { - kv_init(x->x[i].vis); - kv_malloc(x->x[i].vis, hap->n); - x->x[i].vis.n = hap->n; - } - - x->chain_idx_n = 0; - MALLOC(x->chain_idx, bub->chain_weight.n+1); - for (i = n = 0; i < bub->chain_weight.n; i++) - { - x->chain_idx[i] = n; - if(bub->chain_weight.a[i].del) continue; - u = &(bub->b_ug->u.a[bub->chain_weight.a[i].id]); - n += shift_block_phase_type(u, g_p, bub, &b, (uint32_t)-1); - x->chain_idx_n++; - } - x->chain_idx[i] = n;///index of chain - x->chain_ele_occ = n; -} - -void destory_mul_block_phase_type(mul_block_phase_type* x) -{ - uint32_t i; - free(x->res); - free(x->chain_idx); - for (i = 0; i < x->n_thread; i++) - { - kv_destroy(x->x[i].vis); - } -} - -void select_max_block_by_utg_multi_thread(H_partition* h, G_partition* g_p, bubble_type* bub, -hc_links* link, block_phase_type* i_b, uint64_t* chain_idx, uint32_t id, block_res_type* res) -{ - long long c_bid, c_uid, l_bid, l_uid; - uint32_t gid; - get_block_phase_type(chain_idx, g_p, bub, id, i_b); - - ma_utg_t *u = &(bub->b_ug->u.a[i_b->chainID]); - - gid = next_hap_label_id(i_b, g_p, bub, u, 1, &c_bid, &c_uid); - - if(gid == (uint32_t)-1) return; - if(identify_best_interval(i_b, h->lock, g_p, bub, u, link, c_bid, c_uid, &l_bid, &l_uid)) return; - if(l_bid == -1 || l_uid == -1) return; - - if((res->min_w > i_b->weight) || (res->min_w == i_b->weight && id < res->min_idx)) - { - res->min_w = i_b->weight; - res->min_f_bid = c_bid; - res->min_f_uid = c_uid; - res->min_l_bid = l_bid; - res->min_l_uid = l_uid; - res->min_chain_id = i_b->chainID; - res->min_idx = id; - } -} - -static void worker_for_max_block(void *data, long i, int tid) // callback for kt_for() -{ - mul_block_phase_type* x = (mul_block_phase_type*)data; - select_max_block_by_utg_multi_thread(x->h, x->g_p, x->bub, x->h->link, - &(x->x[tid]), x->chain_idx, i, &(x->res[tid])); -} - -void select_max_block_by_utg_multi_thread_by_chain(H_partition* h, G_partition* g_p, bubble_type* bub, -hc_links* link, block_phase_type* i_b, uint32_t id, block_res_type* res) -{ - long long c_bid, c_uid, l_bid, l_uid; - uint32_t gid; - ma_utg_t *u = &(bub->b_ug->u.a[id]); - i_b->bid = i_b->uid = 0; i_b->chainID = id; - while (1) - { - gid = next_hap_label_id(i_b, g_p, bub, u, 1, &c_bid, &c_uid); - if(gid == (uint32_t)-1) break; - - if(identify_best_interval(i_b, h->lock, g_p, bub, u, link, c_bid, c_uid, &l_bid, &l_uid)) - { - break; - } - if(l_bid == -1 || l_uid == -1) continue; - if(res->min_w > i_b->weight) - { - res->min_w = i_b->weight; - res->min_f_bid = c_bid; - res->min_f_uid = c_uid; - res->min_l_bid = l_bid; - res->min_l_uid = l_uid; - res->min_chain_id = i_b->chainID; - res->min_idx = id; - } - } -} - - -int get_max_block_multi_thread(H_partition* h, G_partition* g_p, bubble_type* bub, mul_block_phase_type* x, -long long* min_u, long long* min_f_bid, long long* min_f_uid, long long* min_l_bid, long long* min_l_uid, -double* min_w) -{ - uint32_t i; - (*min_w) = 1; - (*min_u) = (*min_f_bid) = (*min_f_uid) = (*min_l_bid) = (*min_l_uid) = -1; - for (i = 0; i < x->n_thread; i++) - { - x->res[i].min_chain_id = x->res[i].min_f_bid = x->res[i].min_f_uid = -1; - x->res[i].min_l_bid = x->res[i].min_l_uid = x->res[i].min_idx = -1; - x->res[i].min_w = 1; - } - x->g_p = g_p; - x->h = h; - kt_for(x->n_thread, worker_for_max_block, x, x->chain_ele_occ); - ///kt_for(x->n_thread, worker_for_max_block_by_chain, x, x->chain_idx_n); - - long long min_idx = -1; - for (i = 0; i < x->n_thread; i++) - { - if(x->res[i].min_chain_id == -1) continue; - if(x->res[i].min_f_bid == -1 || x->res[i].min_f_uid == -1) continue; - if(x->res[i].min_l_bid == -1 || x->res[i].min_l_uid == -1) continue; - if(((*min_w) > x->res[i].min_w) || ((*min_w) == x->res[i].min_w && x->res[i].min_idx < min_idx)) - { - (*min_w) = x->res[i].min_w; - (*min_u) = x->res[i].min_chain_id; - (*min_f_bid) = x->res[i].min_f_bid; - (*min_f_uid) = x->res[i].min_f_uid; - (*min_l_bid) = x->res[i].min_l_bid; - (*min_l_uid) = x->res[i].min_l_uid; - min_idx = x->res[i].min_idx; - } - } - - if((*min_u) != -1 && (*min_f_bid) != -1 && (*min_f_uid) != -1 && (*min_l_bid) != -1 && (*min_l_uid) != -1) - { - return 1; - } - - return 0; -} - -void select_max_block_by_utg(H_partition* hap, G_partition* g_p, bubble_type* bub, hc_links* link, uint32_t chain_id, -long long* min_f_bid, long long* min_f_uid, long long* min_l_bid, long long* min_l_uid, double* min_w) -{ - long long c_bid, c_uid, l_bid, l_uid; - uint32_t gid; - ma_utg_t *u = &(bub->b_ug->u.a[chain_id]); - (*min_w) = 1; - hap->b.bid = hap->b.uid = 0; - (*min_f_bid) = (*min_f_uid) = (*min_l_bid) = (*min_l_uid) = -1; - while (1) - { - gid = next_hap_label_id(&(hap->b), g_p, bub, u, 1, &c_bid, &c_uid); - if(gid == (uint32_t)-1) break; - - if(identify_best_interval(&(hap->b), hap->lock, g_p, bub, u, link, c_bid, c_uid, &l_bid, &l_uid)) - { - break; - } - if(l_bid == -1 || l_uid == -1) continue; - if((*min_w) > hap->b.weight) - { - (*min_w) = hap->b.weight; - (*min_f_bid) = c_bid; - (*min_f_uid) = c_uid; - (*min_l_bid) = l_bid; - (*min_l_uid) = l_uid; - } - } -} - - -int get_max_block(H_partition* h, G_partition* g_p, bubble_type* bub, long long* min_u, -long long* min_f_bid, long long* min_f_uid, long long* min_l_bid, long long* min_l_uid, -double* min_w) -{ - uint32_t i; - long long f_bid, f_uid, l_bid, l_uid; - double w; - (*min_w) = 1; - (*min_u) = (*min_f_bid) = (*min_f_uid) = (*min_l_bid) = (*min_l_uid) = -1; - for (i = 0; i < bub->chain_weight.n; i++) - { - if(bub->chain_weight.a[i].del) continue; - select_max_block_by_utg(h, g_p, bub, h->link, bub->chain_weight.a[i].id, - &f_bid, &f_uid, &l_bid, &l_uid, &w); - if(f_bid == -1 || f_uid == -1 || l_bid == -1 || l_uid == -1) continue; - if((*min_w) > w) - { - (*min_w) = w; - (*min_u) = bub->chain_weight.a[i].id; - (*min_f_bid) = f_bid; - (*min_f_uid) = f_uid; - (*min_l_bid) = l_bid; - (*min_l_uid) = l_uid; - } - } - - if((*min_u) != -1 && (*min_f_bid) != -1 && (*min_f_uid) != -1 && (*min_l_bid) != -1 && (*min_l_uid) != -1) - { - return 1; - } - - return 0; -} - -void phasing_improvement_by_block(H_partition* h, G_partition* g_p, bubble_type* bub, mul_block_phase_type* x) -{ - long long min_u, min_f_bid, min_f_uid, min_l_bid, min_l_uid; - double min_w; - - memset(h->lock, 0, sizeof(uint8_t)*h->n); - while(get_max_block_multi_thread(h, g_p, bub, x, &min_u, &min_f_bid, &min_f_uid, &min_l_bid, &min_l_uid, &min_w)) - ///while(get_max_block(h, g_p, bub, &min_u, &min_f_bid, &min_f_uid, &min_l_bid, &min_l_uid, &min_w)) - { - ///fprintf(stderr, "\nmin_w: %f, min_u: %lld, min_f_bid: %lld, min_f_uid: %lld, min_l_bid: %lld, min_l_uid: %lld\n", min_w, min_u, min_f_bid, min_f_uid, min_l_bid, min_l_uid); - ///fprintf(stderr, "before weight: %f\n", get_total_weight(h, g_p)); - flip_block(&(h->b), g_p, bub, &(bub->b_ug->u.a[min_u]), h->link, h->lock, min_f_bid, - min_f_uid, min_l_bid, min_l_uid); - ///fprintf(stderr, "after weight: %f\n", get_total_weight(h, g_p)); - } -} - -void flip_by_chain(H_partition* h, G_partition* g_p, bubble_type* bub) -{ - uint32_t i; - memset(h->lock, 0, sizeof(uint8_t)*h->n); - for (i = 0; i < bub->chain_weight.n; i++) - { - if(bub->chain_weight.a[i].del) continue; - merge_phase_group_by_chain(h, g_p, bub, bub->chain_weight.a[i].id); - } - - double pre_w = get_total_weight(h, g_p), current_w; - uint32_t round = 0; - while (1) - { - memset(h->lock, 0, sizeof(uint8_t)*h->n); - while (1) - { - i = get_max_unitig(h, g_p, h->link, bub); - if(i == (uint32_t)-1) break; - h->lock[i] = 1; - flip_unitig(g_p, h->link, bub, i); - } - current_w = get_total_weight(h, g_p); - ///fprintf(stderr, "[M::%s::round %u, pre_w: %f, current_w: %f]\n", __func__, round, pre_w, current_w); - if(ceil(current_w) <= ceil(pre_w)) break; - round++; - pre_w = current_w; - } - - - ///print_phase_group(g_p, bub, "Large-pre"); - - ///fprintf(stderr, "[M::%s::round %u, before block flipping: %f]\n", __func__, round, get_total_weight(h, g_p)); - - mul_block_phase_type b_x; - init_mul_block_phase_type(&b_x, g_p, bub, asm_opt.thread_num, h); - - pre_w = get_total_weight(h, g_p); - while (1) - { - phasing_improvement_by_block(h, g_p, bub, &b_x); - current_w = get_total_weight(h, g_p); - ///fprintf(stderr, "[M::%s::round %u, after block flipping: %f]\n", __func__, round, get_total_weight(h, g_p)); - ///debug_flip(g_p, h->link, bub, 0); - if(ceil(current_w) <= ceil(pre_w)) break; - round++; - pre_w = current_w; - } - destory_mul_block_phase_type(&b_x); - - for (i = 0; i < g_p->n; i++) - { - update_partition_flag(h, g_p, h->link, i); - } -} - -void flip_by_node(H_partition* h, G_partition* g_p, bubble_type* bub) -{ - uint32_t i; - memset(h->lock, 0, sizeof(uint8_t)*h->n); - - - double pre_w = get_total_weight(h, g_p), current_w; - uint32_t round = 0; - while (1) - { - memset(h->lock, 0, sizeof(uint8_t)*h->n); - while (1) - { - i = get_max_unitig(h, g_p, h->link, bub); - if(i == (uint32_t)-1) break; - h->lock[i] = 1; - flip_unitig(g_p, h->link, bub, i); - } - current_w = get_total_weight(h, g_p); - ///fprintf(stderr, "[M::%s::round %u, pre_w: %f, current_w: %f]\n", __func__, round, pre_w, current_w); - if(ceil(current_w) <= ceil(pre_w)) break; - round++; - pre_w = current_w; - } - - ///fprintf(stderr, "[M::%s::round %u, before block flipping: %f]\n", __func__, round, get_total_weight(h, g_p)); - - for (i = 0; i < g_p->n; i++) - { - update_partition_flag(h, g_p, h->link, i); - } -} - - -void link_phase_group(H_partition* hap, bubble_type* bub) -{ - double index_time = yak_realtime(); - uint32_t i, k, n = (hap->label>>hap->label_shift)+1, *h0, h0_n, *h1, h1_n;; - init_G_partition(&(hap->group_g_p), hap->n); - partition_warp *res = NULL; - for (i = 0; i < n; i++)///how many haplotype group - { - kv_pushp(partition_warp, hap->group_g_p, &res); - kv_init(res->a); - res->full_bub = 0; - res->h[0] = res->h[1] = 0; - res->status[0] = 1; res->status[1] = -1; - res->weight[0] = res->weight[1] = res->weight_convex = 0; - ///all unitigs - for (k = 0; k < hap->n; k++) - { - if(get_phase_group(hap, k) == i && get_phase_status(hap, k) == 1) - { - kv_push(uint32_t, res->a, k); - res->h[0]++; - } - } - - for (k = 0; k < hap->n; k++) - { - if(get_phase_group(hap, k) == i && get_phase_status(hap, k) == -1) - { - kv_push(uint32_t, res->a, k); - res->h[1]++; - } - } - - for (k = 0; k < res->h[0]; k++) - { - ///if(hap->group_g_p.index[res->a.a[k]] != (uint32_t)-1) fprintf(stderr, "ERROR---00\n"); - hap->group_g_p.index[res->a.a[k]] = hap->group_g_p.n-1; - hap->group_g_p.index[res->a.a[k]] = hap->group_g_p.index[res->a.a[k]] << 1; - } - - for (; k < res->a.n; k++) - { - ///if(hap->group_g_p.index[res->a.a[k]] != (uint32_t)-1) fprintf(stderr, "ERROR---11\n"); - hap->group_g_p.index[res->a.a[k]] = hap->group_g_p.n-1; - hap->group_g_p.index[res->a.a[k]] = (hap->group_g_p.index[res->a.a[k]] << 1) + 1; - } - - get_phased_block(&(hap->group_g_p), NULL, i, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); - if(h0_n >0) res->weight[0] = get_cluster_weight(hap, hap->link, h0, h0_n); - if(h1_n >0) res->weight[1] = get_cluster_weight(hap, hap->link, h1, h1_n); - res->weight_convex = get_cluster_inner_weight(hap, hap->link, h0, h0_n, h1, h1_n); - } - - fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); - // for (i = 0; i < n; i++) - // { - // double w0 = 0, w1 = 0; - // res = &(hap->group_g_p.a[i]); - // fprintf(stderr, "%u-th group: # %d = %u, # %d = %u\n", i, - // res->status[0], res->h[0], res->status[1], res->h[1]); - // get_phased_block(&(hap->group_g_p), NULL, i, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); - // if(h0_n >0) w0 = get_cluster_weight_debug(&(hap->group_g_p), hap->link, h0, h0_n); - // if(h1_n >0) w1 = get_cluster_weight_debug(&(hap->group_g_p), hap->link, h1, h1_n); - // if(w0 != res->weight[0]) fprintf(stderr, "i: %u, ERROR: w0: %f, weight[0]: %f\n", i, w0, res->weight[0]); - // if(w1 != res->weight[1]) fprintf(stderr, "i: %u, ERROR: w1: %f, weight[1]: %f\n", i, w1, res->weight[1]); - - - // for (k = 0; k < res->h[0]; k++) - // { - // fprintf(stderr, "%d: utg%.6ul\n", res->status[0], int(res->a.a[k]+1)); - // } - - // for (; k < res->a.n; k++) - // { - // fprintf(stderr, "%d: utg%.6ul\n", res->status[1], int(res->a.a[k]+1)); - // } - // } - - /*******************************for debug************************************/ - // for (i = 0; i < hap->n; i++) - // { - // if(hap->link->a.a[i].e.n == 0) continue; - // if(get_phase_status(hap, i) == -2) - // { - // fprintf(stderr, "ERROR+++: i: %u, group: %u, bub->index: %u\n", i, get_phase_group(hap, i), bub->index[i]); - // for (k = 0; k < hap->link->a.a[i].e.n; k++) - // { - // fprintf(stderr, "k: %u, uID: %u, weight: %f, del: %u\n", k, hap->link->a.a[i].e.a[k].uID, - // hap->link->a.a[i].e.a[k].weight, hap->link->a.a[i].e.a[k].del); - // } - // } - // } - /*******************************for debug************************************/ - - - flip_by_chain(hap, &(hap->group_g_p), bub); - ///print_phase_group(&(hap->group_g_p), bub, "Large"); -} - -void print_chain_phasing(H_partition* hap, ma_ug_t *ug, bubble_type* bub, uint32_t chain_id) -{ - uint32_t i, k; - uint32_t beg, sink, *a, n; - uint64_t bid, uid; - ma_utg_t *u = &(bub->b_ug->u.a[chain_id]); - fprintf(stderr, "\n**********chain_id: %u**********\n", chain_id); - for (i = 0; i < u->n; i++) - { - bid = u->a[i]>>33; - fprintf(stderr, "(%u) chain_id: %u, u->n: %u, bid: %u\n", i, chain_id, (uint32_t)u->n, i); - get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); - for (k = 0; k < n; k++) - { - uid = a[k]>>1; - fprintf(stderr, "utg%.6ul, hap: %u, group: %u, stats: %d\n", (int)(uid+1), hap->hap[uid], - get_phase_group(hap, uid), get_phase_status(hap, uid)); - } - } -} - -int graph_bipartiteness(uint32_t* b_a, uint32_t b_a_n, uint8_t *color, hc_links* link, kvec_t_u32_warp* stack) -{ - if(b_a_n == 0) return 0; - uint32_t i, uID, cur, occ = 0, sucess = 0, c; - for (i = 0; i < b_a_n; i++) color[b_a[i]>>1] = 8; - stack->a.n = 0; - kv_push(uint32_t, stack->a, b_a[0]>>1); - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - if((color[cur] & 1) == 0) occ++; - color[cur] |= 1; - for (i = 0; i < link->a.a[cur].f.n; i++) - { - if(link->a.a[cur].f.a[i].del) continue; - if(link->a.a[cur].f.a[i].dis != RC_0) continue; - uID = link->a.a[cur].f.a[i].uID; - if((color[uID] & 8) == 0) continue; - if((color[uID] & 1) == 1) continue; - kv_push(uint32_t, stack->a, uID); - } - } - if(occ != b_a_n) goto Failed; - - sucess = 1; - for (i = 0; i < b_a_n; i++) color[b_a[i]>>1] = 8; - stack->a.n = 0; - kv_push(uint32_t, stack->a, b_a[0]>>1); - color[b_a[0]>>1] |= 2;///colored - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - color[cur] |= 1; - c = color[cur] & 4; ///get color - for (i = 0; i < link->a.a[cur].f.n; i++) - { - if(link->a.a[cur].f.a[i].del) continue; - if(link->a.a[cur].f.a[i].dis != RC_0) continue; - uID = link->a.a[cur].f.a[i].uID; - if((color[uID] & 8) == 0) continue; - if((color[uID] & 2) && ((color[uID] & 4) == c)) break; ///conflict - if((color[uID] & 1) == 1) continue; - kv_push(uint32_t, stack->a, uID); - color[uID] |= 2; color[uID] |= (c^4); - } - - if(i != link->a.a[cur].f.n) - { - sucess = -1; - break; - } - } - - Failed: - if(sucess != 1) - { - for (i = 0; i < b_a_n; i++) color[b_a[i]>>1] = 0; - } - - return sucess; -} - -void assign_per_unitig_G_partition(G_partition* g_p, uint64_t hap_n, hc_links* link, bubble_type* bub, -uint32_t bubble_first) -{ - double index_time = yak_realtime(); - reset_G_partition(g_p, hap_n); - - partition_warp* res = NULL; - hc_edge *a = NULL; - uint32_t i, a_n, v, u, uv = (uint32_t)-1, k, k_n, k_nv, k_nu, beg, sink, *b_a = NULL, b_a_n; - - if(bubble_first) - { - int c; - kvec_t_u32_warp stack; kv_init(stack.a); - uint8_t *color = NULL; CALLOC(color, hap_n); - uint32_t n_bub = bub->f_bub + bub->b_bub; - for (i = 0; i < n_bub; i++) - { - get_bubbles(bub, i, &beg, &sink, &b_a, &b_a_n, NULL); - if(b_a_n == 2 && i < bub->f_bub) - { - continue; - } - ///full bubble do not overlap with any others - ///broken bubbles might be, but should do nothing - c = graph_bipartiteness(b_a, b_a_n, color, link, &stack); - - if(c == 0) - { - fprintf(stderr, "too good: s-utg%.6ul && e-utg%.6ul && %s\n",(beg>>1)+1, (sink>>1)+1, b_a_n != 4? "abnormal" : "normal"); - } - if(c == -1) - { - fprintf(stderr, "too bad: s-utg%.6ul && e-utg%.6ul\n",(beg>>1)+1, (sink>>1)+1); - } - if(c == 1) - { - fprintf(stderr, "\nprefect=%u: s-utg%.6ul && e-utg%.6ul\n", b_a_n, (beg>>1)+1, (sink>>1)+1); - - - for (k = 0; k < b_a_n; k++) - { - if((color[b_a[k]>>1] & 2) == 0) fprintf(stderr, "ERROR\n"); - if((color[b_a[k]>>1] & 4) == 0) fprintf(stderr, "0: utg%.6ul\n", (b_a[k]>>1)+1); - } - - for (k = 0; k < b_a_n; k++) - { - if((color[b_a[k]>>1] & 2) == 0) fprintf(stderr, "ERROR\n"); - if((color[b_a[k]>>1] & 4) != 0) fprintf(stderr, "1: utg%.6ul\n", (b_a[k]>>1)+1); - } - - for (k = 0; k < b_a_n; k++) color[b_a[k]>>1] = 0; - } - } - free(color); - kv_destroy(stack.a); - } - - for (i = 0; i < hap_n; i++) - { - v = i; - a = link->a.a[v].f.a; - a_n = link->a.a[v].f.n; - for (k = k_n = 0; k < a_n; k++) - { - if(a[k].del) continue; - if(a[k].dis != RC_0) break; - u = a[k].uID; - k_n++; - } - if(k_n != 1) - { - u = (uint32_t)-1; - goto push_uv; - } - - a = link->a.a[u].f.a; - a_n = link->a.a[u].f.n; - for (k = k_n = 0; k < a_n; k++) - { - if(a[k].del) continue; - if(a[k].dis != RC_0) break; - uv = a[k].uID; - k_n++; - } - if(k_n != 1 || uv != v) - { - u = (uint32_t)-1; - goto push_uv; - } - - push_uv: - k_nv = 0;k_nu = 0; - - // not such easy. need to deal with here very carefully - // if(g_p->index[v] != (uint32_t)-1) continue; - // if(u != (uint32_t)-1 && g_p->index[u] != (uint32_t)-1) u = (uint32_t)-1; - - a = link->a.a[v].e.a; - a_n = link->a.a[v].e.n; - for (k = 0; k < a_n; k++) - { - if(a[k].del) continue; - k_nv++; - } - - if(u != (uint32_t)-1) - { - a = link->a.a[u].e.a; - a_n = link->a.a[u].e.n; - for (k = 0; k < a_n; k++) - { - if(a[k].del) continue; - k_nu++; - } - } - if(k_nv == 0) continue; - if(k_nv > 0 && k_nu > 0 && v > u) continue; - - kv_pushp(partition_warp, *g_p, &res); - kv_init(res->a); - res->full_bub = 0; - res->h[0] = 1; res->h[1] = 0; - kv_push(uint32_t, res->a, v); - if(u != (uint32_t)-1) - { - res->h[1] = 1; - kv_push(uint32_t, res->a, u); - } - - for (k = 0; k < res->h[0]; k++) - { - g_p->index[res->a.a[k]] = g_p->n-1; - g_p->index[res->a.a[k]] = g_p->index[res->a.a[k]] << 1; - } - - for (; k < res->a.n; k++) - { - g_p->index[res->a.a[k]] = g_p->n-1; - g_p->index[res->a.a[k]] = (g_p->index[res->a.a[k]] << 1) + 1; - } - } - fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); -} - -typedef struct { - double weight; - uint64_t p_id, beg_idx, end_idx; - uint8_t used; -}bub_sort_type; - -typedef struct { - bub_sort_type* a; - size_t n, m; -}bub_sort_vec; - -double get_specific_weight_by_chain(uint64_t* ids, uint64_t beg_idx, uint64_t end_idx, uint64_t p_id, -hc_links* link, uint8_t* vis, uint8_t flag) -{ - uint64_t x, k; - uint32_t uid; - double w; - for (x = beg_idx, w = 0; x <= end_idx; x++) - { - uid = (uint32_t)((uint32_t)ids[x])>>1; - for (k = 0; k < link->a.a[uid].e.n; k++) - { - if(link->a.a[uid].e.a[k].del) continue; - if(vis[link->a.a[uid].e.a[k].uID] != flag) continue; - w += link->a.a[uid].e.a[k].weight; - } - } - - return w; -} - -int cmp_bubble_ele_by_chain(const void * a, const void * b) -{ - if((*(bub_sort_type*)a).weight == (*(bub_sort_type*)b).weight) - { - return (*(bub_sort_type*)a).weight > (*(bub_sort_type*)b).weight? -1 : 1; - } - - return 0; -} - -uint32_t get_max_hap_g(bub_sort_vec* w_stack, uint32_t* require_iso) -{ - uint32_t k, max_idx = (uint32_t)-1; - double max_w; - for (k = require_iso? (*require_iso)+1 : 0, max_idx = (uint32_t)-1; k < w_stack->n; k++) - { - if(w_stack->a[k].used) continue; - if(!require_iso) - { - if(w_stack->a[k].p_id == (uint32_t)-1) continue; - if((max_idx == (uint32_t)-1) || (max_idx != (uint32_t)-1 && max_w < w_stack->a[k].weight)) - { - max_w = w_stack->a[k].weight; - max_idx = k; - } - } - else - { - if(w_stack->a[k].p_id != (uint32_t)-1) continue; - return k; - } - } - - if(require_iso && (*require_iso) != 0) - { - for (k = 0; k < w_stack->n; k++) - { - if(w_stack->a[k].used) continue; - if(w_stack->a[k].p_id != (uint32_t)-1) continue; - return k; - } - } - - return max_idx; -} - -void update_bub_sort_vec(uint64_t* ids, bub_sort_vec* w_stack, uint32_t max_idx, hc_links* link, -uint32_t* set_hap) -{ - w_stack->a[max_idx].used = 1; - uint64_t i, k; - uint32_t uid, pid_idx; - for (i = w_stack->a[max_idx].beg_idx; i <= w_stack->a[max_idx].end_idx; i++) - { - uid = (uint32_t)((uint32_t)ids[i])>>1; - for (k = 0; k < link->a.a[uid].e.n; k++) - { - if(link->a.a[uid].e.a[k].del) continue; - pid_idx = set_hap[link->a.a[uid].e.a[k].uID]; - if(pid_idx == (uint32_t)-1) continue; - if(w_stack->a[pid_idx].used) continue; - w_stack->a[pid_idx].weight += link->a.a[uid].e.a[k].weight; - } - } -} - -void sort_bubble_ele_by_chain(G_partition* g_p, hc_links* link, bubble_type* bub, kvec_t_u64_warp* stack, -bub_sort_vec* w_stack, uint8_t* vis, uint32_t* set_hap, uint32_t n_utg, uint32_t chain_id) -{ - uint32_t max_idx, i, k, j, m, beg, sink, *a, n, flag_cur = 3, flag_right = 2, flag_left = 1, flag_unset = 0; - uint64_t bid, uid, pid, pre_pid; - ma_utg_t *u = &(bub->b_ug->u.a[chain_id]); - bub_sort_type *p = NULL; - memset(vis, flag_unset, n_utg); - for (i = 0; i < u->n; i++) - { - bid = u->a[i]>>33; - get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); - for (k = 0; k < n; k++) - { - uid = a[k]>>1; - vis[uid] = flag_right; - } - } - - for (i = 0; i < u->n; i++) - { - stack->a.n = 0; w_stack->n = 0; - bid = u->a[i]>>33; - get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); - for (k = 0; k < n; k++) - { - uid = a[k]>>1; - pid = g_p->index[uid]; - if(pid != (uint32_t)-1) pid >>= 1; - kv_push(uint64_t, stack->a, (pid<<32)|a[k]); - vis[uid] = flag_cur; - } - radix_sort_hc64(stack->a.a, stack->a.a + stack->a.n);///sort is to dedup pid - - for (k = 0, pre_pid = (uint64_t)-1; k < stack->a.n; k++) - { - if((stack->a.a[k]>>32) == pre_pid) continue; - if(w_stack->n > 0) w_stack->a[w_stack->n-1].end_idx = k - 1; - - pre_pid = stack->a.a[k]>>32; - kv_pushp(bub_sort_type, *w_stack, &p); - p->weight = 0; - p->p_id = pre_pid; - p->beg_idx = k; - p->end_idx = (uint64_t)-1; - p->used = 0; - } - if(w_stack->n > 0) w_stack->a[w_stack->n-1].end_idx = k - 1; - - ///get each hap id - for (k = 0; k < w_stack->n; k++) - { - w_stack->a[k].weight += get_specific_weight_by_chain(stack->a.a, w_stack->a[k].beg_idx, w_stack->a[k].end_idx, w_stack->a[k].p_id, - link, vis, flag_left); - w_stack->a[k].weight -= get_specific_weight_by_chain(stack->a.a, w_stack->a[k].beg_idx, w_stack->a[k].end_idx, w_stack->a[k].p_id, - link, vis, flag_right); - for (j = w_stack->a[k].beg_idx; j <= w_stack->a[k].end_idx; j++) - { - set_hap[((uint32_t)stack->a.a[j])>>1] = k; - } - } - - m = 0; - while ((max_idx = get_max_hap_g(w_stack, NULL)) != (uint32_t)-1) - { - for (j = w_stack->a[max_idx].beg_idx; j <= w_stack->a[max_idx].end_idx; j++) - { - a[m] = (uint32_t)stack->a.a[j]; - m++; - } - update_bub_sort_vec(stack->a.a, w_stack, max_idx, link, set_hap); - } - - while ((max_idx = get_max_hap_g(w_stack, &max_idx)) != (uint32_t)-1) - { - for (j = w_stack->a[max_idx].beg_idx; j <= w_stack->a[max_idx].end_idx; j++) - { - a[m] = (uint32_t)stack->a.a[j]; - m++; - } - update_bub_sort_vec(stack->a.a, w_stack, max_idx, link, set_hap); - } - - - /** - qsort(w_stack->a, w_stack->n, sizeof(bub_sort_type), cmp_bubble_ele_by_chain); - - m = 0; - - for (k = 0; k < w_stack->n; k++) - { - if(w_stack->a[k].p_id == (uint32_t)-1) continue; - for (j = w_stack->a[k].beg_idx; j <= w_stack->a[k].end_idx; j++) - { - a[m] = (uint32_t)stack->a.a[j]; - m++; - } - } - - for (k = 0; k < w_stack->n; k++) - { - if(w_stack->a[k].p_id != (uint32_t)-1) continue; - for (j = w_stack->a[k].beg_idx; j <= w_stack->a[k].end_idx; j++) - { - a[m] = (uint32_t)stack->a.a[j]; - m++; - } - } - **/ - - for (k = 0; k < n; k++) - { - uid = a[k]>>1; - vis[uid] = flag_left; - set_hap[uid] = (uint32_t)-1; - } - } -} - -void sort_bubble_ele(G_partition* g_p, hc_links* link, bubble_type* bub, uint32_t n_utg) -{ - double index_time = yak_realtime(); - kvec_t_u64_warp stack; kv_init(stack.a); - bub_sort_vec w_stack; kv_init(w_stack); - uint8_t* vis = NULL; MALLOC(vis, n_utg); - uint32_t* set_hap = NULL; MALLOC(set_hap, n_utg); memset(set_hap, -1, sizeof(uint32_t)*n_utg); - uint32_t i; - - for (i = 0; i < bub->chain_weight.n; i++) - { - if(bub->chain_weight.a[i].del) continue; - sort_bubble_ele_by_chain(g_p, link, bub, &stack, &w_stack, vis, set_hap, n_utg, bub->chain_weight.a[i].id); - } - - kv_destroy(stack.a); kv_destroy(w_stack); free(vis); free(set_hap); - fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); -} - -uint32_t init_contig_partition(H_partition* hap, ha_ug_index* idx, bubble_type* bub, hc_links* link) -{ - ///hc_links* link = idx->link; - ma_ug_t *ug = idx->ug; - bub_p_t_warp b; - memset(&b, 0, sizeof(bub_p_t_warp)); - CALLOC(b.a, ug->g->n_seq*2); - uint32_t i, nv = ug->g->n_seq * 2, max_i, max_hap_label; - for (i = 0; i < nv; i++) - { - b.a[i].w[0] = b.a[i].w[1] = b.a[i].nh = 0; - b.a[i].p =b.a[i].d = b.a[i].nc = b.a[i].uc = b.a[i].ac = b.a[i].r = b.a[i].s = 0; - } - uint8_t* hap_label_flag = NULL; - CALLOC(hap_label_flag, ug->g->n_seq); - - - hap->n = ug->u.n; - MALLOC(hap->hap, hap->n); - memset(hap->hap, 0, hap->n*sizeof(uint32_t)); - MALLOC(hap->lock, hap->n); - memset(hap->lock, 0, hap->n); - hap->m[0] = 1; hap->m[1] = 2; hap->m[2] = 4; - hap->link = link; - hap->label = 0; - hap->label_add = 8;//1000, for hap group - for(hap->label_shift=1; (uint64_t)(1<label_shift)<(uint64_t)hap->label_add; hap->label_shift++); - kv_init(hap->label_buffer); - kv_init(hap->b.vis); kv_malloc(hap->b.vis, hap->n); hap->b.vis.n = hap->n; - - ///sorted by weight - for (i = 0; i < bub->chain_weight.n; i++) - { - if(bub->chain_weight.a[i].del) continue; - phase_bubble_chain(hap, ug, &b, bub, hap_label_flag, bub->chain_weight.a[i].id); - ///print_chain_phasing(hap, ug, bub, bub->chain_weight.a[i].id); - } - - memset(hap_label_flag, 1, ug->g->n_seq); - while (1) - { - max_i = get_unset_com(hap, bub, ug, hap_label_flag, &max_hap_label); - if(max_i == (uint32_t)-1) break; - phase_com(hap, ug, &b, bub, max_i, max_hap_label); - } - - for (i = 0; i < hap->n; i++) - { - if((hap->hap[i]&hap->m[0])&&(hap->hap[i]&hap->m[1])) - { - hap->hap[i] >>= hap->label_shift; - hap->hap[i] <<= hap->label_shift; - hap->hap[i] |= hap->m[2]; - reset_ambiguous_label(hap, hap_label_flag, i); - } - } - - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - - init_G_partition(&(hap->g_p), hap->n); - - link_phase_group(hap, bub); - - assign_per_unitig_G_partition(&(hap->g_p), hap->n, link, bub, 0);///warp unitigs - - adjust_contig_partition(hap, link); - - update_bubble_chain(ug, bub, 0, 1); - - resolve_bubble_chain_tangle(ug, bub); - - clean_bubble_chain_by_HiC(ug, link, bub); - - append_boundary_chain(ug, link, bub); - - sort_bubble_ele(&(hap->g_p), link, bub, hap->n); - - free(hap_label_flag); - return 1; -} - -double get_path_phasing_weight(uint32_t query, uint32_t v0, uint32_t root, bub_p_t_warp *b, kv_u_trans_t *ta) -{ - if(v0 == root) return 0; - uint32_t v, u; - u_trans_t *p = NULL; - double nw = 0; - v = v0; - do { - u = b->a[v].p; // u->v - get_u_trans_spec(ta, query>>1, v>>1, &p, NULL); - if(p && (!p->del)) nw += p->nw; - v = u; - } while (v != root); - - return nw; -} - -void get_related_phasing_weight(uint32_t x, kv_u_trans_t *ta, double* w0, double* w1, int8_t *s) -{ - (*w0) = (*w1) = 0; - if(x >= ta->idx.n) return; - uint32_t e_n, k; - u_trans_t* e = u_trans_a(*ta, x); - e_n = u_trans_n(*ta, x); - for (k = 0; k < e_n; k++) - { - if(e[k].del) continue; - if(s[e[k].tn] > 0) (*w0) += e[k].nw; - else if(s[e[k].tn] < 0) (*w1) += e[k].nw; - } -} - -void set_phase_path(bub_p_t_warp *b, uint32_t root, kv_u_trans_t *ta, ps_t *s) -{ - int8_t f; - uint32_t v, u; - double z[2], cur_w[2]; - z[0] = z[1] = 0; - - v = b->S.a[0]; - do { - u = b->a[v].p; // u->v - if(v != b->S.a[0]) - { - get_related_phasing_weight(v>>1, ta, &cur_w[0], &cur_w[1], s->s); - z[0] += cur_w[0]; z[1] += cur_w[1]; - } - v = u; - } while (v != root); - - if(z[0] - z[1] < 0) - { - f = 1; - } - else if(z[0] - z[1] > 0) - { - f = -1; - } - else - { - s->xs = kr_splitmix64(s->xs); - f = s->xs&1? 1 : -1; - } - - v = b->S.a[0]; - do { - u = b->a[v].p; // u->v - if(v != b->S.a[0]) s->s[v>>1] = f; - v = u; - } while (v != root); -} - -uint32_t bub_phase(ma_ug_t *ug, uint32_t beg, uint32_t end, bub_p_t_warp *b, kv_u_trans_t *ta, ps_t *s) -{ - asg_t *g = ug->g; - if(g->seq[beg>>1].del) return 0; // already deleted - if(get_real_length(g, beg, NULL)<2) return 0; - uint32_t i, is_end, n_pending, to_replace, cur_nc, cur_uc, cur_ac, n_tips, tip_end, n_pop; - double cur_nh, cur_w0, cur_w1, cur_rate, max_rate, cur_weight, min_weight; - ///S saves nodes with all incoming edges visited - b->S.n = b->T.n = b->b.n = b->e.n = 0; - ///for each node, b->a saves all related information - b->a[beg].d = b->a[beg].nc = b->a[beg].ac = b->a[beg].uc = 0; - b->a[beg].nh = b->a[beg].w[0] = b->a[beg].w[1] = 0; - b->a[beg].p = (uint32_t)-1; - ///b->S is the nodes with all incoming edges visited - kv_push(uint32_t, b->S, beg); - n_pop = n_tips = n_pending = 0; - tip_end = (uint32_t)-1; - - do { - ///v is a node that all incoming edges have been visited - ///d is the distance from v0 to v - uint32_t v = kv_pop(b->S); - uint32_t d = b->a[v].d, nc = b->a[v].nc, uc = b->a[v].uc, ac = b->a[v].ac; - double nh = b->a[v].nh;///path weight - double nw_0 = b->a[v].w[0], nw_1 = b->a[v].w[1];///weight to haplotype 1/2 - - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - for (i = 0; i < nv; ++i) { - uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l, not overlap length - bub_p_t *t = &b->a[w]; - is_end = 0; - if((w>>1) == (end>>1)) is_end = 1; - //got a circle - if ((w>>1) == (beg>>1)) goto pop_reset; - if (av[i].del) continue; - ///push the edge - kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); - - if (t->s == 0) - { // this vertex has never been visited - kv_push(uint32_t, b->b, w); // save it for revert - ///t->p is the parent node of - ///t->s = 1 means w has been visited - ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) - t->p = v, t->s = 1, t->d = d + l; - t->r = get_real_length(g, w^1, NULL); - - if(is_end == 0) - { - t->nc = nc + ug->u.a[(w>>1)].n; - t->nh = nh + get_path_phasing_weight(w, v, beg, b, ta); - get_related_phasing_weight(w>>1, ta, &(t->w[0]), &(t->w[1]), s->s); - t->w[0] += nw_0; t->w[1] += nw_1; - t->ac = ac + ((s->s[w>>1] == 0)? ug->u.a[(w>>1)].n : 0); - t->uc = uc + ((s->s[w>>1] != 0)? ug->u.a[(w>>1)].n : 0); - } - - ++n_pending; - } - else { - to_replace = 0; - - if(is_end) - { - cur_nc = nc; cur_nh = nh; - cur_w0 = nw_0; cur_w1= nw_1; - cur_ac = ac; cur_uc = uc; - } - else - { - cur_nc = nc + ug->u.a[(w>>1)].n; - cur_nh = nh + get_path_phasing_weight(w, v, beg, b, ta); - get_related_phasing_weight(w>>1, ta, &cur_w0, &cur_w1, s->s); - cur_w0 += nw_0; cur_w1 += nw_1; - cur_ac = ac + ((s->s[w>>1] == 0)? ug->u.a[(w>>1)].n : 0); - cur_uc = uc + ((s->s[w>>1] != 0)? ug->u.a[(w>>1)].n : 0); - } - - cur_weight = cur_nh + MIN(cur_w0, cur_w1) - MAX(cur_w0, cur_w1); - min_weight = t->nh + MIN(t->w[0], t->w[1]) - MAX(t->w[0], t->w[1]); - cur_rate = ((cur_ac+cur_uc == 0)? -1 : ((double)(cur_ac)/(double)(cur_ac+cur_uc))); - max_rate = ((t->ac+t->uc == 0)? -1 : ((double)(t->ac)/(double)(t->ac+t->uc))); - - if(cur_rate > max_rate) - { - to_replace = 1; - } - else if(cur_rate == max_rate) - { - if(cur_weight < min_weight) - { - to_replace = 1; - } - else if(cur_weight == min_weight) - { - if(cur_nc > t->nc) - { - to_replace = 1; - } - else if(cur_nc == t->nc) - { - if(d + l > t->d) - { - to_replace = 1; - } - } - } - } - - - if(to_replace) - { - t->p = v; - t->nc = cur_nc; - t->nh = cur_nh; - t->ac = cur_ac; - t->uc = cur_uc; - t->w[0] = cur_w0; - t->w[1] = cur_w1; - } - - - if (d + l < t->d) t->d = d + l; // update dist - } - - if (--(t->r) == 0) { - uint32_t x = get_real_length(g, w, NULL); - if(x > 0) - { - kv_push(uint32_t, b->S, w); - } - else - { - ///at most one tip - if(n_tips != 0) goto pop_reset; - n_tips++; - tip_end = w; - } - --n_pending; - } - } - - if(n_tips == 1) - { - if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) - { - ///sink is b.S.a[0] - kv_push(uint32_t, b->S, tip_end); - break; - } - else - { - goto pop_reset; - } - } - - if (i < nv || b->S.n == 0) goto pop_reset; - }while (b->S.n > 1 || n_pending); - - n_pop = 1; - /**need fix**/ - set_phase_path(b, beg, ta, s); - - pop_reset: - - for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices - bub_p_t *t = &b->a[b->b.a[i]]; - t->p = t->d = t->nc = t->ac = t->uc = t->r = t->s = 0; - t->nh = t->w[0] = t->w[1] = 0; - } - return n_pop; -} - -uint32_t get_weightest_node(kv_u_trans_t *ta, bubble_type* bub, ma_ug_t* ug, int8_t *s, uint8_t *vis) -{ - double w_a, w_n, max_w_a, max_w_n; - uint32_t i, occ, k, m, v, *a = NULL, a_n, e_n, max_w_a_i, max_w_n_i; - u_trans_t *e = NULL; - max_w_a = max_w_n = -1; max_w_a_i = max_w_n_i = (uint32_t)-1; - for (i = 0; i < bub->f_bub; i++) - { - get_bubbles(bub, i, NULL, NULL, &a, &a_n, NULL); - if(vis[i]) continue; - for (k = 0, w_a = w_n = 0; k < a_n; k++) - { - v = a[k]>>1; - if(s[v] != 0) break; - e = u_trans_a(*ta, v); - e_n = u_trans_n(*ta, v); - for (m = 0; m < e_n; m++) - { - if(s[e[m].tn] != 0) - { - w_a += (e[m].nw>=0?e[m].nw:-e[m].nw); - } - else - { - w_n += (e[m].nw>=0?e[m].nw:-e[m].nw); - } - } - } - - if(k >= a_n && a_n > 0)//unset whole bubble - { - if(w_a > max_w_a) - { - max_w_a_i = i<<1; - max_w_a = w_a; - } - - if(w_n > max_w_n) - { - max_w_n_i = i<<1; - max_w_n = w_n; - } - } - else - { - for (k = occ = 0; k < a_n; k++) - { - v = a[k]>>1; - if(s[v] != 0) - { - occ++; - continue; - } - - e = u_trans_a(*ta, v); - e_n = u_trans_n(*ta, v); - for (m = 0, w_a = w_n = 0; m < e_n; m++) - { - if(s[e[m].tn] != 0) - { - w_a += (e[m].nw>=0?e[m].nw:-e[m].nw); - } - else - { - w_n += (e[m].nw>=0?e[m].nw:-e[m].nw); - } - } - - if(w_a > max_w_a) - { - max_w_a_i = (v<<1)+1; - max_w_a = w_a; - } - - if(w_n > max_w_n) - { - max_w_n_i = (v<<1)+1; - max_w_n = w_n; - } - } - - if(occ == a_n) vis[i] = 1; - } - } - - for (i = 0; i < ug->g->n_seq; i++) - { - if(s[i] != 0 || (IF_BUB(i, *bub))) continue; - v = i; - e = u_trans_a(*ta, v); - e_n = u_trans_n(*ta, v); - for (m = 0, w_a = w_n = 0; m < e_n; m++) - { - if(s[e[m].tn] != 0) - { - w_a += (e[m].nw>=0?e[m].nw:-e[m].nw); - } - else - { - w_n += (e[m].nw>=0?e[m].nw:-e[m].nw); - } - } - - if(w_a > max_w_a) - { - max_w_a_i = (i<<1)+1; - max_w_a = w_a; - } - - if(w_n > max_w_n) - { - max_w_n_i = (i<<1)+1; - max_w_n = w_n; - } - } - - if(max_w_a_i != (uint32_t)-1) return max_w_a_i; - return max_w_n_i; -} - -void init_phase(ha_ug_index* idx, kv_u_trans_t *ta, bubble_type* bub, ps_t *st) -{ - double index_time = yak_realtime(); - uint8_t *vis = NULL; CALLOC(vis, idx->ug->g->n_seq); - bub_p_t_warp b; memset(&b, 0, sizeof(bub_p_t_warp)); - CALLOC(b.a, idx->ug->g->n_seq*2); - uint32_t i, k, *a = NULL, n, beg, end; - memset(st->s, 0, sizeof(int8_t)*idx->ug->g->n_seq); - - double z[2]; - u_trans_t *e = NULL; - uint32_t e_n; - while(1) - { - i = get_weightest_node(ta, bub, idx->ug, st->s, vis); - if(i == (uint32_t)-1) break; - if(i&1) - { - i>>=1; - z[0] = z[1] = 0; - e = u_trans_a(*ta, i); - e_n = u_trans_n(*ta, i); - for (k = 0; k < e_n; k++) - { - if(e[k].del) continue; - if(st->s[e[k].tn] > 0) z[0] += e[k].nw; - else if(st->s[e[k].tn] < 0) z[1] += e[k].nw; - } - if(z[0] - z[1] < 0) - { - st->s[i] = 1; - } - else if(z[0] - z[1] > 0) - { - st->s[i] = -1; - } - else - { - st->xs = kr_splitmix64(st->xs); - st->s[i] = st->xs&1? 1 : -1; - } - } - else - { - i>>=1; - get_bubbles(bub, i, &beg, &end, &a, &n, NULL); - bub_phase(idx->ug, beg, end, &b, ta, st); - bub_phase(idx->ug, beg, end, &b, ta, st); - } - } - free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); - free(vis); - - for (i = 0; i < idx->ug->g->n_seq; i++) - { - if(st->s[i] == 0) fprintf(stderr, "ERROR\n"); - if(u_trans_n(*ta, i) == 0) st->s[i] = 0; - } - - fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); -} - - -double dfs_weight_hic(uint32_t v, uint8_t* vis_flag, uint8_t* is_vis, kv_u_trans_t *ta, -kvec_t_u32_warp* stack, kvec_t_u32_warp* result, uint32_t e_flag, uint32_t ava_flag, uint32_t* link_occ) -{ - u_trans_t *e = NULL; - uint32_t cur, i, next = (uint32_t)-1, e_n; - stack->a.n = 0; - kv_push(uint32_t, stack->a, v); - double w = 0; - if(link_occ) (*link_occ) = 0; - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - if(is_vis[cur]) continue; - is_vis[cur] = 1; - if(cur!=v && vis_flag[cur] != ava_flag) continue; - e = u_trans_a(*ta, cur); e_n = u_trans_n(*ta, cur); - for (i = 0; i < e_n; i++) - { - if(e[i].del) continue; - next = e[i].tn; - if(vis_flag[next]&e_flag) - { - w += (e[i].nw >= 0? e[i].nw : -e[i].nw); - if(link_occ) (*link_occ) += e[i].occ; - continue; - } - if(is_vis[next]) continue; - if(vis_flag[next] != ava_flag) continue; - kv_push(uint32_t, stack->a, next); - } - } - return w; -} - -double get_chain_weight_hic(bubble_type* bub, ma_ug_t *bub_ug, buf_t* b, uint32_t v, uint32_t convex_source, -kv_u_trans_t *ta, uint8_t* vis_flag, uint8_t* is_vis, ma_ug_t* ug, kvec_t_u32_warp* stack, -kvec_t_u32_warp* result, uint32_t e_flag, uint32_t ava_flag, kvec_t_u32_warp* res_utg, uint32_t* link_occ) -{ - long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; - ma_utg_t *u = NULL; - uint32_t convex, k, k_i, k_j, *a, n, beg, sink, uID, root, cur, ncur, n_vx = ug->g->n_seq<<1, occ; - asg_arc_t *acur = NULL; - double w = 0; - b->b.n = 0; - get_unitig(bub_ug->g, NULL, v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, - &max_stop_baseLen, 1, b); - memset(is_vis, 0, n_vx); - - for (k = 0; k < b->b.n; k++) - { - u = &(bub_ug->u.a[b->b.a[k]>>1]); - if(u->n == 0) continue; - - for (k_i = 0; k_i < u->n; k_i++) - { - get_bubbles(bub, u->a[k_i]>>33, &beg, &sink, &a, &n, NULL); - for(k_j = 0; k_j < n; k_j++) is_vis[a[k_j]] = is_vis[a[k_j]^1] = 1; - if(beg != (uint32_t)-1) is_vis[beg] = is_vis[beg^1] = 1; - if(sink != (uint32_t)-1) is_vis[sink] = is_vis[sink^1] = 1; - } - } - - u = &(bub_ug->u.a[v>>1]); - if((v&1)==0) - { - get_bubbles(bub, (u->a[0]>>32)>>1, (((u->a[0]>>32)&1)^1)==1?&root:NULL, - (((u->a[0]>>32)&1)^1) == 0?&root:NULL, NULL, NULL, NULL); - } - else - { - get_bubbles(bub, (u->a[u->n-1]>>32)>>1, ((u->a[u->n-1]>>32)&1)==1?&root:NULL, - ((u->a[u->n-1]>>32)&1) == 0?&root:NULL, NULL, NULL, NULL); - } - - root ^= 1; - is_vis[root] = 0; - stack->a.n = 0; - kv_push(uint32_t, stack->a, root); - while (stack->a.n > 0)///label all untigs not in any chain - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - if(is_vis[cur]) continue; - is_vis[cur] = 1; - if(vis_flag[cur>>1] == 0) vis_flag[cur>>1] = ava_flag;///unitig not in any chain - - ncur = asg_arc_n(ug->g, cur); - acur = asg_arc_a(ug->g, cur); - for (k = 0; k < ncur; k++) - { - if(acur[k].del) continue; - if(is_vis[acur[k].v]) continue; - if(vis_flag[acur[k].v>>1] != 0 && vis_flag[acur[k].v>>1] != ava_flag) continue; - kv_push(uint32_t, stack->a, acur[k].v); - } - } - - - ///vis_flag keeps isloated nodes - uint32_t aim_0, aim_1, root_source; - aim_0 = root>>1; - u = &(bub_ug->u.a[convex_source>>1]); - if((convex_source&1)==1) - { - get_bubbles(bub, (u->a[0]>>32)>>1, (((u->a[0]>>32)&1)^1)==1?&root_source:NULL, - (((u->a[0]>>32)&1)^1) == 0?&root_source:NULL, NULL, NULL, NULL); - } - else - { - get_bubbles(bub, (u->a[u->n-1]>>32)>>1, ((u->a[u->n-1]>>32)&1)==1?&root_source:NULL, - ((u->a[u->n-1]>>32)&1) == 0?&root_source:NULL, NULL, NULL, NULL); - } - root_source ^= 1; - aim_1 = root_source>>1; - - - cur = root_source;///scan nodes that cannot be reached from root but can be reached from root_source - ncur = asg_arc_n(ug->g, cur); - acur = asg_arc_a(ug->g, cur); - for (k_i = 0; k_i < ncur; k_i++) - { - if(acur[k_i].del) continue; - if(vis_flag[acur[k_i].v>>1] != 0) continue;///skip nodes that are already reachable - ///don't label any path that can reack other chains - if_conflict_utg(acur[k_i].v, &aim_0, &aim_1, ug, vis_flag, is_vis, ava_flag, stack); - } - - - for (k = 0; k < ug->g->n_seq; k++) - { - if(vis_flag[k] == ava_flag) - { - cur = k<<1; - ncur = asg_arc_n(ug->g, cur); - acur = asg_arc_a(ug->g, cur); - for (k_i = 0; k_i < ncur; k_i++) - { - if(acur[k_i].del) continue; - if(vis_flag[acur[k_i].v>>1] != 0) continue; - if_conflict_utg(acur[k_i].v, &aim_0, &aim_1, ug, vis_flag, is_vis, ava_flag, stack); - } - - - - cur = (k<<1)+1; - ncur = asg_arc_n(ug->g, cur); - acur = asg_arc_a(ug->g, cur); - for (k_i = 0; k_i < ncur; k_i++) - { - if(acur[k_i].del) continue; - if(vis_flag[acur[k_i].v>>1] != 0) continue; - if_conflict_utg(acur[k_i].v, &aim_0, &aim_1, ug, vis_flag, is_vis, ava_flag, stack); - } - } - } - - - - memset(is_vis, 0, n_vx); - if(link_occ) (*link_occ) = 0; - for (k = result->a.n = 0, w = 0; k < b->b.n; k++) - { - u = &(bub_ug->u.a[b->b.a[k]>>1]); - if(u->n == 0) continue; - for (k_i = 0; k_i < u->n; k_i++) - { - get_bubbles(bub, u->a[k_i]>>33, NULL, NULL, &a, &n, NULL); - - for (k_j = 0; k_j < n; k_j++) - { - uID = a[k_j]>>1; - w += dfs_weight_hic(uID, vis_flag, is_vis, ta, stack, result, e_flag, ava_flag, &occ); - if(link_occ) (*link_occ) += occ; - } - } - } - - - for (k = 0; k < ug->g->n_seq; k++) - { - if(vis_flag[k] == ava_flag) - { - vis_flag[k] = 0; - if(res_utg && (!IF_HOM(k, *bub))) - { - kv_push(uint32_t, res_utg->a, k<<1); - } - } - } - - return w; -} - - -void clean_bubble_chain_by_hic(ma_ug_t* ug, kv_u_trans_t *ta, bubble_type* bub) -{ - double index_time = yak_realtime(); - ma_ug_t *bs_ug = bub->b_ug; - uint32_t v, u, i, m, max_i, nv, rv, n_vx, root, flag_pri = 1, flag_aux = 2, flag_ava = 4, occ; - double w, cutoff = 2; - uint32_t max_w_occ = 4; - asg_arc_t *av = NULL; - n_vx = bs_ug->g->n_seq << 1; - uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq<<1); - uint8_t *is_vis = NULL; CALLOC(is_vis, ug->g->n_seq<<1); - uint8_t *is_used = NULL; CALLOC(is_used, n_vx); - uint8_t *dedup = NULL; CALLOC(dedup, ug->g->n_seq<<1); - buf_t b; memset(&b, 0, sizeof(buf_t)); - kvec_t_u32_warp stack, result, res_utg; - kv_init(stack.a); kv_init(result.a); kv_init(res_utg.a); - double *e_w = NULL; MALLOC(e_w, bs_ug->g->n_arc); - uint32_t *e_occ = NULL, *a_occ = NULL; CALLOC(e_occ, bs_ug->g->n_arc); - double *aw = NULL, max_w = 0; - kvec_asg_arc_t_warp edges; kv_init(edges.a); - ma_ug_t *back_bs_ug = copy_untig_graph(bs_ug); - - for (i = 0; i < bs_ug->g->n_arc; i++)///weight of bs_ug's edges - { - e_w[i] = -1; - } - - for (i = 0; i < bs_ug->g->n_seq; i++)///init all chain with flag_aux - { - set_b_utg_weight_flag(bub, &b, i<<1, vis, flag_aux, NULL); - } - - - for (v = 0; v < n_vx; v++) - { - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - aw = (&e_w[bs_ug->g->idx[v]>>32]); - a_occ = (&e_occ[bs_ug->g->idx[v]>>32]); - if(nv <= 1 || get_real_length(bs_ug->g, v, NULL) <= 1) continue; - set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); - - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - w = get_chain_weight_hic(bub, bs_ug, &b, av[i].v, v, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, NULL, &occ); - aw[i] = w; - a_occ[i] = occ; - } - - set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); - } - - - for (v = 0; v < n_vx; v++) - { - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - aw = (&e_w[bs_ug->g->idx[v]>>32]); - a_occ = (&e_occ[bs_ug->g->idx[v]>>32]); - if(nv <= 1 || get_real_length(bs_ug->g, v, NULL) <= 1) continue; - - for (i = rv = 0, max_i = (uint32_t)-1; i < nv; i++) - { - if(av[i].del) continue; - if(max_i == (uint32_t)-1) - { - max_i = i; - max_w = aw[i]; - } - else if(max_w < aw[i]) - { - max_i = i; - max_w = aw[i]; - } - rv++; - } - - if(max_i == (uint32_t)-1) continue; - ///if(max_w <= max_w_cutoff) continue; //must be <= - if(a_occ[max_i] <= max_w_occ) continue; //must be <= - if(rv < 2) continue; - - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - if(i == max_i) continue; - ///if((av[i].v>>1) == (v>>1) && aw[i] <= max_w_cutoff) continue; ///might be not reasonable - if((av[i].v>>1) == (v>>1) && a_occ[i] <= max_w_occ) continue; ///might be not reasonable - if(aw[i]*cutoff < max_w && double_check_bub_branch(&av[i], bs_ug, e_w, e_occ, cutoff, max_w_occ)) - { - av[i].del = 1; asg_arc_del(bs_ug->g, (av[i].v)^1, (av[i].ul>>32)^1, 1); - } - } - } - - uint32_t rId_0, ori_0, rId_1, ori_1, root_0, root_1, new_bub; - if(bub->num.n > 0) bub->num.n--; - new_bub = bub->b_g->n_seq; - - for (v = 0; v < n_vx; v++) - { - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - rv = get_real_length(bs_ug->g, v, NULL); - if(nv == rv) continue;///no edge drop - if(rv != 1 || nv <= 1) continue; - get_real_length(bs_ug->g, v, &u); - u ^= 1; - if(get_real_length(bs_ug->g, u, NULL) != 1) continue; - drop_g_edges_by_utg(bub, bub->b_g, bs_ug, NULL, v, u); - if(is_used[v] || is_used[u]) continue; - - is_used[v] = is_used[u] = 1; - root = get_utg_end_from_btg(bub, bs_ug, v); - rId_0 = root>>1; - ori_0 = root&1; - get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); - - root = get_utg_end_from_btg(bub, bs_ug, u); - rId_1 = root>>1; - ori_1 = root&1; - get_bubbles(bub, rId_1, ori_1 == 1?&root_1:NULL, ori_1 == 0?&root_1:NULL, NULL, NULL, NULL); - - res_utg.a.n = 0; - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); - get_chain_weight_hic(bub, back_bs_ug, &b, u^1, v, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); - for (i = 0; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 1; - - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); - get_chain_weight_hic(bub, back_bs_ug, &b, v^1, u, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); - for (; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 2; - - for (i = m = 0; i < res_utg.a.n; i++) - { - if(dedup[res_utg.a.a[i]>>1] == 3) - { - res_utg.a.a[m] = res_utg.a.a[i]; - m++; - } - dedup[res_utg.a.a[i]>>1] = 0; - } - res_utg.a.n = m; - - if(!IF_HOM(root_0>>1, *bub)) kv_push(uint32_t, res_utg.a, root_0); - if(!IF_HOM(root_1>>1, *bub)) kv_push(uint32_t, res_utg.a, root_1); - - update_bubble_graph(&res_utg, root_0^1, rId_0, root_1^1, rId_1, bub, &edges, bub->b_g, NULL, NULL, ug, NULL, 0); - - ///fprintf(stderr, "\n******src-btg%.6ul------>dest-btg%.6ul\n", (v>>1)+1, (u>>1)+1); - } - - kv_push(uint32_t, bub->num, bub->list.n); - new_bub = bub->b_g->n_seq - new_bub; - bub->cross_bub += new_bub; - ///actually not useful, and may have bug when one bubble at multipe chains - if(new_bub) update_bub_b_s_idx(bub); - - ///debug_tangle_bubble(bub, bub->b_g->n_seq - bub->cross_bub, bub->b_g->n_seq - 1, "Cross-tangle"); - update_bsg(bub->b_g, &edges); - - ma_ug_destroy(bs_ug); - bs_ug = ma_ug_gen(bub->b_g); - bub->b_ug = bs_ug; - kv_destroy(bub->chain_weight); - ma_utg_t *u_x = NULL; - bs_ug = bub->b_ug; - kv_malloc(bub->chain_weight, bs_ug->u.n); bub->chain_weight.n = bs_ug->u.n; - for (i = 0; i < bs_ug->u.n; i++) - { - u_x = &(bs_ug->u.a[i]); - bub->chain_weight.a[i].id = i; - // if(u->n <= 1) ///not a chain - // { - // bub->chain_weight.a[i].b_occ = bub->chain_weight.a[i].g_occ = 0; - // bub->chain_weight.a[i].del = 1; - // } - // else - { - bub->chain_weight.a[i].del = 0; - calculate_chain_weight(u_x, bub, ug, &(bub->chain_weight.a[i])); - } - } - qsort(bub->chain_weight.a, bub->chain_weight.n, sizeof(chain_w_type), cmp_chain_weight); - - - - free(vis); free(is_vis); free(is_used); free(dedup); free(b.b.a); free(e_w); free(e_occ); - kv_destroy(stack.a); kv_destroy(result.a); kv_destroy(res_utg.a); kv_destroy(edges.a); - ma_ug_destroy(back_bs_ug); - fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); -} - -void clean_sub_tangle(bubble_type* bub, uint8_t* vis_flag, kvec_t_u32_warp *res_utg, -uint8_t *dedup, uint8_t *is_tangle, kvec_asg_arc_t_warp* edges, uint32_t flag, uint32_t s, -uint32_t e) -{ - uint32_t i, k_i, pv, v, occ, beg, sink, p_beg, p_sink, n, *a = NULL; - ma_utg_t *u = NULL; - - for (i = 0, pv = (uint32_t)-1; i < res_utg->a.n; i++) - { - if(is_tangle[res_utg->a.a[i]>>1] == 1) - { - if(pv == (uint32_t)-1) - { - pv = res_utg->a.a[i]>>1; - } - else if(pv != (res_utg->a.a[i]>>1)) - { - pv = (uint32_t)-1; - break; - } - } - else if(is_tangle[res_utg->a.a[i]>>1] == (uint8_t)-1) - { - pv = (uint32_t)-1; - break; - } - } - - if(pv == (uint32_t)-1) - { - for (i = 0; i < res_utg->a.n; i++) - { - is_tangle[res_utg->a.a[i]>>1] = (uint8_t)-1; - } - return; - } - - occ = 0; - u = &(bub->b_ug->u.a[s]); - for (i = 0, p_beg = p_sink = (uint32_t)-1; i < u->n; i++) - { - get_bubbles(bub, u->a[i]>>33, &beg, &sink, &a, &n, NULL); - - for (k_i = 0; k_i < n; k_i++) - { - occ += bub->ug->u.a[a[k_i]>>1].n; - } - if(beg != (uint32_t)-1 && (beg>>1) != (p_beg>>1) && (beg>>1) != (p_sink>>1)) - { - occ += bub->ug->u.a[beg>>1].n; - } - if(sink != (uint32_t)-1 && (sink>>1) != (p_beg>>1) && (sink>>1) != (p_sink>>1)) - { - occ += bub->ug->u.a[sink>>1].n; - } - p_beg = beg; p_sink = sink; - } - - u = &(bub->b_ug->u.a[e]); - for (i = 0, p_beg = p_sink = (uint32_t)-1; i < u->n; i++) - { - get_bubbles(bub, u->a[i]>>33, &beg, &sink, &a, &n, NULL); - - for (k_i = 0; k_i < n; k_i++) - { - occ += bub->ug->u.a[a[k_i]>>1].n; - } - if(beg != (uint32_t)-1 && (beg>>1) != (p_beg>>1) && (beg>>1) != (p_sink>>1)) - { - occ += bub->ug->u.a[beg>>1].n; - } - if(sink != (uint32_t)-1 && (sink>>1) != (p_beg>>1) && (sink>>1) != (p_sink>>1)) - { - occ += bub->ug->u.a[sink>>1].n; - } - p_beg = beg; p_sink = sink; - } - - if(occ <= bub->ug->u.a[pv].n*200) - { - for (i = 0; i < res_utg->a.n; i++) - { - is_tangle[res_utg->a.a[i]>>1] = (uint8_t)-1; - } - return; - } - - if(!edges) return; - - u = &(bub->b_ug->u.a[s]); - for (i = 0; i < u->n; i++) - { - get_bubbles(bub, u->a[i]>>33, &beg, &sink, &a, &n, NULL); - - for (k_i = 0; k_i < n; k_i++) - { - vis_flag[a[k_i]>>1] ^= flag; - } - if(beg != (uint32_t)-1) - { - vis_flag[beg>>1] ^= flag; - } - if(sink != (uint32_t)-1) - { - vis_flag[sink>>1] ^= flag; - } - } - u = &(bub->b_ug->u.a[e]); - for (i = 0; i < u->n; i++) - { - get_bubbles(bub, u->a[i]>>33, &beg, &sink, &a, &n, NULL); - - for (k_i = 0; k_i < n; k_i++) - { - vis_flag[a[k_i]>>1] ^= flag; - } - if(beg != (uint32_t)-1) - { - vis_flag[beg>>1] ^= flag; - } - if(sink != (uint32_t)-1) - { - vis_flag[sink>>1] ^= flag; - } - } - for (i = 0; i < res_utg->a.n; i++) - { - if(dedup[res_utg->a.a[i]>>1] == 3) - { - vis_flag[res_utg->a.a[i]>>1] ^= flag; - } - } - - - - asg_arc_t *av = NULL, *p = NULL; - uint32_t nv, c[2]; - - c[0] = c[1] = 0; - while (1) - { - c[0] = c[1] = 0; p = NULL; - v = pv<<1; - av = asg_arc_a(bub->ug->g, v); - nv = asg_arc_n(bub->ug->g, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - c[(!!(vis_flag[av[i].v>>1]&flag))]++; - if(p == NULL || p->ol > av[i].ol) - { - p = &(av[i]); - } - } - - - - - v = (pv<<1) + 1; - av = asg_arc_a(bub->ug->g, v); - nv = asg_arc_n(bub->ug->g, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - c[(!!(vis_flag[av[i].v>>1]&flag))]++; - if(p == NULL || p->ol > av[i].ol) - { - p = &(av[i]); - } - } - - if(p) - { - p->del = 1; - c[(!!(vis_flag[p->v>>1]&flag))]--; - if((p->v>>1) == pv) - { - asg_arc_del(bub->ug->g, (p->v)^1, (p->ul>>32)^1, 1); - c[0] = c[1] = 0; - v = pv<<1; - av = asg_arc_a(bub->ug->g, v); - nv = asg_arc_n(bub->ug->g, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - c[(!!(vis_flag[av[i].v>>1]&flag))]++; - } - - v = (pv<<1) + 1; - av = asg_arc_a(bub->ug->g, v); - nv = asg_arc_n(bub->ug->g, v); - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - c[(!!(vis_flag[av[i].v>>1]&flag))]++; - } - } - - - } - if(c[0] == 0 || c[1] == 0) break; - } - - - - - v = pv<<1; - av = asg_arc_a(bub->ug->g, v); - nv = asg_arc_n(bub->ug->g, v); - for (i = 0; i < nv; i++) - { - if(!av[i].del) continue; - av[i].del = 0; - kv_push(asg_arc_t, edges->a, av[i]); - } - - - v = (pv<<1) + 1; - av = asg_arc_a(bub->ug->g, v); - nv = asg_arc_n(bub->ug->g, v); - for (i = 0; i < nv; i++) - { - if(!av[i].del) continue; - av[i].del = 0; - kv_push(asg_arc_t, edges->a, av[i]); - } - - is_tangle[pv] = (uint8_t)-1; - - - u = &(bub->b_ug->u.a[s]); - for (i = 0; i < u->n; i++) - { - get_bubbles(bub, u->a[i]>>33, &beg, &sink, &a, &n, NULL); - - for (k_i = 0; k_i < n; k_i++) - { - vis_flag[a[k_i]>>1] ^= flag; - } - if(beg != (uint32_t)-1) - { - vis_flag[beg>>1] ^= flag; - } - if(sink != (uint32_t)-1) - { - vis_flag[sink>>1] ^= flag; - } - } - u = &(bub->b_ug->u.a[e]); - for (i = 0; i < u->n; i++) - { - get_bubbles(bub, u->a[i]>>33, &beg, &sink, &a, &n, NULL); - - for (k_i = 0; k_i < n; k_i++) - { - vis_flag[a[k_i]>>1] ^= flag; - } - if(beg != (uint32_t)-1) - { - vis_flag[beg>>1] ^= flag; - } - if(sink != (uint32_t)-1) - { - vis_flag[sink>>1] ^= flag; - } - } - for (i = 0; i < res_utg->a.n; i++) - { - if(dedup[res_utg->a.a[i]>>1] == 3) - { - vis_flag[res_utg->a.a[i]>>1] ^= flag; - } - } - - -} - -void delete_sg_e_by_ug(asg_t* rg, ma_ug_t* ug, uint32_t v, uint32_t w) -{ - uint32_t vx, wx; - 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_del(rg, vx, wx, 1); asg_arc_del(rg, wx^1, vx^1, 1); -} - -void resolve_bubble_chain_by_hic(ha_ug_index *idx, kv_u_trans_t *ta, bubble_type* bub) -{ - // double index_time = yak_realtime(); - ma_ug_t* ug = idx->ug; - ma_ug_t *bs_ug = bub->b_ug; - uint32_t v, u, i, max_i, nv, rv, n_vx, root, flag_pri = 1, flag_aux = 2, flag_ava = 4, occ; - double w, cutoff = 2; - uint32_t max_w_occ = 4; - asg_arc_t *av = NULL; - n_vx = bs_ug->g->n_seq << 1; - uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq<<1); - uint8_t *is_vis = NULL; CALLOC(is_vis, ug->g->n_seq<<1); - uint8_t *is_used = NULL; CALLOC(is_used, n_vx); - uint8_t *dedup = NULL; CALLOC(dedup, ug->g->n_seq<<1); - uint8_t *is_tangle = NULL; CALLOC(is_tangle, ug->g->n_seq); - buf_t b; memset(&b, 0, sizeof(buf_t)); - kvec_t_u32_warp stack, result, res_utg; - kv_init(stack.a); kv_init(result.a); kv_init(res_utg.a); - double *e_w = NULL; MALLOC(e_w, bs_ug->g->n_arc); - uint32_t *e_occ = NULL, *a_occ = NULL; CALLOC(e_occ, bs_ug->g->n_arc); - double *aw = NULL, max_w = 0; - kvec_asg_arc_t_warp edges; kv_init(edges.a); - ma_ug_t *back_bs_ug = copy_untig_graph(bs_ug); - - for (i = 0; i < bs_ug->g->n_arc; i++)///weight of bs_ug's edges - { - e_w[i] = -1; - } - - for (i = 0; i < bs_ug->g->n_seq; i++)///init all chain with flag_aux - { - set_b_utg_weight_flag(bub, &b, i<<1, vis, flag_aux, NULL); - } - - - for (v = 0; v < n_vx; v++) - { - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - aw = (&e_w[bs_ug->g->idx[v]>>32]); - a_occ = (&e_occ[bs_ug->g->idx[v]>>32]); - if(nv <= 1 || get_real_length(bs_ug->g, v, NULL) <= 1) continue; - set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); - - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - w = get_chain_weight_hic(bub, bs_ug, &b, av[i].v, v, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, NULL, &occ); - aw[i] = w; - a_occ[i] = occ; - } - - set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); - } - - - for (v = 0; v < n_vx; v++) - { - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - aw = (&e_w[bs_ug->g->idx[v]>>32]); - a_occ = (&e_occ[bs_ug->g->idx[v]>>32]); - if(nv <= 1 || get_real_length(bs_ug->g, v, NULL) <= 1) continue; - - for (i = rv = 0, max_i = (uint32_t)-1; i < nv; i++) - { - if(av[i].del) continue; - if(max_i == (uint32_t)-1) - { - max_i = i; - max_w = aw[i]; - } - else if(max_w < aw[i]) - { - max_i = i; - max_w = aw[i]; - } - rv++; - } - - if(max_i == (uint32_t)-1) continue; - ///if(max_w <= max_w_cutoff) continue; //must be <= - if(a_occ[max_i] <= max_w_occ) continue; //must be <= - if(rv < 2) continue; - - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - if(i == max_i) continue; - ///if((av[i].v>>1) == (v>>1) && aw[i] <= max_w_cutoff) continue; ///might be not reasonable - if((av[i].v>>1) == (v>>1) && a_occ[i] <= max_w_occ) continue; ///might be not reasonable - if(aw[i]*cutoff < max_w && double_check_bub_branch(&av[i], bs_ug, e_w, e_occ, cutoff, max_w_occ)) - { - av[i].del = 1; asg_arc_del(bs_ug->g, (av[i].v)^1, (av[i].ul>>32)^1, 1); - } - } - } - - uint32_t rId_0, ori_0, rId_1, ori_1, root_0, root_1; - for (v = 0; v < n_vx; v++) - { - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - rv = get_real_length(bs_ug->g, v, NULL); - if(nv == rv) continue;///no edge drop - if(rv != 1 || nv <= 1) continue; - get_real_length(bs_ug->g, v, &u); - u ^= 1; - if(get_real_length(bs_ug->g, u, NULL) != 1) continue; - drop_g_edges_by_utg(bub, bub->b_g, bs_ug, NULL, v, u); - if(is_used[v] || is_used[u]) continue; - - is_used[v] = is_used[u] = 1; - root = get_utg_end_from_btg(bub, bs_ug, v); - rId_0 = root>>1; - ori_0 = root&1; - get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); - - root = get_utg_end_from_btg(bub, bs_ug, u); - rId_1 = root>>1; - ori_1 = root&1; - get_bubbles(bub, rId_1, ori_1 == 1?&root_1:NULL, ori_1 == 0?&root_1:NULL, NULL, NULL, NULL); - - res_utg.a.n = 0; - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); - get_chain_weight_hic(bub, back_bs_ug, &b, u^1, v, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); - for (i = 0; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 1; - - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); - get_chain_weight_hic(bub, back_bs_ug, &b, v^1, u, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); - for (; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 2; - - for (i = 0; i < res_utg.a.n; i++) - { - if(dedup[res_utg.a.a[i]>>1] == 3) - { - is_tangle[res_utg.a.a[i]>>1] = 3; - } - else - { - if(is_tangle[res_utg.a.a[i]>>1] != 3) - { - is_tangle[res_utg.a.a[i]>>1] = 1; - } - } - dedup[res_utg.a.a[i]>>1] = 0; - } - } - - /*******************************for debug************************************/ - // for (i = 0; i < ug->g->n_seq; i++) - // { - // if(is_tangle[i] == 1) - // { - // fprintf(stderr, "*****tangle-utg%.6ul\n", i+1); - // } - // } - /*******************************for debug************************************/ - memset(is_used, 0, n_vx); - for (v = 0; v < n_vx; v++) - { - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - rv = get_real_length(bs_ug->g, v, NULL); - if(nv == rv) continue;///no edge drop - if(rv != 1 || nv <= 1) continue; - get_real_length(bs_ug->g, v, &u); - u ^= 1; - if(get_real_length(bs_ug->g, u, NULL) != 1) continue; - drop_g_edges_by_utg(bub, bub->b_g, bs_ug, NULL, v, u); - if(is_used[v] || is_used[u]) continue; - - is_used[v] = is_used[u] = 1; - root = get_utg_end_from_btg(bub, bs_ug, v); - rId_0 = root>>1; - ori_0 = root&1; - get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); - - root = get_utg_end_from_btg(bub, bs_ug, u); - rId_1 = root>>1; - ori_1 = root&1; - get_bubbles(bub, rId_1, ori_1 == 1?&root_1:NULL, ori_1 == 0?&root_1:NULL, NULL, NULL, NULL); - - res_utg.a.n = 0; - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); - get_chain_weight_hic(bub, back_bs_ug, &b, u^1, v, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); - for (i = 0; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 1; - - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); - get_chain_weight_hic(bub, back_bs_ug, &b, v^1, u, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); - for (; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 2; - - - /*******************************for debug************************************/ - // fprintf(stderr, "\nres_utg.a.n: %u, beg-utg%.6ul, sink-utg%.6ul\n", - // (uint32_t)res_utg.a.n, (root_0>>1)+1, (root_1>>1)+1); - // for (i = 0; i < res_utg.a.n; i++) - // { - // if(dedup[res_utg.a.a[i]>>1] == 3) - // { - // fprintf(stderr, "share-utg%.6ul\n", (res_utg.a.a[i]>>1)+1); - // } - // } - // for (i = 0; i < res_utg.a.n; i++) - // { - // if(dedup[res_utg.a.a[i]>>1] == 1) - // { - // fprintf(stderr, "1-utg%.6ul\n", (res_utg.a.a[i]>>1)+1); - // } - // } - // for (i = 0; i < res_utg.a.n; i++) - // { - // if(dedup[res_utg.a.a[i]>>1] == 2) - // { - // fprintf(stderr, "2-utg%.6ul\n", (res_utg.a.a[i]>>1)+1); - // } - // } - /*******************************for debug************************************/ - - clean_sub_tangle(bub, vis, &res_utg, dedup, is_tangle, NULL, flag_pri, v>>1, u>>1); - - for (i = 0; i < res_utg.a.n; i++) - { - dedup[res_utg.a.a[i]>>1] = 0; - } - } - - - edges.a.n = 0; - memset(is_used, 0, n_vx); - for (v = 0; v < n_vx; v++) - { - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - rv = get_real_length(bs_ug->g, v, NULL); - if(nv == rv) continue;///no edge drop - if(rv != 1 || nv <= 1) continue; - get_real_length(bs_ug->g, v, &u); - u ^= 1; - if(get_real_length(bs_ug->g, u, NULL) != 1) continue; - drop_g_edges_by_utg(bub, bub->b_g, bs_ug, NULL, v, u); - if(is_used[v] || is_used[u]) continue; - - is_used[v] = is_used[u] = 1; - root = get_utg_end_from_btg(bub, bs_ug, v); - rId_0 = root>>1; - ori_0 = root&1; - get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); - - root = get_utg_end_from_btg(bub, bs_ug, u); - rId_1 = root>>1; - ori_1 = root&1; - get_bubbles(bub, rId_1, ori_1 == 1?&root_1:NULL, ori_1 == 0?&root_1:NULL, NULL, NULL, NULL); - - res_utg.a.n = 0; - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); - get_chain_weight_hic(bub, back_bs_ug, &b, u^1, v, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); - for (i = 0; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 1; - - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); - get_chain_weight_hic(bub, back_bs_ug, &b, v^1, u, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); - set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); - for (; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 2; - - clean_sub_tangle(bub, vis, &res_utg, dedup, is_tangle, &edges, flag_pri, v>>1, u>>1); - - for (i = 0; i < res_utg.a.n; i++) - { - dedup[res_utg.a.a[i]>>1] = 0; - } - } - - - /*******************************for debug************************************/ - // for (i = 0; i < ug->g->n_seq; i++) - // { - // if(is_tangle[i] == 1) - // { - // fprintf(stderr, "####tangle-utg%.6ul\n", i+1); - // } - // } - - // for (i = 0; i < edges.a.n; i++) - // { - // fprintf(stderr, "s-utg%.6lul<------>d-utg%.6ul\n", (edges.a.a[i].ul>>33) + 1, (edges.a.a[i].v>>1) + 1); - - // } - /*******************************for debug************************************/ - if(edges.a.n > 0) - { - for (i = 0; i < edges.a.n; i++) - { - asg_arc_del(bub->ug->g, edges.a.a[i].ul>>32, edges.a.a[i].v, 1); - asg_arc_del(bub->ug->g, (edges.a.a[i].v)^1, (edges.a.a[i].ul>>32)^1, 1); - delete_sg_e_by_ug(idx->read_g, idx->ug, edges.a.a[i].ul>>32, edges.a.a[i].v); - delete_sg_e_by_ug(idx->read_g, idx->ug, (edges.a.a[i].v)^1, (edges.a.a[i].ul>>32)^1); - } - asg_cleanup(bub->ug->g); - asg_cleanup(idx->read_g); - } - - - free(vis); free(is_vis); free(is_used); free(dedup); free(b.b.a); free(e_w); free(e_occ); free(is_tangle); - kv_destroy(stack.a); kv_destroy(result.a); kv_destroy(res_utg.a); kv_destroy(edges.a); - ma_ug_destroy(back_bs_ug); - // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); -} - -void append_boundary_chain_hic(ma_ug_t* ug, kv_u_trans_t *ta, bubble_type* bub) -{ - // double index_time = yak_realtime(); - ma_ug_t *bs_ug = bub->b_ug; - uint32_t v, u, i, k, beg_idx, m, nv, n_vx, flag_pri = 1, flag_aux = 2, flag_ava = 4; - uint32_t root, rId_0, ori_0, root_0, new_bub; - asg_arc_t *av = NULL; - n_vx = bs_ug->g->n_seq << 1; - uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq<<1); - uint8_t *is_vis = NULL; CALLOC(is_vis, ug->g->n_seq<<1); - uint8_t *is_used = NULL; CALLOC(is_used, n_vx); - uint8_t *dedup = NULL; CALLOC(dedup, ug->g->n_seq<<1); - buf_t b; memset(&b, 0, sizeof(buf_t)); - kvec_t_u32_warp stack, result, res_utg; - kv_init(stack.a); kv_init(result.a); kv_init(res_utg.a); - kvec_asg_arc_t_warp edges; kv_init(edges.a); - - for (i = 0; i < bs_ug->g->n_seq; i++) - { - set_b_utg_weight_flag(bub, &b, i<<1, vis, flag_aux, NULL); - } - - if(bub->num.n > 0) bub->num.n--; - new_bub = bub->b_g->n_seq; - for (v = 0; v < n_vx; v++) - { - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - if(nv == 0 || get_real_length(bs_ug->g, v, NULL) == 0) continue; - res_utg.a.n = 0; - for (i = 0; i < nv; i++) - { - if(av[i].del) continue; - u = av[i].v^1; - beg_idx = res_utg.a.n; - set_b_utg_weight_flag_xor(bub, bs_ug, &b, u^1, vis, flag_pri, NULL); - get_chain_weight_hic(bub, bs_ug, &b, v^1, u, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); - set_b_utg_weight_flag_xor(bub, bs_ug, &b, u^1, vis, flag_pri, NULL); - for (k = m = beg_idx; k < res_utg.a.n; k++) - { - if(dedup[res_utg.a.a[k]>>1] != 0) continue; - dedup[res_utg.a.a[k]>>1] = 1; - res_utg.a.a[m] = res_utg.a.a[k]; - m++; - } - res_utg.a.n = m; - } - - for (k = 0; k < res_utg.a.n; k++) dedup[res_utg.a.a[k]>>1] = 0; - - root = get_utg_end_from_btg(bub, bs_ug, v); - rId_0 = root>>1; - ori_0 = root&1; - get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); - - if(root_0 != (uint32_t)-1 && (!IF_HOM(root_0>>1, *bub))) kv_push(uint32_t, res_utg.a, root_0); - - if(v&1) - { - update_bubble_graph(&res_utg, root_0^1, rId_0, (uint32_t)-1, (uint32_t)-1, bub, &edges, bub->b_g, NULL, NULL, ug, NULL, 0); - } - else - { - update_bubble_graph(&res_utg, (uint32_t)-1, (uint32_t)-1, root_0^1, rId_0, bub, &edges, bub->b_g, NULL, NULL, ug, NULL, 0); - } - } - kv_push(uint32_t, bub->num, bub->list.n); - new_bub = bub->b_g->n_seq - new_bub; - bub->mess_bub += new_bub; - ///actually not useful, and may have bug when one bubble at multipe chains - if(new_bub) update_bub_b_s_idx(bub); - - - for (v = 0; v < n_vx; v++) - { - av = asg_arc_a(bs_ug->g, v); - nv = asg_arc_n(bs_ug->g, v); - if(nv == 0 || get_real_length(bs_ug->g, v, NULL) == 0) continue; - drop_g_edges_by_utg(bub, bub->b_g, bs_ug, NULL, v, (uint32_t)-1); - } - - update_bsg(bub->b_g, &edges); - - ma_ug_destroy(bs_ug); - bs_ug = ma_ug_gen(bub->b_g); - bub->b_ug = bs_ug; - kv_destroy(bub->chain_weight); - ma_utg_t *u_x = NULL; - bs_ug = bub->b_ug; - kv_malloc(bub->chain_weight, bs_ug->u.n); bub->chain_weight.n = bs_ug->u.n; - for (i = 0; i < bs_ug->u.n; i++) - { - u_x = &(bs_ug->u.a[i]); - bub->chain_weight.a[i].id = i; - // if(u->n <= 1) ///not a chain - // { - // bub->chain_weight.a[i].b_occ = bub->chain_weight.a[i].g_occ = 0; - // bub->chain_weight.a[i].del = 1; - // } - // else - { - bub->chain_weight.a[i].del = 0; - calculate_chain_weight(u_x, bub, ug, &(bub->chain_weight.a[i])); - } - } - qsort(bub->chain_weight.a, bub->chain_weight.n, sizeof(chain_w_type), cmp_chain_weight); - - - - free(vis); free(is_vis); free(is_used); free(dedup); free(b.b.a); - kv_destroy(stack.a); kv_destroy(result.a); kv_destroy(res_utg.a); - kv_destroy(edges.a); - // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); -} - -double get_specific_hic_weight_by_chain(uint32_t uid, kv_u_trans_t *ta, uint8_t* vis, uint8_t flag) -{ - u_trans_t *e = u_trans_a(*ta, uid); - uint64_t k, e_n = u_trans_n(*ta, uid); - double w = 0; - - for (k = 0; k < e_n; k++) - { - if(e[k].del) continue; - if(vis[e[k].tn] != flag) continue; - w += (e[k].nw>=0?e[k].nw:-e[k].nw); - } - return w; -} - -void update_bubble_weight(bub_sort_vec* w_stack, uint32_t idx, kv_u_trans_t *ta, uint8_t* vis, uint32_t flag_cur) -{ - w_stack->a[idx].used = 1; - uint32_t k, m, uid = w_stack->a[idx].p_id>>1; - u_trans_t *e = u_trans_a(*ta, uid); - uint32_t e_n = u_trans_n(*ta, uid); - for (k = 0; k < e_n; k++) - { - if(e[k].del) continue; - if(vis[e[k].tn] != flag_cur) continue; - for (m = 0; m < w_stack->n; m++) - { - if(e[k].tn == (w_stack->a[m].p_id>>1)) break; - } - if(m >= w_stack->n) continue; - if(w_stack->a[m].used) continue; - w_stack->a[m].weight += (e[k].nw>=0?e[k].nw:-e[k].nw); - } -} - -void reorder_bubbble_chain(kv_u_trans_t *ta, bubble_type* bub, bub_sort_vec* w_stack, -uint8_t* vis, uint32_t n_utg, uint32_t chain_id) -{ - uint32_t i, k, m, max_idx, flag_cur = 3, flag_right = 2, flag_left = 1, flag_unset = 0, *a, n; - uint64_t bid, uid; - ma_utg_t *u = &(bub->b_ug->u.a[chain_id]); - memset(vis, flag_unset, n_utg); - for (i = 0; i < u->n; i++) - { - bid = u->a[i]>>33; - get_bubbles(bub, bid, NULL, NULL, &a, &n, NULL); - for (k = 0; k < n; k++) - { - uid = a[k]>>1; - vis[uid] = flag_right; - } - } - - for (i = 0; i < u->n; i++) - { - w_stack->n = 0; - bid = u->a[i]>>33; - get_bubbles(bub, bid, NULL, NULL, &a, &n, NULL); - kv_resize(bub_sort_type, *w_stack, n); - w_stack->n = n; - for (k = 0; k < n; k++) - { - uid = a[k]>>1; - vis[uid] = flag_cur; - w_stack->a[k].p_id = a[k]; - w_stack->a[k].weight = 0; - w_stack->a[k].used = 0; - } - - for (k = 0; k < w_stack->n; k++) - { - w_stack->a[k].weight += get_specific_hic_weight_by_chain(w_stack->a[k].p_id>>1, - ta, vis, flag_left); - w_stack->a[k].weight -= get_specific_hic_weight_by_chain(w_stack->a[k].p_id>>1, - ta, vis, flag_right); - } - m = 0; - while ((max_idx = get_max_hap_g(w_stack, NULL)) != (uint32_t)-1) - { - a[m] = w_stack->a[max_idx].p_id; - m++; - update_bubble_weight(w_stack, max_idx, ta, vis, flag_cur); - } - - while ((max_idx = get_max_hap_g(w_stack, &max_idx)) != (uint32_t)-1) - { - a[m] = w_stack->a[max_idx].p_id; - m++; - update_bubble_weight(w_stack, max_idx, ta, vis, flag_cur); - } - if(m != n) fprintf(stderr, "ERROR\n"); - - - for (k = 0; k < n; k++) - { - uid = a[k]>>1; - vis[uid] = flag_left; - } - } -} - -void reorder_bubbles(bubble_type* bub, kv_u_trans_t *ta, uint32_t n_utg) -{ - // double index_time = yak_realtime(); - uint8_t* vis = NULL; MALLOC(vis, n_utg); - bub_sort_vec w_stack; kv_init(w_stack); - uint32_t i; - - for (i = 0; i < bub->chain_weight.n; i++) - { - if(bub->chain_weight.a[i].del) continue; - reorder_bubbble_chain(ta, bub, &w_stack, vis, n_utg, bub->chain_weight.a[i].id); - } - - free(vis); kv_destroy(w_stack); - // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); -} - -void update_trans_g(ha_ug_index* idx, kv_u_trans_t *ta, bubble_type* bub) -{ - // double index_time = yak_realtime(); - // update_bubble_chain(idx->ug, bub, 0, 1); - - // resolve_bubble_chain_tangle(idx->ug, bub); - - clean_bubble_chain_by_hic(idx->ug, ta, bub); - - // print_debug_bubble_graph(bub, idx->ug, "bub-2"); - - // append_boundary_chain_hic(idx->ug, ta, bub); - - // fprintf(stderr, "s_bub: %lu, f_bub: %lu, b_bub: %lu, b_end_bub: %lu, tangle_bub: %lu, cross_bub: %lu, mess_bub: %lu\n", - // bub->s_bub, bub->f_bub, bub->b_bub, bub->b_end_bub, bub->tangle_bub, bub->cross_bub, bub->mess_bub); - - ///reorder_bubbles(bub, ta, idx->ug->g->n_seq); - // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); -} - -uint32_t get_max_unitig(H_partition* h, G_partition* g_p, hc_links* link, bubble_type* bub) -{ - double min, weight; - uint32_t i, min_i; - - for (i = 0, min = 1, min_i = (uint32_t)-1; i < g_p->n; i++) - { - if(h->lock[i]) continue; - weight = 0; - if(g_p->a[i].h[0] > 0 && (g_p->a[i].status[0] == 1 || g_p->a[i].status[0] == -1)) - { - weight += (g_p->a[i].weight[0] * g_p->a[i].status[0]); - } - - if(g_p->a[i].h[1] > 0 && (g_p->a[i].status[1] == 1 || g_p->a[i].status[1] == -1)) - { - weight += (g_p->a[i].weight[1] * g_p->a[i].status[1]); - } - weight += g_p->a[i].weight_convex*2; - - if(weight >= 0) continue; - if(weight < min) - { - min = weight; - min_i = i; - } - } - ///fprintf(stderr, "*****************min: %f\n", min); - return min_i; -} - -double get_cluster_weight_debug(G_partition* g_p, hc_links* link, uint32_t *h, uint32_t h_n) -{ - int o_d = 0; - double weight = 0; - uint32_t j, k, m, uID; - for (j = 0, weight = 0; j < h_n; j++) - { - for (k = 0; k < link->a.a[h[j]].e.n; k++) - { - if(link->a.a[h[j]].e.a[k].del) continue; - for (m = 0; m < h_n; m++) - { - if(h[m] == link->a.a[h[j]].e.a[k].uID) break; - } - if(m < h_n) continue; - - uID = link->a.a[h[j]].e.a[k].uID; - ///o_d = get_phase_status(hap, link->a.a[h[j]].e.a[k].uID); - o_d = g_p->a[g_p->index[uID]>>1].status[g_p->index[uID]&1]; - ///if(o_d < -1) fprintf(stderr, "ERROR\n"); - weight += (o_d*link->a.a[h[j]].e.a[k].weight); - } - } - - return weight; -} - -void flip_unitig(G_partition* g_p, hc_links* link, bubble_type* bub, uint32_t id) -{ - if(g_p->a[id].h[0] > 0 && g_p->a[id].status[0] != 1 && g_p->a[id].status[0] != -1) return; - if(g_p->a[id].h[1] > 0 && g_p->a[id].status[1] != 1 && g_p->a[id].status[1] != -1) return; - uint32_t k, j, m, *h0, h0_n, *h1, h1_n, uID, *h = NULL, h_n; - int status; - double weight; - get_phased_block(g_p, NULL, id, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); - // fprintf(stderr, "h0_n: %u, h1_n: %u\n", h0_n, h1_n); - if(h0_n > 0) - { - - status = g_p->a[id].status[0]; - // fprintf(stderr, "+status: %d\n", status); - h = h0; h_n = h0_n; - for (j = 0; j < h_n; j++) - { - // fprintf(stderr, "+j: %u, h_n: %u\n", j, h_n); - for (k = 0; k < link->a.a[h[j]].e.n; k++) - { - // fprintf(stderr, "+k: %u, e_n: %u\n", k, (uint32_t)link->a.a[h[j]].e.n); - if(link->a.a[h[j]].e.a[k].del) continue; - for (m = 0; m < h_n; m++) - { - if(h[m] == link->a.a[h[j]].e.a[k].uID) break; - } - // fprintf(stderr, "+m: %u, h_n: %u\n", m, h_n); - if(m < h_n) continue; - - uID = link->a.a[h[j]].e.a[k].uID; - - weight = link->a.a[h[j]].e.a[k].weight; - - if(g_p->index[uID] == (uint32_t)-1) continue; - - - g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1] -= (2*status*weight); - - - } - } - g_p->a[id].status[0] *= -1; - } - - // fprintf(stderr, "hehehe\n"); - if(h1_n > 0) - { - status = g_p->a[id].status[1]; - // fprintf(stderr, "-status: %d\n", status); - h = h1; h_n = h1_n; - for (j = 0; j < h_n; j++) - { - // fprintf(stderr, "-j: %u, h_n: %u\n", j, h_n); - for (k = 0; k < link->a.a[h[j]].e.n; k++) - { - // fprintf(stderr, "-k: %u, e_n: %u\n", k, (uint32_t)link->a.a[h[j]].e.n); - if(link->a.a[h[j]].e.a[k].del) continue; - for (m = 0; m < h_n; m++) - { - if(h[m] == link->a.a[h[j]].e.a[k].uID) break; - } - // fprintf(stderr, "-m: %u, h_n: %u\n", m, h_n); - if(m < h_n) continue; - - uID = link->a.a[h[j]].e.a[k].uID; - // fprintf(stderr, "-uID: %u\n", uID); - - weight = link->a.a[h[j]].e.a[k].weight; - - if(g_p->index[uID] == (uint32_t)-1) continue; - - - g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1] -= (2*status*weight); - - } - } - g_p->a[id].status[1] *= -1; - } -} - -void flip_unitig_debug(G_partition* g_p, hc_links* link, bubble_type* bub, uint32_t id) -{ - if(g_p->a[id].h[0] > 0 && g_p->a[id].status[0] != 1 && g_p->a[id].status[0] != -1) return; - if(g_p->a[id].h[1] > 0 && g_p->a[id].status[1] != 1 && g_p->a[id].status[1] != -1) return; - uint32_t k, j, m, *h0, h0_n, *h1, h1_n, uID, *h = NULL, h_n; - int status; - double weight; - get_phased_block(g_p, NULL, id, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); - // fprintf(stderr, "h0_n: %u, h1_n: %u\n", h0_n, h1_n); - if(h0_n > 0) - { - - status = g_p->a[id].status[0]; - // fprintf(stderr, "+status: %d\n", status); - h = h0; h_n = h0_n; - for (j = 0; j < h_n; j++) - { - // fprintf(stderr, "+j: %u, h_n: %u\n", j, h_n); - for (k = 0; k < link->a.a[h[j]].e.n; k++) - { - // fprintf(stderr, "+k: %u, e_n: %u\n", k, (uint32_t)link->a.a[h[j]].e.n); - if(link->a.a[h[j]].e.a[k].del) continue; - for (m = 0; m < h_n; m++) - { - if(h[m] == link->a.a[h[j]].e.a[k].uID) break; - } - // fprintf(stderr, "+m: %u, h_n: %u\n", m, h_n); - if(m < h_n) continue; - - uID = link->a.a[h[j]].e.a[k].uID; - - weight = link->a.a[h[j]].e.a[k].weight; - - if(g_p->index[uID] == (uint32_t)-1) continue; - - if(id == 19675) - { - fprintf(stderr, "+uID+: %u, e-weight: %f, g_p->index[uID]>>1: %u, status[0]: %d, pre_uID_weight: %f\n", - uID, weight, g_p->index[uID]>>1, status, g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1]); - } - - - g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1] -= (2*status*weight); - - if(id == 19675) - { - fprintf(stderr, "+uID+: %u, new_uID_weight: %f\n", uID, - g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1]); - } - - } - } - g_p->a[id].status[0] *= -1; - } - - // fprintf(stderr, "hehehe\n"); - if(h1_n > 0) - { - status = g_p->a[id].status[1]; - // fprintf(stderr, "-status: %d\n", status); - h = h1; h_n = h1_n; - for (j = 0; j < h_n; j++) - { - // fprintf(stderr, "-j: %u, h_n: %u\n", j, h_n); - for (k = 0; k < link->a.a[h[j]].e.n; k++) - { - // fprintf(stderr, "-k: %u, e_n: %u\n", k, (uint32_t)link->a.a[h[j]].e.n); - if(link->a.a[h[j]].e.a[k].del) continue; - for (m = 0; m < h_n; m++) - { - if(h[m] == link->a.a[h[j]].e.a[k].uID) break; - } - // fprintf(stderr, "-m: %u, h_n: %u\n", m, h_n); - if(m < h_n) continue; - - uID = link->a.a[h[j]].e.a[k].uID; - // fprintf(stderr, "-uID: %u\n", uID); - - weight = link->a.a[h[j]].e.a[k].weight; - - if(g_p->index[uID] == (uint32_t)-1) continue; - - if(id == 19675) - { - fprintf(stderr, "-uID-: %u, e-weight: %f, g_p->index[uID]>>1: %u, status[1]: %d, pre_uID_weight: %f\n", - uID, weight, g_p->index[uID]>>1, status, g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1]); - } - - g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1] -= (2*status*weight); - - if(id == 19675) - { - fprintf(stderr, "-uID-: %u, new_uID_weight: %f\n", uID, - g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1]); - } - } - } - g_p->a[id].status[1] *= -1; - } -} - - -uint32_t phasing_improvement(H_partition* h, G_partition* g_p, ha_ug_index* idx, bubble_type* bub, hc_links* link) -{ - uint32_t i, occ = 0, round = 0; - double pre_w, pre_total, current_w; - mul_block_phase_type b_x; - init_mul_block_phase_type(&b_x, g_p, bub, asm_opt.thread_num, h); - ///double index_time = yak_realtime(); - - while(1) - { - pre_w = get_total_weight(h, g_p); - pre_total = pre_w; - - while (1) - { - memset(h->lock, 0, sizeof(uint8_t)*g_p->n); - while (1) - { - i = get_max_unitig(h, g_p, link, bub); - if(i == (uint32_t)-1) break; - h->lock[i] = 1; - flip_unitig(g_p, link, bub, i); - occ++; - } - current_w = get_total_weight(h, g_p); - ///fprintf(stderr, "[M::%s::round single %u, pre_w: %f, current_w: %f]\n", __func__, round, pre_w, current_w); - if(ceil(current_w) <= ceil(pre_w)) break; - round++; - pre_w = current_w; - } - - - pre_w = get_total_weight(h, g_p); - round = 0; - while (1) - { - ///fprintf(stderr, "[M::%s::round block %u, h->n: %lu]\n", __func__, round, h->n); - phasing_improvement_by_block(h, g_p, bub, &b_x); - current_w = get_total_weight(h, g_p); - ///fprintf(stderr, "[M::%s::round block %u, pre_w: %f, current_w: %f]\n", __func__, round, pre_w, current_w); - if(ceil(current_w) <= ceil(pre_w)) break; - round++; - pre_w = current_w; - } - - if(ceil(current_w) <= ceil(pre_total)) break; - } - - destory_mul_block_phase_type(&b_x); - ///fprintf(stderr, "[M::%s:Flipping time:%.3f]\n", __func__, yak_realtime()-index_time); - - - for (i = 0; i < g_p->n; i++) - { - update_partition_flag(h, g_p, link, i); - } - - ///print_phase_group(g_p, bub, "Small"); - // double w0 = 0, w1 = 0; - // uint32_t *h0, h0_n, *h1, h1_n; - // get_phased_block(g_p, NULL, 2973, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); - // w0 = get_cluster_weight_debug(g_p, h->link, h0, h0_n); - // w1 = get_cluster_weight_debug(g_p, h->link, h1, h1_n); - // fprintf(stderr, "debug-w0: %f, g_p->a[2973].weight[0]: %f\n", w0, g_p->a[2973].weight[0]); - // fprintf(stderr, "debug-w1: %f, g_p->a[2973].weight[1]: %f\n", w1, g_p->a[2973].weight[1]); - - return !!occ; -} - -void destory_contig_partition(H_partition* hap) -{ - free(hap->lock); - free(hap->hap); - destory_G_partition(&(hap->g_p)); - destory_G_partition(&(hap->group_g_p)); - kv_destroy(hap->label_buffer); - kv_destroy(hap->b.vis); -} - -void label_unitigs(G_partition* g_p, ma_ug_t* ug) -{ - memset(R_INF.trio_flag, AMBIGU, R_INF.total_reads * sizeof(uint8_t)); - uint32_t i, k, j, *h0, h0_n, *h1, h1_n, uID, *h = NULL, h_n, flag = AMBIGU; - int status; - ma_utg_t *u = NULL; - - for (i = 0; i < g_p->n; i++) - { - if(g_p->a[i].h[0] > 0 && g_p->a[i].status[0] != 1 && g_p->a[i].status[0] != -1) continue; - if(g_p->a[i].h[1] > 0 && g_p->a[i].status[1] != 1 && g_p->a[i].status[1] != -1) continue; - get_phased_block(g_p, NULL, i, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); - - status = g_p->a[i].status[0]; - h = h0; h_n = h0_n; - if(status == 1) - { - flag = FATHER; - } - else if (status == -1) - { - flag = MOTHER; - } - for (j = 0; j < h_n; j++) - { - uID = h[j]; - u = &ug->u.a[uID]; - if(u->m == 0) continue; - for (k = 0; k < u->n; k++) - { - R_INF.trio_flag[u->a[k]>>33] = flag; - } - } - - - - status = g_p->a[i].status[1]; - h = h1; h_n = h1_n; - if(status == 1) - { - flag = FATHER; - } - else if (status == -1) - { - flag = MOTHER; - } - for (j = 0; j < h_n; j++) - { - uID = h[j]; - u = &ug->u.a[uID]; - if(u->m == 0) continue; - for (k = 0; k < u->n; k++) - { - R_INF.trio_flag[u->a[k]>>33] = flag; - } - } - } - - - uint64_t occ = 0; - for (i = 0; i < ug->u.n; i++) - { - occ += ug->u.a[i].n; - } - - ///fprintf(stderr, "# reads: %lu\n", occ); - - for (i = occ = 0; i < R_INF.total_reads; i++) - { - if(R_INF.trio_flag[i] == FATHER) occ++; - } - - ///fprintf(stderr, "# Father reads: %lu\n", occ); - - for (i = occ = 0; i < R_INF.total_reads; i++) - { - if(R_INF.trio_flag[i] == MOTHER) occ++; - } - - ///fprintf(stderr, "# Mother reads: %lu\n", occ); -} - -void label_unitigs_sm(int8_t *s, mc_gg_status *sa, ma_ug_t* ug) -{ - memset(R_INF.trio_flag, AMBIGU, R_INF.total_reads * sizeof(uint8_t)); - uint32_t i, k, flag = AMBIGU; - ma_utg_t *u = NULL; - - for (i = 0; i < ug->g->n_seq; i++) - { - if(ug->g->seq[i].del) continue; - flag = 0; - if(s) - { - if(s[i] == 0) continue; - flag = (s[i] > 0? FATHER:MOTHER); - } - - if(sa) - { - if(sa[i].s != 1 && sa[i].s != 2) continue; - flag = sa[i].s; - } - - u = &ug->u.a[i]; - if(u->m == 0) continue; - for (k = 0; k < u->n; k++) - { - R_INF.trio_flag[u->a[k]>>33] = flag; - } - } -} - - -void print_bubble_graph(bubble_type* bub, ma_ug_t* ug, const char* prefix, FILE *fp) -{ - uint32_t i, k, *a, n, beg, sink, x; - asg_t *b_g = bub->b_g; - char name[32]; - for (i = 0; i < b_g->n_seq; i++) - { - get_bubbles(bub, i, &beg, &sink, &a, &n, NULL); - sprintf(name, "%s%.6d%c", prefix, i, "fb"[if_bub?0:1]); - fprintf(stderr, "S\t%s\t*\tLN:i:%d\n", name, n); - - if(beg != (uint32_t)-1) fprintf(stderr, "A\tutg%.6d%c\t%s\n", (beg>>1)+1, "lc"[ug->u.a[(beg>>1)].circ], "beg"); - if(sink != (uint32_t)-1) fprintf(stderr, "A\tutg%.6d%c\t%s\n", (sink>>1)+1, "lc"[ug->u.a[(sink>>1)].circ], "sink"); - for (k = 0; k < n; k++) - { - x = a[k]>>1; - fprintf(stderr, "A\tutg%.6d%c\t%s\n", x+1, "lc"[ug->u.a[x].circ], "mid"); - } - } - - asg_arc_t* au = NULL; - uint32_t nu, u, v; - for (i = 0; i < b_g->n_seq; i++) - { - u = i<<1; - au = asg_arc_a(b_g, u); - nu = asg_arc_n(b_g, u); - for (k = 0; k < nu; k++) - { - if(au[k].del) continue; - v = au[k].v; - fprintf(stderr, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", - prefix, u>>1, "fb"[(u>>1)f_bub?0:1], "+-"[u&1], - prefix, v>>1, "fb"[(v>>1)f_bub?0:1], "+-"[v&1], 0, 0); - - - asg_arc_t* av = asg_arc_a(b_g, v^1); - uint32_t nv = asg_arc_n(b_g, v^1), m; - for (m = 0; m < nv; m++) - { - if(av[m].del) continue; - if(av[m].v == (u^1)) break; - } - - if(m == nv) fprintf(stderr, "sb1sb, nv: %u, nu: %u\n", nv, nu); - } - - - u = (i<<1) + 1; - au = asg_arc_a(ug->g, u); - nu = asg_arc_n(ug->g, u); - for (k = 0; k < nu; k++) - { - if(au[k].del) continue; - v = au[k].v; - fprintf(stderr, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", - prefix, u>>1, "fb"[(u>>1)f_bub?0:1], "+-"[u&1], - prefix, v>>1, "fb"[(v>>1)f_bub?0:1], "+-"[v&1], 0, 0); - - asg_arc_t* av = asg_arc_a(b_g, v^1); - uint32_t nv = asg_arc_n(b_g, v^1), m; - for (m = 0; m < nv; m++) - { - if(av[m].del) continue; - if(av[m].v == (u^1)) break; - } - - if(m == nv) fprintf(stderr, "sb2sb, nv: %u, nu: %u\n", nv, nu); - } - } -} - - - -void print_bubble_utg(bubble_type* bub, ma_ug_t* unitig_ug, const char* prefix, FILE *fp) -{ - uint32_t i, k, *a, n, beg, sink, x, occ; - ma_ug_t *b_ug = bub->b_ug; - char name[32]; - for (i = 0; i < b_ug->u.n; i++) - { - ma_utg_t *p = &b_ug->u.a[i]; - if(p->n == 0) continue; - for (k = occ = 0; k < p->n; k++) - { - x = p->a[k]>>33; - get_bubbles(bub, x, &beg, &sink, &a, &n, NULL); - occ += n; - } - sprintf(name, "%s%.6d%c", prefix, i + 1, "lc"[p->circ]); - fprintf(fp, "S\t%s\t*\tLN:i:%u\n", name, occ); - for (k = 0; k < p->n; k++) - { - x = p->a[k]>>33; - get_bubbles(bub, x, &beg, &sink, &a, &n, NULL); - if(beg != (uint32_t)-1) fprintf(fp, "A\tutg%.6d%c\t%u\t%s\n", (beg>>1)+1, "lc"[unitig_ug->u.a[(beg>>1)].circ], n, "beg"); - if(sink != (uint32_t)-1) fprintf(fp, "A\tutg%.6d%c\t%u\t%s\n", (sink>>1)+1, "lc"[unitig_ug->u.a[(sink>>1)].circ], n, "sink"); - } - } - - asg_arc_t* au = NULL; - uint32_t nu, u, v, j; - for (i = 0; i < b_ug->u.n; ++i) { - if(b_ug->u.a[i].m == 0) continue; - if(b_ug->u.a[i].circ) - { - fprintf(fp, "L\t%s%.6dc\t+\t%s%.6dc\t+\t%dM\tL1:i:%d\n", - prefix, i+1, prefix, i+1, 0, 0); - fprintf(fp, "L\t%s%.6dc\t-\t%s%.6dc\t-\t%dM\tL1:i:%d\n", - prefix, i+1, prefix, i+1, 0, 0); - } - u = i<<1; - au = asg_arc_a(b_ug->g, u); - nu = asg_arc_n(b_ug->g, u); - for (j = 0; j < nu; j++) - { - if(au[j].del) continue; - v = au[j].v; - fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", - prefix, (u>>1)+1, "lc"[b_ug->u.a[u>>1].circ], "+-"[u&1], - prefix, (v>>1)+1, "lc"[b_ug->u.a[v>>1].circ], "+-"[v&1], 0, 0); - } - - - u = (i<<1) + 1; - au = asg_arc_a(b_ug->g, u); - nu = asg_arc_n(b_ug->g, u); - for (j = 0; j < nu; j++) - { - if(au[j].del) continue; - v = au[j].v; - fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", - prefix, (u>>1)+1, "lc"[b_ug->u.a[u>>1].circ], "+-"[u&1], - prefix, (v>>1)+1, "lc"[b_ug->u.a[v>>1].circ], "+-"[v&1], 0, 0); - } - } - - -} - - -void print_debug_bubble_graph(bubble_type* bub, ma_ug_t* ug, const char *fn) -{ - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.bub.gfa", fn); - FILE* fp = fopen(buf, "w"); - - print_bubble_utg(bub, ug, "btg", fp); - - fclose(fp); - free(buf); -} - -void print_bubble_chain(bubble_type* bub) -{ - uint32_t m, i, k; - uint32_t beg, sink, *a = NULL, n; - uint64_t bid; - ma_utg_t *u = NULL; - for (m = 0; m < bub->chain_weight.n; m++) - { - if(bub->chain_weight.a[m].del) continue; - u = &(bub->b_ug->u.a[bub->chain_weight.a[m].id]); - fprintf(stderr, "\nChain_id=%lu\n", bub->chain_weight.a[m].id); - for (i = 0; i < u->n; i++) - { - bid = u->a[i]>>33; - get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); - fprintf(stderr, "btg%.6lu%c, beg-utg%.6ul, sink-utg%.6ul\n", - bid, "fb"[bidf_bub?0:1], (beg>>1)+1, (sink>>1)+1); - for (k = 0; k < n; k++) - { - if(k != 0 && (k%5)==0) fprintf(stderr, "\n"); - fprintf(stderr, "m-utg%.6ul\t", (a[k]>>1)+1); - } - fprintf(stderr, "\n"); - - } - } -} - -void init_contig_H_partition(bubble_type* bub, ha_ug_index* idx, H_partition* hap) -{ - uint32_t i, k_i, k_j, uID, *a = NULL, n, *h0, h0_n, *h1, h1_n; - destory_G_partition(&(hap->group_g_p)); memset(&(hap->group_g_p), 0, sizeof(G_partition)); - init_G_partition(&(hap->group_g_p), hap->n); - partition_warp *res = NULL; - ma_utg_t *u_x = NULL; - chain_hic_warp *c_w = &(bub->c_w); - - for (i = 0; i < bub->c_w.n; i++) - { - kv_pushp(partition_warp, hap->group_g_p, &res); - kv_init(res->a); - res->full_bub = 0; - res->h[0] = res->h[1] = 0; - - res->status[0] = 1; res->status[1] = -1; - res->weight[0] = res->weight[1] = res->weight_convex = 0; - - - u_x = (*c_w).a[(*c_w).a[i].id].u; - for (k_i = 0; k_i < u_x->n; k_i++) - { - get_bubbles(bub, u_x->a[k_i]>>33, NULL, NULL, &a, &n, NULL); - for (k_j = 0; k_j < n; k_j++) - { - uID = a[k_j]>>1; - if((*c_w).chain_idx[uID] != (*c_w).a[i].id) continue; - if(get_phase_status(hap, uID)==1) - { - kv_push(uint32_t, res->a, uID); - res->h[0]++; - } - } - } - - for (k_i = 0; k_i < u_x->n; k_i++) - { - get_bubbles(bub, u_x->a[k_i]>>33, NULL, NULL, &a, &n, NULL); - for (k_j = 0; k_j < n; k_j++) - { - uID = a[k_j]>>1; - if((*c_w).chain_idx[uID] != (*c_w).a[i].id) continue; - if(get_phase_status(hap, uID)==-1) - { - kv_push(uint32_t, res->a, uID); - res->h[1]++; - } - } - } - - - for (k_i = 0; k_i < res->h[0]; k_i++) - { - ///if(hap->group_g_p.index[res->a.a[k_i]] != (uint32_t)-1) fprintf(stderr, "ERROR---00\n"); - hap->group_g_p.index[res->a.a[k_i]] = hap->group_g_p.n-1; - hap->group_g_p.index[res->a.a[k_i]] = hap->group_g_p.index[res->a.a[k_i]] << 1; - } - - for (; k_i < res->a.n; k_i++) - { - ///if(hap->group_g_p.index[res->a.a[k_i]] != (uint32_t)-1) fprintf(stderr, "ERROR---11\n"); - hap->group_g_p.index[res->a.a[k_i]] = hap->group_g_p.n-1; - hap->group_g_p.index[res->a.a[k_i]] = (hap->group_g_p.index[res->a.a[k_i]] << 1) + 1; - } - - get_phased_block(&(hap->group_g_p), NULL, i, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); - if(h0_n >0) res->weight[0] = get_cluster_weight(hap, hap->link, h0, h0_n); - if(h1_n >0) res->weight[1] = get_cluster_weight(hap, hap->link, h1, h1_n); - res->weight_convex = get_cluster_inner_weight(hap, hap->link, h0, h0_n, h1, h1_n); - } - - flip_by_node(hap, &(hap->group_g_p), bub); - label_unitigs(&(hap->group_g_p), idx->ug); -} - -void reset_H_partition(H_partition* hap, uint32_t is_init) -{ - if(!is_init) - { - hap->n = 0; - free(hap->lock); - free(hap->hap); - hap->m[0] = hap->m[1] = hap->m[2] = (uint32_t)-1; - hap->label = hap->label_add = hap->label_shift = (uint32_t)-1; - destory_G_partition(&(hap->g_p)); memset(&(hap->g_p), 0, sizeof(G_partition)); - destory_G_partition(&(hap->group_g_p)); memset(&(hap->group_g_p), 0, sizeof(G_partition)); - kv_destroy(hap->label_buffer); kv_init(hap->label_buffer); - kv_destroy(hap->b.vis); kv_init(hap->b.vis); memset(&(hap->b), 0, sizeof(block_phase_type)); - } - - memset(hap, 0, sizeof(H_partition)); -} - - -int alignment_worker_pipeline(sldat_t* sl, const enzyme *fn1, const enzyme *fn2) -{ - double index_time = yak_realtime(); - int i; - for (i = 0; i < fn1->n && i < fn2->n; i++) - { - gzFile fp1, fp2; - if ((fp1 = gzopen(fn1->a[i], "r")) == 0) return 0; - if ((fp2 = gzopen(fn2->a[i], "r")) == 0) return 0; - sl->ks1 = kseq_init(fp1); - sl->ks2 = kseq_init(fp2); - - kt_pipeline(3, worker_pipeline, sl, 3); - - kseq_destroy(sl->ks1); - kseq_destroy(sl->ks2); - gzclose(fp1); - gzclose(fp2); - } - fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); - - dedup_hits(&(sl->hits), 1); - return 1; -} - -void debug_gfa_space(ha_ug_index* idx, ma_ug_t* ug, trans_chain* t_ch, kv_u_trans_t *ref) -{ - bubble_type bub; - memset(&bub, 0, sizeof(bubble_type)); - bub.round_id = 0; bub.n_round = 2; - - identify_bubbles(ug, &bub, t_ch->ir_het, ref); - - hc_links link; - init_hc_links(&link, ug->g->n_seq, t_ch); - - measure_distance(idx, ug, NULL, &link, &bub, &(t_ch->k_trans)); - - // uint32_t i, k; - // for (i = 0; i < link.a.n; ++i) - // { - // for (k = 0; k < link.a.a[i].e.n; k++) - // { - // if(link.a.a[i].e.a[k].del || link.a.a[i].e.a[k].dis == (uint64_t)-1) continue; - // fprintf(stderr, "s-utg%.6dl\td-utg%.6dl\t%lu\n", - // (int)(i+1), (int)(link.a.a[i].e.a[k].uID+1), - // link.a.a[i].e.a[k].dis == (uint64_t)-1? (uint64_t)-1 : link.a.a[i].e.a[k].dis>>3); - // } - // } - - - - destory_bubbles(&bub); - destory_hc_links(&link); -} - -void idx_hc_links(kvec_pe_hit* hits, ha_ug_index* idx, bubble_type* bub) -{ - uint64_t k, l; - uint32_t qn, tn; - - kv_resize(uint64_t, hits->idx, idx->ug->g->n_seq); - hits->idx.n = idx->ug->g->n_seq; - memset(hits->idx.a, 0, hits->idx.n*sizeof(uint64_t)); - - kv_resize(uint64_t, hits->occ, idx->ug->g->n_seq); - hits->occ.n = idx->ug->g->n_seq; - memset(hits->occ.a, 0, hits->occ.n*sizeof(uint64_t)); - - radix_sort_pe_hit_idx_an1(hits->a.a, hits->a.a + hits->a.n); - for (k = 1, l = 0; k <= hits->a.n; ++k) - { - if (k == hits->a.n || - ((hits->a.a[k].s<<1)>>(64 - idx->uID_bits)) != ((hits->a.a[l].s<<1)>>(64 - idx->uID_bits))) - { - if (k - l > 1) radix_sort_pe_hit_idx_an2(hits->a.a + l, hits->a.a + k); - - hits->idx.a[((hits->a.a[l].s<<1)>>(64 - idx->uID_bits))] - = (uint64_t)l << 32 | (k - l); - - for (; l < k; l++) - { - qn = ((hits->a.a[l].s<<1)>>(64 - idx->uID_bits)); - tn = ((hits->a.a[l].e<<1)>>(64 - idx->uID_bits)); - if(bub && IF_HOM(qn, *bub)) continue; - if(bub && IF_HOM(tn, *bub)) continue; - hits->occ.a[qn]++; - hits->occ.a[tn]++; - } - - l = k; - } - } -} - -inline uint32_t trans_checking_pass(bubble_type* bub, kv_u_trans_t *ref, uint32_t x, uint32_t y) -{ - if(u_trans_n(*ref, x) == 0 || u_trans_n(*ref, y) == 0) return 0; - u_trans_t *a = NULL; - uint32_t n, i, f[2], qn, tn; - - qn = x; tn = y; - a = u_trans_a(*ref, qn); n = u_trans_n(*ref, qn); - for (i = 0, f[0] = f[1] = 0; i < n; i++) - { - if(a[i].del) continue; - if(a[i].f == RC_2) continue; - if(IF_HOM(a[i].tn, *bub)) continue; - f[(a[i].tn == tn && a[i].f != RC_2)]++; - } - if(f[0] != 0) return 0; - if(f[1] == 0) return 0; - - qn = y; tn = x; - a = u_trans_a(*ref, qn); n = u_trans_n(*ref, qn); - for (i = 0, f[0] = f[1] = 0; i < n; i++) - { - if(a[i].del) continue; - if(IF_HOM(a[i].tn, *bub)) continue; - f[(a[i].tn == tn && a[i].f != RC_2)]++; - } - if(f[0] != 0) return 0; - if(f[1] == 0) return 0; - - fprintf(stderr, "M::%s::s-utg%.6ul<----->d-utg%.6ul\n", __func__, x+1, y+1); - return 1; -} - -uint32_t get_u_trans_spec_idx(kv_u_trans_t *ta, uint32_t qn, uint32_t tn, u_trans_t **r_a, uint32_t *occ, uint32_t *idx) -{ - if(r_a) (*r_a) = NULL; - if(occ) (*occ) = 0; - if(idx) (*idx) = (uint32_t)-1; - u_trans_t *a = NULL; - uint32_t n, st, i; - a = u_trans_a(*ta, qn); - n = u_trans_n(*ta, qn); - for (st = 0, i = 1; i <= n; ++i) - { - if (i == n || a[i].tn != a[st].tn) - { - if(a[st].tn == tn) - { - if(r_a) (*r_a) = a + st; - if(occ) (*occ) = i - st; - if(idx) (*idx) = st + ((*ta).idx.a[(qn)]>>32); - return 1; - } - st = i; - } - } - return 0; -} - -void interpr_hit(ha_ug_index* idx, uint64_t x, uint32_t rLen, uint32_t *uid, uint32_t *beg, uint32_t *end); -int hic_sc_type(ha_ug_index* idx, kvec_pe_hit* hits, uint64_t k) -{ - uint32_t s_uid, s_beg, s_end, e_uid, e_beg, e_end, slen, elen, x = 0; - - interpr_hit(idx, hits->a.a[k].s, hits->a.a[k].len>>32, &s_uid, &s_beg, &s_end); - s_beg = (s_beg+s_end)>>1; slen = idx->ug->u.a[s_uid].len; - if(s_beg >= (slen>>1)) x+=1; - - interpr_hit(idx, hits->a.a[k].e, (uint32_t)hits->a.a[k].len, &e_uid, &e_beg, &e_end); - e_beg = (e_beg+e_end)>>1; elen = idx->ug->u.a[e_uid].len; - if(e_beg >= (elen>>1)) x+=2; - return x; -} - -void weight_kv_u_trans(ha_ug_index* idx, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, -kv_u_trans_t *ta, trans_idx* dis, int sc_weight) -{ - uint64_t k, i, shif = 64 - idx->uID_bits, beg, end, t_d; - u_trans_t *e1 = NULL, *e2 = NULL; - long double weight; - double *sw = NULL; - u_trans_t *p = NULL; - uint32_t is_cc, ii1, ii2; - - for (i = 0, ta->idx.n = ta->n = 0; i < link->a.n; i++) - { - for (k = 0; k < link->a.a[i].e.n; k++) - { - if(link->a.a[i].e.a[k].del) continue; - if(IF_HOM(i, *bub)) continue; - if(IF_HOM(link->a.a[i].e.a[k].uID, *bub)) continue; - if(i == link->a.a[i].e.a[k].uID) continue; - - kv_pushp(u_trans_t, *ta, &p); - memset(p, 0, sizeof(u_trans_t)); - p->qn = i; p->tn = link->a.a[i].e.a[k].uID; - p->nw = 0; p->occ = 0; - } - } - kt_u_trans_t_idx(ta, idx->ug->g->n_seq); - if(sc_weight) { - k = ta->n*3; - MALLOC(sw, k); - for (i = 0; i < k; i++) sw[i] = 0; - } - - - for (k = 0; k < hits->a.n; ++k) - { - beg = ((hits->a.a[k].s<<1)>>shif); - end = ((hits->a.a[k].e<<1)>>shif); - - if(beg == end) continue; - if(IF_HOM(beg, *bub)) continue; - if(IF_HOM(end, *bub)) continue; - if(is_hom_hit(hits->a.a[k])) continue; - - t_d = get_hic_distance(&(hits->a.a[k]), link, idx, &is_cc); - // if(t_d == (uint64_t)-1) continue; - // if(t_d == (uint64_t)-1 && is_cc == 0) continue; - // if(t_d == (uint64_t)-1 && !dis) continue; - - get_u_trans_spec_idx(ta, beg, end, &e1, NULL, &ii1); - get_u_trans_spec_idx(ta, end, beg, &e2, NULL, &ii2); - - if(e1 == NULL || e2 == NULL) continue; - weight = 1; - if(dis) weight = get_trans_weight_advance(idx, t_d, dis); - - if(sc_weight){ - i = hic_sc_type(idx, hits, k); - if(i == 0){ - e1->nw -= weight; e2->nw -= weight; - } - else{ - i--; - sw[(ii1*3)+i] -= weight; - sw[(ii2*3)+i] -= weight; - } - } else{ - e1->nw -= weight; e2->nw -= weight; - } - e1->occ++; e2->occ++; - } - - if(sc_weight) { - for (i = 0; i < ta->n; ++i){ - if(ta->a[i].nw > sw[(i*3)]) ta->a[i].nw = sw[(i*3)]; - if(ta->a[i].nw > sw[(i*3)+1]) ta->a[i].nw = sw[(i*3)+1]; - if(ta->a[i].nw > sw[(i*3)+2]) ta->a[i].nw = sw[(i*3)+2]; - ta->a[i].nw *= 2/**4**/; - } - free(sw); - } -} - -void interpr_hit(ha_ug_index* idx, uint64_t x, uint32_t rLen, uint32_t *uid, uint32_t *beg, uint32_t *end) -{ - if(uid) (*uid) = ((x<<1)>>(64 - idx->uID_bits)); - uint32_t rev = (x>>63); - long long ref_p = x & idx->pos_mode; - long long p_beg, p_end; - - if(rev) - { - p_end = ref_p; - p_beg = p_end + 1 - rLen; - } - else - { - p_beg = ref_p; - p_end = p_beg + rLen - 1; - } - if(p_beg < 0) p_beg = 0; - if(p_end < 0) p_end = 0; - if(beg) (*beg) = p_beg; - if(end) (*end) = p_end + 1; -} -double get_interval_weight(ha_ug_index* idx, hc_links* link, trans_idx* dis, -pe_hit *hits, uint32_t occ, uint32_t qid, uint32_t qs, uint32_t qe, uint32_t tid, uint32_t ts, uint32_t te) -{ - int64_t s_idx = 0, e_idx = (int64_t)occ - 1, m_idx = 0; - uint32_t m_uid = (uint32_t)-1; - while (s_idx <= e_idx) - { - m_idx = s_idx + (e_idx - s_idx)/2; - m_uid = ((hits[m_idx].e<<1)>>(64 - idx->uID_bits)); - if (m_uid == tid) - break; - if (m_uid < tid) - s_idx = m_idx + 1; - else - e_idx = m_idx - 1; - } - if(m_uid != tid) return 0; - - - uint32_t k, s_uid, s_beg, s_end, e_uid, e_beg, e_end; - uint64_t t_d; - double w, weight; - w = 0; - for (k = m_idx; k < occ; k++)///all hits of qid - { - interpr_hit(idx, hits[k].s, hits[k].len>>32, &s_uid, &s_beg, &s_end); - if(s_uid != qid) continue; - if(!(qs <= s_beg && qe >= s_end)) continue; - - interpr_hit(idx, hits[k].e, (uint32_t)hits[k].len, &e_uid, &e_beg, &e_end); - if(e_uid != tid) break; - if(!(ts <= e_beg && te >= e_end)) continue; - - t_d = get_hic_distance(&hits[k], link, idx, NULL); - if(t_d == (uint64_t)-1) continue; - - weight = 1; - if(dis) weight = get_trans_weight_advance(idx, t_d, dis); - - w += weight; - } - - for (m_idx -= 1; m_idx >= 0; m_idx--) - { - k = m_idx; - interpr_hit(idx, hits[k].s, hits[k].len>>32, &s_uid, &s_beg, &s_end); - if(s_uid != qid) continue; - if(!(qs <= s_beg && qe >= s_end)) continue; - - interpr_hit(idx, hits[k].e, (uint32_t)hits[k].len, &e_uid, &e_beg, &e_end); - if(e_uid != tid) break; - if(!(ts <= e_beg && te >= e_end)) continue; - - t_d = get_hic_distance(&hits[k], link, idx, NULL); - if(t_d == (uint64_t)-1) continue; - - weight = 1; - if(dis) weight = get_trans_weight_advance(idx, t_d, dis); - - w += weight; - } - return w; -} - -double get_hits_weight(ha_ug_index* idx, bubble_type* bub, kvec_pe_hit* hits, hc_links* link, trans_idx* dis, -u_trans_t *t_a, uint32_t t_n, uint32_t qid, kv_u_trans_t *ta_idx) -{ - /****************************may have bugs********************************/ - ///need to record self hits - ///if(u_trans_n(*ta_idx, qid) == 0) return 0;///no hit bridging qid - /****************************may have bugs********************************/ - uint32_t k, i, x_n, y; - u_trans_t *x_a = NULL; - double occ_q, occ_t; - double w, i_w; - for (k = 0, w = 0; k < t_n; k++) - { - if(IF_HOM(qid, *bub)) continue; - if(IF_HOM(t_a[k].tn, *bub)) continue; - /****************************may have bugs********************************/ - if(qid != t_a[k].tn) - { - x_n = u_trans_n(*ta_idx, qid); x_a = u_trans_a(*ta_idx, qid); y = t_a[k].tn; - if(u_trans_n(*ta_idx, t_a[k].tn) < x_n) - { - x_n = u_trans_n(*ta_idx, t_a[k].tn); x_a = u_trans_a(*ta_idx, t_a[k].tn); y = qid; - } - if(x_n == 0) continue; - - for (i = 0; i < x_n; i++) - { - if(x_a[i].tn == y) break; - } - if(i >= x_n) continue; ///no hit bridging tn and qid - } - /****************************may have bugs********************************/ - occ_q = hits->occ.a[qid]; - occ_t = hits->occ.a[t_a[k].tn] * ((double)(t_a[k].te - t_a[k].ts) / (double)(idx->ug->g->seq[t_a[k].tn].len)); - if(occ_t < 1) occ_t = 1; - - ///q--->t hits - i_w = get_interval_weight(idx, link, dis, hits->a.a + (hits->idx.a[qid]>>32), - (uint32_t)(hits->idx.a[qid]), qid, 0, idx->ug->g->seq[qid].len, t_a[k].tn, - t_a[k].ts, t_a[k].te); - if(i_w != 0) i_w /= (MIN(occ_q, occ_t)); - w += i_w; - if(t_a[k].tn == qid) continue; - - ///t--->q hits - i_w = get_interval_weight(idx, link, dis, hits->a.a + (hits->idx.a[t_a[k].tn]>>32), - (uint32_t)(hits->idx.a[t_a[k].tn]), t_a[k].tn, t_a[k].ts, t_a[k].te, - qid, 0, idx->ug->g->seq[qid].len); - if(i_w != 0) i_w /= (MIN(occ_q, occ_t)); - w += i_w; - } - return w; -} - - -void adjust_weight_kv_u_trans(ha_ug_index* idx, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, -kv_u_trans_t *ta, kv_u_trans_t *ref, trans_idx* dis) -{ - u_trans_t *a = NULL, *p = NULL; - uint32_t n, k, i, m, qn, tn; - uint8_t *vis = NULL; CALLOC(vis, idx->ug->g->n_seq); - double w; - - for (i = m = 0; i < ta->n; i++) - { - if(ta->a[i].del) continue; - if(IF_HOM(ta->a[i].qn, *bub)) continue; - if(IF_HOM(ta->a[i].tn, *bub)) continue; - ta->a[m] = ta->a[i]; - if(ta->a[m].nw != 0) - { - ta->a[m].nw /= (double)(MIN(hits->occ.a[ta->a[m].qn], hits->occ.a[ta->a[m].tn])); - } - /*******************************for debug************************************/ - // trans_checking_pass(bub, ref, ta->a[i].qn, ta->a[i].tn); - // if(trans_checking_pass(bub, ref, ta->a[i].qn, ta->a[i].tn)) ta->a[m].nw = 0; - /*******************************for debug************************************/ - - m++; - } - ta->n = m; - - for (k = 0; k < ta->idx.n; k++)///all nodes - { - if(IF_HOM(k, *bub)) continue; - a = u_trans_a(*ta, k); - n = u_trans_n(*ta, k); - ///for each pair qn, tn - ///count hic pairs between (qn, tn^) and (qn^1, tn) - for (i = 0, vis[k] = 1; i < n; i++) - { - vis[a[i].tn] = 1; - if(a[i].qn == a[i].tn) continue; - if(IF_HOM(a[i].qn, *bub)) continue; - if(IF_HOM(a[i].tn, *bub)) continue; - ///(qn, tn^) - a[i].nw += get_hits_weight(idx, bub, hits, link, dis, - u_trans_a(*ref, a[i].tn), u_trans_n(*ref, a[i].tn), a[i].qn, ta); - ///(qn^1, tn) - a[i].nw += get_hits_weight(idx, bub, hits, link, dis, - u_trans_a(*ref, a[i].qn), u_trans_n(*ref, a[i].qn), a[i].tn, ta); - } - - - for (i = 0; i < ta->idx.n; i++)///all edges - { - qn = k; tn = i; w = 0; - if(IF_HOM(qn, *bub)) continue; - if(IF_HOM(tn, *bub)) continue; - if(vis[tn]) continue; - if(qn == tn) continue; - ///(qn, tn^) - w += get_hits_weight(idx, bub, hits, link, dis, - u_trans_a(*ref, tn), u_trans_n(*ref, tn), qn, ta); - ///(qn^1, tn) - w += get_hits_weight(idx, bub, hits, link, dis, - u_trans_a(*ref, qn), u_trans_n(*ref, qn), tn, ta); - if(w == 0) continue; - kv_pushp(u_trans_t, *ta, &p); - memset(p, 0, sizeof(u_trans_t));///extra edges - p->nw = w; p->qn = qn; p->tn = tn; - } - - // for (i = 0; i < u_trans_n(*ref, k); i++)///only trans edges - // { - // qn = k; tn = (u_trans_a(*ref, k))[i].tn; w = 0; - // if(IF_HOM(qn, *bub)) continue; - // if(IF_HOM(tn, *bub)) continue; - // if(vis[tn]) continue; - // if(qn == tn) continue; - // ///(qn, tn^) - // w += get_hits_weight(idx, hits, link, dis, - // u_trans_a(*ref, tn), u_trans_n(*ref, tn), qn, ta); - // ///(qn^1, tn) - // w += get_hits_weight(idx, hits, link, dis, - // u_trans_a(*ref, qn), u_trans_n(*ref, qn), tn, ta); - // if(w == 0) continue; - // kv_pushp(u_trans_t, *ta, &p); - // memset(p, 0, sizeof(u_trans_t));///extra edges - // p->nw = w; p->qn = qn; p->tn = tn; - // } - - for (i = 0, vis[k] = 0; i < n; i++) vis[a[i].tn] = 0; - } - - // fprintf(stderr, "------ta->n=%u\n", (uint32_t)ta->n); - - for (i = m = 0; i < ta->n; i++) - { - if(ta->a[i].nw == 0 || ta->a[i].del) continue; - ta->a[m] = ta->a[i]; - m++; - } - ta->n = m; - - free(vis); - kt_u_trans_t_idx(ta, idx->ug->g->n_seq); -} - - -inline uint32_t get_trans_interval_weight(ha_ug_index* idx, hc_links* link, bubble_type* bub, -trans_idx* dis, pe_hit *hit, uint32_t hit_n, uint32_t qn, uint32_t qs, uint32_t qe, uint32_t tn, -uint32_t ts, uint32_t te, double *w_a) -{ - uint32_t i, s_uid, s_beg, s_end, e_uid, e_beg, e_end, found, is_cc; - uint64_t t_d; - double weight; - (*w_a) = 0; found = 0; - for (i = 0; i < hit_n; i++)///all hits already have the same qn and tn - { - if(is_hom_hit(hit[i])) continue; - interpr_hit(idx, hit[i].s, hit[i].len>>32, &s_uid, &s_beg, &s_end); - if(s_uid != qn) continue; - if(!(qs <= s_beg && qe >= s_end)) continue; - - interpr_hit(idx, hit[i].e, (uint32_t)hit[i].len, &e_uid, &e_beg, &e_end); - if(e_uid != tn) continue; - if(!(ts <= e_beg && te >= e_end)) continue; - - t_d = get_hic_distance(&hit[i], link, idx, &is_cc); - // if(t_d == (uint64_t)-1) continue; - // if(t_d == (uint64_t)-1 && is_cc == 0) continue; - // if(t_d == (uint64_t)-1 && !dis) continue; - - weight = 1; - if(dis) weight = get_trans_weight_advance(idx, t_d, dis); - - (*w_a) += weight; - found = 1; - } - - return found; -} - - -void append_trans_hits(ha_ug_index* idx, hc_links* link, bubble_type* bub, -trans_idx* dis, pe_hit *hit, uint32_t hit_n, uint64_t *hit_occ, kv_u_trans_t *ref, -kv_u_trans_t *res, uint32_t qn, uint32_t tn) -{ - u_trans_t *r_a = NULL, *p = NULL, *q = NULL; - uint32_t r_n, i; - uint64_t occ_q, occ_t; - double w; - - ///qn -> tn^ - { - r_a = u_trans_a(*ref, tn); - r_n = u_trans_n(*ref, tn); - for (i = 0; i < r_n; i++) - { - if(IF_HOM(r_a[i].tn, *bub)) continue; - if(r_a[i].tn == qn) continue; - - if(!get_trans_interval_weight(idx, link, bub, dis, hit, hit_n, - qn, 0, idx->ug->g->seq[qn].len, tn, r_a[i].qs, r_a[i].qe, &w)) - { - continue; - } - - occ_q = hit_occ[qn]; - occ_t = (hit_occ[tn] * ((double)(r_a[i].qe - r_a[i].qs)/(double)(idx->ug->g->seq[tn].len))) + 0.5; - if(occ_t < 1) occ_t = 1; - - kv_pushp(u_trans_t, *res, &p); - memset(p, 0, sizeof(u_trans_t)); - p->qn = qn; p->tn = r_a[i].tn; - p->nw = w/**r_a[i].occ**/; - p->occ = MIN(occ_q, occ_t); - - kv_pushp(u_trans_t, *res, &q); - (*q) = (*p); q->qn = p->tn; q->tn = p->qn; - } - } - - if(qn == tn) return; - - ///tn -> qn^ - { - r_a = u_trans_a(*ref, qn); - r_n = u_trans_n(*ref, qn); - for (i = 0; i < r_n; i++) - { - if(IF_HOM(r_a[i].tn, *bub)) continue; - if(r_a[i].tn == tn) continue; - - if(!get_trans_interval_weight(idx, link, bub, dis, hit, hit_n, - qn, r_a[i].qs, r_a[i].qe, tn, 0, idx->ug->g->seq[tn].len, &w)) - { - continue; - } - - occ_q = (hit_occ[qn] * ((double)(r_a[i].qe - r_a[i].qs)/(double)(idx->ug->g->seq[qn].len))) + 0.5; - occ_t = hit_occ[tn]; - if(occ_q < 1) occ_q = 1; - kv_pushp(u_trans_t, *res, &p); - memset(p, 0, sizeof(u_trans_t)); - p->qn = tn; p->tn = r_a[i].tn; - p->nw = w/**r_a[i].occ**/; - p->occ = MIN(occ_q, occ_t); - - kv_pushp(u_trans_t, *res, &q); - (*q) = (*p); q->qn = p->tn; q->tn = p->qn; - } - } - -} - -double merge_u_trans_list(u_trans_t* a, uint32_t a_n) -{ - radix_sort_u_trans_occ(a, a + a_n); - uint32_t k, l, i; - double weight, w = 0; - for (k = 1, l = 0; k <= a_n; ++k) - { - if (k == a_n || a[k].occ != a[l].occ) - { - for (i = l, weight = 0; i < k; i++) - { - weight += a[i].nw; - } - - /*******************************for debug************************************/ - // w += (weight/(double)(a[l].occ)); - w += weight; - /*******************************for debug************************************/ - l = k; - } - } - return w; -} - -void adjust_weight_kv_u_trans_advance(ha_ug_index* idx, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, -kv_u_trans_t *ta, kv_u_trans_t *ref, trans_idx* dis) -{ - double index_time = yak_realtime(); - uint32_t k, l, m, h_occ; - uint64_t shif = 64 - idx->uID_bits, qn, tn; - double w; - pe_hit *h_a = NULL; - - for (k = m = 0; k < ta->n; k++) - { - if(ta->a[k].nw == 0) continue; - ta->a[k].occ = MIN(hits->occ.a[ta->a[k].qn], hits->occ.a[ta->a[k].tn]); - if(ta->a[k].occ == 0) continue; - ta->a[m] = ta->a[k]; - m++; - } - ta->n = m; - - for (qn = 0; qn < hits->idx.n; qn++) - { - if(IF_HOM(qn, *bub)) continue; - h_a = hits->a.a + (hits->idx.a[qn]>>32); - h_occ = (uint32_t)(hits->idx.a[qn]); - - for (k = 1, l = 0; k <= h_occ; ++k) ///same qn - { - if (k == h_occ || ((h_a[k].e<<1)>>shif) != ((h_a[l].e<<1)>>shif)) //same tn - { - tn = ((h_a[l].e<<1)>>shif); - if(!IF_HOM(tn, *bub)) - { - append_trans_hits(idx, link, bub, dis, h_a+l, k-l, hits->occ.a, ref, ta, qn, tn); - } - l = k; - } - } - } - - radix_sort_u_trans_m(ta->a, ta->a + ta->n); - - for (k = 1, l = 0, m = 0; k <= ta->n; ++k) - { - if (k == ta->n || (ta->a[k].qn != ta->a[l].qn || ta->a[k].tn != ta->a[l].tn)) - { - w = merge_u_trans_list(ta->a + l, k - l); - if(w != 0) - { - ta->a[m] = ta->a[l]; - ta->a[m].nw = w; - ta->a[m].occ = 0; - m++; - } - l = k; - } - } - ta->n = m; - - kt_u_trans_t_idx(ta, idx->ug->g->n_seq); - fprintf(stderr, "[M::%s::%.3f] \n", __func__, yak_realtime()-index_time); -} - -void print_kv_weight(kv_u_trans_t *ta, int8_t *s) -{ - uint32_t i; - // u_trans_t *e = NULL; - fprintf(stderr, "\n[M::%s]\n", __func__); - fprintf(stderr, "*********ta->n: %u\n", (uint32_t)ta->n); - for (i = 0; i < ta->n; i++) - { - fprintf(stderr, "+s-utg%.6ul(s:%d)\td-utg%.6ul(s:%d)\tw-%f\n", - ta->a[i].qn+1, s[ta->a[i].qn], ta->a[i].tn+1, s[ta->a[i].tn], ta->a[i].nw); - /** - get_u_trans_spec(ta, ta->a[i].tn, ta->a[i].qn, &e, NULL); - if(e) - { - fprintf(stderr, "-d-utg%.6ul->s-utg%.6ul: %f\n", e->qn+1, e->tn+1, e->nw); - } - else - { - fprintf(stderr, "ERROR"); - } - **/ - } -} - -void print_debug_hc_links(ha_ug_index* idx, bubble_type* bub, hc_links* lk, kv_u_trans_t *ta, kvec_pe_hit* hits) -{ - uint64_t k, len = 0, occ = 0, shif = 64 - idx->uID_bits, beg, end; - hc_edge *e = NULL; - for (k = 0; k < hits->a.n; ++k) - { - beg = ((hits->a.a[k].s<<1)>>shif); - end = ((hits->a.a[k].e<<1)>>shif); - if(beg == end) continue; - if(IF_HOM(beg, *bub)) continue; - if(IF_HOM(end, *bub)) continue; - len += (hits->a.a[k].len>>32) + ((uint32_t)hits->a.a[k].len); - occ++; - } - - fprintf(stderr, "# total Hi-C aligned bases: %lu\n", len); - fprintf(stderr, "# total Hi-C aligned pairs: %lu\n", occ); - for (k = 0; k < ta->n; k++) - { - e = get_hc_edge(lk, ta->a[k].qn, ta->a[k].tn, 0); - fprintf(stderr, "s-utg%.6ul\td-utg%.6ul\tD:%lu\tW:%f\n", - ta->a[k].qn+1, ta->a[k].tn+1, e->dis == (uint64_t)-1? (uint64_t)-1 : e->dis>>3, ta->a[k].nw); - } -} -void renew_kv_u_trans(kv_u_trans_t *ta, hc_links *lk, kvec_pe_hit* hits, kv_u_trans_t *ref, -ha_ug_index* idx, bubble_type* bub, int8_t *s, mc_gg_status *sa, uint32_t ignore_dis) -{ - uint64_t k, i, m, is_comples_weight = 0; - trans_idx dis; - kv_init(dis); - if(bub->round_id > 0 && ignore_dis == 0) - { - is_comples_weight = get_trans_rate_function_advance(idx, hits, lk, bub, NULL, s, sa, &dis); - } - - for (i = 0; i < lk->a.n; i++) - { - for (k = m = 0; k < lk->a.a[i].e.n; k++) - { - if(lk->a.a[i].e.a[k].del) continue; - lk->a.a[i].e.a[m] = lk->a.a[i].e.a[k]; - lk->a.a[i].e.a[m].weight = 0; - lk->a.a[i].e.a[m].occ = 0; - m++; - } - lk->a.a[i].e.n = m; - } - - if(hits->idx.n == 0) idx_hc_links(hits, idx, bub); - - weight_kv_u_trans(idx, hits, lk, bub, ta, is_comples_weight == 1? &dis : NULL, asm_opt.flag&HA_F_USKEW?0:1); - // if(bub->round_id == bub->n_round-1) - // { - // print_debug_hc_links(idx, bub, lk, ta, hits); - // } - // adjust_weight_kv_u_trans(idx, hits, lk, bub, ta, ref, is_comples_weight == 1? &dis : NULL); - adjust_weight_kv_u_trans_advance(idx, hits, lk, bub, ta, ref, is_comples_weight == 1? &dis : NULL); - kv_destroy(dis); - // print_kv_weight(ta); -} - -void print_kv_u_trans(kv_u_trans_t *ta, hc_links* lk, int8_t *s) -{ - uint32_t i; - u_trans_t *p = NULL; - hc_edge *e = NULL; - - for (i = 0; i < ta->n; i++) - { - p = &(ta->a[i]); - e = get_hc_edge(lk, p->qn, p->tn, 0); - fprintf(stderr, "s-utg%.6ul\tS(%d)\td-utg%.6ul\tS(%d)\trev(%u)\td(%lld)\ttw(%f)\n", - p->qn+1, s[p->qn], p->tn+1, s[p->tn], p->rev, - (e == NULL || e->dis == (uint64_t)-1)? -1 : (long long)(e->dis>>3), p->nw); - } - -} - -ps_t* init_ps_t(uint64_t seed, uint64_t n) -{ - ps_t *s = NULL; CALLOC(s, 1); - s->xs = seed; - CALLOC(s->s, n); - s->n = n; - return s; -} - -void destory_ps_t(ps_t **s) -{ - free((*s)->s); - free((*s)); -} - -uint32_t is_hom_map(uint64_t x, uint32_t len, mc_interval_t *p, uint32_t *p_idx, ha_ug_index* idx) -{ - mc_interval_t *a = NULL; - uint32_t uid, qs, qe, as, ae, occ, k; - uint64_t oLen; - interpr_hit(idx, x, len, &uid, &qs, &qe); - - a = p + p_idx[uid]; - occ = p_idx[uid+1] - p_idx[uid]; - for (k = 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(oLen == 0) continue; - if(oLen > len*0.2) return 1; - } - return 0; -} - -void update_hits(ha_ug_index* idx, kvec_pe_hit* hits, uint8_t *r_het) -{ - ma_ug_t *ug = idx->ug; - asg_t *rg = idx->read_g; - uint32_t k, v, l, offset, l_pos; - asg_t* nsg = ug->g; - ma_utg_t *u = NULL; - mc_interval_t *t = NULL; - kvec_t(mc_interval_t) p; kv_init(p); - kvec_t(uint32_t) p_idx; kv_init(p_idx); - - kv_push(uint32_t, p_idx, 0); - for (v = 0; v < nsg->n_seq; v++) - { - u = &(ug->u.a[v]); - for (k = 1, l = 0, offset = 0, l_pos = 0; k <= u->n; ++k) - { - if (k == u->n || r_het[u->a[k]>>33] != r_het[u->a[l]>>33]) - { - if(r_het[u->a[l]>>33] == N_HET)///only keep hom suregions - { - kv_pushp(mc_interval_t, p, &t); - t->uID = v; - t->hs = r_het[u->a[l]>>33]; - - t->bS = l_pos; - t->bE = offset + rg->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_idx, p.n); - } - - - for (k = 0; k < hits->a.n; ++k) - { - hits->a.a[k].id = (uint64_t)-1; - if(is_hom_map(hits->a.a[k].s, hits->a.a[k].len>>32, p.a, p_idx.a, idx) || - is_hom_map(hits->a.a[k].e, (uint32_t)hits->a.a[k].len, p.a, p_idx.a, idx)) - { - continue; - } - hits->a.a[k].id = 0; - } - - kv_destroy(p); kv_destroy(p_idx); -} - -void verbose_het_stat(bubble_type *bub) -{ - uint64_t i, hetBase = 0, homBase = 0; - for (i = 0; i < bub->ug->g->n_seq; i++) - { - if(IF_HOM(i, *bub)) homBase += bub->ug->g->seq[i].len; - else hetBase += bub->ug->g->seq[i].len; - } - - fprintf(stderr, "[M::stat] # heterozygous bases: %lu; # homozygous bases: %lu\n", hetBase, homBase); -} - -void debug_output_disconnected_hits(ha_ug_index* idx, kv_u_trans_t *ta, kvec_pe_hit *hits, hc_links *link, bubble_type *bub, int8_t *s) -{ - uint32_t k, l, i, m, h_occ; - uint64_t shif = 64 - idx->uID_bits, qn, tn, u_dis; - pe_hit *h_a = NULL; - hc_linkeage *t = NULL; - u_trans_t *p = NULL; - kv_u_trans_t k_trans; - kv_init(k_trans); - - - for (qn = 0; qn < hits->idx.n; qn++) - { - if(IF_HOM(qn, *bub)) continue; - h_a = hits->a.a + (hits->idx.a[qn]>>32); - h_occ = (uint32_t)(hits->idx.a[qn]); - - for (k = 1, l = 0; k <= h_occ; ++k) ///same qn - { - if (k == h_occ || ((h_a[k].e<<1)>>shif) != ((h_a[l].e<<1)>>shif)) //same qn and tn - { - tn = ((h_a[l].e<<1)>>shif); - if(!IF_HOM(tn, *bub) && tn != qn) - { - // t = &(link->a.a[qn]); - // for (i = 0, u_dis = (uint64_t)-1; i < t->e.n; i++) - // { - // if(t->e.a[i].del || t->e.a[i].uID != tn) continue; - // u_dis = (t->e.a[i].dis ==(uint64_t)-1? (uint64_t)-1 : t->e.a[i].dis>>3); - // break; - // } - - // if(u_dis == (uint64_t)-1) - { - kv_pushp(u_trans_t, k_trans, &p); - p->qn = qn; p->tn = tn; p->occ = (k-l); - kv_pushp(u_trans_t, k_trans, &p); - p->qn = tn; p->tn = qn; p->occ = (k-l); - } - } - l = k; - } - } - } - - - radix_sort_u_trans_m(k_trans.a, k_trans.a + k_trans.n); - - for (k = 1, l = 0, m = 0; k <= k_trans.n; ++k) - { - if (k == k_trans.n || k_trans.a[l].qn != k_trans.a[k].qn || k_trans.a[l].tn != k_trans.a[k].tn) //same qn and tn - { - for (i = l, h_occ = 0; i < k; i++) - { - h_occ += k_trans.a[i].occ; - } - - k_trans.a[m] = k_trans.a[l]; - k_trans.a[m].occ = ((uint32_t)-1) - h_occ; - m++; - l = k; - } - } - k_trans.n = m; - - radix_sort_u_trans_occ(k_trans.a, k_trans.a + k_trans.n); - for (i = 0; i < k_trans.n; i++) - { - qn = k_trans.a[i].qn; - tn = k_trans.a[i].tn; - - t = &(link->a.a[qn]); - for (k = 0, u_dis = (uint64_t)-1; k < t->e.n; k++) - { - if(t->e.a[k].del || t->e.a[k].uID != tn) continue; - u_dis = (t->e.a[k].dis ==(uint64_t)-1? (uint64_t)-1 : t->e.a[k].dis>>3); - break; - } - get_u_trans_spec(ta, qn, tn, &p, NULL); - - fprintf(stderr, "s-utg%.6lul[hap-%d]<--->d-utg%.6lul[hap-%d](occ: %u, ", - qn + 1, s[qn], tn + 1, s[tn], ((uint32_t)-1) - k_trans.a[i].occ); - if(p) fprintf(stderr, "weight: %f", p->nw); - else fprintf(stderr, "weight: NA"); - fprintf(stderr, "):(dis-%lu)\n", u_dis); - } - - // fprintf(stderr, "########hits########\n"); - // char dir[2] = {'+', '-'}; - // for (k = 0; k < hits->a.n; ++k) - // { - // fprintf(stderr, "%c\tutg%.6dl(len-%u)\t%lu\t%c\tutg%.6dl(len-%u)\t%lu\ti:%lu\n", - // dir[hits->a.a[k].s>>63], (int)((hits->a.a[k].s<<1)>>shif)+1, - // idx->ug->g->seq[((hits->a.a[k].s<<1)>>shif)].len, hits->a.a[k].s&idx->pos_mode, - // dir[hits->a.a[k].e>>63], (int)((hits->a.a[k].e<<1)>>shif)+1, - // idx->ug->g->seq[((hits->a.a[k].e<<1)>>shif)].len, hits->a.a[k].e&idx->pos_mode, - // hits->a.a[k].id); - // } - kv_destroy(k_trans); -} - -void resolve_tangles_hic(ha_ug_index *idx, bubble_type *bub, kvec_pe_hit *hits, kv_u_trans_t *ta) -{ - uint32_t i, k, l, m, h_occ; - uint64_t shif = 64 - idx->uID_bits, qn, tn; - pe_hit *h_a = NULL; - u_trans_t *p = NULL; - identify_bubbles(idx->ug, bub, idx->t_ch->ir_het, &(idx->t_ch->k_trans)); - ta->idx.n = ta->n = 0; - if(hits->idx.n == 0) idx_hc_links(hits, idx, NULL); - for (qn = 0; qn < hits->idx.n; qn++) - { - h_a = hits->a.a + (hits->idx.a[qn]>>32); - h_occ = (uint32_t)(hits->idx.a[qn]); - - for (k = 1, l = 0; k <= h_occ; ++k) ///same qn - { - if (k == h_occ || ((h_a[k].e<<1)>>shif) != ((h_a[l].e<<1)>>shif)) //same qn and tn - { - tn = ((h_a[l].e<<1)>>shif); - if(tn != qn) - { - kv_pushp(u_trans_t, *ta, &p); - p->qn = qn; p->tn = tn; p->occ = (k-l); - kv_pushp(u_trans_t, *ta, &p); - p->qn = tn; p->tn = qn; p->occ = (k-l); - } - l = k; - } - } - } - radix_sort_u_trans_m(ta->a, ta->a + ta->n); - for (k = 1, l = 0, m = 0; k <= ta->n; ++k) - { - if (k == ta->n || ta->a[l].qn != ta->a[k].qn || ta->a[l].tn != ta->a[k].tn) //same qn and tn - { - for (i = l, h_occ = 0; i < k; i++) - { - h_occ += ta->a[i].occ; - } - - qn = ta->a[l].qn; - tn = ta->a[l].tn; - ta->a[m] = ta->a[l]; - ta->a[m].occ = h_occ; - ta->a[m].nw = (h_occ*SCALL)/(MIN(hits->occ.a[qn], hits->occ.a[tn])); - m++; - l = k; - } - } - ta->n = m; - kt_u_trans_t_idx(ta, idx->ug->g->n_seq); - - resolve_bubble_chain_by_hic(idx, ta, bub); - ta->idx.n = ta->n = 0; -} - - -void print_kv_u_trans_t(kv_u_trans_t *ta, ma_ug_t* ug) -{ - uint32_t i; - u_trans_t *p = NULL; - for (i = 0; i < ta->n; i++) - { - p = &(ta->a[i]); - fprintf(stderr, "q-utg%.6ul\tql(%u)\tqs(%u)\tqe(%u)\tt-utg%.6ul\ttl(%u)\tts(%u)\tte(%u)\trev(%u)\tw(%f)\tf(%u)\n", - p->qn+1, ug->u.a[p->qn].len, p->qs, p->qe, p->tn+1, ug->u.a[p->tn].len, p->ts, p->te, p->rev, p->nw, p->f); - } - fprintf(stderr, "[M::%s::] \n", __func__); -} - -void write_ps_t(ps_t *s, const char *fn) -{ - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.hic.pst.bin", fn); - FILE* fp = fopen(buf, "w"); - - fwrite(&(s->xs), sizeof(s->xs), 1, fp); - fwrite(&(s->n), sizeof(s->n), 1, fp); - fwrite(s->s, sizeof(int8_t), s->n, fp); - - fclose(fp); - free(buf); -} - -int load_ps_t(ps_t **s, const char *fn) -{ - uint64_t flag = 0; - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.hic.pst.bin", fn); - FILE* fp = NULL; - fp = fopen(buf, "r"); - if(!fp) return 0; - CALLOC(*s, 1); - flag += fread(&((*s)->xs), sizeof((*s)->xs), 1, fp); - flag += fread(&((*s)->n), sizeof((*s)->n), 1, fp); - MALLOC((*s)->s, (*s)->n); - flag += fread((*s)->s, sizeof(int8_t), (*s)->n, fp); - - fclose(fp); - free(buf); - return 1; -} - -int cmp_kv_u_weight(const void * a, const void * b) -{ - if((*(u_trans_t*)a).nw == (*(u_trans_t*)b).nw) return 0; - return ((*(u_trans_t*)a).nw) > ((*(u_trans_t*)b).nw)?-1:1; -} - -typedef struct{ - uint64_t s, e; -} f_chain_t; - -typedef struct{ - f_chain_t* a; - size_t n, m; - kvec_t(uint64_t) b; - double tw; - uint64_t tov; -} kv_f_chain; - -void insert_dip_chain(kv_f_chain *x, u_trans_t *p, double LenRate) -{ - uint32_t i; - uint64_t ovlp = 0, tLen = MIN(x->tov, p->qe-p->qs); - int64_t dp, old_dp, start = 0; - f_chain_t *t = NULL; - double r; - for (i = 0; i < x->n; i++) - { - ovlp += ((MIN(x->a[i].e, p->qe) > MAX(x->a[i].s, p->qs))? - (MIN(x->a[i].e, p->qe) - MAX(x->a[i].s, p->qs)):0); - } - if(tLen > 0 && ovlp > tLen*LenRate) - { - r = ((double)ovlp)/((double)tLen); - if(r >= 0.75) - { - if(p->nw <= x->tw*0.75) p->del = 1; - } - else - { - if(p->nw <= x->tw*0.5) p->del = 1; - } - } - - if(!p->del) - { - x->tw += p->nw - (((double)ovlp)/((double)(p->qe-p->qs)))*p->nw; - - kv_push(uint64_t, x->b, p->qs<<1); - kv_push(uint64_t, x->b, p->qe<<1|1); - if(x->b.n > 2 && x->b.a[x->b.n-2] < x->b.a[x->b.n-3]) - { - radix_sort_hc64(x->b.a, x->b.a + x->b.n); - } - x->n = 0; x->tov = 0; - for (i = 0, dp = 0, start = 0; i < x->b.n; ++i) - { - old_dp = dp; - ///if a[j] is qe - if (x->b.a[i]&1) - { - --dp; - } - else - { - ++dp; - } - - - if (old_dp < 1 && dp >= 1) ///old_dp < dp, b.a[j] is qs - { - ///case 2, a[j] is qs - start = x->b.a[i]>>1; - } - else if (old_dp >= 1 && dp < 1) ///old_dp > min_dp, b.a[j] is qe - { - kv_pushp(f_chain_t, *x, &t); - t->s = start; t->e = x->b.a[i]>>1; - x->tov += t->e - t->s; - } - } - } -} - -uint32_t get_MAPQ(u_trans_t *a, uint32_t a_n, uint32_t idx, double secondRate) -{ - uint32_t i; - u_trans_t *p = &(a[idx]); - uint64_t ovlp = 0; - double aw = 0; - for (i = 0; i < a_n; i++) - { - if(i == idx) continue; - ovlp = ((MIN(a[i].qe, p->qe) > MAX(a[i].qs, p->qs))? - (MIN(a[i].qe, p->qe) - MAX(a[i].qs, p->qs)):0); - // if(p->qn == 447 && p->tn == 5495) - // { - // fprintf(stderr, "ovlp: %lu, secondRate: %f, len: %u\n", ovlp, secondRate, MIN(a[i].qe - a[i].qs, p->qe - p->qs)); - // } - if(ovlp == 0) continue; - if(ovlp <= (secondRate*MIN(a[i].qe - a[i].qs, p->qe - p->qs))) continue; - - aw += a[i].nw; - } - // if(p->qn == 447 && p->tn == 5495) fprintf(stderr, "aw: %f\n", aw); - aw = aw/p->nw; - // if(p->qn == 447 && p->tn == 5495) fprintf(stderr, "aw: %f\n", aw); - if(aw >= 1) return 16; - if(aw >= 0.75) return 8; - if(aw >= 0.5) return 4; - if(aw >= 0.25) return 2; - return 1; -} - -void filter_kv_u_trans_t(kv_u_trans_t *ta, ma_ug_t* ug, double secondRate) -{ - kv_f_chain x; - memset(&x, 0, sizeof(kv_f_chain)); x.tw = 0; - uint32_t k, i, n; - u_trans_t *a = NULL; - for (k = 0; k < ta->idx.n; k++) - { - a = u_trans_a(*ta, k); - n = u_trans_n(*ta, k); - if(n == 0) continue; - qsort(a, n, sizeof(u_trans_t), cmp_kv_u_weight); - x.n = 0; x.tov = 0; x.tw = 0; x.b.n = 0; - for (i = 0; i < n; i++) - { - if(a[i].del) continue; - insert_dip_chain(&x, &(a[i]), secondRate); - } - } - free(x.a); free(x.b.a); - kt_u_trans_t_idx(ta, ug->g->n_seq); - kt_u_trans_t_simple_symm(ta, ug->g->n_seq, 0); - - - /** - for (k = 0; k < ta->idx.n; k++) - { - a = u_trans_a(*ta, k); - n = u_trans_n(*ta, k); - if(n == 0) continue; - // radix_sort_k_trans_qs(a, a+n); - for (i = 0; i < n; i++) - { - a[i].occ = get_MAPQ(a, n, i, secondRate); - // if(a[i].occ != 1) - // { - // uint32_t debug_i; - // fprintf(stderr, "\nq-utg%.6ul\tt-utg%.6ul\tocc-%u\n", a[i].qn+1, a[i].tn+1, a[i].occ); - - - // for (debug_i = 0; debug_i < n; debug_i++) - // { - // fprintf(stderr, "q-utg%.6ul\tqs(%u)\tqe(%u)\tt-utg%.6ul\tts(%u)\tte(%u)\trev(%u)\tw(%f)\tf(%u)\n", - // a[debug_i].qn+1, a[debug_i].qs, a[debug_i].qe, a[debug_i].tn+1, a[debug_i].ts, - // a[debug_i].te, a[debug_i].rev, a[debug_i].nw, a[debug_i].f); - // } - // } - } - } - - for (k = 0; k < ta->n; k++) - { - if(ta->a[k].del || ta->a[k].qn > ta->a[k].tn) continue; - get_u_trans_spec(ta, ta->a[k].tn, ta->a[k].qn, &r_a, NULL); - a = &(ta->a[k]); - a->occ = r_a->occ = MAX(a->occ, r_a->occ); - } - **/ -} - -uint64_t check_ovlp(f_chain_t *o, uint64_t on, uint64_t qs, uint64_t qe) -{ - uint64_t i, ovlp; - for (i = 0; i < on; i++) - { - ovlp = ((MIN(o[i].e, qe) > MAX(o[i].s, qs))? - (MIN(o[i].e, qe) - MAX(o[i].s, qs)):0); - if(ovlp) return 1; - } - return 0; -} - -void flter_by_cov(ha_ug_index* idx, kvec_pe_hit *hits, int64_t min_dp) -{ - uint64_t i, m, k, l, pos_bits = 64 - idx->uID_bits - 1, uid, pM = ((uint64_t)-1)>>idx->uID_bits, *a = NULL, a_n; - uint32_t s_uid, s_beg, s_end, e_uid, e_beg, e_end; - int64_t dp, old_dp, start = 0; - f_chain_t *t = NULL; - kvec_t(uint64_t) b; kv_init(b); - kvec_t(f_chain_t) x; kv_init(x); - uint64_t *index = NULL; CALLOC(index, idx->ug->u.n); - for (i = 0; i < hits->a.n; i++) - { - interpr_hit(idx, hits->a.a[i].s, hits->a.a[i].len>>32, &s_uid, &s_beg, &s_end); - m = s_uid; m <<= pos_bits; m += s_beg; m <<= 1; kv_push(uint64_t, b, m); - m = s_uid; m <<= pos_bits; m += s_end; m <<= 1; m += 1; kv_push(uint64_t, b, m); - - - interpr_hit(idx, hits->a.a[i].e, (uint32_t)hits->a.a[i].len, &e_uid, &e_beg, &e_end); - m = e_uid; m <<= pos_bits; m += e_beg; m <<= 1; kv_push(uint64_t, b, m); - m = e_uid; m <<= pos_bits; m += e_end; m <<= 1; m += 1; kv_push(uint64_t, b, m); - } - radix_sort_hc64(b.a, b.a + b.n); - for (k = 1, l = 0; k <= b.n; ++k) - { - if (k == b.n || (b.a[k]>>(64 - idx->uID_bits)) != (b.a[l]>>(64 - idx->uID_bits))) - { - uid = (b.a[l]>>(64 - idx->uID_bits)); - a = b.a + l; a_n = k - l; index[uid] = x.n; - for (i = 0, dp = 0, start = 0; i < a_n; ++i) - { - old_dp = dp; - ///if a[j] is qe - if (a[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 = (a[i]&pM)>>1; - } - else if (old_dp >= min_dp && dp < min_dp) ///old_dp > min_dp, b.a[j] is qe - { - kv_pushp(f_chain_t, x, &t); - t->s = start; t->e = (a[i]&pM)>>1; - } - } - - index[uid] |= ((uint64_t)(x.n - index[uid]))<<32; - l = k; - } - } - - - - - for (i = m = 0; i < hits->a.n; i++) - { - interpr_hit(idx, hits->a.a[i].s, hits->a.a[i].len>>32, &s_uid, &s_beg, &s_end); - if(!check_ovlp(x.a+((uint32_t)index[s_uid]), index[s_uid]>>32, s_beg, s_end)) continue; - - interpr_hit(idx, hits->a.a[i].e, (uint32_t)hits->a.a[i].len, &e_uid, &e_beg, &e_end); - if(!check_ovlp(x.a+((uint32_t)index[e_uid]), index[e_uid]>>32, e_beg, e_end)) continue; - hits->a.a[m] = hits->a.a[i]; - m++; - } - - fprintf(stderr, "[M::%s::] # old Hi-C pairs: %lu, # new Hi-C pairs: %lu\n", - __func__, hits->a.n, m); - hits->a.n = m; - - kv_destroy(b); kv_destroy(x); free(index); - -} - -void set_tag_pre_read(uint64_t *r_tag, uint64_t id, uint64_t off, uint64_t pos, ma_hit_t_alloc* sources) -{ - uint64_t i, tn; - ma_hit_t *h = NULL; - if(r_tag[id] == (uint64_t)-1) r_tag[id] = 0; - r_tag[id] += off; - // if(id == 2531247) fprintf(stderr, "***id: %lu, off: %lu, pos: %lu\n", id, off, pos); - for (i = 0; i < (uint64_t)(sources[id].length); i++) - { - h = &(sources[id].buffer[i]); - if(!h->el) continue; - tn = Get_tn((*h)); - if(pos >= Get_qs((*h)) && pos < Get_qe((*h))) - { - // if(tn == 2531247) fprintf(stderr, "###id: %lu, off: %lu, tn: %lu, pos: %lu\n", id, off, tn, pos); - if(r_tag[tn] == (uint64_t)-1) r_tag[tn] = 0; - r_tag[tn] += off; - } - - } -} - -void tag_reads(ha_ug_index* idx, kvec_pe_hit *u_hits, bubble_type* bub, int8_t *s, ma_hit_t_alloc* sources) -{ - kvec_pe_hit *r_hits = get_r_hits_for_trio(u_hits, idx->read_g, idx->ug, bub, idx->uID_bits, idx->pos_mode); - uint64_t *r_tag = NULL, i, k, srid, erid, /**rid, occ, a_occ, **/flag = AMBIGU, cons = 0, incons = 0/**, max, min**/; - ma_utg_t *u = NULL; - ma_ug_t* ug = idx->ug; - int8_t ss, es, sr; - CALLOC(r_tag, idx->read_g->n_seq); - - cons = 0, incons = 0; - memset(r_tag, -1, sizeof(uint64_t)*idx->read_g->n_seq); - for (i = 0; i < r_hits->a.n; i++) - { - srid = get_hit_suid(*r_hits, i); - erid = get_hit_euid(*r_hits, i); - ss = s[r_hits->a.a[i].id>>32]; - es = s[(uint32_t)r_hits->a.a[i].id]; - if(ss == 0 || es == 0) continue; - if((r_hits->a.a[i].id>>32) == ((uint32_t)r_hits->a.a[i].id)) continue; - - set_tag_pre_read(r_tag, srid, es < 0? 1 : ((uint64_t)1<<32), get_hit_spos(*r_hits, i), sources); - set_tag_pre_read(r_tag, erid, ss < 0? 1 : ((uint64_t)1<<32), get_hit_epos(*r_hits, i), sources); - - if(ss == es) cons++; - else incons++; - } - - /** - for (k = 0; k < ug->u.n; k++) - { - if(ug->g->seq[k].del) continue; - u = &(ug->u.a[k]); occ = a_occ = 0; - for (i = 0; i < u->n; i++) - { - rid = u->a[i]>>33; - if(r_tag[rid] == (uint64_t)-1) continue; - max = MAX((r_tag[rid]>>32), ((uint32_t)r_tag[rid])); - min = MIN((r_tag[rid]>>32), ((uint32_t)r_tag[rid])); - ///if(max <= (total*0.7) && max != total) - if(max - min <= max *0.1) - { - fprintf(stderr, "max-%lu, min-%lu\n", max, min); - a_occ++; - } - occ++; - } - if(occ == 0) continue; - if(a_occ > occ*0.85) s[k] = 0, filter++, fprintf(stderr, "k: %lu, a_occ: %lu, occ: %lu\n", k, a_occ, occ); - } - - fprintf(stderr, "[M::%s::] # consistent Hi-C pairs: %lu, # inconsistent Hi-C pairs: %lu, # filter: %lu\n", - __func__, cons, incons, filter); - - memset(r_tag, -1, sizeof(uint64_t)*idx->read_g->n_seq); - for (i = 0; i < r_hits->a.n; i++) - { - srid = get_hit_suid(*r_hits, i); - erid = get_hit_euid(*r_hits, i); - ss = s[r_hits->a.a[i].id>>32]; - es = s[(uint32_t)r_hits->a.a[i].id]; - if(ss == 0 || es == 0) continue; - if((r_hits->a.a[i].id>>32) == ((uint32_t)r_hits->a.a[i].id)) continue; - - set_tag_pre_read(r_tag, srid, es > 0? 1 : ((uint64_t)1<<32), get_hit_spos(*r_hits, i), sources); - set_tag_pre_read(r_tag, erid, ss > 0? 1 : ((uint64_t)1<<32), get_hit_epos(*r_hits, i), sources); - } - **/ - fprintf(stderr, "[M::%s::] # consistent Hi-C pairs: %lu, # inconsistent Hi-C pairs: %lu\n", - __func__, cons, incons); - - cons = 0, incons = 0; - memset(R_INF.trio_flag, AMBIGU, R_INF.total_reads * sizeof(uint8_t)); - for (i = 0; i < ug->g->n_seq; i++) - { - if(ug->g->seq[i].del) continue; - - flag = 0; - if(s[i] == 0) continue; - flag = (s[i] > 0? FATHER:MOTHER); - - u = &ug->u.a[i]; - if(u->m == 0) continue; - for (k = 0; k < u->n; k++) - { - if(r_tag[u->a[k]>>33] == (uint64_t)-1) continue; - if((r_tag[u->a[k]>>33]>>32) == ((uint32_t)r_tag[u->a[k]>>33])) continue; - sr = (r_tag[u->a[k]>>33]>>32) > ((uint32_t)r_tag[u->a[k]>>33])?1:-1; - if(sr == s[i]) - { - R_INF.trio_flag[u->a[k]>>33] = flag; - fprintf(stderr, "*rid: %lu, s[i]: %d, 1-occ: %u, (-1)-occ: %u\n", u->a[k]>>33, s[i], (uint32_t)(r_tag[u->a[k]>>33]>>32), ((uint32_t)r_tag[u->a[k]>>33])); - // cons_occ += (r_tag[u->a[k]>>33]>>32) + ((uint32_t)r_tag[u->a[k]>>33]); - cons++; - } - else - { - // R_INF.trio_flag[u->a[k]>>33] = -flag; - fprintf(stderr, "#rid: %lu, s[i]: %d, 1-occ: %u, (-1)-occ: %u\n", u->a[k]>>33, s[i], (uint32_t)(r_tag[u->a[k]>>33]>>32), ((uint32_t)r_tag[u->a[k]>>33])); - // incons_occ += (r_tag[u->a[k]>>33]>>32) + ((uint32_t)r_tag[u->a[k]>>33]); - incons++; - } - } - } - - free(r_tag); - kv_destroy(r_hits->a); - kv_destroy(r_hits->idx); - kv_destroy(r_hits->occ); - free(r_hits); - fprintf(stderr, "[M::%s::] # consistent reads: %lu, # inconsistent reads: %lu\n", __func__, cons, incons); -} - -void renew_idx_para(ha_ug_index* idx, ma_ug_t* ug) -{ - for (idx->uID_bits=1; (uint64_t)(1<uID_bits)<(uint64_t)ug->u.n; idx->uID_bits++); - idx->pos_bits = 64 - idx->uID_bits - 1; - idx->uID_mode = (((uint64_t)-1) << (64-idx->uID_bits))>>1; - idx->pos_mode = ((uint64_t)-1) >> (64-idx->pos_bits); - idx->rev_mode = ((uint64_t)1) << 63; -} - -uint32_t get_oe_occ(uint32_t qn, uint32_t tn, kvec_pe_hit* hits, ha_ug_index* idx) -{ - uint64_t shif = 64 - idx->uID_bits, occ = 0; - pe_hit *h_a = hits->a.a + (hits->idx.a[qn]>>32); - uint32_t h_occ = (uint32_t)(hits->idx.a[qn]), i; - for (i = 0; i < h_occ; i++) { - if(((h_a[i].s<<1)>>shif)==qn && ((h_a[i].e<<1)>>shif)==tn) occ++; - } - return occ; -} - -void optimize_u_trans(kv_u_trans_t *ovlp, kvec_pe_hit* hits, ha_ug_index* idx) -{ - if(hits->idx.n == 0) idx_hc_links(hits, idx, NULL); - uint64_t i, m, occ; - u_trans_t *x = NULL, *p = NULL; - kv_u_trans_t k_trans; - kv_init(k_trans); kv_init(k_trans.idx); - for (i = 0; i < ovlp->n; i++){ - x = &(ovlp->a[i]); - if(x->qn > x->tn) continue; - if(x->f != RC_2 || x->del) continue;///no need to adjust RC_0/RC_1 - occ = get_oe_occ(x->qn, x->tn, hits, idx) + get_oe_occ(x->tn, x->qn, hits, idx);///how many UL bridging qn and tn - kv_pushp(u_trans_t, k_trans, &p); - (*p) = (*x); p->nw = (x->nw*(1-(((double)(occ<<1))/((double)(hits->occ.a[x->qn]+hits->occ.a[x->tn]))))); - if(p->nw < 0) fprintf(stderr, "ERROR-nw\n"); - if(p->nw == 0) p->nw = x->nw*0.005; - if(p->nw == 0) { - k_trans.n--; - } else { - kv_pushp(u_trans_t, k_trans, &p); - (*p) = k_trans.a[k_trans.n-2]; - p->qn = k_trans.a[k_trans.n-2].tn; p->qs = k_trans.a[k_trans.n-2].ts; p->qe = k_trans.a[k_trans.n-2].te; - p->tn = k_trans.a[k_trans.n-2].qn; p->ts = k_trans.a[k_trans.n-2].qs; p->te = k_trans.a[k_trans.n-2].qe; - } - } - kt_u_trans_t_idx(&k_trans, idx->ug->g->n_seq); - mc_solve(NULL, NULL, &k_trans, idx->ug, idx->read_g, 0.8, R_INF.trio_flag, 1, NULL, 1, NULL, NULL, 1, 0); - for (i = m = 0; i < ovlp->n; i++){ - x = &(ovlp->a[i]); - if(x->del) continue; - if(x->f == RC_2){ - get_u_trans_spec(&k_trans, x->qn, x->tn, &p, NULL); - if(!p) continue; - } - ovlp->a[m++] = ovlp->a[i]; - } - ovlp->n = m; - kt_u_trans_t_idx(ovlp, idx->ug->g->n_seq); - free(hits->idx.a); hits->idx.a = NULL; hits->idx.n = hits->idx.m = 0; - free(hits->occ.a); hits->occ.a = NULL; hits->occ.n = hits->occ.m = 0; - kv_destroy(k_trans); kv_destroy(k_trans.idx); -} - -void round_test(ps_t *s, uint64_t seed, bubble_type *bub, kv_u_trans_t *k_trans, hc_links *link, sldat_t *sl, -ha_ug_index* idx, uint64_t test_block_flip, uint64_t n_perturb) -{ - s->xs = seed; memset(s->s, 0, s->n); - bub->round_id = 0; asm_opt.n_perturb = n_perturb; - - fprintf(stderr, "[M::%s] ----> test_block_flip: %lu, n_perturb: %lu\n", - __func__, test_block_flip, n_perturb); - renew_kv_u_trans(k_trans, link, &sl->hits, &(idx->t_ch->k_trans), idx, bub, s->s, NULL, 0); - mc_solve(NULL, NULL, k_trans, idx->ug, idx->read_g, 0.8, R_INF.trio_flag, - (bub->round_id == 0? 1 : 0), s->s, 1, NULL, test_block_flip?&(idx->t_ch->k_trans):0, 0, 0); - -} - -void debug_round_test(ps_t *s, uint64_t seed, bubble_type *bub, kv_u_trans_t *k_trans, hc_links *link, sldat_t *sl, -ha_ug_index* idx, uint64_t step, uint64_t total) -{ - uint64_t i; - for (i = step; i <= total; i += step) { - fprintf(stderr, "\n"); - round_test(s, seed, bub, k_trans, link, sl, idx, 0, i); - round_test(s, seed, bub, k_trans, link, sl, idx, 1, i); - } - -} - -void prt_hits_noid(ha_ug_index* idx, ma_ug_t* ug, kvec_pe_hit* hits, FILE *fn) -{ - uint64_t k, shif = 64 - idx->uID_bits; - char dir[2] = {'+', '-'}; - for (k = 0; k < hits->a.n; ++k) { - fprintf(fn, "r-%lu-th\t%c\trs-utg%.6d%c\t%lu\t%c\tre-utg%.6d%c\t%lu\n", - hits->a.a[k].id, - dir[hits->a.a[k].s>>63], (int)((hits->a.a[k].s<<1)>>shif)+1, - "lc"[ug->u.a[((hits->a.a[k].s<<1)>>shif)].circ], hits->a.a[k].s&idx->pos_mode, - dir[hits->a.a[k].e>>63], (int)((hits->a.a[k].e<<1)>>shif)+1, - "lc"[ug->u.a[((hits->a.a[k].e<<1)>>shif)].circ], hits->a.a[k].e&idx->pos_mode); - } -} - -void prt_utg_trans(kv_u_trans_t *ta, ma_ug_t* ug, FILE *fn) -{ - uint32_t i; - u_trans_t *p = NULL; - for (i = 0; i < ta->n; i++) { - p = &(ta->a[i]); - fprintf(fn, "utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tw(%f)\tf(%u)\n", - p->qn+1, "lc"[ug->u.a[p->qn].circ], ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], - p->tn+1, "lc"[ug->u.a[p->tn].circ], ug->u.a[p->tn].len, p->ts, p->te, p->nw, p->f); - } -} - - -void prt_kv_u_trans(kv_u_trans_t *ta, hc_links* lk, int8_t *s, FILE *fn) -{ - uint32_t i; - u_trans_t *p = NULL; - hc_edge *e = NULL; - - for (i = 0; i < ta->n; i++) { - p = &(ta->a[i]); - e = get_hc_edge(lk, p->qn, p->tn, 0); - fprintf(fn, "s-utg%.6ul\tS(%d)\td-utg%.6ul\tS(%d)\trev(%u)\td(%lld)\ttw(%f)\n", - p->qn+1, s[p->qn], p->tn+1, s[p->tn], p->rev, - (e == NULL || e->dis == (uint64_t)-1)? -1 : (long long)(e->dis>>3), p->nw); - } -} - - -void prt_bubble_gfa_adv(FILE *fp, bubble_type *bub, const char* utg_pre, const char* bub_pre, const char* chain_pre) -{ - uint32_t i, k, m, *a, n, beg, sink, x; ma_utg_t *p; uint64_t occ; - ma_ug_t *b_ug = bub->b_ug; char name[32], bname[32]; uint8_t *f; CALLOC(f, bub->ug->u.n); - for (i = 0; i < b_ug->u.n; i++) { - p = &b_ug->u.a[i]; - if(p->n == 0) continue; - for (k = occ = 0; k < p->n; k++){ - x = p->a[k]>>33; - get_bubbles(bub, x, &beg, &sink, &a, &n, NULL); - - for (m = 0; m < n; m++) { - occ += bub->ug->u.a[a[m]>>1].n; f[a[m]>>1] = 1; - } - if(beg != (uint32_t)-1 && f[beg>>1] == 0) { - occ += bub->ug->u.a[beg>>1].n; f[beg>>1] = 1; - } - if(sink != (uint32_t)-1 && f[sink>>1] == 0) { - occ += bub->ug->u.a[sink>>1].n; f[sink>>1] = 1; - } - } - - sprintf(name, "%s%.6d%c", chain_pre, i + 1, "lc"[p->circ]); - fprintf(fp, "S\t%s\t*\tLN:i:%lu\n", name, occ); - for (k = 0; k < p->n; k++) { - x = p->a[k]>>33; - sprintf(bname, "%s%.6d", bub_pre, x + 1); - fprintf(fp, "B\t%s\t%c\tcid:i:%s\tsm:%c\n", bname, "+-"[(p->a[k]>>32)&1], name, "01"[xf_bub]); - - get_bubbles(bub, x, &beg, &sink, &a, &n, NULL); - if(beg != (uint32_t)-1) { - fprintf(fp, "U\t%s%.6d%c\t%c\tcid:i:%s\tbid:b:%s\thom:%c\n", - utg_pre, (beg>>1)+1, "lc"[bub->ug->u.a[(beg>>1)].circ], "+-"[beg&1], name, bname, "10"[IF_HOM((beg>>1), *bub)]); - } - - if(sink != (uint32_t)-1) { - fprintf(fp, "U\t%s%.6d%c\t%c\tcid:i:%s\tbid:s:%s\thom:%c\n", - utg_pre, (sink>>1)+1, "lc"[bub->ug->u.a[(sink>>1)].circ], "+-"[sink&1], name, bname, "10"[IF_HOM((sink>>1), *bub)]); - } - for (m = 0; m < n; m++) { - occ += bub->ug->u.a[a[m]>>1].n; - fprintf(fp, "U\t%s%.6d%c\t%c\tcid:i:%s\tbid:c:%s\thom:%c\n", - utg_pre, (a[m]>>1)+1, "lc"[bub->ug->u.a[(a[m]>>1)].circ], "+-"[a[m]&1], name, bname, "10"[IF_HOM((a[m]>>1), *bub)]); - } - } - } - - asg_arc_t* au = NULL; - uint32_t nu, u, v, j; - for (i = 0; i < b_ug->u.n; ++i) { - if(b_ug->u.a[i].m == 0) continue; - if(b_ug->u.a[i].circ) - { - fprintf(fp, "L\t%s%.6dc\t+\t%s%.6dc\t+\t%dM\tL1:i:%d\n", - chain_pre, i+1, chain_pre, i+1, 0, 0); - fprintf(fp, "L\t%s%.6dc\t-\t%s%.6dc\t-\t%dM\tL1:i:%d\n", - chain_pre, i+1, chain_pre, i+1, 0, 0); - } - u = i<<1; - au = asg_arc_a(b_ug->g, u); - nu = asg_arc_n(b_ug->g, u); - for (j = 0; j < nu; j++) - { - if(au[j].del) continue; - v = au[j].v; - fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", - chain_pre, (u>>1)+1, "lc"[b_ug->u.a[u>>1].circ], "+-"[u&1], - chain_pre, (v>>1)+1, "lc"[b_ug->u.a[v>>1].circ], "+-"[v&1], 0, 0); - } - - - u = (i<<1) + 1; - au = asg_arc_a(b_ug->g, u); - nu = asg_arc_n(b_ug->g, u); - for (j = 0; j < nu; j++) - { - if(au[j].del) continue; - v = au[j].v; - fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", - chain_pre, (u>>1)+1, "lc"[b_ug->u.a[u>>1].circ], "+-"[u&1], - chain_pre, (v>>1)+1, "lc"[b_ug->u.a[v>>1].circ], "+-"[v&1], 0, 0); - } - } - - for (i = 0; i < bub->ug->u.n; i++) { - if(f[i]) continue; - fprintf(fp, "U\t%s%.6d%c\t+\tcid:i:*\tbid:c:*\thom:%c\n", - utg_pre, i+1, "lc"[bub->ug->u.a[i].circ], "10"[IF_HOM(i, *bub)]); - } - free(f); -} - - -void prt_debug_hic(const char* o_n, ma_ug_t* ug, ha_ug_index* idx, ug_opt_t *opt, kvec_pe_hit* hits, -kv_u_trans_t *utg_trans, kv_u_trans_t *p_arcs, hc_links* lk, int8_t *s, bubble_type *bub) -{ - char* gfa_name = (char*)malloc(strlen(o_n)+100); FILE *fn = NULL; - - sprintf(gfa_name, "%s.hic.dbg", o_n); - print_debug_gfa(idx->read_g, idx->ug, opt->coverage_cut, gfa_name, opt->sources, opt->ruIndex, - opt->max_hang, opt->min_ovlp, 0, 0, 0); - - if(hits) { - sprintf(gfa_name, "%s.hic.hits.log", o_n); fn = fopen(gfa_name, "w"); - prt_hits_noid(idx, ug, hits, fn); - fclose(fn); - } - - if(utg_trans) { - sprintf(gfa_name, "%s.hic.utg.trans.log", o_n); fn = fopen(gfa_name, "w"); - prt_utg_trans(utg_trans, ug, fn); - fclose(fn); - } - - if(p_arcs) { - sprintf(gfa_name, "%s.hic.parcs.log", o_n); fn = fopen(gfa_name, "w"); - prt_kv_u_trans(p_arcs, lk, s, fn); - fclose(fn); - } - - if(bub) { - sprintf(gfa_name, "%s.bub.noseq.gfa", o_n); fn = fopen(gfa_name, "w"); - prt_bubble_gfa_adv(fn, bub, "utg", "btg", "ctg"); - fclose(fn); - } - - free(gfa_name); - fprintf(stderr, "[M::%s::] done\n", __func__); -} - -int hic_short_align(const enzyme *fn1, const enzyme *fn2, ha_ug_index* idx, ug_opt_t *opt, kvec_pe_hit **rhits) -{ - double index_time = yak_realtime(); - sldat_t sl; - sl.idx = idx; - sl.t_ch = idx->t_ch; - sl.chunk_size = 20000000; - sl.n_thread = asm_opt.thread_num; - sl.total_base = sl.total_pair = 0; - idx->hap_cnt = asm_opt.hap_occ; - kv_init(sl.hits.a); kv_init(sl.hits.idx); kv_init(sl.hits.occ); - - - if(!load_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name)) - { - alignment_worker_pipeline(&sl, fn1, fn2); - write_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name); - } - sl.hits.uID_bits = idx->uID_bits; sl.hits.pos_mode = idx->pos_mode; - - /***debug***/ - if(sl.hits.idx.n == 0) idx_hc_links(&(sl.hits), idx, NULL); - // optimize_u_trans(&(idx->t_ch->k_trans), &sl.hits, idx); - // filter_kv_u_trans_t(&(idx->t_ch->k_trans), idx->ug, 0.5); - /***debug***/ - - // print_kv_u_trans_t(&(idx->t_ch->k_trans), idx->ug); - // flter_by_cov(idx, &sl.hits, 2); - // update_hits(idx, &sl.hits, idx->t_ch->is_r_het); - ///debug_hc_hits_v14(&sl.hits, asm_opt.output_file_name, sl.idx); - ////dedup_hits(&(sl.hits), sl.idx); - ///write_hc_hits_v14(&sl.hits, asm_opt.output_file_name); - - if(asm_opt.misjoin_len > 0/** && (!(asm_opt.ar))**/)//disable it for the UL assembly - { - update_switch_unitig(idx->ug, idx->read_g, &(sl.hits), &(idx->t_ch->k_trans), 10, 20, asm_opt.misjoin_len, 0.15); - renew_idx_para(idx, idx->ug); - } - // print_hits_simp(idx, &sl.hits); - // print_kv_u_trans_t(&(idx->t_ch->k_trans)); - - hc_links link; - init_hc_links(&link, idx->ug->g->n_seq, idx->t_ch); - ///H_partition hap; - bubble_type bub; - kv_u_trans_t k_trans; - kv_init(k_trans); kv_init(k_trans.idx); - ps_t *s = NULL; - mb_nodes_t u; - kv_init(u.bid); kv_init(u.idx); kv_init(u.u); - memset(&bub, 0, sizeof(bubble_type)); - bub.round_id = 0; bub.n_round = asm_opt.n_weight; - - resolve_tangles_hic(idx, &bub, &sl.hits, &k_trans); - measure_distance(idx, idx->ug, &sl.hits, &link, &bub, &(idx->t_ch->k_trans)); - // if((asm_opt.flag & HA_F_VERBOSE_GFA) && load_ps_t(&s, asm_opt.output_file_name)) - // { - // bub.round_id = bub.n_round; - // label_unitigs_sm(s->s, NULL, idx->ug); - // goto skip_flipping; - // } - // print_debug_gfa(idx->read_g, idx->ug, opt->coverage_cut, "hic.phasing", opt->sources, opt->ruIndex, - // opt->max_hang, opt->min_ovlp, 0, 0, 0); - - s = init_ps_t(11, idx->ug->g->n_seq); - // debug_round_test(s, 11, &bub, &k_trans, &link, &sl, idx, 1000, 10000); - for (bub.round_id = 0; bub.round_id < bub.n_round; bub.round_id++) - { - // identify_bubbles(idx->ug, &bub, idx->t_ch->is_r_het, &(idx->t_ch->k_trans)); - renew_kv_u_trans(&k_trans, &link, &sl.hits, &(idx->t_ch->k_trans), idx, &bub, s->s, NULL, 0); - // if(bub.round_id == 0) init_phase(idx, &k_trans, &bub, s); - // update_trans_g(idx, &k_trans, &bub); - /*******************************for debug************************************/ - mc_solve(NULL, NULL, &k_trans, idx->ug, idx->read_g, 0.8, R_INF.trio_flag, - (bub.round_id == 0? 1 : 0), s->s, 1, &bub, - &(idx->t_ch->k_trans), 0, /**(((bub.round_id+1) == bub.n_round)?1:0)**/0); - // mc_solve(NULL, NULL, &k_trans, idx->ug, idx->read_g, 0.8, R_INF.trio_flag, - // (bub.round_id == 0? 1 : 0), s->s, 1, NULL, &(idx->t_ch->k_trans), 0, 0); - /** - if((bub.round_id+1) == bub.n_round) { - prt_debug_hic(asm_opt.output_file_name, idx->ug, idx, opt, &sl.hits, - &(idx->t_ch->k_trans), &k_trans, &link, s->s, &(bub)); - } - **/ - /*******************************for debug************************************/ - label_unitigs_sm(s->s, NULL, idx->ug); - - /*******************************for debug************************************/ - // if(bub.round_id == bub.n_round - 1) - // { - // debug_output_disconnected_hits(idx, &k_trans, &sl.hits, &link, &bub, s->s); - // } - /*******************************for debug************************************/ - /** - init_hic_advance((ha_ug_index*)sl.idx, &sl.hits, &link, &bub, &hap, 0); - reset_H_partition(&hap, (bub.round_id == 0? 1 : 0)); - init_contig_partition(&hap, idx, &bub, &link); - phasing_improvement(&hap, &(hap.g_p), idx, &bub, &link); - label_unitigs(&(hap.g_p), idx->ug); - **/ - } - // write_ps_t(s, asm_opt.output_file_name); - // skip_flipping: - verbose_het_stat(&bub); - - if(rhits) (*rhits) = get_r_hits_order(&sl.hits, idx->uID_bits, idx->pos_mode, idx->read_g, idx->ug, &bub); - - // tag_reads(idx, &sl.hits, &bub, s->s, opt->sources); - - // print_kv_weight(&k_trans, s->s); - - // horder_t *ho = init_horder_t(&sl.hits, idx->uID_bits, idx->pos_mode, idx->read_g, idx->ug, &bub, &(idx->t_ch->k_trans), opt, 3); - - // print_hc_links(&link, 0, &hap); - // print_hits_simp(idx, &sl.hits); - // print_kv_u_trans_t(&(idx->t_ch->k_trans)); - // print_kv_u_trans(&k_trans, &link, s->s); - // print_bubbles(idx->ug, &bub, sl.hits.a.n?&sl.hits:NULL, NULL/**idx->link**/, idx); - // print_hits(idx, &sl.hits, fn1, fn2); - // print_debug_bubble_graph(&bub, idx->ug, asm_opt.output_file_name); - // print_bubble_chain(&bub); - - // destory_contig_partition(&hap); - // destory_horder_t(&ho); - kv_destroy(sl.hits.a); kv_destroy(sl.hits.idx); kv_destroy(sl.hits.occ); - destory_hc_links(&link); - kv_destroy(k_trans); kv_destroy(k_trans.idx); - destory_ps_t(&s); - kv_destroy(u.bid); kv_destroy(u.idx); kv_destroy(u.u); - destory_bubbles(&bub); - return 1; - - - print_bubbles(idx->ug, &bub, sl.hits.a.n?&sl.hits:NULL, &link, idx); - collect_hc_reverse_links(&link, idx->ug, &bub); - normalize_hc_links(&link); - min_cut_t* cut = clean_hap(&link, &bub, idx->ug); - ///print_bubbles(idx->ug, &bub, NULL, &link, idx); - G_partition* gp = clean_bubbles(&link, &bub, cut, idx->ug); - ///print_hc_links(&link); - destory_min_cut_t(cut); free(cut); - destory_G_partition(gp); free(gp); - destory_bubbles(&bub); - - fprintf(stderr, "[M::%s::%.3f] processed %lu pairs; %lu bases\n", __func__, yak_realtime()-index_time, sl.total_pair, sl.total_base); - return 1; -} - -void bp_solve(ug_opt_t *opt, kv_u_trans_t *ref, ma_ug_t *ug, asg_t *sg, bubble_type *bub, double cis_rate) -{ - uint64_t k, i, v, nvx, n[3], nv; u_trans_t *z; - kv_u_trans_t in; memset(&in, 0, sizeof(in)); - ma_utg_t *u = NULL; asg_arc_t *av; double w; - ps_t *s = init_ps_t(11, ug->g->n_seq); - - for (i = 0; i < ug->g->n_seq; i++) { - s->s[i] = 0; - if((ug->g->seq[i].del) || (IF_HOM(i, (*bub)))) { - continue; - } - - u = &ug->u.a[i]; - if(u->m == 0 || u->n == 0) continue; - for (k = n[0] = n[1] = n[2] = 0; k < u->n; k++) { - if(R_INF.trio_flag[u->a[k]>>33] == FATHER) n[1]++; - else if(R_INF.trio_flag[u->a[k]>>33] == MOTHER) n[2]++; - else n[0]++; - } - if(n[1] >= n[2] && n[1] >= n[0]) s->s[i] = 1; - else if(n[2] >= n[1] && n[2] >= n[0]) s->s[i] = -1; - } - - kv_resize(u_trans_t, in, ref->n); - for (k = in.n = 0; k < ref->n; k++) { - if((IF_HOM(ref->a[k].qn, (*bub))) || (IF_HOM(ref->a[k].tn, (*bub))) || ref->a[k].del) { - continue; - } - kv_push(u_trans_t, in, ref->a[k]); - } - - if(cis_rate > 0) { - nvx = ug->g->n_seq<<1; - for (v = 0; v < nvx; v++) { - if((ug->g->seq[v>>1].del) || (IF_HOM((v>>1), (*bub)))) continue; - av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); - for (i = 0; i < nv; i++) { - if((av[i].del) || (av[i].v>>1) == (v>>1) || - (ug->g->seq[av[i].v>>1].del) || (IF_HOM((av[i].v>>1), (*bub)))) { - continue; - } - w = ((double)av[i].ol)*cis_rate; - if(w <= 0) continue; - kv_pushp(u_trans_t, in, &z); - memset(z, 0, sizeof((*z))); - z->f = RC_3; z->nw =-w; z->rev = (v^av[i].v)&1; - z->qn = v>>1; z->tn = av[i].v>>1; - - z->qs = 0; z->qe = sg->seq[z->qn].len; - if(av[i].ol < sg->seq[z->qn].len) { - if(v&1) { - z->qe = z->qs + av[i].ol; - } else { - z->qs = z->qe - av[i].ol; - } - } - - z->ts = 0; z->te = sg->seq[z->tn].len; - if(av[i].ol < sg->seq[z->tn].len) { - if(av[i].v&1) { - z->ts = z->te - av[i].ol; - } else { - z->te = z->ts + av[i].ol; - } - } - } - - } - } - // fprintf(stderr, "[M::%s::] ==> nup::%lu\n", __func__, nup); - clean_u_trans_t_idx_adv(&in, ug, sg); - - mc_solve(NULL, NULL, &in, ug, sg, 0.8, NULL, 0, s->s, 1, bub, ref, 0, 0); - label_unitigs_sm(s->s, NULL, ug); - destory_ps_t(&s); kv_destroy(in); kv_destroy(in.idx); -} - -spg_t *hic_short_pre_align(const enzyme *fn1, const enzyme *fn2, ha_ug_index* idx, ug_opt_t *opt, kvec_pe_hit **rhits) -{ - // double index_time = yak_realtime(); - sldat_t sl; - sl.idx = idx; - sl.t_ch = idx->t_ch; - sl.chunk_size = 20000000; - sl.n_thread = asm_opt.thread_num; - sl.total_base = sl.total_pair = 0; - idx->hap_cnt = asm_opt.hap_occ; - kv_init(sl.hits.a); kv_init(sl.hits.idx); kv_init(sl.hits.occ); - - if(!load_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name)) - { - alignment_worker_pipeline(&sl, fn1, fn2); - fprintf(stderr, "sb0sb\n"); - write_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name); - fprintf(stderr, "sb1sb\n"); - } - sl.hits.uID_bits = idx->uID_bits; sl.hits.pos_mode = idx->pos_mode; - kv_u_trans_t k_trans; - kv_init(k_trans); kv_init(k_trans.idx); - bubble_type bub; - memset(&bub, 0, sizeof(bubble_type)); - bub.round_id = 0; bub.n_round = asm_opt.n_weight; - fprintf(stderr, "sb2sb\n"); - resolve_tangles_hic(idx, &bub, &sl.hits, &k_trans); - fprintf(stderr, "sb3sb\n"); - spg_t *scg = horder_utg(&sl.hits, idx->uID_bits, idx->pos_mode, idx->read_g, idx->ug, &bub, opt); - fprintf(stderr, "sb4sb\n"); - if(rhits){ - CALLOC(*rhits, 1); - (**rhits) = sl.hits; - sl.hits.a.a = NULL; - sl.hits.idx.a = NULL; - sl.hits.occ.a = NULL; - } - kv_destroy(sl.hits.a); kv_destroy(sl.hits.idx); kv_destroy(sl.hits.occ); - kv_destroy(k_trans); kv_destroy(k_trans.idx); - destory_bubbles(&bub); - return scg; -} - -int load_psg_t(psg_t **sg, const char *fn) -{ - uint64_t flag = 0; - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.hic.pst.bin", fn); - FILE* fp = NULL; - fp = fopen(buf, "r"); - if(!fp) return 0; - CALLOC(*sg, 1); - flag += fread(&((*sg)->xs), sizeof((*sg)->xs), 1, fp); - flag += fread(&((*sg)->sg.n), sizeof((*sg)->sg.n), 1, fp); - (*sg)->sg.m = (*sg)->sg.n; - MALLOC((*sg)->sg.a, (*sg)->sg.n); - flag += fread((*sg)->sg.a, sizeof(mc_gg_status), (*sg)->sg.n, fp); - - fclose(fp); - free(buf); - return 1; -} - -void write_psg_t(psg_t *sg, const char *fn) -{ - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.hic.pst.bin", fn); - FILE* fp = fopen(buf, "w"); - - fwrite(&(sg->xs), sizeof(sg->xs), 1, fp); - fwrite(&(sg->sg.n), sizeof(sg->sg.n), 1, fp); - fwrite(sg->sg.a, sizeof(mc_gg_status), sg->sg.n, fp); - - fclose(fp); - free(buf); -} - -psg_t* init_psg_t(uint64_t seed, ma_ug_t* ug, asg_t* rg, ug_opt_t *opt) -{ - psg_t *s = NULL; CALLOC(s, 1); - s->xs = seed; - - kv_gg_status *sa = init_mc_gg_status(ug, rg, opt->coverage_cut, opt->sources, opt->ruIndex, - asm_opt.hom_global_coverage_set?asm_opt.hom_global_coverage:((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE), - asm_opt.polyploidy); - - s->sg = *sa; - free(sa); - return s; -} - -void destory_psg_t(psg_t **s) -{ - free((*s)->sg.a); - free((*s)); -} - -int hic_short_align_poy(const enzyme *fn1, const enzyme *fn2, ha_ug_index* idx, ug_opt_t *opt) -{ - double index_time = yak_realtime(); - sldat_t sl; - kvec_hc_edge back_hc_edge; - kv_init(back_hc_edge.a); - sl.idx = idx; - sl.t_ch = idx->t_ch; - sl.chunk_size = 20000000; - sl.n_thread = asm_opt.thread_num; - sl.total_base = sl.total_pair = 0; - idx->hap_cnt = asm_opt.hap_occ; - kv_init(sl.hits.a); kv_init(sl.hits.idx); kv_init(sl.hits.occ); - - - if(!load_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name)) - { - alignment_worker_pipeline(&sl, fn1, fn2); - write_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name); - } - - hc_links link; - init_hc_links(&link, idx->ug->g->n_seq, idx->t_ch); - ///H_partition hap; - bubble_type bub; - kv_u_trans_t k_trans; - kv_init(k_trans); kv_init(k_trans.idx); - psg_t *s = NULL; - mb_nodes_t u; - kv_init(u.bid); kv_init(u.idx); kv_init(u.u); - memset(&bub, 0, sizeof(bubble_type)); - bub.round_id = 0; bub.n_round = asm_opt.n_weight; - - resolve_tangles_hic(idx, &bub, &sl.hits, &k_trans); - measure_distance(idx, idx->ug, &sl.hits, &link, &bub, &(idx->t_ch->k_trans)); - if((asm_opt.flag & HA_F_VERBOSE_GFA) && load_psg_t(&s, asm_opt.output_file_name)) - { - bub.round_id = bub.n_round; - goto skip_flipping; - } - s = init_psg_t(11, idx->ug, idx->read_g, opt); - for (bub.round_id = 0; bub.round_id < bub.n_round; bub.round_id++) - { - // identify_bubbles(idx->ug, &bub, idx->t_ch->is_r_het, &(idx->t_ch->k_trans)); - renew_kv_u_trans(&k_trans, &link, &sl.hits, &(idx->t_ch->k_trans), idx, &bub, NULL, s->sg.a, 0); - // if(bub.round_id == 0) init_phase(idx, &k_trans, &bub, s); - // update_trans_g(idx, &k_trans, &bub); - /*******************************for debug************************************/ - mc_solve_general(&k_trans, idx->ug->u.n, &(s->sg), asm_opt.polyploidy, 0, 1); - /*******************************for debug************************************/ - - /*******************************for debug************************************/ - // if(bub.round_id == bub.n_round - 1) - // { - // debug_output_disconnected_hits(idx, &k_trans, &sl.hits, &link, &bub, s->s); - // } - /*******************************for debug************************************/ - } - if((asm_opt.flag & HA_F_VERBOSE_GFA)) write_psg_t(s, asm_opt.output_file_name); - - skip_flipping: - verbose_het_stat(&bub); - - if(asm_opt.polyploidy == 2) label_unitigs_sm(NULL, s->sg.a, idx->ug); - - // print_kv_weight(&k_trans); - - // horder_t *ho = init_horder_t(&sl.hits, idx->uID_bits, idx->pos_mode, idx->read_g, idx->ug, &bub, &(idx->t_ch->k_trans), opt, 3); - - ///print_hc_links(&link, 0, &hap); - // print_kv_u_trans(&k_trans, &link, s->s); - - - ///print_bubbles(idx->ug, &bub, sl.hits.a.n?&sl.hits:NULL, idx->link, idx); - ///print_hits(idx, &sl.hits, fn1); - - - ///print_debug_bubble_graph(&bub, idx->ug, asm_opt.output_file_name); - // print_bubble_chain(&bub); - // destory_contig_partition(&hap); - // destory_horder_t(&ho); - kv_destroy(back_hc_edge.a); - kv_destroy(sl.hits.a); - kv_destroy(sl.hits.idx); - kv_destroy(sl.hits.occ); - destory_hc_links(&link); - kv_destroy(k_trans); - kv_destroy(k_trans.idx); - destory_psg_t(&s); - kv_destroy(u.bid); kv_destroy(u.idx); kv_destroy(u.u); - fprintf(stderr, "[M::%s::%.3f] processed %lu pairs; %lu bases\n", __func__, yak_realtime()-index_time, sl.total_pair, sl.total_base); - return 1; -} - -mmhap_t* gen_mmhap_t(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc *src) -{ - uint64_t k, z, hom_cov, het_cov, s, *bs = NULL; uint8_t *ff; mmhap_t *p; - if(asm_opt.hom_global_coverage_set) { - hom_cov = asm_opt.hom_global_coverage; - } else { - hom_cov = ((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE); - } - het_cov = hom_cov/asm_opt.polyploidy; - CALLOC(ff, rg->n_seq); CALLOC(p, 1); CALLOC(bs, asm_opt.polyploidy+1); - p->h.n = p->h.m = ug->u.n; CALLOC(p->h.a, p->h.n); - for (k = p->a.n = s = 0; k < ug->u.n; k++) { - p->h.a[k].a = p->a.n; - p->h.a[k].n = 0; - p->h.a[k].m = infer_mmhap_copy(ug, rg, src, ff, k, het_cov, asm_opt.polyploidy); - if(p->h.a[k].m == (uint64_t)asm_opt.polyploidy) { - p->h.a[k].n = p->h.a[k].m; s = 1; - } - p->a.n += p->h.a[k].m; bs[p->h.a[k].m] += ug->g->seq[k].len; - } - free(ff); - p->a.m = p->a.n; MALLOC(p->a.a, p->a.n); memset(p->a.a, -1, sizeof((*(p->a.a)))*p->a.n); - if(s) { - for (k = p->a.n = 0; k < ug->u.n; k++) { - if(p->h.a[k].n == p->h.a[k].m) { - for (z = 0; z < p->h.a[k].m; z++) p->a.a[p->h.a[k].a+z] = z; - } - } - } - - for (k = 1; k <= (uint64_t)asm_opt.polyploidy; k++) { - fprintf(stderr, "[M::stat] # %lu-copy bases: %lu\n", k, bs[k]); - } - free(bs); - return p; -} - -bubble_type *gen_mmhap_bub(ma_ug_t* ug, uint8_t *r_het_flag, kv_u_trans_t *ref, mmhap_t *hh) -{ - uint64_t k; - bubble_type *p; CALLOC(p, 1); p->n_round = asm_opt.n_weight; p->round_id = 0; - identify_bubbles(ug, p, r_het_flag, ref); - for (k = 0; k < ug->g->n_seq; k++) { - if(IF_BUB(k, (*p))) continue; - if(IF_HOM(k, (*p))) { - if(hh->h.a[k].n < hh->h.a[k].m) p->index[k] = p->num.n; - } else if(IF_HET(k, (*p))) { - if(hh->h.a[k].n >= hh->h.a[k].m) p->index[k] = (uint32_t)-1; - } - } - return p; -} - -void purge_phase_0(ha_ug_index* idx, hc_links *link, bubble_type *bub, ps_t *s, kvec_pe_hit* hits, kv_u_trans_t *k_trans, uint8_t *del, mmhap_t *hh) -{ - k_trans->idx.n = k_trans->n = 0; hits->idx.n = 0; - for (bub->round_id = 0; bub->round_id < bub->n_round; bub->round_id++) { - renew_kv_u_trans(k_trans, link, hits, &(idx->t_ch->k_trans), idx, bub, s->s, NULL, 1/**0**/); - mc_solve(NULL, NULL, k_trans, idx->ug, idx->read_g, 0.8, R_INF.trio_flag, - (bub->round_id==0?1:0), s->s, 1, bub, &(idx->t_ch->k_trans), 0, - /**(((bub.round_id+1) == bub.n_round)?1:0)**/0); - /*******************************for debug************************************/ - // label_unitigs_sm(s->s, NULL, idx->ug); - } - - uint64_t l[2], k, len; int64_t p; ma_ug_t *ug = idx->ug; - for (k = l[0] = l[1] = 0; k < ug->g->n_seq; k++) { - if((del[k] == 1) || (s->s[k] == 0)) continue; - if(s->s[k] > 0) l[0] += ug->g->seq[k].len; - else l[1] += ug->g->seq[k].len; - } - - p = (l[0]>=l[1])?1:-1; - for (k = len = 0; k < ug->g->n_seq; k++) { - if((del[k] == 1) || (s->s[k] == 0)) { - if((del[k] == 2) || - ((hh->h.a[k].n == hh->h.a[k].m) && (hh->h.a[k].m == ((uint64_t)asm_opt.polyploidy)))) { - len += ug->g->seq[k].len; - } - continue; - } - if(s->s[k] == p) { - del[k] = 2; len += ug->g->seq[k].len; - } else { - del[k] = 1; bub->index[k] = (uint32_t)-1; - } - s->s[k] = 0;///reset - } - fprintf(stderr, "[M::%s::stat] # remaining bases: %lu\n", __func__, len); -} - -void exchange_kv_u_trans_t(kv_u_trans_t *a, kv_u_trans_t *b) -{ - uint64_t k, *ua; u_trans_t *u; - k = a->n; a->n = b->n; b->n = k; - k = a->m; a->m = b->m; b->m = k; - u = a->a; a->a = b->a; b->a = u; - - k = a->idx.n; a->idx.n = b->idx.n; b->idx.n = k; - k = a->idx.m; a->idx.m = b->idx.m; b->idx.m = k; - ua = a->idx.a; a->idx.a = b->idx.a; b->idx.a = ua; -} - -uint64_t cal_ave_ovlp(u_trans_t *a, uint64_t an, double top) -{ - if(!an) return 0; - uint64_t k, len, cut, occ, tot; - for (k = len = 0; k < an; k++) { - len += a[k].qe - a[k].qs; - } - cut = len - (len*top); - for (k = occ = tot = 0; k < an; k++) { - if(a[k].qe - a[k].qs < cut) continue; - occ++; tot += a[k].qe - a[k].qs; - } - if(!occ) { - occ = an; tot = len; - } - return tot/occ; -} - - -void clean_trans_ovlp(bubble_type *bub, kv_u_trans_t *des, kv_u_trans_t *src, asg64_v *srt, ma_ug_t *ug) -{ - uint64_t k, st, i, m = 0, ncut; - for (k = des->n = 0; k < src->n; k++) { - if(IF_HOM(src->a[k].qn, (*bub))) continue; - if(IF_HOM(src->a[k].tn, (*bub))) continue; - kv_push(u_trans_t, *des, src->a[k]); - } - - kv_resize(uint64_t, des->idx, src->idx.n); des->idx.n = src->idx.n; - memset(des->idx.a, 0, des->idx.n*sizeof((*(des->idx.a)))); - for (st = 0, i = 1; i <= des->n; ++i) { - if (i == des->n || des->a[i].qn != des->a[st].qn) { - des->idx.a[des->a[st].qn] = (((uint64_t)st)<<32)|(i-st); m++; - st = i; - } - } - - if(srt && m) { - ncut = 0; kv_resize(uint64_t, *srt, m); - for (k = srt->n = 0; k < des->idx.n; k++) { - if(!((uint32_t)(des->idx.a[k]))) continue; - m = cal_ave_ovlp(des->a+(des->idx.a[k]>>32), ((uint32_t)(des->idx.a[k])), 0.9); - m = ((uint64_t)-1)-m; m <<= 32; m += k; - kv_push(uint64_t, *srt, m); - } - radix_sort_b64(srt->a, srt->a + srt->n); - for (k = 0; k < srt->n; k++) { - ncut += trans_sec_cut0(des, srt, (uint32_t)(srt->a[k]), 0.2, 256, ug); - } - - if(ncut) {///renew idx - for (i = k = 0; i < des->n; i++) { - if(des->a[i].del) continue; - des->a[k++] = des->a[i]; - } - des->n = k; - - memset(des->idx.a, 0, des->idx.n*sizeof((*(des->idx.a)))); - for (st = 0, i = 1; i <= des->n; ++i) { - if (i == des->n || des->a[i].qn != des->a[st].qn) { - des->idx.a[des->a[st].qn] = (((uint64_t)st)<<32)|(i-st); m++; - st = i; - } - } - } - } -} - -void purge_phase(ha_ug_index* idx, mmhap_t *hh, uint64_t hapid, uint64_t max_round, hc_links *link, kvec_pe_hit* hits, -bubble_type *bub, ps_t *s, kv_u_trans_t *k_trans, uint8_t *del, uint32_t *bidx, kv_u_trans_t *ref, asg64_v *srt) -{ - uint64_t k, len; uint32_t *bm; - ma_ug_t *ug = idx->ug; - if(max_round <= 0) { - for (k = 0; k < ug->g->n_seq; k++) { - if(hh->h.a[k].n >= hh->h.a[k].m) continue; - hh->a.a[hh->h.a[k].a+hh->h.a[k].n] = hapid; - hh->h.a[k].n++; - } - return; - } - - for (k = 0; k < ug->g->n_seq; k++) { - del[k] = 0; s->s[k] = 0; - if(hh->h.a[k].n >= hh->h.a[k].m) {///all haplotypes have been set - bub->index[k] = (uint32_t)-1; del[k] = 1; - } else { - if(IF_HOM(k, (*bub))) bub->index[k] = bub->num.n; - } - bidx[k] = bub->index[k]; - } - bm = bub->index; bub->index = bidx; bidx = bm; - - kv_resize(u_trans_t, *ref, idx->t_ch->k_trans.n); ref->n = idx->t_ch->k_trans.n; - memcpy(ref->a, idx->t_ch->k_trans.a, ref->n*sizeof((*(ref->a)))); - kv_resize(uint64_t, ref->idx, idx->t_ch->k_trans.idx.n); ref->idx.n = idx->t_ch->k_trans.idx.n; - memcpy(ref->idx.a, idx->t_ch->k_trans.idx.a, ref->idx.n*sizeof((*(ref->idx.a)))); - exchange_kv_u_trans_t(ref, &(idx->t_ch->k_trans)); - - for (k = 0; k < max_round; k++) { - clean_trans_ovlp(bub, &(idx->t_ch->k_trans), ref, ((k+1)g->n_seq; k++) { - if(del[k] != 2) { - if((hh->h.a[k].n == hh->h.a[k].m) && (hh->h.a[k].m == ((uint64_t)asm_opt.polyploidy))) { - len += ug->g->seq[k].len; - } - continue; - } - assert(hh->h.a[k].n < hh->h.a[k].m); - hh->a.a[hh->h.a[k].a+hh->h.a[k].n] = hapid; - hh->h.a[k].n++; len += ug->g->seq[k].len; - } - fprintf(stderr, "[M::%s::stat] # hap%lu bases: %lu\n", __func__, hapid+1, len); - - bm = bub->index; bub->index = bidx; bidx = bm; - exchange_kv_u_trans_t(ref, &(idx->t_ch->k_trans)); -} - -int hic_short_align_mmhap(const enzyme *fn1, const enzyme *fn2, ha_ug_index* idx, ug_opt_t *opt, kvec_pe_hit **rhits, mmhap_t **rh) -{ - if(rh) (*rh) = NULL; - sldat_t sl; - sl.idx = idx; - sl.t_ch = idx->t_ch; - sl.chunk_size = 20000000; - sl.n_thread = asm_opt.thread_num; - sl.total_base = sl.total_pair = 0; - idx->hap_cnt = asm_opt.hap_occ; - kv_init(sl.hits.a); kv_init(sl.hits.idx); kv_init(sl.hits.occ); - - - if(!load_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name)) { - alignment_worker_pipeline(&sl, fn1, fn2); - write_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name); - } - sl.hits.uID_bits = idx->uID_bits; sl.hits.pos_mode = idx->pos_mode; - - if(sl.hits.idx.n == 0) idx_hc_links(&(sl.hits), idx, NULL); - - mmhap_t *hh = gen_mmhap_t(idx->ug, idx->read_g, opt->sources); - bubble_type *bub = gen_mmhap_bub(idx->ug, idx->t_ch->ir_het, &(idx->t_ch->k_trans), hh); - hc_links link; init_hc_links(&link, idx->ug->g->n_seq, idx->t_ch); - measure_distance(idx, idx->ug, &sl.hits, &link, bub, &(idx->t_ch->k_trans)); - kv_u_trans_t k_trans; kv_init(k_trans); kv_init(k_trans.idx); - ps_t *s = init_ps_t(11, idx->ug->g->n_seq); ///H_partition hap; - uint64_t k, n_hap = asm_opt.polyploidy; asg64_v srt; kv_init(srt); - uint8_t *ff; CALLOC(ff, idx->ug->g->n_seq); - uint32_t *bidx; MALLOC(bidx, idx->ug->g->n_seq); - kv_u_trans_t r_trans_buf; kv_init(r_trans_buf); kv_init(r_trans_buf.idx); - - for (k = 0; k < n_hap; k++) { - purge_phase(idx, hh, k, ((n_hap>k)?(n_hap-k-1):(0)), &link, &sl.hits, bub, s, &k_trans, ff, bidx, &r_trans_buf, &srt); - } - if(rh) (*rh) = hh; - - // if(rhits) (*rhits) = get_r_hits_order(&sl.hits, idx->uID_bits, idx->pos_mode, idx->read_g, idx->ug, &bub); - - kv_destroy(sl.hits.a); kv_destroy(sl.hits.idx); kv_destroy(sl.hits.occ); - destory_hc_links(&link); - kv_destroy(k_trans); kv_destroy(k_trans.idx); - destory_ps_t(&s); destory_bubbles(bub); free(bub); - kv_destroy(srt); free(ff); free(bidx); - kv_destroy(r_trans_buf); kv_destroy(r_trans_buf.idx); - return 1; -} - - -void hic_analysis(ma_ug_t *ug, asg_t* read_g, trans_chain* t_ch, ug_opt_t *opt, mmhap_t **rh, kvec_pe_hit **rhits) -{ - ug_index = NULL; - int exist = (asm_opt.load_index_from_disk? - load_hc_pt_index(&ug_index, ug, asm_opt.output_file_name) : 0); - if(exist == 0) ug_index = build_unitig_index(ug, asm_opt.hic_mer_length, asm_opt.hap_occ, 0, asm_opt.thread_num); - if(exist == 0) write_hc_pt_index(ug_index, asm_opt.output_file_name); - ug_index->ug = ug; - ug_index->read_g = read_g; - ug_index->t_ch = t_ch; - ///test_unitig_index(ug_index, ug); - if(!rh) hic_short_align(asm_opt.hic_reads[0], asm_opt.hic_reads[1], ug_index, opt, rhits); - else hic_short_align_mmhap(asm_opt.hic_reads[0], asm_opt.hic_reads[1], ug_index, opt, rhits, rh); - // else hic_short_align_poy(asm_opt.hic_reads[0], asm_opt.hic_reads[1], ug_index, opt); - - - destory_hc_pt_index(ug_index);free(ug_index); -} - -uint64_t ug_occ_hap_w(uint64_t is, uint64_t ie, ma_utg_t *u) -{ - uint64_t l, i, us, ue, occ; - for (i = l = occ = 0; i < u->n; i++) { - us = l; ue = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); - if(is <= us && ie >= ue) { - if((R_INF.trio_flag[u->a[i]>>33] == FATHER) || (R_INF.trio_flag[u->a[i]>>33] == MOTHER)) { - occ++; - } - } - if(us >= ie) break; - l += (uint32_t)u->a[i]; - } - return occ; -} - -void trio_phasing_refine(ma_ug_t *iug, asg_t* sg, kv_u_trans_t *ref, ug_opt_t *opt) -{ - ma_ug_t *ug = copy_untig_graph(iug); uint8_t *bf = NULL; - uint64_t ug_n0 = ug->g->n_seq, k, i, ul, cis_n, trans_n, w_n, tot_hap, tot_r, frid, mrid, flag; - kv_u_trans_t in; memset(&in, 0, sizeof(in)); ma_utg_t *p; u_trans_t *z; int64_t fh, mh; - bubble_type *bub = gen_bubble_chain(sg, ug, opt, &bf, 0); free(bf); - clean_u_trans_t_idx_filter_adv(ref, ug, sg, 0.95, 0); - - ///update ug itself - ul = FATHER; frid = ug->g->n_seq; asg_seq_set(ug->g, frid, ul, 0); - kv_pushp(ma_utg_t, ug->u, &p); memset(p, 0, sizeof((*p))); - p->s = 0; p->start = UINT32_MAX; p->end = UINT32_MAX; p->len = ul, p->n = p->m = 1; p->circ = 1; - kv_roundup32(p->m); p->a = (uint64_t*)malloc(8 * p->m); - p->a[0] = UINT32_MAX; p->a[0] <<= 32; p->a[0] |= ul; - - ul = MOTHER; mrid = ug->g->n_seq; asg_seq_set(ug->g, mrid, ul, 0); - kv_pushp(ma_utg_t, ug->u, &p); memset(p, 0, sizeof((*p))); - p->s = 0; p->start = UINT32_MAX; p->end = UINT32_MAX; p->len = ul, p->n = p->m = 1; p->circ = 1; - kv_roundup32(p->m); p->a = (uint64_t*)malloc(8 * p->m); - p->a[0] = UINT32_MAX; p->a[0] <<= 32; p->a[0] |= ul; - - free(ug->g->idx); ug->g->idx = 0; ug->g->is_srt = 0; asg_cleanup(ug->g); - - ///update bubble - REALLOC(bub->index, ug->g->n_seq); - for (k = ug_n0; k < ug->g->n_seq; k++) bub->index[k] = bub->f_bub+1; - - bub->b_s_idx.n = ug->g->n_seq; kv_resize(uint64_t, bub->b_s_idx, ug->g->n_seq); - for (k = ug_n0; k < bub->b_s_idx.m; k++) bub->b_s_idx.a[k] = (uint64_t)-1; - - ///check if a node has haplotype markers - CALLOC(bf, ug->g->n_seq); - for (k = cis_n = tot_hap = tot_r = 0; k < ug_n0; k++) { - if(ug->g->seq[k].del) continue; - p = &(ug->u.a[k]); tot_r += p->n; - if(p->n == 0 || p->m == 0) continue; - for (i = fh = mh = 0; i < p->n; i++) { - if(R_INF.trio_flag[p->a[i]>>33] == FATHER) { - tot_hap++; fh = 1; - } else if(R_INF.trio_flag[p->a[i]>>33] == MOTHER) { - tot_hap++; mh = 1; - } - if((R_INF.trio_flag[p->a[i]>>33] == FATHER) || (R_INF.trio_flag[p->a[i]>>33] == MOTHER)) { - tot_hap++; bf[k] = 1; - } - } - if(fh > 0) { - bf[k] = 1; cis_n+=2; - } - if(mh > 0) { - bf[k] = 1; cis_n+=2; - } - } - for (; k < ug->g->n_seq; k++) bf[k] = 1;///for father/mother nodes - - - ///update trans overlaps - kv_pushp(u_trans_t, *ref, &z); memset(z, 0, sizeof((*z))); - z->f = RC_2; z->nw = (DBL_MAX/2); z->rev = 0; - z->qn = ug_n0; z->tn = ug_n0+1; z->del = 0; - z->qs = 0; z->qe = ug->g->seq[z->qn].len; - z->ts = 0; z->te = ug->g->seq[z->tn].len; - - kv_pushp(u_trans_t, *ref, &z); memset(z, 0, sizeof((*z))); - z->f = RC_2; z->nw = (DBL_MAX/2); z->rev = 0; - z->qn = ug_n0+1; z->tn = ug_n0; z->del = 0; - z->qs = 0; z->qe = ug->g->seq[z->qn].len; - z->ts = 0; z->te = ug->g->seq[z->tn].len; - - kt_u_trans_t_idx(ref, ug->g->n_seq); - // clean_u_trans_t_idx_adv(ref, ug, sg); - // clean_u_trans_t_idx_filter_adv(ref, ug, sg); - - ///gen all links - for (k = trans_n = 0; k < ref->n; k++) { - if(ref->a[k].del) continue; - if((IF_HOM(ref->a[k].qn, (*bub))) || (IF_HOM(ref->a[k].tn, (*bub)))) continue; - ///disable bf - // if((!bf[ref->a[k].qn]) || (!bf[ref->a[k].tn])) continue; - trans_n++; - } - kv_resize(u_trans_t, in, (trans_n+cis_n)); - - for (k = in.n = 0; k < ref->n; k++) { - if(ref->a[k].del) continue; - if((IF_HOM(ref->a[k].qn, (*bub))) || (IF_HOM(ref->a[k].tn, (*bub)))) continue; - ///disable bf - // if((!bf[ref->a[k].qn]) || (!bf[ref->a[k].tn])) continue; - - kv_pushp(u_trans_t, in, &z); memset(z, 0, sizeof((*z))); w_n = 0; - if((ref->a[k].qn < ug_n0) && (ref->a[k].tn < ug_n0)) { - w_n += ug_occ_hap_w(ref->a[k].qs, ref->a[k].qe, &(ug->u.a[ref->a[k].qn])) + - ug_occ_hap_w(ref->a[k].ts, ref->a[k].te, &(ug->u.a[ref->a[k].tn])); - w_n += ug_occ_w(ref->a[k].qs, ref->a[k].qe, &(ug->u.a[ref->a[k].qn])) + - ug_occ_w(ref->a[k].ts, ref->a[k].te, &(ug->u.a[ref->a[k].tn])); - } else { - w_n += tot_hap + tot_r; - } - w_n >>= 1;///wn/4 - (*z) = ref->a[k]; z->nw = ((w_n)?(w_n):(1)); - } - - for (k = 0; k < ug_n0; k++) { - if(!bf[k]) continue; - p = &(ug->u.a[k]); - if(p->n == 0 || p->m == 0) continue; - fh = mh = 0; - for (i = 0; i < p->n; i++) { - if(R_INF.trio_flag[p->a[i]>>33] == FATHER) fh--; - if(R_INF.trio_flag[p->a[i]>>33] == MOTHER) mh--; - } - if(fh != 0) { - w_n = frid; - - kv_pushp(u_trans_t, in, &z); memset(z, 0, sizeof((*z))); - z->f = RC_2; z->nw = fh; z->rev = 0; - z->qn = w_n; z->tn = k; z->del = 0; - z->qs = 0; z->qe = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); - z->ts = 0; z->te = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); - - kv_pushp(u_trans_t, in, &z); memset(z, 0, sizeof((*z))); - z->f = RC_2; z->nw = fh; z->rev = 0; - z->qn = k; z->tn = w_n; z->del = 0; - z->qs = 0; z->qe = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); - z->ts = 0; z->te = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); - } - - if(mh != 0) { - w_n = mrid; - - kv_pushp(u_trans_t, in, &z); memset(z, 0, sizeof((*z))); - z->f = RC_2; z->nw = mh; z->rev = 0; - z->qn = w_n; z->tn = k; z->del = 0; - z->qs = 0; z->qe = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); - z->ts = 0; z->te = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); - - kv_pushp(u_trans_t, in, &z); memset(z, 0, sizeof((*z))); - z->f = RC_2; z->nw = mh; z->rev = 0; - z->qn = k; z->tn = w_n; z->del = 0; - z->qs = 0; z->qe = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); - z->ts = 0; z->te = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); - } - } - free(bf); - assert(in.n == (trans_n+cis_n)); - kt_u_trans_t_idx(&in, ug->g->n_seq); - // clean_u_trans_t_idx_adv(&in, ug, sg); - - ps_t *s = init_ps_t(11, ug->g->n_seq); s->s[frid] = 1; s->s[mrid] = -1; - mc_solve(NULL, NULL, &in, ug, sg, 0.8, NULL, 0, s->s, 1, bub, ref, 0, 0); - // fprintf(stderr, "[M::%s::] s[frid]::%d, s->s[mrid]::%d\n", __func__, s->s[frid], s->s[mrid]); - if((s->s[frid] != 0) && (s->s[mrid] != 0) && (s->s[frid] != s->s[mrid])) { - memset(R_INF.trio_flag, AMBIGU, R_INF.total_reads * sizeof(uint8_t)); - for (i = 0; i < ug_n0; i++) { - if(ug->g->seq[i].del) continue; - flag = AMBIGU; - if(s->s[i] == 0) continue; - flag = (s->s[i] == s->s[frid]? FATHER:MOTHER); - p = &ug->u.a[i]; - if(p->m == 0) continue; - for (k = 0; k < p->n; k++) R_INF.trio_flag[p->a[k]>>33] = flag; - } - } - - destory_bubbles(bub); free(bub); ma_ug_destroy(ug); - destory_ps_t(&s); kv_destroy(in); kv_destroy(in.idx); -} - -spg_t *hic_pre_analysis(ma_ug_t *ug, asg_t* read_g, trans_chain* t_ch, ug_opt_t *opt, kvec_pe_hit **rhits) -{ - ug_index = NULL; - int exist = (asm_opt.load_index_from_disk? - load_hc_pt_index(&ug_index, ug, asm_opt.output_file_name) : 0); - if(exist == 0) ug_index = build_unitig_index(ug, asm_opt.hic_mer_length, asm_opt.hap_occ, 0, asm_opt.thread_num); - if(exist == 0) write_hc_pt_index(ug_index, asm_opt.output_file_name); - ug_index->ug = ug; - ug_index->read_g = read_g; - ug_index->t_ch = t_ch; - return hic_short_pre_align(asm_opt.hic_reads[0], asm_opt.hic_reads[1], ug_index, opt, rhits); -} - - -void init_ug_idx(ma_ug_t *ug, uint64_t k, uint64_t up_bound, uint64_t low_bound, uint64_t build_idx) -{ - ug_index = NULL; - if(build_idx) - { - ug_index = build_unitig_index(ug, k, up_bound, low_bound, asm_opt.thread_num); - } -} - -void des_ug_idx() -{ - destory_hc_pt_index(ug_index); -} - -uint64_t count_unique_k_mers(char *r, uint64_t len, uint64_t query, uint64_t target, uint64_t *all, uint64_t *found) -{ - if(!ug_index) return 0; - uint64_t i, j, l = 0, skip, *pos_list = NULL, cnt, uID, is_q, k_mer = ug_index->k; - uint64_t x[4], mask = (1ULL<>1)) & mask; - x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; - x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; - if (++l >= k_mer) - { - hash = hc_hash_long(x, &skip, k_mer); - if(skip == (uint64_t)-1) continue; - cnt = get_hc_pt1_count((ha_ug_index*)ug_index, hash, &pos_list); - if(cnt <= 0) continue; - - for (j = 0, is_q = 0; j < cnt; j++) - { - uID = (pos_list[j] << 1) >> (64 - ug_index->uID_bits); - if(query == uID) is_q = 1; - if(target == uID) break; - } - - if(is_q) - { - (*found)++; - if(j < cnt) (*all)++; - } - } - - } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; // if there is an "N", restart - } - - return 1; -} - - -typedef struct{ - //[uID_start, uID_end) - uint64_t uID_start; - uint64_t uID_end; - uint64_t u_n; - uint64_t r_n; - uint64_t* r_idx; -} bench_utg; - -typedef struct{ - uint64_t s, e; -}homo_interval; - -typedef struct{ - kvec_t(bench_utg) ug_idx; - uint64_t uID_bits; - uint64_t pos_mode; - hc_links link; - kvec_t(homo_interval) regions; -}bench_idx; - -uint64_t* set_bench_idx(ma_ug_t *ug, asg_t* read_g, uint64_t uID_start, uint64_t uID_end, uint64_t uID_bits, uint64_t r_n) -{ - uint64_t *idx = (uint64_t*)malloc(sizeof(uint64_t)*r_n), i, k; - memset(idx, -1, sizeof(uint64_t)*r_n); - uint64_t rId, ori, start, l; - ma_utg_t *u = NULL; - for (i = uID_start; i < uID_end; i++) - { - u = &(ug->u.a[i]); - if(u->n == 0) continue; - for (k = l = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - ori = u->a[k]>>32&1; - start = l; - l += (uint32_t)u->a[k]; - if(idx[rId] != (uint64_t)-1) - { - idx[rId] = (uint64_t)-1; - } - else - { - idx[rId] = (ori<<63) + ((i<<(64-uID_bits))>>1) + start; - if(ori) idx[rId] = idx[rId] + read_g->seq[rId].len - 1; - } - } - } - - return idx; -} - -void get_r_utg_bench(uint64_t index, bench_idx* idx, ma_ug_t *ug) -{ - - bench_utg* a_list = idx->ug_idx.a; - uint64_t a_n = idx->ug_idx.n; - bench_utg *x = &(a_list[index]), *y = NULL; - uint64_t i, k, t, rev, x_uid, y_uid, y_pos, x_pos, d; - uint64_t rId, ori; - ma_utg_t *u = NULL; - for (i = x->uID_start; i < x->uID_end; i++) - { - u = &(ug->u.a[i]); - x_uid = i; - if(u->n == 0) continue; - for (k = 0; k < u->n; k++) - { - rId = u->a[k]>>33; - ori = u->a[k]>>32&1; - if(x->r_idx[rId] == (uint64_t)-1) continue; - x_pos = x->r_idx[rId] & idx->pos_mode; - - for (t = 0; t < a_n; t++) - { - if(t == index) continue; - y = &(a_list[t]); - if(y->r_idx[rId] == (uint64_t)-1) continue; - rev = 0; - if((y->r_idx[rId]>>63) != ori) rev = 1; - y_uid = (y->r_idx[rId]<<1)>>(64 - idx->uID_bits); - y_pos = y->r_idx[rId] & idx->pos_mode; - if(rev) y_pos = ug->u.a[y_uid].len - y_pos - 1; - ///if(ori) x_pos = ug->u.a[x_uid].len - x_pos - 1, y_pos = ug->u.a[y_uid].len - y_pos - 1; - d = MAX(x_pos, y_pos) - MIN(x_pos, y_pos); - d = (d<<2) + (rev<<1); - if(y_pos > x_pos) d = d + 1; - push_hc_edge(&(idx->link.a.a[x_uid]), y_uid, 1, 0, &d); - if(x_pos != y_pos) d = d ^ 1; - push_hc_edge(&(idx->link.a.a[y_uid]), x_uid, 1, 0, &d); - } - } - } -} - -void hap_ID(bench_idx* idx, uint64_t ID, uint64_t* hapID, uint64_t* uID) -{ - uint64_t i; - (*hapID) = (*uID) = (uint64_t)-1; - for (i = 0; i < idx->ug_idx.n; i++) - { - if(ID >= idx->ug_idx.a[i].uID_start && ID < idx->ug_idx.a[i].uID_end) - { - (*hapID) = i; - (*uID) = ID - idx->ug_idx.a[i].uID_start; - return; - } - } - return; -} - -void print_bench_idx(bench_idx* idx, ma_ug_t *ug) -{ - uint64_t i, k, s_uID, s_hapID, d_uID, d_hapID; - long long x[2] = {1, -1}; - for (i = 0; i < idx->link.a.n; i++) - { - for (k = 0; k < idx->link.a.a[i].e.n; k++) - { - if(idx->link.a.a[i].e.a[k].del) continue; - hap_ID(idx, i, &s_hapID, &s_uID); - hap_ID(idx, idx->link.a.a[i].e.a[k].uID, &d_hapID, &d_uID); - fprintf(stderr, "s-hap%lu-utg%.6d\td-hap%lu-utg%.6d\t%c\t%lld\n", - s_hapID, (int)(s_uID+1), d_hapID, (int)(d_uID+1), - "+-"[!!(idx->link.a.a[i].e.a[k].dis&(uint64_t)2)], - ((long long)(idx->link.a.a[i].e.a[k].dis>>2))*x[idx->link.a.a[i].e.a[k].dis&(uint64_t)1]); - } - } - - -} - -uint64_t get_hic_distance_bench_hap(pe_hit_hap* hit, hc_links* link, bench_idx* idx, ma_ug_t *ug, uint64_t* is_trans) -{ - (*is_trans) = (uint64_t)-1; - uint64_t s_uid, e_uid; - long long s_pos, e_pos; - s_uid = ((get_pe_s(*hit)<<1)>>(64 - idx->uID_bits)); s_pos = get_pe_s(*hit) & idx->pos_mode; - e_uid = ((get_pe_e(*hit)<<1)>>(64 - idx->uID_bits)); e_pos = get_pe_e(*hit) & idx->pos_mode; - if(s_uid == e_uid) - { - (*is_trans) = 0; - return MAX(s_pos, e_pos) - MIN(s_pos, e_pos); - } - - uint64_t s_i, e_i, k, ori; - for (s_i = 0; s_i < idx->ug_idx.n; s_i++) - { - if(s_uid >= idx->ug_idx.a[s_i].uID_start && s_uid < idx->ug_idx.a[s_i].uID_end) break; - } - for (e_i = 0; e_i < idx->ug_idx.n; e_i++) - { - if(e_uid >= idx->ug_idx.a[e_i].uID_start && e_uid < idx->ug_idx.a[e_i].uID_end) break; - } - if(s_i == idx->ug_idx.n || e_i == idx->ug_idx.n) return (uint64_t)-1; - if(s_i == e_i) - { - (*is_trans) = 0; - return (uint64_t)-1; - } - - (*is_trans) = 1; - hc_linkeage* t = &(link->a.a[s_uid]); - long long m_x[2] = {1, -1}, dis; - for (k = 0; k < t->e.n; k++) - { - if(t->e.a[k].del || t->e.a[k].uID != e_uid) continue; - ori = !!(t->e.a[k].dis & (uint64_t)2); - dis = (long long)(t->e.a[k].dis>>2) * m_x[t->e.a[k].dis & (uint64_t)1]; - if(ori) e_pos = ug->u.a[e_uid].len - e_pos - 1; - e_pos = e_pos + dis; - return MAX(s_pos, e_pos) - MIN(s_pos, e_pos); - } - - return (uint64_t)-1; -} - -uint64_t get_hic_distance_bench(pe_hit* hit, hc_links* link, bench_idx* idx, ma_ug_t *ug, uint64_t* is_trans) -{ - (*is_trans) = (uint64_t)-1; - uint64_t s_uid, e_uid; - long long s_pos, e_pos; - s_uid = ((hit->s<<1)>>(64 - idx->uID_bits)); s_pos = hit->s & idx->pos_mode; - e_uid = ((hit->e<<1)>>(64 - idx->uID_bits)); e_pos = hit->e & idx->pos_mode; - if(s_uid == e_uid) - { - (*is_trans) = 0; - return MAX(s_pos, e_pos) - MIN(s_pos, e_pos); - } - - uint64_t s_i, e_i, k, ori; - for (s_i = 0; s_i < idx->ug_idx.n; s_i++) - { - if(s_uid >= idx->ug_idx.a[s_i].uID_start && s_uid < idx->ug_idx.a[s_i].uID_end) break; - } - for (e_i = 0; e_i < idx->ug_idx.n; e_i++) - { - if(e_uid >= idx->ug_idx.a[e_i].uID_start && e_uid < idx->ug_idx.a[e_i].uID_end) break; - } - if(s_i == idx->ug_idx.n || e_i == idx->ug_idx.n) return (uint64_t)-1; - if(s_i == e_i) - { - (*is_trans) = 0; - return (uint64_t)-1; - } - - (*is_trans) = 1; - hc_linkeage* t = &(link->a.a[s_uid]); - long long m_x[2] = {1, -1}, dis; - for (k = 0; k < t->e.n; k++) - { - if(t->e.a[k].del || t->e.a[k].uID != e_uid) continue; - ori = !!(t->e.a[k].dis & (uint64_t)2); - dis = (long long)(t->e.a[k].dis>>2) * m_x[t->e.a[k].dis & (uint64_t)1]; - if(ori) e_pos = ug->u.a[e_uid].len - e_pos - 1; - e_pos = e_pos + dis; - return MAX(s_pos, e_pos) - MIN(s_pos, e_pos); - } - - return (uint64_t)-1; -} - - -void init_bench_idx(bench_idx* idx, asg_t* read_g, ma_ug_t *ug) -{ - uint64_t i, occ; - kv_init(idx->ug_idx); - kv_init(idx->regions); - kv_malloc(idx->ug_idx, ug->occ.n); idx->ug_idx.n = ug->occ.n; - for (idx->uID_bits = 1; (uint64_t)(1<uID_bits)<(uint64_t)ug->u.n; idx->uID_bits++); - idx->pos_mode = ((uint64_t)-1)>>(idx->uID_bits+1); - for (i = occ = 0; i < ug->occ.n; i++) - { - idx->ug_idx.a[i].uID_start = occ; - occ += ug->occ.a[i]; - idx->ug_idx.a[i].uID_end = occ; - idx->ug_idx.a[i].u_n = ug->occ.a[i]; - - idx->ug_idx.a[i].r_n = read_g->n_seq; - idx->ug_idx.a[i].r_idx - = set_bench_idx(ug, read_g, idx->ug_idx.a[i].uID_start, idx->ug_idx.a[i].uID_end, - idx->uID_bits, idx->ug_idx.a[i].r_n); - } - - init_hc_links(&(idx->link), ug->u.n, NULL); - - for (i = 0; i < idx->ug_idx.n; i++) - { - get_r_utg_bench(i, idx, ug); - } -} - -void evaluate_bench_idx_hap(bench_idx* idx, kvec_pe_hit_hap* hits, ma_ug_t *ug) -{ - uint64_t k, distance, is_trans, trans[2]; - kvec_t(uint64_t) buf; - kv_init(buf); - for (k = trans[0] = trans[1] = 0; k < hits->n_u; ++k) - { - distance = get_hic_distance_bench_hap(&(hits->a[k]), &(idx->link), idx, ug, &is_trans); - if(is_trans != (uint64_t)-1) trans[is_trans]++; - if(distance == (uint64_t)-1 || is_trans == (uint64_t)-1) continue; - distance = (distance << 1) + is_trans; - kv_push(uint64_t, buf, distance); - } - - radix_sort_hc64(buf.a, buf.a+buf.n); - - for (k = 0; k < buf.n; k++) - { - fprintf(stderr, "%lu\t%lu\n", buf.a[k]>>1, buf.a[k]&1); - } - /** - uint64_t up_dis = buf.a[(uint64_t)(buf.n*0.99)]>>1, step = 7240; - uint64_t step_s = 0, step_e = step, cnt[2]; - for (k = cnt[0] = cnt[1] = 0; k < buf.n; k++) - { - if(step_s > up_dis) step_e = (buf.a[buf.n-1]>>1) + 1; - if((buf.a[k]>>1) < step_e && (buf.a[k]>>1) >= step_s) - { - cnt[buf.a[k]&1]++; - } - if((buf.a[k]>>1) >= step_e) - { - while (!((buf.a[k]>>1) < step_e && (buf.a[k]>>1) >= step_s)) - { - fprintf(stderr, "i: %lu, step_s: %lu, step_e: %lu, cnt[0]: %lu, cnt[1]: %lu, rate: %f\n", - step_s/step, step_s, step_e, cnt[0], cnt[1], ((double)cnt[1])/(double)(cnt[0] + cnt[1])); - step_s += step; - step_e += step; - cnt[0] = cnt[1] = 0; - } - } - } - - if(cnt[0] > 0 || cnt[1] > 0) - { - fprintf(stderr, "i: %lu, step_s: %lu, step_e: %lu, cnt[0]: %lu, cnt[1]: %lu, rate: %f\n", - step_s/step, step_s, step_e, cnt[0], cnt[1], ((double)cnt[1])/(double)(cnt[0] + cnt[1])); - } - **/ - kv_destroy(buf); -} - - -void evaluate_bench_idx(bench_idx* idx, kvec_pe_hit* hits, ma_ug_t *ug) -{ - uint64_t k, distance, is_trans, trans[2]; - kvec_t(uint64_t) buf; - kv_init(buf); - for (k = trans[0] = trans[1] = 0; k < hits->a.n; ++k) - { - distance = get_hic_distance_bench(&(hits->a.a[k]), &(idx->link), idx, ug, &is_trans); - if(is_trans != (uint64_t)-1) trans[is_trans]++; - if(distance == (uint64_t)-1 || is_trans == (uint64_t)-1) continue; - distance = (distance << 1) + is_trans; - kv_push(uint64_t, buf, distance); - } - - radix_sort_hc64(buf.a, buf.a+buf.n); - - for (k = 0; k < buf.n; k++) - { - fprintf(stderr, "%lu\t%lu\n", buf.a[k]>>1, buf.a[k]&1); - } - /** - uint64_t up_dis = buf.a[(uint64_t)(buf.n*0.99)]>>1, step = 7240; - uint64_t step_s = 0, step_e = step, cnt[2]; - for (k = cnt[0] = cnt[1] = 0; k < buf.n; k++) - { - if(step_s > up_dis) step_e = (buf.a[buf.n-1]>>1) + 1; - if((buf.a[k]>>1) < step_e && (buf.a[k]>>1) >= step_s) - { - cnt[buf.a[k]&1]++; - } - if((buf.a[k]>>1) >= step_e) - { - while (!((buf.a[k]>>1) < step_e && (buf.a[k]>>1) >= step_s)) - { - fprintf(stderr, "i: %lu, step_s: %lu, step_e: %lu, cnt[0]: %lu, cnt[1]: %lu, rate: %f\n", - step_s/step, step_s, step_e, cnt[0], cnt[1], ((double)cnt[1])/(double)(cnt[0] + cnt[1])); - step_s += step; - step_e += step; - cnt[0] = cnt[1] = 0; - } - } - } - - if(cnt[0] > 0 || cnt[1] > 0) - { - fprintf(stderr, "i: %lu, step_s: %lu, step_e: %lu, cnt[0]: %lu, cnt[1]: %lu, rate: %f\n", - step_s/step, step_s, step_e, cnt[0], cnt[1], ((double)cnt[1])/(double)(cnt[0] + cnt[1])); - } - **/ - kv_destroy(buf); -} - -void destory_bench_idx(bench_idx* idx) -{ - uint64_t i; - for (i = 0; i < idx->ug_idx.n; i++) - { - free(idx->ug_idx.a[i].r_idx); - } - kv_destroy(idx->ug_idx); - kv_destroy(idx->regions); - destory_hc_links(&(idx->link)); -} - - -int hic_short_align_bench(const enzyme *fn1, const enzyme *fn2, const char *output_file_name, ha_ug_index* idx) -{ - double index_time = yak_realtime(); - sldat_t sl; - sl.idx = idx; - ///sl.link = NULL; - sl.chunk_size = 20000000; - sl.n_thread = asm_opt.thread_num; - sl.total_base = sl.total_pair = 0; - idx->hap_cnt = asm_opt.hap_occ; - kv_init(sl.hits.a); - fprintf(stderr, "u.n: %d, uID_bits: %lu, pos_bits: %lu\n", (uint32_t)idx->ug->u.n, idx->uID_bits, idx->pos_bits); - - if(!load_hc_hits(&sl.hits, idx->ug, output_file_name)) - { - // kt_pipeline(3, worker_pipeline, &sl, 3); - // dedup_hits(&sl.hits); - alignment_worker_pipeline(&sl, fn1, fn2); - write_hc_hits(&sl.hits, idx->ug, output_file_name); - } - bench_idx bench; - init_bench_idx(&bench, idx->read_g, idx->ug); - ///print_bench_idx(&bench, idx->ug); - evaluate_bench_idx(&bench, &sl.hits, idx->ug); - - destory_bench_idx(&bench); - kv_destroy(sl.hits.a); - fprintf(stderr, "[M::%s::%.3f] processed %lu pairs; %lu bases\n", __func__, yak_realtime()-index_time, sl.total_pair, sl.total_base); - return 1; -} - -void hic_benchmark(ma_ug_t *ug, asg_t* read_g) -{ - char *output_file_name = (char*)calloc(strlen(asm_opt.output_file_name) + 25, 1); - sprintf(output_file_name, "%s.bench", asm_opt.output_file_name); - ug_index = NULL; - int exist = load_hc_pt_index(&ug_index, ug, output_file_name); - if(exist == 0) ug_index = build_unitig_index(ug, asm_opt.hic_mer_length, asm_opt.hap_occ, 0, asm_opt.thread_num); - if(exist == 0) write_hc_pt_index(ug_index, output_file_name); - ug_index->ug = ug; - ug_index->read_g = read_g; - - hic_short_align_bench(asm_opt.hic_reads[0], asm_opt.hic_reads[1], output_file_name, ug_index); - - free(output_file_name); +#define __STDC_LIMIT_MACROS +#include "float.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" +#include "horder.h" +#include "gfa_ut.h" +KSEQ_INIT(gzFile, gzread) +KDQ_INIT(uint64_t) + + +#define OFFSET_RATE 0.000000001 +#define OFFSET_SECOND_RATE 0.0000000001 +#define SCALL 10000 +#define OFFSET_RATE_MAX_W 6.90675477865*SCALL +#define OFFSET_RATE_MIN_W 4.0000003e-10*SCALL + +#define HIC_COUNTER_BITS 12 +#define HIC_MAX_COUNT ((1<>HIC_COUNTER_BITS == (b)>>HIC_COUNTER_BITS) +#define hic_ct_hash(a) ((a)>>HIC_COUNTER_BITS) +KHASHL_MAP_INIT(static klib_unused, hc_pt_t, hc_pt, uint64_t, uint64_t, hic_ct_hash, hic_ct_eq) + +#define u_trans_m_key(a) (((uint64_t)((a).qn)<<32) | ((uint64_t)((a).tn))) +KRADIX_SORT_INIT(u_trans_m, u_trans_t, u_trans_m_key, 8) + +#define u_trans_occ_key(a) ((a).occ) +KRADIX_SORT_INIT(u_trans_occ, u_trans_t, u_trans_occ_key, member_size(u_trans_t, occ)) + +#define is_hom_hit(a) ((a).id == (uint64_t)-1) +#define HC_PT_MA 65 + +typedef struct { + kv_gg_status sg; + uint64_t xs; +} psg_t; + +typedef struct{ + kvec_t(char) name; + kvec_t(uint64_t) name_Len; + kvec_t(char) r; + kvec_t(uint64_t) r_Len; + uint64_t idx; +} reads_t; + + +typedef struct{ + kvec_t(hc_edge_warp) rGraph; + kvec_t(uint64_t) order; + pdq pq; + kvec_t(uint8_t) rGraphSet; + kvec_t(uint8_t) rGraphVis; + kvec_t(uint8_t) utgVis; + kvec_t(uint8_t) bmerVis; + kdq_t(uint64_t) *q; + kvec_t(uint32_t) parent; + kvec_t(double) p_weight; + const uint64_t* enzymes; + uint64_t uID_mode, uID_shift, n, src, dest, n_e, c_e; + int p_mer, a_mer, b_mer; +} min_cut_t; + + +typedef struct{ + kvec_t(uint32_t) a; + uint32_t h[2]; + uint8_t full_bub; + int status[2]; + double weight[2], weight_convex; +}partition_warp; + +typedef struct{ + size_t n, m; + partition_warp* a; + uint32_t* index; +}G_partition; + +typedef struct{ + kvec_t(uint8_t) vis; + double weight; + long long bid, uid, chainID; +}block_phase_type; + +typedef struct{ + uint64_t n; + uint8_t* lock; + uint32_t* hap; + uint32_t m[3]; + uint32_t label, label_add, label_shift; + hc_links* link; + G_partition g_p; + G_partition group_g_p; + kvec_t(double) label_buffer; + block_phase_type b; +}H_partition; + +typedef struct { + uint32_t p; // the optimal parent vertex + uint32_t d; // the shortest distance from the initial vertex + uint32_t nc; // max count of reads, no matter positive or negative + double nh, w[2]; + uint32_t uc, ac; // used vertex/allowed vertex + uint32_t r:31, s:1; // r: the number of remaining incoming arc; s: state + //s: state, s=0, this edge has not been visited, otherwise, s=1 +} bub_p_t; + +typedef struct { + ///all information for each node + bub_p_t *a; + kvec_t(uint32_t) S; // set of vertices without parents, nodes with all incoming edges visited + kvec_t(uint32_t) T; // set of tips + kvec_t(uint32_t) b; // visited vertices + kvec_t(uint32_t) e; // visited edges/arcs + uint32_t exist_hap_label; +} bub_p_t_warp; + + +typedef struct { + hc_pt_t *h; + uint64_t n; + uint64_t *a; + khint_t end;///end of total idx +} hc_pt1_t; + +typedef struct { + ma_ug_t* ug; + asg_t* read_g; + ///hc_links* link; + trans_chain* t_ch; + uint64_t uID_bits; + uint64_t uID_mode; + uint64_t pos_bits; + uint64_t pos_mode; + uint64_t rev_mode; + uint64_t k; + uint64_t hap_cnt; + + + uint64_t pre; + uint64_t tot; + uint64_t tot_pos; + uint64_t up_bound, low_bound; + hc_pt1_t* idx_buf; + long double a, b, frac, max_d; +} ha_ug_index; + +typedef struct { // data structure for each step in kt_pipeline() + uint64_t key, pos; +} ch_buf_t; + +typedef struct { + kvec_t(uint64_t) a; +} kvec_cnt; + +typedef struct { + kvec_t(ch_buf_t) a; +} kvec_pos; + +typedef struct { // global data structure for kt_pipeline() + int is_cnt; + uint64_t buf_bytes; + ha_ug_index *h; + kvec_cnt* cnt; + kvec_pos* buf; + uint64_t n_thread; +} pldat_t; + +typedef struct { + uint64_t *a, id; + uint16_t occ1, occ2; +} pe_hit_hap; + +typedef struct { + pe_hit_hap* a; + size_t n, m; + uint64_t n_u; +} kvec_pe_hit_hap; + +typedef struct { + kvec_t(hc_edge) a; +}kvec_hc_edge; + +#define pe_hit_an1_key(x) ((x).s) +KRADIX_SORT_INIT(pe_hit_an1, pe_hit, pe_hit_an1_key, member_size(pe_hit, s)) +#define pe_hit_an2_key(x) ((x).e) +KRADIX_SORT_INIT(pe_hit_an2, pe_hit, pe_hit_an2_key, member_size(pe_hit, e)) + +#define pe_hit_an1_idx_key(x) ((x).s<<1) +KRADIX_SORT_INIT(pe_hit_idx_an1, 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_an2, pe_hit, pe_hit_an2_idx_key, member_size(pe_hit, e)) + +#define generic_key(x) (x) +KRADIX_SORT_INIT(hc64, uint64_t, generic_key, 8) +KRADIX_SORT_INIT(u32, uint32_t, generic_key, 4) +#define g_partition_key(x) (((x)>>1)+((x)<<63)) +KRADIX_SORT_INIT(g_partition, uint64_t, g_partition_key, 8) + +#define get_pe_s(x) ((x).a[0]) +#define get_pe_e(x) ((x).a[(x).occ1]) +KRADIX_SORT_INIT(pe_an1, pe_hit_hap, get_pe_s, 8) +KRADIX_SORT_INIT(pe_an2, pe_hit_hap, get_pe_e, 8) + +#define pe_occ_key_1(x) ((x).occ1) +KRADIX_SORT_INIT(pe_occ1, pe_hit_hap, pe_occ_key_1, member_size(pe_hit_hap, occ1)) +#define pe_occ_key_2(x) ((x).occ2) +KRADIX_SORT_INIT(pe_occ2, pe_hit_hap, pe_occ_key_2, member_size(pe_hit_hap, occ2)) +#define pe_occ_key_t(x) (((uint64_t)((x).occ1))+((uint64_t)((x).occ2))) +KRADIX_SORT_INIT(pe_occ_t, pe_hit_hap, pe_occ_key_t, 8) + +#define asg_arc_key(a) ((a).ul) +KRADIX_SORT_INIT(asg_e, asg_arc_t, asg_arc_key, 8) + +typedef struct { // global data structure for kt_pipeline() + const ha_ug_index* idx; + kseq_t *ks1, *ks2; + int64_t chunk_size; + uint64_t n_thread; + uint64_t total_base; + uint64_t total_pair; + kvec_pe_hit hits; + ///kvec_pe_hit_hap hits; + trans_chain* t_ch; +} sldat_t; + +typedef struct { + uint64_t ref; + uint64_t off_cnt; +} s_hit; + +typedef struct { + kvec_t(s_hit) a; +} kvec_vote; + +typedef struct { // data structure for each step in kt_pipeline() + const ha_ug_index* idx; + int n, m, sum_len; + uint64_t *len, id; + char **seq; + ch_buf_t *buf; + kvec_vote* pos_buf; + pe_hit* pos; + ///pe_hit_hap* pos; + trans_chain* t_ch; +} stepdat_t; + +#define generic_key(x) (x) +KRADIX_SORT_INIT(b64, uint64_t, generic_key, 8) +#define ch_buf_t_key(a) ((a).key) +KRADIX_SORT_INIT(ch_buf, ch_buf_t, ch_buf_t_key, member_size(ch_buf_t, key)) +#define hc_pos_key(x) ((x)<<1) +KRADIX_SORT_INIT(hc_pos, uint64_t, hc_pos_key, 8) +#define hc_s_hit_an1_key(a) ((a).ref) +KRADIX_SORT_INIT(hc_s_hit_an1, s_hit, hc_s_hit_an1_key, 8) +#define hc_s_hit_an2_key(a) ((uint32_t)(a).off_cnt) +KRADIX_SORT_INIT(hc_s_hit_an2, s_hit, hc_s_hit_an2_key, 8) +#define hc_s_hit_off_cnt_key(a) ((a).off_cnt) +KRADIX_SORT_INIT(hc_s_hit_off_cnt, s_hit, hc_s_hit_off_cnt_key, 8) +#define hc_edge_key_u(a) ((a).uID) +KRADIX_SORT_INIT(hc_edge_u, hc_edge, hc_edge_key_u, 4) +#define hc_edge_key_d(a) ((a).dis) +KRADIX_SORT_INIT(hc_edge_d, hc_edge, hc_edge_key_d, member_size(hc_edge, dis)) + +#define k_trans_qs_key(a) ((a).qs) +KRADIX_SORT_INIT(k_trans_qs, u_trans_t, k_trans_qs_key, member_size(u_trans_t, qs)) + +#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_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) + +typedef struct { + kvec_t(kvec_t_u64_warp) matrix; + uint64_t uID_shift, dis_mode; +} MT; + +typedef struct{ + uint64_t beg, end, dis, cnt_0, cnt_1; +} trans_p_t; + +typedef struct{ + trans_p_t* a; + size_t n, m; + uint64_t max, med; +} trans_idx; + +reads_t R1, R2; +ha_ug_index* ug_index; + +void print_debug_bubble_graph(bubble_type* bub, ma_ug_t* ug, const char *fn); + +void build_bub_graph(ma_ug_t* ug, bubble_type* bub); + +void init_ha_ug_index_opt(ha_ug_index* idx, ma_ug_t *ug, int k, pldat_t* p, uint64_t up_occ, +uint64_t low_occ, uint64_t thread_num) +{ + uint64_t i, n; + for (idx->uID_bits=1; (uint64_t)(1<uID_bits)<(uint64_t)ug->u.n; idx->uID_bits++); + idx->pos_bits = 64 - idx->uID_bits - 1; + idx->uID_mode = (((uint64_t)-1) << (64-idx->uID_bits))>>1; + idx->pos_mode = ((uint64_t)-1) >> (64-idx->pos_bits); + idx->rev_mode = ((uint64_t)1) << 63; + idx->ug = ug; + idx->k = k; + idx->pre = HIC_COUNTER_BITS; + idx->tot = 1 << idx->pre; + idx->tot_pos = 0; + ///idx->up_bound = 1; + idx->up_bound = up_occ; + idx->low_bound = low_occ; + CALLOC(idx->idx_buf, idx->tot); + for (i = 0; i < idx->tot; i++) + { + idx->idx_buf[i].h = hc_pt_init(); + } + for (i = n = 0; i < ug->u.n; i++) + { + n += ug->u.a[i].len; + } + n = n << 3; + p->h = idx; + p->buf_bytes = n>>7; + CALLOC(p->cnt, idx->tot); + CALLOC(p->buf, idx->tot); + for (i = 0; i < idx->tot; i++) + { + kv_init(p->cnt[i].a); + kv_init(p->buf[i].a); + } + p->n_thread = thread_num; +} + +inline uint64_t get_k_direction(uint64_t x[4]) +{ + if(x[1] != x[3]) + { + return x[1] < x[3]? 0 : 1; + } + else if(x[0] != x[2]) + { + return x[0] < x[2]? 0 : 1; + } + else + { + return (uint64_t)-1; + } +} + +inline uint64_t hc_hash_long(uint64_t x[4], uint64_t* skip, uint64_t k) +{ + ///compare forward k-mer and reverse complementary strand + (*skip) = get_k_direction(x); + if((*skip) == (uint64_t)-1) return (*skip); + if (k <= 32) return ((x[(*skip)<<1|0]<<32)|(x[(*skip)<<1|1])); + return yak_hash64_64(x[(*skip)<<1|0]) + yak_hash64_64(x[(*skip)<<1|1]); +} + +inline uint64_t get_hc_pt1_count(ha_ug_index* index, uint64_t key, uint64_t** pos_list) +{ + uint64_t bucket_mask = (1ULL<pre) - 1; + hc_pt1_t* h = &(index->idx_buf[key & bucket_mask]); + uint64_t beg; + khint_t k; + k = hc_pt_get(h->h, key); + if (k == kh_end(h->h)) + { + return 0; + } + beg = kh_val(h->h, k); + if(pos_list) *pos_list = h->a + beg; + if((kh_key(h->h, k)&HIC_MAX_COUNT)h, k)&HIC_MAX_COUNT; + if(k == h->end) return h->n - beg; + for (k++; k != kh_end(h->h); ++k) + { + if (kh_exist(h->h, k)) + { + return kh_val(h->h, k) - beg; + } + } + return h->n - beg; +} + +void test_hc_pt1(char* seq, uint64_t len, uint64_t uID, ha_ug_index* idx) +{ + uint64_t i, l, k, pos, *pos_list = NULL, cnt; + uint64_t x[4], mask = (1ULL<k) - 1, shift = idx->k - 1, hash, skip; + for (i = l = 0, x[0] = x[1] = x[2] = x[3] = 0; i < len; ++i) { + int c = seq_nt4_table[(uint8_t)seq[i]]; + ///c = 00, 01, 10, 11 + if (c < 4) { // not an "N" base + ///x[0] & x[1] are the forward k-mer + ///x[2] & x[3] are the reverse complementary k-mer + x[0] = (x[0] << 1 | (c&1)) & mask; + x[1] = (x[1] << 1 | (c>>1)) & mask; + x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; + x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; + if (++l >= idx->k) + { + hash = hc_hash_long(x, &skip, idx->k); + if(skip == (uint64_t)-1) continue; + pos = (skip << 63) | ((uID << (64-idx->uID_bits))>>1) | (i & idx->pos_mode); + cnt = get_hc_pt1_count(idx, hash, &pos_list); + if(cnt == 0) fprintf(stderr, "ERROR cnt, uID: %lu\n", uID); + for (k = 0; k < cnt; k++) + { + if(pos_list[k]==pos) + { + pos_list[k] = (uint64_t)-1; + break; + } + } + if(k == cnt) fprintf(stderr, "ERROR k\n"); + + } + } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; // if there is an "N", restart + } +} + +void test_unitig_index(ha_ug_index* idx, ma_ug_t *ug) +{ + double index_time = yak_realtime(); + uint32_t i, j; + ma_utg_t *u = NULL; + hc_pt1_t *h = NULL; + idx->ug = ug; + for (i = 0; i < idx->ug->u.n; i++) + { + u = &(idx->ug->u.a[i]); + if(u->m == 0) continue; + test_hc_pt1(u->s, u->len, i, idx); + } + + for (i = 0; i < idx->tot; i++) + { + h = &(idx->idx_buf[i]); + for (j = 0; j < h->n; j++) + { + if(h->a[j] != (uint64_t)-1) + { + fprintf(stderr, "ERROR j\n"); + } + } + + } + + fprintf(stderr, "[M::%s::%.3f] ==> Test has been passed\n", __func__, yak_realtime()-index_time); +} + +void hc_pt_t_gen_single(hc_pt1_t* pt, uint64_t* up_bound, uint64_t* low_bound) +{ + khint_t k; + uint64_t c; + + if(up_bound || low_bound) + { + for (k = 0; k != kh_end(pt->h); ++k) { + if (kh_exist(pt->h, k)) { + if((up_bound && kh_val(pt->h, k) > (*up_bound)) || + (low_bound && kh_val(pt->h, k) < (*low_bound))) + { + kh_val(pt->h, k) = 0; + kh_key(pt->h, k) = (kh_key(pt->h, k)&HIC_KEY_MODE)| + (kh_val(pt->h, k)h, k):HIC_MAX_COUNT); + } + } + } + } + + + for (k = 0, pt->n = 0; k != kh_end(pt->h); ++k) { + if (kh_exist(pt->h, k)) { + c = kh_val(pt->h, k); + kh_val(pt->h, k) = pt->n; + pt->n += c; + pt->end = k; + } + } + CALLOC(pt->a, pt->n); +} + + +int write_hc_pt_index(ha_ug_index* idx, char* file_name) +{ + char* gfa_name = (char*)malloc(strlen(file_name)+25); + sprintf(gfa_name, "%s.hic.tlb.bin", file_name); + FILE* fp = fopen(gfa_name, "w"); + if (!fp) { + free(gfa_name); + return 0; + } + uint64_t i = HC_PT_MA; + + fwrite(&i, sizeof(i), 1, fp); + fwrite(&idx->uID_bits, sizeof(idx->uID_bits), 1, fp); + fwrite(&idx->uID_mode, sizeof(idx->uID_mode), 1, fp); + fwrite(&idx->pos_bits, sizeof(idx->pos_bits), 1, fp); + fwrite(&idx->pos_mode, sizeof(idx->pos_mode), 1, fp); + fwrite(&idx->rev_mode, sizeof(idx->rev_mode), 1, fp); + fwrite(&idx->k, sizeof(idx->k), 1, fp); + fwrite(&idx->pre, sizeof(idx->pre), 1, fp); + fwrite(&idx->tot, sizeof(idx->tot), 1, fp); + fwrite(&idx->tot_pos, sizeof(idx->tot_pos), 1, fp); + + for (i = 0; i < idx->tot; i++) + { + fwrite(&idx->idx_buf[i].n, sizeof(idx->idx_buf[i].n), 1, fp); + fwrite(&idx->idx_buf[i].end, sizeof(idx->idx_buf[i].end), 1, fp); + fwrite(idx->idx_buf[i].a, sizeof(uint64_t), idx->idx_buf[i].n, fp); + hc_pt_save(idx->idx_buf[i].h, fp); + } + + write_dbug(idx->ug, fp); + + fprintf(stderr, "[M::%s] Index has been written.\n", __func__); + free(gfa_name); + fclose(fp); + return 1; +} + +void destory_hc_pt_index(ha_ug_index* idx); +int load_hc_pt_index(ha_ug_index** r_idx, ma_ug_t *ug, char* file_name) +{ + uint64_t flag = 0; + // double index_time = yak_realtime(); + char* gfa_name = (char*)malloc(strlen(file_name)+25); + sprintf(gfa_name, "%s.hic.tlb.bin", file_name); + FILE* fp = fopen(gfa_name, "r"); + if (!fp) { + free(gfa_name); + return 0; + } + ha_ug_index* idx = NULL; CALLOC(idx, 1); + uint64_t i; + + flag += fread(&i, sizeof(i), 1, fp); + if(i != HC_PT_MA) + { + free(gfa_name); + destory_hc_pt_index(idx); + free(idx); + (*r_idx) = NULL; + fclose(fp); + fprintf(stderr, "[M::%s::] ==> Renew Hi-C index\n", __func__); + return 0; + } + flag += fread(&idx->uID_bits, sizeof(idx->uID_bits), 1, fp); + flag += fread(&idx->uID_mode, sizeof(idx->uID_mode), 1, fp); + flag += fread(&idx->pos_bits, sizeof(idx->pos_bits), 1, fp); + flag += fread(&idx->pos_mode, sizeof(idx->pos_mode), 1, fp); + flag += fread(&idx->rev_mode, sizeof(idx->rev_mode), 1, fp); + flag += fread(&idx->k, sizeof(idx->k), 1, fp); + flag += fread(&idx->pre, sizeof(idx->pre), 1, fp); + flag += fread(&idx->tot, sizeof(idx->tot), 1, fp); + flag += fread(&idx->tot_pos, sizeof(idx->tot_pos), 1, fp); + MALLOC(idx->idx_buf, idx->tot); + + for (i = 0; i < idx->tot; i++) + { + flag += fread(&idx->idx_buf[i].n, sizeof(idx->idx_buf[i].n), 1, fp); + flag += fread(&idx->idx_buf[i].end, sizeof(idx->idx_buf[i].end), 1, fp); + MALLOC(idx->idx_buf[i].a, idx->idx_buf[i].n); + flag += fread(idx->idx_buf[i].a, sizeof(uint64_t), idx->idx_buf[i].n, fp); + hc_pt_load(&(idx->idx_buf[i].h), fp); + } + + + (*r_idx) = idx; + + free(gfa_name); + if(!test_dbug(ug, fp)) + { + destory_hc_pt_index(idx); + free(idx); + (*r_idx) = NULL; + fclose(fp); + fprintf(stderr, "[M::%s::] ==> Renew Hi-C index\n", __func__); + return 0; + } + + fclose(fp); + // fprintf(stderr, "[M::%s::%.3f] ==> HiC index has been loaded\n", __func__, yak_realtime()-index_time); + return 1; +} + +static void worker_for_sort(void *data, long i, int tid) // callback for kt_for() +{ + pldat_t *pl = (pldat_t*)data; + hc_pt1_t *h = &(pl->h->idx_buf[i]); + khint_t k; + uint64_t beg, cnt = 0; + uint64_t* pos_list; + for (k = 0; k != kh_end(h->h); ++k) { + if (kh_exist(h->h, k)) { + beg = kh_val(h->h, k); + pos_list = h->a + beg; + if((kh_key(h->h, k)&HIC_MAX_COUNT)h, k)&HIC_MAX_COUNT; + } + else if(k == h->end) + { + cnt = h->n - beg; + } + else + { + for (k++; k != kh_end(h->h); ++k) + { + if (kh_exist(h->h, k)) + { + cnt = kh_val(h->h, k) - beg; + break; + } + } + } + if(cnt > 0) radix_sort_hc_pos(pos_list, pos_list+cnt); + } + } + +} + +void hc_pt_t_gen(ha_ug_index* idx, pldat_t* pl) +{ + if(pl == NULL) + { + uint64_t i; + for (i = 0; i < idx->tot; i++) + { + hc_pt_t_gen_single(&(idx->idx_buf[i]), &(idx->up_bound), &(idx->low_bound)); + } + } + else + { + kt_for(pl->n_thread, worker_for_sort, pl, pl->h->tot); + } +} + +static void worker_for(void *data, long i, int tid) // callback for kt_for() +{ + pldat_t *pl = (pldat_t*)data; + hc_pt1_t *h = &(pl->h->idx_buf[i]); + uint64_t m = 0, beg, end, occ; + khint_t key; + int absent; + + + if(pl->is_cnt) + { + uint64_t* cnt = NULL; + if(pl->cnt[i].a.n > 2) radix_sort_b64(pl->cnt[i].a.a, pl->cnt[i].a.a + pl->cnt[i].a.n); + cnt = pl->cnt[i].a.a; + occ = pl->cnt[i].a.n; + for (m = beg = end = 0; m < occ; m++) + { + if(cnt[beg] == cnt[m]) + { + end = m; + } + else + { + key = hc_pt_put(h->h, cnt[beg], &absent); + if(absent) kh_val(h->h, key) = 0; + kh_val(h->h, key) += (end - beg + 1); + kh_key(h->h, key) = (kh_key(h->h, key)&HIC_KEY_MODE)| + (kh_val(h->h, key)h, key):HIC_MAX_COUNT); + beg = end = m; + } + } + if(occ > 0) + { + key = hc_pt_put(h->h, cnt[beg], &absent); + if(absent) kh_val(h->h, key) = 0; + kh_val(h->h, key) += (end - beg + 1); + kh_key(h->h, key) = (kh_key(h->h, key)&HIC_KEY_MODE)| + (kh_val(h->h, key)h, key):HIC_MAX_COUNT); + } + pl->cnt[i].a.n = 0; + } + + if(!pl->is_cnt) + { + ch_buf_t* pos = NULL; + uint64_t num, *pos_list = NULL, k, k_n, pos_k; + if(pl->buf[i].a.n > 2) radix_sort_ch_buf(pl->buf[i].a.a, pl->buf[i].a.a + pl->buf[i].a.n); + pos = pl->buf[i].a.a; + occ = pl->buf[i].a.n; + for (m = beg = end = 0; m < occ; m++) + { + if(pos[beg].key == pos[m].key) + { + end = m; + } + else + { + num = get_hc_pt1_count(pl->h, pos[beg].key, &pos_list); + if(num > 0) + { + k_n=(end-beg+1);pos_k=pos_list[num-1];pos_list[num-1]+=k_n; + for (k = 0; k < k_n; k++) + { + pos_list[pos_k+k] = pos[beg+k].pos; + } + } + + beg = end = m; + } + + } + if(occ > 0) + { + num = get_hc_pt1_count(pl->h, pos[beg].key, &pos_list); + if(num > 0) + { + k_n=(end-beg+1);pos_k=pos_list[num-1];pos_list[num-1]+=k_n; + for (k = 0; k < k_n; k++) + { + pos_list[pos_k+k] = pos[beg+k].pos; + } + } + } + pl->buf[i].a.n = 0; + } +} + +void parallel_count_hc_pt1(pldat_t* pl) +{ + uint64_t i, l = 0, uID, num_pos = 0, pos_thre; + uint64_t x[4], mask = (1ULL<h->k) - 1, shift = pl->h->k - 1, hash, pos, skip, bucket_mask = (1ULL<h->pre) - 1; + ma_utg_t *u = NULL; + ch_buf_t k_pos; + if(pl->is_cnt) l = ((pl->buf_bytes>>3)/pl->h->tot) + 1, pos_thre = pl->buf_bytes>>3; + if(!pl->is_cnt) l = ((pl->buf_bytes>>4)/pl->h->tot) + 1, pos_thre = pl->buf_bytes>>4; + for (i = 0; i < pl->h->tot; i++) + { + if(pl->is_cnt) + { + kv_resize(uint64_t, pl->cnt[i].a, l); + pl->cnt[i].a.n = 0; + } + + if(!pl->is_cnt) + { + kv_resize(ch_buf_t, pl->buf[i].a, l); + pl->buf[i].a.n = 0; + } + } + + + for (uID = 0; uID < pl->h->ug->u.n; uID++) + { + u = &(pl->h->ug->u.a[uID]); + if(u->m == 0) continue; + + for (i = l = 0, x[0] = x[1] = x[2] = x[3] = 0; i < u->len; ++i) { + int c = seq_nt4_table[(uint8_t)u->s[i]]; + ///c = 00, 01, 10, 11 + if (c < 4) { // not an "N" base + ///x[0] & x[1] are the forward k-mer + ///x[2] & x[3] are the reverse complementary k-mer + x[0] = (x[0] << 1 | (c&1)) & mask; + x[1] = (x[1] << 1 | (c>>1)) & mask; + x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; + x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; + if (++l >= pl->h->k) + { + hash = hc_hash_long(x, &skip, pl->h->k); + if(skip == (uint64_t)-1) continue; + if(pl->is_cnt) + { + kv_push(uint64_t, pl->cnt[hash & bucket_mask].a, hash); + } + else + { + pos = (skip << 63) | ((uID << (64-pl->h->uID_bits))>>1) | (i & pl->h->pos_mode); + k_pos.key = hash; k_pos.pos = pos; + kv_push(ch_buf_t, pl->buf[hash & bucket_mask].a, k_pos); + } + num_pos++; + + if(num_pos >= pos_thre) + { + num_pos = 0; + kt_for(pl->n_thread, worker_for, pl, pl->h->tot); + } + } + + } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; // if there is an "N", restart + } + } + + if(num_pos > 0) kt_for(pl->n_thread, worker_for, pl, pl->h->tot); + + for (i = 0; i < pl->h->tot; i++) + { + if(pl->cnt[i].a.m > 0) kv_destroy(pl->cnt[i].a), kv_init(pl->cnt[i].a); + if(pl->buf[i].a.m > 0) kv_destroy(pl->buf[i].a), kv_init(pl->buf[i].a); + } +} + +ha_ug_index* build_unitig_index(ma_ug_t *ug, int k, uint64_t up_occ, uint64_t low_occ, uint64_t thread_num) +{ + ha_ug_index* idx = NULL; CALLOC(idx, 1); + pldat_t pl; pl.h = idx; pl.is_cnt = 1; + double index_time = yak_realtime(), beg_time; + init_ha_ug_index_opt(idx, ug, k, &pl, up_occ, low_occ, thread_num); + + beg_time = yak_realtime(); + pl.is_cnt = 1; + parallel_count_hc_pt1(&pl); + fprintf(stderr, "[M::%s::%.3f] ==> Counting\n", __func__, yak_realtime()-beg_time); + + beg_time = yak_realtime(); + hc_pt_t_gen(pl.h, NULL); + fprintf(stderr, "[M::%s::%.3f] ==> Memory allocating\n", __func__, yak_realtime()-beg_time); + + beg_time = yak_realtime(); + pl.is_cnt = 0; + parallel_count_hc_pt1(&pl); + fprintf(stderr, "[M::%s::%.3f] ==> Filling pos\n", __func__, yak_realtime()-beg_time); + + beg_time = yak_realtime(); + hc_pt_t_gen(pl.h, &pl); + fprintf(stderr, "[M::%s::%.3f] ==> Sorting pos\n", __func__, yak_realtime()-beg_time); + + fprintf(stderr, "[M::%s::%.3f] ==> HiC index has been built\n", __func__, yak_realtime()-index_time); + + uint64_t i; + for (i = 0; i < idx->tot; i++) + { + kv_destroy(pl.cnt[i].a); + kv_destroy(pl.buf[i].a); + } + free(pl.cnt); free(pl.buf); + + return idx; +} + +void destory_hc_pt_index(ha_ug_index* idx) +{ + if(idx->idx_buf) + { + uint64_t i = 0; + for (i = 0; i < idx->tot; i++) + { + if(idx->idx_buf[i].a) free(idx->idx_buf[i].a); + if(idx->idx_buf[i].h) hc_pt_destroy(idx->idx_buf[i].h); + } + free(idx->idx_buf); + } +} + +inline void interpret_pos(const ha_ug_index* idx, s_hit *p, uint64_t* rev, uint64_t* uID, +uint64_t* ref_p, uint64_t* self_p, uint64_t* exact_len, uint64_t* total_len) +{ + (*rev) = p->ref>>63; + (*uID) = (p->ref << 1) >> (64 - idx->uID_bits); + (*self_p) = (uint32_t)p->off_cnt; + ///(*exact_len) = p->off_cnt >> 32; + (*exact_len) = (p->off_cnt>>32) & ((uint64_t)65535); + if(total_len != NULL) + { + ///(*exact_len) = (p->off_cnt>>32) & ((uint64_t)65535); + (*total_len) = (p->off_cnt>>48) + (*exact_len); + } + if((p->ref & idx->pos_mode)>>(idx->pos_bits - 1)) + { + (*ref_p) = (*self_p) - (p->ref&(idx->pos_mode>>1)); + } + else + { + (*ref_p) = (*self_p) + (p->ref&(idx->pos_mode)); + } +} + + +inline uint64_t check_exact_match(char* a, long long a_beg, long long a_total, char* b, long long b_beg, +long long b_total, long long Len, uint64_t rev, uint64_t dir) +{ + long long i = 0; + if(rev == 0) + { + if(dir == 0) + { + for (i = 0; i < Len && a_beg < a_total && b_beg < b_total; i++) + { + if(a[a_beg++] != b[b_beg++]) return i; + } + } + else + { + for (i = 0; i < Len && a_beg >= 0 && b_beg >= 0; i++) + { + if(a[a_beg--] != b[b_beg--]) return i; + } + } + } + else + { + + if(dir == 0) + { + for (i = 0; i < Len && a_beg < a_total && b_beg < b_total; i++) + { + if(a[a_beg] != b2rc[seq_nt4_table[(uint8_t)b[b_total - b_beg - 1]]]) return i; + a_beg++; b_beg++; + } + } + else + { + for (i = 0; i < Len && a_beg >= 0 && b_beg >= 0; i++) + { + if(a[a_beg] != b2rc[seq_nt4_table[(uint8_t)b[b_total - b_beg - 1]]]) return i; + a_beg--; b_beg--; + } + } + } + + return i; +} + +uint64_t debug_hash_value(char *r, uint64_t end, uint64_t k_mer) +{ + uint64_t i; + uint64_t x[4], mask = (1ULL<>1)) & mask; + x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; + x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; + } + } + + return hc_hash_long(x, &skip, k_mer); + +} + +inline uint64_t collect_votes(s_hit* a, uint64_t n) +{ + if(n == 0) return 0; + if(n == 1) return (a[0].off_cnt>>32); //seed length, is right + long long i = 0; + uint64_t cur_beg, cur_end, beg, end, ovlp = 0, tLen = 0; + cur_end = (uint32_t)a[n-1].off_cnt; + cur_beg = cur_end + 1 - (a[n-1].off_cnt>>32); + + if(n >= 2) + { + for (i = n - 2; i >= 0; i--) + { + end = (uint32_t)a[i].off_cnt; + beg = end + 1 - (a[i].off_cnt>>32); + if(MAX(cur_beg, beg) <= MIN(cur_end, end)) + { + cur_beg = MIN(cur_beg, beg); + ///cur_end = MAX(cur_end, end); + } + else + { + ovlp += (cur_end + 1 - cur_beg); + cur_beg = beg; + cur_end = end; + } + } + } + + ovlp += (cur_end + 1 - cur_beg); + tLen = (uint32_t)a[n-1].off_cnt + 1 - cur_beg; + tLen = tLen - ovlp; + tLen = tLen << 16; + return ovlp | tLen; +} + +inline void compress_mapped_pos(const ha_ug_index* idx, kvec_vote* buf, uint64_t buf_iter, uint64_t max_i, uint64_t thres) +{ + if(buf_iter >= buf->a.n) + { + buf->a.n = buf_iter; + return; + } + uint64_t rev, uID, ref_p, self_p, eLen, tLen, i, max_beg, max_end, cur_beg, cur_end, ovlp, max_eLen; + uint64_t secondLen = 0, second_i = (uint64_t)-1; + interpret_pos((ha_ug_index*)idx, &buf->a.a[max_i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + max_end = self_p; + max_beg = self_p + 1 - tLen; + max_eLen = eLen; + for (i = buf_iter; i < buf->a.n; i++) + { + if(i == max_i) continue; + interpret_pos(idx, &buf->a.a[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + cur_end = self_p; + cur_beg = self_p + 1 - tLen; + if(MAX(cur_beg, max_beg) <= MIN(cur_end, max_end)) + { + ovlp = MIN(cur_end, max_end) - MAX(cur_beg, max_beg) + 1; + if(ovlp > thres) + { + if(eLen >= max_eLen * 0.8) + { + buf->a.n = buf_iter; + return; + } + continue; + } + } + if(secondLen < eLen) secondLen = eLen, second_i = i; + } + + if(second_i == (uint64_t)-1) + { + buf->a.a[buf_iter] = buf->a.a[max_i]; + buf->a.n = buf_iter + 1; + } + else + { + buf->a.a[buf_iter] = buf->a.a[MIN(max_i, second_i)]; + buf->a.a[buf_iter+1] = buf->a.a[MAX(max_i, second_i)]; + buf->a.n = buf_iter + 2; + } +} + +inline void print_pos_list(const ha_ug_index* idx, s_hit *l, uint64_t occ, uint64_t rid, uint64_t r1) +{ + if(rid == 33045391 || rid == 4239289 || rid == 5267597 || rid == 34474764 || rid == 35016489 + || rid == 36002255 || rid == 37811694 || rid == 46805824) + { + uint64_t i, rev, uID, ref_p, self_p, cnt; + for (i = 0; i < occ; i++) + { + interpret_pos(idx, &l[i], &rev, &uID, &ref_p, &self_p, &cnt, NULL); + fprintf(stderr, "(r%lu) rid: %lu, i: %lu, rev: %lu, uID: %lu, ref_p: %lu, self_p: %lu\n", + r1, rid, i, rev, uID, ref_p, self_p); + } + + } +} + +uint64_t get_longest_hit(char *r, uint64_t len, uint64_t k_mer, uint64_t self_p, uint64_t self_rev, kvec_vote* buf, const ha_ug_index* idx, +uint64_t *pos_list, uint64_t cnt, uint64_t* c_sfx) +{ + uint64_t max_p, map_p_occ, i, j, m, rev, ref_p, u_len, uID, k_len; + s_hit *p = NULL; + ///each k-mer at different unitigs + ///rev:uID:pos + if(c_sfx) (*c_sfx) = (uint64_t)-1; + for (j = 0; j < cnt; j++) + { + ///get + kv_pushp(s_hit, buf->a, &p); + rev = (pos_list[j]>>63) != self_rev; + ref_p = pos_list[j] & idx->pos_mode; + uID = (pos_list[j] << 1) >> (64 - idx->uID_bits); + u_len = idx->ug->u.a[uID].len; + if(rev) ref_p = u_len - 1 - (ref_p + 1 - k_mer); + p->off_cnt = self_p | ((uint64_t)k_mer << 32); ///high bits should be the legnth + + p->ref = ref_p >= self_p? (ref_p-self_p) + : (self_p-ref_p) + ((uint64_t)1 << (idx->pos_bits - 1)); + p->ref = (rev << 63)|(pos_list[j] & idx->uID_mode)|(p->ref&idx->pos_mode); + + + ///extend + k_len = check_exact_match(r, self_p + 1, len, idx->ug->u.a[uID].s, ref_p + 1, u_len, len, rev, 0); + if(c_sfx && cnt == idx->hap_cnt && k_len < (*c_sfx)) (*c_sfx) = k_len; + + p->off_cnt += ((uint64_t)k_len << 32) + k_len; + + if(self_p >= k_mer && ref_p >= k_mer) + { + k_len = check_exact_match(r, self_p - k_mer, len, idx->ug->u.a[uID].s, + ref_p - k_mer, u_len, len, rev, 1); + p->off_cnt += ((uint64_t)k_len << 32); + } + // if(cnt > 0) fprintf(stderr, "inner j: %lu, rev: %lu, uID: %lu, ref_p: %lu, self_p: %u, len: %lu\n", j, rev, uID, ref_p, (uint32_t)p->off_cnt, p->off_cnt>>32); + } + + p = buf->a.a + buf->a.n - cnt; + if(cnt > 1) radix_sort_hc_s_hit_off_cnt(p, p + cnt); + max_p = map_p_occ = 0; + for (j = 1, i = 0; j <= cnt; ++j) + { + if(j == cnt || p[j].off_cnt != p[i].off_cnt) + { + if((max_p>>32) < (p[i].off_cnt>>32)) + { + max_p = p[i].off_cnt; + map_p_occ = j - i; + } + else if(((max_p>>32) == (p[i].off_cnt>>32)) && ((j - i) > map_p_occ)) + { + max_p = p[i].off_cnt; + map_p_occ = j - i; + } + i = j;///must + } + } + + buf->a.n -= cnt; + for (j = m = 0; j < cnt; j++) + { + if(p[j].off_cnt == max_p) + { + p[m] = p[j]; + m++; + } + } + cnt = m; + buf->a.n += cnt; + + // if(cnt > 0) fprintf(stderr, "max_p_offset: %u, max_p_len: %lu, map_p_occ: %lu\n", (uint32_t)max_p, max_p>>32, map_p_occ); + return max_p; +} + +#define is_update_hit(mL, mR, cL, cR) (((mL)<(cL))||((mL)==(cL)&&(mR)<(cR))) +inline void compress_mapped_pos_advance(const ha_ug_index* idx, kvec_vote* buf, uint64_t buf_iter, uint64_t ovlp_thre) +{ + if(buf_iter >= buf->a.n) + { + buf->a.n = buf_iter; + return; + } + s_hit *p = NULL; + uint64_t rev, uID, ref_p, self_p, eLen, tLen, i, j, cnt; + uint64_t max_beg = 0, max_end = 0, max_i, max_occ, cur_beg, cur_end, ovlp; + uint64_t second_i = (uint64_t)-1, second_occ; + uint64_t max_eLen, sec_eLen; + double max_eRate, sec_eRate, eRate; + p = buf->a.a + buf_iter; + cnt = buf->a.n - buf_iter; + if(cnt > 1) radix_sort_hc_s_hit_off_cnt(p, p + cnt); ///buf save all hits, here sort by offset in reads + max_eLen = 0; max_i = (uint64_t)-1; max_occ = 0; max_eRate = -1; + for (j = 1, i = 0; j <= cnt; ++j) + { + if(j == cnt || p[j].off_cnt != p[i].off_cnt) + { + ///occ = j - i; + interpret_pos((ha_ug_index*)idx, &p[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + eRate = (double)(eLen)/(double)(tLen); + if(is_update_hit(max_eLen, max_eRate, eLen, eRate)) + { + max_eLen = eLen; max_eRate = eRate; + max_end = self_p; max_beg = self_p + 1 - tLen; + max_i = i; max_occ = j - i; + } + // fprintf(stderr, "\n++++++[%lu, %lu] uID: %lu, ref_p: %lu, self_p: %lu, eLen: %lu, tLen: %lu, max_i: %lu\n", + // i, j, uID, ref_p, self_p, eLen, tLen, max_i); + i = j;///must + } + } + + + sec_eLen = 0; second_i = (uint64_t)-1; second_occ = 0; sec_eRate = -1; + for (j = 1, i = 0; j <= cnt; ++j) + { + if(j == cnt || p[j].off_cnt != p[i].off_cnt) + { + if(i != max_i) + { + interpret_pos((ha_ug_index*)idx, &p[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + eRate = (double)(eLen)/(double)(tLen); + cur_end = self_p; + cur_beg = self_p + 1 - tLen; + // fprintf(stderr, "\n----[%lu, %lu] uID: %lu, ref_p: %lu, self_p: %lu, eLen: %lu, tLen: %lu, max_i: %lu\n", + // i, j, uID, ref_p, self_p, eLen, tLen, max_i); + // fprintf(stderr, "max_beg: %lu, max_end: %lu, cur_beg: %lu, cur_end: %lu\n", + // max_beg, max_end, cur_beg, cur_end); + ///overlap with max interval + if(MAX(cur_beg, max_beg) <= MIN(cur_end, max_end)) + { + ovlp = MIN(cur_end, max_end) - MAX(cur_beg, max_beg) + 1; + /*******************************for debug************************************/ + if(ovlp == MIN(max_end+1-max_end, tLen))///for non-unique k-mer + { + i = j;///must + continue;///fully contain + } + if(ovlp > ((max_end+1-max_end)*0.8) && eLen > (max_eLen*0.8))///best is not unique + { + buf->a.n = buf_iter; + return; + } + if(ovlp > ((max_end+1-max_end)*0.15) + 1) + { + i = j;///must + continue;///fully contain + } + + // if(ovlp > (MIN((max_end+1-max_end), (cur_end+1-cur_end))*0.15) + 1) + // { + // if(eLen > (max_eLen*0.8))///best is not unique + // { + // buf->a.n = buf_iter; + // return; + // } + // i = j;///must + // continue; + // } + /*******************************for debug************************************/ + } + + if(is_update_hit(sec_eLen, sec_eRate, eLen, eRate)) + { + sec_eLen = eLen; sec_eRate = eRate; + second_i = i; second_occ = j - i; + } + } + i = j;///must + } + } + + // fprintf(stderr, "max_i: %lu, max_occ: %lu, second_i: %lu, second_occ: %lu\n", + // max_i, max_occ, second_i, second_occ); + + if(second_i == (uint64_t)-1) + { + i = 0; + for (j = max_i; j < max_i + max_occ; j++, i++) p[i] = p[j]; + } + else ///be carful about overwritten + { + i = 0; + if(max_i <= second_i) + { + for (j = max_i; j < max_i + max_occ; j++, i++) p[i] = p[j]; + for (j = second_i; j < second_i + second_occ; j++, i++) p[i] = p[j]; + } + else + { + for (j = second_i; j < second_i + second_occ; j++, i++) p[i] = p[j]; + for (j = max_i; j < max_i + max_occ; j++, i++) p[i] = p[j]; + } + } + + buf->a.n = buf_iter + max_occ + second_occ; +} + +void get_alignment(char *r, uint64_t len, uint64_t k_mer, kvec_vote* buf, const ha_ug_index* idx, uint64_t buf_iter, uint64_t rid) +{ + uint64_t i, j, k, l = 0, k_len, c_sfx, m, skip, *pos_list = NULL, cnt, rev, self_p, ref_p, uID; + uint64_t x[4], mask = (1ULL<a.n = 0; + for (i = l = 0, x[0] = x[1] = x[2] = x[3] = 0; i < len; ++i) { + int c = seq_nt4_table[(uint8_t)r[i]]; + ///c = 00, 01, 10, 11 + if (c < 4) { // not an "N" base + ///x[0] & x[1] are the forward k-mer + ///x[2] & x[3] are the reverse complementary k-mer + x[0] = (x[0] << 1 | (c&1)) & mask; + x[1] = (x[1] << 1 | (c>>1)) & mask; + x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; + x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; + if (++l >= k_mer) + { + hash = hc_hash_long(x, &skip, k_mer); + if(skip == (uint64_t)-1) continue; + cnt = get_hc_pt1_count((ha_ug_index*)idx, hash, &pos_list); + if(cnt > idx->hap_cnt || cnt <= 0) continue; + + if(cnt > 1) + { + for (j = 0; j < cnt; j++) + { + uID = (pos_list[j] << 1) >> (64 - idx->uID_bits); + for (k = j + 1; k < cnt; k++) + { + if(uID == ((pos_list[k] << 1) >> (64 - idx->uID_bits))) break; + } + if(k < cnt) break; + } + + if(j < cnt) continue; + } + // if(cnt > 0) fprintf(stderr, "+i: %lu, l: %lu, cnt: %lu\n", i, l, cnt); + get_longest_hit(r, len, k_mer, i, skip, buf, idx, pos_list, cnt, &c_sfx); + // if(cnt > 0) fprintf(stderr, "c_sfx: %lu\n", c_sfx); + if(c_sfx != (uint64_t)-1) + { + k_len = c_sfx; + if((k_len + 1) >= k_mer) + { + l = 0, x[0] = x[1] = x[2] = x[3] = 0; + i = i + k_len - (k_mer - 1); + } + else + { + ///l = i - (i + k_len - (k_mer - 1)); + l = k_mer - k_len - 1; + } + } + // if(cnt > 0) fprintf(stderr, "-i: %lu, l: %lu\n", i, l); + } + + } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; // if there is an "N", restart + } + + if(buf->a.n - buf_iter == 0) return; + if(buf->a.n - buf_iter > 1) radix_sort_hc_s_hit_an1(buf->a.a + buf_iter, buf->a.a + buf->a.n); + + + uint64_t cur_ref_p, thres = (len * HIC_R_E_RATE) + 1, index_beg, ovlp; + i = m = buf_iter; + while (i < buf->a.n) + { + interpret_pos(idx, &buf->a.a[i], &rev, &uID, &ref_p, &self_p, &cnt, NULL); + ///fprintf(stderr, "after-i: %lu, uID: %lu, ref_p: %lu, self_p: %lu\n", i, uID, ref_p, self_p); + cur_ref_p = buf->a.a[i].ref; + index_beg = i; + ///ref>>(idx->pos_bits-1) = (rev:1):(uID:uID-bits):(ref_pos>=self_pos:1) + while ((i < buf->a.n) && + ((buf->a.a[i].ref>>(idx->pos_bits-1)) == (cur_ref_p>>(idx->pos_bits-1))) && + (buf->a.a[i].ref - cur_ref_p <= thres)) + { + i++; + } + if(i - index_beg > 1) + { + radix_sort_hc_s_hit_an2(buf->a.a + index_beg, buf->a.a + i);//sort by self_p + } + ovlp = collect_votes(buf->a.a + index_beg, i - index_beg); + ///fprintf(stderr, "i-1: %lu, self_p: %u\n", i-1, (uint32_t)buf->a.a[i - 1].off_cnt); + buf->a.a[m] = buf->a.a[i - 1]; + buf->a.a[m].off_cnt = (buf->a.a[m].off_cnt << 32)>>32; + buf->a.a[m].off_cnt += ((uint64_t)ovlp<<32); + ///fprintf(stderr, "m: %lu, self_p: %u\n", m, (uint32_t)buf->a.a[m].off_cnt); + m++; + } + buf->a.n = m; + + /*******************************for debug************************************/ + // for (i = buf_iter; i < buf->a.n; i++) + // { + // uint64_t eLen, tLen; + // interpret_pos(idx, &buf->a.a[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + // if(maxLen < eLen) fprintf(stderr, "ERROR1\n"); + // if(i == max_i && maxLen != eLen) fprintf(stderr, "ERROR2\n"); + // } + /*******************************for debug************************************/ + ///select the best alignment at [buf_iter, m) + + /*******************************for debug************************************/ + // fprintf(stderr, "len1:%lu, max_i: %lu\n", buf->a.n - buf_iter, max_i); + // for (i = buf_iter; i < buf->a.n; i++) + // { + // uint64_t eLen, tLen; + // interpret_pos(idx, &buf->a.a[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + // fprintf(stderr, "(%lu) rev: %lu, uID: %lu, ref_p: %lu, self_p: %lu, eLen: %lu, tLen: %lu\n", + // i, rev, uID, ref_p, self_p, eLen, tLen); + // } + /*******************************for debug************************************/ + compress_mapped_pos_advance(idx, buf, buf_iter, (k_mer * 0.1) > 0? (k_mer * 0.1) : 1); + /*******************************for debug************************************/ + // fprintf(stderr, "len2:%lu, max_i: %lu\n", buf->a.n - buf_iter, max_i); + // for (i = buf_iter; i < buf->a.n; i++) + // { + // uint64_t eLen, tLen; + // interpret_pos(idx, &buf->a.a[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + // fprintf(stderr, "(%lu) rev: %lu, uID: %lu, ref_p: %lu, self_p: %lu, eLen: %lu, tLen: %lu\n", + // i, rev, uID, ref_p, self_p, eLen, tLen); + // } + // if(buf->a.n != m) fprintf(stderr, "Changed\n"); + // fprintf(stderr, "\n"); + /*******************************for debug************************************/ +} + +inline void compress_mapped_pos_debug(const ha_ug_index* idx, kvec_vote* buf, uint64_t buf_iter, uint64_t max_i, uint64_t thres) +{ + if(buf_iter >= buf->a.n) + { + buf->a.n = buf_iter; + return; + } + uint64_t rev, uID, ref_p, self_p, eLen, tLen, i, max_beg, max_end, cur_beg, cur_end, ovlp, max_eLen; + uint64_t secondLen = 0, second_i = (uint64_t)-1; + interpret_pos((ha_ug_index*)idx, &buf->a.a[max_i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + max_end = self_p; + max_beg = self_p + 1 - tLen; + max_eLen = eLen; + for (i = buf_iter; i < buf->a.n; i++) + { + if(i == max_i) continue; + interpret_pos(idx, &buf->a.a[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + cur_end = self_p; + cur_beg = self_p + 1 - tLen; + if(MAX(cur_beg, max_beg) <= MIN(cur_end, max_end)) + { + ovlp = MIN(cur_end, max_end) - MAX(cur_beg, max_beg) + 1; + if(ovlp > thres) + { + if(eLen >= max_eLen * 0.8) + { + buf->a.n = buf_iter; + return; + } + continue; + } + } + if(secondLen < eLen) secondLen = eLen, second_i = i; + } + + if(second_i == (uint64_t)-1) + { + buf->a.a[buf_iter] = buf->a.a[max_i]; + buf->a.n = buf_iter + 1; + } + else + { + buf->a.a[buf_iter] = buf->a.a[MIN(max_i, second_i)]; + buf->a.a[buf_iter+1] = buf->a.a[MAX(max_i, second_i)]; + buf->a.n = buf_iter + 2; + } +} + +void get_alignment_debug(char *r, uint64_t len, uint64_t k_mer, kvec_vote* buf, const ha_ug_index* idx, uint64_t buf_iter, uint64_t rid) +{ + uint64_t i, j, l = 0, m, skip, *pos_list = NULL, cnt, rev, self_p, ref_p, uID; + uint64_t x[4], mask = (1ULL<a.n = 0; + uint64_t k_len, c_sfx, k; + for (i = l = 0, x[0] = x[1] = x[2] = x[3] = 0; i < len; ++i) { + int c = seq_nt4_table[(uint8_t)r[i]]; + ///c = 00, 01, 10, 11 + if (c < 4) { // not an "N" base + ///x[0] & x[1] are the forward k-mer + ///x[2] & x[3] are the reverse complementary k-mer + x[0] = (x[0] << 1 | (c&1)) & mask; + x[1] = (x[1] << 1 | (c>>1)) & mask; + x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; + x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; + if (++l >= k_mer) + { + hash = hc_hash_long(x, &skip, k_mer); + if(skip == (uint64_t)-1) continue; + cnt = get_hc_pt1_count((ha_ug_index*)idx, hash, &pos_list); + if(cnt > idx->hap_cnt || cnt <= 0) continue; + + if(cnt > 1) + { + for (j = 0; j < cnt; j++) + { + uID = (pos_list[j] << 1) >> (64 - idx->uID_bits); + for (k = j + 1; k < cnt; k++) + { + if(uID == ((pos_list[k] << 1) >> (64 - idx->uID_bits))) break; + } + if(k < cnt) break; + } + + if(j < cnt) continue; + } + // if(cnt > 0) fprintf(stderr, "+i: %lu, l: %lu, cnt: %lu\n", i, l, cnt); + get_longest_hit(r, len, k_mer, i, skip, buf, idx, pos_list, cnt, &c_sfx); + // if(cnt > 0) fprintf(stderr, "c_sfx: %lu\n", c_sfx); + if(c_sfx != (uint64_t)-1) + { + k_len = c_sfx; + if((k_len + 1) >= k_mer) + { + l = 0, x[0] = x[1] = x[2] = x[3] = 0; + i = i + k_len - (k_mer - 1); + } + else + { + ///l = i - (i + k_len - (k_mer - 1)); + l = k_mer - k_len - 1; + } + } + // if(cnt > 0) fprintf(stderr, "-i: %lu, l: %lu\n", i, l); + } + + } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; // if there is an "N", restart + } + **/ + + s_hit *p = NULL; uint64_t u_len; + ///buf->a.n = 0; + for (i = l = 0, x[0] = x[1] = x[2] = x[3] = 0; i < len; ++i) { + int c = seq_nt4_table[(uint8_t)r[i]]; + ///c = 00, 01, 10, 11 + if (c < 4) { // not an "N" base + ///x[0] & x[1] are the forward k-mer + ///x[2] & x[3] are the reverse complementary k-mer + x[0] = (x[0] << 1 | (c&1)) & mask; + x[1] = (x[1] << 1 | (c>>1)) & mask; + x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; + x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; + if (++l >= k_mer) + { + hash = hc_hash_long(x, &skip, k_mer); + if(skip == (uint64_t)-1) continue; + /*******************************for debug************************************/ + // if(debug_hash_value(r, i, k_mer) != hash) + // { + // fprintf(stderr, "ERROR\n"); + // } + /*******************************for debug************************************/ + cnt = get_hc_pt1_count((ha_ug_index*)idx, hash, &pos_list); + if(cnt > idx->hap_cnt) continue; + if(cnt != 1) continue; ///might be able to be disabled in future + + + for (j = 0; j < cnt; j++) + { + kv_pushp(s_hit, buf->a, &p); + rev = (pos_list[j]>>63) != skip; + self_p = i; + ref_p = pos_list[j] & idx->pos_mode; + uID = (pos_list[j] << 1) >> (64 - idx->uID_bits); + u_len = idx->ug->u.a[uID].len; + if(rev) ref_p = u_len - 1 - (ref_p + 1 - k_mer); + p->off_cnt = self_p | ((uint64_t)k_mer << 32); ///high bits should be the legnth + + p->ref = ref_p >= self_p? (ref_p-self_p) + : (self_p-ref_p) + ((uint64_t)1 << (idx->pos_bits - 1)); + p->ref = (rev << 63)|(pos_list[j] & idx->uID_mode)|(p->ref&idx->pos_mode); + + + /*******************************for debug************************************/ + // if(check_exact_match(r, i + 1 - k_mer, len, + // idx->ug->u.a[uID].s, ref_p + 1 - k_mer, u_len, k_mer, rev, 0) != k_mer + // || + // check_exact_match(r, i, len, + // idx->ug->u.a[uID].s, ref_p, u_len, k_mer, rev, 1) != k_mer) + // { + // fprintf(stderr, "ERROR\n"); + // } + /*******************************for debug************************************/ + } + + if(cnt == 1) + { + ///uint64_t debug_right = 0, debug_left = 0, debug_len; + + j = check_exact_match(r, self_p + 1, len, idx->ug->u.a[uID].s, ref_p + 1, u_len, len, rev, 0); + + ///debug_right = j; + ///if(j == 0) continue; + if((j + 1) >= k_mer) + { + l = 0, x[0] = x[1] = x[2] = x[3] = 0; + i = i + j - (k_mer - 1); + } + else + { + ///l = i - (i + j - (k_mer - 1)); + l = k_mer - j -1; + } + buf->a.a[buf->a.n-1].off_cnt += ((uint64_t)j << 32) + j; + + if(self_p >= k_mer && ref_p >= k_mer) + { + j = check_exact_match(r, self_p - k_mer, len, idx->ug->u.a[uID].s, + ref_p - k_mer, u_len, len, rev, 1); + buf->a.a[buf->a.n-1].off_cnt += ((uint64_t)j << 32); + ///debug_left = j; + } + + + // debug_len = check_exact_match(r, self_p + debug_right, len, idx->ug->u.a[uID].s, + // ref_p + debug_right, u_len, len, rev, 1); + // if(debug_len!= (debug_left + debug_right + k_mer)) + // { + // fprintf(stderr, "debug_len: %lu, debug_left: %lu, debug_right: %lu\n", + // debug_len, debug_left, debug_right); + // } + } + + } + + } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; // if there is an "N", restart + } + /****************************may have bugs********************************/ + + if(buf->a.n - buf_iter == 0) return; + if(buf->a.n - buf_iter > 1) radix_sort_hc_s_hit_an1(buf->a.a + buf_iter, buf->a.a + buf->a.n); + + + uint64_t cur_ref_p, thres = (len * HIC_R_E_RATE) + 1, index_beg, ovlp; + /****************************may have bugs********************************/ + uint64_t maxLen = 0, max_i = (uint64_t)-1; + /****************************may have bugs********************************/ + i = m = buf_iter; + while (i < buf->a.n) + { + interpret_pos(idx, &buf->a.a[i], &rev, &uID, &ref_p, &self_p, &cnt, NULL); + cur_ref_p = buf->a.a[i].ref; + index_beg = i; + while ((i < buf->a.n) && + ((buf->a.a[i].ref>>(idx->pos_bits-1)) == (cur_ref_p>>(idx->pos_bits-1))) && + (buf->a.a[i].ref - cur_ref_p <= thres)) + { + i++; + } + if(i - index_beg > 1) + { + radix_sort_hc_s_hit_an2(buf->a.a + index_beg, buf->a.a + i);//sort by self_p + } + ovlp = collect_votes(buf->a.a + index_beg, i - index_beg); + buf->a.a[m] = buf->a.a[i - 1]; + buf->a.a[m].off_cnt = (buf->a.a[m].off_cnt << 32)>>32; + buf->a.a[m].off_cnt += ((uint64_t)ovlp<<32); + m++; + /****************************may have bugs********************************/ + if(maxLen < (ovlp&((uint64_t)65535))) maxLen = (ovlp&((uint64_t)65535)), max_i = m; + /****************************may have bugs********************************/ + } + buf->a.n = m; + /****************************may have bugs********************************/ + ///compress_mapped_pos_advance(idx, buf, buf_iter, (k_mer * 0.1) > 0? (k_mer * 0.1) : 1); + compress_mapped_pos_debug(idx, buf, buf_iter, max_i, thres); + /****************************may have bugs********************************/ +} + +inline int is_unreliable_hits(long long rev, long long ref_p, long long tLen, uint64_t uID, trans_chain* t_ch) +{ + uint64_t i; + long long p_beg, p_end; + bed_in* p = NULL; + if(rev) + { + p_end = ref_p; + p_beg = p_end + 1 - tLen; + } + else + { + p_beg = ref_p; + p_end = p_beg + tLen - 1; + } + if(p_beg < 0) p_beg = 0; + if(p_end < 0) p_end = 0; + + p = &(t_ch->bed.a[uID]); + for (i = 0; i < p->n; i++) + { + if(inter_interval(p_beg, p_end, p->a[i].beg, p->a[i].end, NULL, NULL)) break; + } + if(p->n > 0 && i < p->n) return 1; + + return 0; +} + + +void get_5_3_list(ha_ug_index* idx, s_hit* p, uint64_t cnt, s_hit** l5, uint64_t* l5_occ, +s_hit** l3, uint64_t* l3_occ) +{ + (*l5) = (*l3) = NULL; + (*l5_occ) = (*l3_occ) = 0; + uint64_t i, j, rev, uID, ref_p, self_p, eLen, tLen, cur_beg, num; + uint64_t beg_5 = (uint64_t)-1; + for (j = 1, i = 0, num = 0; j <= cnt; ++j) + { + if(j == cnt || p[j].off_cnt != p[i].off_cnt) + { + interpret_pos((ha_ug_index*)idx, &p[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + ///cur_end = self_p; + cur_beg = self_p + 1 - tLen; + num++; + if(cur_beg <= beg_5) + { + (*l3_occ) = (*l5_occ); (*l3) = (*l5); + beg_5 = cur_beg; (*l5_occ) = j - i; (*l5) = p + i; + } + else + { + (*l3_occ) = j - i; (*l3) = p + i; + } + i = j;///must + } + } + + ///if(num > 2) fprintf(stderr, "ERROR: get_5_3_list\n"); +} + +inline void set_pe_pos_hap(ha_ug_index* idx, s_hit *l1, uint64_t occ1, s_hit *l2, uint64_t occ2, +pe_hit_hap* x, uint64_t rid, trans_chain *t_ch) +{ + if(occ1 == 0 || occ2 == 0) return; + uint64_t rev, uID, ref_p, self_p, eLen, tLen, i, is_unreliable = 0; + s_hit *l1_5 = NULL, *l1_3 = NULL, *l2_5 = NULL, *l2_3 = NULL; + uint64_t l1_5_occ = 0, l1_3_occ = 0, l2_5_occ = 0, l2_3_occ = 0; + + /***************************for debug******************************/ + // fprintf(stderr, "\nrid: %lu, occ1: %lu, occ2: %lu\n", rid, occ1, occ2); + // for (i = 0; i < occ1; i++) + // { + // interpret_pos(idx, &l1[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + // fprintf(stderr, "***-1-rev: %lu, uID: %lu, ref_p: %lu, self_p: %lu\n", + // rev, uID, ref_p, self_p); + // } + + // for (i = 0; i < occ2; i++) + // { + // interpret_pos(idx, &l2[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + // fprintf(stderr, "***-2-rev: %lu, uID: %lu, ref_p: %lu, self_p: %lu\n", + // rev, uID, ref_p, self_p); + // } + /***************************for debug******************************/ + + + get_5_3_list(idx, l1, occ1, &l1_5, &l1_5_occ, &l1_3, &l1_3_occ); + get_5_3_list(idx, l2, occ2, &l2_5, &l2_5_occ, &l2_3, &l2_3_occ); + if(l1_5_occ == 0 || l2_5_occ == 0) return; + x->id = rid; + MALLOC(x->a, l1_5_occ + l2_5_occ); + + x->occ1 = 0; + for (i = 0; i < l1_5_occ; i++) + { + interpret_pos(idx, &l1_5[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + if(ref_p < self_p) continue; + ref_p -= self_p; + if(rev) ref_p = idx->ug->u.a[uID].len - 1 - ref_p; + if(t_ch && (is_unreliable_hits(rev, ref_p, tLen, uID, t_ch))) + { + is_unreliable = 1; + continue; + } + x->a[x->occ1++] = (rev<<63) | ((uID << (64-idx->uID_bits))>>1) | (ref_p & idx->pos_mode); + } + + x->occ2 = x->occ1; + for (i = 0; i < l2_5_occ; i++) + { + interpret_pos(idx, &l2_5[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + if(ref_p < self_p) continue; + ref_p -= self_p; + if(rev) ref_p = idx->ug->u.a[uID].len - 1 - ref_p; + if(t_ch && (is_unreliable_hits(rev, ref_p, tLen, uID, t_ch))) + { + is_unreliable = 1; + continue; + } + x->a[x->occ2++] = (rev<<63) | ((uID << (64-idx->uID_bits))>>1) | (ref_p & idx->pos_mode); + } + x->occ2 -= x->occ1; + + if(x->occ1 == 0 || x->occ2 == 0 || is_unreliable) + { + free(x->a); x->occ1 = x->occ2 = 0; x->a = NULL; x->id = (uint64_t)-1; + return; + } + + + if(x->occ1 > 1) radix_sort_hc64(x->a, x->a + x->occ1); + if(x->occ2 > 1) radix_sort_hc64(x->a + x->occ1, x->a + x->occ1 + x->occ2); + + + /***************************for debug******************************/ + // fprintf(stderr, "-------------saved: x->occ1: %u, x->occ2: %u-------------\n", x->occ1, x->occ2); + // for (i = 0; i < x->occ1; i++) + // { + // fprintf(stderr, "###-1-rev: %lu, uID: %lu, ref_p: %lu\n", + // x->a[i]>>63, (x->a[i]<<1)>>(64-idx->uID_bits), x->a[i] & idx->pos_mode); + // } + + // for (i = 0; i < x->occ2; i++) + // { + // fprintf(stderr, "###-2-rev: %lu, uID: %lu, ref_p: %lu\n", + // x->a[i+x->occ1]>>63, (x->a[i+x->occ1]<<1)>>(64-idx->uID_bits), x->a[i+x->occ1] & idx->pos_mode); + // } + // fprintf(stderr, "-------------get_pe_s-rev: %lu, uID: %lu, ref_p: %lu-------------\n", + // get_pe_s(*x)>>63, (get_pe_s(*x)<<1)>>(64-idx->uID_bits), get_pe_s(*x) & idx->pos_mode); + // fprintf(stderr, "-------------get_pe_e-rev: %lu, uID: %lu, ref_p: %lu-------------\n", + // get_pe_e(*x)>>63, (get_pe_e(*x)<<1)>>(64-idx->uID_bits), get_pe_e(*x) & idx->pos_mode); + /***************************for debug******************************/ +} + +inline void set_pe_pos(ha_ug_index* idx, s_hit *l1, uint64_t occ1, s_hit *l2, uint64_t occ2, +pe_hit* x, uint64_t rid, trans_chain* t_ch) +{ + if(occ1 == 0 || occ2 == 0) return; + uint64_t rev, uID, ref_p, self_p, eLen, tLen, i, is_unreliable = 0; + s_hit *l1_5 = NULL, *l1_3 = NULL, *l2_5 = NULL, *l2_3 = NULL; + uint64_t l1_5_occ = 0, l1_3_occ = 0, l2_5_occ = 0, l2_3_occ = 0; + + /***************************for debug******************************/ + // fprintf(stderr, "\nrid: %lu, occ1: %lu, occ2: %lu\n", rid, occ1, occ2); + // for (i = 0; i < occ1; i++) + // { + // interpret_pos(idx, &l1[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + // fprintf(stderr, "***-1-rev: %lu, uID: %lu, ref_p: %lu, self_p: %lu\n", + // rev, uID, ref_p, self_p); + // } + + // for (i = 0; i < occ2; i++) + // { + // interpret_pos(idx, &l2[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + // fprintf(stderr, "***-2-rev: %lu, uID: %lu, ref_p: %lu, self_p: %lu\n", + // rev, uID, ref_p, self_p); + // } + /***************************for debug******************************/ + + + get_5_3_list(idx, l1, occ1, &l1_5, &l1_5_occ, &l1_3, &l1_3_occ); + get_5_3_list(idx, l2, occ2, &l2_5, &l2_5_occ, &l2_3, &l2_3_occ); + if(l1_5_occ == 0 || l2_5_occ == 0) return; + x->id = rid; x->len = 0; + + ///if(l1_5_occ != 1 || l2_5_occ != 1) fprintf(stderr, "ERROR\n"); + + for (i = 0; i < l1_5_occ; i++) + { + interpret_pos(idx, &l1_5[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + if((ref_p + 1) < tLen) continue; + ref_p = ref_p + 1 - tLen; + if(rev) ref_p = idx->ug->u.a[uID].len - 1 - ref_p; + + if(t_ch && (is_unreliable_hits(rev, ref_p, tLen, uID, t_ch))) + { + is_unreliable = 1; + continue; + } + x->s = (rev<<63) | ((uID << (64-idx->uID_bits))>>1) | (ref_p & idx->pos_mode); + x->len = tLen; x->len <<= 32; + } + + for (i = 0; i < l2_5_occ; i++) + { + interpret_pos(idx, &l2_5[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + if((ref_p + 1) < tLen) continue; + ref_p = ref_p + 1 - tLen; + if(rev) ref_p = idx->ug->u.a[uID].len - 1 - ref_p; + + if(t_ch && (is_unreliable_hits(rev, ref_p, tLen, uID, t_ch))) + { + is_unreliable = 1; + continue; + } + x->e = (rev<<63) | ((uID << (64-idx->uID_bits))>>1) | (ref_p & idx->pos_mode); + x->len |= tLen; + } + + if(is_unreliable || x->s == (uint64_t)-1 || x->e == (uint64_t)-1) + { + x->id = x->s = x->e = x->len = (uint64_t)-1; + return; + } + + + /****************************may have bugs********************************/ + // for (i = 0; i < l1_3_occ; i++) + // { + // interpret_pos(idx, &l1_3[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + // if(uID != ((x->s << 1) >> (64 - idx->uID_bits)) && + // uID != ((x->e << 1) >> (64 - idx->uID_bits))) + // { + // x->id = x->s = x->e = x->len = (uint64_t)-1; + // return; + // } + // } + + // for (i = 0; i < l2_3_occ; i++) + // { + // interpret_pos(idx, &l2_3[i], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + // if(uID != ((x->s << 1) >> (64 - idx->uID_bits)) && + // uID != ((x->e << 1) >> (64 - idx->uID_bits))) + // { + // x->id = x->s = x->e = x->len = (uint64_t)-1; + // return; + // } + // } + /****************************may have bugs********************************/ + + + + + /***************************for debug******************************/ + // fprintf(stderr, "-------------saved: x->occ1: %u, x->occ2: %u-------------\n", x->occ1, x->occ2); + // for (i = 0; i < x->occ1; i++) + // { + // fprintf(stderr, "###-1-rev: %lu, uID: %lu, ref_p: %lu\n", + // x->a[i]>>63, (x->a[i]<<1)>>(64-idx->uID_bits), x->a[i] & idx->pos_mode); + // } + + // for (i = 0; i < x->occ2; i++) + // { + // fprintf(stderr, "###-2-rev: %lu, uID: %lu, ref_p: %lu\n", + // x->a[i+x->occ1]>>63, (x->a[i+x->occ1]<<1)>>(64-idx->uID_bits), x->a[i+x->occ1] & idx->pos_mode); + // } + // fprintf(stderr, "-------------get_pe_s-rev: %lu, uID: %lu, ref_p: %lu-------------\n", + // get_pe_s(*x)>>63, (get_pe_s(*x)<<1)>>(64-idx->uID_bits), get_pe_s(*x) & idx->pos_mode); + // fprintf(stderr, "-------------get_pe_e-rev: %lu, uID: %lu, ref_p: %lu-------------\n", + // get_pe_e(*x)>>63, (get_pe_e(*x)<<1)>>(64-idx->uID_bits), get_pe_e(*x) & idx->pos_mode); + /***************************for debug******************************/ +} + + +uint64_t if_debug_read(uint64_t rid) +{ + if(rid == 1169718 || rid == 2665829 || rid == 4239289) + { + return 1; + } + return 0; +} + +static void worker_for_alignment(void *data, long i, int tid) // callback for kt_for() +{ + stepdat_t *s = (stepdat_t*)data; + ///s->pos[i].id = (uint64_t)-1; s->pos[i].occ1 = s->pos[i].occ2 = 0; s->pos[i].a = NULL; + s->pos[i].id = s->pos[i].s = s->pos[i].e = s->pos[i].len = (uint64_t)-1; + + /*******************************for debug************************************/ + // if(!if_debug_read(s->id+i)) return; + // fprintf(stderr, "work-rid: %lu\n", (uint64_t)(s->id+i)); + /*******************************for debug************************************/ + + uint64_t len1 = s->len[i]>>32, len2 = (uint32_t)s->len[i], occ1, occ2; + char *r1 = s->seq[i], *r2 = s->seq[i] + len1; + + + // fprintf(stderr, "**********R1**********\n"); + s->pos_buf[tid].a.n = 0; + get_alignment(r1, len1, s->idx->k, &s->pos_buf[tid], s->idx, 0, s->id+i); + occ1 = s->pos_buf[tid].a.n; + if(occ1 == 0) return; + + + // fprintf(stderr, "**********R2**********\n"); + get_alignment(r2, len2, s->idx->k, &s->pos_buf[tid], s->idx, occ1, s->id+i); + occ2 = s->pos_buf[tid].a.n - occ1; + if(occ2 == 0) return; + + set_pe_pos((ha_ug_index*)s->idx, s->pos_buf[tid].a.a, occ1, s->pos_buf[tid].a.a + occ1, occ2, &(s->pos[i]), s->id+i, s->t_ch); + + /*******************************for debug************************************/ + // if(memcmp(r1, R1.r.a + R1.r_Len.a[s->id+i], len1) != 0) + // { + // fprintf(stderr, "haha1\n"); + // } + // if(memcmp(r2, R2.r.a + R2.r_Len.a[s->id+i], len2) != 0) + // { + // fprintf(stderr, "haha2\n"); + // } + // uint64_t j, rev, uID, ref_p, self_p, eLen, tLen; + // char dir[2] = {'+', '-'}; + // fprintf(stderr, "(R1) %.*s\n", (int)(R1.name_Len.a[s->id + i + 1] - R1.name_Len.a[s->id+i]), + // R1.name.a + R1.name_Len.a[s->id+i]); + // for (j = 0; j < occ1; j++) + // { + // interpret_pos(s->idx, &s->pos_buf[tid].a.a[j], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + // fprintf(stderr, "utg%.6lu\t%c\t%lu\t%lu-%lu\n", uID+1, dir[rev], ref_p, self_p + 1 - tLen, self_p); + // } + // fprintf(stderr, "(R2) %.*s\n", (int)(R2.name_Len.a[s->id + i + 1] - R2.name_Len.a[s->id+i]), + // R2.name.a + R2.name_Len.a[s->id+i]); + // for (j = 0; j < occ2; j++) + // { + // interpret_pos(s->idx, &s->pos_buf[tid].a.a[j+occ1], &rev, &uID, &ref_p, &self_p, &eLen, &tLen); + // fprintf(stderr, "utg%.6lu\t%c\t%lu\t%lu-%lu\n", uID+1, dir[rev], ref_p, self_p + 1 - tLen, self_p); + // } + // fprintf(stderr, "\n"); + /*******************************for debug************************************/ +} + +static void *worker_pipeline(void *data, int step, void *in) // callback for kt_pipeline() +{ + sldat_t *p = (sldat_t*)data; + ///uint64_t total_base = 0, total_pair = 0; + if (step == 0) { // step 1: read a block of sequences + int ret1, ret2; + uint64_t l1, l2; + stepdat_t *s; + CALLOC(s, 1); + s->idx = p->idx; s->id = p->total_pair; s->t_ch = p->t_ch; + while (((ret1 = kseq_read(p->ks1)) >= 0)&&((ret2 = kseq_read(p->ks2)) >= 0)) + { + if (p->ks1->seq.l < p->idx->k || p->ks2->seq.l < p->idx->k) continue; + if (s->n == s->m) { + s->m = s->m < 16? 16 : s->m + (s->n>>1); + REALLOC(s->len, s->m); + REALLOC(s->seq, s->m); + } + + l1 = p->ks1->seq.l; l2 = p->ks2->seq.l; + MALLOC(s->seq[s->n], l1+l2); + s->sum_len += l1+l2; + memcpy(s->seq[s->n], p->ks1->seq.s, l1); + memcpy(s->seq[s->n]+l1, p->ks2->seq.s, l2); + s->len[s->n++] = (uint64_t)(l1<<32)|(uint64_t)l2; + + if (s->sum_len >= p->chunk_size) break; + } + p->total_pair += s->n; + if (s->sum_len == 0) free(s); + else return s; + } + else if (step == 1) { // step 2: alignment + stepdat_t *s = (stepdat_t*)in; + CALLOC(s->pos_buf, p->n_thread); + CALLOC(s->pos, s->n); + int i; + kt_for(p->n_thread, worker_for_alignment, s, s->n); + for (i = 0; i < s->n; ++i) { + free(s->seq[i]); + p->total_base += (s->len[i]>>32) + (uint32_t)s->len[i]; + } + + free(s->seq); free(s->len); + for (i = 0; i < (int)p->n_thread; ++i) { + free(s->pos_buf[i].a.a); + } + free(s->pos_buf); + return s; + } + else if (step == 2) { // step 3: dump + stepdat_t *s = (stepdat_t*)in; + int i; + for (i = 0; i < s->n; ++i) { + // if(s->pos[i].a == NULL) continue; + // kv_push(pe_hit_hap, p->hits, s->pos[i]); + if(s->pos[i].s == (uint64_t)-1) continue; + kv_push(pe_hit, p->hits.a, s->pos[i]); + } + free(s->pos); + free(s); + } + return 0; +} + + +int load_reads(reads_t* x, const enzyme *fn1, const enzyme *fn2) +{ + kv_init(x->name); + kv_init(x->name_Len); + kv_init(x->r); + kv_init(x->r_Len); + + int ret; + uint64_t name_tot, base_total; + int i; + name_tot = base_total = 0; + + for (i = 0; i < fn1->n && i < fn2->n; i++) + { + gzFile fp; + if ((fp = gzopen(fn1->a[i], "r")) == 0) + { + kv_destroy(x->name); + kv_destroy(x->name_Len); + kv_destroy(x->r); + kv_destroy(x->r_Len); + return 0; + } + + kseq_t *ks; + ks = kseq_init(fp); + + while (((ret = kseq_read(ks)) >= 0)) + { + kv_push(uint64_t, x->name_Len, name_tot); + kv_resize(char, x->name, name_tot + ks->name.l); + memcpy(x->name.a + name_tot, ks->name.s, ks->name.l); + name_tot += ks->name.l; + + kv_push(uint64_t, x->r_Len, base_total); + kv_resize(char, x->r, base_total + ks->seq.l); + memcpy(x->r.a + base_total, ks->seq.s, ks->seq.l); + base_total += ks->seq.l; + } + + kseq_destroy(ks); + gzclose(fp); + } + kv_push(uint64_t, x->name_Len, name_tot); + kv_push(uint64_t, x->r_Len, base_total); + x->idx = 0; + return 1; +} + + +void test_reads(reads_t* x, const char *fn) +{ + gzFile fp; + kseq_t *ks; + int ret, i = 0; + + if ((fp = gzopen(fn, "r")) == 0) return; + ks = kseq_init(fp); + while (((ret = kseq_read(ks)) >= 0)) + { + if(memcmp(ks->name.s, x->name.a + x->name_Len.a[i], ks->name.l) != 0) + { + fprintf(stderr, "ERROR222: i: %d, len: %lu\n", i, x->name_Len.a[i]); + } + i++; + } + + kseq_destroy(ks); + gzclose(fp); +} + +void destory_reads(reads_t* x) +{ + kv_destroy(x->name); + kv_destroy(x->name_Len); + kv_destroy(x->r); + kv_destroy(x->r_Len); +} + +void print_hits(ha_ug_index* idx, kvec_pe_hit* hits, const enzyme *fn1, const enzyme *fn2) +{ + uint64_t k, shif = 64 - idx->uID_bits; + reads_t r1; + load_reads(&r1, fn1, fn2); + char dir[2] = {'+', '-'}; + for (k = 0; k < hits->a.n; ++k) + { + fprintf(stderr, "%.*s\t%c\ts-utg%.6dl\t%lu\t%c\te-utg%.6dl\t%lu\ti:%lu\n", + (int)(r1.name_Len.a[hits->a.a[k].id + 1] - r1.name_Len.a[hits->a.a[k].id]), + r1.name.a + r1.name_Len.a[hits->a.a[k].id], + dir[hits->a.a[k].s>>63], (int)((hits->a.a[k].s<<1)>>shif)+1, hits->a.a[k].s&idx->pos_mode, + dir[hits->a.a[k].e>>63], (int)((hits->a.a[k].e<<1)>>shif)+1, hits->a.a[k].e&idx->pos_mode, + hits->a.a[k].id); + } + destory_reads(&r1); +} + +void print_hits_simp(ha_ug_index* idx, kvec_pe_hit* hits) +{ + uint64_t k, shif = 64 - idx->uID_bits; + char dir[2] = {'+', '-'}; + for (k = 0; k < hits->a.n; ++k) + { + if(((hits->a.a[k].s<<1)>>shif) == ((hits->a.a[k].e<<1)>>shif)) continue; + fprintf(stderr, "r-%lu-th\t%c\trs-utg%.6dl\t%lu\t%c\tre-utg%.6dl\t%lu\n", + hits->a.a[k].id, + dir[hits->a.a[k].s>>63], (int)((hits->a.a[k].s<<1)>>shif)+1, hits->a.a[k].s&idx->pos_mode, + dir[hits->a.a[k].e>>63], (int)((hits->a.a[k].e<<1)>>shif)+1, hits->a.a[k].e&idx->pos_mode); + } +} + +inline void swap_pe_hit_hap(pe_hit_hap* x, pe_hit_hap* y) +{ + pe_hit_hap tmp; + tmp = (*x); (*x) = (*y); (*y) = tmp; +} + +void dedup_hits(kvec_pe_hit* hits, uint64_t is_dup) +{ + double index_time = yak_realtime(); + uint64_t k, l, m = 0, cur; + radix_sort_pe_hit_an1(hits->a.a, hits->a.a + hits->a.n); + for (k = 1, l = 0; k <= hits->a.n; ++k) + { + if (k == hits->a.n || hits->a.a[k].s != hits->a.a[l].s) + { + if (k - l > 1) radix_sort_pe_hit_an2(hits->a.a + l, hits->a.a + k); + if(is_dup) + { + cur = (uint64_t)-1; + while (l < k) + { + if(hits->a.a[l].e != cur) + { + cur = hits->a.a[l].e; + hits->a.a[m++] = hits->a.a[l]; + } + l++; + } + } + l = k; + } + } + if(is_dup) hits->a.n = m; + fprintf(stderr, "[M::%s::%.3f] ==> Dedup\n", __func__, yak_realtime()-index_time); +} + +void sort_hits(kvec_pe_hit* hits) +{ + double index_time = yak_realtime(); + uint64_t k, l; + radix_sort_pe_hit_an1(hits->a.a, hits->a.a + hits->a.n); + for (k = 1, l = 0; k <= hits->a.n; ++k) + { + if (k == hits->a.n || (hits->a.a[k].s<<1) != (hits->a.a[l].s<<1)) + { + if (k - l > 1) radix_sort_pe_hit_an2(hits->a.a + l, hits->a.a + k); + l = k; + } + } + fprintf(stderr, "[M::%s::%.3f] ==> Sort\n", __func__, yak_realtime()-index_time); +} + +void destory_bubbles(bubble_type* bub) +{ + if(bub->index) free(bub->index); + kv_destroy(bub->list); + kv_destroy(bub->num); + kv_destroy(bub->pathLen); + kv_destroy(bub->b_s_idx); + kv_destroy(bub->chain_weight); + asg_destroy(bub->b_g); + ma_ug_destroy(bub->b_ug); +} + +void get_bubbles(bubble_type* bub, uint64_t id, uint32_t* beg, uint32_t* sink, uint32_t** a, uint32_t* n, uint64_t* pathBase) +{ + if(a) (*a) = bub->list.a + bub->num.a[id] + 2; + if(n) (*n) = bub->num.a[id+1] - bub->num.a[id] - 2; + if(beg) (*beg) = bub->list.a[bub->num.a[id]]; + if(sink) (*sink) = bub->list.a[bub->num.a[id] + 1]; + if(pathBase) (*pathBase) = bub->pathLen.a[id]; +} + +void dfs_bubble_broken(asg_t *g, kvec_t_u32_warp* stack, kvec_t_u32_warp* result, uint8_t* vis_flag, +uint32_t vis_flag_n, uint32_t v_d, uint32_t beg_d, uint32_t sink_d) +{ + memset(vis_flag, 0, vis_flag_n); + asg_arc_t *acur = NULL; + uint32_t cur, ncur, i, p_beg = (uint32_t)-1, p_sink = (uint32_t)-1, v; + stack->a.n = result->a.n = 0; + v = v_d; + if(v != (beg_d^1) && v != (sink_d^1)) kv_push(uint32_t, stack->a, v); + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + vis_flag[cur] = 1; + if((v>>1) != (cur>>1)) kv_push(uint32_t, result->a, cur>>1); + ncur = asg_arc_n(g, cur); + acur = asg_arc_a(g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if(vis_flag[acur[i].v]) continue; + if((acur[i].v>>1) == (beg_d>>1) || (acur[i].v>>1) == (sink_d>>1)) + { + if((acur[i].v>>1) == (beg_d>>1)) p_beg = acur[i].v; + if((acur[i].v>>1) == (sink_d>>1)) p_sink = acur[i].v; + continue; + } + kv_push(uint32_t, stack->a, acur[i].v); + } + } + + memset(vis_flag, 0, vis_flag_n); + v ^= 1; + if(v != (beg_d^1) && v != (sink_d^1)) kv_push(uint32_t, stack->a, v); + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + vis_flag[cur] = 1; + if((v>>1) != (cur>>1)) kv_push(uint32_t, result->a, cur>>1); + ncur = asg_arc_n(g, cur); + acur = asg_arc_a(g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if(vis_flag[acur[i].v]) continue; + if((acur[i].v>>1) == (beg_d>>1) || (acur[i].v>>1) == (sink_d>>1)) + { + if((acur[i].v>>1) == (beg_d>>1)) p_beg = acur[i].v; + if((acur[i].v>>1) == (sink_d>>1)) p_sink = acur[i].v; + continue; + } + kv_push(uint32_t, stack->a, acur[i].v); + } + } + + if(p_beg != (uint32_t)-1) kv_push(uint32_t, result->a, beg_d>>1); + if(p_sink != (uint32_t)-1) kv_push(uint32_t, result->a, sink_d>>1); +} + +void dfs_bubble(asg_t *g, kvec_t_u32_warp* stack, kvec_t_u32_warp* result, uint32_t v, uint32_t beg, uint32_t sink) +{ + asg_arc_t *acur = NULL; + uint32_t cur, ncur, i; + stack->a.n = result->a.n = 0; + v = v << 1; + kv_push(uint32_t, stack->a, v); + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + if((v>>1) != (cur>>1)) kv_push(uint32_t, result->a, cur>>1); + ncur = asg_arc_n(g, cur); + acur = asg_arc_a(g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if((acur[i].v>>1) == beg || (acur[i].v>>1) == sink) continue; + kv_push(uint32_t, stack->a, acur[i].v); + } + } + + + v = v + 1; + kv_push(uint32_t, stack->a, v); + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + if((v>>1) != (cur>>1)) kv_push(uint32_t, result->a, cur>>1); + ncur = asg_arc_n(g, cur); + acur = asg_arc_a(g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if((acur[i].v>>1) == beg || (acur[i].v>>1) == sink) continue; + kv_push(uint32_t, stack->a, acur[i].v); + } + } +} + +uint32_t get_unitig_het_arb(ma_ug_t* ug, uint32_t uid, uint8_t *r_het_flag, kv_u_trans_t *ref, uint32_t m_het_occ, +uint32_t m_het_label, uint32_t p_het_label, uint32_t n_het_label) +{ + if(ref && ref->idx.n > 0 && u_trans_n(*ref, uid) > 0) return m_het_label; + ma_utg_t *u = &(ug->u.a[uid]); + uint32_t k, rId; + uint32_t het_occ, hom_occ; + for (k = 0, het_occ = hom_occ = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + if((r_het_flag[rId] & P_HET)) return m_het_label; + if((r_het_flag[rId] & C_HET) || (r_het_flag[rId] & P_HET)) + { + het_occ++; + } + else + { + hom_occ++; + } + } + + if((het_occ+hom_occ) == 0) return n_het_label; ///hom + if((het_occ > ((het_occ+hom_occ)*0.8)) && ((het_occ+hom_occ) > m_het_occ)) return m_het_label; ///must het + if(het_occ >= hom_occ) return p_het_label; ///potential het + return n_het_label; ///hom +} +void update_bub_b_s_idx(bubble_type* bub); +void identify_bubbles(ma_ug_t* ug, bubble_type* bub, uint8_t *r_het_flag, kv_u_trans_t *ref) +{ + asg_cleanup(ug->g); + if (!ug->g->is_symm) asg_symm(ug->g); + uint32_t v, n_vtx = ug->g->n_seq * 2, i, k, mode = (((uint32_t)-1)<<2); + uint32_t beg, sink, n, *a, n_occ; + uint64_t pathLen; + bub->ug = ug; + bub->b_bub = bub->b_end_bub = bub->tangle_bub = bub->cross_bub = bub->mess_bub = 0; + if(bub->round_id == 0) + { + buf_t b; memset(&b, 0, sizeof(buf_t)); b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + uint64_t tLen = get_bub_pop_max_dist_advance(ug->g, &b); + kv_init(bub->list); kv_init(bub->num); kv_init(bub->pathLen); + kv_init(bub->b_s_idx); kv_malloc(bub->b_s_idx, ug->g->n_seq); + bub->b_ug = NULL; kv_init(bub->chain_weight); + bub->b_s_idx.n = ug->g->n_seq; + memset(bub->b_s_idx.a, -1, bub->b_s_idx.n * sizeof(uint64_t)); + CALLOC(bub->index, n_vtx); + for (i = 0; i < ug->g->n_seq; i++) ug->g->seq[i].c = 0; + for (v = 0; v < n_vtx; ++v) + { + if(ug->g->seq[v>>1].del) continue; + if(asg_arc_n(ug->g, v) < 2) continue; + if((bub->index[v]&(uint32_t)3) != 0) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) + { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (i = 0; i < b.b.n; i++) + { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + bub->index[b.b.a[i]] &= mode; bub->index[b.b.a[i]] += 1; + bub->index[b.b.a[i]^1] &= mode; bub->index[b.b.a[i]^1] += 1; + } + bub->index[v] &= mode; bub->index[v] += 2; + bub->index[b.S.a[0]^1] &= mode; bub->index[b.S.a[0]^1] += 3; + } + } + + kvec_t_u32_warp stack, result; + kv_init(stack.a); kv_init(result.a); + for (v = 0; v < n_vtx; ++v) + { + if((bub->index[v]&(uint32_t)3) !=2) continue; + if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, &pathLen, NULL, NULL, 0, 0, NULL)) + { + //note b.b include end, does not include beg + i = b.b.n + 1; + if(b.b.n == 2 || b.b.n == 3 || b.b.n == 5) + { + for (i = 0; i < b.b.n; i++) + { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + dfs_bubble(ug->g, &stack, &result, b.b.a[i]>>1, v>>1, b.S.a[0]>>1); + if((result.a.n + 3) != b.b.n && (result.a.n + 2) != b.b.n) break; + } + } + + if(i == b.b.n) + { + kv_push(uint32_t, bub->num, v); + } + else + { + kv_push(uint32_t, bub->num, v + (1<<31)); + } + } + } + kv_destroy(stack.a); kv_destroy(result.a); + radix_sort_u32(bub->num.a, bub->num.a + bub->num.n); + bub->s_bub = 0; + for (k = 0; k < bub->num.n; k++) + { + if((bub->num.a[k]>>31) == 0) bub->s_bub++; + v = (bub->num.a[k]<<1)>>1; + bub->num.a[k] = bub->list.n; + if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, &pathLen, NULL, NULL, 0, 0, NULL)) + { + kv_push(uint64_t, bub->pathLen, pathLen); + //beg is v, end is b.S.a[0] + kv_push(uint32_t, bub->list, v); + kv_push(uint32_t, bub->list, b.S.a[0]^1); + + //note b.b include end, does not include beg + for (i = 0; i < b.b.n; i++) + { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + kv_push(uint32_t, bub->list, b.b.a[i]); + } + } + } + kv_push(uint32_t, bub->num, bub->list.n); + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + bub->f_bub = bub->num.n - 1; ///bub->s_bub = bub->num.n - 1; + + for (i = 0; i < ug->g->n_seq; i++) + { + bub->index[i] = get_unitig_het_arb(ug, i, r_het_flag, ref, 20, M_het(*bub), P_het(*bub), (uint32_t)-1); + } + for (i = 0; i < bub->f_bub; i++) + { + get_bubbles(bub, i, &beg, &sink, &a, &n, &pathLen); + for (v = n_occ = 0; v < n; v++) + { + bub->index[(a[v]>>1)] = i; + n_occ += ug->u.a[a[v]>>1].n; + } + + // if((pathLen*2) >= ug->g->seq[beg>>1].len && (pathLen*2) >= ug->g->seq[sink>>1].len) + // { + // bub->index[(beg>>1)] = (uint32_t)-1; + // bub->index[(sink>>1)] = (uint32_t)-1; + // } + + if(n_occ > 3) + { + if(bub->index[(beg>>1)] != M_het(*bub)) bub->index[(beg>>1)] = (uint32_t)-1; + if(bub->index[(sink>>1)] != M_het(*bub)) bub->index[(sink>>1)] = (uint32_t)-1; + } + + + v = beg>>1; + if(bub->b_s_idx.a[v] == (uint64_t)-1) + { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } + else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) + { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } + + + v = sink>>1; + if(bub->b_s_idx.a[v] == (uint64_t)-1) + { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } + else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) + { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } + } + for (i = 0; i < ug->g->n_seq; i++) + { + if(bub->index[i] == M_het(*bub)) bub->index[i] = P_het(*bub); + } + } + else + { + bub->num.n = bub->f_bub + 1; + bub->pathLen.n = bub->f_bub; + bub->list.n = bub->num.a[bub->num.n-1]; + update_bub_b_s_idx(bub); + bub->check_het = 0; + asg_destroy(bub->b_g); bub->b_g = NULL; + ma_ug_destroy(bub->b_ug); bub->b_ug = NULL; + kv_destroy(bub->chain_weight); kv_init(bub->chain_weight); + } + bub->b_g = NULL; + bub->b_ug = NULL; + build_bub_graph(ug, bub); + // fprintf(stderr, "-bub->index[18759]: %u, bub->num.n: %u\n", (uint32_t)bub->index[18759], bub->num.n); +} + +uint32_t get_unitig_het_fly(ma_ug_t* ug, uint32_t uid, asg_t* sg, /**int64_t het_cov_thres,**/ +int64_t m_het_cov_thres, int64_t m_hom_cov_thres, +ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag, uint32_t m_het_occ, uint32_t m_het_label, +uint32_t p_het_label, uint32_t n_het_label) +{ + ma_utg_t *u = &(ug->u.a[uid]); + uint32_t k, i, j, rId, nv, tn, is_Unitig; + asg_arc_t *av = NULL; ma_hit_t *h; + int64_t R_bases = 0, C_bases = 0, cov; + + ///set + u = &(ug->u.a[uid]); + for (k = 0; k < u->n; k++) { + rId = u->a[k]>>33; + r_flag[rId] = 1; + } + for (i = 0; i < 2; i++) { + nv = asg_arc_n(ug->g, (uid<<1)+i); + av = asg_arc_a(ug->g, (uid<<1)+i); + for (j = 0; j < nv; j++) { + u = &(ug->u.a[av[j].v>>1]); + for (k = 0; k < u->n; k++) { + rId = u->a[k]>>33; + r_flag[rId] = 2; + } + } + } + + u = &(ug->u.a[uid]); + for (k = 0; k < u->n; k++) { + if(u->a[k] == (uint64_t)-1) continue; + rId = u->a[k]>>33; + R_bases += sg->seq[rId].len; + for (j = 0; j < (uint64_t)(sources[rId].length); j++) { + h = &(sources[rId].buffer[j]); + if(h->el != 1) continue; + tn = Get_tn((*h)); + if(sg->seq[tn].del == 1) { + ///get the id of read that contains it + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || sg->seq[tn].del == 1) continue; + } + if(sg->seq[tn].del == 1) continue; + if(r_flag[tn] == 0) continue; + if(r_flag[tn] == 1) { + C_bases += (Get_qe((*h)) - Get_qs((*h))); + } + if(r_flag[tn] == 2) { + C_bases += ((Get_qe((*h)) - Get_qs((*h)))/2); + } + } + } + + ///reset + u = &(ug->u.a[uid]); + for (k = 0; k < u->n; k++) { + rId = u->a[k]>>33; + r_flag[rId] = 0; + } + for (i = 0; i < 2; i++) { + nv = asg_arc_n(ug->g, (uid<<1)+i); + av = asg_arc_a(ug->g, (uid<<1)+i); + for (j = 0; j < nv; j++) { + u = &(ug->u.a[av[j].v>>1]); + for (k = 0; k < u->n; k++) { + rId = u->a[k]>>33; + r_flag[rId] = 0; + } + } + } + + u = &(ug->u.a[uid]); cov = 0; + if(R_bases > 0) cov = C_bases/R_bases; + // if(uid == 9253) { + // fprintf(stderr, "[M::%s::uid->%u] u->n::%u, C_bases::%ld, R_bases::%ld, het_cov_thres::%ld, m_het_occ::%u\n", + // __func__, uid, (uint32_t)u->n, C_bases, R_bases, het_cov_thres, m_het_occ); + // } + // if((cov <= (het_cov_thres*1.333333)) && (u->n >= m_het_occ)) return m_het_label; ///must het + // if((cov >= (het_cov_thres*1.6))) return n_het_label; ///hom + if((cov <= m_het_cov_thres) && (u->n >= m_het_occ)) return m_het_label; ///must het + if(cov >= m_hom_cov_thres) return n_het_label; ///hom + return p_het_label; ///potential het +} + +void identify_bubbles_recal(asg_t* sg, ma_ug_t* ug, bubble_type* bub, uint8_t *r_het_flag, ma_hit_t_alloc* sources, R_to_U* ruIndex, +kv_u_trans_t *ref) +{ + asg_cleanup(ug->g); + if (!ug->g->is_symm) asg_symm(ug->g); + uint32_t v, n_vtx = ug->g->n_seq * 2, i, k, mode = (((uint32_t)-1)<<2); + uint32_t beg, sink, n, *a, n_occ; + uint64_t pathLen, hom_cov, het_cov, m_het_cov, m_hom_cov; + bub->ug = ug; + bub->b_bub = bub->b_end_bub = bub->tangle_bub = bub->cross_bub = bub->mess_bub = 0; + + if(asm_opt.hom_global_coverage_set) { + hom_cov = asm_opt.hom_global_coverage; + } else { + hom_cov = ((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE); + } + het_cov = hom_cov/asm_opt.polyploidy; + m_het_cov = hom_cov - het_cov + (het_cov*0.333333); + m_hom_cov = hom_cov - het_cov + (het_cov*0.6); + // fprintf(stderr, "hom_cov::%lu, het_cov::%lu, m_het_cov::%lu, m_hom_cov::%lu\n", hom_cov, het_cov, m_het_cov, m_hom_cov); + + if(bub->round_id == 0) + { + buf_t b; memset(&b, 0, sizeof(buf_t)); b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + uint64_t tLen = get_bub_pop_max_dist_advance(ug->g, &b); + kv_init(bub->list); kv_init(bub->num); kv_init(bub->pathLen); + kv_init(bub->b_s_idx); kv_malloc(bub->b_s_idx, ug->g->n_seq); + bub->b_ug = NULL; kv_init(bub->chain_weight); + bub->b_s_idx.n = ug->g->n_seq; + memset(bub->b_s_idx.a, -1, bub->b_s_idx.n * sizeof(uint64_t)); + CALLOC(bub->index, n_vtx); + for (i = 0; i < ug->g->n_seq; i++) ug->g->seq[i].c = 0; + for (v = 0; v < n_vtx; ++v) + { + if(ug->g->seq[v>>1].del) continue; + if(asg_arc_n(ug->g, v) < 2) continue; + if((bub->index[v]&(uint32_t)3) != 0) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) + { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (i = 0; i < b.b.n; i++) + { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + bub->index[b.b.a[i]] &= mode; bub->index[b.b.a[i]] += 1; + bub->index[b.b.a[i]^1] &= mode; bub->index[b.b.a[i]^1] += 1; + } + bub->index[v] &= mode; bub->index[v] += 2; + bub->index[b.S.a[0]^1] &= mode; bub->index[b.S.a[0]^1] += 3; + } + } + + kvec_t_u32_warp stack, result; + kv_init(stack.a); kv_init(result.a); + for (v = 0; v < n_vtx; ++v) + { + if((bub->index[v]&(uint32_t)3) !=2) continue; + if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, &pathLen, NULL, NULL, 0, 0, NULL)) + { + //note b.b include end, does not include beg + i = b.b.n + 1; + if(b.b.n == 2 || b.b.n == 3 || b.b.n == 5) + { + for (i = 0; i < b.b.n; i++) + { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + dfs_bubble(ug->g, &stack, &result, b.b.a[i]>>1, v>>1, b.S.a[0]>>1); + if((result.a.n + 3) != b.b.n && (result.a.n + 2) != b.b.n) break; + } + } + + if(i == b.b.n) + { + kv_push(uint32_t, bub->num, v); + } + else + { + kv_push(uint32_t, bub->num, v + (1<<31)); + } + } + } + kv_destroy(stack.a); kv_destroy(result.a); + radix_sort_u32(bub->num.a, bub->num.a + bub->num.n); + bub->s_bub = 0; + for (k = 0; k < bub->num.n; k++) + { + if((bub->num.a[k]>>31) == 0) bub->s_bub++; + v = (bub->num.a[k]<<1)>>1; + bub->num.a[k] = bub->list.n; + if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, &pathLen, NULL, NULL, 0, 0, NULL)) + { + kv_push(uint64_t, bub->pathLen, pathLen); + //beg is v, end is b.S.a[0] + kv_push(uint32_t, bub->list, v); + kv_push(uint32_t, bub->list, b.S.a[0]^1); + + //note b.b include end, does not include beg + for (i = 0; i < b.b.n; i++) + { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + kv_push(uint32_t, bub->list, b.b.a[i]); + } + } + } + kv_push(uint32_t, bub->num, bub->list.n); + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + bub->f_bub = bub->num.n - 1; ///bub->s_bub = bub->num.n - 1; + + memset(r_het_flag, 0, sizeof((*r_het_flag))*sg->n_seq); + for (i = 0; i < ug->g->n_seq; i++) { + bub->index[i] = get_unitig_het_fly(ug, i, sg, m_het_cov, m_hom_cov, + sources, ruIndex, r_het_flag, 20, M_het(*bub), P_het(*bub), (uint32_t)-1); + } + + for (i = 0; i < bub->f_bub; i++) + { + get_bubbles(bub, i, &beg, &sink, &a, &n, &pathLen); + for (v = n_occ = 0; v < n; v++) + { + bub->index[(a[v]>>1)] = i; + n_occ += ug->u.a[a[v]>>1].n; + } + + // if((pathLen*2) >= ug->g->seq[beg>>1].len && (pathLen*2) >= ug->g->seq[sink>>1].len) + // { + // bub->index[(beg>>1)] = (uint32_t)-1; + // bub->index[(sink>>1)] = (uint32_t)-1; + // } + + if(n_occ > 3) + { + if(bub->index[(beg>>1)] != M_het(*bub)) bub->index[(beg>>1)] = (uint32_t)-1; + if(bub->index[(sink>>1)] != M_het(*bub)) bub->index[(sink>>1)] = (uint32_t)-1; + } + + + v = beg>>1; + if(bub->b_s_idx.a[v] == (uint64_t)-1) + { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } + else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) + { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } + + + v = sink>>1; + if(bub->b_s_idx.a[v] == (uint64_t)-1) + { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } + else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) + { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } + } + for (i = 0; i < ug->g->n_seq; i++) + { + if(bub->index[i] == M_het(*bub)) bub->index[i] = P_het(*bub); + } + } + else + { + bub->num.n = bub->f_bub + 1; + bub->pathLen.n = bub->f_bub; + bub->list.n = bub->num.a[bub->num.n-1]; + update_bub_b_s_idx(bub); + bub->check_het = 0; + asg_destroy(bub->b_g); bub->b_g = NULL; + ma_ug_destroy(bub->b_ug); bub->b_ug = NULL; + kv_destroy(bub->chain_weight); kv_init(bub->chain_weight); + } + bub->b_g = NULL; + bub->b_ug = NULL; + build_bub_graph(ug, bub); + // fprintf(stderr, "-bub->index[18759]: %u, bub->num.n: %u\n", (uint32_t)bub->index[18759], bub->num.n); +} + +void reset_inner_bub_het_poy(asg_t* sg, ma_ug_t* ug, bubble_type* bub, uint32_t bid, uint64_t tLen, buf_t *b, +uint64_t m_het_cov, uint64_t m_hom_cov, uint8_t *r_het_flag, ma_hit_t_alloc* sources, R_to_U* ruIndex) +{ + uint32_t beg, sink, *ba, bn, m, v, z, socc; + get_bubbles(bub, bid, &beg, &sink, &ba, &bn, NULL); + for (m = 0; m < bn; m++) { + v = ba[m]; + if(IF_HOM((v>>1), *bub)) continue; + if(ug->g->seq[v>>1].del) continue; + if(bub->index[v>>1] == (uint32_t)-1) continue; + + if(get_unitig_het_fly(ug, v>>1, sg, m_het_cov, m_hom_cov, sources, ruIndex, r_het_flag, 20, 1, 0, (uint32_t)-1) == 1) { + continue; + } + + if(asg_arc_n(ug->g, v) < 2) continue; + if(get_real_length(ug->g, v, NULL) < 2) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (z = socc = 0; z < b->b.n; z++) { + if(b->b.a[z]==v || b->b.a[z]==b->S.a[0]) continue; + socc += ug->u.a[b->b.a[z]>>1].n; + } + if((socc > 10) && (socc > (ug->u.a[v>>1].n*3))) { + bub->index[v>>1] = (uint32_t)-1; + } + } + + + v ^= 1; + if(bub->index[v>>1] == (uint32_t)-1) continue; + if(asg_arc_n(ug->g, v) < 2) continue; + if(get_real_length(ug->g, v, NULL) < 2) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (z = socc = 0; z < b->b.n; z++) { + if(b->b.a[z]==v || b->b.a[z]==b->S.a[0]) continue; + socc += ug->u.a[b->b.a[z]>>1].n; + } + if((socc > 10) && (socc > (ug->u.a[v>>1].n*3))) { + bub->index[v>>1] = (uint32_t)-1; + } + } + } +} + +uint32_t deter_unitig_het_fly(ma_ug_t* ug, uint32_t uid, asg_t* sg, int64_t het_cov_thres, +ma_hit_t_alloc* sources, R_to_U* ruIndex, uint8_t* r_flag) +{ + ma_utg_t *u = &(ug->u.a[uid]); + uint32_t k, i, j, rId, nv, tn, is_Unitig; + asg_arc_t *av = NULL; ma_hit_t *h; + int64_t R_bases = 0, C_bases = 0, cov; + + ///set + u = &(ug->u.a[uid]); + for (k = 0; k < u->n; k++) { + rId = u->a[k]>>33; + r_flag[rId] = 1; + } + for (i = 0; i < 2; i++) { + nv = asg_arc_n(ug->g, (uid<<1)+i); + av = asg_arc_a(ug->g, (uid<<1)+i); + for (j = 0; j < nv; j++) { + u = &(ug->u.a[av[j].v>>1]); + for (k = 0; k < u->n; k++) { + rId = u->a[k]>>33; + r_flag[rId] = 2; + } + } + } + + u = &(ug->u.a[uid]); + for (k = 0; k < u->n; k++) { + if(u->a[k] == (uint64_t)-1) continue; + rId = u->a[k]>>33; + R_bases += sg->seq[rId].len; + for (j = 0; j < (uint64_t)(sources[rId].length); j++) { + h = &(sources[rId].buffer[j]); + if(h->el != 1) continue; + tn = Get_tn((*h)); + if(sg->seq[tn].del == 1) { + ///get the id of read that contains it + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || sg->seq[tn].del == 1) continue; + } + if(sg->seq[tn].del == 1) continue; + if(r_flag[tn] == 0) continue; + if(r_flag[tn] == 1) { + C_bases += (Get_qe((*h)) - Get_qs((*h))); + } + if(r_flag[tn] == 2) { + C_bases += ((Get_qe((*h)) - Get_qs((*h)))/2); + } + } + } + + ///reset + u = &(ug->u.a[uid]); + for (k = 0; k < u->n; k++) { + rId = u->a[k]>>33; + r_flag[rId] = 0; + } + for (i = 0; i < 2; i++) { + nv = asg_arc_n(ug->g, (uid<<1)+i); + av = asg_arc_a(ug->g, (uid<<1)+i); + for (j = 0; j < nv; j++) { + u = &(ug->u.a[av[j].v>>1]); + for (k = 0; k < u->n; k++) { + rId = u->a[k]>>33; + r_flag[rId] = 0; + } + } + } + + u = &(ug->u.a[uid]); cov = 0; + if(R_bases > 0) cov = C_bases/R_bases; + if(cov <= het_cov_thres) return 1; + return 0; +} + +void identify_bubbles_recal_poy(asg_t* sg, ma_ug_t* ug, bubble_type* bub, uint8_t *r_het_flag, ma_hit_t_alloc* sources, R_to_U* ruIndex, +kv_u_trans_t *ref) +{ + asg_cleanup(ug->g); + if (!ug->g->is_symm) asg_symm(ug->g); + uint32_t v, n_vtx = ug->g->n_seq * 2, i, k, mode = (((uint32_t)-1)<<2); + uint32_t beg, sink, n, *a, n_occ; + uint64_t pathLen, hom_cov, het_cov, m_het_cov, m_hom_cov; + bub->ug = ug; + bub->b_bub = bub->b_end_bub = bub->tangle_bub = bub->cross_bub = bub->mess_bub = 0; + if(asm_opt.hom_global_coverage_set) { + hom_cov = asm_opt.hom_global_coverage; + } else { + hom_cov = ((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE); + } + het_cov = hom_cov/asm_opt.polyploidy; + m_het_cov = het_cov + (het_cov*0.333333);///hom_cov - het_cov + (het_cov*0.333333); + m_hom_cov = het_cov + (het_cov*0.6);///hom_cov - het_cov + (het_cov*0.6); + // fprintf(stderr, "hom_cov::%lu, het_cov::%lu, m_het_cov::%lu, m_hom_cov::%lu\n", hom_cov, het_cov, m_het_cov, m_hom_cov); + + buf_t b; memset(&b, 0, sizeof(buf_t)); b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + uint64_t tLen = get_bub_pop_max_dist_advance(ug->g, &b); + kv_init(bub->list); kv_init(bub->num); kv_init(bub->pathLen); + kv_init(bub->b_s_idx); kv_malloc(bub->b_s_idx, ug->g->n_seq); + bub->b_ug = NULL; kv_init(bub->chain_weight); + bub->b_s_idx.n = ug->g->n_seq; + memset(bub->b_s_idx.a, -1, bub->b_s_idx.n * sizeof(uint64_t)); + CALLOC(bub->index, n_vtx); + for (i = 0; i < ug->g->n_seq; i++) ug->g->seq[i].c = 0; + for (v = 0; v < n_vtx; ++v) + { + if(ug->g->seq[v>>1].del) continue; + if(asg_arc_n(ug->g, v) < 2) continue; + if((bub->index[v]&(uint32_t)3) != 0) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) + { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (i = 0; i < b.b.n; i++) + { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + bub->index[b.b.a[i]] &= mode; bub->index[b.b.a[i]] += 1; + bub->index[b.b.a[i]^1] &= mode; bub->index[b.b.a[i]^1] += 1; + } + bub->index[v] &= mode; bub->index[v] += 2; + bub->index[b.S.a[0]^1] &= mode; bub->index[b.S.a[0]^1] += 3; + } + } + + kvec_t_u32_warp stack, result; + kv_init(stack.a); kv_init(result.a); + for (v = 0; v < n_vtx; ++v) + { + if((bub->index[v]&(uint32_t)3) !=2) continue; + if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, &pathLen, NULL, NULL, 0, 0, NULL)) + { + //note b.b include end, does not include beg + i = b.b.n + 1; + if(b.b.n == 2 || b.b.n == 3 || b.b.n == 5) + { + for (i = 0; i < b.b.n; i++) + { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + dfs_bubble(ug->g, &stack, &result, b.b.a[i]>>1, v>>1, b.S.a[0]>>1); + if((result.a.n + 3) != b.b.n && (result.a.n + 2) != b.b.n) break; + } + } + + if(i == b.b.n) + { + kv_push(uint32_t, bub->num, v); + } + else + { + kv_push(uint32_t, bub->num, v + (1<<31)); + } + } + } + kv_destroy(stack.a); kv_destroy(result.a); + radix_sort_u32(bub->num.a, bub->num.a + bub->num.n); + bub->s_bub = 0; + for (k = 0; k < bub->num.n; k++) + { + if((bub->num.a[k]>>31) == 0) bub->s_bub++; + v = (bub->num.a[k]<<1)>>1; + bub->num.a[k] = bub->list.n; + if(asg_bub_pop1_primary_trio(ug->g, ug, v, tLen, &b, (uint32_t)-1, (uint32_t)-1, 0, &pathLen, NULL, NULL, 0, 0, NULL)) + { + kv_push(uint64_t, bub->pathLen, pathLen); + //beg is v, end is b.S.a[0] + kv_push(uint32_t, bub->list, v); + kv_push(uint32_t, bub->list, b.S.a[0]^1); + + //note b.b include end, does not include beg + for (i = 0; i < b.b.n; i++) + { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + kv_push(uint32_t, bub->list, b.b.a[i]); + } + } + } + kv_push(uint32_t, bub->num, bub->list.n); + // free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + bub->f_bub = bub->num.n - 1; ///bub->s_bub = bub->num.n - 1; + + + memset(r_het_flag, 0, sizeof((*r_het_flag))*sg->n_seq); + for (i = 0; i < ug->g->n_seq; i++) { + bub->index[i] = get_unitig_het_fly(ug, i, sg, m_het_cov, m_hom_cov, + sources, ruIndex, r_het_flag, 20, M_het(*bub), P_het(*bub), (uint32_t)-1); + } + + for (i = 0; i < bub->f_bub; i++) { + get_bubbles(bub, i, &beg, &sink, &a, &n, &pathLen); + for (v = n_occ = 0; v < n; v++) { + bub->index[(a[v]>>1)] = i; + n_occ += ug->u.a[a[v]>>1].n; + } + + if(n_occ > 3) { + if(bub->index[(beg>>1)] != M_het(*bub)) bub->index[(beg>>1)] = (uint32_t)-1; + if(bub->index[(sink>>1)] != M_het(*bub)) bub->index[(sink>>1)] = (uint32_t)-1; + } + + + v = beg>>1; + if(bub->b_s_idx.a[v] == (uint64_t)-1) { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } + + + v = sink>>1; + if(bub->b_s_idx.a[v] == (uint64_t)-1) { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } + } + for (i = 0; i < ug->g->n_seq; i++) { + if(bub->index[i] == M_het(*bub)) bub->index[i] = P_het(*bub); + } + + bub->b_g = NULL; + bub->b_ug = NULL; + build_bub_graph(ug, bub); + + + ///make het nodes to be hom + ma_utg_t *u = NULL; + for (i = 0; i < bub->b_ug->u.n; i++) { + u = &(bub->b_ug->u.a[i]); + if(u->n == 0) continue; + for (k = 0; k < u->n; k++) { + reset_inner_bub_het_poy(sg, ug, bub, u->a[k]>>33, tLen, &b, m_het_cov, m_hom_cov, r_het_flag, sources, ruIndex); + } + } + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + + for (i = 0; i < ug->g->n_seq; i++) { + if(IF_HOM(i, *bub)) continue; + if(deter_unitig_het_fly(ug, i, sg, het_cov*1.15, sources, ruIndex, r_het_flag)) continue; + bub->index[i] = (uint32_t)-1; + } + // fprintf(stderr, "-bub->index[18759]: %u, bub->num.n: %u\n", (uint32_t)bub->index[18759], bub->num.n); +} + +void print_bubbles(ma_ug_t* ug, bubble_type* bub, kvec_pe_hit* hits, hc_links* link, ha_ug_index* idx) +{ + uint64_t tLen, t_utg, i, k; + uint32_t beg, sink, n, *a; + for (i = 0, tLen = 0; i < bub->ug->u.n; i++) tLen += bub->ug->u.a[i].len; + fprintf(stderr, "[M::%s] # unitigs: %lu, # bases: %lu\n", __func__, bub->ug->u.n, tLen); + for (i = 0, tLen = 0, t_utg = 0; i < bub->f_bub; i++) + { + get_bubbles(bub, i, &beg, &sink, &a, &n, NULL); + t_utg += n; + for (k = 0; k < n; k++) + { + tLen +=bub->ug->u.a[(a[k]>>1)].len; + } + } + fprintf(stderr, "[M::%s] # bubbles: %lu, # unitigs: %lu, # bases: %lu\n", __func__, + Get_bub_num(*bub), t_utg, tLen); + + + for (i = 0, tLen = 0, t_utg = 0; i < ug->g->n_seq; i++) + { + if(IF_BUB(i, *bub)) + { + t_utg++; + tLen +=bub->ug->u.a[i].len; + } + } + fprintf(stderr, "[M::%s] # bubbles: %lu, # unitigs: %lu, # bases: %lu\n", __func__, + Get_bub_num(*bub), t_utg, tLen); + + for (i = 0, tLen = 0, t_utg = 0; i < ug->g->n_seq; i++) + { + if(IF_HET(i, *bub)) + { + t_utg++; + tLen +=bub->ug->u.a[i].len; + } + } + fprintf(stderr, "[M::%s] # het unitigs: %lu, # het bases: %lu\n", __func__, t_utg, tLen); + + uint8_t* flag; CALLOC(flag, ug->g->n_seq); + uint64_t s_uid, e_uid, shif = 64 - idx->uID_bits; + if(hits) + { + for (k = 0; k < hits->a.n; ++k) + { + s_uid = ((hits->a.a[k].s<<1)>>shif); + e_uid = ((hits->a.a[k].e<<1)>>shif); + if(bub->index[s_uid] == (uint32_t)-1 || bub->index[e_uid] == (uint32_t)-1) continue; + if(IF_BUB(s_uid, *bub) && IF_BUB(e_uid, *bub)) + { + flag[s_uid] |= 1; + flag[e_uid] |= 1; + continue; + } + if(IF_HET(s_uid, *bub) && IF_HET(e_uid, *bub)) + { + flag[s_uid] |= 4; + flag[e_uid] |= 4; + continue; + } + if(IF_BUB(s_uid, *bub)) flag[s_uid] |= 2, flag[e_uid] |= 2; + if(IF_BUB(e_uid, *bub)) flag[e_uid] |= 2, flag[s_uid] |= 2; + } + } + else if(link) + { + for (i = 0; i < link->a.n; i++) + { + for (k = 0; k < link->a.a[i].e.n; ++k) + { + if(link->a.a[i].e.a[k].del) continue; + s_uid = i; + e_uid = link->a.a[i].e.a[k].uID; + if(bub->index[s_uid] == (uint32_t)-1 || bub->index[e_uid] == (uint32_t)-1) continue; + if(IF_BUB(s_uid, *bub) && IF_BUB(e_uid, *bub)) + { + flag[s_uid] |= 1; + flag[e_uid] |= 1; + continue; + } + if(IF_HET(s_uid, *bub) && IF_HET(e_uid, *bub)) + { + flag[s_uid] |= 4; + flag[e_uid] |= 4; + continue; + } + if(IF_BUB(s_uid, *bub)) flag[s_uid] |= 2, flag[e_uid] |= 2; + if(IF_BUB(e_uid, *bub)) flag[e_uid] |= 2, flag[s_uid] |= 2; + } + } + } + + + + + for (i = 0, tLen = 0, t_utg = 0; i < ug->g->n_seq; i++) + { + if(flag[i] & (uint32_t)1) + { + t_utg++; + tLen +=bub->ug->u.a[i].len; + } + } + fprintf(stderr, "[M::%s] # bubble-chained unitigs: %lu, # bubble-chained bases: %lu\n", + __func__, t_utg, tLen); + + for (i = 0, tLen = 0, t_utg = 0; i < ug->g->n_seq; i++) + { + if((flag[i] & (uint32_t)1) || (flag[i] & (uint32_t)2)) + { + t_utg++; + tLen +=bub->ug->u.a[i].len; + } + } + fprintf(stderr, "[M::%s] # (bubble && het)-chained unitigs: %lu, # (bubble && het)-chained bases: %lu\n", + __func__, t_utg, tLen); + + + for (i = 0, tLen = 0, t_utg = 0; i < ug->g->n_seq; i++) + { + if((flag[i] & (uint32_t)1) || (flag[i] & (uint32_t)2) || (flag[i] & (uint32_t)4)) + { + t_utg++; + tLen +=bub->ug->u.a[i].len; + } + } + fprintf(stderr, "[M::%s] # (bubble || het)-chained unitigs: %lu, # (bubble || het)-chained bases: %lu\n", + __func__, t_utg, tLen); + free(flag); + + + fprintf(stderr, "************bubble utgs************\n"); + uint64_t pathLen; + for (i = 0, tLen = 0, t_utg = 0; i < bub->f_bub; i++) + { + get_bubbles(bub, i, &beg, &sink, &a, &n, &pathLen); + t_utg += n; + fprintf(stderr, "(full-%lu)\tbeg:utg%.6u\tsink:utg%.6u\tpathLen:%lu\t%s\n", + i, (beg>>1)+1, (sink>>1)+1, pathLen, i < bub->s_bub? "s-bub":(if_bub?"f-bub":"b-bub")); + for (k = 0; k < n; k++) + { + tLen +=bub->ug->u.a[(a[k]>>1)].len; + fprintf(stderr, "utg%.6u,", (a[k]>>1)+1); + } + fprintf(stderr, "\n"); + ///if(i < bub->s_bub && (n != 4 && n != 2 && n != 1)) fprintf(stderr, "weird\n"); + } + + for (i = bub->f_bub, tLen = 0, t_utg = 0; i < bub->f_bub + bub->b_bub; i++) + { + get_bubbles(bub, i, &beg, &sink, &a, &n, &pathLen); + t_utg += n; + fprintf(stderr, "(broken-%lu)\tbeg:utg%.6u\tsink:utg%.6u\tpathLen:%lu\t%s\n", + i, (beg>>1)+1, (sink>>1)+1, pathLen, i < bub->s_bub? "s-bub":(if_bub?"f-bub":"b-bub")); + for (k = 0; k < n; k++) + { + tLen +=bub->ug->u.a[(a[k]>>1)].len; + fprintf(stderr, "utg%.6u,", (a[k]>>1)+1); + } + fprintf(stderr, "\n"); + } + + // fprintf(stderr, "************het utgs************\n"); + // for (i = 0; i < ug->g->n_seq; i++) + // { + // if(IF_HET(i, *bub)) fprintf(stderr, "utg%.6lu\n", i+1); + // } + // fprintf(stderr, "************het utgs************\n"); +} + +hc_edge* push_hc_edge(hc_linkeage* x, uint64_t uID, double weight, int dir, uint64_t* d) +{ + uint64_t k, n; + hc_edge* a = NULL; + hc_edge* p = NULL; + if(dir == 0) + { + a = x->e.a; + n = x->e.n; + } + else + { + a = x->f.a; + n = x->f.n; + } + + for (k = 0; k < n; k++) + { + if(a[k].del) continue; + if(a[k].uID == uID) + { + a[k].weight += weight; + if(d) a[k].dis = (*d); + return &(a[k]); + } + } + + if(dir == 0) + { + kv_pushp(hc_edge, x->e, &p); + } + else + { + kv_pushp(hc_edge, x->f, &p); + } + + ///p->del = p->enzyme = 0; + p->del = 0; + p->uID = uID; + p->weight = weight; + if(d) p->dis = (*d); + return p; +} + +long long get_enzyme_occ_debug(char* t, long long tlen, char* p, long long plen) +{ + long long s = 0, j, occ = 0; + while(s <= (tlen - plen)) + { + j = plen-1; + + while(j >= 0) + { + if(seq_nt4_table[(uint8_t)t[s+j]] >= 4) break; + if((p[j] != t[s+j]) && seq_nt4_table[(uint8_t)p[j]] < 4) break; + j--; + } + + if (j < 0) occ++; + s++; + } + + return occ; +} + +int check_exact_match(char* x, long long xlen, char* y, long long ylen) +{ + long long i; + if(xlen != ylen) return 0; + for (i = 0; i < xlen; i++) + { + if(seq_nt4_table[(uint8_t)x[i]] >= 4) return 0; + if((x[i] != y[i]) && seq_nt4_table[(uint8_t)y[i]] < 4) return 0; + } + + return 1; +} + +long long get_enzyme_occ(char* t, long long tlen, char* p, long long plen) +{ + long long i, c, s = 0, j, occ = 0; + int badchar[5]; badchar[0] = badchar[1] = badchar[2] = badchar[3] = badchar[4] = -1; + for (i = 0; i < plen; i++) + { + c = seq_nt4_table[(uint8_t)p[i]]; + badchar[c] = i; + if(c == 4) badchar[0] = badchar[1] = badchar[2] = badchar[3] = i; + } + badchar[4] = -1; + + while(s <= (tlen - plen)) + { + j = plen-1; + + while(j >= 0) + { + if(seq_nt4_table[(uint8_t)t[s+j]] >= 4) break; + if((p[j] != t[s+j]) && seq_nt4_table[(uint8_t)p[j]] < 4) break; + j--; + } + + + if (j < 0) + { + occ++; + ///s += (s+m < n)? m-badchar[txt[s+m]] : 1; + s++; + } + else + { + /*******************************for debug************************************/ + // long long f, end = s + MAX(1, j - badchar[seq_nt4_table[(uint8_t)t[s+j]]]); + // for (f = s+1; f < end; f++) + // { + // if(check_exact_match(t+f, plen, p, plen)) + // { + // fprintf(stderr, "s: %lld, end: %lld, s+j: %lld, t[s+j]: %c, badchar: %d, j: %lld\n", + // s, end, s+j, t[s+j], badchar[seq_nt4_table[(uint8_t)t[s+j]]], j); + // } + // } + /*******************************for debug************************************/ + + s += MAX(1, j - badchar[seq_nt4_table[(uint8_t)t[s+j]]]); + } + } + + return occ; +} + +#define pdq_cnt(q) ((q).x.a[0]) + +void init_pdq(pdq* q, uint64_t utg_num) +{ + kv_init(q->x); kv_push(uint64_t, q->x, 0); + kv_malloc(q->dis, utg_num); q->dis.n = utg_num; + kv_malloc(q->vis, utg_num); q->vis.n = utg_num; + + uint64_t i; + for (i = 1; (uint64_t)(1<uID_mode = ((uint64_t)-1) >> (64-i); + q->uID_shift = i; +} + +void destory_pdq(pdq* q) +{ + kv_destroy(q->x); + kv_destroy(q->dis); + kv_destroy(q->vis); +} + +void reset_pdq(pdq* q) +{ + q->x.n = 1; pdq_cnt(*q) = 0; + memset(q->dis.a, -1, sizeof(uint64_t)*q->dis.n); + memset(q->vis.a, 0, sizeof(uint8_t)*q->vis.n); +} + +void swap_pdq(uint64_t* i, uint64_t* j) +{ + uint64_t k; + k = (*i); + (*i) = (*j); + (*j) = k; +} + +#define weight(q, i) (get_dv_adv((q).x.a[i], (q).uID_mode, (q).uID_shift, &(q).tmp_v, &(q).tmp_d)) + +uint64_t inline set_dv_adv(uint64_t v, uint64_t dis, uint64_t v_mode, uint64_t v_shift) +{ + dis <<= v_shift; dis |= (v&v_mode); + return dis; +} + +uint64_t inline get_dv_adv(uint64_t x, uint64_t v_mode, uint64_t v_shift, uint64_t* v, uint64_t* dis) +{ + (*v) = x & v_mode; + (*dis) = x >> v_shift; + return (*dis); +} + +void push_pdq(pdq* q, uint64_t v, uint64_t dis) +{ + kv_push(uint64_t, q->x, set_dv_adv(v, dis, q->uID_mode, q->uID_shift)); + pdq_cnt(*q)++; + int c_i = pdq_cnt(*q), p_i = c_i>>1; + + while ((p_i > 0) && (weight(*q, c_i) < weight(*q, p_i))) + { + swap_pdq(&(q->x.a[c_i]), &(q->x.a[p_i])); + c_i = p_i; + p_i = c_i >> 1; + } +} + +void pop_pdq(pdq* q, uint64_t* min_v, uint64_t* min_dis) +{ + (*min_v) = (*min_dis) = (uint64_t)-1; + if(pdq_cnt(*q) == 0) return; + get_dv_adv((*q).x.a[1], (*q).uID_mode, (*q).uID_shift, min_v, min_dis); + /*******************************for debug************************************/ + // uint64_t i; + // for (i = 1; i < q->x.n; i++) + // { + // if(weight(*q, i) < (*min_dis)) fprintf(stderr, "ERROR\n"); + // } + /*******************************for debug************************************/ + ///min = q->x.a[1]; + swap_pdq(&(q->x.a[1]), &(q->x.a[pdq_cnt(*q)])); + pdq_cnt(*q)--; + q->x.n--; + + int c_i = 1, left_i, right_i, min_i, flag = 1; + while(flag == 1) + { + flag = 0; + left_i = c_i << 1; + right_i = left_i + 1; + if(left_i > (int)(pdq_cnt(*q))) + { + break; // both children are null + } + else if(right_i > (int)(pdq_cnt(*q))) + { + min_i = left_i; // right children is null + } + else + { + min_i = (weight(*q, left_i) < weight(*q, right_i))? left_i : right_i; + } + + if(weight(*q, c_i) > weight(*q, min_i)) + { + swap_pdq(&(q->x.a[c_i]), &(q->x.a[min_i])); + c_i = min_i; + flag = 1; + } + } +} + +void get_shortest_path(uint32_t src, pdq* pq, asg_t *sg, uint32_t* pre) +{ + uint64_t v, u, i, nv, w; + asg_arc_t *av = NULL; + reset_pdq(pq); + pq->dis.a[src] = 0; + if(pre) pre[src] = (uint32_t)-1; + push_pdq(pq, src, 0); + while (pdq_cnt(*pq) > 0) + { + pop_pdq(pq, &v, &w); + pq->vis.a[v] = 1; + + av = asg_arc_a(sg, v); + nv = asg_arc_n(sg, v); + + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + u = av[i].v; + w = (uint32_t)av[i].ul; + + if(pq->vis.a[u] == 0 && pq->dis.a[u] > pq->dis.a[v] + w) + { + pq->dis.a[u] = pq->dis.a[v] + w; + push_pdq(pq, u, pq->dis.a[u]); + if(pre) pre[u] = v; + } + } + } +} + +void all_pair_shortest_path(asg_t *sg, hc_links* link, MT* M) +{ + hc_linkeage* t = NULL; + pdq pq; + init_pdq(&pq, sg->n_seq<<1); + uint32_t n_vtx = sg->n_seq<<1, v; + uint64_t k, *p = NULL; + + for (v = 0; v < n_vtx; ++v) + { + if (sg->seq[v>>1].del) continue; + t = &(link->a.a[v>>1]); + if (t->e.n == 0) continue; + get_shortest_path(v, &pq, sg, NULL); + for (k = 0; k < pq.dis.n; k++) + { + if(pq.dis.a[k] == (uint64_t)-1) continue; + kv_pushp(uint64_t, M->matrix.a[v].a, &p); + (*p) = k << M->uID_shift; + (*p) = (*p) | pq.dis.a[k]; + } + } + + destory_pdq(&pq); +} + +typedef struct{ + pdq* pq; + uint32_t src; + asg_t *sg; + uint8_t *dest, flag; + uint64_t occ, df_occ, v; + uint32_t* pre; +}pdq_spec; + +uint32_t get_specific_shortest_path(pdq_spec *p) +{ + uint64_t u, i, nv, w; + asg_arc_t *av = NULL; + if(p->v == (uint64_t)-1) + { + // reset_pdq(p->pq); + p->pq->dis.a[p->src] = 0; + if(p->pre) p->pre[p->src] = (uint32_t)-1; + push_pdq(p->pq, p->src, 0); + p->occ = 0; + } + if(p->occ >= p->df_occ) return 0; + + while (pdq_cnt(*(p->pq)) > 0) + { + pop_pdq(p->pq, &(p->v), &w); + p->pq->vis.a[p->v] = 1; + if(p->dest && p->dest[p->v] == p->flag) p->occ++; + if(p->occ > p->df_occ) return 0; + + av = asg_arc_a(p->sg, p->v); + nv = asg_arc_n(p->sg, p->v); + + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + u = av[i].v; + w = (uint32_t)av[i].ul; + + if(p->pq->vis.a[u] == 0 && p->pq->dis.a[u] > p->pq->dis.a[p->v] + w) + { + p->pq->dis.a[u] = p->pq->dis.a[p->v] + w; + push_pdq(p->pq, u, p->pq->dis.a[u]); + if(p->pre) p->pre[u] = p->v; + } + } + if(p->dest && p->dest[p->v] == p->flag) return 1; + if(!p->dest) return 1; + } + + return 0; +} +void get_utg_path(uint64_t s, uint64_t e, uint32_t *path, buf_t *res) +{ + uint64_t p = path[e], i; + res->b.n = 0; + kv_push(uint32_t, res->b, e); + while (p != s) + { + kv_push(uint32_t, res->b, p); + p = path[p]; + } + kv_push(uint32_t, res->b, s); + for (i = 0; i < (res->b.n>>1); i++) + { + p = res->b.a[i]; + res->b.a[i] = res->b.a[res->b.n-i-1]; + res->b.a[res->b.n-i-1] = p; + } + res->b.n--; +} +uint32_t check_trans_relation_by_path(uint32_t v, uint32_t w, pdq* pqv, uint32_t* path_v, buf_t *resv, +pdq* pqw, uint32_t* path_w, buf_t *resw, asg_t *sg, uint8_t *dest, uint8_t df, uint32_t df_occ, +double rate, long long *dis) +{ + uint64_t r1, r2, d1, d2; + pdq_spec p1, p2, *p = NULL; + p1.v = (uint64_t)-1; p1.src = v; p1.pq = pqv; p1.sg = sg; p1.df_occ = df_occ; + p1.occ = df_occ; p1.flag = df; p1.dest = dest; p1.pre = path_v; if(resv) resv->b.n = 0; + reset_pdq(p1.pq); + + p2.v = (uint64_t)-1; p2.src = w; p2.pq = pqw; p2.sg = sg; p2.df_occ = df_occ; + p2.occ = df_occ; p2.flag = df; p2.dest = dest; p2.pre = path_w; if(resw) resw->b.n = 0; + reset_pdq(p2.pq); + + if(dis) (*dis) = 0; + + while (1) + { + p = &p1; + r1 = get_specific_shortest_path(p); + if(r1 && p1.pq->vis.a[p->v] && p2.pq->vis.a[p->v]) + { + d1 = p1.pq->dis.a[p->v]; d2 = p2.pq->dis.a[p->v]; + if(d1 != (uint64_t)-1 && d2 != (uint64_t)-1) + { + if(d2 <= d1*(1+rate) && d2 >= d1*(1-rate)) + { + if(resv) get_utg_path(p1.src, p->v, p1.pre, resv); + if(resw) get_utg_path(p2.src, p->v, p2.pre, resw); + if(dis) + { + (*dis) = d1 + d2; + (*dis) -= (sg->seq[p1.src>>1].len + sg->seq[p2.src>>1].len); + } + + // fprintf(stderr, "p-utg%.6ul(d1-%lu), a-utg%.6ul(d2-%lu), conver-utg%.6lul\n", + // (v>>1) + 1, d1, (w>>1) + 1, d2, (p->v>>1) + 1); + + + return 1; + } + } + } + p = &p2; + r2 = get_specific_shortest_path(p); + if(r2 && p1.pq->vis.a[p->v] && p2.pq->vis.a[p->v]) + { + d1 = p1.pq->dis.a[p->v]; d2 = p2.pq->dis.a[p->v]; + if(d1 != (uint64_t)-1 && d2 != (uint64_t)-1) + { + if(d2 <= d1*(1+rate) && d2 >= d1*(1-rate)) + { + if(resv) get_utg_path(p1.src, p->v, p1.pre, resv); + if(resw) get_utg_path(p2.src, p->v, p2.pre, resw); + if(dis) + { + (*dis) = d1 + d2; + (*dis) -= (sg->seq[p1.src>>1].len + sg->seq[p2.src>>1].len); + } + // fprintf(stderr, "p-utg%.6ul(d1-%lu), a-utg%.6ul(d2-%lu), conver-utg%.6lul\n", + // (v>>1) + 1, d1, (w>>1) + 1, d2, (p->v>>1) + 1); + return 1; + } + } + } + if(!r1 && !r2) return 0; + } + +} + +void set_utg_by_dis(uint32_t v, pdq* pq, asg_t *g, kvec_t_u32_warp *res, uint32_t dis) +{ + uint64_t r; + pdq_spec a; + a.v = (uint64_t)-1; a.src = v; a.pq = pq; a.sg = g; a.df_occ = (uint64_t)-1; + a.occ = 0; a.flag = (uint8_t)-1; a.dest = NULL; a.pre = NULL; + reset_pdq(a.pq); + while (1) + { + r = get_specific_shortest_path(&a); + if(!r) return; + if(a.pq->dis.a[a.v] <= dis) kv_push(uint32_t, res->a, a.v); + else return; + } +} + +uint64_t LCA_distance(long long d_x, long long d_y, long long xLen, long long yLen, uint8_t* rev) +{ + (*rev) = 0; + long long x_beg, x_end, y_beg, y_end, t_beg, t_end; + x_end = d_x; x_beg = x_end - xLen + 1; + y_end = d_y; y_beg = y_end - yLen + 1; + if(x_end >= y_end) + { + t_end = x_end; (*rev) = 0; + t_beg = y_beg; + } + else + { + t_end = y_end; (*rev) = 1; + t_beg = x_beg; + } + + return t_end + 1 - t_beg; +} + +uint64_t get_LCA_bubble(uint32_t x, uint64_t xLen, uint32_t y, uint64_t yLen, uint8_t* dis, uint64_t n, MT* M, bubble_type* bub, uint64_t* min_rev) +{ + uint32_t j, v, k; + uint64_t u, d = (uint64_t)-1, tmp; + uint8_t rev; + uint32_t root[2], a_n, *a; + get_bubbles(bub, bub->index[x>>1], &root[0], &root[1], &a, &a_n, NULL); + root[0] ^= 1; root[1] ^= 1; + if(root[0] > root[1]) + { + k = root[0]; + root[0] = root[1]; + root[1] = k; + } + + dis[root[0]] = (uint8_t)-1; + dis[root[1]] = (uint8_t)-1; + + v = x; + for (j = 0; j < M->matrix.a[v].a.n; j++) + { + u = M->matrix.a[v].a.a[j] >> M->uID_shift; + d = M->matrix.a[v].a.a[j] & M->dis_mode; + dis[u] = dis[u] >> 4; + } + + v = y; + for (j = 0; j < M->matrix.a[v].a.n; j++) + { + u = M->matrix.a[v].a.a[j] >> M->uID_shift; + d = M->matrix.a[v].a.a[j] & M->dis_mode; + dis[u] = dis[u] >> 4; + } + uint64_t x_i = 0, y_i = 0, d_x, d_y, min_d = (uint64_t)-1; + uint32_t min_j = (uint32_t)-1; + (*min_rev) = (uint64_t)-1; + + + for (k = 0; k < 2; k++) + { + j = root[k]; + if(dis[j] != 0) + { + dis[j] = (uint8_t)-1; + continue; + } + + for (; x_i < M->matrix.a[x].a.n; x_i++) + { + u = M->matrix.a[x].a.a[x_i] >> M->uID_shift; + d = M->matrix.a[x].a.a[x_i] & M->dis_mode; + if(u == j) break; + } + if(x_i == M->matrix.a[x].a.n && M->matrix.a[x].a.n != 0) fprintf(stderr, "ERROR X\n"); + d_x = d; + + for (; y_i < M->matrix.a[y].a.n; y_i++) + { + u = M->matrix.a[y].a.a[y_i] >> M->uID_shift; + d = M->matrix.a[y].a.a[y_i] & M->dis_mode; + if(u == j) break; + } + if(y_i == M->matrix.a[y].a.n && M->matrix.a[y].a.n != 0) fprintf(stderr, "ERROR Y\n"); + d_y = d; + + tmp = LCA_distance(d_x, d_y, xLen, yLen, &rev); + if(tmp < min_d) min_d = tmp, (*min_rev) = rev, min_j = j; + } + + if(min_j == x || min_j == y) return (uint64_t)-1; + + return min_d; + + +} + +uint64_t get_LCA(uint32_t x, uint64_t xLen, uint32_t y, uint64_t yLen, uint8_t* dis, uint64_t n, MT* M, bubble_type* bub, uint64_t* min_rev) +{ + if(IF_BUB(x>>1, *bub) && IF_BUB(y>>1, *bub) && bub->index[x>>1] == bub->index[y>>1]) + { + return get_LCA_bubble(x, xLen, y, yLen, dis, n, M, bub, min_rev); + } + else + { + memset(dis, -1, sizeof(uint8_t)*n); + } + + uint32_t j, v; + uint64_t u, d = (uint64_t)-1, tmp; + uint8_t rev; + + v = x; + for (j = 0; j < M->matrix.a[v].a.n; j++) + { + u = M->matrix.a[v].a.a[j] >> M->uID_shift; + d = M->matrix.a[v].a.a[j] & M->dis_mode; + dis[u] = dis[u] >> 4; + } + + v = y; + for (j = 0; j < M->matrix.a[v].a.n; j++) + { + u = M->matrix.a[v].a.a[j] >> M->uID_shift; + d = M->matrix.a[v].a.a[j] & M->dis_mode; + dis[u] = dis[u] >> 4; + } + + uint64_t x_i = 0, y_i = 0, d_x, d_y, min_d = (uint64_t)-1; + uint32_t min_j = (uint32_t)-1; + (*min_rev) = (uint64_t)-1; + for (j = 0; j < n; j++) + { + if(dis[j] != 0) + { + dis[j] = (uint8_t)-1; + continue; + } + + for (; x_i < M->matrix.a[x].a.n; x_i++) + { + u = M->matrix.a[x].a.a[x_i] >> M->uID_shift; + d = M->matrix.a[x].a.a[x_i] & M->dis_mode; + if(u == j) break; + } + if(x_i == M->matrix.a[x].a.n && M->matrix.a[x].a.n != 0) fprintf(stderr, "ERROR X\n"); + d_x = d; + + for (; y_i < M->matrix.a[y].a.n; y_i++) + { + u = M->matrix.a[y].a.a[y_i] >> M->uID_shift; + d = M->matrix.a[y].a.a[y_i] & M->dis_mode; + if(u == j) break; + } + if(y_i == M->matrix.a[y].a.n && M->matrix.a[y].a.n != 0) fprintf(stderr, "ERROR Y\n"); + d_y = d; + + + tmp = LCA_distance(d_x, d_y, xLen, yLen, &rev); + if(tmp < min_d) min_d = tmp, (*min_rev) = rev, min_j = j; + } + + if(min_j == x || min_j == y) return (uint64_t)-1; + + return min_d; +} + +typedef struct { // data structure for each step in kt_pipeline() + asg_t *sg; + hc_links* link; + MT* M; + bubble_type* bub; + uint8_t** dis_buf; +} utg_d_t; + +static void worker_for_dis(void *data, long i, int tid) +{ + utg_d_t* s = (utg_d_t*)data; + hc_links* link = s->link; + MT* M = s->M; + bubble_type* bub = s->bub; + uint8_t* dis_buf = s->dis_buf[tid]; + asg_t *sg = s->sg; + hc_linkeage* t = NULL; + uint32_t n_vtx = sg->n_seq<<1, v, u, k, j; + uint64_t d[2], db[2], q_u, min, min_i, min_b, rev[2], min_rev; + + if (sg->seq[i].del) return; + t = &(link->a.a[i]); + if (t->e.n == 0) return; + + for (k = 0; k < t->e.n; k++) + { + if(t->e.a[k].del) continue; + if(i == t->e.a[k].uID) continue; + u = t->e.a[k].uID; + + for (v = ((uint64_t)(i)<<1); v < ((uint64_t)(i+1)<<1); v++)///two directions + { + d[0] = d[1] = db[0] = db[1] = (uint64_t)-1; + for (j = 0; j < M->matrix.a[v].a.n; j++) + { + q_u = M->matrix.a[v].a.a[j] >> M->uID_shift; + if((q_u>>1) == u) d[q_u&1] = (M->matrix.a[v].a.a[j] & M->dis_mode) + sg->seq[q_u>>1].len; + if((q_u>>1) > u) break;///just for speeding up, doesn't affect results + } + + min = min_i = min_b = (uint64_t)-1; + if(t->e.a[k].dis != (uint64_t)-1) min = t->e.a[k].dis >> 3; + + if(d[0] < min) min = d[0], min_i = 0, min_b = 0; + if(d[1] < min) min = d[1], min_i = 1, min_b = 0; + + if(min_i != (uint64_t)-1 && min != (uint64_t)-1) + { + t->e.a[k].dis = min<<1; + t->e.a[k].dis += min_b; + t->e.a[k].dis <<=1; + t->e.a[k].dis += v&1;//s-direction + t->e.a[k].dis <<=1; + t->e.a[k].dis += min_i;//e-direction + } + } + + + ///might be wrong + if(IF_BUB(i, *bub) && IF_BUB(u, *bub) + && bub->index[i] != bub->index[u] && t->e.a[k].dis != (uint64_t)-1) + { + continue; + } + + for (v = ((uint64_t)(i)<<1); v < ((uint64_t)(i+1)<<1); v++) + { + d[0] = d[1] = db[0] = db[1] = (uint64_t)-1; + db[0] = get_LCA(v, sg->seq[v>>1].len, u<<1, sg->seq[u].len, + dis_buf, n_vtx, M, bub, &rev[0]); + db[1] = get_LCA(v, sg->seq[v>>1].len, (u<<1) + 1, sg->seq[u].len, + dis_buf, n_vtx, M, bub, &rev[1]); + + min = min_i = min_b = min_rev = (uint64_t)-1; + if(t->e.a[k].dis != (uint64_t)-1) min = t->e.a[k].dis >> 3; + + if(db[0] < min) min = db[0], min_i = 0, min_b = 1, min_rev = rev[0]; + if(db[1] < min) min = db[1], min_i = 1, min_b = 1, min_rev = rev[1]; + + if(min_i != (uint64_t)-1 && min != (uint64_t)-1) + { + t->e.a[k].dis = min<<1; + t->e.a[k].dis += min_b; + t->e.a[k].dis <<=1; + t->e.a[k].dis += ((v&1)^min_rev);//s-direction + t->e.a[k].dis <<=1; + t->e.a[k].dis += (min_i^min_rev);//e-direction + } + } + } +} + +void fill_utg_distance_multi(asg_t *sg, hc_links* link, MT* M, bubble_type* bub) +{ + // double index_time = yak_realtime(); + uint32_t i; + utg_d_t s; + s.sg = sg; s.link = link; s.M = M; s.bub = bub; + s.dis_buf = (uint8_t**)malloc(sizeof(uint8_t*)*asm_opt.thread_num); + for (i = 0; i < (uint32_t)asm_opt.thread_num; i++) + { + s.dis_buf[i] = (uint8_t*)malloc(sizeof(uint8_t)*(s.sg->n_seq<<1)); + } + + kt_for(asm_opt.thread_num, worker_for_dis, &s, s.sg->n_seq); + + + for (i = 0; i < (uint32_t)asm_opt.thread_num; i++) + { + free(s.dis_buf[i]); + } + free(s.dis_buf); + // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); +} + +void init_MT(MT* M, uint32_t n_vtx) +{ + uint32_t v; + kv_init(M->matrix); kv_malloc(M->matrix, n_vtx); M->matrix.n = n_vtx; + for (v = 0; v < n_vtx; ++v) kv_init(M->matrix.a[v].a); + for (v = 1; (uint64_t)(1<uID_shift = 64 - v; M->dis_mode = ((uint64_t)-1) >> v; +} + +void destory_MT(MT* M) +{ + uint32_t v; + for (v = 0; v < M->matrix.n; ++v) kv_destroy(M->matrix.a[v].a); + kv_destroy(M->matrix); +} + +int get_trans_ug_arch(uint32_t qn, uint32_t qs, uint32_t qe, uint32_t qLen, +uint32_t tn, uint32_t ts, uint32_t te, uint32_t tLen, uint32_t rev, asg_arc_t* t) +{ + ma_hit_t h; + h.qns = qn; + h.qns = h.qns << 32; + h.qns = h.qns | qs; + h.qe = qe; + h.tn = tn; + h.ts = ts; + h.te = te; + h.rev = rev; + h.del = 0; + h.bl = h.el = h.ml = h.no_l_indel = 0; + return ma_hit2arc(&h, qLen, tLen, MAX(qLen, tLen) + 1, 0, 0, t); +} + +void update_ug_by_trans(asg_t *sg, kv_u_trans_t *ta) +{ + u_trans_t *a = NULL, *p = NULL; + uint32_t i, k, st, occ, n, m; + uint32_t qn, tn, qs, qe, ts, te, rev; + asg_arc_t t, *e = NULL; + long long r_qs, r_qe, r_ts, r_te; + int r; + + for (k = occ = 0; k < ta->idx.n; k++) + { + a = u_trans_a(*ta, k); + n = u_trans_n(*ta, k); + for (st = 0, i = 1; i <= n; ++i) + { + if (i == n || a[i].tn != a[st].tn) + { + for (m = st, p = &(a[st]); m < i; m++) + { + if(a[m].nw > p->nw) p = &(a[m]); + } + + if(p->f == RC_2)///dis-connected + { + rev = p->rev; + qn = p->qn; + qs = p->qs; + qe = p->qe - 1; + if(rev) + { + tn = p->tn; + ts = sg->seq[tn].len - (p->te - 1) - 1; + te = sg->seq[tn].len - p->ts - 1; + } + else + { + tn = p->tn; + ts = p->ts; + te = p->te - 1; + } + + classify_hap_overlap(qs, qe, sg->seq[qn].len, ts, te, sg->seq[tn].len, + &r_qs, &r_qe, &r_ts, &r_te); + + qs = r_qs; qe = r_qe + 1; + if(rev) + { + ts = sg->seq[tn].len - r_te - 1; + te = sg->seq[tn].len - r_ts - 1 + 1; + } + else + { + ts = r_ts; te = r_te + 1; + } + + r = get_trans_ug_arch(qn, qs, qe, sg->seq[qn].len, + tn, ts, te, sg->seq[tn].len, rev, &t); + if(r >= 0) + { + e = asg_arc_pushp(sg); + *e = t; + occ++; + } + } + st = i; + } + } + } + + if(occ > 0) + { + free(sg->idx); + sg->idx = 0; + sg->is_srt = 0; + asg_cleanup(sg); + } + asg_arc_del_trans(sg, asm_opt.gap_fuzz); + +} + +void push_LCA_edges(long long d_x, long long d_y, long long xLen, long long yLen, +uint32_t v, uint32_t w, uint64_t *e0, uint64_t *e1) +{ + long long x_beg, x_end, y_beg, y_end; + uint64_t d, rev; + x_end = d_x; x_beg = x_end - xLen + 1; + y_end = d_y; y_beg = y_end - yLen + 1; + + long long ovlp = ((MIN(x_end, y_end) >= MAX(x_beg, y_beg))? + MIN(x_end, y_end) - MAX(x_beg, y_beg) + 1 : 0); + if(ovlp != xLen && ovlp != yLen) + { + d = MAX(x_end, y_end) - MIN(x_beg, y_beg) + 1; + if(x_end >= y_end) rev = 1; + else rev = 0; + + (*e0) = d; + (*e0) <<= 1; + (*e0) += 1; + (*e0) <<= 1; + (*e0) += ((v&1)^rev);//s-direction + (*e0) <<= 1; + (*e0) += ((w&1)^rev);//e-direction + + rev ^= 1; + (*e1) = d; + (*e1) <<= 1; + (*e1) += 1; + (*e1) <<= 1; + (*e1) += ((w&1)^rev);//s-direction + (*e1) <<= 1; + (*e1) += ((v&1)^rev);//e-direction + } + else + { + if(xLen >= yLen) d = (x_beg + 1) + (y_end - y_beg + 1); + else d = (x_end - x_beg + 1) + (yLen - y_end - 1); + + (*e0) = d; + (*e0) <<= 1; + (*e0) += 1; + (*e0) <<= 1; + (*e0) += (v&1);//s-direction + (*e0) <<= 1; + (*e0) += (w&1);//e-direction + + if(xLen >= yLen) d = (y_end - y_beg + 1) + (xLen - x_end - 1); + else d = (y_beg + 1) + (x_end - x_beg + 1); + (*e1) = d; + (*e1) <<= 1; + (*e1) += 1; + (*e1) <<= 1; + (*e1) += (w&1);//s-direction + (*e1) <<= 1; + (*e1) += (v&1);//e-direction + } +} + +void push_LCA_edges_rev(hc_edge *hx, hc_edge *hy, +long long xLen, long long yLen, long long rLen, +uint32_t v, uint32_t w, uint64_t *e0, uint64_t *e1) +{ + long long x_beg, x_end, y_beg, y_end, dx, dy; + uint64_t d, rev; + dx = (hx->dis>>3); + if((hx->dis&(uint64_t)2)) + { + x_beg = rLen - dx - 1; x_end = x_beg + xLen - 1; + } + else + { + x_end = dx; x_beg = x_end - xLen + 1; + } + + dy = (hy->dis>>3); + if((hy->dis&(uint64_t)2)) + { + y_beg = rLen - dy - 1; y_end = y_beg + yLen - 1; + } + else + { + y_end = dy; y_beg = y_end - yLen + 1; + } + + long long ovlp = ((MIN(x_end, y_end) >= MAX(x_beg, y_beg))? + MIN(x_end, y_end) - MAX(x_beg, y_beg) + 1 : 0); + if(ovlp != xLen && ovlp != yLen) + { + d = MAX(x_end, y_end) - MIN(x_beg, y_beg) + 1; + if(x_end >= y_end) rev = 1; + else rev = 0; + + (*e0) = d; + (*e0) <<= 1; + (*e0) += 1; + (*e0) <<= 1; + (*e0) += ((v&1)^rev);//s-direction + (*e0) <<= 1; + (*e0) += ((w&1)^rev);//e-direction + + rev ^= 1; + (*e1) = d; + (*e1) <<= 1; + (*e1) += 1; + (*e1) <<= 1; + (*e1) += ((w&1)^rev);//s-direction + (*e1) <<= 1; + (*e1) += ((v&1)^rev);//e-direction + } + else + { + if(xLen >= yLen) d = (x_beg + 1) + (y_end - y_beg + 1); + else d = (x_end - x_beg + 1) + (yLen - y_end - 1); + (*e0) = d; + (*e0) <<= 1; + (*e0) += 1; + (*e0) <<= 1; + (*e0) += (v&1);//s-direction + (*e0) <<= 1; + (*e0) += (w&1);//e-direction + + if(xLen >= yLen) d = (y_end - y_beg + 1) + (xLen - x_end - 1); + else d = (y_beg + 1) + (x_end - x_beg + 1); + (*e1) = d; + (*e1) <<= 1; + (*e1) += 1; + (*e1) <<= 1; + (*e1) += (w&1);//s-direction + (*e1) <<= 1; + (*e1) += (v&1);//e-direction + } +} + +uint32_t up_contain(kv_u_trans_t *ta, hc_links* link, uint8_t *uc_idx, asg_t *sg, kvec_t_u64_warp *buf) +{ + hc_edge *he = NULL, *ht = NULL, *hx = NULL; + uint64_t t_d = (uint64_t)-1, hd; + uint32_t qn, tn, qs, qe, ts, te, rev, is_c; + u_trans_t *a = NULL, *p = NULL; + asg_arc_t t; + uint32_t i, k, st, occ, n, m; + long long r_qs, r_qe, r_ts, r_te; + int r; + + for (k = 0, buf->a.n = 0; k < ta->idx.n; k++) + { + if((uc_idx[k]&2)&&(!(uc_idx[k]&1)))///contain others + { + if(link->a.a[k].e.n == 0) + { + uc_idx[k] -= 2; + continue; + } + a = u_trans_a(*ta, k); + n = u_trans_n(*ta, k); + for (st = 0, i = 1; i <= n; ++i) + { + if (i == n || a[i].tn != a[st].tn) + { + for (m = st, p = &(a[st]); m < i; m++) + { + if(a[m].nw > p->nw) p = &(a[m]); + } + + if(p->f == RC_2)///dis-connected + { + rev = p->rev; + qn = p->qn; + qs = p->qs; + qe = p->qe - 1; + if(rev) + { + tn = p->tn; + ts = sg->seq[tn].len - (p->te - 1) - 1; + te = sg->seq[tn].len - p->ts - 1; + } + else + { + tn = p->tn; + ts = p->ts; + te = p->te - 1; + } + + classify_hap_overlap(qs, qe, sg->seq[qn].len, ts, te, sg->seq[tn].len, + &r_qs, &r_qe, &r_ts, &r_te); + + qs = r_qs; qe = r_qe + 1; + if(rev) + { + ts = sg->seq[tn].len - r_te - 1; + te = sg->seq[tn].len - r_ts - 1 + 1; + } + else + { + ts = r_ts; te = r_te + 1; + } + + r = get_trans_ug_arch(qn, qs, qe, sg->seq[qn].len, + tn, ts, te, sg->seq[tn].len, rev, &t); + if(r == MA_HT_TCONT)//q contains t + { + hd = tn; hd <<= 32; hd |= qn; + kv_push(uint64_t, buf->a, hd); + ///qn->tn + he = get_hc_edge(link, qn, tn, 0); + if(!he) + { + push_hc_edge(&(link->a.a[qn]), tn, 0, 0, &t_d); + he = get_hc_edge(link, qn, tn, 0); + } + hd = (te - ts) + qs; + if(hd < he->dis) + { + he->dis = hd << 1; + he->dis += 1; + he->dis <<= 1; + he->dis += 0;//s-direction + he->dis <<= 1; + he->dis += rev;//e-direction + } + + ///tn->qn + he = get_hc_edge(link, tn, qn, 0); + if(!he) + { + push_hc_edge(&(link->a.a[tn]), qn, 0, 0, &t_d); + he = get_hc_edge(link, tn, qn, 0); + } + hd = (te - ts) + sg->seq[qn].len - qe; + if(hd < he->dis) + { + he->dis = hd << 1; + he->dis += 1; + he->dis <<= 1; + he->dis += 0;//s-direction + he->dis <<= 1; + he->dis += rev;//e-direction + } + } + } + st = i; + } + } + uc_idx[k] -= 2; + } + } + + uint64_t e0, e1; + for (k = 0; k < buf->a.n; k++) + { + qn = buf->a.a[k] >> 32; + tn = (uint32_t)buf->a.a[k]; + + he = get_hc_edge(link, tn, qn, 0); //tn contains qn + for (i = 0; i < link->a.a[tn].e.n; i++) + { + if(link->a.a[tn].e.a[i].del) continue; + if(link->a.a[tn].e.a[i].uID == qn) continue; + ht = &(link->a.a[tn].e.a[i]); + if(ht->dis == (uint64_t)-1) continue; + + if((he->dis&(uint64_t)2) == (ht->dis&(uint64_t)2))///s in same direction + { + push_LCA_edges(he->dis>>3, ht->dis>>3, sg->seq[he->uID].len, sg->seq[ht->uID].len, + he->dis&1, ht->dis&1, &e0, &e1); + + ///forward + hx = get_hc_edge(link, he->uID, ht->uID, 0); + if(!hx) + { + push_hc_edge(&(link->a.a[he->uID]), ht->uID, 0, 0, &t_d); + hx = get_hc_edge(link, he->uID, ht->uID, 0); + } + if ((e0>>3) < (hx->dis>>3)) hx->dis = e0; + + ///backward + hx = get_hc_edge(link, ht->uID, he->uID, 0); + if(!hx) + { + push_hc_edge(&(link->a.a[ht->uID]), he->uID, 0, 0, &t_d); + hx = get_hc_edge(link, ht->uID, he->uID, 0); + } + if ((e1>>3) < (hx->dis>>3)) hx->dis = e1; + } + else + { + push_LCA_edges_rev(he, ht, sg->seq[he->uID].len, sg->seq[ht->uID].len, + sg->seq[tn].len, he->dis&1, ht->dis&1, &e0, &e1); + + ///forward + hx = get_hc_edge(link, he->uID, ht->uID, 0); + if(!hx) + { + push_hc_edge(&(link->a.a[he->uID]), ht->uID, 0, 0, &t_d); + hx = get_hc_edge(link, he->uID, ht->uID, 0); + } + if ((e0>>3) < (hx->dis>>3)) hx->dis = e0; + + ///backward + hx = get_hc_edge(link, ht->uID, he->uID, 0); + if(!hx) + { + push_hc_edge(&(link->a.a[ht->uID]), he->uID, 0, 0, &t_d); + hx = get_hc_edge(link, ht->uID, he->uID, 0); + } + if ((e1>>3) < (hx->dis>>3)) hx->dis = e1; + } + } + } + + + for (k = 0, occ = 0; k < ta->idx.n; k++) + { + if((uc_idx[k]&1) && (uc_idx[k]&2)) + { + is_c = 0; + a = u_trans_a(*ta, k); + n = u_trans_n(*ta, k); + for (st = 0, i = 1; i <= n; ++i) + { + if (i == n || a[i].tn != a[st].tn) + { + for (m = st, p = &(a[st]); m < i; m++) + { + if(a[m].nw > p->nw) p = &(a[m]); + } + + if(p->f == RC_2)///dis-connected + { + rev = p->rev; + qn = p->qn; + qs = p->qs; + qe = p->qe - 1; + if(rev) + { + tn = p->tn; + ts = sg->seq[tn].len - (p->te - 1) - 1; + te = sg->seq[tn].len - p->ts - 1; + } + else + { + tn = p->tn; + ts = p->ts; + te = p->te - 1; + } + + classify_hap_overlap(qs, qe, sg->seq[qn].len, ts, te, sg->seq[tn].len, + &r_qs, &r_qe, &r_ts, &r_te); + + qs = r_qs; qe = r_qe + 1; + if(rev) + { + ts = sg->seq[tn].len - r_te - 1; + te = sg->seq[tn].len - r_ts - 1 + 1; + } + else + { + ts = r_ts; te = r_te + 1; + } + + r = get_trans_ug_arch(qn, qs, qe, sg->seq[qn].len, + tn, ts, te, sg->seq[tn].len, rev, &t); + if(r == MA_HT_QCONT && (uc_idx[tn]&2))//t contains q + { + is_c = 1; + } + } + st = i; + } + } + if(is_c == 0) uc_idx[k] -= 1; + } + if(uc_idx[k]&2) occ++; + } + + return occ; +} + +void print_u_trans_t(u_trans_t *p) +{ + fprintf(stderr, "q-utg%.6ul\tqs(%u)\tqe(%u)\tt-utg%.6ul\tts(%u)\tte(%u)\trev(%u)\tw(%f)\n", p->qn+1, p->qs, p->qe, p->tn+1, p->ts, p->te, p->rev, p->nw); +} + +void update_containment_distance(asg_t *sg, kv_u_trans_t *ta, hc_links* link) +{ + uint8_t *uc_idx = NULL; + CALLOC(uc_idx, sg->n_seq); + + u_trans_t *a = NULL, *p = NULL; + uint32_t i, k, st, n, m; + uint32_t qn, tn, qs, qe, ts, te, rev; + asg_arc_t t; + long long r_qs, r_qe, r_ts, r_te; + int r; + + for (k = 0; k < ta->idx.n; k++) + { + a = u_trans_a(*ta, k); + n = u_trans_n(*ta, k); + for (st = 0, i = 1; i <= n; ++i) + { + if (i == n || a[i].tn != a[st].tn) + { + for (m = st, p = &(a[st]); m < i; m++) + { + if(a[m].nw > p->nw) p = &(a[m]); + } + + if(p->f == RC_2)///dis-connected + { + rev = p->rev; + qn = p->qn; + qs = p->qs; + qe = p->qe - 1; + if(rev) + { + tn = p->tn; + ts = sg->seq[tn].len - (p->te - 1) - 1; + te = sg->seq[tn].len - p->ts - 1; + } + else + { + tn = p->tn; + ts = p->ts; + te = p->te - 1; + } + + classify_hap_overlap(qs, qe, sg->seq[qn].len, ts, te, sg->seq[tn].len, + &r_qs, &r_qe, &r_ts, &r_te); + + qs = r_qs; qe = r_qe + 1; + if(rev) + { + ts = sg->seq[tn].len - r_te - 1; + te = sg->seq[tn].len - r_ts - 1 + 1; + } + else + { + ts = r_ts; te = r_te + 1; + } + + r = get_trans_ug_arch(qn, qs, qe, sg->seq[qn].len, + tn, ts, te, sg->seq[tn].len, rev, &t); + if(r == MA_HT_QCONT) uc_idx[qn] |= 1; + else if(r == MA_HT_TCONT) uc_idx[qn] |= 2; + + // if(r < 0) print_u_trans_t(p); + } + st = i; + } + } + } + + kvec_t_u64_warp buf; kv_init(buf.a); + while(up_contain(ta, link, uc_idx, sg, &buf)) + { + if(buf.a.n != 0) continue; + for (k = 0; k < ta->idx.n; k++) + { + if((uc_idx[k]&1) && (uc_idx[k]&2)) + { + uc_idx[k] = 2; + break; + } + } + } + + kv_destroy(buf.a); + free(uc_idx); +} + + +void collect_hc_links(const ha_ug_index* idx, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, MT* M) +{ + double index_time = yak_realtime(); + uint64_t k, i, shif = 64 - idx->uID_bits, beg, end, t_d; + for (k = 0; k < hits->a.n; ++k) + { + beg = ((hits->a.a[k].s<<1)>>shif); + end = ((hits->a.a[k].e<<1)>>shif); + + if(beg == end) continue; + if(IF_HOM(beg, *bub)) continue; + if(IF_HOM(end, *bub)) continue; + + t_d = (uint64_t)-1; + push_hc_edge(&(link->a.a[beg]), end, 0, 0, &t_d); + push_hc_edge(&(link->a.a[end]), beg, 0, 0, &t_d); + } + asg_t *copy_sg = copy_read_graph(idx->ug->g); + + + update_ug_by_trans(copy_sg, &(idx->t_ch->k_trans)); + all_pair_shortest_path(copy_sg, link, M); + fill_utg_distance_multi(copy_sg, link, M, bub); + update_containment_distance(copy_sg, &(idx->t_ch->k_trans), link); + asg_destroy(copy_sg); + + fprintf(stderr, "[M::%s::%.3f] ==> Hi-C linkages have been counted\n", __func__, yak_realtime()-index_time); + return; + + + + + + index_time = yak_realtime(); + for (k = 0; k < link->enzymes.n; k++) + { + link->enzymes.a[k] = 0; + for (i = 0; i < (uint64_t)asm_opt.hic_enzymes->n; i++) + { + link->enzymes.a[k] += get_enzyme_occ(idx->ug->u.a[k].s, idx->ug->u.a[k].len, + asm_opt.hic_enzymes->a[i], asm_opt.hic_enzymes->l[i]); + } + } + fprintf(stderr, "[M::%s::%.3f] ==> Enzymes have been counted\n", __func__, yak_realtime()-index_time); +} + + +void update_dis_connected_gfa(asg_t *sg, hc_links *link, MT *M) +{ + uint32_t i, m, v, nv, x, y; + asg_arc_t *av = NULL; + kvec_t(uint32_t) stack; kv_init(stack); + uint32_t *flag = NULL; MALLOC(flag, sg->n_seq); + uint64_t *group = NULL; MALLOC(group, sg->n_seq); + + for (i = 0; i < link->a.n; i++) + { + for (m = 0; m < link->a.a[i].e.n; m++) + { + if(link->a.a[i].e.a[m].dis == (uint64_t)-1) + { + if(link->a.a[i].e.a[m].is_cc != 0) + { + fprintf(stderr, "ERROR 1\n"); + } + } + + if(link->a.a[i].e.a[m].occ == (uint64_t)-1) + { + if(link->a.a[i].e.a[m].is_cc != 0 || link->a.a[i].e.a[m].dis == (uint64_t)-1) + { + fprintf(stderr, "ERROR 2\n"); + } + } + } + } + + + memset(flag, -1, sg->n_seq*sizeof(uint32_t)); + // connected componets + for (i = 0; i < sg->n_seq; ++i) { + if (flag[i] != (uint32_t)-1) continue; + stack.n = 0; + kv_push(uint32_t, stack, i); + while (stack.n > 0) { + stack.n--; + flag[stack.a[stack.n]] = i;///group id + + v = (stack.a[stack.n])<<1; + av = asg_arc_a(sg, v); + nv = asg_arc_n(sg, v); + for (m = 0; m < nv; ++m) { + if (flag[av[m].v>>1] != (uint32_t)-1) continue; + kv_push(uint32_t, stack, av[m].v>>1); + } + + v++; + av = asg_arc_a(sg, v); + nv = asg_arc_n(sg, v); + for (m = 0; m < nv; ++m) { + if (flag[av[m].v>>1] != (uint32_t)-1) continue; + kv_push(uint32_t, stack, av[m].v>>1); + } + } + } + kv_destroy(stack); + + + + // precalculate the size of each group + for (i = 0; i < sg->n_seq; ++i) + group[i] = (uint64_t)flag[i] << 32 | i; + radix_sort_hc64(group, group + sg->n_seq); + for (i = 1, x = y = 0; i <= sg->n_seq; ++i) { + if (i == sg->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; + } + } + + memset(flag, 0, sg->n_seq*sizeof(uint32_t)); + for (i = 1, x = y = 0; i <= sg->n_seq; ++i) + { + if (i == sg->n_seq || (group[i]>>32) != (group[x]>>32)) + { + x = i; + } + } + + + free(flag); +} + +void append_tig_link(uint64_t *cc, uint32_t cc_off, uint32_t cc_size, hc_links *link, asg_t *sg, kvec_t_u32_warp *buf) +{ + uint32_t i, k, id, tig_occ, b_cc_occ, *tig, *b_cc, qn, tn; + uint64_t t_d = (uint64_t)-1; + hc_edge *p = NULL; + for (i = 0; i < cc_size; ++i) ///how many nodes + { + id = (uint32_t)cc[cc_off + i];///node id + for (k = 0; k < link->a.a[id].e.n; k++) + { + if(link->a.a[id].e.a[k].is_cc == 0) break; + } + if(k < link->a.a[id].e.n) break; + } + if(i >= cc_size) return; + + buf->a.n = 0; tig_occ = 0; + for (i = 0; i < cc_size; ++i) ///how many nodes + { + id = (uint32_t)cc[cc_off + i];///node id + + if(asg_arc_n(sg, (id<<1)) == 0 || asg_arc_n(sg, ((id<<1)+1)) == 0)///tig + { + kv_push(uint32_t, buf->a, id); + tig_occ++; + } + } + + if(tig_occ == 0) return; + + b_cc_occ = 0; + for (i = 0; i < cc_size; ++i) ///how many nodes + { + id = (uint32_t)cc[cc_off + i];///node id + if(link->a.a[id].e.n == 0) continue; + + for (k = 0; k < link->a.a[id].e.n; k++) + { + if(link->a.a[id].e.a[k].is_cc == 0) break; + } + if(k < link->a.a[id].e.n)///disconnected + { + kv_push(uint32_t, buf->a, id); + b_cc_occ++; + } + } + + if(b_cc_occ == 0) return; + + tig = buf->a.a; + b_cc = buf->a.a + tig_occ; + for (i = 0; i < tig_occ; i++) + { + qn = tig[i]; + for (k = 0; k < b_cc_occ; k++) + { + tn = b_cc[k]; + if(qn == tn) continue; + p = get_hc_edge(link, qn, tn, 0); + if(p) continue; + + t_d = (uint64_t)-1; + p = push_hc_edge(&(link->a.a[qn]), tn, 0, 0, &t_d); + p->is_cc = 0; p->occ = (uint64_t)-1; + p = push_hc_edge(&(link->a.a[tn]), qn, 0, 0, &t_d); + p->is_cc = 0; p->occ = (uint64_t)-1; + } + } +} + +void update_ug_by_tigs(asg_t *sg, hc_links *link) +{ + uint32_t i, m, v, nv, x, y, qn, tn; + asg_arc_t *av = NULL; + kvec_t(uint32_t) stack; kv_init(stack); + uint32_t *flag = NULL; MALLOC(flag, sg->n_seq); + uint64_t *group = NULL; MALLOC(group, sg->n_seq); + kvec_t_u32_warp buf; kv_init(buf.a); + + + memset(flag, -1, sg->n_seq*sizeof(uint32_t)); + // connected componets + for (i = 0; i < sg->n_seq; ++i) { + if (flag[i] != (uint32_t)-1) continue; + stack.n = 0; + kv_push(uint32_t, stack, i); + while (stack.n > 0) { + stack.n--; + flag[stack.a[stack.n]] = i;///group id + + v = (stack.a[stack.n])<<1; + av = asg_arc_a(sg, v); + nv = asg_arc_n(sg, v); + for (m = 0; m < nv; ++m) { + if (flag[av[m].v>>1] != (uint32_t)-1) continue; + kv_push(uint32_t, stack, av[m].v>>1); + } + + v++; + av = asg_arc_a(sg, v); + nv = asg_arc_n(sg, v); + for (m = 0; m < nv; ++m) { + if (flag[av[m].v>>1] != (uint32_t)-1) continue; + kv_push(uint32_t, stack, av[m].v>>1); + } + } + } + kv_destroy(stack); + + + + // precalculate the size of each group + for (i = 0; i < sg->n_seq; ++i) + group[i] = (uint64_t)flag[i] << 32 | i; + radix_sort_hc64(group, group + sg->n_seq); + for (i = 1, x = y = 0; i <= sg->n_seq; ++i) { + if (i == sg->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; + } + } + + + for (i = 0; i < link->a.n; i++) + { + qn = i; + for (m = 0; m < link->a.a[i].e.n; m++) + { + link->a.a[i].e.a[m].occ = 0; + link->a.a[i].e.a[m].is_cc = 0; + tn = link->a.a[i].e.a[m].uID; + if((group[qn]>>32) == (group[tn]>>32)) + { + link->a.a[i].e.a[m].is_cc = 1; + } + } + } + + + for (i = 1, x = 0; i <= sg->n_seq; ++i) + { + if (i == sg->n_seq || (group[i]>>32) != (group[x]>>32)) + { + append_tig_link(group, x, i - x, link, sg, &buf); + x = i; + } + } + + free(flag); kv_destroy(buf.a); +} + +void idx_hc_links(kvec_pe_hit* hits, ha_ug_index* idx, bubble_type* bub); +void filter_disconnect_edges(ha_ug_index* idx, kvec_pe_hit *hits, hc_links *link, bubble_type *bub, uint32_t thres, double rate) +{ + uint32_t k, l, i, m, h_occ, *occ = NULL; + uint64_t shif = 64 - idx->uID_bits, qn, tn, u_dis; + pe_hit *h_a = NULL; + hc_linkeage *t = NULL; + u_trans_t *p = NULL; + hc_edge *e = NULL; + kv_u_trans_t k_trans; + kv_init(k_trans); + + if(hits->idx.n == 0) idx_hc_links(hits, idx, bub); + CALLOC(occ, hits->idx.n); + for (qn = 0; qn < hits->idx.n; qn++) + { + if(IF_HOM(qn, *bub)) continue; + h_a = hits->a.a + (hits->idx.a[qn]>>32); + h_occ = (uint32_t)(hits->idx.a[qn]); + + for (k = 1, l = 0; k <= h_occ; ++k) ///same qn + { + if (k == h_occ || ((h_a[k].e<<1)>>shif) != ((h_a[l].e<<1)>>shif)) //same qn and tn + { + tn = ((h_a[l].e<<1)>>shif); + if(!IF_HOM(tn, *bub) && tn != qn) + { + t = &(link->a.a[qn]); + for (i = 0, u_dis = (uint64_t)-1; i < t->e.n; i++) + { + if(t->e.a[i].del || t->e.a[i].uID != tn) continue; + u_dis = (t->e.a[i].dis ==(uint64_t)-1? (uint64_t)-1 : t->e.a[i].dis>>3); + break; + } + + if(u_dis == (uint64_t)-1) + { + kv_pushp(u_trans_t, k_trans, &p); + p->qn = qn; p->tn = tn; p->occ = (k-l); + kv_pushp(u_trans_t, k_trans, &p); + p->qn = tn; p->tn = qn; p->occ = (k-l); + } + else + { + occ[qn] += (k-l); occ[tn] += (k-l); + } + } + l = k; + } + } + } + + + radix_sort_u_trans_m(k_trans.a, k_trans.a + k_trans.n); + + for (k = 1, l = 0, m = 0; k <= k_trans.n; ++k) + { + if (k == k_trans.n || k_trans.a[l].qn != k_trans.a[k].qn || k_trans.a[l].tn != k_trans.a[k].tn) //same qn and tn + { + if(k - l > 2) fprintf(stderr, "ERROR-3\n"); + for (i = l, h_occ = 0; i < k; i++) + { + h_occ += k_trans.a[i].occ; + } + + k_trans.a[m] = k_trans.a[l]; + // k_trans.a[m].occ = ((uint32_t)-1) - h_occ; + k_trans.a[m].occ = h_occ; + + if(h_occ > thres || h_occ >= (occ[k_trans.a[m].qn]*rate) || h_occ >= (occ[k_trans.a[m].tn]*rate)) + { + e = get_hc_edge(link, k_trans.a[m].qn, k_trans.a[m].tn, 0); + if(e->dis != (uint64_t)-1) fprintf(stderr, "ERROR-3-0\n"); + e->is_cc = 1; + + e = get_hc_edge(link, k_trans.a[m].tn, k_trans.a[m].qn, 0); + if(e->dis != (uint64_t)-1) fprintf(stderr, "ERROR-3-0\n"); + e->is_cc = 1; + } + m++; + l = k; + } + } + k_trans.n = m; + + kv_destroy(k_trans); free(occ); +} + +void measure_distance(ha_ug_index* idx, const ma_ug_t* ug, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, kv_u_trans_t *ta) +{ + // double index_time = yak_realtime(); + MT M; + init_MT(&M, ug->g->n_seq<<1); + uint64_t uID_bits; + for (uID_bits=1; (uint64_t)(1<u.n; uID_bits++); + uint64_t k, i, shif = 64 - uID_bits, beg, end, t_d; + if(hits) + { + for (k = 0; k < hits->a.n; ++k) + { + beg = ((hits->a.a[k].s<<1)>>shif); + end = ((hits->a.a[k].e<<1)>>shif); + + if(beg == end) continue; + if(IF_HOM(beg, *bub)) continue; + if(IF_HOM(end, *bub)) continue; + + t_d = (uint64_t)-1; + push_hc_edge(&(link->a.a[beg]), end, 0, 0, &t_d); + push_hc_edge(&(link->a.a[end]), beg, 0, 0, &t_d); + } + } + else + { + for (k = 0; k < ug->g->n_seq; ++k) + { + if(IF_HOM(k, *bub)) continue; + for (i = 0; i < ug->g->n_seq; ++i) + { + if(i == k || IF_HOM(i, *bub)) continue; + t_d = (uint64_t)-1; + push_hc_edge(&(link->a.a[i]), k, 0, 0, &t_d); + push_hc_edge(&(link->a.a[k]), i, 0, 0, &t_d); + } + } + } + + asg_t *copy_sg = copy_read_graph(ug->g); + + update_ug_by_trans(copy_sg, ta); + // update_ug_by_tigs(copy_sg, link); + all_pair_shortest_path(copy_sg, link, &M); + fill_utg_distance_multi(copy_sg, link, &M, bub); + update_containment_distance(copy_sg, ta, link); + // update_dis_connected_gfa(copy_sg, link, &M); + asg_destroy(copy_sg); + destory_MT(&M); + + for (i = 0; i < link->a.n; i++) + { + for (k = 0; k < link->a.a[i].e.n; k++) + { + link->a.a[i].e.a[k].is_cc = 0; + if(link->a.a[i].e.a[k].del) continue; + if(link->a.a[i].e.a[k].dis == (uint64_t)-1) continue; + link->a.a[i].e.a[k].is_cc = 1; + } + } + + // filter_disconnect_edges(idx, hits, link, bub, 1, 0.01); + // fprintf(stderr, "[M::%s::%.3f] ==> Hi-C linkages have been counted\n", __func__, yak_realtime()-index_time); + return; +} + +void set_reverse_links(uint32_t* bub, uint32_t n, kvec_t_u32_warp* reach, uint32_t root, hc_links* link) +{ + uint64_t i, k, d = RC_0; + uint32_t v; + for (i = 0; i < n; i++) + { + v = bub[i]>>1; + if(v == root) continue; + for (k = 0; k < reach->a.n; k++) + { + if(v == reach->a.a[k]) break; + } + + ///if(k == reach->a.n && reach->a.n > 0) + if(k == reach->a.n) + { + push_hc_edge(&(link->a.a[root]), v, 1, 1, &d); + push_hc_edge(&(link->a.a[v]), root, 1, 1, &d); + } + } + +} + +void collect_hc_reverse_links(hc_links* link, ma_ug_t* ug, bubble_type* bub) +{ + uint64_t i, j, k, d = RC_0, m, pre; + uint32_t beg, sink, n, v, *a = NULL; + kvec_t_u32_warp stack, result; + hc_edge *e = NULL; + kv_init(stack.a); kv_init(result.a); + ///clean all reverse overlaps within bubbles + ///might be wrong + for (i = 0; i < bub->f_bub; i++) + { + get_bubbles(bub, i, &beg, &sink, &a, &n, NULL); + for (k = 0; k < n; k++) + { + v = a[k]>>1; + for (j = 0; j < link->a.a[v].f.n; j++) + { + if(link->a.a[v].f.a[j].del) continue; + e = get_hc_edge(link, link->a.a[v].f.a[j].uID, v, 1); + e->del = 1; + } + link->a.a[v].f.n = 0; + } + + v = beg>>1; + if(IF_HOM(v, *bub)) + { + for (j = 0; j < link->a.a[v].f.n; j++) + { + if(link->a.a[v].f.a[j].del) continue; + e = get_hc_edge(link, link->a.a[v].f.a[j].uID, v, 1); + e->del = 1; + } + link->a.a[v].f.n = 0; + } + + v = sink>>1; + if(IF_HOM(v, *bub)) + { + for (j = 0; j < link->a.a[v].f.n; j++) + { + if(link->a.a[v].f.a[j].del) continue; + e = get_hc_edge(link, link->a.a[v].f.a[j].uID, v, 1); + e->del = 1; + } + link->a.a[v].f.n = 0; + } + } + + for (i = 0; i < bub->f_bub; i++) + { + get_bubbles(bub, i, &beg, &sink, &a, &n, NULL); + if(n == 2) + { + push_hc_edge(&(link->a.a[a[0]>>1]), a[1]>>1, 1, 1, &d); + push_hc_edge(&(link->a.a[a[1]>>1]), a[0]>>1, 1, 1, &d); + continue; + } + ///for complex bubbles, shouldn't have any assumption + ///if(i >= bub->s_bub) continue; + + beg = beg>>1; sink = sink>>1; + for (k = 0; k < n; k++) + { + v = a[k]>>1; + dfs_bubble(ug->g, &stack, &result, v, beg, sink); + set_reverse_links(a, n, &result, v, link); + } + } + + uint8_t* vis_flag = NULL; + MALLOC(vis_flag, ug->g->n_seq*2); + ///for broken bubbles + for (i = bub->f_bub; i < bub->f_bub + bub->b_bub; i++) + { + get_bubbles(bub, i, &beg, &sink, &a, &n, NULL); + + for (k = 0; k < n; k++) + { + v = a[k]; + dfs_bubble_broken(ug->g, &stack, &result, vis_flag, ug->g->n_seq*2, v, beg, sink); + set_reverse_links(a, n, &result, v>>1, link); + } + } + + kv_destroy(stack.a); kv_destroy(result.a); free(vis_flag); + + + for (i = 0; i < link->a.n; i++) + { + for (k = m = 0; k < link->a.a[i].f.n; k++) + { + if(link->a.a[i].f.a[k].del) continue; + link->a.a[i].f.a[m] = link->a.a[i].f.a[k]; + m++; + } + link->a.a[i].f.n = m; + radix_sort_hc_edge_u(link->a.a[i].f.a, link->a.a[i].f.a + link->a.a[i].f.n); + + for (k = m = 0, pre = (uint64_t)-1; k < link->a.a[i].f.n; k++) + { + if(link->a.a[i].f.a[k].del) continue; + if(link->a.a[i].f.a[k].uID == pre) + { + if(link->a.a[i].f.a[k].dis == RC_0) link->a.a[i].f.a[m-1].dis = RC_0; + continue; + } + + pre = link->a.a[i].f.a[k].uID; + link->a.a[i].f.a[m] = link->a.a[i].f.a[k]; + m++; + } + link->a.a[i].f.n = m; + radix_sort_hc_edge_d(link->a.a[i].f.a, link->a.a[i].f.a + link->a.a[i].f.n); + } + + + // hc_edge *e = NULL; + // for (i = 0; i < link->a.n; i++) + // { + // for (k = 0; k < link->a.a[i].f.n; k++) + // { + // if(link->a.a[i].f.a[k].del) continue; + // e = get_hc_edge(link, link->a.a[i].f.a[k].uID, i, 1); + // if(e == NULL) fprintf(stderr, "ERROR\n"); + // } + // } + +} + +void write_hc_links(hc_links* link, const char *fn) +{ + uint64_t k; + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.hic.link.bin", fn); + FILE* fp = fopen(buf, "w"); + + fwrite(&link->a.n, sizeof(link->a.n), 1, fp); + for (k = 0; k < link->a.n; k++) + { + fwrite(&link->a.a[k].e.n, sizeof(link->a.a[k].e.n), 1, fp); + fwrite(link->a.a[k].e.a, sizeof(hc_edge), link->a.a[k].e.n, fp); + + fwrite(&link->a.a[k].f.n, sizeof(link->a.a[k].f.n), 1, fp); + fwrite(link->a.a[k].f.a, sizeof(hc_edge), link->a.a[k].f.n, fp); + } + + fwrite(&link->enzymes.n, sizeof(link->enzymes.n), 1, fp); + fwrite(link->enzymes.a, sizeof(uint64_t), link->enzymes.n, fp); + + fclose(fp); + free(buf); + fprintf(stderr, "[M::%s::] ==> Hi-C linkages have been written\n", __func__); +} + +int load_hc_links(hc_links* link, const char *fn) +{ + uint64_t k, flag = 0; + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.hic.link.bin", fn); + + FILE* fp = NULL; + fp = fopen(buf, "r"); + if(!fp) + { + free(buf); + return 0; + } + + + kv_init(link->a); + flag += fread(&link->a.n, sizeof(link->a.n), 1, fp); + link->a.m = link->a.n; CALLOC(link->a.a, link->a.n); + for (k = 0; k < link->a.n; k++) + { + flag += fread(&link->a.a[k].e.n, sizeof(link->a.a[k].e.n), 1, fp); + link->a.a[k].e.m = link->a.a[k].e.n; MALLOC(link->a.a[k].e.a, link->a.a[k].e.n); + flag += fread(link->a.a[k].e.a, sizeof(hc_edge), link->a.a[k].e.n, fp); + + flag += fread(&link->a.a[k].f.n, sizeof(link->a.a[k].f.n), 1, fp); + link->a.a[k].f.m = link->a.a[k].f.n; MALLOC(link->a.a[k].f.a, link->a.a[k].f.n); + flag += fread(link->a.a[k].f.a, sizeof(hc_edge), link->a.a[k].f.n, fp); + } + + kv_init(link->enzymes); + flag += fread(&link->enzymes.n, sizeof(link->enzymes.n), 1, fp); + link->enzymes.m = link->enzymes.n; MALLOC(link->enzymes.a, link->enzymes.n); + flag += fread(link->enzymes.a, sizeof(uint64_t), link->enzymes.n, fp); + + fclose(fp); + free(buf); + fprintf(stderr, "[M::%s::] ==> Hi-C linkages have been loaded\n", __func__); + return 1; +} + +void write_hc_hits(kvec_pe_hit* hits, ma_ug_t* ug, const char *fn) +{ + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.hic.lk.bin", fn); + FILE* fp = fopen(buf, "w"); + + fwrite(&hits->a.n, sizeof(hits->a.n), 1, fp); + fwrite(hits->a.a, sizeof(pe_hit), hits->a.n, fp); + write_dbug(ug, fp); + + fclose(fp); + free(buf); +} + +void write_hc_hits_v14(kvec_pe_hit_hap* i_hits, const char *fn) +{ + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.v14.hic.lk.bin", fn); + FILE* fp = fopen(buf, "w"); + kvec_pe_hit hits; + kv_init(hits.a); + uint64_t i, m_u = (uint64_t)-1, m_m = (uint64_t)-1; + pe_hit* p = NULL; + for (i = 0; i < i_hits->n; i++) + { + if(i_hits->a[i].occ1 == 1 && i_hits->a[i].occ2 == 1) + { + kv_pushp(pe_hit, hits.a, &p); + p->id = i_hits->a[i].id; + p->s = i_hits->a[i].a[0]; + p->e = i_hits->a[i].a[1]; + m_u = i; + } + else + { + if(m_m == (uint64_t)-1) m_m = i; + } + } + fprintf(stderr, "m_u: %lu, m_m: %lu, n_u: %lu\n", m_u, m_m, i_hits->n_u); + + fwrite(&hits.a.n, sizeof(hits.a.n), 1, fp); + fwrite(hits.a.a, sizeof(pe_hit), hits.a.n, fp); + + kv_destroy(hits.a); + fclose(fp); + free(buf); + exit(1); +} + +#define pe_hit_hap_id_key(x) ((x).id) +KRADIX_SORT_INIT(pe_hit_hap_id, pe_hit_hap, pe_hit_hap_id_key, member_size(pe_hit_hap, id)) + +#define pe_hit_id_key(x) ((x).id) +KRADIX_SORT_INIT(pe_hit_id, pe_hit, pe_hit_id_key, member_size(pe_hit, id)) + +void debug_hc_hits_v14(kvec_pe_hit_hap* i_hits, const char *fn, const ha_ug_index* idx) +{ + uint64_t flag = 0; + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.v14.hic.lk.bin", fn); + kvec_pe_hit hits; + kv_init(hits.a); + FILE* fp = NULL; + fp = fopen(buf, "r"); + + kv_init(hits.a); + flag += fread(&hits.a.n, sizeof(hits.a.n), 1, fp); + hits.a.m = hits.a.n; MALLOC(hits.a.a, hits.a.n); + flag += fread(hits.a.a, sizeof(pe_hit), hits.a.n, fp); + + radix_sort_pe_hit_id(hits.a.a, hits.a.a + hits.a.n); + radix_sort_pe_hit_hap_id(i_hits->a, i_hits->a + i_hits->n_u); + + fprintf(stderr, "i_hits->n_u: %lu, hits.a.n: %lu\n", (uint64_t)i_hits->n_u, (uint64_t)hits.a.n); + + uint64_t i, k; + uint64_t i_beg_utg, i_beg_pos, i_beg_rev; + uint64_t i_end_utg, i_end_pos, i_end_rev; + uint64_t k_beg_utg, k_beg_pos, k_beg_rev; + uint64_t k_end_utg, k_end_pos, k_end_rev; + uint64_t i_id, k_id; + uint64_t same_occ = 0, diff_occ = 0, miss_occ = 0; + for (i = 0, k = 0; i < i_hits->n_u; i++) + { + i_beg_rev = get_pe_s(i_hits->a[i])>>63; + i_beg_utg = ((get_pe_s(i_hits->a[i])<<1)>>(64 - idx->uID_bits)); + i_beg_pos = get_pe_s(i_hits->a[i]) & idx->pos_mode; + + i_end_rev = get_pe_e(i_hits->a[i])>>63; + i_end_utg = ((get_pe_e(i_hits->a[i])<<1)>>(64 - idx->uID_bits)); + i_end_pos = get_pe_e(i_hits->a[i]) & idx->pos_mode; + + i_id = i_hits->a[i].id; + for (; k < hits.a.n; k++) + { + k_beg_rev = hits.a.a[k].s>>63; + k_beg_utg = ((hits.a.a[k].s<<1)>>(64 - idx->uID_bits)); + k_beg_pos = hits.a.a[k].s & idx->pos_mode; + + k_end_rev = hits.a.a[k].e>>63; + k_end_utg = ((hits.a.a[k].e<<1)>>(64 - idx->uID_bits)); + k_end_pos = hits.a.a[k].e & idx->pos_mode; + + k_id = hits.a.a[k].id; + + if(k_id > i_id) + { + miss_occ++; + fprintf(stderr, "\n[MISS]rid=%lu\n", i_id); + fprintf(stderr, "********v0.15********\n"); + fprintf(stderr, "beg_rev: %lu, beg_utg: %lu, beg_pos: %lu\n", + i_beg_rev, i_beg_utg, i_beg_pos); + fprintf(stderr, "end_rev: %lu, end_utg: %lu, end_pos: %lu\n", + i_end_rev, i_end_utg, i_end_pos); + break; + } + + if(k_id == i_id) + { + if(get_pe_s(i_hits->a[i]) == hits.a.a[k].s && get_pe_e(i_hits->a[i]) == hits.a.a[k].e) + { + same_occ++; + // fprintf(stderr, "\n[SAME]rid=%lu\n", i_id); + // fprintf(stderr, "********v0.15********\n"); + // fprintf(stderr, "beg_rev: %lu, beg_utg: %lu, beg_pos: %lu\n", + // i_beg_rev, i_beg_utg, i_beg_pos); + // fprintf(stderr, "end_rev: %lu, end_utg: %lu, end_pos: %lu\n", + // i_end_rev, i_end_utg, i_end_pos); + // fprintf(stderr, "********v0.14********\n"); + // fprintf(stderr, "beg_rev: %lu, beg_utg: %lu, beg_pos: %lu\n", + // k_beg_rev, k_beg_utg, k_beg_pos); + // fprintf(stderr, "end_rev: %lu, end_utg: %lu, end_pos: %lu\n", + // k_end_rev, k_end_utg, k_end_pos); + } + else + { + diff_occ++; + fprintf(stderr, "\n[DIFF]rid=%lu\n", i_id); + fprintf(stderr, "********v0.15********\n"); + fprintf(stderr, "beg_rev: %lu, beg_utg: %lu, beg_pos: %lu\n", + i_beg_rev, i_beg_utg, i_beg_pos); + fprintf(stderr, "end_rev: %lu, end_utg: %lu, end_pos: %lu\n", + i_end_rev, i_end_utg, i_end_pos); + fprintf(stderr, "********v0.14********\n"); + fprintf(stderr, "beg_rev: %lu, beg_utg: %lu, beg_pos: %lu\n", + k_beg_rev, k_beg_utg, k_beg_pos); + fprintf(stderr, "end_rev: %lu, end_utg: %lu, end_pos: %lu\n", + k_end_rev, k_end_utg, k_end_pos); + } + break; + } + } + } + + fprintf(stderr, "same_occ: %lu, diff_occ: %lu, miss_occ: %lu", same_occ, diff_occ, miss_occ); + + + kv_destroy(hits.a); + fclose(fp); + free(buf); + exit(1); +} + +int load_hc_hits(kvec_pe_hit* hits, ma_ug_t* ug, const char *fn) +{ + uint64_t flag = 0; + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.hic.lk.bin", fn); + + FILE* fp = NULL; + fp = fopen(buf, "r"); + if(!fp) + { + free(buf); + return 0; + } + + + kv_init(hits->a); + flag += fread(&hits->a.n, sizeof(hits->a.n), 1, fp); + hits->a.m = hits->a.n; MALLOC(hits->a.a, hits->a.n); + flag += fread(hits->a.a, sizeof(pe_hit), hits->a.n, fp); + free(buf); + + if(!test_dbug(ug, fp)) + { + free(hits->a.a); + kv_init(hits->a); + fclose(fp); + fprintf(stderr, "[M::%s::] ==> Renew Hi-C linkages\n", __func__); + return 0; + } + + fclose(fp); + fprintf(stderr, "[M::%s::] ==> Hi-C linkages have been loaded\n", __func__); + return 1; +} + +inline int get_phase_status(H_partition* hap, uint32_t uID) +{ + int d = -2; + if(hap->hap[uID] & hap->m[0]) d = 1; + if(hap->hap[uID] & hap->m[1]) d = -1; + if(hap->hap[uID] & hap->m[2]) d = 0; + return d; +} + +inline uint32_t get_phase_group(H_partition* hap, uint32_t uID) +{ + return hap->hap[uID]>>hap->label_shift; +} + +void print_hc_links(hc_links* link, int dir, H_partition* hap) +{ + uint64_t i, k; + if(dir == 0) + { + double f_w, r_w; + for (i = 0; i < link->a.n; ++i) + { + f_w = r_w = 0; + for (k = 0; k < link->a.a[i].e.n; k++) + { + if(link->a.a[i].e.a[k].del) continue; + fprintf(stderr, "s-utg%.6dl(%c)\tCLU:%d:%u\td-utg%.6dl(%c)\tCLU:%d:%u\t%lu\t%c\t%f\te\n", + (int)(i+1), "01"[!!(link->a.a[i].e.a[k].dis&(uint64_t)2)], + get_phase_status(hap, i), hap->hap[i]>>3, + (int)(link->a.a[i].e.a[k].uID+1), "01"[!!(link->a.a[i].e.a[k].dis&(uint64_t)1)], + get_phase_status(hap, link->a.a[i].e.a[k].uID), hap->hap[link->a.a[i].e.a[k].uID]>>3, + link->a.a[i].e.a[k].dis == (uint64_t)-1? (uint64_t)-1 : link->a.a[i].e.a[k].dis>>3, + "fb"[!!(link->a.a[i].e.a[k].dis&(uint64_t)4)], link->a.a[i].e.a[k].weight); + if(get_phase_status(hap, i) == get_phase_status(hap, link->a.a[i].e.a[k].uID)) + { + f_w += link->a.a[i].e.a[k].weight; + } + else + { + r_w += link->a.a[i].e.a[k].weight; + } + } + + // fprintf(stderr, "self-utg%.6dl\tFW:%f\tRW:%f\tRT:%f\n**************************************************\n", + // (int)(i+1), f_w, r_w, (f_w+r_w) != 0? r_w/(f_w+r_w):0); + } + } + + + if(dir == 1) + { + for (i = 0; i < link->a.n; ++i) + { + for (k = 0; k < link->a.a[i].f.n; k++) + { + if(link->a.a[i].f.a[k].del) continue; + fprintf(stderr, "s-utg%.6d\td-utg%.6d\t%lu\te\n", + (int)(i+1), (int)(link->a.a[i].f.a[k].uID+1), link->a.a[i].f.a[k].dis); + } + } + } +} + +void normalize_hc_links(hc_links* link) +{ + uint64_t i, k; + for (i = 0; i < link->a.n; ++i) + { + for (k = 0; k < link->a.a[i].e.n; k++) + { + if(link->a.a[i].e.a[k].del) continue; + link->a.a[i].e.a[k].weight *= 100; + link->a.a[i].e.a[k].weight /= (double)(MIN(link->enzymes.a[i], link->enzymes.a[link->a.a[i].e.a[k].uID])); + ///link->a.a[i].e.a[k].weight /= (double)(link->enzymes.a[i] + link->enzymes.a[link->a.a[i].e.a[k].uID]); + } + } +} + +hc_edge* get_rGraph_edge(min_cut_t* x, uint64_t src, uint64_t dest) +{ + if(src >= x->rGraph.n) return NULL; + uint64_t i; + for (i = 0; i < x->rGraph.a[src].n; i++) + { + if(x->rGraph.a[src].a[i].del) continue; + if(x->rGraph.a[src].a[i].uID == dest) return &(x->rGraph.a[src].a[i]); + } + return NULL; +} + +void init_min_cut_t(min_cut_t* x, hc_links* link, const bubble_type* bub, const ma_ug_t *ug) +{ + uint64_t utg_num = link->a.n, i, k, u, v; + x->n = utg_num; + x->n_e = x->c_e = 0; + + kv_malloc(x->rGraphSet, utg_num); x->rGraphSet.n = utg_num; + ///must utg_num<<1) + kv_malloc(x->rGraphVis, utg_num); x->rGraphVis.n = utg_num; + kv_malloc(x->utgVis, utg_num); x->utgVis.n = utg_num; + kv_malloc(x->bmerVis, utg_num); x->bmerVis.n = utg_num; + kv_malloc(x->order, utg_num); x->order.n = utg_num; + kv_malloc(x->parent, utg_num); x->parent.n = utg_num; + kv_malloc(x->p_weight, utg_num); x->p_weight.n = utg_num; + ///uresolved BUGs, if use kv_resize segfault; if use kv_malloc, work????? + kv_malloc(x->rGraph, utg_num); x->rGraph.n = utg_num; + // kv_init(x->rGraph); kv_resize(hc_edge_warp, x->rGraph, utg_num); x->rGraph.n = utg_num; + x->enzymes = link->enzymes.a; + init_pdq(&(x->pq), utg_num<<1); + + //must be utg_num + 2 since we may need to add fake nodes + for (i = 1; (uint64_t)(1<uID_mode = ((uint64_t)-1) >> (64-i); + x->uID_shift = i; + for (i = 0; i < utg_num; i++) + { + ///x->order.a[i] = link->a.a[i].f.n; + ///x->order.a[i] = ug->u.a[i].len; + x->order.a[i] = x->enzymes[i]; + x->order.a[i] <<= x->uID_shift; + x->order.a[i] |= (uint64_t)(i & x->uID_mode); + + x->rGraphSet.a[i] = 0; + x->rGraphVis.a[i] = 0; + x->utgVis.a[i] = 0; + x->bmerVis.a[i] = 0; + x->parent.a[i] = (uint32_t)-1; + + ///uresolved BUGs, if use kv_resize segfault; if use kv_malloc, work????? + // kv_init(x->rGraph.a[i]); kv_resize(hc_edge, x->rGraph.a[i], link->a.a[i].e.n); + kv_malloc(x->rGraph.a[i], link->a.a[i].e.n); + x->rGraph.a[i].n = link->a.a[i].e.n; + + if(x->rGraph.a[i].n) + { + for (k = 0; k < x->rGraph.a[i].n; k++) + { + ///kv_push(hc_edge, x->rGraph.a[i], link->a.a[i].e.a[k]); + x->rGraph.a[i].a[k] = link->a.a[i].e.a[k]; + x->n_e++; + + if((x->rGraph.a[i].a[k].weight == 0) || IF_HOM(x->rGraph.a[i].a[k].uID, *bub) + || IF_HOM(i, *bub) || (x->rGraph.a[i].a[k].del)) + { + x->rGraph.a[i].a[k].del = 1; + x->n_e--; + } + } + } + } + + hc_edge *p = NULL; + for (i = 0; i < utg_num; i++) + { + v = i; + for (k = 0; k < link->a.a[v].f.n; k++) + { + if(link->a.a[v].f.a[k].del) continue; + u = link->a.a[v].f.a[k].uID; + + + p = get_rGraph_edge(x, v, u); + if(p) + { + p->del = 1; + x->n_e--; + } + + + p = get_rGraph_edge(x, u, v); + if(p) + { + p->del = 1; + x->n_e--; + } + } + } + + x->q = kdq_init(uint64_t); + radix_sort_hc64(x->order.a, x->order.a + x->order.n); + + x->b_mer = asm_opt.bub_mer_length; + ///fprintf(stderr, "[M::%s]\n", __func__); + ///exit(0); +} + +void destory_min_cut_t(min_cut_t* x) +{ + kv_destroy(x->order); + kv_destroy(x->parent); + kv_destroy(x->p_weight); + kv_destroy(x->rGraphSet); + kv_destroy(x->rGraphVis); + kv_destroy(x->utgVis); + kv_destroy(x->bmerVis); + destory_pdq(&(x->pq)); + uint64_t i; + for (i = 0; i < x->rGraph.m; i++) + { + kv_destroy(x->rGraph.a[i]); + } + kv_destroy(x->rGraph); + kdq_destroy(uint64_t, x->q); +} + +void reset_min_cut_t(min_cut_t* x, hc_links* link) +{ + ///no need to reset parent[] and q + uint64_t i, j; + ///important to have this line + x->bmerVis.n = x->parent.n = x->p_weight.n = x->order.n = x->rGraph.n = x->rGraphVis.n = x->rGraphSet.n = link->a.n; + kdq_clear(x->q); + + for (i = 0; i < x->rGraphSet.n; i++) + { + x->rGraphVis.a[i] = 0; + ///x->bmerVis.a[i] = 0; + ///important to have this line + x->rGraph.a[i].n = link->a.a[i].e.n; + + if(x->rGraphSet.a[i] == 0) continue; + for (j = 0; j < x->rGraph.a[i].n; j++) + { + x->rGraph.a[i].a[j].weight = link->a.a[i].e.a[j].weight; + } + x->rGraphSet.a[i] = 0; + } +} + +void update_link_by_min_cut_t(min_cut_t* x, hc_links* link) +{ + uint64_t i, j; + + for (i = 0; i < link->a.n; i++) + { + for (j = 0; j < link->a.a[i].e.n; j++) + { + link->a.a[i].e.a[j].del = x->rGraph.a[i].a[j].del; + } + } +} + +uint64_t add_mul_convex(min_cut_t* x, uint64_t* a, uint64_t n) +{ + if(n == 0) return (uint64_t)-1; + if(n == 1) return a[0]; + kv_push(uint8_t, x->rGraphSet, 0); + kv_push(uint8_t, x->rGraphVis, 0); + kv_push(uint8_t, x->bmerVis, 0); + kv_push(uint32_t, x->parent, 0); + kv_push(double, x->p_weight, 0); + kv_resize(hc_edge_warp, x->rGraph, x->rGraph.n+1); + kv_init(x->rGraph.a[x->rGraph.n]); + uint64_t i, k; + hc_edge t; + for (i = 0; i < n; i++) + { + ///t.uID = a[i]; t.del = t.enzyme = t.weight = 0; + t.uID = a[i]; t.del = t.weight = 0; + for (k = 0; k < x->rGraph.a[a[i]].n; k++) + { + if(x->rGraph.a[a[i]].a[k].del) continue; + t.weight += x->rGraph.a[a[i]].a[k].weight; + } + kv_push(hc_edge, x->rGraph.a[x->rGraph.n], t); + t.uID = x->rGraph.n; + kv_push(hc_edge, x->rGraph.a[a[i]], t); + } + + x->rGraph.n++; + return x->rGraph.n - 1; +} + +void get_s_t(min_cut_t* x, hc_links* link, uint64_t uID, uint64_t* src, uint64_t* dest, kvec_t_u64_warp* buff) +{ + buff->a.n = 0; (*src) = (*dest) = (uint64_t)-1; + if(link->a.a[uID].f.n == 0) return; + (*src) = uID; + + uint64_t i, n; + for (i = 0, n = 0; i < link->a.a[uID].f.n; i++) + { + if(link->a.a[uID].f.a[i].del) continue; + kv_push(uint64_t, buff->a, link->a.a[uID].f.a[i].uID); + (*dest) = link->a.a[uID].f.a[i].uID; + n++; + } + if(n == 1 || n == 0) return; + (*dest) = add_mul_convex(x, buff->a.a, buff->a.n); +} + +uint64_t bfs_flow(uint64_t src, uint64_t dest, min_cut_t* x, kvec_t_u64_warp* buff) +{ + uint64_t *p = NULL, v, u, i; + if(dest != (uint64_t)-1) memset(x->rGraphVis.a, 0, x->rGraphVis.n); + + kdq_push(uint64_t, x->q, src); + if(buff) kv_push(uint64_t, buff->a, src); + + x->rGraphVis.a[src] = 1; + x->parent.a[src] = (uint32_t)-1; + + while (1) + { + p = kdq_shift(uint64_t, x->q); + if(!p) break; + v = *p; + if(v == dest) return 1; + for (i = 0; i < x->rGraph.a[v].n; i++) + { + if(x->rGraph.a[v].a[i].del) continue; + if(x->rGraph.a[v].a[i].weight == 0) continue; + u = x->rGraph.a[v].a[i].uID; + if(x->rGraphVis.a[u]) continue; + if(!x->bmerVis.a[u]) continue; + + x->parent.a[u] = v; + x->p_weight.a[u] = x->rGraph.a[v].a[i].weight; + + kdq_push(uint64_t, x->q, u); + if(buff) kv_push(uint64_t, buff->a, u); + ///set u or v to be 1? doesn't matter + x->rGraphVis.a[u] = 1; + } + } + + return 0; +} + +uint64_t maxFlow(uint64_t src, uint64_t dest, min_cut_t* x) +{ + double flow = 0, max_flow = 0; + uint64_t v, u; + hc_edge *p; + + while (bfs_flow(src, dest, x, NULL)) + { + kdq_clear(x->q); + flow = DBL_MAX; + for (v = dest; v != src; v = x->parent.a[v]) + { + flow = MIN(flow, x->p_weight.a[v]); + } + + /*******************************for debug************************************/ + // if(src == 26818) fprintf(stderr, "***********flow: %f*********\n", flow); + /*******************************for debug************************************/ + + for (v = dest; v != src; v = x->parent.a[v]) + { + u = x->parent.a[v]; + p = get_rGraph_edge(x, u, v); + + /*******************************for debug************************************/ + // if(src == 26818) fprintf(stderr, "utg%.6lul (%f)\n", u+1, p->weight); + /*******************************for debug************************************/ + + p->weight -= flow; + p = get_rGraph_edge(x, v, u); + p->weight += flow; + x->rGraphSet.a[u] = x->rGraphSet.a[v] = 1; + } + + max_flow += flow; + } + + return (max_flow != 0); +} + +uint64_t print_path(uint64_t src, uint64_t dest, min_cut_t* x) +{ + double flow = 0, max_flow = 0; + uint64_t v, u; + hc_edge *p; + + if(bfs_flow(src, dest, x, NULL)) + { + kdq_clear(x->q); + flow = DBL_MAX; + for (v = dest; v != src; v = x->parent.a[v]) + { + flow = MIN(flow, x->p_weight.a[v]); + } + + /*******************************for debug************************************/ + fprintf(stderr, "***********flow: %f*********\n", flow); + /*******************************for debug************************************/ + + for (v = dest; v != src; v = x->parent.a[v]) + { + u = x->parent.a[v]; + p = get_rGraph_edge(x, u, v); + + /*******************************for debug************************************/ + fprintf(stderr, "utg%.6lul (%f)\n", u+1, p->weight); + /*******************************for debug************************************/ + } + + max_flow += flow; + } + + return (max_flow != 0); +} + +void print_src_dest(uint64_t src, min_cut_t* x, const char* command) +{ + uint64_t i; + fprintf(stderr, "********************\n%s\n", command); + if(src >= x->n) + { + for (i = 0; i < x->rGraph.a[src].n; i++) + { + if(x->rGraph.a[src].a[i].del) continue; + fprintf(stderr, "utg%.6ul\n", x->rGraph.a[src].a[i].uID + 1); + } + + } + else + { + fprintf(stderr, "utg%.6lul\n", src+1); + } + fprintf(stderr, "!!!!!!!!!!!!!!!!!!!!\n"); + +} + +void print_debug_rGraph(min_cut_t* x) +{ + fprintf(stderr, "******rGraph******\n"); + uint64_t i, j, u; + for (i = 0; i < x->rGraphVis.n; i++) + { + if(!x->bmerVis.a[i]) continue; + for (j = 0; j < x->rGraph.a[i].n; j++) + { + if(x->rGraph.a[i].a[j].del) continue; + u = x->rGraph.a[i].a[j].uID; + if(!x->bmerVis.a[u]) continue; + fprintf(stderr, "***utg%.6lul\tutg%.6lul\t%f\n", i+1, u+1, x->rGraph.a[i].a[j].weight); + } + } + fprintf(stderr, "******rGraph******\n"); +} + +void graph_cut(uint64_t src, uint64_t dest, min_cut_t* x) +{ + /*******************************for debug************************************/ + ///if(src == 45179) print_debug_rGraph(x); + /*******************************for debug************************************/ + if(maxFlow(src, dest, x)) + { + ///in the last time bfs of maxFlow, rGraphVis has already been set + uint64_t i, j, v, u; + hc_edge *p; + /*******************************for debug************************************/ + if(src == 45179) + ///if(src == 26818) + { + ///print_debug_rGraph(x); + print_src_dest(src, x, "src utg:"); + print_src_dest(dest, x, "dest utg:"); + } + /*******************************for debug************************************/ + for (i = 0; i < x->rGraphVis.n; i++) + { + if(x->rGraphVis.a[i] == 0) continue; + if(!x->bmerVis.a[i]) continue; + v = i; + for (j = 0; j < x->rGraph.a[i].n; j++) + { + if(x->rGraph.a[i].a[j].del) continue; + u = x->rGraph.a[i].a[j].uID; + if(x->rGraphVis.a[u]) continue; + if(!x->bmerVis.a[u]) continue; + /*******************************for debug************************************/ + if(src == 45179) fprintf(stderr, "utg%.6lul\tutg%.6lul\t%f\n", v+1, u+1, x->rGraph.a[i].a[j].weight); + /*******************************for debug************************************/ + ///delete + x->rGraph.a[i].a[j].del = 1; + ///delete + p = get_rGraph_edge(x, u, v); + p->del = 1; + x->c_e += 2; + } + + } + + /*******************************for debug************************************/ + ///if(src == 45179 || src == 31635) + // if(src == 26818) + // { + // fprintf(stderr, "hahahaha\n"); + // print_path(26818, 1143, x); + // } + /*******************************for debug************************************/ + } + /*******************************for debug************************************/ + ///if(src == 45179 || src == 31635) + // { + // print_src_dest(src, x, "++++++src utg:"); + // uint64_t m; + // for (m = 0; m < x->rGraph.a[src].n; m++) + // { + // if(x->rGraph.a[src].a[m].del) continue; + // fprintf(stderr, "src(utg%.6dl, enz:%lu)\tdes(utg%.6dl, enz:%lu)\t%f\n", + // (int)(src+1), x->enzymes[src], + // (int)(x->rGraph.a[src].a[m].uID+1), x->enzymes[x->rGraph.a[src].a[m].uID], + // x->rGraph.a[src].a[m].weight); + // } + // } + /*******************************for debug************************************/ +} + +void check_connective(min_cut_t* x, hc_links* link) +{ + double index_time = yak_realtime(); + kvec_t_u64_warp buff; + kv_init(buff.a); + uint64_t i, k, uID; + for (i = 0; i < x->n; i++) + { + uID = x->order.a[i] & x->uID_mode; + if(link->a.a[uID].f.n == 0) continue; + for (k = 0; k < link->a.a[uID].f.n; k++) + { + if(link->a.a[uID].f.a[k].del) continue; + if(x->utgVis.a[link->a.a[uID].f.a[k].uID] == 0) break; + } + if(k == link->a.a[uID].f.n) continue; + reset_min_cut_t(x, link); + get_s_t(x, link, uID, &(x->src), &(x->dest), &buff); + + bfs_flow(x->src, x->dest, x, NULL); + + x->utgVis.a[uID] = 1; + } + + //reset x.utgVis + memset(x->utgVis.a, 0, x->utgVis.n); + kv_destroy(buff.a); + fprintf(stderr, "[M::%s::%.3f] \n", __func__, yak_realtime()-index_time); +} + +void get_Connected_Components(min_cut_t* x) +{ + double index_time = yak_realtime(); + uint64_t i, j, k = 0, uID, e; + kvec_t_u64_warp buff; + kv_init(buff.a); + while (1) + { + for (i = 0; i < x->n; i++) + { + uID = x->order.a[i] & x->uID_mode; + if(x->rGraphVis.a[uID] == 0) break; + } + if(i < x->n) + { + e = buff.a.n = 0; + bfs_flow(uID, (uint64_t)-1, x, &buff); + for (i = 0; i < buff.a.n; i++) + { + for (j = 0; j < x->rGraph.a[buff.a.a[i]].n; j++) + { + if(x->rGraph.a[buff.a.a[i]].a[j].del == 0) e++; + } + } + e >>= 1; + if(buff.a.n > 1) + { + fprintf(stderr, "(%lu) Component: # nodes: %lu, # edges: %lu\n", + k, (uint64_t)buff.a.n, e); + } + k++; + } + else + { + break; + } + } + + kv_destroy(buff.a); + fprintf(stderr, "[M::%s::%.3f] # Connected Components: %lu\n", + __func__, yak_realtime()-index_time, k); +} + +void print_rGraph(min_cut_t* x) +{ + uint64_t i, k; + for (i = 0; i < x->rGraph.n; ++i) + { + for (k = 0; k < x->rGraph.a[i].n; k++) + { + if(x->rGraph.a[i].a[k].del) continue; + fprintf(stderr, "src(utg%.6dl, enz:%lu)\tdes(utg%.6dl, enz:%lu)\t%f\n", + (int)(i+1), x->enzymes[i], + (int)(x->rGraph.a[i].a[k].uID+1), x->enzymes[x->rGraph.a[i].a[k].uID], + x->rGraph.a[i].a[k].weight); + } + } +} + +int select_large_node(const ma_ug_t *ug, min_cut_t* x, +uint64_t src, uint64_t dest, uint64_t utg_thres, int weight_thres) +{ + if(src >= ug->u.n || dest >= ug->u.n) return 0; + if(ug->u.a[src].n < utg_thres || ug->u.a[dest].n < utg_thres) return 0; + + uint64_t k; + for (k = 0; k < x->rGraph.a[src].n; k++) + { + if(x->rGraph.a[src].a[k].del) continue; + if(x->rGraph.a[src].a[k].weight >= weight_thres) break; + } + if(k == x->rGraph.a[src].n) return 0; + + src = dest; + for (k = 0; k < x->rGraph.a[src].n; k++) + { + if(x->rGraph.a[src].a[k].del) continue; + if(x->rGraph.a[src].a[k].weight >= weight_thres) break; + } + if(k == x->rGraph.a[src].n) return 0; + + return 1; +} + +uint64_t inline set_dv(uint64_t v, uint64_t dis) +{ + dis <<= 32; dis |= v; + return dis; +} + +uint64_t select_bmer(uint32_t src, uint64_t k, const bubble_type* bub, min_cut_t* x, uint32_t bub_only) +{ + uint32_t beg, sink, n, *a; + uint32_t v, d, u, i, nv, b_mer_d, j; + asg_t *sg = bub->ug->g; + uint64_t *p = NULL; + asg_arc_t *av = NULL; + + memset(x->rGraphVis.a, 0, x->rGraphVis.n); + kdq_push(uint64_t, x->q, set_dv(src , 0)); + b_mer_d = 0; + + x->rGraphVis.a[src] = 1; + x->bmerVis.a[src] = 1; + + while (1) + { + p = kdq_shift(uint64_t, x->q); + if(!p) break; + v = (uint32_t)(*p); d = ((uint64_t)(*p))>>32; + + v = v<<1; + av = asg_arc_a(sg, v); + nv = asg_arc_n(sg, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + u = av[i].v>>1; + if(x->rGraphVis.a[u]) continue; + x->rGraphVis.a[u] = 1; + if(IF_HOM(u, *bub)) + { + if(d < k) kdq_push(uint64_t, x->q, set_dv(u, d+1)); + } + else + { + kdq_push(uint64_t, x->q, set_dv(u , d)); + b_mer_d = d; + if(IF_BUB(u, *bub) && x->bmerVis.a[u] == 0) + { + get_bubbles((bubble_type*)bub, bub->index[u], &beg, &sink, &a, &n, NULL); + for (j = 0; j < n; j++) x->bmerVis.a[(a[j]>>1)] = 1; + } + //must be here + if(bub_only == 0) x->bmerVis.a[u] = 1; + } + } + + + v = v + 1; + av = asg_arc_a(sg, v); + nv = asg_arc_n(sg, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + u = av[i].v>>1; + if(x->rGraphVis.a[u]) continue; + x->rGraphVis.a[u] = 1; + if(IF_HOM(u, *bub)) + { + if(d < k) kdq_push(uint64_t, x->q, set_dv(u, d+1)); + } + else + { + kdq_push(uint64_t, x->q, set_dv(u , d)); + b_mer_d = d; + if(IF_BUB(u, *bub) && x->bmerVis.a[u] == 0) + { + get_bubbles((bubble_type*)bub, bub->index[u], &beg, &sink, &a, &n, NULL); + for (j = 0; j < n; j++) x->bmerVis.a[(a[j]>>1)] = 1; + } + //must be here + if(bub_only == 0) x->bmerVis.a[u] = 1; + } + } + } + + return b_mer_d; +} + +void select_bmer_distance(uint32_t src, uint64_t k, const bubble_type* bub, min_cut_t* x, +uint32_t bub_only, uint32_t bub_extend) +{ + uint32_t beg, sink, n, *a; + asg_t *sg = bub->ug->g; + uint64_t v, u, i, j, nv, w, first = 1; + asg_arc_t *av = NULL; + reset_pdq(&(x->pq)); + + x->bmerVis.a[src>>1] = 1; + x->pq.dis.a[src] = 0; + push_pdq(&(x->pq), src, 0); + + while (pdq_cnt(x->pq) > 0) + { + pop_pdq(&(x->pq), &v, &w); + x->pq.vis.a[v] = 1; + if(x->pq.dis.a[v] > k) break; + + ///fprintf(stderr, "******utg%.6dl, dis: %lu\n", (int)((v>>1)+1), x->pq.dis.a[v]); + + if(IF_BUB(v>>1, *bub)) + { + if(bub_extend && x->bmerVis.a[v>>1] == 0) + { + get_bubbles((bubble_type*)bub, bub->index[v>>1], &beg, &sink, &a, &n, NULL); + for (j = 0; j < n; j++) x->bmerVis.a[(a[j]>>1)] = 1; + } + x->bmerVis.a[v>>1] = 1; + } + + if(IF_HET(v>>1, *bub) && bub_only == 0) x->bmerVis.a[v>>1] = 1; + + av = asg_arc_a(sg, v); + nv = asg_arc_n(sg, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + u = av[i].v; + w = (uint32_t)av[i].ul; + if(first) w = 0; + + if(x->pq.vis.a[u] == 0 && x->pq.dis.a[u] > x->pq.dis.a[v] + w) + { + x->pq.dis.a[u] = x->pq.dis.a[v] + w; + push_pdq(&(x->pq), u, x->pq.dis.a[u]); + } + } + + first = 0; + } +} + +void get_bmer_unitgs(min_cut_t* x, const bubble_type* bub, uint64_t k, uint64_t src) +{ + uint32_t beg, sink, n, *a; + if(!IF_BUB(src, *bub)) return; + get_bubbles((bubble_type*)bub, bub->index[src], &beg, &sink, &a, &n, NULL); + memset(x->bmerVis.a, 0, x->bmerVis.n); + ///select_bmer(src, k, bub, x, 1); + select_bmer_distance(beg^1, k, bub, x, 1, 1); + select_bmer_distance(sink^1, k, bub, x, 1, 1); +} + +min_cut_t* clean_hap(hc_links* link, bubble_type* bub, const ma_ug_t *ug) +{ + double index_time = yak_realtime(); + min_cut_t* x; CALLOC(x, 1); + kvec_t_u64_warp buff; + kv_init(buff.a); + init_min_cut_t(x, link, (const bubble_type*)bub, ug); + + // get_Connected_Components(&x); + // check_connective(&x, link); + // print_rGraph(&x); + + long long i; + uint64_t k, uID; + + ///for (i = 0; (uint64_t)i < x.n; i++) + for (i = x->n - 1; i >= 0; i--) + { + uID = x->order.a[i] & x->uID_mode; + ///fprintf(stderr, "uID: %lu, f.n: %lu\n", uID, (uint64_t)link->a.a[uID].f.n); + if(link->a.a[uID].f.n == 0) continue; + for (k = 0; k < link->a.a[uID].f.n; k++) + { + if(link->a.a[uID].f.a[k].del) continue; + if(x->utgVis.a[link->a.a[uID].f.a[k].uID] == 0) break; + } + ///fprintf(stderr, "k: %lu\n", k); + if(k == link->a.a[uID].f.n) continue; + reset_min_cut_t(x, link); + ///fprintf(stderr, "reset\n"); + get_s_t(x, link, uID, &(x->src), &(x->dest), &buff); + ///fprintf(stderr, "x.src: %lu, x.dest: %lu\n", x.src, x.dest); + ///Note: should only consider edges betweem bubbles, ignore edges to homo untigs + + /*******************************for debug************************************/ + ///if(!select_large_node(ug, &x, x.src, x.dest, 10, 0)) continue; + ///if(uID != 26818) continue; + //if(uID != 45179) continue; + ///memset(x.bmerVis.a, 1, x.bmerVis.n); + get_bmer_unitgs(x, bub, x->b_mer, x->src); + x->bmerVis.a[x->src] = x->bmerVis.a[x->dest] = 1; + /*******************************for debug************************************/ + + graph_cut(x->src, x->dest, x); + ///fprintf(stderr, "graph_cut\n"); + x->utgVis.a[uID] = 1; + ///exit(0); + } + + reset_min_cut_t(x, link); + + fprintf(stderr, "[M::%s::%.3f] # edges: %lu, # cutted edges: %lu\n", + __func__, yak_realtime()-index_time, x->n_e, x->c_e); + update_link_by_min_cut_t(x, link); + ///destory_min_cut_t(x); + kv_destroy(buff.a); + return x; +} + +void init_G_partition(G_partition* x, uint64_t n_utg) +{ + uint64_t i; + kv_init(*x); + MALLOC(x->index, n_utg); + for (i = 0; i < n_utg; i++) + { + x->index[i] = (uint32_t)-1; + } +} + +void reset_G_partition(G_partition* x, uint64_t n_utg) +{ + uint64_t i; + x->n = 0; + for (i = 0; i < n_utg; i++) + { + x->index[i] = (uint32_t)-1; + } +} + +void destory_G_partition(G_partition* x) +{ + uint64_t i; + for (i = 0; i < x->n; i++) + { + kv_destroy(x->a[i].a); + } + kv_destroy(*x); + free(x->index); +} + +double get_hc_weight(uint32_t query, uint32_t v0, uint32_t root, bub_p_t_warp *b, min_cut_t* x) +{ + if(v0 == root) return 0; + uint32_t v, u; + hc_edge *p = NULL; + double weight = 0; + v = v0; + do { + u = b->a[v].p; // u->v + p = get_rGraph_edge(x, query>>1, v>>1); + if(p) weight += p->weight; + v = u; + } while (v != root); + + return weight; +} + +void set_path(bub_p_t_warp *b, uint32_t root, uint8_t* flag, uint8_t label) +{ + uint32_t v, u; + ///v is the sink of this bubble + v = b->S.a[0]; + do { + u = b->a[v].p; // u->v + flag[v>>1] |= label; + v = u; + } while (v != root); + flag[b->S.a[0]>>1] = 0; +} + +uint64_t trace_phase_path(ma_ug_t *ug, uint32_t s, uint32_t d, bub_p_t_warp *b, min_cut_t* x, uint8_t* flag, uint8_t label) +{ + asg_t *g = ug->g; + if(g->seq[s>>1].del) return 0; // already deleted + if(get_real_length(g, s, NULL)<2) return 0; + uint32_t i, n_pending, is_first, to_replace, cur_nc, cur_uc, cur_ac, n_tips, tip_end, n_pop; + double cur_nh, cur_rate, max_rate; + ///S saves nodes with all incoming edges visited + b->S.n = b->T.n = b->b.n = b->e.n = 0; + ///for each node, b->a saves all related information + b->a[s].d = b->a[s].nc = b->a[s].ac = b->a[s].uc = 0; b->a[s].nh = 0; + ///b->S is the nodes with all incoming edges visited + kv_push(uint32_t, b->S, s); + n_pop = n_tips = n_pending = 0; + tip_end = (uint32_t)-1; + is_first = 1; + + do { + ///v is a node that all incoming edges have been visited + ///d is the distance from v0 to v + uint32_t v = kv_pop(b->S); + uint32_t d = b->a[v].d, nc = b->a[v].nc, uc = b->a[v].uc, ac = b->a[v].ac; + double nh = b->a[v].nh; + + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + for (i = 0; i < nv; ++i) { + uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l, not overlap length + bub_p_t *t = &b->a[w]; + //got a circle + if ((w>>1) == (s>>1)) goto pop_reset; + //important when poping at long untig graph + if(is_first) l = 0; + if (av[i].del) continue; + ///push the edge + kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); + + if (t->s == 0) + { // this vertex has never been visited + kv_push(uint32_t, b->b, w); // save it for revert + ///t->p is the parent node of + ///t->s = 1 means w has been visited + ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) + t->p = v, t->s = 1, t->d = d + l, t->nc = nc + ug->u.a[(w>>1)].n; + t->r = get_real_length(g, w^1, NULL); + /**need fix**/ + t->nh = nh + get_hc_weight(w, v, s, b, x); + t->ac = ac + (flag[(w>>1)] == 0? ug->u.a[(w>>1)].n : 0); + t->uc = uc + (flag[(w>>1)] != 0? ug->u.a[(w>>1)].n : 0); + ++n_pending; + } + else { + to_replace = 0; + + cur_nc = nc + ug->u.a[(w>>1)].n; + /**need fix**/ + cur_nh = nh + get_hc_weight(w, v, s, b, x); + cur_ac = ac + (flag[(w>>1)] == 0? ug->u.a[(w>>1)].n : 0); + cur_uc = uc + (flag[(w>>1)] != 0? ug->u.a[(w>>1)].n : 0); + cur_rate = ((double)(cur_ac)/(double)(cur_ac+cur_uc)); + max_rate = ((double)(t->ac)/(double)(t->ac+t->uc)); + + if(cur_rate > max_rate) + { + to_replace = 1; + } + else if(cur_rate == max_rate) + { + if(cur_nh > t->nh) + { + to_replace = 1; + } + else if(cur_nh == t->nh) + { + if(cur_nc > t->nc) + { + to_replace = 1; + } + else if(cur_nc == t->nc) + { + if(d + l > t->d) + { + to_replace = 1; + } + } + } + } + + + if(to_replace) + { + t->p = v; + t->nc = cur_nc; + t->nh = cur_nh; + t->ac = cur_ac; + t->uc = cur_uc; + } + + + if (d + l < t->d) t->d = d + l; // update dist + } + + if (--(t->r) == 0) { + uint32_t x = get_real_length(g, w, NULL); + if(x > 0) + { + kv_push(uint32_t, b->S, w); + } + else + { + ///at most one tip + if(n_tips != 0) goto pop_reset; + n_tips++; + tip_end = w; + } + --n_pending; + } + } + is_first = 0; + + + if(n_tips == 1) + { + if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) + { + ///sink is b.S.a[0] + kv_push(uint32_t, b->S, tip_end); + break; + } + else + { + goto pop_reset; + } + } + + if (i < nv || b->S.n == 0) goto pop_reset; + }while (b->S.n > 1 || n_pending); + + + n_pop = 1; + /**need fix**/ + set_path(b, s, flag, label); + pop_reset: + + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + bub_p_t *t = &b->a[b->b.a[i]]; + t->p = t->d = t->nc = t->ac = t->uc = t->r = t->s = 0; + t->nh = 0; + } + + return n_pop; +} + +inline void get_phased_block(G_partition* x, bubble_type* bub, uint64_t id, +uint32_t* beg, uint32_t* sink, uint32_t** h0, uint32_t* h0_n, uint32_t** h1, uint32_t* h1_n, +uint32_t* phased, uint32_t* bub_id) +{ + if(bub && beg && sink && bub_id) + { + (*bub_id) = (*beg) = (*sink) = (uint32_t)-1; + if(x->a[id].a.n > 0) + { + (*bub_id) = bub->index[x->a[id].a.a[0]]; + if(IF_BUB(x->a[id].a.a[0], *bub)) + { + (*beg) = bub->list.a[bub->num.a[(*bub_id)]]; + (*sink) = bub->list.a[bub->num.a[(*bub_id)] + 1]; + } + } + } + + (*h0) = x->a[id].a.a; + (*h0_n) = x->a[id].h[0]; + + (*h1) = x->a[id].a.a + x->a[id].h[0]; + (*h1_n) = x->a[id].h[1]; + if(phased) (*phased) = x->a[id].full_bub; + if((*h0_n) == 0) (*h0) = NULL; + if((*h1_n) == 0) (*h1) = NULL; +} + +double get_co_weight(uint32_t *query, uint32_t query_n, uint32_t *target, uint32_t target_n, min_cut_t* m) +{ + double weight = 0; + hc_edge *p = NULL; + uint32_t i, k; + for (i = 0; i < query_n; i++) + { + for (k = 0; k < target_n; k++) + { + p = get_rGraph_edge(m, query[i], target[k]); + if(p) weight += p->weight; + } + } + + return weight; +} + +void phase_bubble(uint64_t bid, bub_p_t_warp *b, bubble_type* bub, uint8_t* flag, const ma_ug_t *ug, +min_cut_t* m, hc_links* link, G_partition* x) +{ + #define HAP1_LAB 1 + #define HAP2_LAB 2 + + partition_warp* res = NULL; + kv_pushp(partition_warp, *x, &res); + memset(flag, 0, ug->g->n_seq); + uint32_t beg, sink, n, *a, i, k; + get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); + res->full_bub = 0; + trace_phase_path((ma_ug_t *)ug, beg, sink, b, m, flag, HAP1_LAB); + trace_phase_path((ma_ug_t *)ug, beg, sink, b, m, flag, HAP2_LAB); + kv_init(res->a); + for (i = 0; i < ug->g->n_seq; i++) + { + if(flag[i] & (uint8_t)HAP1_LAB) kv_push(uint32_t, res->a, i); + } + res->h[0] = res->a.n; + for (i = 0; i < ug->g->n_seq; i++) + { + if(flag[i] & (uint8_t)HAP2_LAB) kv_push(uint32_t, res->a, i); + } + res->h[1] = res->a.n - res->h[0]; + if(n == 2) res->full_bub = 1; + if(res->full_bub == 0) + { + double self = 0, intersec = 0; + uint32_t *h0 = NULL, *h1 = NULL; + h0 = res->a.a; h1 = res->a.a + res->h[0]; + self += get_co_weight(h0, res->h[0], h0, res->h[0], m); + self += get_co_weight(h1, res->h[1], h1, res->h[1], m); + + intersec += get_co_weight(h0, res->h[0], h1, res->h[1], m); + intersec = intersec * 2; + + if(self > intersec) res->full_bub = 1; + } + + if(res->full_bub == 0) + { + res->a.n = 0; + uint32_t v, u = 0, uv = UINT32_MAX, k_n, pre_n = x->n; + hc_linkeage* t = NULL; + x->n--; + for (i = 0; i < n; i++) + { + v = a[i]>>1; + t = &(link->a.a[v]); + for (k = k_n = 0; k < t->f.n; k++) + { + if(t->f.a[k].del) continue; + k_n++; + u = t->f.a[k].uID; + } + if(k_n != 1) continue; + + t = &(link->a.a[u]); + for (k = k_n = 0; k < t->f.n; k++) + { + if(t->f.a[k].del) continue; + k_n++; + uv = t->f.a[k].uID; + } + if(k_n != 1) continue; + if(uv != v) continue; + + ///avoid dups + for (k = 0; k < i; k++) + { + if((a[k]>>1) == u) break; + } + if(k < i) continue; + + + kv_pushp(partition_warp, *x, &res); + if(x->n > pre_n) kv_init(res->a); + res->full_bub = 0; + res->h[0] = res->h[1] = 1; + kv_push(uint32_t, res->a, v); + kv_push(uint32_t, res->a, u); + + for (k = 0; k < res->a.n; k++) + { + x->index[res->a.a[k]] = x->n-1; + } + } + } + else + { + for (k = 0; k < res->a.n; k++) + { + x->index[res->a.a[k]] = x->n-1; + } + } + + /*******************************for debug************************************/ + // for (i = 0; i < ug->g->n_seq; i++) + // { + // if(flag[i] & (uint8_t)3) + // { + // uint32_t k; + // for (k = 0; k < n; k++) + // { + // if((a[k]>>1) == i) + // { + // break; + // } + // } + + // if(k == n) fprintf(stderr, "ERROR5\n"); + // } + // } + /*******************************for debug************************************/ +} + +void print_phased_bubble(G_partition* x, bubble_type* bub, uint32_t utg_n) +{ + uint64_t i, k; + uint32_t beg = 0, sink = 0, h0_n, h1_n, *h0, *h1, full_bub = 0, bubID = 0; + + for (i = 0; i < x->n; i++) + { + get_phased_block(x, bub, i, &beg, &sink, &h0, &h0_n, &h1, &h1_n, &full_bub, &bubID); + + fprintf(stderr, "\n[%lu]\tbeg:utg%.6ul\tsink:utg%.6ul\tphased=%u\n", i, (beg>>1)+1, (sink>>1)+1, full_bub); + for (k = 0; k < h0_n; k++) + { + fprintf(stderr, "(0) utg%.6ul\n", h0[k] + 1); + } + + for (k = 0; k < h1_n; k++) + { + fprintf(stderr, "(1) utg%.6ul\n", h1[k] + 1); + } + + uint32_t n, *a; + get_bubbles(bub, bubID, &beg, &sink, &a, &n, NULL); + if(n > 2) fprintf(stderr, "complex\n"); + } + + /*******************************for debug************************************/ + for (i = 0; i < utg_n; i++) + { + if(x->index[i] == (uint32_t)-1) continue; + partition_warp* p = &(x->a[x->index[i]]); + for (k = 0; k < p->a.n; k++) + { + if(p->a.a[k] != i) break; + } + + if(k == p->a.n) fprintf(stderr, "ERROR\n"); + } + /*******************************for debug************************************/ +} + +G_partition* clean_bubbles(hc_links* link, bubble_type* bub, min_cut_t* m, const ma_ug_t *ug) +{ + double index_time = yak_realtime(); + uint64_t i; + bub_p_t_warp b; + memset(&b, 0, sizeof(bub_p_t_warp)); + CALLOC(b.a, ug->g->n_seq*2); + uint8_t* flag = NULL; + CALLOC(flag, ug->g->n_seq); + G_partition* x; CALLOC(x, 1); + init_G_partition(x, ug->g->n_seq); + + for (i = 0; i < bub->f_bub; i++) + { + phase_bubble(i, &b, bub, flag, ug, m, link, x); + } + + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + free(flag); + fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); + ///print_phased_bubble(x, bub, ug->g->n_seq); + + return x; +} + +uint64_t get_hic_distance(pe_hit* hit, hc_links* link, const ha_ug_index* idx, uint32_t *is_cc) +{ + uint64_t s_uid, s_dir, e_uid, e_dir, u_dis, k; + long long s_pos, e_pos; + s_uid = ((hit->s<<1)>>(64 - idx->uID_bits)); s_pos = hit->s & idx->pos_mode; + e_uid = ((hit->e<<1)>>(64 - idx->uID_bits)); e_pos = hit->e & idx->pos_mode; + if(s_uid == e_uid) + { + if(is_cc) (*is_cc) = 1; + return MAX(s_pos, e_pos) - MIN(s_pos, e_pos); + } + hc_linkeage* t = &(link->a.a[s_uid]); + for (k = 0; k < t->e.n; k++) + { + if(t->e.a[k].del || t->e.a[k].uID != e_uid) continue; + if(is_cc) (*is_cc) = t->e.a[k].is_cc; + s_dir = (!!(t->e.a[k].dis&(uint64_t)2)); + e_dir = (!!(t->e.a[k].dis&(uint64_t)1)); + u_dis = (t->e.a[k].dis ==(uint64_t)-1? (uint64_t)-1 : t->e.a[k].dis>>3); + // if(s_uid == 24684 && s_pos == 124953 && e_uid == 16950 && e_pos == 93039) + // { + // fprintf(stderr, "*****************s_dir: %lu, e_dir: %lu, u_dis: %lu\n", s_dir, e_dir, u_dis); + // } + if(u_dis == (uint64_t)-1) return (uint64_t)-1; + if(s_dir == 1) s_pos = (long long)idx->ug->g->seq[s_uid].len - s_pos - 1; + if(e_dir == 1) e_pos = (long long)idx->ug->g->seq[e_uid].len - e_pos - 1; + e_pos = e_pos + u_dis - (long long)idx->ug->g->seq[e_uid].len; + return MAX(s_pos, e_pos) - MIN(s_pos, e_pos); + } + + return (uint64_t)-1; +} + +hc_edge* get_hc_edge(hc_links* link, uint64_t src, uint64_t dest, uint64_t dir) +{ + if(src >= link->a.n) return NULL; + uint64_t i, n; + hc_edge* a = NULL; + if(dir == 0) + { + n = link->a.a[src].e.n; + a = link->a.a[src].e.a; + } + else + { + n = link->a.a[src].f.n; + a = link->a.a[src].f.a; + } + + for (i = 0; i < n; i++) + { + if(a[i].del) continue; + if(a[i].uID == dest) return &(a[i]); + } + + return NULL; +} + +inline double get_trans(const ha_ug_index* idx, uint64_t x) +{ + return idx->a*(x/idx->frac) + idx->b; +} + +inline double get_trans_weight_advance(const ha_ug_index* idx, uint64_t x, trans_idx* dis) +{ + long double rate = 0; + + ///if(x == (uint64_t)-1) x = dis->med; + if(x != (uint64_t)-1) + { + if(x < dis->max) + { + uint64_t i; + for (i = 0; i < dis->n; i++) + { + if(x < dis->a[i].end && x >= dis->a[i].beg) break; + } + if(i < dis->n) + { + rate = ((double)(dis->a[i].cnt_1))/((double)(dis->a[i].cnt_0 + dis->a[i].cnt_1)); + } + else + { + rate = get_trans(idx, x); + } + } + else + { + rate = get_trans(idx, x); + } + } + else + { + // rate = 0.2; + rate = 0.4; + } + + + if(rate < 0) rate = 0; + rate += OFFSET_RATE; + if(rate > 0.5) rate = 0.5; + rate -= OFFSET_SECOND_RATE; //[OFFSET_RATE - OFFSET_SECOND_RATE, 0.5 - OFFSET_SECOND_RATE] + + long double w = logl((1/rate)-1)*SCALL; + if(w < OFFSET_RATE_MIN_W) w = OFFSET_RATE_MIN_W; + if(w > OFFSET_RATE_MAX_W) w = OFFSET_RATE_MAX_W; + return w; +} + +void LeastSquare_advance(trans_idx* dis, ha_ug_index* idx, uint64_t med) +{ + #define SCAL_RATE 1000 + long double t1=0, t2=0, t3=0, t4=0, x, y; + uint64_t i, m, ava_size; + + for (i = m = 0; i < dis->n; i++) + { + x = ((double)(dis->a[i].beg + dis->a[i].end))/2; + y = ((double)(dis->a[i].cnt_1))/((double)(dis->a[i].cnt_0 + dis->a[i].cnt_1)); + if(dis->a[i].beg >= med) break; + + t1 += x*x; + t2 += x; + t3 += x*y; + t4 += y; + m++; + } + + if(i < dis->n) + { + uint64_t beg, end, cnt_0, cnt_1; + for (beg = dis->a[i].beg, end = dis->a[i].end, cnt_0 = cnt_1 = 0; i < dis->n; i++) + { + cnt_0 += dis->a[i].cnt_0; + cnt_1 += dis->a[i].cnt_1; + beg = MIN(beg, dis->a[i].beg); + end = MAX(end, dis->a[i].end); + } + + x = ((double)(beg + end))/2; + y = ((double)(cnt_1))/((double)(cnt_0 + cnt_1)); + + t1 += x*x; + t2 += x; + t3 += x*y; + t4 += y; + m++; + } + + + + if(t2 > t4) + { + idx->frac = t2/t4; + if(idx->frac > SCAL_RATE) idx->frac = idx->frac / SCAL_RATE; + if(idx->frac < 1) idx->frac = 1; + } + + ava_size = m; + t1 /= (idx->frac*idx->frac); + t2 /= idx->frac; + t3 /= idx->frac; + if((t1*ava_size - t2*t2) != 0) + { + idx->a = (t3*ava_size - t2*t4) / (t1*ava_size - t2*t2); + } + if((t1*ava_size - t2*t2) != 0) + { + idx->b = (t1*t4 - t2*t3) / (t1*ava_size - t2*t2); + } +} + +void weight_edges_advance(ha_ug_index* idx, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, trans_idx* dis) +{ + uint64_t k, i, shif = 64 - idx->uID_bits, beg, end, t_d; + hc_edge *e1 = NULL, *e2 = NULL; + long double weight; + + for (i = 0; i < link->a.n; i++) + { + for (k = 0; k < link->a.a[i].e.n; k++) + { + if(link->a.a[i].e.a[k].del) continue; + link->a.a[i].e.a[k].weight = 0; + } + } + + for (k = 0; k < hits->a.n; ++k) + { + beg = ((hits->a.a[k].s<<1)>>shif); + end = ((hits->a.a[k].e<<1)>>shif); + + if(beg == end) continue; + if(IF_HOM(beg, *bub)) continue; + if(IF_HOM(end, *bub)) continue; + + t_d = get_hic_distance(&(hits->a.a[k]), link, idx, NULL); + if(t_d == (uint64_t)-1) continue; + + e1 = get_hc_edge(link, beg, end, 0); + e2 = get_hc_edge(link, end, beg, 0); + if(e1 == NULL || e2 == NULL) continue; + weight = 1; + if(dis) + { + weight = get_trans_weight_advance(idx, t_d, dis); + } + + e1->weight += weight; e1->occ++; + e2->weight += weight; e2->occ++; + } +} + +void get_bub_id(bubble_type* bub, uint32_t root, uint64_t* id0, uint64_t* id1, uint32_t check_het) +{ + if(id0) (*id0) = (uint64_t)-1; + if(id1) (*id1) = (uint64_t)-1; + uint64_t b_id0 = (uint64_t)-1, b_id1 = (uint64_t)-1; + uint32_t beg, sink; + + if((bub->b_s_idx.a[root]&0xffffffff) != 0xffffffff) + { + b_id0 = bub->b_s_idx.a[root]&0xffffffff; + if(check_het) + { + get_bubbles(bub, b_id0, &beg, &sink, NULL, NULL, NULL); + if(((beg == (uint32_t)-1) || IF_HET(beg>>1, *bub)) && ((sink == (uint32_t)-1) || IF_HET(sink>>1, *bub))) b_id0 = (uint64_t)-1; + } + } + + if((bub->b_s_idx.a[root]&0xffffffff00000000) != 0xffffffff00000000) + { + b_id1 = bub->b_s_idx.a[root]&0xffffffff00000000; b_id1 >>= 32; + if(check_het) + { + get_bubbles(bub, b_id1, &beg, &sink, NULL, NULL, NULL); + if(((beg == (uint32_t)-1) || IF_HET(beg>>1, *bub)) && ((sink == (uint32_t)-1) || IF_HET(sink>>1, *bub))) b_id1 = (uint64_t)-1; + } + } + + if(b_id0 == (uint64_t)-1 && b_id1 != (uint64_t)-1) + { + b_id0 = b_id1; + b_id1 = (uint64_t)-1; + } + + if(id0) (*id0) = b_id0; + if(id1) (*id1) = b_id1; +} + +///return how many bubbles linked by this node +uint32_t connect_bub_occ(bubble_type* bub, uint32_t root_id, uint32_t check_het) +{ + uint64_t id0, id1, occ = 2; + get_bub_id(bub, root_id, &id0, &id1, check_het); + if(id0 == (uint64_t)-1) occ--; + if(id1 == (uint64_t)-1) occ--; + return occ; +} +///x_0 and x_1 are the ids of unitigs; +///x_0_b_id and x_1_b_id are the ids of bubble graph; +int ma_2_bub_arc(bubble_type* bub, uint32_t x_0, uint32_t* x_0_b_id, uint32_t x_1, uint32_t* x_1_b_id, +asg_arc_t *p, uint32_t check_het) +{ + uint64_t id0, ori_0, id1, ori_1, tmp_id; + uint32_t beg, sink, n, *a, x; + uint32_t beg_0, sink_0, beg_1, sink_1; + if(x_0_b_id) id0 = (*x_0_b_id); + if(x_1_b_id) id1 = (*x_1_b_id); + if((x_0 != (uint32_t)-1) && (x_1 != (uint32_t)-1)) + { + if(((x_0>>1) == (x_1>>1)))///if we would like to find a edge bridging two nearby bubbles + { + if(x_0_b_id == NULL && x_1_b_id == NULL) + { + get_bub_id(bub, x_0>>1, &id0, &id1, check_het); + } + + get_bubbles(bub, id0, &beg_0, &sink_0, &a, &n, NULL);//first bubble + get_bubbles(bub, id1, &beg_1, &sink_1, &a, &n, NULL);//second bubble + + + ori_0 = (uint64_t)-1; + if(x_0 == (beg_0^1)) + { + ori_0 = 1; + } + else if(x_0 == (sink_0^1)) + { + ori_0 = 0; + } + else if(x_0 == (beg_1^1)) + { + ori_0 = 1+2; + } + else if(x_0 == (sink_1^1)) + { + ori_0 = 0+2; + } + else + { + fprintf(stderr, "error 0\n"); + return 0; + } + + + ori_1 = (uint64_t)-1; + if(x_1 == (beg_0^1)) + { + ori_1 = 1; + } + else if(x_1 == (sink_0^1)) + { + ori_1 = 0; + } + else if(x_1 == (beg_1^1)) + { + ori_1 = 1 + 2; + } + else if(x_1 == (sink_1^1)) + { + ori_1 = 0 + 2; + } + else + { + fprintf(stderr, "error 1\n"); + return 0; + } + + + + if((((ori_0>>1)^(ori_1>>1))&1) != 1) + { + fprintf(stderr, "error 10\n"); + fprintf(stderr, "x_0: %u, id0: %lu, beg_0: %u, sink_0: %u, ori_0: %lu\n", + x_0, id0, beg_0, sink_0, ori_0); + fprintf(stderr, "x_1: %u, id1: %lu, beg_1: %u, sink_1: %u, ori_1: %lu\n", + x_1, id1, beg_1, sink_1, ori_1); + return 0; + } + + if(ori_0 & 2) + { + tmp_id = id0; id0 = id1; id1 = tmp_id; + } + + ori_0 &= 1; ori_1 &= 1; ori_1 ^= 1; + + + + p->ul = (id0<<1) | ori_0; p->ul <<= 32; p->ul += 0; + p->v = (id1<<1) | ori_1; + p->ol = 0; p->del = 0; p->el = p->no_l_indel = p->strong = 1; + } + else + { + if(x_0_b_id == NULL) get_bub_id(bub, x_0>>1, &id0, NULL, check_het); + if(x_1_b_id == NULL) get_bub_id(bub, x_1>>1, &id1, NULL, check_het); + + + get_bubbles(bub, id0, &beg, &sink, &a, &n, NULL); + ori_0 = (uint64_t)-1; + if(x_0 == (beg^1)) + { + ori_0 = 1; + } + else if(x_0 == (sink^1)) + { + ori_0 = 0; + } + else + { + fprintf(stderr, "error 0\n"); + return 0; + } + + + + get_bubbles(bub, id1, &beg, &sink, &a, &n, NULL); + ori_1 = (uint64_t)-1; + if(x_1 == (beg^1)) + { + ori_1 = 1; + } + else if(x_1 == (sink^1)) + { + ori_1 = 0; + } + else + { + fprintf(stderr, "error 1\n"); + return 0; + } + ori_0 &= 1; ori_1 &= 1; ori_1 ^= 1; + + p->ul = (id0<<1) | ori_0; p->ul <<= 32; p->ul += 0; + p->v = (id1<<1) | ori_1; + p->ol = 0; p->del = 0; p->el = p->no_l_indel = p->strong = 1; + } + } + else + { + x = (uint32_t)-1; + if(x_0 != (uint32_t)-1) x = x_0; + if(x_1 != (uint32_t)-1) x = x_1; + if(x == (uint32_t)-1) return 0; + if(x_0_b_id == NULL && x_1_b_id == NULL) + { + get_bub_id(bub, x>>1, &id0, &id1, check_het); + } + + if(id0 != (uint64_t)-1) + { + get_bubbles(bub, id0, &beg, &sink, &a, &n, NULL); + if(x == (beg^1)) + { + return 1; + } + else if(x == (sink^1)) + { + return 1; + } + + return 0; + } + + if(id1 != (uint64_t)-1) + { + get_bubbles(bub, id1, &beg, &sink, &a, &n, NULL); + if(x == (beg^1)) + { + return 1; + } + else if(x == (sink^1)) + { + return 1; + } + + return 0; + } + } + + return 1; +} + +#define arc_first(g, v) ((g)->arc[(g)->idx[(v)]>>32]) +#define arc_cnt(g, v) ((uint32_t)(g)->idx[(v)]) +void debug_bub_utg(bubble_type* bub, ma_ug_t *bug, asg_t *bsg, uint32_t check_het) +{ + uint32_t i, k, rId, rId_next, ori, ori_next, root, beg, end; + uint64_t id0, id1; + ma_utg_t *u = NULL; + asg_arc_t *t = NULL; + for (i = 0; i < bug->u.n; i++) + { + u = &(bug->u.a[i]); + if(u->n == 0) continue; + for (k = 0; k < u->n; k++) + { + if(k+1 >= u->n) continue; + rId = u->a[k]>>33; + ori = u->a[k]>>32&1; + get_bubbles(bub, rId, ori == 1?&root:NULL, ori == 0?&root:NULL, NULL, NULL, NULL); + + t = &(arc_first(bsg, u->a[k]>>32)); + get_bub_id(bub, root>>1, &id0, &id1, check_het); + if(id0 == (uint64_t)-1 || (t->el == 1 && id1 == (uint64_t)-1) || (t->el == 0 && id1 != (uint64_t)-1)) + { + fprintf(stderr, "sbsbsb0sbsbsb-utg%.6d, check_het: %u\n", (int)((root>>1)+1), check_het); + fprintf(stderr, "id0: %lu, id1: %lu, t->el: %u\n", id0, id1, t->el); + continue; + } + + ///fprintf(stderr, "aaaaaaaa10aaaaaaaa-utg%.6d\n", (int)((root>>1)+1)); + + rId_next = u->a[k+1]>>33; + ori_next = u->a[k+1]>>32&1; + + + get_bubbles(bub, rId, &beg, &end, NULL, NULL, NULL); + if(ori == 1) + { + if(root != beg) fprintf(stderr, "sbsbsb1sbsbsb, root: %u, beg: %u, end: %u\n", root, beg, end); + } + else + { + if(root != end) fprintf(stderr, "sbsbsb2sbsbsb, root: %u, beg: %u, end: %u\n", root, beg, end); + } + + if(t->el == 1) + { + get_bubbles(bub, rId_next, &beg, &end, NULL, NULL, NULL); + if(ori_next == 0) + { + if(root != (beg^1)) fprintf(stderr, "sbsbsb3sbsbsb, root: %u, beg: %u, end: %u\n", root, beg, end); + } + else + { + if(root != (end^1)) fprintf(stderr, "sbsbsb4sbsbsb, root: %u, beg: %u, end: %u\n", root, beg, end); + } + } + } + } + + fprintf(stderr, "[M::%s]\n", __func__); +} + +///just change the hap status of beg/sink, but they are are still at a chain of bubble +///might be ok +inline void set_bub_idx(bubble_type* bub, ma_utg_t *bu, asg_t *untig_sg, int beg_idx, int end_idx, +uint32_t is_to_hom, uint32_t check_het) +{ + int k; + uint32_t rId, ori, root; + uint64_t id0, id1, len0, len1; + for (k = beg_idx; k <= end_idx; k++) + { + rId = bu->a[k]>>33; + ori = bu->a[k]>>32&1; + get_bubbles(bub, rId, ori == 1?&root:NULL, ori == 0?&root:NULL, NULL, NULL, NULL); + + if(is_to_hom && IF_HOM(root>>1, *bub)) continue; + if(!is_to_hom && IF_HET(root>>1, *bub)) continue; + + + get_bub_id(bub, root>>1, &id0, &id1, check_het); + if(id0 == (uint64_t)-1 || id1 == (uint64_t)-1) continue; + get_bubbles(bub, id0, NULL, NULL, NULL, NULL, &len0); + get_bubbles(bub, id1, NULL, NULL, NULL, NULL, &len1); + + if(is_to_hom) + { + if(untig_sg->seq[root>>1].len > (MIN(len0, len1)*3)) continue; + bub->index[root>>1] = (uint32_t)-1; + } + else + { + bub->index[root>>1] = bub->f_bub+1; + } + + } +} + +void determine_bub_idx(bubble_type* bub, ma_utg_t *bu, asg_t *untig_sg, uint64_t pLen, +uint64_t rLEN, uint64_t r_hetLen, int beg_idx, int end_idx, uint32_t check_het) +{ + if(beg_idx > end_idx) return; + + uint64_t r_homLen = rLEN - r_hetLen; + ///pLen: total length, rLEN: beg/sink length + if(pLen > 0 && rLEN > 0 && r_hetLen > 0 && rLEN < pLen*0.5 && r_hetLen < rLEN * 0.2) ///set het to hom + { + set_bub_idx(bub, bu, untig_sg, beg_idx, end_idx, 1, bub->check_het); + } + else if(pLen > 0 && rLEN > 0 && r_homLen > 0 && rLEN > pLen*0.9 && r_homLen < rLEN * 0.1) ///set hom to het + { + set_bub_idx(bub, bu, untig_sg, beg_idx, end_idx, 0, bub->check_het); + } +} + +void detect_bub_graph(bubble_type* bub, asg_t *untig_sg) +{ + asg_t *bg = bub->b_g; + ma_ug_t *ug = NULL; + ug = ma_ug_gen(bub->b_g); + ///debug_bub_utg(bub, ug, bg, bub->check_het); + uint32_t i, k, rId, ori, root, r_root; + int beg_idx, end_idx; + uint64_t pLen, rLEN, r_hetLen; + ma_utg_t *u = NULL; + asg_arc_t *t = NULL; + for (i = 0; i < ug->u.n; i++)///bubble chain graph; bubbles within the same chain have been merged + { + u = &(ug->u.a[i]); + if(u->n == 0) continue; + ///u is a bubble chain + for (k = pLen = rLEN = r_hetLen = beg_idx = 0, end_idx = -1; k < u->n; k++) + { + rId = u->a[k]>>33; + ori = u->a[k]>>32&1; + get_bubbles(bub, rId, ori == 1?&root:&r_root, ori == 0?&root:&r_root, NULL, NULL, NULL); + + t = NULL; + if(k+1 < u->n) t = &(arc_first(bg, u->a[k]>>32));//edge between two bubbles within the same chain + + pLen += bg->seq[rId].len;///path length in bubble + if(end_idx < beg_idx) ///first bubble + { + pLen += untig_sg->seq[r_root>>1].len; + rLEN += untig_sg->seq[r_root>>1].len; + if(IF_HET(r_root>>1, *bub)) r_hetLen += untig_sg->seq[r_root>>1].len; + } + + if(t) + { + if(t->el == 0)///there is tangle between two bubbles + { + if(end_idx >= beg_idx) + { + pLen += untig_sg->seq[root>>1].len; + rLEN += untig_sg->seq[root>>1].len; + if(IF_HET(root>>1, *bub)) r_hetLen += untig_sg->seq[root>>1].len; + determine_bub_idx(bub, u, untig_sg, pLen, rLEN, r_hetLen, beg_idx, end_idx, bub->check_het); + } + + pLen = rLEN = r_hetLen = 0; + beg_idx = k + 1; end_idx = k; + } + else///two bubbles directly connected with each other + { + pLen += t->ol; + rLEN += t->ol; + if(IF_HET(root>>1, *bub)) r_hetLen += t->ol; + end_idx = k; + } + } + } + + if(end_idx >= beg_idx) + { + pLen += untig_sg->seq[root>>1].len; + rLEN += untig_sg->seq[root>>1].len; + if(IF_HET(root>>1, *bub)) r_hetLen += untig_sg->seq[root>>1].len; + determine_bub_idx(bub, u, untig_sg, pLen, rLEN, r_hetLen, beg_idx, end_idx, bub->check_het); + } + } + + ma_ug_destroy(ug); +} + +void get_bub_graph(ma_ug_t* ug, bubble_type* bub) +{ + asg_t *sg = ug->g; + asg_arc_t t, *p = NULL; + pdq pq; + init_pdq(&pq, sg->n_seq<<1); + uint32_t n_vtx = sg->n_seq<<1, v, k; + uint32_t *pre = NULL; MALLOC(pre, n_vtx); + uint32_t pre_id, adjecent, bub_occ; + asg_t *bub_g = asg_init(); + for (v = 0; v < bub->f_bub; v++)///all bubbles + { + uint64_t pathbase; + uint32_t beg, sink; + get_bubbles(bub, v, &beg, &sink, NULL, NULL, &pathbase); + asg_seq_set(bub_g, v, pathbase, (bub->check_het && IF_HET(beg>>1, *bub) && IF_HET(sink>>1, *bub))?1:0); + bub_g->seq[v].c = PRIMARY_LABLE; + } + + //check all unitigs, instead of bubble nodes + for (v = 0; v < n_vtx; ++v) + { + if(sg->seq[v>>1].del) continue; + if(bub->b_s_idx.a[v>>1] == (uint64_t)-1) continue; ///if (v>>1) is not a beg or sink of bubbles + ///one node might be the beg/sink node of at most two bubbles + bub_occ = connect_bub_occ(bub, v>>1, bub->check_het); + if(bub_occ == 0) continue; + if(bub_occ == 2) + { + if(ma_2_bub_arc(bub, v, NULL, v^1, NULL, &t, bub->check_het)) + { + t.ol = sg->seq[v>>1].len; + p = asg_arc_pushp(bub_g); + *p = t; + } + continue; + } + if(ma_2_bub_arc(bub, v, NULL, (uint32_t)-1, NULL, &t, bub->check_het) == 0) continue; + + ///v is the beg/sink node of only one bubble + get_shortest_path(v, &pq, sg, pre); + for (k = 0; k < pq.dis.n; k++) + { + if(pq.dis.a[k] == (uint64_t)-1) continue; + if(bub->b_s_idx.a[k>>1] == (uint64_t)-1) continue; + if(connect_bub_occ(bub, k>>1, bub->check_het) == 0) continue; + if((k>>1) == (v>>1)) continue; + pre_id = pre[k]; + adjecent = 0; + while (pre_id != v) + { + if(connect_bub_occ(bub, pre_id>>1, bub->check_het) > 0)///some bubbles between v and k + { + adjecent = 1; + break; + } + pre_id = pre[pre_id]; + } + + if(adjecent == 0) + { + if(ma_2_bub_arc(bub, v, NULL, k^1, NULL, &t, bub->check_het))///edges spanning tangles + { + t.el = 0; t.ol = pq.dis.a[k] + sg->seq[k>>1].len; + p = asg_arc_pushp(bub_g); + *p = t; + } + } + } + } + + free(pre); + destory_pdq(&pq); + + asg_cleanup(bub_g); + bub_g->r_seq = bub_g->n_seq; + bub->b_g = bub_g; +} + +void print_bubble_chain(bubble_type* bub, const char* command) +{ + ma_ug_t *ug = NULL; + ug = ma_ug_gen(bub->b_g); + uint32_t i, k, j, rId, beg, sink, *a, n; + ma_utg_t *u = NULL; + asg_arc_t *t = NULL; + for (i = 0; i < ug->u.n; i++) + { + u = &(ug->u.a[i]); + if(u->n == 0) continue; + fprintf(stderr,"\n%s: chain-%u\n", command, i); + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + get_bubbles(bub, rId, &beg, &sink, &a, &n, NULL); + t = NULL; + if(k+1 < u->n) t = &(arc_first(bub->b_g, u->a[k]>>32)); + fprintf(stderr, "[utg%.6dl, utg%.6dl] el=%u no_long_indel=%u, rId=%u, nv: %u, nv^: %u\n", + (int)((beg>>1)+1), (int)((sink>>1)+1), t?t->el:16, t?t->no_l_indel:16, rId, arc_cnt(bub->b_g, u->a[k]>>32), arc_cnt(bub->b_g, (u->a[k]>>32)^1)); + // if((u->a[k]>>33) == 9658) + // { + // asg_arc_t *av; + // uint32_t nv, nv_i; + // av = asg_arc_a(bub->b_g, u->a[k]>>32); + // nv = asg_arc_n(bub->b_g, u->a[k]>>32); + // for (nv_i = 0; nv_i < nv; nv_i++) + // { + // if(av[nv_i].del) continue; + // fprintf(stderr, "v--->%u\n", av[nv_i].v>>1); + // } + + + + // av = asg_arc_a(bub->b_g, (u->a[k]>>32)^1); + // nv = asg_arc_n(bub->b_g, (u->a[k]>>32)^1); + // for (nv_i = 0; nv_i < nv; nv_i++) + // { + // if(av[nv_i].del) continue; + // fprintf(stderr, "v^1--->%u\n", av[nv_i].v>>1); + // } + + // } + if(bub->b_g->seq[rId].c == HAP_LABLE) + { + for (j = 0; j < n; j++) + { + fprintf(stderr, ">>>utg%.6dl\n", (int)((a[j]>>1)+1)); + } + } + } + } + + ma_ug_destroy(ug); +} + +int is_simple_broken_bubble(ma_ug_t *unitig_ug, uint32_t x, uint32_t beg, uint32_t sink, uint32_t* new_het) +{ + uint32_t nv, v = (uint32_t)-1, u_s = (uint32_t)-1, u_e = (uint32_t)-1, i; + asg_arc_t *av = NULL; + (*new_het) = (uint32_t)-1; + + if((asg_arc_n(unitig_ug->g, x) == 1) + && (asg_arc_n(unitig_ug->g, x^1) == 0)) + { + v = x; + } + + if((asg_arc_n(unitig_ug->g, x^1) == 1) + && (asg_arc_n(unitig_ug->g, x) == 0)) + { + v = x^1; + } + + if(v == (uint32_t)-1) return 0; + + + av = asg_arc_a(unitig_ug->g, v); + nv = asg_arc_n(unitig_ug->g, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + if((av[i].v>>1) == (beg>>1)) u_s = beg, u_e = sink; + if((av[i].v>>1) == (sink>>1)) u_s = sink, u_e = beg; + } + + if(u_s == (uint32_t)-1 || u_e == (uint32_t)-1) return 0; + + av = asg_arc_a(unitig_ug->g, u_s); + nv = asg_arc_n(unitig_ug->g, u_s); + if(nv != 2) return 0; + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + if(av[i].v == (v^1)) continue; + if(av[i].v == (u_e^1)) + { + (*new_het) = u_e; + return 1; + } + } + + return 0; +} + +int double_check_broken_bubble(asg_t *g, kvec_t_u32_warp* broken, uint32_t beg, uint32_t sink, +uint8_t* vis_flag, uint32_t vis_flag_n, kvec_t_u32_warp* stack, asg_t *bsg, asg_arc_t *p_t) +{ + uint32_t cur, ncur, i, n, pre, occ; + radix_sort_u32(broken->a.a, broken->a.a + broken->a.n); + for (i = n = 0, pre = (uint32_t)-1; i < broken->a.n; i++) + { + if((broken->a.a[i]>>1) == (pre>>1)) continue;///skip same node like v and v^1 + pre = broken->a.a[i]; + broken->a.a[n] = pre; + n++; + } + broken->a.n = n; + + asg_arc_t *acur = NULL; + memset(vis_flag, 0, vis_flag_n); + stack->a.n = 0; + kv_push(uint32_t, stack->a, beg); + occ = 0; + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + if(vis_flag[cur] == 0 && vis_flag[cur^1] == 0) occ++; + if(vis_flag[cur] == 0 && cur != (beg^1) && (sink == (uint32_t)-1 || cur != (sink^1))) + { + vis_flag[cur] = 1; + ncur = asg_arc_n(g, cur); + acur = asg_arc_a(g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if(vis_flag[acur[i].v]) continue; + kv_push(uint32_t, stack->a, acur[i].v); + } + } + vis_flag[cur] = 1; + + + cur^=1; + if(vis_flag[cur] == 0 && cur != (beg^1) && (sink == (uint32_t)-1 || cur != (sink^1))) + { + vis_flag[cur] = 1; + ncur = asg_arc_n(g, cur); + acur = asg_arc_a(g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if(vis_flag[acur[i].v]) continue; + kv_push(uint32_t, stack->a, acur[i].v); + } + } + vis_flag[cur] = 1; + } + + n = broken->a.n; + if(beg != (uint32_t)-1) n++; + if(sink != (uint32_t)-1) n++; + + if(occ > n) + { + ///fprintf(stderr, "\n+++++sb+++++beg-utg%.6ul, sink-utg%.6ul, occ: %u, n: %u\n", (beg>>1)+1, (sink>>1)+1, occ, n); + if(bsg && p_t && beg != (uint32_t)-1 && sink != (uint32_t)-1) + { + p_t->del = 1; + asg_arc_del(bsg, (p_t->v)^1, (p_t->ul>>32)^1, 1); + } + /*******************************for debug************************************/ + // memset(vis_flag, 0, vis_flag_n); + // stack->a.n = 0; + // kv_push(uint32_t, stack->a, beg); + // occ = 0; + // while (stack->a.n > 0) + // { + // occ++; + // stack->a.n--; + // cur = stack->a.a[stack->a.n]; + + // fprintf(stderr, "cur-utg%.6ul\n", (cur>>1)+1); + + // vis_flag[cur] = 1; + // if(cur == (beg^1) || cur == (sink^1)) continue; + // ncur = asg_arc_n(g, cur); + // acur = asg_arc_a(g, cur); + // for (i = 0; i < ncur; i++) + // { + // if(acur[i].del) continue; + // if(vis_flag[acur[i].v]) continue; + // kv_push(uint32_t, stack->a, acur[i].v); + // } + + // cur^=1; + // if(vis_flag[cur]) continue; + // vis_flag[cur] = 1; + // if(cur == (beg^1) || cur == (sink^1)) continue; + // ncur = asg_arc_n(g, cur); + // acur = asg_arc_a(g, cur); + // for (i = 0; i < ncur; i++) + // { + // if(acur[i].del) continue; + // if(vis_flag[acur[i].v]) continue; + // kv_push(uint32_t, stack->a, acur[i].v); + // } + // } + + // for (i = 0; i < broken->a.n; i++) + // { + // fprintf(stderr, "*****cur-utg%.6ul\n", (broken->a.a[i]>>1)+1); + // } + /*******************************for debug************************************/ + return 0; + } + + return 1; +} + +int is_local_simple_circle(asg_t *g, uint32_t v) +{ + if(asg_arc_n(g, v) != asg_arc_n(g, v^1)) return 0; + if(asg_arc_n(g, v) == 1) v = arc_first(g, v).v; + if(asg_arc_n(g, v) != asg_arc_n(g, v^1)) return 0; + if(asg_arc_n(g, v) != 2) return 0; + uint32_t ncur, i, u; + asg_arc_t *acur = NULL; + ncur = asg_arc_n(g, v); + acur = asg_arc_a(g, v); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + u = acur[i].v; + if(asg_arc_n(g, u) != 1 || asg_arc_n(g, u^1) != 1) continue; + if(arc_first(g, u).v != v) continue; + return 1; + } + return 0; +} + +///actually not useful, and may have bug when one bubble at multipe chains +void update_bub_b_s_idx(bubble_type* bub) +{ + memset(bub->b_s_idx.a, -1, bub->b_s_idx.n * sizeof(uint64_t)); + uint32_t i, v, beg, sink, n_bub = bub->num.n - 1; + for (i = 0; i < n_bub; i++) + { + get_bubbles(bub, i, &beg, &sink, NULL, NULL, NULL); + + if(beg != (uint32_t)-1) + { + v = beg>>1; + if(bub->b_s_idx.a[v] == (uint64_t)-1) + { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } + else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) + { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } + } + + + + if(sink != (uint32_t)-1) + { + v = sink>>1; + if(bub->b_s_idx.a[v] == (uint64_t)-1) + { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } + else if((bub->b_s_idx.a[v] & 0xffffffff00000000) == 0xffffffff00000000) + { + bub->b_s_idx.a[v] <<= 32; + bub->b_s_idx.a[v] |= i; + } + } + } +} + +void update_bubble_graph(kvec_t_u32_warp* broken, uint32_t beg, uint32_t beg_bub_id, +uint32_t sink, uint32_t sink_bub_id, bubble_type* bub, kvec_asg_arc_t_warp* edges, asg_t *bsg, +asg_arc_t *p_t, uint8_t *bsg_idx, ma_ug_t *unitig_ug, uint64_t* occ_thres, uint64_t is_b_bub) +{ + uint32_t i, pre, n, bub_id, v; + uint64_t occ; + asg_arc_t t_f, t_r; + + radix_sort_u32(broken->a.a, broken->a.a + broken->a.n); + for (i = n = occ = 0, pre = (uint32_t)-1; i < broken->a.n; i++) + { + if((broken->a.a[i]>>1) == (pre>>1)) continue; + if(IF_HOM((broken->a.a[i]>>1), *bub)) + { + if(is_local_simple_circle(unitig_ug->g, broken->a.a[i])) + { + bub->index[broken->a.a[i]>>1] = bub->f_bub+1; + } + else + { + continue; + } + } + + pre = broken->a.a[i]; + broken->a.a[n] = pre; + occ += unitig_ug->u.a[broken->a.a[n]>>1].n; + n++; + } + broken->a.n = n; + ///if(broken->a.n == 0) return; + if(broken->a.n == 1) + { + ///fprintf(stderr, "+++++sb+++++utg%.6ul\n", (broken->a.a[0]>>1)+1); + if(beg != (uint32_t)-1 && sink != (uint32_t)-1 && + is_simple_broken_bubble(unitig_ug, broken->a.a[0], beg, sink, &v)) + { + if((v>>1) != (broken->a.a[0]>>1)) + { + ///fprintf(stderr, "-----sb-----utg%.6ul\n", (v>>1)+1); + kv_push(uint32_t, broken->a, v); + occ += unitig_ug->u.a[v>>1].n; + if(occ_thres && occ > (*occ_thres)) return; + bub->index[v>>1] = bub->f_bub+1; ///set to het + } + } + } + + + if(occ_thres && occ > (*occ_thres)) return; + /********************push graph node********************/ + bub_id = bub->b_g->n_seq; + asg_seq_set(bub->b_g, bub_id, 0, 0); + bub->b_g->seq[bub_id].c = HAP_LABLE; + if(is_b_bub) bub->b_bub++; + /********************push graph node********************/ + + /********************push bubble********************/ + kv_push(uint32_t, bub->num, bub->list.n); + kv_push(uint64_t, bub->pathLen, 0); + kv_push(uint32_t, bub->list, beg); + kv_push(uint32_t, bub->list, sink); + + for (i = 0; i < broken->a.n; i++) + { + kv_push(uint32_t, bub->list, broken->a.a[i]); + if(bsg_idx) bsg_idx[broken->a.a[i]>>1] = 1; + } + /********************push bubble********************/ + if(beg != (uint32_t)-1) ///beg_bub_id ----> bub_id + { + if(ma_2_bub_arc(bub, beg, &beg_bub_id, beg^1, &bub_id, &t_f, bub->check_het) && + ma_2_bub_arc(bub, beg^1, &bub_id, beg, &beg_bub_id, &t_r, bub->check_het)) + { + t_f.el = 0; t_f.no_l_indel = 0; t_f.del = 0; + kv_push(asg_arc_t, edges->a, t_f); + + t_r.el = 0; t_r.no_l_indel = 0; t_r.del = 0; + kv_push(asg_arc_t, edges->a, t_r); + } + } + + if(sink != (uint32_t)-1) ///bub_id ----> sink_bub_id + { + if(ma_2_bub_arc(bub, sink^1, &bub_id, sink, &sink_bub_id, &t_f, bub->check_het) && + ma_2_bub_arc(bub, sink, &sink_bub_id, sink^1, &bub_id, &t_r, bub->check_het)) + { + t_f.el = 0; t_f.no_l_indel = 0; t_f.del = 0; + kv_push(asg_arc_t, edges->a, t_f); + + t_r.el = 0; t_r.no_l_indel = 0; t_r.del = 0; + kv_push(asg_arc_t, edges->a, t_r); + } + } + + if(beg != (uint32_t)-1 && sink != (uint32_t)-1 && p_t) + { + p_t->del = 1; + asg_arc_del(bsg, (p_t->v)^1, (p_t->ul>>32)^1, 1); + } +} + +void get_related_bub_nodes(kvec_t_u32_warp* broken, bubble_type* bub, pdq* pq, asg_t *unitig_g, + uint32_t *pre, uint32_t src, uint32_t dest, uint8_t *bsg_idx) +{ + uint32_t j_i, pre_id, adjecent; + src ^= 1; + get_shortest_path(src, pq, unitig_g, pre); + + for (j_i = 0; j_i < pq->dis.n; j_i++) + { + if(pq->dis.a[j_i] == (uint64_t)-1) continue; + ///if(IF_HOM(j_i>>1, *bub)) continue; + if((j_i>>1) == (src>>1)) continue; + if((dest != (uint32_t)-1) && ((j_i>>1) == (dest>>1))) continue; + + pre_id = pre[j_i]; + adjecent = 0; + while (pre_id != src) + { + if(((dest != (uint32_t)-1) && ((pre_id>>1) == (dest>>1))) + || ((pre_id>>1) == (src>>1))) + { + adjecent = 1; + break; + } + pre_id = pre[pre_id]; + } + + if(adjecent == 0) + { + if(broken->a.n == 0 || (broken->a.n > 0 && (j_i>>1) != (broken->a.a[broken->a.n - 1]>>1))) + { + if(bsg_idx && bsg_idx[(j_i>>1)]) + { + broken->a.n = 0; + return; + } + kv_push(uint32_t, broken->a, j_i); + } + } + } +} + +uint64_t calculate_chain_weight(ma_utg_t *u, bubble_type* bub, ma_ug_t *unitig_ug, chain_w_type* x) +{ + x->b_occ = x->g_occ = 0; + uint32_t i, j, *a, n; + uint64_t occ, occ_n, thres; + for (i = occ = occ_n = 0; i < u->n; i++) + { + if(bub->b_g->seq[u->a[i]>>33].c != HAP_LABLE) + { + get_bubbles(bub, u->a[i]>>33, NULL, NULL, &a, &n, NULL); + for (j = 0; j < n; j++) + { + occ += unitig_ug->u.a[a[j]>>1].n; + } + occ_n++; + } + } + + thres = (uint64_t)-1; + if(occ_n > 0) thres = (occ*6)/occ_n; + + for (i = 0; i < u->n; i++) + { + occ = 0; + get_bubbles(bub, u->a[i]>>33, NULL, NULL, &a, &n, NULL); + for (j = 0; j < n; j++) + { + occ += unitig_ug->u.a[a[j]>>1].n; + } + + if(bub->b_g->seq[u->a[i]>>33].c != HAP_LABLE || occ < thres) + { + x->g_occ += occ; + } + else + { + x->b_occ += occ; + } + } + + return thres; +} + +int cmp_chain_weight(const void * a, const void * b) +{ + if((*(chain_w_type*)a).del != (*(chain_w_type*)b).del) + { + return (*(chain_w_type*)a).del > (*(chain_w_type*)b).del? 1 : -1; + } + else + { + long long a_occ = (*(chain_w_type*)a).g_occ - (*(chain_w_type*)a).b_occ; + long long b_occ = (*(chain_w_type*)b).g_occ - (*(chain_w_type*)b).b_occ; + if(a_occ != b_occ) + { + return a_occ > b_occ? -1 : 1; + } + else + { + return 0; + } + } +} + +void resolve_bubble_chain_tangle_back(ma_ug_t* ug, bubble_type* bub, hc_links* link) +{ + ma_ug_t *copy_ug = copy_untig_graph(bub->b_ug); + asg_arc_t *av = NULL; + uint32_t i, j, k, v, w, w1, w2, nw1, nw2, nv, occ_e_1, occ_e_2, occ_c; + ma_ug_t *bub_ug = copy_ug; + ///ma_utg_t *u = NULL; + buf_t b; memset(&b, 0, sizeof(buf_t)); + kvec_t_u32_warp stack, result; + kv_init(stack.a); kv_init(result.a); + uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq<<1); + uint8_t *is_vis = NULL; CALLOC(is_vis, ug->g->n_seq<<1); + kvec_t(uint64_t) occ_idx; kv_init(occ_idx); uint64_t tmp, *p = NULL; + + for (k = occ_idx.n = 0; k < bub_ug->g->n_seq; k++) + { + v = (k<<1); + av = asg_arc_a(bub_ug->g, v); + nv = asg_arc_n(bub_ug->g, v); + for (i = 0, w = (uint32_t)-1, nw1 = 0; i < nv; i++) + { + if(av[i].del) continue; + nw1++; + if((av[i].v>>1) == (v>>1)) continue; + if(w != (uint32_t)-1) break; + w = av[i].v; + } + if(i < nv) continue; + w1 = w; + + + v = (k<<1)+1; + av = asg_arc_a(bub_ug->g, v); + nv = asg_arc_n(bub_ug->g, v); + for (i = 0, w = (uint32_t)-1, nw2 = 0; i < nv; i++) + { + if(av[i].del) continue; + nw2++; + if((av[i].v>>1) == (v>>1)) continue; + if(w != (uint32_t)-1) break; + w = av[i].v; + } + if(i < nv) continue; + w2 = w; + + if(nw1 <= 1 && nw2 <= 1) continue; + if(w1 == (uint32_t)-1 && w2 == (uint32_t)-1) continue; + if(w1 != (uint32_t)-1) w1 ^=1; + if(w2 != (uint32_t)-1) w2 ^=1; + + if(w1 != (uint32_t)-1) + { + w = (uint32_t)-1; + if(w2 != (uint32_t)-1) w = w2^1; + + av = asg_arc_a(bub_ug->g, w1); + nv = asg_arc_n(bub_ug->g, w1); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + if((av[i].v>>1) == k) continue; + if(av[i].v == w) continue; + break; + } + if(i < nv) continue; + } + + + if(w2 != (uint32_t)-1) + { + w = (uint32_t)-1; + if(w1 != (uint32_t)-1) w = w1^1; + + av = asg_arc_a(bub_ug->g, w2); + nv = asg_arc_n(bub_ug->g, w2); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + if((av[i].v>>1) == k) continue; + if(av[i].v == w) continue; + break; + } + if(i < nv) continue; + } + + + if(w1 == (uint32_t)-1 && w2 != (uint32_t)-1) w1 = w2; + if(w1 == w2) w2 = (uint32_t)-1; + + occ_c = occ_e_1 = occ_e_2 = (uint32_t)-1; + set_b_utg_weight_flag(bub, &b, k<<1, NULL, 0, &occ_c); + if(w1 != (uint32_t)-1) set_b_utg_weight_flag(bub, &b, w1^1, NULL, 0, &occ_e_1); + if(w2 != (uint32_t)-1) set_b_utg_weight_flag(bub, &b, w2^1, NULL, 0, &occ_e_2); + + fprintf(stderr, "\n>>>>>>k=btg%.6ul (n=%u), w1=btg%.6ul (n=%u), w2=utg%.6ul (n=%u)\n", k+1, occ_c, + (w1>>1)+1, occ_e_1, (w2>>1)+1, occ_e_2); + + if(occ_c*5 >= occ_e_1) continue; + if(occ_c*5 >= occ_e_2) continue; + if(occ_c*10 >= (occ_e_1 + occ_e_2)) continue; + kv_pushp(uint64_t, occ_idx, &p); + (*p) = occ_e_1 + occ_e_2 - occ_c; + (*p) <<= 32; (*p) += k; + fprintf(stderr, "passed\n"); + } + + radix_sort_hc64(occ_idx.a, occ_idx.a + occ_idx.n); + + for (k = 0; k < occ_idx.n; ++k) + { + tmp = occ_idx.a[k]; + occ_idx.a[k] = occ_idx.a[occ_idx.n - k - 1]; + occ_idx.a[occ_idx.n - k - 1] = tmp; + } + + for (j = 0; j < occ_idx.n; j++) + { + k = (uint32_t)occ_idx.a[j]; + + v = (k<<1); + av = asg_arc_a(bub_ug->g, v); + nv = asg_arc_n(bub_ug->g, v); + for (i = 0, w = (uint32_t)-1, nw1 = 0; i < nv; i++) + { + if(av[i].del) continue; + nw1++; + if((av[i].v>>1) == (v>>1)) continue; + if(w != (uint32_t)-1) break; + w = av[i].v; + } + if(i < nv) continue; + w1 = w; + + + v = (k<<1)+1; + av = asg_arc_a(bub_ug->g, v); + nv = asg_arc_n(bub_ug->g, v); + for (i = 0, w = (uint32_t)-1, nw2 = 0; i < nv; i++) + { + if(av[i].del) continue; + nw2++; + if((av[i].v>>1) == (v>>1)) continue; + if(w != (uint32_t)-1) break; + w = av[i].v; + } + if(i < nv) continue; + w2 = w; + + if(nw1 <= 1 && nw2 <= 1) continue; + if(w1 == (uint32_t)-1 && w2 == (uint32_t)-1) continue; + if(w1 != (uint32_t)-1) w1 ^=1; + if(w2 != (uint32_t)-1) w2 ^=1; + + + + } + + free(vis); free(is_vis); free(b.b.a); kv_destroy(occ_idx); kv_destroy(stack.a); kv_destroy(result.a); + ma_ug_destroy(copy_ug); +} + +uint32_t get_btg_occ(bubble_type* bub, uint32_t v) +{ + ma_ug_t *bub_ug = bub->b_ug; + ma_utg_t *u = NULL; + uint32_t k_i, k_j, *a = NULL, n, tan_occ = 0; + + u = &(bub_ug->u.a[v]); + for (k_i = 0; k_i < u->n; k_i++) + { + get_bubbles(bub, u->a[k_i]>>33, NULL, NULL, &a, &n, NULL); + for (k_j = 0; k_j < n; k_j++) + { + tan_occ += bub->ug->u.a[a[k_j]>>1].n; + } + } + return tan_occ; +} + +int check_bubble_tangle(bubble_type* bub, ma_ug_t* ug, uint32_t beg, uint32_t sink, +double side_rate, double total_rate, uint32_t beg_occ, uint32_t sink_occ, +uint8_t* is_vis, kvec_t_u32_warp* stack, kvec_t_u32_warp* res, uint8_t* chain_flag, +uint32_t* extra_check) +{ + if(extra_check) (*extra_check) = 1; + uint32_t cur, tan_occ = 0, ncur, i, no_first = 0; + asg_arc_t *acur = NULL; + memset(is_vis, 0, ug->g->n_seq<<1); + stack->a.n = 0; + kv_push(uint32_t, stack->a, beg); + if(res) res->a.n = 0; + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + + if(no_first && cur == beg) return 0; + if(sink != (uint32_t)-1 && cur == sink) return 0; + + + if(is_vis[cur] == 0 && is_vis[cur^1] == 0) + { + if((cur>>1) != (beg>>1) && (sink == (uint32_t)-1 || (cur>>1) != (sink>>1))) + { + if(res) kv_push(uint32_t, res->a, cur); + if(chain_flag && chain_flag[cur>>1] != 0 && extra_check) + { + (*extra_check) = 0; + } + + if(bub) + { + tan_occ += get_btg_occ(bub, cur>>1); + if(tan_occ*side_rate >= beg_occ) return 0; + if(sink != (uint32_t)-1 && (tan_occ*side_rate >= sink_occ)) return 0; + if(tan_occ*total_rate >= (beg_occ + ((sink != (uint32_t)-1)?sink_occ : 0))) return 0; + } + } + } + + + if(is_vis[cur] == 0 && cur != (beg^1) && (sink == (uint32_t)-1 || cur != (sink^1))) + { + is_vis[cur] = 1; + ncur = asg_arc_n(ug->g, cur); + acur = asg_arc_a(ug->g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + + if(acur[i].v == beg) return 0; + if(sink != (uint32_t)-1 && acur[i].v == sink) return 0; + + if(is_vis[acur[i].v]) continue; + kv_push(uint32_t, stack->a, acur[i].v); + } + } + is_vis[cur] = 1; + + + cur^=1; + if(is_vis[cur] == 0 && cur != (beg^1) && (sink == (uint32_t)-1 || cur != (sink^1))) + { + is_vis[cur] = 1; + ncur = asg_arc_n(ug->g, cur); + acur = asg_arc_a(ug->g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + + if(acur[i].v == beg) return 0; + if(sink != (uint32_t)-1 && acur[i].v == sink) return 0; + + if(is_vis[acur[i].v]) continue; + kv_push(uint32_t, stack->a, acur[i].v); + } + } + is_vis[cur] = 1; + no_first = 1; + } + + if(bub) + { + if(tan_occ*side_rate >= beg_occ) return 0; + if(sink != (uint32_t)-1 && (tan_occ*side_rate >= sink_occ)) return 0; + if(tan_occ*total_rate >= (beg_occ + ((sink != (uint32_t)-1)?sink_occ : 0))) return 0; + } + + return 1; +} + + +int find_bubble_tangle(bubble_type* bub, ma_ug_t* ug, uint8_t* is_vis, uint8_t* is_vis2, +uint32_t v, double side_rate, double total_rate, kvec_t_u32_warp* stack, +kvec_t_u32_warp* stack2, kvec_t_u32_warp* res_btg, kvec_t_u32_warp* res_utg, uint8_t* chain_flag, +uint32_t* r_b_utg_beg, uint32_t* r_b_utg_sink, uint32_t* r_b_tg_beg, uint32_t* r_b_tg_sink, +uint32_t* r_utg_beg, uint32_t* r_utg_sink) +{ + (*r_b_utg_beg) = (*r_b_utg_sink) = (*r_b_tg_beg) = (*r_b_tg_sink) = (*r_utg_beg) = (*r_utg_sink) = (uint32_t)-1; + ma_ug_t *bub_ug = bub->b_ug; + ma_utg_t *u = NULL; + uint32_t tan_occ = 0, cur, ncur, i, k, no_root = 0, v_occ, c_occ, utg_occ, w, btg_beg, btg_sink, utg_beg, utg_sink, is_t, extra_check; + stack->a.n = 0; + asg_arc_t *acur = NULL; + + memset(is_vis, 0, bub_ug->g->n_seq<<1); + stack->a.n = 0; + kv_push(uint32_t, stack->a, v); + v_occ = get_btg_occ(bub, v>>1); + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + if(is_vis[cur]) continue; + + c_occ = 0; + if(no_root && cur == v) return 0; + if(no_root && is_vis[cur] == 0 && is_vis[cur^1] == 0) + { + c_occ = get_btg_occ(bub, cur>>1); + ///assume v_occ is the beg node, c_occ is the end node, which means tan_occ cannot be too large + if((tan_occ*side_rate) < c_occ && (tan_occ*total_rate) < (c_occ + v_occ)) + { + if(check_bubble_tangle(bub, bub->b_ug, v, cur^1, side_rate, total_rate, v_occ, c_occ, + is_vis2, stack2, NULL, NULL, NULL)) + { + check_bubble_tangle(bub, bub->b_ug, v, cur^1, side_rate, total_rate, v_occ, c_occ, + is_vis2, stack2, res_btg, NULL, NULL); + + for (k = 0; k < res_btg->a.n; k++) + { + set_b_utg_weight_flag(bub, NULL, res_btg->a.a[k], chain_flag, 0, NULL); + } + btg_beg = v; btg_sink = cur^1;///b_utg id + + u = &(bub_ug->u.a[btg_beg>>1]); + if((btg_beg&1)==1) + { + get_bubbles(bub, (u->a[0]>>32)>>1, (((u->a[0]>>32)&1)^1)==1?&w:NULL, + (((u->a[0]>>32)&1)^1) == 0?&w:NULL, NULL, NULL, NULL); + (*r_b_tg_beg) = u->a[0]>>32; + } + else + { + get_bubbles(bub, (u->a[u->n-1]>>32)>>1, ((u->a[u->n-1]>>32)&1)==1?&w:NULL, + ((u->a[u->n-1]>>32)&1) == 0?&w:NULL, NULL, NULL, NULL); + (*r_b_tg_beg) = u->a[u->n-1]>>32; + } + utg_beg = w^1; ///ug id + + + u = &(bub_ug->u.a[btg_sink>>1]); + if((btg_sink&1)==1) + { + get_bubbles(bub, (u->a[0]>>32)>>1, (((u->a[0]>>32)&1)^1)==1?&w:NULL, + (((u->a[0]>>32)&1)^1) == 0?&w:NULL, NULL, NULL, NULL); + (*r_b_tg_sink) = u->a[0]>>32; + } + else + { + get_bubbles(bub, (u->a[u->n-1]>>32)>>1, ((u->a[u->n-1]>>32)&1)==1?&w:NULL, + ((u->a[u->n-1]>>32)&1) == 0?&w:NULL, NULL, NULL, NULL); + (*r_b_tg_sink) = u->a[u->n-1]>>32; + } + utg_sink = w^1; ///ug id + + is_t = check_bubble_tangle(NULL, ug, utg_beg, utg_sink, side_rate, total_rate, + (uint32_t)-1, (uint32_t)-1, is_vis2, stack2, res_utg, chain_flag, &extra_check); + + if(is_t == 1 && extra_check == 0) + { + for (k = utg_occ = 0; k < res_utg->a.n; k++) + { + if(IF_HOM((res_utg->a.a[k]>>1), *bub)) continue; + utg_occ += ug->u.a[res_utg->a.a[k]>>1].n; + } + + if(utg_occ*total_rate >= (v_occ+c_occ)) is_t = 0; + } + + for (k = 0; k < res_btg->a.n; k++) + { + set_b_utg_weight_flag(bub, NULL, res_btg->a.a[k], chain_flag, 1, NULL); + } + + if(is_t) + { + (*r_b_utg_beg) = btg_beg; + (*r_b_utg_sink) = btg_sink; + (*r_utg_beg) = utg_beg; + (*r_utg_sink) = utg_sink; + return is_t; + } + } + } + } + + is_vis[cur] = 1; + if(cur != (v^1)) + { + ncur = asg_arc_n(bub_ug->g, cur); + acur = asg_arc_a(bub_ug->g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if(acur[i].v == v) return 0; + if(is_vis[acur[i].v]) continue; + kv_push(uint32_t, stack->a, acur[i].v); + } + } + + + if(no_root) tan_occ += c_occ; + if((tan_occ*side_rate) >= v_occ) return 0; + no_root = 1; + } + + if(tan_occ*side_rate >= v_occ) return 0; + if(tan_occ*total_rate >= v_occ) return 0; + //let one end as a tangle + if(check_bubble_tangle(bub, bub->b_ug, v, (uint32_t)-1, side_rate, total_rate, v_occ, (uint32_t)-1, + is_vis2, stack2, res_btg, NULL, NULL) == 0) + { + return 0; + } + + for (k = 0; k < res_btg->a.n; k++) + { + set_b_utg_weight_flag(bub, NULL, res_btg->a.a[k], chain_flag, 0, NULL); + } + + btg_beg = v; + u = &(bub_ug->u.a[btg_beg>>1]); + if((btg_beg&1)==1) + { + get_bubbles(bub, (u->a[0]>>32)>>1, (((u->a[0]>>32)&1)^1)==1?&w:NULL, + (((u->a[0]>>32)&1)^1) == 0?&w:NULL, NULL, NULL, NULL); + (*r_b_tg_beg) = u->a[0]>>32; + } + else + { + get_bubbles(bub, (u->a[u->n-1]>>32)>>1, ((u->a[u->n-1]>>32)&1)==1?&w:NULL, + ((u->a[u->n-1]>>32)&1) == 0?&w:NULL, NULL, NULL, NULL); + (*r_b_tg_beg) = u->a[u->n-1]>>32; + } + utg_beg = w^1; + + is_t = check_bubble_tangle(NULL, ug, utg_beg, (uint32_t)-1, side_rate, total_rate, + (uint32_t)-1, (uint32_t)-1, is_vis2, stack2, res_utg, chain_flag, &extra_check); + + if(is_t == 1 && extra_check == 0) + { + for (k = utg_occ = 0; k < res_utg->a.n; k++) + { + if(IF_HOM((res_utg->a.a[k]>>1), *bub)) continue; + utg_occ += ug->u.a[res_utg->a.a[k]>>1].n; + } + + if(utg_occ*total_rate >= v_occ) is_t = 0; + } + + for (k = 0; k < res_btg->a.n; k++) + { + set_b_utg_weight_flag(bub, NULL, res_btg->a.a[k], chain_flag, 1, NULL); + } + + if(is_t) + { + (*r_b_utg_beg) = btg_beg; + (*r_utg_beg) = utg_beg; + } + return is_t; +} + +uint32_t get_utg_end_from_btg(bubble_type* bub, ma_ug_t *bub_ug, uint32_t v) +{ + ma_utg_t *u = &(bub_ug->u.a[v>>1]); + + if((v&1)==1) + { + return (u->a[0]>>32)^1; + } + else + { + return u->a[u->n-1]>>32; + } +} + +void drop_g_edges_by_utg(bubble_type* bub, asg_t *bsg, ma_ug_t *bub_ug, kvec_t_u32_warp* res_btg, +uint32_t b_utg_beg, uint32_t b_utg_sink) +{ + uint32_t i, k, v, root, nv; + asg_arc_t *av = NULL; + if(b_utg_beg != (uint32_t)-1) + { + root = b_utg_beg; + v = get_utg_end_from_btg(bub, bub_ug, root); + nv = asg_arc_n(bsg, v); + av = asg_arc_a(bsg, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + av[i].del = 1; + asg_arc_del(bsg, (av[i].v)^1, (av[i].ul>>32)^1, 1); + } + } + + if(b_utg_sink != (uint32_t)-1) + { + root = b_utg_sink; + v = get_utg_end_from_btg(bub, bub_ug, root); + nv = asg_arc_n(bsg, v); + av = asg_arc_a(bsg, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + av[i].del = 1; + asg_arc_del(bsg, (av[i].v)^1, (av[i].ul>>32)^1, 1); + } + } + + + if(res_btg == NULL) return; + + for (k = 0; k < res_btg->a.n; k++) + { + root = res_btg->a.a[k]; + v = get_utg_end_from_btg(bub, bub_ug, root); + nv = asg_arc_n(bsg, v); + av = asg_arc_a(bsg, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + av[i].del = 1; + asg_arc_del(bsg, (av[i].v)^1, (av[i].ul>>32)^1, 1); + } + + + root = res_btg->a.a[k]^1; + v = get_utg_end_from_btg(bub, bub_ug, root); + nv = asg_arc_n(bsg, v); + av = asg_arc_a(bsg, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + av[i].del = 1; + asg_arc_del(bsg, (av[i].v)^1, (av[i].ul>>32)^1, 1); + } + } +} + +void debug_tangle_bubble(bubble_type* bub, long long beg_idx, long long end_idx, const char* command) +{ + // long long beg_idx = (long long)bub->b_g->n_seq - bub->tangle_bub; + // long long end_idx = (long long)bub->b_g->n_seq - 1; + long long i, j, k; + ma_utg_t *u = NULL; + uint32_t beg_utg, sink_utg, *a = NULL, n, btg_left, ori_left, btg_right, ori_right, root_0, root_1; + for (i = beg_idx; i <= end_idx; i++) + { + get_bubbles(bub, i, &beg_utg, &sink_utg, &a, &n, NULL); + fprintf(stderr, "\n(%lld) %s: beg=utg%.6ul, sink=utg%.6ul, n: %u\n", i, command, (beg_utg>>1)+1, (sink_utg>>1)+1, n); + for (k = 0; k < n; k++) + { + fprintf(stderr, "mid=utg%.6ul\n", (a[k]>>1)+1); + } + + for (j = 0; j < bub->b_ug->g->n_seq; j++) + { + u = &(bub->b_ug->u.a[j]); + if(u->n) continue; + for (k = 0; k < u->n; k++) + { + if((long long)(u->a[k]>>33) != i) continue; + fprintf(stderr, "is the %lld-th bubble at btg%.6lldl\n", k, j+1); + if(k > 0) + { + btg_left = u->a[k-1]>>33; + ori_left = u->a[k-1]>>32&1; + get_bubbles(bub, btg_left, ori_left == 1?&root_0:NULL, ori_left == 0?&root_0:NULL, NULL, NULL, NULL); + fprintf(stderr, "left-utg%.6ul\n", (ori_left>>1)+1); + } + + if(k + 1 < u->n) + { + btg_right = u->a[k+1]>>33; + ori_right = (u->a[k+1]>>32&1)^1; + get_bubbles(bub, btg_right, ori_right == 1?&root_1:NULL, ori_right == 0?&root_1:NULL, NULL, NULL, NULL); + fprintf(stderr, "right-utg%.6ul\n", (ori_right>>1)+1); + } + } + } + + } +} + +uint32_t print_b_utg_occ(bubble_type* bub, uint32_t v) +{ + ma_ug_t *bub_ug = bub->b_ug; + ma_utg_t *u = NULL; + uint32_t k_i, k_j, *a = NULL, n, tan_occ = 0, beg, sink; + + + u = &(bub_ug->u.a[v]); + fprintf(stderr, "\nstart: %u-th bubble-utg-start (# bubbles: %u)\n", v, (uint32_t)u->n); + for (k_i = 0; k_i < u->n; k_i++) + { + get_bubbles(bub, u->a[k_i]>>33, &beg, &sink, &a, &n, NULL); + for (k_j = 0; k_j < n; k_j++) + { + tan_occ += bub->ug->u.a[a[k_j]>>1].n; + } + + fprintf(stderr, "bid: %lu, n: %u, beg-utg%.6dl(%u), sink-utg%.6dl(%u)\n", u->a[k_i]>>33, n, (beg>>1)+1, beg&1, (sink>>1)+1, sink&1); + } + + fprintf(stderr, "end: %u-th bubble-utg-end\n\n", v); + return tan_occ; +} + +void update_bsg(asg_t *bsg, kvec_asg_arc_t_warp* edges) +{ + asg_arc_t *t = NULL; + uint32_t k, l, i, convex, max_i; + long long max, nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + + for (k = 0; k < edges->a.n; k++) + { + t = asg_arc_pushp(bsg); + *t = edges->a.a[k]; + } + bsg->is_srt = 0; free(bsg->idx); bsg->idx = 0; + asg_cleanup(bsg); + + + + radix_sort_asg_e(edges->a.a, edges->a.a + edges->a.n); + for (k = 1, l = 0; k <= edges->a.n; ++k) + { + if (k == edges->a.n || (edges->a.a[k].ul>>32) != (edges->a.a[l].ul>>32)) + { + if(k - l > 1) + { + for (i = l, max = -1, max_i = (uint32_t)-1; i < k; i++) + { + get_unitig(bsg, NULL, edges->a.a[i].v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, + &max_stop_baseLen, 1, NULL); + if(max < nodeLen) max = nodeLen, max_i = i; + } + + ///fprintf(stderr, "k - l: %u, max_i: %u\n", k - l, max_i); + for (i = l; i < k; i++) + { + // fprintf(stderr, "i: %u, +t->ul>>32: %lu, t->v: %u\n", + // i, edges->a.a[i].ul>>32, edges->a.a[i].v); + if(i == max_i) continue; + asg_arc_del(bsg, (edges->a.a[i].ul>>32), (edges->a.a[i].v), 1); + asg_arc_del(bsg, (edges->a.a[i].v)^1, (edges->a.a[i].ul>>32)^1, 1); + ///edges->a.a[i].del = 1; + } + } + l = k; + } + } + + asg_cleanup(bsg); + +} + +void resolve_bubble_chain_tangle(ma_ug_t* ug, bubble_type* bub) +{ + // double index_time = yak_realtime(); + ma_ug_t *bub_ug = bub->b_ug; + asg_t *bsg = bub->b_g; + uint32_t k, i, v, n_vx, new_bub; + n_vx = MAX((MAX(ug->g->n_seq<<1, bub->b_ug->g->n_seq<<1)), bub->b_g->n_seq<<1); + buf_t b; memset(&b, 0, sizeof(buf_t)); + kvec_t_u32_warp stack, stack2, res_btg, res_utg; + kv_init(stack.a); kv_init(stack2.a); kv_init(res_btg.a); kv_init(res_utg.a); + kvec_asg_arc_t_warp edges; kv_init(edges.a); + uint8_t *is_vis = NULL; CALLOC(is_vis, n_vx); + uint8_t *is_vis2 = NULL; CALLOC(is_vis2, n_vx); + uint8_t *is_used = NULL; CALLOC(is_used, n_vx); + uint8_t *chain_flag = NULL; CALLOC(chain_flag, n_vx); + kvec_t(uint64_t) occ_idx; kv_init(occ_idx); uint64_t tmp, *p = NULL; + double side_rate = 2.5, total_rate = 8; + uint32_t b_utg_beg, b_utg_sink, b_tg_beg, b_tg_sink, utg_beg, utg_sink; + + + while(1) + { + occ_idx.n = 0; edges.a.n = 0; + if(n_vx < (uint32_t)(MAX((MAX(ug->g->n_seq<<1, bub->b_ug->g->n_seq<<1)), bub->b_g->n_seq<<1))) + { + n_vx = MAX((MAX(ug->g->n_seq<<1, bub->b_ug->g->n_seq<<1)), bub->b_g->n_seq<<1); + is_vis = (uint8_t*)realloc(is_vis, n_vx); + is_vis2 = (uint8_t*)realloc(is_vis2, n_vx); + is_used = (uint8_t*)realloc(is_used, n_vx); + chain_flag = (uint8_t*)realloc(chain_flag, n_vx); + } + memset(is_vis, 0, n_vx); + memset(is_vis2, 0, n_vx); + memset(is_used, 0, n_vx); + memset(chain_flag, 0, n_vx); + if(bub->num.n > 0) bub->num.n--; + new_bub = bub->b_g->n_seq; + //label all unitigs in bubble chain + for (k = 0; k < bub_ug->g->n_seq; k++) + { + kv_pushp(uint64_t, occ_idx, &p); + (*p) = get_btg_occ(bub, k); + (*p) <<= 32; (*p) += k; + set_b_utg_weight_flag(bub, NULL, k<<1, chain_flag, 1, NULL); + } + radix_sort_hc64(occ_idx.a, occ_idx.a + occ_idx.n); + for (k = 0; k < occ_idx.n>>1; ++k) + { + tmp = occ_idx.a[k]; + occ_idx.a[k] = occ_idx.a[occ_idx.n - k - 1]; + occ_idx.a[occ_idx.n - k - 1] = tmp; + } + + for (k = 0; k < bub_ug->g->n_seq; k++)///start from the longest chain + { + v = ((uint32_t)(occ_idx.a[k]))<<1; + if(is_used[v] == 0 && asg_arc_n(bub_ug->g, v) > 0) + { + if(find_bubble_tangle(bub, ug, is_vis, is_vis2, v, side_rate, total_rate, &stack, &stack2, + &res_btg, &res_utg, chain_flag, &b_utg_beg, &b_utg_sink, &b_tg_beg, &b_tg_sink, + &utg_beg, &utg_sink)) + { + if(utg_beg != (uint32_t)-1 && (!IF_HOM(utg_beg>>1, *bub))) + { + kv_push(uint32_t, res_utg.a, utg_beg); + } + if(utg_sink != (uint32_t)-1 && (!IF_HOM(utg_sink>>1, *bub))) + { + kv_push(uint32_t, res_utg.a, utg_sink); + } + + for (i = 0; i < res_btg.a.n; i++) + { + is_used[res_btg.a.a[i]] = 1; + is_used[res_btg.a.a[i]^1] = 1; + } + if(b_utg_beg != (uint32_t)-1) is_used[b_utg_beg] = 1; + if(b_utg_sink != (uint32_t)-1) is_used[b_utg_sink] = 1; + if(b_tg_beg != (uint32_t)-1) b_tg_beg>>=1; + if(b_tg_sink != (uint32_t)-1) b_tg_sink>>=1; + update_bubble_graph(&res_utg, utg_beg, b_tg_beg, utg_sink, b_tg_sink, + bub, &edges, bsg, NULL, NULL, ug, NULL, 0); + drop_g_edges_by_utg(bub, bsg, bub_ug, &res_btg, b_utg_beg, b_utg_sink); + } + } + + + v ^= 1; + if(is_used[v] == 0 && asg_arc_n(bub_ug->g, v) > 0) + { + + if(find_bubble_tangle(bub, ug, is_vis, is_vis2, v, side_rate, total_rate, &stack, &stack2, + &res_btg, &res_utg, chain_flag, &b_utg_beg, &b_utg_sink, &b_tg_beg, &b_tg_sink, + &utg_beg, &utg_sink)) + { + if(utg_beg != (uint32_t)-1 && (!IF_HOM(utg_beg>>1, *bub))) + { + kv_push(uint32_t, res_utg.a, utg_beg); + } + if(utg_sink != (uint32_t)-1 && (!IF_HOM(utg_sink>>1, *bub))) + { + kv_push(uint32_t, res_utg.a, utg_sink); + } + + for (i = 0; i < res_btg.a.n; i++) + { + is_used[res_btg.a.a[i]] = 1; + is_used[res_btg.a.a[i]^1] = 1; + } + + if(b_utg_beg != (uint32_t)-1) is_used[b_utg_beg] = 1; + if(b_utg_sink != (uint32_t)-1) is_used[b_utg_sink] = 1; + if(b_tg_beg != (uint32_t)-1) b_tg_beg>>=1; + if(b_tg_sink != (uint32_t)-1) b_tg_sink>>=1; + /*******************************for debug************************************/ + // if(utg_beg == (utg_sink^1)) + // { + // print_b_utg_occ(bub, b_utg_beg>>1); + // print_b_utg_occ(bub, b_utg_sink>>1); + // print_b_utg_occ(bub, 42); + // ///print_debug_bubble_graph(bub, ug, asm_opt.output_file_name); + // } + /*******************************for debug************************************/ + update_bubble_graph(&res_utg, utg_beg, b_tg_beg, utg_sink, b_tg_sink, bub, &edges, bsg, NULL, NULL, ug, NULL, 0); + drop_g_edges_by_utg(bub, bsg, bub_ug, &res_btg, b_utg_beg, b_utg_sink); + ///fprintf(stderr, "->>>>>>beg=btg%.6ul, sink=btg%.6ul\n", (b_utg_beg>>1)+1, (b_utg_sink>>1)+1); + } + } + } + kv_push(uint32_t, bub->num, bub->list.n); + new_bub = bub->b_g->n_seq - new_bub; + bub->tangle_bub += new_bub; + ///actually not useful, and may have bug when one bubble at multipe chains + if(new_bub) update_bub_b_s_idx(bub); + update_bsg(bsg, &edges); + + ma_ug_destroy(bub_ug); + bub_ug = ma_ug_gen(bub->b_g); + bub->b_ug = bub_ug; + ///fprintf(stderr, "new_bub: %u, bub->tangle_bub: %lu\n", new_bub, bub->tangle_bub); + if(new_bub == 0) break; + } + + kv_destroy(bub->chain_weight); + ma_utg_t *u = NULL; + bub_ug = bub->b_ug; + kv_malloc(bub->chain_weight, bub_ug->u.n); bub->chain_weight.n = bub_ug->u.n; + for (i = 0; i < bub_ug->u.n; i++) + { + u = &(bub_ug->u.a[i]); + bub->chain_weight.a[i].id = i; + // if(u->n <= 1) ///not a chain + // { + // bub->chain_weight.a[i].b_occ = bub->chain_weight.a[i].g_occ = 0; + // bub->chain_weight.a[i].del = 1; + // } + // else + { + bub->chain_weight.a[i].del = 0; + calculate_chain_weight(u, bub, ug, &(bub->chain_weight.a[i])); + } + } + qsort(bub->chain_weight.a, bub->chain_weight.n, sizeof(chain_w_type), cmp_chain_weight); + + ///debug_tangle_bubble(bub); + + free(is_vis); free(is_vis2); free(is_used); free(chain_flag); free(b.b.a); + kv_destroy(occ_idx); kv_destroy(stack.a); kv_destroy(stack2.a); + kv_destroy(res_btg.a); kv_destroy(res_utg.a); kv_destroy(edges.a); + + ///print_debug_bubble_graph(bub, ug, asm_opt.output_file_name); + // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); +} + +void update_bubble_chain(ma_ug_t* ug, bubble_type* bub, uint32_t is_middle, uint32_t is_end) +{ + // double index_time = yak_realtime(); + if(bub->b_ug) ma_ug_destroy(bub->b_ug); + if(bub->chain_weight.a) kv_destroy(bub->chain_weight); + kvec_t_u32_warp broken; + kv_init(broken.a); + kvec_asg_arc_t_warp edges; + kv_init(edges.a); + ma_utg_t *u = NULL; + asg_arc_t *t = NULL; + asg_t *sg = ug->g; + pdq pq; + init_pdq(&pq, sg->n_seq<<1); + asg_t *bsg = bub->b_g; + ma_ug_t *bub_ug = NULL; + bub_ug = ma_ug_gen(bub->b_g); + uint32_t i, j, k_i, rId_0, ori_0, root_0, rId_1, ori_1, root_1, n_vtx = sg->n_seq<<1, new_bub; + uint32_t *pre = NULL; MALLOC(pre, n_vtx); + uint8_t* vis_flag = NULL; MALLOC(vis_flag, ug->g->n_seq*2); + kvec_t_u32_warp stack; kv_init(stack.a); + ///chain_w_type x; + ///uint64_t end_thres; + + uint8_t *bsg_idx = NULL; CALLOC(bsg_idx, n_vtx>>1); + for (i = 0; i < bub_ug->u.n; i++)///label all unitigs within the bubble chains + { + u = &(bub_ug->u.a[i]);///a bubble chain + if(u->n == 0) continue; + for (k_i = 0; k_i < u->n; k_i++) + { + uint32_t *a, n; + get_bubbles(bub, u->a[k_i]>>33, &root_0, &root_1, &a, &n, NULL); + for (j = 0; j < n; j++) + { + bsg_idx[a[j]>>1] = 1; + } + bsg_idx[root_0>>1] = 1; + bsg_idx[root_1>>1] = 1; + } + } + + if(bub->num.n > 0) bub->num.n--; + new_bub = bub->b_g->n_seq; + for (i = 0; i < bub_ug->u.n; i++) + { + u = &(bub_ug->u.a[i]);///bubble chain + if(u->n == 0) continue; + ///end_thres = calculate_chain_weight(u, bub, ug, &x); + if(is_middle) + { + for (k_i = 0; k_i < u->n; k_i++) + { + if(k_i+1 >= u->n) continue; + ///note: must igore .del here, since bsg might be changed + t = &(arc_first(bsg, u->a[k_i]>>32)); + if(t->el == 1) continue;///if a[k_i] and a[k_i+1] are directly connected without any tangle involoved + + rId_0 = u->a[k_i]>>33; + ori_0 = u->a[k_i]>>32&1; + get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); + + rId_1 = u->a[k_i+1]>>33; + ori_1 = (u->a[k_i+1]>>32&1)^1; + get_bubbles(bub, rId_1, ori_1 == 1?&root_1:NULL, ori_1 == 0?&root_1:NULL, NULL, NULL, NULL); + + broken.a.n = 0;///just collect all nodes between root_0 and root_1 + get_related_bub_nodes(&broken, bub, &pq, sg, pre, root_0, root_1, NULL); + get_related_bub_nodes(&broken, bub, &pq, sg, pre, root_1, root_0, NULL); + ///no need to cut the edge, we still have chance to flip by chain + if(double_check_broken_bubble(ug->g, &broken, root_0^1, root_1^1, vis_flag, + ug->g->n_seq*2, &stack, NULL, NULL/**bsg, t**/) == 0) + { + continue; + } + if(!IF_HOM(root_0>>1, *bub)) kv_push(uint32_t, broken.a, root_0); + if(!IF_HOM(root_1>>1, *bub)) kv_push(uint32_t, broken.a, root_1); + if(broken.a.n > 0) + { + update_bubble_graph(&broken, root_0^1, rId_0, root_1^1, rId_1, bub, &edges, bsg, t, bsg_idx, ug, NULL, 1); + } + } + } + + + if(is_end) + { + if(u->n >0 && arc_cnt(bub_ug->g, (i<<1)+1) == 0) + { + rId_0 = u->a[0]>>33; + ori_0 = (u->a[0]>>32&1)^1; + get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); + broken.a.n = 0; + get_related_bub_nodes(&broken, bub, &pq, sg, pre, root_0, (uint32_t)-1, NULL); + + if(double_check_broken_bubble(ug->g, &broken, root_0^1, (uint32_t)-1, vis_flag, + ug->g->n_seq*2, &stack, NULL, NULL)) + { + if(!IF_HOM(root_0>>1, *bub)) kv_push(uint32_t, broken.a, root_0); + if(broken.a.n > 0) + { + ///fprintf(stderr, "root_0: utg%.6ul, broken.a.n: %u\n", (root_0>>1)+1, (uint32_t)broken.a.n); + update_bubble_graph(&broken, root_0^1, rId_0, (uint32_t)-1, (uint32_t)-1, bub, &edges, bsg, NULL, bsg_idx, ug, NULL, 0); + } + } + } + + + if(u->n >0 && arc_cnt(bub_ug->g, i<<1) == 0) + { + rId_1 = u->a[u->n-1]>>33; + ori_1 = u->a[u->n-1]>>32&1; + get_bubbles(bub, rId_1, ori_1 == 1?&root_1:NULL, ori_1 == 0?&root_1:NULL, NULL, NULL, NULL); + broken.a.n = 0; + get_related_bub_nodes(&broken, bub, &pq, sg, pre, root_1, (uint32_t)-1, bsg_idx); + + if(double_check_broken_bubble(ug->g, &broken, root_1^1, (uint32_t)-1, vis_flag, + ug->g->n_seq*2, &stack, NULL, NULL)) + { + if(!IF_HOM(root_1>>1, *bub)) kv_push(uint32_t, broken.a, root_1); + if(broken.a.n > 0) + { + ///fprintf(stderr, "root_1: utg%.6ul, broken.a.n: %u\n", (root_1>>1)+1, (uint32_t)broken.a.n); + update_bubble_graph(&broken, (uint32_t)-1, (uint32_t)-1, root_1^1, rId_1, bub, &edges, bsg, NULL, bsg_idx, ug, NULL, 0); + } + + } + } + } + } + kv_push(uint32_t, bub->num, bub->list.n); + new_bub = bub->b_g->n_seq - new_bub; + if(is_end) bub->b_end_bub += new_bub; + ///actually not useful, and may have bug when one bubble at multipe chains + if(new_bub) update_bub_b_s_idx(bub); + + + for (i = 0; i < edges.a.n; i++) + { + t = asg_arc_pushp(bsg); + *t = edges.a.a[i]; + } + + bsg->is_srt = 0; free(bsg->idx); bsg->idx = 0; + asg_cleanup(bsg); + ma_ug_destroy(bub_ug); + destory_pdq(&pq); + free(pre); + kv_destroy(broken.a); + kv_destroy(edges.a); + free(bsg_idx); + kv_destroy(stack.a); + free(vis_flag); + + bub->b_ug = ma_ug_gen(bub->b_g); + bub_ug = bub->b_ug; + kv_malloc(bub->chain_weight, bub_ug->u.n); bub->chain_weight.n = bub_ug->u.n; + for (i = 0; i < bub_ug->u.n; i++) + { + u = &(bub_ug->u.a[i]); + bub->chain_weight.a[i].id = i; + // if(u->n <= 1) ///not a chain + // { + // bub->chain_weight.a[i].b_occ = bub->chain_weight.a[i].g_occ = 0; + // bub->chain_weight.a[i].del = 1; + // } + // else + { + bub->chain_weight.a[i].del = 0; + calculate_chain_weight(u, bub, ug, &(bub->chain_weight.a[i])); + } + } + + qsort(bub->chain_weight.a, bub->chain_weight.n, sizeof(chain_w_type), cmp_chain_weight); + + + + /** + uint32_t d_v, d_u, v; + for (i = 0; i < bsg->n_arc; i++) + { + d_v = (uint32_t)(bsg->arc[i].ul>>32); + d_u = bsg->arc[i].v; + for (v = 0; v < bsg->n_arc; v++) + { + if(((bsg->arc[v].ul>>32) == (d_u^1)) && (bsg->arc[v].v == (d_v^1))) break; + } + + if(v == bsg->n_arc) + { + fprintf(stderr, "hahaha, el: %u, ul>>33: %lu, ul&1: %lu, v>>1: %u, v&1: %u\n", + bsg->arc[i].el, bsg->arc[i].ul>>33, (bsg->arc[i].ul>>32)&1, bsg->arc[i].v>>1, bsg->arc[i].v&1); + } + // else + // { + // fprintf(stderr, "hehehe, el: %u, ul>>33: %lu, ul&1: %lu, v>>1: %u, v&1: %u\n", + // bsg->arc[i].el, bsg->arc[i].ul>>33, (bsg->arc[i].ul>>32)&1, bsg->arc[i].v>>1, bsg->arc[i].v&1); + // } + } + + asg_arc_t *av = NULL, *au = NULL; + uint32_t nv, nu; + for (v = 0; v < (uint32_t)(bsg->n_seq<<1); v++) + { + av = asg_arc_a(bsg, v); + nv = asg_arc_n(bsg, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + + au = asg_arc_a(bsg, av[i].v^1); + nu = asg_arc_n(bsg, av[i].v^1); + for (k_i = 0; k_i < nu; k_i++) + { + if(au[k_i].del) continue; + if(au[k_i].v == (v^1)) break; + } + if(k_i == nu) fprintf(stderr, "hahaha: v: %u, u: %u\n", v, av[i].v); + } + } + **/ + // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); +} + +void set_b_utg_weight_flag(bubble_type* bub, buf_t* b, uint32_t v, uint8_t* vis_flag, uint32_t flag, uint32_t* occ) +{ + ma_ug_t *bub_ug = bub->b_ug; + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + ma_utg_t *u = NULL; + uint32_t convex, k, k_i, k_j, *a, n, beg, sink; + if(b) + { + b->b.n = 0; + get_unitig(bub_ug->g, NULL, v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, + &max_stop_baseLen, 1, b); + } + + if(occ) (*occ) = 0; + for (k = 0; k < (b?b->b.n:1); k++) + { + u = &(bub_ug->u.a[b?(b->b.a[k]>>1):(v>>1)]); + if(u->n == 0) continue; + for (k_i = 0; k_i < u->n; k_i++) + { + get_bubbles(bub, u->a[k_i]>>33, &beg, &sink, &a, &n, NULL); + + for (k_j = 0; k_j < n; k_j++) + { + if(vis_flag) vis_flag[a[k_j]>>1] = flag; + if(occ) (*occ) += bub->ug->u.a[a[k_j]>>1].n; + } + if(beg != (uint32_t)-1 && vis_flag) vis_flag[beg>>1] = flag; + if(sink != (uint32_t)-1 && vis_flag) vis_flag[sink>>1] = flag; + } + } +} + +void set_b_utg_weight_flag_xor(bubble_type* bub, ma_ug_t *bub_ug, buf_t* b, uint32_t v, uint8_t* vis_flag, uint32_t flag, uint32_t* occ) +{ + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + ma_utg_t *u = NULL; + uint32_t convex, k, k_i, k_j, *a, n, beg, sink; + if(b) + { + b->b.n = 0; + get_unitig(bub_ug->g, NULL, v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, + &max_stop_baseLen, 1, b); + } + + if(occ) (*occ) = 0; + for (k = 0; k < (b?b->b.n:1); k++) + { + u = &(bub_ug->u.a[b?(b->b.a[k]>>1):(v>>1)]); + if(u->n == 0) continue; + for (k_i = 0; k_i < u->n; k_i++) + { + get_bubbles(bub, u->a[k_i]>>33, &beg, &sink, &a, &n, NULL); + + for (k_j = 0; k_j < n; k_j++) + { + if(vis_flag) vis_flag[a[k_j]>>1] ^= flag; + if(occ) (*occ) += bub->ug->u.a[a[k_j]>>1].n; + } + if(beg != (uint32_t)-1 && vis_flag) vis_flag[beg>>1] ^= flag; + if(sink != (uint32_t)-1 && vis_flag) vis_flag[sink>>1] ^= flag; + } + } +} + +double dfs_weight(uint32_t v, uint8_t* vis_flag, uint8_t* is_vis, hc_links* link, +kvec_t_u32_warp* stack, kvec_t_u32_warp* result, uint32_t e_flag, uint32_t ava_flag, +uint32_t* link_occ) +{ + uint32_t cur, i, next = (uint32_t)-1; + stack->a.n = 0; + kv_push(uint32_t, stack->a, v); + double w = 0; + if(link_occ) (*link_occ) = 0; + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + if(is_vis[cur]) continue; + is_vis[cur] = 1; + if(cur!=v && vis_flag[cur] != ava_flag) continue; + for (i = 0; i < link->a.a[cur].e.n; i++) + { + if(link->a.a[cur].e.a[i].del) continue; + next = link->a.a[cur].e.a[i].uID; + ///if(vis_flag[next] == e_flag) + if(vis_flag[next]&e_flag) + { + w += link->a.a[cur].e.a[i].weight; + if(link_occ) (*link_occ) += link->a.a[cur].e.a[i].occ; + continue; + } + if(is_vis[next]) continue; + if(vis_flag[next] != ava_flag) continue; + kv_push(uint32_t, stack->a, next); + } + } + return w; +} + +void if_conflict_utg(uint32_t root, uint32_t* aim_0, uint32_t* aim_1, ma_ug_t* ug, uint8_t* vis_flag, +uint8_t* is_vis_2, uint32_t ava_flag, kvec_t_u32_warp* stack) +{ + uint32_t n_vx = ug->g->n_seq<<1, k, cur, ncur; + asg_arc_t *acur = NULL; + memset(is_vis_2, 0, n_vx); + + stack->a.n = 0; + kv_push(uint32_t, stack->a, root); + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + if(is_vis_2[cur]) continue; + is_vis_2[cur] = 1; + + ncur = asg_arc_n(ug->g, cur); + acur = asg_arc_a(ug->g, cur); + for (k = 0; k < ncur; k++) + { + if(acur[k].del) continue; + if(is_vis_2[acur[k].v]) continue; + if(vis_flag[acur[k].v>>1] != 0 && vis_flag[acur[k].v>>1] != ava_flag) + { + if(aim_0 && (acur[k].v>>1) == (*aim_0)) continue; + if(aim_1 && (acur[k].v>>1) == (*aim_1)) continue; + break; + } + kv_push(uint32_t, stack->a, acur[k].v); + } + + if(k < ncur) return; + } + + for (k = 0; k < n_vx; k++) + { + if(is_vis_2[k] && vis_flag[k>>1] == 0) + { + ///fprintf(stderr, "******************k=utg%.6ul, vis_flag: %u\n", (k>>1)+1, vis_flag[k>>1]); + vis_flag[k>>1] = ava_flag; + } + + } +} + +double get_chain_weight(bubble_type* bub, ma_ug_t *bub_ug, buf_t* b, uint32_t v, uint32_t convex_source, hc_links* link, +uint8_t* vis_flag, uint8_t* is_vis, ma_ug_t* ug, kvec_t_u32_warp* stack, kvec_t_u32_warp* result, +uint32_t e_flag, uint32_t ava_flag, kvec_t_u32_warp* res_utg, uint32_t* link_occ) +{ + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + ma_utg_t *u = NULL; + uint32_t convex, k, k_i, k_j, *a, n, beg, sink, uID, root, cur, ncur, n_vx = ug->g->n_seq<<1, occ; + asg_arc_t *acur = NULL; + double w = 0; + b->b.n = 0; + get_unitig(bub_ug->g, NULL, v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, + &max_stop_baseLen, 1, b); + memset(is_vis, 0, n_vx); + + for (k = 0; k < b->b.n; k++) + { + u = &(bub_ug->u.a[b->b.a[k]>>1]); + if(u->n == 0) continue; + + for (k_i = 0; k_i < u->n; k_i++) + { + get_bubbles(bub, u->a[k_i]>>33, &beg, &sink, &a, &n, NULL); + for(k_j = 0; k_j < n; k_j++) is_vis[a[k_j]] = is_vis[a[k_j]^1] = 1; + if(beg != (uint32_t)-1) is_vis[beg] = is_vis[beg^1] = 1; + if(sink != (uint32_t)-1) is_vis[sink] = is_vis[sink^1] = 1; + } + } + + u = &(bub_ug->u.a[v>>1]); + if((v&1)==0) + { + get_bubbles(bub, (u->a[0]>>32)>>1, (((u->a[0]>>32)&1)^1)==1?&root:NULL, + (((u->a[0]>>32)&1)^1) == 0?&root:NULL, NULL, NULL, NULL); + } + else + { + get_bubbles(bub, (u->a[u->n-1]>>32)>>1, ((u->a[u->n-1]>>32)&1)==1?&root:NULL, + ((u->a[u->n-1]>>32)&1) == 0?&root:NULL, NULL, NULL, NULL); + } + + root ^= 1; + ///fprintf(stderr, "root=utg%.6dl\n", (root>>1)+1); + is_vis[root] = 0; + stack->a.n = 0; + kv_push(uint32_t, stack->a, root); + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + if(is_vis[cur]) continue; + is_vis[cur] = 1; + if(vis_flag[cur>>1] == 0) vis_flag[cur>>1] = ava_flag; + + ncur = asg_arc_n(ug->g, cur); + acur = asg_arc_a(ug->g, cur); + for (k = 0; k < ncur; k++) + { + if(acur[k].del) continue; + if(is_vis[acur[k].v]) continue; + if(vis_flag[acur[k].v>>1] != 0 && vis_flag[acur[k].v>>1] != ava_flag) continue; + kv_push(uint32_t, stack->a, acur[k].v); + } + } + + + + uint32_t aim_0, aim_1, root_source; + aim_0 = root>>1; + u = &(bub_ug->u.a[convex_source>>1]); + if((convex_source&1)==1) + { + get_bubbles(bub, (u->a[0]>>32)>>1, (((u->a[0]>>32)&1)^1)==1?&root_source:NULL, + (((u->a[0]>>32)&1)^1) == 0?&root_source:NULL, NULL, NULL, NULL); + } + else + { + get_bubbles(bub, (u->a[u->n-1]>>32)>>1, ((u->a[u->n-1]>>32)&1)==1?&root_source:NULL, + ((u->a[u->n-1]>>32)&1) == 0?&root_source:NULL, NULL, NULL, NULL); + } + root_source ^= 1; + aim_1 = root_source>>1; + + ///fprintf(stderr, "aim_0=utg%.6ul, aim_1=utg%.6ul\n", aim_0+1, aim_1+1); + + cur = root_source; + ncur = asg_arc_n(ug->g, cur); + acur = asg_arc_a(ug->g, cur); + for (k_i = 0; k_i < ncur; k_i++) + { + if(acur[k_i].del) continue; + if(vis_flag[acur[k_i].v>>1] != 0) continue; + if_conflict_utg(acur[k_i].v, &aim_0, &aim_1, ug, vis_flag, is_vis, ava_flag, stack); + } + + + for (k = 0; k < ug->g->n_seq; k++) + { + if(vis_flag[k] == ava_flag) + { + cur = k<<1; + ncur = asg_arc_n(ug->g, cur); + acur = asg_arc_a(ug->g, cur); + for (k_i = 0; k_i < ncur; k_i++) + { + if(acur[k_i].del) continue; + if(vis_flag[acur[k_i].v>>1] != 0) continue; + if_conflict_utg(acur[k_i].v, &aim_0, &aim_1, ug, vis_flag, is_vis, ava_flag, stack); + } + + + + cur = (k<<1)+1; + ncur = asg_arc_n(ug->g, cur); + acur = asg_arc_a(ug->g, cur); + for (k_i = 0; k_i < ncur; k_i++) + { + if(acur[k_i].del) continue; + if(vis_flag[acur[k_i].v>>1] != 0) continue; + if_conflict_utg(acur[k_i].v, &aim_0, &aim_1, ug, vis_flag, is_vis, ava_flag, stack); + } + } + } + + + + + + + + memset(is_vis, 0, n_vx); + if(link_occ) (*link_occ) = 0; + for (k = result->a.n = 0, w = 0; k < b->b.n; k++) + { + u = &(bub_ug->u.a[b->b.a[k]>>1]); + if(u->n == 0) continue; + for (k_i = 0; k_i < u->n; k_i++) + { + get_bubbles(bub, u->a[k_i]>>33, NULL, NULL, &a, &n, NULL); + + for (k_j = 0; k_j < n; k_j++) + { + uID = a[k_j]>>1; + w += dfs_weight(uID, vis_flag, is_vis, link, stack, result, e_flag, ava_flag, &occ); + if(link_occ) (*link_occ) += occ; + } + } + } + + + for (k = 0; k < ug->g->n_seq; k++) + { + if(vis_flag[k] == ava_flag) + { + vis_flag[k] = 0; + if(res_utg && (!IF_HOM(k, *bub))) + { + kv_push(uint32_t, res_utg->a, k<<1); + } + } + } + + + return w; +} + +int double_check_bub_branch(asg_arc_t *t, ma_ug_t *bs_ug, double *e_w, uint32_t *e_occ, double cutoff, uint32_t max_w_occ) +{ + uint32_t v = t->v^1, w = (t->ul>>32)^1, i, nv, rv, max_i, w_i, *a_occ = NULL; + asg_arc_t *av = NULL; + double *aw = NULL, max_w = cutoff - 1, w_w = 1; + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + aw = (&e_w[bs_ug->g->idx[v]>>32]); + a_occ = (&e_occ[bs_ug->g->idx[v]>>32]); + + if(nv <= 1) return 1; + + for (i = rv = 0, max_i = w_i = (uint32_t)-1; i < nv; i++) + { + if(av[i].del) continue; + rv++; + if(av[i].v == w) + { + w_i = i; + w_w = aw[i]; + continue; + } + if(max_i == (uint32_t)-1) + { + max_i = i; + max_w = aw[i]; + } + else if(max_w < aw[i]) + { + max_i = i; + max_w = aw[i]; + } + } + + if(rv <= 1) return 1; ///must be here + + if(max_i == (uint32_t)-1 || w_i == (uint32_t)-1) return 0; + ///if(max_w <= max_w_cutoff) return 0; //must be <= + if(a_occ[max_i] <= max_w_occ) return 0; //must be <= + + if(w_w*cutoff < max_w) return 1; + return 0; +} + +void clean_bubble_chain_by_HiC(ma_ug_t* ug, hc_links* link, bubble_type* bub) +{ + double index_time = yak_realtime(); + ma_ug_t *bs_ug = bub->b_ug; + uint32_t v, u, i, m, max_i, nv, rv, n_vx, root, flag_pri = 1, flag_aux = 2, flag_ava = 4, occ; + double w, cutoff = 2/**, max_w_cutoff = MAX(MIN(100*OFFSET_RATE_MIN_W, OFFSET_RATE_MAX_W/100), OFFSET_RATE_MIN_W)**/; + uint32_t max_w_occ = 4; + asg_arc_t *av = NULL; + n_vx = bs_ug->g->n_seq << 1; + uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq<<1); + uint8_t *is_vis = NULL; CALLOC(is_vis, ug->g->n_seq<<1); + uint8_t *is_used = NULL; CALLOC(is_used, n_vx); + uint8_t *dedup = NULL; CALLOC(dedup, ug->g->n_seq<<1); + buf_t b; memset(&b, 0, sizeof(buf_t)); + kvec_t_u32_warp stack, result, res_utg; + kv_init(stack.a); kv_init(result.a); kv_init(res_utg.a); + double *e_w = NULL; MALLOC(e_w, bs_ug->g->n_arc); + uint32_t *e_occ = NULL, *a_occ = NULL; CALLOC(e_occ, bs_ug->g->n_arc); + double *aw = NULL, max_w = 0; + kvec_asg_arc_t_warp edges; kv_init(edges.a); + ma_ug_t *back_bs_ug = copy_untig_graph(bs_ug); + + for (i = 0; i < bs_ug->g->n_arc; i++)///weight of bs_ug's edges + { + e_w[i] = -1; + } + + for (i = 0; i < bs_ug->g->n_seq; i++)///init all chain with flag_aux + { + set_b_utg_weight_flag(bub, &b, i<<1, vis, flag_aux, NULL); + } + + + for (v = 0; v < n_vx; v++) + { + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + aw = (&e_w[bs_ug->g->idx[v]>>32]); + a_occ = (&e_occ[bs_ug->g->idx[v]>>32]); + if(nv <= 1 || get_real_length(bs_ug->g, v, NULL) <= 1) continue; + set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); + + ///fprintf(stderr, "\n******pri>btg%.6dl\n", (v>>1)+1); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + //fprintf(stderr, "aux>btg%.6dl\n", (av[i].v>>1)+1); + w = get_chain_weight(bub, bs_ug, &b, av[i].v, v, link, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, NULL, &occ); + ///fprintf(stderr, "aux>btg%.6dl, w: %f\n", (av[i].v>>1)+1, w); + aw[i] = w; + a_occ[i] = occ; + } + + set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); + } + + + for (v = 0; v < n_vx; v++) + { + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + aw = (&e_w[bs_ug->g->idx[v]>>32]); + a_occ = (&e_occ[bs_ug->g->idx[v]>>32]); + if(nv <= 1 || get_real_length(bs_ug->g, v, NULL) <= 1) continue; + + for (i = rv = 0, max_i = (uint32_t)-1; i < nv; i++) + { + if(av[i].del) continue; + if(max_i == (uint32_t)-1) + { + max_i = i; + max_w = aw[i]; + } + else if(max_w < aw[i]) + { + max_i = i; + max_w = aw[i]; + } + rv++; + } + + if(max_i == (uint32_t)-1) continue; + ///if(max_w <= max_w_cutoff) continue; //must be <= + if(a_occ[max_i] <= max_w_occ) continue; //must be <= + if(rv < 2) continue; + + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + if(i == max_i) continue; + ///if((av[i].v>>1) == (v>>1) && aw[i] <= max_w_cutoff) continue; ///might be not reasonable + if((av[i].v>>1) == (v>>1) && a_occ[i] <= max_w_occ) continue; ///might be not reasonable + if(aw[i]*cutoff < max_w && double_check_bub_branch(&av[i], bs_ug, e_w, e_occ, cutoff, max_w_occ)) + { + av[i].del = 1; asg_arc_del(bs_ug->g, (av[i].v)^1, (av[i].ul>>32)^1, 1); + } + } + } + + uint32_t rId_0, ori_0, rId_1, ori_1, root_0, root_1, new_bub; + if(bub->num.n > 0) bub->num.n--; + new_bub = bub->b_g->n_seq; + + for (v = 0; v < n_vx; v++) + { + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + rv = get_real_length(bs_ug->g, v, NULL); + if(nv == rv) continue; + if(rv != 1 || nv <= 1) continue; + get_real_length(bs_ug->g, v, &u); + u ^= 1; + if(get_real_length(bs_ug->g, u, NULL) != 1) continue; + drop_g_edges_by_utg(bub, bub->b_g, bs_ug, NULL, v, u); + if(is_used[v] || is_used[u]) continue; + + is_used[v] = is_used[u] = 1; + root = get_utg_end_from_btg(bub, bs_ug, v); + rId_0 = root>>1; + ori_0 = root&1; + get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); + + root = get_utg_end_from_btg(bub, bs_ug, u); + rId_1 = root>>1; + ori_1 = root&1; + get_bubbles(bub, rId_1, ori_1 == 1?&root_1:NULL, ori_1 == 0?&root_1:NULL, NULL, NULL, NULL); + + res_utg.a.n = 0; + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); + get_chain_weight(bub, back_bs_ug, &b, u^1, v, link, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); + for (i = 0; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 1; + + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); + get_chain_weight(bub, back_bs_ug, &b, v^1, u, link, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); + for (; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 2; + + + for (i = m = 0; i < res_utg.a.n; i++) + { + if(dedup[res_utg.a.a[i]>>1] == 3) + { + res_utg.a.a[m] = res_utg.a.a[i]; + m++; + } + dedup[res_utg.a.a[i]>>1] = 0; + } + res_utg.a.n = m; + + // fprintf(stderr, "res_utg.a.n: %u, m: %u, beg-utg%.6ul, sink-utg%.6ul\n", + // res_utg.a.n, m, (root_0>>1)+1, (root_1>>1)+1); + + if(!IF_HOM(root_0>>1, *bub)) kv_push(uint32_t, res_utg.a, root_0); + if(!IF_HOM(root_1>>1, *bub)) kv_push(uint32_t, res_utg.a, root_1); + + update_bubble_graph(&res_utg, root_0^1, rId_0, root_1^1, rId_1, bub, &edges, bub->b_g, NULL, NULL, ug, NULL, 0); + + ///fprintf(stderr, "\n******src-btg%.6ul------>dest-btg%.6ul\n", (v>>1)+1, (u>>1)+1); + } + + kv_push(uint32_t, bub->num, bub->list.n); + new_bub = bub->b_g->n_seq - new_bub; + bub->cross_bub += new_bub; + ///actually not useful, and may have bug when one bubble at multipe chains + if(new_bub) update_bub_b_s_idx(bub); + + ///debug_tangle_bubble(bub, bub->b_g->n_seq - bub->cross_bub, bub->b_g->n_seq - 1, "Cross-tangle"); + update_bsg(bub->b_g, &edges); + + ma_ug_destroy(bs_ug); + bs_ug = ma_ug_gen(bub->b_g); + bub->b_ug = bs_ug; + kv_destroy(bub->chain_weight); + ma_utg_t *u_x = NULL; + bs_ug = bub->b_ug; + kv_malloc(bub->chain_weight, bs_ug->u.n); bub->chain_weight.n = bs_ug->u.n; + for (i = 0; i < bs_ug->u.n; i++) + { + u_x = &(bs_ug->u.a[i]); + bub->chain_weight.a[i].id = i; + // if(u->n <= 1) ///not a chain + // { + // bub->chain_weight.a[i].b_occ = bub->chain_weight.a[i].g_occ = 0; + // bub->chain_weight.a[i].del = 1; + // } + // else + { + bub->chain_weight.a[i].del = 0; + calculate_chain_weight(u_x, bub, ug, &(bub->chain_weight.a[i])); + } + } + qsort(bub->chain_weight.a, bub->chain_weight.n, sizeof(chain_w_type), cmp_chain_weight); + + + + free(vis); free(is_vis); free(is_used); free(dedup); free(b.b.a); free(e_w); free(e_occ); + kv_destroy(stack.a); kv_destroy(result.a); kv_destroy(res_utg.a); kv_destroy(edges.a); + ma_ug_destroy(back_bs_ug); + fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); +} + +void append_boundary_chain(ma_ug_t* ug, hc_links* link, bubble_type* bub) +{ + double index_time = yak_realtime(); + ma_ug_t *bs_ug = bub->b_ug; + uint32_t v, u, i, k, beg_idx, m, nv, n_vx, flag_pri = 1, flag_aux = 2, flag_ava = 4; + uint32_t root, rId_0, ori_0, root_0, new_bub; + asg_arc_t *av = NULL; + n_vx = bs_ug->g->n_seq << 1; + uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq<<1); + uint8_t *is_vis = NULL; CALLOC(is_vis, ug->g->n_seq<<1); + uint8_t *is_used = NULL; CALLOC(is_used, n_vx); + uint8_t *dedup = NULL; CALLOC(dedup, ug->g->n_seq<<1); + buf_t b; memset(&b, 0, sizeof(buf_t)); + kvec_t_u32_warp stack, result, res_utg; + kv_init(stack.a); kv_init(result.a); kv_init(res_utg.a); + kvec_asg_arc_t_warp edges; kv_init(edges.a); + + for (i = 0; i < bs_ug->g->n_seq; i++) + { + set_b_utg_weight_flag(bub, &b, i<<1, vis, flag_aux, NULL); + } + + if(bub->num.n > 0) bub->num.n--; + new_bub = bub->b_g->n_seq; + for (v = 0; v < n_vx; v++) + { + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + if(nv == 0 || get_real_length(bs_ug->g, v, NULL) == 0) continue; + res_utg.a.n = 0; + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + u = av[i].v^1; + /** + beg_idx = res_utg.a.n; + set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); + get_chain_weight(bub, bs_ug, &b, u^1, v, link, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); + set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); + for (k = m = beg_idx; k < res_utg.a.n; k++) + { + if(dedup[res_utg.a.a[k]>>1] != 0) continue; + dedup[res_utg.a.a[k]>>1] = 1; + res_utg.a.a[m] = res_utg.a.a[k]; + m++; + } + res_utg.a.n = m; + **/ + beg_idx = res_utg.a.n; + set_b_utg_weight_flag_xor(bub, bs_ug, &b, u^1, vis, flag_pri, NULL); + get_chain_weight(bub, bs_ug, &b, v^1, u, link, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); + set_b_utg_weight_flag_xor(bub, bs_ug, &b, u^1, vis, flag_pri, NULL); + for (k = m = beg_idx; k < res_utg.a.n; k++) + { + if(dedup[res_utg.a.a[k]>>1] != 0) continue; + dedup[res_utg.a.a[k]>>1] = 1; + res_utg.a.a[m] = res_utg.a.a[k]; + m++; + } + res_utg.a.n = m; + } + + for (k = 0; k < res_utg.a.n; k++) dedup[res_utg.a.a[k]>>1] = 0; + /*******************************for debug************************************/ + // for (i = 0; i < res_utg.a.n; i++) + // { + // for (k = 0; k < res_utg.a.n; k++) + // { + // if(k == i) continue; + // if((res_utg.a.a[i]>>1) == (res_utg.a.a[k]>>1)) fprintf(stderr, "ERROR\n"); + // } + // } + /*******************************for debug************************************/ + + root = get_utg_end_from_btg(bub, bs_ug, v); + rId_0 = root>>1; + ori_0 = root&1; + get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); + + if(root_0 != (uint32_t)-1 && (!IF_HOM(root_0>>1, *bub))) kv_push(uint32_t, res_utg.a, root_0); + + if(v&1) + { + update_bubble_graph(&res_utg, root_0^1, rId_0, (uint32_t)-1, (uint32_t)-1, bub, &edges, bub->b_g, NULL, NULL, ug, NULL, 0); + } + else + { + update_bubble_graph(&res_utg, (uint32_t)-1, (uint32_t)-1, root_0^1, rId_0, bub, &edges, bub->b_g, NULL, NULL, ug, NULL, 0); + } + } + kv_push(uint32_t, bub->num, bub->list.n); + new_bub = bub->b_g->n_seq - new_bub; + bub->mess_bub += new_bub; + ///actually not useful, and may have bug when one bubble at multipe chains + if(new_bub) update_bub_b_s_idx(bub); + + + for (v = 0; v < n_vx; v++) + { + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + if(nv == 0 || get_real_length(bs_ug->g, v, NULL) == 0) continue; + drop_g_edges_by_utg(bub, bub->b_g, bs_ug, NULL, v, (uint32_t)-1); + } + + update_bsg(bub->b_g, &edges); + + ma_ug_destroy(bs_ug); + bs_ug = ma_ug_gen(bub->b_g); + bub->b_ug = bs_ug; + kv_destroy(bub->chain_weight); + ma_utg_t *u_x = NULL; + bs_ug = bub->b_ug; + kv_malloc(bub->chain_weight, bs_ug->u.n); bub->chain_weight.n = bs_ug->u.n; + for (i = 0; i < bs_ug->u.n; i++) + { + u_x = &(bs_ug->u.a[i]); + bub->chain_weight.a[i].id = i; + // if(u->n <= 1) ///not a chain + // { + // bub->chain_weight.a[i].b_occ = bub->chain_weight.a[i].g_occ = 0; + // bub->chain_weight.a[i].del = 1; + // } + // else + { + bub->chain_weight.a[i].del = 0; + calculate_chain_weight(u_x, bub, ug, &(bub->chain_weight.a[i])); + } + } + qsort(bub->chain_weight.a, bub->chain_weight.n, sizeof(chain_w_type), cmp_chain_weight); + + + + free(vis); free(is_vis); free(is_used); free(dedup); free(b.b.a); + kv_destroy(stack.a); kv_destroy(result.a); kv_destroy(res_utg.a); + kv_destroy(edges.a); + + + /*******************************for debug************************************/ + // for (v = 0; v < (uint32_t)(bs_ug->g->n_seq<<1); v++) + // { + // if(asg_arc_n(bs_ug->g, v) > 0) fprintf(stderr, "ERROR, btg%.6ul\n", (v>>1)+1); + // ma_utg_t *utg = &(bs_ug->u.a[v>>1]); + // for (i = 0; i < utg->n; i++) + // { + // if((utg->a[i]>>33) >= + // (bub->f_bub + bub->b_bub + bub->b_end_bub + bub->tangle_bub + bub->cross_bub)) + // { + // if(i != 0 && i != utg->n - 1) fprintf(stderr, "ERROR, btg%.6ul, i: %u\n", (v>>1)+1, i); + // } + // } + // } + /*******************************for debug************************************/ + fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); +} + +int cmp_chain_hic_w_weight(const void * a, const void * b) +{ + if((*(chain_hic_w_type*)a).w != (*(chain_hic_w_type*)b).w) + { + return (*(chain_hic_w_type*)a).w > (*(chain_hic_w_type*)b).w? -1 : 1; + } + else + { + return 0; + } +} + + +#define is_useful_bub(ID, B) (((ID)>=((B).f_bub + (B).b_bub + (B).b_end_bub + (B).tangle_bub + (B).cross_bub))\ + && ((ID)<((B).f_bub + (B).b_bub + (B).b_end_bub + (B).tangle_bub + (B).cross_bub + (B).mess_bub))) +void init_chain_hic_warp(ma_ug_t* ug, hc_links* link, bubble_type* bub, chain_hic_warp* c_w) +{ + ma_ug_t *bs_ug = bub->b_ug; + uint32_t *a = NULL, n, occ, i, k_i, k_j, k_k, uID, is_del, m, bub_mess; + double w; + ma_utg_t *u_x = NULL; + + kv_init((*c_w)); + kv_malloc((*c_w), bs_ug->u.n); + (*c_w).n = bs_ug->u.n; + (*c_w).max_bub_id = 0; + (*c_w).u_n = ug->u.n; + (*c_w).chain_idx = NULL; + MALLOC((*c_w).chain_idx, ug->u.n); + memset((*c_w).chain_idx, -1, sizeof(uint32_t)*ug->u.n); + + for (i = bub_mess = 0; i < bs_ug->u.n; i++) + { + u_x = &(bs_ug->u.a[i]); + (*c_w).a[i].id = i; + (*c_w).a[i].w = 0; + (*c_w).a[i].occ = 0; + (*c_w).a[i].u = NULL; + for (k_i = 0, w = 0, occ = 0; k_i < u_x->n; k_i++) + { + if(is_useful_bub(u_x->a[k_i]>>33, *bub)) + { + bub_mess++; + continue; + } + get_bubbles(bub, u_x->a[k_i]>>33, NULL, NULL, &a, &n, NULL); + + for (k_j = 0; k_j < n; k_j++) + { + uID = a[k_j]>>1; + occ += ug->u.a[uID].n; + for (k_k = 0; k_k < link->a.a[uID].e.n; k_k++) + { + if(link->a.a[uID].e.a[k_k].del) continue; + w += link->a.a[uID].e.a[k_k].weight; + } + } + } + (*c_w).a[i].w = w; + (*c_w).a[i].occ = occ; + } + if(bub_mess != bub->mess_bub) fprintf(stderr, "ERROR\n"); + ///fprintf(stderr, "bub_mess: %u, bub->mess_bub: %lu\n", bub_mess, bub->mess_bub); + + for (i = 0; i < bs_ug->u.n; i++) + { + u_x = &(bs_ug->u.a[i]); + for (k_i = 0; k_i < u_x->n; k_i++) + { + if(is_useful_bub(u_x->a[k_i]>>33, *bub)) + { + continue; + } + + get_bubbles(bub, u_x->a[k_i]>>33, NULL, NULL, &a, &n, NULL); + for (k_j = 0; k_j < n; k_j++) + { + uID = a[k_j]>>1; + if((*c_w).chain_idx[uID] == (uint32_t)-1) + { + (*c_w).chain_idx[uID] = i; + } + else + { + if((*c_w).a[i].occ > (*c_w).a[(*c_w).chain_idx[uID]].occ) + { + (*c_w).chain_idx[uID] = i; + } + } + } + } + } + + for (i = m = 0; i < (*c_w).n; i++) + { + u_x = &(bs_ug->u.a[(*c_w).a[i].id]); + is_del = 1; + for (k_i = 0; k_i < u_x->n; k_i++) + { + if(is_useful_bub(u_x->a[k_i]>>33, *bub)) + { + continue; + } + + get_bubbles(bub, u_x->a[k_i]>>33, NULL, NULL, &a, &n, NULL); + for (k_j = 0; k_j < n; k_j++) + { + uID = a[k_j]>>1; + if((*c_w).chain_idx[uID] == (*c_w).a[i].id) + { + is_del = 0; + break; + } + } + if(is_del == 0) break; + } + if(is_del == 0) + { + (*c_w).a[m] = (*c_w).a[i]; + m++; + } + } + + ///fprintf(stderr, "# chain: %u, # pre chain: %u\n", m, (uint32_t)(*c_w).n); + (*c_w).n = m; + for (i = 0; i < (*c_w).n; i++) + { + u_x = &(bs_ug->u.a[(*c_w).a[i].id]); + CALLOC((*c_w).a[i].u, 1); + for (k_i = (*c_w).a[i].u->n = 0; k_i < u_x->n; k_i++) + { + if(is_useful_bub(u_x->a[k_i]>>33, *bub)) continue; + (*c_w).a[i].u->n++; + } + (*c_w).a[i].u->m = (*c_w).a[i].u->n; + MALLOC((*c_w).a[i].u->a, (*c_w).a[i].u->m); + for (k_i = (*c_w).a[i].u->n = 0; k_i < u_x->n; k_i++) + { + if(is_useful_bub(u_x->a[k_i]>>33, *bub)) continue; + (*c_w).a[i].u->a[(*c_w).a[i].u->n] = u_x->a[k_i]; + (*c_w).a[i].u->n++; + } + } + (*c_w).max_bub_id = (*c_w).n; + + if(bub->num.n > 0) bub->num.n--; + chain_hic_w_type* p = NULL; + for (i = 0; i < ug->u.n; i++) + { + uID = i; + if(IF_HOM(uID, *bub)) continue; + if((*c_w).chain_idx[uID] == (uint32_t)-1) + { + kv_pushp(chain_hic_w_type, (*c_w), &p); + CALLOC(p->u, 1); + p->u->n = p->u->m = 1; + MALLOC(p->u->a, p->u->m); + p->u->a[0] = (bub->pathLen.n)<<33; + /********************push bubble********************/ + kv_push(uint32_t, bub->num, bub->list.n); + kv_push(uint64_t, bub->pathLen, 0); + kv_push(uint32_t, bub->list, uID<<1); + kv_push(uint32_t, bub->list, uID<<1); + kv_push(uint32_t, bub->list, uID<<1); + /********************push bubble********************/ + p->occ = ug->u.a[uID].n; + p->w = 0; + for (k_k = 0; k_k < link->a.a[uID].e.n; k_k++) + { + if(link->a.a[uID].e.a[k_k].del) continue; + p->w += link->a.a[uID].e.a[k_k].weight; + } + p->id = (*c_w).n - 1; + (*c_w).chain_idx[uID] = p->id; + } + } + kv_push(uint32_t, bub->num, bub->list.n); + + + + + memset((*c_w).chain_idx, -1, sizeof(uint32_t)*ug->u.n); + for (i = 0; i < (*c_w).n; i++) + { + (*c_w).a[i].id = i; + u_x = (*c_w).a[i].u; + for (k_i = 0; k_i < u_x->n; k_i++) + { + get_bubbles(bub, u_x->a[k_i]>>33, NULL, NULL, &a, &n, NULL); + for (k_j = 0; k_j < n; k_j++) + { + uID = a[k_j]>>1; + if((*c_w).chain_idx[uID] == (uint32_t)-1) + { + (*c_w).chain_idx[uID] = (*c_w).a[i].id; + } + else + { + if((*c_w).a[i].occ > (*c_w).a[(*c_w).chain_idx[uID]].occ) + { + (*c_w).chain_idx[uID] = (*c_w).a[i].id; + } + } + } + } + } + + /** + uint32_t rId_0, ori_0, root_0, rId_1, ori_1, root_1; + for (i = 0; i < (*c_w).n; i++) + { + (*c_w).a[i].l_d = (*c_w).a[i].r_d = (uint64_t)-1; + u_x = (*c_w).a[i].u; + if(u_x->n == 0) continue; + + rId_0 = u_x->a[0]>>33; + ori_0 = (u_x->a[0]>>32&1)^1; + get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); + root_0 ^= 1; + } + **/ + + ///fprintf(stderr, "# chain: %u, # c_w.max_bub_id: %u\n", (uint32_t)(*c_w).n, (*c_w).max_bub_id); + ///qsort((*c_w).a, (*c_w).n, sizeof(chain_hic_w_type), cmp_chain_hic_w_weight); +} + +void destory_chain_hic_warp(chain_hic_warp* c_w) +{ + uint32_t i; + for (i = 0; i < c_w->n; i++) + { + free(c_w->a[i].u->a); + free(c_w->a[i].u); + } + kv_destroy((*c_w)); + free((*c_w).chain_idx); +} + +void build_bub_graph(ma_ug_t* ug, bubble_type* bub) +{ + bub->check_het = 0; + get_bub_graph(ug, bub); ///just create nodes/edges from f_bub + detect_bub_graph(bub, ug->g); + asg_destroy(bub->b_g); + bub->check_het = 1; + get_bub_graph(ug, bub); + ///print_bubble_chain(bub, "first round"); + // detect_bub_graph(bub, ug->g, 1); + update_bubble_chain(ug, bub, 1, 0); + ///print_bubble_chain(bub, "second round"); + update_bubble_chain(ug, bub, 0, 1);///resolve tangles within bubble chains + resolve_bubble_chain_tangle(ug, bub);///resolve tangles between bubble chains +} + +void get_forward_distance(uint32_t src, uint32_t dest, asg_t *sg, hc_links* link, MT* M) +{ + hc_edge *e = NULL; + e = get_hc_edge(link, src, dest, 0); + if(e == NULL) return; + uint32_t v, j; + uint64_t d[2], db[2], q_u, min, min_i, min_b; + e->dis = (uint64_t)-1; + + for (v = ((uint64_t)(src)<<1); v < ((uint64_t)(src+1)<<1); v++) + { + d[0] = d[1] = db[0] = db[1] = (uint64_t)-1; + for (j = 0; j < M->matrix.a[v].a.n; j++) + { + q_u = M->matrix.a[v].a.a[j] >> M->uID_shift; + if((q_u>>1) == dest) d[q_u&1] = (M->matrix.a[v].a.a[j] & M->dis_mode) + sg->seq[q_u>>1].len; + if((q_u>>1) > dest) break;///just for speeding up, doesn't affect results + } + + min = min_i = min_b = (uint64_t)-1; + if(e->dis != (uint64_t)-1) min = e->dis >> 3; + + if(d[0] < min) min = d[0], min_i = 0, min_b = 0; + if(d[1] < min) min = d[1], min_i = 1, min_b = 0; + if(min_i != (uint64_t)-1 && min != (uint64_t)-1) + { + e->dis = min<<1; + e->dis += min_b; + e->dis <<=1; + e->dis += v&1; + e->dis <<=1; + e->dis += min_i; + } + } + // fprintf(stderr, "%s\t%s\tdis(%lu)\n", e->dis == (uint64_t)-1? "unreach cur": "**reach cur", + // ((e->dis>>2)&1)?"back":"forw", e->dis>>3); +} + +uint32_t is_same_phase(uint64_t bid, uint64_t eid, H_partition* hap, int8_t *s, mc_gg_status *sa) +{ + if(bid == eid) return 1; + if(hap || s) + { + int beg_status, end_status; + beg_status = (hap? get_phase_status(hap, bid):s[bid]); + if(beg_status != 1 && beg_status != -1) return (uint32_t)-1; + end_status = (hap? get_phase_status(hap, eid):s[eid]); + if(end_status != 1 && end_status != -1) return (uint32_t)-1; + if(beg_status == end_status) return 1; + return 0; + } + + if(sa) + { + if(sa[bid].s == 0 || sa[eid].s == 0) return (uint32_t)-1; + return !!(sa[bid].s&sa[eid].s); + } + return (uint32_t)-1; +} + +int get_trans_rate_function_advance(ha_ug_index* idx, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, +H_partition* hap, int8_t *s, mc_gg_status *sa, trans_idx* dis) +{ + kvec_t(uint64_t) buf; + kv_init(buf); + uint64_t beg, end, cnt[2]; + uint64_t k, i, t_d, r_idx, f_idx, med = (uint64_t)-1; + uint32_t is_s; + // int beg_status, end_status; + + buf.n = 0; + for (k = 0; k < hits->a.n; ++k) + { + beg = ((hits->a.a[k].s<<1)>>(64 - idx->uID_bits)); + end = ((hits->a.a[k].e<<1)>>(64 - idx->uID_bits)); + + if(IF_HOM(beg, *bub)) continue; + if(IF_HOM(end, *bub)) continue; + if(is_hom_hit(hits->a.a[k])) continue; + + + t_d = get_hic_distance(&(hits->a.a[k]), link, idx, NULL); + if(t_d == (uint64_t)-1) continue; + // if(beg == end) + // { + // t_d = (t_d << 1); + // } + // else + // { + // beg_status = (hap? get_phase_status(hap, beg):s[beg]); + // if(beg_status != 1 && beg_status != -1) continue; + // end_status = (hap? get_phase_status(hap, end):s[end]); + // if(end_status != 1 && end_status != -1) continue; + // if(beg_status != end_status) + // { + // t_d = (t_d << 1) + 1; + // } + // else + // { + // t_d = (t_d << 1); + // } + // } + is_s = is_same_phase(beg, end, hap, s, sa); + if(is_s == (uint32_t)-1) continue; + t_d = (t_d << 1) + 1 - is_s; + + kv_push(uint64_t, buf, t_d); + } + + ///might have bias, we may not use right linkage larger than trans rc linkage + radix_sort_hc64(buf.a, buf.a+buf.n); + + for (k = 0, r_idx = f_idx = (uint64_t)-1; k < buf.n; k++) + { + if((buf.a[k]&1) == 0) r_idx = k; + if((buf.a[k]&1) == 1) f_idx = k; + } + buf.n = MIN(r_idx, f_idx); + + + trans_p_t* p = NULL; + dis->n = 0; + uint64_t bin_size = MIN(2250, buf.n>>8), m; + if(bin_size == 0) + { + for (i = 8; i > 0; i--) + { + bin_size = buf.n>>i; + if(bin_size > 0) break; + } + if(bin_size == 0) bin_size = buf.n; + } + i = 0; + while (i < buf.n) + { + kv_pushp(trans_p_t, *dis, &p); + p->beg = i; + + cnt[0] = cnt[1] = 0; + k = MIN(i+bin_size, buf.n); + for (; i < k; i++) + { + cnt[buf.a[i]&1]++; + } + p->end = i; + p->cnt_0 = cnt[0]; + p->cnt_1 = cnt[1]; + } + + i = m = 0; med = (uint64_t)-1; + while(i < dis->n) + { + if(dis->a[i].cnt_0 > 0 && dis->a[i].cnt_1 > 0) + { + dis->a[m] = dis->a[i]; + m++; + i++; + continue; + } + + if(med == (uint64_t)-1) med = buf.a[dis->a[i].beg]>>1; + k = i; cnt[0] = cnt[1] = 0; + for (; i < dis->n; i++) + { + cnt[0] += dis->a[i].cnt_0; + cnt[1] += dis->a[i].cnt_1; + if(cnt[0] > 0 && cnt[1] > 0) break; + } + + if(i < dis->n) + { + dis->a[m].cnt_0 = cnt[0]; + dis->a[m].cnt_1 = cnt[1]; + dis->a[m].beg = dis->a[k].beg; + dis->a[m].end = dis->a[i].end; + m++; + i++; + continue; + } + + cnt[0] -= dis->a[k].cnt_0; + cnt[1] -= dis->a[k].cnt_1; + while (1) + { + cnt[0] += dis->a[k].cnt_0; + cnt[1] += dis->a[k].cnt_1; + if(cnt[0] > 0 && cnt[1] > 0) break; + + if(k == 0) + { + k = (uint64_t)-1; + break; + } + k--; + } + + if(k != (uint64_t)-1) + { + dis->a[m].cnt_0 = cnt[0]; + dis->a[m].cnt_1 = cnt[1]; + dis->a[m].end = dis->a[i-1].end; + continue; + } + m = 0; + break; + } + dis->n = m; + if(dis->n == 0) + { + kv_destroy(buf); + return 0; + } + + for (i = 0; i < dis->n; i++) + { + dis->a[i].beg = buf.a[dis->a[i].beg]>>1; + dis->a[i].end = (buf.a[dis->a[i].end-1]>>1); + } + + for (i = 0; i < dis->n - 1; i++) + { + dis->a[i].end += ((dis->a[i+1].beg - dis->a[i].end)/2); + dis->a[i+1].beg = dis->a[i].end; + } + + // for (i = 0; i < dis->n; i++) + // { + // if(i > 0 && dis->a[i].beg != dis->a[i-1].end) fprintf(stderr, "ERROR: dis->a[i].beg: %lu, dis->a[i-1].end: %lu\n", dis->a[i].beg, dis->a[i-1].end); + // fprintf(stderr, "beg: %lu, end: %lu, cnt_0: %lu, cnt_1: %lu, error_rate: %f\n", + // dis->a[i].beg, dis->a[i].end, dis->a[i].cnt_0, dis->a[i].cnt_1, (double)(dis->a[i].cnt_1)/(double)(dis->a[i].cnt_1 + dis->a[i].cnt_0)); + // } + + LeastSquare_advance(dis, idx, med); + // fprintf(stderr, "idx->a: %f, idx->b: %f, idx->frac: %f, med: %lu\n", + // (double)idx->a, (double)idx->b, (double)idx->frac, med); + + dis->max = dis->a[dis->n-1].end; + + + + if(idx->a < 0) idx->a = 0; + if(idx->a == 0) + { + idx->b = MAX((((double)(dis->a[dis->n-1].cnt_1))/((double)(dis->a[dis->n-1].cnt_0 + dis->a[dis->n-1].cnt_1))), idx->b); + } + if(idx->b < 0 && get_trans(idx, dis->max) < 0) + { + idx->b = ((double)(dis->a[dis->n-1].cnt_1))/((double)(dis->a[dis->n-1].cnt_0 + dis->a[dis->n-1].cnt_1)); + } + + // fprintf(stderr, "idx->a: %f, idx->b: %f, idx->frac: %f, med: %lu\n", + // (double)idx->a, (double)idx->b, (double)idx->frac, med); + + + + + + buf.n = 0; + for (k = 0; k < hits->a.n; ++k) + { + beg = ((hits->a.a[k].s<<1)>>(64 - idx->uID_bits)); + end = ((hits->a.a[k].e<<1)>>(64 - idx->uID_bits)); + + if(IF_HOM(beg, *bub)) continue; + if(IF_HOM(end, *bub)) continue; + if(is_hom_hit(hits->a.a[k])) continue; + if(beg == end) continue; + + t_d = get_hic_distance(&(hits->a.a[k]), link, idx, NULL); + if(t_d == (uint64_t)-1) continue; + kv_push(uint64_t, buf, t_d); + } + + ///might have bias, we may not use right linkage larger than trans rc linkage + radix_sort_hc64(buf.a, buf.a+buf.n); + if(buf.n == 0) + { + dis->med = 0; + } + else + { + dis->med = ((buf.n&1)?buf.a[buf.n>>1]:((buf.a[buf.n>>1]+buf.a[(buf.n>>1)-1])/2)); + } + + // fprintf(stderr, "dis->med: %lu\n", dis->med); + + kv_destroy(buf); + return 1; +} + +void init_hic_advance(ha_ug_index* idx, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, H_partition* hap, uint32_t ignore_dis) +{ + uint64_t k, i, m, is_comples_weight = 0; + trans_idx dis; + kv_init(dis); + + if(bub->round_id > 0 && ignore_dis == 0) + { + is_comples_weight = get_trans_rate_function_advance(idx, hits, link, bub, hap, NULL, NULL, &dis); + } + + + hc_edge *e = NULL; + for (i = 0; i < link->a.n; i++) + { + for (k = 0; k < link->a.a[i].e.n; k++) + { + if(link->a.a[i].e.a[k].del) continue; + if(link->a.a[i].e.a[k].dis == (uint64_t)-1) + { + e = get_hc_edge(link, link->a.a[i].e.a[k].uID, i, 0); + if(!e) fprintf(stderr, "ERROR\n"); + e->del = link->a.a[i].e.a[k].del = 1; + } + } + } + + for (i = 0; i < link->a.n; i++) + { + for (k = m = 0; k < link->a.a[i].e.n; k++) + { + if(link->a.a[i].e.a[k].del) continue; + link->a.a[i].e.a[m] = link->a.a[i].e.a[k]; + link->a.a[i].e.a[m].weight = 0; + link->a.a[i].e.a[m].occ = 0; + m++; + } + link->a.a[i].e.n = m; + } + + weight_edges_advance(idx, hits, link, bub, is_comples_weight == 1? &dis : NULL); + + for (i = 0; i < link->a.n; i++) + { + for (k = 0; k < link->a.a[i].e.n; k++) + { + if(link->a.a[i].e.a[k].del) continue; + if(link->a.a[i].e.a[k].weight <= 0) + { + e = get_hc_edge(link, link->a.a[i].e.a[k].uID, i, 0); + e->del = link->a.a[i].e.a[k].del = 1; + } + } + } + + for (i = 0; i < link->a.n; i++) + { + for (k = m = 0; k < link->a.a[i].e.n; k++) + { + if(link->a.a[i].e.a[k].del) continue; + link->a.a[i].e.a[m] = link->a.a[i].e.a[k]; + m++; + } + link->a.a[i].e.n = m; + } + kv_destroy(dis); +} + + +#define is_hap_set(i, Hap) (!!((Hap).hap[(i)]&((Hap).m[0]|(Hap).m[1]|(Hap).m[2]))) +#define is_hap_set_label(i, Hap, label) (is_hap_set((i), (Hap))&&((Hap).hap[(i)]>>(Hap).label_shift)==((label)>>(Hap).label_shift)) + +double get_path_weight(uint32_t query, uint32_t v0, uint32_t root, bub_p_t_warp *b, hc_links* x) +{ + if(v0 == root) return 0; + uint32_t v, u; + hc_edge *p = NULL; + double weight = 0; + v = v0; + do { + u = b->a[v].p; // u->v + p = get_hc_edge(x, query>>1, v>>1, 0); + if(p) weight += p->weight; + v = u; + } while (v != root); + + return weight; +} + +uint32_t get_related_weight(uint32_t x, H_partition* hap, double* w0, double* w1, uint32_t* hap_label) +{ + (*w0) = (*w1) = 0; + if(x >= hap->link->a.n) return 0; + uint32_t i, a_n = hap->link->a.a[x].e.n, occ; + hc_edge* a = hap->link->a.a[x].e.a; + for (i = occ = 0; i < a_n; i++) + { + if(a[i].del) continue; + if(hap_label && (!is_hap_set_label(a[i].uID, *hap, *hap_label))) continue; + if(is_hap_set(a[i].uID, *hap)) occ++; + if((hap->hap[a[i].uID] & hap->m[0])) (*w0)+= a[i].weight; + if((hap->hap[a[i].uID] & hap->m[1])) (*w1)+= a[i].weight; + } + return occ; +} + +void set_path_hap(bub_p_t_warp *b, uint32_t root, H_partition* hap, uint32_t max_hap_label) +{ + uint32_t v, u, label; + double w0 = 0, w1 = 0, cur_w0, cur_w1; + ///v is the sink of this bubble + v = b->S.a[0]; + do { + u = b->a[v].p; // u->v + if(v != b->S.a[0]) + { + get_related_weight(v>>1, hap, &cur_w0, &cur_w1, &max_hap_label); + w0 += cur_w0; w1 += cur_w1; + } + v = u; + } while (v != root); + + if(w0 > w1) + { + label = max_hap_label | hap->m[0]; + b->exist_hap_label = hap->m[0]; + } + else if(w0 < w1) + { + label = max_hap_label | hap->m[1]; + b->exist_hap_label = hap->m[1]; + } + else + { + if(b->exist_hap_label == (uint32_t)-1) + { + label = max_hap_label | hap->m[0]; + b->exist_hap_label = hap->m[0]; + } + else + { + if(b->exist_hap_label == hap->m[0]) + { + label = max_hap_label | hap->m[1]; + b->exist_hap_label = hap->m[1]; + } + else + { + label = max_hap_label | hap->m[0]; + b->exist_hap_label = hap->m[0]; + } + } + } + + + v = b->S.a[0]; + do { + u = b->a[v].p; // u->v + if(v != b->S.a[0]) hap->hap[v>>1] |= label; + v = u; + } while (v != root); +} + + +uint64_t get_phase_path(ma_ug_t *ug, uint32_t s, uint32_t d, bub_p_t_warp *b, H_partition* hap, uint32_t max_hap_label) +{ + asg_t *g = ug->g; + if(g->seq[s>>1].del) return 0; // already deleted + if(get_real_length(g, s, NULL)<2) return 0; + uint32_t i, n_pending, is_first, to_replace, cur_nc, cur_uc, cur_ac, n_tips, tip_end, n_pop; + double cur_nh, cur_w0, cur_w1, cur_rate, max_rate, cur_weight, max_weight; + ///S saves nodes with all incoming edges visited + b->S.n = b->T.n = b->b.n = b->e.n = 0; + ///for each node, b->a saves all related information + b->a[s].d = b->a[s].nc = b->a[s].ac = b->a[s].uc = 0; b->a[s].nh = b->a[s].w[0] = b->a[s].w[1] = 0; + ///b->S is the nodes with all incoming edges visited + kv_push(uint32_t, b->S, s); + n_pop = n_tips = n_pending = 0; + tip_end = (uint32_t)-1; + is_first = 1; + + do { + ///v is a node that all incoming edges have been visited + ///d is the distance from v0 to v + uint32_t v = kv_pop(b->S); + uint32_t d = b->a[v].d, nc = b->a[v].nc, uc = b->a[v].uc, ac = b->a[v].ac; + double nh = b->a[v].nh; + double nw_0 = b->a[v].w[0], nw_1 = b->a[v].w[1]; + + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + for (i = 0; i < nv; ++i) { + uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l, not overlap length + bub_p_t *t = &b->a[w]; + //got a circle + if ((w>>1) == (s>>1)) goto pop_reset; + //important when poping at long untig graph + if(is_first) l = 0; + if (av[i].del) continue; + ///push the edge + kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); + + if (t->s == 0) + { // this vertex has never been visited + kv_push(uint32_t, b->b, w); // save it for revert + ///t->p is the parent node of + ///t->s = 1 means w has been visited + ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) + t->p = v, t->s = 1, t->d = d + l, t->nc = nc + ug->u.a[(w>>1)].n; + t->r = get_real_length(g, w^1, NULL); + /**need fix**/ + t->nh = nh + get_path_weight(w, v, s, b, hap->link); + + get_related_weight(w>>1, hap, &(t->w[0]), &(t->w[1]), &max_hap_label); + t->w[0] += nw_0; t->w[1] += nw_1; + + t->ac = ac + ((!is_hap_set_label(w>>1, *hap, max_hap_label))?ug->u.a[(w>>1)].n : 0); + t->uc = uc + ((is_hap_set_label(w>>1, *hap, max_hap_label))?ug->u.a[(w>>1)].n : 0); + + ++n_pending; + } + else { + to_replace = 0; + + cur_nc = nc + ug->u.a[(w>>1)].n; + /**need fix**/ + cur_nh = nh + get_path_weight(w, v, s, b, hap->link); + get_related_weight(w>>1, hap, &cur_w0, &cur_w1, &max_hap_label); + cur_w0 += nw_0; cur_w1 += nw_1; + cur_weight = cur_nh + MAX(cur_w0, cur_w1) - MIN(cur_w0, cur_w1); + max_weight = t->nh + MAX(t->w[0], t->w[1]) - MIN(t->w[0], t->w[1]); + + cur_ac = ac + ((!is_hap_set_label(w>>1, *hap, max_hap_label))?ug->u.a[(w>>1)].n : 0);; + cur_uc = uc + ((is_hap_set_label(w>>1, *hap, max_hap_label))?ug->u.a[(w>>1)].n : 0); + cur_rate = ((double)(cur_ac)/(double)(cur_ac+cur_uc)); + max_rate = ((double)(t->ac)/(double)(t->ac+t->uc)); + + if(cur_rate > max_rate) + { + to_replace = 1; + } + else if(cur_rate == max_rate) + { + ///if(cur_nh > t->nh) + if(cur_weight > max_weight) + { + to_replace = 1; + } + else if(cur_weight == max_weight)///(cur_nh == t->nh) + { + if(cur_nc > t->nc) + { + to_replace = 1; + } + else if(cur_nc == t->nc) + { + if(d + l > t->d) + { + to_replace = 1; + } + } + } + } + + + if(to_replace) + { + t->p = v; + t->nc = cur_nc; + t->nh = cur_nh; + t->ac = cur_ac; + t->uc = cur_uc; + t->w[0] = cur_w0; + t->w[1] = cur_w1; + } + + + if (d + l < t->d) t->d = d + l; // update dist + } + + if (--(t->r) == 0) { + uint32_t x = get_real_length(g, w, NULL); + if(x > 0) + { + kv_push(uint32_t, b->S, w); + } + else + { + ///at most one tip + if(n_tips != 0) goto pop_reset; + n_tips++; + tip_end = w; + } + --n_pending; + } + } + is_first = 0; + + + if(n_tips == 1) + { + if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) + { + ///sink is b.S.a[0] + kv_push(uint32_t, b->S, tip_end); + break; + } + else + { + goto pop_reset; + } + } + + if (i < nv || b->S.n == 0) goto pop_reset; + }while (b->S.n > 1 || n_pending); + + + n_pop = 1; + /**need fix**/ + set_path_hap(b, s, hap, max_hap_label); + pop_reset: + + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + bub_p_t *t = &b->a[b->b.a[i]]; + t->p = t->d = t->nc = t->ac = t->uc = t->r = t->s = 0; + t->nh = t->w[0] = t->w[1] = 0; + } + + return n_pop; +} + +uint32_t get_weightest_hap_label_from_uid(uint64_t x, H_partition* hap, uint8_t* hap_label_flag, +uint32_t* max_hap_label, double* max_hap_weight) +{ + (*max_hap_label) = (uint32_t)-1; + kv_resize(double, hap->label_buffer, (hap->label>>hap->label_shift)+1); + hap->label_buffer.n = (hap->label>>hap->label_shift)+1; + uint32_t i, is_set_ava, is_unset_ava, a_n; + hc_edge* a = NULL; + for (i = 0; i < hap->label_buffer.n; i++) + { + hap->label_buffer.a[i] = 0; + } + + is_set_ava = is_unset_ava = 0; + a_n = hap->link->a.a[x].e.n; + a = hap->link->a.a[x].e.a; + for (i = 0; i < a_n; i++) + { + if(a[i].del) continue; + if(is_hap_set(a[i].uID, *hap)) + { + if(hap_label_flag && hap_label_flag[hap->hap[a[i].uID]] == 0) continue; + hap->label_buffer.a[hap->hap[a[i].uID]>>hap->label_shift] += a[i].weight; + is_set_ava = 1; + } + is_unset_ava = 1; + } + + if(hap_label_flag && is_set_ava == 0) return 0; + if(is_unset_ava == 0) return 0; + if(is_set_ava == 0 && is_unset_ava > 0) + { + hap->label += hap->label_add; + (*max_hap_label) = hap->label; + return 1; + } + + double max_weight; + uint32_t max_i; + for (i = 0, max_weight = -1, max_i = (uint32_t)-1; i < hap->label_buffer.n; i++) + { + if(hap->label_buffer.a[i] > max_weight) + { + max_weight = hap->label_buffer.a[i]; + max_i = i; + } + } + + (*max_hap_label) = max_i<label_shift; + if(max_hap_weight) (*max_hap_weight) = max_weight; + return 1; + +} + +uint32_t get_weightest_hap_label_from_bubble(uint64_t bid, H_partition* hap, bubble_type* bub, +uint8_t* hap_label_flag, uint32_t* max_hap_label, double* max_hap_weight) +{ + (*max_hap_label) = (uint32_t)-1; + + kv_resize(double, hap->label_buffer, (hap->label>>hap->label_shift)+1); + hap->label_buffer.n = (hap->label>>hap->label_shift)+1; + uint32_t i, m, is_set_ava, is_unset_ava, a_n, *x_a, x_n, x; + hc_edge* a = NULL; + for (i = 0; i < hap->label_buffer.n; i++) + { + hap->label_buffer.a[i] = 0; + } + + ///bid might be bubble or non-bubble + get_bubbles(bub, bid, NULL, NULL, &x_a, &x_n, NULL); + for (m = is_set_ava = is_unset_ava = 0; m < x_n; m++) + { + ///x is uid + x = x_a[m]>>1; + a_n = hap->link->a.a[x].e.n; + a = hap->link->a.a[x].e.a; + for (i = 0; i < a_n; i++) + { + if(a[i].del) continue; + if(is_hap_set(a[i].uID, *hap)) + { + if(hap_label_flag && hap_label_flag[hap->hap[a[i].uID]] == 0) continue; ///not at current chain + hap->label_buffer.a[hap->hap[a[i].uID]>>hap->label_shift] += a[i].weight; + is_set_ava = 1; + } + is_unset_ava = 1; + } + } + if(hap_label_flag && is_set_ava == 0) return 0; ///no connection in current chain + + if(is_unset_ava == 0) return 0; ///no any connection + if(is_set_ava == 0 && is_unset_ava > 0) ///update hap->label + { + hap->label += hap->label_add; + (*max_hap_label) = hap->label; + return 1; + } + + double max_weight; + uint32_t max_i; + for (i = 0, max_weight = -1, max_i = (uint32_t)-1; i < hap->label_buffer.n; i++) + { + if(hap->label_buffer.a[i] > max_weight) + { + max_weight = hap->label_buffer.a[i]; + max_i = i; + } + } + + (*max_hap_label) = max_i<label_shift; + if(max_hap_weight) (*max_hap_weight) = max_weight; + return 1; +} + + +uint32_t get_available_com(H_partition* hap, bubble_type* bub, ma_ug_t *ug, uint32_t check_self, uint32_t check_others, +uint8_t* hap_label_flag, uint32_t* max_hap_label) +{ + hc_links* link = hap->link; + uint32_t beg, sink, n, *a, i, j, k, uID, max_bub_i, max_non_bub_i, max_i, is_ava; + uint32_t hap_label, max_bub_label = (uint32_t)-1, max_non_bub_label = (uint32_t)-1; + double w, max_bub_w, max_non_bub_w; + max_i = (uint32_t)-1; + + for (i = 0, max_bub_w = -1, max_bub_i = (uint32_t)-1; i < bub->f_bub/**bub->s_bub**/; i++) + { + get_bubbles(bub, i, &beg, &sink, &a, &n, NULL); + for (j = 0, w = 0; j < n; j++) + { + uID = a[j]>>1; + if(check_self && is_hap_set(uID, *hap)) break; + } + if(j != n) continue; + + is_ava = 0; + hap_label = (uint32_t)-1; + if(check_others) + { + if(get_weightest_hap_label_from_bubble(i, hap, bub, + hap_label_flag, &hap_label, &w)>0) + { + is_ava = 1; + } + } + else + { + for (j = 0, w = 0, is_ava = 0; j < n; j++) + { + uID = a[j]>>1; + for (k = 0; k < link->a.a[uID].e.n; k++) + { + if(link->a.a[uID].e.a[k].del) continue; + w += link->a.a[uID].e.a[k].weight; + is_ava = 1; + } + } + } + + if(is_ava == 0) continue; + + if(w > max_bub_w) + { + max_bub_w = w; + max_bub_i = i; + max_bub_label = hap_label; + } + } + + for (i = 0, max_non_bub_w = -1, max_non_bub_i = (uint32_t)-1; i < ug->u.n; i++) + { + if(IF_HET(i, *bub)/** || (bub->index[i] >= bub->s_bub && bub->index[i] < bub->f_bub)**/) + { + uID = i; + is_ava = 0; + if(check_self && is_hap_set(uID, *hap)) continue; + hap_label = (uint32_t)-1; + if(check_others) + { + if(get_weightest_hap_label_from_uid(uID, hap, hap_label_flag, &hap_label, &w)>0) + { + is_ava = 1; + } + } + else + { + for (k = 0, w = 0, is_ava = 0; k < link->a.a[uID].e.n; k++) + { + if(link->a.a[uID].e.a[k].del) continue; + w += link->a.a[uID].e.a[k].weight; + is_ava = 1; + } + } + + if(is_ava == 0) continue; + + if(w > max_non_bub_w) + { + max_non_bub_w = w; + max_non_bub_i = i; + max_non_bub_label = hap_label; + } + } + } + + if(max_bub_i != (uint32_t)-1 && max_non_bub_i != (uint32_t)-1) + { + if(max_non_bub_w > max_bub_w) + { + max_i = (max_non_bub_i << 1) + 1; + w = max_non_bub_w; + (*max_hap_label) = max_non_bub_label; + } + else + { + max_i = (max_bub_i << 1); + w = max_bub_w; + (*max_hap_label) = max_bub_label; + } + } + else if(max_bub_i != (uint32_t)-1) + { + max_i = (max_bub_i << 1); + w = max_bub_w; + (*max_hap_label) = max_bub_label; + } + else if(max_non_bub_i != (uint32_t)-1) + { + max_i = (max_non_bub_i << 1) + 1; + w = max_non_bub_w; + (*max_hap_label) = max_non_bub_label; + } + + if(max_i == (uint32_t)-1) + { + for (i = 0, max_non_bub_w = -1, max_non_bub_i = (uint32_t)-1; i < ug->u.n; i++) + { + ///if(bub->index[i] < bub->s_bub) + if(IF_BUB(i, *bub)) + { + + uID = i; + is_ava = 0; + if(check_self && is_hap_set(uID, *hap)) continue; + hap_label = (uint32_t)-1; + if(check_others) + { + if(get_weightest_hap_label_from_uid(uID, hap, hap_label_flag, &hap_label, &w)>0) + { + is_ava = 1; + } + } + else + { + for (k = 0, w = 0, is_ava = 0; k < link->a.a[uID].e.n; k++) + { + if(link->a.a[uID].e.a[k].del) continue; + w += link->a.a[uID].e.a[k].weight; + is_ava = 1; + } + } + + if(is_ava == 0) continue; + + if(w > max_non_bub_w) + { + max_non_bub_w = w; + max_non_bub_i = i; + max_non_bub_label = hap_label; + } + + } + } + + if(max_non_bub_i != (uint32_t)-1) + { + max_i = (max_non_bub_i << 1) + 1; + w = max_non_bub_w; + (*max_hap_label) = max_non_bub_label; + } + } + + // if(max_i == (uint32_t)-1) + // { + // fprintf(stderr, "-Cannot find!\n"); + // } + // else if(max_i & 1) + // { + // fprintf(stderr, "-utg-%uth, phasing ID: %u, w: %f, max_bub_i: %u, max_bub_w: %f, max_non_bub_i: %u, max_non_bub_w: %f\n", + // max_i>>1, hap->label>>3, w, max_bub_i, max_bub_w, max_non_bub_i, max_non_bub_w); + // } + // else + // { + // fprintf(stderr, "-bubble-%uth, phasing ID: %u, w: %f, max_bub_i: %u, max_bub_w: %f, max_non_bub_i: %u, max_non_bub_w: %f\n", + // max_i>>1, hap->label>>3, w, max_bub_i, max_bub_w, max_non_bub_i, max_non_bub_w); + // } + + return max_i; +} + +void reset_ambiguous_label(H_partition* hap, uint8_t* hap_label_flag, uint32_t uID) +{ + uint32_t hap_label = (uint32_t)-1; + if(get_weightest_hap_label_from_uid(uID, hap, hap_label_flag, &hap_label, NULL)>0) + { + double cur_w0, cur_w1; + get_related_weight(uID, hap, &cur_w0, &cur_w1, &hap_label); + if(cur_w0 >= cur_w1) + { + hap->hap[uID] |= (hap_label | hap->m[0]); + } + else + { + hap->hap[uID] |= (hap_label | hap->m[1]); + } + } +} + +uint32_t get_unset_com(H_partition* hap, bubble_type* bub, ma_ug_t *ug, uint8_t* hap_label_flag, uint32_t* max_hap_label) +{ + uint32_t max_i = get_available_com(hap, bub, ug, 1, 1, hap_label_flag, max_hap_label); + + if(max_i == (uint32_t)-1) + { + max_i = get_available_com(hap, bub, ug, 1, 0, hap_label_flag, max_hap_label); + if(max_i != (uint32_t)-1) + { + hap->label += hap->label_add; + (*max_hap_label) = hap->label; + } + } + + return max_i; +} + +void phase_com(H_partition* hap, ma_ug_t *ug, bub_p_t_warp* b, bubble_type* bub, uint32_t bid, uint32_t max_hap_label) +{ + + if((bid & 1) == 0) ///bubble + { + uint32_t beg = (uint32_t)-1, sink = (uint32_t)-1, n, *a; + get_bubbles(bub, bid>>1, &beg, &sink, &a, &n, NULL); + ///fprintf(stderr, "+bubble-%uth, beg: %u, sink: %u, phasing ID: %u\n", bid>>1, beg>>1, sink>>1, hap->label>>3); + b->exist_hap_label = (uint32_t)-1; + get_phase_path(ug, beg, sink, b, hap, max_hap_label); + get_phase_path(ug, beg, sink, b, hap, max_hap_label); + ///fprintf(stderr, "-bubble-%uth, beg: %u, sink: %u, phasing ID: %u\n", bid>>1, beg>>1, sink>>1, hap->label>>3); + } + else + { + double cur_w0, cur_w1; + get_related_weight(bid>>1, hap, &cur_w0, &cur_w1, &max_hap_label); + ///fprintf(stderr, "utg-%uth, phasing ID: %u\n", bid>>1, hap->label>>3); + if(cur_w0 >= cur_w1) + { + hap->hap[bid>>1] |= (max_hap_label | hap->m[0]); + } + else + { + hap->hap[bid>>1] |= (max_hap_label | hap->m[1]); + } + } +} + + +double get_cluster_weight(H_partition* hap, hc_links* link, uint32_t *h, uint32_t h_n) +{ + int o_d = 0; + double weight = 0; + uint32_t j, k, m; + for (j = 0, weight = 0; j < h_n; j++) + { + for (k = 0; k < link->a.a[h[j]].e.n; k++) + { + if(link->a.a[h[j]].e.a[k].del) continue; + for (m = 0; m < h_n; m++) + { + if(h[m] == link->a.a[h[j]].e.a[k].uID) break; + } + if(m < h_n) continue; + + o_d = get_phase_status(hap, link->a.a[h[j]].e.a[k].uID); + if(o_d < -1) continue; + ///if(o_d < -1) fprintf(stderr, "ERROR\n"); + weight += (o_d*link->a.a[h[j]].e.a[k].weight); + } + } + + return weight; +} + + +double get_cluster_inner_weight(H_partition* hap, hc_links* link, uint32_t *h0, uint32_t h0_n, +uint32_t *h1, uint32_t h1_n) +{ + double weight = 0; + uint32_t j, k, m; + for (j = 0, weight = 0; j < h0_n; j++) + { + for (k = 0; k < link->a.a[h0[j]].e.n; k++) + { + if(link->a.a[h0[j]].e.a[k].del) continue; + for (m = 0; m < h1_n; m++) + { + if(h1[m] == link->a.a[h0[j]].e.a[k].uID) break; + } + if(m == h1_n) continue; + + weight += link->a.a[h0[j]].e.a[k].weight; + } + } + + return weight * 2; +} + +void update_partition_flag(H_partition* h, G_partition* g_p, hc_links* link, uint32_t id) +{ + uint32_t k, *h0, h0_n, *h1, h1_n, uID, flag = 0; + int status; + get_phased_block(g_p, NULL, id, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); + + status = g_p->a[id].status[0]; + if(status == 1) flag = h->m[0]; + else if(status == -1) flag = h->m[1]; + else if(status == 0) flag = h->m[2]; + else if(status == -2) flag = 0; + for (k = 0; k < h0_n; k++) + { + uID = h0[k]; + h->hap[uID] >>= 3; + h->hap[uID] <<= 3; + h->hap[uID] |= flag; + } + + status = g_p->a[id].status[1]; + if(status == 1) flag = h->m[0]; + else if(status == -1) flag = h->m[1]; + else if(status == 0) flag = h->m[2]; + else if(status == -2) flag = 0; + for (k = 0; k < h1_n; k++) + { + uID = h1[k]; + h->hap[uID] >>= 3; + h->hap[uID] <<= 3; + h->hap[uID] |= flag; + } +} + + +void update_partition_flag_debug(H_partition* h, G_partition* g_p, hc_links* link, uint32_t id) +{ + uint32_t k, *h0, h0_n, *h1, h1_n, uID, flag = 0; + int status; + get_phased_block(g_p, NULL, id, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); + + status = g_p->a[id].status[0]; + if(status == 1) flag = h->m[0]; + else if(status == -1) flag = h->m[1]; + else if(status == 0) flag = h->m[2]; + else if(status == -2) flag = 0; + for (k = 0; k < h0_n; k++) + { + uID = h0[k]; + if(flag != (h->hap[uID]&7)) fprintf(stderr, "h0, id: %u, uID: %u, pre_flag: %u, cur_flag: %u\n", id, uID, (h->hap[uID]&7), flag); + h->hap[uID] >>= 3; + h->hap[uID] <<= 3; + h->hap[uID] |= flag; + } + + status = g_p->a[id].status[1]; + if(status == 1) flag = h->m[0]; + else if(status == -1) flag = h->m[1]; + else if(status == 0) flag = h->m[2]; + else if(status == -2) flag = 0; + for (k = 0; k < h1_n; k++) + { + uID = h1[k]; + if(flag != (h->hap[uID]&7)) fprintf(stderr, "h1, id: %u, uID: %u, pre_flag: %u, cur_flag: %u\n", id, uID, (h->hap[uID]&7), flag); + h->hap[uID] >>= 3; + h->hap[uID] <<= 3; + h->hap[uID] |= flag; + } +} + +void print_contig_partition(H_partition* hap, const char* debug) +{ + uint32_t i; + int status; + for (i = 0; i < hap->n; i++) + { + status = get_phase_status(hap, i); + fprintf(stderr, "%s\tutg%.6d\tP:%u\tHG:A:%d\n", debug, (int)(i+1), hap->hap[i]>>3, status); + } +} + +void adjust_contig_partition(H_partition* hap, hc_links* link) +{ + double index_time = yak_realtime(); + uint32_t i, k, *h0, h0_n, *h1, h1_n; + uint32_t h0_status[4], h1_status[4], h0_status_max; + int h0_h, h1_h; + for (i = 0; i < hap->g_p.n; i++) + { + + get_phased_block(&(hap->g_p), NULL, i, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); + hap->g_p.a[i].status[0] = hap->g_p.a[i].status[1] = -2; + hap->g_p.a[i].weight[0] = hap->g_p.a[i].weight[1] = hap->g_p.a[i].weight_convex = 0; + + + h0_status[0] = h0_status[1] = h0_status[2] = h0_status[3] = 0; + for (k = 0; k < h0_n; k++) + { + h0_status[get_phase_status(hap, h0[k])+2]++; + } + + hap->g_p.a[i].weight[0] = get_cluster_weight(hap, link, h0, h0_n); + if(h1_n == 0) + { + if(h0_status[0] == h0_n) ///unset, flag = -2 + { + hap->g_p.a[i].status[0] = -2; + } + else + { + if(h0_status[1] > 0 || h0_status[3] > 0) ///phased flag = 1/-1 + { + h0_status[0] = h0_status[2] = 0; + + h0_h = -2; + h0_status_max = 0; + for (k = 0; k < 4; k++) + { + if(h0_status[k] > h0_status_max) + { + h0_status_max = h0_status[k]; + h0_h = (int)(k) - 2; + } + } + hap->g_p.a[i].status[0] = h0_h; + } + else if(h0_status[2] > 0) ///hom flag + { + hap->g_p.a[i].status[0] = 0; + } + else //unset flag + { + hap->g_p.a[i].status[0] = -2; + } + } + } + else + { + hap->g_p.a[i].weight[1] = get_cluster_weight( hap, link, h1, h1_n); + h1_status[0] = h1_status[1] = h1_status[2] = h1_status[3] = 0; + for (k = 0; k < h1_n; k++) + { + h1_status[get_phase_status(hap, h1[k])+2]++; + } + + + h0_h = h1_h = 0; + for (k = 0; k < 4; k++) + { + if(h0_status[k] == h0_n) h0_h = (int)(k) - 2; + if(h1_status[k] == h1_n) h1_h = (int)(k) - 2; + } + + if(h0_h * h1_h == -1) + { + hap->g_p.a[i].status[0] = h0_h; + hap->g_p.a[i].status[1] = h1_h; + } + else + { + if(hap->g_p.a[i].weight[0] >= hap->g_p.a[i].weight[1]) + { + hap->g_p.a[i].status[0] = 1; + hap->g_p.a[i].status[1] = -1; + } + else + { + hap->g_p.a[i].status[0] = -1; + hap->g_p.a[i].status[1] = 1; + } + } + } + hap->g_p.a[i].weight_convex = get_cluster_inner_weight(hap, link, h0, h0_n, h1, h1_n); + update_partition_flag(hap, &(hap->g_p), link, i); + ///update_partition_flag_debug(hap, &(hap->g_p), link, i); + } + + for (i = 0; i < hap->g_p.n; i++) + { + get_phased_block(&(hap->g_p), NULL, i, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); + hap->g_p.a[i].weight[0] = get_cluster_weight(hap, link, h0, h0_n); + hap->g_p.a[i].weight[1] = get_cluster_weight(hap, link, h1, h1_n); + hap->g_p.a[i].weight_convex = get_cluster_inner_weight(hap, link, h0, h0_n, h1, h1_n); + } + fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); +} + +uint32_t get_weightest_uid(uint32_t* a, uint32_t n, H_partition* hap, uint8_t* hap_label_flag, +uint32_t* max_hap_label) +{ + double cur_w0, cur_w1, max_weight; + uint32_t j, max_i, is_ava, hap_label; + + for (j = is_ava = 0, max_i = (uint32_t)-1; j < n; j++) + { + if(is_hap_set(a[j]>>1, *hap)) ///avoid repeat phasing + { + continue; + } + + get_weightest_hap_label_from_uid(a[j]>>1, hap, hap_label_flag, &hap_label, NULL); + + if(hap_label == (uint32_t)-1) + { + continue; + } + + if(get_related_weight(a[j]>>1, hap, &cur_w0, &cur_w1, &hap_label) > 0) + { + if(max_i == (uint32_t)-1) + { + max_i = j; + max_weight = cur_w0 + cur_w1; + (*max_hap_label) = hap_label; + } + else if((cur_w0 + cur_w1) > max_weight) + { + max_i = j; + max_weight = cur_w0 + cur_w1; + (*max_hap_label) = hap_label; + } + is_ava++; + } + } + + ///no useful unitig + if(is_ava == 0) + { + for (j = is_ava = 0, max_i = (uint32_t)-1; j < n; j++) + { + if(is_hap_set(a[j]>>1, *hap)) + { + continue; + } + + if(get_weightest_hap_label_from_uid(a[j]>>1, hap, NULL, &hap_label, NULL)==0) continue; + + if(get_related_weight(a[j]>>1, hap, &cur_w0, &cur_w1, &hap_label) > 0) + { + if(max_i == (uint32_t)-1) + { + max_i = j; + max_weight = cur_w0 + cur_w1; + (*max_hap_label) = hap_label; + } + else if((cur_w0 + cur_w1) > max_weight) + { + max_i = j; + max_weight = cur_w0 + cur_w1; + (*max_hap_label) = hap_label; + } + is_ava++; + } + } + } + if(max_i == (uint32_t)-1) return max_i; + + return a[max_i]>>1; +} + + +void get_weightest_hap_label_from_chain(ma_utg_t *u, H_partition* hap, bubble_type* bub, +uint32_t* max_hap_label, uint32_t* max_bid_idx, uint32_t* is_forward_first) +{ + (*max_hap_label) = (uint32_t)-1; + if(max_bid_idx) (*max_bid_idx) = 0; + if(is_forward_first) (*is_forward_first) = 1; + + if(u->n == 0) return; + kv_resize(double, hap->label_buffer, (hap->label>>hap->label_shift)+1);///how many group + hap->label_buffer.n = (hap->label>>hap->label_shift)+1; + uint32_t i, k, m, is_ava, a_n, *x_a, x_n, x; + uint64_t bid; + hc_edge* a = NULL; + for (i = 0; i < hap->label_buffer.n; i++) + { + hap->label_buffer.a[i] = 0;///count weight for each group + } + + for (k = is_ava = 0; k < u->n; k++) + { + bid = u->a[k]>>33; + ///bid might be bubble or non-bubble + get_bubbles(bub, bid, NULL, NULL, &x_a, &x_n, NULL); + for (m = 0; m < x_n; m++) + { + ///x is uid + x = x_a[m]>>1; + a_n = hap->link->a.a[x].e.n; + a = hap->link->a.a[x].e.a; + for (i = 0; i < a_n; i++) + { + if(a[i].del) continue; + if(is_hap_set(a[i].uID, *hap)) + { + hap->label_buffer.a[hap->hap[a[i].uID]>>hap->label_shift] += a[i].weight; + is_ava = 1; + } + } + } + } + + if(is_ava == 0) return; ///totally new chain + double max_weight; + uint32_t max_i; + ///select the best exsiting group to u + for (i = 0, max_weight = -1, max_i = (uint32_t)-1; i < hap->label_buffer.n; i++) + { + if(hap->label_buffer.a[i] > max_weight) + { + max_weight = hap->label_buffer.a[i]; + max_i = i; + } + } + + (*max_hap_label) = max_i<label_shift; + if(max_bid_idx) + { + double current_weight, tot_w = 0, half_w = 0; + for (k = 0, max_weight = -1, max_i = (uint32_t)-1; k < u->n; k++) + { + bid = u->a[k]>>33; + ///bid might be bubble or non-bubble + get_bubbles(bub, bid, NULL, NULL, &x_a, &x_n, NULL); + for (m = 0, current_weight = 0; m < x_n; m++) + { + x = x_a[m]>>1; + a_n = hap->link->a.a[x].e.n; + a = hap->link->a.a[x].e.a; + for (i = 0; i < a_n; i++) + { + if(a[i].del) continue; + if(is_hap_set_label(a[i].uID, *hap, *max_hap_label)) + { + current_weight += a[i].weight; + } + } + } + + if(current_weight > max_weight) /// the weight of each bubble + { + max_weight = current_weight; + max_i = k; + half_w = 0; + } + tot_w += current_weight; + half_w += current_weight; + } + + (*max_bid_idx) = max_i; + if(is_forward_first) + { + if(half_w >= (tot_w - half_w)) + { + (*is_forward_first) = 1; + } + else + { + (*is_forward_first) = 0; + } + } + } + + return; +} + +void phase_bubble_chain_dir(H_partition* hap, ma_ug_t *ug, bub_p_t_warp* b, bubble_type* bub, +ma_utg_t *u, uint8_t* hap_label_flag, uint32_t beg_idx, uint32_t end_idx, uint32_t is_forward) +{ + uint32_t i, j, beg, sink, *a, n, max_hap_label, max_uid; + uint64_t bid; + double cur_w0, cur_w1; + for (i = beg_idx; i <= end_idx; i++) + { + bid = is_forward? u->a[i]>>33:u->a[u->n-i-1]>>33; + get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); + + if(bub->b_g->seq[bid].c != HAP_LABLE/** && bid < bub->s_bub**/) ///simple bubble + { + for (j = 0; j < n; j++) ///avoiding repeat phasing + { + if(is_hap_set(a[j]>>1, *hap)) break; + } + + if(j < n) goto complete; + + ///get current max_hap_label from current chain + get_weightest_hap_label_from_bubble(bid, hap, bub, hap_label_flag, &max_hap_label, NULL); + + + ///three levels: + ///1. has setted weight with same hap label (using current max_hap_label) + ///2. has setted weight but with different hap labels (using max max_hap_label from current weight) + ///3. has unsetted weight (add hap->hap_label) + ///4. skip, do nothing + if(max_hap_label == (uint32_t)-1 && + get_weightest_hap_label_from_bubble(bid, hap, bub, NULL, &max_hap_label, NULL) == 0) + { + goto complete; + } + + ///phase bubble + b->exist_hap_label = (uint32_t)-1; + get_phase_path(ug, beg, sink, b, hap, max_hap_label); + get_phase_path(ug, beg, sink, b, hap, max_hap_label); + for (j = 0; j < n; j++) ///set bubble as visited + { + hap_label_flag[a[j]>>1] = 1; + } + } + else + { + ///select unitig with highest related weight at one time + while (1) + { + max_uid = get_weightest_uid(a, n, hap, hap_label_flag, &max_hap_label); + if(max_uid == (uint32_t)-1) break; + + get_related_weight(max_uid, hap, &cur_w0, &cur_w1, &max_hap_label); + if(cur_w0 >= cur_w1) + { + hap->hap[max_uid] |= (max_hap_label | hap->m[0]); + } + else + { + hap->hap[max_uid] |= (max_hap_label | hap->m[1]); + } + + hap_label_flag[max_uid] = 1; + } + } + + complete:; + } +} +///ignore unitigs wihci have already been labeled in current chain (might happen) +void phase_bubble_chain(H_partition* hap, ma_ug_t *ug, bub_p_t_warp* b, bubble_type* bub, + uint8_t* hap_label_flag, uint32_t chain_id) +{ + ma_utg_t *u = &(bub->b_ug->u.a[chain_id]); + if(u->n == 0) return; + uint32_t is_forward = 1, i, max_hap_label, max_bid_idx; + memset(hap_label_flag, 0, ug->g->n_seq); + + get_weightest_hap_label_from_chain(u, hap, bub, &max_hap_label, &max_bid_idx, &is_forward); + + if(max_hap_label != (uint32_t)-1) ///means this is not a new chain + { + for (i = 0; i < hap->n; i++) + { + if(is_hap_set_label(i, *hap, max_hap_label)) hap_label_flag[i] = 1; + } + } + + if(max_hap_label == (uint32_t)-1) ///a totally new chain + { + phase_bubble_chain_dir(hap, ug, b, bub, u, hap_label_flag, 0, u->n - 1, 1); + } + else + { + if(max_bid_idx == 0) + { + phase_bubble_chain_dir(hap, ug, b, bub, u, hap_label_flag, 0, u->n - 1, 1); + } + else + { + if(is_forward) + { + phase_bubble_chain_dir(hap, ug, b, bub, u, hap_label_flag, max_bid_idx, u->n - 1, 1); + phase_bubble_chain_dir(hap, ug, b, bub, u, hap_label_flag, 0, max_bid_idx-1, 0); + } + else + { + phase_bubble_chain_dir(hap, ug, b, bub, u, hap_label_flag, 0, max_bid_idx-1, 0); + phase_bubble_chain_dir(hap, ug, b, bub, u, hap_label_flag, max_bid_idx, u->n - 1, 1); + } + } + } +} + + +uint32_t if_flip(H_partition* h, G_partition* g_p, hc_links* link, +bubble_type* bub, uint32_t gid) +{ + double weight = 0; + if(h->lock[gid]) return 0; + if(g_p->a[gid].h[0] > 0 && (g_p->a[gid].status[0] == 1 || g_p->a[gid].status[0] == -1)) + { + weight += (g_p->a[gid].weight[0] * g_p->a[gid].status[0]); + } + + if(g_p->a[gid].h[1] > 0 && (g_p->a[gid].status[1] == 1 || g_p->a[gid].status[1] == -1)) + { + weight += (g_p->a[gid].weight[1] * g_p->a[gid].status[1]); + } + weight += g_p->a[gid].weight_convex*2; + if(weight >= 0) return 0; + return 1; +} +void flip_unitig(G_partition* g_p, hc_links* link, bubble_type* bub, uint32_t id); +uint32_t phasing_improvement(H_partition* h, G_partition* g_p, ha_ug_index* idx, bubble_type* bub, hc_links* link); +uint32_t get_max_unitig(H_partition* h, G_partition* g_p, hc_links* link, bubble_type* bub); +double get_cluster_weight_debug(G_partition* g_p, hc_links* link, uint32_t *h, uint32_t h_n); + +void debug_flip(G_partition* g_p, hc_links* link, bubble_type* bub, uint32_t id) +{ + fprintf(stderr, "33333333333\n"); + uint32_t *h0, h0_n, *h1, h1_n, k, wrong; + double hw0, hw1; + for (k = wrong = 0; k < g_p->n; k++) + { + hw0 = hw1 = 0; + get_phased_block(g_p, NULL, k, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); + if(h0_n >0) hw0 = get_cluster_weight_debug(g_p, link, h0, h0_n); + if(h1_n >0) hw1 = get_cluster_weight_debug(g_p, link, h1, h1_n); + if(hw0 != g_p->a[k].weight[0]) + { + if((uint32_t)hw0 != (uint32_t)g_p->a[k].weight[0]) wrong = 1; + fprintf(stderr, "k: %u, ERROR(id: %u): hw0: %f, weight[0]: %f\n", k, id, hw0, g_p->a[k].weight[0]); + } + + if(hw1 != g_p->a[k].weight[1]) + { + if((uint32_t)hw1 != (uint32_t)g_p->a[k].weight[1]) wrong = 1; + fprintf(stderr, "k: %u, ERROR(id: %u): hw1: %f, weight[1]: %f\n", k, id, hw1, g_p->a[k].weight[1]); + } + + if(wrong) break; + } +} +void merge_phase_group_by_chain(H_partition* hap, G_partition* g_p, bubble_type* bub, uint32_t chain_id) +{ + uint32_t i, k; + uint32_t beg, sink, *a, n, pre_id, hap_label_id; + uint64_t bid, uid; + ma_utg_t *u = &(bub->b_ug->u.a[chain_id]); + + for (i = 0, pre_id = (uint32_t)-1; i < u->n; i++) + { + // fprintf(stderr, "inner i: %u, u->n: %u\n", i, (uint32_t)u->n); + bid = u->a[i]>>33; ///here is a bubble + // fprintf(stderr, "bid: %lu\n", bid); + get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); + for (k = 0; k < n; k++) + { + // fprintf(stderr, "k: %u, n: %u\n", k, n); + uid = a[k]>>1; + // fprintf(stderr, "uid: %lu\n", uid); + if(g_p->index[uid] == (uint32_t)-1) ///mean this unitig doesn't have hap label + { + pre_id = (uint32_t)-1; + continue; + } + hap_label_id = g_p->index[uid]>>1; + // fprintf(stderr, "hap_label_id: %u, hap->n: %lu\n", hap_label_id, hap->n); + if(hap_label_id == pre_id) continue; + pre_id = hap_label_id; + if(hap->lock[hap_label_id] == 1) continue; + if(if_flip(hap, g_p, hap->link, bub, hap_label_id)) + { + // fprintf(stderr, "2222222222\n"); + flip_unitig(g_p, hap->link, bub, hap_label_id); + ///debug_flip(g_p, hap->link, bub, hap_label_id); + } + } + } +} + +void print_phase_group(G_partition* g_p, bubble_type* bub, const char* command) +{ + uint32_t i, k; + partition_warp *res = NULL; + for (i = 0; i < g_p->n; i++) + { + res = &(g_p->a[i]); + fprintf(stderr, "\n%s: %u-th group: # %d = %u (weight: %f), # %d = %u (weight: %f), inner_weight: %f\n", command, i, + res->status[0], res->h[0], res->weight[0], res->status[1], res->h[1], res->weight[1], res->weight_convex); + for (k = 0; k < res->h[0]; k++) + { + fprintf(stderr, "%d: utg%.6ul\n", res->status[0], int(res->a.a[k]+1)); + } + + for (; k < res->a.n; k++) + { + fprintf(stderr, "%d: utg%.6ul\n", res->status[1], int(res->a.a[k]+1)); + } + } +} + +void set_bubble(H_partition* hap, G_partition* g_p, bubble_type* bub, block_phase_type* block, +uint64_t bid) +{ + uint32_t beg, sink, k, uid, *a, n, gid; + block->weight = 0; + get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); + for (k = 0; k < n; k++) + { + uid = a[k]>>1; + if(g_p->index[uid] == (uint32_t)-1) continue; + gid = g_p->index[uid]>>1; + block->vis.a[gid] = 1; + } +} + +uint32_t next_hap_label_id(block_phase_type* b, G_partition* g_p, bubble_type* bub, ma_utg_t *u, +int is_forward, long long* c_bid, long long* c_uid) +{ + uint32_t beg, sink, uid, *a, n, gid, pre_gid; + while (1) ///while(b->bid < (long long)u->n) + { + if(is_forward == 1 && b->bid >= (long long)u->n) break; + if(is_forward == 0 && b->bid < 0) break; + + get_bubbles(bub, u->a[b->bid]>>33, &beg, &sink, &a, &n, NULL); + while (1) ///while (b->uid < (long long)n) + { + if(is_forward == 1 && b->uid >= (long long)n) break; + if(is_forward == 0 && b->uid < 0) break; + + uid = a[b->uid]>>1; + gid = (uint32_t)-1; + if(g_p->index[uid] != (uint32_t)-1) + { + gid = g_p->index[uid]>>1; + } + if(c_bid) (*c_bid) = b->bid; + if(c_uid) (*c_uid) = b->uid; + + if(is_forward == 1) b->uid++; + if(is_forward == 0) b->uid--; + if(gid == (uint32_t)-1) continue; + + + pre_gid = uid = (uint32_t)-1; + if(is_forward == 1 && (b->uid >= 2)) uid = a[b->uid - 2]>>1; + if(is_forward == 0 && (b->uid + 2 < n)) uid = a[b->uid + 2]>>1; + if(uid != (uint32_t)-1 && g_p->index[uid] != (uint32_t)-1) pre_gid = g_p->index[uid]>>1; + + if(pre_gid == gid) continue; + + return gid; + } + + if(is_forward == 1) b->bid++, b->uid = 0; + if(is_forward == 0) b->bid--, b->uid = (long long)n - (long long)1; + } + + return (uint32_t)-1; +} + +double get_new_weight(G_partition* g_p, uint8_t* flag, hc_links* link, uint32_t gid) +{ + double total_weight = 0, weight; + int status, o_d; + uint32_t *h0, h0_n, *h1, h1_n, *h, h_n, j, k, uID; + + if(g_p->a[gid].h[0] > 0 && (g_p->a[gid].status[0] == 1 || g_p->a[gid].status[0] == -1)) + { + total_weight += (g_p->a[gid].weight[0] * g_p->a[gid].status[0]); + } + + if(g_p->a[gid].h[1] > 0 && (g_p->a[gid].status[1] == 1 || g_p->a[gid].status[1] == -1)) + { + total_weight += (g_p->a[gid].weight[1] * g_p->a[gid].status[1]); + } + total_weight += g_p->a[gid].weight_convex*2; + + + + get_phased_block(g_p, NULL, gid, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); + + h = h0; h_n = h0_n; status = g_p->a[gid].status[0]; + for (j = 0, weight = 0; j < h_n; j++) + { + for (k = 0; k < link->a.a[h[j]].e.n; k++) + { + if(link->a.a[h[j]].e.a[k].del) continue; + uID = link->a.a[h[j]].e.a[k].uID; + if(g_p->index[uID] == (uint32_t)-1) continue; + if(flag[g_p->index[uID]>>1] == 0) continue; + if((g_p->index[uID]>>1) == gid) continue; + o_d = g_p->a[g_p->index[uID]>>1].status[g_p->index[uID]&1]; + weight += (status*o_d*link->a.a[h[j]].e.a[k].weight); + } + } + total_weight -= (2*weight); + + + + + h = h1; h_n = h1_n; status = g_p->a[gid].status[1]; + for (j = 0, weight = 0; j < h_n; j++) + { + for (k = 0; k < link->a.a[h[j]].e.n; k++) + { + if(link->a.a[h[j]].e.a[k].del) continue; + uID = link->a.a[h[j]].e.a[k].uID; + if(g_p->index[uID] == (uint32_t)-1) continue; + if(flag[g_p->index[uID]>>1] == 0) continue; + if((g_p->index[uID]>>1) == gid) continue; + o_d = g_p->a[g_p->index[uID]>>1].status[g_p->index[uID]&1]; + weight += (status*o_d*link->a.a[h[j]].e.a[k].weight); + } + } + total_weight -= (2*weight); + + + + return total_weight; +} + +int identify_best_interval(block_phase_type* i_buf, uint8_t* lock, G_partition* g_p, bubble_type* bub, +ma_utg_t *u, hc_links* link, long long f_bid, long long f_uid, long long* l_bid, long long* l_uid) +{ + long long c_bid, c_uid, min_bid, min_uid; + double w = 0, min_w = 1; + uint32_t gid, val = 0; + block_phase_type b; + b.bid = f_bid; b.uid = f_uid; + memset(i_buf->vis.a, 0, g_p->n); + i_buf->weight = min_w = 1; min_bid = min_uid = -1; + (*l_bid) = (*l_uid) = -1; + + while (1) + { + gid = next_hap_label_id(&b, g_p, bub, u, 1, &c_bid, &c_uid); + if(gid == (uint32_t)-1) break; + if(i_buf->vis.a[gid] == 1) continue; + w += get_new_weight(g_p, i_buf->vis.a, link, gid); + i_buf->vis.a[gid] = 1; + if(lock[gid] == 0) val = 1; + if(val == 0) continue; + + if(min_w > w) + { + min_w = w; + min_bid = c_bid; + min_uid = c_uid; + } + } + + if(min_w < 0 && min_bid != -1 && min_uid != -1) + { + (*l_bid) = min_bid; (*l_uid) = min_uid; + i_buf->weight = min_w; + ///fprintf(stderr, "+min_w: %f, min_bid: %lld, min_uid: %lld\n", min_w, min_bid, min_uid); + } + + if(val == 0) return 1; + + return 0; +} + +void identify_best_interval_debug(block_phase_type* i_buf, G_partition* g_p, bubble_type* bub, +ma_utg_t *u, hc_links* link, long long f_bid, long long f_uid, long long* l_bid, long long* l_uid) +{ + long long c_bid, c_uid, min_bid, min_uid; + double w = 0, min_w = 1; + uint32_t gid; + block_phase_type b; + b.bid = f_bid; b.uid = f_uid; + memset(i_buf->vis.a, 0, g_p->n); + min_w = 1; min_bid = min_uid = -1; + (*l_bid) = (*l_uid) = -1; + + while (1) + { + gid = next_hap_label_id(&b, g_p, bub, u, 1, &c_bid, &c_uid); + if(gid == (uint32_t)-1) break; + if(i_buf->vis.a[gid] == 1) continue; + w += get_new_weight(g_p, i_buf->vis.a, link, gid); + if(f_bid == 689 && f_uid == 1) + { + fprintf(stderr, "gid: %u, w: %f\n", gid, w); + } + + if(min_w > w) + { + min_w = w; + min_bid = c_bid; + min_uid = c_uid; + } + i_buf->vis.a[gid] = 1; + } + + if(min_w < 0 && min_bid != -1 && min_uid != -1) + { + (*l_bid) = min_bid; (*l_uid) = min_uid; + i_buf->weight = min_w; + b.bid = min_bid; b.uid = min_uid; + + + gid = next_hap_label_id(&b, g_p, bub, u, 1, &c_bid, &c_uid); + fprintf(stderr, "-min_w: %f, f_bid: %lld, f_uid: %lld, min_bid: %lld, min_uid: %lld, gid: %u\n", + min_w, f_bid, f_uid, min_bid, min_uid, gid); + + } +} + +int flip_block(block_phase_type* i_buf, G_partition* g_p, bubble_type* bub, +ma_utg_t *u, hc_links* link, uint8_t* lock, long long f_bid, long long f_uid, long long l_bid, long long l_uid) +{ + long long c_bid = l_bid, c_uid = l_uid; + uint32_t gid, val = 0; + block_phase_type b; + b.bid = f_bid; b.uid = f_uid; + memset(i_buf->vis.a, 0, g_p->n); + val = 0; + while (1) + { + gid = next_hap_label_id(&b, g_p, bub, u, 1, &c_bid, &c_uid); + ////fprintf(stderr, "+gid: %u\n", gid); + if(gid == (uint32_t)-1) break; + ///fprintf(stderr, "lock[gid]: %u\n", lock[gid]); + if(lock[gid] == 0) + { + val = 1; + break; + } + if(c_bid == l_bid && c_uid == l_uid) break; + } + + if(val == 0) return 0; + + b.bid = f_bid; b.uid = f_uid; + while (1) + { + gid = next_hap_label_id(&b, g_p, bub, u, 1, &c_bid, &c_uid); + ///fprintf(stderr, "-gid: %u\n", gid); + if(gid == (uint32_t)-1) break; + ///fprintf(stderr, "vis[gid]: %u\n", i_buf->vis.a[gid]); + if(i_buf->vis.a[gid] == 1) continue; + lock[gid] = 1; + i_buf->vis.a[gid] = 1; + // if(f_bid == 689 && f_uid == 1) + // { + // fprintf(stderr, "sssssssssssssssssssss\n"); + // print_phase_group(g_p, bub, "Small-1"); + // fprintf(stderr, "sbsbsbsb-gid: %u\n", gid); + // } + flip_unitig(g_p, link, bub, gid); + ///flip_unitig_debug(g_p, link, bub, gid); + // if(f_bid == 689 && f_uid == 1) + // { + // fprintf(stderr, "sasasasa-gid: %u\n", gid); + // print_phase_group(g_p, bub, "Small-2"); + // fprintf(stderr, "eeeeeeeeeeeeeeeeeeeeee\n"); + // } + if(c_bid == l_bid && c_uid == l_uid) break; + } + + return 1; +} + +double get_total_weight(H_partition* h, G_partition* g_p) +{ + uint32_t i, k, uID; + hc_links* link = h->link; + int o_d = 0, o_f = 0; + double w, t_w; + for (i = 0, t_w = 0; i < h->n; i++) + { + if(g_p->index[i] == (uint32_t)-1) continue; + o_f = g_p->a[g_p->index[i]>>1].status[g_p->index[i]&1]; + for (k = 0; k < link->a.a[i].e.n; k++) + { + if(link->a.a[i].e.a[k].del) continue; + uID = link->a.a[i].e.a[k].uID; + w = link->a.a[i].e.a[k].weight; + if(g_p->index[uID] == (uint32_t)-1) continue; + o_d = g_p->a[g_p->index[uID]>>1].status[g_p->index[uID]&1]; + t_w += (o_f*o_d*w); + } + } + + return t_w; +} + +void hap_label_fliping(H_partition* hap, G_partition* g_p, bubble_type* bub, hc_links* link, uint32_t chain_id) +{ + long long c_bid, c_uid, l_bid, l_uid; + uint32_t gid; + ma_utg_t *u = &(bub->b_ug->u.a[chain_id]); + hap->b.bid = hap->b.uid = 0; + while (1) + { + gid = next_hap_label_id(&(hap->b), g_p, bub, u, 1, &c_bid, &c_uid); + if(gid == (uint32_t)-1) break; + identify_best_interval(&(hap->b), hap->lock, g_p, bub, u, link, c_bid, c_uid, &l_bid, &l_uid); + if(l_bid == -1 || l_uid == -1) continue; + + // fprintf(stderr, "\nbefore weight: %f\n", get_total_weight(hap, g_p)); + // identify_best_interval_debug(&(hap->b), g_p, bub, u, link, c_bid, c_uid, &l_bid, &l_uid); + if(flip_block(&(hap->b), g_p, bub, u, link, hap->lock, c_bid, c_uid, l_bid, l_uid)) + { + ///fprintf(stderr, "after weight +: %f\n", get_total_weight(hap, g_p)); + hap->b.bid = l_bid; + hap->b.uid = l_uid; + gid = next_hap_label_id(&(hap->b), g_p, bub, u, 1, &c_bid, &c_uid); + if(gid == (uint32_t)-1) break; + } + ///fprintf(stderr, "after weight -: %f\n", get_total_weight(hap, g_p)); + // exit(0); + } +} + +typedef struct{ + long long min_chain_id; + long long min_f_bid; + long long min_f_uid; + long long min_l_bid; + long long min_l_uid; + long long min_idx; + double min_w; +}block_res_type; + +typedef struct{ + block_phase_type* x; + uint32_t n_thread; + bubble_type* bub; + uint64_t* chain_idx;///index of each chain + uint64_t chain_idx_n; + uint64_t chain_ele_occ; + block_res_type* res; + H_partition* h; + G_partition* g_p; +}mul_block_phase_type; + +uint32_t shift_block_phase_type(ma_utg_t *u, G_partition* g_p, bubble_type* bub, +block_phase_type* b, uint32_t offset) +{ + long long c_bid, c_uid; + uint32_t gid, occ = 0; + b->bid = b->uid = 0; + while (1) + { + if(occ == offset) break; + gid = next_hap_label_id(b, g_p, bub, u, 1, &c_bid, &c_uid); + if(gid == (uint32_t)-1) break; + occ++; + } + return occ; +} + +void get_block_phase_type(uint64_t* chain_idx, G_partition* g_p, bubble_type* bub, uint32_t id, block_phase_type* i_b) +{ + uint64_t i; + ma_utg_t *u = NULL; + for (i = 0; i < bub->chain_weight.n; i++) + { + if(id >= chain_idx[i] && id < chain_idx[i+1]) break; + } + + u = &(bub->b_ug->u.a[bub->chain_weight.a[i].id]); + shift_block_phase_type(u, g_p, bub, i_b, id - chain_idx[i]); + i_b->chainID = bub->chain_weight.a[i].id; +} + +void init_mul_block_phase_type(mul_block_phase_type* x, G_partition* g_p, bubble_type* bub, uint32_t n_thread, H_partition* hap) +{ + ma_utg_t *u = NULL; + uint32_t i, n; + block_phase_type b; + x->bub = bub; + x->n_thread = n_thread; + CALLOC(x->res, x->n_thread); + CALLOC(x->x, x->n_thread); + for (i = 0; i < x->n_thread; i++) + { + kv_init(x->x[i].vis); + kv_malloc(x->x[i].vis, hap->n); + x->x[i].vis.n = hap->n; + } + + x->chain_idx_n = 0; + MALLOC(x->chain_idx, bub->chain_weight.n+1); + for (i = n = 0; i < bub->chain_weight.n; i++) + { + x->chain_idx[i] = n; + if(bub->chain_weight.a[i].del) continue; + u = &(bub->b_ug->u.a[bub->chain_weight.a[i].id]); + n += shift_block_phase_type(u, g_p, bub, &b, (uint32_t)-1); + x->chain_idx_n++; + } + x->chain_idx[i] = n;///index of chain + x->chain_ele_occ = n; +} + +void destory_mul_block_phase_type(mul_block_phase_type* x) +{ + uint32_t i; + free(x->res); + free(x->chain_idx); + for (i = 0; i < x->n_thread; i++) + { + kv_destroy(x->x[i].vis); + } +} + +void select_max_block_by_utg_multi_thread(H_partition* h, G_partition* g_p, bubble_type* bub, +hc_links* link, block_phase_type* i_b, uint64_t* chain_idx, uint32_t id, block_res_type* res) +{ + long long c_bid, c_uid, l_bid, l_uid; + uint32_t gid; + get_block_phase_type(chain_idx, g_p, bub, id, i_b); + + ma_utg_t *u = &(bub->b_ug->u.a[i_b->chainID]); + + gid = next_hap_label_id(i_b, g_p, bub, u, 1, &c_bid, &c_uid); + + if(gid == (uint32_t)-1) return; + if(identify_best_interval(i_b, h->lock, g_p, bub, u, link, c_bid, c_uid, &l_bid, &l_uid)) return; + if(l_bid == -1 || l_uid == -1) return; + + if((res->min_w > i_b->weight) || (res->min_w == i_b->weight && id < res->min_idx)) + { + res->min_w = i_b->weight; + res->min_f_bid = c_bid; + res->min_f_uid = c_uid; + res->min_l_bid = l_bid; + res->min_l_uid = l_uid; + res->min_chain_id = i_b->chainID; + res->min_idx = id; + } +} + +static void worker_for_max_block(void *data, long i, int tid) // callback for kt_for() +{ + mul_block_phase_type* x = (mul_block_phase_type*)data; + select_max_block_by_utg_multi_thread(x->h, x->g_p, x->bub, x->h->link, + &(x->x[tid]), x->chain_idx, i, &(x->res[tid])); +} + +void select_max_block_by_utg_multi_thread_by_chain(H_partition* h, G_partition* g_p, bubble_type* bub, +hc_links* link, block_phase_type* i_b, uint32_t id, block_res_type* res) +{ + long long c_bid, c_uid, l_bid, l_uid; + uint32_t gid; + ma_utg_t *u = &(bub->b_ug->u.a[id]); + i_b->bid = i_b->uid = 0; i_b->chainID = id; + while (1) + { + gid = next_hap_label_id(i_b, g_p, bub, u, 1, &c_bid, &c_uid); + if(gid == (uint32_t)-1) break; + + if(identify_best_interval(i_b, h->lock, g_p, bub, u, link, c_bid, c_uid, &l_bid, &l_uid)) + { + break; + } + if(l_bid == -1 || l_uid == -1) continue; + if(res->min_w > i_b->weight) + { + res->min_w = i_b->weight; + res->min_f_bid = c_bid; + res->min_f_uid = c_uid; + res->min_l_bid = l_bid; + res->min_l_uid = l_uid; + res->min_chain_id = i_b->chainID; + res->min_idx = id; + } + } +} + + +int get_max_block_multi_thread(H_partition* h, G_partition* g_p, bubble_type* bub, mul_block_phase_type* x, +long long* min_u, long long* min_f_bid, long long* min_f_uid, long long* min_l_bid, long long* min_l_uid, +double* min_w) +{ + uint32_t i; + (*min_w) = 1; + (*min_u) = (*min_f_bid) = (*min_f_uid) = (*min_l_bid) = (*min_l_uid) = -1; + for (i = 0; i < x->n_thread; i++) + { + x->res[i].min_chain_id = x->res[i].min_f_bid = x->res[i].min_f_uid = -1; + x->res[i].min_l_bid = x->res[i].min_l_uid = x->res[i].min_idx = -1; + x->res[i].min_w = 1; + } + x->g_p = g_p; + x->h = h; + kt_for(x->n_thread, worker_for_max_block, x, x->chain_ele_occ); + ///kt_for(x->n_thread, worker_for_max_block_by_chain, x, x->chain_idx_n); + + long long min_idx = -1; + for (i = 0; i < x->n_thread; i++) + { + if(x->res[i].min_chain_id == -1) continue; + if(x->res[i].min_f_bid == -1 || x->res[i].min_f_uid == -1) continue; + if(x->res[i].min_l_bid == -1 || x->res[i].min_l_uid == -1) continue; + if(((*min_w) > x->res[i].min_w) || ((*min_w) == x->res[i].min_w && x->res[i].min_idx < min_idx)) + { + (*min_w) = x->res[i].min_w; + (*min_u) = x->res[i].min_chain_id; + (*min_f_bid) = x->res[i].min_f_bid; + (*min_f_uid) = x->res[i].min_f_uid; + (*min_l_bid) = x->res[i].min_l_bid; + (*min_l_uid) = x->res[i].min_l_uid; + min_idx = x->res[i].min_idx; + } + } + + if((*min_u) != -1 && (*min_f_bid) != -1 && (*min_f_uid) != -1 && (*min_l_bid) != -1 && (*min_l_uid) != -1) + { + return 1; + } + + return 0; +} + +void select_max_block_by_utg(H_partition* hap, G_partition* g_p, bubble_type* bub, hc_links* link, uint32_t chain_id, +long long* min_f_bid, long long* min_f_uid, long long* min_l_bid, long long* min_l_uid, double* min_w) +{ + long long c_bid, c_uid, l_bid, l_uid; + uint32_t gid; + ma_utg_t *u = &(bub->b_ug->u.a[chain_id]); + (*min_w) = 1; + hap->b.bid = hap->b.uid = 0; + (*min_f_bid) = (*min_f_uid) = (*min_l_bid) = (*min_l_uid) = -1; + while (1) + { + gid = next_hap_label_id(&(hap->b), g_p, bub, u, 1, &c_bid, &c_uid); + if(gid == (uint32_t)-1) break; + + if(identify_best_interval(&(hap->b), hap->lock, g_p, bub, u, link, c_bid, c_uid, &l_bid, &l_uid)) + { + break; + } + if(l_bid == -1 || l_uid == -1) continue; + if((*min_w) > hap->b.weight) + { + (*min_w) = hap->b.weight; + (*min_f_bid) = c_bid; + (*min_f_uid) = c_uid; + (*min_l_bid) = l_bid; + (*min_l_uid) = l_uid; + } + } +} + + +int get_max_block(H_partition* h, G_partition* g_p, bubble_type* bub, long long* min_u, +long long* min_f_bid, long long* min_f_uid, long long* min_l_bid, long long* min_l_uid, +double* min_w) +{ + uint32_t i; + long long f_bid, f_uid, l_bid, l_uid; + double w; + (*min_w) = 1; + (*min_u) = (*min_f_bid) = (*min_f_uid) = (*min_l_bid) = (*min_l_uid) = -1; + for (i = 0; i < bub->chain_weight.n; i++) + { + if(bub->chain_weight.a[i].del) continue; + select_max_block_by_utg(h, g_p, bub, h->link, bub->chain_weight.a[i].id, + &f_bid, &f_uid, &l_bid, &l_uid, &w); + if(f_bid == -1 || f_uid == -1 || l_bid == -1 || l_uid == -1) continue; + if((*min_w) > w) + { + (*min_w) = w; + (*min_u) = bub->chain_weight.a[i].id; + (*min_f_bid) = f_bid; + (*min_f_uid) = f_uid; + (*min_l_bid) = l_bid; + (*min_l_uid) = l_uid; + } + } + + if((*min_u) != -1 && (*min_f_bid) != -1 && (*min_f_uid) != -1 && (*min_l_bid) != -1 && (*min_l_uid) != -1) + { + return 1; + } + + return 0; +} + +void phasing_improvement_by_block(H_partition* h, G_partition* g_p, bubble_type* bub, mul_block_phase_type* x) +{ + long long min_u, min_f_bid, min_f_uid, min_l_bid, min_l_uid; + double min_w; + + memset(h->lock, 0, sizeof(uint8_t)*h->n); + while(get_max_block_multi_thread(h, g_p, bub, x, &min_u, &min_f_bid, &min_f_uid, &min_l_bid, &min_l_uid, &min_w)) + ///while(get_max_block(h, g_p, bub, &min_u, &min_f_bid, &min_f_uid, &min_l_bid, &min_l_uid, &min_w)) + { + ///fprintf(stderr, "\nmin_w: %f, min_u: %lld, min_f_bid: %lld, min_f_uid: %lld, min_l_bid: %lld, min_l_uid: %lld\n", min_w, min_u, min_f_bid, min_f_uid, min_l_bid, min_l_uid); + ///fprintf(stderr, "before weight: %f\n", get_total_weight(h, g_p)); + flip_block(&(h->b), g_p, bub, &(bub->b_ug->u.a[min_u]), h->link, h->lock, min_f_bid, + min_f_uid, min_l_bid, min_l_uid); + ///fprintf(stderr, "after weight: %f\n", get_total_weight(h, g_p)); + } +} + +void flip_by_chain(H_partition* h, G_partition* g_p, bubble_type* bub) +{ + uint32_t i; + memset(h->lock, 0, sizeof(uint8_t)*h->n); + for (i = 0; i < bub->chain_weight.n; i++) + { + if(bub->chain_weight.a[i].del) continue; + merge_phase_group_by_chain(h, g_p, bub, bub->chain_weight.a[i].id); + } + + double pre_w = get_total_weight(h, g_p), current_w; + uint32_t round = 0; + while (1) + { + memset(h->lock, 0, sizeof(uint8_t)*h->n); + while (1) + { + i = get_max_unitig(h, g_p, h->link, bub); + if(i == (uint32_t)-1) break; + h->lock[i] = 1; + flip_unitig(g_p, h->link, bub, i); + } + current_w = get_total_weight(h, g_p); + ///fprintf(stderr, "[M::%s::round %u, pre_w: %f, current_w: %f]\n", __func__, round, pre_w, current_w); + if(ceil(current_w) <= ceil(pre_w)) break; + round++; + pre_w = current_w; + } + + + ///print_phase_group(g_p, bub, "Large-pre"); + + ///fprintf(stderr, "[M::%s::round %u, before block flipping: %f]\n", __func__, round, get_total_weight(h, g_p)); + + mul_block_phase_type b_x; + init_mul_block_phase_type(&b_x, g_p, bub, asm_opt.thread_num, h); + + pre_w = get_total_weight(h, g_p); + while (1) + { + phasing_improvement_by_block(h, g_p, bub, &b_x); + current_w = get_total_weight(h, g_p); + ///fprintf(stderr, "[M::%s::round %u, after block flipping: %f]\n", __func__, round, get_total_weight(h, g_p)); + ///debug_flip(g_p, h->link, bub, 0); + if(ceil(current_w) <= ceil(pre_w)) break; + round++; + pre_w = current_w; + } + destory_mul_block_phase_type(&b_x); + + for (i = 0; i < g_p->n; i++) + { + update_partition_flag(h, g_p, h->link, i); + } +} + +void flip_by_node(H_partition* h, G_partition* g_p, bubble_type* bub) +{ + uint32_t i; + memset(h->lock, 0, sizeof(uint8_t)*h->n); + + + double pre_w = get_total_weight(h, g_p), current_w; + uint32_t round = 0; + while (1) + { + memset(h->lock, 0, sizeof(uint8_t)*h->n); + while (1) + { + i = get_max_unitig(h, g_p, h->link, bub); + if(i == (uint32_t)-1) break; + h->lock[i] = 1; + flip_unitig(g_p, h->link, bub, i); + } + current_w = get_total_weight(h, g_p); + ///fprintf(stderr, "[M::%s::round %u, pre_w: %f, current_w: %f]\n", __func__, round, pre_w, current_w); + if(ceil(current_w) <= ceil(pre_w)) break; + round++; + pre_w = current_w; + } + + ///fprintf(stderr, "[M::%s::round %u, before block flipping: %f]\n", __func__, round, get_total_weight(h, g_p)); + + for (i = 0; i < g_p->n; i++) + { + update_partition_flag(h, g_p, h->link, i); + } +} + + +void link_phase_group(H_partition* hap, bubble_type* bub) +{ + double index_time = yak_realtime(); + uint32_t i, k, n = (hap->label>>hap->label_shift)+1, *h0, h0_n, *h1, h1_n;; + init_G_partition(&(hap->group_g_p), hap->n); + partition_warp *res = NULL; + for (i = 0; i < n; i++)///how many haplotype group + { + kv_pushp(partition_warp, hap->group_g_p, &res); + kv_init(res->a); + res->full_bub = 0; + res->h[0] = res->h[1] = 0; + res->status[0] = 1; res->status[1] = -1; + res->weight[0] = res->weight[1] = res->weight_convex = 0; + ///all unitigs + for (k = 0; k < hap->n; k++) + { + if(get_phase_group(hap, k) == i && get_phase_status(hap, k) == 1) + { + kv_push(uint32_t, res->a, k); + res->h[0]++; + } + } + + for (k = 0; k < hap->n; k++) + { + if(get_phase_group(hap, k) == i && get_phase_status(hap, k) == -1) + { + kv_push(uint32_t, res->a, k); + res->h[1]++; + } + } + + for (k = 0; k < res->h[0]; k++) + { + ///if(hap->group_g_p.index[res->a.a[k]] != (uint32_t)-1) fprintf(stderr, "ERROR---00\n"); + hap->group_g_p.index[res->a.a[k]] = hap->group_g_p.n-1; + hap->group_g_p.index[res->a.a[k]] = hap->group_g_p.index[res->a.a[k]] << 1; + } + + for (; k < res->a.n; k++) + { + ///if(hap->group_g_p.index[res->a.a[k]] != (uint32_t)-1) fprintf(stderr, "ERROR---11\n"); + hap->group_g_p.index[res->a.a[k]] = hap->group_g_p.n-1; + hap->group_g_p.index[res->a.a[k]] = (hap->group_g_p.index[res->a.a[k]] << 1) + 1; + } + + get_phased_block(&(hap->group_g_p), NULL, i, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); + if(h0_n >0) res->weight[0] = get_cluster_weight(hap, hap->link, h0, h0_n); + if(h1_n >0) res->weight[1] = get_cluster_weight(hap, hap->link, h1, h1_n); + res->weight_convex = get_cluster_inner_weight(hap, hap->link, h0, h0_n, h1, h1_n); + } + + fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); + // for (i = 0; i < n; i++) + // { + // double w0 = 0, w1 = 0; + // res = &(hap->group_g_p.a[i]); + // fprintf(stderr, "%u-th group: # %d = %u, # %d = %u\n", i, + // res->status[0], res->h[0], res->status[1], res->h[1]); + // get_phased_block(&(hap->group_g_p), NULL, i, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); + // if(h0_n >0) w0 = get_cluster_weight_debug(&(hap->group_g_p), hap->link, h0, h0_n); + // if(h1_n >0) w1 = get_cluster_weight_debug(&(hap->group_g_p), hap->link, h1, h1_n); + // if(w0 != res->weight[0]) fprintf(stderr, "i: %u, ERROR: w0: %f, weight[0]: %f\n", i, w0, res->weight[0]); + // if(w1 != res->weight[1]) fprintf(stderr, "i: %u, ERROR: w1: %f, weight[1]: %f\n", i, w1, res->weight[1]); + + + // for (k = 0; k < res->h[0]; k++) + // { + // fprintf(stderr, "%d: utg%.6ul\n", res->status[0], int(res->a.a[k]+1)); + // } + + // for (; k < res->a.n; k++) + // { + // fprintf(stderr, "%d: utg%.6ul\n", res->status[1], int(res->a.a[k]+1)); + // } + // } + + /*******************************for debug************************************/ + // for (i = 0; i < hap->n; i++) + // { + // if(hap->link->a.a[i].e.n == 0) continue; + // if(get_phase_status(hap, i) == -2) + // { + // fprintf(stderr, "ERROR+++: i: %u, group: %u, bub->index: %u\n", i, get_phase_group(hap, i), bub->index[i]); + // for (k = 0; k < hap->link->a.a[i].e.n; k++) + // { + // fprintf(stderr, "k: %u, uID: %u, weight: %f, del: %u\n", k, hap->link->a.a[i].e.a[k].uID, + // hap->link->a.a[i].e.a[k].weight, hap->link->a.a[i].e.a[k].del); + // } + // } + // } + /*******************************for debug************************************/ + + + flip_by_chain(hap, &(hap->group_g_p), bub); + ///print_phase_group(&(hap->group_g_p), bub, "Large"); +} + +void print_chain_phasing(H_partition* hap, ma_ug_t *ug, bubble_type* bub, uint32_t chain_id) +{ + uint32_t i, k; + uint32_t beg, sink, *a, n; + uint64_t bid, uid; + ma_utg_t *u = &(bub->b_ug->u.a[chain_id]); + fprintf(stderr, "\n**********chain_id: %u**********\n", chain_id); + for (i = 0; i < u->n; i++) + { + bid = u->a[i]>>33; + fprintf(stderr, "(%u) chain_id: %u, u->n: %u, bid: %u\n", i, chain_id, (uint32_t)u->n, i); + get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); + for (k = 0; k < n; k++) + { + uid = a[k]>>1; + fprintf(stderr, "utg%.6ul, hap: %u, group: %u, stats: %d\n", (int)(uid+1), hap->hap[uid], + get_phase_group(hap, uid), get_phase_status(hap, uid)); + } + } +} + +int graph_bipartiteness(uint32_t* b_a, uint32_t b_a_n, uint8_t *color, hc_links* link, kvec_t_u32_warp* stack) +{ + if(b_a_n == 0) return 0; + uint32_t i, uID, cur, occ = 0, sucess = 0, c; + for (i = 0; i < b_a_n; i++) color[b_a[i]>>1] = 8; + stack->a.n = 0; + kv_push(uint32_t, stack->a, b_a[0]>>1); + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + if((color[cur] & 1) == 0) occ++; + color[cur] |= 1; + for (i = 0; i < link->a.a[cur].f.n; i++) + { + if(link->a.a[cur].f.a[i].del) continue; + if(link->a.a[cur].f.a[i].dis != RC_0) continue; + uID = link->a.a[cur].f.a[i].uID; + if((color[uID] & 8) == 0) continue; + if((color[uID] & 1) == 1) continue; + kv_push(uint32_t, stack->a, uID); + } + } + if(occ != b_a_n) goto Failed; + + sucess = 1; + for (i = 0; i < b_a_n; i++) color[b_a[i]>>1] = 8; + stack->a.n = 0; + kv_push(uint32_t, stack->a, b_a[0]>>1); + color[b_a[0]>>1] |= 2;///colored + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + color[cur] |= 1; + c = color[cur] & 4; ///get color + for (i = 0; i < link->a.a[cur].f.n; i++) + { + if(link->a.a[cur].f.a[i].del) continue; + if(link->a.a[cur].f.a[i].dis != RC_0) continue; + uID = link->a.a[cur].f.a[i].uID; + if((color[uID] & 8) == 0) continue; + if((color[uID] & 2) && ((color[uID] & 4) == c)) break; ///conflict + if((color[uID] & 1) == 1) continue; + kv_push(uint32_t, stack->a, uID); + color[uID] |= 2; color[uID] |= (c^4); + } + + if(i != link->a.a[cur].f.n) + { + sucess = -1; + break; + } + } + + Failed: + if(sucess != 1) + { + for (i = 0; i < b_a_n; i++) color[b_a[i]>>1] = 0; + } + + return sucess; +} + +void assign_per_unitig_G_partition(G_partition* g_p, uint64_t hap_n, hc_links* link, bubble_type* bub, +uint32_t bubble_first) +{ + double index_time = yak_realtime(); + reset_G_partition(g_p, hap_n); + + partition_warp* res = NULL; + hc_edge *a = NULL; + uint32_t i, a_n, v, u, uv = (uint32_t)-1, k, k_n, k_nv, k_nu, beg, sink, *b_a = NULL, b_a_n; + + if(bubble_first) + { + int c; + kvec_t_u32_warp stack; kv_init(stack.a); + uint8_t *color = NULL; CALLOC(color, hap_n); + uint32_t n_bub = bub->f_bub + bub->b_bub; + for (i = 0; i < n_bub; i++) + { + get_bubbles(bub, i, &beg, &sink, &b_a, &b_a_n, NULL); + if(b_a_n == 2 && i < bub->f_bub) + { + continue; + } + ///full bubble do not overlap with any others + ///broken bubbles might be, but should do nothing + c = graph_bipartiteness(b_a, b_a_n, color, link, &stack); + + if(c == 0) + { + fprintf(stderr, "too good: s-utg%.6ul && e-utg%.6ul && %s\n",(beg>>1)+1, (sink>>1)+1, b_a_n != 4? "abnormal" : "normal"); + } + if(c == -1) + { + fprintf(stderr, "too bad: s-utg%.6ul && e-utg%.6ul\n",(beg>>1)+1, (sink>>1)+1); + } + if(c == 1) + { + fprintf(stderr, "\nprefect=%u: s-utg%.6ul && e-utg%.6ul\n", b_a_n, (beg>>1)+1, (sink>>1)+1); + + + for (k = 0; k < b_a_n; k++) + { + if((color[b_a[k]>>1] & 2) == 0) fprintf(stderr, "ERROR\n"); + if((color[b_a[k]>>1] & 4) == 0) fprintf(stderr, "0: utg%.6ul\n", (b_a[k]>>1)+1); + } + + for (k = 0; k < b_a_n; k++) + { + if((color[b_a[k]>>1] & 2) == 0) fprintf(stderr, "ERROR\n"); + if((color[b_a[k]>>1] & 4) != 0) fprintf(stderr, "1: utg%.6ul\n", (b_a[k]>>1)+1); + } + + for (k = 0; k < b_a_n; k++) color[b_a[k]>>1] = 0; + } + } + free(color); + kv_destroy(stack.a); + } + + for (i = 0; i < hap_n; i++) + { + v = i; + a = link->a.a[v].f.a; + a_n = link->a.a[v].f.n; + for (k = k_n = 0; k < a_n; k++) + { + if(a[k].del) continue; + if(a[k].dis != RC_0) break; + u = a[k].uID; + k_n++; + } + if(k_n != 1) + { + u = (uint32_t)-1; + goto push_uv; + } + + a = link->a.a[u].f.a; + a_n = link->a.a[u].f.n; + for (k = k_n = 0; k < a_n; k++) + { + if(a[k].del) continue; + if(a[k].dis != RC_0) break; + uv = a[k].uID; + k_n++; + } + if(k_n != 1 || uv != v) + { + u = (uint32_t)-1; + goto push_uv; + } + + push_uv: + k_nv = 0;k_nu = 0; + + // not such easy. need to deal with here very carefully + // if(g_p->index[v] != (uint32_t)-1) continue; + // if(u != (uint32_t)-1 && g_p->index[u] != (uint32_t)-1) u = (uint32_t)-1; + + a = link->a.a[v].e.a; + a_n = link->a.a[v].e.n; + for (k = 0; k < a_n; k++) + { + if(a[k].del) continue; + k_nv++; + } + + if(u != (uint32_t)-1) + { + a = link->a.a[u].e.a; + a_n = link->a.a[u].e.n; + for (k = 0; k < a_n; k++) + { + if(a[k].del) continue; + k_nu++; + } + } + if(k_nv == 0) continue; + if(k_nv > 0 && k_nu > 0 && v > u) continue; + + kv_pushp(partition_warp, *g_p, &res); + kv_init(res->a); + res->full_bub = 0; + res->h[0] = 1; res->h[1] = 0; + kv_push(uint32_t, res->a, v); + if(u != (uint32_t)-1) + { + res->h[1] = 1; + kv_push(uint32_t, res->a, u); + } + + for (k = 0; k < res->h[0]; k++) + { + g_p->index[res->a.a[k]] = g_p->n-1; + g_p->index[res->a.a[k]] = g_p->index[res->a.a[k]] << 1; + } + + for (; k < res->a.n; k++) + { + g_p->index[res->a.a[k]] = g_p->n-1; + g_p->index[res->a.a[k]] = (g_p->index[res->a.a[k]] << 1) + 1; + } + } + fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); +} + +typedef struct { + double weight; + uint64_t p_id, beg_idx, end_idx; + uint8_t used; +}bub_sort_type; + +typedef struct { + bub_sort_type* a; + size_t n, m; +}bub_sort_vec; + +double get_specific_weight_by_chain(uint64_t* ids, uint64_t beg_idx, uint64_t end_idx, uint64_t p_id, +hc_links* link, uint8_t* vis, uint8_t flag) +{ + uint64_t x, k; + uint32_t uid; + double w; + for (x = beg_idx, w = 0; x <= end_idx; x++) + { + uid = (uint32_t)((uint32_t)ids[x])>>1; + for (k = 0; k < link->a.a[uid].e.n; k++) + { + if(link->a.a[uid].e.a[k].del) continue; + if(vis[link->a.a[uid].e.a[k].uID] != flag) continue; + w += link->a.a[uid].e.a[k].weight; + } + } + + return w; +} + +int cmp_bubble_ele_by_chain(const void * a, const void * b) +{ + if((*(bub_sort_type*)a).weight == (*(bub_sort_type*)b).weight) + { + return (*(bub_sort_type*)a).weight > (*(bub_sort_type*)b).weight? -1 : 1; + } + + return 0; +} + +uint32_t get_max_hap_g(bub_sort_vec* w_stack, uint32_t* require_iso) +{ + uint32_t k, max_idx = (uint32_t)-1; + double max_w; + for (k = require_iso? (*require_iso)+1 : 0, max_idx = (uint32_t)-1; k < w_stack->n; k++) + { + if(w_stack->a[k].used) continue; + if(!require_iso) + { + if(w_stack->a[k].p_id == (uint32_t)-1) continue; + if((max_idx == (uint32_t)-1) || (max_idx != (uint32_t)-1 && max_w < w_stack->a[k].weight)) + { + max_w = w_stack->a[k].weight; + max_idx = k; + } + } + else + { + if(w_stack->a[k].p_id != (uint32_t)-1) continue; + return k; + } + } + + if(require_iso && (*require_iso) != 0) + { + for (k = 0; k < w_stack->n; k++) + { + if(w_stack->a[k].used) continue; + if(w_stack->a[k].p_id != (uint32_t)-1) continue; + return k; + } + } + + return max_idx; +} + +void update_bub_sort_vec(uint64_t* ids, bub_sort_vec* w_stack, uint32_t max_idx, hc_links* link, +uint32_t* set_hap) +{ + w_stack->a[max_idx].used = 1; + uint64_t i, k; + uint32_t uid, pid_idx; + for (i = w_stack->a[max_idx].beg_idx; i <= w_stack->a[max_idx].end_idx; i++) + { + uid = (uint32_t)((uint32_t)ids[i])>>1; + for (k = 0; k < link->a.a[uid].e.n; k++) + { + if(link->a.a[uid].e.a[k].del) continue; + pid_idx = set_hap[link->a.a[uid].e.a[k].uID]; + if(pid_idx == (uint32_t)-1) continue; + if(w_stack->a[pid_idx].used) continue; + w_stack->a[pid_idx].weight += link->a.a[uid].e.a[k].weight; + } + } +} + +void sort_bubble_ele_by_chain(G_partition* g_p, hc_links* link, bubble_type* bub, kvec_t_u64_warp* stack, +bub_sort_vec* w_stack, uint8_t* vis, uint32_t* set_hap, uint32_t n_utg, uint32_t chain_id) +{ + uint32_t max_idx, i, k, j, m, beg, sink, *a, n, flag_cur = 3, flag_right = 2, flag_left = 1, flag_unset = 0; + uint64_t bid, uid, pid, pre_pid; + ma_utg_t *u = &(bub->b_ug->u.a[chain_id]); + bub_sort_type *p = NULL; + memset(vis, flag_unset, n_utg); + for (i = 0; i < u->n; i++) + { + bid = u->a[i]>>33; + get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); + for (k = 0; k < n; k++) + { + uid = a[k]>>1; + vis[uid] = flag_right; + } + } + + for (i = 0; i < u->n; i++) + { + stack->a.n = 0; w_stack->n = 0; + bid = u->a[i]>>33; + get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); + for (k = 0; k < n; k++) + { + uid = a[k]>>1; + pid = g_p->index[uid]; + if(pid != (uint32_t)-1) pid >>= 1; + kv_push(uint64_t, stack->a, (pid<<32)|a[k]); + vis[uid] = flag_cur; + } + radix_sort_hc64(stack->a.a, stack->a.a + stack->a.n);///sort is to dedup pid + + for (k = 0, pre_pid = (uint64_t)-1; k < stack->a.n; k++) + { + if((stack->a.a[k]>>32) == pre_pid) continue; + if(w_stack->n > 0) w_stack->a[w_stack->n-1].end_idx = k - 1; + + pre_pid = stack->a.a[k]>>32; + kv_pushp(bub_sort_type, *w_stack, &p); + p->weight = 0; + p->p_id = pre_pid; + p->beg_idx = k; + p->end_idx = (uint64_t)-1; + p->used = 0; + } + if(w_stack->n > 0) w_stack->a[w_stack->n-1].end_idx = k - 1; + + ///get each hap id + for (k = 0; k < w_stack->n; k++) + { + w_stack->a[k].weight += get_specific_weight_by_chain(stack->a.a, w_stack->a[k].beg_idx, w_stack->a[k].end_idx, w_stack->a[k].p_id, + link, vis, flag_left); + w_stack->a[k].weight -= get_specific_weight_by_chain(stack->a.a, w_stack->a[k].beg_idx, w_stack->a[k].end_idx, w_stack->a[k].p_id, + link, vis, flag_right); + for (j = w_stack->a[k].beg_idx; j <= w_stack->a[k].end_idx; j++) + { + set_hap[((uint32_t)stack->a.a[j])>>1] = k; + } + } + + m = 0; + while ((max_idx = get_max_hap_g(w_stack, NULL)) != (uint32_t)-1) + { + for (j = w_stack->a[max_idx].beg_idx; j <= w_stack->a[max_idx].end_idx; j++) + { + a[m] = (uint32_t)stack->a.a[j]; + m++; + } + update_bub_sort_vec(stack->a.a, w_stack, max_idx, link, set_hap); + } + + while ((max_idx = get_max_hap_g(w_stack, &max_idx)) != (uint32_t)-1) + { + for (j = w_stack->a[max_idx].beg_idx; j <= w_stack->a[max_idx].end_idx; j++) + { + a[m] = (uint32_t)stack->a.a[j]; + m++; + } + update_bub_sort_vec(stack->a.a, w_stack, max_idx, link, set_hap); + } + + + /** + qsort(w_stack->a, w_stack->n, sizeof(bub_sort_type), cmp_bubble_ele_by_chain); + + m = 0; + + for (k = 0; k < w_stack->n; k++) + { + if(w_stack->a[k].p_id == (uint32_t)-1) continue; + for (j = w_stack->a[k].beg_idx; j <= w_stack->a[k].end_idx; j++) + { + a[m] = (uint32_t)stack->a.a[j]; + m++; + } + } + + for (k = 0; k < w_stack->n; k++) + { + if(w_stack->a[k].p_id != (uint32_t)-1) continue; + for (j = w_stack->a[k].beg_idx; j <= w_stack->a[k].end_idx; j++) + { + a[m] = (uint32_t)stack->a.a[j]; + m++; + } + } + **/ + + for (k = 0; k < n; k++) + { + uid = a[k]>>1; + vis[uid] = flag_left; + set_hap[uid] = (uint32_t)-1; + } + } +} + +void sort_bubble_ele(G_partition* g_p, hc_links* link, bubble_type* bub, uint32_t n_utg) +{ + double index_time = yak_realtime(); + kvec_t_u64_warp stack; kv_init(stack.a); + bub_sort_vec w_stack; kv_init(w_stack); + uint8_t* vis = NULL; MALLOC(vis, n_utg); + uint32_t* set_hap = NULL; MALLOC(set_hap, n_utg); memset(set_hap, -1, sizeof(uint32_t)*n_utg); + uint32_t i; + + for (i = 0; i < bub->chain_weight.n; i++) + { + if(bub->chain_weight.a[i].del) continue; + sort_bubble_ele_by_chain(g_p, link, bub, &stack, &w_stack, vis, set_hap, n_utg, bub->chain_weight.a[i].id); + } + + kv_destroy(stack.a); kv_destroy(w_stack); free(vis); free(set_hap); + fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); +} + +uint32_t init_contig_partition(H_partition* hap, ha_ug_index* idx, bubble_type* bub, hc_links* link) +{ + ///hc_links* link = idx->link; + ma_ug_t *ug = idx->ug; + bub_p_t_warp b; + memset(&b, 0, sizeof(bub_p_t_warp)); + CALLOC(b.a, ug->g->n_seq*2); + uint32_t i, nv = ug->g->n_seq * 2, max_i, max_hap_label; + for (i = 0; i < nv; i++) + { + b.a[i].w[0] = b.a[i].w[1] = b.a[i].nh = 0; + b.a[i].p =b.a[i].d = b.a[i].nc = b.a[i].uc = b.a[i].ac = b.a[i].r = b.a[i].s = 0; + } + uint8_t* hap_label_flag = NULL; + CALLOC(hap_label_flag, ug->g->n_seq); + + + hap->n = ug->u.n; + MALLOC(hap->hap, hap->n); + memset(hap->hap, 0, hap->n*sizeof(uint32_t)); + MALLOC(hap->lock, hap->n); + memset(hap->lock, 0, hap->n); + hap->m[0] = 1; hap->m[1] = 2; hap->m[2] = 4; + hap->link = link; + hap->label = 0; + hap->label_add = 8;//1000, for hap group + for(hap->label_shift=1; (uint64_t)(1<label_shift)<(uint64_t)hap->label_add; hap->label_shift++); + kv_init(hap->label_buffer); + kv_init(hap->b.vis); kv_malloc(hap->b.vis, hap->n); hap->b.vis.n = hap->n; + + ///sorted by weight + for (i = 0; i < bub->chain_weight.n; i++) + { + if(bub->chain_weight.a[i].del) continue; + phase_bubble_chain(hap, ug, &b, bub, hap_label_flag, bub->chain_weight.a[i].id); + ///print_chain_phasing(hap, ug, bub, bub->chain_weight.a[i].id); + } + + memset(hap_label_flag, 1, ug->g->n_seq); + while (1) + { + max_i = get_unset_com(hap, bub, ug, hap_label_flag, &max_hap_label); + if(max_i == (uint32_t)-1) break; + phase_com(hap, ug, &b, bub, max_i, max_hap_label); + } + + for (i = 0; i < hap->n; i++) + { + if((hap->hap[i]&hap->m[0])&&(hap->hap[i]&hap->m[1])) + { + hap->hap[i] >>= hap->label_shift; + hap->hap[i] <<= hap->label_shift; + hap->hap[i] |= hap->m[2]; + reset_ambiguous_label(hap, hap_label_flag, i); + } + } + + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + + init_G_partition(&(hap->g_p), hap->n); + + link_phase_group(hap, bub); + + assign_per_unitig_G_partition(&(hap->g_p), hap->n, link, bub, 0);///warp unitigs + + adjust_contig_partition(hap, link); + + update_bubble_chain(ug, bub, 0, 1); + + resolve_bubble_chain_tangle(ug, bub); + + clean_bubble_chain_by_HiC(ug, link, bub); + + append_boundary_chain(ug, link, bub); + + sort_bubble_ele(&(hap->g_p), link, bub, hap->n); + + free(hap_label_flag); + return 1; +} + +double get_path_phasing_weight(uint32_t query, uint32_t v0, uint32_t root, bub_p_t_warp *b, kv_u_trans_t *ta) +{ + if(v0 == root) return 0; + uint32_t v, u; + u_trans_t *p = NULL; + double nw = 0; + v = v0; + do { + u = b->a[v].p; // u->v + get_u_trans_spec(ta, query>>1, v>>1, &p, NULL); + if(p && (!p->del)) nw += p->nw; + v = u; + } while (v != root); + + return nw; +} + +void get_related_phasing_weight(uint32_t x, kv_u_trans_t *ta, double* w0, double* w1, int8_t *s) +{ + (*w0) = (*w1) = 0; + if(x >= ta->idx.n) return; + uint32_t e_n, k; + u_trans_t* e = u_trans_a(*ta, x); + e_n = u_trans_n(*ta, x); + for (k = 0; k < e_n; k++) + { + if(e[k].del) continue; + if(s[e[k].tn] > 0) (*w0) += e[k].nw; + else if(s[e[k].tn] < 0) (*w1) += e[k].nw; + } +} + +void set_phase_path(bub_p_t_warp *b, uint32_t root, kv_u_trans_t *ta, ps_t *s) +{ + int8_t f; + uint32_t v, u; + double z[2], cur_w[2]; + z[0] = z[1] = 0; + + v = b->S.a[0]; + do { + u = b->a[v].p; // u->v + if(v != b->S.a[0]) + { + get_related_phasing_weight(v>>1, ta, &cur_w[0], &cur_w[1], s->s); + z[0] += cur_w[0]; z[1] += cur_w[1]; + } + v = u; + } while (v != root); + + if(z[0] - z[1] < 0) + { + f = 1; + } + else if(z[0] - z[1] > 0) + { + f = -1; + } + else + { + s->xs = kr_splitmix64(s->xs); + f = s->xs&1? 1 : -1; + } + + v = b->S.a[0]; + do { + u = b->a[v].p; // u->v + if(v != b->S.a[0]) s->s[v>>1] = f; + v = u; + } while (v != root); +} + +uint32_t bub_phase(ma_ug_t *ug, uint32_t beg, uint32_t end, bub_p_t_warp *b, kv_u_trans_t *ta, ps_t *s) +{ + asg_t *g = ug->g; + if(g->seq[beg>>1].del) return 0; // already deleted + if(get_real_length(g, beg, NULL)<2) return 0; + uint32_t i, is_end, n_pending, to_replace, cur_nc, cur_uc, cur_ac, n_tips, tip_end, n_pop; + double cur_nh, cur_w0, cur_w1, cur_rate, max_rate, cur_weight, min_weight; + ///S saves nodes with all incoming edges visited + b->S.n = b->T.n = b->b.n = b->e.n = 0; + ///for each node, b->a saves all related information + b->a[beg].d = b->a[beg].nc = b->a[beg].ac = b->a[beg].uc = 0; + b->a[beg].nh = b->a[beg].w[0] = b->a[beg].w[1] = 0; + b->a[beg].p = (uint32_t)-1; + ///b->S is the nodes with all incoming edges visited + kv_push(uint32_t, b->S, beg); + n_pop = n_tips = n_pending = 0; + tip_end = (uint32_t)-1; + + do { + ///v is a node that all incoming edges have been visited + ///d is the distance from v0 to v + uint32_t v = kv_pop(b->S); + uint32_t d = b->a[v].d, nc = b->a[v].nc, uc = b->a[v].uc, ac = b->a[v].ac; + double nh = b->a[v].nh;///path weight + double nw_0 = b->a[v].w[0], nw_1 = b->a[v].w[1];///weight to haplotype 1/2 + + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + for (i = 0; i < nv; ++i) { + uint32_t w = av[i].v, l = (uint32_t)av[i].ul; // v->w with length l, not overlap length + bub_p_t *t = &b->a[w]; + is_end = 0; + if((w>>1) == (end>>1)) is_end = 1; + //got a circle + if ((w>>1) == (beg>>1)) goto pop_reset; + if (av[i].del) continue; + ///push the edge + kv_push(uint32_t, b->e, (g->idx[v]>>32) + i); + + if (t->s == 0) + { // this vertex has never been visited + kv_push(uint32_t, b->b, w); // save it for revert + ///t->p is the parent node of + ///t->s = 1 means w has been visited + ///d is len(v0->v), l is len(v->w), so t->d is len(v0->w) + t->p = v, t->s = 1, t->d = d + l; + t->r = get_real_length(g, w^1, NULL); + + if(is_end == 0) + { + t->nc = nc + ug->u.a[(w>>1)].n; + t->nh = nh + get_path_phasing_weight(w, v, beg, b, ta); + get_related_phasing_weight(w>>1, ta, &(t->w[0]), &(t->w[1]), s->s); + t->w[0] += nw_0; t->w[1] += nw_1; + t->ac = ac + ((s->s[w>>1] == 0)? ug->u.a[(w>>1)].n : 0); + t->uc = uc + ((s->s[w>>1] != 0)? ug->u.a[(w>>1)].n : 0); + } + + ++n_pending; + } + else { + to_replace = 0; + + if(is_end) + { + cur_nc = nc; cur_nh = nh; + cur_w0 = nw_0; cur_w1= nw_1; + cur_ac = ac; cur_uc = uc; + } + else + { + cur_nc = nc + ug->u.a[(w>>1)].n; + cur_nh = nh + get_path_phasing_weight(w, v, beg, b, ta); + get_related_phasing_weight(w>>1, ta, &cur_w0, &cur_w1, s->s); + cur_w0 += nw_0; cur_w1 += nw_1; + cur_ac = ac + ((s->s[w>>1] == 0)? ug->u.a[(w>>1)].n : 0); + cur_uc = uc + ((s->s[w>>1] != 0)? ug->u.a[(w>>1)].n : 0); + } + + cur_weight = cur_nh + MIN(cur_w0, cur_w1) - MAX(cur_w0, cur_w1); + min_weight = t->nh + MIN(t->w[0], t->w[1]) - MAX(t->w[0], t->w[1]); + cur_rate = ((cur_ac+cur_uc == 0)? -1 : ((double)(cur_ac)/(double)(cur_ac+cur_uc))); + max_rate = ((t->ac+t->uc == 0)? -1 : ((double)(t->ac)/(double)(t->ac+t->uc))); + + if(cur_rate > max_rate) + { + to_replace = 1; + } + else if(cur_rate == max_rate) + { + if(cur_weight < min_weight) + { + to_replace = 1; + } + else if(cur_weight == min_weight) + { + if(cur_nc > t->nc) + { + to_replace = 1; + } + else if(cur_nc == t->nc) + { + if(d + l > t->d) + { + to_replace = 1; + } + } + } + } + + + if(to_replace) + { + t->p = v; + t->nc = cur_nc; + t->nh = cur_nh; + t->ac = cur_ac; + t->uc = cur_uc; + t->w[0] = cur_w0; + t->w[1] = cur_w1; + } + + + if (d + l < t->d) t->d = d + l; // update dist + } + + if (--(t->r) == 0) { + uint32_t x = get_real_length(g, w, NULL); + if(x > 0) + { + kv_push(uint32_t, b->S, w); + } + else + { + ///at most one tip + if(n_tips != 0) goto pop_reset; + n_tips++; + tip_end = w; + } + --n_pending; + } + } + + if(n_tips == 1) + { + if(tip_end != (uint32_t)-1 && n_pending == 0 && b->S.n == 0) + { + ///sink is b.S.a[0] + kv_push(uint32_t, b->S, tip_end); + break; + } + else + { + goto pop_reset; + } + } + + if (i < nv || b->S.n == 0) goto pop_reset; + }while (b->S.n > 1 || n_pending); + + n_pop = 1; + /**need fix**/ + set_phase_path(b, beg, ta, s); + + pop_reset: + + for (i = 0; i < b->b.n; ++i) { // clear the states of visited vertices + bub_p_t *t = &b->a[b->b.a[i]]; + t->p = t->d = t->nc = t->ac = t->uc = t->r = t->s = 0; + t->nh = t->w[0] = t->w[1] = 0; + } + return n_pop; +} + +uint32_t get_weightest_node(kv_u_trans_t *ta, bubble_type* bub, ma_ug_t* ug, int8_t *s, uint8_t *vis) +{ + double w_a, w_n, max_w_a, max_w_n; + uint32_t i, occ, k, m, v, *a = NULL, a_n, e_n, max_w_a_i, max_w_n_i; + u_trans_t *e = NULL; + max_w_a = max_w_n = -1; max_w_a_i = max_w_n_i = (uint32_t)-1; + for (i = 0; i < bub->f_bub; i++) + { + get_bubbles(bub, i, NULL, NULL, &a, &a_n, NULL); + if(vis[i]) continue; + for (k = 0, w_a = w_n = 0; k < a_n; k++) + { + v = a[k]>>1; + if(s[v] != 0) break; + e = u_trans_a(*ta, v); + e_n = u_trans_n(*ta, v); + for (m = 0; m < e_n; m++) + { + if(s[e[m].tn] != 0) + { + w_a += (e[m].nw>=0?e[m].nw:-e[m].nw); + } + else + { + w_n += (e[m].nw>=0?e[m].nw:-e[m].nw); + } + } + } + + if(k >= a_n && a_n > 0)//unset whole bubble + { + if(w_a > max_w_a) + { + max_w_a_i = i<<1; + max_w_a = w_a; + } + + if(w_n > max_w_n) + { + max_w_n_i = i<<1; + max_w_n = w_n; + } + } + else + { + for (k = occ = 0; k < a_n; k++) + { + v = a[k]>>1; + if(s[v] != 0) + { + occ++; + continue; + } + + e = u_trans_a(*ta, v); + e_n = u_trans_n(*ta, v); + for (m = 0, w_a = w_n = 0; m < e_n; m++) + { + if(s[e[m].tn] != 0) + { + w_a += (e[m].nw>=0?e[m].nw:-e[m].nw); + } + else + { + w_n += (e[m].nw>=0?e[m].nw:-e[m].nw); + } + } + + if(w_a > max_w_a) + { + max_w_a_i = (v<<1)+1; + max_w_a = w_a; + } + + if(w_n > max_w_n) + { + max_w_n_i = (v<<1)+1; + max_w_n = w_n; + } + } + + if(occ == a_n) vis[i] = 1; + } + } + + for (i = 0; i < ug->g->n_seq; i++) + { + if(s[i] != 0 || (IF_BUB(i, *bub))) continue; + v = i; + e = u_trans_a(*ta, v); + e_n = u_trans_n(*ta, v); + for (m = 0, w_a = w_n = 0; m < e_n; m++) + { + if(s[e[m].tn] != 0) + { + w_a += (e[m].nw>=0?e[m].nw:-e[m].nw); + } + else + { + w_n += (e[m].nw>=0?e[m].nw:-e[m].nw); + } + } + + if(w_a > max_w_a) + { + max_w_a_i = (i<<1)+1; + max_w_a = w_a; + } + + if(w_n > max_w_n) + { + max_w_n_i = (i<<1)+1; + max_w_n = w_n; + } + } + + if(max_w_a_i != (uint32_t)-1) return max_w_a_i; + return max_w_n_i; +} + +void init_phase(ha_ug_index* idx, kv_u_trans_t *ta, bubble_type* bub, ps_t *st) +{ + double index_time = yak_realtime(); + uint8_t *vis = NULL; CALLOC(vis, idx->ug->g->n_seq); + bub_p_t_warp b; memset(&b, 0, sizeof(bub_p_t_warp)); + CALLOC(b.a, idx->ug->g->n_seq*2); + uint32_t i, k, *a = NULL, n, beg, end; + memset(st->s, 0, sizeof(int8_t)*idx->ug->g->n_seq); + + double z[2]; + u_trans_t *e = NULL; + uint32_t e_n; + while(1) + { + i = get_weightest_node(ta, bub, idx->ug, st->s, vis); + if(i == (uint32_t)-1) break; + if(i&1) + { + i>>=1; + z[0] = z[1] = 0; + e = u_trans_a(*ta, i); + e_n = u_trans_n(*ta, i); + for (k = 0; k < e_n; k++) + { + if(e[k].del) continue; + if(st->s[e[k].tn] > 0) z[0] += e[k].nw; + else if(st->s[e[k].tn] < 0) z[1] += e[k].nw; + } + if(z[0] - z[1] < 0) + { + st->s[i] = 1; + } + else if(z[0] - z[1] > 0) + { + st->s[i] = -1; + } + else + { + st->xs = kr_splitmix64(st->xs); + st->s[i] = st->xs&1? 1 : -1; + } + } + else + { + i>>=1; + get_bubbles(bub, i, &beg, &end, &a, &n, NULL); + bub_phase(idx->ug, beg, end, &b, ta, st); + bub_phase(idx->ug, beg, end, &b, ta, st); + } + } + free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); + free(vis); + + for (i = 0; i < idx->ug->g->n_seq; i++) + { + if(st->s[i] == 0) fprintf(stderr, "ERROR\n"); + if(u_trans_n(*ta, i) == 0) st->s[i] = 0; + } + + fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); +} + + +double dfs_weight_hic(uint32_t v, uint8_t* vis_flag, uint8_t* is_vis, kv_u_trans_t *ta, +kvec_t_u32_warp* stack, kvec_t_u32_warp* result, uint32_t e_flag, uint32_t ava_flag, uint32_t* link_occ) +{ + u_trans_t *e = NULL; + uint32_t cur, i, next = (uint32_t)-1, e_n; + stack->a.n = 0; + kv_push(uint32_t, stack->a, v); + double w = 0; + if(link_occ) (*link_occ) = 0; + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + if(is_vis[cur]) continue; + is_vis[cur] = 1; + if(cur!=v && vis_flag[cur] != ava_flag) continue; + e = u_trans_a(*ta, cur); e_n = u_trans_n(*ta, cur); + for (i = 0; i < e_n; i++) + { + if(e[i].del) continue; + next = e[i].tn; + if(vis_flag[next]&e_flag) + { + w += (e[i].nw >= 0? e[i].nw : -e[i].nw); + if(link_occ) (*link_occ) += e[i].occ; + continue; + } + if(is_vis[next]) continue; + if(vis_flag[next] != ava_flag) continue; + kv_push(uint32_t, stack->a, next); + } + } + return w; +} + +double get_chain_weight_hic(bubble_type* bub, ma_ug_t *bub_ug, buf_t* b, uint32_t v, uint32_t convex_source, +kv_u_trans_t *ta, uint8_t* vis_flag, uint8_t* is_vis, ma_ug_t* ug, kvec_t_u32_warp* stack, +kvec_t_u32_warp* result, uint32_t e_flag, uint32_t ava_flag, kvec_t_u32_warp* res_utg, uint32_t* link_occ) +{ + long long nodeLen, baseLen, max_stop_nodeLen, max_stop_baseLen; + ma_utg_t *u = NULL; + uint32_t convex, k, k_i, k_j, *a, n, beg, sink, uID, root, cur, ncur, n_vx = ug->g->n_seq<<1, occ; + asg_arc_t *acur = NULL; + double w = 0; + b->b.n = 0; + get_unitig(bub_ug->g, NULL, v, &convex, &nodeLen, &baseLen, &max_stop_nodeLen, + &max_stop_baseLen, 1, b); + memset(is_vis, 0, n_vx); + + for (k = 0; k < b->b.n; k++) + { + u = &(bub_ug->u.a[b->b.a[k]>>1]); + if(u->n == 0) continue; + + for (k_i = 0; k_i < u->n; k_i++) + { + get_bubbles(bub, u->a[k_i]>>33, &beg, &sink, &a, &n, NULL); + for(k_j = 0; k_j < n; k_j++) is_vis[a[k_j]] = is_vis[a[k_j]^1] = 1; + if(beg != (uint32_t)-1) is_vis[beg] = is_vis[beg^1] = 1; + if(sink != (uint32_t)-1) is_vis[sink] = is_vis[sink^1] = 1; + } + } + + u = &(bub_ug->u.a[v>>1]); + if((v&1)==0) + { + get_bubbles(bub, (u->a[0]>>32)>>1, (((u->a[0]>>32)&1)^1)==1?&root:NULL, + (((u->a[0]>>32)&1)^1) == 0?&root:NULL, NULL, NULL, NULL); + } + else + { + get_bubbles(bub, (u->a[u->n-1]>>32)>>1, ((u->a[u->n-1]>>32)&1)==1?&root:NULL, + ((u->a[u->n-1]>>32)&1) == 0?&root:NULL, NULL, NULL, NULL); + } + + root ^= 1; + is_vis[root] = 0; + stack->a.n = 0; + kv_push(uint32_t, stack->a, root); + while (stack->a.n > 0)///label all untigs not in any chain + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + if(is_vis[cur]) continue; + is_vis[cur] = 1; + if(vis_flag[cur>>1] == 0) vis_flag[cur>>1] = ava_flag;///unitig not in any chain + + ncur = asg_arc_n(ug->g, cur); + acur = asg_arc_a(ug->g, cur); + for (k = 0; k < ncur; k++) + { + if(acur[k].del) continue; + if(is_vis[acur[k].v]) continue; + if(vis_flag[acur[k].v>>1] != 0 && vis_flag[acur[k].v>>1] != ava_flag) continue; + kv_push(uint32_t, stack->a, acur[k].v); + } + } + + + ///vis_flag keeps isloated nodes + uint32_t aim_0, aim_1, root_source; + aim_0 = root>>1; + u = &(bub_ug->u.a[convex_source>>1]); + if((convex_source&1)==1) + { + get_bubbles(bub, (u->a[0]>>32)>>1, (((u->a[0]>>32)&1)^1)==1?&root_source:NULL, + (((u->a[0]>>32)&1)^1) == 0?&root_source:NULL, NULL, NULL, NULL); + } + else + { + get_bubbles(bub, (u->a[u->n-1]>>32)>>1, ((u->a[u->n-1]>>32)&1)==1?&root_source:NULL, + ((u->a[u->n-1]>>32)&1) == 0?&root_source:NULL, NULL, NULL, NULL); + } + root_source ^= 1; + aim_1 = root_source>>1; + + + cur = root_source;///scan nodes that cannot be reached from root but can be reached from root_source + ncur = asg_arc_n(ug->g, cur); + acur = asg_arc_a(ug->g, cur); + for (k_i = 0; k_i < ncur; k_i++) + { + if(acur[k_i].del) continue; + if(vis_flag[acur[k_i].v>>1] != 0) continue;///skip nodes that are already reachable + ///don't label any path that can reack other chains + if_conflict_utg(acur[k_i].v, &aim_0, &aim_1, ug, vis_flag, is_vis, ava_flag, stack); + } + + + for (k = 0; k < ug->g->n_seq; k++) + { + if(vis_flag[k] == ava_flag) + { + cur = k<<1; + ncur = asg_arc_n(ug->g, cur); + acur = asg_arc_a(ug->g, cur); + for (k_i = 0; k_i < ncur; k_i++) + { + if(acur[k_i].del) continue; + if(vis_flag[acur[k_i].v>>1] != 0) continue; + if_conflict_utg(acur[k_i].v, &aim_0, &aim_1, ug, vis_flag, is_vis, ava_flag, stack); + } + + + + cur = (k<<1)+1; + ncur = asg_arc_n(ug->g, cur); + acur = asg_arc_a(ug->g, cur); + for (k_i = 0; k_i < ncur; k_i++) + { + if(acur[k_i].del) continue; + if(vis_flag[acur[k_i].v>>1] != 0) continue; + if_conflict_utg(acur[k_i].v, &aim_0, &aim_1, ug, vis_flag, is_vis, ava_flag, stack); + } + } + } + + + + memset(is_vis, 0, n_vx); + if(link_occ) (*link_occ) = 0; + for (k = result->a.n = 0, w = 0; k < b->b.n; k++) + { + u = &(bub_ug->u.a[b->b.a[k]>>1]); + if(u->n == 0) continue; + for (k_i = 0; k_i < u->n; k_i++) + { + get_bubbles(bub, u->a[k_i]>>33, NULL, NULL, &a, &n, NULL); + + for (k_j = 0; k_j < n; k_j++) + { + uID = a[k_j]>>1; + w += dfs_weight_hic(uID, vis_flag, is_vis, ta, stack, result, e_flag, ava_flag, &occ); + if(link_occ) (*link_occ) += occ; + } + } + } + + + for (k = 0; k < ug->g->n_seq; k++) + { + if(vis_flag[k] == ava_flag) + { + vis_flag[k] = 0; + if(res_utg && (!IF_HOM(k, *bub))) + { + kv_push(uint32_t, res_utg->a, k<<1); + } + } + } + + return w; +} + + +void clean_bubble_chain_by_hic(ma_ug_t* ug, kv_u_trans_t *ta, bubble_type* bub) +{ + double index_time = yak_realtime(); + ma_ug_t *bs_ug = bub->b_ug; + uint32_t v, u, i, m, max_i, nv, rv, n_vx, root, flag_pri = 1, flag_aux = 2, flag_ava = 4, occ; + double w, cutoff = 2; + uint32_t max_w_occ = 4; + asg_arc_t *av = NULL; + n_vx = bs_ug->g->n_seq << 1; + uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq<<1); + uint8_t *is_vis = NULL; CALLOC(is_vis, ug->g->n_seq<<1); + uint8_t *is_used = NULL; CALLOC(is_used, n_vx); + uint8_t *dedup = NULL; CALLOC(dedup, ug->g->n_seq<<1); + buf_t b; memset(&b, 0, sizeof(buf_t)); + kvec_t_u32_warp stack, result, res_utg; + kv_init(stack.a); kv_init(result.a); kv_init(res_utg.a); + double *e_w = NULL; MALLOC(e_w, bs_ug->g->n_arc); + uint32_t *e_occ = NULL, *a_occ = NULL; CALLOC(e_occ, bs_ug->g->n_arc); + double *aw = NULL, max_w = 0; + kvec_asg_arc_t_warp edges; kv_init(edges.a); + ma_ug_t *back_bs_ug = copy_untig_graph(bs_ug); + + for (i = 0; i < bs_ug->g->n_arc; i++)///weight of bs_ug's edges + { + e_w[i] = -1; + } + + for (i = 0; i < bs_ug->g->n_seq; i++)///init all chain with flag_aux + { + set_b_utg_weight_flag(bub, &b, i<<1, vis, flag_aux, NULL); + } + + + for (v = 0; v < n_vx; v++) + { + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + aw = (&e_w[bs_ug->g->idx[v]>>32]); + a_occ = (&e_occ[bs_ug->g->idx[v]>>32]); + if(nv <= 1 || get_real_length(bs_ug->g, v, NULL) <= 1) continue; + set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); + + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + w = get_chain_weight_hic(bub, bs_ug, &b, av[i].v, v, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, NULL, &occ); + aw[i] = w; + a_occ[i] = occ; + } + + set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); + } + + + for (v = 0; v < n_vx; v++) + { + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + aw = (&e_w[bs_ug->g->idx[v]>>32]); + a_occ = (&e_occ[bs_ug->g->idx[v]>>32]); + if(nv <= 1 || get_real_length(bs_ug->g, v, NULL) <= 1) continue; + + for (i = rv = 0, max_i = (uint32_t)-1; i < nv; i++) + { + if(av[i].del) continue; + if(max_i == (uint32_t)-1) + { + max_i = i; + max_w = aw[i]; + } + else if(max_w < aw[i]) + { + max_i = i; + max_w = aw[i]; + } + rv++; + } + + if(max_i == (uint32_t)-1) continue; + ///if(max_w <= max_w_cutoff) continue; //must be <= + if(a_occ[max_i] <= max_w_occ) continue; //must be <= + if(rv < 2) continue; + + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + if(i == max_i) continue; + ///if((av[i].v>>1) == (v>>1) && aw[i] <= max_w_cutoff) continue; ///might be not reasonable + if((av[i].v>>1) == (v>>1) && a_occ[i] <= max_w_occ) continue; ///might be not reasonable + if(aw[i]*cutoff < max_w && double_check_bub_branch(&av[i], bs_ug, e_w, e_occ, cutoff, max_w_occ)) + { + av[i].del = 1; asg_arc_del(bs_ug->g, (av[i].v)^1, (av[i].ul>>32)^1, 1); + } + } + } + + uint32_t rId_0, ori_0, rId_1, ori_1, root_0, root_1, new_bub; + if(bub->num.n > 0) bub->num.n--; + new_bub = bub->b_g->n_seq; + + for (v = 0; v < n_vx; v++) + { + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + rv = get_real_length(bs_ug->g, v, NULL); + if(nv == rv) continue;///no edge drop + if(rv != 1 || nv <= 1) continue; + get_real_length(bs_ug->g, v, &u); + u ^= 1; + if(get_real_length(bs_ug->g, u, NULL) != 1) continue; + drop_g_edges_by_utg(bub, bub->b_g, bs_ug, NULL, v, u); + if(is_used[v] || is_used[u]) continue; + + is_used[v] = is_used[u] = 1; + root = get_utg_end_from_btg(bub, bs_ug, v); + rId_0 = root>>1; + ori_0 = root&1; + get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); + + root = get_utg_end_from_btg(bub, bs_ug, u); + rId_1 = root>>1; + ori_1 = root&1; + get_bubbles(bub, rId_1, ori_1 == 1?&root_1:NULL, ori_1 == 0?&root_1:NULL, NULL, NULL, NULL); + + res_utg.a.n = 0; + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); + get_chain_weight_hic(bub, back_bs_ug, &b, u^1, v, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); + for (i = 0; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 1; + + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); + get_chain_weight_hic(bub, back_bs_ug, &b, v^1, u, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); + for (; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 2; + + for (i = m = 0; i < res_utg.a.n; i++) + { + if(dedup[res_utg.a.a[i]>>1] == 3) + { + res_utg.a.a[m] = res_utg.a.a[i]; + m++; + } + dedup[res_utg.a.a[i]>>1] = 0; + } + res_utg.a.n = m; + + if(!IF_HOM(root_0>>1, *bub)) kv_push(uint32_t, res_utg.a, root_0); + if(!IF_HOM(root_1>>1, *bub)) kv_push(uint32_t, res_utg.a, root_1); + + update_bubble_graph(&res_utg, root_0^1, rId_0, root_1^1, rId_1, bub, &edges, bub->b_g, NULL, NULL, ug, NULL, 0); + + ///fprintf(stderr, "\n******src-btg%.6ul------>dest-btg%.6ul\n", (v>>1)+1, (u>>1)+1); + } + + kv_push(uint32_t, bub->num, bub->list.n); + new_bub = bub->b_g->n_seq - new_bub; + bub->cross_bub += new_bub; + ///actually not useful, and may have bug when one bubble at multipe chains + if(new_bub) update_bub_b_s_idx(bub); + + ///debug_tangle_bubble(bub, bub->b_g->n_seq - bub->cross_bub, bub->b_g->n_seq - 1, "Cross-tangle"); + update_bsg(bub->b_g, &edges); + + ma_ug_destroy(bs_ug); + bs_ug = ma_ug_gen(bub->b_g); + bub->b_ug = bs_ug; + kv_destroy(bub->chain_weight); + ma_utg_t *u_x = NULL; + bs_ug = bub->b_ug; + kv_malloc(bub->chain_weight, bs_ug->u.n); bub->chain_weight.n = bs_ug->u.n; + for (i = 0; i < bs_ug->u.n; i++) + { + u_x = &(bs_ug->u.a[i]); + bub->chain_weight.a[i].id = i; + // if(u->n <= 1) ///not a chain + // { + // bub->chain_weight.a[i].b_occ = bub->chain_weight.a[i].g_occ = 0; + // bub->chain_weight.a[i].del = 1; + // } + // else + { + bub->chain_weight.a[i].del = 0; + calculate_chain_weight(u_x, bub, ug, &(bub->chain_weight.a[i])); + } + } + qsort(bub->chain_weight.a, bub->chain_weight.n, sizeof(chain_w_type), cmp_chain_weight); + + + + free(vis); free(is_vis); free(is_used); free(dedup); free(b.b.a); free(e_w); free(e_occ); + kv_destroy(stack.a); kv_destroy(result.a); kv_destroy(res_utg.a); kv_destroy(edges.a); + ma_ug_destroy(back_bs_ug); + fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); +} + +void clean_sub_tangle(bubble_type* bub, uint8_t* vis_flag, kvec_t_u32_warp *res_utg, +uint8_t *dedup, uint8_t *is_tangle, kvec_asg_arc_t_warp* edges, uint32_t flag, uint32_t s, +uint32_t e) +{ + uint32_t i, k_i, pv, v, occ, beg, sink, p_beg, p_sink, n, *a = NULL; + ma_utg_t *u = NULL; + + for (i = 0, pv = (uint32_t)-1; i < res_utg->a.n; i++) + { + if(is_tangle[res_utg->a.a[i]>>1] == 1) + { + if(pv == (uint32_t)-1) + { + pv = res_utg->a.a[i]>>1; + } + else if(pv != (res_utg->a.a[i]>>1)) + { + pv = (uint32_t)-1; + break; + } + } + else if(is_tangle[res_utg->a.a[i]>>1] == (uint8_t)-1) + { + pv = (uint32_t)-1; + break; + } + } + + if(pv == (uint32_t)-1) + { + for (i = 0; i < res_utg->a.n; i++) + { + is_tangle[res_utg->a.a[i]>>1] = (uint8_t)-1; + } + return; + } + + occ = 0; + u = &(bub->b_ug->u.a[s]); + for (i = 0, p_beg = p_sink = (uint32_t)-1; i < u->n; i++) + { + get_bubbles(bub, u->a[i]>>33, &beg, &sink, &a, &n, NULL); + + for (k_i = 0; k_i < n; k_i++) + { + occ += bub->ug->u.a[a[k_i]>>1].n; + } + if(beg != (uint32_t)-1 && (beg>>1) != (p_beg>>1) && (beg>>1) != (p_sink>>1)) + { + occ += bub->ug->u.a[beg>>1].n; + } + if(sink != (uint32_t)-1 && (sink>>1) != (p_beg>>1) && (sink>>1) != (p_sink>>1)) + { + occ += bub->ug->u.a[sink>>1].n; + } + p_beg = beg; p_sink = sink; + } + + u = &(bub->b_ug->u.a[e]); + for (i = 0, p_beg = p_sink = (uint32_t)-1; i < u->n; i++) + { + get_bubbles(bub, u->a[i]>>33, &beg, &sink, &a, &n, NULL); + + for (k_i = 0; k_i < n; k_i++) + { + occ += bub->ug->u.a[a[k_i]>>1].n; + } + if(beg != (uint32_t)-1 && (beg>>1) != (p_beg>>1) && (beg>>1) != (p_sink>>1)) + { + occ += bub->ug->u.a[beg>>1].n; + } + if(sink != (uint32_t)-1 && (sink>>1) != (p_beg>>1) && (sink>>1) != (p_sink>>1)) + { + occ += bub->ug->u.a[sink>>1].n; + } + p_beg = beg; p_sink = sink; + } + + if(occ <= bub->ug->u.a[pv].n*200) + { + for (i = 0; i < res_utg->a.n; i++) + { + is_tangle[res_utg->a.a[i]>>1] = (uint8_t)-1; + } + return; + } + + if(!edges) return; + + u = &(bub->b_ug->u.a[s]); + for (i = 0; i < u->n; i++) + { + get_bubbles(bub, u->a[i]>>33, &beg, &sink, &a, &n, NULL); + + for (k_i = 0; k_i < n; k_i++) + { + vis_flag[a[k_i]>>1] ^= flag; + } + if(beg != (uint32_t)-1) + { + vis_flag[beg>>1] ^= flag; + } + if(sink != (uint32_t)-1) + { + vis_flag[sink>>1] ^= flag; + } + } + u = &(bub->b_ug->u.a[e]); + for (i = 0; i < u->n; i++) + { + get_bubbles(bub, u->a[i]>>33, &beg, &sink, &a, &n, NULL); + + for (k_i = 0; k_i < n; k_i++) + { + vis_flag[a[k_i]>>1] ^= flag; + } + if(beg != (uint32_t)-1) + { + vis_flag[beg>>1] ^= flag; + } + if(sink != (uint32_t)-1) + { + vis_flag[sink>>1] ^= flag; + } + } + for (i = 0; i < res_utg->a.n; i++) + { + if(dedup[res_utg->a.a[i]>>1] == 3) + { + vis_flag[res_utg->a.a[i]>>1] ^= flag; + } + } + + + + asg_arc_t *av = NULL, *p = NULL; + uint32_t nv, c[2]; + + c[0] = c[1] = 0; + while (1) + { + c[0] = c[1] = 0; p = NULL; + v = pv<<1; + av = asg_arc_a(bub->ug->g, v); + nv = asg_arc_n(bub->ug->g, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + c[(!!(vis_flag[av[i].v>>1]&flag))]++; + if(p == NULL || p->ol > av[i].ol) + { + p = &(av[i]); + } + } + + + + + v = (pv<<1) + 1; + av = asg_arc_a(bub->ug->g, v); + nv = asg_arc_n(bub->ug->g, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + c[(!!(vis_flag[av[i].v>>1]&flag))]++; + if(p == NULL || p->ol > av[i].ol) + { + p = &(av[i]); + } + } + + if(p) + { + p->del = 1; + c[(!!(vis_flag[p->v>>1]&flag))]--; + if((p->v>>1) == pv) + { + asg_arc_del(bub->ug->g, (p->v)^1, (p->ul>>32)^1, 1); + c[0] = c[1] = 0; + v = pv<<1; + av = asg_arc_a(bub->ug->g, v); + nv = asg_arc_n(bub->ug->g, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + c[(!!(vis_flag[av[i].v>>1]&flag))]++; + } + + v = (pv<<1) + 1; + av = asg_arc_a(bub->ug->g, v); + nv = asg_arc_n(bub->ug->g, v); + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + c[(!!(vis_flag[av[i].v>>1]&flag))]++; + } + } + + + } + if(c[0] == 0 || c[1] == 0) break; + } + + + + + v = pv<<1; + av = asg_arc_a(bub->ug->g, v); + nv = asg_arc_n(bub->ug->g, v); + for (i = 0; i < nv; i++) + { + if(!av[i].del) continue; + av[i].del = 0; + kv_push(asg_arc_t, edges->a, av[i]); + } + + + v = (pv<<1) + 1; + av = asg_arc_a(bub->ug->g, v); + nv = asg_arc_n(bub->ug->g, v); + for (i = 0; i < nv; i++) + { + if(!av[i].del) continue; + av[i].del = 0; + kv_push(asg_arc_t, edges->a, av[i]); + } + + is_tangle[pv] = (uint8_t)-1; + + + u = &(bub->b_ug->u.a[s]); + for (i = 0; i < u->n; i++) + { + get_bubbles(bub, u->a[i]>>33, &beg, &sink, &a, &n, NULL); + + for (k_i = 0; k_i < n; k_i++) + { + vis_flag[a[k_i]>>1] ^= flag; + } + if(beg != (uint32_t)-1) + { + vis_flag[beg>>1] ^= flag; + } + if(sink != (uint32_t)-1) + { + vis_flag[sink>>1] ^= flag; + } + } + u = &(bub->b_ug->u.a[e]); + for (i = 0; i < u->n; i++) + { + get_bubbles(bub, u->a[i]>>33, &beg, &sink, &a, &n, NULL); + + for (k_i = 0; k_i < n; k_i++) + { + vis_flag[a[k_i]>>1] ^= flag; + } + if(beg != (uint32_t)-1) + { + vis_flag[beg>>1] ^= flag; + } + if(sink != (uint32_t)-1) + { + vis_flag[sink>>1] ^= flag; + } + } + for (i = 0; i < res_utg->a.n; i++) + { + if(dedup[res_utg->a.a[i]>>1] == 3) + { + vis_flag[res_utg->a.a[i]>>1] ^= flag; + } + } + + +} + +void delete_sg_e_by_ug(asg_t* rg, ma_ug_t* ug, uint32_t v, uint32_t w) +{ + uint32_t vx, wx; + 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_del(rg, vx, wx, 1); asg_arc_del(rg, wx^1, vx^1, 1); +} + +void resolve_bubble_chain_by_hic(ha_ug_index *idx, kv_u_trans_t *ta, bubble_type* bub) +{ + // double index_time = yak_realtime(); + ma_ug_t* ug = idx->ug; + ma_ug_t *bs_ug = bub->b_ug; + uint32_t v, u, i, max_i, nv, rv, n_vx, root, flag_pri = 1, flag_aux = 2, flag_ava = 4, occ; + double w, cutoff = 2; + uint32_t max_w_occ = 4; + asg_arc_t *av = NULL; + n_vx = bs_ug->g->n_seq << 1; + uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq<<1); + uint8_t *is_vis = NULL; CALLOC(is_vis, ug->g->n_seq<<1); + uint8_t *is_used = NULL; CALLOC(is_used, n_vx); + uint8_t *dedup = NULL; CALLOC(dedup, ug->g->n_seq<<1); + uint8_t *is_tangle = NULL; CALLOC(is_tangle, ug->g->n_seq); + buf_t b; memset(&b, 0, sizeof(buf_t)); + kvec_t_u32_warp stack, result, res_utg; + kv_init(stack.a); kv_init(result.a); kv_init(res_utg.a); + double *e_w = NULL; MALLOC(e_w, bs_ug->g->n_arc); + uint32_t *e_occ = NULL, *a_occ = NULL; CALLOC(e_occ, bs_ug->g->n_arc); + double *aw = NULL, max_w = 0; + kvec_asg_arc_t_warp edges; kv_init(edges.a); + ma_ug_t *back_bs_ug = copy_untig_graph(bs_ug); + + for (i = 0; i < bs_ug->g->n_arc; i++)///weight of bs_ug's edges + { + e_w[i] = -1; + } + + for (i = 0; i < bs_ug->g->n_seq; i++)///init all chain with flag_aux + { + set_b_utg_weight_flag(bub, &b, i<<1, vis, flag_aux, NULL); + } + + + for (v = 0; v < n_vx; v++) + { + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + aw = (&e_w[bs_ug->g->idx[v]>>32]); + a_occ = (&e_occ[bs_ug->g->idx[v]>>32]); + if(nv <= 1 || get_real_length(bs_ug->g, v, NULL) <= 1) continue; + set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); + + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + w = get_chain_weight_hic(bub, bs_ug, &b, av[i].v, v, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, NULL, &occ); + aw[i] = w; + a_occ[i] = occ; + } + + set_b_utg_weight_flag_xor(bub, bs_ug, &b, v^1, vis, flag_pri, NULL); + } + + + for (v = 0; v < n_vx; v++) + { + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + aw = (&e_w[bs_ug->g->idx[v]>>32]); + a_occ = (&e_occ[bs_ug->g->idx[v]>>32]); + if(nv <= 1 || get_real_length(bs_ug->g, v, NULL) <= 1) continue; + + for (i = rv = 0, max_i = (uint32_t)-1; i < nv; i++) + { + if(av[i].del) continue; + if(max_i == (uint32_t)-1) + { + max_i = i; + max_w = aw[i]; + } + else if(max_w < aw[i]) + { + max_i = i; + max_w = aw[i]; + } + rv++; + } + + if(max_i == (uint32_t)-1) continue; + ///if(max_w <= max_w_cutoff) continue; //must be <= + if(a_occ[max_i] <= max_w_occ) continue; //must be <= + if(rv < 2) continue; + + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + if(i == max_i) continue; + ///if((av[i].v>>1) == (v>>1) && aw[i] <= max_w_cutoff) continue; ///might be not reasonable + if((av[i].v>>1) == (v>>1) && a_occ[i] <= max_w_occ) continue; ///might be not reasonable + if(aw[i]*cutoff < max_w && double_check_bub_branch(&av[i], bs_ug, e_w, e_occ, cutoff, max_w_occ)) + { + av[i].del = 1; asg_arc_del(bs_ug->g, (av[i].v)^1, (av[i].ul>>32)^1, 1); + } + } + } + + uint32_t rId_0, ori_0, rId_1, ori_1, root_0, root_1; + for (v = 0; v < n_vx; v++) + { + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + rv = get_real_length(bs_ug->g, v, NULL); + if(nv == rv) continue;///no edge drop + if(rv != 1 || nv <= 1) continue; + get_real_length(bs_ug->g, v, &u); + u ^= 1; + if(get_real_length(bs_ug->g, u, NULL) != 1) continue; + drop_g_edges_by_utg(bub, bub->b_g, bs_ug, NULL, v, u); + if(is_used[v] || is_used[u]) continue; + + is_used[v] = is_used[u] = 1; + root = get_utg_end_from_btg(bub, bs_ug, v); + rId_0 = root>>1; + ori_0 = root&1; + get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); + + root = get_utg_end_from_btg(bub, bs_ug, u); + rId_1 = root>>1; + ori_1 = root&1; + get_bubbles(bub, rId_1, ori_1 == 1?&root_1:NULL, ori_1 == 0?&root_1:NULL, NULL, NULL, NULL); + + res_utg.a.n = 0; + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); + get_chain_weight_hic(bub, back_bs_ug, &b, u^1, v, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); + for (i = 0; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 1; + + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); + get_chain_weight_hic(bub, back_bs_ug, &b, v^1, u, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); + for (; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 2; + + for (i = 0; i < res_utg.a.n; i++) + { + if(dedup[res_utg.a.a[i]>>1] == 3) + { + is_tangle[res_utg.a.a[i]>>1] = 3; + } + else + { + if(is_tangle[res_utg.a.a[i]>>1] != 3) + { + is_tangle[res_utg.a.a[i]>>1] = 1; + } + } + dedup[res_utg.a.a[i]>>1] = 0; + } + } + + /*******************************for debug************************************/ + // for (i = 0; i < ug->g->n_seq; i++) + // { + // if(is_tangle[i] == 1) + // { + // fprintf(stderr, "*****tangle-utg%.6ul\n", i+1); + // } + // } + /*******************************for debug************************************/ + memset(is_used, 0, n_vx); + for (v = 0; v < n_vx; v++) + { + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + rv = get_real_length(bs_ug->g, v, NULL); + if(nv == rv) continue;///no edge drop + if(rv != 1 || nv <= 1) continue; + get_real_length(bs_ug->g, v, &u); + u ^= 1; + if(get_real_length(bs_ug->g, u, NULL) != 1) continue; + drop_g_edges_by_utg(bub, bub->b_g, bs_ug, NULL, v, u); + if(is_used[v] || is_used[u]) continue; + + is_used[v] = is_used[u] = 1; + root = get_utg_end_from_btg(bub, bs_ug, v); + rId_0 = root>>1; + ori_0 = root&1; + get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); + + root = get_utg_end_from_btg(bub, bs_ug, u); + rId_1 = root>>1; + ori_1 = root&1; + get_bubbles(bub, rId_1, ori_1 == 1?&root_1:NULL, ori_1 == 0?&root_1:NULL, NULL, NULL, NULL); + + res_utg.a.n = 0; + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); + get_chain_weight_hic(bub, back_bs_ug, &b, u^1, v, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); + for (i = 0; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 1; + + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); + get_chain_weight_hic(bub, back_bs_ug, &b, v^1, u, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); + for (; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 2; + + + /*******************************for debug************************************/ + // fprintf(stderr, "\nres_utg.a.n: %u, beg-utg%.6ul, sink-utg%.6ul\n", + // (uint32_t)res_utg.a.n, (root_0>>1)+1, (root_1>>1)+1); + // for (i = 0; i < res_utg.a.n; i++) + // { + // if(dedup[res_utg.a.a[i]>>1] == 3) + // { + // fprintf(stderr, "share-utg%.6ul\n", (res_utg.a.a[i]>>1)+1); + // } + // } + // for (i = 0; i < res_utg.a.n; i++) + // { + // if(dedup[res_utg.a.a[i]>>1] == 1) + // { + // fprintf(stderr, "1-utg%.6ul\n", (res_utg.a.a[i]>>1)+1); + // } + // } + // for (i = 0; i < res_utg.a.n; i++) + // { + // if(dedup[res_utg.a.a[i]>>1] == 2) + // { + // fprintf(stderr, "2-utg%.6ul\n", (res_utg.a.a[i]>>1)+1); + // } + // } + /*******************************for debug************************************/ + + clean_sub_tangle(bub, vis, &res_utg, dedup, is_tangle, NULL, flag_pri, v>>1, u>>1); + + for (i = 0; i < res_utg.a.n; i++) + { + dedup[res_utg.a.a[i]>>1] = 0; + } + } + + + edges.a.n = 0; + memset(is_used, 0, n_vx); + for (v = 0; v < n_vx; v++) + { + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + rv = get_real_length(bs_ug->g, v, NULL); + if(nv == rv) continue;///no edge drop + if(rv != 1 || nv <= 1) continue; + get_real_length(bs_ug->g, v, &u); + u ^= 1; + if(get_real_length(bs_ug->g, u, NULL) != 1) continue; + drop_g_edges_by_utg(bub, bub->b_g, bs_ug, NULL, v, u); + if(is_used[v] || is_used[u]) continue; + + is_used[v] = is_used[u] = 1; + root = get_utg_end_from_btg(bub, bs_ug, v); + rId_0 = root>>1; + ori_0 = root&1; + get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); + + root = get_utg_end_from_btg(bub, bs_ug, u); + rId_1 = root>>1; + ori_1 = root&1; + get_bubbles(bub, rId_1, ori_1 == 1?&root_1:NULL, ori_1 == 0?&root_1:NULL, NULL, NULL, NULL); + + res_utg.a.n = 0; + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); + get_chain_weight_hic(bub, back_bs_ug, &b, u^1, v, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, v^1, vis, flag_pri, NULL); + for (i = 0; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 1; + + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); + get_chain_weight_hic(bub, back_bs_ug, &b, v^1, u, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); + set_b_utg_weight_flag_xor(bub, back_bs_ug, &b, u^1, vis, flag_pri, NULL); + for (; i < res_utg.a.n; i++) dedup[res_utg.a.a[i]>>1] |= 2; + + clean_sub_tangle(bub, vis, &res_utg, dedup, is_tangle, &edges, flag_pri, v>>1, u>>1); + + for (i = 0; i < res_utg.a.n; i++) + { + dedup[res_utg.a.a[i]>>1] = 0; + } + } + + + /*******************************for debug************************************/ + // for (i = 0; i < ug->g->n_seq; i++) + // { + // if(is_tangle[i] == 1) + // { + // fprintf(stderr, "####tangle-utg%.6ul\n", i+1); + // } + // } + + // for (i = 0; i < edges.a.n; i++) + // { + // fprintf(stderr, "s-utg%.6lul<------>d-utg%.6ul\n", (edges.a.a[i].ul>>33) + 1, (edges.a.a[i].v>>1) + 1); + + // } + /*******************************for debug************************************/ + if(edges.a.n > 0) + { + for (i = 0; i < edges.a.n; i++) + { + asg_arc_del(bub->ug->g, edges.a.a[i].ul>>32, edges.a.a[i].v, 1); + asg_arc_del(bub->ug->g, (edges.a.a[i].v)^1, (edges.a.a[i].ul>>32)^1, 1); + delete_sg_e_by_ug(idx->read_g, idx->ug, edges.a.a[i].ul>>32, edges.a.a[i].v); + delete_sg_e_by_ug(idx->read_g, idx->ug, (edges.a.a[i].v)^1, (edges.a.a[i].ul>>32)^1); + } + asg_cleanup(bub->ug->g); + asg_cleanup(idx->read_g); + } + + + free(vis); free(is_vis); free(is_used); free(dedup); free(b.b.a); free(e_w); free(e_occ); free(is_tangle); + kv_destroy(stack.a); kv_destroy(result.a); kv_destroy(res_utg.a); kv_destroy(edges.a); + ma_ug_destroy(back_bs_ug); + // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); +} + +void append_boundary_chain_hic(ma_ug_t* ug, kv_u_trans_t *ta, bubble_type* bub) +{ + // double index_time = yak_realtime(); + ma_ug_t *bs_ug = bub->b_ug; + uint32_t v, u, i, k, beg_idx, m, nv, n_vx, flag_pri = 1, flag_aux = 2, flag_ava = 4; + uint32_t root, rId_0, ori_0, root_0, new_bub; + asg_arc_t *av = NULL; + n_vx = bs_ug->g->n_seq << 1; + uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq<<1); + uint8_t *is_vis = NULL; CALLOC(is_vis, ug->g->n_seq<<1); + uint8_t *is_used = NULL; CALLOC(is_used, n_vx); + uint8_t *dedup = NULL; CALLOC(dedup, ug->g->n_seq<<1); + buf_t b; memset(&b, 0, sizeof(buf_t)); + kvec_t_u32_warp stack, result, res_utg; + kv_init(stack.a); kv_init(result.a); kv_init(res_utg.a); + kvec_asg_arc_t_warp edges; kv_init(edges.a); + + for (i = 0; i < bs_ug->g->n_seq; i++) + { + set_b_utg_weight_flag(bub, &b, i<<1, vis, flag_aux, NULL); + } + + if(bub->num.n > 0) bub->num.n--; + new_bub = bub->b_g->n_seq; + for (v = 0; v < n_vx; v++) + { + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + if(nv == 0 || get_real_length(bs_ug->g, v, NULL) == 0) continue; + res_utg.a.n = 0; + for (i = 0; i < nv; i++) + { + if(av[i].del) continue; + u = av[i].v^1; + beg_idx = res_utg.a.n; + set_b_utg_weight_flag_xor(bub, bs_ug, &b, u^1, vis, flag_pri, NULL); + get_chain_weight_hic(bub, bs_ug, &b, v^1, u, ta, vis, is_vis, ug, &stack, &result, flag_pri, flag_ava, &res_utg, NULL); + set_b_utg_weight_flag_xor(bub, bs_ug, &b, u^1, vis, flag_pri, NULL); + for (k = m = beg_idx; k < res_utg.a.n; k++) + { + if(dedup[res_utg.a.a[k]>>1] != 0) continue; + dedup[res_utg.a.a[k]>>1] = 1; + res_utg.a.a[m] = res_utg.a.a[k]; + m++; + } + res_utg.a.n = m; + } + + for (k = 0; k < res_utg.a.n; k++) dedup[res_utg.a.a[k]>>1] = 0; + + root = get_utg_end_from_btg(bub, bs_ug, v); + rId_0 = root>>1; + ori_0 = root&1; + get_bubbles(bub, rId_0, ori_0 == 1?&root_0:NULL, ori_0 == 0?&root_0:NULL, NULL, NULL, NULL); + + if(root_0 != (uint32_t)-1 && (!IF_HOM(root_0>>1, *bub))) kv_push(uint32_t, res_utg.a, root_0); + + if(v&1) + { + update_bubble_graph(&res_utg, root_0^1, rId_0, (uint32_t)-1, (uint32_t)-1, bub, &edges, bub->b_g, NULL, NULL, ug, NULL, 0); + } + else + { + update_bubble_graph(&res_utg, (uint32_t)-1, (uint32_t)-1, root_0^1, rId_0, bub, &edges, bub->b_g, NULL, NULL, ug, NULL, 0); + } + } + kv_push(uint32_t, bub->num, bub->list.n); + new_bub = bub->b_g->n_seq - new_bub; + bub->mess_bub += new_bub; + ///actually not useful, and may have bug when one bubble at multipe chains + if(new_bub) update_bub_b_s_idx(bub); + + + for (v = 0; v < n_vx; v++) + { + av = asg_arc_a(bs_ug->g, v); + nv = asg_arc_n(bs_ug->g, v); + if(nv == 0 || get_real_length(bs_ug->g, v, NULL) == 0) continue; + drop_g_edges_by_utg(bub, bub->b_g, bs_ug, NULL, v, (uint32_t)-1); + } + + update_bsg(bub->b_g, &edges); + + ma_ug_destroy(bs_ug); + bs_ug = ma_ug_gen(bub->b_g); + bub->b_ug = bs_ug; + kv_destroy(bub->chain_weight); + ma_utg_t *u_x = NULL; + bs_ug = bub->b_ug; + kv_malloc(bub->chain_weight, bs_ug->u.n); bub->chain_weight.n = bs_ug->u.n; + for (i = 0; i < bs_ug->u.n; i++) + { + u_x = &(bs_ug->u.a[i]); + bub->chain_weight.a[i].id = i; + // if(u->n <= 1) ///not a chain + // { + // bub->chain_weight.a[i].b_occ = bub->chain_weight.a[i].g_occ = 0; + // bub->chain_weight.a[i].del = 1; + // } + // else + { + bub->chain_weight.a[i].del = 0; + calculate_chain_weight(u_x, bub, ug, &(bub->chain_weight.a[i])); + } + } + qsort(bub->chain_weight.a, bub->chain_weight.n, sizeof(chain_w_type), cmp_chain_weight); + + + + free(vis); free(is_vis); free(is_used); free(dedup); free(b.b.a); + kv_destroy(stack.a); kv_destroy(result.a); kv_destroy(res_utg.a); + kv_destroy(edges.a); + // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); +} + +double get_specific_hic_weight_by_chain(uint32_t uid, kv_u_trans_t *ta, uint8_t* vis, uint8_t flag) +{ + u_trans_t *e = u_trans_a(*ta, uid); + uint64_t k, e_n = u_trans_n(*ta, uid); + double w = 0; + + for (k = 0; k < e_n; k++) + { + if(e[k].del) continue; + if(vis[e[k].tn] != flag) continue; + w += (e[k].nw>=0?e[k].nw:-e[k].nw); + } + return w; +} + +void update_bubble_weight(bub_sort_vec* w_stack, uint32_t idx, kv_u_trans_t *ta, uint8_t* vis, uint32_t flag_cur) +{ + w_stack->a[idx].used = 1; + uint32_t k, m, uid = w_stack->a[idx].p_id>>1; + u_trans_t *e = u_trans_a(*ta, uid); + uint32_t e_n = u_trans_n(*ta, uid); + for (k = 0; k < e_n; k++) + { + if(e[k].del) continue; + if(vis[e[k].tn] != flag_cur) continue; + for (m = 0; m < w_stack->n; m++) + { + if(e[k].tn == (w_stack->a[m].p_id>>1)) break; + } + if(m >= w_stack->n) continue; + if(w_stack->a[m].used) continue; + w_stack->a[m].weight += (e[k].nw>=0?e[k].nw:-e[k].nw); + } +} + +void reorder_bubbble_chain(kv_u_trans_t *ta, bubble_type* bub, bub_sort_vec* w_stack, +uint8_t* vis, uint32_t n_utg, uint32_t chain_id) +{ + uint32_t i, k, m, max_idx, flag_cur = 3, flag_right = 2, flag_left = 1, flag_unset = 0, *a, n; + uint64_t bid, uid; + ma_utg_t *u = &(bub->b_ug->u.a[chain_id]); + memset(vis, flag_unset, n_utg); + for (i = 0; i < u->n; i++) + { + bid = u->a[i]>>33; + get_bubbles(bub, bid, NULL, NULL, &a, &n, NULL); + for (k = 0; k < n; k++) + { + uid = a[k]>>1; + vis[uid] = flag_right; + } + } + + for (i = 0; i < u->n; i++) + { + w_stack->n = 0; + bid = u->a[i]>>33; + get_bubbles(bub, bid, NULL, NULL, &a, &n, NULL); + kv_resize(bub_sort_type, *w_stack, n); + w_stack->n = n; + for (k = 0; k < n; k++) + { + uid = a[k]>>1; + vis[uid] = flag_cur; + w_stack->a[k].p_id = a[k]; + w_stack->a[k].weight = 0; + w_stack->a[k].used = 0; + } + + for (k = 0; k < w_stack->n; k++) + { + w_stack->a[k].weight += get_specific_hic_weight_by_chain(w_stack->a[k].p_id>>1, + ta, vis, flag_left); + w_stack->a[k].weight -= get_specific_hic_weight_by_chain(w_stack->a[k].p_id>>1, + ta, vis, flag_right); + } + m = 0; + while ((max_idx = get_max_hap_g(w_stack, NULL)) != (uint32_t)-1) + { + a[m] = w_stack->a[max_idx].p_id; + m++; + update_bubble_weight(w_stack, max_idx, ta, vis, flag_cur); + } + + while ((max_idx = get_max_hap_g(w_stack, &max_idx)) != (uint32_t)-1) + { + a[m] = w_stack->a[max_idx].p_id; + m++; + update_bubble_weight(w_stack, max_idx, ta, vis, flag_cur); + } + if(m != n) fprintf(stderr, "ERROR\n"); + + + for (k = 0; k < n; k++) + { + uid = a[k]>>1; + vis[uid] = flag_left; + } + } +} + +void reorder_bubbles(bubble_type* bub, kv_u_trans_t *ta, uint32_t n_utg) +{ + // double index_time = yak_realtime(); + uint8_t* vis = NULL; MALLOC(vis, n_utg); + bub_sort_vec w_stack; kv_init(w_stack); + uint32_t i; + + for (i = 0; i < bub->chain_weight.n; i++) + { + if(bub->chain_weight.a[i].del) continue; + reorder_bubbble_chain(ta, bub, &w_stack, vis, n_utg, bub->chain_weight.a[i].id); + } + + free(vis); kv_destroy(w_stack); + // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); +} + +void update_trans_g(ha_ug_index* idx, kv_u_trans_t *ta, bubble_type* bub) +{ + // double index_time = yak_realtime(); + // update_bubble_chain(idx->ug, bub, 0, 1); + + // resolve_bubble_chain_tangle(idx->ug, bub); + + clean_bubble_chain_by_hic(idx->ug, ta, bub); + + // print_debug_bubble_graph(bub, idx->ug, "bub-2"); + + // append_boundary_chain_hic(idx->ug, ta, bub); + + // fprintf(stderr, "s_bub: %lu, f_bub: %lu, b_bub: %lu, b_end_bub: %lu, tangle_bub: %lu, cross_bub: %lu, mess_bub: %lu\n", + // bub->s_bub, bub->f_bub, bub->b_bub, bub->b_end_bub, bub->tangle_bub, bub->cross_bub, bub->mess_bub); + + ///reorder_bubbles(bub, ta, idx->ug->g->n_seq); + // fprintf(stderr, "[M::%s::%.3f]\n", __func__, yak_realtime()-index_time); +} + +uint32_t get_max_unitig(H_partition* h, G_partition* g_p, hc_links* link, bubble_type* bub) +{ + double min, weight; + uint32_t i, min_i; + + for (i = 0, min = 1, min_i = (uint32_t)-1; i < g_p->n; i++) + { + if(h->lock[i]) continue; + weight = 0; + if(g_p->a[i].h[0] > 0 && (g_p->a[i].status[0] == 1 || g_p->a[i].status[0] == -1)) + { + weight += (g_p->a[i].weight[0] * g_p->a[i].status[0]); + } + + if(g_p->a[i].h[1] > 0 && (g_p->a[i].status[1] == 1 || g_p->a[i].status[1] == -1)) + { + weight += (g_p->a[i].weight[1] * g_p->a[i].status[1]); + } + weight += g_p->a[i].weight_convex*2; + + if(weight >= 0) continue; + if(weight < min) + { + min = weight; + min_i = i; + } + } + ///fprintf(stderr, "*****************min: %f\n", min); + return min_i; +} + +double get_cluster_weight_debug(G_partition* g_p, hc_links* link, uint32_t *h, uint32_t h_n) +{ + int o_d = 0; + double weight = 0; + uint32_t j, k, m, uID; + for (j = 0, weight = 0; j < h_n; j++) + { + for (k = 0; k < link->a.a[h[j]].e.n; k++) + { + if(link->a.a[h[j]].e.a[k].del) continue; + for (m = 0; m < h_n; m++) + { + if(h[m] == link->a.a[h[j]].e.a[k].uID) break; + } + if(m < h_n) continue; + + uID = link->a.a[h[j]].e.a[k].uID; + ///o_d = get_phase_status(hap, link->a.a[h[j]].e.a[k].uID); + o_d = g_p->a[g_p->index[uID]>>1].status[g_p->index[uID]&1]; + ///if(o_d < -1) fprintf(stderr, "ERROR\n"); + weight += (o_d*link->a.a[h[j]].e.a[k].weight); + } + } + + return weight; +} + +void flip_unitig(G_partition* g_p, hc_links* link, bubble_type* bub, uint32_t id) +{ + if(g_p->a[id].h[0] > 0 && g_p->a[id].status[0] != 1 && g_p->a[id].status[0] != -1) return; + if(g_p->a[id].h[1] > 0 && g_p->a[id].status[1] != 1 && g_p->a[id].status[1] != -1) return; + uint32_t k, j, m, *h0, h0_n, *h1, h1_n, uID, *h = NULL, h_n; + int status; + double weight; + get_phased_block(g_p, NULL, id, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); + // fprintf(stderr, "h0_n: %u, h1_n: %u\n", h0_n, h1_n); + if(h0_n > 0) + { + + status = g_p->a[id].status[0]; + // fprintf(stderr, "+status: %d\n", status); + h = h0; h_n = h0_n; + for (j = 0; j < h_n; j++) + { + // fprintf(stderr, "+j: %u, h_n: %u\n", j, h_n); + for (k = 0; k < link->a.a[h[j]].e.n; k++) + { + // fprintf(stderr, "+k: %u, e_n: %u\n", k, (uint32_t)link->a.a[h[j]].e.n); + if(link->a.a[h[j]].e.a[k].del) continue; + for (m = 0; m < h_n; m++) + { + if(h[m] == link->a.a[h[j]].e.a[k].uID) break; + } + // fprintf(stderr, "+m: %u, h_n: %u\n", m, h_n); + if(m < h_n) continue; + + uID = link->a.a[h[j]].e.a[k].uID; + + weight = link->a.a[h[j]].e.a[k].weight; + + if(g_p->index[uID] == (uint32_t)-1) continue; + + + g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1] -= (2*status*weight); + + + } + } + g_p->a[id].status[0] *= -1; + } + + // fprintf(stderr, "hehehe\n"); + if(h1_n > 0) + { + status = g_p->a[id].status[1]; + // fprintf(stderr, "-status: %d\n", status); + h = h1; h_n = h1_n; + for (j = 0; j < h_n; j++) + { + // fprintf(stderr, "-j: %u, h_n: %u\n", j, h_n); + for (k = 0; k < link->a.a[h[j]].e.n; k++) + { + // fprintf(stderr, "-k: %u, e_n: %u\n", k, (uint32_t)link->a.a[h[j]].e.n); + if(link->a.a[h[j]].e.a[k].del) continue; + for (m = 0; m < h_n; m++) + { + if(h[m] == link->a.a[h[j]].e.a[k].uID) break; + } + // fprintf(stderr, "-m: %u, h_n: %u\n", m, h_n); + if(m < h_n) continue; + + uID = link->a.a[h[j]].e.a[k].uID; + // fprintf(stderr, "-uID: %u\n", uID); + + weight = link->a.a[h[j]].e.a[k].weight; + + if(g_p->index[uID] == (uint32_t)-1) continue; + + + g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1] -= (2*status*weight); + + } + } + g_p->a[id].status[1] *= -1; + } +} + +void flip_unitig_debug(G_partition* g_p, hc_links* link, bubble_type* bub, uint32_t id) +{ + if(g_p->a[id].h[0] > 0 && g_p->a[id].status[0] != 1 && g_p->a[id].status[0] != -1) return; + if(g_p->a[id].h[1] > 0 && g_p->a[id].status[1] != 1 && g_p->a[id].status[1] != -1) return; + uint32_t k, j, m, *h0, h0_n, *h1, h1_n, uID, *h = NULL, h_n; + int status; + double weight; + get_phased_block(g_p, NULL, id, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); + // fprintf(stderr, "h0_n: %u, h1_n: %u\n", h0_n, h1_n); + if(h0_n > 0) + { + + status = g_p->a[id].status[0]; + // fprintf(stderr, "+status: %d\n", status); + h = h0; h_n = h0_n; + for (j = 0; j < h_n; j++) + { + // fprintf(stderr, "+j: %u, h_n: %u\n", j, h_n); + for (k = 0; k < link->a.a[h[j]].e.n; k++) + { + // fprintf(stderr, "+k: %u, e_n: %u\n", k, (uint32_t)link->a.a[h[j]].e.n); + if(link->a.a[h[j]].e.a[k].del) continue; + for (m = 0; m < h_n; m++) + { + if(h[m] == link->a.a[h[j]].e.a[k].uID) break; + } + // fprintf(stderr, "+m: %u, h_n: %u\n", m, h_n); + if(m < h_n) continue; + + uID = link->a.a[h[j]].e.a[k].uID; + + weight = link->a.a[h[j]].e.a[k].weight; + + if(g_p->index[uID] == (uint32_t)-1) continue; + + if(id == 19675) + { + fprintf(stderr, "+uID+: %u, e-weight: %f, g_p->index[uID]>>1: %u, status[0]: %d, pre_uID_weight: %f\n", + uID, weight, g_p->index[uID]>>1, status, g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1]); + } + + + g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1] -= (2*status*weight); + + if(id == 19675) + { + fprintf(stderr, "+uID+: %u, new_uID_weight: %f\n", uID, + g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1]); + } + + } + } + g_p->a[id].status[0] *= -1; + } + + // fprintf(stderr, "hehehe\n"); + if(h1_n > 0) + { + status = g_p->a[id].status[1]; + // fprintf(stderr, "-status: %d\n", status); + h = h1; h_n = h1_n; + for (j = 0; j < h_n; j++) + { + // fprintf(stderr, "-j: %u, h_n: %u\n", j, h_n); + for (k = 0; k < link->a.a[h[j]].e.n; k++) + { + // fprintf(stderr, "-k: %u, e_n: %u\n", k, (uint32_t)link->a.a[h[j]].e.n); + if(link->a.a[h[j]].e.a[k].del) continue; + for (m = 0; m < h_n; m++) + { + if(h[m] == link->a.a[h[j]].e.a[k].uID) break; + } + // fprintf(stderr, "-m: %u, h_n: %u\n", m, h_n); + if(m < h_n) continue; + + uID = link->a.a[h[j]].e.a[k].uID; + // fprintf(stderr, "-uID: %u\n", uID); + + weight = link->a.a[h[j]].e.a[k].weight; + + if(g_p->index[uID] == (uint32_t)-1) continue; + + if(id == 19675) + { + fprintf(stderr, "-uID-: %u, e-weight: %f, g_p->index[uID]>>1: %u, status[1]: %d, pre_uID_weight: %f\n", + uID, weight, g_p->index[uID]>>1, status, g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1]); + } + + g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1] -= (2*status*weight); + + if(id == 19675) + { + fprintf(stderr, "-uID-: %u, new_uID_weight: %f\n", uID, + g_p->a[g_p->index[uID]>>1].weight[g_p->index[uID]&1]); + } + } + } + g_p->a[id].status[1] *= -1; + } +} + + +uint32_t phasing_improvement(H_partition* h, G_partition* g_p, ha_ug_index* idx, bubble_type* bub, hc_links* link) +{ + uint32_t i, occ = 0, round = 0; + double pre_w, pre_total, current_w; + mul_block_phase_type b_x; + init_mul_block_phase_type(&b_x, g_p, bub, asm_opt.thread_num, h); + ///double index_time = yak_realtime(); + + while(1) + { + pre_w = get_total_weight(h, g_p); + pre_total = pre_w; + + while (1) + { + memset(h->lock, 0, sizeof(uint8_t)*g_p->n); + while (1) + { + i = get_max_unitig(h, g_p, link, bub); + if(i == (uint32_t)-1) break; + h->lock[i] = 1; + flip_unitig(g_p, link, bub, i); + occ++; + } + current_w = get_total_weight(h, g_p); + ///fprintf(stderr, "[M::%s::round single %u, pre_w: %f, current_w: %f]\n", __func__, round, pre_w, current_w); + if(ceil(current_w) <= ceil(pre_w)) break; + round++; + pre_w = current_w; + } + + + pre_w = get_total_weight(h, g_p); + round = 0; + while (1) + { + ///fprintf(stderr, "[M::%s::round block %u, h->n: %lu]\n", __func__, round, h->n); + phasing_improvement_by_block(h, g_p, bub, &b_x); + current_w = get_total_weight(h, g_p); + ///fprintf(stderr, "[M::%s::round block %u, pre_w: %f, current_w: %f]\n", __func__, round, pre_w, current_w); + if(ceil(current_w) <= ceil(pre_w)) break; + round++; + pre_w = current_w; + } + + if(ceil(current_w) <= ceil(pre_total)) break; + } + + destory_mul_block_phase_type(&b_x); + ///fprintf(stderr, "[M::%s:Flipping time:%.3f]\n", __func__, yak_realtime()-index_time); + + + for (i = 0; i < g_p->n; i++) + { + update_partition_flag(h, g_p, link, i); + } + + ///print_phase_group(g_p, bub, "Small"); + // double w0 = 0, w1 = 0; + // uint32_t *h0, h0_n, *h1, h1_n; + // get_phased_block(g_p, NULL, 2973, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); + // w0 = get_cluster_weight_debug(g_p, h->link, h0, h0_n); + // w1 = get_cluster_weight_debug(g_p, h->link, h1, h1_n); + // fprintf(stderr, "debug-w0: %f, g_p->a[2973].weight[0]: %f\n", w0, g_p->a[2973].weight[0]); + // fprintf(stderr, "debug-w1: %f, g_p->a[2973].weight[1]: %f\n", w1, g_p->a[2973].weight[1]); + + return !!occ; +} + +void destory_contig_partition(H_partition* hap) +{ + free(hap->lock); + free(hap->hap); + destory_G_partition(&(hap->g_p)); + destory_G_partition(&(hap->group_g_p)); + kv_destroy(hap->label_buffer); + kv_destroy(hap->b.vis); +} + +void label_unitigs(G_partition* g_p, ma_ug_t* ug) +{ + memset(R_INF.trio_flag, AMBIGU, R_INF.total_reads * sizeof(uint8_t)); + uint32_t i, k, j, *h0, h0_n, *h1, h1_n, uID, *h = NULL, h_n, flag = AMBIGU; + int status; + ma_utg_t *u = NULL; + + for (i = 0; i < g_p->n; i++) + { + if(g_p->a[i].h[0] > 0 && g_p->a[i].status[0] != 1 && g_p->a[i].status[0] != -1) continue; + if(g_p->a[i].h[1] > 0 && g_p->a[i].status[1] != 1 && g_p->a[i].status[1] != -1) continue; + get_phased_block(g_p, NULL, i, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); + + status = g_p->a[i].status[0]; + h = h0; h_n = h0_n; + if(status == 1) + { + flag = FATHER; + } + else if (status == -1) + { + flag = MOTHER; + } + for (j = 0; j < h_n; j++) + { + uID = h[j]; + u = &ug->u.a[uID]; + if(u->m == 0) continue; + for (k = 0; k < u->n; k++) + { + R_INF.trio_flag[u->a[k]>>33] = flag; + } + } + + + + status = g_p->a[i].status[1]; + h = h1; h_n = h1_n; + if(status == 1) + { + flag = FATHER; + } + else if (status == -1) + { + flag = MOTHER; + } + for (j = 0; j < h_n; j++) + { + uID = h[j]; + u = &ug->u.a[uID]; + if(u->m == 0) continue; + for (k = 0; k < u->n; k++) + { + R_INF.trio_flag[u->a[k]>>33] = flag; + } + } + } + + + uint64_t occ = 0; + for (i = 0; i < ug->u.n; i++) + { + occ += ug->u.a[i].n; + } + + ///fprintf(stderr, "# reads: %lu\n", occ); + + for (i = occ = 0; i < R_INF.total_reads; i++) + { + if(R_INF.trio_flag[i] == FATHER) occ++; + } + + ///fprintf(stderr, "# Father reads: %lu\n", occ); + + for (i = occ = 0; i < R_INF.total_reads; i++) + { + if(R_INF.trio_flag[i] == MOTHER) occ++; + } + + ///fprintf(stderr, "# Mother reads: %lu\n", occ); +} + +void label_unitigs_sm(int8_t *s, mc_gg_status *sa, ma_ug_t* ug) +{ + memset(R_INF.trio_flag, AMBIGU, R_INF.total_reads * sizeof(uint8_t)); + uint32_t i, k, flag = AMBIGU; + ma_utg_t *u = NULL; + + for (i = 0; i < ug->g->n_seq; i++) + { + if(ug->g->seq[i].del) continue; + flag = 0; + if(s) + { + if(s[i] == 0) continue; + flag = (s[i] > 0? FATHER:MOTHER); + } + + if(sa) + { + if(sa[i].s != 1 && sa[i].s != 2) continue; + flag = sa[i].s; + } + + u = &ug->u.a[i]; + if(u->m == 0) continue; + for (k = 0; k < u->n; k++) + { + R_INF.trio_flag[u->a[k]>>33] = flag; + } + } +} + + +void print_bubble_graph(bubble_type* bub, ma_ug_t* ug, const char* prefix, FILE *fp) +{ + uint32_t i, k, *a, n, beg, sink, x; + asg_t *b_g = bub->b_g; + char name[32]; + for (i = 0; i < b_g->n_seq; i++) + { + get_bubbles(bub, i, &beg, &sink, &a, &n, NULL); + sprintf(name, "%s%.6d%c", prefix, i, "fb"[if_bub?0:1]); + fprintf(stderr, "S\t%s\t*\tLN:i:%d\n", name, n); + + if(beg != (uint32_t)-1) fprintf(stderr, "A\tutg%.6d%c\t%s\n", (beg>>1)+1, "lc"[ug->u.a[(beg>>1)].circ], "beg"); + if(sink != (uint32_t)-1) fprintf(stderr, "A\tutg%.6d%c\t%s\n", (sink>>1)+1, "lc"[ug->u.a[(sink>>1)].circ], "sink"); + for (k = 0; k < n; k++) + { + x = a[k]>>1; + fprintf(stderr, "A\tutg%.6d%c\t%s\n", x+1, "lc"[ug->u.a[x].circ], "mid"); + } + } + + asg_arc_t* au = NULL; + uint32_t nu, u, v; + for (i = 0; i < b_g->n_seq; i++) + { + u = i<<1; + au = asg_arc_a(b_g, u); + nu = asg_arc_n(b_g, u); + for (k = 0; k < nu; k++) + { + if(au[k].del) continue; + v = au[k].v; + fprintf(stderr, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", + prefix, u>>1, "fb"[(u>>1)f_bub?0:1], "+-"[u&1], + prefix, v>>1, "fb"[(v>>1)f_bub?0:1], "+-"[v&1], 0, 0); + + + asg_arc_t* av = asg_arc_a(b_g, v^1); + uint32_t nv = asg_arc_n(b_g, v^1), m; + for (m = 0; m < nv; m++) + { + if(av[m].del) continue; + if(av[m].v == (u^1)) break; + } + + if(m == nv) fprintf(stderr, "sb1sb, nv: %u, nu: %u\n", nv, nu); + } + + + u = (i<<1) + 1; + au = asg_arc_a(ug->g, u); + nu = asg_arc_n(ug->g, u); + for (k = 0; k < nu; k++) + { + if(au[k].del) continue; + v = au[k].v; + fprintf(stderr, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", + prefix, u>>1, "fb"[(u>>1)f_bub?0:1], "+-"[u&1], + prefix, v>>1, "fb"[(v>>1)f_bub?0:1], "+-"[v&1], 0, 0); + + asg_arc_t* av = asg_arc_a(b_g, v^1); + uint32_t nv = asg_arc_n(b_g, v^1), m; + for (m = 0; m < nv; m++) + { + if(av[m].del) continue; + if(av[m].v == (u^1)) break; + } + + if(m == nv) fprintf(stderr, "sb2sb, nv: %u, nu: %u\n", nv, nu); + } + } +} + + + +void print_bubble_utg(bubble_type* bub, ma_ug_t* unitig_ug, const char* prefix, FILE *fp) +{ + uint32_t i, k, *a, n, beg, sink, x, occ; + ma_ug_t *b_ug = bub->b_ug; + char name[32]; + for (i = 0; i < b_ug->u.n; i++) + { + ma_utg_t *p = &b_ug->u.a[i]; + if(p->n == 0) continue; + for (k = occ = 0; k < p->n; k++) + { + x = p->a[k]>>33; + get_bubbles(bub, x, &beg, &sink, &a, &n, NULL); + occ += n; + } + sprintf(name, "%s%.6d%c", prefix, i + 1, "lc"[p->circ]); + fprintf(fp, "S\t%s\t*\tLN:i:%u\n", name, occ); + for (k = 0; k < p->n; k++) + { + x = p->a[k]>>33; + get_bubbles(bub, x, &beg, &sink, &a, &n, NULL); + if(beg != (uint32_t)-1) fprintf(fp, "A\tutg%.6d%c\t%u\t%s\n", (beg>>1)+1, "lc"[unitig_ug->u.a[(beg>>1)].circ], n, "beg"); + if(sink != (uint32_t)-1) fprintf(fp, "A\tutg%.6d%c\t%u\t%s\n", (sink>>1)+1, "lc"[unitig_ug->u.a[(sink>>1)].circ], n, "sink"); + } + } + + asg_arc_t* au = NULL; + uint32_t nu, u, v, j; + for (i = 0; i < b_ug->u.n; ++i) { + if(b_ug->u.a[i].m == 0) continue; + if(b_ug->u.a[i].circ) + { + fprintf(fp, "L\t%s%.6dc\t+\t%s%.6dc\t+\t%dM\tL1:i:%d\n", + prefix, i+1, prefix, i+1, 0, 0); + fprintf(fp, "L\t%s%.6dc\t-\t%s%.6dc\t-\t%dM\tL1:i:%d\n", + prefix, i+1, prefix, i+1, 0, 0); + } + u = i<<1; + au = asg_arc_a(b_ug->g, u); + nu = asg_arc_n(b_ug->g, u); + for (j = 0; j < nu; j++) + { + if(au[j].del) continue; + v = au[j].v; + fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", + prefix, (u>>1)+1, "lc"[b_ug->u.a[u>>1].circ], "+-"[u&1], + prefix, (v>>1)+1, "lc"[b_ug->u.a[v>>1].circ], "+-"[v&1], 0, 0); + } + + + u = (i<<1) + 1; + au = asg_arc_a(b_ug->g, u); + nu = asg_arc_n(b_ug->g, u); + for (j = 0; j < nu; j++) + { + if(au[j].del) continue; + v = au[j].v; + fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", + prefix, (u>>1)+1, "lc"[b_ug->u.a[u>>1].circ], "+-"[u&1], + prefix, (v>>1)+1, "lc"[b_ug->u.a[v>>1].circ], "+-"[v&1], 0, 0); + } + } + + +} + + +void print_debug_bubble_graph(bubble_type* bub, ma_ug_t* ug, const char *fn) +{ + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.bub.gfa", fn); + FILE* fp = fopen(buf, "w"); + + print_bubble_utg(bub, ug, "btg", fp); + + fclose(fp); + free(buf); +} + +void print_bubble_chain(bubble_type* bub) +{ + uint32_t m, i, k; + uint32_t beg, sink, *a = NULL, n; + uint64_t bid; + ma_utg_t *u = NULL; + for (m = 0; m < bub->chain_weight.n; m++) + { + if(bub->chain_weight.a[m].del) continue; + u = &(bub->b_ug->u.a[bub->chain_weight.a[m].id]); + fprintf(stderr, "\nChain_id=%lu\n", bub->chain_weight.a[m].id); + for (i = 0; i < u->n; i++) + { + bid = u->a[i]>>33; + get_bubbles(bub, bid, &beg, &sink, &a, &n, NULL); + fprintf(stderr, "btg%.6lu%c, beg-utg%.6ul, sink-utg%.6ul\n", + bid, "fb"[bidf_bub?0:1], (beg>>1)+1, (sink>>1)+1); + for (k = 0; k < n; k++) + { + if(k != 0 && (k%5)==0) fprintf(stderr, "\n"); + fprintf(stderr, "m-utg%.6ul\t", (a[k]>>1)+1); + } + fprintf(stderr, "\n"); + + } + } +} + +void init_contig_H_partition(bubble_type* bub, ha_ug_index* idx, H_partition* hap) +{ + uint32_t i, k_i, k_j, uID, *a = NULL, n, *h0, h0_n, *h1, h1_n; + destory_G_partition(&(hap->group_g_p)); memset(&(hap->group_g_p), 0, sizeof(G_partition)); + init_G_partition(&(hap->group_g_p), hap->n); + partition_warp *res = NULL; + ma_utg_t *u_x = NULL; + chain_hic_warp *c_w = &(bub->c_w); + + for (i = 0; i < bub->c_w.n; i++) + { + kv_pushp(partition_warp, hap->group_g_p, &res); + kv_init(res->a); + res->full_bub = 0; + res->h[0] = res->h[1] = 0; + + res->status[0] = 1; res->status[1] = -1; + res->weight[0] = res->weight[1] = res->weight_convex = 0; + + + u_x = (*c_w).a[(*c_w).a[i].id].u; + for (k_i = 0; k_i < u_x->n; k_i++) + { + get_bubbles(bub, u_x->a[k_i]>>33, NULL, NULL, &a, &n, NULL); + for (k_j = 0; k_j < n; k_j++) + { + uID = a[k_j]>>1; + if((*c_w).chain_idx[uID] != (*c_w).a[i].id) continue; + if(get_phase_status(hap, uID)==1) + { + kv_push(uint32_t, res->a, uID); + res->h[0]++; + } + } + } + + for (k_i = 0; k_i < u_x->n; k_i++) + { + get_bubbles(bub, u_x->a[k_i]>>33, NULL, NULL, &a, &n, NULL); + for (k_j = 0; k_j < n; k_j++) + { + uID = a[k_j]>>1; + if((*c_w).chain_idx[uID] != (*c_w).a[i].id) continue; + if(get_phase_status(hap, uID)==-1) + { + kv_push(uint32_t, res->a, uID); + res->h[1]++; + } + } + } + + + for (k_i = 0; k_i < res->h[0]; k_i++) + { + ///if(hap->group_g_p.index[res->a.a[k_i]] != (uint32_t)-1) fprintf(stderr, "ERROR---00\n"); + hap->group_g_p.index[res->a.a[k_i]] = hap->group_g_p.n-1; + hap->group_g_p.index[res->a.a[k_i]] = hap->group_g_p.index[res->a.a[k_i]] << 1; + } + + for (; k_i < res->a.n; k_i++) + { + ///if(hap->group_g_p.index[res->a.a[k_i]] != (uint32_t)-1) fprintf(stderr, "ERROR---11\n"); + hap->group_g_p.index[res->a.a[k_i]] = hap->group_g_p.n-1; + hap->group_g_p.index[res->a.a[k_i]] = (hap->group_g_p.index[res->a.a[k_i]] << 1) + 1; + } + + get_phased_block(&(hap->group_g_p), NULL, i, NULL, NULL, &h0, &h0_n, &h1, &h1_n, NULL, NULL); + if(h0_n >0) res->weight[0] = get_cluster_weight(hap, hap->link, h0, h0_n); + if(h1_n >0) res->weight[1] = get_cluster_weight(hap, hap->link, h1, h1_n); + res->weight_convex = get_cluster_inner_weight(hap, hap->link, h0, h0_n, h1, h1_n); + } + + flip_by_node(hap, &(hap->group_g_p), bub); + label_unitigs(&(hap->group_g_p), idx->ug); +} + +void reset_H_partition(H_partition* hap, uint32_t is_init) +{ + if(!is_init) + { + hap->n = 0; + free(hap->lock); + free(hap->hap); + hap->m[0] = hap->m[1] = hap->m[2] = (uint32_t)-1; + hap->label = hap->label_add = hap->label_shift = (uint32_t)-1; + destory_G_partition(&(hap->g_p)); memset(&(hap->g_p), 0, sizeof(G_partition)); + destory_G_partition(&(hap->group_g_p)); memset(&(hap->group_g_p), 0, sizeof(G_partition)); + kv_destroy(hap->label_buffer); kv_init(hap->label_buffer); + kv_destroy(hap->b.vis); kv_init(hap->b.vis); memset(&(hap->b), 0, sizeof(block_phase_type)); + } + + memset(hap, 0, sizeof(H_partition)); +} + + +int alignment_worker_pipeline(sldat_t* sl, const enzyme *fn1, const enzyme *fn2) +{ + double index_time = yak_realtime(); + int i; + for (i = 0; i < fn1->n && i < fn2->n; i++) + { + gzFile fp1, fp2; + if ((fp1 = gzopen(fn1->a[i], "r")) == 0) return 0; + if ((fp2 = gzopen(fn2->a[i], "r")) == 0) return 0; + sl->ks1 = kseq_init(fp1); + sl->ks2 = kseq_init(fp2); + + kt_pipeline(3, worker_pipeline, sl, 3); + + kseq_destroy(sl->ks1); + kseq_destroy(sl->ks2); + gzclose(fp1); + gzclose(fp2); + } + fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); + + dedup_hits(&(sl->hits), 1); + return 1; +} + +void debug_gfa_space(ha_ug_index* idx, ma_ug_t* ug, trans_chain* t_ch, kv_u_trans_t *ref) +{ + bubble_type bub; + memset(&bub, 0, sizeof(bubble_type)); + bub.round_id = 0; bub.n_round = 2; + + identify_bubbles(ug, &bub, t_ch->ir_het, ref); + + hc_links link; + init_hc_links(&link, ug->g->n_seq, t_ch); + + measure_distance(idx, ug, NULL, &link, &bub, &(t_ch->k_trans)); + + // uint32_t i, k; + // for (i = 0; i < link.a.n; ++i) + // { + // for (k = 0; k < link.a.a[i].e.n; k++) + // { + // if(link.a.a[i].e.a[k].del || link.a.a[i].e.a[k].dis == (uint64_t)-1) continue; + // fprintf(stderr, "s-utg%.6dl\td-utg%.6dl\t%lu\n", + // (int)(i+1), (int)(link.a.a[i].e.a[k].uID+1), + // link.a.a[i].e.a[k].dis == (uint64_t)-1? (uint64_t)-1 : link.a.a[i].e.a[k].dis>>3); + // } + // } + + + + destory_bubbles(&bub); + destory_hc_links(&link); +} + +void idx_hc_links(kvec_pe_hit* hits, ha_ug_index* idx, bubble_type* bub) +{ + uint64_t k, l; + uint32_t qn, tn; + + kv_resize(uint64_t, hits->idx, idx->ug->g->n_seq); + hits->idx.n = idx->ug->g->n_seq; + memset(hits->idx.a, 0, hits->idx.n*sizeof(uint64_t)); + + kv_resize(uint64_t, hits->occ, idx->ug->g->n_seq); + hits->occ.n = idx->ug->g->n_seq; + memset(hits->occ.a, 0, hits->occ.n*sizeof(uint64_t)); + + radix_sort_pe_hit_idx_an1(hits->a.a, hits->a.a + hits->a.n); + for (k = 1, l = 0; k <= hits->a.n; ++k) + { + if (k == hits->a.n || + ((hits->a.a[k].s<<1)>>(64 - idx->uID_bits)) != ((hits->a.a[l].s<<1)>>(64 - idx->uID_bits))) + { + if (k - l > 1) radix_sort_pe_hit_idx_an2(hits->a.a + l, hits->a.a + k); + + hits->idx.a[((hits->a.a[l].s<<1)>>(64 - idx->uID_bits))] + = (uint64_t)l << 32 | (k - l); + + for (; l < k; l++) + { + qn = ((hits->a.a[l].s<<1)>>(64 - idx->uID_bits)); + tn = ((hits->a.a[l].e<<1)>>(64 - idx->uID_bits)); + if(bub && IF_HOM(qn, *bub)) continue; + if(bub && IF_HOM(tn, *bub)) continue; + hits->occ.a[qn]++; + hits->occ.a[tn]++; + } + + l = k; + } + } +} + +inline uint32_t trans_checking_pass(bubble_type* bub, kv_u_trans_t *ref, uint32_t x, uint32_t y) +{ + if(u_trans_n(*ref, x) == 0 || u_trans_n(*ref, y) == 0) return 0; + u_trans_t *a = NULL; + uint32_t n, i, f[2], qn, tn; + + qn = x; tn = y; + a = u_trans_a(*ref, qn); n = u_trans_n(*ref, qn); + for (i = 0, f[0] = f[1] = 0; i < n; i++) + { + if(a[i].del) continue; + if(a[i].f == RC_2) continue; + if(IF_HOM(a[i].tn, *bub)) continue; + f[(a[i].tn == tn && a[i].f != RC_2)]++; + } + if(f[0] != 0) return 0; + if(f[1] == 0) return 0; + + qn = y; tn = x; + a = u_trans_a(*ref, qn); n = u_trans_n(*ref, qn); + for (i = 0, f[0] = f[1] = 0; i < n; i++) + { + if(a[i].del) continue; + if(IF_HOM(a[i].tn, *bub)) continue; + f[(a[i].tn == tn && a[i].f != RC_2)]++; + } + if(f[0] != 0) return 0; + if(f[1] == 0) return 0; + + fprintf(stderr, "M::%s::s-utg%.6ul<----->d-utg%.6ul\n", __func__, x+1, y+1); + return 1; +} + +uint32_t get_u_trans_spec_idx(kv_u_trans_t *ta, uint32_t qn, uint32_t tn, u_trans_t **r_a, uint32_t *occ, uint32_t *idx) +{ + if(r_a) (*r_a) = NULL; + if(occ) (*occ) = 0; + if(idx) (*idx) = (uint32_t)-1; + u_trans_t *a = NULL; + uint32_t n, st, i; + a = u_trans_a(*ta, qn); + n = u_trans_n(*ta, qn); + for (st = 0, i = 1; i <= n; ++i) + { + if (i == n || a[i].tn != a[st].tn) + { + if(a[st].tn == tn) + { + if(r_a) (*r_a) = a + st; + if(occ) (*occ) = i - st; + if(idx) (*idx) = st + ((*ta).idx.a[(qn)]>>32); + return 1; + } + st = i; + } + } + return 0; +} + +void interpr_hit(ha_ug_index* idx, uint64_t x, uint32_t rLen, uint32_t *uid, uint32_t *beg, uint32_t *end); +int hic_sc_type(ha_ug_index* idx, kvec_pe_hit* hits, uint64_t k) +{ + uint32_t s_uid, s_beg, s_end, e_uid, e_beg, e_end, slen, elen, x = 0; + + interpr_hit(idx, hits->a.a[k].s, hits->a.a[k].len>>32, &s_uid, &s_beg, &s_end); + s_beg = (s_beg+s_end)>>1; slen = idx->ug->u.a[s_uid].len; + if(s_beg >= (slen>>1)) x+=1; + + interpr_hit(idx, hits->a.a[k].e, (uint32_t)hits->a.a[k].len, &e_uid, &e_beg, &e_end); + e_beg = (e_beg+e_end)>>1; elen = idx->ug->u.a[e_uid].len; + if(e_beg >= (elen>>1)) x+=2; + return x; +} + +void weight_kv_u_trans(ha_ug_index* idx, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, +kv_u_trans_t *ta, trans_idx* dis, int sc_weight) +{ + uint64_t k, i, shif = 64 - idx->uID_bits, beg, end, t_d; + u_trans_t *e1 = NULL, *e2 = NULL; + long double weight; + double *sw = NULL; + u_trans_t *p = NULL; + uint32_t is_cc, ii1, ii2; + + for (i = 0, ta->idx.n = ta->n = 0; i < link->a.n; i++) + { + for (k = 0; k < link->a.a[i].e.n; k++) + { + if(link->a.a[i].e.a[k].del) continue; + if(IF_HOM(i, *bub)) continue; + if(IF_HOM(link->a.a[i].e.a[k].uID, *bub)) continue; + if(i == link->a.a[i].e.a[k].uID) continue; + + kv_pushp(u_trans_t, *ta, &p); + memset(p, 0, sizeof(u_trans_t)); + p->qn = i; p->tn = link->a.a[i].e.a[k].uID; + p->nw = 0; p->occ = 0; + } + } + kt_u_trans_t_idx(ta, idx->ug->g->n_seq); + if(sc_weight) { + k = ta->n*3; + MALLOC(sw, k); + for (i = 0; i < k; i++) sw[i] = 0; + } + + + for (k = 0; k < hits->a.n; ++k) + { + beg = ((hits->a.a[k].s<<1)>>shif); + end = ((hits->a.a[k].e<<1)>>shif); + + if(beg == end) continue; + if(IF_HOM(beg, *bub)) continue; + if(IF_HOM(end, *bub)) continue; + if(is_hom_hit(hits->a.a[k])) continue; + + t_d = get_hic_distance(&(hits->a.a[k]), link, idx, &is_cc); + // if(t_d == (uint64_t)-1) continue; + // if(t_d == (uint64_t)-1 && is_cc == 0) continue; + // if(t_d == (uint64_t)-1 && !dis) continue; + + get_u_trans_spec_idx(ta, beg, end, &e1, NULL, &ii1); + get_u_trans_spec_idx(ta, end, beg, &e2, NULL, &ii2); + + if(e1 == NULL || e2 == NULL) continue; + weight = 1; + if(dis) weight = get_trans_weight_advance(idx, t_d, dis); + + if(sc_weight){ + i = hic_sc_type(idx, hits, k); + if(i == 0){ + e1->nw -= weight; e2->nw -= weight; + } + else{ + i--; + sw[(ii1*3)+i] -= weight; + sw[(ii2*3)+i] -= weight; + } + } else{ + e1->nw -= weight; e2->nw -= weight; + } + e1->occ++; e2->occ++; + } + + if(sc_weight) { + for (i = 0; i < ta->n; ++i){ + if(ta->a[i].nw > sw[(i*3)]) ta->a[i].nw = sw[(i*3)]; + if(ta->a[i].nw > sw[(i*3)+1]) ta->a[i].nw = sw[(i*3)+1]; + if(ta->a[i].nw > sw[(i*3)+2]) ta->a[i].nw = sw[(i*3)+2]; + ta->a[i].nw *= 2/**4**/; + } + free(sw); + } +} + +void interpr_hit(ha_ug_index* idx, uint64_t x, uint32_t rLen, uint32_t *uid, uint32_t *beg, uint32_t *end) +{ + if(uid) (*uid) = ((x<<1)>>(64 - idx->uID_bits)); + uint32_t rev = (x>>63); + long long ref_p = x & idx->pos_mode; + long long p_beg, p_end; + + if(rev) + { + p_end = ref_p; + p_beg = p_end + 1 - rLen; + } + else + { + p_beg = ref_p; + p_end = p_beg + rLen - 1; + } + if(p_beg < 0) p_beg = 0; + if(p_end < 0) p_end = 0; + if(beg) (*beg) = p_beg; + if(end) (*end) = p_end + 1; +} +double get_interval_weight(ha_ug_index* idx, hc_links* link, trans_idx* dis, +pe_hit *hits, uint32_t occ, uint32_t qid, uint32_t qs, uint32_t qe, uint32_t tid, uint32_t ts, uint32_t te) +{ + int64_t s_idx = 0, e_idx = (int64_t)occ - 1, m_idx = 0; + uint32_t m_uid = (uint32_t)-1; + while (s_idx <= e_idx) + { + m_idx = s_idx + (e_idx - s_idx)/2; + m_uid = ((hits[m_idx].e<<1)>>(64 - idx->uID_bits)); + if (m_uid == tid) + break; + if (m_uid < tid) + s_idx = m_idx + 1; + else + e_idx = m_idx - 1; + } + if(m_uid != tid) return 0; + + + uint32_t k, s_uid, s_beg, s_end, e_uid, e_beg, e_end; + uint64_t t_d; + double w, weight; + w = 0; + for (k = m_idx; k < occ; k++)///all hits of qid + { + interpr_hit(idx, hits[k].s, hits[k].len>>32, &s_uid, &s_beg, &s_end); + if(s_uid != qid) continue; + if(!(qs <= s_beg && qe >= s_end)) continue; + + interpr_hit(idx, hits[k].e, (uint32_t)hits[k].len, &e_uid, &e_beg, &e_end); + if(e_uid != tid) break; + if(!(ts <= e_beg && te >= e_end)) continue; + + t_d = get_hic_distance(&hits[k], link, idx, NULL); + if(t_d == (uint64_t)-1) continue; + + weight = 1; + if(dis) weight = get_trans_weight_advance(idx, t_d, dis); + + w += weight; + } + + for (m_idx -= 1; m_idx >= 0; m_idx--) + { + k = m_idx; + interpr_hit(idx, hits[k].s, hits[k].len>>32, &s_uid, &s_beg, &s_end); + if(s_uid != qid) continue; + if(!(qs <= s_beg && qe >= s_end)) continue; + + interpr_hit(idx, hits[k].e, (uint32_t)hits[k].len, &e_uid, &e_beg, &e_end); + if(e_uid != tid) break; + if(!(ts <= e_beg && te >= e_end)) continue; + + t_d = get_hic_distance(&hits[k], link, idx, NULL); + if(t_d == (uint64_t)-1) continue; + + weight = 1; + if(dis) weight = get_trans_weight_advance(idx, t_d, dis); + + w += weight; + } + return w; +} + +double get_hits_weight(ha_ug_index* idx, bubble_type* bub, kvec_pe_hit* hits, hc_links* link, trans_idx* dis, +u_trans_t *t_a, uint32_t t_n, uint32_t qid, kv_u_trans_t *ta_idx) +{ + /****************************may have bugs********************************/ + ///need to record self hits + ///if(u_trans_n(*ta_idx, qid) == 0) return 0;///no hit bridging qid + /****************************may have bugs********************************/ + uint32_t k, i, x_n, y; + u_trans_t *x_a = NULL; + double occ_q, occ_t; + double w, i_w; + for (k = 0, w = 0; k < t_n; k++) + { + if(IF_HOM(qid, *bub)) continue; + if(IF_HOM(t_a[k].tn, *bub)) continue; + /****************************may have bugs********************************/ + if(qid != t_a[k].tn) + { + x_n = u_trans_n(*ta_idx, qid); x_a = u_trans_a(*ta_idx, qid); y = t_a[k].tn; + if(u_trans_n(*ta_idx, t_a[k].tn) < x_n) + { + x_n = u_trans_n(*ta_idx, t_a[k].tn); x_a = u_trans_a(*ta_idx, t_a[k].tn); y = qid; + } + if(x_n == 0) continue; + + for (i = 0; i < x_n; i++) + { + if(x_a[i].tn == y) break; + } + if(i >= x_n) continue; ///no hit bridging tn and qid + } + /****************************may have bugs********************************/ + occ_q = hits->occ.a[qid]; + occ_t = hits->occ.a[t_a[k].tn] * ((double)(t_a[k].te - t_a[k].ts) / (double)(idx->ug->g->seq[t_a[k].tn].len)); + if(occ_t < 1) occ_t = 1; + + ///q--->t hits + i_w = get_interval_weight(idx, link, dis, hits->a.a + (hits->idx.a[qid]>>32), + (uint32_t)(hits->idx.a[qid]), qid, 0, idx->ug->g->seq[qid].len, t_a[k].tn, + t_a[k].ts, t_a[k].te); + if(i_w != 0) i_w /= (MIN(occ_q, occ_t)); + w += i_w; + if(t_a[k].tn == qid) continue; + + ///t--->q hits + i_w = get_interval_weight(idx, link, dis, hits->a.a + (hits->idx.a[t_a[k].tn]>>32), + (uint32_t)(hits->idx.a[t_a[k].tn]), t_a[k].tn, t_a[k].ts, t_a[k].te, + qid, 0, idx->ug->g->seq[qid].len); + if(i_w != 0) i_w /= (MIN(occ_q, occ_t)); + w += i_w; + } + return w; +} + + +void adjust_weight_kv_u_trans(ha_ug_index* idx, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, +kv_u_trans_t *ta, kv_u_trans_t *ref, trans_idx* dis) +{ + u_trans_t *a = NULL, *p = NULL; + uint32_t n, k, i, m, qn, tn; + uint8_t *vis = NULL; CALLOC(vis, idx->ug->g->n_seq); + double w; + + for (i = m = 0; i < ta->n; i++) + { + if(ta->a[i].del) continue; + if(IF_HOM(ta->a[i].qn, *bub)) continue; + if(IF_HOM(ta->a[i].tn, *bub)) continue; + ta->a[m] = ta->a[i]; + if(ta->a[m].nw != 0) + { + ta->a[m].nw /= (double)(MIN(hits->occ.a[ta->a[m].qn], hits->occ.a[ta->a[m].tn])); + } + /*******************************for debug************************************/ + // trans_checking_pass(bub, ref, ta->a[i].qn, ta->a[i].tn); + // if(trans_checking_pass(bub, ref, ta->a[i].qn, ta->a[i].tn)) ta->a[m].nw = 0; + /*******************************for debug************************************/ + + m++; + } + ta->n = m; + + for (k = 0; k < ta->idx.n; k++)///all nodes + { + if(IF_HOM(k, *bub)) continue; + a = u_trans_a(*ta, k); + n = u_trans_n(*ta, k); + ///for each pair qn, tn + ///count hic pairs between (qn, tn^) and (qn^1, tn) + for (i = 0, vis[k] = 1; i < n; i++) + { + vis[a[i].tn] = 1; + if(a[i].qn == a[i].tn) continue; + if(IF_HOM(a[i].qn, *bub)) continue; + if(IF_HOM(a[i].tn, *bub)) continue; + ///(qn, tn^) + a[i].nw += get_hits_weight(idx, bub, hits, link, dis, + u_trans_a(*ref, a[i].tn), u_trans_n(*ref, a[i].tn), a[i].qn, ta); + ///(qn^1, tn) + a[i].nw += get_hits_weight(idx, bub, hits, link, dis, + u_trans_a(*ref, a[i].qn), u_trans_n(*ref, a[i].qn), a[i].tn, ta); + } + + + for (i = 0; i < ta->idx.n; i++)///all edges + { + qn = k; tn = i; w = 0; + if(IF_HOM(qn, *bub)) continue; + if(IF_HOM(tn, *bub)) continue; + if(vis[tn]) continue; + if(qn == tn) continue; + ///(qn, tn^) + w += get_hits_weight(idx, bub, hits, link, dis, + u_trans_a(*ref, tn), u_trans_n(*ref, tn), qn, ta); + ///(qn^1, tn) + w += get_hits_weight(idx, bub, hits, link, dis, + u_trans_a(*ref, qn), u_trans_n(*ref, qn), tn, ta); + if(w == 0) continue; + kv_pushp(u_trans_t, *ta, &p); + memset(p, 0, sizeof(u_trans_t));///extra edges + p->nw = w; p->qn = qn; p->tn = tn; + } + + // for (i = 0; i < u_trans_n(*ref, k); i++)///only trans edges + // { + // qn = k; tn = (u_trans_a(*ref, k))[i].tn; w = 0; + // if(IF_HOM(qn, *bub)) continue; + // if(IF_HOM(tn, *bub)) continue; + // if(vis[tn]) continue; + // if(qn == tn) continue; + // ///(qn, tn^) + // w += get_hits_weight(idx, hits, link, dis, + // u_trans_a(*ref, tn), u_trans_n(*ref, tn), qn, ta); + // ///(qn^1, tn) + // w += get_hits_weight(idx, hits, link, dis, + // u_trans_a(*ref, qn), u_trans_n(*ref, qn), tn, ta); + // if(w == 0) continue; + // kv_pushp(u_trans_t, *ta, &p); + // memset(p, 0, sizeof(u_trans_t));///extra edges + // p->nw = w; p->qn = qn; p->tn = tn; + // } + + for (i = 0, vis[k] = 0; i < n; i++) vis[a[i].tn] = 0; + } + + // fprintf(stderr, "------ta->n=%u\n", (uint32_t)ta->n); + + for (i = m = 0; i < ta->n; i++) + { + if(ta->a[i].nw == 0 || ta->a[i].del) continue; + ta->a[m] = ta->a[i]; + m++; + } + ta->n = m; + + free(vis); + kt_u_trans_t_idx(ta, idx->ug->g->n_seq); +} + + +inline uint32_t get_trans_interval_weight(ha_ug_index* idx, hc_links* link, bubble_type* bub, +trans_idx* dis, pe_hit *hit, uint32_t hit_n, uint32_t qn, uint32_t qs, uint32_t qe, uint32_t tn, +uint32_t ts, uint32_t te, double *w_a) +{ + uint32_t i, s_uid, s_beg, s_end, e_uid, e_beg, e_end, found, is_cc; + uint64_t t_d; + double weight; + (*w_a) = 0; found = 0; + for (i = 0; i < hit_n; i++)///all hits already have the same qn and tn + { + if(is_hom_hit(hit[i])) continue; + interpr_hit(idx, hit[i].s, hit[i].len>>32, &s_uid, &s_beg, &s_end); + if(s_uid != qn) continue; + if(!(qs <= s_beg && qe >= s_end)) continue; + + interpr_hit(idx, hit[i].e, (uint32_t)hit[i].len, &e_uid, &e_beg, &e_end); + if(e_uid != tn) continue; + if(!(ts <= e_beg && te >= e_end)) continue; + + t_d = get_hic_distance(&hit[i], link, idx, &is_cc); + // if(t_d == (uint64_t)-1) continue; + // if(t_d == (uint64_t)-1 && is_cc == 0) continue; + // if(t_d == (uint64_t)-1 && !dis) continue; + + weight = 1; + if(dis) weight = get_trans_weight_advance(idx, t_d, dis); + + (*w_a) += weight; + found = 1; + } + + return found; +} + + +void append_trans_hits(ha_ug_index* idx, hc_links* link, bubble_type* bub, +trans_idx* dis, pe_hit *hit, uint32_t hit_n, uint64_t *hit_occ, kv_u_trans_t *ref, +kv_u_trans_t *res, uint32_t qn, uint32_t tn) +{ + u_trans_t *r_a = NULL, *p = NULL, *q = NULL; + uint32_t r_n, i; + uint64_t occ_q, occ_t; + double w; + + ///qn -> tn^ + { + r_a = u_trans_a(*ref, tn); + r_n = u_trans_n(*ref, tn); + for (i = 0; i < r_n; i++) + { + if(IF_HOM(r_a[i].tn, *bub)) continue; + if(r_a[i].tn == qn) continue; + + if(!get_trans_interval_weight(idx, link, bub, dis, hit, hit_n, + qn, 0, idx->ug->g->seq[qn].len, tn, r_a[i].qs, r_a[i].qe, &w)) + { + continue; + } + + occ_q = hit_occ[qn]; + occ_t = (hit_occ[tn] * ((double)(r_a[i].qe - r_a[i].qs)/(double)(idx->ug->g->seq[tn].len))) + 0.5; + if(occ_t < 1) occ_t = 1; + + kv_pushp(u_trans_t, *res, &p); + memset(p, 0, sizeof(u_trans_t)); + p->qn = qn; p->tn = r_a[i].tn; + p->nw = w/**r_a[i].occ**/; + p->occ = MIN(occ_q, occ_t); + + kv_pushp(u_trans_t, *res, &q); + (*q) = (*p); q->qn = p->tn; q->tn = p->qn; + } + } + + if(qn == tn) return; + + ///tn -> qn^ + { + r_a = u_trans_a(*ref, qn); + r_n = u_trans_n(*ref, qn); + for (i = 0; i < r_n; i++) + { + if(IF_HOM(r_a[i].tn, *bub)) continue; + if(r_a[i].tn == tn) continue; + + if(!get_trans_interval_weight(idx, link, bub, dis, hit, hit_n, + qn, r_a[i].qs, r_a[i].qe, tn, 0, idx->ug->g->seq[tn].len, &w)) + { + continue; + } + + occ_q = (hit_occ[qn] * ((double)(r_a[i].qe - r_a[i].qs)/(double)(idx->ug->g->seq[qn].len))) + 0.5; + occ_t = hit_occ[tn]; + if(occ_q < 1) occ_q = 1; + kv_pushp(u_trans_t, *res, &p); + memset(p, 0, sizeof(u_trans_t)); + p->qn = tn; p->tn = r_a[i].tn; + p->nw = w/**r_a[i].occ**/; + p->occ = MIN(occ_q, occ_t); + + kv_pushp(u_trans_t, *res, &q); + (*q) = (*p); q->qn = p->tn; q->tn = p->qn; + } + } + +} + +double merge_u_trans_list(u_trans_t* a, uint32_t a_n) +{ + radix_sort_u_trans_occ(a, a + a_n); + uint32_t k, l, i; + double weight, w = 0; + for (k = 1, l = 0; k <= a_n; ++k) + { + if (k == a_n || a[k].occ != a[l].occ) + { + for (i = l, weight = 0; i < k; i++) + { + weight += a[i].nw; + } + + /*******************************for debug************************************/ + // w += (weight/(double)(a[l].occ)); + w += weight; + /*******************************for debug************************************/ + l = k; + } + } + return w; +} + +void adjust_weight_kv_u_trans_advance(ha_ug_index* idx, kvec_pe_hit* hits, hc_links* link, bubble_type* bub, +kv_u_trans_t *ta, kv_u_trans_t *ref, trans_idx* dis) +{ + double index_time = yak_realtime(); + uint32_t k, l, m, h_occ; + uint64_t shif = 64 - idx->uID_bits, qn, tn; + double w; + pe_hit *h_a = NULL; + + for (k = m = 0; k < ta->n; k++) + { + if(ta->a[k].nw == 0) continue; + ta->a[k].occ = MIN(hits->occ.a[ta->a[k].qn], hits->occ.a[ta->a[k].tn]); + if(ta->a[k].occ == 0) continue; + ta->a[m] = ta->a[k]; + m++; + } + ta->n = m; + + for (qn = 0; qn < hits->idx.n; qn++) + { + if(IF_HOM(qn, *bub)) continue; + h_a = hits->a.a + (hits->idx.a[qn]>>32); + h_occ = (uint32_t)(hits->idx.a[qn]); + + for (k = 1, l = 0; k <= h_occ; ++k) ///same qn + { + if (k == h_occ || ((h_a[k].e<<1)>>shif) != ((h_a[l].e<<1)>>shif)) //same tn + { + tn = ((h_a[l].e<<1)>>shif); + if(!IF_HOM(tn, *bub)) + { + append_trans_hits(idx, link, bub, dis, h_a+l, k-l, hits->occ.a, ref, ta, qn, tn); + } + l = k; + } + } + } + + radix_sort_u_trans_m(ta->a, ta->a + ta->n); + + for (k = 1, l = 0, m = 0; k <= ta->n; ++k) + { + if (k == ta->n || (ta->a[k].qn != ta->a[l].qn || ta->a[k].tn != ta->a[l].tn)) + { + w = merge_u_trans_list(ta->a + l, k - l); + if(w != 0) + { + ta->a[m] = ta->a[l]; + ta->a[m].nw = w; + ta->a[m].occ = 0; + m++; + } + l = k; + } + } + ta->n = m; + + kt_u_trans_t_idx(ta, idx->ug->g->n_seq); + fprintf(stderr, "[M::%s::%.3f] \n", __func__, yak_realtime()-index_time); +} + +void print_kv_weight(kv_u_trans_t *ta, int8_t *s) +{ + uint32_t i; + // u_trans_t *e = NULL; + fprintf(stderr, "\n[M::%s]\n", __func__); + fprintf(stderr, "*********ta->n: %u\n", (uint32_t)ta->n); + for (i = 0; i < ta->n; i++) + { + fprintf(stderr, "+s-utg%.6ul(s:%d)\td-utg%.6ul(s:%d)\tw-%f\n", + ta->a[i].qn+1, s[ta->a[i].qn], ta->a[i].tn+1, s[ta->a[i].tn], ta->a[i].nw); + /** + get_u_trans_spec(ta, ta->a[i].tn, ta->a[i].qn, &e, NULL); + if(e) + { + fprintf(stderr, "-d-utg%.6ul->s-utg%.6ul: %f\n", e->qn+1, e->tn+1, e->nw); + } + else + { + fprintf(stderr, "ERROR"); + } + **/ + } +} + +void print_debug_hc_links(ha_ug_index* idx, bubble_type* bub, hc_links* lk, kv_u_trans_t *ta, kvec_pe_hit* hits) +{ + uint64_t k, len = 0, occ = 0, shif = 64 - idx->uID_bits, beg, end; + hc_edge *e = NULL; + for (k = 0; k < hits->a.n; ++k) + { + beg = ((hits->a.a[k].s<<1)>>shif); + end = ((hits->a.a[k].e<<1)>>shif); + if(beg == end) continue; + if(IF_HOM(beg, *bub)) continue; + if(IF_HOM(end, *bub)) continue; + len += (hits->a.a[k].len>>32) + ((uint32_t)hits->a.a[k].len); + occ++; + } + + fprintf(stderr, "# total Hi-C aligned bases: %lu\n", len); + fprintf(stderr, "# total Hi-C aligned pairs: %lu\n", occ); + for (k = 0; k < ta->n; k++) + { + e = get_hc_edge(lk, ta->a[k].qn, ta->a[k].tn, 0); + fprintf(stderr, "s-utg%.6ul\td-utg%.6ul\tD:%lu\tW:%f\n", + ta->a[k].qn+1, ta->a[k].tn+1, e->dis == (uint64_t)-1? (uint64_t)-1 : e->dis>>3, ta->a[k].nw); + } +} +void renew_kv_u_trans(kv_u_trans_t *ta, hc_links *lk, kvec_pe_hit* hits, kv_u_trans_t *ref, +ha_ug_index* idx, bubble_type* bub, int8_t *s, mc_gg_status *sa, uint32_t ignore_dis) +{ + uint64_t k, i, m, is_comples_weight = 0; + trans_idx dis; + kv_init(dis); + if(bub->round_id > 0 && ignore_dis == 0) + { + is_comples_weight = get_trans_rate_function_advance(idx, hits, lk, bub, NULL, s, sa, &dis); + } + + for (i = 0; i < lk->a.n; i++) + { + for (k = m = 0; k < lk->a.a[i].e.n; k++) + { + if(lk->a.a[i].e.a[k].del) continue; + lk->a.a[i].e.a[m] = lk->a.a[i].e.a[k]; + lk->a.a[i].e.a[m].weight = 0; + lk->a.a[i].e.a[m].occ = 0; + m++; + } + lk->a.a[i].e.n = m; + } + + if(hits->idx.n == 0) idx_hc_links(hits, idx, bub); + + weight_kv_u_trans(idx, hits, lk, bub, ta, is_comples_weight == 1? &dis : NULL, asm_opt.flag&HA_F_USKEW?0:1); + // if(bub->round_id == bub->n_round-1) + // { + // print_debug_hc_links(idx, bub, lk, ta, hits); + // } + // adjust_weight_kv_u_trans(idx, hits, lk, bub, ta, ref, is_comples_weight == 1? &dis : NULL); + adjust_weight_kv_u_trans_advance(idx, hits, lk, bub, ta, ref, is_comples_weight == 1? &dis : NULL); + kv_destroy(dis); + // print_kv_weight(ta); +} + +void print_kv_u_trans(kv_u_trans_t *ta, hc_links* lk, int8_t *s) +{ + uint32_t i; + u_trans_t *p = NULL; + hc_edge *e = NULL; + + for (i = 0; i < ta->n; i++) + { + p = &(ta->a[i]); + e = get_hc_edge(lk, p->qn, p->tn, 0); + fprintf(stderr, "s-utg%.6ul\tS(%d)\td-utg%.6ul\tS(%d)\trev(%u)\td(%lld)\ttw(%f)\n", + p->qn+1, s[p->qn], p->tn+1, s[p->tn], p->rev, + (e == NULL || e->dis == (uint64_t)-1)? -1 : (long long)(e->dis>>3), p->nw); + } + +} + +ps_t* init_ps_t(uint64_t seed, uint64_t n) +{ + ps_t *s = NULL; CALLOC(s, 1); + s->xs = seed; + CALLOC(s->s, n); + s->n = n; + return s; +} + +void destory_ps_t(ps_t **s) +{ + free((*s)->s); + free((*s)); +} + +uint32_t is_hom_map(uint64_t x, uint32_t len, mc_interval_t *p, uint32_t *p_idx, ha_ug_index* idx) +{ + mc_interval_t *a = NULL; + uint32_t uid, qs, qe, as, ae, occ, k; + uint64_t oLen; + interpr_hit(idx, x, len, &uid, &qs, &qe); + + a = p + p_idx[uid]; + occ = p_idx[uid+1] - p_idx[uid]; + for (k = 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(oLen == 0) continue; + if(oLen > len*0.2) return 1; + } + return 0; +} + +void update_hits(ha_ug_index* idx, kvec_pe_hit* hits, uint8_t *r_het) +{ + ma_ug_t *ug = idx->ug; + asg_t *rg = idx->read_g; + uint32_t k, v, l, offset, l_pos; + asg_t* nsg = ug->g; + ma_utg_t *u = NULL; + mc_interval_t *t = NULL; + kvec_t(mc_interval_t) p; kv_init(p); + kvec_t(uint32_t) p_idx; kv_init(p_idx); + + kv_push(uint32_t, p_idx, 0); + for (v = 0; v < nsg->n_seq; v++) + { + u = &(ug->u.a[v]); + for (k = 1, l = 0, offset = 0, l_pos = 0; k <= u->n; ++k) + { + if (k == u->n || r_het[u->a[k]>>33] != r_het[u->a[l]>>33]) + { + if(r_het[u->a[l]>>33] == N_HET)///only keep hom suregions + { + kv_pushp(mc_interval_t, p, &t); + t->uID = v; + t->hs = r_het[u->a[l]>>33]; + + t->bS = l_pos; + t->bE = offset + rg->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_idx, p.n); + } + + + for (k = 0; k < hits->a.n; ++k) + { + hits->a.a[k].id = (uint64_t)-1; + if(is_hom_map(hits->a.a[k].s, hits->a.a[k].len>>32, p.a, p_idx.a, idx) || + is_hom_map(hits->a.a[k].e, (uint32_t)hits->a.a[k].len, p.a, p_idx.a, idx)) + { + continue; + } + hits->a.a[k].id = 0; + } + + kv_destroy(p); kv_destroy(p_idx); +} + +void verbose_het_stat(bubble_type *bub) +{ + uint64_t i, hetBase = 0, homBase = 0; + for (i = 0; i < bub->ug->g->n_seq; i++) + { + if(IF_HOM(i, *bub)) homBase += bub->ug->g->seq[i].len; + else hetBase += bub->ug->g->seq[i].len; + } + + fprintf(stderr, "[M::stat] # heterozygous bases: %lu; # homozygous bases: %lu\n", hetBase, homBase); +} + +void debug_output_disconnected_hits(ha_ug_index* idx, kv_u_trans_t *ta, kvec_pe_hit *hits, hc_links *link, bubble_type *bub, int8_t *s) +{ + uint32_t k, l, i, m, h_occ; + uint64_t shif = 64 - idx->uID_bits, qn, tn, u_dis; + pe_hit *h_a = NULL; + hc_linkeage *t = NULL; + u_trans_t *p = NULL; + kv_u_trans_t k_trans; + kv_init(k_trans); + + + for (qn = 0; qn < hits->idx.n; qn++) + { + if(IF_HOM(qn, *bub)) continue; + h_a = hits->a.a + (hits->idx.a[qn]>>32); + h_occ = (uint32_t)(hits->idx.a[qn]); + + for (k = 1, l = 0; k <= h_occ; ++k) ///same qn + { + if (k == h_occ || ((h_a[k].e<<1)>>shif) != ((h_a[l].e<<1)>>shif)) //same qn and tn + { + tn = ((h_a[l].e<<1)>>shif); + if(!IF_HOM(tn, *bub) && tn != qn) + { + // t = &(link->a.a[qn]); + // for (i = 0, u_dis = (uint64_t)-1; i < t->e.n; i++) + // { + // if(t->e.a[i].del || t->e.a[i].uID != tn) continue; + // u_dis = (t->e.a[i].dis ==(uint64_t)-1? (uint64_t)-1 : t->e.a[i].dis>>3); + // break; + // } + + // if(u_dis == (uint64_t)-1) + { + kv_pushp(u_trans_t, k_trans, &p); + p->qn = qn; p->tn = tn; p->occ = (k-l); + kv_pushp(u_trans_t, k_trans, &p); + p->qn = tn; p->tn = qn; p->occ = (k-l); + } + } + l = k; + } + } + } + + + radix_sort_u_trans_m(k_trans.a, k_trans.a + k_trans.n); + + for (k = 1, l = 0, m = 0; k <= k_trans.n; ++k) + { + if (k == k_trans.n || k_trans.a[l].qn != k_trans.a[k].qn || k_trans.a[l].tn != k_trans.a[k].tn) //same qn and tn + { + for (i = l, h_occ = 0; i < k; i++) + { + h_occ += k_trans.a[i].occ; + } + + k_trans.a[m] = k_trans.a[l]; + k_trans.a[m].occ = ((uint32_t)-1) - h_occ; + m++; + l = k; + } + } + k_trans.n = m; + + radix_sort_u_trans_occ(k_trans.a, k_trans.a + k_trans.n); + for (i = 0; i < k_trans.n; i++) + { + qn = k_trans.a[i].qn; + tn = k_trans.a[i].tn; + + t = &(link->a.a[qn]); + for (k = 0, u_dis = (uint64_t)-1; k < t->e.n; k++) + { + if(t->e.a[k].del || t->e.a[k].uID != tn) continue; + u_dis = (t->e.a[k].dis ==(uint64_t)-1? (uint64_t)-1 : t->e.a[k].dis>>3); + break; + } + get_u_trans_spec(ta, qn, tn, &p, NULL); + + fprintf(stderr, "s-utg%.6lul[hap-%d]<--->d-utg%.6lul[hap-%d](occ: %u, ", + qn + 1, s[qn], tn + 1, s[tn], ((uint32_t)-1) - k_trans.a[i].occ); + if(p) fprintf(stderr, "weight: %f", p->nw); + else fprintf(stderr, "weight: NA"); + fprintf(stderr, "):(dis-%lu)\n", u_dis); + } + + // fprintf(stderr, "########hits########\n"); + // char dir[2] = {'+', '-'}; + // for (k = 0; k < hits->a.n; ++k) + // { + // fprintf(stderr, "%c\tutg%.6dl(len-%u)\t%lu\t%c\tutg%.6dl(len-%u)\t%lu\ti:%lu\n", + // dir[hits->a.a[k].s>>63], (int)((hits->a.a[k].s<<1)>>shif)+1, + // idx->ug->g->seq[((hits->a.a[k].s<<1)>>shif)].len, hits->a.a[k].s&idx->pos_mode, + // dir[hits->a.a[k].e>>63], (int)((hits->a.a[k].e<<1)>>shif)+1, + // idx->ug->g->seq[((hits->a.a[k].e<<1)>>shif)].len, hits->a.a[k].e&idx->pos_mode, + // hits->a.a[k].id); + // } + kv_destroy(k_trans); +} + +void resolve_tangles_hic(ha_ug_index *idx, bubble_type *bub, kvec_pe_hit *hits, kv_u_trans_t *ta) +{ + uint32_t i, k, l, m, h_occ; + uint64_t shif = 64 - idx->uID_bits, qn, tn; + pe_hit *h_a = NULL; + u_trans_t *p = NULL; + identify_bubbles(idx->ug, bub, idx->t_ch->ir_het, &(idx->t_ch->k_trans)); + ta->idx.n = ta->n = 0; + if(hits->idx.n == 0) idx_hc_links(hits, idx, NULL); + for (qn = 0; qn < hits->idx.n; qn++) + { + h_a = hits->a.a + (hits->idx.a[qn]>>32); + h_occ = (uint32_t)(hits->idx.a[qn]); + + for (k = 1, l = 0; k <= h_occ; ++k) ///same qn + { + if (k == h_occ || ((h_a[k].e<<1)>>shif) != ((h_a[l].e<<1)>>shif)) //same qn and tn + { + tn = ((h_a[l].e<<1)>>shif); + if(tn != qn) + { + kv_pushp(u_trans_t, *ta, &p); + p->qn = qn; p->tn = tn; p->occ = (k-l); + kv_pushp(u_trans_t, *ta, &p); + p->qn = tn; p->tn = qn; p->occ = (k-l); + } + l = k; + } + } + } + radix_sort_u_trans_m(ta->a, ta->a + ta->n); + for (k = 1, l = 0, m = 0; k <= ta->n; ++k) + { + if (k == ta->n || ta->a[l].qn != ta->a[k].qn || ta->a[l].tn != ta->a[k].tn) //same qn and tn + { + for (i = l, h_occ = 0; i < k; i++) + { + h_occ += ta->a[i].occ; + } + + qn = ta->a[l].qn; + tn = ta->a[l].tn; + ta->a[m] = ta->a[l]; + ta->a[m].occ = h_occ; + ta->a[m].nw = (h_occ*SCALL)/(MIN(hits->occ.a[qn], hits->occ.a[tn])); + m++; + l = k; + } + } + ta->n = m; + kt_u_trans_t_idx(ta, idx->ug->g->n_seq); + + resolve_bubble_chain_by_hic(idx, ta, bub); + ta->idx.n = ta->n = 0; +} + + +void print_kv_u_trans_t(kv_u_trans_t *ta, ma_ug_t* ug) +{ + uint32_t i; + u_trans_t *p = NULL; + for (i = 0; i < ta->n; i++) + { + p = &(ta->a[i]); + fprintf(stderr, "q-utg%.6ul\tql(%u)\tqs(%u)\tqe(%u)\tt-utg%.6ul\ttl(%u)\tts(%u)\tte(%u)\trev(%u)\tw(%f)\tf(%u)\n", + p->qn+1, ug->u.a[p->qn].len, p->qs, p->qe, p->tn+1, ug->u.a[p->tn].len, p->ts, p->te, p->rev, p->nw, p->f); + } + fprintf(stderr, "[M::%s::] \n", __func__); +} + +void write_ps_t(ps_t *s, const char *fn) +{ + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.hic.pst.bin", fn); + FILE* fp = fopen(buf, "w"); + + fwrite(&(s->xs), sizeof(s->xs), 1, fp); + fwrite(&(s->n), sizeof(s->n), 1, fp); + fwrite(s->s, sizeof(int8_t), s->n, fp); + + fclose(fp); + free(buf); +} + +int load_ps_t(ps_t **s, const char *fn) +{ + uint64_t flag = 0; + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.hic.pst.bin", fn); + FILE* fp = NULL; + fp = fopen(buf, "r"); + if(!fp) return 0; + CALLOC(*s, 1); + flag += fread(&((*s)->xs), sizeof((*s)->xs), 1, fp); + flag += fread(&((*s)->n), sizeof((*s)->n), 1, fp); + MALLOC((*s)->s, (*s)->n); + flag += fread((*s)->s, sizeof(int8_t), (*s)->n, fp); + + fclose(fp); + free(buf); + return 1; +} + +int cmp_kv_u_weight(const void * a, const void * b) +{ + if((*(u_trans_t*)a).nw == (*(u_trans_t*)b).nw) return 0; + return ((*(u_trans_t*)a).nw) > ((*(u_trans_t*)b).nw)?-1:1; +} + +typedef struct{ + uint64_t s, e; +} f_chain_t; + +typedef struct{ + f_chain_t* a; + size_t n, m; + kvec_t(uint64_t) b; + double tw; + uint64_t tov; +} kv_f_chain; + +void insert_dip_chain(kv_f_chain *x, u_trans_t *p, double LenRate) +{ + uint32_t i; + uint64_t ovlp = 0, tLen = MIN(x->tov, p->qe-p->qs); + int64_t dp, old_dp, start = 0; + f_chain_t *t = NULL; + double r; + for (i = 0; i < x->n; i++) + { + ovlp += ((MIN(x->a[i].e, p->qe) > MAX(x->a[i].s, p->qs))? + (MIN(x->a[i].e, p->qe) - MAX(x->a[i].s, p->qs)):0); + } + if(tLen > 0 && ovlp > tLen*LenRate) + { + r = ((double)ovlp)/((double)tLen); + if(r >= 0.75) + { + if(p->nw <= x->tw*0.75) p->del = 1; + } + else + { + if(p->nw <= x->tw*0.5) p->del = 1; + } + } + + if(!p->del) + { + x->tw += p->nw - (((double)ovlp)/((double)(p->qe-p->qs)))*p->nw; + + kv_push(uint64_t, x->b, p->qs<<1); + kv_push(uint64_t, x->b, p->qe<<1|1); + if(x->b.n > 2 && x->b.a[x->b.n-2] < x->b.a[x->b.n-3]) + { + radix_sort_hc64(x->b.a, x->b.a + x->b.n); + } + x->n = 0; x->tov = 0; + for (i = 0, dp = 0, start = 0; i < x->b.n; ++i) + { + old_dp = dp; + ///if a[j] is qe + if (x->b.a[i]&1) + { + --dp; + } + else + { + ++dp; + } + + + if (old_dp < 1 && dp >= 1) ///old_dp < dp, b.a[j] is qs + { + ///case 2, a[j] is qs + start = x->b.a[i]>>1; + } + else if (old_dp >= 1 && dp < 1) ///old_dp > min_dp, b.a[j] is qe + { + kv_pushp(f_chain_t, *x, &t); + t->s = start; t->e = x->b.a[i]>>1; + x->tov += t->e - t->s; + } + } + } +} + +uint32_t get_MAPQ(u_trans_t *a, uint32_t a_n, uint32_t idx, double secondRate) +{ + uint32_t i; + u_trans_t *p = &(a[idx]); + uint64_t ovlp = 0; + double aw = 0; + for (i = 0; i < a_n; i++) + { + if(i == idx) continue; + ovlp = ((MIN(a[i].qe, p->qe) > MAX(a[i].qs, p->qs))? + (MIN(a[i].qe, p->qe) - MAX(a[i].qs, p->qs)):0); + // if(p->qn == 447 && p->tn == 5495) + // { + // fprintf(stderr, "ovlp: %lu, secondRate: %f, len: %u\n", ovlp, secondRate, MIN(a[i].qe - a[i].qs, p->qe - p->qs)); + // } + if(ovlp == 0) continue; + if(ovlp <= (secondRate*MIN(a[i].qe - a[i].qs, p->qe - p->qs))) continue; + + aw += a[i].nw; + } + // if(p->qn == 447 && p->tn == 5495) fprintf(stderr, "aw: %f\n", aw); + aw = aw/p->nw; + // if(p->qn == 447 && p->tn == 5495) fprintf(stderr, "aw: %f\n", aw); + if(aw >= 1) return 16; + if(aw >= 0.75) return 8; + if(aw >= 0.5) return 4; + if(aw >= 0.25) return 2; + return 1; +} + +void filter_kv_u_trans_t(kv_u_trans_t *ta, ma_ug_t* ug, double secondRate) +{ + kv_f_chain x; + memset(&x, 0, sizeof(kv_f_chain)); x.tw = 0; + uint32_t k, i, n; + u_trans_t *a = NULL; + for (k = 0; k < ta->idx.n; k++) + { + a = u_trans_a(*ta, k); + n = u_trans_n(*ta, k); + if(n == 0) continue; + qsort(a, n, sizeof(u_trans_t), cmp_kv_u_weight); + x.n = 0; x.tov = 0; x.tw = 0; x.b.n = 0; + for (i = 0; i < n; i++) + { + if(a[i].del) continue; + insert_dip_chain(&x, &(a[i]), secondRate); + } + } + free(x.a); free(x.b.a); + kt_u_trans_t_idx(ta, ug->g->n_seq); + kt_u_trans_t_simple_symm(ta, ug->g->n_seq, 0); + + + /** + for (k = 0; k < ta->idx.n; k++) + { + a = u_trans_a(*ta, k); + n = u_trans_n(*ta, k); + if(n == 0) continue; + // radix_sort_k_trans_qs(a, a+n); + for (i = 0; i < n; i++) + { + a[i].occ = get_MAPQ(a, n, i, secondRate); + // if(a[i].occ != 1) + // { + // uint32_t debug_i; + // fprintf(stderr, "\nq-utg%.6ul\tt-utg%.6ul\tocc-%u\n", a[i].qn+1, a[i].tn+1, a[i].occ); + + + // for (debug_i = 0; debug_i < n; debug_i++) + // { + // fprintf(stderr, "q-utg%.6ul\tqs(%u)\tqe(%u)\tt-utg%.6ul\tts(%u)\tte(%u)\trev(%u)\tw(%f)\tf(%u)\n", + // a[debug_i].qn+1, a[debug_i].qs, a[debug_i].qe, a[debug_i].tn+1, a[debug_i].ts, + // a[debug_i].te, a[debug_i].rev, a[debug_i].nw, a[debug_i].f); + // } + // } + } + } + + for (k = 0; k < ta->n; k++) + { + if(ta->a[k].del || ta->a[k].qn > ta->a[k].tn) continue; + get_u_trans_spec(ta, ta->a[k].tn, ta->a[k].qn, &r_a, NULL); + a = &(ta->a[k]); + a->occ = r_a->occ = MAX(a->occ, r_a->occ); + } + **/ +} + +uint64_t check_ovlp(f_chain_t *o, uint64_t on, uint64_t qs, uint64_t qe) +{ + uint64_t i, ovlp; + for (i = 0; i < on; i++) + { + ovlp = ((MIN(o[i].e, qe) > MAX(o[i].s, qs))? + (MIN(o[i].e, qe) - MAX(o[i].s, qs)):0); + if(ovlp) return 1; + } + return 0; +} + +void flter_by_cov(ha_ug_index* idx, kvec_pe_hit *hits, int64_t min_dp) +{ + uint64_t i, m, k, l, pos_bits = 64 - idx->uID_bits - 1, uid, pM = ((uint64_t)-1)>>idx->uID_bits, *a = NULL, a_n; + uint32_t s_uid, s_beg, s_end, e_uid, e_beg, e_end; + int64_t dp, old_dp, start = 0; + f_chain_t *t = NULL; + kvec_t(uint64_t) b; kv_init(b); + kvec_t(f_chain_t) x; kv_init(x); + uint64_t *index = NULL; CALLOC(index, idx->ug->u.n); + for (i = 0; i < hits->a.n; i++) + { + interpr_hit(idx, hits->a.a[i].s, hits->a.a[i].len>>32, &s_uid, &s_beg, &s_end); + m = s_uid; m <<= pos_bits; m += s_beg; m <<= 1; kv_push(uint64_t, b, m); + m = s_uid; m <<= pos_bits; m += s_end; m <<= 1; m += 1; kv_push(uint64_t, b, m); + + + interpr_hit(idx, hits->a.a[i].e, (uint32_t)hits->a.a[i].len, &e_uid, &e_beg, &e_end); + m = e_uid; m <<= pos_bits; m += e_beg; m <<= 1; kv_push(uint64_t, b, m); + m = e_uid; m <<= pos_bits; m += e_end; m <<= 1; m += 1; kv_push(uint64_t, b, m); + } + radix_sort_hc64(b.a, b.a + b.n); + for (k = 1, l = 0; k <= b.n; ++k) + { + if (k == b.n || (b.a[k]>>(64 - idx->uID_bits)) != (b.a[l]>>(64 - idx->uID_bits))) + { + uid = (b.a[l]>>(64 - idx->uID_bits)); + a = b.a + l; a_n = k - l; index[uid] = x.n; + for (i = 0, dp = 0, start = 0; i < a_n; ++i) + { + old_dp = dp; + ///if a[j] is qe + if (a[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 = (a[i]&pM)>>1; + } + else if (old_dp >= min_dp && dp < min_dp) ///old_dp > min_dp, b.a[j] is qe + { + kv_pushp(f_chain_t, x, &t); + t->s = start; t->e = (a[i]&pM)>>1; + } + } + + index[uid] |= ((uint64_t)(x.n - index[uid]))<<32; + l = k; + } + } + + + + + for (i = m = 0; i < hits->a.n; i++) + { + interpr_hit(idx, hits->a.a[i].s, hits->a.a[i].len>>32, &s_uid, &s_beg, &s_end); + if(!check_ovlp(x.a+((uint32_t)index[s_uid]), index[s_uid]>>32, s_beg, s_end)) continue; + + interpr_hit(idx, hits->a.a[i].e, (uint32_t)hits->a.a[i].len, &e_uid, &e_beg, &e_end); + if(!check_ovlp(x.a+((uint32_t)index[e_uid]), index[e_uid]>>32, e_beg, e_end)) continue; + hits->a.a[m] = hits->a.a[i]; + m++; + } + + fprintf(stderr, "[M::%s::] # old Hi-C pairs: %lu, # new Hi-C pairs: %lu\n", + __func__, hits->a.n, m); + hits->a.n = m; + + kv_destroy(b); kv_destroy(x); free(index); + +} + +void set_tag_pre_read(uint64_t *r_tag, uint64_t id, uint64_t off, uint64_t pos, ma_hit_t_alloc* sources) +{ + uint64_t i, tn; + ma_hit_t *h = NULL; + if(r_tag[id] == (uint64_t)-1) r_tag[id] = 0; + r_tag[id] += off; + // if(id == 2531247) fprintf(stderr, "***id: %lu, off: %lu, pos: %lu\n", id, off, pos); + for (i = 0; i < (uint64_t)(sources[id].length); i++) + { + h = &(sources[id].buffer[i]); + if(!h->el) continue; + tn = Get_tn((*h)); + if(pos >= Get_qs((*h)) && pos < Get_qe((*h))) + { + // if(tn == 2531247) fprintf(stderr, "###id: %lu, off: %lu, tn: %lu, pos: %lu\n", id, off, tn, pos); + if(r_tag[tn] == (uint64_t)-1) r_tag[tn] = 0; + r_tag[tn] += off; + } + + } +} + +void tag_reads(ha_ug_index* idx, kvec_pe_hit *u_hits, bubble_type* bub, int8_t *s, ma_hit_t_alloc* sources) +{ + kvec_pe_hit *r_hits = get_r_hits_for_trio(u_hits, idx->read_g, idx->ug, bub, idx->uID_bits, idx->pos_mode); + uint64_t *r_tag = NULL, i, k, srid, erid, /**rid, occ, a_occ, **/flag = AMBIGU, cons = 0, incons = 0/**, max, min**/; + ma_utg_t *u = NULL; + ma_ug_t* ug = idx->ug; + int8_t ss, es, sr; + CALLOC(r_tag, idx->read_g->n_seq); + + cons = 0, incons = 0; + memset(r_tag, -1, sizeof(uint64_t)*idx->read_g->n_seq); + for (i = 0; i < r_hits->a.n; i++) + { + srid = get_hit_suid(*r_hits, i); + erid = get_hit_euid(*r_hits, i); + ss = s[r_hits->a.a[i].id>>32]; + es = s[(uint32_t)r_hits->a.a[i].id]; + if(ss == 0 || es == 0) continue; + if((r_hits->a.a[i].id>>32) == ((uint32_t)r_hits->a.a[i].id)) continue; + + set_tag_pre_read(r_tag, srid, es < 0? 1 : ((uint64_t)1<<32), get_hit_spos(*r_hits, i), sources); + set_tag_pre_read(r_tag, erid, ss < 0? 1 : ((uint64_t)1<<32), get_hit_epos(*r_hits, i), sources); + + if(ss == es) cons++; + else incons++; + } + + /** + for (k = 0; k < ug->u.n; k++) + { + if(ug->g->seq[k].del) continue; + u = &(ug->u.a[k]); occ = a_occ = 0; + for (i = 0; i < u->n; i++) + { + rid = u->a[i]>>33; + if(r_tag[rid] == (uint64_t)-1) continue; + max = MAX((r_tag[rid]>>32), ((uint32_t)r_tag[rid])); + min = MIN((r_tag[rid]>>32), ((uint32_t)r_tag[rid])); + ///if(max <= (total*0.7) && max != total) + if(max - min <= max *0.1) + { + fprintf(stderr, "max-%lu, min-%lu\n", max, min); + a_occ++; + } + occ++; + } + if(occ == 0) continue; + if(a_occ > occ*0.85) s[k] = 0, filter++, fprintf(stderr, "k: %lu, a_occ: %lu, occ: %lu\n", k, a_occ, occ); + } + + fprintf(stderr, "[M::%s::] # consistent Hi-C pairs: %lu, # inconsistent Hi-C pairs: %lu, # filter: %lu\n", + __func__, cons, incons, filter); + + memset(r_tag, -1, sizeof(uint64_t)*idx->read_g->n_seq); + for (i = 0; i < r_hits->a.n; i++) + { + srid = get_hit_suid(*r_hits, i); + erid = get_hit_euid(*r_hits, i); + ss = s[r_hits->a.a[i].id>>32]; + es = s[(uint32_t)r_hits->a.a[i].id]; + if(ss == 0 || es == 0) continue; + if((r_hits->a.a[i].id>>32) == ((uint32_t)r_hits->a.a[i].id)) continue; + + set_tag_pre_read(r_tag, srid, es > 0? 1 : ((uint64_t)1<<32), get_hit_spos(*r_hits, i), sources); + set_tag_pre_read(r_tag, erid, ss > 0? 1 : ((uint64_t)1<<32), get_hit_epos(*r_hits, i), sources); + } + **/ + fprintf(stderr, "[M::%s::] # consistent Hi-C pairs: %lu, # inconsistent Hi-C pairs: %lu\n", + __func__, cons, incons); + + cons = 0, incons = 0; + memset(R_INF.trio_flag, AMBIGU, R_INF.total_reads * sizeof(uint8_t)); + for (i = 0; i < ug->g->n_seq; i++) + { + if(ug->g->seq[i].del) continue; + + flag = 0; + if(s[i] == 0) continue; + flag = (s[i] > 0? FATHER:MOTHER); + + u = &ug->u.a[i]; + if(u->m == 0) continue; + for (k = 0; k < u->n; k++) + { + if(r_tag[u->a[k]>>33] == (uint64_t)-1) continue; + if((r_tag[u->a[k]>>33]>>32) == ((uint32_t)r_tag[u->a[k]>>33])) continue; + sr = (r_tag[u->a[k]>>33]>>32) > ((uint32_t)r_tag[u->a[k]>>33])?1:-1; + if(sr == s[i]) + { + R_INF.trio_flag[u->a[k]>>33] = flag; + fprintf(stderr, "*rid: %lu, s[i]: %d, 1-occ: %u, (-1)-occ: %u\n", u->a[k]>>33, s[i], (uint32_t)(r_tag[u->a[k]>>33]>>32), ((uint32_t)r_tag[u->a[k]>>33])); + // cons_occ += (r_tag[u->a[k]>>33]>>32) + ((uint32_t)r_tag[u->a[k]>>33]); + cons++; + } + else + { + // R_INF.trio_flag[u->a[k]>>33] = -flag; + fprintf(stderr, "#rid: %lu, s[i]: %d, 1-occ: %u, (-1)-occ: %u\n", u->a[k]>>33, s[i], (uint32_t)(r_tag[u->a[k]>>33]>>32), ((uint32_t)r_tag[u->a[k]>>33])); + // incons_occ += (r_tag[u->a[k]>>33]>>32) + ((uint32_t)r_tag[u->a[k]>>33]); + incons++; + } + } + } + + free(r_tag); + kv_destroy(r_hits->a); + kv_destroy(r_hits->idx); + kv_destroy(r_hits->occ); + free(r_hits); + fprintf(stderr, "[M::%s::] # consistent reads: %lu, # inconsistent reads: %lu\n", __func__, cons, incons); +} + +void renew_idx_para(ha_ug_index* idx, ma_ug_t* ug) +{ + for (idx->uID_bits=1; (uint64_t)(1<uID_bits)<(uint64_t)ug->u.n; idx->uID_bits++); + idx->pos_bits = 64 - idx->uID_bits - 1; + idx->uID_mode = (((uint64_t)-1) << (64-idx->uID_bits))>>1; + idx->pos_mode = ((uint64_t)-1) >> (64-idx->pos_bits); + idx->rev_mode = ((uint64_t)1) << 63; +} + +uint32_t get_oe_occ(uint32_t qn, uint32_t tn, kvec_pe_hit* hits, ha_ug_index* idx) +{ + uint64_t shif = 64 - idx->uID_bits, occ = 0; + pe_hit *h_a = hits->a.a + (hits->idx.a[qn]>>32); + uint32_t h_occ = (uint32_t)(hits->idx.a[qn]), i; + for (i = 0; i < h_occ; i++) { + if(((h_a[i].s<<1)>>shif)==qn && ((h_a[i].e<<1)>>shif)==tn) occ++; + } + return occ; +} + +void optimize_u_trans(kv_u_trans_t *ovlp, kvec_pe_hit* hits, ha_ug_index* idx) +{ + if(hits->idx.n == 0) idx_hc_links(hits, idx, NULL); + uint64_t i, m, occ; + u_trans_t *x = NULL, *p = NULL; + kv_u_trans_t k_trans; + kv_init(k_trans); kv_init(k_trans.idx); + for (i = 0; i < ovlp->n; i++){ + x = &(ovlp->a[i]); + if(x->qn > x->tn) continue; + if(x->f != RC_2 || x->del) continue;///no need to adjust RC_0/RC_1 + occ = get_oe_occ(x->qn, x->tn, hits, idx) + get_oe_occ(x->tn, x->qn, hits, idx);///how many UL bridging qn and tn + kv_pushp(u_trans_t, k_trans, &p); + (*p) = (*x); p->nw = (x->nw*(1-(((double)(occ<<1))/((double)(hits->occ.a[x->qn]+hits->occ.a[x->tn]))))); + if(p->nw < 0) fprintf(stderr, "ERROR-nw\n"); + if(p->nw == 0) p->nw = x->nw*0.005; + if(p->nw == 0) { + k_trans.n--; + } else { + kv_pushp(u_trans_t, k_trans, &p); + (*p) = k_trans.a[k_trans.n-2]; + p->qn = k_trans.a[k_trans.n-2].tn; p->qs = k_trans.a[k_trans.n-2].ts; p->qe = k_trans.a[k_trans.n-2].te; + p->tn = k_trans.a[k_trans.n-2].qn; p->ts = k_trans.a[k_trans.n-2].qs; p->te = k_trans.a[k_trans.n-2].qe; + } + } + kt_u_trans_t_idx(&k_trans, idx->ug->g->n_seq); + mc_solve(NULL, NULL, &k_trans, idx->ug, idx->read_g, 0.8, R_INF.trio_flag, 1, NULL, 1, NULL, NULL, 1, 0); + for (i = m = 0; i < ovlp->n; i++){ + x = &(ovlp->a[i]); + if(x->del) continue; + if(x->f == RC_2){ + get_u_trans_spec(&k_trans, x->qn, x->tn, &p, NULL); + if(!p) continue; + } + ovlp->a[m++] = ovlp->a[i]; + } + ovlp->n = m; + kt_u_trans_t_idx(ovlp, idx->ug->g->n_seq); + free(hits->idx.a); hits->idx.a = NULL; hits->idx.n = hits->idx.m = 0; + free(hits->occ.a); hits->occ.a = NULL; hits->occ.n = hits->occ.m = 0; + kv_destroy(k_trans); kv_destroy(k_trans.idx); +} + +void round_test(ps_t *s, uint64_t seed, bubble_type *bub, kv_u_trans_t *k_trans, hc_links *link, sldat_t *sl, +ha_ug_index* idx, uint64_t test_block_flip, uint64_t n_perturb) +{ + s->xs = seed; memset(s->s, 0, s->n); + bub->round_id = 0; asm_opt.n_perturb = n_perturb; + + fprintf(stderr, "[M::%s] ----> test_block_flip: %lu, n_perturb: %lu\n", + __func__, test_block_flip, n_perturb); + renew_kv_u_trans(k_trans, link, &sl->hits, &(idx->t_ch->k_trans), idx, bub, s->s, NULL, 0); + mc_solve(NULL, NULL, k_trans, idx->ug, idx->read_g, 0.8, R_INF.trio_flag, + (bub->round_id == 0? 1 : 0), s->s, 1, NULL, test_block_flip?&(idx->t_ch->k_trans):0, 0, 0); + +} + +void debug_round_test(ps_t *s, uint64_t seed, bubble_type *bub, kv_u_trans_t *k_trans, hc_links *link, sldat_t *sl, +ha_ug_index* idx, uint64_t step, uint64_t total) +{ + uint64_t i; + for (i = step; i <= total; i += step) { + fprintf(stderr, "\n"); + round_test(s, seed, bub, k_trans, link, sl, idx, 0, i); + round_test(s, seed, bub, k_trans, link, sl, idx, 1, i); + } + +} + +void prt_hits_noid(ha_ug_index* idx, ma_ug_t* ug, kvec_pe_hit* hits, FILE *fn) +{ + uint64_t k, shif = 64 - idx->uID_bits; + char dir[2] = {'+', '-'}; + for (k = 0; k < hits->a.n; ++k) { + fprintf(fn, "r-%lu-th\t%c\trs-utg%.6d%c\t%lu\t%c\tre-utg%.6d%c\t%lu\n", + hits->a.a[k].id, + dir[hits->a.a[k].s>>63], (int)((hits->a.a[k].s<<1)>>shif)+1, + "lc"[ug->u.a[((hits->a.a[k].s<<1)>>shif)].circ], hits->a.a[k].s&idx->pos_mode, + dir[hits->a.a[k].e>>63], (int)((hits->a.a[k].e<<1)>>shif)+1, + "lc"[ug->u.a[((hits->a.a[k].e<<1)>>shif)].circ], hits->a.a[k].e&idx->pos_mode); + } +} + +void prt_utg_trans(kv_u_trans_t *ta, ma_ug_t* ug, FILE *fn) +{ + uint32_t i; + u_trans_t *p = NULL; + for (i = 0; i < ta->n; i++) { + p = &(ta->a[i]); + fprintf(fn, "utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tw(%f)\tf(%u)\n", + p->qn+1, "lc"[ug->u.a[p->qn].circ], ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], + p->tn+1, "lc"[ug->u.a[p->tn].circ], ug->u.a[p->tn].len, p->ts, p->te, p->nw, p->f); + } +} + + +void prt_kv_u_trans(kv_u_trans_t *ta, hc_links* lk, int8_t *s, FILE *fn) +{ + uint32_t i; + u_trans_t *p = NULL; + hc_edge *e = NULL; + + for (i = 0; i < ta->n; i++) { + p = &(ta->a[i]); + e = get_hc_edge(lk, p->qn, p->tn, 0); + fprintf(fn, "s-utg%.6ul\tS(%d)\td-utg%.6ul\tS(%d)\trev(%u)\td(%lld)\ttw(%f)\n", + p->qn+1, s[p->qn], p->tn+1, s[p->tn], p->rev, + (e == NULL || e->dis == (uint64_t)-1)? -1 : (long long)(e->dis>>3), p->nw); + } +} + + +void prt_bubble_gfa_adv(FILE *fp, bubble_type *bub, const char* utg_pre, const char* bub_pre, const char* chain_pre) +{ + uint32_t i, k, m, *a, n, beg, sink, x; ma_utg_t *p; uint64_t occ; + ma_ug_t *b_ug = bub->b_ug; char name[32], bname[32]; uint8_t *f; CALLOC(f, bub->ug->u.n); + for (i = 0; i < b_ug->u.n; i++) { + p = &b_ug->u.a[i]; + if(p->n == 0) continue; + for (k = occ = 0; k < p->n; k++){ + x = p->a[k]>>33; + get_bubbles(bub, x, &beg, &sink, &a, &n, NULL); + + for (m = 0; m < n; m++) { + occ += bub->ug->u.a[a[m]>>1].n; f[a[m]>>1] = 1; + } + if(beg != (uint32_t)-1 && f[beg>>1] == 0) { + occ += bub->ug->u.a[beg>>1].n; f[beg>>1] = 1; + } + if(sink != (uint32_t)-1 && f[sink>>1] == 0) { + occ += bub->ug->u.a[sink>>1].n; f[sink>>1] = 1; + } + } + + sprintf(name, "%s%.6d%c", chain_pre, i + 1, "lc"[p->circ]); + fprintf(fp, "S\t%s\t*\tLN:i:%lu\n", name, occ); + for (k = 0; k < p->n; k++) { + x = p->a[k]>>33; + sprintf(bname, "%s%.6d", bub_pre, x + 1); + fprintf(fp, "B\t%s\t%c\tcid:i:%s\tsm:%c\n", bname, "+-"[(p->a[k]>>32)&1], name, "01"[xf_bub]); + + get_bubbles(bub, x, &beg, &sink, &a, &n, NULL); + if(beg != (uint32_t)-1) { + fprintf(fp, "U\t%s%.6d%c\t%c\tcid:i:%s\tbid:b:%s\thom:%c\n", + utg_pre, (beg>>1)+1, "lc"[bub->ug->u.a[(beg>>1)].circ], "+-"[beg&1], name, bname, "10"[IF_HOM((beg>>1), *bub)]); + } + + if(sink != (uint32_t)-1) { + fprintf(fp, "U\t%s%.6d%c\t%c\tcid:i:%s\tbid:s:%s\thom:%c\n", + utg_pre, (sink>>1)+1, "lc"[bub->ug->u.a[(sink>>1)].circ], "+-"[sink&1], name, bname, "10"[IF_HOM((sink>>1), *bub)]); + } + for (m = 0; m < n; m++) { + occ += bub->ug->u.a[a[m]>>1].n; + fprintf(fp, "U\t%s%.6d%c\t%c\tcid:i:%s\tbid:c:%s\thom:%c\n", + utg_pre, (a[m]>>1)+1, "lc"[bub->ug->u.a[(a[m]>>1)].circ], "+-"[a[m]&1], name, bname, "10"[IF_HOM((a[m]>>1), *bub)]); + } + } + } + + asg_arc_t* au = NULL; + uint32_t nu, u, v, j; + for (i = 0; i < b_ug->u.n; ++i) { + if(b_ug->u.a[i].m == 0) continue; + if(b_ug->u.a[i].circ) + { + fprintf(fp, "L\t%s%.6dc\t+\t%s%.6dc\t+\t%dM\tL1:i:%d\n", + chain_pre, i+1, chain_pre, i+1, 0, 0); + fprintf(fp, "L\t%s%.6dc\t-\t%s%.6dc\t-\t%dM\tL1:i:%d\n", + chain_pre, i+1, chain_pre, i+1, 0, 0); + } + u = i<<1; + au = asg_arc_a(b_ug->g, u); + nu = asg_arc_n(b_ug->g, u); + for (j = 0; j < nu; j++) + { + if(au[j].del) continue; + v = au[j].v; + fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", + chain_pre, (u>>1)+1, "lc"[b_ug->u.a[u>>1].circ], "+-"[u&1], + chain_pre, (v>>1)+1, "lc"[b_ug->u.a[v>>1].circ], "+-"[v&1], 0, 0); + } + + + u = (i<<1) + 1; + au = asg_arc_a(b_ug->g, u); + nu = asg_arc_n(b_ug->g, u); + for (j = 0; j < nu; j++) + { + if(au[j].del) continue; + v = au[j].v; + fprintf(fp, "L\t%s%.6d%c\t%c\t%s%.6d%c\t%c\t%dM\tL1:i:%d\n", + chain_pre, (u>>1)+1, "lc"[b_ug->u.a[u>>1].circ], "+-"[u&1], + chain_pre, (v>>1)+1, "lc"[b_ug->u.a[v>>1].circ], "+-"[v&1], 0, 0); + } + } + + for (i = 0; i < bub->ug->u.n; i++) { + if(f[i]) continue; + fprintf(fp, "U\t%s%.6d%c\t+\tcid:i:*\tbid:c:*\thom:%c\n", + utg_pre, i+1, "lc"[bub->ug->u.a[i].circ], "10"[IF_HOM(i, *bub)]); + } + free(f); +} + + +void prt_debug_hic(const char* o_n, ma_ug_t* ug, ha_ug_index* idx, ug_opt_t *opt, kvec_pe_hit* hits, +kv_u_trans_t *utg_trans, kv_u_trans_t *p_arcs, hc_links* lk, int8_t *s, bubble_type *bub) +{ + char* gfa_name = (char*)malloc(strlen(o_n)+100); FILE *fn = NULL; + + sprintf(gfa_name, "%s.hic.dbg", o_n); + print_debug_gfa(idx->read_g, idx->ug, opt->coverage_cut, gfa_name, opt->sources, opt->ruIndex, + opt->max_hang, opt->min_ovlp, 0, 0, 0); + + if(hits) { + sprintf(gfa_name, "%s.hic.hits.log", o_n); fn = fopen(gfa_name, "w"); + prt_hits_noid(idx, ug, hits, fn); + fclose(fn); + } + + if(utg_trans) { + sprintf(gfa_name, "%s.hic.utg.trans.log", o_n); fn = fopen(gfa_name, "w"); + prt_utg_trans(utg_trans, ug, fn); + fclose(fn); + } + + if(p_arcs) { + sprintf(gfa_name, "%s.hic.parcs.log", o_n); fn = fopen(gfa_name, "w"); + prt_kv_u_trans(p_arcs, lk, s, fn); + fclose(fn); + } + + if(bub) { + sprintf(gfa_name, "%s.bub.noseq.gfa", o_n); fn = fopen(gfa_name, "w"); + prt_bubble_gfa_adv(fn, bub, "utg", "btg", "ctg"); + fclose(fn); + } + + free(gfa_name); + fprintf(stderr, "[M::%s::] done\n", __func__); +} + +int hic_short_align(const enzyme *fn1, const enzyme *fn2, ha_ug_index* idx, ug_opt_t *opt, kvec_pe_hit **rhits) +{ + double index_time = yak_realtime(); + sldat_t sl; + sl.idx = idx; + sl.t_ch = idx->t_ch; + sl.chunk_size = 20000000; + sl.n_thread = asm_opt.thread_num; + sl.total_base = sl.total_pair = 0; + idx->hap_cnt = asm_opt.hap_occ; + kv_init(sl.hits.a); kv_init(sl.hits.idx); kv_init(sl.hits.occ); + + + if(!load_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name)) + { + alignment_worker_pipeline(&sl, fn1, fn2); + write_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name); + } + sl.hits.uID_bits = idx->uID_bits; sl.hits.pos_mode = idx->pos_mode; + + /***debug***/ + if(sl.hits.idx.n == 0) idx_hc_links(&(sl.hits), idx, NULL); + // optimize_u_trans(&(idx->t_ch->k_trans), &sl.hits, idx); + // filter_kv_u_trans_t(&(idx->t_ch->k_trans), idx->ug, 0.5); + /***debug***/ + + // print_kv_u_trans_t(&(idx->t_ch->k_trans), idx->ug); + // flter_by_cov(idx, &sl.hits, 2); + // update_hits(idx, &sl.hits, idx->t_ch->is_r_het); + ///debug_hc_hits_v14(&sl.hits, asm_opt.output_file_name, sl.idx); + ////dedup_hits(&(sl.hits), sl.idx); + ///write_hc_hits_v14(&sl.hits, asm_opt.output_file_name); + + if(asm_opt.misjoin_len > 0/** && (!(asm_opt.ar))**/)//disable it for the UL assembly + { + update_switch_unitig(idx->ug, idx->read_g, &(sl.hits), &(idx->t_ch->k_trans), 10, 20, asm_opt.misjoin_len, 0.15); + renew_idx_para(idx, idx->ug); + } + // print_hits_simp(idx, &sl.hits); + // print_kv_u_trans_t(&(idx->t_ch->k_trans)); + + hc_links link; + init_hc_links(&link, idx->ug->g->n_seq, idx->t_ch); + ///H_partition hap; + bubble_type bub; + kv_u_trans_t k_trans; + kv_init(k_trans); kv_init(k_trans.idx); + ps_t *s = NULL; + mb_nodes_t u; + kv_init(u.bid); kv_init(u.idx); kv_init(u.u); + memset(&bub, 0, sizeof(bubble_type)); + bub.round_id = 0; bub.n_round = asm_opt.n_weight; + + resolve_tangles_hic(idx, &bub, &sl.hits, &k_trans); + measure_distance(idx, idx->ug, &sl.hits, &link, &bub, &(idx->t_ch->k_trans)); + // if((asm_opt.flag & HA_F_VERBOSE_GFA) && load_ps_t(&s, asm_opt.output_file_name)) + // { + // bub.round_id = bub.n_round; + // label_unitigs_sm(s->s, NULL, idx->ug); + // goto skip_flipping; + // } + // print_debug_gfa(idx->read_g, idx->ug, opt->coverage_cut, "hic.phasing", opt->sources, opt->ruIndex, + // opt->max_hang, opt->min_ovlp, 0, 0, 0); + + s = init_ps_t(11, idx->ug->g->n_seq); + // debug_round_test(s, 11, &bub, &k_trans, &link, &sl, idx, 1000, 10000); + for (bub.round_id = 0; bub.round_id < bub.n_round; bub.round_id++) + { + // identify_bubbles(idx->ug, &bub, idx->t_ch->is_r_het, &(idx->t_ch->k_trans)); + renew_kv_u_trans(&k_trans, &link, &sl.hits, &(idx->t_ch->k_trans), idx, &bub, s->s, NULL, 0); + // if(bub.round_id == 0) init_phase(idx, &k_trans, &bub, s); + // update_trans_g(idx, &k_trans, &bub); + /*******************************for debug************************************/ + mc_solve(NULL, NULL, &k_trans, idx->ug, idx->read_g, 0.8, R_INF.trio_flag, + (bub.round_id == 0? 1 : 0), s->s, 1, &bub, + &(idx->t_ch->k_trans), 0, /**(((bub.round_id+1) == bub.n_round)?1:0)**/0); + // mc_solve(NULL, NULL, &k_trans, idx->ug, idx->read_g, 0.8, R_INF.trio_flag, + // (bub.round_id == 0? 1 : 0), s->s, 1, NULL, &(idx->t_ch->k_trans), 0, 0); + /** + if((bub.round_id+1) == bub.n_round) { + prt_debug_hic(asm_opt.output_file_name, idx->ug, idx, opt, &sl.hits, + &(idx->t_ch->k_trans), &k_trans, &link, s->s, &(bub)); + } + **/ + /*******************************for debug************************************/ + label_unitigs_sm(s->s, NULL, idx->ug); + + /*******************************for debug************************************/ + // if(bub.round_id == bub.n_round - 1) + // { + // debug_output_disconnected_hits(idx, &k_trans, &sl.hits, &link, &bub, s->s); + // } + /*******************************for debug************************************/ + /** + init_hic_advance((ha_ug_index*)sl.idx, &sl.hits, &link, &bub, &hap, 0); + reset_H_partition(&hap, (bub.round_id == 0? 1 : 0)); + init_contig_partition(&hap, idx, &bub, &link); + phasing_improvement(&hap, &(hap.g_p), idx, &bub, &link); + label_unitigs(&(hap.g_p), idx->ug); + **/ + } + // write_ps_t(s, asm_opt.output_file_name); + // skip_flipping: + verbose_het_stat(&bub); + + if(rhits) (*rhits) = get_r_hits_order(&sl.hits, idx->uID_bits, idx->pos_mode, idx->read_g, idx->ug, &bub); + + // tag_reads(idx, &sl.hits, &bub, s->s, opt->sources); + + // print_kv_weight(&k_trans, s->s); + + // horder_t *ho = init_horder_t(&sl.hits, idx->uID_bits, idx->pos_mode, idx->read_g, idx->ug, &bub, &(idx->t_ch->k_trans), opt, 3); + + // print_hc_links(&link, 0, &hap); + // print_hits_simp(idx, &sl.hits); + // print_kv_u_trans_t(&(idx->t_ch->k_trans)); + // print_kv_u_trans(&k_trans, &link, s->s); + // print_bubbles(idx->ug, &bub, sl.hits.a.n?&sl.hits:NULL, NULL/**idx->link**/, idx); + // print_hits(idx, &sl.hits, fn1, fn2); + // print_debug_bubble_graph(&bub, idx->ug, asm_opt.output_file_name); + // print_bubble_chain(&bub); + + // destory_contig_partition(&hap); + // destory_horder_t(&ho); + kv_destroy(sl.hits.a); kv_destroy(sl.hits.idx); kv_destroy(sl.hits.occ); + destory_hc_links(&link); + kv_destroy(k_trans); kv_destroy(k_trans.idx); + destory_ps_t(&s); + kv_destroy(u.bid); kv_destroy(u.idx); kv_destroy(u.u); + destory_bubbles(&bub); + return 1; + + + print_bubbles(idx->ug, &bub, sl.hits.a.n?&sl.hits:NULL, &link, idx); + collect_hc_reverse_links(&link, idx->ug, &bub); + normalize_hc_links(&link); + min_cut_t* cut = clean_hap(&link, &bub, idx->ug); + ///print_bubbles(idx->ug, &bub, NULL, &link, idx); + G_partition* gp = clean_bubbles(&link, &bub, cut, idx->ug); + ///print_hc_links(&link); + destory_min_cut_t(cut); free(cut); + destory_G_partition(gp); free(gp); + destory_bubbles(&bub); + + fprintf(stderr, "[M::%s::%.3f] processed %lu pairs; %lu bases\n", __func__, yak_realtime()-index_time, sl.total_pair, sl.total_base); + return 1; +} + +void bp_solve(ug_opt_t *opt, kv_u_trans_t *ref, ma_ug_t *ug, asg_t *sg, bubble_type *bub, double cis_rate) +{ + uint64_t k, i, v, nvx, n[3], nv; u_trans_t *z; + kv_u_trans_t in; memset(&in, 0, sizeof(in)); + ma_utg_t *u = NULL; asg_arc_t *av; double w; + ps_t *s = init_ps_t(11, ug->g->n_seq); + + for (i = 0; i < ug->g->n_seq; i++) { + s->s[i] = 0; + if((ug->g->seq[i].del) || (IF_HOM(i, (*bub)))) { + continue; + } + + u = &ug->u.a[i]; + if(u->m == 0 || u->n == 0) continue; + for (k = n[0] = n[1] = n[2] = 0; k < u->n; k++) { + if(R_INF.trio_flag[u->a[k]>>33] == FATHER) n[1]++; + else if(R_INF.trio_flag[u->a[k]>>33] == MOTHER) n[2]++; + else n[0]++; + } + if(n[1] >= n[2] && n[1] >= n[0]) s->s[i] = 1; + else if(n[2] >= n[1] && n[2] >= n[0]) s->s[i] = -1; + } + + kv_resize(u_trans_t, in, ref->n); + for (k = in.n = 0; k < ref->n; k++) { + if((IF_HOM(ref->a[k].qn, (*bub))) || (IF_HOM(ref->a[k].tn, (*bub))) || ref->a[k].del) { + continue; + } + kv_push(u_trans_t, in, ref->a[k]); + } + + if(cis_rate > 0) { + nvx = ug->g->n_seq<<1; + for (v = 0; v < nvx; v++) { + if((ug->g->seq[v>>1].del) || (IF_HOM((v>>1), (*bub)))) continue; + av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); + for (i = 0; i < nv; i++) { + if((av[i].del) || (av[i].v>>1) == (v>>1) || + (ug->g->seq[av[i].v>>1].del) || (IF_HOM((av[i].v>>1), (*bub)))) { + continue; + } + w = ((double)av[i].ol)*cis_rate; + if(w <= 0) continue; + kv_pushp(u_trans_t, in, &z); + memset(z, 0, sizeof((*z))); + z->f = RC_3; z->nw =-w; z->rev = (v^av[i].v)&1; + z->qn = v>>1; z->tn = av[i].v>>1; + + z->qs = 0; z->qe = sg->seq[z->qn].len; + if(av[i].ol < sg->seq[z->qn].len) { + if(v&1) { + z->qe = z->qs + av[i].ol; + } else { + z->qs = z->qe - av[i].ol; + } + } + + z->ts = 0; z->te = sg->seq[z->tn].len; + if(av[i].ol < sg->seq[z->tn].len) { + if(av[i].v&1) { + z->ts = z->te - av[i].ol; + } else { + z->te = z->ts + av[i].ol; + } + } + } + + } + } + // fprintf(stderr, "[M::%s::] ==> nup::%lu\n", __func__, nup); + clean_u_trans_t_idx_adv(&in, ug, sg); + + mc_solve(NULL, NULL, &in, ug, sg, 0.8, NULL, 0, s->s, 1, bub, ref, 0, 0); + label_unitigs_sm(s->s, NULL, ug); + destory_ps_t(&s); kv_destroy(in); kv_destroy(in.idx); +} + +spg_t *hic_short_pre_align(const enzyme *fn1, const enzyme *fn2, ha_ug_index* idx, ug_opt_t *opt, kvec_pe_hit **rhits) +{ + // double index_time = yak_realtime(); + sldat_t sl; + sl.idx = idx; + sl.t_ch = idx->t_ch; + sl.chunk_size = 20000000; + sl.n_thread = asm_opt.thread_num; + sl.total_base = sl.total_pair = 0; + idx->hap_cnt = asm_opt.hap_occ; + kv_init(sl.hits.a); kv_init(sl.hits.idx); kv_init(sl.hits.occ); + + if(!load_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name)) + { + alignment_worker_pipeline(&sl, fn1, fn2); + fprintf(stderr, "sb0sb\n"); + write_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name); + fprintf(stderr, "sb1sb\n"); + } + sl.hits.uID_bits = idx->uID_bits; sl.hits.pos_mode = idx->pos_mode; + kv_u_trans_t k_trans; + kv_init(k_trans); kv_init(k_trans.idx); + bubble_type bub; + memset(&bub, 0, sizeof(bubble_type)); + bub.round_id = 0; bub.n_round = asm_opt.n_weight; + fprintf(stderr, "sb2sb\n"); + resolve_tangles_hic(idx, &bub, &sl.hits, &k_trans); + fprintf(stderr, "sb3sb\n"); + spg_t *scg = horder_utg(&sl.hits, idx->uID_bits, idx->pos_mode, idx->read_g, idx->ug, &bub, opt); + fprintf(stderr, "sb4sb\n"); + if(rhits){ + CALLOC(*rhits, 1); + (**rhits) = sl.hits; + sl.hits.a.a = NULL; + sl.hits.idx.a = NULL; + sl.hits.occ.a = NULL; + } + kv_destroy(sl.hits.a); kv_destroy(sl.hits.idx); kv_destroy(sl.hits.occ); + kv_destroy(k_trans); kv_destroy(k_trans.idx); + destory_bubbles(&bub); + return scg; +} + +int load_psg_t(psg_t **sg, const char *fn) +{ + uint64_t flag = 0; + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.hic.pst.bin", fn); + FILE* fp = NULL; + fp = fopen(buf, "r"); + if(!fp) return 0; + CALLOC(*sg, 1); + flag += fread(&((*sg)->xs), sizeof((*sg)->xs), 1, fp); + flag += fread(&((*sg)->sg.n), sizeof((*sg)->sg.n), 1, fp); + (*sg)->sg.m = (*sg)->sg.n; + MALLOC((*sg)->sg.a, (*sg)->sg.n); + flag += fread((*sg)->sg.a, sizeof(mc_gg_status), (*sg)->sg.n, fp); + + fclose(fp); + free(buf); + return 1; +} + +void write_psg_t(psg_t *sg, const char *fn) +{ + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.hic.pst.bin", fn); + FILE* fp = fopen(buf, "w"); + + fwrite(&(sg->xs), sizeof(sg->xs), 1, fp); + fwrite(&(sg->sg.n), sizeof(sg->sg.n), 1, fp); + fwrite(sg->sg.a, sizeof(mc_gg_status), sg->sg.n, fp); + + fclose(fp); + free(buf); +} + +psg_t* init_psg_t(uint64_t seed, ma_ug_t* ug, asg_t* rg, ug_opt_t *opt) +{ + psg_t *s = NULL; CALLOC(s, 1); + s->xs = seed; + + kv_gg_status *sa = init_mc_gg_status(ug, rg, opt->coverage_cut, opt->sources, opt->ruIndex, + asm_opt.hom_global_coverage_set?asm_opt.hom_global_coverage:((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE), + asm_opt.polyploidy); + + s->sg = *sa; + free(sa); + return s; +} + +void destory_psg_t(psg_t **s) +{ + free((*s)->sg.a); + free((*s)); +} + +int hic_short_align_poy(const enzyme *fn1, const enzyme *fn2, ha_ug_index* idx, ug_opt_t *opt) +{ + double index_time = yak_realtime(); + sldat_t sl; + kvec_hc_edge back_hc_edge; + kv_init(back_hc_edge.a); + sl.idx = idx; + sl.t_ch = idx->t_ch; + sl.chunk_size = 20000000; + sl.n_thread = asm_opt.thread_num; + sl.total_base = sl.total_pair = 0; + idx->hap_cnt = asm_opt.hap_occ; + kv_init(sl.hits.a); kv_init(sl.hits.idx); kv_init(sl.hits.occ); + + + if(!load_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name)) + { + alignment_worker_pipeline(&sl, fn1, fn2); + write_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name); + } + + hc_links link; + init_hc_links(&link, idx->ug->g->n_seq, idx->t_ch); + ///H_partition hap; + bubble_type bub; + kv_u_trans_t k_trans; + kv_init(k_trans); kv_init(k_trans.idx); + psg_t *s = NULL; + mb_nodes_t u; + kv_init(u.bid); kv_init(u.idx); kv_init(u.u); + memset(&bub, 0, sizeof(bubble_type)); + bub.round_id = 0; bub.n_round = asm_opt.n_weight; + + resolve_tangles_hic(idx, &bub, &sl.hits, &k_trans); + measure_distance(idx, idx->ug, &sl.hits, &link, &bub, &(idx->t_ch->k_trans)); + if((asm_opt.flag & HA_F_VERBOSE_GFA) && load_psg_t(&s, asm_opt.output_file_name)) + { + bub.round_id = bub.n_round; + goto skip_flipping; + } + s = init_psg_t(11, idx->ug, idx->read_g, opt); + for (bub.round_id = 0; bub.round_id < bub.n_round; bub.round_id++) + { + // identify_bubbles(idx->ug, &bub, idx->t_ch->is_r_het, &(idx->t_ch->k_trans)); + renew_kv_u_trans(&k_trans, &link, &sl.hits, &(idx->t_ch->k_trans), idx, &bub, NULL, s->sg.a, 0); + // if(bub.round_id == 0) init_phase(idx, &k_trans, &bub, s); + // update_trans_g(idx, &k_trans, &bub); + /*******************************for debug************************************/ + mc_solve_general(&k_trans, idx->ug->u.n, &(s->sg), asm_opt.polyploidy, 0, 1); + /*******************************for debug************************************/ + + /*******************************for debug************************************/ + // if(bub.round_id == bub.n_round - 1) + // { + // debug_output_disconnected_hits(idx, &k_trans, &sl.hits, &link, &bub, s->s); + // } + /*******************************for debug************************************/ + } + if((asm_opt.flag & HA_F_VERBOSE_GFA)) write_psg_t(s, asm_opt.output_file_name); + + skip_flipping: + verbose_het_stat(&bub); + + if(asm_opt.polyploidy == 2) label_unitigs_sm(NULL, s->sg.a, idx->ug); + + // print_kv_weight(&k_trans); + + // horder_t *ho = init_horder_t(&sl.hits, idx->uID_bits, idx->pos_mode, idx->read_g, idx->ug, &bub, &(idx->t_ch->k_trans), opt, 3); + + ///print_hc_links(&link, 0, &hap); + // print_kv_u_trans(&k_trans, &link, s->s); + + + ///print_bubbles(idx->ug, &bub, sl.hits.a.n?&sl.hits:NULL, idx->link, idx); + ///print_hits(idx, &sl.hits, fn1); + + + ///print_debug_bubble_graph(&bub, idx->ug, asm_opt.output_file_name); + // print_bubble_chain(&bub); + // destory_contig_partition(&hap); + // destory_horder_t(&ho); + kv_destroy(back_hc_edge.a); + kv_destroy(sl.hits.a); + kv_destroy(sl.hits.idx); + kv_destroy(sl.hits.occ); + destory_hc_links(&link); + kv_destroy(k_trans); + kv_destroy(k_trans.idx); + destory_psg_t(&s); + kv_destroy(u.bid); kv_destroy(u.idx); kv_destroy(u.u); + fprintf(stderr, "[M::%s::%.3f] processed %lu pairs; %lu bases\n", __func__, yak_realtime()-index_time, sl.total_pair, sl.total_base); + return 1; +} + +mmhap_t* gen_mmhap_t(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc *src) +{ + uint64_t k, z, hom_cov, het_cov, s, *bs = NULL; uint8_t *ff; mmhap_t *p; + if(asm_opt.hom_global_coverage_set) { + hom_cov = asm_opt.hom_global_coverage; + } else { + hom_cov = ((double)asm_opt.hom_global_coverage)/((double)HOM_PEAK_RATE); + } + het_cov = hom_cov/asm_opt.polyploidy; + CALLOC(ff, rg->n_seq); CALLOC(p, 1); CALLOC(bs, asm_opt.polyploidy+1); + p->h.n = p->h.m = ug->u.n; CALLOC(p->h.a, p->h.n); + for (k = p->a.n = s = 0; k < ug->u.n; k++) { + p->h.a[k].a = p->a.n; + p->h.a[k].n = 0; + p->h.a[k].m = infer_mmhap_copy(ug, rg, src, ff, k, het_cov, asm_opt.polyploidy); + if(p->h.a[k].m == (uint64_t)asm_opt.polyploidy) { + p->h.a[k].n = p->h.a[k].m; s = 1; + } + p->a.n += p->h.a[k].m; bs[p->h.a[k].m] += ug->g->seq[k].len; + } + free(ff); + p->a.m = p->a.n; MALLOC(p->a.a, p->a.n); memset(p->a.a, -1, sizeof((*(p->a.a)))*p->a.n); + if(s) { + for (k = p->a.n = 0; k < ug->u.n; k++) { + if(p->h.a[k].n == p->h.a[k].m) { + for (z = 0; z < p->h.a[k].m; z++) p->a.a[p->h.a[k].a+z] = z; + } + } + } + + for (k = 1; k <= (uint64_t)asm_opt.polyploidy; k++) { + fprintf(stderr, "[M::stat] # %lu-copy bases: %lu\n", k, bs[k]); + } + free(bs); + return p; +} + +bubble_type *gen_mmhap_bub(ma_ug_t* ug, uint8_t *r_het_flag, kv_u_trans_t *ref, mmhap_t *hh) +{ + uint64_t k; + bubble_type *p; CALLOC(p, 1); p->n_round = asm_opt.n_weight; p->round_id = 0; + identify_bubbles(ug, p, r_het_flag, ref); + for (k = 0; k < ug->g->n_seq; k++) { + if(IF_BUB(k, (*p))) continue; + if(IF_HOM(k, (*p))) { + if(hh->h.a[k].n < hh->h.a[k].m) p->index[k] = p->num.n; + } else if(IF_HET(k, (*p))) { + if(hh->h.a[k].n >= hh->h.a[k].m) p->index[k] = (uint32_t)-1; + } + } + return p; +} + +void purge_phase_0(ha_ug_index* idx, hc_links *link, bubble_type *bub, ps_t *s, kvec_pe_hit* hits, kv_u_trans_t *k_trans, uint8_t *del, mmhap_t *hh) +{ + k_trans->idx.n = k_trans->n = 0; hits->idx.n = 0; + for (bub->round_id = 0; bub->round_id < bub->n_round; bub->round_id++) { + renew_kv_u_trans(k_trans, link, hits, &(idx->t_ch->k_trans), idx, bub, s->s, NULL, 1/**0**/); + mc_solve(NULL, NULL, k_trans, idx->ug, idx->read_g, 0.8, R_INF.trio_flag, + (bub->round_id==0?1:0), s->s, 1, bub, &(idx->t_ch->k_trans), 0, + /**(((bub.round_id+1) == bub.n_round)?1:0)**/0); + /*******************************for debug************************************/ + // label_unitigs_sm(s->s, NULL, idx->ug); + } + + uint64_t l[2], k, len; int64_t p; ma_ug_t *ug = idx->ug; + for (k = l[0] = l[1] = 0; k < ug->g->n_seq; k++) { + if((del[k] == 1) || (s->s[k] == 0)) continue; + if(s->s[k] > 0) l[0] += ug->g->seq[k].len; + else l[1] += ug->g->seq[k].len; + } + + p = (l[0]>=l[1])?1:-1; + for (k = len = 0; k < ug->g->n_seq; k++) { + if((del[k] == 1) || (s->s[k] == 0)) { + if((del[k] == 2) || + ((hh->h.a[k].n == hh->h.a[k].m) && (hh->h.a[k].m == ((uint64_t)asm_opt.polyploidy)))) { + len += ug->g->seq[k].len; + } + continue; + } + if(s->s[k] == p) { + del[k] = 2; len += ug->g->seq[k].len; + } else { + del[k] = 1; bub->index[k] = (uint32_t)-1; + } + s->s[k] = 0;///reset + } + fprintf(stderr, "[M::%s::stat] # remaining bases: %lu\n", __func__, len); +} + +void exchange_kv_u_trans_t(kv_u_trans_t *a, kv_u_trans_t *b) +{ + uint64_t k, *ua; u_trans_t *u; + k = a->n; a->n = b->n; b->n = k; + k = a->m; a->m = b->m; b->m = k; + u = a->a; a->a = b->a; b->a = u; + + k = a->idx.n; a->idx.n = b->idx.n; b->idx.n = k; + k = a->idx.m; a->idx.m = b->idx.m; b->idx.m = k; + ua = a->idx.a; a->idx.a = b->idx.a; b->idx.a = ua; +} + +uint64_t cal_ave_ovlp(u_trans_t *a, uint64_t an, double top) +{ + if(!an) return 0; + uint64_t k, len, cut, occ, tot; + for (k = len = 0; k < an; k++) { + len += a[k].qe - a[k].qs; + } + cut = len - (len*top); + for (k = occ = tot = 0; k < an; k++) { + if(a[k].qe - a[k].qs < cut) continue; + occ++; tot += a[k].qe - a[k].qs; + } + if(!occ) { + occ = an; tot = len; + } + return tot/occ; +} + + +void clean_trans_ovlp(bubble_type *bub, kv_u_trans_t *des, kv_u_trans_t *src, asg64_v *srt, ma_ug_t *ug) +{ + uint64_t k, st, i, m = 0, ncut; + for (k = des->n = 0; k < src->n; k++) { + if(IF_HOM(src->a[k].qn, (*bub))) continue; + if(IF_HOM(src->a[k].tn, (*bub))) continue; + kv_push(u_trans_t, *des, src->a[k]); + } + + kv_resize(uint64_t, des->idx, src->idx.n); des->idx.n = src->idx.n; + memset(des->idx.a, 0, des->idx.n*sizeof((*(des->idx.a)))); + for (st = 0, i = 1; i <= des->n; ++i) { + if (i == des->n || des->a[i].qn != des->a[st].qn) { + des->idx.a[des->a[st].qn] = (((uint64_t)st)<<32)|(i-st); m++; + st = i; + } + } + + if(srt && m) { + ncut = 0; kv_resize(uint64_t, *srt, m); + for (k = srt->n = 0; k < des->idx.n; k++) { + if(!((uint32_t)(des->idx.a[k]))) continue; + m = cal_ave_ovlp(des->a+(des->idx.a[k]>>32), ((uint32_t)(des->idx.a[k])), 0.9); + m = ((uint64_t)-1)-m; m <<= 32; m += k; + kv_push(uint64_t, *srt, m); + } + radix_sort_b64(srt->a, srt->a + srt->n); + for (k = 0; k < srt->n; k++) { + ncut += trans_sec_cut0(des, srt, (uint32_t)(srt->a[k]), 0.2, 256, ug); + } + + if(ncut) {///renew idx + for (i = k = 0; i < des->n; i++) { + if(des->a[i].del) continue; + des->a[k++] = des->a[i]; + } + des->n = k; + + memset(des->idx.a, 0, des->idx.n*sizeof((*(des->idx.a)))); + for (st = 0, i = 1; i <= des->n; ++i) { + if (i == des->n || des->a[i].qn != des->a[st].qn) { + des->idx.a[des->a[st].qn] = (((uint64_t)st)<<32)|(i-st); m++; + st = i; + } + } + } + } +} + +void purge_phase(ha_ug_index* idx, mmhap_t *hh, uint64_t hapid, uint64_t max_round, hc_links *link, kvec_pe_hit* hits, +bubble_type *bub, ps_t *s, kv_u_trans_t *k_trans, uint8_t *del, uint32_t *bidx, kv_u_trans_t *ref, asg64_v *srt) +{ + uint64_t k, len; uint32_t *bm; + ma_ug_t *ug = idx->ug; + if(max_round <= 0) { + for (k = 0; k < ug->g->n_seq; k++) { + if(hh->h.a[k].n >= hh->h.a[k].m) continue; + hh->a.a[hh->h.a[k].a+hh->h.a[k].n] = hapid; + hh->h.a[k].n++; + } + return; + } + + for (k = 0; k < ug->g->n_seq; k++) { + del[k] = 0; s->s[k] = 0; + if(hh->h.a[k].n >= hh->h.a[k].m) {///all haplotypes have been set + bub->index[k] = (uint32_t)-1; del[k] = 1; + } else { + if(IF_HOM(k, (*bub))) bub->index[k] = bub->num.n; + } + bidx[k] = bub->index[k]; + } + bm = bub->index; bub->index = bidx; bidx = bm; + + kv_resize(u_trans_t, *ref, idx->t_ch->k_trans.n); ref->n = idx->t_ch->k_trans.n; + memcpy(ref->a, idx->t_ch->k_trans.a, ref->n*sizeof((*(ref->a)))); + kv_resize(uint64_t, ref->idx, idx->t_ch->k_trans.idx.n); ref->idx.n = idx->t_ch->k_trans.idx.n; + memcpy(ref->idx.a, idx->t_ch->k_trans.idx.a, ref->idx.n*sizeof((*(ref->idx.a)))); + exchange_kv_u_trans_t(ref, &(idx->t_ch->k_trans)); + + for (k = 0; k < max_round; k++) { + clean_trans_ovlp(bub, &(idx->t_ch->k_trans), ref, ((k+1)g->n_seq; k++) { + if(del[k] != 2) { + if((hh->h.a[k].n == hh->h.a[k].m) && (hh->h.a[k].m == ((uint64_t)asm_opt.polyploidy))) { + len += ug->g->seq[k].len; + } + continue; + } + assert(hh->h.a[k].n < hh->h.a[k].m); + hh->a.a[hh->h.a[k].a+hh->h.a[k].n] = hapid; + hh->h.a[k].n++; len += ug->g->seq[k].len; + } + fprintf(stderr, "[M::%s::stat] # hap%lu bases: %lu\n", __func__, hapid+1, len); + + bm = bub->index; bub->index = bidx; bidx = bm; + exchange_kv_u_trans_t(ref, &(idx->t_ch->k_trans)); +} + +int hic_short_align_mmhap(const enzyme *fn1, const enzyme *fn2, ha_ug_index* idx, ug_opt_t *opt, kvec_pe_hit **rhits, mmhap_t **rh) +{ + if(rh) (*rh) = NULL; + sldat_t sl; + sl.idx = idx; + sl.t_ch = idx->t_ch; + sl.chunk_size = 20000000; + sl.n_thread = asm_opt.thread_num; + sl.total_base = sl.total_pair = 0; + idx->hap_cnt = asm_opt.hap_occ; + kv_init(sl.hits.a); kv_init(sl.hits.idx); kv_init(sl.hits.occ); + + + if(!load_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name)) { + alignment_worker_pipeline(&sl, fn1, fn2); + write_hc_hits(&sl.hits, idx->ug, asm_opt.output_file_name); + } + sl.hits.uID_bits = idx->uID_bits; sl.hits.pos_mode = idx->pos_mode; + + if(sl.hits.idx.n == 0) idx_hc_links(&(sl.hits), idx, NULL); + + mmhap_t *hh = gen_mmhap_t(idx->ug, idx->read_g, opt->sources); + bubble_type *bub = gen_mmhap_bub(idx->ug, idx->t_ch->ir_het, &(idx->t_ch->k_trans), hh); + hc_links link; init_hc_links(&link, idx->ug->g->n_seq, idx->t_ch); + measure_distance(idx, idx->ug, &sl.hits, &link, bub, &(idx->t_ch->k_trans)); + kv_u_trans_t k_trans; kv_init(k_trans); kv_init(k_trans.idx); + ps_t *s = init_ps_t(11, idx->ug->g->n_seq); ///H_partition hap; + uint64_t k, n_hap = asm_opt.polyploidy; asg64_v srt; kv_init(srt); + uint8_t *ff; CALLOC(ff, idx->ug->g->n_seq); + uint32_t *bidx; MALLOC(bidx, idx->ug->g->n_seq); + kv_u_trans_t r_trans_buf; kv_init(r_trans_buf); kv_init(r_trans_buf.idx); + + for (k = 0; k < n_hap; k++) { + purge_phase(idx, hh, k, ((n_hap>k)?(n_hap-k-1):(0)), &link, &sl.hits, bub, s, &k_trans, ff, bidx, &r_trans_buf, &srt); + } + if(rh) (*rh) = hh; + + // if(rhits) (*rhits) = get_r_hits_order(&sl.hits, idx->uID_bits, idx->pos_mode, idx->read_g, idx->ug, &bub); + + kv_destroy(sl.hits.a); kv_destroy(sl.hits.idx); kv_destroy(sl.hits.occ); + destory_hc_links(&link); + kv_destroy(k_trans); kv_destroy(k_trans.idx); + destory_ps_t(&s); destory_bubbles(bub); free(bub); + kv_destroy(srt); free(ff); free(bidx); + kv_destroy(r_trans_buf); kv_destroy(r_trans_buf.idx); + return 1; +} + + +void hic_analysis(ma_ug_t *ug, asg_t* read_g, trans_chain* t_ch, ug_opt_t *opt, mmhap_t **rh, kvec_pe_hit **rhits) +{ + ug_index = NULL; + int exist = (asm_opt.load_index_from_disk? + load_hc_pt_index(&ug_index, ug, asm_opt.output_file_name) : 0); + if(exist == 0) ug_index = build_unitig_index(ug, asm_opt.hic_mer_length, asm_opt.hap_occ, 0, asm_opt.thread_num); + if(exist == 0) write_hc_pt_index(ug_index, asm_opt.output_file_name); + ug_index->ug = ug; + ug_index->read_g = read_g; + ug_index->t_ch = t_ch; + ///test_unitig_index(ug_index, ug); + if(!rh) hic_short_align(asm_opt.hic_reads[0], asm_opt.hic_reads[1], ug_index, opt, rhits); + else hic_short_align_mmhap(asm_opt.hic_reads[0], asm_opt.hic_reads[1], ug_index, opt, rhits, rh); + // else hic_short_align_poy(asm_opt.hic_reads[0], asm_opt.hic_reads[1], ug_index, opt); + + + destory_hc_pt_index(ug_index);free(ug_index); +} + +uint64_t ug_occ_hap_w(uint64_t is, uint64_t ie, ma_utg_t *u) +{ + uint64_t l, i, us, ue, occ; + for (i = l = occ = 0; i < u->n; i++) { + us = l; ue = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); + if(is <= us && ie >= ue) { + if((R_INF.trio_flag[u->a[i]>>33] == FATHER) || (R_INF.trio_flag[u->a[i]>>33] == MOTHER)) { + occ++; + } + } + if(us >= ie) break; + l += (uint32_t)u->a[i]; + } + return occ; +} + +void trio_phasing_refine(ma_ug_t *iug, asg_t* sg, kv_u_trans_t *ref, ug_opt_t *opt) +{ + ma_ug_t *ug = copy_untig_graph(iug); uint8_t *bf = NULL; + uint64_t ug_n0 = ug->g->n_seq, k, i, ul, cis_n, trans_n, w_n, tot_hap, tot_r, frid, mrid, flag; + kv_u_trans_t in; memset(&in, 0, sizeof(in)); ma_utg_t *p; u_trans_t *z; int64_t fh, mh; + bubble_type *bub = gen_bubble_chain(sg, ug, opt, &bf, 0); free(bf); + clean_u_trans_t_idx_filter_adv(ref, ug, sg, 0.95, 0); + + ///update ug itself + ul = FATHER; frid = ug->g->n_seq; asg_seq_set(ug->g, frid, ul, 0); + kv_pushp(ma_utg_t, ug->u, &p); memset(p, 0, sizeof((*p))); + p->s = 0; p->start = UINT32_MAX; p->end = UINT32_MAX; p->len = ul, p->n = p->m = 1; p->circ = 1; + kv_roundup32(p->m); p->a = (uint64_t*)malloc(8 * p->m); + p->a[0] = UINT32_MAX; p->a[0] <<= 32; p->a[0] |= ul; + + ul = MOTHER; mrid = ug->g->n_seq; asg_seq_set(ug->g, mrid, ul, 0); + kv_pushp(ma_utg_t, ug->u, &p); memset(p, 0, sizeof((*p))); + p->s = 0; p->start = UINT32_MAX; p->end = UINT32_MAX; p->len = ul, p->n = p->m = 1; p->circ = 1; + kv_roundup32(p->m); p->a = (uint64_t*)malloc(8 * p->m); + p->a[0] = UINT32_MAX; p->a[0] <<= 32; p->a[0] |= ul; + + free(ug->g->idx); ug->g->idx = 0; ug->g->is_srt = 0; asg_cleanup(ug->g); + + ///update bubble + REALLOC(bub->index, ug->g->n_seq); + for (k = ug_n0; k < ug->g->n_seq; k++) bub->index[k] = bub->f_bub+1; + + bub->b_s_idx.n = ug->g->n_seq; kv_resize(uint64_t, bub->b_s_idx, ug->g->n_seq); + for (k = ug_n0; k < bub->b_s_idx.m; k++) bub->b_s_idx.a[k] = (uint64_t)-1; + + ///check if a node has haplotype markers + CALLOC(bf, ug->g->n_seq); + for (k = cis_n = tot_hap = tot_r = 0; k < ug_n0; k++) { + if(ug->g->seq[k].del) continue; + p = &(ug->u.a[k]); tot_r += p->n; + if(p->n == 0 || p->m == 0) continue; + for (i = fh = mh = 0; i < p->n; i++) { + if(R_INF.trio_flag[p->a[i]>>33] == FATHER) { + tot_hap++; fh = 1; + } else if(R_INF.trio_flag[p->a[i]>>33] == MOTHER) { + tot_hap++; mh = 1; + } + if((R_INF.trio_flag[p->a[i]>>33] == FATHER) || (R_INF.trio_flag[p->a[i]>>33] == MOTHER)) { + tot_hap++; bf[k] = 1; + } + } + if(fh > 0) { + bf[k] = 1; cis_n+=2; + } + if(mh > 0) { + bf[k] = 1; cis_n+=2; + } + } + for (; k < ug->g->n_seq; k++) bf[k] = 1;///for father/mother nodes + + + ///update trans overlaps + kv_pushp(u_trans_t, *ref, &z); memset(z, 0, sizeof((*z))); + z->f = RC_2; z->nw = (DBL_MAX/2); z->rev = 0; + z->qn = ug_n0; z->tn = ug_n0+1; z->del = 0; + z->qs = 0; z->qe = ug->g->seq[z->qn].len; + z->ts = 0; z->te = ug->g->seq[z->tn].len; + + kv_pushp(u_trans_t, *ref, &z); memset(z, 0, sizeof((*z))); + z->f = RC_2; z->nw = (DBL_MAX/2); z->rev = 0; + z->qn = ug_n0+1; z->tn = ug_n0; z->del = 0; + z->qs = 0; z->qe = ug->g->seq[z->qn].len; + z->ts = 0; z->te = ug->g->seq[z->tn].len; + + kt_u_trans_t_idx(ref, ug->g->n_seq); + // clean_u_trans_t_idx_adv(ref, ug, sg); + // clean_u_trans_t_idx_filter_adv(ref, ug, sg); + + ///gen all links + for (k = trans_n = 0; k < ref->n; k++) { + if(ref->a[k].del) continue; + if((IF_HOM(ref->a[k].qn, (*bub))) || (IF_HOM(ref->a[k].tn, (*bub)))) continue; + ///disable bf + // if((!bf[ref->a[k].qn]) || (!bf[ref->a[k].tn])) continue; + trans_n++; + } + kv_resize(u_trans_t, in, (trans_n+cis_n)); + + for (k = in.n = 0; k < ref->n; k++) { + if(ref->a[k].del) continue; + if((IF_HOM(ref->a[k].qn, (*bub))) || (IF_HOM(ref->a[k].tn, (*bub)))) continue; + ///disable bf + // if((!bf[ref->a[k].qn]) || (!bf[ref->a[k].tn])) continue; + + kv_pushp(u_trans_t, in, &z); memset(z, 0, sizeof((*z))); w_n = 0; + if((ref->a[k].qn < ug_n0) && (ref->a[k].tn < ug_n0)) { + w_n += ug_occ_hap_w(ref->a[k].qs, ref->a[k].qe, &(ug->u.a[ref->a[k].qn])) + + ug_occ_hap_w(ref->a[k].ts, ref->a[k].te, &(ug->u.a[ref->a[k].tn])); + w_n += ug_occ_w(ref->a[k].qs, ref->a[k].qe, &(ug->u.a[ref->a[k].qn])) + + ug_occ_w(ref->a[k].ts, ref->a[k].te, &(ug->u.a[ref->a[k].tn])); + } else { + w_n += tot_hap + tot_r; + } + w_n >>= 1;///wn/4 + (*z) = ref->a[k]; z->nw = ((w_n)?(w_n):(1)); + } + + for (k = 0; k < ug_n0; k++) { + if(!bf[k]) continue; + p = &(ug->u.a[k]); + if(p->n == 0 || p->m == 0) continue; + fh = mh = 0; + for (i = 0; i < p->n; i++) { + if(R_INF.trio_flag[p->a[i]>>33] == FATHER) fh--; + if(R_INF.trio_flag[p->a[i]>>33] == MOTHER) mh--; + } + if(fh != 0) { + w_n = frid; + + kv_pushp(u_trans_t, in, &z); memset(z, 0, sizeof((*z))); + z->f = RC_2; z->nw = fh; z->rev = 0; + z->qn = w_n; z->tn = k; z->del = 0; + z->qs = 0; z->qe = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); + z->ts = 0; z->te = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); + + kv_pushp(u_trans_t, in, &z); memset(z, 0, sizeof((*z))); + z->f = RC_2; z->nw = fh; z->rev = 0; + z->qn = k; z->tn = w_n; z->del = 0; + z->qs = 0; z->qe = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); + z->ts = 0; z->te = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); + } + + if(mh != 0) { + w_n = mrid; + + kv_pushp(u_trans_t, in, &z); memset(z, 0, sizeof((*z))); + z->f = RC_2; z->nw = mh; z->rev = 0; + z->qn = w_n; z->tn = k; z->del = 0; + z->qs = 0; z->qe = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); + z->ts = 0; z->te = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); + + kv_pushp(u_trans_t, in, &z); memset(z, 0, sizeof((*z))); + z->f = RC_2; z->nw = mh; z->rev = 0; + z->qn = k; z->tn = w_n; z->del = 0; + z->qs = 0; z->qe = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); + z->ts = 0; z->te = MIN(ug->g->seq[z->qn].len, ug->g->seq[z->tn].len); + } + } + free(bf); + assert(in.n == (trans_n+cis_n)); + kt_u_trans_t_idx(&in, ug->g->n_seq); + // clean_u_trans_t_idx_adv(&in, ug, sg); + + ps_t *s = init_ps_t(11, ug->g->n_seq); s->s[frid] = 1; s->s[mrid] = -1; + mc_solve(NULL, NULL, &in, ug, sg, 0.8, NULL, 0, s->s, 1, bub, ref, 0, 0); + // fprintf(stderr, "[M::%s::] s[frid]::%d, s->s[mrid]::%d\n", __func__, s->s[frid], s->s[mrid]); + if((s->s[frid] != 0) && (s->s[mrid] != 0) && (s->s[frid] != s->s[mrid])) { + memset(R_INF.trio_flag, AMBIGU, R_INF.total_reads * sizeof(uint8_t)); + for (i = 0; i < ug_n0; i++) { + if(ug->g->seq[i].del) continue; + flag = AMBIGU; + if(s->s[i] == 0) continue; + flag = (s->s[i] == s->s[frid]? FATHER:MOTHER); + p = &ug->u.a[i]; + if(p->m == 0) continue; + for (k = 0; k < p->n; k++) R_INF.trio_flag[p->a[k]>>33] = flag; + } + } + + destory_bubbles(bub); free(bub); ma_ug_destroy(ug); + destory_ps_t(&s); kv_destroy(in); kv_destroy(in.idx); +} + +spg_t *hic_pre_analysis(ma_ug_t *ug, asg_t* read_g, trans_chain* t_ch, ug_opt_t *opt, kvec_pe_hit **rhits) +{ + ug_index = NULL; + int exist = (asm_opt.load_index_from_disk? + load_hc_pt_index(&ug_index, ug, asm_opt.output_file_name) : 0); + if(exist == 0) ug_index = build_unitig_index(ug, asm_opt.hic_mer_length, asm_opt.hap_occ, 0, asm_opt.thread_num); + if(exist == 0) write_hc_pt_index(ug_index, asm_opt.output_file_name); + ug_index->ug = ug; + ug_index->read_g = read_g; + ug_index->t_ch = t_ch; + return hic_short_pre_align(asm_opt.hic_reads[0], asm_opt.hic_reads[1], ug_index, opt, rhits); +} + + +void init_ug_idx(ma_ug_t *ug, uint64_t k, uint64_t up_bound, uint64_t low_bound, uint64_t build_idx) +{ + ug_index = NULL; + if(build_idx) + { + ug_index = build_unitig_index(ug, k, up_bound, low_bound, asm_opt.thread_num); + } +} + +void des_ug_idx() +{ + destory_hc_pt_index(ug_index); +} + +uint64_t count_unique_k_mers(char *r, uint64_t len, uint64_t query, uint64_t target, uint64_t *all, uint64_t *found) +{ + if(!ug_index) return 0; + uint64_t i, j, l = 0, skip, *pos_list = NULL, cnt, uID, is_q, k_mer = ug_index->k; + uint64_t x[4], mask = (1ULL<>1)) & mask; + x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift; + x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift; + if (++l >= k_mer) + { + hash = hc_hash_long(x, &skip, k_mer); + if(skip == (uint64_t)-1) continue; + cnt = get_hc_pt1_count((ha_ug_index*)ug_index, hash, &pos_list); + if(cnt <= 0) continue; + + for (j = 0, is_q = 0; j < cnt; j++) + { + uID = (pos_list[j] << 1) >> (64 - ug_index->uID_bits); + if(query == uID) is_q = 1; + if(target == uID) break; + } + + if(is_q) + { + (*found)++; + if(j < cnt) (*all)++; + } + } + + } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; // if there is an "N", restart + } + + return 1; +} + + +typedef struct{ + //[uID_start, uID_end) + uint64_t uID_start; + uint64_t uID_end; + uint64_t u_n; + uint64_t r_n; + uint64_t* r_idx; +} bench_utg; + +typedef struct{ + uint64_t s, e; +}homo_interval; + +typedef struct{ + kvec_t(bench_utg) ug_idx; + uint64_t uID_bits; + uint64_t pos_mode; + hc_links link; + kvec_t(homo_interval) regions; +}bench_idx; + +uint64_t* set_bench_idx(ma_ug_t *ug, asg_t* read_g, uint64_t uID_start, uint64_t uID_end, uint64_t uID_bits, uint64_t r_n) +{ + uint64_t *idx = (uint64_t*)malloc(sizeof(uint64_t)*r_n), i, k; + memset(idx, -1, sizeof(uint64_t)*r_n); + uint64_t rId, ori, start, l; + ma_utg_t *u = NULL; + for (i = uID_start; i < uID_end; i++) + { + u = &(ug->u.a[i]); + if(u->n == 0) continue; + for (k = l = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + ori = u->a[k]>>32&1; + start = l; + l += (uint32_t)u->a[k]; + if(idx[rId] != (uint64_t)-1) + { + idx[rId] = (uint64_t)-1; + } + else + { + idx[rId] = (ori<<63) + ((i<<(64-uID_bits))>>1) + start; + if(ori) idx[rId] = idx[rId] + read_g->seq[rId].len - 1; + } + } + } + + return idx; +} + +void get_r_utg_bench(uint64_t index, bench_idx* idx, ma_ug_t *ug) +{ + + bench_utg* a_list = idx->ug_idx.a; + uint64_t a_n = idx->ug_idx.n; + bench_utg *x = &(a_list[index]), *y = NULL; + uint64_t i, k, t, rev, x_uid, y_uid, y_pos, x_pos, d; + uint64_t rId, ori; + ma_utg_t *u = NULL; + for (i = x->uID_start; i < x->uID_end; i++) + { + u = &(ug->u.a[i]); + x_uid = i; + if(u->n == 0) continue; + for (k = 0; k < u->n; k++) + { + rId = u->a[k]>>33; + ori = u->a[k]>>32&1; + if(x->r_idx[rId] == (uint64_t)-1) continue; + x_pos = x->r_idx[rId] & idx->pos_mode; + + for (t = 0; t < a_n; t++) + { + if(t == index) continue; + y = &(a_list[t]); + if(y->r_idx[rId] == (uint64_t)-1) continue; + rev = 0; + if((y->r_idx[rId]>>63) != ori) rev = 1; + y_uid = (y->r_idx[rId]<<1)>>(64 - idx->uID_bits); + y_pos = y->r_idx[rId] & idx->pos_mode; + if(rev) y_pos = ug->u.a[y_uid].len - y_pos - 1; + ///if(ori) x_pos = ug->u.a[x_uid].len - x_pos - 1, y_pos = ug->u.a[y_uid].len - y_pos - 1; + d = MAX(x_pos, y_pos) - MIN(x_pos, y_pos); + d = (d<<2) + (rev<<1); + if(y_pos > x_pos) d = d + 1; + push_hc_edge(&(idx->link.a.a[x_uid]), y_uid, 1, 0, &d); + if(x_pos != y_pos) d = d ^ 1; + push_hc_edge(&(idx->link.a.a[y_uid]), x_uid, 1, 0, &d); + } + } + } +} + +void hap_ID(bench_idx* idx, uint64_t ID, uint64_t* hapID, uint64_t* uID) +{ + uint64_t i; + (*hapID) = (*uID) = (uint64_t)-1; + for (i = 0; i < idx->ug_idx.n; i++) + { + if(ID >= idx->ug_idx.a[i].uID_start && ID < idx->ug_idx.a[i].uID_end) + { + (*hapID) = i; + (*uID) = ID - idx->ug_idx.a[i].uID_start; + return; + } + } + return; +} + +void print_bench_idx(bench_idx* idx, ma_ug_t *ug) +{ + uint64_t i, k, s_uID, s_hapID, d_uID, d_hapID; + long long x[2] = {1, -1}; + for (i = 0; i < idx->link.a.n; i++) + { + for (k = 0; k < idx->link.a.a[i].e.n; k++) + { + if(idx->link.a.a[i].e.a[k].del) continue; + hap_ID(idx, i, &s_hapID, &s_uID); + hap_ID(idx, idx->link.a.a[i].e.a[k].uID, &d_hapID, &d_uID); + fprintf(stderr, "s-hap%lu-utg%.6d\td-hap%lu-utg%.6d\t%c\t%lld\n", + s_hapID, (int)(s_uID+1), d_hapID, (int)(d_uID+1), + "+-"[!!(idx->link.a.a[i].e.a[k].dis&(uint64_t)2)], + ((long long)(idx->link.a.a[i].e.a[k].dis>>2))*x[idx->link.a.a[i].e.a[k].dis&(uint64_t)1]); + } + } + + +} + +uint64_t get_hic_distance_bench_hap(pe_hit_hap* hit, hc_links* link, bench_idx* idx, ma_ug_t *ug, uint64_t* is_trans) +{ + (*is_trans) = (uint64_t)-1; + uint64_t s_uid, e_uid; + long long s_pos, e_pos; + s_uid = ((get_pe_s(*hit)<<1)>>(64 - idx->uID_bits)); s_pos = get_pe_s(*hit) & idx->pos_mode; + e_uid = ((get_pe_e(*hit)<<1)>>(64 - idx->uID_bits)); e_pos = get_pe_e(*hit) & idx->pos_mode; + if(s_uid == e_uid) + { + (*is_trans) = 0; + return MAX(s_pos, e_pos) - MIN(s_pos, e_pos); + } + + uint64_t s_i, e_i, k, ori; + for (s_i = 0; s_i < idx->ug_idx.n; s_i++) + { + if(s_uid >= idx->ug_idx.a[s_i].uID_start && s_uid < idx->ug_idx.a[s_i].uID_end) break; + } + for (e_i = 0; e_i < idx->ug_idx.n; e_i++) + { + if(e_uid >= idx->ug_idx.a[e_i].uID_start && e_uid < idx->ug_idx.a[e_i].uID_end) break; + } + if(s_i == idx->ug_idx.n || e_i == idx->ug_idx.n) return (uint64_t)-1; + if(s_i == e_i) + { + (*is_trans) = 0; + return (uint64_t)-1; + } + + (*is_trans) = 1; + hc_linkeage* t = &(link->a.a[s_uid]); + long long m_x[2] = {1, -1}, dis; + for (k = 0; k < t->e.n; k++) + { + if(t->e.a[k].del || t->e.a[k].uID != e_uid) continue; + ori = !!(t->e.a[k].dis & (uint64_t)2); + dis = (long long)(t->e.a[k].dis>>2) * m_x[t->e.a[k].dis & (uint64_t)1]; + if(ori) e_pos = ug->u.a[e_uid].len - e_pos - 1; + e_pos = e_pos + dis; + return MAX(s_pos, e_pos) - MIN(s_pos, e_pos); + } + + return (uint64_t)-1; +} + +uint64_t get_hic_distance_bench(pe_hit* hit, hc_links* link, bench_idx* idx, ma_ug_t *ug, uint64_t* is_trans) +{ + (*is_trans) = (uint64_t)-1; + uint64_t s_uid, e_uid; + long long s_pos, e_pos; + s_uid = ((hit->s<<1)>>(64 - idx->uID_bits)); s_pos = hit->s & idx->pos_mode; + e_uid = ((hit->e<<1)>>(64 - idx->uID_bits)); e_pos = hit->e & idx->pos_mode; + if(s_uid == e_uid) + { + (*is_trans) = 0; + return MAX(s_pos, e_pos) - MIN(s_pos, e_pos); + } + + uint64_t s_i, e_i, k, ori; + for (s_i = 0; s_i < idx->ug_idx.n; s_i++) + { + if(s_uid >= idx->ug_idx.a[s_i].uID_start && s_uid < idx->ug_idx.a[s_i].uID_end) break; + } + for (e_i = 0; e_i < idx->ug_idx.n; e_i++) + { + if(e_uid >= idx->ug_idx.a[e_i].uID_start && e_uid < idx->ug_idx.a[e_i].uID_end) break; + } + if(s_i == idx->ug_idx.n || e_i == idx->ug_idx.n) return (uint64_t)-1; + if(s_i == e_i) + { + (*is_trans) = 0; + return (uint64_t)-1; + } + + (*is_trans) = 1; + hc_linkeage* t = &(link->a.a[s_uid]); + long long m_x[2] = {1, -1}, dis; + for (k = 0; k < t->e.n; k++) + { + if(t->e.a[k].del || t->e.a[k].uID != e_uid) continue; + ori = !!(t->e.a[k].dis & (uint64_t)2); + dis = (long long)(t->e.a[k].dis>>2) * m_x[t->e.a[k].dis & (uint64_t)1]; + if(ori) e_pos = ug->u.a[e_uid].len - e_pos - 1; + e_pos = e_pos + dis; + return MAX(s_pos, e_pos) - MIN(s_pos, e_pos); + } + + return (uint64_t)-1; +} + + +void init_bench_idx(bench_idx* idx, asg_t* read_g, ma_ug_t *ug) +{ + uint64_t i, occ; + kv_init(idx->ug_idx); + kv_init(idx->regions); + kv_malloc(idx->ug_idx, ug->occ.n); idx->ug_idx.n = ug->occ.n; + for (idx->uID_bits = 1; (uint64_t)(1<uID_bits)<(uint64_t)ug->u.n; idx->uID_bits++); + idx->pos_mode = ((uint64_t)-1)>>(idx->uID_bits+1); + for (i = occ = 0; i < ug->occ.n; i++) + { + idx->ug_idx.a[i].uID_start = occ; + occ += ug->occ.a[i]; + idx->ug_idx.a[i].uID_end = occ; + idx->ug_idx.a[i].u_n = ug->occ.a[i]; + + idx->ug_idx.a[i].r_n = read_g->n_seq; + idx->ug_idx.a[i].r_idx + = set_bench_idx(ug, read_g, idx->ug_idx.a[i].uID_start, idx->ug_idx.a[i].uID_end, + idx->uID_bits, idx->ug_idx.a[i].r_n); + } + + init_hc_links(&(idx->link), ug->u.n, NULL); + + for (i = 0; i < idx->ug_idx.n; i++) + { + get_r_utg_bench(i, idx, ug); + } +} + +void evaluate_bench_idx_hap(bench_idx* idx, kvec_pe_hit_hap* hits, ma_ug_t *ug) +{ + uint64_t k, distance, is_trans, trans[2]; + kvec_t(uint64_t) buf; + kv_init(buf); + for (k = trans[0] = trans[1] = 0; k < hits->n_u; ++k) + { + distance = get_hic_distance_bench_hap(&(hits->a[k]), &(idx->link), idx, ug, &is_trans); + if(is_trans != (uint64_t)-1) trans[is_trans]++; + if(distance == (uint64_t)-1 || is_trans == (uint64_t)-1) continue; + distance = (distance << 1) + is_trans; + kv_push(uint64_t, buf, distance); + } + + radix_sort_hc64(buf.a, buf.a+buf.n); + + for (k = 0; k < buf.n; k++) + { + fprintf(stderr, "%lu\t%lu\n", buf.a[k]>>1, buf.a[k]&1); + } + /** + uint64_t up_dis = buf.a[(uint64_t)(buf.n*0.99)]>>1, step = 7240; + uint64_t step_s = 0, step_e = step, cnt[2]; + for (k = cnt[0] = cnt[1] = 0; k < buf.n; k++) + { + if(step_s > up_dis) step_e = (buf.a[buf.n-1]>>1) + 1; + if((buf.a[k]>>1) < step_e && (buf.a[k]>>1) >= step_s) + { + cnt[buf.a[k]&1]++; + } + if((buf.a[k]>>1) >= step_e) + { + while (!((buf.a[k]>>1) < step_e && (buf.a[k]>>1) >= step_s)) + { + fprintf(stderr, "i: %lu, step_s: %lu, step_e: %lu, cnt[0]: %lu, cnt[1]: %lu, rate: %f\n", + step_s/step, step_s, step_e, cnt[0], cnt[1], ((double)cnt[1])/(double)(cnt[0] + cnt[1])); + step_s += step; + step_e += step; + cnt[0] = cnt[1] = 0; + } + } + } + + if(cnt[0] > 0 || cnt[1] > 0) + { + fprintf(stderr, "i: %lu, step_s: %lu, step_e: %lu, cnt[0]: %lu, cnt[1]: %lu, rate: %f\n", + step_s/step, step_s, step_e, cnt[0], cnt[1], ((double)cnt[1])/(double)(cnt[0] + cnt[1])); + } + **/ + kv_destroy(buf); +} + + +void evaluate_bench_idx(bench_idx* idx, kvec_pe_hit* hits, ma_ug_t *ug) +{ + uint64_t k, distance, is_trans, trans[2]; + kvec_t(uint64_t) buf; + kv_init(buf); + for (k = trans[0] = trans[1] = 0; k < hits->a.n; ++k) + { + distance = get_hic_distance_bench(&(hits->a.a[k]), &(idx->link), idx, ug, &is_trans); + if(is_trans != (uint64_t)-1) trans[is_trans]++; + if(distance == (uint64_t)-1 || is_trans == (uint64_t)-1) continue; + distance = (distance << 1) + is_trans; + kv_push(uint64_t, buf, distance); + } + + radix_sort_hc64(buf.a, buf.a+buf.n); + + for (k = 0; k < buf.n; k++) + { + fprintf(stderr, "%lu\t%lu\n", buf.a[k]>>1, buf.a[k]&1); + } + /** + uint64_t up_dis = buf.a[(uint64_t)(buf.n*0.99)]>>1, step = 7240; + uint64_t step_s = 0, step_e = step, cnt[2]; + for (k = cnt[0] = cnt[1] = 0; k < buf.n; k++) + { + if(step_s > up_dis) step_e = (buf.a[buf.n-1]>>1) + 1; + if((buf.a[k]>>1) < step_e && (buf.a[k]>>1) >= step_s) + { + cnt[buf.a[k]&1]++; + } + if((buf.a[k]>>1) >= step_e) + { + while (!((buf.a[k]>>1) < step_e && (buf.a[k]>>1) >= step_s)) + { + fprintf(stderr, "i: %lu, step_s: %lu, step_e: %lu, cnt[0]: %lu, cnt[1]: %lu, rate: %f\n", + step_s/step, step_s, step_e, cnt[0], cnt[1], ((double)cnt[1])/(double)(cnt[0] + cnt[1])); + step_s += step; + step_e += step; + cnt[0] = cnt[1] = 0; + } + } + } + + if(cnt[0] > 0 || cnt[1] > 0) + { + fprintf(stderr, "i: %lu, step_s: %lu, step_e: %lu, cnt[0]: %lu, cnt[1]: %lu, rate: %f\n", + step_s/step, step_s, step_e, cnt[0], cnt[1], ((double)cnt[1])/(double)(cnt[0] + cnt[1])); + } + **/ + kv_destroy(buf); +} + +void destory_bench_idx(bench_idx* idx) +{ + uint64_t i; + for (i = 0; i < idx->ug_idx.n; i++) + { + free(idx->ug_idx.a[i].r_idx); + } + kv_destroy(idx->ug_idx); + kv_destroy(idx->regions); + destory_hc_links(&(idx->link)); +} + + +int hic_short_align_bench(const enzyme *fn1, const enzyme *fn2, const char *output_file_name, ha_ug_index* idx) +{ + double index_time = yak_realtime(); + sldat_t sl; + sl.idx = idx; + ///sl.link = NULL; + sl.chunk_size = 20000000; + sl.n_thread = asm_opt.thread_num; + sl.total_base = sl.total_pair = 0; + idx->hap_cnt = asm_opt.hap_occ; + kv_init(sl.hits.a); + fprintf(stderr, "u.n: %d, uID_bits: %lu, pos_bits: %lu\n", (uint32_t)idx->ug->u.n, idx->uID_bits, idx->pos_bits); + + if(!load_hc_hits(&sl.hits, idx->ug, output_file_name)) + { + // kt_pipeline(3, worker_pipeline, &sl, 3); + // dedup_hits(&sl.hits); + alignment_worker_pipeline(&sl, fn1, fn2); + write_hc_hits(&sl.hits, idx->ug, output_file_name); + } + bench_idx bench; + init_bench_idx(&bench, idx->read_g, idx->ug); + ///print_bench_idx(&bench, idx->ug); + evaluate_bench_idx(&bench, &sl.hits, idx->ug); + + destory_bench_idx(&bench); + kv_destroy(sl.hits.a); + fprintf(stderr, "[M::%s::%.3f] processed %lu pairs; %lu bases\n", __func__, yak_realtime()-index_time, sl.total_pair, sl.total_base); + return 1; +} + +void hic_benchmark(ma_ug_t *ug, asg_t* read_g) +{ + char *output_file_name = (char*)calloc(strlen(asm_opt.output_file_name) + 25, 1); + sprintf(output_file_name, "%s.bench", asm_opt.output_file_name); + ug_index = NULL; + int exist = load_hc_pt_index(&ug_index, ug, output_file_name); + if(exist == 0) ug_index = build_unitig_index(ug, asm_opt.hic_mer_length, asm_opt.hap_occ, 0, asm_opt.thread_num); + if(exist == 0) write_hc_pt_index(ug_index, output_file_name); + ug_index->ug = ug; + ug_index->read_g = read_g; + + hic_short_align_bench(asm_opt.hic_reads[0], asm_opt.hic_reads[1], output_file_name, ug_index); + + free(output_file_name); } \ No newline at end of file diff --git a/hic.h b/hic.h index 3e66d6e..0829b3a 100644 --- a/hic.h +++ b/hic.h @@ -1,122 +1,122 @@ -#ifndef __HIC__ -#define __HIC__ - -#define __STDC_LIMIT_MACROS -#include -#include "Overlaps.h" - -#define kdq_clear(q) ((q)->count = (q)->front = 0) -#define kv_malloc(v, s) ((v).n = 0, (v).m = (s), MALLOC((v).a, (s))) -#define RC_0 0 -#define RC_1 1 -#define RC_2 2 -#define RC_3 3 - -hc_edge* get_hc_edge(hc_links* link, uint64_t src, uint64_t dest, uint64_t dir); -hc_edge* push_hc_edge(hc_linkeage* x, uint64_t uID, double weight, int dir, uint64_t* d); -void hic_benchmark(ma_ug_t *ug, asg_t* read_g); - -typedef struct { - double w; - uint32_t id, occ; - ///uint32_t *bid, bid_n; - ma_utg_t *u; - uint64_t l_d, r_d; -}chain_hic_w_type; - -typedef struct { - size_t n, m; - chain_hic_w_type* a; - uint32_t max_bub_id; - uint32_t *chain_idx, u_n; -}chain_hic_warp; - -typedef struct { - long long g_occ, b_occ; - uint64_t id; - uint8_t del; -}chain_w_type; - -typedef struct { - uint32_t* index, round_id, n_round; - ma_ug_t* ug; - kvec_t(uint32_t) list; - kvec_t(uint32_t) num; - kvec_t(uint64_t) pathLen; - kvec_t(uint64_t) b_s_idx; - uint64_t s_bub, f_bub, b_bub, b_end_bub, tangle_bub, cross_bub, mess_bub; - uint32_t check_het; - asg_t *b_g; - ma_ug_t* b_ug; - kvec_t(chain_w_type) chain_weight; - chain_hic_warp c_w; -} bubble_type; - -typedef struct { - int8_t *s; - uint64_t xs; - uint64_t n; -} ps_t; - -typedef struct { - uint64_t s, e, id, len; -} pe_hit; - -typedef struct { - kvec_t(pe_hit) a; - kvec_t(uint64_t) idx; - kvec_t(uint64_t) occ; - uint64_t uID_bits; - uint64_t pos_mode; -} kvec_pe_hit; - -typedef struct{ - kvec_t(uint8_t) vis; - kvec_t(uint64_t) x; - kvec_t(uint64_t) dis; - uint64_t uID_mode, uID_shift, tmp_v, tmp_d; -}pdq; - - - -#define P_het(B) ((B).num.n) -#define M_het(B) ((B).num.n + 1) -// #define IF_BUB(ID, B) ((B).index[(ID)] < (B).num.n) -// #define IF_HET(ID, B) ((B).index[(ID)] == (B).num.n) -// #define IF_HOM(ID, B) ((B).index[(ID)] > (B).num.n) -#define IF_BUB(ID, B) ((B).index[(ID)] < (B).f_bub+1) -#define IF_HET(ID, B) ((B).index[(ID)] == (B).f_bub+1) -#define IF_HOM(ID, B) ((B).index[(ID)] > (B).f_bub+1) -#define Get_bub_num(RECORD) ((RECORD).num.n-1) -void get_bubbles(bubble_type* bub, uint64_t id, uint32_t* beg, uint32_t* sink, uint32_t** a, uint32_t* n, uint64_t* pathBase); -int load_hc_links(hc_links* link, const char *fn); -void write_hc_links(hc_links* link, const char *fn); -void destory_bubbles(bubble_type* bub); -void identify_bubbles(ma_ug_t* ug, bubble_type* bub, uint8_t *r_het_flag, kv_u_trans_t *ref); -void identify_bubbles_recal(asg_t* sg, ma_ug_t* ug, bubble_type* bub, uint8_t *r_het_flag, ma_hit_t_alloc* sources, R_to_U* ruIndex, -kv_u_trans_t *ref); -void identify_bubbles_recal_poy(asg_t* sg, ma_ug_t* ug, bubble_type* bub, uint8_t *r_het_flag, ma_hit_t_alloc* sources, R_to_U* ruIndex, -kv_u_trans_t *ref); -void resolve_bubble_chain_tangle(ma_ug_t* ug, bubble_type* bub); -uint32_t connect_bub_occ(bubble_type* bub, uint32_t root_id, uint32_t check_het); -void get_bub_id(bubble_type* bub, uint32_t root, uint64_t* id0, uint64_t* id1, uint32_t check_het); -void update_bubble_chain(ma_ug_t* ug, bubble_type* bub, uint32_t is_middle, uint32_t is_end); -void set_b_utg_weight_flag(bubble_type* bub, buf_t* b, uint32_t v, uint8_t* vis_flag, uint32_t flag, uint32_t* occ); -void debug_gfa_space(ma_ug_t* ug, hap_cov_t *cov); -void init_ug_idx(ma_ug_t *ug, uint64_t k, uint64_t up_bound, uint64_t low_bound, uint64_t build_idx); -void des_ug_idx(); -uint64_t count_unique_k_mers(char *r, uint64_t len, uint64_t query, uint64_t target, uint64_t *all, uint64_t *found); -void init_pdq(pdq* q, uint64_t utg_num); -void destory_pdq(pdq* q); -uint32_t check_trans_relation_by_path(uint32_t v, uint32_t w, pdq* pqv, uint32_t* path_v, buf_t *resv, -pdq* pqw, uint32_t* path_w, buf_t *resw, asg_t *sg, uint8_t *dest, uint8_t df, uint32_t df_occ, double rate, -long long *dis); -void set_utg_by_dis(uint32_t v, pdq* pq, asg_t *g, kvec_t_u32_warp *res, uint32_t dis); -void dedup_hits(kvec_pe_hit* hits, uint64_t is_dup); -void hic_analysis(ma_ug_t *ug, asg_t* read_g, trans_chain* t_ch, ug_opt_t *opt, mmhap_t **rh, kvec_pe_hit **rhits); -spg_t *hic_pre_analysis(ma_ug_t *ug, asg_t* read_g, trans_chain* t_ch, ug_opt_t *opt, kvec_pe_hit **rhits); -void prt_bubble_gfa_adv(FILE *fp, bubble_type *bub, const char* utg_pre, const char* bub_pre, const char* chain_pre); -void bp_solve(ug_opt_t *opt, kv_u_trans_t *ref, ma_ug_t *ug, asg_t *sg, bubble_type *bub, double cis_rate); -void trio_phasing_refine(ma_ug_t *ug, asg_t* sg, kv_u_trans_t *ta, ug_opt_t *opt); - -#endif +#ifndef __HIC__ +#define __HIC__ + +#define __STDC_LIMIT_MACROS +#include +#include "Overlaps.h" + +#define kdq_clear(q) ((q)->count = (q)->front = 0) +#define kv_malloc(v, s) ((v).n = 0, (v).m = (s), MALLOC((v).a, (s))) +#define RC_0 0 +#define RC_1 1 +#define RC_2 2 +#define RC_3 3 + +hc_edge* get_hc_edge(hc_links* link, uint64_t src, uint64_t dest, uint64_t dir); +hc_edge* push_hc_edge(hc_linkeage* x, uint64_t uID, double weight, int dir, uint64_t* d); +void hic_benchmark(ma_ug_t *ug, asg_t* read_g); + +typedef struct { + double w; + uint32_t id, occ; + ///uint32_t *bid, bid_n; + ma_utg_t *u; + uint64_t l_d, r_d; +}chain_hic_w_type; + +typedef struct { + size_t n, m; + chain_hic_w_type* a; + uint32_t max_bub_id; + uint32_t *chain_idx, u_n; +}chain_hic_warp; + +typedef struct { + long long g_occ, b_occ; + uint64_t id; + uint8_t del; +}chain_w_type; + +typedef struct { + uint32_t* index, round_id, n_round; + ma_ug_t* ug; + kvec_t(uint32_t) list; + kvec_t(uint32_t) num; + kvec_t(uint64_t) pathLen; + kvec_t(uint64_t) b_s_idx; + uint64_t s_bub, f_bub, b_bub, b_end_bub, tangle_bub, cross_bub, mess_bub; + uint32_t check_het; + asg_t *b_g; + ma_ug_t* b_ug; + kvec_t(chain_w_type) chain_weight; + chain_hic_warp c_w; +} bubble_type; + +typedef struct { + int8_t *s; + uint64_t xs; + uint64_t n; +} ps_t; + +typedef struct { + uint64_t s, e, id, len; +} pe_hit; + +typedef struct { + kvec_t(pe_hit) a; + kvec_t(uint64_t) idx; + kvec_t(uint64_t) occ; + uint64_t uID_bits; + uint64_t pos_mode; +} kvec_pe_hit; + +typedef struct{ + kvec_t(uint8_t) vis; + kvec_t(uint64_t) x; + kvec_t(uint64_t) dis; + uint64_t uID_mode, uID_shift, tmp_v, tmp_d; +}pdq; + + + +#define P_het(B) ((B).num.n) +#define M_het(B) ((B).num.n + 1) +// #define IF_BUB(ID, B) ((B).index[(ID)] < (B).num.n) +// #define IF_HET(ID, B) ((B).index[(ID)] == (B).num.n) +// #define IF_HOM(ID, B) ((B).index[(ID)] > (B).num.n) +#define IF_BUB(ID, B) ((B).index[(ID)] < (B).f_bub+1) +#define IF_HET(ID, B) ((B).index[(ID)] == (B).f_bub+1) +#define IF_HOM(ID, B) ((B).index[(ID)] > (B).f_bub+1) +#define Get_bub_num(RECORD) ((RECORD).num.n-1) +void get_bubbles(bubble_type* bub, uint64_t id, uint32_t* beg, uint32_t* sink, uint32_t** a, uint32_t* n, uint64_t* pathBase); +int load_hc_links(hc_links* link, const char *fn); +void write_hc_links(hc_links* link, const char *fn); +void destory_bubbles(bubble_type* bub); +void identify_bubbles(ma_ug_t* ug, bubble_type* bub, uint8_t *r_het_flag, kv_u_trans_t *ref); +void identify_bubbles_recal(asg_t* sg, ma_ug_t* ug, bubble_type* bub, uint8_t *r_het_flag, ma_hit_t_alloc* sources, R_to_U* ruIndex, +kv_u_trans_t *ref); +void identify_bubbles_recal_poy(asg_t* sg, ma_ug_t* ug, bubble_type* bub, uint8_t *r_het_flag, ma_hit_t_alloc* sources, R_to_U* ruIndex, +kv_u_trans_t *ref); +void resolve_bubble_chain_tangle(ma_ug_t* ug, bubble_type* bub); +uint32_t connect_bub_occ(bubble_type* bub, uint32_t root_id, uint32_t check_het); +void get_bub_id(bubble_type* bub, uint32_t root, uint64_t* id0, uint64_t* id1, uint32_t check_het); +void update_bubble_chain(ma_ug_t* ug, bubble_type* bub, uint32_t is_middle, uint32_t is_end); +void set_b_utg_weight_flag(bubble_type* bub, buf_t* b, uint32_t v, uint8_t* vis_flag, uint32_t flag, uint32_t* occ); +void debug_gfa_space(ma_ug_t* ug, hap_cov_t *cov); +void init_ug_idx(ma_ug_t *ug, uint64_t k, uint64_t up_bound, uint64_t low_bound, uint64_t build_idx); +void des_ug_idx(); +uint64_t count_unique_k_mers(char *r, uint64_t len, uint64_t query, uint64_t target, uint64_t *all, uint64_t *found); +void init_pdq(pdq* q, uint64_t utg_num); +void destory_pdq(pdq* q); +uint32_t check_trans_relation_by_path(uint32_t v, uint32_t w, pdq* pqv, uint32_t* path_v, buf_t *resv, +pdq* pqw, uint32_t* path_w, buf_t *resw, asg_t *sg, uint8_t *dest, uint8_t df, uint32_t df_occ, double rate, +long long *dis); +void set_utg_by_dis(uint32_t v, pdq* pq, asg_t *g, kvec_t_u32_warp *res, uint32_t dis); +void dedup_hits(kvec_pe_hit* hits, uint64_t is_dup); +void hic_analysis(ma_ug_t *ug, asg_t* read_g, trans_chain* t_ch, ug_opt_t *opt, mmhap_t **rh, kvec_pe_hit **rhits); +spg_t *hic_pre_analysis(ma_ug_t *ug, asg_t* read_g, trans_chain* t_ch, ug_opt_t *opt, kvec_pe_hit **rhits); +void prt_bubble_gfa_adv(FILE *fp, bubble_type *bub, const char* utg_pre, const char* bub_pre, const char* chain_pre); +void bp_solve(ug_opt_t *opt, kv_u_trans_t *ref, ma_ug_t *ug, asg_t *sg, bubble_type *bub, double cis_rate); +void trio_phasing_refine(ma_ug_t *ug, asg_t* sg, kv_u_trans_t *ta, ug_opt_t *opt); + +#endif diff --git a/hifiasm.1 b/hifiasm.1 index 6f19a24..965f0d6 100644 --- a/hifiasm.1 +++ b/hifiasm.1 @@ -1,589 +1,589 @@ -.TH hifiasm 1 "22 August 2021" "hifiasm-0.16.0 (r369)" "Bioinformatics tools" - -.SH NAME -.PP -hifiasm - haplotype-resolved de novo assembler for PacBio Hifi reads. - -.SH SYNOPSIS - -* Assemble HiFi reads: -.RS 4 -.B hifiasm -.RB [ -o -.IR prefix ] -.RB [ -t -.IR nThreads ] -.RB [ -z -.IR endTrimLen ] -.R [options] -.I input1.fq -.RI [ input2.fq -.R [...]] -.RE - -* Trio binning assembly with yak dumps: -.RS 4 -.B yak count -.B -o -.I paternal.yak -.B -b37 -.RB [ -t -.IR nThreads ] -.RB [ -k -.IR kmerLen ] -.I paternal.fq.gz -.br -.B yak count -.B -o -.I maternal.yak -.B -b37 -.RB [ -t -.IR nThreads ] -.RB [ -k -.IR kmerLen ] -.I maternal.fq.gz -.br -.B hifiasm -.RB [ -o -.IR prefix ] -.RB [ -t -.IR nThreads ] -.R [options] -.B -1 -.I paternal.yak -.B -2 -.I maternal.yak -.I child.hifi.fq.gz -.RE - -.SH DESCRIPTION -.PP -Hifiasm is an ultrafast haplotype-resolved de novo assembler for PacBio -Hifi reads. Unlike most existing assemblers, hifiasm starts from uncollapsed -genome. Thus, it is able to keep the haplotype information as much as possible. -The input of hifiasm is the PacBio Hifi reads in fasta/fastq format, and its -outputs consist of multiple types of assembly graphs in GFA format. - - -.SH OPTIONS - -.SS General options - -.TP 10 -.BI -o \ FILE -Prefix of output files [hifiasm.asm]. For detailed description of all assembly -graphs, please see the -.B OUTPUTS -section of this man-page. - -.TP 10 -.BI -t \ INT -Number of CPU threads used by hifiasm [1]. - -.TP -.BI -h -Show help information. - -.TP -.BI --version -Show version number. - - -.SS Error correction options - -.TP 10 -.BI -k \ INT -K-mer length [51]. This option must be less than 64. - -.TP -.BI -w \ INT -Minimizer window size [51]. - -.TP -.BI -f \ INT -Number of bits for bloom filter; 0 to disable [37]. This bloom filter is used -to filter out singleton k-mers when counting all k-mers. It takes -.RI 2^( INT -3) -bytes of memory. A proper setting saves memory. -.BR -f37 -is recommended for human -assembly. For small genomes, use -.BR -f0 -to disable the initial bloom filter -which takes 16GB memory at the beginning. For genomes much larger -than human, applying -.BR -f38 -or even -.BR -f39 -is preferred to save memory on k-mer counting. - -.TP -.BI -D \ INT -Drop k-mers occurring -.I >FLOAT*coverage -times [5.0]. -Hifiasm discards these high-frequency k-mers -during error correction to reduce running time. -The -.I coverage -is determined automatically -by hifiasm based on k-mer plot, representing -homozygous read coverage. Raising this option -may improve the resolution of repetitive regions -but takes longer time. - -.TP -.BI -N \ INT -Consider up to -.I max(-D*coverage,-N) -overlaps for each oriented read [100]. -The -.I coverage -is determined automatically -by hifiasm based on k-mer plot, representing -homozygous read coverage. Raising this option may -improve the resolution of repetitive regions but -takes longer time. - - -.TP -.BI -r \ INT -Rounds of haplotype-aware error corrections [3]. -This option affects all outputs of hifiasm. -Odd rounds of correction are preferred in practice. - -.TP -.BI -z \ INT -Length of adapters that should be removed [0]. This option remove -.I INT -bases from both ends of each read. -Some old Hifi reads may consist of -short adapters (e.g., 20bp adapter at one end). For such data, trimming short adapters would -significantly improve the assembly quality. - -.TP -.BI --max-kocc \ INT -Employ k-mers occurring < -.IR INT -times to rescue repetitive overlaps [2000]. -This option may improve the resolution of repeats. - -.TP -.BI --hg-size \ INT (k/m/g) -Estimated haploid genome size used for inferring read coverage [auto]. -This option is used to get accurate homozygous read coverage during -error correction. Common suffices are required, for example, 100m or 3g. - -.TP -.BI --min-hist-cnt \ INT -When analyzing the k-mer spectrum, ignore counts below -.IR INT -[5]. For very low coverage of HiFi data, set smaller -value for this option. - -.SS Assembly options - -.TP -.BI -a \ INT -Rounds of assembly graph cleaning [4]. This option is used with -.B -x -and -.BR -y . -Note that unlike -.BR -r , -this option does not affect error corrected reads and all-to-all overlaps. - - -.TP -.BI -m \ INT -Maximal probing distance for bubble popping when generating primary/alternate -contig graphs [10000000]. Bubbles longer than -.I INT -bases will not be popped. For detailed description of these graphs, please see the -.B OUTPUTS -section of this man-page. - -.TP -.BI -p \ INT -Maximal probing distance for bubble popping when generating haplotype-resolved processed unitig graph -without small bubbles [0]. Bubbles longer than -.I INT -bases will not be popped. Small bubbles might be caused by somatic mutations or noise in data. -Please note that hifiasm automatically pops small bubbles based on coverage, -which can be tweaked by -.BR --hom-cov . -For detailed description of this graph, please see the -.B OUTPUTS -section of this man-page. - -.TP -.BI -n \ INT -A unitig is considered small if it is composed of less than -.I INT -reads [3]. Hifiasm may try to remove small unitigs at various steps. - -.TP -.BI -x \ FLOAT1, -y \ FLOAT2 -Max and min overlap drop ratio [0.8, 0.2]. This option is used with -.BR -a . -Given a node -.I N -in the assembly graph, let max(N) -be the length of the longest overlap of -.I N. -Hifiasm iteratively drops overlaps of -.I N -if their length / max(N) -are below a threshold controlled by -.B -x -and -.BR -y . -Hifiasm applies -.B -a -rounds of short overlap removal with an increasing threshold between -.I FLOAT1 -and -.I FLOAT2. - -.TP -.BI -i -Ignore error corrected reads and overlaps saved in -.IR prefix .*.bin -files so that hifiasm will start again from scratch. -Apart from assembly graphs, hifiasm also outputs three binary files -that save all overlap information during assembly step. -With these files, hifiasm can avoid the time-consuming all-to-all overlap calculation step, -and do the assembly directly and quickly. -This might be helpful when users want to get an optimized assembly by multiple rounds of experiments -with different parameters. - -.TP -.BI -u -Disable post-join step for contigs which may improve N50. -The post-join step of hifiasm improves contig N50 but may introduce misassemblies. - -.TP -.BI --hom-cov \ INT -Homozygous read coverage inferred automatically in default. This option affects different types of outputs, -including Hi-C phased assembly and HiFi-only assembly. - -.TP -.BI --pri-range \ INT1[,INT2] -Min and max coverage cutoff of primary contigs. -Keep contigs with coverage in this range at p_ctg.gfa. -Inferred automatically in default. -If -.I INT2 -is not specified, it is set to infinity. -Set -1 to disable. - -.TP -.BI --lowQ \ INT -Output contig regions with >=INT% inconsistency to the bed file -with suffix -.B lowQ.bed -[70]. Set 0 to disable. - - -.TP -.BI --b-cov \ INT -Break contigs at potential misassemblies with INT-fold coverage [-1]. -Work with -.B --m-rate. -Set -1 to disable. - -.TP -.BI --m-rate \ FLOAT -Break contigs with <=FLOAT*coverage exact overlaps [0.75]. -Only work with -.B --b-cov -and -.B --h-cov. - -.TP -.BI --primary -Output a primary assembly and an alternate assembly. -Hifiasm outputs two balanced assemblies and a primary -assembly in default. Enable this option or -.B -l0 -outputs a primary assembly and an alternate assembly. - - -.SS Trio-partition options - -.TP 10 -.BI -1 \ FILE -K-mer dump generated by -.B yak count -from the paternal/haplotype1 reads [] - -.TP -.BI -2 \ FILE -K-mer dump generated by -.B yak count -from the maternal/haplotype2 reads [] - -.TP -.BI -3 \ FILE -List of paternal/haplotype1 read names [] - -.TP -.BI -4 \ FILE -List of maternal/haplotype2 read names [] - -.TP -.BI -c \ INT -Lower bound of the binned k-mer's frequency [2]. When doing trio binning, -a k-mer is said to be differentiating if it occurs >= -.B -d -times in one sample -but occurs < -.B -c -times in the other sample. - -.TP -.BI -d \ INT -Upper bound of the binned k-mer's frequency [5]. When doing trio binning, -a k-mer is said to be differentiating if it occurs >= -.B -d -times in one sample -but occurs < -.B -c -times in the other sample. - -.TP -.BI --t-occ \ INT -Forcedly remove unitig including > -.I INT -unexpected haplotype-specific reads -without considering graph topology [60]. - - -.SS Purge-dups options - -.TP 10 -.BI -l \ INT -Level of purge-dup. 0 to disable purge-dup, 1 to only purge contained haplotigs, -2 to purge all types of haplotigs, 3 to purge all types of haplotigs in most aggressive way. -In default, [3] for non-trio assembly, [0] for trio assembly. -For trio assembly, only level 0 and level 1 are allowed. - -.TP -.BI -s \ FLOAT -Similarity threshold for duplicate haplotigs that should be purged [0.75 for -.BR -l1/-l2 , -0.55 for -.BR -l3 ]. - -.TP -.BI -O \ FLOAT -Min number of overlapped reads for duplicate haplotigs that should be purged [1]. - -.TP -.BI --purge-max \ INT -Coverage upper bound of Purge-dups, which is inferred automatically in default. -If the coverage of a contig is higher than this bound, don't apply Purge-dups. -Larger value makes assembly more contiguous but may collapse repeats or segmental duplications. - -.TP -.BI --n-hap \ INT -Assumption of haplotype number. If it is set to >2, the quality of -primary assembly for polyploid genomes might be improved. - - - -.SS Hi-C-partition options [experimental, not stable] - -.TP -.BI --h1 \ FILEs -File names of input Hi-C R1 [r1_1.fq,r1_2.fq,...]. - -.TP -.BI --h2 \ FILEs -File names of input Hi-C R2 [r2_1.fq,r2_2.fq,...]. - -.TP -.BI --n-weight \ INT -Rounds of reweighting Hi-C links [3]. Increasing this may improves -phasing results but takes longer time. - -.TP -.BI --n-perturb \ INT -Rounds of perturbation [10000]. Increasing this may improves -phasing results but takes longer time. - -.TP -.BI --f-perturb \ FLOAT -Fraction to flip for perturbation [0.1]. Increasing this may improves -phasing results but takes longer time. - -.TP -.BI --l-msjoin \ INT -Detect misjoined unitigs of >= -.I INT -in size; 0 to disable [500000]. - -.TP -.BI --seed \ INT -RNG seed [11]. - -.SH OUTPUTS - -.PP -In general, hifiasm generates the following assembly graphs in the GFA format: - -.RS 2 -.TP 2 -* -.IR prefix .r_utg.gfa: -haplotype-resolved raw unitig graph. This graph keeps all haplotype information. - -.TP -* -.IR prefix .p_utg.gfa: -haplotype-resolved processed unitig graph without small bubbles. Small bubbles -might be caused by somatic mutations or noise in data, which are not the real -haplotype information. Hifiasm automatically pops such small bubbles based on coverage. -The option -.BR --hom-cov -affects the result. -In addition, the option -.BR -p -forcedly pops bubbles. - -.TP -* -.IR prefix .p_ctg.gfa: -assembly graph of primary contigs. This graph includes a complete assembly with -long stretches of phased blocks. - -.TP -* -.IR prefix .a_ctg.gfa: -assembly graph of alternate contigs. This graph consists of all contigs that -are discarded in primary contig graph. - -.TP -* -.IR prefix .*hap*.p_ctg.gfa: -phased contig graph. This graph keeps the phased assembly. - -.RE - -.PP -Hifiasm outputs -.B *.r_utg.gfa -and -.B *.p_utg.gfa -in any cases. -Specifically, hifiasm outputs the following assembly graphs -with trio-binning options: - -.RS 2 -.TP 2 -* -.IR prefix .dip.hap1.p_ctg.gfa: -fully phased paternal/haplotype1 contig graph keeping the phased -paternal/haplotype1 assembly. - -.TP -* -.IR prefix .dip.hap2.p_ctg.gfa: -fully phased maternal/haplotype2 contig graph keeping the phased -maternal/haplotype2 assembly. -.RE - -.PP -With Hi-C partition options, hifiasm outputs: - -.RS 2 -.TP 2 -* -.IR prefix .hic.p_ctg.gfa: -assembly graph of primary contigs. - -.TP -* -.IR prefix .hic.hap1.p_ctg.gfa: -fully phased contig graph where each contig is fully phased. - -.TP -* -.IR prefix .hic.hap2.p_ctg.gfa: -fully phased contig graph where each contig is fully phased. - -.TP -* -.IR prefix .hic.a_ctg.gfa -(optional with -.BR --primary): -assembly graph of alternate contigs. - -.RE - - -.PP -Hifiasm keeps Hi-C alignment results and Hi-C index in two bin -files: -.B *hic.lk.bin -and -.B *hic.tlb.bin. -Rerunning hifiasm with different Hi-C reads needs to delete these bin files -or use -.BR -i . -.RE - -.PP -Hifiasm generates the following assembly graphs only with HiFi reads: - -.RS 2 -.TP 2 -* -.IR prefix .bp.p_ctg.gfa: -assembly graph of primary contigs. - -.TP -* -.IR prefix .bp.hap1.p_ctg.gfa: -partially phased contig graph of haplotype1. - -.TP -* -.IR prefix .bp.hap2.p_ctg.gfa: -partially phased contig graph of haplotype2. -.RE - -.PP -If the option -.BR -l0 -or -.BR --primary -is specified, hifiasm outputs: - -.RS 2 -.TP 2 -* -.IR prefix .p_ctg.gfa: -assembly graph of primary contigs. - -.TP -* -.IR prefix .a_ctg.gfa: -assembly graph of alternate contigs. -.RE - - - - -.PP -For each graph, hifiasm also outputs a simplified version without sequences for -the ease of visualization. Hifiasm keeps corrected reads and overlaps in three -binary files such as it can regenerate assembly graphs from the binary files -without redoing error correction. +.TH hifiasm 1 "22 August 2021" "hifiasm-0.16.0 (r369)" "Bioinformatics tools" + +.SH NAME +.PP +hifiasm - haplotype-resolved de novo assembler for PacBio Hifi reads. + +.SH SYNOPSIS + +* Assemble HiFi reads: +.RS 4 +.B hifiasm +.RB [ -o +.IR prefix ] +.RB [ -t +.IR nThreads ] +.RB [ -z +.IR endTrimLen ] +.R [options] +.I input1.fq +.RI [ input2.fq +.R [...]] +.RE + +* Trio binning assembly with yak dumps: +.RS 4 +.B yak count +.B -o +.I paternal.yak +.B -b37 +.RB [ -t +.IR nThreads ] +.RB [ -k +.IR kmerLen ] +.I paternal.fq.gz +.br +.B yak count +.B -o +.I maternal.yak +.B -b37 +.RB [ -t +.IR nThreads ] +.RB [ -k +.IR kmerLen ] +.I maternal.fq.gz +.br +.B hifiasm +.RB [ -o +.IR prefix ] +.RB [ -t +.IR nThreads ] +.R [options] +.B -1 +.I paternal.yak +.B -2 +.I maternal.yak +.I child.hifi.fq.gz +.RE + +.SH DESCRIPTION +.PP +Hifiasm is an ultrafast haplotype-resolved de novo assembler for PacBio +Hifi reads. Unlike most existing assemblers, hifiasm starts from uncollapsed +genome. Thus, it is able to keep the haplotype information as much as possible. +The input of hifiasm is the PacBio Hifi reads in fasta/fastq format, and its +outputs consist of multiple types of assembly graphs in GFA format. + + +.SH OPTIONS + +.SS General options + +.TP 10 +.BI -o \ FILE +Prefix of output files [hifiasm.asm]. For detailed description of all assembly +graphs, please see the +.B OUTPUTS +section of this man-page. + +.TP 10 +.BI -t \ INT +Number of CPU threads used by hifiasm [1]. + +.TP +.BI -h +Show help information. + +.TP +.BI --version +Show version number. + + +.SS Error correction options + +.TP 10 +.BI -k \ INT +K-mer length [51]. This option must be less than 64. + +.TP +.BI -w \ INT +Minimizer window size [51]. + +.TP +.BI -f \ INT +Number of bits for bloom filter; 0 to disable [37]. This bloom filter is used +to filter out singleton k-mers when counting all k-mers. It takes +.RI 2^( INT -3) +bytes of memory. A proper setting saves memory. +.BR -f37 +is recommended for human +assembly. For small genomes, use +.BR -f0 +to disable the initial bloom filter +which takes 16GB memory at the beginning. For genomes much larger +than human, applying +.BR -f38 +or even +.BR -f39 +is preferred to save memory on k-mer counting. + +.TP +.BI -D \ INT +Drop k-mers occurring +.I >FLOAT*coverage +times [5.0]. +Hifiasm discards these high-frequency k-mers +during error correction to reduce running time. +The +.I coverage +is determined automatically +by hifiasm based on k-mer plot, representing +homozygous read coverage. Raising this option +may improve the resolution of repetitive regions +but takes longer time. + +.TP +.BI -N \ INT +Consider up to +.I max(-D*coverage,-N) +overlaps for each oriented read [100]. +The +.I coverage +is determined automatically +by hifiasm based on k-mer plot, representing +homozygous read coverage. Raising this option may +improve the resolution of repetitive regions but +takes longer time. + + +.TP +.BI -r \ INT +Rounds of haplotype-aware error corrections [3]. +This option affects all outputs of hifiasm. +Odd rounds of correction are preferred in practice. + +.TP +.BI -z \ INT +Length of adapters that should be removed [0]. This option remove +.I INT +bases from both ends of each read. +Some old Hifi reads may consist of +short adapters (e.g., 20bp adapter at one end). For such data, trimming short adapters would +significantly improve the assembly quality. + +.TP +.BI --max-kocc \ INT +Employ k-mers occurring < +.IR INT +times to rescue repetitive overlaps [2000]. +This option may improve the resolution of repeats. + +.TP +.BI --hg-size \ INT (k/m/g) +Estimated haploid genome size used for inferring read coverage [auto]. +This option is used to get accurate homozygous read coverage during +error correction. Common suffices are required, for example, 100m or 3g. + +.TP +.BI --min-hist-cnt \ INT +When analyzing the k-mer spectrum, ignore counts below +.IR INT +[5]. For very low coverage of HiFi data, set smaller +value for this option. + +.SS Assembly options + +.TP +.BI -a \ INT +Rounds of assembly graph cleaning [4]. This option is used with +.B -x +and +.BR -y . +Note that unlike +.BR -r , +this option does not affect error corrected reads and all-to-all overlaps. + + +.TP +.BI -m \ INT +Maximal probing distance for bubble popping when generating primary/alternate +contig graphs [10000000]. Bubbles longer than +.I INT +bases will not be popped. For detailed description of these graphs, please see the +.B OUTPUTS +section of this man-page. + +.TP +.BI -p \ INT +Maximal probing distance for bubble popping when generating haplotype-resolved processed unitig graph +without small bubbles [0]. Bubbles longer than +.I INT +bases will not be popped. Small bubbles might be caused by somatic mutations or noise in data. +Please note that hifiasm automatically pops small bubbles based on coverage, +which can be tweaked by +.BR --hom-cov . +For detailed description of this graph, please see the +.B OUTPUTS +section of this man-page. + +.TP +.BI -n \ INT +A unitig is considered small if it is composed of less than +.I INT +reads [3]. Hifiasm may try to remove small unitigs at various steps. + +.TP +.BI -x \ FLOAT1, -y \ FLOAT2 +Max and min overlap drop ratio [0.8, 0.2]. This option is used with +.BR -a . +Given a node +.I N +in the assembly graph, let max(N) +be the length of the longest overlap of +.I N. +Hifiasm iteratively drops overlaps of +.I N +if their length / max(N) +are below a threshold controlled by +.B -x +and +.BR -y . +Hifiasm applies +.B -a +rounds of short overlap removal with an increasing threshold between +.I FLOAT1 +and +.I FLOAT2. + +.TP +.BI -i +Ignore error corrected reads and overlaps saved in +.IR prefix .*.bin +files so that hifiasm will start again from scratch. +Apart from assembly graphs, hifiasm also outputs three binary files +that save all overlap information during assembly step. +With these files, hifiasm can avoid the time-consuming all-to-all overlap calculation step, +and do the assembly directly and quickly. +This might be helpful when users want to get an optimized assembly by multiple rounds of experiments +with different parameters. + +.TP +.BI -u +Disable post-join step for contigs which may improve N50. +The post-join step of hifiasm improves contig N50 but may introduce misassemblies. + +.TP +.BI --hom-cov \ INT +Homozygous read coverage inferred automatically in default. This option affects different types of outputs, +including Hi-C phased assembly and HiFi-only assembly. + +.TP +.BI --pri-range \ INT1[,INT2] +Min and max coverage cutoff of primary contigs. +Keep contigs with coverage in this range at p_ctg.gfa. +Inferred automatically in default. +If +.I INT2 +is not specified, it is set to infinity. +Set -1 to disable. + +.TP +.BI --lowQ \ INT +Output contig regions with >=INT% inconsistency to the bed file +with suffix +.B lowQ.bed +[70]. Set 0 to disable. + + +.TP +.BI --b-cov \ INT +Break contigs at potential misassemblies with INT-fold coverage [-1]. +Work with +.B --m-rate. +Set -1 to disable. + +.TP +.BI --m-rate \ FLOAT +Break contigs with <=FLOAT*coverage exact overlaps [0.75]. +Only work with +.B --b-cov +and +.B --h-cov. + +.TP +.BI --primary +Output a primary assembly and an alternate assembly. +Hifiasm outputs two balanced assemblies and a primary +assembly in default. Enable this option or +.B -l0 +outputs a primary assembly and an alternate assembly. + + +.SS Trio-partition options + +.TP 10 +.BI -1 \ FILE +K-mer dump generated by +.B yak count +from the paternal/haplotype1 reads [] + +.TP +.BI -2 \ FILE +K-mer dump generated by +.B yak count +from the maternal/haplotype2 reads [] + +.TP +.BI -3 \ FILE +List of paternal/haplotype1 read names [] + +.TP +.BI -4 \ FILE +List of maternal/haplotype2 read names [] + +.TP +.BI -c \ INT +Lower bound of the binned k-mer's frequency [2]. When doing trio binning, +a k-mer is said to be differentiating if it occurs >= +.B -d +times in one sample +but occurs < +.B -c +times in the other sample. + +.TP +.BI -d \ INT +Upper bound of the binned k-mer's frequency [5]. When doing trio binning, +a k-mer is said to be differentiating if it occurs >= +.B -d +times in one sample +but occurs < +.B -c +times in the other sample. + +.TP +.BI --t-occ \ INT +Forcedly remove unitig including > +.I INT +unexpected haplotype-specific reads +without considering graph topology [60]. + + +.SS Purge-dups options + +.TP 10 +.BI -l \ INT +Level of purge-dup. 0 to disable purge-dup, 1 to only purge contained haplotigs, +2 to purge all types of haplotigs, 3 to purge all types of haplotigs in most aggressive way. +In default, [3] for non-trio assembly, [0] for trio assembly. +For trio assembly, only level 0 and level 1 are allowed. + +.TP +.BI -s \ FLOAT +Similarity threshold for duplicate haplotigs that should be purged [0.75 for +.BR -l1/-l2 , +0.55 for +.BR -l3 ]. + +.TP +.BI -O \ FLOAT +Min number of overlapped reads for duplicate haplotigs that should be purged [1]. + +.TP +.BI --purge-max \ INT +Coverage upper bound of Purge-dups, which is inferred automatically in default. +If the coverage of a contig is higher than this bound, don't apply Purge-dups. +Larger value makes assembly more contiguous but may collapse repeats or segmental duplications. + +.TP +.BI --n-hap \ INT +Assumption of haplotype number. If it is set to >2, the quality of +primary assembly for polyploid genomes might be improved. + + + +.SS Hi-C-partition options [experimental, not stable] + +.TP +.BI --h1 \ FILEs +File names of input Hi-C R1 [r1_1.fq,r1_2.fq,...]. + +.TP +.BI --h2 \ FILEs +File names of input Hi-C R2 [r2_1.fq,r2_2.fq,...]. + +.TP +.BI --n-weight \ INT +Rounds of reweighting Hi-C links [3]. Increasing this may improves +phasing results but takes longer time. + +.TP +.BI --n-perturb \ INT +Rounds of perturbation [10000]. Increasing this may improves +phasing results but takes longer time. + +.TP +.BI --f-perturb \ FLOAT +Fraction to flip for perturbation [0.1]. Increasing this may improves +phasing results but takes longer time. + +.TP +.BI --l-msjoin \ INT +Detect misjoined unitigs of >= +.I INT +in size; 0 to disable [500000]. + +.TP +.BI --seed \ INT +RNG seed [11]. + +.SH OUTPUTS + +.PP +In general, hifiasm generates the following assembly graphs in the GFA format: + +.RS 2 +.TP 2 +* +.IR prefix .r_utg.gfa: +haplotype-resolved raw unitig graph. This graph keeps all haplotype information. + +.TP +* +.IR prefix .p_utg.gfa: +haplotype-resolved processed unitig graph without small bubbles. Small bubbles +might be caused by somatic mutations or noise in data, which are not the real +haplotype information. Hifiasm automatically pops such small bubbles based on coverage. +The option +.BR --hom-cov +affects the result. +In addition, the option +.BR -p +forcedly pops bubbles. + +.TP +* +.IR prefix .p_ctg.gfa: +assembly graph of primary contigs. This graph includes a complete assembly with +long stretches of phased blocks. + +.TP +* +.IR prefix .a_ctg.gfa: +assembly graph of alternate contigs. This graph consists of all contigs that +are discarded in primary contig graph. + +.TP +* +.IR prefix .*hap*.p_ctg.gfa: +phased contig graph. This graph keeps the phased assembly. + +.RE + +.PP +Hifiasm outputs +.B *.r_utg.gfa +and +.B *.p_utg.gfa +in any cases. +Specifically, hifiasm outputs the following assembly graphs +with trio-binning options: + +.RS 2 +.TP 2 +* +.IR prefix .dip.hap1.p_ctg.gfa: +fully phased paternal/haplotype1 contig graph keeping the phased +paternal/haplotype1 assembly. + +.TP +* +.IR prefix .dip.hap2.p_ctg.gfa: +fully phased maternal/haplotype2 contig graph keeping the phased +maternal/haplotype2 assembly. +.RE + +.PP +With Hi-C partition options, hifiasm outputs: + +.RS 2 +.TP 2 +* +.IR prefix .hic.p_ctg.gfa: +assembly graph of primary contigs. + +.TP +* +.IR prefix .hic.hap1.p_ctg.gfa: +fully phased contig graph where each contig is fully phased. + +.TP +* +.IR prefix .hic.hap2.p_ctg.gfa: +fully phased contig graph where each contig is fully phased. + +.TP +* +.IR prefix .hic.a_ctg.gfa +(optional with +.BR --primary): +assembly graph of alternate contigs. + +.RE + + +.PP +Hifiasm keeps Hi-C alignment results and Hi-C index in two bin +files: +.B *hic.lk.bin +and +.B *hic.tlb.bin. +Rerunning hifiasm with different Hi-C reads needs to delete these bin files +or use +.BR -i . +.RE + +.PP +Hifiasm generates the following assembly graphs only with HiFi reads: + +.RS 2 +.TP 2 +* +.IR prefix .bp.p_ctg.gfa: +assembly graph of primary contigs. + +.TP +* +.IR prefix .bp.hap1.p_ctg.gfa: +partially phased contig graph of haplotype1. + +.TP +* +.IR prefix .bp.hap2.p_ctg.gfa: +partially phased contig graph of haplotype2. +.RE + +.PP +If the option +.BR -l0 +or +.BR --primary +is specified, hifiasm outputs: + +.RS 2 +.TP 2 +* +.IR prefix .p_ctg.gfa: +assembly graph of primary contigs. + +.TP +* +.IR prefix .a_ctg.gfa: +assembly graph of alternate contigs. +.RE + + + + +.PP +For each graph, hifiasm also outputs a simplified version without sequences for +the ease of visualization. Hifiasm keeps corrected reads and overlaps in three +binary files such as it can regenerate assembly graphs from the binary files +without redoing error correction. diff --git a/hist.cpp b/hist.cpp index 88ee752..6fc78ae 100644 --- a/hist.cpp +++ b/hist.cpp @@ -1,157 +1,157 @@ -#include -#include -#include "htab.h" - -static void ha_hist_line(int c, int x, int exceed, int64_t cnt) -{ - int j; - if (c >= 0) fprintf(stderr, "[M::%s] %5d: ", __func__, c); - else fprintf(stderr, "[M::%s] %5s: ", __func__, "rest"); - for (j = 0; j < x; ++j) fputc('*', stderr); - if (exceed) fputc('>', stderr); - fprintf(stderr, " %lld\n", (long long)cnt); -} - -void print_hist_lines(int n_cnt, int start_cnt, const int64_t *cnt) -{ - const int hist_max = 100; - int i, start, low_i, max_i, max; - // determine the start point - assert(n_cnt > start_cnt); - start = cnt[1] > 0? 1 : 2; - - // find the low point from the left - low_i = start > start_cnt? start : start_cnt; - for (i = low_i; i < n_cnt; ++i) - if (cnt[i] > cnt[i-1]) break; - low_i = i - 1; - fprintf(stderr, "[M::%s] lowest: count[%d] = %ld\n", __func__, low_i, (long)cnt[low_i]); - - // find the highest peak - max_i = start > start_cnt? start : start_cnt, max = cnt[max_i]; - for (i = max_i; i < n_cnt; ++i) - if (cnt[i] > max) - max = cnt[i], max_i = i; - fprintf(stderr, "[M::%s] highest: count[%d] = %ld\n", __func__, max_i, (long)cnt[max_i]); - - for (i = start; i < n_cnt; ++i) { - int x, exceed = 0; - x = (int)((double)hist_max * cnt[i] / cnt[max_i] + .499); - if (x > hist_max) exceed = 1, x = hist_max; // may happen if cnt[2] is higher - if (i > max_i && x == 0) break; - ha_hist_line(i, x, exceed, cnt[i]); - } -} - -int adj_m_peak_hom(int m_peak_hom, int max_i, int max2_i, int max3_i, int *peak_het) -{ - int64_t mm[3], d, min_i, min_d, i; - mm[0] = max2_i; mm[1] = max_i; mm[2] = max3_i; - for (i = 0, min_i = -1, min_d = -1; i < 3; i++){ - if(mm[i] <= 0) continue; - d = (mm[i] >= m_peak_hom?mm[i]-m_peak_hom:m_peak_hom-mm[i]); - if(min_d == -1 || min_d > d || (min_d == d && i == 1)){ - min_d = d; min_i = i; - } - } - if(min_i < 0) return m_peak_hom; - if(mm[min_i] < m_peak_hom){ - d = m_peak_hom - mm[min_i]; - if(d >= mm[min_i]*0.51) { - *peak_het = mm[min_i]; - return m_peak_hom; - } - } - - for (i = min_i-1; i >= 0; i--){ - if(mm[i] <= 0) continue; - *peak_het = mm[i]; - break; - } - return mm[min_i]; -} - -int ha_analyze_count(int n_cnt, int start_cnt, int m_peak_hom, const int64_t *cnt, int *peak_het) -{ - const int hist_max = 100; - int i, start, low_i, max_i, max2_i, max3_i; - int64_t max, max2, max3, min; - - // determine the start point - assert(n_cnt > start_cnt); - *peak_het = -1; - start = cnt[1] > 0? 1 : 2; - - // find the low point from the left - low_i = start > start_cnt? start : start_cnt; - for (i = low_i + 1; i < n_cnt; ++i) - if (cnt[i] > cnt[i-1]) break; - low_i = i - 1; - fprintf(stderr, "[M::%s] lowest: count[%d] = %ld\n", __func__, low_i, (long)cnt[low_i]); - if (low_i == n_cnt - 1) return -1; // low coverage - - // find the highest peak - max_i = low_i + 1, max = cnt[max_i]; - for (i = low_i + 1; i < n_cnt; ++i) - if (cnt[i] > max) - max = cnt[i], max_i = i; - fprintf(stderr, "[M::%s] highest: count[%d] = %ld\n", __func__, max_i, (long)cnt[max_i]); - - // print histogram - for (i = start; i < n_cnt; ++i) { - int x, exceed = 0; - x = (int)((double)hist_max * cnt[i] / cnt[max_i] + .499); - if (x > hist_max) exceed = 1, x = hist_max; // may happen if cnt[2] is higher - if (i > max_i && x == 0) break; - ha_hist_line(i, x, exceed, cnt[i]); - } - { - int x, exceed = 0; - int64_t rest = 0; - for (; i < n_cnt; ++i) rest += cnt[i]; - x = (int)((double)hist_max * rest / cnt[max_i] + .499); - if (x > hist_max) exceed = 1, x = hist_max; - ha_hist_line(-1, x, exceed, rest); - } - - // look for smaller peak on the low end - max2 = -1; max2_i = -1; - for (i = max_i - 1; i > low_i; --i) { - if (cnt[i] >= cnt[i-1] && cnt[i] >= cnt[i+1]) { - if (cnt[i] > max2) max2 = cnt[i], max2_i = i; - } - } - if (max2_i > low_i && max2_i < max_i) { - for (i = max2_i + 1, min = max; i < max_i; ++i) - if (cnt[i] < min) min = cnt[i]; - if (max2 < max * 0.05 || min > max2 * 0.95) - max2 = -1, max2_i = -1; - } - if (max2 > 0) fprintf(stderr, "[M::%s] left: count[%d] = %ld\n", __func__, max2_i, (long)cnt[max2_i]); - else fprintf(stderr, "[M::%s] left: none\n", __func__); - - // look for smaller peak on the high end - max3 = -1; max3_i = -1; - for (i = max_i + 1; i < n_cnt - 1; ++i) { - if (cnt[i] >= cnt[i-1] && cnt[i] >= cnt[i+1]) { - if (cnt[i] > max3) max3 = cnt[i], max3_i = i; - } - } - if (max3_i > max_i) { - for (i = max_i + 1, min = max; i < max3_i; ++i) - if (cnt[i] < min) min = cnt[i]; - if (max3 < max * 0.05 || min > max3 * 0.95 || max3_i > max_i * 2.5) - max3 = -1, max3_i = -1; - } - if (max3 > 0) fprintf(stderr, "[M::%s] right: count[%d] = %ld\n", __func__, max3_i, (long)cnt[max3_i]); - else fprintf(stderr, "[M::%s] right: none\n", __func__); - - if(m_peak_hom > 0) return adj_m_peak_hom(m_peak_hom, max_i, max2_i, max3_i, peak_het); - if (max3_i > 0) { - *peak_het = max_i; - return max3_i; - } else { - if (max2_i > 0) *peak_het = max2_i; - return max_i; - } -} +#include +#include +#include "htab.h" + +static void ha_hist_line(int c, int x, int exceed, int64_t cnt) +{ + int j; + if (c >= 0) fprintf(stderr, "[M::%s] %5d: ", __func__, c); + else fprintf(stderr, "[M::%s] %5s: ", __func__, "rest"); + for (j = 0; j < x; ++j) fputc('*', stderr); + if (exceed) fputc('>', stderr); + fprintf(stderr, " %lld\n", (long long)cnt); +} + +void print_hist_lines(int n_cnt, int start_cnt, const int64_t *cnt) +{ + const int hist_max = 100; + int i, start, low_i, max_i, max; + // determine the start point + assert(n_cnt > start_cnt); + start = cnt[1] > 0? 1 : 2; + + // find the low point from the left + low_i = start > start_cnt? start : start_cnt; + for (i = low_i; i < n_cnt; ++i) + if (cnt[i] > cnt[i-1]) break; + low_i = i - 1; + fprintf(stderr, "[M::%s] lowest: count[%d] = %ld\n", __func__, low_i, (long)cnt[low_i]); + + // find the highest peak + max_i = start > start_cnt? start : start_cnt, max = cnt[max_i]; + for (i = max_i; i < n_cnt; ++i) + if (cnt[i] > max) + max = cnt[i], max_i = i; + fprintf(stderr, "[M::%s] highest: count[%d] = %ld\n", __func__, max_i, (long)cnt[max_i]); + + for (i = start; i < n_cnt; ++i) { + int x, exceed = 0; + x = (int)((double)hist_max * cnt[i] / cnt[max_i] + .499); + if (x > hist_max) exceed = 1, x = hist_max; // may happen if cnt[2] is higher + if (i > max_i && x == 0) break; + ha_hist_line(i, x, exceed, cnt[i]); + } +} + +int adj_m_peak_hom(int m_peak_hom, int max_i, int max2_i, int max3_i, int *peak_het) +{ + int64_t mm[3], d, min_i, min_d, i; + mm[0] = max2_i; mm[1] = max_i; mm[2] = max3_i; + for (i = 0, min_i = -1, min_d = -1; i < 3; i++){ + if(mm[i] <= 0) continue; + d = (mm[i] >= m_peak_hom?mm[i]-m_peak_hom:m_peak_hom-mm[i]); + if(min_d == -1 || min_d > d || (min_d == d && i == 1)){ + min_d = d; min_i = i; + } + } + if(min_i < 0) return m_peak_hom; + if(mm[min_i] < m_peak_hom){ + d = m_peak_hom - mm[min_i]; + if(d >= mm[min_i]*0.51) { + *peak_het = mm[min_i]; + return m_peak_hom; + } + } + + for (i = min_i-1; i >= 0; i--){ + if(mm[i] <= 0) continue; + *peak_het = mm[i]; + break; + } + return mm[min_i]; +} + +int ha_analyze_count(int n_cnt, int start_cnt, int m_peak_hom, const int64_t *cnt, int *peak_het) +{ + const int hist_max = 100; + int i, start, low_i, max_i, max2_i, max3_i; + int64_t max, max2, max3, min; + + // determine the start point + assert(n_cnt > start_cnt); + *peak_het = -1; + start = cnt[1] > 0? 1 : 2; + + // find the low point from the left + low_i = start > start_cnt? start : start_cnt; + for (i = low_i + 1; i < n_cnt; ++i) + if (cnt[i] > cnt[i-1]) break; + low_i = i - 1; + fprintf(stderr, "[M::%s] lowest: count[%d] = %ld\n", __func__, low_i, (long)cnt[low_i]); + if (low_i == n_cnt - 1) return -1; // low coverage + + // find the highest peak + max_i = low_i + 1, max = cnt[max_i]; + for (i = low_i + 1; i < n_cnt; ++i) + if (cnt[i] > max) + max = cnt[i], max_i = i; + fprintf(stderr, "[M::%s] highest: count[%d] = %ld\n", __func__, max_i, (long)cnt[max_i]); + + // print histogram + for (i = start; i < n_cnt; ++i) { + int x, exceed = 0; + x = (int)((double)hist_max * cnt[i] / cnt[max_i] + .499); + if (x > hist_max) exceed = 1, x = hist_max; // may happen if cnt[2] is higher + if (i > max_i && x == 0) break; + ha_hist_line(i, x, exceed, cnt[i]); + } + { + int x, exceed = 0; + int64_t rest = 0; + for (; i < n_cnt; ++i) rest += cnt[i]; + x = (int)((double)hist_max * rest / cnt[max_i] + .499); + if (x > hist_max) exceed = 1, x = hist_max; + ha_hist_line(-1, x, exceed, rest); + } + + // look for smaller peak on the low end + max2 = -1; max2_i = -1; + for (i = max_i - 1; i > low_i; --i) { + if (cnt[i] >= cnt[i-1] && cnt[i] >= cnt[i+1]) { + if (cnt[i] > max2) max2 = cnt[i], max2_i = i; + } + } + if (max2_i > low_i && max2_i < max_i) { + for (i = max2_i + 1, min = max; i < max_i; ++i) + if (cnt[i] < min) min = cnt[i]; + if (max2 < max * 0.05 || min > max2 * 0.95) + max2 = -1, max2_i = -1; + } + if (max2 > 0) fprintf(stderr, "[M::%s] left: count[%d] = %ld\n", __func__, max2_i, (long)cnt[max2_i]); + else fprintf(stderr, "[M::%s] left: none\n", __func__); + + // look for smaller peak on the high end + max3 = -1; max3_i = -1; + for (i = max_i + 1; i < n_cnt - 1; ++i) { + if (cnt[i] >= cnt[i-1] && cnt[i] >= cnt[i+1]) { + if (cnt[i] > max3) max3 = cnt[i], max3_i = i; + } + } + if (max3_i > max_i) { + for (i = max_i + 1, min = max; i < max3_i; ++i) + if (cnt[i] < min) min = cnt[i]; + if (max3 < max * 0.05 || min > max3 * 0.95 || max3_i > max_i * 2.5) + max3 = -1, max3_i = -1; + } + if (max3 > 0) fprintf(stderr, "[M::%s] right: count[%d] = %ld\n", __func__, max3_i, (long)cnt[max3_i]); + else fprintf(stderr, "[M::%s] right: none\n", __func__); + + if(m_peak_hom > 0) return adj_m_peak_hom(m_peak_hom, max_i, max2_i, max3_i, peak_het); + if (max3_i > 0) { + *peak_het = max_i; + return max3_i; + } else { + if (max2_i > 0) *peak_het = max2_i; + return max_i; + } +} diff --git a/horder.cpp b/horder.cpp index 8521c10..4e71d52 100644 --- a/horder.cpp +++ b/horder.cpp @@ -1,4575 +1,4575 @@ -#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" -#include "tovlp.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 osg_arc_key(a) ((a).u) -KRADIX_SORT_INIT(osg, osg_arc_t, osg_arc_key, member_size(osg_arc_t, u)) - -#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 5000000 -#define BREAK_CUTOFF 0.1 -#define BREAK_BOUNDARY 0.015 -void reduce_hamming_error_adv(ma_ug_t *iug, asg_t *sg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, -int max_hang, int min_ovlp, long long gap_fuzz, R_to_U *ru, bubble_type* bub); - -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 e, d; - double w; -} hw_aux_t; - -typedef struct { - hw_aux_t *a; - size_t n, m; -} h_w_t; - -#define hw_e_key(x) ((x).e) -KRADIX_SORT_INIT(hw_e, hw_aux_t, hw_e_key, member_size(hw_aux_t, e)) - -#define hw_d_key(x) ((x).d) -KRADIX_SORT_INIT(hw_d, hw_aux_t, hw_d_key, member_size(hw_aux_t, d)) - -#define hw_ew_key(x) ((uint32_t)((x).e)) -KRADIX_SORT_INIT(hw_ew, hw_aux_t, hw_ew_key, member_size(hw_aux_t, e)) - -#define hw_dw_key(x) ((uint32_t)((x).d)) -KRADIX_SORT_INIT(hw_dw, hw_aux_t, hw_dw_key, member_size(hw_aux_t, d)) - -typedef struct { - kvec_t(uint64_t) pos; - uint64_t *a; - size_t n, m; -} dens_idx_t; - -typedef struct { - uint64_t s, e, dp; -} h_cov_t; - -typedef struct { - h_cov_t *a; - size_t n, m; -} h_covs; - -typedef struct { - uint32_t *a; - size_t n, m; -}lay_t; - -typedef struct { - lay_t *a; - size_t n, m; -}sc_lay_t; - -typedef struct { - uint64_t uid, sid; - uint64_t iid:63, ori:1; -} sc_id_t; - -typedef struct { - sc_id_t *a; - size_t n, m; - sc_lay_t *sl; - osg_t *sg; - uint32_t n_thread; -} sc_mul; - -#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 h_cov_e_key(x) ((x).e) -KRADIX_SORT_INIT(h_cov_e, h_cov_t, h_cov_e_key, member_size(h_cov_t, e)) -#define h_cov_dp_key(x) ((x).dp) -KRADIX_SORT_INIT(h_cov_dp, h_cov_t, h_cov_dp_key, member_size(h_cov_t, dp)) -#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)) - -typedef struct { - kv_u_trans_t *ref; - trans_chain* idx; -} trans_col_t; - -typedef struct { - uint32_t Spre, Epre, Scur, Ecur, uCur, uPre;///[qSp, qEp) && [qSn, qEn] -} u_hit_t; - -#define u_hit_t_key(x) ((x).uPre) -KRADIX_SORT_INIT(u_hit, u_hit_t, u_hit_t_key, member_size(u_hit_t, uPre)) - -typedef struct { - ma_ug_t *ug; - kvec_pe_hit hits; - kv_u_trans_t k_trans; - h_covs *b_points; -} debug_phasing_t; - -debug_phasing_t *init_debug_phasing(ma_ug_t *ug, kvec_pe_hit *hits, kv_u_trans_t *k_trans, h_covs *b_points) -{ - debug_phasing_t *p = NULL; CALLOC(p, 1); - p->ug = copy_untig_graph(ug); - p->b_points = b_points; - - p->hits.pos_mode = hits->pos_mode; p->hits.uID_bits = hits->pos_mode; - p->hits.a.n = p->hits.a.m = hits->a.n = hits->a.m; - MALLOC(p->hits.a.a, p->hits.a.n); - memcpy(p->hits.a.a, hits->a.a, p->hits.a.n*sizeof(pe_hit)); - - p->k_trans.n = p->k_trans.m = k_trans->n; - MALLOC(p->k_trans.a, p->k_trans.n); - memcpy(p->k_trans.a, k_trans->a, p->k_trans.n*sizeof(u_trans_t)); - - p->k_trans.idx.n = p->k_trans.idx.m = k_trans->idx.n; - MALLOC(p->k_trans.idx.a, p->k_trans.idx.n); - memcpy(p->k_trans.idx.a, k_trans->idx.a, p->k_trans.idx.n*sizeof(uint64_t)); - - return p; -} - -void destory_debug_phasing_t(debug_phasing_t **x) -{ - ma_ug_destroy((*x)->ug); - free((*x)->hits.a.a); free((*x)->hits.idx.a); free((*x)->hits.occ.a); - free((*x)->k_trans.a); free((*x)->k_trans.idx.a); - free(*x); -} - -uint64_t new_node(uint64_t v, h_covs *join, uint64_t *idx, uint64_t is_ul) -{ - if(v&1) return (((uint32_t)join->a[(idx[v>>1]>>32)+(is_ul?0:(((uint32_t)idx[v>>1])-1))].dp)<<1)+1; - else return (((uint32_t)join->a[(idx[v>>1]>>32)+(is_ul?(((uint32_t)idx[v>>1])-1):0)].dp)<<1); -} - -uint32_t iter_rid(buf_t *b, uint64_t *ui, uint64_t *ri, ma_ug_t *ug) -{ - ma_utg_t *u = NULL; - while ((*ui) < b->b.n) - { - u = &(ug->u.a[b->b.a[(*ui)]>>1]); - while ((*ri) < u->n) return u->a[(*ri)++]>>32; - (*ui)++; (*ri) = 0; - } - - return (uint32_t)-1; -} - -void debug_debug_phasing_t(debug_phasing_t *x, ma_ug_t *cug, kvec_pe_hit *chits, kv_u_trans_t *ck_trans, -h_covs *join, uint64_t *idx) -{ - uint64_t i, k, m, pv, cv, pui, pri, cui, cri, e; - uint32_t p_cvx, c_cvx, pr, cr, occ; - long long p_nodeLen, p_baseLen, t1, t2; - long long c_nodeLen, c_baseLen; - asg_arc_t *ap, *ac; - u_trans_t *pk, *ck, *p; - buf_t pb, cb; - memset(&pb, 0, sizeof(buf_t)); - memset(&cb, 0, sizeof(buf_t)); - - uint32_t *cnt = NULL; CALLOC(cnt, cug->g->n_seq<<1); - for (cv = 0; cv < (uint64_t)(cug->g->n_seq<<1); ++cv) { - ///out-nodes of v - ac = asg_arc_a(cug->g, cv); - ///if v just have one out-node, there is no muti-edge - if (asg_arc_n(cug->g, cv) < 2) continue; - for (i = 0; i < asg_arc_n(cug->g, cv); ++i) ++cnt[ac[i].v]; - for (i = 0; i < asg_arc_n(cug->g, cv); ++i) - if (--cnt[ac[i].v] != 0) fprintf(stderr, "ERROR-9\n"); - } - free(cnt); - - for (e = 0; e < cug->g->n_arc; ++e) { - uint32_t v = cug->g->arc[e].v^1, u = cug->g->arc[e].ul>>32^1; - asg_arc_t *av = asg_arc_a(cug->g, v); - for (i = 0; i < asg_arc_n(cug->g, v); ++i) - if (av[i].v == u) break; - if (i == asg_arc_n(cug->g, v)) fprintf(stderr, "ERROR-10\n"); - } - - - for (i = 0; i < x->ug->g->n_seq; i++) - { - pv = (i<<1); - cv = new_node(pv, join, idx, 1); - if(asg_arc_n(x->ug->g, pv) != asg_arc_n(cug->g, cv)) fprintf(stderr, "ERROR-1\n"); - ap = asg_arc_a(x->ug->g, pv); ac = asg_arc_a(cug->g, cv); - for (k = 0; k < asg_arc_n(x->ug->g, pv); k++) - { - for (m = 0; m < asg_arc_n(cug->g, cv); m++) - { - if(new_node(ap[k].v, join, idx, 0) == ac[m].v) break; - } - if(m >= asg_arc_n(cug->g, cv)) - { - fprintf(stderr, "\n+ERROR-2\n"); - fprintf(stderr, "+putg%.6lul (%lu), cutg%.6lul (%lu)\n", (pv>>1) + 1, pv&1, (cv>>1) + 1, cv&1); - fprintf(stderr, "+p-occ: %u, c-occ: %u\n", asg_arc_n(x->ug->g, pv), asg_arc_n(cug->g, cv)); - fprintf(stderr, "+ap[k]-utg%.6ul (%u), new-utg%.6lul (%lu)\n", (ap[k].v>>1)+1, ap[k].v&1, - (new_node(ap[k].v, join, idx, 0)>>1)+1, new_node(ap[k].v, join, idx, 0)&1); - for (m = 0; m < asg_arc_n(cug->g, cv); m++) - { - fprintf(stderr, "+ac[%lu]-utg%.6ul (%u)\n", m, (ac[m].v>>1) + 1, ac[m].v&1); - } - } - } - - - - pv = (i<<1) + 1; - cv = new_node(pv, join, idx, 1); - if(asg_arc_n(x->ug->g, pv) != asg_arc_n(cug->g, cv)) fprintf(stderr, "ERROR-1\n"); - ap = asg_arc_a(x->ug->g, pv); ac = asg_arc_a(cug->g, cv); - for (k = 0; k < asg_arc_n(x->ug->g, pv); k++) - { - for (m = 0; m < asg_arc_n(cug->g, cv); m++) - { - if(new_node(ap[k].v, join, idx, 0) == ac[m].v) break; - } - if(m >= asg_arc_n(cug->g, cv)) - { - fprintf(stderr, "\n-ERROR-2\n"); - fprintf(stderr, "-putg%.6lul (%lu), cutg%.6lul (%lu)\n", (pv>>1) + 1, pv&1, (cv>>1) + 1, cv&1); - fprintf(stderr, "-p-occ: %u, c-occ: %u\n", asg_arc_n(x->ug->g, pv), asg_arc_n(cug->g, cv)); - fprintf(stderr, "-ap[k]-utg%.6ul (%u), new-utg%.6lul (%lu)\n", (ap[k].v>>1)+1, ap[k].v&1, - (new_node(ap[k].v, join, idx, 0)>>1)+1, new_node(ap[k].v, join, idx, 0)&1); - for (m = 0; m < asg_arc_n(cug->g, cv); m++) - { - fprintf(stderr, "-ac[%lu]-utg%.6ul (%u)\n", m, (ac[m].v>>1) + 1, ac[m].v&1); - } - } - } - - pb.b.n = cb.b.n = 0; - if(get_unitig(x->ug->g, NULL, i<<1, &p_cvx, &p_nodeLen, &p_baseLen, &t1, &t2, 1, &pb) != - get_unitig(cug->g, NULL, new_node((i<<1)+1, join, idx, 1)^1, &c_cvx, &c_nodeLen, &c_baseLen, &t1, &t2, 1, &cb)) - { - fprintf(stderr, "ERROR-3\n"); - } - if(new_node(p_cvx, join, idx, 1) != c_cvx) fprintf(stderr, "ERROR-4\n"); - if(p_baseLen != c_baseLen) - { - fprintf(stderr, "ERROR-6\n"); - fprintf(stderr, "-putg%.6lul, pb.b.n: %u, p_nodeLen: %lld, p_baseLen: %lld, cb.b.n: %u, c_nodeLen: %lld, c_baseLen: %lld\n", - i+1, (uint32_t)pb.b.n, p_nodeLen, p_baseLen, (uint32_t)cb.b.n, c_nodeLen, c_baseLen); - } - - - - pui = pri = cui = cri = 0; - while(1) - { - pr = iter_rid(&pb, &pui, &pri, x->ug); - cr = iter_rid(&cb, &cui, &cri, cug); - if(pr != cr) fprintf(stderr, "ERROR-7\n"); - if(pr == (uint32_t)-1 || cr == (uint32_t)-1) break; - } - } - - for (i = 0; i < x->k_trans.n; i++) - { - pk = &(x->k_trans.a[i]); - if(((uint32_t)idx[pk->qn]) <= 1 && ((uint32_t)idx[pk->tn]) <= 1) - { - get_u_trans_spec(ck_trans, ((uint32_t)join->a[idx[pk->qn]>>32].dp), - ((uint32_t)join->a[idx[pk->tn]>>32].dp), &ck, &occ); - if(occ != 1 || !ck) fprintf(stderr, "ERROR-8\n"); - - if(pk->qs != ck->qs || pk->qe != ck->qe || pk->ts != ck->ts || pk->te != ck->te || - pk->f != ck->f || pk->rev != ck->rev || pk->del != ck->del) - { - fprintf(stderr, "ERROR-9\n"); - } - } - else - { - p = pk; - fprintf(stderr, "\n+q-utg%.6ul\tqs(%u)\tqe(%u)\tt-utg%.6ul\tts(%u)\tte(%u)\trev(%u)\tw(%f)\tf(%u)\n", - p->qn+1, p->qs, p->qe, p->tn+1, p->ts, p->te, p->rev, p->nw, p->f); - - uint64_t qi, ti, qid = p->qn, tid = p->tn; - for (qi = 0; qi < (uint32_t)idx[qid]; qi++) - { - for (ti = 0; ti < (uint32_t)idx[tid]; ti++) - { - get_u_trans_spec(ck_trans, (uint32_t)(join->a[(idx[qid]>>32)+qi].dp), - (uint32_t)(join->a[(idx[tid]>>32)+ti].dp), &ck, &occ); - // fprintf(stderr, "s-utg%.6ul\td-utg%.6ul\tocc:%u\n", - // (uint32_t)(join->a[(idx[qid]>>32)+qi].dp)+1, - // (uint32_t)(join->a[(idx[tid]>>32)+ti].dp)+1, - // occ); - for (k = 0; k < occ; k++) - { - p = &(ck[k]); - fprintf(stderr, "-q-utg%.6ul\tqs(%u)\tqe(%u)\tt-utg%.6ul\tts(%u)\tte(%u)\trev(%u)\tw(%f)\tf(%u)\n", - p->qn+1, p->qs, p->qe, p->tn+1, p->ts, p->te, p->rev, p->nw, p->f); - } - } - - } - - - // get_u_trans_spec(ck_trans, ((uint32_t)join->a[idx[pk->qn]>>32].dp), - // ((uint32_t)join->a[idx[pk->tn]>>32].dp), &ck, &occ); - // for (k = 0; k < occ; k++) - // { - // p = &(ck[k]); - // fprintf(stderr, "-q-utg%.6ul\tqs(%u)\tqe(%u)\tt-utg%.6ul\tts(%u)\tte(%u)\trev(%u)\tw(%f)\tf(%u)\n", - // p->qn+1, p->qs, p->qe, p->tn+1, p->ts, p->te, p->rev, p->nw, p->f); - // } - } - } - - free(pb.b.a); free(cb.b.a); -} - -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->u.n; ++i) - { - kv_push(uint64_t, b, ug->u.a[i].len); - s += ug->u.a[i].len; - } - len = s; - - radix_sort_ho64(b.a, b.a+b.n); - fprintf(stderr, "[M::%s::] Genome Size: %lu, # Contigs: %u, Largest Contig: %lu\n", - __func__, len, (uint32_t)ug->u.n, b.a[b.n-1]); - 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 print_N50_layout(ma_ug_t* ug, sc_lay_t* sl) -{ - kvec_t(uint64_t) b; kv_init(b); - lay_t *p = NULL; - uint64_t i, k, s, ulen, len, occ = 0; - for (i = s = 0; i < sl->n; ++i) - { - p = &(sl->a[i]); - for (k = ulen = 0; k < p->n; k+=2) - { - ulen += ug->u.a[p->a[k]>>1].len; - } - occ += p->n; - - kv_push(uint64_t, b, ulen); - s += ulen; - } - len = s; - - radix_sort_ho64(b.a, b.a+b.n); - fprintf(stderr, "[M::%s::] Scaffold Size: %lu, # Scaffolds: %u (occ-%lu), Largest Scaffold: %lu\n", - __func__, len, (uint32_t)sl->n, occ, b.a[b.n-1]); - 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); -} - -trans_col_t *init_trans_col(ma_ug_t *ug, uint64_t r_num, kv_u_trans_t *ref) -{ - trans_col_t *p = NULL; - CALLOC(p, 1); - p->ref = ref; - p->idx = init_trans_chain(ug, r_num); - return p; -} - -void destory_trans_col(trans_col_t **p) -{ - destory_trans_chain(&((*p)->idx)); - free(*p); -} - -void resolve_hit(uint64_t x, uint32_t rLen, uint64_t uID_bits, uint64_t pos_mode, uint64_t *uid, uint64_t *beg, uint64_t *end) -{ - if(uid) (*uid) = ((x<<1)>>(64 - uID_bits)); - uint32_t rev = (x>>63); - long long ref_p = x & pos_mode; - long long p_beg, p_end; - - if(rev) - { - p_end = ref_p; - p_beg = p_end + 1 - rLen; - } - else - { - p_beg = ref_p; - p_end = p_beg + rLen - 1; - } - if(p_beg < 0) p_beg = 0; - if(p_end < 0) p_end = 0; - if(beg) (*beg) = p_beg; - if(end) (*end) = p_end + 1; -} - -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; - } - } -} - -kvec_pe_hit *get_r_hits_for_trio(kvec_pe_hit *u_hits, asg_t* r_g, ma_ug_t* ug, bubble_type* bub, uint64_t uID_bits, uint64_t pos_mode) -{ - kvec_pe_hit *r_hits = NULL; - CALLOC(r_hits, 1); - uint64_t k, l, i, r_i, offset, rid, rev, rBeg, rEnd, ubits, p_mode, upos, rpos, update, ubeg, uend, suid, euid; - 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); - - u_hits->uID_bits = uID_bits; u_hits->pos_mode = pos_mode; - for (i = r_i = 0; i < u_hits->a.n; i++) - { - suid = get_hit_suid(*u_hits, i); - euid = get_hit_euid(*u_hits, i); - if(IF_HOM(suid, *bub)) continue; - if(IF_HOM(euid, *bub)) continue; - if(suid == euid) continue; - kv_push(pe_hit, r_hits->a, u_hits->a.a[i]); - - resolve_hit(r_hits->a.a[r_i].s, r_hits->a.a[r_i].len>>32, r_hits->uID_bits, - r_hits->pos_mode, NULL, &ubeg, &uend); - upos = (ubeg+uend-1)>>1; - r_hits->a.a[r_i].s -= get_hit_spos(*r_hits, r_i); - r_hits->a.a[r_i].s += upos; - - - resolve_hit(r_hits->a.a[r_i].e, (uint32_t)r_hits->a.a[r_i].len, r_hits->uID_bits, - r_hits->pos_mode, NULL, &ubeg, &uend); - upos = (ubeg+uend-1)>>1; - r_hits->a.a[r_i].e -= get_hit_epos(*r_hits, r_i);///pos at unitig - r_hits->a.a[r_i].e += upos; - - r_hits->a.a[r_i].id = (suid<<32)|euid; - r_i++; - } - - 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) - { - 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) - { - 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; - return r_hits; -} - -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]; - } - assert((r_i == k) && (update == (k-l))); - // 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]; - } - assert((r_i == k) && (update == (k - l))); - // 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; - idx_hits(r_hits, r_g->n_seq); -} - -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 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;///rid|rev|uid - p->off = offset; - offset += (uint32_t)u->a[i]; - } - else - { - offset += GAP_LEN; - } - } - } - - radix_sort_hit_aux_ruid(x.a, x.a + x.n);///sort by (rid|rev|uid) - x.idx.n = x.idx.m = (x.n?(x.a[x.n-1].ruid>>33)+1:0);///how many reads? - 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->u.n; 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 = ((occ_1 == 1) && (occ_2 == 1)); - 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, - opt->gap_fuzz, &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, w, k, nv, vx, wx; - asg_arc_t *av = NULL; - ma_utg_t *u = NULL; - - for (i = 0; i < sg->n_arc; i++) sg->arc[i].del = (!!1); - for (i = 0; i < sg->n_seq; i++) sg->seq[i].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); - } - - if(u->circ) { - v = w = i<<1; - 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;///res keeps all intervals with >= cutoff coverage - 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); -} - -int append_sub_utg(ma_ug_t *ug, asg_t *rg, uint64_t uid, uint64_t sidx, uint64_t eidx, uint64_t *rsidx, uint64_t *reidx) -{ - if(eidx <= sidx) return 0; - uint64_t i, offset; - ma_utg_t *u = &(ug->u.a[uid]), *p = NULL; - if(u->a[sidx] == (uint64_t)-1) sidx++; - if(u->a[eidx-1] == (uint64_t)-1) eidx--; - if(eidx <= sidx) return 0 ; - kv_pushp(ma_utg_t, ug->u, &p); - memset(p, 0, sizeof(*p)); - if(rsidx) (*rsidx) = sidx; - if(reidx) (*reidx) = eidx; - p->m = p->n = eidx - sidx; - MALLOC(p->a, p->m); - memcpy(p->a, u->a + sidx, p->n*sizeof(uint64_t)); - p->start = p->a[0]>>32; - p->end = (p->a[p->n-1]>>32)^1; - p->a[p->n-1] >>= 32; p->a[p->n-1] <<= 32; - p->a[p->n-1] += rg->seq[(p->a[p->n-1]>>33)].len; - - p->circ = 0; - for (i = offset = 0; i < p->n; i++) - { - offset += (p->a[i] != (uint64_t)-1? (uint32_t)p->a[i]:GAP_LEN); - } - p->len = offset; - return 1; -} - -uint64_t get_utg_len(ma_ug_t *ug) -{ - uint64_t i, s; - for (i = s = 0; i < ug->u.n; ++i) - { - if(!ug->u.a[i].a) continue; - s += ug->u.a[i].len; - } - - return s; -} -void break_utg_horder(horder_t *h, h_covs *b_points) -{ - if(b_points->n == 0) return; - kvec_t(uint64_t) join; kv_init(join); - ma_ug_t *ug = h->ug; - uint64_t k, l, i, idx, m, pidx, de_u, u_n, oug_n = ug->u.n, dug_n = 0, puid, nuid[2], ps, pe; - radix_sort_h_cov_s(b_points->a, b_points->a+b_points->n); - - for (k = 1, l = 0; k <= b_points->n; ++k) - { - if (k == b_points->n || b_points->a[k].s != b_points->a[l].s) - { - de_u = 0; - radix_sort_h_cov_e(b_points->a+l, b_points->a+k); - u_n = ug->u.a[b_points->a[l].s].n; - for (i = l, pidx = 0; i < k; i++) - { - idx = b_points->a[i].e + 1; - if(idx > pidx && idx - pidx < u_n) - { - if(append_sub_utg(h->ug, h->r_g, b_points->a[l].s, pidx, idx, NULL, NULL)) - { - de_u++; - kv_push(uint64_t, join, (b_points->a[l].s<<32)|(ug->u.n-1)); - } - } - pidx = idx; - } - - idx = u_n; - if(idx > pidx && idx - pidx < u_n) - { - if(append_sub_utg(h->ug, h->r_g, b_points->a[l].s, pidx, idx, NULL, NULL)) - { - de_u++; - kv_push(uint64_t, join, (b_points->a[l].s<<32)|(ug->u.n-1)); - } - } - - if(de_u) - { - free(ug->u.a[b_points->a[l].s].a); free(ug->u.a[b_points->a[l].s].s); - memset(&(ug->u.a[b_points->a[l].s]), 0, sizeof(ug->u.a[b_points->a[l].s])); - dug_n++; - } - - l = k; - } - } - - // fprintf(stderr, "oug_n-%lu, dug_n-%lu\n", oug_n, dug_n); - // for (i = 0; i < join.n; i++) - // { - // fprintf(stderr, "+puid-%lu, nuid-%u\n", join.a[i]>>32, (uint32_t)join.a[i]); - // } - - for (i = 0; i < join.n; i++) - { - join.a[i] -= dug_n; - } - - for (i = m = 0; i < ug->u.n; i++) - { - if(!ug->u.a[i].a) continue; - if(i < oug_n) kv_push(uint64_t, join, (i<<32)|(m)); - ug->u.a[m] = ug->u.a[i]; - m++; - } - - if(m < ug->u.n) - { - for (i = m; i < ug->u.n; i++) - { - memset(&(ug->u.a[i]), 0, sizeof(ug->u.a[i])); - } - ug->u.n = m; - } - - // for (i = 0; i < join.n; i++) - // { - // fprintf(stderr, "-puid-%lu, nuid-%u\n", join.a[i]>>32, (uint32_t)join.a[i]); - // } - - oug_n = h->avoid.n; - radix_sort_ho64(join.a, join.a+join.n); - for (k = 1, l = 0; k <= join.n; ++k) - { - if (k == join.n || ((join.a[k]>>32) != (join.a[l]>>32))) - { - puid = (join.a[l]>>32); - nuid[0] = (uint32_t)join.a[l]; - nuid[0] <<= 1; - - nuid[1] = (uint32_t)join.a[k-1]; - nuid[1] <<= 1; nuid[1] += 1; - - for (i = 0; i < oug_n; i++) - { - ps = h->avoid.a[i]>>32; - pe = (uint32_t)h->avoid.a[i]; - - if((ps>>1) == puid) ps = nuid[ps&1]; - if((pe>>1) == puid) pe = nuid[pe&1]; - - h->avoid.a[i] = (ps<<32)|pe; - } - - if(k - l > 1) - { - for (i = l; i + 1 < k; i++) - { - nuid[0] = (uint32_t)join.a[i]; - nuid[0] <<=1; nuid[0] += 1; - - nuid[1] = (uint32_t)join.a[i+1]; - nuid[1] <<=1; - kv_push(uint64_t, h->avoid, (nuid[0]<<32)|(nuid[1])); - } - } - - l = k; - } - } - - radix_sort_ho64(h->avoid.a, h->avoid.a + h->avoid.n); - - // for (i = 0; i < h->avoid.n; i++) - // { - // fprintf(stderr, "break-s-%lu (dir: %lu), break-e-%u (dir: %u)\n", - // h->avoid.a[i]>>33, (h->avoid.a[i]>>32)&1, - // ((uint32_t)h->avoid.a[i])>>1, ((uint32_t)h->avoid.a[i])&1); - // } - - kv_destroy(join); -} - - -void update_nus(ma_utg_t *u, ma_ug_t *ug, h_cov_t *a, uint64_t a_n) -{ - uint64_t i, k, offset; - for (i = offset = 0; i < u->n; i++) - { - for (k = 0; k < a_n; k++) - { - if(a[k].s == i) - { - a[k].s = offset; a[k].e += offset; - if(k + 1 == a_n) return; - } - - } - offset += (u->a[i] != (uint64_t)-1? (uint32_t)u->a[i]:GAP_LEN); - } -} - -void break_contig(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? - - /*******************************for debug************************************/ - // 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); - /*******************************for debug************************************/ - - 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; - /*******************************for debug************************************/ - // fprintf(stderr, "cutoff: %lu, bs: %lu, be: %lu\n", cutoff, bs, be); - /*******************************for debug************************************/ - } - } - - if(res.n > 0) - { - get_consensus_break(&res, &cov_buf); - /*******************************for debug************************************/ - // 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); - // } - /*******************************for debug************************************/ - 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 = get_hit_suid(*hits, l); p->e = bs; p->dp = dp; - /*******************************for debug************************************/ - // 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); - /*******************************for debug************************************/ - } - - } - l = k; - } - } - - break_utg_horder(h, &b_points); - - kv_destroy(b); - kv_destroy(cov_buf); - kv_destroy(res); - kv_destroy(b_points); -} - -asg_arc_t *get_r_edge(asg_t *rg, uint64_t v, uint64_t w, uint64_t *id) -{ - asg_arc_t *av = asg_arc_a(rg, v); - uint64_t nv = asg_arc_n(rg, v), k; - if(id) (*id) = (uint64_t)-1; - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - if(id) (*id) = (rg->idx[v]>>32) + k; - return &(av[k]); - } - } - return NULL; -} - -void update_unitig_ends(asg_t *g, asg_arc_t *arc, uint64_t puid, uint64_t nuid_0, uint64_t nuid_1) -{ - uint64_t nv, k, v, idx, ridx; - - - v = puid<<1; - idx = g->idx[v]>>32; nv = asg_arc_n(g, v); - for (k = 0; k < nv; k++) - { - arc[idx+k].ul = ((uint32_t)arc[idx+k].ul) + (nuid_0<<32); - get_r_edge(g, g->arc[idx+k].v^1, v^1, &ridx); - arc[ridx].v = nuid_0^1; - } - - - v = (puid<<1)+1; - idx = g->idx[v]>>32; nv = asg_arc_n(g, v); - for (k = 0; k < nv; k++) - { - arc[idx+k].ul = ((uint32_t)arc[idx+k].ul) + (nuid_1<<32); - get_r_edge(g, g->arc[idx+k].v^1, v^1, &ridx); - arc[ridx].v = nuid_1^1; - } -} - - - -int get_switch_ovlp_hits(uint64_t *i, uint64_t pid, uint64_t ls, uint64_t le, u_trans_hit_t *hit, -h_covs *join, uint64_t *idx) -{ - uint64_t os, oe; - hit->qSpre = hit->qEpre = hit->qScur = hit->qEcur = hit->qn = (uint32_t)-1; - hit->tSpre = hit->tEpre = hit->tScur = hit->tEcur = hit->tn = (uint32_t)-1; - - while ((*i) < ((uint32_t)idx[pid])) - { - os = join->a[(idx[pid]>>32)+(*i)].s; - oe = join->a[(idx[pid]>>32)+(*i)].e; - if(OVL(os, oe, ls, le) == 0) - { - (*i)++; - continue; - } - - hit->qn = (uint32_t)(join->a[(idx[pid]>>32)+(*i)].dp); - hit->qScur = MAX(os, ls); hit->qEcur = MIN(oe, le); - hit->qSpre = hit->qScur - os; hit->qEpre = hit->qEcur - os; - (*i)++; - return 1; - } - - return 0; -} - -///[ts, te) -void extract_switch_sub(uint32_t i_tScur, uint32_t i_tEcur, uint32_t i_tSpre, uint32_t i_tEpre, -uint32_t tn, kv_u_trans_hit_t* ktb, uint32_t bn, uint32_t rev) -{ - uint32_t i, ovlp, found, beg, end, offS, offE; - u_trans_hit_t *q = NULL, x; - for (i = found = 0; i < bn; i++) - { - q = &(ktb->a[i]);///for q, already know [qScur, qEcur), [qSpre, qEpre), [tScur, tEcur) - - ovlp = ((MIN(i_tEcur, q->tEcur) > MAX(i_tScur, q->tScur))? - MIN(i_tEcur, q->tEcur) - MAX(i_tScur, q->tScur):0); - if(found == 1 && ovlp == 0) break; - if(ovlp > 0) found = 1; - if(ovlp == 0) continue; - - - beg = MAX(i_tScur, q->tScur); end = MIN(i_tEcur, q->tEcur); - offS = beg - q->tScur; offE = q->tEcur - end; - x.tScur = q->tScur + offS; //beg - x.tEcur = q->tEcur - offE; //end - - - x.qn = q->qn; - offS = beg - q->tScur; offE = q->tEcur - end; - if(rev == 0) - { - // x.qSpre = q->qSpre + offS; - x.qSpre = q->qSpre + get_offset_adjust(offS, q->tEcur-q->tScur, q->qEpre-q->qSpre); - // x.qEpre = q->qEpre - offE; - x.qEpre = q->qEpre - get_offset_adjust(offE, q->tEcur-q->tScur, q->qEpre-q->qSpre); - } - else - { - // x.qSpre = q->qSpre + offE; - x.qSpre = q->qSpre + get_offset_adjust(offE, q->tEcur-q->tScur, q->qEpre-q->qSpre); - // x.qEpre = q->qEpre - offS; - x.qEpre = q->qEpre - get_offset_adjust(offS, q->tEcur-q->tScur, q->qEpre-q->qSpre); - } - - x.tn = tn; - offS = beg - i_tScur; offE = i_tEcur - end; - // x.tSpre = i_tSpre + offS; - x.tSpre = i_tSpre + get_offset_adjust(offS, i_tEcur-i_tScur, i_tEpre-i_tSpre); - // x.tEpre = i_tEpre - offE; - x.tEpre = i_tEpre - get_offset_adjust(offE, i_tEcur-i_tScur, i_tEpre-i_tSpre); - - kv_push(u_trans_hit_t, *ktb, x); - - // if(x.tSpre >= x.tEpre || x.qSpre >= x.qEpre) - // { - // fprintf(stderr, "\n*********x.qn: %u, x.tn: %u\n", x.qn, x.tn); - // fprintf(stderr, "x.qSpre: %u, x.qEpre: %u, x.tSpre: %u, x.tEpre: %u\n", - // x.qSpre, x.qEpre, x.tSpre, x.tEpre); - // fprintf(stderr, "q->qScur: %u, q->qEcur: %u, q->qSpre: %u, q->qEpre: %u\n", - // q->qScur, q->qEcur, q->qSpre, q->qEpre); - // fprintf(stderr, "q->tScur: %u, q->tEcur: %u, q->tSpre: %u, q->tEpre: %u\n", - // q->tScur, q->tEcur, q->tSpre, q->tEpre); - // fprintf(stderr, "i_tScur: %u, i_tEcur: %u, i_tSpre: %u, i_tEpre: %u\n", - // i_tScur, i_tEcur, i_tSpre, i_tEpre); - // } - } -} - - -void extract_novlp(u_trans_t *e, h_covs *join, uint64_t *idx, kv_u_trans_hit_t *kv, kv_u_trans_t *n_trans) -{ - uint64_t i, bn; - u_trans_hit_t hit, *kh = NULL; - u_trans_t *kt = NULL; - kv->n = 0; - - i = 0; - while (get_switch_ovlp_hits(&i, e->qn, e->qs, e->qe, &hit, join, idx)) //get [qScur, qEcur), [qSpre, qEpre) - { - if(e->rev == 0) - { - hit.tScur = e->ts + get_offset_adjust(hit.qScur-e->qs, e->qe-e->qs, e->te-e->ts); - hit.tEcur = e->te - get_offset_adjust(e->qe-hit.qEcur, e->qe-e->qs, e->te-e->ts); - } - else - { - hit.tScur = e->ts + get_offset_adjust(e->qe-hit.qEcur, e->qe-e->qs, e->te-e->ts); - hit.tEcur = e->te - get_offset_adjust(hit.qScur-e->qs, e->qe-e->qs, e->te-e->ts); - } - - kv_push(u_trans_hit_t, *kv, hit); - } - bn = kv->n; - - i = 0; - while (get_switch_ovlp_hits(&i, e->tn, e->ts, e->te, &hit, join, idx)) - { - extract_switch_sub(hit.qScur, hit.qEcur, hit.qSpre, hit.qEpre, hit.qn, kv, bn, e->rev); - } - - double x_score, y_score; - for (i = bn; i < kv->n; i++) - { - kh = &(kv->a[i]); - if(kh->qEpre <= kh->qSpre) continue; - if(kh->tEpre <= kh->tSpre) continue; - kv_pushp(u_trans_t, *n_trans, &kt); - - kt->f = e->f; kt->rev = e->rev; kt->del = 0; - kt->qn = kh->qn; kt->qs = kh->qSpre; kt->qe = kh->qEpre; - kt->tn = kh->tn; kt->ts = kh->tSpre; kt->te = kh->tEpre; - - x_score = ((double)(kt->qe-kt->qs)/(double)(e->qe-e->qs))*e->nw; - y_score = ((double)(kt->te-kt->ts)/(double)(e->te-e->ts))*e->nw; - kt->nw = MIN(x_score, y_score); - kt->occ = 0; - - // if(kv->n - bn > 1) - // { - // fprintf(stderr, "-kt-utg%.6ul\tqs(%u)\tqe(%u)\tt-utg%.6ul\tts(%u)\tte(%u)\trev(%u)\tw(%f)\tf(%u)\n", - // kt->qn+1, kt->qs, kt->qe, kt->tn+1, kt->ts, kt->te, kt->rev, kt->nw, kt->f); - // } - - } -} - -int get_new_offset(kvec_pe_hit *hits, uint64_t id, uint64_t *index, h_covs *join, uint64_t new_uID_bits) -{ - uint64_t suid, sbeg, send, k, uid, os, oe, ls, le, occ, nuid, noff; - uint64_t euid, ebeg, eend; - resolve_hit(hits->a.a[id].s, hits->a.a[id].len>>32, hits->uID_bits, - hits->pos_mode, &suid, &sbeg, &send); - uid = suid; ls = sbeg; le = send; occ = 0; nuid = noff = (uint64_t)-1; - for (k = 0; k < ((uint32_t)index[uid]); k++) - { - os = join->a[(index[uid]>>32)+k].s; - oe = join->a[(index[uid]>>32)+k].e; - if(ls >= os && le <= oe) - { - occ++; - nuid = (uint32_t)join->a[(index[uid]>>32)+k].dp; - noff = os; - } - } - if(occ != 1) return 0; - noff = get_hit_spos(*hits, id) - noff; - nuid <<= (64 - new_uID_bits - 1); - hits->a.a[id].s >>= 63; hits->a.a[id].s <<= 63; - hits->a.a[id].s += nuid + noff; - - - resolve_hit(hits->a.a[id].e, (uint32_t)hits->a.a[id].len, hits->uID_bits, - hits->pos_mode, &euid, &ebeg, &eend); - uid = euid; ls = ebeg; le = eend; occ = 0; nuid = noff = (uint64_t)-1; - for (k = 0; k < ((uint32_t)index[uid]); k++) - { - os = join->a[(index[uid]>>32)+k].s; - oe = join->a[(index[uid]>>32)+k].e; - if(ls >= os && le <= oe) - { - occ++; - nuid = (uint32_t)join->a[(index[uid]>>32)+k].dp; - noff = os; - } - } - if(occ != 1) return 0; - noff = get_hit_epos(*hits, id) - noff; - nuid <<= (64 - new_uID_bits - 1); - hits->a.a[id].e >>= 63; hits->a.a[id].e <<= 63; - hits->a.a[id].e += nuid + noff; - return 1; -} - -void verbose_misjoin(uint64_t *a, uint64_t a_n) -{ - radix_sort_ho64(a, a + a_n); - uint64_t k, l, i, len, s, C[2], N[2]; - C[0] = C[1] = N[0] = N[1] = 0; - for (k = 1, l = 0; k <= a_n; ++k) - { - if (k == a_n || (a[k]>>63) != (a[l]>>63)) - { - for (i = l, s = 0; i < k; i++) s += ((a[i]<<1)>>1); - len = s; - - i = k; s = 0; - while (i > l) - { - i--; - s += ((a[i]<<1)>>1); - if(s >= (len>>1)) - { - N[a[l]>>63] = ((a[i]<<1)>>1); - C[a[l]>>63] = k - l; - // fprintf(stderr, "[M::%s::] N50: %lu\n", __func__, b.a[i]); - break; - } - } - - l = k; - } - } - - fprintf(stderr, "[M::stat] # misjoined unitigs: %lu (N50: %lu); # corrected unitigs: %lu (N50: %lu)\n", - C[0], N[0], C[1], N[1]); -} - -void break_phasing_utg(ma_ug_t *ug, asg_t *rg, kvec_pe_hit *hits, kv_u_trans_t *k_trans, h_covs *b_points) -{ - if(b_points->n == 0) return; - kv_u_trans_hit_t kv; kv_init(kv); - asg_arc_t *rt = NULL, *ut = NULL; - asg_t *utg = NULL; - h_cov_t *p = NULL; - h_covs join; kv_init(join); - uint64_t k, l, i, idx, m, pidx, de_u, u_n, oug_n = ug->u.n, dug_n = 0, puid, pn, rsi, prid, nrid, x, y, *index = NULL; - kv_u_trans_t *n_trans = NULL; CALLOC(n_trans, 1); - kvec_t(uint64_t) dbg_N50; kv_init(dbg_N50); - /*******************************for debug************************************/ - // debug_phasing_t *dbp = init_debug_phasing(ug, hits, k_trans, b_points); - /*******************************for debug************************************/ - radix_sort_h_cov_s(b_points->a, b_points->a+b_points->n); - for (k = 1, l = 0; k <= b_points->n; ++k) - { - if (k == b_points->n || b_points->a[k].s != b_points->a[l].s) - { - de_u = 0; pn = join.n; - radix_sort_h_cov_e(b_points->a+l, b_points->a+k); - u_n = ug->u.a[b_points->a[l].s].n; - for (i = l, pidx = 0; i < k; i++) - { - idx = b_points->a[i].e + 1; - if(idx > pidx && idx - pidx < u_n) - { - // fprintf(stderr, "sa-utg%.6lul, pidx: %lu, idx: %lu\n", b_points->a[l].s+1, pidx, idx); - if(append_sub_utg(ug, rg, b_points->a[l].s, pidx, idx, &rsi, NULL)) - { - de_u++; - kv_pushp(h_cov_t, join, &p); - p->dp = (b_points->a[l].s<<32)|(ug->u.n-1); - p->s = rsi; p->e = ug->u.a[ug->u.n-1].len; - kv_push(uint64_t, dbg_N50, (uint64_t)(ug->u.a[ug->u.n-1].len)+((uint64_t)(1)<<63));///new nodes - } - } - pidx = idx; - } - - idx = u_n; - if(idx > pidx && idx - pidx < u_n) - { - // fprintf(stderr, "sa-utg%.6lul, pidx: %lu, idx: %lu\n", b_points->a[l].s+1, pidx, idx); - if(append_sub_utg(ug, rg, b_points->a[l].s, pidx, idx, &rsi, NULL)) - { - de_u++; - kv_pushp(h_cov_t, join, &p); - p->dp = (b_points->a[l].s<<32)|(ug->u.n-1); - p->s = rsi; p->e = ug->u.a[ug->u.n-1].len; - kv_push(uint64_t, dbg_N50, (uint64_t)(ug->u.a[ug->u.n-1].len)+((uint64_t)(1)<<63));///new nodes - } - } - - if(de_u) - { - kv_push(uint64_t, dbg_N50, ug->u.a[b_points->a[l].s].len);///old nodes - update_nus(&(ug->u.a[b_points->a[l].s]), ug, join.a + pn, join.n - pn); - free(ug->u.a[b_points->a[l].s].a); free(ug->u.a[b_points->a[l].s].s); - memset(&(ug->u.a[b_points->a[l].s]), 0, sizeof(ug->u.a[b_points->a[l].s])); - dug_n++; - } - - l = k; - } - } - // fprintf(stderr, "oug_n-%lu, dug_n-%lu\n", oug_n, dug_n); - // for (i = 0; i < join.n; i++) - // { - // fprintf(stderr, "+p-utg%.6lul, n-utg%.6ul\n", (join.a[i].dp>>32)+1, ((uint32_t)join.a[i].dp)+1); - // } - - for (i = 0; i < join.n; i++) - { - join.a[i].dp -= dug_n; - } - for (i = m = 0; i < ug->u.n; i++) - { - if(!ug->u.a[i].a) continue; - if(i < oug_n) - { - kv_pushp(h_cov_t, join, &p); - p->dp = (i<<32)|(m);///current id | updated id - p->s = 0; p->e = ug->u.a[i].len; - } - - ug->u.a[m] = ug->u.a[i]; - m++; - } - if(m < ug->u.n) - { - for (i = m; i < ug->u.n; i++) - { - memset(&(ug->u.a[i]), 0, sizeof(ug->u.a[i])); - } - ug->u.n = m; - } - radix_sort_h_cov_dp(join.a, join.a+join.n); - CALLOC(index, ug->u.n); - // for (i = 0; i < join.n; i++) - // { - // fprintf(stderr, "+p-utg%.6lul (len: %u), n-utg%.6ul, s-%lu, e-%lu\n", - // (join.a[i].dp>>32)+1, ug->g->seq[(join.a[i].dp>>32)].len, ((uint32_t)join.a[i].dp)+1, join.a[i].s, join.a[i].e); - // } - utg = asg_init(); - utg->n_arc = utg->m_arc = ug->g->n_arc; - MALLOC(utg->arc, utg->n_arc); - memcpy(utg->arc, ug->g->arc, utg->n_arc*sizeof(asg_arc_t)); - for (k = 1, l = 0; k <= join.n; ++k) - { - if (k == join.n || ((join.a[k].dp>>32) != (join.a[l].dp>>32))) - { - puid = (join.a[l].dp>>32); - index[puid] = (l<<32) | (k-l); - - for (i = l; i < k; i++) - { - asg_seq_set(utg, (uint32_t)join.a[i].dp, ug->u.a[(uint32_t)join.a[i].dp].len, 0); - utg->seq[(uint32_t)join.a[i].dp].c = ug->g->seq[puid].c; - - if(i + 1 >= k) continue; - prid = ug->u.a[(uint32_t)join.a[i].dp].a[ug->u.a[(uint32_t)join.a[i].dp].n-1]>>32; - nrid = ug->u.a[(uint32_t)join.a[i+1].dp].a[0]>>32; - - rt = get_r_edge(rg, prid, nrid, NULL); - ut = asg_arc_pushp(utg); - x = (uint32_t)join.a[i].dp; x <<= 1; - y = (uint32_t)join.a[i+1].dp; y <<= 1; - ut->ol = rt->ol, ut->del = 0; - ut->ul = (uint64_t)x<<32 | (ug->u.a[x>>1].len - ut->ol); - ut->v = y; - - rt = get_r_edge(rg, nrid^1, prid^1, NULL); - ut = asg_arc_pushp(utg); - x = (uint32_t)join.a[i+1].dp; x <<= 1; x++; - y = (uint32_t)join.a[i].dp; y <<= 1; y++; - ut->ol = rt->ol, ut->del = 0; - ut->ul = (uint64_t)x<<32 | (ug->u.a[x>>1].len - ut->ol); - ut->v = y; - } - update_unitig_ends(ug->g, utg->arc, puid, ((uint32_t)join.a[k-1].dp)<<1, (((uint32_t)join.a[l].dp)<<1)+1); - l = k; - } - } - asg_cleanup(utg); - asg_destroy(ug->g); - ug->g = utg; - - for (k = 0; k < k_trans->n; k++) - { - extract_novlp(&(k_trans->a[k]), &join, index, &kv, n_trans); - } - free(k_trans->a); free(k_trans->idx.a); memset(k_trans, 0, sizeof(*k_trans)); - k_trans->a = n_trans->a; k_trans->n = n_trans->n; k_trans->m = n_trans->m; - free(n_trans); - - clean_u_trans_t_idx_adv(k_trans, ug, rg); - // clean_u_trans_t_idx(k_trans, ug, rg); - - - uint64_t uID_bits, pos_mode; - for (uID_bits=1; (uint64_t)(1<u.n; uID_bits++); - pos_mode = ((uint64_t)-1)>>(uID_bits+1); - - for (k = m = 0; k < hits->a.n; k++) - { - if(get_new_offset(hits, k, index, &join, uID_bits)) - { - hits->a.a[m] = hits->a.a[k]; - m++; - } - } - // fprintf(stderr, "hits->a.n: %u, m: %lu\n", (uint32_t)hits->a.n, m); - hits->a.n = m; - - dedup_hits(hits, 0); - hits->uID_bits = uID_bits; hits->pos_mode = pos_mode; - free(hits->idx.a); hits->idx.a = NULL; hits->idx.n = hits->idx.m = 0; - free(hits->occ.a); hits->occ.a = NULL; hits->occ.n = hits->occ.m = 0; - - /*******************************for debug************************************/ - // debug_debug_phasing_t(dbp, ug, hits, k_trans, &join, index); - // destory_debug_phasing_t(&dbp); - /*******************************for debug************************************/ - verbose_misjoin(dbg_N50.a, dbg_N50.n); - kv_destroy(join); kv_destroy(kv); free(index); kv_destroy(dbg_N50); -} - -///min_ulen = BREAK_THRES -///boundaryRate = BREAK_BOUNDARY -void update_switch_unitig(ma_ug_t *ug, asg_t *rg, kvec_pe_hit *hits, kv_u_trans_t *k_trans, uint64_t cutoff_s, uint64_t cutoff_e, -uint64_t min_ulen, double boundaryRate) -{ - 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; - radix_sort_pe_hit_idx_hn1(hits->a.a, hits->a.a + hits->a.n); - 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 >= min_ulen) - { - 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? - - /*******************************for debug************************************/ - // 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); - /*******************************for debug************************************/ - - 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*boundaryRate, ulen - ulen*boundaryRate, &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; - /*******************************for debug************************************/ - // fprintf(stderr, "cutoff: %lu, bs: %lu, be: %lu\n", cutoff, bs, be); - /*******************************for debug************************************/ - } - } - - if(res.n > 0) - { - get_consensus_break(&res, &cov_buf); - /*******************************for debug************************************/ - // 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); - // } - /*******************************for debug************************************/ - ///res -> all low coverage intervals; - ///cov_buf -> consensus coverage intervals; - get_read_breaks(&(ug->u.a[get_hit_suid(*hits, l)]), rg, &cov_buf, - &res, hits, l, k, ulen, &bs, &dp); - if(bs == (uint64_t)-1) fprintf(stderr, "ERROR-read\n"); - - if(bs > 0 && bs < ug->u.a[get_hit_suid(*hits, l)].n) - { - kv_pushp(h_cov_t, b_points, &p); - p->s = get_hit_suid(*hits, l); p->e = bs; p->dp = dp; - /*******************************for debug************************************/ - // fprintf(stderr, "\n[M::%s::] utg%.6lul, consensus_break-rid: %lu, cov: %lu, un: %u\n", - // __func__, get_hit_suid(*hits, l)+1, bs, dp, ug->u.a[get_hit_suid(*hits, l)].n); - // debug_sub_cov(hits, l, k, ulen, &(ug->u.a[get_hit_suid(*hits, l)]), h->r_g, bs, dp); - /*******************************for debug************************************/ - } - - } - - } - l = k; - } - } - // break_utg_horder(h, &b_points); - break_phasing_utg(ug, rg, hits, k_trans, &b_points); - - kv_destroy(b); - kv_destroy(cov_buf); - kv_destroy(res); - kv_destroy(b_points); -} - -void get_Ns(ma_utg_t *u, h_covs *Ns) -{ - uint64_t i, offset; - h_cov_t *p = NULL; - Ns->n = 0; - for (i = offset = 0; i < u->n; i++) - { - if(u->a[i] == (uint64_t)-1) - { - kv_pushp(h_cov_t, *Ns, &p); - p->s = offset; - p->e = offset + GAP_LEN; - p->dp = i; - } - offset += (u->a[i] != (uint64_t)-1? (uint32_t)u->a[i]:GAP_LEN); - } -} - -void debug_sub_cov(kvec_pe_hit *hits, uint64_t sidx, uint64_t eidx, uint64_t ulen, -uint64_t rs, uint64_t re, uint64_t limit_s, uint64_t limit_e, int unique_only) -{ - uint64_t i, p0s, p0e, p1s, p1e, span_s, span_e, cnt = 0, cnt_no_lim = 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; - if(unique_only && hits->a.a[i].id == 0) 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_no_lim++; - if(span_s >= limit_s && span_e <= limit_e) cnt++; - } - } - - fprintf(stderr, "******cnt-%lu, cnt_no_lim-%lu, rs-%lu, re-%lu, limit_s-%lu, limit_e-%lu\n", cnt, cnt_no_lim, rs, re, limit_s, limit_e); -} - -uint64_t get_sub_cov(kvec_pe_hit *hits, uint64_t sidx, uint64_t eidx, uint64_t ulen, -uint64_t rs, uint64_t re, uint64_t limit_s, uint64_t limit_e, int unique_only) -{ - uint64_t i, p0s, p0e, p1s, p1e, span_s, span_e, cnt = 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; - if(unique_only && hits->a.a[i].id == 0) 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) - { - if(span_s >= limit_s && span_e <= limit_e) cnt++; - } - } - - return cnt; -} - -int detect_lowNs(kvec_pe_hit *hit, uint64_t sHit, uint64_t eHit, kvec_t_u64_warp *b, -h_cov_t *Np, uint64_t len, uint64_t cutoff_s, uint64_t cutoff_e, uint64_t force_cutoff, uint64_t force_cutoff_cov, -h_covs *res, h_covs *cov_buf, h_covs *b_points, uint64_t local_bound, int unique_only) -{ - uint64_t cov_hic, cov_utg, cov_ava, i, p0s, p0e, p1s, p1e, span_s, span_e, cutoff, bs, be, occ = 0; - uint64_t sPos, ePos, min_cutoff; - h_cov_t *p = NULL; - b->a.n = 0; cov_hic = cov_utg = 0; - sPos = (Np->s>=local_bound? Np->s-local_bound:0); - ePos = (Np->e+local_bound<=len? Np->e+local_bound:len); - for (i = sHit; i < eHit; i++) - { - if(get_hit_suid(*hit, i) != get_hit_euid(*hit, i)) continue; - - p0s = get_hit_spos(*hit, i); - p0e = get_hit_spos_e(*hit, i); - p1s = get_hit_epos(*hit, i); - p1e = get_hit_epos_e(*hit, i); - - span_s = MIN(MIN(p0s, p0e), MIN(p1s, p1e)); - span_s = MIN(span_s, len-1); - span_e = MAX(MAX(p0s, p0e), MAX(p1s, p1e)); - span_e = MIN(span_e, len-1) + 1; - //if(span_e - span_s <= ulen*BREAK_CUTOFF)//need it or not? - { - if(span_s >= sPos && span_e <= ePos)///test the density of this local region; bug -> should use any HiC pairs that are overlapped with [sPos, sPoe), instead of fully covered by [sPos, sPoe) - { - occ++; - if(unique_only && hit->a.a[i].id == 0) continue; - kv_push(uint64_t, b->a, (span_s<<1)); - kv_push(uint64_t, b->a, (span_e<<1)|1); - cov_hic += (span_e - span_s); - } - } - } - - - - radix_sort_ho64(b->a.a, b->a.a+b->a.n); - cov_utg = get_hic_cov_interval(b->a.a, b->a.n, 1, NULL, NULL, NULL); - cov_ava = (cov_utg? cov_hic/cov_utg:0); - if(force_cutoff != (uint64_t)-1 || force_cutoff_cov != (uint64_t)-1) - { - min_cutoff = get_sub_cov(hit, sHit, eHit, len, Np->s, Np->e, sPos, ePos, unique_only); - if((force_cutoff != (uint64_t)-1 && min_cutoff <= (cov_ava/force_cutoff)) || - (force_cutoff_cov != (uint64_t)-1 && min_cutoff <= force_cutoff_cov)) - { - kv_pushp(h_cov_t, *b_points, &p); - p->s = get_hit_suid(*hit, sHit); p->e = Np->dp; p->dp = 0; - return 1; - } - } - - ///if cov_ava == 0, do nothing or break? - /*******************************for debug************************************/ - // 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(*hit, sHit)+1, len, (uint64_t)(b->a.n>>1), cov_hic, cov_utg, cov_ava); - /*******************************for debug************************************/ - - // fprintf(stderr, "[M::%s::] sPos: %lu, ePos: %lu, # hits: %lu, # non-unique hits: %lu, cov_hic: %lu, cov_utg: %lu, cov_ava: %lu\n", - // __func__, sPos, ePos, (uint64_t)(b->a.n>>1), occ, cov_hic, cov_utg, cov_ava); - // debug_sub_cov(hit, sHit, eHit, len, Np->s, Np->e, sPos, ePos, unique_only); - 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.a, b->a.n, cutoff, cov_buf, sPos + (ePos-sPos)*BREAK_BOUNDARY, - ePos - (ePos-sPos)*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; - /*******************************for debug************************************/ - // fprintf(stderr, "cutoff: %lu, bs: %lu, be: %lu\n", cutoff, bs, be); - /*******************************for debug************************************/ - } - } - - if(res->n > 0) - { - get_consensus_break(res, cov_buf); - /*******************************for debug************************************/ - // 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); - // } - /*******************************for debug************************************/ - for (i = 0, min_cutoff = (uint64_t)-1; i < cov_buf->n; i++) - { - if(cov_buf->a[i].s<=Np->s && cov_buf->a[i].e>=Np->e) - { - break; - } - min_cutoff = MIN(min_cutoff, cov_buf->a[i].dp); - } - if(i < cov_buf->n || - get_sub_cov(hit, sHit, eHit, len, Np->s, Np->e, sPos, ePos, unique_only) <= min_cutoff) - { - kv_pushp(h_cov_t, *b_points, &p); - p->s = get_hit_suid(*hit, sHit); p->e = Np->dp; p->dp = 0; - return 1; - /*******************************for debug************************************/ - // fprintf(stderr, "consensus_break-rid: %lu\n", p->e); - /*******************************for debug************************************/ - } - } - return 0; -} - -uint64_t break_scaffold(horder_t *h, uint64_t cutoff_s, uint64_t cutoff_e, uint64_t force_cutoff, uint64_t force_cutoff_cov, -uint64_t local_bound, int unique_only, h_covs *r_b_points) -{ - uint64_t k, l, i, ulen; - kvec_t_u64_warp b; kv_init(b.a); - h_covs cov_buf; kv_init(cov_buf); - h_covs res; kv_init(res); - h_covs *b_points = NULL; - if(r_b_points) b_points = r_b_points; - else CALLOC(b_points, 1); - b_points->n = 0; - h_covs Ns; kv_init(Ns); - ma_ug_t *ug = h->ug; - kvec_pe_hit *hits = &(h->u_hits); - 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; - Ns.n = 0; - if(ulen >= BREAK_THRES) - { - get_Ns(&(ug->u.a[get_hit_suid(*hits, l)]), &Ns); - // fprintf(stderr, "\n[M::%s::] utg%.6lul, ulen: %lu, # Ns: %lu\n", - // __func__, get_hit_suid(*hits, l)+1, ulen, (uint64_t)(Ns.n)); - if(Ns.n) - { - for (i = 0; i < Ns.n; i++) - { - if(detect_lowNs(hits, l, k, &b, &(Ns.a[i]), ulen, cutoff_s, cutoff_e, force_cutoff, - force_cutoff_cov, &res, &cov_buf, b_points, local_bound, unique_only) && r_b_points){ - b_points->a[b_points->n-1].dp = i; - } - } - } - } - l = k; - } - } - - if(!r_b_points){ - break_utg_horder(h, b_points); - kv_destroy(*b_points); - } - - kv_destroy(b.a); - kv_destroy(cov_buf); - kv_destroy(res); - kv_destroy(Ns); - - return b_points->n; -} - -uint64_t break_scaffold_mean(horder_t *h, uint64_t cutoff_s, uint64_t cutoff_e, uint64_t force_cutoff, uint64_t force_cutoff_cov, -uint64_t local_bound, int unique_only, h_covs *r_b_points) -{ - uint64_t k, l, i, ulen; - kvec_t_u64_warp b; kv_init(b.a); - h_covs cov_buf; kv_init(cov_buf); - h_covs res; kv_init(res); - h_covs *b_points = NULL; - if(r_b_points) b_points = r_b_points; - else CALLOC(b_points, 1); - b_points->n = 0; - h_covs Ns; kv_init(Ns); - ma_ug_t *ug = h->ug; - kvec_pe_hit *hits = &(h->u_hits); - 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; - Ns.n = 0; - // if(ulen >= BREAK_THRES) - { - get_Ns(&(ug->u.a[get_hit_suid(*hits, l)]), &Ns); - if(Ns.n) - { - for (i = 0; i < Ns.n; i++) - { - if(detect_lowNs(hits, l, k, &b, &(Ns.a[i]), ulen, cutoff_s, cutoff_e, force_cutoff, - force_cutoff_cov, &res, &cov_buf, b_points, local_bound, unique_only) && r_b_points){ - b_points->a[b_points->n-1].dp = i; - } - } - } - } - l = k; - } - } - - if(!r_b_points){ - break_utg_horder(h, b_points); - kv_destroy(*b_points); - } - - kv_destroy(b.a); - kv_destroy(cov_buf); - kv_destroy(res); - kv_destroy(Ns); - - return b_points->n; -} - - -void generate_haplotypes(horder_t *h, ug_opt_t *opt) -{ - uint64_t i; - ma_ug_t *ug_1 = NULL, *ug_2 = NULL; - - ug_1 = get_trio_unitig_graph(h->r_g, FATHER, opt); - ug_2 = get_trio_unitig_graph(h->r_g, MOTHER, opt); - // kv_push(uint64_t, h->occ, ug_1->u.n); - // kv_push(uint64_t, h->occ, ug_2->u.n); - - h->ug = ug_1; - - ///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; - } - - ug_1 = NULL; - ma_ug_destroy(ug_2); - asg_destroy(h->ug->g); - h->ug->g = NULL; - - // MALLOC(h->hf.a, h->ug->u.n); h->hf.n = h->hf.m = h->ug->u.n; - // for (i = 0; i < h->ug->u.n; i++) h->hf.a[i] = (i < h->occ.a[0]? 0 : 1); -} - -osg_t *osg_init(void) -{ - return (osg_t*)calloc(1, sizeof(osg_t)); -} - -void osg_destroy(osg_t *g) -{ - if (g == 0) return; - free(g->seq); free(g->idx); free(g->arc); - free(g); -} - -void osg_seq_set(osg_t *g, int sid, int del) -{ - ///just malloc size - if (sid >= (int)g->m_seq) { - g->m_seq = sid + 1; - kv_roundup32(g->m_seq); - g->seq = (osg_seq_t*)realloc(g->seq, g->m_seq * sizeof(osg_seq_t)); - } - - if (sid >= g->n_seq) g->n_seq = sid + 1; - g->seq[sid].del = !!del; -} - -static inline osg_arc_t *osg_arc_pushp(osg_t *g) -{ - if (g->n_arc == g->m_arc) { - g->m_arc = g->m_arc? g->m_arc<<1 : 16; - g->arc = (osg_arc_t*)realloc(g->arc, g->m_arc * sizeof(osg_arc_t)); - } - return &g->arc[g->n_arc++]; -} - -void osg_arc_rm(osg_t *g) -{ - uint32_t e, n; - ///just clean arc requiring: 1. arc it self must be available 2. both the query and target are available - for (e = n = 0; e < g->n_arc; ++e) { - //u and v is the read id - uint32_t u = g->arc[e].u, v = g->arc[e].v; - if (!g->arc[e].del && !g->seq[u>>1].del && !g->seq[v>>1].del) - g->arc[n++] = g->arc[e]; - } - if (n < g->n_arc) { // arc index is out of sync - if (g->idx) free(g->idx); - g->idx = 0; - } - g->n_arc = n; -} - -uint64_t *osg_arc_index_core(size_t max_seq, size_t n, const osg_arc_t *a) -{ - size_t i, last; - uint64_t *idx; - idx = (uint64_t*)calloc(max_seq * 2, 8); - - for (i = 1, last = 0; i <= n; ++i) - if (i == n || a[i-1].u != a[i].u) - idx[a[i-1].u] = (uint64_t)last<<32 | (i - last), last = i; - return idx; -} - -void osg_arc_index(osg_t *g) -{ - if (g->idx) free(g->idx); - g->idx = osg_arc_index_core(g->n_seq, g->n_arc, g->arc); -} - -void osg_cleanup(osg_t *g) -{ - osg_arc_rm(g); - if (!g->is_srt) { - radix_sort_osg(g->arc, g->arc + g->n_arc); - g->is_srt = 1; - } - - if (g->idx == 0) osg_arc_index(g); -} - -double get_max_weight(uint32_t u, uint32_t v, osg_t *g) -{ - double max = 0; - uint32_t i, nv; - osg_arc_t *av = NULL; - - nv = asg_arc_n(g, u); - av = asg_arc_a(g, u); - for (i = 0; i < nv; i++) - { - if(av[i].v == v) continue; - max = MAX(max, av[i].w); - } - - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - for (i = 0; i < nv; i++) - { - if(av[i].v == u) continue; - max = MAX(max, av[i].w); - } - - return max; -} - -dens_idx_t *build_interval_idx(kvec_pe_hit *hits, ma_ug_t *ug) -{ - uint64_t i, k, l, p0s, p0e, p1s, p1e, suid, euid, slen, elen, span_s, span_e; - dens_idx_t *idx = NULL; - CALLOC(idx, 1); - - for (i = 0; i < hits->a.n; i++) { - if(!hits->a.a[i].id) continue; - suid = get_hit_suid(*hits, i); - euid = get_hit_euid(*hits, i); - slen = ug->u.a[suid].len; - elen = ug->u.a[euid].len; - - p0s = get_hit_spos(*hits, i); - p0e = get_hit_spos_e(*hits, i); - span_s = MIN(p0s, p0e); - span_s = MIN(span_s, slen-1); - span_e = MAX(p0s, p0e); - span_e = MIN(span_e, slen-1); - span_s = ((span_s+span_e)>>1); - kv_push(uint64_t, idx->pos, (suid<<32)|span_s); - - - p1s = get_hit_epos(*hits, i); - p1e = get_hit_epos_e(*hits, i); - span_s = MIN(p1s, p1e); - span_s = MIN(span_s, elen-1); - span_e = MAX(p1s, p1e); - span_e = MIN(span_e, elen-1); - span_s = ((span_s+span_e)>>1); - kv_push(uint64_t, idx->pos, (euid<<32)|span_s); - } - radix_sort_ho64(idx->pos.a, idx->pos.a + idx->pos.n); - idx->n = idx->m = ug->u.n; - CALLOC(idx->a, idx->n); - for (k = 1, l = 0; k <= idx->pos.n; ++k) { - if (k == idx->pos.n || ((idx->pos.a[k]>>32) != (idx->pos.a[l]>>32))) { - idx->a[idx->pos.a[l]>>32] = (uint64_t)l << 32 | (k - l); - l = k; - } - } - return idx; -} - -uint64_t get_vw_hits_num(h_w_t *e, uint64_t x, uint64_t y) -{ - uint64_t i, occ; - hw_aux_t *ep = NULL; - for (i = occ = 0; i < e->n; i++) - { - ep = &(e->a[i]); - if(((ep->e>>33) == x && (((uint32_t)(ep->e))>>1) == y) || - ((ep->e>>33) == y && (((uint32_t)(ep->e))>>1) == x)) - { - occ++; - } - } - return occ; -} - -void update_h_w(h_w_t *e, dens_idx_t *idx, double *max_div) -{ - uint64_t k, l, ii, pi, pos, ori, uid, *id = NULL, idn; - if(max_div) (*max_div) = 0; - radix_sort_hw_e(e->a, e->a+e->n); - for (k = 1, l = 0; k <= e->n; ++k) - { - if (k == e->n || (e->a[k].e>>32) != (e->a[l].e>>32)) ///same uid - { - if(k - l > 1) radix_sort_hw_d(e->a+l, e->a+k); - ori = (e->a[l].e>>32)&1; - uid = e->a[l].e>>33; - id = idx->pos.a + (idx->a[uid]>>32); - idn = (uint32_t)(idx->a[uid]); - ii = 0; - for (pi = l; pi < k; pi++) - { - pos = e->a[pi].d>>32;///loc of 3'-end - while (ii < idn) - { - if(((uint32_t)id[ii]) == pos) - { - if(ori)///the most left one - { - break; - } - else - { - while (ii < idn && (((uint32_t)id[ii]) == pos))///the most right one - { - ii++; - } - ii--; - break; - } - } - ii++; - } - if(ii >= idn) fprintf(stderr, "ERROR-1\n"); - e->a[pi].w += (ori? idn-ii: ii+1);///the smaller the better - if(max_div) (*max_div) = MAX((*max_div), e->a[pi].w); - } - l = k; - } - } - - radix_sort_hw_ew(e->a, e->a+e->n); - for (k = 1, l = 0; k <= e->n; ++k) - { - if (k == e->n || ((uint32_t)(e->a[k].e)) != ((uint32_t)(e->a[l].e))) ///same uid - { - if(k - l > 1) radix_sort_hw_dw(e->a+l, e->a+k); - ori = e->a[l].e&1; - uid = (((uint32_t)e->a[l].e)>>1); - id = idx->pos.a + (idx->a[uid]>>32); - idn = (uint32_t)(idx->a[uid]); - ii = 0; - for (pi = l; pi < k; pi++) - { - pos = (uint32_t)(e->a[pi].d);/// - while (ii < idn) - { - if(((uint32_t)id[ii]) == pos) - { - if(ori) - { - break; - } - else - { - while (ii < idn && (((uint32_t)id[ii]) == pos)) - { - ii++; - } - ii--; - break; - } - } - ii++; - } - if(ii >= idn) fprintf(stderr, "ERROR-2\n"); - e->a[pi].w += (ori? idn-ii: ii+1); - if(max_div) (*max_div) = MAX((*max_div), e->a[pi].w); - } - l = k; - } - } - // radix_sort_hw_e(e->a, e->a+e->n); - if(max_div) (*max_div) *= 2;///different with slsa2 -} - -void print_specfic_hic_hits(kvec_pe_hit *hits, uint64_t v, uint64_t w, ma_ug_t *ug) -{ - uint64_t i, suid, euid, slen, elen, p0s, p0e, p1s, p1e, span_s, span_e, sd, ed; - for (i = 0; i < hits->a.n; i++) - { - if(!hits->a.a[i].id) continue; - suid = get_hit_suid(*hits, i); - euid = get_hit_euid(*hits, i); - if((suid == v && euid == w) || (suid == w && euid == v)) - { - slen = ug->u.a[suid].len; - elen = ug->u.a[euid].len; - - p0s = get_hit_spos(*hits, i); - p0e = get_hit_spos_e(*hits, i); - span_s = MIN(p0s, p0e); - span_s = MIN(span_s, slen-1); - span_e = MAX(p0s, p0e); - span_e = MIN(span_e, slen-1); - span_s = ((span_s+span_e)>>1); - sd = span_s; - - - p1s = get_hit_epos(*hits, i); - p1e = get_hit_epos_e(*hits, i); - span_s = MIN(p1s, p1e); - span_s = MIN(span_s, elen-1); - span_e = MAX(p1s, p1e); - span_e = MIN(span_e, elen-1); - span_s = ((span_s+span_e)>>1); - ed = span_s; - - fprintf(stderr, "u-stg%.6lul\t%lu\tv-stg%.6lul\t%lu\n", suid+1, sd, euid + 1, ed); - } - } -} - -kv_u_trans_t *get_update_trans_idx(horder_t *h, trans_col_t *t_idx) -{ - uint64_t i, k, l; - uint32_t uid/**, q_n, t_n**/; - ma_ug_t *ug = h->ug; - asg_t *rg = h->r_g; - kv_u_trans_t *idx = NULL; CALLOC(idx, 1); - u_trans_hit_idx iter; - u_trans_hit_t hit; - kvec_t(u_hit_t) b; kv_init(b); - uint64_t *b_idx = NULL; CALLOC(b_idx, t_idx->ref->idx.n); - /**u_hit_t *q, *t;**/ - u_hit_t *p = NULL; - for (i = 0; i < ug->u.n; i++) - { - uid = i<<1; - reset_u_trans_hit_idx(&iter, &uid, 1, ug, rg, t_idx->idx, 0, ug->u.a[i].len); - while(get_u_trans_hit(&iter, &hit))///get [qScur, qEcur), [qSpre, qEpre) - { - kv_pushp(u_hit_t, b, &p); - p->Scur = hit.qScur; - p->Ecur = hit.qEcur; - p->Spre = hit.qSpre; - p->Epre = hit.qEpre; - p->uPre = hit.qn; - p->uCur = uid; - } - } - - radix_sort_u_hit(b.a, b.a + b.n); - for (k = 1, l = 0; k <= b.n; ++k) - { - if (k == b.n || (b.a[k].uPre>>1) != (b.a[l].uPre>>1)) - { - b_idx[b.a[l].uPre>>1] = (uint64_t)l << 32 | (k - l); - l = k; - } - } - - /** - for (i = 0; i < t_idx->ref->idx.n; i++) - { - q_n = (uint32_t)b_idx[i]; - q = b.a + (b_idx[i]>>32); - if(!q_n) continue; - } - **/ - - // for (i = 0; i < b.n; i++) - // { - - // } - - - free(b_idx); - kv_destroy(b); - return idx; -} - -void update_scg(horder_t *h, trans_col_t *t_idx) -{ - uint64_t i, k, l, p0s, p0e, p1s, p1e, span_s, span_e, suid, euid, v, w, slen, elen, sd, ed; - uint64_t t_hits = 0, a_hits = 0; - double max_div, we; - h_w_t e; kv_init(e); - dens_idx_t *idx = NULL; - hw_aux_t *ep = NULL; - ma_ug_t *ug = h->ug; - kvec_pe_hit *hits = &(h->u_hits); - osg_arc_t *p = NULL; - osg_destroy(h->sg.g); - h->sg.g = osg_init(); - for (i = 0; i < ug->u.n; i++) { - osg_seq_set(h->sg.g, i, 0); - h->sg.g->seq[i].mw[0] = h->sg.g->seq[i].mw[1] = 0; - h->sg.g->seq[i].ez[0] = ug->u.a[i].len>>1; - h->sg.g->seq[i].ez[1] = ug->u.a[i].len - (ug->u.a[i].len>>1); - } - idx = build_interval_idx(hits, ug);///idx is used to get density - - for (i = 0, e.n = 0; i < hits->a.n; i++) { - if(!hits->a.a[i].id) continue;//hom hits - suid = get_hit_suid(*hits, i); - euid = get_hit_euid(*hits, i); - if(suid == euid) continue;//same unitig - slen = ug->u.a[suid].len; - elen = ug->u.a[euid].len; - - p0s = get_hit_spos(*hits, i); - p0e = get_hit_spos_e(*hits, i); - span_s = MIN(p0s, p0e); - span_s = MIN(span_s, slen-1); - span_e = MAX(p0s, p0e); - span_e = MIN(span_e, slen-1); - span_s = ((span_s+span_e)>>1); - sd = span_s; - v = suid << 1; - if(span_s > (slen>>1)) v++; - - - p1s = get_hit_epos(*hits, i); - p1e = get_hit_epos_e(*hits, i); - span_s = MIN(p1s, p1e); - span_s = MIN(span_s, elen-1); - span_e = MAX(p1s, p1e); - span_e = MIN(span_e, elen-1); - span_s = ((span_s+span_e)>>1); - ed = span_s; - w = euid << 1; - if(span_s > (elen>>1)) w++; - t_hits++; - - kv_pushp(hw_aux_t, e, &ep); - ep->w = 0; - ep->e = (v<<32)|w; - ep->d = (sd<<32)|ed; - - if(v > w) { - ep->e = (w<<32)|v; - ep->d = (ed<<32)|sd; - } - - // div = h->sg.g->seq[v>>1].ez[v&1] + h->sg.g->seq[w>>1].ez[w&1]; - // max_div = MAX(max_div, div); - a_hits++; - } - - // fprintf(stderr, "sa-0-sa: occ-%lu\n", get_vw_hits_num(&e, 12, 690)); - // print_specfic_hic_hits(hits, 12, 690, ug); - - - - update_h_w(&e, idx, &max_div); - - // fprintf(stderr, "sa-1-sa: occ-%lu\n", get_vw_hits_num(&e, 676, 738)); - - radix_sort_hw_e(e.a, e.a+e.n); - for (k = 1, l = 0; k <= e.n; ++k) - { - if (k == e.n || e.a[k].e != e.a[l].e) - { - for (i = 0; i < h->avoid.n; i++) - { - v = e.a[l].e; - w = e.a[l].e<<32; w |= (e.a[l].e>>32); - if(h->avoid.a[i] == v || h->avoid.a[i] == w) - { - break; - } - } - - if(i >= h->avoid.n) - { - for (i = l, we = 0; i < k; i++) - { - if(e.a[i].w == 0) fprintf(stderr, "ERROR-3\n"); - we += (max_div/e.a[i].w); - } - - p = osg_arc_pushp(h->sg.g); - p->u = p->v = p->occ = p->del = p->w = p->nw = 0; - p->u = e.a[l].e>>32; p->v = (uint32_t)e.a[l].e; - p->occ = k - l; p->w = we; - // if(div != 0) p->w = (double)(k - l)*(max_div/div); - p = osg_arc_pushp(h->sg.g); - p->u = p->v = p->occ = p->del = p->w = p->nw = 0; - p->u = (uint32_t)e.a[l].e; p->v = e.a[l].e>>32; - p->occ = k - l; p->w = we; - - - h->sg.g->seq[e.a[l].e>>33].mw[(e.a[l].e>>32)&1] - = MAX(h->sg.g->seq[e.a[l].e>>33].mw[(e.a[l].e>>32)&1], p->w); - h->sg.g->seq[((uint32_t)e.a[l].e)>>1].mw[e.a[l].e&1] - = MAX(h->sg.g->seq[((uint32_t)e.a[l].e)>>1].mw[e.a[l].e&1], p->w); - } - - l = k; - } - } - - // fprintf(stderr, "sa-2-sa: occ-%lu\n", get_vw_hits_num(&e, 676, 738)); - osg_cleanup(h->sg.g); - double bestAlt; - uint64_t eg_edges = 0; - for (i = 0; i < h->sg.g->n_arc; i++)///all p->w should be >= 2 - { - p = &(h->sg.g->arc[i]); - bestAlt = MAX(h->sg.g->seq[p->u>>1].mw[p->u&1], h->sg.g->seq[p->v>>1].mw[p->v&1]); - if(p->w >= bestAlt*0.95)///acutally should be p->w == bestAlt - { - bestAlt = get_max_weight(p->u, p->v, h->sg.g); - } - - if(bestAlt == 0) bestAlt = 1; - ///if there is just one edges between p->u and p->v, then bestAlt -> p->nw <= 1; this is wrong - p->nw = p->w/bestAlt; - if(p->nw > 1) eg_edges++; - } - - fprintf(stderr, "[M::%s::] # Nodes: %u, # Edges: %u, # Best Edges: %lu, t_hits: %lu, a_hits: %lu\n", - __func__, h->sg.g->n_seq, h->sg.g->n_arc, eg_edges, t_hits, a_hits); - - /*******************************for debug************************************/ - /** - for (i = 0; i < h->sg.g->n_arc; i++) - { - p = &(h->sg.g->arc[i]); - fprintf(stderr, "u-stg%.6ul(%c)(div:%f)\tv-stg%.6ul(%c)(div:%f)\tocc:%u\tw:%f\tnw:%f\n", - (p->u>>1)+1, "+-"[p->u&1], h->sg.g->seq[p->u>>1].ez[p->u&1], - (p->v>>1)+1, "+-"[p->v&1], h->sg.g->seq[p->v>>1].ez[p->v&1], p->occ, p->w, p->nw); - } - fprintf(stderr, "sbsbsbsb\n\n\n\n\n\n"); - **/ - - // uint32_t u, nv, f; - // osg_arc_t *av = NULL; - // for (k = 0; k < h->sg.g->n_arc; k++) - // { - // p = &(h->sg.g->arc[k]); - // u = p->u; v = p->v; - // f = 0; - - // nv = asg_arc_n(h->sg.g, u); - // av = asg_arc_a(h->sg.g, u); - // for (i = 0; i < nv; i++) - // { - // if(av[i].v == v) continue; - // if(av[i].w > p->w) f = 1; - // } - - // nv = asg_arc_n(h->sg.g, v); - // av = asg_arc_a(h->sg.g, v); - // for (i = 0; i < nv; i++) - // { - // if(av[i].v == u) continue; - // if(av[i].w > p->w) f = 1; - // } - - // if(p->nw > 1 && f == 1) fprintf(stderr, "ERROR1\n"); - // if(p->nw <= 1 && f == 0) - // { - // fprintf(stderr, "\nERROR2, nw-%f, w-%f, u-%u, v-%u\n", p->nw, p->w, p->u, p->v); - // nv = asg_arc_n(h->sg.g, u); - // av = asg_arc_a(h->sg.g, u); - // for (i = 0; i < nv; i++) - // { - // if(av[i].v == v) continue; - // fprintf(stderr, "+u-%u, v-%u, w-%f\n", av[i].u, av[i].v, av[i].w); - // } - - // nv = asg_arc_n(h->sg.g, v); - // av = asg_arc_a(h->sg.g, v); - // for (i = 0; i < nv; i++) - // { - // if(av[i].v == u) continue; - // fprintf(stderr, "-u-%u, v-%u, w-%f\n", av[i].u, av[i].v, av[i].w); - // } - // } - - // } - /*******************************for debug************************************/ - kv_destroy(e); - free(idx->pos.a); - free(idx->a); - free(idx); -} - -int cmp_arc_nw(const void * a, const void * b) -{ - if((*(osg_arc_t*)a).nw == (*(osg_arc_t*)b).nw) return 0; - return (*(osg_arc_t*)a).nw < (*(osg_arc_t*)b).nw ? 1 : -1; -} - -#define arc_first(g, v) ((g)->arc[(g)->idx[(v)]>>32]) -void get_backbone_layout(horder_t *h, sc_lay_t *sl, osg_t *lg, uint8_t *vis) -{ - uint32_t k, v, nc = 0, c = 0; - lay_t *p = NULL; - osg_arc_t *t = NULL; - sl->n = 0; - ///in lg, there might be single-path paths or cycles - memset(vis, 0, sizeof(uint8_t)*(lg->n_seq<<1)); - for (k = 0; k < lg->n_seq; k++) - { - ///I guess this should be (!!(asg_arc_n(lg, k<<1)))^(!!(asg_arc_n(lg, (k<<1)+1)))? - ///no, since asg_arc_n is at most 1 - if((asg_arc_n(lg, k<<1))^(asg_arc_n(lg, (k<<1)+1)))///end scaffolding - { - v = (asg_arc_n(lg, k<<1)?(k<<1):((k<<1)+1)); - if(vis[k<<1] || vis[(k<<1)+1]) continue; - kv_pushp(lay_t, *sl, &p); - kv_init(*p); - kv_push(uint32_t, *p, v^1); - kv_push(uint32_t, *p, v); - vis[v] = vis[v^1] = 1; - - while (asg_arc_n(lg, v)) - { - v = (arc_first(lg, v).v)^1; - kv_push(uint32_t, *p, v^1); - kv_push(uint32_t, *p, v); - vis[v] = vis[v^1] = 1; - } - } - } - - nc = sl->n; - for (k = 0; k < lg->n_seq; k++) - { - if(vis[k<<1] || vis[(k<<1)+1]) continue; - if(asg_arc_n(lg, k<<1) && asg_arc_n(lg, (k<<1)+1))//circle - { - v = k<<1; t = NULL; - while (asg_arc_n(lg, v)) - { - if((!t) || (t->nw > arc_first(lg, v).nw) - || (t->nw == arc_first(lg, v).nw && t->w > arc_first(lg, v).w)) - { - t = &(arc_first(lg, v)); - } - v = (arc_first(lg, v).v)^1; - if(v == (k<<1)) break; - } - - v = t->v^1; - kv_pushp(lay_t, *sl, &p); - kv_init(*p); - kv_push(uint32_t, *p, v^1); - kv_push(uint32_t, *p, v); - vis[v] = vis[v^1] = 1; - - while (1) - { - v = (arc_first(lg, v).v)^1; - if(vis[v]) break; - kv_push(uint32_t, *p, v^1); - kv_push(uint32_t, *p, v); - vis[v] = vis[v^1] = 1; - } - } - } - - c = sl->n - nc; - fprintf(stderr, "[M::%s::] # Scaffolds: %u, # non-circles: %u, # circles: %u\n", - __func__, (uint32_t)sl->n, nc, c); - /*******************************for debug************************************/ - // for (k = 0; k < sl->n; k++) - // { - // p = &(sl->a[k]); - // if(k >= nc) - // { - // fprintf(stderr, "%s:\t", k < nc?"non-circle":"circle"); - // for (i = 0; i < p->n; i+=2) - // { - // if((p->a[i]>>1) != (p->a[i+1]>>1)) fprintf(stderr, "ERROR-S\n"); - // fprintf(stderr, "utg%.6ul[%u%u](%u)#", p->a[i]>>1, p->a[i]&1, p->a[i+1]&1, h->ug->u.a[p->a[i]>>1].len); - // } - // fprintf(stderr, "\n"); - // } - - // for (i = 1; i < p->n; i+=2) - // { - // if(k < nc) - // { - // if(i < p->n - 1) - // { - // if(asg_arc_n(lg, p->a[i])!=1) fprintf(stderr, "ERROR-A\n"); - // if(arc_first(lg, p->a[i]).v!=p->a[i+1]) fprintf(stderr, "ERROR-B\n"); - // } - - // if(i == p->n - 1) - // { - // if(asg_arc_n(lg, p->a[i])!=0) fprintf(stderr, "ERROR-A-0\n"); - // } - // } - - - // if(k >= nc) - // { - // if(i < p->n - 1) - // { - // if(asg_arc_n(lg, p->a[i])!=1) fprintf(stderr, "ERROR-A\n"); - // if(arc_first(lg, p->a[i]).v!=p->a[i+1]) fprintf(stderr, "ERROR-B\n"); - // fprintf(stderr, "i-%u, nw-%f\n", i, arc_first(lg, p->a[i]).nw); - // } - - // if(i == p->n - 1) - // { - // if(asg_arc_n(lg, p->a[i])!=1) fprintf(stderr, "ERROR-A\n"); - // if(arc_first(lg, p->a[i]).v!=p->a[0]) fprintf(stderr, "ERROR-B-0\n"); - // fprintf(stderr, "i-%u, nw-%f\n", i, arc_first(lg, p->a[i]).nw); - // } - // } - // } - - // } - - - // for (k = 0; k < lg->n_seq; k++) - // { - // if(!asg_arc_n(lg, k<<1) && !asg_arc_n(lg, (k<<1)+1)) - // { - // if(vis[k<<1] || vis[(k<<1)+1]) fprintf(stderr, "ERROR-bone\n"); - // } - // } - /*******************************for debug************************************/ -} - -/** -static void worker_for_insert(void *data, long i, int tid) // callback for kt_for() -{ - sc_id_t *s = &((*(sc_mul*)(data)).a[i]); - osg_t *sg = (*(sc_mul*)(data)).sg; - sc_lay_t *sl = (*(sc_mul*)(data)).sl; - lay_t *p = NULL; - uint32_t k, i, uid = s->uid; - for (k = 0; k < sl->n; k++) - { - p = &(sl->a[k]); - for (i = 0; i < p->n; i += 2) - { - } - } -} - - -void refine_layout(horder_t *h, sc_lay_t *sl, uint8_t *vis) -{ - uint32_t i; - sc_id_t *p = NULL; - sc_mul st; kv_init(st); - st.sl = sl; st.sg = h->sg.g; st.n_thread = asm_opt.thread_num; - for (i = 0; i < h->sg.g->n_seq; i++) - { - if(vis[i<<1]) continue; - kv_pushp(sc_id_t, st, &p); - p->uid = i; - p->iid = p->ori = p->sid = 0; - } - - while (st.n) - { - kt_for(st.n_thread, worker_for_insert, &st, st.n); - } - sc_id_t - - kv_destroy(st); -} -**/ -void refine_layout_back(horder_t *h, sc_lay_t *sl, uint8_t *vis) -{ - uint32_t i, k, m, v, nv, max_k; - osg_arc_t *av = NULL; - lay_t *p = NULL; - uint8_t *sgv = NULL; MALLOC(sgv, sl->n); - double *w = NULL; MALLOC(w, sl->n); - uint32_t *idx = NULL; MALLOC(idx, h->sg.g->n_seq); - memset(idx, -1, sizeof(uint32_t)*h->sg.g->n_seq); - kvec_t(uint64_t) p_refine; kv_init(p_refine); - - for (k = 0; k < sl->n; k++) - { - p = &(sl->a[k]); - for (m = 0; m < p->n; m++) - { - idx[p->a[m]>>1] = k; - } - } - - for (i = 0, p_refine.n = 0; i < h->sg.g->n_seq; i++) - { - if(vis[i<<1]) continue; - if(!asg_arc_n(h->sg.g, i<<1)&&!asg_arc_n(h->sg.g, (i<<1)+1)) continue; - for (k = 0; k < sl->n; k++) w[k] = 0, sgv[k] = 0; - - v = i<<1; - nv = asg_arc_n(h->sg.g, v); - av = asg_arc_a(h->sg.g, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - w[idx[av[k].v>>1]] += av[k].nw; - sgv[idx[av[k].v>>1]] = 1; - } - - - v = (i<<1) + 1; - nv = asg_arc_n(h->sg.g, v); - av = asg_arc_a(h->sg.g, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - w[idx[av[k].v>>1]] += av[k].nw; - sgv[idx[av[k].v>>1]] = 1; - } - - for (k = 0, max_k = (uint32_t)-1; k < sl->n; k++) - { - if(!sgv[k]) continue; - if(max_k == (uint32_t)-1 || w[max_k] < w[k]) max_k = k; - } - - if(max_k != (uint32_t)-1) - { - vis[i<<1] = vis[(i<<1) + 1] = 1; - kv_push(uint64_t, p_refine, (((uint64_t)(max_k))<<32)|((uint64_t)(i))); - } - } - free(w); free(idx); free(sgv); - - for (i = 0; i < p_refine.n; i++) - { - p = &(sl->a[p_refine.a[i]>>32]); - // uid = (uint32_t)p_refine.a[i]; - } - - kv_destroy(p_refine); -} - -uint32_t get_max_anchor(horder_t *h, sc_lay_t *sl, uint8_t *vis, double *w, uint8_t *sgv, uint32_t *idx, -uint32_t *max_utg, uint32_t *max_sc) -{ - (*max_utg) = (*max_sc) = (uint32_t)-1; - double max_utg_w = -1; - uint32_t i, k, v, nv, max_k; - osg_arc_t *av = NULL; - for (i = 0; i < h->sg.g->n_seq; i++) - { - if(vis[i<<1]) continue; - if(!asg_arc_n(h->sg.g, i<<1)&&!asg_arc_n(h->sg.g, (i<<1)+1)) continue; - for (k = 0; k < sl->n; k++) w[k] = 0, sgv[k] = 0; - - v = i<<1; - nv = asg_arc_n(h->sg.g, v); - av = asg_arc_a(h->sg.g, v); - for (k = 0; k < nv; k++) - { - if(av[k].del || idx[av[k].v>>1] == (uint32_t)-1) continue; - w[idx[av[k].v>>1]] += av[k].nw; - sgv[idx[av[k].v>>1]] = 1; - } - - - v = (i<<1) + 1; - nv = asg_arc_n(h->sg.g, v); - av = asg_arc_a(h->sg.g, v); - for (k = 0; k < nv; k++) - { - if(av[k].del || idx[av[k].v>>1] == (uint32_t)-1) continue; - w[idx[av[k].v>>1]] += av[k].nw; - sgv[idx[av[k].v>>1]] = 1; - } - - for (k = 0, max_k = (uint32_t)-1; k < sl->n; k++) - { - if(!sgv[k]) continue; - if(max_k == (uint32_t)-1 || w[max_k] < w[k]) max_k = k; - } - - if(max_k != (uint32_t)-1) - { - if((*max_utg) == (uint32_t)-1 || max_utg_w < w[max_k]) - { - max_utg_w = w[max_k]; - (*max_utg) = i; - (*max_sc) = max_k; - } - } - } - - return (*max_utg) == (uint32_t)-1?0:1; -} - -osg_arc_t *get_osg_arc(osg_t *g, uint32_t u, uint32_t v) -{ - osg_arc_t *au = asg_arc_a(g, u); - uint32_t i, nu = asg_arc_n(g, u); - for (i = 0; i < nu; i++) - { - if(au[i].del) continue; - if(au[i].v == v) return &(au[i]); - } - - return NULL; -} - -void insert_sc(osg_t *g, lay_t *p, uint32_t uid) -{ - uint32_t i, b, e, vb, ve, max_i = (uint32_t)-1, is_found, ori, max_ori = (uint32_t)-1; - osg_arc_t *bE = NULL, *eE = NULL; - double w[2], s_w, max_w = -1; - for (i = 1; i+1 < p->n; i++)///middle points - { - b = p->a[i]; e = p->a[i+1]; w[0] = w[1] = 0; - s_w = 0; ori = 0; is_found = 0; - - vb = (uid<<1); ve = (uid<<1)+1; - bE = get_osg_arc(g, vb, b); - eE = get_osg_arc(g, ve, e); - if(bE || eE) ///different with slsa2 - { - if(bE) w[0] += bE->nw; - if(eE) w[0] += eE->nw; - is_found++; - } - - - vb = (uid<<1)+1; ve = (uid<<1); - bE = get_osg_arc(g, vb, b); - eE = get_osg_arc(g, ve, e); - if(bE || eE) ///different with slsa2 - { - if(bE) w[1] += bE->nw; - if(eE) w[1] += eE->nw; - is_found++; - } - - if(is_found > 0) - { - s_w = MAX(w[0], w[1]); - ori = ((w[0] >= w[1])? 0 : 1); - - if(max_i == (uint32_t)-1 || max_w < s_w) - { - max_w = s_w; - max_i = i; - max_ori = ori; - } - } - } - - - ///beg point, ///different with slsa2 - i = 0; - b = (uint32_t)-1; e = p->a[0]; w[0] = w[1] = 0; - s_w = 0; ori = 0; is_found = 0; - - vb = (uint32_t)-1; ve = (uid<<1)+1; - bE = NULL; - eE = get_osg_arc(g, ve, e); - if(bE || eE) ///different with slsa2 - { - if(bE) w[0] += bE->nw; - if(eE) w[0] += eE->nw; - is_found++; - } - - vb = (uint32_t)-1; ve = (uid<<1); - bE = NULL; - eE = get_osg_arc(g, ve, e); - if(bE || eE) ///different with slsa2 - { - if(bE) w[1] += bE->nw; - if(eE) w[1] += eE->nw; - is_found++; - } - - if(is_found > 0) - { - s_w = MAX(w[0], w[1]); - ori = ((w[0] >= w[1])? 0 : 1); - - if(max_i == (uint32_t)-1 || max_w < s_w) - { - max_w = s_w; - max_i = i; - max_ori = ori; - } - } - - ///end point, ///different with slsa2 - i = p->n - 1; - b = p->a[p->n - 1]; e = (uint32_t)-1; w[0] = w[1] = 0; - s_w = 0; ori = 0; is_found = 0; - - vb = (uid<<1); ve = (uint32_t)-1; - bE = get_osg_arc(g, vb, b); - eE = NULL; - if(bE || eE) ///different with slsa2 - { - if(bE) w[0] += bE->nw; - if(eE) w[0] += eE->nw; - is_found++; - } - - vb = (uid<<1)+1; ve = (uint32_t)-1; - bE = get_osg_arc(g, vb, b); - eE = NULL; - if(bE || eE) ///different with slsa2 - { - if(bE) w[1] += bE->nw; - if(eE) w[1] += eE->nw; - is_found++; - } - - if(is_found > 0) - { - s_w = MAX(w[0], w[1]); - ori = ((w[0] >= w[1])? 0 : 1); - - if(max_i == (uint32_t)-1 || max_w < s_w) - { - max_w = s_w; - max_i = i; - max_ori = ori; - } - } - - if(max_i != 0 && max_i != (uint32_t)-1) max_i++; - - i = p->n; - kv_resize(uint32_t, *p, p->n+2); - p->n += 2; - while (i > max_i) - { - i--; - p->a[i+2] = p->a[i]; - } - - p->a[max_i] = (uid<<1) + max_ori; - p->a[max_i+1] = (uid<<1) + 1 - max_ori; -} - - -uint32_t get_vis_occ(uint8_t *vis, uint32_t n) -{ - uint32_t i, occ; - n <<= 1; - for (i = occ = 0; i < n; i++) - { - if(vis[i]) occ++; - } - return occ; -} - -uint32_t get_sl_occ(sc_lay_t *sl) -{ - uint32_t i, occ; - for (i = occ = 0; i < sl->n; i++) - { - occ += sl->a[i].n; - } - return occ; -} - -void refine_layout(horder_t *h, sc_lay_t *sl, uint8_t *vis) -{ - uint32_t k/**m, max_utg, max_sc**/; - lay_t *p = NULL; - uint8_t *sgv = NULL; MALLOC(sgv, sl->n); - double *w = NULL; MALLOC(w, sl->n); - - /** - uint32_t *idx = NULL; MALLOC(idx, h->sg.g->n_seq); - memset(idx, -1, sizeof(uint32_t)*h->sg.g->n_seq); - - for (k = 0; k < sl->n; k++) - { - p = &(sl->a[k]); - for (m = 0; m < p->n; m++) - { - idx[p->a[m]>>1] = k; - } - } - while (get_max_anchor(h, sl, vis, w, sgv, idx, &max_utg, &max_sc)) - { - - insert_sc(h->sg.g, &(sl->a[max_sc]), max_utg); - - vis[max_utg<<1] = vis[(max_utg<<1)+1] = 1; - idx[max_utg] = max_sc; - } - free(idx); - **/ - - for (k = 0; k < h->sg.g->n_seq; k++) - { - if(vis[k<<1]) continue; - kv_pushp(lay_t, *sl, &p); - kv_init(*p); - kv_push(uint32_t, *p, (k<<1)); - kv_push(uint32_t, *p, (k<<1)+1); - vis[(k<<1)] = vis[(k<<1)+1] = 1; - } - - free(w); free(sgv); -} - - - -void generate_scaffold(ma_utg_t *su, lay_t *ly, ma_ug_t *pug, asg_t *rg) -{ - ma_utg_t *uu = NULL; - uint32_t i, k, r_i, uid, ori, nv, is_circle = 0; - uint64_t v, w, l, totalLen; - asg_arc_t *av = NULL; - memset(su, 0, sizeof(*su)); - for (i = 0; i < ly->n; i += 2) - { - ori = ly->a[i]&1; - uid = ly->a[i]>>1; - uu = &(pug->u.a[uid]); - is_circle = uu->circ; - for (r_i = 0; r_i < uu->n; r_i++) - { - v = (ori?uu->a[uu->n - r_i - 1]:uu->a[r_i]); - if(v != (uint64_t)-1 && ori) v ^= (uint64_t)(0x100000000); - kv_push(uint64_t, *su, v); - } - if(i < ly->n - 2) kv_push(uint64_t, *su, (uint64_t)-1); - } - if(ly->n != 2) is_circle = 0;///ly-> == 2: single circle - - for (i = 0, totalLen = 0; i < su->n-1; i++) - { - if(su->a[i] == (uint64_t)-1) - { - totalLen += GAP_LEN; - continue; - } - v = su->a[i]>>32; - if(su->a[i+1] == (uint64_t)-1) - { - l = rg->seq[v>>1].len; - } - else - { - w = su->a[i+1]>>32; - av = asg_arc_a(rg, v); - nv = asg_arc_n(rg, v); - - l = 0; - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - l = asg_arc_len(av[k]); - break; - } - } - if(k == nv) fprintf(stderr, "ERROR-scf-0, v-%lu, w-%lu\n", v, w); - } - - su->a[i] = v; su->a[i] = su->a[i]<<32; su->a[i] = su->a[i] | (uint64_t)(l); - totalLen += l; - } - if(i < su->n) - { - if(su->a[i] == (uint64_t)-1) - { - totalLen += GAP_LEN; - } - else - { - if(is_circle && su->a[0] != (uint64_t)-1) - { - v = su->a[i]>>32; - w = su->a[0]>>32; - av = asg_arc_a(rg, v); - nv = asg_arc_n(rg, v); - - l = 0; - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - l = asg_arc_len(av[k]); - break; - } - } - if(k == nv) fprintf(stderr, "ERROR-scf-1, v-%lu, w-%lu\n", v, w); - - su->a[i] = v; su->a[i] = su->a[i]<<32; su->a[i] = su->a[i] | (uint64_t)(l); - totalLen += l; - } - else - { - v = su->a[i]>>32; - l = rg->seq[v>>1].len; - su->a[i] = v; - su->a[i] = su->a[i]<<32; - su->a[i] = su->a[i] | (uint64_t)(l); - totalLen += l; - } - } - } - - su->circ = is_circle; - su->len = totalLen; - if(!su->circ) - { - su->start = su->a[0]>>32; - su->end = (su->a[su->n-1]>>32)^1; - } - else - { - su->start = su->end = UINT32_MAX; - } -} - -uint64_t get_nuid(sc_lay_t *sl, uint64_t *p) -{ - uint64_t k, ouid[2]; - for (k = 0; k < sl->n; k++) - { - ouid[0] = sl->a[k].a[0]; - ouid[1] = sl->a[k].a[sl->a[k].n - 1]; - if((*p) == ouid[0]) - { - (*p) = (k<<1); - return 1; - } - - if((*p) == ouid[1]) - { - (*p) = (k<<1)+1; - return 1; - } - } - - return 0; -} - -void update_avoids(horder_t *h, sc_lay_t *sl) -{ - uint64_t i, m, ps, pe; - for (i = m = 0; i < h->avoid.n; i++) - { - ps = h->avoid.a[i]>>32; - pe = (uint32_t)h->avoid.a[i]; - if(get_nuid(sl, &ps) && get_nuid(sl, &pe)) - { - h->avoid.a[m] = (ps<<32)|pe; - m++; - } - } - h->avoid.n = m; -} - -void update_ug_by_layout(horder_t *h, sc_lay_t *sl, ma_ug_t* i_ug) -{ - uint32_t i; - lay_t *p = NULL; - ma_utg_t *pu = NULL; - ma_ug_t *sug = NULL; - kvec_t_u64_warp n_avoids; kv_init(n_avoids.a); - sug = (ma_ug_t*)calloc(1, sizeof(ma_ug_t)); - for (i = 0; i < sl->n; i++) - { - p = &(sl->a[i]); - kv_pushp(ma_utg_t, sug->u, &pu); - generate_scaffold(pu, p, i_ug?i_ug:h->ug, h->r_g); - } - ma_ug_destroy(h->ug); - h->ug = sug; - kv_destroy(n_avoids.a); - update_avoids(h, sl); -} - -void get_long_switch_scaffolds(horder_t *h, sc_lay_t *sl, osg_t *lg) -{ - fprintf(stderr, "\n[M::%s::]\n", __func__); - uint32_t i, k, r_i, ori, sw[3], sw_inner[3]; - uint64_t v, len; - kvec_t(uint64_t) idx; kv_init(idx); - lay_t *p = NULL; - ma_utg_t *u = NULL; - for (i = 0; i < sl->n; i++) - { - p = &(sl->a[i]); - sw[0] = sw[1] = sw[2] = 0; - for (k = 0; k < p->n; k += 2) - { - u = &(h->ug->u.a[p->a[k]>>1]); - ori = p->a[k]&1; - for (r_i = 0; r_i < u->n; r_i++) - { - v = (ori?u->a[u->n - r_i - 1]:u->a[r_i]); - if(v != (uint64_t)-1) - { - v >>= 33; - sw[R_INF.trio_flag[v]]++; - } - } - } - - v = MIN(sw[FATHER], sw[MOTHER]); - v = ((uint32_t)-1) - v; - v <<= 32; v |= i; - kv_push(uint64_t, idx, v); - } - - radix_sort_ho64(idx.a, idx.a+idx.n); - for (i = 0; i < sl->n; i++) - { - p = &(sl->a[(uint32_t)(idx.a[i])]); - fprintf(stderr, "\nscaf-%u-th, occ-%u\n", (uint32_t)(idx.a[i]), (uint32_t)(p->n>>1)); - sw[0] = sw[1] = sw[2] = len = 0; - for (k = 0; k < p->n; k += 2) - { - sw_inner[0] = sw_inner[1] = sw_inner[2] = 0; - u = &(h->ug->u.a[p->a[k]>>1]); - ori = p->a[k]&1; - for (r_i = 0; r_i < u->n; r_i++) - { - v = (ori?u->a[u->n - r_i - 1]:u->a[r_i]); - if(v != (uint64_t)-1) - { - v >>= 33; - if(R_INF.trio_flag[v] == FATHER || R_INF.trio_flag[v] == MOTHER) - { - sw[R_INF.trio_flag[v]]++; - sw_inner[R_INF.trio_flag[v]]++; - } - } - } - fprintf(stderr, "utg%.6ul (ori: %u), u->len-%u, sw_in[FATHER]-%u, sw_in[MOTHER]-%u\n", - (p->a[k]>>1)+1, p->a[k]&1, u->len, sw_inner[FATHER], sw_inner[MOTHER]); - len += u->len + ((k + 2)< p->n? GAP_LEN:0); - } - fprintf(stderr, "sw[FATHER]-%u, sw[MOTHER]-%u, len-%lu\n", sw[FATHER], sw[MOTHER], len); - } - kv_destroy(idx); -} - -void destory_sc_lay_t(sc_lay_t *sl) -{ - uint32_t i; - for (i = 0; i < sl->n; i++) kv_destroy(sl->a[i]); - kv_destroy(*sl); -} - -void layout_scg(horder_t *h, double nw_thres, uint32_t occ_thres, sc_lay_t *r_sl) -{ - uint32_t k; - osg_arc_t *p = NULL, *lp = NULL; - uint8_t *vis = NULL; CALLOC(vis, h->sg.g->n_seq<<1); - sc_lay_t sl; kv_init(sl); - osg_t *lg = osg_init(); - qsort(h->sg.g->arc, h->sg.g->n_arc, sizeof(osg_arc_t), cmp_arc_nw); - for (k = 0; k < h->sg.g->n_arc; k++) - { - p = &(h->sg.g->arc[k]); - if(vis[p->u] || vis[p->v]) continue; - ///different with slsa2 - if(p->nw <= nw_thres || p->occ <= occ_thres) continue; - vis[p->u] = vis[p->v] = 1; - lp = osg_arc_pushp(lg); - (*lp) = (*p); - lp = osg_arc_pushp(lg); - (*lp) = (*p); - lp->u = p->v; - lp->v = p->u; - } - for (k = 0; k < h->sg.g->n_seq; k++) - { - osg_seq_set(lg, k, 0); - } - osg_cleanup(lg); - radix_sort_osg(h->sg.g->arc, h->sg.g->arc + h->sg.g->n_arc); - - get_backbone_layout(h, &sl, lg, vis); - - // get_long_switch_scaffolds(h, &sl, lg); - - refine_layout(h, &sl, vis); - - // print_N50_layout(h->ug, &sl); - - update_ug_by_layout(h, &sl, NULL); - - print_N50(h->ug); - - if(r_sl){ - r_sl->a = sl.a; sl.a = NULL; - r_sl->m = sl.m; sl.m = 0; - r_sl->n = sl.n; sl.n = 0; - - } - destory_sc_lay_t(&sl); - osg_destroy(lg); - free(vis); -} - -void renew_scaffold(horder_t *h) -{ - double index_time = yak_realtime(); - while (1) - { - update_u_hits(&(h->u_hits), &(h->r_hits), h->ug, h->r_g); - if(!break_scaffold(h, 5, 15, (uint64_t)-1, (uint64_t)-1, 2500000, 1, NULL)) break; - print_N50(h->ug); - } - fprintf(stderr, "[M::%s::%.3f] \n", __func__, yak_realtime()-index_time); -} - -void print_scaffold(ma_ug_t *ug, asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, -ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, -long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, -float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp) -{ - char* gfa_name = (char*)malloc(strlen(output_file_name)+100); - sprintf(gfa_name, "%s.%s.p_ctg.gfa", output_file_name, "stg"); - fprintf(stderr, "Writing %s to disk... \n", gfa_name); - FILE* output_file = NULL; - output_file = fopen(gfa_name, "w"); - - - kvec_asg_arc_t_warp new_rtg_edges; - kv_init(new_rtg_edges.a); - ma_ug_seq_scaffold(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 1); - ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "stg", output_file); - fclose(output_file); - - sprintf(gfa_name, "%s.%s.p_ctg.noseq.gfa", output_file_name, "stg"); - output_file = fopen(gfa_name, "w"); - ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "stg", output_file); - fclose(output_file); - - free(gfa_name); - kv_destroy(new_rtg_edges.a); -} - -void scaffold_hap(horder_t *h, ug_opt_t *opt, trans_col_t *t_idx, uint32_t round, char *output_file_name, uint8_t flag) -{ - uint32_t i; - kv_destroy(h->u_hits.a); - kv_destroy(h->u_hits.idx); - kv_destroy(h->u_hits.occ); - memset(&(h->u_hits), 0, sizeof(h->u_hits)); - kv_destroy(h->avoid); - h->avoid.m = h->avoid.n = 0; - h->avoid.a = NULL; - osg_destroy(h->sg.g); - h->sg.g = NULL; - ma_ug_destroy(h->ug); - h->ug = NULL; - - h->ug = get_trio_unitig_graph(h->r_g, flag, opt); - asg_destroy(h->ug->g); - h->ug->g = NULL; - // kv_push(uint64_t, h->occ, h->ug->u.n); - // CALLOC(h->hf.a, h->ug->u.n); h->hf.n = h->hf.m = h->ug->u.n; - - print_N50(h->ug); - - for (i = 0; i < round; i++) - { - update_u_hits(&(h->u_hits), &(h->r_hits), h->ug, h->r_g); - update_scg(h, t_idx); - layout_scg(h, 1.001, 19, NULL); - renew_scaffold(h); - } - - char* gfa_name = (char*)malloc(strlen(output_file_name)+100); - sprintf(gfa_name, "%s.%s", output_file_name, (flag==FATHER?"hap1":"hap2")); - - print_scaffold(h->ug, h->r_g, opt->coverage_cut, gfa_name, - opt->sources, opt->reverse_sources, opt->tipsLen, opt->tip_drop_ratio, - opt->stops_threshold, opt->ruIndex, opt->chimeric_rate, opt->drop_ratio, - opt->max_hang, opt->min_ovlp); - - free(gfa_name); -} - -void scaffold_ug(horder_t *h, ma_ug_t *ug, ug_opt_t *opt, uint32_t round, char *output_file_name, uint8_t flag) -{ - uint32_t i; - kv_destroy(h->u_hits.a); - kv_destroy(h->u_hits.idx); - kv_destroy(h->u_hits.occ); - memset(&(h->u_hits), 0, sizeof(h->u_hits)); - kv_destroy(h->avoid); - h->avoid.m = h->avoid.n = 0; - h->avoid.a = NULL; - osg_destroy(h->sg.g); - h->sg.g = NULL; - - h->ug = ug; - asg_destroy(h->ug->g); - h->ug->g = NULL; - // kv_push(uint64_t, h->occ, h->ug->u.n); - // CALLOC(h->hf.a, h->ug->u.n); h->hf.n = h->hf.m = h->ug->u.n; - - print_N50(h->ug); - fprintf(stderr, "[M::%s::]***0***\n", __func__); - for (i = 0; i < round; i++) - { - fprintf(stderr, "[M::%s::]*i->%u*\n", __func__, i); - update_u_hits(&(h->u_hits), &(h->r_hits), h->ug, h->r_g); - fprintf(stderr, "[M::%s::]**i->%u**\n", __func__, i); - update_scg(h, NULL); - fprintf(stderr, "[M::%s::]***i->%u***\n", __func__, i); - layout_scg(h, 1.001, 19, NULL); - fprintf(stderr, "[M::%s::]****i->%u****\n", __func__, i); - renew_scaffold(h); - fprintf(stderr, "[M::%s::]*****i->%u*****\n", __func__, i); - } - - char* gfa_name = (char*)malloc(strlen(output_file_name)+100); - sprintf(gfa_name, "%s.%s", output_file_name, (flag==FATHER?"hap1":"hap2")); - - print_scaffold(h->ug, h->r_g, opt->coverage_cut, gfa_name, - opt->sources, opt->reverse_sources, opt->tipsLen, opt->tip_drop_ratio, - opt->stops_threshold, opt->ruIndex, opt->chimeric_rate, opt->drop_ratio, - opt->max_hang, opt->min_ovlp); - - free(gfa_name); -} - -void output_hic_rtg(ma_ug_t *ug, asg_t *rg, ug_opt_t *opt, char* output_file_name) -{ - char* gfa_name = (char*)malloc(strlen(output_file_name)+50); - sprintf(gfa_name, "%s.all.noseq.gfa", output_file_name); - FILE* output_file = fopen(gfa_name, "w"); - ma_ug_print_simple(ug, rg, opt->coverage_cut, opt->sources, opt->ruIndex, "utg", output_file); - fclose(output_file); - free(gfa_name); -} - -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, kv_u_trans_t *ref, ug_opt_t *opt, uint32_t round) -{ - uint32_t i; - trans_col_t *t_idx = NULL; - 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); - t_idx = init_trans_col(i_ug, h->r_g->n_seq, ref); - // output_hic_rtg(i_ug, h->r_g, opt, asm_opt.output_file_name); - - // reduce_hamming_error(h->r_g, opt->sources, opt->coverage_cut, opt->max_hang, opt->min_ovlp, opt->gap_fuzz); - reduce_hamming_error_adv(NULL, h->r_g, opt->sources, opt->coverage_cut, opt->max_hang, opt->min_ovlp, opt->gap_fuzz, opt->ruIndex, NULL); - /** - scaffold_hap(h, t_idx, opt, round, asm_opt.output_file_name, FATHER); - scaffold_hap(h, t_idx, opt, round, asm_opt.output_file_name, MOTHER); - **/ - - - generate_haplotypes(h, opt); - print_N50(h->ug); - - // update_u_hits(&(h->u_hits), &(h->r_hits), h->ug, h->r_g); - // break_contig(h, 10, 20); - for (i = 0; i < round; i++) - { - update_u_hits(&(h->u_hits), &(h->r_hits), h->ug, h->r_g); - update_scg(h, t_idx); - layout_scg(h, 1.001, 19, NULL); - renew_scaffold(h); - } - - - print_scaffold(h->ug, h->r_g, opt->coverage_cut, asm_opt.output_file_name, - opt->sources, opt->reverse_sources, opt->tipsLen, opt->tip_drop_ratio, - opt->stops_threshold, opt->ruIndex, opt->chimeric_rate, opt->drop_ratio, - opt->max_hang, opt->min_ovlp); - - destory_trans_col(&t_idx); - exit(1); - return h; -} - -int cmp_mc_edge_t_w(const void * a, const void * b) -{ - if((*(mc_edge_t*)a).w == (*(mc_edge_t*)b).w) return 0; - return (*(mc_edge_t*)a).w < (*(mc_edge_t*)b).w ? -1 : 1; -} - -void cal_chain_arch(scg_t *sg, const mc_match_t *ma, uint32_t v, uint32_t *va, uint32_t vn, uint64_t *idx, asg64_v *srt) -{ - uint64_t z, n, j, t, w, o, l, k; double mw; osg_arc_t *p; - srt->n = 0; - for (z = 0; z < vn; z++) { - assert((v == (idx[va[z]]>>32)) || v == ((uint32_t)idx[va[z]])); - o = (ma->idx.a[va[z]]>>32); - n = (uint32_t)ma->idx.a[va[z]]; - for (j = 0; j < n; ++j) { - t = ((uint32_t)(ma->ma.a[o+j]).x); - - w = idx[t]>>32; - if((w != (uint32_t)-1) && ((w>>1) > (v>>1))) { - kv_push(uint64_t, (*srt), ((w<<32)|(o+j))); - } - - w = (uint32_t)idx[t]; - if((w != (uint32_t)-1) && ((w>>1) > (v>>1))) { - kv_push(uint64_t, (*srt), ((w<<32)|(o+j))); - } - } - } - - radix_sort_ho64(srt->a, srt->a + srt->n); - for (l = 0, k = 1; k <= srt->n; k++) { - if(k == srt->n || (srt->a[l]>>32) != (srt->a[k]>>32)) { - w = srt->a[l]>>32; mw = 0; - for (j = l; j < k; j++) { - t = ((uint32_t)(ma->ma.a[(uint32_t)srt->a[j]]).x); - assert((w == (idx[t]>>32)) || (w == ((uint32_t)idx[t]))); - mw += fabs(ma->ma.a[(uint32_t)srt->a[j]].w); - } - - p = osg_arc_pushp(sg->g); - p->occ = p->del = 0; - p->u = v; p->v = w; p->w = p->nw = mw; - - p = osg_arc_pushp(sg->g); - p->occ = p->del = 0; - p->u = w; p->v = v; p->w = p->nw = mw; - - l = k; - } - } -} - -void prt_scg_t_arc(scg_t *sg) -{ - uint64_t k; - for (k = 0; k < sg->g->n_arc; k++) { - fprintf(stderr, "[M::%s] k::%lu, v::%u, w::%u\n", __func__, k, sg->g->arc[k].u, sg->g->arc[k].v); - } -} - -uint64_t mc_clus_cut(scg_t *sg, mc_edge_t *sa, uint64_t sn, double cut_rate, uint64_t force_cut) -{ - uint64_t i, k, kv, kw, v, w, nv, nw, cnt = 0, m = sn; double mm_ol, ol_max; - osg_arc_t *av, *aw, *ve, *we; - for (k = 0; k < sn; k++) { - if(sa[k].x == ((uint64_t)-1)) { - cnt++; continue; - } - if(sg->g->arc[sa[k].x].del) { - sa[k].x = ((uint64_t)-1); cnt++; - continue; - } - - v = sg->g->arc[sa[k].x].u; - w = sg->g->arc[sa[k].x].v; - - nv = asg_arc_n(sg->g, v); nw = asg_arc_n(sg->g, w); - if(nv<=1 && nw <= 1) { - sa[k].x = ((uint64_t)-1); cnt++; - continue; - } - av = asg_arc_a(sg->g, v); aw = asg_arc_a(sg->g, w); - - ve = &(sg->g->arc[sa[k].x]); we = NULL; - for (i = 0; i < nw; ++i) { - if (aw[i].v == v) { - we = &(aw[i]); - break; - } - } - // if(!((!we) && (!(we->del)))) { - // fprintf(stderr, "[M::%s] sn::%lu, sg->g->n_arc::%u, sg->g->n_seq::%u, cut_rate::%f, v::%lu, w::%lu, x::%lu, v_beg::%lu, nv::%lu, w_beg::%lu, nw::%lu\n", __func__, - // sn, sg->g->n_arc, sg->g->n_seq, cut_rate, v, w, sa[k].x, - // (sg->g)->idx[(v)]>>32, nv, (sg->g)->idx[(w)]>>32, nw); - // prt_scg_t_arc(sg); - // } - assert((we) && (!(we->del))); - mm_ol = sg->g->arc[sa[k].x].nw; - - for (i = kv = ol_max = 0; i < nv; ++i) { - if(av[i].del) continue; - kv++; - if(ol_max < av[i].nw) ol_max = av[i].nw; - } - if (kv < 1) { - sa[k].x = ((uint64_t)-1); cnt++; - continue; - } - if (kv >= 2) { - if ((!force_cut) && (mm_ol > (ol_max*cut_rate))) continue; - } - - - for (i = kw = ol_max = 0; i < nw; ++i) { - if(aw[i].del) continue; - kw++; - if(ol_max < aw[i].nw) ol_max = aw[i].nw; - } - if (kw < 1) { - sa[k].x = ((uint64_t)-1); cnt++; - continue; - } - if (kw >= 2) { - if ((!force_cut) && (mm_ol > (ol_max*cut_rate))) continue; - } - - if (kv <= 1 && kw <= 1) { - sa[k].x = ((uint64_t)-1); cnt++; - continue; - } - - ve->del = we->del = 1; - sa[k].x = ((uint64_t)-1); cnt++; - } - - m = sn; - if(cnt) { - for (k = m = 0; k < sn; k++) { - if(sa[k].x == ((uint64_t)-1)) continue; - sa[m++] = sa[k]; - } - } - return m; -} - -void gen_mc_clus_backbone_layout(scg_t *sg, asg64_v *res, uint32_t *out, uint32_t out_n, uint32_t *buf) -{ - uint64_t k, l, i, rn, n0, n1, v, z; int64_t m, s, e; osg_arc_t *t = NULL; - kv_resize(uint64_t, *res, sg->g->n_seq); res->n = sg->g->n_seq; - memset(res->a, 0, sizeof((*(res->a)))*res->n); rn = res->n; - // fprintf(stderr, "[M::%s::]******Start******\n",__func__); - - for (k = 0; k < sg->g->n_seq; k++) { - ///I guess this should be (!!(asg_arc_n(lg, k<<1)))^(!!(asg_arc_n(lg, (k<<1)+1)))? - ///no, since asg_arc_n is at most 1 - n0 = asg_arc_n(sg->g, (k<<1)); - n1 = asg_arc_n(sg->g, ((k<<1)+1)); - assert((n0 <= 1) && (n1 <= 1)); - ///1&&0; 0&&0; 1&&1; - if((n0^n1) || ((!n0) && (!n1))) { - v = (n0?(k<<1):((k<<1)+1)); - // if(vis[k<<1] || vis[(k<<1)+1]) continue; - // if((res->a[k]>>32) || ((uint32_t)res->a[k])) continue; - if(res->a[k]) continue; - - // kv_pushp(lay_t, *sl, &p); - // kv_init(*p); - // kv_push(uint32_t, *p, v^1); - // kv_push(uint32_t, *p, v); - // vis[v] = vis[v^1] = 1; - // kv_push(uint64_t, *res, (((uint64_t)((v^1)<<32))|((uint64_t)(v))|((uint64_t)(0x8000000000000000)))); - kv_push(uint64_t, *res, (((uint64_t)((v^1)<<32))|((uint64_t)(v)))); - // res->a[v>>1] |= ((uint64_t)(1))<<32; - // res->a[v>>1] |= ((uint64_t)(1)); - res->a[v>>1] = 1; - - while (asg_arc_n(sg->g, v)) { - v = (arc_first(sg->g, v).v)^1; - // kv_push(uint32_t, *p, v^1); - // kv_push(uint32_t, *p, v); - // vis[v] = vis[v^1] = 1; - kv_push(uint64_t, *res, ((uint64_t)((v^1)<<32))|((uint64_t)(v))); - // res->a[v>>1] |= ((uint64_t)(1))<<32; - // res->a[v>>1] |= ((uint64_t)(1)); - res->a[v>>1] = 1; - } - } - } - - - for (k = 0; k < sg->g->n_seq; k++) { - // if(vis[k<<1] || vis[(k<<1)+1]) continue; - // if((res->a[k]>>32) || ((uint32_t)res->a[k])) continue; - if(res->a[k]) continue; - n0 = asg_arc_n(sg->g, (k<<1)); - n1 = asg_arc_n(sg->g, ((k<<1)+1)); - assert((n0 == 1) && (n1 == 1));///must within a circle - - - v = k<<1; t = NULL; - while (asg_arc_n(sg->g, v)) { - if((!t) || (t->nw > arc_first(sg->g, v).nw)) { - t = &(arc_first(sg->g, v)); - } - v = (arc_first(sg->g, v).v)^1; - if(v == (k<<1)) break; - } - - v = t->v^1; - // kv_pushp(lay_t, *sl, &p); - // kv_init(*p); - // kv_push(uint32_t, *p, v^1); - // kv_push(uint32_t, *p, v); - // vis[v] = vis[v^1] = 1; - // kv_push(uint64_t, *res, (((uint64_t)((v^1)<<32))|((uint64_t)(v))|((uint64_t)(0x8000000000000000)))); - kv_push(uint64_t, *res, ((uint64_t)((v^1)<<32))|((uint64_t)(v))); - // res->a[v>>1] |= ((uint64_t)(1))<<32; - // res->a[v>>1] |= ((uint64_t)(1)); - res->a[v>>1] = 1; - - while (1) { - v = (arc_first(sg->g, v).v)^1; - // if(vis[v]) break; - if(res->a[v>>1]) break; - // kv_push(uint32_t, *p, v^1); - // kv_push(uint32_t, *p, v); - // vis[v] = vis[v^1] = 1; - kv_push(uint64_t, *res, ((uint64_t)((v^1)<<32))|((uint64_t)(v))); - // res->a[v>>1] |= ((uint64_t)(1))<<32; - // res->a[v>>1] |= ((uint64_t)(1)); - res->a[v>>1] = 1; - } - } - - // uint32_t db_on = 0, db_z = 0; - assert((res->n-rn) == sg->g->n_seq); - for (l = 0, k = 1, i = 0; k <= out_n; k++) { - if(k == out_n || out[k] == (uint32_t)-1) { - if(k > l) { - res->a[i++] = ((l<<32)|(k)); ///db_on += k - l; - } else { - assert(k == out_n); - } - l = k + 1; - } - } - assert(i == sg->g->n_seq && i == rn); - for (k = rn, z = 0; k < res->n; k++) { - v = (res->a[k]>>32); - s = res->a[v>>1]>>32; e = (uint32_t)res->a[v>>1]; - if(!(v&1)) { - for (m = s; m < e; m++) buf[z++] = out[m]; - } else { - for (m = e-1; m >= s; m--) buf[z++] = out[m]; - } - - // if(e > s) { - // fprintf(stderr, "[M::%s::]\t#chain::%ld\tutg%.6ul->utg%.6ul\n", - // __func__, (e-s), buf[z-(e-s)]+1, buf[z-1]+1); - // } - - buf[z++] = (uint32_t)-1; - // db_z += e - s; - } - // if(!(z == out_n)) { - // fprintf(stderr, "[M::%s] sg->g->n_arc::%u, sg->g->n_seq::%u, z::%lu, out_n::%u, db_z::%u, db_on::%u\n", __func__, - // sg->g->n_arc, sg->g->n_seq, z, out_n, db_z, db_on); - // } - assert(z == out_n); - memcpy(out, buf, sizeof((*out))*out_n); -} - -void layout_mc_clus_t(const mc_match_t *ma, uint32_t *a, uint32_t an, scg_t *sg, uint32_t *buf, uint64_t *idx, ma_ug_t* ug, -double min_cut, double max_cut, uint64_t cut_round) -{ - uint64_t i, k, l, len, z, cutoff, s, e, v, vn; mc_edge_t *sp; - asg64_v srt; kv_init(srt); kvec_t(mc_edge_t) sm; kv_init(sm); - osg_destroy(sg->g); sg->g = osg_init(); - memset(idx, -1, sizeof((*idx))*ug->g->n_seq); - - // for (k = 0; k < an; k++) { - // fprintf(stderr, "[M::%s] k::%lu, a[k]::%u, an::%u\n", __func__, k, a[k], an); - // } - for (l = 0, k = 1, i = 0; k <= an; k++) { - if(k == an || a[k] == (uint32_t)-1) { - // fprintf(stderr, "[M::%s] l::%lu, k::%lu\n", __func__, l, k); - if(k > l) { - osg_seq_set(sg->g, i, 0); - for (z = l, len = 0; z < k; z++) len += ug->g->seq[a[z]].len; - cutoff = len >> 1; - for (z = l, len = 0; z < k; z++) { - s = len; len += ug->g->seq[a[z]].len; e = len; - if(s <= cutoff) { - idx[a[z]] <<= 32; idx[a[z]] |= (i<<1); - } - if(e >= cutoff) { - idx[a[z]] <<= 32; idx[a[z]] |= ((i<<1)+1); - } - } - i++; - } else { - assert(k == an); - } - l = k+1; - } - } - - for (l = 0, k = 1, i = 0; k <= an; k++) { - if(k == an || a[k] == (uint32_t)-1) { - if(k > l) { - for (z = l, v = (i<<1), vn = 0; z < k; z++) { - if((v == (idx[a[z]]>>32)) || v == ((uint32_t)idx[a[z]])) buf[vn++] = a[z]; - } - cal_chain_arch(sg, ma, v, buf, vn, idx, &srt); - - for (z = l, v = (i<<1)+1, vn = 0; z < k; z++) { - if((v == (idx[a[z]]>>32)) || v == ((uint32_t)idx[a[z]])) buf[vn++] = a[z]; - } - cal_chain_arch(sg, ma, v, buf, vn, idx, &srt); - - i++; - } else { - assert(k == an); - } - l = k + 1; - } - } - osg_cleanup(sg->g); - - sm.n = 0; - // kv_resize(mc_edge_t, sm, sg->g->n_arc); - for (k = 0; k < sg->g->n_arc; k++) { - if((asg_arc_n(sg->g, sg->g->arc[k].u)<=1) && (asg_arc_n(sg->g, sg->g->arc[k].v)<=1)) continue; - kv_pushp(mc_edge_t, sm, &sp); - sp->w = sg->g->arc[k].nw; sp->x = k; - } - // fprintf(stderr, "sm.n::%lu\n", (uint64_t)sm.n); - qsort(sm.a, sm.n, sizeof(mc_edge_t), cmp_mc_edge_t_w); - - - - double step = (cut_round==1?max_cut:((max_cut-min_cut)/(cut_round-1))); - double drop = min_cut; - - for (i = 0; i < cut_round; i++, drop += step) { - if(drop > max_cut) drop = max_cut; - sm.n = mc_clus_cut(sg, sm.a, sm.n, drop, 0); - } - mc_clus_cut(sg, sm.a, sm.n, 1.1, 1); - osg_cleanup(sg->g); - - gen_mc_clus_backbone_layout(sg, &srt, a, an, buf); - - - kv_destroy(srt); kv_destroy(sm); -} - -void cpy_u_hits(kvec_pe_hit *u_hits, kvec_pe_hit *i_hits, uint32_t u_n) -{ - uint64_t i; - memset(u_hits, 0, sizeof(kvec_pe_hit)); - u_hits->pos_mode = i_hits->pos_mode; - u_hits->uID_bits = i_hits->uID_bits; - u_hits->a.n = u_hits->a.m = i_hits->a.n; - MALLOC(u_hits->a.a, u_hits->a.n); - memcpy(u_hits->a.a, i_hits->a.a, u_hits->a.n*sizeof(pe_hit)); - for (i = 0; i < u_hits->a.n; i++) u_hits->a.a[i].id = 1; - idx_hits(u_hits, u_n); -} - -void update_sc_lay(sc_lay_t *sl, h_covs *b) -{ - uint64_t k, l, i, pidx, cidx; - lay_t *s = NULL; - lay_t *p = NULL; - for (k = 1, l = 0; k <= b->n; ++k) - { - if (k == b->n || (b->a[k].s != b->a[l].s)) - { - s = &(sl->a[b->a[l].s]); - for (i = l, pidx = 0; i < k; i++){ - cidx = b->a[i].dp; - kv_pushp(lay_t, *sl, &p); - kv_init(*p); - p->n = p->m = (cidx - pidx + 1)<<1; - MALLOC(p->a, p->n); - memcpy(p->a, s->a + (pidx<<1), sizeof(*(p->a))*p->n); - pidx = cidx + 1; - } - - if(pidx >= (s->n>>1)) fprintf(stderr, "ERROR-update\n"); - cidx = (s->n>>1)-1; - kv_pushp(lay_t, *sl, &p); - kv_init(*p); - p->n = p->m = (cidx - pidx + 1)<<1; - MALLOC(p->a, p->n); - memcpy(p->a, s->a + (pidx<<1), sizeof(*(p->a))*p->n); - free(s->a); s->n = s->m = 0; - l = k; - } - } - - for (i = k = 0; i < sl->n; i++){ - if(!sl->a[i].a) continue; - sl->a[k] = sl->a[i]; - sl->a[i].a = NULL; sl->a[i].n = sl->a[i].m = 0; - if(sl->a[k].n == 2){ - sl->a[k].a[0] >>= 1; sl->a[k].a[0] <<= 1; - sl->a[k].a[1] >>= 1; sl->a[k].a[1] <<= 1; sl->a[k].a[1]++; - } - k++; - } - sl->n = k; -} - -void renew_scaffold_utg(horder_t *h, sc_lay_t *sl, ma_ug_t* i_ug) -{ - double index_time = yak_realtime(); - h_covs b; kv_init(b); - while (1) - { - update_u_hits(&(h->u_hits), &(h->r_hits), h->ug, h->r_g); - if(!break_scaffold(h, 5, 15, 15, 25, 2500000, 1, &b)) break; - update_sc_lay(sl, &b); - update_ug_by_layout(h, sl, i_ug); - print_N50(h->ug); - } - fprintf(stderr, "[M::%s::%.3f] \n", __func__, yak_realtime()-index_time); - kv_destroy(b); -} - -spg_t *scf_g(sc_lay_t *sl, ma_ug_t* ug) -{ - spg_t *scg = NULL; CALLOC(scg, 1); scg->ug = ug; - uint64_t i, k; - lay_t *p = NULL; - for (i = 0; i < sl->n; i++){ - p = &(sl->a[i]); - kv_push(uint64_t, scg->idx, (uint64_t)scg->dst.n << 32 | (p->n>>1)); - for (k = 0; k < p->n; k+=2) kv_push(uint32_t, scg->dst, p->a[k]); - } - return scg; -} - -spg_t *horder_utg(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); - sc_lay_t sl; kv_init(sl); - 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);///udate rg by ug - h->ug = copy_untig_graph(i_ug); asg_destroy(h->ug->g); h->ug->g = NULL; - cpy_u_hits(&(h->u_hits), i_hits, h->ug->u.n); - - update_scg(h, NULL); - layout_scg(h, ((double)1)/((double)0.75), 19, &sl); - renew_scaffold_utg(h, &sl, i_ug); - - spg_t *scg = scf_g(&sl, i_ug); - destory_sc_lay_t(&sl); - destory_horder_t(&h); - return scg; -} - -void gen_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, m, 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 = m = 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 - if((!bub) || ((!IF_HOM(get_hit_suid(*r_hits, l), *bub)))) { - 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) { - 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); - r_hits->a.a[r_i].id = 1; r_hits->a.a[m++] = r_hits->a.a[r_i]; - - update++; - } - } - offset += (uint32_t)u->a[i]; - } - assert((r_i == k) && (update == (k-l))); - } - // if(r_i != k || update != k - l) fprintf(stderr, "ERROR-r_i\n"); - l = k; - } - } - r_hits->a.n = m; - - radix_sort_pe_hit_idx_hn2(r_hits->a.a, r_hits->a.a + r_hits->a.n); - for (k = 1, l = m = 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 - if((!bub) || ((!IF_HOM(get_hit_euid(*r_hits, l), *bub)))) { - 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) { - 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); - r_hits->a.a[r_i].id = 1; r_hits->a.a[m++] = r_hits->a.a[r_i]; - - update++; - } - } - offset += (uint32_t)u->a[i]; - } - assert((r_i == k) && (update == (k - l))); - } - // if(r_i != k || update != k - l) fprintf(stderr, "ERROR-r_i\n"); - l = k; - } - } - r_hits->a.n = m; - - r_hits->uID_bits = ubits; - r_hits->pos_mode = p_mode; - idx_hits(r_hits, r_g->n_seq); -} - -spg_t *horder_sensitive_utg(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); - sc_lay_t sl; kv_init(sl); - gen_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);///udate rg by ug - h->ug = copy_untig_graph(i_ug); asg_destroy(h->ug->g); h->ug->g = NULL; - cpy_u_hits(&(h->u_hits), i_hits, h->ug->u.n); - - update_scg(h, NULL); - layout_scg(h, ((double)1)/((double)0.75), 19, &sl); - renew_scaffold_utg(h, &sl, i_ug); - - spg_t *scg = scf_g(&sl, i_ug); - destory_sc_lay_t(&sl); - destory_horder_t(&h); - return scg; -} - - -void ha_aware_order(kvec_pe_hit *r_hits, asg_t *rg, ma_ug_t *ug_fa, ma_ug_t *ug_mo, kv_u_trans_t *ref, -ug_opt_t *opt, uint32_t round) -{ - horder_t *h = NULL; CALLOC(h, 1); - h->r_hits = *r_hits; - h->r_g = rg; - scaffold_ug(h, ug_fa, opt, round, asm_opt.output_file_name, FATHER); - scaffold_ug(h, ug_mo, opt, round, asm_opt.output_file_name, MOTHER); -} - -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)->avoid); - - osg_destroy((*h)->sg.g); - - ma_ug_destroy((*h)->ug); - asg_destroy((*h)->r_g); - free((*h)); -} - -kvec_pe_hit *get_r_hits_order(kvec_pe_hit *uhits, uint64_t hits_uid_bits, uint64_t hits_pos_mode, -asg_t *rg, ma_ug_t* ug, bubble_type* bub) -{ - kvec_pe_hit *r_hits = NULL; CALLOC(r_hits, 1); - get_r_hits(uhits, r_hits, rg, ug, bub, hits_uid_bits, hits_pos_mode); - return r_hits; +#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" +#include "tovlp.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 osg_arc_key(a) ((a).u) +KRADIX_SORT_INIT(osg, osg_arc_t, osg_arc_key, member_size(osg_arc_t, u)) + +#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 5000000 +#define BREAK_CUTOFF 0.1 +#define BREAK_BOUNDARY 0.015 +void reduce_hamming_error_adv(ma_ug_t *iug, asg_t *sg, ma_hit_t_alloc* sources, ma_sub_t *coverage_cut, +int max_hang, int min_ovlp, long long gap_fuzz, R_to_U *ru, bubble_type* bub, uint32_t max_ext); + +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 e, d; + double w; +} hw_aux_t; + +typedef struct { + hw_aux_t *a; + size_t n, m; +} h_w_t; + +#define hw_e_key(x) ((x).e) +KRADIX_SORT_INIT(hw_e, hw_aux_t, hw_e_key, member_size(hw_aux_t, e)) + +#define hw_d_key(x) ((x).d) +KRADIX_SORT_INIT(hw_d, hw_aux_t, hw_d_key, member_size(hw_aux_t, d)) + +#define hw_ew_key(x) ((uint32_t)((x).e)) +KRADIX_SORT_INIT(hw_ew, hw_aux_t, hw_ew_key, member_size(hw_aux_t, e)) + +#define hw_dw_key(x) ((uint32_t)((x).d)) +KRADIX_SORT_INIT(hw_dw, hw_aux_t, hw_dw_key, member_size(hw_aux_t, d)) + +typedef struct { + kvec_t(uint64_t) pos; + uint64_t *a; + size_t n, m; +} dens_idx_t; + +typedef struct { + uint64_t s, e, dp; +} h_cov_t; + +typedef struct { + h_cov_t *a; + size_t n, m; +} h_covs; + +typedef struct { + uint32_t *a; + size_t n, m; +}lay_t; + +typedef struct { + lay_t *a; + size_t n, m; +}sc_lay_t; + +typedef struct { + uint64_t uid, sid; + uint64_t iid:63, ori:1; +} sc_id_t; + +typedef struct { + sc_id_t *a; + size_t n, m; + sc_lay_t *sl; + osg_t *sg; + uint32_t n_thread; +} sc_mul; + +#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 h_cov_e_key(x) ((x).e) +KRADIX_SORT_INIT(h_cov_e, h_cov_t, h_cov_e_key, member_size(h_cov_t, e)) +#define h_cov_dp_key(x) ((x).dp) +KRADIX_SORT_INIT(h_cov_dp, h_cov_t, h_cov_dp_key, member_size(h_cov_t, dp)) +#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)) + +typedef struct { + kv_u_trans_t *ref; + trans_chain* idx; +} trans_col_t; + +typedef struct { + uint32_t Spre, Epre, Scur, Ecur, uCur, uPre;///[qSp, qEp) && [qSn, qEn] +} u_hit_t; + +#define u_hit_t_key(x) ((x).uPre) +KRADIX_SORT_INIT(u_hit, u_hit_t, u_hit_t_key, member_size(u_hit_t, uPre)) + +typedef struct { + ma_ug_t *ug; + kvec_pe_hit hits; + kv_u_trans_t k_trans; + h_covs *b_points; +} debug_phasing_t; + +debug_phasing_t *init_debug_phasing(ma_ug_t *ug, kvec_pe_hit *hits, kv_u_trans_t *k_trans, h_covs *b_points) +{ + debug_phasing_t *p = NULL; CALLOC(p, 1); + p->ug = copy_untig_graph(ug); + p->b_points = b_points; + + p->hits.pos_mode = hits->pos_mode; p->hits.uID_bits = hits->pos_mode; + p->hits.a.n = p->hits.a.m = hits->a.n = hits->a.m; + MALLOC(p->hits.a.a, p->hits.a.n); + memcpy(p->hits.a.a, hits->a.a, p->hits.a.n*sizeof(pe_hit)); + + p->k_trans.n = p->k_trans.m = k_trans->n; + MALLOC(p->k_trans.a, p->k_trans.n); + memcpy(p->k_trans.a, k_trans->a, p->k_trans.n*sizeof(u_trans_t)); + + p->k_trans.idx.n = p->k_trans.idx.m = k_trans->idx.n; + MALLOC(p->k_trans.idx.a, p->k_trans.idx.n); + memcpy(p->k_trans.idx.a, k_trans->idx.a, p->k_trans.idx.n*sizeof(uint64_t)); + + return p; +} + +void destory_debug_phasing_t(debug_phasing_t **x) +{ + ma_ug_destroy((*x)->ug); + free((*x)->hits.a.a); free((*x)->hits.idx.a); free((*x)->hits.occ.a); + free((*x)->k_trans.a); free((*x)->k_trans.idx.a); + free(*x); +} + +uint64_t new_node(uint64_t v, h_covs *join, uint64_t *idx, uint64_t is_ul) +{ + if(v&1) return (((uint32_t)join->a[(idx[v>>1]>>32)+(is_ul?0:(((uint32_t)idx[v>>1])-1))].dp)<<1)+1; + else return (((uint32_t)join->a[(idx[v>>1]>>32)+(is_ul?(((uint32_t)idx[v>>1])-1):0)].dp)<<1); +} + +uint32_t iter_rid(buf_t *b, uint64_t *ui, uint64_t *ri, ma_ug_t *ug) +{ + ma_utg_t *u = NULL; + while ((*ui) < b->b.n) + { + u = &(ug->u.a[b->b.a[(*ui)]>>1]); + while ((*ri) < u->n) return u->a[(*ri)++]>>32; + (*ui)++; (*ri) = 0; + } + + return (uint32_t)-1; +} + +void debug_debug_phasing_t(debug_phasing_t *x, ma_ug_t *cug, kvec_pe_hit *chits, kv_u_trans_t *ck_trans, +h_covs *join, uint64_t *idx) +{ + uint64_t i, k, m, pv, cv, pui, pri, cui, cri, e; + uint32_t p_cvx, c_cvx, pr, cr, occ; + long long p_nodeLen, p_baseLen, t1, t2; + long long c_nodeLen, c_baseLen; + asg_arc_t *ap, *ac; + u_trans_t *pk, *ck, *p; + buf_t pb, cb; + memset(&pb, 0, sizeof(buf_t)); + memset(&cb, 0, sizeof(buf_t)); + + uint32_t *cnt = NULL; CALLOC(cnt, cug->g->n_seq<<1); + for (cv = 0; cv < (uint64_t)(cug->g->n_seq<<1); ++cv) { + ///out-nodes of v + ac = asg_arc_a(cug->g, cv); + ///if v just have one out-node, there is no muti-edge + if (asg_arc_n(cug->g, cv) < 2) continue; + for (i = 0; i < asg_arc_n(cug->g, cv); ++i) ++cnt[ac[i].v]; + for (i = 0; i < asg_arc_n(cug->g, cv); ++i) + if (--cnt[ac[i].v] != 0) fprintf(stderr, "ERROR-9\n"); + } + free(cnt); + + for (e = 0; e < cug->g->n_arc; ++e) { + uint32_t v = cug->g->arc[e].v^1, u = cug->g->arc[e].ul>>32^1; + asg_arc_t *av = asg_arc_a(cug->g, v); + for (i = 0; i < asg_arc_n(cug->g, v); ++i) + if (av[i].v == u) break; + if (i == asg_arc_n(cug->g, v)) fprintf(stderr, "ERROR-10\n"); + } + + + for (i = 0; i < x->ug->g->n_seq; i++) + { + pv = (i<<1); + cv = new_node(pv, join, idx, 1); + if(asg_arc_n(x->ug->g, pv) != asg_arc_n(cug->g, cv)) fprintf(stderr, "ERROR-1\n"); + ap = asg_arc_a(x->ug->g, pv); ac = asg_arc_a(cug->g, cv); + for (k = 0; k < asg_arc_n(x->ug->g, pv); k++) + { + for (m = 0; m < asg_arc_n(cug->g, cv); m++) + { + if(new_node(ap[k].v, join, idx, 0) == ac[m].v) break; + } + if(m >= asg_arc_n(cug->g, cv)) + { + fprintf(stderr, "\n+ERROR-2\n"); + fprintf(stderr, "+putg%.6lul (%lu), cutg%.6lul (%lu)\n", (pv>>1) + 1, pv&1, (cv>>1) + 1, cv&1); + fprintf(stderr, "+p-occ: %u, c-occ: %u\n", asg_arc_n(x->ug->g, pv), asg_arc_n(cug->g, cv)); + fprintf(stderr, "+ap[k]-utg%.6ul (%u), new-utg%.6lul (%lu)\n", (ap[k].v>>1)+1, ap[k].v&1, + (new_node(ap[k].v, join, idx, 0)>>1)+1, new_node(ap[k].v, join, idx, 0)&1); + for (m = 0; m < asg_arc_n(cug->g, cv); m++) + { + fprintf(stderr, "+ac[%lu]-utg%.6ul (%u)\n", m, (ac[m].v>>1) + 1, ac[m].v&1); + } + } + } + + + + pv = (i<<1) + 1; + cv = new_node(pv, join, idx, 1); + if(asg_arc_n(x->ug->g, pv) != asg_arc_n(cug->g, cv)) fprintf(stderr, "ERROR-1\n"); + ap = asg_arc_a(x->ug->g, pv); ac = asg_arc_a(cug->g, cv); + for (k = 0; k < asg_arc_n(x->ug->g, pv); k++) + { + for (m = 0; m < asg_arc_n(cug->g, cv); m++) + { + if(new_node(ap[k].v, join, idx, 0) == ac[m].v) break; + } + if(m >= asg_arc_n(cug->g, cv)) + { + fprintf(stderr, "\n-ERROR-2\n"); + fprintf(stderr, "-putg%.6lul (%lu), cutg%.6lul (%lu)\n", (pv>>1) + 1, pv&1, (cv>>1) + 1, cv&1); + fprintf(stderr, "-p-occ: %u, c-occ: %u\n", asg_arc_n(x->ug->g, pv), asg_arc_n(cug->g, cv)); + fprintf(stderr, "-ap[k]-utg%.6ul (%u), new-utg%.6lul (%lu)\n", (ap[k].v>>1)+1, ap[k].v&1, + (new_node(ap[k].v, join, idx, 0)>>1)+1, new_node(ap[k].v, join, idx, 0)&1); + for (m = 0; m < asg_arc_n(cug->g, cv); m++) + { + fprintf(stderr, "-ac[%lu]-utg%.6ul (%u)\n", m, (ac[m].v>>1) + 1, ac[m].v&1); + } + } + } + + pb.b.n = cb.b.n = 0; + if(get_unitig(x->ug->g, NULL, i<<1, &p_cvx, &p_nodeLen, &p_baseLen, &t1, &t2, 1, &pb) != + get_unitig(cug->g, NULL, new_node((i<<1)+1, join, idx, 1)^1, &c_cvx, &c_nodeLen, &c_baseLen, &t1, &t2, 1, &cb)) + { + fprintf(stderr, "ERROR-3\n"); + } + if(new_node(p_cvx, join, idx, 1) != c_cvx) fprintf(stderr, "ERROR-4\n"); + if(p_baseLen != c_baseLen) + { + fprintf(stderr, "ERROR-6\n"); + fprintf(stderr, "-putg%.6lul, pb.b.n: %u, p_nodeLen: %lld, p_baseLen: %lld, cb.b.n: %u, c_nodeLen: %lld, c_baseLen: %lld\n", + i+1, (uint32_t)pb.b.n, p_nodeLen, p_baseLen, (uint32_t)cb.b.n, c_nodeLen, c_baseLen); + } + + + + pui = pri = cui = cri = 0; + while(1) + { + pr = iter_rid(&pb, &pui, &pri, x->ug); + cr = iter_rid(&cb, &cui, &cri, cug); + if(pr != cr) fprintf(stderr, "ERROR-7\n"); + if(pr == (uint32_t)-1 || cr == (uint32_t)-1) break; + } + } + + for (i = 0; i < x->k_trans.n; i++) + { + pk = &(x->k_trans.a[i]); + if(((uint32_t)idx[pk->qn]) <= 1 && ((uint32_t)idx[pk->tn]) <= 1) + { + get_u_trans_spec(ck_trans, ((uint32_t)join->a[idx[pk->qn]>>32].dp), + ((uint32_t)join->a[idx[pk->tn]>>32].dp), &ck, &occ); + if(occ != 1 || !ck) fprintf(stderr, "ERROR-8\n"); + + if(pk->qs != ck->qs || pk->qe != ck->qe || pk->ts != ck->ts || pk->te != ck->te || + pk->f != ck->f || pk->rev != ck->rev || pk->del != ck->del) + { + fprintf(stderr, "ERROR-9\n"); + } + } + else + { + p = pk; + fprintf(stderr, "\n+q-utg%.6ul\tqs(%u)\tqe(%u)\tt-utg%.6ul\tts(%u)\tte(%u)\trev(%u)\tw(%f)\tf(%u)\n", + p->qn+1, p->qs, p->qe, p->tn+1, p->ts, p->te, p->rev, p->nw, p->f); + + uint64_t qi, ti, qid = p->qn, tid = p->tn; + for (qi = 0; qi < (uint32_t)idx[qid]; qi++) + { + for (ti = 0; ti < (uint32_t)idx[tid]; ti++) + { + get_u_trans_spec(ck_trans, (uint32_t)(join->a[(idx[qid]>>32)+qi].dp), + (uint32_t)(join->a[(idx[tid]>>32)+ti].dp), &ck, &occ); + // fprintf(stderr, "s-utg%.6ul\td-utg%.6ul\tocc:%u\n", + // (uint32_t)(join->a[(idx[qid]>>32)+qi].dp)+1, + // (uint32_t)(join->a[(idx[tid]>>32)+ti].dp)+1, + // occ); + for (k = 0; k < occ; k++) + { + p = &(ck[k]); + fprintf(stderr, "-q-utg%.6ul\tqs(%u)\tqe(%u)\tt-utg%.6ul\tts(%u)\tte(%u)\trev(%u)\tw(%f)\tf(%u)\n", + p->qn+1, p->qs, p->qe, p->tn+1, p->ts, p->te, p->rev, p->nw, p->f); + } + } + + } + + + // get_u_trans_spec(ck_trans, ((uint32_t)join->a[idx[pk->qn]>>32].dp), + // ((uint32_t)join->a[idx[pk->tn]>>32].dp), &ck, &occ); + // for (k = 0; k < occ; k++) + // { + // p = &(ck[k]); + // fprintf(stderr, "-q-utg%.6ul\tqs(%u)\tqe(%u)\tt-utg%.6ul\tts(%u)\tte(%u)\trev(%u)\tw(%f)\tf(%u)\n", + // p->qn+1, p->qs, p->qe, p->tn+1, p->ts, p->te, p->rev, p->nw, p->f); + // } + } + } + + free(pb.b.a); free(cb.b.a); +} + +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->u.n; ++i) + { + kv_push(uint64_t, b, ug->u.a[i].len); + s += ug->u.a[i].len; + } + len = s; + + radix_sort_ho64(b.a, b.a+b.n); + fprintf(stderr, "[M::%s::] Genome Size: %lu, # Contigs: %u, Largest Contig: %lu\n", + __func__, len, (uint32_t)ug->u.n, b.a[b.n-1]); + 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 print_N50_layout(ma_ug_t* ug, sc_lay_t* sl) +{ + kvec_t(uint64_t) b; kv_init(b); + lay_t *p = NULL; + uint64_t i, k, s, ulen, len, occ = 0; + for (i = s = 0; i < sl->n; ++i) + { + p = &(sl->a[i]); + for (k = ulen = 0; k < p->n; k+=2) + { + ulen += ug->u.a[p->a[k]>>1].len; + } + occ += p->n; + + kv_push(uint64_t, b, ulen); + s += ulen; + } + len = s; + + radix_sort_ho64(b.a, b.a+b.n); + fprintf(stderr, "[M::%s::] Scaffold Size: %lu, # Scaffolds: %u (occ-%lu), Largest Scaffold: %lu\n", + __func__, len, (uint32_t)sl->n, occ, b.a[b.n-1]); + 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); +} + +trans_col_t *init_trans_col(ma_ug_t *ug, uint64_t r_num, kv_u_trans_t *ref) +{ + trans_col_t *p = NULL; + CALLOC(p, 1); + p->ref = ref; + p->idx = init_trans_chain(ug, r_num); + return p; +} + +void destory_trans_col(trans_col_t **p) +{ + destory_trans_chain(&((*p)->idx)); + free(*p); +} + +void resolve_hit(uint64_t x, uint32_t rLen, uint64_t uID_bits, uint64_t pos_mode, uint64_t *uid, uint64_t *beg, uint64_t *end) +{ + if(uid) (*uid) = ((x<<1)>>(64 - uID_bits)); + uint32_t rev = (x>>63); + long long ref_p = x & pos_mode; + long long p_beg, p_end; + + if(rev) + { + p_end = ref_p; + p_beg = p_end + 1 - rLen; + } + else + { + p_beg = ref_p; + p_end = p_beg + rLen - 1; + } + if(p_beg < 0) p_beg = 0; + if(p_end < 0) p_end = 0; + if(beg) (*beg) = p_beg; + if(end) (*end) = p_end + 1; +} + +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; + } + } +} + +kvec_pe_hit *get_r_hits_for_trio(kvec_pe_hit *u_hits, asg_t* r_g, ma_ug_t* ug, bubble_type* bub, uint64_t uID_bits, uint64_t pos_mode) +{ + kvec_pe_hit *r_hits = NULL; + CALLOC(r_hits, 1); + uint64_t k, l, i, r_i, offset, rid, rev, rBeg, rEnd, ubits, p_mode, upos, rpos, update, ubeg, uend, suid, euid; + 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); + + u_hits->uID_bits = uID_bits; u_hits->pos_mode = pos_mode; + for (i = r_i = 0; i < u_hits->a.n; i++) + { + suid = get_hit_suid(*u_hits, i); + euid = get_hit_euid(*u_hits, i); + if(IF_HOM(suid, *bub)) continue; + if(IF_HOM(euid, *bub)) continue; + if(suid == euid) continue; + kv_push(pe_hit, r_hits->a, u_hits->a.a[i]); + + resolve_hit(r_hits->a.a[r_i].s, r_hits->a.a[r_i].len>>32, r_hits->uID_bits, + r_hits->pos_mode, NULL, &ubeg, &uend); + upos = (ubeg+uend-1)>>1; + r_hits->a.a[r_i].s -= get_hit_spos(*r_hits, r_i); + r_hits->a.a[r_i].s += upos; + + + resolve_hit(r_hits->a.a[r_i].e, (uint32_t)r_hits->a.a[r_i].len, r_hits->uID_bits, + r_hits->pos_mode, NULL, &ubeg, &uend); + upos = (ubeg+uend-1)>>1; + r_hits->a.a[r_i].e -= get_hit_epos(*r_hits, r_i);///pos at unitig + r_hits->a.a[r_i].e += upos; + + r_hits->a.a[r_i].id = (suid<<32)|euid; + r_i++; + } + + 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) + { + 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) + { + 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; + return r_hits; +} + +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]; + } + assert((r_i == k) && (update == (k-l))); + // 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]; + } + assert((r_i == k) && (update == (k - l))); + // 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; + idx_hits(r_hits, r_g->n_seq); +} + +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 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;///rid|rev|uid + p->off = offset; + offset += (uint32_t)u->a[i]; + } + else + { + offset += GAP_LEN; + } + } + } + + radix_sort_hit_aux_ruid(x.a, x.a + x.n);///sort by (rid|rev|uid) + x.idx.n = x.idx.m = (x.n?(x.a[x.n-1].ruid>>33)+1:0);///how many reads? + 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->u.n; 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 = ((occ_1 == 1) && (occ_2 == 1)); + 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, + opt->gap_fuzz, &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, w, k, nv, vx, wx; + asg_arc_t *av = NULL; + ma_utg_t *u = NULL; + + for (i = 0; i < sg->n_arc; i++) sg->arc[i].del = (!!1); + for (i = 0; i < sg->n_seq; i++) sg->seq[i].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); + } + + if(u->circ) { + v = w = i<<1; + 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;///res keeps all intervals with >= cutoff coverage + 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); +} + +int append_sub_utg(ma_ug_t *ug, asg_t *rg, uint64_t uid, uint64_t sidx, uint64_t eidx, uint64_t *rsidx, uint64_t *reidx) +{ + if(eidx <= sidx) return 0; + uint64_t i, offset; + ma_utg_t *u = &(ug->u.a[uid]), *p = NULL; + if(u->a[sidx] == (uint64_t)-1) sidx++; + if(u->a[eidx-1] == (uint64_t)-1) eidx--; + if(eidx <= sidx) return 0 ; + kv_pushp(ma_utg_t, ug->u, &p); + memset(p, 0, sizeof(*p)); + if(rsidx) (*rsidx) = sidx; + if(reidx) (*reidx) = eidx; + p->m = p->n = eidx - sidx; + MALLOC(p->a, p->m); + memcpy(p->a, u->a + sidx, p->n*sizeof(uint64_t)); + p->start = p->a[0]>>32; + p->end = (p->a[p->n-1]>>32)^1; + p->a[p->n-1] >>= 32; p->a[p->n-1] <<= 32; + p->a[p->n-1] += rg->seq[(p->a[p->n-1]>>33)].len; + + p->circ = 0; + for (i = offset = 0; i < p->n; i++) + { + offset += (p->a[i] != (uint64_t)-1? (uint32_t)p->a[i]:GAP_LEN); + } + p->len = offset; + return 1; +} + +uint64_t get_utg_len(ma_ug_t *ug) +{ + uint64_t i, s; + for (i = s = 0; i < ug->u.n; ++i) + { + if(!ug->u.a[i].a) continue; + s += ug->u.a[i].len; + } + + return s; +} +void break_utg_horder(horder_t *h, h_covs *b_points) +{ + if(b_points->n == 0) return; + kvec_t(uint64_t) join; kv_init(join); + ma_ug_t *ug = h->ug; + uint64_t k, l, i, idx, m, pidx, de_u, u_n, oug_n = ug->u.n, dug_n = 0, puid, nuid[2], ps, pe; + radix_sort_h_cov_s(b_points->a, b_points->a+b_points->n); + + for (k = 1, l = 0; k <= b_points->n; ++k) + { + if (k == b_points->n || b_points->a[k].s != b_points->a[l].s) + { + de_u = 0; + radix_sort_h_cov_e(b_points->a+l, b_points->a+k); + u_n = ug->u.a[b_points->a[l].s].n; + for (i = l, pidx = 0; i < k; i++) + { + idx = b_points->a[i].e + 1; + if(idx > pidx && idx - pidx < u_n) + { + if(append_sub_utg(h->ug, h->r_g, b_points->a[l].s, pidx, idx, NULL, NULL)) + { + de_u++; + kv_push(uint64_t, join, (b_points->a[l].s<<32)|(ug->u.n-1)); + } + } + pidx = idx; + } + + idx = u_n; + if(idx > pidx && idx - pidx < u_n) + { + if(append_sub_utg(h->ug, h->r_g, b_points->a[l].s, pidx, idx, NULL, NULL)) + { + de_u++; + kv_push(uint64_t, join, (b_points->a[l].s<<32)|(ug->u.n-1)); + } + } + + if(de_u) + { + free(ug->u.a[b_points->a[l].s].a); free(ug->u.a[b_points->a[l].s].s); + memset(&(ug->u.a[b_points->a[l].s]), 0, sizeof(ug->u.a[b_points->a[l].s])); + dug_n++; + } + + l = k; + } + } + + // fprintf(stderr, "oug_n-%lu, dug_n-%lu\n", oug_n, dug_n); + // for (i = 0; i < join.n; i++) + // { + // fprintf(stderr, "+puid-%lu, nuid-%u\n", join.a[i]>>32, (uint32_t)join.a[i]); + // } + + for (i = 0; i < join.n; i++) + { + join.a[i] -= dug_n; + } + + for (i = m = 0; i < ug->u.n; i++) + { + if(!ug->u.a[i].a) continue; + if(i < oug_n) kv_push(uint64_t, join, (i<<32)|(m)); + ug->u.a[m] = ug->u.a[i]; + m++; + } + + if(m < ug->u.n) + { + for (i = m; i < ug->u.n; i++) + { + memset(&(ug->u.a[i]), 0, sizeof(ug->u.a[i])); + } + ug->u.n = m; + } + + // for (i = 0; i < join.n; i++) + // { + // fprintf(stderr, "-puid-%lu, nuid-%u\n", join.a[i]>>32, (uint32_t)join.a[i]); + // } + + oug_n = h->avoid.n; + radix_sort_ho64(join.a, join.a+join.n); + for (k = 1, l = 0; k <= join.n; ++k) + { + if (k == join.n || ((join.a[k]>>32) != (join.a[l]>>32))) + { + puid = (join.a[l]>>32); + nuid[0] = (uint32_t)join.a[l]; + nuid[0] <<= 1; + + nuid[1] = (uint32_t)join.a[k-1]; + nuid[1] <<= 1; nuid[1] += 1; + + for (i = 0; i < oug_n; i++) + { + ps = h->avoid.a[i]>>32; + pe = (uint32_t)h->avoid.a[i]; + + if((ps>>1) == puid) ps = nuid[ps&1]; + if((pe>>1) == puid) pe = nuid[pe&1]; + + h->avoid.a[i] = (ps<<32)|pe; + } + + if(k - l > 1) + { + for (i = l; i + 1 < k; i++) + { + nuid[0] = (uint32_t)join.a[i]; + nuid[0] <<=1; nuid[0] += 1; + + nuid[1] = (uint32_t)join.a[i+1]; + nuid[1] <<=1; + kv_push(uint64_t, h->avoid, (nuid[0]<<32)|(nuid[1])); + } + } + + l = k; + } + } + + radix_sort_ho64(h->avoid.a, h->avoid.a + h->avoid.n); + + // for (i = 0; i < h->avoid.n; i++) + // { + // fprintf(stderr, "break-s-%lu (dir: %lu), break-e-%u (dir: %u)\n", + // h->avoid.a[i]>>33, (h->avoid.a[i]>>32)&1, + // ((uint32_t)h->avoid.a[i])>>1, ((uint32_t)h->avoid.a[i])&1); + // } + + kv_destroy(join); +} + + +void update_nus(ma_utg_t *u, ma_ug_t *ug, h_cov_t *a, uint64_t a_n) +{ + uint64_t i, k, offset; + for (i = offset = 0; i < u->n; i++) + { + for (k = 0; k < a_n; k++) + { + if(a[k].s == i) + { + a[k].s = offset; a[k].e += offset; + if(k + 1 == a_n) return; + } + + } + offset += (u->a[i] != (uint64_t)-1? (uint32_t)u->a[i]:GAP_LEN); + } +} + +void break_contig(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? + + /*******************************for debug************************************/ + // 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); + /*******************************for debug************************************/ + + 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; + /*******************************for debug************************************/ + // fprintf(stderr, "cutoff: %lu, bs: %lu, be: %lu\n", cutoff, bs, be); + /*******************************for debug************************************/ + } + } + + if(res.n > 0) + { + get_consensus_break(&res, &cov_buf); + /*******************************for debug************************************/ + // 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); + // } + /*******************************for debug************************************/ + 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 = get_hit_suid(*hits, l); p->e = bs; p->dp = dp; + /*******************************for debug************************************/ + // 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); + /*******************************for debug************************************/ + } + + } + l = k; + } + } + + break_utg_horder(h, &b_points); + + kv_destroy(b); + kv_destroy(cov_buf); + kv_destroy(res); + kv_destroy(b_points); +} + +asg_arc_t *get_r_edge(asg_t *rg, uint64_t v, uint64_t w, uint64_t *id) +{ + asg_arc_t *av = asg_arc_a(rg, v); + uint64_t nv = asg_arc_n(rg, v), k; + if(id) (*id) = (uint64_t)-1; + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + if(id) (*id) = (rg->idx[v]>>32) + k; + return &(av[k]); + } + } + return NULL; +} + +void update_unitig_ends(asg_t *g, asg_arc_t *arc, uint64_t puid, uint64_t nuid_0, uint64_t nuid_1) +{ + uint64_t nv, k, v, idx, ridx; + + + v = puid<<1; + idx = g->idx[v]>>32; nv = asg_arc_n(g, v); + for (k = 0; k < nv; k++) + { + arc[idx+k].ul = ((uint32_t)arc[idx+k].ul) + (nuid_0<<32); + get_r_edge(g, g->arc[idx+k].v^1, v^1, &ridx); + arc[ridx].v = nuid_0^1; + } + + + v = (puid<<1)+1; + idx = g->idx[v]>>32; nv = asg_arc_n(g, v); + for (k = 0; k < nv; k++) + { + arc[idx+k].ul = ((uint32_t)arc[idx+k].ul) + (nuid_1<<32); + get_r_edge(g, g->arc[idx+k].v^1, v^1, &ridx); + arc[ridx].v = nuid_1^1; + } +} + + + +int get_switch_ovlp_hits(uint64_t *i, uint64_t pid, uint64_t ls, uint64_t le, u_trans_hit_t *hit, +h_covs *join, uint64_t *idx) +{ + uint64_t os, oe; + hit->qSpre = hit->qEpre = hit->qScur = hit->qEcur = hit->qn = (uint32_t)-1; + hit->tSpre = hit->tEpre = hit->tScur = hit->tEcur = hit->tn = (uint32_t)-1; + + while ((*i) < ((uint32_t)idx[pid])) + { + os = join->a[(idx[pid]>>32)+(*i)].s; + oe = join->a[(idx[pid]>>32)+(*i)].e; + if(OVL(os, oe, ls, le) == 0) + { + (*i)++; + continue; + } + + hit->qn = (uint32_t)(join->a[(idx[pid]>>32)+(*i)].dp); + hit->qScur = MAX(os, ls); hit->qEcur = MIN(oe, le); + hit->qSpre = hit->qScur - os; hit->qEpre = hit->qEcur - os; + (*i)++; + return 1; + } + + return 0; +} + +///[ts, te) +void extract_switch_sub(uint32_t i_tScur, uint32_t i_tEcur, uint32_t i_tSpre, uint32_t i_tEpre, +uint32_t tn, kv_u_trans_hit_t* ktb, uint32_t bn, uint32_t rev) +{ + uint32_t i, ovlp, found, beg, end, offS, offE; + u_trans_hit_t *q = NULL, x; + for (i = found = 0; i < bn; i++) + { + q = &(ktb->a[i]);///for q, already know [qScur, qEcur), [qSpre, qEpre), [tScur, tEcur) + + ovlp = ((MIN(i_tEcur, q->tEcur) > MAX(i_tScur, q->tScur))? + MIN(i_tEcur, q->tEcur) - MAX(i_tScur, q->tScur):0); + if(found == 1 && ovlp == 0) break; + if(ovlp > 0) found = 1; + if(ovlp == 0) continue; + + + beg = MAX(i_tScur, q->tScur); end = MIN(i_tEcur, q->tEcur); + offS = beg - q->tScur; offE = q->tEcur - end; + x.tScur = q->tScur + offS; //beg + x.tEcur = q->tEcur - offE; //end + + + x.qn = q->qn; + offS = beg - q->tScur; offE = q->tEcur - end; + if(rev == 0) + { + // x.qSpre = q->qSpre + offS; + x.qSpre = q->qSpre + get_offset_adjust(offS, q->tEcur-q->tScur, q->qEpre-q->qSpre); + // x.qEpre = q->qEpre - offE; + x.qEpre = q->qEpre - get_offset_adjust(offE, q->tEcur-q->tScur, q->qEpre-q->qSpre); + } + else + { + // x.qSpre = q->qSpre + offE; + x.qSpre = q->qSpre + get_offset_adjust(offE, q->tEcur-q->tScur, q->qEpre-q->qSpre); + // x.qEpre = q->qEpre - offS; + x.qEpre = q->qEpre - get_offset_adjust(offS, q->tEcur-q->tScur, q->qEpre-q->qSpre); + } + + x.tn = tn; + offS = beg - i_tScur; offE = i_tEcur - end; + // x.tSpre = i_tSpre + offS; + x.tSpre = i_tSpre + get_offset_adjust(offS, i_tEcur-i_tScur, i_tEpre-i_tSpre); + // x.tEpre = i_tEpre - offE; + x.tEpre = i_tEpre - get_offset_adjust(offE, i_tEcur-i_tScur, i_tEpre-i_tSpre); + + kv_push(u_trans_hit_t, *ktb, x); + + // if(x.tSpre >= x.tEpre || x.qSpre >= x.qEpre) + // { + // fprintf(stderr, "\n*********x.qn: %u, x.tn: %u\n", x.qn, x.tn); + // fprintf(stderr, "x.qSpre: %u, x.qEpre: %u, x.tSpre: %u, x.tEpre: %u\n", + // x.qSpre, x.qEpre, x.tSpre, x.tEpre); + // fprintf(stderr, "q->qScur: %u, q->qEcur: %u, q->qSpre: %u, q->qEpre: %u\n", + // q->qScur, q->qEcur, q->qSpre, q->qEpre); + // fprintf(stderr, "q->tScur: %u, q->tEcur: %u, q->tSpre: %u, q->tEpre: %u\n", + // q->tScur, q->tEcur, q->tSpre, q->tEpre); + // fprintf(stderr, "i_tScur: %u, i_tEcur: %u, i_tSpre: %u, i_tEpre: %u\n", + // i_tScur, i_tEcur, i_tSpre, i_tEpre); + // } + } +} + + +void extract_novlp(u_trans_t *e, h_covs *join, uint64_t *idx, kv_u_trans_hit_t *kv, kv_u_trans_t *n_trans) +{ + uint64_t i, bn; + u_trans_hit_t hit, *kh = NULL; + u_trans_t *kt = NULL; + kv->n = 0; + + i = 0; + while (get_switch_ovlp_hits(&i, e->qn, e->qs, e->qe, &hit, join, idx)) //get [qScur, qEcur), [qSpre, qEpre) + { + if(e->rev == 0) + { + hit.tScur = e->ts + get_offset_adjust(hit.qScur-e->qs, e->qe-e->qs, e->te-e->ts); + hit.tEcur = e->te - get_offset_adjust(e->qe-hit.qEcur, e->qe-e->qs, e->te-e->ts); + } + else + { + hit.tScur = e->ts + get_offset_adjust(e->qe-hit.qEcur, e->qe-e->qs, e->te-e->ts); + hit.tEcur = e->te - get_offset_adjust(hit.qScur-e->qs, e->qe-e->qs, e->te-e->ts); + } + + kv_push(u_trans_hit_t, *kv, hit); + } + bn = kv->n; + + i = 0; + while (get_switch_ovlp_hits(&i, e->tn, e->ts, e->te, &hit, join, idx)) + { + extract_switch_sub(hit.qScur, hit.qEcur, hit.qSpre, hit.qEpre, hit.qn, kv, bn, e->rev); + } + + double x_score, y_score; + for (i = bn; i < kv->n; i++) + { + kh = &(kv->a[i]); + if(kh->qEpre <= kh->qSpre) continue; + if(kh->tEpre <= kh->tSpre) continue; + kv_pushp(u_trans_t, *n_trans, &kt); + + kt->f = e->f; kt->rev = e->rev; kt->del = 0; + kt->qn = kh->qn; kt->qs = kh->qSpre; kt->qe = kh->qEpre; + kt->tn = kh->tn; kt->ts = kh->tSpre; kt->te = kh->tEpre; + + x_score = ((double)(kt->qe-kt->qs)/(double)(e->qe-e->qs))*e->nw; + y_score = ((double)(kt->te-kt->ts)/(double)(e->te-e->ts))*e->nw; + kt->nw = MIN(x_score, y_score); + kt->occ = 0; + + // if(kv->n - bn > 1) + // { + // fprintf(stderr, "-kt-utg%.6ul\tqs(%u)\tqe(%u)\tt-utg%.6ul\tts(%u)\tte(%u)\trev(%u)\tw(%f)\tf(%u)\n", + // kt->qn+1, kt->qs, kt->qe, kt->tn+1, kt->ts, kt->te, kt->rev, kt->nw, kt->f); + // } + + } +} + +int get_new_offset(kvec_pe_hit *hits, uint64_t id, uint64_t *index, h_covs *join, uint64_t new_uID_bits) +{ + uint64_t suid, sbeg, send, k, uid, os, oe, ls, le, occ, nuid, noff; + uint64_t euid, ebeg, eend; + resolve_hit(hits->a.a[id].s, hits->a.a[id].len>>32, hits->uID_bits, + hits->pos_mode, &suid, &sbeg, &send); + uid = suid; ls = sbeg; le = send; occ = 0; nuid = noff = (uint64_t)-1; + for (k = 0; k < ((uint32_t)index[uid]); k++) + { + os = join->a[(index[uid]>>32)+k].s; + oe = join->a[(index[uid]>>32)+k].e; + if(ls >= os && le <= oe) + { + occ++; + nuid = (uint32_t)join->a[(index[uid]>>32)+k].dp; + noff = os; + } + } + if(occ != 1) return 0; + noff = get_hit_spos(*hits, id) - noff; + nuid <<= (64 - new_uID_bits - 1); + hits->a.a[id].s >>= 63; hits->a.a[id].s <<= 63; + hits->a.a[id].s += nuid + noff; + + + resolve_hit(hits->a.a[id].e, (uint32_t)hits->a.a[id].len, hits->uID_bits, + hits->pos_mode, &euid, &ebeg, &eend); + uid = euid; ls = ebeg; le = eend; occ = 0; nuid = noff = (uint64_t)-1; + for (k = 0; k < ((uint32_t)index[uid]); k++) + { + os = join->a[(index[uid]>>32)+k].s; + oe = join->a[(index[uid]>>32)+k].e; + if(ls >= os && le <= oe) + { + occ++; + nuid = (uint32_t)join->a[(index[uid]>>32)+k].dp; + noff = os; + } + } + if(occ != 1) return 0; + noff = get_hit_epos(*hits, id) - noff; + nuid <<= (64 - new_uID_bits - 1); + hits->a.a[id].e >>= 63; hits->a.a[id].e <<= 63; + hits->a.a[id].e += nuid + noff; + return 1; +} + +void verbose_misjoin(uint64_t *a, uint64_t a_n) +{ + radix_sort_ho64(a, a + a_n); + uint64_t k, l, i, len, s, C[2], N[2]; + C[0] = C[1] = N[0] = N[1] = 0; + for (k = 1, l = 0; k <= a_n; ++k) + { + if (k == a_n || (a[k]>>63) != (a[l]>>63)) + { + for (i = l, s = 0; i < k; i++) s += ((a[i]<<1)>>1); + len = s; + + i = k; s = 0; + while (i > l) + { + i--; + s += ((a[i]<<1)>>1); + if(s >= (len>>1)) + { + N[a[l]>>63] = ((a[i]<<1)>>1); + C[a[l]>>63] = k - l; + // fprintf(stderr, "[M::%s::] N50: %lu\n", __func__, b.a[i]); + break; + } + } + + l = k; + } + } + + fprintf(stderr, "[M::stat] # misjoined unitigs: %lu (N50: %lu); # corrected unitigs: %lu (N50: %lu)\n", + C[0], N[0], C[1], N[1]); +} + +void break_phasing_utg(ma_ug_t *ug, asg_t *rg, kvec_pe_hit *hits, kv_u_trans_t *k_trans, h_covs *b_points) +{ + if(b_points->n == 0) return; + kv_u_trans_hit_t kv; kv_init(kv); + asg_arc_t *rt = NULL, *ut = NULL; + asg_t *utg = NULL; + h_cov_t *p = NULL; + h_covs join; kv_init(join); + uint64_t k, l, i, idx, m, pidx, de_u, u_n, oug_n = ug->u.n, dug_n = 0, puid, pn, rsi, prid, nrid, x, y, *index = NULL; + kv_u_trans_t *n_trans = NULL; CALLOC(n_trans, 1); + kvec_t(uint64_t) dbg_N50; kv_init(dbg_N50); + /*******************************for debug************************************/ + // debug_phasing_t *dbp = init_debug_phasing(ug, hits, k_trans, b_points); + /*******************************for debug************************************/ + radix_sort_h_cov_s(b_points->a, b_points->a+b_points->n); + for (k = 1, l = 0; k <= b_points->n; ++k) + { + if (k == b_points->n || b_points->a[k].s != b_points->a[l].s) + { + de_u = 0; pn = join.n; + radix_sort_h_cov_e(b_points->a+l, b_points->a+k); + u_n = ug->u.a[b_points->a[l].s].n; + for (i = l, pidx = 0; i < k; i++) + { + idx = b_points->a[i].e + 1; + if(idx > pidx && idx - pidx < u_n) + { + // fprintf(stderr, "sa-utg%.6lul, pidx: %lu, idx: %lu\n", b_points->a[l].s+1, pidx, idx); + if(append_sub_utg(ug, rg, b_points->a[l].s, pidx, idx, &rsi, NULL)) + { + de_u++; + kv_pushp(h_cov_t, join, &p); + p->dp = (b_points->a[l].s<<32)|(ug->u.n-1); + p->s = rsi; p->e = ug->u.a[ug->u.n-1].len; + kv_push(uint64_t, dbg_N50, (uint64_t)(ug->u.a[ug->u.n-1].len)+((uint64_t)(1)<<63));///new nodes + } + } + pidx = idx; + } + + idx = u_n; + if(idx > pidx && idx - pidx < u_n) + { + // fprintf(stderr, "sa-utg%.6lul, pidx: %lu, idx: %lu\n", b_points->a[l].s+1, pidx, idx); + if(append_sub_utg(ug, rg, b_points->a[l].s, pidx, idx, &rsi, NULL)) + { + de_u++; + kv_pushp(h_cov_t, join, &p); + p->dp = (b_points->a[l].s<<32)|(ug->u.n-1); + p->s = rsi; p->e = ug->u.a[ug->u.n-1].len; + kv_push(uint64_t, dbg_N50, (uint64_t)(ug->u.a[ug->u.n-1].len)+((uint64_t)(1)<<63));///new nodes + } + } + + if(de_u) + { + kv_push(uint64_t, dbg_N50, ug->u.a[b_points->a[l].s].len);///old nodes + update_nus(&(ug->u.a[b_points->a[l].s]), ug, join.a + pn, join.n - pn); + free(ug->u.a[b_points->a[l].s].a); free(ug->u.a[b_points->a[l].s].s); + memset(&(ug->u.a[b_points->a[l].s]), 0, sizeof(ug->u.a[b_points->a[l].s])); + dug_n++; + } + + l = k; + } + } + // fprintf(stderr, "oug_n-%lu, dug_n-%lu\n", oug_n, dug_n); + // for (i = 0; i < join.n; i++) + // { + // fprintf(stderr, "+p-utg%.6lul, n-utg%.6ul\n", (join.a[i].dp>>32)+1, ((uint32_t)join.a[i].dp)+1); + // } + + for (i = 0; i < join.n; i++) + { + join.a[i].dp -= dug_n; + } + for (i = m = 0; i < ug->u.n; i++) + { + if(!ug->u.a[i].a) continue; + if(i < oug_n) + { + kv_pushp(h_cov_t, join, &p); + p->dp = (i<<32)|(m);///current id | updated id + p->s = 0; p->e = ug->u.a[i].len; + } + + ug->u.a[m] = ug->u.a[i]; + m++; + } + if(m < ug->u.n) + { + for (i = m; i < ug->u.n; i++) + { + memset(&(ug->u.a[i]), 0, sizeof(ug->u.a[i])); + } + ug->u.n = m; + } + radix_sort_h_cov_dp(join.a, join.a+join.n); + CALLOC(index, ug->u.n); + // for (i = 0; i < join.n; i++) + // { + // fprintf(stderr, "+p-utg%.6lul (len: %u), n-utg%.6ul, s-%lu, e-%lu\n", + // (join.a[i].dp>>32)+1, ug->g->seq[(join.a[i].dp>>32)].len, ((uint32_t)join.a[i].dp)+1, join.a[i].s, join.a[i].e); + // } + utg = asg_init(); + utg->n_arc = utg->m_arc = ug->g->n_arc; + MALLOC(utg->arc, utg->n_arc); + memcpy(utg->arc, ug->g->arc, utg->n_arc*sizeof(asg_arc_t)); + for (k = 1, l = 0; k <= join.n; ++k) + { + if (k == join.n || ((join.a[k].dp>>32) != (join.a[l].dp>>32))) + { + puid = (join.a[l].dp>>32); + index[puid] = (l<<32) | (k-l); + + for (i = l; i < k; i++) + { + asg_seq_set(utg, (uint32_t)join.a[i].dp, ug->u.a[(uint32_t)join.a[i].dp].len, 0); + utg->seq[(uint32_t)join.a[i].dp].c = ug->g->seq[puid].c; + + if(i + 1 >= k) continue; + prid = ug->u.a[(uint32_t)join.a[i].dp].a[ug->u.a[(uint32_t)join.a[i].dp].n-1]>>32; + nrid = ug->u.a[(uint32_t)join.a[i+1].dp].a[0]>>32; + + rt = get_r_edge(rg, prid, nrid, NULL); + ut = asg_arc_pushp(utg); + x = (uint32_t)join.a[i].dp; x <<= 1; + y = (uint32_t)join.a[i+1].dp; y <<= 1; + ut->ol = rt->ol, ut->del = 0; + ut->ul = (uint64_t)x<<32 | (ug->u.a[x>>1].len - ut->ol); + ut->v = y; + + rt = get_r_edge(rg, nrid^1, prid^1, NULL); + ut = asg_arc_pushp(utg); + x = (uint32_t)join.a[i+1].dp; x <<= 1; x++; + y = (uint32_t)join.a[i].dp; y <<= 1; y++; + ut->ol = rt->ol, ut->del = 0; + ut->ul = (uint64_t)x<<32 | (ug->u.a[x>>1].len - ut->ol); + ut->v = y; + } + update_unitig_ends(ug->g, utg->arc, puid, ((uint32_t)join.a[k-1].dp)<<1, (((uint32_t)join.a[l].dp)<<1)+1); + l = k; + } + } + asg_cleanup(utg); + asg_destroy(ug->g); + ug->g = utg; + + for (k = 0; k < k_trans->n; k++) + { + extract_novlp(&(k_trans->a[k]), &join, index, &kv, n_trans); + } + free(k_trans->a); free(k_trans->idx.a); memset(k_trans, 0, sizeof(*k_trans)); + k_trans->a = n_trans->a; k_trans->n = n_trans->n; k_trans->m = n_trans->m; + free(n_trans); + + clean_u_trans_t_idx_adv(k_trans, ug, rg); + // clean_u_trans_t_idx(k_trans, ug, rg); + + + uint64_t uID_bits, pos_mode; + for (uID_bits=1; (uint64_t)(1<u.n; uID_bits++); + pos_mode = ((uint64_t)-1)>>(uID_bits+1); + + for (k = m = 0; k < hits->a.n; k++) + { + if(get_new_offset(hits, k, index, &join, uID_bits)) + { + hits->a.a[m] = hits->a.a[k]; + m++; + } + } + // fprintf(stderr, "hits->a.n: %u, m: %lu\n", (uint32_t)hits->a.n, m); + hits->a.n = m; + + dedup_hits(hits, 0); + hits->uID_bits = uID_bits; hits->pos_mode = pos_mode; + free(hits->idx.a); hits->idx.a = NULL; hits->idx.n = hits->idx.m = 0; + free(hits->occ.a); hits->occ.a = NULL; hits->occ.n = hits->occ.m = 0; + + /*******************************for debug************************************/ + // debug_debug_phasing_t(dbp, ug, hits, k_trans, &join, index); + // destory_debug_phasing_t(&dbp); + /*******************************for debug************************************/ + verbose_misjoin(dbg_N50.a, dbg_N50.n); + kv_destroy(join); kv_destroy(kv); free(index); kv_destroy(dbg_N50); +} + +///min_ulen = BREAK_THRES +///boundaryRate = BREAK_BOUNDARY +void update_switch_unitig(ma_ug_t *ug, asg_t *rg, kvec_pe_hit *hits, kv_u_trans_t *k_trans, uint64_t cutoff_s, uint64_t cutoff_e, +uint64_t min_ulen, double boundaryRate) +{ + 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; + radix_sort_pe_hit_idx_hn1(hits->a.a, hits->a.a + hits->a.n); + 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 >= min_ulen) + { + 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? + + /*******************************for debug************************************/ + // 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); + /*******************************for debug************************************/ + + 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*boundaryRate, ulen - ulen*boundaryRate, &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; + /*******************************for debug************************************/ + // fprintf(stderr, "cutoff: %lu, bs: %lu, be: %lu\n", cutoff, bs, be); + /*******************************for debug************************************/ + } + } + + if(res.n > 0) + { + get_consensus_break(&res, &cov_buf); + /*******************************for debug************************************/ + // 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); + // } + /*******************************for debug************************************/ + ///res -> all low coverage intervals; + ///cov_buf -> consensus coverage intervals; + get_read_breaks(&(ug->u.a[get_hit_suid(*hits, l)]), rg, &cov_buf, + &res, hits, l, k, ulen, &bs, &dp); + if(bs == (uint64_t)-1) fprintf(stderr, "ERROR-read\n"); + + if(bs > 0 && bs < ug->u.a[get_hit_suid(*hits, l)].n) + { + kv_pushp(h_cov_t, b_points, &p); + p->s = get_hit_suid(*hits, l); p->e = bs; p->dp = dp; + /*******************************for debug************************************/ + // fprintf(stderr, "\n[M::%s::] utg%.6lul, consensus_break-rid: %lu, cov: %lu, un: %u\n", + // __func__, get_hit_suid(*hits, l)+1, bs, dp, ug->u.a[get_hit_suid(*hits, l)].n); + // debug_sub_cov(hits, l, k, ulen, &(ug->u.a[get_hit_suid(*hits, l)]), h->r_g, bs, dp); + /*******************************for debug************************************/ + } + + } + + } + l = k; + } + } + // break_utg_horder(h, &b_points); + break_phasing_utg(ug, rg, hits, k_trans, &b_points); + + kv_destroy(b); + kv_destroy(cov_buf); + kv_destroy(res); + kv_destroy(b_points); +} + +void get_Ns(ma_utg_t *u, h_covs *Ns) +{ + uint64_t i, offset; + h_cov_t *p = NULL; + Ns->n = 0; + for (i = offset = 0; i < u->n; i++) + { + if(u->a[i] == (uint64_t)-1) + { + kv_pushp(h_cov_t, *Ns, &p); + p->s = offset; + p->e = offset + GAP_LEN; + p->dp = i; + } + offset += (u->a[i] != (uint64_t)-1? (uint32_t)u->a[i]:GAP_LEN); + } +} + +void debug_sub_cov(kvec_pe_hit *hits, uint64_t sidx, uint64_t eidx, uint64_t ulen, +uint64_t rs, uint64_t re, uint64_t limit_s, uint64_t limit_e, int unique_only) +{ + uint64_t i, p0s, p0e, p1s, p1e, span_s, span_e, cnt = 0, cnt_no_lim = 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; + if(unique_only && hits->a.a[i].id == 0) 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_no_lim++; + if(span_s >= limit_s && span_e <= limit_e) cnt++; + } + } + + fprintf(stderr, "******cnt-%lu, cnt_no_lim-%lu, rs-%lu, re-%lu, limit_s-%lu, limit_e-%lu\n", cnt, cnt_no_lim, rs, re, limit_s, limit_e); +} + +uint64_t get_sub_cov(kvec_pe_hit *hits, uint64_t sidx, uint64_t eidx, uint64_t ulen, +uint64_t rs, uint64_t re, uint64_t limit_s, uint64_t limit_e, int unique_only) +{ + uint64_t i, p0s, p0e, p1s, p1e, span_s, span_e, cnt = 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; + if(unique_only && hits->a.a[i].id == 0) 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) + { + if(span_s >= limit_s && span_e <= limit_e) cnt++; + } + } + + return cnt; +} + +int detect_lowNs(kvec_pe_hit *hit, uint64_t sHit, uint64_t eHit, kvec_t_u64_warp *b, +h_cov_t *Np, uint64_t len, uint64_t cutoff_s, uint64_t cutoff_e, uint64_t force_cutoff, uint64_t force_cutoff_cov, +h_covs *res, h_covs *cov_buf, h_covs *b_points, uint64_t local_bound, int unique_only) +{ + uint64_t cov_hic, cov_utg, cov_ava, i, p0s, p0e, p1s, p1e, span_s, span_e, cutoff, bs, be, occ = 0; + uint64_t sPos, ePos, min_cutoff; + h_cov_t *p = NULL; + b->a.n = 0; cov_hic = cov_utg = 0; + sPos = (Np->s>=local_bound? Np->s-local_bound:0); + ePos = (Np->e+local_bound<=len? Np->e+local_bound:len); + for (i = sHit; i < eHit; i++) + { + if(get_hit_suid(*hit, i) != get_hit_euid(*hit, i)) continue; + + p0s = get_hit_spos(*hit, i); + p0e = get_hit_spos_e(*hit, i); + p1s = get_hit_epos(*hit, i); + p1e = get_hit_epos_e(*hit, i); + + span_s = MIN(MIN(p0s, p0e), MIN(p1s, p1e)); + span_s = MIN(span_s, len-1); + span_e = MAX(MAX(p0s, p0e), MAX(p1s, p1e)); + span_e = MIN(span_e, len-1) + 1; + //if(span_e - span_s <= ulen*BREAK_CUTOFF)//need it or not? + { + if(span_s >= sPos && span_e <= ePos)///test the density of this local region; bug -> should use any HiC pairs that are overlapped with [sPos, sPoe), instead of fully covered by [sPos, sPoe) + { + occ++; + if(unique_only && hit->a.a[i].id == 0) continue; + kv_push(uint64_t, b->a, (span_s<<1)); + kv_push(uint64_t, b->a, (span_e<<1)|1); + cov_hic += (span_e - span_s); + } + } + } + + + + radix_sort_ho64(b->a.a, b->a.a+b->a.n); + cov_utg = get_hic_cov_interval(b->a.a, b->a.n, 1, NULL, NULL, NULL); + cov_ava = (cov_utg? cov_hic/cov_utg:0); + if(force_cutoff != (uint64_t)-1 || force_cutoff_cov != (uint64_t)-1) + { + min_cutoff = get_sub_cov(hit, sHit, eHit, len, Np->s, Np->e, sPos, ePos, unique_only); + if((force_cutoff != (uint64_t)-1 && min_cutoff <= (cov_ava/force_cutoff)) || + (force_cutoff_cov != (uint64_t)-1 && min_cutoff <= force_cutoff_cov)) + { + kv_pushp(h_cov_t, *b_points, &p); + p->s = get_hit_suid(*hit, sHit); p->e = Np->dp; p->dp = 0; + return 1; + } + } + + ///if cov_ava == 0, do nothing or break? + /*******************************for debug************************************/ + // 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(*hit, sHit)+1, len, (uint64_t)(b->a.n>>1), cov_hic, cov_utg, cov_ava); + /*******************************for debug************************************/ + + // fprintf(stderr, "[M::%s::] sPos: %lu, ePos: %lu, # hits: %lu, # non-unique hits: %lu, cov_hic: %lu, cov_utg: %lu, cov_ava: %lu\n", + // __func__, sPos, ePos, (uint64_t)(b->a.n>>1), occ, cov_hic, cov_utg, cov_ava); + // debug_sub_cov(hit, sHit, eHit, len, Np->s, Np->e, sPos, ePos, unique_only); + 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.a, b->a.n, cutoff, cov_buf, sPos + (ePos-sPos)*BREAK_BOUNDARY, + ePos - (ePos-sPos)*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; + /*******************************for debug************************************/ + // fprintf(stderr, "cutoff: %lu, bs: %lu, be: %lu\n", cutoff, bs, be); + /*******************************for debug************************************/ + } + } + + if(res->n > 0) + { + get_consensus_break(res, cov_buf); + /*******************************for debug************************************/ + // 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); + // } + /*******************************for debug************************************/ + for (i = 0, min_cutoff = (uint64_t)-1; i < cov_buf->n; i++) + { + if(cov_buf->a[i].s<=Np->s && cov_buf->a[i].e>=Np->e) + { + break; + } + min_cutoff = MIN(min_cutoff, cov_buf->a[i].dp); + } + if(i < cov_buf->n || + get_sub_cov(hit, sHit, eHit, len, Np->s, Np->e, sPos, ePos, unique_only) <= min_cutoff) + { + kv_pushp(h_cov_t, *b_points, &p); + p->s = get_hit_suid(*hit, sHit); p->e = Np->dp; p->dp = 0; + return 1; + /*******************************for debug************************************/ + // fprintf(stderr, "consensus_break-rid: %lu\n", p->e); + /*******************************for debug************************************/ + } + } + return 0; +} + +uint64_t break_scaffold(horder_t *h, uint64_t cutoff_s, uint64_t cutoff_e, uint64_t force_cutoff, uint64_t force_cutoff_cov, +uint64_t local_bound, int unique_only, h_covs *r_b_points) +{ + uint64_t k, l, i, ulen; + kvec_t_u64_warp b; kv_init(b.a); + h_covs cov_buf; kv_init(cov_buf); + h_covs res; kv_init(res); + h_covs *b_points = NULL; + if(r_b_points) b_points = r_b_points; + else CALLOC(b_points, 1); + b_points->n = 0; + h_covs Ns; kv_init(Ns); + ma_ug_t *ug = h->ug; + kvec_pe_hit *hits = &(h->u_hits); + 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; + Ns.n = 0; + if(ulen >= BREAK_THRES) + { + get_Ns(&(ug->u.a[get_hit_suid(*hits, l)]), &Ns); + // fprintf(stderr, "\n[M::%s::] utg%.6lul, ulen: %lu, # Ns: %lu\n", + // __func__, get_hit_suid(*hits, l)+1, ulen, (uint64_t)(Ns.n)); + if(Ns.n) + { + for (i = 0; i < Ns.n; i++) + { + if(detect_lowNs(hits, l, k, &b, &(Ns.a[i]), ulen, cutoff_s, cutoff_e, force_cutoff, + force_cutoff_cov, &res, &cov_buf, b_points, local_bound, unique_only) && r_b_points){ + b_points->a[b_points->n-1].dp = i; + } + } + } + } + l = k; + } + } + + if(!r_b_points){ + break_utg_horder(h, b_points); + kv_destroy(*b_points); + } + + kv_destroy(b.a); + kv_destroy(cov_buf); + kv_destroy(res); + kv_destroy(Ns); + + return b_points->n; +} + +uint64_t break_scaffold_mean(horder_t *h, uint64_t cutoff_s, uint64_t cutoff_e, uint64_t force_cutoff, uint64_t force_cutoff_cov, +uint64_t local_bound, int unique_only, h_covs *r_b_points) +{ + uint64_t k, l, i, ulen; + kvec_t_u64_warp b; kv_init(b.a); + h_covs cov_buf; kv_init(cov_buf); + h_covs res; kv_init(res); + h_covs *b_points = NULL; + if(r_b_points) b_points = r_b_points; + else CALLOC(b_points, 1); + b_points->n = 0; + h_covs Ns; kv_init(Ns); + ma_ug_t *ug = h->ug; + kvec_pe_hit *hits = &(h->u_hits); + 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; + Ns.n = 0; + // if(ulen >= BREAK_THRES) + { + get_Ns(&(ug->u.a[get_hit_suid(*hits, l)]), &Ns); + if(Ns.n) + { + for (i = 0; i < Ns.n; i++) + { + if(detect_lowNs(hits, l, k, &b, &(Ns.a[i]), ulen, cutoff_s, cutoff_e, force_cutoff, + force_cutoff_cov, &res, &cov_buf, b_points, local_bound, unique_only) && r_b_points){ + b_points->a[b_points->n-1].dp = i; + } + } + } + } + l = k; + } + } + + if(!r_b_points){ + break_utg_horder(h, b_points); + kv_destroy(*b_points); + } + + kv_destroy(b.a); + kv_destroy(cov_buf); + kv_destroy(res); + kv_destroy(Ns); + + return b_points->n; +} + + +void generate_haplotypes(horder_t *h, ug_opt_t *opt) +{ + uint64_t i; + ma_ug_t *ug_1 = NULL, *ug_2 = NULL; + + ug_1 = get_trio_unitig_graph(h->r_g, FATHER, opt); + ug_2 = get_trio_unitig_graph(h->r_g, MOTHER, opt); + // kv_push(uint64_t, h->occ, ug_1->u.n); + // kv_push(uint64_t, h->occ, ug_2->u.n); + + h->ug = ug_1; + + ///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; + } + + ug_1 = NULL; + ma_ug_destroy(ug_2); + asg_destroy(h->ug->g); + h->ug->g = NULL; + + // MALLOC(h->hf.a, h->ug->u.n); h->hf.n = h->hf.m = h->ug->u.n; + // for (i = 0; i < h->ug->u.n; i++) h->hf.a[i] = (i < h->occ.a[0]? 0 : 1); +} + +osg_t *osg_init(void) +{ + return (osg_t*)calloc(1, sizeof(osg_t)); +} + +void osg_destroy(osg_t *g) +{ + if (g == 0) return; + free(g->seq); free(g->idx); free(g->arc); + free(g); +} + +void osg_seq_set(osg_t *g, int sid, int del) +{ + ///just malloc size + if (sid >= (int)g->m_seq) { + g->m_seq = sid + 1; + kv_roundup32(g->m_seq); + g->seq = (osg_seq_t*)realloc(g->seq, g->m_seq * sizeof(osg_seq_t)); + } + + if (sid >= g->n_seq) g->n_seq = sid + 1; + g->seq[sid].del = !!del; +} + +static inline osg_arc_t *osg_arc_pushp(osg_t *g) +{ + if (g->n_arc == g->m_arc) { + g->m_arc = g->m_arc? g->m_arc<<1 : 16; + g->arc = (osg_arc_t*)realloc(g->arc, g->m_arc * sizeof(osg_arc_t)); + } + return &g->arc[g->n_arc++]; +} + +void osg_arc_rm(osg_t *g) +{ + uint32_t e, n; + ///just clean arc requiring: 1. arc it self must be available 2. both the query and target are available + for (e = n = 0; e < g->n_arc; ++e) { + //u and v is the read id + uint32_t u = g->arc[e].u, v = g->arc[e].v; + if (!g->arc[e].del && !g->seq[u>>1].del && !g->seq[v>>1].del) + g->arc[n++] = g->arc[e]; + } + if (n < g->n_arc) { // arc index is out of sync + if (g->idx) free(g->idx); + g->idx = 0; + } + g->n_arc = n; +} + +uint64_t *osg_arc_index_core(size_t max_seq, size_t n, const osg_arc_t *a) +{ + size_t i, last; + uint64_t *idx; + idx = (uint64_t*)calloc(max_seq * 2, 8); + + for (i = 1, last = 0; i <= n; ++i) + if (i == n || a[i-1].u != a[i].u) + idx[a[i-1].u] = (uint64_t)last<<32 | (i - last), last = i; + return idx; +} + +void osg_arc_index(osg_t *g) +{ + if (g->idx) free(g->idx); + g->idx = osg_arc_index_core(g->n_seq, g->n_arc, g->arc); +} + +void osg_cleanup(osg_t *g) +{ + osg_arc_rm(g); + if (!g->is_srt) { + radix_sort_osg(g->arc, g->arc + g->n_arc); + g->is_srt = 1; + } + + if (g->idx == 0) osg_arc_index(g); +} + +double get_max_weight(uint32_t u, uint32_t v, osg_t *g) +{ + double max = 0; + uint32_t i, nv; + osg_arc_t *av = NULL; + + nv = asg_arc_n(g, u); + av = asg_arc_a(g, u); + for (i = 0; i < nv; i++) + { + if(av[i].v == v) continue; + max = MAX(max, av[i].w); + } + + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + for (i = 0; i < nv; i++) + { + if(av[i].v == u) continue; + max = MAX(max, av[i].w); + } + + return max; +} + +dens_idx_t *build_interval_idx(kvec_pe_hit *hits, ma_ug_t *ug) +{ + uint64_t i, k, l, p0s, p0e, p1s, p1e, suid, euid, slen, elen, span_s, span_e; + dens_idx_t *idx = NULL; + CALLOC(idx, 1); + + for (i = 0; i < hits->a.n; i++) { + if(!hits->a.a[i].id) continue; + suid = get_hit_suid(*hits, i); + euid = get_hit_euid(*hits, i); + slen = ug->u.a[suid].len; + elen = ug->u.a[euid].len; + + p0s = get_hit_spos(*hits, i); + p0e = get_hit_spos_e(*hits, i); + span_s = MIN(p0s, p0e); + span_s = MIN(span_s, slen-1); + span_e = MAX(p0s, p0e); + span_e = MIN(span_e, slen-1); + span_s = ((span_s+span_e)>>1); + kv_push(uint64_t, idx->pos, (suid<<32)|span_s); + + + p1s = get_hit_epos(*hits, i); + p1e = get_hit_epos_e(*hits, i); + span_s = MIN(p1s, p1e); + span_s = MIN(span_s, elen-1); + span_e = MAX(p1s, p1e); + span_e = MIN(span_e, elen-1); + span_s = ((span_s+span_e)>>1); + kv_push(uint64_t, idx->pos, (euid<<32)|span_s); + } + radix_sort_ho64(idx->pos.a, idx->pos.a + idx->pos.n); + idx->n = idx->m = ug->u.n; + CALLOC(idx->a, idx->n); + for (k = 1, l = 0; k <= idx->pos.n; ++k) { + if (k == idx->pos.n || ((idx->pos.a[k]>>32) != (idx->pos.a[l]>>32))) { + idx->a[idx->pos.a[l]>>32] = (uint64_t)l << 32 | (k - l); + l = k; + } + } + return idx; +} + +uint64_t get_vw_hits_num(h_w_t *e, uint64_t x, uint64_t y) +{ + uint64_t i, occ; + hw_aux_t *ep = NULL; + for (i = occ = 0; i < e->n; i++) + { + ep = &(e->a[i]); + if(((ep->e>>33) == x && (((uint32_t)(ep->e))>>1) == y) || + ((ep->e>>33) == y && (((uint32_t)(ep->e))>>1) == x)) + { + occ++; + } + } + return occ; +} + +void update_h_w(h_w_t *e, dens_idx_t *idx, double *max_div) +{ + uint64_t k, l, ii, pi, pos, ori, uid, *id = NULL, idn; + if(max_div) (*max_div) = 0; + radix_sort_hw_e(e->a, e->a+e->n); + for (k = 1, l = 0; k <= e->n; ++k) + { + if (k == e->n || (e->a[k].e>>32) != (e->a[l].e>>32)) ///same uid + { + if(k - l > 1) radix_sort_hw_d(e->a+l, e->a+k); + ori = (e->a[l].e>>32)&1; + uid = e->a[l].e>>33; + id = idx->pos.a + (idx->a[uid]>>32); + idn = (uint32_t)(idx->a[uid]); + ii = 0; + for (pi = l; pi < k; pi++) + { + pos = e->a[pi].d>>32;///loc of 3'-end + while (ii < idn) + { + if(((uint32_t)id[ii]) == pos) + { + if(ori)///the most left one + { + break; + } + else + { + while (ii < idn && (((uint32_t)id[ii]) == pos))///the most right one + { + ii++; + } + ii--; + break; + } + } + ii++; + } + if(ii >= idn) fprintf(stderr, "ERROR-1\n"); + e->a[pi].w += (ori? idn-ii: ii+1);///the smaller the better + if(max_div) (*max_div) = MAX((*max_div), e->a[pi].w); + } + l = k; + } + } + + radix_sort_hw_ew(e->a, e->a+e->n); + for (k = 1, l = 0; k <= e->n; ++k) + { + if (k == e->n || ((uint32_t)(e->a[k].e)) != ((uint32_t)(e->a[l].e))) ///same uid + { + if(k - l > 1) radix_sort_hw_dw(e->a+l, e->a+k); + ori = e->a[l].e&1; + uid = (((uint32_t)e->a[l].e)>>1); + id = idx->pos.a + (idx->a[uid]>>32); + idn = (uint32_t)(idx->a[uid]); + ii = 0; + for (pi = l; pi < k; pi++) + { + pos = (uint32_t)(e->a[pi].d);/// + while (ii < idn) + { + if(((uint32_t)id[ii]) == pos) + { + if(ori) + { + break; + } + else + { + while (ii < idn && (((uint32_t)id[ii]) == pos)) + { + ii++; + } + ii--; + break; + } + } + ii++; + } + if(ii >= idn) fprintf(stderr, "ERROR-2\n"); + e->a[pi].w += (ori? idn-ii: ii+1); + if(max_div) (*max_div) = MAX((*max_div), e->a[pi].w); + } + l = k; + } + } + // radix_sort_hw_e(e->a, e->a+e->n); + if(max_div) (*max_div) *= 2;///different with slsa2 +} + +void print_specfic_hic_hits(kvec_pe_hit *hits, uint64_t v, uint64_t w, ma_ug_t *ug) +{ + uint64_t i, suid, euid, slen, elen, p0s, p0e, p1s, p1e, span_s, span_e, sd, ed; + for (i = 0; i < hits->a.n; i++) + { + if(!hits->a.a[i].id) continue; + suid = get_hit_suid(*hits, i); + euid = get_hit_euid(*hits, i); + if((suid == v && euid == w) || (suid == w && euid == v)) + { + slen = ug->u.a[suid].len; + elen = ug->u.a[euid].len; + + p0s = get_hit_spos(*hits, i); + p0e = get_hit_spos_e(*hits, i); + span_s = MIN(p0s, p0e); + span_s = MIN(span_s, slen-1); + span_e = MAX(p0s, p0e); + span_e = MIN(span_e, slen-1); + span_s = ((span_s+span_e)>>1); + sd = span_s; + + + p1s = get_hit_epos(*hits, i); + p1e = get_hit_epos_e(*hits, i); + span_s = MIN(p1s, p1e); + span_s = MIN(span_s, elen-1); + span_e = MAX(p1s, p1e); + span_e = MIN(span_e, elen-1); + span_s = ((span_s+span_e)>>1); + ed = span_s; + + fprintf(stderr, "u-stg%.6lul\t%lu\tv-stg%.6lul\t%lu\n", suid+1, sd, euid + 1, ed); + } + } +} + +kv_u_trans_t *get_update_trans_idx(horder_t *h, trans_col_t *t_idx) +{ + uint64_t i, k, l; + uint32_t uid/**, q_n, t_n**/; + ma_ug_t *ug = h->ug; + asg_t *rg = h->r_g; + kv_u_trans_t *idx = NULL; CALLOC(idx, 1); + u_trans_hit_idx iter; + u_trans_hit_t hit; + kvec_t(u_hit_t) b; kv_init(b); + uint64_t *b_idx = NULL; CALLOC(b_idx, t_idx->ref->idx.n); + /**u_hit_t *q, *t;**/ + u_hit_t *p = NULL; + for (i = 0; i < ug->u.n; i++) + { + uid = i<<1; + reset_u_trans_hit_idx(&iter, &uid, 1, ug, rg, t_idx->idx, 0, ug->u.a[i].len); + while(get_u_trans_hit(&iter, &hit))///get [qScur, qEcur), [qSpre, qEpre) + { + kv_pushp(u_hit_t, b, &p); + p->Scur = hit.qScur; + p->Ecur = hit.qEcur; + p->Spre = hit.qSpre; + p->Epre = hit.qEpre; + p->uPre = hit.qn; + p->uCur = uid; + } + } + + radix_sort_u_hit(b.a, b.a + b.n); + for (k = 1, l = 0; k <= b.n; ++k) + { + if (k == b.n || (b.a[k].uPre>>1) != (b.a[l].uPre>>1)) + { + b_idx[b.a[l].uPre>>1] = (uint64_t)l << 32 | (k - l); + l = k; + } + } + + /** + for (i = 0; i < t_idx->ref->idx.n; i++) + { + q_n = (uint32_t)b_idx[i]; + q = b.a + (b_idx[i]>>32); + if(!q_n) continue; + } + **/ + + // for (i = 0; i < b.n; i++) + // { + + // } + + + free(b_idx); + kv_destroy(b); + return idx; +} + +void update_scg(horder_t *h, trans_col_t *t_idx) +{ + uint64_t i, k, l, p0s, p0e, p1s, p1e, span_s, span_e, suid, euid, v, w, slen, elen, sd, ed; + uint64_t t_hits = 0, a_hits = 0; + double max_div, we; + h_w_t e; kv_init(e); + dens_idx_t *idx = NULL; + hw_aux_t *ep = NULL; + ma_ug_t *ug = h->ug; + kvec_pe_hit *hits = &(h->u_hits); + osg_arc_t *p = NULL; + osg_destroy(h->sg.g); + h->sg.g = osg_init(); + for (i = 0; i < ug->u.n; i++) { + osg_seq_set(h->sg.g, i, 0); + h->sg.g->seq[i].mw[0] = h->sg.g->seq[i].mw[1] = 0; + h->sg.g->seq[i].ez[0] = ug->u.a[i].len>>1; + h->sg.g->seq[i].ez[1] = ug->u.a[i].len - (ug->u.a[i].len>>1); + } + idx = build_interval_idx(hits, ug);///idx is used to get density + + for (i = 0, e.n = 0; i < hits->a.n; i++) { + if(!hits->a.a[i].id) continue;//hom hits + suid = get_hit_suid(*hits, i); + euid = get_hit_euid(*hits, i); + if(suid == euid) continue;//same unitig + slen = ug->u.a[suid].len; + elen = ug->u.a[euid].len; + + p0s = get_hit_spos(*hits, i); + p0e = get_hit_spos_e(*hits, i); + span_s = MIN(p0s, p0e); + span_s = MIN(span_s, slen-1); + span_e = MAX(p0s, p0e); + span_e = MIN(span_e, slen-1); + span_s = ((span_s+span_e)>>1); + sd = span_s; + v = suid << 1; + if(span_s > (slen>>1)) v++; + + + p1s = get_hit_epos(*hits, i); + p1e = get_hit_epos_e(*hits, i); + span_s = MIN(p1s, p1e); + span_s = MIN(span_s, elen-1); + span_e = MAX(p1s, p1e); + span_e = MIN(span_e, elen-1); + span_s = ((span_s+span_e)>>1); + ed = span_s; + w = euid << 1; + if(span_s > (elen>>1)) w++; + t_hits++; + + kv_pushp(hw_aux_t, e, &ep); + ep->w = 0; + ep->e = (v<<32)|w; + ep->d = (sd<<32)|ed; + + if(v > w) { + ep->e = (w<<32)|v; + ep->d = (ed<<32)|sd; + } + + // div = h->sg.g->seq[v>>1].ez[v&1] + h->sg.g->seq[w>>1].ez[w&1]; + // max_div = MAX(max_div, div); + a_hits++; + } + + // fprintf(stderr, "sa-0-sa: occ-%lu\n", get_vw_hits_num(&e, 12, 690)); + // print_specfic_hic_hits(hits, 12, 690, ug); + + + + update_h_w(&e, idx, &max_div); + + // fprintf(stderr, "sa-1-sa: occ-%lu\n", get_vw_hits_num(&e, 676, 738)); + + radix_sort_hw_e(e.a, e.a+e.n); + for (k = 1, l = 0; k <= e.n; ++k) + { + if (k == e.n || e.a[k].e != e.a[l].e) + { + for (i = 0; i < h->avoid.n; i++) + { + v = e.a[l].e; + w = e.a[l].e<<32; w |= (e.a[l].e>>32); + if(h->avoid.a[i] == v || h->avoid.a[i] == w) + { + break; + } + } + + if(i >= h->avoid.n) + { + for (i = l, we = 0; i < k; i++) + { + if(e.a[i].w == 0) fprintf(stderr, "ERROR-3\n"); + we += (max_div/e.a[i].w); + } + + p = osg_arc_pushp(h->sg.g); + p->u = p->v = p->occ = p->del = p->w = p->nw = 0; + p->u = e.a[l].e>>32; p->v = (uint32_t)e.a[l].e; + p->occ = k - l; p->w = we; + // if(div != 0) p->w = (double)(k - l)*(max_div/div); + p = osg_arc_pushp(h->sg.g); + p->u = p->v = p->occ = p->del = p->w = p->nw = 0; + p->u = (uint32_t)e.a[l].e; p->v = e.a[l].e>>32; + p->occ = k - l; p->w = we; + + + h->sg.g->seq[e.a[l].e>>33].mw[(e.a[l].e>>32)&1] + = MAX(h->sg.g->seq[e.a[l].e>>33].mw[(e.a[l].e>>32)&1], p->w); + h->sg.g->seq[((uint32_t)e.a[l].e)>>1].mw[e.a[l].e&1] + = MAX(h->sg.g->seq[((uint32_t)e.a[l].e)>>1].mw[e.a[l].e&1], p->w); + } + + l = k; + } + } + + // fprintf(stderr, "sa-2-sa: occ-%lu\n", get_vw_hits_num(&e, 676, 738)); + osg_cleanup(h->sg.g); + double bestAlt; + uint64_t eg_edges = 0; + for (i = 0; i < h->sg.g->n_arc; i++)///all p->w should be >= 2 + { + p = &(h->sg.g->arc[i]); + bestAlt = MAX(h->sg.g->seq[p->u>>1].mw[p->u&1], h->sg.g->seq[p->v>>1].mw[p->v&1]); + if(p->w >= bestAlt*0.95)///acutally should be p->w == bestAlt + { + bestAlt = get_max_weight(p->u, p->v, h->sg.g); + } + + if(bestAlt == 0) bestAlt = 1; + ///if there is just one edges between p->u and p->v, then bestAlt -> p->nw <= 1; this is wrong + p->nw = p->w/bestAlt; + if(p->nw > 1) eg_edges++; + } + + fprintf(stderr, "[M::%s::] # Nodes: %u, # Edges: %u, # Best Edges: %lu, t_hits: %lu, a_hits: %lu\n", + __func__, h->sg.g->n_seq, h->sg.g->n_arc, eg_edges, t_hits, a_hits); + + /*******************************for debug************************************/ + /** + for (i = 0; i < h->sg.g->n_arc; i++) + { + p = &(h->sg.g->arc[i]); + fprintf(stderr, "u-stg%.6ul(%c)(div:%f)\tv-stg%.6ul(%c)(div:%f)\tocc:%u\tw:%f\tnw:%f\n", + (p->u>>1)+1, "+-"[p->u&1], h->sg.g->seq[p->u>>1].ez[p->u&1], + (p->v>>1)+1, "+-"[p->v&1], h->sg.g->seq[p->v>>1].ez[p->v&1], p->occ, p->w, p->nw); + } + fprintf(stderr, "sbsbsbsb\n\n\n\n\n\n"); + **/ + + // uint32_t u, nv, f; + // osg_arc_t *av = NULL; + // for (k = 0; k < h->sg.g->n_arc; k++) + // { + // p = &(h->sg.g->arc[k]); + // u = p->u; v = p->v; + // f = 0; + + // nv = asg_arc_n(h->sg.g, u); + // av = asg_arc_a(h->sg.g, u); + // for (i = 0; i < nv; i++) + // { + // if(av[i].v == v) continue; + // if(av[i].w > p->w) f = 1; + // } + + // nv = asg_arc_n(h->sg.g, v); + // av = asg_arc_a(h->sg.g, v); + // for (i = 0; i < nv; i++) + // { + // if(av[i].v == u) continue; + // if(av[i].w > p->w) f = 1; + // } + + // if(p->nw > 1 && f == 1) fprintf(stderr, "ERROR1\n"); + // if(p->nw <= 1 && f == 0) + // { + // fprintf(stderr, "\nERROR2, nw-%f, w-%f, u-%u, v-%u\n", p->nw, p->w, p->u, p->v); + // nv = asg_arc_n(h->sg.g, u); + // av = asg_arc_a(h->sg.g, u); + // for (i = 0; i < nv; i++) + // { + // if(av[i].v == v) continue; + // fprintf(stderr, "+u-%u, v-%u, w-%f\n", av[i].u, av[i].v, av[i].w); + // } + + // nv = asg_arc_n(h->sg.g, v); + // av = asg_arc_a(h->sg.g, v); + // for (i = 0; i < nv; i++) + // { + // if(av[i].v == u) continue; + // fprintf(stderr, "-u-%u, v-%u, w-%f\n", av[i].u, av[i].v, av[i].w); + // } + // } + + // } + /*******************************for debug************************************/ + kv_destroy(e); + free(idx->pos.a); + free(idx->a); + free(idx); +} + +int cmp_arc_nw(const void * a, const void * b) +{ + if((*(osg_arc_t*)a).nw == (*(osg_arc_t*)b).nw) return 0; + return (*(osg_arc_t*)a).nw < (*(osg_arc_t*)b).nw ? 1 : -1; +} + +#define arc_first(g, v) ((g)->arc[(g)->idx[(v)]>>32]) +void get_backbone_layout(horder_t *h, sc_lay_t *sl, osg_t *lg, uint8_t *vis) +{ + uint32_t k, v, nc = 0, c = 0; + lay_t *p = NULL; + osg_arc_t *t = NULL; + sl->n = 0; + ///in lg, there might be single-path paths or cycles + memset(vis, 0, sizeof(uint8_t)*(lg->n_seq<<1)); + for (k = 0; k < lg->n_seq; k++) + { + ///I guess this should be (!!(asg_arc_n(lg, k<<1)))^(!!(asg_arc_n(lg, (k<<1)+1)))? + ///no, since asg_arc_n is at most 1 + if((asg_arc_n(lg, k<<1))^(asg_arc_n(lg, (k<<1)+1)))///end scaffolding + { + v = (asg_arc_n(lg, k<<1)?(k<<1):((k<<1)+1)); + if(vis[k<<1] || vis[(k<<1)+1]) continue; + kv_pushp(lay_t, *sl, &p); + kv_init(*p); + kv_push(uint32_t, *p, v^1); + kv_push(uint32_t, *p, v); + vis[v] = vis[v^1] = 1; + + while (asg_arc_n(lg, v)) + { + v = (arc_first(lg, v).v)^1; + kv_push(uint32_t, *p, v^1); + kv_push(uint32_t, *p, v); + vis[v] = vis[v^1] = 1; + } + } + } + + nc = sl->n; + for (k = 0; k < lg->n_seq; k++) + { + if(vis[k<<1] || vis[(k<<1)+1]) continue; + if(asg_arc_n(lg, k<<1) && asg_arc_n(lg, (k<<1)+1))//circle + { + v = k<<1; t = NULL; + while (asg_arc_n(lg, v)) + { + if((!t) || (t->nw > arc_first(lg, v).nw) + || (t->nw == arc_first(lg, v).nw && t->w > arc_first(lg, v).w)) + { + t = &(arc_first(lg, v)); + } + v = (arc_first(lg, v).v)^1; + if(v == (k<<1)) break; + } + + v = t->v^1; + kv_pushp(lay_t, *sl, &p); + kv_init(*p); + kv_push(uint32_t, *p, v^1); + kv_push(uint32_t, *p, v); + vis[v] = vis[v^1] = 1; + + while (1) + { + v = (arc_first(lg, v).v)^1; + if(vis[v]) break; + kv_push(uint32_t, *p, v^1); + kv_push(uint32_t, *p, v); + vis[v] = vis[v^1] = 1; + } + } + } + + c = sl->n - nc; + fprintf(stderr, "[M::%s::] # Scaffolds: %u, # non-circles: %u, # circles: %u\n", + __func__, (uint32_t)sl->n, nc, c); + /*******************************for debug************************************/ + // for (k = 0; k < sl->n; k++) + // { + // p = &(sl->a[k]); + // if(k >= nc) + // { + // fprintf(stderr, "%s:\t", k < nc?"non-circle":"circle"); + // for (i = 0; i < p->n; i+=2) + // { + // if((p->a[i]>>1) != (p->a[i+1]>>1)) fprintf(stderr, "ERROR-S\n"); + // fprintf(stderr, "utg%.6ul[%u%u](%u)#", p->a[i]>>1, p->a[i]&1, p->a[i+1]&1, h->ug->u.a[p->a[i]>>1].len); + // } + // fprintf(stderr, "\n"); + // } + + // for (i = 1; i < p->n; i+=2) + // { + // if(k < nc) + // { + // if(i < p->n - 1) + // { + // if(asg_arc_n(lg, p->a[i])!=1) fprintf(stderr, "ERROR-A\n"); + // if(arc_first(lg, p->a[i]).v!=p->a[i+1]) fprintf(stderr, "ERROR-B\n"); + // } + + // if(i == p->n - 1) + // { + // if(asg_arc_n(lg, p->a[i])!=0) fprintf(stderr, "ERROR-A-0\n"); + // } + // } + + + // if(k >= nc) + // { + // if(i < p->n - 1) + // { + // if(asg_arc_n(lg, p->a[i])!=1) fprintf(stderr, "ERROR-A\n"); + // if(arc_first(lg, p->a[i]).v!=p->a[i+1]) fprintf(stderr, "ERROR-B\n"); + // fprintf(stderr, "i-%u, nw-%f\n", i, arc_first(lg, p->a[i]).nw); + // } + + // if(i == p->n - 1) + // { + // if(asg_arc_n(lg, p->a[i])!=1) fprintf(stderr, "ERROR-A\n"); + // if(arc_first(lg, p->a[i]).v!=p->a[0]) fprintf(stderr, "ERROR-B-0\n"); + // fprintf(stderr, "i-%u, nw-%f\n", i, arc_first(lg, p->a[i]).nw); + // } + // } + // } + + // } + + + // for (k = 0; k < lg->n_seq; k++) + // { + // if(!asg_arc_n(lg, k<<1) && !asg_arc_n(lg, (k<<1)+1)) + // { + // if(vis[k<<1] || vis[(k<<1)+1]) fprintf(stderr, "ERROR-bone\n"); + // } + // } + /*******************************for debug************************************/ +} + +/** +static void worker_for_insert(void *data, long i, int tid) // callback for kt_for() +{ + sc_id_t *s = &((*(sc_mul*)(data)).a[i]); + osg_t *sg = (*(sc_mul*)(data)).sg; + sc_lay_t *sl = (*(sc_mul*)(data)).sl; + lay_t *p = NULL; + uint32_t k, i, uid = s->uid; + for (k = 0; k < sl->n; k++) + { + p = &(sl->a[k]); + for (i = 0; i < p->n; i += 2) + { + } + } +} + + +void refine_layout(horder_t *h, sc_lay_t *sl, uint8_t *vis) +{ + uint32_t i; + sc_id_t *p = NULL; + sc_mul st; kv_init(st); + st.sl = sl; st.sg = h->sg.g; st.n_thread = asm_opt.thread_num; + for (i = 0; i < h->sg.g->n_seq; i++) + { + if(vis[i<<1]) continue; + kv_pushp(sc_id_t, st, &p); + p->uid = i; + p->iid = p->ori = p->sid = 0; + } + + while (st.n) + { + kt_for(st.n_thread, worker_for_insert, &st, st.n); + } + sc_id_t + + kv_destroy(st); +} +**/ +void refine_layout_back(horder_t *h, sc_lay_t *sl, uint8_t *vis) +{ + uint32_t i, k, m, v, nv, max_k; + osg_arc_t *av = NULL; + lay_t *p = NULL; + uint8_t *sgv = NULL; MALLOC(sgv, sl->n); + double *w = NULL; MALLOC(w, sl->n); + uint32_t *idx = NULL; MALLOC(idx, h->sg.g->n_seq); + memset(idx, -1, sizeof(uint32_t)*h->sg.g->n_seq); + kvec_t(uint64_t) p_refine; kv_init(p_refine); + + for (k = 0; k < sl->n; k++) + { + p = &(sl->a[k]); + for (m = 0; m < p->n; m++) + { + idx[p->a[m]>>1] = k; + } + } + + for (i = 0, p_refine.n = 0; i < h->sg.g->n_seq; i++) + { + if(vis[i<<1]) continue; + if(!asg_arc_n(h->sg.g, i<<1)&&!asg_arc_n(h->sg.g, (i<<1)+1)) continue; + for (k = 0; k < sl->n; k++) w[k] = 0, sgv[k] = 0; + + v = i<<1; + nv = asg_arc_n(h->sg.g, v); + av = asg_arc_a(h->sg.g, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + w[idx[av[k].v>>1]] += av[k].nw; + sgv[idx[av[k].v>>1]] = 1; + } + + + v = (i<<1) + 1; + nv = asg_arc_n(h->sg.g, v); + av = asg_arc_a(h->sg.g, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + w[idx[av[k].v>>1]] += av[k].nw; + sgv[idx[av[k].v>>1]] = 1; + } + + for (k = 0, max_k = (uint32_t)-1; k < sl->n; k++) + { + if(!sgv[k]) continue; + if(max_k == (uint32_t)-1 || w[max_k] < w[k]) max_k = k; + } + + if(max_k != (uint32_t)-1) + { + vis[i<<1] = vis[(i<<1) + 1] = 1; + kv_push(uint64_t, p_refine, (((uint64_t)(max_k))<<32)|((uint64_t)(i))); + } + } + free(w); free(idx); free(sgv); + + for (i = 0; i < p_refine.n; i++) + { + p = &(sl->a[p_refine.a[i]>>32]); + // uid = (uint32_t)p_refine.a[i]; + } + + kv_destroy(p_refine); +} + +uint32_t get_max_anchor(horder_t *h, sc_lay_t *sl, uint8_t *vis, double *w, uint8_t *sgv, uint32_t *idx, +uint32_t *max_utg, uint32_t *max_sc) +{ + (*max_utg) = (*max_sc) = (uint32_t)-1; + double max_utg_w = -1; + uint32_t i, k, v, nv, max_k; + osg_arc_t *av = NULL; + for (i = 0; i < h->sg.g->n_seq; i++) + { + if(vis[i<<1]) continue; + if(!asg_arc_n(h->sg.g, i<<1)&&!asg_arc_n(h->sg.g, (i<<1)+1)) continue; + for (k = 0; k < sl->n; k++) w[k] = 0, sgv[k] = 0; + + v = i<<1; + nv = asg_arc_n(h->sg.g, v); + av = asg_arc_a(h->sg.g, v); + for (k = 0; k < nv; k++) + { + if(av[k].del || idx[av[k].v>>1] == (uint32_t)-1) continue; + w[idx[av[k].v>>1]] += av[k].nw; + sgv[idx[av[k].v>>1]] = 1; + } + + + v = (i<<1) + 1; + nv = asg_arc_n(h->sg.g, v); + av = asg_arc_a(h->sg.g, v); + for (k = 0; k < nv; k++) + { + if(av[k].del || idx[av[k].v>>1] == (uint32_t)-1) continue; + w[idx[av[k].v>>1]] += av[k].nw; + sgv[idx[av[k].v>>1]] = 1; + } + + for (k = 0, max_k = (uint32_t)-1; k < sl->n; k++) + { + if(!sgv[k]) continue; + if(max_k == (uint32_t)-1 || w[max_k] < w[k]) max_k = k; + } + + if(max_k != (uint32_t)-1) + { + if((*max_utg) == (uint32_t)-1 || max_utg_w < w[max_k]) + { + max_utg_w = w[max_k]; + (*max_utg) = i; + (*max_sc) = max_k; + } + } + } + + return (*max_utg) == (uint32_t)-1?0:1; +} + +osg_arc_t *get_osg_arc(osg_t *g, uint32_t u, uint32_t v) +{ + osg_arc_t *au = asg_arc_a(g, u); + uint32_t i, nu = asg_arc_n(g, u); + for (i = 0; i < nu; i++) + { + if(au[i].del) continue; + if(au[i].v == v) return &(au[i]); + } + + return NULL; +} + +void insert_sc(osg_t *g, lay_t *p, uint32_t uid) +{ + uint32_t i, b, e, vb, ve, max_i = (uint32_t)-1, is_found, ori, max_ori = (uint32_t)-1; + osg_arc_t *bE = NULL, *eE = NULL; + double w[2], s_w, max_w = -1; + for (i = 1; i+1 < p->n; i++)///middle points + { + b = p->a[i]; e = p->a[i+1]; w[0] = w[1] = 0; + s_w = 0; ori = 0; is_found = 0; + + vb = (uid<<1); ve = (uid<<1)+1; + bE = get_osg_arc(g, vb, b); + eE = get_osg_arc(g, ve, e); + if(bE || eE) ///different with slsa2 + { + if(bE) w[0] += bE->nw; + if(eE) w[0] += eE->nw; + is_found++; + } + + + vb = (uid<<1)+1; ve = (uid<<1); + bE = get_osg_arc(g, vb, b); + eE = get_osg_arc(g, ve, e); + if(bE || eE) ///different with slsa2 + { + if(bE) w[1] += bE->nw; + if(eE) w[1] += eE->nw; + is_found++; + } + + if(is_found > 0) + { + s_w = MAX(w[0], w[1]); + ori = ((w[0] >= w[1])? 0 : 1); + + if(max_i == (uint32_t)-1 || max_w < s_w) + { + max_w = s_w; + max_i = i; + max_ori = ori; + } + } + } + + + ///beg point, ///different with slsa2 + i = 0; + b = (uint32_t)-1; e = p->a[0]; w[0] = w[1] = 0; + s_w = 0; ori = 0; is_found = 0; + + vb = (uint32_t)-1; ve = (uid<<1)+1; + bE = NULL; + eE = get_osg_arc(g, ve, e); + if(bE || eE) ///different with slsa2 + { + if(bE) w[0] += bE->nw; + if(eE) w[0] += eE->nw; + is_found++; + } + + vb = (uint32_t)-1; ve = (uid<<1); + bE = NULL; + eE = get_osg_arc(g, ve, e); + if(bE || eE) ///different with slsa2 + { + if(bE) w[1] += bE->nw; + if(eE) w[1] += eE->nw; + is_found++; + } + + if(is_found > 0) + { + s_w = MAX(w[0], w[1]); + ori = ((w[0] >= w[1])? 0 : 1); + + if(max_i == (uint32_t)-1 || max_w < s_w) + { + max_w = s_w; + max_i = i; + max_ori = ori; + } + } + + ///end point, ///different with slsa2 + i = p->n - 1; + b = p->a[p->n - 1]; e = (uint32_t)-1; w[0] = w[1] = 0; + s_w = 0; ori = 0; is_found = 0; + + vb = (uid<<1); ve = (uint32_t)-1; + bE = get_osg_arc(g, vb, b); + eE = NULL; + if(bE || eE) ///different with slsa2 + { + if(bE) w[0] += bE->nw; + if(eE) w[0] += eE->nw; + is_found++; + } + + vb = (uid<<1)+1; ve = (uint32_t)-1; + bE = get_osg_arc(g, vb, b); + eE = NULL; + if(bE || eE) ///different with slsa2 + { + if(bE) w[1] += bE->nw; + if(eE) w[1] += eE->nw; + is_found++; + } + + if(is_found > 0) + { + s_w = MAX(w[0], w[1]); + ori = ((w[0] >= w[1])? 0 : 1); + + if(max_i == (uint32_t)-1 || max_w < s_w) + { + max_w = s_w; + max_i = i; + max_ori = ori; + } + } + + if(max_i != 0 && max_i != (uint32_t)-1) max_i++; + + i = p->n; + kv_resize(uint32_t, *p, p->n+2); + p->n += 2; + while (i > max_i) + { + i--; + p->a[i+2] = p->a[i]; + } + + p->a[max_i] = (uid<<1) + max_ori; + p->a[max_i+1] = (uid<<1) + 1 - max_ori; +} + + +uint32_t get_vis_occ(uint8_t *vis, uint32_t n) +{ + uint32_t i, occ; + n <<= 1; + for (i = occ = 0; i < n; i++) + { + if(vis[i]) occ++; + } + return occ; +} + +uint32_t get_sl_occ(sc_lay_t *sl) +{ + uint32_t i, occ; + for (i = occ = 0; i < sl->n; i++) + { + occ += sl->a[i].n; + } + return occ; +} + +void refine_layout(horder_t *h, sc_lay_t *sl, uint8_t *vis) +{ + uint32_t k/**m, max_utg, max_sc**/; + lay_t *p = NULL; + uint8_t *sgv = NULL; MALLOC(sgv, sl->n); + double *w = NULL; MALLOC(w, sl->n); + + /** + uint32_t *idx = NULL; MALLOC(idx, h->sg.g->n_seq); + memset(idx, -1, sizeof(uint32_t)*h->sg.g->n_seq); + + for (k = 0; k < sl->n; k++) + { + p = &(sl->a[k]); + for (m = 0; m < p->n; m++) + { + idx[p->a[m]>>1] = k; + } + } + while (get_max_anchor(h, sl, vis, w, sgv, idx, &max_utg, &max_sc)) + { + + insert_sc(h->sg.g, &(sl->a[max_sc]), max_utg); + + vis[max_utg<<1] = vis[(max_utg<<1)+1] = 1; + idx[max_utg] = max_sc; + } + free(idx); + **/ + + for (k = 0; k < h->sg.g->n_seq; k++) + { + if(vis[k<<1]) continue; + kv_pushp(lay_t, *sl, &p); + kv_init(*p); + kv_push(uint32_t, *p, (k<<1)); + kv_push(uint32_t, *p, (k<<1)+1); + vis[(k<<1)] = vis[(k<<1)+1] = 1; + } + + free(w); free(sgv); +} + + + +void generate_scaffold(ma_utg_t *su, lay_t *ly, ma_ug_t *pug, asg_t *rg) +{ + ma_utg_t *uu = NULL; + uint32_t i, k, r_i, uid, ori, nv, is_circle = 0; + uint64_t v, w, l, totalLen; + asg_arc_t *av = NULL; + memset(su, 0, sizeof(*su)); + for (i = 0; i < ly->n; i += 2) + { + ori = ly->a[i]&1; + uid = ly->a[i]>>1; + uu = &(pug->u.a[uid]); + is_circle = uu->circ; + for (r_i = 0; r_i < uu->n; r_i++) + { + v = (ori?uu->a[uu->n - r_i - 1]:uu->a[r_i]); + if(v != (uint64_t)-1 && ori) v ^= (uint64_t)(0x100000000); + kv_push(uint64_t, *su, v); + } + if(i < ly->n - 2) kv_push(uint64_t, *su, (uint64_t)-1); + } + if(ly->n != 2) is_circle = 0;///ly-> == 2: single circle + + for (i = 0, totalLen = 0; i < su->n-1; i++) + { + if(su->a[i] == (uint64_t)-1) + { + totalLen += GAP_LEN; + continue; + } + v = su->a[i]>>32; + if(su->a[i+1] == (uint64_t)-1) + { + l = rg->seq[v>>1].len; + } + else + { + w = su->a[i+1]>>32; + av = asg_arc_a(rg, v); + nv = asg_arc_n(rg, v); + + l = 0; + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + l = asg_arc_len(av[k]); + break; + } + } + if(k == nv) fprintf(stderr, "ERROR-scf-0, v-%lu, w-%lu\n", v, w); + } + + su->a[i] = v; su->a[i] = su->a[i]<<32; su->a[i] = su->a[i] | (uint64_t)(l); + totalLen += l; + } + if(i < su->n) + { + if(su->a[i] == (uint64_t)-1) + { + totalLen += GAP_LEN; + } + else + { + if(is_circle && su->a[0] != (uint64_t)-1) + { + v = su->a[i]>>32; + w = su->a[0]>>32; + av = asg_arc_a(rg, v); + nv = asg_arc_n(rg, v); + + l = 0; + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + l = asg_arc_len(av[k]); + break; + } + } + if(k == nv) fprintf(stderr, "ERROR-scf-1, v-%lu, w-%lu\n", v, w); + + su->a[i] = v; su->a[i] = su->a[i]<<32; su->a[i] = su->a[i] | (uint64_t)(l); + totalLen += l; + } + else + { + v = su->a[i]>>32; + l = rg->seq[v>>1].len; + su->a[i] = v; + su->a[i] = su->a[i]<<32; + su->a[i] = su->a[i] | (uint64_t)(l); + totalLen += l; + } + } + } + + su->circ = is_circle; + su->len = totalLen; + if(!su->circ) + { + su->start = su->a[0]>>32; + su->end = (su->a[su->n-1]>>32)^1; + } + else + { + su->start = su->end = UINT32_MAX; + } +} + +uint64_t get_nuid(sc_lay_t *sl, uint64_t *p) +{ + uint64_t k, ouid[2]; + for (k = 0; k < sl->n; k++) + { + ouid[0] = sl->a[k].a[0]; + ouid[1] = sl->a[k].a[sl->a[k].n - 1]; + if((*p) == ouid[0]) + { + (*p) = (k<<1); + return 1; + } + + if((*p) == ouid[1]) + { + (*p) = (k<<1)+1; + return 1; + } + } + + return 0; +} + +void update_avoids(horder_t *h, sc_lay_t *sl) +{ + uint64_t i, m, ps, pe; + for (i = m = 0; i < h->avoid.n; i++) + { + ps = h->avoid.a[i]>>32; + pe = (uint32_t)h->avoid.a[i]; + if(get_nuid(sl, &ps) && get_nuid(sl, &pe)) + { + h->avoid.a[m] = (ps<<32)|pe; + m++; + } + } + h->avoid.n = m; +} + +void update_ug_by_layout(horder_t *h, sc_lay_t *sl, ma_ug_t* i_ug) +{ + uint32_t i; + lay_t *p = NULL; + ma_utg_t *pu = NULL; + ma_ug_t *sug = NULL; + kvec_t_u64_warp n_avoids; kv_init(n_avoids.a); + sug = (ma_ug_t*)calloc(1, sizeof(ma_ug_t)); + for (i = 0; i < sl->n; i++) + { + p = &(sl->a[i]); + kv_pushp(ma_utg_t, sug->u, &pu); + generate_scaffold(pu, p, i_ug?i_ug:h->ug, h->r_g); + } + ma_ug_destroy(h->ug); + h->ug = sug; + kv_destroy(n_avoids.a); + update_avoids(h, sl); +} + +void get_long_switch_scaffolds(horder_t *h, sc_lay_t *sl, osg_t *lg) +{ + fprintf(stderr, "\n[M::%s::]\n", __func__); + uint32_t i, k, r_i, ori, sw[3], sw_inner[3]; + uint64_t v, len; + kvec_t(uint64_t) idx; kv_init(idx); + lay_t *p = NULL; + ma_utg_t *u = NULL; + for (i = 0; i < sl->n; i++) + { + p = &(sl->a[i]); + sw[0] = sw[1] = sw[2] = 0; + for (k = 0; k < p->n; k += 2) + { + u = &(h->ug->u.a[p->a[k]>>1]); + ori = p->a[k]&1; + for (r_i = 0; r_i < u->n; r_i++) + { + v = (ori?u->a[u->n - r_i - 1]:u->a[r_i]); + if(v != (uint64_t)-1) + { + v >>= 33; + sw[R_INF.trio_flag[v]]++; + } + } + } + + v = MIN(sw[FATHER], sw[MOTHER]); + v = ((uint32_t)-1) - v; + v <<= 32; v |= i; + kv_push(uint64_t, idx, v); + } + + radix_sort_ho64(idx.a, idx.a+idx.n); + for (i = 0; i < sl->n; i++) + { + p = &(sl->a[(uint32_t)(idx.a[i])]); + fprintf(stderr, "\nscaf-%u-th, occ-%u\n", (uint32_t)(idx.a[i]), (uint32_t)(p->n>>1)); + sw[0] = sw[1] = sw[2] = len = 0; + for (k = 0; k < p->n; k += 2) + { + sw_inner[0] = sw_inner[1] = sw_inner[2] = 0; + u = &(h->ug->u.a[p->a[k]>>1]); + ori = p->a[k]&1; + for (r_i = 0; r_i < u->n; r_i++) + { + v = (ori?u->a[u->n - r_i - 1]:u->a[r_i]); + if(v != (uint64_t)-1) + { + v >>= 33; + if(R_INF.trio_flag[v] == FATHER || R_INF.trio_flag[v] == MOTHER) + { + sw[R_INF.trio_flag[v]]++; + sw_inner[R_INF.trio_flag[v]]++; + } + } + } + fprintf(stderr, "utg%.6ul (ori: %u), u->len-%u, sw_in[FATHER]-%u, sw_in[MOTHER]-%u\n", + (p->a[k]>>1)+1, p->a[k]&1, u->len, sw_inner[FATHER], sw_inner[MOTHER]); + len += u->len + ((k + 2)< p->n? GAP_LEN:0); + } + fprintf(stderr, "sw[FATHER]-%u, sw[MOTHER]-%u, len-%lu\n", sw[FATHER], sw[MOTHER], len); + } + kv_destroy(idx); +} + +void destory_sc_lay_t(sc_lay_t *sl) +{ + uint32_t i; + for (i = 0; i < sl->n; i++) kv_destroy(sl->a[i]); + kv_destroy(*sl); +} + +void layout_scg(horder_t *h, double nw_thres, uint32_t occ_thres, sc_lay_t *r_sl) +{ + uint32_t k; + osg_arc_t *p = NULL, *lp = NULL; + uint8_t *vis = NULL; CALLOC(vis, h->sg.g->n_seq<<1); + sc_lay_t sl; kv_init(sl); + osg_t *lg = osg_init(); + qsort(h->sg.g->arc, h->sg.g->n_arc, sizeof(osg_arc_t), cmp_arc_nw); + for (k = 0; k < h->sg.g->n_arc; k++) + { + p = &(h->sg.g->arc[k]); + if(vis[p->u] || vis[p->v]) continue; + ///different with slsa2 + if(p->nw <= nw_thres || p->occ <= occ_thres) continue; + vis[p->u] = vis[p->v] = 1; + lp = osg_arc_pushp(lg); + (*lp) = (*p); + lp = osg_arc_pushp(lg); + (*lp) = (*p); + lp->u = p->v; + lp->v = p->u; + } + for (k = 0; k < h->sg.g->n_seq; k++) + { + osg_seq_set(lg, k, 0); + } + osg_cleanup(lg); + radix_sort_osg(h->sg.g->arc, h->sg.g->arc + h->sg.g->n_arc); + + get_backbone_layout(h, &sl, lg, vis); + + // get_long_switch_scaffolds(h, &sl, lg); + + refine_layout(h, &sl, vis); + + // print_N50_layout(h->ug, &sl); + + update_ug_by_layout(h, &sl, NULL); + + print_N50(h->ug); + + if(r_sl){ + r_sl->a = sl.a; sl.a = NULL; + r_sl->m = sl.m; sl.m = 0; + r_sl->n = sl.n; sl.n = 0; + + } + destory_sc_lay_t(&sl); + osg_destroy(lg); + free(vis); +} + +void renew_scaffold(horder_t *h) +{ + double index_time = yak_realtime(); + while (1) + { + update_u_hits(&(h->u_hits), &(h->r_hits), h->ug, h->r_g); + if(!break_scaffold(h, 5, 15, (uint64_t)-1, (uint64_t)-1, 2500000, 1, NULL)) break; + print_N50(h->ug); + } + fprintf(stderr, "[M::%s::%.3f] \n", __func__, yak_realtime()-index_time); +} + +void print_scaffold(ma_ug_t *ug, asg_t *sg, ma_sub_t* coverage_cut, char* output_file_name, +ma_hit_t_alloc* sources, ma_hit_t_alloc* reverse_sources, +long long tipsLen, float tip_drop_ratio, long long stops_threshold, R_to_U* ruIndex, +float chimeric_rate, float drop_ratio, int max_hang, int min_ovlp) +{ + char* gfa_name = (char*)malloc(strlen(output_file_name)+100); + sprintf(gfa_name, "%s.%s.p_ctg.gfa", output_file_name, "stg"); + fprintf(stderr, "Writing %s to disk... \n", gfa_name); + FILE* output_file = NULL; + output_file = fopen(gfa_name, "w"); + + + kvec_asg_arc_t_warp new_rtg_edges; + kv_init(new_rtg_edges.a); + ma_ug_seq_scaffold(ug, sg, coverage_cut, sources, &new_rtg_edges, max_hang, min_ovlp, 0, 1); + ma_ug_print(ug, sg, coverage_cut, sources, ruIndex, "stg", output_file); + fclose(output_file); + + sprintf(gfa_name, "%s.%s.p_ctg.noseq.gfa", output_file_name, "stg"); + output_file = fopen(gfa_name, "w"); + ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "stg", output_file); + fclose(output_file); + + free(gfa_name); + kv_destroy(new_rtg_edges.a); +} + +void scaffold_hap(horder_t *h, ug_opt_t *opt, trans_col_t *t_idx, uint32_t round, char *output_file_name, uint8_t flag) +{ + uint32_t i; + kv_destroy(h->u_hits.a); + kv_destroy(h->u_hits.idx); + kv_destroy(h->u_hits.occ); + memset(&(h->u_hits), 0, sizeof(h->u_hits)); + kv_destroy(h->avoid); + h->avoid.m = h->avoid.n = 0; + h->avoid.a = NULL; + osg_destroy(h->sg.g); + h->sg.g = NULL; + ma_ug_destroy(h->ug); + h->ug = NULL; + + h->ug = get_trio_unitig_graph(h->r_g, flag, opt); + asg_destroy(h->ug->g); + h->ug->g = NULL; + // kv_push(uint64_t, h->occ, h->ug->u.n); + // CALLOC(h->hf.a, h->ug->u.n); h->hf.n = h->hf.m = h->ug->u.n; + + print_N50(h->ug); + + for (i = 0; i < round; i++) + { + update_u_hits(&(h->u_hits), &(h->r_hits), h->ug, h->r_g); + update_scg(h, t_idx); + layout_scg(h, 1.001, 19, NULL); + renew_scaffold(h); + } + + char* gfa_name = (char*)malloc(strlen(output_file_name)+100); + sprintf(gfa_name, "%s.%s", output_file_name, (flag==FATHER?"hap1":"hap2")); + + print_scaffold(h->ug, h->r_g, opt->coverage_cut, gfa_name, + opt->sources, opt->reverse_sources, opt->tipsLen, opt->tip_drop_ratio, + opt->stops_threshold, opt->ruIndex, opt->chimeric_rate, opt->drop_ratio, + opt->max_hang, opt->min_ovlp); + + free(gfa_name); +} + +void scaffold_ug(horder_t *h, ma_ug_t *ug, ug_opt_t *opt, uint32_t round, char *output_file_name, uint8_t flag) +{ + uint32_t i; + kv_destroy(h->u_hits.a); + kv_destroy(h->u_hits.idx); + kv_destroy(h->u_hits.occ); + memset(&(h->u_hits), 0, sizeof(h->u_hits)); + kv_destroy(h->avoid); + h->avoid.m = h->avoid.n = 0; + h->avoid.a = NULL; + osg_destroy(h->sg.g); + h->sg.g = NULL; + + h->ug = ug; + asg_destroy(h->ug->g); + h->ug->g = NULL; + // kv_push(uint64_t, h->occ, h->ug->u.n); + // CALLOC(h->hf.a, h->ug->u.n); h->hf.n = h->hf.m = h->ug->u.n; + + print_N50(h->ug); + fprintf(stderr, "[M::%s::]***0***\n", __func__); + for (i = 0; i < round; i++) + { + fprintf(stderr, "[M::%s::]*i->%u*\n", __func__, i); + update_u_hits(&(h->u_hits), &(h->r_hits), h->ug, h->r_g); + fprintf(stderr, "[M::%s::]**i->%u**\n", __func__, i); + update_scg(h, NULL); + fprintf(stderr, "[M::%s::]***i->%u***\n", __func__, i); + layout_scg(h, 1.001, 19, NULL); + fprintf(stderr, "[M::%s::]****i->%u****\n", __func__, i); + renew_scaffold(h); + fprintf(stderr, "[M::%s::]*****i->%u*****\n", __func__, i); + } + + char* gfa_name = (char*)malloc(strlen(output_file_name)+100); + sprintf(gfa_name, "%s.%s", output_file_name, (flag==FATHER?"hap1":"hap2")); + + print_scaffold(h->ug, h->r_g, opt->coverage_cut, gfa_name, + opt->sources, opt->reverse_sources, opt->tipsLen, opt->tip_drop_ratio, + opt->stops_threshold, opt->ruIndex, opt->chimeric_rate, opt->drop_ratio, + opt->max_hang, opt->min_ovlp); + + free(gfa_name); +} + +void output_hic_rtg(ma_ug_t *ug, asg_t *rg, ug_opt_t *opt, char* output_file_name) +{ + char* gfa_name = (char*)malloc(strlen(output_file_name)+50); + sprintf(gfa_name, "%s.all.noseq.gfa", output_file_name); + FILE* output_file = fopen(gfa_name, "w"); + ma_ug_print_simple(ug, rg, opt->coverage_cut, opt->sources, opt->ruIndex, "utg", output_file); + fclose(output_file); + free(gfa_name); +} + +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, kv_u_trans_t *ref, ug_opt_t *opt, uint32_t round) +{ + uint32_t i; + trans_col_t *t_idx = NULL; + 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); + t_idx = init_trans_col(i_ug, h->r_g->n_seq, ref); + // output_hic_rtg(i_ug, h->r_g, opt, asm_opt.output_file_name); + + // reduce_hamming_error(h->r_g, opt->sources, opt->coverage_cut, opt->max_hang, opt->min_ovlp, opt->gap_fuzz); + reduce_hamming_error_adv(NULL, h->r_g, opt->sources, opt->coverage_cut, opt->max_hang, opt->min_ovlp, opt->gap_fuzz, opt->ruIndex, NULL, (asm_opt.max_short_tip*2)); + /** + scaffold_hap(h, t_idx, opt, round, asm_opt.output_file_name, FATHER); + scaffold_hap(h, t_idx, opt, round, asm_opt.output_file_name, MOTHER); + **/ + + + generate_haplotypes(h, opt); + print_N50(h->ug); + + // update_u_hits(&(h->u_hits), &(h->r_hits), h->ug, h->r_g); + // break_contig(h, 10, 20); + for (i = 0; i < round; i++) + { + update_u_hits(&(h->u_hits), &(h->r_hits), h->ug, h->r_g); + update_scg(h, t_idx); + layout_scg(h, 1.001, 19, NULL); + renew_scaffold(h); + } + + + print_scaffold(h->ug, h->r_g, opt->coverage_cut, asm_opt.output_file_name, + opt->sources, opt->reverse_sources, opt->tipsLen, opt->tip_drop_ratio, + opt->stops_threshold, opt->ruIndex, opt->chimeric_rate, opt->drop_ratio, + opt->max_hang, opt->min_ovlp); + + destory_trans_col(&t_idx); + exit(1); + return h; +} + +int cmp_mc_edge_t_w(const void * a, const void * b) +{ + if((*(mc_edge_t*)a).w == (*(mc_edge_t*)b).w) return 0; + return (*(mc_edge_t*)a).w < (*(mc_edge_t*)b).w ? -1 : 1; +} + +void cal_chain_arch(scg_t *sg, const mc_match_t *ma, uint32_t v, uint32_t *va, uint32_t vn, uint64_t *idx, asg64_v *srt) +{ + uint64_t z, n, j, t, w, o, l, k; double mw; osg_arc_t *p; + srt->n = 0; + for (z = 0; z < vn; z++) { + assert((v == (idx[va[z]]>>32)) || v == ((uint32_t)idx[va[z]])); + o = (ma->idx.a[va[z]]>>32); + n = (uint32_t)ma->idx.a[va[z]]; + for (j = 0; j < n; ++j) { + t = ((uint32_t)(ma->ma.a[o+j]).x); + + w = idx[t]>>32; + if((w != (uint32_t)-1) && ((w>>1) > (v>>1))) { + kv_push(uint64_t, (*srt), ((w<<32)|(o+j))); + } + + w = (uint32_t)idx[t]; + if((w != (uint32_t)-1) && ((w>>1) > (v>>1))) { + kv_push(uint64_t, (*srt), ((w<<32)|(o+j))); + } + } + } + + radix_sort_ho64(srt->a, srt->a + srt->n); + for (l = 0, k = 1; k <= srt->n; k++) { + if(k == srt->n || (srt->a[l]>>32) != (srt->a[k]>>32)) { + w = srt->a[l]>>32; mw = 0; + for (j = l; j < k; j++) { + t = ((uint32_t)(ma->ma.a[(uint32_t)srt->a[j]]).x); + assert((w == (idx[t]>>32)) || (w == ((uint32_t)idx[t]))); + mw += fabs(ma->ma.a[(uint32_t)srt->a[j]].w); + } + + p = osg_arc_pushp(sg->g); + p->occ = p->del = 0; + p->u = v; p->v = w; p->w = p->nw = mw; + + p = osg_arc_pushp(sg->g); + p->occ = p->del = 0; + p->u = w; p->v = v; p->w = p->nw = mw; + + l = k; + } + } +} + +void prt_scg_t_arc(scg_t *sg) +{ + uint64_t k; + for (k = 0; k < sg->g->n_arc; k++) { + fprintf(stderr, "[M::%s] k::%lu, v::%u, w::%u\n", __func__, k, sg->g->arc[k].u, sg->g->arc[k].v); + } +} + +uint64_t mc_clus_cut(scg_t *sg, mc_edge_t *sa, uint64_t sn, double cut_rate, uint64_t force_cut) +{ + uint64_t i, k, kv, kw, v, w, nv, nw, cnt = 0, m = sn; double mm_ol, ol_max; + osg_arc_t *av, *aw, *ve, *we; + for (k = 0; k < sn; k++) { + if(sa[k].x == ((uint64_t)-1)) { + cnt++; continue; + } + if(sg->g->arc[sa[k].x].del) { + sa[k].x = ((uint64_t)-1); cnt++; + continue; + } + + v = sg->g->arc[sa[k].x].u; + w = sg->g->arc[sa[k].x].v; + + nv = asg_arc_n(sg->g, v); nw = asg_arc_n(sg->g, w); + if(nv<=1 && nw <= 1) { + sa[k].x = ((uint64_t)-1); cnt++; + continue; + } + av = asg_arc_a(sg->g, v); aw = asg_arc_a(sg->g, w); + + ve = &(sg->g->arc[sa[k].x]); we = NULL; + for (i = 0; i < nw; ++i) { + if (aw[i].v == v) { + we = &(aw[i]); + break; + } + } + // if(!((!we) && (!(we->del)))) { + // fprintf(stderr, "[M::%s] sn::%lu, sg->g->n_arc::%u, sg->g->n_seq::%u, cut_rate::%f, v::%lu, w::%lu, x::%lu, v_beg::%lu, nv::%lu, w_beg::%lu, nw::%lu\n", __func__, + // sn, sg->g->n_arc, sg->g->n_seq, cut_rate, v, w, sa[k].x, + // (sg->g)->idx[(v)]>>32, nv, (sg->g)->idx[(w)]>>32, nw); + // prt_scg_t_arc(sg); + // } + assert((we) && (!(we->del))); + mm_ol = sg->g->arc[sa[k].x].nw; + + for (i = kv = ol_max = 0; i < nv; ++i) { + if(av[i].del) continue; + kv++; + if(ol_max < av[i].nw) ol_max = av[i].nw; + } + if (kv < 1) { + sa[k].x = ((uint64_t)-1); cnt++; + continue; + } + if (kv >= 2) { + if ((!force_cut) && (mm_ol > (ol_max*cut_rate))) continue; + } + + + for (i = kw = ol_max = 0; i < nw; ++i) { + if(aw[i].del) continue; + kw++; + if(ol_max < aw[i].nw) ol_max = aw[i].nw; + } + if (kw < 1) { + sa[k].x = ((uint64_t)-1); cnt++; + continue; + } + if (kw >= 2) { + if ((!force_cut) && (mm_ol > (ol_max*cut_rate))) continue; + } + + if (kv <= 1 && kw <= 1) { + sa[k].x = ((uint64_t)-1); cnt++; + continue; + } + + ve->del = we->del = 1; + sa[k].x = ((uint64_t)-1); cnt++; + } + + m = sn; + if(cnt) { + for (k = m = 0; k < sn; k++) { + if(sa[k].x == ((uint64_t)-1)) continue; + sa[m++] = sa[k]; + } + } + return m; +} + +void gen_mc_clus_backbone_layout(scg_t *sg, asg64_v *res, uint32_t *out, uint32_t out_n, uint32_t *buf) +{ + uint64_t k, l, i, rn, n0, n1, v, z; int64_t m, s, e; osg_arc_t *t = NULL; + kv_resize(uint64_t, *res, sg->g->n_seq); res->n = sg->g->n_seq; + memset(res->a, 0, sizeof((*(res->a)))*res->n); rn = res->n; + // fprintf(stderr, "[M::%s::]******Start******\n",__func__); + + for (k = 0; k < sg->g->n_seq; k++) { + ///I guess this should be (!!(asg_arc_n(lg, k<<1)))^(!!(asg_arc_n(lg, (k<<1)+1)))? + ///no, since asg_arc_n is at most 1 + n0 = asg_arc_n(sg->g, (k<<1)); + n1 = asg_arc_n(sg->g, ((k<<1)+1)); + assert((n0 <= 1) && (n1 <= 1)); + ///1&&0; 0&&0; 1&&1; + if((n0^n1) || ((!n0) && (!n1))) { + v = (n0?(k<<1):((k<<1)+1)); + // if(vis[k<<1] || vis[(k<<1)+1]) continue; + // if((res->a[k]>>32) || ((uint32_t)res->a[k])) continue; + if(res->a[k]) continue; + + // kv_pushp(lay_t, *sl, &p); + // kv_init(*p); + // kv_push(uint32_t, *p, v^1); + // kv_push(uint32_t, *p, v); + // vis[v] = vis[v^1] = 1; + // kv_push(uint64_t, *res, (((uint64_t)((v^1)<<32))|((uint64_t)(v))|((uint64_t)(0x8000000000000000)))); + kv_push(uint64_t, *res, (((uint64_t)((v^1)<<32))|((uint64_t)(v)))); + // res->a[v>>1] |= ((uint64_t)(1))<<32; + // res->a[v>>1] |= ((uint64_t)(1)); + res->a[v>>1] = 1; + + while (asg_arc_n(sg->g, v)) { + v = (arc_first(sg->g, v).v)^1; + // kv_push(uint32_t, *p, v^1); + // kv_push(uint32_t, *p, v); + // vis[v] = vis[v^1] = 1; + kv_push(uint64_t, *res, ((uint64_t)((v^1)<<32))|((uint64_t)(v))); + // res->a[v>>1] |= ((uint64_t)(1))<<32; + // res->a[v>>1] |= ((uint64_t)(1)); + res->a[v>>1] = 1; + } + } + } + + + for (k = 0; k < sg->g->n_seq; k++) { + // if(vis[k<<1] || vis[(k<<1)+1]) continue; + // if((res->a[k]>>32) || ((uint32_t)res->a[k])) continue; + if(res->a[k]) continue; + n0 = asg_arc_n(sg->g, (k<<1)); + n1 = asg_arc_n(sg->g, ((k<<1)+1)); + assert((n0 == 1) && (n1 == 1));///must within a circle + + + v = k<<1; t = NULL; + while (asg_arc_n(sg->g, v)) { + if((!t) || (t->nw > arc_first(sg->g, v).nw)) { + t = &(arc_first(sg->g, v)); + } + v = (arc_first(sg->g, v).v)^1; + if(v == (k<<1)) break; + } + + v = t->v^1; + // kv_pushp(lay_t, *sl, &p); + // kv_init(*p); + // kv_push(uint32_t, *p, v^1); + // kv_push(uint32_t, *p, v); + // vis[v] = vis[v^1] = 1; + // kv_push(uint64_t, *res, (((uint64_t)((v^1)<<32))|((uint64_t)(v))|((uint64_t)(0x8000000000000000)))); + kv_push(uint64_t, *res, ((uint64_t)((v^1)<<32))|((uint64_t)(v))); + // res->a[v>>1] |= ((uint64_t)(1))<<32; + // res->a[v>>1] |= ((uint64_t)(1)); + res->a[v>>1] = 1; + + while (1) { + v = (arc_first(sg->g, v).v)^1; + // if(vis[v]) break; + if(res->a[v>>1]) break; + // kv_push(uint32_t, *p, v^1); + // kv_push(uint32_t, *p, v); + // vis[v] = vis[v^1] = 1; + kv_push(uint64_t, *res, ((uint64_t)((v^1)<<32))|((uint64_t)(v))); + // res->a[v>>1] |= ((uint64_t)(1))<<32; + // res->a[v>>1] |= ((uint64_t)(1)); + res->a[v>>1] = 1; + } + } + + // uint32_t db_on = 0, db_z = 0; + assert((res->n-rn) == sg->g->n_seq); + for (l = 0, k = 1, i = 0; k <= out_n; k++) { + if(k == out_n || out[k] == (uint32_t)-1) { + if(k > l) { + res->a[i++] = ((l<<32)|(k)); ///db_on += k - l; + } else { + assert(k == out_n); + } + l = k + 1; + } + } + assert(i == sg->g->n_seq && i == rn); + for (k = rn, z = 0; k < res->n; k++) { + v = (res->a[k]>>32); + s = res->a[v>>1]>>32; e = (uint32_t)res->a[v>>1]; + if(!(v&1)) { + for (m = s; m < e; m++) buf[z++] = out[m]; + } else { + for (m = e-1; m >= s; m--) buf[z++] = out[m]; + } + + // if(e > s) { + // fprintf(stderr, "[M::%s::]\t#chain::%ld\tutg%.6ul->utg%.6ul\n", + // __func__, (e-s), buf[z-(e-s)]+1, buf[z-1]+1); + // } + + buf[z++] = (uint32_t)-1; + // db_z += e - s; + } + // if(!(z == out_n)) { + // fprintf(stderr, "[M::%s] sg->g->n_arc::%u, sg->g->n_seq::%u, z::%lu, out_n::%u, db_z::%u, db_on::%u\n", __func__, + // sg->g->n_arc, sg->g->n_seq, z, out_n, db_z, db_on); + // } + assert(z == out_n); + memcpy(out, buf, sizeof((*out))*out_n); +} + +void layout_mc_clus_t(const mc_match_t *ma, uint32_t *a, uint32_t an, scg_t *sg, uint32_t *buf, uint64_t *idx, ma_ug_t* ug, +double min_cut, double max_cut, uint64_t cut_round) +{ + uint64_t i, k, l, len, z, cutoff, s, e, v, vn; mc_edge_t *sp; + asg64_v srt; kv_init(srt); kvec_t(mc_edge_t) sm; kv_init(sm); + osg_destroy(sg->g); sg->g = osg_init(); + memset(idx, -1, sizeof((*idx))*ug->g->n_seq); + + // for (k = 0; k < an; k++) { + // fprintf(stderr, "[M::%s] k::%lu, a[k]::%u, an::%u\n", __func__, k, a[k], an); + // } + for (l = 0, k = 1, i = 0; k <= an; k++) { + if(k == an || a[k] == (uint32_t)-1) { + // fprintf(stderr, "[M::%s] l::%lu, k::%lu\n", __func__, l, k); + if(k > l) { + osg_seq_set(sg->g, i, 0); + for (z = l, len = 0; z < k; z++) len += ug->g->seq[a[z]].len; + cutoff = len >> 1; + for (z = l, len = 0; z < k; z++) { + s = len; len += ug->g->seq[a[z]].len; e = len; + if(s <= cutoff) { + idx[a[z]] <<= 32; idx[a[z]] |= (i<<1); + } + if(e >= cutoff) { + idx[a[z]] <<= 32; idx[a[z]] |= ((i<<1)+1); + } + } + i++; + } else { + assert(k == an); + } + l = k+1; + } + } + + for (l = 0, k = 1, i = 0; k <= an; k++) { + if(k == an || a[k] == (uint32_t)-1) { + if(k > l) { + for (z = l, v = (i<<1), vn = 0; z < k; z++) { + if((v == (idx[a[z]]>>32)) || v == ((uint32_t)idx[a[z]])) buf[vn++] = a[z]; + } + cal_chain_arch(sg, ma, v, buf, vn, idx, &srt); + + for (z = l, v = (i<<1)+1, vn = 0; z < k; z++) { + if((v == (idx[a[z]]>>32)) || v == ((uint32_t)idx[a[z]])) buf[vn++] = a[z]; + } + cal_chain_arch(sg, ma, v, buf, vn, idx, &srt); + + i++; + } else { + assert(k == an); + } + l = k + 1; + } + } + osg_cleanup(sg->g); + + sm.n = 0; + // kv_resize(mc_edge_t, sm, sg->g->n_arc); + for (k = 0; k < sg->g->n_arc; k++) { + if((asg_arc_n(sg->g, sg->g->arc[k].u)<=1) && (asg_arc_n(sg->g, sg->g->arc[k].v)<=1)) continue; + kv_pushp(mc_edge_t, sm, &sp); + sp->w = sg->g->arc[k].nw; sp->x = k; + } + // fprintf(stderr, "sm.n::%lu\n", (uint64_t)sm.n); + qsort(sm.a, sm.n, sizeof(mc_edge_t), cmp_mc_edge_t_w); + + + + double step = (cut_round==1?max_cut:((max_cut-min_cut)/(cut_round-1))); + double drop = min_cut; + + for (i = 0; i < cut_round; i++, drop += step) { + if(drop > max_cut) drop = max_cut; + sm.n = mc_clus_cut(sg, sm.a, sm.n, drop, 0); + } + mc_clus_cut(sg, sm.a, sm.n, 1.1, 1); + osg_cleanup(sg->g); + + gen_mc_clus_backbone_layout(sg, &srt, a, an, buf); + + + kv_destroy(srt); kv_destroy(sm); +} + +void cpy_u_hits(kvec_pe_hit *u_hits, kvec_pe_hit *i_hits, uint32_t u_n) +{ + uint64_t i; + memset(u_hits, 0, sizeof(kvec_pe_hit)); + u_hits->pos_mode = i_hits->pos_mode; + u_hits->uID_bits = i_hits->uID_bits; + u_hits->a.n = u_hits->a.m = i_hits->a.n; + MALLOC(u_hits->a.a, u_hits->a.n); + memcpy(u_hits->a.a, i_hits->a.a, u_hits->a.n*sizeof(pe_hit)); + for (i = 0; i < u_hits->a.n; i++) u_hits->a.a[i].id = 1; + idx_hits(u_hits, u_n); +} + +void update_sc_lay(sc_lay_t *sl, h_covs *b) +{ + uint64_t k, l, i, pidx, cidx; + lay_t *s = NULL; + lay_t *p = NULL; + for (k = 1, l = 0; k <= b->n; ++k) + { + if (k == b->n || (b->a[k].s != b->a[l].s)) + { + s = &(sl->a[b->a[l].s]); + for (i = l, pidx = 0; i < k; i++){ + cidx = b->a[i].dp; + kv_pushp(lay_t, *sl, &p); + kv_init(*p); + p->n = p->m = (cidx - pidx + 1)<<1; + MALLOC(p->a, p->n); + memcpy(p->a, s->a + (pidx<<1), sizeof(*(p->a))*p->n); + pidx = cidx + 1; + } + + if(pidx >= (s->n>>1)) fprintf(stderr, "ERROR-update\n"); + cidx = (s->n>>1)-1; + kv_pushp(lay_t, *sl, &p); + kv_init(*p); + p->n = p->m = (cidx - pidx + 1)<<1; + MALLOC(p->a, p->n); + memcpy(p->a, s->a + (pidx<<1), sizeof(*(p->a))*p->n); + free(s->a); s->n = s->m = 0; + l = k; + } + } + + for (i = k = 0; i < sl->n; i++){ + if(!sl->a[i].a) continue; + sl->a[k] = sl->a[i]; + sl->a[i].a = NULL; sl->a[i].n = sl->a[i].m = 0; + if(sl->a[k].n == 2){ + sl->a[k].a[0] >>= 1; sl->a[k].a[0] <<= 1; + sl->a[k].a[1] >>= 1; sl->a[k].a[1] <<= 1; sl->a[k].a[1]++; + } + k++; + } + sl->n = k; +} + +void renew_scaffold_utg(horder_t *h, sc_lay_t *sl, ma_ug_t* i_ug) +{ + double index_time = yak_realtime(); + h_covs b; kv_init(b); + while (1) + { + update_u_hits(&(h->u_hits), &(h->r_hits), h->ug, h->r_g); + if(!break_scaffold(h, 5, 15, 15, 25, 2500000, 1, &b)) break; + update_sc_lay(sl, &b); + update_ug_by_layout(h, sl, i_ug); + print_N50(h->ug); + } + fprintf(stderr, "[M::%s::%.3f] \n", __func__, yak_realtime()-index_time); + kv_destroy(b); +} + +spg_t *scf_g(sc_lay_t *sl, ma_ug_t* ug) +{ + spg_t *scg = NULL; CALLOC(scg, 1); scg->ug = ug; + uint64_t i, k; + lay_t *p = NULL; + for (i = 0; i < sl->n; i++){ + p = &(sl->a[i]); + kv_push(uint64_t, scg->idx, (uint64_t)scg->dst.n << 32 | (p->n>>1)); + for (k = 0; k < p->n; k+=2) kv_push(uint32_t, scg->dst, p->a[k]); + } + return scg; +} + +spg_t *horder_utg(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); + sc_lay_t sl; kv_init(sl); + 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);///udate rg by ug + h->ug = copy_untig_graph(i_ug); asg_destroy(h->ug->g); h->ug->g = NULL; + cpy_u_hits(&(h->u_hits), i_hits, h->ug->u.n); + + update_scg(h, NULL); + layout_scg(h, ((double)1)/((double)0.75), 19, &sl); + renew_scaffold_utg(h, &sl, i_ug); + + spg_t *scg = scf_g(&sl, i_ug); + destory_sc_lay_t(&sl); + destory_horder_t(&h); + return scg; +} + +void gen_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, m, 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 = m = 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 + if((!bub) || ((!IF_HOM(get_hit_suid(*r_hits, l), *bub)))) { + 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) { + 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); + r_hits->a.a[r_i].id = 1; r_hits->a.a[m++] = r_hits->a.a[r_i]; + + update++; + } + } + offset += (uint32_t)u->a[i]; + } + assert((r_i == k) && (update == (k-l))); + } + // if(r_i != k || update != k - l) fprintf(stderr, "ERROR-r_i\n"); + l = k; + } + } + r_hits->a.n = m; + + radix_sort_pe_hit_idx_hn2(r_hits->a.a, r_hits->a.a + r_hits->a.n); + for (k = 1, l = m = 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 + if((!bub) || ((!IF_HOM(get_hit_euid(*r_hits, l), *bub)))) { + 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) { + 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); + r_hits->a.a[r_i].id = 1; r_hits->a.a[m++] = r_hits->a.a[r_i]; + + update++; + } + } + offset += (uint32_t)u->a[i]; + } + assert((r_i == k) && (update == (k - l))); + } + // if(r_i != k || update != k - l) fprintf(stderr, "ERROR-r_i\n"); + l = k; + } + } + r_hits->a.n = m; + + r_hits->uID_bits = ubits; + r_hits->pos_mode = p_mode; + idx_hits(r_hits, r_g->n_seq); +} + +spg_t *horder_sensitive_utg(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); + sc_lay_t sl; kv_init(sl); + gen_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);///udate rg by ug + h->ug = copy_untig_graph(i_ug); asg_destroy(h->ug->g); h->ug->g = NULL; + cpy_u_hits(&(h->u_hits), i_hits, h->ug->u.n); + + update_scg(h, NULL); + layout_scg(h, ((double)1)/((double)0.75), 19, &sl); + renew_scaffold_utg(h, &sl, i_ug); + + spg_t *scg = scf_g(&sl, i_ug); + destory_sc_lay_t(&sl); + destory_horder_t(&h); + return scg; +} + + +void ha_aware_order(kvec_pe_hit *r_hits, asg_t *rg, ma_ug_t *ug_fa, ma_ug_t *ug_mo, kv_u_trans_t *ref, +ug_opt_t *opt, uint32_t round) +{ + horder_t *h = NULL; CALLOC(h, 1); + h->r_hits = *r_hits; + h->r_g = rg; + scaffold_ug(h, ug_fa, opt, round, asm_opt.output_file_name, FATHER); + scaffold_ug(h, ug_mo, opt, round, asm_opt.output_file_name, MOTHER); +} + +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)->avoid); + + osg_destroy((*h)->sg.g); + + ma_ug_destroy((*h)->ug); + asg_destroy((*h)->r_g); + free((*h)); +} + +kvec_pe_hit *get_r_hits_order(kvec_pe_hit *uhits, uint64_t hits_uid_bits, uint64_t hits_pos_mode, +asg_t *rg, ma_ug_t* ug, bubble_type* bub) +{ + kvec_pe_hit *r_hits = NULL; CALLOC(r_hits, 1); + get_r_hits(uhits, r_hits, rg, ug, bub, hits_uid_bits, hits_pos_mode); + return r_hits; } \ No newline at end of file diff --git a/horder.h b/horder.h index 246f7c2..17a1fca 100644 --- a/horder.h +++ b/horder.h @@ -1,79 +1,79 @@ -#ifndef __HORDER__ -#define __HORDER__ - -#define __STDC_LIMIT_MACROS -#include -#include "hic.h" -#include "rcut.h" - -#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)) - -typedef struct { - uint32_t v; - uint32_t u; - uint32_t occ:31, del:1; - double w, nw; -} osg_arc_t; - -typedef struct { - double mw[2], ez[2]; - uint8_t del; -} osg_seq_t; - -typedef struct { - uint32_t m_arc, n_arc:31, is_srt:1; - osg_arc_t *arc; - - uint32_t m_seq, n_seq:31, is_symm:1; - osg_seq_t *seq; - - uint64_t *idx; -} osg_t; - -typedef struct { - osg_t *g; -}scg_t; -typedef struct { - kvec_t(uint64_t) avoid; - // kvec_t(uint64_t) occ; - // kvec_t(uint8_t) hf; - kvec_pe_hit r_hits, u_hits; - ma_ug_t *ug; - asg_t *r_g; - scg_t sg; -}horder_t; - -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, kv_u_trans_t *ref, ug_opt_t *opt, uint32_t round); -void destory_horder_t(horder_t **h); -void horder_clean_sg_by_utg(asg_t *sg, ma_ug_t *ug); -kvec_pe_hit *get_r_hits_for_trio(kvec_pe_hit *u_hits, asg_t* r_g, ma_ug_t* ug, bubble_type* bub, uint64_t uID_bits, uint64_t pos_mode); -void update_switch_unitig(ma_ug_t *ug, asg_t *rg, kvec_pe_hit *hits, kv_u_trans_t *k_trans, uint64_t cutoff_s, uint64_t cutoff_e, -uint64_t min_ulen, double boundaryRate); -kvec_pe_hit *get_r_hits_order(kvec_pe_hit *uhits, uint64_t hits_uid_bits, uint64_t hits_pos_mode, -asg_t *rg, ma_ug_t* ug, bubble_type* bub); -void ha_aware_order(kvec_pe_hit *r_hits, asg_t *rg, ma_ug_t *ug_fa, ma_ug_t *ug_mo, kv_u_trans_t *ref, -ug_opt_t *opt, uint32_t round); -spg_t *horder_utg(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); -void layout_mc_clus_t(const mc_match_t *ma, uint32_t *a, uint32_t an, scg_t *sg, uint32_t *buf, uint64_t *idx, ma_ug_t* ug, -double min_cut, double max_cut, uint64_t cut_round); -void osg_destroy(osg_t *g); - -#endif +#ifndef __HORDER__ +#define __HORDER__ + +#define __STDC_LIMIT_MACROS +#include +#include "hic.h" +#include "rcut.h" + +#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)) + +typedef struct { + uint32_t v; + uint32_t u; + uint32_t occ:31, del:1; + double w, nw; +} osg_arc_t; + +typedef struct { + double mw[2], ez[2]; + uint8_t del; +} osg_seq_t; + +typedef struct { + uint32_t m_arc, n_arc:31, is_srt:1; + osg_arc_t *arc; + + uint32_t m_seq, n_seq:31, is_symm:1; + osg_seq_t *seq; + + uint64_t *idx; +} osg_t; + +typedef struct { + osg_t *g; +}scg_t; +typedef struct { + kvec_t(uint64_t) avoid; + // kvec_t(uint64_t) occ; + // kvec_t(uint8_t) hf; + kvec_pe_hit r_hits, u_hits; + ma_ug_t *ug; + asg_t *r_g; + scg_t sg; +}horder_t; + +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, kv_u_trans_t *ref, ug_opt_t *opt, uint32_t round); +void destory_horder_t(horder_t **h); +void horder_clean_sg_by_utg(asg_t *sg, ma_ug_t *ug); +kvec_pe_hit *get_r_hits_for_trio(kvec_pe_hit *u_hits, asg_t* r_g, ma_ug_t* ug, bubble_type* bub, uint64_t uID_bits, uint64_t pos_mode); +void update_switch_unitig(ma_ug_t *ug, asg_t *rg, kvec_pe_hit *hits, kv_u_trans_t *k_trans, uint64_t cutoff_s, uint64_t cutoff_e, +uint64_t min_ulen, double boundaryRate); +kvec_pe_hit *get_r_hits_order(kvec_pe_hit *uhits, uint64_t hits_uid_bits, uint64_t hits_pos_mode, +asg_t *rg, ma_ug_t* ug, bubble_type* bub); +void ha_aware_order(kvec_pe_hit *r_hits, asg_t *rg, ma_ug_t *ug_fa, ma_ug_t *ug_mo, kv_u_trans_t *ref, +ug_opt_t *opt, uint32_t round); +spg_t *horder_utg(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); +void layout_mc_clus_t(const mc_match_t *ma, uint32_t *a, uint32_t an, scg_t *sg, uint32_t *buf, uint64_t *idx, ma_ug_t* ug, +double min_cut, double max_cut, uint64_t cut_round); +void osg_destroy(osg_t *g); + +#endif diff --git a/htab.cpp b/htab.cpp index bd16ded..af9802b 100644 --- a/htab.cpp +++ b/htab.cpp @@ -1,1684 +1,1786 @@ -#include -#include -#include -#include -#include -#include "kthread.h" -#include "khashl.h" -#include "kseq.h" -#include "ksort.h" -#include "htab.h" -#include "Process_Read.h" - -#define YAK_COUNTER_BITS 12 -#define YAK_N_COUNTS (1<bf_shift = 0; - o->bf_n_hash = 4; - o->k = 31; - o->w = 1; - o->pre = YAK_COUNTER_BITS; - o->n_thread = 4; - o->chunk_size = 20000000; -} - -/************************ - * Blocked bloom filter * - ************************/ - -#define YAK_BLK_SHIFT 9 // 64 bytes, the size of a cache line -#define YAK_BLK_MASK ((1<<(YAK_BLK_SHIFT)) - 1) - -typedef struct { - int n_shift, n_hashes; - uint8_t *b; -} yak_bf_t; -///in most cases, n_shift = 25, n_hashes = 4 -yak_bf_t *yak_bf_init(int n_shift, int n_hashes) -{ - yak_bf_t *b; - void *ptr = 0; - if (n_shift + YAK_BLK_SHIFT > 64 || n_shift < YAK_BLK_SHIFT) return 0; - CALLOC(b, 1); - b->n_shift = n_shift; - b->n_hashes = n_hashes; - posix_memalign(&ptr, 1<<(YAK_BLK_SHIFT-3), 1ULL<<(n_shift-3)); - b->b = (uint8_t*)ptr; - bzero(b->b, 1ULL<<(n_shift-3)); - return b; -} - -void yak_bf_destroy(yak_bf_t *b) -{ - if (b == 0) return; - free(b->b); free(b); -} - -int yak_bf_insert(yak_bf_t *b, uint64_t hash) -{ - int x = b->n_shift - YAK_BLK_SHIFT; - uint64_t y = hash & ((1ULL<> x & YAK_BLK_MASK; - int h2 = hash >> b->n_shift & YAK_BLK_MASK; - uint8_t *p = &b->b[y<<(YAK_BLK_SHIFT-3)]; - int i, z = h1, cnt = 0; - if ((h2&31) == 0) h2 = (h2 + 1) & YAK_BLK_MASK; // otherwise we may repeatedly use a few bits - for (i = 0; i < b->n_hashes; z = (z + h2) & YAK_BLK_MASK) { - uint8_t *q = &p[z>>3], u; - u = 1<<(z&7); - cnt += !!(*q & u); - *q |= u; - ++i; - } - return cnt; -} - -/******************** - * Count hash table * - ********************/ - -#define yak_ct_eq(a, b) ((a)>>YAK_COUNTER_BITS == (b)>>YAK_COUNTER_BITS) // lower 8 bits for counts; higher bits for k-mer -#define yak_ct_hash(a) ((a)>>YAK_COUNTER_BITS) -KHASHL_SET_INIT(static klib_unused, yak_ct_t, yak_ct, uint64_t, yak_ct_hash, yak_ct_eq) - -typedef struct { - yak_ct_t *h; - yak_bf_t *b; -} ha_ct1_t; - -typedef struct { - int k, pre, n_hash, n_shift; - uint64_t tot; ///number of distinct k-mers - uint64_t bs; - ha_ct1_t *h; -} ha_ct_t; - -///for 0-th counting, k = 51, pre = 12, n_hash = 4, n_shift = 37 -///for 1-th counting, opt.k = 51, opt->pre = 12, opt->bf_n_hash = 4, opt.bf_shift = 0 -static ha_ct_t *ha_ct_init(int k, int pre, int n_hash, int n_shift) -{ - ha_ct_t *h; - int i; - if (pre < YAK_COUNTER_BITS) return 0; - CALLOC(h, 1); - h->k = k, h->pre = pre; - CALLOC(h->h, 1<pre); - ///ipre = 4096 - ///it seems there is a large hash table h, consisting 4096 small hash tables - for (i = 0; i < 1<pre; ++i) - h->h[i].h = yak_ct_init(); - ///for 0-th counting, enter here; used for bloom filter - if (n_hash > 0 && n_shift > h->pre) { - h->n_hash = n_hash, h->n_shift = n_shift; - for (i = 0; i < 1<pre; ++i) - h->h[i].b = yak_bf_init(h->n_shift - h->pre, h->n_hash); ///h->n_shift = 37, h->pre = 12, h->n_hash = 4 - } - return h; -} - -static void ha_ct_destroy_bf(ha_ct_t *h) -{ - int i; - for (i = 0; i < 1<pre; ++i) { - if (h->h[i].b) - yak_bf_destroy(h->h[i].b); - h->h[i].b = 0; - } -} - -static void ha_ct_destroy(ha_ct_t *h) -{ - int i; - if (h == 0) return; - ha_ct_destroy_bf(h); - for (i = 0; i < 1<pre; ++i) - yak_ct_destroy(h->h[i].h); - free(h->h); free(h); -} - -static int ha_ct_insert_list(ha_ct_t *h, int create_new, int n, const uint64_t *a) -{ - int j, mask = (1<pre) - 1, n_ins = 0; - ha_ct1_t *g; - if (n == 0) return 0; - ///corresponding small hash index - g = &h->h[a[0]&mask]; - for (j = 0; j < n; ++j) { - int ins = 1, absent; - ///x is a 64-bit word, h->pre=12 - ///all elements at a have the same low 12 bits - ///so low 12 bits are not useful - uint64_t x = a[j] >> h->pre; - khint_t k; - assert((a[j]&mask) == (a[0]&mask)); - if (create_new) { - if (g->b) - ins = (yak_bf_insert(g->b, x) == h->n_hash); - ///x = the high 52 bits of a[j] + low 12 bits 0 - ///the low 12 bits are used for counting - if (ins) { - k = yak_ct_put(g->h, x << YAK_COUNTER_BITS | (g->b? 1 : 0), &absent); - if (absent) ++n_ins; - if ((kh_key(g->h, k)&YAK_MAX_COUNT) < YAK_MAX_COUNT) - ++kh_key(g->h, k); - } - } else { - k = yak_ct_get(g->h, x<h) && (kh_key(g->h, k)&YAK_MAX_COUNT) < YAK_MAX_COUNT) - ++kh_key(g->h, k); - } - } - return n_ins; -} - -/*** generate histogram ***/ - -typedef struct { - uint64_t c[YAK_N_COUNTS]; -} buf_cnt_t; - -typedef struct { - const ha_ct_t *h; - buf_cnt_t *cnt; -} hist_aux_t; - -static void worker_ct_hist(void *data, long i, int tid) // callback for kt_for() -{ - hist_aux_t *a = (hist_aux_t*)data; - uint64_t *cnt = a->cnt[tid].c; - yak_ct_t *g = a->h->h[i].h; - khint_t k; - for (k = 0; k < kh_end(g); ++k) - if (kh_exist(g, k)) - ++cnt[kh_key(g, k)&YAK_MAX_COUNT]; -} - -///YAK_N_COUNTS is also 4096 -///used for calculating k-mer histogram -static void ha_ct_hist(const ha_ct_t *h, int64_t cnt[YAK_N_COUNTS], int n_thread) -{ - hist_aux_t a; - int i, j; - a.h = h; - memset(cnt, 0, YAK_N_COUNTS * sizeof(uint64_t)); - CALLOC(a.cnt, n_thread); - ///start 4096 threads - kt_for(n_thread, worker_ct_hist, &a, 1<pre); - for (i = 0; i < YAK_N_COUNTS; ++i) cnt[i] = 0; - for (j = 0; j < n_thread; ++j) - for (i = 0; i < YAK_N_COUNTS; ++i) - cnt[i] += a.cnt[j].c[i]; - free(a.cnt); -} - -/*** shrink a hash table ***/ - -typedef struct { - int min, max; - ha_ct_t *h; -} shrink_aux_t; - -static void worker_ct_shrink(void *data, long i, int tid) // callback for kt_for() -{ - shrink_aux_t *a = (shrink_aux_t*)data; - ha_ct_t *h = a->h; - yak_ct_t *g = h->h[i].h, *f; - khint_t k; - f = yak_ct_init(); - yak_ct_resize(f, kh_size(g)); - for (k = 0; k < kh_end(g); ++k) { - if (kh_exist(g, k)) { - int absent, c = kh_key(g, k) & YAK_MAX_COUNT; - if (c >= a->min && c <= a->max) - yak_ct_put(f, kh_key(g, k), &absent); - } - } - yak_ct_destroy(g); - h->h[i].h = f; -} - -static void ha_ct_shrink(ha_ct_t *h, int min, int max, int n_thread) -{ - int i; - shrink_aux_t a; - a.h = h, a.min = min, a.max = max; - ///still start 4096 threads - kt_for(n_thread, worker_ct_shrink, &a, 1<pre); - for (i = 0, h->tot = 0; i < 1<pre; ++i) - h->tot += kh_size(h->h[i].h); - fprintf(stderr, "[M::%s::%.3f*%.2f] ==> counted %ld distinct minimizer k-mers\n", __func__, - yak_realtime(), yak_cpu_usage(), (long)h->tot); -} - -/*********************** - * Position hash table * - ***********************/ - -KHASHL_MAP_INIT(static klib_unused, yak_pt_t, yak_pt, uint64_t, uint64_t, yak_ct_hash, yak_ct_eq) -#define generic_key(x) (x) -KRADIX_SORT_INIT(ha64, uint64_t, generic_key, 8) - -typedef struct { - yak_pt_t *h; - uint64_t n; - ha_idxpos_t *a; - ha_idxposl_t *al; -} ha_pt1_t; - -struct ha_pt_s { - int k, pre; - uint64_t tot, tot_pos; - ha_pt1_t *h; -}; - -typedef struct { - const ha_ct_t *ct; - ha_pt_t *pt; - int is_l; -} pt_gen_aux_t; - - -static void worker_pt_shrink(void *data, long i, int tid) // callback for kt_for() -{ - ha_pt_t *h = (ha_pt_t*)data; - ha_pt1_t *b = &h->h[i]; - yak_pt_t *f = NULL; - khint_t k; - f = yak_pt_init(); - for (k = 0, b->n = 0; k < kh_end(b->h); ++k) { - if (kh_exist(b->h, k)) { - if(kh_val(b->h, k) <= 0) continue; - int absent; khint_t l; - l = yak_pt_put(f, (kh_key(b->h, k) >> h->pre) << YAK_COUNTER_BITS, &absent); - kh_val(f, l) = b->n; - b->n += kh_key(b->h, k) & YAK_MAX_COUNT; - } - } - yak_pt_destroy(b->h); - h->h[i].h = f; - CALLOC(b->a, b->n);///need fix -} - -static uint64_t ha_pt_shrink(ha_pt_t *h, int n_thread) -{ - int i; - uint64_t occ; - ///still start 4096 threads - kt_for(n_thread, worker_pt_shrink, h, 1<pre); - for (i = 0, occ = 0, h->tot = 0; i < 1<pre; ++i) - { - h->tot += kh_size(h->h[i].h); - occ += h->h[i].n; - } - return occ; -} - -static void worker_pt_gen(void *data, long i, int tid) // callback for kt_for() -{ - pt_gen_aux_t *a = (pt_gen_aux_t*)data; - ha_pt1_t *b = &a->pt->h[i]; - yak_ct_t *g = a->ct->h[i].h; - khint_t k; - for (k = 0, b->n = 0; k != kh_end(g); ++k) { - if (kh_exist(g, k)) { - int absent; - khint_t l; - l = yak_pt_put(b->h, kh_key(g, k) >> a->ct->pre << YAK_COUNTER_BITS, &absent); - ///this should be the start index of kh_key's corresponding pos at ha_idxpos_t* a - kh_val(b->h, l) = b->n; - b->n += kh_key(g, k) & YAK_MAX_COUNT; - } - } - yak_ct_destroy(g); - a->ct->h[i].h = 0; - if(a->is_l) CALLOC(b->al, b->n); - else CALLOC(b->a, b->n); -} - -ha_pt_t *ha_pt_gen(ha_ct_t *ct, int n_thread, int is_l) -{ - pt_gen_aux_t a; - int i; - ha_pt_t *pt; - ha_ct_destroy_bf(ct); - CALLOC(pt, 1); - pt->k = ct->k, pt->pre = ct->pre, pt->tot = ct->tot; - CALLOC(pt->h, 1<pre); - for (i = 0; i < 1<pre; ++i) { - pt->h[i].h = yak_pt_init(); - yak_pt_resize(pt->h[i].h, kh_size(ct->h[i].h)); - } - a.ct = ct, a.pt = pt, a.is_l = is_l; - kt_for(n_thread, worker_pt_gen, &a, 1<pre); - free(ct->h); free(ct); - return pt; -} - -static void worker_pt_gen_count(void *data, long i, int tid) // callback for kt_for() -{ - pt_gen_aux_t *a = (pt_gen_aux_t*)data; - ha_pt1_t *b = &a->pt->h[i]; - yak_ct_t *g = a->ct->h[i].h; - khint_t k; - for (k = 0, b->n = 0; k != kh_end(g); ++k) { - if (kh_exist(g, k)) { - int absent; - khint_t l; - l = yak_pt_put(b->h, kh_key(g, k) >> a->ct->pre << YAK_COUNTER_BITS, &absent); - kh_val(b->h, l) = 0; kh_key(b->h, l) |= kh_key(g, k) & YAK_MAX_COUNT; - } - } - yak_ct_destroy(g); - a->ct->h[i].h = 0; -} - -ha_pt_t *ha_pt_gen_count(ha_ct_t *ct, int n_thread) -{ - pt_gen_aux_t a; - int i; - ha_pt_t *pt; - ha_ct_destroy_bf(ct); - CALLOC(pt, 1); - pt->k = ct->k, pt->pre = ct->pre, pt->tot = ct->tot; - CALLOC(pt->h, 1<pre); - for (i = 0; i < 1<pre; ++i) { - pt->h[i].h = yak_pt_init(); - yak_pt_resize(pt->h[i].h, kh_size(ct->h[i].h)); - } - a.ct = ct, a.pt = pt; - kt_for(n_thread, worker_pt_gen_count, &a, 1<pre); - free(ct->h); free(ct); - return pt; -} - - -int ha_pt_insert_list(ha_pt_t *h, int n, const ha_mz1_t *a) -{ - int j, mask = (1<pre) - 1, n_ins = 0; - ha_pt1_t *g; - if (n == 0) return 0; - g = &h->h[a[0].x&mask]; - for (j = 0; j < n; ++j) { - uint64_t x = a[j].x >> h->pre; - khint_t k; - int n; - ha_idxpos_t *p; - assert((a[j].x&mask) == (a[0].x&mask)); - k = yak_pt_get(g->h, x<h)) continue; // TODO: understand why we sometimes come here - n = kh_key(g->h, k) & YAK_MAX_COUNT; - assert(n < YAK_MAX_COUNT); - p = &g->a[kh_val(g->h, k) + n]; - p->rid = a[j].rid, p->rev = a[j].rev, p->pos = a[j].pos, p->span = a[j].span; - //(uint64_t)a[j].rid<<36 | (uint64_t)a[j].rev<<35 | (uint64_t)a[j].pos<<8 | (uint64_t)a[j].span; - ++kh_key(g->h, k); - ++n_ins; - } - return n_ins; -} - - -int ha_pt_cnt_insert_list(ha_pt_t *h, int n, const uint64_t *a) -{ - int j, mask = (1<pre) - 1, n_ins = 0; - ha_pt1_t *g; - if (n == 0) return 0; - g = &h->h[a[0]&mask]; - for (j = 0; j < n; ++j) { - uint64_t x = a[j] >> h->pre; - khint_t k; - assert((a[j]&mask) == (a[0]&mask)); - k = yak_pt_get(g->h, x<h)) continue; // TODO: understand why we sometimes come here - ++kh_val(g->h, k); - ++n_ins; - } - // fprintf(stderr, "n: %d, n_ins: %d\n", n, n_ins); - return n_ins; -} -/* -static void worker_pt_sort(void *data, long i, int tid) -{ - ha_pt_t *h = (ha_pt_t*)data; - ha_pt1_t *g = &h->h[i]; - khint_t k; - for (k = 0; k < kh_end(g->h); ++k) { - int n; - uint64_t *p; - if (!kh_exist(g->h, k)) continue; - n = kh_key(g->h, k) & YAK_MAX_COUNT; - p = &g->a[kh_val(g->h, k)]; - radix_sort_ha64(p, p + n); - } -} - -void ha_pt_sort(ha_pt_t *h, int n_thread) -{ - kt_for(n_thread, worker_pt_sort, h, 1<pre); -} -*/ -void ha_pt_destroy(ha_pt_t *h) -{ - int i; - if (h == 0) return; - for (i = 0; i < 1<pre; ++i) { - yak_pt_destroy(h->h[i].h); - if(h->h[i].a){ - free(h->h[i].a); h->h[i].a = NULL; - } - if(h->h[i].al){ - free(h->h[i].al); h->h[i].al = NULL; - } - } - free(h->h); free(h); -} - -const ha_idxpos_t *ha_pt_get(const ha_pt_t *h, uint64_t hash, int *n) -{ - khint_t k; - const ha_pt1_t *g = &h->h[hash & ((1ULL<pre) - 1)]; - *n = 0; - k = yak_pt_get(g->h, hash >> h->pre << YAK_COUNTER_BITS); - if (k == kh_end(g->h)) return 0; - *n = kh_key(g->h, k) & YAK_MAX_COUNT; - return &g->a[kh_val(g->h, k)]; -} - -const ha_idxposl_t *ha_ptl_get(const ha_pt_t *h, uint64_t hash, int *n) -{ - khint_t k; - const ha_pt1_t *g = &h->h[hash & ((1ULL<pre) - 1)]; - *n = 0; - k = yak_pt_get(g->h, hash >> h->pre << YAK_COUNTER_BITS); - if (k == kh_end(g->h)) return 0; - *n = kh_key(g->h, k) & YAK_MAX_COUNT; - return &g->al[kh_val(g->h, k)]; -} - -const int ha_pt_cnt(const ha_pt_t *h, uint64_t hash) -{ - khint_t k; - const ha_pt1_t *g = &h->h[hash & ((1ULL<pre) - 1)]; - k = yak_pt_get(g->h, hash >> h->pre << YAK_COUNTER_BITS); - if (k == kh_end(g->h)) return 0; - return kh_key(g->h, k) & YAK_MAX_COUNT; -} - -inline uint64_t flt_quals(char *sc_a, uint64_t sc_l, uint64_t sc_off, int64_t sc_cut) -{ - int64_t sc_min = sc_l * sc_cut, sc_tot; uint64_t k; - for (k = sc_tot = 0; (k < sc_l) && (sc_tot < sc_min); k++) { - sc_tot += (((uint8_t)sc_a[k]) - sc_off); - } - - // if(sc_tot < sc_min) { - // fprintf(stderr, "[M::%s] sc_tot::%ld, sc_min::%ld, sc_l::%lu\n", __func__, sc_tot, sc_min, sc_l); - // } - - if(sc_tot < sc_min) return 0; - return 1; -} - -/********************************** - * Buffer for counting all k-mers * - **********************************/ -KSEQ_INIT(gzFile, gzread) -#define HAF_COUNT_EXACT 0x1 -#define HAF_COUNT_ALL 0x2 -#define HAF_RS_WRITE_LEN 0x4 -#define HAF_RS_WRITE_SEQ 0x8 -#define HAF_RS_READ 0x10 -#define HAF_CREATE_NEW 0x20 -#define HAF_SKIP_READ 0x40 -#define HAF_UG_READ 0x80 -#define HAF_COUNT_REFINE 0x100 - -typedef struct { // global data structure for kt_pipeline() - const yak_copt_t *opt; - const void *flt_tab; - int flag, create_new, is_store, uq; - uint64_t n_mz, n_seq; ///number of total reads - kseq_t *ks; - UC_Read ucr; - ha_ct_t *ct; - ha_pt_t *pt; - const All_reads *rs_in; - All_reads *rs_out; - const ma_utg_v *us_in; -} pl_data_t; - -#define MZ_TEST_INIT(sf, HType, VType, IType, Ia) \ -typedef struct {int n, m; uint64_t n_ins; uint64_t *a; HType *b;} sf##_ch_buf_t;\ -static inline void sf##_ct_insert_buf(sf##_ch_buf_t *buf, int p, uint64_t y) /** insert a k-mer $y to a linear buffer**/\ -{\ - /**assign k-mer to one of the 4096 bins**/\ - /**using low 12 bits for assigning**/\ - /**so all elements at b have the same low 12 bits**/\ - int pre = y & ((1<n == b->m) {\ - b->m = b->m < 8? 8 : b->m + (b->m>>1);\ - REALLOC(b->a, b->m);\ - }\ - b->a[b->n++] = y;\ -}\ -/**buf is the read block, k is the k-mer length, p = 12, len is the read length, seq is the read**/\ -static void sf##_count_seq_buf(sf##_ch_buf_t *buf, int k, int p, int len, const char *seq) /**insert k-mers in $seq to linear buffer $buf**/\ -{\ - int i, l;\ - uint64_t x[4], mask = (1ULL<>1)) & mask;\ - x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift;\ - x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift;\ - if (++l >= k)\ - sf##_ct_insert_buf(buf, p, yak_hash_long(x));\ - } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; /** if there is an "N", restart**/\ - }\ -}\ -static void sf##_count_seq_buf_HPC(sf##_ch_buf_t *buf, int k, int p, int len, const char *seq) /**insert k-mers in $seq to linear buffer $buf**/\ -{\ - int i, l, last = -1;\ - uint64_t x[4], mask = (1ULL<>1)) & mask;\ - x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift;\ - x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift;\ - if (++l >= k)\ - sf##_ct_insert_buf(buf, p, yak_hash_long(x));\ - last = c;\ - }\ - } else l = 0, last = -1, x[0] = x[1] = x[2] = x[3] = 0; /**if there is an "N", restart**/\ - }\ -}\ -int sf##_ha_pt_insert_list(ha_pt_t *h, int n, const HType *a)\ -{\ - int j, mask = (1<pre) - 1, n_ins = 0;\ - ha_pt1_t *g;\ - if (n == 0) return 0;\ - g = &h->h[a[0].x&mask];\ - /**fprintf(stderr, "a[0].x&mask: %lu, a[0].x&mask: %lu, n: %d\n", a[0].x&mask, a[0].x, n);**/\ - for (j = 0; j < n; ++j) {\ - uint64_t x = a[j].x >> h->pre;\ - khint_t k;\ - int n;\ - IType *p;\ - assert((a[j].x&mask) == (a[0].x&mask));\ - k = yak_pt_get(g->h, x<h)) continue; \ - n = kh_key(g->h, k) & YAK_MAX_COUNT;\ - /**fprintf(stderr, "j: %d, n: %d\n", j, n);**/\ - assert(n < YAK_MAX_COUNT);\ - p = &g->Ia[kh_val(g->h, k) + n];\ - p->rid = a[j].rid, p->rev = a[j].rev, p->pos = a[j].pos, p->span = a[j].span;\ - /**(uint64_t)a[j].rid<<36 | (uint64_t)a[j].rev<<35 | (uint64_t)a[j].pos<<8 | (uint64_t)a[j].span;**/\ - ++kh_key(g->h, k);\ - ++n_ins;\ - }\ - return n_ins;\ -}\ -/** data structure for each step in kt_pipeline()**/\ -typedef struct {pl_data_t *p;uint64_t n_seq0; int n_seq, m_seq, sum_len, nk, uq, *len; char **seq; VType *mz_buf; VType *mz;sf##_ch_buf_t *buf;st_mt_t *mt;} sf##_st_data_t;\ -static void sf##_worker_for_insert(void *data, long i, int tid) /** callback for kt_for()**/\ -{\ - sf##_st_data_t *s = (sf##_st_data_t*)data;\ - sf##_ch_buf_t *b = &s->buf[i];\ - if (s->p->pt){\ - if(s->p->flag&HAF_COUNT_REFINE) b->n_ins += ha_pt_cnt_insert_list(s->p->pt, b->n, b->a);\ - else b->n_ins += sf##_ha_pt_insert_list(s->p->pt, b->n, b->b);\ - }else{\ - b->n_ins += ha_ct_insert_list(s->p->ct, s->p->create_new, b->n, b->a);\ - }\ -}\ -static void sf##_worker_for_mz(void *data, long i, int tid)\ -{\ - sf##_st_data_t *s = (sf##_st_data_t*)data;\ - /**get the corresponding minimzer vector of this read**/\ - VType *b = &s->mz_buf[tid];\ - s->mz_buf[tid].n = 0;\ - sf##_ha_sketch(s->seq[i], s->len[i], s->p->opt->w, s->p->opt->k, s->n_seq0 + i, s->p->opt->is_HPC, b, s->p->flt_tab, asm_opt.mz_sample_dist, 0, 0, \ - (s->p->pt&&(s->p->flag&HAF_COUNT_REFINE))?s->p->pt:NULL, s->p->opt->min_rcnt, asm_opt.dp_min_len, asm_opt.dp_e, &(s->mt[tid]), asm_opt.mz_rewin, s->uq, NULL);\ - s->mz[i].n = s->mz[i].m = b->n;\ - MALLOC(s->mz[i].a, b->n);\ - MEMCPY(s->mz[i].a, b->a, b->n);\ -}\ -static inline void sf##_pt_insert_buf(sf##_ch_buf_t *buf, int p, const HType *y){\ - /**assign minimizer to one of 4096 bins by low 12 bits**/\ - int pre = y->x & ((1<n == b->m) {\ - b->m = b->m < 8? 8 : b->m + (b->m>>1);\ - REALLOC(b->b, b->m);\ - }\ - b->b[b->n++] = *y;\ -}\ -static void *sf##_worker_count(void *data, int step, void *in) /** callback for kt_pipeline()**/\ -{\ - pl_data_t *p = (pl_data_t*)data;\ - /**uint8_t src_a[1000000], des_a[1000000];**/\ - if (step == 0) { /** step 1: read a block of sequences**/\ - int ret;\ - sf##_st_data_t *s;\ - CALLOC(s, 1);\ - s->p = p;\ - s->n_seq0 = p->n_seq;\ - s->uq = p->opt->uq;\ - if (p->rs_in && (p->flag & HAF_RS_READ)) {\ - while (p->n_seq < p->rs_in->total_reads) {\ - if ((p->flag & HAF_SKIP_READ) && p->rs_in->trio_flag[p->n_seq] != AMBIGU) {\ - ++p->n_seq;\ - continue;\ - }\ - int l;\ - recover_UC_Read(&p->ucr, p->rs_in, p->n_seq);\ - l = p->ucr.length;\ - if (s->n_seq == s->m_seq) {\ - s->m_seq = s->m_seq < 16? 16 : s->m_seq + (s->m_seq>>1);\ - REALLOC(s->len, s->m_seq);\ - REALLOC(s->seq, s->m_seq);\ - }\ - MALLOC(s->seq[s->n_seq], l);\ - memcpy(s->seq[s->n_seq], p->ucr.seq, l);\ - s->len[s->n_seq++] = l;\ - ++p->n_seq;\ - s->sum_len += l;\ - s->nk += l >= p->opt->k? l - p->opt->k + 1 : 0;\ - if (s->sum_len >= p->opt->chunk_size)\ - break;\ - }\ - } else if(p->us_in) {\ - ma_utg_t *u;\ - while (p->n_seq < p->us_in->n) {\ - u = &(p->us_in->a[p->n_seq]);\ - if (s->n_seq == s->m_seq) {\ - s->m_seq = s->m_seq < 16? 16 : s->m_seq + (s->m_seq>>1);\ - REALLOC(s->len, s->m_seq);\ - REALLOC(s->seq, s->m_seq);\ - }\ - MALLOC(s->seq[s->n_seq], u->len);\ - if(u->s) memcpy(s->seq[s->n_seq], u->s, u->len);\ - else retrieve_u_seq(NULL, s->seq[s->n_seq], u, 0, 0, -1, NULL);\ - s->len[s->n_seq++] = u->len;\ - ++p->n_seq;\ - s->sum_len += u->len;\ - s->nk += u->len >= p->opt->k? u->len - p->opt->k + 1 : 0;\ - if (s->sum_len >= p->opt->chunk_size)\ - break;\ - }\ - } else {\ - while ((ret = kseq_read(p->ks)) >= 0) {\ - int l = (int)(p->ks->seq.l) - (int)(p->opt->adaLen) - (int)(p->opt->adaLen);\ - if((l <= 0) || (l < asm_opt.rl_cut)) continue;\ - if((asm_opt.is_sc) && (asm_opt.sc_cut > 0) && (!flt_quals(p->ks->qual.s+p->opt->adaLen, l, 33, asm_opt.sc_cut))) continue;\ - if (p->n_seq >= 1<<28) {\ - fprintf(stderr, "ERROR: this implementation supports no more than %d reads\n", 1<<28);\ - exit(1);\ - }\ - if (p->rs_out) {\ - /**for 0-th count, just insert read length to R_INF, instead of read**/\ - if (p->flag & HAF_RS_WRITE_LEN) {\ - assert(p->n_seq == p->rs_out->total_reads);\ - ha_insert_read_len(p->rs_out, l, p->ks->name.l);\ - } else if (p->flag & HAF_RS_WRITE_SEQ) {\ - int i, n_N;\ - assert(l == (int)p->rs_out->read_length[p->n_seq]);\ - for (i = n_N = 0; i < l; ++i) /** count number of ambiguous bases**/\ - if (seq_nt4_table[(uint8_t)p->ks->seq.s[i+p->opt->adaLen]] >= 4)\ - ++n_N;\ - ha_compress_base(Get_READ(*p->rs_out, p->n_seq), p->ks->seq.s+p->opt->adaLen, l, &p->rs_out->N_site[p->n_seq], n_N);\ - memcpy(&p->rs_out->name[p->rs_out->name_index[p->n_seq]], p->ks->name.s, p->ks->name.l);\ - if(p->rs_out->rsc) {\ - ha_compress_qual(Get_QUAL(*p->rs_out, p->n_seq), p->ks->qual.s+p->opt->adaLen, l, sc_bn, 33);\ - /**print_fastq(NULL, p->ks->name.s, p->ks->seq.s, p->ks->qual.s, (1<ks->qual.s+p->opt->adaLen, l, (1<n_seq, -1, -1, 0, sc_bn);\ - if(memcmp(src_a, des_a, l)!=0) fprintf(stderr, "ERROR: incorrect qual values\n");\ - else fprintf(stderr, "Correct: correct qual values\n");\ - }**/\ - }\ - }\ - }\ - if (s->n_seq == s->m_seq) {\ - s->m_seq = s->m_seq < 16? 16 : s->m_seq + (s->m_seq>>1);\ - REALLOC(s->len, s->m_seq);\ - REALLOC(s->seq, s->m_seq);\ - }\ - MALLOC(s->seq[s->n_seq], l);\ - memcpy(s->seq[s->n_seq], p->ks->seq.s+p->opt->adaLen, l);\ - s->len[s->n_seq++] = l;\ - ++p->n_seq;\ - s->sum_len += l;\ - s->nk += l >= p->opt->k? l - p->opt->k + 1 : 0;\ - /**p->opt->chunk_size is the block max size**/\ - if (s->sum_len >= p->opt->chunk_size)\ - break;\ - }\ - }\ - if (s->sum_len == 0) free(s);\ - else return s;\ - } else if (step == 1) { /** step 2: extract k-mers**/\ - /**s is the block of reads**/\ - sf##_st_data_t *s = (sf##_st_data_t*)in;\ - int i, n_pre = 1<opt->pre, m;\ - /**allocate the k-mer buffer**/\ - CALLOC(s->buf, n_pre);\ - m = (int)(s->nk * 1.2 / n_pre) + 1;\ - /**pre-allocate memory for each of 4096 buffer**/\ - for (i = 0; i < n_pre; ++i) {\ - s->buf[i].m = m;\ - /**for 0-th counting, p->pt = NULL**/\ - if (p->pt && !(p->flag&HAF_COUNT_REFINE)) MALLOC(s->buf[i].b, m);\ - else MALLOC(s->buf[i].a, m);\ - }\ - if (p->opt->w == 1) { /** enumerate all k-mers**/\ - int i;\ - for (i = 0; i < s->n_seq; ++i) {\ - if (p->opt->is_HPC)\ - sf##_count_seq_buf_HPC(s->buf, p->opt->k, p->opt->pre, s->len[i], s->seq[i]);\ - else\ - sf##_count_seq_buf(s->buf, p->opt->k, p->opt->pre, s->len[i], s->seq[i]);\ - if (!p->is_store) free(s->seq[i]);\ - }\ - } else { /** minimizers only**/\ - uint32_t j;\ - /**s->n_seq is how many reads at this buffer**/\ - /**s->mz && s->mz_buf are lists of minimzer vectors**/\ - CALLOC(s->mz, s->n_seq), CALLOC(s->mz_buf, p->opt->n_thread), CALLOC(s->mt, p->opt->n_thread);\ - /**calculate minimzers for each read, each read corresponds to one thread**/\ - kt_for(p->opt->n_thread, sf##_worker_for_mz, s, s->n_seq);\ - for (i = 0; i < p->opt->n_thread; ++i) free(s->mt[i].a), free(s->mz_buf[i].a);\ - free(s->mt), free(s->mz_buf);\ - /**insert minimizers**/\ - if (p->pt && !(p->flag&HAF_COUNT_REFINE)) {/**insert whole minimizer**/\ - for (i = 0; i < s->n_seq; ++i)\ - for (j = 0; j < s->mz[i].n; ++j)\ - sf##_pt_insert_buf(s->buf, p->opt->pre, &s->mz[i].a[j]);\ - } else {/**just insert the hash key of minimizer**/\ - for (i = 0; i < s->n_seq; ++i)\ - for (j = 0; j < s->mz[i].n; ++j)\ - sf##_ct_insert_buf(s->buf, p->opt->pre, s->mz[i].a[j].x);\ - }\ - for (i = 0; i < s->n_seq; ++i) {\ - p->n_mz += s->mz[i].n;\ - free(s->mz[i].a);\ - if (!p->is_store) free(s->seq[i]);\ - }\ - free(s->mz);\ - }\ - /**just clean seq**/\ - free(s->seq); free(s->len);\ - s->seq = 0, s->len = 0;\ - return s;\ - } else if (step == 2) { /** step 3: insert k-mers to hash table**/\ - sf##_st_data_t *s = (sf##_st_data_t*)in;\ - int i, n = 1<opt->pre;uint64_t n_ins = 0;\ - /**for 0-th counting, p->pt = NULL**/\ - kt_for(p->opt->n_thread, sf##_worker_for_insert, s, n);\ - /**n_ins is number of distinct k-mers**/\ - for (i = 0; i < n; ++i) {\ - n_ins += s->buf[i].n_ins;\ - if (p->pt && !(p->flag&HAF_COUNT_REFINE)) free(s->buf[i].b);\ - else free(s->buf[i].a);\ - }\ - if (p->ct) p->ct->tot += n_ins, p->ct->bs += s->sum_len;\ - if (p->pt) p->pt->tot_pos += n_ins;\ - free(s->buf);\ - free(s);\ - }\ - return 0;\ -} - -MZ_TEST_INIT(mz1, ha_mz1_t, ha_mz1_v, ha_idxpos_t, a) -MZ_TEST_INIT(mz2, ha_mzl_t, ha_mzl_v, ha_idxposl_t, al) - - -void debug_adapter(const hifiasm_opt_t *asm_opt, All_reads *rs) -{ - int ret; - uint32_t i, m, pass, unpass; - gzFile fp = 0; - kseq_t *ks = NULL; - UC_Read ucr; - init_UC_Read(&ucr); - - for (i = m = pass = unpass = 0; i < (uint32_t)asm_opt->num_reads; ++i) - { - if ((fp = gzopen(asm_opt->read_file_names[i], "r")) == 0) continue; - ks = kseq_init(fp); - while ((ret = kseq_read(ks)) >= 0) - { - int l = ks->seq.l; - if((l - asm_opt->adapterLen*2) <= 0) continue; - recover_UC_Read(&ucr, rs, m); - fprintf(stderr, "l: %d, ucr.length: %lld, asm_opt->adapterLen: %d\n", - l, ucr.length, asm_opt->adapterLen); - if(memcmp(ucr.seq, ks->seq.s+asm_opt->adapterLen, ucr.length) == 0) - { - pass++; - } - else - { - unpass++; - } - m++; - } - kseq_destroy(ks); - gzclose(fp); - ks = NULL; - fp = 0; - } - - destory_UC_Read(&ucr); - - fprintf(stderr, "[M::%s::# reads: %u, # pass: %u, # unpass: %u\n]", __func__, m, pass, unpass); - exit(1); -} - -static ha_ct_t *yak_count(const yak_copt_t *opt, const char *fn, int flag, ha_pt_t *p0, ha_ct_t *c0, const void *flt_tab, All_reads *rs, ma_utg_v *us, int64_t *n_seq) -{ - ///for 0-th counting, flag = HAF_COUNT_ALL|HAF_RS_WRITE_LEN|HAF_CREATE_NEW - int read_rs = (rs && (flag & HAF_RS_READ)); - int ug_rs = (us && (flag & HAF_UG_READ)); - pl_data_t pl; - gzFile fp = 0; - memset(&pl, 0, sizeof(pl_data_t)); - pl.n_seq = *n_seq; - if(ug_rs) { - pl.us_in = us; - } else if (read_rs) { - pl.rs_in = rs; - init_UC_Read(&pl.ucr); - } else {///for 0-th counting, go into here - if ((fp = gzopen(fn, "r")) == 0) return 0; - pl.ks = kseq_init(fp); - } - ///for 0-th counting, read all reads into pl.rs_out - if (rs && (flag & (HAF_RS_WRITE_LEN|HAF_RS_WRITE_SEQ))) - pl.rs_out = rs; - ///for 0-th counting, flt_tab = NULL - ///for 1-th counting, flt_tab = NULL - pl.flt_tab = flt_tab; - pl.opt = opt; - pl.flag = flag; - if (p0) {///for 1-th counting, p0 = NULL - pl.pt = p0, pl.create_new = 0; // never create new elements in a position table - assert(p0->k == opt->k && p0->pre == opt->pre); - } else if (c0) { - pl.ct = c0, pl.create_new = !!(flag&HAF_CREATE_NEW); - assert(c0->k == opt->k && c0->pre == opt->pre); - } else {///for ft-th counting and 1-th counting, go into here - pl.create_new = 1; // alware create new elements if the count table is empty - ///for 0-th counting, opt.k = 51, opt->pre = 12, opt->bf_n_hash = 4, opt.bf_shift = 37 - ///for 1-th counting, opt.k = 51, opt->pre = 12, opt->bf_n_hash = 4, opt.bf_shift = 0 - ///building a large hash table consisting of 4096 small hash tables - pl.ct = ha_ct_init(opt->k, opt->pre, opt->bf_n_hash, opt->bf_shift); - } - if(pl.ct) pl.ct->bs = 0; - if(ug_rs) kt_pipeline(3, mz2_worker_count, &pl, 3); - else kt_pipeline(3, mz1_worker_count, &pl, 3); - if (read_rs) { - destory_UC_Read(&pl.ucr); - } else if(!read_rs && !ug_rs) { - kseq_destroy(pl.ks); - gzclose(fp); - } - *n_seq = pl.n_seq; - if (pl.opt->w > 1) fprintf(stderr, "[M::%s] collected %ld minimizers\n", __func__, (long)pl.n_mz); - return pl.ct; -} - -ha_ct_t *ha_count(const hifiasm_opt_t *asm_o, int flag, int HPC, int k, int w, ha_pt_t *p0, const void *flt_tab, All_reads *rs, ma_utg_v *us, int keep_adapter, int *low_freq, int unique_only) -{ - int i; - int64_t n_seq = 0; - uint64_t n_bs = 0; - yak_copt_t opt; - ha_ct_t *h = 0; - assert(!(flag & HAF_RS_WRITE_LEN) || !(flag & HAF_RS_WRITE_SEQ)); // not both - ///for 0-th counting, flag = HAF_COUNT_ALL|HAF_RS_WRITE_LEN - if (rs) { - if (flag & HAF_RS_WRITE_LEN) - init_All_reads(rs); - else if (flag & HAF_RS_WRITE_SEQ) - malloc_All_reads(rs); - } - yak_copt_init(&opt); - opt.k = k; - opt.is_HPC = HPC; - ///for ft-counting, shoud be 1 - opt.w = flag & HAF_COUNT_ALL? 1 : w; - ///for ft-counting, shoud be 37 - ///for ha_pt_gen, shoud be 0 - opt.bf_shift = flag & HAF_COUNT_EXACT? 0 : asm_o->bf_shift; - opt.n_thread = asm_o->thread_num; - opt.adaLen = (keep_adapter? asm_o->adapterLen : 0); - opt.min_rcnt = (low_freq?*low_freq:-1); - opt.uq = (unique_only?1:0); - - n_bs = 0; - ///pending for integration - /** - if(rs && asm_o->ar && asm_o->ul_mod) { - for (i = 0; i < asm_o->ar->n; ++i){ - h = yak_count(&opt, asm_o->ar->a[i], flag|HAF_CREATE_NEW, p0, h, flt_tab, rs, us, &n_seq); - if(h) n_bs += h->bs; - } - }**/ - ///asm_opt->num_reads is the number of fastq files - for (i = 0; i < (us?1:asm_o->num_reads); ++i){ - h = yak_count(&opt, asm_o->read_file_names[i], flag|HAF_CREATE_NEW, p0, h, flt_tab, rs, us, &n_seq); - if(h) n_bs += h->bs; - } - if(h) h->bs = n_bs; - if (h && opt.bf_shift > 0) - ha_ct_destroy_bf(h); - return h; -} - -/*************************** - * High count filter table * - ***************************/ - -// Warning: the max count is 32767 -KHASHL_MAP_INIT(static klib_unused, yak_ft_t, yak_ft, uint64_t, int16_t, kh_hash_dummy, kh_eq_generic) - -static yak_ft_t *gen_hh(const ha_ct_t *h, int max_cnt) -{ - int i; - yak_ft_t *hh; - if (max_cnt > YAK_MAX_COUNT - 1) max_cnt = YAK_MAX_COUNT - 1; - if (max_cnt > INT16_MAX - 1) max_cnt = INT16_MAX - 1; - hh = yak_ft_init(); - yak_ft_resize(hh, h->tot * 2); - for (i = 0; i < 1<pre; ++i) { - yak_ct_t *ht = h->h[i].h; - khint_t k, l; - for (k = 0; k < kh_end(ht); ++k) { - if (kh_exist(ht, k)) { - uint64_t y = kh_key(ht, k) >> h->pre << YAK_COUNTER_BITS | i; - int absent; - l = yak_ft_put(hh, y, &absent); - if (absent) { - int cnt = kh_key(ht, k) & YAK_MAX_COUNT; - kh_val(hh, l) = cnt > max_cnt? INT16_MAX : cnt; - } - } - } - } - return hh; -} - -int32_t ha_ft_cnt(const void *hh, uint64_t y) -{ - yak_ft_t *h = (yak_ft_t*)hh; - khint_t k; - k = yak_ft_get(h, y); - return k == kh_end(h)? 0 : kh_val(h, k) == INT16_MAX? INT32_MAX : kh_val(h, k); -} - -void ha_ft_destroy(void *h) -{ - if (h) yak_ft_destroy((yak_ft_t*)h); -} - - -void debug_ct_index(void* q_ct_idx, void* r_ct_idx) -{ - ha_ct_t* ct_idx = (ha_ct_t*)q_ct_idx; - yak_ct_t *g = NULL; - uint64_t i; - khint_t k; - for (i = 0; (int)i < 1<pre; i++) - { - g = ct_idx->h[i].h; - for (k = 0; k < kh_end(g); ++k) - { - if (kh_exist(g, k)) - { - int c = kh_key(g, k) & YAK_MAX_COUNT; - uint64_t hash = ((kh_key(g, k) >> ct_idx->pre)<pre) | i; - int q = query_ct_index(r_ct_idx, hash); - if(q!=c) - { - fprintf(stderr, "ERROR:c: %d, q: %d\n", c, q); - } - } - } - } -} - -/************************* - * High-level interfaces * - *************************/ -void *ha_ft_ul_gen(const hifiasm_opt_t *asm_opt, ma_utg_v *us, int k, int w, int cutoff) -{ - yak_ft_t *flt_tab; - ha_ct_t *h; - ///HAF_COUNT_EXACT ---> no bf; HAF_COUNT_ALL ---> no minimizer - h = ha_count(asm_opt, HAF_COUNT_ALL|HAF_UG_READ, !(asm_opt->flag&HA_F_NO_HPC), k, w, NULL, NULL, NULL, us, 0, NULL, 0); - - // cutoff = (int)(asm_opt->hom_cov * asm_opt->high_factor); - if (cutoff > YAK_MAX_COUNT - 1) cutoff = YAK_MAX_COUNT - 1; - // fprintf(stderr, "[M::%s::] cutoff->%d\n\n", __func__, cutoff); - ha_ct_shrink(h, cutoff, YAK_MAX_COUNT, asm_opt->thread_num); - flt_tab = gen_hh(h, asm_opt->max_kmer_cnt); - ha_ct_destroy(h); - fprintf(stderr, "[M::%s::%.3f*%.2f@%.3fGB] ==> filtered out %ld k-mers occurring %d or more times\n", __func__, - yak_realtime(), yak_cpu_usage(), yak_peakrss_in_gb(), (long)kh_size(flt_tab), cutoff); - return (void*)flt_tab; -} - -void *ha_ft_ug_gen(const hifiasm_opt_t *asm_opt, ma_utg_v *us, int is_HPC, int k, int w, int min_freq, int max_freq) -{ - yak_ft_t *flt_tab; - ha_ct_t *h; - ///HAF_COUNT_EXACT ---> no bf; HAF_COUNT_ALL ---> no minimizer - h = ha_count(asm_opt, HAF_COUNT_ALL|HAF_UG_READ|HAF_COUNT_EXACT, is_HPC, k, w, NULL, NULL, NULL, us, 0, NULL, 0); - ha_ct_shrink(h, min_freq, max_freq>YAK_MAX_COUNT-1?YAK_MAX_COUNT-1:max_freq, asm_opt->thread_num); - flt_tab = gen_hh(h, YAK_MAX_COUNT); - ha_ct_destroy(h); - return (void*)flt_tab; -} - -void *ha_ft_gen(const hifiasm_opt_t *asm_opt, All_reads *rs, int *hom_cov, int is_hp_mode, int read_from_store) -{ - yak_ft_t *flt_tab; - int64_t cnt[YAK_N_COUNTS]; - int peak_hom, peak_het, cutoff = YAK_MAX_COUNT - 1, ex_flag = 0; - if(is_hp_mode) ex_flag = HAF_RS_READ|HAF_SKIP_READ; - ha_ct_t *h; - h = ha_count(asm_opt, HAF_COUNT_ALL|ex_flag|((read_from_store)?(HAF_RS_READ):(HAF_RS_WRITE_LEN)), !(asm_opt->flag&HA_F_NO_HPC), asm_opt->k_mer_length, asm_opt->mz_win, NULL, NULL, rs, NULL, 1, NULL, 0); - if((asm_opt->flag & HA_F_VERBOSE_GFA)) - { - write_ct_index((void*)h, asm_opt->output_file_name); - // load_ct_index(&ha_ct_table, asm_opt->output_file_name); - // debug_ct_index((void*)h, ha_ct_table); - // debug_ct_index(ha_ct_table, (void*)h); - // ha_ct_destroy((ha_ct_t *)ha_ct_table); - } - - if(!(ex_flag & HAF_SKIP_READ)) - { - ha_ct_hist(h, cnt, asm_opt->thread_num); - peak_hom = ha_analyze_count(YAK_N_COUNTS, asm_opt->min_hist_kmer_cnt, asm_opt->hg_size>0?(h->bs/asm_opt->hg_size):(-1), cnt, &peak_het); - if (hom_cov) *hom_cov = peak_hom; - if (peak_hom > 0) fprintf(stderr, "[M::%s] peak_hom: %d; peak_het: %d\n", __func__, peak_hom, peak_het); - ///in default, asm_opt->high_factor = 5.0 - cutoff = (int)(peak_hom * asm_opt->high_factor); - if (cutoff > YAK_MAX_COUNT - 1) cutoff = YAK_MAX_COUNT - 1; - } - ha_ct_shrink(h, cutoff, YAK_MAX_COUNT, asm_opt->thread_num); - flt_tab = gen_hh(h, asm_opt->max_kmer_cnt); - ha_ct_destroy(h); - fprintf(stderr, "[M::%s::%.3f*%.2f@%.3fGB] ==> filtered out %ld k-mers occurring %d or more times\n", __func__, - yak_realtime(), yak_cpu_usage(), yak_peakrss_in_gb(), (long)kh_size(flt_tab), cutoff); - return (void*)flt_tab; -} - -ha_pt_t *ha_pt_ul_gen(const hifiasm_opt_t *asm_opt, const void *flt_tab, ma_utg_v *us, int k, int w, int cutoff) -{ - ha_ct_t *ct; - ha_pt_t *pt; - ///HAF_COUNT_EXACT: no bf - ct = ha_count(asm_opt, HAF_COUNT_EXACT|HAF_UG_READ, !(asm_opt->flag&HA_F_NO_HPC), k, w, NULL, flt_tab, NULL, us, 0, NULL, 0); - fprintf(stderr, "[M::%s::%.3f*%.2f] ==> counted %ld distinct minimizer k-mers\n", __func__, - yak_realtime(), yak_cpu_usage(), (long)ct->tot); - ///minimizer with YAK_MAX_COUNT occ may apper > YAK_MAX_COUNT times, so it may lead to overflow at ha_pt_gen - if (flt_tab == 0) { - if (cutoff > YAK_MAX_COUNT - 1) cutoff = YAK_MAX_COUNT - 1; - ha_ct_shrink(ct, /**2**/1, cutoff, asm_opt->thread_num); - } else { - ///Note: here is just to remove minimizer appearing YAK_MAX_COUNT times - ///minimizer with YAK_MAX_COUNT occ may apper > YAK_MAX_COUNT times, so it may lead to overflow at ha_pt_gen - ha_ct_shrink(ct, /**2**/1, YAK_MAX_COUNT - 1, asm_opt->thread_num); - } - - pt = ha_pt_gen(ct, asm_opt->thread_num, 1); - ha_count(asm_opt, HAF_COUNT_EXACT|HAF_UG_READ, !(asm_opt->flag&HA_F_NO_HPC), k, w, pt, flt_tab, NULL, us, 0, NULL, 0); - //ha_pt_sort(pt, asm_opt->thread_num); - fprintf(stderr, "[M::%s::%.3f*%.2f] ==> indexed %ld positions\n", __func__, - yak_realtime(), yak_cpu_usage(), (long)pt->tot_pos); - return pt; -} - -ha_pt_t *ha_pt_ug_gen(const hifiasm_opt_t *asm_opt, const void *flt_tab, ma_utg_v *us, int is_HPC, int k, int w, int min_freq) -{ - ha_ct_t *ct; - ha_pt_t *pt; - ///HAF_COUNT_EXACT: no bf - ct = ha_count(asm_opt, HAF_COUNT_EXACT|HAF_UG_READ, is_HPC, k, w, NULL, flt_tab, NULL, us, 0, NULL, 1); - fprintf(stderr, "[M::%s::%.3f*%.2f] ==> counted %ld distinct minimizer k-mers\n", __func__, - yak_realtime(), yak_cpu_usage(), (long)ct->tot); - ///minimizer with YAK_MAX_COUNT occ may apper > YAK_MAX_COUNT times, so it may lead to overflow at ha_pt_gen - ha_ct_shrink(ct, min_freq, YAK_MAX_COUNT - 1, asm_opt->thread_num); - - pt = ha_pt_gen(ct, asm_opt->thread_num, 1); - ha_count(asm_opt, HAF_COUNT_EXACT|HAF_UG_READ, is_HPC, k, w, pt, flt_tab, NULL, us, 0, NULL, 1); - //ha_pt_sort(pt, asm_opt->thread_num); - fprintf(stderr, "[M::%s::%.3f*%.2f] ==> indexed %ld positions\n", __func__, - yak_realtime(), yak_cpu_usage(), (long)pt->tot_pos); - return pt; -} - -ha_pt_t *ha_pt_gen_dp(const hifiasm_opt_t *asm_opt, ha_ct_t *ct, int flag, int n_thread, const void *flt_tab, All_reads *rs, int peak_hom, int peak_het) -{ - int low_freq = mz_low_b(peak_hom, peak_het); - ha_pt_t *pt = ha_pt_gen_count(ct, n_thread); ///key = cnt, val = 0 - ha_count(asm_opt, HAF_COUNT_EXACT|HAF_COUNT_REFINE|flag, !(asm_opt->flag&HA_F_NO_HPC), asm_opt->k_mer_length, asm_opt->mz_win, pt, flt_tab, rs, NULL, 1, &low_freq, 0); - uint64_t occ = ha_pt_shrink(pt, n_thread); - if(flag&HAF_RS_WRITE_LEN) flag -= HAF_RS_WRITE_LEN; - if(flag&HAF_RS_WRITE_SEQ) flag -= HAF_RS_WRITE_SEQ; - flag |= HAF_RS_READ; pt->tot_pos = 0; - ha_count(asm_opt, HAF_COUNT_EXACT|flag, !(asm_opt->flag&HA_F_NO_HPC), asm_opt->k_mer_length, asm_opt->mz_win, pt, flt_tab, rs, NULL, 1, NULL, 0); - // fprintf(stderr, "[M::%s::] counted %lu distinct minimizer k-mers\n", __func__, pt->tot); - // fprintf(stderr, "[M::%s::] collected %lu minimizers\n\n\n", __func__, pt->tot_pos); - assert(occ == pt->tot_pos); - return pt; -} - -ha_pt_t *ha_pt_gen(const hifiasm_opt_t *asm_opt, const void *flt_tab, int read_from_store, int is_hp_mode, All_reads *rs, int *hom_cov, int *het_cov) -{ - int64_t cnt[YAK_N_COUNTS], tot_cnt; - int peak_hom, peak_het, i, extra_flag1, extra_flag2; - ha_ct_t *ct; - ha_pt_t *pt; - if (read_from_store) {///if reads have already been read - extra_flag1 = extra_flag2 = HAF_RS_READ; - } else if (rs->total_reads == 0) {///if reads & length have not been scanned - extra_flag1 = HAF_RS_WRITE_LEN; - extra_flag2 = HAF_RS_WRITE_SEQ; - } else {///if length has been loaded but reads have not - extra_flag1 = HAF_RS_WRITE_SEQ; - extra_flag2 = HAF_RS_READ; - } - if(is_hp_mode) extra_flag1 |= HAF_SKIP_READ, extra_flag2 |= HAF_SKIP_READ; - - ct = ha_count(asm_opt, HAF_COUNT_EXACT|extra_flag1, !(asm_opt->flag&HA_F_NO_HPC), asm_opt->k_mer_length, asm_opt->mz_win, NULL, flt_tab, rs, NULL, 1, NULL, 0); - fprintf(stderr, "[M::%s::%.3f*%.2f] ==> counted %ld distinct minimizer k-mers\n", __func__, - yak_realtime(), yak_cpu_usage(), (long)ct->tot); - ha_ct_hist(ct, cnt, asm_opt->thread_num); - fprintf(stderr, "[M::%s] count[%d] = %ld (for sanity check)\n", __func__, YAK_MAX_COUNT, (long)cnt[YAK_MAX_COUNT]); - peak_hom = ha_analyze_count(YAK_N_COUNTS, asm_opt->min_hist_kmer_cnt, asm_opt->hg_size>0?(ct->bs/asm_opt->hg_size):(-1), cnt, &peak_het); - if (hom_cov) *hom_cov = peak_hom; - if (het_cov) *het_cov = peak_het; - if (peak_hom > 0) fprintf(stderr, "[M::%s] peak_hom: %d; peak_het: %d\n", __func__, peak_hom, peak_het); - ///here ha_ct_shrink is mostly used to remove k-mer appearing only 1 time - if (flt_tab == 0) { - int cutoff = (int)(peak_hom * asm_opt->high_factor); - if (cutoff > YAK_MAX_COUNT - 1) cutoff = YAK_MAX_COUNT - 1; - if((extra_flag1 & HAF_SKIP_READ) && (extra_flag2 & HAF_SKIP_READ)) cutoff = YAK_MAX_COUNT - 1; - ha_ct_shrink(ct, 2, cutoff, asm_opt->thread_num); - for (i = 2, tot_cnt = 0; i <= cutoff; ++i) tot_cnt += cnt[i] * i; - } else { - ///Note: here is just to remove minimizer appearing YAK_MAX_COUNT times - ///minimizer with YAK_MAX_COUNT occ may apper > YAK_MAX_COUNT times, so it may lead to overflow at ha_pt_gen - ha_ct_shrink(ct, 2, YAK_MAX_COUNT - 1, asm_opt->thread_num); - for (i = 2, tot_cnt = 0; i <= YAK_MAX_COUNT - 1; ++i) tot_cnt += cnt[i] * i; - } - if(!(asm_opt->flag & HA_F_FAST)) - { - fprintf(stderr, "[M::%s::] counting in normal mode\n", __func__); - pt = ha_pt_gen(ct, asm_opt->thread_num, 0); - ha_count(asm_opt, HAF_COUNT_EXACT|extra_flag2, !(asm_opt->flag&HA_F_NO_HPC), asm_opt->k_mer_length, asm_opt->mz_win, pt, flt_tab, rs, NULL, 1, NULL, 0); - assert((uint64_t)tot_cnt == pt->tot_pos); - } - else - { - fprintf(stderr, "[M::%s::] counting in fast mode\n", __func__); - pt = ha_pt_gen_dp(asm_opt, ct, HAF_COUNT_EXACT|extra_flag2, asm_opt->thread_num, flt_tab, rs, peak_hom, peak_het); - } - //ha_pt_sort(pt, asm_opt->thread_num); - fprintf(stderr, "[M::%s::%.3f*%.2f] ==> indexed %ld positions, counted %ld distinct minimizer k-mers\n", __func__, - yak_realtime(), yak_cpu_usage(), (long)pt->tot_pos, (long)pt->tot); - return pt; -} - -int query_ct_index(void* ct_idx, uint64_t hash) -{ - ha_ct1_t *g = &(((ha_ct_t*)ct_idx)->h[hash & ((1ULL<<((ha_ct_t*)ct_idx)->pre) - 1)]); - khint_t k; - k = yak_ct_get(g->h, hash); - if (k == kh_end(g->h)) return 0; - return ((kh_key(g->h, k)&YAK_MAX_COUNT)==YAK_MAX_COUNT)?-1:(kh_key(g->h, k)&YAK_MAX_COUNT); -} - -int write_ct_index(void *i_ct_idx, char* file_name) -{ - char* gfa_name = (char*)malloc(strlen(file_name)+25); - sprintf(gfa_name, "%s.ct_flt", file_name); - FILE* fp = fopen(gfa_name, "w"); - if (!fp) { - free(gfa_name); - return 0; - } - ha_ct_t* ct_idx = (ha_ct_t*)i_ct_idx; - int i; - ha_ct1_t *g; - fwrite(&ct_idx->k, sizeof(ct_idx->k), 1, fp); - fwrite(&ct_idx->pre, sizeof(ct_idx->pre), 1, fp); - fwrite(&ct_idx->n_hash, sizeof(ct_idx->n_hash), 1, fp); - fwrite(&ct_idx->n_shift, sizeof(ct_idx->n_shift), 1, fp); - fwrite(&ct_idx->tot, sizeof(ct_idx->tot), 1, fp); - for (i = 0; i < 1<pre; i++) - { - g = &(ct_idx->h[i]); - yak_ct_save(g->h, fp); - } - - - fprintf(stderr, "[M::%s] Index has been written.\n", __func__); - free(gfa_name); - fclose(fp); - return 1; -} - -int load_ct_index(void **i_ct_idx, char* file_name) -{ - char* gfa_name = (char*)malloc(strlen(file_name)+25); - sprintf(gfa_name, "%s.ct_flt", file_name); - FILE* fp = fopen(gfa_name, "r"); - if (!fp) { - free(gfa_name); - return 0; - } - ha_ct_t** ct_idx = (ha_ct_t**)i_ct_idx; - double index_time = 0; - uint64_t flag = 0; - int i; - ha_ct_t *h = 0; - ha_ct1_t *g; - CALLOC(h, 1); - - flag += fread(&h->k, sizeof(h->k), 1, fp); - flag += fread(&h->pre, sizeof(h->pre), 1, fp); - flag += fread(&h->n_hash, sizeof(h->n_hash), 1, fp); - flag += fread(&h->n_shift, sizeof(h->n_shift), 1, fp); - flag += fread(&h->tot, sizeof(h->tot), 1, fp); - CALLOC(h->h, 1<pre); - - - index_time = yak_realtime(); - for (i = 0; i < 1<pre; ++i) - { - g = &(h->h[i]); - yak_ct_load(&(g->h), fp); - } - - (*ct_idx) = h; - fprintf(stderr, "[M::%s::%.3f] ==> Loaded count table\n", __func__, yak_realtime() - index_time); - fprintf(stderr, "[M::%s] Index has been loaded.\n", __func__); - free(gfa_name); - return 1; -} - -int write_pt_index(void *flt_tab, ha_pt_t *ha_idx, All_reads* r, hifiasm_opt_t* opt, char* file_name) -{ - char* gfa_name = (char*)malloc(strlen(file_name)+64); - sprintf(gfa_name, "%s.pt_flt", file_name); - FILE* fp = fopen(gfa_name, "w"); - if (!fp) { - free(gfa_name); - return 0; - } - yak_ft_t *ha_flt_tab = (yak_ft_t*)flt_tab; - - if(ha_flt_tab) - { - fwrite("f", 1, 1, fp); - yak_ft_save(ha_flt_tab, fp); - } - - - if(ha_idx) - { - int i; - ha_pt1_t *g; - fwrite("h", 1, 1, fp); - fwrite(&ha_idx->k, sizeof(ha_idx->k), 1, fp); - fwrite(&ha_idx->pre, sizeof(ha_idx->pre), 1, fp); - fwrite(&ha_idx->tot, sizeof(ha_idx->tot), 1, fp); - fwrite(&ha_idx->tot_pos, sizeof(ha_idx->tot_pos), 1, fp); - - for (i = 0; i < 1<pre; ++i) - { - g = &(ha_idx->h[i]); - yak_pt_save(g->h, fp); - fwrite(&g->n, sizeof(g->n), 1, fp); - fwrite(g->a, sizeof(ha_idxpos_t), g->n, fp); - } - } - - fwrite(&opt->number_of_round, sizeof(opt->number_of_round), 1, fp); - fwrite(&opt->hom_cov, sizeof(opt->hom_cov), 1, fp); - fwrite(&opt->het_cov, sizeof(opt->het_cov), 1, fp); - fwrite(&opt->max_n_chain, sizeof(opt->max_n_chain), 1, fp); - - - write_All_reads(r, gfa_name); - - sprintf(gfa_name, "%s.pt_flt.paf.bin", file_name); - fclose(fp); fp = fopen(gfa_name, "w"); uint64_t k; - if (!fp) { - free(gfa_name); - return 0; - } - fwrite(&(r->total_reads), sizeof(r->total_reads), 1, fp); - for (k = 0; k < r->total_reads; k++) { - fwrite(&(r->paf[k].is_fully_corrected), sizeof(r->paf[k].is_fully_corrected), 1, fp); - fwrite(&(r->paf[k].is_abnormal), sizeof(r->paf[k].is_abnormal), 1, fp); - fwrite(&(r->paf[k].length), sizeof(r->paf[k].length), 1, fp); - fwrite(r->paf[k].buffer, sizeof((*(r->paf[k].buffer))), r->paf[k].length, fp); - } - - fprintf(stderr, "[M::%s] Index has been written.\n", __func__); - free(gfa_name); - fclose(fp); - return 1; -} - -int load_pt_index(void **r_flt_tab, ha_pt_t **r_ha_idx, All_reads *r, hifiasm_opt_t* opt, char* file_name) -{ - char* gfa_name = (char*)malloc(strlen(file_name)+64); - sprintf(gfa_name, "%s.pt_flt", file_name); - FILE* fp = fopen(gfa_name, "r"); - if (!fp) { - free(gfa_name); - return 0; - } - - ha_pt_t *ha_idx = NULL; - char mode = 0; - int f_flag = 0, absent, i; - double index_time, index_s_time, pos_time, pos_s_time; - - - - f_flag += fread(&mode, 1, 1, fp); - if(mode == 'f') - { - index_time = yak_realtime(); - - yak_ft_load((yak_ft_t **)r_flt_tab, fp); - - f_flag += fread(&mode, 1, 1, fp); - - fprintf(stderr, "[M::%s::%.3f] ==> Loaded flt table\n", __func__, yak_realtime()-index_time); - } - ///insert using multiple threads??? - if(mode == 'h') - { - pos_time = index_time = 0; - - CALLOC(ha_idx, 1); - ha_pt1_t *g; - f_flag += fread(&ha_idx->k, sizeof(ha_idx->k), 1, fp); - f_flag += fread(&ha_idx->pre, sizeof(ha_idx->pre), 1, fp); - f_flag += fread(&ha_idx->tot, sizeof(ha_idx->tot), 1, fp); - f_flag += fread(&ha_idx->tot_pos, sizeof(ha_idx->tot_pos), 1, fp); - CALLOC(ha_idx->h, 1<pre); - for (i = 0; i < 1<pre; ++i) - { - index_s_time = yak_realtime(); - - g = &(ha_idx->h[i]); - yak_pt_load(&(g->h), fp); - - index_time += yak_realtime() - index_s_time; - - pos_s_time = yak_realtime(); - - f_flag += fread(&g->n, sizeof(g->n), 1, fp); - MALLOC(g->a, g->n); - f_flag += fread(g->a, sizeof(ha_idxpos_t), g->n, fp); - - pos_time += yak_realtime() - pos_s_time; - } - (*r_ha_idx) = ha_idx; - - fprintf(stderr, "[M::%s::%.3f(index)/%.3f(pos)] ==> Loaded pos table\n", __func__, index_time, pos_time); - } - - if(mode != 'h' && mode != 'f') - { - free(gfa_name); - fclose(fp); - return 0; - } - - - f_flag += fread(&absent, sizeof(absent), 1, fp); - if(absent != opt->number_of_round) - { - fprintf(stderr, "ERROR: different number of rounds!\n"); - exit(1); - } - - f_flag += fread(&opt->hom_cov, sizeof(opt->hom_cov), 1, fp); - f_flag += fread(&opt->het_cov, sizeof(opt->het_cov), 1, fp); - f_flag += fread(&opt->max_n_chain, sizeof(opt->max_n_chain), 1, fp); - - - // fclose(fp); - - if(!load_All_reads(r, gfa_name)) - { - free(gfa_name); - return 0; - } - - memset(r->trio_flag, AMBIGU, r->total_reads*sizeof(uint8_t)); - - sprintf(gfa_name, "%s.pt_flt.paf.bin", file_name); - fclose(fp); fp = fopen(gfa_name, "r"); uint64_t k; - if (!fp) { - free(gfa_name); - return 0; - } - f_flag += fread(&(r->total_reads), sizeof(r->total_reads), 1, fp); - r->paf = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*r->total_reads); - r->reverse_paf = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*r->total_reads); - for (k = 0; k < r->total_reads; k++) { - // init_ma_hit_t_alloc(&(r->paf[k])); - init_ma_hit_t_alloc(&(r->reverse_paf[k])); - - f_flag += fread(&(r->paf[k].is_fully_corrected), sizeof(r->paf[k].is_fully_corrected), 1, fp); - f_flag += fread(&(r->paf[k].is_abnormal), sizeof(r->paf[k].is_abnormal), 1, fp); - f_flag += fread(&(r->paf[k].length), sizeof(r->paf[k].length), 1, fp); - r->paf[k].size = r->paf[k].length; - - r->paf[k].buffer = NULL; - if(r->paf[k].length == 0) continue; - - r->paf[k].buffer = (ma_hit_t*)malloc(sizeof(ma_hit_t)*r->paf[k].length); - fread(r->paf[k].buffer, sizeof((*(r->paf[k].buffer))), r->paf[k].length, fp); - } - fclose(fp); - - fprintf(stderr, "[M::%s] Index has been loaded.\n", __func__); - - free(gfa_name); - return 1; -} - - - -int uidx_write(void *flt_tab, ha_pt_t *ha_idx, char* file_name, ma_ug_t *ug) -{ - char* gfa_name = (char*)malloc(strlen(file_name)+25); - sprintf(gfa_name, "%s.uidx.bin", file_name); - FILE* fp = fopen(gfa_name, "w"); - if (!fp) { - free(gfa_name); - return 0; - } - - if(ug) write_dbug(ug, fp); - - yak_ft_t *ha_flt_tab = (yak_ft_t*)flt_tab; - - if(ha_flt_tab) - { - fwrite("f", 1, 1, fp); - yak_ft_save(ha_flt_tab, fp); - } - - if(ha_idx) - { - int i; - ha_pt1_t *g; - fwrite("h", 1, 1, fp); - fwrite(&ha_idx->k, sizeof(ha_idx->k), 1, fp); - fwrite(&ha_idx->pre, sizeof(ha_idx->pre), 1, fp); - fwrite(&ha_idx->tot, sizeof(ha_idx->tot), 1, fp); - fwrite(&ha_idx->tot_pos, sizeof(ha_idx->tot_pos), 1, fp); - - for (i = 0; i < 1<pre; ++i) - { - g = &(ha_idx->h[i]); - yak_pt_save(g->h, fp); - fwrite(&g->n, sizeof(g->n), 1, fp); - fwrite(g->al, sizeof(ha_idxposl_t), g->n, fp); - } - } - fprintf(stderr, "[M::%s] Index has been written.\n", __func__); - free(gfa_name); - fclose(fp); - return 1; -} - - -int uidx_load(void **r_flt_tab, ha_pt_t **r_ha_idx, char* file_name, ma_ug_t *ug) -{ - char* gfa_name = (char*)malloc(strlen(file_name)+25); - sprintf(gfa_name, "%s.uidx.bin", file_name); - FILE* fp = fopen(gfa_name, "r"); - if (!fp) { - free(gfa_name); - return 0; - } - - if(ug && (!test_dbug(ug, fp))) { - fprintf(stderr, "[M::%s] Renew UL Index\n", __func__); - free(gfa_name); fclose(fp); - return 0; - } - // fprintf(stderr, "[M::%s]\t%s\tftell::%ld\n", __func__, file_name, ftell(fp)); - - ha_pt_t *ha_idx = NULL; - char mode = 0; - int f_flag = 0, i; - double index_time, index_s_time, pos_time, pos_s_time; - - - - f_flag += fread(&mode, 1, 1, fp); - if(mode == 'f') - { - index_time = yak_realtime(); - - yak_ft_load((yak_ft_t **)r_flt_tab, fp); - - f_flag += fread(&mode, 1, 1, fp); - - fprintf(stderr, "[M::%s::%.3f] ==> Loaded flt table\n", __func__, yak_realtime()-index_time); - } - ///insert using multiple threads??? - if(mode == 'h') - { - pos_time = index_time = 0; - - CALLOC(ha_idx, 1); - ha_pt1_t *g; - f_flag += fread(&ha_idx->k, sizeof(ha_idx->k), 1, fp); - f_flag += fread(&ha_idx->pre, sizeof(ha_idx->pre), 1, fp); - f_flag += fread(&ha_idx->tot, sizeof(ha_idx->tot), 1, fp); - f_flag += fread(&ha_idx->tot_pos, sizeof(ha_idx->tot_pos), 1, fp); - CALLOC(ha_idx->h, 1<pre); - for (i = 0; i < 1<pre; ++i) - { - index_s_time = yak_realtime(); - - g = &(ha_idx->h[i]); - yak_pt_load(&(g->h), fp); - - index_time += yak_realtime() - index_s_time; - - pos_s_time = yak_realtime(); - - f_flag += fread(&g->n, sizeof(g->n), 1, fp); - MALLOC(g->al, g->n); - f_flag += fread(g->al, sizeof(ha_idxposl_t), g->n, fp); - - pos_time += yak_realtime() - pos_s_time; - } - (*r_ha_idx) = ha_idx; - - fprintf(stderr, "[M::%s::%.3f(index)/%.3f(pos)] ==> Loaded pos table\n", __func__, index_time, pos_time); - } - - if(mode != 'h' && mode != 'f') - { - free(gfa_name); - fclose(fp); - return 0; - } - - fprintf(stderr, "[M::%s] Index has been loaded.\n", __func__); - - fclose(fp); - free(gfa_name); - return 1; -} +#include +#include +#include +#include +#include +#include "kthread.h" +#include "khashl.h" +#include "kseq.h" +#include "ksort.h" +#include "htab.h" +#include "Process_Read.h" + +#define YAK_COUNTER_BITS 12 +#define YAK_N_COUNTS (1<bf_shift = 0; + o->bf_n_hash = 4; + o->k = 31; + o->w = 1; + o->pre = YAK_COUNTER_BITS; + o->n_thread = 4; + o->chunk_size = 20000000; +} + +/************************ + * Blocked bloom filter * + ************************/ + +#define YAK_BLK_SHIFT 9 // 64 bytes, the size of a cache line +#define YAK_BLK_MASK ((1<<(YAK_BLK_SHIFT)) - 1) + +typedef struct { + int n_shift, n_hashes; + uint8_t *b; +} yak_bf_t; +///in most cases, n_shift = 25, n_hashes = 4 +yak_bf_t *yak_bf_init(int n_shift, int n_hashes) +{ + yak_bf_t *b; + void *ptr = 0; + if (n_shift + YAK_BLK_SHIFT > 64 || n_shift < YAK_BLK_SHIFT) return 0; + CALLOC(b, 1); + b->n_shift = n_shift; + b->n_hashes = n_hashes; + posix_memalign(&ptr, 1<<(YAK_BLK_SHIFT-3), 1ULL<<(n_shift-3)); + b->b = (uint8_t*)ptr; + bzero(b->b, 1ULL<<(n_shift-3)); + return b; +} + +void yak_bf_destroy(yak_bf_t *b) +{ + if (b == 0) return; + free(b->b); free(b); +} + +int yak_bf_insert(yak_bf_t *b, uint64_t hash) +{ + int x = b->n_shift - YAK_BLK_SHIFT; + uint64_t y = hash & ((1ULL<> x & YAK_BLK_MASK; + int h2 = hash >> b->n_shift & YAK_BLK_MASK; + uint8_t *p = &b->b[y<<(YAK_BLK_SHIFT-3)]; + int i, z = h1, cnt = 0; + if ((h2&31) == 0) h2 = (h2 + 1) & YAK_BLK_MASK; // otherwise we may repeatedly use a few bits + for (i = 0; i < b->n_hashes; z = (z + h2) & YAK_BLK_MASK) { + uint8_t *q = &p[z>>3], u; + u = 1<<(z&7); + cnt += !!(*q & u); + *q |= u; + ++i; + } + return cnt; +} + +/******************** + * Count hash table * + ********************/ + +#define yak_ct_eq(a, b) ((a)>>YAK_COUNTER_BITS == (b)>>YAK_COUNTER_BITS) // lower 8 bits for counts; higher bits for k-mer +#define yak_ct_hash(a) ((a)>>YAK_COUNTER_BITS) +KHASHL_SET_INIT(static klib_unused, yak_ct_t, yak_ct, uint64_t, yak_ct_hash, yak_ct_eq) + +typedef struct { + yak_ct_t *h; + yak_bf_t *b; +} ha_ct1_t; + +typedef struct { + int k, pre, n_hash, n_shift; + uint64_t tot; ///number of distinct k-mers + uint64_t bs; + ha_ct1_t *h; +} ha_ct_t; + +///for 0-th counting, k = 51, pre = 12, n_hash = 4, n_shift = 37 +///for 1-th counting, opt.k = 51, opt->pre = 12, opt->bf_n_hash = 4, opt.bf_shift = 0 +static ha_ct_t *ha_ct_init(int k, int pre, int n_hash, int n_shift) +{ + ha_ct_t *h; + int i; + if (pre < YAK_COUNTER_BITS) return 0; + CALLOC(h, 1); + h->k = k, h->pre = pre; + CALLOC(h->h, 1<pre); + ///ipre = 4096 + ///it seems there is a large hash table h, consisting 4096 small hash tables + for (i = 0; i < 1<pre; ++i) + h->h[i].h = yak_ct_init(); + ///for 0-th counting, enter here; used for bloom filter + if (n_hash > 0 && n_shift > h->pre) { + h->n_hash = n_hash, h->n_shift = n_shift; + for (i = 0; i < 1<pre; ++i) + h->h[i].b = yak_bf_init(h->n_shift - h->pre, h->n_hash); ///h->n_shift = 37, h->pre = 12, h->n_hash = 4 + } + return h; +} + +static void ha_ct_destroy_bf(ha_ct_t *h) +{ + int i; + for (i = 0; i < 1<pre; ++i) { + if (h->h[i].b) + yak_bf_destroy(h->h[i].b); + h->h[i].b = 0; + } +} + +static void ha_ct_destroy(ha_ct_t *h) +{ + int i; + if (h == 0) return; + ha_ct_destroy_bf(h); + for (i = 0; i < 1<pre; ++i) + yak_ct_destroy(h->h[i].h); + free(h->h); free(h); +} + +static int ha_ct_insert_list(ha_ct_t *h, int create_new, int n, const uint64_t *a) +{ + int j, mask = (1<pre) - 1, n_ins = 0; + ha_ct1_t *g; + if (n == 0) return 0; + ///corresponding small hash index + g = &h->h[a[0]&mask]; + for (j = 0; j < n; ++j) { + int ins = 1, absent; + ///x is a 64-bit word, h->pre=12 + ///all elements at a have the same low 12 bits + ///so low 12 bits are not useful + uint64_t x = a[j] >> h->pre; + khint_t k; + assert((a[j]&mask) == (a[0]&mask)); + if (create_new) { + if (g->b) + ins = (yak_bf_insert(g->b, x) == h->n_hash); + ///x = the high 52 bits of a[j] + low 12 bits 0 + ///the low 12 bits are used for counting + if (ins) { + k = yak_ct_put(g->h, x << YAK_COUNTER_BITS | (g->b? 1 : 0), &absent); + if (absent) ++n_ins; + if ((kh_key(g->h, k)&YAK_MAX_COUNT) < YAK_MAX_COUNT) + ++kh_key(g->h, k); + } + } else { + k = yak_ct_get(g->h, x<h) && (kh_key(g->h, k)&YAK_MAX_COUNT) < YAK_MAX_COUNT) + ++kh_key(g->h, k); + } + } + return n_ins; +} + +/*** generate histogram ***/ + +typedef struct { + uint64_t c[YAK_N_COUNTS]; +} buf_cnt_t; + +typedef struct { + const ha_ct_t *h; + buf_cnt_t *cnt; +} hist_aux_t; + +static void worker_ct_hist(void *data, long i, int tid) // callback for kt_for() +{ + hist_aux_t *a = (hist_aux_t*)data; + uint64_t *cnt = a->cnt[tid].c; + yak_ct_t *g = a->h->h[i].h; + khint_t k; + for (k = 0; k < kh_end(g); ++k) + if (kh_exist(g, k)) + ++cnt[kh_key(g, k)&YAK_MAX_COUNT]; +} + +///YAK_N_COUNTS is also 4096 +///used for calculating k-mer histogram +static void ha_ct_hist(const ha_ct_t *h, int64_t cnt[YAK_N_COUNTS], int n_thread) +{ + hist_aux_t a; + int i, j; + a.h = h; + memset(cnt, 0, YAK_N_COUNTS * sizeof(uint64_t)); + CALLOC(a.cnt, n_thread); + ///start 4096 threads + kt_for(n_thread, worker_ct_hist, &a, 1<pre); + for (i = 0; i < YAK_N_COUNTS; ++i) cnt[i] = 0; + for (j = 0; j < n_thread; ++j) + for (i = 0; i < YAK_N_COUNTS; ++i) + cnt[i] += a.cnt[j].c[i]; + free(a.cnt); +} + +/*** shrink a hash table ***/ + +typedef struct { + int min, max; + ha_ct_t *h; +} shrink_aux_t; + +static void worker_ct_shrink(void *data, long i, int tid) // callback for kt_for() +{ + shrink_aux_t *a = (shrink_aux_t*)data; + ha_ct_t *h = a->h; + yak_ct_t *g = h->h[i].h, *f; + khint_t k; + f = yak_ct_init(); + yak_ct_resize(f, kh_size(g)); + for (k = 0; k < kh_end(g); ++k) { + if (kh_exist(g, k)) { + int absent, c = kh_key(g, k) & YAK_MAX_COUNT; + if (c >= a->min && c <= a->max) + yak_ct_put(f, kh_key(g, k), &absent); + } + } + yak_ct_destroy(g); + h->h[i].h = f; +} + +static void ha_ct_shrink(ha_ct_t *h, int min, int max, int n_thread) +{ + int i; + shrink_aux_t a; + a.h = h, a.min = min, a.max = max; + ///still start 4096 threads + kt_for(n_thread, worker_ct_shrink, &a, 1<pre); + for (i = 0, h->tot = 0; i < 1<pre; ++i) + h->tot += kh_size(h->h[i].h); + fprintf(stderr, "[M::%s::%.3f*%.2f] ==> counted %ld distinct minimizer k-mers\n", __func__, + yak_realtime(), yak_cpu_usage(), (long)h->tot); +} + +/*********************** + * Position hash table * + ***********************/ + +KHASHL_MAP_INIT(static klib_unused, yak_pt_t, yak_pt, uint64_t, uint64_t, yak_ct_hash, yak_ct_eq) +#define generic_key(x) (x) +KRADIX_SORT_INIT(ha64, uint64_t, generic_key, 8) + +typedef struct { + yak_pt_t *h; + uint64_t n; + ha_idxpos_t *a; + ha_idxposl_t *al; +} ha_pt1_t; + +struct ha_pt_s { + int k, pre; + uint64_t tot, tot_pos; + ha_pt1_t *h; +}; + +typedef struct { + const ha_ct_t *ct; + ha_pt_t *pt; + int is_l; +} pt_gen_aux_t; + + +static void worker_pt_shrink(void *data, long i, int tid) // callback for kt_for() +{ + ha_pt_t *h = (ha_pt_t*)data; + ha_pt1_t *b = &h->h[i]; + yak_pt_t *f = NULL; + khint_t k; + f = yak_pt_init(); + for (k = 0, b->n = 0; k < kh_end(b->h); ++k) { + if (kh_exist(b->h, k)) { + if(kh_val(b->h, k) <= 0) continue; + int absent; khint_t l; + l = yak_pt_put(f, (kh_key(b->h, k) >> h->pre) << YAK_COUNTER_BITS, &absent); + kh_val(f, l) = b->n; + b->n += kh_key(b->h, k) & YAK_MAX_COUNT; + } + } + yak_pt_destroy(b->h); + h->h[i].h = f; + CALLOC(b->a, b->n);///need fix +} + +static uint64_t ha_pt_shrink(ha_pt_t *h, int n_thread) +{ + int i; + uint64_t occ; + ///still start 4096 threads + kt_for(n_thread, worker_pt_shrink, h, 1<pre); + for (i = 0, occ = 0, h->tot = 0; i < 1<pre; ++i) + { + h->tot += kh_size(h->h[i].h); + occ += h->h[i].n; + } + return occ; +} + +static void worker_pt_gen(void *data, long i, int tid) // callback for kt_for() +{ + pt_gen_aux_t *a = (pt_gen_aux_t*)data; + ha_pt1_t *b = &a->pt->h[i]; + yak_ct_t *g = a->ct->h[i].h; + khint_t k; + for (k = 0, b->n = 0; k != kh_end(g); ++k) { + if (kh_exist(g, k)) { + int absent; + khint_t l; + l = yak_pt_put(b->h, kh_key(g, k) >> a->ct->pre << YAK_COUNTER_BITS, &absent); + ///this should be the start index of kh_key's corresponding pos at ha_idxpos_t* a + kh_val(b->h, l) = b->n; + b->n += kh_key(g, k) & YAK_MAX_COUNT; + } + } + yak_ct_destroy(g); + a->ct->h[i].h = 0; + if(a->is_l) CALLOC(b->al, b->n); + else CALLOC(b->a, b->n); +} + +ha_pt_t *ha_pt_gen(ha_ct_t *ct, int n_thread, int is_l) +{ + pt_gen_aux_t a; + int i; + ha_pt_t *pt; + ha_ct_destroy_bf(ct); + CALLOC(pt, 1); + pt->k = ct->k, pt->pre = ct->pre, pt->tot = ct->tot; + CALLOC(pt->h, (((uint64_t)1)<pre)); + for (i = 0; i < 1<pre; ++i) { + pt->h[i].h = yak_pt_init(); + yak_pt_resize(pt->h[i].h, kh_size(ct->h[i].h)); + } + a.ct = ct, a.pt = pt, a.is_l = is_l; + kt_for(n_thread, worker_pt_gen, &a, 1<pre); + free(ct->h); free(ct); + return pt; +} + +static void worker_pt_gen_count(void *data, long i, int tid) // callback for kt_for() +{ + pt_gen_aux_t *a = (pt_gen_aux_t*)data; + ha_pt1_t *b = &a->pt->h[i]; + yak_ct_t *g = a->ct->h[i].h; + khint_t k; + for (k = 0, b->n = 0; k != kh_end(g); ++k) { + if (kh_exist(g, k)) { + int absent; + khint_t l; + l = yak_pt_put(b->h, kh_key(g, k) >> a->ct->pre << YAK_COUNTER_BITS, &absent); + kh_val(b->h, l) = 0; kh_key(b->h, l) |= kh_key(g, k) & YAK_MAX_COUNT; + } + } + yak_ct_destroy(g); + a->ct->h[i].h = 0; +} + +ha_pt_t *ha_pt_gen_count(ha_ct_t *ct, int n_thread) +{ + pt_gen_aux_t a; + int i; + ha_pt_t *pt; + ha_ct_destroy_bf(ct); + CALLOC(pt, 1); + pt->k = ct->k, pt->pre = ct->pre, pt->tot = ct->tot; + CALLOC(pt->h, (((uint64_t)1)<pre)); + for (i = 0; i < 1<pre; ++i) { + pt->h[i].h = yak_pt_init(); + yak_pt_resize(pt->h[i].h, kh_size(ct->h[i].h)); + } + a.ct = ct, a.pt = pt; + kt_for(n_thread, worker_pt_gen_count, &a, 1<pre); + free(ct->h); free(ct); + return pt; +} + + +int ha_pt_insert_list(ha_pt_t *h, int n, const ha_mz1_t *a) +{ + int j, mask = (1<pre) - 1, n_ins = 0; + ha_pt1_t *g; + if (n == 0) return 0; + g = &h->h[a[0].x&mask]; + for (j = 0; j < n; ++j) { + uint64_t x = a[j].x >> h->pre; + khint_t k; + int n; + ha_idxpos_t *p; + assert((a[j].x&mask) == (a[0].x&mask)); + k = yak_pt_get(g->h, x<h)) continue; // TODO: understand why we sometimes come here + n = kh_key(g->h, k) & YAK_MAX_COUNT; + assert(n < YAK_MAX_COUNT); + p = &g->a[kh_val(g->h, k) + n]; + p->rid = a[j].rid, p->rev = a[j].rev, p->pos = a[j].pos, p->span = a[j].span; + //(uint64_t)a[j].rid<<36 | (uint64_t)a[j].rev<<35 | (uint64_t)a[j].pos<<8 | (uint64_t)a[j].span; + ++kh_key(g->h, k); + ++n_ins; + } + return n_ins; +} + + +int ha_pt_cnt_insert_list(ha_pt_t *h, int n, const uint64_t *a) +{ + int j, mask = (1<pre) - 1, n_ins = 0; + ha_pt1_t *g; + if (n == 0) return 0; + g = &h->h[a[0]&mask]; + for (j = 0; j < n; ++j) { + uint64_t x = a[j] >> h->pre; + khint_t k; + assert((a[j]&mask) == (a[0]&mask)); + k = yak_pt_get(g->h, x<h)) continue; // TODO: understand why we sometimes come here + ++kh_val(g->h, k); + ++n_ins; + } + // fprintf(stderr, "n: %d, n_ins: %d\n", n, n_ins); + return n_ins; +} +/* +static void worker_pt_sort(void *data, long i, int tid) +{ + ha_pt_t *h = (ha_pt_t*)data; + ha_pt1_t *g = &h->h[i]; + khint_t k; + for (k = 0; k < kh_end(g->h); ++k) { + int n; + uint64_t *p; + if (!kh_exist(g->h, k)) continue; + n = kh_key(g->h, k) & YAK_MAX_COUNT; + p = &g->a[kh_val(g->h, k)]; + radix_sort_ha64(p, p + n); + } +} + +void ha_pt_sort(ha_pt_t *h, int n_thread) +{ + kt_for(n_thread, worker_pt_sort, h, 1<pre); +} +*/ +void ha_pt_destroy(ha_pt_t *h) +{ + int i; + if (h == 0) return; + for (i = 0; i < 1<pre; ++i) { + yak_pt_destroy(h->h[i].h); + if(h->h[i].a){ + free(h->h[i].a); h->h[i].a = NULL; + } + if(h->h[i].al){ + free(h->h[i].al); h->h[i].al = NULL; + } + } + free(h->h); free(h); +} + +const ha_idxpos_t *ha_pt_get(const ha_pt_t *h, uint64_t hash, int *n) +{ + khint_t k; + const ha_pt1_t *g = &h->h[hash & ((1ULL<pre) - 1)]; + *n = 0; + k = yak_pt_get(g->h, hash >> h->pre << YAK_COUNTER_BITS); + if (k == kh_end(g->h)) return 0; + *n = kh_key(g->h, k) & YAK_MAX_COUNT; + return &g->a[kh_val(g->h, k)]; +} + +const ha_idxposl_t *ha_ptl_get(const ha_pt_t *h, uint64_t hash, int *n) +{ + khint_t k; + const ha_pt1_t *g = &h->h[hash & ((1ULL<pre) - 1)]; + *n = 0; + k = yak_pt_get(g->h, hash >> h->pre << YAK_COUNTER_BITS); + if (k == kh_end(g->h)) return 0; + *n = kh_key(g->h, k) & YAK_MAX_COUNT; + return &g->al[kh_val(g->h, k)]; +} + +const int ha_pt_cnt(const ha_pt_t *h, uint64_t hash) +{ + khint_t k; + const ha_pt1_t *g = &h->h[hash & ((1ULL<pre) - 1)]; + k = yak_pt_get(g->h, hash >> h->pre << YAK_COUNTER_BITS); + if (k == kh_end(g->h)) return 0; + return kh_key(g->h, k) & YAK_MAX_COUNT; +} + +inline uint64_t flt_quals(char *sc_a, uint64_t sc_l, uint64_t sc_off, int64_t sc_cut) +{ + int64_t sc_min = sc_l * sc_cut, sc_tot; uint64_t k; + for (k = sc_tot = 0; (k < sc_l) && (sc_tot < sc_min); k++) { + sc_tot += (((uint8_t)sc_a[k]) - sc_off); + } + + // if(sc_tot < sc_min) { + // fprintf(stderr, "[M::%s] sc_tot::%ld, sc_min::%ld, sc_l::%lu\n", __func__, sc_tot, sc_min, sc_l); + // } + + if(sc_tot < sc_min) return 0; + return 1; +} + +/********************************** + * Buffer for counting all k-mers * + **********************************/ +KSEQ_INIT(gzFile, gzread) +#define HAF_COUNT_EXACT 0x1 +#define HAF_COUNT_ALL 0x2 +#define HAF_RS_WRITE_LEN 0x4 +#define HAF_RS_WRITE_SEQ 0x8 +#define HAF_RS_READ 0x10 +#define HAF_CREATE_NEW 0x20 +#define HAF_SKIP_READ 0x40 +#define HAF_UG_READ 0x80 +#define HAF_COUNT_REFINE 0x100 + +typedef struct { // global data structure for kt_pipeline() + const yak_copt_t *opt; + const void *flt_tab; + int flag, create_new, is_store, uq, ifq; + uint64_t n_mz, n_seq; ///number of total reads + kseq_t *ks; + UC_Read ucr; + ha_ct_t *ct; + ha_pt_t *pt; + const All_reads *rs_in; + All_reads *rs_out; + const ma_utg_v *us_in; +} pl_data_t; + +#define MZ_TEST_INIT(sf, HType, VType, IType, Ia) \ +typedef struct {int n, m; uint64_t n_ins; uint64_t *a; HType *b;} sf##_ch_buf_t;\ +static inline void sf##_ct_insert_buf(sf##_ch_buf_t *buf, int p, uint64_t y) /** insert a k-mer $y to a linear buffer**/\ +{\ + /**assign k-mer to one of the 4096 bins**/\ + /**using low 12 bits for assigning**/\ + /**so all elements at b have the same low 12 bits**/\ + int pre = y & ((1<n == b->m) {\ + b->m = b->m < 8? 8 : b->m + (b->m>>1);\ + REALLOC(b->a, b->m);\ + }\ + b->a[b->n++] = y;\ +}\ +/**buf is the read block, k is the k-mer length, p = 12, len is the read length, seq is the read**/\ +static void sf##_count_seq_buf(sf##_ch_buf_t *buf, int k, int p, int len, const char *seq) /**insert k-mers in $seq to linear buffer $buf**/\ +{\ + int i, l;\ + uint64_t x[4], mask = (1ULL<>1)) & mask;\ + x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift;\ + x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift;\ + if (++l >= k)\ + sf##_ct_insert_buf(buf, p, yak_hash_long(x));\ + } else l = 0, x[0] = x[1] = x[2] = x[3] = 0; /** if there is an "N", restart**/\ + }\ +}\ +static void sf##_count_seq_buf_HPC(sf##_ch_buf_t *buf, int k, int p, int len, const char *seq) /**insert k-mers in $seq to linear buffer $buf**/\ +{\ + int i, l, last = -1;\ + uint64_t x[4], mask = (1ULL<>1)) & mask;\ + x[2] = x[2] >> 1 | (uint64_t)(1 - (c&1)) << shift;\ + x[3] = x[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift;\ + if (++l >= k)\ + sf##_ct_insert_buf(buf, p, yak_hash_long(x));\ + last = c;\ + }\ + } else l = 0, last = -1, x[0] = x[1] = x[2] = x[3] = 0; /**if there is an "N", restart**/\ + }\ +}\ +int sf##_ha_pt_insert_list(ha_pt_t *h, int n, const HType *a)\ +{\ + int j, mask = (1<pre) - 1, n_ins = 0;\ + ha_pt1_t *g;\ + if (n == 0) return 0;\ + g = &h->h[a[0].x&mask];\ + /**fprintf(stderr, "a[0].x&mask: %lu, a[0].x&mask: %lu, n: %d\n", a[0].x&mask, a[0].x, n);**/\ + for (j = 0; j < n; ++j) {\ + uint64_t x = a[j].x >> h->pre;\ + khint_t k;\ + int n;\ + IType *p;\ + assert((a[j].x&mask) == (a[0].x&mask));\ + k = yak_pt_get(g->h, x<h)) continue; \ + n = kh_key(g->h, k) & YAK_MAX_COUNT;\ + /**fprintf(stderr, "j: %d, n: %d\n", j, n);**/\ + assert(n < YAK_MAX_COUNT);\ + p = &g->Ia[kh_val(g->h, k) + n];\ + p->rid = a[j].rid, p->rev = a[j].rev, p->pos = a[j].pos, p->span = a[j].span;\ + /**(uint64_t)a[j].rid<<36 | (uint64_t)a[j].rev<<35 | (uint64_t)a[j].pos<<8 | (uint64_t)a[j].span;**/\ + ++kh_key(g->h, k);\ + ++n_ins;\ + }\ + return n_ins;\ +}\ +/** data structure for each step in kt_pipeline()**/\ +typedef struct {pl_data_t *p;uint64_t n_seq0; int n_seq, m_seq, sum_len, nk, uq, *len; char **seq; VType *mz_buf; VType *mz;sf##_ch_buf_t *buf;st_mt_t *mt;} sf##_st_data_t;\ +static void sf##_worker_for_insert(void *data, long i, int tid) /** callback for kt_for()**/\ +{\ + sf##_st_data_t *s = (sf##_st_data_t*)data;\ + sf##_ch_buf_t *b = &s->buf[i];\ + if (s->p->pt){\ + if(s->p->flag&HAF_COUNT_REFINE) b->n_ins += ha_pt_cnt_insert_list(s->p->pt, b->n, b->a);\ + else b->n_ins += sf##_ha_pt_insert_list(s->p->pt, b->n, b->b);\ + }else{\ + b->n_ins += ha_ct_insert_list(s->p->ct, s->p->create_new, b->n, b->a);\ + }\ +}\ +static void sf##_worker_for_mz(void *data, long i, int tid)\ +{\ + sf##_st_data_t *s = (sf##_st_data_t*)data;\ + /**get the corresponding minimzer vector of this read**/\ + VType *b = &s->mz_buf[tid];\ + s->mz_buf[tid].n = 0;\ + sf##_ha_sketch(s->seq[i], s->len[i], s->p->opt->w, s->p->opt->k, s->n_seq0 + i, s->p->opt->is_HPC, b, s->p->flt_tab, asm_opt.mz_sample_dist, 0, 0, \ + (s->p->pt&&(s->p->flag&HAF_COUNT_REFINE))?s->p->pt:NULL, s->p->opt->min_rcnt, asm_opt.dp_min_len, asm_opt.dp_e, &(s->mt[tid]), asm_opt.mz_rewin, s->uq, NULL);\ + s->mz[i].n = s->mz[i].m = b->n;\ + MALLOC(s->mz[i].a, b->n);\ + MEMCPY(s->mz[i].a, b->a, b->n);\ +}\ +static inline void sf##_pt_insert_buf(sf##_ch_buf_t *buf, int p, const HType *y){\ + /**assign minimizer to one of 4096 bins by low 12 bits**/\ + int pre = y->x & ((1<n == b->m) {\ + b->m = b->m < 8? 8 : b->m + (b->m>>1);\ + REALLOC(b->b, b->m);\ + }\ + b->b[b->n++] = *y;\ +}\ +static void *sf##_worker_count(void *data, int step, void *in) /** callback for kt_pipeline()**/\ +{\ + pl_data_t *p = (pl_data_t*)data;\ + /**uint8_t src_a[1000000], des_a[1000000];**/\ + if (step == 0) { /** step 1: read a block of sequences**/\ + int ret;\ + sf##_st_data_t *s;\ + CALLOC(s, 1);\ + s->p = p;\ + s->n_seq0 = p->n_seq;\ + s->uq = p->opt->uq;\ + if (p->rs_in && (p->flag & HAF_RS_READ)) {\ + while (p->n_seq < p->rs_in->total_reads) {\ + if ((p->flag & HAF_SKIP_READ) && p->rs_in->trio_flag[p->n_seq] != AMBIGU) {\ + ++p->n_seq;\ + continue;\ + }\ + int l;\ + recover_UC_Read(&p->ucr, p->rs_in, p->n_seq);\ + l = p->ucr.length;\ + if (s->n_seq == s->m_seq) {\ + s->m_seq = s->m_seq < 16? 16 : s->m_seq + (s->m_seq>>1);\ + REALLOC(s->len, s->m_seq);\ + REALLOC(s->seq, s->m_seq);\ + }\ + MALLOC(s->seq[s->n_seq], l);\ + memcpy(s->seq[s->n_seq], p->ucr.seq, l);\ + s->len[s->n_seq++] = l;\ + ++p->n_seq;\ + s->sum_len += l;\ + s->nk += l >= p->opt->k? l - p->opt->k + 1 : 0;\ + if (s->sum_len >= p->opt->chunk_size)\ + break;\ + }\ + } else if(p->us_in) {\ + ma_utg_t *u;\ + while (p->n_seq < p->us_in->n) {\ + u = &(p->us_in->a[p->n_seq]);\ + if (s->n_seq == s->m_seq) {\ + s->m_seq = s->m_seq < 16? 16 : s->m_seq + (s->m_seq>>1);\ + REALLOC(s->len, s->m_seq);\ + REALLOC(s->seq, s->m_seq);\ + }\ + MALLOC(s->seq[s->n_seq], u->len);\ + if(u->s) memcpy(s->seq[s->n_seq], u->s, u->len);\ + else retrieve_u_seq(NULL, s->seq[s->n_seq], u, 0, 0, -1, NULL);\ + s->len[s->n_seq++] = u->len;\ + ++p->n_seq;\ + s->sum_len += u->len;\ + s->nk += u->len >= p->opt->k? u->len - p->opt->k + 1 : 0;\ + if (s->sum_len >= p->opt->chunk_size)\ + break;\ + }\ + } else {\ + while ((ret = kseq_read(p->ks)) >= 0) {\ + int l = (int)(p->ks->seq.l) - (int)(p->opt->adaLen) - (int)(p->opt->adaLen);\ + if((l <= 0) || (l < asm_opt.rl_cut)) continue;\ + if((p->ifq) && (asm_opt.sc_cut > 0) && (!flt_quals(p->ks->qual.s+p->opt->adaLen, l, 33, asm_opt.sc_cut))) continue;\ + if (p->n_seq >= 1<<28) {\ + fprintf(stderr, "ERROR: this implementation supports no more than %d reads\n", 1<<28);\ + exit(1);\ + }\ + if (p->rs_out) {\ + /**for 0-th count, just insert read length to R_INF, instead of read**/\ + if (p->flag & HAF_RS_WRITE_LEN) {\ + assert(p->n_seq == p->rs_out->total_reads);\ + ha_insert_read_len(p->rs_out, l, p->ks->name.l);\ + } else if (p->flag & HAF_RS_WRITE_SEQ) {\ + int i, n_N;\ + assert(l == (int)p->rs_out->read_length[p->n_seq]);\ + for (i = n_N = 0; i < l; ++i) /** count number of ambiguous bases**/\ + if (seq_nt4_table[(uint8_t)p->ks->seq.s[i+p->opt->adaLen]] >= 4)\ + ++n_N;\ + ha_compress_base(Get_READ(*p->rs_out, p->n_seq), p->ks->seq.s+p->opt->adaLen, l, &p->rs_out->N_site[p->n_seq], n_N);\ + memcpy(&p->rs_out->name[p->rs_out->name_index[p->n_seq]], p->ks->name.s, p->ks->name.l);\ + if(p->ifq) {\ + ha_compress_qual(Get_QUAL(*p->rs_out, p->n_seq), p->ks->qual.s+p->opt->adaLen, l, sc_bn, 33);\ + /**print_fastq(NULL, p->ks->name.s, p->ks->seq.s, p->ks->qual.s, (1<ks->qual.s+p->opt->adaLen, l, (1<n_seq, -1, -1, 0, sc_bn);\ + if(memcmp(src_a, des_a, l)!=0) fprintf(stderr, "ERROR: incorrect qual values\n");\ + else fprintf(stderr, "Correct: correct qual values\n");\ + }**/\ + }\ + }\ + }\ + if (s->n_seq == s->m_seq) {\ + s->m_seq = s->m_seq < 16? 16 : s->m_seq + (s->m_seq>>1);\ + REALLOC(s->len, s->m_seq);\ + REALLOC(s->seq, s->m_seq);\ + }\ + MALLOC(s->seq[s->n_seq], l);\ + memcpy(s->seq[s->n_seq], p->ks->seq.s+p->opt->adaLen, l);\ + s->len[s->n_seq++] = l;\ + ++p->n_seq;\ + s->sum_len += l;\ + s->nk += l >= p->opt->k? l - p->opt->k + 1 : 0;\ + /**p->opt->chunk_size is the block max size**/\ + if (s->sum_len >= p->opt->chunk_size)\ + break;\ + }\ + }\ + if (s->sum_len == 0) free(s);\ + else return s;\ + } else if (step == 1) { /** step 2: extract k-mers**/\ + /**s is the block of reads**/\ + sf##_st_data_t *s = (sf##_st_data_t*)in;\ + int i, n_pre = 1<opt->pre, m;\ + /**allocate the k-mer buffer**/\ + CALLOC(s->buf, n_pre);\ + m = (int)(s->nk * 1.2 / n_pre) + 1;\ + /**pre-allocate memory for each of 4096 buffer**/\ + for (i = 0; i < n_pre; ++i) {\ + s->buf[i].m = m;\ + /**for 0-th counting, p->pt = NULL**/\ + if (p->pt && !(p->flag&HAF_COUNT_REFINE)) MALLOC(s->buf[i].b, m);\ + else MALLOC(s->buf[i].a, m);\ + }\ + if (p->opt->w == 1) { /** enumerate all k-mers**/\ + int i;\ + for (i = 0; i < s->n_seq; ++i) {\ + if (p->opt->is_HPC)\ + sf##_count_seq_buf_HPC(s->buf, p->opt->k, p->opt->pre, s->len[i], s->seq[i]);\ + else\ + sf##_count_seq_buf(s->buf, p->opt->k, p->opt->pre, s->len[i], s->seq[i]);\ + if (!p->is_store) free(s->seq[i]);\ + }\ + } else { /** minimizers only**/\ + uint32_t j;\ + /**s->n_seq is how many reads at this buffer**/\ + /**s->mz && s->mz_buf are lists of minimzer vectors**/\ + CALLOC(s->mz, s->n_seq); CALLOC(s->mz_buf, p->opt->n_thread); CALLOC(s->mt, p->opt->n_thread);\ + /**calculate minimzers for each read, each read corresponds to one thread**/\ + kt_for(p->opt->n_thread, sf##_worker_for_mz, s, s->n_seq);\ + for (i = 0; i < p->opt->n_thread; ++i) free(s->mt[i].a), free(s->mz_buf[i].a);\ + free(s->mt), free(s->mz_buf);\ + /**insert minimizers**/\ + if (p->pt && !(p->flag&HAF_COUNT_REFINE)) {/**insert whole minimizer**/\ + for (i = 0; i < s->n_seq; ++i)\ + for (j = 0; j < s->mz[i].n; ++j)\ + sf##_pt_insert_buf(s->buf, p->opt->pre, &s->mz[i].a[j]);\ + } else {/**just insert the hash key of minimizer**/\ + for (i = 0; i < s->n_seq; ++i)\ + for (j = 0; j < s->mz[i].n; ++j)\ + sf##_ct_insert_buf(s->buf, p->opt->pre, s->mz[i].a[j].x);\ + }\ + for (i = 0; i < s->n_seq; ++i) {\ + p->n_mz += s->mz[i].n;\ + free(s->mz[i].a);\ + if (!p->is_store) free(s->seq[i]);\ + }\ + free(s->mz);\ + }\ + /**just clean seq**/\ + free(s->seq); free(s->len);\ + s->seq = 0, s->len = 0;\ + return s;\ + } else if (step == 2) { /** step 3: insert k-mers to hash table**/\ + sf##_st_data_t *s = (sf##_st_data_t*)in;\ + int i, n = 1<opt->pre;uint64_t n_ins = 0;\ + /**for 0-th counting, p->pt = NULL**/\ + kt_for(p->opt->n_thread, sf##_worker_for_insert, s, n);\ + /**n_ins is number of distinct k-mers**/\ + for (i = 0; i < n; ++i) {\ + n_ins += s->buf[i].n_ins;\ + if (p->pt && !(p->flag&HAF_COUNT_REFINE)) free(s->buf[i].b);\ + else free(s->buf[i].a);\ + }\ + if (p->ct) p->ct->tot += n_ins, p->ct->bs += s->sum_len;\ + if (p->pt) p->pt->tot_pos += n_ins;\ + free(s->buf);\ + free(s);\ + }\ + return 0;\ +} + +MZ_TEST_INIT(mz1, ha_mz1_t, ha_mz1_v, ha_idxpos_t, a) +MZ_TEST_INIT(mz2, ha_mzl_t, ha_mzl_v, ha_idxposl_t, al) + + +void debug_adapter(const hifiasm_opt_t *asm_opt, All_reads *rs) +{ + int ret; + uint32_t i, m, pass, unpass; + gzFile fp = 0; + kseq_t *ks = NULL; + UC_Read ucr; + init_UC_Read(&ucr); + + for (i = m = pass = unpass = 0; i < (uint32_t)asm_opt->num_reads; ++i) + { + if ((fp = gzopen(asm_opt->read_file_names[i], "r")) == 0) continue; + ks = kseq_init(fp); + while ((ret = kseq_read(ks)) >= 0) + { + int l = ks->seq.l; + if((l - asm_opt->adapterLen*2) <= 0) continue; + recover_UC_Read(&ucr, rs, m); + fprintf(stderr, "l: %d, ucr.length: %lld, asm_opt->adapterLen: %d\n", + l, ucr.length, asm_opt->adapterLen); + if(memcmp(ucr.seq, ks->seq.s+asm_opt->adapterLen, ucr.length) == 0) + { + pass++; + } + else + { + unpass++; + } + m++; + } + kseq_destroy(ks); + gzclose(fp); + ks = NULL; + fp = 0; + } + + destory_UC_Read(&ucr); + + fprintf(stderr, "[M::%s::# reads: %u, # pass: %u, # unpass: %u\n]", __func__, m, pass, unpass); + exit(1); +} + +static ha_ct_t *yak_count(const yak_copt_t *opt, const char *fn, int flag, ha_pt_t *p0, ha_ct_t *c0, const void *flt_tab, All_reads *rs, ma_utg_v *us, int64_t *n_seq, uint8_t ifq) +{ + ///for 0-th counting, flag = HAF_COUNT_ALL|HAF_RS_WRITE_LEN|HAF_CREATE_NEW + int read_rs = (rs && (flag & HAF_RS_READ)); + int ug_rs = (us && (flag & HAF_UG_READ)); + pl_data_t pl; + gzFile fp = 0; + memset(&pl, 0, sizeof(pl_data_t)); + pl.n_seq = *n_seq; pl.ifq = ifq; + if(ug_rs) { + pl.us_in = us; + } else if (read_rs) { + pl.rs_in = rs; + init_UC_Read(&pl.ucr); + } else {///for 0-th counting, go into here + if ((fp = gzopen(fn, "r")) == 0) return 0; + pl.ks = kseq_init(fp); + } + ///for 0-th counting, read all reads into pl.rs_out + if (rs && (flag & (HAF_RS_WRITE_LEN|HAF_RS_WRITE_SEQ))) + pl.rs_out = rs; + ///for 0-th counting, flt_tab = NULL + ///for 1-th counting, flt_tab = NULL + pl.flt_tab = flt_tab; + pl.opt = opt; + pl.flag = flag; + if (p0) {///for 1-th counting, p0 = NULL + pl.pt = p0, pl.create_new = 0; // never create new elements in a position table + assert(p0->k == opt->k && p0->pre == opt->pre); + } else if (c0) { + pl.ct = c0, pl.create_new = !!(flag&HAF_CREATE_NEW); + assert(c0->k == opt->k && c0->pre == opt->pre); + } else {///for ft-th counting and 1-th counting, go into here + pl.create_new = 1; // alware create new elements if the count table is empty + ///for 0-th counting, opt.k = 51, opt->pre = 12, opt->bf_n_hash = 4, opt.bf_shift = 37 + ///for 1-th counting, opt.k = 51, opt->pre = 12, opt->bf_n_hash = 4, opt.bf_shift = 0 + ///building a large hash table consisting of 4096 small hash tables + pl.ct = ha_ct_init(opt->k, opt->pre, opt->bf_n_hash, opt->bf_shift); + } + if(pl.ct) pl.ct->bs = 0; + if(ug_rs) kt_pipeline(3, mz2_worker_count, &pl, 3); + else kt_pipeline(3, mz1_worker_count, &pl, 3); + if (read_rs) { + destory_UC_Read(&pl.ucr); + } else if(!read_rs && !ug_rs) { + kseq_destroy(pl.ks); + gzclose(fp); + } + *n_seq = pl.n_seq; + if (pl.opt->w > 1) fprintf(stderr, "[M::%s] collected %ld minimizers\n", __func__, (long)pl.n_mz); + return pl.ct; +} + +ha_ct_t *ha_count(const hifiasm_opt_t *asm_o, int flag, int HPC, int k, int w, ha_pt_t *p0, const void *flt_tab, All_reads *rs, ma_utg_v *us, int keep_adapter, int *low_freq, int unique_only) +{ + int i; + int64_t n_seq = 0; + uint64_t n_bs = 0; + yak_copt_t opt; + ha_ct_t *h = 0; + assert(!(flag & HAF_RS_WRITE_LEN) || !(flag & HAF_RS_WRITE_SEQ)); // not both + ///for 0-th counting, flag = HAF_COUNT_ALL|HAF_RS_WRITE_LEN + if (rs) { + if (flag & HAF_RS_WRITE_LEN) + init_All_reads(rs); + else if (flag & HAF_RS_WRITE_SEQ) + malloc_All_reads(rs); + } + yak_copt_init(&opt); + opt.k = k; + opt.is_HPC = HPC; + ///for ft-counting, shoud be 1 + opt.w = flag & HAF_COUNT_ALL? 1 : w; + ///for ft-counting, shoud be 37 + ///for ha_pt_gen, shoud be 0 + opt.bf_shift = flag & HAF_COUNT_EXACT? 0 : asm_o->bf_shift; + opt.n_thread = asm_o->thread_num; + opt.adaLen = (keep_adapter? asm_o->adapterLen : 0); + opt.min_rcnt = (low_freq?*low_freq:-1); + opt.uq = (unique_only?1:0); + + n_bs = 0; + ///pending for integration + /** + if(rs && asm_o->ar && asm_o->ul_mod) { + for (i = 0; i < asm_o->ar->n; ++i){ + h = yak_count(&opt, asm_o->ar->a[i], flag|HAF_CREATE_NEW, p0, h, flt_tab, rs, us, &n_seq); + if(h) n_bs += h->bs; + } + }**/ + ///asm_opt->num_reads is the number of fastq files + for (i = 0; i < (us?1:asm_o->num_reads); ++i){ + h = yak_count(&opt, asm_o->read_file_names[i], flag|HAF_CREATE_NEW, p0, h, flt_tab, rs, us, &n_seq, asm_opt.is_sc); + if(h) n_bs += h->bs; + } + + if((rs) && (flag & HAF_RS_WRITE_LEN) && (asm_opt.is_sc)) { + rs->tqn = rs->total_reads; rs->tr[0] = rs->total_reads_bases; + } + + if((asm_o->hf) && (!us)) { + for (i = 0; i < asm_o->hf->n; ++i) { + h = yak_count(&opt, asm_o->hf->a[i], flag|HAF_CREATE_NEW, p0, h, flt_tab, rs, us, &n_seq, 0); + if(h) n_bs += h->bs; + } + } + if((rs) && (flag & HAF_RS_WRITE_LEN) && (asm_opt.is_sc)) { + rs->tr[1] = rs->total_reads_bases - rs->tr[0]; + } + + // fprintf(stderr, "[M::%s]\t# tqn::%lu, Ont base::%lu, # HiFi bases::%lu\n", __func__, R_INF.tqn, R_INF.tr[0], R_INF.tr[1]); + + if(h) h->bs = n_bs; + if (h && opt.bf_shift > 0) + ha_ct_destroy_bf(h); + return h; +} + +/*************************** + * High count filter table * + ***************************/ + +// Warning: the max count is 32767 +KHASHL_MAP_INIT(static klib_unused, yak_ft_t, yak_ft, uint64_t, int16_t, kh_hash_dummy, kh_eq_generic) + +static yak_ft_t *gen_hh(const ha_ct_t *h, int max_cnt) +{ + int i; + yak_ft_t *hh; + if (max_cnt > YAK_MAX_COUNT - 1) max_cnt = YAK_MAX_COUNT - 1; + if (max_cnt > INT16_MAX - 1) max_cnt = INT16_MAX - 1; + hh = yak_ft_init(); + yak_ft_resize(hh, h->tot * 2); + for (i = 0; i < 1<pre; ++i) { + yak_ct_t *ht = h->h[i].h; + khint_t k, l; + for (k = 0; k < kh_end(ht); ++k) { + if (kh_exist(ht, k)) { + uint64_t y = kh_key(ht, k) >> h->pre << YAK_COUNTER_BITS | i; + int absent; + l = yak_ft_put(hh, y, &absent); + if (absent) { + int cnt = kh_key(ht, k) & YAK_MAX_COUNT; + kh_val(hh, l) = cnt > max_cnt? INT16_MAX : cnt; + } + } + } + } + return hh; +} + +int32_t ha_ft_cnt(const void *hh, uint64_t y) +{ + yak_ft_t *h = (yak_ft_t*)hh; + khint_t k; + k = yak_ft_get(h, y); + return k == kh_end(h)? 0 : kh_val(h, k) == INT16_MAX? INT32_MAX : kh_val(h, k); +} + +void ha_ft_destroy(void *h) +{ + if (h) yak_ft_destroy((yak_ft_t*)h); +} + + +void debug_ct_index(void* q_ct_idx, void* r_ct_idx) +{ + ha_ct_t* ct_idx = (ha_ct_t*)q_ct_idx; + yak_ct_t *g = NULL; + uint64_t i; + khint_t k; + for (i = 0; (int)i < 1<pre; i++) + { + g = ct_idx->h[i].h; + for (k = 0; k < kh_end(g); ++k) + { + if (kh_exist(g, k)) + { + int c = kh_key(g, k) & YAK_MAX_COUNT; + uint64_t hash = ((kh_key(g, k) >> ct_idx->pre)<pre) | i; + int q = query_ct_index(r_ct_idx, hash); + if(q!=c) + { + fprintf(stderr, "ERROR:c: %d, q: %d\n", c, q); + } + } + } + } +} + +/************************* + * High-level interfaces * + *************************/ +void *ha_ft_ul_gen(const hifiasm_opt_t *asm_opt, ma_utg_v *us, int k, int w, int cutoff) +{ + yak_ft_t *flt_tab; + ha_ct_t *h; + ///HAF_COUNT_EXACT ---> no bf; HAF_COUNT_ALL ---> no minimizer + h = ha_count(asm_opt, HAF_COUNT_ALL|HAF_UG_READ, !(asm_opt->flag&HA_F_NO_HPC), k, w, NULL, NULL, NULL, us, 0, NULL, 0); + + // cutoff = (int)(asm_opt->hom_cov * asm_opt->high_factor); + if (cutoff > YAK_MAX_COUNT - 1) cutoff = YAK_MAX_COUNT - 1; + // fprintf(stderr, "[M::%s::] cutoff->%d\n\n", __func__, cutoff); + ha_ct_shrink(h, cutoff, YAK_MAX_COUNT, asm_opt->thread_num); + flt_tab = gen_hh(h, asm_opt->max_kmer_cnt); + ha_ct_destroy(h); + fprintf(stderr, "[M::%s::%.3f*%.2f@%.3fGB] ==> filtered out %ld k-mers occurring %d or more times\n", __func__, + yak_realtime(), yak_cpu_usage(), yak_peakrss_in_gb(), (long)kh_size(flt_tab), cutoff); + return (void*)flt_tab; +} + +void *ha_ft_ug_gen(const hifiasm_opt_t *asm_opt, ma_utg_v *us, int is_HPC, int k, int w, int min_freq, int max_freq) +{ + yak_ft_t *flt_tab; + ha_ct_t *h; + ///HAF_COUNT_EXACT ---> no bf; HAF_COUNT_ALL ---> no minimizer + h = ha_count(asm_opt, HAF_COUNT_ALL|HAF_UG_READ|HAF_COUNT_EXACT, is_HPC, k, w, NULL, NULL, NULL, us, 0, NULL, 0); + ha_ct_shrink(h, min_freq, max_freq>YAK_MAX_COUNT-1?YAK_MAX_COUNT-1:max_freq, asm_opt->thread_num); + flt_tab = gen_hh(h, YAK_MAX_COUNT); + ha_ct_destroy(h); + return (void*)flt_tab; +} + +void *ha_ft_gen(const hifiasm_opt_t *asm_opt, All_reads *rs, int *hom_cov, int is_hp_mode, int read_from_store) +{ + yak_ft_t *flt_tab; + int64_t cnt[YAK_N_COUNTS]; + int peak_hom, peak_het, cutoff = YAK_MAX_COUNT - 1, ex_flag = 0; + if(is_hp_mode) ex_flag = HAF_RS_READ|HAF_SKIP_READ; + ha_ct_t *h; + h = ha_count(asm_opt, HAF_COUNT_ALL|ex_flag|((read_from_store)?(HAF_RS_READ):(HAF_RS_WRITE_LEN)), !(asm_opt->flag&HA_F_NO_HPC), asm_opt->k_mer_length, asm_opt->mz_win, NULL, NULL, rs, NULL, 1, NULL, 0); + if((asm_opt->flag & HA_F_VERBOSE_GFA) || (asm_opt->restart)) + { + write_ct_index((void*)h, asm_opt->output_file_name); + // load_ct_index(&ha_ct_table, asm_opt->output_file_name); + // debug_ct_index((void*)h, ha_ct_table); + // debug_ct_index(ha_ct_table, (void*)h); + // ha_ct_destroy((ha_ct_t *)ha_ct_table); + } + + if(!(ex_flag & HAF_SKIP_READ)) + { + ha_ct_hist(h, cnt, asm_opt->thread_num); + peak_hom = ha_analyze_count(YAK_N_COUNTS, asm_opt->min_hist_kmer_cnt, asm_opt->hg_size>0?(h->bs/asm_opt->hg_size):(-1), cnt, &peak_het); + ///r850 + fprintf(stderr, "[M::%s::auto] inferred peak_hom: %d; peak_het: %d\n", __func__, peak_hom, peak_het); + if((asm_opt->het_cov_ss > 0) || (asm_opt->hmo_cov_ss > 0)) { + fprintf(stderr, "[M::%s::user] override requested peak_hom: %ld; peak_het: %ld\n", __func__, asm_opt->hmo_cov_ss, asm_opt->het_cov_ss); + if(asm_opt->hmo_cov_ss > 0) peak_hom = asm_opt->hmo_cov_ss; + if(asm_opt->het_cov_ss > 0) peak_het = asm_opt->het_cov_ss; + } + if (hom_cov) *hom_cov = peak_hom; + if (peak_hom > 0) fprintf(stderr, "[M::%s::final] using peak_hom: %d; peak_het: %d\n", __func__, peak_hom, peak_het); + + ///in default, asm_opt->high_factor = 5.0 + ///r833 + cutoff = (int)(peak_hom * asm_opt->high_factor); + if(cutoff < asm_opt->hf_cutoff) cutoff = asm_opt->hf_cutoff; + if (cutoff > YAK_MAX_COUNT - 1) cutoff = YAK_MAX_COUNT - 1; + } + ha_ct_shrink(h, cutoff, YAK_MAX_COUNT, asm_opt->thread_num); + flt_tab = gen_hh(h, asm_opt->max_kmer_cnt); + ha_ct_destroy(h); + fprintf(stderr, "[M::%s::%.3f*%.2f@%.3fGB] ==> filtered out %ld k-mers occurring %d or more times\n", __func__, + yak_realtime(), yak_cpu_usage(), yak_peakrss_in_gb(), (long)kh_size(flt_tab), cutoff); + return (void*)flt_tab; +} + +ha_pt_t *ha_pt_ul_gen(const hifiasm_opt_t *asm_opt, const void *flt_tab, ma_utg_v *us, int k, int w, int cutoff) +{ + ha_ct_t *ct; + ha_pt_t *pt; + ///HAF_COUNT_EXACT: no bf + ct = ha_count(asm_opt, HAF_COUNT_EXACT|HAF_UG_READ, !(asm_opt->flag&HA_F_NO_HPC), k, w, NULL, flt_tab, NULL, us, 0, NULL, 0); + fprintf(stderr, "[M::%s::%.3f*%.2f] ==> counted %ld distinct minimizer k-mers\n", __func__, + yak_realtime(), yak_cpu_usage(), (long)ct->tot); + ///minimizer with YAK_MAX_COUNT occ may apper > YAK_MAX_COUNT times, so it may lead to overflow at ha_pt_gen + if (flt_tab == 0) { + if (cutoff > YAK_MAX_COUNT - 1) cutoff = YAK_MAX_COUNT - 1; + ha_ct_shrink(ct, /**2**/1, cutoff, asm_opt->thread_num); + } else { + ///Note: here is just to remove minimizer appearing YAK_MAX_COUNT times + ///minimizer with YAK_MAX_COUNT occ may apper > YAK_MAX_COUNT times, so it may lead to overflow at ha_pt_gen + ha_ct_shrink(ct, /**2**/1, YAK_MAX_COUNT - 1, asm_opt->thread_num); + } + + pt = ha_pt_gen(ct, asm_opt->thread_num, 1); + ha_count(asm_opt, HAF_COUNT_EXACT|HAF_UG_READ, !(asm_opt->flag&HA_F_NO_HPC), k, w, pt, flt_tab, NULL, us, 0, NULL, 0); + //ha_pt_sort(pt, asm_opt->thread_num); + fprintf(stderr, "[M::%s::%.3f*%.2f] ==> indexed %ld positions\n", __func__, + yak_realtime(), yak_cpu_usage(), (long)pt->tot_pos); + return pt; +} + +ha_pt_t *ha_pt_ug_gen(const hifiasm_opt_t *asm_opt, const void *flt_tab, ma_utg_v *us, int is_HPC, int k, int w, int min_freq) +{ + ha_ct_t *ct; + ha_pt_t *pt; + ///HAF_COUNT_EXACT: no bf + ct = ha_count(asm_opt, HAF_COUNT_EXACT|HAF_UG_READ, is_HPC, k, w, NULL, flt_tab, NULL, us, 0, NULL, 1); + fprintf(stderr, "[M::%s::%.3f*%.2f] ==> counted %ld distinct minimizer k-mers\n", __func__, + yak_realtime(), yak_cpu_usage(), (long)ct->tot); + ///minimizer with YAK_MAX_COUNT occ may apper > YAK_MAX_COUNT times, so it may lead to overflow at ha_pt_gen + ha_ct_shrink(ct, min_freq, YAK_MAX_COUNT - 1, asm_opt->thread_num); + + pt = ha_pt_gen(ct, asm_opt->thread_num, 1); + ha_count(asm_opt, HAF_COUNT_EXACT|HAF_UG_READ, is_HPC, k, w, pt, flt_tab, NULL, us, 0, NULL, 1); + //ha_pt_sort(pt, asm_opt->thread_num); + fprintf(stderr, "[M::%s::%.3f*%.2f] ==> indexed %ld positions\n", __func__, + yak_realtime(), yak_cpu_usage(), (long)pt->tot_pos); + return pt; +} + +ha_pt_t *ha_pt_gen_dp(const hifiasm_opt_t *asm_opt, ha_ct_t *ct, int flag, int n_thread, const void *flt_tab, All_reads *rs, int peak_hom, int peak_het) +{ + int low_freq = mz_low_b(peak_hom, peak_het); + ha_pt_t *pt = ha_pt_gen_count(ct, n_thread); ///key = cnt, val = 0 + ha_count(asm_opt, HAF_COUNT_EXACT|HAF_COUNT_REFINE|flag, !(asm_opt->flag&HA_F_NO_HPC), asm_opt->k_mer_length, asm_opt->mz_win, pt, flt_tab, rs, NULL, 1, &low_freq, 0); + uint64_t occ = ha_pt_shrink(pt, n_thread); + if(flag&HAF_RS_WRITE_LEN) flag -= HAF_RS_WRITE_LEN; + if(flag&HAF_RS_WRITE_SEQ) flag -= HAF_RS_WRITE_SEQ; + flag |= HAF_RS_READ; pt->tot_pos = 0; + ha_count(asm_opt, HAF_COUNT_EXACT|flag, !(asm_opt->flag&HA_F_NO_HPC), asm_opt->k_mer_length, asm_opt->mz_win, pt, flt_tab, rs, NULL, 1, NULL, 0); + // fprintf(stderr, "[M::%s::] counted %lu distinct minimizer k-mers\n", __func__, pt->tot); + // fprintf(stderr, "[M::%s::] collected %lu minimizers\n\n\n", __func__, pt->tot_pos); + assert(occ == pt->tot_pos); + return pt; +} + +ha_pt_t *ha_pt_gen(const hifiasm_opt_t *asm_opt, const void *flt_tab, int read_from_store, int is_hp_mode, All_reads *rs, int *hom_cov, int *het_cov) +{ + int64_t cnt[YAK_N_COUNTS], tot_cnt; + int peak_hom, peak_het, i, extra_flag1, extra_flag2; + ha_ct_t *ct; + ha_pt_t *pt; + if (read_from_store) {///if reads have already been read + extra_flag1 = extra_flag2 = HAF_RS_READ; + } else if (rs->total_reads == 0) {///if reads & length have not been scanned + extra_flag1 = HAF_RS_WRITE_LEN; + extra_flag2 = HAF_RS_WRITE_SEQ; + } else {///if length has been loaded but reads have not + extra_flag1 = HAF_RS_WRITE_SEQ; + extra_flag2 = HAF_RS_READ; + } + if(is_hp_mode) extra_flag1 |= HAF_SKIP_READ, extra_flag2 |= HAF_SKIP_READ; + + ct = ha_count(asm_opt, HAF_COUNT_EXACT|extra_flag1, !(asm_opt->flag&HA_F_NO_HPC), asm_opt->k_mer_length, asm_opt->mz_win, NULL, flt_tab, rs, NULL, 1, NULL, 0); + fprintf(stderr, "[M::%s::%.3f*%.2f] ==> counted %ld distinct minimizer k-mers\n", __func__, + yak_realtime(), yak_cpu_usage(), (long)ct->tot); + ha_ct_hist(ct, cnt, asm_opt->thread_num); + fprintf(stderr, "[M::%s] count[%d] = %ld (for sanity check)\n", __func__, YAK_MAX_COUNT, (long)cnt[YAK_MAX_COUNT]); + peak_hom = ha_analyze_count(YAK_N_COUNTS, asm_opt->min_hist_kmer_cnt, asm_opt->hg_size>0?(ct->bs/asm_opt->hg_size):(-1), cnt, &peak_het); + ///r850 + fprintf(stderr, "[M::%s::auto] inferred peak_hom: %d; peak_het: %d\n", __func__, peak_hom, peak_het); + if((asm_opt->het_cov_ss > 0) || (asm_opt->hmo_cov_ss > 0)) { + fprintf(stderr, "[M::%s::user] override requested peak_hom: %ld; peak_het: %ld\n", __func__, asm_opt->hmo_cov_ss, asm_opt->het_cov_ss); + if(asm_opt->hmo_cov_ss > 0) peak_hom = asm_opt->hmo_cov_ss; + if(asm_opt->het_cov_ss > 0) peak_het = asm_opt->het_cov_ss; + } + if (hom_cov) *hom_cov = peak_hom; + if (het_cov) *het_cov = peak_het; + if (peak_hom > 0) fprintf(stderr, "[M::%s::final] using peak_hom: %d; peak_het: %d\n", __func__, peak_hom, peak_het); + ///here ha_ct_shrink is mostly used to remove k-mer appearing only 1 time + if (flt_tab == 0) { + int cutoff = (int)(peak_hom * asm_opt->high_factor); + if (cutoff > YAK_MAX_COUNT - 1) cutoff = YAK_MAX_COUNT - 1; + if((extra_flag1 & HAF_SKIP_READ) && (extra_flag2 & HAF_SKIP_READ)) cutoff = YAK_MAX_COUNT - 1; + ha_ct_shrink(ct, 2, cutoff, asm_opt->thread_num); + for (i = 2, tot_cnt = 0; i <= cutoff; ++i) tot_cnt += cnt[i] * i; + } else { + ///Note: here is just to remove minimizer appearing YAK_MAX_COUNT times + ///minimizer with YAK_MAX_COUNT occ may apper > YAK_MAX_COUNT times, so it may lead to overflow at ha_pt_gen + ha_ct_shrink(ct, 2, YAK_MAX_COUNT - 1, asm_opt->thread_num); + for (i = 2, tot_cnt = 0; i <= YAK_MAX_COUNT - 1; ++i) tot_cnt += cnt[i] * i; + } + if(!(asm_opt->flag & HA_F_FAST)) + { + fprintf(stderr, "[M::%s::] counting in normal mode\n", __func__); + pt = ha_pt_gen(ct, asm_opt->thread_num, 0); + ha_count(asm_opt, HAF_COUNT_EXACT|extra_flag2, !(asm_opt->flag&HA_F_NO_HPC), asm_opt->k_mer_length, asm_opt->mz_win, pt, flt_tab, rs, NULL, 1, NULL, 0); + assert((uint64_t)tot_cnt == pt->tot_pos); + } + else + { + fprintf(stderr, "[M::%s::] counting in fast mode\n", __func__); + pt = ha_pt_gen_dp(asm_opt, ct, HAF_COUNT_EXACT|extra_flag2, asm_opt->thread_num, flt_tab, rs, peak_hom, peak_het); + } + //ha_pt_sort(pt, asm_opt->thread_num); + fprintf(stderr, "[M::%s::%.3f*%.2f] ==> indexed %ld positions, counted %ld distinct minimizer k-mers\n", __func__, + yak_realtime(), yak_cpu_usage(), (long)pt->tot_pos, (long)pt->tot); + return pt; +} + +int query_ct_index(void* ct_idx, uint64_t hash) +{ + ha_ct1_t *g = &(((ha_ct_t*)ct_idx)->h[hash & ((1ULL<<((ha_ct_t*)ct_idx)->pre) - 1)]); + khint_t k; + k = yak_ct_get(g->h, hash); + if (k == kh_end(g->h)) return 0; + return ((kh_key(g->h, k)&YAK_MAX_COUNT)==YAK_MAX_COUNT)?-1:(kh_key(g->h, k)&YAK_MAX_COUNT); +} + +int write_ct_index(void *i_ct_idx, char* file_name) +{ + char* gfa_name = (char*)malloc(strlen(file_name)+25); + sprintf(gfa_name, "%s.ct_flt", file_name); + FILE* fp = fopen(gfa_name, "w"); + if (!fp) { + free(gfa_name); + return 0; + } + ha_ct_t* ct_idx = (ha_ct_t*)i_ct_idx; + int i; + ha_ct1_t *g; + fwrite(&ct_idx->k, sizeof(ct_idx->k), 1, fp); + fwrite(&ct_idx->pre, sizeof(ct_idx->pre), 1, fp); + fwrite(&ct_idx->n_hash, sizeof(ct_idx->n_hash), 1, fp); + fwrite(&ct_idx->n_shift, sizeof(ct_idx->n_shift), 1, fp); + fwrite(&ct_idx->tot, sizeof(ct_idx->tot), 1, fp); + for (i = 0; i < 1<pre; i++) + { + g = &(ct_idx->h[i]); + yak_ct_save(g->h, fp); + } + + + fprintf(stderr, "[M::%s] Index has been written.\n", __func__); + free(gfa_name); + fclose(fp); + return 1; +} + +int load_ct_index(void **i_ct_idx, char* file_name) +{ + char* gfa_name = (char*)malloc(strlen(file_name)+25); + sprintf(gfa_name, "%s.ct_flt", file_name); + FILE* fp = fopen(gfa_name, "r"); + if (!fp) { + free(gfa_name); + return 0; + } + ha_ct_t** ct_idx = (ha_ct_t**)i_ct_idx; + double index_time = 0; + uint64_t flag = 0; + int i; + ha_ct_t *h = 0; + ha_ct1_t *g; + CALLOC(h, 1); + + flag += fread(&h->k, sizeof(h->k), 1, fp); + flag += fread(&h->pre, sizeof(h->pre), 1, fp); + flag += fread(&h->n_hash, sizeof(h->n_hash), 1, fp); + flag += fread(&h->n_shift, sizeof(h->n_shift), 1, fp); + flag += fread(&h->tot, sizeof(h->tot), 1, fp); + CALLOC(h->h, 1<pre); + + + index_time = yak_realtime(); + for (i = 0; i < 1<pre; ++i) + { + g = &(h->h[i]); + yak_ct_load(&(g->h), fp); + } + + (*ct_idx) = h; + fprintf(stderr, "[M::%s::%.3f] ==> Loaded count table\n", __func__, yak_realtime() - index_time); + fprintf(stderr, "[M::%s] Index has been loaded.\n", __func__); + free(gfa_name); + return 1; +} + +int write_pt_index(void *flt_tab, ha_pt_t *ha_idx, All_reads* r, hifiasm_opt_t* opt, char* file_name) +{ + char* gfa_name = (char*)malloc(strlen(file_name)+64); + if(r) sprintf(gfa_name, "%s.pt_flt", file_name); + else sprintf(gfa_name, "%s.pt_flt.bin", file_name); + FILE* fp = fopen(gfa_name, "w"); + if (!fp) { + free(gfa_name); + return 0; + } + yak_ft_t *ha_flt_tab = (yak_ft_t*)flt_tab; + + if(ha_flt_tab) + { + fwrite("f", 1, 1, fp); + yak_ft_save(ha_flt_tab, fp); + } + + + if(ha_idx) + { + int i; + ha_pt1_t *g; + fwrite("h", 1, 1, fp); + fwrite(&ha_idx->k, sizeof(ha_idx->k), 1, fp); + fwrite(&ha_idx->pre, sizeof(ha_idx->pre), 1, fp); + fwrite(&ha_idx->tot, sizeof(ha_idx->tot), 1, fp); + fwrite(&ha_idx->tot_pos, sizeof(ha_idx->tot_pos), 1, fp); + + for (i = 0; i < 1<pre; ++i) + { + g = &(ha_idx->h[i]); + yak_pt_save(g->h, fp); + fwrite(&g->n, sizeof(g->n), 1, fp); + fwrite(g->a, sizeof(ha_idxpos_t), g->n, fp); + } + } + + fwrite(&opt->number_of_round, sizeof(opt->number_of_round), 1, fp); + fwrite(&opt->hom_cov, sizeof(opt->hom_cov), 1, fp); + fwrite(&opt->het_cov, sizeof(opt->het_cov), 1, fp); + fwrite(&opt->max_n_chain, sizeof(opt->max_n_chain), 1, fp); + + if(r) { + write_All_reads(r, gfa_name); + + sprintf(gfa_name, "%s.pt_flt.paf.bin", file_name); + fclose(fp); fp = fopen(gfa_name, "w"); uint64_t k; + if (!fp) { + free(gfa_name); + return 0; + } + fwrite(&(r->total_reads), sizeof(r->total_reads), 1, fp); + for (k = 0; k < r->total_reads; k++) { + fwrite(&(r->paf[k].is_fully_corrected), sizeof(r->paf[k].is_fully_corrected), 1, fp); + fwrite(&(r->paf[k].is_abnormal), sizeof(r->paf[k].is_abnormal), 1, fp); + fwrite(&(r->paf[k].length), sizeof(r->paf[k].length), 1, fp); + fwrite(r->paf[k].buffer, sizeof((*(r->paf[k].buffer))), r->paf[k].length, fp); + } + } + + fprintf(stderr, "[M::%s] Index has been written.\n", __func__); + free(gfa_name); + fclose(fp); + return 1; +} + +int load_pt_index(void **r_flt_tab, ha_pt_t **r_ha_idx, All_reads *r, hifiasm_opt_t* opt, char* file_name) +{ + char* gfa_name = (char*)malloc(strlen(file_name)+64); + if(r) sprintf(gfa_name, "%s.pt_flt", file_name); + else sprintf(gfa_name, "%s.pt_flt.bin", file_name); + // fprintf(stderr, "[M::%s]\tgfa_name::%s\n", __func__, gfa_name); + FILE* fp = fopen(gfa_name, "r"); + if (!fp) { + free(gfa_name); + return 0; + } + + ha_pt_t *ha_idx = NULL; + char mode = 0; + int f_flag = 0, absent, i; + double index_time, index_s_time, pos_time, pos_s_time; + + + + f_flag += fread(&mode, 1, 1, fp); + if(mode == 'f') + { + index_time = yak_realtime(); + + yak_ft_load((yak_ft_t **)r_flt_tab, fp); + + f_flag += fread(&mode, 1, 1, fp); + + fprintf(stderr, "[M::%s::%.3f] ==> Loaded flt table\n", __func__, yak_realtime()-index_time); + } + ///insert using multiple threads??? + if(mode == 'h') + { + pos_time = index_time = 0; + + CALLOC(ha_idx, 1); + ha_pt1_t *g; + f_flag += fread(&ha_idx->k, sizeof(ha_idx->k), 1, fp); + f_flag += fread(&ha_idx->pre, sizeof(ha_idx->pre), 1, fp); + f_flag += fread(&ha_idx->tot, sizeof(ha_idx->tot), 1, fp); + f_flag += fread(&ha_idx->tot_pos, sizeof(ha_idx->tot_pos), 1, fp); + CALLOC(ha_idx->h, 1<pre); + for (i = 0; i < 1<pre; ++i) + { + index_s_time = yak_realtime(); + + g = &(ha_idx->h[i]); + yak_pt_load(&(g->h), fp); + + index_time += yak_realtime() - index_s_time; + + pos_s_time = yak_realtime(); + + f_flag += fread(&g->n, sizeof(g->n), 1, fp); + MALLOC(g->a, g->n); + f_flag += fread(g->a, sizeof(ha_idxpos_t), g->n, fp); + + pos_time += yak_realtime() - pos_s_time; + } + (*r_ha_idx) = ha_idx; + + fprintf(stderr, "[M::%s::%.3f(index)/%.3f(pos)] ==> Loaded pos table\n", __func__, index_time, pos_time); + } + + if(mode != 'h' && mode != 'f') + { + free(gfa_name); + fclose(fp); + return 0; + } + + + f_flag += fread(&absent, sizeof(absent), 1, fp); + if(absent != opt->number_of_round) + { + fprintf(stderr, "ERROR: different number of rounds!\n"); + exit(1); + } + + f_flag += fread(&opt->hom_cov, sizeof(opt->hom_cov), 1, fp); + f_flag += fread(&opt->het_cov, sizeof(opt->het_cov), 1, fp); + f_flag += fread(&opt->max_n_chain, sizeof(opt->max_n_chain), 1, fp); + + + // fclose(fp); + if(r) { + if(!load_All_reads(r, gfa_name)) { + free(gfa_name); + return 0; + } + + memset(r->trio_flag, AMBIGU, r->total_reads*sizeof(uint8_t)); + + sprintf(gfa_name, "%s.pt_flt.paf.bin", file_name); + fclose(fp); fp = fopen(gfa_name, "r"); uint64_t k; + if (!fp) { + free(gfa_name); + return 0; + } + f_flag += fread(&(r->total_reads), sizeof(r->total_reads), 1, fp); + r->paf = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*r->total_reads); + r->reverse_paf = (ma_hit_t_alloc*)malloc(sizeof(ma_hit_t_alloc)*r->total_reads); + for (k = 0; k < r->total_reads; k++) { + // init_ma_hit_t_alloc(&(r->paf[k])); + init_ma_hit_t_alloc(&(r->reverse_paf[k])); + + f_flag += fread(&(r->paf[k].is_fully_corrected), sizeof(r->paf[k].is_fully_corrected), 1, fp); + f_flag += fread(&(r->paf[k].is_abnormal), sizeof(r->paf[k].is_abnormal), 1, fp); + f_flag += fread(&(r->paf[k].length), sizeof(r->paf[k].length), 1, fp); + r->paf[k].size = r->paf[k].length; + + r->paf[k].buffer = NULL; + if(r->paf[k].length == 0) continue; + + r->paf[k].buffer = (ma_hit_t*)malloc(sizeof(ma_hit_t)*r->paf[k].length); + fread(r->paf[k].buffer, sizeof((*(r->paf[k].buffer))), r->paf[k].length, fp); + } + } + fclose(fp); + + fprintf(stderr, "[M::%s] Index has been loaded.\n", __func__); + + free(gfa_name); + return 1; +} + +void refresh_pt_idx(void **flt_tab, ha_pt_t **ha_idx, All_reads *r, hifiasm_opt_t *opt, char *file_name, uint8_t is_w) +{ + char* gfa_name = (char*)malloc(strlen(file_name)+64); + sprintf(gfa_name, "%s.ad", file_name); + + if(is_w) { + write_pt_index(*flt_tab, *ha_idx, NULL, opt, gfa_name); + } else { + load_pt_index(flt_tab, ha_idx, NULL, opt, gfa_name); + } + + free(gfa_name); +} + + +uint64_t tmp_pt_pro(void **r_flt_tab, ha_pt_t **r_ha_idx, All_reads *r, hifiasm_opt_t *opt, char *file_name, uint64_t rr, uint64_t tot_rr, uint64_t is_load) +{ + char* gfa_name = (char*)malloc(strlen(file_name)+64); + FILE *fp = NULL; int f_flag = 0; uint64_t rr0 = (uint64_t)-1, tot_rr0 = (uint64_t)-1; + + + if(is_load) { + sprintf(gfa_name, "%s.r%lu.ht.bin", file_name, rr); + fp = fopen(gfa_name, "r"); + if (!fp) { + free(gfa_name); + return 0; + } + f_flag += fread(&rr0, sizeof(rr0), 1, fp); + f_flag += fread(&tot_rr0, sizeof(tot_rr0), 1, fp); + fclose(fp); + if(rr0 != rr || tot_rr0 != tot_rr) { + free(gfa_name); + return 0; + } + + + + sprintf(gfa_name, "%s.r%lu", file_name, rr); + if(!load_pt_index(r_flt_tab, r_ha_idx, r, opt, gfa_name)) { + free(gfa_name); + return 0; + } + } else { + sprintf(gfa_name, "%s.r%lu", file_name, rr); + write_pt_index(*r_flt_tab, *r_ha_idx, r, opt, gfa_name); + + + + sprintf(gfa_name, "%s.r%lu.ht.bin", file_name, rr); + fp = fopen(gfa_name, "w"); + if (!fp) { + free(gfa_name); + return 0; + } + fwrite(&rr, sizeof(rr), 1, fp); + fwrite(&tot_rr, sizeof(tot_rr), 1, fp); + fclose(fp); + } + + free(gfa_name); + return 1; +} + + + +int uidx_write(void *flt_tab, ha_pt_t *ha_idx, char* file_name, ma_ug_t *ug) +{ + char* gfa_name = (char*)malloc(strlen(file_name)+25); + sprintf(gfa_name, "%s.uidx.bin", file_name); + FILE* fp = fopen(gfa_name, "w"); + if (!fp) { + free(gfa_name); + return 0; + } + + if(ug) write_dbug(ug, fp); + + yak_ft_t *ha_flt_tab = (yak_ft_t*)flt_tab; + + if(ha_flt_tab) + { + fwrite("f", 1, 1, fp); + yak_ft_save(ha_flt_tab, fp); + } + + if(ha_idx) + { + int i; + ha_pt1_t *g; + fwrite("h", 1, 1, fp); + fwrite(&ha_idx->k, sizeof(ha_idx->k), 1, fp); + fwrite(&ha_idx->pre, sizeof(ha_idx->pre), 1, fp); + fwrite(&ha_idx->tot, sizeof(ha_idx->tot), 1, fp); + fwrite(&ha_idx->tot_pos, sizeof(ha_idx->tot_pos), 1, fp); + + for (i = 0; i < 1<pre; ++i) + { + g = &(ha_idx->h[i]); + yak_pt_save(g->h, fp); + fwrite(&g->n, sizeof(g->n), 1, fp); + fwrite(g->al, sizeof(ha_idxposl_t), g->n, fp); + } + } + fprintf(stderr, "[M::%s] Index has been written.\n", __func__); + free(gfa_name); + fclose(fp); + return 1; +} + + +int uidx_load(void **r_flt_tab, ha_pt_t **r_ha_idx, char* file_name, ma_ug_t *ug) +{ + char* gfa_name = (char*)malloc(strlen(file_name)+25); + sprintf(gfa_name, "%s.uidx.bin", file_name); + FILE* fp = fopen(gfa_name, "r"); + if (!fp) { + free(gfa_name); + return 0; + } + + if(ug && (!test_dbug(ug, fp))) { + fprintf(stderr, "[M::%s] Renew UL Index\n", __func__); + free(gfa_name); fclose(fp); + return 0; + } + // fprintf(stderr, "[M::%s]\t%s\tftell::%ld\n", __func__, file_name, ftell(fp)); + + ha_pt_t *ha_idx = NULL; + char mode = 0; + int f_flag = 0, i; + double index_time, index_s_time, pos_time, pos_s_time; + + + + f_flag += fread(&mode, 1, 1, fp); + if(mode == 'f') + { + index_time = yak_realtime(); + + yak_ft_load((yak_ft_t **)r_flt_tab, fp); + + f_flag += fread(&mode, 1, 1, fp); + + fprintf(stderr, "[M::%s::%.3f] ==> Loaded flt table\n", __func__, yak_realtime()-index_time); + } + ///insert using multiple threads??? + if(mode == 'h') + { + pos_time = index_time = 0; + + CALLOC(ha_idx, 1); + ha_pt1_t *g; + f_flag += fread(&ha_idx->k, sizeof(ha_idx->k), 1, fp); + f_flag += fread(&ha_idx->pre, sizeof(ha_idx->pre), 1, fp); + f_flag += fread(&ha_idx->tot, sizeof(ha_idx->tot), 1, fp); + f_flag += fread(&ha_idx->tot_pos, sizeof(ha_idx->tot_pos), 1, fp); + CALLOC(ha_idx->h, 1<pre); + for (i = 0; i < 1<pre; ++i) + { + index_s_time = yak_realtime(); + + g = &(ha_idx->h[i]); + yak_pt_load(&(g->h), fp); + + index_time += yak_realtime() - index_s_time; + + pos_s_time = yak_realtime(); + + f_flag += fread(&g->n, sizeof(g->n), 1, fp); + MALLOC(g->al, g->n); + f_flag += fread(g->al, sizeof(ha_idxposl_t), g->n, fp); + + pos_time += yak_realtime() - pos_s_time; + } + (*r_ha_idx) = ha_idx; + + fprintf(stderr, "[M::%s::%.3f(index)/%.3f(pos)] ==> Loaded pos table\n", __func__, index_time, pos_time); + } + + if(mode != 'h' && mode != 'f') + { + free(gfa_name); + fclose(fp); + return 0; + } + + fprintf(stderr, "[M::%s] Index has been loaded.\n", __func__); + + fclose(fp); + free(gfa_name); + return 1; +} diff --git a/htab.h b/htab.h index d17f812..425dd07 100644 --- a/htab.h +++ b/htab.h @@ -1,190 +1,193 @@ -#ifndef __HA_HTAB_H__ -#define __HA_HTAB_H__ -#define __STDC_LIMIT_MACROS -#include -#include "Process_Read.h" -#include "CommandLines.h" - -typedef struct { - size_t n, m; - uint64_t *a; -} st_mt_t; - -typedef struct { - uint64_t x; ///x is the hash key - ///rid is the read id, pos is the end pos of this minimizer, rev is the direction - ///span is the length of this k-mer. For non-HPC k-mer, span may not be equal to k - uint64_t rid:28, pos:27, rev:1, span:8; -} ha_mz1_t; - -typedef struct { - uint64_t rid:28, pos:27, rev:1, span:8; // actually it is not necessary to keep span in the index -} ha_idxpos_t; - -typedef struct { uint32_t n, m; ha_mz1_t *a; } ha_mz1_v; - -typedef struct { - uint64_t x; ///x is the hash key - uint64_t rid:31, rev:1, pos:32; - uint8_t span; -} ha_mzl_t; - -typedef struct { - uint64_t rid:31, rev:1, pos:32; - uint8_t span; -} ha_idxposl_t; - -typedef struct { uint32_t n, m; ha_mzl_t *a; } ha_mzl_v; - -typedef struct { // a simplified version of kdq - int front, count; - int a[64]; -} tiny_queue_t; - -static inline void tq_push(tiny_queue_t *q, int x) -{ - q->a[((q->count++) + q->front) & 0x3f] = x; -} - -static inline int tq_shift(tiny_queue_t *q) -{ - int x; - if (q->count == 0) return -1; - x = q->a[q->front++]; - q->front &= 0x3f; - --q->count; - return x; -} - -struct ha_pt_s; -typedef struct ha_pt_s ha_pt_t; - -struct ha_abuf_s; -typedef struct ha_abuf_s ha_abuf_t; - -struct ha_abufl_s; -typedef struct ha_abufl_s ha_abufl_t; - -extern const unsigned char seq_nt4_table[256]; -extern void *ha_flt_tab; -extern ha_pt_t *ha_idx; -extern void *ha_flt_tab_hp; -extern ha_pt_t *ha_idx_hp; -extern void *ha_ct_table; - -void *ha_ft_ul_gen(const hifiasm_opt_t *asm_opt, ma_utg_v *us, int k, int w, int cutoff); -void *ha_ft_ug_gen(const hifiasm_opt_t *asm_opt, ma_utg_v *us, int is_HPC, int k, int w, int min_freq, int max_freq); -void *ha_ft_gen(const hifiasm_opt_t *asm_opt, All_reads *rs, int *hom_cov, int is_hp_mode, int read_from_store); -int32_t ha_ft_cnt(const void *hh, uint64_t y); -void ha_ft_destroy(void *h); - -ha_pt_t *ha_pt_ul_gen(const hifiasm_opt_t *asm_opt, const void *flt_tab, ma_utg_v *us, int k, int w, int cutoff); -ha_pt_t *ha_pt_ug_gen(const hifiasm_opt_t *asm_opt, const void *flt_tab, ma_utg_v *us, int is_HPC, int k, int w, int min_freq); -ha_pt_t *ha_pt_gen(const hifiasm_opt_t *asm_opt, const void *flt_tab, int read_from_store, int is_hp_mode, All_reads *rs, int *hom_cov, int *het_cov); -void ha_pt_destroy(ha_pt_t *h); -const ha_idxpos_t *ha_pt_get(const ha_pt_t *h, uint64_t hash, int *n); -const ha_idxposl_t *ha_ptl_get(const ha_pt_t *h, uint64_t hash, int *n); -const int ha_pt_cnt(const ha_pt_t *h, uint64_t hash); - -int write_pt_index(void *flt_tab, ha_pt_t *ha_idx, All_reads* r, hifiasm_opt_t* opt, char* file_name); -int load_pt_index(void **r_flt_tab, ha_pt_t **r_ha_idx, All_reads* r, hifiasm_opt_t* opt, char* file_name); -int uidx_write(void *flt_tab, ha_pt_t *ha_idx, char* file_name, ma_ug_t *ug); -int uidx_load(void **r_flt_tab, ha_pt_t **r_ha_idx, char* file_name, ma_ug_t *ug); -int write_ct_index(void *ct_idx, char* file_name); -int load_ct_index(void **ct_idx, char* file_name); -int query_ct_index(void* ct_idx, uint64_t hash); - -ha_abuf_t *ha_abuf_init_buf(void *km); -ha_abufl_t *ha_abufl_init_buf(void *km); -void ha_abuf_destroy_buf(void *km, ha_abuf_t *ab); -void ha_abufl_destroy_buf(void *km, ha_abufl_t *ab); -void ha_abufl_free_buf(void *km, ha_abufl_t *ab, int is_z); -ha_abuf_t *ha_abuf_init(void); -void ha_abuf_destroy(ha_abuf_t *ab); -uint64_t ha_abuf_mem(const ha_abuf_t *ab); -ha_abufl_t *ha_abufl_init(void); -void ha_abufl_destroy(ha_abufl_t *ab); -uint64_t ha_abufl_mem(const ha_abufl_t *ab); - -double yak_cputime(void); -void yak_reset_realtime(void); -double yak_realtime_0(void); -double yak_realtime(void); -long yak_peakrss(void); -double yak_peakrss_in_gb(void); -double yak_cpu_usage(void); - -void ha_triobin(const hifiasm_opt_t *opt); -uint32_t test_yak_binning(char* fn, char *cmd); -uint32_t *ha_polybin_list(const hifiasm_opt_t *opt); - -void mz1_ha_sketch(const char *str, int len, int w, int k, uint32_t rid, int is_hpc, ha_mz1_v *p, const void *hf, int sample_dist, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, ha_pt_t *pt, int min_freq, int32_t dp_min_len, float dp_e, st_mt_t *mt, int32_t ws, int32_t is_unique, void *km); -void mz2_ha_sketch(const char *str, int len, int w, int k, uint32_t rid, int is_hpc, ha_mzl_v *p, const void *hf, int sample_dist, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, ha_pt_t *pt, int min_freq, int32_t dp_min_len, float dp_e, st_mt_t *mt, int32_t ws, int32_t is_unique, void *km); -int ha_analyze_count(int n_cnt, int start_cnt, int m_peak_hom, const int64_t *cnt, int *peak_het); -int adj_m_peak_hom(int m_peak_hom, int max_i, int max2_i, int max3_i, int *peak_het); -void print_hist_lines(int n_cnt, int start_cnt, const int64_t *cnt); -void debug_adapter(const hifiasm_opt_t *asm_opt, All_reads *rs); - - -inline int mz_low_b(int peak_hom, int peak_het) -{ - int low_freq = 2; - if(peak_het > 0) low_freq = peak_het/2; - else if(peak_hom > 0) low_freq = peak_hom/4; - if(low_freq < 2) low_freq = 2; - return low_freq; -} - -static inline uint64_t yak_hash64(uint64_t key, uint64_t mask) // invertible integer hash function -{ - key = (~key + (key << 21)) & mask; // key = (key << 21) - key - 1; - key = key ^ key >> 24; - key = ((key + (key << 3)) + (key << 8)) & mask; // key * 265 - key = key ^ key >> 14; - key = ((key + (key << 2)) + (key << 4)) & mask; // key * 21 - key = key ^ key >> 28; - key = (key + (key << 31)) & mask; - return key; -} - -static inline uint64_t yak_hash64_64(uint64_t key) -{ - key = ~key + (key << 21); - key = key ^ key >> 24; - key = (key + (key << 3)) + (key << 8); - key = key ^ key >> 14; - key = (key + (key << 2)) + (key << 4); - key = key ^ key >> 28; - key = key + (key << 31); - return key; -} - -static inline uint64_t yak_hash_long(uint64_t x[4]) -{ - ///compare forward k-mer and reverse complementary strand - int j = x[1] < x[3]? 0 : 1; - return yak_hash64_64(x[j<<1|0]) + yak_hash64_64(x[j<<1|1]); -} - -#define CALLOC(ptr, len) ((ptr) = (__typeof__(ptr))calloc((len), sizeof(*(ptr)))) -#define MALLOC(ptr, len) ((ptr) = (__typeof__(ptr))malloc((len) * sizeof(*(ptr)))) -#define REALLOC(ptr, len) ((ptr) = (__typeof__(ptr))realloc((ptr), (len) * sizeof(*(ptr)))) -#define MEMCPY(dest, src, len) (memcpy((dest), (src), (len) * sizeof(*(src)))) - -#ifndef kroundup32 -#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) -#endif - -#ifndef kroundup64 -#define kroundup64(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, x|=(x)>>32, ++(x)) -#endif - -#ifndef klib_unused -#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) -#define klib_unused __attribute__ ((__unused__)) -#else -#define klib_unused -#endif -#endif /* klib_unused */ - -#endif // __YAK_H__ +#ifndef __HA_HTAB_H__ +#define __HA_HTAB_H__ +#define __STDC_LIMIT_MACROS +#include +#include "Process_Read.h" +#include "CommandLines.h" + +typedef struct { + size_t n, m; + uint64_t *a; +} st_mt_t; + +typedef struct { + uint64_t x; ///x is the hash key + ///rid is the read id, pos is the end pos of this minimizer, rev is the direction + ///span is the length of this k-mer. For non-HPC k-mer, span may not be equal to k + uint64_t rid:28, pos:27, rev:1, span:8; +} ha_mz1_t; + +typedef struct { + uint64_t rid:28, pos:27, rev:1, span:8; // actually it is not necessary to keep span in the index +} ha_idxpos_t; + +typedef struct { uint32_t n, m; ha_mz1_t *a; } ha_mz1_v; + +typedef struct { + uint64_t x; ///x is the hash key + uint64_t rid:31, rev:1, pos:32; + uint8_t span; +} ha_mzl_t; + +typedef struct { + uint64_t rid:31, rev:1, pos:32; + uint8_t span; +} ha_idxposl_t; + +typedef struct { uint32_t n, m; ha_mzl_t *a; } ha_mzl_v; + +typedef struct { // a simplified version of kdq + int front, count; + int a[64]; +} tiny_queue_t; + +static inline void tq_push(tiny_queue_t *q, int x) +{ + q->a[((q->count++) + q->front) & 0x3f] = x; +} + +static inline int tq_shift(tiny_queue_t *q) +{ + int x; + if (q->count == 0) return -1; + x = q->a[q->front++]; + q->front &= 0x3f; + --q->count; + return x; +} + +struct ha_pt_s; +typedef struct ha_pt_s ha_pt_t; + +struct ha_abuf_s; +typedef struct ha_abuf_s ha_abuf_t; + +struct ha_abufl_s; +typedef struct ha_abufl_s ha_abufl_t; + +extern const unsigned char seq_nt4_table[256]; +extern void *ha_flt_tab; +extern ha_pt_t *ha_idx; +extern void *ha_flt_tab_hp; +extern ha_pt_t *ha_idx_hp; +extern void *ha_ct_table; + +void *ha_ft_ul_gen(const hifiasm_opt_t *asm_opt, ma_utg_v *us, int k, int w, int cutoff); +void *ha_ft_ug_gen(const hifiasm_opt_t *asm_opt, ma_utg_v *us, int is_HPC, int k, int w, int min_freq, int max_freq); +void *ha_ft_gen(const hifiasm_opt_t *asm_opt, All_reads *rs, int *hom_cov, int is_hp_mode, int read_from_store); +int32_t ha_ft_cnt(const void *hh, uint64_t y); +void ha_ft_destroy(void *h); + +ha_pt_t *ha_pt_ul_gen(const hifiasm_opt_t *asm_opt, const void *flt_tab, ma_utg_v *us, int k, int w, int cutoff); +ha_pt_t *ha_pt_ug_gen(const hifiasm_opt_t *asm_opt, const void *flt_tab, ma_utg_v *us, int is_HPC, int k, int w, int min_freq); +ha_pt_t *ha_pt_gen(const hifiasm_opt_t *asm_opt, const void *flt_tab, int read_from_store, int is_hp_mode, All_reads *rs, int *hom_cov, int *het_cov); +void ha_pt_destroy(ha_pt_t *h); +const ha_idxpos_t *ha_pt_get(const ha_pt_t *h, uint64_t hash, int *n); +const ha_idxposl_t *ha_ptl_get(const ha_pt_t *h, uint64_t hash, int *n); +const int ha_pt_cnt(const ha_pt_t *h, uint64_t hash); + +int write_pt_index(void *flt_tab, ha_pt_t *ha_idx, All_reads* r, hifiasm_opt_t* opt, char* file_name); +int load_pt_index(void **r_flt_tab, ha_pt_t **r_ha_idx, All_reads* r, hifiasm_opt_t* opt, char* file_name); +void refresh_pt_idx(void **flt_tab, ha_pt_t **ha_idx, All_reads *r, hifiasm_opt_t *opt, char *file_name, uint8_t is_w); +int uidx_write(void *flt_tab, ha_pt_t *ha_idx, char* file_name, ma_ug_t *ug); +int uidx_load(void **r_flt_tab, ha_pt_t **r_ha_idx, char* file_name, ma_ug_t *ug); +int write_ct_index(void *ct_idx, char* file_name); +int load_ct_index(void **ct_idx, char* file_name); +int query_ct_index(void* ct_idx, uint64_t hash); +uint64_t tmp_pt_pro(void **r_flt_tab, ha_pt_t **r_ha_idx, All_reads *r, hifiasm_opt_t *opt, char *file_name, uint64_t rr, uint64_t tot_rr, uint64_t is_load); + +ha_abuf_t *ha_abuf_init_buf(void *km); +ha_abufl_t *ha_abufl_init_buf(void *km); +void ha_abuf_destroy_buf(void *km, ha_abuf_t *ab); +void ha_abufl_destroy_buf(void *km, ha_abufl_t *ab); +void ha_abufl_free_buf(void *km, ha_abufl_t *ab, int is_z); +ha_abuf_t *ha_abuf_init(void); +void ha_abuf_destroy(ha_abuf_t *ab); +uint64_t ha_abuf_mem(const ha_abuf_t *ab); +ha_abufl_t *ha_abufl_init(void); +void ha_abufl_destroy(ha_abufl_t *ab); +uint64_t ha_abufl_mem(const ha_abufl_t *ab); + +double yak_cputime(void); +void yak_reset_realtime(void); +double yak_realtime_0(void); +double yak_realtime(void); +long yak_peakrss(void); +double yak_peakrss_in_gb(void); +double yak_cpu_usage(void); + +void ha_triobin(const hifiasm_opt_t *opt); +uint32_t test_yak_binning(char* fn, char *cmd); +uint32_t *ha_polybin_list(const hifiasm_opt_t *opt); +uint32_t *ha_charbin_list(const hifiasm_opt_t *opt, uint8_t **idx, uint32_t *idx_n); + +void mz1_ha_sketch(const char *str, int len, int w, int k, uint32_t rid, int is_hpc, ha_mz1_v *p, const void *hf, int sample_dist, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, ha_pt_t *pt, int min_freq, int32_t dp_min_len, float dp_e, st_mt_t *mt, int32_t ws, int32_t is_unique, void *km); +void mz2_ha_sketch(const char *str, int len, int w, int k, uint32_t rid, int is_hpc, ha_mzl_v *p, const void *hf, int sample_dist, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, ha_pt_t *pt, int min_freq, int32_t dp_min_len, float dp_e, st_mt_t *mt, int32_t ws, int32_t is_unique, void *km); +int ha_analyze_count(int n_cnt, int start_cnt, int m_peak_hom, const int64_t *cnt, int *peak_het); +int adj_m_peak_hom(int m_peak_hom, int max_i, int max2_i, int max3_i, int *peak_het); +void print_hist_lines(int n_cnt, int start_cnt, const int64_t *cnt); +void debug_adapter(const hifiasm_opt_t *asm_opt, All_reads *rs); + + +inline int mz_low_b(int peak_hom, int peak_het) +{ + int low_freq = 2; + if(peak_het > 0) low_freq = peak_het/2; + else if(peak_hom > 0) low_freq = peak_hom/4; + if(low_freq < 2) low_freq = 2; + return low_freq; +} + +static inline uint64_t yak_hash64(uint64_t key, uint64_t mask) // invertible integer hash function +{ + key = (~key + (key << 21)) & mask; // key = (key << 21) - key - 1; + key = key ^ key >> 24; + key = ((key + (key << 3)) + (key << 8)) & mask; // key * 265 + key = key ^ key >> 14; + key = ((key + (key << 2)) + (key << 4)) & mask; // key * 21 + key = key ^ key >> 28; + key = (key + (key << 31)) & mask; + return key; +} + +static inline uint64_t yak_hash64_64(uint64_t key) +{ + key = ~key + (key << 21); + key = key ^ key >> 24; + key = (key + (key << 3)) + (key << 8); + key = key ^ key >> 14; + key = (key + (key << 2)) + (key << 4); + key = key ^ key >> 28; + key = key + (key << 31); + return key; +} + +static inline uint64_t yak_hash_long(uint64_t x[4]) +{ + ///compare forward k-mer and reverse complementary strand + int j = x[1] < x[3]? 0 : 1; + return yak_hash64_64(x[j<<1|0]) + yak_hash64_64(x[j<<1|1]); +} + +#define CALLOC(ptr, len) ((ptr) = ((((len)*sizeof(*(ptr))) <= 9223372036854775807)?((__typeof__(ptr))calloc((len), sizeof(*(ptr)))):(NULL))) +#define MALLOC(ptr, len) ((ptr) = (__typeof__(ptr))malloc((len) * sizeof(*(ptr)))) +#define REALLOC(ptr, len) ((ptr) = (__typeof__(ptr))realloc((ptr), (len) * sizeof(*(ptr)))) +#define MEMCPY(dest, src, len) (memcpy((dest), (src), (len) * sizeof(*(src)))) + +#ifndef kroundup32 +#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) +#endif + +#ifndef kroundup64 +#define kroundup64(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, x|=(x)>>32, ++(x)) +#endif + +#ifndef klib_unused +#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) +#define klib_unused __attribute__ ((__unused__)) +#else +#define klib_unused +#endif +#endif /* klib_unused */ + +#endif // __YAK_H__ diff --git a/inter.cpp b/inter.cpp index 60cbe0e..e70d29b 100644 --- a/inter.cpp +++ b/inter.cpp @@ -1,22978 +1,22978 @@ -#include -#include -#include -#include -#include -#include "kseq.h" // FASTA/Q parser -#include "kavl.h" -#include "khash.h" -#include "kalloc.h" -#include "kthread.h" -#include "inter.h" -#include "Overlaps.h" -#include "CommandLines.h" -#include "htab.h" -#include "Hash_Table.h" -#include "Correct.h" -#include "Process_Read.h" -#include "Assembly.h" -#include "hic.h" -#include "gfa_ut.h" -KSEQ_INIT(gzFile, gzread) - -#define oreg_xe_lt(a, b) (((uint64_t)(a).x_pos_e<<32|(a).x_pos_s) < ((uint64_t)(b).x_pos_e<<32|(b).x_pos_s)) -KSORT_INIT(or_xe, overlap_region, oreg_xe_lt) - -#define u_trans_qs_key0(a) ((a).qs) -KRADIX_SORT_INIT(u_trans_qs0, u_trans_t, u_trans_qs_key0, member_size(u_trans_t, qs)) - -void ha_get_ul_candidates_interface(ha_abufl_t *ab, int64_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, overlap_region_alloc *overlap_list_hp, Candidates_list *cl, double bw_thres, - int max_n_chain, int keep_whole_chain, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* chain_idx, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t high_occ, void *km); -void ul_map_lchain(ha_abufl_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, - int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut); -int64_t ug_map_lchain(ha_abufl_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, double bw_thres_sec, - int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, - uint32_t gen_off, double mcopy_rate, uint32_t mcopy_khit_cut, uint32_t is_hpc, ha_mzl_t *res, uint64_t res_n, ha_mzl_t *idx, uint64_t idx_n, uint64_t mzl_cutoff, uint64_t chain_cutoff, kv_u_trans_t *kov); -int64_t ug_map_lchain_simple(ha_abufl_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, - int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, - uint32_t gen_off, double mcopy_rate, uint32_t mcopy_khit_cut, uint32_t is_hpc, ha_mzl_t *res, uint64_t res_n, ha_mzl_t *idx, uint64_t idx_n, uint64_t mzl_cutoff, uint64_t chain_cutoff); - -#define MG_SEED_IGNORE (1ULL<<41) -#define MG_SEED_TANDEM (1ULL<<42) -#define MG_SEED_KEPT (1ULL<<43) - -#define MG_MAX_SEG 255 -#define MG_SEED_SEG_SHIFT 48 -#define MG_SEED_SEG_MASK (0xffULL<<(MG_SEED_SEG_SHIFT)) -#define mg_seg_id(a) ((int32_t)(((a).y&MG_SEED_SEG_MASK) >> MG_SEED_SEG_SHIFT)) - -#define MG_SEED_WT_SHIFT 56 -#define MG_MAX_SHORT_K 15 - -#define MG_SHORT_K_EXT 10000 ///1000 in minigraph - -#define GC_OFFSET_RATE 0.0001 -#define GC_OFFSET_POS 8 - -#define SEC_LEN_DIF 0.03 -#define REA_ALIGN_CUTOFF 32 -#define CHUNK_SIZE 1000000000 - -#define GBIN_K 31 -#define GBIN_W 31 -#define GBIN_E 0.04 -#define GBIN_BE 0.005 -#define GBIN_ME 4 -///GBIN_L -> for the length of one HiFi read -// #define GBIN_L 15000 -#define GBIN_L 256 - -#define FREE_BATCH 16 - -#define generic_key(x) (x) -KRADIX_SORT_INIT(gfa64, uint64_t, generic_key, 8) - -#define generic_key(x) (x) -KRADIX_SORT_INIT(gfa64i, int64_t, generic_key, 8) - -#define ul_ov_srt_qe_key(p) ((p).qe) -KRADIX_SORT_INIT(ul_ov_srt_qe, ul_ov_t, ul_ov_srt_qe_key, member_size(ul_ov_t, qe)) - -#define ul_ov_srt_qs_key(p) ((p).qs) -KRADIX_SORT_INIT(ul_ov_srt_qs, ul_ov_t, ul_ov_srt_qs_key, member_size(ul_ov_t, qs)) - -#define ul_ov_srt_tn_key(p) ((p).tn) -KRADIX_SORT_INIT(ul_ov_srt_tn, ul_ov_t, ul_ov_srt_tn_key, member_size(ul_ov_t, tn)) - -#define ul_ov_srt_qn_key(p) ((p).qn) -KRADIX_SORT_INIT(ul_ov_srt_qn, ul_ov_t, ul_ov_srt_qn_key, member_size(ul_ov_t, qn)) - -#define utg_ct_t_x_key(p) ((p).x) -KRADIX_SORT_INIT(utg_ct_t_x_srt, utg_ct_t, utg_ct_t_x_key, member_size(utg_ct_t, x)) - -#define utg_ct_t_s_key(p) ((p).s) -KRADIX_SORT_INIT(utg_ct_t_s_srt, utg_ct_t, utg_ct_t_s_key, member_size(utg_ct_t, s)) - -#define hap_ev_cov_key(x) ((x).cov) -KRADIX_SORT_INIT(hap_ev_cov_srt, haplotype_evdience, hap_ev_cov_key, member_size(haplotype_evdience, cov)) - -#define uc_block_t_qe_key(x) ((x).qe) -KRADIX_SORT_INIT(uc_block_t_qe_srt, uc_block_t, uc_block_t_qe_key, member_size(uc_block_t, qe)); - -#define uc_block_t_qs_key(x) ((x).qs) -KRADIX_SORT_INIT(uc_block_t_qs_srt, uc_block_t, uc_block_t_qs_key, member_size(uc_block_t, qs)); - -#define hpc_ss_t_s_key(p) ((p).s) -KRADIX_SORT_INIT(hpc_ss_t_s, hpc_ss_t, hpc_ss_t_s_key, member_size(hpc_ss_t, s)) - -typedef struct { - char *a; - size_t n, m; -}mul_buf_t; - -typedef struct { - mul_buf_t *a; - size_t n, m; -}mul_debug_prt_t; - -mul_debug_prt_t *init_mul_debug_prt_t(uint64_t n) -{ - mul_debug_prt_t *p; CALLOC(p, 1); - CALLOC(p->a, n); p->n = p->m = n; - return p; -} - -void print_mul_debug_prt_t(const char *nn, mul_debug_prt_t *p) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+70); - sprintf(gfa_name, "%s.ul.vlog", nn); - FILE* fp = fopen(gfa_name, "w"); free(gfa_name); - if (!fp) return; - uint32_t k; - for (k = 0; k < p->n; k++) { - if(p->a[k].n) { - kv_push(char, p->a[k], '\0'); - fprintf(fp, "%s", p->a[k].a); - } - } - fclose(fp); -} - -void print_raw_uls_seq_direct(const ma_ug_t *ug, all_ul_t *aln, const char *nn) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+70); - sprintf(gfa_name, "%s.init.raw.integer.seq.log", nn); - FILE* fp = fopen(gfa_name, "w"); free(gfa_name); - if (!fp) return; - uint64_t id; uc_block_t *a = NULL; int64_t k, a_n; - for (id = 0; id < aln->n; id++) { - a = aln->a[id].bb.a; a_n = aln->a[id].bb.n; k = 0; - if(a_n == 0) continue; - fprintf(fp,"%.*s\tid::%lu\t", (int32_t)aln->nid.a[id].n, aln->nid.a[id].a, id); - // for (k = 0; k < a_n && ug_occ_w(a[k].ts, a[k].te, &(ug->u.a[a[k].hid])) == 0; k++); - for (; k < a_n; k++) { - // if(ug_occ_w(a[k].ts, a[k].te, &(ug->u.a[a[k].hid])) == 0) break; - fprintf(fp, "utg%.6d%c(%c)\t", a[k].hid + 1, "lc"[ug->u.a[a[k].hid].circ], "+-"[a[k].rev]); - } - fprintf(fp,"\n"); - } - fclose(fp); -} - -void push_vlog(mul_buf_t *o, char *str) -{ - uint32_t str_l = strlen(str); - kv_resize(char, *o, str_l+o->n); - memcpy(o->a+o->n, str, str_l); o->n += str_l; -} - -// mul_debug_prt_t *overall_zdbg; - -mg_tbuf_t *mg_tbuf_init(void) -{ - mg_tbuf_t *b; - b = (mg_tbuf_t*)calloc(1, sizeof(mg_tbuf_t)); - b->km = km_init(); - return b; -} - -void mg_tbuf_destroy(mg_tbuf_t *b) -{ - if (b == 0) return; - if (b->km) km_destroy(b->km); - free(b); -} - -void *mg_tbuf_get_km(mg_tbuf_t *b) -{ - return b->km; -} - -typedef struct { - uint32_t v, d; - int32_t pre; -} mg_pathv_t; - -typedef struct { - int32_t qs, qe, rs, re; - uint32_t v; -} mg_coor_t; - -///mg128_t->y: weight(8)seg_id(8)flag(8)span(8)pos(32) -///mg128_t->x: rid(31)rev(1)pos(33); keep reference -typedef struct { uint64_t x, y; } mg128_t; -#define sort_key_128x(a) ((a).x) -KRADIX_SORT_INIT(128x, mg128_t, sort_key_128x, 8) -void radix_sort_128x(mg128_t *beg, mg128_t *end); - -#define mg_pathv_t_v_srt_key(x) ((x).v) -KRADIX_SORT_INIT(mg_pathv_t_v_srt, mg_pathv_t, mg_pathv_t_v_srt_key, member_size(mg_pathv_t, v)) -#define mg_pathv_t_d_srt_key(x) ((x).d) -KRADIX_SORT_INIT(mg_pathv_t_d_srt, mg_pathv_t, mg_pathv_t_d_srt_key, member_size(mg_pathv_t, d)) - - -typedef struct { // global data structure for kt_pipeline() - const void *ha_flt_tab; - const ha_pt_t *ha_idx; - const mg_idxopt_t *opt; - const ma_ug_t *ug; - const asg_t *rg; - const ug_opt_t *uopt; - const ul_idx_t *uu; - idx_emask_t *mm; - ucr_file_t *ucr_s; - kseq_t *ks; - int64_t chunk_size; - uint64_t n_thread; - uint64_t total_base; - uint64_t total_pair; - mg_gres_a hits; - mg_dbn_t nn; - uint64_t num_bases, num_corrected_bases, num_recorrected_bases; -} uldat_t; - -typedef struct { - uint64_t asm_size; - uint64_t asm_cov; -} mul_ov_t; - -///three levels: -///level-0: minimizers -///level-1: linear chains -///level-2: g chains -///gc[] saves the idx in lc[], lc saves the idx in a[] -typedef struct { - void *km; - int32_t n_gc, n_lc, n_a, rep_len; - mg_gchain_t *gc;///g_chain; idx in l_chains - mg_llchain_t *lc;///l_chain - mg128_t *a; // minimizer positions; see comments above mg_update_anchors() for details - uint64_t qid, qlen; -} mg_gchains_t; - -typedef struct { - uint32_t n; ///length of candidate list - uint64_t q_span:31, rev:1, q_pos:32; - uint32_t qid:16, weight:15, is_tandem:1; - const ha_idxposl_t *cr; ///candidate list -} mg_match_t; - -typedef struct { - uint64_t qse, rse, gld; -} lc_srt_t; - -#define lc_srt_key(p) ((p).qse) -KRADIX_SORT_INIT(lc_srt, lc_srt_t, lc_srt_key, member_size(lc_srt_t, qse)) - -typedef struct { - uint64_t x, e; - int32_t d; - uint32_t id; -} eg_srt_t; - -#define eg_srt_x_key(p) ((p).x) -KRADIX_SORT_INIT(eg_srt_x, eg_srt_t, eg_srt_x_key, member_size(eg_srt_t, x)) -#define eg_srt_d_key(p) ((p).d) -KRADIX_SORT_INIT(eg_srt_d, eg_srt_t, eg_srt_d_key, member_size(eg_srt_t, d)) - -// shortest path -typedef struct { - // input - ///(lj_ref_id)|(lj_ref_rev^1) - uint32_t v; - ///target_dist should like the overlap length in string graph - ///it should be used to evaluate if the identified path is close to real path/alignment - int32_t target_dist; - uint32_t target_hash; - ///inner: if li and lj are at the same ref id - ///meta: j - uint32_t meta:30, check_hash:1, inner:1; - /** - * There are two cases: - * (1) lj->qs************lj->qe - * li->qs************li->qe - * (2) lj->qs************lj->qe - * li->qs************li->qe - * qlen = li->qs - lj->qe;///might be negative - * **/ - int32_t qlen/**, so**/; - // output - uint32_t n_path:31, is_0:1;///I guess n_path is how many path from src to dest - int32_t path_end;///looks like an idx to alignment - int32_t dist, mlen; - uint32_t hash; - // aux - uint64_t srt_key; -} mg_path_dst_t; - -typedef struct { - uint32_t srt; - int32_t i; -} gc_frag_t; - -///I think this structure is just used for iteration -///iterate each ref id, instead of alignment id -typedef struct sp_node_s { - uint64_t di; // dist<<32 | node_id in avl tree(doesn't matter too much) - uint32_t v;///ref_id|rev - int32_t pre; - uint32_t hash;///hash is path hash, instead of node hash - int32_t is_0; - KAVL_HEAD(struct sp_node_s) head; -} sp_node_t, *sp_node_p; - -typedef struct { - int32_t k, mlen;//k: number of walks from src to this node - int32_t qs, qe; - sp_node_t *p[MG_MAX_SHORT_K]; // this forms a max-heap -} sp_topk_t; - -#define gc_frag_key(p) ((p).srt) -KRADIX_SORT_INIT(gc, gc_frag_t, gc_frag_key, 4) - -#define dst_key(p) ((p).srt_key) -KRADIX_SORT_INIT(dst, mg_path_dst_t, dst_key, 8) - -#define sp_node_cmp(a, b) (((a)->di > (b)->di) - ((a)->di < (b)->di)) -KAVL_INIT(sp, sp_node_t, head, sp_node_cmp) - -#define sp_node_lt(a, b) ((a)->di < (b)->di) -KSORT_INIT(sp, sp_node_p, sp_node_lt) - -KHASH_MAP_INIT_INT(sp, sp_topk_t) -KHASH_MAP_INIT_INT(sp2, uint64_t) - -typedef struct { - kv_ul_ov_t lo; - kv_ul_ov_t tk; - kv_rtrace_t tc; - kvec_t_u64_warp srt; -}glchain_t; - -typedef struct { - mg_path_dst_t *a; - size_t n, m; -}vec_mg_path_dst_t; - -typedef struct { - sp_node_t **a; - size_t n, m; -}vec_sp_node_t; - -typedef struct { - mg_pathv_t *a; - size_t n, m; -}vec_mg_pathv_t; - -typedef struct { - vec_mg_lchain_t l; - vec_mg_lchain_t swap; - vec_mg_path_dst_t dst; - vec_sp_node_t out; - vec_mg_pathv_t path; - kvec_t(uint64_t) v; - kvec_t(int64_t) f; - st_mt_t dst_done; -}gdpchain_t; - -typedef struct { // data structure for each step in kt_pipeline() - const mg_idxopt_t *opt; - const void *ha_flt_tab; - const ha_pt_t *ha_idx; - const ma_ug_t *ug; - const asg_t *rg; - const ug_opt_t *uopt; - const ul_idx_t *uu; - int n, m, sum_len; - uint64_t *len, id; - char **seq; - ha_mzl_v *mzs;///useless - st_mt_t *sps;///useless - mg_gchains_t **gcs;///useless - mg_tbuf_t **buf;///useless - ha_ovec_buf_t **hab; - glchain_t *ll; - gdpchain_t *gdp; - mask_ul_ov_t *mk; - idx_emask_t *mm; - // glchain_t *sec_ll; - uint64_t num_bases, num_corrected_bases, num_recorrected_bases; - int64_t n_thread; - scaf_res_t *rsc; -} utepdat_t; - -typedef struct { // global data structure for kt_pipeline() - utepdat_t *s; - ma_ug_t *qry; - scaf_res_t *qry_sc; - ma_ug_t *ref; - scaf_res_t *ref_sc; - ma_ug_t *gfa; - bubble_type *bub; - kv_u_trans_t *ta; - uint64_t mm; - uint64_t soff; - uint64_t is_exact; -} ctdat_t; - - -#define ha_mzl_t_key(p) ((p).x) -KRADIX_SORT_INIT(ha_mzl_t_srt, ha_mzl_t, ha_mzl_t_key, member_size(ha_mzl_t, x)) - -typedef struct { // global data structure for kt_pipeline() - ug_opt_t *uopt; - ma_ug_t *ug; - asg_t *rg; - ha_ovec_buf_t **hab; - glchain_t *ll; - bubble_type *bub; - int32_t w, k; - ///base-alignment - double bw_thres, diff_ec_ul, sec_cutoff; - double bw_thres_double, diff_ec_ul_double; - int32_t max_n_chain; - ha_mzl_v idx_a; - asg64_v idx_n; - ha_mzl_v srt_a; - int32_t is_HPC, bw, max_gap, chn_pen_gap, n_thread, is_cnt, is_ovlp, mini_cut, chain_cut, keep_unsymm_arc; - ul_idx_t udb; - kv_u_trans_t *filter; - uint32_t *free_cnt; - ug_rid_cov_t *ccov; -} ug_trans_t; - -typedef struct { // global data structure for kt_pipeline() - const ug_opt_t *uopt; - ma_ug_t *ug; - asg_t *rg; - ha_ovec_buf_t **hab; - glchain_t *ll; - int32_t w, k; - ///base-alignment - double bw_thres, diff_ov, diff_bin; - uint64_t min_bin_len, max_diff; - int32_t max_n_chain; - ha_mzl_v idx_a; - asg64_v idx_n; - ha_mzl_v srt_a; - int32_t is_HPC, bw, max_gap, chn_pen_gap, n_thread, is_cnt, is_ovlp, mini_cut, chain_cut, keep_unsymm_arc; - ul_idx_t udb; - // hpc_re_t *hre; - mask_ul_ov_t *mk; - idx_emask_t *mm; - // bit_mask_t *bm; -} ug_bin_t; - - -void hc_glchain_destroy(glchain_t *b) -{ - if (!b) return; - kv_destroy(b->lo); kv_destroy(b->tk); kv_destroy(b->srt.a); kv_destroy(b->tc); -} - - -void hc_gdpchain_destroy(gdpchain_t *b) -{ - if (!b) return; - kv_destroy(b->l); kv_destroy(b->swap); kv_destroy(b->dst); kv_destroy(b->out); - kv_destroy(b->path); kv_destroy(b->v); kv_destroy(b->f); kv_destroy(b->dst_done); -} - -void init_mg_opt(mg_idxopt_t *opt, int is_HPC, int k, int w, int hap_n, int max_n_chain, double bw_thres, -double diff_ec_ul, double diff_ec_ul_low, double diff_ec_ul_hpc, int ec_ul_round) -{ - opt->k = k; - opt->w = w; - opt->hap_n = hap_n; - opt->is_HPC = is_HPC; - opt->bw = 10000;///2000 in minigraph - opt->max_gap = 500000;///5000 in minigraph - opt->occ_weight = 20; - opt->max_gap_pre = 10000;///1000 in minigraph - opt->max_lc_iter = 10000; - opt->chn_pen_gap = 0.19;///using minimap2's value - opt->max_lc_skip = 25;// mo->max_gc_skip = 25; - opt->max_lc_iter = 10000; - opt->min_lc_cnt = 2; - opt->min_lc_score = 30; - opt->max_gc_skip = 25; - opt->ref_bonus = 0; - opt->mask_level = 0.5f; - opt->max_gc_seq_ext = 5; - opt->seed = 11; - opt->min_gc_cnt = 3, opt->min_gc_score = 50; - opt->sub_diff = 6; - opt->best_n = 5; - opt->pri_ratio = 0.8f; - opt->max_n_chain = max_n_chain; - opt->bw_thres = bw_thres; - opt->diff_ec_ul = diff_ec_ul; - opt->diff_ec_ul_low = diff_ec_ul_low; - opt->diff_ec_ul_hpc = diff_ec_ul_hpc; - opt->ec_ul_round = ec_ul_round; -} - -void uidx_l_build(ma_ug_t *ug, mg_idxopt_t *opt, int cutoff) -{ - ha_flt_tab = ha_ft_ul_gen(&asm_opt, &(ug->u), opt->k, opt->w, cutoff); - ha_idx = ha_pt_ul_gen(&asm_opt, ha_flt_tab, &(ug->u), opt->k, opt->w, cutoff); - fprintf(stderr, "[M::%s] Index has been built.\n", __func__); -} - -void uidx_build(ma_ug_t *ug, mg_idxopt_t *opt) -{ - int flag = asm_opt.flag; - asm_opt.flag |= HA_F_NO_HPC; - ha_flt_tab = ha_ft_ug_gen(&asm_opt, &(ug->u), opt->is_HPC, opt->k, opt->w, 1, opt->hap_n*5); - ha_idx = ha_pt_ug_gen(&asm_opt, ha_flt_tab, &(ug->u), opt->is_HPC, opt->k, opt->w, 1); - asm_opt.flag = flag; - fprintf(stderr, "[M::%s] Index has been built.\n", __func__); -} - -void uidx_destory() -{ - ha_ft_destroy(ha_flt_tab); - ha_pt_destroy(ha_idx); - ha_flt_tab = NULL; ha_idx = NULL; -} - -void mg_gres_a_des(mg_gres_a *p) -{ - uint64_t i = 0; - for (i = 0; i < p->n; i++){ - free(p->a[i].lc); free(p->a[i].gc); - } - free(p->a); -} - -///only use non-repetitive minimizers -static mg_match_t *collect_matches(void *km, int *_n_m, int max_occ, const void *ha_flt_tab, const ha_pt_t *ha_idx, int check_unique, const ha_mzl_v *mv, int64_t *n_a, int *rep_len, int *n_mini_pos, int32_t **mini_pos) -{ - int rep_st = 0, rep_en = 0, n_m, tn, tw; - size_t i; - mg_match_t *m; - *n_mini_pos = 0; - KMALLOC(km, *mini_pos, mv->n);///mv->n how many minimizers in query - m = (mg_match_t*)kmalloc(km, mv->n * sizeof(mg_match_t)); - for (i = 0, n_m = 0, *rep_len = 0, *n_a = 0; i < mv->n; ++i) { - const ha_idxposl_t *cr; - ha_mzl_t *z = &mv->a[i]; - cr = ha_ptl_get(ha_idx, z->x, &tn); - tw = ha_ft_cnt(ha_flt_tab, z->x); - if ((tw > max_occ) || (check_unique && tw != 1)) { ///the frequency of repetitive regions; ignore those minimizers - int en = z->pos + 1, st = en - z->span;//[st, en) - if (st > rep_en) { ///just record the length of repetive regions - *rep_len += rep_en - rep_st; - rep_st = st, rep_en = en; - } else rep_en = en; - } else { - mg_match_t *q = &m[n_m++]; - q->q_pos = z->pos, q->q_span = z->span, q->rev = z->rev, q->cr = cr, q->n = tn, q->qid = 0; - q->is_tandem = 0, q->weight = 255; - if(check_unique && tw != 1) q->is_tandem = 1, q->weight = 1; - *n_a += q->n;///how many candidates - (*mini_pos)[(*n_mini_pos)++] = z->pos;///minimizer offset in query - } - } - *rep_len += rep_en - rep_st; ///the length of repetitive regions - *_n_m = n_m; - return m; -} - -mg128_t *collect_seed_hits(void *km, const mg_idxopt_t *opt, int max_occ, const void *ha_flt_tab, const ha_pt_t *ha_idx, -const ma_ug_t *ug, const ha_mzl_v *mv, int64_t *n_a, int *rep_len, int *n_mini_pos, int32_t **mini_pos) -{ - int i, n_m; - mg128_t *a = NULL; - mg_match_t *m = collect_matches(km, &n_m, max_occ, ha_flt_tab, ha_idx, 1, mv, n_a, rep_len, n_mini_pos, mini_pos); - a = (mg128_t*)kmalloc(km, *n_a * sizeof(mg128_t));///n_a: how many available candidates in total - for (i = 0, *n_a = 0; i < n_m; ++i) {///n_m: how many available seeds, instead of candidates - mg_match_t *q = &m[i]; - const ha_idxposl_t *r = q->cr; - uint32_t k; - for (k = 0; k < q->n; ++k) {///q->n: number of candidates belonging to seed m[i] - mg128_t *p; - p = &a[(*n_a)++];///pick up a slot for one candidate - if (r[k].rev == q->rev) // forward strand - p->x = (uint64_t)(r[k].rid)<<33|r[k].pos; ///reference: rid(31)|rev(1)|pos(32) - else // reverse strand - p->x = (uint64_t)(r[k].rid)<<33 | 1ULL<<32 | (ug->g->seq[r[k].rid].len - (r[k].pos + 1 - r[k].span) - 1); - p->y = (uint64_t)q->q_span << 32 | q->q_pos; - p->y |= (uint64_t)q->qid << MG_SEED_SEG_SHIFT; - if (q->is_tandem) p->y |= MG_SEED_TANDEM; - p->y |= (uint64_t)q->weight << MG_SEED_WT_SHIFT; - ///p->y: weight(8)seg_id(8)flag(8)span(8)pos(32) - ///p->x: rid(31)rev(1)pos(33); keep reference - } - } - kfree(km, m); - radix_sort_128x(a, a + (*n_a)); - return a; -} - -///r is 1000 in default -///remove isolated hits, whic are not close enough to others -int64_t flt_anchors(int64_t n_a, mg128_t *a, int32_t r) -{ - int64_t i, j; - for (i = 0; i < n_a; ++i) { - for (j = i - 1; j >= 0; --j) { - /** - * a is sorted by x - * a[].x: ref_id(31)rev(1)r_pos(32) - * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) - **/ - int32_t dq; - int64_t dr = a[i].x - a[j].x;///a is sorted by x - if (dr > r) break;///if two candidates coming from differnt unitigs, dr would be extremly large - dq = (int32_t)a[i].y - (int32_t)a[j].y; - if (dq > r || dq < 0) continue; - a[j].y |= MG_SEED_KEPT; - a[i].y |= MG_SEED_KEPT; - break; - } - } - for (i = n_a - 1; i >= 0; --i) { - if (a[i].y & MG_SEED_KEPT) continue; - for (j = i + 1; j < n_a; ++j) { - int32_t dq; - int64_t dr = a[j].x - a[i].x; - if (dr > r) break; - dq = (int32_t)a[j].y - (int32_t)a[i].y; - if (dq > r || dq < 0) continue; - a[j].y |= MG_SEED_KEPT; - a[i].y |= MG_SEED_KEPT; - break; - } - } - for (i = j = 0; i < n_a; ++i) - if (a[i].y & MG_SEED_KEPT) - a[j++] = a[i]; - return j; -} - -static inline float mg_log2(float x) // NB: this doesn't work when x<2 -{ - union { float f; uint32_t i; } z = { x }; - float log_2 = ((z.i >> 23) & 255) - 128; - z.i &= ~(255 << 23); - z.i += 127 << 23; - log_2 += (-0.34484843f * z.f + 2.02466578f) * z.f - 0.67487759f; - return log_2; -} - -inline int32_t normal_sc(uint64_t w, int32_t sc) -{ - if(w < 255){ - int32_t tmp = (int)(0.00392156862745098 * w * sc); // 0.00392... = 1/255 - sc = tmp > 1? tmp : 1; - } - return sc; -} -// ai[].x: ref_id(31)rev(1)r_pos(32) -// ai[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) -// comput_sc(&a[i], &a[j], max_dist_x, max_dist_y, bw, chn_pen_gap, chn_pen_skip, is_cdna, n_segs); -static inline int32_t comput_sc(const mg128_t *ai, const mg128_t *aj, int32_t max_dist_x, int32_t max_dist_y, int32_t bw, float chn_pen_gap) -{ - int32_t dq = (int32_t)ai->y - (int32_t)aj->y, dr = (int32_t)ai->x - (int32_t)aj->x, dd, dg, q_span, sc; - ///ai and aj has already been sorted by x - ///which means ai->x >= aj->x - if (dq <= 0 || dq > max_dist_x) return INT32_MIN; - if (dr <= 0 || dr > max_dist_y) return INT32_MIN; - dd = dr > dq? dr - dq : dq - dr; ///indel, dd is always >= 0 - if (dd > bw) return INT32_MIN; - dg = dr < dq? dr : dq;///MIN(dr, dq) - q_span = aj->y>>32&0xff;///query span; should be ai->y>>32&0xff, is it a bug? - sc = normal_sc(aj->y>>MG_SEED_WT_SHIFT, (q_span q_span: there are some bases that are not covered between ai and aj - ///it is if (dd || dg > q_span) in minigraph - if (dd) { - float lin_pen, log_pen; - lin_pen = chn_pen_gap * (float)dd; - log_pen = dd >= 2? mg_log2(dd) : 0.0f; // mg_log2() only works for dd>=2 - sc -= (int)(lin_pen + log_pen); - } - return sc; -} - - -///p[]: id of last -///f[]: the score ending at i, not always the peak -///v[]: keeps the peak score up to i; -///t[]: used for buffer -///min_cnt = 2; min_sc = 30; extra_u = 0 -///u = mg_chain_backtrack(n, f, p, v, t, min_cnt, min_sc, 0, &n_u, &n_v); -uint64_t *mg_chain_backtrack(void *km, int64_t n, const int32_t *f, const int64_t *p, int32_t *v, int32_t *t, int32_t min_cnt, int32_t min_sc, int32_t extra_u, int32_t *n_u_, int32_t *n_v_) -{ - mg128_t *z; - uint64_t *u; - int64_t i, k, n_z, n_v; - int32_t n_u; - // v[] keeps the peak score up to i; f[] is the score ending at i, not always the peak - *n_u_ = *n_v_ = 0; - for (i = 0, n_z = 0; i < n; ++i) // precompute n_z - if (f[i] >= min_sc) ++n_z; - if (n_z == 0) return 0; - KMALLOC(km, z, n_z); - for (i = 0, k = 0; i < n; ++i) // populate z[] - if (f[i] >= min_sc) z[k].x = f[i], z[k++].y = i; - radix_sort_128x(z, z + n_z);///sort by score - - memset(t, 0, n * 4);///t is a buffer - ///from the largest to the smallest - for (k = n_z - 1, n_v = n_u = 0; k >= 0; --k) { // precompute n_u - int64_t n_v0 = n_v; - int32_t sc; - ///note t[i] == 0 is not used to find local alignment - ///say if we have already found a long chain, then the secondary might be able to merged to the long chain - ///t[i] == 0 is used to find those chains - for (i = z[k].y; i >= 0 && t[i] == 0; i = p[i]) - ++n_v, t[i] = 1; - sc = i < 0? z[k].x : (int32_t)z[k].x - f[i]; - if (sc >= min_sc && n_v > n_v0 && n_v - n_v0 >= min_cnt) - ++n_u;///how many chains, including primary chains and non-primary chains - else n_v = n_v0; - } - KMALLOC(km, u, n_u + extra_u); - memset(t, 0, n * 4); - for (k = n_z - 1, n_v = n_u = 0; k >= 0; --k) { // populate u[] - int64_t n_v0 = n_v; - int32_t sc; - for (i = z[k].y; i >= 0 && t[i] == 0; i = p[i]) - v[n_v++] = i, t[i] = 1; - sc = i < 0? z[k].x : (int32_t)z[k].x - f[i]; - if (sc >= min_sc && n_v > n_v0 && n_v - n_v0 >= min_cnt) - u[n_u++] = (uint64_t)sc << 32 | (n_v - n_v0); - else n_v = n_v0; - } - kfree(km, z); - assert(n_v < INT32_MAX); - *n_u_ = n_u, *n_v_ = n_v; - return u; -} - -//u[]: sc|occ of chains -//v[]: idx of each element -static mg128_t *compact_a(void *km, int32_t n_u, uint64_t *u, int32_t n_v, int32_t *v, mg128_t *a) -{ - mg128_t *b, *w; - uint64_t *u2; - int64_t i, j, k; - - // write the result to b[] - KMALLOC(km, b, n_v); - for (i = 0, k = 0; i < n_u; ++i) { - int32_t k0 = k, ni = (int32_t)u[i]; - for (j = 0; j < ni; ++j) - b[k++] = a[v[k0 + (ni - j - 1)]];///write all elements of a chain together - } - kfree(km, v); - - // sort u[] and a[] by the target position, such that adjacent chains may be joined - KMALLOC(km, w, n_u); - for (i = k = 0; i < n_u; ++i) {///n_u: how many chains - ///x: ref_id(31)rev(1)r_pos(32) - w[i].x = b[k].x, w[i].y = (uint64_t)k<<32|i; - k += (int32_t)u[i]; - } - radix_sort_128x(w, w + n_u);///sort by ref_id(31)rev(1)r_pos(32); r_pos is the start pos of chain - KMALLOC(km, u2, n_u); - for (i = k = 0; i < n_u; ++i) {///note merge chain; just place close chains together - ///j is chain id; n is how many elements in j-th chain - int32_t j = (int32_t)w[i].y, n = (int32_t)u[j]; - u2[i] = u[j]; - memcpy(&a[k], &b[w[i].y>>32], n * sizeof(mg128_t)); - k += n; - } - memcpy(u, u2, n_u * 8); - memcpy(b, a, k * sizeof(mg128_t)); // write _a_ to _b_ and deallocate _a_ because _a_ is oversized, sometimes a lot - kfree(km, a); kfree(km, w); kfree(km, u2); - return b; -} - -/* Input: - * a[].x: ref_id(31)rev(1)r_pos(32) - * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) - * n: length of a[] - * Output: - * n_u: #chains - * u[]: score<<32 | #anchors (sum of lower 32 bits of u[] is the returned length of a[]) - * input a[] is deallocated on return - */ -///is_cdna is is_splice -mg128_t *mg_lchain_dp(int max_dist_x, int max_dist_y, int bw, int max_skip, int max_iter, int min_cnt, int min_sc, float chn_pen_gap, - int64_t n, mg128_t *a, int *n_u_, uint64_t **_u, void *km) -{ // TODO: make sure this works when n has more than 32 bits - int32_t *f, *t, *v, n_u, n_v; - int64_t *p, i, j, max_ii, st = 0; - uint64_t *u; - - if (_u) *_u = 0, *n_u_ = 0; - if (n == 0 || a == 0) return 0; - KMALLOC(km, p, n);///id of last cell - KMALLOC(km, f, n);///f[] is the score ending at i, not always the peak - KMALLOC(km, v, n);///v[] keeps the peak score up to i; - KCALLOC(km, t, n);///t doesn't matter too much; it is mainly used to accelrate the iteration - - // a[].x: ref_id(31)rev(1)r_pos(32) - // a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) - // fill the score and backtrack arrays - for (i = st = 0, max_ii = -1; i < n; ++i) { - int64_t max_j = -1, end_j; - ///max_f -> score of minimizer - int32_t max_f = normal_sc(a[i].y>>MG_SEED_WT_SHIFT, a[i].y>>32&0xff), n_skip = 0; - ///until we are at the same rid, same direction, and the coordinates are close enough - while (st < i && (a[i].x>>32 != a[st].x>>32 || a[i].x > a[st].x + max_dist_x)) ++st; - ///max_iter = 10000 in default, which means dp can go back to up to 10000 cells - if (i - st > max_iter) st = i - max_iter; - for (j = i - 1; j >= st; --j) { - int32_t sc; - sc = comput_sc(&a[i], &a[j], max_dist_x, max_dist_y, bw, chn_pen_gap); - if (sc == INT32_MIN) continue; - sc += f[j]; - if (sc > max_f) { - max_f = sc, max_j = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == (int32_t)i) {///note we scan j backwards; we don't need to update t[] for each i - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i;//p[]: prefix idx; means there is a chain longer than 2 - } - end_j = j;///end_j might be > 0; just the end idx of backwards - ///if not close enough, select a new max - ///max_ii is just used to rescue best-score in case best-score appears before end_j - if (max_ii < 0 || (int64_t)(a[i].x - a[max_ii].x) > (int64_t)max_dist_x) {///select a new max - int32_t max = INT32_MIN; - max_ii = -1; - for (j = i - 1; j >= st; --j) - if (max < f[j]) max = f[j], max_ii = j; - } - ///note: it will happen when `max_ii` < `end_j`; - ///iteration is terminated at `end_j` mostly because of `max_skip` and `max_iter` - ///max_ii is just used to rescue best-score in case best-score appears before end_j - if (max_ii >= 0 && max_ii < end_j) { - int32_t tmp; - tmp = comput_sc(&a[i], &a[max_ii], max_dist_x, max_dist_y, bw, chn_pen_gap); - if (tmp != INT32_MIN && max_f < tmp + f[max_ii]) - max_f = tmp + f[max_ii], max_j = max_ii; - } - // v[] keeps the peak score up to i (as score might decerase); f[] is the score ending at i, not always the peak - f[i] = max_f, p[i] = max_j;//p[]: prefix idx - v[i] = max_j >= 0 && v[max_j] > max_f? v[max_j] : max_f; - if (max_ii < 0 || ((int64_t)(a[i].x - a[max_ii].x) <= (int64_t)max_dist_x && f[max_ii] < f[i])) - max_ii = i; - } - ///after mg_chain_backtrack, the results are saved in u and v; - u = mg_chain_backtrack(km, n, f, p, v, t, min_cnt, min_sc, 0, &n_u, &n_v); - *n_u_ = n_u, *_u = u; // NB: note that u[] may not be sorted by score here - kfree(km, p); kfree(km, f); kfree(km, t); - if (n_u == 0) { - kfree(km, a); kfree(km, v); - return 0; - } - //u[]: sc|occ of chains; chain is mostly sorted by the score; at least the first chain has the largest score - //v[]: idx of each element - return compact_a(km, n_u, u, n_v, v, a); -} - - -void extend_coordinates(mg_lchain_t *ri, int64_t qlen, int64_t rlen) -{ - int64_t qs, qe, rs, re, qtail, rtail; - qs = ri->qs; qe = ri->qe - 1; rs = ri->rs; re = ri->re - 1; - if(ri->v&1) { - rs = rlen - ri->re; re = rlen - ri->rs - 1; - } - - if(qs <= rs) { - rs -= qs; qs = 0; - } else { - qs -= rs; rs = 0; - } - - qtail = qlen - qe - 1; rtail = rlen - re - 1; - if(qtail <= rtail) { - qe = qlen - 1; re += qtail; - } - else - { - re = rlen - 1; qe += rtail; - } - - ri->qs = qs; ri->qe = qe + 1; ri->rs = rs; ri->re = re + 1; - if(ri->v&1) { - ri->rs = rlen - re - 1; ri->re = rlen - rs; - } -} -///qlen: query length -///u[]: sc|occ of chains -///a[]: candidate list -mg_lchain_t *mg_lchain_gen(void *km, int qlen, int n_u, uint64_t *u, mg128_t *a, const ma_ug_t *ug) -{ - mg128_t *z; - mg_lchain_t *r; - int i, k; - - if (n_u == 0) return 0; - KCALLOC(km, r, n_u); KMALLOC(km, z, n_u); - // u[] is sorted by query position - for (i = k = 0; i < n_u; ++i) { - /** - * a[].x: ref_id(31)rev(1)r_pos(32) - * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) - **/ - ///u[]: sc(32)occ(32) - int32_t qs = (int32_t)a[k].y + 1 - (a[k].y>>32 & 0xff); - z[i].x = (uint64_t)qs << 32 | u[i] >> 32; - z[i].y = (uint64_t)k << 32 | (int32_t)u[i]; - k += (int32_t)u[i]; - } - radix_sort_128x(z, z + n_u);//sort by qs|sc - - // populate r[] - for (i = 0; i < n_u; ++i) { - mg_lchain_t *ri = &r[i]; - /** - * z[].x: query start pos| chain score - * z[].y: idx in a[] | chain occ - * a[].x: ref_id(31)rev(1)r_pos(32) - * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) - * **/ - int32_t k = z[i].y >> 32, q_span = a[k].y >> 32 & 0xff; - ri->off = k; - ri->cnt = (int32_t)z[i].y; - ri->score = (uint32_t)z[i].x; - ri->v = a[k].x >> 32;///ref_id|rev - ri->rs = (int32_t)a[k].x + 1 > q_span? (int32_t)a[k].x + 1 - q_span : 0; // for HPC k-mer - ri->qs = z[i].x >> 32; - ri->re = (int32_t)a[k + ri->cnt - 1].x + 1; - ri->qe = (int32_t)a[k + ri->cnt - 1].y + 1; - // fprintf(stderr, "+0+\tA\tutg%.6d%c\t%c\tqs:%u\tqe:%u\tql:%d\tts:%u\tte:%u\ttl:%u\n", - // (ri->v>>1)+1, "lc"[ug->u.a[ri->v>>1].circ], "+-"[ri->v&1], ri->qs, ri->qe, qlen, ri->rs, ri->re, ug->u.a[ri->v>>1].len); - // extend_coordinates(ri, qlen, ug->u.a[ri->v>>1].len); - // fprintf(stderr, "-0-\tA\tutg%.6d%c\t%c\tqs:%u\tqe:%u\tql:%d\tts:%u\tte:%u\ttl:%u\n", - // (ri->v>>1)+1, "lc"[ug->u.a[ri->v>>1].circ], "+-"[ri->v&1], ri->qs, ri->qe, qlen, ri->rs, ri->re, ug->u.a[ri->v>>1].len); - } - kfree(km, z); - return r; -} - -static int32_t get_mini_idx(const mg128_t *a, int32_t n, const int32_t *mini_pos) -{ - int32_t x, L = 0, R = n - 1; - x = (int32_t)a->y; - while (L <= R) { // binary search - int32_t m = ((uint64_t)L + R) >> 1; - int32_t y = mini_pos[m]; - if (y < x) L = m + 1; - else if (y > x) R = m - 1; - else return m; - } - return -1; -} - -/* Before: - * a[].x: ref_id(31)rev(1)r_pos(32) - * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) - * After: - * a[].x: idx_in_minimizer_arr(32)r_pos(32) - * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) - */ -void mg_update_anchors(int32_t n_a, mg128_t *a, int32_t n, const int32_t *mini_pos) -{ - int32_t st, j, k; - if (n_a <= 0) return; - st = get_mini_idx(&a[0], n, mini_pos); - assert(st >= 0); - for (k = 0, j = st; j < n && k < n_a; ++j) - if ((int32_t)a[k].y == mini_pos[j]) - a[k].x = (uint64_t)j << 32 | (a[k].x & 0xffffffffU), ++k; - assert(k == n_a); -} - -static int32_t find_max(int32_t n, const gc_frag_t *gf, uint32_t x) -{ - int32_t s = 0, e = n; - if (n == 0) return -1; - if (gf[n-1].srt < x) return n - 1; - if (gf[0].srt >= x) return -1; - while (e > s) { // TODO: finish this block - int32_t m = s + (e - s) / 2; - if (gf[m].srt >= x) e = m; - else s = m + 1; - } - assert(s == e); - return s; -} -///target_dist should like the overlap length in string graph -///it should be used to evaluate if the identified path is close to real path/alignment -static int32_t mg_target_dist(const asg_t *g, const mg_lchain_t *l0, const mg_lchain_t *l1) -{ - /** - case 1: l0->qs************l0->qe - l1->qs************l1->qe - case 2: l0->qs************l0->qe - l1->qs************l1->qe - - *****l0->rs************l0->re***** - ****l1->rs************l1->re** - * **/ - ///min_dist = l1->rs + (g->seg[l0->v>>1].len - l0->re); - // below equals (l1->qs - l0->qe) - min_dist + g->seg[l1->v>>1].len; see mg_gchain1_dp() for the calculation of min_dist - //(l1->qs - l0->qe) is the gap in query, min_dist is the gap in reference - return (l1->qs - l0->qe) - (g->seq[l0->v>>1].len - l0->re) + (g->seq[l1->v>>1].len - l1->rs); - // when l0->v == l1->v, the above becomes (l1->qs - l0->qe) - (l1->rs - l0->re), which is what we want -} - -static inline sp_node_t *gen_sp_node(void *km, uint32_t v, int32_t d, int32_t id) -{ - sp_node_t *p; - KMALLOC(km, p, 1); - p->v = v, p->di = (uint64_t)d<<32 | id, p->pre = -1, p->is_0 = 1; - return p; -} - -///max_dist is like the overlap length in string graph -///the end position of qs is li->qs; dst[]->->qlen indicate the region that need to be checked in bases -mg_pathv_t *mg_shortest_k(void *km0, const asg_t *g, uint32_t src, int32_t n_dst, mg_path_dst_t *dst, int32_t max_dist, int32_t max_k, /** //pathint32_t ql, const char *qs, int is_rev, **/int32_t *n_pathv) -{ - sp_node_t *p, *root = 0, **out; - sp_topk_t *q; - khash_t(sp) *h; - khash_t(sp2) *h2; - void *km; - khint_t k; - int absent; - int32_t i, j, n_done, n_found; - uint32_t id, n_out, m_out; - int8_t *dst_done; - mg_pathv_t *ret = 0; - uint64_t *dst_group; - /** //path - int32_t n_seeds = 0; - uint64_t *seeds = 0; - void *h_seeds = 0; - mg128_v mini = {0,0,0}; - **/ - - if (n_pathv) *n_pathv = 0;///for us, n_pathv = NULL - if (n_dst <= 0) return 0;///n_dst: how many candidate nodes - for (i = 0; i < n_dst; ++i) { // initialize - mg_path_dst_t *t = &dst[i]; - ///if src and dest are at the same ref id, there are already one path - if (t->inner)///if two chains are at the same ref id - t->dist = 0, t->n_path = 1, t->path_end = -1; - else - t->dist = -1, t->n_path = 0, t->path_end = -1; - } - if (max_k > MG_MAX_SHORT_K) max_k = MG_MAX_SHORT_K; - km = km_init2(km0, 0x4000); - - /** //path - ///for the first time, we just check th reachability without sequence (qs); - ///but for the second round, we need to check sequence - ///qs is the sequence between two minimizers - if (ql > 0 && qs) { // build the seed hash table for the query - mg_sketch(km, qs, ql, MG_SHORT_KW, MG_SHORT_KK, 0, &mini); - // mini->a[].x = hash_key<<8 | kmerSpan - // mini->a[].y = rid<<32 | lastPos<<1 | strand - if (is_rev)///is_rev = 1; - for (i = 0; i < mini.n; ++i)///reverse qs[0, ql) to qs(ql, 0] - mini.a[i].y = (ql - (((int32_t)mini.a[i].y>>1) + 1 - MG_SHORT_KK) - 1) << 1 | ((mini.a[i].y&1)^1); - ///h_seeds is the ordinary hash index - h_seeds = mg_idx_a2h(km, mini.n, mini.a, 0, &seeds, &n_seeds); - ///h_seeds+seeds+n_seeds ----> hash index of qs[0, ql) - } - **/ - ///dst is how many candidates - KCALLOC(km, dst_done, n_dst); - KMALLOC(km, dst_group, n_dst); - // multiple dst[] may have the same dst[].v. We need to group them first. - // in other words, one ref id may have multiple dst alignment chains - for (i = 0; i < n_dst; ++i) - dst_group[i] = (uint64_t)dst[i].v<<32 | i; - radix_sort_gfa64(dst_group, dst_group + n_dst); - - h2 = kh_init2(sp2, km); // (h2+dst_group) keeps all destinations from the same ref id - kh_resize(sp2, h2, n_dst * 2); - ///please note that one contig in ref may have multiple alignment chains - ///so h2 is a index that helps us to query it - ///key(h2) = ref id; value(h2) = start_idx | occ - for (i = 1, j = 0; i <= n_dst; ++i) { - if (i == n_dst || dst_group[i]>>32 != dst_group[j]>>32) { - k = kh_put(sp2, h2, dst_group[j]>>32, &absent); - kh_val(h2, k) = (uint64_t)j << 32 | (i - j); - assert(absent); - j = i; - } - } - - - - h = kh_init2(sp, km); // h keeps visited vertices; path to each visited vertice - kh_resize(sp, h, 16); - - m_out = 16, n_out = 0;///16 is just the initial size - KMALLOC(km, out, m_out); - - /** - typedef struct { - int32_t k, mlen;//k: number of walks from src to this node - int32_t qs, qe; - sp_node_t *p[MG_MAX_SHORT_K]; // this forms a max-heap; all path - } sp_topk_t; - **/ - id = 0; - p = gen_sp_node(km, src, 0, id++);///just malloc a node for src; the distance is 0 - p->hash = __ac_Wang_hash(src);///hash is path hash, instead of node hash - kavl_insert(sp, &root, p, 0);///should be avl tree - ///each src corresponds to one node in the hash table , but corresponds to node in the AVL tree - k = kh_put(sp, h, src, &absent);///here is a hash table - q = &kh_val(h, k); - ///for normal graph traversal, one node just has one parental node; here each node has at most 16 parental nodes - q->k = 1, q->p[0] = p, q->mlen = 0, q->qs = q->qe = -1; - - n_done = 0; - ///the key of avl tree: #define sp_node_cmp(a, b) (((a)->di > (b)->di) - ((a)->di < (b)->di)) - ///the higher bits of (*)->di is distance to src node - ///so the key of avl tree is distance - ///in avl tree , one node might be saved multipe times - while (kavl_size(head, root) > 0) {///thr first root is src - int32_t i, nv; - asg_arc_t *av; - sp_node_t *r; - ///note that one (sp_node_t->v) might be visited multiple times if there are circles - ///so there might be multipe nodes with the same (sp_node_t->v) - ///delete the first node - r = kavl_erase_first(sp, &root); // take out the closest vertex in the heap (as a binary tree) - //fprintf(stderr, "XX\t%d\t%d\t%d\t%c%s[%d]\t%d\n", n_out, kavl_size(head, root), n_finished, "><"[(r->v&1)^1], g->seg[r->v>>1].name, r->v, (int32_t)(r->di>>32)); - if (n_out == m_out) KEXPAND(km, out, m_out); - ///higher 32 bits might be the distance to root node - // lower 32 bits now for position in the out[] array - r->di = r->di>>32<<32 | n_out; ///n_out is just the id in out - ///so one node id in graph might be saved multiple times in avl tree and out[] - out[n_out++] = r;///out[0] = src - - ///r->v is the dst vertex id - ///sometimes k==kh_end(h2). Some nodes are found by graph travesal but not in linear chain alignment - k = kh_get(sp2, h2, r->v); - // we have reached one dst vertex - // note that one dst vertex may have multipe alignment chains - // we can visit some nodes in graph which are not reachable during chaining - // h2 is used to determine if one node is reachable or not - if (k != kh_end(h2)) { - ///node r->v might be visited multiple times - int32_t j, dist = r->di>>32, off = kh_val(h2, k) >> 32, cnt = (int32_t)kh_val(h2, k); - //src can reach ref id r->v; there might be not only one alignment chain in r->v - //so we need to scan all of them - for (j = 0; j < cnt; ++j) { - mg_path_dst_t *t = &dst[(int32_t)dst_group[off + j]];///t is a linear alignment at r->v - int32_t done = 0; - ///the src and dest are at the same ref id, say we directly find the shortest path - if (t->inner) {//usually the first node, which is same to src - done = 1; - } else { - int32_t mlen = 0, copy = 0; - ///in the first round, we just check reachability without sequence - ///so h_seeds = NULL; we can assume mlen = 0 - /** //path - mlen = h_seeds? path_mlen(out, n_out - 1, h, t->qlen) : 0; - **/ - //if (mg_dbg_flag & MG_DBG_GC1) fprintf(stderr, " src=%c%s[%d],qlen=%d\tdst=%c%s[%d]\ttarget_distx=%d,target_hash=%x\tdistx=%d,mlen=%d,hash=%x\n", "><"[src&1], g->seg[src>>1].name, src, ql, "><"[t->v&1], g->seg[t->v>>1].name, t->v, t->target_dist - g->seg[src>>1].len, t->target_hash, dist - g->seg[src>>1].len, mlen, r->hash); - // note: t indicates a linear alignmnet, instead of a node in graph - ///target_dist should be the distance on query - if (t->n_path == 0) { // means this alignment has never been visited before; keep the shortest path anyway - copy = 1; - // we have a target distance; choose the closest; - // there is already several paths reaching the linear alignment - } else if (t->target_dist >= 0) { - // we found the target path; hash is the path hash including multiple nodes, instead of node hash - if (dist == t->target_dist && t->check_hash && r->hash == t->target_hash) { - copy = 1, done = 1; - } else { - int32_t d0 = t->dist, d1 = dist; - d0 = d0 > t->target_dist? d0 - t->target_dist : t->target_dist - d0; - d1 = d1 > t->target_dist? d1 - t->target_dist : t->target_dist - d1; - ///if the new distance (d1) is smaller than the old distance (d0), update the results - ///the length of new path should be closer to t->target_dist - if (d1 - mlen/2 < d0 - t->mlen/2) copy = 1; - } - } - if (copy) { - t->path_end = n_out - 1, t->dist = dist, t->hash = r->hash, t->mlen = mlen, t->is_0 = r->is_0; - if (t->target_dist >= 0) { - ///src is from li from li to lj, so the dis is generally increased; dijkstra algorithm - ///target_dist should be the distance on query - if (dist == t->target_dist && t->check_hash && r->hash == t->target_hash) done = 1; - else if ((dist > t->target_dist + MG_SHORT_K_EXT) && (dist > (t->target_dist>>4))) done = 1; - } - } - ++t->n_path;///we found a path to the alignment t - if (t->n_path >= max_k) done = 1; - } - if (dst_done[off + j] == 0 && done) - dst_done[off + j] = 1, ++n_done; - } - ///if all alignments have been settle down - ///pre-end; accelerate the loop - if (n_done == n_dst) break; - } - - ///below is used to push new nodes to avl tree for iteration - nv = asg_arc_n(g, r->v); - av = asg_arc_a(g, r->v); - for (i = 0; i < nv; ++i) { // visit all neighbors - asg_arc_t *ai = &av[i]; - ///v_lv is the (dest_length - overlap_length); it is a normal path length in string graph - ///ai->v_lv is the path length from r->v to ai->w - ///(r->di>>32) - int32_t d = (r->di>>32) + (uint32_t)ai->ul; - if (d > max_dist) continue; // don't probe vertices too far away - // h keeps visited vertices; path to each visited vertice - ///ai->w is the dest ref id; we insert a new ref id, instead of an alignment chain - k = kh_put(sp, h, ai->v, &absent);///one node might be visited multiple times - q = &kh_val(h, k); - if (absent) { // a new vertex visited - ///q->k: number of walks from src to ai->w - q->k = 0, q->qs = q->qe = -1; q->mlen = 0; - ///h_seeds = NULL; so q->mlen = 0 - /** //path - q->mlen = h_seeds && d + gfa_arc_lw(g, *ai) <= max_dist? node_mlen(km, g, ai->w, &mini, h_seeds, n_seeds, seeds, &q->qs, &q->qe) : 0; - **/ - //if (ql && qs) fprintf(stderr, "ql=%d,src=%d\tv=%c%s[%d],n_seeds=%d,mlen=%d\n", ql, src, "><"[ai->w&1], g->seg[ai->w>>1].name, ai->w, n_seeds, q->mlen); - } - ///if there are less than walks from src to ai->w, directly add - ///if there are more, keep the smallest walks - if (q->k < max_k) { // enough room: add to the heap - p = gen_sp_node(km, ai->v, d, id++); - p->pre = n_out - 1;///the parent node of this one - p->hash = r->hash + __ac_Wang_hash(ai->v); - p->is_0 = r->is_0; - /** //path - if (ai->rank > 0) p->is_0 = 0; - **/ - kavl_insert(sp, &root, p, 0); - q->p[q->k++] = p; - ks_heapup_sp(q->k, q->p);///adjust heap by distance - } else if ((int32_t)(q->p[0]->di>>32) > d) { // shorter than the longest path so far: replace the longest - p = kavl_erase(sp, &root, q->p[0], 0); - if (p) { - p->di = (uint64_t)d<<32 | (id++); - p->pre = n_out - 1; - p->hash = r->hash + __ac_Wang_hash(ai->v); - p->is_0 = r->is_0; - /** //path - if (ai->rank > 0) p->is_0 = 0; - **/ - kavl_insert(sp, &root, p, 0); - ks_heapdown_sp(0, q->k, q->p); - } else { - fprintf(stderr, "Warning: logical bug in gfa_shortest_k(): q->k=%d,q->p[0]->{d,i}={%d,%d},d=%d,src=%u,max_dist=%d,n_dst=%d\n", q->k, (int32_t)(q->p[0]->di>>32), (int32_t)q->p[0]->di, d, src, max_dist, n_dst); - km_destroy(km); - return 0; - } - } // else: the path is longer than all the existing paths ended at ai->w - } - } - - kfree(km, dst_group); - kfree(km, dst_done); - kh_destroy(sp, h); - /** //path - mg_idx_hfree(h_seeds); - kfree(km, seeds); - kfree(km, mini.a); - **/ - // NB: AVL nodes are not deallocated. When km==0, they are memory leaks. - - for (i = 0, n_found = 0; i < n_dst; ++i) - if (dst[i].n_path > 0) ++n_found;///n_path might be larger than 16 - ///we can assume n_pathv = NULL for now - if (n_found > 0 && n_pathv) { // then generate the backtrack array - int32_t n, *trans; - ///n_out: how many times that nodes in graph have been visited - ///note one node might be visited multiples times - KCALLOC(km, trans, n_out); // used to squeeze unused elements in out[] - ///n_dst: number of alignment chains - for (i = 0; i < n_dst; ++i) { // mark dst vertices with a target distance - mg_path_dst_t *t = &dst[i]; - if (t->n_path > 0 && t->target_dist >= 0 && t->path_end >= 0) - trans[(int32_t)out[t->path_end]->di] = 1;///(int32_t)out[]->di: traverse track corresponds to the alignment chain dst[] - } - for (i = 0; (uint32_t)i < n_out; ++i) { // mark dst vertices without a target distance - k = kh_get(sp2, h2, out[i]->v); - if (k != kh_end(h2)) { // TODO: check if this is correct! - int32_t off = kh_val(h2, k)>>32, cnt = (int32_t)kh_val(h2, k); - for (j = off; j < off + cnt; ++j) - if (dst[j].target_dist < 0) - trans[i] = 1; - } - } - for (i = n_out - 1; i >= 0; --i) // mark all predecessors - if (trans[i] && out[i]->pre >= 0) - trans[out[i]->pre] = 1; - for (i = n = 0; (uint32_t)i < n_out; ++i) // generate coordinate translations - if (trans[i]) trans[i] = n++; - else trans[i] = -1; - - *n_pathv = n; - KMALLOC(km0, ret, n); - for (i = 0; (uint32_t)i < n_out; ++i) { // generate the backtrack array - mg_pathv_t *p; - if (trans[i] < 0) continue; - p = &ret[trans[i]]; - p->v = out[i]->v, p->d = out[i]->di >> 32; - p->pre = out[i]->pre < 0? out[i]->pre : trans[out[i]->pre]; - } - for (i = 0; i < n_dst; ++i) // translate "path_end" - if (dst[i].path_end >= 0) - dst[i].path_end = trans[dst[i].path_end]; - } - - km_destroy(km); - return ret; -} - -static inline int32_t cal_sc(const mg_path_dst_t *dj, const mg_lchain_t *li, const mg_lchain_t *lc, const mg128_t *an, const gc_frag_t *a, const int32_t *f, - int bw, int ref_bonus, float chn_pen_gap) -{ - const mg_lchain_t *lj; - int32_t gap, sc; - float lin_pen, log_pen; - if (dj->n_path == 0) return INT32_MIN; - gap = dj->dist - dj->target_dist; - lj = &lc[a[dj->meta].i]; - if (gap < 0) gap = -gap; - if (gap > bw) return INT32_MIN; - if (lj->qe <= li->qs) sc = li->score; - else sc = (int32_t)((double)(li->qe - lj->qe) / (li->qe - li->qs) * li->score + .499); // dealing with overlap on query - //sc += dj->mlen; // TODO: is this line the right thing to do? - if (dj->is_0) sc += ref_bonus; - lin_pen = chn_pen_gap * (float)gap; - log_pen = gap >= 2? mg_log2(gap) : 0.0f; - sc -= (int32_t)(lin_pen + log_pen); - sc += f[dj->meta]; - return sc; -} - -void transfor_icoord(const int64_t iqs, const int64_t iqe, const int64_t irs, const int64_t ire, const uint8_t rev, -const int64_t qlen, const int64_t rlen, int32_t *r_qs, int32_t *r_qe, int32_t *r_rs, int32_t *r_re) -{ - int64_t qs, qe, rs, re, qtail, rtail; - qs = iqs; qe = iqe - 1; rs = irs; re = ire - 1; - if(rev) { - rs = rlen - ire; re = rlen - irs - 1; - } - - if(qs <= rs) { - rs -= qs; qs = 0; - } else { - qs -= rs; rs = 0; - } - - qtail = qlen - qe - 1; rtail = rlen - re - 1; - if(qtail <= rtail) { - qe = qlen - 1; re += qtail; - } - else - { - re = rlen - 1; qe += rtail; - } - - if(r_qs) (*r_qs) = qs; if(r_qe) (*r_qe) = qe + 1; - if(r_rs) (*r_rs) = rs; if(r_re) (*r_re) = re + 1; - if(rev) { - if(r_rs) (*r_rs) = rlen - re - 1; - if(r_re) (*r_re) = rlen - rs; - } -} - -void transfor_coord(mg_lchain_t *ri, const int64_t qlen, const int64_t rlen, -int32_t *r_qs, int32_t *r_qe, int32_t *r_rs, int32_t *r_re) -{ - int64_t qs, qe, rs, re, qtail, rtail; - qs = ri->qs; qe = ri->qe - 1; rs = ri->rs; re = ri->re - 1; - if(ri->v&1) { - rs = rlen - ri->re; re = rlen - ri->rs - 1; - } - - if(qs <= rs) { - rs -= qs; qs = 0; - } else { - qs -= rs; rs = 0; - } - - qtail = qlen - qe - 1; rtail = rlen - re - 1; - if(qtail <= rtail) { - qe = qlen - 1; re += qtail; - } - else - { - re = rlen - 1; qe += rtail; - } - - if(r_qs) (*r_qs) = qs; if(r_qe) (*r_qe) = qe + 1; - if(r_rs) (*r_rs) = rs; if(r_re) (*r_re) = re + 1; - if(ri->v&1) { - if(r_rs) (*r_rs) = rlen - re - 1; - if(r_re) (*r_re) = rlen - rs; - } -} - -int64_t get_nn_ov(const uint32_t v, const uint32_t w, const asg_t *g) -{ - uint32_t i; - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v), *p = NULL; - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - if(av[i].v == w) { - // o -= av[i].ol; - p = &(av[i]); - break; - } - } - return p?p->ol:0; -} - -int64_t get_lchain_ovlp(mg_lchain_t *lp, mg_lchain_t *la, const asg_t *g, const int64_t qlen, const ma_ug_t *ug) -{ - int64_t o = lp->qe - la->qs, oj; - uint32_t v = la->v^1, w = lp->v^1, i; - int32_t pqe, aqs; - if(o <= 0) return 0; - if(v == w) return o; - transfor_coord(lp, qlen, ug->u.a[lp->v>>1].len, NULL, &pqe, NULL, NULL); - transfor_coord(la, qlen, ug->u.a[la->v>>1].len, &aqs, NULL, NULL, NULL); - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v), *p = NULL; - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - if(av[i].v == w) { - // o -= av[i].ol; - p = &(av[i]); - break; - } - } - oj = o; - if(p) oj = pqe - aqs - p->ol; - if(o > oj) o = oj; - if(o < 0) o = 0; - return o; -} - - - -int64_t get_lchain_gap(mg_lchain_t *lp, mg_lchain_t *la, const asg_t *g, const int64_t qlen, const ma_ug_t *ug, int32_t double_ol) -{ - int64_t gg = la->qs - lp->qe, ggj; - uint32_t v = la->v^1, w = lp->v^1, i; - int32_t aqs, pqe; - if(double_ol == 0 && gg >= 0) return gg; - if(v == w) return gg; - transfor_coord(la, qlen, ug->u.a[la->v>>1].len, &aqs, NULL, NULL, NULL); - transfor_coord(lp, qlen, ug->u.a[lp->v>>1].len, NULL, &pqe, NULL, NULL); - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v), *p = NULL;; - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - if(av[i].v == w) { - // gg += av[i].ol; - p = &(av[i]); - break; - } - } - ggj = gg; - if(p) ggj = aqs - pqe + p->ol + (double_ol?p->ol:0); - // if(gg < ggj) gg = ggj; - // return gg; - return ggj; -} - -int64_t max_ovlp(const asg_t *g, uint32_t v) -{ - uint32_t i, nv = asg_arc_n(g, v), o = 0; - asg_arc_t *av = asg_arc_a(g, v); - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - if(o < av[i].ol) o = av[i].ol; - } - return o; -} - -int64_t max_ovlp_src(const ug_opt_t *uopt, uint32_t v) -{ - ma_hit_t_alloc* src = uopt->sources; - int64_t min_ovlp = uopt->min_ovlp, max_hang = uopt->max_hang; - uint32_t i, qn, tn, o = 0, x = v>>1; asg_arc_t e; - - for (i = 0; i < src[x].length; i++) { - qn = Get_qn(src[x].buffer[i]); tn = Get_tn(src[x].buffer[i]); - if(ma_hit2arc(&(src[x].buffer[i]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), - max_hang, asm_opt.max_hang_rate, min_ovlp, &e) < 0) { - continue; - } - if((e.ul>>32) != v) continue; - if(o < e.ol) o = e.ol; - } - - return o; -} - -int64_t specific_ovlp(const ma_ug_t *ug, const ug_opt_t *uopt, const uint32_t v, const uint32_t w) -{ - if(ug->u.a[v>>1].circ || ug->u.a[w>>1].circ) return 0; - uint32_t rv, rw, i; int32_t r; - const ma_hit_t_alloc *x = NULL; - asg_arc_t t; memset(&t, 0, sizeof(t)); - if(v&1) rv = ug->u.a[v>>1].start^1; - else rv = ug->u.a[v>>1].end^1; - if(w&1) rw = ug->u.a[v>>1].end; - else rw = ug->u.a[v>>1].start; - x = &(uopt->sources[rv>>1]); - for (i = 0; i < x->length; i++) { - if(Get_tn(x->buffer[i]) == (rw>>1)) { - r = ma_hit2arc(&(x->buffer[i]), uopt->coverage_cut[rv>>1].e - uopt->coverage_cut[rv>>1].s, - uopt->coverage_cut[rw>>1].e - uopt->coverage_cut[rw>>1].s, uopt->max_hang, asm_opt.max_hang_rate, uopt->min_ovlp, &t); - if(r < 0) return 0; - if((t.ul>>32)!=rv || t.v!=rw) return 0; - return t.ol; - } - } - return 0; -} - -void extend_lchain(mg_lchain_t *lc, int32_t n_lc, int32_t qlen, const ma_ug_t *ug) -{ - int32_t i; - for (i = 0; i < n_lc; ++i) { - extend_coordinates(&lc[i], qlen, ug->u.a[lc[i].v>>1].len); - } -} - -void compress_lchain(mg_lchain_t *lc, int32_t n_lc, int32_t qlen, const ma_ug_t *ug, const mg128_t *a) -{ - int32_t i, k, q_span; - mg_lchain_t *ri = NULL; - for (i = 0; i < n_lc; ++i) { - ri = &lc[i]; - k = ri->off; - ri->rs = (int32_t)a[k].x + 1 > q_span? (int32_t)a[k].x + 1 - q_span : 0; // for HPC k-mer - ri->qs = (int32_t)a[k].y + 1 - (a[k].y>>32 & 0xff); - ri->re = (int32_t)a[k + ri->cnt - 1].x + 1; - ri->qe = (int32_t)a[k + ri->cnt - 1].y + 1; - } -} - -void print_gchain(gc_frag_t *a, const int64_t *p, mg_lchain_t *lc, const int64_t nlc, const ma_ug_t *ug, int32_t qlen) -{ - int64_t k, i; - gc_frag_t *ai = NULL; - mg_lchain_t *li = NULL; - for (k = 0; k < nlc; k++) { - fprintf(stderr, "\n"); - for (i = k; i >= 0; i = p[i]) { - ai = &a[i]; li = &lc[ai->i]; - fprintf(stderr, "*\tXXXXXX\tutg%.6d%c\t%c\tqs:%u\tqe:%u\tql:%d\tts:%u\tte:%u\ttl:%u\n", - (li->v>>1)+1, "lc"[ug->u.a[li->v>>1].circ], "+-"[li->v&1], li->qs, li->qe, qlen, li->rs, li->re, ug->u.a[li->v>>1].len); - } - } -} - -// void extend_graph_coordnates(const ma_ug_t *ug, const ug_opt_t *uopt, const mg_lchain_t *lp, const mg_lchain_t *la, -// mg_coor_t *gp, mg_coor_t *ga, int32_t *go, int32_t *gg) -// { -// int32_t so = specific_ovlp(ug, uopt, lp->v^1, la->v^1); -// } - -int32_t mg_gchain1_dp(void *km, const ma_ug_t *ug, const asg_t *rg, int32_t *n_lc_, mg_lchain_t *lc, int32_t qlen, int32_t max_dist_g, int32_t max_dist_q, int32_t bw, int32_t max_skip, - int32_t ref_bonus, float chn_pen_gap, float mask_level, int32_t max_gc_seq_ext, const ug_opt_t *uopt, const mg128_t *an, uint64_t **u_) -{ - int32_t i, j, k, m_dst, n_dst, n_ext, n_u, n_v, n_lc = *n_lc_, rrs, rre; - int32_t *f, *v, *t, li_qs, li_qe, li_rs, li_re, lj_qs, lj_qe, lj_rs, lj_re; - int64_t *p; - uint64_t *u; - mg_path_dst_t *dst; - gc_frag_t *a; - mg_lchain_t *swap; - // char *qs; - asg_t *g = ug->g; - - *u_ = 0; - if (n_lc == 0) return 0; - - // extend_lchain(lc, n_lc, qlen, ug); - KMALLOC(km, a, n_lc); - ///n_lc how many linear chains; just filter some linear chains - for (i = n_ext = 0; i < n_lc; ++i) { // a[] is a view of frag[]; for sorting - mg_lchain_t *r = &lc[i]; - gc_frag_t *ai = &a[i]; - int32_t is_isolated = 0, min_end_dist_g; - transfor_coord(r, qlen, ug->u.a[r->v>>1].len, NULL, NULL, &rrs, &rre); - r->dist_pre = -1;///indicate parent in graph chain - min_end_dist_g = g->seq[r->v>>1].len - rre;///r->v: ref_id|rev - if (rrs < min_end_dist_g) min_end_dist_g = rrs; - if (min_end_dist_g > max_dist_g) is_isolated = 1; // if too far from segment ends - else if (min_end_dist_g>>3 > r->score) is_isolated = 1; // if the lchain too small relative to distance to the segment ends - ai->srt = (uint32_t)is_isolated<<31 | r->qe; - ai->i = i; - if (!is_isolated) ++n_ext; - } - ///if the alignment is too far from segment ends, which means it cannot contribute to graph alignment - if (n_ext < 2) { // no graph chaining needed; early return - kfree(km, a); - KMALLOC(km, u, n_lc); - for (i = 0; i < n_lc; ++i) - u[i] = (uint64_t)lc[i].score<<32 | 1; - *u_ = u; - // compress_lchain(lc, n_lc, qlen, ug, an); - return n_lc; - } - radix_sort_gc(a, a + n_lc);///sort by: is_isolated(1):qe - - KMALLOC(km, v, n_lc); - KMALLOC(km, f, n_ext); - KMALLOC(km, p, n_ext); - KCALLOC(km, t, n_ext); - // KMALLOC(km, qs, max_dist_q + 1);//for - - m_dst = n_dst = 0, dst = 0; - ///n_ext is number of linear chains that might be included in graph chains - ///sorted by the positions in query; sorted by qe of each chain - for (i = 0; i < n_ext; ++i) { // core loop - gc_frag_t *ai = &a[i]; - mg_lchain_t *li = &lc[ai->i];///linear chain; sorted by qe, i.e. end position in query - int32_t mm_ovlp = max_ovlp(ug->g, li->v^1); - transfor_coord(li, qlen, ug->u.a[li->v>>1].len, &li_qs, &li_qe, &li_rs, &li_re); - ///note segi is query id, instead of ref id; it is not such useful - /** - * a[].x: idx_in_minimizer_arr(32)r_pos(32) - * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) - **/ - { // collect end points potentially reachable from _i_ - int32_t x = li->qs + bw + mm_ovlp, n_skip = 0; - if (x > qlen) x = qlen; - ///collect alignments that can be reachable from the left side - ///that is, a[x].qe <= x - x = find_max(i, a, x); - n_dst = 0; - for (j = x; j >= 0; --j) { // collect potential destination vertices - gc_frag_t *aj = &a[j]; - //potential chains that might be overlapped with the left side of li - mg_lchain_t *lj = &lc[aj->i]; - mg_path_dst_t *q; - int32_t target_dist, dq/**, so = specific_ovlp(ug, uopt, li->v^1, lj->v^1)**/; - transfor_coord(lj, qlen, ug->u.a[lj->v>>1].len, &lj_qs, &lj_qe, &lj_rs, &lj_re); - ///lj->qs >= li->qs && lj->qe <= li->qs, so lj is contained - if (lj->qs >= li->qs) continue; // lj is contained in li on the query coordinate - /** - * doesn't work for overlap graph - if (lj_qe > li_qs) { // test overlap on the query - int o = lj_qe - li_qs - so;///get_lchain_ovlp(lj, li, ug->g, qlen, ug); - ///mask_level = 0.5, if overlap is too long - ///note here is the overlap in query, so too long overlaps might be wrong - if (o > (lj->qe - lj->qs) * mask_level || o > (li->qe - li->qs) * mask_level) - continue; - } - **/ - dq = li_qs - lj_qe;///dq might be smaller than 0 - if (dq > max_dist_q) break; // if query gap too large, stop - ///The above filter chains like: - ///1. lj is contained in li - ///2. the overlap between li and lj is too large - ///3. li and lj are too far - ///above we have checked gap/overlap in query - ///then we need to check gap/overlap in reference - if (li->v != lj->v) { // the two linear chains are on two different refs - // minimal graph gap; the real graph gap might be larger - int32_t min_dist = li_rs + (g->seq[lj->v>>1].len - lj_re); - if (min_dist > max_dist_g) continue; // graph gap too large - //note here min_dist - (lj->qs - li->qe) > bw is important - //min_dist is always larger than 0, (lj->qs - li->qe) might be negative - /** - * doesn't work for overlap graph - min_dist -= so; - if (min_dist - bw > li->qs - lj->qe) continue; ///note seg* is the query id, instead of ref id - **/ - target_dist = mg_target_dist(g, lj, li); - if (target_dist < 0) continue; // this may happen if the query overlap is far too large - } else if (lj->rs >= li->rs || lj->re >= li->re) { // not colinear - continue; - } else {///li->v == lj->v and colinear; at the same ref id - ///w is indel, w is always positive - int32_t dr = li->rs - lj->re, dq = li->qs - lj->qe, w = dr > dq? dr - dq : dq - dr; - ///note that l*->v is the ref id, while seg* is the query id - if (w > bw) continue; // test bandwidth - if (dr > max_dist_g || dr < -max_dist_g) continue; - if (lj->re > li->rs) { // test overlap on the graph segment - int o = lj->re - li->rs; - if (o > (lj->re - lj->rs) * mask_level || o > (li->re - li->rs) * mask_level) - continue; - } - target_dist = mg_target_dist(g, lj, li); - } - if (n_dst == m_dst) KEXPAND(km, dst, m_dst); // TODO: watch out the quadratic behavior! - q = &dst[n_dst++];///q saves information for i->j - memset(q, 0, sizeof(mg_path_dst_t)); - ///note v is (rid:rev), so two alignment chains might be at the same ref id with different directions - q->inner = (li->v == lj->v); - q->v = lj->v^1;///must be v^1 instead of v - q->meta = j; - q->qlen = li->qs - lj->qe;///might be negative - /** - * doesn't work for overlap graph - q->so = 0; - if(li->v != lj->v && lj->qe > li->qs) { - lj_qe = lj->qe; li_qs = li->qs + g->seq[lj->v>>1].len - so; - q->so = lj_qe - li_qs; - if(q->so < 0) q->so = 0; - } - **/ - q->target_dist = target_dist;///cannot understand the target_dist - q->target_hash = 0; - q->check_hash = 0; - if (t[j] == i) {///this pre-cut is weird; attention - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - } - ///the above saves all linear chains that might be reached to the left side of chain i - ///all those chains are saved to dst - { // confirm reach-ability - int32_t k; - // test reach-ability without sequences - // (g->seg[li->v>>1].len - li->rs) ----> is like the node length in string graph - mg_shortest_k(km, g, li->v^1, n_dst, dst, max_dist_g + (g->seq[li->v>>1].len - li->rs), MG_MAX_SHORT_K, /**0, 0, 1,**/ 0); - // remove unreachable destinations - for (j = k = 0; j < n_dst; ++j) { - mg_path_dst_t *dj = &dst[j]; - int32_t sc; - if (dj->n_path == 0) continue; // unreachable - sc = cal_sc(dj, li, lc, an, a, f, bw, ref_bonus, chn_pen_gap); - if (sc == INT32_MIN) continue; // out of band - if (sc + li->score < 0) continue; // negative score and too low - dst[k] = dst[j]; - dst[k++].srt_key = INT64_MAX/2 - (int64_t)sc; // sort in the descending order - } - n_dst = k; - if (n_dst > 0) { - radix_sort_dst(dst, dst + n_dst); - // discard weaker chains if the best score is much larger (assuming base-level heuristic won't lift it to the top chain) - // dst[0].srt_key has the largest score - for (j = 1; j < n_dst; ++j) - if ((int64_t)(dst[j].srt_key - dst[0].srt_key) > li->score)//discard chains with too small weight - break; - n_dst = j; - if (n_dst > max_gc_seq_ext) n_dst = max_gc_seq_ext; // discard weaker chains - } - } - /** //path - if (n_dst > 0) { // find paths with sequences - int32_t min_qs = li->qs; - for (j = 0; j < n_dst; ++j) { - const mg_lchain_t *lj; - assert(dst[j].n_path > 0); - ///a[]->srt = (uint32_t)is_isolated<<31 | r->qe; - ///a[]->i = i; - lj = &lc[a[dst[j].meta].i]; - if (lj->qe < min_qs) min_qs = lj->qe; - } - ///qs keeps the sequence at the gap between the li and lj in query - memcpy(qs, &qseq[min_qs], li->qs - min_qs); - mg_shortest_k(km, g, li->v^1, n_dst, dst, max_dist_g + (g->seg[li->v>>1].len - li->rs), MG_MAX_SHORT_K, li->qs - min_qs, qs, 1, 0); - if (mg_dbg_flag & MG_DBG_GC1) fprintf(stderr, "[src:%d] q_intv=[%d,%d), src=%c%s[%d], n_dst=%d, max_dist=%d, min_qs=%d, lc_score=%d\n", ai->i, li->qs, li->qe, "><"[(li->v&1)^1], g->seg[li->v>>1].name, li->v^1, n_dst, max_dist_g + (g->seg[li->v>>1].len - li->rs), min_qs, li->score); - }**/ - { // DP - int32_t max_f = li->score, max_j = -1, max_d = -1, max_inner = 0; - uint32_t max_hash = 0; - for (j = 0; j < n_dst; ++j) { - mg_path_dst_t *dj = &dst[j]; - int32_t sc; - sc = cal_sc(dj, li, lc, an, a, f, bw, ref_bonus, chn_pen_gap); - if (sc == INT32_MIN) continue; - if (sc > max_f) max_f = sc, max_j = dj->meta, max_d = dj->dist, max_hash = dj->hash, max_inner = dj->inner; - } - f[i] = max_f, p[i] = max_j; - li->dist_pre = max_d; - li->hash_pre = max_hash; - li->inner_pre = max_inner; - v[i] = max_j >= 0 && v[max_j] > max_f? v[max_j] : max_f; - } - } - kfree(km, dst); - - // print_gchain(a, p, lc, n_ext, ug, qlen); - - // kfree(km, qs); - ///n_ext: number of useful chains - ///n_lc - n_ext: number of isoated chains - u = mg_chain_backtrack(km, n_ext, f, p, v, t, 0, 0, n_lc - n_ext, &n_u, &n_v); - kfree(km, f); kfree(km, p); kfree(km, t); - ///store the extra isoated chains - for (i = 0; i < n_lc - n_ext; ++i) { - u[n_u++] = (uint64_t)lc[a[n_ext + i].i].score << 32 | 1; - v[n_v++] = n_ext + i; - } - - ///reorganize lc; - KMALLOC(km, swap, n_v); - for (i = 0, k = 0; i < n_u; ++i) { - int32_t k0 = k, ni = (int32_t)u[i]; - for (j = 0; j < ni; ++j) - swap[k++] = lc[a[v[k0 + (ni - j - 1)]].i]; - } - assert(k == n_v); - memcpy(lc, swap, n_v * sizeof(mg_lchain_t)); - *n_lc_ = n_v; - *u_ = u; - // compress_lchain(lc, *n_lc_, qlen, ug, an); - - kfree(km, a); - kfree(km, swap); - kfree(km, v); - return n_u; -} - - -static inline void copy_lchain(mg_llchain_t *q, const mg_lchain_t *p, int32_t *n_a, mg128_t *a_new, const mg128_t *a_old) -{ - q->cnt = p->cnt, q->v = p->v, q->score = p->score; - memcpy(&a_new[*n_a], &a_old[p->off], q->cnt * sizeof(mg128_t)); - q->off = *n_a; - (*n_a) += q->cnt; -} - -void mg_gchain_extra(const asg_t *g, mg_gchains_t *gs) -{ - int32_t i, j, k; - for (i = 0; i < gs->n_gc; ++i) { // iterate over gchains - mg_gchain_t *p = &gs->gc[i]; - const mg_llchain_t *q; - const mg128_t *last_a; - int32_t q_span, rest_pl, tmp, n_mini; - - p->qs = p->qe = p->ps = p->pe = -1, p->plen = p->blen = p->mlen = 0, p->div = -1.0f; - if (p->cnt == 0) continue; - ///some linear chains in middle might be [].cnt == 0 - ///but for the first and the last linear chains, [].cnt > 0 - assert(gs->lc[p->off].cnt > 0 && gs->lc[p->off + p->cnt - 1].cnt > 0); // first and last lchains can't be empty - q = &gs->lc[p->off]; - q_span = (int32_t)(gs->a[q->off].y>>32&0xff); - /** - * a[].x: idx_in_minimizer_arr(32)r_pos(32) - * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) - * **/ - p->qs = (int32_t)gs->a[q->off].y + 1 - q_span;///calculated by the first lchain - p->ps = (int32_t)gs->a[q->off].x + 1 - q_span;///calculated by the first lchain - tmp = (int32_t)(gs->a[q->off].x>>32); - assert(p->qs >= 0 && p->ps >= 0); - q = &gs->lc[p->off + p->cnt - 1];///last lchain - p->qe = (int32_t)gs->a[q->off + q->cnt - 1].y + 1; - p->pe = g->seq[q->v>>1].len - (int32_t)gs->a[q->off + q->cnt - 1].x - 1; // this is temporary - n_mini = (int32_t)(gs->a[q->off + q->cnt - 1].x>>32) - tmp + 1; - assert(p->n_anchor > 0); - - rest_pl = 0; // this value is never used if the first lchain is not empty (which should always be true) - last_a = &gs->a[gs->lc[p->off].off];///first minizers in the first linear chain - for (j = 0; j < p->cnt; ++j) { // iterate over lchains - const mg_llchain_t *q = &gs->lc[p->off + j]; - int32_t vlen = g->seq[q->v>>1].len;///node length in graph - p->plen += vlen; - for (k = 0; k < q->cnt; ++k) { // iterate over anchors - const mg128_t *r = &gs->a[q->off + k]; - int32_t pl, ql = (int32_t)r->y - (int32_t)last_a->y; - int32_t span = (int32_t)(r->y>>32&0xff); - if (j == 0 && k == 0) { // the first anchor on the first lchain - pl = ql = span; - } else if (j > 0 && k == 0) { // the first anchor but not on the first lchain - pl = (int32_t)r->x + 1 + rest_pl; - } else { - pl = (int32_t)r->x - (int32_t)last_a->x; - } - if (ql < 0) ql = -ql, n_mini += (int32_t)(last_a->x>>32) - (int32_t)(r->x>>32); // dealing with overlapping query at junctions - p->blen += pl > ql? pl : ql; - p->mlen += pl > span && ql > span? span : pl < ql? pl : ql; - last_a = r; - } - if (q->cnt == 0) rest_pl += vlen; - else rest_pl = vlen - (int32_t)gs->a[q->off + q->cnt - 1].x - 1; - } - p->pe = p->plen - p->pe; - assert(p->pe >= p->ps); - // here n_mini >= p->n_anchor should stand almost all the time - p->div = n_mini >= p->n_anchor? log((double)n_mini / p->n_anchor) / q_span : log((double)p->n_anchor / n_mini) / q_span; - } -} - -// reorder gcs->a[] and gcs->lc[] such that they are in the same order as gcs->gc[] -void mg_gchain_restore_order(void *km, mg_gchains_t *gcs) -{ - int32_t i, n_a, n_lc; - mg_llchain_t *lc; - mg128_t *a; - KMALLOC(km, lc, gcs->n_lc); - KMALLOC(km, a, gcs->n_a); - n_a = n_lc = 0; - for (i = 0; i < gcs->n_gc; ++i) { - mg_gchain_t *gc = &gcs->gc[i]; - assert(gc->cnt > 0); - memcpy(&lc[n_lc], &gcs->lc[gc->off], gc->cnt * sizeof(mg_llchain_t)); - memcpy(&a[n_a], &gcs->a[gcs->lc[gc->off].off], gc->n_anchor * sizeof(mg128_t)); - n_lc += gc->cnt, n_a += gc->n_anchor; - } - memcpy(gcs->lc, lc, gcs->n_lc * sizeof(mg_llchain_t)); - memcpy(gcs->a, a, gcs->n_a * sizeof(mg128_t)); - kfree(km, lc); kfree(km, a); -} - -// sort chains by score -void mg_gchain_sort_by_score(void *km, mg_gchains_t *gcs) -{ - mg128_t *z; - mg_gchain_t *gc; - int32_t i; - KMALLOC(km, z, gcs->n_gc); - KMALLOC(km, gc, gcs->n_gc); - for (i = 0; i < gcs->n_gc; ++i) - z[i].x = (uint64_t)gcs->gc[i].score << 32 | gcs->gc[i].hash, z[i].y = i; - radix_sort_128x(z, z + gcs->n_gc); - for (i = gcs->n_gc - 1; i >= 0; --i) - gc[gcs->n_gc - 1 - i] = gcs->gc[z[i].y]; - memcpy(gcs->gc, gc, gcs->n_gc * sizeof(mg_gchain_t)); - kfree(km, z); kfree(km, gc); - mg_gchain_restore_order(km, gcs); // this put gcs in the proper order -} - -///u[]: sc|occ of chains -///a[]: candidate list -///gcs[0] = mg_gchain_gen(0, b->km, gi->g, n_gc, u, lc, a, hash, opt->min_gc_cnt, opt->min_gc_score); -// TODO: if frequent malloc() is a concern, filter first and then generate gchains; or generate gchains in thread-local pool and then move to global malloc() -mg_gchains_t *mg_gchain_gen(void *km_dst, void *km, const asg_t *g, int32_t n_u, const uint64_t *u, const mg_lchain_t *lc, const mg128_t *a, - uint32_t hash, int32_t min_gc_cnt, int32_t min_gc_score) -{ - mg_gchains_t *gc; - mg_llchain_t *tmp; - int32_t i, j, k, st, n_g, n_a, s_tmp, n_tmp, m_tmp; - KCALLOC(km_dst, gc, 1); - // count the number of gchains and remaining anchors - // filter out low-quality g_chains - for (i = 0, st = 0, n_g = n_a = 0; i < n_u; ++i) { - ///nui: how many linear chaisn in i-th g_chain - int32_t m = 0, nui = (int32_t)u[i]; - for (j = 0; j < nui; ++j) m += lc[st + j].cnt; // m is the number of anchors in this gchain - if (m >= min_gc_cnt && (int64_t)(u[i]>>32) >= min_gc_score) - ++n_g, n_a += m; - st += nui; - } - if (n_g == 0) return gc; - - // preallocate - gc->km = km_dst; - gc->n_gc = n_g, gc->n_a = n_a; - KCALLOC(km_dst, gc->gc, n_g);///all graph chains - KMALLOC(km_dst, gc->a, n_a);///all anchors, aka minimizers - - // core loop - tmp = 0; s_tmp = n_tmp = m_tmp = 0; - for (i = k = 0, st = 0, n_a = 0; i < n_u; ++i) { - int32_t n_a0 = n_a, m = 0, nui = (int32_t)u[i]; ///nui: how many linear chaisn in i-th g_chain - for (j = 0; j < nui; ++j) m += lc[st + j].cnt; ///how many minizers in i-th g_chain - if (m >= min_gc_cnt && (int64_t)(u[i]>>32) >= min_gc_score) { - mg_llchain_t *q; - uint32_t h = hash; - - gc->gc[k].score = u[i]>>32; ///chain score - gc->gc[k].off = s_tmp; ///all minimizers of k-th chain: gc->a[gc->gc[k].off, ) - - for (j = 0; j < nui; ++j) {///how many linear chains - const mg_lchain_t *p = &lc[st + j]; - h += __ac_Wang_hash(p->qs) + __ac_Wang_hash(p->re) + __ac_Wang_hash(p->v); - } - gc->gc[k].hash = __ac_Wang_hash(h);///hash key for the k-th graph chain - - if (n_tmp == m_tmp) KEXPAND(km, tmp, m_tmp); - // copy the first lchain to gc->a[] and tmp[] (aka, gc->lc[]) - // for the first lchain, it is easy and we just copy all its anchors - copy_lchain(&tmp[n_tmp++], &lc[st], &n_a, gc->a, a); - ///0-th lchain has been stored - ///process the remaining chains - for (j = 1; j < nui; ++j) { - const mg_lchain_t *l0 = &lc[st + j - 1], *l1 = &lc[st + j]; - if (!l1->inner_pre) { // bridging two segments; if l0 and l1 are at different reference - int32_t s, n_pathv; - mg_path_dst_t dst; - mg_pathv_t *p; - memset(&dst, 0, sizeof(mg_path_dst_t)); - dst.v = l0->v ^ 1; - assert(l1->dist_pre >= 0); - dst.target_dist = l1->dist_pre; - dst.target_hash = l1->hash_pre;///hash value of the whole path - dst.check_hash = 1; - p = mg_shortest_k(km, g, l1->v^1, 1, &dst, dst.target_dist, MG_MAX_SHORT_K, &n_pathv); - if (n_pathv == 0 || dst.target_hash != dst.hash) - fprintf(stderr, "%c[%d] -> %c[%d], dist=%d, target_dist=%d\n", "><"[(l1->v^1)&1], l1->v^1, "><"[(l0->v^1)&1], l0->v^1, dst.dist, dst.target_dist); - assert(n_pathv > 0); - assert(dst.target_hash == dst.hash); - for (s = n_pathv - 2; s >= 1; --s) { // path found in a backward way, so we need to reverse it - if (n_tmp == m_tmp) KEXPAND(km, tmp, m_tmp); - q = &tmp[n_tmp++]; - q->off = q->cnt = q->score = 0; - q->v = p[s].v^1; // when reversing a path, we also need to flip the orientation - } - kfree(km, p); - if (n_tmp == m_tmp) KEXPAND(km, tmp, m_tmp); - copy_lchain(&tmp[n_tmp++], l1, &n_a, gc->a, a); - } - else { // if both of them are at the same linear chain, just merge them - #if 1 - int32_t k; - mg_llchain_t *t = &tmp[n_tmp - 1];//the last lchain, have alread done - assert(l0->v == l1->v); - // a[].x: ref_id(31)rev(1)r_pos(32) - // a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) - for (k = 0; k < l1->cnt; ++k) { - const mg128_t *ak = &a[l1->off + k]; - if ((int32_t)ak->x > l0->re && (int32_t)ak->y > l0->qe)//find colinear anchors - break; - } - assert(k < l1->cnt); - t->cnt += l1->cnt - k, t->score += l1->score; - memcpy(&gc->a[n_a], &a[l1->off + k], (l1->cnt - k) * sizeof(mg128_t)); - n_a += l1->cnt - k; - #else // don't use this block; for debugging only - if (n_tmp == m_tmp) KEXPAND(km, tmp, m_tmp); - copy_lchain(&tmp[n_tmp++], l1, &n_a, gc->a, a); - #endif - } - } - gc->gc[k].cnt = n_tmp - s_tmp; - gc->gc[k].n_anchor = n_a - n_a0; - ++k, s_tmp = n_tmp; - } - st += nui;//nui: how many linear chains in this gchain - } - assert(n_a <= gc->n_a); - - gc->n_a = n_a; - gc->n_lc = n_tmp; - KMALLOC(km_dst, gc->lc, n_tmp); - memcpy(gc->lc, tmp, n_tmp * sizeof(mg_llchain_t)); - kfree(km, tmp); - - mg_gchain_extra(g, gc); - mg_gchain_sort_by_score(km, gc); - return gc; -} - - -// set r[].{id,parent,subsc}, ASSUMING r[] is sorted by score -// mg_gchain_set_parent(b->km, opt->mask_level, gcs[0]->n_gc, gcs[0]->gc, opt->sub_diff, 0); -void mg_gchain_set_parent(void *km, float mask_level, int n, mg_gchain_t *r, int sub_diff, int hard_mask_level) -{ - int i, j, k, *w; - uint64_t *cov; - if (n <= 0) return; - for (i = 0; i < n; ++i) r[i].id = i; - cov = (uint64_t*)kmalloc(km, n * sizeof(uint64_t)); - w = (int*)kmalloc(km, n * sizeof(int)); - w[0] = 0, r[0].parent = 0;///the first gchain is a primary hits; since all gchains have already been sorted by scores - for (i = 1, k = 1; i < n; ++i) {///start from the 1-th chain, instead of the 0-th chain - mg_gchain_t *ri = &r[i]; - int si = ri->qs, ei = ri->qe, n_cov = 0, uncov_len = 0; - if (hard_mask_level) goto skip_uncov; - for (j = 0; j < k; ++j) { // traverse existing primary hits to find overlapping hits - mg_gchain_t *rp = &r[w[j]]; - int sj = rp->qs, ej = rp->qe; - if (ej <= si || sj >= ei) continue;///no overlaps - if (sj < si) sj = si;///MAX(si, sj) - if (ej > ei) ej = ei;///MIN(ei, ej) - cov[n_cov++] = (uint64_t)sj<<32 | ej;///overlap coordinates - } - if (n_cov == 0) { - goto set_parent_test; // no overlapping primary hits; then i is a new primary hit - } else if (n_cov > 0) { // there are overlapping primary hits; find the length not covered by existing primary hits - int j, x = si; - radix_sort_gfa64(cov, cov + n_cov); - for (j = 0; j < n_cov; ++j) { - if ((int)(cov[j]>>32) > x) uncov_len += (cov[j]>>32) - x; - x = (int32_t)cov[j] > x? (int32_t)cov[j] : x; - } - if (ei > x) uncov_len += ei - x; - } -skip_uncov: - for (j = 0; j < k; ++j) { // traverse existing primary hits again - mg_gchain_t *rp = &r[w[j]]; - int sj = rp->qs, ej = rp->qe, min, max, ol; - if (ej <= si || sj >= ei) continue; // no overlap - min = ej - sj < ei - si? ej - sj : ei - si;///chain length - max = ej - sj > ei - si? ej - sj : ei - si;///chain length - ol = si < sj? (ei < sj? 0 : ei < ej? ei - sj : ej - sj) : (ej < si? 0 : ej < ei? ej - si : ei - si); // overlap length; TODO: this can be simplified - if ((float)ol / min - (float)uncov_len / max > mask_level) { - int cnt_sub = 0; - ri->parent = rp->parent; - rp->subsc = rp->subsc > ri->score? rp->subsc : ri->score; - if (ri->cnt >= rp->cnt) cnt_sub = 1; - if (cnt_sub) ++rp->n_sub; - break; - } - } -set_parent_test: - if (j == k) w[k++] = i, ri->parent = i, ri->n_sub = 0; - } - kfree(km, cov); - kfree(km, w); -} - -// set r[].flt, i.e. mark weak suboptimal chains as filtered -int mg_gchain_flt_sub(float pri_ratio, int min_diff, int best_n, int n, mg_gchain_t *r) -{ - if (pri_ratio > 0.0f && n > 0) { - int i, k, n_2nd = 0; - for (i = k = 0; i < n; ++i) { - int p = r[i].parent; - if (p == i) { // primary - r[i].flt = 0, ++k; - } else if ((r[i].score >= r[p].score * pri_ratio || r[i].score + min_diff >= r[p].score) && n_2nd < best_n) { - if (!(r[i].qs == r[p].qs && r[i].qe == r[p].qe && r[i].ps == r[p].ps && r[i].pe == r[p].pe)) // not identical hits; TODO: check path as well - r[i].flt = 0, ++n_2nd, ++k; - else r[i].flt = 1; - } else r[i].flt = 1; - } - return k; - } - return n; -} - -// recompute gcs->gc[].{off,n_anchor} and gcs->lc[].off, ASSUMING they are properly ordered (see mg_gchain_restore_order) -void mg_gchain_restore_offset(mg_gchains_t *gcs) -{ - int32_t i, j, n_a, n_lc; - for (i = 0, n_a = n_lc = 0; i < gcs->n_gc; ++i) { - mg_gchain_t *gc = &gcs->gc[i]; - gc->off = n_lc; - for (j = 0, gc->n_anchor = 0; j < gc->cnt; ++j) { - mg_llchain_t *lc = &gcs->lc[n_lc + j]; - lc->off = n_a; - n_a += lc->cnt; - gc->n_anchor += lc->cnt; - } - n_lc += gc->cnt; - } - assert(n_lc == gcs->n_lc && n_a == gcs->n_a); -} - -// hard drop filtered chains, ASSUMING gcs is properly ordered -void mg_gchain_drop_flt(void *km, mg_gchains_t *gcs) -{ - int32_t i, n_gc, n_lc, n_a, n_lc0, n_a0, *o2n; - if (gcs->n_gc == 0) return; - KMALLOC(km, o2n, gcs->n_gc); - for (i = 0, n_gc = 0; i < gcs->n_gc; ++i) { - mg_gchain_t *r = &gcs->gc[i]; - o2n[i] = -1; - if (r->flt || r->cnt == 0) continue; - o2n[i] = n_gc++; - } - n_gc = n_lc = n_a = 0; - n_lc0 = n_a0 = 0; - for (i = 0; i < gcs->n_gc; ++i) { - mg_gchain_t *r = &gcs->gc[i]; - if (o2n[i] >= 0) { - memmove(&gcs->a[n_a], &gcs->a[n_a0], r->n_anchor * sizeof(mg128_t)); - memmove(&gcs->lc[n_lc], &gcs->lc[n_lc0], r->cnt * sizeof(mg_llchain_t)); - gcs->gc[n_gc] = *r; - gcs->gc[n_gc].id = n_gc; - gcs->gc[n_gc].parent = o2n[gcs->gc[n_gc].parent]; - ++n_gc, n_lc += r->cnt, n_a += r->n_anchor; - } - n_lc0 += r->cnt, n_a0 += r->n_anchor; - } - assert(n_lc0 == gcs->n_lc && n_a0 == gcs->n_a); - kfree(km, o2n); - gcs->n_gc = n_gc, gcs->n_lc = n_lc, gcs->n_a = n_a; - if (n_a != n_a0) { - KREALLOC(gcs->km, gcs->a, gcs->n_a); - KREALLOC(gcs->km, gcs->lc, gcs->n_lc); - KREALLOC(gcs->km, gcs->gc, gcs->n_gc); - } - mg_gchain_restore_offset(gcs); -} - -// estimate mapping quality -///mg_gchain_set_mapq(b->km, gcs, qlen, mz->n, opt->min_gc_score); -void mg_gchain_set_mapq(void *km, mg_gchains_t *gcs, int qlen, int max_mini, int min_gc_score) -{ - static const float q_coef = 40.0f; - int64_t sum_sc = 0; - float uniq_ratio, r_sc, r_cnt; - int i, t_sc, t_cnt; - if (gcs == 0 || gcs->n_gc == 0) return; - t_sc = qlen < 100? qlen : 100; - t_cnt = max_mini < 10? max_mini : 10; - if (t_cnt < 5) t_cnt = 5; - r_sc = 1.0 / t_sc; - r_cnt = 1.0 / t_cnt; - for (i = 0; i < gcs->n_gc; ++i) - if (gcs->gc[i].parent == gcs->gc[i].id) - sum_sc += gcs->gc[i].score;///primary chain - uniq_ratio = (float)sum_sc / (sum_sc + gcs->rep_len); - for (i = 0; i < gcs->n_gc; ++i) { - mg_gchain_t *r = &gcs->gc[i]; - if (r->parent == r->id) {///primary chain - int mapq, subsc; - float pen_s1 = (r->score > t_sc? 1.0f : r->score * r_sc) * uniq_ratio; - float x, pen_cm = r->n_anchor > t_cnt? 1.0f : r->n_anchor * r_cnt; - pen_cm = pen_s1 < pen_cm? pen_s1 : pen_cm; - subsc = r->subsc > min_gc_score? r->subsc : min_gc_score; - x = (float)subsc / r->score; - mapq = (int)(pen_cm * q_coef * (1.0f - x) * logf(r->score)); - mapq -= (int)(4.343f * logf(r->n_sub + 1) + .499f); - mapq = mapq > 0? mapq : 0; - if (r->score > subsc && mapq == 0) mapq = 1; - r->mapq = mapq < 60? mapq : 60; - } else r->mapq = 0; - } -} - -void mg_map_frag(const void *ha_flt_tab, const ha_pt_t *ha_idx, const ma_ug_t *ug, const asg_t *rg, const uint32_t qid, const int qlen, const char *qseq, ha_mzl_v *mz, -st_mt_t *sp, mg_tbuf_t *b, int32_t w, int32_t k, int32_t hpc, int32_t mz_sd, int32_t mz_rewin, const mg_idxopt_t *opt, const ug_opt_t *uopt, mg_gchains_t **gcs) -{ - mg128_t *a = NULL; - int64_t n_a; - int32_t *mini_pos; - int i, rep_len, n_mini_pos, n_lc, max_chain_gap_qry, max_chain_gap_ref, n_gc; - uint32_t hash; - uint64_t *u; - mg_lchain_t *lc; - km_stat_t kmst; - (*gcs) = NULL; - - hash = qid; - hash ^= __ac_Wang_hash(qlen) + __ac_Wang_hash(opt->seed); - hash = __ac_Wang_hash(hash); - - mz->n = 0; - mz2_ha_sketch(qseq, qlen, w, k, 0, hpc, mz, ha_flt_tab, mz_sd, NULL, NULL, NULL, -1, -1, -1, sp, mz_rewin, 1, NULL); - ///a[]->y: weight(8)seg_id(8)flag(8)span(8)pos(32);--->query - ///a[]->x: rid(31)rev(1)rpos(33);--->reference - a = collect_seed_hits(b->km, opt, 1/**opt->hap_n**/, ha_flt_tab, ha_idx, ug, mz, &n_a, &rep_len, &n_mini_pos, &mini_pos); - /** - // might be recover - if (opt->max_gap_pre > 0 && opt->max_gap_pre * 2 < opt->max_gap) n_a = flt_anchors(n_a, a, opt->max_gap_pre); - max_chain_gap_qry = max_chain_gap_ref = opt->max_gap; - **/ - max_chain_gap_qry = max_chain_gap_ref = qlen*2; - if (n_a == 0) {//no matched minimizer - if(a) kfree(b->km, a); - a = 0, n_lc = 0, u = 0; - } else { - a = mg_lchain_dp(max_chain_gap_ref, max_chain_gap_qry, opt->bw, opt->max_lc_skip, opt->max_lc_iter, - opt->min_lc_cnt, opt->min_lc_score, opt->chn_pen_gap, n_a, a, &n_lc, &u, b->km); - } - - if (n_lc) {///n_lc is how many linear chain we found - lc = mg_lchain_gen(b->km, qlen, n_lc, u, a, ug);//lc->the status of each chain; u->idx of each chain; - for (i = 0; i < n_lc; ++i)///update a[] since ref_id|rev has already been saved to lc[].v - mg_update_anchors(lc[i].cnt, &a[lc[i].off], n_mini_pos, mini_pos);///update a[].x - } else lc = 0; - kfree(b->km, mini_pos); kfree(b->km, u); - // fprintf(stderr, "++0++qid: %u, qlen: %d, n_a: %ld, n_lc: %d\n", qid, qlen, n_a, n_lc); - /** - * up to here, a[] has been changed - * a[].x: idx_in_minimizer_arr(32)r_pos(32) - * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) - **/ - // for (i = 0; i < n_lc; i++) { - // mg_lchain_t *ri = &lc[i]; - // fprintf(stderr, "+0)))))))))))))))))))))))))))+\tA\tutg%.6d%c\t%c\tqs:%u\tqe:%u\tql:%d\tts:%u\tte:%u\ttl:%u\n", - // (ri->v>>1)+1, "lc"[ug->u.a[ri->v>>1].circ], "+-"[ri->v&1], ri->qs, ri->qe, qlen, ri->rs, ri->re, ug->u.a[ri->v>>1].len); - // } - max_chain_gap_qry = max_chain_gap_ref = opt->max_gap; - n_gc = mg_gchain1_dp(b->km, ug, rg, &n_lc, lc, qlen, max_chain_gap_ref, max_chain_gap_qry, opt->bw, opt->max_gc_skip, opt->ref_bonus, - opt->chn_pen_gap, opt->mask_level, opt->max_gc_seq_ext, uopt, a, &u); - // for (i = 0; i < n_lc; i++) { - // mg_lchain_t *ri = &lc[i]; - // fprintf(stderr, "-0-\tA\tutg%.6d%c\t%c\tqs:%u\tqe:%u\tql:%d\tts:%u\tte:%u\ttl:%u\n", - // (ri->v>>1)+1, "lc"[ug->u.a[ri->v>>1].circ], "+-"[ri->v&1], ri->qs, ri->qe, qlen, ri->rs, ri->re, ug->u.a[ri->v>>1].len); - // } - (*gcs) = mg_gchain_gen(0, b->km, ug->g, n_gc, u, lc, a, hash, opt->min_gc_cnt, opt->min_gc_score); - (*gcs)->rep_len = rep_len; (*gcs)->qid = qid; (*gcs)->qlen = qlen; - kfree(b->km, a); - kfree(b->km, lc); - kfree(b->km, u); - - mg_gchain_set_parent(b->km, opt->mask_level, (*gcs)->n_gc, (*gcs)->gc, opt->sub_diff, 0); - mg_gchain_flt_sub(opt->pri_ratio, k * 2, opt->best_n, (*gcs)->n_gc, (*gcs)->gc); - mg_gchain_drop_flt(b->km, (*gcs)); - mg_gchain_set_mapq(b->km, (*gcs), qlen, mz->n, opt->min_gc_score); - - if (b->km) { - km_stat(b->km, &kmst); - if (kmst.n_blocks != kmst.n_cores) { - fprintf(stderr, "[E::%s] memory leak at %u\n", __func__, qid); - abort(); - } - if (kmst.largest > 1U<<28) { - km_destroy(b->km); - b->km = km_init(); - } - } - // fprintf(stderr, "++6++qid: %u, (*gcs)->n_gc: %d\n", qid, (*gcs)->n_gc); - -} - -static void worker_for_ul_alignment(void *data, long i, int tid) // callback for kt_for() -{ - utepdat_t *s = (utepdat_t*)data; - mg_map_frag(s->ha_flt_tab, s->ha_idx, s->ug, s->rg, s->id+i, s->len[i], s->seq[i], &(s->mzs[tid]), &(s->sps[tid]), s->buf[tid], s->opt->w, s->opt->k, - s->opt->is_HPC, asm_opt.mz_sample_dist, asm_opt.mz_rewin, s->opt, s->uopt, &(s->gcs[i])); -} - -uint32_t overlap_statistics(overlap_region_alloc* olist, ma_ug_t *ug, int64_t *tt, uint8_t mm) -{ - uint32_t k, sp = (uint32_t)-1, ep = (uint32_t)-1, l = 0; - for (k = 0; k < olist->length; k++) { - /** - if(b->olist.list[k].y_id != 38) continue; - **/ - /** - - for (z = 0, te = ta = tua = 0; z < b->olist.list[k].w_list_length; z++) { - if(b->olist.list[k].w_list[z].y_end != -1) { - te += b->olist.list[k].w_list[z].error; - ta += b->olist.list[k].w_list[z].x_end + 1 - b->olist.list[k].w_list[z].x_start; - fprintf(stderr, "x->[%lu, %lu), y->[%d, %d), e->%d\n", b->olist.list[k].w_list[z].x_start, b->olist.list[k].w_list[z].x_end+1, - b->olist.list[k].w_list[z].y_start, b->olist.list[k].w_list[z].y_end+1, b->olist.list[k].w_list[z].error); - } - else { - tua += b->olist.list[k].w_list[z].x_end + 1 - b->olist.list[k].w_list[z].x_start; - } - } - fprintf(stderr, "[M::utg%.6d%c::is_match:%u] x->[%u, %u); y->[%u, %u), ualigned->%u, e_rate->%f\n", b->olist.list[k].y_id+1, "lc"[s->ug->u.a[b->olist.list[k].y_id].circ], - b->olist.list[k].is_match == 1, b->olist.list[k].x_pos_s, b->olist.list[k].x_pos_e+1, b->olist.list[k].y_pos_s, b->olist.list[k].y_pos_e+1, tua, (float)te/(float)ta); - **/ - if(tt){ - uint32_t z; - for (z = 0; z < olist->list[k].w_list.n; z++) { - if(olist->list[k].w_list.a[z].y_end != -1) { - if(tt) *tt += olist->list[k].w_list.a[z].x_end+1-olist->list[k].w_list.a[z].x_start; - } - } - } - if(olist->list[k].is_match == mm) { - if(sp == (uint32_t)-1 || ep < olist->list[k].x_pos_s) { - if(sp != (uint32_t)-1) l += ep + 1 - sp; - sp = olist->list[k].x_pos_s; - ep = olist->list[k].x_pos_e; - } else { - ep = MAX(ep, olist->list[k].x_pos_e); - } - if(ug) { - fprintf(stderr, "[M::utg%.6d%c::is_match->%u] rev->%u, x->[%u, %u), y->[%u, %u)\n", (int)olist->list[k].y_id+1, "lc"[ug->u.a[olist->list[k].y_id].circ], olist->list[k].is_match, - olist->list[k].y_pos_strand, olist->list[k].x_pos_s, olist->list[k].x_pos_e+1, olist->list[k].y_pos_s, olist->list[k].y_pos_e+1); - } - } - } - if(sp != (uint32_t)-1) l += ep + 1 - sp; - return l; -} -/** -void replace_ul(overlap_region_alloc* olist, Correct_dumy* dumy, haplotype_evdience_alloc* hap, const ul_idx_t *uu) -{ - int64_t k, z, n = 0, c_qs, c_qe, c_ts, c_te, c_rev, p_qs, p_qe, p_te, p_ts, p_rev; - uint64_t *sc = NULL, *track = NULL; - overlap_region *c = NULL, *p = NULL; - dumy->length = 0; - for (k = 0; k < olist->length; k++) {///has already sorted by x_pos_e - if(olist->list[k].is_match!=1) continue; - dumy->overlapID[dumy->length] = (uint64_t)-1; - dumy->overlapID[dumy->length] <<= 32; - dumy->overlapID[dumy->length] |= k; - dumy->length++; - } - - kv_resize(uint64_t, hap->snp_srt, dumy->length); - hap->snp_srt.n = dumy->length; - memset(hap->snp_srt.a, 0, hap->snp_srt.n*sizeof(uint64_t)); - - sc = dumy->overlapID; track = hap->snp_srt.a; n = dumy->length; - for (k = 0; k < n; k++) { - c = &(olist->list[(uint32_t)track[k]]); - for (z = k-1; z >= 0; z--) { - p = &(olist->list[(uint32_t)track[z]]); - } - } -} -**/ - -uint64_t update_ava_het_site(haplotype_evdience_alloc *h, uint64_t oid, uint64_t *beg, uint64_t *end, uint64_t is_srt) -{ - uint64_t k, l, i, occ = 0, n = h->length, need_srt = 0; SnpStats *s = NULL; - haplotype_evdience tt; - l = beg? (*beg):0; if(end) (*end) = n; if(beg) (*beg) = n; - if(l < n && h->list[l].overlapID > oid){ - if(end) (*end) = l; - return 0; - } - for (k = l + 1; k <= n; ++k) { - if(h->list[l].overlapID > oid) { - if(end) (*end) = l; - break; - } - if (k == n || h->list[k].overlapID != h->list[l].overlapID) { - if(h->list[l].overlapID == oid) { - for (i = l; i < k; i++) { - if(h->list[i].type!=1) continue; - s = &(h->snp_stat.a[h->list[i].overlapSite]); - if(s->score == 1 && (!(s->occ_0 < 2 || s->occ_1 < 2))) { - if(l+occ != i) { - tt = h->list[l+occ]; - h->list[l+occ] = h->list[i]; - h->list[i] = tt; - } - if((occ>0) && (h->list[l+occ].covlist[l+occ-1].cov)) need_srt = 1; - occ++; - } - } - if(beg) (*beg) = l; - if(end) (*end) = k; - break; - } - l = k; - } - } - // if(oid == 160) { - // fprintf(stderr, "###[M::%s] l:%lu, occ:%lu\n", __func__, l, occ); - // for (k = l; k < l + occ; k++) { - // fprintf(stderr, "h->list[%lu]:%u\n", k, h->list[k].cov); - // } - // } - if(occ && is_srt && need_srt) { - radix_sort_hap_ev_cov_srt(h->list+l, h->list+l+occ); - } - - return occ; -} - - -uint64_t gl_chain_gen(overlap_region_alloc* olist, const ul_idx_t *uref, kv_ul_ov_t *res, uint32_t rec_trans, haplotype_evdience_alloc *hap, void *km) -{ - uint64_t k, o2 = 0, si = 0, ei = 0; ul_ov_t *p = NULL; - res->n = 0; - for (k = 0; k < olist->length; k++) { - if(olist->list[k].is_match==2) o2++; - if((!rec_trans) && olist->list[k].is_match!=1) continue; - if(rec_trans && olist->list[k].is_match!=1 && olist->list[k].is_match!=2) continue; - kv_pushp_km(km, ul_ov_t, *res, &p); - p->qn = k/**olist->list[k].x_id**/; p->qs = olist->list[k].x_pos_s; p->qe = olist->list[k].x_pos_e+1; - p->tn = olist->list[k].y_id; p->sec = 0; p->rev = olist->list[k].y_pos_strand; - p->el = (olist->list[k].is_match==1?1:0); - if(p->rev) { - p->ts = uref->ug->u.a[p->tn].len - (olist->list[k].y_pos_e+1); - p->te = uref->ug->u.a[p->tn].len - olist->list[k].y_pos_s; - } else { - p->ts = olist->list[k].y_pos_s; - p->te = olist->list[k].y_pos_e+1; - } - if(olist->list[k].is_match==2) { - p->sec = update_ava_het_site(hap, k, &si, &ei, 1); - assert(p->sec > 0); - si = ei; - } - } - return o2; -} - -int32_t find_ul_ov_max(int32_t n, const ul_ov_t *a, uint32_t x) -{ - int32_t s = 0, e = n; - if (n == 0) return -1; - if (a[n-1].qe < x) return n - 1; - if (a[0].qe >= x) return -1; - while (e > s) { // TODO: finish this block - int32_t m = s + (e - s) / 2; - if (a[m].qe >= x) e = m; - else s = m + 1; - } - assert(s == e); - return s; -} - - - -int64_t get_ecov(const ul_idx_t *uref, ul_ov_t *lv, ul_ov_t *lw, int64_t qlen, int64_t bw, double diff_ec_ul) -{ - int64_t dis_q = lv->qe - lw->qe, dis_t = 0, dif, mm; - uint32_t i, v = ((lv->tn<<1)|lv->rev)^1, w = ((lw->tn<<1)|lw->rev)^1; - const asg_t *g = uref->ug->g; - uint32_t nv = asg_arc_n(g, v); - asg_arc_t *av = asg_arc_a(g, v); - for (i = 0; i < nv; i++) { - if(av[i].del || av[i].v != w) continue; - dis_t = ((uint32_t)av[i].ul); - dis_t -= (lv->rev?lv->ts:g->seq[v>>1].len-lv->te); - break; - } - - dif = (dis_q>dis_t? dis_q-dis_t:dis_t-dis_q); - mm = MAX(dis_q, dis_t); mm *= diff_ec_ul; if(mm < bw) mm = bw; - // if((v>>1) == 1163 && (w>>1) == 1168) fprintf(stderr, ">>>>>>dis_q:%ld, dis_t:%ld, dif:%ld, mm:%ld\n", dis_q, dis_t, dif, mm); - if(dif <= mm) return 1; - return 0; -} - -int64_t gl_exact_chain(kv_ul_ov_t *res, kv_ul_ov_t *ex, const ul_idx_t *uref, int64_t bw, double diff_ec_ul, -int64_t qlen, uint64_t *srt, uint64_t *idx, uint64_t *track, void *km) -{ - // fprintf(stderr, "*****************\n"); - uint32_t li_v, lj_v; - int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx; - ul_ov_t *li = NULL, *lj = NULL; - const asg_t *g = uref->ug->g; - radix_sort_ul_ov_srt_qe(res->a, res->a + res->n); - for (i = 0; i < (int64_t)res->n; ++i) { - li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; - mm_ovlp = max_ovlp(g, li_v^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(i, res->a, x); - csc = retrieve_u_cov_region(uref, li->tn, 0, li->ts, li->te, NULL); - mm_sc = csc; mm_idx = -1; - // fprintf(stderr, "---i:%ld, csc:%ld, li->tn:%u, li->ts:%u, li->te:%u\n", i, csc, li->tn, li->ts, li->te); - for (j = x; j >= 0; --j) { // collect potential destination vertices - lj = &(res->a[j]); lj_v = (lj->tn<<1)|lj->rev; - // if(lj->qs >= li->qs) continue; // lj is contained in li on the query coordinate - if(li_v != lj_v && get_ecov(uref, li, lj, qlen, bw, diff_ec_ul)) { - sc = csc + (track[j]>>32); - if(sc > mm_sc) mm_sc = sc, mm_idx = j; - } - } - // 4294967295L - track[i] = mm_sc; track[i] <<= 32; - track[i] |= (mm_idx>=0?mm_idx:((uint64_t)0x7FFFFFFF)); - srt[i] = mm_sc; srt[i] <<= 32; srt[i] |= i; - // fprintf(stderr, "+++i:%ld, mm_idx:%ld, mm_sc:%ld\n", i, mm_idx, mm_sc); - // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n\n", li->tn+1, "lc"[uref->ug->u.a[li->tn].circ], li->qs, li->qe); - } - - int64_t n_v, n_u, n_v0; - radix_sort_gfa64(srt, srt+res->n); ex->n = res->n; - for (k = (int64_t)res->n-1, n_v = n_u = 0; k >= 0; --k) { - // fprintf(stderr, "\nk:%ld\n", k); - n_v0 = n_v; - for (i = (uint32_t)srt[k]; i >= 0 && (track[i]&((uint64_t)0x80000000)) == 0;) { - ex->a[n_v++] = res->a[i]; track[i] |= ((uint64_t)0x80000000); - // fprintf(stderr, "+i:%ld, ", i); - // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n", res->a[i].tn+1, "lc"[uref->ug->u.a[res->a[i].tn].circ], res->a[i].qs, res->a[i].qe); - if((track[i]&((uint64_t)0x7FFFFFFF)) == ((uint64_t)0x7FFFFFFF)) i = -1; - else i = track[i]&((uint64_t)0x7FFFFFFF); - // if(i>=(int64_t)res->n) fprintf(stderr, "ERROR->i:%ld, res->n:%d, n_v:%ld, qlen:%ld\n", i, (int32_t)res->n, n_v, qlen); - // fprintf(stderr, "next_i:%ld\n", i); - // i = (olist->list[i].y_id == (uint32_t)-1?-1:olist->list[i].y_id); - // fprintf(stderr, "-i:%ld\n", i); - } - if(n_v0 == n_v) continue; - ///keep the whole score; do not cut score like minigraph - // sc = (i<0?(srt[k]>>32):((srt[k]>>32)-olist->list[i].x_id)); - sc = srt[k]>>32; - idx[n_u++] = ((uint64_t)sc<<32)|(n_v-n_v0); - } - // if(n_v != (int64_t)res->n) { - // fprintf(stderr, "\nERROR->n_v:%ld, res->n:%d, qlen:%ld\n", n_v, (int32_t)res->n, qlen); - // for (k = 0; k < (int64_t)res->n; k++) { - // fprintf(stderr, "(%ld)srt-sc:%lu, srt-i:%u\n", k, srt[k]>>32, (uint32_t)srt[k]); - // } - - // for (k = 0; k < (int64_t)res->n; k++) { - // fprintf(stderr, "(%ld)track-sc:%lu, track-pi:%lu\n", k, track[k]>>32, track[k]&((uint64_t)0x7FFFFFFF)); - // } - // } - // if(n_v && ex->a[0].qn == 6) { - // for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { - // n_v0 = n_v; n_v += (uint32_t)idx[k]; - // fprintf(stderr, "\n"); - // for (i = n_v0; i < n_v; i++) { - // fprintf(stderr, "[%u, %u]\n", ex->a[i].qs, ex->a->qe); - // } - // } - // } - - for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { - n_v0 = n_v; n_v += (uint32_t)idx[k]; - res->a[k].qn = idx[k]>>32; - res->a[k].ts = n_v0; res->a[k].te = n_v; - res->a[k].qs = ex->a[n_v-1].qs; - res->a[k].qe = ex->a[n_v0].qe; - } - res->n = n_u; - return res->n; -} - -uint64_t get_het_site(haplotype_evdience_alloc *hap, uint32_t oid) -{ - uint64_t k, l, i, occ = 0; SnpStats *s = NULL; - for (k = 1, l = 0; k <= hap->length; ++k) { - if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { - if(hap->list[l].overlapID != oid) { - l = k; - continue; - } - for (i = l; i < k; i++) { - if(hap->list[i].type!=1) continue; - s = &(hap->snp_stat.a[hap->list[i].overlapSite]); - if(s->score == 1 && (!(s->occ_0 < 2 || s->occ_1 < 2))) { - occ++; - } - } - l = k; - } - } - - return (occ&((uint64_t)0x3FFFFFFF)); -} - - -int64_t get_chain_x(overlap_region* ot, int64_t q) -{ - int64_t x, y, off, i, lx = -1, ly = -1; Fake_Cigar* o = &(ot->f_cigar); - x = get_fake_gap_pos(o, o->length - 1); - off = get_fake_gap_shift(o, o->length - 1); - y = x - ot->x_pos_s + ot->y_pos_s + off; - // if(ot->x_id == 98 && (q == 6681 || q == 6990)) fprintf(stderr, "o->length->%u, q->%ld, y->%ld, x->%ld\n", o->length, q, y, x); - if(y == q) return x; - - for (i = 0; i < (int64_t)o->length; i++){ - x = get_fake_gap_pos(o, i); off = get_fake_gap_shift(o, i); - y = x - ot->x_pos_s + ot->y_pos_s + off; - // if(ot->x_id == 98 && (q == 6681 || q == 6990)) fprintf(stderr, "+i->%ld, q->%ld, y->%ld, x->%ld\n", i, q, y, x); - if(q < y) { - lx = x; ly = y; - break; - } - } - - if(i == 0 || i == (int64_t)o->length) { - fprintf(stderr, "ERROR at %s:%d, x_id->%u, y_id->%u, q->%ld, i->%ld, yi_s->%u, yi_e->%u\n", - __FILE__, __LINE__, ot->x_id, ot->y_id, q, i, ot->y_pos_s, ot->y_pos_e); - exit(0); - } - - x = get_fake_gap_pos(o, i-1); off = get_fake_gap_shift(o, i-1); - y = x - ot->x_pos_s + ot->y_pos_s + off; - y = (((double)(q - y))/((double)(ly - y)))*((double)(lx -x)) + x; - // y = q - y + x; - if(y < ot->x_pos_s) y = ot->x_pos_s; - if(y > ot->x_pos_e) y = ot->x_pos_e; - return y; -} - - - -//[s, e] -double es_win_err(overlap_region* o, int64_t winLen, int64_t s, int64_t e) -{ - int64_t si, ei, os, k, tErr = 0, tLen = 0, minE, maxS, ov; - os = (o->x_pos_s/winLen)*winLen; - si = (s-os)/winLen; ei = (e-os)/winLen; - for (k = si+1; k <= ei-1; k++) { - tLen += o->w_list.a[k].x_end+1-o->w_list.a[k].x_start; - if(o->w_list.a[k].y_end != -1) { - tErr += o->w_list.a[k].error; - } else { - tErr += o->w_list.a[k].x_end+1-o->w_list.a[k].x_start; - } - } - - k = si; - maxS = MAX(s, (int64_t)(o->w_list.a[k].x_start)); minE = MIN(e, (int64_t)(o->w_list.a[k].x_end)) + 1; - ov = minE > maxS? minE - maxS:0; - if(ov == 0) { - fprintf(stderr, "WARNNING-1, o->w_list.n->%u, o->x_id->%u, s->%ld, e->%ld, w_list_s->%d, w_list_e->%d, winLen->%ld, o->x_pos_s->%u, o->x_pos_e->%u, si->%ld, flag->%d\n", - (uint32_t)o->w_list.n, o->x_id, s, e, o->w_list.a[k].x_start, o->w_list.a[k].x_end, winLen, o->x_pos_s, o->x_pos_e, si, o->w_list.a[k].y_end); - } - tLen += ov/**o->w_list[k].x_end+1-o->w_list[k].x_start**/; - if(o->w_list.a[k].y_end != -1) { - tErr += (ov*o->w_list.a[k].error)/(o->w_list.a[k].x_end+1-o->w_list.a[k].x_start); - } else { - tErr += ov/**o->w_list[k].x_end+1-o->w_list[k].x_start**/; - } - - k = ei; - maxS = MAX(s, (int64_t)(o->w_list.a[k].x_start)); minE = MIN(e, (int64_t)(o->w_list.a[k].x_end)) + 1; - ov = minE > maxS? minE - maxS:0; - if(ov == 0) { - fprintf(stderr, "WARNNING-2, o->w_list.n->%u, o->x_id->%u, s->%ld, e->%ld, w_list_s->%d, w_list_e->%d, winLen->%ld, o->x_pos_s->%u, o->x_pos_e->%u, ei->%ld, flag->%d\n", - (uint32_t)o->w_list.n, o->x_id, s, e, o->w_list.a[k].x_start, o->w_list.a[k].x_end, winLen, o->x_pos_s, o->x_pos_e, ei, o->w_list.a[k].y_end); - } - tLen += ov/**o->w_list[k].x_end+1-o->w_list[k].x_start**/; - if(o->w_list.a[k].y_end != -1) { - tErr += (ov*o->w_list.a[k].error)/(o->w_list.a[k].x_end+1-o->w_list.a[k].x_start); - } else { - tErr += ov/**o->w_list[k].x_end+1-o->w_list[k].x_start**/; - } - - return ((double)tErr)/((double)tLen); -} - -int64_t gen_contain_chain(const ul_idx_t *uref, utg_ct_t *p, overlap_region* o, kv_ul_ov_t *chains, double diff_ec_ul, int64_t winLen, void *km) -{ - int64_t y_s, y_e, y_bs, y_be, x_s, x_e, q_s, q_e; - if(o->y_pos_strand) { - y_s = uref->ug->u.a[o->y_id].len - p->e; - y_e = uref->ug->u.a[o->y_id].len - p->s - 1; - } else { - y_s = p->s; y_e = p->e - 1; - } - - - y_s = MAX(y_s, (int64_t)o->y_pos_s); y_e = MIN(y_e, (int64_t)o->y_pos_e); - if(y_s > y_e) return 0; - x_s = get_chain_x(o, y_s); x_e = get_chain_x(o, y_e) + 1; - if(x_s >= x_e) fprintf(stderr, "+++y_s->%ld, y_e->%ld, x_s->%ld, x_e->%ld\n", y_s, y_e, x_s, x_e); - if(o->y_pos_strand) { - y_bs = uref->ug->u.a[o->y_id].len - (y_e+1); - y_be = uref->ug->u.a[o->y_id].len - y_s; - } else { - y_bs = y_s; y_be = y_e + 1; - } - - q_s = 0; q_e = p->e - p->s; - if(p->x&1) { - q_s += (p->e - y_be); - q_e -= (y_bs - p->s); - } else { - q_s += (y_bs - p->s); - q_e -= (p->e - y_be); - } - // if(q_s < 0 || q_e < 0 || q_s >= (int64_t)(p->e - p->s) || q_e > (int64_t)(p->e - p->s)) fprintf(stderr, "ERROR\n"); - if(winLen > 0 && diff_ec_ul > 0 && es_win_err(o, winLen, x_s, x_e-1) > diff_ec_ul) return 0; - - ul_ov_t *x = NULL; - kv_pushp_km(km, ul_ov_t, *chains, &x); - x->qn = o->x_id; x->qs = x_s; x->qe = x_e; - - /**x->tn = p->x>>1;**/x->tn = (uint32_t)(0x80000000); x->tn |= (p->x>>1); - x->ts = q_s; x->te = q_e; x->el = 1;x->sec = 0; x->rev = ((o->y_pos_strand == (p->x&1))?0:1); - // if(((x->tn<<1)>>1) == 23113) fprintf(stderr, "x->tn:%u, o->y_id:%u\n", (x->tn<<1)>>1, o->y_id); - // if(x->qn == 0 /**&& ((x->tn<<1)>>1) == 302**/) { - // /**if(o->x_id == 0 && (o->y_id == 46 || o->y_id == 48))**/ { - // // fprintf(stderr, "\nUL[%u]\t%u\t%u\t%c\tUTG[%u]\t%u\t%u\n", o->x_id, o->x_pos_s, o->x_pos_e, - // // "+-"[o->y_pos_strand], o->y_id, o->y_pos_s, o->y_pos_e); - // // fprintf(stderr, "Contain[%u]\t%c\ts[%u]\te[%u]\n", p->x>>1, "+-"[p->x&1], p->s, p->e); - // fprintf(stderr, "U[%u]\t%u\t%u\t%c\tR[%u]\t%u\t%u\tUid[%u]\n", x->qn, x->qs, x->qe, - // "+-"[x->rev], ((x->tn<<1)>>1), x->ts, x->te, o->y_id); - // } - // } - - return 1; -} - -int64_t debug_utg_ct_t(const ul_idx_t *uref, overlap_region* o, utg_ct_t *ct_a, int64_t ct_n, ma_utg_t *u, utg_ct_t *z, haplotype_evdience *he_a, int64_t he_n) -{ - int64_t k, i, l, rs, re, ss, m = 0; - utg_ct_t *p = NULL; - if(ct_a && ct_n) { - for (i = 0; i < ct_n; i++) { - p = &(ct_a[i]); - for (k = 0; k < he_n; k++) { - ss = o->y_pos_strand?uref->ug->u.a[o->y_id].len - he_a[k].cov - 1:he_a[k].cov; - if(ss >= p->s && ss < p->e) break; - } - if(k < he_n) m++; - } - } - if(u) { - for (i = l = 0; i < u->n; i++) { - rs = l; re = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); - l += (uint32_t)u->a[i]; - for (k = 0; k < he_n; k++) { - ss = o->y_pos_strand?uref->ug->u.a[o->y_id].len - he_a[k].cov - 1:he_a[k].cov; - if(ss >= rs && ss < re) break; - } - if(k < he_n) m++; - } - } - - if(z) { - for (k = 0; k < he_n; k++) { - ss = o->y_pos_strand?uref->ug->u.a[o->y_id].len - he_a[k].cov - 1:he_a[k].cov; - if(ss >= z->s && ss < z->e) break; - } - if(k < he_n) m++; - } - return m; -} - -int64_t get_het_occ(haplotype_evdience *he_a, int64_t he_n, int64_t c_k, int64_t ylen, utg_ct_t *p, int64_t rev) -{ - int64_t k, occ = 0, ss; - if(!rev) { - for (k = c_k; k >= 0; k--) { - if(he_a[k].cov >= p->s && he_a[k].cov < p->e) { - occ++; - } else { - break; - } - } - - for (k = c_k+1; k < he_n; k++) { - if(he_a[k].cov >= p->s && he_a[k].cov < p->e) { - occ++; - } else { - break; - } - } - } else { - for (k = c_k; k >= 0; k--) { - ss = ylen - he_a[k].cov - 1; - if(ss >= p->s && ss < p->e) { - occ++; - } else { - break; - } - } - - for (k = c_k+1; k < he_n; k++) { - ss = ylen - he_a[k].cov - 1; - if(ss >= p->s && ss < p->e) { - occ++; - } else { - break; - } - } - } - - assert(occ); - return occ; -} - - -int64_t rescue_contain_ul_chains(const ul_idx_t *uref, overlap_region* o, haplotype_evdience *he_a, int64_t he_n, utg_ct_t *ct_a, int64_t ct_n, -kv_ul_ov_t *chains, double diff_ec_ul, int64_t winLen, int64_t rescue_trans, void *km) -{ - int64_t i, k, ss, ff, t0 = 0; - uint64_t ys, ye; - utg_ct_t *p = NULL; - // if(o->x_id == 0) { - // fprintf(stderr, "\no->y_id->%u\n", o->y_id); - // for (i = 0; i < ct_n; i++) { - // p = &(ct_a[i]); - // fprintf(stderr, "***rid->%u, rev->%u, s->%u, e->%u\n", p->x>>1, p->x&1, p->s, p->e); - // } - // } - - if(o->y_pos_strand == 0){ - ys = o->y_pos_s; ye = o->y_pos_e + 1; - for (i = k = 0; i < ct_n; i++) { - p = &(ct_a[i]); - if(p->e <= ys) continue; - if(p->s >= ye) break; - ff = 1; - if(he_a && he_n > 0) { - for (; k < he_n; k++) { - if(he_a[k].cov >= p->s && he_a[k].cov < p->e) { - ff = 0; - break; - } - if(he_a[k].cov >= p->e) break; - } - } - // if(ff == debug_utg_ct_t(uref, o, p, he_a, he_n)) fprintf(stderr, "ERROR\n"); - if(ff) { - ///push ovlp - t0 += gen_contain_chain(uref, p, o, chains, diff_ec_ul, winLen, km); - } else if(rescue_trans) { - if(gen_contain_chain(uref, p, o, chains, diff_ec_ul, winLen, km)){ - t0++; chains->a[chains->n-1].el = 0; - chains->a[chains->n-1].sec = get_het_occ(he_a, he_n, k, uref->ug->u.a[o->y_id].len, p, o->y_pos_strand); - } - } - // if(!ff) t0++; - } - - } else { - ys = uref->ug->u.a[o->y_id].len - (o->y_pos_e+1); - ye = uref->ug->u.a[o->y_id].len - o->y_pos_s; - for (i = 0, k = he_n - 1; i < ct_n; i++) { - p = &(ct_a[i]); - if(p->e <= ys) continue; - if(p->s >= ye) break; - ff = 1; - if(he_a && he_n > 0) { - for (; k >= 0; k--) { - ss = uref->ug->u.a[o->y_id].len - he_a[k].cov - 1; - if(ss >= p->s && ss < p->e) { - ff = 0; - break; - } - if(ss >= p->e) break; - } - } - // if(ff == debug_utg_ct_t(uref, o, p, he_a, he_n)) fprintf(stderr, "ERROR\n"); - if(ff) { - ///push ovlp - t0 += gen_contain_chain(uref, p, o, chains, diff_ec_ul, winLen, km); - } else if(rescue_trans) { - if(gen_contain_chain(uref, p, o, chains, diff_ec_ul, winLen, km)){ - t0++; chains->a[chains->n-1].el = 0; - chains->a[chains->n-1].sec = get_het_occ(he_a, he_n, k, uref->ug->u.a[o->y_id].len, p, o->y_pos_strand); - } - } - // if(!ff) t0++; - } - } - // if(debug_utg_ct_t(uref, o, ct_a, ct_n, he_a, he_n)!=t0) fprintf(stderr, "ERROR\n"); - // fprintf(stderr, "***[M::%s] o->y_id:%u, chains->n:%u\n", __func__, o->y_id, (uint32_t)chains->n); - return t0; -} - - -int64_t rescue_trans_ul_chains(const ul_idx_t *uref, overlap_region* o, haplotype_evdience *he_a, int64_t he_n, ma_utg_t *u, -kv_ul_ov_t *chains, double diff_ec_ul, int64_t winLen, int64_t rescue_trans, uint64_t *cis_occ, void *km) -{ - uint64_t ys, ye, i, l; - int64_t k, ff, ss, t0 = 0; - utg_ct_t p; - if(cis_occ) (*cis_occ) = 0; - - if(o->y_pos_strand == 0) { - ys = o->y_pos_s; ye = o->y_pos_e + 1; - for (i = k = l = 0; i < u->n; i++) { - p.x = u->a[i]>>32; p.s = l; p.e = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); - l += (uint32_t)u->a[i]; - if(p.e <= ys) continue; - if(p.s >= ye) break; - ff = 1; - if(he_a && he_n) { - for (; k < he_n; k++) { - if(he_a[k].cov >= p.s && he_a[k].cov < p.e) { - ff = 0; - break; - } - if(he_a[k].cov >= p.e) break; - } - } - // if(ff == debug_utg_ct_t(uref, o, 0, 0, 0, &p, he_a, he_n)) fprintf(stderr, "ERROR\n"); - if(ff) { - ///push ovlp - t0 += gen_contain_chain(uref, &p, o, chains, diff_ec_ul, winLen, km); - } else if(rescue_trans) { - if(gen_contain_chain(uref, &p, o, chains, diff_ec_ul, winLen, km)){ - t0++; chains->a[chains->n-1].el = 0; if(cis_occ) (*cis_occ)++; - chains->a[chains->n-1].sec = get_het_occ(he_a, he_n, k, uref->ug->u.a[o->y_id].len, &p, o->y_pos_strand); - } - } - // if(!ff) t0++; - } - } else { - ys = uref->ug->u.a[o->y_id].len - (o->y_pos_e+1); - ye = uref->ug->u.a[o->y_id].len - o->y_pos_s; - for (i = l = 0, k = he_n - 1; i < u->n; i++) { - p.x = u->a[i]>>32; p.s = l; p.e = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); - l += (uint32_t)u->a[i]; - if(p.e <= ys) continue; - if(p.s >= ye) break; - ff = 1; - if(he_a && he_n) { - for (; k >= 0; k--) { - ss = uref->ug->u.a[o->y_id].len - he_a[k].cov - 1; - if(ss >= p.s && ss < p.e) { - ff = 0; - break; - } - if(ss >= p.e) break; - } - } - // if(ff == debug_utg_ct_t(uref, o, 0, 0, 0, &p, he_a, he_n)) fprintf(stderr, "ERROR\n"); - if(ff) { - ///push ovlp - t0 += gen_contain_chain(uref, &p, o, chains, diff_ec_ul, winLen, km); - } else if(rescue_trans) { - if(gen_contain_chain(uref, &p, o, chains, diff_ec_ul, winLen, km)){ - t0++; chains->a[chains->n-1].el = 0; if(cis_occ) (*cis_occ)++; - chains->a[chains->n-1].sec = get_het_occ(he_a, he_n, k, uref->ug->u.a[o->y_id].len, &p, o->y_pos_strand); - } - } - // if(!ff) t0++; - } - } - // if(debug_utg_ct_t(uref, o, NULL, 0, u, he_a, he_n)!=t0) fprintf(stderr, "ERROR\n"); - // fprintf(stderr, "t0->%ld\n", t0); - return t0; -} - -int64_t dedup_sort_ul_ov_t(ul_ov_t *a, int64_t a_n) -{ - int64_t k, l, z, r, i, qo, to; float rr = 0.9; - for (k = 1, l = i = 0; k <= a_n; k++) { - if(k == a_n || a[k].tn != a[l].tn) {///remove the duplicated contained alignments - for (z = l; z < k; z++) { - for (r = i-1; r >= 0 && a[r].tn == a[z].tn; r--){ - /** - if(a[z].qn == a[r].qn && a[z].qs == a[r].qs && a[z].qe == a[r].qe && - a[z].tn == a[r].tn && a[z].ts == a[r].ts && a[z].te == a[r].te && - a[z].sec == a[r].sec && a[z].el == a[r].el && a[z].rev == a[r].rev) { - break; - } - **/ - if(a[z].qn == a[r].qn && a[z].tn == a[r].tn && a[z].rev == a[r].rev) { - qo = ((MIN(a[z].qe, a[r].qe) > MAX(a[z].qs, a[r].qs))? - MIN(a[z].qe, a[r].qe) - MAX(a[z].qs, a[r].qs):0); - to = ((MIN(a[z].te, a[r].te) > MAX(a[z].ts, a[r].ts))? - MIN(a[z].te, a[r].te) - MAX(a[z].ts, a[r].ts):0); - if(qo >= ((a[r].qe - a[r].qs)*rr) && qo >= ((a[z].qe - a[z].qs)*rr) && - to >= ((a[r].te - a[r].ts)*rr) && to >= ((a[z].te - a[z].ts)*rr)) { - break; - } - } - } - if(r >= 0 && a[r].tn == a[z].tn) { - if(a[z].el) a[r].el = 1; - continue; - } - a[i++] = a[z]; - } - l = k; - } - } - return i; -} - - -uint32_t check_contain_pair(const ug_opt_t *uopt, uint32_t x, uint32_t y, uint32_t check_el) -{ - ma_hit_t_alloc* src = uopt->sources; - int64_t min_ovlp = uopt->min_ovlp; - int64_t max_hang = uopt->max_hang; - uint64_t z, qn, tn; int32_t r = 1; asg_arc_t e; - for (z = 0; z < src[x].length; z++) { - if(check_el && (!src[x].buffer[z].el)) continue; - qn = Get_qn(src[x].buffer[z]); tn = Get_tn(src[x].buffer[z]); - if(tn != y) continue; - r = ma_hit2arc(&(src[x].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); - if(r == MA_HT_QCONT || r == MA_HT_TCONT) break; - } - - if(z < src[x].length) return 1; - return 0; -} - -void debug_contain_ovlps(ul_ov_t *a, uint64_t a_n, const ug_opt_t *uopt) -{ - uint64_t k, i, f; ul_ov_t *z = NULL, *w = NULL; - for (k = 0; k < a_n; k++) { - z = &(a[k]); - if(!(z->tn&((uint32_t)(0x80000000)))) continue; - for (i = 0, f = z->qn; i < a_n; i++) { - w = &(a[i]); - if(i == k) continue; - if(w->tn&((uint32_t)(0x80000000))) continue; - if(z->qs >= w->qs && z->qe <= w->qe && check_contain_pair(uopt, (z->tn<<1)>>1, w->tn, 1)) { - f = (uint32_t)-1; - break; - } - } - if(z->qn != f) fprintf(stderr, "ERROR\n"); - } -} - -ma_hit_t* query_ovlp_src(const ug_opt_t *uopt, uint32_t v, uint32_t w, int64_t o, double diff_ec_ul, uint32_t *ol) -{ - ma_hit_t_alloc* src = uopt->sources; - int64_t min_ovlp = uopt->min_ovlp; - int64_t max_hang = uopt->max_hang, d, l, max_l; - uint64_t z, qn, tn, x = v>>1; int32_t r = 1; asg_arc_t e; - l = (o>=0?o:-o); //l *= diff_ec_ul; - if(l <= 0) return NULL; - for (z = 0; z < src[x].length; z++) { - qn = Get_qn(src[x].buffer[z]); tn = Get_tn(src[x].buffer[z]); - if(tn != (w>>1)) continue; - r = ma_hit2arc(&(src[x].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); - if(r < 0) continue; - if((e.ul>>32) != v || e.v != w) continue; - // if(v == 56 && w == 25) fprintf(stderr, "+xxxx, o:%ld, e.ol:%u\n", o, e.ol); - // if(v == 25 && w == 56) fprintf(stderr, "-xxxx, o:%ld, e.ol:%u\n", o, e.ol); - d = (o>=e.ol?o-e.ol:e.ol-o); - max_l = MAX(l, e.ol); - if(d <= (max_l*diff_ec_ul)) { - if(ol) (*ol) = e.ol; - return &(src[x].buffer[z]); - } - } - return NULL; -} - -void debug_infer_read_ovlp(const ug_opt_t *uopt, double diff_ec_ul, ul_ov_t *li, ul_ov_t *lj, ma_utg_t *u, -uint32_t i_idx, uint32_t j_idx, All_reads *ridx, ma_ug_t *ug) -{ - uint32_t li_v, lj_v; ma_hit_t *t = NULL; - li_v = (((uint32_t)(li->tn))<<1)|((uint32_t)(li->rev)); - lj_v = (((uint32_t)(lj->tn))<<1)|((uint32_t)(lj->rev)); - if(lj->qe <= li->qs || li_v == lj_v) fprintf(stderr, "ERROR-1\n"); - t = query_ovlp_src(uopt, li_v^1, lj_v^1, infer_rovlp(li, lj, NULL, NULL, ridx, ug), diff_ec_ul, NULL); - // ((int64_t)(lj->qe))-((int64_t)(li->qs)) - if(!t /**&& (li_v^1) == 648 && (lj_v^1) == 638 && li->qs == 63841**/) { - fprintf(stderr, "ERROR-2, li_v^1->%u, li->qs->%u, li->qe->%u, lj_v^1->%u, lj->qs->%u, lj->qe->%u, infer_rovlp->%ld\n", - li_v^1, li->qs, li->qe, lj_v^1, lj->qs, lj->qe, infer_rovlp(li, lj, NULL, NULL, ridx, ug)); - } -} - -uint64_t infer_read_ovlp(const ul_idx_t *uref, overlap_region_alloc* olist, kv_ul_ov_t *in, kv_ul_ov_t *res, double diff_ec_ul, int64_t winLen, const ug_opt_t *uopt, ul_contain *ct, void *km) -{ - uint64_t t, k, l, t_0, pb, cut = res->n, c_occ = 0;; - ma_ug_t *ug = uref->ug; - ma_utg_t *u = NULL; - overlap_region* o = NULL; - ul_ov_t *z = NULL; - utg_ct_t p; - // res->n = 0; - for (t = 0; t < in->n; t++) { - if(!(in->a[t].tn&(uint32_t)(0x80000000))) {///uid - u = &(ug->u.a[in->a[t].tn]); o = &(olist->list[in->a[t].qn]); - assert(o->y_id == in->a[t].tn); - for (k = l = 0, pb = res->n+2; k < u->n; k++) { - p.x = u->a[k]>>32; - p.s = l; p.e = l + Get_READ_LENGTH(R_INF, (u->a[k]>>33)); - l += (uint32_t)u->a[k]; - if(p.e <= in->a[t].ts) continue; - if(p.s >= in->a[t].te) break; - t_0 = gen_contain_chain(uref, &p, o, res, -1, -1, km); - assert(t_0 > 0); - // if(t_0 == 0) { - // fprintf(stderr, "ERROR-2, o->x_id:%u, o->y_id:%u, k:%lu, u->n:%lu, p.s:%u, p.e:%u, ts:%u, te:%u, rev:%u\n", - // o->x_id, o->y_id, k, (uint64_t)u->n, p.s, p.e, in->a[t].ts, in->a[t].te, in->a[t].rev); - // } - res->a[res->n-1].el = in->a[t].el; - res->a[res->n-1].sec = in->a[t].sec; - res->a[res->n-1].tn <<= 1; - res->a[res->n-1].tn >>= 1; - res->a[res->n-1].qn = o->x_id; - if(res->n >= pb) { - if(in->a[t].rev == 0) { - // if(res->a[res->n-1].qs > res->a[res->n-2].qe) fprintf(stderr, "ERROR-3\n"); - if(!(res->a[res->n-2].qs<=res->a[res->n-1].qs && res->a[res->n-1].qs <= res->a[res->n-2].qe - && res->a[res->n-2].qe <= res->a[res->n-1].qe)) { - fprintf(stderr, "ERROR-3\n"); - } - // if(res->a[res->n-1].qs == res->a[res->n-2].qe) { - // if(res->a[res->n-2].qe < in->a[t].qe) res->a[res->n-2].qe++; - // else if(res->a[res->n-1].qs > 0) res->a[res->n-1].qs--; - // } - } else { - if(!(res->a[res->n-1].qs<=res->a[res->n-2].qs && res->a[res->n-2].qs <= res->a[res->n-1].qe - && res->a[res->n-1].qe <= res->a[res->n-2].qe)) { - fprintf(stderr, "ERROR-4\n"); - } - } - - // debug_infer_read_ovlp(uopt, diff_ec_ul, - // in->a[t].rev?&(res->a[res->n-2]):&(res->a[res->n-1]), - // in->a[t].rev?&(res->a[res->n-1]):&(res->a[res->n-2]), u, k, k-1); - } - } - } else {///rid - kv_push(ul_ov_t, *res, in->a[t]); - // res->a[res->n-1].tn <<= 1; - // res->a[res->n-1].tn >>= 1; - res->a[res->n-1].qn = o->x_id; - c_occ++; - } - } - if(res->n != cut) { - radix_sort_ul_ov_srt_qe(res->a + cut, res->a + res->n); - if(c_occ) { - int64_t ci, cn = cut; - for (k = cut; k < res->n; k++) { - z = &(res->a[k]); - if(z->tn&((uint32_t)(0x80000000))) continue; - if(ct->is_c.a[z->tn] == 0) continue; - - for (ci = k+1; ci < (int64_t)(res->n); ci++) { - if(res->a[ci].qe > z->qe) break; - if(res->a[ci].qn == (uint32_t)-1) continue; - if(!(res->a[ci].tn&((uint32_t)(0x80000000)))) continue; - if(z->qs <= res->a[ci].qs && z->qe >= res->a[ci].qe) { - if(check_contain_pair(uopt, (res->a[ci].tn<<1)>>1, z->tn, 1)) { - res->a[ci].qn = (uint32_t)-1; - } - } - } - - for (ci = k-1; ci >= cn; ci--) { - if(res->a[ci].qe <= z->qs) break; - if(res->a[ci].qn == (uint32_t)-1) continue; - if(!(res->a[ci].tn&((uint32_t)(0x80000000)))) continue; - if(z->qs <= res->a[ci].qs && z->qe >= res->a[ci].qe) { - if(check_contain_pair(uopt, (res->a[ci].tn<<1)>>1, z->tn, 1)) { - res->a[ci].qn = (uint32_t)-1; - } - } - } - } - - // debug_contain_ovlps(res->a+cut, res->n-cut, uopt); - - for (k = l = cut; k < res->n; k++) { - if(res->a[k].qn == (uint32_t)-1) continue; - if(k != l) { - res->a[l] = res->a[k]; - } - res->a[l].tn <<= 1; res->a[l].tn >>= 1; - ++l; - } - res->n = l; - } - } - - return res->n - cut; -} - - -int64_t gl_chain_refine(overlap_region_alloc* olist, Correct_dumy* dumy, haplotype_evdience_alloc *hap, glchain_t *ll, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, int64_t qlen, const ug_opt_t *uopt, void *km) -{ - ll->tk.n = ll->lo.n = 0; - kv_ul_ov_t *idx = &(ll->lo); - ul_contain *ct = uref->ct; - gl_chain_gen(olist, uref, idx, 0, hap, km); - if(idx->n == 0) return 0; - kv_resize_km(km, ul_ov_t, ll->tk, idx->n); - kv_resize_km(km, uint64_t, ll->srt.a, idx->n); - kv_resize_km(km, uint64_t, hap->snp_srt, idx->n); - if(gl_exact_chain(idx, &(ll->tk), uref, G_CHAIN_BW, diff_ec_ul, qlen, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, km)) { - kv_ul_ov_t *chains = &(ll->tk); ul_ov_t *p = NULL; - uint64_t k, z, ff, s, e, an, cn, sft = 50, si = 0, ei = 0, resc = 0, chains_pl = chains->n; - radix_sort_ul_ov_srt_qs(idx->a, idx->a + idx->n); - for (k = 0; k < olist->length; k++) { - if(olist->list[k].is_match!=2) continue; - - s = olist->list[k].x_pos_s; e = olist->list[k].x_pos_e+1; - for (z = ff = 0; z < idx->n; z++) { - if((s+sft) >= idx->a[z].qs && e <= (idx->a[z].qe+sft)) { - ff = 1; - break; - } - if(idx->a[z].qs >= (e+sft)) break; - } - cn = ((uint32_t)(ct->idx.a[olist->list[k].y_id])); - if(ff && cn==0) continue; - an = update_ava_het_site(hap, k, &si, &ei, cn); - // if(an != get_het_site(hap, k)) fprintf(stderr, "an->%lu, get_het_site->%lu\n", an, get_het_site(hap, k)); - - if(cn > 0 && an > 0) { - resc += rescue_contain_ul_chains(uref, &(olist->list[k]), hap->list+si, an, - ct->rids.a + ((ct->idx.a[olist->list[k].y_id])>>32), cn, chains, diff_ec_ul, winLen, 0, km); - } - - if(ff == 0) { - kv_pushp_km(km, ul_ov_t, *chains, &p); - p->qn = k/**olist->list[k].x_id**/; p->qs = olist->list[k].x_pos_s; p->qe = olist->list[k].x_pos_e+1; - p->tn = olist->list[k].y_id; p->el = 0; p->sec = (an&((uint64_t)0x3FFFFFFF))/**get_het_site(hap, k)**/; - p->rev = olist->list[k].y_pos_strand; - if(p->rev) { - p->ts = uref->ug->u.a[p->tn].len - (olist->list[k].y_pos_e+1); - p->te = uref->ug->u.a[p->tn].len - olist->list[k].y_pos_s; - } else { - p->ts = olist->list[k].y_pos_s; - p->te = olist->list[k].y_pos_e+1; - } - - } - si = ei; - } - - if(resc > 0) { - radix_sort_ul_ov_srt_tn(chains->a + chains_pl, chains->a + chains->n); - ff = dedup_sort_ul_ov_t(chains->a + chains->n - resc, resc); - chains->n = chains->n - resc + ff; - } - } - - if(ll->tk.n > 0) infer_read_ovlp(uref, olist, &(ll->tk), &(ll->lo), diff_ec_ul, winLen, uopt, ct, km); - else ll->lo.n = 0; - return 1; -} - - -/** -void fill_edge_weight(ul_ov_t *a, int64_t a_n, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, int64_t qlen) -{ - uint32_t li_v, lj_v; - ul_ov_t *li = NULL, *lj = NULL; - int64_t mm_ovlp, x, i, j, o; - ma_hit_t *t = NULL; - for (i = 0; i < a_n; i++) { - li = &(a[i]); li_v = (li->tn<<1)|li->rev; - mm_ovlp = max_ovlp_src(uopt, li_v^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(i, a, x); - for (j = x; j >= 0; --j) { // collect potential destination vertices - lj = &(a[j]); lj_v = (lj->tn<<1)|lj->rev; - if(lj->qe <= li->qs) break; - if(li_v == lj_v) continue; - t = query_ovlp_src(uopt, li_v, lj_v, ((int64_t)(lj->qe))-((int64_t)(li->qs)), diff_ec_ul); - if(t) { - t->bl; - } - } - } - - -} -**/ - -int64_t get_ecov_adv_back(const ul_idx_t *uref, const ug_opt_t *uopt, uint32_t v, uint32_t w, int64_t bw, double diff_ec_ul, int64_t dq, uint32_t *is_contain) -{ - int64_t dt = -1, dif, mm; if(is_contain) (*is_contain) = 0; - const asg_t *g = uref?uref->ug->g:NULL; - uint32_t nv, i; asg_arc_t *av = NULL; - if(g) { - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (i = 0; i < nv; i++) { - if(av[i].del || av[i].v != w) continue; - dt = av[i].ol; - break; - } - } - - if(dt < 0 && uopt) { - ma_hit_t_alloc* src = uopt->sources; - int64_t min_ovlp = uopt->min_ovlp; - int64_t max_hang = uopt->max_hang; - uint64_t z, qn, tn, x = v>>1; int32_t r = 1; asg_arc_t e; - for (z = 0; z < src[x].length; z++) { - qn = Get_qn(src[x].buffer[z]); tn = Get_tn(src[x].buffer[z]); - if(tn != (w>>1)) continue; - r = ma_hit2arc(&(src[x].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); - if(r < 0) { - if(r == MA_HT_QCONT || r == MA_HT_TCONT) { - if(src[x].buffer[z].rev == ((uint32_t)(v^w))) { - dt = Get_qe(src[x].buffer[z]) - Get_qs(src[x].buffer[z]); - if(dt < Get_te(src[x].buffer[z]) - Get_ts(src[x].buffer[z])) { - dt = Get_te(src[x].buffer[z]) - Get_ts(src[x].buffer[z]); - } - if(is_contain) (*is_contain) = 1; - break; - } - } - continue; - } - if((e.ul>>32) != v || e.v != w) continue; - dt = e.ol; - break; - } - } - if(dt < 0) return 0; - dif = (dq>dt? dq-dt:dt-dq); - mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; - // if((v>>1) == 1163 && (w>>1) == 1168) fprintf(stderr, ">>>>>>dis_q:%ld, dis_t:%ld, dif:%ld, mm:%ld\n", dis_q, dis_t, dif, mm); - if(dif <= mm) return 1; - return 0; -} - -ma_hit_t *get_ug_edge_src(ma_ug_t *ug, ma_hit_t_alloc *src, int64_t max_hang, int64_t min_ovlp, uint32_t uv, uint32_t uw) -{ - if(ug->u.a[uv>>1].circ || ug->u.a[uw>>1].circ) return NULL; - uint32_t v, w, k, qn, tn; int32_t r; asg_arc_t t; - v = ((uv&1)?(ug->u.a[uv>>1].start^1):(ug->u.a[uv>>1].end^1)); - w = ((uw&1)?(ug->u.a[uw>>1].end):(ug->u.a[uw>>1].start)); - ma_hit_t_alloc *x = &(src[v>>1]); - - for (k = 0; k < x->length; k++) { - qn = Get_qn(x->buffer[k]); - tn = Get_tn(x->buffer[k]); - if(qn == (v>>1) && tn == (w>>1)) { - r = ma_hit2arc(&(x->buffer[k]), Get_READ_LENGTH(R_INF, v>>1), Get_READ_LENGTH(R_INF, w>>1), - max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - if(r < 0) continue; - if((t.ul>>32)!=v || t.v!=w) continue; - return &(x->buffer[k]); - } - } - - return NULL; -} - -///mode: 0->ug; 1->read -int64_t get_ecov_adv(const ul_idx_t *uref, const ug_opt_t *uopt, uint32_t v, uint32_t w, int64_t bw, double diff_ec_ul, int64_t dq, uint64_t mode, int64_t *contain_off) -{ - int64_t dt = -1, dif, mm; if(contain_off) (*contain_off) = 0; - uint32_t nv, i; asg_arc_t *av = NULL; ma_hit_t *x = NULL; - if(!mode) { - const asg_t *g = uref?uref->ug->g:NULL; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (i = 0; i < nv; i++) { - if(av[i].del || av[i].v != w) continue; - dt = av[i].ol; - // if((v>>1)==25288) fprintf(stderr, "+++v:%u, w:%u, ou:%ld\n", v, w, dt); - // if((v>>1) == 3012 && (w>>1) == 3011) fprintf(stderr, "******************\n"); - if(contain_off) { - (*contain_off) = av[i].ou; - if(av[i].ou >= OU_MASK) { - x = get_ug_edge_src(uref->ug, uopt->sources, uopt->max_hang, uopt->min_ovlp, - av[i].ul>>32, av[i].v); - (*contain_off) = x->cc; - // if(v==1772 && w==1769) fprintf(stderr, "---v:%u, w:%u, cc:%u\n", v, w, x->cc); - } - } - break; - } - }else { - ma_hit_t_alloc* src = uopt->sources; - int64_t min_ovlp = uopt->min_ovlp; - int64_t max_hang = uopt->max_hang; - uint64_t z, qn, tn, x = v>>1; int32_t r = 1; asg_arc_t e; - for (z = 0; z < src[x].length; z++) { - qn = Get_qn(src[x].buffer[z]); tn = Get_tn(src[x].buffer[z]); - if(tn != (w>>1)) continue; - r = ma_hit2arc(&(src[x].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); - if(r < 0) continue; - if((e.ul>>32) != v || e.v != w) continue; - dt = e.ol; if(contain_off) (*contain_off) = src[x].buffer[z].cc; - break; - } - } - if(dt < 0) return 0; - dif = (dq>dt? dq-dt:dt-dq); - mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; - // if((v>>1) == 1163 && (w>>1) == 1168) fprintf(stderr, ">>>>>>dis_q:%ld, dis_t:%ld, dif:%ld, mm:%ld\n", dis_q, dis_t, dif, mm); - if(dif <= mm) return 1; - return 0; -} - -void get_rr_tse(const ul_idx_t *uref, ul_ov_t *li, uint32_t *ts, uint32_t *te, uint32_t *tl) -{ - (*tl) = uref?uref->ug->g->seq[li->tn].len:Get_READ_LENGTH(R_INF, li->tn); - if(!(li->rev)) { - (*ts) = li->ts; (*te) = li->te; - } else { - (*ts) = (*tl) - li->te; (*te) = (*tl) - li->ts; - } -} -/** -uint32_t checkM(uint32_t v, uint32_t l, const ul_idx_t *uref, const asg_t *g, uint32_t in, uint32_t its, -uint32_t iqs, uint32_t iqe, int64_t bw, double diff_ec_ul, int64_t qlen, ul_ov_t *a, uint32_t a_n) -{ - int64_t vl = uref?uref->ug->g->seq[v>>1].len:Get_READ_LENGTH(R_INF, (v>>1)), t_dis, q_dis, kcs, mm_ovlp, x, k; - t_dis = ((int64_t)(l + vl)) - ((int64_t)(in - its)); - kcs = iqs; kcs -= t_dis; if(kcs < 0) kcs = 0; - uint32_t nv = asg_arc_n(g, v), i, lk_v, kts, kte, kn; - asg_arc_t *av = asg_arc_a(g, v), *p = NULL; mm_ovlp = -1; ul_ov_t *lk; - for (i = 0, p = NULL; i < nv; i++) { - if(av[i].del) continue; - if((int32_t)(av[i].ol) > mm_ovlp) { - p = &(av[i]); mm_ovlp = av[i].ol; - } - } - if(!p) return 0; - - x = (kcs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += kcs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(a_n, a, x); - for (k = x; k >= 0; --k) { - lk = &(a[k]); lk_v = ((lk->tn<<1)|lk->rev)^1; - if(lk->qe <= kcs) break;//evan this pair has a overlap, its length will be very small; just ignore - if(lk->qs >= kcs) continue; // lk is contained in li on the query coordinate - - get_rr_tse(uref, lk, &kts, &kte, &kn); - ///t_dis and q_dis might be < 0 - t_dis = ((int64_t)(l + kn - kte)) - ((int64_t)(in - its)); - q_dis = ((int64_t)(iqs)) - ((int64_t)(lk->qe)); - } - -} - -void best_path_ext(const ul_idx_t *uref, const ug_opt_t *uopt, int64_t g_gap, ul_ov_t *a, uint32_t a_n, -int64_t bw, double diff_ec_ul, uint64_t *track, ul_ov_t *li) -{ - if(a_n <= 0) return; - const asg_t *g = uref?uref->ug->g:NULL; asg_arc_t *av = NULL, *p = NULL; ul_ov_t *lk; - uint32_t nv, i, v, io, in, its, ite, kn, kts, kte; int64_t mm, l, max_dist, k, t_dis, q_dis; - - get_rr_tse(uref, li, &its, &ite, &in); - io = in - ite; max_dist = g_gap + in - its; - - if(g) { - v = (((li->tn<<1)|li->rev)^1); mm = 1; l = 0; - while (mm >= 0) { - - - - - - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); mm = -1; - for (i = 0, p = NULL; i < nv; i++) { - if(av[i].del) continue; - if((int32_t)(av[i].ol) > mm) { - p = &(av[i]); mm = av[i].ol; - } - } - if(p) { - l += (uint32_t)(p->ul); - if(l > max_dist) break; - for (k = a_n-1; k >= 0; k--) { - lk = &(a[k]); - if((lk->qe+g_gap) <= li->qs) break; - if(p->v == (((lk->tn<<1)|lk->rev)^1)) { - ///check if lk can be directly reachedc from li - if(lk->qe > li->qs && (track[k]&((uint64_t)0x80000000))) { - ; - } - get_rr_tse(uref, lk, &kts, &kte, &kn); - ///t_dis and q_dis might be < 0 - t_dis = ((int64_t)(l + kn - kte)) - ((int64_t)(in - its)); - q_dis = ((int64_t)(li->qs)) - ((int64_t)(lk->qe)); - } - } - v = p->v; - } - } - } -} - - -int64_t gl_chain_advance(kv_ul_ov_t *res, ul_ov_t *ex, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, int64_t max_skip, uint64_t *srt, uint64_t *idx, uint64_t *track, float trav_rate, void *km) -{ - uint32_t li_v, lj_v, rev_n, gapLen = (trav_rate>0?trav_rate*qlen:0); - int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, qo, n_skip, n_all; - ul_ov_t *li = NULL, *lj = NULL, rev_t; - radix_sort_ul_ov_srt_qe(res->a, res->a + res->n); - for (i = 0; i < (int64_t)res->n; ++i) { - li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; - // if(!(li->el)) continue; - mm_ovlp = uref?max_ovlp(uref->ug->g, li_v^1):max_ovlp_src(uopt, li_v^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(i, res->a, x); - if(li->el) { - csc = uref?retrieve_u_cov_region(uref, li->tn, 0, li->ts, li->te, NULL):li->te-li->ts; - } else { - csc = -1;///for cis overlap, the csc should be >1000; so -1 for trans overlaps should be fine - } - mm_sc = csc; mm_idx = -1; n_skip = n_all = 0; - for (j = x; j >= 0; --j) { // collect potential destination vertices - lj = &(res->a[j]); lj_v = (lj->tn<<1)|lj->rev; - // if((lj->qe+gapLen) <= li->qs) break; - if(lj->qe <= li->qs) break;//evan this pair has a overlap, its length will be very small; just ignore - if(lj->qs >= li->qs) continue; // lj is contained in li on the query coordinate - qo = infer_rovlp(li, lj, NULL, NULL); ///overlap length in query (UL read) - if(li_v != lj_v && get_ecov_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo)) { - sc = csc + (track[j]>>32); - if(sc > mm_sc) mm_sc = sc, mm_idx = j; - if(res->a[j].sec == i && res->a[j].el) n_skip++; - if((track[j]&((uint64_t)0x7FFFFFFF)) != ((uint64_t)0x7FFFFFFF)) { - res->a[(track[j]&((uint64_t)0x7FFFFFFF))].sec = i; - } - track[j] |= ((uint64_t)0x80000000); - } else { - if(track[j]&((uint64_t)0x80000000)) track[j] -= ((uint64_t)0x80000000); - } - n_all++; - } - - if(n_all > max_skip) n_all = max_skip; - else n_all -= 2; //allow one mismatch; note here must be -2 - - if(li->el && (mm_idx<0 || n_skip0?trav_rate*qlen*li->el:0); - if(gapLen > 0) { - // if((lj->qe+gapLen) <= li->qs) break; - ///since graph traversal just has one path, so this step might be quite easy - - best_path_ext(uref, uopt, gapLen, res->a, x+1, bw, diff_ec_ul, li); - } - } - // 4294967295L - track[i] = mm_sc; track[i] <<= 32; - track[i] |= (mm_idx>=0?mm_idx:((uint64_t)0x7FFFFFFF)); - srt[i] = mm_sc; srt[i] <<= 32; srt[i] |= i; - // fprintf(stderr, "+++i:%ld, mm_idx:%ld, mm_sc:%ld\n", i, mm_idx, mm_sc); - // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n\n", li->tn+1, "lc"[uref->ug->u.a[li->tn].circ], li->qs, li->qe); - } - - for (i = 0; i < (int64_t)res->n; ++i) { - if(track[i]&((uint64_t)0x80000000)) track[i] -= ((uint64_t)0x80000000); - } - - int64_t n_v, n_u, n_v0; - radix_sort_gfa64(srt, srt+res->n); //ex->n = res->n; - for (k = (int64_t)res->n-1, n_v = n_u = 0; k >= 0; --k) { - // fprintf(stderr, "\nk:%ld\n", k); - n_v0 = n_v; - for (i = (uint32_t)srt[k]; i >= 0 && (track[i]&((uint64_t)0x80000000)) == 0;) { - ex[n_v++] = res->a[i]; track[i] |= ((uint64_t)0x80000000); - // fprintf(stderr, "+i:%ld, ", i); - // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n", res->a[i].tn+1, "lc"[uref->ug->u.a[res->a[i].tn].circ], res->a[i].qs, res->a[i].qe); - if((track[i]&((uint64_t)0x7FFFFFFF)) == ((uint64_t)0x7FFFFFFF)) i = -1; - else i = track[i]&((uint64_t)0x7FFFFFFF); - } - if(n_v0 == n_v) continue; - ///keep the whole score; do not cut score like minigraph - sc = (i<0?(srt[k]>>32):((srt[k]>>32)-(track[i]>>32))); - // sc = srt[k]>>32; - idx[n_u++] = ((uint64_t)sc<<32)|(n_v-n_v0); - } - - for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { - n_v0 = n_v; n_v += (uint32_t)idx[k]; - res->a[k].qn = idx[k]>>32; - res->a[k].ts = n_v0; res->a[k].te = n_v; - - rev_n = ((uint32_t)idx[k])>>1; - ///we need to consider contained reads; so determining qs is not such easy - res->a[k].qs = (uint32_t)-1; res->a[k].qe = ex[n_v0].qe; - for (i = 0; i < rev_n; i++) { - rev_t = ex[n_v0+i]; - ex[n_v0+i] = ex[n_v0+rev_n-i-1]; - ex[n_v0+rev_n-i-1] = rev_t; - if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; - if(res->a[k].qs > ex[n_v0+rev_n-i-1].qs) res->a[k].qs = ex[n_v0+rev_n-i-1].qs; - } - if(i < ((uint32_t)idx[k]) && res->a[k].qs < ex[n_v0+i].qs) { - res->a[k].qs = ex[n_v0+i].qs; - } - } - res->n = n_u; - return res->n; -} -**/ - -int64_t determine_containment_chain(const ug_opt_t *uopt, uint64_t *track, uint64_t *flag, kv_ul_ov_t *res, int32_t nc, int64_t *nsc, int64_t mm_idx, int64_t bw, double diff_ec_ul, uint32_t el, All_reads *ridx, ma_ug_t *ug) -{ - int64_t i, k, pk, ak, e, off = 128, qo, tt = 0, ii; ul_ov_t *li = NULL, *lk = NULL; - uint32_t li_v, lk_v, is_c; - if(nc<=0) return 0; - for (k = tt = ak = 0; k < nc; k++) { - if(!(flag[res->a[k].sec]&((uint64_t)0x80000000))) { - flag[res->a[k].sec] |= ((uint64_t)0x80000000); tt++; - } else { - res->a[ak++].sec = res->a[k].sec; - } - } - if(tt==nc) return nsc[0] - nsc[1]; - assert(ak>0); - e = res->a[res->a[ak-1].sec].qe;//e is the smallest qe - for (i = mm_idx, pk = 0; i >= 0;) {///i++, li->qe-- - li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; - if((track[i]&((uint64_t)0x7FFFFFFF)) == ((uint64_t)0x7FFFFFFF)) i = -1; - else i = track[i]&((uint64_t)0x7FFFFFFF); - if(li->qe + off < e || tt == nc) break;//128 is used to tolerate indels; - for (k = pk, ii = 0; k < ak; k++) {///k++, lk->qe-- - if(res->a[k].sec == ((uint32_t)0x3FFFFFFF)) continue; - lk = &(res->a[res->a[k].sec]); lk_v = (lk->tn<<1)|lk->rev; - if(li->qe + off >= lk->qe) { - if(ii == 0) pk = k; - if(li->qs <= lk->qs + off) { - qo = infer_rovlp(li, lk, NULL, NULL, ridx, ug); ///overlap length in query (UL read) - if(li_v != lk_v && get_ecov_adv_back(NULL, uopt, li_v^1, lk_v^1, bw, diff_ec_ul, qo, &is_c)) { - if(is_c) { - tt++; res->a[k].sec = ((uint32_t)0x3FFFFFFF); - if(el) nsc[0] -= ((int64_t)(lk->te-lk->ts)); - else nsc[!(lk->el)] -= ((int64_t)(lk->te-lk->ts)); - } - } - } - ii = 1; - } - } - } - - assert(nsc[0]>=0 && nsc[1]>=0); - return nsc[0] - nsc[1]; -} - -uint64_t push_sc_pre(int64_t mm_sc, int64_t mm_idx) -{ - uint32_t sc = (mm_sc>=0?(((uint32_t)(mm_sc))|((uint32_t)(0x80000000))):((uint32_t)(-mm_sc))); - uint64_t x = sc; x <<= 32; x |= (mm_idx>=0?mm_idx:((uint64_t)0x7FFFFFFF)); - return x; -} - -int64_t pop_sc(uint64_t x) -{ - int64_t sc; - x >>= 32; - if(x&((uint64_t)(0x80000000))) { - sc = x - ((uint64_t)(0x80000000)); - } else { - sc = x; sc *= -1; - } - return sc; -} - -int64_t pop_pre(uint64_t x) -{ - if((x&((uint64_t)0x7FFFFFFF)) == ((uint64_t)0x7FFFFFFF)) return -1; - else return (x&((uint64_t)0x7FFFFFFF)); -} - -///mode: 0->ug; 1->read -int64_t gl_chain_advance(kv_ul_ov_t *res, ul_ov_t *ex, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, int64_t max_skip, uint64_t *srt, uint64_t *idx, uint64_t *track, int64_t trans_sc, -uint64_t mode, All_reads *ridx, ma_ug_t *ug, int64_t debug_i, void *km) -{ - // fprintf(stderr, "\n+++[M::%s] res->n:%u\n", __func__, (uint32_t)res->n); - if(res->n == 0) return 0; - uint32_t li_v, lj_v, rev_n; - int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, qo, share, n_el = 0; - ul_ov_t *li = NULL, *lj = NULL, rev_t; - radix_sort_ul_ov_srt_qe(res->a, res->a + res->n); - for (i = 1, j = 0; i <= (int64_t)res->n; i++) { - if (i == (int64_t)res->n || res->a[i].qe != res->a[j].qe) { - if(i - j > 1) { - radix_sort_ul_ov_srt_qs(res->a+j, res->a+i); - } - j = i; - } - } - for (i = 0; i < (int64_t)res->n; ++i) { - li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; - mm_ovlp = mode?max_ovlp_src(uopt, li_v^1):max_ovlp(uref->ug->g, li_v^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(i, res->a, x+G_CHAIN_INDEL); - if(li->el) csc = mode?retrieve_r_cov_region(uref, li->tn, 0, li->ts, li->te, NULL):retrieve_u_cov_region(uref, li->tn, 0, li->ts, li->te, NULL); - else csc = (trans_sc*li->sec); //trans overlaps - mm_sc = csc; mm_idx = -1; - // if(i == 37 || i == 36 || i == 35 || i == 32) fprintf(stderr, "*i:%ld, x:%ld, mm_sc:%ld\n", i, x, mm_sc); - for (j = x; j >= 0; --j) { // collect potential destination vertices - lj = &(res->a[j]); lj_v = (lj->tn<<1)|lj->rev; - // if((lj->qe+gapLen) <= li->qs) break; - if(lj->qe+G_CHAIN_INDEL <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore - // if(lj->qs >= li->qs+G_CHAIN_INDEL) continue; // lj is contained in li on the query coordinate; 128 for indel offset - if(lj->qs >= li->qs) continue; - qo = infer_rovlp(li, lj, NULL, NULL, ridx, ug); ///overlap length in query (UL read) - // if(i == 37 || i == 36 || i == 35 || i == 32) fprintf(stderr, ">i:%ld, j:%ld, qo:%ld\n", i, j, qo); - if(li_v != lj_v && get_ecov_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, mode, &share)) { - // if(i == 37 || i == 36 || i == 35 || i == 32) fprintf(stderr, "#i:%ld, j:%ld, share:%ld\n", i, j, share); - sc = csc + pop_sc(track[j]); - // if((!mode)&&i==11&&j==10) { - // fprintf(stderr,"+share:%ld, i:%ld, j:%ld, li_v^1:%u, lj_v^1:%u\n", - // share, i, j, li_v^1, lj_v^1); - // } - // if((mode&&i==21&&j==20) || (mode&&i==22&&j==21) || (mode&&i==23&&j==22)) { - // fprintf(stderr,"-share:%ld, i:%ld, j:%ld, li_v^1:%u, lj_v^1:%u\n", - // share, i, j, li_v^1, lj_v^1); - // } - if(li->el && lj->el) sc -= (share>=csc?csc:share);///csc must be larger than 0 - // if((!li->el) && (!lj->el)) sc -= ((share>=o_csc?o_csc:share)*(-trans_scl)); - if(sc > mm_sc) mm_sc = sc, mm_idx = j; - } - } - - track[i] = push_sc_pre(mm_sc, mm_idx); - srt[i] = track[i]>>32; srt[i] <<= 32; srt[i] |= i; - n_el += li->el; - - // if(mode) { - // fprintf(stderr, "[M::%.*s] i:%ld, li->el:%u, li->score:%ld (raw_sc:%u), mm_idx:%ld, mm_sc:%ld, q[%u, %u), t[%u, %u), rev:%c\n", - // (int32_t)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), i, li->el, csc, li->te - li->ts, mm_idx, mm_sc, li->qs, li->qe, li->ts, li->te, "+-"[li->rev]); - // } else { - // fprintf(stderr, "[M::utg%.6u%c] i:%ld, li->el:%u, li->score:%ld (raw_sc:%u), mm_idx:%ld, mm_sc:%ld, q[%u, %u), t[%u, %u), rev:%c\n", - // li->tn+1, "lc"[uref->ug->u.a[li->tn].circ], i, li->el, csc, li->te - li->ts, mm_idx, mm_sc, li->qs, li->qe, li->ts, li->te, "+-"[li->rev]); - // } - // if(!mode) { - // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n", li->tn+1, "lc"[uref->ug->u.a[li->tn].circ], li->qs, li->qe); - // } - // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u; sc->%ld; pre->%ld; el->%u;\n", - // li->tn+1, "lc"[uref->ug->u.a[li->tn].circ], li->qs, li->qe, pop_sc(track[i]), pop_pre(track[i]), li->el); - } - - int64_t n_v, n_u, n_v0, le, lnv; - radix_sort_gfa64(srt, srt+res->n); - for (k = (int64_t)res->n-1, n_v = n_u = 0; k >= 0; --k) { - n_v0 = n_v; i = (uint32_t)srt[k]; - // fprintf(stderr, "+[M::utg%.6d%c] n_v0->%ld;\n", res->a[i].tn+1, "lc"[uref->ug->u.a[res->a[i].tn].circ], n_v0); - if(res->a[i].el) { ///chain must start from cis alignments - for (le = -1; i >= 0 && (track[i]&((uint64_t)0x80000000)) == 0;) { - if(res->a[i].el) { - le = -1; - }else if(n_v>n_v0 && ex[n_v-1].el) { - le = i; lnv = n_v;///cut the cis alignments in the end - } - ex[n_v++] = res->a[i]; track[i] |= ((uint64_t)0x80000000); - // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n", res->a[i].tn+1, "lc"[uref->ug->u.a[res->a[i].tn].circ], res->a[i].qs, res->a[i].qe); - i = pop_pre(track[i]); - } - } - // fprintf(stderr, "-[M::] n_v->%ld;\n", n_v); - if(n_v0 == n_v) continue; - if(le >= 0) { - i = le; n_v = lnv; - } - if(n_v0 == n_v) continue; - // fprintf(stderr, "[++chain::] beg_idx->%u, end_idx->%ld, le->%ld, chain_n->%ld\n", (uint32_t)srt[k], i, le, n_v - n_v0); - ///keep the whole score; do not cut score like minigraph - // sc = pop_sc(srt[k]); - sc = (i<0?(pop_sc(srt[k])):(pop_sc(srt[k])-pop_sc(track[i]))); - // fprintf(stderr, "++[M::%s] k:%ld, n_v0:%ld, n_v:%ld, le:%ld, sc:%ld, beg:%u, end:%ld, p_score:%ld, cut_score:%ld\n", - // __func__, k, n_v0, n_v, le, sc, (uint32_t)srt[k], i, pop_sc(srt[k]), i<0?0:pop_sc(track[i])); - if(sc /**<=**/< 0) {///sc might be 0, if the UL alignment cannot cover the whole overlap between two HiFi reads - n_v = n_v0; - continue; - } - // idx[n_u++] = push_sc_pre(sc, n_v-n_v0); - idx[n_u++] = ((uint64_t)sc<<32)|(n_v-n_v0); - } - // fprintf(stderr, "[M::%s] n_u:%ld, n_v:%ld\n", __func__, n_u, n_v); - for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { - n_v0 = n_v; n_v += (uint32_t)idx[k]; - // fprintf(stderr, "[M::%s] k:%ld, n_v0:%ld, n_v:%ld\n", __func__, k, n_v0, n_v); - res->a[k].qn = idx[k]>>32;//score - res->a[k].ts = n_v0; res->a[k].te = n_v;///idx - - rev_n = ((uint32_t)idx[k])>>1; - ///we need to consider contained reads; so determining qs is not such easy - res->a[k].qs = (uint32_t)-1; res->a[k].qe = ex[n_v0].qe; - for (i = 0; i < rev_n; i++) { - rev_t = ex[n_v0+i]; ex[n_v0+i] = ex[n_v-i-1]; ex[n_v-i-1] = rev_t; - - if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; - if(res->a[k].qs > ex[n_v-i-1].qs) res->a[k].qs = ex[n_v-i-1].qs; - n_el -= ex[n_v0+i].el; n_el -= ex[n_v-i-1].el; - ex[n_v0+i].sec = ex[n_v-i-1].sec = SEC_MODE; - } - if(((uint32_t)idx[k])&1) { - if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; - n_el -= ex[n_v0+i].el; ex[n_v0+i].sec = SEC_MODE; - } - assert(ex[n_v0].el && ex[n_v-1].el); - // fprintf(stderr, "[M::%s] k:%ld, qs:%u, qe:%u, chain_occ:%u, chain_score:%u\n", __func__, k, - // res->a[k].qs, res->a[k].qe, res->a[k].te - res->a[k].ts, res->a[k].qn); - } - // if(n_el) { - // fprintf(stderr, "[M::%s] debug_i->%ld, n_el->%ld, n_u->%ld, n_v->%ld\n", __func__, debug_i, n_el, n_u, n_v); - // } - assert(n_el == 0); - res->n = n_u; - radix_sort_ul_ov_srt_qn(res->a, res->a + res->n);//sort by score - // fprintf(stderr, "---[M::%s] n_u:%ld, n_v:%ld\n", __func__, n_u, n_v); - return n_v; -} - - -int64_t gl_chain_advance_back(kv_ul_ov_t *res, ul_ov_t *ex, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, int64_t max_skip, uint64_t *srt, uint64_t *idx, uint64_t *track, float trans_allow, -All_reads *ridx, ma_ug_t *ug, void *km) -{ - uint32_t li_v, lj_v, rev_n, is_c, nc, s_nc; - int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, qo, trans_scl = (int64_t)(((float)(1))/trans_allow), nsc[2]; - ul_ov_t *li = NULL, *lj = NULL, rev_t; - radix_sort_ul_ov_srt_qe(res->a, res->a + res->n); - for (i = s_nc = 0; i < (int64_t)res->n; ++i) { - li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; - mm_ovlp = uref?max_ovlp(uref->ug->g, li_v^1):max_ovlp_src(uopt, li_v^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(i, res->a, x); - csc = uref?retrieve_u_cov_region(uref, li->tn, 0, li->ts, li->te, NULL):li->te-li->ts; - if(!(li->el)) { - csc *= -trans_scl; //trans overlaps - if(csc >= 0) csc = -1; - } - mm_sc = csc; mm_idx = -1; nc = nsc[0] = nsc[1] = 0; - for (j = x; j >= 0; --j) { // collect potential destination vertices - lj = &(res->a[j]); lj_v = (lj->tn<<1)|lj->rev; - // if((lj->qe+gapLen) <= li->qs) break; - if(lj->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore - // if(lj->qs >= li->qs) continue; // lj is contained in li on the query coordinate - qo = infer_rovlp(li, lj, NULL, NULL, ridx, ug); ///overlap length in query (UL read) - if(li_v != lj_v && get_ecov_adv_back(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, &is_c)) { - if(!is_c) { - sc = csc + pop_sc(track[j]); - if(sc > mm_sc) mm_sc = sc, mm_idx = j; - } else if(!uref) {///with uref, retrieve_u_cov_region has already consider contained reads - res->a[nc++].sec = j; - if(li->el) nsc[0] += lj->te-lj->ts; - else nsc[!(lj->el)] += lj->te-lj->ts; - } - } - } - - if(nc && (!uref) && mm_idx>=0) {///deal with containments - mm_sc += determine_containment_chain(uopt, track, srt, res, nc, nsc, mm_idx, bw, diff_ec_ul, li->el, ridx, ug); - s_nc++; - } - - track[i] = push_sc_pre(mm_sc, mm_idx); - srt[i] = track[i]>>32; srt[i] <<= 32; srt[i] |= i; - // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n\n", li->tn+1, "lc"[uref->ug->u.a[li->tn].circ], li->qs, li->qe); - } - - if(s_nc) { - for (i = 0; i < (int64_t)res->n; ++i) { - if(srt[i]&((uint64_t)0x80000000)) srt[i]-=((uint64_t)0x80000000); - } - } - - int64_t n_v, n_u, n_v0, le, lnv; - radix_sort_gfa64(srt, srt+res->n); //ex->n = res->n; - for (k = (int64_t)res->n-1, n_v = n_u = 0; k >= 0; --k) { - n_v0 = n_v; i = (uint32_t)srt[k]; - if(i>=0 && (res->a[i].el)) { ///chain must start from cis alignments - for (le = -1; i >= 0 && (track[i]&((uint64_t)0x80000000)) == 0;) { - if(res->a[i].el) { - le = -1; - }else if(n_v>n_v0 && ex[n_v-1].el) { - le = i; lnv = n_v;///cut the cis alignments in the end - } - ex[n_v++] = res->a[i]; track[i] |= ((uint64_t)0x80000000); - // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n", res->a[i].tn+1, "lc"[uref->ug->u.a[res->a[i].tn].circ], res->a[i].qs, res->a[i].qe); - i = pop_pre(track[i]); - } - } - if(n_v0 == n_v) continue; - if(le >= 0) { - i = le; n_v = lnv; - } - if(n_v0 == n_v) continue; - ///keep the whole score; do not cut score like minigraph - // sc = pop_sc(srt[k]); - sc = (i<0?(pop_sc(srt[k])):(pop_sc(srt[k])-pop_sc(track[i]))); - if(sc < 0) { - n_v = n_v0; - continue; - } - // idx[n_u++] = push_sc_pre(sc, n_v-n_v0); - idx[n_u++] = ((uint64_t)sc<<32)|(n_v-n_v0); - } - - for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { - n_v0 = n_v; n_v += (uint32_t)idx[k]; - res->a[k].qn = idx[k]>>32; - res->a[k].ts = n_v0; res->a[k].te = n_v; - - rev_n = ((uint32_t)idx[k])>>1; - ///we need to consider contained reads; so determining qs is not such easy - res->a[k].qs = (uint32_t)-1; res->a[k].qe = ex[n_v0].qe; - for (i = 0; i < rev_n; i++) { - rev_t = ex[n_v0+i]; - ex[n_v0+i] = ex[n_v0+rev_n-i-1]; - ex[n_v0+rev_n-i-1] = rev_t; - if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; - if(res->a[k].qs > ex[n_v0+rev_n-i-1].qs) res->a[k].qs = ex[n_v0+rev_n-i-1].qs; - } - if(i < ((uint32_t)idx[k]) && res->a[k].qs < ex[n_v0+i].qs) { - res->a[k].qs = ex[n_v0+i].qs; - } - } - res->n = n_u; - radix_sort_ul_ov_srt_qn(res->a, res->a + res->n); - return n_v; -} - -uint32_t check_trans_rate(ul_ov_t *a, int64_t a_n, float trans_thres) -{ - uint32_t sp = (uint32_t)-1, ep = (uint32_t)-1, tts = (uint32_t)-1, tte = 0, el = 0, iel = 0; - int64_t k; - for (k = a_n-1; k >= 0; k--) { - if(a[k].qs < tts) tts = a[k].qs; - if(a[k].qe > tte) tte = a[k].qe; - if(!(a[k].el)) continue; - if(sp == (uint32_t)-1 || a[k].qe <= sp) { - if(sp != (uint32_t)-1) el += ep - sp; - sp = a[k].qs; - ep = a[k].qe; - } else { - sp = MIN(sp, a[k].qs); - } - } - if(sp != (uint32_t)-1) el += ep - sp; - iel = (tte - tts) - el; - // fprintf(stderr, "[M::%s] el:%u, iel:%u\n", __func__, el, iel); - if((iel == 0) || (iel <= ((tte - tts)*trans_thres))) return 1; - return 0; -} - -uint32_t ff_chain(kv_ul_ov_t *idx, int64_t qlen, float cov_rate, float trans_thres, ul_ov_t *a, -overlap_region_alloc* olist, haplotype_evdience_alloc *hap, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, -void *km) -{ - if(idx->n <= 0) return 0; - ul_ov_t *m = &(idx->a[idx->n-1]); //largest chain - // fprintf(stderr, "[M::%s] m->score:%u, m->qs:%u, m->qe:%u, chain_n:%u\n", __func__, m->qn, m->qs, m->qe, m->te-m->ts); - if((m->qe-m->qs) <= (qlen*cov_rate)) return 0; - if(trans_thres >= 0) { - if(check_trans_rate(a+m->ts, m->te-m->ts, trans_thres)) return 1; - if(olist && hap && uref) { - int64_t idx_n = idx->n, z, i, het_n, resc_tk = 0, f = 0; - uint64_t si; ma_utg_t *u = NULL; - for (z = m->ts; z < m->te; z++) { - if(a[z].el) { - kv_push_km(km, ul_ov_t, *idx, a[z]); - } else { - i = a[z].qn; si = 0; - het_n = update_ava_het_site(hap, i, &si, NULL, 1); - assert(het_n > 0 && olist->list[i].is_match == 2); - u = &(uref->ug->u.a[olist->list[i].y_id]); - if(u->n > 1) { - resc_tk += rescue_trans_ul_chains(uref, &(olist->list[i]), hap->list+si, het_n, u, - idx, diff_ec_ul, winLen, 0, NULL, km); - } - } - } - - if(resc_tk) { - radix_sort_ul_ov_srt_qe(idx->a+idx_n, idx->a+idx->n); - f = check_trans_rate(idx->a+idx_n, idx->n-idx_n, trans_thres); - } - idx->n = idx_n; - return f; - } - return 0; - } else { - return 1; - } -} - -void dump_chain(kv_ul_ov_t *des, ul_ov_t *src, ul_ov_t *chain, void *km) -{ - ///note: dump results to may change , so we should save in advance - uint64_t beg = chain->ts, occ = chain->te - chain->ts; - kv_resize_km(km, ul_ov_t, *des, occ); des->n = occ; - memcpy(des->a, src + beg, occ*sizeof((*src))); -} - -int64_t dedup_sort_contains(ul_ov_t *a, int64_t a_n, ul_contain *ct, const ug_opt_t *uopt) -{ - int64_t k, l, ci; ul_ov_t *z = NULL; - for (k = 0; k < a_n; k++) { - z = &(a[k]); - if(z->tn&((uint32_t)(0x80000000))) continue;///contained alignment - if(ct->is_c.a[z->tn] == 0) continue; - - for (ci = k+1; ci < a_n; ci++) { - if(a[ci].qe > z->qe + G_CHAIN_INDEL) break;///128 is for indel - if(a[ci].qn == (uint32_t)-1) continue; - if(!(a[ci].tn&((uint32_t)(0x80000000)))) continue; - if(z->qs <= a[ci].qs + G_CHAIN_INDEL && z->qe + G_CHAIN_INDEL >= a[ci].qe) { - if(check_contain_pair(uopt, (a[ci].tn<<1)>>1, z->tn, 1)) { - a[ci].qn = (uint32_t)-1; - } - } - } - - for (ci = k-1; ci >= 0; ci--) { - if(a[ci].qe + G_CHAIN_INDEL <= z->qs) break; - if(a[ci].qn == (uint32_t)-1) continue; - if(!(a[ci].tn&((uint32_t)(0x80000000)))) continue; - if(z->qs <= a[ci].qs + G_CHAIN_INDEL && z->qe + G_CHAIN_INDEL >= a[ci].qe) { - if(check_contain_pair(uopt, (a[ci].tn<<1)>>1, z->tn, 1)) { - a[ci].qn = (uint32_t)-1; - } - } - } - } - for (k = l = 0; k < a_n; k++) { - if(a[k].qn == (uint32_t)-1) continue; - if(k != l) a[l] = a[k]; - a[l].tn <<= 1; a[l].tn >>= 1; - ++l; - } - return l; -} - -void ins_merge_ul_ov(kv_ul_ov_t *idx, int64_t idx_s, int64_t idx_e, ul_ov_t q) -{ - int64_t k, ii, s = -1, e = -1, ovlp = 0, qs = q.qs, qe = q.qe; - for (k = idx_s, ii = -1; k < idx_e; k++) { - if(ii == -1 && q.qs > idx->a[k].qs) ii = k; - if(((int64_t)(idx->a[k].qs)) >= e) { - if(s >= 0 && e >= 0) { - ovlp += ((MIN(e, qe) > MAX(s, qs))?(MIN(e, qe) - MAX(s, qs)):0); - } - s = idx->a[k].qs; e = idx->a[k].qe; - } else { - if(e < ((int64_t)(idx->a[k].qe))) e = idx->a[k].qe; - } - } - - if(s >= 0 && e >= 0) { - ovlp += ((MIN(e, qe) > MAX(s, qs))?(MIN(e, qe) - MAX(s, qs)):0); - } -} - -void dump_all_chain(kv_ul_ov_t *idx, kv_ul_ov_t *ax, int64_t ax_new_occ, int64_t qlen, float primary_cov_rate, float primary_score_rate) { - if(idx->n <= 0) return; - ul_ov_t *m = &(idx->a[idx->n-1]); //largest chain - ul_ov_t *a = ax->a + ax->n; int64_t k, i, z, l, idx_n = idx->n; uint64_t ovlp; - if((m->qe-m->qs) > (qlen*primary_cov_rate)) { ///found a primary chain - for (k = m->ts, l = 0; k < m->te; k++) { - a[l] = a[k]; a[l].tn |= ((uint32_t)(0x80000000)); - l++; - } - ax->n += l; - } else { - for (k = idx_n-1; k >= 0; k--) { - for (i = idx_n-1; i > k; i--) { - if(idx->a[i].qn == (uint32_t)-1) continue;///just remove totally contained alignments - if(idx->a[k].qn > idx->a[i].qn*primary_score_rate) continue;///consider score - ovlp = ((MIN(idx->a[k].qe, idx->a[i].qe) > MAX(idx->a[k].qs, idx->a[i].qs))? - (MIN(idx->a[k].qe, idx->a[i].qe) - MAX(idx->a[k].qs, idx->a[i].qs)):0); - if(ovlp > ((idx->a[k].qe-idx->a[k].qs)*primary_cov_rate)) { - for (z = idx->a[k].ts; z < idx->a[k].te; z++) a[z].el = 1; - idx->a[k].qn = (uint32_t)-1; - break; - } - } - // ins_merge_ul_ov(idx, idx_n, idx->n, idx->a[k]); - } - for (k = 0, l = 0; k < ax_new_occ; k++) { - if(a[k].el) continue; - a[l] = a[k]; l++; - } - radix_sort_ul_ov_srt_qe(a, a + l); - ax->n += l; - } -} - -int64_t dump_all_chain_simple(kv_ul_ov_t *idx, kv_ul_ov_t *ax, int64_t ax_new_occ, int64_t qlen, -float primary_cov_rate, float fragement_cov_rate, float primary_fragment_cov_rate, -float primary_fragment_second_score_rate, float trans_thres, uint64_t mini_primary_fragment_len) -{ - if(idx->n <= 0) return 0; - ul_ov_t *m = &(idx->a[idx->n-1]); //largest chain - ul_ov_t *a = ax->a + ax->n; int64_t k, z, l, idx_n = idx->n, ovlp, om, ok, ff = 0; - // fprintf(stderr, "[M::%s] m->score:%u, m->qs:%u, m->qe:%u, chain_n:%u\n", __func__, m->qn, m->qs, m->qe, m->te-m->ts); - if(((m->qe-m->qs) > (qlen*primary_cov_rate)) && - (check_trans_rate(a+m->ts, m->te-m->ts, trans_thres))) { ///found a primary chain - for (k = m->ts, l = 0; k < m->te; k++) { - a[l] = a[k]; a[l].tn |= ((uint32_t)(0x80000000)); a[l].el = 1; - l++; - } - ax->n += l; ff = 1; - } else { - if((((m->qe-m->qs) > (qlen*primary_fragment_cov_rate)) || ((m->qe - m->qs) > mini_primary_fragment_len)) - && (check_trans_rate(a+m->ts, m->te-m->ts, trans_thres))) { - om = m->qe - m->qs; - for (k = 0; k < idx_n-1; k++) { - ovlp = ((MIN((m->qe), (idx->a[k].qe)) > MAX((m->qs), (idx->a[k].qs)))? - (MIN((m->qe), (idx->a[k].qe)) - MAX((m->qs), (idx->a[k].qs))):0); - if(ovlp == 0) continue; - ok = idx->a[k].qe - idx->a[k].qs; - if(ok > om ) ok = om; - if((ovlp > ok*0.1/**0.25**/) && idx->a[k].qn > (m->qn*primary_fragment_second_score_rate)) break; - } - - if(k >= idx_n-1) { - for (k = m->ts; k < m->te; k++) { - // if(a[k].el) a[k].tn |= ((uint32_t)(0x80000000)); - a[k].tn |= ((uint32_t)(0x80000000)); - } - ff = 1; - } - } - - radix_sort_ul_ov_srt_qe(idx->a, idx->a + idx->n); - for (k = 0; k < idx_n; k++) { - if(k < idx_n-1 && idx->a[k].qe > idx->a[k+1].qs) break;//not one chain - if((idx->a[k].qe - idx->a[k].qs) > (qlen*fragement_cov_rate)) {///large enough fragements - if(!check_trans_rate(a+idx->a[k].ts, idx->a[k].te-idx->a[k].ts, trans_thres)) break; - } - } - - if(k == idx_n) {///only if there is a clear chain (with holes) - for (k = 0; k < idx_n; k++) { - if((idx->a[k].qe - idx->a[k].qs) <= (qlen*fragement_cov_rate)) continue; - for (z = idx->a[k].ts; z < idx->a[k].te; z++) { - // if(a[z].el) a[z].tn |= ((uint32_t)(0x80000000)); - a[z].tn |= ((uint32_t)(0x80000000)); - } - ff = 1; - } - } - /** - for (k = 0, l = 0; k < ax_new_occ; k++) { - if(!(a[k].el)) continue; - a[l] = a[k]; l++; - } - - radix_sort_ul_ov_srt_qe(a, a + l); - ax->n += l; - **/ - for (k = 0, l = 0; k < ax_new_occ; k++) { - if(a[k].el || (a[k].tn&((uint32_t)(0x80000000)))) { - a[l] = a[k]; l++; - } - } - ax_new_occ = l; - - radix_sort_ul_ov_srt_qe(a, a + ax_new_occ); - for (k = 1, l = 0; k <= ax_new_occ; k++) { - if (k == ax_new_occ || a[k].qe != a[l].qe) { - if(k - l > 1) radix_sort_ul_ov_srt_qs(a+l, a+k); - l = k; - } - } - ax->n += ax_new_occ; - } - return ff; -} - -void save_tmp_chains(ul_ov_t *idx_a, uint64_t idx_n, uint64_t *idx_buf_0, uint64_t *idx_buf_1, ul_ov_t *cc_a, uint64_t cc_n, uint64_t *cc_buf) -{ - uint64_t k; - for (k = 0; k < idx_n; k++) ; -} - -void debug_reverse_chain(ul_ov_t *a, int64_t a_n) -{ - int64_t rev_n = a_n>>1, i; ul_ov_t rev_t; - for (i = 0; i < rev_n; i++) { - rev_t = a[i]; a[i] = a[a_n-i-1]; a[a_n-i-1] = rev_t; - } -} - -uint32_t quick_primary_assgin(const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, ul_ov_t *a, int64_t a_n) -{ - int64_t k, qo, share, f = 1; ul_ov_t *li, *lk; uint32_t li_v, lk_v; - for (k = a_n - 1, li = NULL; k >= 0; k--) { - lk = &(a[k]); lk_v = (lk->tn<<1)|lk->rev; lk->sec = SEC_MODE; - if(!(lk->tn&((uint32_t)(0x80000000)))) continue; - if(li && lk->qe > li->qs) { ///lk is overlapped with li - li->tn <<= 1; li->tn >>= 1; lk->tn <<= 1; lk->tn >>= 1; - qo = infer_rovlp(li, lk, NULL, NULL, NULL, NULL); - li->tn |= ((uint32_t)(0x80000000)); lk->tn |= ((uint32_t)(0x80000000)); - if(qo && li_v != lk_v && get_ecov_adv(uref, uopt, li_v^1, lk_v^1, bw, diff_ec_ul, qo, 1, &share)) { - li->sec = k; f++; ///the end of a chain is a cis overlap - } else { - f = 0; - break; - } - } - li = lk; li_v = lk_v; - } - return f; -} - -void assgin_primary_chains(ul_ov_t *a, int64_t a_n, int64_t is_srt, const ul_idx_t *uref, const ug_opt_t *uopt, -uint64_t *track, uint64_t *srt, int64_t bw, double diff_ec_ul, int64_t qlen, int64_t is_ungap) -{ - if(a_n == 0) return; - int64_t i, j, k, mm_ovlp, x, csc, mm_sc, mm_idx, qo, share, sc; - uint32_t li_v, lj_v; ul_ov_t *li = NULL, *lj = NULL; - if(is_srt) { - radix_sort_ul_ov_srt_qe(a, a + a_n); - for (i = 1, j = 0; i <= a_n; i++) { - if (i == a_n || a[i].qe != a[j].qe) { - if(i - j > 1) { - radix_sort_ul_ov_srt_qs(a+j, a+i); - } - j = i; - } - } - } - - if(uref && uopt && track && srt) { - if(quick_primary_assgin(uref, uopt, bw, diff_ec_ul, a, a_n) == 0) { - for (i = 0; i < a_n; ++i) { - li = &(a[i]); li_v = (li->tn<<1)|li->rev; li->sec = SEC_MODE; - mm_sc = csc = 1; mm_idx = -1; - if(li->tn&((uint32_t)(0x80000000))) { - mm_ovlp = max_ovlp_src(uopt, li_v^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(i, a, x+G_CHAIN_INDEL); - - for (j = x; j >= 0; --j) { - lj = &(a[j]); lj_v = (lj->tn<<1)|lj->rev; - if(lj->qe+G_CHAIN_INDEL <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore - if(is_ungap && (lj->qs >= li->qs+G_CHAIN_INDEL)) continue; // lj is contained in li on the query coordinate; 128 for indel offset - if(!(lj->tn&((uint32_t)(0x80000000)))) continue; - li->tn <<= 1; li->tn >>= 1; lj->tn <<= 1; lj->tn >>= 1; - qo = infer_rovlp(li, lj, NULL, NULL, NULL, NULL); - li->tn |= ((uint32_t)(0x80000000)); lj->tn |= ((uint32_t)(0x80000000)); - if(qo && li_v != lj_v && get_ecov_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, 1, &share)) { - sc = csc + pop_sc(track[j]); - if(sc > mm_sc) mm_sc = sc, mm_idx = j; - } - } - } - track[i] = push_sc_pre(mm_sc, mm_idx); - srt[i] = track[i]>>32; srt[i] <<= 32; srt[i] |= i; - // fprintf(stderr, "[M::] i->%ld; mm_idx->%ld\n", i, mm_idx); - } - - radix_sort_gfa64(srt, srt+a_n); - for (k = a_n-1; k >= 0; --k) { - i = (uint32_t)srt[k]; - // if(i < 0 || i >= a_n) fprintf(stderr, "sbsbsbsbsbsb, k->%ld, i->%ld, a_n->%ld\n", k, i, a_n); - if(a[i].el && (a[i].tn&((uint32_t)(0x80000000)))) { - for (; i >= 0 && (track[i]&((uint64_t)0x80000000)) == 0;) { - track[i] |= ((uint64_t)0x80000000); j = i; - i = pop_pre(track[i]); - if(i >= 0) { - // if(i == j) fprintf(stderr, "sb\n"); - a[j].sec = i; - } - } - } - } - } - } -} - -int64_t gl_chain_refine_advance(overlap_region_alloc* olist, Correct_dumy* dumy, haplotype_evdience_alloc *hap, glchain_t *ll, st_mt_t *sps, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, int64_t qlen, const ug_opt_t *uopt, -int64_t debug_i, void *km) -{ - // ll->tk.n = ll->lo.n = 0; - kv_ul_ov_t *idx = &(ll->lo); - ul_contain *ct = uref->ct; - uint64_t o2 = gl_chain_gen(olist, uref, idx, 0, hap, km); - if(idx->n == 0) return 0; - // fprintf(stderr, "[M::%s] qlen:%ld, idx->n:%u\n", __func__, qlen, (uint32_t)idx->n); - uint64_t k, an, cn, si = 0, ei = 0, resc = 0, resc_tk = 0, tk_pl = 0, f = 0, occ = 0, cis_occ = 0, t_cis = 0; - ma_utg_t *u = NULL; overlap_region *o = NULL; - - kv_resize_km(km, uint64_t, ll->srt.a, idx->n); - kv_resize_km(km, uint64_t, hap->snp_srt, idx->n); - kv_resize_km(km, ul_ov_t, ll->tk, ll->tk.n+idx->n); - ///note: there are three rounds of gl_chain_advance() - ///the first two rounds could reuse dumy->overlapID. But for the last round, dumy->overlapID is not long enough - occ = gl_chain_advance(idx, ll->tk.a+ll->tk.n, uref, uopt, G_CHAIN_BW, diff_ec_ul, qlen, UG_SKIP, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 0, NULL, uref->ug, debug_i, km); - if(occ) { - if(ff_chain(idx, qlen, P_CHAIN_COV, -1/**G_CHAIN_TRANS_RATE**/, ll->tk.a+ll->tk.n, NULL, NULL, NULL, diff_ec_ul, winLen, km)) { - f = 1; //dump_chain(idx, ll->tk.a+ll->tk.n, &(idx->a[idx->n-1]), km); - for (k = idx->a[idx->n-1].ts; k < idx->a[idx->n-1].te; k++) { - olist->list[ll->tk.a[ll->tk.n+k].qn].x_pos_strand = 1; - } - } else if(o2) {///means there are trans overlaps - gl_chain_gen(olist, uref, idx, 1, hap, km); - kv_resize_km(km, uint64_t, ll->srt.a, idx->n); - kv_resize_km(km, uint64_t, hap->snp_srt, idx->n); - kv_resize_km(km, ul_ov_t, ll->tk, ll->tk.n+idx->n); - ///chain all U-matches - occ = gl_chain_advance(idx, ll->tk.a+ll->tk.n, uref, uopt, G_CHAIN_BW, diff_ec_ul, qlen, UG_SKIP, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 0, NULL, uref->ug, debug_i, km); - if(ff_chain(idx, qlen, P_CHAIN_COV, G_CHAIN_TRANS_RATE, ll->tk.a+ll->tk.n, olist, hap, uref, diff_ec_ul, winLen, km)) { - f = 1; //dump_chain(idx, ll->tk.a+ll->tk.n, &(idx->a[idx->n-1]), km); - for (k = idx->a[idx->n-1].ts; k < idx->a[idx->n-1].te; k++) { - olist->list[ll->tk.a[ll->tk.n+k].qn].x_pos_strand = 1; - } - } - } - } - - if(!f) {///if f == 1, only dump primary chain; otherwise dump all chains - ///we can save all data to buffer like ll->srt.a in advance; in case we don't need third round of chaining - ///means no trans overlaps, no need to do third round of chaining - // if(!o2) { - // ; - // } - /** - uint64_t z; - for (k = 0; k < idx->n; k++) { - if(check_trans_rate(ll->tk.a+ll->tk.n+idx->a[k].ts, idx->a[k].te-idx->a[k].ts, G_CHAIN_TRANS_RATE)) { - for (z = idx->a[k].ts; z < idx->a[k].te; z++) { - olist->list[ll->tk.a[ll->tk.n+z].qn].x_pos_strand = 1; - } - } else { - for (z = idx->a[k].ts; z < idx->a[k].te; z++) { - if(!(ll->tk.a[ll->tk.n+z].el)) continue; - olist->list[ll->tk.a[ll->tk.n+z].qn].x_pos_strand = 1; - } - } - } - **/ - for (k = 0; k < occ; k++) { - olist->list[ll->tk.a[ll->tk.n+k].qn].x_pos_strand = 1; - } - // kv_resize_km(km, ul_ov_t, *idx, occ); idx->n = occ; - // memcpy(idx->a, ll->tk.a+ll->tk.n, occ*sizeof((*(idx->a)))); - } - // for (k = 0; k < idx->n; k++) olist->list[idx->a[k].qn].x_pos_strand = 1; - - for (k = 0, idx->n = 0, tk_pl = ll->tk.n, t_cis = 0; k < olist->length; k++) { - o = &(olist->list[k]); - ///if f == 1, no matter - if(o->x_pos_strand && (f || o->is_match == 1)){ - u = &(uref->ug->u.a[o->y_id]);///overlaped reads - resc_tk += rescue_trans_ul_chains(uref, o, NULL, 0, u, &(ll->tk), -1, -1, 0, NULL, km); - } else if((!f) && o->is_match == 2) { - // fprintf(stderr, "###[M::%s] # k:%lu, # o->y_id:%u\n", __func__, k, o->y_id); - an = update_ava_het_site(hap, k, &si, &ei, 1); - // if(an != get_het_site(hap, k)) fprintf(stderr, "an->%lu, get_het_site->%lu\n", an, get_het_site(hap, k)); - assert(an > 0); - - cn = ((uint32_t)(ct->idx.a[o->y_id])); - if(cn > 0) { - resc += rescue_contain_ul_chains(uref, o, hap->list+si, an, - ct->rids.a + ((ct->idx.a[o->y_id])>>32), cn, idx, diff_ec_ul, winLen, 0, km); - } - - u = &(uref->ug->u.a[o->y_id]); - if(u->n > 1 || o->x_pos_strand) {///no redundant items here - resc_tk += rescue_trans_ul_chains(uref, o, hap->list+si, an, u, - &(ll->tk), diff_ec_ul, winLen, o->x_pos_strand, &cis_occ, km); - t_cis += cis_occ; - } - - si = ei; - } - } - - assert(ll->tk.n == resc_tk+tk_pl); - assert(idx->n == resc); - if(f) assert(resc==0); - - - if(!f) {///dedup contained alignments - if(idx->n) {///if some contained alignments have been rescued - radix_sort_ul_ov_srt_tn(idx->a, idx->a + idx->n); - idx->n = dedup_sort_ul_ov_t(idx->a, idx->n);///different trans alignments may have the same contained alignment - } - resc = idx->n; - // fprintf(stderr, "***[M::%s] # contain:%lu, # non-contain:%lu\n", __func__, resc, (uint64_t)(ll->tk.n-tk_pl)); - for (k = tk_pl; k < ll->tk.n; k++) {///dump all non-contained reads - kv_push_km(km, ul_ov_t, *idx, ll->tk.a[k]); - if(idx->a[idx->n-1].tn&((uint32_t)(0x80000000))) { - idx->a[idx->n-1].tn -= ((uint32_t)(0x80000000)); - } - } - ll->tk.n = tk_pl; - - radix_sort_ul_ov_srt_qe(idx->a, idx->a + idx->n); - if(resc) {///need to dedup contained alignment again - // fprintf(stderr, "[M::%s] idx->n:%lu, resc:%lu\n", __func__, (uint64_t)idx->n, resc); - idx->n = dedup_sort_contains(idx->a, idx->n, ct, uopt); - } - - ///note: need sps for third round of gl_chain_advance() as dumy->overlapID might be not long enough - kv_resize_km(km, uint64_t, *sps, idx->n); - kv_resize_km(km, uint64_t, ll->srt.a, idx->n); - kv_resize_km(km, uint64_t, hap->snp_srt, idx->n); - kv_resize_km(km, ul_ov_t, ll->tk, ll->tk.n+idx->n); - occ = gl_chain_advance(idx, ll->tk.a+ll->tk.n, uref, uopt, G_CHAIN_BW, diff_ec_ul, qlen, UG_SKIP, sps->a, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 1, &R_INF, NULL, debug_i, km); - // fprintf(stderr, "***[M::%s] ll->tk.n:%u, occ:%lu\n", __func__, (uint32_t)ll->tk.n, occ); - f = dump_all_chain_simple(idx, &(ll->tk), occ, qlen, P_CHAIN_COV, P_FRAGEMENT_CHAIN_COV, - P_FRAGEMENT_PRIMARY_CHAIN_COV, 0.1/**P_FRAGEMENT_PRIMARY_SECOND_COV**/, G_CHAIN_TRANS_RATE, PRIMARY_UL_CHAIN_MIN); - // fprintf(stderr, ">>>[M::%s] ll->tk.n:%u\n", __func__, (uint32_t)ll->tk.n); - // dump_all_chain(idx, &(ll->tk), occ, qlen, P_CHAIN_COV, P_CHAIN_SCORE); - } else { - ///for primary chain, each element x: (x->tn & (uint32_t)(0x80000000)) - assgin_primary_chains(ll->tk.a+tk_pl, ll->tk.n-tk_pl, 1, NULL, NULL, NULL, NULL, G_CHAIN_BW, diff_ec_ul, qlen, 1); - // radix_sort_ul_ov_srt_qe(ll->tk.a+tk_pl, ll->tk.a+ll->tk.n); - } - - ///if f == 0, results have already been sorted by qe|qs - if(f) { - kv_resize_km(km, uint64_t, ll->srt.a, ll->tk.n-tk_pl); kv_resize_km(km, uint64_t, hap->snp_srt, ll->tk.n-tk_pl); - assgin_primary_chains(ll->tk.a+tk_pl, ll->tk.n-tk_pl, 0, uref, uopt, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_BW, diff_ec_ul, qlen, 1); - } - // debug_reverse_chain(ll->tk.a+tk_pl, ll->tk.n-tk_pl); - /** - if(idx->n > 0) { - an = infer_read_ovlp(uref, olist, idx , &(ll->tk), diff_ec_ul, winLen, uopt, ct, km); - // if(an) fill_edge_weight(ll->tk.a+ll->tk.n-an, an, uopt, G_CHAIN_BW, diff_ec_ul, qlen); - } - **/ - return 1; -} - -int64_t g_adjacent_dis(const asg_t *g, uint32_t v, uint32_t w) -{ - uint32_t nv, i; asg_arc_t *av = NULL; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (i = 0; i < nv; i++) { - if(av[i].del || av[i].v != w) continue; - return (uint32_t)av[i].ul; - } - return -1; -} - -void get_r_offset(ma_ug_t *ug, mg_lchain_t *x, int64_t *rs, int64_t *re, int64_t *qs, int64_t *qe) -{ - if(qs) *qs = x->qs; if(qe) *qe = x->qe; - if(!(x->score&1)) { - if(rs) *rs = x->rs + x->off; - if(re) *re = x->re + x->off; - } else { - if(rs) *rs = x->off + ug->g->seq[x->score>>1].len - x->re; - if(re) *re = x->off + ug->g->seq[x->score>>1].len - x->rs; - } -} - -void get_u_offset(ma_ug_t *ug, mg_lchain_t *x, int64_t *rs, int64_t *re, int64_t *qs, int64_t *qe) -{ - if(qs) *qs = x->qs; if(qe) *qe = x->qe; - if(!(x->v&1)) { - if(rs) *rs = x->rs + x->off; - if(re) *re = x->re + x->off; - } else { - if(rs) *rs = x->off + ug->g->seq[x->v>>1].len - x->re; - if(re) *re = x->off + ug->g->seq[x->v>>1].len - x->rs; - } -} - -void l2g_chain(const ul_idx_t *uref, kv_ul_ov_t *lidx, vec_mg_lchain_t *res) -{ - uint64_t k; - res->n = 0; kv_resize(mg_lchain_t, *res, lidx->n); res->n = lidx->n; - for (k = 0; k < lidx->n; k++) { - memset(&(res->a[k]), 0, sizeof(res->a[k])); - res->a[k].v = (lidx->a[k].tn<<1)|(lidx->a[k].rev); - res->a[k].off = lidx->a[k].qn; res->a[k].score = lidx->a[k].sec; - res->a[k].qs = lidx->a[k].qs; res->a[k].qe = lidx->a[k].qe; - res->a[k].rs = lidx->a[k].ts; res->a[k].re = lidx->a[k].te; - if(lidx->a[k].el) { - res->a[k].score = retrieve_u_cov_region(uref, lidx->a[k].tn, 0, lidx->a[k].ts, lidx->a[k].te, NULL); - } - } -} - -int64_t l2g_res_chain(ma_ug_t *ug, ul_ov_t *a, uint64_t a_n, vec_mg_lchain_t *gchains, double diff_rate) -{ - // fprintf(stderr, "[M::%s::] a_n::%lu\n", __func__, a_n); - if(a_n <= 0) return 0; - uint64_t k, m; int64_t l, rs, re, qs, qe, dq, dr, dif, mm; a_n++; asg_t *g = ug->g; - gchains->n = 0; kv_resize(mg_lchain_t, *gchains, a_n); gchains->n = a_n; - memset(&(gchains->a[0]), 0, sizeof(gchains->a[0])); - gchains->a[0].cnt = a_n - 1; gchains->a[0].v = (uint32_t)-1; - for (k = 1, m = 0, l = 0; k < a_n; k++, m++) { - memset(&(gchains->a[k]), 0, sizeof(gchains->a[k])); - gchains->a[k].v = (a[m].tn<<1)|(a[m].rev); gchains->a[k].dist_pre = -1; - gchains->a[k].off = a[m].qn; gchains->a[k].score = a[m].sec; - gchains->a[k].qs = a[m].qs; gchains->a[k].qe = a[m].qe; - gchains->a[k].rs = a[m].ts; gchains->a[k].re = a[m].te; - if(k > 1) { - gchains->a[k-1].dist_pre = g_adjacent_dis(g, gchains->a[k].v^1, gchains->a[k-1].v^1); - assert(gchains->a[k-1].dist_pre >= 0); - l += g->seq[gchains->a[k-1].v>>1].len + gchains->a[k-1].dist_pre; - } - // fprintf(stderr, "[M::%s::k->%lu] utg%.6dl(%c)\n", __func__, k, (int32_t)(gchains->a[k].v>>1)+1, "+-"[gchains->a[k].v&1]); - } - - if(diff_rate < 0) return 1; - - mg_lchain_t s = gchains->a[1], e = gchains->a[a_n-1]; - s.off = 0; - l -= (int64_t)g->seq[gchains->a[a_n-1].v>>1].len; - if(l < 0) l = 0; - e.off = l; - - get_u_offset(ug, &s, &rs, NULL, &qs, NULL); get_u_offset(ug, &e, NULL, &re, NULL, &qe); - dq = qe - qs; dr = re - rs; - dif = (dq>dr? dq-dr:dr-dq); - mm = MAX(dq, dr); mm *= diff_rate; - if(dif <= mm) return 1; - return 0; -} - - -int64_t l2g_res_chain_sc(ma_ug_t *ug, ul_ov_t *a, uint64_t a_n, vec_mg_lchain_t *gchains) -{ - // fprintf(stderr, "[M::%s::] a_n::%lu\n", __func__, a_n); - if(a_n <= 0) return 0; - uint64_t k, m; int64_t l; a_n++; asg_t *g = ug->g; - gchains->n = 0; kv_resize(mg_lchain_t, *gchains, a_n); gchains->n = a_n; - memset(&(gchains->a[0]), 0, sizeof(gchains->a[0])); - gchains->a[0].cnt = a_n - 1; gchains->a[0].v = (uint32_t)-1; - for (k = 1, m = 0, l = 0; k < a_n; k++, m++) { - memset(&(gchains->a[k]), 0, sizeof(gchains->a[k])); - gchains->a[k].v = (a[m].tn<<1)|(a[m].rev); gchains->a[k].dist_pre = -1; - gchains->a[k].off = a[m].qn; gchains->a[k].score = a[m].sec; - gchains->a[k].qs = a[m].qs; gchains->a[k].qe = a[m].qe; - gchains->a[k].rs = a[m].ts; gchains->a[k].re = a[m].te; - if(k > 1) { - gchains->a[k-1].dist_pre = g_adjacent_dis(g, gchains->a[k].v^1, gchains->a[k-1].v^1); - assert(gchains->a[k-1].dist_pre >= 0); - l += g->seq[gchains->a[k-1].v>>1].len + gchains->a[k-1].dist_pre; - } - // fprintf(stderr, "[M::%s::k->%lu] utg%.6dl(%c)\n", __func__, k, (int32_t)(gchains->a[k].v>>1)+1, "+-"[gchains->a[k].v&1]); - } - - return 1; -} - -int64_t check_elen_gchain(ul_ov_t *a, int64_t a_n, float trans_thres) -{ - uint32_t sp_e, ep_e, ts, te, tl = 0, el = 0, iel = 0; - sp_e = ep_e = ts = te = (uint32_t)-1; - int64_t k; - for (k = a_n-1; k >= 0; k--) { - if(ts == (uint32_t)-1 || a[k].qe <= ts) { - if(ts != (uint32_t)-1) tl += te - ts; - ts = a[k].qs; te = a[k].qe; - } else { - ts = MIN(ts, a[k].qs); - } - if(!(a[k].el)) continue; - - if(sp_e == (uint32_t)-1 || a[k].qe <= sp_e) { - if(sp_e != (uint32_t)-1) el += ep_e - sp_e; - sp_e = a[k].qs; - ep_e = a[k].qe; - } else { - sp_e = MIN(sp_e, a[k].qs); - } - } - if(ts != (uint32_t)-1) tl += te - ts; - if(sp_e != (uint32_t)-1) el += ep_e - sp_e; - - iel = tl - el; - // fprintf(stderr, "[M::%s] el:%u, iel:%u\n", __func__, el, iel); - if((iel == 0) || (iel <= (tl*trans_thres))) return 1; - return 0; -} - -int64_t ds_check_vec_mg_lchain_t(mg_lchain_t *a, int64_t a_n, kv_ul_ov_t *buf, overlap_region_alloc* olist, -haplotype_evdience_alloc *hap, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, float trans_thres) -{ - if(a_n <= 0) return 0; - int64_t k, resc_tk, het_n; ul_ov_t *p; uint64_t si; ma_utg_t *u = NULL; buf->n = 0; - for (k = 0; k < a_n; k++) { - if(a[k].off < 0) continue; - kv_pushp(ul_ov_t, *buf, &p); - p->qs = a[k].qs; p->qe = a[k].qe; p->el = 1; - if(a[k].score < 0) p->el = 0; - } - if(buf->n <= 0) return 0; - if(check_elen_gchain(buf->a, buf->n, trans_thres)) return 1; - - buf->n = 0; resc_tk = 0; - for (k = 0; k < a_n; k++) { - if(a[k].off < 0) continue; - if(a[k].score >= 0) { - kv_pushp(ul_ov_t, *buf, &p); - p->qs = a[k].qs; p->qe = a[k].qe; p->el = 1; - } else { - si = 0; - het_n = update_ava_het_site(hap, a[k].off, &si, NULL, 1); - assert(het_n > 0 && olist->list[a[k].off].is_match == 2); - u = &(uref->ug->u.a[olist->list[a[k].off].y_id]); - if(u->n > 1) { - resc_tk += rescue_trans_ul_chains(uref, &(olist->list[a[k].off]), hap->list+si, het_n, u, - buf, diff_ec_ul, winLen, 0, NULL, NULL); - } - } - } - - if(resc_tk) { - radix_sort_ul_ov_srt_qe(buf->a, buf->a+buf->n); - if(check_elen_gchain(buf->a, buf->n, trans_thres)) return 1; - } - - return 0; -} - -int64_t check_trans_rate_gap(vec_mg_lchain_t *uc, kv_ul_ov_t *buf, overlap_region_alloc* olist, -haplotype_evdience_alloc *hap, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, float trans_thres) -{ - if(uc->n <= 0) return 0; - int64_t k, m, ucn = uc->n, k_cnt, z; mg_lchain_t *ix; buf->n = 0; - for (k = m = 0; k < ucn; k += k_cnt) { - ix = &(uc->a[k]); assert(ix->v == (uint32_t)-1); k_cnt = ix->cnt + 1; - if(ds_check_vec_mg_lchain_t(uc->a + k + 1, ix->cnt, buf, olist, hap, uref, diff_ec_ul, winLen, trans_thres)) { - if(m == k) { - m += k_cnt; - } else { - for (z = 0; z < k_cnt; z++) uc->a[m++] = uc->a[k+z]; - } - } - } - uc->n = m; - if(uc->n) return 1; - return 0; -} - -int64_t hc_gchain1_dp(void *km, const ul_idx_t *uref, const ma_ug_t *ug, vec_mg_lchain_t *lc, vec_mg_lchain_t *sw, vec_mg_path_dst_t *dst, vec_sp_node_t *out, vec_mg_pathv_t *path, -int64_t qlen, const ug_opt_t *uopt, int64_t bw, double diff_thre, double ng_diff_thre, uint64_t *srt, st_mt_t *bf, int64_t *f, uint64_t *p, uint64_t *v); -uint32_t gen_max_gchain_adv(void *km, const ul_idx_t *uref, int64_t ulid, st_mt_t *idx, vec_mg_lchain_t *e, kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, -int64_t qlen, float primary_cov_rate, float primary_fragment_cov_rate, float primary_fragment_second_score_rate, uint64_t mini_primary_fragment_len, -const asg_t *g, st_mt_t *dst_done, vec_sp_node_t *out, vec_mg_pathv_t *res, uint64_t *b, vec_mg_lchain_t *gchains); - - - -void debug_intermediate_chain(ma_ug_t *ug, mg_lchain_t *a, int64_t a_n, int64_t is_uovlp, int64_t debug_i) -{ - int64_t k; mg_lchain_t *p, *c; - int64_t prs, pre, pqs, pqe, crs, cre, cqs, cqe; - int64_t tot = 0, fal = 0; - for (k = a_n-1; k >= 0; k--) { - c = &(a[k]); - if(c->v!=(uint32_t)-1) { - fprintf(stderr, "+(%ld) [M::utg%.6u%c::%c] qs:%d, qe:%d, rs:%d, re:%d, off:%d\n", k, (c->v>>1)+1, "lc"[ug->u.a[c->v>>1].circ], "+-"[c->v&1], - c->qs, c->qe, c->rs, c->re, c->off); - } - - - if(c->hash_pre != (uint32_t)-1) { - p = &(a[c->hash_pre]); tot++; - if(is_uovlp) { - get_u_offset(ug, p, &prs, &pre, &pqs, &pqe); - } else { - get_r_offset(ug, p, &prs, &pre, &pqs, &pqe); - } - if(is_uovlp) { - get_u_offset(ug, c, &crs, &cre, &cqs, &cqe); - } else { - get_r_offset(ug, c, &crs, &cre, &cqs, &cqe); - } - - fprintf(stderr, "cur (%ld) [M::utg%.6u%c::%c] qs:%ld, qe:%ld, rs:%ld, re:%ld, pidx:%u\n", - k, (c->v>>1)+1, "lc"[ug->u.a[c->v>>1].circ], "+-"[c->v&1], cqs, cqe, crs, cre, c->hash_pre); - - fprintf(stderr, "pre (%ld) [M::utg%.6u%c::%c] qs:%ld, qe:%ld, rs:%ld, re:%ld, pidx:%u\n", - k, (p->v>>1)+1, "lc"[ug->u.a[p->v>>1].circ], "+-"[p->v&1], pqs, pqe, prs, pre, p->hash_pre); - - if((!(prs<=crs&&pre<=cre&&pqs<=cqs&&pqe<=cqe)) || (!(prs<=pre&&pqs<=pqe&&crs<=cre&&cqs<=cqe))) { - fal++; - // fprintf(stderr, "[M::%s::a_n->%ld, k->%ld]p->dist_pre:%d, c->dist_pre:%d, c->pre_idx:%u\n", __func__, a_n, k, p->dist_pre, c->dist_pre, c->hash_pre); - // fprintf(stderr, "[M::%s::]prs->%ld, pre->%ld, pqs->%ld, pqe->%ld, crs->%ld, cre->%ld, cqs->%ld, cqe->%ld\n", - // __func__, prs, pre, pqs, pqe, crs, cre, cqs, cqe); - } - assert(prs<=pre&&pqs<=pqe&&crs<=cre&&cqs<=cqe); - // assert(prs<=crs&&pre<=cre&&pqs<=cqs&&pqe<=cqe); - } - } - if(fal) fprintf(stderr, "[M::%s::tot->%ld, fal->%ld] ulid->%ld\n", __func__, tot, fal, debug_i); -} - -int64_t adjust_utg_chain_qoffset(uint64_t *r_srt, int64_t *r_pos, int64_t *q_pos, int64_t r_off) -{ - if(r_off < ((int64_t)(r_srt[0]>>32))) { - // fprintf(stderr, "r_off:%ld, r_srt[0]:%ld\n", r_off, ((int64_t)(r_srt[0]>>32))); - return q_pos[(uint32_t)r_srt[0]]; ///have small chance - } - if(r_off >= ((int64_t)(r_srt[3]>>32))) { - // fprintf(stderr, "r_off:%ld, r_srt[3]:%ld\n", r_off, ((int64_t)(r_srt[3]>>32))); - return q_pos[(uint32_t)r_srt[3]]; ///have small chance - } - int64_t k, rdis, qdis; - for (k = 0; k < 3; k++) { - if(r_off >= ((int64_t)(r_srt[k]>>32)) && r_off < ((int64_t)(r_srt[k+1]>>32))) break; - } - // if(k >= 3) { - // if(rs >= ((int64_t)(r_srt[2]>>32)) && rs <= ((int64_t)(r_srt[3]>>32))) k = 2; - // } - if(k >= 3) { - for (k = 0; k < 3; k++) { - if(r_off >= ((int64_t)(r_srt[k]>>32)) && r_off <= ((int64_t)(r_srt[k+1]>>32))) break; - } - } - assert(k < 3); - - qdis = q_pos[(uint32_t)r_srt[k+1]] - q_pos[(uint32_t)r_srt[k]]; - rdis = r_pos[(uint32_t)r_srt[k+1]] - r_pos[(uint32_t)r_srt[k]]; - if(qdis < 0) return -1; - return q_pos[(uint32_t)r_srt[k]] + get_offset_adjust(r_off-r_pos[(uint32_t)r_srt[k]], rdis, qdis); -} - -int64_t cal_qext_coor(int64_t pr, int64_t ar, int64_t pq, int64_t aq, int64_t r_off) -{ - int64_t q_off = -1, pd, ad; - if(r_off >= pr && r_off <= ar && ar >= pr && aq >= pq) { - q_off = pq + get_offset_adjust(r_off - pr, ar - pr, aq - pq); - } else { - pd = ((r_off >= pr)?(r_off-pr):(pr-r_off)); - ad = ((r_off >= ar)?(r_off-ar):(ar-r_off)); - q_off = ((ad <= pd)?aq:pq); - } - return q_off; -} - -void update_uovlp_chain_qse(ma_ug_t *ug, int64_t sidx, int64_t eidx, mg_lchain_t *a, int64_t a_n) -{ - // fprintf(stderr, "******[M::%s::] sidx:%ld, eidx:%ld\n", __func__, sidx, eidx); - if(eidx - sidx <= 1) return; - ///for ug chains, sidx >= 0 && eidx < a_n - assert(sidx>=0 && eidx= 0 - int64_t pqs, pqe, aqs, aqe, fail_s, fail_e; - if(sidx >= 0) { - get_u_offset(ug, &(a[sidx]), &r_pos[0], &r_pos[1], &q_pos[0], &q_pos[1]); - } else { - get_u_offset(ug, &(a[0]), &r_pos[0], &r_pos[1], &q_pos[0], &q_pos[1]); - } - - if(eidx < a_n) { - get_u_offset(ug, &(a[eidx]), &r_pos[2], &r_pos[3], &q_pos[2], &q_pos[3]); - } else { - get_u_offset(ug, &(a[a_n-1]), &r_pos[2], &r_pos[3], &q_pos[2], &q_pos[3]); - } - prs = r_pos[0]; pre = r_pos[1]; ars = r_pos[2]; are = r_pos[3]; - pqs = q_pos[0]; pqe = q_pos[1]; aqs = q_pos[2]; aqe = q_pos[3]; - // fprintf(stderr, "\n[M::%s::] sidx->%ld, eidx->%ld\n", __func__, - // sidx, r_pos[0], r_pos[1], q_pos[0], q_pos[1], - // eidx, r_pos[2], r_pos[3], q_pos[2], q_pos[3]); - // assert((left_q[0] >= 0 && left_q[1] >= 0) || (right_q[0] >= 0 && right_q[1] >= 0)); ///assert(re >= rs); - ///for ug chains, sidx >= 0 && eidx < a_n - assert(q_pos[0] >= 0 && q_pos[1] >= 0 && q_pos[2] >= 0 && q_pos[3] >= 0); - r_srt[0] = r_pos[0]; r_srt[0] <<= 32; - r_srt[1] = r_pos[1]; r_srt[1] <<= 32; r_srt[1] += 1; - r_srt[2] = r_pos[2]; r_srt[2] <<= 32; r_srt[2] += 2; - r_srt[3] = r_pos[3]; r_srt[3] <<= 32; r_srt[3] += 3; - radix_sort_gfa64(r_srt, r_srt + 4); - // assert(r_pos[(uint32_t)r_srt[0]] == (r_srt[0]>>32)); - // assert(r_pos[(uint32_t)r_srt[1]] == (r_srt[1]>>32)); - // assert(r_pos[(uint32_t)r_srt[2]] == (r_srt[2]>>32)); - // assert(r_pos[(uint32_t)r_srt[3]] == (r_srt[3]>>32)); - - for (i = sidx+1; i < eidx; i++) { - get_u_offset(ug, &(a[i]), &rs, &re, NULL, NULL); - // assert(rs >= prs && rs <= ars && re >= pre && re <= are); - assert(rs <= re); - a[i].qs = adjust_utg_chain_qoffset(r_srt, r_pos, q_pos, rs); fail_s = 1; - a[i].qe = adjust_utg_chain_qoffset(r_srt, r_pos, q_pos, re); fail_e = 1; - if(a[i].qs >= 0 && a[i].qs >= pqs && a[i].qs <= aqs) fail_s = 0; - if(a[i].qe >= 0 && a[i].qe >= pqe && a[i].qe <= aqe) fail_e = 0; - if(a[i].qs > a[i].qe) fail_s = fail_e = 1; - - if(fail_s || fail_e) { - // if(re >= pre && are >= pre && re <= are) {///aqe >= pqe is always true - // a[i].qe = pqe + get_offset_adjust(re-pre, are-pre, aqe-pqe);///first priority - // } else {///abnormal coordinates - // pd = ((re >= pre)?(re-pre):(pre-re)); - // ad = ((re >= are)?(re-are):(are-re)); - // a[i].qe = ((ad <= pd)?aqe:pqe); - // } - a[i].qe = cal_qext_coor(pre, are, pqe, aqe, re); - // if(aqs <= a[i].qe) { - // if(rs >= prs && ars >= prs && rs <= ars) {///aqs >= pqs is always true - // a[i].qs = pqs + get_offset_adjust(rs-prs, ars-prs, aqs-pqs); - // } else { - // pd = ((rs >= prs)?(rs-prs):(prs-rs)); - // ad = ((rs >= ars)?(rs-ars):(ars-rs)); - // a[i].qs = ((ad <= pd)?aqs:pqs); - // } - // } else { - // if(rs >= prs && re >= prs && rs <= re) {///as a[i].qe >= pqe, a[i].qe >= pqs - // a[i].qs = pqs + get_offset_adjust(rs-prs, re-prs, a[i].qe-pqs); - // } else { - // pd = ((rs >= prs)?(rs-prs):(prs-rs)); - // ad = ((rs >= re)?(rs-re):(re-rs)); - // a[i].qs = ((ad <= pd)?a[i].qe:pqs); - // } - // } - a[i].qs = cal_qext_coor(prs, (a[i].qe<=aqs)?re:ars, pqs, (a[i].qe<=aqs)?a[i].qe:aqs, rs); - } - // assert(a[i].qs >= pqs && a[i].qs <= aqs && a[i].qe >= pqe && a[i].qe <= aqe); assert(a[i].qs <= a[i].qe); - assert(a[i].qs >= pqs && a[i].qs <= aqs && a[i].qe >= pqe && a[i].qe <= aqe && a[i].qs <= a[i].qe); - // fprintf(stderr, "[M::%s::i->%ld] rs::%ld, re::%ld, a[i].qs::%d, a[i].qe::%d\n", - // __func__, i, rs, re, a[i].qs, a[i].qe); - - if(i + 1 < eidx) { - q_pos[0] = a[i].qs; q_pos[1] = a[i].qe; r_pos[0] = rs; r_pos[1] = re; - r_srt[0] = r_pos[0]; r_srt[0] <<= 32; - r_srt[1] = r_pos[1]; r_srt[1] <<= 32; r_srt[1] += 1; - r_srt[2] = r_pos[2]; r_srt[2] <<= 32; r_srt[2] += 2; - r_srt[3] = r_pos[3]; r_srt[3] <<= 32; r_srt[3] += 3; - radix_sort_gfa64(r_srt, r_srt + 4); - // assert(r_pos[(uint32_t)r_srt[0]] == (r_srt[0]>>32)); - // assert(r_pos[(uint32_t)r_srt[1]] == (r_srt[1]>>32)); - // assert(r_pos[(uint32_t)r_srt[2]] == (r_srt[2]>>32)); - // assert(r_pos[(uint32_t)r_srt[3]] == (r_srt[3]>>32)); - // fprintf(stderr, "[Srt::i->%ld] , \n", i, - // r_pos[0], r_pos[1], q_pos[0], q_pos[1], - // r_pos[2], r_pos[3], q_pos[2], q_pos[3]); - } - prs = rs; pre = re; pqs = a[i].qs; pqe = a[i].qe; - } - - - - // if(right_q[0] < 0 || right_q[1] < 0) { - // for (i = sidx+1; i < eidx; i++) { - // get_u_offset(ug, &(a[i]), &rs, &re, NULL, NULL); - // a[i].qs = left_q[0] + get_offset_adjust(rs - left_r[0], left_r[1]-left_r[0], left_q[1]-left_q[0]); - // a[i].qe = left_q[1] + (re - left_r[1]); - // left_q[0] = a[i].qs; left_q[1] = a[i].qe; - // left_r[0] = rs; left_r[1] = re; - // } - // } - - // if(left_q[0] < 0 || left_q[1] < 0) { - // for (i = eidx-1; i > sidx; i--) { - // get_u_offset(ug, &(a[i]), &rs, &re, NULL, NULL); - // a[i].qe = right_q[1] - get_offset_adjust(right_r[1]-re, right_r[1]-right_r[0], right_q[1]-right_q[0]); - // a[i].qs = right_q[0] - (right_r[0]-rs); - // right_q[0] = a[i].qs; right_q[1] = a[i].qe; - // right_r[0] = rs; right_r[1] = re; - // } - // } - - // fprintf(stderr, "******[M::%s::] right_q[0]:%ld, right_q[1]:%ld\n", __func__, right_q[0], right_q[1]); -} - - -void debug_update_uovlp_chain_qse(ma_ug_t *ug, mg_lchain_t *a, int64_t a_n, int64_t ulid) -{ - if(a_n <= 2) return; - int64_t r0_s, r0_e, q0_s, q0_e, k; - int64_t r1_s, r1_e, q1_s, q1_e; - get_u_offset(ug, &(a[0]), &r0_s, &r0_e, &q0_s, &q0_e); - get_u_offset(ug, &(a[a_n-1]), &r1_s, &r1_e, &q1_s, &q1_e); - /**if(r0_s <= r1_s && r0_e <= r1_e && q0_s <= q1_s && q0_e <= q1_e)**/ { - for (k = 1; k + 1 < a_n; k++) a[k].qs = a[k].qe = -1; - update_uovlp_chain_qse(ug, 0, a_n-1, a, a_n); - for (k = 1; k < a_n; k++) { - get_u_offset(ug, a + k - 1, &r0_s, &r0_e, &q0_s, &q0_e); - get_u_offset(ug, a + k, &r1_s, &r1_e, &q1_s, &q1_e); - // if(!(r0_s <= r1_s && r0_e <= r1_e && q0_s <= q1_s && q0_e <= q1_e)) { - // fprintf(stderr, "ulid:%ld, r0_s:%ld, r1_s:%ld, r0_e:%ld, r1_e:%ld, q0_s:%ld, q1_s:%ld, q0_e:%ld, q1_e:%ld\n", ulid, - // r0_s, r1_s, r0_e, r1_e, q0_s, q1_s, q0_e, q1_e); - // } - // assert(q0_s <= q1_s && q0_e <= q1_e && q0_s <= q0_e && q1_s <= q1_e); - if(r0_s <= r1_s) assert(q0_s <= q1_s); - if(r0_e <= r1_e) assert(q0_e <= q1_e); - // assert(r0_s <= r1_s && r0_e <= r1_e && q0_s <= q1_s && q0_e <= q1_e); - assert(q0_s>=0 && q0_e>=0 && q1_s>=0 && q1_e>=0); - } - } -} - -void fill_unaligned_alignments(ma_ug_t *ug, mg_lchain_t *a, int64_t a_n, int64_t offset, int64_t ulid) -{ - // fprintf(stderr, "\n[M::%s::] a_n->%ld, offset->%ld\n", __func__, a_n, offset); - if(a_n == 0) return; - int64_t k, l; - for (k = 0, l = ug->g->seq[a[0].v>>1].len; k < a_n; k++) { - l -= ug->g->seq[a[k].v>>1].len; - if(a[k].off < 0) a[k].qs = a[k].qe = -1; - a[k].off = l; a[k].hash_pre = (uint32_t)-1; - if(k > 0) a[k].hash_pre = offset + k - 1; - // fprintf(stderr, "k->%ld, l->%ld, [M::utg%.6u%c::%c::len->%u], qs->%u, qe->%u, rs->%u, re->%u\n", k, l, - // (a[k].v>>1)+1, "lc"[ug->u.a[a[k].v>>1].circ], "+-"[a[k].v&1], ug->u.a[a[k].v>>1].len, - // a[k].qs, a[k].qe, a[k].rs, a[k].re); - l += ug->g->seq[a[k].v>>1].len + a[k].dist_pre; - } - - // debug_update_uovlp_chain_qse(ug, a, a_n, ulid); - - for (l = -1, k = 0; k <= a_n; k++) { - if(k == a_n || a[k].qs >= 0) { ///a[k] and a[l] are anchors - if(k-l>1) update_uovlp_chain_qse(ug, l, k, a, a_n); - l = k; - } - } -} - -void sort_uc_block_qe(uc_block_t* a, uint64_t a_n) { - radix_sort_uc_block_t_qe_srt(a, a + a_n); -} - -void update_ul_vec_t_ug(const ul_idx_t *uref, ul_vec_t *rch, vec_mg_lchain_t *uc, int64_t ulid) -{ - int64_t k, ucn = uc->n, a_n, m, l, lk; ma_ug_t *ug = uref->ug; mg_lchain_t *ix, *a; uc_block_t *z; - for (k = 0, a_n = 0; k < ucn; k += ix->cnt + 1) { - ix = &(uc->a[k]); assert(ix->v == (uint32_t)-1); ix->hash_pre = (uint32_t)-1; ix->off = -1; - fill_unaligned_alignments(ug, uc->a + k + 1, ix->cnt, k + 1, ulid); a_n += ix->cnt; - } - - ///up to now, given a in swap - ///x->ts and x->te are the coordinates in unitig - ///x->qs and x->qe are the coordinates in UL - ///x->dist_pre is the idx of this chain at rch - // debug_intermediate_chain(uref->ug, uc->a, uc->n, 1, debug_i); - // dd_ul_vec_t(uref, swap->a, swap->n, rch); - rch->bb.n = 0; kv_resize(uc_block_t, rch->bb, (uint64_t)a_n); - for (k = 0; k < ucn; k += ix->cnt + 1) { - ix = &(uc->a[k]); assert(ix->v == (uint32_t)-1); ix->hash_pre = (uint32_t)-1; ix->off = -1; - a = uc->a + k + 1; a_n = ix->cnt; - for (m = 0; m < a_n; m++) { - kv_pushp(uc_block_t, rch->bb, &z); - z->hid = (a[m].v>>1); z->rev = (a[m].v&1); - z->pchain = 1; z->base = 0; z->el = 1; - z->qs = a[m].qs; z->qe = a[m].qe; - z->te = a[m].re; z->ts = a[m].rs; - z->pidx = k + 1 + m; z->pdis = z->aidx = (uint32_t)-1; - // fprintf(stderr, "[M::%s::k->%ld] m->%ld, utg%.6dl(%c), q::[%u, %u), t::[%u, %u)\n", - // __func__, k, m, (int32_t)z->hid+1, "+-"[z->rev], z->qs, z->qe, z->ts, z->te); - } - } - - a_n = rch->bb.n; a = uc->a; - radix_sort_uc_block_t_qe_srt(rch->bb.a, rch->bb.a + rch->bb.n); - for (k = 1, lk = 0, l = m = -1; k <= a_n; k++) { - a[rch->bb.a[k-1].pidx].off = k-1; - if(m < (int64_t)rch->bb.a[k-1].pidx) { - m = rch->bb.a[k-1].pidx; l = k-1; - } - if(k == a_n || rch->bb.a[k].qe != rch->bb.a[lk].qe) { - if(k - lk > 1) { - radix_sort_uc_block_t_qs_srt(rch->bb.a+lk, rch->bb.a+k); - } - lk = k; - } - } - // for (k = 0, l = m = -1; k < a_n; k++) { - // a[rch->bb.a[k].pidx].off = k; - // if(m < (int64_t)rch->bb.a[k].pidx) { - // m = rch->bb.a[k].pidx; l = k; - // } - // } - - for (k = 0; k < a_n; k++) { - if(a[rch->bb.a[k].pidx].hash_pre == (uint32_t)-1) { - rch->bb.a[k].pidx = rch->bb.a[k].pdis = rch->bb.a[k].aidx = (uint32_t)-1; - continue; - } - m = rch->bb.a[k].pidx; - rch->bb.a[k].pidx = a[a[m].hash_pre].off; - rch->bb.a[k].pdis = a[a[m].hash_pre].dist_pre; - rch->bb.a[rch->bb.a[k].pidx].aidx = k; - } - // fprintf(stderr, "+ulid->%ld\n", ulid); - uint32_t sp = (uint32_t)-1, ep = (uint32_t)-1, ch_n = 0; - k = l/**a_n - 1**/;///start from the max chain - for (l = 0; k >= 0; ) { - if(sp == (uint32_t)-1 || rch->bb.a[k].qe <= sp) { - if(sp != (uint32_t)-1) l += ep - sp; - sp = rch->bb.a[k].qs; ep = rch->bb.a[k].qe; - } else { - sp = MIN(sp, rch->bb.a[k].qs); - } - if(rch->bb.a[k].pidx == (uint32_t)-1) k = -1; - else k = rch->bb.a[k].pidx; - ch_n++; - } - - rch->dd = 0; - if(sp != (uint32_t)-1) l += ep - sp; - l = (int64_t)rch->rlen - l; - - // fprintf(stderr, "-ulid:%ld, l:%ld, rch->rlen:%u\n", ulid, l, rch->rlen); - if(l == 0) { - rch->dd = 1; - } else if(l < ((int64_t)rch->rlen)*0.001) { - rch->dd = 2; - } else if(ch_n < rch->bb.n) {///multiple chain, might be useful for the scaffolding - rch->dd = 3; - } - // fprintf(stderr, "[M::%s::] rch->dd::%u, rch->bb.n::%u\n", - // __func__, rch->dd, (uint32_t)rch->bb.n); -} - -void print_raw_chains(vec_mg_lchain_t *uc, int64_t ulid) -{ - if(uc->n <= 0) return; - int64_t k, m, ucn = uc->n, k_cnt, a_n; mg_lchain_t *ix, *a; - for (k = m = 0; k < ucn; k += k_cnt) { - ix = &(uc->a[k]); assert(ix->v == (uint32_t)-1); k_cnt = ix->cnt + 1; - a = uc->a + k + 1; a_n = ix->cnt; - for (m = 0; m < a_n; m++) { - if(a[m].off < 0) break; - } - if(m < a_n) fprintf(stderr, "ulid->%ld\n", ulid); - } -} - -void hc_shortest_k(void *km0, const asg_t *g, uint32_t src, int32_t n_dst, mg_path_dst_t *dst, int32_t max_dist, int32_t max_k, -st_mt_t *dst_done, uint64_t *dst_group, vec_sp_node_t *out, vec_mg_pathv_t *res, uint64_t first_src_ban, -uint64_t detect_mul_way, float len_dif); - -void debug_ul_vec_t_chain(void *km, const asg_t *g, ul_vec_t *rch, st_mt_t *dst_done, vec_sp_node_t *out) -{ - if(rch->dd == 0) return; - uint64_t k, i, v, w, nv; int64_t dd; asg_arc_t *av; - mg_path_dst_t dst; uint64_t dst_group; uc_block_t *a = rch->bb.a; - for (k = 0; k < rch->bb.n; k++) { - if(a[k].pidx != (uint32_t)-1) assert(a[a[k].pidx].aidx == k); - if(a[k].aidx != (uint32_t)-1) assert(a[a[k].aidx].pidx == k); - if(a[k].pidx == (uint32_t)-1) continue; - - v = (a[k].hid<<1)|a[k].rev; v ^= 1; - w = (a[a[k].pidx].hid<<1)|a[a[k].pidx].rev; w ^= 1; - - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (i = 0; i < nv; i++) { - if(av[i].v == w) break; - } - // if(i >= nv) { - // // fprintf(stderr, "[M::%s::]\n", __func__); - // fprintf(stderr, "[M::%s::]\tutg%.6dl(%c)\t->\tutg%.6dl(%c)\n", __func__, (int32_t)(v>>1)+1, "+-"[v&1], (int32_t)(w>>1)+1, "+-"[w&1]); - // } - if(i < nv) { - dd = (int64_t)((uint32_t)(av[i].ul)); - } else { - memset(&dst, 0, sizeof(dst)); - dst.v = w; - dst.target_dist = a[k].pdis; - dst.target_hash = 0; dst.check_hash = 0; - hc_shortest_k(km, g, v, 1, &dst, dst.target_dist, MG_MAX_SHORT_K, dst_done, &dst_group, out, NULL, 1, 0, 0); - dd = dst.dist; - } - if(a[k].pdis != dd) { - fprintf(stderr, "[M::%s::]\tutg%.6dl(%c)\t->\tutg%.6dl(%c)\tdist_pre:%d\td:%ld\n", __func__, (int32_t)(v>>1)+1, "+-"[v&1], - (int32_t)(w>>1)+1, "+-"[w&1], a[k].pdis, dd); - } - } -} - - -int64_t gl_chain_refine_advance_combine_with_trans(mg_tbuf_t *b, ul_vec_t *rch, overlap_region_alloc* olist, Correct_dumy* dumy, haplotype_evdience_alloc *hap, st_mt_t *sps, glchain_t *ll, gdpchain_t *gdp, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, int64_t qlen, const ug_opt_t *uopt, -int64_t debug_i, int64_t tid, void *km) -{ - ll->tk.n = ll->lo.n = 0; - kv_ul_ov_t *idx = &(ll->lo); - uint64_t o2 = gl_chain_gen(olist, uref, idx, 0, hap, km); - if(idx->n == 0) return 0; - // fprintf(stderr, "(beg0) [M::%s::tid:%ld] debug_i:%ld, qlen:%ld, # cis:%lu, # trans:%lu\n", __func__, tid, debug_i, qlen, (uint64_t)idx->n, o2); - int64_t max_idx, occ = 0, f = 0; - - kv_resize_km(km, uint64_t, ll->srt.a, idx->n); - kv_resize_km(km, uint64_t, hap->snp_srt, idx->n); - kv_resize_km(km, ul_ov_t, ll->tk, idx->n); - ///chain exact U-matches - occ = gl_chain_advance(idx, ll->tk.a, uref, uopt, G_CHAIN_BW, /**diff_ec_ul**/N_GCHAIN_RATE, qlen, UG_SKIP, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 0, NULL, uref->ug, debug_i, km); - if(occ) { - if(ff_chain(idx, qlen, 0.99/**P_CHAIN_COV**/, -1/**G_CHAIN_TRANS_RATE**/, ll->tk.a, NULL, NULL, NULL, diff_ec_ul, winLen, km)) { - f = l2g_res_chain(uref->ug, ll->tk.a+idx->a[idx->n-1].ts, idx->a[idx->n-1].te-idx->a[idx->n-1].ts, &(gdp->swap), -1/**N_GCHAIN_RATE**/); - } else if(o2) {///means there are trans overlaps - gl_chain_gen(olist, uref, idx, 1, hap, km); - kv_resize_km(km, uint64_t, ll->srt.a, idx->n); - kv_resize_km(km, uint64_t, hap->snp_srt, idx->n); - kv_resize_km(km, ul_ov_t, ll->tk, idx->n); - ///chain all U-matches - occ = gl_chain_advance(idx, ll->tk.a, uref, uopt, G_CHAIN_BW, /**diff_ec_ul**/N_GCHAIN_RATE, qlen, UG_SKIP, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 0, NULL, uref->ug, debug_i, km); - if(ff_chain(idx, qlen, 0.99/**P_CHAIN_COV**/, G_CHAIN_TRANS_RATE, ll->tk.a, olist, hap, uref, diff_ec_ul, winLen, km)) { - f = l2g_res_chain(uref->ug, ll->tk.a+idx->a[idx->n-1].ts, idx->a[idx->n-1].te-idx->a[idx->n-1].ts, &(gdp->swap), -1/**N_GCHAIN_RATE**/); - } - } - } - // fprintf(stderr, "(beg1) [M::%s] debug_i:%ld, qlen:%ld\n", __func__, debug_i, qlen); - if(!f) { - gl_chain_gen(olist, uref, idx, 1, hap, km); - l2g_chain(uref, idx, &(gdp->l)); ll->tk.n = 0; - ///buffer - kv_resize(uint64_t, ll->srt.a, gdp->l.n); kv_resize(uint64_t, hap->snp_srt, gdp->l.n); - kv_resize(uint64_t, gdp->v, gdp->l.n); kv_resize(int64_t, gdp->f, gdp->l.n); - max_idx = hc_gchain1_dp(b->km, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), &(gdp->path), rch->rlen, - uopt, G_CHAIN_BW, diff_ec_ul, -1, ll->srt.a.a, sps, gdp->f.a, hap->snp_srt.a, gdp->v.a); - if(max_idx >= 0 && gen_max_gchain_adv(b->km, uref, debug_i, sps, &(gdp->l), &(ll->tk), NULL, rch->rlen, P_CHAIN_COV, 0.3/**P_FRAGEMENT_PRIMARY_CHAIN_COV**/, - 0.1/**P_FRAGEMENT_PRIMARY_SECOND_COV**/, PRIMARY_UL_CHAIN_MIN, uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), ll->srt.a.a, &(gdp->swap))) { - // print_raw_chains(&(gdp->swap), debug_i); - f = check_trans_rate_gap(&(gdp->swap), &(ll->tk), olist, hap, uref, diff_ec_ul, winLen, G_CHAIN_TRANS_RATE); - } - } - // if(debug_i == 1756) fprintf(stderr, "[M::%s] ulid:%ld, qlen:%ld, f:%ld\n", __func__, debug_i, qlen, f); - if(f) update_ul_vec_t_ug(uref, rch, &(gdp->swap), debug_i); - // debug_ul_vec_t_chain(km, uref->ug->g, rch, &(gdp->dst_done), &(gdp->out)); - // fprintf(stderr, "(beg3) [M::%s::tid:%ld] debug_i:%ld, qlen:%ld\n", __func__, tid, debug_i, qlen); - return 1; -} - -int64_t gl_chain_refine_advance_combine(mg_tbuf_t *b, ul_vec_t *rch, overlap_region_alloc* olist, Correct_dumy* dumy, haplotype_evdience_alloc *hap, st_mt_t *sps, glchain_t *ll, gdpchain_t *gdp, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, int64_t qlen, const ug_opt_t *uopt, -int64_t debug_i, int64_t tid, void *km) -{ - ll->tk.n = ll->lo.n = 0; - kv_ul_ov_t *idx = &(ll->lo); - gl_chain_gen(olist, uref, idx, 0, hap, km);///no trans - // fprintf(stderr, "0-[M::%s] idx->n::%lu\n", __func__, (uint64_t)idx->n); - if(idx->n == 0) return 0; - // fprintf(stderr, "(beg0) [M::%s::tid:%ld] debug_i:%ld, qlen:%ld, # cis:%lu, # trans:%lu\n", __func__, tid, debug_i, qlen, (uint64_t)idx->n, o2); - int64_t max_idx, occ = 0, f = 0; - - kv_resize_km(km, uint64_t, ll->srt.a, idx->n); - kv_resize_km(km, uint64_t, hap->snp_srt, idx->n); - kv_resize_km(km, ul_ov_t, ll->tk, idx->n); - ///chain exact U-matches - occ = gl_chain_advance(idx, ll->tk.a, uref, uopt, G_CHAIN_BW, /**diff_ec_ul**/N_GCHAIN_RATE, qlen, UG_SKIP, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 0, NULL, uref->ug, debug_i, km); - if(occ) { - if(ff_chain(idx, qlen, 0.99/**P_CHAIN_COV**/, -1/**G_CHAIN_TRANS_RATE**/, ll->tk.a, NULL, NULL, NULL, diff_ec_ul, winLen, km)) { - f = l2g_res_chain(uref->ug, ll->tk.a+idx->a[idx->n-1].ts, idx->a[idx->n-1].te-idx->a[idx->n-1].ts, &(gdp->swap), -1/**N_GCHAIN_RATE**/); - } - } - // fprintf(stderr, "1-[M::%s] f::%ld\n", __func__, f); - // fprintf(stderr, "(beg1) [M::%s] debug_i:%ld, qlen:%ld\n", __func__, debug_i, qlen); - if(!f) { - gl_chain_gen(olist, uref, idx, 0, hap, km);///no trans - l2g_chain(uref, idx, &(gdp->l)); ll->tk.n = 0; - ///buffer - kv_resize(uint64_t, ll->srt.a, gdp->l.n); kv_resize(uint64_t, hap->snp_srt, gdp->l.n); - kv_resize(uint64_t, gdp->v, gdp->l.n); kv_resize(int64_t, gdp->f, gdp->l.n); - max_idx = hc_gchain1_dp(b->km, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), &(gdp->path), rch->rlen, - uopt, G_CHAIN_BW, diff_ec_ul, -1, ll->srt.a.a, sps, gdp->f.a, hap->snp_srt.a, gdp->v.a); - if(max_idx >= 0 && gen_max_gchain_adv(b->km, uref, debug_i, sps, &(gdp->l), &(ll->tk), NULL, rch->rlen, P_CHAIN_COV, 0.3/**P_FRAGEMENT_PRIMARY_CHAIN_COV**/, - 0.1/**P_FRAGEMENT_PRIMARY_SECOND_COV**/, PRIMARY_UL_CHAIN_MIN, uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), ll->srt.a.a, &(gdp->swap))) { - // print_raw_chains(&(gdp->swap), debug_i); - // f = check_trans_rate_gap(&(gdp->swap), &(ll->tk), olist, hap, uref, diff_ec_ul, winLen, G_CHAIN_TRANS_RATE); - f = 1; - } - } - // if(debug_i == 1756) fprintf(stderr, "[M::%s] ulid:%ld, qlen:%ld, f:%ld\n", __func__, debug_i, qlen, f); - if(f) update_ul_vec_t_ug(uref, rch, &(gdp->swap), debug_i); - // debug_ul_vec_t_chain(km, uref->ug->g, rch, &(gdp->dst_done), &(gdp->out)); - // fprintf(stderr, "(beg3) [M::%s::tid:%ld] debug_i:%ld, qlen:%ld\n", __func__, tid, debug_i, qlen); - return 1; -} - -// #define aln_sc(a, w) (((int64_t)((a).sec))-((int64_t)(((a).qe-(a).qs-(a).sec)*(w)))) -#define aln_sc(a, trans_w, err_w) (((int64_t)((a).align_length))-((int64_t)(((a).overlapLen-(a).align_length)*(trans_w)))-(((int64_t)((a).non_homopolymer_errors))*(err_w))) - -void gen_gl_aln(overlap_region_alloc* olist, const ul_idx_t *uref, kv_ul_ov_t *res) -{ - uint64_t k; ul_ov_t *p = NULL; - res->n = 0; kv_resize(ul_ov_t, *res, olist->length); - for (k = 0; k < olist->length; k++) { - // fprintf(stderr, "+++[M::%s::utg%.6dl] q[%d, %d), t[%d, %d), tot::%u, cis::%u, err::%u\n", __func__, - // (int32_t)olist->list[k].y_id+1, olist->list[k].x_pos_s, olist->list[k].x_pos_e+1, - // olist->list[k].y_pos_s, olist->list[k].y_pos_e+1, - // olist->list[k].overlapLen, olist->list[k].align_length, olist->list[k].non_homopolymer_errors); - p = &(res->a[res->n++]); assert(olist->list[k].overlapLen >= olist->list[k].align_length); - p->qn = k; p->qs = olist->list[k].x_pos_s; p->qe = olist->list[k].x_pos_e+1; - p->tn = olist->list[k].y_id; p->sec = olist->list[k].align_length; - p->rev = olist->list[k].y_pos_strand; p->el = (olist->list[k].is_match==1?1:0); - if(p->rev) { - p->ts = uref->ug->u.a[p->tn].len - (olist->list[k].y_pos_e+1); - p->te = uref->ug->u.a[p->tn].len - olist->list[k].y_pos_s; - } else { - p->ts = olist->list[k].y_pos_s; - p->te = olist->list[k].y_pos_e+1; - } - } -} - -void gen_gg_aln(overlap_region_alloc* olist, const ul_idx_t *uref, int64_t trans_sc, vec_mg_lchain_t *res) -{ - uint64_t k; mg_lchain_t *p = NULL; - res->n = 0; kv_resize(mg_lchain_t, *res, olist->length); - for (k = 0; k < olist->length; k++) { - p = &(res->a[res->n++]); memset(p, 0, sizeof((*p))); - p->v = ((olist->list[k].y_id<<1)|(olist->list[k].y_pos_strand)); p->off = k; - p->score = aln_sc((olist->list[k]), (trans_sc), UG_TRANS_ERR_W); - p->qs = olist->list[k].x_pos_s; p->qe = olist->list[k].x_pos_e+1; - if((p->v&1)) { - p->rs = uref->ug->u.a[p->v>>1].len - (olist->list[k].y_pos_e+1); - p->re = uref->ug->u.a[p->v>>1].len - olist->list[k].y_pos_s; - } else { - p->rs = olist->list[k].y_pos_s; - p->re = olist->list[k].y_pos_e+1; - } - } -} - -int64_t get_overlap_region_sub_err_debug(overlap_region *o, int64_t qs, int64_t *sec_err) -{ - (*sec_err) = 0; - if(o->w_list.n <= 0) return 0; - int64_t k; double rr; int64_t terr, dd; - for (k = o->w_list.n-1, terr = 0; k >= 0 && qs < o->w_list.a[k].x_end; k--) { - if(qs >= o->w_list.a[k].x_start && qs < o->w_list.a[k].x_end) { - // if(qs == 102178) { - // fprintf(stderr, "[M::%s::qs->%ld] k::%ld, wn::%u, x::[%d, %d), clen::%u, terr::%ld, sec_err::%ld\n", - // __func__, qs, k, (uint32_t)o->w_list.n, o->w_list.a[k].x_start, o->w_list.a[k].x_end, - // o->w_list.a[k].clen, terr, (*sec_err)); - // } - if(o->w_list.a[k].clen > 0) { - rr = ((double)(o->w_list.a[k].x_end-qs))/ - ((double)(o->w_list.a[k].x_end-o->w_list.a[k].x_start)); - dd = o->w_list.a[k].clen*rr; - (*sec_err) += (dd>0?dd:1); - } - - terr += ((o->w_list.a[k].clen > 0)?(o->w_list.a[k].x_end-qs):(0)); - return terr; - } - if(o->w_list.a[k].clen > 0) { - (*sec_err) += o->w_list.a[k].clen; - terr += o->w_list.a[k].x_end-o->w_list.a[k].x_start; - } - } - return terr; -} - -int64_t get_overlap_region_sub_err(overlap_region *o, rtrace_iter *it, int64_t qs, int64_t *sec_err) -{ - if(o->w_list.n <= 0) { - (*sec_err) = 0; - return 0; - } - if(it->k == INT32_MAX) { - it->k = o->w_list.n-1; - it->cur_qoff = o->x_pos_e+1; - it->qoff = o->w_list.a[it->k].x_end; - it->werr = 0; it->werr0 = 0; - } - assert(qs <= it->cur_qoff); - it->cur_qoff = qs; (*sec_err) = it->werr0; - - if(qs == it->qoff) { - (*sec_err) = it->werr0; - return it->werr; - } - double rr; int64_t terr; - for (; (it->k >= 0) && (qs < o->w_list.a[it->k].x_end); it->k--) { - if(qs >= o->w_list.a[it->k].x_start && qs < o->w_list.a[it->k].x_end) { - (*sec_err) = 0; - if(o->w_list.a[it->k].clen > 0) { - rr = ((double)(o->w_list.a[it->k].x_end-qs))/ - ((double)(o->w_list.a[it->k].x_end-o->w_list.a[it->k].x_start)); - (*sec_err) = rr*o->w_list.a[it->k].clen; - // if((*sec_err) == 0) (*sec_err) = 1; - } - (*sec_err) += it->werr0; - - terr = ((o->w_list.a[it->k].clen > 0)?(o->w_list.a[it->k].x_end-qs):(0)); - return it->werr + terr; - } - if(o->w_list.a[it->k].clen > 0) { - it->werr += o->w_list.a[it->k].x_end-o->w_list.a[it->k].x_start; - it->werr0 += o->w_list.a[it->k].clen; - } - it->qoff = o->w_list.a[it->k].x_start; - } - - (*sec_err) = it->werr0; - return it->werr; -} - - -int64_t get_ecov_el(const ul_idx_t *uref, const ug_opt_t *uopt, uint32_t v, uint32_t w, int64_t bw, double diff_ec_ul, int64_t dq, uint64_t mode, int64_t *el) -{ - int64_t dt = -1, dif, mm; (*el) = 0; - uint32_t nv, i; asg_arc_t *av = NULL; ///ma_hit_t *x = NULL; - if(!mode) { - const asg_t *g = uref?uref->ug->g:NULL; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (i = 0; i < nv; i++) { - if(av[i].del || av[i].v != w) continue; - dt = av[i].ol; (*el) = av[i].el; - // if(v==1772 && w==1769) fprintf(stderr, "+++v:%u, w:%u, ou:%u\n", v, w, av[i].ou); - // if((v>>1) == 3012 && (w>>1) == 3011) fprintf(stderr, "******************\n"); - break; - } - }else { - ma_hit_t_alloc* src = uopt->sources; - int64_t min_ovlp = uopt->min_ovlp; - int64_t max_hang = uopt->max_hang; - uint64_t z, qn, tn, x = v>>1; int32_t r = 1; asg_arc_t e; - for (z = 0; z < src[x].length; z++) { - qn = Get_qn(src[x].buffer[z]); tn = Get_tn(src[x].buffer[z]); - if(tn != (w>>1)) continue; - r = ma_hit2arc(&(src[x].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); - if(r < 0) continue; - if((e.ul>>32) != v || e.v != w) continue; - dt = e.ol; (*el) = src[x].buffer[z].el; - break; - } - } - if(dt < 0) return 0; - dif = (dq>dt? dq-dt:dt-dq); - mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; - // if((v>>1) == 1163 && (w>>1) == 1168) fprintf(stderr, ">>>>>>dis_q:%ld, dis_t:%ld, dif:%ld, mm:%ld\n", dis_q, dis_t, dif, mm); - if(dif <= mm) return 1; - return 0; -} - -//ai > aj -int64_t cal_gl_chain_lin_sc(ul_ov_t *a, int32_t ai, int32_t aj, rtrace_iter *tc, overlap_region *ol, All_reads *ridx, ma_ug_t *ug, -const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, uint64_t mode, int64_t trans_sc, int64_t sec_sec, -int32_t *f, int64_t debug_i) -{ - ul_ov_t *li = &(a[ai]), *lj = &(a[aj]); - ///li is the suffix of lj - if(lj->qs >= li->qs) return INT32_MIN; - uint32_t li_v = (li->tn<<1)|li->rev, lj_v = (lj->tn<<1)|lj->rev; - int64_t qo = infer_rovlp(li, lj, NULL, NULL, ridx, ug), trans_l = 0, sec_err = 0, sc, sc0, el; ///overlap length in query (UL read) - ///li_v == lj_v is possiable - if(get_ecov_el(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, mode, &el)) { - trans_l = get_overlap_region_sub_err(&(ol[li->qn]), tc, lj->qe, &sec_err); - sc = f[aj] + ((int64_t)(li->qe - lj->qe)) - (trans_l*trans_sc) - (sec_err*sec_sec); - - // char *as = NULL; - // asprintf(&as, "+[M::utg%.6dl] utg%.6dl, liq::[%u, %u), ljq::[%u, %u), trans_l::%ld, sec_err::%ld, sc::%ld, f[aj]::%d\n", - // (int32_t)li->tn+1, (int32_t)lj->tn+1, li->qs, li->qe, lj->qs, lj->qe, trans_l, sec_err, sc, f[aj]); - // push_vlog(&(overall_zdbg->a[debug_i]), as); free(as); as = NULL; - // fprintf(stderr, "+[M::utg%.6dl] utg%.6dl, liq::[%u, %u), ljq::[%u, %u), trans_l::%ld, sec_err::%ld, sc::%ld, f[aj]::%d\n", - // (int32_t)li->tn+1, (int32_t)lj->tn+1, li->qs, li->qe, lj->qs, lj->qe, trans_l, sec_err, sc, f[aj]); - if((el == 0) && ((trans_l > 0) || (sec_err > 0)) && (lj->qe > li->qs)) { - rtrace_iter tr; tr.k = INT32_MAX; sc0 = sc; - sc = f[aj] + aln_sc(ol[(*li).qn], trans_sc, sec_sec); - trans_l = get_overlap_region_sub_err(&(ol[lj->qn]), &tr, li->qs, &sec_err); - sc -= (((int64_t)(lj->qe - li->qs)) - (trans_l*trans_sc) - (sec_err*sec_sec)); - - - // char *as = NULL; - // asprintf(&as, "-[M::utg%.6dl] utg%.6dl, liq::[%u, %u), ljq::[%u, %u), trans_l::%ld, sec_err::%ld, sc::%ld, f[aj]::%d\n", - // (int32_t)li->tn+1, (int32_t)lj->tn+1, li->qs, li->qe, lj->qs, lj->qe, trans_l, sec_err, sc, f[aj]); - // push_vlog(&(overall_zdbg->a[debug_i]), as); free(as); as = NULL; - - if(sc < sc0) sc = sc0; - // fprintf(stderr, "-[M::utg%.6dl] utg%.6dl, liq::[%u, %u), ljq::[%u, %u), trans_l::%ld, sec_err::%ld, sc::%ld, f[aj]::%d, aln_sc::%ld\n", - // (int32_t)li->tn+1, (int32_t)lj->tn+1, li->qs, li->qe, lj->qs, lj->qe, trans_l, sec_err, sc, f[aj], aln_sc(ol[(*li).qn], trans_sc, sec_sec)); - } - // int64_t trans_l_debug, sec_err_debug; - // trans_l_debug = get_overlap_region_sub_err_debug(&(ol[li->qn]), lj->qe, &sec_err_debug); - // if(!(trans_l_debug == trans_l && sec_err_debug == sec_err)) { - // fprintf(stderr, "[M::%s::qs->%u] trans_l::%ld, trans_l_debug::%ld, sec_err::%ld, sec_err_debug::%ld\n", - // __func__, lj->qe, trans_l, trans_l_debug, sec_err, sec_err_debug); - // } - // assert(trans_l_debug == trans_l && sec_err_debug == sec_err); - // if(li->tn == 308 || li->tn == 311 || lj->tn == 305 || lj->tn == 304) { - // fprintf(stderr, "[M::%s::utg%.6dl] utg%.6dl, liq::[%u, %u), ljq::[%u, %u), trans_l::%ld, sec_err::%ld, sc::%ld\n", __func__, - // (int32_t)li->tn+1, (int32_t)lj->tn+1, li->qs, li->qe, lj->qs, lj->qe, trans_l, sec_err, sc); - // } - return sc; - } - return INT32_MIN; -} - -int64_t gl_chain_lin(kv_ul_ov_t *res, overlap_region *ol, ul_ov_t *ex, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, int64_t trans_sc, -uint64_t mode, All_reads *ridx, ma_ug_t *ug, int64_t need_srt, int64_t debug_i) -{ - if(res->n == 0) return 0; - uint32_t rev_n; int32_t *f, *c_n, *c_sc; int64_t *p, *t, res_n = res->n, st, max_ii, max; rtrace_iter tc; - int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, n_skip, end_j, plus; ul_ov_t *li, *lj, rev_t; - resize_Chain_Data(dp, res_n, NULL); memset(&tc, 0, sizeof(tc)); - t = dp->tmp; f = dp->score; p = dp->pre; c_n = dp->occ; c_sc = dp->self_length; - if(need_srt) { - radix_sort_ul_ov_srt_qe(res->a, res->a + res_n); - for (i = 1, j = 0; i <= res_n; i++) { - if (i == res_n || res->a[i].qe != res->a[j].qe) { - if(i - j > 1) { - radix_sort_ul_ov_srt_qs(res->a+j, res->a+i); - } - j = i; - } - } - } - - memset(t, 0, (res_n*sizeof((*t)))); - for (i = st = plus = 0, max_ii = -1; i < res_n; ++i) { - li = &(res->a[i]); - mm_ovlp = mode?max_ovlp_src(uopt, ((li->tn<<1)|li->rev)^1):max_ovlp(uref->ug->g, ((li->tn<<1)|li->rev)^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(i, res->a, x+G_CHAIN_INDEL); - csc = aln_sc(ol[(*li).qn], trans_sc, UG_TRANS_ERR_W); - // fprintf(stderr, "[M::%s::utg%.6dl] i::%ld, csc::%ld, q::[%u, %u), aln::%u, ol::%u, sec_e::%u\n", - // __func__, (int32_t)li->tn+1, i, csc, li->qs, li->qe, - // (ol[(*li).qn]).align_length, (ol[(*li).qn]).overlapLen, - // (ol[(*li).qn]).non_homopolymer_errors); - mm_sc = csc; mm_idx = -1; - n_skip = 0; end_j = -1; tc.k = INT32_MAX; - if ((x-st) > max_iter) st = x-max_iter; - for (j = x; j >= st; --j) { // collect potential destination vertices - lj = &(res->a[j]); - if(lj->qe+G_CHAIN_INDEL <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore - sc = cal_gl_chain_lin_sc(res->a, i, j, &tc, ol, ridx, ug, uref, uopt, bw, diff_ec_ul, mode, trans_sc, UG_TRANS_ERR_W, f, debug_i); - // char *as = NULL; - // asprintf(&as, "-3-[M::%s::] i::%ld(utg%.6dl), j::%ld(utg%.6dl), sc::%ld\n", - // __func__, i, (int32_t)li->tn+1, j, (int32_t)lj->tn+1, sc); - // push_vlog(&(overall_zdbg->a[debug_i]), as); free(as); as = NULL; - - if(sc == INT32_MIN) continue; - if(sc > mm_sc) { - mm_sc = sc, mm_idx = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - - end_j = j; - if (max_ii < 0 || (res->a[i].qe>(res->a[max_ii].qe+max_dis))) {//too long - max = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && (res->a[i].qe<=(max_dis+res->a[j].qe)); --j) { - if (max < f[j]) { - max = f[j], max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - lj = &(res->a[max_ii]); - if(lj->qe+G_CHAIN_INDEL > li->qs && lj->qs < li->qs) { - sc = cal_gl_chain_lin_sc(res->a, i, max_ii, &tc, ol, ridx, ug, uref, uopt, bw, diff_ec_ul, mode, trans_sc, UG_TRANS_ERR_W, f, debug_i); - if(sc != INT32_MIN) { - if(sc > mm_sc) { - mm_sc = sc; mm_idx = max_ii; - } - } - } - } - if(mm_sc < 0) { - mm_sc = csc; mm_idx = -1; - } - f[i] = mm_sc; p[i] = mm_idx; - if ((max_ii < 0) || ((res->a[i].qe<=max_dis+res->a[max_ii].qe) && (f[max_ii]tn+1, i, res_n, csc, f[i], p[i], li->qs, li->qe); - // char *as = NULL; - // asprintf(&as, "-5-[M::%s::utg%.6dl] i::%ld, csc::%ld, f[i]::%d, p[i]::%ld, q::[%u, %u)\n", __func__, (int32_t)li->tn+1, i, csc, f[i], p[i], li->qs, li->qe); - // push_vlog(&(overall_zdbg->a[debug_i]), as); free(as); as = NULL; - } - for (i = 0; i < res_n; ++i) {///make all f[] positive - f[i] -= plus; t[i] = ((uint64_t)f[i])<<32; t[i] += (i<<1); - } - - int64_t n_v, n_u, n_v0; - radix_sort_gfa64i(t, t + res_n); plus = 0; - for (k = res_n-1, n_v = n_u = 0; k >= 0; --k) { - n_v0 = n_v; - for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { - ex[n_v++] = res->a[i]; t[i] |= 1; i = p[i]; - } - if(n_v0 == n_v) continue; - sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); - // fprintf(stderr, "[M::%s::] n_v::%ld, n_v0::%ld, t[k]::%ld, sc::%ld\n", - // __func__, n_v, n_v0, t[k]>>32, sc); - c_n[n_u] = n_v-n_v0; c_sc[n_u] = sc; n_u++; if(sc < plus) plus = sc; - } - // fprintf(stderr, "---[M::%s] n_u:%ld, n_v:%ld\n", __func__, n_u, n_v); - for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { - n_v0 = n_v; n_v += c_n[k]; - res->a[k].qn = c_sc[k]-plus;//score - res->a[k].ts = n_v0; res->a[k].te = n_v;///idx - // fprintf(stderr, "[M::%s] k:%ld, c_sc:%d\n", __func__, k, c_sc[k]); - - rev_n = c_n[k]>>1; - ///we need to consider contained reads; so determining qs is not such easy - res->a[k].qs = (uint32_t)-1; res->a[k].qe = ex[n_v0].qe; - for (i = 0; i < rev_n; i++) { - rev_t = ex[n_v0+i]; ex[n_v0+i] = ex[n_v-i-1]; ex[n_v-i-1] = rev_t; - - if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; - if(res->a[k].qs > ex[n_v-i-1].qs) res->a[k].qs = ex[n_v-i-1].qs; - ex[n_v0+i].sec = ex[n_v-i-1].sec = SEC_MODE; - } - if(c_n[k]&1) { - if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; - ex[n_v0+i].sec = SEC_MODE; - } - } - res->n = n_u; - radix_sort_ul_ov_srt_qn(res->a, res->a + res->n);//sort by score - return n_v; -} - -void set_ul_ov_t_by_mg_lchain_t(ul_ov_t *u, mg_lchain_t *l) -{ - u->tn = l->v>>1; u->rev = (l->v&1); - u->ts = l->rs; u->te = l->re; - u->qs = l->qs; u->qe = l->qe; -} - -int64_t find_mg_lchain_max(int64_t n, const mg_lchain_t *a, int32_t x) -{ - int64_t s = 0, e = n; - if (n == 0) return -1; - if (a[n-1].qe < x) return n - 1; - if (a[0].qe >= x) return -1; - while (e > s) { // TODO: finish this block - int64_t m = s + (e - s) / 2; - if (a[m].qe >= x) e = m; - else s = m + 1; - } - assert(s == e); - return s; -} - - -int64_t hc_target_len(asg_t *g, mg_lchain_t *s, mg_lchain_t *e) -{ - // int64_t ql = s->qe - e->qe, tp, tm; - // if((s->v^1)&1) tp = g->seq[s->v>>1].len - s->re; - // else tp = s->rs; - - // if((e->v^1)&1) tm = g->seq[e->v>>1].len - e->re; - // else tm = e->rs; - int64_t ql = (int64_t)s->qs - (int64_t)e->qe, tp, tm; - int64_t sts, ete; - sts = (s->v&1)?g->seq[s->v>>1].len-s->re:s->rs; tp = g->seq[s->v>>1].len - sts; - ete = (e->v&1)?g->seq[e->v>>1].len-e->rs:e->re; tm = g->seq[e->v>>1].len - ete; - // fprintf(stderr, "[M::%s::] ql:%ld, tp:%ld, tm:%ld, sts:%ld, ete:%ld\n", __func__, ql, tp, tm, sts, ete); - return ql + tp - tm; -} - -inline int32_t cal_gchain_sc(const mg_path_dst_t *dj, const mg_lchain_t *li, const mg_lchain_t *lc, int64_t *f, int64_t b_w, float diff_thre, float chn_pen_gap) -{ - // const mg_lchain_t *lj; - int32_t gap, sc; - float lin_pen, log_pen; - if (dj->n_path == 0) return INT32_MIN; - gap = dj->dist - dj->target_dist; - // lj = &lc[dj->meta]; - if (gap < 0) gap = -gap; - if ((gap > ((dj->target_dist)*diff_thre)) && (gap > b_w)) return INT32_MIN; - // if (lj->qe <= li->qs) sc = li->score; - // else sc = (int32_t)((double)(li->qe - lj->qe) / (li->qe - li->qs) * li->score + .499); // dealing with overlap on query - sc = li->score; - //sc += dj->mlen; // TODO: is this line the right thing to do? - // if (dj->is_0) sc += ref_bonus; - lin_pen = chn_pen_gap * (float)gap; - log_pen = gap >= 2? mg_log2(gap) : 0.0f; - sc -= (int32_t)(lin_pen + log_pen); - sc += f[dj->meta]; - return sc; -} - -uint64_t primary_chain_check(uint64_t *idx, int64_t idx_n, mg_lchain_t *a) -{ - if(idx_n <= 0) return 0; - ul_ov_t m; memset(&m, 0, sizeof(m)); int64_t m_sc = -1, i, a_n; uint64_t s_idx, e_idx, ovlp, novlp; - for (i = a_n = 0; i < idx_n; ++i) { - if(((int64_t)(idx[i]>>32)) > m_sc) { - m_sc = ((int64_t)(idx[i]>>32)); m.qn = i; - m.ts = a_n; m.te = a_n + ((uint32_t)idx[i]); - m.qs = a[m.ts].qs; m.qe = a[m.te-1].qe; - } - a_n += ((uint32_t)idx[i]); - } - assert(a[m.ts].qs<=a[m.te-1].qs && a[m.te-1].qe>=a[m.ts].qe); - - for (i = a_n = 0; i < idx_n; ++i) { - s_idx = a[a_n].qs; a_n += ((uint32_t)idx[i]); e_idx = a[a_n-1].qe; - if(i == m.qn) continue; - ovlp = ((MIN(m.qe, e_idx) > MAX(m.qs, s_idx))? (MIN(m.qe, e_idx) - MAX(m.qs, s_idx)):0); - novlp = (e_idx - s_idx) - ovlp; - if(novlp > ((m.qe-m.qs)*GC_OFFSET_RATE) && novlp > GC_OFFSET_POS) break; - } - if(i >= idx_n) return 1; - return 0; -} - -int64_t gl_chain_linear(const ul_idx_t *uref, const ma_ug_t *ug, vec_mg_lchain_t *lc, -vec_mg_lchain_t *sw, int64_t qlen, const ug_opt_t *uopt, int64_t bw, double ng_diff_thre, -st_mt_t *bf, int64_t max_skip, int64_t max_iter, int64_t max_dis, int32_t *p, int64_t *f, -int64_t *t, int64_t n_ext, uint64_t id) -{ - int64_t i, j, lc_n = lc->n, mm_ovlp, x, m_idx, m_sc, qo, n_skip, k, k0, n_u, n_v, ni; - int64_t max_f, st, max_ii, sc, csc, mm_sc, mm_idx, end_j, max, n_v0; - mg_lchain_t *li, *lj; asg_t *g = ug->g; uint64_t *u, ff; ul_ov_t ui, uj; - - memset(t, 0, (n_ext*sizeof((*t)))); - for (i = st = 0, max_ii = -1; i < n_ext; ++i) { // core loop - li = &lc->a[i]; set_ul_ov_t_by_mg_lchain_t(&ui, li); - mm_ovlp = max_ovlp(g, li->v^1); - x = (li->qs + mm_ovlp)*ng_diff_thre; if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_mg_lchain_max(i, lc->a, x+G_CHAIN_INDEL); - csc = li->score; - mm_sc = csc; mm_idx = -1; - n_skip = 0; end_j = -1; - if ((x-st) > max_iter) st = x-max_iter; - // if(id == 123/** || id == 192**/) { - // fprintf(stderr, "[M::id->%lu::i->%ld::utg%.6d%c] q::[%u, %u); t::[%u, %u); st->%ld; x->%ld\n", id, i, (li->v>>1)+1, "lc"[ug->u.a[li->v>>1].circ], li->qs, li->qe, li->rs, li->re, st, x); - // } - for (j = x; j >= st; --j) { // collect potential destination vertices - lj = &lc->a[j]; - if(lj->qe+G_CHAIN_INDEL <= li->qs) break; - if(lj->qs >= li->qs) continue; - set_ul_ov_t_by_mg_lchain_t(&uj, lj); - qo = infer_rovlp(&ui, &uj, NULL, NULL, NULL, (ma_ug_t *)ug); ///overlap length in query (UL read) - // if(id == 123/** || id == 192**/) { - // fprintf(stderr, "[M::id->%lu::j->%ld] qo->%ld\n", id, j, qo); - // } - if(/**li->v!=lj->v &&**/get_ecov_adv(uref, uopt, li->v^1, lj->v^1, bw, ng_diff_thre, qo, 0, NULL)) { - sc = csc + f[j]; - if(sc > mm_sc) { - mm_sc = sc, mm_idx = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - } - - end_j = j; - if (max_ii < 0 || (lc->a[i].qe>(lc->a[max_ii].qe+max_dis))) {//too long - max = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && (lc->a[i].qe<=(max_dis+lc->a[j].qe)); --j) { - if (max < f[j]) { - max = f[j], max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - lj = &(lc->a[max_ii]); - if(lj->qe+G_CHAIN_INDEL > li->qs && lj->qs < li->qs) { - set_ul_ov_t_by_mg_lchain_t(&uj, lj); - qo = infer_rovlp(&ui, &uj, NULL, NULL, NULL, (ma_ug_t *)ug);///overlap length in query (UL read) - if(/**li->v!=lj->v &&**/get_ecov_adv(uref, uopt, li->v^1, lj->v^1, bw, ng_diff_thre, qo, 0, NULL)) { - sc = csc + f[max_ii]; - if(sc > mm_sc) { - mm_sc = sc; mm_idx = max_ii; - } - } - } - } - - f[i] = mm_sc; p[i] = mm_idx; - if ((max_ii < 0) || ((lc->a[i].qe<=max_dis+lc->a[max_ii].qe) && (f[max_ii]dist_pre = mm_idx<0?-1:g_adjacent_dis(g, li->v^1, lc->a[mm_idx].v^1); li->inner_pre = 0; - li->hash_pre = mm_idx<0?0:(__ac_Wang_hash((li->v^1))+__ac_Wang_hash((lc->a[mm_idx].v^1))); - } - - for (; i < lc_n; i++) { - li = &lc->a[i]; - max_f = li->score; f[i] = max_f; p[i] = -1; - ///same time for gchain - li->dist_pre = -1; - li->hash_pre = 0; - li->inner_pre = 0; - } - - for (i = 0; i < lc_n; ++i) {///all sc are positive - t[i] = f[i]<<32; t[i] += (i<<1); - } - - sw->n = 0; kv_resize(mg_lchain_t, *sw, (uint64_t)lc_n); - kv_resize(uint64_t, *bf, (uint64_t)lc_n); u = bf->a; - n_u = n_v = 0; radix_sort_gfa64i(t, t + lc_n); - for (k = lc_n-1, n_v = n_u = 0; k >= 0; --k) { - n_v0 = n_v; - for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { - sw->a[n_v++] = lc->a[i]; t[i] |= 1; i = p[i]; - } - if(n_v0 == n_v) continue; - sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); - if(sc >= 0) { - ff = ((uint64_t)(0x8000000000000000)); - } else { - ff = 0; sc = -sc; - } - u[n_u++] = (((uint64_t)sc)<<32)|((uint64_t)(n_v-n_v0))|ff; - } - - m_idx = m_sc = -1; - for (i = 0, k = 0; i < n_u; ++i) { - if((u[i]&((uint64_t)(0x8000000000000000)))) { - u[i] -= ((uint64_t)(0x8000000000000000)); sc = u[i]>>32; - } else { - sc = u[i]>>32; sc = -sc; - } - u[i] <<= 32; u[i] >>= 32; u[i] |= (((uint64_t)sc)<<32); - - k0 = k, ni = (uint32_t)u[i]; - for (j = 0; j < ni; ++j) { - lc->a[k++] = sw->a[k0 + (ni - j - 1)]; - } - if(m_idx < 0 || m_sc < ((int64_t)(u[i]>>32))) { - m_idx = i; m_sc = ((int64_t)(u[i]>>32)); - } - } - assert(k == n_v); bf->n = n_u; - return m_idx; -} - -int64_t gl_chain_graph(void *km, const ul_idx_t *uref, const ma_ug_t *ug, vec_mg_lchain_t *lc, -vec_mg_lchain_t *sw, vec_mg_path_dst_t *dst, vec_sp_node_t *out, vec_mg_pathv_t *path, -int64_t qlen, const ug_opt_t *uopt, int64_t bw, double diff_thre, double ng_diff_thre, uint64_t *srt, -st_mt_t *bf, Chain_Data* dp, int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t need_srt) -{ - bf->n = 0; - if(lc->n == 0) return 0; - int64_t i, j, lc_n = lc->n, n_ext, mm_ovlp, target_dist, max_target_dist, x, m_idx, m_sc, qo, sc; - int64_t max_f, max_j = -1, max_d = -1, max_inner = 0; uint32_t max_hash = 0; int64_t k, k0, n_u, n_v, ni; - mg_lchain_t *r, *li, *lj; mg_path_dst_t *q; asg_t *g = ug->g; uint64_t isolated, *u, ff; ul_ov_t ui, uj; - if(!need_srt) { - for (i = n_ext = 0; i < lc_n; i++) { - r = &lc->a[i]; r->dist_pre = -1; isolated = 0;///dist_pre -> parent in graph chain - if((r->re < g->seq[r->v>>1].len) && (r->rs > 0)) isolated = 1;///UL contained in one vertice - if (!isolated) { - srt[n_ext] = r->qe; srt[n_ext] <<= 32; - srt[n_ext] |= (uint64_t)i; srt[n_ext] |= (isolated<<63); - ++n_ext; - } - } - j = n_ext; - if(j < lc_n) { - for (i = 0; i < lc_n; i++) { - r = &lc->a[i]; r->dist_pre = -1; isolated = 0;///dist_pre -> parent in graph chain - if((r->re < g->seq[r->v>>1].len) && (r->rs > 0)) isolated = 1;///UL contained in one vertice - if (isolated) { - srt[j] = r->qe; srt[j] <<= 32; srt[j] |= (uint64_t)i; srt[j] |= (isolated<<63); ++j; - } - } - } - assert(j == lc_n); - } else { - for (i = n_ext = 0; i < lc_n; i++) { - r = &lc->a[i]; r->dist_pre = -1; isolated = 0;///dist_pre -> parent in graph chain - if((r->re < g->seq[r->v>>1].len) && (r->rs > 0)) isolated = 1;///UL contained in one vertice - if (!isolated) ++n_ext; - srt[i] = r->qe; srt[i] <<= 32; srt[i] |= (uint64_t)i; srt[i] |= (isolated<<63); - } - radix_sort_gfa64(srt, srt+lc_n); - for (i = 1, j = 0; i <= lc_n; i++) { - if (i == lc_n || (srt[i]>>32) != (srt[j]>>32)) { - if(i - j > 1) { - for (x = j; x < i; x++) { - srt[x] <<= 32; srt[x] >>= 32; srt[x] |= ((uint64_t)lc->a[(uint32_t)srt[x]].qs)<<32; - } - radix_sort_gfa64(srt+j, srt+i); - } - j = i; - } - } - } - if((n_ext != lc_n) || (need_srt)) { - kv_resize(mg_lchain_t, *sw, (uint64_t)lc_n); sw->n = lc_n; - for (i = 0; i < lc_n; i++) sw->a[i] = lc->a[(uint32_t)srt[i]]; - memcpy(lc->a, sw->a, lc_n *sizeof((*(lc->a)))); - } - - resize_Chain_Data(dp, lc_n, NULL); - int32_t *p; int64_t *f, *t, n_skip, dst_n, is_f, plus, n_v0; mg_path_dst_t *dj; - t = dp->tmp; p = dp->score; f = dp->pre; - if(ng_diff_thre >= 0) { - m_idx = gl_chain_linear(uref, ug, lc, sw, qlen, uopt, bw, ng_diff_thre, bf, - max_skip, max_iter, max_dis, p, f, t, n_ext, -1); - if(diff_thre < 0) return m_idx; - if(m_idx >= 0 && primary_chain_check(bf->a, bf->n, lc->a)) return m_idx; - else m_idx = -1; - // if(m_idx >= 0) return m_idx; - bf->n = 0; - } - - memset(t, 0, (n_ext*sizeof((*t)))); - for (i = plus = 0; i < n_ext; ++i) { // core loop - li = &lc->a[i]; set_ul_ov_t_by_mg_lchain_t(&ui, li); - mm_ovlp = max_ovlp(g, li->v^1); - x = (li->qs + mm_ovlp)*diff_thre; if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_mg_lchain_max(i, lc->a, x+G_CHAIN_INDEL); - - n_skip = 0; is_f = 0; - // collect potential destination vertices - for (dst->n = 0, max_target_dist = -1, j = x; j >= 0; --j) { - lj = &lc->a[j]; ///extend_end_coord(lj, qlen, g->seq[lj->v>>1].len, &jqs, &jqe, &jrs, &jre); - //lj contained in li; actually in circle, this might happen; need to deal with it later - if(lj->qs >= li->qs/**+G_CHAIN_INDEL**/) continue; - ///if there is a circle, the two linear chains might be at the same vertice - target_dist = hc_target_len(g, li, lj); - if(target_dist < 0) continue; - kv_pushp(mg_path_dst_t, *dst, &q); - memset(q, 0, sizeof(*q)); - q->inner = 0;//we set q->inner = 0 to allow circles - q->v = lj->v^1;///must be v^1 instead of v - q->meta = j; - ///lj->qs************lj->qe - /// li->qs************li->qe - q->qlen = li->qs - lj->qe;///might be negative; this is the region that need to be checked in base-level - q->target_dist = target_dist;///cannot understand the target_dist - q->target_hash = 0; - q->check_hash = 0; - if(max_target_dist < target_dist) max_target_dist = target_dist; - if (t[j] == i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - if((!is_f) && (lj->qe+G_CHAIN_INDEL > li->qs)) { - set_ul_ov_t_by_mg_lchain_t(&uj, lj); - qo = infer_rovlp(&ui, &uj, NULL, NULL, NULL, (ma_ug_t *)ug); - if(/**li->v!=lj->v &&**/ get_ecov_adv(uref, uopt, li->v^1, lj->v^1, bw, N_GCHAIN_RATE, qo, 0, NULL)) { - is_f = 1; if(n_skip > 0) n_skip--; - if(n_skip < (max_skip>>1)) n_skip= (max_skip>>1); - } - } - } - - // confirm reach-ability - max_f = li->score, max_j = -1, max_d = -1, max_inner = 0; max_hash = 0; - if(dst->n) { - max_target_dist *= (1+diff_thre); if(max_target_dist < bw) max_target_dist = bw; - hc_shortest_k(km, g, li->v^1, dst->n, dst->a, max_target_dist, MG_MAX_SHORT_K, bf, srt, out, NULL, 1, 0, 0); - // remove unreachable destinations - //TODO: check sequence identity - dst_n = dst->n; - for (j = 0; j < dst_n; ++j) { - dj = &dst->a[j]; - if (dj->n_path == 0) continue; // unreachable - sc = cal_gchain_sc(dj, li, lc->a, f, bw, diff_thre, W_CHN_PEN_GAP); - - if (sc == INT32_MIN) continue; // out of band - // if (sc < 0) continue;// negative score - if (sc > max_f) { - max_f = sc, max_j = dj->meta, max_d = dj->dist, max_hash = dj->hash, max_inner = dj->inner; - } - } - } - if(max_f < 0) { - max_f = li->score; max_j = -1; - } - - f[i] = max_f; p[i] = max_j; - ///same time for gchain - li->dist_pre = max_d; - li->hash_pre = max_hash; - li->inner_pre = max_inner; - if(max_f < plus) plus = max_f;//minmun negative - } - - for (; i < lc_n; i++) { - li = &lc->a[i]; - max_f = li->score, max_j = -1, max_d = -1, max_inner = 0; max_hash = 0; - f[i] = max_f; p[i] = max_j; - ///same time for gchain - li->dist_pre = max_d; - li->hash_pre = max_hash; - li->inner_pre = max_inner; - if(max_f < plus) plus = max_f;//minmun negative - } - - for (i = 0; i < lc_n; ++i) { - f[i]-=plus; t[i] = f[i]<<32; t[i] += (i<<1); - } - - sw->n = 0; kv_resize(mg_lchain_t, *sw, (uint64_t)lc_n); - kv_resize(uint64_t, *bf, (uint64_t)lc_n); u = bf->a; - n_u = n_v = 0; radix_sort_gfa64i(t, t + lc_n); plus = 0; - for (k = lc_n-1, n_v = n_u = 0; k >= 0; --k) { - n_v0 = n_v; - for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { - sw->a[n_v++] = lc->a[i]; t[i] |= 1; i = p[i]; - } - if(n_v0 == n_v) continue; - sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); - if(sc < plus) plus = sc; - if(sc >= 0) { - ff = ((uint64_t)(0x8000000000000000)); - } else { - ff = 0; sc = -sc; - } - u[n_u++] = (((uint64_t)sc)<<32)|((uint64_t)(n_v-n_v0))|ff; - } - - m_idx = m_sc = -1; - for (i = 0, k = 0; i < n_u; ++i) { - if((u[i]&((uint64_t)(0x8000000000000000)))) { - u[i] -= ((uint64_t)(0x8000000000000000)); sc = u[i]>>32; - } else { - sc = u[i]>>32; sc = -sc; - } - sc -= plus; u[i] <<= 32; u[i] >>= 32; u[i] |= (((uint64_t)sc)<<32); - - k0 = k, ni = (uint32_t)u[i]; - for (j = 0; j < ni; ++j) { - lc->a[k++] = sw->a[k0 + (ni - j - 1)]; - } - if(m_idx < 0 || m_sc < ((int64_t)(u[i]>>32))) { - m_idx = i; m_sc = ((int64_t)(u[i]>>32)); - } - } - assert(k == n_v); bf->n = n_u; - return m_idx; -} - - - -int64_t ctg_chain_graph(void *km, const ul_idx_t *uref, const ma_ug_t *ug, vec_mg_lchain_t *lc, -vec_mg_lchain_t *sw, vec_mg_path_dst_t *dst, vec_sp_node_t *out, vec_mg_pathv_t *path, -int64_t qlen, const ug_opt_t *uopt, int64_t bw, double ng_diff_thre, uint64_t *srt, -st_mt_t *bf, Chain_Data* dp, int64_t max_skip, int64_t max_iter, int64_t max_dis, uint64_t id) -{ - bf->n = 0; - if(lc->n == 0) return 0; - int64_t i, j, lc_n = lc->n, x, m_idx; mg_lchain_t *r; - - - for (i = 0; i < lc_n; i++) { - r = &lc->a[i]; r->dist_pre = -1; - srt[i] = r->qe; srt[i] <<= 32; srt[i] |= (uint64_t)i; - } - radix_sort_gfa64(srt, srt+lc_n); - for (i = 1, j = 0; i <= lc_n; i++) { - if (i == lc_n || (srt[i]>>32) != (srt[j]>>32)) { - if(i - j > 1) { - for (x = j; x < i; x++) { - srt[x] <<= 32; srt[x] >>= 32; srt[x] |= ((uint64_t)lc->a[(uint32_t)srt[x]].qs)<<32; - } - radix_sort_gfa64(srt+j, srt+i); - } - j = i; - } - } - - - kv_resize(mg_lchain_t, *sw, (uint64_t)lc_n); sw->n = lc_n; - for (i = 0; i < lc_n; i++) sw->a[i] = lc->a[(uint32_t)srt[i]]; - memcpy(lc->a, sw->a, lc_n *sizeof((*(lc->a)))); - - - resize_Chain_Data(dp, lc_n, NULL); - int32_t *p; int64_t *f, *t; - t = dp->tmp; p = dp->score; f = dp->pre; - - m_idx = gl_chain_linear(uref, ug, lc, sw, qlen, uopt, bw, ng_diff_thre, bf, - max_skip, max_iter, max_dis, p, f, t, lc->n, id); - - // if(m_idx >= 0 && primary_chain_check(bf->a, bf->n, lc->a)) return m_idx; - // else m_idx = -1; - // bf->n = 0; - return m_idx; -} - - -inline int32_t cal_gchain_sc_adv(const ma_ug_t *ug, const ul_idx_t *uref, const ug_opt_t *uopt, -overlap_region *ol, const mg_path_dst_t *dj, const mg_lchain_t *li, ul_ov_t *ui, mg_lchain_t *lc, int64_t *f, -int64_t b_w, float diff_thre, float chn_pen_gap, rtrace_iter *tc, int64_t trans_sc, int64_t sec_sec) -{ - // const mg_lchain_t *lj; - int32_t gap; - float lin_pen, log_pen; - if (dj->n_path == 0) return INT32_MIN; - gap = dj->dist - dj->target_dist; - // lj = &lc[dj->meta]; - if (gap < 0) gap = -gap; - if ((gap > ((dj->target_dist)*diff_thre)) && (gap > b_w)) return INT32_MIN; - // if (lj->qe <= li->qs) sc = li->score; - // else sc = (int32_t)((double)(li->qe - lj->qe) / (li->qe - li->qs) * li->score + .499); // dealing with overlap on query - int64_t trans_l = 0, sec_err = 0, qo, el = 0, sc, sc0; - mg_lchain_t *lj = &(lc[dj->meta]); ul_ov_t uj; - - trans_l = get_overlap_region_sub_err(&(ol[li->off]), tc, lj->qe, &sec_err); - sc = (li->qe - lj->qe) - (trans_l*trans_sc) - (sec_err*sec_sec); sc += f[dj->meta]; - if(((trans_l > 0) || (sec_err > 0)) && (lj->qe > li->qs)) { - set_ul_ov_t_by_mg_lchain_t(&uj, lj); - qo = infer_rovlp(ui, &uj, NULL, NULL, NULL, (ma_ug_t *)ug); - if((!get_ecov_el(uref, uopt, li->v^1, lj->v^1, b_w, N_GCHAIN_RATE, qo, 0, &el)) || (el == 0)) { - rtrace_iter tr; tr.k = INT32_MAX; sc0 = sc; - sc = f[dj->meta] + li->score; - trans_l = get_overlap_region_sub_err(&(ol[lj->off]), &tr, li->qs, &sec_err); - sc -= (((int64_t)(lj->qe - li->qs)) - (trans_l*trans_sc) - (sec_err*sec_sec)); - if(sc < sc0) sc = sc0; - } - } - - - // int64_t trans_l_debug, sec_err_debug; - // trans_l_debug = get_overlap_region_sub_err_debug(&(ol[li->off]), lc[dj->meta].qe, &sec_err_debug); - // if(!(trans_l_debug == trans_l && sec_err_debug == sec_err)) { - // fprintf(stderr, "[M::%s::] trans_l::%ld, trans_l_debug::%ld, sec_err::%ld, sec_err_debug::%ld\n", - // __func__, trans_l, trans_l_debug, sec_err, sec_err_debug); - // } - // assert(trans_l_debug == trans_l && sec_err_debug == sec_err); - - - // sc = li->score; - //sc += dj->mlen; // TODO: is this line the right thing to do? - // if (dj->is_0) sc += ref_bonus; - lin_pen = chn_pen_gap * (float)gap; - log_pen = gap >= 2? mg_log2(gap) : 0.0f; - sc -= (int32_t)(lin_pen + log_pen); - return sc; -} - -int64_t gl_chain_graph_adv(void *km, overlap_region *ol, const ul_idx_t *uref, const ma_ug_t *ug, vec_mg_lchain_t *lc, -vec_mg_lchain_t *sw, vec_mg_path_dst_t *dst, vec_sp_node_t *out, vec_mg_pathv_t *path, -int64_t qlen, const ug_opt_t *uopt, int64_t bw, double diff_thre, uint64_t *srt, -st_mt_t *bf, Chain_Data* dp, int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t trans_sc, int64_t sec_sec, -int64_t need_srt) -{ - bf->n = 0; - if(lc->n == 0) return 0; - int64_t i, j, lc_n = lc->n, n_ext, mm_ovlp, target_dist, max_target_dist, x, m_idx, m_sc, qo, sc; rtrace_iter tc; - int64_t max_f, max_j = -1, max_d = -1, max_inner = 0; uint32_t max_hash = 0; int64_t k, k0, n_u, n_v, ni; - mg_lchain_t *r, *li, *lj; mg_path_dst_t *q; asg_t *g = ug->g; uint64_t isolated, *u, ff; ul_ov_t ui, uj; - if(!need_srt) { - for (i = n_ext = 0; i < lc_n; i++) { - r = &lc->a[i]; r->dist_pre = -1; isolated = 0;///dist_pre -> parent in graph chain - if((r->re < g->seq[r->v>>1].len) && (r->rs > 0)) isolated = 1;///UL contained in one vertice - if (!isolated) { - srt[n_ext] = r->qe; srt[n_ext] <<= 32; - srt[n_ext] |= (uint64_t)i; srt[n_ext] |= (isolated<<63); - ++n_ext; - } - } - j = n_ext; - if(j < lc_n) { - for (i = 0; i < lc_n; i++) { - r = &lc->a[i]; r->dist_pre = -1; isolated = 0;///dist_pre -> parent in graph chain - if((r->re < g->seq[r->v>>1].len) && (r->rs > 0)) isolated = 1;///UL contained in one vertice - if (isolated) { - srt[j] = r->qe; srt[j] <<= 32; srt[j] |= (uint64_t)i; srt[j] |= (isolated<<63); ++j; - } - } - } - assert(j == lc_n); - } else { - for (i = n_ext = 0; i < lc_n; i++) { - r = &lc->a[i]; r->dist_pre = -1; isolated = 0;///dist_pre -> parent in graph chain - if((r->re < g->seq[r->v>>1].len) && (r->rs > 0)) isolated = 1;///UL contained in one vertice - if (!isolated) ++n_ext; - srt[i] = r->qe; srt[i] <<= 32; srt[i] |= (uint64_t)i; srt[i] |= (isolated<<63); - } - radix_sort_gfa64(srt, srt+lc_n); - for (i = 1, j = 0; i <= lc_n; i++) { - if (i == lc_n || (srt[i]>>32) != (srt[j]>>32)) { - if(i - j > 1) { - for (x = j; x < i; x++) { - srt[x] <<= 32; srt[x] >>= 32; srt[x] |= ((uint64_t)lc->a[(uint32_t)srt[x]].qs)<<32; - } - radix_sort_gfa64(srt+j, srt+i); - } - j = i; - } - } - } - if((n_ext != lc_n) || (need_srt)) { - kv_resize(mg_lchain_t, *sw, (uint64_t)lc_n); sw->n = lc_n; - for (i = 0; i < lc_n; i++) sw->a[i] = lc->a[(uint32_t)srt[i]]; - memcpy(lc->a, sw->a, lc_n *sizeof((*(lc->a)))); - } - - resize_Chain_Data(dp, lc_n, NULL); memset(&tc, 0, sizeof(tc)); - int32_t *p; int64_t *f, *t, n_skip, dst_n, is_f, plus, n_v0; mg_path_dst_t *dj; - t = dp->tmp; p = dp->score; f = dp->pre; - - memset(t, 0, (n_ext*sizeof((*t)))); - for (i = plus = 0; i < n_ext; ++i) { // core loop - li = &lc->a[i]; set_ul_ov_t_by_mg_lchain_t(&ui, li); - mm_ovlp = max_ovlp(g, li->v^1); - x = (li->qs + mm_ovlp)*diff_thre; if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_mg_lchain_max(i, lc->a, x+G_CHAIN_INDEL); - - n_skip = 0; is_f = 0; - // collect potential destination vertices - for (dst->n = 0, max_target_dist = -1, j = x; j >= 0; --j) { - lj = &lc->a[j]; ///extend_end_coord(lj, qlen, g->seq[lj->v>>1].len, &jqs, &jqe, &jrs, &jre); - //lj contained in li; actually in circle, this might happen; need to deal with it later - if(lj->qs >= li->qs/**+G_CHAIN_INDEL**/) continue; - ///if there is a circle, the two linear chains might be at the same vertice - target_dist = hc_target_len(g, li, lj); - if(target_dist < 0) continue; - kv_pushp(mg_path_dst_t, *dst, &q); - memset(q, 0, sizeof(*q)); - q->inner = 0;//we set q->inner = 0 to allow circles - q->v = lj->v^1;///must be v^1 instead of v - q->meta = j; - ///lj->qs************lj->qe - /// li->qs************li->qe - q->qlen = li->qs - lj->qe;///might be negative; this is the region that need to be checked in base-level - q->target_dist = target_dist;///cannot understand the target_dist - q->target_hash = 0; - q->check_hash = 0; - if(max_target_dist < target_dist) max_target_dist = target_dist; - if (t[j] == i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - if((!is_f) && (lj->qe+G_CHAIN_INDEL > li->qs)) { - set_ul_ov_t_by_mg_lchain_t(&uj, lj); - qo = infer_rovlp(&ui, &uj, NULL, NULL, NULL, (ma_ug_t *)ug); - if(/**li->v!=lj->v &&**/ get_ecov_adv(uref, uopt, li->v^1, lj->v^1, bw, N_GCHAIN_RATE, qo, 0, NULL)) { - is_f = 1; if(n_skip > 0) n_skip--; - if(n_skip < (max_skip>>1)) n_skip= (max_skip>>1); - } - } - } - - // confirm reach-ability - max_f = li->score, max_j = -1, max_d = -1, max_inner = 0; max_hash = 0; - if(dst->n) { - max_target_dist *= (1+diff_thre); if(max_target_dist < bw) max_target_dist = bw; - hc_shortest_k(km, g, li->v^1, dst->n, dst->a, max_target_dist, MG_MAX_SHORT_K, bf, srt, out, NULL, 1, 0, 0); - // remove unreachable destinations - //TODO: check sequence identity - dst_n = dst->n; tc.k = INT32_MAX; - for (j = 0; j < dst_n; ++j) { - dj = &dst->a[j]; - if (dj->n_path == 0) continue; // unreachable - sc = cal_gchain_sc_adv(ug, uref, uopt, ol, dj, li, &ui, lc->a, f, bw, diff_thre, W_CHN_PEN_GAP, &tc, trans_sc, sec_sec); - - if (sc == INT32_MIN) continue; // out of band - // if (sc < 0) continue;// negative score - if (sc > max_f) { - max_f = sc, max_j = dj->meta, max_d = dj->dist, max_hash = dj->hash, max_inner = dj->inner; - } - } - } - if(max_f < 0) { - max_f = li->score; max_j = -1; - } - - f[i] = max_f; p[i] = max_j; - ///same time for gchain - li->dist_pre = max_d; - li->hash_pre = max_hash; - li->inner_pre = max_inner; - if(max_f < plus) plus = max_f;//minmun negative - } - - for (; i < lc_n; i++) { - li = &lc->a[i]; - max_f = li->score, max_j = -1, max_d = -1, max_inner = 0; max_hash = 0; - f[i] = max_f; p[i] = max_j; - ///same time for gchain - li->dist_pre = max_d; - li->hash_pre = max_hash; - li->inner_pre = max_inner; - if(max_f < plus) plus = max_f;//minmun negative - } - - for (i = 0; i < lc_n; ++i) { - f[i]-=plus; t[i] = f[i]<<32; t[i] += (i<<1); - } - - sw->n = 0; kv_resize(mg_lchain_t, *sw, (uint64_t)lc_n); - kv_resize(uint64_t, *bf, (uint64_t)lc_n); u = bf->a; - n_u = n_v = 0; radix_sort_gfa64i(t, t + lc_n); plus = 0; - for (k = lc_n-1, n_v = n_u = 0; k >= 0; --k) { - n_v0 = n_v; - for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { - sw->a[n_v++] = lc->a[i]; t[i] |= 1; i = p[i]; - } - if(n_v0 == n_v) continue; - sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); - if(sc < plus) plus = sc; - if(sc >= 0) { - ff = ((uint64_t)(0x8000000000000000)); - } else { - ff = 0; sc = -sc; - } - u[n_u++] = (((uint64_t)sc)<<32)|((uint64_t)(n_v-n_v0))|ff; - } - - m_idx = m_sc = -1; - for (i = 0, k = 0; i < n_u; ++i) { - if((u[i]&((uint64_t)(0x8000000000000000)))) { - u[i] -= ((uint64_t)(0x8000000000000000)); sc = u[i]>>32; - } else { - sc = u[i]>>32; sc = -sc; - } - sc -= plus; u[i] <<= 32; u[i] >>= 32; u[i] |= (((uint64_t)sc)<<32); - - k0 = k, ni = (uint32_t)u[i]; - for (j = 0; j < ni; ++j) { - lc->a[k++] = sw->a[k0 + (ni - j - 1)]; - } - if(m_idx < 0 || m_sc < ((int64_t)(u[i]>>32))) { - m_idx = i; m_sc = ((int64_t)(u[i]>>32)); - } - } - assert(k == n_v); bf->n = n_u; - return m_idx; -} - - -void prt_chains(ul_ov_t *l_idx, int64_t l_idx_n, ul_ov_t *l_a, uint64_t *g_idx, int64_t g_idx_n, vec_mg_lchain_t *g_a, int64_t ql) -{ - int64_t k, i, s, e; - if(l_idx && l_a) { - fprintf(stderr, "\n[M::%s::qlen->%ld] print linear chains\n", __func__, ql); - for (k = 0; k < l_idx_n; k++) { - s = l_idx[k].ts; e = l_idx[k].te; - fprintf(stderr, "[M::%s::linear_chain] sc::%u, occ::%ld\n", __func__, l_idx[k].qn, e-s); - for (i = s; i < e; i++) { - fprintf(stderr, "[M::%s::utg%.6dl] q::[%u, %u)\n", __func__, (int32_t)l_a[i].tn+1, l_a[i].qs, l_a[i].qe); - } - } - } - - if(g_idx && g_a) { - fprintf(stderr, "\n[M::%s::qlen->%ld] print graph chains\n", __func__, ql); - for (k = s = e = 0; k < g_idx_n; ++k) { - s = e; e += ((uint32_t)g_idx[k]); - fprintf(stderr, "[M::%s::grapn_chain] sc::%lu, occ::%ld\n", __func__, g_idx[k]>>32, e-s); - for (i = s; i < e; i++) { - fprintf(stderr, "[M::%s::utg%.6dl] q::[%u, %u)\n", __func__, (int32_t)(g_a->a[i].v>>1)+1, g_a->a[i].qs, g_a->a[i].qe); - } - } - } -} - -uint32_t gen_gchain_track(void *km, mg_lchain_t *a, int64_t a_n, const asg_t *g, -st_mt_t *dst_done, vec_sp_node_t *out, vec_mg_pathv_t *res); - -uint32_t select_max_gchain(void *km, const ul_idx_t *uref, int64_t ulid, st_mt_t *idx, vec_mg_lchain_t *e, kv_ul_ov_t *raw_idx, -const asg_t *g, st_mt_t *dst_done, vec_sp_node_t *out, vec_mg_pathv_t *res, vec_mg_lchain_t *gchains) -{ - gchains->n = 0; - if(idx->n <= 0) return 0; - int64_t a_n, idx_n = idx->n, i, k, n_mchain = 0, min_sc, max_sc; uint64_t om, ok, ovlp; - ul_ov_t *m = NULL, *p = NULL, kp; mg_lchain_t *a = e->a, *g_item; int64_t raw_idx_n = raw_idx->n; - ul_ov_t *gb = NULL; int64_t gb_n = 0; - for (i = a_n = 0; i < idx_n; ++i) { - kv_pushp(ul_ov_t, *raw_idx, &p); - p->qn = ((int64_t)(idx->a[i]>>32));//score - p->ts = a_n; p->te = a_n + ((uint32_t)idx->a[i]); - p->qs = a[p->ts].qs; p->qe = a[p->te-1].qe; p->tn = 1;//(tn = 1) -> normal; (t = 0) -> duplicated chain - a_n += ((uint32_t)idx->a[i]); - } - gb = raw_idx->a + raw_idx_n; gb_n = raw_idx->n - raw_idx_n; - radix_sort_ul_ov_srt_qn(gb, gb + gb_n);//sort by scores - for (k = 0, n_mchain = gb_n>>1; k < n_mchain; k++) { - kp = gb[k]; gb[k] = gb[gb_n-k-1]; gb[gb_n-k-1] = kp; - } - - for (k = 0; k < gb_n; k++) {//filter too close chains - m = &(gb[k]); om = m->qe - m->qs; ///current chain - // fprintf(stderr, "k::%ld[M::%s::sc->%u] q::[%u, %u), set::%u\n", k, __func__, m->qn, m->qs, m->qe, m->tn); - if(m->tn == 0) continue; - for (i = k-1; i >= 0; i--) { - p = &(gb[i]); - ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); - if(ovlp == 0) continue; - min_sc = MIN(p->qn, m->qn); max_sc = MAX(p->qn, m->qn); - ok = p->qe - p->qs; ok = MAX(ok, om); - if(min_sc < (max_sc*0.98)) break; - if((ovlp > GC_OFFSET_POS) && (min_sc > (max_sc*0.98)) && (ovlp > (ok*0.8))) { - // fprintf(stderr, "k::%ld[M::%s::i->%ld] min_sc::%ld, max_sc::%ld\n", - // k, __func__, i, min_sc, max_sc); - m->tn = p->tn = 0; - } - } - - for (i = k+1; i < gb_n; i++) { - p = &(gb[i]); - ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); - if(ovlp == 0) continue; - min_sc = MIN(p->qn, m->qn); max_sc = MAX(p->qn, m->qn); - ok = p->qe - p->qs; ok = MAX(ok, om); - if(min_sc < (max_sc*0.98)) break; - if((ovlp > GC_OFFSET_POS) && (min_sc > (max_sc*0.98)) && (ovlp > (ok*0.8))) { - // fprintf(stderr, "k::%ld[M::%s::i->%ld] min_sc::%ld, max_sc::%ld\n", - // k, __func__, i, min_sc, max_sc); - m->tn = p->tn = 0; - } - } - } - - for (k = i = 0; k < gb_n; k++) { - m = &(gb[k]); if(m->tn == 0) continue; - gb[i++] = gb[k]; - } - // fprintf(stderr, "[M::%s::] gb_n0::%ld, gb_n::%ld\n", __func__, gb_n, i); - gb_n = i; - - for (k = n_mchain = 0; k < gb_n; k++) { - m = &(gb[k]); om = m->qe - m->qs; - for (i = 0; i < n_mchain; i++) { - p = &(gb[i]); - ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); - if(ovlp == 0) continue; - ok = p->qe - p->qs; - if((ovlp > ok*0.1) || (ovlp > om*0.1)) break; - } - if(i < n_mchain) continue; - gb[n_mchain++] = gb[k]; - } - gb_n = n_mchain; - - if(gb_n) { - gchains->n = 0; - for (k = 0; k < gb_n; k++) { - kv_pushp(mg_lchain_t, *gchains, &g_item); - g_item->v = (uint32_t)-1; - g_item->qs = gb[k].qs; g_item->qe = gb[k].qe; - g_item->rs = gb[k].ts; g_item->re = gb[k].te; - g_item->cnt = g_item->off = 0; - gen_gchain_track(km, a + g_item->rs, g_item->re - g_item->rs, g, dst_done, out, res); - kv_resize(mg_lchain_t, *gchains, gchains->n + res->n); ///a = gchains->a + gchains->n; - for (i = 0, g_item = &(gchains->a[gchains->n-1]); i < ((int64_t)res->n); i++) { - if(res->a[i].v == (uint32_t)-1) { - gchains->a[i+gchains->n] = a[res->a[i].pre + g_item->rs]; - gchains->a[i+gchains->n].dist_pre = res->a[i].d; - // if(ulid == 14714) { - // fprintf(stderr, "+[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\n", __func__, - // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1], - // gchains->a[i+gchains->n].qs, gchains->a[i+gchains->n].qe, - // gchains->a[i+gchains->n].rs, gchains->a[i+gchains->n].re); - // } - } else { - gchains->a[i+gchains->n].v = res->a[i].v; - gchains->a[i+gchains->n].off = -1; - gchains->a[i+gchains->n].dist_pre = res->a[i].d; - ///the nodes detected by the graph chaining should be fully covered - gchains->a[i+gchains->n].rs = 0; - gchains->a[i+gchains->n].re = uref->ug->g->seq[res->a[i].v>>1].len; - // fprintf(stderr, "aaaaaaa, ulid->%ld\n", ulid); - // fprintf(stderr, "-[M::%s::]\tutg%.6dl(%c)\n", __func__, - // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1]); - // if(ulid == 14714) { - // fprintf(stderr, "-[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\n", __func__, - // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1], - // gchains->a[i+gchains->n].qs, gchains->a[i+gchains->n].qe, - // gchains->a[i+gchains->n].rs, gchains->a[i+gchains->n].re); - // } - } - } - g_item->cnt = res->n; - gchains->n += res->n; - // fprintf(stderr, "sbsbsbsb, ulid->%ld\n", ulid); - // debug_gchain(km, g, gchains->a + gchains->n - res->n, res->n, dst_done, out); - } - } - - raw_idx->n = raw_idx_n; - return n_mchain; -} - -inline uint32_t is_compat_contig_chain(const asg_t *g, ul_ov_t *p, ul_ov_t *m, mg_lchain_t *a, double overhead) -{ - uint64_t ovlp; - ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); - if(ovlp == 0) return 1; - if(ovlp == (m->qe - m->qs)) return 0;////contain - if(ovlp == (p->qe - p->qs)) return 0;////contain - ul_ov_t *i0, *i1; - if(p->qs <= m->qs) { - i0 = p; i1 = m; - } else { - i0 = m; i1 = p; - } - - uint64_t o0 = max_ovlp(g,a[i0->te-1].v); - uint64_t o1 = max_ovlp(g,a[i1->ts].v^1); - uint64_t cut = MIN(o0, o1); cut *= (1 + overhead); - if(ovlp > cut) return 0; - return 1; -} - - -uint32_t select_max_ctg_chain(void *km, const ul_idx_t *uref, int64_t ulid, st_mt_t *idx, vec_mg_lchain_t *e, kv_ul_ov_t *raw_idx, -const asg_t *g, st_mt_t *dst_done, vec_sp_node_t *out, vec_mg_pathv_t *res, vec_mg_lchain_t *gchains) -{ - gchains->n = 0; - if(idx->n <= 0) return 0; - int64_t a_n, idx_n = idx->n, i, k, n_mchain = 0, min_sc, max_sc; uint64_t om, ok, ovlp; - ul_ov_t *m = NULL, *p = NULL, kp; mg_lchain_t *a = e->a, *g_item; int64_t raw_idx_n = raw_idx->n; - ul_ov_t *gb = NULL; int64_t gb_n = 0; - for (i = a_n = 0; i < idx_n; ++i) { - kv_pushp(ul_ov_t, *raw_idx, &p); - p->qn = ((int64_t)(idx->a[i]>>32));//score - p->ts = a_n; p->te = a_n + ((uint32_t)idx->a[i]); - p->qs = a[p->ts].qs; p->qe = a[p->te-1].qe; p->tn = 1;//(tn = 1) -> normal; (t = 0) -> duplicated chain - a_n += ((uint32_t)idx->a[i]); - } - gb = raw_idx->a + raw_idx_n; gb_n = raw_idx->n - raw_idx_n; - radix_sort_ul_ov_srt_qn(gb, gb + gb_n);//sort by scores - for (k = 0, n_mchain = gb_n>>1; k < n_mchain; k++) { - kp = gb[k]; gb[k] = gb[gb_n-k-1]; gb[gb_n-k-1] = kp; - } - - for (k = 0; k < gb_n; k++) {//filter too close chains - m = &(gb[k]); om = m->qe - m->qs; ///current chain - // fprintf(stderr, "k::%ld[M::%s::sc->%u] q::[%u, %u), set::%u\n", k, __func__, m->qn, m->qs, m->qe, m->tn); - if(m->tn == 0) continue; - for (i = k-1; i >= 0; i--) { - p = &(gb[i]); - ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); - if(ovlp == 0) continue; - min_sc = MIN(p->qn, m->qn); max_sc = MAX(p->qn, m->qn); - ok = p->qe - p->qs; ok = MAX(ok, om); - if(min_sc < (max_sc*0.98)) break; - if((ovlp > GC_OFFSET_POS) && (min_sc > (max_sc*0.98)) && (ovlp > (ok*0.8))) { - // fprintf(stderr, "k::%ld[M::%s::i->%ld] min_sc::%ld, max_sc::%ld\n", - // k, __func__, i, min_sc, max_sc); - m->tn = p->tn = 0; - } - } - - for (i = k+1; i < gb_n; i++) { - p = &(gb[i]); - ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); - if(ovlp == 0) continue; - min_sc = MIN(p->qn, m->qn); max_sc = MAX(p->qn, m->qn); - ok = p->qe - p->qs; ok = MAX(ok, om); - if(min_sc < (max_sc*0.98)) break; - if((ovlp > GC_OFFSET_POS) && (min_sc > (max_sc*0.98)) && (ovlp > (ok*0.8))) { - // fprintf(stderr, "k::%ld[M::%s::i->%ld] min_sc::%ld, max_sc::%ld\n", - // k, __func__, i, min_sc, max_sc); - m->tn = p->tn = 0; - } - } - } - - for (k = i = 0; k < gb_n; k++) { - m = &(gb[k]); if(m->tn == 0) continue; - gb[i++] = gb[k]; - } - // fprintf(stderr, "[M::%s::] gb_n0::%ld, gb_n::%ld\n", __func__, gb_n, i); - gb_n = i; - - for (k = n_mchain = 0; k < gb_n; k++) { - m = &(gb[k]); - for (i = 0; i < n_mchain; i++) { - p = &(gb[i]); - if(!is_compat_contig_chain(g, p, m, a, 0.333333)) break; - } - if(i < n_mchain) continue; - gb[n_mchain++] = gb[k]; - } - gb_n = n_mchain; - - if(gb_n) { - gchains->n = 0; - for (k = 0; k < gb_n; k++) { - kv_pushp(mg_lchain_t, *gchains, &g_item); - g_item->v = (uint32_t)-1; - g_item->qs = gb[k].qs; g_item->qe = gb[k].qe; - g_item->rs = gb[k].ts; g_item->re = gb[k].te; - g_item->cnt = g_item->off = 0; - gen_gchain_track(km, a + g_item->rs, g_item->re - g_item->rs, g, dst_done, out, res); - kv_resize(mg_lchain_t, *gchains, gchains->n + res->n); ///a = gchains->a + gchains->n; - for (i = 0, g_item = &(gchains->a[gchains->n-1]); i < ((int64_t)res->n); i++) { - if(res->a[i].v == (uint32_t)-1) { - gchains->a[i+gchains->n] = a[res->a[i].pre + g_item->rs]; - gchains->a[i+gchains->n].dist_pre = res->a[i].d; - // if(ulid == 14714) { - // fprintf(stderr, "+[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\n", __func__, - // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1], - // gchains->a[i+gchains->n].qs, gchains->a[i+gchains->n].qe, - // gchains->a[i+gchains->n].rs, gchains->a[i+gchains->n].re); - // } - } else { - gchains->a[i+gchains->n].v = res->a[i].v; - gchains->a[i+gchains->n].off = -1; - gchains->a[i+gchains->n].dist_pre = res->a[i].d; - ///the nodes detected by the graph chaining should be fully covered - gchains->a[i+gchains->n].rs = 0; - gchains->a[i+gchains->n].re = uref->ug->g->seq[res->a[i].v>>1].len; - // fprintf(stderr, "aaaaaaa, ulid->%ld\n", ulid); - // fprintf(stderr, "-[M::%s::]\tutg%.6dl(%c)\n", __func__, - // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1]); - // if(ulid == 14714) { - // fprintf(stderr, "-[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\n", __func__, - // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1], - // gchains->a[i+gchains->n].qs, gchains->a[i+gchains->n].qe, - // gchains->a[i+gchains->n].rs, gchains->a[i+gchains->n].re); - // } - } - } - g_item->cnt = res->n; - gchains->n += res->n; - // fprintf(stderr, "sbsbsbsb, ulid->%ld\n", ulid); - // debug_gchain(km, g, gchains->a + gchains->n - res->n, res->n, dst_done, out); - } - } - - raw_idx->n = raw_idx_n; - return n_mchain; -} - -// void prt_chains_vlog(ul_ov_t *l_idx, int64_t l_idx_n, ul_ov_t *l_a, uint64_t *g_idx, int64_t g_idx_n, vec_mg_lchain_t *g_a, int64_t ql, int64_t ulid) -// { -// int64_t k, i, s, e; char *as = NULL; -// if(l_idx && l_a) { -// for (k = 0; k < l_idx_n; k++) { -// s = l_idx[k].ts; e = l_idx[k].te; -// asprintf(&as, "[M::%s::linear_chain] sc::%u, occ::%ld\n", __func__, l_idx[k].qn, e-s); -// push_vlog(&(overall_zdbg->a[ulid]), as); free(as); as = NULL; -// for (i = s; i < e; i++) { -// asprintf(&as, "[M::%s::utg%.6dl] q::[%u, %u)\n", __func__, (int32_t)l_a[i].tn+1, l_a[i].qs, l_a[i].qe); -// push_vlog(&(overall_zdbg->a[ulid]), as); free(as); as = NULL; -// } -// } -// } - -// if(g_idx && g_a) { -// for (k = s = e = 0; k < g_idx_n; ++k) { -// s = e; e += ((uint32_t)g_idx[k]); -// asprintf(&as, "[M::%s::grapn_chain] sc::%lu, occ::%ld\n", __func__, g_idx[k]>>32, e-s); -// push_vlog(&(overall_zdbg->a[ulid]), as); free(as); as = NULL; -// for (i = s; i < e; i++) { -// asprintf(&as, "[M::%s::utg%.6dl] q::[%u, %u)\n", __func__, (int32_t)(g_a->a[i].v>>1)+1, g_a->a[i].qs, g_a->a[i].qe); -// push_vlog(&(overall_zdbg->a[ulid]), as); free(as); as = NULL; -// } -// } -// } -// } - -int64_t gl_chain(mg_tbuf_t *b, ul_vec_t *rch, overlap_region_alloc* olist, -Chain_Data* dp, haplotype_evdience_alloc *hap, st_mt_t *sps, glchain_t *ll, -gdpchain_t *gdp, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, -int64_t qlen, const ug_opt_t *uopt, int64_t debug_i, int64_t tid, void *km) -{ - ll->tk.n = ll->lo.n = 0; - kv_ul_ov_t *idx = &(ll->lo); - ks_introsort_or_xe(olist->length, olist->list); - gen_gl_aln(olist, uref, idx); - if(idx->n == 0) return 0; - int64_t max_idx, occ = 0, f = 0; - - kv_resize(ul_ov_t, ll->tk, idx->n); - occ = gl_chain_lin(idx, olist->list, ll->tk.a, uref, uopt, G_CHAIN_BW, N_GCHAIN_RATE, qlen, UG_SKIP_N, UG_ITER_N, UG_DIS_N, dp, UG_TRANS_W, 0, NULL, uref->ug, 0, debug_i); - // prt_chains(idx->a, idx->n, ll->tk.a, NULL, 0, NULL, qlen); - // prt_chains_vlog(idx->a, idx->n, ll->tk.a, NULL, 0, NULL, qlen, debug_i); - - - if(occ) { - if(ff_chain(idx, qlen, 0.99/**P_CHAIN_COV**/, -1/**G_CHAIN_TRANS_RATE**/, ll->tk.a, NULL, NULL, NULL, diff_ec_ul, winLen, km)) { - f = l2g_res_chain_sc(uref->ug, ll->tk.a+idx->a[idx->n-1].ts, idx->a[idx->n-1].te-idx->a[idx->n-1].ts, &(gdp->swap)); - // f = l2g_res_chain(uref->ug, ll->tk.a+idx->a[idx->n-1].ts, idx->a[idx->n-1].te-idx->a[idx->n-1].ts, &(gdp->swap), -1/**N_GCHAIN_RATE**/); - } - } - - // fprintf(stderr, "+[M::%s]\tf::%ld\n", __func__, f); - // fprintf(stderr, "1-[M::%s] f::%ld\n", __func__, f); - // fprintf(stderr, "(beg1) [M::%s] debug_i:%ld, qlen:%ld\n", __func__, debug_i, qlen); - if(!f) { - // gl_chain_gen(olist, uref, idx, 0, hap, km);///no trans - // l2g_chain(uref, idx, &(gdp->l)); ll->tk.n = 0; - gen_gg_aln(olist, uref, UG_TRANS_W, &(gdp->l)); ll->tk.n = 0; - ///buffer - // kv_resize(uint64_t, ll->srt.a, gdp->l.n); kv_resize(uint64_t, hap->snp_srt, gdp->l.n); - // kv_resize(uint64_t, gdp->v, gdp->l.n); kv_resize(int64_t, gdp->f, gdp->l.n); - // max_idx = hc_gchain1_dp(b->km, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), &(gdp->path), rch->rlen, - // uopt, G_CHAIN_BW, diff_ec_ul, -1, ll->srt.a.a, sps, gdp->f.a, hap->snp_srt.a, gdp->v.a); - kv_resize(uint64_t, ll->srt.a, gdp->l.n); - max_idx = gl_chain_graph_adv(b->km, olist->list, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), - &(gdp->path), rch->rlen, uopt, G_CHAIN_BW, diff_ec_ul, ll->srt.a.a, sps, dp, UG_SKIP_GRAPH_N, UG_ITER_N, UG_DIS_N, 0, UG_TRANS_W, UG_TRANS_ERR_W); - // prt_chains(NULL, 0, NULL, sps->a, sps->n, &(gdp->l), qlen); - // prt_chains_vlog(NULL, 0, NULL, sps->a, sps->n, &(gdp->l), qlen, debug_i); - // if(max_idx >= 0 && gen_max_gchain_adv(b->km, uref, debug_i, sps, &(gdp->l), &(ll->tk), NULL, rch->rlen, P_CHAIN_COV, 0.3/**P_FRAGEMENT_PRIMARY_CHAIN_COV**/, - // 0.1, PRIMARY_UL_CHAIN_MIN, uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), ll->srt.a.a, &(gdp->swap))) { - if(max_idx >= 0 && select_max_gchain(b->km, uref, debug_i, sps, &(gdp->l), &(ll->tk), uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), &(gdp->swap))){ - // print_raw_chains(&(gdp->swap), debug_i); - // f = check_trans_rate_gap(&(gdp->swap), &(ll->tk), olist, hap, uref, diff_ec_ul, winLen, G_CHAIN_TRANS_RATE); - f = 1; - } - } - // fprintf(stderr, "[M::%s] f::%ld\n", __func__, f); - // if(debug_i == 1756) fprintf(stderr, "[M::%s] ulid:%ld, qlen:%ld, f:%ld\n", __func__, debug_i, qlen, f); - if(f) update_ul_vec_t_ug(uref, rch, &(gdp->swap), debug_i); - // debug_ul_vec_t_chain(km, uref->ug->g, rch, &(gdp->dst_done), &(gdp->out)); - // fprintf(stderr, "(beg3) [M::%s::tid:%ld] debug_i:%ld, qlen:%ld\n", __func__, tid, debug_i, qlen); - return 1; -} - - -int64_t comput_err_partial_cigar(int64_t ol, overlap_region *z, int64_t *rk) -{ - int64_t k = 0, err = 0, e = z->x_pos_s+ol, wn = z->w_list.n; (*rk) = -1; - for (k = 0; k < wn; k++) { - if(z->w_list.a[k].x_start >= e) break; - if(z->w_list.a[k].y_end != -1) { - err += z->w_list.a[k].error; - } - } - k--; - if(k < 0) return 0; - if(z->w_list.a[k].y_end != -1) { - err -= z->w_list.a[k].error; - } - - if((int64_t)z->w_list.a[k].x_end+1 <= e) { - if(z->w_list.a[k].y_end != -1) { - err += z->w_list.a[k].error; - } - } else { - // assert(z->w_list.a[k].x_start < e); - if(z->w_list.a[k].y_end != -1) { - err += (((double)(e-z->w_list.a[k].x_start))/ - ((double)(z->w_list.a[k].x_end+1-z->w_list.a[k].x_start)))*z->w_list.a[k].error; - } - } - (*rk) = k; - return err; -} - -int64_t sum_w_err(window_list *a, int64_t n) -{ - int64_t k, err = 0; - for (k = 0; k < n; k++) { - if(a[k].y_end != -1) err += a[k].error; - } - return err; -} - -int64_t comput_sc_partial_cigar(int64_t sc, int64_t ol, double err_sc_r, overlap_region *z, int64_t *wi, int64_t *werr) -{ - int64_t k = wi?(*wi):0, wn = z->w_list.n, err = werr?(*werr):0, e = z->x_pos_s+ol; - if(ol == 0) return sc; - // int64_t pk, pe; - if((int64_t)(z->x_pos_e + 1 - z->x_pos_s) <= ol) return 0; - if(k == wn) { - k--; - if(z->w_list.a[k].y_end != -1) { - err -= z->w_list.a[k].error; - } - } - if(z->w_list.a[k].x_start >= e) { - if(z->w_list.a[k].y_end != -1) err += z->w_list.a[k].error; - for (;(k>=0) && (z->w_list.a[k].x_start>=e); k--) { - if(z->w_list.a[k].y_end != -1) { - err -= z->w_list.a[k].error; - } - } - } else { - for (;(kw_list.a[k].x_startw_list.a[k].y_end != -1) { - err += z->w_list.a[k].error; - } - } - k--; - } - // pk = (*wi); pe = (*werr); - if(k < 0) { - k = 0; err = 0; - if(wi) (*wi) = k; if(werr) (*werr) = err; - // assert(e <= z->w_list.a[0].x_start); - } else { - if(z->w_list.a[k].y_end != -1) { - err -= z->w_list.a[k].error; - } - if(wi) (*wi) = k; if(werr) (*werr) = err; - - // if(!(err >= 0 && k >= 0 && k < wn && z->w_list.a[k].x_start < e && z->w_list.a[k].x_end + 1 >= e)){ - // fprintf(stderr, "[M::%s] ol::%ld, e::%ld, z::[%u, %u], k::%ld, wn::%ld, w::[%d, %d], err::%ld\n", __func__, - // ol, e, z->x_pos_s, z->x_pos_e, k, wn, z->w_list.a[k].x_start, z->w_list.a[k].x_end, err); - // } - // assert(err >= 0 && k >= 0 && k < wn && z->w_list.a[k].x_start < e && - // (e <= z->w_list.a[k+1].x_start)); - - if((int64_t)z->w_list.a[k].x_end+1 <= e) { - if(z->w_list.a[k].y_end != -1) { - err += z->w_list.a[k].error; - } - } else { - // assert(z->w_list.a[k].x_start < e); - if(z->w_list.a[k].y_end != -1) { - err += (((double)(e-z->w_list.a[k].x_start))/ - ((double)(z->w_list.a[k].x_end+1-z->w_list.a[k].x_start)))*z->w_list.a[k].error; - } - } - } - - // int64_t dbg_k, dbg_e = comput_err_partial_cigar(ol, z, &dbg_k); - // if(err != dbg_e) { - // fprintf(stderr, "[M::%s] ol::%ld, e::%ld, z::[%u, %u], k::%ld, wn::%ld, w::[%d, %d], err::%ld, dbg_e::%ld, dbg_k::%ld, pe::%ld, pk::%ld, sum_pk_err::%ld, sum_k_err::%ld, werr::%ld\n", - // __func__, ol, e, z->x_pos_s, z->x_pos_e, k, wn, z->w_list.a[k].x_start, z->w_list.a[k].x_end, err, dbg_e, dbg_k, pe, pk, - // sum_w_err(z->w_list.a, pk), sum_w_err(z->w_list.a, k), *werr); - // } - // assert(err == dbg_e); - - ol -= (err*err_sc_r); sc -= ol; if(sc <= 0) sc = 1; - return sc; -} - -///mode: 0->ug; 1->read -int64_t ed_dp_c(overlap_region_alloc *o, kv_ul_ov_t *res, ul_ov_t *ex, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, int64_t max_skip, uint64_t *srt, uint64_t *idx, uint64_t *track, double err_sc, -uint64_t mode, All_reads *ridx, ma_ug_t *ug, uint32_t need_srt) -{ - if(res->n == 0) return 0; - uint32_t li_v, lj_v, rev_n; - int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, qo, qovl, minus_sc, pj, n_skip, wi, werr; - ul_ov_t *li = NULL, *lj = NULL, rev_t; - if(need_srt) { - radix_sort_ul_ov_srt_qe(res->a, res->a + res->n); - for (i = 1, j = 0; i <= (int64_t)res->n; i++) { - if (i == (int64_t)res->n || res->a[i].qe != res->a[j].qe) { - if(i - j > 1) radix_sort_ul_ov_srt_qs(res->a+j, res->a+i); - j = i; - } - } - } - ///res->a[0].qe: min_qe; res->a[res->n-1].qs: max_qs - if(res->a[0].qe == qlen && res->a[res->n-1].qs == 0) {///all alignments are contained - for (i = 0; i < (int64_t)res->n; ++i) { - li = &(res->a[i]); assert(li->qs == 0 && li->qe == qlen); - csc = (li->qe-li->qs); minus_sc = (o->list[li->qn].non_homopolymer_errors*err_sc); - csc -= minus_sc; if(csc <= 0) csc = 1; mm_sc = csc; mm_idx = -1; - - if(mm_sc > ((int64_t)0x7fffffff)) mm_sc = ((int64_t)0x7fffffff); - track[i] = push_sc_pre(mm_sc, mm_idx); - srt[i] = track[i]>>32; srt[i] <<= 32; srt[i] |= i; - } - } else { - memset(idx, 0, (sizeof((*idx))*res->n)); - for (i = 0; i < (int64_t)res->n; ++i) { - li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; - // fprintf(stderr, "[M::%s::i->%ld::utg%.6dl] q[%u, %u), t[%u, %u)\n", __func__, i, (int32_t)li->tn+1, li->qs, li->qe, li->ts, li->te); - mm_ovlp = mode?max_ovlp_src(uopt, li_v^1):max_ovlp(uref->ug->g, li_v^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(i, res->a, x+G_CHAIN_INDEL); - csc = (li->qe-li->qs); minus_sc = (o->list[li->qn].non_homopolymer_errors*err_sc); - csc -= minus_sc; if(csc <= 0) csc = 1; - mm_sc = csc; mm_idx = -1; n_skip = 0; wi = werr = 0; - for (j = x; j >= 0; --j) { // collect potential destination vertices - lj = &(res->a[j]); lj_v = (lj->tn<<1)|lj->rev; - if(lj->qe+G_CHAIN_INDEL <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore - if(lj->qs > li->qs+G_CHAIN_INDEL) continue;///at boundary, migh be lj->qs == li->qs - qo = infer_rovlp(li, lj, NULL, NULL, ridx, ug); ///overlap length in query (UL read) - // fprintf(stderr, "[M::%s::j->%ld] qo::%ld\n", __func__, j, qo); - if(li_v != lj_v && get_ecov_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, mode, NULL)) { - qovl = ((MIN(li->qe, lj->qe) > MAX(li->qs, lj->qs))? (MIN(li->qe, lj->qe) - MAX(li->qs, lj->qs)):0); - // fprintf(stderr, "[M::%s::] utg%.6dl->utg%.6dl, icsc::%ld, ierr::%u, ilen::%u, aln::%u, app_sc::%ld\n", - // __func__, (int32_t)li->tn+1, (int32_t)lj->tn+1, csc, o->list[li->qn].non_homopolymer_errors, - // li->qe - li->qs, o->list[li->qn].align_length, comput_sc_partial_cigar(csc, qovl, err_sc, &(o->list[li->qn]), &wi, &werr)); - sc = comput_sc_partial_cigar(csc, qovl, err_sc, &(o->list[li->qn]), &wi, &werr) - + pop_sc(track[j]); - // fprintf(stderr, "[M::%s::j->%ld] qo::%ld, sc::%ld, mm_sc::%ld\n", __func__, j, qo, sc, mm_sc); - if(sc > mm_sc) { - mm_sc = sc, mm_idx = j; - if (n_skip > 0) --n_skip; - } else if (idx[j] == (uint64_t)i) { - if (++n_skip > max_skip) - break; - } - pj = pop_pre(track[j]); - if(pj >= 0) idx[pj] = i; - } - } - if(mm_sc > ((int64_t)0x7fffffff)) mm_sc = ((int64_t)0x7fffffff); - track[i] = push_sc_pre(mm_sc, mm_idx); - srt[i] = track[i]>>32; srt[i] <<= 32; srt[i] |= i; - // fprintf(stderr, "[M::%s::i->%ld] mm_idx::%ld\n", __func__, i, mm_idx); - } - } - - int64_t n_v, n_u, n_v0; - radix_sort_gfa64(srt, srt+res->n); - for (k = (int64_t)res->n-1, n_v = n_u = 0; k >= 0; --k) { - n_v0 = n_v; - for (i = (uint32_t)srt[k]; i >= 0 && (track[i]&((uint64_t)0x80000000)) == 0;) { - ex[n_v++] = res->a[i]; track[i] |= ((uint64_t)0x80000000); - i = pop_pre(track[i]); - } - if(n_v0 == n_v) continue; - sc = (i<0?(pop_sc(srt[k])):(pop_sc(srt[k])-pop_sc(track[i]))); - if(sc < 0) { - n_v = n_v0; - continue; - } - idx[n_u++] = ((uint64_t)sc<<32)|(n_v-n_v0); - } - - for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { - n_v0 = n_v; n_v += (uint32_t)idx[k]; - res->a[k].qn = idx[k]>>32;//score - res->a[k].ts = n_v0; res->a[k].te = n_v;///idx - - rev_n = ((uint32_t)idx[k])>>1; - ///we need to consider contained reads; so determining qs is not such easy - res->a[k].qs = (uint32_t)-1; res->a[k].qe = ex[n_v0].qe; - for (i = 0; i < rev_n; i++) { - rev_t = ex[n_v0+i]; ex[n_v0+i] = ex[n_v-i-1]; ex[n_v-i-1] = rev_t; - if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; - if(res->a[k].qs > ex[n_v-i-1].qs) res->a[k].qs = ex[n_v-i-1].qs; - } - if(((uint32_t)idx[k])&1) { - if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; - } - } - - res->n = n_u; - radix_sort_ul_ov_srt_qn(res->a, res->a + res->n);//sort by score - // fprintf(stderr, "---[M::%s] n_u:%ld, n_v:%ld\n", __func__, n_u, n_v); - return n_v; -} - -void set_sec_e_min(overlap_region *z, uint64_t *w_idx, int64_t wl, int64_t ql) -{ - int64_t wid, k, wn = z->w_list.n, ws, we; - for (k = 0; k < wn; k++) { - wid = z->w_list.a[k].x_start/wl; - ws = wid*wl; we = ws+wl; if(we > ql) we = ql; we--; - // fprintf(stderr, "[M::%s] ws::%ld, we::%ld, xs::%d, xe::%d, err::%d\n", __func__, - // ws, we, z->w_list.a[k].x_start, z->w_list.a[k].x_end, z->w_list.a[k].error); - if(ws == z->w_list.a[k].x_start && we == z->w_list.a[k].x_end && z->w_list.a[k].y_end != -1) { - if((w_idx[wid] == (uint64_t)-1) || (w_idx[wid] > (uint64_t)z->w_list.a[k].error)) { - w_idx[wid] = z->w_list.a[k].error; - } - } - } -} - -int64_t cal_sec_e_min(overlap_region *z, uint64_t *w_idx, int64_t wl, int64_t ql, int64_t *sec_err) -{ - int64_t wid, k, wn = z->w_list.n, ws, we, o[2], tot_e, sc; uint64_t self_err; - o[0] = o[1] = tot_e = 0; - for (k = 0; k < wn; k++) { - wid = z->w_list.a[k].x_start/wl; - if(w_idx[wid] == (uint64_t)-1) continue; - ws = wid*wl; we = ws+wl; if(we > ql) we = ql; we--; - self_err = THRESHOLD_MAX_SIZE + 1; - if(z->w_list.a[k].y_end != -1) self_err = z->w_list.a[k].error; - - if(ws == z->w_list.a[k].x_start && we == z->w_list.a[k].x_end) { - if(self_err <= w_idx[wid]) { - o[0] += we+1-ws; - } else { - o[1] += we+1-ws; tot_e += self_err - w_idx[wid]; - } - } - } - if(sec_err) (*sec_err) = tot_e; - - sc = o[0] - (o[1]*ERROR_RATE)-(tot_e*5); - return sc; -} - - -void set_w_e(overlap_region *z, uint64_t *w_idx, int64_t wl, int64_t ql) -{ - int64_t wid, k, wn = z->w_list.n, ws, we; - for (k = 0; k < wn; k++) { - wid = z->w_list.a[k].x_start/wl; - ws = wid*wl; we = ws+wl; if(we > ql) we = ql; we--; - // fprintf(stderr, "[M::%s] ws::%ld, we::%ld, xs::%d, xe::%d, err::%d\n", __func__, - // ws, we, z->w_list.a[k].x_start, z->w_list.a[k].x_end, z->w_list.a[k].error); - if(ws == z->w_list.a[k].x_start && we == z->w_list.a[k].x_end && z->w_list.a[k].y_end != -1) { - if((w_idx[wid] == (uint64_t)-1) || (w_idx[wid] < (uint64_t)z->w_list.a[k].error)) { - w_idx[wid] = z->w_list.a[k].error; - } - } - } -} - -uint32_t ck_w_err(overlap_region *z, uint64_t *w_idx, int64_t wl, int64_t ql) -{ - int64_t wid, k, wn = z->w_list.n, ws, we, ol, e[2]; - ol = e[0] = e[1] = 0; - for (k = 0; k < wn; k++) { - wid = z->w_list.a[k].x_start/wl; - if(w_idx[wid] == (uint64_t)-1) continue; - ws = wid*wl; we = ws+wl; if(we > ql) we = ql; we--; - if(ws == z->w_list.a[k].x_start && we == z->w_list.a[k].x_end) { - ol += we+1-ws; e[0] += w_idx[wid]; - if(z->w_list.a[k].y_end != -1) e[1] += z->w_list.a[k].error; - else e[1] += THRESHOLD_MAX_SIZE + 1; - } - } - // fprintf(stderr, "[M::%s::utg%.6dl] x::[%u, %u), ol::%ld, e[0]::%ld, e[1]::%ld\n", - // __func__, (int32_t)z->y_id+1, z->x_pos_s, z->x_pos_e+1, ol, e[0], e[1]); - if(e[1] > (e[0]+64)) { - if((e[1] > (e[0]+(ol*0.01)))/**||(e[1] > (e[0]+(e[0]*0.03)))**/) { - z->non_homopolymer_errors = e[1] - e[0]; - return 0; - } - } - // if((e[1] > (e[0]+16)) && (e[1] > (e[0]+(ol*0.01)))) return 0; - return 1; -} - -int64_t filter_sec(overlap_region_alloc *ol, ul_ov_t *idx, int64_t idx_n, ul_ov_t *a, uint64_t *w_idx, uint64_t nw, uint64_t wl, uint64_t ql) -{ - if(idx_n <= 0) return 1; - int64_t on = ol->length, k, z, on_contain = 0, max_i = -1, max_k = -1; overlap_region t; - memset(w_idx, -1, nw*sizeof((*w_idx))); - for (k = 0; k < on; k++) ol->list[k].is_match = 0; - for (k = 0; k < idx_n; k++) {///potiential best chains - // fprintf(stderr, "[M::%s::pri_chain[%ld]] q_coord::[%u, %u), occ::%u\n", - // __func__, k, idx[k].qs, idx[k].qe, idx[k].te-idx[k].ts); - for (z = idx[k].ts; z < idx[k].te; z++) { - ol->list[a[z].qn].is_match = 2; - set_w_e(&(ol->list[a[z].qn]), w_idx, wl, ql); - // fprintf(stderr, "[M::%s::utg%.6dl]\n", __func__, (int32_t)a[z].tn+1); - } - on_contain += (((idx[k].te-idx[k].ts)==1)?1:0); - } - if(on_contain == idx_n) {///each primary chain only has one alignment - on_contain = 0; - } else { - on_contain = -on-1;///in this case, on_contain == z is always wrong - } - max_i = a[idx[idx_n-1].ts].qn; - for (k = z = 0; k < on; k++) { - if(!ol->list[k].is_match) ol->list[k].is_match = ck_w_err(&(ol->list[k]), w_idx, wl, ql); - if(!ol->list[k].is_match) continue; - if(z != k) { - t = ol->list[k]; - ol->list[k] = ol->list[z]; - ol->list[z] = t; - } - if(ol->list[z].x_pos_s == 0 && ol->list[z].x_pos_e == ql - 1) { - on_contain++; - if(max_i == k) max_k = z; - } - // if(ol->list[z].is_match == 1) alt_occ++; - // else ol->list[z].is_match = 1; - ol->list[z].is_match = 1; - z++; - } - ol->length = z; - // fprintf(stderr, "+[M::%s] oln::%ld\n", __func__, ol->length); - if(on_contain == z) {///do not contribute to phase - k = max_k; z = 0; - if(z != k) { - t = ol->list[k]; - ol->list[k] = ol->list[z]; - ol->list[z] = t; - } - ol->length = 1; - } - // fprintf(stderr, "-[M::%s] oln::%ld\n", __func__, ol->length); - // if(alt_occ == 0 || ol->length == 1) return 1;//if all alignments are primary or there is only one alignment - // for (k = ol->length; k < on; k++) ol->list[k].is_match = 2;//recover trans alignments - // ol->length = on; - if(ol->length == 1) return 1; - return 0; -} - -void regen_ul_ov_t_lst(const ul_idx_t *uref, overlap_region_alloc* olist, kv_ul_ov_t *idx) -{ - uint64_t k; ul_ov_t *p; idx->n = 0; - kv_resize(ul_ov_t, *idx, olist->length); - for (k = 0; k < olist->length; k++) { - // fprintf(stderr, "---[M::%s::utg%.6dl] q[%d, %d), t[%d, %d), tot::%u, cis::%u\n", __func__, - // (int32_t)olist->list[k].y_id+1, olist->list[k].x_pos_s, olist->list[k].x_pos_e+1, - // olist->list[k].y_pos_s, olist->list[k].y_pos_e+1, - // olist->list[k].overlapLen, olist->list[k].align_length); - p = &(idx->a[idx->n++]); - p->qn = k; p->qs = olist->list[k].x_pos_s; p->qe = olist->list[k].x_pos_e+1; - p->tn = olist->list[k].y_id; p->el = 1; p->rev = olist->list[k].y_pos_strand; - p->sec = olist->list[k].non_homopolymer_errors; - if(p->rev) { - p->ts = uref->ug->u.a[p->tn].len - (olist->list[k].y_pos_e+1); - p->te = uref->ug->u.a[p->tn].len - olist->list[k].y_pos_s; - } else { - p->ts = olist->list[k].y_pos_s; - p->te = olist->list[k].y_pos_e+1; - } - } -} - -int64_t gl_chain_flter(overlap_region_alloc* olist, Correct_dumy* dumy, st_mt_t *sps, glchain_t *ll, -const ul_idx_t *uref, double diff_ec_ul, int64_t wl, int64_t ql, const ug_opt_t *uopt, uint32_t *need_phase) -{ - (*need_phase) = 1; - uint64_t k, nw; ul_ov_t *m, *p; int64_t occ, i, ovlp, idx_n; - ll->tk.n = ll->lo.n = 0; - kv_ul_ov_t *idx = &(ll->lo); - ks_introsort_or_xe(olist->length, olist->list); - regen_ul_ov_t_lst(uref, olist, idx); - if(idx->n == 0) return 0; - kv_resize(uint64_t, ll->srt.a, idx->n); - kv_resize(uint64_t, *sps, idx->n); - kv_resize(ul_ov_t, ll->tk, idx->n); - - occ = ed_dp_c(olist, idx, ll->tk.a, uref, uopt, G_CHAIN_BW, N_GCHAIN_RATE, ql, 75, dumy->overlapID, ll->srt.a.a, sps->a, ERROR_RATE, 0, NULL, uref->ug, 0); - if((!occ) || (!idx->n)) return 0; - idx_n = idx->n; p = &(idx->a[idx_n-1]); - if(idx_n <= 1) {//one chain; nothing to do - if(p->te - p->ts <= 1) (*need_phase) = 0;//one alignment; nothing to do - return 0; - } - // fprintf(stderr, "[M::%s] qs::%u, qe::%u, ql::%ld, occ::%u\n", __func__, p->qs, p->qe, ql, p->te - p->ts); - if(p->qe-p->qs <= (ql*0.333333)) return 0;///primary chain is too short - - i = idx_n-1; occ = p->te - p->ts; - if(p->qe-p->qs < ql && idx_n > 1) { - for (occ = 0; i >= 0; i--) { - p = &(idx->a[i]); - for (k = i + 1; k < idx->n; k++) { - m = &(idx->a[k]); - ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); - if(((ovlp > ((m->qe-m->qs)*0.005)) || (ovlp > ((p->qe-p->qs)*0.015))) && ovlp > 32) break; - if((ovlp == (m->qe-m->qs)) || (ovlp == (p->qe-p->qs))) break; - } - if(k < idx->n) break; - occ += p->te - p->ts; - } - i++; - } - //all alignments are primary chains; nothing to do - if(occ == (int64_t)olist->length) return 1; - - // if(i >= ((int64_t)idx->n)) return 0; - nw = get_num_wins(0, ql, wl); kv_resize(uint64_t, ll->srt.a, (uint64_t)nw); - if(filter_sec(olist, idx->a+i, idx->n-i, ll->tk.a, ll->srt.a.a, nw, wl, ql)) { - (*need_phase) = 0; - } - return 1; -} - - - -uint64_t gen_shared_trace(overlap_region_alloc* ol, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, -const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, int64_t *is_srt, kv_ul_ov_t *res)///[s, e] -{ - if(!id_n) return 0; - uint64_t i, m, k, os, oe, ovlp, rm_n = 0; ul_ov_t p, q, *li, *lj, *t; - for (i = m = 0; i < id_n; i++) { - if(ol->list[id_a[i]].x_pos_e < s) continue; - id_a[m++] = id_a[i]; - } - id_n = m; - if(!id_n) return 0; - //idx_a[] is sorted by ol->list[].x_pos_s - for (k = 0; k < id_n; k++) { - convert_ul_ov_t(&p, &(ol->list[id_a[k]]), uref->ug); p.qn = id_a[k]; - if(ol->list[id_a[k]].x_pos_e <= e) rm_n++; - - for (i = 0; i < id_n && ol->list[id_a[i]].x_pos_s <= ol->list[id_a[k]].x_pos_e; i++) { - if(i == k) continue; - convert_ul_ov_t(&q, &(ol->list[id_a[i]]), uref->ug); q.qn = id_a[i]; - if(p.qe > q.qe) li = &p, lj = &q; - else if(p.qe == q.qe && p.qs >= q.qs) li = &p, lj = &q; - else lj = &p, li = &q; - os = MAX(li->qs, lj->qs), oe = MIN(li->qe, lj->qe); - ovlp = ((oe > os)? (oe - os):0); - if(!ovlp) continue;//no overlap - t = NULL; - if(res->n > 0 && res->a[res->n-1].qn == p.qn) { - if(res->a[res->n-1].qs<=os && res->a[res->n-1].qe>=oe) continue; - t = &(res->a[res->n-1]); - } - // fprintf(stderr, "\nk::%lu::utg%.6dl[M::%s::utg%.6dl->utg%.6dl]\n", - // k, (int32_t)ol->list[id_a[k]].y_id+1, __func__, (int32_t)li->tn+1, (int32_t)lj->tn+1); - //not contain; graph does not has contained overlaps - //but at boundary, migh be lj->qs == li->qs - if(lj->qs <= li->qs+G_CHAIN_INDEL) { - if(govlp_check(uref, uopt, bw, diff_ec_ul, li, lj)) continue; - } else if((lj->qe+G_CHAIN_INDEL>=li->qe) && (lj->qs+G_CHAIN_INDEL>=li->qs)) { - if(govlp_check(uref, uopt, bw, diff_ec_ul, lj, li)) continue; - } - if(t && t->qs<=os && t->qe >= os) { - ///assert(t->qs<=os && t->qe t->qe) t->qe = oe; - } else { - kv_pushp(ul_ov_t, *res, &t); - t->qn = p.qn; t->qs = os; t->qe = oe; - } - } - if(res->n > 0 && res->a[res->n-1].qn == p.qn) { - ol->list[p.qn].align_length++; - if(ol->list[p.qn].align_length > 1) (*is_srt) = 0; - } - } - - if(rm_n) { - for (i = m = 0; i < id_n; i++) { - if(ol->list[id_a[i]].x_pos_e <= e) continue; - id_a[m++] = id_a[i]; - } - id_n = m; - } - return id_n; -} - -uint64_t gen_shared_intervals(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t wl, kvec_t_u64_warp* idx, kv_ul_ov_t *res) -{ - int64_t i, j, k, on = ol->length, srt_n = on<<1, dp, old_dp, beg, end, is_srt = 1; - ///collect overlapped regions - kv_resize(uint64_t, idx->a, (ol->length<<1)); res->n = 0; - for (i = k = 0; i < on; i++) { - idx->a.a[k] = (ol->list[i].x_pos_s<<1); idx->a.a[k] <<= 32; idx->a.a[k] += i; k++; - idx->a.a[k] = (ol->list[i].x_pos_e<<1)+1; idx->a.a[k] <<= 32; idx->a.a[k] += i; k++; - ol->list[i].align_length = 0; - // fprintf(stderr, "+++[M::%s::utg%.6dl] q[%u, %u), t[%u, %u)\n", __func__, (int32_t)ol->list[i].y_id+1, - // ol->list[i].x_pos_s, ol->list[i].x_pos_e+1, - // ol->list[i].y_pos_s, ol->list[i].y_pos_e+1); - } - radix_sort_gfa64(idx->a.a, idx->a.a+k); idx->a.n = k; - for (i = 0, dp = 0, beg = 0, end = -1; i < srt_n; ++i) {///[beg, end] - old_dp = dp; - ///if idx->a.a[] is qe - if ((idx->a.a[i]>>32)&1) { - --dp; - }else { - //meet a new overlap; the overlaps are pushed by the x_pos_s - ++dp; kv_push(uint64_t, idx->a, ((uint32_t)idx->a.a[i])); - } - - ///old_dp < dp, idx->a.a[] is qs - if (old_dp < 2 && dp >= 2) { - beg = idx->a.a[i]>>33; - } else if (old_dp >= 2 && dp < 2) {///old_dp > min_dp, idx->a.a[] is qe - end = idx->a.a[i]>>33;///[beg, end] - idx->a.n = srt_n + gen_shared_trace(ol, idx->a.a+srt_n, idx->a.n-srt_n, beg, end, uref, uopt, G_CHAIN_BW, N_GCHAIN_RATE, &is_srt, res); - } - } - if(!res->n) return res->n; - - int64_t res_n = res->n; - // if(!is_srt) { - radix_sort_ul_ov_srt_qn(res->a, res->a + res->n); - for (i = 1, j = 0; i <= res_n; i++) { - if (i == res_n || res->a[i].qn != res->a[j].qn) { - if(i - j > 1) radix_sort_ul_ov_srt_qs(res->a+j, res->a+i); - j = i; - } - } - // } - - - // fprintf(stderr, "[M::%s::] res->n::%d\n", __func__, (int32_t)res->n); - // for (i = 0; i < res_n; i++) { - // fprintf(stderr, "---[M::%s::utg%.6dl] oid::%u, q[%u, %u)\n", __func__, - // (int32_t)ol->list[res->a[i].qn].y_id+1, res->a[i].qn, res->a[i].qs, res->a[i].qe); - // } - return res->n; -} - -void filter_topN(overlap_region_alloc* ol, kv_ul_ov_t *aln, uint64_t ql, uint64_t wl, uint64_t max_cov, glchain_t *ll) -{ - uint64_t i, j, k, cc, nw, cc_max = (ql*max_cov), *w_idx, *srt; overlap_region *z; - for (i = cc = 0; i < aln->n; i++) cc += aln->a[i].qe-aln->a[i].qs; - if(cc <= cc_max) return; - - nw = get_num_wins(0, ql, wl); kv_resize(uint64_t, ll->srt.a, nw+ol->length); - w_idx = ll->srt.a.a; memset(w_idx, -1, nw*sizeof((*w_idx))); srt = ll->srt.a.a + nw; - for (i = 0; i < ol->length; i++) { - ol->list[i].is_match = ol->list[i].align_length = 0; - append_unmatched_wins(&(ol->list[i]), wl); - set_sec_e_min(&(ol->list[i]), w_idx, wl, ql); - } - - for (i = 1, j = 0; i <= aln->n; i++) { - if (i == aln->n || aln->a[i].qn != aln->a[j].qn) { - z = &(ol->list[aln->a[j].qn]); z->align_length = 0; - for (k = j; k < i; k++) { - z->align_length += aln->a[k].qe-aln->a[k].qs; - assert(k <= j || aln->a[k].qs >= aln->a[k-1].qe); - } - j = i; - } - } - - int64_t sc, m, sec_err, h0, h1; - for (i = m = h0 = h1 = 0; i < ol->length; i++) { - sc = cal_sec_e_min(&(ol->list[i]), w_idx, wl, ql, NULL); - if(sc >= 0) { - srt[m] = sc; srt[m] <<= 32; srt[m] |= i; srt[m] |= ((uint64_t)0x8000000000000000); h0++; - } else { - srt[m] = -sc; srt[m] <<= 32; srt[m] |= i; h1++; - } - m++; - } - - radix_sort_gfa64(srt, srt + ol->length); - if(h1 > 0) {///have chains with negative weight - uint64_t zn = h1>>1, zt; - for (i = 0; i < zn; i++) { - zt = srt[i]; srt[i] = srt[h1-i-1]; srt[h1-i-1] = zt; - } - } - - for (m = ((int64_t)ol->length)-1, cc = 0; m >= 0 && cc <= cc_max; m--) { - cc += ol->list[(uint32_t)srt[m]].align_length; - ol->list[(uint32_t)srt[m]].is_match = 1; - } - - for (k = m = 0; k < ol->length; k++) { - ol->list[k].align_length = (uint32_t)-1; - if(!ol->list[k].is_match) continue; - ol->list[k].align_length = m; - m++; - } - - for (i = m = 0; i < aln->n; i++) { - if(ol->list[aln->a[i].qn].is_match == 0) continue; - aln->a[m] = aln->a[i]; - aln->a[m].qn = ol->list[aln->a[m].qn].align_length; - m++; - } - aln->n = m; - - overlap_region t; - for (k = m = 0; k < ol->length; k++) { - if(!ol->list[k].is_match) { - cal_sec_e_min(&(ol->list[k]), w_idx, wl, ql, &sec_err); - ol->list[k].non_homopolymer_errors = sec_err; - continue; - } - if(m != (int64_t)k) { - t = ol->list[k]; ol->list[k] = ol->list[m]; ol->list[m] = t; - } - m++; - } - ol->length = m; -} - - -uint64_t get_win_info(overlap_region *z, uint64_t wid, int64_t *ys, int64_t *ye, int64_t *err) -{ - (*err) = -2; - if((wid > 0) && (z->w_list.a[wid].y_end != -1) && (z->w_list.a[wid-1].y_end != -1) && (z->w_list.a[wid].y_end > z->w_list.a[wid-1].y_end)) { - (*ys) = z->w_list.a[wid-1].y_end+1; - (*ye) = z->w_list.a[wid].y_end; - (*err) = z->w_list.a[wid].error; - return 1; - }else if(z->w_list.a[wid].y_end == -1) { - (*ys) = (*ye) = (*err) -1; - return 1; - } - return 0; -} - -char* retrive_str_piece(All_reads *rref, const ul_idx_t *uref, char *buf, int64_t s, int64_t l, int64_t rev, int64_t id) -{ - if(rref) recover_UC_Read_sub_region(buf, s, l, rev, rref, id); - else if(uref) retrieve_u_seq(NULL, buf, &(uref->ug->u.a[id]), rev, s, l, NULL); - else return NULL; - return buf; -} - -uint64_t gen_commen_win(All_reads *rref, const ul_idx_t *uref, overlap_region_alloc* ol, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, uint64_t ql, uint64_t wl, -uint64_t *buf, uint64_t dp, char *str0, char *str1, kv_ul_ov_t *aln)///[s, e) -{ - if(!id_n) return id_n; - uint64_t i, m, k, rm_n = 0, buf_n = 0, qs, qe, wid; char *qstring, *tstring; - overlap_region *z; uint64_t ws, we; int64_t r_y[2], r_err, p_y[2], p_err; - ///shrink [qs, qe) - qs = (s/wl)*wl; if(qs < s) qs += wl; if(qs >= ql) return id_n; - qe = (e/wl)*wl; if(qe >= ql) qe = ql; - if(qs >= qe) return id_n; - //idx_a[] is sorted by aln[].qs - for (k = 0; k < id_n; k++) { - if(aln->a[id_a[k]].qs<=qs && aln->a[id_a[k]].qe>=qe) { - buf[buf_n++] = id_a[k]; - } - if(aln->a[id_a[k]].qe < e) rm_n++; - } - assert(buf_n == dp && buf_n > 1); - - if(buf_n > 0) { - ///fs = fe = (uint64_t)-1; - for (k = qs; k < qe; k += wl) { - ws = k; we = ws + wl; if(we > qe) we = qe;//[ws, we) - // fprintf(stderr, ">>>[M::%s::] w[%lu, %lu), buf_n::%lu\n", __func__, ws, we, buf_n); - ///first overlap - z = &(ol->list[aln->a[buf[0]].qn]); - wid = get_win_id_by_s(z, ws, wl, NULL); - if(!get_win_info(z, wid, &(r_y[0]), &(r_y[1]), &r_err)) continue; - // fprintf(stderr, "###[M::%s::] y[%ld, %ld), off::%ld, y_err::%ld\n", __func__, r_y[0], r_y[1], r_y[1]-r_y[0], r_err); - qstring = tstring = NULL; - for (i = 1; i < buf_n; i++) { - z = &(ol->list[aln->a[buf[i]].qn]); - wid = get_win_id_by_s(z, ws, wl, NULL); - if(!get_win_info(z, wid, &(p_y[0]), &(p_y[1]), &p_err)) break; - // fprintf(stderr, "###[M::%s::] y[%ld, %ld), off::%ld, y_err::%ld\n", __func__, p_y[0], p_y[1], p_y[1]-p_y[0], p_err); - if(((r_y[1]-r_y[0]) != (p_y[1]-p_y[0])) || (r_err != p_err)) break; - if(r_err == 0) continue; - if(r_err != -1) {///if this window ar all overlaps is unmapped - if(!qstring) { - qstring = retrive_str_piece(rref, uref, str0, r_y[0], r_y[1]+1-r_y[0], - ol->list[aln->a[buf[0]].qn].y_pos_strand, ol->list[aln->a[buf[0]].qn].y_id); - } - tstring = retrive_str_piece(rref, uref, str1, p_y[0], p_y[1]+1-p_y[0], z->y_pos_strand, z->y_id); - if(memcmp(str0, str1, (we-ws))) break; - } - } - if(i < buf_n) continue; - for (i = 0; i < buf_n; i++) { - z = &(ol->list[aln->a[buf[i]].qn]); - wid = get_win_id_by_s(z, ws, wl, NULL); - z->w_list.a[wid].extra_end = -1; - } - // if(fs == (uint64_t)-1) { - // fs = ws; fe = we; - // } else if(ws >= fs && ws <= fe) { - // if(fe < we) fe = we; - // } else { - // kv_pushp(ul_ov_t, *aln, &p); p->el = 0; p->qs = fs; p->qe = fe; - // fs = ws; fe = we; - // } - } - // if(fs != (uint64_t)-1) { - // kv_pushp(ul_ov_t, *aln, &p); p->el = 0; p->qs = fs; p->qe = fe; - // } - } - if(rm_n) { - for (i = m = 0; i < id_n; i++) { - if(aln->a[id_a[i]].qe < e) continue; - id_a[m++] = id_a[i]; - } - id_n = m; - } - return id_n; -} - - -void update_shared_intervals(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, -All_reads *rref, UC_Read* tu, kvec_t_u64_warp* idx, st_mt_t *sps, int64_t ql, int64_t wl, kv_ul_ov_t *aln, uint64_t rid) -{ - if(!aln->n) return; - uint64_t i, k, own, srt_n; int64_t dp, old_dp, beg, end; overlap_region *z; - for (i = 0; i < ol->length; i++) { - z = &(ol->list[i]); append_unmatched_wins(z, wl); - own = z->w_list.n; z->align_length = (uint32_t)-1; - for (k = 0; k < own; k++) { - if(z->w_list.a[k].extra_end < 0) z->w_list.a[k].extra_end = 0; - } - } - - kv_resize(uint64_t, idx->a, (aln->n<<1)); kv_resize(uint64_t, *sps, aln->n); - for (i = srt_n = 0; i < aln->n; i++) { - if(i == 0 || aln->a[i].qn != aln->a[i-1].qn) ol->list[aln->a[i].qn].align_length = i; - idx->a.a[srt_n] = aln->a[i].qs<<1; idx->a.a[srt_n] <<= 32; idx->a.a[srt_n] += i; srt_n++; - idx->a.a[srt_n] = ((aln->a[i].qe-1)<<1)+1; idx->a.a[srt_n] <<= 32; idx->a.a[srt_n] += i; srt_n++; - aln->a[i].el = 1; - } - - radix_sort_gfa64(idx->a.a, idx->a.a+srt_n); idx->a.n = srt_n; resize_UC_Read(tu, (wl<<1)); - for (i = 0, dp = 0, beg = 0, end = -1; i < srt_n; ++i) {///[beg, end] - old_dp = dp; - ///if idx->a.a[] is qe - if ((idx->a.a[i]>>32)&1) { - --dp; end = (idx->a.a[i]>>33)+1; - }else { - //meet a new overlap; the overlaps are pushed by the x_pos_s - ++dp; end = (idx->a.a[i]>>33); - kv_push(uint64_t, idx->a, ((uint32_t)idx->a.a[i])); - } - ///[beg, end) - // if(rid == 92) { - // fprintf(stderr, "[M::%s::input] beg::%ld, end::%ld, old_dp::%ld, dp::%ld\n", - // __func__, beg, end, old_dp, dp); - // } - if((end > beg) && (end - beg > wl) && (old_dp >= 2) ) { - idx->a.n = srt_n + - gen_commen_win(rref, uref, ol, idx->a.a+srt_n, idx->a.n-srt_n, beg, end, ql, wl, sps->a, old_dp, tu->seq, tu->seq+wl, aln); - } - beg = end; - } - - return; -} - -uint64_t kv_ul_ov_t_statistics(kv_ul_ov_t *olist, uint64_t qn, int64_t *occ) -{ - int64_t k, l = 0; - uint32_t sp = (uint32_t)-1, ep = (uint32_t)-1; - for (k = olist->n-1; k >= 0 && olist->a[k].qn == qn; k--) { - if(!(olist->a[k].el)) continue; - if(!(olist->a[k].tn&((uint32_t)(0x80000000)))) continue; - if(sp == (uint32_t)-1 || olist->a[k].qe <= sp) { - if(sp != (uint32_t)-1) l += ep - sp; - sp = olist->a[k].qs; - ep = olist->a[k].qe; - } else { - sp = MIN(sp, olist->a[k].qs); - } - (*occ)++; - } - if(sp != (uint32_t)-1) l += ep - sp; - return l; -} - -#define kv_mem(v) ((v).m * sizeof(*((v).a))) - -int64_t get_utepdat_t_mem_tid(const utepdat_t *b, int64_t tid, int64_t *mem, int64_t *mem_hab) -{ - km_stat_t kmst; memset(mem, 0, sizeof(*(mem))*6); - if(b->hab) { - mem[0] += ha_ovec_mem(b->hab[tid], mem_hab); - } - if(b->ll) { - mem[1] += kv_mem(b->ll[tid].lo) + kv_mem(b->ll[tid].tk) + kv_mem(b->ll[tid].srt.a)+ kv_mem(b->ll[tid].tc); - } - if(b->buf) { - km_stat(b->buf[tid]->km, &kmst); - mem[2] += kmst.capacity; - } - if(b->gdp) { - mem[3] += kv_mem(b->gdp[tid].l) + kv_mem(b->gdp[tid].swap) + kv_mem(b->gdp[tid].dst) + kv_mem(b->gdp[tid].out) - + kv_mem(b->gdp[tid].path) + kv_mem(b->gdp[tid].v) + kv_mem(b->gdp[tid].f) + kv_mem(b->gdp[tid].dst_done); - } - if(b->mzs) { - mem[4] += kv_mem(b->mzs[tid]); - } - if(b->sps) { - mem[5] += kv_mem(b->sps[tid]); - } - return mem[0] + mem[1] + mem[2] + mem[3] + mem[4] + mem[5]; -} - -/** -static void worker_for_ul_scall_alignment_back(void *data, long i, int tid) // callback for kt_for() -{ - utepdat_t *s = (utepdat_t*)data; - ha_ovec_buf_t *b = s->hab[tid]; - glchain_t *bl = &(s->ll[tid]); - int64_t winLen = MIN((((double)THRESHOLD_MAX_SIZE)/s->opt->diff_ec_ul), WINDOW); - uint64_t align = 0; - int fully_cov, abnormal; - void *km = s->buf?(s->buf[tid]?s->buf[tid]->km:NULL):NULL; - // if(s->id+i!=3196) return; - // fprintf(stderr, "[M::%s] rid:%ld\n", __func__, s->id+i); - // if (memcmp(UL_INF.nid.a[s->id+i].a, "d0aab024-b3a7-40fb-83cc-22c3d6d951f8", UL_INF.nid.a[s->id+i].n-1)) return; - // fprintf(stderr, "[M::%s::] ==> len: %lu\n", __func__, s->len[i]); - ha_get_ul_candidates_interface(b->abl, i, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->olist_hp, &b->clist, s->opt->bw_thres, - s->opt->max_n_chain, 1, NULL, &b->r_buf, &(b->tmp_region), NULL, &(b->sp), asm_opt.hom_cov, km); - - clear_Cigar_record(&b->cigar1); - clear_Round2_alignment(&b->round2); - // return; - // b->num_correct_base += overlap_statistics(&b->olist, NULL, 0); - - b->self_read.seq = s->seq[i]; b->self_read.length = s->len[i]; b->self_read.size = 0; - correct_ul_overlap(&b->olist, s->uu, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, - &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 1, &fully_cov, &abnormal, s->opt->diff_ec_ul, winLen, km); - - // uint64_t k; - // for (k = 0; k < b->olist.length; k++) { - // if(b->olist.list[k].is_match == 1) b->num_correct_base += b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; - // if(b->olist.list[k].is_match == 2) b->num_recorrect_base += b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; - // } - - - // gl_chain_refine(&b->olist, &b->correct, &b->hap, bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], km); - gl_chain_refine_advance(&b->olist, &b->correct, &b->hap, bl, &(s->sps[tid]), s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, km); - // return; - // b->num_read_base += b->self_read.length; - // b->num_correct_base += b->correct.corrected_base; - // b->num_recorrect_base += b->round2.dumy.corrected_base; - memset(&b->self_read, 0, sizeof(b->self_read)); - align = kv_ul_ov_t_statistics(&(bl->tk), i, &(b->num_recorrect_base)); - if(align == s->len[i]) { - free(s->seq[i]); s->seq[i] = NULL; - } - b->num_correct_base += align; - // exit(1); - // uint64_t k; - // b->num_read_base += overlap_statistics(&b->olist, NULL, NULL, 1); - // for (k = 0; k < bl->tk.n; k++) { - // if(bl->tk.a[k].sec == 0) b->num_correct_base += bl->tk.a[k].qe - bl->tk.a[k].qs; - // if(bl->tk.a[k].sec > 0) b->num_recorrect_base += bl->tk.a[k].qe - bl->tk.a[k].qs; - // } - // for (k = 0; k < bl->lo.n; k++) { - // b->num_read_base += bl->lo.a[k].qe - bl->lo.a[k].qs; - // } - - // uint32_t l1 = overlap_statistics(&b->olist, s->uu->ug, 1), l2 = overlap_statistics(&b->olist, s->uu->ug, 2); - // - // if(l1 == 0 && l2 > 0) fprintf(stderr, "[M::%s::%lu::no_match]\n", UL_INF.nid.a[s->id+i].a, s->len[i]); - // fprintf(stderr, "[M::%s::%lu::] l1->%u; l2->%u\n", UL_INF.nid.a[s->id+i].a, s->len[i], l1, l2); -} -**/ - - -overlap_region *gen_aux_ovlp(overlap_region_alloc* ol) -{ - if (ol->length + 1 > ol->size) { - uint64_t sl = ol->size; - ol->size = ol->length + 1; - kroundup64(ol->size); - REALLOC(ol->list, ol->size); - /// need to set new space to be 0 - memset(ol->list + sl, 0, sizeof(overlap_region)*(ol->size - sl)); - } - return &(ol->list[ol->length+1]); -} - - -///mode: 0->ug; 1->read -int64_t get_ecov_contain_adv(const ul_idx_t *uref, const ug_opt_t *uopt, uint32_t v, uint32_t w, int64_t bw, double diff_ec_ul, int64_t dq, int64_t *is_contain) -{ - int64_t dt = -1, dif, mm; - ma_hit_t_alloc* src = uopt->sources; - int64_t min_ovlp = uopt->min_ovlp; - int64_t max_hang = uopt->max_hang; - uint64_t z, qn, tn, x = v>>1; int32_t r = 1; asg_arc_t e; - - for (z = 0; z < src[x].length; z++) { - qn = Get_qn(src[x].buffer[z]); tn = Get_tn(src[x].buffer[z]); - if(tn != (w>>1)) continue; - r = ma_hit2arc(&(src[x].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); - if(r >= 0) { - if((e.ul>>32) != v || e.v != w) continue; - dt = e.ol; if(is_contain) (*is_contain) = 0; - break; - } else if(r == MA_HT_TCONT) {///tn is contained in qn - // if(qn == 543 && tn == 548) { - // fprintf(stderr, "[M::%s]\t%.*s\t->%.*s\tr::%d\tsrc::%c\tqry::%c\n", __func__, (int)Get_NAME_LENGTH(R_INF, qn), - // Get_NAME(R_INF, qn), (int)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), r, - // "+-"[src[x].buffer[z].rev], "+-"[((uint32_t)(v^w))]); - // } - if((src[x].buffer[z].rev == (((uint32_t)(v^w))&1)) && (tn == (w>>1))) { - dt = Get_qe(src[x].buffer[z]) - Get_qs(src[x].buffer[z]); - if(dt < Get_te(src[x].buffer[z]) - Get_ts(src[x].buffer[z])) { - dt = Get_te(src[x].buffer[z]) - Get_ts(src[x].buffer[z]); - } - if(is_contain) (*is_contain) = 1; - // fprintf(stderr, "[M::%s]\t%.*s\t->%.*s\tdt::%ld\n", __func__, (int)Get_NAME_LENGTH(R_INF, qn), - // Get_NAME(R_INF, qn), (int)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), dt); - break; - } - } - } - - if(dt < 0) return 0; - dif = (dq>dt? dq-dt:dt-dq); - mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; - // if((v>>1) == 1163 && (w>>1) == 1168) fprintf(stderr, ">>>>>>dis_q:%ld, dis_t:%ld, dif:%ld, mm:%ld\n", dis_q, dis_t, dif, mm); - if(dif <= mm) return 1; - return 0; -} - -int64_t gl_rchain_lin(overlap_region_alloc* ol, kv_ul_ov_t *res, ul_ov_t *ex, kv_rtrace_t *trace, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, bit_extz_t *exz, -int64_t trans_sc, All_reads *ridx, char* qstr, UC_Read *tu, int64_t rid, double e_rate, int64_t need_srt) -{ - if(res->n == 0) return 0; - uint32_t li_v, lj_v, rev_n; int32_t *f, *c_n, *c_sc; int64_t *p, *t, res_n = res->n, st, max_ii, max, err; - int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, qo, n_skip, end_j, plus; ul_ov_t *li, *lj, rev_t; rtrace_iter tc; - resize_Chain_Data(dp, res_n, NULL); - t = dp->tmp; f = dp->score; p = dp->pre; c_n = dp->occ; c_sc = dp->self_length; - if(need_srt) { - radix_sort_ul_ov_srt_qe(res->a, res->a + res_n); - for (i = 1, j = 0; i <= res_n; i++) { - if (i == res_n || res->a[i].qe != res->a[j].qe) { - if(i-j>1) radix_sort_ul_ov_srt_qs(res->a+j, res->a+i); - j = i; - } - } - } - - memset(t, 0, (res_n*sizeof((*t)))); - for (i = st = plus = 0, max_ii = -1; i < res_n; ++i) { - li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; - mm_ovlp = max_ovlp_src(uopt, li_v^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(i, res->a, x+G_CHAIN_INDEL); - csc = li->qe - li->qs; csc -= (((int64_t)li->sec)*trans_sc); - mm_sc = csc; mm_idx = -1; - n_skip = 0; end_j = -1; tc.k = INT32_MAX; - if ((x-st) > max_iter) st = x-max_iter; - // fprintf(stderr, "[M::%s] i::%ld, iq::[%u, %u)\n", __func__, i, li->qs, li->qe); - for (j = x; j >= st; --j) { // collect potential destination vertices - lj = &(res->a[j]); lj_v = (lj->tn<<1)|lj->rev; - if(lj->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore - if(lj->qs >= li->qs) continue;///no contain - qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) - if(li_v != lj_v && get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, NULL)) { - // fprintf(stderr, "[M::%s] j::%ld, jq::[%u, %u)\n", __func__, j, lj->qs, lj->qe); - err = get_rid_backward_cigar_err(&tc, li, trace, NULL, uref, qstr, tu, ol, NULL, exz, e_rate, lj->qe); - sc = f[j] + (li->qe - lj->qe) - (err*trans_sc); - if(sc > mm_sc) { - mm_sc = sc, mm_idx = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - } - - end_j = j; - if (max_ii < 0 || (res->a[i].qe>(res->a[max_ii].qe+max_dis))) {//too long - max = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && (res->a[i].qe<=(max_dis+res->a[j].qe)); --j) { - if (max < f[j]) { - max = f[j], max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - lj = &(res->a[max_ii]); lj_v = (lj->tn<<1)|lj->rev; - if(lj->qe > li->qs && lj->qs < li->qs) { - qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) - if(li_v != lj_v && get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, NULL)) { - ///as max_ii < end_j, get_rid_backward_cigar_err still works - // fprintf(stderr, "[M::%s] max_ii::%ld, max_ii::[%u, %u)\n", __func__, max_ii, lj->qs, lj->qe); - err = get_rid_backward_cigar_err(&tc, li, trace, NULL, uref, qstr, tu, ol, NULL, exz, e_rate, lj->qe); - sc = f[max_ii] + (li->qe - lj->qe) - (err*trans_sc); - if(sc > mm_sc) { - mm_sc = sc; mm_idx = max_ii; - } - } - } - } - if(mm_sc < 0) { - mm_sc = csc; mm_idx = -1; - } - f[i] = mm_sc; p[i] = mm_idx; - if ((max_ii < 0) || ((res->a[i].qe<=max_dis+res->a[max_ii].qe) && (f[max_ii]tn+1, i, res_n, csc, f[i], p[i], li->qs, li->qe); - } - - for (i = 0; i < res_n; ++i) {///make all f[] positive - f[i] -= plus; t[i] = ((uint64_t)f[i])<<32; t[i] += (i<<1); - } - - int64_t n_v, n_u, n_v0; - radix_sort_gfa64i(t, t + res_n); plus = 0; - for (k = res_n-1, n_v = n_u = 0; k >= 0; --k) { - n_v0 = n_v; - for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { - ex[n_v++] = res->a[i]; t[i] |= 1; i = p[i]; - } - if(n_v0 == n_v) continue; - sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); - // fprintf(stderr, "[M::%s::] n_v::%ld, n_v0::%ld, t[k]::%ld, sc::%ld\n", - // __func__, n_v, n_v0, t[k]>>32, sc); - c_n[n_u] = n_v-n_v0; c_sc[n_u] = sc; n_u++; if(sc < plus) plus = sc; - } - // fprintf(stderr, "---[M::%s] n_u:%ld, n_v:%ld\n", __func__, n_u, n_v); - for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { - n_v0 = n_v; n_v += c_n[k]; - res->a[k].qn = c_sc[k]-plus;//score - res->a[k].ts = n_v0; res->a[k].te = n_v;///idx - // fprintf(stderr, "[M::%s] k:%ld, c_sc:%d\n", __func__, k, c_sc[k]); - - rev_n = c_n[k]>>1; - ///we need to consider contained reads; so determining qs is not such easy - res->a[k].qs = (uint32_t)-1; res->a[k].qe = ex[n_v0].qe; - for (i = 0; i < rev_n; i++) { - rev_t = ex[n_v0+i]; ex[n_v0+i] = ex[n_v-i-1]; ex[n_v-i-1] = rev_t; - - if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; - if(res->a[k].qs > ex[n_v-i-1].qs) res->a[k].qs = ex[n_v-i-1].qs; - ex[n_v0+i].sec = ex[n_v-i-1].sec = SEC_MODE; - } - if(c_n[k]&1) { - if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; - ex[n_v0+i].sec = SEC_MODE; - } - } - res->n = n_u; - radix_sort_ul_ov_srt_qn(res->a, res->a + res->n);//sort by score - // if(res->n > 0) { - // fprintf(stderr, "[M::%s::rid->%ld] qlen::%ld, q::[%u, %u), sc::%u\n", - // __func__, rid, qlen, res->a[res->n-1].qs, res->a[res->n-1].qe, res->a[res->n-1].qn); - // } - return n_v; -} - - -void collapse_contain(ul_ov_t *a, int64_t a_n, int64_t i, int64_t *mm_idx, int64_t *mm_sc, int64_t *p, int32_t *s, int64_t min_s) -{ - if((*mm_idx) < 0) return; - -} - -#define rch_connect(x, i) ((((x)>>2)==(i))&&(((x)&3)!=3)) - -int64_t connect_detect(ul_ov_t *a, int64_t a_n, int64_t ai, int64_t aj, All_reads *ridx, int32_t *rch, -const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff, int64_t *p, int32_t *f, rtrace_iter *tc, -kv_rtrace_t *trace, char* qstr, UC_Read *tu, overlap_region_alloc* ol, bit_extz_t *exz, double e_rate, -int64_t trans_sc, uint32_t *is_fc) -{ - ul_ov_t *li = &(a[ai]), *lj = &(a[aj]), *lk; - uint32_t li_v, lj_v, lk_v, lqs = INT32_MAX; int64_t qo, is_c, ak, afk, err, sc = INT32_MIN, wsc; - li_v = (li->tn<<1)|li->rev; lj_v = (lj->tn<<1)|lj->rev; (*is_fc) = 0; - if(li_v == lj_v) return INT32_MIN; - //even this pair has a overlap, its length will be very small; just ignore - if(lj->qe <= li->qs) return INT32_MIN; - // if(lj->qs >= li->qs) continue;///no contain - - if((rch[aj]>>2) != ai) { - qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) - rch[aj] = (ai<<2); rch[aj] += 3; - // fprintf(stderr, "[j::%ld] (id::%u) %.*s\tqo::%ld\n", aj, lj->tn, - // (int)Get_NAME_LENGTH(R_INF, a[aj].tn), Get_NAME(R_INF, a[aj].tn), qo); - if(get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff, qo, &is_c)) { - rch[aj] = (ai<<2); rch[aj] += is_c; if(is_c) lj->el = 0; - } else { - // if(li->tn == 20171) { - // fprintf(stderr, "[j::%ld] %.*s\tconnect::0\n", aj, - // (int)Get_NAME_LENGTH(R_INF, a[aj].tn), Get_NAME(R_INF, a[aj].tn)); - // } - return INT32_MIN; - } - } - // if(li->tn == 20171) { - // fprintf(stderr, "[j::%ld] %.*s\tconnect::%u\n", aj, - // (int)Get_NAME_LENGTH(R_INF, a[aj].tn), Get_NAME(R_INF, a[aj].tn), rch_connect(rch[aj], ai)); - // } - - if(!rch_connect(rch[aj], ai)) return INT32_MIN; - is_c = rch[aj]&1; ak = afk = aj; - // fprintf(stderr, "+[j::%ld] %.*s\tis_c::%ld\n", aj, - // (int)Get_NAME_LENGTH(R_INF, a[aj].tn), Get_NAME(R_INF, a[aj].tn), is_c); - if(is_c) { - lqs = a[aj].qs; - for (ak = p[aj]; ak >= 0; ak = p[ak]) { - if((rch[ak]>>2) != ai) { - rch[ak] = (ak<<2); rch[ak] += 3; - lk = &(a[ak]); lk_v = (lk->tn<<1)|lk->rev; - if(li_v == lk_v) break; - if(lk->qe <= li->qs) break; - qo = infer_rovlp(li, lk, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) - if(!get_ecov_contain_adv(uref, uopt, li_v^1, lk_v^1, bw, diff, qo, &is_c)) break; - rch[ak] = (ai<<2); rch[ak] += is_c; - } - if(!rch_connect(rch[ak], ai)) break; - if(lqs > a[ak].qs) lqs = a[ak].qs; - is_c = rch[ak]&1; if(is_c == 0) break; - } - - afk = ak; - if((ak >= 0) && (!rch_connect(rch[ak], ai))) return INT32_MIN;///go to a disconnected node - // if(ak >= 0) { - // if(!rch_connect(rch[ak], ai)) return INT32_MIN;///go to a disconnected node - // for (ak = p[ak]; ak >= 0 && a[afk].qe <= a[ak].qe + 256; ak = p[ak]) { - // if((rch[ak]>>2) != ai) { - // rch[ak] = (ak<<2); rch[ak] += 3; - // lk = &(a[ak]); lk_v = (lk->tn<<1)|lk->rev; - // if(li_v == lk_v) return INT32_MIN; - // if(lk->qe <= li->qs) return INT32_MIN; - // qo = infer_rovlp(li, lk, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) - // if(!get_ecov_contain_adv(uref, uopt, li_v^1, lk_v^1, bw, diff, qo, &is_c)) return INT32_MIN; - // rch[ak] = (ai<<2); rch[ak] += is_c; - // } - // if(!rch_connect(rch[ak], ai)) return INT32_MIN; - // } - // } - } - // if(li->tn == 6317) { - // fprintf(stderr, "[M::%s::] [j::%ld] %.*s\tis_c::%ld\tafk::%ld\tlqs::%u\n", __func__, aj, - // (int)Get_NAME_LENGTH(R_INF, a[aj].tn), Get_NAME(R_INF, a[aj].tn), is_c, afk, lqs); - // } - ///afk >=0: reach to one non-contained read, lqs should <= li->qs - ///afk < 0: all reads are contained, lqs >= li->qs - if((afk >= 0) || (lqs <= li->qs)) { - lj = &(a[aj]); - err = get_rid_backward_cigar_err(tc, li, trace, NULL, uref, qstr, tu, ol, NULL, exz, e_rate, lj->qe); - sc = f[aj] + (li->qe - lj->qe) - (err*trans_sc); (*is_fc) = 0; - if(afk < 0) { - wsc = li->qe - li->qs; wsc -= (((int64_t)li->sec)*trans_sc); - if(sc < wsc) sc = wsc; - } - } else { - sc = li->qe - li->qs; sc -= (((int64_t)li->sec)*trans_sc); (*is_fc) = 1; - } - return sc; -} - - -int64_t max_ovlp_src_contain(const ug_opt_t *uopt, uint32_t v) -{ - ma_hit_t_alloc* src = uopt->sources; - int64_t min_ovlp = uopt->min_ovlp, max_hang = uopt->max_hang; - uint32_t i, qn, tn, o = 0, x = v>>1, dt; asg_arc_t e; int32_t r = 1; - - for (i = 0; i < src[x].length; i++) { - qn = Get_qn(src[x].buffer[i]); tn = Get_tn(src[x].buffer[i]); - r = ma_hit2arc(&(src[x].buffer[i]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), - max_hang, asm_opt.max_hang_rate, min_ovlp, &e); - // if(qn == 20171 && tn == 20172) { - // fprintf(stderr, "[r::%d]\t%.*s\t%c\tq::[%u, %u)\t%.*s\tt::[%u, %u)\n", r, - // (int)Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), "+-"[src[x].buffer[i].rev], - // Get_qs(src[x].buffer[i]), Get_qe(src[x].buffer[i]), - // (int)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), - // Get_ts(src[x].buffer[i]), Get_te(src[x].buffer[i])); - // } - if(r >= 0) { - if((e.ul>>32) != v) continue; - if(o < e.ol) o = e.ol; - } else if(r == MA_HT_TCONT) {///tn is contained in qn - if(v&1) dt = Get_qe(src[x].buffer[i]); - else dt = Get_READ_LENGTH(R_INF, qn) - Get_qs(src[x].buffer[i]); - if(o < dt) o = dt; - } - } - - return o; -} - -int64_t quick_rechain_sc(ul_ov_t *a, overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, -int64_t bw, double diff, All_reads *ridx, kv_rtrace_t *trace, char* qstr, UC_Read *tu, rtrace_iter *tc, -double e_rate, bit_extz_t *exz, int64_t trans_sc, int32_t *f, int64_t ai, int64_t aj) -{ - ul_ov_t *li = &(a[ai]), *lj = &(a[aj]); - uint32_t li_v, lj_v; int64_t qo, is_c, err, sc = INT32_MIN; - li_v = (li->tn<<1)|li->rev; lj_v = (lj->tn<<1)|lj->rev; - if(li_v == lj_v) return INT32_MIN; - if(lj->qe <= li->qs) return INT32_MIN; - if(lj->qs > li->qs) return INT32_MIN; - qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); - if(get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff, qo, &is_c)) { - if(is_c == 0) { - err = get_rid_backward_cigar_err(tc, li, trace, NULL, uref, qstr, tu, ol, NULL, exz, e_rate, lj->qe); - sc = f[aj] + (li->qe - lj->qe) - (err*trans_sc); - } - } - return sc; -} - -uint32_t if_qchain_cnn(const ul_idx_t *uref, const ug_opt_t *uopt, All_reads *ridx, int64_t bw, double diff, ul_ov_t *li, ul_ov_t *lj, int64_t *is_c, int64_t *arc_len); -void quick_rechain_propagate_transitive_reduction(const ul_idx_t *uref, const ug_opt_t *uopt, All_reads *ridx, int64_t bw, double diff, -ul_ov_t *a, int32_t a_n, int64_t ai, int32_t *rch, int32_t *f, int64_t *p, int32_t *c_n, int64_t *t, int64_t *mm_sc, -int64_t *mm_idx, int64_t *mm_n) -{ - if((*mm_idx) < 0) return; - int64_t mm_idx0 = (*mm_idx), j, k, is_c, sn; - for (j = mm_idx0 + 1; j < a_n; j++) { - t[j] = mm_idx0 - 1; - if(p[j] < 0) continue; - // if(a[ai].tn == 23989) { - // fprintf(stderr, "+chain[i::%ld] (id::%u)%.*s\t%c\tj::%ld\t%.*s\tconnect::%u\n", ai, a[ai].tn, - // (int)Get_NAME_LENGTH(R_INF, a[ai].tn), Get_NAME(R_INF, a[ai].tn), - // "+-"[a[ai].rev], j, (int)Get_NAME_LENGTH(R_INF, a[ai].tn), Get_NAME(R_INF, a[ai].tn), rch_connect(rch[j], ai)); - // } - if((rch[j]>>2) != ai) { - rch[j] = (ai<<2); rch[j] += 3; - if((a[j].el) && (if_qchain_cnn(uref, uopt, ridx, bw, diff, &(a[ai]), &(a[j]), &is_c, NULL))) { - rch[j] = (ai<<2); rch[j] += is_c; - } - } - // if(a[ai].tn == 23989) { - // fprintf(stderr, "-chain[i::%ld] (id::%u)%.*s\t%c\tj::%ld\t%.*s\tconnect::%u\n", ai, a[ai].tn, - // (int)Get_NAME_LENGTH(R_INF, a[ai].tn), Get_NAME(R_INF, a[ai].tn), - // "+-"[a[ai].rev], j, (int)Get_NAME_LENGTH(R_INF, a[ai].tn), Get_NAME(R_INF, a[ai].tn), rch_connect(rch[j], ai)); - // } - if(!rch_connect(rch[j], ai)) continue; - for (k = p[j]; k >= 0 && k > mm_idx0; k = p[k]) { - if(t[k] == mm_idx0) { - k = mm_idx0; break; - } else { - k = mm_idx0-1; break; - } - } - if (k != mm_idx0) continue; - t[j] = mm_idx0;//a[j] could reach mm_idx0; - if(p[j] != k) { - if(!(if_qchain_cnn(uref, uopt, ridx, bw, diff, &(a[j]), &(a[k]), &is_c, NULL))) continue; - } - sn = c_n[j] + 1; - if(sn >= (*mm_n)) {//must >= - (*mm_n) = sn; (*mm_idx) = j; - } - } - return; -} - - - -int64_t quick_rechain(overlap_region_alloc* ol, ul_ov_t *a, int64_t a_n, kv_rtrace_t *trace, const ul_idx_t *uref, const ug_opt_t *uopt, -int64_t bw, double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, -bit_extz_t *exz, int64_t trans_sc, All_reads *ridx, char* qstr, UC_Read *tu, double e_rate, -int32_t *f, int32_t *c_n, int32_t *c_sc, int32_t *rch, int64_t *p, int64_t *t) -{ - int64_t mm_ovlp, x, i, j, sc, csc, mm_sc, mm_idx, mm_n, sn, n_skip, end_j; - ul_ov_t *li, *lj; rtrace_iter tc; int64_t st, max_ii, max, max_n; uint32_t li_v; - memset(t, 0, (a_n*sizeof((*t)))); - - for (i = st = 0, max_ii = -1; i < a_n; ++i) { - li = &(a[i]); li_v = (li->tn<<1)|li->rev; rch[i] = INT32_MAX; - csc = li->qe - li->qs; csc -= (((int64_t)li->sec)*trans_sc); - mm_sc = INT32_MIN; mm_idx = -1; mm_n = 0; - n_skip = 0; end_j = -1; tc.k = INT32_MAX; - // if((i>=15) && (rch_connect(rch[15], 18))) { - // fprintf(stderr, ">>>[i::%ld] (id::%u)%.*s\t%c\trch[i]::%d\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), - // "+-"[a[i].rev], rch[15]); - // } - if(li->el) { - mm_ovlp = max_ovlp_src_contain(uopt, li_v^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(i, a, x+G_CHAIN_INDEL); - if ((x-st) > max_iter) st = x-max_iter; - for (j = x; j >= st; --j) { // collect potential destination vertices - lj = &(a[j]); - rch[j] = (i<<2); rch[j] += 3;//set it to unaviable - // if((i>=15) && (rch_connect(rch[15], 18))) { - // fprintf(stderr, "**j::%ld**[i::%ld] (id::%u)%.*s\t%c\trch[i]::%d\n", j, i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), - // "+-"[a[i].rev], rch[15]); - // } - if(!(lj->el)) continue; - if(lj->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore - if(lj->qs > li->qs) continue;///no contain - sc = quick_rechain_sc(a, ol, uref, uopt, bw, diff_ec_ul, ridx, trace, qstr, tu, - &tc, e_rate, exz, trans_sc, f, i, j); - if(sc == INT32_MIN) continue; - // if(li->tn == 23989) { - // fprintf(stderr, "*[i::%ld] (id::%u)%.*s\t%c\tj::%ld\t%.*s\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), - // "+-"[a[i].rev], j, (int)Get_NAME_LENGTH(R_INF, lj->tn), Get_NAME(R_INF, lj->tn)); - // } - rch[j] = (i<<2);//set it to aviable - sn = c_n[j] + 1; - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { - mm_sc = sc, mm_idx = j; mm_n = sn; - if (n_skip > 0) --n_skip; - } else if (t[j] == i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - // if((i>=15) && (rch_connect(rch[15], 18))) { - // fprintf(stderr, ">>>1[i::%ld] (id::%u)%.*s\t%c\trch[i]::%d\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), - // "+-"[a[i].rev], rch[15]); - // } - - end_j = j; - if (max_ii < 0 || (a[i].qe>(a[max_ii].qe+max_dis))) {//too long - max = INT32_MIN; max_n = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && (a[i].qe<=(max_dis+a[j].qe)); --j) { - if ((max < f[j]) || ((max == f[j]) && (max_n < c_n[j]))) { - max = f[j]; max_n = c_n[j]; max_ii = j; - } - } - } - // if((i>=15) && (rch_connect(rch[15], 18))) { - // fprintf(stderr, ">>>2[i::%ld] (id::%u)%.*s\t%c\trch[i]::%d\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), - // "+-"[a[i].rev], rch[15]); - // } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - lj = &(a[max_ii]); - if((lj->el) && (lj->qe > li->qs) && (lj->qs <= li->qs)) { - sc = quick_rechain_sc(a, ol, uref, uopt, bw, diff_ec_ul, ridx, trace, qstr, tu, - &tc, e_rate, exz, trans_sc, f, i, max_ii); - ///as max_ii < end_j, get_rid_backward_cigar_err still works - if(sc != INT32_MIN) { - sn = c_n[max_ii] + 1; - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { - mm_sc = sc; mm_idx = max_ii; mm_n = sn; - } - } - } - } - // if((i>=15) && (rch_connect(rch[15], 18))) { - // fprintf(stderr, ">>>3[i::%ld] (id::%u)%.*s\t%c\trch[i]::%d\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), - // "+-"[a[i].rev], rch[15]); - // } - sc = csc; sn = 1;///for i itself - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { - mm_sc = sc, mm_idx = -1; mm_n = sn; - } - - if(mm_sc < 0) { - mm_sc = csc; mm_idx = -1; mm_n = 1; - } - // if(li->tn == 23989) { - // fprintf(stderr, "+[i::%ld] (id::%u)%.*s\t%c\tj::%ld\t%.*s\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), - // "+-"[a[i].rev], mm_idx, mm_idx>=0?((int)Get_NAME_LENGTH(R_INF, a[mm_idx].tn)):(1), - // mm_idx>=0?(Get_NAME(R_INF, a[mm_idx].tn)):("*")); - // } - if(mm_idx >= 0) { - ///mo meed to update mm_sc and is_fc - quick_rechain_propagate_transitive_reduction(uref, uopt, ridx, bw, diff_ec_ul, a, x+1, i, rch, f, p, c_n, t, &mm_sc, &mm_idx, &mm_n); - } - // if(li->tn == 23989) { - // fprintf(stderr, "-[i::%ld] (id::%u)%.*s\t%c\tj::%ld\t%.*s\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), - // "+-"[a[i].rev], mm_idx, mm_idx>=0?((int)Get_NAME_LENGTH(R_INF, a[mm_idx].tn)):(1), - // mm_idx>=0?(Get_NAME(R_INF, a[mm_idx].tn)):("*")); - // } - } - f[i] = mm_sc; p[i] = mm_idx; c_n[i] = mm_n; - if ((max_ii < 0) || ((a[i].qe<=max_dis+a[max_ii].qe) && (f[max_ii]= 0) { - // fprintf(stderr, "i::%ld[M::%s] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", - // i, __func__, a[i].tn, (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), - // "+-"[a[i].rev], a[i].qs, a[i].qe, a[i].ts, a[i].te, !a[i].el); - t[cl++] = i; i = p[i]; - } - return cl; -} - -///ai is smaller than aj -int64_t push_trans_aln(const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, -All_reads *ridx, ul_ov_t *a, int64_t ai0, int64_t aj, int64_t *vis, int32_t *c_n) -{ - int64_t k, qo, is_c, ai = ai0, m = 0; ul_ov_t *li, *lj; uint32_t li_v, lj_v; - for (k = ai + 1; k < aj; k++) { - if(vis[k]&1) continue; - if(!(a[k].el)) continue; - // if(a[ai0].tn == 1053 || a[aj].tn == 1053) { - // fprintf(stderr, "**0**[k::%ld] ai0::%ld, ai::%ld, aj::%ld, (id::%u)%.*s\t%c\n", - // k, ai0, ai, aj, a[k].tn, (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), - // "+-"[a[k].rev]); - // } - lj = &(a[ai]); li = &(a[k]); - li_v = (li->tn<<1)|li->rev; - lj_v = (lj->tn<<1)|lj->rev; - if(lj->qe <= li->qs) continue;//even this pair has a overlap, its length will be very small; just ignore - if(lj->qs > li->qs) continue;///no contain - if(li_v == lj_v) continue; - qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) - if(!get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, &is_c)) continue; - // if(a[ai0].tn == 1053 || a[aj].tn == 1053) { - // fprintf(stderr, "**1**[k::%ld] ai0::%ld, ai::%ld, aj::%ld, (id::%u)%.*s\t%c\n", - // k, ai0, ai, aj, a[k].tn, (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), - // "+-"[a[k].rev]); - // } - if(is_c) continue; - // if(a[ai0].tn == 1053 || a[aj].tn == 1053) { - // fprintf(stderr, "**2**[k::%ld] ai0::%ld, ai::%ld, aj::%ld, (id::%u)%.*s\t%c\n", - // k, ai0, ai, aj, a[k].tn, (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), - // "+-"[a[k].rev]); - // } - - - lj = &(a[k]); li = &(a[aj]); - li_v = (li->tn<<1)|li->rev; - lj_v = (lj->tn<<1)|lj->rev; - if(lj->qe <= li->qs) continue;//even this pair has a overlap, its length will be very small; just ignore - if(lj->qs > li->qs) continue;///no contain - if(li_v == lj_v) continue; - qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) - // if(a[ai0].tn == 1053 || a[aj].tn == 1053) { - // fprintf(stderr, "**2-a**[k::%ld] ai0::%ld, ai::%ld, aj::%ld, (id::%u)%.*s\t%c, qo::%ld\n", - // k, ai0, ai, aj, a[k].tn, (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), - // "+-"[a[k].rev], qo); - // } - if(!get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, &is_c)) continue; - // if(a[ai0].tn == 1053 || a[aj].tn == 1053) { - // fprintf(stderr, "**3**[k::%ld] ai0::%ld, ai::%ld, aj::%ld, (id::%u)%.*s\t%c\n", - // k, ai0, ai, aj, a[k].tn, (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), - // "+-"[a[k].rev]); - // } - if(is_c) continue; - // if(a[ai0].tn == 1053 || a[aj].tn == 1053) - // { - // fprintf(stderr, "**4**[k::%ld] ai0::%ld, ai::%ld, aj::%ld, (id::%u)%.*s\t%c\n", - // k, ai0, ai, aj, a[k].tn, (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), - // "+-"[a[k].rev]); - // } - - // res[m] = a[k]; vis[k] |= 1; - // if(res[m].qs < idx->qs) idx->qs = res[m].qs; - // if(res[m].qe > idx->qe) idx->qe = res[m].qe; - // if(res[m].tn == 1032) { - // fprintf(stderr, "**5**[k::%ld] ai0::%ld, ai::%ld, aj::%ld, (id::%u)%.*s\t%c\n", - // k, ai0, ai, aj, a[k].tn, (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), - // "+-"[a[k].rev]); - // } - // m++; ai = k; - c_n[m++] = k; vis[k] |= 1; ai = k; - } - return m; -} - -int64_t flat_contain_adv(overlap_region_alloc* ol, All_reads *ridx, const ul_idx_t *uref, -const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, -int64_t max_dis, bit_extz_t *exz, int64_t trans_sc, char* qstr, UC_Read *tu, double e_rate, -kv_rtrace_t *trace, ul_ov_t *a, int64_t a_n, int32_t *f0, int32_t *c_n0, int32_t *c_sc0, -int32_t *rch0, int32_t *ssc0, int64_t *p0, int64_t *t0, ul_ov_t *ori_a, uint64_t *flag, -uint64_t rechain_w, int64_t *vis, ul_ov_t *idx) -{ - if(a_n <= 0) return 0; - int32_t *t = f0, *c_n = c_n0; int64_t *p = p0, *f = t0, rech = 0, nf = 0, ori_i, ori_j, ncl; uint64_t qs; - int64_t mm_ovlp, x, i, j, st, max_ii, mm_sc, mm_n, mm_idx, n_skip, end_j, qo, sc, sn, is_c, cl, csc, cl1; - uint32_t li_v, lj_v; ul_ov_t *li, *lj; int64_t max, max_n, tot_sc = INT32_MIN, tot_n = INT32_MIN, tot_i = -1; - for (i = 1, j = 0; i <= a_n; i++) { - if (i == a_n || a[i].qe != a[j].qe) { - if(i - j > 1) radix_sort_ul_ov_srt_qs(a+j, a+i); - j = i; - } - } - // fprintf(stderr, "\n[M::%s::] sc::%u\n", __func__, idx->qn); - memset(t, 0, (a_n*sizeof((*t)))); - for (i = st = 0, max_ii = -1; i < a_n; ++i) { - li = &(a[i]); li_v = (li->tn<<1)|li->rev; - flag[i] = li->sec; li->sec = ori_a[li->sec>>1].sec; - - csc = ((li->el)?(li->qe-li->qs):(0)); - mm_sc = csc; mm_n = 1; mm_idx = -1; n_skip = 0; end_j = -1; - if(flag[i]&1) {//low prority - rech++; f[i] = INT32_MIN; p[i] = mm_idx; c_n[i] = 0; continue; - } - // fprintf(stderr, "[i::%ld] (id::%u)\n", i, li->tn); - // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), - // "+-"[a[i].rev], a[i].qs, a[i].qe, a[i].ts, a[i].te, !a[i].el); - mm_ovlp = max_ovlp_src(uopt, li_v^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(i, a, x+G_CHAIN_INDEL); - - if ((x-st) > max_iter) st = x-max_iter; - for (j = x; j >= st; --j) { // collect potential destination vertices - lj = &(a[j]); lj_v = (lj->tn<<1)|lj->rev; - if(flag[j]&1) continue;//low prority - if(lj->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore - // if(lj->qs >= li->qs) continue;///no contain - if(lj->qs > li->qs) continue;///no contain, must be > instad of >= - qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) - if(li_v != lj_v && get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, &is_c)) { - if(is_c == 0) { - sc = f[j] + csc; sn = c_n[j] + 1; - // if(li->tn == 6312) { - // fprintf(stderr, "***[i::%ld] (id::%u)%.*s\t%c\tj::%ld\t%.*s\tsc::%ld\tsn::%ld\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), - // "+-"[a[i].rev], j, (int)Get_NAME_LENGTH(R_INF, a[j].tn), Get_NAME(R_INF, a[j].tn), - // sc, sn); - // } - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { - mm_sc = sc, mm_idx = j; mm_n = sn; - if (n_skip > 0) --n_skip; - } else if (t[j] == i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - } - } - - end_j = j; - if (max_ii < 0 || ((a[i].qe) > (a[max_ii].qe+max_dis))) {//too long - max = INT32_MIN; max_n = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && (a[i].qe<=(max_dis+a[j].qe)); --j) { - if ((max < f[j]) || ((max == f[j]) && (max_n < c_n[j]))) { - max = f[j]; max_n = c_n[j]; max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - lj = &(a[max_ii]); lj_v = (lj->tn<<1)|lj->rev; - if((lj->qe > li->qs) && (lj->qs <= li->qs) && (!(flag[max_ii]&1))) { - qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) - if(li_v != lj_v && get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, &is_c)) { - if(is_c == 0) { - sc = f[max_ii] + csc; sn = c_n[max_ii] + 1; - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { - mm_sc = sc; mm_idx = max_ii; mm_n = sn; - } - } - } - } - } - - f[i] = mm_sc; p[i] = mm_idx; c_n[i] = mm_n; - if ((max_ii < 0) || ((a[i].qe<=max_dis+a[max_ii].qe) && (f[max_ii]tn); - cl = 0; i = tot_i; t = NULL; - while (i >= 0) { - flag[cl] |= (((uint64_t)i)<<32); - i = p[i]; cl++; - } - // fprintf(stderr, "+++[i::%ld] (cl::%ld)\n", i, cl); - - st = flag[cl-1]>>32; qs = a[st].qs; cl1 = 0; - // fprintf(stderr, "[M::%s] qs::%lu\trechain_w::%lu\trech::%ld\tcl::%ld\n", - // __func__, qs, rechain_w, rech, cl); - if((qs <= rechain_w) && (rech > 0)) { - for (i = nf = 0; i < cl; i++) { - st = flag[cl-i-1]>>32; - if(a[st].el) break; - if((a[st].ts == 0) && (a[st].te == Get_READ_LENGTH(R_INF, a[st].tn))) nf++; - } - if(i < cl && a[st].qs > qs && nf > 0) { - - cl1 = quick_rechain(ol, a, st+1, trace, uref, uopt, bw, diff_ec_ul, qlen, max_skip, max_iter, max_dis, - exz, trans_sc, ridx, qstr, tu, e_rate, f0, c_n0, c_sc0, rch0, p0, t0); - // fprintf(stderr, "st::%ld\tcl1::%ld[M::%s]\t(id::%u)\t%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", - // st, cl1, __func__, a[st].tn, (int)Get_NAME_LENGTH(R_INF, a[st].tn), Get_NAME(R_INF, a[st].tn), - // "+-"[a[st].rev], a[st].qs, a[st].qe, a[st].ts, a[st].te, !a[st].el); - - // fprintf(stderr, "i::%ld\t[M::%s]\t(id::%u)\t%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", - // i, __func__, a[t0[cl1-1]].tn, (int)Get_NAME_LENGTH(R_INF, a[t0[cl1-1]].tn), - // Get_NAME(R_INF, a[t0[cl1-1]].tn), "+-"[a[t0[cl1-1]].rev], a[t0[cl1-1]].qs, a[t0[cl1-1]].qe, - // a[t0[cl1-1]].ts, a[t0[cl1-1]].te, !a[t0[cl1-1]].el); - - if(cl1 > 0 && a[t0[cl1-1]].qs <= qs) { - cl = cl-i-1; assert(st == t0[0]); - for (i = 0; i < cl1; i++) { - flag[cl] <<= 32; flag[cl] >>= 32; - flag[cl] |= ((uint64_t)t0[i])<<32; cl++; - } - } - } - } - // fprintf(stderr, "---[i::%ld] (cl::%ld)\n", i, cl); - for (i = 0; i < cl; i++) { - // fprintf(stderr, "[i::%ld] flag[cl-i-1]>>32::%lu\n", i, flag[cl-i-1]>>32); - t0[i] = flag[cl-i-1]>>32; - vis[((uint32_t)flag[t0[i]])>>1] |= 1;///set as used - // fprintf(stderr, "[i::%ld]\t%.*s\traw_i::%u\n", i, - // (int)Get_NAME_LENGTH(R_INF, a[t0[i]].tn), Get_NAME(R_INF, a[t0[i]].tn), ((uint32_t)flag[t0[i]])>>1); - // flag[cl-i-1] = (uint32_t)flag[cl-i-1]; - } - - i = 0; ncl = 0; - if(cl1 > 1) { - // for (i = 0; i < cl; i++) vis[((uint32_t)flag[t0[i]])>>1] |= 1;///set as used - for (i = 0; i < cl1; i++) { - if(flag[t0[i]]&1) flag[t0[i]]-=1; - vis[((uint32_t)flag[t0[i]])>>1] |= 1; - c_n[ncl++] = ((uint32_t)flag[t0[i]])>>1; - - // a[ncl] = a[t0[i]]; - // if(a[ncl].qs < idx->qs) idx->qs = a[ncl].qs; - // if(a[ncl].qe > idx->qe) idx->qe = a[ncl].qe; - // fprintf(stderr, "[ncl::%ld]\t%.*s\n", ncl, - // (int)Get_NAME_LENGTH(R_INF, a[ncl].tn), Get_NAME(R_INF, a[ncl].tn)); - // ncl++; - - if(i < cl1 - 1) { - ori_i = ((uint32_t)flag[t0[i]])>>1; - ori_j = ((uint32_t)flag[t0[i+1]])>>1; - ncl += push_trans_aln(uref, uopt, bw, diff_ec_ul, ridx, ori_a, ori_i, ori_j, vis, c_n+ncl); - } - } - } - - - for (; i < cl; i++) { - ///t0[i] -> idx of a; (uint32_t)flag[t0[i]] -> idx of ori_a - if(flag[t0[i]]&1) flag[t0[i]]-=1; - vis[((uint32_t)flag[t0[i]])>>1] |= 1; - c_n[ncl++] = ((uint32_t)flag[t0[i]])>>1; - // a[ncl] = a[t0[i]]; - // if(a[ncl].qs < idx->qs) idx->qs = a[ncl].qs; - // if(a[ncl].qe > idx->qe) idx->qe = a[ncl].qe; - // fprintf(stderr, "[ncl::%ld]\t%.*s\n", ncl, - // (int)Get_NAME_LENGTH(R_INF, a[ncl].tn), Get_NAME(R_INF, a[ncl].tn)); - // ncl++; - // fprintf(stderr, "[M::%s] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", - // __func__, a[i].tn, (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), - // "+-"[a[i].rev], a[i].qs, a[i].qe, a[i].ts, a[i].te, !a[i].el); - } - assert(ncl >= cl); - if(ncl <= 0) return ncl; - - idx->qs = ori_a[c_n[0]].qs; - idx->qe = ori_a[c_n[0]].qe; - for (i = 0; i < ncl; i++) { - a[i] = ori_a[c_n[i]]; - if(a[i].qs < idx->qs) idx->qs = a[i].qs; - if(a[i].qe > idx->qe) idx->qe = a[i].qe; - } - return ncl; -} - - -int64_t flat_contain(All_reads *ridx, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, -ul_ov_t *a, int64_t a_n, int32_t *t, int32_t *c_n, int64_t *p, int64_t *f, ul_ov_t *idx) -{ - if(a_n <= 0) return 0; - int64_t mm_ovlp, x, i, j, st, max_ii, mm_sc, mm_n, mm_idx, n_skip, end_j, qo, sc, sn, is_c, cl, csc; - uint32_t li_v, lj_v; ul_ov_t *li, *lj; int64_t max, max_n, tot_sc = INT32_MIN, tot_n = INT32_MIN, tot_i = -1; - for (i = 1, j = 0; i <= a_n; i++) { - if (i == a_n || a[i].qe != a[j].qe) { - if(i - j > 1) radix_sort_ul_ov_srt_qs(a+j, a+i); - j = i; - } - } - // fprintf(stderr, "\n[M::%s::] sc::%u\n", __func__, idx->qn); - memset(t, 0, (a_n*sizeof((*t)))); - for (i = st = 0, max_ii = -1; i < a_n; ++i) { - li = &(a[i]); li_v = (li->tn<<1)|li->rev; - // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), - // "+-"[a[i].rev], a[i].qs, a[i].qe, a[i].ts, a[i].te, !a[i].el); - mm_ovlp = max_ovlp_src(uopt, li_v^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(i, a, x+G_CHAIN_INDEL); csc = ((li->el)?(li->qe-li->qs):(0)); - mm_sc = csc; mm_n = 1; mm_idx = -1; n_skip = 0; end_j = -1; - if ((x-st) > max_iter) st = x-max_iter; - for (j = x; j >= st; --j) { // collect potential destination vertices - lj = &(a[j]); lj_v = (lj->tn<<1)|lj->rev; - if(lj->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore - // if(lj->qs >= li->qs) continue;///no contain - qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) - if(li_v != lj_v && get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, &is_c)) { - if(is_c == 0) { - sc = f[j] + csc; sn = c_n[j] + 1; - // if(li->tn == 20171) { - // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tj::%ld\tsc::%ld\tsn::%ld\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), - // "+-"[a[i].rev], j, sc, sn); - // } - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { - mm_sc = sc, mm_idx = j; mm_n = sn; - if (n_skip > 0) --n_skip; - } else if (t[j] == i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - } - } - - end_j = j; - if (max_ii < 0 || ((a[i].qe) > (a[max_ii].qe+max_dis))) {//too long - max = INT32_MIN; max_n = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && (a[i].qe<=(max_dis+a[j].qe)); --j) { - if ((max < f[j]) || ((max == f[j]) && (max_n < c_n[j]))) { - max = f[j]; max_n = c_n[j]; max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - lj = &(a[max_ii]); lj_v = (lj->tn<<1)|lj->rev; - if(lj->qe > li->qs && lj->qs < li->qs) { - qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) - if(li_v != lj_v && get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, &is_c)) { - if(is_c == 0) { - sc = f[max_ii] + csc; sn = c_n[max_ii] + 1; - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { - mm_sc = sc; mm_idx = max_ii; mm_n = sn; - } - } - } - } - } - - f[i] = mm_sc; p[i] = mm_idx; c_n[i] = mm_n; - if ((max_ii < 0) || ((a[i].qe<=max_dis+a[max_ii].qe) && (f[max_ii]= 0) { - t[cl++] = i; i = p[i]; - } - idx->qs = a[t[cl-1]].qs; idx->qe = a[t[cl-1]].qe; - for (i = 0; i < cl; i++) { - a[i] = a[t[cl-i-1]]; - if(a[i].qs < idx->qs) idx->qs = a[i].qs; - if(a[i].qe > idx->qe) idx->qe = a[i].qe; - } - return cl; -} - - -///li is the suffix -uint32_t if_qchain_cnn(const ul_idx_t *uref, const ug_opt_t *uopt, All_reads *ridx, int64_t bw, double diff, ul_ov_t *li, ul_ov_t *lj, int64_t *is_c, int64_t *arc_len) -{ - uint32_t li_v = (li->tn<<1)|li->rev, lj_v = (lj->tn<<1)|lj->rev; int64_t qo; - if((li_v == lj_v) || (lj->qe <= li->qs)) return 0; - qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) - if(get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff, qo, is_c)) return 1; - return 0; -} - -void propagate_transitive_reduction(const ul_idx_t *uref, const ug_opt_t *uopt, All_reads *ridx, int64_t bw, double diff, -ul_ov_t *a, int32_t a_n, int64_t ai, int32_t *rch, int32_t *f, int64_t *p, int32_t *c_n, int64_t *t, int64_t *mm_sc, -int64_t *mm_idx, int64_t *mm_n) -{ - if((*mm_idx) < 0) return; - int64_t mm_idx0 = (*mm_idx), j, k, is_c, sn; - for (j = mm_idx0 + 1; j < a_n; j++) { - t[j] = mm_idx0 - 1; - if(p[j] < 0) continue; - if((rch[j]>>2) != ai) { - rch[j] = (ai<<2); rch[j] += 3; - if(if_qchain_cnn(uref, uopt, ridx, bw, diff, &(a[ai]), &(a[j]), &is_c, NULL)) { - rch[j] = (ai<<2); rch[j] += is_c; - } - } - if(!rch_connect(rch[j], ai)) continue; - for (k = p[j]; k >= 0 && k > mm_idx0; k = p[k]) { - if(t[k] == mm_idx0) { - k = mm_idx0; break; - } else { - k = mm_idx0-1; break; - } - } - if (k != mm_idx0) continue; - t[j] = mm_idx0;//a[j] could reach mm_idx0; - if(p[j] != k) { - if(!(if_qchain_cnn(uref, uopt, ridx, bw, diff, &(a[j]), &(a[k]), &is_c, NULL))) continue; - } - sn = c_n[j] + 1; - if(sn >= (*mm_n)) {//must >= - (*mm_n) = sn; (*mm_idx) = j; - } - } - return; -} - - -int64_t gl_rchain_lin_contain(overlap_region_alloc* ol, kv_ul_ov_t *res, ul_ov_t *ex, kv_rtrace_t *trace, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, bit_extz_t *exz, uint64_t *a, -int64_t trans_sc, All_reads *ridx, char* qstr, UC_Read *tu, int64_t rid, double e_rate, int64_t need_srt) -{ - if(res->n == 0) return 0; - uint32_t li_v, rev_n, is_fc, cc; int32_t *f, *c_n, *c_sc, *rch, *ssc; int64_t *p, *t, res_n = res->n, st, max_ii, max, max_n; - int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, mm_n, sn, n_skip, end_j, plus; ul_ov_t *li, *lj, rev_t; rtrace_iter tc; - resize_Chain_Data(dp, res_n, NULL); - t = dp->tmp; f = dp->score; p = dp->pre; c_n = dp->occ; - c_sc = rch = dp->self_length; ssc = dp->indels; - if(need_srt) { - radix_sort_ul_ov_srt_qe(res->a, res->a + res_n); - for (i = 1, j = 0; i <= res_n; i++) { - res->a[i-1].qs = ((uint32_t)-1)-res->a[i-1].qs; - if (i == res_n || res->a[i].qe != res->a[j].qe) { - if(i - j > 1) radix_sort_ul_ov_srt_qs(res->a+j, res->a+i); - j = i; - } - } - } - - memset(t, 0, (res_n*sizeof((*t)))); - for (i = st = plus = 0, max_ii = -1; i < res_n; ++i) { - li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; li->qs = ((uint32_t)-1)-li->qs; - rch[i] = INT32_MAX; ssc[i] = INT32_MIN; a[i] = ((uint64_t)-1); - mm_ovlp = max_ovlp_src_contain(uopt, li_v^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - // if(li->tn == 20171 || li->tn == 20209 || li->tn == 20204) { - // fprintf(stderr, "\n[i::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\tmax_d::%ld\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, res->a[i].tn), Get_NAME(R_INF, res->a[i].tn), - // "+-"[res->a[i].rev], res->a[i].qs, res->a[i].qe, res->a[i].ts, res->a[i].te, - // !res->a[i].el, x+G_CHAIN_INDEL); - // } - x = find_ul_ov_max(i, res->a, x+G_CHAIN_INDEL); - // if(li->tn == 20171 || li->tn == 20209 || li->tn == 20204) { - // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\tmax_j::%ld\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, res->a[i].tn), Get_NAME(R_INF, res->a[i].tn), - // "+-"[res->a[i].rev], res->a[i].qs, res->a[i].qe, res->a[i].ts, res->a[i].te, - // !res->a[i].el, x); - // } - csc = li->qe - li->qs; csc -= (((int64_t)li->sec)*trans_sc); - // mm_sc = csc; mm_idx = -1; mm_n = 1; - mm_sc = INT32_MIN; mm_idx = -1; mm_n = 0; is_fc = 0; - n_skip = 0; end_j = -1; tc.k = INT32_MAX; - if ((x-st) > max_iter) st = x-max_iter; - for (j = x; j >= st; --j) { // collect potential destination vertices - lj = &(res->a[j]); - if(lj->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore - sc = connect_detect(res->a, res->n, i, j, ridx, rch, uref, uopt, bw, diff_ec_ul, p, f, &tc, - trace, qstr, tu, ol, exz, e_rate, trans_sc, &cc); - if(sc == INT32_MIN) continue; - sn = c_n[j] + 1; - // if(li->tn == 6312 || li->tn == 6322 || li->tn == 6317 || li->tn == 6319/** && lj->tn == 6329**/) { - // fprintf(stderr, "(id::%u)%.*s\t%c\t(id::%u)%.*s\t%c\tsc::%ld\tsn::%ld\tc_n[j]::%d\tmsc::%ld\ti::%ld\tj::%ld\tm_idx::%ld\n", - // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], - // lj->tn, (int)Get_NAME_LENGTH(R_INF, lj->tn), Get_NAME(R_INF, lj->tn), "+-"[lj->rev], - // sc, sn, c_n[j], mm_sc, i, j, mm_idx); - // } - // if(li->tn == 20209) { - // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tj::%ld\tsc::%ld\tsn::%ld\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, res->a[i].tn), Get_NAME(R_INF, res->a[i].tn), - // "+-"[res->a[i].rev], j, sc, sn); - // } - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { - mm_sc = sc, mm_idx = j; mm_n = sn; is_fc = cc; - if (n_skip > 0) --n_skip; - } else if (t[j] == i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - - end_j = j; - if (max_ii < 0 || (res->a[i].qe>(res->a[max_ii].qe+max_dis))) {//too long - max = INT32_MIN; max_n = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && (res->a[i].qe<=(max_dis+res->a[j].qe)); --j) { - if ((max < f[j]) || ((max == f[j]) && (max_n < c_n[j]))) { - max = f[j]; max_n = c_n[j]; max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - lj = &(res->a[max_ii]); - if(lj->qe > li->qs/** && lj->qs < li->qs**/) { - ///as max_ii < end_j, get_rid_backward_cigar_err still works - sc = connect_detect(res->a, res->n, i, max_ii, ridx, rch, uref, uopt, bw, diff_ec_ul, p, f, &tc, - trace, qstr, tu, ol, exz, e_rate, trans_sc, &cc); - if(sc != INT32_MIN) { - sn = c_n[max_ii] + 1; - // if(li->tn == 6312 || li->tn == 6322 || li->tn == 6317 || li->tn == 6319/** && lj->tn == 6329**/) { - // fprintf(stderr, "(id::%u)%.*s\t%c\t(id::%u)%.*s\t%c\tsc::%ld\tsn::%ld\tc_n[j]::%d\tmsc::%ld\ti::%ld\tmax_ii::%ld\tm_idx::%ld\n", - // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], - // lj->tn, (int)Get_NAME_LENGTH(R_INF, lj->tn), Get_NAME(R_INF, lj->tn), "+-"[lj->rev], - // sc, sn, c_n[j], mm_sc, i, max_ii, mm_idx); - // } - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { - mm_sc = sc; mm_idx = max_ii; mm_n = sn; is_fc = cc; - } - } - } - } - - sc = csc; sn = 1;///for i itself - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { - mm_sc = sc, mm_idx = -1; mm_n = sn; is_fc = 0; - } - - if(mm_sc < 0) { - mm_sc = csc; mm_idx = -1; mm_n = 1; - } - - // if(li->tn == 6317) { - // fprintf(stderr, "+(id::%u)%.*s\t%c\tmm_idx::%ld\tmm_sc::%ld\tmm_n::%ld\n", - // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], mm_idx, mm_sc, mm_n); - // } - - if(mm_idx >= 0) { - ///mo meed to update mm_sc and is_fc - propagate_transitive_reduction(uref, uopt, ridx, bw, diff_ec_ul, res->a, x+1, i, rch, f, p, c_n, t, &mm_sc, &mm_idx, &mm_n); - } - // if(li->tn == 6317) { - // fprintf(stderr, "-(id::%u)%.*s\t%c\tmm_idx::%ld\tmm_sc::%ld\tmm_n::%ld\n", - // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], mm_idx, mm_sc, mm_n); - // } - // collapse_contain(res->a, res_n, i, &mm_idx, &mm_sc, p, c_sc, end_j); - - f[i] = mm_sc; p[i] = mm_idx; c_n[i] = mm_n; - if(mm_idx < 0 || ((ssc[mm_idx] < mm_sc) && (is_fc == 0))) ssc[i] = mm_sc; - else ssc[i] = ssc[mm_idx]; - - if ((max_ii < 0) || ((res->a[i].qe<=max_dis+res->a[max_ii].qe) && (f[max_ii]tn == 20171 || li->tn == 20209 || li->tn == 20204) { - // fprintf(stderr, "[i::%ld]\tf::%d\tp::%ld\n", i, f[i], p[i]); - // } - - } - - for (i = 0; i < res_n; ++i) {///make all f[] positive - ssc[i] -= plus; t[i] = ((uint64_t)ssc[i])<<32; t[i] += (i<<1); - } - - int64_t n_v, n_u, n_v0; - radix_sort_gfa64i(t, t + res_n); plus = 0; - for (k = res_n-1, n_v = n_u = 0; k >= 0; --k) { - n_v0 = n_v; - for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { - ex[n_v++] = res->a[i]; t[i] |= 1; i = p[i]; - } - if(n_v0 == n_v) continue; - sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); - c_n[n_u] = n_v-n_v0; c_sc[n_u] = sc; n_u++; if(sc < plus) plus = sc; - } - // fprintf(stderr, "---[M::%s] n_u:%ld, n_v:%ld\n", __func__, n_u, n_v); - for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { - n_v0 = n_v; n_v += c_n[k]; - res->a[k].qn = c_sc[k]-plus;//score - res->a[k].ts = n_v0; res->a[k].te = n_v;///idx - // fprintf(stderr, "[M::%s] k:%ld, c_sc:%d\n", __func__, k, c_sc[k]); - - rev_n = c_n[k]>>1; - ///we need to consider contained reads; so determining qs is not such easy - // res->a[k].qs = (uint32_t)-1; res->a[k].qe = ex[n_v0].qe; - for (i = 0; i < rev_n; i++) { - rev_t = ex[n_v0+i]; ex[n_v0+i] = ex[n_v-i-1]; ex[n_v-i-1] = rev_t; - // if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; - // if(res->a[k].qs > ex[n_v-i-1].qs) res->a[k].qs = ex[n_v-i-1].qs; - ex[n_v0+i].sec = ex[n_v-i-1].sec = SEC_MODE; - } - if(c_n[k]&1) { - // if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; - ex[n_v0+i].sec = SEC_MODE; - } - // flat_contain(ex+n_v0, n_v-n_v0); - res->a[k].te = res->a[k].ts + flat_contain(ridx, uref, uopt, bw, diff_ec_ul, qlen, max_skip, max_iter, max_dis, - ex + res->a[k].ts, res->a[k].te - res->a[k].ts, f, ssc, p, t, &(res->a[k])); - } - res->n = n_u; - radix_sort_ul_ov_srt_qn(res->a, res->a + res->n);//sort by score - - // if(res->n > 0) { - // fprintf(stderr, "[M::%s::rid->%ld] qlen::%ld, q::[%u, %u), sc::%u\n", - // __func__, rid, qlen, res->a[res->n-1].qs, res->a[res->n-1].qe, res->a[res->n-1].qn); - // } - return n_v; -} - - -int64_t gen_trans_aln(overlap_region_alloc* ol, All_reads *ridx, const ul_idx_t *uref, -const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, int64_t qlen, uint64_t *id, int64_t idn, -ul_ov_t *a, int64_t a_n, uint64_t qs, uint64_t qe, int64_t *vis, int32_t *f0, int32_t *c_n0, -int32_t *c_sc0, int32_t *rch0, int32_t *ssc0, int64_t *p0, int64_t *t0, int64_t max_skip, -int64_t max_iter, int64_t max_dis, bit_extz_t *exz, int64_t trans_sc, char* qstr, UC_Read *tu, -double e_rate, kv_rtrace_t *trace, uint32_t rechain_w, ul_ov_t *res, ul_ov_t *rr) -{ - if(idn == 0) return 0; - int64_t k, l, i, j, z, nv = 0, qo, is_c, nf; - ul_ov_t *li, *lj; uint32_t li_v, lj_v, update, tipl = 0, mm = ((uint32_t)(0x20000000U)); - // for (i = 0; i < idn; i++) { - // li = &(a[id[i]]); - // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", - // i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), - // "+-"[li->rev], li->qs, li->qe, li->ts, li->te, !li->el); - // } - for (i = nf = 0; i < idn; i++) { - if(a[id[i]].el) break; - if((a[id[i]].ts == 0) && (a[id[i]].te == Get_READ_LENGTH(R_INF, a[id[i]].tn))) nf++; - } - if(i < idn && nf > 0) { - if((a[id[i]].qs > qs) && (qs <= rechain_w)) { - tipl = qs; ///there are contained chains beforehand - } - } - - for (i = 0, k = l = -1; i < idn; i++) { - k = id[i]; - if(k - l > 1) { - if(l < 0) { - for (l = k-1; l >= 0 && a[l].qe > qs; l--); - } - - for (z = l + 1; z < k; z++) { - li = &(a[z]); li_v = (li->tn<<1)|li->rev; - if((!(li->el))||(vis[z]&1)) continue; - if(!(((li->qs + tipl) >= qs) && (li->qe < qe))) continue; - for (j = i-1, update = 1; j >= 0; --j) { - lj = &(a[id[j]]); lj_v = (lj->tn<<1)|lj->rev; - if(lj->qe <= li->qs) break; - qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) - if((li_v == lj_v) || (!get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, - bw, diff_ec_ul, qo, &is_c))) { - update = 0; break; - } - } - // if(li->tn == 6312) { - // fprintf(stderr, "[z::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\tnf::%ld\ttipl::%u\tl::%ld\tk::%ld\tupdate::%u\n", z, li->tn, - // (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), - // "+-"[li->rev], li->qs, li->qe, li->ts, li->te, !li->el, nf, tipl, l, k, update); - // } - if(update) { - res[nv] = a[z]; res[nv].sec = (z<<1) + ((li->qs>=qs)?0:1); nv++; - } - } - } - l = k; - - li = &(a[k]); li_v = (li->tn<<1)|li->rev; - for (j = nv-1; j >= 0; --j) { - lj = &(res[j]); lj_v = (lj->tn<<1)|lj->rev; - if(lj->qe <= li->qs) break; - if(lj->qn == (uint32_t)-1) continue;//deleted - if((lj->sec&mm)) continue;//could not be deleted - qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) - if((li_v == lj_v) || (!get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, - bw, diff_ec_ul, qo, &is_c))) { - // if(lj->tn == 6312) { - // fprintf(stderr, "delete::(id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", - // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), - // "+-"[li->rev], li->qs, li->qe, li->ts, li->te, !li->el); - // } - res[j].qn = res[j].tn = (uint32_t)-1; - } - } - res[nv] = a[k]; res[nv].sec = k; res[nv].sec<<=1; res[nv].sec |= mm; nv++; - } - - k = a_n; i = idn; - if(k - l > 1) { - for (z = l + 1; z < k; z++) { - li = &(a[z]); li_v = (li->tn<<1)|li->rev; - if((!(li->el))||(vis[z]&1)) continue; - if(!(((li->qs + tipl) >= qs) && (li->qe < qe))) continue; - for (j = i-1, update = 1; j >= 0; --j) { - lj = &(a[id[j]]); lj_v = (lj->tn<<1)|lj->rev; - if(lj->qe <= li->qs) break; - qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) - if((li_v == lj_v) || (!get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, - bw, diff_ec_ul, qo, &is_c))) { - update = 0; break; - } - } - if(update) { - res[nv] = a[z]; res[nv].sec = (z<<1) + ((li->qs>=qs)?0:1); nv++; - } - } - } - // fprintf(stderr, "\n[M::%s::] old_n::%ld, new_n::%ld\n", __func__, idn, nv); - for (i = k = 0; i < nv; i++) { - if(res[i].qn == (uint32_t)-1) continue; - res[k] = res[i]; - if(res[k].sec&mm) res[k].sec -= mm; k++; - // res[k] = res[i]; - // id[k] = res[k].sec; - // if(id[k]&mm) id[k] -= mm; - // id[k] >>= 1; - // if(res[k].sec&1) id[k] |= ((uint64_t)(0x100000000U));///low prority - // // if(res[k].sec&mm) id[k] |= ((uint64_t)(0x200000000U));//orignal alignments - // k++; - - // fprintf(stderr, "[k::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\tnew::%u\n", k, - // res[k].tn,(int)Get_NAME_LENGTH(R_INF, res[k].tn), Get_NAME(R_INF, res[k].tn), - // "+-"[res[k].rev], res[k].qs, res[k].qe, res[k].ts, res[k].te, !res[k].el, - // (res[k].sec != SEC_MODE)); - // if(res[k].sec != SEC_MODE) vis[res[k].sec>>1] |= 1; - // res[k].sec = SEC_MODE; k++; - } - nv = idn = k; - nv = flat_contain_adv(ol, ridx, uref, uopt, bw, diff_ec_ul, qlen, max_skip, max_iter, max_dis, - exz, trans_sc, qstr, tu, e_rate, trace, res, nv, f0, c_n0, c_sc0, rch0, ssc0, p0, t0, a, id, - rechain_w, vis, rr); - // f, ssc, p, t, &(res->a[k])); - // for (k = 0; k < idn; k++) { - // if(((uint32_t)id[k])&1) continue; - // vis[((uint32_t)id[k])>>1] |= 1; - // } - return nv; -} - -int64_t gl_rchain_lin_contain_adv(overlap_region_alloc* ol, kv_ul_ov_t *res, ul_ov_t *ex, kv_rtrace_t *trace, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, bit_extz_t *exz, uint64_t *id, -int64_t trans_sc, All_reads *ridx, char* qstr, UC_Read *tu, int64_t rid, double e_rate, int64_t need_srt) -{ - if(res->n == 0) return 0; - uint32_t li_v, rev_n, is_fc, cc, idn, mqs, mqe; int32_t *f, *c_n, *c_sc, *rch, *ssc; int64_t *p, *t, res_n = res->n, st, max_ii, max, max_n; - int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, mm_n, sn, n_skip, end_j, plus; ul_ov_t *li, *lj, rr, mrr; rtrace_iter tc; uint64_t ovlp; - resize_Chain_Data(dp, res_n<<1, NULL);///res_n<<1 - t = dp->tmp; f = dp->score; p = dp->pre; c_n = dp->occ; - c_sc = rch = dp->self_length; ssc = dp->indels; - if(need_srt) { - radix_sort_ul_ov_srt_qe(res->a, res->a + res_n); - for (i = 1, j = 0; i <= res_n; i++) { - res->a[i-1].qs = ((uint32_t)-1)-res->a[i-1].qs; - if (i == res_n || res->a[i].qe != res->a[j].qe) { - if(i - j > 1) radix_sort_ul_ov_srt_qs(res->a+j, res->a+i); - j = i; - } - } - } - - memset(t, 0, (res_n*sizeof((*t)))); - for (i = st = plus = 0, max_ii = -1; i < res_n; ++i) { - li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; li->qs = ((uint32_t)-1)-li->qs; - rch[i] = INT32_MAX; ssc[i] = INT32_MIN; - mm_ovlp = max_ovlp_src_contain(uopt, li_v^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - // if(li->tn == 20171 || li->tn == 20209 || li->tn == 20204) { - // fprintf(stderr, "\n[i::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\tmax_d::%ld\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, res->a[i].tn), Get_NAME(R_INF, res->a[i].tn), - // "+-"[res->a[i].rev], res->a[i].qs, res->a[i].qe, res->a[i].ts, res->a[i].te, - // !res->a[i].el, x+G_CHAIN_INDEL); - // } - x = find_ul_ov_max(i, res->a, x+G_CHAIN_INDEL); - // if(li->tn == 6312) { - // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\tmax_j::%ld\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, res->a[i].tn), Get_NAME(R_INF, res->a[i].tn), - // "+-"[res->a[i].rev], res->a[i].qs, res->a[i].qe, res->a[i].ts, res->a[i].te, - // !res->a[i].el, x); - // } - csc = li->qe - li->qs; csc -= (((int64_t)li->sec)*trans_sc); - // mm_sc = csc; mm_idx = -1; mm_n = 1; - mm_sc = INT32_MIN; mm_idx = -1; mm_n = 0; is_fc = 0; - n_skip = 0; end_j = -1; tc.k = INT32_MAX; - if ((x-st) > max_iter) st = x-max_iter; - for (j = x; j >= st; --j) { // collect potential destination vertices - lj = &(res->a[j]); - if(lj->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore - sc = connect_detect(res->a, res->n, i, j, ridx, rch, uref, uopt, bw, diff_ec_ul, p, f, &tc, - trace, qstr, tu, ol, exz, e_rate, trans_sc, &cc); - if(sc == INT32_MIN) continue; - sn = c_n[j] + 1; - // if(li->tn == 6312) { - // fprintf(stderr, "(id::%u)%.*s\t%c\t(id::%u)%.*s\t%c\tsc::%ld\tsn::%ld\tc_n[j]::%d\tmsc::%ld\ti::%ld\tj::%ld\tm_idx::%ld\n", - // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], - // lj->tn, (int)Get_NAME_LENGTH(R_INF, lj->tn), Get_NAME(R_INF, lj->tn), "+-"[lj->rev], - // sc, sn, c_n[j], mm_sc, i, j, mm_idx); - // } - // if(li->tn == 20209) { - // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tj::%ld\tsc::%ld\tsn::%ld\n", i, li->tn, - // (int)Get_NAME_LENGTH(R_INF, res->a[i].tn), Get_NAME(R_INF, res->a[i].tn), - // "+-"[res->a[i].rev], j, sc, sn); - // } - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { - mm_sc = sc, mm_idx = j; mm_n = sn; is_fc = cc; - if (n_skip > 0) --n_skip; - } else if (t[j] == i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - - end_j = j; - if (max_ii < 0 || (res->a[i].qe>(res->a[max_ii].qe+max_dis))) {//too long - max = INT32_MIN; max_n = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && (res->a[i].qe<=(max_dis+res->a[j].qe)); --j) { - if ((max < f[j]) || ((max == f[j]) && (max_n < c_n[j]))) { - max = f[j]; max_n = c_n[j]; max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - lj = &(res->a[max_ii]); - if(lj->qe > li->qs/** && lj->qs < li->qs**/) { - ///as max_ii < end_j, get_rid_backward_cigar_err still works - sc = connect_detect(res->a, res->n, i, max_ii, ridx, rch, uref, uopt, bw, diff_ec_ul, p, f, &tc, - trace, qstr, tu, ol, exz, e_rate, trans_sc, &cc); - if(sc != INT32_MIN) { - sn = c_n[max_ii] + 1; - // if(li->tn == 6312 || li->tn == 6322 || li->tn == 6317 || li->tn == 6319/** && lj->tn == 6329**/) { - // fprintf(stderr, "(id::%u)%.*s\t%c\t(id::%u)%.*s\t%c\tsc::%ld\tsn::%ld\tc_n[j]::%d\tmsc::%ld\ti::%ld\tmax_ii::%ld\tm_idx::%ld\n", - // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], - // lj->tn, (int)Get_NAME_LENGTH(R_INF, lj->tn), Get_NAME(R_INF, lj->tn), "+-"[lj->rev], - // sc, sn, c_n[j], mm_sc, i, max_ii, mm_idx); - // } - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { - mm_sc = sc; mm_idx = max_ii; mm_n = sn; is_fc = cc; - } - } - } - } - - sc = csc; sn = 1;///for i itself - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { - mm_sc = sc, mm_idx = -1; mm_n = sn; is_fc = 0; - } - - if(mm_sc < 0) { - mm_sc = csc; mm_idx = -1; mm_n = 1; - } - - // if(li->tn == 6317) { - // fprintf(stderr, "+(id::%u)%.*s\t%c\tmm_idx::%ld\tmm_sc::%ld\tmm_n::%ld\n", - // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], mm_idx, mm_sc, mm_n); - // } - - if(mm_idx >= 0) { - ///mo meed to update mm_sc and is_fc - propagate_transitive_reduction(uref, uopt, ridx, bw, diff_ec_ul, res->a, x+1, i, rch, f, p, c_n, t, &mm_sc, &mm_idx, &mm_n); - } - // if(li->tn == 6317) { - // fprintf(stderr, "-(id::%u)%.*s\t%c\tmm_idx::%ld\tmm_sc::%ld\tmm_n::%ld\n", - // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], mm_idx, mm_sc, mm_n); - // } - // collapse_contain(res->a, res_n, i, &mm_idx, &mm_sc, p, c_sc, end_j); - - f[i] = mm_sc; p[i] = mm_idx; c_n[i] = mm_n; - if(mm_idx < 0 || ((ssc[mm_idx] < mm_sc) && (is_fc == 0))) ssc[i] = mm_sc; - else ssc[i] = ssc[mm_idx]; - - if ((max_ii < 0) || ((res->a[i].qe<=max_dis+res->a[max_ii].qe) && (f[max_ii]tn == 20171 || li->tn == 20209 || li->tn == 20204) { - // fprintf(stderr, "[i::%ld]\tf::%d\tp::%ld\n", i, f[i], p[i]); - // } - - } - - for (i = 0; i < res_n; ++i) {///make all f[] positive - ssc[i] -= plus; t[i] = ((uint64_t)ssc[i])<<32; t[i] += (i<<1); - } - - int64_t n_v, n_u, n_v0; mrr.qn = (uint32_t)-1; mrr.qe = mrr.qs = 0; - int32_t *f0, *c_n0, *c_sc0, *rch0, *ssc0; int64_t *p0, *t0; - f0 = f + res_n; c_n0 = c_n + res_n; c_sc0 = c_sc + res_n; - rch0 = rch + res_n; ssc0 = ssc + res_n; p0 = p + res_n; t0 = t + res_n; - radix_sort_gfa64i(t, t + res_n); plus = 0; mqs = UINT32_MAX; mqe = 0; - for (k = res_n-1, n_v = n_u = 0; k >= 0; --k) { - n_v0 = n_v; idn = 0; - for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { - if(res->a[i].qs < mqs) mqs = res->a[i].qs; - if(res->a[i].qe > mqe) mqe = res->a[i].qe; - // ex[n_v] = res->a[i]; ex[n_v].sec = i; - id[idn++] = i; t[i] |= 1; i = p[i]; n_v++; - } - if(n_v0 == n_v) continue; - sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); - - - if((mrr.qn != (uint32_t)-1) && (sc < (c_sc[mrr.qn]*0.98))) { - ovlp = ((MIN(mrr.qe, mqe) > MAX(mrr.qs, mqs))? (MIN(mrr.qe, mqe) - MAX(mrr.qs, mqs)):0); - if(ovlp >= ((mqe-mqs)*0.95)) { - n_v = n_v0; continue; - } - } - - rev_n = idn>>1; - for (i = 0; i < rev_n; i++) { - st = id[i]; id[i] = id[idn-i-1]; id[idn-i-1] = st; - } - n_v = n_v0 + gen_trans_aln(ol, ridx, uref, uopt, bw, diff_ec_ul, qlen, id, idn, res->a, res_n, mqs, mqe, t, - f0, c_n0, c_sc0, rch0, ssc0, p0, t0, max_skip, max_iter, max_dis, exz, trans_sc, qstr, tu, e_rate, trace, 1000, ex + n_v0, &rr); - assert(n_v > n_v0); - c_n[n_u] = n_v-n_v0; c_sc[n_u] = sc; n_u++; if(sc < plus) plus = sc; - if((mrr.qn == (uint32_t)-1) || (sc > c_sc[mrr.qn]) || - ((sc == c_sc[mrr.qn]) && ((rr.qe - rr.qs) > (mrr.qe - mrr.qs)))) { - mrr = rr; mrr.qn = n_u - 1; - } - } - - // fprintf(stderr, "---[M::%s] n_u:%ld, n_v:%ld\n", __func__, n_u, n_v); - for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { - n_v0 = n_v; n_v += c_n[k]; - res->a[k].qn = c_sc[k]-plus;//score - res->a[k].ts = n_v0; res->a[k].te = n_v;///idx - res->a[k].qs = ex[n_v0].qs; res->a[k].qe = ex[n_v-1].qe; - // fprintf(stderr, "[M::%s] k:%ld, c_sc:%d\n", __func__, k, c_sc[k]); - // res->a[k].te = res->a[k].ts + flat_contain(ridx, uref, uopt, bw, diff_ec_ul, qlen, max_skip, max_iter, max_dis, - // ex + res->a[k].ts, res->a[k].te - res->a[k].ts, f, ssc, p, t, &(res->a[k])); - } - res->n = n_u; - radix_sort_ul_ov_srt_qn(res->a, res->a + res->n);//sort by score - - // if(res->n > 0) { - // fprintf(stderr, "[M::%s::rid->%ld] qlen::%ld, q::[%u, %u), sc::%u\n", - // __func__, rid, qlen, res->a[res->n-1].qs, res->a[res->n-1].qe, res->a[res->n-1].qn); - // } - return n_v; -} - -int64_t select_clean_chain(kv_ul_ov_t *idx, ul_ov_t *res_a, int64_t res_n, int64_t ulid_local, asg64_v *b64) -{ - ul_ov_t kp, *m, *p, *idx_a = idx->a; uint64_t om, ovlp, min_sc, max_sc, ok, z; - int64_t k, i, idx_n = idx->n, mm, n_mchain; - for (k = 0, mm = idx_n>>1; k < mm; k++) { - kp = idx_a[k]; idx_a[k] = idx_a[idx_n-k-1]; idx_a[idx_n-k-1] = kp; - idx_a[k].tn = idx_a[idx_n-k-1].tn = 1; - } - if(idx_n&1) idx_a[k].tn = 1; - - for (k = 0; k < idx_n; k++) {//filter too close chains - m = &(idx_a[k]); om = m->qe - m->qs; ///current chain - // fprintf(stderr, "k::%ld[M::%s::sc->%u] q::[%u, %u), set::%u\n", k, __func__, m->qn, m->qs, m->qe, m->tn); - if(m->tn == 0) continue; - for (i = k-1; i >= 0; i--) { - p = &(idx_a[i]); - ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); - if(ovlp == 0) continue; - min_sc = MIN(p->qn, m->qn); max_sc = MAX(p->qn, m->qn); - ok = p->qe - p->qs; ok = MAX(ok, om); - if(min_sc < (max_sc*0.98)) break; - if((ovlp > GC_OFFSET_POS) && (min_sc > (max_sc*0.98)) && (ovlp > (ok*0.8))) { - // fprintf(stderr, "k::%ld[M::%s::i->%ld] min_sc::%ld, max_sc::%ld\n", - // k, __func__, i, min_sc, max_sc); - m->tn = p->tn = 0; - } - } - - for (i = k+1; i < idx_n; i++) { - p = &(idx_a[i]); - ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); - if(ovlp == 0) continue; - min_sc = MIN(p->qn, m->qn); max_sc = MAX(p->qn, m->qn); - ok = p->qe - p->qs; ok = MAX(ok, om); - if(min_sc < (max_sc*0.98)) break; - if((ovlp > GC_OFFSET_POS) && (min_sc > (max_sc*0.98)) && (ovlp > (ok*0.8))) { - // fprintf(stderr, "k::%ld[M::%s::i->%ld] min_sc::%ld, max_sc::%ld\n", - // k, __func__, i, min_sc, max_sc); - m->tn = p->tn = 0; - } - } - } - - for (k = i = 0; k < idx_n; k++) { - m = &(idx_a[k]); if(m->tn == 0) continue; - idx_a[i++] = idx_a[k]; - } - // fprintf(stderr, "[M::%s::] gb_n0::%ld, gb_n::%ld\n", __func__, gb_n, i); - idx->n = idx_n = i; - for (k = n_mchain = 0; k < idx_n; k++) { - m = &(idx_a[k]); om = m->qe - m->qs; - for (i = 0; i < n_mchain; i++) { - p = &(idx_a[i]); - ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); - if(ovlp == 0) continue; - ok = p->qe - p->qs; - if((ovlp > ok*0.1) || (ovlp > om*0.1)) break; - } - if(i < n_mchain) continue; - idx_a[n_mchain++] = idx_a[k]; - } - idx->n = idx_n = n_mchain; - - b64->n = idx->n; kv_resize(uint64_t, *b64, b64->n); - for (k = 0; k < idx_n; k++) { - om = idx_a[k].ts; om <<= 32; om |= k; b64->a[k] = om; - } - radix_sort_gfa64(b64->a, b64->a + b64->n); - for (k = res_n = 0; k < idx_n; k++) { - m = &(idx_a[(uint32_t)(b64->a[k])]); - for (z = m->ts, ok = SEC_MODE; z < m->te; z++) { - res_a[res_n] = res_a[z]; res_a[res_n].el = 1; - res_a[res_n].tn |= ((uint32_t)(0x80000000)); - res_a[res_n].sec = ok; - res_a[res_n].qn = ((idx_n<=1)?ulid_local:res_n); - ok = res_n; res_n++; - } - } - - if(idx_n > 1) { - radix_sort_ul_ov_srt_qe(res_a, res_a + res_n); - for (i = 1, k = 0; i <= res_n; i++) { - if (i == res_n || res_a[i].qe != res_a[k].qe) { - if(i-k>1) radix_sort_ul_ov_srt_qs(res_a+k, res_a+i); - k = i; - } - } - b64->n = res_n; kv_resize(uint64_t, *b64, b64->n); - for (i = 0; i < res_n; i++) b64->a[res_a[i].qn] = i; - for (i = 0; i < res_n; i++) { - if(res_a[b64->a[i]].sec != SEC_MODE) { - res_a[b64->a[i]].sec = b64->a[res_a[b64->a[i]].sec]; - } - res_a[b64->a[i]].qn = ulid_local; - } - } - return res_n; -} - -void prt_rid_raw_chain(kv_ul_ov_t *idx, int64_t rid, int64_t qlen) -{ - uint64_t i; - for (i = 0; i < idx->n; i++) { - fprintf(stderr, "[M::%s::rid->%ld] qlen::%ld, q::[%u, %u), sc::%u, cha_n::%u, idx_n::%u\n", - __func__, rid, qlen, idx->a[i].qs, idx->a[i].qe, idx->a[i].qn, idx->a[i].te - idx->a[i].ts, - (uint32_t)idx->n); - } - -} - -void prt_all_chain(kv_ul_ov_t *idx, ul_ov_t *a, int64_t ql) -{ - uint64_t i, k; - for (i = 0; i < idx->n; i++) { - fprintf(stderr, "\n[M::%s] q::[%u, %u), ql::%ld, sc::%u\n", __func__, idx->a[i].qs, idx->a[i].qe, ql, idx->a[i].qn); - for (k = idx->a[i].ts; k < idx->a[i].te; k++) { - fprintf(stderr, "%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", - (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), "+-"[a[k].rev], - a[k].qs, a[k].qe, a[k].ts, a[k].te, !a[k].el); - } - } - -} - -void gen_rid_raw_chain(overlap_region_alloc* ol, glchain_t *ll, uint64_t cha_idx, Chain_Data* dp, const ul_idx_t *uref, double diff_ec_ul, int64_t qlen, const ug_opt_t *uopt, char* qstr, UC_Read *tu, bit_extz_t *exz, int64_t ulid_local, -int64_t rid, ha_ovec_buf_t *bb, int64_t max_chain) -{ - ul_ov_t *res_a; uint64_t res_n; asg64_v b64; - int64_t tran_sc = ((diff_ec_ul>0)?(((double)1)/(diff_ec_ul)):(0)); - kv_ul_ov_t *idx = &(ll->lo), *res = &(ll->tk); - idx->n = 0; if(res->n <= cha_idx) return; - - res_a = res->a + cha_idx; res_n = res->n - cha_idx; - kv_resize(ul_ov_t, *idx, res_n); idx->n = res_n; - memcpy(idx->a, res_a, res_n*sizeof(*(res->a))); - kv_resize(uint64_t, ll->srt.a, res_n); - // fprintf(stderr, "\n+[M::%s] rid::%ld, name::%.*s\n", __func__, rid, - // (int32_t)UL_INF.nid.a[rid].n, UL_INF.nid.a[rid].a); - // res_n = gl_rchain_lin_contain(ol, idx, res_a, &(ll->tc), uref, uopt, G_CHAIN_BW, N_GCHAIN_RATE, qlen, ((max_chain>UG_SKIP_N)?max_chain:UG_SKIP_N), UG_ITER_N, UG_DIS_N, dp, exz, ll->srt.a.a, tran_sc, &R_INF, qstr, tu, rid, diff_ec_ul, 1); - res_n = gl_rchain_lin_contain_adv(ol, idx, res_a, &(ll->tc), uref, uopt, G_CHAIN_BW, N_GCHAIN_RATE, qlen, ((max_chain>UG_SKIP_N)?max_chain:UG_SKIP_N), UG_ITER_N, UG_DIS_N, dp, exz, ll->srt.a.a, tran_sc, &R_INF, qstr, tu, rid, diff_ec_ul, 1); - // fprintf(stderr, "-[M::%s] rid::%ld, name::%.*s\n", __func__, rid, - // (int32_t)UL_INF.nid.a[rid].n, UL_INF.nid.a[rid].a); - - // prt_all_chain(idx, res_a, qlen); - - copy_asg_arr(b64, ll->srt.a); - res_n = select_clean_chain(idx, res_a, res_n, ulid_local, &b64); - copy_asg_arr(ll->srt.a, b64); - res->n = cha_idx + res_n; - - if((idx->n) && (idx->a[0].qe - idx->a[0].qs) >= (qlen*0.95)) { - bb->num_read_base++; - } - - // else { - // // idx->n = 1; - // prt_rid_raw_chain(idx, rid, qlen); - // } - // prt_rid_raw_chain(idx, rid, qlen); - - // //debug - // ll->lo.n = ll->tk.n = 0; -} - - -static void worker_for_ul_scall_alignment(void *data, long i, int tid) // callback for kt_for() -{ - utepdat_t *s = (utepdat_t*)data; - ha_ovec_buf_t *b = s->hab[tid]; - glchain_t *bl = &(s->ll[tid]); - int64_t /**rid = s->id+i,**/ winLen = MIN((((double)THRESHOLD_MAX_SIZE)/s->opt->diff_ec_ul), WINDOW), cha_idx; - uint32_t high_occ = 2; overlap_region *aux_o = NULL; - // if(s->id+i != 901) return; - // if(s->id+i != 1052) return; - // fprintf(stderr, "[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], - // (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); - // if (memcmp(UL_INF.nid.a[s->id+i].a, "d0aab024-b3a7-40fb-83cc-22c3d6d951f8", UL_INF.nid.a[s->id+i].n-1)) return; - // fprintf(stderr, "[M::%s::] ==> len: %lu\n", __func__, s->len[i]); - // ha_get_ul_candidates_interface(b->abl, i, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->olist_hp, &b->clist, s->opt->bw_thres, - // s->opt->max_n_chain, 1, NULL/**&(b->k_flag)**/, &b->r_buf, &(b->tmp_region), NULL, &(b->sp), asm_opt.hom_cov, km); - ul_map_lchain(b->abl, (uint32_t)-1, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->clist, s->opt->bw_thres, - s->opt->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2/**0.75**/, 2, 3); - - clear_Cigar_record(&b->cigar1); - clear_Round2_alignment(&b->round2); - - ul_rid_lalign_adv(&b->olist, &b->clist, s->uu, s->uopt, s->seq[i], s->len[i], &b->self_read, &b->ovlp_read, - &b->exz, NULL, s->opt->diff_ec_ul, winLen, NULL, NULL, NULL, s->id+i, s->opt->k, NULL); - - aux_o = gen_aux_ovlp(&b->olist);///must be here - cha_idx = bl->tk.n; - - ul_rid_lalign_adv(&b->olist, &b->clist, s->uu, s->uopt, s->seq[i], s->len[i], &b->self_read, &b->ovlp_read, - &b->exz, aux_o, s->opt->diff_ec_ul, winLen, &(bl->tk), &(bl->lo), &(bl->tc), s->id+i, s->opt->k, NULL); - - // bl->lo.n = bl->tk.n = 0; - gen_rid_raw_chain(&b->olist, bl, cha_idx, &(b->clist.chainDP), s->uu, s->opt->diff_ec_ul, s->len[i], s->uopt, s->seq[i], &b->ovlp_read, &b->exz, i, s->id+i, b, s->opt->max_n_chain); - /** - // gl_chain_refine(&b->olist, &b->correct, &b->hap, bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], km); - gl_chain_refine_advance(&b->olist, &b->correct, &b->hap, bl, &(s->sps[tid]), s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, km); - align = kv_ul_ov_t_statistics(&(bl->tk), i, &(b->num_recorrect_base)); - if(align == s->len[i]) { - free(s->seq[i]); s->seq[i] = NULL; - } - b->num_correct_base += align; - **/ - // fprintf(stderr, "[1M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], - // (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); - - // fprintf(stderr, "[M::%s] rid:%ld, dd:%u\n", __func__, s->id+i, UL_INF.a[s->id+i].dd); - // int64_t mem[6], mem_hab[6]; - // if(get_utepdat_t_mem_tid(s, tid, mem, mem_hab)>((int64_t)5*(int64_t)1073741824)) { - // fprintf(stderr, "[M::%s::tid->%d::rid->%ld] buffer[0]: %.3fGB(%.3fGB::%.3fGB::%.3fGB::%.3fGB::%.3fGB), buffer[1]: %.3fGB, buffer[2]: %.3fGB, buffer[3]: %.3fGB, buffer[4]: %.3fGB, buffer[5]: %.3fGB\n", - // __func__, tid, i, mem[0]/1073741824.0, - // mem_hab[0]/1073741824.0, mem_hab[1]/1073741824.0, mem_hab[2]/1073741824.0, - // mem_hab[3]/1073741824.0, mem_hab[4]/1073741824.0, - // mem[1]/1073741824.0, mem[2]/1073741824.0, - // mem[3]/1073741824.0, mem[4]/1073741824.0, mem[5]/1073741824.0); - // } -} - -// void prt_overlap_region_alloc_ol(overlap_region_alloc* ol, uint32_t ulid) -// { -// char *as = NULL; -// uint32_t i, k; overlap_region *z; -// asprintf(&as, "[M::%s] ol->length::%lu\n", __func__, ol->length); -// push_vlog(&(overall_zdbg->a[ulid]), as); free(as); as = NULL; -// for (i = 0; i < ol->length; i++) { -// z = &(ol->list[i]); -// asprintf(&as, "[name::utg%.6dl::%c]\tq::[%u, %u)\tt::[%u, %u)\talign_length::%u\tnon_homopolymer_errors::%u\tw_list.n::%u\n", -// (int32_t)z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1, -// z->align_length, z->non_homopolymer_errors, (uint32_t)z->w_list.n); -// push_vlog(&(overall_zdbg->a[ulid]), as); free(as); as = NULL; - -// for (k = 0; k < z->w_list.n; k++) { -// asprintf(&as, "q::[%u, %u)\tclen::%u\n", -// z->w_list.a[k].x_start, z->w_list.a[k].x_end+1, z->w_list.a[k].clen); -// push_vlog(&(overall_zdbg->a[ulid]), as); free(as); as = NULL; -// } - -// } - -// } - -static void worker_for_ul_rescall_alignment(void *data, long i, int tid) // callback for kt_for() -{ - utepdat_t *s = (utepdat_t*)data; - ha_ovec_buf_t *b = s->hab[tid]; - glchain_t *bl = &(s->ll[tid]); - int64_t /**rid = s->id+i,**/ winLen = MIN((((double)THRESHOLD_MAX_SIZE)/s->opt->diff_ec_ul), WINDOW), ton = 0; - uint32_t high_occ = 2, phase = 1, k; - asg64_v b0, b1, b2; window_list p; memset(&p, 0, sizeof(p)); - overlap_region *aux_o = NULL; - // uint64_t align = 0; - - // if(UL_INF.a[s->id+i].rlen != s->len[i]) { - // fprintf(stderr, "[M::%s] rid:%ld, s->len:%lu, UL_INF->rlen:%u\n", __func__, s->id+i, s->len[i], UL_INF.a[s->id+i].rlen); - // } - // assert(UL_INF.a[s->id+i].rlen == s->len[i]); - // void *km = s->buf?(s->buf[tid]?s->buf[tid]->km:NULL):NULL; - // if(s->id+i!=0/** && s->id+i!=4 && s->id+i!=5**/) return; - // if(s->id+i!=300) return; - // fprintf(stderr, "\n[M::%s] rid:%ld, s->len:%lu\n", __func__, s->id+i, s->len[i]); - // if((s->id+i!=871) && (s->id+i!=963) && (s->id+i!=980)) return; - // if(s->id+i!=944) return; - // if(s->id+i != 35437) return; - // if((s->id+i != 7086) && (s->id+i != 51705) && (s->id+i != 266022) && (s->id+i != 353608) - // && (s->id+i != 399416) && (s->id+i != 403014) && (s->id+i != 420915) && (s->id+i != 603855) - // && (s->id+i != 680134) && (s->id+i != 766261) && (s->id+i != 794527)) { - // return; - // } - // char *as = NULL; - // asprintf(&as, "\n[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); - // push_vlog(&(overall_zdbg->a[s->id+i]), as); free(as); as = NULL; - // fprintf(stderr, "\n[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], - // (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); - // fprintf(stderr, ">%.*s\n%.*s\n", (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a, - // (int32_t)s->len[i], s->seq[i]); - - // if (memcmp(UL_INF.nid.a[s->id+i].a, "d0aab024-b3a7-40fb-83cc-22c3d6d951f8", UL_INF.nid.a[s->id+i].n-1)) return; - // fprintf(stderr, "[M::%s::] ==> len: %lu\n", __func__, s->len[i]); - // ha_get_ul_candidates_interface(b->abl, i, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->olist_hp, &b->clist, s->opt->bw_thres, - // s->opt->max_n_chain, 1, NULL, &b->r_buf, &(b->tmp_region), NULL, &(b->sp), 1, NULL); - ul_map_lchain(b->abl, (uint32_t)-1, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->clist, s->opt->bw_thres, - s->opt->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, /**0**/2, 1/**3**/); - - clear_Cigar_record(&b->cigar1); - clear_Round2_alignment(&b->round2); - // return; - // b->num_correct_base += overlap_statistics(&b->olist, NULL, 0); - - // int fully_cov, abnormal; - // b->self_read.seq = s->seq[i]; b->self_read.length = s->len[i]; b->self_read.size = 0; - // correct_ul_overlap(&b->olist, s->uu, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, - // &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 1, &fully_cov, &abnormal, s->opt->diff_ec_ul, winLen, NULL); - // memset(&b->self_read, 0, sizeof(b->self_read)); - - ul_lalign(&b->olist, &b->clist, s->uu, s->uopt, s->seq[i], s->len[i], &b->self_read, &b->ovlp_read, - &b->correct, &b->exz, &b->hap, &b->r_buf, aux_o, s->opt->diff_ec_ul, winLen, NULL, s->id+i, s->opt->k, &(s->sps[tid]), s->mm, &(s->mk[tid]), NULL); - // ul_lalign_old_ed(&b->olist, &b->clist, s->uu, s->seq[i], s->len[i], &b->self_read, &b->ovlp_read, - // &b->correct, &b->hap, &b->r_buf, s->opt->diff_ec_ul, winLen, 1, NULL); - ton = b->olist.length;//all alignments pass similary check - aux_o = gen_aux_ovlp(&b->olist);///must be here - gl_chain_flter(&b->olist, &b->correct, &(s->sps[tid]), bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, &phase); - - // fprintf(stderr, "[M::%s] rid::%ld, len::%lu, name::%.*s, phase::%u\n", __func__, s->id+i, s->len[i], - // (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a, phase); - if(phase && gen_shared_intervals(&b->olist, s->uu, s->uopt, winLen, &b->r_buf, &(bl->lo))) { - filter_topN(&b->olist, &(bl->lo), s->len[i], winLen, UL_TOPN, bl); - // update_shared_intervals(&b->olist, s->uu, s->uopt, NULL, &b->ovlp_read, &b->r_buf, &(s->sps[tid]), s->len[i], winLen, &(bl->lo), s->id+i); - - copy_asg_arr(b0, b->hap.snp_srt); copy_asg_arr(b1, s->sps[tid]); copy_asg_arr(b2, b->r_buf.a); - // update_shared_intervals(&b->olist, s->uu, s->uopt, NULL, &b->ovlp_read, &b0, &b1, &b2, s->len[i], winLen, &(bl->lo), s->id+i); - update_sketch_trace(&b->olist, s->uu, s->uopt, NULL, &b->ovlp_read, &b0, &b1, &b2, s->len[i], winLen, &(bl->lo), s->id+i, MAX_LGAP(s->len[i]), s->opt->diff_ec_ul); - copy_asg_arr(b->hap.snp_srt, b0); copy_asg_arr(s->sps[tid], b1); copy_asg_arr(b->r_buf.a, b2); - - ul_lalign(&b->olist, &b->clist, s->uu, s->uopt, s->seq[i], s->len[i], &b->self_read, &b->ovlp_read, - &b->correct, &b->exz, &b->hap, &b->r_buf, aux_o, s->opt->diff_ec_ul, winLen, &(bl->lo), s->id+i, s->opt->k, &(s->sps[tid]), s->mm, &(s->mk[tid]), NULL); - // ul_lalign_old_ed(&b->olist, &b->clist, s->uu, s->seq[i], s->len[i], &b->self_read, &b->ovlp_read, - // &b->correct, &b->hap, &b->r_buf, s->opt->diff_ec_ul, winLen, 0, NULL); - // fprintf(stderr, "\n[M::%s] b->olist.length::%lu, ton::%ld\n", __func__, - // b->olist.length, ton); - ///recover alignments - for (k = b->olist.length; k < ton; k++) { - b->olist.list[k].w_list.n = 0; - p.x_start = b->olist.list[k].x_pos_s; - p.x_end = b->olist.list[k].x_pos_e+1; - p.clen = b->olist.list[k].non_homopolymer_errors; - kv_push(window_list, b->olist.list[k].w_list, p); - b->olist.list[k].align_length = 0; - b->olist.list[k].overlapLen = b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; - // fprintf(stderr, "[M::%s]\tutg%.6u%c\txl::%lu\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\n", - // __func__, b->olist.list[k].y_id + 1, "lc"[s->uu->ug->u.a[b->olist.list[k].y_id].circ], - // s->len[i], b->olist.list[k].x_pos_s, b->olist.list[k].x_pos_e+1, "+-"[b->olist.list[k].y_pos_strand], - // s->uu->ug->u.a[b->olist.list[k].y_id].len, b->olist.list[k].y_pos_s, b->olist.list[k].y_pos_e+1, - // b->olist.list[k].non_homopolymer_errors); - } - b->olist.length = ton; - } else { - for (k = 0; k < b->olist.length; k++) { - b->olist.list[k].w_list.n = 0; - p.x_start = b->olist.list[k].x_pos_s; - p.x_end = b->olist.list[k].x_pos_e+1; - p.clen = 0; - kv_push(window_list, b->olist.list[k].w_list, p); - b->olist.list[k].align_length = b->olist.list[k].overlapLen = - b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; - b->olist.list[k].non_homopolymer_errors = 0; - } - } - - // prt_overlap_region_alloc_ol(&(b->olist), s->id+i); - - - gl_chain(s->buf[tid], &(UL_INF.a[s->id+i]), &b->olist, &(b->clist.chainDP), &b->hap, &(s->sps[tid]), bl, &(s->gdp[tid]), s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, tid, NULL); - - // exit(1); - // uint64_t k; - // for (k = 0; k < b->olist.length; k++) { - // if(b->olist.list[k].is_match == 1) b->num_correct_base += b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; - // if(b->olist.list[k].is_match == 2) b->num_recorrect_base += b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; - // } - - - // gl_chain_refine(&b->olist, &b->correct, &b->hap, bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], km); - // gl_chain_refine_advance_combine(s->buf[tid], &(UL_INF.a[s->id+i]), &b->olist, &b->correct, &b->hap, &(s->sps[tid]), bl, &(s->gdp[tid]), s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, tid, NULL); - // return; - // b->num_read_base += b->self_read.length; - // b->num_correct_base += b->correct.corrected_base; - // b->num_recorrect_base += b->round2.dumy.corrected_base; - - if(UL_INF.a[s->id+i].dd == 1 || UL_INF.a[s->id+i].dd == 2) { - b->num_correct_base++; - } - if(UL_INF.a[s->id+i].dd != 3) { - free(s->seq[i]); s->seq[i] = NULL; - } - s->hab[tid]->num_read_base++; - // fprintf(stderr, "[M::%s] rid:%ld, dd:%u\n", __func__, s->id+i, UL_INF.a[s->id+i].dd); - // int64_t mem[6], mem_hab[6]; - // if(get_utepdat_t_mem_tid(s, tid, mem, mem_hab)>((int64_t)5*(int64_t)1073741824)) { - // fprintf(stderr, "[M::%s::tid->%d::rid->%ld] buffer[0]: %.3fGB(%.3fGB::%.3fGB::%.3fGB::%.3fGB::%.3fGB), buffer[1]: %.3fGB, buffer[2]: %.3fGB, buffer[3]: %.3fGB, buffer[4]: %.3fGB, buffer[5]: %.3fGB\n", - // __func__, tid, i, mem[0]/1073741824.0, - // mem_hab[0]/1073741824.0, mem_hab[1]/1073741824.0, mem_hab[2]/1073741824.0, - // mem_hab[3]/1073741824.0, mem_hab[4]/1073741824.0, - // mem[1]/1073741824.0, mem[2]/1073741824.0, - // mem[3]/1073741824.0, mem[4]/1073741824.0, mem[5]/1073741824.0); - // } - - // align = kv_ul_ov_t_statistics(&(bl->tk), i, &(b->num_recorrect_base)); - // if(align == s->len[i]) { - // free(s->seq[i]); s->seq[i] = NULL; - // } - // b->num_correct_base += align; - - // uint64_t k; - // b->num_read_base += overlap_statistics(&b->olist, NULL, NULL, 1); - // for (k = 0; k < bl->tk.n; k++) { - // if(bl->tk.a[k].sec == 0) b->num_correct_base += bl->tk.a[k].qe - bl->tk.a[k].qs; - // if(bl->tk.a[k].sec > 0) b->num_recorrect_base += bl->tk.a[k].qe - bl->tk.a[k].qs; - // } - // for (k = 0; k < bl->lo.n; k++) { - // b->num_read_base += bl->lo.a[k].qe - bl->lo.a[k].qs; - // } - - // uint32_t l1 = overlap_statistics(&b->olist, s->uu->ug, 1), l2 = overlap_statistics(&b->olist, s->uu->ug, 2); - // - // if(l1 == 0 && l2 > 0) fprintf(stderr, "[M::%s::%lu::no_match]\n", UL_INF.nid.a[s->id+i].a, s->len[i]); - // fprintf(stderr, "[M::%s::%lu::] l1->%u; l2->%u\n", UL_INF.nid.a[s->id+i].a, s->len[i], l1, l2); - // fprintf(stderr, "[M::%s::rid->%ld] done\n", __func__, s->id+i); - // exit(1); -} - - -uint32_t ck_ul_alignment(ul_vec_t *x) -{ - uc_block_t *a = x->bb.a, *p, *z0, *z1; uint64_t a_n = x->bb.n, k, rlen = x->rlen; - for (k = 0; k < a_n; k++) { - p = &(a[k]); - if(p->base) continue; - if(p->qs > rlen || p->qe > rlen || p->qs > p->qe) break; - if(p->pidx != (uint32_t)-1) { - if(a[p->pidx].aidx == (uint32_t)-1 || a[p->pidx].aidx != k) break; - if(p->pidx >= k) break; - z1 = p; z0 = &(a[p->pidx]); - if(!(z1->qs >= z0->qs && z1->qe >= z0->qe)) break; - } - - if(p->aidx != (uint32_t)-1) { - if(a[p->aidx].pidx == (uint32_t)-1 || a[p->aidx].pidx != k) break; - if(p->aidx <= k) break; - z0 = p; z1 = &(a[p->aidx]); - if(!(z1->qs >= z0->qs && z1->qe >= z0->qe)) break; - } - } - if(k >= a_n) return 1; - return 0; -} - -uint32_t filter_sec_trans_ovlp(ul_ov_t *a, uint32_t a_n, uint32_t qn, double sec_rate) -{ - if(a_n <= 0) return a_n; - uint32_t i, m, k, oz, op, ovlp, min_sc, max_sc; int64_t nw[2], ml, uml, msc; ul_ov_t *z, *p, t; - for (i = m = 0; i < a_n; i++) { - z = &(a[i]); z->qn = 0; - ml = z->qe - z->qs; uml = z->sec; ml -= uml; - nw[0] = (ml*CHAIN_MATCH) - (uml*CHAIN_UNMATCH); - ml = z->te - z->ts; uml = z->sec; ml -= uml; - nw[1] = (ml*CHAIN_MATCH) - (uml*CHAIN_UNMATCH); - msc = MIN(nw[0], nw[1]); - if(msc <= 0) continue; - if(msc >= UINT32_MAX) msc = UINT32_MAX; - z->qn = msc; - a[m++] = (*z); - } - a_n = m; - if(a_n <= 0) return a_n; - radix_sort_ul_ov_srt_qn(a, a + a_n);//sort by scores - for (i = 0, m = (a_n>>1); i < m; i++) { - t = a[i]; a[i] = a[a_n-i-1]; a[a_n-i-1] = t; - } - - for (k = m = 0; k < a_n; k++) { - z = &a[k]; oz = z->qe - z->qs; ///current chain - for (i = 0; i < m; i++) { - p = &(a[i]); - ovlp = ((MIN(z->qe, p->qe) > MAX(z->qs, p->qs))? (MIN(z->qe, p->qe) - MAX(z->qs, p->qs)):0); - if(ovlp == 0) continue; - op = p->qe - p->qs; - min_sc = MIN(p->qn, z->qn); max_sc = MAX(p->qn, z->qn); - if(min_sc <= (max_sc*0.95)) { - if((ovlp > (oz*sec_rate)) || (ovlp > (op*sec_rate))) break; - } - } - if(i < m) continue; - a[m++] = a[k]; - } - a_n = m; - for (k = 0; k < a_n; k++) a[k].qn = qn; - return a_n; -} - -uint32_t trans_ovlp_connect(ul_ov_t *p, ma_ug_t *ug) -{ - uint32_t v = p->qn<<1, w = (p->tn<<1) + ((uint32_t)p->rev), i, dg = (uint32_t)-1, da, dif, mm; - asg_arc_t *av = asg_arc_a(ug->g, v); uint32_t nv = asg_arc_n(ug->g, v); - for (i = 0; i < nv; i++) { - if(av[i].del || av[i].v != w) continue; - dg = av[i].ol; - break; - } - // if(i >= nv) return 1; - if(i < nv) { - da = (p->qe - p->qs); - dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; - if(dif <= mm) return 0; - - da = (p->te - p->ts); - dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; - if(dif <= mm) return 0; - } - - - v ^= 1; w ^= 1; dg = (uint32_t)-1; - av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); - for (i = 0; i < nv; i++) { - if(av[i].del || av[i].v != w) continue; - dg = av[i].ol; - break; - } - if(i < nv) { - da = (p->qe - p->qs); - dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; - if(dif <= mm) return 0; - - da = (p->te - p->ts); - dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; - if(dif <= mm) return 0; - } - - return 1; -} - -uint64_t filter_by_reliable_ovlp0(u_trans_t *a, uint64_t a_n, uint64_t s, uint64_t e, double sec_rate) -{ - uint64_t k, ovlp; - for (k = 0; k < a_n; k++) { - if(a[k].del) continue; - if(a[k].f == RC_0 || a[k].f == RC_1) { - ovlp = ((MIN(a[k].qe, e) > MAX(a[k].qs, s))? (MIN(a[k].qe, e)-MAX(a[k].qs, s)):0); - if(ovlp == 0) continue; - if((ovlp) && (ovlp > ((e-s)*sec_rate))) return 1; - } - } - return 0; -} - -void filter_by_reliable_ovlp(uint32_t id, kv_u_trans_t *idx, st_mt_t *sp, overlap_region_alloc* ol, const ul_idx_t *udb, double sec_rate, uint32_t pre_filter) -{ - u_trans_t *a; uint64_t n, k, l, s, e, s0, e0, z, ov, rr; overlap_region *m, t; - a = u_trans_a(*idx, id); n = u_trans_n(*idx, id); - for (k = sp->n = 0; k < n; k++) { - if(a[k].del) continue; - if(a[k].f == RC_0 || a[k].f == RC_1) { - z = a[k].tn; z <<= 1; z |= a[k].rev; z <<= 32; z |= k; - kv_push(uint64_t, *sp, z); - // fprintf(stderr, "***utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", - // a[k].qn+1, "lc"[udb->ug->u.a[a[k].qn].circ], udb->ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], - // a[k].tn+1, "lc"[udb->ug->u.a[a[k].tn].circ], udb->ug->u.a[a[k].tn].len, a[k].ts, a[k].te); - } - } - if(!sp->n) return; - for (k = 0; k < ol->length; k++) { - if((!pre_filter) || (ol->list[k].x_pos_strand)) {///corresponding to the overlaps within idx - z = ol->list[k].y_id; z <<= 1; z |= ol->list[k].y_pos_strand; - z <<= 32; z |= k; z |= ((uint64_t)0x80000000); - kv_push(uint64_t, *sp, z); - ol->list[k].x_pos_strand = 0; - } - } - radix_sort_gfa64(sp->a, sp->a + sp->n); - for (k = 1, l = 0; k <= sp->n; k++) { - if(k == sp->n || (sp->a[l]>>32)!=(sp->a[k]>>32)) { - if((k - l > 1) && (!(sp->a[l]&((uint64_t)0x80000000)))) { - for (z = l; z < k; z++) { - if(!(sp->a[z]&((uint64_t)0x80000000))) continue; - rr = (uint32_t)(sp->a[z]-((uint64_t)0x80000000)); - ol->list[rr].x_pos_strand = 1; - } - } - l = k; - } - } - - for (k = sp->n = 0; k < n; k++) { - if(a[k].del) continue; - if(a[k].f == RC_0 || a[k].f == RC_1) { - kv_push(uint64_t, *sp, (((uint64_t)a[k].qs)<<32)|((uint64_t)a[k].qe)); - } - } - if(sp->n > 1) { - radix_sort_gfa64(sp->a, sp->a + sp->n); - for (k = z = 0; k < sp->n; k++) { - s = sp->a[k]>>32; e = (uint32_t)sp->a[k]; - if(z > 0 && s <= ((uint32_t)sp->a[z-1])) { - if(e > ((uint32_t)sp->a[z-1])) { - sp->a[z-1] >>= 32; sp->a[z-1] <<= 32; sp->a[z-1] |= e; - } - } else { - sp->a[z++] = sp->a[k]; - } - } - sp->n = z; - } - - for (k = rr = 0; k < ol->length; k++) { - m = &(ol->list[k]); - if(m->x_pos_strand == 0) { - s = m->x_pos_s; e = m->x_pos_e + 1; l = 0; - for (z = 0; z < sp->n; z++) { - s0 = sp->a[z]>>32; e0 = (uint32_t)sp->a[z]; - ov = ((MIN(e, e0) > MAX(s, s0))? (MIN(e, e0) - MAX(s, s0)):0); - l += ov; - if((l) && (l > ((e-s)*sec_rate))) break; - } - if(z < sp->n) { - // fprintf(stderr, ">[M::%s] utg%.6u%c -> utg%.6u%c\n", __func__, id+1, "lc"[udb->ug->u.a[id].circ], - // m->y_id+1, "lc"[udb->ug->u.a[m->y_id].circ]); - continue;///filter by the overlaps of id/m->x_id - } - ///filter by the overlaps of m->y_id - if(filter_by_reliable_ovlp0(u_trans_a(*idx, m->y_id), u_trans_n(*idx, m->y_id), - m->y_pos_strand?udb->ug->u.a[m->y_id].len-m->y_pos_e-1:m->y_pos_s, - m->y_pos_strand?udb->ug->u.a[m->y_id].len-m->y_pos_s:m->y_pos_e+1, sec_rate)) { - // fprintf(stderr, "<[M::%s] utg%.6u%c -> utg%.6u%c\n", __func__, id+1, "lc"[udb->ug->u.a[id].circ], - // m->y_id+1, "lc"[udb->ug->u.a[m->y_id].circ]); - continue; - } - } - m->x_pos_strand = 0; - if(rr != k) { - t = ol->list[k]; - ol->list[k] = ol->list[rr]; - ol->list[rr] = t; - } - // fprintf(stderr, ">>>utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", - // ol->list[rr].x_id+1, "lc"[udb->ug->u.a[ol->list[rr].x_id].circ], udb->ug->u.a[ol->list[rr].x_id].len, - // ol->list[rr].x_pos_s, ol->list[rr].x_pos_e+1, "+-"[ol->list[rr].y_pos_strand], - // ol->list[rr].y_id+1, "lc"[udb->ug->u.a[ol->list[rr].y_id].circ], udb->ug->u.a[ol->list[rr].y_id].len, - // ol->list[rr].y_pos_s, ol->list[rr].y_pos_e+1); - rr++; - } - // if(id == 1576) { - // fprintf(stderr, "[M::%s] utg%.6ul, ol->length0::%lu, ol->length::%lu\n", __func__, id+1, ol->length, rr); - // } - ol->length = rr; -} - -static void worker_for_trans_ovlp(void *data, long i, int tid) // callback for kt_for() -{ - ug_trans_t *s = (ug_trans_t*)data; - ha_ovec_buf_t *b = s->hab[tid]; - kv_ul_ov_t *bl = &(s->ll[tid].tk); - int64_t winLen = MIN((((double)THRESHOLD_MAX_SIZE)/s->diff_ec_ul), WINDOW); - uint32_t high_occ = asm_opt.polyploidy + 1, k; uint64_t cnt, bn; - overlap_region *aux_o = NULL; ul_ov_t *p; - char *seq = s->ug->u.a[i].s; - int64_t len = s->ug->u.a[i].len; - if((!s->is_ovlp) && (s->is_cnt)) s->idx_n.a[i] = 0; - if(IF_HOM(i, (*(s->bub))) || s->ug->g->seq[i].del) return; - - // asprintf(&as, "\n[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); - // push_vlog(&(overall_zdbg->a[s->id+i]), as); free(as); as = NULL; - - if(!s->is_ovlp) { - if(s->is_cnt) { - s->idx_n.a[i] = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, - s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, NULL, 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); - // fprintf(stderr, "-1-[M::%s] rid::%ld, is_ovlp::%d, is_cnt::%d, len::%d, str::%u, s->idx_n.a[i]::%lu\n", - // __func__, i, s->is_ovlp, s->is_cnt, len, !!seq, s->idx_n.a[i]); - } else { - cnt = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, - s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); - assert(cnt == ((s->idx_n.a[i+1]-s->idx_n.a[i]))); - // if(i == 1576 || i == 2879) { - // fprintf(stderr, "-2-[M::%s] rid::%ld, is_ovlp::%d, is_cnt::%d, len::%ld, str::%u, cnt::%lu\n", - // __func__, i, s->is_ovlp, s->is_cnt, len, !!seq, cnt); - // } - } - return; - } else { - cnt = ((s->idx_n.a[i+1]-s->idx_n.a[i])); - // fprintf(stderr, "\n-0-[M::%s] utg%.6u%c, rid::%ld, is_ovlp::%d, is_cnt::%d, len::%ld, str::%u, cnt::%lu, diff::%f\n", - // __func__, (uint32_t)i+1, "lc"[s->ug->u.a[i].circ], i, s->is_ovlp, s->is_cnt, len, (uint32_t)(!!seq), cnt, s->diff_ec_ul); - ///note: high_occ is different - ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), &b->olist, &b->clist, s->bw_thres, s->bw_thres_double, - s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], cnt, s->srt_a.a, s->srt_a.n, s->mini_cut, s->chain_cut, NULL); - } - - filter_by_reliable_ovlp(i, s->filter, &(b->sp), &b->olist, &(s->udb), s->sec_cutoff, 0); - // fprintf(stderr, "-0-[M::%s] rid::%ld, is_ovlp::%d, is_cnt::%d, len::%ld, str::%u\n", - // __func__, i, s->is_ovlp, s->is_cnt, len, !!seq); - clear_Cigar_record(&b->cigar1); clear_Round2_alignment(&b->round2); - - ug_lalign(&b->olist, &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, - &b->correct, &b->exz, aux_o, s->diff_ec_ul, winLen, i, s->k, s->chain_cut, NULL); - - aux_o = gen_aux_ovlp(&b->olist);///must be here - - ug_lalign(&b->olist, &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, - &b->correct, &b->exz, aux_o, s->diff_ec_ul, winLen, i, s->k, s->chain_cut, NULL); - if(b->olist.length > 0) { - cnt = bl->n + b->olist.length; kv_resize(ul_ov_t, (*bl), cnt); - for (k = 0, bn = bl->n; k < b->olist.length; k++) { - // if(b->olist.list[k].non_homopolymer_errors == 0) continue;///exact match is not trans - kv_pushp(ul_ov_t, (*bl), &p); - p->qn = i; p->tn = b->olist.list[k].y_id; p->el = 1; - p->sec = b->olist.list[k].non_homopolymer_errors; - p->rev = b->olist.list[k].y_pos_strand; - p->qs = b->olist.list[k].x_pos_s; p->qe = b->olist.list[k].x_pos_e+1; - // p->ts = b->olist.list[k].y_pos_s; p->te = b->olist.list[k].y_pos_e+1; - if(p->rev) { - p->ts = s->udb.ug->u.a[p->tn].len - (b->olist.list[k].y_pos_e+1); - p->te = s->udb.ug->u.a[p->tn].len - b->olist.list[k].y_pos_s; - } else { - p->ts = b->olist.list[k].y_pos_s; - p->te = b->olist.list[k].y_pos_e+1; - } - // if(i == 5) - // { - // fprintf(stderr, "***utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\ti::%ld\n", - // p->qn+1, "lc"[s->ug->u.a[p->qn].circ], s->ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], - // p->tn+1, "lc"[s->ug->u.a[p->tn].circ], s->ug->u.a[p->tn].len, p->ts, p->te, i); - // } - if(!trans_ovlp_connect(p, s->ug)) { - bl->n--; - } - // else { - // if(i == 5) - // { - // fprintf(stderr, ">>>utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\ti::%ld\n", - // p->qn+1, "lc"[s->ug->u.a[p->qn].circ], s->ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], - // p->tn+1, "lc"[s->ug->u.a[p->tn].circ], s->ug->u.a[p->tn].len, p->ts, p->te, i); - // } - // } - } - cnt = filter_sec_trans_ovlp(bl->a+bn, bl->n-bn, i, s->sec_cutoff) + bn; - bl->n = cnt; - } - - - // fprintf(stderr, "[M::%s] rid:%ld, dd:%u\n", __func__, s->id+i, UL_INF.a[s->id+i].dd); - // int64_t mem[6], mem_hab[6]; - // if(get_utepdat_t_mem_tid(s, tid, mem, mem_hab)>((int64_t)5*(int64_t)1073741824)) { - // fprintf(stderr, "[M::%s::tid->%d::rid->%ld] buffer[0]: %.3fGB(%.3fGB::%.3fGB::%.3fGB::%.3fGB::%.3fGB), buffer[1]: %.3fGB, buffer[2]: %.3fGB, buffer[3]: %.3fGB, buffer[4]: %.3fGB, buffer[5]: %.3fGB\n", - // __func__, tid, i, mem[0]/1073741824.0, - // mem_hab[0]/1073741824.0, mem_hab[1]/1073741824.0, mem_hab[2]/1073741824.0, - // mem_hab[3]/1073741824.0, mem_hab[4]/1073741824.0, - // mem[1]/1073741824.0, mem[2]/1073741824.0, - // mem[3]/1073741824.0, mem[4]/1073741824.0, mem[5]/1073741824.0); - // } -} - - -void filter_by_reliable_ovlp_adv(uint32_t id, kv_u_trans_t *idx, st_mt_t *sp, overlap_region_alloc* ol, const ul_idx_t *udb, double sec_rate, uint64_t avoid_dup_aln, -uint64_t dedup_by_reliable_ovlp, uint64_t *occ1) -{ - (*occ1) = 0; - u_trans_t *a; uint64_t n, k, l, s, e, s0, e0, z, ov, rr, r1, spn; overlap_region *m, t; - a = u_trans_a(*idx, id); n = u_trans_n(*idx, id); - if(avoid_dup_aln) { - kv_resize(uint64_t, *sp, (ol->length)+n); - for (k = sp->n = 0; k < n; k++) { - if(a[k].del) continue; - // if(id == 160) { - // fprintf(stderr, "[rid::%u]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\n", id, - // a[k].qn+1, "lc"[udb->ug->u.a[a[k].qn].circ], udb->ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], - // a[k].tn+1, "lc"[udb->ug->u.a[a[k].tn].circ], udb->ug->u.a[a[k].tn].len, a[k].ts, a[k].te, a[k].nw, a[k].f); - // } - if(a[k].f == RC_0 || a[k].f == RC_1) { - z = a[k].tn; z <<= 1; z |= a[k].rev; z <<= 32; - kv_push(uint64_t, *sp, z); - } - } - if(sp->n > 0) { - for (k = 0; k < ol->length; k++) { - z = ol->list[k].y_id; z <<= 1; z |= ol->list[k].y_pos_strand; - z <<= 32; z |= k; z |= ((uint64_t)0x80000000); - kv_push(uint64_t, *sp, z); - } - - radix_sort_gfa64(sp->a, sp->a + sp->n); - for (k = 1, l = 0, rr = 0; k <= sp->n; k++) { - if(k == sp->n || (sp->a[l]>>32)!=(sp->a[k]>>32)) { - if((k - l > 1) && (!(sp->a[l]&((uint64_t)0x80000000)))) {///overlap within bck - for (z = l; z < k; z++) { - if(sp->a[z]&((uint64_t)0x80000000)) { - ol->list[(uint32_t)(sp->a[z]-((uint64_t)0x80000000))].y_id = ((uint32_t)-1); - rr++; - } - } - } - l = k; - } - } - - if(rr > 0) { - for (k = rr = 0; k < ol->length; k++) { - if(ol->list[k].y_id == ((uint32_t)-1)) continue; - if(rr != k) { - t = ol->list[rr]; - ol->list[rr] = ol->list[k]; - ol->list[k] = t; - } - rr++; - } - ol->length = rr; - } - } - } - - sp->n = 0; - if(dedup_by_reliable_ovlp) { - for (k = sp->n = 0; k < n; k++) { - if(a[k].del) continue; - if(a[k].f == RC_0 || a[k].f == RC_1) { - kv_push(uint64_t, *sp, (((uint64_t)a[k].qs)<<32)|((uint64_t)a[k].qe)); - } - } - if(sp->n > 1) { - radix_sort_gfa64(sp->a, sp->a + sp->n); - for (k = z = 0; k < sp->n; k++) { - s = sp->a[k]>>32; e = (uint32_t)sp->a[k]; - if(z > 0 && s <= ((uint32_t)sp->a[z-1])) { - if(e > ((uint32_t)sp->a[z-1])) { - sp->a[z-1] >>= 32; sp->a[z-1] <<= 32; sp->a[z-1] |= e; - } - } else { - sp->a[z++] = sp->a[k]; - } - } - sp->n = z; - } - } - - for (k = rr = r1 = 0, spn = sp->n; k < ol->length; k++) { - m = &(ol->list[k]); - // if(id == 160) { - // fprintf(stderr, "[M::%s] utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\txstr::%u\n", __func__, - // ol->list[k].x_id+1, "lc"[udb->ug->u.a[ol->list[k].x_id].circ], udb->ug->u.a[ol->list[k].x_id].len, - // ol->list[k].x_pos_s, ol->list[k].x_pos_e+1, "+-"[ol->list[k].y_pos_strand], - // ol->list[k].y_id+1, "lc"[udb->ug->u.a[ol->list[k].y_id].circ], udb->ug->u.a[ol->list[k].y_id].len, - // ol->list[k].y_pos_s, ol->list[k].y_pos_e+1, ol->list[k].x_pos_strand); - // } - if((dedup_by_reliable_ovlp) && (m->x_pos_strand == 0)) { - s = m->x_pos_s; e = m->x_pos_e + 1; l = 0; - for (z = 0; z < spn; z++) { - s0 = sp->a[z]>>32; e0 = (uint32_t)sp->a[z]; - ov = ((MIN(e, e0) > MAX(s, s0))? (MIN(e, e0) - MAX(s, s0)):0); - l += ov; - if((l) && (l > ((e-s)*sec_rate))) break; - } - ///filter by the overlaps of id/m->x_id - if(z < spn) continue; - ///filter by the overlaps of m->y_id - if(filter_by_reliable_ovlp0(u_trans_a(*idx, m->y_id), u_trans_n(*idx, m->y_id), - m->y_pos_strand?udb->ug->u.a[m->y_id].len-m->y_pos_e-1:m->y_pos_s, - m->y_pos_strand?udb->ug->u.a[m->y_id].len-m->y_pos_s:m->y_pos_e+1, sec_rate)) { - continue; - } - } - // else { - // if(id == 7) { - // fprintf(stderr, "[M::%s] utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, - // ol->list[k].x_id+1, "lc"[udb->ug->u.a[ol->list[k].x_id].circ], udb->ug->u.a[ol->list[k].x_id].len, - // ol->list[k].x_pos_s, ol->list[k].x_pos_e+1, "+-"[ol->list[k].y_pos_strand], - // ol->list[k].y_id+1, "lc"[udb->ug->u.a[ol->list[k].y_id].circ], udb->ug->u.a[ol->list[k].y_id].len, - // ol->list[k].y_pos_s, ol->list[k].y_pos_e+1); - // } - // } - if(rr != k) { - t = ol->list[k]; - ol->list[k] = ol->list[rr]; - ol->list[rr] = t; - } - if(ol->list[rr].x_pos_strand) { - ol->list[rr].x_pos_strand = 0; - if(r1 != rr) { - t = ol->list[r1]; - ol->list[r1] = ol->list[rr]; - ol->list[rr] = t; - } - r1++; - } - // fprintf(stderr, ">>>utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", - // ol->list[rr].x_id+1, "lc"[udb->ug->u.a[ol->list[rr].x_id].circ], udb->ug->u.a[ol->list[rr].x_id].len, - // ol->list[rr].x_pos_s, ol->list[rr].x_pos_e+1, "+-"[ol->list[rr].y_pos_strand], - // ol->list[rr].y_id+1, "lc"[udb->ug->u.a[ol->list[rr].y_id].circ], udb->ug->u.a[ol->list[rr].y_id].len, - // ol->list[rr].y_pos_s, ol->list[rr].y_pos_e+1); - rr++; - } - // if(id == 1576) { - // fprintf(stderr, "[M::%s] utg%.6ul, ol->length0::%lu, ol->length::%lu\n", __func__, id+1, ol->length, rr); - // } - ol->length = rr; (*occ1) = r1; -} - -void prt_split_ovs(overlap_region_alloc* ol, ma_ug_t *ug, uint64_t ol_h, uint64_t ol_l, const char* cmd) -{ - uint64_t k; overlap_region *z; - fprintf(stderr, "[M::%s] %s\tol->length::%lu, ol_h::%lu, ol_l::%lu\n", __func__, cmd, ol->length, ol_h, ol_l); - // assert((ol_h+ol_l) == ol->length); - for (k = 0; k < ol_h; k++) { - z = &(ol->list[k]); - fprintf(stderr, "oh->[%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\twn::%u\taln::%u\ted::%u\n", cmd, - z->x_id+1, "lc"[ug->u.a[z->x_id].circ], ug->u.a[z->x_id].len, - z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - z->y_id+1, "lc"[ug->u.a[z->y_id].circ], ug->u.a[z->y_id].len, - z->y_pos_s, z->y_pos_e+1, (uint32_t)z->w_list.n, z->align_length, z->non_homopolymer_errors); - } - - for (; k < ol->length; k++) { - z = &(ol->list[k]); - fprintf(stderr, "ol->[%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\twn::%u\taln::%u\ted::%u\n", cmd, - z->x_id+1, "lc"[ug->u.a[z->x_id].circ], ug->u.a[z->x_id].len, - z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - z->y_id+1, "lc"[ug->u.a[z->y_id].circ], ug->u.a[z->y_id].len, - z->y_pos_s, z->y_pos_e+1, (uint32_t)z->w_list.n, z->align_length, z->non_homopolymer_errors); - } -} - - -uint64_t split_ug_lalign(uint64_t ol_h, overlap_region_alloc* ol, double errh, double errl, - Candidates_list *cl, const ul_idx_t *uref, const ug_opt_t *uopt, - char *qstr, uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, bit_extz_t *exz, - overlap_region *aux_o, int64_t sid, uint64_t khit, uint64_t chain_cut, void *km) -{ - uint64_t ol_l = ol->length - ol_h, on0, k, m; int64_t wl; double erate; overlap_region t; - // if(sid == 57) fprintf(stderr, "[M::%s] errh::%f, errl::%f\n", __func__, errh, errl); - // if(sid == 57) prt_split_ovs(ol, uref->ug, ol_h, ol_l, "st"); - if(ol_h) { - erate = errh; on0 = ol->length; - wl = MIN((((double)THRESHOLD_MAX_SIZE)/erate), WINDOW); - ol->length = ol_h; - ug_lalign(ol, cl, uref, uopt, qstr, ql, qu, tu, dumy, exz, aux_o, erate, wl, sid, khit, chain_cut, km); - for (k = ol_h, m = ol->length; k < on0; k++) {///move ovlps with ol_l - if(k != m) { - t = ol->list[k]; - ol->list[k] = ol->list[m]; - ol->list[m] = t; - } - m++; - } - ol_h = ol->length; ol->length = m; ol_l = ol->length - ol_h; - } - // if(sid == 57) prt_split_ovs(ol, uref->ug, ol_h, ol_l, "mi"); - if(ol_l) { - erate = errl; on0 = ol->length; - wl = MIN((((double)THRESHOLD_MAX_SIZE)/erate), WINDOW); - if(ol_h) {///swap ol_h and ol_l - for (k = ol_h, m = 0; k < ol->length; k++) { - if(k != m) { - t = ol->list[k]; - ol->list[k] = ol->list[m]; - ol->list[m] = t; - } - m++; - } - } - // if(sid == 57) prt_split_ovs(ol, uref->ug, ol_h, ol_l, "sw"); - ol->length = ol_l; - ug_lalign(ol, cl, uref, uopt, qstr, ql, qu, tu, dumy, exz, aux_o, erate, wl, sid, khit, chain_cut, km); - // if(sid == 57) { - // fprintf(stderr, "[M::%s::]\ton0::%lu\tol_l::%lu\tol_h::%lu\tol->length::%lu\n", __func__, - // on0, ol_l, ol_h, ol->length); - // prt_split_ovs(ol, uref->ug, ol_h, ol_l, "u0"); - // } - for (k = ol_l, m = ol->length; k < on0; k++) {///move ovlps with ol_h - if(k != m) { - t = ol->list[k]; - ol->list[k] = ol->list[m]; - ol->list[m] = t; - } - m++; - } - ol_l = ol->length; ol->length = m; ol_h = ol->length - ol_l; - // if(sid == 57) prt_split_ovs(ol, uref->ug, ol_h, ol_l, "u1"); - if(ol_l) {///swap ol_h and ol_l - for (k = ol_l, m = 0; k < ol->length; k++) { - if(k != m) { - t = ol->list[k]; - ol->list[k] = ol->list[m]; - ol->list[m] = t; - } - m++; - } - } - } - // if(sid == 57) prt_split_ovs(ol, uref->ug, ol_h, ol_l, "ed"); - return ol_h; -} - -uint32_t test_het_aln(ma_ug_t *ug, uint64_t rid, u_trans_t *a, uint64_t a_n, st_mt_t *sp, overlap_region_alloc* ol, uint64_t len) -{ - uint64_t k, s, e, z, l = 0; - for (k = sp->n = 0; k < a_n; k++) { - if(a[k].del) continue; - // if(rid == 56 || rid == 160) { - // fprintf(stderr, "[rid::%lu]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\n", rid, - // a[k].qn+1, "lc"[ug->u.a[a[k].qn].circ], ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], - // a[k].tn+1, "lc"[ug->u.a[a[k].tn].circ], ug->u.a[a[k].tn].len, a[k].ts, a[k].te, a[k].nw, a[k].f); - // } - kv_push(uint64_t, *sp, (((uint64_t)a[k].qs)<<32)|((uint64_t)a[k].qe)); - } - for (k = 0; k < ol->length; k++) { - // if(b->olist.list[k].non_homopolymer_errors == 0) continue;///exact match is not trans - s = ol->list[k].x_pos_s; e = ol->list[k].x_pos_e+1; - kv_push(uint64_t, *sp, (((uint64_t)s)<<32)|((uint64_t)e)); - } - - if(sp->n > 1) { - radix_sort_gfa64(sp->a, sp->a + sp->n); - for (k = z = 0; k < sp->n; k++) { - s = sp->a[k]>>32; e = (uint32_t)sp->a[k]; - if(z > 0 && s <= ((uint32_t)sp->a[z-1])) { - if(e > ((uint32_t)sp->a[z-1])) { - sp->a[z-1] >>= 32; sp->a[z-1] <<= 32; sp->a[z-1] |= e; - } - } else { - sp->a[z++] = sp->a[k]; - } - } - sp->n = z; - } - for (k = l = 0; k < sp->n; k++) l += (((uint32_t)sp->a[k]) - (sp->a[k]>>32)); - - // if(rid == 7) { - // fprintf(stderr, "\n[M::%s] utg%.6lu%c, rid::%lu, l::%lu, len::%lu, sp->n::%u\n", - // __func__, rid+1, "lc"[ug->u.a[rid].circ], rid, l, len, (uint32_t)sp->n); - // for (k = 0; k < a_n; k++) { - // if(a[k].del) continue; - // fprintf(stderr, "0\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\n", - // a[k].qn+1, "lc"[ug->u.a[a[k].qn].circ], ug->u.a[a[k].qn].len, - // a[k].qs, a[k].qe, "+-"[a[k].rev], - // a[k].tn+1, "lc"[ug->u.a[a[k].tn].circ], ug->u.a[a[k].tn].len, - // a[k].ts, a[k].te, a[k].nw, a[k].f); - // } - // for (k = 0; k < ol->length; k++) { - // overlap_region *z = &(ol->list[k]); - // fprintf(stderr, "1\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", - // z->x_id+1, "lc"[ug->u.a[z->x_id].circ], ug->u.a[z->x_id].len, - // z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[ug->u.a[z->y_id].circ], ug->u.a[z->y_id].len, - // z->y_pos_s, z->y_pos_e+1); - // } - // for (k = 0; k < sp->n; k++) { - // fprintf(stderr, "in::[%lu, %u)\n", (sp->a[k]>>32), ((uint32_t)sp->a[k])); - // } - // } - if((l > 0) && (l >= (len*0.8))) return 1; - // fprintf(stderr, "\n[M::%s] utg%.6lu%c, rid::%lu, l::%lu, len::%lu, sp->n::%u\n", - // __func__, rid+1, "lc"[ug->u.a[rid].circ], rid, l, len, (uint32_t)sp->n); - return 0; -} - -uint32_t is_mmhom_node(uint64_t *ca, ma_utg_t *u, asg_t *sg, uint64_t cov_bd, double cut_rate) -{ - if(cut_rate < 0) cut_rate = 0; if(cut_rate > 1.0) cut_rate = 1.0; - uint64_t k, a, na, a_cut = u->n*cut_rate, na_cut = u->n*(1.0-cut_rate); - for (k = a = na = 0; k < u->n; k++) { - if(ca[k] > (cov_bd*((uint64_t)sg->seq[u->a[k]>>33].len))) { - a++; if((a) && (a>=a_cut)) return 1; - } else { - na++; if((na) && (na>=na_cut)) return 0; - } - } - - if((a) && (a>=a_cut)) return 1; - return 0; -} - -uint32_t test_het_aln_mmhap(uint64_t uid, ug_rid_cov_t *ccov, u_trans_t *a, uint64_t a_n, overlap_region_alloc* ol, st_mt_t *sp) -{ - uint64_t k; u_trans_t p; - if(a_n == 0 && ol->length == 0) return 0; - kv_resize(uint64_t, *sp, ccov->ug->u.a[uid].n); - memcpy(sp->a, ccov->cov.a+ccov->idx[uid], sizeof((*(sp->a)))*ccov->ug->u.a[uid].n); - - for (k = 0; k < a_n; k++) { - if(a[k].del) continue; - append_cov_line_ug_rid_cov_t(uid, sp->a, &(a[k]), ccov, ((uint64_t)-1), -1); - } - for (k = 0; k < ol->length; k++) { - p.qn = uid; p.tn = ol->list[k].y_id; - p.rev = ol->list[k].y_pos_strand; p.f = RC_3; p.nw = 0; - p.qs = ol->list[k].x_pos_s; p.qe = ol->list[k].x_pos_e+1; - if(p.rev) { - p.ts = ccov->ug->u.a[p.tn].len - (ol->list[k].y_pos_e+1); - p.te = ccov->ug->u.a[p.tn].len - ol->list[k].y_pos_s; - } else { - p.ts = ol->list[k].y_pos_s; - p.te = ol->list[k].y_pos_e+1; - } - append_cov_line_ug_rid_cov_t(uid, sp->a, &p, ccov, ((uint64_t)-1), -1); - } - - return is_mmhom_node(sp->a, &(ccov->ug->u.a[uid]), ccov->rg, ccov->hom_min, 0.8); -} - -void push_ul_ov_t(ul_idx_t *udb, u_trans_t *a, uint64_t a_n, uint64_t rid, st_mt_t *sp, overlap_region_alloc* ol, uint64_t len, uint64_t is_arc_filter, double max_err, kv_ul_ov_t *res) -{ - uint64_t cnt, z, k, l, m, spn; ul_ov_t *p; - sp->n = 0; - if(a_n) { - for (k = sp->n = 0; k < a_n; k++) { - if(a[k].del) continue; - z = a[k].tn; z <<= 1; z |= a[k].rev; z <<= 32; - z |= k; z |= ((uint64_t)0x80000000); - kv_push(uint64_t, *sp, z); - } - for (k = 0; k < ol->length; k++) { - z = ol->list[k].y_id; z <<= 1; - z |= ol->list[k].y_pos_strand; - z <<= 32; z |= k; - kv_push(uint64_t, *sp, z); - } - - radix_sort_gfa64(sp->a, sp->a + sp->n); spn = sp->n; - for (k = 1, l = m = 0; k <= spn; k++) { - if(k == spn || (sp->a[l]>>32)!=(sp->a[k]>>32)) { - if((sp->a[l]&((uint64_t)0x80000000))) {///no overlap within ol - for (z = l; z < k; z++) { - sp->a[m++] = (uint32_t)(sp->a[z]-((uint64_t)0x80000000)); - } - } - l = k; - } - } - sp->n = m; - } - - if(ol->length > 0) { - cnt = res->n + ol->length; kv_resize(ul_ov_t, (*res), cnt); - for (k = 0/**, bn = res->n**/; k < ol->length; k++) { - // if(b->olist.list[k].non_homopolymer_errors == 0) continue;///exact match is not trans - kv_pushp(ul_ov_t, (*res), &p); - p->qn = rid; p->tn = ol->list[k].y_id; p->el = 1; - p->sec = ol->list[k].non_homopolymer_errors; - p->rev = ol->list[k].y_pos_strand; - p->qs = ol->list[k].x_pos_s; p->qe = ol->list[k].x_pos_e+1; - if(p->rev) { - p->ts = udb->ug->u.a[p->tn].len - (ol->list[k].y_pos_e+1); - p->te = udb->ug->u.a[p->tn].len - ol->list[k].y_pos_s; - } else { - p->ts = ol->list[k].y_pos_s; - p->te = ol->list[k].y_pos_e+1; - } - // fprintf(stderr, ">0<[M::%s] utg%.6u%c -> utg%.6u%c\n", __func__, - // p->qn+1, "lc"[s->udb.ug->u.a[p->qn].circ], - // p->tn+1, "lc"[s->udb.ug->u.a[p->tn].circ]); - // if(p->ts >= p->te || p->qs >= p->qe) { - // fprintf(stderr, "+[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, - // p->qn+1, "lc"[udb->ug->u.a[p->qn].circ], udb->ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], - // p->tn+1, "lc"[udb->ug->u.a[p->tn].circ], udb->ug->u.a[p->tn].len, p->ts, p->te); - // } - if((is_arc_filter) && (!trans_ovlp_connect(p, udb->ug))) res->n--; - // fprintf(stderr, ">1<[M::%s] utg%.6u%c -> utg%.6u%c\n", __func__, - // p->qn+1, "lc"[s->udb.ug->u.a[p->qn].circ], - // p->tn+1, "lc"[s->udb.ug->u.a[p->tn].circ]); - // else { - // if(i == 5) - // { - // fprintf(stderr, ">>>utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", - // p->qn+1, "lc"[udb->ug->u.a[p->qn].circ], udb->ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], - // p->tn+1, "lc"[udb->ug->u.a[p->tn].circ], udb->ug->u.a[p->tn].len, p->ts, p->te); - // } - // } - } - - for (k = 0; k < sp->n; k++) { - kv_pushp(ul_ov_t, (*res), &p); - p->qn = a[sp->a[k]].qn; p->tn = a[sp->a[k]].tn; - p->rev = a[sp->a[k]].rev; p->el = 0; - p->qs = a[sp->a[k]].qs; p->qe = a[sp->a[k]].qe; - p->ts = a[sp->a[k]].ts; p->te = a[sp->a[k]].te; - p->sec = (p->qe-p->qs)*max_err; - // if(p->ts >= p->te || p->qs >= p->qe) { - // fprintf(stderr, "-[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, - // p->qn+1, "lc"[udb->ug->u.a[p->qn].circ], udb->ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], - // p->tn+1, "lc"[udb->ug->u.a[p->tn].circ], udb->ug->u.a[p->tn].len, p->ts, p->te); - // } - } - - // if(is_sec_filter) { - // cnt = filter_sec_trans_ovlp(res->a+bn, res->n-bn, rid, sec_rate) + bn; - // res->n = cnt; - // } - // fprintf(stderr, "-1-[M::%s] utg%.6u%c, # ov::%lu\n", - // __func__, (uint32_t)i+1, "lc"[s->ug->u.a[i].circ], cnt - bn); - } -} - -void backward_dedup_ol(uint64_t rid, kv_ul_ov_t *bck, st_mt_t *sp, overlap_region_alloc* ol) -{ - int64_t i, m; uint64_t z, k, l; overlap_region t; - - kv_resize(uint64_t, *sp, ol->length); - for (i = ((int64_t)bck->n)-1, sp->n = 0; i >= 0 && bck->a[i].qn == rid; i--) { - z = bck->a[i].tn; z <<= 1; z |= bck->a[i].rev; z <<= 32; - kv_push(uint64_t, *sp, z); - } - if(!(sp->n)) return;///no bck overlap - - kv_resize(uint64_t, *sp, (ol->length)+sp->n); - for (k = 0; k < ol->length; k++) { - z = ol->list[k].y_id; z <<= 1; z |= ol->list[k].y_pos_strand; - z <<= 32; z |= k; z |= ((uint64_t)0x80000000); - kv_push(uint64_t, *sp, z); - } - - radix_sort_gfa64(sp->a, sp->a + sp->n); - for (k = 1, l = 0, m = 0; k <= sp->n; k++) { - if(k == sp->n || (sp->a[l]>>32)!=(sp->a[k]>>32)) { - if((k - l > 1) && (!(sp->a[l]&((uint64_t)0x80000000)))) {///overlap within bck - for (z = l; z < k; z++) { - if(sp->a[z]&((uint64_t)0x80000000)) { - ol->list[(uint32_t)(sp->a[z]-((uint64_t)0x80000000))].y_id = (uint32_t)-1; - m++; - } - } - } - l = k; - } - } - if(m > 0) { - for (k = z = 0; k < ol->length; k++) { - if(ol->list[k].y_id == (uint32_t)-1) continue; - if(z != k) { - t = ol->list[z]; - ol->list[z] = ol->list[k]; - ol->list[k] = t; - } - z++; - } - ol->length = z; - } - -} - -void remove_trans_ovlp_connect(ma_ug_t *ug, uint64_t rid, kv_ul_ov_t *bck) -{ - int64_t i; uint64_t m, k; - for (i = ((int64_t)bck->n)-1; i >= 0 && bck->a[i].qn == rid; i--); - m = i + 1; - if(m >= bck->n) return; - for (k = m; k < bck->n; k++) { - if(!trans_ovlp_connect(&(bck->a[k]), ug)) continue; - bck->a[m++] = bck->a[k]; - } - bck->n = m; -} - -uint64_t gen_trans_adaptive_aln(ug_trans_t *s, uint64_t rid, ha_ovec_buf_t *b, kv_ul_ov_t *bl, char *seq, uint64_t len, kv_u_trans_t *fi, - double err_low, double err_high, double bw_low, double bw_high) -{ - uint64_t cnt = ((s->idx_n.a[rid+1]-s->idx_n.a[rid])), ol_h = 0, pass_aln = 0; - uint32_t high_occ = asm_opt.polyploidy + 1; overlap_region *aux_o = NULL; - ///note: high_occ is different - ug_map_lchain(b->abl, rid, seq, len, s->w, s->k, &(s->udb), &b->olist, &b->clist, bw_low, bw_high, - s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, - s->is_HPC, s->idx_a.a + s->idx_n.a[rid], cnt, s->srt_a.a, s->srt_a.n, s->mini_cut, s->chain_cut, fi); - // if(rid == 160) { - // fprintf(stderr, "-1-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); - // } - ///remove candidate chains that have been calculated - if(!fi) backward_dedup_ol(rid, bl, &(b->sp), &b->olist); - // if(rid == 160) { - // fprintf(stderr, "-2-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); - // } - filter_by_reliable_ovlp_adv(rid, s->filter, &(b->sp), &b->olist, &(s->udb), s->sec_cutoff, 1, 1, &ol_h); - clear_Cigar_record(&b->cigar1); clear_Round2_alignment(&b->round2); - if(!fi) ol_h = 0; - - ol_h = split_ug_lalign(ol_h, &b->olist, err_high, err_low, - &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, - &b->correct, &b->exz, aux_o, rid, s->k, s->chain_cut, NULL); - - aux_o = gen_aux_ovlp(&b->olist);///must be here - - ol_h = split_ug_lalign(ol_h, &b->olist, err_high, err_low, - &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, - &b->correct, &b->exz, aux_o, rid, s->k, s->chain_cut, NULL); - - if(fi) {///first round - pass_aln = test_het_aln(s->ug, rid, u_trans_a((*(s->filter)), rid), u_trans_n((*(s->filter)), rid), &(b->sp), &b->olist, len); - push_ul_ov_t(&(s->udb), u_trans_a((*(s->filter)), rid), u_trans_n((*(s->filter)), rid), rid, &(b->sp), &b->olist, len, pass_aln, err_high, bl); - // fprintf(stderr, "-1-[M::%s] utg%.6lu%c, rid::%lu, pass_aln::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, pass_aln); - } else {///second round - push_ul_ov_t(&(s->udb), NULL, 0, rid, &(b->sp), &b->olist, len, 0, err_high, bl); - remove_trans_ovlp_connect(s->udb.ug, rid, bl); - } - return pass_aln; -} - -void clear_count_buf(ug_trans_t *s, uint32_t tid, uint32_t free_count) -{ - // fprintf(stderr, "[M::%s]\n", __func__); - ha_ovec_buf_t *b = s->hab[tid]; - destory_fake_cigar(&(b->tmp_region.f_cigar)); - free(b->tmp_region.w_list.a); free(b->tmp_region.w_list.c.a); - memset(&(b->tmp_region), 0, sizeof(b->tmp_region)); - init_fake_cigar(&(b->tmp_region.f_cigar)); - memset(&(b->tmp_region.w_list), 0, sizeof(b->tmp_region.w_list)); - CALLOC(b->tmp_region.w_list.a, 1); b->tmp_region.w_list.n = b->tmp_region.w_list.m = 1; - - ha_abufl_destroy(b->abl); b->abl = ha_abufl_init(); - - kv_destroy(b->sp); memset(&(b->sp), 0, sizeof((b->sp))); - if(free_count) return; - - destory_Candidates_list(&b->clist); - memset((&(b->clist)), 0, sizeof(b->clist)); - init_Candidates_list(&b->clist); - - destory_overlap_region_alloc(&b->olist); - memset((&(b->olist)), 0, sizeof(b->olist)); - init_overlap_region_alloc(&b->olist); - - destory_UC_Read(&b->self_read); - memset((&(b->self_read)), 0, sizeof(b->self_read)); - init_UC_Read(&b->self_read); - - destory_UC_Read(&b->ovlp_read); - memset((&(b->ovlp_read)), 0, sizeof(b->ovlp_read)); - init_UC_Read(&b->ovlp_read); - - destory_Correct_dumy(&b->correct); - memset((&(b->correct)), 0, sizeof(b->correct)); - init_Correct_dumy(&b->correct); - - destroy_bit_extz_t(&(b->exz)); - memset((&(b->exz)), 0, sizeof(b->exz)); - init_bit_extz_t(&(b->exz), 31); -} - -static void worker_for_trans_ovlp_adv(void *data, long i, int tid) // callback for kt_for() -{ - ug_trans_t *s = (ug_trans_t*)data; - ha_ovec_buf_t *b = s->hab[tid]; kv_ul_ov_t *bl = &(s->ll[tid].tk); - uint32_t high_occ = asm_opt.polyploidy + 1; uint64_t cnt; - char *seq = s->ug->u.a[i].s; int64_t len = s->ug->u.a[i].len; - if((!s->is_ovlp) && (s->is_cnt)) s->idx_n.a[i] = 0; - if(IF_HOM(i, (*(s->bub))) || s->ug->g->seq[i].del) return; - - // asprintf(&as, "\n[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); - // push_vlog(&(overall_zdbg->a[s->id+i]), as); free(as); as = NULL; - - if(!s->is_ovlp) { - if(s->is_cnt) { - s->idx_n.a[i] = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, - s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, NULL, 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); - } else { - cnt = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, - s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); - assert(cnt == ((s->idx_n.a[i+1]-s->idx_n.a[i]))); - } - if(s->free_cnt[tid] >= FREE_BATCH) { - clear_count_buf(s, tid, 1); s->free_cnt[tid] = 0; - } - s->free_cnt[tid]++; - return; - } - - // if(i == 160) { - // fprintf(stderr, "\n-1-[M::%s] utg%.6u%c, rid::%ld, is_ovlp::%d, is_cnt::%d, len::%ld, str::%u\n", - // __func__, (uint32_t)i+1, "lc"[s->ug->u.a[i].circ], i, s->is_ovlp, s->is_cnt, len, (uint32_t)(!!seq)); - // } - - if(!gen_trans_adaptive_aln(s, i, b, bl, seq, len, s->filter, s->diff_ec_ul, s->diff_ec_ul_double, s->bw_thres, s->bw_thres_double)) { - gen_trans_adaptive_aln(s, i, b, bl, seq, len, NULL, s->diff_ec_ul_double, s->diff_ec_ul_double, s->bw_thres_double, s->bw_thres_double); - } - - if(s->free_cnt[tid] >= FREE_BATCH) { - clear_count_buf(s, tid, 0); s->free_cnt[tid] = 0; - } - s->free_cnt[tid]++; -} - -uint64_t *gen_reliable_cov_arr(uint32_t id, kv_u_trans_t *idx, ug_rid_cov_t *ccov, st_mt_t *sp) -{ - u_trans_t *a; uint64_t n, k; - a = u_trans_a(*idx, id); n = u_trans_n(*idx, id); - kv_resize(uint64_t, *sp, ccov->ug->u.a[id].n); - memcpy(sp->a, ccov->cov.a+ccov->idx[id], sizeof((*(sp->a)))*ccov->ug->u.a[id].n); - for (k = 0; k < n; k++) { - if(a[k].del) continue; - if(a[k].f == RC_0 || a[k].f == RC_1) { - append_cov_line_ug_rid_cov_t(id, sp->a, &(a[k]), ccov, ((uint64_t)-1), -1); - } - } - return sp->a; -} - -uint64_t is_above_cov(uint64_t uid, overlap_region *o, uint64_t *fc, ug_rid_cov_t *ccov, double sec_rate) -{ - u_trans_t p; - p.qn = uid; p.tn = o->y_id; - p.rev = o->y_pos_strand; p.f = RC_3; p.nw = 0; - p.qs = o->x_pos_s; p.qe = o->x_pos_e+1; - if(p.rev) { - p.ts = ccov->ug->u.a[p.tn].len - (o->y_pos_e+1); - p.te = ccov->ug->u.a[p.tn].len - o->y_pos_s; - } else { - p.ts = o->y_pos_s; - p.te = o->y_pos_e+1; - } - - if(append_cov_line_ug_rid_cov_t(uid, fc, &p, ccov, ccov->hom_max, sec_rate)) return 0; - return 1; -} - -void filter_by_reliable_ovlp_mmhap_adv(uint32_t id, kv_u_trans_t *idx, st_mt_t *sp, overlap_region_alloc* ol, const ul_idx_t *udb, double sec_rate, uint64_t avoid_dup_aln, -uint64_t dedup_by_reliable_ovlp, ug_rid_cov_t *ccov, uint64_t *occ1) -{ - (*occ1) = 0; - u_trans_t *a; uint64_t n, k, l, z, rr, r1, *fc; overlap_region *m, t; - a = u_trans_a(*idx, id); n = u_trans_n(*idx, id); - if(avoid_dup_aln) { - kv_resize(uint64_t, *sp, (ol->length)+n); - for (k = sp->n = 0; k < n; k++) { - if(a[k].del) continue; - if(a[k].f == RC_0 || a[k].f == RC_1) { - z = a[k].tn; z <<= 1; z |= a[k].rev; z <<= 32; - kv_push(uint64_t, *sp, z); - } - } - if(sp->n > 0) { - for (k = 0; k < ol->length; k++) { - z = ol->list[k].y_id; z <<= 1; z |= ol->list[k].y_pos_strand; - z <<= 32; z |= k; z |= ((uint64_t)0x80000000); - kv_push(uint64_t, *sp, z); - } - - radix_sort_gfa64(sp->a, sp->a + sp->n); - for (k = 1, l = 0, rr = 0; k <= sp->n; k++) { - if(k == sp->n || (sp->a[l]>>32)!=(sp->a[k]>>32)) { - if((k - l > 1) && (!(sp->a[l]&((uint64_t)0x80000000)))) {///overlap within bck - for (z = l; z < k; z++) { - if(sp->a[z]&((uint64_t)0x80000000)) { - ol->list[(uint32_t)(sp->a[z]-((uint64_t)0x80000000))].y_id = ((uint32_t)-1); - rr++; - } - } - } - l = k; - } - } - - if(rr > 0) { - for (k = rr = 0; k < ol->length; k++) { - if(ol->list[k].y_id == ((uint32_t)-1)) continue; - if(rr != k) { - t = ol->list[rr]; - ol->list[rr] = ol->list[k]; - ol->list[k] = t; - } - rr++; - } - ol->length = rr; - } - } - } - - sp->n = 0; fc = NULL; - if(dedup_by_reliable_ovlp) { - for (k = 0; k < n; k++) { - if(a[k].del) continue; - if(a[k].f == RC_0 || a[k].f == RC_1) break; - } - if(k < n) fc = gen_reliable_cov_arr(id, idx, ccov, sp); - } - - for (k = rr = r1 = 0; k < ol->length; k++) { - m = &(ol->list[k]); - if((dedup_by_reliable_ovlp) && (m->x_pos_strand == 0) && (fc)) { - if(is_above_cov(id, m, fc, ccov, sec_rate)) continue; - } - - if(rr != k) { - t = ol->list[k]; - ol->list[k] = ol->list[rr]; - ol->list[rr] = t; - } - if(ol->list[rr].x_pos_strand) { - ol->list[rr].x_pos_strand = 0; - if(r1 != rr) { - t = ol->list[r1]; - ol->list[r1] = ol->list[rr]; - ol->list[rr] = t; - } - r1++; - } - rr++; - } - // if(id == 1576) { - // fprintf(stderr, "[M::%s] utg%.6ul, ol->length0::%lu, ol->length::%lu\n", __func__, id+1, ol->length, rr); - // } - ol->length = rr; (*occ1) = r1; -} - - -uint64_t gen_trans_adaptive_mmhap_aln(ug_trans_t *s, uint64_t rid, ha_ovec_buf_t *b, kv_ul_ov_t *bl, char *seq, uint64_t len, kv_u_trans_t *fi, double err_low, double err_high, double bw_low, double bw_high) -{ - uint64_t cnt = ((s->idx_n.a[rid+1]-s->idx_n.a[rid])), ol_h = 0, pass_aln = 0; - uint32_t high_occ = asm_opt.polyploidy + 1; overlap_region *aux_o = NULL; - ///note: high_occ is different - ug_map_lchain(b->abl, rid, seq, len, s->w, s->k, &(s->udb), &b->olist, &b->clist, bw_low, bw_high, - s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, - s->is_HPC, s->idx_a.a + s->idx_n.a[rid], cnt, s->srt_a.a, s->srt_a.n, s->mini_cut, s->chain_cut, fi); - // if(rid == 57) { - // fprintf(stderr, "-1-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); - // } - ///remove candidate chains that have been calculated - if(!fi) backward_dedup_ol(rid, bl, &(b->sp), &b->olist);///it is ok - // if(rid == 57) { - // fprintf(stderr, "-2-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); - // } - filter_by_reliable_ovlp_mmhap_adv(rid, s->filter, &(b->sp), &b->olist, &(s->udb), s->sec_cutoff, 1, 1, s->ccov, &ol_h); - clear_Cigar_record(&b->cigar1); clear_Round2_alignment(&b->round2); - if(!fi) ol_h = 0; - - // if(rid == 57) { - // fprintf(stderr, "-3-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); - // } - - ol_h = split_ug_lalign(ol_h, &b->olist, err_high, err_low, - &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, - &b->correct, &b->exz, aux_o, rid, s->k, s->chain_cut, NULL); - - // if(rid == 57) { - // fprintf(stderr, "-4-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); - // } - - aux_o = gen_aux_ovlp(&b->olist);///must be here - - // if(rid == 57) { - // fprintf(stderr, "-5-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); - // } - - ol_h = split_ug_lalign(ol_h, &b->olist, err_high, err_low, - &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, - &b->correct, &b->exz, aux_o, rid, s->k, s->chain_cut, NULL); - - // if(rid == 57) { - // fprintf(stderr, "-6-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); - // } - - if(fi) {///first round - pass_aln = test_het_aln_mmhap(rid, s->ccov, u_trans_a((*(s->filter)), rid), u_trans_n((*(s->filter)), rid), &b->olist, &(b->sp)); - push_ul_ov_t(&(s->udb), u_trans_a((*(s->filter)), rid), u_trans_n((*(s->filter)), rid), rid, &(b->sp), &b->olist, len, pass_aln, err_high, bl); - // fprintf(stderr, "-1-[M::%s] utg%.6lu%c, rid::%lu, pass_aln::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, pass_aln); - } else {///second round - push_ul_ov_t(&(s->udb), NULL, 0, rid, &(b->sp), &b->olist, len, 0, err_high, bl); - remove_trans_ovlp_connect(s->udb.ug, rid, bl); - } - return pass_aln; -} - -static void worker_for_trans_ovlp_mmhap_adv(void *data, long i, int tid) // callback for kt_for() -{ - ug_trans_t *s = (ug_trans_t*)data; - ha_ovec_buf_t *b = s->hab[tid]; kv_ul_ov_t *bl = &(s->ll[tid].tk); - uint32_t high_occ = asm_opt.polyploidy + 1; uint64_t cnt; - char *seq = s->ug->u.a[i].s; int64_t len = s->ug->u.a[i].len; - if((!s->is_ovlp) && (s->is_cnt)) s->idx_n.a[i] = 0; - if(s->ug->g->seq[i].del) return; - if(is_mmhom_node(s->ccov->cov.a+s->ccov->idx[i], &(s->ug->u.a[i]), s->ccov->rg, s->ccov->hom_min, 0.9)) return; - // asprintf(&as, "\n[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); - // push_vlog(&(overall_zdbg->a[s->id+i]), as); free(as); as = NULL; - - if(!s->is_ovlp) { - if(s->is_cnt) { - s->idx_n.a[i] = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, - s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, NULL, 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); - } else { - cnt = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, - s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); - assert(cnt == ((s->idx_n.a[i+1]-s->idx_n.a[i]))); - } - if(s->free_cnt[tid] >= FREE_BATCH) { - clear_count_buf(s, tid, 1); s->free_cnt[tid] = 0; - } - s->free_cnt[tid]++; - return; - } - - // if(i == 58) { - // fprintf(stderr, "\n-1-[M::%s] utg%.6u%c, rid::%ld, is_ovlp::%d, is_cnt::%d, len::%ld, str::%u\n", - // __func__, (uint32_t)i+1, "lc"[s->ug->u.a[i].circ], i, s->is_ovlp, s->is_cnt, len, (uint32_t)(!!seq)); - // } - - if(!gen_trans_adaptive_mmhap_aln(s, i, b, bl, seq, len, s->filter, s->diff_ec_ul, s->diff_ec_ul_double, s->bw_thres, s->bw_thres_double)) { - gen_trans_adaptive_mmhap_aln(s, i, b, bl, seq, len, NULL, s->diff_ec_ul_double, s->diff_ec_ul_double, s->bw_thres_double, s->bw_thres_double); - } - if(s->free_cnt[tid] >= FREE_BATCH) { - clear_count_buf(s, tid, 0); s->free_cnt[tid] = 0; - } - s->free_cnt[tid]++; -} - -uint32_t tranfor_ovlp(u_trans_t *qovlp, u_trans_t *tovlp, asg_t *g, ul_ov_t *res, uint32_t adjust_rev) -{ - int64_t os, oe, s_shift, e_shift, tt, qs, qe, ts, te; - os = MAX(qovlp->ts, tovlp->qs); - oe = MIN(qovlp->te, tovlp->qe); - if(oe <= os) return 0; - - ///[os, oe) -> qovlp->t* - s_shift = get_offset_adjust(os-qovlp->ts, qovlp->te-qovlp->ts, qovlp->qe-qovlp->qs); - e_shift = get_offset_adjust(qovlp->te-oe, qovlp->te-qovlp->ts, qovlp->qe-qovlp->qs); - if(qovlp->rev) { - tt = s_shift; s_shift = e_shift; e_shift = tt; - } - qs = qovlp->qs+s_shift; qe = ((int64_t)qovlp->qe)-e_shift; - if(qs >= qe) return 0; - - ///[os, oe) -> tovlp->q* - s_shift = get_offset_adjust(os-tovlp->qs, tovlp->qe-tovlp->qs, tovlp->te-tovlp->ts); - e_shift = get_offset_adjust(tovlp->qe-oe, tovlp->qe-tovlp->qs, tovlp->te-tovlp->ts); - if(tovlp->rev) { - tt = s_shift; s_shift = e_shift; e_shift = tt; - } - ts = tovlp->ts+s_shift; te = ((int64_t)tovlp->te)-e_shift; - if(ts >= te) return 0; - - memset(res, 0, sizeof(*res)); - res->qn = qovlp->qn; res->qs = qs; res->qe = qe; - res->tn = tovlp->tn; res->ts = ts; res->te = te; - res->rev = ((qovlp->rev == tovlp->rev)?0:1); - if(adjust_rev && res->rev) {///for linear chaining - res->ts = g->seq[res->tn].len - te; - res->te = g->seq[res->tn].len - ts; - } - return 1; -} - -uint32_t rescue_adject_ovlp(asg_t *g, uint32_t id, kv_u_trans_t *ta, kv_ul_ov_t *out, st_mt_t *buf) -{ - u_trans_t *a, *b; ul_ov_t rr; uint64_t a_n, b_n, k, l, i, z, m; - a = u_trans_a((*ta), id); a_n = u_trans_n((*ta), id); - for (i = out->n = buf->n = 0; i < a_n; i++) { - b = u_trans_a((*ta), a[i].tn); b_n = u_trans_n((*ta), a[i].tn); - z = a[i].tn; z <<= 32; kv_push(uint64_t, *buf, z); - for (k = 0; k < b_n; k++) { - if(b[k].tn == id) continue; - if(!tranfor_ovlp(&(a[i]), &(b[k]), g, &rr, 1)) continue; - z = rr.tn; z <<= 32; z |= out->n; z |= ((uint64_t)0x80000000); - rr.tn <<= 1; rr.tn |= rr.rev; kv_push(ul_ov_t, *out, rr); - } - } - if(out->n == 0) return 1; - - radix_sort_gfa64(buf->a, buf->a + buf->n); - for (k = 1, l = m = 0; k <= buf->n; k++) { - if(k == buf->n || (buf->a[l]>>32)!=(buf->a[k]>>32)) { - if((k - l > 1) && (!(buf->a[l]&((uint64_t)0x80000000)))) {///overlap within bck - for (z = l; z < k; z++) { - if(buf->a[z]&((uint64_t)0x80000000)) { - out->a[(uint32_t)(buf->a[z]-((uint64_t)0x80000000))].tn = (uint32_t)-1; - m++; - } - } - } - l = k; - } - } - - if(m) { - for (k = m = 0; k < out->n; k++) { - if(out->a[k].tn == (uint32_t)-1) continue; - out->a[m++] = out->a[k]; - } - out->n = m; - } - if(out->n == 0) return 1; - - radix_sort_ul_ov_srt_tn(out->a, out->a+out->n); - for (k = 0; k < out->n; k++) out->a[k].tn >>= 1; - - return 0; -} - -/** -uint64_t gen_trans_chain_mmhap(ug_trans_t *s, uint64_t rid, ha_ovec_buf_t *b, kv_ul_ov_t *bl, char *seq, uint64_t len, -double err, double bw) -{ - uint64_t cnt = ((s->idx_n.a[rid+1]-s->idx_n.a[rid])), ol_h = 0, pass_aln = 0; - uint32_t high_occ = asm_opt.polyploidy + 1; overlap_region *aux_o = NULL; - ///note: high_occ is different - ug_map_lchain(b->abl, rid, seq, len, s->w, s->k, &(s->udb), &b->olist, &b->clist, bw, bw, - s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, - s->is_HPC, s->idx_a.a + s->idx_n.a[rid], cnt, s->srt_a.a, s->srt_a.n, s->mini_cut, s->chain_cut, NULL); - // if(rid == 57) { - // fprintf(stderr, "-1-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); - // } - ///remove candidate chains that have been calculated - if(!fi) backward_dedup_ol(rid, bl, &(b->sp), &b->olist);///it is ok - // if(rid == 57) { - // fprintf(stderr, "-2-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); - // } - filter_by_reliable_ovlp_mmhap_adv(rid, s->filter, &(b->sp), &b->olist, &(s->udb), s->sec_cutoff, 1, 1, s->ccov, &ol_h); - clear_Cigar_record(&b->cigar1); clear_Round2_alignment(&b->round2); - if(!fi) ol_h = 0; - - // if(rid == 57) { - // fprintf(stderr, "-3-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); - // } - - ol_h = split_ug_lalign(ol_h, &b->olist, err_high, err_low, - &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, - &b->correct, &b->exz, aux_o, rid, s->k, s->chain_cut, NULL); - - // if(rid == 57) { - // fprintf(stderr, "-4-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); - // } - - aux_o = gen_aux_ovlp(&b->olist);///must be here - - // if(rid == 57) { - // fprintf(stderr, "-5-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); - // } - - ol_h = split_ug_lalign(ol_h, &b->olist, err_high, err_low, - &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, - &b->correct, &b->exz, aux_o, rid, s->k, s->chain_cut, NULL); - - // if(rid == 57) { - // fprintf(stderr, "-6-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); - // } - - if(fi) {///first round - pass_aln = test_het_aln_mmhap(rid, s->ccov, u_trans_a((*(s->filter)), rid), u_trans_n((*(s->filter)), rid), &b->olist, &(b->sp)); - push_ul_ov_t(&(s->udb), u_trans_a((*(s->filter)), rid), u_trans_n((*(s->filter)), rid), rid, &(b->sp), &b->olist, len, pass_aln, err_high, bl); - // fprintf(stderr, "-1-[M::%s] utg%.6lu%c, rid::%lu, pass_aln::%lu\n", - // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, pass_aln); - } else {///second round - push_ul_ov_t(&(s->udb), NULL, 0, rid, &(b->sp), &b->olist, len, 0, err_high, bl); - remove_trans_ovlp_connect(s->udb.ug, rid, bl); - } - return pass_aln; -} -**/ - - - -static void worker_for_trans_chain_mmhap_adv(void *data, long i, int tid) // callback for kt_for() -{ - ug_trans_t *s = (ug_trans_t*)data; - ha_ovec_buf_t *b = s->hab[tid]; kv_ul_ov_t *bl = &(s->ll[tid].tk); - uint32_t high_occ = asm_opt.polyploidy + 1; uint64_t cnt; - char *seq = s->ug->u.a[i].s; int64_t len = s->ug->u.a[i].len; - if((!s->is_ovlp) && (s->is_cnt)) s->idx_n.a[i] = 0; - if(s->ug->g->seq[i].del) return; - if(is_mmhom_node(s->ccov->cov.a+s->ccov->idx[i], &(s->ug->u.a[i]), s->ccov->rg, s->ccov->hom_min, 0.9)) return; - // asprintf(&as, "\n[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); - // push_vlog(&(overall_zdbg->a[s->id+i]), as); free(as); as = NULL; - // if(rescue_adject_ovlp(s->ug->g, i, s->filter, &(s->ll[tid].lo))) return; - - // gen_trans_chain_mmhap(s, i, b, bl, seq, len, 0.8, 0.8); - - if(!s->is_ovlp) { - if(s->is_cnt) { - s->idx_n.a[i] = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, - s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, NULL, 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); - } else { - cnt = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, - s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); - assert(cnt == ((s->idx_n.a[i+1]-s->idx_n.a[i]))); - } - if(s->free_cnt[tid] >= FREE_BATCH) { - clear_count_buf(s, tid, 1); s->free_cnt[tid] = 0; - } - s->free_cnt[tid]++; - return; - } - - // if(i == 58) { - // fprintf(stderr, "\n-1-[M::%s] utg%.6u%c, rid::%ld, is_ovlp::%d, is_cnt::%d, len::%ld, str::%u\n", - // __func__, (uint32_t)i+1, "lc"[s->ug->u.a[i].circ], i, s->is_ovlp, s->is_cnt, len, (uint32_t)(!!seq)); - // } - - if(!gen_trans_adaptive_mmhap_aln(s, i, b, bl, seq, len, s->filter, s->diff_ec_ul, s->diff_ec_ul_double, s->bw_thres, s->bw_thres_double)) { - gen_trans_adaptive_mmhap_aln(s, i, b, bl, seq, len, NULL, s->diff_ec_ul_double, s->diff_ec_ul_double, s->bw_thres_double, s->bw_thres_double); - } - if(s->free_cnt[tid] >= FREE_BATCH) { - clear_count_buf(s, tid, 0); s->free_cnt[tid] = 0; - } - s->free_cnt[tid]++; -} - - -int64_t retrieve_cigar_err_dir(bit_extz_t *ez, int64_t s, int64_t e, int64_t *xk, int64_t *ck, int64_t is_back) -{ ///[ez->ts, ez->te]/[ez->qs, ez->qe]/[s, e) - if(!ez->cigar.n) return 0; - int64_t cn = ez->cigar.n, op, err = 0; int64_t ws, we, os, oe, ovlp; - if(!is_back) { - if(((*ck) < 0) || ((*ck) > cn)) {//(*ck) == cn is allowed - (*ck) = 0; (*xk) = ez->ts; - } - - while ((*ck) > 0 && (*xk) > s) { - --(*ck); - op = ez->cigar.a[(*ck)]>>14; - if(op!=2) (*xk) -= (ez->cigar.a[(*ck)]&(0x3fff)); - } - - //some cigar will span s or e - while ((*ck) < cn && (*xk) < e) {//[s, e) - ws = (*xk); - op = ez->cigar.a[(*ck)]>>14; - if(op!=2) (*xk) += (ez->cigar.a[(*ck)]&(0x3fff)); - we = (*xk); - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - if((op==2) && (ws>=s) && (wscigar.a[(*ck)]&(0x3fff)); - } - (*ck)++; - if((!ovlp) || (!op)) continue; - err += ovlp; - } - } else { - if(((*ck) < 0) || ((*ck) >= cn)) { - (*ck) = cn-1; (*xk) = ez->te + 1; ///[ez->ts, ez->te] - } - while (((*ck) < cn) && ((*xk) < e)) { - ++(*ck); - op = ez->cigar.a[(*ck)]>>14; - if(op!=2) (*xk) += (ez->cigar.a[(*ck)]&(0x3fff)); - } - - //some cigar will span s or e - while ((*ck) >= 0 && (*xk) > s) {//[s, e) - we = (*xk); - op = ez->cigar.a[(*ck)]>>14; - if(op!=2) (*xk) -= (ez->cigar.a[(*ck)]&(0x3fff)); - ws = (*xk); - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - if((op==2) && (ws>=s) && (wscigar.a[(*ck)]&(0x3fff)); - } - (*ck)--; - if((!ovlp) || (!op)) continue; - err += ovlp; - } - } - // int64_t debug_err = retrieve_cigar_err_debug(ez, s, e); - // if(!(err == debug_err)) { - // fprintf(stderr, "[M::%s::] err::%ld, debug_err::%ld, s::%ld, e::%ld, ez->ts::%u, ez->te::%u\n", - // __func__, err, debug_err, s, e, ez->ts, ez->te); - // } - // assert(err == debug_err); - return err; -} - -int64_t cal_cigar_err(overlap_region *z, int64_t s, int64_t e, int64_t is_back)///need debugging -{ - int64_t wn = z->w_list.n, wk, xk, ck; window_list *m; bit_extz_t ez; - int64_t ws, we, os, oe, ovlp, xl, yl, werr, err, tot; - err = 0; tot = e - s; wk = xk = ck = -1; - if(!wn) return INT32_MAX; - - if(!is_back) { - wk = 0; - if(wn) { - xk = z->w_list.a[wk].x_start; ck = 0; - } - while(wk < wn) { - m = &(z->w_list.a[wk]); - ws = m->x_start; we = m->x_end+1; - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - if(ovlp) { - xl = m->x_end+1-m->x_start; - yl = m->y_end+1-m->y_start; - if((is_ualn_win((*m))) || (is_est_aln((*m)))) { - if(is_ualn_win((*m))) { //unmapped - werr = MAX(xl, yl);///gen_err_unaligned(xl, yl); - } else { - werr = m->error;//shared window - } - if(ovlp < xl) { - werr = (((double)ovlp)/((double)xl))*((double)werr); - } - //skip the whole window - err += werr; xk = m->x_end+1; ck = m->clen; - } else { - if(ovlp == xl) { //skip the whole window - err += m->error; xk = m->x_end+1; ck = m->clen; - } else { - set_bit_extz_t(ez, (*z), wk); - err += retrieve_cigar_err_dir(&ez, os, oe, &xk, &ck, is_back); - } - } - } - tot -= ovlp; - if(xk >= e) break;//[min_w, max_w] && [s, e) - wk++; if(wk >= wn) break; - xk = z->w_list.a[wk].x_start; ck = 0;//reset - } - } else { - wk = wn-1; - if(wn) { - xk = z->w_list.a[wk].x_end+1; ck = z->w_list.a[wk].clen-1; - } - while(wk >= 0) { - m = &(z->w_list.a[wk]); - ws = m->x_start; we = m->x_end+1; - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - if(ovlp) { - xl = m->x_end+1-m->x_start; - yl = m->y_end+1-m->y_start; - if((is_ualn_win((*m))) || (is_est_aln((*m)))) { - if(is_ualn_win((*m))) { //unmapped - werr = MAX(xl, yl);///gen_err_unaligned(xl, yl); - } else { - werr = m->error;//shared window - } - if(ovlp < xl) { - werr = (((double)ovlp)/((double)xl))*((double)werr); - } - //skip the whole window - err += werr; xk = m->x_start; ck = -1; - } else { - if(ovlp == xl) { //skip the whole window - err += m->error; xk = m->x_start; ck = -1; - } else { - set_bit_extz_t(ez, (*z), wk); - err += retrieve_cigar_err_dir(&ez, os, oe, &xk, &ck, is_back); - } - } - } - tot -= ovlp; - if(xk <= s) break;//[s, e) - wk--; if(wk < 0) break; - xk = z->w_list.a[wk].x_end+1; ck = z->w_list.a[wk].clen-1;//reset - } - } - assert(!tot); - return err; -} - -uint64_t get_high_simi(overlap_region *z, double erate, uint64_t maxe, uint64_t minov, uint64_t *re0, uint64_t *re1) -{ - uint64_t ol, err = z->non_homopolymer_errors, e0, e1, f0 = 0, f1 = 0; - ol = z->x_pos_e+1-z->x_pos_s; (*re0) = (*re1) = (uint64_t)-1; - if(ol > (z->y_pos_e+1-z->y_pos_s)) ol = z->y_pos_e+1-z->y_pos_s; - if((err <= (ol*erate)) && (err <= maxe)) return 1; - if(ol <= minov) return 0;///too short - e0 = cal_cigar_err(z, 0, minov, 0); - e1 = cal_cigar_err(z, z->x_pos_e+1-minov, z->x_pos_e+1, 1); - if((e0 <= (minov*erate)) && (e0 <= maxe)) f0 = 1; - if((e1 <= (minov*erate)) && (e1 <= maxe)) f1 = 1; - if(f0 && f1 && (ol <= (minov<<1))) { - if(e0 >= e1) f0 = 0; - else f1 = 0; - } - if((!f0) && (!f1)) return 0; - if(f0) (*re0) = e0; - if(f1) (*re1) = e1; - return 2; -} - -int64_t hpc_check_naive(hpc_ss_t *a, int64_t n, int64_t s, int64_t e, int64_t bd) -{ - int64_t k, os, oe; - for (k = 0; k < n; k++) { - os = MAX(s, a[k].s); oe = MIN(e, a[k].e); - if(oe - os >= -bd) return 1; - if(a[k].s > (uint64_t)(e + bd)) break; - } - return 0; -} - -int64_t hpc_check(hpc_ss_t *a, int64_t n, int64_t s, int64_t e, int64_t *idx, int64_t bd) -{ - if(n<=0) return 0; - if((*idx) >= n) (*idx) = n - 1; - if((*idx) < 0) (*idx) = 0; - int64_t k = (*idx), os, oe; - for (; k < n; k++) { - os = MAX(s, a[k].s); oe = MIN(e, a[k].e); - if(oe - os >= -bd) { - (*idx) = k; return 1; - } - if(a[k].s > (uint64_t)(e + bd)) break; - } - os = (*idx); (*idx) = k; k = os - 1; - for (; k >= 0; k--) { - os = MAX(s, a[k].s); oe = MIN(e, a[k].e); - if(oe - os >= -bd) { - (*idx) = k; return 1; - } - } - // assert(!hpc_check_naive(a, n, s, e, bd)); - return 0; -} - -int64_t retrieve_npc_cigar_err(bit_extz_t *ez, int64_t s, int64_t e, int64_t *xk, int64_t *yk, int64_t *ck, -hpc_ss_t *fx, int64_t nx, hpc_ss_t *fy, int64_t ny, int64_t ylen, int64_t is_rev)///[s, e) for x -{ - if(!ez->cigar.n) return 0; - int64_t cn = ez->cigar.n, op, err = 0; int64_t ws, we, ws1, we1, os, oe, ovlp, xi, yi; - if(((*ck) < 0) || ((*ck) > cn)) {//(*ck) == cn is allowed - (*ck) = 0; (*xk) = ez->ts; (*yk) = ez->ps; - } - while ((*ck) > 0 && (*xk) > s) { - --(*ck); - op = ez->cigar.a[(*ck)]>>14; - if(op!=2) (*xk) -= (ez->cigar.a[(*ck)]&(0x3fff)); - if(op!=3) (*yk) -= (ez->cigar.a[(*ck)]&(0x3fff)); - } - xi = yi = 0; if(nx<=0) fx = NULL; if(ny<=0) fy = NULL; - - //some cigar will span s or e - while ((*ck) < cn && (*xk) < e) {//[s, e) - ws = (*xk); ws1 = (*yk); - op = ez->cigar.a[(*ck)]>>14; - if(op!=2) (*xk) += (ez->cigar.a[(*ck)]&(0x3fff)); - if(op!=3) (*yk) += (ez->cigar.a[(*ck)]&(0x3fff)); - we = (*xk); we1 = (*yk); - os = MAX(s, ws); oe = MIN(e, we); - ovlp = ((oe>os)? (oe-os):0); - if((op==2) && (ws>=s) && (wscigar.a[(*ck)]&(0x3fff)); - } - (*ck)++; - if((!ovlp) || (!op)) continue; - if(fx && hpc_check(fx, nx, ws, we, &xi, 1)) continue; - if(fy && hpc_check(fy, ny, ((is_rev)?(ylen-we1):(ws1)), ((is_rev)?(ylen-ws1):(we1)), &yi, 1)) continue; - err += ovlp; - } - return err; -} - -///[s, e) for x -int64_t cal_npc_err(overlap_region *z, int64_t xs, int64_t xe, hpc_re_t *hre, int64_t ylen) -{ - int64_t wn = z->w_list.n, wk, xk, yk, ck; window_list *m; bit_extz_t ez; - int64_t ws, we, os, oe, ovlp, xl, yl, werr, err, tot; - hpc_ss_t *fx = NULL, *fy = NULL; int64_t nx = 0, ny = 0; - err = 0; tot = xe - xs; wk = xk = yk = ck = -1; - if(!wn) return INT32_MAX; - wk = 0; - if(wn) { - xk = z->w_list.a[wk].x_start; yk = z->w_list.a[wk].y_start; ck = 0; - } - if(hre) { - fx = hre->a + hre->idx[z->x_id].s; nx = hre->idx[z->x_id].e - hre->idx[z->x_id].s; - fy = hre->a + hre->idx[z->y_id].s; ny = hre->idx[z->y_id].e - hre->idx[z->y_id].s; - } - // if(hre && ((z->x_id == 44 && z->y_id == 45) || (z->x_id == 45 && z->y_id == 44))) { - // fprintf(stderr, "[M::%s]\tutg%.6ul\tq::[%u,\t%u)\t%c\tutg%.6ul\tt::[%u,\t%u)\terr::%u\twn::%u\n", - // __func__, z->x_id+1, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], - // z->y_id+1, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors, (uint32_t)z->w_list.n); - // } - - while(wk < wn) { - m = &(z->w_list.a[wk]); - // if(hre && ((z->x_id == 44 && z->y_id == 45) || (z->x_id == 45 && z->y_id == 44))) { - // fprintf(stderr, "[M::%s]k::%ld\tq::[%u,\t%u)\tt::[%u,\t%u)\terr::%u\tis_ualn::%u\tis_est::%u\n", - // __func__, wk, m->x_start, m->x_end+1, m->y_start, m->y_end+1, m->error, - // (is_ualn_win((*m))), is_est_aln((*m))); - // } - ws = m->x_start; we = m->x_end+1; - os = MAX(xs, ws); oe = MIN(xe, we); - ovlp = ((oe>os)? (oe-os):0); - if(ovlp) { - xl = m->x_end+1-m->x_start; - yl = m->y_end+1-m->y_start; - if((is_ualn_win((*m))) || (is_est_aln((*m)))) { - if(is_ualn_win((*m))) { //unmapped - werr = MAX(xl, yl);///gen_err_unaligned(xl, yl); - } else { - werr = m->error;//shared window - } - if(ovlp < xl) { - werr = (((double)ovlp)/((double)xl))*((double)werr); - } - //skip the whole window - err += werr; xk = m->x_end+1; yk = m->y_end+1; ck = m->clen; - } else { - if(ovlp == xl) { //skip the whole window - err += m->error; xk = m->x_end+1; yk = m->y_end+1; ck = m->clen; - } else { - set_bit_extz_t(ez, (*z), wk); - err += retrieve_npc_cigar_err(&ez, os, oe, &xk, &yk, &ck, fx, nx, fy, ny, ylen, z->y_pos_strand); - } - } - } - tot -= ovlp; - if(xk >= xe) break;//[min_w, max_w] && [s, e) - wk++; if(wk >= wn) break; - xk = z->w_list.a[wk].x_start; yk = z->w_list.a[wk].y_start; ck = 0;//reset - } - assert(!tot); - return err; -} - -void cal_s_interval(ma_ug_t *ug, asg_arc_t *p, ul_ov_t *res) -{ - memset(res, 0, sizeof((*res))); - res->rev = (((p->ul>>32)^(p->v))&((uint32_t)1)); - res->qn = p->ul>>33; res->tn = p->v>>1; - uint32_t ql = ug->g->seq[res->qn].len, tl = ug->g->seq[res->tn].len; - if((p->ul>>32)&1) { - res->qs = 0; res->qe = ((p->ol<=ql)?(p->ol):(ql)); - } else { - res->qe = ql; res->qs = ((p->ol<=res->qe)?(res->qe-p->ol):(0)); - } - - if(p->v&1) { - res->te = tl; res->ts = ((p->ol<=res->te)?(res->te-p->ol):(0)); - } else { - res->ts = 0; res->te = ((p->ol<=tl)?(p->ol):(tl)); - } -} - -uint32_t infer_se(uint32_t qs, uint32_t qe, uint32_t ts, uint32_t te, uint32_t rev, -uint32_t rqs, uint32_t rqe, uint32_t *rts, uint32_t *rte) -{ - if(rqs <= rqe && rqs >= qs && rqe <= qe) { - uint32_t s_shift, e_shift, m; - s_shift = get_offset_adjust(rqs-qs, qe-qs, te-ts); - e_shift = get_offset_adjust(qe-rqe, qe-qs, te-ts); - if(rev) { - m = s_shift; s_shift = e_shift; e_shift = m; - } - // if(rqs == 2623 && rqe == 17620) { - // fprintf(stderr, "[M::%s]\tqs::%u\tqe::%u\tts::%u\tte::%u\trqs::%u\trqe::%u\ts_shift::%u\te_shift::%u\n", __func__, - // qs, qe, ts, te, rqs, rqe, s_shift, e_shift); - // } - (*rts) = ts + s_shift; (*rte) = te - e_shift; - if((*rts) <= (*rte) && (*rts) >= ts && (*rte) <= te) return 1; - } - (*rts) = (*rte) = (uint32_t)-1; - return 0; -} - -uint32_t cal_x_interval(ma_ug_t *ug, ul_ov_t *v, ul_ov_t *w, ul_ov_t *res) -{ - uint32_t os, oe, rqs, rqe, rts, rte; memset(res, 0, sizeof((*res))); - // if(v->qn == 97) { - // fprintf(stderr, "-0-v-[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\n", __func__, - // v->qn+1, "lc"[ug->u.a[v->qn].circ], v->qs, v->qe, "+-"[v->rev], - // v->tn+1, "lc"[ug->u.a[v->tn].circ], v->ts, v->te); - // fprintf(stderr, "-0-w-[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\n", __func__, - // w->qn+1, "lc"[ug->u.a[w->qn].circ], w->qs, w->qe, "+-"[v->rev], - // w->tn+1, "lc"[ug->u.a[w->tn].circ], w->ts, w->te); - // } - if(v->tn == w->qn) { - os = MAX(v->ts, w->qs); oe = MIN(v->te, w->qe); - // if(v->qn == 97) { - // fprintf(stderr, "-1-[M::%s]\tutg%.6u%c->utg%.6u%c\tutg%.6u%c->utg%.6u%c\to::[%u,\t%u)\n", __func__, - // v->qn+1, "lc"[ug->u.a[v->qn].circ], - // v->tn+1, "lc"[ug->u.a[v->tn].circ], - // w->qn+1, "lc"[ug->u.a[w->qn].circ], - // w->tn+1, "lc"[ug->u.a[w->tn].circ], - // os, oe); - // } - if(oe <= os) return 0; - if(infer_se(v->ts, v->te, v->qs, v->qe, v->rev, os, oe, &rqs, &rqe) && - infer_se(w->qs, w->qe, w->ts, w->te, w->rev, os, oe, &rts, &rte)) { - // if(v->qn == 97) { - // fprintf(stderr, "-2-[M::%s]\tutg%.6u%c->utg%.6u%c\tutg%.6u%c->utg%.6u%c\trq::[%u,\t%u)\trt::[%u,\t%u)\n", __func__, - // v->qn+1, "lc"[ug->u.a[v->qn].circ], - // v->tn+1, "lc"[ug->u.a[v->tn].circ], - // w->qn+1, "lc"[ug->u.a[w->qn].circ], - // w->tn+1, "lc"[ug->u.a[w->tn].circ], - // rqs, rqe, rts, rte); - // } - if(rqe > rqs && rte > rts) { - res->qn = v->qn; res->tn = w->tn; res->rev = ((v->rev==w->rev)?0:1); - res->qs = rqs; res->qe = rqe; res->ts = rts; res->te = rte; - return 1; - } - } - } - return 0; -} - - -void gen_shared_interval(ul_ov_t *p, ma_ug_t *ug, kv_ul_ov_t *res) -{ - uint32_t st, et, v, w, i, k, nv, nw; asg_arc_t *av, *aw; - ul_ov_t s1, s2, rr; res->n = 0; - - st = p->qn<<1; et = (p->tn<<1) + (!!(p->rev)); - // if(p->qn == 101 && p->tn == 102) { - // if(p->qn == 97 && p->tn == 98) { - // fprintf(stderr, ">[M::%s]\tutg%.6u%c(%c)->utg%.6u%c(%c)\n", __func__, - // (st>>1)+1, "lc"[ug->u.a[st>>1].circ], "+-"[st&1], - // (et>>1)+1, "lc"[ug->u.a[et>>1].circ], "+-"[et&1]); - // } - v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - w = av[i].v; - cal_s_interval(ug, &(av[i]), &s1); - // if(p->qn == 101 && p->tn == 102) { - // if(p->qn == 97 && p->tn == 98) { - // fprintf(stderr, "+[M::%s]\tutg%.6lu%c(%c)->utg%.6u%c(%c)\n", __func__, - // (av[i].ul>>33)+1, "lc"[ug->u.a[(av[i].ul>>33)].circ], "+-"[(av[i].ul>>32)&1], - // (av[i].v>>1)+1, "lc"[ug->u.a[av[i].v>>1].circ], "+-"[av[i].v&1]); - // } - if(w == et) { - kv_push(ul_ov_t, *res, s1); - } else { - aw = asg_arc_a(ug->g, (w^1)); nw = asg_arc_n(ug->g, (w^1)); - for (k = 0; k < nw; k++) { - if(aw[k].del) continue; - if((aw[k].v>>1) == (st>>1)) continue; - // if(p->qn == 101 && p->tn == 102) { - // if(p->qn == 97 && p->tn == 98) { - // fprintf(stderr, "-[M::%s]\tutg%.6lu%c(%c)->utg%.6u%c(%c)\n", __func__, - // (aw[k].ul>>33)+1, "lc"[ug->u.a[(aw[k].ul>>33)].circ], "+-"[(aw[k].ul>>32)&1], - // (aw[k].v>>1)+1, "lc"[ug->u.a[aw[k].v>>1].circ], "+-"[aw[k].v&1]); - // } - // cal_s_interval(ug, &(aw[k]), &s2); - // if(!cal_x_interval(ug, &s1, &s2, &rr)) continue; - - if(aw[k].v == (et^1)) { - // if(p->qn == 101 && p->tn == 102) { - // if(p->qn == 97 && p->tn == 98) { - // fprintf(stderr, "*[M::%s]\tutg%.6lu%c(%c)->utg%.6u%c(%c)\n", __func__, - // (aw[k].ul>>33)+1, "lc"[ug->u.a[(aw[k].ul>>33)].circ], "+-"[(aw[k].ul>>32)&1], - // (aw[k].v>>1)+1, "lc"[ug->u.a[aw[k].v>>1].circ], "+-"[aw[k].v&1]); - // } - cal_s_interval(ug, &(aw[k]), &s2); - if(cal_x_interval(ug, &s1, &s2, &rr)) { - kv_push(ul_ov_t, *res, rr); - } - } - } - } - } - - st ^= 1; et ^= 1; - v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - w = av[i].v; - cal_s_interval(ug, &(av[i]), &s1); - // if(p->qn == 101 && p->tn == 102) { - // if(p->qn == 97 && p->tn == 98) { - // fprintf(stderr, "+[M::%s]\tutg%.6lu%c(%c)->utg%.6u%c(%c)\n", __func__, - // (av[i].ul>>33)+1, "lc"[ug->u.a[(av[i].ul>>33)].circ], "+-"[(av[i].ul>>32)&1], - // (av[i].v>>1)+1, "lc"[ug->u.a[av[i].v>>1].circ], "+-"[av[i].v&1]); - // } - if(w == et) { - kv_push(ul_ov_t, *res, s1); - } else { - aw = asg_arc_a(ug->g, (w^1)); nw = asg_arc_n(ug->g, (w^1)); - for (k = 0; k < nw; k++) { - if(aw[k].del) continue; - if((aw[k].v>>1) == (st>>1)) continue; - // if(p->qn == 101 && p->tn == 102) { - // if(p->qn == 97 && p->tn == 98) { - // fprintf(stderr, "-[M::%s]\tutg%.6lu%c(%c)->utg%.6u%c(%c)\n", __func__, - // (aw[k].ul>>33)+1, "lc"[ug->u.a[(aw[k].ul>>33)].circ], "+-"[(aw[k].ul>>32)&1], - // (aw[k].v>>1)+1, "lc"[ug->u.a[aw[k].v>>1].circ], "+-"[aw[k].v&1]); - // } - if(aw[k].v == (et^1)) { - // if(p->qn == 101 && p->tn == 102) { - // if(p->qn == 97 && p->tn == 98) { - // fprintf(stderr, "*[M::%s]\tutg%.6lu%c(%c)->utg%.6u%c(%c)\n", __func__, - // (aw[k].ul>>33)+1, "lc"[ug->u.a[(aw[k].ul>>33)].circ], "+-"[(aw[k].ul>>32)&1], - // (aw[k].v>>1)+1, "lc"[ug->u.a[aw[k].v>>1].circ], "+-"[aw[k].v&1]); - // } - cal_s_interval(ug, &(aw[k]), &s2); - if(cal_x_interval(ug, &s1, &s2, &rr)) { - kv_push(ul_ov_t, *res, rr); - } - } - } - } - } -} - -void gen_shared_interval_adv(ul_ov_t *p, ma_ug_t *ug, kv_ul_ov_t *res) -{ - uint32_t st, et, v, w, i, k, z, nv, nw, nz; asg_arc_t *av, *aw, *az; - ul_ov_t s1, s2, s3, s4, rr; res->n = 0; - - st = p->qn<<1; et = (p->tn<<1) + (!!(p->rev)); - v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - w = av[i].v; - cal_s_interval(ug, &(av[i]), &s1); - if(w == et) { - kv_push(ul_ov_t, *res, s1); - } else { - aw = asg_arc_a(ug->g, (w^1)); nw = asg_arc_n(ug->g, (w^1)); - for (k = 0; k < nw; k++) { - if(aw[k].del) continue; - if((aw[k].v>>1) == (st>>1)) continue; - - cal_s_interval(ug, &(aw[k]), &s2); - if(!cal_x_interval(ug, &s1, &s2, &s3)) continue; - if(aw[k].v == (et^1)) { - kv_push(ul_ov_t, *res, s3); - } else { - az = asg_arc_a(ug->g, (aw[k].v^1)); nz = asg_arc_n(ug->g, (aw[k].v^1)); - for (z = 0; z < nz; z++) { - if(az[z].del) continue; - if(az[z].v == et) { - cal_s_interval(ug, &(az[z]), &s4); - if(cal_x_interval(ug, &s3, &s4, &rr)) { - kv_push(ul_ov_t, *res, rr); - } - } - } - } - } - } - } - - st ^= 1; et ^= 1; - v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - w = av[i].v; - cal_s_interval(ug, &(av[i]), &s1); - if(w == et) { - kv_push(ul_ov_t, *res, s1); - } else { - aw = asg_arc_a(ug->g, (w^1)); nw = asg_arc_n(ug->g, (w^1)); - for (k = 0; k < nw; k++) { - if(aw[k].del) continue; - if((aw[k].v>>1) == (st>>1)) continue; - - cal_s_interval(ug, &(aw[k]), &s2); - if(!cal_x_interval(ug, &s1, &s2, &s3)) continue; - if(aw[k].v == (et^1)) { - kv_push(ul_ov_t, *res, s3); - } else { - az = asg_arc_a(ug->g, (aw[k].v^1)); nz = asg_arc_n(ug->g, (aw[k].v^1)); - for (z = 0; z < nz; z++) { - if(az[z].del) continue; - if(az[z].v == et) { - cal_s_interval(ug, &(az[z]), &s4); - if(cal_x_interval(ug, &s3, &s4, &rr)) { - kv_push(ul_ov_t, *res, rr); - } - } - } - } - } - } - } -} - - -void gen_src_shared_interval_adv(uint32_t src, ma_ug_t *ug, kv_ul_ov_t *res) -{ - uint32_t st, v, w, i, k, z, nv, nw, nz, rn; asg_arc_t *av, *aw, *az; - ul_ov_t s1, s2, s3, s4, s5; rn = res->n; ///res->n = 0; - - st = src<<1; - v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - if((av[i].v>>1) == (st>>1)) continue; - w = av[i].v; - cal_s_interval(ug, &(av[i]), &s1); - if(s1.qn == src && s1.tn != src) kv_push(ul_ov_t, *res, s1); - - aw = asg_arc_a(ug->g, (w^1)); - nw = asg_arc_n(ug->g, (w^1)); - for (k = 0; k < nw; k++) { - if(aw[k].del) continue; - if((aw[k].v>>1) == (st>>1)) continue; - - cal_s_interval(ug, &(aw[k]), &s2); - if(!cal_x_interval(ug, &s1, &s2, &s3)) continue; - if(s3.qn == src && s3.tn != src) kv_push(ul_ov_t, *res, s3); - - az = asg_arc_a(ug->g, (aw[k].v^1)); - nz = asg_arc_n(ug->g, (aw[k].v^1)); - for (z = 0; z < nz; z++) { - if(az[z].del) continue; - cal_s_interval(ug, &(az[z]), &s4); - if(!cal_x_interval(ug, &s3, &s4, &s5)) continue; - if(s5.qn == src && s5.tn != src) kv_push(ul_ov_t, *res, s5); - } - } - } - - st ^= 1; - v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - if((av[i].v>>1) == (st>>1)) continue; - w = av[i].v; - cal_s_interval(ug, &(av[i]), &s1); - if(s1.qn == src && s1.tn != src) kv_push(ul_ov_t, *res, s1); - - aw = asg_arc_a(ug->g, (w^1)); - nw = asg_arc_n(ug->g, (w^1)); - for (k = 0; k < nw; k++) { - if(aw[k].del) continue; - if((aw[k].v>>1) == (st>>1)) continue; - - cal_s_interval(ug, &(aw[k]), &s2); - if(!cal_x_interval(ug, &s1, &s2, &s3)) continue; - if(s3.qn == src && s3.tn != src) kv_push(ul_ov_t, *res, s3); - - az = asg_arc_a(ug->g, (aw[k].v^1)); - nz = asg_arc_n(ug->g, (aw[k].v^1)); - for (z = 0; z < nz; z++) { - if(az[z].del) continue; - cal_s_interval(ug, &(az[z]), &s4); - if(!cal_x_interval(ug, &s3, &s4, &s5)) continue; - if(s5.qn == src && s5.tn != src) kv_push(ul_ov_t, *res, s5); - } - } - } - - radix_sort_ul_ov_srt_tn(res->a + rn, res->a + res->n); - if(res->n > rn) { - uint64_t os, oe, on, ovlpq, ovlpt, is_cov; - for (k = rn + 1, i = rn; k <= res->n; k++) { - if(k == res->n || res->a[k].tn != res->a[i].tn) { - on = k - i; - if(k - i > 1) { - for (v = i; v < k; v++) { - if(res->a[v].tn == (uint32_t)-1) continue; - for (z = i; z < k; z++) { - if(v == z) continue; - if(res->a[z].tn == (uint32_t)-1) continue; - if(res->a[v].rev != res->a[z].rev) continue; - - - os = MAX(res->a[v].qs, res->a[z].qs); - oe = MIN(res->a[v].qe, res->a[z].qe); - if(oe <= os) continue; - ovlpq = oe - os; - - os = MAX(res->a[v].ts, res->a[z].ts); - oe = MIN(res->a[v].te, res->a[z].te); - if(oe <= os) continue; - ovlpt = oe - os; - - is_cov = 0; - if(((ovlpq == (res->a[v].qe-res->a[v].qs)) && (ovlpt == (res->a[v].te-res->a[v].ts))) || - ((ovlpq == (res->a[z].qe-res->a[z].qs)) && (ovlpt == (res->a[z].te-res->a[z].ts)))) { - is_cov = 1; - } - - if(!is_cov) { - if(ovlpq <= ((res->a[v].qe-res->a[v].qs)*0.95)) continue; - if(ovlpq <= ((res->a[z].qe-res->a[z].qs)*0.95)) continue; - if(ovlpt <= ((res->a[v].te-res->a[v].ts)*0.95)) continue; - if(ovlpt <= ((res->a[z].te-res->a[z].ts)*0.95)) continue; - } - - if(res->a[v].qs > res->a[z].qs) res->a[v].qs = res->a[z].qs; - if(res->a[v].qe < res->a[z].qe) res->a[v].qe = res->a[z].qe; - if(res->a[v].ts > res->a[z].ts) res->a[v].ts = res->a[z].ts; - if(res->a[v].te < res->a[z].te) res->a[v].te = res->a[z].te; - res->a[z].tn = (uint32_t)-1; on--; - - // uint64_t vd, vz; - // vd = (uint64_t)(res->a[v].qe-res->a[v].qs) + (uint64_t)(res->a[v].te-res->a[v].ts); - // zd = (uint64_t)(res->a[z].qe-res->a[z].qs) + (uint64_t)(res->a[z].te-res->a[z].ts); - // ovlp = ((vd>=zd)?(vd-zd):(zd-vd)); - // if(ovlp > 64) { - // if(vd < zd) { - // res->a[v].tn = (uint32_t)-1; break; - // } else if(vd < zd) { - // res->a[z].tn = (uint32_t)-1; continue; - // } - // } - - // vd = ((res->a[v].qe-res->a[v].qs)>=(res->a[v].te-res->a[v].ts))? - // ((res->a[v].qe-res->a[v].qs)-(res->a[v].te-res->a[v].ts)): - // ((res->a[v].te-res->a[v].ts)-(res->a[v].qe-res->a[v].qs)); - // zd = ((res->a[z].qe-res->a[z].qs)>=(res->a[z].te-res->a[z].ts))? - // ((res->a[z].qe-res->a[z].qs)-(res->a[z].te-res->a[z].ts)): - // ((res->a[z].te-res->a[z].ts)-(res->a[z].qe-res->a[z].qs)); - // if(zd <= vd) { - // res->a[v].tn = (uint32_t)-1; break; - // } else { - // res->a[z].tn = (uint32_t)-1; - // } - } - } - if(on > 1) radix_sort_ul_ov_srt_qs(res->a + i, res->a + k); - } - i = k; - } - } - for (k = z = rn; k < res->n; k++) { - if(res->a[k].tn == (uint32_t)-1) continue; - res->a[z++] = res->a[k]; - } - res->n = z; - } -} - - -uint32_t gen_src_shared_interval_simple(uint32_t src, ma_ug_t *ug, uint64_t *flt, uint64_t flt_n, kv_ul_ov_t *res) -{ - uint32_t st, v, w, i, k, z, nv, nw, nz, rn; asg_arc_t *av, *aw, *az; - ul_ov_t s1, s2, s3, s4, s5; rn = res->n; - - st = src<<1; - v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - if((av[i].v>>1) == (st>>1)) continue; - w = av[i].v; - cal_s_interval(ug, &(av[i]), &s1); - if(s1.qn == src && s1.tn != src) kv_push(ul_ov_t, *res, s1); - - aw = asg_arc_a(ug->g, (w^1)); - nw = asg_arc_n(ug->g, (w^1)); - for (k = 0; k < nw; k++) { - if(aw[k].del) continue; - if((aw[k].v>>1) == (st>>1)) continue; - - cal_s_interval(ug, &(aw[k]), &s2); - if(!cal_x_interval(ug, &s1, &s2, &s3)) continue; - if(s3.qn == src && s3.tn != src) kv_push(ul_ov_t, *res, s3); - - az = asg_arc_a(ug->g, (aw[k].v^1)); - nz = asg_arc_n(ug->g, (aw[k].v^1)); - for (z = 0; z < nz; z++) { - if(az[z].del) continue; - cal_s_interval(ug, &(az[z]), &s4); - if(!cal_x_interval(ug, &s3, &s4, &s5)) continue; - if(s5.qn == src && s5.tn != src) kv_push(ul_ov_t, *res, s5); - } - } - } - - st ^= 1; - v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); - for (i = 0; i < nv; i++) { - if(av[i].del) continue; - if((av[i].v>>1) == (st>>1)) continue; - w = av[i].v; - cal_s_interval(ug, &(av[i]), &s1); - if(s1.qn == src && s1.tn != src) kv_push(ul_ov_t, *res, s1); - - aw = asg_arc_a(ug->g, (w^1)); - nw = asg_arc_n(ug->g, (w^1)); - for (k = 0; k < nw; k++) { - if(aw[k].del) continue; - if((aw[k].v>>1) == (st>>1)) continue; - - cal_s_interval(ug, &(aw[k]), &s2); - if(!cal_x_interval(ug, &s1, &s2, &s3)) continue; - if(s3.qn == src && s3.tn != src) kv_push(ul_ov_t, *res, s3); - - az = asg_arc_a(ug->g, (aw[k].v^1)); - nz = asg_arc_n(ug->g, (aw[k].v^1)); - for (z = 0; z < nz; z++) { - if(az[z].del) continue; - cal_s_interval(ug, &(az[z]), &s4); - if(!cal_x_interval(ug, &s3, &s4, &s5)) continue; - if(s5.qn == src && s5.tn != src) kv_push(ul_ov_t, *res, s5); - } - } - } - - radix_sort_ul_ov_srt_tn(res->a + rn, res->a + res->n); - if(res->n > rn) { - uint64_t os, oe, ovlpq, ovlpt, is_cov, fi = 0; - for (k = rn + 1, i = rn; k <= res->n; k++) { - if(k == res->n || res->a[k].tn != res->a[i].tn) { - for (; fi < flt_n && (flt[fi]>>32) < res->a[i].tn; fi++); - if(fi < flt_n && (flt[fi]>>32) == res->a[i].tn) { - // on = k - i; - if(k - i > 1) { - for (v = i; v < k; v++) { - if(res->a[v].tn == (uint32_t)-1) continue; - for (z = i; z < k; z++) { - if(v == z) continue; - if(res->a[z].tn == (uint32_t)-1) continue; - if(res->a[v].rev != res->a[z].rev) continue; - - os = MAX(res->a[v].qs, res->a[z].qs); - oe = MIN(res->a[v].qe, res->a[z].qe); - if(oe <= os) continue; - ovlpq = oe - os; - - os = MAX(res->a[v].ts, res->a[z].ts); - oe = MIN(res->a[v].te, res->a[z].te); - if(oe <= os) continue; - ovlpt = oe - os; - - is_cov = 0; - if(((ovlpq == (res->a[v].qe-res->a[v].qs)) && (ovlpt == (res->a[v].te-res->a[v].ts))) || - ((ovlpq == (res->a[z].qe-res->a[z].qs)) && (ovlpt == (res->a[z].te-res->a[z].ts)))) { - is_cov = 1; - } - - if(!is_cov) { - if(ovlpq <= ((res->a[v].qe-res->a[v].qs)*0.95)) continue; - if(ovlpq <= ((res->a[z].qe-res->a[z].qs)*0.95)) continue; - if(ovlpt <= ((res->a[v].te-res->a[v].ts)*0.95)) continue; - if(ovlpt <= ((res->a[z].te-res->a[z].ts)*0.95)) continue; - } - - if(res->a[v].qs > res->a[z].qs) res->a[v].qs = res->a[z].qs; - if(res->a[v].qe < res->a[z].qe) res->a[v].qe = res->a[z].qe; - if(res->a[v].ts > res->a[z].ts) res->a[v].ts = res->a[z].ts; - if(res->a[v].te < res->a[z].te) res->a[v].te = res->a[z].te; - res->a[z].tn = (uint32_t)-1; ///on--; - } - } - // if(on > 1) radix_sort_ul_ov_srt_qs(res->a + i, res->a + k); - } - } else { - for (v = i; v < k; v++) res->a[v].tn = (uint32_t)-1; - } - i = k; - } - } - for (k = z = rn; k < res->n; k++) { - if(res->a[k].tn == (uint32_t)-1) continue; - res->a[z] = res->a[k]; res->a[z].sec = ((uint32_t)(0x3fffffff)); - z++; - } - res->n = z; - } - return res->n - rn; -} - -inline void overlap_region2ul_ov_t(overlap_region *in, ul_ov_t *ou, uint64_t tl) -{ - ou->qn = in->x_id; ou->tn = in->y_id; ou->el = 1; - ou->sec = in->non_homopolymer_errors; - ou->rev = in->y_pos_strand; - ou->qs = in->x_pos_s; ou->qe = in->x_pos_e+1; - if(ou->rev) { - ou->ts = tl - (in->y_pos_e+1); - ou->te = tl - in->y_pos_s; - } else { - ou->ts = in->y_pos_s; - ou->te = in->y_pos_e+1; - } -} - -void extend_batch(ul_ov_t *z, int64_t ql, int64_t tl, int64_t *rqs, int64_t *rqe, int64_t *rts, int64_t *rte) -{ - int64_t q0, t0, q1, t1; - (*rqs) = (*rqe) = (*rts) = (*rte) = -1; - if(!(z->rev)) { - q0 = z->qs; t0 = z->ts; - if(q0 <= t0) { - (*rqs) = z->qs - q0; (*rts) = z->ts - q0; - } else { - (*rqs) = z->qs - t0; (*rts) = z->ts - t0; - } - - q1 = ql - z->qe; t1 = tl - z->te; - if(q1 <= t1) { - (*rqe) = z->qe + q1; (*rte) = z->te + q1; - } else { - (*rqe) = z->qe + t1; (*rte) = z->te + t1; - } - } else { - q0 = z->qs; t0 = tl - z->te; - if(q0 <= t0) { - (*rqs) = z->qs - q0; (*rte) = z->te + q0; - } else { - (*rqs) = z->qs - t0; (*rte) = z->te + t0; - } - - q1 = ql - z->qe; t1 = z->ts; - if(q1 <= t1) { - (*rqe) = z->qe + q1; (*rts) = z->ts - q1; - } else { - (*rqe) = z->qe + t1; (*rts) = z->ts - t1; - } - } -} - -uint64_t check_ul_ov_t_consist(ul_ov_t *x, ul_ov_t *y, int64_t ql, int64_t tl, double diff) -{ - if(x->qn == y->qn && x->tn == y->tn && x->rev == y->rev) { - int64_t xqs, xqe, xts, xte, yqs, yqe, yts, yte, os, oe, ovlp; - extend_batch(x, ql, tl, &xqs, &xqe, &xts, &xte); - extend_batch(y, ql, tl, &yqs, &yqe, &yts, &yte); - - os = MAX(xqs, yqs); oe = MIN(xqe, yqe); - if(oe <= os) return 0; - ovlp = oe - os; - if(ovlp <= ((xqe-xqs)*(1-diff))) return 0; - if(ovlp <= ((yqe-yqs)*(1-diff))) return 0; - - os = MAX(xts, yts); oe = MIN(xte, yte); - if(oe <= os) return 0; - if(ovlp <= ((xte-xts)*(1-diff))) return 0; - if(ovlp <= ((yte-yts)*(1-diff))) return 0; - return 1; - } - return 0; -} - -ul_ov_t* get_mask_interval(ul_ov_t *in, kv_ul_ov_t *idx, uint64_t *ii, int64_t ql, int64_t tl, uint64_t *n, uint64_t *n_skip) -{ - int64_t idx_n = idx->n, i = (*ii), m; ul_ov_t *a, z; - (*n) = (*n_skip) = 0; - if(i >= idx_n) i = idx_n-1; - if(i < 0) i = 0; - // if(in->qn == 101 && in->tn == 102) { - // fprintf(stderr, "-0-[M::%s]\tutg%.6ul\t%c\tutg%.6ul\ti::%ld\tidx_n::%ld\n", __func__, - // in->qn+1, "+-"[in->rev], in->tn+1, i, idx_n); - // } - if(i >= 0 && i < idx_n) { - while (i >= 0 && in->tn <= idx->a[i].tn) i--; - if(i < 0 && idx_n > 0 && in->tn == idx->a[0].tn) i = 0; - // if(in->qn == 101 && in->tn == 102) { - // fprintf(stderr, "-1-[M::%s]\tutg%.6ul\t%c\tutg%.6ul\ti::%ld\tidx_n::%ld\n", __func__, - // in->qn+1, "+-"[in->rev], in->tn+1, i, idx_n); - // } - if(i >= 0) { - while (i < idx_n && in->tn > idx->a[i].tn) i++; - // if(in->qn == 101 && in->tn == 102) { - // fprintf(stderr, "-2-[M::%s]\tutg%.6ul\t%c\tutg%.6ul\ti::%ld\tidx_n::%ld\n", __func__, - // in->qn+1, "+-"[in->rev], in->tn+1, i, idx_n); - // } - if(i < idx_n && in->tn == idx->a[i].tn) { - for (m = i, a = idx->a + i; i < idx_n && in->tn == idx->a[i].tn; i++) { - if(!check_ul_ov_t_consist(in, &(idx->a[i]), ql, tl, 0.06)) { - (*n_skip)++; continue; - } - if(m != i) { - z = idx->a[i]; idx->a[i] = idx->a[m]; idx->a[m] = z; - } - m++; (*n)++; - } - // if(in->qn == 101 && in->tn == 102) { - // fprintf(stderr, "-3-[M::%s]\tutg%.6ul\t%c\tutg%.6ul\ti::%ld\tidx_n::%ld\n", __func__, - // in->qn+1, "+-"[in->rev], in->tn+1, i, idx_n); - // } - (*ii) = i; - if((*n)) return a; - } - } - } - (*ii) = i; - return NULL; -} - -inline uint64_t is_mask_err_full(ul_ov_t *sa, uint64_t sn, uint64_t qs, uint64_t qe, uint64_t ts, uint64_t te) -{ - uint64_t k; - for (k = 0; k < sn; k++) { - if(sa[k].qs <= qs && sa[k].qe >= qe && sa[k].ts <= ts && sa[k].te >= te) break; - } - if(k < sn) return 1; - return 0; -} - -int64_t cal_exact_len(bit_extz_t *ez, int64_t rev, ul_ov_t *sa, uint64_t sn, int64_t ylen, int64_t *xoff, int64_t *yoff, int64_t *exac, int64_t *err, int64_t backward) -{ - (*xoff) = (*yoff) = (*exac) = (*err) = 0; - if(!ez->cigar.n) return 0; - int64_t cn = ez->cigar.n, op, ck, xk, yk, xs, xe, ys, ye, se; - if(!backward) { - xk = ez->ts; yk = ez->ps; - for (ck = 0; ck < cn; ck++) { - xs = xk; ys = yk; - op = ez->cigar.a[ck]>>14; - se = (ez->cigar.a[ck]&(0x3fff)); - if(op!=2) xk += se; - if(op!=3) yk += se; - xe = xk; ye = yk; - if(!op) {///exact match - (*exac) += se; continue; - } - ///if there is an unmasked error - if((!sn) || (!is_mask_err_full(sa, sn, xs, xe, ((rev)?(ylen-ye):(ys)), ((rev)?(ylen-ys):(ye))))) { - (*xoff) = xs - ez->ts; (*yoff) = ys - ez->ps; - return 0; - } - (*exac) = 0; (*err) += se;///if the error has been masked - } - } else { - xk = ez->te+1; yk = ez->pe+1; - for (ck = cn-1; ck >= 0; ck--) { - xe = xk; ye = yk; - op = ez->cigar.a[ck]>>14; - se = (ez->cigar.a[ck]&(0x3fff)); - if(op!=2) xk -= se; - if(op!=3) yk -= se; - xs = xk; ys = yk; - if(!op) {///exact match - (*exac) += se; continue; - } - ///if there is an unmasked error - if((!sn) || (!is_mask_err_full(sa, sn, xs, xe, ((rev)?(ylen-ye):(ys)), ((rev)?(ylen-ys):(ye))))) { - (*xoff) = ez->te+1-xe; (*yoff) = ez->pe+1-ye; - return 0; - } - (*exac) = 0; (*err) += se;///if the error has been masked - } - - } - (*xoff) = ez->te+1-ez->ts; (*yoff) = ez->pe+1-ez->ps; - return 1; -} - -int64_t cal_exact_batch(overlap_region *z, ul_ov_t *sa, uint64_t sn, int64_t ylen, uint64_t *q0l, uint64_t *t0l, uint64_t *e0l, uint64_t *q1l, uint64_t *t1l, uint64_t *e1l, ma_ug_t *ug) -{ - int64_t wn = z->w_list.n, wk, xk, yk, is_t, is_f, err0, err1, tot, mask_win = 0; window_list *m; bit_extz_t ez; - int64_t qs, qe, ts, te, rev = !!(z->y_pos_strand), qoff, toff, elen, sube; - tot = z->non_homopolymer_errors; - if(!tot) { - (*q0l) = (*q1l) = z->x_pos_e+1-z->x_pos_s; - (*t0l) = (*t1l) = z->y_pos_e+1-z->y_pos_s; - (*e0l) = (*e1l) = z->x_pos_e+1-z->x_pos_s; - return 0; - } - (*q0l) = (*t0l) = (*e0l) = (*q1l) = (*t1l) = (*e1l) = (uint64_t)-1; - wk = xk = yk = -1; if(!wn) return INT32_MAX; - - ///forward - (*q0l) = (*t0l) = (*e0l) = err0 = 0; - wk = 0; xk = z->w_list.a[wk].x_start; yk = z->w_list.a[wk].y_start; is_t = 0; - if((xk == z->x_pos_s) && (yk == z->y_pos_s)) is_t = 1; - if((!is_t) && (sn > 0)) {///if the flanking unmapped regions could be masked - qs = z->x_pos_s; qe = xk; - if(!rev) { - ts = z->y_pos_s; te = yk; - } else { - ts = ylen - yk; te = ylen - z->y_pos_s; - } - is_t = is_mask_err_full(sa, sn, qs, qe, ts, te); - if(is_t) { - (*q0l) += qe - qs; (*t0l) += te - ts; (*e0l) = 0; - } - } - if(is_t) { - for (; wk < wn; wk++) { - m = &(z->w_list.a[wk]); - qs = m->x_start; qe = m->x_end+1; - if(!rev) { - ts = m->y_start; te = m->y_end+1; - } else { - ts = ylen-(m->y_end+1); te = ylen-m->y_start; - } - - if((is_ualn_win((*m))) || ((is_est_aln((*m))) && (m->error > 0))) {///unmapped - if(is_mask_err_full(sa, sn, qs, qe, ts, te)) { - (*q0l) += qe - qs; (*t0l) += te - ts; (*e0l) = 0; mask_win = 1; - continue; - } - break; - } - if(m->error == 0) {///an exactly matched window - (*q0l) += qe - qs; (*t0l) += te - ts; (*e0l) += qe - qs; - continue; - } - set_bit_extz_t(ez, (*z), wk); - is_f = cal_exact_len(&ez, rev, sa, sn, ylen, &qoff, &toff, &elen, &sube, 0); - (*q0l) += qoff; (*t0l) += toff; err0 += sube; - ///exactly match - if(elen == qoff && elen == toff) (*e0l) += elen; - else (*e0l) = elen; - if(!is_f) break; - } - } - - - ///backward - (*q1l) = (*t1l) = (*e1l) = err1 = 0; - wk = wn-1; xk = z->w_list.a[wk].x_end+1; yk = z->w_list.a[wk].y_end+1; is_t = 0; - if((xk == (z->x_pos_e+1)) && (yk == (z->y_pos_e+1))) is_t = 1; - if((!is_t) && (sn > 0)) {///if the flanking unmapped regions could be masked - qs = xk; qe = z->x_pos_e+1; - if(!rev) { - ts = yk; te = z->y_pos_e+1; - } else { - ts = ylen-(z->y_pos_e+1); te = ylen-yk; - } - is_t = is_mask_err_full(sa, sn, qs, qe, ts, te); - if(is_t) { - (*q1l) += qe - qs; (*t1l) += te - ts; (*e1l) = 0; - } - } - if(is_t) { - for (; wk >= 0; wk--) { - m = &(z->w_list.a[wk]); - qs = m->x_start; qe = m->x_end+1; - if(!rev) { - ts = m->y_start; te = m->y_end+1; - } else { - ts = ylen-(m->y_end+1); te = ylen-m->y_start; - } - - if((is_ualn_win((*m))) || ((is_est_aln((*m))) && (m->error > 0))) {///unmapped - if(is_mask_err_full(sa, sn, qs, qe, ts, te)) { - (*q1l) += qe - qs; (*t1l) += te - ts; (*e1l) = 0; mask_win = 1; - continue; - } - break; - } - if(m->error == 0) {///an exactly matched window - (*q1l) += qe - qs; (*t1l) += te - ts; (*e1l) += qe - qs; - continue; - } - set_bit_extz_t(ez, (*z), wk); - is_f = cal_exact_len(&ez, rev, sa, sn, ylen, &qoff, &toff, &elen, &sube, 1); - (*q1l) += qoff; (*t1l) += toff; err1 += sube; - ///exactly match - if(elen == qoff && elen == toff) (*e1l) += elen; - else (*e1l) = elen; - if(!is_f) break; - } - } - - if((*q0l) >= (z->x_pos_e+1-z->x_pos_s) && (*t0l) >= (z->y_pos_e+1-z->y_pos_s)) { - // if((!(((*q0l) == (*q1l)) && ((*t0l) == (*t1l)) && (err0 == err1)))/** || (!(err0 == tot))**/) { - // fprintf(stderr, "[M::%s]\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\terr::%u\twn::%u\n", - // __func__, - // z->x_id+1, "lc"[ug->u.a[z->x_id].circ], ug->u.a[z->x_id].len, z->x_pos_s, z->x_pos_e+1, - // "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[ug->u.a[z->y_id].circ], ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, - // z->non_homopolymer_errors, (uint32_t)z->w_list.n); - // uint64_t k; - // for (k = 0; k < z->w_list.n; k++) { - // m = &(z->w_list.a[k]); - // fprintf(stderr, "k::%ld[M::%s]\tutg%.6u%c\twx::[%u,\t%u)\t%c\tutg%.6u%c\twy::[%u,\t%u)\terr::%d\tualn::%u\test::%u\n", k, __func__, - // z->x_id+1, "lc"[ug->u.a[z->x_id].circ], m->x_start, m->x_end+1, - // "+-"[z->y_pos_strand], - // z->y_id+1, "lc"[ug->u.a[z->y_id].circ], m->y_start, m->y_end+1, m->error, - // (is_ualn_win((*m))), (is_est_aln((*m)))); - // } - // fprintf(stderr, "[M::%s]\tutg%.6ul\tutg%.6ul\terr0::%ld\terr1::%ld\ttot::%ld\n", __func__, - // z->x_id+1, z->y_id+1, err0, err1, tot); - // fprintf(stderr, "[M::%s]\tutg%.6ul\tq0l::%lu\tt0l::%lu\te0l::%lu\tutg%.6ul\tq1l::%lu\tt1l::%lu\te1l::%lu\n", __func__, - // z->x_id+1, *q0l, *t0l, *e0l, z->y_id+1, *q1l, *t1l, *e1l); - // } - assert(((*q0l) == (*q1l)) && ((*t0l) == (*t1l)) && (err0 == err1)); - assert((mask_win) || (err0 == tot)); - return 0; - } - - // if(!(err0+err1 < tot)) { - // fprintf(stderr, "[M::%s]\tutg%.6ul\tutg%.6ul\terr0::%ld\terr1::%ld\ttot::%ld\n", __func__, - // z->x_id+1, z->y_id+1, err0, err1, tot); - // fprintf(stderr, "[M::%s]\tutg%.6ul\tq0l::%lu\tt0l::%lu\te0l::%lu\tutg%.6ul\tq1l::%lu\tt1l::%lu\te1l::%lu\n", __func__, - // z->x_id+1, *q0l, *t0l, *e0l, z->y_id+1, *q1l, *t1l, *e1l); - // } - - assert(err0+err1 < tot); - return tot-(err0+err1); -} - -void push_graph_bin_back(overlap_region_alloc* ol, const ul_idx_t *udb, hpc_re_t *hre, -double erate, uint64_t maxe, uint64_t minov, uint64_t rid, asg64_v *b0, asg64_v *b1, mask_ul_ov_t *mk) -{ - uint64_t k, i, m, si, sn, skip_n, zt, re; overlap_region t, *z; ul_ov_t p, *sa; int64_t npc; - uint64_t q0l, t0l, e0l, q1l, t1l, e1l, mm, occ[3]; - b0->n = b1->n = 0; - - mk->srt.n = mk->idx.n = 0; - gen_src_shared_interval_adv(rid, udb->ug, &(mk->srt)); - kv_resize(uint64_t, mk->idx, ol->length); - for (k = 0; k < ol->length; k++) { - kv_push(uint64_t, mk->idx, (((uint64_t)ol->list[k].y_id)<<32)|((uint64_t)k)); - } - radix_sort_gfa64(mk->idx.a, mk->idx.a+mk->idx.n); - for (i = si = b0->n = 0, occ[0] = occ[1] = occ[2] = 0; i < mk->idx.n; i++) { - k = (uint32_t)mk->idx.a[i]; - z = &(ol->list[k]); - overlap_region2ul_ov_t(z, &p, udb->ug->u.a[z->y_id].len); - if(((p.qe-p.qs) >= minov) && ((p.te-p.ts) >= minov)) { - if(!trans_ovlp_connect(&p, udb->ug)) continue;//could be eaisly detected - if(p.sec == 0) {///no error - zt = ((uint32_t)-1); zt <<= 32; zt |= (i<<1); occ[2]++; - kv_push(uint64_t, *b0, zt); continue; - } - sa = get_mask_interval(&p, &(mk->srt), &si, udb->ug->u.a[p.qn].len, udb->ug->u.a[p.tn].len, &sn, &skip_n); - re = cal_exact_batch(z, sa, sn, udb->ug->u.a[p.tn].len, &q0l, &t0l, &e0l, &q1l, &t1l, &e1l, udb->ug); - if(!re) {//no unmask errors - zt = ((uint32_t)-1); zt <<= 32; zt |= (i<<1); occ[2]++; - kv_push(uint64_t, *b0, zt); continue; - } - - mm = ((re <= maxe)?((uint64_t)(0x8000000000000000)):(0)); - ///left end - if(q0l >= minov && t0l >= minov) { - zt = MIN(q0l, t0l); zt <<= 32; zt |= (i<<1); zt |= mm; occ[!!mm]++; - kv_push(uint64_t, *b0, zt); - } - - ///right end - if(q1l >= minov && t1l >= minov) { - zt = MIN(q1l, t1l); zt <<= 32; zt |= (i<<1); zt += 1; zt |= mm; occ[!!mm]++; - kv_push(uint64_t, *b0, zt); - } - } - } - - // radix_sort_gfa64(b0->a, b0->a+b0->n); - // uint64_t *a0, *a1, *a2, a0n, a1n, a2n; - // a2 = b0->a; a2n = occ[0]; - // a1 = a2 + a2n; a1n = occ[1]; - // a0 = a1 + a1n; a0n = occ[2]; - - - fprintf(stderr, "\n[M::%s]\tutg%.6lu%c\t#s::%u\n", __func__, rid+1, "lc"[udb->ug->u.a[rid].circ], (uint32_t)mk->srt.n); - for (k = 0; k < mk->srt.n; k++) { - fprintf(stderr, "[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\n", __func__, - mk->srt.a[k].qn+1, "lc"[udb->ug->u.a[mk->srt.a[k].qn].circ], mk->srt.a[k].qs, mk->srt.a[k].qe, "+-"[mk->srt.a[k].rev], - mk->srt.a[k].tn+1, "lc"[udb->ug->u.a[mk->srt.a[k].tn].circ], mk->srt.a[k].ts, mk->srt.a[k].te); - } - - - - for (k = m = 0; k < ol->length; k++) { - z = &(ol->list[k]); - if(z->non_homopolymer_errors == 0) continue; - p.qn = rid; p.tn = ol->list[k].y_id; p.el = 1; - p.sec = ol->list[k].non_homopolymer_errors; - p.rev = ol->list[k].y_pos_strand; - p.qs = ol->list[k].x_pos_s; p.qe = ol->list[k].x_pos_e+1; - if(p.rev) { - p.ts = udb->ug->u.a[p.tn].len - (ol->list[k].y_pos_e+1); - p.te = udb->ug->u.a[p.tn].len - ol->list[k].y_pos_s; - } else { - p.ts = ol->list[k].y_pos_s; - p.te = ol->list[k].y_pos_e+1; - } - // gen_shared_interval(&p, udb->ug, bl); - // gen_shared_interval_adv(&p, udb->ug, bl); - // if(!trans_ovlp_connect(&p, udb->ug)) continue; - // assert(z->x_id == rid); - // if(!get_high_simi(z, erate, maxe, minov, &e0, &e1)) continue; - npc = cal_npc_err(z, p.qs, p.qe, hre, udb->ug->u.a[p.tn].len); - if(npc == INT32_MAX || npc < 0) continue; - if(((uint64_t)npc <= maxe) && ((uint64_t)npc <= ((p.qe - p.qs)*erate)) && ((uint64_t)npc <= ((p.te - p.ts)*erate))) { - ; - } else if(((uint64_t)npc > maxe) && ((p.qe - p.qs) > minov) && ((p.te - p.ts) > minov)) { - ; - } - - // if((z->x_id == 44 && z->y_id == 45) || (z->x_id == 45 && z->y_id == 44)) - // if(npc <= 4) - { - // int64_t nnpc; - // nnpc = cal_npc_err(z, p.qs, p.qe, NULL, udb->ug->u.a[p.tn].len); - // fprintf(stderr, "[M::%s]\tutg%.6u%c->utg%.6u%c\terr::%u\tnpc::%ld\t#s::%u\n", __func__, p.qn+1, "lc"[udb->ug->u.a[p.qn].circ], - // p.tn+1, "lc"[udb->ug->u.a[p.tn].circ], ol->list[k].non_homopolymer_errors, npc, (uint32_t)bl->n); - // uint64_t t; - // for (t = 0; t < bl->n; t++) { - // fprintf(stderr, "[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\n", __func__, - // bl->a[t].qn+1, "lc"[udb->ug->u.a[bl->a[t].qn].circ], bl->a[t].qs, bl->a[t].qe, "+-"[bl->a[t].rev], - // bl->a[t].tn+1, "lc"[udb->ug->u.a[bl->a[t].tn].circ], bl->a[t].ts, bl->a[t].te); - // } - } - - if(k != m) { - t = ol->list[k]; - ol->list[k] = ol->list[m]; - ol->list[m] = t; - } - m++; - } - ol->length = m; -} - -void full_lst_set(emask_t *a, uint64_t a_n, ul_ov_t *sa, uint64_t sn, uint64_t skip_n) -{ - uint64_t ff = 0, k, i; int64_t sql, stl, os, oe, ovlp; - if(sn == 0 && skip_n == 0) { - ff = 1; - } else if(skip_n > 0) { - ff = 0; - } else {///sn > 0 && skip_n == 0 - for (k = 0; k < sn; k++) { - sql = sa[k].qe - sa[k].qs; - stl = sa[k].te - sa[k].ts; - for (i = 0; i < a_n && sql > 0 && stl > 0; i++) { - os = MAX(sa[k].qs, a[i].qs); oe = MIN(sa[k].qe, a[i].qe); - ovlp = ((oe>os)?(oe-os):(0)); sql -= ovlp; - - os = MAX(sa[k].ts, a[i].ts); oe = MIN(sa[k].te, a[i].te); - ovlp = ((oe>os)?(oe-os):(0)); stl -= ovlp; - } - if((sql > 256) && (sql > ((sa[k].qe - sa[k].qs)*0.06))) break; - if((sql <= 256) && (sql > ((sa[k].qe - sa[k].qs)*0.6))) break; - if((stl > 256) && (stl > ((sa[k].te - sa[k].ts)*0.06))) break; - if((stl <= 256) && (stl > ((sa[k].te - sa[k].ts)*0.6))) break; - } - if(k < sn) ff = 0; - else ff = 1; - } - for (k = 0; k < a_n; k++) a[k].full = ff; -} - -void push_emask0(kv_emask_t *res, uint64_t q0l, uint64_t t0l, uint64_t e0l, uint64_t q1l, uint64_t t1l, uint64_t e1l, -uint64_t end, uint64_t is_pe, uint64_t minov, ul_ov_t *p) -{ - emask_t *m; - m = &(res->a[res->n++]); memset(m, 0, sizeof((*m))); - m->dir = end; m->pe = is_pe; - m->tn = p->tn; m->rev = p->rev; m->rn = (uint32_t)-1; - if(!end) {///left end - assert(q0l >= minov && t0l >= minov); - m->el = e0l; - m->qs = p->qs; m->qe = p->qs + q0l; - if(!(m->rev)) { - m->ts = p->ts; m->te = p->ts + t0l; - } else { - m->te = p->te; m->ts = p->te - t0l; - } - } else {///right end - assert(q1l >= minov && t1l >= minov); - m->el = e1l; - m->qe = p->qe; m->qs = p->qe - q1l; - if(!(m->rev)) { - m->te = p->te; m->ts = p->te - t1l; - } else { - m->ts = p->ts; m->te = p->ts + t1l; - } - } -} - -void push_emask_lst(mask_ul_ov_t *mk, overlap_region_alloc* ol, uint64_t minov, ma_ug_t *ug, uint64_t *a, uint64_t an, kv_emask_t *res, uint64_t is_pe) -{ - uint64_t i, l, sn, si, re, cn, skip_n; overlap_region *z; ul_ov_t p, *sa; - uint64_t q0l, t0l, e0l, q1l, t1l, e1l; emask_t *m; - if(is_pe) { - for (i = 0; i < an; i++) { - a[i] <<= 32; a[i] >>= 32; - } - radix_sort_gfa64(a, a+an); - for (i = 1, l = si = 0; i <= an; i++) { - if(i == an || (a[i]>>1) != (a[l]>>1)) { - // k = (uint32_t)mk->idx.a[a[l]>>1]; - z = &(ol->list[(uint32_t)mk->idx.a[a[l]>>1]]); - overlap_region2ul_ov_t(z, &p, ug->u.a[z->y_id].len); - assert(i<=l+2); - assert((p.qe-p.qs) >= minov); - assert((p.te-p.ts) >= minov); - assert(p.sec > 0); - sa = get_mask_interval(&p, &(mk->srt), &si, ug->u.a[p.qn].len, ug->u.a[p.tn].len, &sn, &skip_n); - re = cal_exact_batch(z, sa, sn, ug->u.a[p.tn].len, &q0l, &t0l, &e0l, &q1l, &t1l, &e1l, ug); - assert(re); - cn = i - l; - - push_emask0(res, q0l, t0l, e0l, q1l, t1l, e1l, a[l]&1, ((i==(l+2))?1:0), minov, &p); l++; - if(l < i) push_emask0(res, q0l, t0l, e0l, q1l, t1l, e1l, a[l]&1, ((i==(l+2))?1:0), minov, &p); - // fprintf(stderr, "[M::%s]\tres->n::%u\tcn::%lu\n", __func__, (uint32_t)res->n, cn); - full_lst_set(res->a+res->n-cn, cn, sa, sn, skip_n); - l = i; - } - } - } else { - for (i = 0; i < an; i++) { - a[i] <<= 32; a[i] >>= 32; - z = &(ol->list[(uint32_t)mk->idx.a[a[i]>>1]]); - overlap_region2ul_ov_t(z, &p, ug->u.a[z->y_id].len); - assert((p.qe-p.qs) >= minov); - assert((p.te-p.ts) >= minov); - if(p.sec > 0) { - sa = get_mask_interval(&p, &(mk->srt), &si, ug->u.a[p.qn].len, ug->u.a[p.tn].len, &sn, &skip_n); - re = cal_exact_batch(z, sa, sn, ug->u.a[p.tn].len, &q0l, &t0l, &e0l, &q1l, &t1l, &e1l, ug); - assert(re == 0); - } - - m = &(res->a[res->n++]); memset(m, 0, sizeof((*m))); - m->dir = 2; m->pe = 0; m->tn = p.tn; m->rev = p.rev; m->full = 1; m->el = (uint32_t)-1; m->rn = (uint32_t)-1; - m->qs = p.qs; m->qe = p.qe; m->ts = p.ts; m->te = p.te; - } - } -} - -void srt_kv_emask_t(kv_emask_t *res, mask_ul_ov_t *mk, uint32_t rid, ma_ug_t *ug) -{ - uint64_t k, m, z; ul_ov_t *p; - mk->srt.n = mk->idx.n = 0; - kv_resize(uint64_t, mk->idx, res->n); - kv_resize(ul_ov_t, mk->srt, res->n); - - for (k = 0; k < res->n; k++) { - m = k + 1; z = (((uint64_t)res->a[k].tn)<<32)|(k<<1); - if((m < res->n) && (res->a[k].tn == res->a[m].tn) && (res->a[k].rev == res->a[m].rev) && - (res->a[k].pe) && (res->a[m].pe) && (res->a[k].dir == 0 && res->a[m].dir == 1)) { - z |= 1; - } - kv_push(uint64_t, mk->idx, z); - } - radix_sort_gfa64(mk->idx.a, mk->idx.a+mk->idx.n); - for (z = 0; z < mk->idx.n; z++) { - k = ((uint32_t)mk->idx.a[z])>>1; - kv_pushp(ul_ov_t, mk->srt, &p); - p->tn = res->a[k].tn; p->qn = res->a[k].el; - p->qs = res->a[k].qs; p->qe = res->a[k].qe; - p->ts = res->a[k].ts; p->te = res->a[k].te; - p->rev = res->a[k].rev; p->el = res->a[k].full; - m = res->a[k].dir; m <<= 1; m |= (uint32_t)res->a[k].pe; p->sec = m; - - if(mk->idx.a[z]&1) { - k++; - kv_pushp(ul_ov_t, mk->srt, &p); - p->tn = res->a[k].tn; p->qn = res->a[k].el; - p->qs = res->a[k].qs; p->qe = res->a[k].qe; - p->ts = res->a[k].ts; p->te = res->a[k].te; - p->rev = res->a[k].rev; p->el = res->a[k].full; - m = res->a[k].dir; m <<= 1; m |= (uint32_t)res->a[k].pe; p->sec = m; - } - } - - for (k = 0; k < res->n; k++) { - p = &(mk->srt.a[k]); - res->a[k].tn = p->tn; res->a[k].el = p->qn; - res->a[k].qs = p->qs; res->a[k].qe = p->qe; - res->a[k].ts = p->ts; res->a[k].te = p->te; - res->a[k].rev = p->rev; res->a[k].full = p->el; res->a[k].rn = (uint32_t)-1; - m = p->sec; res->a[k].pe = m&1; res->a[k].dir = m>>1; - } - - // for (k = 0; k < res->n; k++) { - // int64_t fqs, fqe, fts, fte, ql = ug->g->seq[rid].len, tl = ug->g->seq[res->a[k].tn].len; - // p = &(mk->srt.a[k]); extend_batch(p, ql, tl, &fqs, &fqe, &fts, &fte); - // ///if(res->a[k].full == 0) - // { - // // fprintf(stderr, "+[M::%s]\tutg%.6ul\tq::[%u,\t%u)[%ld,\t%ld)\t%c\tutg%.6ul\tt::[%u,\t%u)[%ld,\t%ld)\tel::%u\tfu::%u\n", __func__, - // // rid+1, res->a[k].qs, res->a[k].qe, fqs, fqe, "+-"[res->a[k].rev], res->a[k].tn+1, res->a[k].ts, res->a[k].te, fts, fte, res->a[k].el, res->a[k].full); - // // fprintf(stderr, "utg%.6ul\tq::[%u,\t%u)[%ld,\t%ld)\t%c\tutg%.6ul\tt::[%u,\t%u)[%ld,\t%ld)\tel::%u\tfu::%u\n", - // // rid+1, res->a[k].qs, res->a[k].qe, fqs, fqe, "+-"[res->a[k].rev], res->a[k].tn+1, res->a[k].ts, res->a[k].te, fts, fte, res->a[k].el, res->a[k].full); - // } - // } -} - -void push_graph_bin(overlap_region_alloc* ol, const ul_idx_t *udb, double erate, uint64_t maxe, uint64_t minov, uint64_t rid, asg64_v *b0, mask_ul_ov_t *mk, kv_emask_t *res) -{ - uint64_t k, i, si, sn, zt, re, skip_n; overlap_region *z; ul_ov_t p, *sa; - uint64_t q0l, t0l, e0l, q1l, t1l, e1l, mm, occ[3], mocc, mn[3]; - b0->n = 0; - mocc = (udb->ug->u.a[rid].len/sizeof((*(res->a))))/8; if(mocc < 16) mocc = 16; - - // fprintf(stderr, "\n[M::%s]\tutg%.6lu%c\n", __func__, rid+1, "lc"[udb->ug->u.a[rid].circ]); - - mk->srt.n = mk->idx.n = 0; - gen_src_shared_interval_adv(rid, udb->ug, &(mk->srt)); - kv_resize(uint64_t, mk->idx, ol->length); - for (k = 0; k < ol->length; k++) { - kv_push(uint64_t, mk->idx, (((uint64_t)ol->list[k].y_id)<<32)|((uint64_t)k)); - } - radix_sort_gfa64(mk->idx.a, mk->idx.a+mk->idx.n);///sort by the unitig id - // if(rid == 4) { - // sa = mk->srt.a; sn = mk->srt.n; - // for (si = 0; si < sn; si++) { - // fprintf(stderr, "si::%lu[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\n", si, __func__, - // sa[si].qn+1, "lc"[udb->ug->u.a[sa[si].qn].circ], sa[si].qs, sa[si].qe, "+-"[sa[si].rev], - // sa[si].tn+1, "lc"[udb->ug->u.a[sa[si].tn].circ], sa[si].ts, sa[si].te); - // } - // } - - // if(ol->length > 0 && ol->list[0].x_id == 29033) fprintf(stderr, "[M::%s]\t0\t\n", __func__); - - - for (i = si = b0->n = 0, occ[0] = occ[1] = occ[2] = 0; i < mk->idx.n; i++) { - k = (uint32_t)mk->idx.a[i]; - z = &(ol->list[k]); - overlap_region2ul_ov_t(z, &p, udb->ug->u.a[z->y_id].len); - if(((p.qe-p.qs) >= minov) && ((p.te-p.ts) >= minov)) { - if(!trans_ovlp_connect(&p, udb->ug)) continue;//could be eaisly detected - if(p.sec == 0) {///no error - zt = ((uint32_t)-1); zt <<= 32; zt |= (i<<1); occ[2]++; - kv_push(uint64_t, *b0, zt); continue; - } - sa = get_mask_interval(&p, &(mk->srt), &si, udb->ug->u.a[p.qn].len, udb->ug->u.a[p.tn].len, &sn, &skip_n); - // if(p.qn == 4 && p.tn == 3) { - // fprintf(stderr, "[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\tsn::%lu\tskip_n::%lu\n", __func__, - // p.qn+1, "lc"[udb->ug->u.a[p.qn].circ], p.qs, p.qe, "+-"[p.rev], - // p.tn+1, "lc"[udb->ug->u.a[p.tn].circ], p.ts, p.te, sn, skip_n); - // uint32_t ci; - // for (ci = 0; ci < sn; ci++) { - // fprintf(stderr, "sa::[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\n", __func__, - // sa[ci].qn+1, "lc"[udb->ug->u.a[sa[ci].qn].circ], sa[ci].qs, sa[ci].qe, "+-"[sa[ci].rev], - // sa[ci].tn+1, "lc"[udb->ug->u.a[sa[ci].tn].circ], sa[ci].ts, sa[ci].te); - // } - // } - - - re = cal_exact_batch(z, sa, sn, udb->ug->u.a[p.tn].len, &q0l, &t0l, &e0l, &q1l, &t1l, &e1l, udb->ug); - if(!re) {//no unmask errors - zt = ((uint32_t)-1); zt <<= 32; zt |= (i<<1); occ[2]++; - kv_push(uint64_t, *b0, zt); continue; - } - // if(p.qn == 4 && p.tn == 3) { - // fprintf(stderr, "[M::%s]\tutg%.6u%c\tq0l::%lu\tt0l::%lu\te0l::%lu\tutg%.6u%c\tq1l::%lu\tt1l::%lu\te1l::%lu\n", __func__, - // p.qn+1, "lc"[udb->ug->u.a[p.qn].circ], q0l, t0l, e0l, - // p.tn+1, "lc"[udb->ug->u.a[p.tn].circ], q1l, t1l, e1l); - // } - mm = ((re <= maxe)?((uint64_t)(0x8000000000000000)):(0)); - ///left end - if(q0l >= minov && t0l >= minov) { - zt = MIN(q0l, t0l); zt <<= 32; zt |= (i<<1); zt |= mm; occ[!!mm]++; - kv_push(uint64_t, *b0, zt); - } - - ///right end - if(q1l >= minov && t1l >= minov) { - zt = MIN(q1l, t1l); zt <<= 32; zt |= (i<<1); zt += 1; zt |= mm; occ[!!mm]++; - kv_push(uint64_t, *b0, zt); - } - } - } - - radix_sort_gfa64(b0->a, b0->a+b0->n); - uint64_t *a0, *a1, *a2, a0n, a1n, a2n, *a, m; - a2 = b0->a; a2n = occ[0]; mn[2] = mocc>>2;//high error - a1 = a2 + a2n; a1n = occ[1]; mn[1] = mocc>>1;//low error - a0 = a1 + a1n; a0n = occ[2]; mn[0] = mocc>>2;//0 error - mn[1] = mocc - mn[0] - mn[2]; - - sn = a2n; a = a2;//high error - for (i = 0, si = sn>>1; i < si; i++) { - m = a[i]; a[i] = a[sn-i-1]; a[sn-i-1] = m; - } - - sn = a1n; a = a1;//low error - for (i = 0, si = sn>>1; i < si; i++) { - m = a[i]; a[i] = a[sn-i-1]; a[sn-i-1] = m; - } - - sn = a0n; a = a0;//0 error - for (i = 0; i < sn; i++) { - z = &(ol->list[(((uint32_t)a[i])>>1)]); - q0l = z->x_pos_e+1-z->x_pos_s; - t0l = z->y_pos_e+1-z->y_pos_s; - m = ((uint32_t)-1) - (MIN(q0l, t0l)); m <<= 32; m |= ((uint32_t)a[i]); - a[i] = m; - } - radix_sort_gfa64(a, a+sn);///sort by length - ///a1 -> a2 -> a0 - if(mn[1] > a1n) mn[1] = a1n; - if(mn[2] > a2n) mn[2] = a2n; - if(mn[0] > a0n) mn[0] = a0n; - - ///reassign a1 - mn[1] = mocc - mn[0] - mn[2]; - if(mn[1] > a1n) mn[1] = a1n; - - ///reassign a2 - mn[2] = mocc - mn[1] - mn[0]; - if(mn[2] > a2n) mn[2] = a2n; - - ///reassign a0 - mn[0] = mocc - mn[1] - mn[2]; - if(mn[0] > a0n) mn[0] = a0n; - - res->n = res->m = mn[0]+mn[1]+mn[2]; - MALLOC(res->a, res->n); - res->n = 0; - // if(ol->length > 0 && ol->list[0].x_id == 29033) fprintf(stderr, "[M::%s]\t1\t\n", __func__); - // fprintf(stderr, "\n[M::%s]\tutg%.6lu%c\t#s::%u\tmn[0]::%lu\tmn[1]::%lu\tmn[2]::%lu\n", __func__, - // rid+1, "lc"[udb->ug->u.a[rid].circ], (uint32_t)mk->srt.n, mn[0], mn[1], mn[2]); - push_emask_lst(mk, ol, minov, udb->ug, a2, mn[2], res, 1); - // if(ol->length > 0 && ol->list[0].x_id == 29033) fprintf(stderr, "[M::%s]\t2\t\n", __func__); - // fprintf(stderr, "[M::%s]\tutg%.6lu%c\tres->n::%u\n", __func__, rid+1, "lc"[udb->ug->u.a[rid].circ], res->n); - push_emask_lst(mk, ol, minov, udb->ug, a1, mn[1], res, 1); - // if(ol->length > 0 && ol->list[0].x_id == 29033) fprintf(stderr, "[M::%s]\t3\t\n", __func__); - // fprintf(stderr, "[M::%s]\tutg%.6lu%c\tres->n::%u\n", __func__, rid+1, "lc"[udb->ug->u.a[rid].circ], res->n); - push_emask_lst(mk, ol, minov, udb->ug, a0, mn[0], res, 0); - // if(ol->length > 0 && ol->list[0].x_id == 29033) fprintf(stderr, "[M::%s]\t4\t\n", __func__); - // fprintf(stderr, "[M::%s]\tutg%.6lu%c\tres->n::%u\n", __func__, rid+1, "lc"[udb->ug->u.a[rid].circ], res->n); - srt_kv_emask_t(res, mk, rid, udb->ug); - // if(ol->length > 0 && ol->list[0].x_id == 29033) fprintf(stderr, "[M::%s]\t5\t\n", __func__); - - // for (k = 0; k < mk->srt.n; k++) { - // fprintf(stderr, "[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\n", __func__, - // mk->srt.a[k].qn+1, "lc"[udb->ug->u.a[mk->srt.a[k].qn].circ], mk->srt.a[k].qs, mk->srt.a[k].qe, "+-"[mk->srt.a[k].rev], - // mk->srt.a[k].tn+1, "lc"[udb->ug->u.a[mk->srt.a[k].tn].circ], mk->srt.a[k].ts, mk->srt.a[k].te); - // } -} - -static void worker_for_graph_bin(void *data, long i, int tid) // callback for kt_for() -{ - ug_bin_t *s = (ug_bin_t*)data; double erate; int64_t wl; overlap_region *aux_o; - ha_ovec_buf_t *b = s->hab[tid]; asg64_v b0; - uint32_t high_occ = asm_opt.polyploidy + 1; uint64_t cnt; - char *seq = s->ug->u.a[i].s; int64_t len = s->ug->u.a[i].len; - if((!s->is_ovlp) && (s->is_cnt)) s->idx_n.a[i] = 0; - if(s->ug->g->seq[i].del) return; - if(!seq) { - resize_UC_Read(&(b->self_read), len); - retrieve_u_seq(NULL, b->self_read.seq, &(s->ug->u.a[i]), 0, 0, len, NULL); - seq = b->self_read.seq; - } - - // if(i!=77960) return; - - // asprintf(&as, "\n[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); - // push_vlog(&(overall_zdbg->a[s->id+i]), as); free(as); as = NULL; - - if(!s->is_ovlp) { - if(s->is_cnt) { - // s->idx_n.a[i] = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, - // s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, NULL, 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); - s->idx_n.a[i] = ug_map_lchain_simple(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, - s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 1, 1, 0.2, 3, s->is_HPC, NULL, 0, NULL, 0, s->mini_cut, s->chain_cut); - } else { - // cnt = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, - // s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); - cnt = ug_map_lchain_simple(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, - s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 1, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], 0, NULL, 0, s->mini_cut, s->chain_cut); - assert(cnt == ((s->idx_n.a[i+1]-s->idx_n.a[i]))); - } - return; - } - - // if(i == 160) { - // fprintf(stderr, "\n-1-[M::%s] utg%.6u%c, rid::%ld, is_ovlp::%d, is_cnt::%d, len::%ld, str::%u\n", - // __func__, (uint32_t)i+1, "lc"[s->ug->u.a[i].circ], i, s->is_ovlp, s->is_cnt, len, (uint32_t)(!!seq)); - // } - - - // ug_map_lchain(b->abl, rid, seq, len, s->w, s->k, &(s->udb), &b->olist, &b->clist, bw_low, bw_high, - // s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, - // s->is_HPC, s->idx_a.a + s->idx_n.a[rid], cnt, s->srt_a.a, s->srt_a.n, s->mini_cut, s->chain_cut, fi); - cnt = ((s->idx_n.a[i+1]-s->idx_n.a[i])); - ug_map_lchain_simple(b->abl, i, seq, len, s->w, s->k, &(s->udb), &b->olist, &b->clist, s->bw_thres, - s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 1, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], cnt, s->srt_a.a, s->srt_a.n, s->mini_cut, s->chain_cut); - clear_Cigar_record(&b->cigar1); clear_Round2_alignment(&b->round2); - - erate = s->diff_ov; wl = MIN((((double)THRESHOLD_MAX_SIZE)/erate), WINDOW); aux_o = NULL; - ug_lalign(&b->olist, &b->clist, &(s->udb), s->uopt, seq, len, NULL/**&b->self_read**/, &b->ovlp_read, - &b->correct, &b->exz, aux_o, erate, wl, i, s->k, s->chain_cut, NULL); - aux_o = gen_aux_ovlp(&b->olist);///must be here - ug_lalign(&b->olist, &b->clist, &(s->udb), s->uopt, seq, len, NULL/**&b->self_read**/, &b->ovlp_read, - &b->correct, &b->exz, aux_o, erate, wl, i, s->k, s->chain_cut, NULL); - - copy_asg_arr(b0, s->ll[tid].srt.a); - push_graph_bin(&b->olist, &(s->udb), s->diff_bin, s->max_diff, s->min_bin_len, i, &b0, &(s->mk[tid]), &(s->mm->a[i])); - copy_asg_arr(s->ll[tid].srt.a, b0); - // if(!gen_trans_adaptive_aln(s, i, b, bl, seq, len, s->filter, s->diff_ec_ul, s->diff_ec_ul_double, s->bw_thres, s->bw_thres_double)) { - // gen_trans_adaptive_aln(s, i, b, bl, seq, len, NULL, s->diff_ec_ul_double, s->diff_ec_ul_double, s->bw_thres_double, s->bw_thres_double); - // } -} - -emask_t* get_emask_ovlp(idx_emask_t *idx, uint32_t qn, uint32_t tn, uint32_t *occ, uint32_t *st) -{ - emask_t *a = NULL; (*occ) = 0; if(st) (*st) = (uint32_t)-1; - if(qn >= idx->n) return a; - uint32_t k; - for (k = 0; k < idx->a[qn].n && idx->a[qn].a[k].tn < tn; k++); - if(k < idx->a[qn].n && idx->a[qn].a[k].tn == tn) { - a = idx->a[qn].a + k; if(st) (*st) = k; - for ((*occ) = k; k < idx->a[qn].n && idx->a[qn].a[k].tn == tn; k++); - (*occ) = k - (*occ); - return a; - } - return a; -} - -void detect_sysm_graph_bin(idx_emask_t *idx, uint32_t rid) -{ - kv_emask_t *r = &(idx->a[rid]); uint32_t k, an, st; - for (k = 0; k < r->n; k++) { - get_emask_ovlp(idx, r->a[k].tn, rid, &an, &st); - r->a[k].rn = (uint32_t)-1; - if(!an) r->a[k].rn = st; - } -} - -static void worker_for_graph_bin_sysm(void *data, long i, int tid) // callback for kt_for() -{ - ug_bin_t *s = (ug_bin_t*)data; - if(s->ug->g->seq[i].del) return; - if((s->is_cnt) && (!s->is_ovlp)) detect_sysm_graph_bin(s->mm, i); - if((!s->is_cnt) && (s->is_ovlp)) srt_kv_emask_t(&(s->mm->a[i]), &(s->mk[tid]), i, s->udb.ug); - if((s->is_cnt) && (s->is_ovlp)) detect_sysm_graph_bin(s->mm, i); -} - -ul_ov_t* get_trans_ul_ov_t(ug_trans_t *s, uint32_t qn, uint32_t tn) -{ - ha_mzl_t *f = &(s->srt_a.a[qn]); - if(!(f->rev)) return NULL; - kv_ul_ov_t *bl = &(s->ll[(uint32_t)(f->x)].tk); - uint64_t k = f->rid; k <<= 32; k += f->pos; - // if(!(bl->a[k].qn == (f->x>>32))) { - // fprintf(stderr, "[M::%s::] k::%lu, qn::%u, tn::%u, x>>32::%lu, (uint32_t)x::%u\n", - // __func__, k, qn, tn, (f->x>>32), (uint32_t)(f->x)); - // } - // if(!(bl->a[k].qn == (f->x>>32))) { - // fprintf(stderr, "[M::%s::] k::%lu, bl->a[k].qn::%u, (f->x>>32)::%lu, (uint32_t)(f->x)::%u\n", - // __func__, k, bl->a[k].qn, (f->x>>32), (uint32_t)(f->x)); - // } - assert(bl->a[k].qn == (f->x>>32)); - for (; (k < bl->n) && (bl->a[k].qn == (f->x>>32)); k++) { - if(bl->a[k].qn == bl->a[k].tn) continue; - if(bl->a[k].tn == tn) return &(bl->a[k]); - } - return NULL; -} - -double inline cal_trans_ov_w(ul_ov_t *z) -{ - double nw[2], ml, uml; - ml = z->qe - z->qs; uml = z->sec; ml -= uml; - nw[0] = (ml*CHAIN_MATCH) - (uml*CHAIN_UNMATCH); - ml = z->te - z->ts; uml = z->sec; ml -= uml; - nw[1] = (ml*CHAIN_MATCH) - (uml*CHAIN_UNMATCH); - return MIN(nw[0], nw[1]); -} - -static void worker_for_sysm_trans_ovlp(void *data, long i, int tid) // callback for kt_for() -{ - ug_trans_t *s = (ug_trans_t*)data; - uint64_t k; ul_ov_t *z; double w0, w1; - ha_mzl_t *f = &(s->srt_a.a[i]); - if(!(f->rev)) return; - kv_ul_ov_t *bl = &(s->ll[(uint32_t)(f->x)].tk); - k = f->rid; k <<= 32; k += f->pos; - // if(!(bl->a[k].qn == (f->x>>32))) { - // fprintf(stderr, "[M::%s::] k::%lu, bl->a[k].qn::%u, (f->x>>32)::%lu, (uint32_t)(f->x)::%u\n", - // __func__, k, bl->a[k].qn, (f->x>>32), (uint32_t)(f->x)); - // } - assert(bl->a[k].qn == (f->x>>32)); - for (; (k < bl->n) && (bl->a[k].qn == (f->x>>32)); k++) { - if(bl->a[k].qn == bl->a[k].tn) { - bl->a[k].qs = bl->a[k].qe = (uint32_t)-1; - continue; - } - - w0 = cal_trans_ov_w(&(bl->a[k])); - z = get_trans_ul_ov_t(s, bl->a[k].tn, bl->a[k].qn); - if(!z) { - if((!(s->keep_unsymm_arc)) || (w0 <= 0)) { - bl->a[k].qs = bl->a[k].qe = (uint32_t)-1; - } - continue; - } - if(bl->a[k].qn > bl->a[k].tn) continue; - - w1 = cal_trans_ov_w(z); - if(w0 <= 0 && w1 <= 0) { - bl->a[k].qs = bl->a[k].qe = (uint32_t)-1; - z->qs = z->qe = (uint32_t)-1; - continue; - } - if(w0 > w1) { - // (*z) = bl->a[k];///cannot copy, this will affect tn&&qn - z->qs = bl->a[k].ts; z->qe = bl->a[k].te; - z->ts = bl->a[k].qs; z->te = bl->a[k].qe; - z->sec = bl->a[k].sec; z->el = bl->a[k].el; z->rev = bl->a[k].rev; - // z->qn = bl->a[k].tn; z->tn = bl->a[k].qn; - } else { - // bl->a[k] = (*z);///cannot copy, this will affect tn&&qn - bl->a[k].ts = z->qs; bl->a[k].te = z->qe; - bl->a[k].qs = z->ts; bl->a[k].qe = z->te; - bl->a[k].sec = z->sec; bl->a[k].el = z->el; bl->a[k].rev = z->rev; - // bl->a[k].tn = z->qn; bl->a[k].qn = z->tn; - } - } -} - - -static void worker_for_ul_recorrect_alignment(void *data, long i, int tid) // callback for kt_for() -{ - utepdat_t *s = (utepdat_t*)data; - ha_ovec_buf_t *b = s->hab[tid]; - glchain_t *bl = &(s->ll[tid]); - int64_t /**rid = s->id+i,**/ winLen = MIN((((double)THRESHOLD_MAX_SIZE)/s->opt->diff_ec_ul), WINDOW), is_correct; - // uint64_t align = 0; - int fully_cov, abnormal; - // if(UL_INF.a[s->id+i].rlen != s->len[i]) { - // fprintf(stderr, "[M::%s] rid:%ld, s->len:%lu, UL_INF->rlen:%u\n", __func__, s->id+i, s->len[i], UL_INF.a[s->id+i].rlen); - // } - is_correct = ck_ul_alignment(&(UL_INF.a[s->id+i])); - if(is_correct) { - assert((UL_INF.a[s->id+i].rlen == s->len[i]) && (!s->seq[i])); - return; - } - assert(UL_INF.a[s->id+i].rlen&((uint32_t)(0x80000000))); - UL_INF.a[s->id+i].rlen<<=1; UL_INF.a[s->id+i].rlen>>=1; - assert((UL_INF.a[s->id+i].rlen == s->len[i])); - - // void *km = s->buf?(s->buf[tid]?s->buf[tid]->km:NULL):NULL; - // if(s->id+i!=41927 && s->id+i!=47072 && s->id+i!=67641 && s->id+i!=90305 && s->id+i!=698342 && s->id+i!=329421) { - // return; - // } - // if(s->id+i!=41927) return; - - // fprintf(stderr, "\n[M::%s] rid:%ld, len:%lu\n", __func__, s->id+i, s->len[i]); - // if (memcmp(UL_INF.nid.a[s->id+i].a, "d0aab024-b3a7-40fb-83cc-22c3d6d951f8", UL_INF.nid.a[s->id+i].n-1)) return; - // fprintf(stderr, "[M::%s::] ==> len: %lu\n", __func__, s->len[i]); - ha_get_ul_candidates_interface(b->abl, i, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->olist_hp, &b->clist, s->opt->bw_thres, - s->opt->max_n_chain, 1, NULL/**&(b->k_flag)**/, &b->r_buf, &(b->tmp_region), NULL, &(b->sp), 1, NULL); - - clear_Cigar_record(&b->cigar1); - clear_Round2_alignment(&b->round2); - // return; - // b->num_correct_base += overlap_statistics(&b->olist, NULL, 0); - - b->self_read.seq = s->seq[i]; b->self_read.length = s->len[i]; b->self_read.size = 0; - correct_ul_overlap(&b->olist, s->uu, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, - &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 1, &fully_cov, &abnormal, s->opt->diff_ec_ul, winLen, NULL); - - // uint64_t k; - // for (k = 0; k < b->olist.length; k++) { - // if(b->olist.list[k].is_match == 1) b->num_correct_base += b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; - // if(b->olist.list[k].is_match == 2) b->num_recorrect_base += b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; - // } - - - // gl_chain_refine(&b->olist, &b->correct, &b->hap, bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], km); - gl_chain_refine_advance_combine(s->buf[tid], &(UL_INF.a[s->id+i]), &b->olist, &b->correct, &b->hap, &(s->sps[tid]), bl, &(s->gdp[tid]), s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, tid, NULL); - // return; - // b->num_read_base += b->self_read.length; - // b->num_correct_base += b->correct.corrected_base; - // b->num_recorrect_base += b->round2.dumy.corrected_base; - memset(&b->self_read, 0, sizeof(b->self_read)); - - - - is_correct = ck_ul_alignment(&(UL_INF.a[s->id+i])); - if(is_correct) b->num_correct_base++; - s->hab[tid]->num_read_base++; - - // fprintf(stderr, "[M::%s] rid:%ld, dd:%u\n", __func__, s->id+i, UL_INF.a[s->id+i].dd); - // int64_t mem[6], mem_hab[6]; - // if(get_utepdat_t_mem_tid(s, tid, mem, mem_hab)>((int64_t)5*(int64_t)1073741824)) { - // fprintf(stderr, "[M::%s::tid->%d::rid->%ld] buffer[0]: %.3fGB(%.3fGB::%.3fGB::%.3fGB::%.3fGB::%.3fGB), buffer[1]: %.3fGB, buffer[2]: %.3fGB, buffer[3]: %.3fGB, buffer[4]: %.3fGB, buffer[5]: %.3fGB\n", - // __func__, tid, i, mem[0]/1073741824.0, - // mem_hab[0]/1073741824.0, mem_hab[1]/1073741824.0, mem_hab[2]/1073741824.0, - // mem_hab[3]/1073741824.0, mem_hab[4]/1073741824.0, - // mem[1]/1073741824.0, mem[2]/1073741824.0, - // mem[3]/1073741824.0, mem[4]/1073741824.0, mem[5]/1073741824.0); - // } - - // align = kv_ul_ov_t_statistics(&(bl->tk), i, &(b->num_recorrect_base)); - // if(align == s->len[i]) { - // free(s->seq[i]); s->seq[i] = NULL; - // } - // b->num_correct_base += align; - - // uint64_t k; - // b->num_read_base += overlap_statistics(&b->olist, NULL, NULL, 1); - // for (k = 0; k < bl->tk.n; k++) { - // if(bl->tk.a[k].sec == 0) b->num_correct_base += bl->tk.a[k].qe - bl->tk.a[k].qs; - // if(bl->tk.a[k].sec > 0) b->num_recorrect_base += bl->tk.a[k].qe - bl->tk.a[k].qs; - // } - // for (k = 0; k < bl->lo.n; k++) { - // b->num_read_base += bl->lo.a[k].qe - bl->lo.a[k].qs; - // } - - // uint32_t l1 = overlap_statistics(&b->olist, s->uu->ug, 1), l2 = overlap_statistics(&b->olist, s->uu->ug, 2); - // - // if(l1 == 0 && l2 > 0) fprintf(stderr, "[M::%s::%lu::no_match]\n", UL_INF.nid.a[s->id+i].a, s->len[i]); - // fprintf(stderr, "[M::%s::%lu::] l1->%u; l2->%u\n", UL_INF.nid.a[s->id+i].a, s->len[i], l1, l2); - // fprintf(stderr, "[M::%s::rid->%ld] done\n", __func__, s->id+i); - // exit(1); -} - - -void dump_gaf(mg_gres_a *hits, const mg_gchains_t *gs, uint32_t only_p) -{ - if (gs == NULL || gs->n_gc == 0 || gs->n_lc == 0) return; - uint64_t i, j; - int64_t q_span; - mg_gres_t *p = NULL; - kv_pushp(mg_gres_t, *hits, &p); memset(p, 0, sizeof(*p)); - p->n_gc = 0; p->n_lc = 0; p->qid = gs->qid; p->qlen = gs->qlen; - // p->n_gc = gs->n_gc; p->n_lc = gs->n_lc; p->qid = gs->qid; p->qlen = gs->qlen; - // MALLOC(p->gc, p->n_gc); memcpy(p->gc, gs->gc, p->n_gc); - for (i = 0; i < (uint64_t)gs->n_gc; ++i) { - const mg_gchain_t *t = &gs->gc[i];///one of the gchain - if(only_p && t->id != t->parent) continue; - if (t->cnt == 0) continue; - p->n_gc++; p->n_lc += t->cnt; - } - if (p->n_gc == 0) { - hits->n--; - return; - } - MALLOC(p->gc, p->n_gc); MALLOC(p->lc, p->n_lc); - p->n_gc = p->n_lc = 0; - for (i = 0; i < (uint64_t)gs->n_gc; ++i) { - const mg_gchain_t *t = &gs->gc[i];///one of the gchain - if(only_p && t->id != t->parent) continue; - if (t->cnt == 0) continue; - p->gc[p->n_gc] = *t; p->gc[p->n_gc].off = p->n_lc; - for (j = 0; j < (uint64_t)t->cnt; ++j) { - const mg_llchain_t *q = &gs->lc[t->off + j]; - p->lc[p->n_lc+j].cnt = q->cnt; - p->lc[p->n_lc+j].score = q->score; - p->lc[p->n_lc+j].v = q->v; - if(q->cnt) { - q_span = (int32_t)(gs->a[q->off].y>>32&0xff); - p->lc[p->n_lc+j].qs = (int32_t)gs->a[q->off].y + 1 - q_span;///calculated by the first lchain - p->lc[p->n_lc+j].ts = (int32_t)gs->a[q->off].x + 1 - q_span;///calculated by the first lchain - p->lc[p->n_lc+j].qe = (int32_t)gs->a[q->off + q->cnt - 1].y + 1; - p->lc[p->n_lc+j].te = (int32_t)gs->a[q->off + q->cnt - 1].x + 1; - } else { - p->lc[p->n_lc+j].qs = p->lc[p->n_lc+j].qe = p->lc[p->n_lc+j].ts = p->lc[p->n_lc+j].te = (uint32_t)-1; - } - - // mg_sprintf_lite(s, "%c%s", "><"[q->v&1], g->seg[q->v>>1].name); - } - p->n_gc++; p->n_lc += t->cnt; - } -} - - -int64_t get_utepdat_t_mem(const utepdat_t *b, int64_t is_print) -{ - int64_t i, mem[7] = {0}, tt[6] = {0}; - for (i = 0; i < b->n_thread; i++) { - get_utepdat_t_mem_tid(b, i, tt, NULL); - mem[0] += tt[0]; mem[1] += tt[1]; mem[2] += tt[2]; mem[3] += tt[3]; mem[4] += tt[4]; mem[5] += tt[5]; - } - - for (i = 0; i < b->n; ++i) mem[6] += b->len[i]; - mem[6] += (sizeof(*(b->len))*b->n) + (sizeof(*(b->seq))*b->n); - if(is_print) { - for (i = 0; i < 7; i++) { - fprintf(stderr, "[M::%s] size of buffer[%ld]: %.3fGB, %.3fKB, %ldB\n", - __func__, i, mem[i]/1073741824.0, mem[i]/1048576.0, mem[i]); - } - } - - return mem[0] + mem[1] + mem[2] + mem[3] + mem[4] + mem[5] + mem[6]; -} - -static void *worker_ul_pipeline(void *data, int step, void *in) // callback for kt_pipeline() -{ - uldat_t *p = (uldat_t*)data; - ///uint64_t total_base = 0, total_pair = 0; - if (step == 0) { // step 1: read a block of sequences - int ret; - uint64_t l; - utepdat_t *s; - CALLOC(s, 1); - s->ha_flt_tab = p->ha_flt_tab; s->ha_idx = p->ha_idx; s->id = p->total_pair; - s->opt = p->opt; s->ug = p->ug; s->uopt = p->uopt; s->rg = p->rg; - while ((ret = kseq_read(p->ks)) >= 0) - { - if (p->ks->seq.l < (uint64_t)p->opt->k) continue; - if (s->n == s->m) { - s->m = s->m < 16? 16 : s->m + (s->n>>1); - REALLOC(s->len, s->m); - REALLOC(s->seq, s->m); - } - /**if(asm_opt.flag & HA_F_VERBOSE_GFA)**/ { - kv_push(uint64_t, p->nn, p->ks->name.l+p->nn.tl); - kv_resize(char, p->nn.cc, p->ks->name.l+p->nn.tl); - memcpy(p->nn.cc.a+p->nn.tl, p->ks->name.s, p->ks->name.l); - p->nn.tl += p->ks->name.l; - } - l = p->ks->seq.l; - MALLOC(s->seq[s->n], l); - s->sum_len += l; - memcpy(s->seq[s->n], p->ks->seq.s, l); - s->len[s->n++] = l; - if (s->sum_len >= p->chunk_size) break; - } - p->total_pair += s->n; - if (s->sum_len == 0) free(s); - else return s; - } - else if (step == 1) { // step 2: alignment - uint64_t i; - utepdat_t *s = (utepdat_t*)in; - CALLOC(s->mzs, p->n_thread); - CALLOC(s->sps, p->n_thread); - CALLOC(s->gcs, s->n); - - s->buf = (mg_tbuf_t**)calloc(p->n_thread, sizeof(mg_tbuf_t*)); - for (i = 0; i < p->n_thread; ++i) s->buf[i] = mg_tbuf_init(); - - kt_for(p->n_thread, worker_for_ul_alignment, s, s->n); - for (i = 0; i < (uint64_t)s->n; ++i) { - free(s->seq[i]); - p->total_base += s->len[i]; - } - free(s->seq); free(s->len); - - for (i = 0; i < p->n_thread; ++i) { - mg_tbuf_destroy(s->buf[i]); - free(s->mzs[i].a); free(s->sps[i].a); - } - - free(s->buf); free(s->mzs); free(s->sps); - return s; - } - else if (step == 2) { // step 3: dump - utepdat_t *s = (utepdat_t*)in; - uint64_t i; - for (i = 0; i < (uint64_t)s->n; ++i) { - // if(s->pos[i].s == (uint64_t)-1) continue; - // kv_push(pe_hit, p->hits.a, s->pos[i]); - if(!s->gcs[i]) continue; - dump_gaf(&(p->hits), s->gcs[i], 1); - free(s->gcs[i]->gc); free(s->gcs[i]->a); free(s->gcs[i]->lc); free(s->gcs[i]); - } - free(s->gcs); - free(s); - } - return 0; -} - -int alignment_ul_pipeline(uldat_t* sl, const enzyme *fn) -{ - double index_time = yak_realtime(); - int i; - for (i = 0; i < fn->n; i++){ - gzFile fp; - if ((fp = gzopen(fn->a[i], "r")) == 0) return 0; - sl->ks = kseq_init(fp); - kt_pipeline(3, worker_ul_pipeline, sl, 3); - kseq_destroy(sl->ks); - gzclose(fp); - } - sl->hits.total_base = sl->total_base; - sl->hits.total_pair = sl->total_pair; - fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); - return 1; -} - -void push_uc_block_t(const ug_opt_t *uopt, kv_ul_ov_t *z, char **seq, uint64_t *len, uint64_t b_id) -{ - uint64_t k, l, rid; - for (k = 1, l = 0; k <= z->n; k++) { - if(k == z->n || z->a[k].qn != z->a[l].qn) { - rid = b_id + z->a[l].qn; - // fprintf(stderr, "rid->%lu, b_id->%lu, l->%lu, z->a[l].qn->%u, len[z->a[l].qn]->%lu, seq[z->a[l].qn]->%u\n", rid, b_id, l, z->a[l].qn, len[z->a[l].qn], seq[z->a[l].qn]?1:0); - append_ul_t(&UL_INF, &rid, NULL, 0, seq[z->a[l].qn], len[z->a[l].qn], z->a + l, k - l, P_CHAIN_COV, uopt, 0); - // append_ul_t_back(&UL_INF, &rid, NULL, 0, seq[z->a[l].qn], len[z->a[l].qn], z->a + l, k - l, P_CHAIN_COV); - l = k; - } - } -} - -static void *worker_ul_scall_pipeline(void *data, int step, void *in) // callback for kt_pipeline() -{ - uldat_t *p = (uldat_t*)data; - ///uint64_t total_base = 0, total_pair = 0; - if (step == 0) { // step 1: read a block of sequences - int ret; - uint64_t l; - utepdat_t *s; - CALLOC(s, 1); - s->ha_flt_tab = p->ha_flt_tab; s->ha_idx = p->ha_idx; s->id = p->total_pair; - s->opt = p->opt; s->uu = p->uu; s->uopt = p->uopt; s->rg = p->rg; - while ((ret = kseq_read(p->ks)) >= 0) - { - if ((p->ks->seq.l < (uint64_t)p->opt->k) || (p->ks->seq.l < asm_opt.ul_min_base)) continue; - if (s->n == s->m) { - s->m = s->m < 16? 16 : s->m + (s->n>>1); - REALLOC(s->len, s->m); - REALLOC(s->seq, s->m); - } - - append_ul_t(&UL_INF, NULL, p->ks->name.s, p->ks->name.l, NULL, 0, NULL, 0, P_CHAIN_COV, s->uopt, 0); - l = p->ks->seq.l; - MALLOC(s->seq[s->n], l); - s->sum_len += l; - memcpy(s->seq[s->n], p->ks->seq.s, l); - // fprintf(stderr, "s->n->%d, l->%lu\n", s->n, l); - s->len[s->n++] = l; - if (s->sum_len >= p->chunk_size) break; - } - p->total_pair += s->n; - if (s->sum_len == 0) free(s); - else return s; - } - else if (step == 1) { // step 2: alignment - utepdat_t *s = (utepdat_t*)in; - - uint64_t i; - CALLOC(s->hab, p->n_thread); CALLOC(s->ll, p->n_thread); - CALLOC(s->sps, p->n_thread); - // CALLOC(s->buf, p->n_thread); - for (i = 0; i < p->n_thread; ++i) { - // s->buf[i] = mg_tbuf_init(); - // s->hab[i] = ha_ovec_buf_init(s->buf[i]->km, 0, 0, 1); - // s->buf[i] = NULL; - // s->hab[i] = ha_ovec_buf_init(NULL, 0, 0, 1); - s->hab[i] = ha_ovec_init(0, 0, 1); - } - // fprintf(stderr, "[M::%s::Start] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); - kt_for(p->n_thread, worker_for_ul_scall_alignment, s, s->n); - // fprintf(stderr, "[M::%s::Done] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); - ///debug - /** - uint64_t i; - CALLOC(s->mzs, p->n_thread); - CALLOC(s->sps, p->n_thread); - CALLOC(s->gcs, s->n); - - s->buf = (mg_tbuf_t**)calloc(p->n_thread, sizeof(mg_tbuf_t*)); - for (i = 0; i < p->n_thread; ++i) s->buf[i] = mg_tbuf_init(); - - kt_for(p->n_thread, worker_for_ul_alignment, s, s->n); - for (i = 0; i < (uint64_t)s->n; ++i) { - free(s->seq[i]); - p->total_base += s->len[i]; - } - free(s->seq); free(s->len); - - for (i = 0; i < p->n_thread; ++i) { - mg_tbuf_destroy(s->buf[i]); - free(s->mzs[i].a); free(s->sps[i].a); - } - **/ - for (i = 0; i < p->n_thread; ++i) { - s->num_bases += s->hab[i]->num_read_base; - s->num_corrected_bases += s->hab[i]->num_correct_base; - s->num_recorrected_bases += s->hab[i]->num_recorrect_base; - // mg_tbuf_destroy(s->buf[i]); - ha_ovec_destroy(s->hab[i]); kv_destroy(s->sps[i]); - free(s->ll[i].lo.a); /**free(s->ll[i].tk.a);**/ free(s->ll[i].srt.a.a); free(s->ll[i].tc.a); - } - free(s->hab); free(s->sps); - /**free(s->ll);**/ // free(s->buf); - //free(s->mzs); free(s->sps); - return s; - } - else if (step == 2) { // step 3: dump - utepdat_t *s = (utepdat_t*)in; - uint64_t i, rid; - p->num_bases += s->num_bases; - p->num_corrected_bases += s->num_corrected_bases; - p->num_recorrected_bases += s->num_recorrected_bases; - // fprintf(stderr, "[M::%s::dump_start] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); - for (i = 0; i < p->n_thread; ++i) { - push_uc_block_t(s->uopt, &(s->ll[i].tk), s->seq, s->len, s->id); - free(s->ll[i].tk.a); - } - for (i = 0; i < (uint64_t)s->n; ++i) { - rid = s->id + i; - if((UL_INF.n <= rid) || (UL_INF.n > rid && UL_INF.a[rid].rlen != s->len[i])) { - append_ul_t(&UL_INF, &rid, NULL, 0, s->seq[i], s->len[i], NULL, 0, P_CHAIN_COV, s->uopt, 0); - } - free(s->seq[i]); - } - // fprintf(stderr, "[M::%s::dump_done] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); - /** - for (i = 0; i < (uint64_t)s->n; ++i) { - ///debug - - // if(s->pos[i].s == (uint64_t)-1) continue; - // kv_push(pe_hit, p->hits.a, s->pos[i]); - // if(!s->gcs[i]) continue; - // dump_gaf(&(p->hits), s->gcs[i], 1); - // free(s->gcs[i]->gc); free(s->gcs[i]->a); free(s->gcs[i]->lc); free(s->gcs[i]); - - rid = s->id + i; - append_ul_t(&UL_INF, &rid, NULL, 0, s->seq[i], s->len[i], NULL, 0, P_CHAIN_COV); - // fprintf(stderr, "%.*s\n", (int)s->len[i], s->seq[i]); - free(s->seq[i]); p->total_base += s->len[i]; - } - **/ - ///debug - /** - free(s->gcs); - **/ - - free(s->ll); free(s->len); free(s->seq); free(s); - } - return 0; -} - - -static void *worker_ul_rescall_pipeline(void *data, int step, void *in) // callback for kt_pipeline() -{ - uldat_t *p = (uldat_t*)data; - ///uint64_t total_base = 0, total_pair = 0; - if (step == 0) { // step 1: read a block of sequences - int ret; - uint64_t l; - utepdat_t *s; - CALLOC(s, 1); - s->ha_flt_tab = p->ha_flt_tab; s->ha_idx = p->ha_idx; s->id = p->total_pair; - s->opt = p->opt; s->uu = p->uu; s->uopt = p->uopt; s->rg = p->rg; s->mm = p->mm; - while ((ret = kseq_read(p->ks)) >= 0) - { - if ((p->ks->seq.l < (uint64_t)p->opt->k) || (p->ks->seq.l < asm_opt.ul_min_base)) continue; - if (s->n == s->m) { - s->m = s->m < 16? 16 : s->m + (s->n>>1); - REALLOC(s->len, s->m); - REALLOC(s->seq, s->m); - } - - // append_ul_t(&UL_INF, NULL, p->ks->name.s, p->ks->name.l, NULL, 0, NULL, 0, P_CHAIN_COV, s->uopt); - l = p->ks->seq.l; - MALLOC(s->seq[s->n], l); - s->sum_len += l; - memcpy(s->seq[s->n], p->ks->seq.s, l); - // fprintf(stderr, "s->n->%d, l->%lu\n", s->n, l); - // fprintf(stderr, "+++++rid->%lu, l->%lu, %.*s\n", - // s->id + s->n, l, (int32_t)p->ks->name.l, p->ks->name.s); - s->len[s->n++] = l; - if (s->sum_len >= p->chunk_size) break; - } - p->total_pair += s->n; - if (s->sum_len == 0) free(s); - else return s; - } - else if (step == 1) { // step 2: alignment - utepdat_t *s = (utepdat_t*)in; - - uint64_t i; s->n_thread = p->n_thread; - CALLOC(s->hab, p->n_thread); CALLOC(s->ll, p->n_thread); CALLOC(s->buf, p->n_thread); - CALLOC(s->gdp, p->n_thread); CALLOC(s->mzs, p->n_thread); CALLOC(s->sps, p->n_thread); - CALLOC(s->mk, p->n_thread); - - // CALLOC(s->buf, p->n_thread); - for (i = 0; i < p->n_thread; ++i) { - s->hab[i] = ha_ovec_init(0, 0, 1); s->buf[i] = mg_tbuf_init(); - } - // fprintf(stderr, "[M::%s::Start] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); - kt_for(p->n_thread, worker_for_ul_rescall_alignment, s, s->n); - // fprintf(stderr, "[M::%s::Done] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); - // get_utepdat_t_mem(s, 1); - - for (i = 0; i < p->n_thread; ++i) { - p->num_bases += s->hab[i]->num_read_base; - p->num_corrected_bases += s->hab[i]->num_correct_base; - - // s->num_recorrected_bases += s->hab[i]->num_recorrect_base; - ha_ovec_destroy(s->hab[i]); hc_glchain_destroy(&(s->ll[i])); - mg_tbuf_destroy(s->buf[i]); hc_gdpchain_destroy(&(s->gdp[i])); - kv_destroy(s->mzs[i]); kv_destroy(s->sps[i]); - kv_destroy(s->mk[i].idx); kv_destroy(s->mk[i].srt); - //free(s->seq[i]); - } - free(s->hab); free(s->ll); free(s->mk); ///free(s->len); free(s->seq); - free(s->buf); free(s->gdp); free(s->mzs); free(s->sps); ///free(s); - return s; - } else if (step == 2) { // step 3: dump - utepdat_t *s = (utepdat_t*)in; int64_t i, rid; - // fprintf(stderr, "[M::%s::dump_start] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); - for (i = 0; i < s->n; ++i) { - rid = s->id + i; - if(UL_INF.a[rid].dd == 3 && p->ucr_s && p->ucr_s->flag == 1) {///for the scaffolding - assert(s->seq[i]); - // if(s->seq[i] == NULL) fprintf(stderr, "[M::%s::]rid->%ld, len->%lu\n", __func__, rid, s->len[i]); - ///for debug interval - write_compress_base_disk(p->ucr_s->fp, rid, s->seq[i], s->len[i], &(p->ucr_s->u)); - } - // if(UL_INF.a[rid].dd) fprintf(stderr, "rid->%ld\n", rid); - free(s->seq[i]); - } - // fprintf(stderr, "[M::%s::dump_done] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); - free(s->len); free(s->seq); free(s); - } - return 0; -} - -static void *worker_ul_recorrect_pipeline(void *data, int step, void *in) // callback for kt_pipeline() -{ - uldat_t *p = (uldat_t*)data; - ///uint64_t total_base = 0, total_pair = 0; - if (step == 0) { // step 1: read a block of sequences - int ret; - uint64_t l, rid; - utepdat_t *s; - CALLOC(s, 1); - s->ha_flt_tab = p->ha_flt_tab; s->ha_idx = p->ha_idx; s->id = p->total_pair; - s->opt = p->opt; s->uu = p->uu; s->uopt = p->uopt; s->rg = p->rg; - while ((ret = kseq_read(p->ks)) >= 0) - { - if (p->ks->seq.l < (uint64_t)p->opt->k) continue; - if (s->n == s->m) { - s->m = s->m < 16? 16 : s->m + (s->n>>1); - REALLOC(s->len, s->m); - REALLOC(s->seq, s->m); - } - // append_ul_t(&UL_INF, NULL, p->ks->name.s, p->ks->name.l, NULL, 0, NULL, 0, P_CHAIN_COV, s->uopt); - l = p->ks->seq.l; s->seq[s->n] = NULL; rid = s->id + s->n; - if(UL_INF.a[rid].rlen & ((uint32_t)(0x80000000))) { - MALLOC(s->seq[s->n], l); memcpy(s->seq[s->n], p->ks->seq.s, l); - } - s->sum_len += l; - s->len[s->n++] = l; - if (s->sum_len >= p->chunk_size) break; - } - p->total_pair += s->n; - if (s->sum_len == 0) free(s); - else return s; - } - else if (step == 1) { // step 2: alignment - utepdat_t *s = (utepdat_t*)in; - - uint64_t i; s->n_thread = p->n_thread; - CALLOC(s->hab, p->n_thread); CALLOC(s->ll, p->n_thread); CALLOC(s->buf, p->n_thread); - CALLOC(s->gdp, p->n_thread); CALLOC(s->mzs, p->n_thread); CALLOC(s->sps, p->n_thread); - - // CALLOC(s->buf, p->n_thread); - for (i = 0; i < p->n_thread; ++i) { - s->hab[i] = ha_ovec_init(0, 0, 1); s->buf[i] = mg_tbuf_init(); - } - fprintf(stderr, "[M::%s::Start] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); - kt_for(p->n_thread, worker_for_ul_recorrect_alignment, s, s->n); - fprintf(stderr, "[M::%s::Done] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); - get_utepdat_t_mem(s, 1); - - for (i = 0; i < p->n_thread; ++i) { - p->num_bases += s->hab[i]->num_read_base; - p->num_corrected_bases += s->hab[i]->num_correct_base; - - // s->num_recorrected_bases += s->hab[i]->num_recorrect_base; - ha_ovec_destroy(s->hab[i]); hc_glchain_destroy(&(s->ll[i])); - mg_tbuf_destroy(s->buf[i]); hc_gdpchain_destroy(&(s->gdp[i])); - kv_destroy(s->mzs[i]); kv_destroy(s->sps[i]); free(s->seq[i]); - } - free(s->hab); free(s->ll); free(s->len); free(s->seq); - free(s->buf); free(s->gdp); free(s->mzs); free(s->sps); free(s); - } - return 0; -} - - -int32_t init_ucr_file_t(uldat_t *sl, char* file, uint64_t mode) -{ - if(mode == 1 || mode == 2) { - char *gfa_name = (char*)malloc(strlen(file)+25); - sprintf(gfa_name, "%s.uidx.ucr.bin", file); - CALLOC(sl->ucr_s, 1); - sl->ucr_s->flag = mode; - sl->ucr_s->fp = fopen(gfa_name, mode==1?"w":"r"); - if (!(sl->ucr_s->fp)) { - free(gfa_name); - return 0; - } - free(gfa_name); - return 1; - } - return 0; -} - - -void destory_ucr_file_t(uldat_t *sl) -{ - if(sl->ucr_s) { - free(sl->ucr_s->u.r_base.a); - free(sl->ucr_s->u.bb.a); - free(sl->ucr_s->u.N_site.a); - - fclose(sl->ucr_s->fp); - free(sl->ucr_s); - sl->ucr_s = NULL; - } -} - - -void debug_sl_compress_base_disk_0(uldat_t *sl, char* gfa_name) -{ - int32_t ret, rid = 0, sr_0, sr_1; gzFile fp; - init_ucr_file_t(sl, gfa_name, 1); - fp = gzopen(gfa_name, "r"); assert(fp); - sl->ks = kseq_init(fp); - while ((ret = kseq_read(sl->ks)) >= 0) { - write_compress_base_disk(sl->ucr_s->fp, rid, sl->ks->seq.s, sl->ks->seq.l, &(sl->ucr_s->u)); - rid++; - } - kseq_destroy(sl->ks); - gzclose(fp); - - destory_ucr_file_t(sl); - - - uint64_t ulid; uint32_t ulen; kvec_t(char) des; kv_init(des); - init_ucr_file_t(sl, gfa_name, 2); rid = 0; - - fp = gzopen(gfa_name, "r"); assert(fp); - sl->ks = kseq_init(fp); - while (1) { - sr_0 = kseq_read(sl->ks); des.n = 0; - if(sr_0 >= 0) sr_0 = 1; - else sr_0 = 0; - if(sr_0 == 0) sl->ks->seq.l = 1; - kv_resize(char, des, sl->ks->seq.l); - sr_1 = load_compress_base_disk(sl->ucr_s->fp, &ulid, des.a, &ulen, &(sl->ucr_s->u)); - if(sr_0 != sr_1) fprintf(stderr, "[M::%s::] rid->%d, sr_0->%d, sr_1->%d\n", __func__, rid, sr_0, sr_1); - assert(sr_0 == sr_1); - if(sr_0 == 0 || sr_1 == 0) break; - // if(rid != (int64_t)ulid) fprintf(stderr, "[M::%s::] rid->%d, ulid->%lu, sr_0->%d, sr_1->%d\n", __func__, rid, ulid, sr_0, sr_1); - assert(rid == (int64_t)ulid); - assert(sl->ks->seq.l == ulen); - assert(memcmp(sl->ks->seq.s, des.a, ulen) == 0); - rid++; - } - kseq_destroy(sl->ks); kv_destroy(des); - gzclose(fp); - - destory_ucr_file_t(sl); - fprintf(stderr, "[M::%s::] ==> Have checked %d UL reads\n", __func__, rid); - -} - -void debug_sl_compress_base_disk_0(uldat_t *sl, const enzyme *fn) -{ - int32_t i; - for (i = 0; i < fn->n; i++) debug_sl_compress_base_disk_0(sl, fn->a[i]); - exit(1); -} - - - -utg_rid_dt *get_r_ug_region(utg_rid_t *idx, uint64_t *n, uint64_t rid) -{ - (*n) = idx->idx[rid+1] - idx->idx[rid]; - return (*n)?idx->p.a + idx->idx[rid]:NULL; -} - -uint64_t rov2uov(uint64_t rid, const ul_idx_t *uref, utg_rid_dt *ru_map, uc_block_t *rovlp, ul_ov_t *res, uint32_t adjust_rev, int64_t ulid) -{ - uint64_t ori = ru_map->u&1, ts, te; - if(!ori) { - ts = rovlp->ts; te = rovlp->te; - } else { - ts = uref->r_ug->rg->seq[rid].len - rovlp->te; - te = uref->r_ug->rg->seq[rid].len - rovlp->ts; - } - // if(ulid == 14714) { - // fprintf(stderr, "[M::%s::]\tori::%lu\trovlp->rev::%u\tro_t::[%u, %u)\tt::[%lu, %lu)\toff::%u\n", __func__, - // ori, rovlp->rev, rovlp->ts, rovlp->te, ts, te, ru_map->off); - // } - ts += ru_map->off; te += ru_map->off; - if(ts >= 0 && te <= uref->ug->g->seq[ru_map->u>>1].len) { - memset(res, 0, sizeof(*res)); - res->qn = 0; res->qs = rovlp->qs; res->qe = rovlp->qe; - res->tn = ru_map->u>>1; res->ts = ts; res->te = te; - res->el = rovlp->el; res->rev = (rovlp->rev == ori?0:1); - if(adjust_rev && res->rev) {///for linear chaining - res->ts = uref->ug->g->seq[res->tn].len - te; - res->te = uref->ug->g->seq[res->tn].len - ts; - } - return 1; - } - return 0; - // if(ulid == 14714) { - // fprintf(stderr, "[M::%s::]\tulen::%u\trlen::%u\tro_t::[%u, %u)\tt::[%lu, %lu)\toff::%u\n", __func__, - // uref->ug->g->seq[res->tn].len, uref->r_ug->rg->seq[rid].len, rovlp->ts, rovlp->te, ts, te, ru_map->off); - // } -} - -void print_ul_ov_t(ul_ov_t *xs, const char* cmd) -{ - fprintf(stderr, "%s\t%s\t%u\t%u\t%c\t%.*s\t%u\t%u\n", cmd, UL_INF.nid.a[xs->qn].a, xs->qs, xs->qe, - "+-"[xs->rev], (int)Get_NAME_LENGTH(R_INF, ((xs->tn<<1)>>1)), Get_NAME(R_INF, ((xs->tn<<1)>>1)), xs->ts, xs->te); -} - -void gl_rg2ug_gen(ul_vec_t *r_cl, kv_ul_ov_t *u_cl, const ul_idx_t *uref, uint64_t is_el, uint64_t n_pchain, int64_t ulid) -{ - uint64_t k, a_k, a_n; uc_block_t *z; utg_rid_dt *a; ul_ov_t p; - u_cl->n = 0; - for (k = 0; k < r_cl->bb.n; k++) { - z = &(r_cl->bb.a[k]); - if(z->base) continue; - if(is_el && (!(z->el))) continue; - if(z->pchain == n_pchain) continue; - a = get_r_ug_region(uref->r_ug, &a_n, z->hid); - if(!a) continue; - for (a_k = 0; a_k < a_n; a_k++) { - // if(ulid == 14714) { - // fprintf(stderr, "\n+[M::%s::]\tq::[%u, %u)\t%c\t%.*s(%u)\tt::[%u, %u)\n", __func__, z->qs, z->qe, "+-"[z->rev], - // (int)Get_NAME_LENGTH(R_INF, z->hid), Get_NAME(R_INF, z->hid), (uint32_t)Get_READ_LENGTH(R_INF, z->hid), - // z->ts, z->te); - // fprintf(stderr, "*[M::%s::] utg%.6d%c(%u)\t%c\toff::%u\tpos::%u\n", __func__, - // (int32_t)(a[a_k].u>>1)+1, "lc"[uref->ug->u.a[a[a_k].u>>1].circ], uref->ug->u.a[a[a_k].u>>1].len, - // "+-"[a[a_k].u&1], a[a_k].off, a[a_k].pos); - // } - if(!rov2uov(z->hid, uref, &(a[a_k]), z, &p, 1, ulid)) continue; - p.el = 1; p.tn <<= 1; p.tn |= p.rev; p.qn = k/**uref->r_ug->idx[z->hid] + a_k**/;//for linear chain - kv_push(ul_ov_t, *u_cl, p); - // if(ulid == 14714) { - // fprintf(stderr, "[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\ttlen::%u\n", __func__, - // (int32_t)(p->tn>>1)+1, "+-"[p->tn&1], p->qs, p->qe, - // p->ts, p->te, uref->ug->g->seq[p->tn>>1].len); - // } - // if(k == 2) { - // fprintf(stderr, "[M::%s::] p->ts:%u, p->te:%u, z->ts:%u, z->te:%u, a[a_k].off:%u\n", __func__, p->ts, p->te, z->ts, z->te, a[a_k].off); - // } - // fprintf(stderr, "-[M::%s::] %u\t%u\t%c\tutg%.6d%c(%u)\t%u\t%u\n", __func__, p->qs, p->qe, "+-"[p->rev], - // (int32_t)(p->tn>>1)+1, "lc"[uref->ug->u.a[p->tn>>1].circ], uref->ug->u.a[p->tn>>1].len, p->ts, p->te); - } - } -} - -void adjust_rev_tse(ul_ov_t *x, int64_t tlen, int64_t *ts, int64_t *te) -{ - *ts = x->ts; *te = x->te; - if(x->rev) { - *ts = tlen - x->te; *te = tlen - x->ts; - } -} - -uint64_t get_add_cov_score(const ul_idx_t *uref, int64_t ps, int64_t pe, int64_t cs, int64_t ce, int64_t uid, int64_t *cov_i) -{ - int64_t os = MAX(ps, cs), oe = MIN(pe, ce); - int64_t ovlp = ((oe > os)? (oe - os):0); - // fprintf(stderr, "ovlp:%ld, os:%ld, oe:%ld, ps:%ld, pe:%ld, cs:%ld, ce::%ld\n", ovlp, os, oe, ps, pe, cs, ce); - if(ovlp > 0) { - return (os>cs?retrieve_u_cov_region(uref, uid, 0, cs, os, cov_i):0) + - (ce>oe?retrieve_u_cov_region(uref, uid, 0, oe, ce, cov_i):0); - } - - return retrieve_u_cov_region(uref, uid, 0, cs, ce, cov_i); -} - -uint64_t linear_chain_dp(ul_ov_t *ch, int64_t ch_n, ul_ov_t *sv, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, int64_t max_skip, uint64_t *idx, uint64_t *track, ma_ug_t *ug, int64_t chain_offset) -{ ///all in[].el must be 1 - if(ch_n == 0) return 0; - int64_t /**mm_ovlp, x,**/ i, j, k, sc, csc, mm_sc, mm_idx, its, ite, jts, jte, cov_i, dq, dt, dd, mm; - ul_ov_t *li = NULL, *lj = NULL; - radix_sort_ul_ov_srt_qe(ch, ch + ch_n); - for (i = 1, j = 0; i <= ch_n; i++) { - // if(i < ch_n) { - // li = &(ch[i]); - // fprintf(stderr, "##(%ld) %u\t%u\t%c\tutg%.6d%c(%u)\t%u\t%u\tmm_idx:%ld\tmm_sc:%ld\n", i, li->qs, li->qe, "+-"[li->rev], - // (int32_t)(li->tn)+1, "lc"[uref->ug->u.a[li->tn].circ], uref->ug->u.a[li->tn].len, li->ts, li->te, mm_idx, mm_sc); - // } - if (i == ch_n || ch[i].qe != ch[j].qe) { - if(i - j > 1) { - radix_sort_ul_ov_srt_qs(ch+j, ch+i); - } - j = i; - } - } - - // fprintf(stderr, "[M::%s::] ch_n:%ld\n", __func__, ch_n); - for (i = 0; i < ch_n; ++i) { - li = &(ch[i]); - // mm_ovlp = max_ovlp_src(uopt, ((li->tn<<1)|li->rev)^1); - // x = (li->qs + mm_ovlp)*diff_ec_ul; - // if(x < bw) x = bw; - // x += li->qs + mm_ovlp; - // if (x > qlen+1) x = qlen+1; - // x = find_ul_ov_max(i, ch, x+G_CHAIN_INDEL); - adjust_rev_tse(li, ug->g->seq[li->tn].len, &its, &ite); - cov_i = 0; - csc = retrieve_u_cov_region(uref, li->tn, 0, its, ite, &cov_i); - mm_sc = csc; mm_idx = -1; - for (j = i-1/**x**/; j >= 0; --j) { - lj = &(ch[j]); - // fprintf(stderr, "<0>\n"); - if(lj->qs <= li->qs && lj->qe <= li->qe && lj->ts <= li->ts && lj->te <= li->te) {///co-linear - assert(li->tn == lj->tn && li->rev == lj->rev); - // fprintf(stderr, "<1>\n"); - if(lj->qs == li->qs && lj->qe == li->qe && lj->ts == li->ts && lj->te == li->te) continue; - dq = li->qe - lj->qs; dt = li->te - lj->ts; - dd = (dq>dt? dq-dt:dt-dq); - mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; - // fprintf(stderr, "+++i->%ld, j->%ld, dd->%ld, mm->%ld\n", i, j, dd, mm); - if(dd <= mm) {///pass distance checking - adjust_rev_tse(lj, ug->g->seq[lj->tn].len, &jts, &jte); - sc = get_add_cov_score(uref, jts, jte, its, ite, li->tn, &cov_i) + pop_sc(track[j]); - - if((sc > mm_sc) || (sc == mm_sc && mm_idx == -1)) { ///must be >= instead of > - mm_sc = sc, mm_idx = j; - } - // fprintf(stderr, "%ld, its:%ld, ite:%ld>, %ld, jts:%ld, jte:%ld> sc:%ld, pop_sc(track[j]):%ld, csc:%ld\n", - // i, its, ite, j, jts, jte, sc, pop_sc(track[j]), csc); - } - } - } - - // fprintf(stderr, "##(%ld) %u\t%u\t%c\tutg%.6d%c(%u)\t%u\t%u\tmm_idx:%ld\tmm_sc:%ld\n", i, li->qs, li->qe, "+-"[li->rev], - // (int32_t)(li->tn)+1, "lc"[uref->ug->u.a[li->tn].circ], uref->ug->u.a[li->tn].len, li->ts, li->te, mm_idx, mm_sc); - track[i] = push_sc_pre(mm_sc, mm_idx); - li->sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); sv[i] = *li; - } - - int64_t n_u; - for (k = ch_n-1, n_u = 0; k >= 0; --k) { - if(track[k]&((uint64_t)0x80000000)) continue; - i = k; ch[n_u]=sv[i]; sc = pop_sc(track[i]); - for (;i>=0;) { - track[i] |= ((uint64_t)0x80000000); - if(sv[i].qs < ch[n_u].qs) ch[n_u].qs = sv[i].qs; - if(sv[i].ts < ch[n_u].ts) ch[n_u].ts = sv[i].ts; - if(sv[i].qe > ch[n_u].qe) ch[n_u].qe = sv[i].qe; - if(sv[i].te > ch[n_u].te) ch[n_u].te = sv[i].te; - // ch[n_u].qn = i;//start idx of read alignment in chain - i = pop_pre(track[i]); - } - adjust_rev_tse(&(ch[n_u]), ug->g->seq[ch[n_u].tn].len, &its, &ite); - ch[n_u].ts = its; ch[n_u].te = ite; ch[n_u].sec = (sc>0x3FFFFFFF?0x3FFFFFFF:sc); - // ch[n_u].qn += chain_offset; //start idx of read alignment in chain - // ch[n_u].tn = k + chain_offset; //end idx of read alignment in chain - ch[n_u].qn = k + chain_offset; //end idx of read alignment in chain - n_u++; - } - for (i = 0; i < ch_n; ++i) { - adjust_rev_tse(&(sv[i]), ug->g->seq[sv[i].tn].len, &its, &ite); - sv[i].ts = its; sv[i].te = ite; - k = pop_pre(track[i]); sv[i].tn = k>=0?k+chain_offset:(uint32_t)-1; - } - return n_u; -} - -inline int64_t comput_linear_sc(ul_ov_t *li, ul_ov_t *lj, double diff_ec_ul, int64_t bw) -{ ///li is the suffix of lj - int64_t dq, dt, dd, mm; - if(lj->te > li->te) return INT32_MIN; - dq = li->qe - lj->qs; dt = li->te - lj->ts; - dd = (dq>dt? dq-dt:dt-dq); - mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; - if(dd > mm) return INT32_MIN; - return li->qe - li->qs; -} - -uint64_t linear_chain_dp_adv(ul_ov_t *ch, int64_t ch_n, ul_ov_t *sv, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, ma_ug_t *ug, -int64_t chain_offset) -{ ///all in[].el must be 1 - if(ch_n == 0) return 0; - int64_t /**mm_ovlp, x,**/ i, j, k, sc, csc, mm_sc, mm_idx, its, ite, max; - ul_ov_t *li = NULL, *lj = NULL; int64_t *p, *t, st, plus, max_ii, n_skip, end_j; int32_t *f; - resize_Chain_Data(dp, ch_n, NULL); - t = dp->tmp; f = dp->score; p = dp->pre; - - radix_sort_ul_ov_srt_qe(ch, ch + ch_n); - for (i = 1, j = 0; i <= ch_n; i++) { - if (i == ch_n || ch[i].qe != ch[j].qe) { - if(i - j > 1) radix_sort_ul_ov_srt_qs(ch+j, ch+i); - j = i; - } - } - - // fprintf(stderr, "[M::%s::] ch_n:%ld\n", __func__, ch_n); - memset(t, 0, (ch_n*sizeof((*t)))); - for (i = st = plus = 0, max_ii = -1; i < ch_n; ++i) { - li = &(ch[i]); csc = li->qe - li->qs; - mm_sc = csc; mm_idx = -1; n_skip = 0; end_j = -1; - st = (i= st; --j) { - lj = &(ch[j]); - sc = comput_linear_sc(li, lj, diff_ec_ul, bw); ///should allow contain - if(sc == INT32_MIN) continue; - sc += f[j]; - if(sc > mm_sc) { - mm_sc = sc, mm_idx = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - end_j = j; - if (max_ii < 0 || (ch[i].qe>(ch[max_ii].qe+max_dis))) {//too long - max = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && (ch[i].qe<=(max_dis+ch[j].qe)); --j) { - if (max < f[j]) { - max = f[j], max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - lj = &(ch[max_ii]); - sc = comput_linear_sc(li, lj, diff_ec_ul, bw); ///should allow contain - if(sc != INT32_MIN) { - sc += f[max_ii]; - if(sc > mm_sc) { - mm_sc = sc; mm_idx = max_ii; - } - } - } - - f[i] = mm_sc; p[i] = mm_idx; - if ((max_ii < 0) || ((ch[i].qe<=max_dis+ch[max_ii].qe) && (f[max_ii]sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); sv[i] = *li; - // fprintf(stderr, "##(%ld) %u\t%u\t%c\tutg%.6d%c(%u)\t%u\t%u\tmm_idx:%ld\tmm_sc:%ld\n", i, li->qs, li->qe, "+-"[li->rev], - // (int32_t)(li->tn)+1, "lc"[uref->ug->u.a[li->tn].circ], uref->ug->u.a[li->tn].len, li->ts, li->te, mm_idx, mm_sc); - // track[i] = push_sc_pre(mm_sc, mm_idx); - // li->sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); sv[i] = *li; - } - - for (i = 0; i < ch_n; ++i) t[i] = 0; - int64_t n_u; - for (k = ch_n-1, n_u = 0; k >= 0; --k) { - if(t[k]) continue; - i = k; ch[n_u]=sv[i]; sc = f[i]; - for (;i>=0;) { - if(sv[i].qs < ch[n_u].qs) ch[n_u].qs = sv[i].qs; - if(sv[i].ts < ch[n_u].ts) ch[n_u].ts = sv[i].ts; - if(sv[i].qe > ch[n_u].qe) ch[n_u].qe = sv[i].qe; - if(sv[i].te > ch[n_u].te) ch[n_u].te = sv[i].te; - // ch[n_u].qn = i;//start idx of read alignment in chain - t[i] = 1; i = p[i]; - } - adjust_rev_tse(&(ch[n_u]), ug->g->seq[ch[n_u].tn].len, &its, &ite); - ch[n_u].ts = its; ch[n_u].te = ite; ch[n_u].sec = (sc>0x3FFFFFFF?0x3FFFFFFF:sc); - // ch[n_u].qn += chain_offset; //start idx of read alignment in chain - // ch[n_u].tn = k + chain_offset; //end idx of read alignment in chain - ch[n_u].qn = k + chain_offset; //end idx of read alignment in chain - n_u++; - } - for (i = 0; i < ch_n; ++i) { - adjust_rev_tse(&(sv[i]), ug->g->seq[sv[i].tn].len, &its, &ite); - sv[i].ts = its; sv[i].te = ite; - k = p[i]; sv[i].tn = k>=0?k+chain_offset:(uint32_t)-1; - } - return n_u; -} - -void gen_linear_chains(kv_ul_ov_t *res, kv_ul_ov_t *buf, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, Chain_Data* dp) -{ - uint64_t k, l, z, an, m; - radix_sort_ul_ov_srt_tn(res->a, res->a + res->n); - ///after this function, res keeps unitig alignment, while buf keeps read alignments - kv_resize(ul_ov_t, *buf, res->n); buf->n = res->n; - for (k = 1, l = m = 0; k <= res->n; k++) { - if(k == res->n || res->a[k].tn != res->a[l].tn) {///qn <- (tn|rev) - // kv_resize(uint64_t, bufg->srt.a, k-l); - // kv_resize(uint64_t, *bufs, k-l); - for (z = l; z < k; z++) res->a[z].tn>>=1; - // fprintf(stderr, "\n*[M::%s::] %c\tutg%.6d%c(%u)\tocc:[%lu, %lu)\n", __func__, "+-"[res->a[l].rev], (int32_t)(res->a[l].tn)+1, - // "lc"[uref->ug->u.a[res->a[l].tn].circ], uref->ug->u.a[res->a[l].tn].len, l, k); - an = l + linear_chain_dp_adv(res->a+l, k-l, buf->a+l, uref, uopt, bw, diff_ec_ul, qlen, - UG_SKIP_N, UG_ITER_N, UG_DIS_N, dp, uref->ug, l); - for (z = l; z < an; z++) res->a[m++] = res->a[z]; - // fprintf(stderr, "#occ:[%lu, %lu)\n", l, an); - l = k; - } - } - res->n = m; -} - - -void gen_linear_chains_backup(kv_ul_ov_t *res, kv_ul_ov_t *buf, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, int64_t max_skip, glchain_t *bufg, st_mt_t *bufs) -{ - uint64_t k, l, z, an, m; - radix_sort_ul_ov_srt_tn(res->a, res->a + res->n); - kv_resize(ul_ov_t, *buf, res->n); buf->n = res->n; - for (k = 1, l = m = 0; k <= res->n; k++) { - if(k == res->n || res->a[k].tn != res->a[l].tn) {///qn <- (tn|rev) - kv_resize(uint64_t, bufg->srt.a, k-l); - kv_resize(uint64_t, *bufs, k-l); - for (z = l; z < k; z++) res->a[z].tn>>=1; - // fprintf(stderr, "\n*[M::%s::] %c\tutg%.6d%c(%u)\tocc:[%lu, %lu)\n", __func__, "+-"[res->a[l].rev], (int32_t)(res->a[l].tn)+1, - // "lc"[uref->ug->u.a[res->a[l].tn].circ], uref->ug->u.a[res->a[l].tn].len, l, k); - an = l + linear_chain_dp(res->a+l, k-l, buf->a+l, uref, uopt, bw, diff_ec_ul, qlen, max_skip, bufg->srt.a.a, bufs->a, uref->ug, l); - for (z = l; z < an; z++) res->a[m++] = res->a[z]; - // fprintf(stderr, "#occ:[%lu, %lu)\n", l, an); - l = k; - } - } - res->n = m; -} - -void gen_end_coord(ul_ov_t *z, int64_t qlen, int64_t tlen, int64_t *r_qs, int64_t *r_qe, int64_t *r_ts, int64_t *r_te) -{ - int64_t qs, qe, ts, te, qtail, ttail; - qs = z->qs; qe = z->qe; ts = z->ts; te = z->te; - if(z->rev) { - ts = tlen - z->te; te = tlen - z->ts; - } - - if(qs <= ts) { - ts -= qs; qs = 0; - } else { - qs -= ts; ts = 0; - } - - qtail = qlen - qe; ttail = tlen - te; - if(qtail <= ttail) { - qe = qlen; te += qtail; - } - else { - te = tlen; qe += ttail; - } - - if(r_qs) (*r_qs) = qs; if(r_qe) (*r_qe) = qe; - if(r_ts) (*r_ts) = ts; if(r_te) (*r_te) = te; - if(z->rev) { - if(r_ts) (*r_ts) = tlen - te; - if(r_te) (*r_te) = tlen - ts; - } -} - -uint32_t is_end_check(uint32_t v, ul_ov_t *z, asg_t *g) -{ - if(v&1) { - if(z->ts==0) return 1; - } else { - if(z->te==g->seq[v>>1].len) return 1; - } - - return 0; -} - -int64_t simple_g_chain_dp(kv_ul_ov_t *in, ul_ov_t *buf, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, int64_t max_skip, uint64_t *srt, uint64_t *idx, uint64_t *track) -{ - if(in->n == 0) return 0; - uint32_t ai_v, aj_v, rev_n; ma_ug_t *ug = uref->ug; - int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, qo, share, in_n = in->n; - int64_t iqs, iqe, its, ite, i_end, j_end; - ul_ov_t *ai, *aj, *e_ai, *e_aj, rev_t; - for (i = 0; i < in_n; i++) { - gen_end_coord(&(in->a[i]), qlen, ug->u.a[in->a[i].tn].len, NULL, &iqe, NULL, NULL); - srt[i] = iqe; srt[i] <<= 32; srt[i] |= (uint64_t)i; - } - radix_sort_gfa64(srt, srt+in_n); - for (i = 0; i < in_n; i++) buf[i] = in->a[(uint32_t)srt[i]]; - memcpy(in->a, buf, in_n *sizeof((*buf)));///all alignments have been sorted by the real end-qe - - for (i = 0; i < in_n; ++i) { - ai = &(in->a[i]); ai_v = (ai->tn<<1)|ai->rev; e_ai = &(buf[i]); i_end = 0; - gen_end_coord(ai, qlen, ug->u.a[ai->tn].len, &iqs, &iqe, &its, &ite); - e_ai->qs = iqs; e_ai->qe = iqe; e_ai->ts = its; e_ai->te = ite; - mm_ovlp = max_ovlp(uref->ug->g, ai_v^1); - x = (e_ai->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += e_ai->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(i, buf, x+G_CHAIN_INDEL); - i_end = is_end_check(ai_v^1, ai, uref->ug->g); - csc = mm_sc = e_ai->sec; mm_idx = -1; - for (j = x; j >= 0; --j) { // collect potential destination vertices - aj = &(in->a[j]); aj_v = (aj->tn<<1)|aj->rev; e_aj = &(buf[i]); j_end = 0; - if(e_aj->qe+G_CHAIN_INDEL <= e_ai->qs) break;//even this pair has a overlap, its length will be very small; just ignore - if(e_aj->qs >= e_ai->qs+G_CHAIN_INDEL) continue; // lj is contained in li on the query coordinate; 128 for indel offset - qo = infer_rovlp(e_ai, e_aj, NULL, NULL, NULL, ug); ///overlap length in query (UL read) - if(ai_v != aj_v && get_ecov_adv(uref, uopt, ai_v^1, aj_v^1, bw, diff_ec_ul, qo, 0, &share)) { - sc = csc + pop_sc(track[j]); j_end = is_end_check(aj_v, aj, uref->ug->g); - if(i_end && j_end) sc -= (share>=csc?csc:share); - if(sc > mm_sc) mm_sc = sc, mm_idx = j; - } - } - track[i] = push_sc_pre(mm_sc, mm_idx); - srt[i] = track[i]>>32; srt[i] <<= 32; srt[i] |= i; - } - - int64_t n_v, n_u, n_v0; - radix_sort_gfa64(srt, srt+in_n); - for (k = in_n-1, n_v = n_u = 0; k >= 0; --k) { - n_v0 = n_v; - for (i = (uint32_t)srt[k]; i >= 0 && (track[i]&((uint64_t)0x80000000)) == 0;){ - buf[n_v] = in->a[i]; - gen_end_coord(&(buf[n_v]), qlen, ug->u.a[buf[n_v].tn].len, &iqs, &iqe, &its, &ite); - buf[n_v].qs = iqs; buf[n_v].qe = iqe; buf[n_v].ts = its; buf[n_v].te = ite; - - track[i] |= ((uint64_t)0x80000000); - i = pop_pre(track[i]); - n_v++; - } - if(n_v0 == n_v) continue; - sc = (i<0?(pop_sc(srt[k])):(pop_sc(srt[k])-pop_sc(track[i]))); - idx[n_u++] = ((uint64_t)sc<<32)|(n_v-n_v0); - } - - for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { - n_v0 = n_v; n_v += (uint32_t)idx[k]; - in->a[k].qn = idx[k]>>32;//score - in->a[k].ts = n_v0; in->a[k].te = n_v;///idx - - rev_n = ((uint32_t)idx[k])>>1; - ///we need to consider contained reads; so determining qs is not such easy - in->a[k].qs = (uint32_t)-1; in->a[k].qe = buf[n_v0].qe; - for (i = 0; i < rev_n; i++) { - rev_t = buf[n_v0+i]; buf[n_v0+i] = buf[n_v-i-1]; buf[n_v-i-1] = rev_t; - - if(in->a[k].qs > buf[n_v0+i].qs) in->a[k].qs = buf[n_v0+i].qs; - if(in->a[k].qs > buf[n_v-i-1].qs) in->a[k].qs = buf[n_v-i-1].qs; - } - if(((uint32_t)idx[k])&1) { - if(in->a[k].qs > buf[n_v0+i].qs) in->a[k].qs = buf[n_v0+i].qs; - } - // fprintf(stderr, "[M::%s] k:%ld, qs:%u, qe:%u, chain_occ:%u, chain_score:%u\n", __func__, k, - // res->a[k].qs, res->a[k].qe, res->a[k].te - res->a[k].ts, res->a[k].qn); - } - - in->n = n_u; - radix_sort_ul_ov_srt_qn(in->a, in->a + in->n);//sort by score - return n_v; -} - -/** -uint32_t uov2rov(const ul_idx_t *uref, ul_ov_t *r_al, ul_ov_t *ul_al, ul_ov_t *res) -{ - int64_t y_s, y_e, y_bs, y_be, x_s, x_e, q_s, q_e, s_shift, e_shift; - y_s = MAX(r_al->ts, ul_al->ts); y_e = MIN(r_al->te, ul_al->te); - if(y_s > y_e) return 0; - res->tn = r_al->qn; res->ts = y_s; res->te = y_e; res->el = 1; res->rev = r_al->rev; res->sec = 0; - s_shift = get_offset_adjust(y_s-r_al->ts, r_al->te-r_al->ts, r_al->qe-r_al->qs); - e_shift = get_offset_adjust(r_al->te-y_e, r_al->te-r_al->ts, r_al->qe-r_al->qs); - if(r_al->rev) { - y_s = s_shift; s_shift = e_shift; e_shift = y_s; - } - res->qn = 0; res->qs = r_al->qs+s_shift; res->qe = r_al->qe-e_shift; - return 1; -} - - -void ug2rg_gen(ul_ov_t *a, int64_t an, ul_vec_t *qn, const ul_idx_t *uref, ul_vec_t *rch) -{ - ul_ov_t *ot, p, res; uint64_t i, l, m; - ma_utg_t *u; uc_block_t *b; int64_t z, ff, iqs, iqe, its, ite; - - - for (z = 0; z < an; z++) { - gen_end_coord(&(a[z]), rch->rlen, uref->ug->u.a[a[z].tn].len, &iqs, &iqe, NULL, NULL); - o = &(a[z]); u = &(uref->ug->u.a[o->tn]); - for (i = l = 0; i < u->n; i++) { - p.tn = o->tn; p.rev = (u->a[i]>>32)&1; p.qn = u->a[i]>>33;///tn is unitig, qn is HiFi read - p.qs = 0; p.qe = Get_READ_LENGTH(R_INF, (u->a[i]>>33)); - p.ts = l; p.te = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); - l += (uint32_t)u->a[i]; - if(p.te <= o->ts) continue; - if(p.ts >= o->te) break; - ff = uov2rov(uref, &p, o, &res); - assert(ff); - if(ff) { - kv_pushp(uc_block_t, rch->bb, &b); - b->hid = res.tn; b->rev = res.rev; b->base = 0; b->el = res.el; - b->pchain = 1; b->qs = res.qs; b->qe = res.qe; b->ts = res.ts; b->te = res.te; - } - } - } -} -**/ - - - -void extend_end_coord(mg_lchain_t *li, ul_ov_t *ui, const int64_t qlen, const int64_t rlen, int64_t *r_qs, int64_t *r_qe, int64_t *r_rs, int64_t *r_re) -{ - int64_t qs = 0, qe = 0, rs = 0, re = 0, rev = 0, qtail = 0, rtail = 0; - if(li) { - qs = li->qs; qe = li->qe; rs = li->rs; re = li->re; rev = li->v&1; - if(rev) { - rs = rlen - li->re; re = rlen - li->rs; - } - } - if(ui) { - qs = ui->qs; qe = ui->qe; rs = ui->ts; re = ui->te; rev = ui->rev; - if(rev) { - rs = rlen - ui->te; re = rlen - ui->ts; - } - } - - - - if(qs <= rs) { - rs -= qs; qs = 0; - } else { - qs -= rs; rs = 0; - } - - qtail = qlen - qe; rtail = rlen - re; - if(qtail <= rtail) { - qe = qlen; re += qtail; - } - else { - re = rlen; qe += rtail; - } - - if(r_qs) (*r_qs) = qs; if(r_qe) (*r_qe) = qe; - if(r_rs) (*r_rs) = rs; if(r_re) (*r_re) = re; - if(rev) { - if(r_rs) (*r_rs) = rlen - re; - if(r_re) (*r_re) = rlen - rs; - } -} - -void dump_linear_chain(ma_ug_t *ug, kv_ul_ov_t *lidx, vec_mg_lchain_t *res, int64_t qlen, int64_t ulid) -{ - uint64_t i; int64_t iqs, iqe, its, ite; mg_lchain_t *p; - kv_resize(mg_lchain_t, *res, lidx->n); - for (i = 0, res->n = 0; i < lidx->n; i++) { - kv_pushp(mg_lchain_t, *res, &p); memset(p, 0, sizeof((*p))); - // res->a[k].v = (autom->a[lidx->a[k].tn].tn<<1)|lidx->a[k].rev; - p->v = (lidx->a[i].tn<<1)|(lidx->a[i].rev); - ///.off -> idx of original chain; cnt -> score of the chain - p->off = i; p->score = lidx->a[i].sec; - p->qs = lidx->a[i].qs; p->qe = lidx->a[i].qe; - p->rs = lidx->a[i].ts; p->re = lidx->a[i].te; - // if(ulid == 123) { - // fprintf(stderr, "+[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tqlen::%ld\tt::[%d, %d)\ttlen::%u\tsc::%d\n", __func__, - // (int32_t)(p->v>>1)+1, "+-"[p->v&1], p->qs, p->qe, qlen, - // p->rs, p->re, ug->g->seq[p->v>>1].len, p->score); - // } - extend_end_coord(p, NULL, qlen, ug->g->seq[p->v>>1].len, &iqs, &iqe, &its, &ite); - p->qs = iqs; p->qe = iqe; p->rs = its; p->re = ite; - // if(!ugl_cover_check(p->rs, p->re, &(ug->u.a[p->v>>1]))) res->n--; - // fprintf(stderr, "chain_id:%d\t%u\t%u\t%c\tutg%.6dl(%u)\t%u\t%u\n", - // res->a[k].off, res->a[k].qs, res->a[k].qe, "+-"[res->a[k].v&1], (int32_t)(res->a[k].v>>1)+1, - // g->seq[res->a[k].v>>1].len, res->a[k].rs, res->a[k].re); - // if(ulid == 14714) { - // fprintf(stderr, "-[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\n", __func__, - // (int32_t)(p->v>>1)+1, "+-"[p->v&1], p->qs, p->qe, p->rs, p->re); - // } - } -} - -void set_trans_arr(uint64_t *trans, vec_sp_node_t *out, int64_t idx) -{ - int64_t i; - for (i = idx; i >=0; ) { - // if(out->a[idx]->v == 65) { - // fprintf(stderr, "+[M::%s::] out->a[%ld]->v:%u\n", __func__, i, out->a[i]->v); - // } - trans[i]++; - i = out->a[i]->pre; - } -} - -int64_t select_mul_way_nodes(mg_pathv_t *a, int64_t a_n, vec_sp_node_t *out, float len_dif, int32_t m_pathn, uint64_t *flag) -{ - int64_t i, k, pd, kd, occ, tt = 0; uint32_t pp; mg_pathv_t *p = NULL; - if(a_n > 1) radix_sort_mg_pathv_t_d_srt(a, a + a_n); - for (i = 0; i < a_n; i++) { - p = &(a[i]); pp = (p->d<<1)>>1; pd = out->a[p->pre]->di>>32; occ = 1; - - if(p->d&0x80000000) break; - for (k = 0; k < a_n; k++) { - if(k == i) continue; ///same alignment - if(((a[k].d<<1)>>1) == pp) continue; //same path - if(a[k].v!=p->v) continue; - kd = out->a[a[k].pre]->di>>32; - if(kd >= (pd*(1-len_dif)) && kd <= (pd*(1+len_dif))) occ++; - } - if(occ >= m_pathn) { - flag[p->pre] = 1; tt++; - } - } - - return tt; -} - -int32_t phase_mul_ways(vec_mg_pathv_t *res, st_mt_t *dst_done, vec_sp_node_t *out, int32_t n_dst, mg_path_dst_t *dst, int32_t max_k, float len_dif) -{ - int64_t i, j, z, zl, n = 0, n_mpath, kk_p, od, res_n = res->n, pid; mg_pathv_t *h; - dst_done->n = 0; kv_resize(uint64_t, *dst_done, out->n); - uint64_t *trans = dst_done->a; memset(dst_done->a, 0, out->n*sizeof(*(dst_done->a))); - - n_mpath = 0; - for (i = 0; i < n_dst; ++i) { // mark dst vertices with a target distance - mg_path_dst_t *t = &dst[i]; - if (t->n_path > 0 && t->target_dist >= 0 && t->path_end >= 0){ - assert((int32_t)(out->a[t->path_end]->di>>32) == t->target_dist); - if(t->n_path >= max_k) { - t->n_path = 0; - for (z = zl = t->path_end; z >= 0;) { - zl = z; - z = out->a[z]->pre; - } - n += 2; trans[t->path_end] = trans[zl] = 1; - } else { - kk_p = 0; - for (j = t->path_end; j < (int32_t)out->n; j++) { - od = out->a[j]->di>>32; - if(od >= (t->target_dist*(1-len_dif)) && - od <= (t->target_dist*(1+len_dif))) { - if(out->a[j]->v == t->v) kk_p++; - } else { - break; - } - } - for (j = t->path_end-1; j >=0; j--) { - od = out->a[j]->di>>32; - if(od >= (t->target_dist*(1-len_dif)) && - od <= (t->target_dist*(1+len_dif))) { - if(out->a[j]->v == t->v) kk_p++; - } else { - break; - } - } - assert(kk_p > 0 && kk_p <= t->n_path); - n_mpath += kk_p; - } - } - } - - // if(detect_mul_way && src == 74) { - // fprintf(stderr, "+[M::%s::] src:%u, dst:%u, n_mpath:%d\n", __func__, src, dst[0].v, n_mpath); - // } - - if(n_mpath > 1) { - for (i = 0, pid = 0; i < n_dst; ++i) { // mark dst vertices with a target distance - mg_path_dst_t *t = &dst[i]; - if (t->n_path > 0 && t->target_dist >= 0 && t->path_end >= 0){ - assert((int32_t)(out->a[t->path_end]->di>>32) == t->target_dist); - assert(t->n_path < max_k); - for (j = t->path_end; j < (int32_t)out->n; j++) { - od = out->a[j]->di>>32; - if(od >= (t->target_dist*(1-len_dif)) && - od <= (t->target_dist*(1+len_dif))) { - if(out->a[j]->v == t->v) { - for (z = j; z >= 0;) { - kv_pushp(mg_pathv_t, *res, &h); - h->v = out->a[z]->v; h->pre = z; - h->d = pid; if(j!=t->path_end) h->d |= 0x80000000; - z = out->a[z]->pre; - } - pid++; - } - } else { - break; - } - } - for (j = t->path_end-1; j >=0; j--) { - od = out->a[j]->di>>32; - if(od >= (t->target_dist*(1-len_dif)) && - od <= (t->target_dist*(1+len_dif))) { - if(out->a[j]->v == t->v) { - for (z = j; z >= 0;) { - kv_pushp(mg_pathv_t, *res, &h); - h->v = out->a[z]->v; h->pre = z; - h->d = pid; if(j!=t->path_end) h->d |= 0x80000000; - z = out->a[z]->pre; - } - pid++; - } - } else { - break; - } - } - } - } - - radix_sort_mg_pathv_t_v_srt(res->a + res_n, res->a + res->n); - for (i = res_n+1, j = res_n/**, n = 0**/; i <= (int64_t)res->n; ++i) { - if (i == (int64_t)res->n || res->a[i].v != res->a[j].v) { - n += select_mul_way_nodes(res->a + j, i - j, out, len_dif, n_mpath, trans); - j = i; - } - } - - res->n = res_n; - } - - - if(n > 0) {//found some nodes - for (i = n = 0; (uint32_t)i < out->n; ++i) { // generate coordinate translations - if (trans[i]) { - trans[i] = n++; - } else { - trans[i] = (uint32_t)-1; - } - } - - kv_resize(mg_pathv_t, *res, res->n + n); //res->n += n; - for (i = 0; (uint32_t)i < out->n; ++i) { // generate the backtrack array - mg_pathv_t *p; - if (trans[i] == (uint32_t)-1) continue; - p = &res->a[trans[i]+res->n]; - p->v = out->a[i]->v, p->d = out->a[i]->di >> 32; - if(out->a[i]->pre < 0) { - p->pre = out->a[i]->pre; - } else { - if(trans[out->a[i]->pre] == (uint32_t)-1) p->pre = -2; - else p->pre = trans[out->a[i]->pre]; - } - } - - res->n += n; - for (i = 0; i < n_dst; ++i) // translate "path_end" - if (dst[i].path_end >= 0) - dst[i].path_end = trans[dst[i].path_end]; - } - - return n_mpath; -} - - -///max_dist is like the overlap length in string graph -///first_src_ban do not allow co-linear chain at the same node -void hc_shortest_k(void *km0, const asg_t *g, uint32_t src, int32_t n_dst, mg_path_dst_t *dst, int32_t max_dist, int32_t max_k, -st_mt_t *dst_done, uint64_t *dst_group, vec_sp_node_t *out, vec_mg_pathv_t *res, uint64_t first_src_ban, -uint64_t detect_mul_way, float len_dif) -{ - sp_node_t *p, *root = 0; - sp_topk_t *q; - khash_t(sp) *h;/// - khash_t(sp2) *h2;///alignment->vertice index - void *km; - khint_t k; - int absent; - int32_t i, j, n_done, n_found; - uint32_t id; - - // if (res) res->n = 0;///for us, n_pathv = NULL - if (n_dst <= 0) return;///n_dst: how many candidate vertices - for (i = 0; i < n_dst; ++i) { // initialize - mg_path_dst_t *t = &dst[i]; - ///if src and dest are at the same ref id, there are already one path - if (t->inner)///if two chains are at the same ref id - t->dist = 0, t->n_path = 1, t->path_end = -1; - else - t->dist = -1, t->n_path = 0, t->path_end = -1; - } - if (max_k > MG_MAX_SHORT_K) max_k = MG_MAX_SHORT_K; - km = km_init2(km0, 0x4000); - - // multiple dst[] may have the same dst[].v. We need to group them first. - // in other words, one ref id may have multiple dst alignment chains - dst_done->n = 0; kv_resize(uint64_t, *dst_done, (uint64_t)n_dst); - for (i = 0; i < n_dst; ++i) { - dst_group[i] = ((((uint64_t)dst[i].v)<<32)|((uint64_t)i)); - dst_done->a[i] = 0; - } - - radix_sort_gfa64(dst_group, dst_group + n_dst); - - h2 = kh_init2(sp2, km); // (h2+dst_group) keeps all destinations from the same ref id - kh_resize(sp2, h2, n_dst * 2); - ///please note that one contig in ref may have multiple alignment chains - ///so h2 is a index that helps us to query it - ///key(h2) = ref id; value(h2) = start_idx | occ - for (i = 1, j = 0; i <= n_dst; ++i) { - if (i == n_dst || dst_group[i]>>32 != dst_group[j]>>32) { - k = kh_put(sp2, h2, dst_group[j]>>32, &absent); - kh_val(h2, k) = (((uint64_t)j)<<32)|((uint64_t)(i-j)); - assert(absent); - j = i; - } - } - - h = kh_init2(sp, km); // h keeps visited vertices; path to each visited vertice - kh_resize(sp, h, 16); - - out->n = 0; kv_resize(sp_node_t*, *out, 16); ///16 is just the initial size - id = 0; - p = gen_sp_node(km, src, 0, id++);///just malloc a node for src; the distance is 0 - p->hash = __ac_Wang_hash(src);///hash is path hash, instead of node hash - kavl_insert(sp, &root, p, 0);///should be avl tree; p is a node at avl-tree - - ///each cell in the hash table corresponds to one node in the graph - ///each cell in the AVL tree is a path, corresponds to node in the graph - k = kh_put(sp, h, src, &absent); - q = &kh_val(h, k); - ///for normal graph traversal, one node just has one parental node; here each node has at most 16 parental nodes - q->k = 1, q->p[0] = p, q->mlen = 0, q->qs = q->qe = -1; - - n_done = 0; first_src_ban = first_src_ban?0:1; - ///the key of avl tree: #define sp_node_cmp(a, b) (((a)->di > (b)->di) - ((a)->di < (b)->di)) - ///the higher bits of (*)->di is distance to src node - ///so the key of avl tree is distance - ///in avl tree , one node might be saved multipe times - while (kavl_size(head, root) > 0) {///thr first root is src - int32_t i, nv; - asg_arc_t *av; - sp_node_t *r; - ///note that one node in the graph (sp_node_t->v) might be visited multiple times if there are circles - ///so there might be multipe cells in the avl-tree with the same (sp_node_t->v) - ///delete the first cell - r = kavl_erase_first(sp, &root); // take out the closest vertex in the heap (as a binary tree) - //fprintf(stderr, "XX\t%d\t%d\t%d\t%c%s[%d]\t%d\n", n_out, kavl_size(head, root), n_finished, "><"[(r->v&1)^1], g->seg[r->v>>1].name, r->v, (int32_t)(r->di>>32)); - - ///higher 32 bits might be the distance to root node - // lower 32 bits now for position in the out[] array - ///r->pre keep the pre-node in the path; follow the pre it is able to recover the whole path - r->di = ((r->di>>32)<<32)|((uint64_t)out->n); ///n_out is just the id in out - ///so one node id in graph might be saved multiple times in avl tree and out[] - kv_push(sp_node_t*, *out, r); - - ///r->v is the dst vertex id - ///sometimes k==kh_end(h2). Some nodes are found by graph travesal but not in linear chain alignment - k = kh_get(sp2, h2, r->v); - // we have reached one dst vertex - // note that one dst vertex may have multipe alignment chains - // we can visit some nodes in graph which are not reachable during chaining - // h2 is used to determine if one node is reachable or not - // if(src == 2844) { - // fprintf(stderr, "******src->%u, dst->%u, max_dist->%d\n", src, r->v, max_dist); - // } - if (k != kh_end(h2) && first_src_ban) { - ///node r->v might be visited multiple times - int32_t j, dist = r->di>>32, off = kh_val(h2, k) >> 32, cnt = (int32_t)kh_val(h2, k); - // if(src == 2844) { - // fprintf(stderr, "----src->%u, dst->%u, max_dist->%d, cnt->%d\n", src, r->v, max_dist, cnt); - // } - //src can reach ref id r->v; there might be not only one alignment chain in r->v - //so we need to scan all of them - for (j = 0; j < cnt; ++j) { - mg_path_dst_t *t = &dst[(int32_t)dst_group[off + j]];///t is a linear alignment at r->v - int32_t done = 0; - // if((src>>1) == 51) { - // fprintf(stderr, "###src->%u, dst->%u, max_dist->%d, dist:%d\n", src, r->v, max_dist, dist); - // } - ///the src and dest are at the same ref id, say we directly find the shortest path - if (t->inner) { - done = 1; - } else { - int32_t mlen = 0, copy = 0; - ///in the first round, we just check reachability without sequence - ///so h_seeds = NULL; we can assume mlen = 0 - /** //path - mlen = h_seeds? path_mlen(out, n_out - 1, h, t->qlen) : 0; - **/ - // means this alignment has never been visited before; keep it anyway - // note here is the alignment, instead of node - - // if(src == 2844) { - // fprintf(stderr, ">>src->%u, dst->%u, target_dist->%d, dist->%d, max_dist->%d\n", - // src, r->v, t->target_dist, dist, max_dist); - // } - if (t->n_path == 0) { - copy = 1; - // we have a target distance; choose the closest; - // there is already several paths reaching the linear alignment - } else if (t->target_dist >= 0) { - // we found the target path; hash is the path hash including multiple nodes, instead of node hash - if (dist == t->target_dist && t->check_hash && r->hash == t->target_hash) { - copy = 1, done = 1; - } else { - int32_t d0 = t->dist, d1 = dist; - d0 = d0 > t->target_dist? d0 - t->target_dist : t->target_dist - d0; - d1 = d1 > t->target_dist? d1 - t->target_dist : t->target_dist - d1; - ///if the new distance (d1) is smaller than the old distance (d0), update the results - ///the length of new path should be closer to t->target_dist - if (d1 - mlen/2 < d0 - t->mlen/2) copy = 1; - } - } - if (copy) { - t->path_end = out->n-1, t->dist = dist, t->hash = r->hash, t->mlen = mlen, t->is_0 = r->is_0; - if (t->target_dist >= 0) { - ///src is from li from li to lj, so the dis is generally increased; dijkstra algorithm - ///target_dist should be the distance on query - if (dist == t->target_dist && t->check_hash && r->hash == t->target_hash) { - done = 1; - } else if ((dist > t->target_dist + MG_SHORT_K_EXT) && (dist > (t->target_dist>>4)) && - (dist > (t->target_dist*1.25))) { - done = 1; - } - } - } - ++t->n_path;///we found a path to the alignment t - if (t->n_path >= max_k) done = 1; - } - if (detect_mul_way == 0 && dst_done->a[off + j] == 0 && done) - dst_done->a[off + j] = 1, ++n_done; - } - ///if all alignments have been settle down - ///pre-end; accelerate the loop - if (n_done == n_dst) break; - } - first_src_ban = 1; - ///below is used to push new nodes to avl tree for iteration - nv = asg_arc_n(g, r->v); - av = asg_arc_a(g, r->v); - for (i = 0; i < nv; ++i) { // visit all neighbors - asg_arc_t *ai = &av[i]; - ///v_lv is the (dest_length - overlap_length); it is a normal path length in string graph - ///ai->v_lv is the path length from r->v to ai->w - ///(r->di>>32) - int32_t d = (r->di>>32) + (uint32_t)ai->ul; - if (d > max_dist) continue; // don't probe vertices too far away - // h keeps visited vertices; path to each visited vertice - ///ai->w is the dest ref id; we insert a new ref id, instead of an alignment chain - k = kh_put(sp, h, ai->v, &absent);///one node might be visited multiple times - q = &kh_val(h, k); - if (absent) { // a new vertex visited - ///q->k: number of walks from src to ai->w - q->k = 0, q->qs = q->qe = -1; q->mlen = 0; - ///h_seeds = NULL; so q->mlen = 0 - /** //path - q->mlen = h_seeds && d + gfa_arc_lw(g, *ai) <= max_dist? node_mlen(km, g, ai->w, &mini, h_seeds, n_seeds, seeds, &q->qs, &q->qe) : 0; - **/ - //if (ql && qs) fprintf(stderr, "ql=%d,src=%d\tv=%c%s[%d],n_seeds=%d,mlen=%d\n", ql, src, "><"[ai->w&1], g->seg[ai->w>>1].name, ai->w, n_seeds, q->mlen); - } - ///if there are less than walks from src to ai->w, directly add - ///if there are more, keep the smallest walks - if (q->k < max_k) { // enough room: add to the heap - p = gen_sp_node(km, ai->v, d, id++); - p->pre = out->n - 1;///the parent node of this one - p->hash = r->hash + __ac_Wang_hash(ai->v); - p->is_0 = r->is_0; - /** //path - if (ai->rank > 0) p->is_0 = 0; - **/ - kavl_insert(sp, &root, p, 0); - q->p[q->k++] = p; - ks_heapup_sp(q->k, q->p);///adjust heap by distance - } else if ((int32_t)(q->p[0]->di>>32) > d) { // shorter than the longest path so far: replace the longest - p = kavl_erase(sp, &root, q->p[0], 0); - if (p) { - p->di = (uint64_t)d<<32 | (id++); - p->pre = out->n - 1; - p->hash = r->hash + __ac_Wang_hash(ai->v); - p->is_0 = r->is_0; - /** //path - if (ai->rank > 0) p->is_0 = 0; - **/ - kavl_insert(sp, &root, p, 0); - ks_heapdown_sp(0, q->k, q->p); - } else { - fprintf(stderr, "Warning: logical bug in gfa_shortest_k(): q->k=%d,q->p[0]->{d,i}={%d,%d},d=%d,src=%u,max_dist=%d,n_dst=%d\n", q->k, (int32_t)(q->p[0]->di>>32), (int32_t)q->p[0]->di, d, src, max_dist, n_dst); - km_destroy(km); - return; - } - } // else: the path is longer than all the existing paths ended at ai->w - } - } - kh_destroy(sp, h); - // NB: AVL nodes are not deallocated. When km==0, they are memory leaks. - - for (i = 0, n_found = 0; i < n_dst; ++i) - if (dst[i].n_path > 0) ++n_found;///n_path might be larger than 16 - ///we can assume n_pathv = NULL for now - if (n_found > 0 && res) { // then generate the backtrack array - int32_t n, n_mpath = 1; dst_done->n = 0; kv_resize(uint64_t, *dst_done, out->n); - uint64_t *trans = dst_done->a; memset(dst_done->a, 0, out->n*sizeof(*(dst_done->a))); - - if(detect_mul_way) { - n_mpath = phase_mul_ways(res, dst_done, out, n_dst, dst, max_k, len_dif); - } - - if(n_mpath == 1) { - // KCALLOC(km, trans, n_out); // used to squeeze unused elements in out[] - ///n_out: how many times that nodes in graph have been visited - ///note one node might be visited multiples times - ///n_dst: number of alignment chains - for (i = 0; i < n_dst; ++i) { // mark dst vertices with a target distance - mg_path_dst_t *t = &dst[i]; - if (t->n_path > 0 && t->target_dist >= 0 && t->path_end >= 0) - trans[(uint32_t)out->a[t->path_end]->di] = 1;///(int32_t)out[]->di: traverse track corresponds to the alignment chain dst[] - } - // for (i = 0; (uint32_t)i < out->n; ++i) { // mark dst vertices without a target distance - // k = kh_get(sp2, h2, out->a[i]->v); - // if (k != kh_end(h2)) { // TODO: check if this is correct! - // int32_t off = kh_val(h2, k)>>32, cnt = (int32_t)kh_val(h2, k); - // for (j = off; j < off + cnt; ++j) - // if (dst[j].target_dist < 0) - // trans[i] = 1; - // } - // } - for (i = (int32_t)(out->n) - 1; i >= 0; --i) // mark all predecessors - if (trans[i] && out->a[i]->pre >= 0) - trans[out->a[i]->pre] = 1; - for (i = n = 0; (uint32_t)i < out->n; ++i) // generate coordinate translations - if (trans[i]) trans[i] = n++; - else trans[i] = (uint32_t)-1; - - kv_resize(mg_pathv_t, *res, res->n + n); //res->n += n; - for (i = 0; (uint32_t)i < out->n; ++i) { // generate the backtrack array - mg_pathv_t *p; - if (trans[i] == (uint32_t)-1) continue; - p = &res->a[trans[i]+res->n]; - p->v = out->a[i]->v, p->d = out->a[i]->di >> 32; - p->pre = out->a[i]->pre < 0? out->a[i]->pre:trans[out->a[i]->pre]; - } - res->n += n; - for (i = 0; i < n_dst; ++i) // translate "path_end" - if (dst[i].path_end >= 0) - dst[i].path_end = trans[dst[i].path_end]; - } - } - - km_destroy(km); -} - -///p[]: id of last -///f[]: the score ending at i, not always the peak -///v[]: keeps the peak score up to i; -///t[]: used for buffer -///min_cnt = 2; min_sc = 30; extra_u = 0 -///u = mg_chain_backtrack(n, f, p, v, t, min_cnt, min_sc, 0, &n_u, &n_v); -int64_t hc_chain_backtrack(int64_t n, const int64_t *f, const uint64_t *p, uint64_t *srt, uint64_t *u, uint64_t *v, -int64_t *n_u_, int64_t *n_v_) -{ - if(n_u_) *n_u_ = 0; if(n_v_) *n_v_ = 0; - int64_t i, k, n_v, n_srt, n_v0, n_u, sc; - if (n == 0) return 0; - // v[] keeps the peak score up to i; f[] is the score ending at i, not always the peak - *n_u_ = *n_v_ = 0; - for (i = 0, k = 0; i < n; ++i) { - if(f[i] >= 0) { - srt[k] = (uint64_t)f[i]; srt[k] <<= 32; srt[k] |= (((uint64_t)i)<<1); k++; - } - } - n_srt = k; - radix_sort_gfa64(srt, srt + n_srt); ///sort by score - - ///from the largest to the smallest - for (k = n_srt-1, n_v = n_u = 0; k >= 0; --k) { // precompute n_u - n_v0 = n_v; - for (i = ((uint32_t)srt[k])>>1; i >= 0 && (srt[i]&1) == 0; i = (p[i]==(uint64_t)-1?-1:p[i])) { - v[n_v++] = i; srt[i] |= 1; - } - if(n_v <= n_v0) continue; - sc = i < 0? srt[k]>>32: (int64_t)(srt[k]>>32)-f[i]; - u[n_u++] = (((uint64_t)sc)<<32) | ((uint64_t)(n_v-n_v0)); - } - - if(n_u_) *n_u_ = n_u; if(n_v_) *n_v_ = n_v; - return n_u; -} - -uint64_t ck_hq_chain(mg_lchain_t *li, mg_lchain_t *lj, ma_ug_t *ug, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double ng_diff_thre) -{ - if(lj->qe+G_CHAIN_INDEL <= li->qs) return 0; - if(lj->qs >= li->qs/**+G_CHAIN_INDEL**/) return 0; - ul_ov_t ui, uj; int64_t qo, share -; set_ul_ov_t_by_mg_lchain_t(&ui, li); set_ul_ov_t_by_mg_lchain_t(&uj, lj); - qo = infer_rovlp(&ui, &uj, NULL, NULL, NULL, ug); ///overlap length in query (UL read) - if(li->v!=lj->v && get_ecov_adv(uref, uopt, li->v^1, lj->v^1, bw, ng_diff_thre, qo, 0, &share)) { - return 1; - } - return 0; -} - -int64_t hc_gchain1_dp(void *km, const ul_idx_t *uref, const ma_ug_t *ug, vec_mg_lchain_t *lc, vec_mg_lchain_t *sw, vec_mg_path_dst_t *dst, vec_sp_node_t *out, vec_mg_pathv_t *path, -int64_t qlen, const ug_opt_t *uopt, int64_t bw, double diff_thre, double ng_diff_thre, uint64_t *srt, st_mt_t *bf, int64_t *f, uint64_t *p, uint64_t *v) -{ - bf->n = 0; - if(lc->n == 0) return 0; - int64_t i, j, lc_n = lc->n, n_ext, mm_ovlp, target_dist, max_target_dist, x, m_idx, m_sc, qo, sc; - int64_t max_f, max_j = -1, max_d = -1, max_inner = 0, share; uint32_t max_hash = 0; int64_t k, k0, n_u, n_v, ni; - mg_lchain_t *r, *li, *lj; mg_path_dst_t *q; asg_t *g = ug->g; uint64_t isolated, *u; ul_ov_t ui, uj; - for (i = n_ext = 0; i < lc_n; i++) { - r = &lc->a[i]; r->dist_pre = -1; isolated = 0;///dist_pre -> parent in graph chain - if((r->re < g->seq[r->v>>1].len) && (r->rs > 0)) isolated = 1;///UL contained in one vertice - if (!isolated) ++n_ext; - srt[i] = r->qe; srt[i] <<= 32; srt[i] |= (uint64_t)i; srt[i] |= (isolated<<63); - } - radix_sort_gfa64(srt, srt+lc_n); - for (i = 1, j = 0; i <= lc_n; i++) { - if (i == lc_n || (srt[i]>>32) != (srt[j]>>32)) { - if(i - j > 1) { - for (x = j; x < i; x++) { - srt[x] <<= 32; srt[x] >>= 32; srt[x] |= ((uint64_t)lc->a[(uint32_t)srt[x]].qs)<<32; - } - radix_sort_gfa64(srt+j, srt+i); - } - j = i; - } - } - - kv_resize(mg_lchain_t, *sw, (uint64_t)lc_n); sw->n = lc_n; - for (i = 0; i < lc_n; i++) sw->a[i] = lc->a[(uint32_t)srt[i]]; - memcpy(lc->a, sw->a, lc_n *sizeof((*(lc->a)))); - // fprintf(stderr, "[M::%s::] n_ext:%ld, lc_n:%ld\n", __func__, n_ext, lc_n); - - if(ng_diff_thre >= 0) { - //first non-gap chain - for (i = 0; i < n_ext; ++i) { // core loop - li = &lc->a[i]; set_ul_ov_t_by_mg_lchain_t(&ui, li); - mm_ovlp = max_ovlp(g, li->v^1); - x = (li->qs + mm_ovlp)*diff_thre; if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_mg_lchain_max(i, lc->a, x+G_CHAIN_INDEL); - // fprintf(stderr, "\nli->(%ld)\tutg%.6d%c(%u)\tqs:%u\tqe:%u\t%c\trs:%u\tre:%u\tsrc:%u\tscore:%d, x:%ld\n", - // i, (int32_t)(li->v>>1)+1, "lc"[ug->u.a[li->v>>1].circ], ug->u.a[li->v>>1].len, - // li->qs, li->qe, "+-"[li->v&1], li->rs, li->re, li->v^1, li->score, x); - max_f = li->score, max_j = -1; - // collect potential destination vertices - for (j = x; j >= 0; --j) { - lj = &lc->a[j]; ///extend_end_coord(lj, qlen, g->seq[lj->v>>1].len, &jqs, &jqe, &jrs, &jre); - //even this pair has a overlap, its length will be very small; just ignore; only for non-gapped chains - if(lj->qe+G_CHAIN_INDEL <= li->qs) break; - if(lj->qs >= li->qs/**+G_CHAIN_INDEL**/) continue; - set_ul_ov_t_by_mg_lchain_t(&uj, lj); - qo = infer_rovlp(&ui, &uj, NULL, NULL, NULL, (ma_ug_t *)ug); ///overlap length in query (UL read) - if(li->v!=lj->v && get_ecov_adv(uref, uopt, li->v^1, lj->v^1, bw, ng_diff_thre, qo, 0, &share)) { - sc = li->score + f[j]; - if(sc > max_f) { - max_f = sc; max_j = j; - } - } - } - - f[i] = max_f, p[i] = max_j<0?(uint64_t)-1:max_j; - li->dist_pre = max_j<0?-1:g_adjacent_dis(g, li->v^1, lc->a[max_j].v^1); li->inner_pre = 0; - li->hash_pre = max_j<0?0:(__ac_Wang_hash((li->v^1))+__ac_Wang_hash((lc->a[max_j].v^1))); - // fprintf(stderr, "i->%ld, utg%.6d%c->utg%.6d%c, max_f:%ld\n", i, (int32_t)(li->v>>1)+1, "lc"[ug->u.a[li->v>>1].circ], - // max_j<0?0:(int32_t)(lc->a[max_j].v>>1)+1, max_j<0?'*':"lc"[ug->u.a[lc->a[max_j].v>>1].circ], max_f); - } - - kv_resize(uint64_t, *bf, (uint64_t)lc_n); u = bf->a; - hc_chain_backtrack(n_ext, f, p, srt, u, v, &n_u, &n_v); - for (i = 0; i < lc_n - n_ext; ++i) { - u[n_u++] = (((uint64_t)lc->a[n_ext + i].score)<<32) | 1; - v[n_v++] = n_ext + i; - } - - sw->n = 0; kv_resize(mg_lchain_t, *sw, (uint64_t)n_v); m_idx = m_sc = -1; bf->n = 0; - for (i = 0, k = 0; i < n_u; ++i) { - k0 = k, ni = (int32_t)u[i]; - for (j = 0; j < ni; ++j) { - sw->a[k++] = lc->a[v[k0 + (ni - j - 1)]]; - } - if(m_idx < 0 || m_sc < ((int64_t)(u[i]>>32))) { - m_idx = i; m_sc = ((int64_t)(u[i]>>32)); - } - } - assert(k == n_v); bf->n = n_u; - - if(primary_chain_check(u, n_u, sw->a)) { - memcpy(lc->a, sw->a, n_v*sizeof(mg_lchain_t)); - return m_idx; - } - } - bf->n = 0; - - ///then gapped-chaining - for (i = 0; i < n_ext; ++i) { // core loop - li = &lc->a[i]; - mm_ovlp = max_ovlp(g, li->v^1); - x = (li->qs + mm_ovlp)*diff_thre; if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_mg_lchain_max(i, lc->a, x+G_CHAIN_INDEL); - // fprintf(stderr, "\nli->(%ld)\tutg%.6d%c(%u)\tqs:%u\tqe:%u\t%c\trs:%u\tre:%u\tsrc:%u\tscore:%d, x:%ld\n", - // i, (int32_t)(li->v>>1)+1, "lc"[ug->u.a[li->v>>1].circ], ug->u.a[li->v>>1].len, - // li->qs, li->qe, "+-"[li->v&1], li->rs, li->re, li->v^1, li->score, x); - - // collect potential destination vertices - for (dst->n = 0, max_target_dist= -1, j = x; j >= 0; --j) { - ///same time for gchain - // if((p[j]>>33) == ((uint64_t)i)) continue; - - lj = &lc->a[j]; ///extend_end_coord(lj, qlen, g->seq[lj->v>>1].len, &jqs, &jqe, &jrs, &jre); - //lj contained in li; actually in circle, this might happen; need to deal with it later - if(lj->qs >= li->qs/**+G_CHAIN_INDEL**/) continue; - ///if there is a circle, the two linear chains might be at the same vertice - target_dist = hc_target_len(g, li, lj); - // fprintf(stderr, "j:%ld, target_dist:%ld\n", j, target_dist); - if(target_dist < 0) continue; - kv_pushp(mg_path_dst_t, *dst, &q); - memset(q, 0, sizeof(*q)); - q->inner = 0;//we set q->inner = 0 to allow circles - q->v = lj->v^1;///must be v^1 instead of v - q->meta = j; - ///lj->qs************lj->qe - /// li->qs************li->qe - q->qlen = li->qs - lj->qe;///might be negative; this is the region that need to be checked in base-level - q->target_dist = target_dist;///cannot understand the target_dist - q->target_hash = 0; - q->check_hash = 0; - if(max_target_dist < target_dist) max_target_dist = target_dist; - ///not sure how to use this cut-off - // if (t[j] == i) { - // if (++n_skip > max_skip) - // break; - // } - // if (p[j] >= 0) t[p[j]] = i; - // if((li->v>>1)==10 && ((lj->v>>1)==15||(lj->v>>1)==14)) max_target_dist = 100000; - // fprintf(stderr, "+++lj->(%ld)\tutg%.6d%c(%u)\t%u\t%u\t%c\ttarget_dist:%d\n", - // j, (int32_t)(lj->v>>1)+1, "lc"[ug->u.a[lj->v>>1].circ], ug->u.a[lj->v>>1].len, - // lj->qs, lj->qe, "+-"[lj->v&1], q->target_dist); - - ///j-th has pre, and the pre is good alignment - ///same time for gchain - // if((((uint32_t)p[j])!=((uint32_t)-1)) && (p[j]&(uint64_t)(0x100000000))) { - // p[((uint32_t)p[j])] &= (uint64_t)(0x1ffffffff); - // p[((uint32_t)p[j])] |= (((uint64_t)i)<<33); - // } - } - - // confirm reach-ability - max_f = li->score, max_j = -1, max_d = -1, max_inner = 0; max_hash = 0; - if(dst->n) { - max_target_dist *= (1+diff_thre); if(max_target_dist < bw) max_target_dist = bw; - hc_shortest_k(km, g, li->v^1, dst->n, dst->a, max_target_dist, MG_MAX_SHORT_K, bf, srt, out, NULL, 1, 0, 0); - // remove unreachable destinations - //TODO: check sequence identity - for (j = 0; j < (int64_t)dst->n; ++j) { - mg_path_dst_t *dj = &dst->a[j]; - if (dj->n_path == 0) continue; // unreachable - sc = cal_gchain_sc(dj, li, lc->a, f, bw, diff_thre, W_CHN_PEN_GAP); - - // fprintf(stderr, "---dj->(%ld)\tutg%.6d%c(%u)\tsc:%d\tmax_f:%ld\ttarget_dist:%d\tdj->dist:%d\n", - // j, (int32_t)(dj->v>>1)+1, "lc"[ug->u.a[dj->v>>1].circ], ug->u.a[dj->v>>1].len, sc, max_f, dj->target_dist, dj->dist); - if (sc == INT32_MIN) continue; // out of band - // fprintf(stderr, "+max_f->%d, max_j->%d\n", max_f, max_j); - if (sc < 0) continue;// negative score - // fprintf(stderr, "++max_f->%d, max_j->%d\n", max_f, max_j); - if (sc > max_f) { - max_f = sc, max_j = dj->meta, max_d = dj->dist, max_hash = dj->hash, max_inner = dj->inner; - // fprintf(stderr, "+++max_f->%d, max_j->%d\n", max_f, max_j); - } - } - } - - f[i] = max_f; p[i] = max_j<0?(uint64_t)-1:max_j; - ///same time for gchain - // if(max_j < 0) { - // p[i] = (uint32_t)-1; - // } else { - // p[i] = max_j; - // if(ck_hq_chain(li, &(lc->a[max_j]), (ma_ug_t *)ug, uref, uopt, bw, ng_diff_thre)) { - // p[i] |= (uint64_t)(0x100000000); - // } - // } - - - li->dist_pre = max_d; - li->hash_pre = max_hash; - li->inner_pre = max_inner; - // fprintf(stderr, "i->%ld, utg%.6d%c->utg%.6d%c, max_f:%ld\n", i, (int32_t)(li->v>>1)+1, "lc"[ug->u.a[li->v>>1].circ], - // max_j<0?0:(int32_t)(lc->a[max_j].v>>1)+1, max_j<0?'*':"lc"[ug->u.a[lc->a[max_j].v>>1].circ], max_f); - } - - ///same time for gchain - // for (i = 0; i < n_ext; ++i) { - // if(((uint32_t)p[i])==((uint32_t)-1)) p[i] = (uint64_t)-1; - // else p[i] = (uint32_t)p[i]; - // } - - kv_resize(uint64_t, *bf, (uint64_t)lc_n); u = bf->a; - hc_chain_backtrack(n_ext, f, p, srt, u, v, &n_u, &n_v); - for (i = 0; i < lc_n - n_ext; ++i) { - u[n_u++] = (((uint64_t)lc->a[n_ext + i].score)<<32) | 1; - v[n_v++] = n_ext + i; - } - - sw->n = 0; kv_resize(mg_lchain_t, *sw, (uint64_t)n_v); m_idx = m_sc = -1; bf->n = 0; - for (i = 0, k = 0; i < n_u; ++i) { - k0 = k, ni = (int32_t)u[i]; - for (j = 0; j < ni; ++j) { - sw->a[k++] = lc->a[v[k0 + (ni - j - 1)]]; - } - if(m_idx < 0 || m_sc < ((int64_t)(u[i]>>32))) { - m_idx = i; m_sc = ((int64_t)(u[i]>>32)); - } - } - assert(k == n_v); bf->n = n_u; - memcpy(lc->a, sw->a, n_v*sizeof(mg_lchain_t)); - return m_idx; -} - - -void debug_gchain(void *km, const asg_t *g, mg_lchain_t *a, uint64_t n, st_mt_t *dst_done, vec_sp_node_t *out) -{ - uint64_t k, i, v, w, nv; int64_t dd; asg_arc_t *av; mg_path_dst_t dst; uint64_t dst_group; - for (k = 1; k < n; k++) { - v = a[k].v^1; w = a[k-1].v^1; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (i = 0; i < nv; i++) { - if(av[i].v == w) break; - } - // if(i >= nv) { - // // fprintf(stderr, "[M::%s::]\n", __func__); - // fprintf(stderr, "[M::%s::]\tutg%.6dl(%c)\t->\tutg%.6dl(%c)\n", __func__, (int32_t)(v>>1)+1, "+-"[v&1], (int32_t)(w>>1)+1, "+-"[w&1]); - // } - if(i < nv) { - dd = (int64_t)((uint32_t)(av[i].ul)); - } else { - memset(&dst, 0, sizeof(dst)); - dst.v = w; - dst.target_dist = a[k-1].dist_pre; - dst.target_hash = 0; dst.check_hash = 0; - hc_shortest_k(km, g, v, 1, &dst, dst.target_dist, MG_MAX_SHORT_K, dst_done, &dst_group, out, NULL, 1, 0, 0); - dd = dst.dist; - } - if(a[k-1].dist_pre != dd) { - fprintf(stderr, "[M::%s::]\tutg%.6dl(%c)\t->\tutg%.6dl(%c)\tdist_pre:%d\td:%ld\n", __func__, (int32_t)(v>>1)+1, "+-"[v&1], - (int32_t)(w>>1)+1, "+-"[w&1], a[k-1].dist_pre, dd); - } - } -} - -void debug_gchain2(const asg_t *g, mg_pathv_t *a, uint64_t n) -{ - uint64_t k, i, v, w, nv; asg_arc_t *av; - for (k = 1; k < n; k++) { - v = a[k-1].v; w = a[k].v; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (i = 0; i < nv; i++) { - if(av[i].v == w) break; - } - if(i >= nv) { - // fprintf(stderr, "[M::%s::]\n", __func__); - fprintf(stderr, "[M::%s::]\tutg%.6dl(%c)\t->\tutg%.6dl(%c)\n", __func__, (int32_t)(v>>1)+1, "+-"[v&1], (int32_t)(w>>1)+1, "+-"[w&1]); - } - } -} - - -void reverse_track(mg_pathv_t *a, uint64_t a_n) -{ - int64_t k, hn = (a_n>>1); mg_pathv_t z; - for (k = a_n-1; k >= 1; k--) a[k].d -= a[k-1].d; - - for (k = 0; k < hn; k++) { - z = a[k]; a[k] = a[a_n - k - 1]; a[a_n - k - 1] = z; - a[k].v ^= 1; a[a_n - k - 1].v ^= 1; - } - if(a_n&1) a[k].v ^= 1; -} - -void dbg_print(mg_pathv_t *a, int64_t a_n) -{ - int64_t k; - for (k = 0; k < a_n; k++) { - if(a[k].pre == -2) break; - } - - if(k < a_n) { - fprintf(stderr, "+[M::%s::] src:utg%.6dl(v:%u), dst:utg%.6dl(v:%u)\n", __func__, - (int32_t)(a[0].v>>1)+1, a[0].v, (int32_t)(a[a_n-1].v>>1)+1, a[a_n-1].v); - for (k = 0; k < a_n; k++) { - fprintf(stderr, "-[M::%s::] utg%.6dl(v:%u), pre:%d, d:%u\n", __func__, (int32_t)(a[k].v>>1)+1, a[k].v, - a[k].pre, a[k].d); - } - } - -} - -uint32_t gen_gchain_track(void *km, mg_lchain_t *a, int64_t a_n, const asg_t *g, -st_mt_t *dst_done, vec_sp_node_t *out, vec_mg_pathv_t *res) -{ - int64_t k, p_n/**, trav_occ = 0**/; mg_lchain_t *l0, *l1; mg_path_dst_t dst; uint64_t dst_group; mg_pathv_t *p; - res->n = 0; kv_pushp(mg_pathv_t, *res, &p); p->v = (uint32_t)-1; p->d = 0; p->pre = 0; - for (k = 1; k < a_n; k++) { - l0 = a + k - 1; l1 = a + k; - assert(!l1->inner_pre); assert(l1->dist_pre >= 0); - memset(&dst, 0, sizeof(dst)); - dst.v = l0->v^1; - assert(l1->dist_pre >= 0); - dst.target_dist = l1->dist_pre; - dst.target_hash = l1->hash_pre; - dst.check_hash = 1; p_n = res->n; - if((dst.target_hash != (__ac_Wang_hash((l1->v^1))+__ac_Wang_hash(dst.v))) || - (g_adjacent_dis(g, l1->v^1, dst.v) != dst.target_dist)) { - hc_shortest_k(km, g, l1->v^1, 1, &dst, dst.target_dist*(1+SEC_LEN_DIF), MG_MAX_SHORT_K, dst_done, &dst_group, out, res, 1, 1, SEC_LEN_DIF); - // debug_gchain2(g, res->a + p_n, res->n - p_n); - // fprintf(stderr, "[M::%s::n->%ld]\tutg%.6dl(%c)\t->\tutg%.6dl(%c)\n", __func__, res->n - p_n, - // (int32_t)(l0->v>>1)+1, "+-"[l0->v&1], (int32_t)(l1->v>>1)+1, "+-"[l1->v&1]); - - // fprintf(stderr, "\n-[M::%s::res->n->%u::p_n->%ld] utg%.6dl(v:%u) -> utg%.6dl(v:%u)\n", - // __func__, (uint32_t)res->n, p_n, (int32_t)(l1->v>>1)+1, l1->v, (int32_t)(l0->v>>1)+1, l0->v); - // dbg_print(res->a + p_n, res->n - p_n); - assert(res->n - p_n > 1); assert(dst.target_hash == dst.hash); - res->a[p_n-1].d = res->a[res->n-1].d - res->a[res->n-2].d; res->n--; - reverse_track(res->a + p_n, res->n - p_n); res->n--;///reomve l1 from res - // trav_occ++; - } else { - res->a[p_n-1].d = dst.target_dist; - } - - kv_pushp(mg_pathv_t, *res, &p); p->v = (uint32_t)-1; p->pre = k; p->d = 0; - - } - // fprintf(stderr, "[M::%s::]\ta_n:%ld\ttrav_occ:%ld\n", __func__, a_n, trav_occ); - return res->n; -} - -void print_chain(mg_lchain_t *a, uint32_t a_n) -{ - uint32_t k; - for (k = 0; k < a_n; k++) { - if(a[k].off!=-1) { - fprintf(stderr, "%u\t%u\t%c\tutg%.6dl\t%u\t%u\n", - a[k].qs, a[k].qe, "+-"[a[k].v&1], (int32_t)(a[k].v>>1)+1, a[k].rs, a[k].re); - } else { - fprintf(stderr, "*\t*\t%c\tutg%.6dl\t*\t*\n", "+-"[a[k].v&1], (int32_t)(a[k].v>>1)+1); - } - } -} - -void update_exist_chain(const ul_idx_t *uref, ul_ov_t *ch, uint64_t *idx, int64_t idx_n, int64_t tid, int64_t bw, -double diff_ec_ul, mg_lchain_t *res) -{ - int64_t i, j, cov_i, i_qs, i_qe, i_ts, i_te, j_qs, j_qe, j_ts, j_te, dq, dt, dd, mm, sc = 0; - int64_t tlen = uref->ug->g->seq[tid].len; memset(res, 0, sizeof(*res)); - ul_ov_t *li, *lj; - if(idx_n <= 0) return; - i = idx_n - 1; - res->qs = (ch[idx[i]].qs<<1)>>1; res->qe = ch[idx[i]].qe; - res->rs = ch[idx[i]].ts; res->re = ch[idx[i]].te; - for (; i >= 0; i--) { - li = &(ch[idx[i]]); - i_qs = (li->qs<<1)>>1; i_qe = li->qe; - i_ts = (li->rev?(tlen-li->te):(li->ts)); - i_te = (li->rev?(tlen-li->ts):(li->te)); - - if((int64_t)((li->qs<<1)>>1) < res->qs) res->qs = ((li->qs<<1)>>1); - if((int64_t)li->ts < res->rs) res->rs = li->ts; - if((int64_t)li->qe > res->qe) res->qe = li->qe; - if((int64_t)li->te > res->re) res->re = li->te; - - cov_i = 0; j = i + 1; - if(j < idx_n) { - lj = &(ch[idx[j]]); - j_qs = (lj->qs<<1)>>1; j_qe = lj->qe; - j_ts = (lj->rev?(tlen-lj->te):(lj->ts)); - j_te = (lj->rev?(tlen-lj->ts):(lj->te)); - if(j_qs <= i_qs && j_qe <= i_qe && j_ts <= i_ts && j_te <= i_te) {///co-linear - assert(li->rev == lj->rev); - if(j_qs == i_qs && j_qe == i_qe && j_ts == i_ts && j_te == i_te) continue; - dq = i_qe - j_qs; dt = i_te - j_ts; - dd = (dq>dt? dq-dt:dt-dq); - mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; - if(dd <= mm) {///pass distance checking - sc += get_add_cov_score(uref, lj->ts, lj->te, li->ts, li->te, tid, &cov_i); - } - } - } else { - sc += retrieve_u_cov_region(uref, tid, 0, li->ts, li->te, &cov_i); - } - } - res->score = (sc>0x3FFFFFFF?0x3FFFFFFF:sc); -} - -void debug_ll_chains(const ul_idx_t *uref, uint64_t *ix, int64_t ix_n, int64_t p_sidx, int64_t p_eidx, mg_lchain_t *chain_a, -kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, uint64_t *b, int64_t bw, double diff_ec_ul, int64_t qlen) -{ - int64_t k, i, z, a_n, ss, ee, b_n; uint64_t qs, qe, ts, te; uint32_t mk = 0x80000000; mg_lchain_t nn; - int64_t iqs, iqe, its, ite, tsc; - - for (k = p_sidx; k < p_eidx; k++) { - i = raw_idx->a[chain_a[k].off].qn; - qs = raw_chn->a[i].qs; qe = raw_chn->a[i].qe; - ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; - // fprintf(stderr, "++++++++++++[M::%s::idx:%ld]\n", __func__, i); - for (;i>=0;) { - // fprintf(stderr, "--[M::%s::i->%ld]\n", __func__, i); - if(raw_chn->a[i].qs < qs) qs = raw_chn->a[i].qs; - if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; - if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; - if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; - raw_chn->a[i].qs |= mk; - - if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; - else i = raw_chn->a[i].tn; - } - assert(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && - raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te); - } - - - ///dedup - for (z = a_n = 0; z < ix_n; ++z) { - ss = a_n; ee = a_n + ((uint32_t)ix[z]); tsc = 0; - /**if(ss != p_sidx || ee != p_eidx)**/ { - for (k = ss; k < ee; k++) { - i = raw_idx->a[chain_a[k].off].qn; b_n = 0; - qs = ((raw_chn->a[i].qs<<1)>>1); qe = raw_chn->a[i].qe; - ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; - // fprintf(stderr, "++++++++++++[M::%s::idx:%ld]\n", __func__, i); - for (;i>=0;) { - // fprintf(stderr, "--[M::%s::i->%ld]\n", __func__, i); - if(((raw_chn->a[i].qs<<1)>>1) < qs) qs = ((raw_chn->a[i].qs<<1)>>1); - if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; - if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; - if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; - // raw_chn->a[i].qs |= mk; - //update here!!!!!!! - // if(!(raw_chn->a[i].qs&mk)) b[b_n++] = i; - b[b_n++] = i; - if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; - else i = raw_chn->a[i].tn; - } - assert(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && - raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te); - - update_exist_chain(uref, raw_chn->a, b, b_n, raw_idx->a[chain_a[k].off].tn, bw, diff_ec_ul, &nn); - nn.v = (raw_idx->a[chain_a[k].off].tn<<1)|raw_idx->a[chain_a[k].off].rev; - extend_end_coord(&nn, NULL, qlen, uref->ug->g->seq[raw_idx->a[chain_a[k].off].tn].len, - &iqs, &iqe, &its, &ite); - nn.qs = iqs; nn.qe = iqe; nn.rs = its; nn.re = ite; - if(!(chain_a[k].score == nn.score && chain_a[k].qs == nn.qs && chain_a[k].qe == nn.qe - && chain_a[k].rs == nn.rs && chain_a[k].re == nn.re)){ - fprintf(stderr, "[M::%s::] chain_a[k].score->%d, nn.score->%d\n", __func__, chain_a[k].score, nn.score); - fprintf(stderr, "[M::%s::] chain_a[k].qs->%d, nn.qs->%d, chain_a[k].qe->%d, nn.qe->%d, chain_a[k].rs->%d, nn.rs->%d, chain_a[k].re->%d, nn.re->%d\n", __func__, - chain_a[k].qs, nn.qs, chain_a[k].qe, nn.qe, chain_a[k].rs, nn.rs, chain_a[k].re, nn.re); - } - assert(chain_a[k].score == nn.score && chain_a[k].qs == nn.qs && chain_a[k].qe == nn.qe - && chain_a[k].rs == nn.rs && chain_a[k].re == nn.re); - tsc += nn.score; - } - assert(tsc >= ((int64_t)(ix[z]>>32))); - } - - a_n += ((uint32_t)ix[z]); - } - - - - for (k = p_sidx; k < p_eidx; k++) { - i = raw_idx->a[chain_a[k].off].qn; - qs = ((raw_chn->a[i].qs<<1)>>1); qe = raw_chn->a[i].qe; - ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; - for (;i>=0;) { - // fprintf(stderr, "--[M::%s::i->%ld]\n", __func__, i); - if(raw_chn->a[i].qs&mk) raw_chn->a[i].qs -= mk; - if(raw_chn->a[i].qs < qs) qs = raw_chn->a[i].qs; - if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; - if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; - if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; - - - if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; - else i = raw_chn->a[i].tn; - } - assert(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && - raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te); - } -} - -void dedup_second_chain(const ul_idx_t *uref, uint64_t *ix, int64_t ix_n, int64_t p_sidx, int64_t p_eidx, mg_lchain_t *chain_a, -kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, uint64_t *b, int64_t bw, double diff_ec_ul, int64_t qlen) -{ - int64_t k, i, z, a_n, ss, ee, b_n; uint64_t qs, qe, ts, te; uint32_t mk = 0x80000000; mg_lchain_t nn; - int64_t iqs, iqe, its, ite, tsc; - - for (k = p_sidx; k < p_eidx; k++) { - i = raw_idx->a[chain_a[k].off].qn; - qs = raw_chn->a[i].qs; qe = raw_chn->a[i].qe; - ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; - // fprintf(stderr, "++++++++++++[M::%s::idx:%ld]\n", __func__, i); - for (;i>=0;) { - // fprintf(stderr, "--[M::%s::i->%ld]\n", __func__, i); - if(raw_chn->a[i].qs < qs) qs = raw_chn->a[i].qs; - if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; - if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; - if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; - raw_chn->a[i].qs |= mk; - - if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; - else i = raw_chn->a[i].tn; - } - assert(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && - raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te); - } - - - ///dedup - for (z = a_n = 0; z < ix_n; ++z) { - ss = a_n; ee = a_n + ((uint32_t)ix[z]); tsc = 0; - if(ss != p_sidx || ee != p_eidx) { - for (k = ss; k < ee; k++) { - i = raw_idx->a[chain_a[k].off].qn; b_n = 0; - qs = ((raw_chn->a[i].qs<<1)>>1); qe = raw_chn->a[i].qe; - ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; - // fprintf(stderr, "++++++++++++[M::%s::idx:%ld]\n", __func__, i); - for (;i>=0;) { - // fprintf(stderr, "--[M::%s::i->%ld]\n", __func__, i); - if(((raw_chn->a[i].qs<<1)>>1) < qs) qs = ((raw_chn->a[i].qs<<1)>>1); - if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; - if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; - if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; - // raw_chn->a[i].qs |= mk; - //update here!!!!!!! - if(!(raw_chn->a[i].qs&mk)) b[b_n++] = i; - if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; - else i = raw_chn->a[i].tn; - } - assert(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && - raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te); - - update_exist_chain(uref, raw_chn->a, b, b_n, raw_idx->a[chain_a[k].off].tn, bw, diff_ec_ul, &nn); - nn.v = (raw_idx->a[chain_a[k].off].tn<<1)|raw_idx->a[chain_a[k].off].rev; - extend_end_coord(&nn, NULL, qlen, uref->ug->g->seq[raw_idx->a[chain_a[k].off].tn].len, &iqs, &iqe, &its, &ite); - nn.qs = iqs; nn.qe = iqe; nn.rs = its; nn.re = ite; - assert(chain_a[k].score >= nn.score); - tsc += (chain_a[k].score - nn.score); - } - } - ///TODO: also update qs, qe - tsc = ((int64_t)(ix[z]>>32)) - tsc; if(tsc < 0) tsc = 0; - ix[z] <<= 32; ix[z] >>= 32; ix[z] |= ((uint64_t)tsc)<<32; - - a_n += ((uint32_t)ix[z]); - } - - - - for (k = p_sidx; k < p_eidx; k++) { - i = raw_idx->a[chain_a[k].off].qn; - qs = ((raw_chn->a[i].qs<<1)>>1); qe = raw_chn->a[i].qe; - ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; - for (;i>=0;) { - // fprintf(stderr, "--[M::%s::i->%ld]\n", __func__, i); - if(raw_chn->a[i].qs&mk) raw_chn->a[i].qs -= mk; - if(raw_chn->a[i].qs < qs) qs = raw_chn->a[i].qs; - if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; - if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; - if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; - - - if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; - else i = raw_chn->a[i].tn; - } - assert(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && - raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te); - } -} - -uint32_t gen_max_gchain(void *km, const ul_idx_t *uref, int64_t ulid, st_mt_t *idx, vec_mg_lchain_t *e, kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, -int64_t qlen, float primary_cov_rate, float primary_fragment_cov_rate, float primary_fragment_second_score_rate, const asg_t *g, st_mt_t *dst_done, -vec_sp_node_t *out, vec_mg_pathv_t *res, uint64_t *b, int64_t bw, double diff_ec_ul) -{ - if(idx->n <= 0) return 0; - int64_t a_n, idx_n = idx->n, i, m_sc = 0, is_done = 0; uint64_t s_idx, e_idx, om, ok, ovlp, novlp; - ul_ov_t m; memset(&m, 0, sizeof(m)); m_sc = -1; mg_lchain_t *a = e->a; - for (i = a_n = 0; i < idx_n; ++i) { - if(((int64_t)(idx->a[i]>>32)) > m_sc) { - m_sc = ((int64_t)(idx->a[i]>>32)); m.qn = i; - m.ts = a_n; m.te = a_n + ((uint32_t)idx->a[i]); - m.qs = a[m.ts].qs; m.qe = a[m.te-1].qe; - } - // dedup_second_chain(NULL, 0, a_n, a_n + ((uint32_t)idx->a[i]), a, raw_idx, raw_chn); - a_n += ((uint32_t)idx->a[i]); - } - assert(a[m.ts].qs<=a[m.te-1].qs && a[m.te-1].qe>=a[m.ts].qe); - // print_chain(a + m.ts, m.te - m.ts); - ///for debug - // dedup_second_chain(uref, idx->a, idx_n, m.ts, m.te, a, raw_idx, raw_chn, b, bw, diff_ec_ul); - // debug_ll_chains(uref, idx->a, idx_n, m.ts, m.te, a, raw_idx, raw_chn, b, bw, diff_ec_ul, qlen); - - if((m.qe - m.qs) > (qlen*primary_cov_rate)) is_done = 1; - if(is_done == 0) { - // for (i = a_n = 0; i < idx_n; ++i) { - // s_idx = a[a_n].qs; a_n += ((uint32_t)idx->a[i]); e_idx = a[a_n-1].qe; - // if(i == m.qn) continue; - // if(s_idx < m.qs || e_idx < m.qs || s_idx > m.qe || e_idx > m.qe) break; - // } - // if(i >= idx_n) is_done = 2;///no alignment that is on the left or the right side of the primary chain - for (i = a_n = 0; i < idx_n; ++i) { - s_idx = a[a_n].qs; a_n += ((uint32_t)idx->a[i]); e_idx = a[a_n-1].qe; - if(i == m.qn) continue; - ovlp = ((MIN(m.qe, e_idx) > MAX(m.qs, s_idx))? (MIN(m.qe, e_idx) - MAX(m.qs, s_idx)):0); - novlp = (e_idx - s_idx) - ovlp; - if(novlp > ((m.qe-m.qs)*GC_OFFSET_RATE) && novlp > GC_OFFSET_POS) break; - } - if(i >= idx_n) is_done = 2;///no alignment that is on the left or the right side of the primary chain - } - - if(is_done == 0) { - if((m.qe - m.qs) > (qlen*primary_fragment_cov_rate)) { - dedup_second_chain(uref, idx->a, idx_n, m.ts, m.te, a, raw_idx, raw_chn, b, bw, diff_ec_ul, qlen); - - om = m.qe - m.qs; - for (i = a_n = 0; i < idx_n; ++i) { - s_idx = a[a_n].qs; a_n += ((uint32_t)idx->a[i]); e_idx = a[a_n-1].qe; - if(i == m.qn) continue; - ovlp = ((MIN(m.qe, e_idx) > MAX(m.qs, s_idx))? (MIN(m.qe, e_idx) - MAX(m.qs, s_idx)):0); - if(ovlp == 0) continue; - ok = e_idx - s_idx; - if(ok > om) ok = om; - if((ovlp > ok*0.1) && ((int64_t)(idx->a[i]>>32)) > (m_sc*primary_fragment_second_score_rate)) break; - } - if(i >= idx_n) is_done = 3; - } - } - - if(is_done && gen_gchain_track(km, a + m.ts, m.te - m.ts, g, dst_done, out, res)) {///try to find a path - for (i = m.ts, e->n = 0; i < (int64_t)m.te; i++) a[e->n++] = a[i]; - // fprintf(stderr, "--[M::%s::id->%ld] [%u, %u), res->n:%lu\n", __func__, ulid, m.qs, m.qe, (uint64_t)res->n); - kv_resize(mg_lchain_t, *e, res->n); a = e->a; - for (i = ((int64_t)res->n)-1; i >= 0; i--) { - - if(res->a[i].v == (uint32_t)-1) { - a[i] = a[res->a[i].pre]; a[i].dist_pre = res->a[i].d; - // fprintf(stderr, "ulid:%ld\t%u\t%u\t%c\tutg%.6dl\t%u\t%u\tdist_pre:%d\n", ulid, a[i].qs, a[i].qe, "+-"[a[i].v&1], (int32_t)(a[i].v>>1)+1, a[i].rs, a[i].re, a[i].dist_pre); - } - else { - a[i].v = res->a[i].v; a[i].off = -1; a[i].dist_pre = res->a[i].d; - // fprintf(stderr, "ulid:%ld\t*\t*\t%c\tutg%.6dl\t*\t*\tdist_pre:%d\n", ulid, "+-"[a[i].v&1], (int32_t)(a[i].v>>1)+1, a[i].dist_pre); - } - } - e->n = res->n; - - - - - // debug_gchain(km, g, e->a, e->n, dst_done, out); - - - return 1; - } - - return 0; -} - - -void update_exist_chain_adv(const ul_idx_t *uref, ul_ov_t *ch, uint64_t *idx, int64_t idx_n, int64_t tid, mg_lchain_t *res) -{ - int64_t i, j, cov_i, sc = 0; memset(res, 0, sizeof(*res)); - ul_ov_t *li, *lj; - if(idx_n <= 0) return; - i = 0; - res->qs = (ch[idx[i]].qs<<1)>>1; res->qe = ch[idx[i]].qe; - res->rs = ch[idx[i]].ts; res->re = ch[idx[i]].te; - for (i = 0; i < idx_n; i++) { - li = &(ch[idx[i]]); - - if((int64_t)((li->qs<<1)>>1) < res->qs) res->qs = ((li->qs<<1)>>1); - if((int64_t)li->ts < res->rs) res->rs = li->ts; - if((int64_t)li->qe > res->qe) res->qe = li->qe; - if((int64_t)li->te > res->re) res->re = li->te; - - cov_i = 0; j = i - 1; - if(j >= 0) { - lj = &(ch[idx[j]]); - sc += get_add_cov_score(uref, lj->ts, lj->te, li->ts, li->te, tid, &cov_i); - } else { - sc += retrieve_u_cov_region(uref, tid, 0, li->ts, li->te, &cov_i); - } - } - res->score = (sc>0x3FFFFFFF?0x3FFFFFFF:sc); -} - - -void dedup_second_chain_adv(const ul_idx_t *uref, ul_ov_t *gb, int64_t gb_n, mg_lchain_t *chain_a, -kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, uint64_t *b, int64_t qlen, int64_t ulid) -{ - int64_t k, i, z, ss, ee, b_n, n_s; uint64_t qs, qe, ts, te; uint32_t mk = 0x80000000/**, pi**/; mg_lchain_t nn; - int64_t iqs, iqe, its, ite, tsc; - - for (z = gb_n - 1; z >= 0; z--) {///start from the best chain - ss = gb[z].ts; ee = gb[z].te; tsc = 0; gb[z].qs = qlen; gb[z].qe = 0; - for (k = ss; k < ee; k++) { - i = raw_idx->a[chain_a[k].off].qn; b_n = 0; - qs = ((raw_chn->a[i].qs<<1)>>1); qe = raw_chn->a[i].qe; - ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; - for (n_s = 0;i>=0;) { - if(((raw_chn->a[i].qs<<1)>>1) < qs) qs = ((raw_chn->a[i].qs<<1)>>1); - if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; - if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; - if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; - - if(!(raw_chn->a[i].qs&mk)) b[b_n++] = i; - else n_s++; - - raw_chn->a[i].qs |= mk; - if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; - else i = raw_chn->a[i].tn; - } - assert(b_n > 0); - assert(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && - raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te); - // if(!(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && - // raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te)) { - // fprintf(stderr, "\n[M::%s::ulid->%ld******] raw_idx_offset:%d, qs:%lu, qe:%lu, ts:%lu, te:%lu, raw_idx->qs:%u, raw_idx->qe:%u, raw_idx->ts:%u, raw_idx->te:%u\n", - // __func__, ulid, chain_a[k].off, qs, qe, ts, te, - // raw_idx->a[chain_a[k].off].qs, raw_idx->a[chain_a[k].off].qe, - // raw_idx->a[chain_a[k].off].ts, raw_idx->a[chain_a[k].off].te); - - // for (i = raw_idx->a[chain_a[k].off].qn;i>=0;) { - // if(((raw_chn->a[i].qs<<1)>>1) < qs) qs = ((raw_chn->a[i].qs<<1)>>1); - // if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; - // if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; - // if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; - // fprintf(stderr, "[M::%s->pieces (%ld)] qs->%u, qe->%u, ts->%u, te->%u\n", __func__, i, - // ((raw_chn->a[i].qs<<1)>>1), raw_chn->a[i].qe, raw_chn->a[i].ts, raw_chn->a[i].te); - // if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; - // else i = raw_chn->a[i].tn; - // } - // } - - update_exist_chain_adv(uref, raw_chn->a, b, b_n, raw_idx->a[chain_a[k].off].tn, &nn); - nn.v = (raw_idx->a[chain_a[k].off].tn<<1)|raw_idx->a[chain_a[k].off].rev; - extend_end_coord(&nn, NULL, qlen, uref->ug->g->seq[raw_idx->a[chain_a[k].off].tn].len, &iqs, &iqe, &its, &ite); - nn.qs = iqs; nn.qe = iqe; nn.rs = its; nn.re = ite; - assert(chain_a[k].score >= nn.score); - tsc += (chain_a[k].score - nn.score); - - if(n_s) { - // raw_idx->a[chain_a[k].off].qn = b[b_n-1]; - // for (i = 0, pi = (uint32_t)-1; i < b_n; i++) { - // raw_chn->a[b[i]].tn = pi; pi = b[i]; - // } - ///don't update chain_a[k] as it will be used for taceback in the next step - chain_a[k].score = nn.score; - chain_a[k].qs = nn.qs; chain_a[k].qe = nn.qe; - chain_a[k].rs = nn.rs; chain_a[k].re = nn.re; - // raw_idx->a[chain_a[k].off].sec = nn.score; - // raw_idx->a[chain_a[k].off].qs = nn.qs; - // raw_idx->a[chain_a[k].off].qe = nn.qe; - // raw_idx->a[chain_a[k].off].ts = nn.rs; - // raw_idx->a[chain_a[k].off].te = nn.re; - } else { - // if(!(chain_a[k].score == nn.score && chain_a[k].qs == nn.qs && chain_a[k].qe == nn.qe && chain_a[k].rs == nn.rs && chain_a[k].re == nn.re)) { - // fprintf(stderr, "++++[M::%s::k->%ld] chain_a[k].score->%d, nn.score->%d, chain_a[k].qs->%d, nn.qs->%d, chain_a[k].qe->%d, nn.qe->%d, chain_a[k].rs->%d, nn.rs->%d, chain_a[k].re->%d, nn.re->%d\n", __func__, - // k, chain_a[k].score, nn.score, chain_a[k].qs, nn.qs, chain_a[k].qe, nn.qe, chain_a[k].rs, nn.rs, chain_a[k].re, nn.re); - // } - assert(chain_a[k].score == nn.score && chain_a[k].qs == nn.qs && chain_a[k].qe == nn.qe && chain_a[k].rs == nn.rs && chain_a[k].re == nn.re); - } - - if((int32_t)gb[z].qs > nn.qs) gb[z].qs = nn.qs;///update qs and qe - if((int32_t)gb[z].qe < nn.qe) gb[z].qe = nn.qe; - } - tsc = (int64_t)(gb[z].qn) - tsc; if(tsc < 0) tsc = 0; gb[z].qn = tsc;///update score - // if(gb[z].qe <= gb[z].qs) { - // fprintf(stderr, "++++[M::%s::] gb[%ld].qe->%u, gb[%ld].qs->%u\n", __func__, z, gb[z].qe, z, gb[z].qs); - // } - assert(gb[z].qe > gb[z].qs); - // fprintf(stderr, "[M::%s::z->%ld] score->%u, qs->%u, qe->%u, occ->%u\n", - // __func__, z, gb[z].qn, gb[z].qs, gb[z].qe, gb[z].te-gb[z].ts); - } - - for (i = 0; i < (int64_t)raw_chn->n; i++){ - if(raw_chn->a[i].qs&mk) raw_chn->a[i].qs -= mk; - } - radix_sort_ul_ov_srt_qn(gb, gb + gb_n);//sort by scores -} - -uint32_t gen_max_gchain_adv(void *km, const ul_idx_t *uref, int64_t ulid, st_mt_t *idx, vec_mg_lchain_t *e, kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, -int64_t qlen, float primary_cov_rate, float primary_fragment_cov_rate, float primary_fragment_second_score_rate, uint64_t mini_primary_fragment_len, -const asg_t *g, st_mt_t *dst_done, vec_sp_node_t *out, vec_mg_pathv_t *res, uint64_t *b, vec_mg_lchain_t *gchains) -{ - gchains->n = 0; - if(idx->n <= 0) return 0; - int64_t a_n, idx_n = idx->n, i, k, is_done = 0, n_mchain = 0; uint64_t om, ok, ovlp, novlp; - ul_ov_t *m = NULL, *p = NULL; mg_lchain_t *a = e->a, *g_item; int64_t raw_idx_n = raw_idx->n; - ul_ov_t *gb = NULL; int64_t gb_n = 0; - for (i = a_n = 0; i < idx_n; ++i) { - kv_pushp(ul_ov_t, *raw_idx, &p); - p->qn = ((int64_t)(idx->a[i]>>32));//score - p->ts = a_n; p->te = a_n + ((uint32_t)idx->a[i]); - p->qs = a[p->ts].qs; p->qe = a[p->te-1].qe; p->tn = 0;//(tn = 1) -> normal; (t = 0) -> duplicated chain - a_n += ((uint32_t)idx->a[i]); - // fprintf(stderr, "[M::%s::i->%ld] score->%u, qs->%u, qe->%u, occ->%u\n", __func__, i, p->qn, p->qs, p->qe, p->te-p->ts); - } - gb = raw_idx->a + raw_idx_n; gb_n = raw_idx->n - raw_idx_n; - radix_sort_ul_ov_srt_qn(gb, gb + gb_n);//sort by scores - m = &(gb[gb_n-1]);///max chain - // assert(a[m.ts].qs<=a[m.te-1].qs && a[m.te-1].qe>=a[m.ts].qe); - // print_chain(a + m.ts, m.te - m.ts); - ///for debug - // dedup_second_chain(uref, idx->a, idx_n, m.ts, m.te, a, raw_idx, raw_chn, b, bw, diff_ec_ul); - // debug_ll_chains(uref, idx->a, idx_n, m.ts, m.te, a, raw_idx, raw_chn, b, bw, diff_ec_ul, qlen); - - if((m->qe - m->qs) > (qlen*primary_cov_rate)) { - is_done = 1; m->tn = 1; n_mchain = 1; - } - - if(is_done == 0) { - for (i = gb_n - 2; i >= 0; i--) {///from the second best chain - p = &(gb[i]); - ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); - novlp = (p->qe - p->qs) - ovlp; - if(novlp > ((m->qe-m->qs)*GC_OFFSET_RATE) && novlp > GC_OFFSET_POS) break; - } - if(i < 0) { ///no alignment that is on the left or the right side of the primary chain - is_done = 2; m->tn = 1; n_mchain = 1; - } - } - - if(is_done == 0) { - if(((m->qe - m->qs) > (qlen*primary_fragment_cov_rate)) || ((m->qe - m->qs) > mini_primary_fragment_len)) { - // dedup_second_chain(uref, idx->a, idx_n, m.ts, m.te, a, raw_idx, raw_chn, b, bw, diff_ec_ul, qlen); - if(raw_chn && raw_idx) dedup_second_chain_adv(uref, gb, gb_n, a, raw_idx, raw_chn, b, qlen, ulid); - for (k = gb_n-1, n_mchain = 0; k >= 0; k--) { - m = &(gb[k]);///max chain - // fprintf(stderr, "++[M::%s::k->%ld] score->%u, qs->%u, qe->%u\n", __func__, k, m->qn, m->qs, m->qe); - if(((m->qe - m->qs) <= (qlen*primary_fragment_cov_rate)) && - ((m->qe - m->qs) <= mini_primary_fragment_len)) break; - om = m->qe - m->qs; - for (i = gb_n-1; i >= 0; i--) { - if(i == k) continue; - p = &(gb[i]); - // fprintf(stderr, "--[M::%s::i->%ld] score->%u, qs->%u, qe->%u\n", __func__, i, p->qn, p->qs, p->qe); - ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); - if(ovlp == 0) continue; - ok = p->qe - p->qs; - if(p->tn == 1 && ((ovlp > ok*0.1) || (ovlp > om*0.1))) break; - if(ok > om) ok = om; - if((ovlp > ok*0.1) && (p->qn > (m->qn*primary_fragment_second_score_rate))) break; - } - if(i < 0) { - is_done = 3; m->tn = 1; n_mchain++; - } else { - break; - } - } - } - } - - if(is_done) { - gchains->n = 0; - for (k = gb_n - n_mchain; k < gb_n; k++) { - kv_pushp(mg_lchain_t, *gchains, &g_item); - g_item->v = (uint32_t)-1; - g_item->qs = gb[k].qs; g_item->qe = gb[k].qe; - g_item->rs = gb[k].ts; g_item->re = gb[k].te; - g_item->cnt = g_item->off = 0; - gen_gchain_track(km, a + g_item->rs, g_item->re - g_item->rs, g, dst_done, out, res); - kv_resize(mg_lchain_t, *gchains, gchains->n + res->n); ///a = gchains->a + gchains->n; - for (i = 0, g_item = &(gchains->a[gchains->n-1]); i < ((int64_t)res->n); i++) { - if(res->a[i].v == (uint32_t)-1) { - gchains->a[i+gchains->n] = a[res->a[i].pre + g_item->rs]; - gchains->a[i+gchains->n].dist_pre = res->a[i].d; - - // fprintf(stderr, "+[M::%s::]\tutg%.6dl(%c)\n", __func__, - // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1]); - } else { - gchains->a[i+gchains->n].v = res->a[i].v; - gchains->a[i+gchains->n].off = -1; - gchains->a[i+gchains->n].dist_pre = res->a[i].d; - ///the nodes detected by the graph chaining should be fully covered - gchains->a[i+gchains->n].rs = 0; - gchains->a[i+gchains->n].re = uref->ug->g->seq[res->a[i].v>>1].len; - // fprintf(stderr, "aaaaaaa, ulid->%ld\n", ulid); - // fprintf(stderr, "-[M::%s::]\tutg%.6dl(%c)\n", __func__, - // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1]); - } - } - g_item->cnt = res->n; - gchains->n += res->n; - // fprintf(stderr, "sbsbsbsb, ulid->%ld\n", ulid); - // debug_gchain(km, g, gchains->a + gchains->n - res->n, res->n, dst_done, out); - } - } - raw_idx->n = raw_idx_n; - return n_mchain; -} - -int64_t extract_rovlp_by_ug(utg_ct_t *p, mg_lchain_t* o, vec_mg_lchain_t *chains, int64_t tOff) -{ - int64_t rs, re; - rs = MAX((int32_t)p->s, o->rs); re = MIN((int32_t)p->e, o->re); - if(rs > re) return 0; - mg_lchain_t *x = NULL; - kv_pushp(mg_lchain_t, *chains, &x); memset(x, 0, sizeof(*x)); - x->v = (p->x>>1)<<1; x->v += (((o->v&1) == (p->x&1))?0:1); x->rs = rs; x->re = re; x->off = tOff; - x->hash_pre = (uint32_t)-1; x->dist_pre = -1; x->qs = x->qe = -1; - return 1; -} - - - - -void update_existing_anchors(const asg_t *rg, ul_vec_t *rch, ma_ug_t *ug, ma_utg_t *u, vec_mg_lchain_t *res, int64_t res_n0, -mg_lchain_t *uo, kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn) -{ - int64_t z = -1, m = res->n-1, midx, mdif, ovlp, novlp, mbeg, left[2], right[2]; - uint64_t zv; - if(uo->off >= 0) z = raw_idx->a[uo->off].qn;///if there are some base-level alignments - - for (; z >= 0;) { - zv = ((rch->bb.a[raw_chn->a[z].qn].hid<<1)+rch->bb.a[raw_chn->a[z].qn].rev); - if(!(rg->seq[zv>>1].del)) { - for (midx = mdif = -1, mbeg = m; m >= res_n0; m--) { - if(zv==res->a[m].v) { - if(((int32_t)raw_chn->a[z].ts == res->a[m].rs && (int32_t)raw_chn->a[z].te == res->a[m].re)) { - midx = m; mdif = 0; - break; - } else { - ovlp = ((MIN((int32_t)raw_chn->a[z].te, res->a[m].re) > MAX((int32_t)raw_chn->a[z].ts, res->a[m].rs))? - (MIN((int32_t)raw_chn->a[z].te, res->a[m].re) - MAX((int32_t)raw_chn->a[z].ts, res->a[m].rs)):0); - novlp = (raw_chn->a[z].te - raw_chn->a[z].ts - ovlp) + (res->a[m].re - res->a[m].rs - ovlp); - if(midx==-1 || mdif>novlp) { - midx = m; mdif = novlp; - } - } - } - } - if(mdif != 0) { - for (m = res->n-1; m > mbeg; m--) { - if(zv == res->a[m].v) { - if(((int32_t)raw_chn->a[z].ts == res->a[m].rs && (int32_t)raw_chn->a[z].te == res->a[m].re)) { - midx = m; mdif = 0; - break; - } else { - ovlp = ((MIN((int32_t)raw_chn->a[z].te, res->a[m].re) > MAX((int32_t)raw_chn->a[z].ts, res->a[m].rs))? - (MIN((int32_t)raw_chn->a[z].te, res->a[m].re) - MAX((int32_t)raw_chn->a[z].ts, res->a[m].rs)):0); - novlp = (raw_chn->a[z].te - raw_chn->a[z].ts - ovlp) + (res->a[m].re - res->a[m].rs - ovlp); - if(midx==-1 || mdif>novlp) { - midx = m; mdif = novlp; - } - } - } - } - } - m = midx; - // if(m < 0) fprintf(stderr, ">>>>>>[M::%s::] z->%ld\n", __func__, z); - assert(m >= res_n0); - res->a[m].qs = raw_chn->a[z].qs; res->a[m].qe = raw_chn->a[z].qe; - res->a[m].dist_pre = raw_chn->a[z].qn;///the idx of this chain at rch - // fprintf(stderr, "%c, res_n0->%ld, m->%ld, raw_idx->%u, qs->%d, qe->%d, ts->%d, te->%d, mdif->%ld\n", - // "+-"[(uo->v&1)], res_n0, m, raw_chn->a[z].qn, raw_chn->a[z].qs, raw_chn->a[z].qe, raw_chn->a[z].ts, raw_chn->a[z].te, mdif); - - - - left[0] = left[1] = -1; right[0] = right[1] = u->len+1; - if(m > 0) get_r_offset(ug, &(res->a[m-1]), &left[0], &left[1], NULL, NULL); - if(m + 1 < (int64_t)res->n) get_r_offset(ug, &(res->a[m+1]), &right[0], &right[1], NULL, NULL); - - // if(!(uo->v&1)) {///forward - // if(m > 0) { - // left[0] = a[m-1].rs; left[1] = a[m-1].re; - // } - // if(m + 1 < (int64_t)a_n) { - // right[0] = a[m+1].rs; right[1] = a[m+1].re; - // } - // } else {//reverse - // if(m > 0) { - // right[0] = a[m-1].rs; right[1] = a[m-1].re; - // } - // if(m + 1 < (int64_t)a_n) { - // left[0] = a[m+1].rs; left[1] = a[m+1].re; - // } - // } - ///otherwise a[m] is not co-linear with a[m-1] and a[m+1] - if(raw_chn->a[z].ts>=left[0]&&raw_chn->a[z].ts<=right[0] - &&raw_chn->a[z].te>=left[1]&&raw_chn->a[z].te<=right[1]) { - res->a[m].rs = raw_chn->a[z].ts; res->a[m].re = raw_chn->a[z].te; - } - } - if(raw_chn->a[z].tn == (uint32_t)-1) z = -1; - else z = raw_chn->a[z].tn; - } -} - -void gl_ug2rg_gen(const asg_t *rg, ul_vec_t *rch, ma_ug_t *ug, mg_lchain_t *uo, vec_mg_lchain_t *res, int64_t tOff, -int64_t ulid, kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn) -{ - // fprintf(stderr, "\n[M::%s::] uo->qs:%d, uo->qe:%d\n", __func__, uo->qs, uo->qe); - ///uo is a unitig alignment - ma_utg_t *u = &(ug->u.a[uo->v>>1]); int64_t res_n0 = res->n; - uint64_t rs = uo->rs, re = uo->re, i, l; utg_ct_t p; - - for (i = l = 0; i < u->n; i++) { - p.x = u->a[i]>>32; p.s = l; p.e = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); - l += (uint32_t)u->a[i]; - if(p.e <= rs) continue; - if(p.s >= re) break; - - assert(extract_rovlp_by_ug(&p, uo, res, tOff)); - // if(!extract_rovlp_by_ug(&p, uo, res, tOff)) { - // fprintf(stderr, "[M::%s::ulid::%ld]u_rs->%lu, u_re->%lu, p.s->%u, p.e->%u\n", __func__, ulid, rs, re, p.s, p.e); - // exit(1); - // } - res->a[res->n-1].score = uo->v; res->a[res->n-1].cnt = i; - // fprintf(stderr, "[M::%s::]u_rs->%lu, u_re->%lu, p.s->%u, p.e->%u\n", __func__, rs, re, p.s, p.e); - - // int64_t read_rs, read_re, read_qs, read_qe; - // get_r_offset(ug, &(res->a[res->n-1]), &read_rs, &read_re, &read_qs, &read_qe); - // fprintf(stderr, "\t\t\t(k->%u) r_rs->%ld, r_re->%ld, r_qs->%ld, r_qe->%ld\n", (uint32_t)res->n-1, read_rs, read_re, read_qs, read_qe); - ///for res->a[res->n-1] - ///ts and te are the coordinates in unitig (res->a[res->n-1].score>>1), instead of HiFi read (res->a[res->n-1].v>>1) - ///qs and qe are the coordinates in UL, - } - - mg_lchain_t *a = res->a + res_n0, t; uint64_t a_n = res->n - res_n0; - if(uo->v&1) { - for (i = 0; i < (a_n>>1); i++) { - t = a[i]; a[i] = a[a_n-i-1]; a[a_n-i-1] = t; - } - } - - update_existing_anchors(rg, rch, ug, u, res, res_n0, uo, raw_idx, raw_chn); -} - -void update_rovlp_chain_qse_back(ma_ug_t *ug, int64_t sidx, int64_t eidx, mg_lchain_t *a, int64_t a_n) -{ - if(eidx - sidx <= 1) return; - assert(sidx>=0||eidx= 0 - if(sidx >= 0) { - get_r_offset(ug, &(a[sidx]), &left_r[0], &left_r[1], &left_q[0], &left_q[1]); - } else { - get_r_offset(ug, &(a[0]), &left_r[0], &left_r[1], &left_q[0], &left_q[1]); - } - - if(eidx < a_n) { - get_r_offset(ug, &(a[eidx]), &right_r[0], &right_r[1], &right_q[0], &right_q[1]); - } else { - get_r_offset(ug, &(a[a_n-1]), &right_r[0], &right_r[1], &right_q[0], &right_q[1]); - } - assert((left_q[0] >= 0 && left_q[1] >= 0) || (right_q[0] >= 0 && right_q[1] >= 0)); ///assert(re >= rs); - // fprintf(stderr, "##[M::%s::] right_q[0]:%ld, right_q[1]:%ld, left_q[0]:%ld, left_q[1]:%ld\n", - // __func__, right_q[0], right_q[1], left_q[0], left_q[1]); - // fprintf(stderr, "##[M::%s::] right_r[0]:%ld, right_r[1]:%ld, left_r[0]:%ld, left_r[1]:%ld\n", - // __func__, right_r[0], right_r[1], left_r[0], left_r[1]); - // if(left_q[0] >= 0 && left_q[1] >= 0 && right_q[0] >= 0 && right_q[1] >= 0) { - // rlen[0] = (right_r[0] - left_r[0]); rlen[1] = (right_r[1] - left_r[1]); - // qlen[0] = (right_q[0] - left_q[0]); qlen[1] = (right_q[1] - left_q[1]); - // for (i = sidx+1; i < eidx; i++) { - // get_r_offset(ug, &(a[i]), &rs, &re, NULL, NULL); - // a[i].qs = left_q[0] + get_offset_adjust((rs - left_r[0]), rlen[0], qlen[0]); - // a[i].qe = left_q[1] + get_offset_adjust((re - left_r[1]), rlen[1], qlen[1]); - // } - // } - - if(left_q[0] >= 0 && left_q[1] >= 0 && right_q[0] >= 0 && right_q[1] >= 0) { - // fprintf(stderr, "+++sidx:%ld+++ left_qs:%ld, left_qe:%ld, left_rs:%ld, left_re:%ld\n", - // sidx, left_q[0], left_q[1], left_r[0], left_r[1]); - // fprintf(stderr, "---eidx:%ld--- right_qs:%ld, right_qe:%ld, right_rs:%ld, right_re:%ld\n", - // eidx, right_q[0], right_q[1], right_r[0], right_r[1]); - - for (i = sidx+1; i < eidx; i++) { - get_r_offset(ug, &(a[i]), &rs, &re, NULL, NULL); - // a[i].qs = left_q[0] + get_offset_adjust((rs - left_r[0]), rlen[0], qlen[0]); - ///a[i].qs>=left_q[0] && a[i].qs>>i:%ld<<< a[i].qs:%u, a[i].qe:%u, rs:%ld, re:%ld\n", i, a[i].qs, a[i].qe, rs, re); - - left_q[0] = a[i].qs; left_q[1] = a[i].qe; - left_r[0] = rs; left_r[1] = re; - } - } - - if(right_q[0] < 0 || right_q[1] < 0) { - for (i = sidx+1; i < eidx; i++) { - get_r_offset(ug, &(a[i]), &rs, &re, NULL, NULL); - ///a[i].qs>=left_q[0] && a[i].qs=left_q[1] - a[i].qe = left_q[1] + (re - left_r[1]); - left_q[0] = a[i].qs; left_q[1] = a[i].qe; - left_r[0] = rs; left_r[1] = re; - } - } - - if(left_q[0] < 0 || left_q[1] < 0) { - for (i = eidx-1; i > sidx; i--) { - get_r_offset(ug, &(a[i]), &rs, &re, NULL, NULL); - a[i].qe = right_q[1] - get_offset_adjust(right_r[1]-re, right_r[1]-right_r[0], right_q[1]-right_q[0]); - a[i].qs = right_q[0] - (right_r[0]-rs); - right_q[0] = a[i].qs; right_q[1] = a[i].qe; - right_r[0] = rs; right_r[1] = re; - } - } - // if(left_q[0] < 0) left_q[0] = right_q[0] - (right_r[0] - left_r[0]); - // if(left_q[1] < 0) left_q[1] = right_q[1] - (right_r[1] - left_r[1]); - // if(right_q[0] < 0 || right_q[1] < 0) { - // right_q[0] = left_q[0] + (right_r[0] - left_r[0]); - // right_q[1] = left_q[1] + (right_r[1] - left_r[1]); - // } - - // fprintf(stderr, "******[M::%s::] right_q[0]:%ld, right_q[1]:%ld\n", __func__, right_q[0], right_q[1]); -} - -void update_rovlp_chain_qse(ma_ug_t *ug, int64_t sidx, int64_t eidx, mg_lchain_t *a, int64_t a_n, int64_t qlen) -{ - if(eidx - sidx <= 1) return; - assert(sidx>=0||eidx= 0 - if(sidx >= 0) { - get_r_offset(ug, &(a[sidx]), &left_r[0], &left_r[1], &left_q[0], &left_q[1]); - } else { - get_r_offset(ug, &(a[0]), &left_r[0], &left_r[1], &left_q[0], &left_q[1]); - } - - if(eidx < a_n) { - get_r_offset(ug, &(a[eidx]), &right_r[0], &right_r[1], &right_q[0], &right_q[1]); - } else { - get_r_offset(ug, &(a[a_n-1]), &right_r[0], &right_r[1], &right_q[0], &right_q[1]); - } - assert((left_q[0] >= 0 && left_q[1] >= 0) || (right_q[0] >= 0 && right_q[1] >= 0)); ///assert(re >= rs); - - if(left_q[0] >= 0 && left_q[1] >= 0 && right_q[0] >= 0 && right_q[1] >= 0) { - for (i = sidx+1; i < eidx; i++) { - get_r_offset(ug, &(a[i]), &rs, &re, NULL, NULL); - a[i].qe = cal_qext_coor(left_r[1], right_r[1], left_q[1], right_q[1], re); - assert(a[i].qe >= 0 && a[i].qe <= qlen); - a[i].qs = cal_qext_coor(left_r[0], (a[i].qe<=right_q[0])?re:right_r[0], - left_q[0], (a[i].qe<=right_q[0])?a[i].qe:right_q[0], rs); - assert(a[i].qs >= 0 && a[i].qs <= qlen); - if(a[i].qs > a[i].qe) { - tt = a[i].qs; a[i].qs = a[i].qe; a[i].qe = tt; - } - left_q[0] = a[i].qs; left_q[1] = a[i].qe; - left_r[0] = rs; left_r[1] = re; - } - } - - if(right_q[0] < 0 || right_q[1] < 0) { - for (i = sidx+1; i < eidx; i++) { - get_r_offset(ug, &(a[i]), &rs, &re, NULL, NULL); - a[i].qe = cal_qext_coor(left_r[1], re, left_q[1], left_q[1] + re - left_r[1], re); - if(a[i].qe < 0) a[i].qe = 0; if(a[i].qe > qlen) a[i].qe = qlen; - a[i].qs = cal_qext_coor(left_r[0], (a[i].qe<=left_q[1])?re:left_r[1], - left_q[0], (a[i].qe<=left_q[1])?a[i].qe:left_q[1], rs); - assert(a[i].qs >= 0 && a[i].qs <= qlen); - if(a[i].qs > a[i].qe) { - tt = a[i].qs; a[i].qs = a[i].qe; a[i].qe = tt; - } - - left_q[0] = a[i].qs; left_q[1] = a[i].qe; - left_r[0] = rs; left_r[1] = re; - } - } - - if(left_q[0] < 0 || left_q[1] < 0) { - for (i = eidx-1; i > sidx; i--) { - get_r_offset(ug, &(a[i]), &rs, &re, NULL, NULL); - // a[i].qe = right_q[1] - get_offset_adjust(right_r[1]-re, right_r[1]-right_r[0], right_q[1]-right_q[0]); - // a[i].qs = right_q[0] - (right_r[0]-rs); - a[i].qe = cal_qext_coor(right_r[0], right_r[1], right_q[0], right_q[1], re); - assert(a[i].qe >= 0 && a[i].qe <= qlen); - a[i].qs = cal_qext_coor(rs, right_r[0], right_q[0]-(right_r[0]-rs), right_q[0], rs); - if(a[i].qs < 0) a[i].qs = 0; if(a[i].qs > qlen) a[i].qs = qlen; - if(a[i].qs > a[i].qe) { - tt = a[i].qs; a[i].qs = a[i].qe; a[i].qe = tt; - } - - right_q[0] = a[i].qs; right_q[1] = a[i].qe; - right_r[0] = rs; right_r[1] = re; - } - } - // if(left_q[0] < 0) left_q[0] = right_q[0] - (right_r[0] - left_r[0]); - // if(left_q[1] < 0) left_q[1] = right_q[1] - (right_r[1] - left_r[1]); - // if(right_q[0] < 0 || right_q[1] < 0) { - // right_q[0] = left_q[0] + (right_r[0] - left_r[0]); - // right_q[1] = left_q[1] + (right_r[1] - left_r[1]); - // } - - // fprintf(stderr, "******[M::%s::] right_q[0]:%ld, right_q[1]:%ld\n", __func__, right_q[0], right_q[1]); -} - -inline int64_t flat_rovlp_chain_sc(ma_ug_t *ug, mg_lchain_t *li, mg_lchain_t *lj) -{ - int64_t iqs, iqe, its, ite, jqs, jqe, jts, jte, ovlp; - get_r_offset(ug, li, &its, &ite, &iqs, &iqe); - get_r_offset(ug, lj, &jts, &jte, &jqs, &jqe); - if(jqs <= iqs && jqe <= iqe && jts <= its && jte <= ite) { - if(jqs == iqs && jqe == iqe && jts == its && jte == ite) return INT32_MIN; - ovlp = ((MIN(jqe, iqe) > MAX(jqs, iqs))? (MIN(jqe, iqe) - MAX(jqs, iqs)):0); - return iqe - iqs - ovlp; - } - return INT32_MIN; -} - -int64_t flat_rovlp_chain(ma_ug_t *ug, mg_lchain_t *x, int64_t x_n, Chain_Data* dp, int64_t max_skip, int64_t max_iter, int64_t max_dis) -{ - if(x_n <= 0) return 0; - int32_t *p, *c_n, *id; int64_t *f, *t, i, j, a_n, st, max_ii, cl; mg_lchain_t *li, *lj; - int64_t mm_sc, mm_n, mm_idx, n_skip, end_j, sc, sn, max, max_n, tot_sc = INT32_MIN, tot_n = INT32_MIN, tot_i = -1; - resize_Chain_Data(dp, x_n, NULL); - t = dp->tmp; p = dp->score; f = dp->pre; c_n = dp->occ; id = dp->indels; - for (i = a_n = 0, cl = 1; i < x_n; i++) { - if(x[i].qs >= 0) { - if(cl && a_n > 0) { - li = &(x[i]); lj = &(x[id[a_n-1]]); - sc = flat_rovlp_chain_sc(ug, li, lj); - if(sc == INT32_MIN) cl = 0; - } - id[a_n++] = i; - } - } - if(a_n <= 0) return 0; - if(cl) return a_n; - - memset(t, 0, (a_n*sizeof((*t)))); - for (i = st = 0, max_ii = -1; i < a_n; ++i) { - li = &(x[id[i]]); - mm_sc = li->qe - li->qs; mm_n = 1; mm_idx = -1; n_skip = 0; end_j = -1; - st = (i= st; --j) { - lj = &(x[id[j]]); - sc = flat_rovlp_chain_sc(ug, li, lj); - if(sc == INT32_MIN) continue; - sc += f[j]; sn = c_n[j] + 1; - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { - mm_sc = sc, mm_idx = j; mm_n = sn; - if (n_skip > 0) --n_skip; - } else if (t[j] == i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - - end_j = j; - if (max_ii < 0 || ((x[id[i]].qe) > (x[id[max_ii]].qe+max_dis))) {//too long - max = INT32_MIN; max_n = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && (x[id[i]].qe<=(max_dis+x[id[j]].qe)); --j) { - if ((max < f[j]) || ((max == f[j]) && (max_n < c_n[j]))) { - max = f[j]; max_n = c_n[j]; max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - lj = &(x[id[max_ii]]); - sc = flat_rovlp_chain_sc(ug, li, lj); - if(sc != INT32_MIN) { - sc += f[max_ii]; sn = c_n[max_ii] + 1; - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { - mm_sc = sc; mm_idx = max_ii; mm_n = sn; - } - } - } - - f[i] = mm_sc; p[i] = mm_idx; c_n[i] = mm_n; - if ((max_ii < 0) || ((x[id[i]].qe<=max_dis+x[id[max_ii]].qe) && (f[max_ii]= 0) { - id[i] = -1; i = p[i]; cl++; - // t[cl++] = i; i = p[i]; - } - - if(cl < a_n) { - for (i = 0; i < a_n; ++i) { - if(id[i] < 0) continue; - li = &(x[id[i]]); - li->dist_pre = li->qs = li->qe = -1; - } - } - return cl; -} - -void gen_rovlp_chain_by_ul(const asg_t *rg, ul_vec_t *rch, const ul_idx_t *uref, kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, mg_lchain_t *a, int64_t a_n, vec_mg_lchain_t *res, Chain_Data* dp, -int64_t dp_max_skip, int64_t dp_max_iter, int64_t dp_max_dis, int64_t ulid) -{ - if(a_n == 0) return; - int64_t k, l, res_n0 = res->n, tt = 0; ma_ug_t *ug = uref->ug; - // fprintf(stderr, "***[M::%s::a_n->%ld]\n", __func__, a_n); - ///a[0, a_n) is a gchain of untigs - for (k = 0, l = ug->g->seq[a[0].v>>1].len; k < a_n; k++) { - // fprintf(stderr, ">k->%ld, ls->%ld, le->%ld, rev->%c\n", k, l - ug->g->seq[a[k].v>>1].len, l, "+-"[a[k].v&1]); - l -= ug->g->seq[a[k].v>>1].len; - gl_ug2rg_gen(rg, rch, ug, &(a[k]), res, l, ulid, raw_idx, raw_chn); - l += ug->g->seq[a[k].v>>1].len + a[k].dist_pre; - } - mg_lchain_t *x = res->a + res_n0; int64_t x_n = res->n - res_n0, fn; - fn = flat_rovlp_chain(ug, x, x_n, dp, dp_max_skip, dp_max_iter, dp_max_dis); - // fprintf(stderr, "***[M::%s::x_n->%ld] fn::%ld\n", __func__, x_n, fn); - if(fn) { - for (l = -1, k = 0; k <= x_n; k++) { - if(k < x_n) { - if(k > 0) x[k].hash_pre = k-1+res_n0; - else x[k].hash_pre = (uint32_t)-1; - if(x[k].qs >= 0) tt++; - } - if(k == x_n || x[k].qs >=0) { ///x[k] and x[l] are anchors - if(k-l>1) { - update_rovlp_chain_qse(ug, l, k, x, x_n, rch->rlen); - // update_rovlp_chain_qse_back(ug, l, k, x, x_n); - } - l = k; - } - } - assert(tt > 0); - } else { - res->n = res_n0; - } -} - - - -int64_t convert_mg_lchain_t(utg_ct_t *p, mg_lchain_t *o) -{ - int64_t rs = p->s, re = p->e; - rs = MAX(rs, o->rs); re = MIN(re, o->re); - assert(rs < re); - if(!(p->x&1)) { - o->rs = rs-p->s; o->re = re-p->s; - } else { - o->rs = p->e-re; o->re = p->e-rs; - } - return 1; -} - -void renew_mg_lchains(ma_ug_t *ug, mg_lchain_t *a, int64_t a_n, int64_t ulid) -{ - if (a_n <= 0) return; - uint32_t rev = (a[0].score&1); ma_utg_t *u = &(ug->u.a[a[0].score>>1]); - uint64_t i, l; int64_t k; utg_ct_t p; - // fprintf(stderr, "\n[M::%s::ulid->%ld] utg%.6d%c(%c), a_n:%ld, u->n:%u\n", __func__, ulid, - // (int32_t)(a[0].score>>1)+1, "lc"[ug->u.a[(a[0].score>>1)].circ], "+-"[(a[0].score&1)], - // a_n, u->n); - // for (k = 0; k < a_n; k++, i++) { - // fprintf(stderr, "[M::%s::ulid->%ld] utg%.6d%c(%c), k:%ld, a[k].cnt:%d\n", __func__, ulid, - // (int32_t)(a[k].score>>1)+1, "lc"[ug->u.a[(a[k].score>>1)].circ], "+-"[(a[k].score&1)], k, a[k].cnt); - // } - - if(!rev) { - k = 0; - while (k < a_n) { - for (i = l = 0; i < u->n; i++) { - if(i == (uint64_t)a[k].cnt) break; - l += (uint32_t)u->a[i]; - } - assert(i < u->n); - for (; k < a_n; k++, i++) { - ///might have self-circle, so this assertion won't work - // assert(a[k].cnt == (int64_t)i && (a[k].v>>1) == (u->a[i]>>33)); - if(a[k].cnt != (int64_t)i) break; - assert((a[k].v>>1) == (u->a[i]>>33)); - p.x = u->a[i]>>32; p.s = l; p.e = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); - convert_mg_lchain_t(&p, &a[k]); - l += (uint32_t)u->a[i]; - } - } - } else { - k = a_n-1; - while(k >= 0) { - for (i = l = 0; i < u->n; i++) { - if(i == (uint64_t)a[k].cnt) break; - l += (uint32_t)u->a[i]; - } - assert(i < u->n); - for (; k >= 0; k--, i++) { - ///might have self-circle, so this assertion won't work - // assert(a[k].cnt == (int64_t)i && (a[k].v>>1) == (u->a[i]>>33)); - if(a[k].cnt != (int64_t)i) break; - assert((a[k].v>>1) == (u->a[i]>>33)); - p.x = u->a[i]>>32; p.s = l; p.e = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); - convert_mg_lchain_t(&p, &a[k]); - l += (uint32_t)u->a[i]; - } - } - } -} - - -int64_t g_adjacent_dis_mul(const asg_t *g, ma_hit_t_alloc *src, int64_t max_hang, int64_t min_ovlp, uint32_t v, uint32_t w) -{ - uint32_t i; - if(g) { - uint32_t nv; asg_arc_t *av = NULL; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (i = 0; i < nv; i++) { - if(av[i].del || av[i].v != w) continue; - return (uint32_t)av[i].ul; - } - } - - if(src) { - ma_hit_t_alloc *x = &(src[v>>1]); uint32_t qn, tn; - int32_t r; asg_arc_t e; - for (i = 0; i < x->length; i++) { - qn = Get_qn(x->buffer[i]); - tn = Get_tn(x->buffer[i]); - if(qn == (v>>1) && tn == (w>>1)) { - r = ma_hit2arc(&(x->buffer[i]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), - max_hang, asm_opt.max_hang_rate, min_ovlp, &e); - if(r < 0) continue; - if((e.ul>>32) != v || e.v != w) continue; - return (uint32_t)e.ul; - } - } - } - - return -1; -} - - -void dd_ul_vec_t(const ul_idx_t *uref, mg_lchain_t *a, int64_t a_n, ul_vec_t *rch, int64_t ulid) -{ - int64_t k, l, ovlp, novlp, tt, rs, re; uint64_t i; uc_block_t *z; mg_lchain_t *p, *c; - for (l = 0, k = 1; k <= a_n; k++) { - if(k == a_n || a[k].score != a[l].score) { ///x[k] and x[l] come from the same unitig - renew_mg_lchains(uref->ug, a + l, k - l, ulid); - l = k; - } - } - - - for (i = 0; i < rch->bb.n; i++) { - rch->bb.a[i].pidx = 0xfffffffe; - rch->bb.a[i].aidx = rch->bb.a[i].pdis = (uint32_t)-1; - } - - for (k = 0; k < a_n; k++) { - if(a[k].dist_pre >= 0) {///not a new alignment - z = &(rch->bb.a[a[k].dist_pre]); - assert(z->hid == (a[k].v>>1) && z->rev == (a[k].v&1)); - if((int64_t)z->qs == a[k].qs && (int64_t)z->qe == a[k].qe && (int64_t)z->ts == a[k].rs && (int64_t)z->te == a[k].re) { - z->pidx = k; z->pchain = 1; - } else { - ovlp = novlp = tt = 0; - ovlp = ((MIN((int64_t)z->qe, a[k].qe) > MAX((int64_t)z->qs, a[k].qs))? (MIN((int64_t)z->qe, a[k].qe)-MAX((int64_t)z->qs, a[k].qs)):0); - tt += ovlp; - novlp += (a[k].qe - a[k].qs - ovlp) + (z->qe - z->qs - ovlp); - - ovlp = ((MIN((int64_t)z->te, a[k].re) > MAX((int64_t)z->ts, a[k].rs))? (MIN((int64_t)z->te, a[k].re)-MAX((int64_t)z->ts, a[k].rs)):0); - tt += ovlp; - novlp += (a[k].re - a[k].rs - ovlp) + (z->te - z->ts - ovlp); - if(novlp > 8 || novlp > (tt*0.01)) { - kv_pushp(uc_block_t, rch->bb, &z); - z->hid = (a[k].v>>1); z->rev = (a[k].v&1); - z->pchain = 2; z->base = 0; z->el = 1; - z->qs = a[k].qs; z->qe = a[k].qe; - z->te = a[k].re; z->ts = a[k].rs; - z->pidx = k; - z->aidx = z->pdis = (uint32_t)-1; - } else { - z->qs = a[k].qs; z->qe = a[k].qe; - z->te = a[k].re; z->ts = a[k].rs; - z->pidx = k; z->pchain = 1; - } - } - } else { - kv_pushp(uc_block_t, rch->bb, &z); - z->hid = (a[k].v>>1); z->rev = (a[k].v&1); - z->pchain = 2; z->base = 0; z->el = 1; - z->qs = a[k].qs; z->qe = a[k].qe; - z->te = a[k].re; z->ts = a[k].rs; - z->pidx = k; - z->aidx = z->pdis = (uint32_t)-1; - } - } - - for (i = k = 0; i < rch->bb.n; i++) { - if(rch->bb.a[i].pidx == 0xfffffffe && (rch->bb.a[i].pchain != 1 || rch->bb.a[i].pchain != 0)) continue; - rch->bb.a[k++] = rch->bb.a[i]; - } - rch->bb.n = k; - - radix_sort_uc_block_t_qe_srt(rch->bb.a, rch->bb.a + rch->bb.n); - for (l = 0, k = 1; k <= (int64_t)rch->bb.n; k++) { - if(k == (int64_t)rch->bb.n || rch->bb.a[k].qe != rch->bb.a[l].qe) { - if(k - l > 1) radix_sort_uc_block_t_qs_srt(rch->bb.a+l, rch->bb.a+k); - for (; l < k; l++) { - if(rch->bb.a[l].pidx == 0xfffffffe) { - rch->bb.a[l].pidx = (uint32_t)-1; - } else { - a[rch->bb.a[l].pidx].dist_pre = l; - } - } - } - } - - // for (i = 0; i < rch->bb.n; i++) { - // if(rch->bb.a[i].pidx == 0xfffffffe) { - // rch->bb.a[i].pidx = (uint32_t)-1; - // } else { - // a[rch->bb.a[i].pidx].dist_pre = i; - // } - // } - // fprintf(stderr, "\n[M::%s::]\n", __func__); - for (i = 0, k = -1; i < rch->bb.n; i++) { - if(rch->bb.a[i].pidx == (uint32_t)-1) continue; - if(k < 0) k = i;///in case there is only one UL-to-HiFi alignment - if(a[rch->bb.a[i].pidx].hash_pre == (uint32_t)-1) { - rch->bb.a[i].pidx = (uint32_t)-1; - continue; - } - c = &(a[rch->bb.a[i].pidx]); p = &(a[a[rch->bb.a[i].pidx].hash_pre]); - rch->bb.a[i].pidx = a[a[rch->bb.a[i].pidx].hash_pre].dist_pre; - rch->bb.a[rch->bb.a[i].pidx].aidx = i; - tt = g_adjacent_dis_mul(uref->r_ug->rg, NULL, -1, -1, - ((rch->bb.a[i].hid<<1)|((uint32_t)rch->bb.a[i].rev))^1, - ((rch->bb.a[rch->bb.a[i].pidx].hid<<1)|((uint32_t)rch->bb.a[rch->bb.a[i].pidx].rev))^1); - if(tt >= 0) { - rch->bb.a[i].pdis = tt; - // get_r_offset(uref->ug, p, NULL, &rs, NULL, NULL); - // get_r_offset(uref->ug, c, NULL, &re, NULL, NULL); - // fprintf(stderr, "+i->%lu: dis->%u, record_dis->%ld\n", i, rch->bb.a[i].pdis, re-rs); - } else { - rs = p->off + uref->ug->g->seq[p->score>>1].len; - re = c->off + uref->ug->g->seq[c->score>>1].len; - if(re >= rs) rch->bb.a[i].pdis = re - rs; - else rch->bb.a[i].pdis = (uint32_t)-1; - // fprintf(stderr, "-i->%lu: dis->%u\n", i, rch->bb.a[i].pdis); - } - - k = i; - // if(rch->bb.a[i].base || rch->bb.a[i].pchain == 0 || rch->bb.a[i].el == 0) { - // fprintf(stderr, "+++(%lu) base:%u, pchain:%u, el:%u\n", - // i, rch->bb.a[i].base, rch->bb.a[i].pchain, rch->bb.a[i].el); - // } - } - - ///make sure if this UL read has been done - uint32_t sp = (uint32_t)-1, ep = (uint32_t)-1; - for (l = 0 ; k >= 0; ) { - // fprintf(stderr, "k->%ld\n", k); - if(sp == (uint32_t)-1 || rch->bb.a[k].qe <= sp) { - if(sp != (uint32_t)-1) l += ep - sp; - sp = rch->bb.a[k].qs; ep = rch->bb.a[k].qe; - } else { - sp = MIN(sp, rch->bb.a[k].qs); - } - if(rch->bb.a[k].pidx == (uint32_t)-1) k = -1; - else k = rch->bb.a[k].pidx; - } - - if(sp != (uint32_t)-1) l += ep - sp; - if(l == (int64_t)rch->rlen) rch->dd = 1; - - - ///debug_ssb - // for (k = 0; (uint32_t)k < rch->bb.n; k++) { - // if(rch->bb.a[k].pidx != (uint32_t)-1) { - // if((rch->bb.a[k].pidx >= 0) && (rch->bb.a[k].pidx < rch->bb.n) && - // (rch->bb.a[rch->bb.a[k].pidx].aidx == k)) { - // ; - // } else { - // fprintf(stderr, "[M::%s::k->%ld] +rch->bb.n::%u\n", __func__, k, (uint32_t)rch->bb.n); - // for (l = 0; (uint32_t)l < rch->bb.n; l++) { - // fprintf(stderr, "[M::%.*s::k->%lu] q::[%u, %u), t::[%u, %u), pidx::%u, aidx::%u\n", - // (int)Get_NAME_LENGTH(R_INF, rch->bb.a[l].hid), Get_NAME(R_INF, rch->bb.a[l].hid), l, - // rch->bb.a[l].qs, rch->bb.a[l].qe, rch->bb.a[l].ts, rch->bb.a[l].te, - // rch->bb.a[l].pidx, rch->bb.a[l].aidx); - // } - // exit(1); - // } - // } - - // if(rch->bb.a[k].aidx != (uint32_t)-1) { - // if((rch->bb.a[k].aidx >= 0) && (rch->bb.a[k].aidx < rch->bb.n) && - // (rch->bb.a[rch->bb.a[k].aidx].pidx == k)) { - // ; - // } else { - // fprintf(stderr, "[M::%s::k->%ld] -rch->bb.n::%u\n", __func__, k, (uint32_t)rch->bb.n); - // for (l = 0; (uint32_t)l < rch->bb.n; l++) { - // fprintf(stderr, "[M::%.*s::k->%lu] q::[%u, %u), t::[%u, %u), pidx::%u, aidx::%u\n", - // (int)Get_NAME_LENGTH(R_INF, rch->bb.a[l].hid), Get_NAME(R_INF, rch->bb.a[l].hid), l, - // rch->bb.a[l].qs, rch->bb.a[l].qe, rch->bb.a[l].ts, rch->bb.a[l].te, - // rch->bb.a[l].pidx, rch->bb.a[l].aidx); - // } - // exit(1); - // } - // } - // } - - // if(ulid == 292) { - // for (i = 0; i < rch->bb.n; i++) { - // fprintf(stderr, "(%lu) qs:%u, qe:%u, ts:%u, te:%u, pidx:%u\n", i, - // rch->bb.a[i].qs, rch->bb.a[i].qe, rch->bb.a[i].ts, rch->bb.a[i].te, rch->bb.a[i].pidx); - // } - // } - - // for (i = 0; i < rch->bb.n; i++) { - // if(rch->bb.a[i].pidx == (uint32_t)-1) continue; - // if(rch->bb.a[i].base || rch->bb.a[i].pchain == 0 || rch->bb.a[i].el == 0) { - // fprintf(stderr, "(%lu) base:%u, pchain:%u, el:%u\n", - // i, rch->bb.a[i].base, rch->bb.a[i].pchain, rch->bb.a[i].el); - // } - // assert((!(rch->bb.a[i].base)) && (rch->bb.a[i].pchain) && (rch->bb.a[i].el)); - // assert((!(rch->bb.a[rch->bb.a[i].pidx].base)) && (rch->bb.a[rch->bb.a[i].pidx].pchain) - // && (rch->bb.a[rch->bb.a[i].pidx].el)); - // } - // int64_t exact = 0, inexact = 0; uc_block_t *z; - // for (k = 0; k < a_n; k++) { - // // fprintf(stderr, "(%ld) a->qs:%d, a->qe:%d, a->rs:%d, a->re:%d\n", k, a[k].qs, a[k].qe, a[k].rs, a[k].re); - // if(a[k].dist_pre < 0) continue; - // z = &(rch->bb.a[a[k].dist_pre]); - // assert(z->hid == (a[k].v>>1) && z->rev == (a[k].v&1)); - // if((int64_t)z->qs == a[k].qs && (int64_t)z->qe == a[k].qe && (int64_t)z->ts == a[k].rs && (int64_t)z->te == a[k].re) { - // exact++; - // } else { - // inexact++; - // // fprintf(stderr, "+z->qs:%u, z->qe:%u, z->ts:%u, z->te:%u\n", z->qs, z->qe, z->ts, z->te); - // // fprintf(stderr, "-a->qs:%d, a->qe:%d, a->rs:%d, a->re:%d\n\n", a[k].qs, a[k].qe, a[k].rs, a[k].re); - // } - // } - // fprintf(stderr, "[M::%s::exact->%ld, inexact->%ld]\n", __func__, exact, inexact); -} - -void print_debug_gchain(const ul_idx_t *uref, mg_lchain_t *a, int64_t a_n, ul_vec_t *rch) -{ - int64_t k; - fprintf(stderr, "\n[M::%s] a_n->%ld\n", __func__, a_n); - for (k = 0; k < a_n; k++) { - fprintf(stderr, "[M::%s::k->%ld] utg%.6d%c(%c), qs->%d, qe->%d, rs->%u, re->%u, qlen->%u\n", __func__, k, - (int32_t)(a[k].v>>1)+1, "lc"[uref->ug->u.a[(a[k].v>>1)].circ], "+-"[(a[k].v&1)], - a[k].off<0?-1:a[k].qs, a[k].off<0?-1:a[k].qe, a[k].rs, a[k].re, rch->rlen); - } - -} - -void update_ul_vec_t(const ul_idx_t *uref, kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, ul_vec_t *rch, -vec_mg_lchain_t *uc, vec_mg_lchain_t *swap, int64_t ulid, const asg_t *rg, Chain_Data* dp, -int64_t dp_max_skip, int64_t dp_max_iter, int64_t dp_max_dis) -{ - // fprintf(stderr, "\n++[M::%s::%.*s(id:%ld), len:%u]\n", __func__, - // UL_INF.nid.a[ulid].n, UL_INF.nid.a[ulid].a, ulid, rch->rlen); - - int64_t k, ucn = uc->n; mg_lchain_t *ix; - for (k = 0, swap->n = 0; k < ucn; k += ix->cnt + 1) { - ix = &(uc->a[k]); assert(ix->v == (uint32_t)-1); - // if(ulid == 14714) { - // fprintf(stderr, "\n[M::%s::ucn->%ld, k->%ld, kcnt->%d]\n", __func__, ucn, k, ix->cnt); - // print_debug_gchain(uref, uc->a + k + 1, ix->cnt, rch); - // } - gen_rovlp_chain_by_ul(rg, rch, uref, raw_idx, raw_chn, uc->a + k + 1, ix->cnt, swap, dp, - dp_max_skip, dp_max_iter, dp_max_dis, ulid); - } - - ///up to now, given a in swap - ///x->ts and x->te are the coordinates in unitig (x->score>>1), instead of HiFi read (x->v>>1) - ///x->qs and x->qe are the coordinates in UL - ///x->dist_pre is the idx of this chain at rch - // debug_intermediate_chain(uref->ug, swap->a, swap->n); - dd_ul_vec_t(uref, swap->a, swap->n, rch, ulid); -} - - -void push_ctg_res(ul_vec_t *rch, vec_mg_lchain_t *uc, uint64_t id) -{ - // fprintf(stderr, "\n++[M::%s::%.*s(id:%ld), len:%u]\n", __func__, - // UL_INF.nid.a[ulid].n, UL_INF.nid.a[ulid].a, ulid, rch->rlen); - - uint64_t k, ucn = uc->n; uint64_t tt, s, e, z, rrn; mg_lchain_t *ix; uc_block_t *p; uc_block_t *rr; mg_lchain_t *src; - for (k = 0, rch->bb.n = 0, tt = 0; k < ucn; k += ix->cnt + 1) { - ix = &(uc->a[k]); assert(ix->v == (uint32_t)-1); - kv_pushp(uc_block_t, rch->bb, &p); memset(p, 0, sizeof((*p))); - p->hid = k/**(uint32_t)-1**/; p->qs = ix->qs; p->qe = ix->qe; p->ts = ix->cnt; tt += ix->cnt; - - // if(id == 206) { - // fprintf(stderr, "init->[M::%s::ucn->%lu, k->%lu, kcnt->%d]\n", __func__, ucn, k, ix->cnt); - // } - } - radix_sort_uc_block_t_qe_srt(rch->bb.a, rch->bb.a + rch->bb.n); - - kv_resize(uc_block_t, rch->bb, rch->bb.n + tt); - memset(rch->bb.a + rch->bb.n, 0, tt * sizeof(*(rch->bb.a))); - for (k = 0, tt = rch->bb.n; k < rch->bb.n; k++) { - s = tt; e = tt + rch->bb.a[k].ts; - rch->bb.a[k].ts = s; rch->bb.a[k].te = e; - tt = e; - // if(id == 206) { - // fprintf(stderr, "mid->[M::%s::rch->bb.n->%u, k->%lu] [%lu, %lu)\n", - // __func__, (uint32_t)rch->bb.n, k, s, e); - // } - - ix = &(uc->a[rch->bb.a[k].hid]); assert(ix->v == (uint32_t)-1); - rr = rch->bb.a + rch->bb.a[k].ts; rrn = rch->bb.a[k].te - rch->bb.a[k].ts; - src = uc->a + rch->bb.a[k].hid + 1; assert((uint32_t)ix->cnt == rrn); - for(z = 0; z < rrn; z++) { - rr[z].hid = src[z].v>>1; - rr[z].rev = src[z].v&1; - rr[z].qs = src[z].qs; rr[z].qe = src[z].qe; - rr[z].ts = src[z].rs; rr[z].te = src[z].re; - rr[z].aidx = rch->bb.a[k].hid; - } - rch->bb.a[k].hid = (uint32_t)-1; - - } - assert(tt <= rch->bb.m); - - // for (k = 0, tt = 0; k < ucn; k += ix->cnt + 1, tt++) { - // ix = &(uc->a[k]); assert(ix->v == (uint32_t)-1); - // rr = rch->bb.a + rch->bb.a[tt].ts; rrn = rch->bb.a[tt].te - rch->bb.a[tt].ts; - // src = uc->a + k + 1; - // if(!((uint32_t)ix->cnt == rrn)) { - // fprintf(stderr, "\n++[M::%s::(id::%lu)] ix->cnt::%d, rrn::%lu\n", __func__, id, ix->cnt, rrn); - // } - // assert((uint32_t)ix->cnt == rrn); - // for(z = 0; z < rrn; z++) { - // rr[z].hid = src[z].v>>1; - // rr[z].rev = src[z].v&1; - // rr[z].qs = src[z].qs; rr[z].qe = src[z].qe; - // rr[z].ts = src[z].rs; rr[z].te = src[z].re; - // rr[z].aidx = k; - // } - // } - ///up to now, given a in swap - ///x->ts and x->te are the coordinates in unitig (x->score>>1), instead of HiFi read (x->v>>1) - ///x->qs and x->qe are the coordinates in UL - ///x->dist_pre is the idx of this chain at rch - // debug_intermediate_chain(uref->ug, swap->a, swap->n); - // dd_ul_vec_t(uref, swap->a, swap->n, rch, ulid); -} - -void print_ru_raw_chains(kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, vec_mg_lchain_t *gch, ul_vec_t *rch, ma_ug_t *ug) -{ - int64_t k, i; uint64_t ts, te, qs, qe; - for (k = 0; k < (int64_t)gch->n; k++) { - i = raw_idx->a[gch->a[k].off].qn; - qs = ((raw_chn->a[i].qs<<1)>>1); qe = raw_chn->a[i].qe; - fprintf(stderr, "\n[M::%s->overall chain (%ld)] utg%.6d%c(%c), qs->%u, qe->%u, qlen->%u, ts->%u, te->%u, tlen->%u\n", __func__, k, - (int32_t)(gch->a[k].v>>1)+1, "lc"[ug->u.a[(gch->a[k].v>>1)].circ], "+-"[(gch->a[k].v&1)], - raw_idx->a[gch->a[k].off].qs, raw_idx->a[gch->a[k].off].qe, rch->rlen, - raw_idx->a[gch->a[k].off].ts, raw_idx->a[gch->a[k].off].te, ug->u.a[(gch->a[k].v>>1)].len); - ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; - for (;i>=0;) { - if(((raw_chn->a[i].qs<<1)>>1) < qs) qs = ((raw_chn->a[i].qs<<1)>>1); - if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; - if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; - if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; - - fprintf(stderr, "[M::%s->chain pieces (%ld)] qs->%u, qe->%u, ts->%u, te->%u\n", __func__, i, - ((raw_chn->a[i].qs<<1)>>1), raw_chn->a[i].qe, raw_chn->a[i].ts, raw_chn->a[i].te); - - if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; - else i = raw_chn->a[i].tn; - } - - } - -} - -///sps and hap are just vector for uint64_t; used for buffer -uint32_t direct_gchain(mg_tbuf_t *b, ul_vec_t *rch, glchain_t *ll, gdpchain_t *gdp, st_mt_t *sps, haplotype_evdience_alloc *hap, const ul_idx_t *uref, const ug_opt_t *uopt, -int64_t bw, double diff_ec_ul, int64_t max_skip, int64_t ulid, Chain_Data* dp, const asg_t *rg, int64_t linear_only) -{ - // if(ulid != 86660) return 0; - kv_ul_ov_t *idx = &(ll->lo), *init = &(ll->tk); int64_t max_idx; - idx->n = init->n = 0; - gl_rg2ug_gen(rch, idx, uref, 1, 2, ulid); - if(idx->n == 0) return 0; - ///generate linear chains - gen_linear_chains(idx, init, uref, uopt, bw, diff_ec_ul, rch->rlen, dp); - // gen_linear_chains_backup(idx, init, uref, uopt, bw, diff_ec_ul, rch->rlen, max_skip, ll, sps); -// gen_linear_chains_backup(kv_ul_ov_t *res, kv_ul_ov_t *buf, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -// double diff_ec_ul, int64_t qlen, int64_t max_skip, glchain_t *bufg, st_mt_t *bufs) - assert(idx->n); - if(idx->n == 0) return 0; - ///idx includes unitig alignments, while init keeps read alignments - // fprintf(stderr, "\n++[M::%s::%.*s(id:%ld), len:%u] idx->n:%lu\n", __func__, UL_INF.nid.a[ulid].n, UL_INF.nid.a[ulid].a, - // ulid, rch->rlen, (uint64_t)idx->n); - - dump_linear_chain(uref->ug, idx, &(gdp->l), rch->rlen, ulid); - if(gdp->l.n == 0) return 0; - // fprintf(stderr, "\n+++[M::%s::id->%ld, len->%u] idx->n:%lu\n", __func__, ulid, rch->rlen, (uint64_t)idx->n); - // kv_resize(uint64_t, ll->srt.a, idx->n); kv_resize(uint64_t, hap->snp_srt, idx->n); kv_resize(uint64_t, gdp->v, idx->n); - // occ = gl_chain_advance(&(gdp->l), &(gdp->swap), uref, uopt, G_CHAIN_BW, diff_ec_ul, qlen, UG_SKIP, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 0, NULL, uref->ug, debug_i, km); - // print_ru_raw_chains(idx, init, &(gdp->l), rch, uref->ug); - - kv_resize(uint64_t, ll->srt.a, gdp->l.n); - max_idx = gl_chain_graph(b->km, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), - &(gdp->path), rch->rlen, uopt, G_CHAIN_BW, linear_only?-1:diff_ec_ul, N_GCHAIN_RATE, ll->srt.a.a, sps, dp, UG_SKIP_GRAPH_N, UG_ITER_N, UG_DIS_N, 1); - //sps -> idx; (gdp->l) -> alignments - if(max_idx >= 0) { - max_idx = select_max_gchain(b->km, uref, ulid, sps, &(gdp->l), &(ll->tk), uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), &(gdp->swap)); - if(max_idx) { - if((!linear_only) || ((linear_only) && (gdp->swap.a[0].qe-gdp->swap.a[0].qs) - >= (rch->rlen*P_CHAIN_COV))) { - update_ul_vec_t(uref, idx, init, rch, &(gdp->swap), &(gdp->l), ulid, rg, dp, UG_SKIP_GRAPH_N, UG_ITER_N, UG_DIS_N); - } - return (rch->dd == 1?1:0); - } - } - // if(max_idx >= 0 && select_max_gchain(b->km, uref, ulid, sps, &(gdp->l), &(ll->tk), uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), &(gdp->swap))){ - // update_ul_vec_t(uref, idx, init, rch, &(gdp->swap), &(gdp->l), ulid, rg, dp, UG_SKIP_GRAPH_N, UG_ITER_N, UG_DIS_N); - // return (rch->dd == 1?1:0); - // } - - /** - ///buffer - kv_resize(uint64_t, ll->srt.a, gdp->l.n); kv_resize(uint64_t, hap->snp_srt, gdp->l.n); - kv_resize(uint64_t, gdp->v, gdp->l.n); kv_resize(int64_t, gdp->f, gdp->l.n); - max_idx = hc_gchain1_dp(b->km, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), &(gdp->path), rch->rlen, - uopt, bw, diff_ec_ul, N_GCHAIN_RATE, ll->srt.a.a, sps, gdp->f.a, hap->snp_srt.a, gdp->v.a); - // fprintf(stderr, "++++[M::%s::id->%ld, len->%u] gdp->l.n:%lu\n", __func__, ulid, rch->rlen, (uint64_t)gdp->l.n); - // fprintf(stderr, "+[M::%s::] gdp->l.n:%lu\n", __func__, (uint64_t)gdp->l.n); - //sps has the chain idx; gdp->l has the chain - if(max_idx >= 0 && gen_max_gchain_adv(b->km, uref, ulid, sps, &(gdp->l), idx, init, rch->rlen, P_CHAIN_COV, 0.3, - 0.1, PRIMARY_UL_CHAIN_MIN, uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), ll->srt.a.a, &(gdp->swap))) { - // update_ul_vec_t(rch, &(gdp->l), uref); - // fprintf(stderr, "\n++[M::%s::(id:%ld), len:%u]\n", __func__, ulid, rch->rlen); - update_ul_vec_t(uref, idx, init, rch, &(gdp->swap), &(gdp->l), ulid); - // __ac_X31_hash_string("hehe"); - // if(rch->dd == 1) { - // fprintf(stderr, "[M::%s::%.*s(id:%ld)] ulen->%u\n", __func__, UL_INF.nid.a[ulid].n, UL_INF.nid.a[ulid].a, ulid, rch->rlen); - // } - return (rch->dd == 1?1:0); - // } else { - // // uint64_t i; - // fprintf(stderr, "unsuccess->[M::%s::id->%ld, len->%u] gdp->l.n:%lu\n", __func__, ulid, rch->rlen, (uint64_t)gdp->l.n); - // for (i = 0; i < gdp->l.n; ++i) { - // fprintf(stderr, "(%lu)\t%u\t%u\t%c\tutg%.6d%c(%u)\t%u\t%u\tsrc:%u\tscore:%d\n", - // i, gdp->l.a[i].qs, gdp->l.a[i].qe, "+-"[gdp->l.a[i].v&1], (int32_t)(gdp->l.a[i].v>>1)+1, "lc"[uref->ug->u.a[gdp->l.a[i].v>>1].circ], uref->ug->u.a[gdp->l.a[i].v>>1].len, - // gdp->l.a[i].rs, gdp->l.a[i].re, gdp->l.a[i].v^1, gdp->l.a[i].score); - // } - } - **/ - - - - // occ = gl_chain_advance(idx, ll->tk.a+ll->tk.n, uref, uopt, G_CHAIN_BW, diff_ec_ul, qlen, UG_SKIP, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 0, NULL, uref->ug, debug_i, km); - - // simple_g_chain_dp(idx, buf->a, uref, uopt, bw, diff_ec_ul, rch->rlen, max_skip, ll->srt.a.a, hap->snp_srt.a, sps->a); - // if(check_extension_end(idx, rch->rlen, buf->a)) { - // // ug2rg_gen(idx->a[idx->n-1].qs, idx->a[idx->n-1].qe, buf->a + idx->a[idx->n-1].ts, idx->a[idx->n-1].te - idx->a[idx->n-1].ts, rch); - // } else {///need graph chaining - - // } - - return 0; -} - - - -uint64_t rov2uov_ctg(uint64_t rid, const ul_idx_t *uref, utg_rid_dt *ru_map, uc_block_t *rovlp, ul_ov_t *res, uint32_t qidx, uint32_t adjust_rev) -{ - uint64_t ori = ru_map->u&1, ts, te; - if(!ori) { - ts = rovlp->ts; te = rovlp->te; - } else { - ts = Get_READ_LENGTH(R_INF, rid) - rovlp->te; - te = Get_READ_LENGTH(R_INF, rid) - rovlp->ts; - } - - ts += ru_map->pos; te += ru_map->pos; - if(ts >= 0 && te <= uref->ug->g->seq[ru_map->u>>1].len) { - memset(res, 0, sizeof(*res)); - res->qn = qidx; res->qs = rovlp->qs; res->qe = rovlp->qe; - res->tn = ru_map->u>>1; res->ts = ts; res->te = te; - res->el = rovlp->el; res->rev = (rovlp->rev == ori?0:1); res->sec = ru_map->off; - if(adjust_rev && res->rev) {///for linear chaining - res->ts = uref->ug->g->seq[ru_map->u>>1].len - te; - res->te = uref->ug->g->seq[ru_map->u>>1].len - ts; - res->sec = uref->ug->u.a[ru_map->u>>1].n - ru_map->off; - } - return 1; - } - return 0; -} - - -uint64_t get_unique_rctg_aln(const ul_idx_t *uref, uint64_t v, uint64_t vi, uint64_t vs, uint64_t ulen, ul_ov_t *ures, kv_ul_ov_t *rr, uint32_t sec) -{ - utg_rid_dt *a = NULL; uint64_t a_n, k, rrn = 0, over_bd = 0; uc_block_t z; ul_ov_t p; - p.tn = p.qn = ((uint32_t)-1); if(ures) ures->tn = ures->qn = ((uint32_t)-1); - if(IS_SCAF_READ(R_INF, (v>>1))) return 0;///actually no scaf nodes within the assembly graph - a = get_r_ug_region(uref->r_ug, &a_n, v>>1); - if(!a) return 0; - - z.qs = vs; z.qe = vs + Get_READ_LENGTH(R_INF, (v>>1)); - if(z.qs > ulen) { - z.qs = ulen; - over_bd = 1; - } - - if(z.qe > ulen) { - z.qe = ulen; - over_bd = 1; - } - - z.hid = v>>1; z.rev = v&1; z.el = 1; - z.ts = 0; z.te = Get_READ_LENGTH(R_INF, (v>>1)); - if(over_bd) {//////need to handle it especially for circles - over_bd = z.qe - z.qs; - if(over_bd > Get_READ_LENGTH(R_INF, (v>>1))) { - over_bd = Get_READ_LENGTH(R_INF, (v>>1)); - } - if(!(z.rev)) { - z.ts = 0; z.te = over_bd; - } else { - z.ts = Get_READ_LENGTH(R_INF, (v>>1))-over_bd; z.te = Get_READ_LENGTH(R_INF, (v>>1)); - } - } - if(z.qe <= z.qs || z.te <= z.ts) return 0; - - - for (k = rrn = 0; k < a_n; k++) { - if(!rov2uov_ctg(v>>1, uref, &(a[k]), &z, &p, vi, 1)) continue; - p.el = 1; p.tn <<= 1; p.tn |= p.rev; ///p.qn: offset within q; p.sec: offset within t; p.tn: tid - if(sec != ((uint32_t)-1)) p.sec = sec; - if(rr) kv_push(ul_ov_t, *rr, p); - rrn++; - } - - if((ures) && (rrn == 1)) *ures = p; - return rrn; -} - -uint64_t cmp_shrink_ul_ov_t(ul_ov_t *a0, ul_ov_t *a1, uint64_t off) -{ - if((a0->tn == ((uint32_t)-1)) || (a1->tn == ((uint32_t)-1))) return 1; - if((a0->tn == a1->tn) && (a0->qn + off == a1->qn) && (a0->sec + off == a1->sec)) return 0; - return 1; -} - -void ctg_rg2ug_gen(ma_utg_t *r_cl, kv_ul_ov_t *u_cl, const ul_idx_t *uref, uint64_t id) -{ - if(r_cl->n <= 0) return ; - uint64_t k, i, m, l, is_push, vs, ls; ul_ov_t kp, lp, kp0; - u_cl->n = 0; kp.tn = kp.qn = kp0.tn = kp0.qn = ((uint32_t)-1); - - k = 1; l = 0; ls = 0; vs = 0; - get_unique_rctg_aln(uref, r_cl->a[l]>>32, l, ls, r_cl->len, &lp, NULL, ((uint32_t)-1)); ///get lp for l = 0 - vs += (uint32_t)(r_cl->a[l]); - - for (; k <= r_cl->n; k++) { - is_push = 0; - if(k < r_cl->n) { - get_unique_rctg_aln(uref, r_cl->a[k]>>32, k, vs, r_cl->len, &kp, NULL, ((uint32_t)-1)); - if(cmp_shrink_ul_ov_t(&lp, &kp, k - l)) is_push = 1; - } else { - is_push = 1; - } - - if(is_push) { - kp0 = kp; - if(k - l > 1) { - for (i = l; i < k; i++) {///could be merged - m = get_unique_rctg_aln(uref, r_cl->a[i]>>32, i, ls, r_cl->len, &kp, NULL, ((uint32_t)-1)); - assert(m == 1); assert(kp.tn == lp.tn); assert(kp.qn == lp.qn + i - l); assert(kp.sec == lp.sec + i - l); - if(kp.qs < lp.qs) lp.qs = kp.qs; if(kp.qe > lp.qe) lp.qe = kp.qe; - if(kp.ts < lp.ts) lp.ts = kp.ts; if(kp.te > lp.te) lp.te = kp.te; - ls += (uint32_t)(r_cl->a[i]); - - // if(id == 123) { - // fprintf(stderr, "-0-[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\tsc::%d\n", __func__, - // (int32_t)(kp.tn>>1)+1, "+-"[kp.tn&1], kp.qs, kp.qe, kp.qe-kp.qs, kp.ts, kp.te, kp.te-kp.ts, kp.sec); - // } - } - lp.sec = k - l; - kv_push(ul_ov_t, *u_cl, lp); - } else if(k - l == 1) { - m = get_unique_rctg_aln(uref, r_cl->a[l]>>32, l, ls, r_cl->len, NULL, u_cl, 1); - // if(id == 123) { - // fprintf(stderr, "-1-[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\tsc::%d\n", __func__, - // (int32_t)(kp.tn>>1)+1, "+-"[kp.tn&1], kp.qs, kp.qe, kp.qe-kp.qs, kp.ts, kp.te, kp.te-kp.ts, kp.sec); - // } - } - - l = k; lp = kp0; ls = vs; - } - - if(k < r_cl->n) vs += (uint32_t)(r_cl->a[k]); - } -} - -inline int64_t comput_linear_ctg_sc(ul_ov_t *li, ul_ov_t *lj, double diff_ec_ul, int64_t bw) -{ ///li is the suffix of lj - int64_t dq, dt, dd, mm; - if(lj->te > li->te) return INT32_MIN; - dq = li->qe - lj->qs; dt = li->te - lj->ts; - dd = (dq>dt? dq-dt:dt-dq); - mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; - if(dd > mm) return INT32_MIN; - return li->sec; -} - -inline uint64_t is_available_ctg_aln(const ul_idx_t *uref, ul_ov_t *z) -{ - if((z->te > z->ts) && (uref->ug->u.a[z->tn].len >= (z->te-z->ts)) && ((uref->ug->u.a[z->tn].len) - (z->te-z->ts) <= 16) && (z->sec >= (uref->ug->u.a[z->tn].n*0.333333))) { - return 1; - } - return 0; -} - -uint64_t linear_ctg_chain_dp_adv(ul_ov_t *ch, int64_t ch_n, ul_ov_t *sv, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, ma_ug_t *ug, -int64_t chain_offset) -{ ///all in[].el must be 1 - if(ch_n == 0) return 0; - int64_t i, j, k, sc, csc, mm_sc, mm_idx, its, ite, max; - ul_ov_t *li = NULL, *lj = NULL; int64_t *p, *t, st, plus, max_ii, n_skip, end_j; int32_t *f; - resize_Chain_Data(dp, ch_n, NULL); - t = dp->tmp; f = dp->score; p = dp->pre; - - radix_sort_ul_ov_srt_qe(ch, ch + ch_n); - for (i = 1, j = 0; i <= ch_n; i++) { - if (i == ch_n || ch[i].qe != ch[j].qe) { - if(i - j > 1) radix_sort_ul_ov_srt_qs(ch+j, ch+i); - j = i; - } - } - - // fprintf(stderr, "[M::%s::] ch_n:%ld\n", __func__, ch_n); - memset(t, 0, (ch_n*sizeof((*t)))); - for (i = st = plus = 0, max_ii = -1; i < ch_n; ++i) { - li = &(ch[i]); csc = li->sec; - mm_sc = csc; mm_idx = -1; n_skip = 0; end_j = -1; - st = (i= st; --j) { - lj = &(ch[j]); - sc = comput_linear_ctg_sc(li, lj, diff_ec_ul, bw); ///should allow contain - if(sc == INT32_MIN) continue; - sc += f[j]; - if(sc > mm_sc) { - mm_sc = sc, mm_idx = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - end_j = j; - if (max_ii < 0 || (ch[i].qe>(ch[max_ii].qe+max_dis))) {//too long - max = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && (ch[i].qe<=(max_dis+ch[j].qe)); --j) { - if (max < f[j]) { - max = f[j], max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - lj = &(ch[max_ii]); - sc = comput_linear_ctg_sc(li, lj, diff_ec_ul, bw); ///should allow contain - if(sc != INT32_MIN) { - sc += f[max_ii]; - if(sc > mm_sc) { - mm_sc = sc; mm_idx = max_ii; - } - } - } - - f[i] = mm_sc; p[i] = mm_idx; - if ((max_ii < 0) || ((ch[i].qe<=max_dis+ch[max_ii].qe) && (f[max_ii]sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); - sv[i] = *li; - // fprintf(stderr, "##(%ld) %u\t%u\t%c\tutg%.6d%c(%u)\t%u\t%u\tmm_idx:%ld\tmm_sc:%ld\n", i, li->qs, li->qe, "+-"[li->rev], - // (int32_t)(li->tn)+1, "lc"[uref->ug->u.a[li->tn].circ], uref->ug->u.a[li->tn].len, li->ts, li->te, mm_idx, mm_sc); - // track[i] = push_sc_pre(mm_sc, mm_idx); - // li->sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); sv[i] = *li; - } - - for (i = 0; i < ch_n; ++i) t[i] = 0; - int64_t n_u; - for (k = ch_n-1, n_u = 0; k >= 0; --k) { - if(t[k]) continue; - i = k; ch[n_u]=sv[i]; sc = f[i]; - for (;i>=0;) { - if(sv[i].qs < ch[n_u].qs) ch[n_u].qs = sv[i].qs; - if(sv[i].ts < ch[n_u].ts) ch[n_u].ts = sv[i].ts; - if(sv[i].qe > ch[n_u].qe) ch[n_u].qe = sv[i].qe; - if(sv[i].te > ch[n_u].te) ch[n_u].te = sv[i].te; - // ch[n_u].qn = i;//start idx of read alignment in chain - t[i] = 1; i = p[i]; - } - adjust_rev_tse(&(ch[n_u]), ug->g->seq[ch[n_u].tn].len, &its, &ite); - ch[n_u].ts = its; ch[n_u].te = ite; - - sc = ((i < 0)?(sc):(sc-f[i])); - ch[n_u].sec = (sc>0x3FFFFFFF?0x3FFFFFFF:sc);///this is calculated incorrectly - // ch[n_u].qn += chain_offset; //start idx of read alignment in chain - // ch[n_u].tn = k + chain_offset; //end idx of read alignment in chain - ch[n_u].qn = k + chain_offset; //end idx of read alignment in chain - - - n_u++; - } - for (i = 0; i < ch_n; ++i) { - adjust_rev_tse(&(sv[i]), ug->g->seq[sv[i].tn].len, &its, &ite); - sv[i].ts = its; sv[i].te = ite; - k = p[i]; sv[i].tn = k>=0?k+chain_offset:(uint32_t)-1; - } - return n_u; -} - -void gen_linear_chains_ctg(kv_ul_ov_t *res, kv_ul_ov_t *buf, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, Chain_Data* dp) -{ - uint64_t k, l, z, an, m; - radix_sort_ul_ov_srt_tn(res->a, res->a + res->n); - ///after this function, res keeps unitig alignment, while buf keeps read alignments - kv_resize(ul_ov_t, *buf, res->n); buf->n = res->n; - for (k = 1, l = m = 0; k <= res->n; k++) { - if(k == res->n || res->a[k].tn != res->a[l].tn) {///qn <- (tn|rev) - for (z = l; z < k; z++) res->a[z].tn>>=1; - an = k; - if(k - l > 1) {///if there is only one alignment for a node, then no need for DP - an = l + linear_ctg_chain_dp_adv(res->a+l, k-l, buf->a+l, uref, uopt, bw, diff_ec_ul, qlen, UG_SKIP_N, UG_ITER_N, UG_DIS_N, dp, uref->ug, l); - } - - for (z = l; z < an; z++) { - if(is_available_ctg_aln(uref, &(res->a[z]))) { - res->a[z].ts = 0; res->a[z].te = uref->ug->u.a[res->a[z].tn].len; - res->a[m++] = res->a[z]; - } - } - l = k; - } - } - res->n = m; -} - - - - -///sps and hap are just vector for uint64_t; used for buffer -uint32_t direct_gchain_scaf(mg_tbuf_t *b, ma_utg_t *rch, glchain_t *ll, gdpchain_t *gdp, st_mt_t *sps, haplotype_evdience_alloc *hap, const ul_idx_t *uref, const ug_opt_t *uopt, -int64_t bw, double diff_ec_ul, int64_t max_skip, int64_t ulid, Chain_Data* dp, const asg_t *rg, ul_vec_t *res) -{ - res->bb.n = 0; - // if(ulid != 86660) return 0; - kv_ul_ov_t *idx = &(ll->lo), *init = &(ll->tk); int64_t max_idx; - idx->n = init->n = 0; - // gl_rg2ug_gen(rch, idx, uref, 1, 2, ulid); - ctg_rg2ug_gen(rch, idx, uref, ulid); - - // uint32_t k; - // fprintf(stderr, "[M::%s] rch->len::%u, rch->n::%u, idx->n::%u\n", __func__, (uint32_t)rch->len, (uint32_t)rch->n, (uint32_t)idx->n); - // for (k = 0; k < idx->n; k++) { - // fprintf(stderr, "[k->%u::utg%.6u%c(len->%u::n->%u)]\tq::[%u, %u)\t%c\tt::[%u, %u)\n", - // k, (idx->a[k].tn>>1) + 1, "lc"[uref->ug->u.a[(idx->a[k].tn>>1)].circ], uref->ug->u.a[(idx->a[k].tn>>1)].len, idx->a[k].sec, - // idx->a[k].qs, idx->a[k].qe, "+-"[idx->a[k].rev], idx->a[k].ts, idx->a[k].te); - // } - - // for (k = 0; k < idx->n; k++) { - // fprintf(stderr, "utg%.6u%c,", (idx->a[k].tn>>1)+1, "lc"[uref->ug->u.a[(idx->a[k].tn>>1)].circ]); - // } - // fprintf(stderr, "\n"); - - if(idx->n == 0) return 0; - ///generate linear chains - gen_linear_chains_ctg(idx, init, uref, uopt, bw, diff_ec_ul, rch->len, dp); - - if(idx->n == 0) return 0; - - dump_linear_chain(uref->ug, idx, &(gdp->l), rch->len, ulid); - if(gdp->l.n == 0) return 0; - - kv_resize(uint64_t, ll->srt.a, gdp->l.n); - max_idx = ctg_chain_graph(b->km, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), - &(gdp->path), rch->len, uopt, G_CHAIN_BW, N_GCHAIN_RATE, ll->srt.a.a, sps, dp, UG_SKIP_GRAPH_N, UG_ITER_N, /**UG_DIS_N**/UG_DIS_N*100, ulid); - - //sps -> idx; (gdp->l) -> alignments - if(max_idx >= 0) { - max_idx = select_max_ctg_chain(b->km, uref, ulid, sps, &(gdp->l), &(ll->tk), uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), &(gdp->swap)); - if(max_idx) { - push_ctg_res(res, &(gdp->swap), ulid); - return 1; - } - } - - return 0; -} - -uint64_t get_seq_bub_id(uint64_t v, bubble_type *bub, uint64_t *bid, uint64_t *nxt) -{ - uint64_t id0, id1, id; uint32_t beg, sink; - - (*bid) = (*nxt) = (uint64_t)-1; - get_bub_id(bub, v>>1, &id0, &id1, 1); - - id = id0; - if((id != (uint64_t)-1) && (id < bub->f_bub)) {///no need broken bubble - get_bubbles(bub, id, &beg, &sink, NULL, NULL, NULL); - if(v == beg) { - (*bid) = id; (*nxt) = sink^1; return 1; - } - - if(v == sink) { - (*bid) = id; (*nxt) = beg^1; return 1; - } - } - - id = id1; - if((id != (uint64_t)-1) && (id < bub->f_bub)) {///no need broken bubble - get_bubbles(bub, id, &beg, &sink, NULL, NULL, NULL); - if(v == beg) { - (*bid) = id; (*nxt) = sink^1; return 1; - } - - if(v == sink) { - (*bid) = id; (*nxt) = beg^1; return 1; - } - } - - return 0; -} - -uint64_t pick_bubble(uc_block_t *a, uint64_t a_n, bubble_type *bub, uint64_t *r_bid) -{ - uint64_t k = 0, v, bid = (uint64_t)-1, w = (uint64_t)-1; (*r_bid) = (uint64_t)-1; - if(a_n <= 1) return 0;///no bubble - v = (((uint32_t)a[k].hid)<<1)|((uint32_t)a[k].rev); - if(!get_seq_bub_id(v, bub, &bid, &w)) return 0; - (*r_bid) = bid; - for (k = 1; k < a_n; k++) { - v = (((uint32_t)a[k].hid)<<1)|((uint32_t)a[k].rev); - if(v == w) return k; - if(bub->index[v>>1] != bid) return 0; - } - - return 0; -} - -uint64_t qry_bub_sc(const ul_idx_t *uref, ma_ug_t *gfa, scaf_res_t *ref_sc, bubble_type *bub, uint64_t bid, uint64_t qsidx, uint64_t qeidx, ul_vec_t *qstr, uint32_t avoid_id, kv_ul_ov_t *res) -{ - // fprintf(stderr, "qsidx::%lu(utg%.6u%c), qeidx::%lu(utg%.6u%c)\n", qsidx, (qstr->bb.a[qsidx].hid)+1, "lc"[gfa->u.a[qstr->bb.a[qsidx].hid].circ], qeidx, (qstr->bb.a[qeidx].hid)+1, "lc"[gfa->u.a[qstr->bb.a[qeidx].hid].circ]); - uint32_t beg, sink, v, w, z, si, ei, qrev = (uint32_t)-1, qv, qw, trev, nn = 0, tn; - get_bubbles(bub, bid, &beg, &sink, NULL, NULL, NULL); - if((beg == ((uint32_t)-1)) || (sink == ((uint32_t)-1))) return 0; - utg_rid_dt *a; uint64_t a_n, i, k; ul_vec_t *q; ul_ov_t p; - qv = qstr->bb.a[qsidx].hid; qv <<= 1; qv |= ((uint32_t)qstr->bb.a[qsidx].rev); - qw = qstr->bb.a[qeidx].hid; qw <<= 1; qw |= ((uint32_t)qstr->bb.a[qeidx].rev); - if((qv == beg) && (qw == (sink^1))) qrev = 0; - if((qv == sink) && (qw == (beg^1))) qrev = 1; - assert(qrev != (uint32_t)-1); - memset(&p, 0, sizeof(p)); - - v = beg; w = sink^1; trev = 0; - a = get_r_ug_region(uref->r_ug, &a_n, v>>1); - // fprintf(stderr, "+a_n::%lu\n", a_n); - for (i = 0; i < a_n; i++) { - // fprintf(stderr, "+(0)i::%lu\n", i); - if((a[i].u&1) != (v&1)) continue; - if((a[i].u>>1) == avoid_id) continue; - q = &(ref_sc->a[a[i].u>>1]); si = ei = a[i].off; - assert((q->bb.a[si].hid == (v>>1)) && (q->bb.a[si].rev == (v&1))); - // fprintf(stderr, "+(1)i::%lu\n", i); - for (k = tn = 0; k < q->bb.n; k++) tn += q->bb.a[k].te - q->bb.a[k].ts; - for (k = si + 1; (k < tn) && (q->bb.a[k].aidx == q->bb.a[si].aidx); k++) { - z = (((uint32_t)q->bb.a[k].hid)<<1)|((uint32_t)q->bb.a[k].rev); - if(z == w) {ei = k; break;} - if(bub->index[z>>1] != bid) break; - } - - if(ei > si) {////found a bubble - // fprintf(stderr, "+(2)i::%lu, si::%u, ei::%u, ref_id::%u\nn", i, si, ei, a[i].u>>1); - p.qn = q->bb.a[si].aidx; p.qs = qsidx; p.qe = qeidx; - p.tn = a[i].u>>1; p.ts = si; p.te = ei; - p.rev = (qrev == trev?0:1); - kv_push(ul_ov_t, *res, p); - nn++; - } - } - - - v = sink; w = beg^1; trev = 1; - a = get_r_ug_region(uref->r_ug, &a_n, v>>1); - // fprintf(stderr, "-a_n::%lu\n", a_n); - for (i = 0; i < a_n; i++) { - if((a[i].u&1) != (v&1)) continue; - if((a[i].u>>1) == avoid_id) continue; - q = &(ref_sc->a[a[i].u>>1]); si = ei = a[i].off; - assert((q->bb.a[si].hid == (v>>1)) && (q->bb.a[si].rev == (v&1))); - for (k = tn = 0; k < q->bb.n; k++) tn += q->bb.a[k].te - q->bb.a[k].ts; - for (k = si + 1; (k < tn) && (q->bb.a[k].aidx == q->bb.a[si].aidx); k++) { - z = (((uint32_t)q->bb.a[k].hid)<<1)|((uint32_t)q->bb.a[k].rev); - if(z == w) {ei = k; break;} - if(bub->index[z>>1] != bid) break; - } - - if(ei > si) {////found a bubble - // fprintf(stderr, "-(2)i::%lu, si::%u, ei::%u, ref_id::%u\nn", i, si, ei, a[i].u>>1); - p.qn = q->bb.a[si].aidx; p.qs = qsidx; p.qe = qeidx; - p.tn = a[i].u>>1; p.ts = si; p.te = ei; - p.rev = (qrev == trev?0:1); - kv_push(ul_ov_t, *res, p); - nn++; - } - } - - return nn; -} - -/** -uint64_t bubble_check_push(uc_block_t *a, uint64_t a_n, bubble_type *bub) -{ - uint64_t k = 0, v, bid, w; - if(a_n <= 1) return 0;///no bubble - while(k < a_n) { - v = (((uint32_t)a[k].hid)<<1)|((uint32_t)a[k].rev); - if(!get_seq_bub_id(v, bub, &bid, &w)) break; - } - - - for (k = 1, l = 0; k <= a_n; k++) { - if(k ) { - l = k; - } - } - - get_bub_id(bub, root_id, &id0, &id1, 1);; -} -**/ - - -uint64_t cc_bub_match(ul_ov_t *ch, int64_t ch_n) { - if(ch_n == 0) return 0; - int64_t i, j, k; - - radix_sort_ul_ov_srt_qs(ch, ch + ch_n); - for (i = 1, j = 0; i <= ch_n; i++) { - if (i == ch_n || ch[i].qs != ch[j].qs) { - if(i - j > 1) radix_sort_ul_ov_srt_qe(ch+j, ch+i); - j = i; - } - } - - for (i = k = 0; i < ch_n; ++i) { - if(ch[i].tn == (uint32_t)-1) continue; - for (j = i + 1; j < ch_n && ch[i].qe >= ch[j].qs; j++) { - if(ch[j].tn == (uint32_t)-1) continue; - if((ch[i].qe == ch[j].qs) && (ch[i].rev == ch[j].rev) && (ch[i].qn == ch[j].qn)) { - if(!ch[i].rev) { - if(ch[i].te == ch[j].ts) { - ch[i].qe = ch[j].qe; - ch[i].te = ch[j].te; - ch[j].tn = (uint32_t)-1; - } - } else { - if(ch[j].te == ch[i].ts) { - ch[i].qe = ch[j].qe; - ch[i].ts = ch[j].ts; - ch[j].tn = (uint32_t)-1; - } - } - } - } - - ch[k++] = ch[i]; - } - - return k; -} - -uint64_t extract_scaf_res_t(uc_block_t *in, const ul_idx_t *uref, scaf_res_t *ref_sc, uint32_t avid, kv_ul_ov_t *res) -{ - utg_rid_dt *a; uint64_t i, a_n, nn, nw; uc_block_t *ou; ul_ov_t p; memset(&p, 0, sizeof(p)); - a = get_r_ug_region(uref->r_ug, &a_n, in->hid); - for (i = nn = 0; i < a_n; i++) { - if((a[i].u>>1) == avid) continue; - ou = &(ref_sc->a[a[i].u>>1].bb.a[a[i].off]); - p.qn = (uint32_t)-1; p.qs = in->qs; p.qe = in->qe; - p.tn = a[i].u>>1; p.ts = ou->qs; p.te = ou->qe; - p.el = 1; p.rev = ((in->rev == ou->rev)?0:1); - nw = MAX(p.te-p.ts, p.qe-p.qs); nw *= CHAIN_MATCH; - p.sec = ((nw>=0x3fffffff)?(0x3fffffff):(nw)); - kv_push(ul_ov_t, *res, p); - - nn++; - } - return nn; -} - -uint64_t gen_trans_ovlp_scaf(ma_ug_t *gfa, u_trans_t *map, uc_block_t *qin, uc_block_t *rin, ul_ov_t *res) -{ - uint64_t s, e, s0, e0; uc_block_t *z; - - z = qin; s0 = map->qs; e0 = map->qe; - if(s0 > gfa->u.a[z->hid].len || e0 > gfa->u.a[z->hid].len) return 0; - if(!(z->rev)) { - s = s0; e = e0; - } else { - s = gfa->u.a[z->hid].len - e0; - e = gfa->u.a[z->hid].len - s0; - } - s += z->qs; e += z->qs; - if(s >= e) return 0; - res->qs = s; res->qe = e; - - - z = rin; s0 = map->ts; e0 = map->te; - if(s0 > gfa->u.a[z->hid].len || e0 > gfa->u.a[z->hid].len) return 0; - if(!(z->rev)) { - s = s0; e = e0; - } else { - s = gfa->u.a[z->hid].len - e0; - e = gfa->u.a[z->hid].len - s0; - } - s += z->qs; e += z->qs; - if(s >= e) return 0; - res->ts = s; res->te = e; - - res->rev = map->rev^(qin->rev^rin->rev); - - return 1; -} - -void extract_trans_scaf_res_t(uc_block_t *qin, const ul_idx_t *uref, scaf_res_t *ref_sc, ma_ug_t *gfa, kv_u_trans_t *ta, uint32_t avid, uint32_t is_exact, kv_ul_ov_t *res) -{ - utg_rid_dt *a; uint64_t i, a_n; uc_block_t *rin; - u_trans_t *u; uint64_t k, u_n; - ul_ov_t p; memset(&p, 0, sizeof(p)); - - // fprintf(stderr, "\n[M::%s] utg%.6u%c, [%u, %u)\n", __func__, qin->hid+1, "lc"[gfa->u.a[qin->hid].circ], qin->qs, qin->qe); - u = u_trans_a(*ta, qin->hid); - u_n = u_trans_n(*ta, qin->hid); - for (k = 0; k < u_n; k++) { - if(is_exact && u[k].f != RC_0 && u[k].f != RC_1) continue; - // fprintf(stderr, "+[M::%s] utg%.6u%c->utg%.6u%c, q::[%u, %u), %c, t::[%u, %u)\n", __func__, qin->hid+1, "lc"[gfa->u.a[qin->hid].circ], u[k].tn+1, "lc"[gfa->u.a[u[k].tn].circ], u[k].qs, u[k].qe, "+-"[u[k].rev], u[k].ts, u[k].te); - a = get_r_ug_region(uref->r_ug, &a_n, u[k].tn); - for (i = 0; i < a_n; i++) { - if((a[i].u>>1) == avid) continue; - rin = &(ref_sc->a[a[i].u>>1].bb.a[a[i].off]); - if(gen_trans_ovlp_scaf(gfa, &(u[k]), qin, rin, &p)) { - p.tn = a[i].u>>1; p.qn = u[k].f; p.el = 0; p.sec = u[k].nw; - kv_push(ul_ov_t, *res, p); - - // fprintf(stderr, "-[M::%s] q::[%u, %u), %c, t::[%u, %u), qin->qs::%u, rin->qs::%u\n", __func__, p.qs, p.qe, "+-"[p.rev], p.ts, p.te, qin->qs, rin->qs); - } - } - } -} - -void cl_trans_gen(uint32_t qid, uint32_t qlen, ul_vec_t *qstr, kv_ul_ov_t *res, const ul_idx_t *uref, ma_ug_t *ref, scaf_res_t *ref_sc, ma_ug_t *gfa, bubble_type *bub, kv_u_trans_t *ta, uint32_t is_self, uint32_t is_exact) -{ - uint64_t k, l, m = 0, mi, z, zn, a_n, bid, nw; uc_block_t *a; uint32_t avid = ((is_self)?(qid):((uint32_t)-1)); - res->n = 0; - ///identify bubble chain first - for (k = 0, a = qstr->bb.a; k < qstr->bb.n; k++) { - z = qstr->bb.a[k].ts; a_n = qstr->bb.a[k].te; - while (z < a_n) { - zn = 1; - zn = pick_bubble(a + z, a_n - z, bub, &bid); - if((!zn) || (!qry_bub_sc(uref, gfa, ref_sc, bub, bid, z, z + zn, qstr, avid, res))) {///found a bubble; a[z] -> beg; a[z + zn] -> sink - zn = 1; - } - z += zn; - } - } - - if(res->n) {///matched bubbles - for (k = 0; k < res->n; k++) res->a[k].tn = (((uint64_t)res->a[k].tn)<<1)|((uint64_t)res->a[k].rev); - radix_sort_ul_ov_srt_tn(res->a, res->a + res->n); - - for (k = 1, l = m = 0; k <= res->n; k++) { - if(k == res->n || res->a[k].tn != res->a[l].tn) {///qn <- (tn|rev) - for (z = l; z < k; z++) res->a[z].tn>>=1; - a_n = k; - if(k - l > 1) {///if there is only one alignment for a node, then no need for DP - a_n = l + cc_bub_match(res->a+l, k-l); - } - - for (z = l; z < a_n; z++) res->a[m++] = res->a[z]; - // fprintf(stderr, "l::%lu, k::%lu, m::%lu\n", l, k, m); - l = k; - } - } - res->n = m; - radix_sort_ul_ov_srt_qe(res->a, res->a + res->n); - // for (k = 0; k < res->n; k++) { - // fprintf(stderr, "***qsidx::%u(utg%.6u%c), qeidx::%u(utg%.6u%c)\n", res->a[k].qs, (qstr->bb.a[res->a[k].qs].hid)+1, "lc"[gfa->u.a[qstr->bb.a[res->a[k].qs].hid].circ], res->a[k].qe, (qstr->bb.a[res->a[k].qe].hid)+1, "lc"[gfa->u.a[qstr->bb.a[res->a[k].qe].hid].circ]); - // } - - } - - for (k = 0; k < qstr->bb.n; k++) { - z = qstr->bb.a[k].ts; a_n = qstr->bb.a[k].te; - for (; z < a_n; z++) { - ///filter by bubble - for (mi = 0; mi < m && z <= res->a[mi].qe; mi++) { - if((z >= res->a[mi].qs) && (z <= res->a[mi].qe)) break; - } - if((mi < m) && (z >= res->a[mi].qs) && (z <= res->a[mi].qe)) continue; - - ///exact match - if(extract_scaf_res_t(&(qstr->bb.a[z]), uref, ref_sc, avid, res)) continue; - - ///trans match - extract_trans_scaf_res_t(&(qstr->bb.a[z]), uref, ref_sc, gfa, ta, avid, is_exact, res); - } - } - - for(k = 0; k < m; k++) {///reset bubble - res->a[k].el = 1; res->a[k].qn = res->a[k].qs; - - res->a[k].qs = qstr->bb.a[res->a[k].qs].qs; - res->a[k].qe = qstr->bb.a[res->a[k].qe].qe; - - res->a[k].ts = ref_sc->a[res->a[k].tn].bb.a[res->a[k].ts].qs; - res->a[k].te = ref_sc->a[res->a[k].tn].bb.a[res->a[k].te].qe; - - nw = MAX(res->a[k].te-res->a[k].ts, res->a[k].qe-res->a[k].qs); nw *= CHAIN_MATCH; - res->a[k].sec = ((nw>=0x3fffffff)?(0x3fffffff):(nw)); - } - - // for (k = 0; k < res->n; k++) { - // fprintf(stderr, "[M::%s]\tutg%.6ul(len::%u)\tq::[%u, %u)\t%c\tutg%.6ul(len::%u)\tt::[%u, %u)\tel::%u\ttp::%u\n", __func__, qid + 1, qlen, res->a[k].qs, res->a[k].qe, "+-"[res->a[k].rev], res->a[k].tn+1, ref->u.a[res->a[k].tn].len, res->a[k].ts, res->a[k].te, res->a[k].el, res->a[k].qn); - // } -} - -inline int64_t comput_linear_ctg_trans_sc(ul_ov_t *li, ul_ov_t *lj, double diff_ec_ul, double ovlp_max, int64_t bw) -{ ///li is the suffix of lj - int64_t dq, dt, dd, mm, os, oe; - if(lj->rev != li->rev) return INT32_MIN; - int64_t iqs, iqe, its, ite, jqs, jqe, jts, jte; - iqs = li->qs; iqe = li->qe; - jqs = lj->qs; jqe = lj->qe; - its = li->ts; ite = li->te; - jts = lj->ts; jte = lj->te; - // if(li->rev) { - // its = lj->ts; ite = lj->te; - // jts = li->ts; jte = li->te; - // } - if(jte > ite) return INT32_MIN; - - - - - dq = iqs - jqe; - dt = its - jte; - dd = (dq>dt? dq-dt:dt-dq); - - dq = iqe - jqs; - dt = ite - jts; - mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; - if(dd > mm) return INT32_MIN; - - ///too long overlap - dd = iqe - iqs; if(dd > jqe - jqs) dd = jqe - jqs; - dd *= ovlp_max; if(dd < bw) dd = bw; - os = MAX(iqs, jqs), oe = MIN(iqe, jqe); - mm = ((oe > os)? (oe - os):0); - if(mm > 0 && mm > dd) return INT32_MIN; - - dd = ite - its; if(dd > jte - jts) dd = jte - jts; - dd *= ovlp_max; if(dd < bw) dd = bw; - os = MAX(its, jts), oe = MIN(ite, jte); - mm = ((oe > os)? (oe - os):0); - if(mm > dd) return INT32_MIN; - - return li->sec; -} - -uint64_t linear_ctg_trans_chain_dp(uint32_t qid, ul_ov_t *ch, int64_t ch_n, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, double ovlp_max, double unmatch_max, int64_t qlen, int64_t tlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, ul_ov_t *res, asg64_v *ea) -{ - memset(res, 0, sizeof((*res))); - if(ch_n == 0) return 0; - int64_t i, j, k, l, sc, csc, se, cse, mm_sc, mm_se, mm_idx, max, max_e, peak_sc, peak_e, peak_i, rts, rte, rqs, rqe; - ul_ov_t *li = NULL, *lj = NULL; int64_t *f, *e, st, plus, max_ii, n_skip, end_j; int32_t *p, *t; - resize_Chain_Data(dp, ch_n, NULL); - e = dp->tmp; f = dp->pre; p = dp->score; t = dp->indels; - - i = 0; - if(i < ch_n) { - ch[i].tn >>= 1; - if(ch[i].rev) { - adjust_rev_tse(&(ch[i]), tlen, &rts, &rte); - ch[i].ts = rts; ch[i].te = rte; - } - } - - for (i = 1, j = 0; i <= ch_n; i++) { - if(i < ch_n) { - ch[i].tn >>= 1; - if(ch[i].rev) { - adjust_rev_tse(&(ch[i]), tlen, &rts, &rte); - ch[i].ts = rts; ch[i].te = rte; - } - } - if (i == ch_n || ch[i].rev != ch[j].rev) { - if(i - j > 1) { - radix_sort_ul_ov_srt_qe(ch+j, ch+i); - for (k = j + 1, l = j; k <= i; k++) { - if(k == i || ch[k].qe != ch[l].qe) { - if(k - l > 1) radix_sort_ul_ov_srt_qs(ch+l, ch+k); - l = k; - } - } - } - j = i; - } - } - - // fprintf(stderr, "[M::%s::] ch_n:%ld\n", __func__, ch_n); - memset(t, 0, (ch_n*sizeof((*t)))); peak_sc = peak_e = peak_i = INT32_MIN; - for (i = st = plus = 0, max_ii = -1; i < ch_n; ++i) { - li = &(ch[i]); csc = li->sec; cse = 0; - if(li->el || li->qn == RC_0 || li->qn == RC_1) cse = li->qe - li->qs; - - mm_sc = csc; mm_se = cse; mm_idx = -1; n_skip = 0; end_j = -1; - st = (i= st; --j) { - lj = &(ch[j]); - sc = comput_linear_ctg_trans_sc(li, lj, diff_ec_ul, ovlp_max, bw); ///should allow contain - if(sc == INT32_MIN) continue; - sc += f[j]; se = cse + e[j]; - if((sc > mm_sc) || (sc == mm_sc && se > mm_se)) { - mm_sc = sc, mm_se = se, mm_idx = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - - - end_j = j; - if (max_ii < 0 || (ch[i].qe>(ch[max_ii].qe+max_dis))) {//too long - max = INT32_MIN; max_e = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && (ch[i].qe<=(max_dis+ch[j].qe)); --j) { - if ((max < f[j]) || (max == f[j] && max_e < e[j])) { - max = f[j], max_e = e[j], max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - lj = &(ch[max_ii]); - sc = comput_linear_ctg_trans_sc(li, lj, diff_ec_ul, ovlp_max, bw); ///should allow contain - if(sc != INT32_MIN) { - sc += f[max_ii]; - se = cse + e[max_ii]; - if((sc > mm_sc) || (sc == mm_sc && se > mm_se)) { - mm_sc = sc; mm_se = se; mm_idx = max_ii; - } - } - } - - f[i] = mm_sc; e[i] = mm_se; p[i] = mm_idx; - if ((max_ii < 0) || ((ch[i].qe<=max_dis+ch[max_ii].qe) && ((f[max_ii] peak_sc) || (f[i] == peak_sc || e[i] > peak_e)) { - peak_sc = f[i]; peak_e = e[i]; peak_i = i; - } - // li->sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); - // sv[i] = *li; - // fprintf(stderr, "##(%ld) %u\t%u\t%c\tutg%.6d%c(%u)\t%u\t%u\tmm_idx:%ld\tmm_sc:%ld\n", i, li->qs, li->qe, "+-"[li->rev], - // (int32_t)(li->tn)+1, "lc"[uref->ug->u.a[li->tn].circ], uref->ug->u.a[li->tn].len, li->ts, li->te, mm_idx, mm_sc); - // track[i] = push_sc_pre(mm_sc, mm_idx); - // li->sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); sv[i] = *li; - } - - if(peak_i < 0) return 0; - - uint64_t qs, qgap = 0, ts, tgap = 0, eqs = (uint64_t)-1, eqe = (uint64_t)-1, ea_n = ea->n; - i = peak_i; *res = ch[i]; - res->qn = ((peak_sc>UINT32_MAX)?(UINT32_MAX):(peak_sc)); - res->sec = 0; qs = res->qs; ts = res->ts; - - // memset(er, 0, sizeof((*er))); er->qs = er->qe = er->ts = er->te = (uint32_t)-1; - // er->qn = ((peak_e>UINT32_MAX)?(UINT32_MAX):(peak_e)); - - ///has been sorted by qe && te - while (i >= 0) { - if(ch[i].qe >= qs) { - if(ch[i].qs < qs) qs = ch[i].qs; - } else { - qgap += qs - ch[i].qe; - qs = ch[i].qs; - } - - if(ch[i].te >= ts) { - if(ch[i].ts < ts) ts = ch[i].ts; - } else { - tgap += ts - ch[i].te; - ts = ch[i].ts; - } - - if(ch[i].el || ch[i].qn == RC_0 || ch[i].qn == RC_1) {///reliable - if ((ea->n > ea_n) && (ch[i].qe >= (ea->a[ea->n-1]>>32))) { - if(ch[i].qs < (ea->a[ea->n-1]>>32)) { - eqs = ch[i].qs; eqe = (uint32_t)(ea->a[ea->n-1]); - ea->a[ea->n-1] = eqs << 32; ea->a[ea->n-1] |= eqe; - } - } else { - eqs = ch[i].qs; eqe = ch[i].qe; eqs <<= 32; eqs |= eqe; - kv_push(uint64_t, *ea, eqs); - // ea->a[ea->n-1] = eqs << 32; ea->a[ea->n-1] |= eqe; - } - } - - if(ch[i].qs < res->qs) res->qs = ch[i].qs; - if(ch[i].qe > res->qe) res->qe = ch[i].qe; - if(ch[i].ts < res->ts) res->ts = ch[i].ts; - if(ch[i].te > res->te) res->te = ch[i].te; - // if(qid == 2 && qlen == 112183461 && ch[i].tn == 30 && tlen == 24761445) { - // fprintf(stderr, "-(%ld)[M::%s] h2tg%.6u%c\t%ld\t%u\t%u\t%c\th1tg%.6u%c\t%ld\t%u\t%u\tsec(%u)\tel(%u)\tf(%u)\n", i, __func__, - // qid+1, "lc"[0], qlen, ch[i].qs, ch[i].qe, "+-"[ch[i].rev], ch[i].tn+1, "lc"[0], tlen, ch[i].ts, ch[i].te, ch[i].sec, ch[i].el, ch[i].qn); - // } else if(ch[i].tn == 2 && tlen == 112183461 && ch[i].qn == 30 && qlen == 24761445) { - // fprintf(stderr, "-(%ld)[M::%s] h1tg%.6u%c\t%ld\t%u\t%u\t%c\th2tg%.6u%c\t%ld\t%u\t%u\tsec(%u)\tel(%u)\tf(%u)\n", i, __func__, - // qid+1, "lc"[0], qlen, ch[i].qs, ch[i].qe, "+-"[ch[i].rev], ch[i].tn+1, "lc"[0], tlen, ch[i].ts, ch[i].te, ch[i].sec, ch[i].el, ch[i].qn); - // } - i = p[i]; - } - ////0x3fffffff - // if(qgap > 0x3fffffff || tgap > 0x3fffffff) { - // ea->n = ea_n; return 0; - // } - - adjust_rev_tse(res, tlen, &rts, &rte); - res->ts = rts; res->te = rte; - extend_end_coord(NULL, res, qlen, tlen, &rqs, &rqe, &rts, &rte); - qgap += (rqe - rqs) - (res->qe - res->qs); - tgap += (rte - rts) - (res->te - res->ts); - - // if(qid == 2 && qlen == 112183461 && ch[0].tn == 30 && tlen == 24761445) { - // fprintf(stderr, "+(%ld)[M::%s] h2tg%.6u%c\t%ld\t%ld(%u)\t%ld(%u)\t%c\th1tg%.6u%c\t%ld\t%ld(%u)\t%ld(%u)\tqgap(%ld)\ttgap(%ld)\n", i, __func__, - // qid+1, "lc"[0], qlen, rqs, res->qs, rqe, res->qe, "+-"[ch[0].rev], ch[0].tn+1, "lc"[0], tlen, rts, res->ts, rte, res->te, qgap, tgap); - // } else if(ch[i].tn == 2 && tlen == 112183461 && ch[0].qn == 30 && qlen == 24761445) { - // fprintf(stderr, "+(%ld)[M::%s] h2tg%.6u%c\t%ld\t%ld(%u)\t%ld(%u)\t%c\th1tg%.6u%c\t%ld\t%ld(%u)\t%ld(%u)\tqgap(%ld)\ttgap(%ld)\n", i, __func__, - // qid+1, "lc"[0], qlen, rqs, res->qs, rqe, res->qe, "+-"[ch[0].rev], ch[0].tn+1, "lc"[0], tlen, rts, res->ts, rte, res->te, qgap, tgap); - // } - - // if(qgap > 0x3fffffff || tgap > 0x3fffffff) { - // ea->n = ea_n; return 0; - // } - if((qgap > ((rqe-rqs)*unmatch_max)) || (tgap > ((rte-rts)*unmatch_max))) { - ea->n = ea_n; return 0; - } - - double qrate = ((double)((rqe-rqs)-qgap))/((double)(rqe-rqs)); - double trate = ((double)((rte-rts)-tgap))/((double)(rte-rts)); - double mrate = MIN(qrate, trate); if(mrate < 0) mrate = 0; - res->qn *= mrate; - if(res->qn <= 0) { - ea->n = ea_n; return 0; - } - - res->qs = rqs; res->qe = rqe; res->ts = rts; res->te = rte; - res->sec = (0x3fffffff); - if(ea->n > ea_n) { - uint64_t *a = ea->a + ea_n, an = ea->n - ea_n, ai, an1 = an>>1; - for(ai = 0; ai < an1; ai++) { - qs = a[ai]; a[ai] = a[an - ai - 1]; a[an - ai - 1] = qs; - } - res->sec = ea->n; kv_push(uint64_t, *ea, an); - } - - return 1; -} - -void ctg_trans_gp_chain(uint32_t qid, kv_ul_ov_t *res, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, int64_t qlen, Chain_Data* dp, ma_ug_t *ref, uint32_t is_self, asg64_v *b, double unmatch_max) -{ - uint64_t k, l, m = 0, rn = res->n; ul_ov_t rr; uint32_t avid = ((is_self)?(qid):((uint32_t)-1)); - for (k = 0; k < rn; k++) { - res->a[k].tn <<= 1; res->a[k].tn |= res->a[k].rev; - } - radix_sort_ul_ov_srt_tn(res->a, res->a + rn); - - for (k = 1, l = 0, b->n = 0; k <= rn; k++) { - if((k == rn) || ((res->a[l].tn>>1) != (res->a[k].tn>>1))) { - // fprintf(stderr, "+[M::%s]\tutg%.6ul\n", __func__, (res->a[l].tn>>1) + 1); - if(((res->a[l].tn>>1) != avid) && (linear_ctg_trans_chain_dp(qid, res->a+l, k-l, uref, uopt, bw, diff_ec_ul, /**0.333333**/0.4, unmatch_max, qlen, ref->u.a[(res->a[l].tn>>1)].len, UG_SKIP_N, UG_ITER_N, UG_DIS_N, dp, &rr, b))) { - res->a[m++] = rr; - // fprintf(stderr, "-[M::%s]\tutg%.6ul\n", __func__, rr.tn + 1); - } - l = k; - } - } - res->n = m; - - // for (k = 0; k < res->n; k++) { - // fprintf(stderr, "[M::%s]\tutg%.6ul(len::%ld)\tq::[%u, %u)\t%c\tutg%.6ul(len::%u)\tt::[%u, %u)\tel::%u\ttp::%u\n", __func__, qid + 1, qlen, res->a[k].qs, res->a[k].qe, "+-"[res->a[k].rev], res->a[k].tn+1, ref->u.a[res->a[k].tn].len, res->a[k].ts, res->a[k].te, res->a[k].el, res->a[k].qn); - // } -} - - -uint64_t cal_reliable_ovlp(ul_ov_t *z, asg64_v *in, uint64_t s, uint64_t e) -{ - if(z->sec >= in->n) return 0; - uint64_t k, zs, ze, os, oe, ovq, l = 0; - for (k = z->sec - in->a[z->sec]; k < z->sec; k++) { - zs = (in->a[k]>>32); ze = ((uint32_t)in->a[k]); - if(zs >= e) break; - if(ze <= s) continue; - os = MAX(s, zs); oe = MIN(e, ze); - ovq = ((oe > os)? (oe - os):0); - l += ovq; - } - return l; -} - - -uint64_t filter_ctg_trans(uint32_t qid, ma_ug_t *qry, ma_ug_t *ref, kv_ul_ov_t *aln, asg64_v *aln_e, asg64_v *srt, double reliable_rate, uint64_t reliable_len, double sec_rate, uint64_t sec_bd, double sec_sc, uint64_t soff, uint32_t is_self) -{ - if(aln->n <= 0) return 0; - - uint64_t k, an, *ss, *hs, *bu, *wu, clen, m, wm, z, l, wl, le, os, oe, ovq; ul_ov_t *cz, *mz; uint32_t sce[2]; sce[0] = 0; sce[1] = 1; - for (k = 0; k < aln->n; k++) { - aln->a[k].el = 0; clen = 0; - if((!is_self) || (sce[(qida[k].tna[k].sec < aln_e->n) {///has reliable regions - for (z = aln->a[k].sec - aln_e->a[aln->a[k].sec]; z < aln->a[k].sec; z++) { - clen += ((uint32_t)aln_e->a[z]) - (aln_e->a[z]>>32); - } - } - if((clen > reliable_len) && (clen > ((aln->a[k].qe - aln->a[k].qs)*reliable_rate))) { - aln->a[k].el = 1; - } - } - aln->a[k].qn = ((uint32_t)-1) - aln->a[k].qn; - - // if(qid == 2 && qry->u.a[qid].len == 112183461) {///h2tg000003l - // fprintf(stderr, "+[M::%s] h2tg%.6u%c\t%u\t%u\t%u\t%c\th1tg%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, - // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], - // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); - // } else if(qid == 30 && qry->u.a[qid].len == 24761445) {///h1tg000031l - // fprintf(stderr, "+[M::%s] h1tg%.6u%c\t%u\t%u\t%u\t%c\th12g%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, - // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], - // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); - // } else if(aln->a[k].tn == 2 && ref->u.a[aln->a[k].tn].len == 112183461) {///h2tg000003l - // fprintf(stderr, "+[M::%s] h1tg%.6u%c\t%u\t%u\t%u\t%c\th12g%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, - // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], - // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); - // } else if(aln->a[k].tn == 30 && ref->u.a[aln->a[k].tn].len == 24761445) { - // fprintf(stderr, "+[M::%s] h2tg%.6u%c\t%u\t%u\t%u\t%c\th1tg%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, - // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], - // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); - // } - } - if(aln->n > 1) radix_sort_ul_ov_srt_qn(aln->a, aln->a + aln->n);///qn->score - for (k = 0; k < aln->n; k++) aln->a[k].qn = ((uint32_t)-1) - aln->a[k].qn; - - an = aln->n; an <<= 2; - srt->n = 0; kv_resize(uint64_t, *srt, an); - for (k = 0; k < aln->n; k++) { - srt->a[srt->n] = aln->a[k].qs; - srt->a[srt->n] <<= 32; - srt->a[srt->n] |= k; - srt->n++; - } - - ss = srt->a; hs = ss + srt->n; bu = hs + srt->n; wu = bu + srt->n; - radix_sort_gfa64(ss, ss + aln->n); - for (k = 0; k < aln->n; k++) { - ss[k] = (uint32_t)ss[k]; hs[ss[k]] = k; - } - for (k = 0; k < aln->n; k++) { - if(aln->a[k].el) continue; - cz = &(aln->a[k]); clen = (cz->qe-cz->qs) * sec_rate; m = wm = 0; - - for (z = l = wl = le = 0; z < aln->n; z++) { - if(z == hs[k]) { - assert(ss[z] == k); - continue; - } - if(ss[z] > k) continue;///smaller nw than a[k] - mz = &(aln->a[ss[z]]); - if(mz->qs >= cz->qe) break; - if(mz->tn == ((uint32_t)-1)) continue;///has been deleted - if((!(mz->el)) && (cz->qn > (mz->qn*0.9))) continue; - os = MAX(cz->qs, mz->qs); oe = MIN(cz->qe, mz->qe); - ovq = ((oe > os)? (oe - os):0); - if(!ovq) continue; - // if(is_connect_arc(cz, mz, s->ug, 0.04) || is_connect_arc(mz, cz, s->ug, 0.04)) continue; - - if((m > 0) && (((uint32_t)bu[m-1]) >= os)) { - if(oe > ((uint32_t)bu[m-1])) { - le += cal_reliable_ovlp(cz, aln_e, ((uint32_t)bu[m-1]), oe); - l += (oe - ((uint32_t)bu[m-1])); - bu[m-1] += (oe - ((uint32_t)bu[m-1])); - } - } else { - le += cal_reliable_ovlp(cz, aln_e, os, oe); - l += oe - os; - bu[m] = os; bu[m] <<= 32; bu[m] |= oe; m++; - } - - if((wm > 0) && (((uint32_t)wu[wm-1]) >= mz->qs)) { - if(mz->qe > ((uint32_t)wu[wm-1])) { - wl += (mz->qe - ((uint32_t)wu[wm-1])); - wu[wm-1] += (mz->qe - ((uint32_t)wu[wm-1])); - } - } else { - wl += mz->qe - mz->qs; - wu[wm] = mz->qs; wu[wm] <<= 32; wu[wm] |= mz->qe; wm++; - } - - if((l > 0) && (l > sec_bd) && (le <= l*0.5)) { - if((l>=clen) || (l>=(wl*sec_rate))) { - ///sc is small enough - if(cz->qn <= (mz->qn*sec_sc)) { - cz->tn = ((uint32_t)-1); - break; - } - } - } - } - } - - for (k = m = 0; k < aln->n; k++) { - if(aln->a[k].tn == ((uint32_t)-1)) continue; - // if(qid == 2 && qry->u.a[qid].len == 112183461) {///h2tg000003l - // fprintf(stderr, "-[M::%s] h2tg%.6u%c\t%u\t%u\t%u\t%c\th1tg%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, - // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], - // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); - // } else if(qid == 30 && qry->u.a[qid].len == 24761445) {///h1tg000031l - // fprintf(stderr, "-[M::%s] h1tg%.6u%c\t%u\t%u\t%u\t%c\th12g%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, - // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], - // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); - // } else if(aln->a[k].tn == 2 && ref->u.a[aln->a[k].tn].len == 112183461) {///h2tg000003l - // fprintf(stderr, "-[M::%s] h1tg%.6u%c\t%u\t%u\t%u\t%c\th12g%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, - // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], - // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); - // } else if(aln->a[k].tn == 30 && ref->u.a[aln->a[k].tn].len == 24761445) { - // fprintf(stderr, "-[M::%s] h2tg%.6u%c\t%u\t%u\t%u\t%c\th1tg%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, - // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], - // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); - // } - aln->a[m++] = aln->a[k]; - } - aln->n = m; - // radix_sort_ul_ov_srt_qs(aln->a, aln->a + aln->n); - return aln->n; -} - -void push_ctg_trans_res(uint32_t id, kv_ul_ov_t *in, kv_ul_ov_t *ou) -{ - uint32_t k; - kv_resize(ul_ov_t, *ou, ou->n + in->n); - for (k = 0; k < in->n; k++) { - in->a[k].sec = ((in->a[k].qn>=(0x3fffffff))?(0x3fffffff):(in->a[k].qn)); - in->a[k].qn = id; kv_push(ul_ov_t, *ou, in->a[k]); - } -} - -uint32_t direct_ctg_trans_chain(mg_tbuf_t *b, uint32_t id, glchain_t *ll, gdpchain_t *gdp, st_mt_t *sps, haplotype_evdience_alloc *hap, const ul_idx_t *uref, const ug_opt_t *uopt, -int64_t bw, double diff_ec_ul, int64_t max_skip, int64_t ulid, Chain_Data* dp, ma_ug_t *qry, scaf_res_t *qry_sc, ma_ug_t *ref, scaf_res_t *ref_sc, ma_ug_t *gfa, bubble_type *bub, kv_u_trans_t *ta, const asg_t *rg, uint64_t soff, uint64_t is_exact) -{ - // res->bb.n = 0; - // if(ulid != 86660) return 0; - kv_ul_ov_t *idx = &(ll->lo), *init = &(ll->tk); ///int64_t max_idx; - asg64_v b0, b1; uint32_t is_self = (qry?0:1); idx->n = 0; - - cl_trans_gen(id, qry?qry->u.a[id].len:ref->u.a[id].len, qry_sc?&(qry_sc->a[id]):&(ref_sc->a[id]), idx, uref, ref, ref_sc, gfa, bub, ta, is_self, is_exact); - if(idx->n == 0) return 0; - - copy_asg_arr(b0, (*sps)); - ctg_trans_gp_chain(id, idx, uref, uopt, bw, diff_ec_ul, qry?qry->u.a[id].len:ref->u.a[id].len, dp, ref, is_self, &b0, ((is_exact)?(0.5):(0.666666))); - copy_asg_arr((*sps), b0); - if(idx->n == 0) return 0; - - copy_asg_arr(b0, (*sps)); copy_asg_arr(b1, ll->srt.a); - filter_ctg_trans(id, qry, ref, idx, &b0, &b1, 0.5, 10000, /**0.333333**/0.85, 10000, 0.3, soff, is_self); - copy_asg_arr((*sps), b0); copy_asg_arr(ll->srt.a, b1); - if(idx->n == 0) return 0; - - push_ctg_trans_res(id, idx, init); - - /** - // gl_rg2ug_gen(rch, idx, uref, 1, 2, ulid); - ctg_rg2ug_gen(rch, idx, uref); - - // uint32_t k; - // fprintf(stderr, "[M::%s] rch->len::%u, rch->n::%u, idx->n::%u\n", __func__, (uint32_t)rch->len, (uint32_t)rch->n, (uint32_t)idx->n); - // for (k = 0; k < idx->n; k++) { - // fprintf(stderr, "[k->%u::utg%.6u%c(len->%u::n->%u)]\tq::[%u, %u)\t%c\tt::[%u, %u)\n", - // k, (idx->a[k].tn>>1) + 1, "lc"[uref->ug->u.a[(idx->a[k].tn>>1)].circ], uref->ug->u.a[(idx->a[k].tn>>1)].len, idx->a[k].sec, - // idx->a[k].qs, idx->a[k].qe, "+-"[idx->a[k].rev], idx->a[k].ts, idx->a[k].te); - // } - - // for (k = 0; k < idx->n; k++) { - // fprintf(stderr, "utg%.6u%c,", (idx->a[k].tn>>1)+1, "lc"[uref->ug->u.a[(idx->a[k].tn>>1)].circ]); - // } - // fprintf(stderr, "\n"); - - if(idx->n == 0) return 0; - ///generate linear chains - gen_linear_chains_ctg(idx, init, uref, uopt, bw, diff_ec_ul, rch->len, dp); - - if(idx->n == 0) return 0; - - dump_linear_chain(uref->ug, idx, &(gdp->l), rch->len, ulid); - if(gdp->l.n == 0) return 0; - - kv_resize(uint64_t, ll->srt.a, gdp->l.n); - max_idx = ctg_chain_graph(b->km, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), - &(gdp->path), rch->len, uopt, G_CHAIN_BW, N_GCHAIN_RATE, ll->srt.a.a, sps, dp, UG_SKIP_GRAPH_N, UG_ITER_N, UG_DIS_N*100); - - //sps -> idx; (gdp->l) -> alignments - if(max_idx >= 0) { - max_idx = select_max_ctg_chain(b->km, uref, ulid, sps, &(gdp->l), &(ll->tk), uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), &(gdp->swap)); - if(max_idx) { - push_ctg_res(res, &(gdp->swap)); - return 1; - } - } - **/ - - return 0; -} - - -uint32_t refine_rid_chain(const asg_t *rg, mg_tbuf_t *b, ul_vec_t *rch, uint64_t ulid) -{ - if(rch->bb.n == 1 && rch->bb.a[0].base) return 1;///no alignment - if(rch->bb.n == 0) return 1;///no alignment - uint64_t i, m, c[2], nc, cc/**, ni[2]**/; - for (i = c[1] = rch->bb.n-1, m = nc = 0; i != (uint32_t)-1; i = rch->bb.a[i].pidx) { - m++; c[0] = i; if(!(rg->seq[rch->bb.a[i].hid].del)) nc++; - } - if(m == rch->bb.n) {///only one chain - if(nc == m || nc == 0) return 1;///all alignments are non-contained/contained - cc = 0; - for (i = c[1]; i != (uint32_t)-1; i = rch->bb.a[i].pidx) { - if(rg->seq[rch->bb.a[i].hid].del) cc++; - else break; - } - // ni[1] = i; - for (i = c[0]; i != (uint32_t)-1; i = rch->bb.a[i].aidx) { - if(rg->seq[rch->bb.a[i].hid].del) cc++; - else break; - } - // ni[0] = i; - if(nc + cc == m) return 1; - // assert(ni[1] > ni[0] && ni[0] != (uint32_t)-1 && ni[1] != (uint32_t)-1); - return 2; - } - return 0; -} - -static void worker_for_ul_gchains_alignment(void *data, long i, int tid) -{ - ul_vec_t *p = &(UL_INF.a[i]); - utepdat_t *s = (utepdat_t*)data; uint32_t ff; - ff = refine_rid_chain(s->rg, s->buf[tid], p, i); - // fprintf(stderr, "[M::%s::%.*s(id:%ld), len:%u] ff:%u\n", __func__, - // UL_INF.nid.a[i].n, UL_INF.nid.a[i].a, i, p->rlen, ff); - if(ff == 1) return; - // if(p->dd == 1) return; //fully aligned - // if(p->bb.n == 1 && p->bb.a[0].base) return;///no alignment - // if(p->bb.n == 0) return;///no alignment - s->hab[tid]->num_read_base++; - s->hab[tid]->num_correct_base += direct_gchain(s->buf[tid], p, &(s->ll[tid]), &(s->gdp[tid]), &(s->sps[tid]), &(s->hab[tid]->hap), s->uu, s->uopt, G_CHAIN_BW, s->opt->diff_ec_ul, UG_SKIP, i, &(s->hab[tid]->clist.chainDP), s->rg, ((ff==2)?1:0)); - // gl_chain_refine_advance(&b->olist, &b->correct, &b->hap, bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, km); -} - -static void worker_for_ctg_gchains_alignment(void *data, long i, int tid) -{ - utepdat_t *s = (utepdat_t*)data; ma_utg_t *q = &(s->ug->u.a[i]); s->rsc->a[i].bb.n = 0; - - s->hab[tid]->num_read_base++; - s->hab[tid]->num_correct_base += direct_gchain_scaf(s->buf[tid], q, &(s->ll[tid]), &(s->gdp[tid]), &(s->sps[tid]), &(s->hab[tid]->hap), s->uu, s->uopt, G_CHAIN_BW, s->opt->diff_ec_ul, UG_SKIP, i, &(s->hab[tid]->clist.chainDP), s->rg, &(s->rsc->a[i])); -} - -static void worker_for_ctg_trans_alignment(void *data, long i, int tid) -{ - ctdat_t *c = (ctdat_t*)data; - utepdat_t *s = c->s; - // ul_vec_t *q = &(c->qry_sc->a[i]); - - s->hab[tid]->num_read_base++; - s->hab[tid]->num_correct_base += direct_ctg_trans_chain(s->buf[tid], i, &(s->ll[tid]), &(s->gdp[tid]), &(s->sps[tid]), &(s->hab[tid]->hap), s->uu, s->uopt, G_CHAIN_BW, s->opt->diff_ec_ul, UG_SKIP, i, &(s->hab[tid]->clist.chainDP), - c->qry, c->qry_sc, c->ref, c->ref_sc, c->gfa, c->bub, c->ta, s->rg, c->soff, c->is_exact); -} - -void rm_dup_aln(u_trans_t *u, uint64_t u_n, asg64_v *b, double dup_cut) -{ - if(u_n <= 0) return; - uint64_t k, m, s, e, dp, old_dp, z, zs, ze, l, os, oe, ovq, cut; u_trans_t t; - b->n = 0; - for (k = 0; k < u_n; k++) { - s = u[k].qs; e = u[k].qe; u[k].occ = 0; - kv_push(uint64_t, *b, (s<<1)); - kv_push(uint64_t, *b, (e<<1|1)); - } - radix_sort_gfa64(b->a, b->a + b->n); - - for (k = dp = old_dp = m = 0, s = e = (uint64_t)-1; k < b->n; k++) { - old_dp = dp; - //if a[j] is qe - if (b->a[k]&1) --dp; - else ++dp; - - if (old_dp < 2 && dp >= 2) {///old_dp < dp, b.a[k] is qs - s = b->a[k]>>1; - } else if (old_dp >= 2 && dp < 2) {///old_dp > min_dp, b.a[k] is qe - e = b->a[k]>>1; - if(e > s) b->a[m++] = (s<<32)|e;///non-unique region - } - } - - b->n = m; - for (k = m = 0; k < u_n; k++) { - l = 0; s = u[k].qs; e = u[k].qe; - cut = (e - s)*dup_cut; - if(!(u[k].f)) {//unreliable - for (z = 0; z < b->n; z++) { - zs = (b->a[z]>>32); ze = ((uint32_t)b->a[z]); - if(zs >= e) break; - if(ze <= s) continue; - os = MAX(s, zs); oe = MIN(e, ze); - ovq = ((oe > os)? (oe - os):0); - l += ovq; - if(l > cut) break; - } - } - if(((l <= 0) || (l <= cut)) && (l < (e - s))) { - if(m != k) { t = u[m]; u[m] = u[k]; u[k] = t;} - m++; - } - } - - for (k = m; k < u_n; k++) u[k].del = 1;///delete - - for (k = b->n = 0; k < m; k++) { - dp = u[k].nw; dp <<= 32; dp |= k; kv_push(uint64_t, *b, dp); - } - radix_sort_gfa64(b->a, b->a + b->n); old_dp = 0; - for (k = 0; k < b->n; k++) { - assert(!u[((uint32_t)b->a[k])].del); - for (z = 0; z < b->n; z++) { - if(k == z) continue; - if(u[((uint32_t)b->a[z])].del) continue; - if(u[((uint32_t)b->a[k])].qs >= u[((uint32_t)b->a[z])].qs && u[((uint32_t)b->a[k])].qe <= u[((uint32_t)b->a[z])].qe) break; - } - if(z < b->n) { - u[((uint32_t)b->a[k])].del = 1; old_dp++; - } - } - - if(old_dp) { - for (k = m = 0; k < u_n; k++) { - if(u[k].del) continue; - if(m != k) { t = u[m]; u[m] = u[k]; u[k] = t;} - m++; - } - } - - - ///for debug is there is any contained overlaps in u[0, m) - for (k = 0; k < m; k++) { - for (z = 0; z < m; z++) { - if(k == z) continue; - if(u[k].qs >= u[z].qs && u[k].qe <= u[z].qe) break; - } - assert(z >= m); - } -} - -static void worker_for_ctg_trans_order(void *data, long i, int tid) -{ - ctdat_t *c = (ctdat_t*)data; utepdat_t *s = c->s; asg64_v b; - u_trans_t *a = NULL, *r_a = NULL, t; uint64_t n, r_n, k, z, m; - - if(c->mm == 0) { - copy_asg_arr(b, (s->sps[tid])); - rm_dup_aln(u_trans_a(*(c->ta), i), u_trans_n(*(c->ta), i), &b, 0.25); - copy_asg_arr((s->sps[tid]), b); - } else if(c->mm == 1) { - a = u_trans_a(*(c->ta), i); n = u_trans_n(*(c->ta), i); - for (k = 0; k < n; k++) { - if(a[k].tn < a[k].qn) continue; - r_a = u_trans_a(*(c->ta), a[k].tn); r_n = u_trans_n(*(c->ta), a[k].tn); - for(z = 0; (z < r_n) && (r_a[z].tn != a[k].qn); z++); - assert(z < r_n); - // if(a[k].del || r_a[z].del) { - // a[k].del = r_a[z].del = 1; - // } - ///discard too short overlaps - if((!a[k].f) || (!r_a[z].f)) { - if((a[k].qe - a[k].qs <= asm_opt.self_scaf_min) || (a[k].te - a[k].ts <= asm_opt.self_scaf_min)) { - a[k].del = r_a[z].del = 1; - } else if((r_a[z].qe - r_a[z].qs <= asm_opt.self_scaf_min) || (r_a[z].te - r_a[z].ts <= asm_opt.self_scaf_min)) { - a[k].del = r_a[z].del = 1; - } - } - - if(a[k].del != r_a[z].del) { - a[k].del = r_a[z].del = 0; - a[k].occ = r_a[z].occ = (uint32_t)-1; - } - } - } else { - a = u_trans_a(*(c->ta), i); n = u_trans_n(*(c->ta), i); - for (k = m = 0; k < n; k++) { - if((a[k].occ != (uint32_t)-1)) { - if(m != k) {t = a[k]; a[k] = a[m]; a[m] = t;} - m++; - } - } - radix_sort_u_trans_qs0(a, a + m); - radix_sort_u_trans_qs0(a + m, a + n); - a = a + m; n = n - m; - if(n) {//sort and merge unreliable regions - for (k = 0; k < n; k++) a[k].del = 1; - for (k = m = 0; k < n; k++) { - if((m > 0) && (a[m-1].qe >= a[k].qs)) { - if(a[k].qe > a[m-1].qe) a[m-1].qe = a[k].qe; - } else { - a[m++] = a[k]; - } - } - - for(k = m; k < n; k++) {///not useful anymore - a[k].qn = a[k].qs = a[k].qe = (uint32_t)-1; - a[k].tn = a[k].ts = a[k].te = (uint32_t)-1; - } - } - } - -} - -uint32_t inline is_rg_connect(const asg_t *rg, uint32_t v, uint32_t w) -{ - uint32_t nv = asg_arc_n(rg, v), i; - asg_arc_t *av = asg_arc_a(rg, v); - for (i = 0; i < nv; i++) { - if((!(av[i].del)) && (av[i].v == w)) return 1; - } - return 0; -} - -uint32_t refine_contain_consensus_chain(const asg_t *rg, ul_vec_t *rch, R_to_U *ri, asg64_v *bu, uint64_t ulid) -{ - bu->n = 0; - if(rch->bb.n == 1 && rch->bb.a[0].base) return bu->n;///no alignment - if(rch->bb.n == 0) return bu->n;///no alignment - uint64_t i, m, nc, occ, is_end; int64_t k, kn; - kv_resize(uint64_t, *bu, rch->bb.n); - memset(bu->a, -1, (sizeof((*(bu->a)))*rch->bb.n)); - for (k = rch->bb.n-1; k >= 0; k--) { - // if(ulid == 2 || ulid == 46 || ulid == 475 || ulid == 3274 || ulid == 3360) { - // fprintf(stderr, "[M::%s::] ulid::%lu, k::%ld, q::[%u, %u), t::[%u, %u), del::%u, pidx::%u, pconn::%u, aidx::%u, aconn::%u\n", - // __func__, ulid, k, - // rch->bb.a[k].qs, rch->bb.a[k].qe, rch->bb.a[k].ts, rch->bb.a[k].te, rg->seq[rch->bb.a[k].hid].del, - // rch->bb.a[k].pidx, - // ((rch->bb.a[k].pidx!=((uint32_t)-1))&&is_rg_connect(rg, (uint64_t)((rch->bb.a[rch->bb.a[k].pidx].hid<<1)|(rch->bb.a[rch->bb.a[k].pidx].rev)), (uint64_t)((rch->bb.a[k].hid<<1)|(rch->bb.a[k].rev))))?1:0, - // rch->bb.a[k].aidx, - // ((rch->bb.a[k].aidx!=((uint32_t)-1))&&is_rg_connect(rg, (uint64_t)((rch->bb.a[k].hid<<1)|(rch->bb.a[k].rev)),(uint64_t)((rch->bb.a[rch->bb.a[k].aidx].hid<<1)|(rch->bb.a[rch->bb.a[k].aidx].rev))))?1:0); - // } - - - - if(bu->a[k] != ((uint64_t)-1)) continue; - is_end = 0; - if((rch->bb.a[k].aidx == ((uint32_t)-1)) && (rch->bb.a[k].pidx != ((uint32_t)-1))) {///the end of a chain - is_end = 1; - } else if((rch->bb.a[k].aidx != ((uint32_t)-1)) && (rch->bb.a[k].pidx != ((uint32_t)-1))) { - if(!is_rg_connect(rg, (uint64_t)((rch->bb.a[k].hid<<1)|(rch->bb.a[k].rev)), - (uint64_t)((rch->bb.a[rch->bb.a[k].aidx].hid<<1)|(rch->bb.a[rch->bb.a[k].aidx].rev)))) { - is_end = 1; - } - } - if(!is_end) continue; - i = m = k; occ = 0; - while (i != ((uint32_t)-1)) { - //assert(bu->a[i] == ((uint64_t)-1)); - if(rg->seq[rch->bb.a[i].hid].del) { - if(occ > 1) { - bu->a[m] = occ; - // if(debug_out) { - // fprintf(stderr, "+[M::%s::] ulid::%lu, k::%ld, m::%lu, occ::%lu\n", - // __func__, ulid, k, m, occ); - // } - } - // assert(i!=m); - bu->a[i] = 0; m = (uint32_t)-1; occ = 0; - } else { - if(m == (uint32_t)-1) m = i; - bu->a[i] = 0; occ++; - } - i = rch->bb.a[i].pidx; - if(i != ((uint32_t)-1)) { - if(!is_rg_connect(rg, (uint64_t)((rch->bb.a[i].hid<<1)|(rch->bb.a[i].rev)), - (uint64_t)((rch->bb.a[rch->bb.a[i].aidx].hid<<1)|(rch->bb.a[rch->bb.a[i].aidx].rev)))) { - i = ((uint32_t)-1); - } - } - } - - if(occ > 1) { - bu->a[m] = occ; - // if(debug_out) { - // fprintf(stderr, "+[M::%s::] ulid::%lu, k::%ld, m::%lu, occ::%lu\n", - // __func__, ulid, k, m, occ); - // } - } - } - - kn = rch->bb.n; - for (k = bu->n = 0; k < kn; k++) { - if((bu->a[k] == ((uint64_t)-1)) || (bu->a[k] == 0)) continue; - i = k; occ = nc = 0; - while (i != (uint32_t)-1) { - if(rg->seq[rch->bb.a[i].hid].del) break; - - occ++; if(is_contain_r((*ri), rch->bb.a[i].hid)) nc++; - - i = rch->bb.a[i].pidx; - if(i != ((uint32_t)-1)) { - if(!is_rg_connect(rg, (uint64_t)((rch->bb.a[i].hid<<1)|(rch->bb.a[i].rev)), - (uint64_t)((rch->bb.a[rch->bb.a[i].aidx].hid<<1)|(rch->bb.a[rch->bb.a[i].aidx].rev)))) { - i = ((uint32_t)-1); - } - } - } - // for (i = k, occ = nc = 0; (i != (uint32_t)-1) && (!rg->seq[rch->bb.a[i].hid].del); i = rch->bb.a[i].pidx) { - // occ++; if(is_contain_r((*ri), rch->bb.a[i].hid)) nc++; - // } - assert(occ == bu->a[k]); - if(nc) bu->a[bu->n++] = k; - // if(debug_out) { - // if(occ != rch->bb.n) { - // fprintf(stderr, "-[M::%s::] ulid::%lu, nc::%lu, occ::%lu, k::%ld, rch->bb.n::%u\n", - // __func__, ulid, nc, occ, k, (uint32_t)rch->bb.n); - // } - // } - } - return bu->n;///# chains have contained reads -} - -uint32_t extract_ccov(ma_hit_t *in, uc_block_t *rovlp, const asg_t *rg, ul_ov_t *res, uint32_t adjust_rev, int64_t min_ovlp, int64_t max_hang) -{ - uint64_t qn, tn; int32_t r = 1; asg_arc_t e; - qn = Get_qn((*in)); tn = Get_tn((*in)); - if(rg->seq[tn].del) return 0; - - r = ma_hit2arc(in, Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); - if(r != MA_HT_QCONT) return 0; ///qn is contained in tn - - uint64_t ori = in->rev, ts = rovlp->ts, te = rovlp->te, tl; - if(ori) { - ts = rg->seq[qn].len - rovlp->te; - te = rg->seq[qn].len - rovlp->ts; - } - - ts += in->ts; te += in->ts; - if(te <= ts) return 0; - tl = te - ts; tl = tl*0.01; if(tl > 8) tl = 8; - if((ts >= (rg->seq[tn].len+tl)) || (te >= (rg->seq[tn].len+tl))) return 0; - if(ts > rg->seq[tn].len) ts = rg->seq[tn].len; - if(te > rg->seq[tn].len) te = rg->seq[tn].len; - if(te <= ts) return 0; - - memset(res, 0, sizeof(*res)); - res->qn = 0; res->qs = rovlp->qs; res->qe = rovlp->qe; - res->tn = tn; res->ts = ts; res->te = te; - res->el = rovlp->el; res->rev = (rovlp->rev == ori?0:1); - if(adjust_rev && res->rev) {///for linear chaining - res->ts = rg->seq[tn].len - te; - res->te = rg->seq[tn].len - ts; - } - return 1; -} - -uint32_t extract_nccov(ma_hit_t *in, uc_block_t *rovlp, const asg_t *rg, ul_ov_t *res, uint32_t adjust_rev, int64_t min_ovlp, int64_t max_hang) -{ - uint64_t tn; int64_t os, oe, s_shift, e_shift, tt, qs, qe, ts, te; - tn = Get_tn((*in)); if(rg->seq[tn].del) return 0; - os = MAX(rovlp->ts, Get_qs((*in))); - oe = MIN(rovlp->te, Get_qe((*in))); - if(oe <= os) return 0; - - ///[os, oe) -> rovlp->t* - s_shift = get_offset_adjust(os-rovlp->ts, rovlp->te-rovlp->ts, rovlp->qe-rovlp->qs); - e_shift = get_offset_adjust(rovlp->te-oe, rovlp->te-rovlp->ts, rovlp->qe-rovlp->qs); - if(rovlp->rev) { - tt = s_shift; s_shift = e_shift; e_shift = tt; - } - qs = rovlp->qs + s_shift; qe = ((int64_t)rovlp->qe)-e_shift; - if(qs >= qe) return 0; - - ///[os, oe) -> in->q* - s_shift = get_offset_adjust(os-Get_qs((*in)), Get_qe((*in))-Get_qs((*in)), Get_te((*in))-Get_ts((*in))); - e_shift = get_offset_adjust(Get_qe((*in))-oe, Get_qe((*in))-Get_qs((*in)), Get_te((*in))-Get_ts((*in))); - if(in->rev) { - tt = s_shift; s_shift = e_shift; e_shift = tt; - } - ts = Get_ts((*in)) + s_shift; te = ((int64_t)Get_te((*in)))-e_shift; - if(ts >= te) return 0; - - memset(res, 0, sizeof(*res)); - res->qn = 0; res->qs = qs; res->qe = qe; - res->tn = tn; res->ts = ts; res->te = te; - res->el = rovlp->el; res->rev = ((rovlp->rev == in->rev)?0:1); - if(adjust_rev && res->rev) {///for linear chaining - res->ts = rg->seq[tn].len - te; - res->te = rg->seq[tn].len - ts; - } - - // fprintf(stderr, "\n[M::%s::id->%u::%c] q::[%u, %u), t::[%u, %u)\n", - // __func__, rovlp->hid, "+-"[rovlp->rev], rovlp->qs, rovlp->qe, rovlp->ts, rovlp->te); - // fprintf(stderr, "+[M::%s::] qn::%u, q::[%u, %u), %c, tn::%u, t::[%u, %u)\n", - // __func__, Get_qn((*in)), Get_qs((*in)), in->qe, "+-"[in->rev], in->tn, in->ts, in->te); - // fprintf(stderr, "-[M::%s::] qn::%u, q::[%u, %u), %c, tn::%u, t::[%u, %u)\n", - // __func__, res->qn, res->qs, res->qe, "+-"[res->rev], res->tn, res->ts, res->te); - return 1; -} - - -void collect_nc_ovlps(ul_vec_t *rch, uint32_t rch_i, kv_ul_ov_t *res, const ug_opt_t *uopt, const asg_t *rg, R_to_U *ri, int64_t ulid, uint64_t *mqs, uint64_t *mqe) -{ - uint64_t i, occ, nc, k; ma_hit_t_alloc* src; - int64_t min_ovlp = uopt->min_ovlp, max_hang = uopt->max_hang; ul_ov_t p; - res->n = occ = nc = 0; (*mqs) = (*mqe) = (uint64_t)-1; - i = rch_i; - // for (i = rch_i; (i != (uint32_t)-1) && (!rg->seq[rch->bb.a[i].hid].del); i = rch->bb.a[i].pidx) { - while(i != (uint32_t)-1) { - if(rg->seq[rch->bb.a[i].hid].del) break; - // if(ulid == 442462) { - // fprintf(stderr, "\n>>>[M::%s::i->%lu::id->%u::%.*s]\n", __func__, i, rch->bb.a[i].hid, - // (int)Get_NAME_LENGTH(R_INF, rch->bb.a[i].hid), Get_NAME(R_INF, rch->bb.a[i].hid)); - // fprintf(stderr, "*[M::%s::id->%u::%.*s]\tq::[%u, %u),\tt::[%u, %u),\tis_rev::%u,\tis_cr::%u\n", - // __func__, rch->bb.a[i].hid, - // (int)Get_NAME_LENGTH(R_INF, rch->bb.a[i].hid), Get_NAME(R_INF, rch->bb.a[i].hid), - // rch->bb.a[i].qs, rch->bb.a[i].qe, rch->bb.a[i].ts, rch->bb.a[i].te, rch->bb.a[i].rev, - // !!(is_contain_r((*(ri)), rch->bb.a[i].hid))); - // } - - if(is_contain_r((*ri), rch->bb.a[i].hid)) { - src = &(uopt->sources[rch->bb.a[i].hid]); - for (k = 0; k < src->length; k++) { - if(rg->seq[Get_tn(src->buffer[k])].del) continue;///tn must exist - // if(!extract_ccov(&(src->buffer[k]), &(rch->bb.a[i]), rg, &p, 1, min_ovlp, max_hang)) continue; - // if(ulid == 442462) { - // fprintf(stderr, "+[M::%s::id->%u::%.*s]\tq::[%u, %u),\tql::%u,\tt::[%u, %u),\ttl::%u,\tis_rev::%u,\tis_cr::%u\n", - // __func__, src->buffer[k].tn, - // (int)Get_NAME_LENGTH(R_INF, src->buffer[k].tn), Get_NAME(R_INF, src->buffer[k].tn), - // Get_qs(src->buffer[k]), Get_qe(src->buffer[k]), rg->seq[Get_qn(src->buffer[k])].len, - // Get_ts(src->buffer[k]), Get_te(src->buffer[k]), rg->seq[Get_tn(src->buffer[k])].len, - // src->buffer[k].rev, !!(is_contain_r((*(ri)), src->buffer[k].tn))); - // } - if(!extract_nccov(&(src->buffer[k]), &(rch->bb.a[i]), rg, &p, 1, min_ovlp, max_hang)) continue; - // if(ulid == 442462) { - // fprintf(stderr, "-[M::%s::id->%u::%.*s]\tq::[%u, %u),\tt::[%u, %u),\tis_rev::%u,\tis_cr::%u\n", - // __func__, p.tn, (int)Get_NAME_LENGTH(R_INF, p.tn), Get_NAME(R_INF, p.tn), - // p.qs, p.qe, p.ts, p.te, p.rev, !!(is_contain_r((*(ri)), p.tn))); - // // fprintf(stderr, "cc[M::%s::id->%u::%.*s] q::[%u, %u), t::[%u, %u), is_cr::%u, del::%u\n", - // // __func__, p.tn, (int)Get_NAME_LENGTH(R_INF, p.tn), Get_NAME(R_INF, p.tn), - // // p.qs, p.qe, p.ts, p.te, !!(is_contain_r((*(ri)), p.tn)), rg->seq[p.tn].del); - // } - p.el = 0; p.tn <<= 1; p.tn |= p.rev; p.qn = i;//for linear chain - kv_push(ul_ov_t, *res, p); - } - nc++; - } - ///push itself into the chain - memset(&p, 0, sizeof(p)); - p.qn = 0; p.qs = rch->bb.a[i].qs; p.qe = rch->bb.a[i].qe; - p.tn = rch->bb.a[i].hid; p.ts = rch->bb.a[i].ts; p.te = rch->bb.a[i].te; - p.el = 1; p.rev = rch->bb.a[i].rev; - if(p.rev) {///for linear chaining - p.ts = rg->seq[p.tn].len - rch->bb.a[i].te; - p.te = rg->seq[p.tn].len - rch->bb.a[i].ts; - } - p.el = 1; p.tn <<= 1; p.tn |= p.rev; p.qn = i;//for linear chain - kv_push(ul_ov_t, *res, p); - if(((*mqs) == ((uint64_t)-1)) || ((*mqs) > rch->bb.a[i].qs)) (*mqs) = rch->bb.a[i].qs; - if(((*mqe) == ((uint64_t)-1)) || ((*mqe) < rch->bb.a[i].qe)) (*mqe) = rch->bb.a[i].qe; - occ++; - - i = rch->bb.a[i].pidx; - if(i != ((uint32_t)-1)) { - if(!is_rg_connect(rg, (uint64_t)((rch->bb.a[i].hid<<1)|(rch->bb.a[i].rev)), - (uint64_t)((rch->bb.a[rch->bb.a[i].aidx].hid<<1)|(rch->bb.a[rch->bb.a[i].aidx].rev)))) { - i = ((uint32_t)-1); - } - } - } - assert(occ > 1 && nc > 0); -} - - -inline int64_t comput_rlinear_sc(ul_ov_t *li, ul_ov_t *lj, int64_t jidx, int32_t *bq, int32_t *bt, double diff_ec_ul, int64_t bw) -{ ///li is the suffix of lj; sorted by qe, so li->qe >= lj->qe, so li->te >= lj->te - if(li->te < lj->te) return INT32_MIN; - int64_t dq, dt, dd, mm, os, oe; - oe = MIN((li->qe), (lj->qe)); os = MAX((li->qs), (lj->qs)); - if(oe <= os) return INT32_MIN; - oe = MIN((li->te), (lj->te)); os = MAX((li->ts), (lj->ts)); - if(oe <= os) return INT32_MIN; - - dq = li->qe - lj->qs; dt = li->te - lj->ts; - dd = (dq>dt? dq-dt:dt-dq); - mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; - if(dd > mm) return INT32_MIN; - dq = (int64_t)li->qe - bq[jidx]; - dt = (int64_t)li->te - bt[jidx]; - if(dq < ((int64_t)(li->qe - li->qs))) dq = li->qe - li->qs; - if(dt < ((int64_t)(li->te - li->ts))) dt = li->te - li->ts; - return MIN(dq, dt); -} - -uint64_t linear_rchain_dp_adv(ul_ov_t *ch, int64_t ch_n, ul_ov_t *sv, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, const asg_t *rg, int64_t ulid) -{ ///all in[].el must be 1 - if(ch_n == 0) return 0; - int64_t i, j, k, sc, csc, mm_sc, mm_idx, its, ite, max; int32_t *f, *bq, *bt; - ul_ov_t *li = NULL, *lj = NULL; int64_t *p, *t, st, plus, max_ii, n_skip, end_j; - resize_Chain_Data(dp, ch_n, NULL); - t = dp->tmp; f = dp->score; p = dp->pre; bq = dp->indels; bt = dp->self_length; - - radix_sort_ul_ov_srt_qe(ch, ch + ch_n); - for (i = 1, j = 0; i <= ch_n; i++) { - if (i == ch_n || ch[i].qe != ch[j].qe) { - if(i - j > 1) radix_sort_ul_ov_srt_qs(ch+j, ch+i); - j = i; - } - } - - memset(t, 0, (ch_n*sizeof((*t)))); - for (i = st = plus = 0, max_ii = -1; i < ch_n; ++i) { - li = &(ch[i]); csc = MIN((li->qe-li->qs), (li->te-li->ts)); - mm_sc = /**csc**/-1; mm_idx = -1; n_skip = 0; end_j = -1; - st = (i= st; --j) { - lj = &(ch[j]); - if(lj->qe <= li->qs) break; - sc = comput_rlinear_sc(li, lj, j, bq, bt, diff_ec_ul, bw); ///should allow contain - if(sc == INT32_MIN) continue; - if(sc > mm_sc) { - mm_sc = sc, mm_idx = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == i) { - if (++n_skip > max_skip) - break; - } - if (p[j] >= 0) t[p[j]] = i; - } - end_j = j; - if (max_ii < 0 || (ch[i].qe>(ch[max_ii].qe+max_dis))) {//too long - max = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && (ch[i].qe<=(max_dis+ch[j].qe)); --j) { - if (max < f[j]) { - max = f[j], max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - lj = &(ch[max_ii]); - if(lj->qe > li->qs) { - sc = comput_rlinear_sc(li, lj, max_ii, bq, bt, diff_ec_ul, bw); ///should allow contain - if(sc != INT32_MIN) { - if(sc > mm_sc) { - mm_sc = sc; mm_idx = max_ii; - } - } - } - } - - if(mm_idx < 0) mm_sc = csc; - f[i] = mm_sc; p[i] = mm_idx; - bq[i] = li->qs; bt[i] = li->ts; - if(mm_idx >= 0) { - if(bq[i] > bq[mm_idx]) bq[i] = bq[mm_idx]; - if(bt[i] > bt[mm_idx]) bt[i] = bt[mm_idx]; - } - - if ((max_ii < 0) || ((ch[i].qe<=max_dis+ch[max_ii].qe) && (f[max_ii]sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); sv[i] = *li; - // if(ulid == 442462) { - // fprintf(stderr, "[M::%s::id->%u::%.*s]\tq::[%u, %u),\tt::[%u, %u),\tis_rev::%u\n", - // __func__, li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), - // li->qs, li->qe, li->ts, li->te, li->rev); - // } - - } - // radix_sort_gfa64i - for (i = 0; i < ch_n; ++i) { - t[i] = ((uint64_t)f[i])<<32; t[i] += i; bt[i] = 0; - } - radix_sort_gfa64i(t, t+ch_n); - int64_t n_u, z; - for (z = ch_n-1, n_u = 0; z >= 0; --z) { - k = (uint32_t)t[z]; - if(bt[k]) continue; - i = k; ch[n_u]=sv[i]; sc = f[i]; - for (;i>=0;) { - if(sv[i].qs < ch[n_u].qs) ch[n_u].qs = sv[i].qs; - if(sv[i].ts < ch[n_u].ts) ch[n_u].ts = sv[i].ts; - if(sv[i].qe > ch[n_u].qe) ch[n_u].qe = sv[i].qe; - if(sv[i].te > ch[n_u].te) ch[n_u].te = sv[i].te; - // ch[n_u].qn = i;//start idx of read alignment in chain - bt[i] = 1; i = p[i]; - } - adjust_rev_tse(&(ch[n_u]), rg->seq[ch[n_u].tn].len, &its, &ite); - ch[n_u].ts = its; ch[n_u].te = ite; ch[n_u].sec = (sc>0x3FFFFFFF?0x3FFFFFFF:sc); - ch[n_u].qn = 0; - n_u++; - } - return n_u; -} - - -void gen_linear_rchains(kv_ul_ov_t *res, kv_ul_ov_t *buf, const asg_t *rg, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, Chain_Data* dp, int64_t ulid) -{ - uint64_t k, l, z, an, m, bn = buf->n; - radix_sort_ul_ov_srt_tn(res->a, res->a + res->n); - ///after this function, res keeps unitig alignment, while buf keeps read alignments - for (k = 1, l = m = 0; k <= res->n; k++) { - if(k == res->n || res->a[k].tn != res->a[l].tn) {///qn <- (tn|rev) - for (z = l; z < k; z++) res->a[z].tn>>=1; - kv_resize(ul_ov_t, *buf, bn+k-l); - an = l + linear_rchain_dp_adv(res->a+l, k-l, buf->a+bn, uopt, bw, diff_ec_ul, qlen, - UG_SKIP_N, UG_ITER_N, UG_DIS_N, dp, rg, ulid); - for (z = l; z < an; z++) res->a[m++] = res->a[z]; - l = k; - } - } - res->n = m; - // kv_resize(ul_ov_t, *buf, bn+res->n); - // int64_t iqs, iqe, its, ite; - // for (k = 0, z = bn; k < res->n; k++) { - // buf->a[z] = res->a[k]; res->a[k].qn = z; - // extend_end_coord(NULL, &(res->a[k]), qlen, rg->seq[res->a[k].tn].len, &iqs, &iqe, &its, &ite); - // res->a[k].qs = iqs; res->a[k].qe = iqe; res->a[k].ts = its; res->a[k].te = ite; - // z++; - // } -} - -int64_t gconnect_test(const asg_t *g, uint32_t v, uint32_t w, int64_t bw, double diff_ec_ul, int64_t dq) -{ - int64_t dt = -1, dif, mm; - uint32_t nv, i; asg_arc_t *av = NULL; ///ma_hit_t *x = NULL; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (i = 0; i < nv; i++) { - if(av[i].del || av[i].v != w) continue; - dt = av[i].ol; - break; - } - - if(dt < 0) return 0; - dif = (dq>dt? dq-dt:dt-dq); - mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; - if(dif <= mm) return 1; - return 0; -} - -uint64_t gen_cns_chain_linear(ul_ov_t *a, int64_t a_n, /**ul_ov_t *ab,**/ const asg_t *rg, R_to_U *ri, int64_t qlen, int64_t bw, double diff_thre, Chain_Data* dp, -int64_t max_skip, int64_t max_iter, int64_t max_dis, uint64_t mqs, uint64_t mqe, uint64_t ulid) -{ - if(a_n == 0) return 0; - uint32_t li_v, lj_v; int32_t *f, *c_n, *len; int64_t *p, *t, st, max_ii, max, qo, cL, sn, ln, csn, mm_sn, cln, mm_ln; - int64_t mm_ovlp, x, i, j, sc, csc, mm_sc, mm_idx, n_skip, end_j, ch_sc, cn_sn, ch_ln, ch_i; ul_ov_t *li, *lj; - resize_Chain_Data(dp, a_n, NULL); - t = dp->tmp; f = dp->score; p = dp->pre; c_n = dp->occ; len = dp->indels; - - radix_sort_ul_ov_srt_qe(a, a + a_n); - for (i = 1, j = 0; i <= a_n; i++) { - if (i == a_n || a[i].qe != a[j].qe) { - if(i - j > 1) radix_sort_ul_ov_srt_qs(a+j, a+i); - j = i; - } - } - - memset(t, 0, (a_n*sizeof((*t)))); - ch_sc = ch_i = cn_sn = INT32_MIN; ch_ln = INT32_MAX; - for (i = st = 0, max_ii = -1; i < a_n; ++i) { - li = &(a[i]); - mm_ovlp = max_ovlp(rg, ((li->tn<<1)|li->rev)^1); - x = (li->qs + mm_ovlp)*diff_thre; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(i, a, x+G_CHAIN_INDEL); - - csc = 0; csn = 1; cln = 0; - if(is_contain_r((*ri), li->tn)) {csc = -1; csn = 0; cln = rg->seq[li->tn].len;} - mm_sc = INT32_MIN+1; mm_sn = INT32_MIN+1; mm_ln = INT32_MAX; - mm_idx = -1; n_skip = 0; end_j = -1; - - li_v = (li->tn<<1)|li->rev; li_v ^= 1; - if ((x-st) > max_iter) st = x-max_iter; - for (j = x; j >= st; --j) { // collect potential destination vertices - lj = &(a[j]); - if(lj->qe+G_CHAIN_INDEL <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore - if(f[j] == INT32_MIN) continue;///could not reach the left end - sc = sn = ln = INT32_MIN; - if(lj->qs <= li->qs && lj->qe <= li->qe) {///not contained - lj_v = (lj->tn<<1)|lj->rev; lj_v ^= 1; - qo = infer_rovlp(li, lj, NULL, NULL, NULL, NULL); - if(gconnect_test(rg, li_v, lj_v, bw, diff_thre, qo)) { - sc = f[j] + csc; sn = c_n[j] + csn; ln = len[j] + cln; - } - } - if(sc == INT32_MIN) continue; - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_sn)) || - ((sc == mm_sc) && (sn == mm_sn) && (ln < mm_ln))) { - mm_sc = sc, mm_idx = j, mm_sn = sn, mm_ln = ln; - if (n_skip > 0) --n_skip; - } else if (t[j] == i) { - if (++n_skip > max_skip) break; - } - if (p[j] >= 0) t[p[j]] = i; - } - - end_j = j; - if (max_ii < 0 || (a[i].qe > (a[max_ii].qe+max_dis))) {//too long - max = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && (a[i].qe<=(max_dis+a[j].qe)); --j) { - if (max < f[j]) { - max = f[j], max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - lj = &(a[max_ii]); - if(((lj->qe+G_CHAIN_INDEL)>li->qs) && (lj->qs<=li->qs) && (lj->qe<=li->qe) && (f[max_ii]!=INT32_MIN)) { - lj_v = (lj->tn<<1)|lj->rev; lj_v ^= 1; sc = sn = ln = INT32_MIN; - qo = infer_rovlp(li, lj, NULL, NULL, NULL, NULL); - if(gconnect_test(rg, li_v, lj_v, bw, diff_thre, qo)) { - sc = f[max_ii] + csc; sn = c_n[max_ii] + csn; ln = len[max_ii] + cln; - } - if(sc != INT32_MIN) { - if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_sn)) || - ((sc == mm_sc) && (sn == mm_sn) && (ln < mm_ln))) { - mm_sc = sc, mm_idx = max_ii, mm_sn = sn, mm_ln = ln; - } - } - } - } - - if((mm_idx == -1) && (((int64_t)li->qs) > ((int64_t)(mqs+bw)))) { - mm_sc = mm_idx = mm_sn = INT32_MIN; mm_ln = INT32_MAX; - } - if((mm_sc==(INT32_MIN+1))) { - mm_sc = csc; mm_sn = csn; mm_ln = cln; - } - - - f[i] = mm_sc; p[i] = mm_idx; c_n[i] = mm_sn; len[i] = mm_ln; - if ((max_ii < 0) || ((a[i].qe<=max_dis+a[max_ii].qe) && (f[max_ii]=((int64_t)(mqe)))) { - if((mm_sc > ch_sc) || ((mm_sc == ch_sc) && (mm_sn > cn_sn)) || - ((mm_sc == ch_sc) && (mm_sn == cn_sn) && (mm_ln < ch_ln))) { - ch_sc = mm_sc; ch_i = i; cn_sn = mm_sn; ch_ln = mm_ln; - } - } - // if(ulid == 442462) { - // fprintf(stderr, "[M::%s::id->%u::%.*s] i::%ld, q::[%u, %u), t::[%u, %u), is_cr::%u, mm_idx::%ld, end::%u\n", - // __func__, li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), i, - // li->qs, li->qe, li->ts, li->te, !!(is_contain_r((*ri), li->tn)), mm_idx, !!(((int64_t)(a[i].qe+bw))>=((int64_t)(mqe)))); - // } - } - // if(ulid == 442462) { - // fprintf(stderr, "[M::%s::] ch_i::%ld, mqs::%lu, mqe::%lu\n", - // __func__, ch_i, mqs, mqe); - // } - if(ch_i == INT32_MIN) return 0; - - i = ch_i; cL = 0; - while (i >= 0) {t[cL++] = i; i = p[i];} - for (i = 0; i < cL; i++) a[i] = a[t[cL-i-1]]; - return cL; -} - -void gen_contain_consensus_chain(ul_vec_t *rch, uint32_t rch_i, kv_ul_ov_t *idx, kv_ul_ov_t *dump, -const ug_opt_t *uopt, const asg_t *rg, R_to_U *ri, int64_t bw, double diff_ec_ul, int64_t ulid, Chain_Data* dp) -{ - uint64_t dn = dump->n, i, mqs, mqe; int64_t iqs, iqe, its, ite; idx->n = 0; - collect_nc_ovlps(rch, rch_i, idx, uopt, rg, ri, ulid, &mqs, &mqe); - // assert(idx->n > 1); assert((mqs != ((uint64_t)-1)) && (mqe != ((uint64_t)-1)) && (mqe > mqs)); - if((idx->n <= 1) || (mqs == ((uint64_t)-1)) || (mqe == ((uint64_t)-1)) || (mqe <= mqs)) return; - - gen_linear_rchains(idx, dump, rg, uopt, bw, diff_ec_ul, rch->rlen, dp, ulid); - assert(idx->n); - idx->n = gen_cns_chain_linear(idx->a, idx->n, /**dump->a+dn,**/ rg, ri, rch->rlen, bw, diff_ec_ul, dp, UG_SKIP_N, UG_ITER_N, UG_DIS_N, mqs, mqe, ulid); - // fprintf(stderr, "[M::%s::] idx->n::%u, mqs::%lu, mqe::%lu\n", __func__, (uint32_t)idx->n, mqs, mqe); - if(idx->n) { - kv_resize(ul_ov_t, *dump, dn + idx->n); - ///mask existing overlaps - for (i = rch_i; (i != (uint32_t)-1) && (!rg->seq[rch->bb.a[i].hid].del); i = rch->bb.a[i].pidx) { - dump->a[i].tn = dump->a[i].qn = (uint32_t)-1; - } - for (i = 0; i < idx->n; i++) { - dump->a[dn] = idx->a[i]; - extend_end_coord(NULL, &(dump->a[dn]), rch->rlen, rg->seq[dump->a[dn].tn].len, &iqs, &iqe, &its, &ite); - dump->a[dn].qs = iqs; dump->a[dn].qe = iqe; dump->a[dn].ts = its; dump->a[dn].te = ite; - dump->a[dn].qn = ((i>0)?(dn-1):((uint32_t)-1)); dn++; - } - dump->n = dn; - } -} - -uint32_t update_consensus_chain(const ug_opt_t *uopt, const asg_t *rg, kv_ul_ov_t *idx, kv_ul_ov_t *dump, ul_vec_t *rch, asg64_v *b, R_to_U *ri) -{ - uint64_t *idm, k, l, kn, dn, cc = 0; - assert(dump->n >= rch->bb.n); - kv_resize(uint64_t, *b, dump->n); idm = b->a; - - for (k = kn = 0; k < rch->bb.n; k++) { - idm[k] = (uint64_t)-1; - if((dump->a[k].qn == ((uint32_t)-1)) && (dump->a[k].tn == ((uint32_t)-1))) continue; - dump->a[k].qn = rch->bb.a[dump->a[k].qn].pidx; idm[k] = kn; kn++; - } - for (; k < dump->n; k++) { - idm[k] = kn; kn++; - } - // fprintf(stderr, "[M::%s::kn->%lu] dump->n::%u\n", __func__, kn, (uint32_t)dump->n); - - dn = dump->n; dump->n = 0; - kv_resize(ul_ov_t, *idx, kn); idx->n = 0; - for (k = 0; k < dn; k++) { - if(idm[k] == ((uint64_t)-1)) continue; - dump->a[idm[k]] = dump->a[k]; kn--; dump->n++; - if(dump->a[idm[k]].qn != ((uint32_t)-1)) { - dump->a[idm[k]].qn = (uint32_t)idm[dump->a[idm[k]].qn]; - } - kv_push(ul_ov_t, *idx, dump->a[idm[k]]); idx->a[idx->n-1].qn = idm[k]; - } - assert(kn == 0); - - radix_sort_ul_ov_srt_qe(idx->a, idx->a + idx->n); - for (k = 1, l = 0; k <= idx->n; k++) { - if (k == idx->n || idx->a[l].qe != idx->a[k].qe) { - if(k - l > 1) radix_sort_ul_ov_srt_qs(idx->a+l, idx->a+k); - l = k; - } - } - for (k = 0; k < idx->n; k++) dump->a[idx->a[k].qn].tn = k; - - for (k = 0; k < idx->n; k++) { - idx->a[k].qn = ((dump->a[idx->a[k].qn].qn!=((uint32_t)-1))? - (dump->a[dump->a[idx->a[k].qn].qn].tn):((uint32_t)-1)); - idx->a[k].el = 1; - } - - uc_block_t *z, *p; int64_t tt; - kv_resize(uc_block_t, rch->bb, idx->n); rch->bb.n = 0; - for (k = 0; k < idx->n; k++) { - // fprintf(stderr, "+k::%lu[M::%s::id->%u] q::[%u, %u), t::[%u, %u), is_cr::%u\n", - // k, __func__, idx->a[k].tn, idx->a[k].qs, idx->a[k].qe, idx->a[k].ts, idx->a[k].te, - // !!(is_contain_r((*ri), idx->a[k].tn))); - kv_pushp(uc_block_t, rch->bb, &z); memset(z, 0, sizeof((*z))); - z->hid = idx->a[k].tn; z->rev = idx->a[k].rev; - z->pchain = 1; z->base = 0; z->el = 1; - z->qs = idx->a[k].qs; z->qe = idx->a[k].qe; - z->te = idx->a[k].te; z->ts = idx->a[k].ts; - z->pidx = idx->a[k].qn; z->pdis = z->aidx = (uint32_t)-1; - - } - for (k = cc = 0; k < rch->bb.n; k++) { - if(is_contain_r((*ri), rch->bb.a[k].hid)) cc++; - // fprintf(stderr, "-k::%lu[M::%s::id->%u] q::[%u, %u), t::[%u, %u), is_cr::%u\n", - // k, __func__, rch->bb.a[k].hid, rch->bb.a[k].qs, rch->bb.a[k].qe, rch->bb.a[k].ts, rch->bb.a[k].te, - // !!(is_contain_r((*ri), rch->bb.a[k].hid))); - if(rch->bb.a[k].pidx == (uint32_t)-1) continue; - z = &(rch->bb.a[k]); p = &(rch->bb.a[z->pidx]); - assert(p->aidx == (uint32_t)-1); p->aidx = k; - tt = g_adjacent_dis_mul(NULL, uopt->sources, uopt->max_hang, uopt->min_ovlp, ((z->hid<<1)|((uint32_t)z->rev))^1, ((p->hid<<1)|((uint32_t)p->rev))^1); - if(tt >= 0) z->pdis = tt; ///assert(tt >= 0); - } - - ///debug_ssb - // for (k = 0; k < rch->bb.n; k++) { - // if(rch->bb.a[k].pidx != (uint32_t)-1) { - // if((rch->bb.a[k].pidx >= 0) && (rch->bb.a[k].pidx < rch->bb.n) && - // (rch->bb.a[rch->bb.a[k].pidx].aidx == k)) { - // ; - // } else { - // fprintf(stderr, "[M::%s::k->%lu] +rch->bb.n::%u\n", __func__, k, (uint32_t)rch->bb.n); - // for (l = 0; l < rch->bb.n; l++) { - // fprintf(stderr, "[M::%.*s::k->%lu] q::[%u, %u), t::[%u, %u), is_cr::%u, pidx::%u, aidx::%u\n", - // (int)Get_NAME_LENGTH(R_INF, rch->bb.a[l].hid), Get_NAME(R_INF, rch->bb.a[l].hid), l, - // rch->bb.a[l].qs, rch->bb.a[l].qe, rch->bb.a[l].ts, rch->bb.a[l].te, - // !!(is_contain_r((*ri), rch->bb.a[l].hid)), - // rch->bb.a[l].pidx, rch->bb.a[l].aidx); - // } - // exit(1); - // } - // } - - // if(rch->bb.a[k].aidx != (uint32_t)-1) { - // if((rch->bb.a[k].aidx >= 0) && (rch->bb.a[k].aidx < rch->bb.n) && - // (rch->bb.a[rch->bb.a[k].aidx].pidx == k)) { - // ; - // } else { - // fprintf(stderr, "[M::%s::k->%lu] -rch->bb.n::%u\n", __func__, k, (uint32_t)rch->bb.n); - // for (l = 0; l < rch->bb.n; l++) { - // fprintf(stderr, "[M::%.*s::k->%lu] q::[%u, %u), t::[%u, %u), is_cr::%u, pidx::%u, aidx::%u\n", - // (int)Get_NAME_LENGTH(R_INF, rch->bb.a[l].hid), Get_NAME(R_INF, rch->bb.a[l].hid), l, - // rch->bb.a[l].qs, rch->bb.a[l].qe, rch->bb.a[l].ts, rch->bb.a[l].te, - // !!(is_contain_r((*ri), rch->bb.a[l].hid)), - // rch->bb.a[l].pidx, rch->bb.a[l].aidx); - // } - // exit(1); - // } - // } - // } - - return ((cc==0)?1:0); -} - -static void worker_for_contain_consensus(void *data, long i, int tid) -{ - ul_vec_t *p = &(UL_INF.a[i]); asg64_v b0; - utepdat_t *s = (utepdat_t*)data; uint32_t ff, k; - - // if(i != 304) return; - copy_asg_arr(b0, s->ll[tid].srt.a); - ff = refine_contain_consensus_chain(s->rg, p, s->uopt->ruIndex, &b0, i); - copy_asg_arr(s->ll[tid].srt.a, b0); - // fprintf(stderr, "[M::%s::%.*s(id:%ld), len:%u] ff:%u\n", __func__, - // UL_INF.nid.a[i].n, UL_INF.nid.a[i].a, i, p->rlen, ff); - // if(debug_out) { - // for (k = 0; k < p->bb.n; k++) { - // fprintf(stderr, "[M::%.*s] q::[%u, %u), t::[%u, %u), is_cr::%u, pidx::%u, aidx::%u\n", - // (int)Get_NAME_LENGTH(R_INF, p->bb.a[k].hid), Get_NAME(R_INF, p->bb.a[k].hid), - // p->bb.a[k].qs, p->bb.a[k].qe, p->bb.a[k].ts, p->bb.a[k].te, - // !!(is_contain_r((*(s->uopt->ruIndex)), p->bb.a[k].hid)), p->bb.a[k].pidx, p->bb.a[k].aidx); - // } - // fprintf(stderr, "***[M::%s::%.*s(id:%ld), len:%u] ff:%u, sp_chn::%u, p->bb.n::%u\n\n", __func__, - // UL_INF.nid.a[i].n, UL_INF.nid.a[i].a, i, p->rlen, ff, (uint32_t)s->ll[tid].srt.a.n, (uint32_t)p->bb.n); - // } - if(!ff) return; - - // char *as = NULL; - // asprintf(&as, "\n[M::%s]\trid::%ld\tlen::%lu\tname::%.*s\tb0.n::%u\n", - // __func__, s->id+i, s->len[i], (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a, (uint32_t)b0.n); - // push_vlog(&(overall_zdbg->a[s->id+i]), as); free(as); as = NULL; - - - - kv_ul_ov_t *idx = &(s->ll[tid].lo), *dump = &(s->ll[tid].tk); ul_ov_t *z; - // if(p->dd == 1) return; //fully aligned - // if(p->bb.n == 1 && p->bb.a[0].base) return;///no alignment - // if(p->bb.n == 0) return;///no alignment - s->hab[tid]->num_read_base++; - - // if(i == 442462) { - // fprintf(stderr, "\n[M::%s::%.*s(id:%ld), len:%u] ff:%u, sp_chn::%u, p->bb.n::%u\n", __func__, - // UL_INF.nid.a[i].n, UL_INF.nid.a[i].a, i, p->rlen, ff, (uint32_t)s->ll[tid].srt.a.n, (uint32_t)p->bb.n); - // } - - // fprintf(stderr, "[M::%s]\tp->bb.n::%u\n", __func__, (uint32_t)p->bb.n); - kv_resize(ul_ov_t, *dump, p->bb.n); - for (k = dump->n = 0; k < p->bb.n; k++) { - z = &(dump->a[dump->n++]); ///memset(z, 0, sizeof((*z))); - z->qn = k; z->qs = p->bb.a[k].qs; z->qe = p->bb.a[k].qe; - z->tn = p->bb.a[k].hid; z->ts = p->bb.a[k].ts; z->te = p->bb.a[k].te; - z->el = 1; z->rev = p->bb.a[k].rev; z->sec = 0; - // if(i == 442462) { - // fprintf(stderr, "[M::%s::id->%u::%.*s] q::[%u, %u), t::[%u, %u), is_rev::%u, is_cr::%u\n", - // __func__, z->tn, (int)Get_NAME_LENGTH(R_INF, z->tn), Get_NAME(R_INF, z->tn), - // z->qs, z->qe, z->ts, z->te, z->rev, !!(is_contain_r((*(s->uopt->ruIndex)), z->tn))); - // } - } - - for (k = 0; k < s->ll[tid].srt.a.n; k++) { - gen_contain_consensus_chain(p, s->ll[tid].srt.a.a[k], idx, dump, s->uopt, s->rg, s->uopt->ruIndex, G_CHAIN_BW, s->opt->diff_ec_ul, i, &(s->hab[tid]->clist.chainDP)); - } - - copy_asg_arr(b0, s->ll[tid].srt.a); - ff = update_consensus_chain(s->uopt, s->rg, idx, dump, p, &b0, s->uopt->ruIndex); - copy_asg_arr(s->ll[tid].srt.a, b0); - s->hab[tid]->num_correct_base += ff; - // fprintf(stderr, "[M::%s::%.*s(id:%ld), len:%u] ffa->%u, sp_chn::%u\n", __func__, - // UL_INF.nid.a[i].n, UL_INF.nid.a[i].a, i, p->rlen, ff, (uint32_t)s->ll[tid].srt.a.n); - - // s->hab[tid]->num_correct_base += direct_gchain(s->buf[tid], p, &(s->ll[tid]), &(s->gdp[tid]), &(s->sps[tid]), &(s->hab[tid]->hap), s->uu, s->uopt, G_CHAIN_BW, s->opt->diff_ec_ul, UG_SKIP, i, &(s->hab[tid]->clist.chainDP), s->rg, ((ff==2)?1:0)); - // gl_chain_refine_advance(&b->olist, &b->correct, &b->hap, bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, km); -} - -uint32_t extract_contain_tig(asg_t *g, uint64_t v0, R_to_U *ri, uint64_t offset, uint64_t must_tip, kv_ul_ov_t *res) -{ - uint32_t v = v0, w, kv, kw, is_tip = 0, l = offset; - ul_ov_t p; memset(&p, 0, sizeof(p)); - - while (1) { - if(!is_contain_r((*ri), (v>>1))) return 0; - kv = get_arcs(g, v, &w, 1); - if(kv > 1) return 0; - - p.qn = 0; p.qs = l; p.qe = l + g->seq[v>>1].len; - p.tn = v>>1; p.ts = 0; p.te = g->seq[v>>1].len; - p.el = 0; p.rev = v&1; kv_push(ul_ov_t, *res, p); - - if(kv == 0) {is_tip = 1; break;} - - l += asg_arc_len(g->arc[w]); - w = g->arc[w].v; - ///kv must be 1 here - kw = get_arcs(g, w^1, NULL, 0); - assert(kw >= 1); - if(kw > 1) { - p.qn = 0; p.qs = l; p.qe = l + g->seq[w>>1].len; - p.tn = w>>1; p.ts = 0; p.te = g->seq[w>>1].len; - p.el = 1; p.rev = w&1; kv_push(ul_ov_t, *res, p); - break; - } - v = w; - if(v == v0) return 0; - } - if((must_tip) && (!is_tip)) return 0; - return 1; -} - -uint32_t gen_dup_path(const asg_t *g, R_to_U *ri, kv_ul_ov_t *res, uint64_t v) -{ - asg_t *rg = (asg_t *)g; res->n = 0; - if(rg->seq[v>>1].del) return res->n; - uint64_t nv = asg_arc_n(rg, v); asg_arc_t *av = asg_arc_a(rg, v); - uint64_t k, kv, w = (uint64_t)-1, kw, l, rn, z; ul_ov_t p; memset(&p, 0, sizeof(p)); - - // for (k = 0; k < nv; k++) { - // if(av[k].del) continue; - // asg_arc_t *aw = asg_arc_a(rg, av[k].v); - // uint64_t nw = asg_arc_n(rg, av[k].v); - // for (l = 0; l < nw; l++) { - // if(aw[l].del) continue; - // for (rn = 0; rn < nv; rn++) { - // if(av[rn].del) continue; - // if(av[rn].v == aw[l].v) break; - // } - // if(rn < nv) { - // fprintf(stderr, "[M::%s] v0::%lu, w::%u, v1::%u\n", __func__, v, av[k].v, aw[l].v); - // } - // } - // } - - - - - for (k = kv = 0; k < nv && kv < 2; k++) { - if(!(av[k].del)) kv++; - } - // if(v == 7723) { - // fprintf(stderr, "[M::%s] v0::%lu, kv::%lu\n", __func__, v, kv); - // } - if(kv > 1) { - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - w = av[k].v; kw = get_arcs(rg, w^1, NULL, 0); - // if(v == 7723) { - // fprintf(stderr, "*[M::%s] v0::%lu, av[%lu].v::%u, kw::%lu,\n", __func__, v, k, av[k].v, kw); - // } - if(kw > 1) {///kv > 1 && kw > 1 - if((v>>1) != (w>>1)) {///cannot handle if the prefix and suffix nodes are the same - l = 0; - p.qn = 0; p.qs = l; p.qe = l + rg->seq[v>>1].len; - p.tn = v>>1; p.ts = 0; p.te = rg->seq[v>>1].len; - p.el = 1; p.rev = v&1; kv_push(ul_ov_t, *res, p); - // if(v == 7723) { - // fprintf(stderr, "*[M::%s] v0::%lu, p.tn::%u, p.rev::%u\n", __func__, v, p.tn, p.rev); - // } - - l += asg_arc_len(av[k]); - p.qn = 0; p.qs = l; p.qe = l + rg->seq[w>>1].len; - p.tn = w>>1; p.ts = 0; p.te = rg->seq[w>>1].len; - p.el = 1; p.rev = w&1; kv_push(ul_ov_t, *res, p); - - // if(v == 7723) { - // fprintf(stderr, "*[M::%s] v0::%lu, p.tn::%u, p.rev::%u\n", __func__, v, p.tn, p.rev); - // } - - p.tn = (uint32_t)-1; p.qn = ((uint64_t)(av-g->arc+k)); - kv_push(ul_ov_t, *res, p); - } - } else if((kw == 1) && (is_contain_r((*ri), (w>>1)))) {///kv > 1 && kw == 1 && w is contained - rn = res->n; l = 0; - p.qn = 0; p.qs = l; p.qe = l + rg->seq[v>>1].len; - p.tn = v>>1; p.ts = 0; p.te = rg->seq[v>>1].len; - p.el = 1; p.rev = v&1; kv_push(ul_ov_t, *res, p); - l += asg_arc_len(av[k]); - if(!extract_contain_tig(rg, w, ri, l, 0, res)) { - res->n = rn; - } else { - for (z = rn+1; z < res->n; z++) { - if(res->a[z].tn == (v>>1)) break; - } - if(z >= res->n) {///cannot handle circles - p.tn = (uint32_t)-1; p.qn = ((uint64_t)(av-g->arc+k)); - kv_push(ul_ov_t, *res, p); - } else { - res->n = rn; - } - } - } - } - } else if(((kv == 1) || (kv == 0)) && (!get_arcs(rg, v^1, NULL, 0)) && (is_contain_r((*ri), (v>>1)))) { - ///1. kv == 1 && kv^ == 0 && v is contained - ///2. kv == 0 && kv^ == 0 && v is contained; an isolated single contained read - rn = res->n; l = 0; - if(!extract_contain_tig(rg, v, ri, l, 1, res)) { - res->n = rn; - } else { - for (z = rn+1; z < res->n; z++) { - if(res->a[z].tn == (v>>1)) break; - } - if(z >= res->n) {///cannot handle circles - p.tn = (uint32_t)-1; p.qn = (uint32_t)-1; - if(kv > 0) { - for (k = 0; k < nv; k++) { - if(!(av[k].del)) break; - } - assert(k < nv); - p.qn = ((uint64_t)(av-g->arc+k)); - } - - kv_push(ul_ov_t, *res, p); - } else { - res->n = rn; - } - } - } - // if(v == 7723) { - // fprintf(stderr, "[M::%s] v0::%lu, res->n::%lu,\n", __func__, v, (uint64_t)res->n); - // } - return res->n;///# chains have contained reads -} - -void collect_pp_ovlps(ul_ov_t *a, uint64_t a_n, kv_ul_ov_t *res, const ug_opt_t *uopt, const asg_t *rg, uint64_t rlen, int64_t ulid, uint64_t *mqs, uint64_t *mqe) -{ - uint64_t i, k; ma_hit_t_alloc* src; uc_block_t rch; ul_ov_t p, *st, *et; - int64_t min_ovlp = uopt->min_ovlp, max_hang = uopt->max_hang, iqs, iqe; st = et = NULL; - res->n = 0; (*mqs) = (*mqe) = (uint64_t)-1; memset(&rch, 0, sizeof(rch)); - if(a_n && a[0].el) st = &(a[0]); - if(a_n > 1 && a[a_n-1].el) et = &(a[a_n-1]); - // if(ulid == 7723 && a_n == 2 && a[0].tn == (7723>>1) && a[a_n-1].tn == (7829>>1)) { - // fprintf(stderr, "[M::%s] ulid::%ld, st::%ld, st_q::[%ld, %ld), et::%ld, et_q::[%ld, %ld)\n", - // __func__, ulid, st?(int64_t)st->tn:-1, st?(int64_t)st->qs:-1, st?(int64_t)st->qe:-1, - // et?(int64_t)et->tn:-1, et?(int64_t)et->qs:-1, et?(int64_t)et->qe:-1); - // } - for (i = 0; i < a_n; i++) { - src = &(uopt->sources[a[i].tn]); - rch.hid = a[i].tn; rch.rev = a[i].rev; - rch.qs = a[i].qs; rch.qe = a[i].qe; - rch.ts = a[i].ts; rch.te = a[i].te; - for (k = 0; k < src->length; k++) { - if(rg->seq[Get_tn(src->buffer[k])].del) continue;///tn must exist - if(st && st->tn == Get_tn(src->buffer[k])) continue;//not useful - if(et && et->tn == Get_tn(src->buffer[k])) continue;//not useful - if(!extract_nccov(&(src->buffer[k]), &rch, rg, &p, 0, min_ovlp, max_hang)) continue; - - extend_end_coord(NULL, &p, rlen, rg->seq[p.tn].len, &iqs, &iqe, NULL, NULL); - if(st && iqs <= (int64_t)st->qe && iqe <= (int64_t)st->qe) continue;//not useful - if(et && iqs >= (int64_t)et->qs && iqe >= (int64_t)et->qs) continue;//not useful - - if(p.rev) { - iqs = rg->seq[p.tn].len - p.te; - iqe = rg->seq[p.tn].len - p.ts; - p.ts = iqs; p.te = iqe; - } - // if(ulid == 7723 && a_n == 2 && a[0].tn == (7723>>1) && a[a_n-1].tn == (7829>>1)) { - // fprintf(stderr, "[M::%s] ulid::%ld, p.tn::%u, pq::[%u, %u), p.el::%u\n", - // __func__, ulid, p.tn, p.qs, p.qe, p.el); - // } - p.el = 0; p.tn <<= 1; p.tn |= p.rev; p.qn = i;//for linear chain - kv_push(ul_ov_t, *res, p); - } - - ///it is unnecessary to push any non-end reads; - ///since the read graph will remove any old read; each read/node is unique within the read graph - if(a[i].el) { - ///push itself into the chain - p = a[i]; - // if(ulid == 7723 && a_n == 2 && a[0].tn == (7723>>1) && a[a_n-1].tn == (7829>>1)) { - // fprintf(stderr, "[M::%s] ulid::%ld, p.tn::%u, pq::[%u, %u), p.el::%u\n", - // __func__, ulid, p.tn, p.qs, p.qe, p.el); - // } - p.tn <<= 1; p.tn |= p.rev; p.qn = i;//for linear chain - kv_push(ul_ov_t, *res, p); - } - if(((*mqs) == ((uint64_t)-1)) || ((*mqs) > a[i].qs)) (*mqs) = a[i].qs; - if(((*mqe) == ((uint64_t)-1)) || ((*mqe) < a[i].qe)) (*mqe) = a[i].qe; - - } - if(st) (*mqs) = st->qs; if(et) (*mqe) = et->qe; -} - -uint64_t gen_cns_chain_linear_hard(ul_ov_t *a, int64_t a_n, const asg_t *rg, int64_t qlen, int64_t bw, double diff_thre, Chain_Data* dp, -int64_t max_skip, int64_t max_iter, int64_t max_dis, uint64_t mqs, uint64_t mqe, uint64_t ulid, uint64_t ltn, uint64_t rtn) -{ - if(a_n == 0) return 0; - uint32_t li_v, lj_v; int32_t *f; int64_t *p, *t, st, max_ii, max, qo, cL; ul_ov_t *li, *lj; - int64_t mm_ovlp, x, i, j, sc, csc, mm_sc, mm_idx, n_skip, end_j, ch_sc, ch_i; - resize_Chain_Data(dp, a_n, NULL); t = dp->tmp; f = dp->score; p = dp->pre; - - radix_sort_ul_ov_srt_qe(a, a + a_n); - for (i = 1, j = 0; i <= a_n; i++) { - if (i == a_n || a[i].qe != a[j].qe) { - if(i - j > 1) radix_sort_ul_ov_srt_qs(a+j, a+i); - j = i; - } - } - - memset(t, 0, (a_n*sizeof((*t)))); - ch_sc = ch_i = INT32_MIN; - for (i = st = 0, max_ii = -1; i < a_n; ++i) { - li = &(a[i]); - mm_ovlp = max_ovlp(rg, ((li->tn<<1)|li->rev)^1); - x = (li->qs + mm_ovlp)*diff_thre; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > qlen+1) x = qlen+1; - x = find_ul_ov_max(i, a, x+G_CHAIN_INDEL); - - csc = 1; if(li->el) csc = 0; - mm_sc = INT32_MIN+1; mm_idx = -1; n_skip = 0; end_j = -1; - - li_v = (li->tn<<1)|li->rev; li_v ^= 1; - if ((x-st) > max_iter) st = x-max_iter; - for (j = x; j >= st; --j) { // collect potential destination vertices - lj = &(a[j]); - if(lj->qe+G_CHAIN_INDEL <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore - if(f[j] == INT32_MIN) continue;///could not reach the left end - sc = INT32_MIN; - if(lj->qs <= li->qs && lj->qe <= li->qe) {///not contained - lj_v = (lj->tn<<1)|lj->rev; lj_v ^= 1; - qo = infer_rovlp(li, lj, NULL, NULL, NULL, NULL); - if(gconnect_test(rg, li_v, lj_v, bw, diff_thre, qo)) { - sc = f[j] + csc; - } - } - if(sc == INT32_MIN) continue; - if(sc > mm_sc) { - mm_sc = sc, mm_idx = j; - if (n_skip > 0) --n_skip; - } else if (t[j] == i) { - if (++n_skip > max_skip) break; - } - if (p[j] >= 0) t[p[j]] = i; - } - - end_j = j; - if (max_ii < 0 || (a[i].qe > (a[max_ii].qe+max_dis))) {//too long - max = INT32_MIN; max_ii = -1; - for (j = i - 1; (j >= st) && (a[i].qe<=(max_dis+a[j].qe)); --j) { - if (max < f[j]) { - max = f[j], max_ii = j; - } - } - } - - if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] - lj = &(a[max_ii]); - if(((lj->qe+G_CHAIN_INDEL)>li->qs) && (lj->qs<=li->qs) && (lj->qe<=li->qe) && (f[max_ii]!=INT32_MIN)) { - lj_v = (lj->tn<<1)|lj->rev; lj_v ^= 1; sc = INT32_MIN; - qo = infer_rovlp(li, lj, NULL, NULL, NULL, NULL); - if(gconnect_test(rg, li_v, lj_v, bw, diff_thre, qo)) { - sc = f[max_ii] + csc; - } - if(sc != INT32_MIN) { - if(sc > mm_sc) { - mm_sc = sc, mm_idx = max_ii; - } - } - } - } - - if(mm_idx == -1) { - if((ltn) != ((uint64_t)-1)) { - if(ltn != li->tn) mm_sc = mm_idx = INT32_MIN; - } else { - if(((int64_t)li->qs) > ((int64_t)(mqs+bw))) mm_sc = mm_idx = INT32_MIN; - } - } - - if((mm_sc==(INT32_MIN+1))) { - mm_sc = csc; - } - - - f[i] = mm_sc; p[i] = mm_idx; - - // if(ulid == 7723 && ltn == (7723>>1) && rtn == (7829>>1)) { - // fprintf(stderr, "[M::%s::id->%u::%.*s] i::%ld, q::[%u, %u), t::[%u, %u), mm_idx::%ld, mm_sc::%ld\n", - // __func__, li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), i, - // li->qs, li->qe, li->ts, li->te, mm_idx, mm_sc); - // } - - if(mm_sc == INT32_MIN) continue; - if((rtn != ((uint64_t)-1)) && (rtn != li->tn)) continue; - if((rtn == ((uint64_t)-1)) && (((int64_t)(a[i].qe+bw))<((int64_t)(mqe)))) continue; - if(mm_sc >= ch_sc) { - ch_sc = mm_sc; ch_i = i; - } - if ((max_ii < 0) || (f[max_ii]= 0) {t[cL++] = i; i = p[i];} - for (i = 0; i < cL; i++) a[i] = a[t[cL-i-1]]; - return cL; -} - -void gen_linear_rchains_dedup(kv_ul_ov_t *res, kv_ul_ov_t *buf, const asg_t *rg, const ug_opt_t *uopt, int64_t bw, -double diff_ec_ul, int64_t qlen, Chain_Data* dp, int64_t ulid, uint64_t *flt, uint64_t flt_n) -{ - uint64_t k, l, z, an, m, bn = buf->n, fi, tn; - radix_sort_ul_ov_srt_tn(res->a, res->a + res->n); - ///after this function, res keeps unitig alignment, while buf keeps read alignments - for (k = 1, l = m = fi = 0; k <= res->n; k++) { - if(k == res->n || res->a[k].tn != res->a[l].tn) {///qn <- (tn|rev) - tn = res->a[l].tn>>1; - for (z = l; z < k; z++) res->a[z].tn>>=1; - for (; (fi=flt_n) || (flt[fi]!=tn)) { - kv_resize(ul_ov_t, *buf, bn+k-l); - an = l + linear_rchain_dp_adv(res->a+l, k-l, buf->a+bn, uopt, bw, diff_ec_ul, qlen, - UG_SKIP_N, UG_ITER_N, UG_DIS_N, dp, rg, ulid); - for (z = l; z < an; z++) res->a[m++] = res->a[z]; - } - l = k; - } - } - res->n = m; -} - -void renew_consensus_chain(kv_ul_ov_t *in, uint32_t in_s, uint32_t in_e, kv_ul_ov_t *idx, asg64_v *ou, R_to_U *ri, -const ug_opt_t *uopt, const asg_t *rg, int64_t bw, double diff_ec_ul, uint32_t arc_id, Chain_Data* dp, uint64_t rlen, uint32_t ulid) -{ - if(in_e <= in_s) return; - uint64_t mqs, mqe, k, l, ou_n = ou->n, stn, etn; - collect_pp_ovlps(in->a + in_s, in_e - in_s, idx, uopt, rg, rlen, ulid, &mqs, &mqe); - // if(ulid == 7723 && in_e-in_s == 2 && in->a[in_s].tn == (7723>>1) && in->a[in_e-1].tn == (7829>>1)) { - // fprintf(stderr, "-0-[M::%s] ulid::%u, idx->n::%u\n", __func__, ulid, (uint32_t)idx->n); - // } - if(!idx->n) return;///it is possible - kv_resize(uint64_t, *ou, (ou_n+(in_e-in_s))); - for (k = in_s; k < in_e; k++) { - if(in->a[k].el) continue; - ou->a[ou_n++] = in->a[k].tn; - } - assert(ou_n <= ou->m); - radix_sort_gfa64(ou->a+ou->n, ou->a+ou_n); - gen_linear_rchains_dedup(idx, in, rg, uopt, bw, diff_ec_ul, rlen, dp, ulid, ou->a+ou->n, ou_n-ou->n); - // if(ulid == 7723 && in_e-in_s == 2 && in->a[in_s].tn == (7723>>1) && in->a[in_e-1].tn == (7829>>1)) { - // fprintf(stderr, "-1-[M::%s] ulid::%u, idx->n::%u\n", __func__, ulid, (uint32_t)idx->n); - // } - if(!idx->n) return;///it is possible - stn = etn = (uint64_t)-1; - if(in_e > in_s && in->a[in_s].el) stn = in->a[in_s].tn; - if(in_e-in_s>1 && in->a[in_e-1].el) etn = in->a[in_e-1].tn; - idx->n = gen_cns_chain_linear_hard(idx->a, idx->n, rg, rlen, bw, diff_ec_ul, dp, UG_SKIP_N, UG_ITER_N, UG_DIS_N, mqs, mqe, ulid, stn, etn); - // if(ulid == 7723 && in_e-in_s == 2 && in->a[in_s].tn == (7723>>1) && in->a[in_e-1].tn == (7829>>1)) { - // fprintf(stderr, "-2-[M::%s] ulid::%u, idx->n::%u\n", __func__, ulid, (uint32_t)idx->n); - // } - if(!idx->n) return; - assert((stn==((uint64_t)-1))||((idx->a[0].tn == stn) && (idx->a[0].el))); - assert((etn==((uint64_t)-1))||((idx->a[idx->n-1].tn == etn) && (idx->a[idx->n-1].el))); - if((stn != ((uint64_t)-1)) && (etn != ((uint64_t)-1)) && idx->n < 2) return;///could happen for circle - if(((stn != ((uint64_t)-1)) || (etn != ((uint64_t)-1))) && idx->n < 1) return;///not sure if it will happen - ou_n = ou->n; - for (k = in_s; k < in_e; k++) { - if(in->a[k].el) continue; - kv_push(uint64_t, *ou, in->a[k].tn); - } - for (k = 0; k < idx->n; k++) { - if(idx->a[k].el) continue; - kv_push(uint64_t, *ou, idx->a[k].tn); - } - if(ou->n == ou_n) return; - radix_sort_gfa64(ou->a+ou_n, ou->a+ou->n); - for (k = ou_n+1, l = ou_n; k <= ou->n; k++) { - if(k == ou->n || ou->a[l] != ou->a[k]) { - if(k-l > 1) break; - l = k; - } - } - assert(k > ou->n); - ou->n = ou_n; - l = arc_id; - if(arc_id == (uint32_t)-1) {///this is an isloated node - l = idx->a[0].tn; l |= ((uint64_t)0x80000000); - } - l <<= 32; l |= ((uint64_t)((uint32_t)-1)); - kv_push(uint64_t, *ou, l); - for (k = 0; k < idx->n; k++) { - l = ((uint64_t)(idx->a[k].tn<<1))|((uint64_t)idx->a[k].rev); - if(idx->a[k].el) l += ((uint64_t)0x100000000); - kv_push(uint64_t, *ou, l); - } - kv_push(uint64_t, *ou, ((uint64_t)-1)); - for (k = in_s; k < in_e; k++) { - l = ((uint64_t)(in->a[k].tn<<1))|((uint64_t)in->a[k].rev); - if(in->a[k].el) l += ((uint64_t)0x100000000); - kv_push(uint64_t, *ou, l); - } -} - -static void worker_for_contain_dedup(void *data, long i, int tid) -{ - utepdat_t *s = (utepdat_t*)data; asg64_v ou; - kv_ul_ov_t *idx = &(s->ll[tid].lo), *dump = &(s->ll[tid].tk); - uint32_t k, v = i, l, dump_n; - - if(!gen_dup_path(s->rg, s->uopt->ruIndex, dump, v)) return; - // if(v == 7723) { - // fprintf(stderr, "[M::%s] v::%u, dump->n::%u\n", __func__, v, (uint32_t)dump->n); - // } - - - copy_asg_arr(ou, s->ll[tid].srt.a); - for (k = 1, l = 0, dump_n = dump->n; k <= dump_n; k++) { - if(k == dump_n || (dump->a[k].tn == ((uint32_t)-1))) { - assert(k > l || k == dump_n); - if(k > l) { - assert(dump->a[k].tn == ((uint32_t)-1)); - renew_consensus_chain(dump, l, k, idx, &ou, s->uopt->ruIndex, s->uopt, s->rg, G_CHAIN_BW, - 0.02/**s->opt->diff_ec_ul**/, dump->a[k].qn, &(s->hab[tid]->clist.chainDP), dump->a[k-1].qe, v); - } - l = k + 1; - } - } - copy_asg_arr(s->ll[tid].srt.a, ou); -} - -void detect_outlier_len(const char* cmd) -{ - uint64_t k; - for (k = 0; k < UL_INF.n; k++) { - if(UL_INF.a[k].rlen == 0) { - fprintf(stderr, "[%s] rid->%lu, rlen->%u, %.*s\n", - cmd, k, UL_INF.a[k].rlen, (int32_t)UL_INF.nid.a[k].n, UL_INF.nid.a[k].a); - } - } -} - -uint64_t work_ul_gchains(uldat_t *sl) -{ - utepdat_t s; uint64_t i; memset(&s, 0, sizeof(s)); - s.id = 0; s.opt = sl->opt; s.ug = sl->ug; s.uopt = sl->uopt; s.rg = sl->rg; s.uu = sl->uu; - CALLOC(s.hab, sl->n_thread); CALLOC(s.buf, sl->n_thread); CALLOC(s.ll, sl->n_thread); - CALLOC(s.gdp, sl->n_thread); CALLOC(s.mzs, sl->n_thread); CALLOC(s.sps, sl->n_thread); - - for (i = 0; i < sl->n_thread; ++i) { - s.hab[i] = ha_ovec_init(0, 0, 1); s.buf[i] = mg_tbuf_init(); - } - - // detect_outlier_len("+++work_ul_gchains"); - - kt_for(sl->n_thread, worker_for_ul_gchains_alignment, &s, UL_INF.n); - - // detect_outlier_len("---work_ul_gchains"); - - for (i = 0; i < sl->n_thread; ++i) { - s.sum_len += s.hab[i]->num_read_base; s.n += s.hab[i]->num_correct_base; - ha_ovec_destroy(s.hab[i]); mg_tbuf_destroy(s.buf[i]); hc_glchain_destroy(&(s.ll[i])); - hc_gdpchain_destroy(&(s.gdp[i])); kv_destroy(s.mzs[i]); kv_destroy(s.sps[i]); - } - - free(s.hab); free(s.buf); free(s.ll); free(s.gdp); free(s.mzs); free(s.sps); - fprintf(stderr, "[M::%s::] # try:%d, # done:%d\n", __func__, s.sum_len, s.n); - return s.n; -} - -scaf_res_t *work_ctg_path_gchains(uldat_t *sl) -{ - utepdat_t s; uint64_t i; memset(&s, 0, sizeof(s)); scaf_res_t *res = init_scaf_res_t(sl->ug->u.n); - s.id = 0; s.opt = sl->opt; s.ug = sl->ug; s.uopt = sl->uopt; s.rg = sl->rg; s.uu = sl->uu; s.rsc = res; - CALLOC(s.hab, sl->n_thread); CALLOC(s.buf, sl->n_thread); CALLOC(s.ll, sl->n_thread); - CALLOC(s.gdp, sl->n_thread); CALLOC(s.mzs, sl->n_thread); CALLOC(s.sps, sl->n_thread); - - for (i = 0; i < sl->n_thread; ++i) { - s.hab[i] = ha_ovec_init(0, 0, 1); s.buf[i] = mg_tbuf_init(); - } - - // detect_outlier_len("+++work_ul_gchains"); - - kt_for(sl->n_thread, worker_for_ctg_gchains_alignment, &s, s.ug->u.n); - - // detect_outlier_len("---work_ul_gchains"); - - for (i = 0; i < sl->n_thread; ++i) { - s.sum_len += s.hab[i]->num_read_base; s.n += s.hab[i]->num_correct_base; - ha_ovec_destroy(s.hab[i]); mg_tbuf_destroy(s.buf[i]); hc_glchain_destroy(&(s.ll[i])); - hc_gdpchain_destroy(&(s.gdp[i])); kv_destroy(s.mzs[i]); kv_destroy(s.sps[i]); - } - - free(s.hab); free(s.buf); free(s.ll); free(s.gdp); free(s.mzs); free(s.sps); - fprintf(stderr, "[M::%s::] # try:%d, # done:%d\n", __func__, s.sum_len, s.n); - return res; -} - - -void fill_ctg_path_trans_idx(glchain_t *a, uint64_t n, uint64_t qn, uint32_t qoff, uint32_t toff, kv_u_trans_t *ou) -{ - kv_resize(uint64_t, ou->idx, qn); - memset(ou->idx.a, -1, sizeof((*(ou->idx.a)))*qn); - - uint64_t i, k, l, pn; kv_ul_ov_t *s = NULL; u_trans_t *z = NULL; - for(i = pn = 0; i < n; i++) { - s = &(a[i].tk); pn += s->n; - for (k = 1, l = 0; k <= s->n; k++) { - if(k == s->n || s->a[l].qn != s->a[k].qn) { - assert(ou->idx.a[s->a[l].qn] == (uint64_t)-1); - ou->idx.a[s->a[l].qn] = (i<<32)|l; - l = k; - } - } - } - kv_resize(u_trans_t, *ou, ou->n+(pn<<1)); l = ou->n; - - for (i = 0; i < qn; i++) { - if(ou->idx.a[i] == (uint64_t)-1) { - ou->idx.a[i] = 0; continue; - } - s = &(a[ou->idx.a[i]>>32].tk); - for(k = l = (uint32_t)ou->idx.a[i]; k < s->n && s->a[l].qn == s->a[k].qn; k++) { - kv_pushp(u_trans_t, *ou, &z); - z->qn = s->a[k].qn+qoff; z->qs = s->a[k].qs; z->qe = s->a[k].qe; - z->tn = s->a[k].tn+toff; z->ts = s->a[k].ts; z->te = s->a[k].te; - z->rev = s->a[k].rev; z->f = s->a[k].el; z->nw = s->a[k].sec; - z->occ = s->a[k].sec; z->del = 0; - - - kv_pushp(u_trans_t, *ou, &z); - z->tn = s->a[k].qn+qoff; z->ts = s->a[k].qs; z->te = s->a[k].qe; - z->qn = s->a[k].tn+toff; z->qs = s->a[k].ts; z->qe = s->a[k].te; - z->rev = s->a[k].rev; z->f = s->a[k].el; z->nw = s->a[k].sec; - z->occ = s->a[k].sec; z->del = 0; - - } - // p->idx.a[i] = pn - (k - l); p->idx.a[i] <<= 32; p->idx.a[i] |= k - l; ///pn += k - l; - } - // assert(l + (pn<<1) == ou->n); -} - -void work_ctg_path_trans(uldat_t *sl, asg_t *sg, ma_ug_t *qry, scaf_res_t *qry_sc, ma_ug_t *ref, scaf_res_t *ref_sc, ma_ug_t *gfa, kv_u_trans_t *ta, uint32_t qoff, uint32_t toff, bubble_type *bu, kv_u_trans_t *res) -{ - utepdat_t s; uint64_t i; memset(&s, 0, sizeof(s)); - s.id = 0; s.opt = sl->opt; s.ug = sl->ug; s.uopt = sl->uopt; s.rg = sl->rg; s.uu = sl->uu; - CALLOC(s.hab, sl->n_thread); CALLOC(s.buf, sl->n_thread); CALLOC(s.ll, sl->n_thread); - CALLOC(s.gdp, sl->n_thread); CALLOC(s.mzs, sl->n_thread); CALLOC(s.sps, sl->n_thread); - - for (i = 0; i < sl->n_thread; ++i) { - s.hab[i] = ha_ovec_init(0, 0, 1); s.buf[i] = mg_tbuf_init(); - } - - ctdat_t c; memset(&c, 0, sizeof(c)); c.soff = (uint64_t)-1; /**uint8_t *bf = NULL; c.bub = gen_bubble_chain(sg, gfa, (ug_opt_t *)(sl->uopt), &bf, 0); free(bf);**/c.bub = bu; - c.s = &(s); c.qry = qry; c.qry_sc = qry_sc; c.ref = ref; c.ref_sc = ref_sc; c.gfa = gfa; c.ta = ta; - - // detect_outlier_len("+++work_ul_gchains"); - - kt_for(sl->n_thread, worker_for_ctg_trans_alignment, &c, c.qry_sc->n); - - // detect_outlier_len("---work_ul_gchains"); - /**destory_bubbles(c.bub); free(c.bub);**/ - fill_ctg_path_trans_idx(s.ll, sl->n_thread, qry->u.n, qoff, toff, res); - for (i = 0; i < sl->n_thread; ++i) { - s.sum_len += s.hab[i]->num_read_base; s.n += s.hab[i]->num_correct_base; - ha_ovec_destroy(s.hab[i]); mg_tbuf_destroy(s.buf[i]); hc_glchain_destroy(&(s.ll[i])); - hc_gdpchain_destroy(&(s.gdp[i])); kv_destroy(s.mzs[i]); kv_destroy(s.sps[i]); - } - - free(s.hab); free(s.buf); free(s.ll); free(s.gdp); free(s.mzs); free(s.sps); - fprintf(stderr, "[M::%s::] # try:%d, # done:%d\n", __func__, s.sum_len, s.n); -} - -void work_ctg_path_trans_self(uldat_t *sl, asg_t *sg, ma_ug_t *db, scaf_res_t *db_sc, ma_ug_t *gfa, kv_u_trans_t *ta, uint64_t soff, uint64_t is_exact, bubble_type *bu, kv_u_trans_t *res) -{ - utepdat_t s; uint64_t i; memset(&s, 0, sizeof(s)); - s.id = 0; s.opt = sl->opt; s.ug = sl->ug; s.uopt = sl->uopt; s.rg = sl->rg; s.uu = sl->uu; - CALLOC(s.hab, sl->n_thread); CALLOC(s.buf, sl->n_thread); CALLOC(s.ll, sl->n_thread); - CALLOC(s.gdp, sl->n_thread); CALLOC(s.mzs, sl->n_thread); CALLOC(s.sps, sl->n_thread); - - for (i = 0; i < sl->n_thread; ++i) { - s.hab[i] = ha_ovec_init(0, 0, 1); s.buf[i] = mg_tbuf_init(); - } - - ctdat_t c; memset(&c, 0, sizeof(c)); c.soff = soff; c.bub = bu; c.is_exact = is_exact; - c.s = &(s); c.qry = NULL; c.qry_sc = NULL; c.ref = db; c.ref_sc = db_sc; c.gfa = gfa; c.ta = ta; - - // detect_outlier_len("+++work_ul_gchains"); - - kt_for(sl->n_thread, worker_for_ctg_trans_alignment, &c, db_sc->n); - - // detect_outlier_len("---work_ul_gchains"); - fill_ctg_path_trans_idx(s.ll, sl->n_thread, db->u.n, 0, 0, res); - for (i = 0; i < sl->n_thread; ++i) { - s.sum_len += s.hab[i]->num_read_base; s.n += s.hab[i]->num_correct_base; - ha_ovec_destroy(s.hab[i]); mg_tbuf_destroy(s.buf[i]); hc_glchain_destroy(&(s.ll[i])); - hc_gdpchain_destroy(&(s.gdp[i])); kv_destroy(s.mzs[i]); kv_destroy(s.sps[i]); - } - - free(s.hab); free(s.buf); free(s.ll); free(s.gdp); free(s.mzs); free(s.sps); - fprintf(stderr, "[M::%s::] # try:%d, # done:%d\n", __func__, s.sum_len, s.n); -} - -uint64_t work_ul_gchains_consensus(uldat_t *sl) -{ - utepdat_t s; uint64_t i; memset(&s, 0, sizeof(s)); - s.id = 0; s.uopt = sl->uopt; s.rg = sl->rg; s.opt = sl->opt; ///s.ug = sl->ug; s.uu = sl->uu; - // CALLOC(s.buf, sl->n_thread); CALLOC(s.gdp, sl->n_thread); CALLOC(s.mzs, sl->n_thread); - CALLOC(s.hab, sl->n_thread); CALLOC(s.ll, sl->n_thread); ///CALLOC(s.sps, sl->n_thread); - - for (i = 0; i < sl->n_thread; ++i) { - s.hab[i] = ha_ovec_init(0, 0, 1); ///s.buf[i] = mg_tbuf_init(); - } - - // detect_outlier_len("+++work_ul_gchains"); - - //debug - // overall_zdbg = init_mul_debug_prt_t(UL_INF.n); - - kt_for(sl->n_thread, worker_for_contain_consensus, &s, UL_INF.n); - - // detect_outlier_len("---work_ul_gchains"); - - for (i = 0; i < sl->n_thread; ++i) { - s.sum_len += s.hab[i]->num_read_base; s.n += s.hab[i]->num_correct_base; - // hc_gdpchain_destroy(&(s.gdp[i])); kv_destroy(s.mzs[i]); mg_tbuf_destroy(s.buf[i]); - ha_ovec_destroy(s.hab[i]); hc_glchain_destroy(&(s.ll[i])); ///kv_destroy(s.sps[i]); - } - - // free(s.buf); free(s.gdp); free(s.mzs); - free(s.hab); free(s.ll); ///free(s.sps); - fprintf(stderr, "[M::%s::] # try:%d, # done:%d\n", __func__, s.sum_len, s.n); - return s.sum_len; -} - - -void update_contain_dedup_arr(asg64_v *in, uint64_t prefix, asg64_v *res) -{ - if(in->n == 0) return; - uint64_t i, m; - for (i = 0; i < in->n; i++) { - if(in->a[i] == ((uint64_t)-1)) continue; - if(((uint32_t)in->a[i]) == ((uint32_t)-1)) { - m = prefix; m <<= 32; m += i; - kv_push(uint64_t, *res, m); - } - } -} - -uint64_t path_del_topo(asg_t *g, uint64_t v) -{ - uint64_t nv, nw, kw, k, z, w; asg_arc_t *av, *aw; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (k = 0; k < nv; k++){ - if(av[k].del) continue; - w = av[k].v^1; - nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); - for (z = kw = 0; z < nw; z++) { - if(aw[z].del) continue; - if((aw[z].v>>1) != (v>>1)) continue; - kw++; - } - if(kw <= 0) return 0; - } - return 1; -} - -uint64_t tes_path_connec(asg_t *g, uint64_t sn, uint64_t en, uint64_t *pa, uint64_t pn, uint64_t is_single_path, uint64_t *min_ou) -{ - // fprintf(stderr, "-0-[M::%s::]\n", __func__); - if(min_ou) (*min_ou) = 0; - if((sn != (uint64_t)-1) && ((g->seq[sn>>1].del)||(get_arcs(g, sn, NULL, 0)<2))) return 0; - if((en != (uint64_t)-1) && ((g->seq[en>>1].del)||((get_arcs(g, en^1, NULL, 0)<2)))) return 0; - uint64_t nv, k, v, w, i, ou = (uint64_t)-1; asg_arc_t *av; - if((sn != (uint64_t)-1) && (en != (uint64_t)-1) && (!pn)) { - v = sn; w = en; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == w) { - if(((uint64_t)av[k].ou) < ou) ou = av[k].ou; - break; - } - } - if(k >= nv) return 0; - - v = en^1; w = sn^1; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == w) { - if(((uint64_t)av[k].ou) < ou) ou = av[k].ou; - break; - } - } - if(k >= nv) return 0; - - // if(get_arcs(g, sn, NULL, 0) < 2) return 0; - // if(get_arcs(g, en^1, NULL, 0) < 2) return 0; - if(min_ou) (*min_ou) = ou; - return 1; - } - - // fprintf(stderr, "-1-[M::%s::]\n", __func__); - if(sn != (uint64_t)-1) { - v = sn; i = 0; - } else { - v = pa[0]; i = 1; assert(!(pa[0]>>32)); - } - // fprintf(stderr, "-2-[M::%s::]\n", __func__); - for (; i < pn; i++) { - w = pa[i]; assert(!(pa[i]>>32)); - if(g->seq[v>>1].del || g->seq[w>>1].del) return 0; - - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == w) { - if(((uint64_t)av[k].ou) < ou) ou = av[k].ou; - break; - } - } - if(k >= nv) return 0; - - nv = asg_arc_n(g, w^1); av = asg_arc_a(g, w^1); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == (v^1)) { - if(((uint64_t)av[k].ou) < ou) ou = av[k].ou; - break; - } - } - if(k >= nv) return 0; - - if(is_single_path) { - if(v != sn && v != en && get_arcs(g, v, NULL, 0) != 1) return 0; - if(w != sn && w != en && get_arcs(g, w^1, NULL, 0) != 1) return 0; - } - - v = w; - } - // fprintf(stderr, "-3-[M::%s::]\n", __func__); - if(en != (uint64_t)-1) { - w = en; - if(g->seq[v>>1].del || g->seq[w>>1].del) return 0; - // fprintf(stderr, "-3a-[M::%s::]\n", __func__); - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == w) { - if(((uint64_t)av[k].ou) < ou) ou = av[k].ou; - break; - } - } - if(k >= nv) return 0; - // fprintf(stderr, "-3b-[M::%s::]\n", __func__); - nv = asg_arc_n(g, w^1); av = asg_arc_a(g, w^1); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == (v^1)) { - if(((uint64_t)av[k].ou) < ou) ou = av[k].ou; - break; - } - } - if(k >= nv) return 0; - - if(is_single_path) { - if(v != sn && v != en && get_arcs(g, v, NULL, 0) != 1) return 0; - if(w != sn && w != en && get_arcs(g, w^1, NULL, 0) != 1) return 0; - } - } - - - - // fprintf(stderr, "-4-[M::%s::]\n", __func__); - if(!path_del_topo(g, pa[0]^1)) return 0; - // if(sn != ((uint64_t)-1)) { - // v = sn; w = pa[0]; - // nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - // for (k = 0; k < nv; k++) { - // if(av[k].del) continue; - // if(av[k].v == w) break; - // } - // if(k >= nv) return 0; - - // v = pa[0]^1; w = sn^1; - // nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - // for (k = 0; k < nv; k++) { - // if(av[k].del) continue; - // if(av[k].v == w) break; - // } - // if(k >= nv) return 0; - // } - - - - if(!path_del_topo(g, pa[pn-1])) return 0; - // if(en != ((uint64_t)-1)) { - // v = pa[pn-1]; w = en; - // nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - // for (k = 0; k < nv; k++) { - // if(av[k].del) continue; - // if(av[k].v == w) break; - // } - // if(k >= nv) return 0; - - // v = en^1; w = pa[pn-1]^1; - // nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - // for (k = 0; k < nv; k++) { - // if(av[k].del) continue; - // if(av[k].v == w) break; - // } - // if(k >= nv) return 0; - // } - - if(min_ou) (*min_ou) = ou; - return 1; -} - -void append_path_connec(asg_t *g, uint64_t sn, uint64_t en, uint64_t *pa, uint64_t pn, uint64_t min_ou) -{ - uint64_t nv, k, v, w, i, ou; asg_arc_t *av; - if(sn != (uint64_t)-1) { - v = sn; i = 0; - } else { - v = pa[0]; i = 1; - } - - for (; i < pn; i++) { - w = pa[i]; - - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == w) { - ou = av[k].ou; ou += min_ou; - if(ou > OU_MASK) ou = OU_MASK; - av[k].ou = ou; - break; - } - } - assert(k < nv); - - nv = asg_arc_n(g, w^1); av = asg_arc_a(g, w^1); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == (v^1)) { - ou = av[k].ou; ou += min_ou; - if(ou > OU_MASK) ou = OU_MASK; - av[k].ou = ou; - break; - } - } - assert(k < nv); - - v = w; - } - // fprintf(stderr, "-3-[M::%s::]\n", __func__); - if(en != (uint64_t)-1) { - w = en; - // fprintf(stderr, "-3a-[M::%s::]\n", __func__); - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == w) { - ou = av[k].ou; ou += min_ou; - if(ou > OU_MASK) ou = OU_MASK; - av[k].ou = ou; - break; - } - } - assert(k < nv); - - // fprintf(stderr, "-3b-[M::%s::]\n", __func__); - nv = asg_arc_n(g, w^1); av = asg_arc_a(g, w^1); - for (k = 0; k < nv; k++) { - if(av[k].del) continue; - if(av[k].v == (v^1)) { - ou = av[k].ou; ou += min_ou; - if(ou > OU_MASK) ou = OU_MASK; - av[k].ou = ou; - break; - } - } - assert(k < nv); - } -} - - -uint64_t asg_clean_idx_tig(asg_t *g, uint64_t *idx, uint64_t idx_n, uint64_t *srt, uint64_t srt_n, utepdat_t *s) -{ - uint64_t i, k, *a, an, sp, *del_a, del_n, *ref_a, ref_n, *ka, kk, cnt = 0, min_ou; - uint64_t ref_s, ref_e, del_s, del_e; - for (i = 0; i < srt_n; i++) { - a = s->ll[idx[(uint32_t)srt[i]]>>32].srt.a.a; - an = s->ll[idx[(uint32_t)srt[i]]>>32].srt.a.n; - sp = (uint32_t)idx[(uint32_t)srt[i]]; - assert((((uint32_t)a[sp])==((uint32_t)-1)) && ((a[sp]>>32)!=((uint32_t)-1))); - - // fprintf(stderr, "\n+[M::%s::] ((uint32_t)(a[sp]>>32))::%u, ((uint32_t)a[sp])::%u, sp::%lu, an::%lu\n", __func__, - // ((uint32_t)(a[sp]>>32)), ((uint32_t)a[sp]), sp, an); - - k = sp + 1; ref_a = a + k; - for (sp = k; k < an; k++) { - if(a[k] == (uint64_t)-1) break; - } - assert(k < an); - ref_n = k - sp; - // fprintf(stderr, "+[M::%s::] k::%lu\n", __func__, k); - // fprintf(stderr, "+[M::%s::] k::%lu, an::%lu\n", __func__, k, an); - - k++; del_a = a + k; - for (sp = k; k < an; k++) { - if((a[k] != (uint64_t)-1) && (((uint32_t)a[k]) == ((uint32_t)-1))) break; - } - - // assert(k < an);//for the last batch of reads, there is no end marker, so k == an - del_n = k - sp; - - ref_s = ref_e = del_s = del_e = (uint64_t)-1; - if(ref_n > 0 && (ref_a[0]>>32)) ref_s = (uint32_t)ref_a[0]; - if(ref_n > 1 && (ref_a[ref_n-1]>>32)) ref_e = (uint32_t)ref_a[ref_n-1]; - - if(del_n > 0 && (del_a[0]>>32)) del_s = (uint32_t)del_a[0]; - if(del_n > 1 && (del_a[del_n-1]>>32)) del_e = (uint32_t)del_a[del_n-1]; - - // if((ref_e != del_e) || (ref_s != del_s)) { - // fprintf(stderr, "-[M::%s::] idx_n::%lu, idx_n::%lu, ref_n::%lu, del_n::%lu, ref_s::%lu, ref_e::%lu, del_s::%lu, del_e::%lu\n", - // __func__, idx_n, idx_n, ref_n, del_n, ref_s, ref_e, del_s, del_e); - // for (k = 0; k < ref_n; k++) { - // fprintf(stderr, "-[M::ref::] ref_a[k]>>1::%lu\n", ref_a[k]>>1); - // } - // for (k = 0; k < del_n; k++) { - // fprintf(stderr, "-[M::del::] del_a[k]>>1::%lu\n", del_a[k]>>1); - // } - // } - assert(ref_s == del_s); assert(ref_e == del_e); - - if(ref_s != (uint64_t)-1) { - ref_a = ref_a + 1; ref_n--; - } - if(ref_e != (uint64_t)-1) ref_n--; - - if(del_s != (uint64_t)-1) { - del_a = del_a + 1; del_n--; - } - if(del_e != (uint64_t)-1) del_n--; - - if(ref_n == 0 && del_n > 0) { - ka = ref_a; ref_a = del_a; del_a = ka; - kk = ref_n; ref_n = del_n; del_n = kk; - kk = ref_s; ref_s = del_s; del_s = kk; - kk = ref_e; ref_e = del_e; del_e = kk; - } - - // fprintf(stderr, "-[M::%s::] idx_n::%lu, idx_n::%lu, ref_n::%lu, del_n::%lu, ref_s::%lu, ref_e::%lu\n", - // __func__, idx_n, idx_n, ref_n, del_n, ref_s, ref_e); - // for (k = 0; k < ref_n; k++) { - // fprintf(stderr, "-[M::ref::] ref_a[k]>>1::%lu\n", ref_a[k]>>1); - // } - // for (k = 0; k < del_n; k++) { - // fprintf(stderr, "-[M::del::] del_a[k]>>1::%lu\n", del_a[k]>>1); - // } - - - - ///just for debug - // if(ref_s != (uint64_t)-1) { - // assert(get_arcs(g, ref_s, NULL, 0) > 1); - // } - // if(ref_e != (uint64_t)-1) { - // assert(get_arcs(g, ref_e^1, NULL, 0) > 1); - // } - // assert(tes_path_connec(g, ref_s, ref_e, ref_a, ref_n, 0, NULL)); - // assert(tes_path_connec(g, del_s, del_e, del_a, del_n, 1, NULL)); - - min_ou = 0; - if((ref_s!=(uint64_t)-1) && (get_arcs(g, ref_s, NULL, 0)<=1)) continue; - if((ref_e!=(uint64_t)-1) && (get_arcs(g, ref_e^1, NULL, 0)<=1)) continue; - if(!tes_path_connec(g, ref_s, ref_e, ref_a, ref_n, 0, NULL)) continue; - if(!tes_path_connec(g, del_s, del_e, del_a, del_n, 1, &min_ou)) continue; - - if(del_n > 0) { - for (k = 0; k < del_n; k++) asg_seq_del(g, del_a[k]>>1); - cnt += del_n; - } else { - asg_arc_del(g, del_s, del_e, 1); - asg_arc_del(g, del_e^1, del_s^1, 1); - cnt++; - } - if(min_ou > 0) append_path_connec(g, ref_s, ref_e, ref_a, ref_n, min_ou); - } - if(cnt) { - asg_cleanup(g); - } - return cnt; -} - -uint64_t work_rg_contain_dedup(uldat_t *sl) -{ - utepdat_t s; uint64_t i, occ, ou_n, m, *srt, srt_n, *idx, idx_n, tot; - asg64_v ou, bu; kv_init(ou); memset(&s, 0, sizeof(s)); - s.id = 0; s.uopt = sl->uopt; s.rg = sl->rg; s.opt = sl->opt; ///s.ug = sl->ug; s.uu = sl->uu; - // CALLOC(s.buf, sl->n_thread); CALLOC(s.gdp, sl->n_thread); CALLOC(s.mzs, sl->n_thread); - CALLOC(s.hab, sl->n_thread); CALLOC(s.ll, sl->n_thread); ///CALLOC(s.sps, sl->n_thread); - - for (i = 0; i < sl->n_thread; ++i) { - s.hab[i] = ha_ovec_init(0, 0, 1); ///s.buf[i] = mg_tbuf_init(); - } - - // detect_outlier_len("+++work_ul_gchains"); - - //debug - // overall_zdbg = init_mul_debug_prt_t(UL_INF.n); - occ = 1; tot = 0; - while (occ) { - kt_for(sl->n_thread, worker_for_contain_dedup, &s, (s.rg->n_seq<<1)); - for (i = ou.n = 0; i < sl->n_thread; ++i) { - copy_asg_arr(bu, s.ll[i].srt.a); - update_contain_dedup_arr(&bu, i, &ou); - copy_asg_arr(s.ll[i].srt.a, bu); - } - ou_n = ou.n; - for (i = 0; i < ou_n; i++) { - assert(((uint32_t)s.ll[ou.a[i]>>32].srt.a.a[(uint32_t)ou.a[i]]) == ((uint32_t)-1)); - m = s.ll[ou.a[i]>>32].srt.a.a[(uint32_t)ou.a[i]]>>32; m <<= 32; m += i; - kv_push(uint64_t, ou, m); - } - // fprintf(stderr, "[M::%s::] ou_n::%lu, ou.n::%u\n", __func__, ou_n, (uint32_t)ou.n); - idx = ou.a; idx_n = ou_n; srt = ou.a + ou_n; srt_n = ou.n - ou_n; - radix_sort_gfa64(srt, srt + srt_n); - // print_debug_gfa((asg_t *)s.rg, NULL, s.uopt->coverage_cut, "UL.dirty.debug", s.uopt->sources, s.uopt->ruIndex, s.uopt->max_hang, s.uopt->min_ovlp, 0, 0, 0); - occ = asg_clean_idx_tig((asg_t *)s.rg, idx, idx_n, srt, srt_n, &s); - for (i = 0; i < sl->n_thread; ++i) s.ll[i].srt.a.n = 0; - tot += occ; - // fprintf(stderr, "[M::%s::] idx_n::%lu, srt_n::%lu, occ::%lu\n", __func__, idx_n, srt_n, occ); - } - - - - - // detect_outlier_len("---work_ul_gchains"); - - for (i = 0; i < sl->n_thread; ++i) { - s.sum_len += s.hab[i]->num_read_base; s.n += s.hab[i]->num_correct_base; - // hc_gdpchain_destroy(&(s.gdp[i])); kv_destroy(s.mzs[i]); mg_tbuf_destroy(s.buf[i]); - ha_ovec_destroy(s.hab[i]); hc_glchain_destroy(&(s.ll[i])); ///kv_destroy(s.sps[i]); - } - - // free(s.buf); free(s.gdp); free(s.mzs); - free(s.hab); free(s.ll); kv_destroy(ou); ///free(s.sps); - fprintf(stderr, "[M::%s::] # duplicated reads::%lu\n", __func__, tot); - // exit(1); - return tot; -} - -void print_ul_ovlps(all_ul_t *x, int32_t prt_ovlp) -{ - uint64_t k, i, ucov_occ = 0, cov_occ = 0, ucov_len = 0, cov_len = 0, unaligned_len = 0, unaligned_occ = 0, aligned_occ = 0; - ul_vec_t *p = NULL; nid_t *z = NULL; uc_block_t *m = NULL; - for (k = 0; k < x->n; k++) { - z = &(x->nid.a[k]); - p = &(x->a[k]); - fprintf(stderr, "S\t%.*s\tq:id:%lu\tl:%u\tdd:%d\n", (int32_t)z->n, z->a, k, p->rlen, - ((p->bb.n == 1&&p->bb.a[0].base)||(p->bb.n==0))?-1:(int32_t)p->dd); - if(prt_ovlp) { - for (i = 0; i < p->bb.n; i++) { - m = &(p->bb.a[i]); - if(m->base) { - ucov_occ++; - ucov_len += (m->qe-(m->hid&FLANK_M)) - (m->qs+((m->hid>>15)&FLANK_M)); - fprintf(stderr, "B\t%.*s\t%u\t%u\t%u\n", - (int32_t)z->n, z->a, p->rlen, (m->qs+((m->hid>>15)&FLANK_M)), (m->qe-(m->hid&FLANK_M))); - } else { - fprintf(stderr, "A\t%.*s(%lu)\t%u\t%u\t%u\t%c\t%.*s(%u)\t%u\t%u\t%u\n", - (int32_t)z->n, z->a, k, p->rlen, m->qs, m->qe, "+-"[m->rev], - (int32_t)Get_NAME_LENGTH(R_INF, m->hid), Get_NAME(R_INF, m->hid), m->hid, - (uint32_t)Get_READ_LENGTH(R_INF, m->hid), m->ts, m->te); - if(m->el) cov_occ++; - } - } - } - if((p->bb.n == 1 && p->bb.a[0].base)||(p->bb.n == 0)) { - unaligned_len += p->rlen; unaligned_occ++; - } else { - aligned_occ++; - } - cov_len += p->rlen; - } - cov_len -= ucov_len; - fprintf(stderr, "[M::%s::] ==>aligned_occ:%lu, unaligned_occ:%lu\n", __func__, aligned_occ, unaligned_occ); - fprintf(stderr, "[M::%s::] ==>cov_len:%lu, ucov_len:%lu, unaligned_len:%lu\n", - __func__, cov_len, ucov_len-unaligned_len, unaligned_len); -} - -void print_all_ul_t_stat(all_ul_t *x) -{ - uint64_t k, i, ucov_occ = 0, cov_occ = 0, ucov_len = 0, cov_len = 0; - ul_vec_t *p = NULL; - for (k = 0; k < x->n; k++) { - p = &(x->a[k]); - for (i = 0; i < p->bb.n; i++) { - if(p->bb.a[i].base/**.hid&x->mm**/) { - ucov_occ++; - ucov_len += (p->bb.a[i].qe-(p->bb.a[i].hid&FLANK_M)) - - (p->bb.a[i].qs+((p->bb.a[i].hid>>15)&FLANK_M)); - } else { - cov_occ++; - } - } - cov_len += p->rlen; - } - cov_len -= ucov_len; - fprintf(stderr, "[M::%s::] ==>cov_occ:%lu, ucov_occ:%lu\n", __func__, cov_occ, ucov_occ); - fprintf(stderr, "[M::%s::] ==>cov_len:%lu, ucov_len:%lu\n", __func__, cov_len, ucov_len); -} - -void print_ovlp_src_bl_stat(all_ul_t *x, const ug_opt_t *uopt) -{ - uint64_t k, z, tc, ta; - ma_hit_t_alloc* src = uopt->sources; - for (k = tc = ta = 0; k < R_INF.total_reads; k++) { - if(x->ridx.idx.a[k+1] - x->ridx.idx.a[k] == 0) continue; - tc++; - for (z = 0; z < src[k].length; z++) { - if(src[k].buffer[z].bl) { - ta++; - break; - } - } - } - - fprintf(stderr, "[M::%s::] ==> # HiFi reads:%lu, # covered HiFi reads:%lu, # chained HiFi reads:%lu\n", - __func__, R_INF.total_reads, tc, ta); - - uint64_t tt[4] = {0}; - for (k = 0; k < x->n; k++) { - tt[x->a[k].dd]++; - // if(x->a[k].dd == 1) { - // fprintf(stderr, "(%lu) %.*s\n", k, (int32_t)x->nid.a[k].n, x->nid.a[k].a); - // } - } - - fprintf(stderr, "[M::%s::] ==> # passed UL reads:%lu, # fully corrected UL reads:%lu, # almost fully corrected UL reads:%lu, # UL reads have primary chains:%lu\n", - __func__, tt[0]+tt[1]+tt[2]+tt[3], tt[1], tt[2], tt[3]); -} - -void gen_ul_vec_rid_t(all_ul_t *x, All_reads *rdb, ma_ug_t *ug) -{ - ul_vec_rid_t *ridx = &(x->ridx); - uint64_t k, i, l, m, *a, a_n, idx_n; ul_vec_t *p = NULL; - idx_n = (rdb?rdb->total_reads:ug->u.n); - ridx->idx.n = ridx->idx.m = idx_n + 1; CALLOC(ridx->idx.a, ridx->idx.n); - - for (k = 0; k < x->n; k++) {///each UL read - p = &(x->a[k]); - for (i = 0; i < p->bb.n; i++) { - if(p->bb.a[i].base) continue; - ridx->idx.a[p->bb.a[i].hid]++; - } - } - - for (k = l = 0; k < ridx->idx.n; k++) { - m = ridx->idx.a[k]; - ridx->idx.a[k] = l; - l += m; - } - - ridx->occ.n = ridx->occ.m = l; MALLOC(ridx->occ.a, ridx->occ.n); - for (k = 0; k < idx_n; k++) { - a = ridx->occ.a + ridx->idx.a[k]; - a_n = ridx->idx.a[k+1] - ridx->idx.a[k]; - if(a_n) a[a_n-1] = 0; - } - - for (k = 0; k < x->n; k++) { - p = &(x->a[k]); - for (i = 0; i < p->bb.n; i++) { - if(p->bb.a[i].base) continue; - a = ridx->occ.a + ridx->idx.a[p->bb.a[i].hid]; - a_n = ridx->idx.a[p->bb.a[i].hid+1] - ridx->idx.a[p->bb.a[i].hid]; - if(a_n) { - if(a[a_n-1] == a_n-1) a[a_n-1] = (k<<32)|i; - else a[a[a_n-1]++] = (k<<32)|i; - } - } - } -} - - -uint32_t ugl_cover_check(uint64_t is, uint64_t ie, ma_utg_t *u) -{ - if(is == 0 && ie == u->len) return 1; - uint64_t l, i, us, ue; - for (i = l = 0; i < u->n; i++) { - us = l; ue = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); - if(is <= us && ie >= ue) return 1; - if(us >= ie) break; - l += (uint32_t)u->a[i]; - } - return 0; -} - -static void update_ug_arch_ul(void *data, long i, int tid) // callback for kt_for() -{ - const ma_ug_t *ug = (ma_ug_t *)data; - asg_arc_t *e = &(ug->g->arc[i]); e->ou = 0; - uint32_t v = e->ul>>32, w = e->v, k, uv, uw; - uint64_t *a, a_n; uc_block_t *p, *n; - a = UL_INF.ridx.occ.a + UL_INF.ridx.idx.a[v>>1]; - a_n = UL_INF.ridx.idx.a[(v>>1)+1] - UL_INF.ridx.idx.a[v>>1]; - for (k = 0; k < a_n; k++) { - p = &(UL_INF.a[a[k]>>32].bb.a[(uint32_t)(a[k])]); - if(p->base || (!p->el) || (!p->pchain)) continue; - uv = (((uint32_t)(p->hid))<<1)|((uint32_t)(p->rev)); - if((uv == v) && (p->aidx != (uint32_t)-1)) { - n = &(UL_INF.a[a[k]>>32].bb.a[p->aidx]); - assert((!n->base)&&(n->el)&&(n->pchain)&&(n->pidx==((uint32_t)(a[k])))); - uw = (((uint32_t)(n->hid))<<1)|((uint32_t)(n->rev)); - if(uw == w) e->ou++; - } - - if(((uv^1) == v) && (p->pidx != (uint32_t)-1)) { - n = &(UL_INF.a[a[k]>>32].bb.a[p->pidx]); - // if(!((!n->base)&&(n->el)&&(n->pchain)&&(n->aidx==((uint32_t)(a[k]))))) { - // fprintf(stderr, "ulid->%ld, n->base::%u, n->el::%u, n->pchain::%u, n->aidx::%u, ((uint32_t)(a[k]))::%u\n", - // i, n->base, n->el, n->pchain, n->aidx, ((uint32_t)(a[k]))); - // } - assert((!n->base)&&(n->el)&&(n->pchain)&&(n->aidx==((uint32_t)(a[k])))); - uw = (((uint32_t)(n->hid))<<1)|((uint32_t)(n->rev)); uw ^= 1; - if(uw == w) e->ou++; - } - } -} - -void update_ug_arch_ul_mul(ma_ug_t *ug) -{ - kt_for(asm_opt.thread_num, update_ug_arch_ul, ug, ug->g->n_arc); -} - -static void filter_short_ulalignments(void *data, long i, int tid) // callback for kt_for() -{ - const ma_ug_t *ug = (ma_ug_t *)data; - uc_block_t *a = NULL; uc_block_t *p; int64_t k, a_n; uint32_t z, fz, lz, l, bz; - a = UL_INF.a[i].bb.a; a_n = UL_INF.a[i].bb.n; - - for (k = a_n - 1; k >= 0; k--) { - p = &(a[k]); - // if(i == 338344) { - // fprintf(stderr, "+[M::%s::id->%ld::rlen->%u::glen->%u] (%ld) utg%.6dl, q::[%u, %u), t::[%u, %u), pidx::%u, aidx::%u, pdis::%u, a[k].base::%u, a[k].el::%u, a[k].pchain::%u\n", - // __func__, i, UL_INF.a[i].rlen, ug->u.a[p->hid].len, k, (int32_t)a[k].hid+1, a[k].qs, a[k].qe, a[k].ts, a[k].te, a[k].pidx, a[k].aidx, a[k].pdis, - // a[k].base, a[k].el, a[k].pchain); - // } - if(p->base || (!p->el) || (!p->pchain)) continue; - if(p->pidx == (uint32_t)-1) { - if(!ugl_cover_check(p->ts, p->te, &(ug->u.a[p->hid]))) { - p->pchain = 0; - if(p->aidx != (uint32_t)-1) { - a[p->aidx].pidx = a[p->aidx].pdis = (uint32_t)-1; p->aidx = (uint32_t)-1; - } - } - continue; - } - if(ugl_cover_check(p->ts, p->te, &(ug->u.a[p->hid]))) continue; - for (z = p->pidx; z != (uint32_t)-1; z = a[z].pidx) { - if(ugl_cover_check(a[z].ts, a[z].te, &(ug->u.a[a[z].hid]))) break; - } - lz = z; fz = p->aidx; l = 0; if(fz != (uint32_t)-1) l = a[fz].pdis; - for (z = k; z != lz; z = bz) { - bz = a[z].pidx; l += a[z].pdis; - a[z].pidx = a[z].pdis = a[z].aidx = (uint32_t)-1; a[z].pchain = 0; - } - - if(fz != (uint32_t)-1 && lz != (uint32_t)-1) { - a[fz].pdis = l; a[fz].pidx = lz; a[lz].aidx = fz; - } else if(fz != (uint32_t)-1) { - a[fz].pdis = a[fz].pidx = (uint32_t)-1; - } else if(lz != (uint32_t)-1) { - a[lz].aidx = (uint32_t)-1; - } - } - - for (k = a_n - 1; k >= 0; k--) { - p = &(a[k]); - if(p->base || (!p->el) || (!p->pchain)) continue; - if(p->pidx != (uint32_t)-1) { - if((a[p->pidx].aidx != ((uint32_t)k)) && (a[p->pidx].aidx == ((uint32_t)-1))) { - p->pidx = (uint32_t)-1; - } else { - assert(a[p->pidx].aidx == (uint32_t)k); - assert(a[p->pidx].pchain); - } - } - if(p->aidx != (uint32_t)-1) { - if((a[p->aidx].pidx != (uint32_t)k) && (a[p->aidx].pidx == ((uint32_t)-1))) { - p->aidx = (uint32_t)-1; - } else { - assert(a[p->aidx].pidx == (uint32_t)k); - assert(a[p->aidx].pchain); - } - - } - } - - for (k = a_n - 1; k >= 0; k--) { - p = &(a[k]); - if(p->base || (!p->el) || (!p->pchain)) continue; - // if(i == 338344) { - // fprintf(stderr, "-[M::%s::id->%ld::rlen->%u::glen->%u] (%ld) utg%.6dl, q::[%u, %u), t::[%u, %u), pidx::%u, aidx::%u, pdis::%u, a[k].base::%u, a[k].el::%u, a[k].pchain::%u\n", - // __func__, i, UL_INF.a[i].rlen, ug->u.a[p->hid].len, k, (int32_t)a[k].hid+1, a[k].qs, a[k].qe, a[k].ts, a[k].te, a[k].pidx, a[k].aidx, a[k].pdis, - // a[k].base, a[k].el, a[k].pchain); - // } - if(p->pidx != (uint32_t)-1) { - // if(!(a[p->pidx].aidx == (uint32_t)k)) { - // fprintf(stderr, "[M::%s::id->%ld] name::%.*s, a_n::%ld\n", __func__, - // i, (int32_t)UL_INF.nid.a[i].n, UL_INF.nid.a[i].a, a_n); - // } - assert(a[p->pidx].aidx == (uint32_t)k); - assert(a[p->pidx].pchain); - } - if(p->aidx != (uint32_t)-1) { - // if(a[p->aidx].pidx != (uint32_t)k) { - // fprintf(stderr, "[M::%s::id->%ld] name::%.*s, a_n::%ld, p->aidx::%u, p->pidx::%u, a[p->aidx].pidx::%u\n", __func__, i, (int32_t)UL_INF.nid.a[i].n, UL_INF.nid.a[i].a, a_n, - // p->aidx, p->pidx, a[p->aidx].pidx); - // } - assert(a[p->aidx].pidx == (uint32_t)k); - assert(a[p->aidx].pchain); - } - } -} - - -static void dcheck_ulalignments_mul(void *data, long i, int tid) // callback for kt_for() -{ - if(!ck_ul_alignment(&(UL_INF.a[i]))) UL_INF.a[i].rlen |= (uint32_t)(0x80000000); -} - - - -void print_ul_alignment(ma_ug_t *ug, all_ul_t *aln, uint32_t id, const char* cmd) -{ - uc_block_t *a = NULL; int64_t k, a_n; - a = aln->a[id].bb.a; a_n = aln->a[id].bb.n; - fprintf(stderr, "\n%s::[M::%s::ul_id->%u::a_n->%ld]\n", cmd, __func__, id, a_n); - for (k = 0; k < a_n; k++) { - fprintf(stderr, "[k->%ld::utg%.6d%c(len->%u)]\tts::%u\tte::%u\t%c\tqs::%u\tqe::%u\tpchain::%u\tpidx::%u\taidx::%u\tpdis::%u\n", - k, a[k].hid + 1, "lc"[ug->u.a[a[k].hid].circ], ug->u.a[a[k].hid].len, - a[k].ts, a[k].te, "+-"[a[k].rev], a[k].qs, a[k].qe, a[k].pchain, a[k].pidx, a[k].aidx, a[k].pdis); - - } - -} - - -void filter_ul_ug(ma_ug_t *ug) -{ - kt_for(asm_opt.thread_num, filter_short_ulalignments, ug, UL_INF.n); -} - - -int32_t find_ul_block_max_reverse(int32_t n, const uc_block_t *a, uint32_t x) -{ - int32_t s = 0, e = n; - if (n == 0) return n; - if (a[0].qe < x) return 0;///max qe - if (a[n-1].qe >= x) return n;///min qe - - while (e > s) { // TODO: finish this block - int32_t m = s + (e - s) / 2; - // if (a[m].qe >= x) e = m; - // else s = m + 1; - if (a[m].qe > x) s = m + 1; - else e = m; - } - assert(s == e); - return s; -} - -int32_t find_ul_block_max(int32_t n, const uc_block_t *a, uint32_t x) -{ - int32_t s = 0, e = n; - if (n == 0) return -1; - if (a[n-1].qe < x) return n - 1; - if (a[0].qe >= x) return -1; - while (e > s) { // TODO: finish this block - int32_t m = s + (e - s) / 2; - if (a[m].qe >= x) e = m; - else s = m + 1; - } - assert(s == e); - return s; -} -/** -void determine_connective(all_ul_t *m, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, ul_vec_t *p, uint32_t ii, uint64_t rid) -{ - if((p->bb.a[ii].base) || p->bb.a[ii].hid != rid) fprintf(stderr, "ERROR\n"); - if(p->bb.n <= ii + 1) return; - uint32_t li_v, lk_v, k, ol; int64_t mm_ovlp, x; - uc_block_t *li = NULL, *lk = NULL; - ma_hit_t *t = NULL; - li = &(p->bb.a[ii]); li_v = (((uint32_t)(li->hid))<<1)|((uint32_t)(li->rev)); - mm_ovlp = max_ovlp_src(uopt, li_v^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > p->rlen+1) x = p->rlen+1; - x = find_ul_block_max_rev(p->bb.n - ii - 1, p->bb.a + ii + 1, x) + ii + 1; - for (k = x; k < p->bb.n; ++k) { // collect potential destination vertices - lk = &(p->bb.a[k]); lk_v = (((uint32_t)(lk->hid))<<1)|((uint32_t)(lk->rev)); - if(lk->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore - if((li_v == lk_v) || (lk->base)) continue; - // if(li->qs <= 0) continue;///means the UL read does not longer than the overlap between li and lk - // if(lk->qs <= 0) continue;//the UL read should be cover the whole HiFi reads li and lk - if(((li->te - li->ts)*1.05) < Get_READ_LENGTH(R_INF, li->hid)) continue; - if(((lk->te - lk->ts)*1.05) < Get_READ_LENGTH(R_INF, lk->hid)) continue; - x = infer_rovlp(NULL, NULL, li, lk, &R_INF, NULL); - t = query_ovlp_src(uopt, li_v^1, lk_v^1, x, diff_ec_ul, &ol); - if(t) { - // sum = t->bl + ol; - // t->bl = (sum & 0x7fffffffU); - t->bl++; - } - } -} -**/ - -///note: we only label reliable chains -void determine_connective_adv(all_ul_t *m, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, ul_vec_t *p, uint32_t ii, uint64_t rid) -{ - assert((!p->bb.a[ii].base)&&(p->bb.a[ii].hid == rid)); - if(ii <= 0) return; - if(!(p->bb.a[ii].pchain)) return; ///not a primary chain - if(!(p->bb.a[ii].el)) return; ///not a cis alignment - uint32_t li_v, lk_v, ol; int64_t mm_ovlp, k, x; - uc_block_t *li = NULL, *lk = NULL; - ma_hit_t *t = NULL; - li = &(p->bb.a[ii]); li_v = (((uint32_t)(li->hid))<<1)|((uint32_t)(li->rev)); - mm_ovlp = max_ovlp_src(uopt, li_v^1); - x = (li->qs + mm_ovlp)*diff_ec_ul; - if(x < bw) x = bw; - x += li->qs + mm_ovlp; - if (x > p->rlen+1) x = p->rlen+1; - x = find_ul_block_max(ii, p->bb.a, x+G_CHAIN_INDEL); - for (k = x; k >= 0; --k) { // collect potential destination vertices - lk = &(p->bb.a[k]); lk_v = (((uint32_t)(lk->hid))<<1)|((uint32_t)(lk->rev)); - if(lk->qe+G_CHAIN_INDEL <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore - if(lk->base || (!(lk->pchain)) || (!(lk->el))) continue; - if(li_v == lk_v) continue; - // if(li->qs <= 0) continue;///means the UL read does not longer than the overlap between li and lk - // if(lk->qs <= 0) continue;//the UL read should be cover the whole HiFi reads li and lk - // if(((li->te - li->ts)*1.05) < Get_READ_LENGTH(R_INF, li->hid)) continue; - // if(((lk->te - lk->ts)*1.05) < Get_READ_LENGTH(R_INF, lk->hid)) continue; - if((li->te - li->ts) < Get_READ_LENGTH(R_INF, li->hid)) continue; - if((lk->te - lk->ts) < Get_READ_LENGTH(R_INF, lk->hid)) continue; - x = /**((int64_t)(lk->qe))-((int64_t)(li->qs))**/infer_rovlp(NULL, NULL, li, lk, &R_INF, NULL); - t = query_ovlp_src(uopt, li_v^1, lk_v^1, x, diff_ec_ul, &ol); - if(t) { - // sum = t->bl + ol; - // t->bl = (sum & 0x7fffffffU); - t->bl++; - } - } -} - -void determine_connective_backtrack(all_ul_t *m, const ug_opt_t *uopt, ul_vec_t *p, uint32_t ii, uint64_t rid, uint64_t ulid) -{ - assert((!p->bb.a[ii].base)&&(p->bb.a[ii].hid == rid)&&(p->bb.a[ii].el)); - if(ii <= 0) return; - if(!(p->bb.a[ii].pchain)) return; ///not a primary chain - if(p->bb.a[ii].pidx == (uint32_t)-1) return; ///not connected - uint32_t li_v, lk_v, z, qn, tn; int32_t r; uc_block_t *li = NULL, *lk = NULL; asg_arc_t t; - li = &(p->bb.a[ii]); li_v = (((uint32_t)(li->hid))<<1)|((uint32_t)(li->rev)); li_v^=1; - if((li->te - li->ts) < Get_READ_LENGTH(R_INF, li->hid)) return; - ma_hit_t_alloc *x = &(uopt->sources[li_v>>1]); - int64_t min_ovlp = uopt->min_ovlp; - int64_t max_hang = uopt->max_hang; - // if(rid == 4217) fprintf(stderr, "rid: %lu, p->bb.n: %u\n", rid, p->bb.n); - - for (lk = &(p->bb.a[li->pidx]); lk; ) { - lk_v = (((uint32_t)(lk->hid))<<1)|((uint32_t)(lk->rev)); lk_v^=1; - assert((!(lk->base)) && (lk->pchain) && (lk->el)); - if((lk->te - lk->ts) >= Get_READ_LENGTH(R_INF, lk->hid)) { - for (z = 0; z < x->length; z++) { - qn = Get_qn(x->buffer[z]); - tn = Get_tn(x->buffer[z]); - if(qn == (li_v>>1) && tn == (lk_v>>1)) { - r = ma_hit2arc(&(x->buffer[z]), Get_READ_LENGTH(R_INF, li_v>>1), Get_READ_LENGTH(R_INF, lk_v>>1), - max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - if(r < 0) continue; - if((t.ul>>32) != li_v || t.v != lk_v) continue; - break; - } - } - if(z < x->length) { - x->buffer[z].bl++; - // if(((li_v>>1) == 1656459) || ((li_v>>1) == 4179430)|| - // ((lk_v>>1) == 1656459) || ((lk_v>>1) == 4179430)) { - // fprintf(stderr, "[M::%s::]\tulid::%lu\n", __func__, ulid); - // } - } - } - - lk = ((lk->pidx==(uint32_t)-1)?NULL:&(p->bb.a[lk->pidx])); - } -} - -static void update_ovlp_src(void *data, long i, int tid) // callback for kt_for() -{ - uldat_t *sl = (uldat_t *)data; - ma_hit_t_alloc* src = sl->uopt->sources; - uint64_t z, k, *a, a_n; - for (z = 0; z < src[i].length; z++) src[i].buffer[z].bl = 0; - a = UL_INF.ridx.occ.a + UL_INF.ridx.idx.a[i]; - a_n = UL_INF.ridx.idx.a[i+1] - UL_INF.ridx.idx.a[i]; - // fprintf(stderr, "++i->%d, a_n->%lu++\n", i, a_n); - for (k = 0; k < a_n; k++) { - ///note: we only label reliable chains - // if(i == 4217) fprintf(stderr, "\nul_id: %lu\n", a[k]>>32); - determine_connective_backtrack(&UL_INF, sl->uopt, &(UL_INF.a[a[k]>>32]), (uint32_t)(a[k]), i, a[k]>>32); - // determine_connective_adv(&UL_INF, sl->uopt, G_CHAIN_BW, sl->opt->diff_ec_ul, &(UL_INF.a[a[k]>>32]), (uint32_t)(a[k]), i); - // determine_connective(&UL_INF, sl->uopt, G_CHAIN_BW, sl->opt->diff_ec_ul, - // &(UL_INF.a[a[k]>>32]), (uint32_t)(a[k]), i); - } - // fprintf(stderr, "--i->%d, a_n->%lu--\n", i, a_n); -} - - -static void clean_contained_chg(void *data, long i, int tid) // callback for kt_for() -{ - uldat_t *sl = (uldat_t *)data; - sl->rg->seq_vis[i] = 0; - if(sl->rg->seq[i].del) return; - if(!(is_contain_r((*(sl->uopt->ruIndex)), ((uint64_t)i)))) return; - ma_hit_t_alloc* src = sl->uopt->sources; - uint64_t z; - for (z = 0; z < src[i].length; z++) { - if(src[i].buffer[z].bl) break; - } - if(z >= src[i].length) sl->rg->seq_vis[i] = 1; -} - -static void label_contained_chg(void *data, long i, int tid) // callback for kt_for() -{ - uldat_t *sl = (uldat_t *)data; uint32_t v = i; - sl->rg->seq_vis[v] = 0; - if(sl->rg->seq[v>>1].del) return; - if(is_contain_r((*(sl->uopt->ruIndex)), (v>>1))) { - sl->rg->seq_vis[v] = 1; return; - } - asg_arc_t *av = asg_arc_a(sl->rg, v); - uint32_t nv = asg_arc_n(sl->rg, v), k; - for (k = 0; k < nv; ++k) { - if(av[k].del) continue; - if(is_contain_r((*(sl->uopt->ruIndex)), (av[k].v>>1))) break; - } - if(k < nv) sl->rg->seq_vis[v] = 1; -} - - -uint64_t* get_hifi2ul_list(all_ul_t *x, uint64_t hid, uint64_t* a_n) -{ - (*a_n) = x->ridx.idx.a[hid+1] - x->ridx.idx.a[hid]; - return x->ridx.occ.a + x->ridx.idx.a[hid]; -} - - -static void update_ovlp_src_bl(void *data, long i, int tid) -{ - uldat_t *sl = (uldat_t *)data; - ma_hit_t_alloc* src = sl->uopt->sources; - uint64_t z, sum; uint32_t qn, tn; int32_t idx; - for (z = 0; z < src[i].length; z++) { - qn = Get_qn(src[i].buffer[z]); - tn = Get_tn(src[i].buffer[z]); - if(qn > tn) continue; - idx = get_specific_overlap(&(src[tn]), tn, qn); - assert(idx != -1); - sum = src[i].buffer[z].bl + src[tn].buffer[idx].bl; - src[i].buffer[z].bl = src[tn].buffer[idx].bl = sum/**(sum&0x7fffffffU)**/; - } -} - -int scall_ul_pipeline(uldat_t* sl, const enzyme *fn) -{ - double index_time = yak_realtime(); - int i; - - init_all_ul_t(&UL_INF, &R_INF); - for (i = 0; i < fn->n; i++){ - gzFile fp; - if ((fp = gzopen(fn->a[i], "r")) == 0) return 0; - sl->ks = kseq_init(fp); - kt_pipeline(3, worker_ul_scall_pipeline, sl, 3); - kseq_destroy(sl->ks); - gzclose(fp); - } - sl->hits.total_base = sl->total_base; - sl->hits.total_pair = sl->total_pair; - fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); - fprintf(stderr, "[M::%s::] ==> # reads: %lu, # bases: %lu\n", __func__, UL_INF.n, sl->total_base); - // fprintf(stderr, "[M::%s::] ==> # bases: %lu; # corrected bases: %lu; # recorrected bases: %lu\n", - // __func__, sl->num_bases, sl->num_corrected_bases, sl->num_recorrected_bases); - fprintf(stderr, "[M::%s::] ==> # fully covered reads: %lu\n", __func__, sl->num_bases); - gen_ul_vec_rid_t(&UL_INF, &R_INF, NULL); - return 1; -} - - -int rescall_ul_pipeline(uldat_t* sl, const enzyme *fn) -{ - double index_time = yak_realtime(); - int32_t i; - ///debug - // overall_zdbg = init_mul_debug_prt_t(UL_INF.n); - - for (i = 0; i < fn->n; i++){ - gzFile fp; - if ((fp = gzopen(fn->a[i], "r")) == 0) return 0; - sl->ks = kseq_init(fp); - kt_pipeline(3, worker_ul_rescall_pipeline, sl, 3); - kseq_destroy(sl->ks); - gzclose(fp); - } - sl->hits.total_base = sl->total_base; - sl->hits.total_pair = sl->total_pair; - fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); - fprintf(stderr, "[M::%s::] ==> # reads: %lu, # bases: %lu, # fully corrected reads: %lu\n", - __func__, UL_INF.n, sl->total_base, sl->num_corrected_bases); - // fprintf(stderr, "[M::%s::] ==> # bases: %lu; # corrected bases: %lu; # recorrected bases: %lu\n", - // __func__, sl->num_bases, sl->num_corrected_bases, sl->num_recorrected_bases); - // gen_ul_vec_rid_t(&UL_INF); - // for (i = 0; i < UL_INF.n; i++) { - // fprintf(stderr, "[M::%s] rid::%d, dd::%u\n", __func__, i, UL_INF.a[i].dd); - // } - // print_mul_debug_prt_t(asm_opt.output_file_name, overall_zdbg); - // print_raw_uls_seq_direct(sl->uu->ug, &UL_INF, asm_opt.output_file_name); - - return 1; -} - - -int recorrect_ul_pipeline(uldat_t* sl, const enzyme *fn) -{ - double index_time = yak_realtime(); - int32_t i; - - for (i = 0; i < fn->n; i++){ - gzFile fp; - if ((fp = gzopen(fn->a[i], "r")) == 0) return 0; - sl->ks = kseq_init(fp); - kt_pipeline(2, worker_ul_recorrect_pipeline, sl, 2); - kseq_destroy(sl->ks); - gzclose(fp); - } - sl->hits.total_base = sl->total_base; - sl->hits.total_pair = sl->total_pair; - fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); - fprintf(stderr, "[M::%s::] ==> # reads: %lu, # processed reads: %lu, # fixed reads: %lu\n", - __func__, UL_INF.n, sl->num_bases, sl->num_corrected_bases); - // fprintf(stderr, "[M::%s::] ==> # bases: %lu; # corrected bases: %lu; # recorrected bases: %lu\n", - // __func__, sl->num_bases, sl->num_corrected_bases, sl->num_recorrected_bases); - // gen_ul_vec_rid_t(&UL_INF); - return 1; -} - -int print_ul_rs(all_ul_t *U_INF) -{ - uint32_t i; - UC_Read ur; - init_UC_Read(&ur); - for (i = 0; i < U_INF->n; i++) { - retrieve_ul_t(&ur, NULL, U_INF, i, 0, 0, -1); - fprintf(stderr, ">%s\n", U_INF->nid.a[i].a); - fprintf(stderr, "%.*s\n", (int)ur.length, ur.seq); - } - - destory_UC_Read(&ur); - return 1; -} - -inline void get_ulname(mg_dbn_t *name, int32_t rid, char **rn, int32_t *rl) -{ - (*rn) = name->cc.a + (rid>0?name->a[rid-1]:0); - (*rl) = name->a[rid] - (rid>0?name->a[rid-1]:0); -} - -void print_gaf(const ma_ug_t *ug, mg_gres_a *hits, mg_dbn_t *name) -{ - uint64_t i, q; - int32_t k, nl, m; - char *nn; mg_gchain_t *gc; mg_lres_t *lc; - for (i = 0; i < hits->n; i++) { - q = hits->a[i].qid; - nn = name->cc.a + (q>0?name->a[q-1]:0); - nl = name->a[q] - (q>0?name->a[q-1]:0); - for (k = 0; k < hits->a[i].n_gc; k++) { - gc = &(hits->a[i].gc[k]); - fprintf(stderr, "S\t%.*s\tq:id:%lu\tl:n:%d\n", nl, nn, q, gc->cnt); - for (m = 0; m < gc->cnt; m++) { - lc = &(hits->a[i].lc[gc->off + m]); - fprintf(stderr, "*\tA\tutg%.6d%c\t%c\tqs:%u\tqe:%u\tql:%lu\tts:%u\tte:%u\ttl:%u\tcnt:%d\n", - (lc->v>>1)+1, "lc"[ug->u.a[lc->v>>1].circ], "+-"[lc->v&1], lc->qs, lc->qe, hits->a[i].qlen, lc->ts, lc->te, ug->u.a[lc->v>>1].len, lc->cnt); - } - } - } -} - -void write_ul_hits(mg_gres_a *hits, mg_dbn_t *nn, const char *fn) -{ - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.ul.aln.bin", fn); - FILE* fp = fopen(buf, "w"); - uint32_t i; - - fwrite(&hits->n, sizeof(hits->n), 1, fp); - for (i = 0; i < hits->n; i++) { - fwrite(&hits->a[i].qid, sizeof(hits->a[i].qid), 1, fp); - fwrite(&hits->a[i].qlen, sizeof(hits->a[i].qlen), 1, fp); - fwrite(&hits->a[i].n_gc, sizeof(hits->a[i].n_gc), 1, fp); - fwrite(&hits->a[i].n_lc, sizeof(hits->a[i].n_lc), 1, fp); - fwrite(hits->a[i].gc, sizeof(mg_gchain_t), hits->a[i].n_gc, fp); - fwrite(hits->a[i].lc, sizeof(mg_lres_t), hits->a[i].n_lc, fp); - } - // fwrite(hits->a, sizeof(mg_gres_t), hits->n, fp); - fwrite(&hits->total_pair, sizeof(hits->total_pair), 1, fp); - fwrite(&hits->total_base, sizeof(hits->total_base), 1, fp); - - fwrite(&(nn->n), sizeof(nn->n), 1, fp); - fwrite(nn->a, sizeof(uint64_t), nn->n, fp); - fwrite(&(nn->tl), sizeof(nn->tl), 1, fp); - fwrite(&(nn->cc.n), sizeof(nn->cc.n), 1, fp); - fwrite(nn->cc.a, sizeof(char), nn->cc.n, fp); - // write_dbug(ug, fp); - - fclose(fp); - fprintf(stderr, "[M::%s::] ==> UL alignments have been written\n", __func__); - free(buf); -} - -int load_ul_hits(mg_gres_a *hits, mg_dbn_t *nn, const char *fn) -{ - uint64_t flag = 0; - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.ul.aln.bin", fn); - - FILE* fp = NULL; - fp = fopen(buf, "r"); - if(!fp) { - free(buf); - return 0; - } - uint32_t i; - - kv_init(*hits); - flag += fread(&hits->n, sizeof(hits->n), 1, fp); - hits->m = hits->n; MALLOC(hits->a, hits->n); - for (i = 0; i < hits->n; i++) { - flag += fread(&hits->a[i].qid, sizeof(hits->a[i].qid), 1, fp); - flag += fread(&hits->a[i].qlen, sizeof(hits->a[i].qlen), 1, fp); - flag += fread(&hits->a[i].n_gc, sizeof(hits->a[i].n_gc), 1, fp); - flag += fread(&hits->a[i].n_lc, sizeof(hits->a[i].n_lc), 1, fp); - MALLOC(hits->a[i].gc, hits->a[i].n_gc); MALLOC(hits->a[i].lc, hits->a[i].n_lc); - flag += fread(hits->a[i].gc, sizeof(mg_gchain_t), hits->a[i].n_gc, fp); - flag += fread(hits->a[i].lc, sizeof(mg_lres_t), hits->a[i].n_lc, fp); - } - // flag += fread(hits->a, sizeof(mg_gres_t), hits->n, fp); - flag += fread(&hits->total_pair, sizeof(hits->total_pair), 1, fp); - flag += fread(&hits->total_base, sizeof(hits->total_base), 1, fp); - - memset(nn, 0, sizeof(*nn)); - flag += fread(&(nn->n), sizeof(nn->n), 1, fp); - nn->m = nn->n; MALLOC(nn->a, nn->n); - flag += fread(nn->a, sizeof(uint64_t), nn->n, fp); - flag += fread(&(nn->tl), sizeof(nn->tl), 1, fp); - flag += fread(&(nn->cc.n), sizeof(nn->cc.n), 1, fp); - nn->cc.m = nn->cc.n; MALLOC(nn->cc.a, nn->cc.n); - flag += fread(nn->cc.a, sizeof(char), nn->cc.n, fp); - - free(buf); - - // if(!test_dbug(ug, fp)) - // { - // free(hits->a.a); - // kv_init(hits->a); - // fclose(fp); - // fprintf(stderr, "[M::%s::] ==> Renew Hi-C linkages\n", __func__); - // return 0; - // } - - fclose(fp); - fprintf(stderr, "[M::%s::] ==> UL alignments have been loaded\n", __func__); - return 1; -} - -void get_asm_cov(ma_ug_t *ug, uint64_t ul_base, mul_ov_t *aov) -{ - int64_t ss = asm_opt.hg_size; - if(ss < 0) { - uint64_t i, k, an; - int64_t sp; - asg_t *g = ug->g; - asg_arc_t *av = NULL; - for (i = 0, ss = 0; i < g->n_seq; i++) { - sp = g->seq[i].len; av = asg_arc_a(g, i); an = asg_arc_n(g, i); - for (k = 0; k < an; k++) { - if(av[k].del) continue; - if((av[k].v) < i) { - sp -= ((int64_t)av[k].ol); - } - } - if(sp > 0) ss += sp; - } - } else { - ss *= asm_opt.polyploidy; - } - - if(ss <= 0) ss = 1; - - aov->asm_cov = ul_base/ss; aov->asm_size = ss; - fprintf(stderr, "[M::%s::] ==> asm_cov: %lu, asm_size: %lu\n", __func__, aov->asm_cov, aov->asm_size); -} - -int32_t spec_ovlp_occ(eg_srt_t *a, int32_t a_n, int32_t st, int32_t vv, int32_t c_thres) -{ - int32_t i, dst = a[st].d, occ = 1; - if(occ >= c_thres) return 1; - for (i = st + 1; i < a_n; i++) { - if(a[i].id == a[st].id) continue; - if(a[i].d - dst <= vv) { - occ++; - if(occ >= c_thres) return 1; - } - } - - for (i = st - 1; i >= 0; i--) { - if(a[i].id == a[st].id) continue; - if(dst - a[i].d <= vv) { - occ++; - if(occ >= c_thres) return 1; - } - } - return 0; -} - - -int32_t get_spec_ovlp_occ(eg_srt_t *a, int32_t a_n, int32_t st, int32_t vv, int32_t c_thres, int32_t *s, int32_t *e, kvec_t_u64_warp *res) -{ - int32_t i, dst = a[st].d, occ = 1, pp; - (*s) = (*e) = st; res->a.n = 0; - for (i = st + 1; i < a_n; i++) { - if(a[i].d - dst <= vv) { - (*e) = i; - if(a[i].id == a[st].id) continue; - occ++; kv_push(uint64_t, res->a, (((uint64_t)(a[i].id))<<32)|i); - } else { - break; - } - } - - for (i = st - 1; i >= 0; i--) { - if(dst - a[i].d <= vv) { - (*s) = i; - if(a[i].id == a[st].id) continue; - occ++; kv_push(uint64_t, res->a, (((uint64_t)(a[i].id))<<32)|i); - } else { - break; - } - } - if(occ >= c_thres) { - radix_sort_gfa64(res->a.a, res->a.a + res->a.n); - for (i = 0, pp = -1, occ = 0; i < (int32_t)res->a.n; i++) { - if((int32_t)(res->a.a[i]>>32) != pp) { - pp = (res->a.a[i]>>32); - res->a.a[occ] = res->a.a[i]; - occ++; - } - } - res->a.n = occ; - if(occ >= c_thres) return occ; - return 0; - } - else { - return 0; - } -} - -void clean_ul_g(asg_t *xg) -{ - uint32_t n_vtx = xg->n_seq * 2, v, i, nv, ie = 0, ike = 0; - asg_arc_t *av = NULL; - uint8_t* bs_flag = NULL; CALLOC(bs_flag, n_vtx); - buf_t b; memset(&b, 0, sizeof(buf_t)); b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); - uint64_t max_dist = get_bub_pop_max_dist_advance(xg, &b); - for (v = 0; v < xg->n_seq; v++) xg->seq[v].c = 0; - for (v = 0; v < n_vtx; ++v) { - if(bs_flag[v] != 0) continue; - if (asg_arc_n(xg, v) < 2 || xg->seq[v>>1].del) continue; - if(asg_bub_pop1_primary_trio(xg, NULL, v, max_dist, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (i = 0; i < b.b.n; i++) { - if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; - bs_flag[b.b.a[i]] = bs_flag[b.b.a[i]^1] = 1; - } - bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 3; - } - } - - for (v = 0; v < n_vtx; ++v) { - if(bs_flag[v] != 0) continue; - nv = asg_arc_n(xg, v); - if (nv >= 2) { - av = asg_arc_a(xg, v); - for (i = 0; i < nv; ++i){ - if (av[i].ol == 0) { - av[i].del = 1; - asg_arc_del(xg, av[i].v^1, (av[i].ul>>32)^1, 1); - // fprintf(stderr, "---q0-utg%.6d%c, q1-utg%.6d%c\n", - // (int32_t)((av[i].ul>>33)+1), "lc"[ug->u.a[av[i].ul>>33].circ], - // (int32_t)((av[i].v)>>1)+1, "lc"[ug->u.a[av[i].v].circ]); - } - - // fprintf(stderr, "xxxx-nv: %u, q0-utg%.6d%c, q1-utg%.6d%c\n", nv, - // (int32_t)((av[i].ul>>33)+1), "lc"[ug->u.a[av[i].ul>>33].circ], - // (int32_t)((av[i].v)>>1)+1, "lc"[ug->u.a[av[i].v].circ]); - } - } - } - - for (i = 0; i < xg->n_arc; i++) { - if(xg->arc[i].ol == 0) { - ie++; - if(!xg->arc[i].del) ike++; - } - } - - fprintf(stderr, "[M::%s::] ==> # fill gaps: %u, # keep gaps: %u\n", __func__, ie, ike); - free(bs_flag); free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); -} - -// int32_t max_cluster(int32_t mmi, double vv, int32_t min_off, eg_srt_t *a, int32_t a_n, int32_t st, int32_t st_occ, int32_t *s, int32_t *e, kvec_t_u64_warp *res) -// { -// int32_t i, k, iocc, ovlp; -// for (i = st, iocc = 0; i < k; i++) { -// ovlp = (a[i].d > mmi? a[i].d - mmi: mmi - a[i].d) * vv; -// if(ovlp < min_off) ovlp = min_off; -// // fprintf(stderr, "i-%lu, ovlp: %d, td.a[i].d: %d, qid: %u\n", i, ovlp, td.a[i].d, td.a[i].id); -// // if(spec_ovlp_occ(td.a + l, k-l, i - l, ovlp, c_thres)) break; -// iocc = get_spec_ovlp_occ(td.a + l, k-l, i - l, ovlp, c_thres, &is, &ie, &tidx); -// if(iocc >= c_thres) break; -// } -// } - -void get_ul_g(mul_ov_t *aov, mg_gres_a *hits, ma_ug_t *ug, const asg_t *rg, -double cov_thres, double vv, int32_t min_off, int32_t min_read_ovlp) -{ - int64_t c_thres = (aov->asm_cov*cov_thres)>2?(aov->asm_cov*cov_thres):2; - uint64_t i, k, l, m, v0, v1, r0, r1; - int32_t qs, qe, rs, re, qs0, qe0, qs1, qe1, ovlp, mmi, nngc2 = 0, is, ie, iocc, m_iocc, max_i; - mg_gres_t *p = NULL; - mg_gchain_t *gc = NULL, *gc0, *gc1; - mg_lres_t *lf = NULL, *ll = NULL; - asg_t *xg = copy_read_graph(ug->g); - asg_arc_t *pe = NULL; - kvec_t(lc_srt_t) tt; kv_init(tt); lc_srt_t *pt = NULL; - kvec_t(eg_srt_t) td; kv_init(td); eg_srt_t *pd = NULL; - kvec_t_u64_warp tidx; kv_init(tidx.a); - ///for debug - kvec_t(eg_srt_t) dbg_vw_srt; kv_init(dbg_vw_srt); - for (i = 0; i < hits->n; i++) { - // fprintf(stderr, "+i+: %lu\n",i); - p = &(hits->a[i]); tt.n = 0; - // fprintf(stderr, "-i-: %lu\n",i); - if(p->n_gc < 2) continue; - nngc2++; - // fprintf(stderr, "\nsis: %lu, p->n_gc: %d\n",i,p->n_gc); - for (k = 0; k < (uint64_t)p->n_gc; k++) { - gc = &(p->gc[k]); - assert(gc->cnt > 0); - lf = &(p->lc[gc->off]); ll = gc->cnt>1?&(p->lc[gc->off+gc->cnt-1]):NULL; - assert(lf->qs != (uint32_t)-1); - if(ll) assert(ll->qs != (uint32_t)-1); - - transfor_icoord(lf->qs, lf->qe, lf->ts, lf->te, lf->v&1, p->qlen, ug->g->seq[lf->v>>1].len, - &qs, ll?NULL:&qe, &rs, ll?NULL:&re); - if(ll) { - transfor_icoord(ll->qs, ll->qe, ll->ts, ll->te, ll->v&1, p->qlen, ug->g->seq[ll->v>>1].len, - NULL, &qe, NULL, &re); - } else { - ll = lf; - } - if(qe - qs < min_read_ovlp || re - rs < min_read_ovlp) continue; - kv_pushp(lc_srt_t, tt, &pt); - pt->qse = qs; pt->qse <<= 32; pt->qse |= qe; - pt->rse = rs; pt->rse <<= 32; pt->rse |= re; - pt->gld = i; pt->gld <<= 32; pt->gld |= k; - // fprintf(stderr, ">>>>k: %lu, qs: %d, qe: %d, qs-utg%.6d%c, qe-utg%.6d%c\n", k, qs, qe, - // (int32_t)((lf->v>>1)+1), "lc"[ug->u.a[lf->v>>1].circ], - // (int32_t)((ll->v>>1)+1), "lc"[ug->u.a[ll->v>>1].circ]); - // fprintf(stderr, "lf_qs: %u, lf_qe: %u, lf_ts: %u, lf_te: %u\n", lf->qs, lf->qe, lf->ts, lf->te); - // fprintf(stderr, "ll_qs: %u, ll_qe: %u, ll_ts: %u, ll_te: %u\n", ll->qs, ll->qe, ll->ts, ll->te); - } - // fprintf(stderr, "eie: %lu\n",i); - radix_sort_lc_srt(tt.a, tt.a + tt.n); - for (k = 0; k < tt.n; k++) { - for (m = k + 1; m < tt.n; m++) { - gc0 = &(p->gc[(uint32_t)(tt.a[k].gld)]); - v0 = p->lc[gc0->off+gc0->cnt-1].v; - gc1 = &(p->gc[(uint32_t)(tt.a[m].gld)]); - v1 = p->lc[gc1->off].v; - if((v0>>1) == (v1>>1)) continue; - - qs0 = tt.a[k].qse>>32; qe0 = (uint32_t)(tt.a[k].qse); - qs1 = tt.a[m].qse>>32; qe1 = (uint32_t)(tt.a[m].qse); - // fprintf(stderr, "++++k: %lu, qs0: %d, qe0: %d, qs1: %d, qe1: %d, q0-utg%.6d%c, q1-utg%.6d%c\n", - // k, qs0, qe0, qs1, qe1, (int32_t)((v0>>1)+1), "lc"[ug->u.a[v0>>1].circ], (int32_t)((v1>>1)+1), "lc"[ug->u.a[v1>>1].circ]); - if(qs1 <= qs0 && qe1 >= qe0) continue;///contain - if(qs0 <= qs1 && qe0 >= qe1) continue;///contain - if(ug->u.a[v0>>1].circ || ug->u.a[v1>>1].circ) continue; - ovlp = ((MIN((qe0), (qe1)) > MAX((qs0), (qs1)))? MIN((qe0), (qe1)) - MAX((qs0), (qs1)):0); - r0 = v0&1?(ug->u.a[v0>>1].start>>1):(ug->u.a[v0>>1].end>>1); - r1 = v1&1?(ug->u.a[v1>>1].end>>1):(ug->u.a[v1>>1].start>>1); - // fprintf(stderr, "----k: %lu, ovlp: %d\n", k, ovlp); - // if((ovlp == 0) || (ovlp <= ((qe0 - qs0)*vv) && ovlp <= ((qe1 - qs1)*vv)) || - // (asg_arc_n(ug->g, v0) == 0 && asg_arc_n(ug->g, v1^1) == 0)) { - if(/**(asg_arc_n(ug->g, v0) == 0 && asg_arc_n(ug->g, v1^1) == 0) - && **/(ovlp < (int32_t)(MIN(rg->seq[r0].len, rg->seq[r1].len)))) { - kv_pushp(eg_srt_t, td, &pd); - pd->d = MAX((qs0), (qs1)) - MIN((qe0), (qe1)); - pd->x = v0id = p->qid; - pd->e = (uint32_t)(tt.a[k].gld); - pd->e <<= 32; pd->e |= (uint32_t)(tt.a[m].gld); - } - } - } - } - fprintf(stderr, "td.n: %d\n", (int)td.n); - radix_sort_eg_srt_x(td.a, td.a + td.n); - for (k = 1, l = 0; k <= td.n; ++k) - { - if (k == td.n || td.a[k].x != td.a[l].x) - { - if(k - l >= (uint64_t)c_thres) { - for (i = l+1, mmi = l; i < k; i++) { - if(td.a[mmi].d > td.a[i].d) mmi = i; - } - mmi = td.a[mmi].d < 0? -td.a[mmi].d:0; - if(mmi != 0) { - for (i = l; i < k; i++) td.a[i].d += mmi; - } - - - radix_sort_eg_srt_d(td.a + l, td.a + k); - for (i = l, iocc = 0, tidx.a.n = 0; i < k; i++) { - ovlp = (td.a[i].d > mmi? td.a[i].d - mmi: mmi - td.a[i].d) * vv; - if(ovlp < min_off) ovlp = min_off; - // fprintf(stderr, "i-%lu, ovlp: %d, td.a[i].d: %d, qid: %u\n", i, ovlp, td.a[i].d, td.a[i].id); - // if(spec_ovlp_occ(td.a + l, k-l, i - l, ovlp, c_thres)) break; - iocc = get_spec_ovlp_occ(td.a + l, k-l, i - l, ovlp, c_thres, &is, &ie, &tidx); - // fprintf(stderr, "c_thres-%ld, iocc-%d\n", c_thres, iocc); - if(iocc >= c_thres) break; - } - - - - if(i < k) { - m_iocc = iocc; max_i = i; - for (i = ie + 1; i < k; i++) { - iocc = get_spec_ovlp_occ(td.a + l, k-l, i - l, ovlp, m_iocc, &is, &ie, &tidx); - if(iocc > m_iocc) m_iocc = iocc, max_i = i; - i = ie + l; - } - ///for debug - kv_pushp(eg_srt_t, dbg_vw_srt, &pd); - pd->x = m_iocc; pd->e = td.a[l].x; - - v0 = (uint32_t)td.a[l].x; v1 = td.a[l].x>>32; - pe = asg_arc_pushp(xg); - pe->del = 0; pe->strong = 0; pe->el = 0; pe->no_l_indel = 0; pe->ol = 0; - pe->v = v0; pe->ul = v1<<32; pe->ul += xg->seq[v1>>1].len; - - v0 = (td.a[l].x>>32)^1; v1 = ((uint32_t)td.a[l].x)^1; - pe = asg_arc_pushp(xg); - pe->del = 0; pe->strong = 0; pe->el = 0; pe->no_l_indel = 0; pe->ol = 0; - pe->v = v0; pe->ul = v1<<32; pe->ul += xg->seq[v1>>1].len; - - // fprintf(stderr, "++++q0-utg%.6d%c, q1-utg%.6d%c, k-l: %lu, c_thres: %ld, flag: %u\n", - // (int32_t)((td.a[l].x>>33)+1), "lc"[ug->u.a[td.a[l].x>>33].circ], - // (int32_t)(((uint32_t)td.a[l].x)>>1)+1, "lc"[ug->u.a[(((uint32_t)td.a[l].x)>>1)].circ], k-l, c_thres, - // (asg_arc_n(ug->g, ((uint32_t)td.a[l].x)^1) == 0 && asg_arc_n(ug->g, (td.a[l].x>>32)) == 0)); - } - } - l = k; - } - } - - xg->is_srt = 0; xg->idx = 0; free(xg->idx); - asg_cleanup(xg); - clean_ul_g(xg); - - ///for debug - fprintf(stderr, "[M::%s::] ==> nngc2: %d\n", __func__, nngc2); - radix_sort_eg_srt_x(dbg_vw_srt.a, dbg_vw_srt.a + dbg_vw_srt.n); - for (max_i = (int32_t)dbg_vw_srt.n - 1; max_i >= 0; --max_i) { - pd = &(dbg_vw_srt.a[max_i]); - fprintf(stderr, "++++q0-utg%.6d%c, q1-utg%.6d%c, occ: %lu, c_thres: %ld, flag: %u\n", - (int32_t)((pd->e>>33)+1), "lc"[ug->u.a[pd->e>>33].circ], - (int32_t)(((uint32_t)pd->e)>>1)+1, "lc"[ug->u.a[(((uint32_t)pd->e)>>1)].circ], pd->x, c_thres, - (asg_arc_n(ug->g, ((uint32_t)pd->e)^1) == 0 && asg_arc_n(ug->g, (pd->e>>32)) == 0)); - } - - - kv_destroy(tt); kv_destroy(td); kv_destroy(tidx.a); kv_destroy(dbg_vw_srt); - asg_destroy(xg); -} - -int ul_align(mg_idxopt_t *opt, const ug_opt_t *uopt, const asg_t *rg, const enzyme *fn, void *ha_flt_tab, ha_pt_t *ha_idx, ma_ug_t *ug) -{ - uldat_t sl; memset(&sl, 0, sizeof(sl)); - sl.ha_flt_tab = ha_flt_tab; - sl.ha_idx = ha_idx; - sl.opt = opt; - sl.chunk_size = 200000000; - sl.n_thread = asm_opt.thread_num; - sl.ug = ug; - sl.rg = rg; - sl.uopt = uopt; - if(!load_ul_hits(&sl.hits, &sl.nn, asm_opt.output_file_name)) { - alignment_ul_pipeline(&sl, fn); - write_ul_hits(&sl.hits, &sl.nn, asm_opt.output_file_name); - } - - mul_ov_t aov; memset(&aov, 0, sizeof(aov)); - get_asm_cov(ug, sl.hits.total_base, &aov); - fprintf(stderr, "[M::%s::] ==> total_pair: %lu, total_base: %lu, n: %d\n", - __func__, sl.hits.total_pair, sl.hits.total_base, (int32_t)sl.hits.n); - - - - get_ul_g(&aov, &sl.hits, ug, rg, 0.51, 0.1, 500, 1000); - - - - // print_gaf(ug, &(sl.hits), &(sl.nn)); - mg_gres_a_des(&(sl.hits)); free(sl.nn.a); free(sl.nn.cc.a); - return 1; -} - -void ul_resolve(ma_ug_t *ug, const asg_t *rg, const ug_opt_t *uopt, int hap_n) -{ - fprintf(stderr, "[M::%s::] ==> UL\n", __func__); - mg_idxopt_t opt; - init_mg_opt(&opt, 0, 19, 10, hap_n, 0, 0, 0.05, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); - int exist = (asm_opt.load_index_from_disk? uidx_load(&ha_flt_tab, &ha_idx, asm_opt.output_file_name, NULL) : 0); - if(exist == 0) uidx_build(ug, &opt); - if(exist == 0) uidx_write(ha_flt_tab, ha_idx, asm_opt.output_file_name, NULL); - ul_align(&opt, uopt, rg, asm_opt.ar, ha_flt_tab, ha_idx, ug); - uidx_destory(); -} - -void ul_v_call(uldat_t *sl, const enzyme *fn) -{ - scall_ul_pipeline(sl, fn); - // UL_INF; - // print_ul_rs(&UL_INF); - // debug_retrieve_rc_sub(uopt, &UL_INF, &R_INF, (ul_idx_t *)sl.uu, 100); - // if(!load_ul_hits(&sl.hits, &sl.nn, asm_opt.output_file_name)) { - // scall_ul_pipeline(&sl, fn); - // write_ul_hits(&sl.hits, &sl.nn, asm_opt.output_file_name); - // } -} - -void ul_v_recall(uldat_t *sl, const enzyme *fn) -{ - rescall_ul_pipeline(sl, fn); - // UL_INF; - // print_ul_rs(&UL_INF); - // debug_retrieve_rc_sub(uopt, &UL_INF, &R_INF, (ul_idx_t *)sl.uu, 100); - // if(!load_ul_hits(&sl.hits, &sl.nn, asm_opt.output_file_name)) { - // scall_ul_pipeline(&sl, fn); - // write_ul_hits(&sl.hits, &sl.nn, asm_opt.output_file_name); - // } -} - -void print_dedup_HiFis_seq(ma_ug_t *ug) -{ - uint64_t i; - ma_utg_t *p = NULL; - for (i = 0; i < ug->u.n; i++) { - p = &(ug->u.a[i]); - CALLOC(p->s, p->len+1); - retrieve_u_seq(NULL, p->s, p, 0, 0, -1, NULL); - p->s[p->len] = '\0'; - } - - FILE* output_file = fopen("dedup_HiFis_seq.gfa", "w"); - ma_ug_print(ug, NULL, NULL, NULL, NULL, "utg", output_file); - fclose(output_file); - - output_file = fopen("dedup_HiFis_seq.noseq.gfa", "w"); - ma_ug_print_simple(ug, NULL, NULL, NULL, NULL, "utg", output_file); - fclose(output_file); - exit(1); -} - -void push_coverage_track(ucov_t *cc, ul_contain *ct, uint64_t uid, ma_utg_t *u, asg_t *rg, ma_hit_t_alloc* src, int64_t min_ovlp, int64_t max_hang, uint64_t is_el, uint64_t is_del) -{ - uint64_t k, l, z, dp, ct_n; utg_ct_t *ct_a = NULL; - cc->idx[uid] = cc->interval.n; - ct_n = ((uint32_t)(ct->idx.a[uid])); ct_a = ct->rids.a + ((ct->idx.a[uid])>>32); - for (z = 0; z < ct_n; z++) { - kv_push(uint64_t, cc->interval, ct_a[z].s<<1); - kv_push(uint64_t, cc->interval, (ct_a[z].e<<1)|1); - } - for (k = l = 0; k < u->n; k++) { - kv_push(uint64_t, cc->interval, l<<1); - kv_push(uint64_t, cc->interval, ((l + Get_READ_LENGTH(R_INF, u->a[k]>>33))<<1)|1); - /** - i = u->a[k]>>33;///rid - for (z = 0; z < src[i].length; z++) { - if(is_el && (!src[i].buffer[z].el)) continue; - if(is_del && (!src[i].buffer[z].del)) continue; - qn = Get_qn(src[i].buffer[z]); tn = Get_tn(src[i].buffer[z]); - if(!rg->seq[tn].del) continue; - if((Get_qe(src[i].buffer[z]) - Get_qs(src[i].buffer[z])) < min_ovlp) continue; - if((Get_te(src[i].buffer[z]) - Get_ts(src[i].buffer[z])) < min_ovlp) continue; - r = ma_hit2arc(&(src[i].buffer[z]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - if(r != MA_HT_TCONT) continue;///tn is contained - ori = (u->a[k]>>32)&1; - if(ori == 0) { - qs = Get_qs(src[i].buffer[z]); qe = Get_qe(src[i].buffer[z]); - } else { - qs = (Get_READ_LENGTH(R_INF, i)) - Get_qe(src[i].buffer[z]); - qe = (Get_READ_LENGTH(R_INF, i)) - Get_qs(src[i].buffer[z]); - } - kv_push(uint64_t, cc->interval, (l+qs)<<1); - kv_push(uint64_t, cc->interval, ((l+qe)<<1)|1); - } - **/ - l += (uint32_t)u->a[k]; - } - cc->idx[uid+1] = cc->interval.n; - - - radix_sort_gfa64(cc->interval.a+cc->idx[uid], cc->interval.a+cc->interval.n); - for (k = cc->idx[uid], dp = 0; k < cc->interval.n; ++k) { - ///if a[j] is qe - if (cc->interval.a[k]&1) --dp; - else ++dp; - l = cc->interval.a[k]>>1; l <<= 32; l += dp; - cc->interval.a[k] = l; - } -} - - -uint32_t check_if_fully_contain(uint32_t sid, uint32_t lid, uint32_t ori, uint8_t *rset, asg_t *rg, -ma_hit_t_alloc* src, int64_t min_ovlp, int64_t max_hang, int64_t gap_fuzz) -{ - uint32_t rid, k, qn, tn, ff = 1; int32_t r; asg_arc_t t; - return 1; - - rid = lid; - for (k = 0; k < src[rid].length; k++) { - if(!src[rid].buffer[k].el) continue; - qn = Get_qn(src[rid].buffer[k]); tn = Get_tn(src[rid].buffer[k]); - if(rg->seq[qn].del || rg->seq[tn].del) continue; - if((Get_qe(src[rid].buffer[k]) - Get_qs(src[rid].buffer[k])) < min_ovlp) continue; - if((Get_te(src[rid].buffer[k]) - Get_ts(src[rid].buffer[k])) < min_ovlp) continue; - r = ma_hit2arc(&(src[rid].buffer[k]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - if(r < 0) continue; - rset[t.v] = ((t.ul>>32)&1)+1; - } - - - - rid = sid; - for (k = 0; k < src[rid].length; k++) { - if(!src[rid].buffer[k].el) continue; - qn = Get_qn(src[rid].buffer[k]); tn = Get_tn(src[rid].buffer[k]); - if(rg->seq[qn].del || rg->seq[tn].del) continue; - if((Get_qe(src[rid].buffer[k]) - Get_qs(src[rid].buffer[k])) < min_ovlp) continue; - if((Get_te(src[rid].buffer[k]) - Get_ts(src[rid].buffer[k])) < min_ovlp) continue; - r = ma_hit2arc(&(src[rid].buffer[k]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - if(r < 0) continue; - if(rset[t.v] != ((((t.ul>>32)&1)^ori)+1)) { - ff = 0; - break; - } - } - - - rid = lid; - for (k = 0; k < src[rid].length; k++) { - if(!src[rid].buffer[k].el) continue; - qn = Get_qn(src[rid].buffer[k]); tn = Get_tn(src[rid].buffer[k]); - if(rg->seq[qn].del || rg->seq[tn].del) continue; - if((Get_qe(src[rid].buffer[k]) - Get_qs(src[rid].buffer[k])) < min_ovlp) continue; - if((Get_te(src[rid].buffer[k]) - Get_ts(src[rid].buffer[k])) < min_ovlp) continue; - r = ma_hit2arc(&(src[rid].buffer[k]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - if(r < 0) continue; - rset[t.v] = 0; - } - - return ff; -} - -ul_contain *ul_contain_gen(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc* src, int64_t min_ovlp, int64_t max_hang, uint64_t is_el, uint64_t is_del) -{ - uint64_t k, l, i, z, t, qn, tn, ori, qs, qe, ovlp, o_z, o_r, o_o; - ul_contain *p = NULL; ma_utg_t *u = NULL; - utg_ct_t *m = NULL; - int32_t r; asg_arc_t e; - CALLOC(p, 1); - p->idx.n = p->idx.m = ug->u.n; CALLOC(p->idx.a, p->idx.n); - p->is_c.n = rg->n_seq; CALLOC(p->is_c.a, p->is_c.n); - for (t = 0; t < ug->u.n; t++) { - u = &(ug->u.a[t]); - p->idx.a[t] = p->rids.n; p->idx.a[t] <<= 32; - - for (k = l = 0; k < u->n; k++) { - i = u->a[k]>>33;///rid - - for (z = 0; z < src[i].length; z++) { - if(is_el && (!src[i].buffer[z].el)) continue; - if(is_del && (!src[i].buffer[z].del)) continue; - qn = Get_qn(src[i].buffer[z]); tn = Get_tn(src[i].buffer[z]); - if(!rg->seq[tn].del) continue; - if((Get_qe(src[i].buffer[z]) - Get_qs(src[i].buffer[z])) < min_ovlp) continue; - if((Get_te(src[i].buffer[z]) - Get_ts(src[i].buffer[z])) < min_ovlp) continue; - r = ma_hit2arc(&(src[i].buffer[z]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &e); - if(r != MA_HT_TCONT) continue;///tn is contained - p->is_c.a[qn] = 1; - ori = (u->a[k]>>32)&1; - if(ori == 0) { - qs = Get_qs(src[i].buffer[z]); qe = Get_qe(src[i].buffer[z]); - } else { - qs = (Get_READ_LENGTH(R_INF, i)) - Get_qe(src[i].buffer[z]); - qe = (Get_READ_LENGTH(R_INF, i)) - Get_qs(src[i].buffer[z]); - } - qs += l; qe += l; - kv_pushp(utg_ct_t, p->rids, &m); - m->x = tn; m->x <<= 1; m->x |= (src[i].buffer[z].rev == ori?0:1); - m->s = qs; m->e = qe/** + 1**/; - } - - l += (uint32_t)u->a[k]; - } - - radix_sort_utg_ct_t_x_srt(p->rids.a + (p->idx.a[t]>>32), p->rids.a + p->rids.n); - /** - for (k = (p->idx.a[t]>>32) + 1, l = i = (p->idx.a[t]>>32); k <= p->rids.n; ++k) { - if (k == p->rids.n || (p->rids.a[k].x>>1) != (p->rids.a[l].x>>1)) { - p->rids.a[i] = p->rids.a[l]; i++; - l = k; - } - } - **/ - for (k = (p->idx.a[t]>>32) + 1, l = i = (p->idx.a[t]>>32); k <= p->rids.n; ++k) { - if (k == p->rids.n || p->rids.a[k].x != p->rids.a[l].x) { - for (z = l; z < k; z++) { - for (r = (int64_t)i-1; r >= 0 && p->rids.a[r].x == p->rids.a[z].x; r--) { - ovlp = ((MIN(p->rids.a[z].e, p->rids.a[r].e) > MAX(p->rids.a[z].s, p->rids.a[r].s))? - (MIN(p->rids.a[z].e, p->rids.a[r].e) - MAX(p->rids.a[z].s, p->rids.a[r].s)):0); - if(ovlp) { - o_z = p->rids.a[z].e - p->rids.a[z].s; - o_r = p->rids.a[r].e - p->rids.a[r].s; - o_o = MIN(o_z, o_r); - if((ovlp <= o_o*1.05) && (ovlp >= o_o*0.95)) break; - } - // if(p->rids.a[z].s == p->rids.a[r].s && p->rids.a[z].e == p->rids.a[r].e) break; - } - if(r >= 0 && p->rids.a[r].x == p->rids.a[z].x) continue; - p->rids.a[i++] = p->rids.a[z]; - } - l = k; - } - } - p->rids.n = i; - - radix_sort_utg_ct_t_s_srt(p->rids.a + (p->idx.a[t]>>32), p->rids.a + p->rids.n); - p->idx.a[t] |= (p->rids.n - (p->idx.a[t]>>32)); - } - - // fprintf(stderr, "p->rids.n:%u, p->idx.n:%u\n", (uint32_t)p->rids.n, (uint32_t)p->idx.n); - - return p; -} - -void gen_hpc_seq(const char *in, uint32_t in_len, ma_utg_t *ou, hmap_t *mm, uint32_t hpc_id) -{ - uint32_t k, l, m; int64_t n; memset(ou, 0, sizeof((*ou))); - for (l = 0, k = 1; k <= in_len; k++) { - if((k == in_len) || (in[k] != in[l]) || (seq_nt4_table[(uint8_t)in[l]] >= 4)) { - ou->len++; l = k; - } - } - kv_resize(uint8_t, *mm, mm->n+ou->len); - mm->idx[hpc_id] = ((uint64_t)mm->n)<<32; - - ou->len <<= 1; - MALLOC(ou->s, ou->len); m = 0; - for (l = 0, k = 1; k <= in_len; k++) { - if((k == in_len) || (in[k] != in[l]) || (seq_nt4_table[(uint8_t)in[l]] >= 4)) { - ou->s[m++] = in[l]; - n = k-l; - while(n >= 0) {///even if n == 0, need to keep it - if(n < 255) { - kv_push(uint8_t, *mm, n); break; - } else { - kv_push(uint8_t, *mm, 255); n -= 255; - } - } - l = k; - } - } - l = m; mm->idx[hpc_id] += (mm->n - (mm->idx[hpc_id]>>32)); - for (k = 0; k < l; k++) ou->s[m++] = RC_CHAR(ou->s[l-k-1]); - - - -} - -void gen_microsatellite(const char *in, uint32_t in_len, ma_utg_t *idx, hpc_t *res, uint32_t mcs_len) -{ - uint32_t k, i, l, c, o; char sk[256]; - idx->start = idx->end = res->n; - if(mcs_len > 256) mcs_len = 256; - for (k = 1; k <= mcs_len; k++) { - memset(sk, 'N', k); ///k->length of k-mer - o = k + (k>>1) + 1; - for (i = l = 0; i < in_len; i++) { - c = seq_nt4_table[(uint8_t)in[i]]; - if((c < 4) && (((l >= k) && (sk[l%k] == in[i])) || (l < k))) { - if(l < k) sk[l] = in[i]; - l++; - } else { - if(l >= o) { - kv_push(uint64_t, *res, (((uint64_t)(i-l))<<1)); - kv_push(uint64_t, *res, ((((uint64_t)i)<<1)|1)); - } - l = 0; - } - } - } - - radix_sort_gfa64(res->a+idx->start, res->a+res->n); - int64_t dp, old_dp; uint64_t st, en; - for (k = st = idx->start, dp = 0; k < res->n; k++) { - old_dp = dp; - if (res->a[k]&1) --dp;//qe - else ++dp; - if (old_dp < 1 && dp >= 1) {///qs - st = res->a[k]>>1; - } else if (old_dp >= 1 && dp < 1) {///qe - en = res->a[k]>>1; - res->a[idx->end++] = ((st<<32)|(en)); - } - } - res->n = idx->end; -} - -uint32_t hpc_l(char *s, int64_t hof, int64_t sof, int64_t scut) -{ - if(scut == sof) return hof; - if(scut < sof) sof = hof = 0; - int64_t l, k; - for (k=sof; (k>0)&&(k= 4)) { - hof++; l = k; - } - } - return hof; -} - -hpc_t *hpc_g_gen(ma_ug_t *ug) -{ - uint32_t k, i, ho, so, len; int32_t z; hpc_t *p; kvec_t(char) cc; asg_t *ng = asg_init(); - CALLOC(p, 1); CALLOC(p->hg, 1); kv_init(cc); CALLOC(p->mm, 1); - CALLOC(p->hg->u.a, ug->u.n); p->hg->u.n = p->hg->u.m = ug->u.n; - CALLOC(p->mm->idx, ug->u.n); - - for (k = 0; k < ug->u.n; k++) { - kv_resize(char, cc, ug->u.a[k].len); - retrieve_u_seq(NULL, cc.a, &(ug->u.a[k]), 0, 0, ug->u.a[k].len, NULL); - gen_hpc_seq(cc.a, ug->u.a[k].len, &(p->hg->u.a[k]), p->mm, k); - gen_microsatellite(cc.a, ug->u.a[k].len, &(p->hg->u.a[k]), p, 6); - } - - ng->m_arc = ng->n_arc = ug->g->n_arc; CALLOC(ng->arc, ng->n_arc); - ng->m_seq = ng->n_seq = ug->g->n_seq; CALLOC(ng->seq, ng->n_seq); - for (k = 0; k < ng->n_seq; k++) { - ng->seq[k].del = ng->seq[k].c = 0; ng->seq[k].len = p->hg->u.a[k].len>>1;///hpc len - } - memcpy(ng->arc, ug->g->arc, ng->n_arc*(sizeof((*(ng->arc))))); - for (k = 1, i = 0; k <= ng->n_arc; k++) { - if(k == ng->n_arc || (ng->arc[i].ul>>32) != (ng->arc[k].ul>>32)) { - //sorted by ol - len = ng->arc[i].ol; kv_resize(char, cc, len); - retrieve_u_seq(NULL, cc.a, &(ug->u.a[ng->arc[i].ul>>33]), ((ng->arc[i].ul>>32)&1)^1, 0, len, NULL); - // min_o = ng->arc[k-1].ol; max_o = ng->arc[i].ol; - len = ng->seq[ng->arc[i].ul>>33].len;///hpc len - for (z = k-1, ho = so = 0; z >= (int32_t)i; z--) { - ho = hpc_l(cc.a, ho, so, ng->arc[z].ol); - so = ng->arc[z].ol; - ng->arc[z].ol = ho; - ng->arc[z].ul>>=32; - ng->arc[z].ul<<=32; - ng->arc[z].ul += len - ng->arc[z].ol; - assert(z == (int32_t)k-1 || ng->arc[z].ol>=ng->arc[z+1].ol); - } - i = k; - } - } - asg_cleanup(ng); - p->hg->g = ng; - kv_destroy(cc); - return p; -} - -void debug_append_inexact_edges(ma_ug_t *ug, const ug_opt_t *uopt) { - uint32_t n_asymm = 0, n_disconnect = 0, z, v, w, k, nv; asg_arc_t *av = NULL; - for (z = 0; z < ug->g->n_arc; ++z) { - if(ug->g->arc[z].del) continue; - if(!get_ug_edge_src(ug, uopt->sources, uopt->max_hang, uopt->min_ovlp, - ug->g->arc[z].ul>>32, ug->g->arc[z].v)) { - n_disconnect++; - } - v = ug->g->arc[z].v^1; w = (ug->g->arc[z].ul>>32)^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; - // fprintf(stderr, "found <%lu> -> <%u>\n", av[k].ul>>32, av[k].v); - if (av[k].v == w) break; - } - - if (k == nv) { - ug->g->arc[z].del = 1, ++n_asymm; - // fprintf(stderr, "# lack of <%u> -> <%u>, should be <%u> -> <%u>\n\n", w^1, v^1, v, w); - } - } - - if(n_asymm || n_disconnect) { - asg_cleanup(ug->g); - fprintf(stderr, "[M::%s] # asymm edges: %u, # disconnect edges: %u\n", - __func__, n_asymm, n_disconnect); - // exit(1); - } -} - -void append_inexact_edges(ma_ug_t *ug, const ug_opt_t *uopt, asg_t *rg) -{ - uint32_t *idx = NULL, n_read = R_INF.total_reads, z, v, k, qn, tn, tu, ut_v, ut_w; - ma_utg_t *u = NULL; ma_hit_t_alloc *src = uopt->sources, *s = NULL; - int32_t r; asg_arc_t t, *p = NULL; - int64_t min_ovlp = uopt->min_ovlp, max_hang = uopt->max_hang, occ = 0; - - MALLOC(idx, n_read); memset(idx, -1, n_read*sizeof(*(idx))); - for (z = 0; z < ug->u.n; z++) { - u = &(ug->u.a[z]); - if(u->circ) continue; - idx[u->start>>1] = idx[u->end>>1] = z; - } - - for (z = 0; z < ug->u.n; z++) { - u = &(ug->u.a[z]); - if(u->circ) continue; - - v = u->end^1; s = &(src[v>>1]); ut_v = (z<<1); - for (k = 0; k < s->length; k++) { - if(s->buffer[k].el) continue;///we just need inexact edges - qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); tu = idx[tn]; ut_w = (uint32_t)-1; - if(tu == (uint32_t)-1 || ug->g->seq[tu].del) continue; - if((Get_qe(s->buffer[k]) - Get_qs(s->buffer[k])) < min_ovlp) continue; - if((Get_te(s->buffer[k]) - Get_ts(s->buffer[k])) < min_ovlp) continue; - r = ma_hit2arc(&(s->buffer[k]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - if(r < 0 || (t.ul>>32) != v) continue; - if(t.v == ug->u.a[tu].start) ut_w = tu<<1; - if(t.v == ug->u.a[tu].end) ut_w = (tu<<1)+1; - if(ut_w==(uint32_t)-1) continue; - p = asg_arc_pushp(ug->g); memset(p, 0, sizeof(*p)); - *p = t; p->ul = ut_v; p->ul <<= 32; p->ul += ((uint32_t)(t.ul)); p->v = ut_w; - occ++; - // if((p->v>>1)>=ug->g->n_seq || (p->ul>>33)>=ug->g->n_seq) { - // fprintf(stderr, "+ug->g->n_seq:%u, (p->ul>>33):%u, (p->v>>1):%u\n", - // (uint32_t)ug->g->n_seq, (uint32_t)(p->ul>>33), (uint32_t)(p->v>>1)); - // } - // assert((p->v>>1)g->n_seq && (p->ul>>33)g->n_seq); - } - - v = u->start^1; s = &(src[v>>1]); ut_v = (z<<1) + 1; - for (k = 0; k < s->length; k++) { - if(s->buffer[k].el) continue;///we just need inexact edges - qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); tu = idx[tn]; ut_w = (uint32_t)-1; - if(tu == (uint32_t)-1 || ug->g->seq[tu].del) continue; - if((Get_qe(s->buffer[k]) - Get_qs(s->buffer[k])) < min_ovlp) continue; - if((Get_te(s->buffer[k]) - Get_ts(s->buffer[k])) < min_ovlp) continue; - r = ma_hit2arc(&(s->buffer[k]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - if(r < 0 || (t.ul>>32) != v) continue; - if(t.v == ug->u.a[tu].start) ut_w = tu<<1; - if(t.v == ug->u.a[tu].end) ut_w = (tu<<1)+1; - if(ut_w==(uint32_t)-1) continue; - p = asg_arc_pushp(ug->g); memset(p, 0, sizeof(*p)); - *p = t; p->ul = ut_v; p->ul <<= 32; p->ul += ((uint32_t)(t.ul)); p->v = ut_w; - occ++; - // if((p->v>>1)>=ug->g->n_seq || (p->ul>>33)>=ug->g->n_seq) { - // fprintf(stderr, "+ug->g->n_seq:%u, (p->ul>>33):%u, (p->v>>1):%u\n", - // (uint32_t)ug->g->n_seq, (uint32_t)(p->ul>>33), (uint32_t)(p->v>>1)); - // } - // assert((p->v>>1)g->n_seq && (p->ul>>33)g->n_seq); - } - } - if(occ) { - free(ug->g->idx); - ug->g->idx = 0; - ug->g->is_srt = 0; - asg_cleanup(ug->g); - } - - free(idx); - ///for debug - debug_append_inexact_edges(ug, uopt); - fprintf(stderr, "[M::%s] # inserted inexact edges: %ld\n", __func__, occ); -} - -typedef struct { - ucov_t *cr; - ma_hit_t_alloc* src; - int64_t min_ovlp; - int64_t max_hang; - uint64_t is_el; - uint64_t is_del; - uint64_t is_src_cc; - asg_t *rg; - ma_ug_t *ug; -} r_contain_aux; - -static void update_gen_r_contain(void *data, long i, int tid) // callback for kt_for() -{ - r_contain_aux *s = (r_contain_aux *)data; - ma_hit_t_alloc *src = s->src; ma_hit_t *t; int32_t r; asg_arc_t x; - uint64_t *a = s->cr->interval.a + s->cr->idx[i], a_n = s->cr->idx[i+1] - s->cr->idx[i], k, dp, l, z, qn, tn; - uint64_t is_el = s->is_el, is_del = s->is_del, min_ovlp = s->min_ovlp, max_hang = s->max_hang, qs, qe, cs, ce, sum; - int64_t ii; asg_t *rg = s->rg; uint64_t *b, b_n, ti; - // if(a_n == 0 || rg->seq[i].del) return; - if(s->is_src_cc) { - for (z = 0; z < src[i].length; z++) { - t = &(src[i].buffer[z]); t->cc = 0; - if(a_n == 0 || rg->seq[i].del) continue; - qn = Get_qn((*t)); tn = Get_tn((*t)); - if(qn > tn) continue; - if(is_el && (!(t->el))) continue; - if(is_del && (!(t->del))) continue; - if((Get_qe((*t)) - Get_qs((*t))) < min_ovlp) continue; - if((Get_te((*t)) - Get_ts((*t))) < min_ovlp) continue; - if(rg->seq[tn].del) continue; - b = s->cr->interval.a + s->cr->idx[tn]; b_n = s->cr->idx[tn+1] - s->cr->idx[tn]; - if(b_n == 0) continue; - r = ma_hit2arc(t, Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &x); - if(r < 0) continue; - qs = Get_qs((*t)); qe = Get_qe((*t)); - for (k = 0; k < a_n; k += 2) { - cs = a[k]>>33; ce = a[k+1]>>33; assert(rg->seq[(uint32_t)(a[k])].del); - if(qs<=cs+128 && qe+128>=ce) { ///128 is the offset for indel - for (ti = 0; ti < b_n; ti+=2) { - if((uint32_t)(b[ti]) == (uint32_t)(a[k])) { - sum = t->cc; sum += (ce - cs); - if(sum > 0x3fffffffU) sum = 0x3fffffffU; - t->cc = sum; - break; - } - } - } - } - } - } else { - radix_sort_gfa64(a, a + a_n); - for (k = 0, dp = 0; k < a_n; ++k) { - ///if a[j] is qe - if ((a[k]>>32)&1) --dp; - else ++dp; - l = a[k]>>33; l <<= 32; l += dp; - a[k] = l; - } - for (z = 0; z < src[i].length; z++) { - t = &(src[i].buffer[z]); - qn = Get_qn((*t)); tn = Get_tn((*t)); - if(qn > tn) continue; - if(t->cc == 0) continue; - ii = get_specific_overlap(&(src[tn]), tn, qn); - src[tn].buffer[ii].cc = t->cc; - } - } -} - -static void update_ug_uo_t(void *data, long i, int tid) -{ - r_contain_aux *sl = (r_contain_aux *)data; int32_t r; - ma_hit_t_alloc *src = sl->src, *x; uint32_t k, qn, tn, uv, uw, v, w; - asg_arc_t *e = &(sl->ug->g->arc[i]), t; - uv = e->ul>>32; uw = e->v; e->ou = 0; - if(sl->ug->u.a[uv>>1].circ || sl->ug->u.a[uw>>1].circ) return; - v = ((uv&1)?(sl->ug->u.a[uv>>1].start^1):(sl->ug->u.a[uv>>1].end^1)); - w = ((uw&1)?(sl->ug->u.a[uw>>1].end):(sl->ug->u.a[uw>>1].start)); - x = &(src[v>>1]); - - for (k = 0; k < x->length; k++) { - qn = Get_qn(x->buffer[k]); - tn = Get_tn(x->buffer[k]); - if(qn == (v>>1) && tn == (w>>1)) { - r = ma_hit2arc(&(x->buffer[k]), sl->rg->seq[v>>1].len, sl->rg->seq[w>>1].len, - sl->max_hang, asm_opt.max_hang_rate, sl->min_ovlp, &t); - if(r < 0) continue; - if((t.ul>>32)!=v || t.v!=w) continue; - e->ou = (x->buffer[k].cc>OU_MASK?OU_MASK:x->buffer[k].cc); - break; - } - } - assert(k < x->length); -} - -ucov_t *gen_r_contain(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc* src, uint64_t n_read, int64_t min_ovlp, int64_t max_hang, uint64_t n_thread, uint64_t is_el, uint64_t is_del) -{ - ucov_t *cr = NULL; uint64_t i, z, qn, tn, qs, qe; - ma_hit_t *t = NULL; int32_t r; asg_arc_t x; - CALLOC(cr, 1); MALLOC(cr->idx, n_read+1); kv_init(cr->interval); - for (i = 0; i < n_read; i++) { - cr->idx[i] = cr->interval.n; - if(rg->seq[i].del) continue; - for (z = 0; z < src[i].length; z++) { - t = &(src[i].buffer[z]); t->cc = 0; - if(is_el && (!(t->el))) continue; - if(is_del && (!(t->del))) continue; - if((Get_qe((*t)) - Get_qs((*t))) < min_ovlp) continue; - if((Get_te((*t)) - Get_ts((*t))) < min_ovlp) continue; - qn = Get_qn((*t)); tn = Get_tn((*t)); - if(!rg->seq[tn].del) continue; - r = ma_hit2arc(t, Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &x); - if(r == MA_HT_TCONT) { ///tn is contained - qs = Get_qs((*t)); qe = Get_qe((*t)); - kv_push(uint64_t, cr->interval, ((qs<<1)<<32)|tn); - kv_push(uint64_t, cr->interval, (((qe<<1)|1)<<32)|tn); - } - } - } - cr->idx[i] = cr->interval.n; - // fprintf(stderr, "+++[M::%s]n_read:%lu\n", __func__, n_read); - r_contain_aux aux; - aux.cr = cr; aux.src = src; aux.min_ovlp = min_ovlp; aux.rg = rg; aux.ug = ug; - aux.max_hang = max_hang; aux.is_el = 0/**is_el**/; aux.is_del = 0/**is_del**/; - aux.is_src_cc = 1; - kt_for(n_thread, update_gen_r_contain, &aux, n_read);///note: here we should set is_el = is_del = 0 - - aux.is_src_cc = 0; - kt_for(n_thread, update_gen_r_contain, &aux, n_read); - - if(ug) kt_for(n_thread, update_ug_uo_t, &aux, ug->g->n_arc); - - return cr; -} - -ucov_t *gen_cov_track(ma_ug_t *ug, asg_t *rg, ul_contain *ct, ma_hit_t_alloc* src, int64_t min_ovlp, int64_t max_hang, uint64_t is_el, uint64_t is_del) -{ - uint64_t i, k; - ucov_t *cc = NULL; CALLOC(cc, 1); MALLOC(cc->idx, ug->u.n+1); kv_init(cc->interval); - for (i = k = 0; i < ug->u.n; i++) { - k += ug->u.a[i].len; - push_coverage_track(cc, ct, i, &(ug->u.a[i]), rg, src, min_ovlp, max_hang, is_el, is_del); - } - fprintf(stderr, "[M::%s::] # bases: %lu\n", __func__, k); - return cc; -} - -ul_idx_t *dedup_HiFis(const ug_opt_t *uopt, uint64_t is_el, uint64_t is_del) -{ - uint64_t i, k, qn, tn, n_read = R_INF.total_reads, cc_num = 0; - int32_t r; asg_arc_t t, *p = NULL; - uint8_t *rset = NULL; CALLOC(rset, n_read<<1); - asg_t *rg = asg_init(); - ma_hit_t_alloc* src = uopt->sources; - int64_t min_ovlp = uopt->min_ovlp; - int64_t max_hang = uopt->max_hang; - int64_t gap_fuzz = uopt->gap_fuzz; - - rg->m_seq = rg->n_seq = n_read; MALLOC(rg->seq, rg->m_seq); - for (i = 0; i < n_read; ++i) { - rg->seq[i].len = Get_READ_LENGTH(R_INF, i); - rg->seq[i].del = rg->seq[i].c = 0; - } - - for (i = 0; i < n_read; i++) { - if(rg->seq[i].del) continue; - for (k = 0; k < src[i].length; k++) { - if(is_el && (!src[i].buffer[k].el)) continue; - if(is_del && (!src[i].buffer[k].del)) continue; - qn = Get_qn(src[i].buffer[k]); tn = Get_tn(src[i].buffer[k]); - if(rg->seq[qn].del || rg->seq[tn].del) continue; - if((Get_qe(src[i].buffer[k]) - Get_qs(src[i].buffer[k])) < min_ovlp) continue; - if((Get_te(src[i].buffer[k]) - Get_ts(src[i].buffer[k])) < min_ovlp) continue; - r = ma_hit2arc(&(src[i].buffer[k]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - if (r == MA_HT_QCONT/** && check_if_fully_contain(qn, tn, src[i].buffer[k].rev, rset, rg, src, min_ovlp, max_hang, gap_fuzz)**/) { - rg->seq[qn].del = 1; - } else if(r == MA_HT_TCONT/** && check_if_fully_contain(tn, qn, src[i].buffer[k].rev, rset, rg, src, min_ovlp, max_hang, gap_fuzz)**/) { - rg->seq[tn].del = 1; - } - if(rg->seq[i].del) break; - } - } - - - for (i = 0; i < n_read; i++) { - if(rg->seq[i].del) {cc_num++; continue;} - for (k = 0; k < src[i].length; k++) { - if(is_el && (!src[i].buffer[k].el)) continue; - if(is_del && (!src[i].buffer[k].del)) continue; - qn = Get_qn(src[i].buffer[k]); tn = Get_tn(src[i].buffer[k]); - if(rg->seq[qn].del || rg->seq[tn].del) continue; - if((Get_qe(src[i].buffer[k]) - Get_qs(src[i].buffer[k])) < min_ovlp) continue; - if((Get_te(src[i].buffer[k]) - Get_ts(src[i].buffer[k])) < min_ovlp) continue; - r = ma_hit2arc(&(src[i].buffer[k]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); - if (r >= 0) { - p = asg_arc_pushp(rg); - *p = t; - } - } - } - - asg_cleanup(rg); asg_symm(rg); - asg_arc_del_trans(rg, gap_fuzz); - ma_ug_t *ug = NULL; - ug = ma_ug_gen(rg); - append_inexact_edges(ug, uopt, rg); - - ul_idx_t *uu = NULL; CALLOC(uu, 1); - uu->ug = ug; - - uu->ct = ul_contain_gen(ug, rg, src, min_ovlp, max_hang, is_el, is_del); - uu->cc = gen_cov_track(ug, rg, uu->ct, src, min_ovlp, max_hang, is_el, is_del); - uu->cr = gen_r_contain(ug, rg, src, n_read, min_ovlp, max_hang, asm_opt.thread_num, is_el, is_del); - - // uu->ov = compress_dedup_HiFis(ug, src); - asg_destroy(rg); free(rset); - // uu->nug = cvert_t_gen(uopt); - - fprintf(stderr, "[M::%s::] # unitigs: %lu, # edges: %lu, # cc_num: %lu\n", __func__, (uint64_t)ug->u.n, (uint64_t)ug->g->n_arc, cc_num); - // print_dedup_HiFis_seq(ug); - return uu; -} - -ul_idx_t *gen_ul_idx(const ug_opt_t *uopt, ma_ug_t *ug, asg_t *sg) -{ - ma_hit_t_alloc* src = uopt->sources; - int64_t min_ovlp = uopt->min_ovlp; - int64_t max_hang = uopt->max_hang; - - ul_idx_t *uu = NULL; CALLOC(uu, 1); uu->ug = ug; - uu->ct = ul_contain_gen(ug, sg, src, min_ovlp, max_hang, 0, 1); - uu->cc = gen_cov_track(ug, sg, uu->ct, src, min_ovlp, max_hang, 0, 1); - uu->cr = gen_r_contain(ug, sg, src, R_INF.total_reads, min_ovlp, max_hang, asm_opt.thread_num, 0, 1); - // uu->hpc_g = hpc_g_gen(ug); - - return uu; -} - - - -utg_rid_t *gen_r_ug_idx(ma_ug_t *ug, ul_contain *ct, asg_t *rg, uint32_t keep_offset) -{ - uint64_t i, k, l, m, rid, a_n, cn, rn = R_INF.total_reads; ///R_INF.total_reads might be larger than rg->n_seq due scaffold reads - utg_rid_dt *a; ma_utg_t *u = NULL; utg_ct_t *ca; - - utg_rid_t *cc = NULL; CALLOC(cc, 1); CALLOC(cc->idx, rn+1); kv_init(cc->p); cc->rg = rg; - for (i = 0; i < ug->u.n; i++) { - u = &(ug->u.a[i]); - for (k = 0; k < u->n; k++) cc->idx[u->a[k]>>33]++; - - if(ct) { - cn = ((uint32_t)(ct->idx.a[i])); - ca = ct->rids.a + ((ct->idx.a[i])>>32); - for (k = 0; k < cn; k++) cc->idx[ca[k].x>>1]++; - } - } - - for (k = l = 0; k <= rn; k++) { - m = cc->idx[k]; - cc->idx[k] = l; - l += m; - } - cc->p.n = cc->p.m = l; CALLOC(cc->p.a, cc->p.n); - for (i = 0; i < ug->u.n; i++) { - u = &(ug->u.a[i]); - for (k = l = 0; k < u->n; k++) { - rid = u->a[k]>>33; - a = cc->p.a + cc->idx[rid]; - a_n = cc->idx[rid+1] - cc->idx[rid]; - if(a_n) { - if(a[a_n-1].off == a_n-1) { - a[a_n-1].u = (i<<1)|((u->a[k]>>32)&1); - a[a_n-1].pos = l; a[a_n-1].off = (keep_offset?k:l); - } else { - a[a[a_n-1].off].u = (i<<1)|((u->a[k]>>32)&1); - a[a[a_n-1].off].pos = l; a[a[a_n-1].off].off = (keep_offset?k:l); - a[a_n-1].off++; - } - } - l += (uint32_t)u->a[k]; - } - - if(ct) { - cn = ((uint32_t)(ct->idx.a[i])); - ca = ct->rids.a + ((ct->idx.a[i])>>32); - for (k = 0; k < cn; k++) { - rid = ca[k].x>>1; - a = cc->p.a + cc->idx[rid]; - a_n = cc->idx[rid+1] - cc->idx[rid]; - if(a_n) { - if(a[a_n-1].off == a_n-1) { - a[a_n-1].u = (i<<1)|(ca[k].x&1); - a[a_n-1].pos = ca[k].s; a[a_n-1].off = (keep_offset?k:ca[k].s); - } else { - a[a[a_n-1].off].u = (i<<1)|(ca[k].x&1); - a[a[a_n-1].off].pos = ca[k].s; a[a[a_n-1].off].off = (keep_offset?k:ca[k].s); - a[a_n-1].off++; - } - } - } - } - } - return cc; -} - -utg_rid_t *gen_r_ug_sc_idx(scaf_res_t *ug_sc, uint64_t ug_sc_num) -{ - uint64_t i, z, k, l, m, rid, a_n, s, e, rn = ug_sc_num; ///ug_sc_num is the number of nodes within the inital graph - utg_rid_dt *a; ul_vec_t *idx; - - utg_rid_t *cc = NULL; CALLOC(cc, 1); CALLOC(cc->idx, rn+1); kv_init(cc->p); ///cc->rg = rg; - for (i = 0; i < ug_sc->n; i++) { - idx = &(ug_sc->a[i]); - for (z = 0; z < idx->bb.n; z++) { - s = idx->bb.a[z].ts; e = idx->bb.a[z].te; - for (k = s; k < e; k++) cc->idx[idx->bb.a[k].hid]++; - } - } - - for (k = l = 0; k <= rn; k++) { - m = cc->idx[k]; - cc->idx[k] = l; - l += m; - } - cc->p.n = cc->p.m = l; CALLOC(cc->p.a, cc->p.n); - for (i = 0; i < ug_sc->n; i++) { - idx = &(ug_sc->a[i]); - for (z = 0; z < idx->bb.n; z++) { - s = idx->bb.a[z].ts; e = idx->bb.a[z].te; - for (k = s; k < e; k++) { - rid = idx->bb.a[k].hid; - a = cc->p.a + cc->idx[rid]; - a_n = cc->idx[rid+1] - cc->idx[rid]; - if(a_n) { - if(a[a_n-1].off == a_n-1) { - a[a_n-1].u = (i<<1)|(idx->bb.a[k].rev); - a[a_n-1].pos = idx->bb.a[k].qs; a[a_n-1].off = k; - } else { - a[a[a_n-1].off].u = (i<<1)|(idx->bb.a[k].rev); - a[a[a_n-1].off].pos = idx->bb.a[k].qs; a[a[a_n-1].off].off = k; - a[a_n-1].off++; - } - } - } - } - } - return cc; -} - -ul_idx_t *gen_ul_idx_t(const ug_opt_t *uopt, ma_ug_t *ug, asg_t *sg, uint64_t is_el, uint64_t is_del, uint64_t is_scaf) -{ - uint64_t n_read = R_INF.total_reads; - ma_hit_t_alloc* src = uopt->sources; - int64_t min_ovlp = uopt->min_ovlp; - int64_t max_hang = uopt->max_hang; - // int64_t gap_fuzz = uopt->gap_fuzz; - ul_idx_t *uu = NULL; CALLOC(uu, 1); uu->ug = (ug?(ug):(ma_ug_gen(sg))); - if(!is_scaf) { - uu->ct = ul_contain_gen(uu->ug, sg, src, min_ovlp, max_hang, is_el, is_del); - uu->cc = gen_cov_track(uu->ug, sg, uu->ct, src, min_ovlp, max_hang, is_el, is_del); - uu->cr = gen_r_contain(uu->ug, sg, src, n_read, min_ovlp, max_hang, asm_opt.thread_num, is_el, is_del); - } - uu->r_ug = gen_r_ug_idx(uu->ug, (!is_scaf)?(uu->ct):(NULL), sg, is_scaf); - return uu; -} - -ul_idx_t *gen_ul_idx_t_sc(ma_ug_t *ug, asg_t *sg, scaf_res_t *ug_sc, uint64_t ug_sc_num) -{ - // int64_t gap_fuzz = uopt->gap_fuzz; - ul_idx_t *uu = NULL; CALLOC(uu, 1); uu->ug = (ug?(ug):(ma_ug_gen(sg))); - uu->r_ug = gen_r_ug_sc_idx(ug_sc, ug_sc_num); - return uu; -} - - -void destroy_ul_idx_t(ul_idx_t *uu) -{ - if(!uu) return; - if(uu->cc) { - free(uu->cc->idx); - free(uu->cc->interval.a); - free(uu->cc); - } - - if(uu->cr) { - free(uu->cr->idx); - free(uu->cr->interval.a); - free(uu->cr); - } - - if(uu->ct) { - free(uu->ct->idx.a); - free(uu->ct->rids.a); - free(uu->ct->is_c.a); - free(uu->ct); - } - - if(uu->r_ug) { - free(uu->r_ug->idx); - free(uu->r_ug->p.a); - free(uu->r_ug); - } - - if(uu->hpc_g) { - free(uu->hpc_g->a); - ma_ug_destroy(uu->hpc_g->hg); - free(uu->hpc_g->mm->a); - free(uu->hpc_g->mm->idx); - free(uu->hpc_g->mm); - free(uu->hpc_g); - } - // if(uu->ov) { - // free(uu->ov->a); - // free(uu->ov); - // } - ma_ug_destroy(uu->ug); - // if(uu->nug) { - // free(uu->nug->idx); - // ma_ug_destroy(uu->nug->ug); - // free(uu->nug); - // } - free(uu); -} - -void destroy_idx_emask_t(idx_emask_t *mm) -{ - if(mm) { - uint64_t k; - for (k = 0; k < mm->n; k++) { - free(mm->a[k].a); memset(&(mm->a[k]), 0, sizeof(mm->a[k])); - } - free(mm->a); - } -} - -void gen_UL_ovlps(uldat_t *sl, int32_t cutoff) -{ - ul_idx_t *uu = dedup_HiFis(sl->uopt, 1, 0); - ///for unitig index - int exist = (asm_opt.load_index_from_disk? uidx_load(&ha_flt_tab, &ha_idx, asm_opt.output_file_name, NULL) : 0); - if(exist == 0) uidx_l_build(uu->ug, (mg_idxopt_t *)sl->opt, cutoff); - if(exist == 0) uidx_write(ha_flt_tab, ha_idx, asm_opt.output_file_name, NULL); - // print_debug_gfa(sl->uopt, ug, coverage_cut, "debug_dups", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); - sl->ha_flt_tab = ha_flt_tab; sl->ha_idx = (ha_pt_t *)ha_idx; sl->uu = uu; - ul_v_call(sl, asm_opt.ar); - // print_raw_u2rgfa_seq(&UL_INF, uu, 1); - destroy_ul_idx_t(uu); ha_ft_destroy(ha_flt_tab); ha_pt_destroy(ha_idx); - sl->ha_flt_tab = NULL; sl->ha_idx = NULL; sl->uu = NULL; -} - -int32_t load_emask_t(idx_emask_t **z, char* file_name, ma_ug_t *ug) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(file_name)+50); - sprintf(gfa_name, "%s.ul.msk.bin", file_name); - FILE* fp = fopen(gfa_name, "r"); free(gfa_name); - if (!fp) return 0; - if(ug && (!test_dbug(ug, fp))) { - fprintf(stderr, "[M::%s] Renew UL Index\n", __func__); - fclose(fp); - return 0; - } - uint64_t k; kv_emask_t *p; idx_emask_t *x; CALLOC(x, 1); - - - fread(&x->n, sizeof(x->n), 1, fp); MALLOC(x->a, x->n); - for (k = 0; k < x->n; k++) { - p = &(x->a[k]); - fread(&p->n, sizeof(p->n), 1, fp); MALLOC(p->a, p->n); p->m = p->n; - fread(p->a, sizeof((*(p->a))), p->n, fp); - } - - fprintf(stderr, "[M::%s] Index has been loaded.\n", __func__); - fclose(fp); - *z = x; - return 1; -} - -int32_t write_emask_t(idx_emask_t *x, char* file_name, ma_ug_t *ug) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(file_name)+50); - sprintf(gfa_name, "%s.ul.msk.bin", file_name); - FILE* fp = fopen(gfa_name, "w"); free(gfa_name); - if (!fp) return 0; - uint64_t k; kv_emask_t *p = NULL; - - if(ug) write_dbug(ug, fp); - - fwrite(&x->n, sizeof(x->n), 1, fp); - for (k = 0; k < x->n; k++) { - p = &(x->a[k]); - fwrite(&p->n, sizeof(p->n), 1, fp); - fwrite(p->a, sizeof((*(p->a))), p->n, fp); - } - - fprintf(stderr, "[M::%s] Index has been written.\n", __func__); - fclose(fp); - return 1; -} - -void gen_UL_reovlps(uldat_t *sl, ma_ug_t *ug, asg_t *sg, char* gfa_name, int32_t cutoff, int32_t is_emask) -{ - ul_idx_t *uu = gen_ul_idx(sl->uopt, ug, sg); - int exist = (asm_opt.load_index_from_disk? uidx_load(&ha_flt_tab, &ha_idx, gfa_name, ug) : 0); - if(exist == 0) uidx_l_build(uu->ug, (mg_idxopt_t *)sl->opt, cutoff); - if(exist == 0) uidx_write(ha_flt_tab, ha_idx, gfa_name, ug); - sl->ha_flt_tab = ha_flt_tab; sl->ha_idx = (ha_pt_t *)ha_idx; sl->uu = uu; - if(is_emask) { - if((!(asm_opt.load_index_from_disk)) || (!load_emask_t(&(sl->mm), gfa_name, ug))) { - sl->mm = graph_ovlp_binning(ug, sg, sl->uopt); - write_emask_t(sl->mm, gfa_name, ug); - } - } - - init_ucr_file_t(sl, gfa_name, 1); - ul_v_recall(sl, asm_opt.ar); - destory_ucr_file_t(sl); - ///do not free ug - uu->ug = NULL; destroy_ul_idx_t(uu); ha_ft_destroy(ha_flt_tab); ha_pt_destroy(ha_idx); - sl->ha_flt_tab = NULL; sl->ha_idx = NULL; sl->uu = NULL; - destroy_idx_emask_t(sl->mm); free(sl->mm); sl->mm = NULL; - // exit(1); -} - -uint32_t drenew_UL_reovlps(uldat_t *sl, ma_ug_t *ug, asg_t *sg, char* gfa_name, int32_t cutoff) -{ - uint32_t k, f_occ; - kt_for(asm_opt.thread_num, dcheck_ulalignments_mul, ug, UL_INF.n); - for (k = f_occ = 0; k < UL_INF.n; k++) { - if(UL_INF.a[k].rlen&((uint32_t)(0x80000000))) f_occ++; - } - fprintf(stderr, "[M::%s::] # wrong UL alignments::%u\n", __func__, f_occ); - if(f_occ == 0) return 0;//all set - - ul_idx_t *uu = gen_ul_idx(sl->uopt, ug, sg); - int exist = (asm_opt.load_index_from_disk? uidx_load(&ha_flt_tab, &ha_idx, gfa_name, ug) : 0); - if(exist == 0) uidx_l_build(uu->ug, (mg_idxopt_t *)sl->opt, cutoff); - if(exist == 0) uidx_write(ha_flt_tab, ha_idx, gfa_name, ug); - sl->ha_flt_tab = ha_flt_tab; sl->ha_idx = (ha_pt_t *)ha_idx; sl->uu = uu; - - // init_ucr_file_t(sl, gfa_name, 1); - recorrect_ul_pipeline(sl, asm_opt.ar); - // destory_ucr_file_t(sl); - ///do not free ug - uu->ug = NULL; destroy_ul_idx_t(uu); ha_ft_destroy(ha_flt_tab); ha_pt_destroy(ha_idx); - sl->ha_flt_tab = NULL; sl->ha_idx = NULL; sl->uu = NULL; - return 1; - // exit(1); -} - -void init_uldat_t(uldat_t *sl, void *ha_flt_tab, void *ha_idx, mg_idxopt_t *opt, uint64_t chunk_size, uint64_t n_thread, const ug_opt_t *uopt, ul_idx_t *uu) -{ - memset(sl, 0, sizeof(uldat_t)); - sl->ha_flt_tab = ha_flt_tab; - sl->ha_idx = (ha_pt_t *)ha_idx; - sl->opt = opt; - sl->chunk_size = chunk_size; - sl->n_thread = n_thread; - sl->uu = uu; - sl->uopt = uopt; -} - -int32_t write_all_ul_t(all_ul_t *x, char* file_name, ma_ug_t *ug) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(file_name)+50); - sprintf(gfa_name, "%s.ul.ovlp.bin", file_name); - FILE* fp = fopen(gfa_name, "w"); free(gfa_name); - if (!fp) return 0; - uint64_t k; ul_vec_t *p = NULL; - - if(ug) write_dbug(ug, fp); - - fwrite(&x->nid.n, sizeof(x->nid.n), 1, fp); - for (k = 0; k < x->nid.n; k++) { - fwrite(&x->nid.a[k].n, sizeof(x->nid.a[k].n), 1, fp); - fwrite(x->nid.a[k].a, sizeof((*(x->nid.a[k].a))), x->nid.a[k].n, fp); - } - - fwrite(&x->ridx.idx.n, sizeof(x->ridx.idx.n), 1, fp); - fwrite(x->ridx.idx.a, sizeof((*(x->ridx.idx.a))), x->ridx.idx.n, fp); - - fwrite(&x->ridx.occ.n, sizeof(x->ridx.occ.n), 1, fp); - fwrite(x->ridx.occ.a, sizeof((*(x->ridx.occ.a))), x->ridx.occ.n, fp); - - fwrite(&x->n, sizeof(x->n), 1, fp); - for (k = 0; k < x->n; k++) { - p = &(x->a[k]); - fwrite(&p->dd, sizeof(p->dd), 1, fp); - fwrite(&p->rlen, sizeof(p->rlen), 1, fp); - - fwrite(&p->r_base.n, sizeof(p->r_base.n), 1, fp); - fwrite(p->r_base.a, sizeof((*(p->r_base.a))), p->r_base.n, fp); - - fwrite(&p->bb.n, sizeof(p->bb.n), 1, fp); - fwrite(p->bb.a, sizeof((*(p->bb.a))), p->bb.n, fp); - - fwrite(&p->N_site.n, sizeof(p->N_site.n), 1, fp); - fwrite(p->N_site.a, sizeof((*(p->N_site.a))), p->N_site.n, fp); - } - - fprintf(stderr, "[M::%s] Index has been written.\n", __func__); - fclose(fp); - if(asm_opt.bin_only) exit(0); - return 1; -} - - -int32_t load_all_ul_t(all_ul_t *x, char* file_name, All_reads *hR, ma_ug_t *ug) -{ - char* gfa_name = NULL; MALLOC(gfa_name, strlen(file_name)+50); - sprintf(gfa_name, "%s.ul.ovlp.bin", file_name); - FILE* fp = fopen(gfa_name, "r"); free(gfa_name); - if (!fp) return 0; - if(ug && (!test_dbug(ug, fp))) { - fprintf(stderr, "[M::%s] Renew UL Index\n", __func__); - fclose(fp); - return 0; - } - - destory_all_ul_t(x); - memset(x, 0, sizeof(*x)); x->hR = hR; init_aux_table(); - uint64_t k; ul_vec_t *p = NULL; - - fread(&x->nid.n, sizeof(x->nid.n), 1, fp); x->nid.m = x->nid.n; MALLOC(x->nid.a, x->nid.n); - for (k = 0; k < x->nid.n; k++) { - fread(&x->nid.a[k].n, sizeof(x->nid.a[k].n), 1, fp); MALLOC(x->nid.a[k].a, x->nid.a[k].n); - fread(x->nid.a[k].a, sizeof((*(x->nid.a[k].a))), x->nid.a[k].n, fp); - } - - fread(&x->ridx.idx.n, sizeof(x->ridx.idx.n), 1, fp); x->ridx.idx.m = x->ridx.idx.n; MALLOC(x->ridx.idx.a, x->ridx.idx.n); - fread(x->ridx.idx.a, sizeof((*(x->ridx.idx.a))), x->ridx.idx.n, fp); - - fread(&x->ridx.occ.n, sizeof(x->ridx.occ.n), 1, fp); x->ridx.occ.m = x->ridx.occ.n; MALLOC(x->ridx.occ.a, x->ridx.occ.n); - fread(x->ridx.occ.a, sizeof((*(x->ridx.occ.a))), x->ridx.occ.n, fp); - - fread(&x->n, sizeof(x->n), 1, fp); x->m = x->n; MALLOC(x->a, x->n); - for (k = 0; k < x->n; k++) { - p = &(x->a[k]); - fread(&p->dd, sizeof(p->dd), 1, fp); - fread(&p->rlen, sizeof(p->rlen), 1, fp); - - fread(&p->r_base.n, sizeof(p->r_base.n), 1, fp); p->r_base.m = p->r_base.n; MALLOC(p->r_base.a, p->r_base.n); - fread(p->r_base.a, sizeof((*(p->r_base.a))), p->r_base.n, fp); - - fread(&p->bb.n, sizeof(p->bb.n), 1, fp); p->bb.m = p->bb.n; MALLOC(p->bb.a, p->bb.n); - fread(p->bb.a, sizeof((*(p->bb.a))), p->bb.n, fp); - - fread(&p->N_site.n, sizeof(p->N_site.n), 1, fp); p->N_site.m = p->N_site.n; MALLOC(p->N_site.a, p->N_site.n); - fread(p->N_site.a, sizeof((*(p->N_site.a))), p->N_site.n, fp); - } - - fprintf(stderr, "[M::%s] Index has been loaded.\n", __func__); - fclose(fp); - return 1; -} - -void ul_load(const ug_opt_t *uopt) -{ - fprintf(stderr, "[M::%s::] ==> UL\n", __func__); - mg_idxopt_t opt; uldat_t sl; - int32_t cutoff; - init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); - cutoff = asm_opt.max_n_chain; - init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); - init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, NULL); - - if(!load_all_ul_t(&UL_INF, asm_opt.output_file_name, &R_INF, NULL)) { - gen_UL_ovlps(&sl, cutoff); - write_all_ul_t(&UL_INF, asm_opt.output_file_name, NULL); - // exit(1); - } - // detect_outlier_len("ul_load"); - // print_all_ul_t_stat(&UL_INF); - // fprintf(stderr, "**1**\n"); - kt_for(sl.n_thread, update_ovlp_src, &sl, R_INF.total_reads); - // fprintf(stderr, "**2**\n"); - kt_for(sl.n_thread, update_ovlp_src_bl, &sl, R_INF.total_reads); - // fprintf(stderr, "**3**\n"); - - print_ovlp_src_bl_stat(&UL_INF, sl.uopt); - // exit(1); - // print_ul_ovlps(&UL_INF, 0); - // print_ul_ovlps(&UL_INF, 1); - - // destory_all_ul_t(&UL_INF); -} - -void clean_contain_g0(uldat_t *sl) -{ - kt_for(sl->n_thread, clean_contained_chg, sl, R_INF.total_reads); - asg_t *sg = (asg_t *)sl->rg; uint32_t k, cnt; - for (k = cnt = 0; k < sg->n_seq; k++) { - // if(is_contain_r((*(sl->uopt->ruIndex)), k)) { - // fprintf(stderr, "[M::%s::]\t%.*s\n", __func__, (int)Get_NAME_LENGTH(R_INF, k), Get_NAME(R_INF, k)); - // } - if(sg->seq_vis[k]) { - asg_seq_del(sg, k); cnt++; - } - sg->seq_vis[k] = 0; - } - if(cnt) asg_cleanup(sg); - fprintf(stderr, "[M::%s::] # discard cread::%u\n", __func__, cnt); - // exit(1); -} - -void asg_arc_push_contain_trans(asg_t *g, ma_hit_t_alloc* ov, int64_t min_ovlp, int64_t max_hang, double max_hang_rate, int64_t fuzz, R_to_U *ri, uint8_t *mark) -{ - uint32_t n_vtx = g->n_seq<<1, cnt = 0, nc, cc, qn, tn, avi, awi; - uint32_t v, w, i, k, nv, nw; asg_arc_t *av, *aw; int32_t r = 1; - ma_hit_t_alloc *z; asg_arc_t p, *t; - uint32_t *dis, *idx; CALLOC(dis, n_vtx); MALLOC(idx, n_vtx); - for (v = 0; v < n_vtx; ++v) { - if(g->seq[v>>1].del || (!mark[v])) continue; - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); - if (nv == 0) continue; // no hits - for (i = 0; i < nv; ++i) { - if((!(av[i].del)) && (is_contain_r((*ri), (av[i].v>>1)))) break; - } - if(i >= nv) continue; - z = &(ov[v>>1]); - for (i = 0; i < z->length; i++) { - qn = Get_qn(z->buffer[i]); tn = Get_tn(z->buffer[i]); - if(z->buffer[i].del) continue; - r = ma_hit2arc(&(z->buffer[i]), g->seq[qn].len, g->seq[tn].len, max_hang, max_hang_rate, min_ovlp, &p); - if((r < 0) || ((p.ul>>32) != v)) continue; - if(g->seq[p.v>>1].del) continue; - if(mark[p.v^1]) { - dis[p.v] = asg_arc_len(p) + fuzz; idx[p.v] = i; - } - } - - nv = asg_arc_n(g, v); av = asg_arc_a(g, v); avi = g->idx[v]>>32; - while(nv) { - for (i = nc = cc = 0; i < nv; ++i) { - if(av[i].del) continue; w = av[i].v; - if(!(is_contain_r((*ri), (w>>1)))) continue;///new arcs must be bridged by contained reads - assert(!(g->seq[w>>1].del)); - nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); awi = g->idx[w]>>32; - for (k = 0; k < nw; k++) { - if(aw[k].del) continue; - if((dis[aw[k].v] == ((uint32_t)-1)) || (dis[aw[k].v] == 0)) continue; - assert(!(g->seq[aw[k].v>>1].del)); - if((asg_arc_len(av[i]) + asg_arc_len(aw[k])) <= dis[aw[k].v]) { - dis[aw[k].v] = ((uint32_t)-1); assert(!(z->buffer[idx[aw[k].v]].del)); - qn = Get_qn(z->buffer[idx[aw[k].v]]); tn = Get_tn(z->buffer[idx[aw[k].v]]); - r = ma_hit2arc(&(z->buffer[idx[aw[k].v]]), g->seq[qn].len, g->seq[tn].len, max_hang, max_hang_rate, min_ovlp, &p); - assert(r>=0); assert((p.ul>>32)==v); assert(p.v==aw[k].v); - cnt++; p.ou = 0; t = asg_arc_pushp(g); *t = p; - - // fprintf(stderr, "[M::%s::]\t%.*s(id::%lu::%c)(is_c::%u)\t%.*s(id::%u::%c)(is_c::%u)\n", __func__, - // (int)Get_NAME_LENGTH(R_INF, (g->arc[g->n_arc-1].ul>>33)), - // Get_NAME(R_INF, (g->arc[g->n_arc-1].ul>>33)), - // g->arc[g->n_arc-1].ul>>33, "+-"[(g->arc[g->n_arc-1].ul>>32)&1], - // (is_contain_r((*ri), (g->arc[g->n_arc-1].ul>>33))), - // (int)Get_NAME_LENGTH(R_INF, (g->arc[g->n_arc-1].v>>1)), - // Get_NAME(R_INF, (g->arc[g->n_arc-1].v>>1)), - // g->arc[g->n_arc-1].v>>1, "+-"[(g->arc[g->n_arc-1].v)&1], - // (is_contain_r((*ri), (g->arc[g->n_arc-1].v>>1))) - // ); - // fprintf(stderr, "[M::%s::]\tmiddle::%.*s(id::%u::%c)(is_c::%u)\n", __func__, - // (int)Get_NAME_LENGTH(R_INF, (w>>1)), Get_NAME(R_INF, (w>>1)), - // w>>1, "+-"[w&1], (is_contain_r((*ri), (w>>1)))); - - - - av = g->arc + avi; aw = g->arc + awi;///renew av and aw since asg_arc_pushp - if((is_contain_r((*ri), (g->arc[g->n_arc-1].v>>1)))) { - cc++; - } else { - if(g->n_arc!=(nc+1)) { - p = g->arc[g->n_arc-1]; - g->arc[g->n_arc-1] = g->arc[nc]; - g->arc[nc] = p; - } - nc++; - } - } - } - } - - if(cc) {///new arcs must be bridged by contained reads - nv = cc; av = g->arc + g->n_arc - cc; avi = g->n_arc - cc; - } else { - nv = 0; av = NULL; avi = ((uint32_t)-1); - } - } - - z = &(ov[v>>1]); - for (i = 0; i < z->length; i++) { - qn = Get_qn(z->buffer[i]); tn = Get_tn(z->buffer[i]); - if(z->buffer[i].del) continue; - r = ma_hit2arc(&(z->buffer[i]), g->seq[qn].len, g->seq[tn].len, max_hang, max_hang_rate, min_ovlp, &p); - if((r < 0) || ((p.ul>>32) != v)) continue; - dis[p.v] = 0; - } - } - - free(dis); free(idx); - if(cnt) { - free(g->idx); - g->idx = 0; - g->is_srt = 0; - asg_cleanup(g); - asg_symm(g); - } -} - -void repush_contain_trans_archs(uldat_t *sl) -{ - asg_t *sg = (asg_t *)sl->rg; - kt_for(sl->n_thread, label_contained_chg, sl, (sg->n_seq<<1)); - - // print_debug_gfa(sg, NULL, sl->uopt->coverage_cut, "UL.dirty.debug0", sl->uopt->sources, sl->uopt->ruIndex, sl->uopt->max_hang, sl->uopt->min_ovlp, 0, 0, 0); - - asg_arc_push_contain_trans(sg, sl->uopt->sources, sl->uopt->min_ovlp, sl->uopt->max_hang, asm_opt.max_hang_rate, sl->uopt->gap_fuzz, sl->uopt->ruIndex, sg->seq_vis); - - // print_debug_gfa(sg, NULL, sl->uopt->coverage_cut, "UL.dirty.debug1", sl->uopt->sources, sl->uopt->ruIndex, sl->uopt->max_hang, sl->uopt->min_ovlp, 0, 0, 0); - // exit(1); -} - -uint32_t clean_contain_g(const ug_opt_t *uopt, asg_t *sg, uint32_t push_trans) -{ - mg_idxopt_t opt; uldat_t sl; int32_t cutoff, f = 0; - init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); - cutoff = asm_opt.max_n_chain; - init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); - init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, NULL); sl.rg = sg; - - if(push_trans) repush_contain_trans_archs(&sl); - if(work_ul_gchains_consensus(&sl)) { - free(UL_INF.ridx.idx.a); free(UL_INF.ridx.occ.a); memset(&(UL_INF.ridx), 0, sizeof(UL_INF.ridx)); - gen_ul_vec_rid_t(&UL_INF, &R_INF, NULL); - // fprintf(stderr, "+[M::%s::]\n", __func__); - kt_for(sl.n_thread, update_ovlp_src, &sl, R_INF.total_reads); - // fprintf(stderr, "-[M::%s::]\n", __func__); - kt_for(sl.n_thread, update_ovlp_src_bl, &sl, R_INF.total_reads); - clean_contain_g0(&sl); - f = 1; - } - if(push_trans) asg_arc_del_trans_ul(sg, sl.uopt->gap_fuzz); - return f; -} - - -void dedup_contain_g(const ug_opt_t *uopt, asg_t *sg) -{ - mg_idxopt_t opt; uldat_t sl; int32_t cutoff; - init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); - cutoff = asm_opt.max_n_chain; - init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); - init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, NULL); sl.rg = sg; - work_rg_contain_dedup(&sl); -} - - -uint64_t ul_refine_alignment(const ug_opt_t *uopt, asg_t *sg) -{ - fprintf(stderr, "[M::%s::] ==> UL refinement...\n", __func__); - mg_idxopt_t opt; uldat_t sl; int32_t cutoff; - init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); - cutoff = asm_opt.max_n_chain; - init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); - ul_idx_t *uu = gen_ul_idx_t(uopt, NULL, sg, 0, 0, 0);///record contained reads; is_el = is_del = 0 - init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, uu); sl.rg = sg; - if(work_ul_gchains(&sl)) { - free(UL_INF.ridx.idx.a); free(UL_INF.ridx.occ.a); memset(&(UL_INF.ridx), 0, sizeof(UL_INF.ridx)); - gen_ul_vec_rid_t(&UL_INF, &R_INF, NULL); - kt_for(sl.n_thread, update_ovlp_src, &sl, R_INF.total_reads); - kt_for(sl.n_thread, update_ovlp_src_bl, &sl, R_INF.total_reads); - destroy_ul_idx_t(uu); - return 1; - } else { - destroy_ul_idx_t(uu); - return 0; - } -} - -scaf_res_t *gen_contig_path(const ug_opt_t *uopt, asg_t *sg, ma_ug_t *ctg, ma_ug_t *ref) -{ - mg_idxopt_t opt; uldat_t sl; int32_t cutoff; - init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); - cutoff = asm_opt.max_n_chain; - init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); - ul_idx_t *uu = gen_ul_idx_t(uopt, ref, sg, 0, 0, 1); - init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, uu); sl.rg = sg; sl.ug = ctg; - - scaf_res_t *res = work_ctg_path_gchains(&sl); uu->ug = NULL; - destroy_ul_idx_t(uu); - return res; -} - -void gen_contig_trans(const ug_opt_t *uopt, asg_t *sg, ma_ug_t *qry, scaf_res_t *qry_sc, ma_ug_t *ref, scaf_res_t *ref_sc, ma_ug_t *gfa, kv_u_trans_t *ta, uint32_t qoff, uint32_t toff, bubble_type *bu, kv_u_trans_t *res) -{ - mg_idxopt_t opt; uldat_t sl; int32_t cutoff; - init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); - cutoff = asm_opt.max_n_chain; - init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); - ul_idx_t *uu = gen_ul_idx_t_sc(ref, sg, ref_sc, gfa->u.n); - init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, uu); sl.rg = sg; sl.ug = qry; - - work_ctg_path_trans(&sl, sg, qry, qry_sc, ref, ref_sc, gfa, ta, qoff, toff, bu, res); uu->ug = NULL; - destroy_ul_idx_t(uu); -} - -void gen_contig_self(const ug_opt_t *uopt, asg_t *sg, ma_ug_t *db, scaf_res_t *db_sc, ma_ug_t *gfa, kv_u_trans_t *ta, uint64_t soff, bubble_type *bu, kv_u_trans_t *res, uint32_t is_exact) -{ - mg_idxopt_t opt; uldat_t sl; int32_t cutoff; - init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); - cutoff = asm_opt.max_n_chain; - init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, ((is_exact)?(0.333333):(asm_opt.ul_error_rate)), asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); - ul_idx_t *uu = gen_ul_idx_t_sc(db, sg, db_sc, gfa->u.n); - init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, uu); sl.rg = sg; sl.ug = db; - - work_ctg_path_trans_self(&sl, sg, db, db_sc, gfa, ta, soff, is_exact, bu, res); - - uu->ug = NULL; destroy_ul_idx_t(uu); -} - -void order_contig_trans(kv_u_trans_t *in) -{ - utepdat_t s; uint64_t i, n_th = asm_opt.thread_num; memset(&s, 0, sizeof(s)); - CALLOC(s.hab, n_th); CALLOC(s.buf, n_th); CALLOC(s.ll, n_th); - CALLOC(s.gdp, n_th); CALLOC(s.mzs, n_th); CALLOC(s.sps, n_th); - - for (i = 0; i < n_th; ++i) { - s.hab[i] = ha_ovec_init(0, 0, 1); s.buf[i] = mg_tbuf_init(); - } - - ctdat_t c; memset(&c, 0, sizeof(c)); c.s = &(s); c.ta = in; - - c.mm = 0; kt_for(n_th, worker_for_ctg_trans_order, &c, in->idx.n); - c.mm = 1; kt_for(n_th, worker_for_ctg_trans_order, &c, in->idx.n); - - for (i = 0; i < n_th; ++i) { - s.sum_len += s.hab[i]->num_read_base; s.n += s.hab[i]->num_correct_base; - ha_ovec_destroy(s.hab[i]); mg_tbuf_destroy(s.buf[i]); hc_glchain_destroy(&(s.ll[i])); - hc_gdpchain_destroy(&(s.gdp[i])); kv_destroy(s.mzs[i]); kv_destroy(s.sps[i]); - } - - free(s.hab); free(s.buf); free(s.ll); free(s.gdp); free(s.mzs); free(s.sps); - fprintf(stderr, "[M::%s::] # try:%d, # done:%d\n", __func__, s.sum_len, s.n); - - uint64_t m; - for (i = m = 0; i < in->n; i++) { - if(in->a[i].del) continue; - in->a[m++] = in->a[i]; - } - in->n = m; - kt_u_trans_t_idx(in, in->idx.n); - c.mm = 2; kt_for(n_th, worker_for_ctg_trans_order, &c, in->idx.n); -} - - -uint32_t dd_ug(asg_t *sg, ma_ug_t *ug, ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, const char* output_file_name) -{ - fprintf(stderr, "Writing raw unitig GFA to disk... \n"); - char* gfa_name = (char*)malloc(strlen(output_file_name)+25); - sprintf(gfa_name, "%s.r_utg.noseq.gfa", output_file_name); - FILE* output_file = fopen(gfa_name, "w"); - ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); - fclose(output_file); - - free(gfa_name); - exit(1); -} - - -void clear_all_ul_t(all_ul_t *x) -{ - uint64_t k, rlen; - for (k = 0; k < x->n; k++) { - rlen = x->a[k].rlen; - free(x->a[k].bb.a); free(x->a[k].N_site.a); free(x->a[k].r_base.a); - memset(&(x->a[k]), 0, sizeof(x->a[k])); x->a[k].rlen = rlen; - } - free(x->ridx.idx.a); free(x->ridx.occ.a); memset(&(x->ridx), 0, sizeof((x->ridx))); - - // if(x->mm) { - // for (k = 0; k < x->mm->n; k++) { - // free(x->mm->a[k].a); memset(&(x->mm->a[k]), 0, sizeof(x->mm->a[k])); - // } - // free(x->mm->a); free(x->mm); x->mm = NULL; - // } -} - -void init_ug_trans_t(ug_trans_t *opt, ug_opt_t *uopt, int32_t is_HPC, int32_t k, int32_t w, int32_t max_n_chain, -double bw_thres, double diff_ec_ul, double bw_thres_double, double diff_ec_ul_double, double sec_cutoff, int32_t n_thread, -int32_t mini_cut, int32_t chain_cut, int32_t keep_unsymm_arc, ma_ug_t *ug, asg_t *sg, bubble_type *bub, uint8_t gen_bub) -{ - int64_t i; uint8_t *bf = NULL; - memset(opt, 0, sizeof((*opt))); - opt->uopt = uopt; - opt->k = k; - opt->w = w; - opt->is_HPC = is_HPC; - opt->max_n_chain = max_n_chain; - opt->bw_thres = bw_thres; - opt->bw_thres_double = bw_thres_double; - opt->diff_ec_ul = diff_ec_ul; - opt->diff_ec_ul_double = diff_ec_ul_double; - opt->sec_cutoff = sec_cutoff; - opt->mini_cut = mini_cut; - opt->chain_cut = chain_cut; - opt->keep_unsymm_arc = keep_unsymm_arc; - - opt->bw = 10000;///2000 in minigraph - opt->max_gap = 500000;///5000 in minigraph - opt->ug = ug; - opt->rg = sg; - opt->n_thread = ((n_thread>=1)?n_thread:1); - - CALLOC(opt->free_cnt, opt->n_thread); - CALLOC(opt->hab, opt->n_thread); - CALLOC(opt->ll, opt->n_thread); - for (i = 0; i < opt->n_thread; ++i) { - opt->hab[i] = ha_ovec_init(0, 0, 1); - } - - opt->idx_n.n = opt->idx_n.m = ug->u.n+1; - MALLOC(opt->idx_n.a, opt->idx_n.n); - - opt->udb.ug = ug; - if(bub) { - opt->bub = bub; - } else if(gen_bub) { - opt->bub = gen_bubble_chain(sg, ug, uopt, &bf, 0); free(bf); - } -} - -void gen_trans_base_count(ug_trans_t *p, kv_u_trans_t *res) -{ - double index_time = yak_realtime(); - // ha_flt_tab = NULL; - uint64_t i, k, l, occ, m, cc; kv_ul_ov_t *bl = NULL; - u_trans_t *z; ha_mzl_t *tz; - clean_u_trans_t_idx_adv(res, p->ug, p->rg); p->filter = res; - fprintf(stderr, "[M::%s::] ==> 0\n", __func__); - p->is_cnt = 1; p->is_ovlp = 0; - kt_for(p->n_thread, worker_for_trans_ovlp, p, p->ug->u.n); - for (i = l = 0; i < p->ug->u.n; i++) { - occ = p->idx_n.a[i]; p->idx_n.a[i] = l; l += occ; - } - fprintf(stderr, "[M::%s::] i::%lu, l::%lu\n", __func__, i, l); - p->idx_n.a[i] = l; - p->idx_a.n = p->idx_a.m = l; MALLOC(p->idx_a.a, p->idx_a.n); - fprintf(stderr, "[M::%s::] ==> 1\n", __func__); - p->is_cnt = 0; p->is_ovlp = 0; - kt_for(p->n_thread, worker_for_trans_ovlp, p, p->ug->u.n); - p->srt_a.n = p->srt_a.m = p->idx_a.n; MALLOC(p->srt_a.a, p->srt_a.n); - fprintf(stderr, "[M::%s::] p->idx_a.n::%lu \n", __func__, (uint64_t)p->idx_a.n); - // memcpy(p->srt_a.a, p->idx_a.a, p->srt_a.n*sizeof((*(p->srt_a.a)))); - for (i = 0; i < p->srt_a.n; i++) { - p->srt_a.a[i] = p->idx_a.a[i]; - p->srt_a.a[i].pos = (uint32_t)i; - p->srt_a.a[i].rid = i>>32; - } - radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); - kvec_t(uint64_t) cut; kv_init(cut); - for (k = 1, l = 0; k <= p->srt_a.n; k++) { - if(k == p->srt_a.n || p->srt_a.a[l].x != p->srt_a.a[k].x) { - for (i = l; i < k; i++) { - m = p->srt_a.a[i].rid; m <<= 32; m |= p->srt_a.a[i].pos; - assert(p->srt_a.a[i].x == p->idx_a.a[m].x); - p->srt_a.a[i] = p->idx_a.a[m]; p->idx_a.a[m].x = i; - } - kv_push(uint64_t, cut, (k - l)); - l = k; - } - } - - if(cut.n > 0) { - radix_sort_gfa64(cut.a, cut.a + cut.n); - m = cut.n * 0.0002; cc = cut.a[cut.n-1] + 1; - if(m > 0 && m <= cut.n) cc = cut.a[cut.n-m] + 1; - if(cc < (uint64_t)p->mini_cut) p->mini_cut = cc; - } - kv_destroy(cut); - fprintf(stderr, "[M::%s::] p->mini_cut::%d \n", __func__, p->mini_cut); - - fprintf(stderr, "[M::%s::] ==> 2\n", __func__); - p->is_cnt = 0; p->is_ovlp = 1; - kt_for(p->n_thread, worker_for_trans_ovlp, p, p->ug->u.n); - fprintf(stderr, "[M::%s::] ==> 3\n", __func__); - for (i = 0; (int64_t)i < p->n_thread; i++) { - ha_ovec_destroy(p->hab[i]); - free(p->ll[i].lo.a); free(p->ll[i].srt.a.a); free(p->ll[i].tc.a); - } - free(p->idx_a.a); free(p->idx_n.a); free(p->hab); - // destory_bubbles(p->bub); free(p->bub); - - fprintf(stderr, "[M::%s::] ==> 4\n", __func__); - ///make results consistent - kv_resize(ha_mzl_t, p->srt_a, p->ug->u.n); p->srt_a.n = p->ug->u.n; - for (i = 0; i < p->srt_a.n; i++) { - tz = &(p->srt_a.a[i]); - tz->x = (uint64_t)-1; tz->rev = 0; - tz->pos = tz->rid = tz->span = 0; - } - // memset(p->srt_a.a, 0, sizeof((*(p->srt_a.a)))*p->srt_a.n); - for (i = 0, occ = res->n; (int64_t)i < p->n_thread; i++) { - bl = &(p->ll[i].tk); - if(!(bl->n)) continue; - for (k = 1, l = 0; k <= bl->n; k++) { - if(k == bl->n || bl->a[k].qn != bl->a[l].qn) { - if(k > l) { - tz = &(p->srt_a.a[bl->a[l].qn]); - tz->x = bl->a[l].qn; tz->x <<= 32; tz->x |= i; - tz->rid = l>>32; tz->pos = (uint32_t)l; tz->rev = 1; - occ += (k - l); - } - l = k; - } - } - } - fprintf(stderr, "[M::%s::] ==> 5\n", __func__); - kt_for(p->n_thread, worker_for_sysm_trans_ovlp, p, p->ug->u.n); - // assert(p->srt_a.n <= p->ug->u.n); - // radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); - kv_resize(u_trans_t, *res, occ); - for (i = 0; i < p->srt_a.n; i++) { - tz = &(p->srt_a.a[i]); - if(!(tz->rev)) continue; - bl = &(p->ll[(uint32_t)(tz->x)].tk); - k = tz->rid; k <<= 32; k += tz->pos; - assert(bl->a[k].qn == (tz->x>>32)); - for (; (k < bl->n) && (bl->a[k].qn == (tz->x>>32)); k++) { - if(bl->a[k].qn == bl->a[k].tn) continue; - if(bl->a[k].qs == (uint32_t)-1 && bl->a[k].qe == (uint32_t)-1) continue; - - kv_pushp(u_trans_t, *res, &z); - z->f = RC_3; z->rev = bl->a[k].rev; z->del = 0; - z->qn = bl->a[k].qn; z->qs = bl->a[k].qs; z->qe = bl->a[k].qe; - z->tn = bl->a[k].tn; z->ts = bl->a[k].ts; z->te = bl->a[k].te; - z->nw = cal_trans_ov_w(&(bl->a[k])); assert(z->nw > 0); - // if(z->nw <= 0) res->n--; - } - } - fprintf(stderr, "[M::%s::] ==> 6\n", __func__); - for (i = 0; (int64_t)i < p->n_thread; i++) free(p->ll[i].tk.a); - free(p->srt_a.a); free(p->ll); - fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); -} - - -void gen_trans_base_count_comp(ug_trans_t *p, kv_u_trans_t *res) -{ - double index_time = yak_realtime(); - // ha_flt_tab = NULL; - uint64_t i, k, l, occ, m, cc; kv_ul_ov_t *bl = NULL; - u_trans_t *z; ha_mzl_t *tz; double ww; - clean_u_trans_t_idx_adv(res, p->ug, p->rg); p->filter = res; - // fprintf(stderr, "[M::%s::] ==> 0\n", __func__); - p->is_cnt = 1; p->is_ovlp = 0; - memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); - kt_for(p->n_thread, worker_for_trans_ovlp_adv, p, p->ug->u.n); - for (i = l = 0; i < p->ug->u.n; i++) { - occ = p->idx_n.a[i]; p->idx_n.a[i] = l; l += occ; - } - // fprintf(stderr, "[M::%s::] i::%lu, l::%lu\n", __func__, i, l); - p->idx_n.a[i] = l; - p->idx_a.n = p->idx_a.m = l; MALLOC(p->idx_a.a, p->idx_a.n); - // fprintf(stderr, "[M::%s::] ==> 1\n", __func__); - p->is_cnt = 0; p->is_ovlp = 0; - memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); - kt_for(p->n_thread, worker_for_trans_ovlp_adv, p, p->ug->u.n); - p->srt_a.n = p->srt_a.m = p->idx_a.n; MALLOC(p->srt_a.a, p->srt_a.n); - // fprintf(stderr, "[M::%s::] p->idx_a.n::%lu \n", __func__, (uint64_t)p->idx_a.n); - // memcpy(p->srt_a.a, p->idx_a.a, p->srt_a.n*sizeof((*(p->srt_a.a)))); - for (i = 0; i < p->srt_a.n; i++) { - p->srt_a.a[i] = p->idx_a.a[i]; - p->srt_a.a[i].pos = (uint32_t)i; - p->srt_a.a[i].rid = i>>32; - } - radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); - kvec_t(uint64_t) cut; kv_init(cut); - for (k = 1, l = 0; k <= p->srt_a.n; k++) { - if(k == p->srt_a.n || p->srt_a.a[l].x != p->srt_a.a[k].x) { - for (i = l; i < k; i++) { - m = p->srt_a.a[i].rid; m <<= 32; m |= p->srt_a.a[i].pos; - assert(p->srt_a.a[i].x == p->idx_a.a[m].x); - p->srt_a.a[i] = p->idx_a.a[m]; p->idx_a.a[m].x = i; - } - kv_push(uint64_t, cut, (k - l)); - l = k; - } - } - - if(cut.n > 0) { - radix_sort_gfa64(cut.a, cut.a + cut.n); - m = cut.n * 0.0002; cc = cut.a[cut.n-1] + 1; - if(m > 0 && m <= cut.n) cc = cut.a[cut.n-m] + 1; - if(cc < (uint64_t)p->mini_cut) p->mini_cut = cc; - } - kv_destroy(cut); - // fprintf(stderr, "[M::%s::] p->mini_cut::%d \n", __func__, p->mini_cut); - - // fprintf(stderr, "[M::%s::] ==> 2\n", __func__); - p->is_cnt = 0; p->is_ovlp = 1; - memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); - kt_for(p->n_thread, worker_for_trans_ovlp_adv, p, p->ug->u.n); - // fprintf(stderr, "[M::%s::] ==> 3\n", __func__); - for (i = 0; (int64_t)i < p->n_thread; i++) { - ha_ovec_destroy(p->hab[i]); - free(p->ll[i].lo.a); free(p->ll[i].srt.a.a); free(p->ll[i].tc.a); - } - free(p->idx_a.a); free(p->idx_n.a); free(p->hab); free(p->free_cnt); - // destory_bubbles(p->bub); free(p->bub); - - // fprintf(stderr, "[M::%s::] ==> 4\n", __func__); - ///make results consistent - kv_resize(ha_mzl_t, p->srt_a, p->ug->u.n); p->srt_a.n = p->ug->u.n; - for (i = 0; i < p->srt_a.n; i++) { - tz = &(p->srt_a.a[i]); - tz->x = (uint64_t)-1; tz->rev = 0; - tz->pos = tz->rid = tz->span = 0; - } - // memset(p->srt_a.a, 0, sizeof((*(p->srt_a.a)))*p->srt_a.n); - for (i = 0, occ = res->n; (int64_t)i < p->n_thread; i++) { - bl = &(p->ll[i].tk); - if(!(bl->n)) continue; - for (k = 1, l = 0; k <= bl->n; k++) { - if(k == bl->n || bl->a[k].qn != bl->a[l].qn) { - if(k > l) { - tz = &(p->srt_a.a[bl->a[l].qn]); - tz->x = bl->a[l].qn; tz->x <<= 32; tz->x |= i; - tz->rid = l>>32; tz->pos = (uint32_t)l; tz->rev = 1; - occ += (k - l); - } - l = k; - } - } - } - // fprintf(stderr, "[M::%s::] ==> 5\n", __func__); - // kt_for(p->n_thread, worker_for_sysm_trans_ovlp, p, p->ug->u.n);///not correct - // assert(p->srt_a.n <= p->ug->u.n); - // radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); - kv_resize(u_trans_t, *res, occ); - for (i = 0; i < p->srt_a.n; i++) { - tz = &(p->srt_a.a[i]); - if(!(tz->rev)) continue; - bl = &(p->ll[(uint32_t)(tz->x)].tk); - k = tz->rid; k <<= 32; k += tz->pos; - assert(bl->a[k].qn == (tz->x>>32)); - for (; (k < bl->n) && (bl->a[k].qn == (tz->x>>32)); k++) { - if(bl->a[k].qn == bl->a[k].tn) continue; - ww = cal_trans_ov_w(&(bl->a[k])); - if(ww <= 0) continue; - - kv_pushp(u_trans_t, *res, &z); - z->f = RC_3; z->rev = bl->a[k].rev; z->del = 0; - z->qn = bl->a[k].qn; z->qs = bl->a[k].qs; z->qe = bl->a[k].qe; - z->tn = bl->a[k].tn; z->ts = bl->a[k].ts; z->te = bl->a[k].te; - z->nw = ww; - // if(z->qn == 56 || z->qn == 160 || z->tn == 56 || z->tn == 160) { - // fprintf(stderr, ">>>utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\n", - // z->qn+1, "lc"[p->ug->u.a[z->qn].circ], p->ug->u.a[z->qn].len, z->qs, z->qe, "+-"[z->rev], - // z->tn+1, "lc"[p->ug->u.a[z->tn].circ], p->ug->u.a[z->tn].len, z->ts, z->te, z->nw); - // } - // if(z->nw <= 0) res->n--; - } - } - // fprintf(stderr, "[M::%s::] ==> 6\n", __func__); - for (i = 0; (int64_t)i < p->n_thread; i++) free(p->ll[i].tk.a); - free(p->srt_a.a); free(p->ll); - fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); -} - -void clean_trans_base_count_mmhap_comp_rmap(ug_trans_t *p, kv_u_trans_t *res) -{ - uint64_t i, k, l, occ, idx_n; ha_mzl_t *tz; u_trans_t *z; - kv_ul_ov_t *bl; double ww; ha_mzl_t *idx; - ///make results consistent - kv_resize(ha_mzl_t, p->srt_a, p->srt_a.n+p->ug->u.n); - idx = p->srt_a.a + p->srt_a.n; idx_n = p->ug->u.n; - for (i = 0; i < idx_n; i++) { - tz = &(idx[i]); - tz->x = (uint64_t)-1; tz->rev = 0; - tz->pos = tz->rid = tz->span = 0; - } - - for (i = 0, occ = res->n; (int64_t)i < p->n_thread; i++) { - bl = &(p->ll[i].tk); - if(!(bl->n)) continue; - for (k = 1, l = 0; k <= bl->n; k++) { - if(k == bl->n || bl->a[k].qn != bl->a[l].qn) { - if(k > l) { - tz = &(idx[bl->a[l].qn]); - tz->x = bl->a[l].qn; tz->x <<= 32; tz->x |= i; - tz->rid = l>>32; tz->pos = (uint32_t)l; tz->rev = 1; - occ += (k - l); - } - l = k; - } - } - } - - kv_resize(u_trans_t, *res, occ); - for (i = 0; i < idx_n; i++) { - tz = &(idx[i]); - if(!(tz->rev)) continue; - bl = &(p->ll[(uint32_t)(tz->x)].tk); - k = tz->rid; k <<= 32; k += tz->pos; - assert(bl->a[k].qn == (tz->x>>32)); - for (; (k < bl->n) && (bl->a[k].qn == (tz->x>>32)); k++) { - if(bl->a[k].qn == bl->a[k].tn) continue; - ww = cal_trans_ov_w(&(bl->a[k])); - if(ww <= 0) continue; - - kv_pushp(u_trans_t, *res, &z); - z->f = RC_3; z->rev = bl->a[k].rev; z->del = 0; - z->qn = bl->a[k].qn; z->qs = bl->a[k].qs; z->qe = bl->a[k].qe; - z->tn = bl->a[k].tn; z->ts = bl->a[k].ts; z->te = bl->a[k].te; - z->nw = ww; - } - } - destory_ug_rid_cov_t(p->ccov); free(p->ccov); - p->ccov = gen_ug_rid_cov_t(p->ug, p->rg, p->uopt->sources); - - clean_u_trans_t_idx_filter_mmhap_adv(res, p->ug, p->rg, p->uopt->sources, p->ccov); - gen_ug_rid_cov_t_by_ovlp(res, p->ccov); -} - -void gen_trans_base_count_mmhap_comp_rmap(ug_trans_t *p, kv_u_trans_t *res) -{ - double index_time = yak_realtime(); - uint64_t i, k, l, occ, m, cc; - p->ccov = gen_ug_rid_cov_t(p->ug, p->rg, p->uopt->sources); - clean_u_trans_t_idx_adv(res, p->ug, p->rg); p->filter = res; - - p->is_cnt = 1; p->is_ovlp = 0; - memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); - kt_for(p->n_thread, worker_for_trans_ovlp_mmhap_adv, p, p->ug->u.n); - for (i = l = 0; i < p->ug->u.n; i++) { - occ = p->idx_n.a[i]; p->idx_n.a[i] = l; l += occ; - } - - p->idx_n.a[i] = l; - p->idx_a.n = p->idx_a.m = l; MALLOC(p->idx_a.a, p->idx_a.n); - p->is_cnt = 0; p->is_ovlp = 0; - memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); - kt_for(p->n_thread, worker_for_trans_ovlp_mmhap_adv, p, p->ug->u.n); - p->srt_a.n = p->srt_a.m = p->idx_a.n; MALLOC(p->srt_a.a, p->srt_a.n); - - for (i = 0; i < p->srt_a.n; i++) { - p->srt_a.a[i] = p->idx_a.a[i]; - p->srt_a.a[i].pos = (uint32_t)i; - p->srt_a.a[i].rid = i>>32; - } - radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); - kvec_t(uint64_t) cut; kv_init(cut); - for (k = 1, l = 0; k <= p->srt_a.n; k++) { - if(k == p->srt_a.n || p->srt_a.a[l].x != p->srt_a.a[k].x) { - for (i = l; i < k; i++) { - m = p->srt_a.a[i].rid; m <<= 32; m |= p->srt_a.a[i].pos; - assert(p->srt_a.a[i].x == p->idx_a.a[m].x); - p->srt_a.a[i] = p->idx_a.a[m]; p->idx_a.a[m].x = i; - } - kv_push(uint64_t, cut, (k - l)); - l = k; - } - } - - if(cut.n > 0) { - radix_sort_gfa64(cut.a, cut.a + cut.n); - m = cut.n * 0.0002; cc = cut.a[cut.n-1] + 1; - if(m > 0 && m <= cut.n) cc = cut.a[cut.n-m] + 1; - if(cc < (uint64_t)p->mini_cut) p->mini_cut = cc; - } - kv_destroy(cut); - - p->is_cnt = 0; p->is_ovlp = 1; - memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); - kt_for(p->n_thread, worker_for_trans_ovlp_mmhap_adv, p, p->ug->u.n); - - clean_trans_base_count_mmhap_comp_rmap(p, res); - - for (i = 0; (int64_t)i < p->n_thread; i++) p->ll[i].tk.n = 0; - - p->is_cnt = 0; p->is_ovlp = 1; - memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); - kt_for(p->n_thread, worker_for_trans_chain_mmhap_adv, p, p->ug->u.n); - - - - - - for (i = 0; (int64_t)i < p->n_thread; i++) { - ha_ovec_destroy(p->hab[i]); - free(p->ll[i].lo.a); free(p->ll[i].srt.a.a); free(p->ll[i].tc.a); - } - free(p->idx_a.a); free(p->idx_n.a); free(p->hab); free(p->free_cnt); - destory_ug_rid_cov_t(p->ccov); free(p->ccov); - - - - - - - - - - - for (i = 0; (int64_t)i < p->n_thread; i++) free(p->ll[i].tk.a); - free(p->srt_a.a); free(p->ll); - fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); -} - -void gen_trans_base_count_mmhap_comp(ug_trans_t *p, kv_u_trans_t *res) -{ - double index_time = yak_realtime(); - // ha_flt_tab = NULL; - uint64_t i, k, l, occ, m, cc; kv_ul_ov_t *bl = NULL; - u_trans_t *z; ha_mzl_t *tz; double ww; - p->ccov = gen_ug_rid_cov_t(p->ug, p->rg, p->uopt->sources); - clean_u_trans_t_idx_adv(res, p->ug, p->rg); p->filter = res; - // fprintf(stderr, "[M::%s::] ==> 0\n", __func__); - p->is_cnt = 1; p->is_ovlp = 0; - memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); - kt_for(p->n_thread, worker_for_trans_ovlp_mmhap_adv, p, p->ug->u.n); - for (i = l = 0; i < p->ug->u.n; i++) { - occ = p->idx_n.a[i]; p->idx_n.a[i] = l; l += occ; - } - // fprintf(stderr, "[M::%s::] i::%lu, l::%lu\n", __func__, i, l); - p->idx_n.a[i] = l; - p->idx_a.n = p->idx_a.m = l; MALLOC(p->idx_a.a, p->idx_a.n); - // fprintf(stderr, "[M::%s::] ==> 1\n", __func__); - p->is_cnt = 0; p->is_ovlp = 0; - memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); - kt_for(p->n_thread, worker_for_trans_ovlp_mmhap_adv, p, p->ug->u.n); - p->srt_a.n = p->srt_a.m = p->idx_a.n; MALLOC(p->srt_a.a, p->srt_a.n); - // fprintf(stderr, "[M::%s::] p->idx_a.n::%lu \n", __func__, (uint64_t)p->idx_a.n); - // memcpy(p->srt_a.a, p->idx_a.a, p->srt_a.n*sizeof((*(p->srt_a.a)))); - for (i = 0; i < p->srt_a.n; i++) { - p->srt_a.a[i] = p->idx_a.a[i]; - p->srt_a.a[i].pos = (uint32_t)i; - p->srt_a.a[i].rid = i>>32; - } - radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); - kvec_t(uint64_t) cut; kv_init(cut); - for (k = 1, l = 0; k <= p->srt_a.n; k++) { - if(k == p->srt_a.n || p->srt_a.a[l].x != p->srt_a.a[k].x) { - for (i = l; i < k; i++) { - m = p->srt_a.a[i].rid; m <<= 32; m |= p->srt_a.a[i].pos; - assert(p->srt_a.a[i].x == p->idx_a.a[m].x); - p->srt_a.a[i] = p->idx_a.a[m]; p->idx_a.a[m].x = i; - } - kv_push(uint64_t, cut, (k - l)); - l = k; - } - } - - if(cut.n > 0) { - radix_sort_gfa64(cut.a, cut.a + cut.n); - m = cut.n * 0.0002; cc = cut.a[cut.n-1] + 1; - if(m > 0 && m <= cut.n) cc = cut.a[cut.n-m] + 1; - if(cc < (uint64_t)p->mini_cut) p->mini_cut = cc; - } - kv_destroy(cut); - // fprintf(stderr, "[M::%s::] p->mini_cut::%d \n", __func__, p->mini_cut); - - // fprintf(stderr, "[M::%s::] ==> 2\n", __func__); - p->is_cnt = 0; p->is_ovlp = 1; - memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); - kt_for(p->n_thread, worker_for_trans_ovlp_mmhap_adv, p, p->ug->u.n); - // fprintf(stderr, "[M::%s::] ==> 3\n", __func__); - for (i = 0; (int64_t)i < p->n_thread; i++) { - ha_ovec_destroy(p->hab[i]); - free(p->ll[i].lo.a); free(p->ll[i].srt.a.a); free(p->ll[i].tc.a); - } - free(p->idx_a.a); free(p->idx_n.a); free(p->hab); free(p->free_cnt); - destory_ug_rid_cov_t(p->ccov); free(p->ccov); - // destory_bubbles(p->bub); free(p->bub); - - // fprintf(stderr, "[M::%s::] ==> 4\n", __func__); - ///make results consistent - kv_resize(ha_mzl_t, p->srt_a, p->ug->u.n); p->srt_a.n = p->ug->u.n; - for (i = 0; i < p->srt_a.n; i++) { - tz = &(p->srt_a.a[i]); - tz->x = (uint64_t)-1; tz->rev = 0; - tz->pos = tz->rid = tz->span = 0; - } - // memset(p->srt_a.a, 0, sizeof((*(p->srt_a.a)))*p->srt_a.n); - for (i = 0, occ = res->n; (int64_t)i < p->n_thread; i++) { - bl = &(p->ll[i].tk); - if(!(bl->n)) continue; - for (k = 1, l = 0; k <= bl->n; k++) { - if(k == bl->n || bl->a[k].qn != bl->a[l].qn) { - if(k > l) { - tz = &(p->srt_a.a[bl->a[l].qn]); - tz->x = bl->a[l].qn; tz->x <<= 32; tz->x |= i; - tz->rid = l>>32; tz->pos = (uint32_t)l; tz->rev = 1; - occ += (k - l); - } - l = k; - } - } - } - // fprintf(stderr, "[M::%s::] ==> 5\n", __func__); - // kt_for(p->n_thread, worker_for_sysm_trans_ovlp, p, p->ug->u.n);///not correct - // assert(p->srt_a.n <= p->ug->u.n); - // radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); - kv_resize(u_trans_t, *res, occ); - for (i = 0; i < p->srt_a.n; i++) { - tz = &(p->srt_a.a[i]); - if(!(tz->rev)) continue; - bl = &(p->ll[(uint32_t)(tz->x)].tk); - k = tz->rid; k <<= 32; k += tz->pos; - assert(bl->a[k].qn == (tz->x>>32)); - for (; (k < bl->n) && (bl->a[k].qn == (tz->x>>32)); k++) { - if(bl->a[k].qn == bl->a[k].tn) continue; - ww = cal_trans_ov_w(&(bl->a[k])); - if(ww <= 0) continue; - - kv_pushp(u_trans_t, *res, &z); - z->f = RC_3; z->rev = bl->a[k].rev; z->del = 0; - z->qn = bl->a[k].qn; z->qs = bl->a[k].qs; z->qe = bl->a[k].qe; - z->tn = bl->a[k].tn; z->ts = bl->a[k].ts; z->te = bl->a[k].te; - z->nw = ww; - // if(z->ts >= z->te || z->qs >= z->qe) { - // fprintf(stderr, "[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, - // z->qn+1, "lc"[p->ug->u.a[z->qn].circ], p->ug->u.a[z->qn].len, z->qs, z->qe, "+-"[z->rev], - // z->tn+1, "lc"[p->ug->u.a[z->tn].circ], p->ug->u.a[z->tn].len, z->ts, z->te); - // } - // if(z->qn == 56 || z->qn == 160 || z->tn == 56 || z->tn == 160) { - // fprintf(stderr, ">>>utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\n", - // z->qn+1, "lc"[p->ug->u.a[z->qn].circ], p->ug->u.a[z->qn].len, z->qs, z->qe, "+-"[z->rev], - // z->tn+1, "lc"[p->ug->u.a[z->tn].circ], p->ug->u.a[z->tn].len, z->ts, z->te, z->nw); - // } - // if(z->nw <= 0) res->n--; - } - } - // fprintf(stderr, "[M::%s::] ==> 6\n", __func__); - for (i = 0; (int64_t)i < p->n_thread; i++) free(p->ll[i].tk.a); - free(p->srt_a.a); free(p->ll); - fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); -} - -void trans_base_infer(ma_ug_t *ug, asg_t *sg, ug_opt_t *uopt, kv_u_trans_t *res, bubble_type *bub) -{ - ug_trans_t sl; - init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); - init_ug_trans_t(&sl, uopt, 0, asm_opt.trans_mer_length, asm_opt.trans_win, asm_opt.max_n_chain, - 1.0-asm_opt.trans_base_rate, 1.0-asm_opt.trans_base_rate, 1.0-asm_opt.trans_base_rate_sec, 1.0-asm_opt.trans_base_rate_sec, - 0.85, asm_opt.thread_num, 512, 3, 1, ug, sg, bub, 1); - // gen_trans_base_count(&sl, res); - gen_trans_base_count_comp(&sl, res); - if(!bub) { - destory_bubbles(sl.bub); free(sl.bub); - } -} - -void trans_base_mmhap_infer(ma_ug_t *ug, asg_t *sg, ug_opt_t *uopt, kv_u_trans_t *res) -{ - ug_trans_t sl; - init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); - init_ug_trans_t(&sl, uopt, 0, asm_opt.trans_mer_length, asm_opt.trans_win, asm_opt.max_n_chain, - 1.0-asm_opt.trans_base_rate, 1.0-asm_opt.trans_base_rate, 1.0-asm_opt.trans_base_rate_sec, 1.0-asm_opt.trans_base_rate_sec, - 0.85, asm_opt.thread_num, 512, 3, 1, ug, sg, NULL, 0); - // gen_trans_base_count(&sl, res); - gen_trans_base_count_mmhap_comp(&sl, res); -} - -void init_ug_bin_t(ug_bin_t *sl, const ug_opt_t *uopt, int32_t is_HPC, int32_t k, int32_t w, int32_t max_n_chain, -double bw_thres, double diff_ov, double diff_bin, uint64_t max_diff, uint64_t min_bin_len, int32_t n_thread, -int32_t mini_cut, int32_t chain_cut, int32_t keep_unsymm_arc, ma_ug_t *ug, asg_t *sg) -{ - int64_t i; - memset(sl, 0, sizeof((*sl))); - sl->uopt = uopt; - sl->k = k; - sl->w = w; - sl->is_HPC = is_HPC; - sl->max_n_chain = max_n_chain; - sl->bw_thres = bw_thres; - sl->diff_ov = diff_ov; - sl->diff_bin = diff_bin; - sl->max_diff = max_diff; - sl->min_bin_len = min_bin_len; - sl->mini_cut = mini_cut; - sl->chain_cut = chain_cut; - sl->keep_unsymm_arc = keep_unsymm_arc; - - sl->bw = 10000;///2000 in minigraph - sl->max_gap = 500000;///5000 in minigraph - sl->ug = ug; - sl->rg = sg; - sl->n_thread = ((n_thread>=1)?n_thread:1); - - CALLOC(sl->mk, sl->n_thread); - CALLOC(sl->hab, sl->n_thread); - CALLOC(sl->ll, sl->n_thread); - for (i = 0; i < sl->n_thread; ++i) sl->hab[i] = ha_ovec_init(0, 0, 1); - - sl->idx_n.n = sl->idx_n.m = ug->u.n+1; - MALLOC(sl->idx_n.a, sl->idx_n.n); - - sl->udb.ug = ug; - // CALLOC(sl->bm, sl->n_thread); - // for (i = 0; i < sl->n_thread; ++i) { - // sl->bm[i].n = ((sl->udb.ug->g->n_seq<<1)>>3) + (!!((sl->udb.ug->g->n_seq<<1)&((uint32_t)7))); - // CALLOC(sl->bm[i].a, sl->bm[i].n); - // } -} - -void extract_microsatellite(const char *in, uint32_t in_len, hpc_re_t *res, asg64_v *buf, uint32_t mcs_len, -uint32_t min_klen_simple, uint32_t min_klen_complex, uint32_t ksimple_cut, hpc_idx_t *idx) -{ - uint32_t k, i, l, c, o, ls; char sk[256]; hpc_ss_t z, *za; - uint32_t m, cutoff, zn, bn, ovlp, os, oe, oks, oke; - idx->s = idx->e = res->n; - if(mcs_len > 255) mcs_len = 255; - for (k = 1; k <= mcs_len; k++) { - memset(sk, 'N', k); ///k->length of k-mer - o = ((k<=ksimple_cut)?(k*min_klen_simple):(k*min_klen_complex)); - for (i = l = ls = 0; i < in_len; i++) { - c = seq_nt4_table[(uint8_t)in[i]]; - if((c < 4) && (((l >= k) && (sk[(l+ls)%k] == in[i])) || (l < k))) { - if(l < k) sk[(l+ls)%k] = in[i]; - l++; - } else { - if(l >= o) { - z.s = i-l; z.e = i; z.k = k; - kv_push(hpc_ss_t, *res, z); - } - - if(c >= 4) { - l = ls = 0; - } else if(l >= 0) { - sk[(l+ls)%k] = in[i]; l++; - m = ((l<=k)?(l-1):(k)); - ls = (ls+(l-m))%k; l = m; - } - } - } - } - - uint32_t ks, ke, fs, fe; - radix_sort_hpc_ss_t_s(res->a+idx->s, res->a+res->n); - for (k = ks = ke = idx->e = idx->s; k < res->n; k++) { - fs = fe = (uint32_t)-1; - if(ke > idx->s) { - fs = res->a[ks].s; fe = res->a[ke-1].e; - } - ///new interval is not overlapped with existing one - if((fs == ((uint32_t)-1)) || (fe <= res->a[k].s)) { - res->a[idx->e++] = res->a[k]; ks = idx->e - 1; ke = idx->e; - } else { - assert(res->a[k].s >= fs); - ///new interval might be contained in an exist one - if(res->a[k].s >= fs && res->a[k].e <= fe) { - for (i = ks; i < ke; i++) { - if(res->a[k].s >= res->a[i].s && res->a[k].e <= res->a[i].e) {///new interval is contained in an exist one - if((res->a[k].s == res->a[i].s) && (res->a[k].e == res->a[i].e) - && (res->a[k].k < res->a[i].k)) { - res->a[i] = res->a[k]; - } - break; - } - } - if(i < ke) continue; - } - - for (i = m = ks; i < ke; i++) { - ///exist interval is contained in new interval - if(res->a[k].s <= res->a[i].s && res->a[k].e >= res->a[i].e) continue; - res->a[m++] = res->a[i]; - } - ke = idx->e = m; - res->a[idx->e++] = res->a[k]; ke = idx->e; - } - } - res->n = idx->e; - cutoff = (in_len/sizeof((*(res->a))))/4; if(cutoff < 10) cutoff = 10; - if(idx->e-idx->s > cutoff) {///compress if there are too many intervals - kv_resize(uint64_t, *buf, res->n-idx->s); - za = res->a + idx->s; zn = idx->e - idx->s; - for (k = buf->n = 0; k < zn; k++) { - kv_push(uint64_t, *buf, ((((uint64_t)za[k].k)<<32)|((uint64_t)(k)))); - } - radix_sort_gfa64(buf->a, buf->a+buf->n);///sorted by the k-mer length - for (i = 0, bn = buf->n; i < bn; i++) { - k = (uint32_t)buf->a[i]; oks = za[k].s; oke = za[k].e; - for (m = 0; m < zn && za[m].s < za[k].e; m++) { - if(!(buf->a[m]&((uint64_t)0x8000000000000000))) continue; - if(m == k) continue; - ///now has overlap - os = MAX(za[m].s, oks); oe = MIN(za[m].e, oke); - ovlp = ((oe > os)?(oe - os):(0)); - if(!ovlp) continue; - assert(os == oks || oe == oke); - if(os == oks) oks = oe; - if(oe == oke) oke = os; - if(oke < oks + za[k].k) break; - } - if(oke >= oks + za[k].k) { - buf->a[k] |= ((uint64_t)0x8000000000000000); - } - } - for (i = 0, idx->e = idx->s; i < bn; i++) { - if(!(buf->a[i]&((uint64_t)0x8000000000000000))) continue; - res->a[idx->e++] = za[i]; - } - res->n = idx->e; - } - // for (i = idx->s; i < idx->e; i++) { - // fprintf(stderr, "k::%u\tin::[%u,\t%u)\n", res->a[i].k, res->a[i].s, res->a[i].e); - // } -} - -hpc_re_t *gen_hpc_re_t(ma_ug_t *ug) -{ - uint64_t k; asg64_v buf; kv_init(buf); - hpc_re_t *p = NULL; CALLOC(p, 1); - kvec_t(char) cc; kv_init(cc); - p->idx_n = ug->u.n; CALLOC(p->idx, p->idx_n); - - for (k = 0; k < ug->u.n; k++) { - kv_resize(char, cc, ug->u.a[k].len); - retrieve_u_seq(NULL, cc.a, &(ug->u.a[k]), 0, 0, ug->u.a[k].len, NULL); - // fprintf(stderr, "\nutg%.6lu%c\tlen::%u\n", k + 1, "lc"[ug->u.a[k].circ], ug->u.a[k].len); - extract_microsatellite(cc.a, ug->u.a[k].len, p, &buf, 8, 8, 5, 1, &(p->idx[k])); - // fprintf(stderr, "utg%.6lu%c\t#::%u\tlen::%u\n", k + 1, "lc"[ug->u.a[k].circ], p->idx[k].e-p->idx[k].s, ug->u.a[k].len); - } - - kv_destroy(cc); kv_destroy(buf); - return p; -} - -void sysm_graph_bin(ug_bin_t *s) -{ - uint64_t k, i; kv_emask_t *r; - s->is_cnt = 1; s->is_ovlp = 0; - kt_for(s->n_thread, worker_for_graph_bin_sysm, s, s->ug->u.n); - for (i = 0; i < s->mm->n; i++) { - r = &(s->mm->a[i]); - for (k = 0; k < r->n; k++) { - if(r->a[k].rn == (uint32_t)-1) s->mm->a[r->a[k].tn].m++; - } - } - for (i = 0; i < s->mm->n; i++) { - r = &(s->mm->a[i]); - if(r->m > r->n) REALLOC(r->a, r->m); - } - - - s->is_cnt = 0; s->is_ovlp = 1; - kt_for(s->n_thread, worker_for_graph_bin_sysm, s, s->ug->u.n); - - s->is_cnt = 1; s->is_ovlp = 1; - kt_for(s->n_thread, worker_for_graph_bin_sysm, s, s->ug->u.n); -} - -void cal_graph_ovlp_binning(ug_bin_t *p) -{ - double index_time = yak_realtime(); - // ha_flt_tab = NULL; - uint64_t i, k, l, occ, m, cc; - // p->hre = gen_hpc_re_t(p->ug); - CALLOC(p->mm, 1); p->mm->n = p->udb.ug->g->n_seq; CALLOC(p->mm->a, p->mm->n); - - // fprintf(stderr, "[M::%s::] ==> 0\n", __func__); - p->is_cnt = 1; p->is_ovlp = 0; - kt_for(p->n_thread, worker_for_graph_bin, p, p->ug->u.n); - for (i = l = 0; i < p->ug->u.n; i++) { - occ = p->idx_n.a[i]; p->idx_n.a[i] = l; l += occ; - } - // fprintf(stderr, "[M::%s::] i::%lu, l::%lu\n", __func__, i, l); - p->idx_n.a[i] = l; - p->idx_a.n = p->idx_a.m = l; MALLOC(p->idx_a.a, p->idx_a.n); - // fprintf(stderr, "[M::%s::] ==> 1\n", __func__); - p->is_cnt = 0; p->is_ovlp = 0; - kt_for(p->n_thread, worker_for_graph_bin, p, p->ug->u.n); - p->srt_a.n = p->srt_a.m = p->idx_a.n; MALLOC(p->srt_a.a, p->srt_a.n); - // fprintf(stderr, "[M::%s::] p->idx_a.n::%lu \n", __func__, (uint64_t)p->idx_a.n); - // memcpy(p->srt_a.a, p->idx_a.a, p->srt_a.n*sizeof((*(p->srt_a.a)))); - for (i = 0; i < p->srt_a.n; i++) { - p->srt_a.a[i] = p->idx_a.a[i]; - p->srt_a.a[i].pos = (uint32_t)i; - p->srt_a.a[i].rid = i>>32; - } - radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); - kvec_t(uint64_t) cut; kv_init(cut); - for (k = 1, l = 0; k <= p->srt_a.n; k++) { - if(k == p->srt_a.n || p->srt_a.a[l].x != p->srt_a.a[k].x) { - for (i = l; i < k; i++) { - m = p->srt_a.a[i].rid; m <<= 32; m |= p->srt_a.a[i].pos; - assert(p->srt_a.a[i].x == p->idx_a.a[m].x); - p->srt_a.a[i] = p->idx_a.a[m]; p->idx_a.a[m].x = i; - } - kv_push(uint64_t, cut, (k - l)); - l = k; - } - } - - if(cut.n > 0) { - radix_sort_gfa64(cut.a, cut.a + cut.n); - m = cut.n * 0.0002; cc = cut.a[cut.n-1] + 1; - if(m > 0 && m <= cut.n) cc = cut.a[cut.n-m] + 1; - if(cc < (uint64_t)p->mini_cut) p->mini_cut = cc; - } - kv_destroy(cut); - // fprintf(stderr, "[M::%s::] p->mini_cut::%d \n", __func__, p->mini_cut); - - // fprintf(stderr, "[M::%s::] ==> 2\n", __func__); - p->is_cnt = 0; p->is_ovlp = 1; - kt_for(p->n_thread, worker_for_graph_bin, p, p->ug->u.n); - // fprintf(stderr, "[M::%s::] ==> 3\n", __func__); - // exit(1); - for (i = 0; (int64_t)i < p->n_thread; i++) { - ha_ovec_destroy(p->hab[i]); - free(p->ll[i].lo.a); free(p->ll[i].srt.a.a); free(p->ll[i].tc.a); free(p->ll[i].tk.a); - } - free(p->idx_a.a); free(p->idx_n.a); free(p->hab); free(p->srt_a.a); free(p->ll); - // fprintf(stderr, "[M::%s::] ==> 4\n", __func__); - - // sysm_graph_bin(p); - for (i = 0; (int64_t)i < p->n_thread; i++) { - free(p->mk[i].idx.a); free(p->mk[i].srt.a); - } - free(p->mk); - fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); -} - -idx_emask_t* graph_ovlp_binning(ma_ug_t *ug, asg_t *sg, const ug_opt_t *uopt) -{ - ug_bin_t sl; - init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); - init_ug_bin_t(&sl, uopt, 0, GBIN_K, GBIN_W, asm_opt.max_n_chain, GBIN_E, GBIN_E, GBIN_BE, GBIN_ME, GBIN_L, - asm_opt.thread_num, 512, 3, 1, ug, sg); - cal_graph_ovlp_binning(&sl); - return sl.mm; -} - - -ma_ug_t *ul_realignment(const ug_opt_t *uopt, asg_t *sg, uint32_t double_check_cache, const char *bin_file) -{ - fprintf(stderr, "[M::%s::] ==> starting UL\n", __func__); - mg_idxopt_t opt; uldat_t sl; - int32_t cutoff; - char* gfa_name = NULL; MALLOC(gfa_name, strlen(asm_opt.output_file_name)+50); - sprintf(gfa_name, "%s.%s", asm_opt.output_file_name, bin_file); - - init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); - cutoff = REA_ALIGN_CUTOFF; - init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); - init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, NULL); - ma_ug_t *ug = gen_polished_ug(uopt, sg); - // dd_ug(sg, ug, uopt->coverage_cut, uopt->sources, uopt->ruIndex, "UL.sa"); - // debug_sl_compress_base_disk_0(&sl, asm_opt.ar); - // detect_outlier_len("ul_realignment"); - clear_all_ul_t(&UL_INF); - - ///for debug interval - if(!load_all_ul_t(&UL_INF, gfa_name, &R_INF, ug)) { - gen_UL_reovlps(&sl, ug, sg, gfa_name, cutoff, 1); - // exit(1); - write_all_ul_t(&UL_INF, gfa_name, ug); - } else{ - free(UL_INF.ridx.idx.a); free(UL_INF.ridx.occ.a); - memset(&(UL_INF.ridx), 0, sizeof((UL_INF.ridx))); - if(double_check_cache){ - if(drenew_UL_reovlps(&sl, ug, sg, gfa_name, cutoff)) { - write_all_ul_t(&UL_INF, gfa_name, ug); - } - } - } - - // print_ul_alignment(ug, &UL_INF, 147, "init-0"); - filter_ul_ug(ug); - // print_ul_alignment(ug, &UL_INF, 147, "init-1"); - gen_ul_vec_rid_t(&UL_INF, NULL, ug); - // print_ul_alignment(ug, &UL_INF, 147, "init-2"); - update_ug_arch_ul_mul(ug); - - // exit(1); - // print_ul_alignment(ug, &UL_INF, 41927, "init-3"); - // kt_for(asm_opt.thread_num, update_ug_arch_ul, ug, ug->g->n_arc); - // print_all_ul_t_stat(&UL_INF); - // kt_for(sl.n_thread, update_ovlp_src, &sl, R_INF.total_reads); - // kt_for(sl.n_thread, update_ovlp_src_bl, &sl, R_INF.total_reads); - - // print_ovlp_src_bl_stat(&UL_INF, sl.uopt); - // print_ul_ovlps(&UL_INF, 0); print_ul_ovlps(&UL_INF, 1); - - // destory_all_ul_t(&UL_INF); - free(gfa_name); - return ug; -} - - -ma_ug_t *ul_realignment_back(const ug_opt_t *uopt, asg_t *sg, uint32_t double_check_cache, const char *bin_file) -{ - fprintf(stderr, "[M::%s::] ==> starting UL\n", __func__); - mg_idxopt_t opt; uldat_t sl; - int32_t cutoff; - char* gfa_name = NULL; MALLOC(gfa_name, strlen(asm_opt.output_file_name)+50); - sprintf(gfa_name, "%s.%s", asm_opt.output_file_name, bin_file); - - init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); - cutoff = REA_ALIGN_CUTOFF; - init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); - init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, NULL); - ma_ug_t *ug = gen_polished_ug(uopt, sg); - // dd_ug(sg, ug, uopt->coverage_cut, uopt->sources, uopt->ruIndex, "UL.sa"); - // debug_sl_compress_base_disk_0(&sl, asm_opt.ar); - // detect_outlier_len("ul_realignment"); - clear_all_ul_t(&UL_INF); - - ///for debug interval - if(!load_all_ul_t(&UL_INF, gfa_name, &R_INF, ug)) { - gen_UL_reovlps(&sl, ug, sg, gfa_name, cutoff, 0); - // exit(1); - write_all_ul_t(&UL_INF, gfa_name, ug); - } else{ - free(UL_INF.ridx.idx.a); free(UL_INF.ridx.occ.a); - memset(&(UL_INF.ridx), 0, sizeof((UL_INF.ridx))); - if(double_check_cache){ - if(drenew_UL_reovlps(&sl, ug, sg, gfa_name, cutoff)) { - write_all_ul_t(&UL_INF, gfa_name, ug); - } - } - } - - // print_ul_alignment(ug, &UL_INF, 41927, "init-0"); - filter_ul_ug(ug); - // print_ul_alignment(ug, &UL_INF, 41927, "init-1"); - gen_ul_vec_rid_t(&UL_INF, NULL, ug); - // print_ul_alignment(ug, &UL_INF, 41927, "init-2"); - update_ug_arch_ul_mul(ug); - // print_ul_alignment(ug, &UL_INF, 41927, "init-3"); - // kt_for(asm_opt.thread_num, update_ug_arch_ul, ug, ug->g->n_arc); - // print_all_ul_t_stat(&UL_INF); - // kt_for(sl.n_thread, update_ovlp_src, &sl, R_INF.total_reads); - // kt_for(sl.n_thread, update_ovlp_src_bl, &sl, R_INF.total_reads); - - // print_ovlp_src_bl_stat(&UL_INF, sl.uopt); - // print_ul_ovlps(&UL_INF, 0); print_ul_ovlps(&UL_INF, 1); - - // destory_all_ul_t(&UL_INF); - free(gfa_name); - return ug; +#include +#include +#include +#include +#include +#include "kseq.h" // FASTA/Q parser +#include "kavl.h" +#include "khash.h" +#include "kalloc.h" +#include "kthread.h" +#include "inter.h" +#include "Overlaps.h" +#include "CommandLines.h" +#include "htab.h" +#include "Hash_Table.h" +#include "Correct.h" +#include "Process_Read.h" +#include "Assembly.h" +#include "hic.h" +#include "gfa_ut.h" +KSEQ_INIT(gzFile, gzread) + +#define oreg_xe_lt(a, b) (((uint64_t)(a).x_pos_e<<32|(a).x_pos_s) < ((uint64_t)(b).x_pos_e<<32|(b).x_pos_s)) +KSORT_INIT(or_xe, overlap_region, oreg_xe_lt) + +#define u_trans_qs_key0(a) ((a).qs) +KRADIX_SORT_INIT(u_trans_qs0, u_trans_t, u_trans_qs_key0, member_size(u_trans_t, qs)) + +void ha_get_ul_candidates_interface(ha_abufl_t *ab, int64_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, overlap_region_alloc *overlap_list_hp, Candidates_list *cl, double bw_thres, + int max_n_chain, int keep_whole_chain, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* chain_idx, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t high_occ, void *km); +void ul_map_lchain(ha_abufl_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, + int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, uint32_t gen_off, double mcopy_rate, uint32_t chain_cutoff, uint32_t mcopy_khit_cut); +int64_t ug_map_lchain(ha_abufl_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, double bw_thres_sec, + int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, + uint32_t gen_off, double mcopy_rate, uint32_t mcopy_khit_cut, uint32_t is_hpc, ha_mzl_t *res, uint64_t res_n, ha_mzl_t *idx, uint64_t idx_n, uint64_t mzl_cutoff, uint64_t chain_cutoff, kv_u_trans_t *kov); +int64_t ug_map_lchain_simple(ha_abufl_t *ab, uint32_t rid, char* rs, uint64_t rl, uint64_t mz_w, uint64_t mz_k, const ul_idx_t *uref, overlap_region_alloc *overlap_list, Candidates_list *cl, double bw_thres, + int max_n_chain, int apend_be, kvec_t_u8_warp* k_flag, overlap_region* f_cigar, kvec_t_u64_warp* dbg_ct, st_mt_t *sp, uint32_t *high_occ, uint32_t *low_occ, uint32_t is_accurate, + uint32_t gen_off, double mcopy_rate, uint32_t mcopy_khit_cut, uint32_t is_hpc, ha_mzl_t *res, uint64_t res_n, ha_mzl_t *idx, uint64_t idx_n, uint64_t mzl_cutoff, uint64_t chain_cutoff); + +#define MG_SEED_IGNORE (1ULL<<41) +#define MG_SEED_TANDEM (1ULL<<42) +#define MG_SEED_KEPT (1ULL<<43) + +#define MG_MAX_SEG 255 +#define MG_SEED_SEG_SHIFT 48 +#define MG_SEED_SEG_MASK (0xffULL<<(MG_SEED_SEG_SHIFT)) +#define mg_seg_id(a) ((int32_t)(((a).y&MG_SEED_SEG_MASK) >> MG_SEED_SEG_SHIFT)) + +#define MG_SEED_WT_SHIFT 56 +#define MG_MAX_SHORT_K 15 + +#define MG_SHORT_K_EXT 10000 ///1000 in minigraph + +#define GC_OFFSET_RATE 0.0001 +#define GC_OFFSET_POS 8 + +#define SEC_LEN_DIF 0.03 +#define REA_ALIGN_CUTOFF 32 +#define CHUNK_SIZE 1000000000 + +#define GBIN_K 31 +#define GBIN_W 31 +#define GBIN_E 0.04 +#define GBIN_BE 0.005 +#define GBIN_ME 4 +///GBIN_L -> for the length of one HiFi read +// #define GBIN_L 15000 +#define GBIN_L 256 + +#define FREE_BATCH 16 + +#define generic_key(x) (x) +KRADIX_SORT_INIT(gfa64, uint64_t, generic_key, 8) + +#define generic_key(x) (x) +KRADIX_SORT_INIT(gfa64i, int64_t, generic_key, 8) + +#define ul_ov_srt_qe_key(p) ((p).qe) +KRADIX_SORT_INIT(ul_ov_srt_qe, ul_ov_t, ul_ov_srt_qe_key, member_size(ul_ov_t, qe)) + +#define ul_ov_srt_qs_key(p) ((p).qs) +KRADIX_SORT_INIT(ul_ov_srt_qs, ul_ov_t, ul_ov_srt_qs_key, member_size(ul_ov_t, qs)) + +#define ul_ov_srt_tn_key(p) ((p).tn) +KRADIX_SORT_INIT(ul_ov_srt_tn, ul_ov_t, ul_ov_srt_tn_key, member_size(ul_ov_t, tn)) + +#define ul_ov_srt_qn_key(p) ((p).qn) +KRADIX_SORT_INIT(ul_ov_srt_qn, ul_ov_t, ul_ov_srt_qn_key, member_size(ul_ov_t, qn)) + +#define utg_ct_t_x_key(p) ((p).x) +KRADIX_SORT_INIT(utg_ct_t_x_srt, utg_ct_t, utg_ct_t_x_key, member_size(utg_ct_t, x)) + +#define utg_ct_t_s_key(p) ((p).s) +KRADIX_SORT_INIT(utg_ct_t_s_srt, utg_ct_t, utg_ct_t_s_key, member_size(utg_ct_t, s)) + +#define hap_ev_cov_key(x) ((x).cov) +KRADIX_SORT_INIT(hap_ev_cov_srt, haplotype_evdience, hap_ev_cov_key, member_size(haplotype_evdience, cov)) + +#define uc_block_t_qe_key(x) ((x).qe) +KRADIX_SORT_INIT(uc_block_t_qe_srt, uc_block_t, uc_block_t_qe_key, member_size(uc_block_t, qe)); + +#define uc_block_t_qs_key(x) ((x).qs) +KRADIX_SORT_INIT(uc_block_t_qs_srt, uc_block_t, uc_block_t_qs_key, member_size(uc_block_t, qs)); + +#define hpc_ss_t_s_key(p) ((p).s) +KRADIX_SORT_INIT(hpc_ss_t_s, hpc_ss_t, hpc_ss_t_s_key, member_size(hpc_ss_t, s)) + +typedef struct { + char *a; + size_t n, m; +}mul_buf_t; + +typedef struct { + mul_buf_t *a; + size_t n, m; +}mul_debug_prt_t; + +mul_debug_prt_t *init_mul_debug_prt_t(uint64_t n) +{ + mul_debug_prt_t *p; CALLOC(p, 1); + CALLOC(p->a, n); p->n = p->m = n; + return p; +} + +void print_mul_debug_prt_t(const char *nn, mul_debug_prt_t *p) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+70); + sprintf(gfa_name, "%s.ul.vlog", nn); + FILE* fp = fopen(gfa_name, "w"); free(gfa_name); + if (!fp) return; + uint32_t k; + for (k = 0; k < p->n; k++) { + if(p->a[k].n) { + kv_push(char, p->a[k], '\0'); + fprintf(fp, "%s", p->a[k].a); + } + } + fclose(fp); +} + +void print_raw_uls_seq_direct(const ma_ug_t *ug, all_ul_t *aln, const char *nn) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(nn)+70); + sprintf(gfa_name, "%s.init.raw.integer.seq.log", nn); + FILE* fp = fopen(gfa_name, "w"); free(gfa_name); + if (!fp) return; + uint64_t id; uc_block_t *a = NULL; int64_t k, a_n; + for (id = 0; id < aln->n; id++) { + a = aln->a[id].bb.a; a_n = aln->a[id].bb.n; k = 0; + if(a_n == 0) continue; + fprintf(fp,"%.*s\tid::%lu\t", (int32_t)aln->nid.a[id].n, aln->nid.a[id].a, id); + // for (k = 0; k < a_n && ug_occ_w(a[k].ts, a[k].te, &(ug->u.a[a[k].hid])) == 0; k++); + for (; k < a_n; k++) { + // if(ug_occ_w(a[k].ts, a[k].te, &(ug->u.a[a[k].hid])) == 0) break; + fprintf(fp, "utg%.6d%c(%c)\t", a[k].hid + 1, "lc"[ug->u.a[a[k].hid].circ], "+-"[a[k].rev]); + } + fprintf(fp,"\n"); + } + fclose(fp); +} + +void push_vlog(mul_buf_t *o, char *str) +{ + uint32_t str_l = strlen(str); + kv_resize(char, *o, str_l+o->n); + memcpy(o->a+o->n, str, str_l); o->n += str_l; +} + +// mul_debug_prt_t *overall_zdbg; + +mg_tbuf_t *mg_tbuf_init(void) +{ + mg_tbuf_t *b; + b = (mg_tbuf_t*)calloc(1, sizeof(mg_tbuf_t)); + b->km = km_init(); + return b; +} + +void mg_tbuf_destroy(mg_tbuf_t *b) +{ + if (b == 0) return; + if (b->km) km_destroy(b->km); + free(b); +} + +void *mg_tbuf_get_km(mg_tbuf_t *b) +{ + return b->km; +} + +typedef struct { + uint32_t v, d; + int32_t pre; +} mg_pathv_t; + +typedef struct { + int32_t qs, qe, rs, re; + uint32_t v; +} mg_coor_t; + +///mg128_t->y: weight(8)seg_id(8)flag(8)span(8)pos(32) +///mg128_t->x: rid(31)rev(1)pos(33); keep reference +typedef struct { uint64_t x, y; } mg128_t; +#define sort_key_128x(a) ((a).x) +KRADIX_SORT_INIT(128x, mg128_t, sort_key_128x, 8) +void radix_sort_128x(mg128_t *beg, mg128_t *end); + +#define mg_pathv_t_v_srt_key(x) ((x).v) +KRADIX_SORT_INIT(mg_pathv_t_v_srt, mg_pathv_t, mg_pathv_t_v_srt_key, member_size(mg_pathv_t, v)) +#define mg_pathv_t_d_srt_key(x) ((x).d) +KRADIX_SORT_INIT(mg_pathv_t_d_srt, mg_pathv_t, mg_pathv_t_d_srt_key, member_size(mg_pathv_t, d)) + + +typedef struct { // global data structure for kt_pipeline() + const void *ha_flt_tab; + const ha_pt_t *ha_idx; + const mg_idxopt_t *opt; + const ma_ug_t *ug; + const asg_t *rg; + const ug_opt_t *uopt; + const ul_idx_t *uu; + idx_emask_t *mm; + ucr_file_t *ucr_s; + kseq_t *ks; + int64_t chunk_size; + uint64_t n_thread; + uint64_t total_base; + uint64_t total_pair; + mg_gres_a hits; + mg_dbn_t nn; + uint64_t num_bases, num_corrected_bases, num_recorrected_bases; +} uldat_t; + +typedef struct { + uint64_t asm_size; + uint64_t asm_cov; +} mul_ov_t; + +///three levels: +///level-0: minimizers +///level-1: linear chains +///level-2: g chains +///gc[] saves the idx in lc[], lc saves the idx in a[] +typedef struct { + void *km; + int32_t n_gc, n_lc, n_a, rep_len; + mg_gchain_t *gc;///g_chain; idx in l_chains + mg_llchain_t *lc;///l_chain + mg128_t *a; // minimizer positions; see comments above mg_update_anchors() for details + uint64_t qid, qlen; +} mg_gchains_t; + +typedef struct { + uint32_t n; ///length of candidate list + uint64_t q_span:31, rev:1, q_pos:32; + uint32_t qid:16, weight:15, is_tandem:1; + const ha_idxposl_t *cr; ///candidate list +} mg_match_t; + +typedef struct { + uint64_t qse, rse, gld; +} lc_srt_t; + +#define lc_srt_key(p) ((p).qse) +KRADIX_SORT_INIT(lc_srt, lc_srt_t, lc_srt_key, member_size(lc_srt_t, qse)) + +typedef struct { + uint64_t x, e; + int32_t d; + uint32_t id; +} eg_srt_t; + +#define eg_srt_x_key(p) ((p).x) +KRADIX_SORT_INIT(eg_srt_x, eg_srt_t, eg_srt_x_key, member_size(eg_srt_t, x)) +#define eg_srt_d_key(p) ((p).d) +KRADIX_SORT_INIT(eg_srt_d, eg_srt_t, eg_srt_d_key, member_size(eg_srt_t, d)) + +// shortest path +typedef struct { + // input + ///(lj_ref_id)|(lj_ref_rev^1) + uint32_t v; + ///target_dist should like the overlap length in string graph + ///it should be used to evaluate if the identified path is close to real path/alignment + int32_t target_dist; + uint32_t target_hash; + ///inner: if li and lj are at the same ref id + ///meta: j + uint32_t meta:30, check_hash:1, inner:1; + /** + * There are two cases: + * (1) lj->qs************lj->qe + * li->qs************li->qe + * (2) lj->qs************lj->qe + * li->qs************li->qe + * qlen = li->qs - lj->qe;///might be negative + * **/ + int32_t qlen/**, so**/; + // output + uint32_t n_path:31, is_0:1;///I guess n_path is how many path from src to dest + int32_t path_end;///looks like an idx to alignment + int32_t dist, mlen; + uint32_t hash; + // aux + uint64_t srt_key; +} mg_path_dst_t; + +typedef struct { + uint32_t srt; + int32_t i; +} gc_frag_t; + +///I think this structure is just used for iteration +///iterate each ref id, instead of alignment id +typedef struct sp_node_s { + uint64_t di; // dist<<32 | node_id in avl tree(doesn't matter too much) + uint32_t v;///ref_id|rev + int32_t pre; + uint32_t hash;///hash is path hash, instead of node hash + int32_t is_0; + KAVL_HEAD(struct sp_node_s) head; +} sp_node_t, *sp_node_p; + +typedef struct { + int32_t k, mlen;//k: number of walks from src to this node + int32_t qs, qe; + sp_node_t *p[MG_MAX_SHORT_K]; // this forms a max-heap +} sp_topk_t; + +#define gc_frag_key(p) ((p).srt) +KRADIX_SORT_INIT(gc, gc_frag_t, gc_frag_key, 4) + +#define dst_key(p) ((p).srt_key) +KRADIX_SORT_INIT(dst, mg_path_dst_t, dst_key, 8) + +#define sp_node_cmp(a, b) (((a)->di > (b)->di) - ((a)->di < (b)->di)) +KAVL_INIT(sp, sp_node_t, head, sp_node_cmp) + +#define sp_node_lt(a, b) ((a)->di < (b)->di) +KSORT_INIT(sp, sp_node_p, sp_node_lt) + +KHASH_MAP_INIT_INT(sp, sp_topk_t) +KHASH_MAP_INIT_INT(sp2, uint64_t) + +typedef struct { + kv_ul_ov_t lo; + kv_ul_ov_t tk; + kv_rtrace_t tc; + kvec_t_u64_warp srt; +}glchain_t; + +typedef struct { + mg_path_dst_t *a; + size_t n, m; +}vec_mg_path_dst_t; + +typedef struct { + sp_node_t **a; + size_t n, m; +}vec_sp_node_t; + +typedef struct { + mg_pathv_t *a; + size_t n, m; +}vec_mg_pathv_t; + +typedef struct { + vec_mg_lchain_t l; + vec_mg_lchain_t swap; + vec_mg_path_dst_t dst; + vec_sp_node_t out; + vec_mg_pathv_t path; + kvec_t(uint64_t) v; + kvec_t(int64_t) f; + st_mt_t dst_done; +}gdpchain_t; + +typedef struct { // data structure for each step in kt_pipeline() + const mg_idxopt_t *opt; + const void *ha_flt_tab; + const ha_pt_t *ha_idx; + const ma_ug_t *ug; + const asg_t *rg; + const ug_opt_t *uopt; + const ul_idx_t *uu; + int n, m, sum_len; + uint64_t *len, id; + char **seq; + ha_mzl_v *mzs;///useless + st_mt_t *sps;///useless + mg_gchains_t **gcs;///useless + mg_tbuf_t **buf;///useless + ha_ovec_buf_t **hab; + glchain_t *ll; + gdpchain_t *gdp; + mask_ul_ov_t *mk; + idx_emask_t *mm; + // glchain_t *sec_ll; + uint64_t num_bases, num_corrected_bases, num_recorrected_bases; + int64_t n_thread; + scaf_res_t *rsc; +} utepdat_t; + +typedef struct { // global data structure for kt_pipeline() + utepdat_t *s; + ma_ug_t *qry; + scaf_res_t *qry_sc; + ma_ug_t *ref; + scaf_res_t *ref_sc; + ma_ug_t *gfa; + bubble_type *bub; + kv_u_trans_t *ta; + uint64_t mm; + uint64_t soff; + uint64_t is_exact; +} ctdat_t; + + +#define ha_mzl_t_key(p) ((p).x) +KRADIX_SORT_INIT(ha_mzl_t_srt, ha_mzl_t, ha_mzl_t_key, member_size(ha_mzl_t, x)) + +typedef struct { // global data structure for kt_pipeline() + ug_opt_t *uopt; + ma_ug_t *ug; + asg_t *rg; + ha_ovec_buf_t **hab; + glchain_t *ll; + bubble_type *bub; + int32_t w, k; + ///base-alignment + double bw_thres, diff_ec_ul, sec_cutoff; + double bw_thres_double, diff_ec_ul_double; + int32_t max_n_chain; + ha_mzl_v idx_a; + asg64_v idx_n; + ha_mzl_v srt_a; + int32_t is_HPC, bw, max_gap, chn_pen_gap, n_thread, is_cnt, is_ovlp, mini_cut, chain_cut, keep_unsymm_arc; + ul_idx_t udb; + kv_u_trans_t *filter; + uint32_t *free_cnt; + ug_rid_cov_t *ccov; +} ug_trans_t; + +typedef struct { // global data structure for kt_pipeline() + const ug_opt_t *uopt; + ma_ug_t *ug; + asg_t *rg; + ha_ovec_buf_t **hab; + glchain_t *ll; + int32_t w, k; + ///base-alignment + double bw_thres, diff_ov, diff_bin; + uint64_t min_bin_len, max_diff; + int32_t max_n_chain; + ha_mzl_v idx_a; + asg64_v idx_n; + ha_mzl_v srt_a; + int32_t is_HPC, bw, max_gap, chn_pen_gap, n_thread, is_cnt, is_ovlp, mini_cut, chain_cut, keep_unsymm_arc; + ul_idx_t udb; + // hpc_re_t *hre; + mask_ul_ov_t *mk; + idx_emask_t *mm; + // bit_mask_t *bm; +} ug_bin_t; + + +void hc_glchain_destroy(glchain_t *b) +{ + if (!b) return; + kv_destroy(b->lo); kv_destroy(b->tk); kv_destroy(b->srt.a); kv_destroy(b->tc); +} + + +void hc_gdpchain_destroy(gdpchain_t *b) +{ + if (!b) return; + kv_destroy(b->l); kv_destroy(b->swap); kv_destroy(b->dst); kv_destroy(b->out); + kv_destroy(b->path); kv_destroy(b->v); kv_destroy(b->f); kv_destroy(b->dst_done); +} + +void init_mg_opt(mg_idxopt_t *opt, int is_HPC, int k, int w, int hap_n, int max_n_chain, double bw_thres, +double diff_ec_ul, double diff_ec_ul_low, double diff_ec_ul_hpc, int ec_ul_round) +{ + opt->k = k; + opt->w = w; + opt->hap_n = hap_n; + opt->is_HPC = is_HPC; + opt->bw = 10000;///2000 in minigraph + opt->max_gap = 500000;///5000 in minigraph + opt->occ_weight = 20; + opt->max_gap_pre = 10000;///1000 in minigraph + opt->max_lc_iter = 10000; + opt->chn_pen_gap = 0.19;///using minimap2's value + opt->max_lc_skip = 25;// mo->max_gc_skip = 25; + opt->max_lc_iter = 10000; + opt->min_lc_cnt = 2; + opt->min_lc_score = 30; + opt->max_gc_skip = 25; + opt->ref_bonus = 0; + opt->mask_level = 0.5f; + opt->max_gc_seq_ext = 5; + opt->seed = 11; + opt->min_gc_cnt = 3, opt->min_gc_score = 50; + opt->sub_diff = 6; + opt->best_n = 5; + opt->pri_ratio = 0.8f; + opt->max_n_chain = max_n_chain; + opt->bw_thres = bw_thres; + opt->diff_ec_ul = diff_ec_ul; + opt->diff_ec_ul_low = diff_ec_ul_low; + opt->diff_ec_ul_hpc = diff_ec_ul_hpc; + opt->ec_ul_round = ec_ul_round; +} + +void uidx_l_build(ma_ug_t *ug, mg_idxopt_t *opt, int cutoff) +{ + ha_flt_tab = ha_ft_ul_gen(&asm_opt, &(ug->u), opt->k, opt->w, cutoff); + ha_idx = ha_pt_ul_gen(&asm_opt, ha_flt_tab, &(ug->u), opt->k, opt->w, cutoff); + fprintf(stderr, "[M::%s] Index has been built.\n", __func__); +} + +void uidx_build(ma_ug_t *ug, mg_idxopt_t *opt) +{ + int flag = asm_opt.flag; + asm_opt.flag |= HA_F_NO_HPC; + ha_flt_tab = ha_ft_ug_gen(&asm_opt, &(ug->u), opt->is_HPC, opt->k, opt->w, 1, opt->hap_n*5); + ha_idx = ha_pt_ug_gen(&asm_opt, ha_flt_tab, &(ug->u), opt->is_HPC, opt->k, opt->w, 1); + asm_opt.flag = flag; + fprintf(stderr, "[M::%s] Index has been built.\n", __func__); +} + +void uidx_destory() +{ + ha_ft_destroy(ha_flt_tab); + ha_pt_destroy(ha_idx); + ha_flt_tab = NULL; ha_idx = NULL; +} + +void mg_gres_a_des(mg_gres_a *p) +{ + uint64_t i = 0; + for (i = 0; i < p->n; i++){ + free(p->a[i].lc); free(p->a[i].gc); + } + free(p->a); +} + +///only use non-repetitive minimizers +static mg_match_t *collect_matches(void *km, int *_n_m, int max_occ, const void *ha_flt_tab, const ha_pt_t *ha_idx, int check_unique, const ha_mzl_v *mv, int64_t *n_a, int *rep_len, int *n_mini_pos, int32_t **mini_pos) +{ + int rep_st = 0, rep_en = 0, n_m, tn, tw; + size_t i; + mg_match_t *m; + *n_mini_pos = 0; + KMALLOC(km, *mini_pos, mv->n);///mv->n how many minimizers in query + m = (mg_match_t*)kmalloc(km, mv->n * sizeof(mg_match_t)); + for (i = 0, n_m = 0, *rep_len = 0, *n_a = 0; i < mv->n; ++i) { + const ha_idxposl_t *cr; + ha_mzl_t *z = &mv->a[i]; + cr = ha_ptl_get(ha_idx, z->x, &tn); + tw = ha_ft_cnt(ha_flt_tab, z->x); + if ((tw > max_occ) || (check_unique && tw != 1)) { ///the frequency of repetitive regions; ignore those minimizers + int en = z->pos + 1, st = en - z->span;//[st, en) + if (st > rep_en) { ///just record the length of repetive regions + *rep_len += rep_en - rep_st; + rep_st = st, rep_en = en; + } else rep_en = en; + } else { + mg_match_t *q = &m[n_m++]; + q->q_pos = z->pos, q->q_span = z->span, q->rev = z->rev, q->cr = cr, q->n = tn, q->qid = 0; + q->is_tandem = 0, q->weight = 255; + if(check_unique && tw != 1) q->is_tandem = 1, q->weight = 1; + *n_a += q->n;///how many candidates + (*mini_pos)[(*n_mini_pos)++] = z->pos;///minimizer offset in query + } + } + *rep_len += rep_en - rep_st; ///the length of repetitive regions + *_n_m = n_m; + return m; +} + +mg128_t *collect_seed_hits(void *km, const mg_idxopt_t *opt, int max_occ, const void *ha_flt_tab, const ha_pt_t *ha_idx, +const ma_ug_t *ug, const ha_mzl_v *mv, int64_t *n_a, int *rep_len, int *n_mini_pos, int32_t **mini_pos) +{ + int i, n_m; + mg128_t *a = NULL; + mg_match_t *m = collect_matches(km, &n_m, max_occ, ha_flt_tab, ha_idx, 1, mv, n_a, rep_len, n_mini_pos, mini_pos); + a = (mg128_t*)kmalloc(km, *n_a * sizeof(mg128_t));///n_a: how many available candidates in total + for (i = 0, *n_a = 0; i < n_m; ++i) {///n_m: how many available seeds, instead of candidates + mg_match_t *q = &m[i]; + const ha_idxposl_t *r = q->cr; + uint32_t k; + for (k = 0; k < q->n; ++k) {///q->n: number of candidates belonging to seed m[i] + mg128_t *p; + p = &a[(*n_a)++];///pick up a slot for one candidate + if (r[k].rev == q->rev) // forward strand + p->x = (uint64_t)(r[k].rid)<<33|r[k].pos; ///reference: rid(31)|rev(1)|pos(32) + else // reverse strand + p->x = (uint64_t)(r[k].rid)<<33 | 1ULL<<32 | (ug->g->seq[r[k].rid].len - (r[k].pos + 1 - r[k].span) - 1); + p->y = (uint64_t)q->q_span << 32 | q->q_pos; + p->y |= (uint64_t)q->qid << MG_SEED_SEG_SHIFT; + if (q->is_tandem) p->y |= MG_SEED_TANDEM; + p->y |= (uint64_t)q->weight << MG_SEED_WT_SHIFT; + ///p->y: weight(8)seg_id(8)flag(8)span(8)pos(32) + ///p->x: rid(31)rev(1)pos(33); keep reference + } + } + kfree(km, m); + radix_sort_128x(a, a + (*n_a)); + return a; +} + +///r is 1000 in default +///remove isolated hits, whic are not close enough to others +int64_t flt_anchors(int64_t n_a, mg128_t *a, int32_t r) +{ + int64_t i, j; + for (i = 0; i < n_a; ++i) { + for (j = i - 1; j >= 0; --j) { + /** + * a is sorted by x + * a[].x: ref_id(31)rev(1)r_pos(32) + * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) + **/ + int32_t dq; + int64_t dr = a[i].x - a[j].x;///a is sorted by x + if (dr > r) break;///if two candidates coming from differnt unitigs, dr would be extremly large + dq = (int32_t)a[i].y - (int32_t)a[j].y; + if (dq > r || dq < 0) continue; + a[j].y |= MG_SEED_KEPT; + a[i].y |= MG_SEED_KEPT; + break; + } + } + for (i = n_a - 1; i >= 0; --i) { + if (a[i].y & MG_SEED_KEPT) continue; + for (j = i + 1; j < n_a; ++j) { + int32_t dq; + int64_t dr = a[j].x - a[i].x; + if (dr > r) break; + dq = (int32_t)a[j].y - (int32_t)a[i].y; + if (dq > r || dq < 0) continue; + a[j].y |= MG_SEED_KEPT; + a[i].y |= MG_SEED_KEPT; + break; + } + } + for (i = j = 0; i < n_a; ++i) + if (a[i].y & MG_SEED_KEPT) + a[j++] = a[i]; + return j; +} + +static inline float mg_log2(float x) // NB: this doesn't work when x<2 +{ + union { float f; uint32_t i; } z = { x }; + float log_2 = ((z.i >> 23) & 255) - 128; + z.i &= ~(255 << 23); + z.i += 127 << 23; + log_2 += (-0.34484843f * z.f + 2.02466578f) * z.f - 0.67487759f; + return log_2; +} + +inline int32_t normal_sc(uint64_t w, int32_t sc) +{ + if(w < 255){ + int32_t tmp = (int)(0.00392156862745098 * w * sc); // 0.00392... = 1/255 + sc = tmp > 1? tmp : 1; + } + return sc; +} +// ai[].x: ref_id(31)rev(1)r_pos(32) +// ai[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) +// comput_sc(&a[i], &a[j], max_dist_x, max_dist_y, bw, chn_pen_gap, chn_pen_skip, is_cdna, n_segs); +static inline int32_t comput_sc(const mg128_t *ai, const mg128_t *aj, int32_t max_dist_x, int32_t max_dist_y, int32_t bw, float chn_pen_gap) +{ + int32_t dq = (int32_t)ai->y - (int32_t)aj->y, dr = (int32_t)ai->x - (int32_t)aj->x, dd, dg, q_span, sc; + ///ai and aj has already been sorted by x + ///which means ai->x >= aj->x + if (dq <= 0 || dq > max_dist_x) return INT32_MIN; + if (dr <= 0 || dr > max_dist_y) return INT32_MIN; + dd = dr > dq? dr - dq : dq - dr; ///indel, dd is always >= 0 + if (dd > bw) return INT32_MIN; + dg = dr < dq? dr : dq;///MIN(dr, dq) + q_span = aj->y>>32&0xff;///query span; should be ai->y>>32&0xff, is it a bug? + sc = normal_sc(aj->y>>MG_SEED_WT_SHIFT, (q_span q_span: there are some bases that are not covered between ai and aj + ///it is if (dd || dg > q_span) in minigraph + if (dd) { + float lin_pen, log_pen; + lin_pen = chn_pen_gap * (float)dd; + log_pen = dd >= 2? mg_log2(dd) : 0.0f; // mg_log2() only works for dd>=2 + sc -= (int)(lin_pen + log_pen); + } + return sc; +} + + +///p[]: id of last +///f[]: the score ending at i, not always the peak +///v[]: keeps the peak score up to i; +///t[]: used for buffer +///min_cnt = 2; min_sc = 30; extra_u = 0 +///u = mg_chain_backtrack(n, f, p, v, t, min_cnt, min_sc, 0, &n_u, &n_v); +uint64_t *mg_chain_backtrack(void *km, int64_t n, const int32_t *f, const int64_t *p, int32_t *v, int32_t *t, int32_t min_cnt, int32_t min_sc, int32_t extra_u, int32_t *n_u_, int32_t *n_v_) +{ + mg128_t *z; + uint64_t *u; + int64_t i, k, n_z, n_v; + int32_t n_u; + // v[] keeps the peak score up to i; f[] is the score ending at i, not always the peak + *n_u_ = *n_v_ = 0; + for (i = 0, n_z = 0; i < n; ++i) // precompute n_z + if (f[i] >= min_sc) ++n_z; + if (n_z == 0) return 0; + KMALLOC(km, z, n_z); + for (i = 0, k = 0; i < n; ++i) // populate z[] + if (f[i] >= min_sc) z[k].x = f[i], z[k++].y = i; + radix_sort_128x(z, z + n_z);///sort by score + + memset(t, 0, n * 4);///t is a buffer + ///from the largest to the smallest + for (k = n_z - 1, n_v = n_u = 0; k >= 0; --k) { // precompute n_u + int64_t n_v0 = n_v; + int32_t sc; + ///note t[i] == 0 is not used to find local alignment + ///say if we have already found a long chain, then the secondary might be able to merged to the long chain + ///t[i] == 0 is used to find those chains + for (i = z[k].y; i >= 0 && t[i] == 0; i = p[i]) + ++n_v, t[i] = 1; + sc = i < 0? z[k].x : (int32_t)z[k].x - f[i]; + if (sc >= min_sc && n_v > n_v0 && n_v - n_v0 >= min_cnt) + ++n_u;///how many chains, including primary chains and non-primary chains + else n_v = n_v0; + } + KMALLOC(km, u, n_u + extra_u); + memset(t, 0, n * 4); + for (k = n_z - 1, n_v = n_u = 0; k >= 0; --k) { // populate u[] + int64_t n_v0 = n_v; + int32_t sc; + for (i = z[k].y; i >= 0 && t[i] == 0; i = p[i]) + v[n_v++] = i, t[i] = 1; + sc = i < 0? z[k].x : (int32_t)z[k].x - f[i]; + if (sc >= min_sc && n_v > n_v0 && n_v - n_v0 >= min_cnt) + u[n_u++] = (uint64_t)sc << 32 | (n_v - n_v0); + else n_v = n_v0; + } + kfree(km, z); + assert(n_v < INT32_MAX); + *n_u_ = n_u, *n_v_ = n_v; + return u; +} + +//u[]: sc|occ of chains +//v[]: idx of each element +static mg128_t *compact_a(void *km, int32_t n_u, uint64_t *u, int32_t n_v, int32_t *v, mg128_t *a) +{ + mg128_t *b, *w; + uint64_t *u2; + int64_t i, j, k; + + // write the result to b[] + KMALLOC(km, b, n_v); + for (i = 0, k = 0; i < n_u; ++i) { + int32_t k0 = k, ni = (int32_t)u[i]; + for (j = 0; j < ni; ++j) + b[k++] = a[v[k0 + (ni - j - 1)]];///write all elements of a chain together + } + kfree(km, v); + + // sort u[] and a[] by the target position, such that adjacent chains may be joined + KMALLOC(km, w, n_u); + for (i = k = 0; i < n_u; ++i) {///n_u: how many chains + ///x: ref_id(31)rev(1)r_pos(32) + w[i].x = b[k].x, w[i].y = (uint64_t)k<<32|i; + k += (int32_t)u[i]; + } + radix_sort_128x(w, w + n_u);///sort by ref_id(31)rev(1)r_pos(32); r_pos is the start pos of chain + KMALLOC(km, u2, n_u); + for (i = k = 0; i < n_u; ++i) {///note merge chain; just place close chains together + ///j is chain id; n is how many elements in j-th chain + int32_t j = (int32_t)w[i].y, n = (int32_t)u[j]; + u2[i] = u[j]; + memcpy(&a[k], &b[w[i].y>>32], n * sizeof(mg128_t)); + k += n; + } + memcpy(u, u2, n_u * 8); + memcpy(b, a, k * sizeof(mg128_t)); // write _a_ to _b_ and deallocate _a_ because _a_ is oversized, sometimes a lot + kfree(km, a); kfree(km, w); kfree(km, u2); + return b; +} + +/* Input: + * a[].x: ref_id(31)rev(1)r_pos(32) + * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) + * n: length of a[] + * Output: + * n_u: #chains + * u[]: score<<32 | #anchors (sum of lower 32 bits of u[] is the returned length of a[]) + * input a[] is deallocated on return + */ +///is_cdna is is_splice +mg128_t *mg_lchain_dp(int max_dist_x, int max_dist_y, int bw, int max_skip, int max_iter, int min_cnt, int min_sc, float chn_pen_gap, + int64_t n, mg128_t *a, int *n_u_, uint64_t **_u, void *km) +{ // TODO: make sure this works when n has more than 32 bits + int32_t *f, *t, *v, n_u, n_v; + int64_t *p, i, j, max_ii, st = 0; + uint64_t *u; + + if (_u) *_u = 0, *n_u_ = 0; + if (n == 0 || a == 0) return 0; + KMALLOC(km, p, n);///id of last cell + KMALLOC(km, f, n);///f[] is the score ending at i, not always the peak + KMALLOC(km, v, n);///v[] keeps the peak score up to i; + KCALLOC(km, t, n);///t doesn't matter too much; it is mainly used to accelrate the iteration + + // a[].x: ref_id(31)rev(1)r_pos(32) + // a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) + // fill the score and backtrack arrays + for (i = st = 0, max_ii = -1; i < n; ++i) { + int64_t max_j = -1, end_j; + ///max_f -> score of minimizer + int32_t max_f = normal_sc(a[i].y>>MG_SEED_WT_SHIFT, a[i].y>>32&0xff), n_skip = 0; + ///until we are at the same rid, same direction, and the coordinates are close enough + while (st < i && (a[i].x>>32 != a[st].x>>32 || a[i].x > a[st].x + max_dist_x)) ++st; + ///max_iter = 10000 in default, which means dp can go back to up to 10000 cells + if (i - st > max_iter) st = i - max_iter; + for (j = i - 1; j >= st; --j) { + int32_t sc; + sc = comput_sc(&a[i], &a[j], max_dist_x, max_dist_y, bw, chn_pen_gap); + if (sc == INT32_MIN) continue; + sc += f[j]; + if (sc > max_f) { + max_f = sc, max_j = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == (int32_t)i) {///note we scan j backwards; we don't need to update t[] for each i + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i;//p[]: prefix idx; means there is a chain longer than 2 + } + end_j = j;///end_j might be > 0; just the end idx of backwards + ///if not close enough, select a new max + ///max_ii is just used to rescue best-score in case best-score appears before end_j + if (max_ii < 0 || (int64_t)(a[i].x - a[max_ii].x) > (int64_t)max_dist_x) {///select a new max + int32_t max = INT32_MIN; + max_ii = -1; + for (j = i - 1; j >= st; --j) + if (max < f[j]) max = f[j], max_ii = j; + } + ///note: it will happen when `max_ii` < `end_j`; + ///iteration is terminated at `end_j` mostly because of `max_skip` and `max_iter` + ///max_ii is just used to rescue best-score in case best-score appears before end_j + if (max_ii >= 0 && max_ii < end_j) { + int32_t tmp; + tmp = comput_sc(&a[i], &a[max_ii], max_dist_x, max_dist_y, bw, chn_pen_gap); + if (tmp != INT32_MIN && max_f < tmp + f[max_ii]) + max_f = tmp + f[max_ii], max_j = max_ii; + } + // v[] keeps the peak score up to i (as score might decerase); f[] is the score ending at i, not always the peak + f[i] = max_f, p[i] = max_j;//p[]: prefix idx + v[i] = max_j >= 0 && v[max_j] > max_f? v[max_j] : max_f; + if (max_ii < 0 || ((int64_t)(a[i].x - a[max_ii].x) <= (int64_t)max_dist_x && f[max_ii] < f[i])) + max_ii = i; + } + ///after mg_chain_backtrack, the results are saved in u and v; + u = mg_chain_backtrack(km, n, f, p, v, t, min_cnt, min_sc, 0, &n_u, &n_v); + *n_u_ = n_u, *_u = u; // NB: note that u[] may not be sorted by score here + kfree(km, p); kfree(km, f); kfree(km, t); + if (n_u == 0) { + kfree(km, a); kfree(km, v); + return 0; + } + //u[]: sc|occ of chains; chain is mostly sorted by the score; at least the first chain has the largest score + //v[]: idx of each element + return compact_a(km, n_u, u, n_v, v, a); +} + + +void extend_coordinates(mg_lchain_t *ri, int64_t qlen, int64_t rlen) +{ + int64_t qs, qe, rs, re, qtail, rtail; + qs = ri->qs; qe = ri->qe - 1; rs = ri->rs; re = ri->re - 1; + if(ri->v&1) { + rs = rlen - ri->re; re = rlen - ri->rs - 1; + } + + if(qs <= rs) { + rs -= qs; qs = 0; + } else { + qs -= rs; rs = 0; + } + + qtail = qlen - qe - 1; rtail = rlen - re - 1; + if(qtail <= rtail) { + qe = qlen - 1; re += qtail; + } + else + { + re = rlen - 1; qe += rtail; + } + + ri->qs = qs; ri->qe = qe + 1; ri->rs = rs; ri->re = re + 1; + if(ri->v&1) { + ri->rs = rlen - re - 1; ri->re = rlen - rs; + } +} +///qlen: query length +///u[]: sc|occ of chains +///a[]: candidate list +mg_lchain_t *mg_lchain_gen(void *km, int qlen, int n_u, uint64_t *u, mg128_t *a, const ma_ug_t *ug) +{ + mg128_t *z; + mg_lchain_t *r; + int i, k; + + if (n_u == 0) return 0; + KCALLOC(km, r, n_u); KMALLOC(km, z, n_u); + // u[] is sorted by query position + for (i = k = 0; i < n_u; ++i) { + /** + * a[].x: ref_id(31)rev(1)r_pos(32) + * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) + **/ + ///u[]: sc(32)occ(32) + int32_t qs = (int32_t)a[k].y + 1 - (a[k].y>>32 & 0xff); + z[i].x = (uint64_t)qs << 32 | u[i] >> 32; + z[i].y = (uint64_t)k << 32 | (int32_t)u[i]; + k += (int32_t)u[i]; + } + radix_sort_128x(z, z + n_u);//sort by qs|sc + + // populate r[] + for (i = 0; i < n_u; ++i) { + mg_lchain_t *ri = &r[i]; + /** + * z[].x: query start pos| chain score + * z[].y: idx in a[] | chain occ + * a[].x: ref_id(31)rev(1)r_pos(32) + * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) + * **/ + int32_t k = z[i].y >> 32, q_span = a[k].y >> 32 & 0xff; + ri->off = k; + ri->cnt = (int32_t)z[i].y; + ri->score = (uint32_t)z[i].x; + ri->v = a[k].x >> 32;///ref_id|rev + ri->rs = (int32_t)a[k].x + 1 > q_span? (int32_t)a[k].x + 1 - q_span : 0; // for HPC k-mer + ri->qs = z[i].x >> 32; + ri->re = (int32_t)a[k + ri->cnt - 1].x + 1; + ri->qe = (int32_t)a[k + ri->cnt - 1].y + 1; + // fprintf(stderr, "+0+\tA\tutg%.6d%c\t%c\tqs:%u\tqe:%u\tql:%d\tts:%u\tte:%u\ttl:%u\n", + // (ri->v>>1)+1, "lc"[ug->u.a[ri->v>>1].circ], "+-"[ri->v&1], ri->qs, ri->qe, qlen, ri->rs, ri->re, ug->u.a[ri->v>>1].len); + // extend_coordinates(ri, qlen, ug->u.a[ri->v>>1].len); + // fprintf(stderr, "-0-\tA\tutg%.6d%c\t%c\tqs:%u\tqe:%u\tql:%d\tts:%u\tte:%u\ttl:%u\n", + // (ri->v>>1)+1, "lc"[ug->u.a[ri->v>>1].circ], "+-"[ri->v&1], ri->qs, ri->qe, qlen, ri->rs, ri->re, ug->u.a[ri->v>>1].len); + } + kfree(km, z); + return r; +} + +static int32_t get_mini_idx(const mg128_t *a, int32_t n, const int32_t *mini_pos) +{ + int32_t x, L = 0, R = n - 1; + x = (int32_t)a->y; + while (L <= R) { // binary search + int32_t m = ((uint64_t)L + R) >> 1; + int32_t y = mini_pos[m]; + if (y < x) L = m + 1; + else if (y > x) R = m - 1; + else return m; + } + return -1; +} + +/* Before: + * a[].x: ref_id(31)rev(1)r_pos(32) + * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) + * After: + * a[].x: idx_in_minimizer_arr(32)r_pos(32) + * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) + */ +void mg_update_anchors(int32_t n_a, mg128_t *a, int32_t n, const int32_t *mini_pos) +{ + int32_t st, j, k; + if (n_a <= 0) return; + st = get_mini_idx(&a[0], n, mini_pos); + assert(st >= 0); + for (k = 0, j = st; j < n && k < n_a; ++j) + if ((int32_t)a[k].y == mini_pos[j]) + a[k].x = (uint64_t)j << 32 | (a[k].x & 0xffffffffU), ++k; + assert(k == n_a); +} + +static int32_t find_max(int32_t n, const gc_frag_t *gf, uint32_t x) +{ + int32_t s = 0, e = n; + if (n == 0) return -1; + if (gf[n-1].srt < x) return n - 1; + if (gf[0].srt >= x) return -1; + while (e > s) { // TODO: finish this block + int32_t m = s + (e - s) / 2; + if (gf[m].srt >= x) e = m; + else s = m + 1; + } + assert(s == e); + return s; +} +///target_dist should like the overlap length in string graph +///it should be used to evaluate if the identified path is close to real path/alignment +static int32_t mg_target_dist(const asg_t *g, const mg_lchain_t *l0, const mg_lchain_t *l1) +{ + /** + case 1: l0->qs************l0->qe + l1->qs************l1->qe + case 2: l0->qs************l0->qe + l1->qs************l1->qe + + *****l0->rs************l0->re***** + ****l1->rs************l1->re** + * **/ + ///min_dist = l1->rs + (g->seg[l0->v>>1].len - l0->re); + // below equals (l1->qs - l0->qe) - min_dist + g->seg[l1->v>>1].len; see mg_gchain1_dp() for the calculation of min_dist + //(l1->qs - l0->qe) is the gap in query, min_dist is the gap in reference + return (l1->qs - l0->qe) - (g->seq[l0->v>>1].len - l0->re) + (g->seq[l1->v>>1].len - l1->rs); + // when l0->v == l1->v, the above becomes (l1->qs - l0->qe) - (l1->rs - l0->re), which is what we want +} + +static inline sp_node_t *gen_sp_node(void *km, uint32_t v, int32_t d, int32_t id) +{ + sp_node_t *p; + KMALLOC(km, p, 1); + p->v = v, p->di = (uint64_t)d<<32 | id, p->pre = -1, p->is_0 = 1; + return p; +} + +///max_dist is like the overlap length in string graph +///the end position of qs is li->qs; dst[]->->qlen indicate the region that need to be checked in bases +mg_pathv_t *mg_shortest_k(void *km0, const asg_t *g, uint32_t src, int32_t n_dst, mg_path_dst_t *dst, int32_t max_dist, int32_t max_k, /** //pathint32_t ql, const char *qs, int is_rev, **/int32_t *n_pathv) +{ + sp_node_t *p, *root = 0, **out; + sp_topk_t *q; + khash_t(sp) *h; + khash_t(sp2) *h2; + void *km; + khint_t k; + int absent; + int32_t i, j, n_done, n_found; + uint32_t id, n_out, m_out; + int8_t *dst_done; + mg_pathv_t *ret = 0; + uint64_t *dst_group; + /** //path + int32_t n_seeds = 0; + uint64_t *seeds = 0; + void *h_seeds = 0; + mg128_v mini = {0,0,0}; + **/ + + if (n_pathv) *n_pathv = 0;///for us, n_pathv = NULL + if (n_dst <= 0) return 0;///n_dst: how many candidate nodes + for (i = 0; i < n_dst; ++i) { // initialize + mg_path_dst_t *t = &dst[i]; + ///if src and dest are at the same ref id, there are already one path + if (t->inner)///if two chains are at the same ref id + t->dist = 0, t->n_path = 1, t->path_end = -1; + else + t->dist = -1, t->n_path = 0, t->path_end = -1; + } + if (max_k > MG_MAX_SHORT_K) max_k = MG_MAX_SHORT_K; + km = km_init2(km0, 0x4000); + + /** //path + ///for the first time, we just check th reachability without sequence (qs); + ///but for the second round, we need to check sequence + ///qs is the sequence between two minimizers + if (ql > 0 && qs) { // build the seed hash table for the query + mg_sketch(km, qs, ql, MG_SHORT_KW, MG_SHORT_KK, 0, &mini); + // mini->a[].x = hash_key<<8 | kmerSpan + // mini->a[].y = rid<<32 | lastPos<<1 | strand + if (is_rev)///is_rev = 1; + for (i = 0; i < mini.n; ++i)///reverse qs[0, ql) to qs(ql, 0] + mini.a[i].y = (ql - (((int32_t)mini.a[i].y>>1) + 1 - MG_SHORT_KK) - 1) << 1 | ((mini.a[i].y&1)^1); + ///h_seeds is the ordinary hash index + h_seeds = mg_idx_a2h(km, mini.n, mini.a, 0, &seeds, &n_seeds); + ///h_seeds+seeds+n_seeds ----> hash index of qs[0, ql) + } + **/ + ///dst is how many candidates + KCALLOC(km, dst_done, n_dst); + KMALLOC(km, dst_group, n_dst); + // multiple dst[] may have the same dst[].v. We need to group them first. + // in other words, one ref id may have multiple dst alignment chains + for (i = 0; i < n_dst; ++i) + dst_group[i] = (uint64_t)dst[i].v<<32 | i; + radix_sort_gfa64(dst_group, dst_group + n_dst); + + h2 = kh_init2(sp2, km); // (h2+dst_group) keeps all destinations from the same ref id + kh_resize(sp2, h2, n_dst * 2); + ///please note that one contig in ref may have multiple alignment chains + ///so h2 is a index that helps us to query it + ///key(h2) = ref id; value(h2) = start_idx | occ + for (i = 1, j = 0; i <= n_dst; ++i) { + if (i == n_dst || dst_group[i]>>32 != dst_group[j]>>32) { + k = kh_put(sp2, h2, dst_group[j]>>32, &absent); + kh_val(h2, k) = (uint64_t)j << 32 | (i - j); + assert(absent); + j = i; + } + } + + + + h = kh_init2(sp, km); // h keeps visited vertices; path to each visited vertice + kh_resize(sp, h, 16); + + m_out = 16, n_out = 0;///16 is just the initial size + KMALLOC(km, out, m_out); + + /** + typedef struct { + int32_t k, mlen;//k: number of walks from src to this node + int32_t qs, qe; + sp_node_t *p[MG_MAX_SHORT_K]; // this forms a max-heap; all path + } sp_topk_t; + **/ + id = 0; + p = gen_sp_node(km, src, 0, id++);///just malloc a node for src; the distance is 0 + p->hash = __ac_Wang_hash(src);///hash is path hash, instead of node hash + kavl_insert(sp, &root, p, 0);///should be avl tree + ///each src corresponds to one node in the hash table , but corresponds to node in the AVL tree + k = kh_put(sp, h, src, &absent);///here is a hash table + q = &kh_val(h, k); + ///for normal graph traversal, one node just has one parental node; here each node has at most 16 parental nodes + q->k = 1, q->p[0] = p, q->mlen = 0, q->qs = q->qe = -1; + + n_done = 0; + ///the key of avl tree: #define sp_node_cmp(a, b) (((a)->di > (b)->di) - ((a)->di < (b)->di)) + ///the higher bits of (*)->di is distance to src node + ///so the key of avl tree is distance + ///in avl tree , one node might be saved multipe times + while (kavl_size(head, root) > 0) {///thr first root is src + int32_t i, nv; + asg_arc_t *av; + sp_node_t *r; + ///note that one (sp_node_t->v) might be visited multiple times if there are circles + ///so there might be multipe nodes with the same (sp_node_t->v) + ///delete the first node + r = kavl_erase_first(sp, &root); // take out the closest vertex in the heap (as a binary tree) + //fprintf(stderr, "XX\t%d\t%d\t%d\t%c%s[%d]\t%d\n", n_out, kavl_size(head, root), n_finished, "><"[(r->v&1)^1], g->seg[r->v>>1].name, r->v, (int32_t)(r->di>>32)); + if (n_out == m_out) KEXPAND(km, out, m_out); + ///higher 32 bits might be the distance to root node + // lower 32 bits now for position in the out[] array + r->di = r->di>>32<<32 | n_out; ///n_out is just the id in out + ///so one node id in graph might be saved multiple times in avl tree and out[] + out[n_out++] = r;///out[0] = src + + ///r->v is the dst vertex id + ///sometimes k==kh_end(h2). Some nodes are found by graph travesal but not in linear chain alignment + k = kh_get(sp2, h2, r->v); + // we have reached one dst vertex + // note that one dst vertex may have multipe alignment chains + // we can visit some nodes in graph which are not reachable during chaining + // h2 is used to determine if one node is reachable or not + if (k != kh_end(h2)) { + ///node r->v might be visited multiple times + int32_t j, dist = r->di>>32, off = kh_val(h2, k) >> 32, cnt = (int32_t)kh_val(h2, k); + //src can reach ref id r->v; there might be not only one alignment chain in r->v + //so we need to scan all of them + for (j = 0; j < cnt; ++j) { + mg_path_dst_t *t = &dst[(int32_t)dst_group[off + j]];///t is a linear alignment at r->v + int32_t done = 0; + ///the src and dest are at the same ref id, say we directly find the shortest path + if (t->inner) {//usually the first node, which is same to src + done = 1; + } else { + int32_t mlen = 0, copy = 0; + ///in the first round, we just check reachability without sequence + ///so h_seeds = NULL; we can assume mlen = 0 + /** //path + mlen = h_seeds? path_mlen(out, n_out - 1, h, t->qlen) : 0; + **/ + //if (mg_dbg_flag & MG_DBG_GC1) fprintf(stderr, " src=%c%s[%d],qlen=%d\tdst=%c%s[%d]\ttarget_distx=%d,target_hash=%x\tdistx=%d,mlen=%d,hash=%x\n", "><"[src&1], g->seg[src>>1].name, src, ql, "><"[t->v&1], g->seg[t->v>>1].name, t->v, t->target_dist - g->seg[src>>1].len, t->target_hash, dist - g->seg[src>>1].len, mlen, r->hash); + // note: t indicates a linear alignmnet, instead of a node in graph + ///target_dist should be the distance on query + if (t->n_path == 0) { // means this alignment has never been visited before; keep the shortest path anyway + copy = 1; + // we have a target distance; choose the closest; + // there is already several paths reaching the linear alignment + } else if (t->target_dist >= 0) { + // we found the target path; hash is the path hash including multiple nodes, instead of node hash + if (dist == t->target_dist && t->check_hash && r->hash == t->target_hash) { + copy = 1, done = 1; + } else { + int32_t d0 = t->dist, d1 = dist; + d0 = d0 > t->target_dist? d0 - t->target_dist : t->target_dist - d0; + d1 = d1 > t->target_dist? d1 - t->target_dist : t->target_dist - d1; + ///if the new distance (d1) is smaller than the old distance (d0), update the results + ///the length of new path should be closer to t->target_dist + if (d1 - mlen/2 < d0 - t->mlen/2) copy = 1; + } + } + if (copy) { + t->path_end = n_out - 1, t->dist = dist, t->hash = r->hash, t->mlen = mlen, t->is_0 = r->is_0; + if (t->target_dist >= 0) { + ///src is from li from li to lj, so the dis is generally increased; dijkstra algorithm + ///target_dist should be the distance on query + if (dist == t->target_dist && t->check_hash && r->hash == t->target_hash) done = 1; + else if ((dist > t->target_dist + MG_SHORT_K_EXT) && (dist > (t->target_dist>>4))) done = 1; + } + } + ++t->n_path;///we found a path to the alignment t + if (t->n_path >= max_k) done = 1; + } + if (dst_done[off + j] == 0 && done) + dst_done[off + j] = 1, ++n_done; + } + ///if all alignments have been settle down + ///pre-end; accelerate the loop + if (n_done == n_dst) break; + } + + ///below is used to push new nodes to avl tree for iteration + nv = asg_arc_n(g, r->v); + av = asg_arc_a(g, r->v); + for (i = 0; i < nv; ++i) { // visit all neighbors + asg_arc_t *ai = &av[i]; + ///v_lv is the (dest_length - overlap_length); it is a normal path length in string graph + ///ai->v_lv is the path length from r->v to ai->w + ///(r->di>>32) + int32_t d = (r->di>>32) + (uint32_t)ai->ul; + if (d > max_dist) continue; // don't probe vertices too far away + // h keeps visited vertices; path to each visited vertice + ///ai->w is the dest ref id; we insert a new ref id, instead of an alignment chain + k = kh_put(sp, h, ai->v, &absent);///one node might be visited multiple times + q = &kh_val(h, k); + if (absent) { // a new vertex visited + ///q->k: number of walks from src to ai->w + q->k = 0, q->qs = q->qe = -1; q->mlen = 0; + ///h_seeds = NULL; so q->mlen = 0 + /** //path + q->mlen = h_seeds && d + gfa_arc_lw(g, *ai) <= max_dist? node_mlen(km, g, ai->w, &mini, h_seeds, n_seeds, seeds, &q->qs, &q->qe) : 0; + **/ + //if (ql && qs) fprintf(stderr, "ql=%d,src=%d\tv=%c%s[%d],n_seeds=%d,mlen=%d\n", ql, src, "><"[ai->w&1], g->seg[ai->w>>1].name, ai->w, n_seeds, q->mlen); + } + ///if there are less than walks from src to ai->w, directly add + ///if there are more, keep the smallest walks + if (q->k < max_k) { // enough room: add to the heap + p = gen_sp_node(km, ai->v, d, id++); + p->pre = n_out - 1;///the parent node of this one + p->hash = r->hash + __ac_Wang_hash(ai->v); + p->is_0 = r->is_0; + /** //path + if (ai->rank > 0) p->is_0 = 0; + **/ + kavl_insert(sp, &root, p, 0); + q->p[q->k++] = p; + ks_heapup_sp(q->k, q->p);///adjust heap by distance + } else if ((int32_t)(q->p[0]->di>>32) > d) { // shorter than the longest path so far: replace the longest + p = kavl_erase(sp, &root, q->p[0], 0); + if (p) { + p->di = (uint64_t)d<<32 | (id++); + p->pre = n_out - 1; + p->hash = r->hash + __ac_Wang_hash(ai->v); + p->is_0 = r->is_0; + /** //path + if (ai->rank > 0) p->is_0 = 0; + **/ + kavl_insert(sp, &root, p, 0); + ks_heapdown_sp(0, q->k, q->p); + } else { + fprintf(stderr, "Warning: logical bug in gfa_shortest_k(): q->k=%d,q->p[0]->{d,i}={%d,%d},d=%d,src=%u,max_dist=%d,n_dst=%d\n", q->k, (int32_t)(q->p[0]->di>>32), (int32_t)q->p[0]->di, d, src, max_dist, n_dst); + km_destroy(km); + return 0; + } + } // else: the path is longer than all the existing paths ended at ai->w + } + } + + kfree(km, dst_group); + kfree(km, dst_done); + kh_destroy(sp, h); + /** //path + mg_idx_hfree(h_seeds); + kfree(km, seeds); + kfree(km, mini.a); + **/ + // NB: AVL nodes are not deallocated. When km==0, they are memory leaks. + + for (i = 0, n_found = 0; i < n_dst; ++i) + if (dst[i].n_path > 0) ++n_found;///n_path might be larger than 16 + ///we can assume n_pathv = NULL for now + if (n_found > 0 && n_pathv) { // then generate the backtrack array + int32_t n, *trans; + ///n_out: how many times that nodes in graph have been visited + ///note one node might be visited multiples times + KCALLOC(km, trans, n_out); // used to squeeze unused elements in out[] + ///n_dst: number of alignment chains + for (i = 0; i < n_dst; ++i) { // mark dst vertices with a target distance + mg_path_dst_t *t = &dst[i]; + if (t->n_path > 0 && t->target_dist >= 0 && t->path_end >= 0) + trans[(int32_t)out[t->path_end]->di] = 1;///(int32_t)out[]->di: traverse track corresponds to the alignment chain dst[] + } + for (i = 0; (uint32_t)i < n_out; ++i) { // mark dst vertices without a target distance + k = kh_get(sp2, h2, out[i]->v); + if (k != kh_end(h2)) { // TODO: check if this is correct! + int32_t off = kh_val(h2, k)>>32, cnt = (int32_t)kh_val(h2, k); + for (j = off; j < off + cnt; ++j) + if (dst[j].target_dist < 0) + trans[i] = 1; + } + } + for (i = n_out - 1; i >= 0; --i) // mark all predecessors + if (trans[i] && out[i]->pre >= 0) + trans[out[i]->pre] = 1; + for (i = n = 0; (uint32_t)i < n_out; ++i) // generate coordinate translations + if (trans[i]) trans[i] = n++; + else trans[i] = -1; + + *n_pathv = n; + KMALLOC(km0, ret, n); + for (i = 0; (uint32_t)i < n_out; ++i) { // generate the backtrack array + mg_pathv_t *p; + if (trans[i] < 0) continue; + p = &ret[trans[i]]; + p->v = out[i]->v, p->d = out[i]->di >> 32; + p->pre = out[i]->pre < 0? out[i]->pre : trans[out[i]->pre]; + } + for (i = 0; i < n_dst; ++i) // translate "path_end" + if (dst[i].path_end >= 0) + dst[i].path_end = trans[dst[i].path_end]; + } + + km_destroy(km); + return ret; +} + +static inline int32_t cal_sc(const mg_path_dst_t *dj, const mg_lchain_t *li, const mg_lchain_t *lc, const mg128_t *an, const gc_frag_t *a, const int32_t *f, + int bw, int ref_bonus, float chn_pen_gap) +{ + const mg_lchain_t *lj; + int32_t gap, sc; + float lin_pen, log_pen; + if (dj->n_path == 0) return INT32_MIN; + gap = dj->dist - dj->target_dist; + lj = &lc[a[dj->meta].i]; + if (gap < 0) gap = -gap; + if (gap > bw) return INT32_MIN; + if (lj->qe <= li->qs) sc = li->score; + else sc = (int32_t)((double)(li->qe - lj->qe) / (li->qe - li->qs) * li->score + .499); // dealing with overlap on query + //sc += dj->mlen; // TODO: is this line the right thing to do? + if (dj->is_0) sc += ref_bonus; + lin_pen = chn_pen_gap * (float)gap; + log_pen = gap >= 2? mg_log2(gap) : 0.0f; + sc -= (int32_t)(lin_pen + log_pen); + sc += f[dj->meta]; + return sc; +} + +void transfor_icoord(const int64_t iqs, const int64_t iqe, const int64_t irs, const int64_t ire, const uint8_t rev, +const int64_t qlen, const int64_t rlen, int32_t *r_qs, int32_t *r_qe, int32_t *r_rs, int32_t *r_re) +{ + int64_t qs, qe, rs, re, qtail, rtail; + qs = iqs; qe = iqe - 1; rs = irs; re = ire - 1; + if(rev) { + rs = rlen - ire; re = rlen - irs - 1; + } + + if(qs <= rs) { + rs -= qs; qs = 0; + } else { + qs -= rs; rs = 0; + } + + qtail = qlen - qe - 1; rtail = rlen - re - 1; + if(qtail <= rtail) { + qe = qlen - 1; re += qtail; + } + else + { + re = rlen - 1; qe += rtail; + } + + if(r_qs) {(*r_qs) = qs;} if(r_qe) {(*r_qe) = qe + 1;} + if(r_rs) {(*r_rs) = rs;} if(r_re) {(*r_re) = re + 1;} + if(rev) { + if(r_rs) (*r_rs) = rlen - re - 1; + if(r_re) (*r_re) = rlen - rs; + } +} + +void transfor_coord(mg_lchain_t *ri, const int64_t qlen, const int64_t rlen, +int32_t *r_qs, int32_t *r_qe, int32_t *r_rs, int32_t *r_re) +{ + int64_t qs, qe, rs, re, qtail, rtail; + qs = ri->qs; qe = ri->qe - 1; rs = ri->rs; re = ri->re - 1; + if(ri->v&1) { + rs = rlen - ri->re; re = rlen - ri->rs - 1; + } + + if(qs <= rs) { + rs -= qs; qs = 0; + } else { + qs -= rs; rs = 0; + } + + qtail = qlen - qe - 1; rtail = rlen - re - 1; + if(qtail <= rtail) { + qe = qlen - 1; re += qtail; + } + else + { + re = rlen - 1; qe += rtail; + } + + if(r_qs) {(*r_qs) = qs;} if(r_qe) {(*r_qe) = qe + 1;} + if(r_rs) {(*r_rs) = rs;} if(r_re) {(*r_re) = re + 1;} + if(ri->v&1) { + if(r_rs) (*r_rs) = rlen - re - 1; + if(r_re) (*r_re) = rlen - rs; + } +} + +int64_t get_nn_ov(const uint32_t v, const uint32_t w, const asg_t *g) +{ + uint32_t i; + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v), *p = NULL; + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + if(av[i].v == w) { + // o -= av[i].ol; + p = &(av[i]); + break; + } + } + return p?p->ol:0; +} + +int64_t get_lchain_ovlp(mg_lchain_t *lp, mg_lchain_t *la, const asg_t *g, const int64_t qlen, const ma_ug_t *ug) +{ + int64_t o = lp->qe - la->qs, oj; + uint32_t v = la->v^1, w = lp->v^1, i; + int32_t pqe, aqs; + if(o <= 0) return 0; + if(v == w) return o; + transfor_coord(lp, qlen, ug->u.a[lp->v>>1].len, NULL, &pqe, NULL, NULL); + transfor_coord(la, qlen, ug->u.a[la->v>>1].len, &aqs, NULL, NULL, NULL); + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v), *p = NULL; + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + if(av[i].v == w) { + // o -= av[i].ol; + p = &(av[i]); + break; + } + } + oj = o; + if(p) oj = pqe - aqs - p->ol; + if(o > oj) o = oj; + if(o < 0) o = 0; + return o; +} + + + +int64_t get_lchain_gap(mg_lchain_t *lp, mg_lchain_t *la, const asg_t *g, const int64_t qlen, const ma_ug_t *ug, int32_t double_ol) +{ + int64_t gg = la->qs - lp->qe, ggj; + uint32_t v = la->v^1, w = lp->v^1, i; + int32_t aqs, pqe; + if(double_ol == 0 && gg >= 0) return gg; + if(v == w) return gg; + transfor_coord(la, qlen, ug->u.a[la->v>>1].len, &aqs, NULL, NULL, NULL); + transfor_coord(lp, qlen, ug->u.a[lp->v>>1].len, NULL, &pqe, NULL, NULL); + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v), *p = NULL;; + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + if(av[i].v == w) { + // gg += av[i].ol; + p = &(av[i]); + break; + } + } + ggj = gg; + if(p) ggj = aqs - pqe + p->ol + (double_ol?p->ol:0); + // if(gg < ggj) gg = ggj; + // return gg; + return ggj; +} + +int64_t max_ovlp(const asg_t *g, uint32_t v) +{ + uint32_t i, nv = asg_arc_n(g, v), o = 0; + asg_arc_t *av = asg_arc_a(g, v); + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + if(o < av[i].ol) o = av[i].ol; + } + return o; +} + +int64_t max_ovlp_src(const ug_opt_t *uopt, uint32_t v) +{ + ma_hit_t_alloc* src = uopt->sources; + int64_t min_ovlp = uopt->min_ovlp, max_hang = uopt->max_hang; + uint32_t i, qn, tn, o = 0, x = v>>1; asg_arc_t e; + + for (i = 0; i < src[x].length; i++) { + qn = Get_qn(src[x].buffer[i]); tn = Get_tn(src[x].buffer[i]); + if(ma_hit2arc(&(src[x].buffer[i]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), + max_hang, asm_opt.max_hang_rate, min_ovlp, &e) < 0) { + continue; + } + if((e.ul>>32) != v) continue; + if(o < e.ol) o = e.ol; + } + + return o; +} + +int64_t specific_ovlp(const ma_ug_t *ug, const ug_opt_t *uopt, const uint32_t v, const uint32_t w) +{ + if(ug->u.a[v>>1].circ || ug->u.a[w>>1].circ) return 0; + uint32_t rv, rw, i; int32_t r; + const ma_hit_t_alloc *x = NULL; + asg_arc_t t; memset(&t, 0, sizeof(t)); + if(v&1) rv = ug->u.a[v>>1].start^1; + else rv = ug->u.a[v>>1].end^1; + if(w&1) rw = ug->u.a[v>>1].end; + else rw = ug->u.a[v>>1].start; + x = &(uopt->sources[rv>>1]); + for (i = 0; i < x->length; i++) { + if(Get_tn(x->buffer[i]) == (rw>>1)) { + r = ma_hit2arc(&(x->buffer[i]), uopt->coverage_cut[rv>>1].e - uopt->coverage_cut[rv>>1].s, + uopt->coverage_cut[rw>>1].e - uopt->coverage_cut[rw>>1].s, uopt->max_hang, asm_opt.max_hang_rate, uopt->min_ovlp, &t); + if(r < 0) return 0; + if((t.ul>>32)!=rv || t.v!=rw) return 0; + return t.ol; + } + } + return 0; +} + +void extend_lchain(mg_lchain_t *lc, int32_t n_lc, int32_t qlen, const ma_ug_t *ug) +{ + int32_t i; + for (i = 0; i < n_lc; ++i) { + extend_coordinates(&lc[i], qlen, ug->u.a[lc[i].v>>1].len); + } +} + +void compress_lchain(mg_lchain_t *lc, int32_t n_lc, int32_t qlen, const ma_ug_t *ug, const mg128_t *a) +{ + int32_t i, k, q_span; + mg_lchain_t *ri = NULL; + for (i = 0; i < n_lc; ++i) { + ri = &lc[i]; + k = ri->off; + ri->rs = (int32_t)a[k].x + 1 > q_span? (int32_t)a[k].x + 1 - q_span : 0; // for HPC k-mer + ri->qs = (int32_t)a[k].y + 1 - (a[k].y>>32 & 0xff); + ri->re = (int32_t)a[k + ri->cnt - 1].x + 1; + ri->qe = (int32_t)a[k + ri->cnt - 1].y + 1; + } +} + +void print_gchain(gc_frag_t *a, const int64_t *p, mg_lchain_t *lc, const int64_t nlc, const ma_ug_t *ug, int32_t qlen) +{ + int64_t k, i; + gc_frag_t *ai = NULL; + mg_lchain_t *li = NULL; + for (k = 0; k < nlc; k++) { + fprintf(stderr, "\n"); + for (i = k; i >= 0; i = p[i]) { + ai = &a[i]; li = &lc[ai->i]; + fprintf(stderr, "*\tXXXXXX\tutg%.6d%c\t%c\tqs:%u\tqe:%u\tql:%d\tts:%u\tte:%u\ttl:%u\n", + (li->v>>1)+1, "lc"[ug->u.a[li->v>>1].circ], "+-"[li->v&1], li->qs, li->qe, qlen, li->rs, li->re, ug->u.a[li->v>>1].len); + } + } +} + +// void extend_graph_coordnates(const ma_ug_t *ug, const ug_opt_t *uopt, const mg_lchain_t *lp, const mg_lchain_t *la, +// mg_coor_t *gp, mg_coor_t *ga, int32_t *go, int32_t *gg) +// { +// int32_t so = specific_ovlp(ug, uopt, lp->v^1, la->v^1); +// } + +int32_t mg_gchain1_dp(void *km, const ma_ug_t *ug, const asg_t *rg, int32_t *n_lc_, mg_lchain_t *lc, int32_t qlen, int32_t max_dist_g, int32_t max_dist_q, int32_t bw, int32_t max_skip, + int32_t ref_bonus, float chn_pen_gap, float mask_level, int32_t max_gc_seq_ext, const ug_opt_t *uopt, const mg128_t *an, uint64_t **u_) +{ + int32_t i, j, k, m_dst, n_dst, n_ext, n_u, n_v, n_lc = *n_lc_, rrs, rre; + int32_t *f, *v, *t, li_qs, li_qe, li_rs, li_re, lj_qs, lj_qe, lj_rs, lj_re; + int64_t *p; + uint64_t *u; + mg_path_dst_t *dst; + gc_frag_t *a; + mg_lchain_t *swap; + // char *qs; + asg_t *g = ug->g; + + *u_ = 0; + if (n_lc == 0) return 0; + + // extend_lchain(lc, n_lc, qlen, ug); + KMALLOC(km, a, n_lc); + ///n_lc how many linear chains; just filter some linear chains + for (i = n_ext = 0; i < n_lc; ++i) { // a[] is a view of frag[]; for sorting + mg_lchain_t *r = &lc[i]; + gc_frag_t *ai = &a[i]; + int32_t is_isolated = 0, min_end_dist_g; + transfor_coord(r, qlen, ug->u.a[r->v>>1].len, NULL, NULL, &rrs, &rre); + r->dist_pre = -1;///indicate parent in graph chain + min_end_dist_g = g->seq[r->v>>1].len - rre;///r->v: ref_id|rev + if (rrs < min_end_dist_g) min_end_dist_g = rrs; + if (min_end_dist_g > max_dist_g) is_isolated = 1; // if too far from segment ends + else if (min_end_dist_g>>3 > r->score) is_isolated = 1; // if the lchain too small relative to distance to the segment ends + ai->srt = (uint32_t)is_isolated<<31 | r->qe; + ai->i = i; + if (!is_isolated) ++n_ext; + } + ///if the alignment is too far from segment ends, which means it cannot contribute to graph alignment + if (n_ext < 2) { // no graph chaining needed; early return + kfree(km, a); + KMALLOC(km, u, n_lc); + for (i = 0; i < n_lc; ++i) + u[i] = (uint64_t)lc[i].score<<32 | 1; + *u_ = u; + // compress_lchain(lc, n_lc, qlen, ug, an); + return n_lc; + } + radix_sort_gc(a, a + n_lc);///sort by: is_isolated(1):qe + + KMALLOC(km, v, n_lc); + KMALLOC(km, f, n_ext); + KMALLOC(km, p, n_ext); + KCALLOC(km, t, n_ext); + // KMALLOC(km, qs, max_dist_q + 1);//for + + m_dst = n_dst = 0, dst = 0; + ///n_ext is number of linear chains that might be included in graph chains + ///sorted by the positions in query; sorted by qe of each chain + for (i = 0; i < n_ext; ++i) { // core loop + gc_frag_t *ai = &a[i]; + mg_lchain_t *li = &lc[ai->i];///linear chain; sorted by qe, i.e. end position in query + int32_t mm_ovlp = max_ovlp(ug->g, li->v^1); + transfor_coord(li, qlen, ug->u.a[li->v>>1].len, &li_qs, &li_qe, &li_rs, &li_re); + ///note segi is query id, instead of ref id; it is not such useful + /** + * a[].x: idx_in_minimizer_arr(32)r_pos(32) + * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) + **/ + { // collect end points potentially reachable from _i_ + int32_t x = li->qs + bw + mm_ovlp, n_skip = 0; + if (x > qlen) x = qlen; + ///collect alignments that can be reachable from the left side + ///that is, a[x].qe <= x + x = find_max(i, a, x); + n_dst = 0; + for (j = x; j >= 0; --j) { // collect potential destination vertices + gc_frag_t *aj = &a[j]; + //potential chains that might be overlapped with the left side of li + mg_lchain_t *lj = &lc[aj->i]; + mg_path_dst_t *q; + int32_t target_dist, dq/**, so = specific_ovlp(ug, uopt, li->v^1, lj->v^1)**/; + transfor_coord(lj, qlen, ug->u.a[lj->v>>1].len, &lj_qs, &lj_qe, &lj_rs, &lj_re); + ///lj->qs >= li->qs && lj->qe <= li->qs, so lj is contained + if (lj->qs >= li->qs) continue; // lj is contained in li on the query coordinate + /** + * doesn't work for overlap graph + if (lj_qe > li_qs) { // test overlap on the query + int o = lj_qe - li_qs - so;///get_lchain_ovlp(lj, li, ug->g, qlen, ug); + ///mask_level = 0.5, if overlap is too long + ///note here is the overlap in query, so too long overlaps might be wrong + if (o > (lj->qe - lj->qs) * mask_level || o > (li->qe - li->qs) * mask_level) + continue; + } + **/ + dq = li_qs - lj_qe;///dq might be smaller than 0 + if (dq > max_dist_q) break; // if query gap too large, stop + ///The above filter chains like: + ///1. lj is contained in li + ///2. the overlap between li and lj is too large + ///3. li and lj are too far + ///above we have checked gap/overlap in query + ///then we need to check gap/overlap in reference + if (li->v != lj->v) { // the two linear chains are on two different refs + // minimal graph gap; the real graph gap might be larger + int32_t min_dist = li_rs + (g->seq[lj->v>>1].len - lj_re); + if (min_dist > max_dist_g) continue; // graph gap too large + //note here min_dist - (lj->qs - li->qe) > bw is important + //min_dist is always larger than 0, (lj->qs - li->qe) might be negative + /** + * doesn't work for overlap graph + min_dist -= so; + if (min_dist - bw > li->qs - lj->qe) continue; ///note seg* is the query id, instead of ref id + **/ + target_dist = mg_target_dist(g, lj, li); + if (target_dist < 0) continue; // this may happen if the query overlap is far too large + } else if (lj->rs >= li->rs || lj->re >= li->re) { // not colinear + continue; + } else {///li->v == lj->v and colinear; at the same ref id + ///w is indel, w is always positive + int32_t dr = li->rs - lj->re, dq = li->qs - lj->qe, w = dr > dq? dr - dq : dq - dr; + ///note that l*->v is the ref id, while seg* is the query id + if (w > bw) continue; // test bandwidth + if (dr > max_dist_g || dr < -max_dist_g) continue; + if (lj->re > li->rs) { // test overlap on the graph segment + int o = lj->re - li->rs; + if (o > (lj->re - lj->rs) * mask_level || o > (li->re - li->rs) * mask_level) + continue; + } + target_dist = mg_target_dist(g, lj, li); + } + if (n_dst == m_dst) KEXPAND(km, dst, m_dst); // TODO: watch out the quadratic behavior! + q = &dst[n_dst++];///q saves information for i->j + memset(q, 0, sizeof(mg_path_dst_t)); + ///note v is (rid:rev), so two alignment chains might be at the same ref id with different directions + q->inner = (li->v == lj->v); + q->v = lj->v^1;///must be v^1 instead of v + q->meta = j; + q->qlen = li->qs - lj->qe;///might be negative + /** + * doesn't work for overlap graph + q->so = 0; + if(li->v != lj->v && lj->qe > li->qs) { + lj_qe = lj->qe; li_qs = li->qs + g->seq[lj->v>>1].len - so; + q->so = lj_qe - li_qs; + if(q->so < 0) q->so = 0; + } + **/ + q->target_dist = target_dist;///cannot understand the target_dist + q->target_hash = 0; + q->check_hash = 0; + if (t[j] == i) {///this pre-cut is weird; attention + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + } + ///the above saves all linear chains that might be reached to the left side of chain i + ///all those chains are saved to dst + { // confirm reach-ability + int32_t k; + // test reach-ability without sequences + // (g->seg[li->v>>1].len - li->rs) ----> is like the node length in string graph + mg_shortest_k(km, g, li->v^1, n_dst, dst, max_dist_g + (g->seq[li->v>>1].len - li->rs), MG_MAX_SHORT_K, /**0, 0, 1,**/ 0); + // remove unreachable destinations + for (j = k = 0; j < n_dst; ++j) { + mg_path_dst_t *dj = &dst[j]; + int32_t sc; + if (dj->n_path == 0) continue; // unreachable + sc = cal_sc(dj, li, lc, an, a, f, bw, ref_bonus, chn_pen_gap); + if (sc == INT32_MIN) continue; // out of band + if (sc + li->score < 0) continue; // negative score and too low + dst[k] = dst[j]; + dst[k++].srt_key = INT64_MAX/2 - (int64_t)sc; // sort in the descending order + } + n_dst = k; + if (n_dst > 0) { + radix_sort_dst(dst, dst + n_dst); + // discard weaker chains if the best score is much larger (assuming base-level heuristic won't lift it to the top chain) + // dst[0].srt_key has the largest score + for (j = 1; j < n_dst; ++j) + if ((int64_t)(dst[j].srt_key - dst[0].srt_key) > li->score)//discard chains with too small weight + break; + n_dst = j; + if (n_dst > max_gc_seq_ext) n_dst = max_gc_seq_ext; // discard weaker chains + } + } + /** //path + if (n_dst > 0) { // find paths with sequences + int32_t min_qs = li->qs; + for (j = 0; j < n_dst; ++j) { + const mg_lchain_t *lj; + assert(dst[j].n_path > 0); + ///a[]->srt = (uint32_t)is_isolated<<31 | r->qe; + ///a[]->i = i; + lj = &lc[a[dst[j].meta].i]; + if (lj->qe < min_qs) min_qs = lj->qe; + } + ///qs keeps the sequence at the gap between the li and lj in query + memcpy(qs, &qseq[min_qs], li->qs - min_qs); + mg_shortest_k(km, g, li->v^1, n_dst, dst, max_dist_g + (g->seg[li->v>>1].len - li->rs), MG_MAX_SHORT_K, li->qs - min_qs, qs, 1, 0); + if (mg_dbg_flag & MG_DBG_GC1) fprintf(stderr, "[src:%d] q_intv=[%d,%d), src=%c%s[%d], n_dst=%d, max_dist=%d, min_qs=%d, lc_score=%d\n", ai->i, li->qs, li->qe, "><"[(li->v&1)^1], g->seg[li->v>>1].name, li->v^1, n_dst, max_dist_g + (g->seg[li->v>>1].len - li->rs), min_qs, li->score); + }**/ + { // DP + int32_t max_f = li->score, max_j = -1, max_d = -1, max_inner = 0; + uint32_t max_hash = 0; + for (j = 0; j < n_dst; ++j) { + mg_path_dst_t *dj = &dst[j]; + int32_t sc; + sc = cal_sc(dj, li, lc, an, a, f, bw, ref_bonus, chn_pen_gap); + if (sc == INT32_MIN) continue; + if (sc > max_f) max_f = sc, max_j = dj->meta, max_d = dj->dist, max_hash = dj->hash, max_inner = dj->inner; + } + f[i] = max_f, p[i] = max_j; + li->dist_pre = max_d; + li->hash_pre = max_hash; + li->inner_pre = max_inner; + v[i] = max_j >= 0 && v[max_j] > max_f? v[max_j] : max_f; + } + } + kfree(km, dst); + + // print_gchain(a, p, lc, n_ext, ug, qlen); + + // kfree(km, qs); + ///n_ext: number of useful chains + ///n_lc - n_ext: number of isoated chains + u = mg_chain_backtrack(km, n_ext, f, p, v, t, 0, 0, n_lc - n_ext, &n_u, &n_v); + kfree(km, f); kfree(km, p); kfree(km, t); + ///store the extra isoated chains + for (i = 0; i < n_lc - n_ext; ++i) { + u[n_u++] = (uint64_t)lc[a[n_ext + i].i].score << 32 | 1; + v[n_v++] = n_ext + i; + } + + ///reorganize lc; + KMALLOC(km, swap, n_v); + for (i = 0, k = 0; i < n_u; ++i) { + int32_t k0 = k, ni = (int32_t)u[i]; + for (j = 0; j < ni; ++j) + swap[k++] = lc[a[v[k0 + (ni - j - 1)]].i]; + } + assert(k == n_v); + memcpy(lc, swap, n_v * sizeof(mg_lchain_t)); + *n_lc_ = n_v; + *u_ = u; + // compress_lchain(lc, *n_lc_, qlen, ug, an); + + kfree(km, a); + kfree(km, swap); + kfree(km, v); + return n_u; +} + + +static inline void copy_lchain(mg_llchain_t *q, const mg_lchain_t *p, int32_t *n_a, mg128_t *a_new, const mg128_t *a_old) +{ + q->cnt = p->cnt, q->v = p->v, q->score = p->score; + memcpy(&a_new[*n_a], &a_old[p->off], q->cnt * sizeof(mg128_t)); + q->off = *n_a; + (*n_a) += q->cnt; +} + +void mg_gchain_extra(const asg_t *g, mg_gchains_t *gs) +{ + int32_t i, j, k; + for (i = 0; i < gs->n_gc; ++i) { // iterate over gchains + mg_gchain_t *p = &gs->gc[i]; + const mg_llchain_t *q; + const mg128_t *last_a; + int32_t q_span, rest_pl, tmp, n_mini; + + p->qs = p->qe = p->ps = p->pe = -1, p->plen = p->blen = p->mlen = 0, p->div = -1.0f; + if (p->cnt == 0) continue; + ///some linear chains in middle might be [].cnt == 0 + ///but for the first and the last linear chains, [].cnt > 0 + assert(gs->lc[p->off].cnt > 0 && gs->lc[p->off + p->cnt - 1].cnt > 0); // first and last lchains can't be empty + q = &gs->lc[p->off]; + q_span = (int32_t)(gs->a[q->off].y>>32&0xff); + /** + * a[].x: idx_in_minimizer_arr(32)r_pos(32) + * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) + * **/ + p->qs = (int32_t)gs->a[q->off].y + 1 - q_span;///calculated by the first lchain + p->ps = (int32_t)gs->a[q->off].x + 1 - q_span;///calculated by the first lchain + tmp = (int32_t)(gs->a[q->off].x>>32); + assert(p->qs >= 0 && p->ps >= 0); + q = &gs->lc[p->off + p->cnt - 1];///last lchain + p->qe = (int32_t)gs->a[q->off + q->cnt - 1].y + 1; + p->pe = g->seq[q->v>>1].len - (int32_t)gs->a[q->off + q->cnt - 1].x - 1; // this is temporary + n_mini = (int32_t)(gs->a[q->off + q->cnt - 1].x>>32) - tmp + 1; + assert(p->n_anchor > 0); + + rest_pl = 0; // this value is never used if the first lchain is not empty (which should always be true) + last_a = &gs->a[gs->lc[p->off].off];///first minizers in the first linear chain + for (j = 0; j < p->cnt; ++j) { // iterate over lchains + const mg_llchain_t *q = &gs->lc[p->off + j]; + int32_t vlen = g->seq[q->v>>1].len;///node length in graph + p->plen += vlen; + for (k = 0; k < q->cnt; ++k) { // iterate over anchors + const mg128_t *r = &gs->a[q->off + k]; + int32_t pl, ql = (int32_t)r->y - (int32_t)last_a->y; + int32_t span = (int32_t)(r->y>>32&0xff); + if (j == 0 && k == 0) { // the first anchor on the first lchain + pl = ql = span; + } else if (j > 0 && k == 0) { // the first anchor but not on the first lchain + pl = (int32_t)r->x + 1 + rest_pl; + } else { + pl = (int32_t)r->x - (int32_t)last_a->x; + } + if (ql < 0) ql = -ql, n_mini += (int32_t)(last_a->x>>32) - (int32_t)(r->x>>32); // dealing with overlapping query at junctions + p->blen += pl > ql? pl : ql; + p->mlen += pl > span && ql > span? span : pl < ql? pl : ql; + last_a = r; + } + if (q->cnt == 0) rest_pl += vlen; + else rest_pl = vlen - (int32_t)gs->a[q->off + q->cnt - 1].x - 1; + } + p->pe = p->plen - p->pe; + assert(p->pe >= p->ps); + // here n_mini >= p->n_anchor should stand almost all the time + p->div = n_mini >= p->n_anchor? log((double)n_mini / p->n_anchor) / q_span : log((double)p->n_anchor / n_mini) / q_span; + } +} + +// reorder gcs->a[] and gcs->lc[] such that they are in the same order as gcs->gc[] +void mg_gchain_restore_order(void *km, mg_gchains_t *gcs) +{ + int32_t i, n_a, n_lc; + mg_llchain_t *lc; + mg128_t *a; + KMALLOC(km, lc, gcs->n_lc); + KMALLOC(km, a, gcs->n_a); + n_a = n_lc = 0; + for (i = 0; i < gcs->n_gc; ++i) { + mg_gchain_t *gc = &gcs->gc[i]; + assert(gc->cnt > 0); + memcpy(&lc[n_lc], &gcs->lc[gc->off], gc->cnt * sizeof(mg_llchain_t)); + memcpy(&a[n_a], &gcs->a[gcs->lc[gc->off].off], gc->n_anchor * sizeof(mg128_t)); + n_lc += gc->cnt, n_a += gc->n_anchor; + } + memcpy(gcs->lc, lc, gcs->n_lc * sizeof(mg_llchain_t)); + memcpy(gcs->a, a, gcs->n_a * sizeof(mg128_t)); + kfree(km, lc); kfree(km, a); +} + +// sort chains by score +void mg_gchain_sort_by_score(void *km, mg_gchains_t *gcs) +{ + mg128_t *z; + mg_gchain_t *gc; + int32_t i; + KMALLOC(km, z, gcs->n_gc); + KMALLOC(km, gc, gcs->n_gc); + for (i = 0; i < gcs->n_gc; ++i) + z[i].x = (uint64_t)gcs->gc[i].score << 32 | gcs->gc[i].hash, z[i].y = i; + radix_sort_128x(z, z + gcs->n_gc); + for (i = gcs->n_gc - 1; i >= 0; --i) + gc[gcs->n_gc - 1 - i] = gcs->gc[z[i].y]; + memcpy(gcs->gc, gc, gcs->n_gc * sizeof(mg_gchain_t)); + kfree(km, z); kfree(km, gc); + mg_gchain_restore_order(km, gcs); // this put gcs in the proper order +} + +///u[]: sc|occ of chains +///a[]: candidate list +///gcs[0] = mg_gchain_gen(0, b->km, gi->g, n_gc, u, lc, a, hash, opt->min_gc_cnt, opt->min_gc_score); +// TODO: if frequent malloc() is a concern, filter first and then generate gchains; or generate gchains in thread-local pool and then move to global malloc() +mg_gchains_t *mg_gchain_gen(void *km_dst, void *km, const asg_t *g, int32_t n_u, const uint64_t *u, const mg_lchain_t *lc, const mg128_t *a, + uint32_t hash, int32_t min_gc_cnt, int32_t min_gc_score) +{ + mg_gchains_t *gc; + mg_llchain_t *tmp; + int32_t i, j, k, st, n_g, n_a, s_tmp, n_tmp, m_tmp; + KCALLOC(km_dst, gc, 1); + // count the number of gchains and remaining anchors + // filter out low-quality g_chains + for (i = 0, st = 0, n_g = n_a = 0; i < n_u; ++i) { + ///nui: how many linear chaisn in i-th g_chain + int32_t m = 0, nui = (int32_t)u[i]; + for (j = 0; j < nui; ++j) m += lc[st + j].cnt; // m is the number of anchors in this gchain + if (m >= min_gc_cnt && (int64_t)(u[i]>>32) >= min_gc_score) + ++n_g, n_a += m; + st += nui; + } + if (n_g == 0) return gc; + + // preallocate + gc->km = km_dst; + gc->n_gc = n_g, gc->n_a = n_a; + KCALLOC(km_dst, gc->gc, n_g);///all graph chains + KMALLOC(km_dst, gc->a, n_a);///all anchors, aka minimizers + + // core loop + tmp = 0; s_tmp = n_tmp = m_tmp = 0; + for (i = k = 0, st = 0, n_a = 0; i < n_u; ++i) { + int32_t n_a0 = n_a, m = 0, nui = (int32_t)u[i]; ///nui: how many linear chaisn in i-th g_chain + for (j = 0; j < nui; ++j) m += lc[st + j].cnt; ///how many minizers in i-th g_chain + if (m >= min_gc_cnt && (int64_t)(u[i]>>32) >= min_gc_score) { + mg_llchain_t *q; + uint32_t h = hash; + + gc->gc[k].score = u[i]>>32; ///chain score + gc->gc[k].off = s_tmp; ///all minimizers of k-th chain: gc->a[gc->gc[k].off, ) + + for (j = 0; j < nui; ++j) {///how many linear chains + const mg_lchain_t *p = &lc[st + j]; + h += __ac_Wang_hash(p->qs) + __ac_Wang_hash(p->re) + __ac_Wang_hash(p->v); + } + gc->gc[k].hash = __ac_Wang_hash(h);///hash key for the k-th graph chain + + if (n_tmp == m_tmp) KEXPAND(km, tmp, m_tmp); + // copy the first lchain to gc->a[] and tmp[] (aka, gc->lc[]) + // for the first lchain, it is easy and we just copy all its anchors + copy_lchain(&tmp[n_tmp++], &lc[st], &n_a, gc->a, a); + ///0-th lchain has been stored + ///process the remaining chains + for (j = 1; j < nui; ++j) { + const mg_lchain_t *l0 = &lc[st + j - 1], *l1 = &lc[st + j]; + if (!l1->inner_pre) { // bridging two segments; if l0 and l1 are at different reference + int32_t s, n_pathv; + mg_path_dst_t dst; + mg_pathv_t *p; + memset(&dst, 0, sizeof(mg_path_dst_t)); + dst.v = l0->v ^ 1; + assert(l1->dist_pre >= 0); + dst.target_dist = l1->dist_pre; + dst.target_hash = l1->hash_pre;///hash value of the whole path + dst.check_hash = 1; + p = mg_shortest_k(km, g, l1->v^1, 1, &dst, dst.target_dist, MG_MAX_SHORT_K, &n_pathv); + if (n_pathv == 0 || dst.target_hash != dst.hash) + fprintf(stderr, "%c[%d] -> %c[%d], dist=%d, target_dist=%d\n", "><"[(l1->v^1)&1], l1->v^1, "><"[(l0->v^1)&1], l0->v^1, dst.dist, dst.target_dist); + assert(n_pathv > 0); + assert(dst.target_hash == dst.hash); + for (s = n_pathv - 2; s >= 1; --s) { // path found in a backward way, so we need to reverse it + if (n_tmp == m_tmp) KEXPAND(km, tmp, m_tmp); + q = &tmp[n_tmp++]; + q->off = q->cnt = q->score = 0; + q->v = p[s].v^1; // when reversing a path, we also need to flip the orientation + } + kfree(km, p); + if (n_tmp == m_tmp) KEXPAND(km, tmp, m_tmp); + copy_lchain(&tmp[n_tmp++], l1, &n_a, gc->a, a); + } + else { // if both of them are at the same linear chain, just merge them + #if 1 + int32_t k; + mg_llchain_t *t = &tmp[n_tmp - 1];//the last lchain, have alread done + assert(l0->v == l1->v); + // a[].x: ref_id(31)rev(1)r_pos(32) + // a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) + for (k = 0; k < l1->cnt; ++k) { + const mg128_t *ak = &a[l1->off + k]; + if ((int32_t)ak->x > l0->re && (int32_t)ak->y > l0->qe)//find colinear anchors + break; + } + assert(k < l1->cnt); + t->cnt += l1->cnt - k, t->score += l1->score; + memcpy(&gc->a[n_a], &a[l1->off + k], (l1->cnt - k) * sizeof(mg128_t)); + n_a += l1->cnt - k; + #else // don't use this block; for debugging only + if (n_tmp == m_tmp) KEXPAND(km, tmp, m_tmp); + copy_lchain(&tmp[n_tmp++], l1, &n_a, gc->a, a); + #endif + } + } + gc->gc[k].cnt = n_tmp - s_tmp; + gc->gc[k].n_anchor = n_a - n_a0; + ++k, s_tmp = n_tmp; + } + st += nui;//nui: how many linear chains in this gchain + } + assert(n_a <= gc->n_a); + + gc->n_a = n_a; + gc->n_lc = n_tmp; + KMALLOC(km_dst, gc->lc, n_tmp); + memcpy(gc->lc, tmp, n_tmp * sizeof(mg_llchain_t)); + kfree(km, tmp); + + mg_gchain_extra(g, gc); + mg_gchain_sort_by_score(km, gc); + return gc; +} + + +// set r[].{id,parent,subsc}, ASSUMING r[] is sorted by score +// mg_gchain_set_parent(b->km, opt->mask_level, gcs[0]->n_gc, gcs[0]->gc, opt->sub_diff, 0); +void mg_gchain_set_parent(void *km, float mask_level, int n, mg_gchain_t *r, int sub_diff, int hard_mask_level) +{ + int i, j, k, *w; + uint64_t *cov; + if (n <= 0) return; + for (i = 0; i < n; ++i) r[i].id = i; + cov = (uint64_t*)kmalloc(km, n * sizeof(uint64_t)); + w = (int*)kmalloc(km, n * sizeof(int)); + w[0] = 0, r[0].parent = 0;///the first gchain is a primary hits; since all gchains have already been sorted by scores + for (i = 1, k = 1; i < n; ++i) {///start from the 1-th chain, instead of the 0-th chain + mg_gchain_t *ri = &r[i]; + int si = ri->qs, ei = ri->qe, n_cov = 0, uncov_len = 0; + if (hard_mask_level) goto skip_uncov; + for (j = 0; j < k; ++j) { // traverse existing primary hits to find overlapping hits + mg_gchain_t *rp = &r[w[j]]; + int sj = rp->qs, ej = rp->qe; + if (ej <= si || sj >= ei) continue;///no overlaps + if (sj < si) sj = si;///MAX(si, sj) + if (ej > ei) ej = ei;///MIN(ei, ej) + cov[n_cov++] = (uint64_t)sj<<32 | ej;///overlap coordinates + } + if (n_cov == 0) { + goto set_parent_test; // no overlapping primary hits; then i is a new primary hit + } else if (n_cov > 0) { // there are overlapping primary hits; find the length not covered by existing primary hits + int j, x = si; + radix_sort_gfa64(cov, cov + n_cov); + for (j = 0; j < n_cov; ++j) { + if ((int)(cov[j]>>32) > x) uncov_len += (cov[j]>>32) - x; + x = (int32_t)cov[j] > x? (int32_t)cov[j] : x; + } + if (ei > x) uncov_len += ei - x; + } +skip_uncov: + for (j = 0; j < k; ++j) { // traverse existing primary hits again + mg_gchain_t *rp = &r[w[j]]; + int sj = rp->qs, ej = rp->qe, min, max, ol; + if (ej <= si || sj >= ei) continue; // no overlap + min = ej - sj < ei - si? ej - sj : ei - si;///chain length + max = ej - sj > ei - si? ej - sj : ei - si;///chain length + ol = si < sj? (ei < sj? 0 : ei < ej? ei - sj : ej - sj) : (ej < si? 0 : ej < ei? ej - si : ei - si); // overlap length; TODO: this can be simplified + if ((float)ol / min - (float)uncov_len / max > mask_level) { + int cnt_sub = 0; + ri->parent = rp->parent; + rp->subsc = rp->subsc > ri->score? rp->subsc : ri->score; + if (ri->cnt >= rp->cnt) cnt_sub = 1; + if (cnt_sub) ++rp->n_sub; + break; + } + } +set_parent_test: + if (j == k) w[k++] = i, ri->parent = i, ri->n_sub = 0; + } + kfree(km, cov); + kfree(km, w); +} + +// set r[].flt, i.e. mark weak suboptimal chains as filtered +int mg_gchain_flt_sub(float pri_ratio, int min_diff, int best_n, int n, mg_gchain_t *r) +{ + if (pri_ratio > 0.0f && n > 0) { + int i, k, n_2nd = 0; + for (i = k = 0; i < n; ++i) { + int p = r[i].parent; + if (p == i) { // primary + r[i].flt = 0, ++k; + } else if ((r[i].score >= r[p].score * pri_ratio || r[i].score + min_diff >= r[p].score) && n_2nd < best_n) { + if (!(r[i].qs == r[p].qs && r[i].qe == r[p].qe && r[i].ps == r[p].ps && r[i].pe == r[p].pe)) // not identical hits; TODO: check path as well + r[i].flt = 0, ++n_2nd, ++k; + else r[i].flt = 1; + } else r[i].flt = 1; + } + return k; + } + return n; +} + +// recompute gcs->gc[].{off,n_anchor} and gcs->lc[].off, ASSUMING they are properly ordered (see mg_gchain_restore_order) +void mg_gchain_restore_offset(mg_gchains_t *gcs) +{ + int32_t i, j, n_a, n_lc; + for (i = 0, n_a = n_lc = 0; i < gcs->n_gc; ++i) { + mg_gchain_t *gc = &gcs->gc[i]; + gc->off = n_lc; + for (j = 0, gc->n_anchor = 0; j < gc->cnt; ++j) { + mg_llchain_t *lc = &gcs->lc[n_lc + j]; + lc->off = n_a; + n_a += lc->cnt; + gc->n_anchor += lc->cnt; + } + n_lc += gc->cnt; + } + assert(n_lc == gcs->n_lc && n_a == gcs->n_a); +} + +// hard drop filtered chains, ASSUMING gcs is properly ordered +void mg_gchain_drop_flt(void *km, mg_gchains_t *gcs) +{ + int32_t i, n_gc, n_lc, n_a, n_lc0, n_a0, *o2n; + if (gcs->n_gc == 0) return; + KMALLOC(km, o2n, gcs->n_gc); + for (i = 0, n_gc = 0; i < gcs->n_gc; ++i) { + mg_gchain_t *r = &gcs->gc[i]; + o2n[i] = -1; + if (r->flt || r->cnt == 0) continue; + o2n[i] = n_gc++; + } + n_gc = n_lc = n_a = 0; + n_lc0 = n_a0 = 0; + for (i = 0; i < gcs->n_gc; ++i) { + mg_gchain_t *r = &gcs->gc[i]; + if (o2n[i] >= 0) { + memmove(&gcs->a[n_a], &gcs->a[n_a0], r->n_anchor * sizeof(mg128_t)); + memmove(&gcs->lc[n_lc], &gcs->lc[n_lc0], r->cnt * sizeof(mg_llchain_t)); + gcs->gc[n_gc] = *r; + gcs->gc[n_gc].id = n_gc; + gcs->gc[n_gc].parent = o2n[gcs->gc[n_gc].parent]; + ++n_gc, n_lc += r->cnt, n_a += r->n_anchor; + } + n_lc0 += r->cnt, n_a0 += r->n_anchor; + } + assert(n_lc0 == gcs->n_lc && n_a0 == gcs->n_a); + kfree(km, o2n); + gcs->n_gc = n_gc, gcs->n_lc = n_lc, gcs->n_a = n_a; + if (n_a != n_a0) { + KREALLOC(gcs->km, gcs->a, gcs->n_a); + KREALLOC(gcs->km, gcs->lc, gcs->n_lc); + KREALLOC(gcs->km, gcs->gc, gcs->n_gc); + } + mg_gchain_restore_offset(gcs); +} + +// estimate mapping quality +///mg_gchain_set_mapq(b->km, gcs, qlen, mz->n, opt->min_gc_score); +void mg_gchain_set_mapq(void *km, mg_gchains_t *gcs, int qlen, int max_mini, int min_gc_score) +{ + static const float q_coef = 40.0f; + int64_t sum_sc = 0; + float uniq_ratio, r_sc, r_cnt; + int i, t_sc, t_cnt; + if (gcs == 0 || gcs->n_gc == 0) return; + t_sc = qlen < 100? qlen : 100; + t_cnt = max_mini < 10? max_mini : 10; + if (t_cnt < 5) t_cnt = 5; + r_sc = 1.0 / t_sc; + r_cnt = 1.0 / t_cnt; + for (i = 0; i < gcs->n_gc; ++i) + if (gcs->gc[i].parent == gcs->gc[i].id) + sum_sc += gcs->gc[i].score;///primary chain + uniq_ratio = (float)sum_sc / (sum_sc + gcs->rep_len); + for (i = 0; i < gcs->n_gc; ++i) { + mg_gchain_t *r = &gcs->gc[i]; + if (r->parent == r->id) {///primary chain + int mapq, subsc; + float pen_s1 = (r->score > t_sc? 1.0f : r->score * r_sc) * uniq_ratio; + float x, pen_cm = r->n_anchor > t_cnt? 1.0f : r->n_anchor * r_cnt; + pen_cm = pen_s1 < pen_cm? pen_s1 : pen_cm; + subsc = r->subsc > min_gc_score? r->subsc : min_gc_score; + x = (float)subsc / r->score; + mapq = (int)(pen_cm * q_coef * (1.0f - x) * logf(r->score)); + mapq -= (int)(4.343f * logf(r->n_sub + 1) + .499f); + mapq = mapq > 0? mapq : 0; + if (r->score > subsc && mapq == 0) mapq = 1; + r->mapq = mapq < 60? mapq : 60; + } else r->mapq = 0; + } +} + +void mg_map_frag(const void *ha_flt_tab, const ha_pt_t *ha_idx, const ma_ug_t *ug, const asg_t *rg, const uint32_t qid, const int qlen, const char *qseq, ha_mzl_v *mz, +st_mt_t *sp, mg_tbuf_t *b, int32_t w, int32_t k, int32_t hpc, int32_t mz_sd, int32_t mz_rewin, const mg_idxopt_t *opt, const ug_opt_t *uopt, mg_gchains_t **gcs) +{ + mg128_t *a = NULL; + int64_t n_a; + int32_t *mini_pos; + int i, rep_len, n_mini_pos, n_lc, max_chain_gap_qry, max_chain_gap_ref, n_gc; + uint32_t hash; + uint64_t *u; + mg_lchain_t *lc; + km_stat_t kmst; + (*gcs) = NULL; + + hash = qid; + hash ^= __ac_Wang_hash(qlen) + __ac_Wang_hash(opt->seed); + hash = __ac_Wang_hash(hash); + + mz->n = 0; + mz2_ha_sketch(qseq, qlen, w, k, 0, hpc, mz, ha_flt_tab, mz_sd, NULL, NULL, NULL, -1, -1, -1, sp, mz_rewin, 1, NULL); + ///a[]->y: weight(8)seg_id(8)flag(8)span(8)pos(32);--->query + ///a[]->x: rid(31)rev(1)rpos(33);--->reference + a = collect_seed_hits(b->km, opt, 1/**opt->hap_n**/, ha_flt_tab, ha_idx, ug, mz, &n_a, &rep_len, &n_mini_pos, &mini_pos); + /** + // might be recover + if (opt->max_gap_pre > 0 && opt->max_gap_pre * 2 < opt->max_gap) n_a = flt_anchors(n_a, a, opt->max_gap_pre); + max_chain_gap_qry = max_chain_gap_ref = opt->max_gap; + **/ + max_chain_gap_qry = max_chain_gap_ref = qlen*2; + if (n_a == 0) {//no matched minimizer + if(a) kfree(b->km, a); + a = 0, n_lc = 0, u = 0; + } else { + a = mg_lchain_dp(max_chain_gap_ref, max_chain_gap_qry, opt->bw, opt->max_lc_skip, opt->max_lc_iter, + opt->min_lc_cnt, opt->min_lc_score, opt->chn_pen_gap, n_a, a, &n_lc, &u, b->km); + } + + if (n_lc) {///n_lc is how many linear chain we found + lc = mg_lchain_gen(b->km, qlen, n_lc, u, a, ug);//lc->the status of each chain; u->idx of each chain; + for (i = 0; i < n_lc; ++i)///update a[] since ref_id|rev has already been saved to lc[].v + mg_update_anchors(lc[i].cnt, &a[lc[i].off], n_mini_pos, mini_pos);///update a[].x + } else lc = 0; + kfree(b->km, mini_pos); kfree(b->km, u); + // fprintf(stderr, "++0++qid: %u, qlen: %d, n_a: %ld, n_lc: %d\n", qid, qlen, n_a, n_lc); + /** + * up to here, a[] has been changed + * a[].x: idx_in_minimizer_arr(32)r_pos(32) + * a[].y: weight(8)query_id(8)flag(8)span(8)q_pos(32) + **/ + // for (i = 0; i < n_lc; i++) { + // mg_lchain_t *ri = &lc[i]; + // fprintf(stderr, "+0)))))))))))))))))))))))))))+\tA\tutg%.6d%c\t%c\tqs:%u\tqe:%u\tql:%d\tts:%u\tte:%u\ttl:%u\n", + // (ri->v>>1)+1, "lc"[ug->u.a[ri->v>>1].circ], "+-"[ri->v&1], ri->qs, ri->qe, qlen, ri->rs, ri->re, ug->u.a[ri->v>>1].len); + // } + max_chain_gap_qry = max_chain_gap_ref = opt->max_gap; + n_gc = mg_gchain1_dp(b->km, ug, rg, &n_lc, lc, qlen, max_chain_gap_ref, max_chain_gap_qry, opt->bw, opt->max_gc_skip, opt->ref_bonus, + opt->chn_pen_gap, opt->mask_level, opt->max_gc_seq_ext, uopt, a, &u); + // for (i = 0; i < n_lc; i++) { + // mg_lchain_t *ri = &lc[i]; + // fprintf(stderr, "-0-\tA\tutg%.6d%c\t%c\tqs:%u\tqe:%u\tql:%d\tts:%u\tte:%u\ttl:%u\n", + // (ri->v>>1)+1, "lc"[ug->u.a[ri->v>>1].circ], "+-"[ri->v&1], ri->qs, ri->qe, qlen, ri->rs, ri->re, ug->u.a[ri->v>>1].len); + // } + (*gcs) = mg_gchain_gen(0, b->km, ug->g, n_gc, u, lc, a, hash, opt->min_gc_cnt, opt->min_gc_score); + (*gcs)->rep_len = rep_len; (*gcs)->qid = qid; (*gcs)->qlen = qlen; + kfree(b->km, a); + kfree(b->km, lc); + kfree(b->km, u); + + mg_gchain_set_parent(b->km, opt->mask_level, (*gcs)->n_gc, (*gcs)->gc, opt->sub_diff, 0); + mg_gchain_flt_sub(opt->pri_ratio, k * 2, opt->best_n, (*gcs)->n_gc, (*gcs)->gc); + mg_gchain_drop_flt(b->km, (*gcs)); + mg_gchain_set_mapq(b->km, (*gcs), qlen, mz->n, opt->min_gc_score); + + if (b->km) { + km_stat(b->km, &kmst); + if (kmst.n_blocks != kmst.n_cores) { + fprintf(stderr, "[E::%s] memory leak at %u\n", __func__, qid); + abort(); + } + if (kmst.largest > 1U<<28) { + km_destroy(b->km); + b->km = km_init(); + } + } + // fprintf(stderr, "++6++qid: %u, (*gcs)->n_gc: %d\n", qid, (*gcs)->n_gc); + +} + +static void worker_for_ul_alignment(void *data, long i, int tid) // callback for kt_for() +{ + utepdat_t *s = (utepdat_t*)data; + mg_map_frag(s->ha_flt_tab, s->ha_idx, s->ug, s->rg, s->id+i, s->len[i], s->seq[i], &(s->mzs[tid]), &(s->sps[tid]), s->buf[tid], s->opt->w, s->opt->k, + s->opt->is_HPC, asm_opt.mz_sample_dist, asm_opt.mz_rewin, s->opt, s->uopt, &(s->gcs[i])); +} + +uint32_t overlap_statistics(overlap_region_alloc* olist, ma_ug_t *ug, int64_t *tt, uint8_t mm) +{ + uint32_t k, sp = (uint32_t)-1, ep = (uint32_t)-1, l = 0; + for (k = 0; k < olist->length; k++) { + /** + if(b->olist.list[k].y_id != 38) continue; + **/ + /** + + for (z = 0, te = ta = tua = 0; z < b->olist.list[k].w_list_length; z++) { + if(b->olist.list[k].w_list[z].y_end != -1) { + te += b->olist.list[k].w_list[z].error; + ta += b->olist.list[k].w_list[z].x_end + 1 - b->olist.list[k].w_list[z].x_start; + fprintf(stderr, "x->[%lu, %lu), y->[%d, %d), e->%d\n", b->olist.list[k].w_list[z].x_start, b->olist.list[k].w_list[z].x_end+1, + b->olist.list[k].w_list[z].y_start, b->olist.list[k].w_list[z].y_end+1, b->olist.list[k].w_list[z].error); + } + else { + tua += b->olist.list[k].w_list[z].x_end + 1 - b->olist.list[k].w_list[z].x_start; + } + } + fprintf(stderr, "[M::utg%.6d%c::is_match:%u] x->[%u, %u); y->[%u, %u), ualigned->%u, e_rate->%f\n", b->olist.list[k].y_id+1, "lc"[s->ug->u.a[b->olist.list[k].y_id].circ], + b->olist.list[k].is_match == 1, b->olist.list[k].x_pos_s, b->olist.list[k].x_pos_e+1, b->olist.list[k].y_pos_s, b->olist.list[k].y_pos_e+1, tua, (float)te/(float)ta); + **/ + if(tt){ + uint32_t z; + for (z = 0; z < olist->list[k].w_list.n; z++) { + if(olist->list[k].w_list.a[z].y_end != -1) { + if(tt) *tt += olist->list[k].w_list.a[z].x_end+1-olist->list[k].w_list.a[z].x_start; + } + } + } + if(olist->list[k].is_match == mm) { + if(sp == (uint32_t)-1 || ep < olist->list[k].x_pos_s) { + if(sp != (uint32_t)-1) l += ep + 1 - sp; + sp = olist->list[k].x_pos_s; + ep = olist->list[k].x_pos_e; + } else { + ep = MAX(ep, olist->list[k].x_pos_e); + } + if(ug) { + fprintf(stderr, "[M::utg%.6d%c::is_match->%u] rev->%u, x->[%u, %u), y->[%u, %u)\n", (int)olist->list[k].y_id+1, "lc"[ug->u.a[olist->list[k].y_id].circ], olist->list[k].is_match, + olist->list[k].y_pos_strand, olist->list[k].x_pos_s, olist->list[k].x_pos_e+1, olist->list[k].y_pos_s, olist->list[k].y_pos_e+1); + } + } + } + if(sp != (uint32_t)-1) l += ep + 1 - sp; + return l; +} +/** +void replace_ul(overlap_region_alloc* olist, Correct_dumy* dumy, haplotype_evdience_alloc* hap, const ul_idx_t *uu) +{ + int64_t k, z, n = 0, c_qs, c_qe, c_ts, c_te, c_rev, p_qs, p_qe, p_te, p_ts, p_rev; + uint64_t *sc = NULL, *track = NULL; + overlap_region *c = NULL, *p = NULL; + dumy->length = 0; + for (k = 0; k < olist->length; k++) {///has already sorted by x_pos_e + if(olist->list[k].is_match!=1) continue; + dumy->overlapID[dumy->length] = (uint64_t)-1; + dumy->overlapID[dumy->length] <<= 32; + dumy->overlapID[dumy->length] |= k; + dumy->length++; + } + + kv_resize(uint64_t, hap->snp_srt, dumy->length); + hap->snp_srt.n = dumy->length; + memset(hap->snp_srt.a, 0, hap->snp_srt.n*sizeof(uint64_t)); + + sc = dumy->overlapID; track = hap->snp_srt.a; n = dumy->length; + for (k = 0; k < n; k++) { + c = &(olist->list[(uint32_t)track[k]]); + for (z = k-1; z >= 0; z--) { + p = &(olist->list[(uint32_t)track[z]]); + } + } +} +**/ + +uint64_t update_ava_het_site(haplotype_evdience_alloc *h, uint64_t oid, uint64_t *beg, uint64_t *end, uint64_t is_srt) +{ + uint64_t k, l, i, occ = 0, n = h->length, need_srt = 0; SnpStats *s = NULL; + haplotype_evdience tt; + l = beg? (*beg):0; if(end) (*end) = n; if(beg) (*beg) = n; + if(l < n && h->list[l].overlapID > oid){ + if(end) (*end) = l; + return 0; + } + for (k = l + 1; k <= n; ++k) { + if(h->list[l].overlapID > oid) { + if(end) (*end) = l; + break; + } + if (k == n || h->list[k].overlapID != h->list[l].overlapID) { + if(h->list[l].overlapID == oid) { + for (i = l; i < k; i++) { + if(h->list[i].type!=1) continue; + s = &(h->snp_stat.a[h->list[i].overlapSite]); + if(s->score == 1 && (!(s->occ_0 < 2 || s->occ_1 < 2))) { + if(l+occ != i) { + tt = h->list[l+occ]; + h->list[l+occ] = h->list[i]; + h->list[i] = tt; + } + if((occ>0) && (h->list[l+occ].covlist[l+occ-1].cov)) need_srt = 1; + occ++; + } + } + if(beg) (*beg) = l; + if(end) (*end) = k; + break; + } + l = k; + } + } + // if(oid == 160) { + // fprintf(stderr, "###[M::%s] l:%lu, occ:%lu\n", __func__, l, occ); + // for (k = l; k < l + occ; k++) { + // fprintf(stderr, "h->list[%lu]:%u\n", k, h->list[k].cov); + // } + // } + if(occ && is_srt && need_srt) { + radix_sort_hap_ev_cov_srt(h->list+l, h->list+l+occ); + } + + return occ; +} + + +uint64_t gl_chain_gen(overlap_region_alloc* olist, const ul_idx_t *uref, kv_ul_ov_t *res, uint32_t rec_trans, haplotype_evdience_alloc *hap, void *km) +{ + uint64_t k, o2 = 0, si = 0, ei = 0; ul_ov_t *p = NULL; + res->n = 0; + for (k = 0; k < olist->length; k++) { + if(olist->list[k].is_match==2) o2++; + if((!rec_trans) && olist->list[k].is_match!=1) continue; + if(rec_trans && olist->list[k].is_match!=1 && olist->list[k].is_match!=2) continue; + kv_pushp_km(km, ul_ov_t, *res, &p); + p->qn = k/**olist->list[k].x_id**/; p->qs = olist->list[k].x_pos_s; p->qe = olist->list[k].x_pos_e+1; + p->tn = olist->list[k].y_id; p->sec = 0; p->rev = olist->list[k].y_pos_strand; + p->el = (olist->list[k].is_match==1?1:0); + if(p->rev) { + p->ts = uref->ug->u.a[p->tn].len - (olist->list[k].y_pos_e+1); + p->te = uref->ug->u.a[p->tn].len - olist->list[k].y_pos_s; + } else { + p->ts = olist->list[k].y_pos_s; + p->te = olist->list[k].y_pos_e+1; + } + if(olist->list[k].is_match==2) { + p->sec = update_ava_het_site(hap, k, &si, &ei, 1); + assert(p->sec > 0); + si = ei; + } + } + return o2; +} + +int32_t find_ul_ov_max(int32_t n, const ul_ov_t *a, uint32_t x) +{ + int32_t s = 0, e = n; + if (n == 0) return -1; + if (a[n-1].qe < x) return n - 1; + if (a[0].qe >= x) return -1; + while (e > s) { // TODO: finish this block + int32_t m = s + (e - s) / 2; + if (a[m].qe >= x) e = m; + else s = m + 1; + } + assert(s == e); + return s; +} + + + +int64_t get_ecov(const ul_idx_t *uref, ul_ov_t *lv, ul_ov_t *lw, int64_t qlen, int64_t bw, double diff_ec_ul) +{ + int64_t dis_q = lv->qe - lw->qe, dis_t = 0, dif, mm; + uint32_t i, v = ((lv->tn<<1)|lv->rev)^1, w = ((lw->tn<<1)|lw->rev)^1; + const asg_t *g = uref->ug->g; + uint32_t nv = asg_arc_n(g, v); + asg_arc_t *av = asg_arc_a(g, v); + for (i = 0; i < nv; i++) { + if(av[i].del || av[i].v != w) continue; + dis_t = ((uint32_t)av[i].ul); + dis_t -= (lv->rev?lv->ts:g->seq[v>>1].len-lv->te); + break; + } + + dif = (dis_q>dis_t? dis_q-dis_t:dis_t-dis_q); + mm = MAX(dis_q, dis_t); mm *= diff_ec_ul; if(mm < bw) mm = bw; + // if((v>>1) == 1163 && (w>>1) == 1168) fprintf(stderr, ">>>>>>dis_q:%ld, dis_t:%ld, dif:%ld, mm:%ld\n", dis_q, dis_t, dif, mm); + if(dif <= mm) return 1; + return 0; +} + +int64_t gl_exact_chain(kv_ul_ov_t *res, kv_ul_ov_t *ex, const ul_idx_t *uref, int64_t bw, double diff_ec_ul, +int64_t qlen, uint64_t *srt, uint64_t *idx, uint64_t *track, void *km) +{ + // fprintf(stderr, "*****************\n"); + uint32_t li_v, lj_v; + int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx; + ul_ov_t *li = NULL, *lj = NULL; + const asg_t *g = uref->ug->g; + radix_sort_ul_ov_srt_qe(res->a, res->a + res->n); + for (i = 0; i < (int64_t)res->n; ++i) { + li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; + mm_ovlp = max_ovlp(g, li_v^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(i, res->a, x); + csc = retrieve_u_cov_region(uref, li->tn, 0, li->ts, li->te, NULL); + mm_sc = csc; mm_idx = -1; + // fprintf(stderr, "---i:%ld, csc:%ld, li->tn:%u, li->ts:%u, li->te:%u\n", i, csc, li->tn, li->ts, li->te); + for (j = x; j >= 0; --j) { // collect potential destination vertices + lj = &(res->a[j]); lj_v = (lj->tn<<1)|lj->rev; + // if(lj->qs >= li->qs) continue; // lj is contained in li on the query coordinate + if(li_v != lj_v && get_ecov(uref, li, lj, qlen, bw, diff_ec_ul)) { + sc = csc + (track[j]>>32); + if(sc > mm_sc) mm_sc = sc, mm_idx = j; + } + } + // 4294967295L + track[i] = mm_sc; track[i] <<= 32; + track[i] |= (mm_idx>=0?mm_idx:((uint64_t)0x7FFFFFFF)); + srt[i] = mm_sc; srt[i] <<= 32; srt[i] |= i; + // fprintf(stderr, "+++i:%ld, mm_idx:%ld, mm_sc:%ld\n", i, mm_idx, mm_sc); + // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n\n", li->tn+1, "lc"[uref->ug->u.a[li->tn].circ], li->qs, li->qe); + } + + int64_t n_v, n_u, n_v0; + radix_sort_gfa64(srt, srt+res->n); ex->n = res->n; + for (k = (int64_t)res->n-1, n_v = n_u = 0; k >= 0; --k) { + // fprintf(stderr, "\nk:%ld\n", k); + n_v0 = n_v; + for (i = (uint32_t)srt[k]; i >= 0 && (track[i]&((uint64_t)0x80000000)) == 0;) { + ex->a[n_v++] = res->a[i]; track[i] |= ((uint64_t)0x80000000); + // fprintf(stderr, "+i:%ld, ", i); + // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n", res->a[i].tn+1, "lc"[uref->ug->u.a[res->a[i].tn].circ], res->a[i].qs, res->a[i].qe); + if((track[i]&((uint64_t)0x7FFFFFFF)) == ((uint64_t)0x7FFFFFFF)) i = -1; + else i = track[i]&((uint64_t)0x7FFFFFFF); + // if(i>=(int64_t)res->n) fprintf(stderr, "ERROR->i:%ld, res->n:%d, n_v:%ld, qlen:%ld\n", i, (int32_t)res->n, n_v, qlen); + // fprintf(stderr, "next_i:%ld\n", i); + // i = (olist->list[i].y_id == (uint32_t)-1?-1:olist->list[i].y_id); + // fprintf(stderr, "-i:%ld\n", i); + } + if(n_v0 == n_v) continue; + ///keep the whole score; do not cut score like minigraph + // sc = (i<0?(srt[k]>>32):((srt[k]>>32)-olist->list[i].x_id)); + sc = srt[k]>>32; + idx[n_u++] = ((uint64_t)sc<<32)|(n_v-n_v0); + } + // if(n_v != (int64_t)res->n) { + // fprintf(stderr, "\nERROR->n_v:%ld, res->n:%d, qlen:%ld\n", n_v, (int32_t)res->n, qlen); + // for (k = 0; k < (int64_t)res->n; k++) { + // fprintf(stderr, "(%ld)srt-sc:%lu, srt-i:%u\n", k, srt[k]>>32, (uint32_t)srt[k]); + // } + + // for (k = 0; k < (int64_t)res->n; k++) { + // fprintf(stderr, "(%ld)track-sc:%lu, track-pi:%lu\n", k, track[k]>>32, track[k]&((uint64_t)0x7FFFFFFF)); + // } + // } + // if(n_v && ex->a[0].qn == 6) { + // for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { + // n_v0 = n_v; n_v += (uint32_t)idx[k]; + // fprintf(stderr, "\n"); + // for (i = n_v0; i < n_v; i++) { + // fprintf(stderr, "[%u, %u]\n", ex->a[i].qs, ex->a->qe); + // } + // } + // } + + for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { + n_v0 = n_v; n_v += (uint32_t)idx[k]; + res->a[k].qn = idx[k]>>32; + res->a[k].ts = n_v0; res->a[k].te = n_v; + res->a[k].qs = ex->a[n_v-1].qs; + res->a[k].qe = ex->a[n_v0].qe; + } + res->n = n_u; + return res->n; +} + +uint64_t get_het_site(haplotype_evdience_alloc *hap, uint32_t oid) +{ + uint64_t k, l, i, occ = 0; SnpStats *s = NULL; + for (k = 1, l = 0; k <= hap->length; ++k) { + if (k == hap->length || hap->list[k].overlapID != hap->list[l].overlapID) { + if(hap->list[l].overlapID != oid) { + l = k; + continue; + } + for (i = l; i < k; i++) { + if(hap->list[i].type!=1) continue; + s = &(hap->snp_stat.a[hap->list[i].overlapSite]); + if(s->score == 1 && (!(s->occ_0 < 2 || s->occ_1 < 2))) { + occ++; + } + } + l = k; + } + } + + return (occ&((uint64_t)0x3FFFFFFF)); +} + + +int64_t get_chain_x(overlap_region* ot, int64_t q) +{ + int64_t x, y, off, i, lx = -1, ly = -1; Fake_Cigar* o = &(ot->f_cigar); + x = get_fake_gap_pos(o, o->length - 1); + off = get_fake_gap_shift(o, o->length - 1); + y = x - ot->x_pos_s + ot->y_pos_s + off; + // if(ot->x_id == 98 && (q == 6681 || q == 6990)) fprintf(stderr, "o->length->%u, q->%ld, y->%ld, x->%ld\n", o->length, q, y, x); + if(y == q) return x; + + for (i = 0; i < (int64_t)o->length; i++){ + x = get_fake_gap_pos(o, i); off = get_fake_gap_shift(o, i); + y = x - ot->x_pos_s + ot->y_pos_s + off; + // if(ot->x_id == 98 && (q == 6681 || q == 6990)) fprintf(stderr, "+i->%ld, q->%ld, y->%ld, x->%ld\n", i, q, y, x); + if(q < y) { + lx = x; ly = y; + break; + } + } + + if(i == 0 || i == (int64_t)o->length) { + fprintf(stderr, "ERROR at %s:%d, x_id->%u, y_id->%u, q->%ld, i->%ld, yi_s->%u, yi_e->%u\n", + __FILE__, __LINE__, ot->x_id, ot->y_id, q, i, ot->y_pos_s, ot->y_pos_e); + exit(0); + } + + x = get_fake_gap_pos(o, i-1); off = get_fake_gap_shift(o, i-1); + y = x - ot->x_pos_s + ot->y_pos_s + off; + y = (((double)(q - y))/((double)(ly - y)))*((double)(lx -x)) + x; + // y = q - y + x; + if(y < ot->x_pos_s) y = ot->x_pos_s; + if(y > ot->x_pos_e) y = ot->x_pos_e; + return y; +} + + + +//[s, e] +double es_win_err(overlap_region* o, int64_t winLen, int64_t s, int64_t e) +{ + int64_t si, ei, os, k, tErr = 0, tLen = 0, minE, maxS, ov; + os = (o->x_pos_s/winLen)*winLen; + si = (s-os)/winLen; ei = (e-os)/winLen; + for (k = si+1; k <= ei-1; k++) { + tLen += o->w_list.a[k].x_end+1-o->w_list.a[k].x_start; + if(o->w_list.a[k].y_end != -1) { + tErr += o->w_list.a[k].error; + } else { + tErr += o->w_list.a[k].x_end+1-o->w_list.a[k].x_start; + } + } + + k = si; + maxS = MAX(s, (int64_t)(o->w_list.a[k].x_start)); minE = MIN(e, (int64_t)(o->w_list.a[k].x_end)) + 1; + ov = minE > maxS? minE - maxS:0; + if(ov == 0) { + fprintf(stderr, "WARNNING-1, o->w_list.n->%u, o->x_id->%u, s->%ld, e->%ld, w_list_s->%d, w_list_e->%d, winLen->%ld, o->x_pos_s->%u, o->x_pos_e->%u, si->%ld, flag->%d\n", + (uint32_t)o->w_list.n, o->x_id, s, e, o->w_list.a[k].x_start, o->w_list.a[k].x_end, winLen, o->x_pos_s, o->x_pos_e, si, o->w_list.a[k].y_end); + } + tLen += ov/**o->w_list[k].x_end+1-o->w_list[k].x_start**/; + if(o->w_list.a[k].y_end != -1) { + tErr += (ov*o->w_list.a[k].error)/(o->w_list.a[k].x_end+1-o->w_list.a[k].x_start); + } else { + tErr += ov/**o->w_list[k].x_end+1-o->w_list[k].x_start**/; + } + + k = ei; + maxS = MAX(s, (int64_t)(o->w_list.a[k].x_start)); minE = MIN(e, (int64_t)(o->w_list.a[k].x_end)) + 1; + ov = minE > maxS? minE - maxS:0; + if(ov == 0) { + fprintf(stderr, "WARNNING-2, o->w_list.n->%u, o->x_id->%u, s->%ld, e->%ld, w_list_s->%d, w_list_e->%d, winLen->%ld, o->x_pos_s->%u, o->x_pos_e->%u, ei->%ld, flag->%d\n", + (uint32_t)o->w_list.n, o->x_id, s, e, o->w_list.a[k].x_start, o->w_list.a[k].x_end, winLen, o->x_pos_s, o->x_pos_e, ei, o->w_list.a[k].y_end); + } + tLen += ov/**o->w_list[k].x_end+1-o->w_list[k].x_start**/; + if(o->w_list.a[k].y_end != -1) { + tErr += (ov*o->w_list.a[k].error)/(o->w_list.a[k].x_end+1-o->w_list.a[k].x_start); + } else { + tErr += ov/**o->w_list[k].x_end+1-o->w_list[k].x_start**/; + } + + return ((double)tErr)/((double)tLen); +} + +int64_t gen_contain_chain(const ul_idx_t *uref, utg_ct_t *p, overlap_region* o, kv_ul_ov_t *chains, double diff_ec_ul, int64_t winLen, void *km) +{ + int64_t y_s, y_e, y_bs, y_be, x_s, x_e, q_s, q_e; + if(o->y_pos_strand) { + y_s = uref->ug->u.a[o->y_id].len - p->e; + y_e = uref->ug->u.a[o->y_id].len - p->s - 1; + } else { + y_s = p->s; y_e = p->e - 1; + } + + + y_s = MAX(y_s, (int64_t)o->y_pos_s); y_e = MIN(y_e, (int64_t)o->y_pos_e); + if(y_s > y_e) return 0; + x_s = get_chain_x(o, y_s); x_e = get_chain_x(o, y_e) + 1; + if(x_s >= x_e) fprintf(stderr, "+++y_s->%ld, y_e->%ld, x_s->%ld, x_e->%ld\n", y_s, y_e, x_s, x_e); + if(o->y_pos_strand) { + y_bs = uref->ug->u.a[o->y_id].len - (y_e+1); + y_be = uref->ug->u.a[o->y_id].len - y_s; + } else { + y_bs = y_s; y_be = y_e + 1; + } + + q_s = 0; q_e = p->e - p->s; + if(p->x&1) { + q_s += (p->e - y_be); + q_e -= (y_bs - p->s); + } else { + q_s += (y_bs - p->s); + q_e -= (p->e - y_be); + } + // if(q_s < 0 || q_e < 0 || q_s >= (int64_t)(p->e - p->s) || q_e > (int64_t)(p->e - p->s)) fprintf(stderr, "ERROR\n"); + if(winLen > 0 && diff_ec_ul > 0 && es_win_err(o, winLen, x_s, x_e-1) > diff_ec_ul) return 0; + + ul_ov_t *x = NULL; + kv_pushp_km(km, ul_ov_t, *chains, &x); + x->qn = o->x_id; x->qs = x_s; x->qe = x_e; + + /**x->tn = p->x>>1;**/x->tn = (uint32_t)(0x80000000); x->tn |= (p->x>>1); + x->ts = q_s; x->te = q_e; x->el = 1;x->sec = 0; x->rev = ((o->y_pos_strand == (p->x&1))?0:1); + // if(((x->tn<<1)>>1) == 23113) fprintf(stderr, "x->tn:%u, o->y_id:%u\n", (x->tn<<1)>>1, o->y_id); + // if(x->qn == 0 /**&& ((x->tn<<1)>>1) == 302**/) { + // /**if(o->x_id == 0 && (o->y_id == 46 || o->y_id == 48))**/ { + // // fprintf(stderr, "\nUL[%u]\t%u\t%u\t%c\tUTG[%u]\t%u\t%u\n", o->x_id, o->x_pos_s, o->x_pos_e, + // // "+-"[o->y_pos_strand], o->y_id, o->y_pos_s, o->y_pos_e); + // // fprintf(stderr, "Contain[%u]\t%c\ts[%u]\te[%u]\n", p->x>>1, "+-"[p->x&1], p->s, p->e); + // fprintf(stderr, "U[%u]\t%u\t%u\t%c\tR[%u]\t%u\t%u\tUid[%u]\n", x->qn, x->qs, x->qe, + // "+-"[x->rev], ((x->tn<<1)>>1), x->ts, x->te, o->y_id); + // } + // } + + return 1; +} + +int64_t debug_utg_ct_t(const ul_idx_t *uref, overlap_region* o, utg_ct_t *ct_a, int64_t ct_n, ma_utg_t *u, utg_ct_t *z, haplotype_evdience *he_a, int64_t he_n) +{ + int64_t k, i, l, rs, re, ss, m = 0; + utg_ct_t *p = NULL; + if(ct_a && ct_n) { + for (i = 0; i < ct_n; i++) { + p = &(ct_a[i]); + for (k = 0; k < he_n; k++) { + ss = o->y_pos_strand?uref->ug->u.a[o->y_id].len - he_a[k].cov - 1:he_a[k].cov; + if(ss >= p->s && ss < p->e) break; + } + if(k < he_n) m++; + } + } + if(u) { + for (i = l = 0; i < u->n; i++) { + rs = l; re = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); + l += (uint32_t)u->a[i]; + for (k = 0; k < he_n; k++) { + ss = o->y_pos_strand?uref->ug->u.a[o->y_id].len - he_a[k].cov - 1:he_a[k].cov; + if(ss >= rs && ss < re) break; + } + if(k < he_n) m++; + } + } + + if(z) { + for (k = 0; k < he_n; k++) { + ss = o->y_pos_strand?uref->ug->u.a[o->y_id].len - he_a[k].cov - 1:he_a[k].cov; + if(ss >= z->s && ss < z->e) break; + } + if(k < he_n) m++; + } + return m; +} + +int64_t get_het_occ(haplotype_evdience *he_a, int64_t he_n, int64_t c_k, int64_t ylen, utg_ct_t *p, int64_t rev) +{ + int64_t k, occ = 0, ss; + if(!rev) { + for (k = c_k; k >= 0; k--) { + if(he_a[k].cov >= p->s && he_a[k].cov < p->e) { + occ++; + } else { + break; + } + } + + for (k = c_k+1; k < he_n; k++) { + if(he_a[k].cov >= p->s && he_a[k].cov < p->e) { + occ++; + } else { + break; + } + } + } else { + for (k = c_k; k >= 0; k--) { + ss = ylen - he_a[k].cov - 1; + if(ss >= p->s && ss < p->e) { + occ++; + } else { + break; + } + } + + for (k = c_k+1; k < he_n; k++) { + ss = ylen - he_a[k].cov - 1; + if(ss >= p->s && ss < p->e) { + occ++; + } else { + break; + } + } + } + + assert(occ); + return occ; +} + + +int64_t rescue_contain_ul_chains(const ul_idx_t *uref, overlap_region* o, haplotype_evdience *he_a, int64_t he_n, utg_ct_t *ct_a, int64_t ct_n, +kv_ul_ov_t *chains, double diff_ec_ul, int64_t winLen, int64_t rescue_trans, void *km) +{ + int64_t i, k, ss, ff, t0 = 0; + uint64_t ys, ye; + utg_ct_t *p = NULL; + // if(o->x_id == 0) { + // fprintf(stderr, "\no->y_id->%u\n", o->y_id); + // for (i = 0; i < ct_n; i++) { + // p = &(ct_a[i]); + // fprintf(stderr, "***rid->%u, rev->%u, s->%u, e->%u\n", p->x>>1, p->x&1, p->s, p->e); + // } + // } + + if(o->y_pos_strand == 0){ + ys = o->y_pos_s; ye = o->y_pos_e + 1; + for (i = k = 0; i < ct_n; i++) { + p = &(ct_a[i]); + if(p->e <= ys) continue; + if(p->s >= ye) break; + ff = 1; + if(he_a && he_n > 0) { + for (; k < he_n; k++) { + if(he_a[k].cov >= p->s && he_a[k].cov < p->e) { + ff = 0; + break; + } + if(he_a[k].cov >= p->e) break; + } + } + // if(ff == debug_utg_ct_t(uref, o, p, he_a, he_n)) fprintf(stderr, "ERROR\n"); + if(ff) { + ///push ovlp + t0 += gen_contain_chain(uref, p, o, chains, diff_ec_ul, winLen, km); + } else if(rescue_trans) { + if(gen_contain_chain(uref, p, o, chains, diff_ec_ul, winLen, km)){ + t0++; chains->a[chains->n-1].el = 0; + chains->a[chains->n-1].sec = get_het_occ(he_a, he_n, k, uref->ug->u.a[o->y_id].len, p, o->y_pos_strand); + } + } + // if(!ff) t0++; + } + + } else { + ys = uref->ug->u.a[o->y_id].len - (o->y_pos_e+1); + ye = uref->ug->u.a[o->y_id].len - o->y_pos_s; + for (i = 0, k = he_n - 1; i < ct_n; i++) { + p = &(ct_a[i]); + if(p->e <= ys) continue; + if(p->s >= ye) break; + ff = 1; + if(he_a && he_n > 0) { + for (; k >= 0; k--) { + ss = uref->ug->u.a[o->y_id].len - he_a[k].cov - 1; + if(ss >= p->s && ss < p->e) { + ff = 0; + break; + } + if(ss >= p->e) break; + } + } + // if(ff == debug_utg_ct_t(uref, o, p, he_a, he_n)) fprintf(stderr, "ERROR\n"); + if(ff) { + ///push ovlp + t0 += gen_contain_chain(uref, p, o, chains, diff_ec_ul, winLen, km); + } else if(rescue_trans) { + if(gen_contain_chain(uref, p, o, chains, diff_ec_ul, winLen, km)){ + t0++; chains->a[chains->n-1].el = 0; + chains->a[chains->n-1].sec = get_het_occ(he_a, he_n, k, uref->ug->u.a[o->y_id].len, p, o->y_pos_strand); + } + } + // if(!ff) t0++; + } + } + // if(debug_utg_ct_t(uref, o, ct_a, ct_n, he_a, he_n)!=t0) fprintf(stderr, "ERROR\n"); + // fprintf(stderr, "***[M::%s] o->y_id:%u, chains->n:%u\n", __func__, o->y_id, (uint32_t)chains->n); + return t0; +} + + +int64_t rescue_trans_ul_chains(const ul_idx_t *uref, overlap_region* o, haplotype_evdience *he_a, int64_t he_n, ma_utg_t *u, +kv_ul_ov_t *chains, double diff_ec_ul, int64_t winLen, int64_t rescue_trans, uint64_t *cis_occ, void *km) +{ + uint64_t ys, ye, i, l; + int64_t k, ff, ss, t0 = 0; + utg_ct_t p; + if(cis_occ) (*cis_occ) = 0; + + if(o->y_pos_strand == 0) { + ys = o->y_pos_s; ye = o->y_pos_e + 1; + for (i = k = l = 0; i < u->n; i++) { + p.x = u->a[i]>>32; p.s = l; p.e = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); + l += (uint32_t)u->a[i]; + if(p.e <= ys) continue; + if(p.s >= ye) break; + ff = 1; + if(he_a && he_n) { + for (; k < he_n; k++) { + if(he_a[k].cov >= p.s && he_a[k].cov < p.e) { + ff = 0; + break; + } + if(he_a[k].cov >= p.e) break; + } + } + // if(ff == debug_utg_ct_t(uref, o, 0, 0, 0, &p, he_a, he_n)) fprintf(stderr, "ERROR\n"); + if(ff) { + ///push ovlp + t0 += gen_contain_chain(uref, &p, o, chains, diff_ec_ul, winLen, km); + } else if(rescue_trans) { + if(gen_contain_chain(uref, &p, o, chains, diff_ec_ul, winLen, km)){ + t0++; chains->a[chains->n-1].el = 0; if(cis_occ) (*cis_occ)++; + chains->a[chains->n-1].sec = get_het_occ(he_a, he_n, k, uref->ug->u.a[o->y_id].len, &p, o->y_pos_strand); + } + } + // if(!ff) t0++; + } + } else { + ys = uref->ug->u.a[o->y_id].len - (o->y_pos_e+1); + ye = uref->ug->u.a[o->y_id].len - o->y_pos_s; + for (i = l = 0, k = he_n - 1; i < u->n; i++) { + p.x = u->a[i]>>32; p.s = l; p.e = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); + l += (uint32_t)u->a[i]; + if(p.e <= ys) continue; + if(p.s >= ye) break; + ff = 1; + if(he_a && he_n) { + for (; k >= 0; k--) { + ss = uref->ug->u.a[o->y_id].len - he_a[k].cov - 1; + if(ss >= p.s && ss < p.e) { + ff = 0; + break; + } + if(ss >= p.e) break; + } + } + // if(ff == debug_utg_ct_t(uref, o, 0, 0, 0, &p, he_a, he_n)) fprintf(stderr, "ERROR\n"); + if(ff) { + ///push ovlp + t0 += gen_contain_chain(uref, &p, o, chains, diff_ec_ul, winLen, km); + } else if(rescue_trans) { + if(gen_contain_chain(uref, &p, o, chains, diff_ec_ul, winLen, km)){ + t0++; chains->a[chains->n-1].el = 0; if(cis_occ) (*cis_occ)++; + chains->a[chains->n-1].sec = get_het_occ(he_a, he_n, k, uref->ug->u.a[o->y_id].len, &p, o->y_pos_strand); + } + } + // if(!ff) t0++; + } + } + // if(debug_utg_ct_t(uref, o, NULL, 0, u, he_a, he_n)!=t0) fprintf(stderr, "ERROR\n"); + // fprintf(stderr, "t0->%ld\n", t0); + return t0; +} + +int64_t dedup_sort_ul_ov_t(ul_ov_t *a, int64_t a_n) +{ + int64_t k, l, z, r, i, qo, to; float rr = 0.9; + for (k = 1, l = i = 0; k <= a_n; k++) { + if(k == a_n || a[k].tn != a[l].tn) {///remove the duplicated contained alignments + for (z = l; z < k; z++) { + for (r = i-1; r >= 0 && a[r].tn == a[z].tn; r--){ + /** + if(a[z].qn == a[r].qn && a[z].qs == a[r].qs && a[z].qe == a[r].qe && + a[z].tn == a[r].tn && a[z].ts == a[r].ts && a[z].te == a[r].te && + a[z].sec == a[r].sec && a[z].el == a[r].el && a[z].rev == a[r].rev) { + break; + } + **/ + if(a[z].qn == a[r].qn && a[z].tn == a[r].tn && a[z].rev == a[r].rev) { + qo = ((MIN(a[z].qe, a[r].qe) > MAX(a[z].qs, a[r].qs))? + MIN(a[z].qe, a[r].qe) - MAX(a[z].qs, a[r].qs):0); + to = ((MIN(a[z].te, a[r].te) > MAX(a[z].ts, a[r].ts))? + MIN(a[z].te, a[r].te) - MAX(a[z].ts, a[r].ts):0); + if(qo >= ((a[r].qe - a[r].qs)*rr) && qo >= ((a[z].qe - a[z].qs)*rr) && + to >= ((a[r].te - a[r].ts)*rr) && to >= ((a[z].te - a[z].ts)*rr)) { + break; + } + } + } + if(r >= 0 && a[r].tn == a[z].tn) { + if(a[z].el) a[r].el = 1; + continue; + } + a[i++] = a[z]; + } + l = k; + } + } + return i; +} + + +uint32_t check_contain_pair(const ug_opt_t *uopt, uint32_t x, uint32_t y, uint32_t check_el) +{ + ma_hit_t_alloc* src = uopt->sources; + int64_t min_ovlp = uopt->min_ovlp; + int64_t max_hang = uopt->max_hang; + uint64_t z, qn, tn; int32_t r = 1; asg_arc_t e; + for (z = 0; z < src[x].length; z++) { + if(check_el && (!src[x].buffer[z].el)) continue; + qn = Get_qn(src[x].buffer[z]); tn = Get_tn(src[x].buffer[z]); + if(tn != y) continue; + r = ma_hit2arc(&(src[x].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); + if(r == MA_HT_QCONT || r == MA_HT_TCONT) break; + } + + if(z < src[x].length) return 1; + return 0; +} + +void debug_contain_ovlps(ul_ov_t *a, uint64_t a_n, const ug_opt_t *uopt) +{ + uint64_t k, i, f; ul_ov_t *z = NULL, *w = NULL; + for (k = 0; k < a_n; k++) { + z = &(a[k]); + if(!(z->tn&((uint32_t)(0x80000000)))) continue; + for (i = 0, f = z->qn; i < a_n; i++) { + w = &(a[i]); + if(i == k) continue; + if(w->tn&((uint32_t)(0x80000000))) continue; + if(z->qs >= w->qs && z->qe <= w->qe && check_contain_pair(uopt, (z->tn<<1)>>1, w->tn, 1)) { + f = (uint32_t)-1; + break; + } + } + if(z->qn != f) fprintf(stderr, "ERROR\n"); + } +} + +ma_hit_t* query_ovlp_src(const ug_opt_t *uopt, uint32_t v, uint32_t w, int64_t o, double diff_ec_ul, uint32_t *ol) +{ + ma_hit_t_alloc* src = uopt->sources; + int64_t min_ovlp = uopt->min_ovlp; + int64_t max_hang = uopt->max_hang, d, l, max_l; + uint64_t z, qn, tn, x = v>>1; int32_t r = 1; asg_arc_t e; + l = (o>=0?o:-o); //l *= diff_ec_ul; + if(l <= 0) return NULL; + for (z = 0; z < src[x].length; z++) { + qn = Get_qn(src[x].buffer[z]); tn = Get_tn(src[x].buffer[z]); + if(tn != (w>>1)) continue; + r = ma_hit2arc(&(src[x].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); + if(r < 0) continue; + if((e.ul>>32) != v || e.v != w) continue; + // if(v == 56 && w == 25) fprintf(stderr, "+xxxx, o:%ld, e.ol:%u\n", o, e.ol); + // if(v == 25 && w == 56) fprintf(stderr, "-xxxx, o:%ld, e.ol:%u\n", o, e.ol); + d = (o>=e.ol?o-e.ol:e.ol-o); + max_l = MAX(l, e.ol); + if(d <= (max_l*diff_ec_ul)) { + if(ol) (*ol) = e.ol; + return &(src[x].buffer[z]); + } + } + return NULL; +} + +void debug_infer_read_ovlp(const ug_opt_t *uopt, double diff_ec_ul, ul_ov_t *li, ul_ov_t *lj, ma_utg_t *u, +uint32_t i_idx, uint32_t j_idx, All_reads *ridx, ma_ug_t *ug) +{ + uint32_t li_v, lj_v; ma_hit_t *t = NULL; + li_v = (((uint32_t)(li->tn))<<1)|((uint32_t)(li->rev)); + lj_v = (((uint32_t)(lj->tn))<<1)|((uint32_t)(lj->rev)); + if(lj->qe <= li->qs || li_v == lj_v) fprintf(stderr, "ERROR-1\n"); + t = query_ovlp_src(uopt, li_v^1, lj_v^1, infer_rovlp(li, lj, NULL, NULL, ridx, ug), diff_ec_ul, NULL); + // ((int64_t)(lj->qe))-((int64_t)(li->qs)) + if(!t /**&& (li_v^1) == 648 && (lj_v^1) == 638 && li->qs == 63841**/) { + fprintf(stderr, "ERROR-2, li_v^1->%u, li->qs->%u, li->qe->%u, lj_v^1->%u, lj->qs->%u, lj->qe->%u, infer_rovlp->%ld\n", + li_v^1, li->qs, li->qe, lj_v^1, lj->qs, lj->qe, infer_rovlp(li, lj, NULL, NULL, ridx, ug)); + } +} + +uint64_t infer_read_ovlp(const ul_idx_t *uref, overlap_region_alloc* olist, kv_ul_ov_t *in, kv_ul_ov_t *res, double diff_ec_ul, int64_t winLen, const ug_opt_t *uopt, ul_contain *ct, void *km) +{ + uint64_t t, k, l, t_0, pb, cut = res->n, c_occ = 0;; + ma_ug_t *ug = uref->ug; + ma_utg_t *u = NULL; + overlap_region* o = NULL; + ul_ov_t *z = NULL; + utg_ct_t p; + // res->n = 0; + for (t = 0; t < in->n; t++) { + if(!(in->a[t].tn&(uint32_t)(0x80000000))) {///uid + u = &(ug->u.a[in->a[t].tn]); o = &(olist->list[in->a[t].qn]); + assert(o->y_id == in->a[t].tn); + for (k = l = 0, pb = res->n+2; k < u->n; k++) { + p.x = u->a[k]>>32; + p.s = l; p.e = l + Get_READ_LENGTH(R_INF, (u->a[k]>>33)); + l += (uint32_t)u->a[k]; + if(p.e <= in->a[t].ts) continue; + if(p.s >= in->a[t].te) break; + t_0 = gen_contain_chain(uref, &p, o, res, -1, -1, km); + assert(t_0 > 0); + // if(t_0 == 0) { + // fprintf(stderr, "ERROR-2, o->x_id:%u, o->y_id:%u, k:%lu, u->n:%lu, p.s:%u, p.e:%u, ts:%u, te:%u, rev:%u\n", + // o->x_id, o->y_id, k, (uint64_t)u->n, p.s, p.e, in->a[t].ts, in->a[t].te, in->a[t].rev); + // } + res->a[res->n-1].el = in->a[t].el; + res->a[res->n-1].sec = in->a[t].sec; + res->a[res->n-1].tn <<= 1; + res->a[res->n-1].tn >>= 1; + res->a[res->n-1].qn = o->x_id; + if(res->n >= pb) { + if(in->a[t].rev == 0) { + // if(res->a[res->n-1].qs > res->a[res->n-2].qe) fprintf(stderr, "ERROR-3\n"); + if(!(res->a[res->n-2].qs<=res->a[res->n-1].qs && res->a[res->n-1].qs <= res->a[res->n-2].qe + && res->a[res->n-2].qe <= res->a[res->n-1].qe)) { + fprintf(stderr, "ERROR-3\n"); + } + // if(res->a[res->n-1].qs == res->a[res->n-2].qe) { + // if(res->a[res->n-2].qe < in->a[t].qe) res->a[res->n-2].qe++; + // else if(res->a[res->n-1].qs > 0) res->a[res->n-1].qs--; + // } + } else { + if(!(res->a[res->n-1].qs<=res->a[res->n-2].qs && res->a[res->n-2].qs <= res->a[res->n-1].qe + && res->a[res->n-1].qe <= res->a[res->n-2].qe)) { + fprintf(stderr, "ERROR-4\n"); + } + } + + // debug_infer_read_ovlp(uopt, diff_ec_ul, + // in->a[t].rev?&(res->a[res->n-2]):&(res->a[res->n-1]), + // in->a[t].rev?&(res->a[res->n-1]):&(res->a[res->n-2]), u, k, k-1); + } + } + } else {///rid + kv_push(ul_ov_t, *res, in->a[t]); + // res->a[res->n-1].tn <<= 1; + // res->a[res->n-1].tn >>= 1; + res->a[res->n-1].qn = o->x_id; + c_occ++; + } + } + if(res->n != cut) { + radix_sort_ul_ov_srt_qe(res->a + cut, res->a + res->n); + if(c_occ) { + int64_t ci, cn = cut; + for (k = cut; k < res->n; k++) { + z = &(res->a[k]); + if(z->tn&((uint32_t)(0x80000000))) continue; + if(ct->is_c.a[z->tn] == 0) continue; + + for (ci = k+1; ci < (int64_t)(res->n); ci++) { + if(res->a[ci].qe > z->qe) break; + if(res->a[ci].qn == (uint32_t)-1) continue; + if(!(res->a[ci].tn&((uint32_t)(0x80000000)))) continue; + if(z->qs <= res->a[ci].qs && z->qe >= res->a[ci].qe) { + if(check_contain_pair(uopt, (res->a[ci].tn<<1)>>1, z->tn, 1)) { + res->a[ci].qn = (uint32_t)-1; + } + } + } + + for (ci = k-1; ci >= cn; ci--) { + if(res->a[ci].qe <= z->qs) break; + if(res->a[ci].qn == (uint32_t)-1) continue; + if(!(res->a[ci].tn&((uint32_t)(0x80000000)))) continue; + if(z->qs <= res->a[ci].qs && z->qe >= res->a[ci].qe) { + if(check_contain_pair(uopt, (res->a[ci].tn<<1)>>1, z->tn, 1)) { + res->a[ci].qn = (uint32_t)-1; + } + } + } + } + + // debug_contain_ovlps(res->a+cut, res->n-cut, uopt); + + for (k = l = cut; k < res->n; k++) { + if(res->a[k].qn == (uint32_t)-1) continue; + if(k != l) { + res->a[l] = res->a[k]; + } + res->a[l].tn <<= 1; res->a[l].tn >>= 1; + ++l; + } + res->n = l; + } + } + + return res->n - cut; +} + + +int64_t gl_chain_refine(overlap_region_alloc* olist, Correct_dumy* dumy, haplotype_evdience_alloc *hap, glchain_t *ll, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, int64_t qlen, const ug_opt_t *uopt, void *km) +{ + ll->tk.n = ll->lo.n = 0; + kv_ul_ov_t *idx = &(ll->lo); + ul_contain *ct = uref->ct; + gl_chain_gen(olist, uref, idx, 0, hap, km); + if(idx->n == 0) return 0; + kv_resize_km(km, ul_ov_t, ll->tk, idx->n); + kv_resize_km(km, uint64_t, ll->srt.a, idx->n); + kv_resize_km(km, uint64_t, hap->snp_srt, idx->n); + if(gl_exact_chain(idx, &(ll->tk), uref, G_CHAIN_BW, diff_ec_ul, qlen, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, km)) { + kv_ul_ov_t *chains = &(ll->tk); ul_ov_t *p = NULL; + uint64_t k, z, ff, s, e, an, cn, sft = 50, si = 0, ei = 0, resc = 0, chains_pl = chains->n; + radix_sort_ul_ov_srt_qs(idx->a, idx->a + idx->n); + for (k = 0; k < olist->length; k++) { + if(olist->list[k].is_match!=2) continue; + + s = olist->list[k].x_pos_s; e = olist->list[k].x_pos_e+1; + for (z = ff = 0; z < idx->n; z++) { + if((s+sft) >= idx->a[z].qs && e <= (idx->a[z].qe+sft)) { + ff = 1; + break; + } + if(idx->a[z].qs >= (e+sft)) break; + } + cn = ((uint32_t)(ct->idx.a[olist->list[k].y_id])); + if(ff && cn==0) continue; + an = update_ava_het_site(hap, k, &si, &ei, cn); + // if(an != get_het_site(hap, k)) fprintf(stderr, "an->%lu, get_het_site->%lu\n", an, get_het_site(hap, k)); + + if(cn > 0 && an > 0) { + resc += rescue_contain_ul_chains(uref, &(olist->list[k]), hap->list+si, an, + ct->rids.a + ((ct->idx.a[olist->list[k].y_id])>>32), cn, chains, diff_ec_ul, winLen, 0, km); + } + + if(ff == 0) { + kv_pushp_km(km, ul_ov_t, *chains, &p); + p->qn = k/**olist->list[k].x_id**/; p->qs = olist->list[k].x_pos_s; p->qe = olist->list[k].x_pos_e+1; + p->tn = olist->list[k].y_id; p->el = 0; p->sec = (an&((uint64_t)0x3FFFFFFF))/**get_het_site(hap, k)**/; + p->rev = olist->list[k].y_pos_strand; + if(p->rev) { + p->ts = uref->ug->u.a[p->tn].len - (olist->list[k].y_pos_e+1); + p->te = uref->ug->u.a[p->tn].len - olist->list[k].y_pos_s; + } else { + p->ts = olist->list[k].y_pos_s; + p->te = olist->list[k].y_pos_e+1; + } + + } + si = ei; + } + + if(resc > 0) { + radix_sort_ul_ov_srt_tn(chains->a + chains_pl, chains->a + chains->n); + ff = dedup_sort_ul_ov_t(chains->a + chains->n - resc, resc); + chains->n = chains->n - resc + ff; + } + } + + if(ll->tk.n > 0) infer_read_ovlp(uref, olist, &(ll->tk), &(ll->lo), diff_ec_ul, winLen, uopt, ct, km); + else ll->lo.n = 0; + return 1; +} + + +/** +void fill_edge_weight(ul_ov_t *a, int64_t a_n, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, int64_t qlen) +{ + uint32_t li_v, lj_v; + ul_ov_t *li = NULL, *lj = NULL; + int64_t mm_ovlp, x, i, j, o; + ma_hit_t *t = NULL; + for (i = 0; i < a_n; i++) { + li = &(a[i]); li_v = (li->tn<<1)|li->rev; + mm_ovlp = max_ovlp_src(uopt, li_v^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(i, a, x); + for (j = x; j >= 0; --j) { // collect potential destination vertices + lj = &(a[j]); lj_v = (lj->tn<<1)|lj->rev; + if(lj->qe <= li->qs) break; + if(li_v == lj_v) continue; + t = query_ovlp_src(uopt, li_v, lj_v, ((int64_t)(lj->qe))-((int64_t)(li->qs)), diff_ec_ul); + if(t) { + t->bl; + } + } + } + + +} +**/ + +int64_t get_ecov_adv_back(const ul_idx_t *uref, const ug_opt_t *uopt, uint32_t v, uint32_t w, int64_t bw, double diff_ec_ul, int64_t dq, uint32_t *is_contain) +{ + int64_t dt = -1, dif, mm; if(is_contain) (*is_contain) = 0; + const asg_t *g = uref?uref->ug->g:NULL; + uint32_t nv, i; asg_arc_t *av = NULL; + if(g) { + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (i = 0; i < nv; i++) { + if(av[i].del || av[i].v != w) continue; + dt = av[i].ol; + break; + } + } + + if(dt < 0 && uopt) { + ma_hit_t_alloc* src = uopt->sources; + int64_t min_ovlp = uopt->min_ovlp; + int64_t max_hang = uopt->max_hang; + uint64_t z, qn, tn, x = v>>1; int32_t r = 1; asg_arc_t e; + for (z = 0; z < src[x].length; z++) { + qn = Get_qn(src[x].buffer[z]); tn = Get_tn(src[x].buffer[z]); + if(tn != (w>>1)) continue; + r = ma_hit2arc(&(src[x].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); + if(r < 0) { + if(r == MA_HT_QCONT || r == MA_HT_TCONT) { + if(src[x].buffer[z].rev == ((uint32_t)(v^w))) { + dt = Get_qe(src[x].buffer[z]) - Get_qs(src[x].buffer[z]); + if(dt < Get_te(src[x].buffer[z]) - Get_ts(src[x].buffer[z])) { + dt = Get_te(src[x].buffer[z]) - Get_ts(src[x].buffer[z]); + } + if(is_contain) (*is_contain) = 1; + break; + } + } + continue; + } + if((e.ul>>32) != v || e.v != w) continue; + dt = e.ol; + break; + } + } + if(dt < 0) return 0; + dif = (dq>dt? dq-dt:dt-dq); + mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; + // if((v>>1) == 1163 && (w>>1) == 1168) fprintf(stderr, ">>>>>>dis_q:%ld, dis_t:%ld, dif:%ld, mm:%ld\n", dis_q, dis_t, dif, mm); + if(dif <= mm) return 1; + return 0; +} + +ma_hit_t *get_ug_edge_src(ma_ug_t *ug, ma_hit_t_alloc *src, int64_t max_hang, int64_t min_ovlp, uint32_t uv, uint32_t uw) +{ + if(ug->u.a[uv>>1].circ || ug->u.a[uw>>1].circ) return NULL; + uint32_t v, w, k, qn, tn; int32_t r; asg_arc_t t; + v = ((uv&1)?(ug->u.a[uv>>1].start^1):(ug->u.a[uv>>1].end^1)); + w = ((uw&1)?(ug->u.a[uw>>1].end):(ug->u.a[uw>>1].start)); + ma_hit_t_alloc *x = &(src[v>>1]); + + for (k = 0; k < x->length; k++) { + qn = Get_qn(x->buffer[k]); + tn = Get_tn(x->buffer[k]); + if(qn == (v>>1) && tn == (w>>1)) { + r = ma_hit2arc(&(x->buffer[k]), Get_READ_LENGTH(R_INF, v>>1), Get_READ_LENGTH(R_INF, w>>1), + max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + if(r < 0) continue; + if((t.ul>>32)!=v || t.v!=w) continue; + return &(x->buffer[k]); + } + } + + return NULL; +} + +///mode: 0->ug; 1->read +int64_t get_ecov_adv(const ul_idx_t *uref, const ug_opt_t *uopt, uint32_t v, uint32_t w, int64_t bw, double diff_ec_ul, int64_t dq, uint64_t mode, int64_t *contain_off) +{ + int64_t dt = -1, dif, mm; if(contain_off) (*contain_off) = 0; + uint32_t nv, i; asg_arc_t *av = NULL; ma_hit_t *x = NULL; + if(!mode) { + const asg_t *g = uref?uref->ug->g:NULL; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (i = 0; i < nv; i++) { + if(av[i].del || av[i].v != w) continue; + dt = av[i].ol; + // if((v>>1)==25288) fprintf(stderr, "+++v:%u, w:%u, ou:%ld\n", v, w, dt); + // if((v>>1) == 3012 && (w>>1) == 3011) fprintf(stderr, "******************\n"); + if(contain_off) { + (*contain_off) = av[i].ou; + if(av[i].ou >= OU_MASK) { + x = get_ug_edge_src(uref->ug, uopt->sources, uopt->max_hang, uopt->min_ovlp, + av[i].ul>>32, av[i].v); + (*contain_off) = x->cc; + // if(v==1772 && w==1769) fprintf(stderr, "---v:%u, w:%u, cc:%u\n", v, w, x->cc); + } + } + break; + } + }else { + ma_hit_t_alloc* src = uopt->sources; + int64_t min_ovlp = uopt->min_ovlp; + int64_t max_hang = uopt->max_hang; + uint64_t z, qn, tn, x = v>>1; int32_t r = 1; asg_arc_t e; + for (z = 0; z < src[x].length; z++) { + qn = Get_qn(src[x].buffer[z]); tn = Get_tn(src[x].buffer[z]); + if(tn != (w>>1)) continue; + r = ma_hit2arc(&(src[x].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); + if(r < 0) continue; + if((e.ul>>32) != v || e.v != w) continue; + dt = e.ol; if(contain_off) (*contain_off) = src[x].buffer[z].cc; + break; + } + } + if(dt < 0) return 0; + dif = (dq>dt? dq-dt:dt-dq); + mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; + // if((v>>1) == 1163 && (w>>1) == 1168) fprintf(stderr, ">>>>>>dis_q:%ld, dis_t:%ld, dif:%ld, mm:%ld\n", dis_q, dis_t, dif, mm); + if(dif <= mm) return 1; + return 0; +} + +void get_rr_tse(const ul_idx_t *uref, ul_ov_t *li, uint32_t *ts, uint32_t *te, uint32_t *tl) +{ + (*tl) = uref?uref->ug->g->seq[li->tn].len:Get_READ_LENGTH(R_INF, li->tn); + if(!(li->rev)) { + (*ts) = li->ts; (*te) = li->te; + } else { + (*ts) = (*tl) - li->te; (*te) = (*tl) - li->ts; + } +} +/** +uint32_t checkM(uint32_t v, uint32_t l, const ul_idx_t *uref, const asg_t *g, uint32_t in, uint32_t its, +uint32_t iqs, uint32_t iqe, int64_t bw, double diff_ec_ul, int64_t qlen, ul_ov_t *a, uint32_t a_n) +{ + int64_t vl = uref?uref->ug->g->seq[v>>1].len:Get_READ_LENGTH(R_INF, (v>>1)), t_dis, q_dis, kcs, mm_ovlp, x, k; + t_dis = ((int64_t)(l + vl)) - ((int64_t)(in - its)); + kcs = iqs; kcs -= t_dis; if(kcs < 0) kcs = 0; + uint32_t nv = asg_arc_n(g, v), i, lk_v, kts, kte, kn; + asg_arc_t *av = asg_arc_a(g, v), *p = NULL; mm_ovlp = -1; ul_ov_t *lk; + for (i = 0, p = NULL; i < nv; i++) { + if(av[i].del) continue; + if((int32_t)(av[i].ol) > mm_ovlp) { + p = &(av[i]); mm_ovlp = av[i].ol; + } + } + if(!p) return 0; + + x = (kcs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += kcs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(a_n, a, x); + for (k = x; k >= 0; --k) { + lk = &(a[k]); lk_v = ((lk->tn<<1)|lk->rev)^1; + if(lk->qe <= kcs) break;//evan this pair has a overlap, its length will be very small; just ignore + if(lk->qs >= kcs) continue; // lk is contained in li on the query coordinate + + get_rr_tse(uref, lk, &kts, &kte, &kn); + ///t_dis and q_dis might be < 0 + t_dis = ((int64_t)(l + kn - kte)) - ((int64_t)(in - its)); + q_dis = ((int64_t)(iqs)) - ((int64_t)(lk->qe)); + } + +} + +void best_path_ext(const ul_idx_t *uref, const ug_opt_t *uopt, int64_t g_gap, ul_ov_t *a, uint32_t a_n, +int64_t bw, double diff_ec_ul, uint64_t *track, ul_ov_t *li) +{ + if(a_n <= 0) return; + const asg_t *g = uref?uref->ug->g:NULL; asg_arc_t *av = NULL, *p = NULL; ul_ov_t *lk; + uint32_t nv, i, v, io, in, its, ite, kn, kts, kte; int64_t mm, l, max_dist, k, t_dis, q_dis; + + get_rr_tse(uref, li, &its, &ite, &in); + io = in - ite; max_dist = g_gap + in - its; + + if(g) { + v = (((li->tn<<1)|li->rev)^1); mm = 1; l = 0; + while (mm >= 0) { + + + + + + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); mm = -1; + for (i = 0, p = NULL; i < nv; i++) { + if(av[i].del) continue; + if((int32_t)(av[i].ol) > mm) { + p = &(av[i]); mm = av[i].ol; + } + } + if(p) { + l += (uint32_t)(p->ul); + if(l > max_dist) break; + for (k = a_n-1; k >= 0; k--) { + lk = &(a[k]); + if((lk->qe+g_gap) <= li->qs) break; + if(p->v == (((lk->tn<<1)|lk->rev)^1)) { + ///check if lk can be directly reachedc from li + if(lk->qe > li->qs && (track[k]&((uint64_t)0x80000000))) { + ; + } + get_rr_tse(uref, lk, &kts, &kte, &kn); + ///t_dis and q_dis might be < 0 + t_dis = ((int64_t)(l + kn - kte)) - ((int64_t)(in - its)); + q_dis = ((int64_t)(li->qs)) - ((int64_t)(lk->qe)); + } + } + v = p->v; + } + } + } +} + + +int64_t gl_chain_advance(kv_ul_ov_t *res, ul_ov_t *ex, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, int64_t max_skip, uint64_t *srt, uint64_t *idx, uint64_t *track, float trav_rate, void *km) +{ + uint32_t li_v, lj_v, rev_n, gapLen = (trav_rate>0?trav_rate*qlen:0); + int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, qo, n_skip, n_all; + ul_ov_t *li = NULL, *lj = NULL, rev_t; + radix_sort_ul_ov_srt_qe(res->a, res->a + res->n); + for (i = 0; i < (int64_t)res->n; ++i) { + li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; + // if(!(li->el)) continue; + mm_ovlp = uref?max_ovlp(uref->ug->g, li_v^1):max_ovlp_src(uopt, li_v^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(i, res->a, x); + if(li->el) { + csc = uref?retrieve_u_cov_region(uref, li->tn, 0, li->ts, li->te, NULL):li->te-li->ts; + } else { + csc = -1;///for cis overlap, the csc should be >1000; so -1 for trans overlaps should be fine + } + mm_sc = csc; mm_idx = -1; n_skip = n_all = 0; + for (j = x; j >= 0; --j) { // collect potential destination vertices + lj = &(res->a[j]); lj_v = (lj->tn<<1)|lj->rev; + // if((lj->qe+gapLen) <= li->qs) break; + if(lj->qe <= li->qs) break;//evan this pair has a overlap, its length will be very small; just ignore + if(lj->qs >= li->qs) continue; // lj is contained in li on the query coordinate + qo = infer_rovlp(li, lj, NULL, NULL); ///overlap length in query (UL read) + if(li_v != lj_v && get_ecov_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo)) { + sc = csc + (track[j]>>32); + if(sc > mm_sc) mm_sc = sc, mm_idx = j; + if(res->a[j].sec == i && res->a[j].el) n_skip++; + if((track[j]&((uint64_t)0x7FFFFFFF)) != ((uint64_t)0x7FFFFFFF)) { + res->a[(track[j]&((uint64_t)0x7FFFFFFF))].sec = i; + } + track[j] |= ((uint64_t)0x80000000); + } else { + if(track[j]&((uint64_t)0x80000000)) track[j] -= ((uint64_t)0x80000000); + } + n_all++; + } + + if(n_all > max_skip) n_all = max_skip; + else n_all -= 2; //allow one mismatch; note here must be -2 + + if(li->el && (mm_idx<0 || n_skip0?trav_rate*qlen*li->el:0); + if(gapLen > 0) { + // if((lj->qe+gapLen) <= li->qs) break; + ///since graph traversal just has one path, so this step might be quite easy + + best_path_ext(uref, uopt, gapLen, res->a, x+1, bw, diff_ec_ul, li); + } + } + // 4294967295L + track[i] = mm_sc; track[i] <<= 32; + track[i] |= (mm_idx>=0?mm_idx:((uint64_t)0x7FFFFFFF)); + srt[i] = mm_sc; srt[i] <<= 32; srt[i] |= i; + // fprintf(stderr, "+++i:%ld, mm_idx:%ld, mm_sc:%ld\n", i, mm_idx, mm_sc); + // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n\n", li->tn+1, "lc"[uref->ug->u.a[li->tn].circ], li->qs, li->qe); + } + + for (i = 0; i < (int64_t)res->n; ++i) { + if(track[i]&((uint64_t)0x80000000)) track[i] -= ((uint64_t)0x80000000); + } + + int64_t n_v, n_u, n_v0; + radix_sort_gfa64(srt, srt+res->n); //ex->n = res->n; + for (k = (int64_t)res->n-1, n_v = n_u = 0; k >= 0; --k) { + // fprintf(stderr, "\nk:%ld\n", k); + n_v0 = n_v; + for (i = (uint32_t)srt[k]; i >= 0 && (track[i]&((uint64_t)0x80000000)) == 0;) { + ex[n_v++] = res->a[i]; track[i] |= ((uint64_t)0x80000000); + // fprintf(stderr, "+i:%ld, ", i); + // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n", res->a[i].tn+1, "lc"[uref->ug->u.a[res->a[i].tn].circ], res->a[i].qs, res->a[i].qe); + if((track[i]&((uint64_t)0x7FFFFFFF)) == ((uint64_t)0x7FFFFFFF)) i = -1; + else i = track[i]&((uint64_t)0x7FFFFFFF); + } + if(n_v0 == n_v) continue; + ///keep the whole score; do not cut score like minigraph + sc = (i<0?(srt[k]>>32):((srt[k]>>32)-(track[i]>>32))); + // sc = srt[k]>>32; + idx[n_u++] = ((uint64_t)sc<<32)|(n_v-n_v0); + } + + for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { + n_v0 = n_v; n_v += (uint32_t)idx[k]; + res->a[k].qn = idx[k]>>32; + res->a[k].ts = n_v0; res->a[k].te = n_v; + + rev_n = ((uint32_t)idx[k])>>1; + ///we need to consider contained reads; so determining qs is not such easy + res->a[k].qs = (uint32_t)-1; res->a[k].qe = ex[n_v0].qe; + for (i = 0; i < rev_n; i++) { + rev_t = ex[n_v0+i]; + ex[n_v0+i] = ex[n_v0+rev_n-i-1]; + ex[n_v0+rev_n-i-1] = rev_t; + if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; + if(res->a[k].qs > ex[n_v0+rev_n-i-1].qs) res->a[k].qs = ex[n_v0+rev_n-i-1].qs; + } + if(i < ((uint32_t)idx[k]) && res->a[k].qs < ex[n_v0+i].qs) { + res->a[k].qs = ex[n_v0+i].qs; + } + } + res->n = n_u; + return res->n; +} +**/ + +int64_t determine_containment_chain(const ug_opt_t *uopt, uint64_t *track, uint64_t *flag, kv_ul_ov_t *res, int32_t nc, int64_t *nsc, int64_t mm_idx, int64_t bw, double diff_ec_ul, uint32_t el, All_reads *ridx, ma_ug_t *ug) +{ + int64_t i, k, pk, ak, e, off = 128, qo, tt = 0, ii; ul_ov_t *li = NULL, *lk = NULL; + uint32_t li_v, lk_v, is_c; + if(nc<=0) return 0; + for (k = tt = ak = 0; k < nc; k++) { + if(!(flag[res->a[k].sec]&((uint64_t)0x80000000))) { + flag[res->a[k].sec] |= ((uint64_t)0x80000000); tt++; + } else { + res->a[ak++].sec = res->a[k].sec; + } + } + if(tt==nc) return nsc[0] - nsc[1]; + assert(ak>0); + e = res->a[res->a[ak-1].sec].qe;//e is the smallest qe + for (i = mm_idx, pk = 0; i >= 0;) {///i++, li->qe-- + li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; + if((track[i]&((uint64_t)0x7FFFFFFF)) == ((uint64_t)0x7FFFFFFF)) i = -1; + else i = track[i]&((uint64_t)0x7FFFFFFF); + if(li->qe + off < e || tt == nc) break;//128 is used to tolerate indels; + for (k = pk, ii = 0; k < ak; k++) {///k++, lk->qe-- + if(res->a[k].sec == ((uint32_t)0x3FFFFFFF)) continue; + lk = &(res->a[res->a[k].sec]); lk_v = (lk->tn<<1)|lk->rev; + if(li->qe + off >= lk->qe) { + if(ii == 0) pk = k; + if(li->qs <= lk->qs + off) { + qo = infer_rovlp(li, lk, NULL, NULL, ridx, ug); ///overlap length in query (UL read) + if(li_v != lk_v && get_ecov_adv_back(NULL, uopt, li_v^1, lk_v^1, bw, diff_ec_ul, qo, &is_c)) { + if(is_c) { + tt++; res->a[k].sec = ((uint32_t)0x3FFFFFFF); + if(el) nsc[0] -= ((int64_t)(lk->te-lk->ts)); + else nsc[!(lk->el)] -= ((int64_t)(lk->te-lk->ts)); + } + } + } + ii = 1; + } + } + } + + assert(nsc[0]>=0 && nsc[1]>=0); + return nsc[0] - nsc[1]; +} + +uint64_t push_sc_pre(int64_t mm_sc, int64_t mm_idx) +{ + uint32_t sc = (mm_sc>=0?(((uint32_t)(mm_sc))|((uint32_t)(0x80000000))):((uint32_t)(-mm_sc))); + uint64_t x = sc; x <<= 32; x |= (mm_idx>=0?mm_idx:((uint64_t)0x7FFFFFFF)); + return x; +} + +int64_t pop_sc(uint64_t x) +{ + int64_t sc; + x >>= 32; + if(x&((uint64_t)(0x80000000))) { + sc = x - ((uint64_t)(0x80000000)); + } else { + sc = x; sc *= -1; + } + return sc; +} + +int64_t pop_pre(uint64_t x) +{ + if((x&((uint64_t)0x7FFFFFFF)) == ((uint64_t)0x7FFFFFFF)) return -1; + else return (x&((uint64_t)0x7FFFFFFF)); +} + +///mode: 0->ug; 1->read +int64_t gl_chain_advance(kv_ul_ov_t *res, ul_ov_t *ex, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, int64_t max_skip, uint64_t *srt, uint64_t *idx, uint64_t *track, int64_t trans_sc, +uint64_t mode, All_reads *ridx, ma_ug_t *ug, int64_t debug_i, void *km) +{ + // fprintf(stderr, "\n+++[M::%s] res->n:%u\n", __func__, (uint32_t)res->n); + if(res->n == 0) return 0; + uint32_t li_v, lj_v, rev_n; + int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, qo, share, n_el = 0; + ul_ov_t *li = NULL, *lj = NULL, rev_t; + radix_sort_ul_ov_srt_qe(res->a, res->a + res->n); + for (i = 1, j = 0; i <= (int64_t)res->n; i++) { + if (i == (int64_t)res->n || res->a[i].qe != res->a[j].qe) { + if(i - j > 1) { + radix_sort_ul_ov_srt_qs(res->a+j, res->a+i); + } + j = i; + } + } + for (i = 0; i < (int64_t)res->n; ++i) { + li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; + mm_ovlp = mode?max_ovlp_src(uopt, li_v^1):max_ovlp(uref->ug->g, li_v^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(i, res->a, x+G_CHAIN_INDEL); + if(li->el) csc = mode?retrieve_r_cov_region(uref, li->tn, 0, li->ts, li->te, NULL):retrieve_u_cov_region(uref, li->tn, 0, li->ts, li->te, NULL); + else csc = (trans_sc*li->sec); //trans overlaps + mm_sc = csc; mm_idx = -1; + // if(i == 37 || i == 36 || i == 35 || i == 32) fprintf(stderr, "*i:%ld, x:%ld, mm_sc:%ld\n", i, x, mm_sc); + for (j = x; j >= 0; --j) { // collect potential destination vertices + lj = &(res->a[j]); lj_v = (lj->tn<<1)|lj->rev; + // if((lj->qe+gapLen) <= li->qs) break; + if(lj->qe+G_CHAIN_INDEL <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore + // if(lj->qs >= li->qs+G_CHAIN_INDEL) continue; // lj is contained in li on the query coordinate; 128 for indel offset + if(lj->qs >= li->qs) continue; + qo = infer_rovlp(li, lj, NULL, NULL, ridx, ug); ///overlap length in query (UL read) + // if(i == 37 || i == 36 || i == 35 || i == 32) fprintf(stderr, ">i:%ld, j:%ld, qo:%ld\n", i, j, qo); + if(li_v != lj_v && get_ecov_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, mode, &share)) { + // if(i == 37 || i == 36 || i == 35 || i == 32) fprintf(stderr, "#i:%ld, j:%ld, share:%ld\n", i, j, share); + sc = csc + pop_sc(track[j]); + // if((!mode)&&i==11&&j==10) { + // fprintf(stderr,"+share:%ld, i:%ld, j:%ld, li_v^1:%u, lj_v^1:%u\n", + // share, i, j, li_v^1, lj_v^1); + // } + // if((mode&&i==21&&j==20) || (mode&&i==22&&j==21) || (mode&&i==23&&j==22)) { + // fprintf(stderr,"-share:%ld, i:%ld, j:%ld, li_v^1:%u, lj_v^1:%u\n", + // share, i, j, li_v^1, lj_v^1); + // } + if(li->el && lj->el) sc -= (share>=csc?csc:share);///csc must be larger than 0 + // if((!li->el) && (!lj->el)) sc -= ((share>=o_csc?o_csc:share)*(-trans_scl)); + if(sc > mm_sc) mm_sc = sc, mm_idx = j; + } + } + + track[i] = push_sc_pre(mm_sc, mm_idx); + srt[i] = track[i]>>32; srt[i] <<= 32; srt[i] |= i; + n_el += li->el; + + // if(mode) { + // fprintf(stderr, "[M::%.*s] i:%ld, li->el:%u, li->score:%ld (raw_sc:%u), mm_idx:%ld, mm_sc:%ld, q[%u, %u), t[%u, %u), rev:%c\n", + // (int32_t)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), i, li->el, csc, li->te - li->ts, mm_idx, mm_sc, li->qs, li->qe, li->ts, li->te, "+-"[li->rev]); + // } else { + // fprintf(stderr, "[M::utg%.6u%c] i:%ld, li->el:%u, li->score:%ld (raw_sc:%u), mm_idx:%ld, mm_sc:%ld, q[%u, %u), t[%u, %u), rev:%c\n", + // li->tn+1, "lc"[uref->ug->u.a[li->tn].circ], i, li->el, csc, li->te - li->ts, mm_idx, mm_sc, li->qs, li->qe, li->ts, li->te, "+-"[li->rev]); + // } + // if(!mode) { + // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n", li->tn+1, "lc"[uref->ug->u.a[li->tn].circ], li->qs, li->qe); + // } + // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u; sc->%ld; pre->%ld; el->%u;\n", + // li->tn+1, "lc"[uref->ug->u.a[li->tn].circ], li->qs, li->qe, pop_sc(track[i]), pop_pre(track[i]), li->el); + } + + int64_t n_v, n_u, n_v0, le, lnv; + radix_sort_gfa64(srt, srt+res->n); + for (k = (int64_t)res->n-1, n_v = n_u = 0; k >= 0; --k) { + n_v0 = n_v; i = (uint32_t)srt[k]; + // fprintf(stderr, "+[M::utg%.6d%c] n_v0->%ld;\n", res->a[i].tn+1, "lc"[uref->ug->u.a[res->a[i].tn].circ], n_v0); + if(res->a[i].el) { ///chain must start from cis alignments + for (le = -1; i >= 0 && (track[i]&((uint64_t)0x80000000)) == 0;) { + if(res->a[i].el) { + le = -1; + }else if(n_v>n_v0 && ex[n_v-1].el) { + le = i; lnv = n_v;///cut the cis alignments in the end + } + ex[n_v++] = res->a[i]; track[i] |= ((uint64_t)0x80000000); + // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n", res->a[i].tn+1, "lc"[uref->ug->u.a[res->a[i].tn].circ], res->a[i].qs, res->a[i].qe); + i = pop_pre(track[i]); + } + } + // fprintf(stderr, "-[M::] n_v->%ld;\n", n_v); + if(n_v0 == n_v) continue; + if(le >= 0) { + i = le; n_v = lnv; + } + if(n_v0 == n_v) continue; + // fprintf(stderr, "[++chain::] beg_idx->%u, end_idx->%ld, le->%ld, chain_n->%ld\n", (uint32_t)srt[k], i, le, n_v - n_v0); + ///keep the whole score; do not cut score like minigraph + // sc = pop_sc(srt[k]); + sc = (i<0?(pop_sc(srt[k])):(pop_sc(srt[k])-pop_sc(track[i]))); + // fprintf(stderr, "++[M::%s] k:%ld, n_v0:%ld, n_v:%ld, le:%ld, sc:%ld, beg:%u, end:%ld, p_score:%ld, cut_score:%ld\n", + // __func__, k, n_v0, n_v, le, sc, (uint32_t)srt[k], i, pop_sc(srt[k]), i<0?0:pop_sc(track[i])); + if(sc /**<=**/< 0) {///sc might be 0, if the UL alignment cannot cover the whole overlap between two HiFi reads + n_v = n_v0; + continue; + } + // idx[n_u++] = push_sc_pre(sc, n_v-n_v0); + idx[n_u++] = ((uint64_t)sc<<32)|(n_v-n_v0); + } + // fprintf(stderr, "[M::%s] n_u:%ld, n_v:%ld\n", __func__, n_u, n_v); + for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { + n_v0 = n_v; n_v += (uint32_t)idx[k]; + // fprintf(stderr, "[M::%s] k:%ld, n_v0:%ld, n_v:%ld\n", __func__, k, n_v0, n_v); + res->a[k].qn = idx[k]>>32;//score + res->a[k].ts = n_v0; res->a[k].te = n_v;///idx + + rev_n = ((uint32_t)idx[k])>>1; + ///we need to consider contained reads; so determining qs is not such easy + res->a[k].qs = (uint32_t)-1; res->a[k].qe = ex[n_v0].qe; + for (i = 0; i < rev_n; i++) { + rev_t = ex[n_v0+i]; ex[n_v0+i] = ex[n_v-i-1]; ex[n_v-i-1] = rev_t; + + if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; + if(res->a[k].qs > ex[n_v-i-1].qs) res->a[k].qs = ex[n_v-i-1].qs; + n_el -= ex[n_v0+i].el; n_el -= ex[n_v-i-1].el; + ex[n_v0+i].sec = ex[n_v-i-1].sec = SEC_MODE; + } + if(((uint32_t)idx[k])&1) { + if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; + n_el -= ex[n_v0+i].el; ex[n_v0+i].sec = SEC_MODE; + } + assert(ex[n_v0].el && ex[n_v-1].el); + // fprintf(stderr, "[M::%s] k:%ld, qs:%u, qe:%u, chain_occ:%u, chain_score:%u\n", __func__, k, + // res->a[k].qs, res->a[k].qe, res->a[k].te - res->a[k].ts, res->a[k].qn); + } + // if(n_el) { + // fprintf(stderr, "[M::%s] debug_i->%ld, n_el->%ld, n_u->%ld, n_v->%ld\n", __func__, debug_i, n_el, n_u, n_v); + // } + assert(n_el == 0); + res->n = n_u; + radix_sort_ul_ov_srt_qn(res->a, res->a + res->n);//sort by score + // fprintf(stderr, "---[M::%s] n_u:%ld, n_v:%ld\n", __func__, n_u, n_v); + return n_v; +} + + +int64_t gl_chain_advance_back(kv_ul_ov_t *res, ul_ov_t *ex, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, int64_t max_skip, uint64_t *srt, uint64_t *idx, uint64_t *track, float trans_allow, +All_reads *ridx, ma_ug_t *ug, void *km) +{ + uint32_t li_v, lj_v, rev_n, is_c, nc, s_nc; + int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, qo, trans_scl = (int64_t)(((float)(1))/trans_allow), nsc[2]; + ul_ov_t *li = NULL, *lj = NULL, rev_t; + radix_sort_ul_ov_srt_qe(res->a, res->a + res->n); + for (i = s_nc = 0; i < (int64_t)res->n; ++i) { + li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; + mm_ovlp = uref?max_ovlp(uref->ug->g, li_v^1):max_ovlp_src(uopt, li_v^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(i, res->a, x); + csc = uref?retrieve_u_cov_region(uref, li->tn, 0, li->ts, li->te, NULL):li->te-li->ts; + if(!(li->el)) { + csc *= -trans_scl; //trans overlaps + if(csc >= 0) csc = -1; + } + mm_sc = csc; mm_idx = -1; nc = nsc[0] = nsc[1] = 0; + for (j = x; j >= 0; --j) { // collect potential destination vertices + lj = &(res->a[j]); lj_v = (lj->tn<<1)|lj->rev; + // if((lj->qe+gapLen) <= li->qs) break; + if(lj->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore + // if(lj->qs >= li->qs) continue; // lj is contained in li on the query coordinate + qo = infer_rovlp(li, lj, NULL, NULL, ridx, ug); ///overlap length in query (UL read) + if(li_v != lj_v && get_ecov_adv_back(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, &is_c)) { + if(!is_c) { + sc = csc + pop_sc(track[j]); + if(sc > mm_sc) mm_sc = sc, mm_idx = j; + } else if(!uref) {///with uref, retrieve_u_cov_region has already consider contained reads + res->a[nc++].sec = j; + if(li->el) nsc[0] += lj->te-lj->ts; + else nsc[!(lj->el)] += lj->te-lj->ts; + } + } + } + + if(nc && (!uref) && mm_idx>=0) {///deal with containments + mm_sc += determine_containment_chain(uopt, track, srt, res, nc, nsc, mm_idx, bw, diff_ec_ul, li->el, ridx, ug); + s_nc++; + } + + track[i] = push_sc_pre(mm_sc, mm_idx); + srt[i] = track[i]>>32; srt[i] <<= 32; srt[i] |= i; + // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n\n", li->tn+1, "lc"[uref->ug->u.a[li->tn].circ], li->qs, li->qe); + } + + if(s_nc) { + for (i = 0; i < (int64_t)res->n; ++i) { + if(srt[i]&((uint64_t)0x80000000)) srt[i]-=((uint64_t)0x80000000); + } + } + + int64_t n_v, n_u, n_v0, le, lnv; + radix_sort_gfa64(srt, srt+res->n); //ex->n = res->n; + for (k = (int64_t)res->n-1, n_v = n_u = 0; k >= 0; --k) { + n_v0 = n_v; i = (uint32_t)srt[k]; + if(i>=0 && (res->a[i].el)) { ///chain must start from cis alignments + for (le = -1; i >= 0 && (track[i]&((uint64_t)0x80000000)) == 0;) { + if(res->a[i].el) { + le = -1; + }else if(n_v>n_v0 && ex[n_v-1].el) { + le = i; lnv = n_v;///cut the cis alignments in the end + } + ex[n_v++] = res->a[i]; track[i] |= ((uint64_t)0x80000000); + // fprintf(stderr, "[M::utg%.6d%c] qs->%u; qe->%u\n", res->a[i].tn+1, "lc"[uref->ug->u.a[res->a[i].tn].circ], res->a[i].qs, res->a[i].qe); + i = pop_pre(track[i]); + } + } + if(n_v0 == n_v) continue; + if(le >= 0) { + i = le; n_v = lnv; + } + if(n_v0 == n_v) continue; + ///keep the whole score; do not cut score like minigraph + // sc = pop_sc(srt[k]); + sc = (i<0?(pop_sc(srt[k])):(pop_sc(srt[k])-pop_sc(track[i]))); + if(sc < 0) { + n_v = n_v0; + continue; + } + // idx[n_u++] = push_sc_pre(sc, n_v-n_v0); + idx[n_u++] = ((uint64_t)sc<<32)|(n_v-n_v0); + } + + for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { + n_v0 = n_v; n_v += (uint32_t)idx[k]; + res->a[k].qn = idx[k]>>32; + res->a[k].ts = n_v0; res->a[k].te = n_v; + + rev_n = ((uint32_t)idx[k])>>1; + ///we need to consider contained reads; so determining qs is not such easy + res->a[k].qs = (uint32_t)-1; res->a[k].qe = ex[n_v0].qe; + for (i = 0; i < rev_n; i++) { + rev_t = ex[n_v0+i]; + ex[n_v0+i] = ex[n_v0+rev_n-i-1]; + ex[n_v0+rev_n-i-1] = rev_t; + if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; + if(res->a[k].qs > ex[n_v0+rev_n-i-1].qs) res->a[k].qs = ex[n_v0+rev_n-i-1].qs; + } + if(i < ((uint32_t)idx[k]) && res->a[k].qs < ex[n_v0+i].qs) { + res->a[k].qs = ex[n_v0+i].qs; + } + } + res->n = n_u; + radix_sort_ul_ov_srt_qn(res->a, res->a + res->n); + return n_v; +} + +uint32_t check_trans_rate(ul_ov_t *a, int64_t a_n, float trans_thres) +{ + uint32_t sp = (uint32_t)-1, ep = (uint32_t)-1, tts = (uint32_t)-1, tte = 0, el = 0, iel = 0; + int64_t k; + for (k = a_n-1; k >= 0; k--) { + if(a[k].qs < tts) tts = a[k].qs; + if(a[k].qe > tte) tte = a[k].qe; + if(!(a[k].el)) continue; + if(sp == (uint32_t)-1 || a[k].qe <= sp) { + if(sp != (uint32_t)-1) el += ep - sp; + sp = a[k].qs; + ep = a[k].qe; + } else { + sp = MIN(sp, a[k].qs); + } + } + if(sp != (uint32_t)-1) el += ep - sp; + iel = (tte - tts) - el; + // fprintf(stderr, "[M::%s] el:%u, iel:%u\n", __func__, el, iel); + if((iel == 0) || (iel <= ((tte - tts)*trans_thres))) return 1; + return 0; +} + +uint32_t ff_chain(kv_ul_ov_t *idx, int64_t qlen, float cov_rate, float trans_thres, ul_ov_t *a, +overlap_region_alloc* olist, haplotype_evdience_alloc *hap, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, +void *km) +{ + if(idx->n <= 0) return 0; + ul_ov_t *m = &(idx->a[idx->n-1]); //largest chain + // fprintf(stderr, "[M::%s] m->score:%u, m->qs:%u, m->qe:%u, chain_n:%u\n", __func__, m->qn, m->qs, m->qe, m->te-m->ts); + if((m->qe-m->qs) <= (qlen*cov_rate)) return 0; + if(trans_thres >= 0) { + if(check_trans_rate(a+m->ts, m->te-m->ts, trans_thres)) return 1; + if(olist && hap && uref) { + int64_t idx_n = idx->n, z, i, het_n, resc_tk = 0, f = 0; + uint64_t si; ma_utg_t *u = NULL; + for (z = m->ts; z < m->te; z++) { + if(a[z].el) { + kv_push_km(km, ul_ov_t, *idx, a[z]); + } else { + i = a[z].qn; si = 0; + het_n = update_ava_het_site(hap, i, &si, NULL, 1); + assert(het_n > 0 && olist->list[i].is_match == 2); + u = &(uref->ug->u.a[olist->list[i].y_id]); + if(u->n > 1) { + resc_tk += rescue_trans_ul_chains(uref, &(olist->list[i]), hap->list+si, het_n, u, + idx, diff_ec_ul, winLen, 0, NULL, km); + } + } + } + + if(resc_tk) { + radix_sort_ul_ov_srt_qe(idx->a+idx_n, idx->a+idx->n); + f = check_trans_rate(idx->a+idx_n, idx->n-idx_n, trans_thres); + } + idx->n = idx_n; + return f; + } + return 0; + } else { + return 1; + } +} + +void dump_chain(kv_ul_ov_t *des, ul_ov_t *src, ul_ov_t *chain, void *km) +{ + ///note: dump results to may change , so we should save in advance + uint64_t beg = chain->ts, occ = chain->te - chain->ts; + kv_resize_km(km, ul_ov_t, *des, occ); des->n = occ; + memcpy(des->a, src + beg, occ*sizeof((*src))); +} + +int64_t dedup_sort_contains(ul_ov_t *a, int64_t a_n, ul_contain *ct, const ug_opt_t *uopt) +{ + int64_t k, l, ci; ul_ov_t *z = NULL; + for (k = 0; k < a_n; k++) { + z = &(a[k]); + if(z->tn&((uint32_t)(0x80000000))) continue;///contained alignment + if(ct->is_c.a[z->tn] == 0) continue; + + for (ci = k+1; ci < a_n; ci++) { + if(a[ci].qe > z->qe + G_CHAIN_INDEL) break;///128 is for indel + if(a[ci].qn == (uint32_t)-1) continue; + if(!(a[ci].tn&((uint32_t)(0x80000000)))) continue; + if(z->qs <= a[ci].qs + G_CHAIN_INDEL && z->qe + G_CHAIN_INDEL >= a[ci].qe) { + if(check_contain_pair(uopt, (a[ci].tn<<1)>>1, z->tn, 1)) { + a[ci].qn = (uint32_t)-1; + } + } + } + + for (ci = k-1; ci >= 0; ci--) { + if(a[ci].qe + G_CHAIN_INDEL <= z->qs) break; + if(a[ci].qn == (uint32_t)-1) continue; + if(!(a[ci].tn&((uint32_t)(0x80000000)))) continue; + if(z->qs <= a[ci].qs + G_CHAIN_INDEL && z->qe + G_CHAIN_INDEL >= a[ci].qe) { + if(check_contain_pair(uopt, (a[ci].tn<<1)>>1, z->tn, 1)) { + a[ci].qn = (uint32_t)-1; + } + } + } + } + for (k = l = 0; k < a_n; k++) { + if(a[k].qn == (uint32_t)-1) continue; + if(k != l) a[l] = a[k]; + a[l].tn <<= 1; a[l].tn >>= 1; + ++l; + } + return l; +} + +void ins_merge_ul_ov(kv_ul_ov_t *idx, int64_t idx_s, int64_t idx_e, ul_ov_t q) +{ + int64_t k, ii, s = -1, e = -1, ovlp = 0, qs = q.qs, qe = q.qe; + for (k = idx_s, ii = -1; k < idx_e; k++) { + if(ii == -1 && q.qs > idx->a[k].qs) ii = k; + if(((int64_t)(idx->a[k].qs)) >= e) { + if(s >= 0 && e >= 0) { + ovlp += ((MIN(e, qe) > MAX(s, qs))?(MIN(e, qe) - MAX(s, qs)):0); + } + s = idx->a[k].qs; e = idx->a[k].qe; + } else { + if(e < ((int64_t)(idx->a[k].qe))) e = idx->a[k].qe; + } + } + + if(s >= 0 && e >= 0) { + ovlp += ((MIN(e, qe) > MAX(s, qs))?(MIN(e, qe) - MAX(s, qs)):0); + } +} + +void dump_all_chain(kv_ul_ov_t *idx, kv_ul_ov_t *ax, int64_t ax_new_occ, int64_t qlen, float primary_cov_rate, float primary_score_rate) { + if(idx->n <= 0) return; + ul_ov_t *m = &(idx->a[idx->n-1]); //largest chain + ul_ov_t *a = ax->a + ax->n; int64_t k, i, z, l, idx_n = idx->n; uint64_t ovlp; + if((m->qe-m->qs) > (qlen*primary_cov_rate)) { ///found a primary chain + for (k = m->ts, l = 0; k < m->te; k++) { + a[l] = a[k]; a[l].tn |= ((uint32_t)(0x80000000)); + l++; + } + ax->n += l; + } else { + for (k = idx_n-1; k >= 0; k--) { + for (i = idx_n-1; i > k; i--) { + if(idx->a[i].qn == (uint32_t)-1) continue;///just remove totally contained alignments + if(idx->a[k].qn > idx->a[i].qn*primary_score_rate) continue;///consider score + ovlp = ((MIN(idx->a[k].qe, idx->a[i].qe) > MAX(idx->a[k].qs, idx->a[i].qs))? + (MIN(idx->a[k].qe, idx->a[i].qe) - MAX(idx->a[k].qs, idx->a[i].qs)):0); + if(ovlp > ((idx->a[k].qe-idx->a[k].qs)*primary_cov_rate)) { + for (z = idx->a[k].ts; z < idx->a[k].te; z++) a[z].el = 1; + idx->a[k].qn = (uint32_t)-1; + break; + } + } + // ins_merge_ul_ov(idx, idx_n, idx->n, idx->a[k]); + } + for (k = 0, l = 0; k < ax_new_occ; k++) { + if(a[k].el) continue; + a[l] = a[k]; l++; + } + radix_sort_ul_ov_srt_qe(a, a + l); + ax->n += l; + } +} + +int64_t dump_all_chain_simple(kv_ul_ov_t *idx, kv_ul_ov_t *ax, int64_t ax_new_occ, int64_t qlen, +float primary_cov_rate, float fragement_cov_rate, float primary_fragment_cov_rate, +float primary_fragment_second_score_rate, float trans_thres, uint64_t mini_primary_fragment_len) +{ + if(idx->n <= 0) return 0; + ul_ov_t *m = &(idx->a[idx->n-1]); //largest chain + ul_ov_t *a = ax->a + ax->n; int64_t k, z, l, idx_n = idx->n, ovlp, om, ok, ff = 0; + // fprintf(stderr, "[M::%s] m->score:%u, m->qs:%u, m->qe:%u, chain_n:%u\n", __func__, m->qn, m->qs, m->qe, m->te-m->ts); + if(((m->qe-m->qs) > (qlen*primary_cov_rate)) && + (check_trans_rate(a+m->ts, m->te-m->ts, trans_thres))) { ///found a primary chain + for (k = m->ts, l = 0; k < m->te; k++) { + a[l] = a[k]; a[l].tn |= ((uint32_t)(0x80000000)); a[l].el = 1; + l++; + } + ax->n += l; ff = 1; + } else { + if((((m->qe-m->qs) > (qlen*primary_fragment_cov_rate)) || ((m->qe - m->qs) > mini_primary_fragment_len)) + && (check_trans_rate(a+m->ts, m->te-m->ts, trans_thres))) { + om = m->qe - m->qs; + for (k = 0; k < idx_n-1; k++) { + ovlp = ((MIN((m->qe), (idx->a[k].qe)) > MAX((m->qs), (idx->a[k].qs)))? + (MIN((m->qe), (idx->a[k].qe)) - MAX((m->qs), (idx->a[k].qs))):0); + if(ovlp == 0) continue; + ok = idx->a[k].qe - idx->a[k].qs; + if(ok > om ) ok = om; + if((ovlp > ok*0.1/**0.25**/) && idx->a[k].qn > (m->qn*primary_fragment_second_score_rate)) break; + } + + if(k >= idx_n-1) { + for (k = m->ts; k < m->te; k++) { + // if(a[k].el) a[k].tn |= ((uint32_t)(0x80000000)); + a[k].tn |= ((uint32_t)(0x80000000)); + } + ff = 1; + } + } + + radix_sort_ul_ov_srt_qe(idx->a, idx->a + idx->n); + for (k = 0; k < idx_n; k++) { + if(k < idx_n-1 && idx->a[k].qe > idx->a[k+1].qs) break;//not one chain + if((idx->a[k].qe - idx->a[k].qs) > (qlen*fragement_cov_rate)) {///large enough fragements + if(!check_trans_rate(a+idx->a[k].ts, idx->a[k].te-idx->a[k].ts, trans_thres)) break; + } + } + + if(k == idx_n) {///only if there is a clear chain (with holes) + for (k = 0; k < idx_n; k++) { + if((idx->a[k].qe - idx->a[k].qs) <= (qlen*fragement_cov_rate)) continue; + for (z = idx->a[k].ts; z < idx->a[k].te; z++) { + // if(a[z].el) a[z].tn |= ((uint32_t)(0x80000000)); + a[z].tn |= ((uint32_t)(0x80000000)); + } + ff = 1; + } + } + /** + for (k = 0, l = 0; k < ax_new_occ; k++) { + if(!(a[k].el)) continue; + a[l] = a[k]; l++; + } + + radix_sort_ul_ov_srt_qe(a, a + l); + ax->n += l; + **/ + for (k = 0, l = 0; k < ax_new_occ; k++) { + if(a[k].el || (a[k].tn&((uint32_t)(0x80000000)))) { + a[l] = a[k]; l++; + } + } + ax_new_occ = l; + + radix_sort_ul_ov_srt_qe(a, a + ax_new_occ); + for (k = 1, l = 0; k <= ax_new_occ; k++) { + if (k == ax_new_occ || a[k].qe != a[l].qe) { + if(k - l > 1) radix_sort_ul_ov_srt_qs(a+l, a+k); + l = k; + } + } + ax->n += ax_new_occ; + } + return ff; +} + +void save_tmp_chains(ul_ov_t *idx_a, uint64_t idx_n, uint64_t *idx_buf_0, uint64_t *idx_buf_1, ul_ov_t *cc_a, uint64_t cc_n, uint64_t *cc_buf) +{ + uint64_t k; + for (k = 0; k < idx_n; k++) ; +} + +void debug_reverse_chain(ul_ov_t *a, int64_t a_n) +{ + int64_t rev_n = a_n>>1, i; ul_ov_t rev_t; + for (i = 0; i < rev_n; i++) { + rev_t = a[i]; a[i] = a[a_n-i-1]; a[a_n-i-1] = rev_t; + } +} + +uint32_t quick_primary_assgin(const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, ul_ov_t *a, int64_t a_n) +{ + int64_t k, qo, share, f = 1; ul_ov_t *li, *lk; uint32_t li_v, lk_v; + for (k = a_n - 1, li = NULL; k >= 0; k--) { + lk = &(a[k]); lk_v = (lk->tn<<1)|lk->rev; lk->sec = SEC_MODE; + if(!(lk->tn&((uint32_t)(0x80000000)))) continue; + if(li && lk->qe > li->qs) { ///lk is overlapped with li + li->tn <<= 1; li->tn >>= 1; lk->tn <<= 1; lk->tn >>= 1; + qo = infer_rovlp(li, lk, NULL, NULL, NULL, NULL); + li->tn |= ((uint32_t)(0x80000000)); lk->tn |= ((uint32_t)(0x80000000)); + if(qo && li_v != lk_v && get_ecov_adv(uref, uopt, li_v^1, lk_v^1, bw, diff_ec_ul, qo, 1, &share)) { + li->sec = k; f++; ///the end of a chain is a cis overlap + } else { + f = 0; + break; + } + } + li = lk; li_v = lk_v; + } + return f; +} + +void assgin_primary_chains(ul_ov_t *a, int64_t a_n, int64_t is_srt, const ul_idx_t *uref, const ug_opt_t *uopt, +uint64_t *track, uint64_t *srt, int64_t bw, double diff_ec_ul, int64_t qlen, int64_t is_ungap) +{ + if(a_n == 0) return; + int64_t i, j, k, mm_ovlp, x, csc, mm_sc, mm_idx, qo, share, sc; + uint32_t li_v, lj_v; ul_ov_t *li = NULL, *lj = NULL; + if(is_srt) { + radix_sort_ul_ov_srt_qe(a, a + a_n); + for (i = 1, j = 0; i <= a_n; i++) { + if (i == a_n || a[i].qe != a[j].qe) { + if(i - j > 1) { + radix_sort_ul_ov_srt_qs(a+j, a+i); + } + j = i; + } + } + } + + if(uref && uopt && track && srt) { + if(quick_primary_assgin(uref, uopt, bw, diff_ec_ul, a, a_n) == 0) { + for (i = 0; i < a_n; ++i) { + li = &(a[i]); li_v = (li->tn<<1)|li->rev; li->sec = SEC_MODE; + mm_sc = csc = 1; mm_idx = -1; + if(li->tn&((uint32_t)(0x80000000))) { + mm_ovlp = max_ovlp_src(uopt, li_v^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(i, a, x+G_CHAIN_INDEL); + + for (j = x; j >= 0; --j) { + lj = &(a[j]); lj_v = (lj->tn<<1)|lj->rev; + if(lj->qe+G_CHAIN_INDEL <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore + if(is_ungap && (lj->qs >= li->qs+G_CHAIN_INDEL)) continue; // lj is contained in li on the query coordinate; 128 for indel offset + if(!(lj->tn&((uint32_t)(0x80000000)))) continue; + li->tn <<= 1; li->tn >>= 1; lj->tn <<= 1; lj->tn >>= 1; + qo = infer_rovlp(li, lj, NULL, NULL, NULL, NULL); + li->tn |= ((uint32_t)(0x80000000)); lj->tn |= ((uint32_t)(0x80000000)); + if(qo && li_v != lj_v && get_ecov_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, 1, &share)) { + sc = csc + pop_sc(track[j]); + if(sc > mm_sc) mm_sc = sc, mm_idx = j; + } + } + } + track[i] = push_sc_pre(mm_sc, mm_idx); + srt[i] = track[i]>>32; srt[i] <<= 32; srt[i] |= i; + // fprintf(stderr, "[M::] i->%ld; mm_idx->%ld\n", i, mm_idx); + } + + radix_sort_gfa64(srt, srt+a_n); + for (k = a_n-1; k >= 0; --k) { + i = (uint32_t)srt[k]; + // if(i < 0 || i >= a_n) fprintf(stderr, "sbsbsbsbsbsb, k->%ld, i->%ld, a_n->%ld\n", k, i, a_n); + if(a[i].el && (a[i].tn&((uint32_t)(0x80000000)))) { + for (; i >= 0 && (track[i]&((uint64_t)0x80000000)) == 0;) { + track[i] |= ((uint64_t)0x80000000); j = i; + i = pop_pre(track[i]); + if(i >= 0) { + // if(i == j) fprintf(stderr, "sb\n"); + a[j].sec = i; + } + } + } + } + } + } +} + +int64_t gl_chain_refine_advance(overlap_region_alloc* olist, Correct_dumy* dumy, haplotype_evdience_alloc *hap, glchain_t *ll, st_mt_t *sps, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, int64_t qlen, const ug_opt_t *uopt, +int64_t debug_i, void *km) +{ + // ll->tk.n = ll->lo.n = 0; + kv_ul_ov_t *idx = &(ll->lo); + ul_contain *ct = uref->ct; + uint64_t o2 = gl_chain_gen(olist, uref, idx, 0, hap, km); + if(idx->n == 0) return 0; + // fprintf(stderr, "[M::%s] qlen:%ld, idx->n:%u\n", __func__, qlen, (uint32_t)idx->n); + uint64_t k, an, cn, si = 0, ei = 0, resc = 0, resc_tk = 0, tk_pl = 0, f = 0, occ = 0, cis_occ = 0, t_cis = 0; + ma_utg_t *u = NULL; overlap_region *o = NULL; + + kv_resize_km(km, uint64_t, ll->srt.a, idx->n); + kv_resize_km(km, uint64_t, hap->snp_srt, idx->n); + kv_resize_km(km, ul_ov_t, ll->tk, ll->tk.n+idx->n); + ///note: there are three rounds of gl_chain_advance() + ///the first two rounds could reuse dumy->overlapID. But for the last round, dumy->overlapID is not long enough + occ = gl_chain_advance(idx, ll->tk.a+ll->tk.n, uref, uopt, G_CHAIN_BW, diff_ec_ul, qlen, UG_SKIP, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 0, NULL, uref->ug, debug_i, km); + if(occ) { + if(ff_chain(idx, qlen, P_CHAIN_COV, -1/**G_CHAIN_TRANS_RATE**/, ll->tk.a+ll->tk.n, NULL, NULL, NULL, diff_ec_ul, winLen, km)) { + f = 1; //dump_chain(idx, ll->tk.a+ll->tk.n, &(idx->a[idx->n-1]), km); + for (k = idx->a[idx->n-1].ts; k < idx->a[idx->n-1].te; k++) { + olist->list[ll->tk.a[ll->tk.n+k].qn].x_pos_strand = 1; + } + } else if(o2) {///means there are trans overlaps + gl_chain_gen(olist, uref, idx, 1, hap, km); + kv_resize_km(km, uint64_t, ll->srt.a, idx->n); + kv_resize_km(km, uint64_t, hap->snp_srt, idx->n); + kv_resize_km(km, ul_ov_t, ll->tk, ll->tk.n+idx->n); + ///chain all U-matches + occ = gl_chain_advance(idx, ll->tk.a+ll->tk.n, uref, uopt, G_CHAIN_BW, diff_ec_ul, qlen, UG_SKIP, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 0, NULL, uref->ug, debug_i, km); + if(ff_chain(idx, qlen, P_CHAIN_COV, G_CHAIN_TRANS_RATE, ll->tk.a+ll->tk.n, olist, hap, uref, diff_ec_ul, winLen, km)) { + f = 1; //dump_chain(idx, ll->tk.a+ll->tk.n, &(idx->a[idx->n-1]), km); + for (k = idx->a[idx->n-1].ts; k < idx->a[idx->n-1].te; k++) { + olist->list[ll->tk.a[ll->tk.n+k].qn].x_pos_strand = 1; + } + } + } + } + + if(!f) {///if f == 1, only dump primary chain; otherwise dump all chains + ///we can save all data to buffer like ll->srt.a in advance; in case we don't need third round of chaining + ///means no trans overlaps, no need to do third round of chaining + // if(!o2) { + // ; + // } + /** + uint64_t z; + for (k = 0; k < idx->n; k++) { + if(check_trans_rate(ll->tk.a+ll->tk.n+idx->a[k].ts, idx->a[k].te-idx->a[k].ts, G_CHAIN_TRANS_RATE)) { + for (z = idx->a[k].ts; z < idx->a[k].te; z++) { + olist->list[ll->tk.a[ll->tk.n+z].qn].x_pos_strand = 1; + } + } else { + for (z = idx->a[k].ts; z < idx->a[k].te; z++) { + if(!(ll->tk.a[ll->tk.n+z].el)) continue; + olist->list[ll->tk.a[ll->tk.n+z].qn].x_pos_strand = 1; + } + } + } + **/ + for (k = 0; k < occ; k++) { + olist->list[ll->tk.a[ll->tk.n+k].qn].x_pos_strand = 1; + } + // kv_resize_km(km, ul_ov_t, *idx, occ); idx->n = occ; + // memcpy(idx->a, ll->tk.a+ll->tk.n, occ*sizeof((*(idx->a)))); + } + // for (k = 0; k < idx->n; k++) olist->list[idx->a[k].qn].x_pos_strand = 1; + + for (k = 0, idx->n = 0, tk_pl = ll->tk.n, t_cis = 0; k < olist->length; k++) { + o = &(olist->list[k]); + ///if f == 1, no matter + if(o->x_pos_strand && (f || o->is_match == 1)){ + u = &(uref->ug->u.a[o->y_id]);///overlaped reads + resc_tk += rescue_trans_ul_chains(uref, o, NULL, 0, u, &(ll->tk), -1, -1, 0, NULL, km); + } else if((!f) && o->is_match == 2) { + // fprintf(stderr, "###[M::%s] # k:%lu, # o->y_id:%u\n", __func__, k, o->y_id); + an = update_ava_het_site(hap, k, &si, &ei, 1); + // if(an != get_het_site(hap, k)) fprintf(stderr, "an->%lu, get_het_site->%lu\n", an, get_het_site(hap, k)); + assert(an > 0); + + cn = ((uint32_t)(ct->idx.a[o->y_id])); + if(cn > 0) { + resc += rescue_contain_ul_chains(uref, o, hap->list+si, an, + ct->rids.a + ((ct->idx.a[o->y_id])>>32), cn, idx, diff_ec_ul, winLen, 0, km); + } + + u = &(uref->ug->u.a[o->y_id]); + if(u->n > 1 || o->x_pos_strand) {///no redundant items here + resc_tk += rescue_trans_ul_chains(uref, o, hap->list+si, an, u, + &(ll->tk), diff_ec_ul, winLen, o->x_pos_strand, &cis_occ, km); + t_cis += cis_occ; + } + + si = ei; + } + } + + assert(ll->tk.n == resc_tk+tk_pl); + assert(idx->n == resc); + if(f) assert(resc==0); + + + if(!f) {///dedup contained alignments + if(idx->n) {///if some contained alignments have been rescued + radix_sort_ul_ov_srt_tn(idx->a, idx->a + idx->n); + idx->n = dedup_sort_ul_ov_t(idx->a, idx->n);///different trans alignments may have the same contained alignment + } + resc = idx->n; + // fprintf(stderr, "***[M::%s] # contain:%lu, # non-contain:%lu\n", __func__, resc, (uint64_t)(ll->tk.n-tk_pl)); + for (k = tk_pl; k < ll->tk.n; k++) {///dump all non-contained reads + kv_push_km(km, ul_ov_t, *idx, ll->tk.a[k]); + if(idx->a[idx->n-1].tn&((uint32_t)(0x80000000))) { + idx->a[idx->n-1].tn -= ((uint32_t)(0x80000000)); + } + } + ll->tk.n = tk_pl; + + radix_sort_ul_ov_srt_qe(idx->a, idx->a + idx->n); + if(resc) {///need to dedup contained alignment again + // fprintf(stderr, "[M::%s] idx->n:%lu, resc:%lu\n", __func__, (uint64_t)idx->n, resc); + idx->n = dedup_sort_contains(idx->a, idx->n, ct, uopt); + } + + ///note: need sps for third round of gl_chain_advance() as dumy->overlapID might be not long enough + kv_resize_km(km, uint64_t, *sps, idx->n); + kv_resize_km(km, uint64_t, ll->srt.a, idx->n); + kv_resize_km(km, uint64_t, hap->snp_srt, idx->n); + kv_resize_km(km, ul_ov_t, ll->tk, ll->tk.n+idx->n); + occ = gl_chain_advance(idx, ll->tk.a+ll->tk.n, uref, uopt, G_CHAIN_BW, diff_ec_ul, qlen, UG_SKIP, sps->a, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 1, &R_INF, NULL, debug_i, km); + // fprintf(stderr, "***[M::%s] ll->tk.n:%u, occ:%lu\n", __func__, (uint32_t)ll->tk.n, occ); + f = dump_all_chain_simple(idx, &(ll->tk), occ, qlen, P_CHAIN_COV, P_FRAGEMENT_CHAIN_COV, + P_FRAGEMENT_PRIMARY_CHAIN_COV, 0.1/**P_FRAGEMENT_PRIMARY_SECOND_COV**/, G_CHAIN_TRANS_RATE, PRIMARY_UL_CHAIN_MIN); + // fprintf(stderr, ">>>[M::%s] ll->tk.n:%u\n", __func__, (uint32_t)ll->tk.n); + // dump_all_chain(idx, &(ll->tk), occ, qlen, P_CHAIN_COV, P_CHAIN_SCORE); + } else { + ///for primary chain, each element x: (x->tn & (uint32_t)(0x80000000)) + assgin_primary_chains(ll->tk.a+tk_pl, ll->tk.n-tk_pl, 1, NULL, NULL, NULL, NULL, G_CHAIN_BW, diff_ec_ul, qlen, 1); + // radix_sort_ul_ov_srt_qe(ll->tk.a+tk_pl, ll->tk.a+ll->tk.n); + } + + ///if f == 0, results have already been sorted by qe|qs + if(f) { + kv_resize_km(km, uint64_t, ll->srt.a, ll->tk.n-tk_pl); kv_resize_km(km, uint64_t, hap->snp_srt, ll->tk.n-tk_pl); + assgin_primary_chains(ll->tk.a+tk_pl, ll->tk.n-tk_pl, 0, uref, uopt, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_BW, diff_ec_ul, qlen, 1); + } + // debug_reverse_chain(ll->tk.a+tk_pl, ll->tk.n-tk_pl); + /** + if(idx->n > 0) { + an = infer_read_ovlp(uref, olist, idx , &(ll->tk), diff_ec_ul, winLen, uopt, ct, km); + // if(an) fill_edge_weight(ll->tk.a+ll->tk.n-an, an, uopt, G_CHAIN_BW, diff_ec_ul, qlen); + } + **/ + return 1; +} + +int64_t g_adjacent_dis(const asg_t *g, uint32_t v, uint32_t w) +{ + uint32_t nv, i; asg_arc_t *av = NULL; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (i = 0; i < nv; i++) { + if(av[i].del || av[i].v != w) continue; + return (uint32_t)av[i].ul; + } + return -1; +} + +void get_r_offset(ma_ug_t *ug, mg_lchain_t *x, int64_t *rs, int64_t *re, int64_t *qs, int64_t *qe) +{ + if(qs) {*qs = x->qs;} if(qe) {*qe = x->qe;} + if(!(x->score&1)) { + if(rs) *rs = x->rs + x->off; + if(re) *re = x->re + x->off; + } else { + if(rs) *rs = x->off + ug->g->seq[x->score>>1].len - x->re; + if(re) *re = x->off + ug->g->seq[x->score>>1].len - x->rs; + } +} + +void get_u_offset(ma_ug_t *ug, mg_lchain_t *x, int64_t *rs, int64_t *re, int64_t *qs, int64_t *qe) +{ + if(qs) {*qs = x->qs;} if(qe) {*qe = x->qe;} + if(!(x->v&1)) { + if(rs) *rs = x->rs + x->off; + if(re) *re = x->re + x->off; + } else { + if(rs) *rs = x->off + ug->g->seq[x->v>>1].len - x->re; + if(re) *re = x->off + ug->g->seq[x->v>>1].len - x->rs; + } +} + +void l2g_chain(const ul_idx_t *uref, kv_ul_ov_t *lidx, vec_mg_lchain_t *res) +{ + uint64_t k; + res->n = 0; kv_resize(mg_lchain_t, *res, lidx->n); res->n = lidx->n; + for (k = 0; k < lidx->n; k++) { + memset(&(res->a[k]), 0, sizeof(res->a[k])); + res->a[k].v = (lidx->a[k].tn<<1)|(lidx->a[k].rev); + res->a[k].off = lidx->a[k].qn; res->a[k].score = lidx->a[k].sec; + res->a[k].qs = lidx->a[k].qs; res->a[k].qe = lidx->a[k].qe; + res->a[k].rs = lidx->a[k].ts; res->a[k].re = lidx->a[k].te; + if(lidx->a[k].el) { + res->a[k].score = retrieve_u_cov_region(uref, lidx->a[k].tn, 0, lidx->a[k].ts, lidx->a[k].te, NULL); + } + } +} + +int64_t l2g_res_chain(ma_ug_t *ug, ul_ov_t *a, uint64_t a_n, vec_mg_lchain_t *gchains, double diff_rate) +{ + // fprintf(stderr, "[M::%s::] a_n::%lu\n", __func__, a_n); + if(a_n <= 0) return 0; + uint64_t k, m; int64_t l, rs, re, qs, qe, dq, dr, dif, mm; a_n++; asg_t *g = ug->g; + gchains->n = 0; kv_resize(mg_lchain_t, *gchains, a_n); gchains->n = a_n; + memset(&(gchains->a[0]), 0, sizeof(gchains->a[0])); + gchains->a[0].cnt = a_n - 1; gchains->a[0].v = (uint32_t)-1; + for (k = 1, m = 0, l = 0; k < a_n; k++, m++) { + memset(&(gchains->a[k]), 0, sizeof(gchains->a[k])); + gchains->a[k].v = (a[m].tn<<1)|(a[m].rev); gchains->a[k].dist_pre = -1; + gchains->a[k].off = a[m].qn; gchains->a[k].score = a[m].sec; + gchains->a[k].qs = a[m].qs; gchains->a[k].qe = a[m].qe; + gchains->a[k].rs = a[m].ts; gchains->a[k].re = a[m].te; + if(k > 1) { + gchains->a[k-1].dist_pre = g_adjacent_dis(g, gchains->a[k].v^1, gchains->a[k-1].v^1); + assert(gchains->a[k-1].dist_pre >= 0); + l += g->seq[gchains->a[k-1].v>>1].len + gchains->a[k-1].dist_pre; + } + // fprintf(stderr, "[M::%s::k->%lu] utg%.6dl(%c)\n", __func__, k, (int32_t)(gchains->a[k].v>>1)+1, "+-"[gchains->a[k].v&1]); + } + + if(diff_rate < 0) return 1; + + mg_lchain_t s = gchains->a[1], e = gchains->a[a_n-1]; + s.off = 0; + l -= (int64_t)g->seq[gchains->a[a_n-1].v>>1].len; + if(l < 0) l = 0; + e.off = l; + + get_u_offset(ug, &s, &rs, NULL, &qs, NULL); get_u_offset(ug, &e, NULL, &re, NULL, &qe); + dq = qe - qs; dr = re - rs; + dif = (dq>dr? dq-dr:dr-dq); + mm = MAX(dq, dr); mm *= diff_rate; + if(dif <= mm) return 1; + return 0; +} + + +int64_t l2g_res_chain_sc(ma_ug_t *ug, ul_ov_t *a, uint64_t a_n, vec_mg_lchain_t *gchains) +{ + // fprintf(stderr, "[M::%s::] a_n::%lu\n", __func__, a_n); + if(a_n <= 0) return 0; + uint64_t k, m; int64_t l; a_n++; asg_t *g = ug->g; + gchains->n = 0; kv_resize(mg_lchain_t, *gchains, a_n); gchains->n = a_n; + memset(&(gchains->a[0]), 0, sizeof(gchains->a[0])); + gchains->a[0].cnt = a_n - 1; gchains->a[0].v = (uint32_t)-1; + for (k = 1, m = 0, l = 0; k < a_n; k++, m++) { + memset(&(gchains->a[k]), 0, sizeof(gchains->a[k])); + gchains->a[k].v = (a[m].tn<<1)|(a[m].rev); gchains->a[k].dist_pre = -1; + gchains->a[k].off = a[m].qn; gchains->a[k].score = a[m].sec; + gchains->a[k].qs = a[m].qs; gchains->a[k].qe = a[m].qe; + gchains->a[k].rs = a[m].ts; gchains->a[k].re = a[m].te; + if(k > 1) { + gchains->a[k-1].dist_pre = g_adjacent_dis(g, gchains->a[k].v^1, gchains->a[k-1].v^1); + assert(gchains->a[k-1].dist_pre >= 0); + l += g->seq[gchains->a[k-1].v>>1].len + gchains->a[k-1].dist_pre; + } + // fprintf(stderr, "[M::%s::k->%lu] utg%.6dl(%c)\n", __func__, k, (int32_t)(gchains->a[k].v>>1)+1, "+-"[gchains->a[k].v&1]); + } + + return 1; +} + +int64_t check_elen_gchain(ul_ov_t *a, int64_t a_n, float trans_thres) +{ + uint32_t sp_e, ep_e, ts, te, tl = 0, el = 0, iel = 0; + sp_e = ep_e = ts = te = (uint32_t)-1; + int64_t k; + for (k = a_n-1; k >= 0; k--) { + if(ts == (uint32_t)-1 || a[k].qe <= ts) { + if(ts != (uint32_t)-1) tl += te - ts; + ts = a[k].qs; te = a[k].qe; + } else { + ts = MIN(ts, a[k].qs); + } + if(!(a[k].el)) continue; + + if(sp_e == (uint32_t)-1 || a[k].qe <= sp_e) { + if(sp_e != (uint32_t)-1) el += ep_e - sp_e; + sp_e = a[k].qs; + ep_e = a[k].qe; + } else { + sp_e = MIN(sp_e, a[k].qs); + } + } + if(ts != (uint32_t)-1) tl += te - ts; + if(sp_e != (uint32_t)-1) el += ep_e - sp_e; + + iel = tl - el; + // fprintf(stderr, "[M::%s] el:%u, iel:%u\n", __func__, el, iel); + if((iel == 0) || (iel <= (tl*trans_thres))) return 1; + return 0; +} + +int64_t ds_check_vec_mg_lchain_t(mg_lchain_t *a, int64_t a_n, kv_ul_ov_t *buf, overlap_region_alloc* olist, +haplotype_evdience_alloc *hap, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, float trans_thres) +{ + if(a_n <= 0) return 0; + int64_t k, resc_tk, het_n; ul_ov_t *p; uint64_t si; ma_utg_t *u = NULL; buf->n = 0; + for (k = 0; k < a_n; k++) { + if(a[k].off < 0) continue; + kv_pushp(ul_ov_t, *buf, &p); + p->qs = a[k].qs; p->qe = a[k].qe; p->el = 1; + if(a[k].score < 0) p->el = 0; + } + if(buf->n <= 0) return 0; + if(check_elen_gchain(buf->a, buf->n, trans_thres)) return 1; + + buf->n = 0; resc_tk = 0; + for (k = 0; k < a_n; k++) { + if(a[k].off < 0) continue; + if(a[k].score >= 0) { + kv_pushp(ul_ov_t, *buf, &p); + p->qs = a[k].qs; p->qe = a[k].qe; p->el = 1; + } else { + si = 0; + het_n = update_ava_het_site(hap, a[k].off, &si, NULL, 1); + assert(het_n > 0 && olist->list[a[k].off].is_match == 2); + u = &(uref->ug->u.a[olist->list[a[k].off].y_id]); + if(u->n > 1) { + resc_tk += rescue_trans_ul_chains(uref, &(olist->list[a[k].off]), hap->list+si, het_n, u, + buf, diff_ec_ul, winLen, 0, NULL, NULL); + } + } + } + + if(resc_tk) { + radix_sort_ul_ov_srt_qe(buf->a, buf->a+buf->n); + if(check_elen_gchain(buf->a, buf->n, trans_thres)) return 1; + } + + return 0; +} + +int64_t check_trans_rate_gap(vec_mg_lchain_t *uc, kv_ul_ov_t *buf, overlap_region_alloc* olist, +haplotype_evdience_alloc *hap, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, float trans_thres) +{ + if(uc->n <= 0) return 0; + int64_t k, m, ucn = uc->n, k_cnt, z; mg_lchain_t *ix; buf->n = 0; + for (k = m = 0; k < ucn; k += k_cnt) { + ix = &(uc->a[k]); assert(ix->v == (uint32_t)-1); k_cnt = ix->cnt + 1; + if(ds_check_vec_mg_lchain_t(uc->a + k + 1, ix->cnt, buf, olist, hap, uref, diff_ec_ul, winLen, trans_thres)) { + if(m == k) { + m += k_cnt; + } else { + for (z = 0; z < k_cnt; z++) uc->a[m++] = uc->a[k+z]; + } + } + } + uc->n = m; + if(uc->n) return 1; + return 0; +} + +int64_t hc_gchain1_dp(void *km, const ul_idx_t *uref, const ma_ug_t *ug, vec_mg_lchain_t *lc, vec_mg_lchain_t *sw, vec_mg_path_dst_t *dst, vec_sp_node_t *out, vec_mg_pathv_t *path, +int64_t qlen, const ug_opt_t *uopt, int64_t bw, double diff_thre, double ng_diff_thre, uint64_t *srt, st_mt_t *bf, int64_t *f, uint64_t *p, uint64_t *v); +uint32_t gen_max_gchain_adv(void *km, const ul_idx_t *uref, int64_t ulid, st_mt_t *idx, vec_mg_lchain_t *e, kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, +int64_t qlen, float primary_cov_rate, float primary_fragment_cov_rate, float primary_fragment_second_score_rate, uint64_t mini_primary_fragment_len, +const asg_t *g, st_mt_t *dst_done, vec_sp_node_t *out, vec_mg_pathv_t *res, uint64_t *b, vec_mg_lchain_t *gchains); + + + +void debug_intermediate_chain(ma_ug_t *ug, mg_lchain_t *a, int64_t a_n, int64_t is_uovlp, int64_t debug_i) +{ + int64_t k; mg_lchain_t *p, *c; + int64_t prs, pre, pqs, pqe, crs, cre, cqs, cqe; + int64_t tot = 0, fal = 0; + for (k = a_n-1; k >= 0; k--) { + c = &(a[k]); + if(c->v!=(uint32_t)-1) { + fprintf(stderr, "+(%ld) [M::utg%.6u%c::%c] qs:%d, qe:%d, rs:%d, re:%d, off:%d\n", k, (c->v>>1)+1, "lc"[ug->u.a[c->v>>1].circ], "+-"[c->v&1], + c->qs, c->qe, c->rs, c->re, c->off); + } + + + if(c->hash_pre != (uint32_t)-1) { + p = &(a[c->hash_pre]); tot++; + if(is_uovlp) { + get_u_offset(ug, p, &prs, &pre, &pqs, &pqe); + } else { + get_r_offset(ug, p, &prs, &pre, &pqs, &pqe); + } + if(is_uovlp) { + get_u_offset(ug, c, &crs, &cre, &cqs, &cqe); + } else { + get_r_offset(ug, c, &crs, &cre, &cqs, &cqe); + } + + fprintf(stderr, "cur (%ld) [M::utg%.6u%c::%c] qs:%ld, qe:%ld, rs:%ld, re:%ld, pidx:%u\n", + k, (c->v>>1)+1, "lc"[ug->u.a[c->v>>1].circ], "+-"[c->v&1], cqs, cqe, crs, cre, c->hash_pre); + + fprintf(stderr, "pre (%ld) [M::utg%.6u%c::%c] qs:%ld, qe:%ld, rs:%ld, re:%ld, pidx:%u\n", + k, (p->v>>1)+1, "lc"[ug->u.a[p->v>>1].circ], "+-"[p->v&1], pqs, pqe, prs, pre, p->hash_pre); + + if((!(prs<=crs&&pre<=cre&&pqs<=cqs&&pqe<=cqe)) || (!(prs<=pre&&pqs<=pqe&&crs<=cre&&cqs<=cqe))) { + fal++; + // fprintf(stderr, "[M::%s::a_n->%ld, k->%ld]p->dist_pre:%d, c->dist_pre:%d, c->pre_idx:%u\n", __func__, a_n, k, p->dist_pre, c->dist_pre, c->hash_pre); + // fprintf(stderr, "[M::%s::]prs->%ld, pre->%ld, pqs->%ld, pqe->%ld, crs->%ld, cre->%ld, cqs->%ld, cqe->%ld\n", + // __func__, prs, pre, pqs, pqe, crs, cre, cqs, cqe); + } + assert(prs<=pre&&pqs<=pqe&&crs<=cre&&cqs<=cqe); + // assert(prs<=crs&&pre<=cre&&pqs<=cqs&&pqe<=cqe); + } + } + if(fal) fprintf(stderr, "[M::%s::tot->%ld, fal->%ld] ulid->%ld\n", __func__, tot, fal, debug_i); +} + +int64_t adjust_utg_chain_qoffset(uint64_t *r_srt, int64_t *r_pos, int64_t *q_pos, int64_t r_off) +{ + if(r_off < ((int64_t)(r_srt[0]>>32))) { + // fprintf(stderr, "r_off:%ld, r_srt[0]:%ld\n", r_off, ((int64_t)(r_srt[0]>>32))); + return q_pos[(uint32_t)r_srt[0]]; ///have small chance + } + if(r_off >= ((int64_t)(r_srt[3]>>32))) { + // fprintf(stderr, "r_off:%ld, r_srt[3]:%ld\n", r_off, ((int64_t)(r_srt[3]>>32))); + return q_pos[(uint32_t)r_srt[3]]; ///have small chance + } + int64_t k, rdis, qdis; + for (k = 0; k < 3; k++) { + if(r_off >= ((int64_t)(r_srt[k]>>32)) && r_off < ((int64_t)(r_srt[k+1]>>32))) break; + } + // if(k >= 3) { + // if(rs >= ((int64_t)(r_srt[2]>>32)) && rs <= ((int64_t)(r_srt[3]>>32))) k = 2; + // } + if(k >= 3) { + for (k = 0; k < 3; k++) { + if(r_off >= ((int64_t)(r_srt[k]>>32)) && r_off <= ((int64_t)(r_srt[k+1]>>32))) break; + } + } + assert(k < 3); + + qdis = q_pos[(uint32_t)r_srt[k+1]] - q_pos[(uint32_t)r_srt[k]]; + rdis = r_pos[(uint32_t)r_srt[k+1]] - r_pos[(uint32_t)r_srt[k]]; + if(qdis < 0) return -1; + return q_pos[(uint32_t)r_srt[k]] + get_offset_adjust(r_off-r_pos[(uint32_t)r_srt[k]], rdis, qdis); +} + +int64_t cal_qext_coor(int64_t pr, int64_t ar, int64_t pq, int64_t aq, int64_t r_off) +{ + int64_t q_off = -1, pd, ad; + if(r_off >= pr && r_off <= ar && ar >= pr && aq >= pq) { + q_off = pq + get_offset_adjust(r_off - pr, ar - pr, aq - pq); + } else { + pd = ((r_off >= pr)?(r_off-pr):(pr-r_off)); + ad = ((r_off >= ar)?(r_off-ar):(ar-r_off)); + q_off = ((ad <= pd)?aq:pq); + } + return q_off; +} + +void update_uovlp_chain_qse(ma_ug_t *ug, int64_t sidx, int64_t eidx, mg_lchain_t *a, int64_t a_n) +{ + // fprintf(stderr, "******[M::%s::] sidx:%ld, eidx:%ld\n", __func__, sidx, eidx); + if(eidx - sidx <= 1) return; + ///for ug chains, sidx >= 0 && eidx < a_n + assert(sidx>=0 && eidx= 0 + int64_t pqs, pqe, aqs, aqe, fail_s, fail_e; + if(sidx >= 0) { + get_u_offset(ug, &(a[sidx]), &r_pos[0], &r_pos[1], &q_pos[0], &q_pos[1]); + } else { + get_u_offset(ug, &(a[0]), &r_pos[0], &r_pos[1], &q_pos[0], &q_pos[1]); + } + + if(eidx < a_n) { + get_u_offset(ug, &(a[eidx]), &r_pos[2], &r_pos[3], &q_pos[2], &q_pos[3]); + } else { + get_u_offset(ug, &(a[a_n-1]), &r_pos[2], &r_pos[3], &q_pos[2], &q_pos[3]); + } + prs = r_pos[0]; pre = r_pos[1]; ars = r_pos[2]; are = r_pos[3]; + pqs = q_pos[0]; pqe = q_pos[1]; aqs = q_pos[2]; aqe = q_pos[3]; + // fprintf(stderr, "\n[M::%s::] sidx->%ld, eidx->%ld\n", __func__, + // sidx, r_pos[0], r_pos[1], q_pos[0], q_pos[1], + // eidx, r_pos[2], r_pos[3], q_pos[2], q_pos[3]); + // assert((left_q[0] >= 0 && left_q[1] >= 0) || (right_q[0] >= 0 && right_q[1] >= 0)); ///assert(re >= rs); + ///for ug chains, sidx >= 0 && eidx < a_n + assert(q_pos[0] >= 0 && q_pos[1] >= 0 && q_pos[2] >= 0 && q_pos[3] >= 0); + r_srt[0] = r_pos[0]; r_srt[0] <<= 32; + r_srt[1] = r_pos[1]; r_srt[1] <<= 32; r_srt[1] += 1; + r_srt[2] = r_pos[2]; r_srt[2] <<= 32; r_srt[2] += 2; + r_srt[3] = r_pos[3]; r_srt[3] <<= 32; r_srt[3] += 3; + radix_sort_gfa64(r_srt, r_srt + 4); + // assert(r_pos[(uint32_t)r_srt[0]] == (r_srt[0]>>32)); + // assert(r_pos[(uint32_t)r_srt[1]] == (r_srt[1]>>32)); + // assert(r_pos[(uint32_t)r_srt[2]] == (r_srt[2]>>32)); + // assert(r_pos[(uint32_t)r_srt[3]] == (r_srt[3]>>32)); + + for (i = sidx+1; i < eidx; i++) { + get_u_offset(ug, &(a[i]), &rs, &re, NULL, NULL); + // assert(rs >= prs && rs <= ars && re >= pre && re <= are); + assert(rs <= re); + a[i].qs = adjust_utg_chain_qoffset(r_srt, r_pos, q_pos, rs); fail_s = 1; + a[i].qe = adjust_utg_chain_qoffset(r_srt, r_pos, q_pos, re); fail_e = 1; + if(a[i].qs >= 0 && a[i].qs >= pqs && a[i].qs <= aqs) fail_s = 0; + if(a[i].qe >= 0 && a[i].qe >= pqe && a[i].qe <= aqe) fail_e = 0; + if(a[i].qs > a[i].qe) fail_s = fail_e = 1; + + if(fail_s || fail_e) { + // if(re >= pre && are >= pre && re <= are) {///aqe >= pqe is always true + // a[i].qe = pqe + get_offset_adjust(re-pre, are-pre, aqe-pqe);///first priority + // } else {///abnormal coordinates + // pd = ((re >= pre)?(re-pre):(pre-re)); + // ad = ((re >= are)?(re-are):(are-re)); + // a[i].qe = ((ad <= pd)?aqe:pqe); + // } + a[i].qe = cal_qext_coor(pre, are, pqe, aqe, re); + // if(aqs <= a[i].qe) { + // if(rs >= prs && ars >= prs && rs <= ars) {///aqs >= pqs is always true + // a[i].qs = pqs + get_offset_adjust(rs-prs, ars-prs, aqs-pqs); + // } else { + // pd = ((rs >= prs)?(rs-prs):(prs-rs)); + // ad = ((rs >= ars)?(rs-ars):(ars-rs)); + // a[i].qs = ((ad <= pd)?aqs:pqs); + // } + // } else { + // if(rs >= prs && re >= prs && rs <= re) {///as a[i].qe >= pqe, a[i].qe >= pqs + // a[i].qs = pqs + get_offset_adjust(rs-prs, re-prs, a[i].qe-pqs); + // } else { + // pd = ((rs >= prs)?(rs-prs):(prs-rs)); + // ad = ((rs >= re)?(rs-re):(re-rs)); + // a[i].qs = ((ad <= pd)?a[i].qe:pqs); + // } + // } + a[i].qs = cal_qext_coor(prs, (a[i].qe<=aqs)?re:ars, pqs, (a[i].qe<=aqs)?a[i].qe:aqs, rs); + } + // assert(a[i].qs >= pqs && a[i].qs <= aqs && a[i].qe >= pqe && a[i].qe <= aqe); assert(a[i].qs <= a[i].qe); + assert(a[i].qs >= pqs && a[i].qs <= aqs && a[i].qe >= pqe && a[i].qe <= aqe && a[i].qs <= a[i].qe); + // fprintf(stderr, "[M::%s::i->%ld] rs::%ld, re::%ld, a[i].qs::%d, a[i].qe::%d\n", + // __func__, i, rs, re, a[i].qs, a[i].qe); + + if(i + 1 < eidx) { + q_pos[0] = a[i].qs; q_pos[1] = a[i].qe; r_pos[0] = rs; r_pos[1] = re; + r_srt[0] = r_pos[0]; r_srt[0] <<= 32; + r_srt[1] = r_pos[1]; r_srt[1] <<= 32; r_srt[1] += 1; + r_srt[2] = r_pos[2]; r_srt[2] <<= 32; r_srt[2] += 2; + r_srt[3] = r_pos[3]; r_srt[3] <<= 32; r_srt[3] += 3; + radix_sort_gfa64(r_srt, r_srt + 4); + // assert(r_pos[(uint32_t)r_srt[0]] == (r_srt[0]>>32)); + // assert(r_pos[(uint32_t)r_srt[1]] == (r_srt[1]>>32)); + // assert(r_pos[(uint32_t)r_srt[2]] == (r_srt[2]>>32)); + // assert(r_pos[(uint32_t)r_srt[3]] == (r_srt[3]>>32)); + // fprintf(stderr, "[Srt::i->%ld] , \n", i, + // r_pos[0], r_pos[1], q_pos[0], q_pos[1], + // r_pos[2], r_pos[3], q_pos[2], q_pos[3]); + } + prs = rs; pre = re; pqs = a[i].qs; pqe = a[i].qe; + } + + + + // if(right_q[0] < 0 || right_q[1] < 0) { + // for (i = sidx+1; i < eidx; i++) { + // get_u_offset(ug, &(a[i]), &rs, &re, NULL, NULL); + // a[i].qs = left_q[0] + get_offset_adjust(rs - left_r[0], left_r[1]-left_r[0], left_q[1]-left_q[0]); + // a[i].qe = left_q[1] + (re - left_r[1]); + // left_q[0] = a[i].qs; left_q[1] = a[i].qe; + // left_r[0] = rs; left_r[1] = re; + // } + // } + + // if(left_q[0] < 0 || left_q[1] < 0) { + // for (i = eidx-1; i > sidx; i--) { + // get_u_offset(ug, &(a[i]), &rs, &re, NULL, NULL); + // a[i].qe = right_q[1] - get_offset_adjust(right_r[1]-re, right_r[1]-right_r[0], right_q[1]-right_q[0]); + // a[i].qs = right_q[0] - (right_r[0]-rs); + // right_q[0] = a[i].qs; right_q[1] = a[i].qe; + // right_r[0] = rs; right_r[1] = re; + // } + // } + + // fprintf(stderr, "******[M::%s::] right_q[0]:%ld, right_q[1]:%ld\n", __func__, right_q[0], right_q[1]); +} + + +void debug_update_uovlp_chain_qse(ma_ug_t *ug, mg_lchain_t *a, int64_t a_n, int64_t ulid) +{ + if(a_n <= 2) return; + int64_t r0_s, r0_e, q0_s, q0_e, k; + int64_t r1_s, r1_e, q1_s, q1_e; + get_u_offset(ug, &(a[0]), &r0_s, &r0_e, &q0_s, &q0_e); + get_u_offset(ug, &(a[a_n-1]), &r1_s, &r1_e, &q1_s, &q1_e); + /**if(r0_s <= r1_s && r0_e <= r1_e && q0_s <= q1_s && q0_e <= q1_e)**/ { + for (k = 1; k + 1 < a_n; k++) a[k].qs = a[k].qe = -1; + update_uovlp_chain_qse(ug, 0, a_n-1, a, a_n); + for (k = 1; k < a_n; k++) { + get_u_offset(ug, a + k - 1, &r0_s, &r0_e, &q0_s, &q0_e); + get_u_offset(ug, a + k, &r1_s, &r1_e, &q1_s, &q1_e); + // if(!(r0_s <= r1_s && r0_e <= r1_e && q0_s <= q1_s && q0_e <= q1_e)) { + // fprintf(stderr, "ulid:%ld, r0_s:%ld, r1_s:%ld, r0_e:%ld, r1_e:%ld, q0_s:%ld, q1_s:%ld, q0_e:%ld, q1_e:%ld\n", ulid, + // r0_s, r1_s, r0_e, r1_e, q0_s, q1_s, q0_e, q1_e); + // } + // assert(q0_s <= q1_s && q0_e <= q1_e && q0_s <= q0_e && q1_s <= q1_e); + if(r0_s <= r1_s) assert(q0_s <= q1_s); + if(r0_e <= r1_e) assert(q0_e <= q1_e); + // assert(r0_s <= r1_s && r0_e <= r1_e && q0_s <= q1_s && q0_e <= q1_e); + assert(q0_s>=0 && q0_e>=0 && q1_s>=0 && q1_e>=0); + } + } +} + +void fill_unaligned_alignments(ma_ug_t *ug, mg_lchain_t *a, int64_t a_n, int64_t offset, int64_t ulid) +{ + // fprintf(stderr, "\n[M::%s::] a_n->%ld, offset->%ld\n", __func__, a_n, offset); + if(a_n == 0) return; + int64_t k, l; + for (k = 0, l = ug->g->seq[a[0].v>>1].len; k < a_n; k++) { + l -= ug->g->seq[a[k].v>>1].len; + if(a[k].off < 0) a[k].qs = a[k].qe = -1; + a[k].off = l; a[k].hash_pre = (uint32_t)-1; + if(k > 0) a[k].hash_pre = offset + k - 1; + // fprintf(stderr, "k->%ld, l->%ld, [M::utg%.6u%c::%c::len->%u], qs->%u, qe->%u, rs->%u, re->%u\n", k, l, + // (a[k].v>>1)+1, "lc"[ug->u.a[a[k].v>>1].circ], "+-"[a[k].v&1], ug->u.a[a[k].v>>1].len, + // a[k].qs, a[k].qe, a[k].rs, a[k].re); + l += ug->g->seq[a[k].v>>1].len + a[k].dist_pre; + } + + // debug_update_uovlp_chain_qse(ug, a, a_n, ulid); + + for (l = -1, k = 0; k <= a_n; k++) { + if(k == a_n || a[k].qs >= 0) { ///a[k] and a[l] are anchors + if(k-l>1) update_uovlp_chain_qse(ug, l, k, a, a_n); + l = k; + } + } +} + +void sort_uc_block_qe(uc_block_t* a, uint64_t a_n) { + radix_sort_uc_block_t_qe_srt(a, a + a_n); +} + +void update_ul_vec_t_ug(const ul_idx_t *uref, ul_vec_t *rch, vec_mg_lchain_t *uc, int64_t ulid) +{ + int64_t k, ucn = uc->n, a_n, m, l, lk; ma_ug_t *ug = uref->ug; mg_lchain_t *ix, *a; uc_block_t *z; + for (k = 0, a_n = 0; k < ucn; k += ix->cnt + 1) { + ix = &(uc->a[k]); assert(ix->v == (uint32_t)-1); ix->hash_pre = (uint32_t)-1; ix->off = -1; + fill_unaligned_alignments(ug, uc->a + k + 1, ix->cnt, k + 1, ulid); a_n += ix->cnt; + } + + ///up to now, given a in swap + ///x->ts and x->te are the coordinates in unitig + ///x->qs and x->qe are the coordinates in UL + ///x->dist_pre is the idx of this chain at rch + // debug_intermediate_chain(uref->ug, uc->a, uc->n, 1, debug_i); + // dd_ul_vec_t(uref, swap->a, swap->n, rch); + rch->bb.n = 0; kv_resize(uc_block_t, rch->bb, (uint64_t)a_n); + for (k = 0; k < ucn; k += ix->cnt + 1) { + ix = &(uc->a[k]); assert(ix->v == (uint32_t)-1); ix->hash_pre = (uint32_t)-1; ix->off = -1; + a = uc->a + k + 1; a_n = ix->cnt; + for (m = 0; m < a_n; m++) { + kv_pushp(uc_block_t, rch->bb, &z); + z->hid = (a[m].v>>1); z->rev = (a[m].v&1); + z->pchain = 1; z->base = 0; z->el = 1; + z->qs = a[m].qs; z->qe = a[m].qe; + z->te = a[m].re; z->ts = a[m].rs; + z->pidx = k + 1 + m; z->pdis = z->aidx = (uint32_t)-1; + // fprintf(stderr, "[M::%s::k->%ld] m->%ld, utg%.6dl(%c), q::[%u, %u), t::[%u, %u)\n", + // __func__, k, m, (int32_t)z->hid+1, "+-"[z->rev], z->qs, z->qe, z->ts, z->te); + } + } + + a_n = rch->bb.n; a = uc->a; + radix_sort_uc_block_t_qe_srt(rch->bb.a, rch->bb.a + rch->bb.n); + for (k = 1, lk = 0, l = m = -1; k <= a_n; k++) { + a[rch->bb.a[k-1].pidx].off = k-1; + if(m < (int64_t)rch->bb.a[k-1].pidx) { + m = rch->bb.a[k-1].pidx; l = k-1; + } + if(k == a_n || rch->bb.a[k].qe != rch->bb.a[lk].qe) { + if(k - lk > 1) { + radix_sort_uc_block_t_qs_srt(rch->bb.a+lk, rch->bb.a+k); + } + lk = k; + } + } + // for (k = 0, l = m = -1; k < a_n; k++) { + // a[rch->bb.a[k].pidx].off = k; + // if(m < (int64_t)rch->bb.a[k].pidx) { + // m = rch->bb.a[k].pidx; l = k; + // } + // } + + for (k = 0; k < a_n; k++) { + if(a[rch->bb.a[k].pidx].hash_pre == (uint32_t)-1) { + rch->bb.a[k].pidx = rch->bb.a[k].pdis = rch->bb.a[k].aidx = (uint32_t)-1; + continue; + } + m = rch->bb.a[k].pidx; + rch->bb.a[k].pidx = a[a[m].hash_pre].off; + rch->bb.a[k].pdis = a[a[m].hash_pre].dist_pre; + rch->bb.a[rch->bb.a[k].pidx].aidx = k; + } + // fprintf(stderr, "+ulid->%ld\n", ulid); + uint32_t sp = (uint32_t)-1, ep = (uint32_t)-1, ch_n = 0; + k = l/**a_n - 1**/;///start from the max chain + for (l = 0; k >= 0; ) { + if(sp == (uint32_t)-1 || rch->bb.a[k].qe <= sp) { + if(sp != (uint32_t)-1) l += ep - sp; + sp = rch->bb.a[k].qs; ep = rch->bb.a[k].qe; + } else { + sp = MIN(sp, rch->bb.a[k].qs); + } + if(rch->bb.a[k].pidx == (uint32_t)-1) k = -1; + else k = rch->bb.a[k].pidx; + ch_n++; + } + + rch->dd = 0; + if(sp != (uint32_t)-1) l += ep - sp; + l = (int64_t)rch->rlen - l; + + // fprintf(stderr, "-ulid:%ld, l:%ld, rch->rlen:%u\n", ulid, l, rch->rlen); + if(l == 0) { + rch->dd = 1; + } else if(l < ((int64_t)rch->rlen)*0.001) { + rch->dd = 2; + } else if(ch_n < rch->bb.n) {///multiple chain, might be useful for the scaffolding + rch->dd = 3; + } + // fprintf(stderr, "[M::%s::] rch->dd::%u, rch->bb.n::%u\n", + // __func__, rch->dd, (uint32_t)rch->bb.n); +} + +void print_raw_chains(vec_mg_lchain_t *uc, int64_t ulid) +{ + if(uc->n <= 0) return; + int64_t k, m, ucn = uc->n, k_cnt, a_n; mg_lchain_t *ix, *a; + for (k = m = 0; k < ucn; k += k_cnt) { + ix = &(uc->a[k]); assert(ix->v == (uint32_t)-1); k_cnt = ix->cnt + 1; + a = uc->a + k + 1; a_n = ix->cnt; + for (m = 0; m < a_n; m++) { + if(a[m].off < 0) break; + } + if(m < a_n) fprintf(stderr, "ulid->%ld\n", ulid); + } +} + +void hc_shortest_k(void *km0, const asg_t *g, uint32_t src, int32_t n_dst, mg_path_dst_t *dst, int32_t max_dist, int32_t max_k, +st_mt_t *dst_done, uint64_t *dst_group, vec_sp_node_t *out, vec_mg_pathv_t *res, uint64_t first_src_ban, +uint64_t detect_mul_way, float len_dif); + +void debug_ul_vec_t_chain(void *km, const asg_t *g, ul_vec_t *rch, st_mt_t *dst_done, vec_sp_node_t *out) +{ + if(rch->dd == 0) return; + uint64_t k, i, v, w, nv; int64_t dd; asg_arc_t *av; + mg_path_dst_t dst; uint64_t dst_group; uc_block_t *a = rch->bb.a; + for (k = 0; k < rch->bb.n; k++) { + if(a[k].pidx != (uint32_t)-1) assert(a[a[k].pidx].aidx == k); + if(a[k].aidx != (uint32_t)-1) assert(a[a[k].aidx].pidx == k); + if(a[k].pidx == (uint32_t)-1) continue; + + v = (a[k].hid<<1)|a[k].rev; v ^= 1; + w = (a[a[k].pidx].hid<<1)|a[a[k].pidx].rev; w ^= 1; + + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (i = 0; i < nv; i++) { + if(av[i].v == w) break; + } + // if(i >= nv) { + // // fprintf(stderr, "[M::%s::]\n", __func__); + // fprintf(stderr, "[M::%s::]\tutg%.6dl(%c)\t->\tutg%.6dl(%c)\n", __func__, (int32_t)(v>>1)+1, "+-"[v&1], (int32_t)(w>>1)+1, "+-"[w&1]); + // } + if(i < nv) { + dd = (int64_t)((uint32_t)(av[i].ul)); + } else { + memset(&dst, 0, sizeof(dst)); + dst.v = w; + dst.target_dist = a[k].pdis; + dst.target_hash = 0; dst.check_hash = 0; + hc_shortest_k(km, g, v, 1, &dst, dst.target_dist, MG_MAX_SHORT_K, dst_done, &dst_group, out, NULL, 1, 0, 0); + dd = dst.dist; + } + if(a[k].pdis != dd) { + fprintf(stderr, "[M::%s::]\tutg%.6dl(%c)\t->\tutg%.6dl(%c)\tdist_pre:%d\td:%ld\n", __func__, (int32_t)(v>>1)+1, "+-"[v&1], + (int32_t)(w>>1)+1, "+-"[w&1], a[k].pdis, dd); + } + } +} + + +int64_t gl_chain_refine_advance_combine_with_trans(mg_tbuf_t *b, ul_vec_t *rch, overlap_region_alloc* olist, Correct_dumy* dumy, haplotype_evdience_alloc *hap, st_mt_t *sps, glchain_t *ll, gdpchain_t *gdp, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, int64_t qlen, const ug_opt_t *uopt, +int64_t debug_i, int64_t tid, void *km) +{ + ll->tk.n = ll->lo.n = 0; + kv_ul_ov_t *idx = &(ll->lo); + uint64_t o2 = gl_chain_gen(olist, uref, idx, 0, hap, km); + if(idx->n == 0) return 0; + // fprintf(stderr, "(beg0) [M::%s::tid:%ld] debug_i:%ld, qlen:%ld, # cis:%lu, # trans:%lu\n", __func__, tid, debug_i, qlen, (uint64_t)idx->n, o2); + int64_t max_idx, occ = 0, f = 0; + + kv_resize_km(km, uint64_t, ll->srt.a, idx->n); + kv_resize_km(km, uint64_t, hap->snp_srt, idx->n); + kv_resize_km(km, ul_ov_t, ll->tk, idx->n); + ///chain exact U-matches + occ = gl_chain_advance(idx, ll->tk.a, uref, uopt, G_CHAIN_BW, /**diff_ec_ul**/N_GCHAIN_RATE, qlen, UG_SKIP, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 0, NULL, uref->ug, debug_i, km); + if(occ) { + if(ff_chain(idx, qlen, 0.99/**P_CHAIN_COV**/, -1/**G_CHAIN_TRANS_RATE**/, ll->tk.a, NULL, NULL, NULL, diff_ec_ul, winLen, km)) { + f = l2g_res_chain(uref->ug, ll->tk.a+idx->a[idx->n-1].ts, idx->a[idx->n-1].te-idx->a[idx->n-1].ts, &(gdp->swap), -1/**N_GCHAIN_RATE**/); + } else if(o2) {///means there are trans overlaps + gl_chain_gen(olist, uref, idx, 1, hap, km); + kv_resize_km(km, uint64_t, ll->srt.a, idx->n); + kv_resize_km(km, uint64_t, hap->snp_srt, idx->n); + kv_resize_km(km, ul_ov_t, ll->tk, idx->n); + ///chain all U-matches + occ = gl_chain_advance(idx, ll->tk.a, uref, uopt, G_CHAIN_BW, /**diff_ec_ul**/N_GCHAIN_RATE, qlen, UG_SKIP, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 0, NULL, uref->ug, debug_i, km); + if(ff_chain(idx, qlen, 0.99/**P_CHAIN_COV**/, G_CHAIN_TRANS_RATE, ll->tk.a, olist, hap, uref, diff_ec_ul, winLen, km)) { + f = l2g_res_chain(uref->ug, ll->tk.a+idx->a[idx->n-1].ts, idx->a[idx->n-1].te-idx->a[idx->n-1].ts, &(gdp->swap), -1/**N_GCHAIN_RATE**/); + } + } + } + // fprintf(stderr, "(beg1) [M::%s] debug_i:%ld, qlen:%ld\n", __func__, debug_i, qlen); + if(!f) { + gl_chain_gen(olist, uref, idx, 1, hap, km); + l2g_chain(uref, idx, &(gdp->l)); ll->tk.n = 0; + ///buffer + kv_resize(uint64_t, ll->srt.a, gdp->l.n); kv_resize(uint64_t, hap->snp_srt, gdp->l.n); + kv_resize(uint64_t, gdp->v, gdp->l.n); kv_resize(int64_t, gdp->f, gdp->l.n); + max_idx = hc_gchain1_dp(b->km, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), &(gdp->path), rch->rlen, + uopt, G_CHAIN_BW, diff_ec_ul, -1, ll->srt.a.a, sps, gdp->f.a, hap->snp_srt.a, gdp->v.a); + if(max_idx >= 0 && gen_max_gchain_adv(b->km, uref, debug_i, sps, &(gdp->l), &(ll->tk), NULL, rch->rlen, P_CHAIN_COV, 0.3/**P_FRAGEMENT_PRIMARY_CHAIN_COV**/, + 0.1/**P_FRAGEMENT_PRIMARY_SECOND_COV**/, PRIMARY_UL_CHAIN_MIN, uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), ll->srt.a.a, &(gdp->swap))) { + // print_raw_chains(&(gdp->swap), debug_i); + f = check_trans_rate_gap(&(gdp->swap), &(ll->tk), olist, hap, uref, diff_ec_ul, winLen, G_CHAIN_TRANS_RATE); + } + } + // if(debug_i == 1756) fprintf(stderr, "[M::%s] ulid:%ld, qlen:%ld, f:%ld\n", __func__, debug_i, qlen, f); + if(f) update_ul_vec_t_ug(uref, rch, &(gdp->swap), debug_i); + // debug_ul_vec_t_chain(km, uref->ug->g, rch, &(gdp->dst_done), &(gdp->out)); + // fprintf(stderr, "(beg3) [M::%s::tid:%ld] debug_i:%ld, qlen:%ld\n", __func__, tid, debug_i, qlen); + return 1; +} + +int64_t gl_chain_refine_advance_combine(mg_tbuf_t *b, ul_vec_t *rch, overlap_region_alloc* olist, Correct_dumy* dumy, haplotype_evdience_alloc *hap, st_mt_t *sps, glchain_t *ll, gdpchain_t *gdp, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, int64_t qlen, const ug_opt_t *uopt, +int64_t debug_i, int64_t tid, void *km) +{ + ll->tk.n = ll->lo.n = 0; + kv_ul_ov_t *idx = &(ll->lo); + gl_chain_gen(olist, uref, idx, 0, hap, km);///no trans + // fprintf(stderr, "0-[M::%s] idx->n::%lu\n", __func__, (uint64_t)idx->n); + if(idx->n == 0) return 0; + // fprintf(stderr, "(beg0) [M::%s::tid:%ld] debug_i:%ld, qlen:%ld, # cis:%lu, # trans:%lu\n", __func__, tid, debug_i, qlen, (uint64_t)idx->n, o2); + int64_t max_idx, occ = 0, f = 0; + + kv_resize_km(km, uint64_t, ll->srt.a, idx->n); + kv_resize_km(km, uint64_t, hap->snp_srt, idx->n); + kv_resize_km(km, ul_ov_t, ll->tk, idx->n); + ///chain exact U-matches + occ = gl_chain_advance(idx, ll->tk.a, uref, uopt, G_CHAIN_BW, /**diff_ec_ul**/N_GCHAIN_RATE, qlen, UG_SKIP, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 0, NULL, uref->ug, debug_i, km); + if(occ) { + if(ff_chain(idx, qlen, 0.99/**P_CHAIN_COV**/, -1/**G_CHAIN_TRANS_RATE**/, ll->tk.a, NULL, NULL, NULL, diff_ec_ul, winLen, km)) { + f = l2g_res_chain(uref->ug, ll->tk.a+idx->a[idx->n-1].ts, idx->a[idx->n-1].te-idx->a[idx->n-1].ts, &(gdp->swap), -1/**N_GCHAIN_RATE**/); + } + } + // fprintf(stderr, "1-[M::%s] f::%ld\n", __func__, f); + // fprintf(stderr, "(beg1) [M::%s] debug_i:%ld, qlen:%ld\n", __func__, debug_i, qlen); + if(!f) { + gl_chain_gen(olist, uref, idx, 0, hap, km);///no trans + l2g_chain(uref, idx, &(gdp->l)); ll->tk.n = 0; + ///buffer + kv_resize(uint64_t, ll->srt.a, gdp->l.n); kv_resize(uint64_t, hap->snp_srt, gdp->l.n); + kv_resize(uint64_t, gdp->v, gdp->l.n); kv_resize(int64_t, gdp->f, gdp->l.n); + max_idx = hc_gchain1_dp(b->km, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), &(gdp->path), rch->rlen, + uopt, G_CHAIN_BW, diff_ec_ul, -1, ll->srt.a.a, sps, gdp->f.a, hap->snp_srt.a, gdp->v.a); + if(max_idx >= 0 && gen_max_gchain_adv(b->km, uref, debug_i, sps, &(gdp->l), &(ll->tk), NULL, rch->rlen, P_CHAIN_COV, 0.3/**P_FRAGEMENT_PRIMARY_CHAIN_COV**/, + 0.1/**P_FRAGEMENT_PRIMARY_SECOND_COV**/, PRIMARY_UL_CHAIN_MIN, uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), ll->srt.a.a, &(gdp->swap))) { + // print_raw_chains(&(gdp->swap), debug_i); + // f = check_trans_rate_gap(&(gdp->swap), &(ll->tk), olist, hap, uref, diff_ec_ul, winLen, G_CHAIN_TRANS_RATE); + f = 1; + } + } + // if(debug_i == 1756) fprintf(stderr, "[M::%s] ulid:%ld, qlen:%ld, f:%ld\n", __func__, debug_i, qlen, f); + if(f) update_ul_vec_t_ug(uref, rch, &(gdp->swap), debug_i); + // debug_ul_vec_t_chain(km, uref->ug->g, rch, &(gdp->dst_done), &(gdp->out)); + // fprintf(stderr, "(beg3) [M::%s::tid:%ld] debug_i:%ld, qlen:%ld\n", __func__, tid, debug_i, qlen); + return 1; +} + +// #define aln_sc(a, w) (((int64_t)((a).sec))-((int64_t)(((a).qe-(a).qs-(a).sec)*(w)))) +#define aln_sc(a, trans_w, err_w) (((int64_t)((a).align_length))-((int64_t)(((a).overlapLen-(a).align_length)*(trans_w)))-(((int64_t)((a).non_homopolymer_errors))*(err_w))) + +void gen_gl_aln(overlap_region_alloc* olist, const ul_idx_t *uref, kv_ul_ov_t *res) +{ + uint64_t k; ul_ov_t *p = NULL; + res->n = 0; kv_resize(ul_ov_t, *res, olist->length); + for (k = 0; k < olist->length; k++) { + // fprintf(stderr, "+++[M::%s::utg%.6dl] q[%d, %d), t[%d, %d), tot::%u, cis::%u, err::%u\n", __func__, + // (int32_t)olist->list[k].y_id+1, olist->list[k].x_pos_s, olist->list[k].x_pos_e+1, + // olist->list[k].y_pos_s, olist->list[k].y_pos_e+1, + // olist->list[k].overlapLen, olist->list[k].align_length, olist->list[k].non_homopolymer_errors); + p = &(res->a[res->n++]); assert(olist->list[k].overlapLen >= olist->list[k].align_length); + p->qn = k; p->qs = olist->list[k].x_pos_s; p->qe = olist->list[k].x_pos_e+1; + p->tn = olist->list[k].y_id; p->sec = olist->list[k].align_length; + p->rev = olist->list[k].y_pos_strand; p->el = (olist->list[k].is_match==1?1:0); + if(p->rev) { + p->ts = uref->ug->u.a[p->tn].len - (olist->list[k].y_pos_e+1); + p->te = uref->ug->u.a[p->tn].len - olist->list[k].y_pos_s; + } else { + p->ts = olist->list[k].y_pos_s; + p->te = olist->list[k].y_pos_e+1; + } + } +} + +void gen_gg_aln(overlap_region_alloc* olist, const ul_idx_t *uref, int64_t trans_sc, vec_mg_lchain_t *res) +{ + uint64_t k; mg_lchain_t *p = NULL; + res->n = 0; kv_resize(mg_lchain_t, *res, olist->length); + for (k = 0; k < olist->length; k++) { + p = &(res->a[res->n++]); memset(p, 0, sizeof((*p))); + p->v = ((olist->list[k].y_id<<1)|(olist->list[k].y_pos_strand)); p->off = k; + p->score = aln_sc((olist->list[k]), (trans_sc), UG_TRANS_ERR_W); + p->qs = olist->list[k].x_pos_s; p->qe = olist->list[k].x_pos_e+1; + if((p->v&1)) { + p->rs = uref->ug->u.a[p->v>>1].len - (olist->list[k].y_pos_e+1); + p->re = uref->ug->u.a[p->v>>1].len - olist->list[k].y_pos_s; + } else { + p->rs = olist->list[k].y_pos_s; + p->re = olist->list[k].y_pos_e+1; + } + } +} + +int64_t get_overlap_region_sub_err_debug(overlap_region *o, int64_t qs, int64_t *sec_err) +{ + (*sec_err) = 0; + if(o->w_list.n <= 0) return 0; + int64_t k; double rr; int64_t terr, dd; + for (k = o->w_list.n-1, terr = 0; k >= 0 && qs < o->w_list.a[k].x_end; k--) { + if(qs >= o->w_list.a[k].x_start && qs < o->w_list.a[k].x_end) { + // if(qs == 102178) { + // fprintf(stderr, "[M::%s::qs->%ld] k::%ld, wn::%u, x::[%d, %d), clen::%u, terr::%ld, sec_err::%ld\n", + // __func__, qs, k, (uint32_t)o->w_list.n, o->w_list.a[k].x_start, o->w_list.a[k].x_end, + // o->w_list.a[k].clen, terr, (*sec_err)); + // } + if(o->w_list.a[k].clen > 0) { + rr = ((double)(o->w_list.a[k].x_end-qs))/ + ((double)(o->w_list.a[k].x_end-o->w_list.a[k].x_start)); + dd = o->w_list.a[k].clen*rr; + (*sec_err) += (dd>0?dd:1); + } + + terr += ((o->w_list.a[k].clen > 0)?(o->w_list.a[k].x_end-qs):(0)); + return terr; + } + if(o->w_list.a[k].clen > 0) { + (*sec_err) += o->w_list.a[k].clen; + terr += o->w_list.a[k].x_end-o->w_list.a[k].x_start; + } + } + return terr; +} + +int64_t get_overlap_region_sub_err(overlap_region *o, rtrace_iter *it, int64_t qs, int64_t *sec_err) +{ + if(o->w_list.n <= 0) { + (*sec_err) = 0; + return 0; + } + if(it->k == INT32_MAX) { + it->k = o->w_list.n-1; + it->cur_qoff = o->x_pos_e+1; + it->qoff = o->w_list.a[it->k].x_end; + it->werr = 0; it->werr0 = 0; + } + assert(qs <= it->cur_qoff); + it->cur_qoff = qs; (*sec_err) = it->werr0; + + if(qs == it->qoff) { + (*sec_err) = it->werr0; + return it->werr; + } + double rr; int64_t terr; + for (; (it->k >= 0) && (qs < o->w_list.a[it->k].x_end); it->k--) { + if(qs >= o->w_list.a[it->k].x_start && qs < o->w_list.a[it->k].x_end) { + (*sec_err) = 0; + if(o->w_list.a[it->k].clen > 0) { + rr = ((double)(o->w_list.a[it->k].x_end-qs))/ + ((double)(o->w_list.a[it->k].x_end-o->w_list.a[it->k].x_start)); + (*sec_err) = rr*o->w_list.a[it->k].clen; + // if((*sec_err) == 0) (*sec_err) = 1; + } + (*sec_err) += it->werr0; + + terr = ((o->w_list.a[it->k].clen > 0)?(o->w_list.a[it->k].x_end-qs):(0)); + return it->werr + terr; + } + if(o->w_list.a[it->k].clen > 0) { + it->werr += o->w_list.a[it->k].x_end-o->w_list.a[it->k].x_start; + it->werr0 += o->w_list.a[it->k].clen; + } + it->qoff = o->w_list.a[it->k].x_start; + } + + (*sec_err) = it->werr0; + return it->werr; +} + + +int64_t get_ecov_el(const ul_idx_t *uref, const ug_opt_t *uopt, uint32_t v, uint32_t w, int64_t bw, double diff_ec_ul, int64_t dq, uint64_t mode, int64_t *el) +{ + int64_t dt = -1, dif, mm; (*el) = 0; + uint32_t nv, i; asg_arc_t *av = NULL; ///ma_hit_t *x = NULL; + if(!mode) { + const asg_t *g = uref?uref->ug->g:NULL; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (i = 0; i < nv; i++) { + if(av[i].del || av[i].v != w) continue; + dt = av[i].ol; (*el) = av[i].el; + // if(v==1772 && w==1769) fprintf(stderr, "+++v:%u, w:%u, ou:%u\n", v, w, av[i].ou); + // if((v>>1) == 3012 && (w>>1) == 3011) fprintf(stderr, "******************\n"); + break; + } + }else { + ma_hit_t_alloc* src = uopt->sources; + int64_t min_ovlp = uopt->min_ovlp; + int64_t max_hang = uopt->max_hang; + uint64_t z, qn, tn, x = v>>1; int32_t r = 1; asg_arc_t e; + for (z = 0; z < src[x].length; z++) { + qn = Get_qn(src[x].buffer[z]); tn = Get_tn(src[x].buffer[z]); + if(tn != (w>>1)) continue; + r = ma_hit2arc(&(src[x].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); + if(r < 0) continue; + if((e.ul>>32) != v || e.v != w) continue; + dt = e.ol; (*el) = src[x].buffer[z].el; + break; + } + } + if(dt < 0) return 0; + dif = (dq>dt? dq-dt:dt-dq); + mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; + // if((v>>1) == 1163 && (w>>1) == 1168) fprintf(stderr, ">>>>>>dis_q:%ld, dis_t:%ld, dif:%ld, mm:%ld\n", dis_q, dis_t, dif, mm); + if(dif <= mm) return 1; + return 0; +} + +//ai > aj +int64_t cal_gl_chain_lin_sc(ul_ov_t *a, int32_t ai, int32_t aj, rtrace_iter *tc, overlap_region *ol, All_reads *ridx, ma_ug_t *ug, +const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, uint64_t mode, int64_t trans_sc, int64_t sec_sec, +int32_t *f, int64_t debug_i) +{ + ul_ov_t *li = &(a[ai]), *lj = &(a[aj]); + ///li is the suffix of lj + if(lj->qs >= li->qs) return INT32_MIN; + uint32_t li_v = (li->tn<<1)|li->rev, lj_v = (lj->tn<<1)|lj->rev; + int64_t qo = infer_rovlp(li, lj, NULL, NULL, ridx, ug), trans_l = 0, sec_err = 0, sc, sc0, el; ///overlap length in query (UL read) + ///li_v == lj_v is possiable + if(get_ecov_el(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, mode, &el)) { + trans_l = get_overlap_region_sub_err(&(ol[li->qn]), tc, lj->qe, &sec_err); + sc = f[aj] + ((int64_t)(li->qe - lj->qe)) - (trans_l*trans_sc) - (sec_err*sec_sec); + + // char *as = NULL; + // asprintf(&as, "+[M::utg%.6dl] utg%.6dl, liq::[%u, %u), ljq::[%u, %u), trans_l::%ld, sec_err::%ld, sc::%ld, f[aj]::%d\n", + // (int32_t)li->tn+1, (int32_t)lj->tn+1, li->qs, li->qe, lj->qs, lj->qe, trans_l, sec_err, sc, f[aj]); + // push_vlog(&(overall_zdbg->a[debug_i]), as); free(as); as = NULL; + // fprintf(stderr, "+[M::utg%.6dl] utg%.6dl, liq::[%u, %u), ljq::[%u, %u), trans_l::%ld, sec_err::%ld, sc::%ld, f[aj]::%d\n", + // (int32_t)li->tn+1, (int32_t)lj->tn+1, li->qs, li->qe, lj->qs, lj->qe, trans_l, sec_err, sc, f[aj]); + if((el == 0) && ((trans_l > 0) || (sec_err > 0)) && (lj->qe > li->qs)) { + rtrace_iter tr; tr.k = INT32_MAX; sc0 = sc; + sc = f[aj] + aln_sc(ol[(*li).qn], trans_sc, sec_sec); + trans_l = get_overlap_region_sub_err(&(ol[lj->qn]), &tr, li->qs, &sec_err); + sc -= (((int64_t)(lj->qe - li->qs)) - (trans_l*trans_sc) - (sec_err*sec_sec)); + + + // char *as = NULL; + // asprintf(&as, "-[M::utg%.6dl] utg%.6dl, liq::[%u, %u), ljq::[%u, %u), trans_l::%ld, sec_err::%ld, sc::%ld, f[aj]::%d\n", + // (int32_t)li->tn+1, (int32_t)lj->tn+1, li->qs, li->qe, lj->qs, lj->qe, trans_l, sec_err, sc, f[aj]); + // push_vlog(&(overall_zdbg->a[debug_i]), as); free(as); as = NULL; + + if(sc < sc0) sc = sc0; + // fprintf(stderr, "-[M::utg%.6dl] utg%.6dl, liq::[%u, %u), ljq::[%u, %u), trans_l::%ld, sec_err::%ld, sc::%ld, f[aj]::%d, aln_sc::%ld\n", + // (int32_t)li->tn+1, (int32_t)lj->tn+1, li->qs, li->qe, lj->qs, lj->qe, trans_l, sec_err, sc, f[aj], aln_sc(ol[(*li).qn], trans_sc, sec_sec)); + } + // int64_t trans_l_debug, sec_err_debug; + // trans_l_debug = get_overlap_region_sub_err_debug(&(ol[li->qn]), lj->qe, &sec_err_debug); + // if(!(trans_l_debug == trans_l && sec_err_debug == sec_err)) { + // fprintf(stderr, "[M::%s::qs->%u] trans_l::%ld, trans_l_debug::%ld, sec_err::%ld, sec_err_debug::%ld\n", + // __func__, lj->qe, trans_l, trans_l_debug, sec_err, sec_err_debug); + // } + // assert(trans_l_debug == trans_l && sec_err_debug == sec_err); + // if(li->tn == 308 || li->tn == 311 || lj->tn == 305 || lj->tn == 304) { + // fprintf(stderr, "[M::%s::utg%.6dl] utg%.6dl, liq::[%u, %u), ljq::[%u, %u), trans_l::%ld, sec_err::%ld, sc::%ld\n", __func__, + // (int32_t)li->tn+1, (int32_t)lj->tn+1, li->qs, li->qe, lj->qs, lj->qe, trans_l, sec_err, sc); + // } + return sc; + } + return INT32_MIN; +} + +int64_t gl_chain_lin(kv_ul_ov_t *res, overlap_region *ol, ul_ov_t *ex, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, int64_t trans_sc, +uint64_t mode, All_reads *ridx, ma_ug_t *ug, int64_t need_srt, int64_t debug_i) +{ + if(res->n == 0) return 0; + uint32_t rev_n; int32_t *f, *c_n, *c_sc; int64_t *p, *t, res_n = res->n, st, max_ii, max; rtrace_iter tc; + int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, n_skip, end_j, plus; ul_ov_t *li, *lj, rev_t; + resize_Chain_Data(dp, res_n, NULL); memset(&tc, 0, sizeof(tc)); + t = dp->tmp; f = dp->score; p = dp->pre; c_n = dp->occ; c_sc = dp->self_length; + if(need_srt) { + radix_sort_ul_ov_srt_qe(res->a, res->a + res_n); + for (i = 1, j = 0; i <= res_n; i++) { + if (i == res_n || res->a[i].qe != res->a[j].qe) { + if(i - j > 1) { + radix_sort_ul_ov_srt_qs(res->a+j, res->a+i); + } + j = i; + } + } + } + + memset(t, 0, (res_n*sizeof((*t)))); + for (i = st = plus = 0, max_ii = -1; i < res_n; ++i) { + li = &(res->a[i]); + mm_ovlp = mode?max_ovlp_src(uopt, ((li->tn<<1)|li->rev)^1):max_ovlp(uref->ug->g, ((li->tn<<1)|li->rev)^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(i, res->a, x+G_CHAIN_INDEL); + csc = aln_sc(ol[(*li).qn], trans_sc, UG_TRANS_ERR_W); + // fprintf(stderr, "[M::%s::utg%.6dl] i::%ld, csc::%ld, q::[%u, %u), aln::%u, ol::%u, sec_e::%u\n", + // __func__, (int32_t)li->tn+1, i, csc, li->qs, li->qe, + // (ol[(*li).qn]).align_length, (ol[(*li).qn]).overlapLen, + // (ol[(*li).qn]).non_homopolymer_errors); + mm_sc = csc; mm_idx = -1; + n_skip = 0; end_j = -1; tc.k = INT32_MAX; + if ((x-st) > max_iter) st = x-max_iter; + for (j = x; j >= st; --j) { // collect potential destination vertices + lj = &(res->a[j]); + if(lj->qe+G_CHAIN_INDEL <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore + sc = cal_gl_chain_lin_sc(res->a, i, j, &tc, ol, ridx, ug, uref, uopt, bw, diff_ec_ul, mode, trans_sc, UG_TRANS_ERR_W, f, debug_i); + // char *as = NULL; + // asprintf(&as, "-3-[M::%s::] i::%ld(utg%.6dl), j::%ld(utg%.6dl), sc::%ld\n", + // __func__, i, (int32_t)li->tn+1, j, (int32_t)lj->tn+1, sc); + // push_vlog(&(overall_zdbg->a[debug_i]), as); free(as); as = NULL; + + if(sc == INT32_MIN) continue; + if(sc > mm_sc) { + mm_sc = sc, mm_idx = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + + end_j = j; + if (max_ii < 0 || (res->a[i].qe>(res->a[max_ii].qe+max_dis))) {//too long + max = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && (res->a[i].qe<=(max_dis+res->a[j].qe)); --j) { + if (max < f[j]) { + max = f[j], max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + lj = &(res->a[max_ii]); + if(lj->qe+G_CHAIN_INDEL > li->qs && lj->qs < li->qs) { + sc = cal_gl_chain_lin_sc(res->a, i, max_ii, &tc, ol, ridx, ug, uref, uopt, bw, diff_ec_ul, mode, trans_sc, UG_TRANS_ERR_W, f, debug_i); + if(sc != INT32_MIN) { + if(sc > mm_sc) { + mm_sc = sc; mm_idx = max_ii; + } + } + } + } + if(mm_sc < 0) { + mm_sc = csc; mm_idx = -1; + } + f[i] = mm_sc; p[i] = mm_idx; + if ((max_ii < 0) || ((res->a[i].qe<=max_dis+res->a[max_ii].qe) && (f[max_ii]tn+1, i, res_n, csc, f[i], p[i], li->qs, li->qe); + // char *as = NULL; + // asprintf(&as, "-5-[M::%s::utg%.6dl] i::%ld, csc::%ld, f[i]::%d, p[i]::%ld, q::[%u, %u)\n", __func__, (int32_t)li->tn+1, i, csc, f[i], p[i], li->qs, li->qe); + // push_vlog(&(overall_zdbg->a[debug_i]), as); free(as); as = NULL; + } + for (i = 0; i < res_n; ++i) {///make all f[] positive + f[i] -= plus; t[i] = ((uint64_t)f[i])<<32; t[i] += (i<<1); + } + + int64_t n_v, n_u, n_v0; + radix_sort_gfa64i(t, t + res_n); plus = 0; + for (k = res_n-1, n_v = n_u = 0; k >= 0; --k) { + n_v0 = n_v; + for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { + ex[n_v++] = res->a[i]; t[i] |= 1; i = p[i]; + } + if(n_v0 == n_v) continue; + sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); + // fprintf(stderr, "[M::%s::] n_v::%ld, n_v0::%ld, t[k]::%ld, sc::%ld\n", + // __func__, n_v, n_v0, t[k]>>32, sc); + c_n[n_u] = n_v-n_v0; c_sc[n_u] = sc; n_u++; if(sc < plus) plus = sc; + } + // fprintf(stderr, "---[M::%s] n_u:%ld, n_v:%ld\n", __func__, n_u, n_v); + for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { + n_v0 = n_v; n_v += c_n[k]; + res->a[k].qn = c_sc[k]-plus;//score + res->a[k].ts = n_v0; res->a[k].te = n_v;///idx + // fprintf(stderr, "[M::%s] k:%ld, c_sc:%d\n", __func__, k, c_sc[k]); + + rev_n = c_n[k]>>1; + ///we need to consider contained reads; so determining qs is not such easy + res->a[k].qs = (uint32_t)-1; res->a[k].qe = ex[n_v0].qe; + for (i = 0; i < rev_n; i++) { + rev_t = ex[n_v0+i]; ex[n_v0+i] = ex[n_v-i-1]; ex[n_v-i-1] = rev_t; + + if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; + if(res->a[k].qs > ex[n_v-i-1].qs) res->a[k].qs = ex[n_v-i-1].qs; + ex[n_v0+i].sec = ex[n_v-i-1].sec = SEC_MODE; + } + if(c_n[k]&1) { + if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; + ex[n_v0+i].sec = SEC_MODE; + } + } + res->n = n_u; + radix_sort_ul_ov_srt_qn(res->a, res->a + res->n);//sort by score + return n_v; +} + +void set_ul_ov_t_by_mg_lchain_t(ul_ov_t *u, mg_lchain_t *l) +{ + u->tn = l->v>>1; u->rev = (l->v&1); + u->ts = l->rs; u->te = l->re; + u->qs = l->qs; u->qe = l->qe; +} + +int64_t find_mg_lchain_max(int64_t n, const mg_lchain_t *a, int32_t x) +{ + int64_t s = 0, e = n; + if (n == 0) return -1; + if (a[n-1].qe < x) return n - 1; + if (a[0].qe >= x) return -1; + while (e > s) { // TODO: finish this block + int64_t m = s + (e - s) / 2; + if (a[m].qe >= x) e = m; + else s = m + 1; + } + assert(s == e); + return s; +} + + +int64_t hc_target_len(asg_t *g, mg_lchain_t *s, mg_lchain_t *e) +{ + // int64_t ql = s->qe - e->qe, tp, tm; + // if((s->v^1)&1) tp = g->seq[s->v>>1].len - s->re; + // else tp = s->rs; + + // if((e->v^1)&1) tm = g->seq[e->v>>1].len - e->re; + // else tm = e->rs; + int64_t ql = (int64_t)s->qs - (int64_t)e->qe, tp, tm; + int64_t sts, ete; + sts = (s->v&1)?g->seq[s->v>>1].len-s->re:s->rs; tp = g->seq[s->v>>1].len - sts; + ete = (e->v&1)?g->seq[e->v>>1].len-e->rs:e->re; tm = g->seq[e->v>>1].len - ete; + // fprintf(stderr, "[M::%s::] ql:%ld, tp:%ld, tm:%ld, sts:%ld, ete:%ld\n", __func__, ql, tp, tm, sts, ete); + return ql + tp - tm; +} + +inline int32_t cal_gchain_sc(const mg_path_dst_t *dj, const mg_lchain_t *li, const mg_lchain_t *lc, int64_t *f, int64_t b_w, float diff_thre, float chn_pen_gap) +{ + // const mg_lchain_t *lj; + int32_t gap, sc; + float lin_pen, log_pen; + if (dj->n_path == 0) return INT32_MIN; + gap = dj->dist - dj->target_dist; + // lj = &lc[dj->meta]; + if (gap < 0) gap = -gap; + if ((gap > ((dj->target_dist)*diff_thre)) && (gap > b_w)) return INT32_MIN; + // if (lj->qe <= li->qs) sc = li->score; + // else sc = (int32_t)((double)(li->qe - lj->qe) / (li->qe - li->qs) * li->score + .499); // dealing with overlap on query + sc = li->score; + //sc += dj->mlen; // TODO: is this line the right thing to do? + // if (dj->is_0) sc += ref_bonus; + lin_pen = chn_pen_gap * (float)gap; + log_pen = gap >= 2? mg_log2(gap) : 0.0f; + sc -= (int32_t)(lin_pen + log_pen); + sc += f[dj->meta]; + return sc; +} + +uint64_t primary_chain_check(uint64_t *idx, int64_t idx_n, mg_lchain_t *a) +{ + if(idx_n <= 0) return 0; + ul_ov_t m; memset(&m, 0, sizeof(m)); int64_t m_sc = -1, i, a_n; uint64_t s_idx, e_idx, ovlp, novlp; + for (i = a_n = 0; i < idx_n; ++i) { + if(((int64_t)(idx[i]>>32)) > m_sc) { + m_sc = ((int64_t)(idx[i]>>32)); m.qn = i; + m.ts = a_n; m.te = a_n + ((uint32_t)idx[i]); + m.qs = a[m.ts].qs; m.qe = a[m.te-1].qe; + } + a_n += ((uint32_t)idx[i]); + } + assert(a[m.ts].qs<=a[m.te-1].qs && a[m.te-1].qe>=a[m.ts].qe); + + for (i = a_n = 0; i < idx_n; ++i) { + s_idx = a[a_n].qs; a_n += ((uint32_t)idx[i]); e_idx = a[a_n-1].qe; + if(i == m.qn) continue; + ovlp = ((MIN(m.qe, e_idx) > MAX(m.qs, s_idx))? (MIN(m.qe, e_idx) - MAX(m.qs, s_idx)):0); + novlp = (e_idx - s_idx) - ovlp; + if(novlp > ((m.qe-m.qs)*GC_OFFSET_RATE) && novlp > GC_OFFSET_POS) break; + } + if(i >= idx_n) return 1; + return 0; +} + +int64_t gl_chain_linear(const ul_idx_t *uref, const ma_ug_t *ug, vec_mg_lchain_t *lc, +vec_mg_lchain_t *sw, int64_t qlen, const ug_opt_t *uopt, int64_t bw, double ng_diff_thre, +st_mt_t *bf, int64_t max_skip, int64_t max_iter, int64_t max_dis, int32_t *p, int64_t *f, +int64_t *t, int64_t n_ext, uint64_t id) +{ + int64_t i, j, lc_n = lc->n, mm_ovlp, x, m_idx, m_sc, qo, n_skip, k, k0, n_u, n_v, ni; + int64_t max_f, st, max_ii, sc, csc, mm_sc, mm_idx, end_j, max, n_v0; + mg_lchain_t *li, *lj; asg_t *g = ug->g; uint64_t *u, ff; ul_ov_t ui, uj; + + memset(t, 0, (n_ext*sizeof((*t)))); + for (i = st = 0, max_ii = -1; i < n_ext; ++i) { // core loop + li = &lc->a[i]; set_ul_ov_t_by_mg_lchain_t(&ui, li); + mm_ovlp = max_ovlp(g, li->v^1); + x = (li->qs + mm_ovlp)*ng_diff_thre; if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_mg_lchain_max(i, lc->a, x+G_CHAIN_INDEL); + csc = li->score; + mm_sc = csc; mm_idx = -1; + n_skip = 0; end_j = -1; + if ((x-st) > max_iter) st = x-max_iter; + // if(id == 123/** || id == 192**/) { + // fprintf(stderr, "[M::id->%lu::i->%ld::utg%.6d%c] q::[%u, %u); t::[%u, %u); st->%ld; x->%ld\n", id, i, (li->v>>1)+1, "lc"[ug->u.a[li->v>>1].circ], li->qs, li->qe, li->rs, li->re, st, x); + // } + for (j = x; j >= st; --j) { // collect potential destination vertices + lj = &lc->a[j]; + if(lj->qe+G_CHAIN_INDEL <= li->qs) break; + if(lj->qs >= li->qs) continue; + set_ul_ov_t_by_mg_lchain_t(&uj, lj); + qo = infer_rovlp(&ui, &uj, NULL, NULL, NULL, (ma_ug_t *)ug); ///overlap length in query (UL read) + // if(id == 123/** || id == 192**/) { + // fprintf(stderr, "[M::id->%lu::j->%ld] qo->%ld\n", id, j, qo); + // } + if(/**li->v!=lj->v &&**/get_ecov_adv(uref, uopt, li->v^1, lj->v^1, bw, ng_diff_thre, qo, 0, NULL)) { + sc = csc + f[j]; + if(sc > mm_sc) { + mm_sc = sc, mm_idx = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + } + + end_j = j; + if (max_ii < 0 || (lc->a[i].qe>(lc->a[max_ii].qe+max_dis))) {//too long + max = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && (lc->a[i].qe<=(max_dis+lc->a[j].qe)); --j) { + if (max < f[j]) { + max = f[j], max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + lj = &(lc->a[max_ii]); + if(lj->qe+G_CHAIN_INDEL > li->qs && lj->qs < li->qs) { + set_ul_ov_t_by_mg_lchain_t(&uj, lj); + qo = infer_rovlp(&ui, &uj, NULL, NULL, NULL, (ma_ug_t *)ug);///overlap length in query (UL read) + if(/**li->v!=lj->v &&**/get_ecov_adv(uref, uopt, li->v^1, lj->v^1, bw, ng_diff_thre, qo, 0, NULL)) { + sc = csc + f[max_ii]; + if(sc > mm_sc) { + mm_sc = sc; mm_idx = max_ii; + } + } + } + } + + f[i] = mm_sc; p[i] = mm_idx; + if ((max_ii < 0) || ((lc->a[i].qe<=max_dis+lc->a[max_ii].qe) && (f[max_ii]dist_pre = mm_idx<0?-1:g_adjacent_dis(g, li->v^1, lc->a[mm_idx].v^1); li->inner_pre = 0; + li->hash_pre = mm_idx<0?0:(__ac_Wang_hash((li->v^1))+__ac_Wang_hash((lc->a[mm_idx].v^1))); + } + + for (; i < lc_n; i++) { + li = &lc->a[i]; + max_f = li->score; f[i] = max_f; p[i] = -1; + ///same time for gchain + li->dist_pre = -1; + li->hash_pre = 0; + li->inner_pre = 0; + } + + for (i = 0; i < lc_n; ++i) {///all sc are positive + t[i] = f[i]<<32; t[i] += (i<<1); + } + + sw->n = 0; kv_resize(mg_lchain_t, *sw, (uint64_t)lc_n); + kv_resize(uint64_t, *bf, (uint64_t)lc_n); u = bf->a; + n_u = n_v = 0; radix_sort_gfa64i(t, t + lc_n); + for (k = lc_n-1, n_v = n_u = 0; k >= 0; --k) { + n_v0 = n_v; + for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { + sw->a[n_v++] = lc->a[i]; t[i] |= 1; i = p[i]; + } + if(n_v0 == n_v) continue; + sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); + if(sc >= 0) { + ff = ((uint64_t)(0x8000000000000000)); + } else { + ff = 0; sc = -sc; + } + u[n_u++] = (((uint64_t)sc)<<32)|((uint64_t)(n_v-n_v0))|ff; + } + + m_idx = m_sc = -1; + for (i = 0, k = 0; i < n_u; ++i) { + if((u[i]&((uint64_t)(0x8000000000000000)))) { + u[i] -= ((uint64_t)(0x8000000000000000)); sc = u[i]>>32; + } else { + sc = u[i]>>32; sc = -sc; + } + u[i] <<= 32; u[i] >>= 32; u[i] |= (((uint64_t)sc)<<32); + + k0 = k, ni = (uint32_t)u[i]; + for (j = 0; j < ni; ++j) { + lc->a[k++] = sw->a[k0 + (ni - j - 1)]; + } + if(m_idx < 0 || m_sc < ((int64_t)(u[i]>>32))) { + m_idx = i; m_sc = ((int64_t)(u[i]>>32)); + } + } + assert(k == n_v); bf->n = n_u; + return m_idx; +} + +int64_t gl_chain_graph(void *km, const ul_idx_t *uref, const ma_ug_t *ug, vec_mg_lchain_t *lc, +vec_mg_lchain_t *sw, vec_mg_path_dst_t *dst, vec_sp_node_t *out, vec_mg_pathv_t *path, +int64_t qlen, const ug_opt_t *uopt, int64_t bw, double diff_thre, double ng_diff_thre, uint64_t *srt, +st_mt_t *bf, Chain_Data* dp, int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t need_srt) +{ + bf->n = 0; + if(lc->n == 0) return 0; + int64_t i, j, lc_n = lc->n, n_ext, mm_ovlp, target_dist, max_target_dist, x, m_idx, m_sc, qo, sc; + int64_t max_f, max_j = -1, max_d = -1, max_inner = 0; uint32_t max_hash = 0; int64_t k, k0, n_u, n_v, ni; + mg_lchain_t *r, *li, *lj; mg_path_dst_t *q; asg_t *g = ug->g; uint64_t isolated, *u, ff; ul_ov_t ui, uj; + if(!need_srt) { + for (i = n_ext = 0; i < lc_n; i++) { + r = &lc->a[i]; r->dist_pre = -1; isolated = 0;///dist_pre -> parent in graph chain + if((r->re < g->seq[r->v>>1].len) && (r->rs > 0)) isolated = 1;///UL contained in one vertice + if (!isolated) { + srt[n_ext] = r->qe; srt[n_ext] <<= 32; + srt[n_ext] |= (uint64_t)i; srt[n_ext] |= (isolated<<63); + ++n_ext; + } + } + j = n_ext; + if(j < lc_n) { + for (i = 0; i < lc_n; i++) { + r = &lc->a[i]; r->dist_pre = -1; isolated = 0;///dist_pre -> parent in graph chain + if((r->re < g->seq[r->v>>1].len) && (r->rs > 0)) isolated = 1;///UL contained in one vertice + if (isolated) { + srt[j] = r->qe; srt[j] <<= 32; srt[j] |= (uint64_t)i; srt[j] |= (isolated<<63); ++j; + } + } + } + assert(j == lc_n); + } else { + for (i = n_ext = 0; i < lc_n; i++) { + r = &lc->a[i]; r->dist_pre = -1; isolated = 0;///dist_pre -> parent in graph chain + if((r->re < g->seq[r->v>>1].len) && (r->rs > 0)) isolated = 1;///UL contained in one vertice + if (!isolated) ++n_ext; + srt[i] = r->qe; srt[i] <<= 32; srt[i] |= (uint64_t)i; srt[i] |= (isolated<<63); + } + radix_sort_gfa64(srt, srt+lc_n); + for (i = 1, j = 0; i <= lc_n; i++) { + if (i == lc_n || (srt[i]>>32) != (srt[j]>>32)) { + if(i - j > 1) { + for (x = j; x < i; x++) { + srt[x] <<= 32; srt[x] >>= 32; srt[x] |= ((uint64_t)lc->a[(uint32_t)srt[x]].qs)<<32; + } + radix_sort_gfa64(srt+j, srt+i); + } + j = i; + } + } + } + if((n_ext != lc_n) || (need_srt)) { + kv_resize(mg_lchain_t, *sw, (uint64_t)lc_n); sw->n = lc_n; + for (i = 0; i < lc_n; i++) sw->a[i] = lc->a[(uint32_t)srt[i]]; + memcpy(lc->a, sw->a, lc_n *sizeof((*(lc->a)))); + } + + resize_Chain_Data(dp, lc_n, NULL); + int32_t *p; int64_t *f, *t, n_skip, dst_n, is_f, plus, n_v0; mg_path_dst_t *dj; + t = dp->tmp; p = dp->score; f = dp->pre; + if(ng_diff_thre >= 0) { + m_idx = gl_chain_linear(uref, ug, lc, sw, qlen, uopt, bw, ng_diff_thre, bf, + max_skip, max_iter, max_dis, p, f, t, n_ext, -1); + if(diff_thre < 0) return m_idx; + if(m_idx >= 0 && primary_chain_check(bf->a, bf->n, lc->a)) return m_idx; + else m_idx = -1; + // if(m_idx >= 0) return m_idx; + bf->n = 0; + } + + memset(t, 0, (n_ext*sizeof((*t)))); + for (i = plus = 0; i < n_ext; ++i) { // core loop + li = &lc->a[i]; set_ul_ov_t_by_mg_lchain_t(&ui, li); + mm_ovlp = max_ovlp(g, li->v^1); + x = (li->qs + mm_ovlp)*diff_thre; if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_mg_lchain_max(i, lc->a, x+G_CHAIN_INDEL); + + n_skip = 0; is_f = 0; + // collect potential destination vertices + for (dst->n = 0, max_target_dist = -1, j = x; j >= 0; --j) { + lj = &lc->a[j]; ///extend_end_coord(lj, qlen, g->seq[lj->v>>1].len, &jqs, &jqe, &jrs, &jre); + //lj contained in li; actually in circle, this might happen; need to deal with it later + if(lj->qs >= li->qs/**+G_CHAIN_INDEL**/) continue; + ///if there is a circle, the two linear chains might be at the same vertice + target_dist = hc_target_len(g, li, lj); + if(target_dist < 0) continue; + kv_pushp(mg_path_dst_t, *dst, &q); + memset(q, 0, sizeof(*q)); + q->inner = 0;//we set q->inner = 0 to allow circles + q->v = lj->v^1;///must be v^1 instead of v + q->meta = j; + ///lj->qs************lj->qe + /// li->qs************li->qe + q->qlen = li->qs - lj->qe;///might be negative; this is the region that need to be checked in base-level + q->target_dist = target_dist;///cannot understand the target_dist + q->target_hash = 0; + q->check_hash = 0; + if(max_target_dist < target_dist) max_target_dist = target_dist; + if (t[j] == i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + if((!is_f) && (lj->qe+G_CHAIN_INDEL > li->qs)) { + set_ul_ov_t_by_mg_lchain_t(&uj, lj); + qo = infer_rovlp(&ui, &uj, NULL, NULL, NULL, (ma_ug_t *)ug); + if(/**li->v!=lj->v &&**/ get_ecov_adv(uref, uopt, li->v^1, lj->v^1, bw, N_GCHAIN_RATE, qo, 0, NULL)) { + is_f = 1; if(n_skip > 0) n_skip--; + if(n_skip < (max_skip>>1)) n_skip= (max_skip>>1); + } + } + } + + // confirm reach-ability + max_f = li->score, max_j = -1, max_d = -1, max_inner = 0; max_hash = 0; + if(dst->n) { + max_target_dist *= (1+diff_thre); if(max_target_dist < bw) max_target_dist = bw; + hc_shortest_k(km, g, li->v^1, dst->n, dst->a, max_target_dist, MG_MAX_SHORT_K, bf, srt, out, NULL, 1, 0, 0); + // remove unreachable destinations + //TODO: check sequence identity + dst_n = dst->n; + for (j = 0; j < dst_n; ++j) { + dj = &dst->a[j]; + if (dj->n_path == 0) continue; // unreachable + sc = cal_gchain_sc(dj, li, lc->a, f, bw, diff_thre, W_CHN_PEN_GAP); + + if (sc == INT32_MIN) continue; // out of band + // if (sc < 0) continue;// negative score + if (sc > max_f) { + max_f = sc, max_j = dj->meta, max_d = dj->dist, max_hash = dj->hash, max_inner = dj->inner; + } + } + } + if(max_f < 0) { + max_f = li->score; max_j = -1; + } + + f[i] = max_f; p[i] = max_j; + ///same time for gchain + li->dist_pre = max_d; + li->hash_pre = max_hash; + li->inner_pre = max_inner; + if(max_f < plus) plus = max_f;//minmun negative + } + + for (; i < lc_n; i++) { + li = &lc->a[i]; + max_f = li->score, max_j = -1, max_d = -1, max_inner = 0; max_hash = 0; + f[i] = max_f; p[i] = max_j; + ///same time for gchain + li->dist_pre = max_d; + li->hash_pre = max_hash; + li->inner_pre = max_inner; + if(max_f < plus) plus = max_f;//minmun negative + } + + for (i = 0; i < lc_n; ++i) { + f[i]-=plus; t[i] = f[i]<<32; t[i] += (i<<1); + } + + sw->n = 0; kv_resize(mg_lchain_t, *sw, (uint64_t)lc_n); + kv_resize(uint64_t, *bf, (uint64_t)lc_n); u = bf->a; + n_u = n_v = 0; radix_sort_gfa64i(t, t + lc_n); plus = 0; + for (k = lc_n-1, n_v = n_u = 0; k >= 0; --k) { + n_v0 = n_v; + for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { + sw->a[n_v++] = lc->a[i]; t[i] |= 1; i = p[i]; + } + if(n_v0 == n_v) continue; + sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); + if(sc < plus) plus = sc; + if(sc >= 0) { + ff = ((uint64_t)(0x8000000000000000)); + } else { + ff = 0; sc = -sc; + } + u[n_u++] = (((uint64_t)sc)<<32)|((uint64_t)(n_v-n_v0))|ff; + } + + m_idx = m_sc = -1; + for (i = 0, k = 0; i < n_u; ++i) { + if((u[i]&((uint64_t)(0x8000000000000000)))) { + u[i] -= ((uint64_t)(0x8000000000000000)); sc = u[i]>>32; + } else { + sc = u[i]>>32; sc = -sc; + } + sc -= plus; u[i] <<= 32; u[i] >>= 32; u[i] |= (((uint64_t)sc)<<32); + + k0 = k, ni = (uint32_t)u[i]; + for (j = 0; j < ni; ++j) { + lc->a[k++] = sw->a[k0 + (ni - j - 1)]; + } + if(m_idx < 0 || m_sc < ((int64_t)(u[i]>>32))) { + m_idx = i; m_sc = ((int64_t)(u[i]>>32)); + } + } + assert(k == n_v); bf->n = n_u; + return m_idx; +} + + + +int64_t ctg_chain_graph(void *km, const ul_idx_t *uref, const ma_ug_t *ug, vec_mg_lchain_t *lc, +vec_mg_lchain_t *sw, vec_mg_path_dst_t *dst, vec_sp_node_t *out, vec_mg_pathv_t *path, +int64_t qlen, const ug_opt_t *uopt, int64_t bw, double ng_diff_thre, uint64_t *srt, +st_mt_t *bf, Chain_Data* dp, int64_t max_skip, int64_t max_iter, int64_t max_dis, uint64_t id) +{ + bf->n = 0; + if(lc->n == 0) return 0; + int64_t i, j, lc_n = lc->n, x, m_idx; mg_lchain_t *r; + + + for (i = 0; i < lc_n; i++) { + r = &lc->a[i]; r->dist_pre = -1; + srt[i] = r->qe; srt[i] <<= 32; srt[i] |= (uint64_t)i; + } + radix_sort_gfa64(srt, srt+lc_n); + for (i = 1, j = 0; i <= lc_n; i++) { + if (i == lc_n || (srt[i]>>32) != (srt[j]>>32)) { + if(i - j > 1) { + for (x = j; x < i; x++) { + srt[x] <<= 32; srt[x] >>= 32; srt[x] |= ((uint64_t)lc->a[(uint32_t)srt[x]].qs)<<32; + } + radix_sort_gfa64(srt+j, srt+i); + } + j = i; + } + } + + + kv_resize(mg_lchain_t, *sw, (uint64_t)lc_n); sw->n = lc_n; + for (i = 0; i < lc_n; i++) sw->a[i] = lc->a[(uint32_t)srt[i]]; + memcpy(lc->a, sw->a, lc_n *sizeof((*(lc->a)))); + + + resize_Chain_Data(dp, lc_n, NULL); + int32_t *p; int64_t *f, *t; + t = dp->tmp; p = dp->score; f = dp->pre; + + m_idx = gl_chain_linear(uref, ug, lc, sw, qlen, uopt, bw, ng_diff_thre, bf, + max_skip, max_iter, max_dis, p, f, t, lc->n, id); + + // if(m_idx >= 0 && primary_chain_check(bf->a, bf->n, lc->a)) return m_idx; + // else m_idx = -1; + // bf->n = 0; + return m_idx; +} + + +inline int32_t cal_gchain_sc_adv(const ma_ug_t *ug, const ul_idx_t *uref, const ug_opt_t *uopt, +overlap_region *ol, const mg_path_dst_t *dj, const mg_lchain_t *li, ul_ov_t *ui, mg_lchain_t *lc, int64_t *f, +int64_t b_w, float diff_thre, float chn_pen_gap, rtrace_iter *tc, int64_t trans_sc, int64_t sec_sec) +{ + // const mg_lchain_t *lj; + int32_t gap; + float lin_pen, log_pen; + if (dj->n_path == 0) return INT32_MIN; + gap = dj->dist - dj->target_dist; + // lj = &lc[dj->meta]; + if (gap < 0) gap = -gap; + if ((gap > ((dj->target_dist)*diff_thre)) && (gap > b_w)) return INT32_MIN; + // if (lj->qe <= li->qs) sc = li->score; + // else sc = (int32_t)((double)(li->qe - lj->qe) / (li->qe - li->qs) * li->score + .499); // dealing with overlap on query + int64_t trans_l = 0, sec_err = 0, qo, el = 0, sc, sc0; + mg_lchain_t *lj = &(lc[dj->meta]); ul_ov_t uj; + + trans_l = get_overlap_region_sub_err(&(ol[li->off]), tc, lj->qe, &sec_err); + sc = (li->qe - lj->qe) - (trans_l*trans_sc) - (sec_err*sec_sec); sc += f[dj->meta]; + if(((trans_l > 0) || (sec_err > 0)) && (lj->qe > li->qs)) { + set_ul_ov_t_by_mg_lchain_t(&uj, lj); + qo = infer_rovlp(ui, &uj, NULL, NULL, NULL, (ma_ug_t *)ug); + if((!get_ecov_el(uref, uopt, li->v^1, lj->v^1, b_w, N_GCHAIN_RATE, qo, 0, &el)) || (el == 0)) { + rtrace_iter tr; tr.k = INT32_MAX; sc0 = sc; + sc = f[dj->meta] + li->score; + trans_l = get_overlap_region_sub_err(&(ol[lj->off]), &tr, li->qs, &sec_err); + sc -= (((int64_t)(lj->qe - li->qs)) - (trans_l*trans_sc) - (sec_err*sec_sec)); + if(sc < sc0) sc = sc0; + } + } + + + // int64_t trans_l_debug, sec_err_debug; + // trans_l_debug = get_overlap_region_sub_err_debug(&(ol[li->off]), lc[dj->meta].qe, &sec_err_debug); + // if(!(trans_l_debug == trans_l && sec_err_debug == sec_err)) { + // fprintf(stderr, "[M::%s::] trans_l::%ld, trans_l_debug::%ld, sec_err::%ld, sec_err_debug::%ld\n", + // __func__, trans_l, trans_l_debug, sec_err, sec_err_debug); + // } + // assert(trans_l_debug == trans_l && sec_err_debug == sec_err); + + + // sc = li->score; + //sc += dj->mlen; // TODO: is this line the right thing to do? + // if (dj->is_0) sc += ref_bonus; + lin_pen = chn_pen_gap * (float)gap; + log_pen = gap >= 2? mg_log2(gap) : 0.0f; + sc -= (int32_t)(lin_pen + log_pen); + return sc; +} + +int64_t gl_chain_graph_adv(void *km, overlap_region *ol, const ul_idx_t *uref, const ma_ug_t *ug, vec_mg_lchain_t *lc, +vec_mg_lchain_t *sw, vec_mg_path_dst_t *dst, vec_sp_node_t *out, vec_mg_pathv_t *path, +int64_t qlen, const ug_opt_t *uopt, int64_t bw, double diff_thre, uint64_t *srt, +st_mt_t *bf, Chain_Data* dp, int64_t max_skip, int64_t max_iter, int64_t max_dis, int64_t trans_sc, int64_t sec_sec, +int64_t need_srt) +{ + bf->n = 0; + if(lc->n == 0) return 0; + int64_t i, j, lc_n = lc->n, n_ext, mm_ovlp, target_dist, max_target_dist, x, m_idx, m_sc, qo, sc; rtrace_iter tc; + int64_t max_f, max_j = -1, max_d = -1, max_inner = 0; uint32_t max_hash = 0; int64_t k, k0, n_u, n_v, ni; + mg_lchain_t *r, *li, *lj; mg_path_dst_t *q; asg_t *g = ug->g; uint64_t isolated, *u, ff; ul_ov_t ui, uj; + if(!need_srt) { + for (i = n_ext = 0; i < lc_n; i++) { + r = &lc->a[i]; r->dist_pre = -1; isolated = 0;///dist_pre -> parent in graph chain + if((r->re < g->seq[r->v>>1].len) && (r->rs > 0)) isolated = 1;///UL contained in one vertice + if (!isolated) { + srt[n_ext] = r->qe; srt[n_ext] <<= 32; + srt[n_ext] |= (uint64_t)i; srt[n_ext] |= (isolated<<63); + ++n_ext; + } + } + j = n_ext; + if(j < lc_n) { + for (i = 0; i < lc_n; i++) { + r = &lc->a[i]; r->dist_pre = -1; isolated = 0;///dist_pre -> parent in graph chain + if((r->re < g->seq[r->v>>1].len) && (r->rs > 0)) isolated = 1;///UL contained in one vertice + if (isolated) { + srt[j] = r->qe; srt[j] <<= 32; srt[j] |= (uint64_t)i; srt[j] |= (isolated<<63); ++j; + } + } + } + assert(j == lc_n); + } else { + for (i = n_ext = 0; i < lc_n; i++) { + r = &lc->a[i]; r->dist_pre = -1; isolated = 0;///dist_pre -> parent in graph chain + if((r->re < g->seq[r->v>>1].len) && (r->rs > 0)) isolated = 1;///UL contained in one vertice + if (!isolated) ++n_ext; + srt[i] = r->qe; srt[i] <<= 32; srt[i] |= (uint64_t)i; srt[i] |= (isolated<<63); + } + radix_sort_gfa64(srt, srt+lc_n); + for (i = 1, j = 0; i <= lc_n; i++) { + if (i == lc_n || (srt[i]>>32) != (srt[j]>>32)) { + if(i - j > 1) { + for (x = j; x < i; x++) { + srt[x] <<= 32; srt[x] >>= 32; srt[x] |= ((uint64_t)lc->a[(uint32_t)srt[x]].qs)<<32; + } + radix_sort_gfa64(srt+j, srt+i); + } + j = i; + } + } + } + if((n_ext != lc_n) || (need_srt)) { + kv_resize(mg_lchain_t, *sw, (uint64_t)lc_n); sw->n = lc_n; + for (i = 0; i < lc_n; i++) sw->a[i] = lc->a[(uint32_t)srt[i]]; + memcpy(lc->a, sw->a, lc_n *sizeof((*(lc->a)))); + } + + resize_Chain_Data(dp, lc_n, NULL); memset(&tc, 0, sizeof(tc)); + int32_t *p; int64_t *f, *t, n_skip, dst_n, is_f, plus, n_v0; mg_path_dst_t *dj; + t = dp->tmp; p = dp->score; f = dp->pre; + + memset(t, 0, (n_ext*sizeof((*t)))); + for (i = plus = 0; i < n_ext; ++i) { // core loop + li = &lc->a[i]; set_ul_ov_t_by_mg_lchain_t(&ui, li); + mm_ovlp = max_ovlp(g, li->v^1); + x = (li->qs + mm_ovlp)*diff_thre; if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_mg_lchain_max(i, lc->a, x+G_CHAIN_INDEL); + + n_skip = 0; is_f = 0; + // collect potential destination vertices + for (dst->n = 0, max_target_dist = -1, j = x; j >= 0; --j) { + lj = &lc->a[j]; ///extend_end_coord(lj, qlen, g->seq[lj->v>>1].len, &jqs, &jqe, &jrs, &jre); + //lj contained in li; actually in circle, this might happen; need to deal with it later + if(lj->qs >= li->qs/**+G_CHAIN_INDEL**/) continue; + ///if there is a circle, the two linear chains might be at the same vertice + target_dist = hc_target_len(g, li, lj); + if(target_dist < 0) continue; + kv_pushp(mg_path_dst_t, *dst, &q); + memset(q, 0, sizeof(*q)); + q->inner = 0;//we set q->inner = 0 to allow circles + q->v = lj->v^1;///must be v^1 instead of v + q->meta = j; + ///lj->qs************lj->qe + /// li->qs************li->qe + q->qlen = li->qs - lj->qe;///might be negative; this is the region that need to be checked in base-level + q->target_dist = target_dist;///cannot understand the target_dist + q->target_hash = 0; + q->check_hash = 0; + if(max_target_dist < target_dist) max_target_dist = target_dist; + if (t[j] == i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + if((!is_f) && (lj->qe+G_CHAIN_INDEL > li->qs)) { + set_ul_ov_t_by_mg_lchain_t(&uj, lj); + qo = infer_rovlp(&ui, &uj, NULL, NULL, NULL, (ma_ug_t *)ug); + if(/**li->v!=lj->v &&**/ get_ecov_adv(uref, uopt, li->v^1, lj->v^1, bw, N_GCHAIN_RATE, qo, 0, NULL)) { + is_f = 1; if(n_skip > 0) n_skip--; + if(n_skip < (max_skip>>1)) n_skip= (max_skip>>1); + } + } + } + + // confirm reach-ability + max_f = li->score, max_j = -1, max_d = -1, max_inner = 0; max_hash = 0; + if(dst->n) { + max_target_dist *= (1+diff_thre); if(max_target_dist < bw) max_target_dist = bw; + hc_shortest_k(km, g, li->v^1, dst->n, dst->a, max_target_dist, MG_MAX_SHORT_K, bf, srt, out, NULL, 1, 0, 0); + // remove unreachable destinations + //TODO: check sequence identity + dst_n = dst->n; tc.k = INT32_MAX; + for (j = 0; j < dst_n; ++j) { + dj = &dst->a[j]; + if (dj->n_path == 0) continue; // unreachable + sc = cal_gchain_sc_adv(ug, uref, uopt, ol, dj, li, &ui, lc->a, f, bw, diff_thre, W_CHN_PEN_GAP, &tc, trans_sc, sec_sec); + + if (sc == INT32_MIN) continue; // out of band + // if (sc < 0) continue;// negative score + if (sc > max_f) { + max_f = sc, max_j = dj->meta, max_d = dj->dist, max_hash = dj->hash, max_inner = dj->inner; + } + } + } + if(max_f < 0) { + max_f = li->score; max_j = -1; + } + + f[i] = max_f; p[i] = max_j; + ///same time for gchain + li->dist_pre = max_d; + li->hash_pre = max_hash; + li->inner_pre = max_inner; + if(max_f < plus) plus = max_f;//minmun negative + } + + for (; i < lc_n; i++) { + li = &lc->a[i]; + max_f = li->score, max_j = -1, max_d = -1, max_inner = 0; max_hash = 0; + f[i] = max_f; p[i] = max_j; + ///same time for gchain + li->dist_pre = max_d; + li->hash_pre = max_hash; + li->inner_pre = max_inner; + if(max_f < plus) plus = max_f;//minmun negative + } + + for (i = 0; i < lc_n; ++i) { + f[i]-=plus; t[i] = f[i]<<32; t[i] += (i<<1); + } + + sw->n = 0; kv_resize(mg_lchain_t, *sw, (uint64_t)lc_n); + kv_resize(uint64_t, *bf, (uint64_t)lc_n); u = bf->a; + n_u = n_v = 0; radix_sort_gfa64i(t, t + lc_n); plus = 0; + for (k = lc_n-1, n_v = n_u = 0; k >= 0; --k) { + n_v0 = n_v; + for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { + sw->a[n_v++] = lc->a[i]; t[i] |= 1; i = p[i]; + } + if(n_v0 == n_v) continue; + sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); + if(sc < plus) plus = sc; + if(sc >= 0) { + ff = ((uint64_t)(0x8000000000000000)); + } else { + ff = 0; sc = -sc; + } + u[n_u++] = (((uint64_t)sc)<<32)|((uint64_t)(n_v-n_v0))|ff; + } + + m_idx = m_sc = -1; + for (i = 0, k = 0; i < n_u; ++i) { + if((u[i]&((uint64_t)(0x8000000000000000)))) { + u[i] -= ((uint64_t)(0x8000000000000000)); sc = u[i]>>32; + } else { + sc = u[i]>>32; sc = -sc; + } + sc -= plus; u[i] <<= 32; u[i] >>= 32; u[i] |= (((uint64_t)sc)<<32); + + k0 = k, ni = (uint32_t)u[i]; + for (j = 0; j < ni; ++j) { + lc->a[k++] = sw->a[k0 + (ni - j - 1)]; + } + if(m_idx < 0 || m_sc < ((int64_t)(u[i]>>32))) { + m_idx = i; m_sc = ((int64_t)(u[i]>>32)); + } + } + assert(k == n_v); bf->n = n_u; + return m_idx; +} + + +void prt_chains(ul_ov_t *l_idx, int64_t l_idx_n, ul_ov_t *l_a, uint64_t *g_idx, int64_t g_idx_n, vec_mg_lchain_t *g_a, int64_t ql) +{ + int64_t k, i, s, e; + if(l_idx && l_a) { + fprintf(stderr, "\n[M::%s::qlen->%ld] print linear chains\n", __func__, ql); + for (k = 0; k < l_idx_n; k++) { + s = l_idx[k].ts; e = l_idx[k].te; + fprintf(stderr, "[M::%s::linear_chain] sc::%u, occ::%ld\n", __func__, l_idx[k].qn, e-s); + for (i = s; i < e; i++) { + fprintf(stderr, "[M::%s::utg%.6dl] q::[%u, %u)\n", __func__, (int32_t)l_a[i].tn+1, l_a[i].qs, l_a[i].qe); + } + } + } + + if(g_idx && g_a) { + fprintf(stderr, "\n[M::%s::qlen->%ld] print graph chains\n", __func__, ql); + for (k = s = e = 0; k < g_idx_n; ++k) { + s = e; e += ((uint32_t)g_idx[k]); + fprintf(stderr, "[M::%s::grapn_chain] sc::%lu, occ::%ld\n", __func__, g_idx[k]>>32, e-s); + for (i = s; i < e; i++) { + fprintf(stderr, "[M::%s::utg%.6dl] q::[%u, %u)\n", __func__, (int32_t)(g_a->a[i].v>>1)+1, g_a->a[i].qs, g_a->a[i].qe); + } + } + } +} + +uint32_t gen_gchain_track(void *km, mg_lchain_t *a, int64_t a_n, const asg_t *g, +st_mt_t *dst_done, vec_sp_node_t *out, vec_mg_pathv_t *res); + +uint32_t select_max_gchain(void *km, const ul_idx_t *uref, int64_t ulid, st_mt_t *idx, vec_mg_lchain_t *e, kv_ul_ov_t *raw_idx, +const asg_t *g, st_mt_t *dst_done, vec_sp_node_t *out, vec_mg_pathv_t *res, vec_mg_lchain_t *gchains) +{ + gchains->n = 0; + if(idx->n <= 0) return 0; + int64_t a_n, idx_n = idx->n, i, k, n_mchain = 0, min_sc, max_sc; uint64_t om, ok, ovlp; + ul_ov_t *m = NULL, *p = NULL, kp; mg_lchain_t *a = e->a, *g_item; int64_t raw_idx_n = raw_idx->n; + ul_ov_t *gb = NULL; int64_t gb_n = 0; + for (i = a_n = 0; i < idx_n; ++i) { + kv_pushp(ul_ov_t, *raw_idx, &p); + p->qn = ((int64_t)(idx->a[i]>>32));//score + p->ts = a_n; p->te = a_n + ((uint32_t)idx->a[i]); + p->qs = a[p->ts].qs; p->qe = a[p->te-1].qe; p->tn = 1;//(tn = 1) -> normal; (t = 0) -> duplicated chain + a_n += ((uint32_t)idx->a[i]); + } + gb = raw_idx->a + raw_idx_n; gb_n = raw_idx->n - raw_idx_n; + radix_sort_ul_ov_srt_qn(gb, gb + gb_n);//sort by scores + for (k = 0, n_mchain = gb_n>>1; k < n_mchain; k++) { + kp = gb[k]; gb[k] = gb[gb_n-k-1]; gb[gb_n-k-1] = kp; + } + + for (k = 0; k < gb_n; k++) {//filter too close chains + m = &(gb[k]); om = m->qe - m->qs; ///current chain + // fprintf(stderr, "k::%ld[M::%s::sc->%u] q::[%u, %u), set::%u\n", k, __func__, m->qn, m->qs, m->qe, m->tn); + if(m->tn == 0) continue; + for (i = k-1; i >= 0; i--) { + p = &(gb[i]); + ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); + if(ovlp == 0) continue; + min_sc = MIN(p->qn, m->qn); max_sc = MAX(p->qn, m->qn); + ok = p->qe - p->qs; ok = MAX(ok, om); + if(min_sc < (max_sc*0.98)) break; + if((ovlp > GC_OFFSET_POS) && (min_sc > (max_sc*0.98)) && (ovlp > (ok*0.8))) { + // fprintf(stderr, "k::%ld[M::%s::i->%ld] min_sc::%ld, max_sc::%ld\n", + // k, __func__, i, min_sc, max_sc); + m->tn = p->tn = 0; + } + } + + for (i = k+1; i < gb_n; i++) { + p = &(gb[i]); + ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); + if(ovlp == 0) continue; + min_sc = MIN(p->qn, m->qn); max_sc = MAX(p->qn, m->qn); + ok = p->qe - p->qs; ok = MAX(ok, om); + if(min_sc < (max_sc*0.98)) break; + if((ovlp > GC_OFFSET_POS) && (min_sc > (max_sc*0.98)) && (ovlp > (ok*0.8))) { + // fprintf(stderr, "k::%ld[M::%s::i->%ld] min_sc::%ld, max_sc::%ld\n", + // k, __func__, i, min_sc, max_sc); + m->tn = p->tn = 0; + } + } + } + + for (k = i = 0; k < gb_n; k++) { + m = &(gb[k]); if(m->tn == 0) continue; + gb[i++] = gb[k]; + } + // fprintf(stderr, "[M::%s::] gb_n0::%ld, gb_n::%ld\n", __func__, gb_n, i); + gb_n = i; + + for (k = n_mchain = 0; k < gb_n; k++) { + m = &(gb[k]); om = m->qe - m->qs; + for (i = 0; i < n_mchain; i++) { + p = &(gb[i]); + ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); + if(ovlp == 0) continue; + ok = p->qe - p->qs; + if((ovlp > ok*0.1) || (ovlp > om*0.1)) break; + } + if(i < n_mchain) continue; + gb[n_mchain++] = gb[k]; + } + gb_n = n_mchain; + + if(gb_n) { + gchains->n = 0; + for (k = 0; k < gb_n; k++) { + kv_pushp(mg_lchain_t, *gchains, &g_item); + g_item->v = (uint32_t)-1; + g_item->qs = gb[k].qs; g_item->qe = gb[k].qe; + g_item->rs = gb[k].ts; g_item->re = gb[k].te; + g_item->cnt = g_item->off = 0; + gen_gchain_track(km, a + g_item->rs, g_item->re - g_item->rs, g, dst_done, out, res); + kv_resize(mg_lchain_t, *gchains, gchains->n + res->n); ///a = gchains->a + gchains->n; + for (i = 0, g_item = &(gchains->a[gchains->n-1]); i < ((int64_t)res->n); i++) { + if(res->a[i].v == (uint32_t)-1) { + gchains->a[i+gchains->n] = a[res->a[i].pre + g_item->rs]; + gchains->a[i+gchains->n].dist_pre = res->a[i].d; + // if(ulid == 14714) { + // fprintf(stderr, "+[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\n", __func__, + // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1], + // gchains->a[i+gchains->n].qs, gchains->a[i+gchains->n].qe, + // gchains->a[i+gchains->n].rs, gchains->a[i+gchains->n].re); + // } + } else { + gchains->a[i+gchains->n].v = res->a[i].v; + gchains->a[i+gchains->n].off = -1; + gchains->a[i+gchains->n].dist_pre = res->a[i].d; + ///the nodes detected by the graph chaining should be fully covered + gchains->a[i+gchains->n].rs = 0; + gchains->a[i+gchains->n].re = uref->ug->g->seq[res->a[i].v>>1].len; + // fprintf(stderr, "aaaaaaa, ulid->%ld\n", ulid); + // fprintf(stderr, "-[M::%s::]\tutg%.6dl(%c)\n", __func__, + // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1]); + // if(ulid == 14714) { + // fprintf(stderr, "-[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\n", __func__, + // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1], + // gchains->a[i+gchains->n].qs, gchains->a[i+gchains->n].qe, + // gchains->a[i+gchains->n].rs, gchains->a[i+gchains->n].re); + // } + } + } + g_item->cnt = res->n; + gchains->n += res->n; + // fprintf(stderr, "sbsbsbsb, ulid->%ld\n", ulid); + // debug_gchain(km, g, gchains->a + gchains->n - res->n, res->n, dst_done, out); + } + } + + raw_idx->n = raw_idx_n; + return n_mchain; +} + +inline uint32_t is_compat_contig_chain(const asg_t *g, ul_ov_t *p, ul_ov_t *m, mg_lchain_t *a, double overhead) +{ + uint64_t ovlp; + ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); + if(ovlp == 0) return 1; + if(ovlp == (m->qe - m->qs)) return 0;////contain + if(ovlp == (p->qe - p->qs)) return 0;////contain + ul_ov_t *i0, *i1; + if(p->qs <= m->qs) { + i0 = p; i1 = m; + } else { + i0 = m; i1 = p; + } + + uint64_t o0 = max_ovlp(g,a[i0->te-1].v); + uint64_t o1 = max_ovlp(g,a[i1->ts].v^1); + uint64_t cut = MIN(o0, o1); cut *= (1 + overhead); + if(ovlp > cut) return 0; + return 1; +} + + +uint32_t select_max_ctg_chain(void *km, const ul_idx_t *uref, int64_t ulid, st_mt_t *idx, vec_mg_lchain_t *e, kv_ul_ov_t *raw_idx, +const asg_t *g, st_mt_t *dst_done, vec_sp_node_t *out, vec_mg_pathv_t *res, vec_mg_lchain_t *gchains) +{ + gchains->n = 0; + if(idx->n <= 0) return 0; + int64_t a_n, idx_n = idx->n, i, k, n_mchain = 0, min_sc, max_sc; uint64_t om, ok, ovlp; + ul_ov_t *m = NULL, *p = NULL, kp; mg_lchain_t *a = e->a, *g_item; int64_t raw_idx_n = raw_idx->n; + ul_ov_t *gb = NULL; int64_t gb_n = 0; + for (i = a_n = 0; i < idx_n; ++i) { + kv_pushp(ul_ov_t, *raw_idx, &p); + p->qn = ((int64_t)(idx->a[i]>>32));//score + p->ts = a_n; p->te = a_n + ((uint32_t)idx->a[i]); + p->qs = a[p->ts].qs; p->qe = a[p->te-1].qe; p->tn = 1;//(tn = 1) -> normal; (t = 0) -> duplicated chain + a_n += ((uint32_t)idx->a[i]); + } + gb = raw_idx->a + raw_idx_n; gb_n = raw_idx->n - raw_idx_n; + radix_sort_ul_ov_srt_qn(gb, gb + gb_n);//sort by scores + for (k = 0, n_mchain = gb_n>>1; k < n_mchain; k++) { + kp = gb[k]; gb[k] = gb[gb_n-k-1]; gb[gb_n-k-1] = kp; + } + + for (k = 0; k < gb_n; k++) {//filter too close chains + m = &(gb[k]); om = m->qe - m->qs; ///current chain + // fprintf(stderr, "k::%ld[M::%s::sc->%u] q::[%u, %u), set::%u\n", k, __func__, m->qn, m->qs, m->qe, m->tn); + if(m->tn == 0) continue; + for (i = k-1; i >= 0; i--) { + p = &(gb[i]); + ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); + if(ovlp == 0) continue; + min_sc = MIN(p->qn, m->qn); max_sc = MAX(p->qn, m->qn); + ok = p->qe - p->qs; ok = MAX(ok, om); + if(min_sc < (max_sc*0.98)) break; + if((ovlp > GC_OFFSET_POS) && (min_sc > (max_sc*0.98)) && (ovlp > (ok*0.8))) { + // fprintf(stderr, "k::%ld[M::%s::i->%ld] min_sc::%ld, max_sc::%ld\n", + // k, __func__, i, min_sc, max_sc); + m->tn = p->tn = 0; + } + } + + for (i = k+1; i < gb_n; i++) { + p = &(gb[i]); + ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); + if(ovlp == 0) continue; + min_sc = MIN(p->qn, m->qn); max_sc = MAX(p->qn, m->qn); + ok = p->qe - p->qs; ok = MAX(ok, om); + if(min_sc < (max_sc*0.98)) break; + if((ovlp > GC_OFFSET_POS) && (min_sc > (max_sc*0.98)) && (ovlp > (ok*0.8))) { + // fprintf(stderr, "k::%ld[M::%s::i->%ld] min_sc::%ld, max_sc::%ld\n", + // k, __func__, i, min_sc, max_sc); + m->tn = p->tn = 0; + } + } + } + + for (k = i = 0; k < gb_n; k++) { + m = &(gb[k]); if(m->tn == 0) continue; + gb[i++] = gb[k]; + } + // fprintf(stderr, "[M::%s::] gb_n0::%ld, gb_n::%ld\n", __func__, gb_n, i); + gb_n = i; + + for (k = n_mchain = 0; k < gb_n; k++) { + m = &(gb[k]); + for (i = 0; i < n_mchain; i++) { + p = &(gb[i]); + if(!is_compat_contig_chain(g, p, m, a, 0.333333)) break; + } + if(i < n_mchain) continue; + gb[n_mchain++] = gb[k]; + } + gb_n = n_mchain; + + if(gb_n) { + gchains->n = 0; + for (k = 0; k < gb_n; k++) { + kv_pushp(mg_lchain_t, *gchains, &g_item); + g_item->v = (uint32_t)-1; + g_item->qs = gb[k].qs; g_item->qe = gb[k].qe; + g_item->rs = gb[k].ts; g_item->re = gb[k].te; + g_item->cnt = g_item->off = 0; + gen_gchain_track(km, a + g_item->rs, g_item->re - g_item->rs, g, dst_done, out, res); + kv_resize(mg_lchain_t, *gchains, gchains->n + res->n); ///a = gchains->a + gchains->n; + for (i = 0, g_item = &(gchains->a[gchains->n-1]); i < ((int64_t)res->n); i++) { + if(res->a[i].v == (uint32_t)-1) { + gchains->a[i+gchains->n] = a[res->a[i].pre + g_item->rs]; + gchains->a[i+gchains->n].dist_pre = res->a[i].d; + // if(ulid == 14714) { + // fprintf(stderr, "+[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\n", __func__, + // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1], + // gchains->a[i+gchains->n].qs, gchains->a[i+gchains->n].qe, + // gchains->a[i+gchains->n].rs, gchains->a[i+gchains->n].re); + // } + } else { + gchains->a[i+gchains->n].v = res->a[i].v; + gchains->a[i+gchains->n].off = -1; + gchains->a[i+gchains->n].dist_pre = res->a[i].d; + ///the nodes detected by the graph chaining should be fully covered + gchains->a[i+gchains->n].rs = 0; + gchains->a[i+gchains->n].re = uref->ug->g->seq[res->a[i].v>>1].len; + // fprintf(stderr, "aaaaaaa, ulid->%ld\n", ulid); + // fprintf(stderr, "-[M::%s::]\tutg%.6dl(%c)\n", __func__, + // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1]); + // if(ulid == 14714) { + // fprintf(stderr, "-[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\n", __func__, + // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1], + // gchains->a[i+gchains->n].qs, gchains->a[i+gchains->n].qe, + // gchains->a[i+gchains->n].rs, gchains->a[i+gchains->n].re); + // } + } + } + g_item->cnt = res->n; + gchains->n += res->n; + // fprintf(stderr, "sbsbsbsb, ulid->%ld\n", ulid); + // debug_gchain(km, g, gchains->a + gchains->n - res->n, res->n, dst_done, out); + } + } + + raw_idx->n = raw_idx_n; + return n_mchain; +} + +// void prt_chains_vlog(ul_ov_t *l_idx, int64_t l_idx_n, ul_ov_t *l_a, uint64_t *g_idx, int64_t g_idx_n, vec_mg_lchain_t *g_a, int64_t ql, int64_t ulid) +// { +// int64_t k, i, s, e; char *as = NULL; +// if(l_idx && l_a) { +// for (k = 0; k < l_idx_n; k++) { +// s = l_idx[k].ts; e = l_idx[k].te; +// asprintf(&as, "[M::%s::linear_chain] sc::%u, occ::%ld\n", __func__, l_idx[k].qn, e-s); +// push_vlog(&(overall_zdbg->a[ulid]), as); free(as); as = NULL; +// for (i = s; i < e; i++) { +// asprintf(&as, "[M::%s::utg%.6dl] q::[%u, %u)\n", __func__, (int32_t)l_a[i].tn+1, l_a[i].qs, l_a[i].qe); +// push_vlog(&(overall_zdbg->a[ulid]), as); free(as); as = NULL; +// } +// } +// } + +// if(g_idx && g_a) { +// for (k = s = e = 0; k < g_idx_n; ++k) { +// s = e; e += ((uint32_t)g_idx[k]); +// asprintf(&as, "[M::%s::grapn_chain] sc::%lu, occ::%ld\n", __func__, g_idx[k]>>32, e-s); +// push_vlog(&(overall_zdbg->a[ulid]), as); free(as); as = NULL; +// for (i = s; i < e; i++) { +// asprintf(&as, "[M::%s::utg%.6dl] q::[%u, %u)\n", __func__, (int32_t)(g_a->a[i].v>>1)+1, g_a->a[i].qs, g_a->a[i].qe); +// push_vlog(&(overall_zdbg->a[ulid]), as); free(as); as = NULL; +// } +// } +// } +// } + +int64_t gl_chain(mg_tbuf_t *b, ul_vec_t *rch, overlap_region_alloc* olist, +Chain_Data* dp, haplotype_evdience_alloc *hap, st_mt_t *sps, glchain_t *ll, +gdpchain_t *gdp, const ul_idx_t *uref, double diff_ec_ul, int64_t winLen, +int64_t qlen, const ug_opt_t *uopt, int64_t debug_i, int64_t tid, void *km) +{ + ll->tk.n = ll->lo.n = 0; + kv_ul_ov_t *idx = &(ll->lo); + ks_introsort_or_xe(olist->length, olist->list); + gen_gl_aln(olist, uref, idx); + if(idx->n == 0) return 0; + int64_t max_idx, occ = 0, f = 0; + + kv_resize(ul_ov_t, ll->tk, idx->n); + occ = gl_chain_lin(idx, olist->list, ll->tk.a, uref, uopt, G_CHAIN_BW, N_GCHAIN_RATE, qlen, UG_SKIP_N, UG_ITER_N, UG_DIS_N, dp, UG_TRANS_W, 0, NULL, uref->ug, 0, debug_i); + // prt_chains(idx->a, idx->n, ll->tk.a, NULL, 0, NULL, qlen); + // prt_chains_vlog(idx->a, idx->n, ll->tk.a, NULL, 0, NULL, qlen, debug_i); + + + if(occ) { + if(ff_chain(idx, qlen, 0.99/**P_CHAIN_COV**/, -1/**G_CHAIN_TRANS_RATE**/, ll->tk.a, NULL, NULL, NULL, diff_ec_ul, winLen, km)) { + f = l2g_res_chain_sc(uref->ug, ll->tk.a+idx->a[idx->n-1].ts, idx->a[idx->n-1].te-idx->a[idx->n-1].ts, &(gdp->swap)); + // f = l2g_res_chain(uref->ug, ll->tk.a+idx->a[idx->n-1].ts, idx->a[idx->n-1].te-idx->a[idx->n-1].ts, &(gdp->swap), -1/**N_GCHAIN_RATE**/); + } + } + + // fprintf(stderr, "+[M::%s]\tf::%ld\n", __func__, f); + // fprintf(stderr, "1-[M::%s] f::%ld\n", __func__, f); + // fprintf(stderr, "(beg1) [M::%s] debug_i:%ld, qlen:%ld\n", __func__, debug_i, qlen); + if(!f) { + // gl_chain_gen(olist, uref, idx, 0, hap, km);///no trans + // l2g_chain(uref, idx, &(gdp->l)); ll->tk.n = 0; + gen_gg_aln(olist, uref, UG_TRANS_W, &(gdp->l)); ll->tk.n = 0; + ///buffer + // kv_resize(uint64_t, ll->srt.a, gdp->l.n); kv_resize(uint64_t, hap->snp_srt, gdp->l.n); + // kv_resize(uint64_t, gdp->v, gdp->l.n); kv_resize(int64_t, gdp->f, gdp->l.n); + // max_idx = hc_gchain1_dp(b->km, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), &(gdp->path), rch->rlen, + // uopt, G_CHAIN_BW, diff_ec_ul, -1, ll->srt.a.a, sps, gdp->f.a, hap->snp_srt.a, gdp->v.a); + kv_resize(uint64_t, ll->srt.a, gdp->l.n); + max_idx = gl_chain_graph_adv(b->km, olist->list, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), + &(gdp->path), rch->rlen, uopt, G_CHAIN_BW, diff_ec_ul, ll->srt.a.a, sps, dp, UG_SKIP_GRAPH_N, UG_ITER_N, UG_DIS_N, 0, UG_TRANS_W, UG_TRANS_ERR_W); + // prt_chains(NULL, 0, NULL, sps->a, sps->n, &(gdp->l), qlen); + // prt_chains_vlog(NULL, 0, NULL, sps->a, sps->n, &(gdp->l), qlen, debug_i); + // if(max_idx >= 0 && gen_max_gchain_adv(b->km, uref, debug_i, sps, &(gdp->l), &(ll->tk), NULL, rch->rlen, P_CHAIN_COV, 0.3/**P_FRAGEMENT_PRIMARY_CHAIN_COV**/, + // 0.1, PRIMARY_UL_CHAIN_MIN, uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), ll->srt.a.a, &(gdp->swap))) { + if(max_idx >= 0 && select_max_gchain(b->km, uref, debug_i, sps, &(gdp->l), &(ll->tk), uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), &(gdp->swap))){ + // print_raw_chains(&(gdp->swap), debug_i); + // f = check_trans_rate_gap(&(gdp->swap), &(ll->tk), olist, hap, uref, diff_ec_ul, winLen, G_CHAIN_TRANS_RATE); + f = 1; + } + } + // fprintf(stderr, "[M::%s] f::%ld\n", __func__, f); + // if(debug_i == 1756) fprintf(stderr, "[M::%s] ulid:%ld, qlen:%ld, f:%ld\n", __func__, debug_i, qlen, f); + if(f) update_ul_vec_t_ug(uref, rch, &(gdp->swap), debug_i); + // debug_ul_vec_t_chain(km, uref->ug->g, rch, &(gdp->dst_done), &(gdp->out)); + // fprintf(stderr, "(beg3) [M::%s::tid:%ld] debug_i:%ld, qlen:%ld\n", __func__, tid, debug_i, qlen); + return 1; +} + + +int64_t comput_err_partial_cigar(int64_t ol, overlap_region *z, int64_t *rk) +{ + int64_t k = 0, err = 0, e = z->x_pos_s+ol, wn = z->w_list.n; (*rk) = -1; + for (k = 0; k < wn; k++) { + if(z->w_list.a[k].x_start >= e) break; + if(z->w_list.a[k].y_end != -1) { + err += z->w_list.a[k].error; + } + } + k--; + if(k < 0) return 0; + if(z->w_list.a[k].y_end != -1) { + err -= z->w_list.a[k].error; + } + + if((int64_t)z->w_list.a[k].x_end+1 <= e) { + if(z->w_list.a[k].y_end != -1) { + err += z->w_list.a[k].error; + } + } else { + // assert(z->w_list.a[k].x_start < e); + if(z->w_list.a[k].y_end != -1) { + err += (((double)(e-z->w_list.a[k].x_start))/ + ((double)(z->w_list.a[k].x_end+1-z->w_list.a[k].x_start)))*z->w_list.a[k].error; + } + } + (*rk) = k; + return err; +} + +int64_t sum_w_err(window_list *a, int64_t n) +{ + int64_t k, err = 0; + for (k = 0; k < n; k++) { + if(a[k].y_end != -1) err += a[k].error; + } + return err; +} + +int64_t comput_sc_partial_cigar(int64_t sc, int64_t ol, double err_sc_r, overlap_region *z, int64_t *wi, int64_t *werr) +{ + int64_t k = wi?(*wi):0, wn = z->w_list.n, err = werr?(*werr):0, e = z->x_pos_s+ol; + if(ol == 0) return sc; + // int64_t pk, pe; + if((int64_t)(z->x_pos_e + 1 - z->x_pos_s) <= ol) return 0; + if(k == wn) { + k--; + if(z->w_list.a[k].y_end != -1) { + err -= z->w_list.a[k].error; + } + } + if(z->w_list.a[k].x_start >= e) { + if(z->w_list.a[k].y_end != -1) err += z->w_list.a[k].error; + for (;(k>=0) && (z->w_list.a[k].x_start>=e); k--) { + if(z->w_list.a[k].y_end != -1) { + err -= z->w_list.a[k].error; + } + } + } else { + for (;(kw_list.a[k].x_startw_list.a[k].y_end != -1) { + err += z->w_list.a[k].error; + } + } + k--; + } + // pk = (*wi); pe = (*werr); + if(k < 0) { + k = 0; err = 0; + if(wi) {(*wi) = k;} if(werr) {(*werr) = err;} + // assert(e <= z->w_list.a[0].x_start); + } else { + if(z->w_list.a[k].y_end != -1) { + err -= z->w_list.a[k].error; + } + if(wi) {(*wi) = k;} if(werr) {(*werr) = err;} + + // if(!(err >= 0 && k >= 0 && k < wn && z->w_list.a[k].x_start < e && z->w_list.a[k].x_end + 1 >= e)){ + // fprintf(stderr, "[M::%s] ol::%ld, e::%ld, z::[%u, %u], k::%ld, wn::%ld, w::[%d, %d], err::%ld\n", __func__, + // ol, e, z->x_pos_s, z->x_pos_e, k, wn, z->w_list.a[k].x_start, z->w_list.a[k].x_end, err); + // } + // assert(err >= 0 && k >= 0 && k < wn && z->w_list.a[k].x_start < e && + // (e <= z->w_list.a[k+1].x_start)); + + if((int64_t)z->w_list.a[k].x_end+1 <= e) { + if(z->w_list.a[k].y_end != -1) { + err += z->w_list.a[k].error; + } + } else { + // assert(z->w_list.a[k].x_start < e); + if(z->w_list.a[k].y_end != -1) { + err += (((double)(e-z->w_list.a[k].x_start))/ + ((double)(z->w_list.a[k].x_end+1-z->w_list.a[k].x_start)))*z->w_list.a[k].error; + } + } + } + + // int64_t dbg_k, dbg_e = comput_err_partial_cigar(ol, z, &dbg_k); + // if(err != dbg_e) { + // fprintf(stderr, "[M::%s] ol::%ld, e::%ld, z::[%u, %u], k::%ld, wn::%ld, w::[%d, %d], err::%ld, dbg_e::%ld, dbg_k::%ld, pe::%ld, pk::%ld, sum_pk_err::%ld, sum_k_err::%ld, werr::%ld\n", + // __func__, ol, e, z->x_pos_s, z->x_pos_e, k, wn, z->w_list.a[k].x_start, z->w_list.a[k].x_end, err, dbg_e, dbg_k, pe, pk, + // sum_w_err(z->w_list.a, pk), sum_w_err(z->w_list.a, k), *werr); + // } + // assert(err == dbg_e); + + ol -= (err*err_sc_r); sc -= ol; if(sc <= 0) sc = 1; + return sc; +} + +///mode: 0->ug; 1->read +int64_t ed_dp_c(overlap_region_alloc *o, kv_ul_ov_t *res, ul_ov_t *ex, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, int64_t max_skip, uint64_t *srt, uint64_t *idx, uint64_t *track, double err_sc, +uint64_t mode, All_reads *ridx, ma_ug_t *ug, uint32_t need_srt) +{ + if(res->n == 0) return 0; + uint32_t li_v, lj_v, rev_n; + int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, qo, qovl, minus_sc, pj, n_skip, wi, werr; + ul_ov_t *li = NULL, *lj = NULL, rev_t; + if(need_srt) { + radix_sort_ul_ov_srt_qe(res->a, res->a + res->n); + for (i = 1, j = 0; i <= (int64_t)res->n; i++) { + if (i == (int64_t)res->n || res->a[i].qe != res->a[j].qe) { + if(i - j > 1) radix_sort_ul_ov_srt_qs(res->a+j, res->a+i); + j = i; + } + } + } + ///res->a[0].qe: min_qe; res->a[res->n-1].qs: max_qs + if(res->a[0].qe == qlen && res->a[res->n-1].qs == 0) {///all alignments are contained + for (i = 0; i < (int64_t)res->n; ++i) { + li = &(res->a[i]); assert(li->qs == 0 && li->qe == qlen); + csc = (li->qe-li->qs); minus_sc = (o->list[li->qn].non_homopolymer_errors*err_sc); + csc -= minus_sc; if(csc <= 0) csc = 1; mm_sc = csc; mm_idx = -1; + + if(mm_sc > ((int64_t)0x7fffffff)) mm_sc = ((int64_t)0x7fffffff); + track[i] = push_sc_pre(mm_sc, mm_idx); + srt[i] = track[i]>>32; srt[i] <<= 32; srt[i] |= i; + } + } else { + memset(idx, 0, (sizeof((*idx))*res->n)); + for (i = 0; i < (int64_t)res->n; ++i) { + li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; + // fprintf(stderr, "[M::%s::i->%ld::utg%.6dl] q[%u, %u), t[%u, %u)\n", __func__, i, (int32_t)li->tn+1, li->qs, li->qe, li->ts, li->te); + mm_ovlp = mode?max_ovlp_src(uopt, li_v^1):max_ovlp(uref->ug->g, li_v^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(i, res->a, x+G_CHAIN_INDEL); + csc = (li->qe-li->qs); minus_sc = (o->list[li->qn].non_homopolymer_errors*err_sc); + csc -= minus_sc; if(csc <= 0) csc = 1; + mm_sc = csc; mm_idx = -1; n_skip = 0; wi = werr = 0; + for (j = x; j >= 0; --j) { // collect potential destination vertices + lj = &(res->a[j]); lj_v = (lj->tn<<1)|lj->rev; + if(lj->qe+G_CHAIN_INDEL <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore + if(lj->qs > li->qs+G_CHAIN_INDEL) continue;///at boundary, migh be lj->qs == li->qs + qo = infer_rovlp(li, lj, NULL, NULL, ridx, ug); ///overlap length in query (UL read) + // fprintf(stderr, "[M::%s::j->%ld] qo::%ld\n", __func__, j, qo); + if(li_v != lj_v && get_ecov_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, mode, NULL)) { + qovl = ((MIN(li->qe, lj->qe) > MAX(li->qs, lj->qs))? (MIN(li->qe, lj->qe) - MAX(li->qs, lj->qs)):0); + // fprintf(stderr, "[M::%s::] utg%.6dl->utg%.6dl, icsc::%ld, ierr::%u, ilen::%u, aln::%u, app_sc::%ld\n", + // __func__, (int32_t)li->tn+1, (int32_t)lj->tn+1, csc, o->list[li->qn].non_homopolymer_errors, + // li->qe - li->qs, o->list[li->qn].align_length, comput_sc_partial_cigar(csc, qovl, err_sc, &(o->list[li->qn]), &wi, &werr)); + sc = comput_sc_partial_cigar(csc, qovl, err_sc, &(o->list[li->qn]), &wi, &werr) + + pop_sc(track[j]); + // fprintf(stderr, "[M::%s::j->%ld] qo::%ld, sc::%ld, mm_sc::%ld\n", __func__, j, qo, sc, mm_sc); + if(sc > mm_sc) { + mm_sc = sc, mm_idx = j; + if (n_skip > 0) --n_skip; + } else if (idx[j] == (uint64_t)i) { + if (++n_skip > max_skip) + break; + } + pj = pop_pre(track[j]); + if(pj >= 0) idx[pj] = i; + } + } + if(mm_sc > ((int64_t)0x7fffffff)) mm_sc = ((int64_t)0x7fffffff); + track[i] = push_sc_pre(mm_sc, mm_idx); + srt[i] = track[i]>>32; srt[i] <<= 32; srt[i] |= i; + // fprintf(stderr, "[M::%s::i->%ld] mm_idx::%ld\n", __func__, i, mm_idx); + } + } + + int64_t n_v, n_u, n_v0; + radix_sort_gfa64(srt, srt+res->n); + for (k = (int64_t)res->n-1, n_v = n_u = 0; k >= 0; --k) { + n_v0 = n_v; + for (i = (uint32_t)srt[k]; i >= 0 && (track[i]&((uint64_t)0x80000000)) == 0;) { + ex[n_v++] = res->a[i]; track[i] |= ((uint64_t)0x80000000); + i = pop_pre(track[i]); + } + if(n_v0 == n_v) continue; + sc = (i<0?(pop_sc(srt[k])):(pop_sc(srt[k])-pop_sc(track[i]))); + if(sc < 0) { + n_v = n_v0; + continue; + } + idx[n_u++] = ((uint64_t)sc<<32)|(n_v-n_v0); + } + + for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { + n_v0 = n_v; n_v += (uint32_t)idx[k]; + res->a[k].qn = idx[k]>>32;//score + res->a[k].ts = n_v0; res->a[k].te = n_v;///idx + + rev_n = ((uint32_t)idx[k])>>1; + ///we need to consider contained reads; so determining qs is not such easy + res->a[k].qs = (uint32_t)-1; res->a[k].qe = ex[n_v0].qe; + for (i = 0; i < rev_n; i++) { + rev_t = ex[n_v0+i]; ex[n_v0+i] = ex[n_v-i-1]; ex[n_v-i-1] = rev_t; + if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; + if(res->a[k].qs > ex[n_v-i-1].qs) res->a[k].qs = ex[n_v-i-1].qs; + } + if(((uint32_t)idx[k])&1) { + if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; + } + } + + res->n = n_u; + radix_sort_ul_ov_srt_qn(res->a, res->a + res->n);//sort by score + // fprintf(stderr, "---[M::%s] n_u:%ld, n_v:%ld\n", __func__, n_u, n_v); + return n_v; +} + +void set_sec_e_min(overlap_region *z, uint64_t *w_idx, int64_t wl, int64_t ql) +{ + int64_t wid, k, wn = z->w_list.n, ws, we; + for (k = 0; k < wn; k++) { + wid = z->w_list.a[k].x_start/wl; + ws = wid*wl; we = ws+wl; if(we > ql) we = ql; we--; + // fprintf(stderr, "[M::%s] ws::%ld, we::%ld, xs::%d, xe::%d, err::%d\n", __func__, + // ws, we, z->w_list.a[k].x_start, z->w_list.a[k].x_end, z->w_list.a[k].error); + if(ws == z->w_list.a[k].x_start && we == z->w_list.a[k].x_end && z->w_list.a[k].y_end != -1) { + if((w_idx[wid] == (uint64_t)-1) || (w_idx[wid] > (uint64_t)z->w_list.a[k].error)) { + w_idx[wid] = z->w_list.a[k].error; + } + } + } +} + +int64_t cal_sec_e_min(overlap_region *z, uint64_t *w_idx, int64_t wl, int64_t ql, int64_t *sec_err) +{ + int64_t wid, k, wn = z->w_list.n, ws, we, o[2], tot_e, sc; uint64_t self_err; + o[0] = o[1] = tot_e = 0; + for (k = 0; k < wn; k++) { + wid = z->w_list.a[k].x_start/wl; + if(w_idx[wid] == (uint64_t)-1) continue; + ws = wid*wl; we = ws+wl; if(we > ql) we = ql; we--; + self_err = THRESHOLD_MAX_SIZE + 1; + if(z->w_list.a[k].y_end != -1) self_err = z->w_list.a[k].error; + + if(ws == z->w_list.a[k].x_start && we == z->w_list.a[k].x_end) { + if(self_err <= w_idx[wid]) { + o[0] += we+1-ws; + } else { + o[1] += we+1-ws; tot_e += self_err - w_idx[wid]; + } + } + } + if(sec_err) (*sec_err) = tot_e; + + sc = o[0] - (o[1]*ERROR_RATE)-(tot_e*5); + return sc; +} + + +void set_w_e(overlap_region *z, uint64_t *w_idx, int64_t wl, int64_t ql) +{ + int64_t wid, k, wn = z->w_list.n, ws, we; + for (k = 0; k < wn; k++) { + wid = z->w_list.a[k].x_start/wl; + ws = wid*wl; we = ws+wl; if(we > ql) we = ql; we--; + // fprintf(stderr, "[M::%s] ws::%ld, we::%ld, xs::%d, xe::%d, err::%d\n", __func__, + // ws, we, z->w_list.a[k].x_start, z->w_list.a[k].x_end, z->w_list.a[k].error); + if(ws == z->w_list.a[k].x_start && we == z->w_list.a[k].x_end && z->w_list.a[k].y_end != -1) { + if((w_idx[wid] == (uint64_t)-1) || (w_idx[wid] < (uint64_t)z->w_list.a[k].error)) { + w_idx[wid] = z->w_list.a[k].error; + } + } + } +} + +uint32_t ck_w_err(overlap_region *z, uint64_t *w_idx, int64_t wl, int64_t ql) +{ + int64_t wid, k, wn = z->w_list.n, ws, we, ol, e[2]; + ol = e[0] = e[1] = 0; + for (k = 0; k < wn; k++) { + wid = z->w_list.a[k].x_start/wl; + if(w_idx[wid] == (uint64_t)-1) continue; + ws = wid*wl; we = ws+wl; if(we > ql) we = ql; we--; + if(ws == z->w_list.a[k].x_start && we == z->w_list.a[k].x_end) { + ol += we+1-ws; e[0] += w_idx[wid]; + if(z->w_list.a[k].y_end != -1) e[1] += z->w_list.a[k].error; + else e[1] += THRESHOLD_MAX_SIZE + 1; + } + } + // fprintf(stderr, "[M::%s::utg%.6dl] x::[%u, %u), ol::%ld, e[0]::%ld, e[1]::%ld\n", + // __func__, (int32_t)z->y_id+1, z->x_pos_s, z->x_pos_e+1, ol, e[0], e[1]); + if(e[1] > (e[0]+64)) { + if((e[1] > (e[0]+(ol*0.01)))/**||(e[1] > (e[0]+(e[0]*0.03)))**/) { + z->non_homopolymer_errors = e[1] - e[0]; + return 0; + } + } + // if((e[1] > (e[0]+16)) && (e[1] > (e[0]+(ol*0.01)))) return 0; + return 1; +} + +int64_t filter_sec(overlap_region_alloc *ol, ul_ov_t *idx, int64_t idx_n, ul_ov_t *a, uint64_t *w_idx, uint64_t nw, uint64_t wl, uint64_t ql) +{ + if(idx_n <= 0) return 1; + int64_t on = ol->length, k, z, on_contain = 0, max_i = -1, max_k = -1; overlap_region t; + memset(w_idx, -1, nw*sizeof((*w_idx))); + for (k = 0; k < on; k++) ol->list[k].is_match = 0; + for (k = 0; k < idx_n; k++) {///potiential best chains + // fprintf(stderr, "[M::%s::pri_chain[%ld]] q_coord::[%u, %u), occ::%u\n", + // __func__, k, idx[k].qs, idx[k].qe, idx[k].te-idx[k].ts); + for (z = idx[k].ts; z < idx[k].te; z++) { + ol->list[a[z].qn].is_match = 2; + set_w_e(&(ol->list[a[z].qn]), w_idx, wl, ql); + // fprintf(stderr, "[M::%s::utg%.6dl]\n", __func__, (int32_t)a[z].tn+1); + } + on_contain += (((idx[k].te-idx[k].ts)==1)?1:0); + } + if(on_contain == idx_n) {///each primary chain only has one alignment + on_contain = 0; + } else { + on_contain = -on-1;///in this case, on_contain == z is always wrong + } + max_i = a[idx[idx_n-1].ts].qn; + for (k = z = 0; k < on; k++) { + if(!ol->list[k].is_match) ol->list[k].is_match = ck_w_err(&(ol->list[k]), w_idx, wl, ql); + if(!ol->list[k].is_match) continue; + if(z != k) { + t = ol->list[k]; + ol->list[k] = ol->list[z]; + ol->list[z] = t; + } + if(ol->list[z].x_pos_s == 0 && ol->list[z].x_pos_e == ql - 1) { + on_contain++; + if(max_i == k) max_k = z; + } + // if(ol->list[z].is_match == 1) alt_occ++; + // else ol->list[z].is_match = 1; + ol->list[z].is_match = 1; + z++; + } + ol->length = z; + // fprintf(stderr, "+[M::%s] oln::%ld\n", __func__, ol->length); + if(on_contain == z) {///do not contribute to phase + k = max_k; z = 0; + if(z != k) { + t = ol->list[k]; + ol->list[k] = ol->list[z]; + ol->list[z] = t; + } + ol->length = 1; + } + // fprintf(stderr, "-[M::%s] oln::%ld\n", __func__, ol->length); + // if(alt_occ == 0 || ol->length == 1) return 1;//if all alignments are primary or there is only one alignment + // for (k = ol->length; k < on; k++) ol->list[k].is_match = 2;//recover trans alignments + // ol->length = on; + if(ol->length == 1) return 1; + return 0; +} + +void regen_ul_ov_t_lst(const ul_idx_t *uref, overlap_region_alloc* olist, kv_ul_ov_t *idx) +{ + uint64_t k; ul_ov_t *p; idx->n = 0; + kv_resize(ul_ov_t, *idx, olist->length); + for (k = 0; k < olist->length; k++) { + // fprintf(stderr, "---[M::%s::utg%.6dl] q[%d, %d), t[%d, %d), tot::%u, cis::%u\n", __func__, + // (int32_t)olist->list[k].y_id+1, olist->list[k].x_pos_s, olist->list[k].x_pos_e+1, + // olist->list[k].y_pos_s, olist->list[k].y_pos_e+1, + // olist->list[k].overlapLen, olist->list[k].align_length); + p = &(idx->a[idx->n++]); + p->qn = k; p->qs = olist->list[k].x_pos_s; p->qe = olist->list[k].x_pos_e+1; + p->tn = olist->list[k].y_id; p->el = 1; p->rev = olist->list[k].y_pos_strand; + p->sec = olist->list[k].non_homopolymer_errors; + if(p->rev) { + p->ts = uref->ug->u.a[p->tn].len - (olist->list[k].y_pos_e+1); + p->te = uref->ug->u.a[p->tn].len - olist->list[k].y_pos_s; + } else { + p->ts = olist->list[k].y_pos_s; + p->te = olist->list[k].y_pos_e+1; + } + } +} + +int64_t gl_chain_flter(overlap_region_alloc* olist, Correct_dumy* dumy, st_mt_t *sps, glchain_t *ll, +const ul_idx_t *uref, double diff_ec_ul, int64_t wl, int64_t ql, const ug_opt_t *uopt, uint32_t *need_phase) +{ + (*need_phase) = 1; + uint64_t k, nw; ul_ov_t *m, *p; int64_t occ, i, ovlp, idx_n; + ll->tk.n = ll->lo.n = 0; + kv_ul_ov_t *idx = &(ll->lo); + ks_introsort_or_xe(olist->length, olist->list); + regen_ul_ov_t_lst(uref, olist, idx); + if(idx->n == 0) return 0; + kv_resize(uint64_t, ll->srt.a, idx->n); + kv_resize(uint64_t, *sps, idx->n); + kv_resize(ul_ov_t, ll->tk, idx->n); + + occ = ed_dp_c(olist, idx, ll->tk.a, uref, uopt, G_CHAIN_BW, N_GCHAIN_RATE, ql, 75, dumy->overlapID, ll->srt.a.a, sps->a, ERROR_RATE, 0, NULL, uref->ug, 0); + if((!occ) || (!idx->n)) return 0; + idx_n = idx->n; p = &(idx->a[idx_n-1]); + if(idx_n <= 1) {//one chain; nothing to do + if(p->te - p->ts <= 1) (*need_phase) = 0;//one alignment; nothing to do + return 0; + } + // fprintf(stderr, "[M::%s] qs::%u, qe::%u, ql::%ld, occ::%u\n", __func__, p->qs, p->qe, ql, p->te - p->ts); + if(p->qe-p->qs <= (ql*0.333333)) return 0;///primary chain is too short + + i = idx_n-1; occ = p->te - p->ts; + if(p->qe-p->qs < ql && idx_n > 1) { + for (occ = 0; i >= 0; i--) { + p = &(idx->a[i]); + for (k = i + 1; k < idx->n; k++) { + m = &(idx->a[k]); + ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); + if(((ovlp > ((m->qe-m->qs)*0.005)) || (ovlp > ((p->qe-p->qs)*0.015))) && ovlp > 32) break; + if((ovlp == (m->qe-m->qs)) || (ovlp == (p->qe-p->qs))) break; + } + if(k < idx->n) break; + occ += p->te - p->ts; + } + i++; + } + //all alignments are primary chains; nothing to do + if(occ == (int64_t)olist->length) return 1; + + // if(i >= ((int64_t)idx->n)) return 0; + nw = get_num_wins(0, ql, wl); kv_resize(uint64_t, ll->srt.a, (uint64_t)nw); + if(filter_sec(olist, idx->a+i, idx->n-i, ll->tk.a, ll->srt.a.a, nw, wl, ql)) { + (*need_phase) = 0; + } + return 1; +} + + + +uint64_t gen_shared_trace(overlap_region_alloc* ol, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, +const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, int64_t *is_srt, kv_ul_ov_t *res)///[s, e] +{ + if(!id_n) return 0; + uint64_t i, m, k, os, oe, ovlp, rm_n = 0; ul_ov_t p, q, *li, *lj, *t; + for (i = m = 0; i < id_n; i++) { + if(ol->list[id_a[i]].x_pos_e < s) continue; + id_a[m++] = id_a[i]; + } + id_n = m; + if(!id_n) return 0; + //idx_a[] is sorted by ol->list[].x_pos_s + for (k = 0; k < id_n; k++) { + convert_ul_ov_t(&p, &(ol->list[id_a[k]]), uref->ug); p.qn = id_a[k]; + if(ol->list[id_a[k]].x_pos_e <= e) rm_n++; + + for (i = 0; i < id_n && ol->list[id_a[i]].x_pos_s <= ol->list[id_a[k]].x_pos_e; i++) { + if(i == k) continue; + convert_ul_ov_t(&q, &(ol->list[id_a[i]]), uref->ug); q.qn = id_a[i]; + if(p.qe > q.qe) li = &p, lj = &q; + else if(p.qe == q.qe && p.qs >= q.qs) li = &p, lj = &q; + else lj = &p, li = &q; + os = MAX(li->qs, lj->qs), oe = MIN(li->qe, lj->qe); + ovlp = ((oe > os)? (oe - os):0); + if(!ovlp) continue;//no overlap + t = NULL; + if(res->n > 0 && res->a[res->n-1].qn == p.qn) { + if(res->a[res->n-1].qs<=os && res->a[res->n-1].qe>=oe) continue; + t = &(res->a[res->n-1]); + } + // fprintf(stderr, "\nk::%lu::utg%.6dl[M::%s::utg%.6dl->utg%.6dl]\n", + // k, (int32_t)ol->list[id_a[k]].y_id+1, __func__, (int32_t)li->tn+1, (int32_t)lj->tn+1); + //not contain; graph does not has contained overlaps + //but at boundary, migh be lj->qs == li->qs + if(lj->qs <= li->qs+G_CHAIN_INDEL) { + if(govlp_check(uref, uopt, bw, diff_ec_ul, li, lj)) continue; + } else if((lj->qe+G_CHAIN_INDEL>=li->qe) && (lj->qs+G_CHAIN_INDEL>=li->qs)) { + if(govlp_check(uref, uopt, bw, diff_ec_ul, lj, li)) continue; + } + if(t && t->qs<=os && t->qe >= os) { + ///assert(t->qs<=os && t->qe t->qe) t->qe = oe; + } else { + kv_pushp(ul_ov_t, *res, &t); + t->qn = p.qn; t->qs = os; t->qe = oe; + } + } + if(res->n > 0 && res->a[res->n-1].qn == p.qn) { + ol->list[p.qn].align_length++; + if(ol->list[p.qn].align_length > 1) (*is_srt) = 0; + } + } + + if(rm_n) { + for (i = m = 0; i < id_n; i++) { + if(ol->list[id_a[i]].x_pos_e <= e) continue; + id_a[m++] = id_a[i]; + } + id_n = m; + } + return id_n; +} + +uint64_t gen_shared_intervals(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t wl, kvec_t_u64_warp* idx, kv_ul_ov_t *res) +{ + int64_t i, j, k, on = ol->length, srt_n = on<<1, dp, old_dp, beg, end, is_srt = 1; + ///collect overlapped regions + kv_resize(uint64_t, idx->a, (ol->length<<1)); res->n = 0; + for (i = k = 0; i < on; i++) { + idx->a.a[k] = (ol->list[i].x_pos_s<<1); idx->a.a[k] <<= 32; idx->a.a[k] += i; k++; + idx->a.a[k] = (ol->list[i].x_pos_e<<1)+1; idx->a.a[k] <<= 32; idx->a.a[k] += i; k++; + ol->list[i].align_length = 0; + // fprintf(stderr, "+++[M::%s::utg%.6dl] q[%u, %u), t[%u, %u)\n", __func__, (int32_t)ol->list[i].y_id+1, + // ol->list[i].x_pos_s, ol->list[i].x_pos_e+1, + // ol->list[i].y_pos_s, ol->list[i].y_pos_e+1); + } + radix_sort_gfa64(idx->a.a, idx->a.a+k); idx->a.n = k; + for (i = 0, dp = 0, beg = 0, end = -1; i < srt_n; ++i) {///[beg, end] + old_dp = dp; + ///if idx->a.a[] is qe + if ((idx->a.a[i]>>32)&1) { + --dp; + }else { + //meet a new overlap; the overlaps are pushed by the x_pos_s + ++dp; kv_push(uint64_t, idx->a, ((uint32_t)idx->a.a[i])); + } + + ///old_dp < dp, idx->a.a[] is qs + if (old_dp < 2 && dp >= 2) { + beg = idx->a.a[i]>>33; + } else if (old_dp >= 2 && dp < 2) {///old_dp > min_dp, idx->a.a[] is qe + end = idx->a.a[i]>>33;///[beg, end] + idx->a.n = srt_n + gen_shared_trace(ol, idx->a.a+srt_n, idx->a.n-srt_n, beg, end, uref, uopt, G_CHAIN_BW, N_GCHAIN_RATE, &is_srt, res); + } + } + if(!res->n) return res->n; + + int64_t res_n = res->n; + // if(!is_srt) { + radix_sort_ul_ov_srt_qn(res->a, res->a + res->n); + for (i = 1, j = 0; i <= res_n; i++) { + if (i == res_n || res->a[i].qn != res->a[j].qn) { + if(i - j > 1) radix_sort_ul_ov_srt_qs(res->a+j, res->a+i); + j = i; + } + } + // } + + + // fprintf(stderr, "[M::%s::] res->n::%d\n", __func__, (int32_t)res->n); + // for (i = 0; i < res_n; i++) { + // fprintf(stderr, "---[M::%s::utg%.6dl] oid::%u, q[%u, %u)\n", __func__, + // (int32_t)ol->list[res->a[i].qn].y_id+1, res->a[i].qn, res->a[i].qs, res->a[i].qe); + // } + return res->n; +} + +void filter_topN(overlap_region_alloc* ol, kv_ul_ov_t *aln, uint64_t ql, uint64_t wl, uint64_t max_cov, glchain_t *ll) +{ + uint64_t i, j, k, cc, nw, cc_max = (ql*max_cov), *w_idx, *srt; overlap_region *z; + for (i = cc = 0; i < aln->n; i++) cc += aln->a[i].qe-aln->a[i].qs; + if(cc <= cc_max) return; + + nw = get_num_wins(0, ql, wl); kv_resize(uint64_t, ll->srt.a, nw+ol->length); + w_idx = ll->srt.a.a; memset(w_idx, -1, nw*sizeof((*w_idx))); srt = ll->srt.a.a + nw; + for (i = 0; i < ol->length; i++) { + ol->list[i].is_match = ol->list[i].align_length = 0; + append_unmatched_wins(&(ol->list[i]), wl); + set_sec_e_min(&(ol->list[i]), w_idx, wl, ql); + } + + for (i = 1, j = 0; i <= aln->n; i++) { + if (i == aln->n || aln->a[i].qn != aln->a[j].qn) { + z = &(ol->list[aln->a[j].qn]); z->align_length = 0; + for (k = j; k < i; k++) { + z->align_length += aln->a[k].qe-aln->a[k].qs; + assert(k <= j || aln->a[k].qs >= aln->a[k-1].qe); + } + j = i; + } + } + + int64_t sc, m, sec_err, h0, h1; + for (i = m = h0 = h1 = 0; i < ol->length; i++) { + sc = cal_sec_e_min(&(ol->list[i]), w_idx, wl, ql, NULL); + if(sc >= 0) { + srt[m] = sc; srt[m] <<= 32; srt[m] |= i; srt[m] |= ((uint64_t)0x8000000000000000); h0++; + } else { + srt[m] = -sc; srt[m] <<= 32; srt[m] |= i; h1++; + } + m++; + } + + radix_sort_gfa64(srt, srt + ol->length); + if(h1 > 0) {///have chains with negative weight + uint64_t zn = h1>>1, zt; + for (i = 0; i < zn; i++) { + zt = srt[i]; srt[i] = srt[h1-i-1]; srt[h1-i-1] = zt; + } + } + + for (m = ((int64_t)ol->length)-1, cc = 0; m >= 0 && cc <= cc_max; m--) { + cc += ol->list[(uint32_t)srt[m]].align_length; + ol->list[(uint32_t)srt[m]].is_match = 1; + } + + for (k = m = 0; k < ol->length; k++) { + ol->list[k].align_length = (uint32_t)-1; + if(!ol->list[k].is_match) continue; + ol->list[k].align_length = m; + m++; + } + + for (i = m = 0; i < aln->n; i++) { + if(ol->list[aln->a[i].qn].is_match == 0) continue; + aln->a[m] = aln->a[i]; + aln->a[m].qn = ol->list[aln->a[m].qn].align_length; + m++; + } + aln->n = m; + + overlap_region t; + for (k = m = 0; k < ol->length; k++) { + if(!ol->list[k].is_match) { + cal_sec_e_min(&(ol->list[k]), w_idx, wl, ql, &sec_err); + ol->list[k].non_homopolymer_errors = sec_err; + continue; + } + if(m != (int64_t)k) { + t = ol->list[k]; ol->list[k] = ol->list[m]; ol->list[m] = t; + } + m++; + } + ol->length = m; +} + + +uint64_t get_win_info(overlap_region *z, uint64_t wid, int64_t *ys, int64_t *ye, int64_t *err) +{ + (*err) = -2; + if((wid > 0) && (z->w_list.a[wid].y_end != -1) && (z->w_list.a[wid-1].y_end != -1) && (z->w_list.a[wid].y_end > z->w_list.a[wid-1].y_end)) { + (*ys) = z->w_list.a[wid-1].y_end+1; + (*ye) = z->w_list.a[wid].y_end; + (*err) = z->w_list.a[wid].error; + return 1; + }else if(z->w_list.a[wid].y_end == -1) { + (*ys) = (*ye) = (*err) -1; + return 1; + } + return 0; +} + +char* retrive_str_piece(All_reads *rref, const ul_idx_t *uref, char *buf, int64_t s, int64_t l, int64_t rev, int64_t id) +{ + if(rref) recover_UC_Read_sub_region(buf, s, l, rev, rref, id); + else if(uref) retrieve_u_seq(NULL, buf, &(uref->ug->u.a[id]), rev, s, l, NULL); + else return NULL; + return buf; +} + +uint64_t gen_commen_win(All_reads *rref, const ul_idx_t *uref, overlap_region_alloc* ol, uint64_t *id_a, uint64_t id_n, uint64_t s, uint64_t e, uint64_t ql, uint64_t wl, +uint64_t *buf, uint64_t dp, char *str0, char *str1, kv_ul_ov_t *aln)///[s, e) +{ + if(!id_n) return id_n; + uint64_t i, m, k, rm_n = 0, buf_n = 0, qs, qe, wid; char *qstring, *tstring; + overlap_region *z; uint64_t ws, we; int64_t r_y[2], r_err, p_y[2], p_err; + ///shrink [qs, qe) + qs = (s/wl)*wl; if(qs < s) qs += wl; if(qs >= ql) return id_n; + qe = (e/wl)*wl; if(qe >= ql) qe = ql; + if(qs >= qe) return id_n; + //idx_a[] is sorted by aln[].qs + for (k = 0; k < id_n; k++) { + if(aln->a[id_a[k]].qs<=qs && aln->a[id_a[k]].qe>=qe) { + buf[buf_n++] = id_a[k]; + } + if(aln->a[id_a[k]].qe < e) rm_n++; + } + assert(buf_n == dp && buf_n > 1); + + if(buf_n > 0) { + ///fs = fe = (uint64_t)-1; + for (k = qs; k < qe; k += wl) { + ws = k; we = ws + wl; if(we > qe) we = qe;//[ws, we) + // fprintf(stderr, ">>>[M::%s::] w[%lu, %lu), buf_n::%lu\n", __func__, ws, we, buf_n); + ///first overlap + z = &(ol->list[aln->a[buf[0]].qn]); + wid = get_win_id_by_s(z, ws, wl, NULL); + if(!get_win_info(z, wid, &(r_y[0]), &(r_y[1]), &r_err)) continue; + // fprintf(stderr, "###[M::%s::] y[%ld, %ld), off::%ld, y_err::%ld\n", __func__, r_y[0], r_y[1], r_y[1]-r_y[0], r_err); + qstring = tstring = NULL; + for (i = 1; i < buf_n; i++) { + z = &(ol->list[aln->a[buf[i]].qn]); + wid = get_win_id_by_s(z, ws, wl, NULL); + if(!get_win_info(z, wid, &(p_y[0]), &(p_y[1]), &p_err)) break; + // fprintf(stderr, "###[M::%s::] y[%ld, %ld), off::%ld, y_err::%ld\n", __func__, p_y[0], p_y[1], p_y[1]-p_y[0], p_err); + if(((r_y[1]-r_y[0]) != (p_y[1]-p_y[0])) || (r_err != p_err)) break; + if(r_err == 0) continue; + if(r_err != -1) {///if this window ar all overlaps is unmapped + if(!qstring) { + qstring = retrive_str_piece(rref, uref, str0, r_y[0], r_y[1]+1-r_y[0], + ol->list[aln->a[buf[0]].qn].y_pos_strand, ol->list[aln->a[buf[0]].qn].y_id); + } + tstring = retrive_str_piece(rref, uref, str1, p_y[0], p_y[1]+1-p_y[0], z->y_pos_strand, z->y_id); + if(memcmp(str0, str1, (we-ws))) break; + } + } + if(i < buf_n) continue; + for (i = 0; i < buf_n; i++) { + z = &(ol->list[aln->a[buf[i]].qn]); + wid = get_win_id_by_s(z, ws, wl, NULL); + z->w_list.a[wid].extra_end = -1; + } + // if(fs == (uint64_t)-1) { + // fs = ws; fe = we; + // } else if(ws >= fs && ws <= fe) { + // if(fe < we) fe = we; + // } else { + // kv_pushp(ul_ov_t, *aln, &p); p->el = 0; p->qs = fs; p->qe = fe; + // fs = ws; fe = we; + // } + } + // if(fs != (uint64_t)-1) { + // kv_pushp(ul_ov_t, *aln, &p); p->el = 0; p->qs = fs; p->qe = fe; + // } + } + if(rm_n) { + for (i = m = 0; i < id_n; i++) { + if(aln->a[id_a[i]].qe < e) continue; + id_a[m++] = id_a[i]; + } + id_n = m; + } + return id_n; +} + + +void update_shared_intervals(overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, +All_reads *rref, UC_Read* tu, kvec_t_u64_warp* idx, st_mt_t *sps, int64_t ql, int64_t wl, kv_ul_ov_t *aln, uint64_t rid) +{ + if(!aln->n) return; + uint64_t i, k, own, srt_n; int64_t dp, old_dp, beg, end; overlap_region *z; + for (i = 0; i < ol->length; i++) { + z = &(ol->list[i]); append_unmatched_wins(z, wl); + own = z->w_list.n; z->align_length = (uint32_t)-1; + for (k = 0; k < own; k++) { + if(z->w_list.a[k].extra_end < 0) z->w_list.a[k].extra_end = 0; + } + } + + kv_resize(uint64_t, idx->a, (aln->n<<1)); kv_resize(uint64_t, *sps, aln->n); + for (i = srt_n = 0; i < aln->n; i++) { + if(i == 0 || aln->a[i].qn != aln->a[i-1].qn) ol->list[aln->a[i].qn].align_length = i; + idx->a.a[srt_n] = aln->a[i].qs<<1; idx->a.a[srt_n] <<= 32; idx->a.a[srt_n] += i; srt_n++; + idx->a.a[srt_n] = ((aln->a[i].qe-1)<<1)+1; idx->a.a[srt_n] <<= 32; idx->a.a[srt_n] += i; srt_n++; + aln->a[i].el = 1; + } + + radix_sort_gfa64(idx->a.a, idx->a.a+srt_n); idx->a.n = srt_n; resize_UC_Read(tu, (wl<<1)); + for (i = 0, dp = 0, beg = 0, end = -1; i < srt_n; ++i) {///[beg, end] + old_dp = dp; + ///if idx->a.a[] is qe + if ((idx->a.a[i]>>32)&1) { + --dp; end = (idx->a.a[i]>>33)+1; + }else { + //meet a new overlap; the overlaps are pushed by the x_pos_s + ++dp; end = (idx->a.a[i]>>33); + kv_push(uint64_t, idx->a, ((uint32_t)idx->a.a[i])); + } + ///[beg, end) + // if(rid == 92) { + // fprintf(stderr, "[M::%s::input] beg::%ld, end::%ld, old_dp::%ld, dp::%ld\n", + // __func__, beg, end, old_dp, dp); + // } + if((end > beg) && (end - beg > wl) && (old_dp >= 2) ) { + idx->a.n = srt_n + + gen_commen_win(rref, uref, ol, idx->a.a+srt_n, idx->a.n-srt_n, beg, end, ql, wl, sps->a, old_dp, tu->seq, tu->seq+wl, aln); + } + beg = end; + } + + return; +} + +uint64_t kv_ul_ov_t_statistics(kv_ul_ov_t *olist, uint64_t qn, int64_t *occ) +{ + int64_t k, l = 0; + uint32_t sp = (uint32_t)-1, ep = (uint32_t)-1; + for (k = olist->n-1; k >= 0 && olist->a[k].qn == qn; k--) { + if(!(olist->a[k].el)) continue; + if(!(olist->a[k].tn&((uint32_t)(0x80000000)))) continue; + if(sp == (uint32_t)-1 || olist->a[k].qe <= sp) { + if(sp != (uint32_t)-1) l += ep - sp; + sp = olist->a[k].qs; + ep = olist->a[k].qe; + } else { + sp = MIN(sp, olist->a[k].qs); + } + (*occ)++; + } + if(sp != (uint32_t)-1) l += ep - sp; + return l; +} + +#define kv_mem(v) ((v).m * sizeof(*((v).a))) + +int64_t get_utepdat_t_mem_tid(const utepdat_t *b, int64_t tid, int64_t *mem, int64_t *mem_hab) +{ + km_stat_t kmst; memset(mem, 0, sizeof(*(mem))*6); + if(b->hab) { + mem[0] += ha_ovec_mem(b->hab[tid], mem_hab); + } + if(b->ll) { + mem[1] += kv_mem(b->ll[tid].lo) + kv_mem(b->ll[tid].tk) + kv_mem(b->ll[tid].srt.a)+ kv_mem(b->ll[tid].tc); + } + if(b->buf) { + km_stat(b->buf[tid]->km, &kmst); + mem[2] += kmst.capacity; + } + if(b->gdp) { + mem[3] += kv_mem(b->gdp[tid].l) + kv_mem(b->gdp[tid].swap) + kv_mem(b->gdp[tid].dst) + kv_mem(b->gdp[tid].out) + + kv_mem(b->gdp[tid].path) + kv_mem(b->gdp[tid].v) + kv_mem(b->gdp[tid].f) + kv_mem(b->gdp[tid].dst_done); + } + if(b->mzs) { + mem[4] += kv_mem(b->mzs[tid]); + } + if(b->sps) { + mem[5] += kv_mem(b->sps[tid]); + } + return mem[0] + mem[1] + mem[2] + mem[3] + mem[4] + mem[5]; +} + +/** +static void worker_for_ul_scall_alignment_back(void *data, long i, int tid) // callback for kt_for() +{ + utepdat_t *s = (utepdat_t*)data; + ha_ovec_buf_t *b = s->hab[tid]; + glchain_t *bl = &(s->ll[tid]); + int64_t winLen = MIN((((double)THRESHOLD_MAX_SIZE)/s->opt->diff_ec_ul), WINDOW); + uint64_t align = 0; + int fully_cov, abnormal; + void *km = s->buf?(s->buf[tid]?s->buf[tid]->km:NULL):NULL; + // if(s->id+i!=3196) return; + // fprintf(stderr, "[M::%s] rid:%ld\n", __func__, s->id+i); + // if (memcmp(UL_INF.nid.a[s->id+i].a, "d0aab024-b3a7-40fb-83cc-22c3d6d951f8", UL_INF.nid.a[s->id+i].n-1)) return; + // fprintf(stderr, "[M::%s::] ==> len: %lu\n", __func__, s->len[i]); + ha_get_ul_candidates_interface(b->abl, i, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->olist_hp, &b->clist, s->opt->bw_thres, + s->opt->max_n_chain, 1, NULL, &b->r_buf, &(b->tmp_region), NULL, &(b->sp), asm_opt.hom_cov, km); + + clear_Cigar_record(&b->cigar1); + clear_Round2_alignment(&b->round2); + // return; + // b->num_correct_base += overlap_statistics(&b->olist, NULL, 0); + + b->self_read.seq = s->seq[i]; b->self_read.length = s->len[i]; b->self_read.size = 0; + correct_ul_overlap(&b->olist, s->uu, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, + &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 1, &fully_cov, &abnormal, s->opt->diff_ec_ul, winLen, km); + + // uint64_t k; + // for (k = 0; k < b->olist.length; k++) { + // if(b->olist.list[k].is_match == 1) b->num_correct_base += b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; + // if(b->olist.list[k].is_match == 2) b->num_recorrect_base += b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; + // } + + + // gl_chain_refine(&b->olist, &b->correct, &b->hap, bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], km); + gl_chain_refine_advance(&b->olist, &b->correct, &b->hap, bl, &(s->sps[tid]), s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, km); + // return; + // b->num_read_base += b->self_read.length; + // b->num_correct_base += b->correct.corrected_base; + // b->num_recorrect_base += b->round2.dumy.corrected_base; + memset(&b->self_read, 0, sizeof(b->self_read)); + align = kv_ul_ov_t_statistics(&(bl->tk), i, &(b->num_recorrect_base)); + if(align == s->len[i]) { + free(s->seq[i]); s->seq[i] = NULL; + } + b->num_correct_base += align; + // exit(1); + // uint64_t k; + // b->num_read_base += overlap_statistics(&b->olist, NULL, NULL, 1); + // for (k = 0; k < bl->tk.n; k++) { + // if(bl->tk.a[k].sec == 0) b->num_correct_base += bl->tk.a[k].qe - bl->tk.a[k].qs; + // if(bl->tk.a[k].sec > 0) b->num_recorrect_base += bl->tk.a[k].qe - bl->tk.a[k].qs; + // } + // for (k = 0; k < bl->lo.n; k++) { + // b->num_read_base += bl->lo.a[k].qe - bl->lo.a[k].qs; + // } + + // uint32_t l1 = overlap_statistics(&b->olist, s->uu->ug, 1), l2 = overlap_statistics(&b->olist, s->uu->ug, 2); + // + // if(l1 == 0 && l2 > 0) fprintf(stderr, "[M::%s::%lu::no_match]\n", UL_INF.nid.a[s->id+i].a, s->len[i]); + // fprintf(stderr, "[M::%s::%lu::] l1->%u; l2->%u\n", UL_INF.nid.a[s->id+i].a, s->len[i], l1, l2); +} +**/ + + +overlap_region *gen_aux_ovlp(overlap_region_alloc* ol) +{ + if (ol->length + 1 > ol->size) { + uint64_t sl = ol->size; + ol->size = ol->length + 1; + kroundup64(ol->size); + REALLOC(ol->list, ol->size); + /// need to set new space to be 0 + memset(ol->list + sl, 0, sizeof(overlap_region)*(ol->size - sl)); + } + return &(ol->list[ol->length+1]); +} + + +///mode: 0->ug; 1->read +int64_t get_ecov_contain_adv(const ul_idx_t *uref, const ug_opt_t *uopt, uint32_t v, uint32_t w, int64_t bw, double diff_ec_ul, int64_t dq, int64_t *is_contain) +{ + int64_t dt = -1, dif, mm; + ma_hit_t_alloc* src = uopt->sources; + int64_t min_ovlp = uopt->min_ovlp; + int64_t max_hang = uopt->max_hang; + uint64_t z, qn, tn, x = v>>1; int32_t r = 1; asg_arc_t e; + + for (z = 0; z < src[x].length; z++) { + qn = Get_qn(src[x].buffer[z]); tn = Get_tn(src[x].buffer[z]); + if(tn != (w>>1)) continue; + r = ma_hit2arc(&(src[x].buffer[z]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); + if(r >= 0) { + if((e.ul>>32) != v || e.v != w) continue; + dt = e.ol; if(is_contain) (*is_contain) = 0; + break; + } else if(r == MA_HT_TCONT) {///tn is contained in qn + // if(qn == 543 && tn == 548) { + // fprintf(stderr, "[M::%s]\t%.*s\t->%.*s\tr::%d\tsrc::%c\tqry::%c\n", __func__, (int)Get_NAME_LENGTH(R_INF, qn), + // Get_NAME(R_INF, qn), (int)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), r, + // "+-"[src[x].buffer[z].rev], "+-"[((uint32_t)(v^w))]); + // } + if((src[x].buffer[z].rev == (((uint32_t)(v^w))&1)) && (tn == (w>>1))) { + dt = Get_qe(src[x].buffer[z]) - Get_qs(src[x].buffer[z]); + if(dt < Get_te(src[x].buffer[z]) - Get_ts(src[x].buffer[z])) { + dt = Get_te(src[x].buffer[z]) - Get_ts(src[x].buffer[z]); + } + if(is_contain) (*is_contain) = 1; + // fprintf(stderr, "[M::%s]\t%.*s\t->%.*s\tdt::%ld\n", __func__, (int)Get_NAME_LENGTH(R_INF, qn), + // Get_NAME(R_INF, qn), (int)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), dt); + break; + } + } + } + + if(dt < 0) return 0; + dif = (dq>dt? dq-dt:dt-dq); + mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; + // if((v>>1) == 1163 && (w>>1) == 1168) fprintf(stderr, ">>>>>>dis_q:%ld, dis_t:%ld, dif:%ld, mm:%ld\n", dis_q, dis_t, dif, mm); + if(dif <= mm) return 1; + return 0; +} + +int64_t gl_rchain_lin(overlap_region_alloc* ol, kv_ul_ov_t *res, ul_ov_t *ex, kv_rtrace_t *trace, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, bit_extz_t *exz, +int64_t trans_sc, All_reads *ridx, char* qstr, UC_Read *tu, int64_t rid, double e_rate, int64_t need_srt) +{ + if(res->n == 0) return 0; + uint32_t li_v, lj_v, rev_n; int32_t *f, *c_n, *c_sc; int64_t *p, *t, res_n = res->n, st, max_ii, max, err; + int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, qo, n_skip, end_j, plus; ul_ov_t *li, *lj, rev_t; rtrace_iter tc; + resize_Chain_Data(dp, res_n, NULL); + t = dp->tmp; f = dp->score; p = dp->pre; c_n = dp->occ; c_sc = dp->self_length; + if(need_srt) { + radix_sort_ul_ov_srt_qe(res->a, res->a + res_n); + for (i = 1, j = 0; i <= res_n; i++) { + if (i == res_n || res->a[i].qe != res->a[j].qe) { + if(i-j>1) radix_sort_ul_ov_srt_qs(res->a+j, res->a+i); + j = i; + } + } + } + + memset(t, 0, (res_n*sizeof((*t)))); + for (i = st = plus = 0, max_ii = -1; i < res_n; ++i) { + li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; + mm_ovlp = max_ovlp_src(uopt, li_v^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(i, res->a, x+G_CHAIN_INDEL); + csc = li->qe - li->qs; csc -= (((int64_t)li->sec)*trans_sc); + mm_sc = csc; mm_idx = -1; + n_skip = 0; end_j = -1; tc.k = INT32_MAX; + if ((x-st) > max_iter) st = x-max_iter; + // fprintf(stderr, "[M::%s] i::%ld, iq::[%u, %u)\n", __func__, i, li->qs, li->qe); + for (j = x; j >= st; --j) { // collect potential destination vertices + lj = &(res->a[j]); lj_v = (lj->tn<<1)|lj->rev; + if(lj->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore + if(lj->qs >= li->qs) continue;///no contain + qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) + if(li_v != lj_v && get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, NULL)) { + // fprintf(stderr, "[M::%s] j::%ld, jq::[%u, %u)\n", __func__, j, lj->qs, lj->qe); + err = get_rid_backward_cigar_err(&tc, li, trace, NULL, uref, qstr, tu, ol, NULL, exz, e_rate, lj->qe); + sc = f[j] + (li->qe - lj->qe) - (err*trans_sc); + if(sc > mm_sc) { + mm_sc = sc, mm_idx = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + } + + end_j = j; + if (max_ii < 0 || (res->a[i].qe>(res->a[max_ii].qe+max_dis))) {//too long + max = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && (res->a[i].qe<=(max_dis+res->a[j].qe)); --j) { + if (max < f[j]) { + max = f[j], max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + lj = &(res->a[max_ii]); lj_v = (lj->tn<<1)|lj->rev; + if(lj->qe > li->qs && lj->qs < li->qs) { + qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) + if(li_v != lj_v && get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, NULL)) { + ///as max_ii < end_j, get_rid_backward_cigar_err still works + // fprintf(stderr, "[M::%s] max_ii::%ld, max_ii::[%u, %u)\n", __func__, max_ii, lj->qs, lj->qe); + err = get_rid_backward_cigar_err(&tc, li, trace, NULL, uref, qstr, tu, ol, NULL, exz, e_rate, lj->qe); + sc = f[max_ii] + (li->qe - lj->qe) - (err*trans_sc); + if(sc > mm_sc) { + mm_sc = sc; mm_idx = max_ii; + } + } + } + } + if(mm_sc < 0) { + mm_sc = csc; mm_idx = -1; + } + f[i] = mm_sc; p[i] = mm_idx; + if ((max_ii < 0) || ((res->a[i].qe<=max_dis+res->a[max_ii].qe) && (f[max_ii]tn+1, i, res_n, csc, f[i], p[i], li->qs, li->qe); + } + + for (i = 0; i < res_n; ++i) {///make all f[] positive + f[i] -= plus; t[i] = ((uint64_t)f[i])<<32; t[i] += (i<<1); + } + + int64_t n_v, n_u, n_v0; + radix_sort_gfa64i(t, t + res_n); plus = 0; + for (k = res_n-1, n_v = n_u = 0; k >= 0; --k) { + n_v0 = n_v; + for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { + ex[n_v++] = res->a[i]; t[i] |= 1; i = p[i]; + } + if(n_v0 == n_v) continue; + sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); + // fprintf(stderr, "[M::%s::] n_v::%ld, n_v0::%ld, t[k]::%ld, sc::%ld\n", + // __func__, n_v, n_v0, t[k]>>32, sc); + c_n[n_u] = n_v-n_v0; c_sc[n_u] = sc; n_u++; if(sc < plus) plus = sc; + } + // fprintf(stderr, "---[M::%s] n_u:%ld, n_v:%ld\n", __func__, n_u, n_v); + for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { + n_v0 = n_v; n_v += c_n[k]; + res->a[k].qn = c_sc[k]-plus;//score + res->a[k].ts = n_v0; res->a[k].te = n_v;///idx + // fprintf(stderr, "[M::%s] k:%ld, c_sc:%d\n", __func__, k, c_sc[k]); + + rev_n = c_n[k]>>1; + ///we need to consider contained reads; so determining qs is not such easy + res->a[k].qs = (uint32_t)-1; res->a[k].qe = ex[n_v0].qe; + for (i = 0; i < rev_n; i++) { + rev_t = ex[n_v0+i]; ex[n_v0+i] = ex[n_v-i-1]; ex[n_v-i-1] = rev_t; + + if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; + if(res->a[k].qs > ex[n_v-i-1].qs) res->a[k].qs = ex[n_v-i-1].qs; + ex[n_v0+i].sec = ex[n_v-i-1].sec = SEC_MODE; + } + if(c_n[k]&1) { + if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; + ex[n_v0+i].sec = SEC_MODE; + } + } + res->n = n_u; + radix_sort_ul_ov_srt_qn(res->a, res->a + res->n);//sort by score + // if(res->n > 0) { + // fprintf(stderr, "[M::%s::rid->%ld] qlen::%ld, q::[%u, %u), sc::%u\n", + // __func__, rid, qlen, res->a[res->n-1].qs, res->a[res->n-1].qe, res->a[res->n-1].qn); + // } + return n_v; +} + + +void collapse_contain(ul_ov_t *a, int64_t a_n, int64_t i, int64_t *mm_idx, int64_t *mm_sc, int64_t *p, int32_t *s, int64_t min_s) +{ + if((*mm_idx) < 0) return; + +} + +#define rch_connect(x, i) ((((x)>>2)==(i))&&(((x)&3)!=3)) + +int64_t connect_detect(ul_ov_t *a, int64_t a_n, int64_t ai, int64_t aj, All_reads *ridx, int32_t *rch, +const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff, int64_t *p, int32_t *f, rtrace_iter *tc, +kv_rtrace_t *trace, char* qstr, UC_Read *tu, overlap_region_alloc* ol, bit_extz_t *exz, double e_rate, +int64_t trans_sc, uint32_t *is_fc) +{ + ul_ov_t *li = &(a[ai]), *lj = &(a[aj]), *lk; + uint32_t li_v, lj_v, lk_v, lqs = INT32_MAX; int64_t qo, is_c, ak, afk, err, sc = INT32_MIN, wsc; + li_v = (li->tn<<1)|li->rev; lj_v = (lj->tn<<1)|lj->rev; (*is_fc) = 0; + if(li_v == lj_v) return INT32_MIN; + //even this pair has a overlap, its length will be very small; just ignore + if(lj->qe <= li->qs) return INT32_MIN; + // if(lj->qs >= li->qs) continue;///no contain + + if((rch[aj]>>2) != ai) { + qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) + rch[aj] = (ai<<2); rch[aj] += 3; + // fprintf(stderr, "[j::%ld] (id::%u) %.*s\tqo::%ld\n", aj, lj->tn, + // (int)Get_NAME_LENGTH(R_INF, a[aj].tn), Get_NAME(R_INF, a[aj].tn), qo); + if(get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff, qo, &is_c)) { + rch[aj] = (ai<<2); rch[aj] += is_c; if(is_c) lj->el = 0; + } else { + // if(li->tn == 20171) { + // fprintf(stderr, "[j::%ld] %.*s\tconnect::0\n", aj, + // (int)Get_NAME_LENGTH(R_INF, a[aj].tn), Get_NAME(R_INF, a[aj].tn)); + // } + return INT32_MIN; + } + } + // if(li->tn == 20171) { + // fprintf(stderr, "[j::%ld] %.*s\tconnect::%u\n", aj, + // (int)Get_NAME_LENGTH(R_INF, a[aj].tn), Get_NAME(R_INF, a[aj].tn), rch_connect(rch[aj], ai)); + // } + + if(!rch_connect(rch[aj], ai)) return INT32_MIN; + is_c = rch[aj]&1; ak = afk = aj; + // fprintf(stderr, "+[j::%ld] %.*s\tis_c::%ld\n", aj, + // (int)Get_NAME_LENGTH(R_INF, a[aj].tn), Get_NAME(R_INF, a[aj].tn), is_c); + if(is_c) { + lqs = a[aj].qs; + for (ak = p[aj]; ak >= 0; ak = p[ak]) { + if((rch[ak]>>2) != ai) { + rch[ak] = (ak<<2); rch[ak] += 3; + lk = &(a[ak]); lk_v = (lk->tn<<1)|lk->rev; + if(li_v == lk_v) break; + if(lk->qe <= li->qs) break; + qo = infer_rovlp(li, lk, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) + if(!get_ecov_contain_adv(uref, uopt, li_v^1, lk_v^1, bw, diff, qo, &is_c)) break; + rch[ak] = (ai<<2); rch[ak] += is_c; + } + if(!rch_connect(rch[ak], ai)) break; + if(lqs > a[ak].qs) lqs = a[ak].qs; + is_c = rch[ak]&1; if(is_c == 0) break; + } + + afk = ak; + if((ak >= 0) && (!rch_connect(rch[ak], ai))) return INT32_MIN;///go to a disconnected node + // if(ak >= 0) { + // if(!rch_connect(rch[ak], ai)) return INT32_MIN;///go to a disconnected node + // for (ak = p[ak]; ak >= 0 && a[afk].qe <= a[ak].qe + 256; ak = p[ak]) { + // if((rch[ak]>>2) != ai) { + // rch[ak] = (ak<<2); rch[ak] += 3; + // lk = &(a[ak]); lk_v = (lk->tn<<1)|lk->rev; + // if(li_v == lk_v) return INT32_MIN; + // if(lk->qe <= li->qs) return INT32_MIN; + // qo = infer_rovlp(li, lk, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) + // if(!get_ecov_contain_adv(uref, uopt, li_v^1, lk_v^1, bw, diff, qo, &is_c)) return INT32_MIN; + // rch[ak] = (ai<<2); rch[ak] += is_c; + // } + // if(!rch_connect(rch[ak], ai)) return INT32_MIN; + // } + // } + } + // if(li->tn == 6317) { + // fprintf(stderr, "[M::%s::] [j::%ld] %.*s\tis_c::%ld\tafk::%ld\tlqs::%u\n", __func__, aj, + // (int)Get_NAME_LENGTH(R_INF, a[aj].tn), Get_NAME(R_INF, a[aj].tn), is_c, afk, lqs); + // } + ///afk >=0: reach to one non-contained read, lqs should <= li->qs + ///afk < 0: all reads are contained, lqs >= li->qs + if((afk >= 0) || (lqs <= li->qs)) { + lj = &(a[aj]); + err = get_rid_backward_cigar_err(tc, li, trace, NULL, uref, qstr, tu, ol, NULL, exz, e_rate, lj->qe); + sc = f[aj] + (li->qe - lj->qe) - (err*trans_sc); (*is_fc) = 0; + if(afk < 0) { + wsc = li->qe - li->qs; wsc -= (((int64_t)li->sec)*trans_sc); + if(sc < wsc) sc = wsc; + } + } else { + sc = li->qe - li->qs; sc -= (((int64_t)li->sec)*trans_sc); (*is_fc) = 1; + } + return sc; +} + + +int64_t max_ovlp_src_contain(const ug_opt_t *uopt, uint32_t v) +{ + ma_hit_t_alloc* src = uopt->sources; + int64_t min_ovlp = uopt->min_ovlp, max_hang = uopt->max_hang; + uint32_t i, qn, tn, o = 0, x = v>>1, dt; asg_arc_t e; int32_t r = 1; + + for (i = 0; i < src[x].length; i++) { + qn = Get_qn(src[x].buffer[i]); tn = Get_tn(src[x].buffer[i]); + r = ma_hit2arc(&(src[x].buffer[i]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), + max_hang, asm_opt.max_hang_rate, min_ovlp, &e); + // if(qn == 20171 && tn == 20172) { + // fprintf(stderr, "[r::%d]\t%.*s\t%c\tq::[%u, %u)\t%.*s\tt::[%u, %u)\n", r, + // (int)Get_NAME_LENGTH(R_INF, qn), Get_NAME(R_INF, qn), "+-"[src[x].buffer[i].rev], + // Get_qs(src[x].buffer[i]), Get_qe(src[x].buffer[i]), + // (int)Get_NAME_LENGTH(R_INF, tn), Get_NAME(R_INF, tn), + // Get_ts(src[x].buffer[i]), Get_te(src[x].buffer[i])); + // } + if(r >= 0) { + if((e.ul>>32) != v) continue; + if(o < e.ol) o = e.ol; + } else if(r == MA_HT_TCONT) {///tn is contained in qn + if(v&1) dt = Get_qe(src[x].buffer[i]); + else dt = Get_READ_LENGTH(R_INF, qn) - Get_qs(src[x].buffer[i]); + if(o < dt) o = dt; + } + } + + return o; +} + +int64_t quick_rechain_sc(ul_ov_t *a, overlap_region_alloc* ol, const ul_idx_t *uref, const ug_opt_t *uopt, +int64_t bw, double diff, All_reads *ridx, kv_rtrace_t *trace, char* qstr, UC_Read *tu, rtrace_iter *tc, +double e_rate, bit_extz_t *exz, int64_t trans_sc, int32_t *f, int64_t ai, int64_t aj) +{ + ul_ov_t *li = &(a[ai]), *lj = &(a[aj]); + uint32_t li_v, lj_v; int64_t qo, is_c, err, sc = INT32_MIN; + li_v = (li->tn<<1)|li->rev; lj_v = (lj->tn<<1)|lj->rev; + if(li_v == lj_v) return INT32_MIN; + if(lj->qe <= li->qs) return INT32_MIN; + if(lj->qs > li->qs) return INT32_MIN; + qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); + if(get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff, qo, &is_c)) { + if(is_c == 0) { + err = get_rid_backward_cigar_err(tc, li, trace, NULL, uref, qstr, tu, ol, NULL, exz, e_rate, lj->qe); + sc = f[aj] + (li->qe - lj->qe) - (err*trans_sc); + } + } + return sc; +} + +uint32_t if_qchain_cnn(const ul_idx_t *uref, const ug_opt_t *uopt, All_reads *ridx, int64_t bw, double diff, ul_ov_t *li, ul_ov_t *lj, int64_t *is_c, int64_t *arc_len); +void quick_rechain_propagate_transitive_reduction(const ul_idx_t *uref, const ug_opt_t *uopt, All_reads *ridx, int64_t bw, double diff, +ul_ov_t *a, int32_t a_n, int64_t ai, int32_t *rch, int32_t *f, int64_t *p, int32_t *c_n, int64_t *t, int64_t *mm_sc, +int64_t *mm_idx, int64_t *mm_n) +{ + if((*mm_idx) < 0) return; + int64_t mm_idx0 = (*mm_idx), j, k, is_c, sn; + for (j = mm_idx0 + 1; j < a_n; j++) { + t[j] = mm_idx0 - 1; + if(p[j] < 0) continue; + // if(a[ai].tn == 23989) { + // fprintf(stderr, "+chain[i::%ld] (id::%u)%.*s\t%c\tj::%ld\t%.*s\tconnect::%u\n", ai, a[ai].tn, + // (int)Get_NAME_LENGTH(R_INF, a[ai].tn), Get_NAME(R_INF, a[ai].tn), + // "+-"[a[ai].rev], j, (int)Get_NAME_LENGTH(R_INF, a[ai].tn), Get_NAME(R_INF, a[ai].tn), rch_connect(rch[j], ai)); + // } + if((rch[j]>>2) != ai) { + rch[j] = (ai<<2); rch[j] += 3; + if((a[j].el) && (if_qchain_cnn(uref, uopt, ridx, bw, diff, &(a[ai]), &(a[j]), &is_c, NULL))) { + rch[j] = (ai<<2); rch[j] += is_c; + } + } + // if(a[ai].tn == 23989) { + // fprintf(stderr, "-chain[i::%ld] (id::%u)%.*s\t%c\tj::%ld\t%.*s\tconnect::%u\n", ai, a[ai].tn, + // (int)Get_NAME_LENGTH(R_INF, a[ai].tn), Get_NAME(R_INF, a[ai].tn), + // "+-"[a[ai].rev], j, (int)Get_NAME_LENGTH(R_INF, a[ai].tn), Get_NAME(R_INF, a[ai].tn), rch_connect(rch[j], ai)); + // } + if(!rch_connect(rch[j], ai)) continue; + for (k = p[j]; k >= 0 && k > mm_idx0; k = p[k]) { + if(t[k] == mm_idx0) { + k = mm_idx0; break; + } else { + k = mm_idx0-1; break; + } + } + if (k != mm_idx0) continue; + t[j] = mm_idx0;//a[j] could reach mm_idx0; + if(p[j] != k) { + if(!(if_qchain_cnn(uref, uopt, ridx, bw, diff, &(a[j]), &(a[k]), &is_c, NULL))) continue; + } + sn = c_n[j] + 1; + if(sn >= (*mm_n)) {//must >= + (*mm_n) = sn; (*mm_idx) = j; + } + } + return; +} + + + +int64_t quick_rechain(overlap_region_alloc* ol, ul_ov_t *a, int64_t a_n, kv_rtrace_t *trace, const ul_idx_t *uref, const ug_opt_t *uopt, +int64_t bw, double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, +bit_extz_t *exz, int64_t trans_sc, All_reads *ridx, char* qstr, UC_Read *tu, double e_rate, +int32_t *f, int32_t *c_n, int32_t *c_sc, int32_t *rch, int64_t *p, int64_t *t) +{ + int64_t mm_ovlp, x, i, j, sc, csc, mm_sc, mm_idx, mm_n, sn, n_skip, end_j; + ul_ov_t *li, *lj; rtrace_iter tc; int64_t st, max_ii, max, max_n; uint32_t li_v; + memset(t, 0, (a_n*sizeof((*t)))); + + for (i = st = 0, max_ii = -1; i < a_n; ++i) { + li = &(a[i]); li_v = (li->tn<<1)|li->rev; rch[i] = INT32_MAX; + csc = li->qe - li->qs; csc -= (((int64_t)li->sec)*trans_sc); + mm_sc = INT32_MIN; mm_idx = -1; mm_n = 0; + n_skip = 0; end_j = -1; tc.k = INT32_MAX; + // if((i>=15) && (rch_connect(rch[15], 18))) { + // fprintf(stderr, ">>>[i::%ld] (id::%u)%.*s\t%c\trch[i]::%d\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), + // "+-"[a[i].rev], rch[15]); + // } + if(li->el) { + mm_ovlp = max_ovlp_src_contain(uopt, li_v^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(i, a, x+G_CHAIN_INDEL); + if ((x-st) > max_iter) st = x-max_iter; + for (j = x; j >= st; --j) { // collect potential destination vertices + lj = &(a[j]); + rch[j] = (i<<2); rch[j] += 3;//set it to unaviable + // if((i>=15) && (rch_connect(rch[15], 18))) { + // fprintf(stderr, "**j::%ld**[i::%ld] (id::%u)%.*s\t%c\trch[i]::%d\n", j, i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), + // "+-"[a[i].rev], rch[15]); + // } + if(!(lj->el)) continue; + if(lj->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore + if(lj->qs > li->qs) continue;///no contain + sc = quick_rechain_sc(a, ol, uref, uopt, bw, diff_ec_ul, ridx, trace, qstr, tu, + &tc, e_rate, exz, trans_sc, f, i, j); + if(sc == INT32_MIN) continue; + // if(li->tn == 23989) { + // fprintf(stderr, "*[i::%ld] (id::%u)%.*s\t%c\tj::%ld\t%.*s\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), + // "+-"[a[i].rev], j, (int)Get_NAME_LENGTH(R_INF, lj->tn), Get_NAME(R_INF, lj->tn)); + // } + rch[j] = (i<<2);//set it to aviable + sn = c_n[j] + 1; + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { + mm_sc = sc, mm_idx = j; mm_n = sn; + if (n_skip > 0) --n_skip; + } else if (t[j] == i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + // if((i>=15) && (rch_connect(rch[15], 18))) { + // fprintf(stderr, ">>>1[i::%ld] (id::%u)%.*s\t%c\trch[i]::%d\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), + // "+-"[a[i].rev], rch[15]); + // } + + end_j = j; + if (max_ii < 0 || (a[i].qe>(a[max_ii].qe+max_dis))) {//too long + max = INT32_MIN; max_n = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && (a[i].qe<=(max_dis+a[j].qe)); --j) { + if ((max < f[j]) || ((max == f[j]) && (max_n < c_n[j]))) { + max = f[j]; max_n = c_n[j]; max_ii = j; + } + } + } + // if((i>=15) && (rch_connect(rch[15], 18))) { + // fprintf(stderr, ">>>2[i::%ld] (id::%u)%.*s\t%c\trch[i]::%d\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), + // "+-"[a[i].rev], rch[15]); + // } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + lj = &(a[max_ii]); + if((lj->el) && (lj->qe > li->qs) && (lj->qs <= li->qs)) { + sc = quick_rechain_sc(a, ol, uref, uopt, bw, diff_ec_ul, ridx, trace, qstr, tu, + &tc, e_rate, exz, trans_sc, f, i, max_ii); + ///as max_ii < end_j, get_rid_backward_cigar_err still works + if(sc != INT32_MIN) { + sn = c_n[max_ii] + 1; + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { + mm_sc = sc; mm_idx = max_ii; mm_n = sn; + } + } + } + } + // if((i>=15) && (rch_connect(rch[15], 18))) { + // fprintf(stderr, ">>>3[i::%ld] (id::%u)%.*s\t%c\trch[i]::%d\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), + // "+-"[a[i].rev], rch[15]); + // } + sc = csc; sn = 1;///for i itself + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { + mm_sc = sc, mm_idx = -1; mm_n = sn; + } + + if(mm_sc < 0) { + mm_sc = csc; mm_idx = -1; mm_n = 1; + } + // if(li->tn == 23989) { + // fprintf(stderr, "+[i::%ld] (id::%u)%.*s\t%c\tj::%ld\t%.*s\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), + // "+-"[a[i].rev], mm_idx, mm_idx>=0?((int)Get_NAME_LENGTH(R_INF, a[mm_idx].tn)):(1), + // mm_idx>=0?(Get_NAME(R_INF, a[mm_idx].tn)):("*")); + // } + if(mm_idx >= 0) { + ///mo meed to update mm_sc and is_fc + quick_rechain_propagate_transitive_reduction(uref, uopt, ridx, bw, diff_ec_ul, a, x+1, i, rch, f, p, c_n, t, &mm_sc, &mm_idx, &mm_n); + } + // if(li->tn == 23989) { + // fprintf(stderr, "-[i::%ld] (id::%u)%.*s\t%c\tj::%ld\t%.*s\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), + // "+-"[a[i].rev], mm_idx, mm_idx>=0?((int)Get_NAME_LENGTH(R_INF, a[mm_idx].tn)):(1), + // mm_idx>=0?(Get_NAME(R_INF, a[mm_idx].tn)):("*")); + // } + } + f[i] = mm_sc; p[i] = mm_idx; c_n[i] = mm_n; + if ((max_ii < 0) || ((a[i].qe<=max_dis+a[max_ii].qe) && (f[max_ii]= 0) { + // fprintf(stderr, "i::%ld[M::%s] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", + // i, __func__, a[i].tn, (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), + // "+-"[a[i].rev], a[i].qs, a[i].qe, a[i].ts, a[i].te, !a[i].el); + t[cl++] = i; i = p[i]; + } + return cl; +} + +///ai is smaller than aj +int64_t push_trans_aln(const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, +All_reads *ridx, ul_ov_t *a, int64_t ai0, int64_t aj, int64_t *vis, int32_t *c_n) +{ + int64_t k, qo, is_c, ai = ai0, m = 0; ul_ov_t *li, *lj; uint32_t li_v, lj_v; + for (k = ai + 1; k < aj; k++) { + if(vis[k]&1) continue; + if(!(a[k].el)) continue; + // if(a[ai0].tn == 1053 || a[aj].tn == 1053) { + // fprintf(stderr, "**0**[k::%ld] ai0::%ld, ai::%ld, aj::%ld, (id::%u)%.*s\t%c\n", + // k, ai0, ai, aj, a[k].tn, (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), + // "+-"[a[k].rev]); + // } + lj = &(a[ai]); li = &(a[k]); + li_v = (li->tn<<1)|li->rev; + lj_v = (lj->tn<<1)|lj->rev; + if(lj->qe <= li->qs) continue;//even this pair has a overlap, its length will be very small; just ignore + if(lj->qs > li->qs) continue;///no contain + if(li_v == lj_v) continue; + qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) + if(!get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, &is_c)) continue; + // if(a[ai0].tn == 1053 || a[aj].tn == 1053) { + // fprintf(stderr, "**1**[k::%ld] ai0::%ld, ai::%ld, aj::%ld, (id::%u)%.*s\t%c\n", + // k, ai0, ai, aj, a[k].tn, (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), + // "+-"[a[k].rev]); + // } + if(is_c) continue; + // if(a[ai0].tn == 1053 || a[aj].tn == 1053) { + // fprintf(stderr, "**2**[k::%ld] ai0::%ld, ai::%ld, aj::%ld, (id::%u)%.*s\t%c\n", + // k, ai0, ai, aj, a[k].tn, (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), + // "+-"[a[k].rev]); + // } + + + lj = &(a[k]); li = &(a[aj]); + li_v = (li->tn<<1)|li->rev; + lj_v = (lj->tn<<1)|lj->rev; + if(lj->qe <= li->qs) continue;//even this pair has a overlap, its length will be very small; just ignore + if(lj->qs > li->qs) continue;///no contain + if(li_v == lj_v) continue; + qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) + // if(a[ai0].tn == 1053 || a[aj].tn == 1053) { + // fprintf(stderr, "**2-a**[k::%ld] ai0::%ld, ai::%ld, aj::%ld, (id::%u)%.*s\t%c, qo::%ld\n", + // k, ai0, ai, aj, a[k].tn, (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), + // "+-"[a[k].rev], qo); + // } + if(!get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, &is_c)) continue; + // if(a[ai0].tn == 1053 || a[aj].tn == 1053) { + // fprintf(stderr, "**3**[k::%ld] ai0::%ld, ai::%ld, aj::%ld, (id::%u)%.*s\t%c\n", + // k, ai0, ai, aj, a[k].tn, (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), + // "+-"[a[k].rev]); + // } + if(is_c) continue; + // if(a[ai0].tn == 1053 || a[aj].tn == 1053) + // { + // fprintf(stderr, "**4**[k::%ld] ai0::%ld, ai::%ld, aj::%ld, (id::%u)%.*s\t%c\n", + // k, ai0, ai, aj, a[k].tn, (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), + // "+-"[a[k].rev]); + // } + + // res[m] = a[k]; vis[k] |= 1; + // if(res[m].qs < idx->qs) idx->qs = res[m].qs; + // if(res[m].qe > idx->qe) idx->qe = res[m].qe; + // if(res[m].tn == 1032) { + // fprintf(stderr, "**5**[k::%ld] ai0::%ld, ai::%ld, aj::%ld, (id::%u)%.*s\t%c\n", + // k, ai0, ai, aj, a[k].tn, (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), + // "+-"[a[k].rev]); + // } + // m++; ai = k; + c_n[m++] = k; vis[k] |= 1; ai = k; + } + return m; +} + +int64_t flat_contain_adv(overlap_region_alloc* ol, All_reads *ridx, const ul_idx_t *uref, +const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, +int64_t max_dis, bit_extz_t *exz, int64_t trans_sc, char* qstr, UC_Read *tu, double e_rate, +kv_rtrace_t *trace, ul_ov_t *a, int64_t a_n, int32_t *f0, int32_t *c_n0, int32_t *c_sc0, +int32_t *rch0, int32_t *ssc0, int64_t *p0, int64_t *t0, ul_ov_t *ori_a, uint64_t *flag, +uint64_t rechain_w, int64_t *vis, ul_ov_t *idx) +{ + if(a_n <= 0) return 0; + int32_t *t = f0, *c_n = c_n0; int64_t *p = p0, *f = t0, rech = 0, nf = 0, ori_i, ori_j, ncl; uint64_t qs; + int64_t mm_ovlp, x, i, j, st, max_ii, mm_sc, mm_n, mm_idx, n_skip, end_j, qo, sc, sn, is_c, cl, csc, cl1; + uint32_t li_v, lj_v; ul_ov_t *li, *lj; int64_t max, max_n, tot_sc = INT32_MIN, tot_n = INT32_MIN, tot_i = -1; + for (i = 1, j = 0; i <= a_n; i++) { + if (i == a_n || a[i].qe != a[j].qe) { + if(i - j > 1) radix_sort_ul_ov_srt_qs(a+j, a+i); + j = i; + } + } + // fprintf(stderr, "\n[M::%s::] sc::%u\n", __func__, idx->qn); + memset(t, 0, (a_n*sizeof((*t)))); + for (i = st = 0, max_ii = -1; i < a_n; ++i) { + li = &(a[i]); li_v = (li->tn<<1)|li->rev; + flag[i] = li->sec; li->sec = ori_a[li->sec>>1].sec; + + csc = ((li->el)?(li->qe-li->qs):(0)); + mm_sc = csc; mm_n = 1; mm_idx = -1; n_skip = 0; end_j = -1; + if(flag[i]&1) {//low prority + rech++; f[i] = INT32_MIN; p[i] = mm_idx; c_n[i] = 0; continue; + } + // fprintf(stderr, "[i::%ld] (id::%u)\n", i, li->tn); + // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), + // "+-"[a[i].rev], a[i].qs, a[i].qe, a[i].ts, a[i].te, !a[i].el); + mm_ovlp = max_ovlp_src(uopt, li_v^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(i, a, x+G_CHAIN_INDEL); + + if ((x-st) > max_iter) st = x-max_iter; + for (j = x; j >= st; --j) { // collect potential destination vertices + lj = &(a[j]); lj_v = (lj->tn<<1)|lj->rev; + if(flag[j]&1) continue;//low prority + if(lj->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore + // if(lj->qs >= li->qs) continue;///no contain + if(lj->qs > li->qs) continue;///no contain, must be > instad of >= + qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) + if(li_v != lj_v && get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, &is_c)) { + if(is_c == 0) { + sc = f[j] + csc; sn = c_n[j] + 1; + // if(li->tn == 6312) { + // fprintf(stderr, "***[i::%ld] (id::%u)%.*s\t%c\tj::%ld\t%.*s\tsc::%ld\tsn::%ld\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), + // "+-"[a[i].rev], j, (int)Get_NAME_LENGTH(R_INF, a[j].tn), Get_NAME(R_INF, a[j].tn), + // sc, sn); + // } + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { + mm_sc = sc, mm_idx = j; mm_n = sn; + if (n_skip > 0) --n_skip; + } else if (t[j] == i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + } + } + + end_j = j; + if (max_ii < 0 || ((a[i].qe) > (a[max_ii].qe+max_dis))) {//too long + max = INT32_MIN; max_n = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && (a[i].qe<=(max_dis+a[j].qe)); --j) { + if ((max < f[j]) || ((max == f[j]) && (max_n < c_n[j]))) { + max = f[j]; max_n = c_n[j]; max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + lj = &(a[max_ii]); lj_v = (lj->tn<<1)|lj->rev; + if((lj->qe > li->qs) && (lj->qs <= li->qs) && (!(flag[max_ii]&1))) { + qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) + if(li_v != lj_v && get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, &is_c)) { + if(is_c == 0) { + sc = f[max_ii] + csc; sn = c_n[max_ii] + 1; + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { + mm_sc = sc; mm_idx = max_ii; mm_n = sn; + } + } + } + } + } + + f[i] = mm_sc; p[i] = mm_idx; c_n[i] = mm_n; + if ((max_ii < 0) || ((a[i].qe<=max_dis+a[max_ii].qe) && (f[max_ii]tn); + cl = 0; i = tot_i; t = NULL; + while (i >= 0) { + flag[cl] |= (((uint64_t)i)<<32); + i = p[i]; cl++; + } + // fprintf(stderr, "+++[i::%ld] (cl::%ld)\n", i, cl); + + st = flag[cl-1]>>32; qs = a[st].qs; cl1 = 0; + // fprintf(stderr, "[M::%s] qs::%lu\trechain_w::%lu\trech::%ld\tcl::%ld\n", + // __func__, qs, rechain_w, rech, cl); + if((qs <= rechain_w) && (rech > 0)) { + for (i = nf = 0; i < cl; i++) { + st = flag[cl-i-1]>>32; + if(a[st].el) break; + if((a[st].ts == 0) && (a[st].te == Get_READ_LENGTH(R_INF, a[st].tn))) nf++; + } + if(i < cl && a[st].qs > qs && nf > 0) { + + cl1 = quick_rechain(ol, a, st+1, trace, uref, uopt, bw, diff_ec_ul, qlen, max_skip, max_iter, max_dis, + exz, trans_sc, ridx, qstr, tu, e_rate, f0, c_n0, c_sc0, rch0, p0, t0); + // fprintf(stderr, "st::%ld\tcl1::%ld[M::%s]\t(id::%u)\t%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", + // st, cl1, __func__, a[st].tn, (int)Get_NAME_LENGTH(R_INF, a[st].tn), Get_NAME(R_INF, a[st].tn), + // "+-"[a[st].rev], a[st].qs, a[st].qe, a[st].ts, a[st].te, !a[st].el); + + // fprintf(stderr, "i::%ld\t[M::%s]\t(id::%u)\t%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", + // i, __func__, a[t0[cl1-1]].tn, (int)Get_NAME_LENGTH(R_INF, a[t0[cl1-1]].tn), + // Get_NAME(R_INF, a[t0[cl1-1]].tn), "+-"[a[t0[cl1-1]].rev], a[t0[cl1-1]].qs, a[t0[cl1-1]].qe, + // a[t0[cl1-1]].ts, a[t0[cl1-1]].te, !a[t0[cl1-1]].el); + + if(cl1 > 0 && a[t0[cl1-1]].qs <= qs) { + cl = cl-i-1; assert(st == t0[0]); + for (i = 0; i < cl1; i++) { + flag[cl] <<= 32; flag[cl] >>= 32; + flag[cl] |= ((uint64_t)t0[i])<<32; cl++; + } + } + } + } + // fprintf(stderr, "---[i::%ld] (cl::%ld)\n", i, cl); + for (i = 0; i < cl; i++) { + // fprintf(stderr, "[i::%ld] flag[cl-i-1]>>32::%lu\n", i, flag[cl-i-1]>>32); + t0[i] = flag[cl-i-1]>>32; + vis[((uint32_t)flag[t0[i]])>>1] |= 1;///set as used + // fprintf(stderr, "[i::%ld]\t%.*s\traw_i::%u\n", i, + // (int)Get_NAME_LENGTH(R_INF, a[t0[i]].tn), Get_NAME(R_INF, a[t0[i]].tn), ((uint32_t)flag[t0[i]])>>1); + // flag[cl-i-1] = (uint32_t)flag[cl-i-1]; + } + + i = 0; ncl = 0; + if(cl1 > 1) { + // for (i = 0; i < cl; i++) vis[((uint32_t)flag[t0[i]])>>1] |= 1;///set as used + for (i = 0; i < cl1; i++) { + if(flag[t0[i]]&1) flag[t0[i]]-=1; + vis[((uint32_t)flag[t0[i]])>>1] |= 1; + c_n[ncl++] = ((uint32_t)flag[t0[i]])>>1; + + // a[ncl] = a[t0[i]]; + // if(a[ncl].qs < idx->qs) idx->qs = a[ncl].qs; + // if(a[ncl].qe > idx->qe) idx->qe = a[ncl].qe; + // fprintf(stderr, "[ncl::%ld]\t%.*s\n", ncl, + // (int)Get_NAME_LENGTH(R_INF, a[ncl].tn), Get_NAME(R_INF, a[ncl].tn)); + // ncl++; + + if(i < cl1 - 1) { + ori_i = ((uint32_t)flag[t0[i]])>>1; + ori_j = ((uint32_t)flag[t0[i+1]])>>1; + ncl += push_trans_aln(uref, uopt, bw, diff_ec_ul, ridx, ori_a, ori_i, ori_j, vis, c_n+ncl); + } + } + } + + + for (; i < cl; i++) { + ///t0[i] -> idx of a; (uint32_t)flag[t0[i]] -> idx of ori_a + if(flag[t0[i]]&1) flag[t0[i]]-=1; + vis[((uint32_t)flag[t0[i]])>>1] |= 1; + c_n[ncl++] = ((uint32_t)flag[t0[i]])>>1; + // a[ncl] = a[t0[i]]; + // if(a[ncl].qs < idx->qs) idx->qs = a[ncl].qs; + // if(a[ncl].qe > idx->qe) idx->qe = a[ncl].qe; + // fprintf(stderr, "[ncl::%ld]\t%.*s\n", ncl, + // (int)Get_NAME_LENGTH(R_INF, a[ncl].tn), Get_NAME(R_INF, a[ncl].tn)); + // ncl++; + // fprintf(stderr, "[M::%s] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", + // __func__, a[i].tn, (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), + // "+-"[a[i].rev], a[i].qs, a[i].qe, a[i].ts, a[i].te, !a[i].el); + } + assert(ncl >= cl); + if(ncl <= 0) return ncl; + + idx->qs = ori_a[c_n[0]].qs; + idx->qe = ori_a[c_n[0]].qe; + for (i = 0; i < ncl; i++) { + a[i] = ori_a[c_n[i]]; + if(a[i].qs < idx->qs) idx->qs = a[i].qs; + if(a[i].qe > idx->qe) idx->qe = a[i].qe; + } + return ncl; +} + + +int64_t flat_contain(All_reads *ridx, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, +ul_ov_t *a, int64_t a_n, int32_t *t, int32_t *c_n, int64_t *p, int64_t *f, ul_ov_t *idx) +{ + if(a_n <= 0) return 0; + int64_t mm_ovlp, x, i, j, st, max_ii, mm_sc, mm_n, mm_idx, n_skip, end_j, qo, sc, sn, is_c, cl, csc; + uint32_t li_v, lj_v; ul_ov_t *li, *lj; int64_t max, max_n, tot_sc = INT32_MIN, tot_n = INT32_MIN, tot_i = -1; + for (i = 1, j = 0; i <= a_n; i++) { + if (i == a_n || a[i].qe != a[j].qe) { + if(i - j > 1) radix_sort_ul_ov_srt_qs(a+j, a+i); + j = i; + } + } + // fprintf(stderr, "\n[M::%s::] sc::%u\n", __func__, idx->qn); + memset(t, 0, (a_n*sizeof((*t)))); + for (i = st = 0, max_ii = -1; i < a_n; ++i) { + li = &(a[i]); li_v = (li->tn<<1)|li->rev; + // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), + // "+-"[a[i].rev], a[i].qs, a[i].qe, a[i].ts, a[i].te, !a[i].el); + mm_ovlp = max_ovlp_src(uopt, li_v^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(i, a, x+G_CHAIN_INDEL); csc = ((li->el)?(li->qe-li->qs):(0)); + mm_sc = csc; mm_n = 1; mm_idx = -1; n_skip = 0; end_j = -1; + if ((x-st) > max_iter) st = x-max_iter; + for (j = x; j >= st; --j) { // collect potential destination vertices + lj = &(a[j]); lj_v = (lj->tn<<1)|lj->rev; + if(lj->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore + // if(lj->qs >= li->qs) continue;///no contain + qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) + if(li_v != lj_v && get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, &is_c)) { + if(is_c == 0) { + sc = f[j] + csc; sn = c_n[j] + 1; + // if(li->tn == 20171) { + // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tj::%ld\tsc::%ld\tsn::%ld\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, a[i].tn), Get_NAME(R_INF, a[i].tn), + // "+-"[a[i].rev], j, sc, sn); + // } + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { + mm_sc = sc, mm_idx = j; mm_n = sn; + if (n_skip > 0) --n_skip; + } else if (t[j] == i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + } + } + + end_j = j; + if (max_ii < 0 || ((a[i].qe) > (a[max_ii].qe+max_dis))) {//too long + max = INT32_MIN; max_n = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && (a[i].qe<=(max_dis+a[j].qe)); --j) { + if ((max < f[j]) || ((max == f[j]) && (max_n < c_n[j]))) { + max = f[j]; max_n = c_n[j]; max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + lj = &(a[max_ii]); lj_v = (lj->tn<<1)|lj->rev; + if(lj->qe > li->qs && lj->qs < li->qs) { + qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) + if(li_v != lj_v && get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff_ec_ul, qo, &is_c)) { + if(is_c == 0) { + sc = f[max_ii] + csc; sn = c_n[max_ii] + 1; + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { + mm_sc = sc; mm_idx = max_ii; mm_n = sn; + } + } + } + } + } + + f[i] = mm_sc; p[i] = mm_idx; c_n[i] = mm_n; + if ((max_ii < 0) || ((a[i].qe<=max_dis+a[max_ii].qe) && (f[max_ii]= 0) { + t[cl++] = i; i = p[i]; + } + idx->qs = a[t[cl-1]].qs; idx->qe = a[t[cl-1]].qe; + for (i = 0; i < cl; i++) { + a[i] = a[t[cl-i-1]]; + if(a[i].qs < idx->qs) idx->qs = a[i].qs; + if(a[i].qe > idx->qe) idx->qe = a[i].qe; + } + return cl; +} + + +///li is the suffix +uint32_t if_qchain_cnn(const ul_idx_t *uref, const ug_opt_t *uopt, All_reads *ridx, int64_t bw, double diff, ul_ov_t *li, ul_ov_t *lj, int64_t *is_c, int64_t *arc_len) +{ + uint32_t li_v = (li->tn<<1)|li->rev, lj_v = (lj->tn<<1)|lj->rev; int64_t qo; + if((li_v == lj_v) || (lj->qe <= li->qs)) return 0; + qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) + if(get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, bw, diff, qo, is_c)) return 1; + return 0; +} + +void propagate_transitive_reduction(const ul_idx_t *uref, const ug_opt_t *uopt, All_reads *ridx, int64_t bw, double diff, +ul_ov_t *a, int32_t a_n, int64_t ai, int32_t *rch, int32_t *f, int64_t *p, int32_t *c_n, int64_t *t, int64_t *mm_sc, +int64_t *mm_idx, int64_t *mm_n) +{ + if((*mm_idx) < 0) return; + int64_t mm_idx0 = (*mm_idx), j, k, is_c, sn; + for (j = mm_idx0 + 1; j < a_n; j++) { + t[j] = mm_idx0 - 1; + if(p[j] < 0) continue; + if((rch[j]>>2) != ai) { + rch[j] = (ai<<2); rch[j] += 3; + if(if_qchain_cnn(uref, uopt, ridx, bw, diff, &(a[ai]), &(a[j]), &is_c, NULL)) { + rch[j] = (ai<<2); rch[j] += is_c; + } + } + if(!rch_connect(rch[j], ai)) continue; + for (k = p[j]; k >= 0 && k > mm_idx0; k = p[k]) { + if(t[k] == mm_idx0) { + k = mm_idx0; break; + } else { + k = mm_idx0-1; break; + } + } + if (k != mm_idx0) continue; + t[j] = mm_idx0;//a[j] could reach mm_idx0; + if(p[j] != k) { + if(!(if_qchain_cnn(uref, uopt, ridx, bw, diff, &(a[j]), &(a[k]), &is_c, NULL))) continue; + } + sn = c_n[j] + 1; + if(sn >= (*mm_n)) {//must >= + (*mm_n) = sn; (*mm_idx) = j; + } + } + return; +} + + +int64_t gl_rchain_lin_contain(overlap_region_alloc* ol, kv_ul_ov_t *res, ul_ov_t *ex, kv_rtrace_t *trace, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, bit_extz_t *exz, uint64_t *a, +int64_t trans_sc, All_reads *ridx, char* qstr, UC_Read *tu, int64_t rid, double e_rate, int64_t need_srt) +{ + if(res->n == 0) return 0; + uint32_t li_v, rev_n, is_fc, cc; int32_t *f, *c_n, *c_sc, *rch, *ssc; int64_t *p, *t, res_n = res->n, st, max_ii, max, max_n; + int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, mm_n, sn, n_skip, end_j, plus; ul_ov_t *li, *lj, rev_t; rtrace_iter tc; + resize_Chain_Data(dp, res_n, NULL); + t = dp->tmp; f = dp->score; p = dp->pre; c_n = dp->occ; + c_sc = rch = dp->self_length; ssc = dp->indels; + if(need_srt) { + radix_sort_ul_ov_srt_qe(res->a, res->a + res_n); + for (i = 1, j = 0; i <= res_n; i++) { + res->a[i-1].qs = ((uint32_t)-1)-res->a[i-1].qs; + if (i == res_n || res->a[i].qe != res->a[j].qe) { + if(i - j > 1) radix_sort_ul_ov_srt_qs(res->a+j, res->a+i); + j = i; + } + } + } + + memset(t, 0, (res_n*sizeof((*t)))); + for (i = st = plus = 0, max_ii = -1; i < res_n; ++i) { + li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; li->qs = ((uint32_t)-1)-li->qs; + rch[i] = INT32_MAX; ssc[i] = INT32_MIN; a[i] = ((uint64_t)-1); + mm_ovlp = max_ovlp_src_contain(uopt, li_v^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + // if(li->tn == 20171 || li->tn == 20209 || li->tn == 20204) { + // fprintf(stderr, "\n[i::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\tmax_d::%ld\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, res->a[i].tn), Get_NAME(R_INF, res->a[i].tn), + // "+-"[res->a[i].rev], res->a[i].qs, res->a[i].qe, res->a[i].ts, res->a[i].te, + // !res->a[i].el, x+G_CHAIN_INDEL); + // } + x = find_ul_ov_max(i, res->a, x+G_CHAIN_INDEL); + // if(li->tn == 20171 || li->tn == 20209 || li->tn == 20204) { + // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\tmax_j::%ld\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, res->a[i].tn), Get_NAME(R_INF, res->a[i].tn), + // "+-"[res->a[i].rev], res->a[i].qs, res->a[i].qe, res->a[i].ts, res->a[i].te, + // !res->a[i].el, x); + // } + csc = li->qe - li->qs; csc -= (((int64_t)li->sec)*trans_sc); + // mm_sc = csc; mm_idx = -1; mm_n = 1; + mm_sc = INT32_MIN; mm_idx = -1; mm_n = 0; is_fc = 0; + n_skip = 0; end_j = -1; tc.k = INT32_MAX; + if ((x-st) > max_iter) st = x-max_iter; + for (j = x; j >= st; --j) { // collect potential destination vertices + lj = &(res->a[j]); + if(lj->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore + sc = connect_detect(res->a, res->n, i, j, ridx, rch, uref, uopt, bw, diff_ec_ul, p, f, &tc, + trace, qstr, tu, ol, exz, e_rate, trans_sc, &cc); + if(sc == INT32_MIN) continue; + sn = c_n[j] + 1; + // if(li->tn == 6312 || li->tn == 6322 || li->tn == 6317 || li->tn == 6319/** && lj->tn == 6329**/) { + // fprintf(stderr, "(id::%u)%.*s\t%c\t(id::%u)%.*s\t%c\tsc::%ld\tsn::%ld\tc_n[j]::%d\tmsc::%ld\ti::%ld\tj::%ld\tm_idx::%ld\n", + // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], + // lj->tn, (int)Get_NAME_LENGTH(R_INF, lj->tn), Get_NAME(R_INF, lj->tn), "+-"[lj->rev], + // sc, sn, c_n[j], mm_sc, i, j, mm_idx); + // } + // if(li->tn == 20209) { + // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tj::%ld\tsc::%ld\tsn::%ld\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, res->a[i].tn), Get_NAME(R_INF, res->a[i].tn), + // "+-"[res->a[i].rev], j, sc, sn); + // } + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { + mm_sc = sc, mm_idx = j; mm_n = sn; is_fc = cc; + if (n_skip > 0) --n_skip; + } else if (t[j] == i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + + end_j = j; + if (max_ii < 0 || (res->a[i].qe>(res->a[max_ii].qe+max_dis))) {//too long + max = INT32_MIN; max_n = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && (res->a[i].qe<=(max_dis+res->a[j].qe)); --j) { + if ((max < f[j]) || ((max == f[j]) && (max_n < c_n[j]))) { + max = f[j]; max_n = c_n[j]; max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + lj = &(res->a[max_ii]); + if(lj->qe > li->qs/** && lj->qs < li->qs**/) { + ///as max_ii < end_j, get_rid_backward_cigar_err still works + sc = connect_detect(res->a, res->n, i, max_ii, ridx, rch, uref, uopt, bw, diff_ec_ul, p, f, &tc, + trace, qstr, tu, ol, exz, e_rate, trans_sc, &cc); + if(sc != INT32_MIN) { + sn = c_n[max_ii] + 1; + // if(li->tn == 6312 || li->tn == 6322 || li->tn == 6317 || li->tn == 6319/** && lj->tn == 6329**/) { + // fprintf(stderr, "(id::%u)%.*s\t%c\t(id::%u)%.*s\t%c\tsc::%ld\tsn::%ld\tc_n[j]::%d\tmsc::%ld\ti::%ld\tmax_ii::%ld\tm_idx::%ld\n", + // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], + // lj->tn, (int)Get_NAME_LENGTH(R_INF, lj->tn), Get_NAME(R_INF, lj->tn), "+-"[lj->rev], + // sc, sn, c_n[j], mm_sc, i, max_ii, mm_idx); + // } + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { + mm_sc = sc; mm_idx = max_ii; mm_n = sn; is_fc = cc; + } + } + } + } + + sc = csc; sn = 1;///for i itself + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { + mm_sc = sc, mm_idx = -1; mm_n = sn; is_fc = 0; + } + + if(mm_sc < 0) { + mm_sc = csc; mm_idx = -1; mm_n = 1; + } + + // if(li->tn == 6317) { + // fprintf(stderr, "+(id::%u)%.*s\t%c\tmm_idx::%ld\tmm_sc::%ld\tmm_n::%ld\n", + // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], mm_idx, mm_sc, mm_n); + // } + + if(mm_idx >= 0) { + ///mo meed to update mm_sc and is_fc + propagate_transitive_reduction(uref, uopt, ridx, bw, diff_ec_ul, res->a, x+1, i, rch, f, p, c_n, t, &mm_sc, &mm_idx, &mm_n); + } + // if(li->tn == 6317) { + // fprintf(stderr, "-(id::%u)%.*s\t%c\tmm_idx::%ld\tmm_sc::%ld\tmm_n::%ld\n", + // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], mm_idx, mm_sc, mm_n); + // } + // collapse_contain(res->a, res_n, i, &mm_idx, &mm_sc, p, c_sc, end_j); + + f[i] = mm_sc; p[i] = mm_idx; c_n[i] = mm_n; + if(mm_idx < 0 || ((ssc[mm_idx] < mm_sc) && (is_fc == 0))) ssc[i] = mm_sc; + else ssc[i] = ssc[mm_idx]; + + if ((max_ii < 0) || ((res->a[i].qe<=max_dis+res->a[max_ii].qe) && (f[max_ii]tn == 20171 || li->tn == 20209 || li->tn == 20204) { + // fprintf(stderr, "[i::%ld]\tf::%d\tp::%ld\n", i, f[i], p[i]); + // } + + } + + for (i = 0; i < res_n; ++i) {///make all f[] positive + ssc[i] -= plus; t[i] = ((uint64_t)ssc[i])<<32; t[i] += (i<<1); + } + + int64_t n_v, n_u, n_v0; + radix_sort_gfa64i(t, t + res_n); plus = 0; + for (k = res_n-1, n_v = n_u = 0; k >= 0; --k) { + n_v0 = n_v; + for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { + ex[n_v++] = res->a[i]; t[i] |= 1; i = p[i]; + } + if(n_v0 == n_v) continue; + sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); + c_n[n_u] = n_v-n_v0; c_sc[n_u] = sc; n_u++; if(sc < plus) plus = sc; + } + // fprintf(stderr, "---[M::%s] n_u:%ld, n_v:%ld\n", __func__, n_u, n_v); + for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { + n_v0 = n_v; n_v += c_n[k]; + res->a[k].qn = c_sc[k]-plus;//score + res->a[k].ts = n_v0; res->a[k].te = n_v;///idx + // fprintf(stderr, "[M::%s] k:%ld, c_sc:%d\n", __func__, k, c_sc[k]); + + rev_n = c_n[k]>>1; + ///we need to consider contained reads; so determining qs is not such easy + // res->a[k].qs = (uint32_t)-1; res->a[k].qe = ex[n_v0].qe; + for (i = 0; i < rev_n; i++) { + rev_t = ex[n_v0+i]; ex[n_v0+i] = ex[n_v-i-1]; ex[n_v-i-1] = rev_t; + // if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; + // if(res->a[k].qs > ex[n_v-i-1].qs) res->a[k].qs = ex[n_v-i-1].qs; + ex[n_v0+i].sec = ex[n_v-i-1].sec = SEC_MODE; + } + if(c_n[k]&1) { + // if(res->a[k].qs > ex[n_v0+i].qs) res->a[k].qs = ex[n_v0+i].qs; + ex[n_v0+i].sec = SEC_MODE; + } + // flat_contain(ex+n_v0, n_v-n_v0); + res->a[k].te = res->a[k].ts + flat_contain(ridx, uref, uopt, bw, diff_ec_ul, qlen, max_skip, max_iter, max_dis, + ex + res->a[k].ts, res->a[k].te - res->a[k].ts, f, ssc, p, t, &(res->a[k])); + } + res->n = n_u; + radix_sort_ul_ov_srt_qn(res->a, res->a + res->n);//sort by score + + // if(res->n > 0) { + // fprintf(stderr, "[M::%s::rid->%ld] qlen::%ld, q::[%u, %u), sc::%u\n", + // __func__, rid, qlen, res->a[res->n-1].qs, res->a[res->n-1].qe, res->a[res->n-1].qn); + // } + return n_v; +} + + +int64_t gen_trans_aln(overlap_region_alloc* ol, All_reads *ridx, const ul_idx_t *uref, +const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, int64_t qlen, uint64_t *id, int64_t idn, +ul_ov_t *a, int64_t a_n, uint64_t qs, uint64_t qe, int64_t *vis, int32_t *f0, int32_t *c_n0, +int32_t *c_sc0, int32_t *rch0, int32_t *ssc0, int64_t *p0, int64_t *t0, int64_t max_skip, +int64_t max_iter, int64_t max_dis, bit_extz_t *exz, int64_t trans_sc, char* qstr, UC_Read *tu, +double e_rate, kv_rtrace_t *trace, uint32_t rechain_w, ul_ov_t *res, ul_ov_t *rr) +{ + if(idn == 0) return 0; + int64_t k, l, i, j, z, nv = 0, qo, is_c, nf; + ul_ov_t *li, *lj; uint32_t li_v, lj_v, update, tipl = 0, mm = ((uint32_t)(0x20000000U)); + // for (i = 0; i < idn; i++) { + // li = &(a[id[i]]); + // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", + // i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), + // "+-"[li->rev], li->qs, li->qe, li->ts, li->te, !li->el); + // } + for (i = nf = 0; i < idn; i++) { + if(a[id[i]].el) break; + if((a[id[i]].ts == 0) && (a[id[i]].te == Get_READ_LENGTH(R_INF, a[id[i]].tn))) nf++; + } + if(i < idn && nf > 0) { + if((a[id[i]].qs > qs) && (qs <= rechain_w)) { + tipl = qs; ///there are contained chains beforehand + } + } + + for (i = 0, k = l = -1; i < idn; i++) { + k = id[i]; + if(k - l > 1) { + if(l < 0) { + for (l = k-1; l >= 0 && a[l].qe > qs; l--); + } + + for (z = l + 1; z < k; z++) { + li = &(a[z]); li_v = (li->tn<<1)|li->rev; + if((!(li->el))||(vis[z]&1)) continue; + if(!(((li->qs + tipl) >= qs) && (li->qe < qe))) continue; + for (j = i-1, update = 1; j >= 0; --j) { + lj = &(a[id[j]]); lj_v = (lj->tn<<1)|lj->rev; + if(lj->qe <= li->qs) break; + qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) + if((li_v == lj_v) || (!get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, + bw, diff_ec_ul, qo, &is_c))) { + update = 0; break; + } + } + // if(li->tn == 6312) { + // fprintf(stderr, "[z::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\tnf::%ld\ttipl::%u\tl::%ld\tk::%ld\tupdate::%u\n", z, li->tn, + // (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), + // "+-"[li->rev], li->qs, li->qe, li->ts, li->te, !li->el, nf, tipl, l, k, update); + // } + if(update) { + res[nv] = a[z]; res[nv].sec = (z<<1) + ((li->qs>=qs)?0:1); nv++; + } + } + } + l = k; + + li = &(a[k]); li_v = (li->tn<<1)|li->rev; + for (j = nv-1; j >= 0; --j) { + lj = &(res[j]); lj_v = (lj->tn<<1)|lj->rev; + if(lj->qe <= li->qs) break; + if(lj->qn == (uint32_t)-1) continue;//deleted + if((lj->sec&mm)) continue;//could not be deleted + qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) + if((li_v == lj_v) || (!get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, + bw, diff_ec_ul, qo, &is_c))) { + // if(lj->tn == 6312) { + // fprintf(stderr, "delete::(id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", + // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), + // "+-"[li->rev], li->qs, li->qe, li->ts, li->te, !li->el); + // } + res[j].qn = res[j].tn = (uint32_t)-1; + } + } + res[nv] = a[k]; res[nv].sec = k; res[nv].sec<<=1; res[nv].sec |= mm; nv++; + } + + k = a_n; i = idn; + if(k - l > 1) { + for (z = l + 1; z < k; z++) { + li = &(a[z]); li_v = (li->tn<<1)|li->rev; + if((!(li->el))||(vis[z]&1)) continue; + if(!(((li->qs + tipl) >= qs) && (li->qe < qe))) continue; + for (j = i-1, update = 1; j >= 0; --j) { + lj = &(a[id[j]]); lj_v = (lj->tn<<1)|lj->rev; + if(lj->qe <= li->qs) break; + qo = infer_rovlp(li, lj, NULL, NULL, ridx, NULL); ///overlap length in query (UL read) + if((li_v == lj_v) || (!get_ecov_contain_adv(uref, uopt, li_v^1, lj_v^1, + bw, diff_ec_ul, qo, &is_c))) { + update = 0; break; + } + } + if(update) { + res[nv] = a[z]; res[nv].sec = (z<<1) + ((li->qs>=qs)?0:1); nv++; + } + } + } + // fprintf(stderr, "\n[M::%s::] old_n::%ld, new_n::%ld\n", __func__, idn, nv); + for (i = k = 0; i < nv; i++) { + if(res[i].qn == (uint32_t)-1) continue; + res[k] = res[i]; + if(res[k].sec&mm) {res[k].sec -= mm;} k++; + // res[k] = res[i]; + // id[k] = res[k].sec; + // if(id[k]&mm) id[k] -= mm; + // id[k] >>= 1; + // if(res[k].sec&1) id[k] |= ((uint64_t)(0x100000000U));///low prority + // // if(res[k].sec&mm) id[k] |= ((uint64_t)(0x200000000U));//orignal alignments + // k++; + + // fprintf(stderr, "[k::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\tnew::%u\n", k, + // res[k].tn,(int)Get_NAME_LENGTH(R_INF, res[k].tn), Get_NAME(R_INF, res[k].tn), + // "+-"[res[k].rev], res[k].qs, res[k].qe, res[k].ts, res[k].te, !res[k].el, + // (res[k].sec != SEC_MODE)); + // if(res[k].sec != SEC_MODE) vis[res[k].sec>>1] |= 1; + // res[k].sec = SEC_MODE; k++; + } + nv = idn = k; + nv = flat_contain_adv(ol, ridx, uref, uopt, bw, diff_ec_ul, qlen, max_skip, max_iter, max_dis, + exz, trans_sc, qstr, tu, e_rate, trace, res, nv, f0, c_n0, c_sc0, rch0, ssc0, p0, t0, a, id, + rechain_w, vis, rr); + // f, ssc, p, t, &(res->a[k])); + // for (k = 0; k < idn; k++) { + // if(((uint32_t)id[k])&1) continue; + // vis[((uint32_t)id[k])>>1] |= 1; + // } + return nv; +} + +int64_t gl_rchain_lin_contain_adv(overlap_region_alloc* ol, kv_ul_ov_t *res, ul_ov_t *ex, kv_rtrace_t *trace, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, bit_extz_t *exz, uint64_t *id, +int64_t trans_sc, All_reads *ridx, char* qstr, UC_Read *tu, int64_t rid, double e_rate, int64_t need_srt) +{ + if(res->n == 0) return 0; + uint32_t li_v, rev_n, is_fc, cc, idn, mqs, mqe; int32_t *f, *c_n, *c_sc, *rch, *ssc; int64_t *p, *t, res_n = res->n, st, max_ii, max, max_n; + int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, mm_n, sn, n_skip, end_j, plus; ul_ov_t *li, *lj, rr, mrr; rtrace_iter tc; uint64_t ovlp; + resize_Chain_Data(dp, res_n<<1, NULL);///res_n<<1 + t = dp->tmp; f = dp->score; p = dp->pre; c_n = dp->occ; + c_sc = rch = dp->self_length; ssc = dp->indels; + if(need_srt) { + radix_sort_ul_ov_srt_qe(res->a, res->a + res_n); + for (i = 1, j = 0; i <= res_n; i++) { + res->a[i-1].qs = ((uint32_t)-1)-res->a[i-1].qs; + if (i == res_n || res->a[i].qe != res->a[j].qe) { + if(i - j > 1) radix_sort_ul_ov_srt_qs(res->a+j, res->a+i); + j = i; + } + } + } + + memset(t, 0, (res_n*sizeof((*t)))); + for (i = st = plus = 0, max_ii = -1; i < res_n; ++i) { + li = &(res->a[i]); li_v = (li->tn<<1)|li->rev; li->qs = ((uint32_t)-1)-li->qs; + rch[i] = INT32_MAX; ssc[i] = INT32_MIN; + mm_ovlp = max_ovlp_src_contain(uopt, li_v^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + // if(li->tn == 20171 || li->tn == 20209 || li->tn == 20204) { + // fprintf(stderr, "\n[i::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\tmax_d::%ld\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, res->a[i].tn), Get_NAME(R_INF, res->a[i].tn), + // "+-"[res->a[i].rev], res->a[i].qs, res->a[i].qe, res->a[i].ts, res->a[i].te, + // !res->a[i].el, x+G_CHAIN_INDEL); + // } + x = find_ul_ov_max(i, res->a, x+G_CHAIN_INDEL); + // if(li->tn == 6312) { + // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\tmax_j::%ld\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, res->a[i].tn), Get_NAME(R_INF, res->a[i].tn), + // "+-"[res->a[i].rev], res->a[i].qs, res->a[i].qe, res->a[i].ts, res->a[i].te, + // !res->a[i].el, x); + // } + csc = li->qe - li->qs; csc -= (((int64_t)li->sec)*trans_sc); + // mm_sc = csc; mm_idx = -1; mm_n = 1; + mm_sc = INT32_MIN; mm_idx = -1; mm_n = 0; is_fc = 0; + n_skip = 0; end_j = -1; tc.k = INT32_MAX; + if ((x-st) > max_iter) st = x-max_iter; + for (j = x; j >= st; --j) { // collect potential destination vertices + lj = &(res->a[j]); + if(lj->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore + sc = connect_detect(res->a, res->n, i, j, ridx, rch, uref, uopt, bw, diff_ec_ul, p, f, &tc, + trace, qstr, tu, ol, exz, e_rate, trans_sc, &cc); + if(sc == INT32_MIN) continue; + sn = c_n[j] + 1; + // if(li->tn == 6312) { + // fprintf(stderr, "(id::%u)%.*s\t%c\t(id::%u)%.*s\t%c\tsc::%ld\tsn::%ld\tc_n[j]::%d\tmsc::%ld\ti::%ld\tj::%ld\tm_idx::%ld\n", + // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], + // lj->tn, (int)Get_NAME_LENGTH(R_INF, lj->tn), Get_NAME(R_INF, lj->tn), "+-"[lj->rev], + // sc, sn, c_n[j], mm_sc, i, j, mm_idx); + // } + // if(li->tn == 20209) { + // fprintf(stderr, "[i::%ld] (id::%u)%.*s\t%c\tj::%ld\tsc::%ld\tsn::%ld\n", i, li->tn, + // (int)Get_NAME_LENGTH(R_INF, res->a[i].tn), Get_NAME(R_INF, res->a[i].tn), + // "+-"[res->a[i].rev], j, sc, sn); + // } + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { + mm_sc = sc, mm_idx = j; mm_n = sn; is_fc = cc; + if (n_skip > 0) --n_skip; + } else if (t[j] == i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + + end_j = j; + if (max_ii < 0 || (res->a[i].qe>(res->a[max_ii].qe+max_dis))) {//too long + max = INT32_MIN; max_n = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && (res->a[i].qe<=(max_dis+res->a[j].qe)); --j) { + if ((max < f[j]) || ((max == f[j]) && (max_n < c_n[j]))) { + max = f[j]; max_n = c_n[j]; max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + lj = &(res->a[max_ii]); + if(lj->qe > li->qs/** && lj->qs < li->qs**/) { + ///as max_ii < end_j, get_rid_backward_cigar_err still works + sc = connect_detect(res->a, res->n, i, max_ii, ridx, rch, uref, uopt, bw, diff_ec_ul, p, f, &tc, + trace, qstr, tu, ol, exz, e_rate, trans_sc, &cc); + if(sc != INT32_MIN) { + sn = c_n[max_ii] + 1; + // if(li->tn == 6312 || li->tn == 6322 || li->tn == 6317 || li->tn == 6319/** && lj->tn == 6329**/) { + // fprintf(stderr, "(id::%u)%.*s\t%c\t(id::%u)%.*s\t%c\tsc::%ld\tsn::%ld\tc_n[j]::%d\tmsc::%ld\ti::%ld\tmax_ii::%ld\tm_idx::%ld\n", + // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], + // lj->tn, (int)Get_NAME_LENGTH(R_INF, lj->tn), Get_NAME(R_INF, lj->tn), "+-"[lj->rev], + // sc, sn, c_n[j], mm_sc, i, max_ii, mm_idx); + // } + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { + mm_sc = sc; mm_idx = max_ii; mm_n = sn; is_fc = cc; + } + } + } + } + + sc = csc; sn = 1;///for i itself + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { + mm_sc = sc, mm_idx = -1; mm_n = sn; is_fc = 0; + } + + if(mm_sc < 0) { + mm_sc = csc; mm_idx = -1; mm_n = 1; + } + + // if(li->tn == 6317) { + // fprintf(stderr, "+(id::%u)%.*s\t%c\tmm_idx::%ld\tmm_sc::%ld\tmm_n::%ld\n", + // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], mm_idx, mm_sc, mm_n); + // } + + if(mm_idx >= 0) { + ///mo meed to update mm_sc and is_fc + propagate_transitive_reduction(uref, uopt, ridx, bw, diff_ec_ul, res->a, x+1, i, rch, f, p, c_n, t, &mm_sc, &mm_idx, &mm_n); + } + // if(li->tn == 6317) { + // fprintf(stderr, "-(id::%u)%.*s\t%c\tmm_idx::%ld\tmm_sc::%ld\tmm_n::%ld\n", + // li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), "+-"[li->rev], mm_idx, mm_sc, mm_n); + // } + // collapse_contain(res->a, res_n, i, &mm_idx, &mm_sc, p, c_sc, end_j); + + f[i] = mm_sc; p[i] = mm_idx; c_n[i] = mm_n; + if(mm_idx < 0 || ((ssc[mm_idx] < mm_sc) && (is_fc == 0))) ssc[i] = mm_sc; + else ssc[i] = ssc[mm_idx]; + + if ((max_ii < 0) || ((res->a[i].qe<=max_dis+res->a[max_ii].qe) && (f[max_ii]tn == 20171 || li->tn == 20209 || li->tn == 20204) { + // fprintf(stderr, "[i::%ld]\tf::%d\tp::%ld\n", i, f[i], p[i]); + // } + + } + + for (i = 0; i < res_n; ++i) {///make all f[] positive + ssc[i] -= plus; t[i] = ((uint64_t)ssc[i])<<32; t[i] += (i<<1); + } + + int64_t n_v, n_u, n_v0; mrr.qn = (uint32_t)-1; mrr.qe = mrr.qs = 0; + int32_t *f0, *c_n0, *c_sc0, *rch0, *ssc0; int64_t *p0, *t0; + f0 = f + res_n; c_n0 = c_n + res_n; c_sc0 = c_sc + res_n; + rch0 = rch + res_n; ssc0 = ssc + res_n; p0 = p + res_n; t0 = t + res_n; + radix_sort_gfa64i(t, t + res_n); plus = 0; mqs = UINT32_MAX; mqe = 0; + for (k = res_n-1, n_v = n_u = 0; k >= 0; --k) { + n_v0 = n_v; idn = 0; + for (i = ((uint32_t)t[k])>>1; i >= 0 && (t[i]&1) == 0; ) { + if(res->a[i].qs < mqs) mqs = res->a[i].qs; + if(res->a[i].qe > mqe) mqe = res->a[i].qe; + // ex[n_v] = res->a[i]; ex[n_v].sec = i; + id[idn++] = i; t[i] |= 1; i = p[i]; n_v++; + } + if(n_v0 == n_v) continue; + sc = (i<0?(t[k]>>32):((t[k]>>32)-f[i])); + + + if((mrr.qn != (uint32_t)-1) && (sc < (c_sc[mrr.qn]*0.98))) { + ovlp = ((MIN(mrr.qe, mqe) > MAX(mrr.qs, mqs))? (MIN(mrr.qe, mqe) - MAX(mrr.qs, mqs)):0); + if(ovlp >= ((mqe-mqs)*0.95)) { + n_v = n_v0; continue; + } + } + + rev_n = idn>>1; + for (i = 0; i < rev_n; i++) { + st = id[i]; id[i] = id[idn-i-1]; id[idn-i-1] = st; + } + n_v = n_v0 + gen_trans_aln(ol, ridx, uref, uopt, bw, diff_ec_ul, qlen, id, idn, res->a, res_n, mqs, mqe, t, + f0, c_n0, c_sc0, rch0, ssc0, p0, t0, max_skip, max_iter, max_dis, exz, trans_sc, qstr, tu, e_rate, trace, 1000, ex + n_v0, &rr); + assert(n_v > n_v0); + c_n[n_u] = n_v-n_v0; c_sc[n_u] = sc; n_u++; if(sc < plus) plus = sc; + if((mrr.qn == (uint32_t)-1) || (sc > c_sc[mrr.qn]) || + ((sc == c_sc[mrr.qn]) && ((rr.qe - rr.qs) > (mrr.qe - mrr.qs)))) { + mrr = rr; mrr.qn = n_u - 1; + } + } + + // fprintf(stderr, "---[M::%s] n_u:%ld, n_v:%ld\n", __func__, n_u, n_v); + for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { + n_v0 = n_v; n_v += c_n[k]; + res->a[k].qn = c_sc[k]-plus;//score + res->a[k].ts = n_v0; res->a[k].te = n_v;///idx + res->a[k].qs = ex[n_v0].qs; res->a[k].qe = ex[n_v-1].qe; + // fprintf(stderr, "[M::%s] k:%ld, c_sc:%d\n", __func__, k, c_sc[k]); + // res->a[k].te = res->a[k].ts + flat_contain(ridx, uref, uopt, bw, diff_ec_ul, qlen, max_skip, max_iter, max_dis, + // ex + res->a[k].ts, res->a[k].te - res->a[k].ts, f, ssc, p, t, &(res->a[k])); + } + res->n = n_u; + radix_sort_ul_ov_srt_qn(res->a, res->a + res->n);//sort by score + + // if(res->n > 0) { + // fprintf(stderr, "[M::%s::rid->%ld] qlen::%ld, q::[%u, %u), sc::%u\n", + // __func__, rid, qlen, res->a[res->n-1].qs, res->a[res->n-1].qe, res->a[res->n-1].qn); + // } + return n_v; +} + +int64_t select_clean_chain(kv_ul_ov_t *idx, ul_ov_t *res_a, int64_t res_n, int64_t ulid_local, asg64_v *b64) +{ + ul_ov_t kp, *m, *p, *idx_a = idx->a; uint64_t om, ovlp, min_sc, max_sc, ok, z; + int64_t k, i, idx_n = idx->n, mm, n_mchain; + for (k = 0, mm = idx_n>>1; k < mm; k++) { + kp = idx_a[k]; idx_a[k] = idx_a[idx_n-k-1]; idx_a[idx_n-k-1] = kp; + idx_a[k].tn = idx_a[idx_n-k-1].tn = 1; + } + if(idx_n&1) idx_a[k].tn = 1; + + for (k = 0; k < idx_n; k++) {//filter too close chains + m = &(idx_a[k]); om = m->qe - m->qs; ///current chain + // fprintf(stderr, "k::%ld[M::%s::sc->%u] q::[%u, %u), set::%u\n", k, __func__, m->qn, m->qs, m->qe, m->tn); + if(m->tn == 0) continue; + for (i = k-1; i >= 0; i--) { + p = &(idx_a[i]); + ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); + if(ovlp == 0) continue; + min_sc = MIN(p->qn, m->qn); max_sc = MAX(p->qn, m->qn); + ok = p->qe - p->qs; ok = MAX(ok, om); + if(min_sc < (max_sc*0.98)) break; + if((ovlp > GC_OFFSET_POS) && (min_sc > (max_sc*0.98)) && (ovlp > (ok*0.8))) { + // fprintf(stderr, "k::%ld[M::%s::i->%ld] min_sc::%ld, max_sc::%ld\n", + // k, __func__, i, min_sc, max_sc); + m->tn = p->tn = 0; + } + } + + for (i = k+1; i < idx_n; i++) { + p = &(idx_a[i]); + ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); + if(ovlp == 0) continue; + min_sc = MIN(p->qn, m->qn); max_sc = MAX(p->qn, m->qn); + ok = p->qe - p->qs; ok = MAX(ok, om); + if(min_sc < (max_sc*0.98)) break; + if((ovlp > GC_OFFSET_POS) && (min_sc > (max_sc*0.98)) && (ovlp > (ok*0.8))) { + // fprintf(stderr, "k::%ld[M::%s::i->%ld] min_sc::%ld, max_sc::%ld\n", + // k, __func__, i, min_sc, max_sc); + m->tn = p->tn = 0; + } + } + } + + for (k = i = 0; k < idx_n; k++) { + m = &(idx_a[k]); if(m->tn == 0) continue; + idx_a[i++] = idx_a[k]; + } + // fprintf(stderr, "[M::%s::] gb_n0::%ld, gb_n::%ld\n", __func__, gb_n, i); + idx->n = idx_n = i; + for (k = n_mchain = 0; k < idx_n; k++) { + m = &(idx_a[k]); om = m->qe - m->qs; + for (i = 0; i < n_mchain; i++) { + p = &(idx_a[i]); + ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); + if(ovlp == 0) continue; + ok = p->qe - p->qs; + if((ovlp > ok*0.1) || (ovlp > om*0.1)) break; + } + if(i < n_mchain) continue; + idx_a[n_mchain++] = idx_a[k]; + } + idx->n = idx_n = n_mchain; + + b64->n = idx->n; kv_resize(uint64_t, *b64, b64->n); + for (k = 0; k < idx_n; k++) { + om = idx_a[k].ts; om <<= 32; om |= k; b64->a[k] = om; + } + radix_sort_gfa64(b64->a, b64->a + b64->n); + for (k = res_n = 0; k < idx_n; k++) { + m = &(idx_a[(uint32_t)(b64->a[k])]); + for (z = m->ts, ok = SEC_MODE; z < m->te; z++) { + res_a[res_n] = res_a[z]; res_a[res_n].el = 1; + res_a[res_n].tn |= ((uint32_t)(0x80000000)); + res_a[res_n].sec = ok; + res_a[res_n].qn = ((idx_n<=1)?ulid_local:res_n); + ok = res_n; res_n++; + } + } + + if(idx_n > 1) { + radix_sort_ul_ov_srt_qe(res_a, res_a + res_n); + for (i = 1, k = 0; i <= res_n; i++) { + if (i == res_n || res_a[i].qe != res_a[k].qe) { + if(i-k>1) radix_sort_ul_ov_srt_qs(res_a+k, res_a+i); + k = i; + } + } + b64->n = res_n; kv_resize(uint64_t, *b64, b64->n); + for (i = 0; i < res_n; i++) b64->a[res_a[i].qn] = i; + for (i = 0; i < res_n; i++) { + if(res_a[b64->a[i]].sec != SEC_MODE) { + res_a[b64->a[i]].sec = b64->a[res_a[b64->a[i]].sec]; + } + res_a[b64->a[i]].qn = ulid_local; + } + } + return res_n; +} + +void prt_rid_raw_chain(kv_ul_ov_t *idx, int64_t rid, int64_t qlen) +{ + uint64_t i; + for (i = 0; i < idx->n; i++) { + fprintf(stderr, "[M::%s::rid->%ld] qlen::%ld, q::[%u, %u), sc::%u, cha_n::%u, idx_n::%u\n", + __func__, rid, qlen, idx->a[i].qs, idx->a[i].qe, idx->a[i].qn, idx->a[i].te - idx->a[i].ts, + (uint32_t)idx->n); + } + +} + +void prt_all_chain(kv_ul_ov_t *idx, ul_ov_t *a, int64_t ql) +{ + uint64_t i, k; + for (i = 0; i < idx->n; i++) { + fprintf(stderr, "\n[M::%s] q::[%u, %u), ql::%ld, sc::%u\n", __func__, idx->a[i].qs, idx->a[i].qe, ql, idx->a[i].qn); + for (k = idx->a[i].ts; k < idx->a[i].te; k++) { + fprintf(stderr, "%.*s\t%c\tq::[%u, %u)\tt::[%u, %u)\tc::%u\n", + (int)Get_NAME_LENGTH(R_INF, a[k].tn), Get_NAME(R_INF, a[k].tn), "+-"[a[k].rev], + a[k].qs, a[k].qe, a[k].ts, a[k].te, !a[k].el); + } + } + +} + +void gen_rid_raw_chain(overlap_region_alloc* ol, glchain_t *ll, uint64_t cha_idx, Chain_Data* dp, const ul_idx_t *uref, double diff_ec_ul, int64_t qlen, const ug_opt_t *uopt, char* qstr, UC_Read *tu, bit_extz_t *exz, int64_t ulid_local, +int64_t rid, ha_ovec_buf_t *bb, int64_t max_chain) +{ + ul_ov_t *res_a; uint64_t res_n; asg64_v b64; + int64_t tran_sc = ((diff_ec_ul>0)?(((double)1)/(diff_ec_ul)):(0)); + kv_ul_ov_t *idx = &(ll->lo), *res = &(ll->tk); + idx->n = 0; if(res->n <= cha_idx) return; + + res_a = res->a + cha_idx; res_n = res->n - cha_idx; + kv_resize(ul_ov_t, *idx, res_n); idx->n = res_n; + memcpy(idx->a, res_a, res_n*sizeof(*(res->a))); + kv_resize(uint64_t, ll->srt.a, res_n); + // fprintf(stderr, "\n+[M::%s] rid::%ld, name::%.*s\n", __func__, rid, + // (int32_t)UL_INF.nid.a[rid].n, UL_INF.nid.a[rid].a); + // res_n = gl_rchain_lin_contain(ol, idx, res_a, &(ll->tc), uref, uopt, G_CHAIN_BW, N_GCHAIN_RATE, qlen, ((max_chain>UG_SKIP_N)?max_chain:UG_SKIP_N), UG_ITER_N, UG_DIS_N, dp, exz, ll->srt.a.a, tran_sc, &R_INF, qstr, tu, rid, diff_ec_ul, 1); + res_n = gl_rchain_lin_contain_adv(ol, idx, res_a, &(ll->tc), uref, uopt, G_CHAIN_BW, N_GCHAIN_RATE, qlen, ((max_chain>UG_SKIP_N)?max_chain:UG_SKIP_N), UG_ITER_N, UG_DIS_N, dp, exz, ll->srt.a.a, tran_sc, &R_INF, qstr, tu, rid, diff_ec_ul, 1); + // fprintf(stderr, "-[M::%s] rid::%ld, name::%.*s\n", __func__, rid, + // (int32_t)UL_INF.nid.a[rid].n, UL_INF.nid.a[rid].a); + + // prt_all_chain(idx, res_a, qlen); + + copy_asg_arr(b64, ll->srt.a); + res_n = select_clean_chain(idx, res_a, res_n, ulid_local, &b64); + copy_asg_arr(ll->srt.a, b64); + res->n = cha_idx + res_n; + + if((idx->n) && (idx->a[0].qe - idx->a[0].qs) >= (qlen*0.95)) { + bb->num_read_base++; + } + + // else { + // // idx->n = 1; + // prt_rid_raw_chain(idx, rid, qlen); + // } + // prt_rid_raw_chain(idx, rid, qlen); + + // //debug + // ll->lo.n = ll->tk.n = 0; +} + + +static void worker_for_ul_scall_alignment(void *data, long i, int tid) // callback for kt_for() +{ + utepdat_t *s = (utepdat_t*)data; + ha_ovec_buf_t *b = s->hab[tid]; + glchain_t *bl = &(s->ll[tid]); + int64_t /**rid = s->id+i,**/ winLen = MIN((((double)THRESHOLD_MAX_SIZE)/s->opt->diff_ec_ul), WINDOW), cha_idx; + uint32_t high_occ = 2; overlap_region *aux_o = NULL; + // if(s->id+i != 901) return; + // if(s->id+i != 1052) return; + // fprintf(stderr, "[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], + // (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); + // if (memcmp(UL_INF.nid.a[s->id+i].a, "d0aab024-b3a7-40fb-83cc-22c3d6d951f8", UL_INF.nid.a[s->id+i].n-1)) return; + // fprintf(stderr, "[M::%s::] ==> len: %lu\n", __func__, s->len[i]); + // ha_get_ul_candidates_interface(b->abl, i, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->olist_hp, &b->clist, s->opt->bw_thres, + // s->opt->max_n_chain, 1, NULL/**&(b->k_flag)**/, &b->r_buf, &(b->tmp_region), NULL, &(b->sp), asm_opt.hom_cov, km); + ul_map_lchain(b->abl, (uint32_t)-1, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->clist, s->opt->bw_thres, + s->opt->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2/**0.75**/, 2, 3); + + clear_Cigar_record(&b->cigar1); + clear_Round2_alignment(&b->round2); + + ul_rid_lalign_adv(&b->olist, &b->clist, s->uu, s->uopt, s->seq[i], s->len[i], &b->self_read, &b->ovlp_read, + &b->exz, NULL, s->opt->diff_ec_ul, winLen, NULL, NULL, NULL, s->id+i, s->opt->k, NULL); + + aux_o = gen_aux_ovlp(&b->olist);///must be here + cha_idx = bl->tk.n; + + ul_rid_lalign_adv(&b->olist, &b->clist, s->uu, s->uopt, s->seq[i], s->len[i], &b->self_read, &b->ovlp_read, + &b->exz, aux_o, s->opt->diff_ec_ul, winLen, &(bl->tk), &(bl->lo), &(bl->tc), s->id+i, s->opt->k, NULL); + + // bl->lo.n = bl->tk.n = 0; + gen_rid_raw_chain(&b->olist, bl, cha_idx, &(b->clist.chainDP), s->uu, s->opt->diff_ec_ul, s->len[i], s->uopt, s->seq[i], &b->ovlp_read, &b->exz, i, s->id+i, b, s->opt->max_n_chain); + /** + // gl_chain_refine(&b->olist, &b->correct, &b->hap, bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], km); + gl_chain_refine_advance(&b->olist, &b->correct, &b->hap, bl, &(s->sps[tid]), s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, km); + align = kv_ul_ov_t_statistics(&(bl->tk), i, &(b->num_recorrect_base)); + if(align == s->len[i]) { + free(s->seq[i]); s->seq[i] = NULL; + } + b->num_correct_base += align; + **/ + // fprintf(stderr, "[1M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], + // (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); + + // fprintf(stderr, "[M::%s] rid:%ld, dd:%u\n", __func__, s->id+i, UL_INF.a[s->id+i].dd); + // int64_t mem[6], mem_hab[6]; + // if(get_utepdat_t_mem_tid(s, tid, mem, mem_hab)>((int64_t)5*(int64_t)1073741824)) { + // fprintf(stderr, "[M::%s::tid->%d::rid->%ld] buffer[0]: %.3fGB(%.3fGB::%.3fGB::%.3fGB::%.3fGB::%.3fGB), buffer[1]: %.3fGB, buffer[2]: %.3fGB, buffer[3]: %.3fGB, buffer[4]: %.3fGB, buffer[5]: %.3fGB\n", + // __func__, tid, i, mem[0]/1073741824.0, + // mem_hab[0]/1073741824.0, mem_hab[1]/1073741824.0, mem_hab[2]/1073741824.0, + // mem_hab[3]/1073741824.0, mem_hab[4]/1073741824.0, + // mem[1]/1073741824.0, mem[2]/1073741824.0, + // mem[3]/1073741824.0, mem[4]/1073741824.0, mem[5]/1073741824.0); + // } +} + +// void prt_overlap_region_alloc_ol(overlap_region_alloc* ol, uint32_t ulid) +// { +// char *as = NULL; +// uint32_t i, k; overlap_region *z; +// asprintf(&as, "[M::%s] ol->length::%lu\n", __func__, ol->length); +// push_vlog(&(overall_zdbg->a[ulid]), as); free(as); as = NULL; +// for (i = 0; i < ol->length; i++) { +// z = &(ol->list[i]); +// asprintf(&as, "[name::utg%.6dl::%c]\tq::[%u, %u)\tt::[%u, %u)\talign_length::%u\tnon_homopolymer_errors::%u\tw_list.n::%u\n", +// (int32_t)z->y_id+1, "+-"[z->y_pos_strand], z->x_pos_s, z->x_pos_e+1, z->y_pos_s, z->y_pos_e+1, +// z->align_length, z->non_homopolymer_errors, (uint32_t)z->w_list.n); +// push_vlog(&(overall_zdbg->a[ulid]), as); free(as); as = NULL; + +// for (k = 0; k < z->w_list.n; k++) { +// asprintf(&as, "q::[%u, %u)\tclen::%u\n", +// z->w_list.a[k].x_start, z->w_list.a[k].x_end+1, z->w_list.a[k].clen); +// push_vlog(&(overall_zdbg->a[ulid]), as); free(as); as = NULL; +// } + +// } + +// } + +static void worker_for_ul_rescall_alignment(void *data, long i, int tid) // callback for kt_for() +{ + utepdat_t *s = (utepdat_t*)data; + ha_ovec_buf_t *b = s->hab[tid]; + glchain_t *bl = &(s->ll[tid]); + int64_t /**rid = s->id+i,**/ winLen = MIN((((double)THRESHOLD_MAX_SIZE)/s->opt->diff_ec_ul), WINDOW), ton = 0; + uint32_t high_occ = 2, phase = 1, k; + asg64_v b0, b1, b2; window_list p; memset(&p, 0, sizeof(p)); + overlap_region *aux_o = NULL; + // uint64_t align = 0; + + // if(UL_INF.a[s->id+i].rlen != s->len[i]) { + // fprintf(stderr, "[M::%s] rid:%ld, s->len:%lu, UL_INF->rlen:%u\n", __func__, s->id+i, s->len[i], UL_INF.a[s->id+i].rlen); + // } + // assert(UL_INF.a[s->id+i].rlen == s->len[i]); + // void *km = s->buf?(s->buf[tid]?s->buf[tid]->km:NULL):NULL; + // if(s->id+i!=0/** && s->id+i!=4 && s->id+i!=5**/) return; + // if(s->id+i!=300) return; + // fprintf(stderr, "\n[M::%s] rid:%ld, s->len:%lu\n", __func__, s->id+i, s->len[i]); + // if((s->id+i!=871) && (s->id+i!=963) && (s->id+i!=980)) return; + // if(s->id+i!=944) return; + // if(s->id+i != 35437) return; + // if((s->id+i != 7086) && (s->id+i != 51705) && (s->id+i != 266022) && (s->id+i != 353608) + // && (s->id+i != 399416) && (s->id+i != 403014) && (s->id+i != 420915) && (s->id+i != 603855) + // && (s->id+i != 680134) && (s->id+i != 766261) && (s->id+i != 794527)) { + // return; + // } + // char *as = NULL; + // asprintf(&as, "\n[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); + // push_vlog(&(overall_zdbg->a[s->id+i]), as); free(as); as = NULL; + // fprintf(stderr, "\n[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], + // (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); + // fprintf(stderr, ">%.*s\n%.*s\n", (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a, + // (int32_t)s->len[i], s->seq[i]); + + // if (memcmp(UL_INF.nid.a[s->id+i].a, "d0aab024-b3a7-40fb-83cc-22c3d6d951f8", UL_INF.nid.a[s->id+i].n-1)) return; + // fprintf(stderr, "[M::%s::] ==> len: %lu\n", __func__, s->len[i]); + // ha_get_ul_candidates_interface(b->abl, i, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->olist_hp, &b->clist, s->opt->bw_thres, + // s->opt->max_n_chain, 1, NULL, &b->r_buf, &(b->tmp_region), NULL, &(b->sp), 1, NULL); + ul_map_lchain(b->abl, (uint32_t)-1, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->clist, s->opt->bw_thres, + s->opt->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, /**0**/2, 1/**3**/); + + clear_Cigar_record(&b->cigar1); + clear_Round2_alignment(&b->round2); + // return; + // b->num_correct_base += overlap_statistics(&b->olist, NULL, 0); + + // int fully_cov, abnormal; + // b->self_read.seq = s->seq[i]; b->self_read.length = s->len[i]; b->self_read.size = 0; + // correct_ul_overlap(&b->olist, s->uu, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, + // &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 1, &fully_cov, &abnormal, s->opt->diff_ec_ul, winLen, NULL); + // memset(&b->self_read, 0, sizeof(b->self_read)); + + ul_lalign(&b->olist, &b->clist, s->uu, s->uopt, s->seq[i], s->len[i], &b->self_read, &b->ovlp_read, + &b->correct, &b->exz, &b->hap, &b->r_buf, aux_o, s->opt->diff_ec_ul, winLen, NULL, s->id+i, s->opt->k, &(s->sps[tid]), s->mm, &(s->mk[tid]), NULL); + // ul_lalign_old_ed(&b->olist, &b->clist, s->uu, s->seq[i], s->len[i], &b->self_read, &b->ovlp_read, + // &b->correct, &b->hap, &b->r_buf, s->opt->diff_ec_ul, winLen, 1, NULL); + ton = b->olist.length;//all alignments pass similary check + aux_o = gen_aux_ovlp(&b->olist);///must be here + gl_chain_flter(&b->olist, &b->correct, &(s->sps[tid]), bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, &phase); + + // fprintf(stderr, "[M::%s] rid::%ld, len::%lu, name::%.*s, phase::%u\n", __func__, s->id+i, s->len[i], + // (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a, phase); + if(phase && gen_shared_intervals(&b->olist, s->uu, s->uopt, winLen, &b->r_buf, &(bl->lo))) { + filter_topN(&b->olist, &(bl->lo), s->len[i], winLen, UL_TOPN, bl); + // update_shared_intervals(&b->olist, s->uu, s->uopt, NULL, &b->ovlp_read, &b->r_buf, &(s->sps[tid]), s->len[i], winLen, &(bl->lo), s->id+i); + + copy_asg_arr(b0, b->hap.snp_srt); copy_asg_arr(b1, s->sps[tid]); copy_asg_arr(b2, b->r_buf.a); + // update_shared_intervals(&b->olist, s->uu, s->uopt, NULL, &b->ovlp_read, &b0, &b1, &b2, s->len[i], winLen, &(bl->lo), s->id+i); + update_sketch_trace(&b->olist, s->uu, s->uopt, NULL, &b->ovlp_read, &b0, &b1, &b2, s->len[i], winLen, &(bl->lo), s->id+i, MAX_LGAP(s->len[i]), s->opt->diff_ec_ul); + copy_asg_arr(b->hap.snp_srt, b0); copy_asg_arr(s->sps[tid], b1); copy_asg_arr(b->r_buf.a, b2); + + ul_lalign(&b->olist, &b->clist, s->uu, s->uopt, s->seq[i], s->len[i], &b->self_read, &b->ovlp_read, + &b->correct, &b->exz, &b->hap, &b->r_buf, aux_o, s->opt->diff_ec_ul, winLen, &(bl->lo), s->id+i, s->opt->k, &(s->sps[tid]), s->mm, &(s->mk[tid]), NULL); + // ul_lalign_old_ed(&b->olist, &b->clist, s->uu, s->seq[i], s->len[i], &b->self_read, &b->ovlp_read, + // &b->correct, &b->hap, &b->r_buf, s->opt->diff_ec_ul, winLen, 0, NULL); + // fprintf(stderr, "\n[M::%s] b->olist.length::%lu, ton::%ld\n", __func__, + // b->olist.length, ton); + ///recover alignments + for (k = b->olist.length; k < ton; k++) { + b->olist.list[k].w_list.n = 0; + p.x_start = b->olist.list[k].x_pos_s; + p.x_end = b->olist.list[k].x_pos_e+1; + p.clen = b->olist.list[k].non_homopolymer_errors; + kv_push(window_list, b->olist.list[k].w_list, p); + b->olist.list[k].align_length = 0; + b->olist.list[k].overlapLen = b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; + // fprintf(stderr, "[M::%s]\tutg%.6u%c\txl::%lu\tx::[%u,\t%u)\t%c\tyl::%u\ty::[%u,\t%u)\tsec::%u\n", + // __func__, b->olist.list[k].y_id + 1, "lc"[s->uu->ug->u.a[b->olist.list[k].y_id].circ], + // s->len[i], b->olist.list[k].x_pos_s, b->olist.list[k].x_pos_e+1, "+-"[b->olist.list[k].y_pos_strand], + // s->uu->ug->u.a[b->olist.list[k].y_id].len, b->olist.list[k].y_pos_s, b->olist.list[k].y_pos_e+1, + // b->olist.list[k].non_homopolymer_errors); + } + b->olist.length = ton; + } else { + for (k = 0; k < b->olist.length; k++) { + b->olist.list[k].w_list.n = 0; + p.x_start = b->olist.list[k].x_pos_s; + p.x_end = b->olist.list[k].x_pos_e+1; + p.clen = 0; + kv_push(window_list, b->olist.list[k].w_list, p); + b->olist.list[k].align_length = b->olist.list[k].overlapLen = + b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; + b->olist.list[k].non_homopolymer_errors = 0; + } + } + + // prt_overlap_region_alloc_ol(&(b->olist), s->id+i); + + + gl_chain(s->buf[tid], &(UL_INF.a[s->id+i]), &b->olist, &(b->clist.chainDP), &b->hap, &(s->sps[tid]), bl, &(s->gdp[tid]), s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, tid, NULL); + + // exit(1); + // uint64_t k; + // for (k = 0; k < b->olist.length; k++) { + // if(b->olist.list[k].is_match == 1) b->num_correct_base += b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; + // if(b->olist.list[k].is_match == 2) b->num_recorrect_base += b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; + // } + + + // gl_chain_refine(&b->olist, &b->correct, &b->hap, bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], km); + // gl_chain_refine_advance_combine(s->buf[tid], &(UL_INF.a[s->id+i]), &b->olist, &b->correct, &b->hap, &(s->sps[tid]), bl, &(s->gdp[tid]), s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, tid, NULL); + // return; + // b->num_read_base += b->self_read.length; + // b->num_correct_base += b->correct.corrected_base; + // b->num_recorrect_base += b->round2.dumy.corrected_base; + + if(UL_INF.a[s->id+i].dd == 1 || UL_INF.a[s->id+i].dd == 2) { + b->num_correct_base++; + } + if(UL_INF.a[s->id+i].dd != 3) { + free(s->seq[i]); s->seq[i] = NULL; + } + s->hab[tid]->num_read_base++; + // fprintf(stderr, "[M::%s] rid:%ld, dd:%u\n", __func__, s->id+i, UL_INF.a[s->id+i].dd); + // int64_t mem[6], mem_hab[6]; + // if(get_utepdat_t_mem_tid(s, tid, mem, mem_hab)>((int64_t)5*(int64_t)1073741824)) { + // fprintf(stderr, "[M::%s::tid->%d::rid->%ld] buffer[0]: %.3fGB(%.3fGB::%.3fGB::%.3fGB::%.3fGB::%.3fGB), buffer[1]: %.3fGB, buffer[2]: %.3fGB, buffer[3]: %.3fGB, buffer[4]: %.3fGB, buffer[5]: %.3fGB\n", + // __func__, tid, i, mem[0]/1073741824.0, + // mem_hab[0]/1073741824.0, mem_hab[1]/1073741824.0, mem_hab[2]/1073741824.0, + // mem_hab[3]/1073741824.0, mem_hab[4]/1073741824.0, + // mem[1]/1073741824.0, mem[2]/1073741824.0, + // mem[3]/1073741824.0, mem[4]/1073741824.0, mem[5]/1073741824.0); + // } + + // align = kv_ul_ov_t_statistics(&(bl->tk), i, &(b->num_recorrect_base)); + // if(align == s->len[i]) { + // free(s->seq[i]); s->seq[i] = NULL; + // } + // b->num_correct_base += align; + + // uint64_t k; + // b->num_read_base += overlap_statistics(&b->olist, NULL, NULL, 1); + // for (k = 0; k < bl->tk.n; k++) { + // if(bl->tk.a[k].sec == 0) b->num_correct_base += bl->tk.a[k].qe - bl->tk.a[k].qs; + // if(bl->tk.a[k].sec > 0) b->num_recorrect_base += bl->tk.a[k].qe - bl->tk.a[k].qs; + // } + // for (k = 0; k < bl->lo.n; k++) { + // b->num_read_base += bl->lo.a[k].qe - bl->lo.a[k].qs; + // } + + // uint32_t l1 = overlap_statistics(&b->olist, s->uu->ug, 1), l2 = overlap_statistics(&b->olist, s->uu->ug, 2); + // + // if(l1 == 0 && l2 > 0) fprintf(stderr, "[M::%s::%lu::no_match]\n", UL_INF.nid.a[s->id+i].a, s->len[i]); + // fprintf(stderr, "[M::%s::%lu::] l1->%u; l2->%u\n", UL_INF.nid.a[s->id+i].a, s->len[i], l1, l2); + // fprintf(stderr, "[M::%s::rid->%ld] done\n", __func__, s->id+i); + // exit(1); +} + + +uint32_t ck_ul_alignment(ul_vec_t *x) +{ + uc_block_t *a = x->bb.a, *p, *z0, *z1; uint64_t a_n = x->bb.n, k, rlen = x->rlen; + for (k = 0; k < a_n; k++) { + p = &(a[k]); + if(p->base) continue; + if(p->qs > rlen || p->qe > rlen || p->qs > p->qe) break; + if(p->pidx != (uint32_t)-1) { + if(a[p->pidx].aidx == (uint32_t)-1 || a[p->pidx].aidx != k) break; + if(p->pidx >= k) break; + z1 = p; z0 = &(a[p->pidx]); + if(!(z1->qs >= z0->qs && z1->qe >= z0->qe)) break; + } + + if(p->aidx != (uint32_t)-1) { + if(a[p->aidx].pidx == (uint32_t)-1 || a[p->aidx].pidx != k) break; + if(p->aidx <= k) break; + z0 = p; z1 = &(a[p->aidx]); + if(!(z1->qs >= z0->qs && z1->qe >= z0->qe)) break; + } + } + if(k >= a_n) return 1; + return 0; +} + +uint32_t filter_sec_trans_ovlp(ul_ov_t *a, uint32_t a_n, uint32_t qn, double sec_rate) +{ + if(a_n <= 0) return a_n; + uint32_t i, m, k, oz, op, ovlp, min_sc, max_sc; int64_t nw[2], ml, uml, msc; ul_ov_t *z, *p, t; + for (i = m = 0; i < a_n; i++) { + z = &(a[i]); z->qn = 0; + ml = z->qe - z->qs; uml = z->sec; ml -= uml; + nw[0] = (ml*CHAIN_MATCH) - (uml*CHAIN_UNMATCH); + ml = z->te - z->ts; uml = z->sec; ml -= uml; + nw[1] = (ml*CHAIN_MATCH) - (uml*CHAIN_UNMATCH); + msc = MIN(nw[0], nw[1]); + if(msc <= 0) continue; + if(msc >= UINT32_MAX) msc = UINT32_MAX; + z->qn = msc; + a[m++] = (*z); + } + a_n = m; + if(a_n <= 0) return a_n; + radix_sort_ul_ov_srt_qn(a, a + a_n);//sort by scores + for (i = 0, m = (a_n>>1); i < m; i++) { + t = a[i]; a[i] = a[a_n-i-1]; a[a_n-i-1] = t; + } + + for (k = m = 0; k < a_n; k++) { + z = &a[k]; oz = z->qe - z->qs; ///current chain + for (i = 0; i < m; i++) { + p = &(a[i]); + ovlp = ((MIN(z->qe, p->qe) > MAX(z->qs, p->qs))? (MIN(z->qe, p->qe) - MAX(z->qs, p->qs)):0); + if(ovlp == 0) continue; + op = p->qe - p->qs; + min_sc = MIN(p->qn, z->qn); max_sc = MAX(p->qn, z->qn); + if(min_sc <= (max_sc*0.95)) { + if((ovlp > (oz*sec_rate)) || (ovlp > (op*sec_rate))) break; + } + } + if(i < m) continue; + a[m++] = a[k]; + } + a_n = m; + for (k = 0; k < a_n; k++) a[k].qn = qn; + return a_n; +} + +uint32_t trans_ovlp_connect(ul_ov_t *p, ma_ug_t *ug) +{ + uint32_t v = p->qn<<1, w = (p->tn<<1) + ((uint32_t)p->rev), i, dg = (uint32_t)-1, da, dif, mm; + asg_arc_t *av = asg_arc_a(ug->g, v); uint32_t nv = asg_arc_n(ug->g, v); + for (i = 0; i < nv; i++) { + if(av[i].del || av[i].v != w) continue; + dg = av[i].ol; + break; + } + // if(i >= nv) return 1; + if(i < nv) { + da = (p->qe - p->qs); + dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; + if(dif <= mm) return 0; + + da = (p->te - p->ts); + dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; + if(dif <= mm) return 0; + } + + + v ^= 1; w ^= 1; dg = (uint32_t)-1; + av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); + for (i = 0; i < nv; i++) { + if(av[i].del || av[i].v != w) continue; + dg = av[i].ol; + break; + } + if(i < nv) { + da = (p->qe - p->qs); + dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; + if(dif <= mm) return 0; + + da = (p->te - p->ts); + dif = (dg>da? dg-da:da-dg); mm = MAX(dg, da); mm *= 0.06; if(mm < 8) mm = 8; + if(dif <= mm) return 0; + } + + return 1; +} + +uint64_t filter_by_reliable_ovlp0(u_trans_t *a, uint64_t a_n, uint64_t s, uint64_t e, double sec_rate) +{ + uint64_t k, ovlp; + for (k = 0; k < a_n; k++) { + if(a[k].del) continue; + if(a[k].f == RC_0 || a[k].f == RC_1) { + ovlp = ((MIN(a[k].qe, e) > MAX(a[k].qs, s))? (MIN(a[k].qe, e)-MAX(a[k].qs, s)):0); + if(ovlp == 0) continue; + if((ovlp) && (ovlp > ((e-s)*sec_rate))) return 1; + } + } + return 0; +} + +void filter_by_reliable_ovlp(uint32_t id, kv_u_trans_t *idx, st_mt_t *sp, overlap_region_alloc* ol, const ul_idx_t *udb, double sec_rate, uint32_t pre_filter) +{ + u_trans_t *a; uint64_t n, k, l, s, e, s0, e0, z, ov, rr; overlap_region *m, t; + a = u_trans_a(*idx, id); n = u_trans_n(*idx, id); + for (k = sp->n = 0; k < n; k++) { + if(a[k].del) continue; + if(a[k].f == RC_0 || a[k].f == RC_1) { + z = a[k].tn; z <<= 1; z |= a[k].rev; z <<= 32; z |= k; + kv_push(uint64_t, *sp, z); + // fprintf(stderr, "***utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", + // a[k].qn+1, "lc"[udb->ug->u.a[a[k].qn].circ], udb->ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], + // a[k].tn+1, "lc"[udb->ug->u.a[a[k].tn].circ], udb->ug->u.a[a[k].tn].len, a[k].ts, a[k].te); + } + } + if(!sp->n) return; + for (k = 0; k < ol->length; k++) { + if((!pre_filter) || (ol->list[k].x_pos_strand)) {///corresponding to the overlaps within idx + z = ol->list[k].y_id; z <<= 1; z |= ol->list[k].y_pos_strand; + z <<= 32; z |= k; z |= ((uint64_t)0x80000000); + kv_push(uint64_t, *sp, z); + ol->list[k].x_pos_strand = 0; + } + } + radix_sort_gfa64(sp->a, sp->a + sp->n); + for (k = 1, l = 0; k <= sp->n; k++) { + if(k == sp->n || (sp->a[l]>>32)!=(sp->a[k]>>32)) { + if((k - l > 1) && (!(sp->a[l]&((uint64_t)0x80000000)))) { + for (z = l; z < k; z++) { + if(!(sp->a[z]&((uint64_t)0x80000000))) continue; + rr = (uint32_t)(sp->a[z]-((uint64_t)0x80000000)); + ol->list[rr].x_pos_strand = 1; + } + } + l = k; + } + } + + for (k = sp->n = 0; k < n; k++) { + if(a[k].del) continue; + if(a[k].f == RC_0 || a[k].f == RC_1) { + kv_push(uint64_t, *sp, (((uint64_t)a[k].qs)<<32)|((uint64_t)a[k].qe)); + } + } + if(sp->n > 1) { + radix_sort_gfa64(sp->a, sp->a + sp->n); + for (k = z = 0; k < sp->n; k++) { + s = sp->a[k]>>32; e = (uint32_t)sp->a[k]; + if(z > 0 && s <= ((uint32_t)sp->a[z-1])) { + if(e > ((uint32_t)sp->a[z-1])) { + sp->a[z-1] >>= 32; sp->a[z-1] <<= 32; sp->a[z-1] |= e; + } + } else { + sp->a[z++] = sp->a[k]; + } + } + sp->n = z; + } + + for (k = rr = 0; k < ol->length; k++) { + m = &(ol->list[k]); + if(m->x_pos_strand == 0) { + s = m->x_pos_s; e = m->x_pos_e + 1; l = 0; + for (z = 0; z < sp->n; z++) { + s0 = sp->a[z]>>32; e0 = (uint32_t)sp->a[z]; + ov = ((MIN(e, e0) > MAX(s, s0))? (MIN(e, e0) - MAX(s, s0)):0); + l += ov; + if((l) && (l > ((e-s)*sec_rate))) break; + } + if(z < sp->n) { + // fprintf(stderr, ">[M::%s] utg%.6u%c -> utg%.6u%c\n", __func__, id+1, "lc"[udb->ug->u.a[id].circ], + // m->y_id+1, "lc"[udb->ug->u.a[m->y_id].circ]); + continue;///filter by the overlaps of id/m->x_id + } + ///filter by the overlaps of m->y_id + if(filter_by_reliable_ovlp0(u_trans_a(*idx, m->y_id), u_trans_n(*idx, m->y_id), + m->y_pos_strand?udb->ug->u.a[m->y_id].len-m->y_pos_e-1:m->y_pos_s, + m->y_pos_strand?udb->ug->u.a[m->y_id].len-m->y_pos_s:m->y_pos_e+1, sec_rate)) { + // fprintf(stderr, "<[M::%s] utg%.6u%c -> utg%.6u%c\n", __func__, id+1, "lc"[udb->ug->u.a[id].circ], + // m->y_id+1, "lc"[udb->ug->u.a[m->y_id].circ]); + continue; + } + } + m->x_pos_strand = 0; + if(rr != k) { + t = ol->list[k]; + ol->list[k] = ol->list[rr]; + ol->list[rr] = t; + } + // fprintf(stderr, ">>>utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", + // ol->list[rr].x_id+1, "lc"[udb->ug->u.a[ol->list[rr].x_id].circ], udb->ug->u.a[ol->list[rr].x_id].len, + // ol->list[rr].x_pos_s, ol->list[rr].x_pos_e+1, "+-"[ol->list[rr].y_pos_strand], + // ol->list[rr].y_id+1, "lc"[udb->ug->u.a[ol->list[rr].y_id].circ], udb->ug->u.a[ol->list[rr].y_id].len, + // ol->list[rr].y_pos_s, ol->list[rr].y_pos_e+1); + rr++; + } + // if(id == 1576) { + // fprintf(stderr, "[M::%s] utg%.6ul, ol->length0::%lu, ol->length::%lu\n", __func__, id+1, ol->length, rr); + // } + ol->length = rr; +} + +static void worker_for_trans_ovlp(void *data, long i, int tid) // callback for kt_for() +{ + ug_trans_t *s = (ug_trans_t*)data; + ha_ovec_buf_t *b = s->hab[tid]; + kv_ul_ov_t *bl = &(s->ll[tid].tk); + int64_t winLen = MIN((((double)THRESHOLD_MAX_SIZE)/s->diff_ec_ul), WINDOW); + uint32_t high_occ = asm_opt.polyploidy + 1, k; uint64_t cnt, bn; + overlap_region *aux_o = NULL; ul_ov_t *p; + char *seq = s->ug->u.a[i].s; + int64_t len = s->ug->u.a[i].len; + if((!s->is_ovlp) && (s->is_cnt)) s->idx_n.a[i] = 0; + if(IF_HOM(i, (*(s->bub))) || s->ug->g->seq[i].del) return; + + // asprintf(&as, "\n[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); + // push_vlog(&(overall_zdbg->a[s->id+i]), as); free(as); as = NULL; + + if(!s->is_ovlp) { + if(s->is_cnt) { + s->idx_n.a[i] = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, + s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, NULL, 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); + // fprintf(stderr, "-1-[M::%s] rid::%ld, is_ovlp::%d, is_cnt::%d, len::%d, str::%u, s->idx_n.a[i]::%lu\n", + // __func__, i, s->is_ovlp, s->is_cnt, len, !!seq, s->idx_n.a[i]); + } else { + cnt = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, + s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); + assert(cnt == ((s->idx_n.a[i+1]-s->idx_n.a[i]))); + // if(i == 1576 || i == 2879) { + // fprintf(stderr, "-2-[M::%s] rid::%ld, is_ovlp::%d, is_cnt::%d, len::%ld, str::%u, cnt::%lu\n", + // __func__, i, s->is_ovlp, s->is_cnt, len, !!seq, cnt); + // } + } + return; + } else { + cnt = ((s->idx_n.a[i+1]-s->idx_n.a[i])); + // fprintf(stderr, "\n-0-[M::%s] utg%.6u%c, rid::%ld, is_ovlp::%d, is_cnt::%d, len::%ld, str::%u, cnt::%lu, diff::%f\n", + // __func__, (uint32_t)i+1, "lc"[s->ug->u.a[i].circ], i, s->is_ovlp, s->is_cnt, len, (uint32_t)(!!seq), cnt, s->diff_ec_ul); + ///note: high_occ is different + ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), &b->olist, &b->clist, s->bw_thres, s->bw_thres_double, + s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], cnt, s->srt_a.a, s->srt_a.n, s->mini_cut, s->chain_cut, NULL); + } + + filter_by_reliable_ovlp(i, s->filter, &(b->sp), &b->olist, &(s->udb), s->sec_cutoff, 0); + // fprintf(stderr, "-0-[M::%s] rid::%ld, is_ovlp::%d, is_cnt::%d, len::%ld, str::%u\n", + // __func__, i, s->is_ovlp, s->is_cnt, len, !!seq); + clear_Cigar_record(&b->cigar1); clear_Round2_alignment(&b->round2); + + ug_lalign(&b->olist, &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, + &b->correct, &b->exz, aux_o, s->diff_ec_ul, winLen, i, s->k, s->chain_cut, NULL); + + aux_o = gen_aux_ovlp(&b->olist);///must be here + + ug_lalign(&b->olist, &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, + &b->correct, &b->exz, aux_o, s->diff_ec_ul, winLen, i, s->k, s->chain_cut, NULL); + if(b->olist.length > 0) { + cnt = bl->n + b->olist.length; kv_resize(ul_ov_t, (*bl), cnt); + for (k = 0, bn = bl->n; k < b->olist.length; k++) { + // if(b->olist.list[k].non_homopolymer_errors == 0) continue;///exact match is not trans + kv_pushp(ul_ov_t, (*bl), &p); + p->qn = i; p->tn = b->olist.list[k].y_id; p->el = 1; + p->sec = b->olist.list[k].non_homopolymer_errors; + p->rev = b->olist.list[k].y_pos_strand; + p->qs = b->olist.list[k].x_pos_s; p->qe = b->olist.list[k].x_pos_e+1; + // p->ts = b->olist.list[k].y_pos_s; p->te = b->olist.list[k].y_pos_e+1; + if(p->rev) { + p->ts = s->udb.ug->u.a[p->tn].len - (b->olist.list[k].y_pos_e+1); + p->te = s->udb.ug->u.a[p->tn].len - b->olist.list[k].y_pos_s; + } else { + p->ts = b->olist.list[k].y_pos_s; + p->te = b->olist.list[k].y_pos_e+1; + } + // if(i == 5) + // { + // fprintf(stderr, "***utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\ti::%ld\n", + // p->qn+1, "lc"[s->ug->u.a[p->qn].circ], s->ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], + // p->tn+1, "lc"[s->ug->u.a[p->tn].circ], s->ug->u.a[p->tn].len, p->ts, p->te, i); + // } + if(!trans_ovlp_connect(p, s->ug)) { + bl->n--; + } + // else { + // if(i == 5) + // { + // fprintf(stderr, ">>>utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\ti::%ld\n", + // p->qn+1, "lc"[s->ug->u.a[p->qn].circ], s->ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], + // p->tn+1, "lc"[s->ug->u.a[p->tn].circ], s->ug->u.a[p->tn].len, p->ts, p->te, i); + // } + // } + } + cnt = filter_sec_trans_ovlp(bl->a+bn, bl->n-bn, i, s->sec_cutoff) + bn; + bl->n = cnt; + } + + + // fprintf(stderr, "[M::%s] rid:%ld, dd:%u\n", __func__, s->id+i, UL_INF.a[s->id+i].dd); + // int64_t mem[6], mem_hab[6]; + // if(get_utepdat_t_mem_tid(s, tid, mem, mem_hab)>((int64_t)5*(int64_t)1073741824)) { + // fprintf(stderr, "[M::%s::tid->%d::rid->%ld] buffer[0]: %.3fGB(%.3fGB::%.3fGB::%.3fGB::%.3fGB::%.3fGB), buffer[1]: %.3fGB, buffer[2]: %.3fGB, buffer[3]: %.3fGB, buffer[4]: %.3fGB, buffer[5]: %.3fGB\n", + // __func__, tid, i, mem[0]/1073741824.0, + // mem_hab[0]/1073741824.0, mem_hab[1]/1073741824.0, mem_hab[2]/1073741824.0, + // mem_hab[3]/1073741824.0, mem_hab[4]/1073741824.0, + // mem[1]/1073741824.0, mem[2]/1073741824.0, + // mem[3]/1073741824.0, mem[4]/1073741824.0, mem[5]/1073741824.0); + // } +} + + +void filter_by_reliable_ovlp_adv(uint32_t id, kv_u_trans_t *idx, st_mt_t *sp, overlap_region_alloc* ol, const ul_idx_t *udb, double sec_rate, uint64_t avoid_dup_aln, +uint64_t dedup_by_reliable_ovlp, uint64_t *occ1) +{ + (*occ1) = 0; + u_trans_t *a; uint64_t n, k, l, s, e, s0, e0, z, ov, rr, r1, spn; overlap_region *m, t; + a = u_trans_a(*idx, id); n = u_trans_n(*idx, id); + if(avoid_dup_aln) { + kv_resize(uint64_t, *sp, (ol->length)+n); + for (k = sp->n = 0; k < n; k++) { + if(a[k].del) continue; + // if(id == 160) { + // fprintf(stderr, "[rid::%u]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\n", id, + // a[k].qn+1, "lc"[udb->ug->u.a[a[k].qn].circ], udb->ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], + // a[k].tn+1, "lc"[udb->ug->u.a[a[k].tn].circ], udb->ug->u.a[a[k].tn].len, a[k].ts, a[k].te, a[k].nw, a[k].f); + // } + if(a[k].f == RC_0 || a[k].f == RC_1) { + z = a[k].tn; z <<= 1; z |= a[k].rev; z <<= 32; + kv_push(uint64_t, *sp, z); + } + } + if(sp->n > 0) { + for (k = 0; k < ol->length; k++) { + z = ol->list[k].y_id; z <<= 1; z |= ol->list[k].y_pos_strand; + z <<= 32; z |= k; z |= ((uint64_t)0x80000000); + kv_push(uint64_t, *sp, z); + } + + radix_sort_gfa64(sp->a, sp->a + sp->n); + for (k = 1, l = 0, rr = 0; k <= sp->n; k++) { + if(k == sp->n || (sp->a[l]>>32)!=(sp->a[k]>>32)) { + if((k - l > 1) && (!(sp->a[l]&((uint64_t)0x80000000)))) {///overlap within bck + for (z = l; z < k; z++) { + if(sp->a[z]&((uint64_t)0x80000000)) { + ol->list[(uint32_t)(sp->a[z]-((uint64_t)0x80000000))].y_id = ((uint32_t)-1); + rr++; + } + } + } + l = k; + } + } + + if(rr > 0) { + for (k = rr = 0; k < ol->length; k++) { + if(ol->list[k].y_id == ((uint32_t)-1)) continue; + if(rr != k) { + t = ol->list[rr]; + ol->list[rr] = ol->list[k]; + ol->list[k] = t; + } + rr++; + } + ol->length = rr; + } + } + } + + sp->n = 0; + if(dedup_by_reliable_ovlp) { + for (k = sp->n = 0; k < n; k++) { + if(a[k].del) continue; + if(a[k].f == RC_0 || a[k].f == RC_1) { + kv_push(uint64_t, *sp, (((uint64_t)a[k].qs)<<32)|((uint64_t)a[k].qe)); + } + } + if(sp->n > 1) { + radix_sort_gfa64(sp->a, sp->a + sp->n); + for (k = z = 0; k < sp->n; k++) { + s = sp->a[k]>>32; e = (uint32_t)sp->a[k]; + if(z > 0 && s <= ((uint32_t)sp->a[z-1])) { + if(e > ((uint32_t)sp->a[z-1])) { + sp->a[z-1] >>= 32; sp->a[z-1] <<= 32; sp->a[z-1] |= e; + } + } else { + sp->a[z++] = sp->a[k]; + } + } + sp->n = z; + } + } + + for (k = rr = r1 = 0, spn = sp->n; k < ol->length; k++) { + m = &(ol->list[k]); + // if(id == 160) { + // fprintf(stderr, "[M::%s] utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\txstr::%u\n", __func__, + // ol->list[k].x_id+1, "lc"[udb->ug->u.a[ol->list[k].x_id].circ], udb->ug->u.a[ol->list[k].x_id].len, + // ol->list[k].x_pos_s, ol->list[k].x_pos_e+1, "+-"[ol->list[k].y_pos_strand], + // ol->list[k].y_id+1, "lc"[udb->ug->u.a[ol->list[k].y_id].circ], udb->ug->u.a[ol->list[k].y_id].len, + // ol->list[k].y_pos_s, ol->list[k].y_pos_e+1, ol->list[k].x_pos_strand); + // } + if((dedup_by_reliable_ovlp) && (m->x_pos_strand == 0)) { + s = m->x_pos_s; e = m->x_pos_e + 1; l = 0; + for (z = 0; z < spn; z++) { + s0 = sp->a[z]>>32; e0 = (uint32_t)sp->a[z]; + ov = ((MIN(e, e0) > MAX(s, s0))? (MIN(e, e0) - MAX(s, s0)):0); + l += ov; + if((l) && (l > ((e-s)*sec_rate))) break; + } + ///filter by the overlaps of id/m->x_id + if(z < spn) continue; + ///filter by the overlaps of m->y_id + if(filter_by_reliable_ovlp0(u_trans_a(*idx, m->y_id), u_trans_n(*idx, m->y_id), + m->y_pos_strand?udb->ug->u.a[m->y_id].len-m->y_pos_e-1:m->y_pos_s, + m->y_pos_strand?udb->ug->u.a[m->y_id].len-m->y_pos_s:m->y_pos_e+1, sec_rate)) { + continue; + } + } + // else { + // if(id == 7) { + // fprintf(stderr, "[M::%s] utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, + // ol->list[k].x_id+1, "lc"[udb->ug->u.a[ol->list[k].x_id].circ], udb->ug->u.a[ol->list[k].x_id].len, + // ol->list[k].x_pos_s, ol->list[k].x_pos_e+1, "+-"[ol->list[k].y_pos_strand], + // ol->list[k].y_id+1, "lc"[udb->ug->u.a[ol->list[k].y_id].circ], udb->ug->u.a[ol->list[k].y_id].len, + // ol->list[k].y_pos_s, ol->list[k].y_pos_e+1); + // } + // } + if(rr != k) { + t = ol->list[k]; + ol->list[k] = ol->list[rr]; + ol->list[rr] = t; + } + if(ol->list[rr].x_pos_strand) { + ol->list[rr].x_pos_strand = 0; + if(r1 != rr) { + t = ol->list[r1]; + ol->list[r1] = ol->list[rr]; + ol->list[rr] = t; + } + r1++; + } + // fprintf(stderr, ">>>utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", + // ol->list[rr].x_id+1, "lc"[udb->ug->u.a[ol->list[rr].x_id].circ], udb->ug->u.a[ol->list[rr].x_id].len, + // ol->list[rr].x_pos_s, ol->list[rr].x_pos_e+1, "+-"[ol->list[rr].y_pos_strand], + // ol->list[rr].y_id+1, "lc"[udb->ug->u.a[ol->list[rr].y_id].circ], udb->ug->u.a[ol->list[rr].y_id].len, + // ol->list[rr].y_pos_s, ol->list[rr].y_pos_e+1); + rr++; + } + // if(id == 1576) { + // fprintf(stderr, "[M::%s] utg%.6ul, ol->length0::%lu, ol->length::%lu\n", __func__, id+1, ol->length, rr); + // } + ol->length = rr; (*occ1) = r1; +} + +void prt_split_ovs(overlap_region_alloc* ol, ma_ug_t *ug, uint64_t ol_h, uint64_t ol_l, const char* cmd) +{ + uint64_t k; overlap_region *z; + fprintf(stderr, "[M::%s] %s\tol->length::%lu, ol_h::%lu, ol_l::%lu\n", __func__, cmd, ol->length, ol_h, ol_l); + // assert((ol_h+ol_l) == ol->length); + for (k = 0; k < ol_h; k++) { + z = &(ol->list[k]); + fprintf(stderr, "oh->[%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\twn::%u\taln::%u\ted::%u\n", cmd, + z->x_id+1, "lc"[ug->u.a[z->x_id].circ], ug->u.a[z->x_id].len, + z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + z->y_id+1, "lc"[ug->u.a[z->y_id].circ], ug->u.a[z->y_id].len, + z->y_pos_s, z->y_pos_e+1, (uint32_t)z->w_list.n, z->align_length, z->non_homopolymer_errors); + } + + for (; k < ol->length; k++) { + z = &(ol->list[k]); + fprintf(stderr, "ol->[%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\twn::%u\taln::%u\ted::%u\n", cmd, + z->x_id+1, "lc"[ug->u.a[z->x_id].circ], ug->u.a[z->x_id].len, + z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + z->y_id+1, "lc"[ug->u.a[z->y_id].circ], ug->u.a[z->y_id].len, + z->y_pos_s, z->y_pos_e+1, (uint32_t)z->w_list.n, z->align_length, z->non_homopolymer_errors); + } +} + + +uint64_t split_ug_lalign(uint64_t ol_h, overlap_region_alloc* ol, double errh, double errl, + Candidates_list *cl, const ul_idx_t *uref, const ug_opt_t *uopt, + char *qstr, uint64_t ql, UC_Read* qu, UC_Read* tu, Correct_dumy* dumy, bit_extz_t *exz, + overlap_region *aux_o, int64_t sid, uint64_t khit, uint64_t chain_cut, void *km) +{ + uint64_t ol_l = ol->length - ol_h, on0, k, m; int64_t wl; double erate; overlap_region t; + // if(sid == 57) fprintf(stderr, "[M::%s] errh::%f, errl::%f\n", __func__, errh, errl); + // if(sid == 57) prt_split_ovs(ol, uref->ug, ol_h, ol_l, "st"); + if(ol_h) { + erate = errh; on0 = ol->length; + wl = MIN((((double)THRESHOLD_MAX_SIZE)/erate), WINDOW); + ol->length = ol_h; + ug_lalign(ol, cl, uref, uopt, qstr, ql, qu, tu, dumy, exz, aux_o, erate, wl, sid, khit, chain_cut, km); + for (k = ol_h, m = ol->length; k < on0; k++) {///move ovlps with ol_l + if(k != m) { + t = ol->list[k]; + ol->list[k] = ol->list[m]; + ol->list[m] = t; + } + m++; + } + ol_h = ol->length; ol->length = m; ol_l = ol->length - ol_h; + } + // if(sid == 57) prt_split_ovs(ol, uref->ug, ol_h, ol_l, "mi"); + if(ol_l) { + erate = errl; on0 = ol->length; + wl = MIN((((double)THRESHOLD_MAX_SIZE)/erate), WINDOW); + if(ol_h) {///swap ol_h and ol_l + for (k = ol_h, m = 0; k < ol->length; k++) { + if(k != m) { + t = ol->list[k]; + ol->list[k] = ol->list[m]; + ol->list[m] = t; + } + m++; + } + } + // if(sid == 57) prt_split_ovs(ol, uref->ug, ol_h, ol_l, "sw"); + ol->length = ol_l; + ug_lalign(ol, cl, uref, uopt, qstr, ql, qu, tu, dumy, exz, aux_o, erate, wl, sid, khit, chain_cut, km); + // if(sid == 57) { + // fprintf(stderr, "[M::%s::]\ton0::%lu\tol_l::%lu\tol_h::%lu\tol->length::%lu\n", __func__, + // on0, ol_l, ol_h, ol->length); + // prt_split_ovs(ol, uref->ug, ol_h, ol_l, "u0"); + // } + for (k = ol_l, m = ol->length; k < on0; k++) {///move ovlps with ol_h + if(k != m) { + t = ol->list[k]; + ol->list[k] = ol->list[m]; + ol->list[m] = t; + } + m++; + } + ol_l = ol->length; ol->length = m; ol_h = ol->length - ol_l; + // if(sid == 57) prt_split_ovs(ol, uref->ug, ol_h, ol_l, "u1"); + if(ol_l) {///swap ol_h and ol_l + for (k = ol_l, m = 0; k < ol->length; k++) { + if(k != m) { + t = ol->list[k]; + ol->list[k] = ol->list[m]; + ol->list[m] = t; + } + m++; + } + } + } + // if(sid == 57) prt_split_ovs(ol, uref->ug, ol_h, ol_l, "ed"); + return ol_h; +} + +uint32_t test_het_aln(ma_ug_t *ug, uint64_t rid, u_trans_t *a, uint64_t a_n, st_mt_t *sp, overlap_region_alloc* ol, uint64_t len) +{ + uint64_t k, s, e, z, l = 0; + for (k = sp->n = 0; k < a_n; k++) { + if(a[k].del) continue; + // if(rid == 56 || rid == 160) { + // fprintf(stderr, "[rid::%lu]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\n", rid, + // a[k].qn+1, "lc"[ug->u.a[a[k].qn].circ], ug->u.a[a[k].qn].len, a[k].qs, a[k].qe, "+-"[a[k].rev], + // a[k].tn+1, "lc"[ug->u.a[a[k].tn].circ], ug->u.a[a[k].tn].len, a[k].ts, a[k].te, a[k].nw, a[k].f); + // } + kv_push(uint64_t, *sp, (((uint64_t)a[k].qs)<<32)|((uint64_t)a[k].qe)); + } + for (k = 0; k < ol->length; k++) { + // if(b->olist.list[k].non_homopolymer_errors == 0) continue;///exact match is not trans + s = ol->list[k].x_pos_s; e = ol->list[k].x_pos_e+1; + kv_push(uint64_t, *sp, (((uint64_t)s)<<32)|((uint64_t)e)); + } + + if(sp->n > 1) { + radix_sort_gfa64(sp->a, sp->a + sp->n); + for (k = z = 0; k < sp->n; k++) { + s = sp->a[k]>>32; e = (uint32_t)sp->a[k]; + if(z > 0 && s <= ((uint32_t)sp->a[z-1])) { + if(e > ((uint32_t)sp->a[z-1])) { + sp->a[z-1] >>= 32; sp->a[z-1] <<= 32; sp->a[z-1] |= e; + } + } else { + sp->a[z++] = sp->a[k]; + } + } + sp->n = z; + } + for (k = l = 0; k < sp->n; k++) l += (((uint32_t)sp->a[k]) - (sp->a[k]>>32)); + + // if(rid == 7) { + // fprintf(stderr, "\n[M::%s] utg%.6lu%c, rid::%lu, l::%lu, len::%lu, sp->n::%u\n", + // __func__, rid+1, "lc"[ug->u.a[rid].circ], rid, l, len, (uint32_t)sp->n); + // for (k = 0; k < a_n; k++) { + // if(a[k].del) continue; + // fprintf(stderr, "0\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\tf::%u\n", + // a[k].qn+1, "lc"[ug->u.a[a[k].qn].circ], ug->u.a[a[k].qn].len, + // a[k].qs, a[k].qe, "+-"[a[k].rev], + // a[k].tn+1, "lc"[ug->u.a[a[k].tn].circ], ug->u.a[a[k].tn].len, + // a[k].ts, a[k].te, a[k].nw, a[k].f); + // } + // for (k = 0; k < ol->length; k++) { + // overlap_region *z = &(ol->list[k]); + // fprintf(stderr, "1\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", + // z->x_id+1, "lc"[ug->u.a[z->x_id].circ], ug->u.a[z->x_id].len, + // z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[ug->u.a[z->y_id].circ], ug->u.a[z->y_id].len, + // z->y_pos_s, z->y_pos_e+1); + // } + // for (k = 0; k < sp->n; k++) { + // fprintf(stderr, "in::[%lu, %u)\n", (sp->a[k]>>32), ((uint32_t)sp->a[k])); + // } + // } + if((l > 0) && (l >= (len*0.8))) return 1; + // fprintf(stderr, "\n[M::%s] utg%.6lu%c, rid::%lu, l::%lu, len::%lu, sp->n::%u\n", + // __func__, rid+1, "lc"[ug->u.a[rid].circ], rid, l, len, (uint32_t)sp->n); + return 0; +} + +uint32_t is_mmhom_node(uint64_t *ca, ma_utg_t *u, asg_t *sg, uint64_t cov_bd, double cut_rate) +{ + if(cut_rate < 0) {cut_rate = 0;} if(cut_rate > 1.0) {cut_rate = 1.0;} + uint64_t k, a, na, a_cut = u->n*cut_rate, na_cut = u->n*(1.0-cut_rate); + for (k = a = na = 0; k < u->n; k++) { + if(ca[k] > (cov_bd*((uint64_t)sg->seq[u->a[k]>>33].len))) { + a++; if((a) && (a>=a_cut)) return 1; + } else { + na++; if((na) && (na>=na_cut)) return 0; + } + } + + if((a) && (a>=a_cut)) return 1; + return 0; +} + +uint32_t test_het_aln_mmhap(uint64_t uid, ug_rid_cov_t *ccov, u_trans_t *a, uint64_t a_n, overlap_region_alloc* ol, st_mt_t *sp) +{ + uint64_t k; u_trans_t p; + if(a_n == 0 && ol->length == 0) return 0; + kv_resize(uint64_t, *sp, ccov->ug->u.a[uid].n); + memcpy(sp->a, ccov->cov.a+ccov->idx[uid], sizeof((*(sp->a)))*ccov->ug->u.a[uid].n); + + for (k = 0; k < a_n; k++) { + if(a[k].del) continue; + append_cov_line_ug_rid_cov_t(uid, sp->a, &(a[k]), ccov, ((uint64_t)-1), -1); + } + for (k = 0; k < ol->length; k++) { + p.qn = uid; p.tn = ol->list[k].y_id; + p.rev = ol->list[k].y_pos_strand; p.f = RC_3; p.nw = 0; + p.qs = ol->list[k].x_pos_s; p.qe = ol->list[k].x_pos_e+1; + if(p.rev) { + p.ts = ccov->ug->u.a[p.tn].len - (ol->list[k].y_pos_e+1); + p.te = ccov->ug->u.a[p.tn].len - ol->list[k].y_pos_s; + } else { + p.ts = ol->list[k].y_pos_s; + p.te = ol->list[k].y_pos_e+1; + } + append_cov_line_ug_rid_cov_t(uid, sp->a, &p, ccov, ((uint64_t)-1), -1); + } + + return is_mmhom_node(sp->a, &(ccov->ug->u.a[uid]), ccov->rg, ccov->hom_min, 0.8); +} + +void push_ul_ov_t(ul_idx_t *udb, u_trans_t *a, uint64_t a_n, uint64_t rid, st_mt_t *sp, overlap_region_alloc* ol, uint64_t len, uint64_t is_arc_filter, double max_err, kv_ul_ov_t *res) +{ + uint64_t cnt, z, k, l, m, spn; ul_ov_t *p; + sp->n = 0; + if(a_n) { + for (k = sp->n = 0; k < a_n; k++) { + if(a[k].del) continue; + z = a[k].tn; z <<= 1; z |= a[k].rev; z <<= 32; + z |= k; z |= ((uint64_t)0x80000000); + kv_push(uint64_t, *sp, z); + } + for (k = 0; k < ol->length; k++) { + z = ol->list[k].y_id; z <<= 1; + z |= ol->list[k].y_pos_strand; + z <<= 32; z |= k; + kv_push(uint64_t, *sp, z); + } + + radix_sort_gfa64(sp->a, sp->a + sp->n); spn = sp->n; + for (k = 1, l = m = 0; k <= spn; k++) { + if(k == spn || (sp->a[l]>>32)!=(sp->a[k]>>32)) { + if((sp->a[l]&((uint64_t)0x80000000))) {///no overlap within ol + for (z = l; z < k; z++) { + sp->a[m++] = (uint32_t)(sp->a[z]-((uint64_t)0x80000000)); + } + } + l = k; + } + } + sp->n = m; + } + + if(ol->length > 0) { + cnt = res->n + ol->length; kv_resize(ul_ov_t, (*res), cnt); + for (k = 0/**, bn = res->n**/; k < ol->length; k++) { + // if(b->olist.list[k].non_homopolymer_errors == 0) continue;///exact match is not trans + kv_pushp(ul_ov_t, (*res), &p); + p->qn = rid; p->tn = ol->list[k].y_id; p->el = 1; + p->sec = ol->list[k].non_homopolymer_errors; + p->rev = ol->list[k].y_pos_strand; + p->qs = ol->list[k].x_pos_s; p->qe = ol->list[k].x_pos_e+1; + if(p->rev) { + p->ts = udb->ug->u.a[p->tn].len - (ol->list[k].y_pos_e+1); + p->te = udb->ug->u.a[p->tn].len - ol->list[k].y_pos_s; + } else { + p->ts = ol->list[k].y_pos_s; + p->te = ol->list[k].y_pos_e+1; + } + // fprintf(stderr, ">0<[M::%s] utg%.6u%c -> utg%.6u%c\n", __func__, + // p->qn+1, "lc"[s->udb.ug->u.a[p->qn].circ], + // p->tn+1, "lc"[s->udb.ug->u.a[p->tn].circ]); + // if(p->ts >= p->te || p->qs >= p->qe) { + // fprintf(stderr, "+[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, + // p->qn+1, "lc"[udb->ug->u.a[p->qn].circ], udb->ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], + // p->tn+1, "lc"[udb->ug->u.a[p->tn].circ], udb->ug->u.a[p->tn].len, p->ts, p->te); + // } + if((is_arc_filter) && (!trans_ovlp_connect(p, udb->ug))) res->n--; + // fprintf(stderr, ">1<[M::%s] utg%.6u%c -> utg%.6u%c\n", __func__, + // p->qn+1, "lc"[s->udb.ug->u.a[p->qn].circ], + // p->tn+1, "lc"[s->udb.ug->u.a[p->tn].circ]); + // else { + // if(i == 5) + // { + // fprintf(stderr, ">>>utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", + // p->qn+1, "lc"[udb->ug->u.a[p->qn].circ], udb->ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], + // p->tn+1, "lc"[udb->ug->u.a[p->tn].circ], udb->ug->u.a[p->tn].len, p->ts, p->te); + // } + // } + } + + for (k = 0; k < sp->n; k++) { + kv_pushp(ul_ov_t, (*res), &p); + p->qn = a[sp->a[k]].qn; p->tn = a[sp->a[k]].tn; + p->rev = a[sp->a[k]].rev; p->el = 0; + p->qs = a[sp->a[k]].qs; p->qe = a[sp->a[k]].qe; + p->ts = a[sp->a[k]].ts; p->te = a[sp->a[k]].te; + p->sec = (p->qe-p->qs)*max_err; + // if(p->ts >= p->te || p->qs >= p->qe) { + // fprintf(stderr, "-[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, + // p->qn+1, "lc"[udb->ug->u.a[p->qn].circ], udb->ug->u.a[p->qn].len, p->qs, p->qe, "+-"[p->rev], + // p->tn+1, "lc"[udb->ug->u.a[p->tn].circ], udb->ug->u.a[p->tn].len, p->ts, p->te); + // } + } + + // if(is_sec_filter) { + // cnt = filter_sec_trans_ovlp(res->a+bn, res->n-bn, rid, sec_rate) + bn; + // res->n = cnt; + // } + // fprintf(stderr, "-1-[M::%s] utg%.6u%c, # ov::%lu\n", + // __func__, (uint32_t)i+1, "lc"[s->ug->u.a[i].circ], cnt - bn); + } +} + +void backward_dedup_ol(uint64_t rid, kv_ul_ov_t *bck, st_mt_t *sp, overlap_region_alloc* ol) +{ + int64_t i, m; uint64_t z, k, l; overlap_region t; + + kv_resize(uint64_t, *sp, ol->length); + for (i = ((int64_t)bck->n)-1, sp->n = 0; i >= 0 && bck->a[i].qn == rid; i--) { + z = bck->a[i].tn; z <<= 1; z |= bck->a[i].rev; z <<= 32; + kv_push(uint64_t, *sp, z); + } + if(!(sp->n)) return;///no bck overlap + + kv_resize(uint64_t, *sp, (ol->length)+sp->n); + for (k = 0; k < ol->length; k++) { + z = ol->list[k].y_id; z <<= 1; z |= ol->list[k].y_pos_strand; + z <<= 32; z |= k; z |= ((uint64_t)0x80000000); + kv_push(uint64_t, *sp, z); + } + + radix_sort_gfa64(sp->a, sp->a + sp->n); + for (k = 1, l = 0, m = 0; k <= sp->n; k++) { + if(k == sp->n || (sp->a[l]>>32)!=(sp->a[k]>>32)) { + if((k - l > 1) && (!(sp->a[l]&((uint64_t)0x80000000)))) {///overlap within bck + for (z = l; z < k; z++) { + if(sp->a[z]&((uint64_t)0x80000000)) { + ol->list[(uint32_t)(sp->a[z]-((uint64_t)0x80000000))].y_id = (uint32_t)-1; + m++; + } + } + } + l = k; + } + } + if(m > 0) { + for (k = z = 0; k < ol->length; k++) { + if(ol->list[k].y_id == (uint32_t)-1) continue; + if(z != k) { + t = ol->list[z]; + ol->list[z] = ol->list[k]; + ol->list[k] = t; + } + z++; + } + ol->length = z; + } + +} + +void remove_trans_ovlp_connect(ma_ug_t *ug, uint64_t rid, kv_ul_ov_t *bck) +{ + int64_t i; uint64_t m, k; + for (i = ((int64_t)bck->n)-1; i >= 0 && bck->a[i].qn == rid; i--); + m = i + 1; + if(m >= bck->n) return; + for (k = m; k < bck->n; k++) { + if(!trans_ovlp_connect(&(bck->a[k]), ug)) continue; + bck->a[m++] = bck->a[k]; + } + bck->n = m; +} + +uint64_t gen_trans_adaptive_aln(ug_trans_t *s, uint64_t rid, ha_ovec_buf_t *b, kv_ul_ov_t *bl, char *seq, uint64_t len, kv_u_trans_t *fi, + double err_low, double err_high, double bw_low, double bw_high) +{ + uint64_t cnt = ((s->idx_n.a[rid+1]-s->idx_n.a[rid])), ol_h = 0, pass_aln = 0; + uint32_t high_occ = asm_opt.polyploidy + 1; overlap_region *aux_o = NULL; + ///note: high_occ is different + ug_map_lchain(b->abl, rid, seq, len, s->w, s->k, &(s->udb), &b->olist, &b->clist, bw_low, bw_high, + s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, + s->is_HPC, s->idx_a.a + s->idx_n.a[rid], cnt, s->srt_a.a, s->srt_a.n, s->mini_cut, s->chain_cut, fi); + // if(rid == 160) { + // fprintf(stderr, "-1-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); + // } + ///remove candidate chains that have been calculated + if(!fi) backward_dedup_ol(rid, bl, &(b->sp), &b->olist); + // if(rid == 160) { + // fprintf(stderr, "-2-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); + // } + filter_by_reliable_ovlp_adv(rid, s->filter, &(b->sp), &b->olist, &(s->udb), s->sec_cutoff, 1, 1, &ol_h); + clear_Cigar_record(&b->cigar1); clear_Round2_alignment(&b->round2); + if(!fi) ol_h = 0; + + ol_h = split_ug_lalign(ol_h, &b->olist, err_high, err_low, + &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, + &b->correct, &b->exz, aux_o, rid, s->k, s->chain_cut, NULL); + + aux_o = gen_aux_ovlp(&b->olist);///must be here + + ol_h = split_ug_lalign(ol_h, &b->olist, err_high, err_low, + &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, + &b->correct, &b->exz, aux_o, rid, s->k, s->chain_cut, NULL); + + if(fi) {///first round + pass_aln = test_het_aln(s->ug, rid, u_trans_a((*(s->filter)), rid), u_trans_n((*(s->filter)), rid), &(b->sp), &b->olist, len); + push_ul_ov_t(&(s->udb), u_trans_a((*(s->filter)), rid), u_trans_n((*(s->filter)), rid), rid, &(b->sp), &b->olist, len, pass_aln, err_high, bl); + // fprintf(stderr, "-1-[M::%s] utg%.6lu%c, rid::%lu, pass_aln::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, pass_aln); + } else {///second round + push_ul_ov_t(&(s->udb), NULL, 0, rid, &(b->sp), &b->olist, len, 0, err_high, bl); + remove_trans_ovlp_connect(s->udb.ug, rid, bl); + } + return pass_aln; +} + +void clear_count_buf(ug_trans_t *s, uint32_t tid, uint32_t free_count) +{ + // fprintf(stderr, "[M::%s]\n", __func__); + ha_ovec_buf_t *b = s->hab[tid]; + destory_fake_cigar(&(b->tmp_region.f_cigar)); + free(b->tmp_region.w_list.a); free(b->tmp_region.w_list.c.a); + memset(&(b->tmp_region), 0, sizeof(b->tmp_region)); + init_fake_cigar(&(b->tmp_region.f_cigar)); + memset(&(b->tmp_region.w_list), 0, sizeof(b->tmp_region.w_list)); + CALLOC(b->tmp_region.w_list.a, 1); b->tmp_region.w_list.n = b->tmp_region.w_list.m = 1; + + ha_abufl_destroy(b->abl); b->abl = ha_abufl_init(); + + kv_destroy(b->sp); memset(&(b->sp), 0, sizeof((b->sp))); + if(free_count) return; + + destory_Candidates_list(&b->clist); + memset((&(b->clist)), 0, sizeof(b->clist)); + init_Candidates_list(&b->clist); + + destory_overlap_region_alloc(&b->olist); + memset((&(b->olist)), 0, sizeof(b->olist)); + init_overlap_region_alloc(&b->olist); + + destory_UC_Read(&b->self_read); + memset((&(b->self_read)), 0, sizeof(b->self_read)); + init_UC_Read(&b->self_read); + + destory_UC_Read(&b->ovlp_read); + memset((&(b->ovlp_read)), 0, sizeof(b->ovlp_read)); + init_UC_Read(&b->ovlp_read); + + destory_Correct_dumy(&b->correct); + memset((&(b->correct)), 0, sizeof(b->correct)); + init_Correct_dumy(&b->correct); + + destroy_bit_extz_t(&(b->exz)); + memset((&(b->exz)), 0, sizeof(b->exz)); + init_bit_extz_t(&(b->exz), 31); +} + +static void worker_for_trans_ovlp_adv(void *data, long i, int tid) // callback for kt_for() +{ + ug_trans_t *s = (ug_trans_t*)data; + ha_ovec_buf_t *b = s->hab[tid]; kv_ul_ov_t *bl = &(s->ll[tid].tk); + uint32_t high_occ = asm_opt.polyploidy + 1; uint64_t cnt; + char *seq = s->ug->u.a[i].s; int64_t len = s->ug->u.a[i].len; + if((!s->is_ovlp) && (s->is_cnt)) s->idx_n.a[i] = 0; + if(IF_HOM(i, (*(s->bub))) || s->ug->g->seq[i].del) return; + + // asprintf(&as, "\n[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); + // push_vlog(&(overall_zdbg->a[s->id+i]), as); free(as); as = NULL; + + if(!s->is_ovlp) { + if(s->is_cnt) { + s->idx_n.a[i] = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, + s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, NULL, 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); + } else { + cnt = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, + s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); + assert(cnt == ((s->idx_n.a[i+1]-s->idx_n.a[i]))); + } + if(s->free_cnt[tid] >= FREE_BATCH) { + clear_count_buf(s, tid, 1); s->free_cnt[tid] = 0; + } + s->free_cnt[tid]++; + return; + } + + // if(i == 160) { + // fprintf(stderr, "\n-1-[M::%s] utg%.6u%c, rid::%ld, is_ovlp::%d, is_cnt::%d, len::%ld, str::%u\n", + // __func__, (uint32_t)i+1, "lc"[s->ug->u.a[i].circ], i, s->is_ovlp, s->is_cnt, len, (uint32_t)(!!seq)); + // } + + if(!gen_trans_adaptive_aln(s, i, b, bl, seq, len, s->filter, s->diff_ec_ul, s->diff_ec_ul_double, s->bw_thres, s->bw_thres_double)) { + gen_trans_adaptive_aln(s, i, b, bl, seq, len, NULL, s->diff_ec_ul_double, s->diff_ec_ul_double, s->bw_thres_double, s->bw_thres_double); + } + + if(s->free_cnt[tid] >= FREE_BATCH) { + clear_count_buf(s, tid, 0); s->free_cnt[tid] = 0; + } + s->free_cnt[tid]++; +} + +uint64_t *gen_reliable_cov_arr(uint32_t id, kv_u_trans_t *idx, ug_rid_cov_t *ccov, st_mt_t *sp) +{ + u_trans_t *a; uint64_t n, k; + a = u_trans_a(*idx, id); n = u_trans_n(*idx, id); + kv_resize(uint64_t, *sp, ccov->ug->u.a[id].n); + memcpy(sp->a, ccov->cov.a+ccov->idx[id], sizeof((*(sp->a)))*ccov->ug->u.a[id].n); + for (k = 0; k < n; k++) { + if(a[k].del) continue; + if(a[k].f == RC_0 || a[k].f == RC_1) { + append_cov_line_ug_rid_cov_t(id, sp->a, &(a[k]), ccov, ((uint64_t)-1), -1); + } + } + return sp->a; +} + +uint64_t is_above_cov(uint64_t uid, overlap_region *o, uint64_t *fc, ug_rid_cov_t *ccov, double sec_rate) +{ + u_trans_t p; + p.qn = uid; p.tn = o->y_id; + p.rev = o->y_pos_strand; p.f = RC_3; p.nw = 0; + p.qs = o->x_pos_s; p.qe = o->x_pos_e+1; + if(p.rev) { + p.ts = ccov->ug->u.a[p.tn].len - (o->y_pos_e+1); + p.te = ccov->ug->u.a[p.tn].len - o->y_pos_s; + } else { + p.ts = o->y_pos_s; + p.te = o->y_pos_e+1; + } + + if(append_cov_line_ug_rid_cov_t(uid, fc, &p, ccov, ccov->hom_max, sec_rate)) return 0; + return 1; +} + +void filter_by_reliable_ovlp_mmhap_adv(uint32_t id, kv_u_trans_t *idx, st_mt_t *sp, overlap_region_alloc* ol, const ul_idx_t *udb, double sec_rate, uint64_t avoid_dup_aln, +uint64_t dedup_by_reliable_ovlp, ug_rid_cov_t *ccov, uint64_t *occ1) +{ + (*occ1) = 0; + u_trans_t *a; uint64_t n, k, l, z, rr, r1, *fc; overlap_region *m, t; + a = u_trans_a(*idx, id); n = u_trans_n(*idx, id); + if(avoid_dup_aln) { + kv_resize(uint64_t, *sp, (ol->length)+n); + for (k = sp->n = 0; k < n; k++) { + if(a[k].del) continue; + if(a[k].f == RC_0 || a[k].f == RC_1) { + z = a[k].tn; z <<= 1; z |= a[k].rev; z <<= 32; + kv_push(uint64_t, *sp, z); + } + } + if(sp->n > 0) { + for (k = 0; k < ol->length; k++) { + z = ol->list[k].y_id; z <<= 1; z |= ol->list[k].y_pos_strand; + z <<= 32; z |= k; z |= ((uint64_t)0x80000000); + kv_push(uint64_t, *sp, z); + } + + radix_sort_gfa64(sp->a, sp->a + sp->n); + for (k = 1, l = 0, rr = 0; k <= sp->n; k++) { + if(k == sp->n || (sp->a[l]>>32)!=(sp->a[k]>>32)) { + if((k - l > 1) && (!(sp->a[l]&((uint64_t)0x80000000)))) {///overlap within bck + for (z = l; z < k; z++) { + if(sp->a[z]&((uint64_t)0x80000000)) { + ol->list[(uint32_t)(sp->a[z]-((uint64_t)0x80000000))].y_id = ((uint32_t)-1); + rr++; + } + } + } + l = k; + } + } + + if(rr > 0) { + for (k = rr = 0; k < ol->length; k++) { + if(ol->list[k].y_id == ((uint32_t)-1)) continue; + if(rr != k) { + t = ol->list[rr]; + ol->list[rr] = ol->list[k]; + ol->list[k] = t; + } + rr++; + } + ol->length = rr; + } + } + } + + sp->n = 0; fc = NULL; + if(dedup_by_reliable_ovlp) { + for (k = 0; k < n; k++) { + if(a[k].del) continue; + if(a[k].f == RC_0 || a[k].f == RC_1) break; + } + if(k < n) fc = gen_reliable_cov_arr(id, idx, ccov, sp); + } + + for (k = rr = r1 = 0; k < ol->length; k++) { + m = &(ol->list[k]); + if((dedup_by_reliable_ovlp) && (m->x_pos_strand == 0) && (fc)) { + if(is_above_cov(id, m, fc, ccov, sec_rate)) continue; + } + + if(rr != k) { + t = ol->list[k]; + ol->list[k] = ol->list[rr]; + ol->list[rr] = t; + } + if(ol->list[rr].x_pos_strand) { + ol->list[rr].x_pos_strand = 0; + if(r1 != rr) { + t = ol->list[r1]; + ol->list[r1] = ol->list[rr]; + ol->list[rr] = t; + } + r1++; + } + rr++; + } + // if(id == 1576) { + // fprintf(stderr, "[M::%s] utg%.6ul, ol->length0::%lu, ol->length::%lu\n", __func__, id+1, ol->length, rr); + // } + ol->length = rr; (*occ1) = r1; +} + + +uint64_t gen_trans_adaptive_mmhap_aln(ug_trans_t *s, uint64_t rid, ha_ovec_buf_t *b, kv_ul_ov_t *bl, char *seq, uint64_t len, kv_u_trans_t *fi, double err_low, double err_high, double bw_low, double bw_high) +{ + uint64_t cnt = ((s->idx_n.a[rid+1]-s->idx_n.a[rid])), ol_h = 0, pass_aln = 0; + uint32_t high_occ = asm_opt.polyploidy + 1; overlap_region *aux_o = NULL; + ///note: high_occ is different + ug_map_lchain(b->abl, rid, seq, len, s->w, s->k, &(s->udb), &b->olist, &b->clist, bw_low, bw_high, + s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, + s->is_HPC, s->idx_a.a + s->idx_n.a[rid], cnt, s->srt_a.a, s->srt_a.n, s->mini_cut, s->chain_cut, fi); + // if(rid == 57) { + // fprintf(stderr, "-1-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); + // } + ///remove candidate chains that have been calculated + if(!fi) backward_dedup_ol(rid, bl, &(b->sp), &b->olist);///it is ok + // if(rid == 57) { + // fprintf(stderr, "-2-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); + // } + filter_by_reliable_ovlp_mmhap_adv(rid, s->filter, &(b->sp), &b->olist, &(s->udb), s->sec_cutoff, 1, 1, s->ccov, &ol_h); + clear_Cigar_record(&b->cigar1); clear_Round2_alignment(&b->round2); + if(!fi) ol_h = 0; + + // if(rid == 57) { + // fprintf(stderr, "-3-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); + // } + + ol_h = split_ug_lalign(ol_h, &b->olist, err_high, err_low, + &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, + &b->correct, &b->exz, aux_o, rid, s->k, s->chain_cut, NULL); + + // if(rid == 57) { + // fprintf(stderr, "-4-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); + // } + + aux_o = gen_aux_ovlp(&b->olist);///must be here + + // if(rid == 57) { + // fprintf(stderr, "-5-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); + // } + + ol_h = split_ug_lalign(ol_h, &b->olist, err_high, err_low, + &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, + &b->correct, &b->exz, aux_o, rid, s->k, s->chain_cut, NULL); + + // if(rid == 57) { + // fprintf(stderr, "-6-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); + // } + + if(fi) {///first round + pass_aln = test_het_aln_mmhap(rid, s->ccov, u_trans_a((*(s->filter)), rid), u_trans_n((*(s->filter)), rid), &b->olist, &(b->sp)); + push_ul_ov_t(&(s->udb), u_trans_a((*(s->filter)), rid), u_trans_n((*(s->filter)), rid), rid, &(b->sp), &b->olist, len, pass_aln, err_high, bl); + // fprintf(stderr, "-1-[M::%s] utg%.6lu%c, rid::%lu, pass_aln::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, pass_aln); + } else {///second round + push_ul_ov_t(&(s->udb), NULL, 0, rid, &(b->sp), &b->olist, len, 0, err_high, bl); + remove_trans_ovlp_connect(s->udb.ug, rid, bl); + } + return pass_aln; +} + +static void worker_for_trans_ovlp_mmhap_adv(void *data, long i, int tid) // callback for kt_for() +{ + ug_trans_t *s = (ug_trans_t*)data; + ha_ovec_buf_t *b = s->hab[tid]; kv_ul_ov_t *bl = &(s->ll[tid].tk); + uint32_t high_occ = asm_opt.polyploidy + 1; uint64_t cnt; + char *seq = s->ug->u.a[i].s; int64_t len = s->ug->u.a[i].len; + if((!s->is_ovlp) && (s->is_cnt)) s->idx_n.a[i] = 0; + if(s->ug->g->seq[i].del) return; + if(is_mmhom_node(s->ccov->cov.a+s->ccov->idx[i], &(s->ug->u.a[i]), s->ccov->rg, s->ccov->hom_min, 0.9)) return; + // asprintf(&as, "\n[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); + // push_vlog(&(overall_zdbg->a[s->id+i]), as); free(as); as = NULL; + + if(!s->is_ovlp) { + if(s->is_cnt) { + s->idx_n.a[i] = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, + s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, NULL, 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); + } else { + cnt = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, + s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); + assert(cnt == ((s->idx_n.a[i+1]-s->idx_n.a[i]))); + } + if(s->free_cnt[tid] >= FREE_BATCH) { + clear_count_buf(s, tid, 1); s->free_cnt[tid] = 0; + } + s->free_cnt[tid]++; + return; + } + + // if(i == 58) { + // fprintf(stderr, "\n-1-[M::%s] utg%.6u%c, rid::%ld, is_ovlp::%d, is_cnt::%d, len::%ld, str::%u\n", + // __func__, (uint32_t)i+1, "lc"[s->ug->u.a[i].circ], i, s->is_ovlp, s->is_cnt, len, (uint32_t)(!!seq)); + // } + + if(!gen_trans_adaptive_mmhap_aln(s, i, b, bl, seq, len, s->filter, s->diff_ec_ul, s->diff_ec_ul_double, s->bw_thres, s->bw_thres_double)) { + gen_trans_adaptive_mmhap_aln(s, i, b, bl, seq, len, NULL, s->diff_ec_ul_double, s->diff_ec_ul_double, s->bw_thres_double, s->bw_thres_double); + } + if(s->free_cnt[tid] >= FREE_BATCH) { + clear_count_buf(s, tid, 0); s->free_cnt[tid] = 0; + } + s->free_cnt[tid]++; +} + +uint32_t tranfor_ovlp(u_trans_t *qovlp, u_trans_t *tovlp, asg_t *g, ul_ov_t *res, uint32_t adjust_rev) +{ + int64_t os, oe, s_shift, e_shift, tt, qs, qe, ts, te; + os = MAX(qovlp->ts, tovlp->qs); + oe = MIN(qovlp->te, tovlp->qe); + if(oe <= os) return 0; + + ///[os, oe) -> qovlp->t* + s_shift = get_offset_adjust(os-qovlp->ts, qovlp->te-qovlp->ts, qovlp->qe-qovlp->qs); + e_shift = get_offset_adjust(qovlp->te-oe, qovlp->te-qovlp->ts, qovlp->qe-qovlp->qs); + if(qovlp->rev) { + tt = s_shift; s_shift = e_shift; e_shift = tt; + } + qs = qovlp->qs+s_shift; qe = ((int64_t)qovlp->qe)-e_shift; + if(qs >= qe) return 0; + + ///[os, oe) -> tovlp->q* + s_shift = get_offset_adjust(os-tovlp->qs, tovlp->qe-tovlp->qs, tovlp->te-tovlp->ts); + e_shift = get_offset_adjust(tovlp->qe-oe, tovlp->qe-tovlp->qs, tovlp->te-tovlp->ts); + if(tovlp->rev) { + tt = s_shift; s_shift = e_shift; e_shift = tt; + } + ts = tovlp->ts+s_shift; te = ((int64_t)tovlp->te)-e_shift; + if(ts >= te) return 0; + + memset(res, 0, sizeof(*res)); + res->qn = qovlp->qn; res->qs = qs; res->qe = qe; + res->tn = tovlp->tn; res->ts = ts; res->te = te; + res->rev = ((qovlp->rev == tovlp->rev)?0:1); + if(adjust_rev && res->rev) {///for linear chaining + res->ts = g->seq[res->tn].len - te; + res->te = g->seq[res->tn].len - ts; + } + return 1; +} + +uint32_t rescue_adject_ovlp(asg_t *g, uint32_t id, kv_u_trans_t *ta, kv_ul_ov_t *out, st_mt_t *buf) +{ + u_trans_t *a, *b; ul_ov_t rr; uint64_t a_n, b_n, k, l, i, z, m; + a = u_trans_a((*ta), id); a_n = u_trans_n((*ta), id); + for (i = out->n = buf->n = 0; i < a_n; i++) { + b = u_trans_a((*ta), a[i].tn); b_n = u_trans_n((*ta), a[i].tn); + z = a[i].tn; z <<= 32; kv_push(uint64_t, *buf, z); + for (k = 0; k < b_n; k++) { + if(b[k].tn == id) continue; + if(!tranfor_ovlp(&(a[i]), &(b[k]), g, &rr, 1)) continue; + z = rr.tn; z <<= 32; z |= out->n; z |= ((uint64_t)0x80000000); + rr.tn <<= 1; rr.tn |= rr.rev; kv_push(ul_ov_t, *out, rr); + } + } + if(out->n == 0) return 1; + + radix_sort_gfa64(buf->a, buf->a + buf->n); + for (k = 1, l = m = 0; k <= buf->n; k++) { + if(k == buf->n || (buf->a[l]>>32)!=(buf->a[k]>>32)) { + if((k - l > 1) && (!(buf->a[l]&((uint64_t)0x80000000)))) {///overlap within bck + for (z = l; z < k; z++) { + if(buf->a[z]&((uint64_t)0x80000000)) { + out->a[(uint32_t)(buf->a[z]-((uint64_t)0x80000000))].tn = (uint32_t)-1; + m++; + } + } + } + l = k; + } + } + + if(m) { + for (k = m = 0; k < out->n; k++) { + if(out->a[k].tn == (uint32_t)-1) continue; + out->a[m++] = out->a[k]; + } + out->n = m; + } + if(out->n == 0) return 1; + + radix_sort_ul_ov_srt_tn(out->a, out->a+out->n); + for (k = 0; k < out->n; k++) out->a[k].tn >>= 1; + + return 0; +} + +/** +uint64_t gen_trans_chain_mmhap(ug_trans_t *s, uint64_t rid, ha_ovec_buf_t *b, kv_ul_ov_t *bl, char *seq, uint64_t len, +double err, double bw) +{ + uint64_t cnt = ((s->idx_n.a[rid+1]-s->idx_n.a[rid])), ol_h = 0, pass_aln = 0; + uint32_t high_occ = asm_opt.polyploidy + 1; overlap_region *aux_o = NULL; + ///note: high_occ is different + ug_map_lchain(b->abl, rid, seq, len, s->w, s->k, &(s->udb), &b->olist, &b->clist, bw, bw, + s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, + s->is_HPC, s->idx_a.a + s->idx_n.a[rid], cnt, s->srt_a.a, s->srt_a.n, s->mini_cut, s->chain_cut, NULL); + // if(rid == 57) { + // fprintf(stderr, "-1-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); + // } + ///remove candidate chains that have been calculated + if(!fi) backward_dedup_ol(rid, bl, &(b->sp), &b->olist);///it is ok + // if(rid == 57) { + // fprintf(stderr, "-2-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); + // } + filter_by_reliable_ovlp_mmhap_adv(rid, s->filter, &(b->sp), &b->olist, &(s->udb), s->sec_cutoff, 1, 1, s->ccov, &ol_h); + clear_Cigar_record(&b->cigar1); clear_Round2_alignment(&b->round2); + if(!fi) ol_h = 0; + + // if(rid == 57) { + // fprintf(stderr, "-3-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); + // } + + ol_h = split_ug_lalign(ol_h, &b->olist, err_high, err_low, + &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, + &b->correct, &b->exz, aux_o, rid, s->k, s->chain_cut, NULL); + + // if(rid == 57) { + // fprintf(stderr, "-4-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); + // } + + aux_o = gen_aux_ovlp(&b->olist);///must be here + + // if(rid == 57) { + // fprintf(stderr, "-5-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); + // } + + ol_h = split_ug_lalign(ol_h, &b->olist, err_high, err_low, + &b->clist, &(s->udb), s->uopt, seq, len, &b->self_read, &b->ovlp_read, + &b->correct, &b->exz, aux_o, rid, s->k, s->chain_cut, NULL); + + // if(rid == 57) { + // fprintf(stderr, "-6-[M::%s] utg%.6lu%c, rid::%ld, b->olist->length::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, b->olist.length); + // } + + if(fi) {///first round + pass_aln = test_het_aln_mmhap(rid, s->ccov, u_trans_a((*(s->filter)), rid), u_trans_n((*(s->filter)), rid), &b->olist, &(b->sp)); + push_ul_ov_t(&(s->udb), u_trans_a((*(s->filter)), rid), u_trans_n((*(s->filter)), rid), rid, &(b->sp), &b->olist, len, pass_aln, err_high, bl); + // fprintf(stderr, "-1-[M::%s] utg%.6lu%c, rid::%lu, pass_aln::%lu\n", + // __func__, rid+1, "lc"[s->ug->u.a[rid].circ], rid, pass_aln); + } else {///second round + push_ul_ov_t(&(s->udb), NULL, 0, rid, &(b->sp), &b->olist, len, 0, err_high, bl); + remove_trans_ovlp_connect(s->udb.ug, rid, bl); + } + return pass_aln; +} +**/ + + + +static void worker_for_trans_chain_mmhap_adv(void *data, long i, int tid) // callback for kt_for() +{ + ug_trans_t *s = (ug_trans_t*)data; + ha_ovec_buf_t *b = s->hab[tid]; kv_ul_ov_t *bl = &(s->ll[tid].tk); + uint32_t high_occ = asm_opt.polyploidy + 1; uint64_t cnt; + char *seq = s->ug->u.a[i].s; int64_t len = s->ug->u.a[i].len; + if((!s->is_ovlp) && (s->is_cnt)) s->idx_n.a[i] = 0; + if(s->ug->g->seq[i].del) return; + if(is_mmhom_node(s->ccov->cov.a+s->ccov->idx[i], &(s->ug->u.a[i]), s->ccov->rg, s->ccov->hom_min, 0.9)) return; + // asprintf(&as, "\n[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); + // push_vlog(&(overall_zdbg->a[s->id+i]), as); free(as); as = NULL; + // if(rescue_adject_ovlp(s->ug->g, i, s->filter, &(s->ll[tid].lo))) return; + + // gen_trans_chain_mmhap(s, i, b, bl, seq, len, 0.8, 0.8); + + if(!s->is_ovlp) { + if(s->is_cnt) { + s->idx_n.a[i] = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, + s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, NULL, 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); + } else { + cnt = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, + s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); + assert(cnt == ((s->idx_n.a[i+1]-s->idx_n.a[i]))); + } + if(s->free_cnt[tid] >= FREE_BATCH) { + clear_count_buf(s, tid, 1); s->free_cnt[tid] = 0; + } + s->free_cnt[tid]++; + return; + } + + // if(i == 58) { + // fprintf(stderr, "\n-1-[M::%s] utg%.6u%c, rid::%ld, is_ovlp::%d, is_cnt::%d, len::%ld, str::%u\n", + // __func__, (uint32_t)i+1, "lc"[s->ug->u.a[i].circ], i, s->is_ovlp, s->is_cnt, len, (uint32_t)(!!seq)); + // } + + if(!gen_trans_adaptive_mmhap_aln(s, i, b, bl, seq, len, s->filter, s->diff_ec_ul, s->diff_ec_ul_double, s->bw_thres, s->bw_thres_double)) { + gen_trans_adaptive_mmhap_aln(s, i, b, bl, seq, len, NULL, s->diff_ec_ul_double, s->diff_ec_ul_double, s->bw_thres_double, s->bw_thres_double); + } + if(s->free_cnt[tid] >= FREE_BATCH) { + clear_count_buf(s, tid, 0); s->free_cnt[tid] = 0; + } + s->free_cnt[tid]++; +} + + +int64_t retrieve_cigar_err_dir(bit_extz_t *ez, int64_t s, int64_t e, int64_t *xk, int64_t *ck, int64_t is_back) +{ ///[ez->ts, ez->te]/[ez->qs, ez->qe]/[s, e) + if(!ez->cigar.n) return 0; + int64_t cn = ez->cigar.n, op, err = 0; int64_t ws, we, os, oe, ovlp; + if(!is_back) { + if(((*ck) < 0) || ((*ck) > cn)) {//(*ck) == cn is allowed + (*ck) = 0; (*xk) = ez->ts; + } + + while ((*ck) > 0 && (*xk) > s) { + --(*ck); + op = ez->cigar.a[(*ck)]>>14; + if(op!=2) (*xk) -= (ez->cigar.a[(*ck)]&(0x3fff)); + } + + //some cigar will span s or e + while ((*ck) < cn && (*xk) < e) {//[s, e) + ws = (*xk); + op = ez->cigar.a[(*ck)]>>14; + if(op!=2) (*xk) += (ez->cigar.a[(*ck)]&(0x3fff)); + we = (*xk); + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + if((op==2) && (ws>=s) && (wscigar.a[(*ck)]&(0x3fff)); + } + (*ck)++; + if((!ovlp) || (!op)) continue; + err += ovlp; + } + } else { + if(((*ck) < 0) || ((*ck) >= cn)) { + (*ck) = cn-1; (*xk) = ez->te + 1; ///[ez->ts, ez->te] + } + while (((*ck) < cn) && ((*xk) < e)) { + ++(*ck); + op = ez->cigar.a[(*ck)]>>14; + if(op!=2) (*xk) += (ez->cigar.a[(*ck)]&(0x3fff)); + } + + //some cigar will span s or e + while ((*ck) >= 0 && (*xk) > s) {//[s, e) + we = (*xk); + op = ez->cigar.a[(*ck)]>>14; + if(op!=2) (*xk) -= (ez->cigar.a[(*ck)]&(0x3fff)); + ws = (*xk); + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + if((op==2) && (ws>=s) && (wscigar.a[(*ck)]&(0x3fff)); + } + (*ck)--; + if((!ovlp) || (!op)) continue; + err += ovlp; + } + } + // int64_t debug_err = retrieve_cigar_err_debug(ez, s, e); + // if(!(err == debug_err)) { + // fprintf(stderr, "[M::%s::] err::%ld, debug_err::%ld, s::%ld, e::%ld, ez->ts::%u, ez->te::%u\n", + // __func__, err, debug_err, s, e, ez->ts, ez->te); + // } + // assert(err == debug_err); + return err; +} + +int64_t cal_cigar_err(overlap_region *z, int64_t s, int64_t e, int64_t is_back)///need debugging +{ + int64_t wn = z->w_list.n, wk, xk, ck; window_list *m; bit_extz_t ez; + int64_t ws, we, os, oe, ovlp, xl, yl, werr, err, tot; + err = 0; tot = e - s; wk = xk = ck = -1; + if(!wn) return INT32_MAX; + + if(!is_back) { + wk = 0; + if(wn) { + xk = z->w_list.a[wk].x_start; ck = 0; + } + while(wk < wn) { + m = &(z->w_list.a[wk]); + ws = m->x_start; we = m->x_end+1; + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + if(ovlp) { + xl = m->x_end+1-m->x_start; + yl = m->y_end+1-m->y_start; + if((is_ualn_win((*m))) || (is_est_aln((*m)))) { + if(is_ualn_win((*m))) { //unmapped + werr = MAX(xl, yl);///gen_err_unaligned(xl, yl); + } else { + werr = m->error;//shared window + } + if(ovlp < xl) { + werr = (((double)ovlp)/((double)xl))*((double)werr); + } + //skip the whole window + err += werr; xk = m->x_end+1; ck = m->clen; + } else { + if(ovlp == xl) { //skip the whole window + err += m->error; xk = m->x_end+1; ck = m->clen; + } else { + set_bit_extz_t(ez, (*z), wk); + err += retrieve_cigar_err_dir(&ez, os, oe, &xk, &ck, is_back); + } + } + } + tot -= ovlp; + if(xk >= e) break;//[min_w, max_w] && [s, e) + wk++; if(wk >= wn) break; + xk = z->w_list.a[wk].x_start; ck = 0;//reset + } + } else { + wk = wn-1; + if(wn) { + xk = z->w_list.a[wk].x_end+1; ck = z->w_list.a[wk].clen-1; + } + while(wk >= 0) { + m = &(z->w_list.a[wk]); + ws = m->x_start; we = m->x_end+1; + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + if(ovlp) { + xl = m->x_end+1-m->x_start; + yl = m->y_end+1-m->y_start; + if((is_ualn_win((*m))) || (is_est_aln((*m)))) { + if(is_ualn_win((*m))) { //unmapped + werr = MAX(xl, yl);///gen_err_unaligned(xl, yl); + } else { + werr = m->error;//shared window + } + if(ovlp < xl) { + werr = (((double)ovlp)/((double)xl))*((double)werr); + } + //skip the whole window + err += werr; xk = m->x_start; ck = -1; + } else { + if(ovlp == xl) { //skip the whole window + err += m->error; xk = m->x_start; ck = -1; + } else { + set_bit_extz_t(ez, (*z), wk); + err += retrieve_cigar_err_dir(&ez, os, oe, &xk, &ck, is_back); + } + } + } + tot -= ovlp; + if(xk <= s) break;//[s, e) + wk--; if(wk < 0) break; + xk = z->w_list.a[wk].x_end+1; ck = z->w_list.a[wk].clen-1;//reset + } + } + assert(!tot); + return err; +} + +uint64_t get_high_simi(overlap_region *z, double erate, uint64_t maxe, uint64_t minov, uint64_t *re0, uint64_t *re1) +{ + uint64_t ol, err = z->non_homopolymer_errors, e0, e1, f0 = 0, f1 = 0; + ol = z->x_pos_e+1-z->x_pos_s; (*re0) = (*re1) = (uint64_t)-1; + if(ol > (z->y_pos_e+1-z->y_pos_s)) ol = z->y_pos_e+1-z->y_pos_s; + if((err <= (ol*erate)) && (err <= maxe)) return 1; + if(ol <= minov) return 0;///too short + e0 = cal_cigar_err(z, 0, minov, 0); + e1 = cal_cigar_err(z, z->x_pos_e+1-minov, z->x_pos_e+1, 1); + if((e0 <= (minov*erate)) && (e0 <= maxe)) f0 = 1; + if((e1 <= (minov*erate)) && (e1 <= maxe)) f1 = 1; + if(f0 && f1 && (ol <= (minov<<1))) { + if(e0 >= e1) f0 = 0; + else f1 = 0; + } + if((!f0) && (!f1)) return 0; + if(f0) (*re0) = e0; + if(f1) (*re1) = e1; + return 2; +} + +int64_t hpc_check_naive(hpc_ss_t *a, int64_t n, int64_t s, int64_t e, int64_t bd) +{ + int64_t k, os, oe; + for (k = 0; k < n; k++) { + os = MAX(s, a[k].s); oe = MIN(e, a[k].e); + if(oe - os >= -bd) return 1; + if(a[k].s > (uint64_t)(e + bd)) break; + } + return 0; +} + +int64_t hpc_check(hpc_ss_t *a, int64_t n, int64_t s, int64_t e, int64_t *idx, int64_t bd) +{ + if(n<=0) return 0; + if((*idx) >= n) (*idx) = n - 1; + if((*idx) < 0) (*idx) = 0; + int64_t k = (*idx), os, oe; + for (; k < n; k++) { + os = MAX(s, a[k].s); oe = MIN(e, a[k].e); + if(oe - os >= -bd) { + (*idx) = k; return 1; + } + if(a[k].s > (uint64_t)(e + bd)) break; + } + os = (*idx); (*idx) = k; k = os - 1; + for (; k >= 0; k--) { + os = MAX(s, a[k].s); oe = MIN(e, a[k].e); + if(oe - os >= -bd) { + (*idx) = k; return 1; + } + } + // assert(!hpc_check_naive(a, n, s, e, bd)); + return 0; +} + +int64_t retrieve_npc_cigar_err(bit_extz_t *ez, int64_t s, int64_t e, int64_t *xk, int64_t *yk, int64_t *ck, +hpc_ss_t *fx, int64_t nx, hpc_ss_t *fy, int64_t ny, int64_t ylen, int64_t is_rev)///[s, e) for x +{ + if(!ez->cigar.n) return 0; + int64_t cn = ez->cigar.n, op, err = 0; int64_t ws, we, ws1, we1, os, oe, ovlp, xi, yi; + if(((*ck) < 0) || ((*ck) > cn)) {//(*ck) == cn is allowed + (*ck) = 0; (*xk) = ez->ts; (*yk) = ez->ps; + } + while ((*ck) > 0 && (*xk) > s) { + --(*ck); + op = ez->cigar.a[(*ck)]>>14; + if(op!=2) (*xk) -= (ez->cigar.a[(*ck)]&(0x3fff)); + if(op!=3) (*yk) -= (ez->cigar.a[(*ck)]&(0x3fff)); + } + xi = yi = 0; if(nx<=0) fx = NULL; if(ny<=0) fy = NULL; + + //some cigar will span s or e + while ((*ck) < cn && (*xk) < e) {//[s, e) + ws = (*xk); ws1 = (*yk); + op = ez->cigar.a[(*ck)]>>14; + if(op!=2) (*xk) += (ez->cigar.a[(*ck)]&(0x3fff)); + if(op!=3) (*yk) += (ez->cigar.a[(*ck)]&(0x3fff)); + we = (*xk); we1 = (*yk); + os = MAX(s, ws); oe = MIN(e, we); + ovlp = ((oe>os)? (oe-os):0); + if((op==2) && (ws>=s) && (wscigar.a[(*ck)]&(0x3fff)); + } + (*ck)++; + if((!ovlp) || (!op)) continue; + if(fx && hpc_check(fx, nx, ws, we, &xi, 1)) continue; + if(fy && hpc_check(fy, ny, ((is_rev)?(ylen-we1):(ws1)), ((is_rev)?(ylen-ws1):(we1)), &yi, 1)) continue; + err += ovlp; + } + return err; +} + +///[s, e) for x +int64_t cal_npc_err(overlap_region *z, int64_t xs, int64_t xe, hpc_re_t *hre, int64_t ylen) +{ + int64_t wn = z->w_list.n, wk, xk, yk, ck; window_list *m; bit_extz_t ez; + int64_t ws, we, os, oe, ovlp, xl, yl, werr, err, tot; + hpc_ss_t *fx = NULL, *fy = NULL; int64_t nx = 0, ny = 0; + err = 0; tot = xe - xs; wk = xk = yk = ck = -1; + if(!wn) return INT32_MAX; + wk = 0; + if(wn) { + xk = z->w_list.a[wk].x_start; yk = z->w_list.a[wk].y_start; ck = 0; + } + if(hre) { + fx = hre->a + hre->idx[z->x_id].s; nx = hre->idx[z->x_id].e - hre->idx[z->x_id].s; + fy = hre->a + hre->idx[z->y_id].s; ny = hre->idx[z->y_id].e - hre->idx[z->y_id].s; + } + // if(hre && ((z->x_id == 44 && z->y_id == 45) || (z->x_id == 45 && z->y_id == 44))) { + // fprintf(stderr, "[M::%s]\tutg%.6ul\tq::[%u,\t%u)\t%c\tutg%.6ul\tt::[%u,\t%u)\terr::%u\twn::%u\n", + // __func__, z->x_id+1, z->x_pos_s, z->x_pos_e+1, "+-"[z->y_pos_strand], + // z->y_id+1, z->y_pos_s, z->y_pos_e+1, z->non_homopolymer_errors, (uint32_t)z->w_list.n); + // } + + while(wk < wn) { + m = &(z->w_list.a[wk]); + // if(hre && ((z->x_id == 44 && z->y_id == 45) || (z->x_id == 45 && z->y_id == 44))) { + // fprintf(stderr, "[M::%s]k::%ld\tq::[%u,\t%u)\tt::[%u,\t%u)\terr::%u\tis_ualn::%u\tis_est::%u\n", + // __func__, wk, m->x_start, m->x_end+1, m->y_start, m->y_end+1, m->error, + // (is_ualn_win((*m))), is_est_aln((*m))); + // } + ws = m->x_start; we = m->x_end+1; + os = MAX(xs, ws); oe = MIN(xe, we); + ovlp = ((oe>os)? (oe-os):0); + if(ovlp) { + xl = m->x_end+1-m->x_start; + yl = m->y_end+1-m->y_start; + if((is_ualn_win((*m))) || (is_est_aln((*m)))) { + if(is_ualn_win((*m))) { //unmapped + werr = MAX(xl, yl);///gen_err_unaligned(xl, yl); + } else { + werr = m->error;//shared window + } + if(ovlp < xl) { + werr = (((double)ovlp)/((double)xl))*((double)werr); + } + //skip the whole window + err += werr; xk = m->x_end+1; yk = m->y_end+1; ck = m->clen; + } else { + if(ovlp == xl) { //skip the whole window + err += m->error; xk = m->x_end+1; yk = m->y_end+1; ck = m->clen; + } else { + set_bit_extz_t(ez, (*z), wk); + err += retrieve_npc_cigar_err(&ez, os, oe, &xk, &yk, &ck, fx, nx, fy, ny, ylen, z->y_pos_strand); + } + } + } + tot -= ovlp; + if(xk >= xe) break;//[min_w, max_w] && [s, e) + wk++; if(wk >= wn) break; + xk = z->w_list.a[wk].x_start; yk = z->w_list.a[wk].y_start; ck = 0;//reset + } + assert(!tot); + return err; +} + +void cal_s_interval(ma_ug_t *ug, asg_arc_t *p, ul_ov_t *res) +{ + memset(res, 0, sizeof((*res))); + res->rev = (((p->ul>>32)^(p->v))&((uint32_t)1)); + res->qn = p->ul>>33; res->tn = p->v>>1; + uint32_t ql = ug->g->seq[res->qn].len, tl = ug->g->seq[res->tn].len; + if((p->ul>>32)&1) { + res->qs = 0; res->qe = ((p->ol<=ql)?(p->ol):(ql)); + } else { + res->qe = ql; res->qs = ((p->ol<=res->qe)?(res->qe-p->ol):(0)); + } + + if(p->v&1) { + res->te = tl; res->ts = ((p->ol<=res->te)?(res->te-p->ol):(0)); + } else { + res->ts = 0; res->te = ((p->ol<=tl)?(p->ol):(tl)); + } +} + +uint32_t infer_se(uint32_t qs, uint32_t qe, uint32_t ts, uint32_t te, uint32_t rev, +uint32_t rqs, uint32_t rqe, uint32_t *rts, uint32_t *rte) +{ + if(rqs <= rqe && rqs >= qs && rqe <= qe) { + uint32_t s_shift, e_shift, m; + s_shift = get_offset_adjust(rqs-qs, qe-qs, te-ts); + e_shift = get_offset_adjust(qe-rqe, qe-qs, te-ts); + if(rev) { + m = s_shift; s_shift = e_shift; e_shift = m; + } + // if(rqs == 2623 && rqe == 17620) { + // fprintf(stderr, "[M::%s]\tqs::%u\tqe::%u\tts::%u\tte::%u\trqs::%u\trqe::%u\ts_shift::%u\te_shift::%u\n", __func__, + // qs, qe, ts, te, rqs, rqe, s_shift, e_shift); + // } + (*rts) = ts + s_shift; (*rte) = te - e_shift; + if((*rts) <= (*rte) && (*rts) >= ts && (*rte) <= te) return 1; + } + (*rts) = (*rte) = (uint32_t)-1; + return 0; +} + +uint32_t cal_x_interval(ma_ug_t *ug, ul_ov_t *v, ul_ov_t *w, ul_ov_t *res) +{ + uint32_t os, oe, rqs, rqe, rts, rte; memset(res, 0, sizeof((*res))); + // if(v->qn == 97) { + // fprintf(stderr, "-0-v-[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\n", __func__, + // v->qn+1, "lc"[ug->u.a[v->qn].circ], v->qs, v->qe, "+-"[v->rev], + // v->tn+1, "lc"[ug->u.a[v->tn].circ], v->ts, v->te); + // fprintf(stderr, "-0-w-[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\n", __func__, + // w->qn+1, "lc"[ug->u.a[w->qn].circ], w->qs, w->qe, "+-"[v->rev], + // w->tn+1, "lc"[ug->u.a[w->tn].circ], w->ts, w->te); + // } + if(v->tn == w->qn) { + os = MAX(v->ts, w->qs); oe = MIN(v->te, w->qe); + // if(v->qn == 97) { + // fprintf(stderr, "-1-[M::%s]\tutg%.6u%c->utg%.6u%c\tutg%.6u%c->utg%.6u%c\to::[%u,\t%u)\n", __func__, + // v->qn+1, "lc"[ug->u.a[v->qn].circ], + // v->tn+1, "lc"[ug->u.a[v->tn].circ], + // w->qn+1, "lc"[ug->u.a[w->qn].circ], + // w->tn+1, "lc"[ug->u.a[w->tn].circ], + // os, oe); + // } + if(oe <= os) return 0; + if(infer_se(v->ts, v->te, v->qs, v->qe, v->rev, os, oe, &rqs, &rqe) && + infer_se(w->qs, w->qe, w->ts, w->te, w->rev, os, oe, &rts, &rte)) { + // if(v->qn == 97) { + // fprintf(stderr, "-2-[M::%s]\tutg%.6u%c->utg%.6u%c\tutg%.6u%c->utg%.6u%c\trq::[%u,\t%u)\trt::[%u,\t%u)\n", __func__, + // v->qn+1, "lc"[ug->u.a[v->qn].circ], + // v->tn+1, "lc"[ug->u.a[v->tn].circ], + // w->qn+1, "lc"[ug->u.a[w->qn].circ], + // w->tn+1, "lc"[ug->u.a[w->tn].circ], + // rqs, rqe, rts, rte); + // } + if(rqe > rqs && rte > rts) { + res->qn = v->qn; res->tn = w->tn; res->rev = ((v->rev==w->rev)?0:1); + res->qs = rqs; res->qe = rqe; res->ts = rts; res->te = rte; + return 1; + } + } + } + return 0; +} + + +void gen_shared_interval(ul_ov_t *p, ma_ug_t *ug, kv_ul_ov_t *res) +{ + uint32_t st, et, v, w, i, k, nv, nw; asg_arc_t *av, *aw; + ul_ov_t s1, s2, rr; res->n = 0; + + st = p->qn<<1; et = (p->tn<<1) + (!!(p->rev)); + // if(p->qn == 101 && p->tn == 102) { + // if(p->qn == 97 && p->tn == 98) { + // fprintf(stderr, ">[M::%s]\tutg%.6u%c(%c)->utg%.6u%c(%c)\n", __func__, + // (st>>1)+1, "lc"[ug->u.a[st>>1].circ], "+-"[st&1], + // (et>>1)+1, "lc"[ug->u.a[et>>1].circ], "+-"[et&1]); + // } + v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + w = av[i].v; + cal_s_interval(ug, &(av[i]), &s1); + // if(p->qn == 101 && p->tn == 102) { + // if(p->qn == 97 && p->tn == 98) { + // fprintf(stderr, "+[M::%s]\tutg%.6lu%c(%c)->utg%.6u%c(%c)\n", __func__, + // (av[i].ul>>33)+1, "lc"[ug->u.a[(av[i].ul>>33)].circ], "+-"[(av[i].ul>>32)&1], + // (av[i].v>>1)+1, "lc"[ug->u.a[av[i].v>>1].circ], "+-"[av[i].v&1]); + // } + if(w == et) { + kv_push(ul_ov_t, *res, s1); + } else { + aw = asg_arc_a(ug->g, (w^1)); nw = asg_arc_n(ug->g, (w^1)); + for (k = 0; k < nw; k++) { + if(aw[k].del) continue; + if((aw[k].v>>1) == (st>>1)) continue; + // if(p->qn == 101 && p->tn == 102) { + // if(p->qn == 97 && p->tn == 98) { + // fprintf(stderr, "-[M::%s]\tutg%.6lu%c(%c)->utg%.6u%c(%c)\n", __func__, + // (aw[k].ul>>33)+1, "lc"[ug->u.a[(aw[k].ul>>33)].circ], "+-"[(aw[k].ul>>32)&1], + // (aw[k].v>>1)+1, "lc"[ug->u.a[aw[k].v>>1].circ], "+-"[aw[k].v&1]); + // } + // cal_s_interval(ug, &(aw[k]), &s2); + // if(!cal_x_interval(ug, &s1, &s2, &rr)) continue; + + if(aw[k].v == (et^1)) { + // if(p->qn == 101 && p->tn == 102) { + // if(p->qn == 97 && p->tn == 98) { + // fprintf(stderr, "*[M::%s]\tutg%.6lu%c(%c)->utg%.6u%c(%c)\n", __func__, + // (aw[k].ul>>33)+1, "lc"[ug->u.a[(aw[k].ul>>33)].circ], "+-"[(aw[k].ul>>32)&1], + // (aw[k].v>>1)+1, "lc"[ug->u.a[aw[k].v>>1].circ], "+-"[aw[k].v&1]); + // } + cal_s_interval(ug, &(aw[k]), &s2); + if(cal_x_interval(ug, &s1, &s2, &rr)) { + kv_push(ul_ov_t, *res, rr); + } + } + } + } + } + + st ^= 1; et ^= 1; + v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + w = av[i].v; + cal_s_interval(ug, &(av[i]), &s1); + // if(p->qn == 101 && p->tn == 102) { + // if(p->qn == 97 && p->tn == 98) { + // fprintf(stderr, "+[M::%s]\tutg%.6lu%c(%c)->utg%.6u%c(%c)\n", __func__, + // (av[i].ul>>33)+1, "lc"[ug->u.a[(av[i].ul>>33)].circ], "+-"[(av[i].ul>>32)&1], + // (av[i].v>>1)+1, "lc"[ug->u.a[av[i].v>>1].circ], "+-"[av[i].v&1]); + // } + if(w == et) { + kv_push(ul_ov_t, *res, s1); + } else { + aw = asg_arc_a(ug->g, (w^1)); nw = asg_arc_n(ug->g, (w^1)); + for (k = 0; k < nw; k++) { + if(aw[k].del) continue; + if((aw[k].v>>1) == (st>>1)) continue; + // if(p->qn == 101 && p->tn == 102) { + // if(p->qn == 97 && p->tn == 98) { + // fprintf(stderr, "-[M::%s]\tutg%.6lu%c(%c)->utg%.6u%c(%c)\n", __func__, + // (aw[k].ul>>33)+1, "lc"[ug->u.a[(aw[k].ul>>33)].circ], "+-"[(aw[k].ul>>32)&1], + // (aw[k].v>>1)+1, "lc"[ug->u.a[aw[k].v>>1].circ], "+-"[aw[k].v&1]); + // } + if(aw[k].v == (et^1)) { + // if(p->qn == 101 && p->tn == 102) { + // if(p->qn == 97 && p->tn == 98) { + // fprintf(stderr, "*[M::%s]\tutg%.6lu%c(%c)->utg%.6u%c(%c)\n", __func__, + // (aw[k].ul>>33)+1, "lc"[ug->u.a[(aw[k].ul>>33)].circ], "+-"[(aw[k].ul>>32)&1], + // (aw[k].v>>1)+1, "lc"[ug->u.a[aw[k].v>>1].circ], "+-"[aw[k].v&1]); + // } + cal_s_interval(ug, &(aw[k]), &s2); + if(cal_x_interval(ug, &s1, &s2, &rr)) { + kv_push(ul_ov_t, *res, rr); + } + } + } + } + } +} + +void gen_shared_interval_adv(ul_ov_t *p, ma_ug_t *ug, kv_ul_ov_t *res) +{ + uint32_t st, et, v, w, i, k, z, nv, nw, nz; asg_arc_t *av, *aw, *az; + ul_ov_t s1, s2, s3, s4, rr; res->n = 0; + + st = p->qn<<1; et = (p->tn<<1) + (!!(p->rev)); + v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + w = av[i].v; + cal_s_interval(ug, &(av[i]), &s1); + if(w == et) { + kv_push(ul_ov_t, *res, s1); + } else { + aw = asg_arc_a(ug->g, (w^1)); nw = asg_arc_n(ug->g, (w^1)); + for (k = 0; k < nw; k++) { + if(aw[k].del) continue; + if((aw[k].v>>1) == (st>>1)) continue; + + cal_s_interval(ug, &(aw[k]), &s2); + if(!cal_x_interval(ug, &s1, &s2, &s3)) continue; + if(aw[k].v == (et^1)) { + kv_push(ul_ov_t, *res, s3); + } else { + az = asg_arc_a(ug->g, (aw[k].v^1)); nz = asg_arc_n(ug->g, (aw[k].v^1)); + for (z = 0; z < nz; z++) { + if(az[z].del) continue; + if(az[z].v == et) { + cal_s_interval(ug, &(az[z]), &s4); + if(cal_x_interval(ug, &s3, &s4, &rr)) { + kv_push(ul_ov_t, *res, rr); + } + } + } + } + } + } + } + + st ^= 1; et ^= 1; + v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + w = av[i].v; + cal_s_interval(ug, &(av[i]), &s1); + if(w == et) { + kv_push(ul_ov_t, *res, s1); + } else { + aw = asg_arc_a(ug->g, (w^1)); nw = asg_arc_n(ug->g, (w^1)); + for (k = 0; k < nw; k++) { + if(aw[k].del) continue; + if((aw[k].v>>1) == (st>>1)) continue; + + cal_s_interval(ug, &(aw[k]), &s2); + if(!cal_x_interval(ug, &s1, &s2, &s3)) continue; + if(aw[k].v == (et^1)) { + kv_push(ul_ov_t, *res, s3); + } else { + az = asg_arc_a(ug->g, (aw[k].v^1)); nz = asg_arc_n(ug->g, (aw[k].v^1)); + for (z = 0; z < nz; z++) { + if(az[z].del) continue; + if(az[z].v == et) { + cal_s_interval(ug, &(az[z]), &s4); + if(cal_x_interval(ug, &s3, &s4, &rr)) { + kv_push(ul_ov_t, *res, rr); + } + } + } + } + } + } + } +} + + +void gen_src_shared_interval_adv(uint32_t src, ma_ug_t *ug, kv_ul_ov_t *res) +{ + uint32_t st, v, w, i, k, z, nv, nw, nz, rn; asg_arc_t *av, *aw, *az; + ul_ov_t s1, s2, s3, s4, s5; rn = res->n; ///res->n = 0; + + st = src<<1; + v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + if((av[i].v>>1) == (st>>1)) continue; + w = av[i].v; + cal_s_interval(ug, &(av[i]), &s1); + if(s1.qn == src && s1.tn != src) kv_push(ul_ov_t, *res, s1); + + aw = asg_arc_a(ug->g, (w^1)); + nw = asg_arc_n(ug->g, (w^1)); + for (k = 0; k < nw; k++) { + if(aw[k].del) continue; + if((aw[k].v>>1) == (st>>1)) continue; + + cal_s_interval(ug, &(aw[k]), &s2); + if(!cal_x_interval(ug, &s1, &s2, &s3)) continue; + if(s3.qn == src && s3.tn != src) kv_push(ul_ov_t, *res, s3); + + az = asg_arc_a(ug->g, (aw[k].v^1)); + nz = asg_arc_n(ug->g, (aw[k].v^1)); + for (z = 0; z < nz; z++) { + if(az[z].del) continue; + cal_s_interval(ug, &(az[z]), &s4); + if(!cal_x_interval(ug, &s3, &s4, &s5)) continue; + if(s5.qn == src && s5.tn != src) kv_push(ul_ov_t, *res, s5); + } + } + } + + st ^= 1; + v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + if((av[i].v>>1) == (st>>1)) continue; + w = av[i].v; + cal_s_interval(ug, &(av[i]), &s1); + if(s1.qn == src && s1.tn != src) kv_push(ul_ov_t, *res, s1); + + aw = asg_arc_a(ug->g, (w^1)); + nw = asg_arc_n(ug->g, (w^1)); + for (k = 0; k < nw; k++) { + if(aw[k].del) continue; + if((aw[k].v>>1) == (st>>1)) continue; + + cal_s_interval(ug, &(aw[k]), &s2); + if(!cal_x_interval(ug, &s1, &s2, &s3)) continue; + if(s3.qn == src && s3.tn != src) kv_push(ul_ov_t, *res, s3); + + az = asg_arc_a(ug->g, (aw[k].v^1)); + nz = asg_arc_n(ug->g, (aw[k].v^1)); + for (z = 0; z < nz; z++) { + if(az[z].del) continue; + cal_s_interval(ug, &(az[z]), &s4); + if(!cal_x_interval(ug, &s3, &s4, &s5)) continue; + if(s5.qn == src && s5.tn != src) kv_push(ul_ov_t, *res, s5); + } + } + } + + radix_sort_ul_ov_srt_tn(res->a + rn, res->a + res->n); + if(res->n > rn) { + uint64_t os, oe, on, ovlpq, ovlpt, is_cov; + for (k = rn + 1, i = rn; k <= res->n; k++) { + if(k == res->n || res->a[k].tn != res->a[i].tn) { + on = k - i; + if(k - i > 1) { + for (v = i; v < k; v++) { + if(res->a[v].tn == (uint32_t)-1) continue; + for (z = i; z < k; z++) { + if(v == z) continue; + if(res->a[z].tn == (uint32_t)-1) continue; + if(res->a[v].rev != res->a[z].rev) continue; + + + os = MAX(res->a[v].qs, res->a[z].qs); + oe = MIN(res->a[v].qe, res->a[z].qe); + if(oe <= os) continue; + ovlpq = oe - os; + + os = MAX(res->a[v].ts, res->a[z].ts); + oe = MIN(res->a[v].te, res->a[z].te); + if(oe <= os) continue; + ovlpt = oe - os; + + is_cov = 0; + if(((ovlpq == (res->a[v].qe-res->a[v].qs)) && (ovlpt == (res->a[v].te-res->a[v].ts))) || + ((ovlpq == (res->a[z].qe-res->a[z].qs)) && (ovlpt == (res->a[z].te-res->a[z].ts)))) { + is_cov = 1; + } + + if(!is_cov) { + if(ovlpq <= ((res->a[v].qe-res->a[v].qs)*0.95)) continue; + if(ovlpq <= ((res->a[z].qe-res->a[z].qs)*0.95)) continue; + if(ovlpt <= ((res->a[v].te-res->a[v].ts)*0.95)) continue; + if(ovlpt <= ((res->a[z].te-res->a[z].ts)*0.95)) continue; + } + + if(res->a[v].qs > res->a[z].qs) res->a[v].qs = res->a[z].qs; + if(res->a[v].qe < res->a[z].qe) res->a[v].qe = res->a[z].qe; + if(res->a[v].ts > res->a[z].ts) res->a[v].ts = res->a[z].ts; + if(res->a[v].te < res->a[z].te) res->a[v].te = res->a[z].te; + res->a[z].tn = (uint32_t)-1; on--; + + // uint64_t vd, vz; + // vd = (uint64_t)(res->a[v].qe-res->a[v].qs) + (uint64_t)(res->a[v].te-res->a[v].ts); + // zd = (uint64_t)(res->a[z].qe-res->a[z].qs) + (uint64_t)(res->a[z].te-res->a[z].ts); + // ovlp = ((vd>=zd)?(vd-zd):(zd-vd)); + // if(ovlp > 64) { + // if(vd < zd) { + // res->a[v].tn = (uint32_t)-1; break; + // } else if(vd < zd) { + // res->a[z].tn = (uint32_t)-1; continue; + // } + // } + + // vd = ((res->a[v].qe-res->a[v].qs)>=(res->a[v].te-res->a[v].ts))? + // ((res->a[v].qe-res->a[v].qs)-(res->a[v].te-res->a[v].ts)): + // ((res->a[v].te-res->a[v].ts)-(res->a[v].qe-res->a[v].qs)); + // zd = ((res->a[z].qe-res->a[z].qs)>=(res->a[z].te-res->a[z].ts))? + // ((res->a[z].qe-res->a[z].qs)-(res->a[z].te-res->a[z].ts)): + // ((res->a[z].te-res->a[z].ts)-(res->a[z].qe-res->a[z].qs)); + // if(zd <= vd) { + // res->a[v].tn = (uint32_t)-1; break; + // } else { + // res->a[z].tn = (uint32_t)-1; + // } + } + } + if(on > 1) radix_sort_ul_ov_srt_qs(res->a + i, res->a + k); + } + i = k; + } + } + for (k = z = rn; k < res->n; k++) { + if(res->a[k].tn == (uint32_t)-1) continue; + res->a[z++] = res->a[k]; + } + res->n = z; + } +} + + +uint32_t gen_src_shared_interval_simple(uint32_t src, ma_ug_t *ug, uint64_t *flt, uint64_t flt_n, kv_ul_ov_t *res) +{ + uint32_t st, v, w, i, k, z, nv, nw, nz, rn; asg_arc_t *av, *aw, *az; + ul_ov_t s1, s2, s3, s4, s5; rn = res->n; + + st = src<<1; + v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + if((av[i].v>>1) == (st>>1)) continue; + w = av[i].v; + cal_s_interval(ug, &(av[i]), &s1); + if(s1.qn == src && s1.tn != src) kv_push(ul_ov_t, *res, s1); + + aw = asg_arc_a(ug->g, (w^1)); + nw = asg_arc_n(ug->g, (w^1)); + for (k = 0; k < nw; k++) { + if(aw[k].del) continue; + if((aw[k].v>>1) == (st>>1)) continue; + + cal_s_interval(ug, &(aw[k]), &s2); + if(!cal_x_interval(ug, &s1, &s2, &s3)) continue; + if(s3.qn == src && s3.tn != src) kv_push(ul_ov_t, *res, s3); + + az = asg_arc_a(ug->g, (aw[k].v^1)); + nz = asg_arc_n(ug->g, (aw[k].v^1)); + for (z = 0; z < nz; z++) { + if(az[z].del) continue; + cal_s_interval(ug, &(az[z]), &s4); + if(!cal_x_interval(ug, &s3, &s4, &s5)) continue; + if(s5.qn == src && s5.tn != src) kv_push(ul_ov_t, *res, s5); + } + } + } + + st ^= 1; + v = st; av = asg_arc_a(ug->g, v); nv = asg_arc_n(ug->g, v); + for (i = 0; i < nv; i++) { + if(av[i].del) continue; + if((av[i].v>>1) == (st>>1)) continue; + w = av[i].v; + cal_s_interval(ug, &(av[i]), &s1); + if(s1.qn == src && s1.tn != src) kv_push(ul_ov_t, *res, s1); + + aw = asg_arc_a(ug->g, (w^1)); + nw = asg_arc_n(ug->g, (w^1)); + for (k = 0; k < nw; k++) { + if(aw[k].del) continue; + if((aw[k].v>>1) == (st>>1)) continue; + + cal_s_interval(ug, &(aw[k]), &s2); + if(!cal_x_interval(ug, &s1, &s2, &s3)) continue; + if(s3.qn == src && s3.tn != src) kv_push(ul_ov_t, *res, s3); + + az = asg_arc_a(ug->g, (aw[k].v^1)); + nz = asg_arc_n(ug->g, (aw[k].v^1)); + for (z = 0; z < nz; z++) { + if(az[z].del) continue; + cal_s_interval(ug, &(az[z]), &s4); + if(!cal_x_interval(ug, &s3, &s4, &s5)) continue; + if(s5.qn == src && s5.tn != src) kv_push(ul_ov_t, *res, s5); + } + } + } + + radix_sort_ul_ov_srt_tn(res->a + rn, res->a + res->n); + if(res->n > rn) { + uint64_t os, oe, ovlpq, ovlpt, is_cov, fi = 0; + for (k = rn + 1, i = rn; k <= res->n; k++) { + if(k == res->n || res->a[k].tn != res->a[i].tn) { + for (; fi < flt_n && (flt[fi]>>32) < res->a[i].tn; fi++); + if(fi < flt_n && (flt[fi]>>32) == res->a[i].tn) { + // on = k - i; + if(k - i > 1) { + for (v = i; v < k; v++) { + if(res->a[v].tn == (uint32_t)-1) continue; + for (z = i; z < k; z++) { + if(v == z) continue; + if(res->a[z].tn == (uint32_t)-1) continue; + if(res->a[v].rev != res->a[z].rev) continue; + + os = MAX(res->a[v].qs, res->a[z].qs); + oe = MIN(res->a[v].qe, res->a[z].qe); + if(oe <= os) continue; + ovlpq = oe - os; + + os = MAX(res->a[v].ts, res->a[z].ts); + oe = MIN(res->a[v].te, res->a[z].te); + if(oe <= os) continue; + ovlpt = oe - os; + + is_cov = 0; + if(((ovlpq == (res->a[v].qe-res->a[v].qs)) && (ovlpt == (res->a[v].te-res->a[v].ts))) || + ((ovlpq == (res->a[z].qe-res->a[z].qs)) && (ovlpt == (res->a[z].te-res->a[z].ts)))) { + is_cov = 1; + } + + if(!is_cov) { + if(ovlpq <= ((res->a[v].qe-res->a[v].qs)*0.95)) continue; + if(ovlpq <= ((res->a[z].qe-res->a[z].qs)*0.95)) continue; + if(ovlpt <= ((res->a[v].te-res->a[v].ts)*0.95)) continue; + if(ovlpt <= ((res->a[z].te-res->a[z].ts)*0.95)) continue; + } + + if(res->a[v].qs > res->a[z].qs) res->a[v].qs = res->a[z].qs; + if(res->a[v].qe < res->a[z].qe) res->a[v].qe = res->a[z].qe; + if(res->a[v].ts > res->a[z].ts) res->a[v].ts = res->a[z].ts; + if(res->a[v].te < res->a[z].te) res->a[v].te = res->a[z].te; + res->a[z].tn = (uint32_t)-1; ///on--; + } + } + // if(on > 1) radix_sort_ul_ov_srt_qs(res->a + i, res->a + k); + } + } else { + for (v = i; v < k; v++) res->a[v].tn = (uint32_t)-1; + } + i = k; + } + } + for (k = z = rn; k < res->n; k++) { + if(res->a[k].tn == (uint32_t)-1) continue; + res->a[z] = res->a[k]; res->a[z].sec = ((uint32_t)(0x3fffffff)); + z++; + } + res->n = z; + } + return res->n - rn; +} + +inline void overlap_region2ul_ov_t(overlap_region *in, ul_ov_t *ou, uint64_t tl) +{ + ou->qn = in->x_id; ou->tn = in->y_id; ou->el = 1; + ou->sec = in->non_homopolymer_errors; + ou->rev = in->y_pos_strand; + ou->qs = in->x_pos_s; ou->qe = in->x_pos_e+1; + if(ou->rev) { + ou->ts = tl - (in->y_pos_e+1); + ou->te = tl - in->y_pos_s; + } else { + ou->ts = in->y_pos_s; + ou->te = in->y_pos_e+1; + } +} + +void extend_batch(ul_ov_t *z, int64_t ql, int64_t tl, int64_t *rqs, int64_t *rqe, int64_t *rts, int64_t *rte) +{ + int64_t q0, t0, q1, t1; + (*rqs) = (*rqe) = (*rts) = (*rte) = -1; + if(!(z->rev)) { + q0 = z->qs; t0 = z->ts; + if(q0 <= t0) { + (*rqs) = z->qs - q0; (*rts) = z->ts - q0; + } else { + (*rqs) = z->qs - t0; (*rts) = z->ts - t0; + } + + q1 = ql - z->qe; t1 = tl - z->te; + if(q1 <= t1) { + (*rqe) = z->qe + q1; (*rte) = z->te + q1; + } else { + (*rqe) = z->qe + t1; (*rte) = z->te + t1; + } + } else { + q0 = z->qs; t0 = tl - z->te; + if(q0 <= t0) { + (*rqs) = z->qs - q0; (*rte) = z->te + q0; + } else { + (*rqs) = z->qs - t0; (*rte) = z->te + t0; + } + + q1 = ql - z->qe; t1 = z->ts; + if(q1 <= t1) { + (*rqe) = z->qe + q1; (*rts) = z->ts - q1; + } else { + (*rqe) = z->qe + t1; (*rts) = z->ts - t1; + } + } +} + +uint64_t check_ul_ov_t_consist(ul_ov_t *x, ul_ov_t *y, int64_t ql, int64_t tl, double diff) +{ + if(x->qn == y->qn && x->tn == y->tn && x->rev == y->rev) { + int64_t xqs, xqe, xts, xte, yqs, yqe, yts, yte, os, oe, ovlp; + extend_batch(x, ql, tl, &xqs, &xqe, &xts, &xte); + extend_batch(y, ql, tl, &yqs, &yqe, &yts, &yte); + + os = MAX(xqs, yqs); oe = MIN(xqe, yqe); + if(oe <= os) return 0; + ovlp = oe - os; + if(ovlp <= ((xqe-xqs)*(1-diff))) return 0; + if(ovlp <= ((yqe-yqs)*(1-diff))) return 0; + + os = MAX(xts, yts); oe = MIN(xte, yte); + if(oe <= os) return 0; + if(ovlp <= ((xte-xts)*(1-diff))) return 0; + if(ovlp <= ((yte-yts)*(1-diff))) return 0; + return 1; + } + return 0; +} + +ul_ov_t* get_mask_interval(ul_ov_t *in, kv_ul_ov_t *idx, uint64_t *ii, int64_t ql, int64_t tl, uint64_t *n, uint64_t *n_skip) +{ + int64_t idx_n = idx->n, i = (*ii), m; ul_ov_t *a, z; + (*n) = (*n_skip) = 0; + if(i >= idx_n) i = idx_n-1; + if(i < 0) i = 0; + // if(in->qn == 101 && in->tn == 102) { + // fprintf(stderr, "-0-[M::%s]\tutg%.6ul\t%c\tutg%.6ul\ti::%ld\tidx_n::%ld\n", __func__, + // in->qn+1, "+-"[in->rev], in->tn+1, i, idx_n); + // } + if(i >= 0 && i < idx_n) { + while (i >= 0 && in->tn <= idx->a[i].tn) i--; + if(i < 0 && idx_n > 0 && in->tn == idx->a[0].tn) i = 0; + // if(in->qn == 101 && in->tn == 102) { + // fprintf(stderr, "-1-[M::%s]\tutg%.6ul\t%c\tutg%.6ul\ti::%ld\tidx_n::%ld\n", __func__, + // in->qn+1, "+-"[in->rev], in->tn+1, i, idx_n); + // } + if(i >= 0) { + while (i < idx_n && in->tn > idx->a[i].tn) i++; + // if(in->qn == 101 && in->tn == 102) { + // fprintf(stderr, "-2-[M::%s]\tutg%.6ul\t%c\tutg%.6ul\ti::%ld\tidx_n::%ld\n", __func__, + // in->qn+1, "+-"[in->rev], in->tn+1, i, idx_n); + // } + if(i < idx_n && in->tn == idx->a[i].tn) { + for (m = i, a = idx->a + i; i < idx_n && in->tn == idx->a[i].tn; i++) { + if(!check_ul_ov_t_consist(in, &(idx->a[i]), ql, tl, 0.06)) { + (*n_skip)++; continue; + } + if(m != i) { + z = idx->a[i]; idx->a[i] = idx->a[m]; idx->a[m] = z; + } + m++; (*n)++; + } + // if(in->qn == 101 && in->tn == 102) { + // fprintf(stderr, "-3-[M::%s]\tutg%.6ul\t%c\tutg%.6ul\ti::%ld\tidx_n::%ld\n", __func__, + // in->qn+1, "+-"[in->rev], in->tn+1, i, idx_n); + // } + (*ii) = i; + if((*n)) return a; + } + } + } + (*ii) = i; + return NULL; +} + +inline uint64_t is_mask_err_full(ul_ov_t *sa, uint64_t sn, uint64_t qs, uint64_t qe, uint64_t ts, uint64_t te) +{ + uint64_t k; + for (k = 0; k < sn; k++) { + if(sa[k].qs <= qs && sa[k].qe >= qe && sa[k].ts <= ts && sa[k].te >= te) break; + } + if(k < sn) return 1; + return 0; +} + +int64_t cal_exact_len(bit_extz_t *ez, int64_t rev, ul_ov_t *sa, uint64_t sn, int64_t ylen, int64_t *xoff, int64_t *yoff, int64_t *exac, int64_t *err, int64_t backward) +{ + (*xoff) = (*yoff) = (*exac) = (*err) = 0; + if(!ez->cigar.n) return 0; + int64_t cn = ez->cigar.n, op, ck, xk, yk, xs, xe, ys, ye, se; + if(!backward) { + xk = ez->ts; yk = ez->ps; + for (ck = 0; ck < cn; ck++) { + xs = xk; ys = yk; + op = ez->cigar.a[ck]>>14; + se = (ez->cigar.a[ck]&(0x3fff)); + if(op!=2) xk += se; + if(op!=3) yk += se; + xe = xk; ye = yk; + if(!op) {///exact match + (*exac) += se; continue; + } + ///if there is an unmasked error + if((!sn) || (!is_mask_err_full(sa, sn, xs, xe, ((rev)?(ylen-ye):(ys)), ((rev)?(ylen-ys):(ye))))) { + (*xoff) = xs - ez->ts; (*yoff) = ys - ez->ps; + return 0; + } + (*exac) = 0; (*err) += se;///if the error has been masked + } + } else { + xk = ez->te+1; yk = ez->pe+1; + for (ck = cn-1; ck >= 0; ck--) { + xe = xk; ye = yk; + op = ez->cigar.a[ck]>>14; + se = (ez->cigar.a[ck]&(0x3fff)); + if(op!=2) xk -= se; + if(op!=3) yk -= se; + xs = xk; ys = yk; + if(!op) {///exact match + (*exac) += se; continue; + } + ///if there is an unmasked error + if((!sn) || (!is_mask_err_full(sa, sn, xs, xe, ((rev)?(ylen-ye):(ys)), ((rev)?(ylen-ys):(ye))))) { + (*xoff) = ez->te+1-xe; (*yoff) = ez->pe+1-ye; + return 0; + } + (*exac) = 0; (*err) += se;///if the error has been masked + } + + } + (*xoff) = ez->te+1-ez->ts; (*yoff) = ez->pe+1-ez->ps; + return 1; +} + +int64_t cal_exact_batch(overlap_region *z, ul_ov_t *sa, uint64_t sn, int64_t ylen, uint64_t *q0l, uint64_t *t0l, uint64_t *e0l, uint64_t *q1l, uint64_t *t1l, uint64_t *e1l, ma_ug_t *ug) +{ + int64_t wn = z->w_list.n, wk, xk, yk, is_t, is_f, err0, err1, tot, mask_win = 0; window_list *m; bit_extz_t ez; + int64_t qs, qe, ts, te, rev = !!(z->y_pos_strand), qoff, toff, elen, sube; + tot = z->non_homopolymer_errors; + if(!tot) { + (*q0l) = (*q1l) = z->x_pos_e+1-z->x_pos_s; + (*t0l) = (*t1l) = z->y_pos_e+1-z->y_pos_s; + (*e0l) = (*e1l) = z->x_pos_e+1-z->x_pos_s; + return 0; + } + (*q0l) = (*t0l) = (*e0l) = (*q1l) = (*t1l) = (*e1l) = (uint64_t)-1; + wk = xk = yk = -1; if(!wn) return INT32_MAX; + + ///forward + (*q0l) = (*t0l) = (*e0l) = err0 = 0; + wk = 0; xk = z->w_list.a[wk].x_start; yk = z->w_list.a[wk].y_start; is_t = 0; + if((xk == z->x_pos_s) && (yk == z->y_pos_s)) is_t = 1; + if((!is_t) && (sn > 0)) {///if the flanking unmapped regions could be masked + qs = z->x_pos_s; qe = xk; + if(!rev) { + ts = z->y_pos_s; te = yk; + } else { + ts = ylen - yk; te = ylen - z->y_pos_s; + } + is_t = is_mask_err_full(sa, sn, qs, qe, ts, te); + if(is_t) { + (*q0l) += qe - qs; (*t0l) += te - ts; (*e0l) = 0; + } + } + if(is_t) { + for (; wk < wn; wk++) { + m = &(z->w_list.a[wk]); + qs = m->x_start; qe = m->x_end+1; + if(!rev) { + ts = m->y_start; te = m->y_end+1; + } else { + ts = ylen-(m->y_end+1); te = ylen-m->y_start; + } + + if((is_ualn_win((*m))) || ((is_est_aln((*m))) && (m->error > 0))) {///unmapped + if(is_mask_err_full(sa, sn, qs, qe, ts, te)) { + (*q0l) += qe - qs; (*t0l) += te - ts; (*e0l) = 0; mask_win = 1; + continue; + } + break; + } + if(m->error == 0) {///an exactly matched window + (*q0l) += qe - qs; (*t0l) += te - ts; (*e0l) += qe - qs; + continue; + } + set_bit_extz_t(ez, (*z), wk); + is_f = cal_exact_len(&ez, rev, sa, sn, ylen, &qoff, &toff, &elen, &sube, 0); + (*q0l) += qoff; (*t0l) += toff; err0 += sube; + ///exactly match + if(elen == qoff && elen == toff) (*e0l) += elen; + else (*e0l) = elen; + if(!is_f) break; + } + } + + + ///backward + (*q1l) = (*t1l) = (*e1l) = err1 = 0; + wk = wn-1; xk = z->w_list.a[wk].x_end+1; yk = z->w_list.a[wk].y_end+1; is_t = 0; + if((xk == (z->x_pos_e+1)) && (yk == (z->y_pos_e+1))) is_t = 1; + if((!is_t) && (sn > 0)) {///if the flanking unmapped regions could be masked + qs = xk; qe = z->x_pos_e+1; + if(!rev) { + ts = yk; te = z->y_pos_e+1; + } else { + ts = ylen-(z->y_pos_e+1); te = ylen-yk; + } + is_t = is_mask_err_full(sa, sn, qs, qe, ts, te); + if(is_t) { + (*q1l) += qe - qs; (*t1l) += te - ts; (*e1l) = 0; + } + } + if(is_t) { + for (; wk >= 0; wk--) { + m = &(z->w_list.a[wk]); + qs = m->x_start; qe = m->x_end+1; + if(!rev) { + ts = m->y_start; te = m->y_end+1; + } else { + ts = ylen-(m->y_end+1); te = ylen-m->y_start; + } + + if((is_ualn_win((*m))) || ((is_est_aln((*m))) && (m->error > 0))) {///unmapped + if(is_mask_err_full(sa, sn, qs, qe, ts, te)) { + (*q1l) += qe - qs; (*t1l) += te - ts; (*e1l) = 0; mask_win = 1; + continue; + } + break; + } + if(m->error == 0) {///an exactly matched window + (*q1l) += qe - qs; (*t1l) += te - ts; (*e1l) += qe - qs; + continue; + } + set_bit_extz_t(ez, (*z), wk); + is_f = cal_exact_len(&ez, rev, sa, sn, ylen, &qoff, &toff, &elen, &sube, 1); + (*q1l) += qoff; (*t1l) += toff; err1 += sube; + ///exactly match + if(elen == qoff && elen == toff) (*e1l) += elen; + else (*e1l) = elen; + if(!is_f) break; + } + } + + if((*q0l) >= (z->x_pos_e+1-z->x_pos_s) && (*t0l) >= (z->y_pos_e+1-z->y_pos_s)) { + // if((!(((*q0l) == (*q1l)) && ((*t0l) == (*t1l)) && (err0 == err1)))/** || (!(err0 == tot))**/) { + // fprintf(stderr, "[M::%s]\tutg%.6u%c\txl::%u\tx::[%u,\t%u)\t%c\tutg%.6u%c\tyl::%u\ty::[%u,\t%u)\terr::%u\twn::%u\n", + // __func__, + // z->x_id+1, "lc"[ug->u.a[z->x_id].circ], ug->u.a[z->x_id].len, z->x_pos_s, z->x_pos_e+1, + // "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[ug->u.a[z->y_id].circ], ug->u.a[z->y_id].len, z->y_pos_s, z->y_pos_e+1, + // z->non_homopolymer_errors, (uint32_t)z->w_list.n); + // uint64_t k; + // for (k = 0; k < z->w_list.n; k++) { + // m = &(z->w_list.a[k]); + // fprintf(stderr, "k::%ld[M::%s]\tutg%.6u%c\twx::[%u,\t%u)\t%c\tutg%.6u%c\twy::[%u,\t%u)\terr::%d\tualn::%u\test::%u\n", k, __func__, + // z->x_id+1, "lc"[ug->u.a[z->x_id].circ], m->x_start, m->x_end+1, + // "+-"[z->y_pos_strand], + // z->y_id+1, "lc"[ug->u.a[z->y_id].circ], m->y_start, m->y_end+1, m->error, + // (is_ualn_win((*m))), (is_est_aln((*m)))); + // } + // fprintf(stderr, "[M::%s]\tutg%.6ul\tutg%.6ul\terr0::%ld\terr1::%ld\ttot::%ld\n", __func__, + // z->x_id+1, z->y_id+1, err0, err1, tot); + // fprintf(stderr, "[M::%s]\tutg%.6ul\tq0l::%lu\tt0l::%lu\te0l::%lu\tutg%.6ul\tq1l::%lu\tt1l::%lu\te1l::%lu\n", __func__, + // z->x_id+1, *q0l, *t0l, *e0l, z->y_id+1, *q1l, *t1l, *e1l); + // } + assert(((*q0l) == (*q1l)) && ((*t0l) == (*t1l)) && (err0 == err1)); + assert((mask_win) || (err0 == tot)); + return 0; + } + + // if(!(err0+err1 < tot)) { + // fprintf(stderr, "[M::%s]\tutg%.6ul\tutg%.6ul\terr0::%ld\terr1::%ld\ttot::%ld\n", __func__, + // z->x_id+1, z->y_id+1, err0, err1, tot); + // fprintf(stderr, "[M::%s]\tutg%.6ul\tq0l::%lu\tt0l::%lu\te0l::%lu\tutg%.6ul\tq1l::%lu\tt1l::%lu\te1l::%lu\n", __func__, + // z->x_id+1, *q0l, *t0l, *e0l, z->y_id+1, *q1l, *t1l, *e1l); + // } + + assert(err0+err1 < tot); + return tot-(err0+err1); +} + +void push_graph_bin_back(overlap_region_alloc* ol, const ul_idx_t *udb, hpc_re_t *hre, +double erate, uint64_t maxe, uint64_t minov, uint64_t rid, asg64_v *b0, asg64_v *b1, mask_ul_ov_t *mk) +{ + uint64_t k, i, m, si, sn, skip_n, zt, re; overlap_region t, *z; ul_ov_t p, *sa; int64_t npc; + uint64_t q0l, t0l, e0l, q1l, t1l, e1l, mm, occ[3]; + b0->n = b1->n = 0; + + mk->srt.n = mk->idx.n = 0; + gen_src_shared_interval_adv(rid, udb->ug, &(mk->srt)); + kv_resize(uint64_t, mk->idx, ol->length); + for (k = 0; k < ol->length; k++) { + kv_push(uint64_t, mk->idx, (((uint64_t)ol->list[k].y_id)<<32)|((uint64_t)k)); + } + radix_sort_gfa64(mk->idx.a, mk->idx.a+mk->idx.n); + for (i = si = b0->n = 0, occ[0] = occ[1] = occ[2] = 0; i < mk->idx.n; i++) { + k = (uint32_t)mk->idx.a[i]; + z = &(ol->list[k]); + overlap_region2ul_ov_t(z, &p, udb->ug->u.a[z->y_id].len); + if(((p.qe-p.qs) >= minov) && ((p.te-p.ts) >= minov)) { + if(!trans_ovlp_connect(&p, udb->ug)) continue;//could be eaisly detected + if(p.sec == 0) {///no error + zt = ((uint32_t)-1); zt <<= 32; zt |= (i<<1); occ[2]++; + kv_push(uint64_t, *b0, zt); continue; + } + sa = get_mask_interval(&p, &(mk->srt), &si, udb->ug->u.a[p.qn].len, udb->ug->u.a[p.tn].len, &sn, &skip_n); + re = cal_exact_batch(z, sa, sn, udb->ug->u.a[p.tn].len, &q0l, &t0l, &e0l, &q1l, &t1l, &e1l, udb->ug); + if(!re) {//no unmask errors + zt = ((uint32_t)-1); zt <<= 32; zt |= (i<<1); occ[2]++; + kv_push(uint64_t, *b0, zt); continue; + } + + mm = ((re <= maxe)?((uint64_t)(0x8000000000000000)):(0)); + ///left end + if(q0l >= minov && t0l >= minov) { + zt = MIN(q0l, t0l); zt <<= 32; zt |= (i<<1); zt |= mm; occ[!!mm]++; + kv_push(uint64_t, *b0, zt); + } + + ///right end + if(q1l >= minov && t1l >= minov) { + zt = MIN(q1l, t1l); zt <<= 32; zt |= (i<<1); zt += 1; zt |= mm; occ[!!mm]++; + kv_push(uint64_t, *b0, zt); + } + } + } + + // radix_sort_gfa64(b0->a, b0->a+b0->n); + // uint64_t *a0, *a1, *a2, a0n, a1n, a2n; + // a2 = b0->a; a2n = occ[0]; + // a1 = a2 + a2n; a1n = occ[1]; + // a0 = a1 + a1n; a0n = occ[2]; + + + fprintf(stderr, "\n[M::%s]\tutg%.6lu%c\t#s::%u\n", __func__, rid+1, "lc"[udb->ug->u.a[rid].circ], (uint32_t)mk->srt.n); + for (k = 0; k < mk->srt.n; k++) { + fprintf(stderr, "[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\n", __func__, + mk->srt.a[k].qn+1, "lc"[udb->ug->u.a[mk->srt.a[k].qn].circ], mk->srt.a[k].qs, mk->srt.a[k].qe, "+-"[mk->srt.a[k].rev], + mk->srt.a[k].tn+1, "lc"[udb->ug->u.a[mk->srt.a[k].tn].circ], mk->srt.a[k].ts, mk->srt.a[k].te); + } + + + + for (k = m = 0; k < ol->length; k++) { + z = &(ol->list[k]); + if(z->non_homopolymer_errors == 0) continue; + p.qn = rid; p.tn = ol->list[k].y_id; p.el = 1; + p.sec = ol->list[k].non_homopolymer_errors; + p.rev = ol->list[k].y_pos_strand; + p.qs = ol->list[k].x_pos_s; p.qe = ol->list[k].x_pos_e+1; + if(p.rev) { + p.ts = udb->ug->u.a[p.tn].len - (ol->list[k].y_pos_e+1); + p.te = udb->ug->u.a[p.tn].len - ol->list[k].y_pos_s; + } else { + p.ts = ol->list[k].y_pos_s; + p.te = ol->list[k].y_pos_e+1; + } + // gen_shared_interval(&p, udb->ug, bl); + // gen_shared_interval_adv(&p, udb->ug, bl); + // if(!trans_ovlp_connect(&p, udb->ug)) continue; + // assert(z->x_id == rid); + // if(!get_high_simi(z, erate, maxe, minov, &e0, &e1)) continue; + npc = cal_npc_err(z, p.qs, p.qe, hre, udb->ug->u.a[p.tn].len); + if(npc == INT32_MAX || npc < 0) continue; + if(((uint64_t)npc <= maxe) && ((uint64_t)npc <= ((p.qe - p.qs)*erate)) && ((uint64_t)npc <= ((p.te - p.ts)*erate))) { + ; + } else if(((uint64_t)npc > maxe) && ((p.qe - p.qs) > minov) && ((p.te - p.ts) > minov)) { + ; + } + + // if((z->x_id == 44 && z->y_id == 45) || (z->x_id == 45 && z->y_id == 44)) + // if(npc <= 4) + { + // int64_t nnpc; + // nnpc = cal_npc_err(z, p.qs, p.qe, NULL, udb->ug->u.a[p.tn].len); + // fprintf(stderr, "[M::%s]\tutg%.6u%c->utg%.6u%c\terr::%u\tnpc::%ld\t#s::%u\n", __func__, p.qn+1, "lc"[udb->ug->u.a[p.qn].circ], + // p.tn+1, "lc"[udb->ug->u.a[p.tn].circ], ol->list[k].non_homopolymer_errors, npc, (uint32_t)bl->n); + // uint64_t t; + // for (t = 0; t < bl->n; t++) { + // fprintf(stderr, "[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\n", __func__, + // bl->a[t].qn+1, "lc"[udb->ug->u.a[bl->a[t].qn].circ], bl->a[t].qs, bl->a[t].qe, "+-"[bl->a[t].rev], + // bl->a[t].tn+1, "lc"[udb->ug->u.a[bl->a[t].tn].circ], bl->a[t].ts, bl->a[t].te); + // } + } + + if(k != m) { + t = ol->list[k]; + ol->list[k] = ol->list[m]; + ol->list[m] = t; + } + m++; + } + ol->length = m; +} + +void full_lst_set(emask_t *a, uint64_t a_n, ul_ov_t *sa, uint64_t sn, uint64_t skip_n) +{ + uint64_t ff = 0, k, i; int64_t sql, stl, os, oe, ovlp; + if(sn == 0 && skip_n == 0) { + ff = 1; + } else if(skip_n > 0) { + ff = 0; + } else {///sn > 0 && skip_n == 0 + for (k = 0; k < sn; k++) { + sql = sa[k].qe - sa[k].qs; + stl = sa[k].te - sa[k].ts; + for (i = 0; i < a_n && sql > 0 && stl > 0; i++) { + os = MAX(sa[k].qs, a[i].qs); oe = MIN(sa[k].qe, a[i].qe); + ovlp = ((oe>os)?(oe-os):(0)); sql -= ovlp; + + os = MAX(sa[k].ts, a[i].ts); oe = MIN(sa[k].te, a[i].te); + ovlp = ((oe>os)?(oe-os):(0)); stl -= ovlp; + } + if((sql > 256) && (sql > ((sa[k].qe - sa[k].qs)*0.06))) break; + if((sql <= 256) && (sql > ((sa[k].qe - sa[k].qs)*0.6))) break; + if((stl > 256) && (stl > ((sa[k].te - sa[k].ts)*0.06))) break; + if((stl <= 256) && (stl > ((sa[k].te - sa[k].ts)*0.6))) break; + } + if(k < sn) ff = 0; + else ff = 1; + } + for (k = 0; k < a_n; k++) a[k].full = ff; +} + +void push_emask0(kv_emask_t *res, uint64_t q0l, uint64_t t0l, uint64_t e0l, uint64_t q1l, uint64_t t1l, uint64_t e1l, +uint64_t end, uint64_t is_pe, uint64_t minov, ul_ov_t *p) +{ + emask_t *m; + m = &(res->a[res->n++]); memset(m, 0, sizeof((*m))); + m->dir = end; m->pe = is_pe; + m->tn = p->tn; m->rev = p->rev; m->rn = (uint32_t)-1; + if(!end) {///left end + assert(q0l >= minov && t0l >= minov); + m->el = e0l; + m->qs = p->qs; m->qe = p->qs + q0l; + if(!(m->rev)) { + m->ts = p->ts; m->te = p->ts + t0l; + } else { + m->te = p->te; m->ts = p->te - t0l; + } + } else {///right end + assert(q1l >= minov && t1l >= minov); + m->el = e1l; + m->qe = p->qe; m->qs = p->qe - q1l; + if(!(m->rev)) { + m->te = p->te; m->ts = p->te - t1l; + } else { + m->ts = p->ts; m->te = p->ts + t1l; + } + } +} + +void push_emask_lst(mask_ul_ov_t *mk, overlap_region_alloc* ol, uint64_t minov, ma_ug_t *ug, uint64_t *a, uint64_t an, kv_emask_t *res, uint64_t is_pe) +{ + uint64_t i, l, sn, si, re, cn, skip_n; overlap_region *z; ul_ov_t p, *sa; + uint64_t q0l, t0l, e0l, q1l, t1l, e1l; emask_t *m; + if(is_pe) { + for (i = 0; i < an; i++) { + a[i] <<= 32; a[i] >>= 32; + } + radix_sort_gfa64(a, a+an); + for (i = 1, l = si = 0; i <= an; i++) { + if(i == an || (a[i]>>1) != (a[l]>>1)) { + // k = (uint32_t)mk->idx.a[a[l]>>1]; + z = &(ol->list[(uint32_t)mk->idx.a[a[l]>>1]]); + overlap_region2ul_ov_t(z, &p, ug->u.a[z->y_id].len); + assert(i<=l+2); + assert((p.qe-p.qs) >= minov); + assert((p.te-p.ts) >= minov); + assert(p.sec > 0); + sa = get_mask_interval(&p, &(mk->srt), &si, ug->u.a[p.qn].len, ug->u.a[p.tn].len, &sn, &skip_n); + re = cal_exact_batch(z, sa, sn, ug->u.a[p.tn].len, &q0l, &t0l, &e0l, &q1l, &t1l, &e1l, ug); + assert(re); + cn = i - l; + + push_emask0(res, q0l, t0l, e0l, q1l, t1l, e1l, a[l]&1, ((i==(l+2))?1:0), minov, &p); l++; + if(l < i) push_emask0(res, q0l, t0l, e0l, q1l, t1l, e1l, a[l]&1, ((i==(l+2))?1:0), minov, &p); + // fprintf(stderr, "[M::%s]\tres->n::%u\tcn::%lu\n", __func__, (uint32_t)res->n, cn); + full_lst_set(res->a+res->n-cn, cn, sa, sn, skip_n); + l = i; + } + } + } else { + for (i = 0; i < an; i++) { + a[i] <<= 32; a[i] >>= 32; + z = &(ol->list[(uint32_t)mk->idx.a[a[i]>>1]]); + overlap_region2ul_ov_t(z, &p, ug->u.a[z->y_id].len); + assert((p.qe-p.qs) >= minov); + assert((p.te-p.ts) >= minov); + if(p.sec > 0) { + sa = get_mask_interval(&p, &(mk->srt), &si, ug->u.a[p.qn].len, ug->u.a[p.tn].len, &sn, &skip_n); + re = cal_exact_batch(z, sa, sn, ug->u.a[p.tn].len, &q0l, &t0l, &e0l, &q1l, &t1l, &e1l, ug); + assert(re == 0); + } + + m = &(res->a[res->n++]); memset(m, 0, sizeof((*m))); + m->dir = 2; m->pe = 0; m->tn = p.tn; m->rev = p.rev; m->full = 1; m->el = (uint32_t)-1; m->rn = (uint32_t)-1; + m->qs = p.qs; m->qe = p.qe; m->ts = p.ts; m->te = p.te; + } + } +} + +void srt_kv_emask_t(kv_emask_t *res, mask_ul_ov_t *mk, uint32_t rid, ma_ug_t *ug) +{ + uint64_t k, m, z; ul_ov_t *p; + mk->srt.n = mk->idx.n = 0; + kv_resize(uint64_t, mk->idx, res->n); + kv_resize(ul_ov_t, mk->srt, res->n); + + for (k = 0; k < res->n; k++) { + m = k + 1; z = (((uint64_t)res->a[k].tn)<<32)|(k<<1); + if((m < res->n) && (res->a[k].tn == res->a[m].tn) && (res->a[k].rev == res->a[m].rev) && + (res->a[k].pe) && (res->a[m].pe) && (res->a[k].dir == 0 && res->a[m].dir == 1)) { + z |= 1; + } + kv_push(uint64_t, mk->idx, z); + } + radix_sort_gfa64(mk->idx.a, mk->idx.a+mk->idx.n); + for (z = 0; z < mk->idx.n; z++) { + k = ((uint32_t)mk->idx.a[z])>>1; + kv_pushp(ul_ov_t, mk->srt, &p); + p->tn = res->a[k].tn; p->qn = res->a[k].el; + p->qs = res->a[k].qs; p->qe = res->a[k].qe; + p->ts = res->a[k].ts; p->te = res->a[k].te; + p->rev = res->a[k].rev; p->el = res->a[k].full; + m = res->a[k].dir; m <<= 1; m |= (uint32_t)res->a[k].pe; p->sec = m; + + if(mk->idx.a[z]&1) { + k++; + kv_pushp(ul_ov_t, mk->srt, &p); + p->tn = res->a[k].tn; p->qn = res->a[k].el; + p->qs = res->a[k].qs; p->qe = res->a[k].qe; + p->ts = res->a[k].ts; p->te = res->a[k].te; + p->rev = res->a[k].rev; p->el = res->a[k].full; + m = res->a[k].dir; m <<= 1; m |= (uint32_t)res->a[k].pe; p->sec = m; + } + } + + for (k = 0; k < res->n; k++) { + p = &(mk->srt.a[k]); + res->a[k].tn = p->tn; res->a[k].el = p->qn; + res->a[k].qs = p->qs; res->a[k].qe = p->qe; + res->a[k].ts = p->ts; res->a[k].te = p->te; + res->a[k].rev = p->rev; res->a[k].full = p->el; res->a[k].rn = (uint32_t)-1; + m = p->sec; res->a[k].pe = m&1; res->a[k].dir = m>>1; + } + + // for (k = 0; k < res->n; k++) { + // int64_t fqs, fqe, fts, fte, ql = ug->g->seq[rid].len, tl = ug->g->seq[res->a[k].tn].len; + // p = &(mk->srt.a[k]); extend_batch(p, ql, tl, &fqs, &fqe, &fts, &fte); + // ///if(res->a[k].full == 0) + // { + // // fprintf(stderr, "+[M::%s]\tutg%.6ul\tq::[%u,\t%u)[%ld,\t%ld)\t%c\tutg%.6ul\tt::[%u,\t%u)[%ld,\t%ld)\tel::%u\tfu::%u\n", __func__, + // // rid+1, res->a[k].qs, res->a[k].qe, fqs, fqe, "+-"[res->a[k].rev], res->a[k].tn+1, res->a[k].ts, res->a[k].te, fts, fte, res->a[k].el, res->a[k].full); + // // fprintf(stderr, "utg%.6ul\tq::[%u,\t%u)[%ld,\t%ld)\t%c\tutg%.6ul\tt::[%u,\t%u)[%ld,\t%ld)\tel::%u\tfu::%u\n", + // // rid+1, res->a[k].qs, res->a[k].qe, fqs, fqe, "+-"[res->a[k].rev], res->a[k].tn+1, res->a[k].ts, res->a[k].te, fts, fte, res->a[k].el, res->a[k].full); + // } + // } +} + +void push_graph_bin(overlap_region_alloc* ol, const ul_idx_t *udb, double erate, uint64_t maxe, uint64_t minov, uint64_t rid, asg64_v *b0, mask_ul_ov_t *mk, kv_emask_t *res) +{ + uint64_t k, i, si, sn, zt, re, skip_n; overlap_region *z; ul_ov_t p, *sa; + uint64_t q0l, t0l, e0l, q1l, t1l, e1l, mm, occ[3], mocc, mn[3]; + b0->n = 0; + mocc = (udb->ug->u.a[rid].len/sizeof((*(res->a))))/8; if(mocc < 16) mocc = 16; + + // fprintf(stderr, "\n[M::%s]\tutg%.6lu%c\n", __func__, rid+1, "lc"[udb->ug->u.a[rid].circ]); + + mk->srt.n = mk->idx.n = 0; + gen_src_shared_interval_adv(rid, udb->ug, &(mk->srt)); + kv_resize(uint64_t, mk->idx, ol->length); + for (k = 0; k < ol->length; k++) { + kv_push(uint64_t, mk->idx, (((uint64_t)ol->list[k].y_id)<<32)|((uint64_t)k)); + } + radix_sort_gfa64(mk->idx.a, mk->idx.a+mk->idx.n);///sort by the unitig id + // if(rid == 4) { + // sa = mk->srt.a; sn = mk->srt.n; + // for (si = 0; si < sn; si++) { + // fprintf(stderr, "si::%lu[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\n", si, __func__, + // sa[si].qn+1, "lc"[udb->ug->u.a[sa[si].qn].circ], sa[si].qs, sa[si].qe, "+-"[sa[si].rev], + // sa[si].tn+1, "lc"[udb->ug->u.a[sa[si].tn].circ], sa[si].ts, sa[si].te); + // } + // } + + // if(ol->length > 0 && ol->list[0].x_id == 29033) fprintf(stderr, "[M::%s]\t0\t\n", __func__); + + + for (i = si = b0->n = 0, occ[0] = occ[1] = occ[2] = 0; i < mk->idx.n; i++) { + k = (uint32_t)mk->idx.a[i]; + z = &(ol->list[k]); + overlap_region2ul_ov_t(z, &p, udb->ug->u.a[z->y_id].len); + if(((p.qe-p.qs) >= minov) && ((p.te-p.ts) >= minov)) { + if(!trans_ovlp_connect(&p, udb->ug)) continue;//could be eaisly detected + if(p.sec == 0) {///no error + zt = ((uint32_t)-1); zt <<= 32; zt |= (i<<1); occ[2]++; + kv_push(uint64_t, *b0, zt); continue; + } + sa = get_mask_interval(&p, &(mk->srt), &si, udb->ug->u.a[p.qn].len, udb->ug->u.a[p.tn].len, &sn, &skip_n); + // if(p.qn == 4 && p.tn == 3) { + // fprintf(stderr, "[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\tsn::%lu\tskip_n::%lu\n", __func__, + // p.qn+1, "lc"[udb->ug->u.a[p.qn].circ], p.qs, p.qe, "+-"[p.rev], + // p.tn+1, "lc"[udb->ug->u.a[p.tn].circ], p.ts, p.te, sn, skip_n); + // uint32_t ci; + // for (ci = 0; ci < sn; ci++) { + // fprintf(stderr, "sa::[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\n", __func__, + // sa[ci].qn+1, "lc"[udb->ug->u.a[sa[ci].qn].circ], sa[ci].qs, sa[ci].qe, "+-"[sa[ci].rev], + // sa[ci].tn+1, "lc"[udb->ug->u.a[sa[ci].tn].circ], sa[ci].ts, sa[ci].te); + // } + // } + + + re = cal_exact_batch(z, sa, sn, udb->ug->u.a[p.tn].len, &q0l, &t0l, &e0l, &q1l, &t1l, &e1l, udb->ug); + if(!re) {//no unmask errors + zt = ((uint32_t)-1); zt <<= 32; zt |= (i<<1); occ[2]++; + kv_push(uint64_t, *b0, zt); continue; + } + // if(p.qn == 4 && p.tn == 3) { + // fprintf(stderr, "[M::%s]\tutg%.6u%c\tq0l::%lu\tt0l::%lu\te0l::%lu\tutg%.6u%c\tq1l::%lu\tt1l::%lu\te1l::%lu\n", __func__, + // p.qn+1, "lc"[udb->ug->u.a[p.qn].circ], q0l, t0l, e0l, + // p.tn+1, "lc"[udb->ug->u.a[p.tn].circ], q1l, t1l, e1l); + // } + mm = ((re <= maxe)?((uint64_t)(0x8000000000000000)):(0)); + ///left end + if(q0l >= minov && t0l >= minov) { + zt = MIN(q0l, t0l); zt <<= 32; zt |= (i<<1); zt |= mm; occ[!!mm]++; + kv_push(uint64_t, *b0, zt); + } + + ///right end + if(q1l >= minov && t1l >= minov) { + zt = MIN(q1l, t1l); zt <<= 32; zt |= (i<<1); zt += 1; zt |= mm; occ[!!mm]++; + kv_push(uint64_t, *b0, zt); + } + } + } + + radix_sort_gfa64(b0->a, b0->a+b0->n); + uint64_t *a0, *a1, *a2, a0n, a1n, a2n, *a, m; + a2 = b0->a; a2n = occ[0]; mn[2] = mocc>>2;//high error + a1 = a2 + a2n; a1n = occ[1]; mn[1] = mocc>>1;//low error + a0 = a1 + a1n; a0n = occ[2]; mn[0] = mocc>>2;//0 error + mn[1] = mocc - mn[0] - mn[2]; + + sn = a2n; a = a2;//high error + for (i = 0, si = sn>>1; i < si; i++) { + m = a[i]; a[i] = a[sn-i-1]; a[sn-i-1] = m; + } + + sn = a1n; a = a1;//low error + for (i = 0, si = sn>>1; i < si; i++) { + m = a[i]; a[i] = a[sn-i-1]; a[sn-i-1] = m; + } + + sn = a0n; a = a0;//0 error + for (i = 0; i < sn; i++) { + z = &(ol->list[(((uint32_t)a[i])>>1)]); + q0l = z->x_pos_e+1-z->x_pos_s; + t0l = z->y_pos_e+1-z->y_pos_s; + m = ((uint32_t)-1) - (MIN(q0l, t0l)); m <<= 32; m |= ((uint32_t)a[i]); + a[i] = m; + } + radix_sort_gfa64(a, a+sn);///sort by length + ///a1 -> a2 -> a0 + if(mn[1] > a1n) mn[1] = a1n; + if(mn[2] > a2n) mn[2] = a2n; + if(mn[0] > a0n) mn[0] = a0n; + + ///reassign a1 + mn[1] = mocc - mn[0] - mn[2]; + if(mn[1] > a1n) mn[1] = a1n; + + ///reassign a2 + mn[2] = mocc - mn[1] - mn[0]; + if(mn[2] > a2n) mn[2] = a2n; + + ///reassign a0 + mn[0] = mocc - mn[1] - mn[2]; + if(mn[0] > a0n) mn[0] = a0n; + + res->n = res->m = mn[0]+mn[1]+mn[2]; + MALLOC(res->a, res->n); + res->n = 0; + // if(ol->length > 0 && ol->list[0].x_id == 29033) fprintf(stderr, "[M::%s]\t1\t\n", __func__); + // fprintf(stderr, "\n[M::%s]\tutg%.6lu%c\t#s::%u\tmn[0]::%lu\tmn[1]::%lu\tmn[2]::%lu\n", __func__, + // rid+1, "lc"[udb->ug->u.a[rid].circ], (uint32_t)mk->srt.n, mn[0], mn[1], mn[2]); + push_emask_lst(mk, ol, minov, udb->ug, a2, mn[2], res, 1); + // if(ol->length > 0 && ol->list[0].x_id == 29033) fprintf(stderr, "[M::%s]\t2\t\n", __func__); + // fprintf(stderr, "[M::%s]\tutg%.6lu%c\tres->n::%u\n", __func__, rid+1, "lc"[udb->ug->u.a[rid].circ], res->n); + push_emask_lst(mk, ol, minov, udb->ug, a1, mn[1], res, 1); + // if(ol->length > 0 && ol->list[0].x_id == 29033) fprintf(stderr, "[M::%s]\t3\t\n", __func__); + // fprintf(stderr, "[M::%s]\tutg%.6lu%c\tres->n::%u\n", __func__, rid+1, "lc"[udb->ug->u.a[rid].circ], res->n); + push_emask_lst(mk, ol, minov, udb->ug, a0, mn[0], res, 0); + // if(ol->length > 0 && ol->list[0].x_id == 29033) fprintf(stderr, "[M::%s]\t4\t\n", __func__); + // fprintf(stderr, "[M::%s]\tutg%.6lu%c\tres->n::%u\n", __func__, rid+1, "lc"[udb->ug->u.a[rid].circ], res->n); + srt_kv_emask_t(res, mk, rid, udb->ug); + // if(ol->length > 0 && ol->list[0].x_id == 29033) fprintf(stderr, "[M::%s]\t5\t\n", __func__); + + // for (k = 0; k < mk->srt.n; k++) { + // fprintf(stderr, "[M::%s]\tutg%.6u%c\tq::[%u,\t%u)\t%c\tutg%.6u%c\tt::[%u,\t%u)\n", __func__, + // mk->srt.a[k].qn+1, "lc"[udb->ug->u.a[mk->srt.a[k].qn].circ], mk->srt.a[k].qs, mk->srt.a[k].qe, "+-"[mk->srt.a[k].rev], + // mk->srt.a[k].tn+1, "lc"[udb->ug->u.a[mk->srt.a[k].tn].circ], mk->srt.a[k].ts, mk->srt.a[k].te); + // } +} + +static void worker_for_graph_bin(void *data, long i, int tid) // callback for kt_for() +{ + ug_bin_t *s = (ug_bin_t*)data; double erate; int64_t wl; overlap_region *aux_o; + ha_ovec_buf_t *b = s->hab[tid]; asg64_v b0; + uint32_t high_occ = asm_opt.polyploidy + 1; uint64_t cnt; + char *seq = s->ug->u.a[i].s; int64_t len = s->ug->u.a[i].len; + if((!s->is_ovlp) && (s->is_cnt)) s->idx_n.a[i] = 0; + if(s->ug->g->seq[i].del) return; + if(!seq) { + resize_UC_Read(&(b->self_read), len); + retrieve_u_seq(NULL, b->self_read.seq, &(s->ug->u.a[i]), 0, 0, len, NULL); + seq = b->self_read.seq; + } + + // if(i!=77960) return; + + // asprintf(&as, "\n[M::%s] rid::%ld, len::%lu, name::%.*s\n", __func__, s->id+i, s->len[i], (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a); + // push_vlog(&(overall_zdbg->a[s->id+i]), as); free(as); as = NULL; + + if(!s->is_ovlp) { + if(s->is_cnt) { + // s->idx_n.a[i] = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, + // s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, NULL, 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); + s->idx_n.a[i] = ug_map_lchain_simple(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, + s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 1, 1, 0.2, 3, s->is_HPC, NULL, 0, NULL, 0, s->mini_cut, s->chain_cut); + } else { + // cnt = ug_map_lchain(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, s->bw_thres_double, + // s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], 0, NULL, 0, s->mini_cut, s->chain_cut, NULL); + cnt = ug_map_lchain_simple(b->abl, i, seq, len, s->w, s->k, &(s->udb), NULL, NULL, s->bw_thres, + s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 1, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], 0, NULL, 0, s->mini_cut, s->chain_cut); + assert(cnt == ((s->idx_n.a[i+1]-s->idx_n.a[i]))); + } + return; + } + + // if(i == 160) { + // fprintf(stderr, "\n-1-[M::%s] utg%.6u%c, rid::%ld, is_ovlp::%d, is_cnt::%d, len::%ld, str::%u\n", + // __func__, (uint32_t)i+1, "lc"[s->ug->u.a[i].circ], i, s->is_ovlp, s->is_cnt, len, (uint32_t)(!!seq)); + // } + + + // ug_map_lchain(b->abl, rid, seq, len, s->w, s->k, &(s->udb), &b->olist, &b->clist, bw_low, bw_high, + // s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 0, 1, 0.2, 3, + // s->is_HPC, s->idx_a.a + s->idx_n.a[rid], cnt, s->srt_a.a, s->srt_a.n, s->mini_cut, s->chain_cut, fi); + cnt = ((s->idx_n.a[i+1]-s->idx_n.a[i])); + ug_map_lchain_simple(b->abl, i, seq, len, s->w, s->k, &(s->udb), &b->olist, &b->clist, s->bw_thres, + s->max_n_chain, 1, NULL, &(b->tmp_region), NULL, &(b->sp), &high_occ, NULL, 1, 1, 0.2, 3, s->is_HPC, s->idx_a.a + s->idx_n.a[i], cnt, s->srt_a.a, s->srt_a.n, s->mini_cut, s->chain_cut); + clear_Cigar_record(&b->cigar1); clear_Round2_alignment(&b->round2); + + erate = s->diff_ov; wl = MIN((((double)THRESHOLD_MAX_SIZE)/erate), WINDOW); aux_o = NULL; + ug_lalign(&b->olist, &b->clist, &(s->udb), s->uopt, seq, len, NULL/**&b->self_read**/, &b->ovlp_read, + &b->correct, &b->exz, aux_o, erate, wl, i, s->k, s->chain_cut, NULL); + aux_o = gen_aux_ovlp(&b->olist);///must be here + ug_lalign(&b->olist, &b->clist, &(s->udb), s->uopt, seq, len, NULL/**&b->self_read**/, &b->ovlp_read, + &b->correct, &b->exz, aux_o, erate, wl, i, s->k, s->chain_cut, NULL); + + copy_asg_arr(b0, s->ll[tid].srt.a); + push_graph_bin(&b->olist, &(s->udb), s->diff_bin, s->max_diff, s->min_bin_len, i, &b0, &(s->mk[tid]), &(s->mm->a[i])); + copy_asg_arr(s->ll[tid].srt.a, b0); + // if(!gen_trans_adaptive_aln(s, i, b, bl, seq, len, s->filter, s->diff_ec_ul, s->diff_ec_ul_double, s->bw_thres, s->bw_thres_double)) { + // gen_trans_adaptive_aln(s, i, b, bl, seq, len, NULL, s->diff_ec_ul_double, s->diff_ec_ul_double, s->bw_thres_double, s->bw_thres_double); + // } +} + +emask_t* get_emask_ovlp(idx_emask_t *idx, uint32_t qn, uint32_t tn, uint32_t *occ, uint32_t *st) +{ + emask_t *a = NULL; (*occ) = 0; if(st) (*st) = (uint32_t)-1; + if(qn >= idx->n) return a; + uint32_t k; + for (k = 0; k < idx->a[qn].n && idx->a[qn].a[k].tn < tn; k++); + if(k < idx->a[qn].n && idx->a[qn].a[k].tn == tn) { + a = idx->a[qn].a + k; if(st) (*st) = k; + for ((*occ) = k; k < idx->a[qn].n && idx->a[qn].a[k].tn == tn; k++); + (*occ) = k - (*occ); + return a; + } + return a; +} + +void detect_sysm_graph_bin(idx_emask_t *idx, uint32_t rid) +{ + kv_emask_t *r = &(idx->a[rid]); uint32_t k, an, st; + for (k = 0; k < r->n; k++) { + get_emask_ovlp(idx, r->a[k].tn, rid, &an, &st); + r->a[k].rn = (uint32_t)-1; + if(!an) r->a[k].rn = st; + } +} + +static void worker_for_graph_bin_sysm(void *data, long i, int tid) // callback for kt_for() +{ + ug_bin_t *s = (ug_bin_t*)data; + if(s->ug->g->seq[i].del) return; + if((s->is_cnt) && (!s->is_ovlp)) detect_sysm_graph_bin(s->mm, i); + if((!s->is_cnt) && (s->is_ovlp)) srt_kv_emask_t(&(s->mm->a[i]), &(s->mk[tid]), i, s->udb.ug); + if((s->is_cnt) && (s->is_ovlp)) detect_sysm_graph_bin(s->mm, i); +} + +ul_ov_t* get_trans_ul_ov_t(ug_trans_t *s, uint32_t qn, uint32_t tn) +{ + ha_mzl_t *f = &(s->srt_a.a[qn]); + if(!(f->rev)) return NULL; + kv_ul_ov_t *bl = &(s->ll[(uint32_t)(f->x)].tk); + uint64_t k = f->rid; k <<= 32; k += f->pos; + // if(!(bl->a[k].qn == (f->x>>32))) { + // fprintf(stderr, "[M::%s::] k::%lu, qn::%u, tn::%u, x>>32::%lu, (uint32_t)x::%u\n", + // __func__, k, qn, tn, (f->x>>32), (uint32_t)(f->x)); + // } + // if(!(bl->a[k].qn == (f->x>>32))) { + // fprintf(stderr, "[M::%s::] k::%lu, bl->a[k].qn::%u, (f->x>>32)::%lu, (uint32_t)(f->x)::%u\n", + // __func__, k, bl->a[k].qn, (f->x>>32), (uint32_t)(f->x)); + // } + assert(bl->a[k].qn == (f->x>>32)); + for (; (k < bl->n) && (bl->a[k].qn == (f->x>>32)); k++) { + if(bl->a[k].qn == bl->a[k].tn) continue; + if(bl->a[k].tn == tn) return &(bl->a[k]); + } + return NULL; +} + +double inline cal_trans_ov_w(ul_ov_t *z) +{ + double nw[2], ml, uml; + ml = z->qe - z->qs; uml = z->sec; ml -= uml; + nw[0] = (ml*CHAIN_MATCH) - (uml*CHAIN_UNMATCH); + ml = z->te - z->ts; uml = z->sec; ml -= uml; + nw[1] = (ml*CHAIN_MATCH) - (uml*CHAIN_UNMATCH); + return MIN(nw[0], nw[1]); +} + +static void worker_for_sysm_trans_ovlp(void *data, long i, int tid) // callback for kt_for() +{ + ug_trans_t *s = (ug_trans_t*)data; + uint64_t k; ul_ov_t *z; double w0, w1; + ha_mzl_t *f = &(s->srt_a.a[i]); + if(!(f->rev)) return; + kv_ul_ov_t *bl = &(s->ll[(uint32_t)(f->x)].tk); + k = f->rid; k <<= 32; k += f->pos; + // if(!(bl->a[k].qn == (f->x>>32))) { + // fprintf(stderr, "[M::%s::] k::%lu, bl->a[k].qn::%u, (f->x>>32)::%lu, (uint32_t)(f->x)::%u\n", + // __func__, k, bl->a[k].qn, (f->x>>32), (uint32_t)(f->x)); + // } + assert(bl->a[k].qn == (f->x>>32)); + for (; (k < bl->n) && (bl->a[k].qn == (f->x>>32)); k++) { + if(bl->a[k].qn == bl->a[k].tn) { + bl->a[k].qs = bl->a[k].qe = (uint32_t)-1; + continue; + } + + w0 = cal_trans_ov_w(&(bl->a[k])); + z = get_trans_ul_ov_t(s, bl->a[k].tn, bl->a[k].qn); + if(!z) { + if((!(s->keep_unsymm_arc)) || (w0 <= 0)) { + bl->a[k].qs = bl->a[k].qe = (uint32_t)-1; + } + continue; + } + if(bl->a[k].qn > bl->a[k].tn) continue; + + w1 = cal_trans_ov_w(z); + if(w0 <= 0 && w1 <= 0) { + bl->a[k].qs = bl->a[k].qe = (uint32_t)-1; + z->qs = z->qe = (uint32_t)-1; + continue; + } + if(w0 > w1) { + // (*z) = bl->a[k];///cannot copy, this will affect tn&&qn + z->qs = bl->a[k].ts; z->qe = bl->a[k].te; + z->ts = bl->a[k].qs; z->te = bl->a[k].qe; + z->sec = bl->a[k].sec; z->el = bl->a[k].el; z->rev = bl->a[k].rev; + // z->qn = bl->a[k].tn; z->tn = bl->a[k].qn; + } else { + // bl->a[k] = (*z);///cannot copy, this will affect tn&&qn + bl->a[k].ts = z->qs; bl->a[k].te = z->qe; + bl->a[k].qs = z->ts; bl->a[k].qe = z->te; + bl->a[k].sec = z->sec; bl->a[k].el = z->el; bl->a[k].rev = z->rev; + // bl->a[k].tn = z->qn; bl->a[k].qn = z->tn; + } + } +} + + +static void worker_for_ul_recorrect_alignment(void *data, long i, int tid) // callback for kt_for() +{ + utepdat_t *s = (utepdat_t*)data; + ha_ovec_buf_t *b = s->hab[tid]; + glchain_t *bl = &(s->ll[tid]); + int64_t /**rid = s->id+i,**/ winLen = MIN((((double)THRESHOLD_MAX_SIZE)/s->opt->diff_ec_ul), WINDOW), is_correct; + // uint64_t align = 0; + int fully_cov, abnormal; + // if(UL_INF.a[s->id+i].rlen != s->len[i]) { + // fprintf(stderr, "[M::%s] rid:%ld, s->len:%lu, UL_INF->rlen:%u\n", __func__, s->id+i, s->len[i], UL_INF.a[s->id+i].rlen); + // } + is_correct = ck_ul_alignment(&(UL_INF.a[s->id+i])); + if(is_correct) { + assert((UL_INF.a[s->id+i].rlen == s->len[i]) && (!s->seq[i])); + return; + } + assert(UL_INF.a[s->id+i].rlen&((uint32_t)(0x80000000))); + UL_INF.a[s->id+i].rlen<<=1; UL_INF.a[s->id+i].rlen>>=1; + assert((UL_INF.a[s->id+i].rlen == s->len[i])); + + // void *km = s->buf?(s->buf[tid]?s->buf[tid]->km:NULL):NULL; + // if(s->id+i!=41927 && s->id+i!=47072 && s->id+i!=67641 && s->id+i!=90305 && s->id+i!=698342 && s->id+i!=329421) { + // return; + // } + // if(s->id+i!=41927) return; + + // fprintf(stderr, "\n[M::%s] rid:%ld, len:%lu\n", __func__, s->id+i, s->len[i]); + // if (memcmp(UL_INF.nid.a[s->id+i].a, "d0aab024-b3a7-40fb-83cc-22c3d6d951f8", UL_INF.nid.a[s->id+i].n-1)) return; + // fprintf(stderr, "[M::%s::] ==> len: %lu\n", __func__, s->len[i]); + ha_get_ul_candidates_interface(b->abl, i, s->seq[i], s->len[i], s->opt->w, s->opt->k, s->uu, &b->olist, &b->olist_hp, &b->clist, s->opt->bw_thres, + s->opt->max_n_chain, 1, NULL/**&(b->k_flag)**/, &b->r_buf, &(b->tmp_region), NULL, &(b->sp), 1, NULL); + + clear_Cigar_record(&b->cigar1); + clear_Round2_alignment(&b->round2); + // return; + // b->num_correct_base += overlap_statistics(&b->olist, NULL, 0); + + b->self_read.seq = s->seq[i]; b->self_read.length = s->len[i]; b->self_read.size = 0; + correct_ul_overlap(&b->olist, s->uu, &b->self_read, &b->correct, &b->ovlp_read, &b->POA_Graph, &b->DAGCon, + &b->cigar1, &b->hap, &b->round2, &b->r_buf, &(b->tmp_region.w_list), 0, 1, &fully_cov, &abnormal, s->opt->diff_ec_ul, winLen, NULL); + + // uint64_t k; + // for (k = 0; k < b->olist.length; k++) { + // if(b->olist.list[k].is_match == 1) b->num_correct_base += b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; + // if(b->olist.list[k].is_match == 2) b->num_recorrect_base += b->olist.list[k].x_pos_e+1-b->olist.list[k].x_pos_s; + // } + + + // gl_chain_refine(&b->olist, &b->correct, &b->hap, bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], km); + gl_chain_refine_advance_combine(s->buf[tid], &(UL_INF.a[s->id+i]), &b->olist, &b->correct, &b->hap, &(s->sps[tid]), bl, &(s->gdp[tid]), s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, tid, NULL); + // return; + // b->num_read_base += b->self_read.length; + // b->num_correct_base += b->correct.corrected_base; + // b->num_recorrect_base += b->round2.dumy.corrected_base; + memset(&b->self_read, 0, sizeof(b->self_read)); + + + + is_correct = ck_ul_alignment(&(UL_INF.a[s->id+i])); + if(is_correct) b->num_correct_base++; + s->hab[tid]->num_read_base++; + + // fprintf(stderr, "[M::%s] rid:%ld, dd:%u\n", __func__, s->id+i, UL_INF.a[s->id+i].dd); + // int64_t mem[6], mem_hab[6]; + // if(get_utepdat_t_mem_tid(s, tid, mem, mem_hab)>((int64_t)5*(int64_t)1073741824)) { + // fprintf(stderr, "[M::%s::tid->%d::rid->%ld] buffer[0]: %.3fGB(%.3fGB::%.3fGB::%.3fGB::%.3fGB::%.3fGB), buffer[1]: %.3fGB, buffer[2]: %.3fGB, buffer[3]: %.3fGB, buffer[4]: %.3fGB, buffer[5]: %.3fGB\n", + // __func__, tid, i, mem[0]/1073741824.0, + // mem_hab[0]/1073741824.0, mem_hab[1]/1073741824.0, mem_hab[2]/1073741824.0, + // mem_hab[3]/1073741824.0, mem_hab[4]/1073741824.0, + // mem[1]/1073741824.0, mem[2]/1073741824.0, + // mem[3]/1073741824.0, mem[4]/1073741824.0, mem[5]/1073741824.0); + // } + + // align = kv_ul_ov_t_statistics(&(bl->tk), i, &(b->num_recorrect_base)); + // if(align == s->len[i]) { + // free(s->seq[i]); s->seq[i] = NULL; + // } + // b->num_correct_base += align; + + // uint64_t k; + // b->num_read_base += overlap_statistics(&b->olist, NULL, NULL, 1); + // for (k = 0; k < bl->tk.n; k++) { + // if(bl->tk.a[k].sec == 0) b->num_correct_base += bl->tk.a[k].qe - bl->tk.a[k].qs; + // if(bl->tk.a[k].sec > 0) b->num_recorrect_base += bl->tk.a[k].qe - bl->tk.a[k].qs; + // } + // for (k = 0; k < bl->lo.n; k++) { + // b->num_read_base += bl->lo.a[k].qe - bl->lo.a[k].qs; + // } + + // uint32_t l1 = overlap_statistics(&b->olist, s->uu->ug, 1), l2 = overlap_statistics(&b->olist, s->uu->ug, 2); + // + // if(l1 == 0 && l2 > 0) fprintf(stderr, "[M::%s::%lu::no_match]\n", UL_INF.nid.a[s->id+i].a, s->len[i]); + // fprintf(stderr, "[M::%s::%lu::] l1->%u; l2->%u\n", UL_INF.nid.a[s->id+i].a, s->len[i], l1, l2); + // fprintf(stderr, "[M::%s::rid->%ld] done\n", __func__, s->id+i); + // exit(1); +} + + +void dump_gaf(mg_gres_a *hits, const mg_gchains_t *gs, uint32_t only_p) +{ + if (gs == NULL || gs->n_gc == 0 || gs->n_lc == 0) return; + uint64_t i, j; + int64_t q_span; + mg_gres_t *p = NULL; + kv_pushp(mg_gres_t, *hits, &p); memset(p, 0, sizeof(*p)); + p->n_gc = 0; p->n_lc = 0; p->qid = gs->qid; p->qlen = gs->qlen; + // p->n_gc = gs->n_gc; p->n_lc = gs->n_lc; p->qid = gs->qid; p->qlen = gs->qlen; + // MALLOC(p->gc, p->n_gc); memcpy(p->gc, gs->gc, p->n_gc); + for (i = 0; i < (uint64_t)gs->n_gc; ++i) { + const mg_gchain_t *t = &gs->gc[i];///one of the gchain + if(only_p && t->id != t->parent) continue; + if (t->cnt == 0) continue; + p->n_gc++; p->n_lc += t->cnt; + } + if (p->n_gc == 0) { + hits->n--; + return; + } + MALLOC(p->gc, p->n_gc); MALLOC(p->lc, p->n_lc); + p->n_gc = p->n_lc = 0; + for (i = 0; i < (uint64_t)gs->n_gc; ++i) { + const mg_gchain_t *t = &gs->gc[i];///one of the gchain + if(only_p && t->id != t->parent) continue; + if (t->cnt == 0) continue; + p->gc[p->n_gc] = *t; p->gc[p->n_gc].off = p->n_lc; + for (j = 0; j < (uint64_t)t->cnt; ++j) { + const mg_llchain_t *q = &gs->lc[t->off + j]; + p->lc[p->n_lc+j].cnt = q->cnt; + p->lc[p->n_lc+j].score = q->score; + p->lc[p->n_lc+j].v = q->v; + if(q->cnt) { + q_span = (int32_t)(gs->a[q->off].y>>32&0xff); + p->lc[p->n_lc+j].qs = (int32_t)gs->a[q->off].y + 1 - q_span;///calculated by the first lchain + p->lc[p->n_lc+j].ts = (int32_t)gs->a[q->off].x + 1 - q_span;///calculated by the first lchain + p->lc[p->n_lc+j].qe = (int32_t)gs->a[q->off + q->cnt - 1].y + 1; + p->lc[p->n_lc+j].te = (int32_t)gs->a[q->off + q->cnt - 1].x + 1; + } else { + p->lc[p->n_lc+j].qs = p->lc[p->n_lc+j].qe = p->lc[p->n_lc+j].ts = p->lc[p->n_lc+j].te = (uint32_t)-1; + } + + // mg_sprintf_lite(s, "%c%s", "><"[q->v&1], g->seg[q->v>>1].name); + } + p->n_gc++; p->n_lc += t->cnt; + } +} + + +int64_t get_utepdat_t_mem(const utepdat_t *b, int64_t is_print) +{ + int64_t i, mem[7] = {0}, tt[6] = {0}; + for (i = 0; i < b->n_thread; i++) { + get_utepdat_t_mem_tid(b, i, tt, NULL); + mem[0] += tt[0]; mem[1] += tt[1]; mem[2] += tt[2]; mem[3] += tt[3]; mem[4] += tt[4]; mem[5] += tt[5]; + } + + for (i = 0; i < b->n; ++i) mem[6] += b->len[i]; + mem[6] += (sizeof(*(b->len))*b->n) + (sizeof(*(b->seq))*b->n); + if(is_print) { + for (i = 0; i < 7; i++) { + fprintf(stderr, "[M::%s] size of buffer[%ld]: %.3fGB, %.3fKB, %ldB\n", + __func__, i, mem[i]/1073741824.0, mem[i]/1048576.0, mem[i]); + } + } + + return mem[0] + mem[1] + mem[2] + mem[3] + mem[4] + mem[5] + mem[6]; +} + +static void *worker_ul_pipeline(void *data, int step, void *in) // callback for kt_pipeline() +{ + uldat_t *p = (uldat_t*)data; + ///uint64_t total_base = 0, total_pair = 0; + if (step == 0) { // step 1: read a block of sequences + int ret; + uint64_t l; + utepdat_t *s; + CALLOC(s, 1); + s->ha_flt_tab = p->ha_flt_tab; s->ha_idx = p->ha_idx; s->id = p->total_pair; + s->opt = p->opt; s->ug = p->ug; s->uopt = p->uopt; s->rg = p->rg; + while ((ret = kseq_read(p->ks)) >= 0) + { + if (p->ks->seq.l < (uint64_t)p->opt->k) continue; + if (s->n == s->m) { + s->m = s->m < 16? 16 : s->m + (s->n>>1); + REALLOC(s->len, s->m); + REALLOC(s->seq, s->m); + } + /**if(asm_opt.flag & HA_F_VERBOSE_GFA)**/ { + kv_push(uint64_t, p->nn, p->ks->name.l+p->nn.tl); + kv_resize(char, p->nn.cc, p->ks->name.l+p->nn.tl); + memcpy(p->nn.cc.a+p->nn.tl, p->ks->name.s, p->ks->name.l); + p->nn.tl += p->ks->name.l; + } + l = p->ks->seq.l; + MALLOC(s->seq[s->n], l); + s->sum_len += l; + memcpy(s->seq[s->n], p->ks->seq.s, l); + s->len[s->n++] = l; + if (s->sum_len >= p->chunk_size) break; + } + p->total_pair += s->n; + if (s->sum_len == 0) free(s); + else return s; + } + else if (step == 1) { // step 2: alignment + uint64_t i; + utepdat_t *s = (utepdat_t*)in; + CALLOC(s->mzs, p->n_thread); + CALLOC(s->sps, p->n_thread); + CALLOC(s->gcs, s->n); + + s->buf = (mg_tbuf_t**)calloc(p->n_thread, sizeof(mg_tbuf_t*)); + for (i = 0; i < p->n_thread; ++i) s->buf[i] = mg_tbuf_init(); + + kt_for(p->n_thread, worker_for_ul_alignment, s, s->n); + for (i = 0; i < (uint64_t)s->n; ++i) { + free(s->seq[i]); + p->total_base += s->len[i]; + } + free(s->seq); free(s->len); + + for (i = 0; i < p->n_thread; ++i) { + mg_tbuf_destroy(s->buf[i]); + free(s->mzs[i].a); free(s->sps[i].a); + } + + free(s->buf); free(s->mzs); free(s->sps); + return s; + } + else if (step == 2) { // step 3: dump + utepdat_t *s = (utepdat_t*)in; + uint64_t i; + for (i = 0; i < (uint64_t)s->n; ++i) { + // if(s->pos[i].s == (uint64_t)-1) continue; + // kv_push(pe_hit, p->hits.a, s->pos[i]); + if(!s->gcs[i]) continue; + dump_gaf(&(p->hits), s->gcs[i], 1); + free(s->gcs[i]->gc); free(s->gcs[i]->a); free(s->gcs[i]->lc); free(s->gcs[i]); + } + free(s->gcs); + free(s); + } + return 0; +} + +int alignment_ul_pipeline(uldat_t* sl, const enzyme *fn) +{ + double index_time = yak_realtime(); + int i; + for (i = 0; i < fn->n; i++){ + gzFile fp; + if ((fp = gzopen(fn->a[i], "r")) == 0) return 0; + sl->ks = kseq_init(fp); + kt_pipeline(3, worker_ul_pipeline, sl, 3); + kseq_destroy(sl->ks); + gzclose(fp); + } + sl->hits.total_base = sl->total_base; + sl->hits.total_pair = sl->total_pair; + fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); + return 1; +} + +void push_uc_block_t(const ug_opt_t *uopt, kv_ul_ov_t *z, char **seq, uint64_t *len, uint64_t b_id) +{ + uint64_t k, l, rid; + for (k = 1, l = 0; k <= z->n; k++) { + if(k == z->n || z->a[k].qn != z->a[l].qn) { + rid = b_id + z->a[l].qn; + // fprintf(stderr, "rid->%lu, b_id->%lu, l->%lu, z->a[l].qn->%u, len[z->a[l].qn]->%lu, seq[z->a[l].qn]->%u\n", rid, b_id, l, z->a[l].qn, len[z->a[l].qn], seq[z->a[l].qn]?1:0); + append_ul_t(&UL_INF, &rid, NULL, 0, seq[z->a[l].qn], len[z->a[l].qn], z->a + l, k - l, P_CHAIN_COV, uopt, 0); + // append_ul_t_back(&UL_INF, &rid, NULL, 0, seq[z->a[l].qn], len[z->a[l].qn], z->a + l, k - l, P_CHAIN_COV); + l = k; + } + } +} + +static void *worker_ul_scall_pipeline(void *data, int step, void *in) // callback for kt_pipeline() +{ + uldat_t *p = (uldat_t*)data; + ///uint64_t total_base = 0, total_pair = 0; + if (step == 0) { // step 1: read a block of sequences + int ret; + uint64_t l; + utepdat_t *s; + CALLOC(s, 1); + s->ha_flt_tab = p->ha_flt_tab; s->ha_idx = p->ha_idx; s->id = p->total_pair; + s->opt = p->opt; s->uu = p->uu; s->uopt = p->uopt; s->rg = p->rg; + while ((ret = kseq_read(p->ks)) >= 0) + { + if ((p->ks->seq.l < (uint64_t)p->opt->k) || (p->ks->seq.l < asm_opt.ul_min_base)) continue; + if (s->n == s->m) { + s->m = s->m < 16? 16 : s->m + (s->n>>1); + REALLOC(s->len, s->m); + REALLOC(s->seq, s->m); + } + + append_ul_t(&UL_INF, NULL, p->ks->name.s, p->ks->name.l, NULL, 0, NULL, 0, P_CHAIN_COV, s->uopt, 0); + l = p->ks->seq.l; + MALLOC(s->seq[s->n], l); + s->sum_len += l; + memcpy(s->seq[s->n], p->ks->seq.s, l); + // fprintf(stderr, "s->n->%d, l->%lu\n", s->n, l); + s->len[s->n++] = l; + if (s->sum_len >= p->chunk_size) break; + } + p->total_pair += s->n; + if (s->sum_len == 0) free(s); + else return s; + } + else if (step == 1) { // step 2: alignment + utepdat_t *s = (utepdat_t*)in; + + uint64_t i; + CALLOC(s->hab, p->n_thread); CALLOC(s->ll, p->n_thread); + CALLOC(s->sps, p->n_thread); + // CALLOC(s->buf, p->n_thread); + for (i = 0; i < p->n_thread; ++i) { + // s->buf[i] = mg_tbuf_init(); + // s->hab[i] = ha_ovec_buf_init(s->buf[i]->km, 0, 0, 1); + // s->buf[i] = NULL; + // s->hab[i] = ha_ovec_buf_init(NULL, 0, 0, 1); + s->hab[i] = ha_ovec_init(0, 0, 1); + } + // fprintf(stderr, "[M::%s::Start] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); + kt_for(p->n_thread, worker_for_ul_scall_alignment, s, s->n); + // fprintf(stderr, "[M::%s::Done] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); + ///debug + /** + uint64_t i; + CALLOC(s->mzs, p->n_thread); + CALLOC(s->sps, p->n_thread); + CALLOC(s->gcs, s->n); + + s->buf = (mg_tbuf_t**)calloc(p->n_thread, sizeof(mg_tbuf_t*)); + for (i = 0; i < p->n_thread; ++i) s->buf[i] = mg_tbuf_init(); + + kt_for(p->n_thread, worker_for_ul_alignment, s, s->n); + for (i = 0; i < (uint64_t)s->n; ++i) { + free(s->seq[i]); + p->total_base += s->len[i]; + } + free(s->seq); free(s->len); + + for (i = 0; i < p->n_thread; ++i) { + mg_tbuf_destroy(s->buf[i]); + free(s->mzs[i].a); free(s->sps[i].a); + } + **/ + for (i = 0; i < p->n_thread; ++i) { + s->num_bases += s->hab[i]->num_read_base; + s->num_corrected_bases += s->hab[i]->num_correct_base; + s->num_recorrected_bases += s->hab[i]->num_recorrect_base; + // mg_tbuf_destroy(s->buf[i]); + ha_ovec_destroy(s->hab[i]); kv_destroy(s->sps[i]); + free(s->ll[i].lo.a); /**free(s->ll[i].tk.a);**/ free(s->ll[i].srt.a.a); free(s->ll[i].tc.a); + } + free(s->hab); free(s->sps); + /**free(s->ll);**/ // free(s->buf); + //free(s->mzs); free(s->sps); + return s; + } + else if (step == 2) { // step 3: dump + utepdat_t *s = (utepdat_t*)in; + uint64_t i, rid; + p->num_bases += s->num_bases; + p->num_corrected_bases += s->num_corrected_bases; + p->num_recorrected_bases += s->num_recorrected_bases; + // fprintf(stderr, "[M::%s::dump_start] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); + for (i = 0; i < p->n_thread; ++i) { + push_uc_block_t(s->uopt, &(s->ll[i].tk), s->seq, s->len, s->id); + free(s->ll[i].tk.a); + } + for (i = 0; i < (uint64_t)s->n; ++i) { + rid = s->id + i; + if((UL_INF.n <= rid) || (UL_INF.n > rid && UL_INF.a[rid].rlen != s->len[i])) { + append_ul_t(&UL_INF, &rid, NULL, 0, s->seq[i], s->len[i], NULL, 0, P_CHAIN_COV, s->uopt, 0); + } + free(s->seq[i]); + } + // fprintf(stderr, "[M::%s::dump_done] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); + /** + for (i = 0; i < (uint64_t)s->n; ++i) { + ///debug + + // if(s->pos[i].s == (uint64_t)-1) continue; + // kv_push(pe_hit, p->hits.a, s->pos[i]); + // if(!s->gcs[i]) continue; + // dump_gaf(&(p->hits), s->gcs[i], 1); + // free(s->gcs[i]->gc); free(s->gcs[i]->a); free(s->gcs[i]->lc); free(s->gcs[i]); + + rid = s->id + i; + append_ul_t(&UL_INF, &rid, NULL, 0, s->seq[i], s->len[i], NULL, 0, P_CHAIN_COV); + // fprintf(stderr, "%.*s\n", (int)s->len[i], s->seq[i]); + free(s->seq[i]); p->total_base += s->len[i]; + } + **/ + ///debug + /** + free(s->gcs); + **/ + + free(s->ll); free(s->len); free(s->seq); free(s); + } + return 0; +} + + +static void *worker_ul_rescall_pipeline(void *data, int step, void *in) // callback for kt_pipeline() +{ + uldat_t *p = (uldat_t*)data; + ///uint64_t total_base = 0, total_pair = 0; + if (step == 0) { // step 1: read a block of sequences + int ret; + uint64_t l; + utepdat_t *s; + CALLOC(s, 1); + s->ha_flt_tab = p->ha_flt_tab; s->ha_idx = p->ha_idx; s->id = p->total_pair; + s->opt = p->opt; s->uu = p->uu; s->uopt = p->uopt; s->rg = p->rg; s->mm = p->mm; + while ((ret = kseq_read(p->ks)) >= 0) + { + if ((p->ks->seq.l < (uint64_t)p->opt->k) || (p->ks->seq.l < asm_opt.ul_min_base)) continue; + if (s->n == s->m) { + s->m = s->m < 16? 16 : s->m + (s->n>>1); + REALLOC(s->len, s->m); + REALLOC(s->seq, s->m); + } + + // append_ul_t(&UL_INF, NULL, p->ks->name.s, p->ks->name.l, NULL, 0, NULL, 0, P_CHAIN_COV, s->uopt); + l = p->ks->seq.l; + MALLOC(s->seq[s->n], l); + s->sum_len += l; + memcpy(s->seq[s->n], p->ks->seq.s, l); + // fprintf(stderr, "s->n->%d, l->%lu\n", s->n, l); + // fprintf(stderr, "+++++rid->%lu, l->%lu, %.*s\n", + // s->id + s->n, l, (int32_t)p->ks->name.l, p->ks->name.s); + s->len[s->n++] = l; + if (s->sum_len >= p->chunk_size) break; + } + p->total_pair += s->n; + if (s->sum_len == 0) free(s); + else return s; + } + else if (step == 1) { // step 2: alignment + utepdat_t *s = (utepdat_t*)in; + + uint64_t i; s->n_thread = p->n_thread; + CALLOC(s->hab, p->n_thread); CALLOC(s->ll, p->n_thread); CALLOC(s->buf, p->n_thread); + CALLOC(s->gdp, p->n_thread); CALLOC(s->mzs, p->n_thread); CALLOC(s->sps, p->n_thread); + CALLOC(s->mk, p->n_thread); + + // CALLOC(s->buf, p->n_thread); + for (i = 0; i < p->n_thread; ++i) { + s->hab[i] = ha_ovec_init(0, 0, 1); s->buf[i] = mg_tbuf_init(); + } + // fprintf(stderr, "[M::%s::Start] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); + kt_for(p->n_thread, worker_for_ul_rescall_alignment, s, s->n); + // fprintf(stderr, "[M::%s::Done] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); + // get_utepdat_t_mem(s, 1); + + for (i = 0; i < p->n_thread; ++i) { + p->num_bases += s->hab[i]->num_read_base; + p->num_corrected_bases += s->hab[i]->num_correct_base; + + // s->num_recorrected_bases += s->hab[i]->num_recorrect_base; + ha_ovec_destroy(s->hab[i]); hc_glchain_destroy(&(s->ll[i])); + mg_tbuf_destroy(s->buf[i]); hc_gdpchain_destroy(&(s->gdp[i])); + kv_destroy(s->mzs[i]); kv_destroy(s->sps[i]); + kv_destroy(s->mk[i].idx); kv_destroy(s->mk[i].srt); + //free(s->seq[i]); + } + free(s->hab); free(s->ll); free(s->mk); ///free(s->len); free(s->seq); + free(s->buf); free(s->gdp); free(s->mzs); free(s->sps); ///free(s); + return s; + } else if (step == 2) { // step 3: dump + utepdat_t *s = (utepdat_t*)in; int64_t i, rid; + // fprintf(stderr, "[M::%s::dump_start] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); + for (i = 0; i < s->n; ++i) { + rid = s->id + i; + if(UL_INF.a[rid].dd == 3 && p->ucr_s && p->ucr_s->flag == 1) {///for the scaffolding + assert(s->seq[i]); + // if(s->seq[i] == NULL) fprintf(stderr, "[M::%s::]rid->%ld, len->%lu\n", __func__, rid, s->len[i]); + ///for debug interval + write_compress_base_disk(p->ucr_s->fp, rid, s->seq[i], s->len[i], &(p->ucr_s->u)); + } + // if(UL_INF.a[rid].dd) fprintf(stderr, "rid->%ld\n", rid); + free(s->seq[i]); + } + // fprintf(stderr, "[M::%s::dump_done] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); + free(s->len); free(s->seq); free(s); + } + return 0; +} + +static void *worker_ul_recorrect_pipeline(void *data, int step, void *in) // callback for kt_pipeline() +{ + uldat_t *p = (uldat_t*)data; + ///uint64_t total_base = 0, total_pair = 0; + if (step == 0) { // step 1: read a block of sequences + int ret; + uint64_t l, rid; + utepdat_t *s; + CALLOC(s, 1); + s->ha_flt_tab = p->ha_flt_tab; s->ha_idx = p->ha_idx; s->id = p->total_pair; + s->opt = p->opt; s->uu = p->uu; s->uopt = p->uopt; s->rg = p->rg; + while ((ret = kseq_read(p->ks)) >= 0) + { + if (p->ks->seq.l < (uint64_t)p->opt->k) continue; + if (s->n == s->m) { + s->m = s->m < 16? 16 : s->m + (s->n>>1); + REALLOC(s->len, s->m); + REALLOC(s->seq, s->m); + } + // append_ul_t(&UL_INF, NULL, p->ks->name.s, p->ks->name.l, NULL, 0, NULL, 0, P_CHAIN_COV, s->uopt); + l = p->ks->seq.l; s->seq[s->n] = NULL; rid = s->id + s->n; + if(UL_INF.a[rid].rlen & ((uint32_t)(0x80000000))) { + MALLOC(s->seq[s->n], l); memcpy(s->seq[s->n], p->ks->seq.s, l); + } + s->sum_len += l; + s->len[s->n++] = l; + if (s->sum_len >= p->chunk_size) break; + } + p->total_pair += s->n; + if (s->sum_len == 0) free(s); + else return s; + } + else if (step == 1) { // step 2: alignment + utepdat_t *s = (utepdat_t*)in; + + uint64_t i; s->n_thread = p->n_thread; + CALLOC(s->hab, p->n_thread); CALLOC(s->ll, p->n_thread); CALLOC(s->buf, p->n_thread); + CALLOC(s->gdp, p->n_thread); CALLOC(s->mzs, p->n_thread); CALLOC(s->sps, p->n_thread); + + // CALLOC(s->buf, p->n_thread); + for (i = 0; i < p->n_thread; ++i) { + s->hab[i] = ha_ovec_init(0, 0, 1); s->buf[i] = mg_tbuf_init(); + } + fprintf(stderr, "[M::%s::Start] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); + kt_for(p->n_thread, worker_for_ul_recorrect_alignment, s, s->n); + fprintf(stderr, "[M::%s::Done] ==> s->id: %lu, s->n:% d\n", __func__, s->id, s->n); + get_utepdat_t_mem(s, 1); + + for (i = 0; i < p->n_thread; ++i) { + p->num_bases += s->hab[i]->num_read_base; + p->num_corrected_bases += s->hab[i]->num_correct_base; + + // s->num_recorrected_bases += s->hab[i]->num_recorrect_base; + ha_ovec_destroy(s->hab[i]); hc_glchain_destroy(&(s->ll[i])); + mg_tbuf_destroy(s->buf[i]); hc_gdpchain_destroy(&(s->gdp[i])); + kv_destroy(s->mzs[i]); kv_destroy(s->sps[i]); free(s->seq[i]); + } + free(s->hab); free(s->ll); free(s->len); free(s->seq); + free(s->buf); free(s->gdp); free(s->mzs); free(s->sps); free(s); + } + return 0; +} + + +int32_t init_ucr_file_t(uldat_t *sl, char* file, uint64_t mode) +{ + if(mode == 1 || mode == 2) { + char *gfa_name = (char*)malloc(strlen(file)+25); + sprintf(gfa_name, "%s.uidx.ucr.bin", file); + CALLOC(sl->ucr_s, 1); + sl->ucr_s->flag = mode; + sl->ucr_s->fp = fopen(gfa_name, mode==1?"w":"r"); + if (!(sl->ucr_s->fp)) { + free(gfa_name); + return 0; + } + free(gfa_name); + return 1; + } + return 0; +} + + +void destory_ucr_file_t(uldat_t *sl) +{ + if(sl->ucr_s) { + free(sl->ucr_s->u.r_base.a); + free(sl->ucr_s->u.bb.a); + free(sl->ucr_s->u.N_site.a); + + fclose(sl->ucr_s->fp); + free(sl->ucr_s); + sl->ucr_s = NULL; + } +} + + +void debug_sl_compress_base_disk_0(uldat_t *sl, char* gfa_name) +{ + int32_t ret, rid = 0, sr_0, sr_1; gzFile fp; + init_ucr_file_t(sl, gfa_name, 1); + fp = gzopen(gfa_name, "r"); assert(fp); + sl->ks = kseq_init(fp); + while ((ret = kseq_read(sl->ks)) >= 0) { + write_compress_base_disk(sl->ucr_s->fp, rid, sl->ks->seq.s, sl->ks->seq.l, &(sl->ucr_s->u)); + rid++; + } + kseq_destroy(sl->ks); + gzclose(fp); + + destory_ucr_file_t(sl); + + + uint64_t ulid; uint32_t ulen; kvec_t(char) des; kv_init(des); + init_ucr_file_t(sl, gfa_name, 2); rid = 0; + + fp = gzopen(gfa_name, "r"); assert(fp); + sl->ks = kseq_init(fp); + while (1) { + sr_0 = kseq_read(sl->ks); des.n = 0; + if(sr_0 >= 0) sr_0 = 1; + else sr_0 = 0; + if(sr_0 == 0) sl->ks->seq.l = 1; + kv_resize(char, des, sl->ks->seq.l); + sr_1 = load_compress_base_disk(sl->ucr_s->fp, &ulid, des.a, &ulen, &(sl->ucr_s->u)); + if(sr_0 != sr_1) fprintf(stderr, "[M::%s::] rid->%d, sr_0->%d, sr_1->%d\n", __func__, rid, sr_0, sr_1); + assert(sr_0 == sr_1); + if(sr_0 == 0 || sr_1 == 0) break; + // if(rid != (int64_t)ulid) fprintf(stderr, "[M::%s::] rid->%d, ulid->%lu, sr_0->%d, sr_1->%d\n", __func__, rid, ulid, sr_0, sr_1); + assert(rid == (int64_t)ulid); + assert(sl->ks->seq.l == ulen); + assert(memcmp(sl->ks->seq.s, des.a, ulen) == 0); + rid++; + } + kseq_destroy(sl->ks); kv_destroy(des); + gzclose(fp); + + destory_ucr_file_t(sl); + fprintf(stderr, "[M::%s::] ==> Have checked %d UL reads\n", __func__, rid); + +} + +void debug_sl_compress_base_disk_0(uldat_t *sl, const enzyme *fn) +{ + int32_t i; + for (i = 0; i < fn->n; i++) debug_sl_compress_base_disk_0(sl, fn->a[i]); + exit(1); +} + + + +utg_rid_dt *get_r_ug_region(utg_rid_t *idx, uint64_t *n, uint64_t rid) +{ + (*n) = idx->idx[rid+1] - idx->idx[rid]; + return (*n)?idx->p.a + idx->idx[rid]:NULL; +} + +uint64_t rov2uov(uint64_t rid, const ul_idx_t *uref, utg_rid_dt *ru_map, uc_block_t *rovlp, ul_ov_t *res, uint32_t adjust_rev, int64_t ulid) +{ + uint64_t ori = ru_map->u&1, ts, te; + if(!ori) { + ts = rovlp->ts; te = rovlp->te; + } else { + ts = uref->r_ug->rg->seq[rid].len - rovlp->te; + te = uref->r_ug->rg->seq[rid].len - rovlp->ts; + } + // if(ulid == 14714) { + // fprintf(stderr, "[M::%s::]\tori::%lu\trovlp->rev::%u\tro_t::[%u, %u)\tt::[%lu, %lu)\toff::%u\n", __func__, + // ori, rovlp->rev, rovlp->ts, rovlp->te, ts, te, ru_map->off); + // } + ts += ru_map->off; te += ru_map->off; + if(ts >= 0 && te <= uref->ug->g->seq[ru_map->u>>1].len) { + memset(res, 0, sizeof(*res)); + res->qn = 0; res->qs = rovlp->qs; res->qe = rovlp->qe; + res->tn = ru_map->u>>1; res->ts = ts; res->te = te; + res->el = rovlp->el; res->rev = (rovlp->rev == ori?0:1); + if(adjust_rev && res->rev) {///for linear chaining + res->ts = uref->ug->g->seq[res->tn].len - te; + res->te = uref->ug->g->seq[res->tn].len - ts; + } + return 1; + } + return 0; + // if(ulid == 14714) { + // fprintf(stderr, "[M::%s::]\tulen::%u\trlen::%u\tro_t::[%u, %u)\tt::[%lu, %lu)\toff::%u\n", __func__, + // uref->ug->g->seq[res->tn].len, uref->r_ug->rg->seq[rid].len, rovlp->ts, rovlp->te, ts, te, ru_map->off); + // } +} + +void print_ul_ov_t(ul_ov_t *xs, const char* cmd) +{ + fprintf(stderr, "%s\t%s\t%u\t%u\t%c\t%.*s\t%u\t%u\n", cmd, UL_INF.nid.a[xs->qn].a, xs->qs, xs->qe, + "+-"[xs->rev], (int)Get_NAME_LENGTH(R_INF, ((xs->tn<<1)>>1)), Get_NAME(R_INF, ((xs->tn<<1)>>1)), xs->ts, xs->te); +} + +void gl_rg2ug_gen(ul_vec_t *r_cl, kv_ul_ov_t *u_cl, const ul_idx_t *uref, uint64_t is_el, uint64_t n_pchain, int64_t ulid) +{ + uint64_t k, a_k, a_n; uc_block_t *z; utg_rid_dt *a; ul_ov_t p; + u_cl->n = 0; + for (k = 0; k < r_cl->bb.n; k++) { + z = &(r_cl->bb.a[k]); + if(z->base) continue; + if(is_el && (!(z->el))) continue; + if(z->pchain == n_pchain) continue; + a = get_r_ug_region(uref->r_ug, &a_n, z->hid); + if(!a) continue; + for (a_k = 0; a_k < a_n; a_k++) { + // if(ulid == 14714) { + // fprintf(stderr, "\n+[M::%s::]\tq::[%u, %u)\t%c\t%.*s(%u)\tt::[%u, %u)\n", __func__, z->qs, z->qe, "+-"[z->rev], + // (int)Get_NAME_LENGTH(R_INF, z->hid), Get_NAME(R_INF, z->hid), (uint32_t)Get_READ_LENGTH(R_INF, z->hid), + // z->ts, z->te); + // fprintf(stderr, "*[M::%s::] utg%.6d%c(%u)\t%c\toff::%u\tpos::%u\n", __func__, + // (int32_t)(a[a_k].u>>1)+1, "lc"[uref->ug->u.a[a[a_k].u>>1].circ], uref->ug->u.a[a[a_k].u>>1].len, + // "+-"[a[a_k].u&1], a[a_k].off, a[a_k].pos); + // } + if(!rov2uov(z->hid, uref, &(a[a_k]), z, &p, 1, ulid)) continue; + p.el = 1; p.tn <<= 1; p.tn |= p.rev; p.qn = k/**uref->r_ug->idx[z->hid] + a_k**/;//for linear chain + kv_push(ul_ov_t, *u_cl, p); + // if(ulid == 14714) { + // fprintf(stderr, "[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\ttlen::%u\n", __func__, + // (int32_t)(p->tn>>1)+1, "+-"[p->tn&1], p->qs, p->qe, + // p->ts, p->te, uref->ug->g->seq[p->tn>>1].len); + // } + // if(k == 2) { + // fprintf(stderr, "[M::%s::] p->ts:%u, p->te:%u, z->ts:%u, z->te:%u, a[a_k].off:%u\n", __func__, p->ts, p->te, z->ts, z->te, a[a_k].off); + // } + // fprintf(stderr, "-[M::%s::] %u\t%u\t%c\tutg%.6d%c(%u)\t%u\t%u\n", __func__, p->qs, p->qe, "+-"[p->rev], + // (int32_t)(p->tn>>1)+1, "lc"[uref->ug->u.a[p->tn>>1].circ], uref->ug->u.a[p->tn>>1].len, p->ts, p->te); + } + } +} + +void adjust_rev_tse(ul_ov_t *x, int64_t tlen, int64_t *ts, int64_t *te) +{ + *ts = x->ts; *te = x->te; + if(x->rev) { + *ts = tlen - x->te; *te = tlen - x->ts; + } +} + +uint64_t get_add_cov_score(const ul_idx_t *uref, int64_t ps, int64_t pe, int64_t cs, int64_t ce, int64_t uid, int64_t *cov_i) +{ + int64_t os = MAX(ps, cs), oe = MIN(pe, ce); + int64_t ovlp = ((oe > os)? (oe - os):0); + // fprintf(stderr, "ovlp:%ld, os:%ld, oe:%ld, ps:%ld, pe:%ld, cs:%ld, ce::%ld\n", ovlp, os, oe, ps, pe, cs, ce); + if(ovlp > 0) { + return (os>cs?retrieve_u_cov_region(uref, uid, 0, cs, os, cov_i):0) + + (ce>oe?retrieve_u_cov_region(uref, uid, 0, oe, ce, cov_i):0); + } + + return retrieve_u_cov_region(uref, uid, 0, cs, ce, cov_i); +} + +uint64_t linear_chain_dp(ul_ov_t *ch, int64_t ch_n, ul_ov_t *sv, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, int64_t max_skip, uint64_t *idx, uint64_t *track, ma_ug_t *ug, int64_t chain_offset) +{ ///all in[].el must be 1 + if(ch_n == 0) return 0; + int64_t /**mm_ovlp, x,**/ i, j, k, sc, csc, mm_sc, mm_idx, its, ite, jts, jte, cov_i, dq, dt, dd, mm; + ul_ov_t *li = NULL, *lj = NULL; + radix_sort_ul_ov_srt_qe(ch, ch + ch_n); + for (i = 1, j = 0; i <= ch_n; i++) { + // if(i < ch_n) { + // li = &(ch[i]); + // fprintf(stderr, "##(%ld) %u\t%u\t%c\tutg%.6d%c(%u)\t%u\t%u\tmm_idx:%ld\tmm_sc:%ld\n", i, li->qs, li->qe, "+-"[li->rev], + // (int32_t)(li->tn)+1, "lc"[uref->ug->u.a[li->tn].circ], uref->ug->u.a[li->tn].len, li->ts, li->te, mm_idx, mm_sc); + // } + if (i == ch_n || ch[i].qe != ch[j].qe) { + if(i - j > 1) { + radix_sort_ul_ov_srt_qs(ch+j, ch+i); + } + j = i; + } + } + + // fprintf(stderr, "[M::%s::] ch_n:%ld\n", __func__, ch_n); + for (i = 0; i < ch_n; ++i) { + li = &(ch[i]); + // mm_ovlp = max_ovlp_src(uopt, ((li->tn<<1)|li->rev)^1); + // x = (li->qs + mm_ovlp)*diff_ec_ul; + // if(x < bw) x = bw; + // x += li->qs + mm_ovlp; + // if (x > qlen+1) x = qlen+1; + // x = find_ul_ov_max(i, ch, x+G_CHAIN_INDEL); + adjust_rev_tse(li, ug->g->seq[li->tn].len, &its, &ite); + cov_i = 0; + csc = retrieve_u_cov_region(uref, li->tn, 0, its, ite, &cov_i); + mm_sc = csc; mm_idx = -1; + for (j = i-1/**x**/; j >= 0; --j) { + lj = &(ch[j]); + // fprintf(stderr, "<0>\n"); + if(lj->qs <= li->qs && lj->qe <= li->qe && lj->ts <= li->ts && lj->te <= li->te) {///co-linear + assert(li->tn == lj->tn && li->rev == lj->rev); + // fprintf(stderr, "<1>\n"); + if(lj->qs == li->qs && lj->qe == li->qe && lj->ts == li->ts && lj->te == li->te) continue; + dq = li->qe - lj->qs; dt = li->te - lj->ts; + dd = (dq>dt? dq-dt:dt-dq); + mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; + // fprintf(stderr, "+++i->%ld, j->%ld, dd->%ld, mm->%ld\n", i, j, dd, mm); + if(dd <= mm) {///pass distance checking + adjust_rev_tse(lj, ug->g->seq[lj->tn].len, &jts, &jte); + sc = get_add_cov_score(uref, jts, jte, its, ite, li->tn, &cov_i) + pop_sc(track[j]); + + if((sc > mm_sc) || (sc == mm_sc && mm_idx == -1)) { ///must be >= instead of > + mm_sc = sc, mm_idx = j; + } + // fprintf(stderr, "%ld, its:%ld, ite:%ld>, %ld, jts:%ld, jte:%ld> sc:%ld, pop_sc(track[j]):%ld, csc:%ld\n", + // i, its, ite, j, jts, jte, sc, pop_sc(track[j]), csc); + } + } + } + + // fprintf(stderr, "##(%ld) %u\t%u\t%c\tutg%.6d%c(%u)\t%u\t%u\tmm_idx:%ld\tmm_sc:%ld\n", i, li->qs, li->qe, "+-"[li->rev], + // (int32_t)(li->tn)+1, "lc"[uref->ug->u.a[li->tn].circ], uref->ug->u.a[li->tn].len, li->ts, li->te, mm_idx, mm_sc); + track[i] = push_sc_pre(mm_sc, mm_idx); + li->sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); sv[i] = *li; + } + + int64_t n_u; + for (k = ch_n-1, n_u = 0; k >= 0; --k) { + if(track[k]&((uint64_t)0x80000000)) continue; + i = k; ch[n_u]=sv[i]; sc = pop_sc(track[i]); + for (;i>=0;) { + track[i] |= ((uint64_t)0x80000000); + if(sv[i].qs < ch[n_u].qs) ch[n_u].qs = sv[i].qs; + if(sv[i].ts < ch[n_u].ts) ch[n_u].ts = sv[i].ts; + if(sv[i].qe > ch[n_u].qe) ch[n_u].qe = sv[i].qe; + if(sv[i].te > ch[n_u].te) ch[n_u].te = sv[i].te; + // ch[n_u].qn = i;//start idx of read alignment in chain + i = pop_pre(track[i]); + } + adjust_rev_tse(&(ch[n_u]), ug->g->seq[ch[n_u].tn].len, &its, &ite); + ch[n_u].ts = its; ch[n_u].te = ite; ch[n_u].sec = (sc>0x3FFFFFFF?0x3FFFFFFF:sc); + // ch[n_u].qn += chain_offset; //start idx of read alignment in chain + // ch[n_u].tn = k + chain_offset; //end idx of read alignment in chain + ch[n_u].qn = k + chain_offset; //end idx of read alignment in chain + n_u++; + } + for (i = 0; i < ch_n; ++i) { + adjust_rev_tse(&(sv[i]), ug->g->seq[sv[i].tn].len, &its, &ite); + sv[i].ts = its; sv[i].te = ite; + k = pop_pre(track[i]); sv[i].tn = k>=0?k+chain_offset:(uint32_t)-1; + } + return n_u; +} + +inline int64_t comput_linear_sc(ul_ov_t *li, ul_ov_t *lj, double diff_ec_ul, int64_t bw) +{ ///li is the suffix of lj + int64_t dq, dt, dd, mm; + if(lj->te > li->te) return INT32_MIN; + dq = li->qe - lj->qs; dt = li->te - lj->ts; + dd = (dq>dt? dq-dt:dt-dq); + mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; + if(dd > mm) return INT32_MIN; + return li->qe - li->qs; +} + +uint64_t linear_chain_dp_adv(ul_ov_t *ch, int64_t ch_n, ul_ov_t *sv, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, ma_ug_t *ug, +int64_t chain_offset) +{ ///all in[].el must be 1 + if(ch_n == 0) return 0; + int64_t /**mm_ovlp, x,**/ i, j, k, sc, csc, mm_sc, mm_idx, its, ite, max; + ul_ov_t *li = NULL, *lj = NULL; int64_t *p, *t, st, plus, max_ii, n_skip, end_j; int32_t *f; + resize_Chain_Data(dp, ch_n, NULL); + t = dp->tmp; f = dp->score; p = dp->pre; + + radix_sort_ul_ov_srt_qe(ch, ch + ch_n); + for (i = 1, j = 0; i <= ch_n; i++) { + if (i == ch_n || ch[i].qe != ch[j].qe) { + if(i - j > 1) radix_sort_ul_ov_srt_qs(ch+j, ch+i); + j = i; + } + } + + // fprintf(stderr, "[M::%s::] ch_n:%ld\n", __func__, ch_n); + memset(t, 0, (ch_n*sizeof((*t)))); + for (i = st = plus = 0, max_ii = -1; i < ch_n; ++i) { + li = &(ch[i]); csc = li->qe - li->qs; + mm_sc = csc; mm_idx = -1; n_skip = 0; end_j = -1; + st = (i= st; --j) { + lj = &(ch[j]); + sc = comput_linear_sc(li, lj, diff_ec_ul, bw); ///should allow contain + if(sc == INT32_MIN) continue; + sc += f[j]; + if(sc > mm_sc) { + mm_sc = sc, mm_idx = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + end_j = j; + if (max_ii < 0 || (ch[i].qe>(ch[max_ii].qe+max_dis))) {//too long + max = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && (ch[i].qe<=(max_dis+ch[j].qe)); --j) { + if (max < f[j]) { + max = f[j], max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + lj = &(ch[max_ii]); + sc = comput_linear_sc(li, lj, diff_ec_ul, bw); ///should allow contain + if(sc != INT32_MIN) { + sc += f[max_ii]; + if(sc > mm_sc) { + mm_sc = sc; mm_idx = max_ii; + } + } + } + + f[i] = mm_sc; p[i] = mm_idx; + if ((max_ii < 0) || ((ch[i].qe<=max_dis+ch[max_ii].qe) && (f[max_ii]sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); sv[i] = *li; + // fprintf(stderr, "##(%ld) %u\t%u\t%c\tutg%.6d%c(%u)\t%u\t%u\tmm_idx:%ld\tmm_sc:%ld\n", i, li->qs, li->qe, "+-"[li->rev], + // (int32_t)(li->tn)+1, "lc"[uref->ug->u.a[li->tn].circ], uref->ug->u.a[li->tn].len, li->ts, li->te, mm_idx, mm_sc); + // track[i] = push_sc_pre(mm_sc, mm_idx); + // li->sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); sv[i] = *li; + } + + for (i = 0; i < ch_n; ++i) t[i] = 0; + int64_t n_u; + for (k = ch_n-1, n_u = 0; k >= 0; --k) { + if(t[k]) continue; + i = k; ch[n_u]=sv[i]; sc = f[i]; + for (;i>=0;) { + if(sv[i].qs < ch[n_u].qs) ch[n_u].qs = sv[i].qs; + if(sv[i].ts < ch[n_u].ts) ch[n_u].ts = sv[i].ts; + if(sv[i].qe > ch[n_u].qe) ch[n_u].qe = sv[i].qe; + if(sv[i].te > ch[n_u].te) ch[n_u].te = sv[i].te; + // ch[n_u].qn = i;//start idx of read alignment in chain + t[i] = 1; i = p[i]; + } + adjust_rev_tse(&(ch[n_u]), ug->g->seq[ch[n_u].tn].len, &its, &ite); + ch[n_u].ts = its; ch[n_u].te = ite; ch[n_u].sec = (sc>0x3FFFFFFF?0x3FFFFFFF:sc); + // ch[n_u].qn += chain_offset; //start idx of read alignment in chain + // ch[n_u].tn = k + chain_offset; //end idx of read alignment in chain + ch[n_u].qn = k + chain_offset; //end idx of read alignment in chain + n_u++; + } + for (i = 0; i < ch_n; ++i) { + adjust_rev_tse(&(sv[i]), ug->g->seq[sv[i].tn].len, &its, &ite); + sv[i].ts = its; sv[i].te = ite; + k = p[i]; sv[i].tn = k>=0?k+chain_offset:(uint32_t)-1; + } + return n_u; +} + +void gen_linear_chains(kv_ul_ov_t *res, kv_ul_ov_t *buf, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, Chain_Data* dp) +{ + uint64_t k, l, z, an, m; + radix_sort_ul_ov_srt_tn(res->a, res->a + res->n); + ///after this function, res keeps unitig alignment, while buf keeps read alignments + kv_resize(ul_ov_t, *buf, res->n); buf->n = res->n; + for (k = 1, l = m = 0; k <= res->n; k++) { + if(k == res->n || res->a[k].tn != res->a[l].tn) {///qn <- (tn|rev) + // kv_resize(uint64_t, bufg->srt.a, k-l); + // kv_resize(uint64_t, *bufs, k-l); + for (z = l; z < k; z++) res->a[z].tn>>=1; + // fprintf(stderr, "\n*[M::%s::] %c\tutg%.6d%c(%u)\tocc:[%lu, %lu)\n", __func__, "+-"[res->a[l].rev], (int32_t)(res->a[l].tn)+1, + // "lc"[uref->ug->u.a[res->a[l].tn].circ], uref->ug->u.a[res->a[l].tn].len, l, k); + an = l + linear_chain_dp_adv(res->a+l, k-l, buf->a+l, uref, uopt, bw, diff_ec_ul, qlen, + UG_SKIP_N, UG_ITER_N, UG_DIS_N, dp, uref->ug, l); + for (z = l; z < an; z++) res->a[m++] = res->a[z]; + // fprintf(stderr, "#occ:[%lu, %lu)\n", l, an); + l = k; + } + } + res->n = m; +} + + +void gen_linear_chains_backup(kv_ul_ov_t *res, kv_ul_ov_t *buf, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, int64_t max_skip, glchain_t *bufg, st_mt_t *bufs) +{ + uint64_t k, l, z, an, m; + radix_sort_ul_ov_srt_tn(res->a, res->a + res->n); + kv_resize(ul_ov_t, *buf, res->n); buf->n = res->n; + for (k = 1, l = m = 0; k <= res->n; k++) { + if(k == res->n || res->a[k].tn != res->a[l].tn) {///qn <- (tn|rev) + kv_resize(uint64_t, bufg->srt.a, k-l); + kv_resize(uint64_t, *bufs, k-l); + for (z = l; z < k; z++) res->a[z].tn>>=1; + // fprintf(stderr, "\n*[M::%s::] %c\tutg%.6d%c(%u)\tocc:[%lu, %lu)\n", __func__, "+-"[res->a[l].rev], (int32_t)(res->a[l].tn)+1, + // "lc"[uref->ug->u.a[res->a[l].tn].circ], uref->ug->u.a[res->a[l].tn].len, l, k); + an = l + linear_chain_dp(res->a+l, k-l, buf->a+l, uref, uopt, bw, diff_ec_ul, qlen, max_skip, bufg->srt.a.a, bufs->a, uref->ug, l); + for (z = l; z < an; z++) res->a[m++] = res->a[z]; + // fprintf(stderr, "#occ:[%lu, %lu)\n", l, an); + l = k; + } + } + res->n = m; +} + +void gen_end_coord(ul_ov_t *z, int64_t qlen, int64_t tlen, int64_t *r_qs, int64_t *r_qe, int64_t *r_ts, int64_t *r_te) +{ + int64_t qs, qe, ts, te, qtail, ttail; + qs = z->qs; qe = z->qe; ts = z->ts; te = z->te; + if(z->rev) { + ts = tlen - z->te; te = tlen - z->ts; + } + + if(qs <= ts) { + ts -= qs; qs = 0; + } else { + qs -= ts; ts = 0; + } + + qtail = qlen - qe; ttail = tlen - te; + if(qtail <= ttail) { + qe = qlen; te += qtail; + } + else { + te = tlen; qe += ttail; + } + + if(r_qs) {(*r_qs) = qs;} if(r_qe) {(*r_qe) = qe;} + if(r_ts) {(*r_ts) = ts;} if(r_te) {(*r_te) = te;} + if(z->rev) { + if(r_ts) (*r_ts) = tlen - te; + if(r_te) (*r_te) = tlen - ts; + } +} + +uint32_t is_end_check(uint32_t v, ul_ov_t *z, asg_t *g) +{ + if(v&1) { + if(z->ts==0) return 1; + } else { + if(z->te==g->seq[v>>1].len) return 1; + } + + return 0; +} + +int64_t simple_g_chain_dp(kv_ul_ov_t *in, ul_ov_t *buf, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, int64_t max_skip, uint64_t *srt, uint64_t *idx, uint64_t *track) +{ + if(in->n == 0) return 0; + uint32_t ai_v, aj_v, rev_n; ma_ug_t *ug = uref->ug; + int64_t mm_ovlp, x, i, j, k, sc, csc, mm_sc, mm_idx, qo, share, in_n = in->n; + int64_t iqs, iqe, its, ite, i_end, j_end; + ul_ov_t *ai, *aj, *e_ai, *e_aj, rev_t; + for (i = 0; i < in_n; i++) { + gen_end_coord(&(in->a[i]), qlen, ug->u.a[in->a[i].tn].len, NULL, &iqe, NULL, NULL); + srt[i] = iqe; srt[i] <<= 32; srt[i] |= (uint64_t)i; + } + radix_sort_gfa64(srt, srt+in_n); + for (i = 0; i < in_n; i++) buf[i] = in->a[(uint32_t)srt[i]]; + memcpy(in->a, buf, in_n *sizeof((*buf)));///all alignments have been sorted by the real end-qe + + for (i = 0; i < in_n; ++i) { + ai = &(in->a[i]); ai_v = (ai->tn<<1)|ai->rev; e_ai = &(buf[i]); i_end = 0; + gen_end_coord(ai, qlen, ug->u.a[ai->tn].len, &iqs, &iqe, &its, &ite); + e_ai->qs = iqs; e_ai->qe = iqe; e_ai->ts = its; e_ai->te = ite; + mm_ovlp = max_ovlp(uref->ug->g, ai_v^1); + x = (e_ai->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += e_ai->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(i, buf, x+G_CHAIN_INDEL); + i_end = is_end_check(ai_v^1, ai, uref->ug->g); + csc = mm_sc = e_ai->sec; mm_idx = -1; + for (j = x; j >= 0; --j) { // collect potential destination vertices + aj = &(in->a[j]); aj_v = (aj->tn<<1)|aj->rev; e_aj = &(buf[i]); j_end = 0; + if(e_aj->qe+G_CHAIN_INDEL <= e_ai->qs) break;//even this pair has a overlap, its length will be very small; just ignore + if(e_aj->qs >= e_ai->qs+G_CHAIN_INDEL) continue; // lj is contained in li on the query coordinate; 128 for indel offset + qo = infer_rovlp(e_ai, e_aj, NULL, NULL, NULL, ug); ///overlap length in query (UL read) + if(ai_v != aj_v && get_ecov_adv(uref, uopt, ai_v^1, aj_v^1, bw, diff_ec_ul, qo, 0, &share)) { + sc = csc + pop_sc(track[j]); j_end = is_end_check(aj_v, aj, uref->ug->g); + if(i_end && j_end) sc -= (share>=csc?csc:share); + if(sc > mm_sc) mm_sc = sc, mm_idx = j; + } + } + track[i] = push_sc_pre(mm_sc, mm_idx); + srt[i] = track[i]>>32; srt[i] <<= 32; srt[i] |= i; + } + + int64_t n_v, n_u, n_v0; + radix_sort_gfa64(srt, srt+in_n); + for (k = in_n-1, n_v = n_u = 0; k >= 0; --k) { + n_v0 = n_v; + for (i = (uint32_t)srt[k]; i >= 0 && (track[i]&((uint64_t)0x80000000)) == 0;){ + buf[n_v] = in->a[i]; + gen_end_coord(&(buf[n_v]), qlen, ug->u.a[buf[n_v].tn].len, &iqs, &iqe, &its, &ite); + buf[n_v].qs = iqs; buf[n_v].qe = iqe; buf[n_v].ts = its; buf[n_v].te = ite; + + track[i] |= ((uint64_t)0x80000000); + i = pop_pre(track[i]); + n_v++; + } + if(n_v0 == n_v) continue; + sc = (i<0?(pop_sc(srt[k])):(pop_sc(srt[k])-pop_sc(track[i]))); + idx[n_u++] = ((uint64_t)sc<<32)|(n_v-n_v0); + } + + for (k = 0, n_v = n_v0 = 0; k < n_u; k++) { + n_v0 = n_v; n_v += (uint32_t)idx[k]; + in->a[k].qn = idx[k]>>32;//score + in->a[k].ts = n_v0; in->a[k].te = n_v;///idx + + rev_n = ((uint32_t)idx[k])>>1; + ///we need to consider contained reads; so determining qs is not such easy + in->a[k].qs = (uint32_t)-1; in->a[k].qe = buf[n_v0].qe; + for (i = 0; i < rev_n; i++) { + rev_t = buf[n_v0+i]; buf[n_v0+i] = buf[n_v-i-1]; buf[n_v-i-1] = rev_t; + + if(in->a[k].qs > buf[n_v0+i].qs) in->a[k].qs = buf[n_v0+i].qs; + if(in->a[k].qs > buf[n_v-i-1].qs) in->a[k].qs = buf[n_v-i-1].qs; + } + if(((uint32_t)idx[k])&1) { + if(in->a[k].qs > buf[n_v0+i].qs) in->a[k].qs = buf[n_v0+i].qs; + } + // fprintf(stderr, "[M::%s] k:%ld, qs:%u, qe:%u, chain_occ:%u, chain_score:%u\n", __func__, k, + // res->a[k].qs, res->a[k].qe, res->a[k].te - res->a[k].ts, res->a[k].qn); + } + + in->n = n_u; + radix_sort_ul_ov_srt_qn(in->a, in->a + in->n);//sort by score + return n_v; +} + +/** +uint32_t uov2rov(const ul_idx_t *uref, ul_ov_t *r_al, ul_ov_t *ul_al, ul_ov_t *res) +{ + int64_t y_s, y_e, y_bs, y_be, x_s, x_e, q_s, q_e, s_shift, e_shift; + y_s = MAX(r_al->ts, ul_al->ts); y_e = MIN(r_al->te, ul_al->te); + if(y_s > y_e) return 0; + res->tn = r_al->qn; res->ts = y_s; res->te = y_e; res->el = 1; res->rev = r_al->rev; res->sec = 0; + s_shift = get_offset_adjust(y_s-r_al->ts, r_al->te-r_al->ts, r_al->qe-r_al->qs); + e_shift = get_offset_adjust(r_al->te-y_e, r_al->te-r_al->ts, r_al->qe-r_al->qs); + if(r_al->rev) { + y_s = s_shift; s_shift = e_shift; e_shift = y_s; + } + res->qn = 0; res->qs = r_al->qs+s_shift; res->qe = r_al->qe-e_shift; + return 1; +} + + +void ug2rg_gen(ul_ov_t *a, int64_t an, ul_vec_t *qn, const ul_idx_t *uref, ul_vec_t *rch) +{ + ul_ov_t *ot, p, res; uint64_t i, l, m; + ma_utg_t *u; uc_block_t *b; int64_t z, ff, iqs, iqe, its, ite; + + + for (z = 0; z < an; z++) { + gen_end_coord(&(a[z]), rch->rlen, uref->ug->u.a[a[z].tn].len, &iqs, &iqe, NULL, NULL); + o = &(a[z]); u = &(uref->ug->u.a[o->tn]); + for (i = l = 0; i < u->n; i++) { + p.tn = o->tn; p.rev = (u->a[i]>>32)&1; p.qn = u->a[i]>>33;///tn is unitig, qn is HiFi read + p.qs = 0; p.qe = Get_READ_LENGTH(R_INF, (u->a[i]>>33)); + p.ts = l; p.te = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); + l += (uint32_t)u->a[i]; + if(p.te <= o->ts) continue; + if(p.ts >= o->te) break; + ff = uov2rov(uref, &p, o, &res); + assert(ff); + if(ff) { + kv_pushp(uc_block_t, rch->bb, &b); + b->hid = res.tn; b->rev = res.rev; b->base = 0; b->el = res.el; + b->pchain = 1; b->qs = res.qs; b->qe = res.qe; b->ts = res.ts; b->te = res.te; + } + } + } +} +**/ + + + +void extend_end_coord(mg_lchain_t *li, ul_ov_t *ui, const int64_t qlen, const int64_t rlen, int64_t *r_qs, int64_t *r_qe, int64_t *r_rs, int64_t *r_re) +{ + int64_t qs = 0, qe = 0, rs = 0, re = 0, rev = 0, qtail = 0, rtail = 0; + if(li) { + qs = li->qs; qe = li->qe; rs = li->rs; re = li->re; rev = li->v&1; + if(rev) { + rs = rlen - li->re; re = rlen - li->rs; + } + } + if(ui) { + qs = ui->qs; qe = ui->qe; rs = ui->ts; re = ui->te; rev = ui->rev; + if(rev) { + rs = rlen - ui->te; re = rlen - ui->ts; + } + } + + + + if(qs <= rs) { + rs -= qs; qs = 0; + } else { + qs -= rs; rs = 0; + } + + qtail = qlen - qe; rtail = rlen - re; + if(qtail <= rtail) { + qe = qlen; re += qtail; + } + else { + re = rlen; qe += rtail; + } + + if(r_qs) {(*r_qs) = qs;} if(r_qe) {(*r_qe) = qe;} + if(r_rs) {(*r_rs) = rs;} if(r_re) {(*r_re) = re;} + if(rev) { + if(r_rs) (*r_rs) = rlen - re; + if(r_re) (*r_re) = rlen - rs; + } +} + +void dump_linear_chain(ma_ug_t *ug, kv_ul_ov_t *lidx, vec_mg_lchain_t *res, int64_t qlen, int64_t ulid) +{ + uint64_t i; int64_t iqs, iqe, its, ite; mg_lchain_t *p; + kv_resize(mg_lchain_t, *res, lidx->n); + for (i = 0, res->n = 0; i < lidx->n; i++) { + kv_pushp(mg_lchain_t, *res, &p); memset(p, 0, sizeof((*p))); + // res->a[k].v = (autom->a[lidx->a[k].tn].tn<<1)|lidx->a[k].rev; + p->v = (lidx->a[i].tn<<1)|(lidx->a[i].rev); + ///.off -> idx of original chain; cnt -> score of the chain + p->off = i; p->score = lidx->a[i].sec; + p->qs = lidx->a[i].qs; p->qe = lidx->a[i].qe; + p->rs = lidx->a[i].ts; p->re = lidx->a[i].te; + // if(ulid == 123) { + // fprintf(stderr, "+[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tqlen::%ld\tt::[%d, %d)\ttlen::%u\tsc::%d\n", __func__, + // (int32_t)(p->v>>1)+1, "+-"[p->v&1], p->qs, p->qe, qlen, + // p->rs, p->re, ug->g->seq[p->v>>1].len, p->score); + // } + extend_end_coord(p, NULL, qlen, ug->g->seq[p->v>>1].len, &iqs, &iqe, &its, &ite); + p->qs = iqs; p->qe = iqe; p->rs = its; p->re = ite; + // if(!ugl_cover_check(p->rs, p->re, &(ug->u.a[p->v>>1]))) res->n--; + // fprintf(stderr, "chain_id:%d\t%u\t%u\t%c\tutg%.6dl(%u)\t%u\t%u\n", + // res->a[k].off, res->a[k].qs, res->a[k].qe, "+-"[res->a[k].v&1], (int32_t)(res->a[k].v>>1)+1, + // g->seq[res->a[k].v>>1].len, res->a[k].rs, res->a[k].re); + // if(ulid == 14714) { + // fprintf(stderr, "-[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\n", __func__, + // (int32_t)(p->v>>1)+1, "+-"[p->v&1], p->qs, p->qe, p->rs, p->re); + // } + } +} + +void set_trans_arr(uint64_t *trans, vec_sp_node_t *out, int64_t idx) +{ + int64_t i; + for (i = idx; i >=0; ) { + // if(out->a[idx]->v == 65) { + // fprintf(stderr, "+[M::%s::] out->a[%ld]->v:%u\n", __func__, i, out->a[i]->v); + // } + trans[i]++; + i = out->a[i]->pre; + } +} + +int64_t select_mul_way_nodes(mg_pathv_t *a, int64_t a_n, vec_sp_node_t *out, float len_dif, int32_t m_pathn, uint64_t *flag) +{ + int64_t i, k, pd, kd, occ, tt = 0; uint32_t pp; mg_pathv_t *p = NULL; + if(a_n > 1) radix_sort_mg_pathv_t_d_srt(a, a + a_n); + for (i = 0; i < a_n; i++) { + p = &(a[i]); pp = (p->d<<1)>>1; pd = out->a[p->pre]->di>>32; occ = 1; + + if(p->d&0x80000000) break; + for (k = 0; k < a_n; k++) { + if(k == i) continue; ///same alignment + if(((a[k].d<<1)>>1) == pp) continue; //same path + if(a[k].v!=p->v) continue; + kd = out->a[a[k].pre]->di>>32; + if(kd >= (pd*(1-len_dif)) && kd <= (pd*(1+len_dif))) occ++; + } + if(occ >= m_pathn) { + flag[p->pre] = 1; tt++; + } + } + + return tt; +} + +int32_t phase_mul_ways(vec_mg_pathv_t *res, st_mt_t *dst_done, vec_sp_node_t *out, int32_t n_dst, mg_path_dst_t *dst, int32_t max_k, float len_dif) +{ + int64_t i, j, z, zl, n = 0, n_mpath, kk_p, od, res_n = res->n, pid; mg_pathv_t *h; + dst_done->n = 0; kv_resize(uint64_t, *dst_done, out->n); + uint64_t *trans = dst_done->a; memset(dst_done->a, 0, out->n*sizeof(*(dst_done->a))); + + n_mpath = 0; + for (i = 0; i < n_dst; ++i) { // mark dst vertices with a target distance + mg_path_dst_t *t = &dst[i]; + if (t->n_path > 0 && t->target_dist >= 0 && t->path_end >= 0){ + assert((int32_t)(out->a[t->path_end]->di>>32) == t->target_dist); + if(t->n_path >= max_k) { + t->n_path = 0; + for (z = zl = t->path_end; z >= 0;) { + zl = z; + z = out->a[z]->pre; + } + n += 2; trans[t->path_end] = trans[zl] = 1; + } else { + kk_p = 0; + for (j = t->path_end; j < (int32_t)out->n; j++) { + od = out->a[j]->di>>32; + if(od >= (t->target_dist*(1-len_dif)) && + od <= (t->target_dist*(1+len_dif))) { + if(out->a[j]->v == t->v) kk_p++; + } else { + break; + } + } + for (j = t->path_end-1; j >=0; j--) { + od = out->a[j]->di>>32; + if(od >= (t->target_dist*(1-len_dif)) && + od <= (t->target_dist*(1+len_dif))) { + if(out->a[j]->v == t->v) kk_p++; + } else { + break; + } + } + assert(kk_p > 0 && kk_p <= t->n_path); + n_mpath += kk_p; + } + } + } + + // if(detect_mul_way && src == 74) { + // fprintf(stderr, "+[M::%s::] src:%u, dst:%u, n_mpath:%d\n", __func__, src, dst[0].v, n_mpath); + // } + + if(n_mpath > 1) { + for (i = 0, pid = 0; i < n_dst; ++i) { // mark dst vertices with a target distance + mg_path_dst_t *t = &dst[i]; + if (t->n_path > 0 && t->target_dist >= 0 && t->path_end >= 0){ + assert((int32_t)(out->a[t->path_end]->di>>32) == t->target_dist); + assert(t->n_path < max_k); + for (j = t->path_end; j < (int32_t)out->n; j++) { + od = out->a[j]->di>>32; + if(od >= (t->target_dist*(1-len_dif)) && + od <= (t->target_dist*(1+len_dif))) { + if(out->a[j]->v == t->v) { + for (z = j; z >= 0;) { + kv_pushp(mg_pathv_t, *res, &h); + h->v = out->a[z]->v; h->pre = z; + h->d = pid; if(j!=t->path_end) h->d |= 0x80000000; + z = out->a[z]->pre; + } + pid++; + } + } else { + break; + } + } + for (j = t->path_end-1; j >=0; j--) { + od = out->a[j]->di>>32; + if(od >= (t->target_dist*(1-len_dif)) && + od <= (t->target_dist*(1+len_dif))) { + if(out->a[j]->v == t->v) { + for (z = j; z >= 0;) { + kv_pushp(mg_pathv_t, *res, &h); + h->v = out->a[z]->v; h->pre = z; + h->d = pid; if(j!=t->path_end) h->d |= 0x80000000; + z = out->a[z]->pre; + } + pid++; + } + } else { + break; + } + } + } + } + + radix_sort_mg_pathv_t_v_srt(res->a + res_n, res->a + res->n); + for (i = res_n+1, j = res_n/**, n = 0**/; i <= (int64_t)res->n; ++i) { + if (i == (int64_t)res->n || res->a[i].v != res->a[j].v) { + n += select_mul_way_nodes(res->a + j, i - j, out, len_dif, n_mpath, trans); + j = i; + } + } + + res->n = res_n; + } + + + if(n > 0) {//found some nodes + for (i = n = 0; (uint32_t)i < out->n; ++i) { // generate coordinate translations + if (trans[i]) { + trans[i] = n++; + } else { + trans[i] = (uint32_t)-1; + } + } + + kv_resize(mg_pathv_t, *res, res->n + n); //res->n += n; + for (i = 0; (uint32_t)i < out->n; ++i) { // generate the backtrack array + mg_pathv_t *p; + if (trans[i] == (uint32_t)-1) continue; + p = &res->a[trans[i]+res->n]; + p->v = out->a[i]->v, p->d = out->a[i]->di >> 32; + if(out->a[i]->pre < 0) { + p->pre = out->a[i]->pre; + } else { + if(trans[out->a[i]->pre] == (uint32_t)-1) p->pre = -2; + else p->pre = trans[out->a[i]->pre]; + } + } + + res->n += n; + for (i = 0; i < n_dst; ++i) // translate "path_end" + if (dst[i].path_end >= 0) + dst[i].path_end = trans[dst[i].path_end]; + } + + return n_mpath; +} + + +///max_dist is like the overlap length in string graph +///first_src_ban do not allow co-linear chain at the same node +void hc_shortest_k(void *km0, const asg_t *g, uint32_t src, int32_t n_dst, mg_path_dst_t *dst, int32_t max_dist, int32_t max_k, +st_mt_t *dst_done, uint64_t *dst_group, vec_sp_node_t *out, vec_mg_pathv_t *res, uint64_t first_src_ban, +uint64_t detect_mul_way, float len_dif) +{ + sp_node_t *p, *root = 0; + sp_topk_t *q; + khash_t(sp) *h;/// + khash_t(sp2) *h2;///alignment->vertice index + void *km; + khint_t k; + int absent; + int32_t i, j, n_done, n_found; + uint32_t id; + + // if (res) res->n = 0;///for us, n_pathv = NULL + if (n_dst <= 0) return;///n_dst: how many candidate vertices + for (i = 0; i < n_dst; ++i) { // initialize + mg_path_dst_t *t = &dst[i]; + ///if src and dest are at the same ref id, there are already one path + if (t->inner)///if two chains are at the same ref id + t->dist = 0, t->n_path = 1, t->path_end = -1; + else + t->dist = -1, t->n_path = 0, t->path_end = -1; + } + if (max_k > MG_MAX_SHORT_K) max_k = MG_MAX_SHORT_K; + km = km_init2(km0, 0x4000); + + // multiple dst[] may have the same dst[].v. We need to group them first. + // in other words, one ref id may have multiple dst alignment chains + dst_done->n = 0; kv_resize(uint64_t, *dst_done, (uint64_t)n_dst); + for (i = 0; i < n_dst; ++i) { + dst_group[i] = ((((uint64_t)dst[i].v)<<32)|((uint64_t)i)); + dst_done->a[i] = 0; + } + + radix_sort_gfa64(dst_group, dst_group + n_dst); + + h2 = kh_init2(sp2, km); // (h2+dst_group) keeps all destinations from the same ref id + kh_resize(sp2, h2, n_dst * 2); + ///please note that one contig in ref may have multiple alignment chains + ///so h2 is a index that helps us to query it + ///key(h2) = ref id; value(h2) = start_idx | occ + for (i = 1, j = 0; i <= n_dst; ++i) { + if (i == n_dst || dst_group[i]>>32 != dst_group[j]>>32) { + k = kh_put(sp2, h2, dst_group[j]>>32, &absent); + kh_val(h2, k) = (((uint64_t)j)<<32)|((uint64_t)(i-j)); + assert(absent); + j = i; + } + } + + h = kh_init2(sp, km); // h keeps visited vertices; path to each visited vertice + kh_resize(sp, h, 16); + + out->n = 0; kv_resize(sp_node_t*, *out, 16); ///16 is just the initial size + id = 0; + p = gen_sp_node(km, src, 0, id++);///just malloc a node for src; the distance is 0 + p->hash = __ac_Wang_hash(src);///hash is path hash, instead of node hash + kavl_insert(sp, &root, p, 0);///should be avl tree; p is a node at avl-tree + + ///each cell in the hash table corresponds to one node in the graph + ///each cell in the AVL tree is a path, corresponds to node in the graph + k = kh_put(sp, h, src, &absent); + q = &kh_val(h, k); + ///for normal graph traversal, one node just has one parental node; here each node has at most 16 parental nodes + q->k = 1, q->p[0] = p, q->mlen = 0, q->qs = q->qe = -1; + + n_done = 0; first_src_ban = first_src_ban?0:1; + ///the key of avl tree: #define sp_node_cmp(a, b) (((a)->di > (b)->di) - ((a)->di < (b)->di)) + ///the higher bits of (*)->di is distance to src node + ///so the key of avl tree is distance + ///in avl tree , one node might be saved multipe times + while (kavl_size(head, root) > 0) {///thr first root is src + int32_t i, nv; + asg_arc_t *av; + sp_node_t *r; + ///note that one node in the graph (sp_node_t->v) might be visited multiple times if there are circles + ///so there might be multipe cells in the avl-tree with the same (sp_node_t->v) + ///delete the first cell + r = kavl_erase_first(sp, &root); // take out the closest vertex in the heap (as a binary tree) + //fprintf(stderr, "XX\t%d\t%d\t%d\t%c%s[%d]\t%d\n", n_out, kavl_size(head, root), n_finished, "><"[(r->v&1)^1], g->seg[r->v>>1].name, r->v, (int32_t)(r->di>>32)); + + ///higher 32 bits might be the distance to root node + // lower 32 bits now for position in the out[] array + ///r->pre keep the pre-node in the path; follow the pre it is able to recover the whole path + r->di = ((r->di>>32)<<32)|((uint64_t)out->n); ///n_out is just the id in out + ///so one node id in graph might be saved multiple times in avl tree and out[] + kv_push(sp_node_t*, *out, r); + + ///r->v is the dst vertex id + ///sometimes k==kh_end(h2). Some nodes are found by graph travesal but not in linear chain alignment + k = kh_get(sp2, h2, r->v); + // we have reached one dst vertex + // note that one dst vertex may have multipe alignment chains + // we can visit some nodes in graph which are not reachable during chaining + // h2 is used to determine if one node is reachable or not + // if(src == 2844) { + // fprintf(stderr, "******src->%u, dst->%u, max_dist->%d\n", src, r->v, max_dist); + // } + if (k != kh_end(h2) && first_src_ban) { + ///node r->v might be visited multiple times + int32_t j, dist = r->di>>32, off = kh_val(h2, k) >> 32, cnt = (int32_t)kh_val(h2, k); + // if(src == 2844) { + // fprintf(stderr, "----src->%u, dst->%u, max_dist->%d, cnt->%d\n", src, r->v, max_dist, cnt); + // } + //src can reach ref id r->v; there might be not only one alignment chain in r->v + //so we need to scan all of them + for (j = 0; j < cnt; ++j) { + mg_path_dst_t *t = &dst[(int32_t)dst_group[off + j]];///t is a linear alignment at r->v + int32_t done = 0; + // if((src>>1) == 51) { + // fprintf(stderr, "###src->%u, dst->%u, max_dist->%d, dist:%d\n", src, r->v, max_dist, dist); + // } + ///the src and dest are at the same ref id, say we directly find the shortest path + if (t->inner) { + done = 1; + } else { + int32_t mlen = 0, copy = 0; + ///in the first round, we just check reachability without sequence + ///so h_seeds = NULL; we can assume mlen = 0 + /** //path + mlen = h_seeds? path_mlen(out, n_out - 1, h, t->qlen) : 0; + **/ + // means this alignment has never been visited before; keep it anyway + // note here is the alignment, instead of node + + // if(src == 2844) { + // fprintf(stderr, ">>src->%u, dst->%u, target_dist->%d, dist->%d, max_dist->%d\n", + // src, r->v, t->target_dist, dist, max_dist); + // } + if (t->n_path == 0) { + copy = 1; + // we have a target distance; choose the closest; + // there is already several paths reaching the linear alignment + } else if (t->target_dist >= 0) { + // we found the target path; hash is the path hash including multiple nodes, instead of node hash + if (dist == t->target_dist && t->check_hash && r->hash == t->target_hash) { + copy = 1, done = 1; + } else { + int32_t d0 = t->dist, d1 = dist; + d0 = d0 > t->target_dist? d0 - t->target_dist : t->target_dist - d0; + d1 = d1 > t->target_dist? d1 - t->target_dist : t->target_dist - d1; + ///if the new distance (d1) is smaller than the old distance (d0), update the results + ///the length of new path should be closer to t->target_dist + if (d1 - mlen/2 < d0 - t->mlen/2) copy = 1; + } + } + if (copy) { + t->path_end = out->n-1, t->dist = dist, t->hash = r->hash, t->mlen = mlen, t->is_0 = r->is_0; + if (t->target_dist >= 0) { + ///src is from li from li to lj, so the dis is generally increased; dijkstra algorithm + ///target_dist should be the distance on query + if (dist == t->target_dist && t->check_hash && r->hash == t->target_hash) { + done = 1; + } else if ((dist > t->target_dist + MG_SHORT_K_EXT) && (dist > (t->target_dist>>4)) && + (dist > (t->target_dist*1.25))) { + done = 1; + } + } + } + ++t->n_path;///we found a path to the alignment t + if (t->n_path >= max_k) done = 1; + } + if (detect_mul_way == 0 && dst_done->a[off + j] == 0 && done) + dst_done->a[off + j] = 1, ++n_done; + } + ///if all alignments have been settle down + ///pre-end; accelerate the loop + if (n_done == n_dst) break; + } + first_src_ban = 1; + ///below is used to push new nodes to avl tree for iteration + nv = asg_arc_n(g, r->v); + av = asg_arc_a(g, r->v); + for (i = 0; i < nv; ++i) { // visit all neighbors + asg_arc_t *ai = &av[i]; + ///v_lv is the (dest_length - overlap_length); it is a normal path length in string graph + ///ai->v_lv is the path length from r->v to ai->w + ///(r->di>>32) + int32_t d = (r->di>>32) + (uint32_t)ai->ul; + if (d > max_dist) continue; // don't probe vertices too far away + // h keeps visited vertices; path to each visited vertice + ///ai->w is the dest ref id; we insert a new ref id, instead of an alignment chain + k = kh_put(sp, h, ai->v, &absent);///one node might be visited multiple times + q = &kh_val(h, k); + if (absent) { // a new vertex visited + ///q->k: number of walks from src to ai->w + q->k = 0, q->qs = q->qe = -1; q->mlen = 0; + ///h_seeds = NULL; so q->mlen = 0 + /** //path + q->mlen = h_seeds && d + gfa_arc_lw(g, *ai) <= max_dist? node_mlen(km, g, ai->w, &mini, h_seeds, n_seeds, seeds, &q->qs, &q->qe) : 0; + **/ + //if (ql && qs) fprintf(stderr, "ql=%d,src=%d\tv=%c%s[%d],n_seeds=%d,mlen=%d\n", ql, src, "><"[ai->w&1], g->seg[ai->w>>1].name, ai->w, n_seeds, q->mlen); + } + ///if there are less than walks from src to ai->w, directly add + ///if there are more, keep the smallest walks + if (q->k < max_k) { // enough room: add to the heap + p = gen_sp_node(km, ai->v, d, id++); + p->pre = out->n - 1;///the parent node of this one + p->hash = r->hash + __ac_Wang_hash(ai->v); + p->is_0 = r->is_0; + /** //path + if (ai->rank > 0) p->is_0 = 0; + **/ + kavl_insert(sp, &root, p, 0); + q->p[q->k++] = p; + ks_heapup_sp(q->k, q->p);///adjust heap by distance + } else if ((int32_t)(q->p[0]->di>>32) > d) { // shorter than the longest path so far: replace the longest + p = kavl_erase(sp, &root, q->p[0], 0); + if (p) { + p->di = (uint64_t)d<<32 | (id++); + p->pre = out->n - 1; + p->hash = r->hash + __ac_Wang_hash(ai->v); + p->is_0 = r->is_0; + /** //path + if (ai->rank > 0) p->is_0 = 0; + **/ + kavl_insert(sp, &root, p, 0); + ks_heapdown_sp(0, q->k, q->p); + } else { + fprintf(stderr, "Warning: logical bug in gfa_shortest_k(): q->k=%d,q->p[0]->{d,i}={%d,%d},d=%d,src=%u,max_dist=%d,n_dst=%d\n", q->k, (int32_t)(q->p[0]->di>>32), (int32_t)q->p[0]->di, d, src, max_dist, n_dst); + km_destroy(km); + return; + } + } // else: the path is longer than all the existing paths ended at ai->w + } + } + kh_destroy(sp, h); + // NB: AVL nodes are not deallocated. When km==0, they are memory leaks. + + for (i = 0, n_found = 0; i < n_dst; ++i) + if (dst[i].n_path > 0) ++n_found;///n_path might be larger than 16 + ///we can assume n_pathv = NULL for now + if (n_found > 0 && res) { // then generate the backtrack array + int32_t n, n_mpath = 1; dst_done->n = 0; kv_resize(uint64_t, *dst_done, out->n); + uint64_t *trans = dst_done->a; memset(dst_done->a, 0, out->n*sizeof(*(dst_done->a))); + + if(detect_mul_way) { + n_mpath = phase_mul_ways(res, dst_done, out, n_dst, dst, max_k, len_dif); + } + + if(n_mpath == 1) { + // KCALLOC(km, trans, n_out); // used to squeeze unused elements in out[] + ///n_out: how many times that nodes in graph have been visited + ///note one node might be visited multiples times + ///n_dst: number of alignment chains + for (i = 0; i < n_dst; ++i) { // mark dst vertices with a target distance + mg_path_dst_t *t = &dst[i]; + if (t->n_path > 0 && t->target_dist >= 0 && t->path_end >= 0) + trans[(uint32_t)out->a[t->path_end]->di] = 1;///(int32_t)out[]->di: traverse track corresponds to the alignment chain dst[] + } + // for (i = 0; (uint32_t)i < out->n; ++i) { // mark dst vertices without a target distance + // k = kh_get(sp2, h2, out->a[i]->v); + // if (k != kh_end(h2)) { // TODO: check if this is correct! + // int32_t off = kh_val(h2, k)>>32, cnt = (int32_t)kh_val(h2, k); + // for (j = off; j < off + cnt; ++j) + // if (dst[j].target_dist < 0) + // trans[i] = 1; + // } + // } + for (i = (int32_t)(out->n) - 1; i >= 0; --i) // mark all predecessors + if (trans[i] && out->a[i]->pre >= 0) + trans[out->a[i]->pre] = 1; + for (i = n = 0; (uint32_t)i < out->n; ++i) // generate coordinate translations + if (trans[i]) trans[i] = n++; + else trans[i] = (uint32_t)-1; + + kv_resize(mg_pathv_t, *res, res->n + n); //res->n += n; + for (i = 0; (uint32_t)i < out->n; ++i) { // generate the backtrack array + mg_pathv_t *p; + if (trans[i] == (uint32_t)-1) continue; + p = &res->a[trans[i]+res->n]; + p->v = out->a[i]->v, p->d = out->a[i]->di >> 32; + p->pre = out->a[i]->pre < 0? out->a[i]->pre:trans[out->a[i]->pre]; + } + res->n += n; + for (i = 0; i < n_dst; ++i) // translate "path_end" + if (dst[i].path_end >= 0) + dst[i].path_end = trans[dst[i].path_end]; + } + } + + km_destroy(km); +} + +///p[]: id of last +///f[]: the score ending at i, not always the peak +///v[]: keeps the peak score up to i; +///t[]: used for buffer +///min_cnt = 2; min_sc = 30; extra_u = 0 +///u = mg_chain_backtrack(n, f, p, v, t, min_cnt, min_sc, 0, &n_u, &n_v); +int64_t hc_chain_backtrack(int64_t n, const int64_t *f, const uint64_t *p, uint64_t *srt, uint64_t *u, uint64_t *v, +int64_t *n_u_, int64_t *n_v_) +{ + if(n_u_) {*n_u_ = 0;} if(n_v_) {*n_v_ = 0;} + int64_t i, k, n_v, n_srt, n_v0, n_u, sc; + if (n == 0) return 0; + // v[] keeps the peak score up to i; f[] is the score ending at i, not always the peak + *n_u_ = *n_v_ = 0; + for (i = 0, k = 0; i < n; ++i) { + if(f[i] >= 0) { + srt[k] = (uint64_t)f[i]; srt[k] <<= 32; srt[k] |= (((uint64_t)i)<<1); k++; + } + } + n_srt = k; + radix_sort_gfa64(srt, srt + n_srt); ///sort by score + + ///from the largest to the smallest + for (k = n_srt-1, n_v = n_u = 0; k >= 0; --k) { // precompute n_u + n_v0 = n_v; + for (i = ((uint32_t)srt[k])>>1; i >= 0 && (srt[i]&1) == 0; i = (p[i]==(uint64_t)-1?-1:p[i])) { + v[n_v++] = i; srt[i] |= 1; + } + if(n_v <= n_v0) continue; + sc = i < 0? srt[k]>>32: (int64_t)(srt[k]>>32)-f[i]; + u[n_u++] = (((uint64_t)sc)<<32) | ((uint64_t)(n_v-n_v0)); + } + + if(n_u_) {*n_u_ = n_u;} if(n_v_) {*n_v_ = n_v;} + return n_u; +} + +uint64_t ck_hq_chain(mg_lchain_t *li, mg_lchain_t *lj, ma_ug_t *ug, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double ng_diff_thre) +{ + if(lj->qe+G_CHAIN_INDEL <= li->qs) return 0; + if(lj->qs >= li->qs/**+G_CHAIN_INDEL**/) return 0; + ul_ov_t ui, uj; int64_t qo, share +; set_ul_ov_t_by_mg_lchain_t(&ui, li); set_ul_ov_t_by_mg_lchain_t(&uj, lj); + qo = infer_rovlp(&ui, &uj, NULL, NULL, NULL, ug); ///overlap length in query (UL read) + if(li->v!=lj->v && get_ecov_adv(uref, uopt, li->v^1, lj->v^1, bw, ng_diff_thre, qo, 0, &share)) { + return 1; + } + return 0; +} + +int64_t hc_gchain1_dp(void *km, const ul_idx_t *uref, const ma_ug_t *ug, vec_mg_lchain_t *lc, vec_mg_lchain_t *sw, vec_mg_path_dst_t *dst, vec_sp_node_t *out, vec_mg_pathv_t *path, +int64_t qlen, const ug_opt_t *uopt, int64_t bw, double diff_thre, double ng_diff_thre, uint64_t *srt, st_mt_t *bf, int64_t *f, uint64_t *p, uint64_t *v) +{ + bf->n = 0; + if(lc->n == 0) return 0; + int64_t i, j, lc_n = lc->n, n_ext, mm_ovlp, target_dist, max_target_dist, x, m_idx, m_sc, qo, sc; + int64_t max_f, max_j = -1, max_d = -1, max_inner = 0, share; uint32_t max_hash = 0; int64_t k, k0, n_u, n_v, ni; + mg_lchain_t *r, *li, *lj; mg_path_dst_t *q; asg_t *g = ug->g; uint64_t isolated, *u; ul_ov_t ui, uj; + for (i = n_ext = 0; i < lc_n; i++) { + r = &lc->a[i]; r->dist_pre = -1; isolated = 0;///dist_pre -> parent in graph chain + if((r->re < g->seq[r->v>>1].len) && (r->rs > 0)) isolated = 1;///UL contained in one vertice + if (!isolated) ++n_ext; + srt[i] = r->qe; srt[i] <<= 32; srt[i] |= (uint64_t)i; srt[i] |= (isolated<<63); + } + radix_sort_gfa64(srt, srt+lc_n); + for (i = 1, j = 0; i <= lc_n; i++) { + if (i == lc_n || (srt[i]>>32) != (srt[j]>>32)) { + if(i - j > 1) { + for (x = j; x < i; x++) { + srt[x] <<= 32; srt[x] >>= 32; srt[x] |= ((uint64_t)lc->a[(uint32_t)srt[x]].qs)<<32; + } + radix_sort_gfa64(srt+j, srt+i); + } + j = i; + } + } + + kv_resize(mg_lchain_t, *sw, (uint64_t)lc_n); sw->n = lc_n; + for (i = 0; i < lc_n; i++) sw->a[i] = lc->a[(uint32_t)srt[i]]; + memcpy(lc->a, sw->a, lc_n *sizeof((*(lc->a)))); + // fprintf(stderr, "[M::%s::] n_ext:%ld, lc_n:%ld\n", __func__, n_ext, lc_n); + + if(ng_diff_thre >= 0) { + //first non-gap chain + for (i = 0; i < n_ext; ++i) { // core loop + li = &lc->a[i]; set_ul_ov_t_by_mg_lchain_t(&ui, li); + mm_ovlp = max_ovlp(g, li->v^1); + x = (li->qs + mm_ovlp)*diff_thre; if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_mg_lchain_max(i, lc->a, x+G_CHAIN_INDEL); + // fprintf(stderr, "\nli->(%ld)\tutg%.6d%c(%u)\tqs:%u\tqe:%u\t%c\trs:%u\tre:%u\tsrc:%u\tscore:%d, x:%ld\n", + // i, (int32_t)(li->v>>1)+1, "lc"[ug->u.a[li->v>>1].circ], ug->u.a[li->v>>1].len, + // li->qs, li->qe, "+-"[li->v&1], li->rs, li->re, li->v^1, li->score, x); + max_f = li->score, max_j = -1; + // collect potential destination vertices + for (j = x; j >= 0; --j) { + lj = &lc->a[j]; ///extend_end_coord(lj, qlen, g->seq[lj->v>>1].len, &jqs, &jqe, &jrs, &jre); + //even this pair has a overlap, its length will be very small; just ignore; only for non-gapped chains + if(lj->qe+G_CHAIN_INDEL <= li->qs) break; + if(lj->qs >= li->qs/**+G_CHAIN_INDEL**/) continue; + set_ul_ov_t_by_mg_lchain_t(&uj, lj); + qo = infer_rovlp(&ui, &uj, NULL, NULL, NULL, (ma_ug_t *)ug); ///overlap length in query (UL read) + if(li->v!=lj->v && get_ecov_adv(uref, uopt, li->v^1, lj->v^1, bw, ng_diff_thre, qo, 0, &share)) { + sc = li->score + f[j]; + if(sc > max_f) { + max_f = sc; max_j = j; + } + } + } + + f[i] = max_f, p[i] = max_j<0?(uint64_t)-1:max_j; + li->dist_pre = max_j<0?-1:g_adjacent_dis(g, li->v^1, lc->a[max_j].v^1); li->inner_pre = 0; + li->hash_pre = max_j<0?0:(__ac_Wang_hash((li->v^1))+__ac_Wang_hash((lc->a[max_j].v^1))); + // fprintf(stderr, "i->%ld, utg%.6d%c->utg%.6d%c, max_f:%ld\n", i, (int32_t)(li->v>>1)+1, "lc"[ug->u.a[li->v>>1].circ], + // max_j<0?0:(int32_t)(lc->a[max_j].v>>1)+1, max_j<0?'*':"lc"[ug->u.a[lc->a[max_j].v>>1].circ], max_f); + } + + kv_resize(uint64_t, *bf, (uint64_t)lc_n); u = bf->a; + hc_chain_backtrack(n_ext, f, p, srt, u, v, &n_u, &n_v); + for (i = 0; i < lc_n - n_ext; ++i) { + u[n_u++] = (((uint64_t)lc->a[n_ext + i].score)<<32) | 1; + v[n_v++] = n_ext + i; + } + + sw->n = 0; kv_resize(mg_lchain_t, *sw, (uint64_t)n_v); m_idx = m_sc = -1; bf->n = 0; + for (i = 0, k = 0; i < n_u; ++i) { + k0 = k, ni = (int32_t)u[i]; + for (j = 0; j < ni; ++j) { + sw->a[k++] = lc->a[v[k0 + (ni - j - 1)]]; + } + if(m_idx < 0 || m_sc < ((int64_t)(u[i]>>32))) { + m_idx = i; m_sc = ((int64_t)(u[i]>>32)); + } + } + assert(k == n_v); bf->n = n_u; + + if(primary_chain_check(u, n_u, sw->a)) { + memcpy(lc->a, sw->a, n_v*sizeof(mg_lchain_t)); + return m_idx; + } + } + bf->n = 0; + + ///then gapped-chaining + for (i = 0; i < n_ext; ++i) { // core loop + li = &lc->a[i]; + mm_ovlp = max_ovlp(g, li->v^1); + x = (li->qs + mm_ovlp)*diff_thre; if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_mg_lchain_max(i, lc->a, x+G_CHAIN_INDEL); + // fprintf(stderr, "\nli->(%ld)\tutg%.6d%c(%u)\tqs:%u\tqe:%u\t%c\trs:%u\tre:%u\tsrc:%u\tscore:%d, x:%ld\n", + // i, (int32_t)(li->v>>1)+1, "lc"[ug->u.a[li->v>>1].circ], ug->u.a[li->v>>1].len, + // li->qs, li->qe, "+-"[li->v&1], li->rs, li->re, li->v^1, li->score, x); + + // collect potential destination vertices + for (dst->n = 0, max_target_dist= -1, j = x; j >= 0; --j) { + ///same time for gchain + // if((p[j]>>33) == ((uint64_t)i)) continue; + + lj = &lc->a[j]; ///extend_end_coord(lj, qlen, g->seq[lj->v>>1].len, &jqs, &jqe, &jrs, &jre); + //lj contained in li; actually in circle, this might happen; need to deal with it later + if(lj->qs >= li->qs/**+G_CHAIN_INDEL**/) continue; + ///if there is a circle, the two linear chains might be at the same vertice + target_dist = hc_target_len(g, li, lj); + // fprintf(stderr, "j:%ld, target_dist:%ld\n", j, target_dist); + if(target_dist < 0) continue; + kv_pushp(mg_path_dst_t, *dst, &q); + memset(q, 0, sizeof(*q)); + q->inner = 0;//we set q->inner = 0 to allow circles + q->v = lj->v^1;///must be v^1 instead of v + q->meta = j; + ///lj->qs************lj->qe + /// li->qs************li->qe + q->qlen = li->qs - lj->qe;///might be negative; this is the region that need to be checked in base-level + q->target_dist = target_dist;///cannot understand the target_dist + q->target_hash = 0; + q->check_hash = 0; + if(max_target_dist < target_dist) max_target_dist = target_dist; + ///not sure how to use this cut-off + // if (t[j] == i) { + // if (++n_skip > max_skip) + // break; + // } + // if (p[j] >= 0) t[p[j]] = i; + // if((li->v>>1)==10 && ((lj->v>>1)==15||(lj->v>>1)==14)) max_target_dist = 100000; + // fprintf(stderr, "+++lj->(%ld)\tutg%.6d%c(%u)\t%u\t%u\t%c\ttarget_dist:%d\n", + // j, (int32_t)(lj->v>>1)+1, "lc"[ug->u.a[lj->v>>1].circ], ug->u.a[lj->v>>1].len, + // lj->qs, lj->qe, "+-"[lj->v&1], q->target_dist); + + ///j-th has pre, and the pre is good alignment + ///same time for gchain + // if((((uint32_t)p[j])!=((uint32_t)-1)) && (p[j]&(uint64_t)(0x100000000))) { + // p[((uint32_t)p[j])] &= (uint64_t)(0x1ffffffff); + // p[((uint32_t)p[j])] |= (((uint64_t)i)<<33); + // } + } + + // confirm reach-ability + max_f = li->score, max_j = -1, max_d = -1, max_inner = 0; max_hash = 0; + if(dst->n) { + max_target_dist *= (1+diff_thre); if(max_target_dist < bw) max_target_dist = bw; + hc_shortest_k(km, g, li->v^1, dst->n, dst->a, max_target_dist, MG_MAX_SHORT_K, bf, srt, out, NULL, 1, 0, 0); + // remove unreachable destinations + //TODO: check sequence identity + for (j = 0; j < (int64_t)dst->n; ++j) { + mg_path_dst_t *dj = &dst->a[j]; + if (dj->n_path == 0) continue; // unreachable + sc = cal_gchain_sc(dj, li, lc->a, f, bw, diff_thre, W_CHN_PEN_GAP); + + // fprintf(stderr, "---dj->(%ld)\tutg%.6d%c(%u)\tsc:%d\tmax_f:%ld\ttarget_dist:%d\tdj->dist:%d\n", + // j, (int32_t)(dj->v>>1)+1, "lc"[ug->u.a[dj->v>>1].circ], ug->u.a[dj->v>>1].len, sc, max_f, dj->target_dist, dj->dist); + if (sc == INT32_MIN) continue; // out of band + // fprintf(stderr, "+max_f->%d, max_j->%d\n", max_f, max_j); + if (sc < 0) continue;// negative score + // fprintf(stderr, "++max_f->%d, max_j->%d\n", max_f, max_j); + if (sc > max_f) { + max_f = sc, max_j = dj->meta, max_d = dj->dist, max_hash = dj->hash, max_inner = dj->inner; + // fprintf(stderr, "+++max_f->%d, max_j->%d\n", max_f, max_j); + } + } + } + + f[i] = max_f; p[i] = max_j<0?(uint64_t)-1:max_j; + ///same time for gchain + // if(max_j < 0) { + // p[i] = (uint32_t)-1; + // } else { + // p[i] = max_j; + // if(ck_hq_chain(li, &(lc->a[max_j]), (ma_ug_t *)ug, uref, uopt, bw, ng_diff_thre)) { + // p[i] |= (uint64_t)(0x100000000); + // } + // } + + + li->dist_pre = max_d; + li->hash_pre = max_hash; + li->inner_pre = max_inner; + // fprintf(stderr, "i->%ld, utg%.6d%c->utg%.6d%c, max_f:%ld\n", i, (int32_t)(li->v>>1)+1, "lc"[ug->u.a[li->v>>1].circ], + // max_j<0?0:(int32_t)(lc->a[max_j].v>>1)+1, max_j<0?'*':"lc"[ug->u.a[lc->a[max_j].v>>1].circ], max_f); + } + + ///same time for gchain + // for (i = 0; i < n_ext; ++i) { + // if(((uint32_t)p[i])==((uint32_t)-1)) p[i] = (uint64_t)-1; + // else p[i] = (uint32_t)p[i]; + // } + + kv_resize(uint64_t, *bf, (uint64_t)lc_n); u = bf->a; + hc_chain_backtrack(n_ext, f, p, srt, u, v, &n_u, &n_v); + for (i = 0; i < lc_n - n_ext; ++i) { + u[n_u++] = (((uint64_t)lc->a[n_ext + i].score)<<32) | 1; + v[n_v++] = n_ext + i; + } + + sw->n = 0; kv_resize(mg_lchain_t, *sw, (uint64_t)n_v); m_idx = m_sc = -1; bf->n = 0; + for (i = 0, k = 0; i < n_u; ++i) { + k0 = k, ni = (int32_t)u[i]; + for (j = 0; j < ni; ++j) { + sw->a[k++] = lc->a[v[k0 + (ni - j - 1)]]; + } + if(m_idx < 0 || m_sc < ((int64_t)(u[i]>>32))) { + m_idx = i; m_sc = ((int64_t)(u[i]>>32)); + } + } + assert(k == n_v); bf->n = n_u; + memcpy(lc->a, sw->a, n_v*sizeof(mg_lchain_t)); + return m_idx; +} + + +void debug_gchain(void *km, const asg_t *g, mg_lchain_t *a, uint64_t n, st_mt_t *dst_done, vec_sp_node_t *out) +{ + uint64_t k, i, v, w, nv; int64_t dd; asg_arc_t *av; mg_path_dst_t dst; uint64_t dst_group; + for (k = 1; k < n; k++) { + v = a[k].v^1; w = a[k-1].v^1; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (i = 0; i < nv; i++) { + if(av[i].v == w) break; + } + // if(i >= nv) { + // // fprintf(stderr, "[M::%s::]\n", __func__); + // fprintf(stderr, "[M::%s::]\tutg%.6dl(%c)\t->\tutg%.6dl(%c)\n", __func__, (int32_t)(v>>1)+1, "+-"[v&1], (int32_t)(w>>1)+1, "+-"[w&1]); + // } + if(i < nv) { + dd = (int64_t)((uint32_t)(av[i].ul)); + } else { + memset(&dst, 0, sizeof(dst)); + dst.v = w; + dst.target_dist = a[k-1].dist_pre; + dst.target_hash = 0; dst.check_hash = 0; + hc_shortest_k(km, g, v, 1, &dst, dst.target_dist, MG_MAX_SHORT_K, dst_done, &dst_group, out, NULL, 1, 0, 0); + dd = dst.dist; + } + if(a[k-1].dist_pre != dd) { + fprintf(stderr, "[M::%s::]\tutg%.6dl(%c)\t->\tutg%.6dl(%c)\tdist_pre:%d\td:%ld\n", __func__, (int32_t)(v>>1)+1, "+-"[v&1], + (int32_t)(w>>1)+1, "+-"[w&1], a[k-1].dist_pre, dd); + } + } +} + +void debug_gchain2(const asg_t *g, mg_pathv_t *a, uint64_t n) +{ + uint64_t k, i, v, w, nv; asg_arc_t *av; + for (k = 1; k < n; k++) { + v = a[k-1].v; w = a[k].v; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (i = 0; i < nv; i++) { + if(av[i].v == w) break; + } + if(i >= nv) { + // fprintf(stderr, "[M::%s::]\n", __func__); + fprintf(stderr, "[M::%s::]\tutg%.6dl(%c)\t->\tutg%.6dl(%c)\n", __func__, (int32_t)(v>>1)+1, "+-"[v&1], (int32_t)(w>>1)+1, "+-"[w&1]); + } + } +} + + +void reverse_track(mg_pathv_t *a, uint64_t a_n) +{ + int64_t k, hn = (a_n>>1); mg_pathv_t z; + for (k = a_n-1; k >= 1; k--) a[k].d -= a[k-1].d; + + for (k = 0; k < hn; k++) { + z = a[k]; a[k] = a[a_n - k - 1]; a[a_n - k - 1] = z; + a[k].v ^= 1; a[a_n - k - 1].v ^= 1; + } + if(a_n&1) a[k].v ^= 1; +} + +void dbg_print(mg_pathv_t *a, int64_t a_n) +{ + int64_t k; + for (k = 0; k < a_n; k++) { + if(a[k].pre == -2) break; + } + + if(k < a_n) { + fprintf(stderr, "+[M::%s::] src:utg%.6dl(v:%u), dst:utg%.6dl(v:%u)\n", __func__, + (int32_t)(a[0].v>>1)+1, a[0].v, (int32_t)(a[a_n-1].v>>1)+1, a[a_n-1].v); + for (k = 0; k < a_n; k++) { + fprintf(stderr, "-[M::%s::] utg%.6dl(v:%u), pre:%d, d:%u\n", __func__, (int32_t)(a[k].v>>1)+1, a[k].v, + a[k].pre, a[k].d); + } + } + +} + +uint32_t gen_gchain_track(void *km, mg_lchain_t *a, int64_t a_n, const asg_t *g, +st_mt_t *dst_done, vec_sp_node_t *out, vec_mg_pathv_t *res) +{ + int64_t k, p_n/**, trav_occ = 0**/; mg_lchain_t *l0, *l1; mg_path_dst_t dst; uint64_t dst_group; mg_pathv_t *p; + res->n = 0; kv_pushp(mg_pathv_t, *res, &p); p->v = (uint32_t)-1; p->d = 0; p->pre = 0; + for (k = 1; k < a_n; k++) { + l0 = a + k - 1; l1 = a + k; + assert(!l1->inner_pre); assert(l1->dist_pre >= 0); + memset(&dst, 0, sizeof(dst)); + dst.v = l0->v^1; + assert(l1->dist_pre >= 0); + dst.target_dist = l1->dist_pre; + dst.target_hash = l1->hash_pre; + dst.check_hash = 1; p_n = res->n; + if((dst.target_hash != (__ac_Wang_hash((l1->v^1))+__ac_Wang_hash(dst.v))) || + (g_adjacent_dis(g, l1->v^1, dst.v) != dst.target_dist)) { + hc_shortest_k(km, g, l1->v^1, 1, &dst, dst.target_dist*(1+SEC_LEN_DIF), MG_MAX_SHORT_K, dst_done, &dst_group, out, res, 1, 1, SEC_LEN_DIF); + // debug_gchain2(g, res->a + p_n, res->n - p_n); + // fprintf(stderr, "[M::%s::n->%ld]\tutg%.6dl(%c)\t->\tutg%.6dl(%c)\n", __func__, res->n - p_n, + // (int32_t)(l0->v>>1)+1, "+-"[l0->v&1], (int32_t)(l1->v>>1)+1, "+-"[l1->v&1]); + + // fprintf(stderr, "\n-[M::%s::res->n->%u::p_n->%ld] utg%.6dl(v:%u) -> utg%.6dl(v:%u)\n", + // __func__, (uint32_t)res->n, p_n, (int32_t)(l1->v>>1)+1, l1->v, (int32_t)(l0->v>>1)+1, l0->v); + // dbg_print(res->a + p_n, res->n - p_n); + assert(res->n - p_n > 1); assert(dst.target_hash == dst.hash); + res->a[p_n-1].d = res->a[res->n-1].d - res->a[res->n-2].d; res->n--; + reverse_track(res->a + p_n, res->n - p_n); res->n--;///reomve l1 from res + // trav_occ++; + } else { + res->a[p_n-1].d = dst.target_dist; + } + + kv_pushp(mg_pathv_t, *res, &p); p->v = (uint32_t)-1; p->pre = k; p->d = 0; + + } + // fprintf(stderr, "[M::%s::]\ta_n:%ld\ttrav_occ:%ld\n", __func__, a_n, trav_occ); + return res->n; +} + +void print_chain(mg_lchain_t *a, uint32_t a_n) +{ + uint32_t k; + for (k = 0; k < a_n; k++) { + if(a[k].off!=-1) { + fprintf(stderr, "%u\t%u\t%c\tutg%.6dl\t%u\t%u\n", + a[k].qs, a[k].qe, "+-"[a[k].v&1], (int32_t)(a[k].v>>1)+1, a[k].rs, a[k].re); + } else { + fprintf(stderr, "*\t*\t%c\tutg%.6dl\t*\t*\n", "+-"[a[k].v&1], (int32_t)(a[k].v>>1)+1); + } + } +} + +void update_exist_chain(const ul_idx_t *uref, ul_ov_t *ch, uint64_t *idx, int64_t idx_n, int64_t tid, int64_t bw, +double diff_ec_ul, mg_lchain_t *res) +{ + int64_t i, j, cov_i, i_qs, i_qe, i_ts, i_te, j_qs, j_qe, j_ts, j_te, dq, dt, dd, mm, sc = 0; + int64_t tlen = uref->ug->g->seq[tid].len; memset(res, 0, sizeof(*res)); + ul_ov_t *li, *lj; + if(idx_n <= 0) return; + i = idx_n - 1; + res->qs = (ch[idx[i]].qs<<1)>>1; res->qe = ch[idx[i]].qe; + res->rs = ch[idx[i]].ts; res->re = ch[idx[i]].te; + for (; i >= 0; i--) { + li = &(ch[idx[i]]); + i_qs = (li->qs<<1)>>1; i_qe = li->qe; + i_ts = (li->rev?(tlen-li->te):(li->ts)); + i_te = (li->rev?(tlen-li->ts):(li->te)); + + if((int64_t)((li->qs<<1)>>1) < res->qs) res->qs = ((li->qs<<1)>>1); + if((int64_t)li->ts < res->rs) res->rs = li->ts; + if((int64_t)li->qe > res->qe) res->qe = li->qe; + if((int64_t)li->te > res->re) res->re = li->te; + + cov_i = 0; j = i + 1; + if(j < idx_n) { + lj = &(ch[idx[j]]); + j_qs = (lj->qs<<1)>>1; j_qe = lj->qe; + j_ts = (lj->rev?(tlen-lj->te):(lj->ts)); + j_te = (lj->rev?(tlen-lj->ts):(lj->te)); + if(j_qs <= i_qs && j_qe <= i_qe && j_ts <= i_ts && j_te <= i_te) {///co-linear + assert(li->rev == lj->rev); + if(j_qs == i_qs && j_qe == i_qe && j_ts == i_ts && j_te == i_te) continue; + dq = i_qe - j_qs; dt = i_te - j_ts; + dd = (dq>dt? dq-dt:dt-dq); + mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; + if(dd <= mm) {///pass distance checking + sc += get_add_cov_score(uref, lj->ts, lj->te, li->ts, li->te, tid, &cov_i); + } + } + } else { + sc += retrieve_u_cov_region(uref, tid, 0, li->ts, li->te, &cov_i); + } + } + res->score = (sc>0x3FFFFFFF?0x3FFFFFFF:sc); +} + +void debug_ll_chains(const ul_idx_t *uref, uint64_t *ix, int64_t ix_n, int64_t p_sidx, int64_t p_eidx, mg_lchain_t *chain_a, +kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, uint64_t *b, int64_t bw, double diff_ec_ul, int64_t qlen) +{ + int64_t k, i, z, a_n, ss, ee, b_n; uint64_t qs, qe, ts, te; uint32_t mk = 0x80000000; mg_lchain_t nn; + int64_t iqs, iqe, its, ite, tsc; + + for (k = p_sidx; k < p_eidx; k++) { + i = raw_idx->a[chain_a[k].off].qn; + qs = raw_chn->a[i].qs; qe = raw_chn->a[i].qe; + ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; + // fprintf(stderr, "++++++++++++[M::%s::idx:%ld]\n", __func__, i); + for (;i>=0;) { + // fprintf(stderr, "--[M::%s::i->%ld]\n", __func__, i); + if(raw_chn->a[i].qs < qs) qs = raw_chn->a[i].qs; + if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; + if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; + if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; + raw_chn->a[i].qs |= mk; + + if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; + else i = raw_chn->a[i].tn; + } + assert(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && + raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te); + } + + + ///dedup + for (z = a_n = 0; z < ix_n; ++z) { + ss = a_n; ee = a_n + ((uint32_t)ix[z]); tsc = 0; + /**if(ss != p_sidx || ee != p_eidx)**/ { + for (k = ss; k < ee; k++) { + i = raw_idx->a[chain_a[k].off].qn; b_n = 0; + qs = ((raw_chn->a[i].qs<<1)>>1); qe = raw_chn->a[i].qe; + ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; + // fprintf(stderr, "++++++++++++[M::%s::idx:%ld]\n", __func__, i); + for (;i>=0;) { + // fprintf(stderr, "--[M::%s::i->%ld]\n", __func__, i); + if(((raw_chn->a[i].qs<<1)>>1) < qs) qs = ((raw_chn->a[i].qs<<1)>>1); + if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; + if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; + if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; + // raw_chn->a[i].qs |= mk; + //update here!!!!!!! + // if(!(raw_chn->a[i].qs&mk)) b[b_n++] = i; + b[b_n++] = i; + if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; + else i = raw_chn->a[i].tn; + } + assert(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && + raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te); + + update_exist_chain(uref, raw_chn->a, b, b_n, raw_idx->a[chain_a[k].off].tn, bw, diff_ec_ul, &nn); + nn.v = (raw_idx->a[chain_a[k].off].tn<<1)|raw_idx->a[chain_a[k].off].rev; + extend_end_coord(&nn, NULL, qlen, uref->ug->g->seq[raw_idx->a[chain_a[k].off].tn].len, + &iqs, &iqe, &its, &ite); + nn.qs = iqs; nn.qe = iqe; nn.rs = its; nn.re = ite; + if(!(chain_a[k].score == nn.score && chain_a[k].qs == nn.qs && chain_a[k].qe == nn.qe + && chain_a[k].rs == nn.rs && chain_a[k].re == nn.re)){ + fprintf(stderr, "[M::%s::] chain_a[k].score->%d, nn.score->%d\n", __func__, chain_a[k].score, nn.score); + fprintf(stderr, "[M::%s::] chain_a[k].qs->%d, nn.qs->%d, chain_a[k].qe->%d, nn.qe->%d, chain_a[k].rs->%d, nn.rs->%d, chain_a[k].re->%d, nn.re->%d\n", __func__, + chain_a[k].qs, nn.qs, chain_a[k].qe, nn.qe, chain_a[k].rs, nn.rs, chain_a[k].re, nn.re); + } + assert(chain_a[k].score == nn.score && chain_a[k].qs == nn.qs && chain_a[k].qe == nn.qe + && chain_a[k].rs == nn.rs && chain_a[k].re == nn.re); + tsc += nn.score; + } + assert(tsc >= ((int64_t)(ix[z]>>32))); + } + + a_n += ((uint32_t)ix[z]); + } + + + + for (k = p_sidx; k < p_eidx; k++) { + i = raw_idx->a[chain_a[k].off].qn; + qs = ((raw_chn->a[i].qs<<1)>>1); qe = raw_chn->a[i].qe; + ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; + for (;i>=0;) { + // fprintf(stderr, "--[M::%s::i->%ld]\n", __func__, i); + if(raw_chn->a[i].qs&mk) raw_chn->a[i].qs -= mk; + if(raw_chn->a[i].qs < qs) qs = raw_chn->a[i].qs; + if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; + if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; + if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; + + + if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; + else i = raw_chn->a[i].tn; + } + assert(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && + raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te); + } +} + +void dedup_second_chain(const ul_idx_t *uref, uint64_t *ix, int64_t ix_n, int64_t p_sidx, int64_t p_eidx, mg_lchain_t *chain_a, +kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, uint64_t *b, int64_t bw, double diff_ec_ul, int64_t qlen) +{ + int64_t k, i, z, a_n, ss, ee, b_n; uint64_t qs, qe, ts, te; uint32_t mk = 0x80000000; mg_lchain_t nn; + int64_t iqs, iqe, its, ite, tsc; + + for (k = p_sidx; k < p_eidx; k++) { + i = raw_idx->a[chain_a[k].off].qn; + qs = raw_chn->a[i].qs; qe = raw_chn->a[i].qe; + ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; + // fprintf(stderr, "++++++++++++[M::%s::idx:%ld]\n", __func__, i); + for (;i>=0;) { + // fprintf(stderr, "--[M::%s::i->%ld]\n", __func__, i); + if(raw_chn->a[i].qs < qs) qs = raw_chn->a[i].qs; + if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; + if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; + if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; + raw_chn->a[i].qs |= mk; + + if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; + else i = raw_chn->a[i].tn; + } + assert(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && + raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te); + } + + + ///dedup + for (z = a_n = 0; z < ix_n; ++z) { + ss = a_n; ee = a_n + ((uint32_t)ix[z]); tsc = 0; + if(ss != p_sidx || ee != p_eidx) { + for (k = ss; k < ee; k++) { + i = raw_idx->a[chain_a[k].off].qn; b_n = 0; + qs = ((raw_chn->a[i].qs<<1)>>1); qe = raw_chn->a[i].qe; + ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; + // fprintf(stderr, "++++++++++++[M::%s::idx:%ld]\n", __func__, i); + for (;i>=0;) { + // fprintf(stderr, "--[M::%s::i->%ld]\n", __func__, i); + if(((raw_chn->a[i].qs<<1)>>1) < qs) qs = ((raw_chn->a[i].qs<<1)>>1); + if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; + if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; + if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; + // raw_chn->a[i].qs |= mk; + //update here!!!!!!! + if(!(raw_chn->a[i].qs&mk)) b[b_n++] = i; + if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; + else i = raw_chn->a[i].tn; + } + assert(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && + raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te); + + update_exist_chain(uref, raw_chn->a, b, b_n, raw_idx->a[chain_a[k].off].tn, bw, diff_ec_ul, &nn); + nn.v = (raw_idx->a[chain_a[k].off].tn<<1)|raw_idx->a[chain_a[k].off].rev; + extend_end_coord(&nn, NULL, qlen, uref->ug->g->seq[raw_idx->a[chain_a[k].off].tn].len, &iqs, &iqe, &its, &ite); + nn.qs = iqs; nn.qe = iqe; nn.rs = its; nn.re = ite; + assert(chain_a[k].score >= nn.score); + tsc += (chain_a[k].score - nn.score); + } + } + ///TODO: also update qs, qe + tsc = ((int64_t)(ix[z]>>32)) - tsc; if(tsc < 0) tsc = 0; + ix[z] <<= 32; ix[z] >>= 32; ix[z] |= ((uint64_t)tsc)<<32; + + a_n += ((uint32_t)ix[z]); + } + + + + for (k = p_sidx; k < p_eidx; k++) { + i = raw_idx->a[chain_a[k].off].qn; + qs = ((raw_chn->a[i].qs<<1)>>1); qe = raw_chn->a[i].qe; + ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; + for (;i>=0;) { + // fprintf(stderr, "--[M::%s::i->%ld]\n", __func__, i); + if(raw_chn->a[i].qs&mk) raw_chn->a[i].qs -= mk; + if(raw_chn->a[i].qs < qs) qs = raw_chn->a[i].qs; + if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; + if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; + if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; + + + if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; + else i = raw_chn->a[i].tn; + } + assert(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && + raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te); + } +} + +uint32_t gen_max_gchain(void *km, const ul_idx_t *uref, int64_t ulid, st_mt_t *idx, vec_mg_lchain_t *e, kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, +int64_t qlen, float primary_cov_rate, float primary_fragment_cov_rate, float primary_fragment_second_score_rate, const asg_t *g, st_mt_t *dst_done, +vec_sp_node_t *out, vec_mg_pathv_t *res, uint64_t *b, int64_t bw, double diff_ec_ul) +{ + if(idx->n <= 0) return 0; + int64_t a_n, idx_n = idx->n, i, m_sc = 0, is_done = 0; uint64_t s_idx, e_idx, om, ok, ovlp, novlp; + ul_ov_t m; memset(&m, 0, sizeof(m)); m_sc = -1; mg_lchain_t *a = e->a; + for (i = a_n = 0; i < idx_n; ++i) { + if(((int64_t)(idx->a[i]>>32)) > m_sc) { + m_sc = ((int64_t)(idx->a[i]>>32)); m.qn = i; + m.ts = a_n; m.te = a_n + ((uint32_t)idx->a[i]); + m.qs = a[m.ts].qs; m.qe = a[m.te-1].qe; + } + // dedup_second_chain(NULL, 0, a_n, a_n + ((uint32_t)idx->a[i]), a, raw_idx, raw_chn); + a_n += ((uint32_t)idx->a[i]); + } + assert(a[m.ts].qs<=a[m.te-1].qs && a[m.te-1].qe>=a[m.ts].qe); + // print_chain(a + m.ts, m.te - m.ts); + ///for debug + // dedup_second_chain(uref, idx->a, idx_n, m.ts, m.te, a, raw_idx, raw_chn, b, bw, diff_ec_ul); + // debug_ll_chains(uref, idx->a, idx_n, m.ts, m.te, a, raw_idx, raw_chn, b, bw, diff_ec_ul, qlen); + + if((m.qe - m.qs) > (qlen*primary_cov_rate)) is_done = 1; + if(is_done == 0) { + // for (i = a_n = 0; i < idx_n; ++i) { + // s_idx = a[a_n].qs; a_n += ((uint32_t)idx->a[i]); e_idx = a[a_n-1].qe; + // if(i == m.qn) continue; + // if(s_idx < m.qs || e_idx < m.qs || s_idx > m.qe || e_idx > m.qe) break; + // } + // if(i >= idx_n) is_done = 2;///no alignment that is on the left or the right side of the primary chain + for (i = a_n = 0; i < idx_n; ++i) { + s_idx = a[a_n].qs; a_n += ((uint32_t)idx->a[i]); e_idx = a[a_n-1].qe; + if(i == m.qn) continue; + ovlp = ((MIN(m.qe, e_idx) > MAX(m.qs, s_idx))? (MIN(m.qe, e_idx) - MAX(m.qs, s_idx)):0); + novlp = (e_idx - s_idx) - ovlp; + if(novlp > ((m.qe-m.qs)*GC_OFFSET_RATE) && novlp > GC_OFFSET_POS) break; + } + if(i >= idx_n) is_done = 2;///no alignment that is on the left or the right side of the primary chain + } + + if(is_done == 0) { + if((m.qe - m.qs) > (qlen*primary_fragment_cov_rate)) { + dedup_second_chain(uref, idx->a, idx_n, m.ts, m.te, a, raw_idx, raw_chn, b, bw, diff_ec_ul, qlen); + + om = m.qe - m.qs; + for (i = a_n = 0; i < idx_n; ++i) { + s_idx = a[a_n].qs; a_n += ((uint32_t)idx->a[i]); e_idx = a[a_n-1].qe; + if(i == m.qn) continue; + ovlp = ((MIN(m.qe, e_idx) > MAX(m.qs, s_idx))? (MIN(m.qe, e_idx) - MAX(m.qs, s_idx)):0); + if(ovlp == 0) continue; + ok = e_idx - s_idx; + if(ok > om) ok = om; + if((ovlp > ok*0.1) && ((int64_t)(idx->a[i]>>32)) > (m_sc*primary_fragment_second_score_rate)) break; + } + if(i >= idx_n) is_done = 3; + } + } + + if(is_done && gen_gchain_track(km, a + m.ts, m.te - m.ts, g, dst_done, out, res)) {///try to find a path + for (i = m.ts, e->n = 0; i < (int64_t)m.te; i++) a[e->n++] = a[i]; + // fprintf(stderr, "--[M::%s::id->%ld] [%u, %u), res->n:%lu\n", __func__, ulid, m.qs, m.qe, (uint64_t)res->n); + kv_resize(mg_lchain_t, *e, res->n); a = e->a; + for (i = ((int64_t)res->n)-1; i >= 0; i--) { + + if(res->a[i].v == (uint32_t)-1) { + a[i] = a[res->a[i].pre]; a[i].dist_pre = res->a[i].d; + // fprintf(stderr, "ulid:%ld\t%u\t%u\t%c\tutg%.6dl\t%u\t%u\tdist_pre:%d\n", ulid, a[i].qs, a[i].qe, "+-"[a[i].v&1], (int32_t)(a[i].v>>1)+1, a[i].rs, a[i].re, a[i].dist_pre); + } + else { + a[i].v = res->a[i].v; a[i].off = -1; a[i].dist_pre = res->a[i].d; + // fprintf(stderr, "ulid:%ld\t*\t*\t%c\tutg%.6dl\t*\t*\tdist_pre:%d\n", ulid, "+-"[a[i].v&1], (int32_t)(a[i].v>>1)+1, a[i].dist_pre); + } + } + e->n = res->n; + + + + + // debug_gchain(km, g, e->a, e->n, dst_done, out); + + + return 1; + } + + return 0; +} + + +void update_exist_chain_adv(const ul_idx_t *uref, ul_ov_t *ch, uint64_t *idx, int64_t idx_n, int64_t tid, mg_lchain_t *res) +{ + int64_t i, j, cov_i, sc = 0; memset(res, 0, sizeof(*res)); + ul_ov_t *li, *lj; + if(idx_n <= 0) return; + i = 0; + res->qs = (ch[idx[i]].qs<<1)>>1; res->qe = ch[idx[i]].qe; + res->rs = ch[idx[i]].ts; res->re = ch[idx[i]].te; + for (i = 0; i < idx_n; i++) { + li = &(ch[idx[i]]); + + if((int64_t)((li->qs<<1)>>1) < res->qs) res->qs = ((li->qs<<1)>>1); + if((int64_t)li->ts < res->rs) res->rs = li->ts; + if((int64_t)li->qe > res->qe) res->qe = li->qe; + if((int64_t)li->te > res->re) res->re = li->te; + + cov_i = 0; j = i - 1; + if(j >= 0) { + lj = &(ch[idx[j]]); + sc += get_add_cov_score(uref, lj->ts, lj->te, li->ts, li->te, tid, &cov_i); + } else { + sc += retrieve_u_cov_region(uref, tid, 0, li->ts, li->te, &cov_i); + } + } + res->score = (sc>0x3FFFFFFF?0x3FFFFFFF:sc); +} + + +void dedup_second_chain_adv(const ul_idx_t *uref, ul_ov_t *gb, int64_t gb_n, mg_lchain_t *chain_a, +kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, uint64_t *b, int64_t qlen, int64_t ulid) +{ + int64_t k, i, z, ss, ee, b_n, n_s; uint64_t qs, qe, ts, te; uint32_t mk = 0x80000000/**, pi**/; mg_lchain_t nn; + int64_t iqs, iqe, its, ite, tsc; + + for (z = gb_n - 1; z >= 0; z--) {///start from the best chain + ss = gb[z].ts; ee = gb[z].te; tsc = 0; gb[z].qs = qlen; gb[z].qe = 0; + for (k = ss; k < ee; k++) { + i = raw_idx->a[chain_a[k].off].qn; b_n = 0; + qs = ((raw_chn->a[i].qs<<1)>>1); qe = raw_chn->a[i].qe; + ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; + for (n_s = 0;i>=0;) { + if(((raw_chn->a[i].qs<<1)>>1) < qs) qs = ((raw_chn->a[i].qs<<1)>>1); + if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; + if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; + if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; + + if(!(raw_chn->a[i].qs&mk)) b[b_n++] = i; + else n_s++; + + raw_chn->a[i].qs |= mk; + if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; + else i = raw_chn->a[i].tn; + } + assert(b_n > 0); + assert(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && + raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te); + // if(!(raw_idx->a[chain_a[k].off].qs == qs && raw_idx->a[chain_a[k].off].qe == qe && + // raw_idx->a[chain_a[k].off].ts == ts && raw_idx->a[chain_a[k].off].te == te)) { + // fprintf(stderr, "\n[M::%s::ulid->%ld******] raw_idx_offset:%d, qs:%lu, qe:%lu, ts:%lu, te:%lu, raw_idx->qs:%u, raw_idx->qe:%u, raw_idx->ts:%u, raw_idx->te:%u\n", + // __func__, ulid, chain_a[k].off, qs, qe, ts, te, + // raw_idx->a[chain_a[k].off].qs, raw_idx->a[chain_a[k].off].qe, + // raw_idx->a[chain_a[k].off].ts, raw_idx->a[chain_a[k].off].te); + + // for (i = raw_idx->a[chain_a[k].off].qn;i>=0;) { + // if(((raw_chn->a[i].qs<<1)>>1) < qs) qs = ((raw_chn->a[i].qs<<1)>>1); + // if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; + // if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; + // if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; + // fprintf(stderr, "[M::%s->pieces (%ld)] qs->%u, qe->%u, ts->%u, te->%u\n", __func__, i, + // ((raw_chn->a[i].qs<<1)>>1), raw_chn->a[i].qe, raw_chn->a[i].ts, raw_chn->a[i].te); + // if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; + // else i = raw_chn->a[i].tn; + // } + // } + + update_exist_chain_adv(uref, raw_chn->a, b, b_n, raw_idx->a[chain_a[k].off].tn, &nn); + nn.v = (raw_idx->a[chain_a[k].off].tn<<1)|raw_idx->a[chain_a[k].off].rev; + extend_end_coord(&nn, NULL, qlen, uref->ug->g->seq[raw_idx->a[chain_a[k].off].tn].len, &iqs, &iqe, &its, &ite); + nn.qs = iqs; nn.qe = iqe; nn.rs = its; nn.re = ite; + assert(chain_a[k].score >= nn.score); + tsc += (chain_a[k].score - nn.score); + + if(n_s) { + // raw_idx->a[chain_a[k].off].qn = b[b_n-1]; + // for (i = 0, pi = (uint32_t)-1; i < b_n; i++) { + // raw_chn->a[b[i]].tn = pi; pi = b[i]; + // } + ///don't update chain_a[k] as it will be used for taceback in the next step + chain_a[k].score = nn.score; + chain_a[k].qs = nn.qs; chain_a[k].qe = nn.qe; + chain_a[k].rs = nn.rs; chain_a[k].re = nn.re; + // raw_idx->a[chain_a[k].off].sec = nn.score; + // raw_idx->a[chain_a[k].off].qs = nn.qs; + // raw_idx->a[chain_a[k].off].qe = nn.qe; + // raw_idx->a[chain_a[k].off].ts = nn.rs; + // raw_idx->a[chain_a[k].off].te = nn.re; + } else { + // if(!(chain_a[k].score == nn.score && chain_a[k].qs == nn.qs && chain_a[k].qe == nn.qe && chain_a[k].rs == nn.rs && chain_a[k].re == nn.re)) { + // fprintf(stderr, "++++[M::%s::k->%ld] chain_a[k].score->%d, nn.score->%d, chain_a[k].qs->%d, nn.qs->%d, chain_a[k].qe->%d, nn.qe->%d, chain_a[k].rs->%d, nn.rs->%d, chain_a[k].re->%d, nn.re->%d\n", __func__, + // k, chain_a[k].score, nn.score, chain_a[k].qs, nn.qs, chain_a[k].qe, nn.qe, chain_a[k].rs, nn.rs, chain_a[k].re, nn.re); + // } + assert(chain_a[k].score == nn.score && chain_a[k].qs == nn.qs && chain_a[k].qe == nn.qe && chain_a[k].rs == nn.rs && chain_a[k].re == nn.re); + } + + if((int32_t)gb[z].qs > nn.qs) gb[z].qs = nn.qs;///update qs and qe + if((int32_t)gb[z].qe < nn.qe) gb[z].qe = nn.qe; + } + tsc = (int64_t)(gb[z].qn) - tsc; if(tsc < 0) tsc = 0; gb[z].qn = tsc;///update score + // if(gb[z].qe <= gb[z].qs) { + // fprintf(stderr, "++++[M::%s::] gb[%ld].qe->%u, gb[%ld].qs->%u\n", __func__, z, gb[z].qe, z, gb[z].qs); + // } + assert(gb[z].qe > gb[z].qs); + // fprintf(stderr, "[M::%s::z->%ld] score->%u, qs->%u, qe->%u, occ->%u\n", + // __func__, z, gb[z].qn, gb[z].qs, gb[z].qe, gb[z].te-gb[z].ts); + } + + for (i = 0; i < (int64_t)raw_chn->n; i++){ + if(raw_chn->a[i].qs&mk) raw_chn->a[i].qs -= mk; + } + radix_sort_ul_ov_srt_qn(gb, gb + gb_n);//sort by scores +} + +uint32_t gen_max_gchain_adv(void *km, const ul_idx_t *uref, int64_t ulid, st_mt_t *idx, vec_mg_lchain_t *e, kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, +int64_t qlen, float primary_cov_rate, float primary_fragment_cov_rate, float primary_fragment_second_score_rate, uint64_t mini_primary_fragment_len, +const asg_t *g, st_mt_t *dst_done, vec_sp_node_t *out, vec_mg_pathv_t *res, uint64_t *b, vec_mg_lchain_t *gchains) +{ + gchains->n = 0; + if(idx->n <= 0) return 0; + int64_t a_n, idx_n = idx->n, i, k, is_done = 0, n_mchain = 0; uint64_t om, ok, ovlp, novlp; + ul_ov_t *m = NULL, *p = NULL; mg_lchain_t *a = e->a, *g_item; int64_t raw_idx_n = raw_idx->n; + ul_ov_t *gb = NULL; int64_t gb_n = 0; + for (i = a_n = 0; i < idx_n; ++i) { + kv_pushp(ul_ov_t, *raw_idx, &p); + p->qn = ((int64_t)(idx->a[i]>>32));//score + p->ts = a_n; p->te = a_n + ((uint32_t)idx->a[i]); + p->qs = a[p->ts].qs; p->qe = a[p->te-1].qe; p->tn = 0;//(tn = 1) -> normal; (t = 0) -> duplicated chain + a_n += ((uint32_t)idx->a[i]); + // fprintf(stderr, "[M::%s::i->%ld] score->%u, qs->%u, qe->%u, occ->%u\n", __func__, i, p->qn, p->qs, p->qe, p->te-p->ts); + } + gb = raw_idx->a + raw_idx_n; gb_n = raw_idx->n - raw_idx_n; + radix_sort_ul_ov_srt_qn(gb, gb + gb_n);//sort by scores + m = &(gb[gb_n-1]);///max chain + // assert(a[m.ts].qs<=a[m.te-1].qs && a[m.te-1].qe>=a[m.ts].qe); + // print_chain(a + m.ts, m.te - m.ts); + ///for debug + // dedup_second_chain(uref, idx->a, idx_n, m.ts, m.te, a, raw_idx, raw_chn, b, bw, diff_ec_ul); + // debug_ll_chains(uref, idx->a, idx_n, m.ts, m.te, a, raw_idx, raw_chn, b, bw, diff_ec_ul, qlen); + + if((m->qe - m->qs) > (qlen*primary_cov_rate)) { + is_done = 1; m->tn = 1; n_mchain = 1; + } + + if(is_done == 0) { + for (i = gb_n - 2; i >= 0; i--) {///from the second best chain + p = &(gb[i]); + ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); + novlp = (p->qe - p->qs) - ovlp; + if(novlp > ((m->qe-m->qs)*GC_OFFSET_RATE) && novlp > GC_OFFSET_POS) break; + } + if(i < 0) { ///no alignment that is on the left or the right side of the primary chain + is_done = 2; m->tn = 1; n_mchain = 1; + } + } + + if(is_done == 0) { + if(((m->qe - m->qs) > (qlen*primary_fragment_cov_rate)) || ((m->qe - m->qs) > mini_primary_fragment_len)) { + // dedup_second_chain(uref, idx->a, idx_n, m.ts, m.te, a, raw_idx, raw_chn, b, bw, diff_ec_ul, qlen); + if(raw_chn && raw_idx) dedup_second_chain_adv(uref, gb, gb_n, a, raw_idx, raw_chn, b, qlen, ulid); + for (k = gb_n-1, n_mchain = 0; k >= 0; k--) { + m = &(gb[k]);///max chain + // fprintf(stderr, "++[M::%s::k->%ld] score->%u, qs->%u, qe->%u\n", __func__, k, m->qn, m->qs, m->qe); + if(((m->qe - m->qs) <= (qlen*primary_fragment_cov_rate)) && + ((m->qe - m->qs) <= mini_primary_fragment_len)) break; + om = m->qe - m->qs; + for (i = gb_n-1; i >= 0; i--) { + if(i == k) continue; + p = &(gb[i]); + // fprintf(stderr, "--[M::%s::i->%ld] score->%u, qs->%u, qe->%u\n", __func__, i, p->qn, p->qs, p->qe); + ovlp = ((MIN(m->qe, p->qe) > MAX(m->qs, p->qs))? (MIN(m->qe, p->qe) - MAX(m->qs, p->qs)):0); + if(ovlp == 0) continue; + ok = p->qe - p->qs; + if(p->tn == 1 && ((ovlp > ok*0.1) || (ovlp > om*0.1))) break; + if(ok > om) ok = om; + if((ovlp > ok*0.1) && (p->qn > (m->qn*primary_fragment_second_score_rate))) break; + } + if(i < 0) { + is_done = 3; m->tn = 1; n_mchain++; + } else { + break; + } + } + } + } + + if(is_done) { + gchains->n = 0; + for (k = gb_n - n_mchain; k < gb_n; k++) { + kv_pushp(mg_lchain_t, *gchains, &g_item); + g_item->v = (uint32_t)-1; + g_item->qs = gb[k].qs; g_item->qe = gb[k].qe; + g_item->rs = gb[k].ts; g_item->re = gb[k].te; + g_item->cnt = g_item->off = 0; + gen_gchain_track(km, a + g_item->rs, g_item->re - g_item->rs, g, dst_done, out, res); + kv_resize(mg_lchain_t, *gchains, gchains->n + res->n); ///a = gchains->a + gchains->n; + for (i = 0, g_item = &(gchains->a[gchains->n-1]); i < ((int64_t)res->n); i++) { + if(res->a[i].v == (uint32_t)-1) { + gchains->a[i+gchains->n] = a[res->a[i].pre + g_item->rs]; + gchains->a[i+gchains->n].dist_pre = res->a[i].d; + + // fprintf(stderr, "+[M::%s::]\tutg%.6dl(%c)\n", __func__, + // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1]); + } else { + gchains->a[i+gchains->n].v = res->a[i].v; + gchains->a[i+gchains->n].off = -1; + gchains->a[i+gchains->n].dist_pre = res->a[i].d; + ///the nodes detected by the graph chaining should be fully covered + gchains->a[i+gchains->n].rs = 0; + gchains->a[i+gchains->n].re = uref->ug->g->seq[res->a[i].v>>1].len; + // fprintf(stderr, "aaaaaaa, ulid->%ld\n", ulid); + // fprintf(stderr, "-[M::%s::]\tutg%.6dl(%c)\n", __func__, + // (int32_t)(gchains->a[i+gchains->n].v>>1)+1, "+-"[gchains->a[i+gchains->n].v&1]); + } + } + g_item->cnt = res->n; + gchains->n += res->n; + // fprintf(stderr, "sbsbsbsb, ulid->%ld\n", ulid); + // debug_gchain(km, g, gchains->a + gchains->n - res->n, res->n, dst_done, out); + } + } + raw_idx->n = raw_idx_n; + return n_mchain; +} + +int64_t extract_rovlp_by_ug(utg_ct_t *p, mg_lchain_t* o, vec_mg_lchain_t *chains, int64_t tOff) +{ + int64_t rs, re; + rs = MAX((int32_t)p->s, o->rs); re = MIN((int32_t)p->e, o->re); + if(rs > re) return 0; + mg_lchain_t *x = NULL; + kv_pushp(mg_lchain_t, *chains, &x); memset(x, 0, sizeof(*x)); + x->v = (p->x>>1)<<1; x->v += (((o->v&1) == (p->x&1))?0:1); x->rs = rs; x->re = re; x->off = tOff; + x->hash_pre = (uint32_t)-1; x->dist_pre = -1; x->qs = x->qe = -1; + return 1; +} + + + + +void update_existing_anchors(const asg_t *rg, ul_vec_t *rch, ma_ug_t *ug, ma_utg_t *u, vec_mg_lchain_t *res, int64_t res_n0, +mg_lchain_t *uo, kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn) +{ + int64_t z = -1, m = res->n-1, midx, mdif, ovlp, novlp, mbeg, left[2], right[2]; + uint64_t zv; + if(uo->off >= 0) z = raw_idx->a[uo->off].qn;///if there are some base-level alignments + + for (; z >= 0;) { + zv = ((rch->bb.a[raw_chn->a[z].qn].hid<<1)+rch->bb.a[raw_chn->a[z].qn].rev); + if(!(rg->seq[zv>>1].del)) { + for (midx = mdif = -1, mbeg = m; m >= res_n0; m--) { + if(zv==res->a[m].v) { + if(((int32_t)raw_chn->a[z].ts == res->a[m].rs && (int32_t)raw_chn->a[z].te == res->a[m].re)) { + midx = m; mdif = 0; + break; + } else { + ovlp = ((MIN((int32_t)raw_chn->a[z].te, res->a[m].re) > MAX((int32_t)raw_chn->a[z].ts, res->a[m].rs))? + (MIN((int32_t)raw_chn->a[z].te, res->a[m].re) - MAX((int32_t)raw_chn->a[z].ts, res->a[m].rs)):0); + novlp = (raw_chn->a[z].te - raw_chn->a[z].ts - ovlp) + (res->a[m].re - res->a[m].rs - ovlp); + if(midx==-1 || mdif>novlp) { + midx = m; mdif = novlp; + } + } + } + } + if(mdif != 0) { + for (m = res->n-1; m > mbeg; m--) { + if(zv == res->a[m].v) { + if(((int32_t)raw_chn->a[z].ts == res->a[m].rs && (int32_t)raw_chn->a[z].te == res->a[m].re)) { + midx = m; mdif = 0; + break; + } else { + ovlp = ((MIN((int32_t)raw_chn->a[z].te, res->a[m].re) > MAX((int32_t)raw_chn->a[z].ts, res->a[m].rs))? + (MIN((int32_t)raw_chn->a[z].te, res->a[m].re) - MAX((int32_t)raw_chn->a[z].ts, res->a[m].rs)):0); + novlp = (raw_chn->a[z].te - raw_chn->a[z].ts - ovlp) + (res->a[m].re - res->a[m].rs - ovlp); + if(midx==-1 || mdif>novlp) { + midx = m; mdif = novlp; + } + } + } + } + } + m = midx; + // if(m < 0) fprintf(stderr, ">>>>>>[M::%s::] z->%ld\n", __func__, z); + assert(m >= res_n0); + res->a[m].qs = raw_chn->a[z].qs; res->a[m].qe = raw_chn->a[z].qe; + res->a[m].dist_pre = raw_chn->a[z].qn;///the idx of this chain at rch + // fprintf(stderr, "%c, res_n0->%ld, m->%ld, raw_idx->%u, qs->%d, qe->%d, ts->%d, te->%d, mdif->%ld\n", + // "+-"[(uo->v&1)], res_n0, m, raw_chn->a[z].qn, raw_chn->a[z].qs, raw_chn->a[z].qe, raw_chn->a[z].ts, raw_chn->a[z].te, mdif); + + + + left[0] = left[1] = -1; right[0] = right[1] = u->len+1; + if(m > 0) get_r_offset(ug, &(res->a[m-1]), &left[0], &left[1], NULL, NULL); + if(m + 1 < (int64_t)res->n) get_r_offset(ug, &(res->a[m+1]), &right[0], &right[1], NULL, NULL); + + // if(!(uo->v&1)) {///forward + // if(m > 0) { + // left[0] = a[m-1].rs; left[1] = a[m-1].re; + // } + // if(m + 1 < (int64_t)a_n) { + // right[0] = a[m+1].rs; right[1] = a[m+1].re; + // } + // } else {//reverse + // if(m > 0) { + // right[0] = a[m-1].rs; right[1] = a[m-1].re; + // } + // if(m + 1 < (int64_t)a_n) { + // left[0] = a[m+1].rs; left[1] = a[m+1].re; + // } + // } + ///otherwise a[m] is not co-linear with a[m-1] and a[m+1] + if(raw_chn->a[z].ts>=left[0]&&raw_chn->a[z].ts<=right[0] + &&raw_chn->a[z].te>=left[1]&&raw_chn->a[z].te<=right[1]) { + res->a[m].rs = raw_chn->a[z].ts; res->a[m].re = raw_chn->a[z].te; + } + } + if(raw_chn->a[z].tn == (uint32_t)-1) z = -1; + else z = raw_chn->a[z].tn; + } +} + +void gl_ug2rg_gen(const asg_t *rg, ul_vec_t *rch, ma_ug_t *ug, mg_lchain_t *uo, vec_mg_lchain_t *res, int64_t tOff, +int64_t ulid, kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn) +{ + // fprintf(stderr, "\n[M::%s::] uo->qs:%d, uo->qe:%d\n", __func__, uo->qs, uo->qe); + ///uo is a unitig alignment + ma_utg_t *u = &(ug->u.a[uo->v>>1]); int64_t res_n0 = res->n; + uint64_t rs = uo->rs, re = uo->re, i, l; utg_ct_t p; + + for (i = l = 0; i < u->n; i++) { + p.x = u->a[i]>>32; p.s = l; p.e = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); + l += (uint32_t)u->a[i]; + if(p.e <= rs) continue; + if(p.s >= re) break; + + assert(extract_rovlp_by_ug(&p, uo, res, tOff)); + // if(!extract_rovlp_by_ug(&p, uo, res, tOff)) { + // fprintf(stderr, "[M::%s::ulid::%ld]u_rs->%lu, u_re->%lu, p.s->%u, p.e->%u\n", __func__, ulid, rs, re, p.s, p.e); + // exit(1); + // } + res->a[res->n-1].score = uo->v; res->a[res->n-1].cnt = i; + // fprintf(stderr, "[M::%s::]u_rs->%lu, u_re->%lu, p.s->%u, p.e->%u\n", __func__, rs, re, p.s, p.e); + + // int64_t read_rs, read_re, read_qs, read_qe; + // get_r_offset(ug, &(res->a[res->n-1]), &read_rs, &read_re, &read_qs, &read_qe); + // fprintf(stderr, "\t\t\t(k->%u) r_rs->%ld, r_re->%ld, r_qs->%ld, r_qe->%ld\n", (uint32_t)res->n-1, read_rs, read_re, read_qs, read_qe); + ///for res->a[res->n-1] + ///ts and te are the coordinates in unitig (res->a[res->n-1].score>>1), instead of HiFi read (res->a[res->n-1].v>>1) + ///qs and qe are the coordinates in UL, + } + + mg_lchain_t *a = res->a + res_n0, t; uint64_t a_n = res->n - res_n0; + if(uo->v&1) { + for (i = 0; i < (a_n>>1); i++) { + t = a[i]; a[i] = a[a_n-i-1]; a[a_n-i-1] = t; + } + } + + update_existing_anchors(rg, rch, ug, u, res, res_n0, uo, raw_idx, raw_chn); +} + +void update_rovlp_chain_qse_back(ma_ug_t *ug, int64_t sidx, int64_t eidx, mg_lchain_t *a, int64_t a_n) +{ + if(eidx - sidx <= 1) return; + assert(sidx>=0||eidx= 0 + if(sidx >= 0) { + get_r_offset(ug, &(a[sidx]), &left_r[0], &left_r[1], &left_q[0], &left_q[1]); + } else { + get_r_offset(ug, &(a[0]), &left_r[0], &left_r[1], &left_q[0], &left_q[1]); + } + + if(eidx < a_n) { + get_r_offset(ug, &(a[eidx]), &right_r[0], &right_r[1], &right_q[0], &right_q[1]); + } else { + get_r_offset(ug, &(a[a_n-1]), &right_r[0], &right_r[1], &right_q[0], &right_q[1]); + } + assert((left_q[0] >= 0 && left_q[1] >= 0) || (right_q[0] >= 0 && right_q[1] >= 0)); ///assert(re >= rs); + // fprintf(stderr, "##[M::%s::] right_q[0]:%ld, right_q[1]:%ld, left_q[0]:%ld, left_q[1]:%ld\n", + // __func__, right_q[0], right_q[1], left_q[0], left_q[1]); + // fprintf(stderr, "##[M::%s::] right_r[0]:%ld, right_r[1]:%ld, left_r[0]:%ld, left_r[1]:%ld\n", + // __func__, right_r[0], right_r[1], left_r[0], left_r[1]); + // if(left_q[0] >= 0 && left_q[1] >= 0 && right_q[0] >= 0 && right_q[1] >= 0) { + // rlen[0] = (right_r[0] - left_r[0]); rlen[1] = (right_r[1] - left_r[1]); + // qlen[0] = (right_q[0] - left_q[0]); qlen[1] = (right_q[1] - left_q[1]); + // for (i = sidx+1; i < eidx; i++) { + // get_r_offset(ug, &(a[i]), &rs, &re, NULL, NULL); + // a[i].qs = left_q[0] + get_offset_adjust((rs - left_r[0]), rlen[0], qlen[0]); + // a[i].qe = left_q[1] + get_offset_adjust((re - left_r[1]), rlen[1], qlen[1]); + // } + // } + + if(left_q[0] >= 0 && left_q[1] >= 0 && right_q[0] >= 0 && right_q[1] >= 0) { + // fprintf(stderr, "+++sidx:%ld+++ left_qs:%ld, left_qe:%ld, left_rs:%ld, left_re:%ld\n", + // sidx, left_q[0], left_q[1], left_r[0], left_r[1]); + // fprintf(stderr, "---eidx:%ld--- right_qs:%ld, right_qe:%ld, right_rs:%ld, right_re:%ld\n", + // eidx, right_q[0], right_q[1], right_r[0], right_r[1]); + + for (i = sidx+1; i < eidx; i++) { + get_r_offset(ug, &(a[i]), &rs, &re, NULL, NULL); + // a[i].qs = left_q[0] + get_offset_adjust((rs - left_r[0]), rlen[0], qlen[0]); + ///a[i].qs>=left_q[0] && a[i].qs>>i:%ld<<< a[i].qs:%u, a[i].qe:%u, rs:%ld, re:%ld\n", i, a[i].qs, a[i].qe, rs, re); + + left_q[0] = a[i].qs; left_q[1] = a[i].qe; + left_r[0] = rs; left_r[1] = re; + } + } + + if(right_q[0] < 0 || right_q[1] < 0) { + for (i = sidx+1; i < eidx; i++) { + get_r_offset(ug, &(a[i]), &rs, &re, NULL, NULL); + ///a[i].qs>=left_q[0] && a[i].qs=left_q[1] + a[i].qe = left_q[1] + (re - left_r[1]); + left_q[0] = a[i].qs; left_q[1] = a[i].qe; + left_r[0] = rs; left_r[1] = re; + } + } + + if(left_q[0] < 0 || left_q[1] < 0) { + for (i = eidx-1; i > sidx; i--) { + get_r_offset(ug, &(a[i]), &rs, &re, NULL, NULL); + a[i].qe = right_q[1] - get_offset_adjust(right_r[1]-re, right_r[1]-right_r[0], right_q[1]-right_q[0]); + a[i].qs = right_q[0] - (right_r[0]-rs); + right_q[0] = a[i].qs; right_q[1] = a[i].qe; + right_r[0] = rs; right_r[1] = re; + } + } + // if(left_q[0] < 0) left_q[0] = right_q[0] - (right_r[0] - left_r[0]); + // if(left_q[1] < 0) left_q[1] = right_q[1] - (right_r[1] - left_r[1]); + // if(right_q[0] < 0 || right_q[1] < 0) { + // right_q[0] = left_q[0] + (right_r[0] - left_r[0]); + // right_q[1] = left_q[1] + (right_r[1] - left_r[1]); + // } + + // fprintf(stderr, "******[M::%s::] right_q[0]:%ld, right_q[1]:%ld\n", __func__, right_q[0], right_q[1]); +} + +void update_rovlp_chain_qse(ma_ug_t *ug, int64_t sidx, int64_t eidx, mg_lchain_t *a, int64_t a_n, int64_t qlen) +{ + if(eidx - sidx <= 1) return; + assert(sidx>=0||eidx= 0 + if(sidx >= 0) { + get_r_offset(ug, &(a[sidx]), &left_r[0], &left_r[1], &left_q[0], &left_q[1]); + } else { + get_r_offset(ug, &(a[0]), &left_r[0], &left_r[1], &left_q[0], &left_q[1]); + } + + if(eidx < a_n) { + get_r_offset(ug, &(a[eidx]), &right_r[0], &right_r[1], &right_q[0], &right_q[1]); + } else { + get_r_offset(ug, &(a[a_n-1]), &right_r[0], &right_r[1], &right_q[0], &right_q[1]); + } + assert((left_q[0] >= 0 && left_q[1] >= 0) || (right_q[0] >= 0 && right_q[1] >= 0)); ///assert(re >= rs); + + if(left_q[0] >= 0 && left_q[1] >= 0 && right_q[0] >= 0 && right_q[1] >= 0) { + for (i = sidx+1; i < eidx; i++) { + get_r_offset(ug, &(a[i]), &rs, &re, NULL, NULL); + a[i].qe = cal_qext_coor(left_r[1], right_r[1], left_q[1], right_q[1], re); + assert(a[i].qe >= 0 && a[i].qe <= qlen); + a[i].qs = cal_qext_coor(left_r[0], (a[i].qe<=right_q[0])?re:right_r[0], + left_q[0], (a[i].qe<=right_q[0])?a[i].qe:right_q[0], rs); + assert(a[i].qs >= 0 && a[i].qs <= qlen); + if(a[i].qs > a[i].qe) { + tt = a[i].qs; a[i].qs = a[i].qe; a[i].qe = tt; + } + left_q[0] = a[i].qs; left_q[1] = a[i].qe; + left_r[0] = rs; left_r[1] = re; + } + } + + if(right_q[0] < 0 || right_q[1] < 0) { + for (i = sidx+1; i < eidx; i++) { + get_r_offset(ug, &(a[i]), &rs, &re, NULL, NULL); + a[i].qe = cal_qext_coor(left_r[1], re, left_q[1], left_q[1] + re - left_r[1], re); + if(a[i].qe < 0) {a[i].qe = 0;} if(a[i].qe > qlen) {a[i].qe = qlen;} + a[i].qs = cal_qext_coor(left_r[0], (a[i].qe<=left_q[1])?re:left_r[1], + left_q[0], (a[i].qe<=left_q[1])?a[i].qe:left_q[1], rs); + assert(a[i].qs >= 0 && a[i].qs <= qlen); + if(a[i].qs > a[i].qe) { + tt = a[i].qs; a[i].qs = a[i].qe; a[i].qe = tt; + } + + left_q[0] = a[i].qs; left_q[1] = a[i].qe; + left_r[0] = rs; left_r[1] = re; + } + } + + if(left_q[0] < 0 || left_q[1] < 0) { + for (i = eidx-1; i > sidx; i--) { + get_r_offset(ug, &(a[i]), &rs, &re, NULL, NULL); + // a[i].qe = right_q[1] - get_offset_adjust(right_r[1]-re, right_r[1]-right_r[0], right_q[1]-right_q[0]); + // a[i].qs = right_q[0] - (right_r[0]-rs); + a[i].qe = cal_qext_coor(right_r[0], right_r[1], right_q[0], right_q[1], re); + assert(a[i].qe >= 0 && a[i].qe <= qlen); + a[i].qs = cal_qext_coor(rs, right_r[0], right_q[0]-(right_r[0]-rs), right_q[0], rs); + if(a[i].qs < 0) {a[i].qs = 0;} if(a[i].qs > qlen) {a[i].qs = qlen;} + if(a[i].qs > a[i].qe) { + tt = a[i].qs; a[i].qs = a[i].qe; a[i].qe = tt; + } + + right_q[0] = a[i].qs; right_q[1] = a[i].qe; + right_r[0] = rs; right_r[1] = re; + } + } + // if(left_q[0] < 0) left_q[0] = right_q[0] - (right_r[0] - left_r[0]); + // if(left_q[1] < 0) left_q[1] = right_q[1] - (right_r[1] - left_r[1]); + // if(right_q[0] < 0 || right_q[1] < 0) { + // right_q[0] = left_q[0] + (right_r[0] - left_r[0]); + // right_q[1] = left_q[1] + (right_r[1] - left_r[1]); + // } + + // fprintf(stderr, "******[M::%s::] right_q[0]:%ld, right_q[1]:%ld\n", __func__, right_q[0], right_q[1]); +} + +inline int64_t flat_rovlp_chain_sc(ma_ug_t *ug, mg_lchain_t *li, mg_lchain_t *lj) +{ + int64_t iqs, iqe, its, ite, jqs, jqe, jts, jte, ovlp; + get_r_offset(ug, li, &its, &ite, &iqs, &iqe); + get_r_offset(ug, lj, &jts, &jte, &jqs, &jqe); + if(jqs <= iqs && jqe <= iqe && jts <= its && jte <= ite) { + if(jqs == iqs && jqe == iqe && jts == its && jte == ite) return INT32_MIN; + ovlp = ((MIN(jqe, iqe) > MAX(jqs, iqs))? (MIN(jqe, iqe) - MAX(jqs, iqs)):0); + return iqe - iqs - ovlp; + } + return INT32_MIN; +} + +int64_t flat_rovlp_chain(ma_ug_t *ug, mg_lchain_t *x, int64_t x_n, Chain_Data* dp, int64_t max_skip, int64_t max_iter, int64_t max_dis) +{ + if(x_n <= 0) return 0; + int32_t *p, *c_n, *id; int64_t *f, *t, i, j, a_n, st, max_ii, cl; mg_lchain_t *li, *lj; + int64_t mm_sc, mm_n, mm_idx, n_skip, end_j, sc, sn, max, max_n, tot_sc = INT32_MIN, tot_n = INT32_MIN, tot_i = -1; + resize_Chain_Data(dp, x_n, NULL); + t = dp->tmp; p = dp->score; f = dp->pre; c_n = dp->occ; id = dp->indels; + for (i = a_n = 0, cl = 1; i < x_n; i++) { + if(x[i].qs >= 0) { + if(cl && a_n > 0) { + li = &(x[i]); lj = &(x[id[a_n-1]]); + sc = flat_rovlp_chain_sc(ug, li, lj); + if(sc == INT32_MIN) cl = 0; + } + id[a_n++] = i; + } + } + if(a_n <= 0) return 0; + if(cl) return a_n; + + memset(t, 0, (a_n*sizeof((*t)))); + for (i = st = 0, max_ii = -1; i < a_n; ++i) { + li = &(x[id[i]]); + mm_sc = li->qe - li->qs; mm_n = 1; mm_idx = -1; n_skip = 0; end_j = -1; + st = (i= st; --j) { + lj = &(x[id[j]]); + sc = flat_rovlp_chain_sc(ug, li, lj); + if(sc == INT32_MIN) continue; + sc += f[j]; sn = c_n[j] + 1; + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { + mm_sc = sc, mm_idx = j; mm_n = sn; + if (n_skip > 0) --n_skip; + } else if (t[j] == i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + + end_j = j; + if (max_ii < 0 || ((x[id[i]].qe) > (x[id[max_ii]].qe+max_dis))) {//too long + max = INT32_MIN; max_n = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && (x[id[i]].qe<=(max_dis+x[id[j]].qe)); --j) { + if ((max < f[j]) || ((max == f[j]) && (max_n < c_n[j]))) { + max = f[j]; max_n = c_n[j]; max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + lj = &(x[id[max_ii]]); + sc = flat_rovlp_chain_sc(ug, li, lj); + if(sc != INT32_MIN) { + sc += f[max_ii]; sn = c_n[max_ii] + 1; + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_n))) { + mm_sc = sc; mm_idx = max_ii; mm_n = sn; + } + } + } + + f[i] = mm_sc; p[i] = mm_idx; c_n[i] = mm_n; + if ((max_ii < 0) || ((x[id[i]].qe<=max_dis+x[id[max_ii]].qe) && (f[max_ii]= 0) { + id[i] = -1; i = p[i]; cl++; + // t[cl++] = i; i = p[i]; + } + + if(cl < a_n) { + for (i = 0; i < a_n; ++i) { + if(id[i] < 0) continue; + li = &(x[id[i]]); + li->dist_pre = li->qs = li->qe = -1; + } + } + return cl; +} + +void gen_rovlp_chain_by_ul(const asg_t *rg, ul_vec_t *rch, const ul_idx_t *uref, kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, mg_lchain_t *a, int64_t a_n, vec_mg_lchain_t *res, Chain_Data* dp, +int64_t dp_max_skip, int64_t dp_max_iter, int64_t dp_max_dis, int64_t ulid) +{ + if(a_n == 0) return; + int64_t k, l, res_n0 = res->n, tt = 0; ma_ug_t *ug = uref->ug; + // fprintf(stderr, "***[M::%s::a_n->%ld]\n", __func__, a_n); + ///a[0, a_n) is a gchain of untigs + for (k = 0, l = ug->g->seq[a[0].v>>1].len; k < a_n; k++) { + // fprintf(stderr, ">k->%ld, ls->%ld, le->%ld, rev->%c\n", k, l - ug->g->seq[a[k].v>>1].len, l, "+-"[a[k].v&1]); + l -= ug->g->seq[a[k].v>>1].len; + gl_ug2rg_gen(rg, rch, ug, &(a[k]), res, l, ulid, raw_idx, raw_chn); + l += ug->g->seq[a[k].v>>1].len + a[k].dist_pre; + } + mg_lchain_t *x = res->a + res_n0; int64_t x_n = res->n - res_n0, fn; + fn = flat_rovlp_chain(ug, x, x_n, dp, dp_max_skip, dp_max_iter, dp_max_dis); + // fprintf(stderr, "***[M::%s::x_n->%ld] fn::%ld\n", __func__, x_n, fn); + if(fn) { + for (l = -1, k = 0; k <= x_n; k++) { + if(k < x_n) { + if(k > 0) x[k].hash_pre = k-1+res_n0; + else x[k].hash_pre = (uint32_t)-1; + if(x[k].qs >= 0) tt++; + } + if(k == x_n || x[k].qs >=0) { ///x[k] and x[l] are anchors + if(k-l>1) { + update_rovlp_chain_qse(ug, l, k, x, x_n, rch->rlen); + // update_rovlp_chain_qse_back(ug, l, k, x, x_n); + } + l = k; + } + } + assert(tt > 0); + } else { + res->n = res_n0; + } +} + + + +int64_t convert_mg_lchain_t(utg_ct_t *p, mg_lchain_t *o) +{ + int64_t rs = p->s, re = p->e; + rs = MAX(rs, o->rs); re = MIN(re, o->re); + assert(rs < re); + if(!(p->x&1)) { + o->rs = rs-p->s; o->re = re-p->s; + } else { + o->rs = p->e-re; o->re = p->e-rs; + } + return 1; +} + +void renew_mg_lchains(ma_ug_t *ug, mg_lchain_t *a, int64_t a_n, int64_t ulid) +{ + if (a_n <= 0) return; + uint32_t rev = (a[0].score&1); ma_utg_t *u = &(ug->u.a[a[0].score>>1]); + uint64_t i, l; int64_t k; utg_ct_t p; + // fprintf(stderr, "\n[M::%s::ulid->%ld] utg%.6d%c(%c), a_n:%ld, u->n:%u\n", __func__, ulid, + // (int32_t)(a[0].score>>1)+1, "lc"[ug->u.a[(a[0].score>>1)].circ], "+-"[(a[0].score&1)], + // a_n, u->n); + // for (k = 0; k < a_n; k++, i++) { + // fprintf(stderr, "[M::%s::ulid->%ld] utg%.6d%c(%c), k:%ld, a[k].cnt:%d\n", __func__, ulid, + // (int32_t)(a[k].score>>1)+1, "lc"[ug->u.a[(a[k].score>>1)].circ], "+-"[(a[k].score&1)], k, a[k].cnt); + // } + + if(!rev) { + k = 0; + while (k < a_n) { + for (i = l = 0; i < u->n; i++) { + if(i == (uint64_t)a[k].cnt) break; + l += (uint32_t)u->a[i]; + } + assert(i < u->n); + for (; k < a_n; k++, i++) { + ///might have self-circle, so this assertion won't work + // assert(a[k].cnt == (int64_t)i && (a[k].v>>1) == (u->a[i]>>33)); + if(a[k].cnt != (int64_t)i) break; + assert((a[k].v>>1) == (u->a[i]>>33)); + p.x = u->a[i]>>32; p.s = l; p.e = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); + convert_mg_lchain_t(&p, &a[k]); + l += (uint32_t)u->a[i]; + } + } + } else { + k = a_n-1; + while(k >= 0) { + for (i = l = 0; i < u->n; i++) { + if(i == (uint64_t)a[k].cnt) break; + l += (uint32_t)u->a[i]; + } + assert(i < u->n); + for (; k >= 0; k--, i++) { + ///might have self-circle, so this assertion won't work + // assert(a[k].cnt == (int64_t)i && (a[k].v>>1) == (u->a[i]>>33)); + if(a[k].cnt != (int64_t)i) break; + assert((a[k].v>>1) == (u->a[i]>>33)); + p.x = u->a[i]>>32; p.s = l; p.e = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); + convert_mg_lchain_t(&p, &a[k]); + l += (uint32_t)u->a[i]; + } + } + } +} + + +int64_t g_adjacent_dis_mul(const asg_t *g, ma_hit_t_alloc *src, int64_t max_hang, int64_t min_ovlp, uint32_t v, uint32_t w) +{ + uint32_t i; + if(g) { + uint32_t nv; asg_arc_t *av = NULL; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (i = 0; i < nv; i++) { + if(av[i].del || av[i].v != w) continue; + return (uint32_t)av[i].ul; + } + } + + if(src) { + ma_hit_t_alloc *x = &(src[v>>1]); uint32_t qn, tn; + int32_t r; asg_arc_t e; + for (i = 0; i < x->length; i++) { + qn = Get_qn(x->buffer[i]); + tn = Get_tn(x->buffer[i]); + if(qn == (v>>1) && tn == (w>>1)) { + r = ma_hit2arc(&(x->buffer[i]), Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), + max_hang, asm_opt.max_hang_rate, min_ovlp, &e); + if(r < 0) continue; + if((e.ul>>32) != v || e.v != w) continue; + return (uint32_t)e.ul; + } + } + } + + return -1; +} + + +void dd_ul_vec_t(const ul_idx_t *uref, mg_lchain_t *a, int64_t a_n, ul_vec_t *rch, int64_t ulid) +{ + int64_t k, l, ovlp, novlp, tt, rs, re; uint64_t i; uc_block_t *z; mg_lchain_t *p, *c; + for (l = 0, k = 1; k <= a_n; k++) { + if(k == a_n || a[k].score != a[l].score) { ///x[k] and x[l] come from the same unitig + renew_mg_lchains(uref->ug, a + l, k - l, ulid); + l = k; + } + } + + + for (i = 0; i < rch->bb.n; i++) { + rch->bb.a[i].pidx = 0xfffffffe; + rch->bb.a[i].aidx = rch->bb.a[i].pdis = (uint32_t)-1; + } + + for (k = 0; k < a_n; k++) { + if(a[k].dist_pre >= 0) {///not a new alignment + z = &(rch->bb.a[a[k].dist_pre]); + assert(z->hid == (a[k].v>>1) && z->rev == (a[k].v&1)); + if((int64_t)z->qs == a[k].qs && (int64_t)z->qe == a[k].qe && (int64_t)z->ts == a[k].rs && (int64_t)z->te == a[k].re) { + z->pidx = k; z->pchain = 1; + } else { + ovlp = novlp = tt = 0; + ovlp = ((MIN((int64_t)z->qe, a[k].qe) > MAX((int64_t)z->qs, a[k].qs))? (MIN((int64_t)z->qe, a[k].qe)-MAX((int64_t)z->qs, a[k].qs)):0); + tt += ovlp; + novlp += (a[k].qe - a[k].qs - ovlp) + (z->qe - z->qs - ovlp); + + ovlp = ((MIN((int64_t)z->te, a[k].re) > MAX((int64_t)z->ts, a[k].rs))? (MIN((int64_t)z->te, a[k].re)-MAX((int64_t)z->ts, a[k].rs)):0); + tt += ovlp; + novlp += (a[k].re - a[k].rs - ovlp) + (z->te - z->ts - ovlp); + if(novlp > 8 || novlp > (tt*0.01)) { + kv_pushp(uc_block_t, rch->bb, &z); + z->hid = (a[k].v>>1); z->rev = (a[k].v&1); + z->pchain = 2; z->base = 0; z->el = 1; + z->qs = a[k].qs; z->qe = a[k].qe; + z->te = a[k].re; z->ts = a[k].rs; + z->pidx = k; + z->aidx = z->pdis = (uint32_t)-1; + } else { + z->qs = a[k].qs; z->qe = a[k].qe; + z->te = a[k].re; z->ts = a[k].rs; + z->pidx = k; z->pchain = 1; + } + } + } else { + kv_pushp(uc_block_t, rch->bb, &z); + z->hid = (a[k].v>>1); z->rev = (a[k].v&1); + z->pchain = 2; z->base = 0; z->el = 1; + z->qs = a[k].qs; z->qe = a[k].qe; + z->te = a[k].re; z->ts = a[k].rs; + z->pidx = k; + z->aidx = z->pdis = (uint32_t)-1; + } + } + + for (i = k = 0; i < rch->bb.n; i++) { + if(rch->bb.a[i].pidx == 0xfffffffe && (rch->bb.a[i].pchain != 1 || rch->bb.a[i].pchain != 0)) continue; + rch->bb.a[k++] = rch->bb.a[i]; + } + rch->bb.n = k; + + radix_sort_uc_block_t_qe_srt(rch->bb.a, rch->bb.a + rch->bb.n); + for (l = 0, k = 1; k <= (int64_t)rch->bb.n; k++) { + if(k == (int64_t)rch->bb.n || rch->bb.a[k].qe != rch->bb.a[l].qe) { + if(k - l > 1) radix_sort_uc_block_t_qs_srt(rch->bb.a+l, rch->bb.a+k); + for (; l < k; l++) { + if(rch->bb.a[l].pidx == 0xfffffffe) { + rch->bb.a[l].pidx = (uint32_t)-1; + } else { + a[rch->bb.a[l].pidx].dist_pre = l; + } + } + } + } + + // for (i = 0; i < rch->bb.n; i++) { + // if(rch->bb.a[i].pidx == 0xfffffffe) { + // rch->bb.a[i].pidx = (uint32_t)-1; + // } else { + // a[rch->bb.a[i].pidx].dist_pre = i; + // } + // } + // fprintf(stderr, "\n[M::%s::]\n", __func__); + for (i = 0, k = -1; i < rch->bb.n; i++) { + if(rch->bb.a[i].pidx == (uint32_t)-1) continue; + if(k < 0) k = i;///in case there is only one UL-to-HiFi alignment + if(a[rch->bb.a[i].pidx].hash_pre == (uint32_t)-1) { + rch->bb.a[i].pidx = (uint32_t)-1; + continue; + } + c = &(a[rch->bb.a[i].pidx]); p = &(a[a[rch->bb.a[i].pidx].hash_pre]); + rch->bb.a[i].pidx = a[a[rch->bb.a[i].pidx].hash_pre].dist_pre; + rch->bb.a[rch->bb.a[i].pidx].aidx = i; + tt = g_adjacent_dis_mul(uref->r_ug->rg, NULL, -1, -1, + ((rch->bb.a[i].hid<<1)|((uint32_t)rch->bb.a[i].rev))^1, + ((rch->bb.a[rch->bb.a[i].pidx].hid<<1)|((uint32_t)rch->bb.a[rch->bb.a[i].pidx].rev))^1); + if(tt >= 0) { + rch->bb.a[i].pdis = tt; + // get_r_offset(uref->ug, p, NULL, &rs, NULL, NULL); + // get_r_offset(uref->ug, c, NULL, &re, NULL, NULL); + // fprintf(stderr, "+i->%lu: dis->%u, record_dis->%ld\n", i, rch->bb.a[i].pdis, re-rs); + } else { + rs = p->off + uref->ug->g->seq[p->score>>1].len; + re = c->off + uref->ug->g->seq[c->score>>1].len; + if(re >= rs) rch->bb.a[i].pdis = re - rs; + else rch->bb.a[i].pdis = (uint32_t)-1; + // fprintf(stderr, "-i->%lu: dis->%u\n", i, rch->bb.a[i].pdis); + } + + k = i; + // if(rch->bb.a[i].base || rch->bb.a[i].pchain == 0 || rch->bb.a[i].el == 0) { + // fprintf(stderr, "+++(%lu) base:%u, pchain:%u, el:%u\n", + // i, rch->bb.a[i].base, rch->bb.a[i].pchain, rch->bb.a[i].el); + // } + } + + ///make sure if this UL read has been done + uint32_t sp = (uint32_t)-1, ep = (uint32_t)-1; + for (l = 0 ; k >= 0; ) { + // fprintf(stderr, "k->%ld\n", k); + if(sp == (uint32_t)-1 || rch->bb.a[k].qe <= sp) { + if(sp != (uint32_t)-1) l += ep - sp; + sp = rch->bb.a[k].qs; ep = rch->bb.a[k].qe; + } else { + sp = MIN(sp, rch->bb.a[k].qs); + } + if(rch->bb.a[k].pidx == (uint32_t)-1) k = -1; + else k = rch->bb.a[k].pidx; + } + + if(sp != (uint32_t)-1) l += ep - sp; + if(l == (int64_t)rch->rlen) rch->dd = 1; + + + ///debug_ssb + // for (k = 0; (uint32_t)k < rch->bb.n; k++) { + // if(rch->bb.a[k].pidx != (uint32_t)-1) { + // if((rch->bb.a[k].pidx >= 0) && (rch->bb.a[k].pidx < rch->bb.n) && + // (rch->bb.a[rch->bb.a[k].pidx].aidx == k)) { + // ; + // } else { + // fprintf(stderr, "[M::%s::k->%ld] +rch->bb.n::%u\n", __func__, k, (uint32_t)rch->bb.n); + // for (l = 0; (uint32_t)l < rch->bb.n; l++) { + // fprintf(stderr, "[M::%.*s::k->%lu] q::[%u, %u), t::[%u, %u), pidx::%u, aidx::%u\n", + // (int)Get_NAME_LENGTH(R_INF, rch->bb.a[l].hid), Get_NAME(R_INF, rch->bb.a[l].hid), l, + // rch->bb.a[l].qs, rch->bb.a[l].qe, rch->bb.a[l].ts, rch->bb.a[l].te, + // rch->bb.a[l].pidx, rch->bb.a[l].aidx); + // } + // exit(1); + // } + // } + + // if(rch->bb.a[k].aidx != (uint32_t)-1) { + // if((rch->bb.a[k].aidx >= 0) && (rch->bb.a[k].aidx < rch->bb.n) && + // (rch->bb.a[rch->bb.a[k].aidx].pidx == k)) { + // ; + // } else { + // fprintf(stderr, "[M::%s::k->%ld] -rch->bb.n::%u\n", __func__, k, (uint32_t)rch->bb.n); + // for (l = 0; (uint32_t)l < rch->bb.n; l++) { + // fprintf(stderr, "[M::%.*s::k->%lu] q::[%u, %u), t::[%u, %u), pidx::%u, aidx::%u\n", + // (int)Get_NAME_LENGTH(R_INF, rch->bb.a[l].hid), Get_NAME(R_INF, rch->bb.a[l].hid), l, + // rch->bb.a[l].qs, rch->bb.a[l].qe, rch->bb.a[l].ts, rch->bb.a[l].te, + // rch->bb.a[l].pidx, rch->bb.a[l].aidx); + // } + // exit(1); + // } + // } + // } + + // if(ulid == 292) { + // for (i = 0; i < rch->bb.n; i++) { + // fprintf(stderr, "(%lu) qs:%u, qe:%u, ts:%u, te:%u, pidx:%u\n", i, + // rch->bb.a[i].qs, rch->bb.a[i].qe, rch->bb.a[i].ts, rch->bb.a[i].te, rch->bb.a[i].pidx); + // } + // } + + // for (i = 0; i < rch->bb.n; i++) { + // if(rch->bb.a[i].pidx == (uint32_t)-1) continue; + // if(rch->bb.a[i].base || rch->bb.a[i].pchain == 0 || rch->bb.a[i].el == 0) { + // fprintf(stderr, "(%lu) base:%u, pchain:%u, el:%u\n", + // i, rch->bb.a[i].base, rch->bb.a[i].pchain, rch->bb.a[i].el); + // } + // assert((!(rch->bb.a[i].base)) && (rch->bb.a[i].pchain) && (rch->bb.a[i].el)); + // assert((!(rch->bb.a[rch->bb.a[i].pidx].base)) && (rch->bb.a[rch->bb.a[i].pidx].pchain) + // && (rch->bb.a[rch->bb.a[i].pidx].el)); + // } + // int64_t exact = 0, inexact = 0; uc_block_t *z; + // for (k = 0; k < a_n; k++) { + // // fprintf(stderr, "(%ld) a->qs:%d, a->qe:%d, a->rs:%d, a->re:%d\n", k, a[k].qs, a[k].qe, a[k].rs, a[k].re); + // if(a[k].dist_pre < 0) continue; + // z = &(rch->bb.a[a[k].dist_pre]); + // assert(z->hid == (a[k].v>>1) && z->rev == (a[k].v&1)); + // if((int64_t)z->qs == a[k].qs && (int64_t)z->qe == a[k].qe && (int64_t)z->ts == a[k].rs && (int64_t)z->te == a[k].re) { + // exact++; + // } else { + // inexact++; + // // fprintf(stderr, "+z->qs:%u, z->qe:%u, z->ts:%u, z->te:%u\n", z->qs, z->qe, z->ts, z->te); + // // fprintf(stderr, "-a->qs:%d, a->qe:%d, a->rs:%d, a->re:%d\n\n", a[k].qs, a[k].qe, a[k].rs, a[k].re); + // } + // } + // fprintf(stderr, "[M::%s::exact->%ld, inexact->%ld]\n", __func__, exact, inexact); +} + +void print_debug_gchain(const ul_idx_t *uref, mg_lchain_t *a, int64_t a_n, ul_vec_t *rch) +{ + int64_t k; + fprintf(stderr, "\n[M::%s] a_n->%ld\n", __func__, a_n); + for (k = 0; k < a_n; k++) { + fprintf(stderr, "[M::%s::k->%ld] utg%.6d%c(%c), qs->%d, qe->%d, rs->%u, re->%u, qlen->%u\n", __func__, k, + (int32_t)(a[k].v>>1)+1, "lc"[uref->ug->u.a[(a[k].v>>1)].circ], "+-"[(a[k].v&1)], + a[k].off<0?-1:a[k].qs, a[k].off<0?-1:a[k].qe, a[k].rs, a[k].re, rch->rlen); + } + +} + +void update_ul_vec_t(const ul_idx_t *uref, kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, ul_vec_t *rch, +vec_mg_lchain_t *uc, vec_mg_lchain_t *swap, int64_t ulid, const asg_t *rg, Chain_Data* dp, +int64_t dp_max_skip, int64_t dp_max_iter, int64_t dp_max_dis) +{ + // fprintf(stderr, "\n++[M::%s::%.*s(id:%ld), len:%u]\n", __func__, + // UL_INF.nid.a[ulid].n, UL_INF.nid.a[ulid].a, ulid, rch->rlen); + + int64_t k, ucn = uc->n; mg_lchain_t *ix; + for (k = 0, swap->n = 0; k < ucn; k += ix->cnt + 1) { + ix = &(uc->a[k]); assert(ix->v == (uint32_t)-1); + // if(ulid == 14714) { + // fprintf(stderr, "\n[M::%s::ucn->%ld, k->%ld, kcnt->%d]\n", __func__, ucn, k, ix->cnt); + // print_debug_gchain(uref, uc->a + k + 1, ix->cnt, rch); + // } + gen_rovlp_chain_by_ul(rg, rch, uref, raw_idx, raw_chn, uc->a + k + 1, ix->cnt, swap, dp, + dp_max_skip, dp_max_iter, dp_max_dis, ulid); + } + + ///up to now, given a in swap + ///x->ts and x->te are the coordinates in unitig (x->score>>1), instead of HiFi read (x->v>>1) + ///x->qs and x->qe are the coordinates in UL + ///x->dist_pre is the idx of this chain at rch + // debug_intermediate_chain(uref->ug, swap->a, swap->n); + dd_ul_vec_t(uref, swap->a, swap->n, rch, ulid); +} + + +void push_ctg_res(ul_vec_t *rch, vec_mg_lchain_t *uc, uint64_t id) +{ + // fprintf(stderr, "\n++[M::%s::%.*s(id:%ld), len:%u]\n", __func__, + // UL_INF.nid.a[ulid].n, UL_INF.nid.a[ulid].a, ulid, rch->rlen); + + uint64_t k, ucn = uc->n; uint64_t tt, s, e, z, rrn; mg_lchain_t *ix; uc_block_t *p; uc_block_t *rr; mg_lchain_t *src; + for (k = 0, rch->bb.n = 0, tt = 0; k < ucn; k += ix->cnt + 1) { + ix = &(uc->a[k]); assert(ix->v == (uint32_t)-1); + kv_pushp(uc_block_t, rch->bb, &p); memset(p, 0, sizeof((*p))); + p->hid = k/**(uint32_t)-1**/; p->qs = ix->qs; p->qe = ix->qe; p->ts = ix->cnt; tt += ix->cnt; + + // if(id == 206) { + // fprintf(stderr, "init->[M::%s::ucn->%lu, k->%lu, kcnt->%d]\n", __func__, ucn, k, ix->cnt); + // } + } + radix_sort_uc_block_t_qe_srt(rch->bb.a, rch->bb.a + rch->bb.n); + + kv_resize(uc_block_t, rch->bb, rch->bb.n + tt); + memset(rch->bb.a + rch->bb.n, 0, tt * sizeof(*(rch->bb.a))); + for (k = 0, tt = rch->bb.n; k < rch->bb.n; k++) { + s = tt; e = tt + rch->bb.a[k].ts; + rch->bb.a[k].ts = s; rch->bb.a[k].te = e; + tt = e; + // if(id == 206) { + // fprintf(stderr, "mid->[M::%s::rch->bb.n->%u, k->%lu] [%lu, %lu)\n", + // __func__, (uint32_t)rch->bb.n, k, s, e); + // } + + ix = &(uc->a[rch->bb.a[k].hid]); assert(ix->v == (uint32_t)-1); + rr = rch->bb.a + rch->bb.a[k].ts; rrn = rch->bb.a[k].te - rch->bb.a[k].ts; + src = uc->a + rch->bb.a[k].hid + 1; assert((uint32_t)ix->cnt == rrn); + for(z = 0; z < rrn; z++) { + rr[z].hid = src[z].v>>1; + rr[z].rev = src[z].v&1; + rr[z].qs = src[z].qs; rr[z].qe = src[z].qe; + rr[z].ts = src[z].rs; rr[z].te = src[z].re; + rr[z].aidx = rch->bb.a[k].hid; + } + rch->bb.a[k].hid = (uint32_t)-1; + + } + assert(tt <= rch->bb.m); + + // for (k = 0, tt = 0; k < ucn; k += ix->cnt + 1, tt++) { + // ix = &(uc->a[k]); assert(ix->v == (uint32_t)-1); + // rr = rch->bb.a + rch->bb.a[tt].ts; rrn = rch->bb.a[tt].te - rch->bb.a[tt].ts; + // src = uc->a + k + 1; + // if(!((uint32_t)ix->cnt == rrn)) { + // fprintf(stderr, "\n++[M::%s::(id::%lu)] ix->cnt::%d, rrn::%lu\n", __func__, id, ix->cnt, rrn); + // } + // assert((uint32_t)ix->cnt == rrn); + // for(z = 0; z < rrn; z++) { + // rr[z].hid = src[z].v>>1; + // rr[z].rev = src[z].v&1; + // rr[z].qs = src[z].qs; rr[z].qe = src[z].qe; + // rr[z].ts = src[z].rs; rr[z].te = src[z].re; + // rr[z].aidx = k; + // } + // } + ///up to now, given a in swap + ///x->ts and x->te are the coordinates in unitig (x->score>>1), instead of HiFi read (x->v>>1) + ///x->qs and x->qe are the coordinates in UL + ///x->dist_pre is the idx of this chain at rch + // debug_intermediate_chain(uref->ug, swap->a, swap->n); + // dd_ul_vec_t(uref, swap->a, swap->n, rch, ulid); +} + +void print_ru_raw_chains(kv_ul_ov_t *raw_idx, kv_ul_ov_t *raw_chn, vec_mg_lchain_t *gch, ul_vec_t *rch, ma_ug_t *ug) +{ + int64_t k, i; uint64_t ts, te, qs, qe; + for (k = 0; k < (int64_t)gch->n; k++) { + i = raw_idx->a[gch->a[k].off].qn; + qs = ((raw_chn->a[i].qs<<1)>>1); qe = raw_chn->a[i].qe; + fprintf(stderr, "\n[M::%s->overall chain (%ld)] utg%.6d%c(%c), qs->%u, qe->%u, qlen->%u, ts->%u, te->%u, tlen->%u\n", __func__, k, + (int32_t)(gch->a[k].v>>1)+1, "lc"[ug->u.a[(gch->a[k].v>>1)].circ], "+-"[(gch->a[k].v&1)], + raw_idx->a[gch->a[k].off].qs, raw_idx->a[gch->a[k].off].qe, rch->rlen, + raw_idx->a[gch->a[k].off].ts, raw_idx->a[gch->a[k].off].te, ug->u.a[(gch->a[k].v>>1)].len); + ts = raw_chn->a[i].ts; te = raw_chn->a[i].te; + for (;i>=0;) { + if(((raw_chn->a[i].qs<<1)>>1) < qs) qs = ((raw_chn->a[i].qs<<1)>>1); + if(raw_chn->a[i].ts < ts) ts = raw_chn->a[i].ts; + if(raw_chn->a[i].qe > qe) qe = raw_chn->a[i].qe; + if(raw_chn->a[i].te > te) te = raw_chn->a[i].te; + + fprintf(stderr, "[M::%s->chain pieces (%ld)] qs->%u, qe->%u, ts->%u, te->%u\n", __func__, i, + ((raw_chn->a[i].qs<<1)>>1), raw_chn->a[i].qe, raw_chn->a[i].ts, raw_chn->a[i].te); + + if(raw_chn->a[i].tn == (uint32_t)-1) i = -1; + else i = raw_chn->a[i].tn; + } + + } + +} + +///sps and hap are just vector for uint64_t; used for buffer +uint32_t direct_gchain(mg_tbuf_t *b, ul_vec_t *rch, glchain_t *ll, gdpchain_t *gdp, st_mt_t *sps, haplotype_evdience_alloc *hap, const ul_idx_t *uref, const ug_opt_t *uopt, +int64_t bw, double diff_ec_ul, int64_t max_skip, int64_t ulid, Chain_Data* dp, const asg_t *rg, int64_t linear_only) +{ + // if(ulid != 86660) return 0; + kv_ul_ov_t *idx = &(ll->lo), *init = &(ll->tk); int64_t max_idx; + idx->n = init->n = 0; + gl_rg2ug_gen(rch, idx, uref, 1, 2, ulid); + if(idx->n == 0) return 0; + ///generate linear chains + gen_linear_chains(idx, init, uref, uopt, bw, diff_ec_ul, rch->rlen, dp); + // gen_linear_chains_backup(idx, init, uref, uopt, bw, diff_ec_ul, rch->rlen, max_skip, ll, sps); +// gen_linear_chains_backup(kv_ul_ov_t *res, kv_ul_ov_t *buf, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +// double diff_ec_ul, int64_t qlen, int64_t max_skip, glchain_t *bufg, st_mt_t *bufs) + assert(idx->n); + if(idx->n == 0) return 0; + ///idx includes unitig alignments, while init keeps read alignments + // fprintf(stderr, "\n++[M::%s::%.*s(id:%ld), len:%u] idx->n:%lu\n", __func__, UL_INF.nid.a[ulid].n, UL_INF.nid.a[ulid].a, + // ulid, rch->rlen, (uint64_t)idx->n); + + dump_linear_chain(uref->ug, idx, &(gdp->l), rch->rlen, ulid); + if(gdp->l.n == 0) return 0; + // fprintf(stderr, "\n+++[M::%s::id->%ld, len->%u] idx->n:%lu\n", __func__, ulid, rch->rlen, (uint64_t)idx->n); + // kv_resize(uint64_t, ll->srt.a, idx->n); kv_resize(uint64_t, hap->snp_srt, idx->n); kv_resize(uint64_t, gdp->v, idx->n); + // occ = gl_chain_advance(&(gdp->l), &(gdp->swap), uref, uopt, G_CHAIN_BW, diff_ec_ul, qlen, UG_SKIP, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 0, NULL, uref->ug, debug_i, km); + // print_ru_raw_chains(idx, init, &(gdp->l), rch, uref->ug); + + kv_resize(uint64_t, ll->srt.a, gdp->l.n); + max_idx = gl_chain_graph(b->km, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), + &(gdp->path), rch->rlen, uopt, G_CHAIN_BW, linear_only?-1:diff_ec_ul, N_GCHAIN_RATE, ll->srt.a.a, sps, dp, UG_SKIP_GRAPH_N, UG_ITER_N, UG_DIS_N, 1); + //sps -> idx; (gdp->l) -> alignments + if(max_idx >= 0) { + max_idx = select_max_gchain(b->km, uref, ulid, sps, &(gdp->l), &(ll->tk), uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), &(gdp->swap)); + if(max_idx) { + if((!linear_only) || ((linear_only) && (gdp->swap.a[0].qe-gdp->swap.a[0].qs) + >= (rch->rlen*P_CHAIN_COV))) { + update_ul_vec_t(uref, idx, init, rch, &(gdp->swap), &(gdp->l), ulid, rg, dp, UG_SKIP_GRAPH_N, UG_ITER_N, UG_DIS_N); + } + return (rch->dd == 1?1:0); + } + } + // if(max_idx >= 0 && select_max_gchain(b->km, uref, ulid, sps, &(gdp->l), &(ll->tk), uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), &(gdp->swap))){ + // update_ul_vec_t(uref, idx, init, rch, &(gdp->swap), &(gdp->l), ulid, rg, dp, UG_SKIP_GRAPH_N, UG_ITER_N, UG_DIS_N); + // return (rch->dd == 1?1:0); + // } + + /** + ///buffer + kv_resize(uint64_t, ll->srt.a, gdp->l.n); kv_resize(uint64_t, hap->snp_srt, gdp->l.n); + kv_resize(uint64_t, gdp->v, gdp->l.n); kv_resize(int64_t, gdp->f, gdp->l.n); + max_idx = hc_gchain1_dp(b->km, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), &(gdp->path), rch->rlen, + uopt, bw, diff_ec_ul, N_GCHAIN_RATE, ll->srt.a.a, sps, gdp->f.a, hap->snp_srt.a, gdp->v.a); + // fprintf(stderr, "++++[M::%s::id->%ld, len->%u] gdp->l.n:%lu\n", __func__, ulid, rch->rlen, (uint64_t)gdp->l.n); + // fprintf(stderr, "+[M::%s::] gdp->l.n:%lu\n", __func__, (uint64_t)gdp->l.n); + //sps has the chain idx; gdp->l has the chain + if(max_idx >= 0 && gen_max_gchain_adv(b->km, uref, ulid, sps, &(gdp->l), idx, init, rch->rlen, P_CHAIN_COV, 0.3, + 0.1, PRIMARY_UL_CHAIN_MIN, uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), ll->srt.a.a, &(gdp->swap))) { + // update_ul_vec_t(rch, &(gdp->l), uref); + // fprintf(stderr, "\n++[M::%s::(id:%ld), len:%u]\n", __func__, ulid, rch->rlen); + update_ul_vec_t(uref, idx, init, rch, &(gdp->swap), &(gdp->l), ulid); + // __ac_X31_hash_string("hehe"); + // if(rch->dd == 1) { + // fprintf(stderr, "[M::%s::%.*s(id:%ld)] ulen->%u\n", __func__, UL_INF.nid.a[ulid].n, UL_INF.nid.a[ulid].a, ulid, rch->rlen); + // } + return (rch->dd == 1?1:0); + // } else { + // // uint64_t i; + // fprintf(stderr, "unsuccess->[M::%s::id->%ld, len->%u] gdp->l.n:%lu\n", __func__, ulid, rch->rlen, (uint64_t)gdp->l.n); + // for (i = 0; i < gdp->l.n; ++i) { + // fprintf(stderr, "(%lu)\t%u\t%u\t%c\tutg%.6d%c(%u)\t%u\t%u\tsrc:%u\tscore:%d\n", + // i, gdp->l.a[i].qs, gdp->l.a[i].qe, "+-"[gdp->l.a[i].v&1], (int32_t)(gdp->l.a[i].v>>1)+1, "lc"[uref->ug->u.a[gdp->l.a[i].v>>1].circ], uref->ug->u.a[gdp->l.a[i].v>>1].len, + // gdp->l.a[i].rs, gdp->l.a[i].re, gdp->l.a[i].v^1, gdp->l.a[i].score); + // } + } + **/ + + + + // occ = gl_chain_advance(idx, ll->tk.a+ll->tk.n, uref, uopt, G_CHAIN_BW, diff_ec_ul, qlen, UG_SKIP, dumy->overlapID, ll->srt.a.a, hap->snp_srt.a, G_CHAIN_TRANS_WEIGHT, 0, NULL, uref->ug, debug_i, km); + + // simple_g_chain_dp(idx, buf->a, uref, uopt, bw, diff_ec_ul, rch->rlen, max_skip, ll->srt.a.a, hap->snp_srt.a, sps->a); + // if(check_extension_end(idx, rch->rlen, buf->a)) { + // // ug2rg_gen(idx->a[idx->n-1].qs, idx->a[idx->n-1].qe, buf->a + idx->a[idx->n-1].ts, idx->a[idx->n-1].te - idx->a[idx->n-1].ts, rch); + // } else {///need graph chaining + + // } + + return 0; +} + + + +uint64_t rov2uov_ctg(uint64_t rid, const ul_idx_t *uref, utg_rid_dt *ru_map, uc_block_t *rovlp, ul_ov_t *res, uint32_t qidx, uint32_t adjust_rev) +{ + uint64_t ori = ru_map->u&1, ts, te; + if(!ori) { + ts = rovlp->ts; te = rovlp->te; + } else { + ts = Get_READ_LENGTH(R_INF, rid) - rovlp->te; + te = Get_READ_LENGTH(R_INF, rid) - rovlp->ts; + } + + ts += ru_map->pos; te += ru_map->pos; + if(ts >= 0 && te <= uref->ug->g->seq[ru_map->u>>1].len) { + memset(res, 0, sizeof(*res)); + res->qn = qidx; res->qs = rovlp->qs; res->qe = rovlp->qe; + res->tn = ru_map->u>>1; res->ts = ts; res->te = te; + res->el = rovlp->el; res->rev = (rovlp->rev == ori?0:1); res->sec = ru_map->off; + if(adjust_rev && res->rev) {///for linear chaining + res->ts = uref->ug->g->seq[ru_map->u>>1].len - te; + res->te = uref->ug->g->seq[ru_map->u>>1].len - ts; + res->sec = uref->ug->u.a[ru_map->u>>1].n - ru_map->off; + } + return 1; + } + return 0; +} + + +uint64_t get_unique_rctg_aln(const ul_idx_t *uref, uint64_t v, uint64_t vi, uint64_t vs, uint64_t ulen, ul_ov_t *ures, kv_ul_ov_t *rr, uint32_t sec) +{ + utg_rid_dt *a = NULL; uint64_t a_n, k, rrn = 0, over_bd = 0; uc_block_t z; ul_ov_t p; + p.tn = p.qn = ((uint32_t)-1); if(ures) ures->tn = ures->qn = ((uint32_t)-1); + if(IS_SCAF_READ(R_INF, (v>>1))) return 0;///actually no scaf nodes within the assembly graph + a = get_r_ug_region(uref->r_ug, &a_n, v>>1); + if(!a) return 0; + + z.qs = vs; z.qe = vs + Get_READ_LENGTH(R_INF, (v>>1)); + if(z.qs > ulen) { + z.qs = ulen; + over_bd = 1; + } + + if(z.qe > ulen) { + z.qe = ulen; + over_bd = 1; + } + + z.hid = v>>1; z.rev = v&1; z.el = 1; + z.ts = 0; z.te = Get_READ_LENGTH(R_INF, (v>>1)); + if(over_bd) {//////need to handle it especially for circles + over_bd = z.qe - z.qs; + if(over_bd > Get_READ_LENGTH(R_INF, (v>>1))) { + over_bd = Get_READ_LENGTH(R_INF, (v>>1)); + } + if(!(z.rev)) { + z.ts = 0; z.te = over_bd; + } else { + z.ts = Get_READ_LENGTH(R_INF, (v>>1))-over_bd; z.te = Get_READ_LENGTH(R_INF, (v>>1)); + } + } + if(z.qe <= z.qs || z.te <= z.ts) return 0; + + + for (k = rrn = 0; k < a_n; k++) { + if(!rov2uov_ctg(v>>1, uref, &(a[k]), &z, &p, vi, 1)) continue; + p.el = 1; p.tn <<= 1; p.tn |= p.rev; ///p.qn: offset within q; p.sec: offset within t; p.tn: tid + if(sec != ((uint32_t)-1)) p.sec = sec; + if(rr) kv_push(ul_ov_t, *rr, p); + rrn++; + } + + if((ures) && (rrn == 1)) *ures = p; + return rrn; +} + +uint64_t cmp_shrink_ul_ov_t(ul_ov_t *a0, ul_ov_t *a1, uint64_t off) +{ + if((a0->tn == ((uint32_t)-1)) || (a1->tn == ((uint32_t)-1))) return 1; + if((a0->tn == a1->tn) && (a0->qn + off == a1->qn) && (a0->sec + off == a1->sec)) return 0; + return 1; +} + +void ctg_rg2ug_gen(ma_utg_t *r_cl, kv_ul_ov_t *u_cl, const ul_idx_t *uref, uint64_t id) +{ + if(r_cl->n <= 0) return ; + uint64_t k, i, m, l, is_push, vs, ls; ul_ov_t kp, lp, kp0; + u_cl->n = 0; kp.tn = kp.qn = kp0.tn = kp0.qn = ((uint32_t)-1); + + k = 1; l = 0; ls = 0; vs = 0; + get_unique_rctg_aln(uref, r_cl->a[l]>>32, l, ls, r_cl->len, &lp, NULL, ((uint32_t)-1)); ///get lp for l = 0 + vs += (uint32_t)(r_cl->a[l]); + + for (; k <= r_cl->n; k++) { + is_push = 0; + if(k < r_cl->n) { + get_unique_rctg_aln(uref, r_cl->a[k]>>32, k, vs, r_cl->len, &kp, NULL, ((uint32_t)-1)); + if(cmp_shrink_ul_ov_t(&lp, &kp, k - l)) is_push = 1; + } else { + is_push = 1; + } + + if(is_push) { + kp0 = kp; + if(k - l > 1) { + for (i = l; i < k; i++) {///could be merged + m = get_unique_rctg_aln(uref, r_cl->a[i]>>32, i, ls, r_cl->len, &kp, NULL, ((uint32_t)-1)); + assert(m == 1); assert(kp.tn == lp.tn); assert(kp.qn == lp.qn + i - l); assert(kp.sec == lp.sec + i - l); + if(kp.qs < lp.qs) {lp.qs = kp.qs;} if(kp.qe > lp.qe) {lp.qe = kp.qe;} + if(kp.ts < lp.ts) {lp.ts = kp.ts;} if(kp.te > lp.te) {lp.te = kp.te;} + ls += (uint32_t)(r_cl->a[i]); + + // if(id == 123) { + // fprintf(stderr, "-0-[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\tsc::%d\n", __func__, + // (int32_t)(kp.tn>>1)+1, "+-"[kp.tn&1], kp.qs, kp.qe, kp.qe-kp.qs, kp.ts, kp.te, kp.te-kp.ts, kp.sec); + // } + } + lp.sec = k - l; + kv_push(ul_ov_t, *u_cl, lp); + } else if(k - l == 1) { + m = get_unique_rctg_aln(uref, r_cl->a[l]>>32, l, ls, r_cl->len, NULL, u_cl, 1); + // if(id == 123) { + // fprintf(stderr, "-1-[M::%s::]\tutg%.6dl(%c)\tq::[%d, %d)\tt::[%d, %d)\tsc::%d\n", __func__, + // (int32_t)(kp.tn>>1)+1, "+-"[kp.tn&1], kp.qs, kp.qe, kp.qe-kp.qs, kp.ts, kp.te, kp.te-kp.ts, kp.sec); + // } + } + + l = k; lp = kp0; ls = vs; + } + + if(k < r_cl->n) vs += (uint32_t)(r_cl->a[k]); + } +} + +inline int64_t comput_linear_ctg_sc(ul_ov_t *li, ul_ov_t *lj, double diff_ec_ul, int64_t bw) +{ ///li is the suffix of lj + int64_t dq, dt, dd, mm; + if(lj->te > li->te) return INT32_MIN; + dq = li->qe - lj->qs; dt = li->te - lj->ts; + dd = (dq>dt? dq-dt:dt-dq); + mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; + if(dd > mm) return INT32_MIN; + return li->sec; +} + +inline uint64_t is_available_ctg_aln(const ul_idx_t *uref, ul_ov_t *z) +{ + if((z->te > z->ts) && (uref->ug->u.a[z->tn].len >= (z->te-z->ts)) && ((uref->ug->u.a[z->tn].len) - (z->te-z->ts) <= 16) && (z->sec >= (uref->ug->u.a[z->tn].n*0.333333))) { + return 1; + } + return 0; +} + +uint64_t linear_ctg_chain_dp_adv(ul_ov_t *ch, int64_t ch_n, ul_ov_t *sv, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, ma_ug_t *ug, +int64_t chain_offset) +{ ///all in[].el must be 1 + if(ch_n == 0) return 0; + int64_t i, j, k, sc, csc, mm_sc, mm_idx, its, ite, max; + ul_ov_t *li = NULL, *lj = NULL; int64_t *p, *t, st, plus, max_ii, n_skip, end_j; int32_t *f; + resize_Chain_Data(dp, ch_n, NULL); + t = dp->tmp; f = dp->score; p = dp->pre; + + radix_sort_ul_ov_srt_qe(ch, ch + ch_n); + for (i = 1, j = 0; i <= ch_n; i++) { + if (i == ch_n || ch[i].qe != ch[j].qe) { + if(i - j > 1) radix_sort_ul_ov_srt_qs(ch+j, ch+i); + j = i; + } + } + + // fprintf(stderr, "[M::%s::] ch_n:%ld\n", __func__, ch_n); + memset(t, 0, (ch_n*sizeof((*t)))); + for (i = st = plus = 0, max_ii = -1; i < ch_n; ++i) { + li = &(ch[i]); csc = li->sec; + mm_sc = csc; mm_idx = -1; n_skip = 0; end_j = -1; + st = (i= st; --j) { + lj = &(ch[j]); + sc = comput_linear_ctg_sc(li, lj, diff_ec_ul, bw); ///should allow contain + if(sc == INT32_MIN) continue; + sc += f[j]; + if(sc > mm_sc) { + mm_sc = sc, mm_idx = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + end_j = j; + if (max_ii < 0 || (ch[i].qe>(ch[max_ii].qe+max_dis))) {//too long + max = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && (ch[i].qe<=(max_dis+ch[j].qe)); --j) { + if (max < f[j]) { + max = f[j], max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + lj = &(ch[max_ii]); + sc = comput_linear_ctg_sc(li, lj, diff_ec_ul, bw); ///should allow contain + if(sc != INT32_MIN) { + sc += f[max_ii]; + if(sc > mm_sc) { + mm_sc = sc; mm_idx = max_ii; + } + } + } + + f[i] = mm_sc; p[i] = mm_idx; + if ((max_ii < 0) || ((ch[i].qe<=max_dis+ch[max_ii].qe) && (f[max_ii]sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); + sv[i] = *li; + // fprintf(stderr, "##(%ld) %u\t%u\t%c\tutg%.6d%c(%u)\t%u\t%u\tmm_idx:%ld\tmm_sc:%ld\n", i, li->qs, li->qe, "+-"[li->rev], + // (int32_t)(li->tn)+1, "lc"[uref->ug->u.a[li->tn].circ], uref->ug->u.a[li->tn].len, li->ts, li->te, mm_idx, mm_sc); + // track[i] = push_sc_pre(mm_sc, mm_idx); + // li->sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); sv[i] = *li; + } + + for (i = 0; i < ch_n; ++i) t[i] = 0; + int64_t n_u; + for (k = ch_n-1, n_u = 0; k >= 0; --k) { + if(t[k]) continue; + i = k; ch[n_u]=sv[i]; sc = f[i]; + for (;i>=0;) { + if(sv[i].qs < ch[n_u].qs) ch[n_u].qs = sv[i].qs; + if(sv[i].ts < ch[n_u].ts) ch[n_u].ts = sv[i].ts; + if(sv[i].qe > ch[n_u].qe) ch[n_u].qe = sv[i].qe; + if(sv[i].te > ch[n_u].te) ch[n_u].te = sv[i].te; + // ch[n_u].qn = i;//start idx of read alignment in chain + t[i] = 1; i = p[i]; + } + adjust_rev_tse(&(ch[n_u]), ug->g->seq[ch[n_u].tn].len, &its, &ite); + ch[n_u].ts = its; ch[n_u].te = ite; + + sc = ((i < 0)?(sc):(sc-f[i])); + ch[n_u].sec = (sc>0x3FFFFFFF?0x3FFFFFFF:sc);///this is calculated incorrectly + // ch[n_u].qn += chain_offset; //start idx of read alignment in chain + // ch[n_u].tn = k + chain_offset; //end idx of read alignment in chain + ch[n_u].qn = k + chain_offset; //end idx of read alignment in chain + + + n_u++; + } + for (i = 0; i < ch_n; ++i) { + adjust_rev_tse(&(sv[i]), ug->g->seq[sv[i].tn].len, &its, &ite); + sv[i].ts = its; sv[i].te = ite; + k = p[i]; sv[i].tn = k>=0?k+chain_offset:(uint32_t)-1; + } + return n_u; +} + +void gen_linear_chains_ctg(kv_ul_ov_t *res, kv_ul_ov_t *buf, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, Chain_Data* dp) +{ + uint64_t k, l, z, an, m; + radix_sort_ul_ov_srt_tn(res->a, res->a + res->n); + ///after this function, res keeps unitig alignment, while buf keeps read alignments + kv_resize(ul_ov_t, *buf, res->n); buf->n = res->n; + for (k = 1, l = m = 0; k <= res->n; k++) { + if(k == res->n || res->a[k].tn != res->a[l].tn) {///qn <- (tn|rev) + for (z = l; z < k; z++) res->a[z].tn>>=1; + an = k; + if(k - l > 1) {///if there is only one alignment for a node, then no need for DP + an = l + linear_ctg_chain_dp_adv(res->a+l, k-l, buf->a+l, uref, uopt, bw, diff_ec_ul, qlen, UG_SKIP_N, UG_ITER_N, UG_DIS_N, dp, uref->ug, l); + } + + for (z = l; z < an; z++) { + if(is_available_ctg_aln(uref, &(res->a[z]))) { + res->a[z].ts = 0; res->a[z].te = uref->ug->u.a[res->a[z].tn].len; + res->a[m++] = res->a[z]; + } + } + l = k; + } + } + res->n = m; +} + + + + +///sps and hap are just vector for uint64_t; used for buffer +uint32_t direct_gchain_scaf(mg_tbuf_t *b, ma_utg_t *rch, glchain_t *ll, gdpchain_t *gdp, st_mt_t *sps, haplotype_evdience_alloc *hap, const ul_idx_t *uref, const ug_opt_t *uopt, +int64_t bw, double diff_ec_ul, int64_t max_skip, int64_t ulid, Chain_Data* dp, const asg_t *rg, ul_vec_t *res) +{ + res->bb.n = 0; + // if(ulid != 86660) return 0; + kv_ul_ov_t *idx = &(ll->lo), *init = &(ll->tk); int64_t max_idx; + idx->n = init->n = 0; + // gl_rg2ug_gen(rch, idx, uref, 1, 2, ulid); + ctg_rg2ug_gen(rch, idx, uref, ulid); + + // uint32_t k; + // fprintf(stderr, "[M::%s] rch->len::%u, rch->n::%u, idx->n::%u\n", __func__, (uint32_t)rch->len, (uint32_t)rch->n, (uint32_t)idx->n); + // for (k = 0; k < idx->n; k++) { + // fprintf(stderr, "[k->%u::utg%.6u%c(len->%u::n->%u)]\tq::[%u, %u)\t%c\tt::[%u, %u)\n", + // k, (idx->a[k].tn>>1) + 1, "lc"[uref->ug->u.a[(idx->a[k].tn>>1)].circ], uref->ug->u.a[(idx->a[k].tn>>1)].len, idx->a[k].sec, + // idx->a[k].qs, idx->a[k].qe, "+-"[idx->a[k].rev], idx->a[k].ts, idx->a[k].te); + // } + + // for (k = 0; k < idx->n; k++) { + // fprintf(stderr, "utg%.6u%c,", (idx->a[k].tn>>1)+1, "lc"[uref->ug->u.a[(idx->a[k].tn>>1)].circ]); + // } + // fprintf(stderr, "\n"); + + if(idx->n == 0) return 0; + ///generate linear chains + gen_linear_chains_ctg(idx, init, uref, uopt, bw, diff_ec_ul, rch->len, dp); + + if(idx->n == 0) return 0; + + dump_linear_chain(uref->ug, idx, &(gdp->l), rch->len, ulid); + if(gdp->l.n == 0) return 0; + + kv_resize(uint64_t, ll->srt.a, gdp->l.n); + max_idx = ctg_chain_graph(b->km, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), + &(gdp->path), rch->len, uopt, G_CHAIN_BW, N_GCHAIN_RATE, ll->srt.a.a, sps, dp, UG_SKIP_GRAPH_N, UG_ITER_N, /**UG_DIS_N**/UG_DIS_N*100, ulid); + + //sps -> idx; (gdp->l) -> alignments + if(max_idx >= 0) { + max_idx = select_max_ctg_chain(b->km, uref, ulid, sps, &(gdp->l), &(ll->tk), uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), &(gdp->swap)); + if(max_idx) { + push_ctg_res(res, &(gdp->swap), ulid); + return 1; + } + } + + return 0; +} + +uint64_t get_seq_bub_id(uint64_t v, bubble_type *bub, uint64_t *bid, uint64_t *nxt) +{ + uint64_t id0, id1, id; uint32_t beg, sink; + + (*bid) = (*nxt) = (uint64_t)-1; + get_bub_id(bub, v>>1, &id0, &id1, 1); + + id = id0; + if((id != (uint64_t)-1) && (id < bub->f_bub)) {///no need broken bubble + get_bubbles(bub, id, &beg, &sink, NULL, NULL, NULL); + if(v == beg) { + (*bid) = id; (*nxt) = sink^1; return 1; + } + + if(v == sink) { + (*bid) = id; (*nxt) = beg^1; return 1; + } + } + + id = id1; + if((id != (uint64_t)-1) && (id < bub->f_bub)) {///no need broken bubble + get_bubbles(bub, id, &beg, &sink, NULL, NULL, NULL); + if(v == beg) { + (*bid) = id; (*nxt) = sink^1; return 1; + } + + if(v == sink) { + (*bid) = id; (*nxt) = beg^1; return 1; + } + } + + return 0; +} + +uint64_t pick_bubble(uc_block_t *a, uint64_t a_n, bubble_type *bub, uint64_t *r_bid) +{ + uint64_t k = 0, v, bid = (uint64_t)-1, w = (uint64_t)-1; (*r_bid) = (uint64_t)-1; + if(a_n <= 1) return 0;///no bubble + v = (((uint32_t)a[k].hid)<<1)|((uint32_t)a[k].rev); + if(!get_seq_bub_id(v, bub, &bid, &w)) return 0; + (*r_bid) = bid; + for (k = 1; k < a_n; k++) { + v = (((uint32_t)a[k].hid)<<1)|((uint32_t)a[k].rev); + if(v == w) return k; + if(bub->index[v>>1] != bid) return 0; + } + + return 0; +} + +uint64_t qry_bub_sc(const ul_idx_t *uref, ma_ug_t *gfa, scaf_res_t *ref_sc, bubble_type *bub, uint64_t bid, uint64_t qsidx, uint64_t qeidx, ul_vec_t *qstr, uint32_t avoid_id, kv_ul_ov_t *res) +{ + // fprintf(stderr, "qsidx::%lu(utg%.6u%c), qeidx::%lu(utg%.6u%c)\n", qsidx, (qstr->bb.a[qsidx].hid)+1, "lc"[gfa->u.a[qstr->bb.a[qsidx].hid].circ], qeidx, (qstr->bb.a[qeidx].hid)+1, "lc"[gfa->u.a[qstr->bb.a[qeidx].hid].circ]); + uint32_t beg, sink, v, w, z, si, ei, qrev = (uint32_t)-1, qv, qw, trev, nn = 0, tn; + get_bubbles(bub, bid, &beg, &sink, NULL, NULL, NULL); + if((beg == ((uint32_t)-1)) || (sink == ((uint32_t)-1))) return 0; + utg_rid_dt *a; uint64_t a_n, i, k; ul_vec_t *q; ul_ov_t p; + qv = qstr->bb.a[qsidx].hid; qv <<= 1; qv |= ((uint32_t)qstr->bb.a[qsidx].rev); + qw = qstr->bb.a[qeidx].hid; qw <<= 1; qw |= ((uint32_t)qstr->bb.a[qeidx].rev); + if((qv == beg) && (qw == (sink^1))) qrev = 0; + if((qv == sink) && (qw == (beg^1))) qrev = 1; + assert(qrev != (uint32_t)-1); + memset(&p, 0, sizeof(p)); + + v = beg; w = sink^1; trev = 0; + a = get_r_ug_region(uref->r_ug, &a_n, v>>1); + // fprintf(stderr, "+a_n::%lu\n", a_n); + for (i = 0; i < a_n; i++) { + // fprintf(stderr, "+(0)i::%lu\n", i); + if((a[i].u&1) != (v&1)) continue; + if((a[i].u>>1) == avoid_id) continue; + q = &(ref_sc->a[a[i].u>>1]); si = ei = a[i].off; + assert((q->bb.a[si].hid == (v>>1)) && (q->bb.a[si].rev == (v&1))); + // fprintf(stderr, "+(1)i::%lu\n", i); + for (k = tn = 0; k < q->bb.n; k++) tn += q->bb.a[k].te - q->bb.a[k].ts; + for (k = si + 1; (k < tn) && (q->bb.a[k].aidx == q->bb.a[si].aidx); k++) { + z = (((uint32_t)q->bb.a[k].hid)<<1)|((uint32_t)q->bb.a[k].rev); + if(z == w) {ei = k; break;} + if(bub->index[z>>1] != bid) break; + } + + if(ei > si) {////found a bubble + // fprintf(stderr, "+(2)i::%lu, si::%u, ei::%u, ref_id::%u\nn", i, si, ei, a[i].u>>1); + p.qn = q->bb.a[si].aidx; p.qs = qsidx; p.qe = qeidx; + p.tn = a[i].u>>1; p.ts = si; p.te = ei; + p.rev = (qrev == trev?0:1); + kv_push(ul_ov_t, *res, p); + nn++; + } + } + + + v = sink; w = beg^1; trev = 1; + a = get_r_ug_region(uref->r_ug, &a_n, v>>1); + // fprintf(stderr, "-a_n::%lu\n", a_n); + for (i = 0; i < a_n; i++) { + if((a[i].u&1) != (v&1)) continue; + if((a[i].u>>1) == avoid_id) continue; + q = &(ref_sc->a[a[i].u>>1]); si = ei = a[i].off; + assert((q->bb.a[si].hid == (v>>1)) && (q->bb.a[si].rev == (v&1))); + for (k = tn = 0; k < q->bb.n; k++) tn += q->bb.a[k].te - q->bb.a[k].ts; + for (k = si + 1; (k < tn) && (q->bb.a[k].aidx == q->bb.a[si].aidx); k++) { + z = (((uint32_t)q->bb.a[k].hid)<<1)|((uint32_t)q->bb.a[k].rev); + if(z == w) {ei = k; break;} + if(bub->index[z>>1] != bid) break; + } + + if(ei > si) {////found a bubble + // fprintf(stderr, "-(2)i::%lu, si::%u, ei::%u, ref_id::%u\nn", i, si, ei, a[i].u>>1); + p.qn = q->bb.a[si].aidx; p.qs = qsidx; p.qe = qeidx; + p.tn = a[i].u>>1; p.ts = si; p.te = ei; + p.rev = (qrev == trev?0:1); + kv_push(ul_ov_t, *res, p); + nn++; + } + } + + return nn; +} + +/** +uint64_t bubble_check_push(uc_block_t *a, uint64_t a_n, bubble_type *bub) +{ + uint64_t k = 0, v, bid, w; + if(a_n <= 1) return 0;///no bubble + while(k < a_n) { + v = (((uint32_t)a[k].hid)<<1)|((uint32_t)a[k].rev); + if(!get_seq_bub_id(v, bub, &bid, &w)) break; + } + + + for (k = 1, l = 0; k <= a_n; k++) { + if(k ) { + l = k; + } + } + + get_bub_id(bub, root_id, &id0, &id1, 1);; +} +**/ + + +uint64_t cc_bub_match(ul_ov_t *ch, int64_t ch_n) { + if(ch_n == 0) return 0; + int64_t i, j, k; + + radix_sort_ul_ov_srt_qs(ch, ch + ch_n); + for (i = 1, j = 0; i <= ch_n; i++) { + if (i == ch_n || ch[i].qs != ch[j].qs) { + if(i - j > 1) radix_sort_ul_ov_srt_qe(ch+j, ch+i); + j = i; + } + } + + for (i = k = 0; i < ch_n; ++i) { + if(ch[i].tn == (uint32_t)-1) continue; + for (j = i + 1; j < ch_n && ch[i].qe >= ch[j].qs; j++) { + if(ch[j].tn == (uint32_t)-1) continue; + if((ch[i].qe == ch[j].qs) && (ch[i].rev == ch[j].rev) && (ch[i].qn == ch[j].qn)) { + if(!ch[i].rev) { + if(ch[i].te == ch[j].ts) { + ch[i].qe = ch[j].qe; + ch[i].te = ch[j].te; + ch[j].tn = (uint32_t)-1; + } + } else { + if(ch[j].te == ch[i].ts) { + ch[i].qe = ch[j].qe; + ch[i].ts = ch[j].ts; + ch[j].tn = (uint32_t)-1; + } + } + } + } + + ch[k++] = ch[i]; + } + + return k; +} + +uint64_t extract_scaf_res_t(uc_block_t *in, const ul_idx_t *uref, scaf_res_t *ref_sc, uint32_t avid, kv_ul_ov_t *res) +{ + utg_rid_dt *a; uint64_t i, a_n, nn, nw; uc_block_t *ou; ul_ov_t p; memset(&p, 0, sizeof(p)); + a = get_r_ug_region(uref->r_ug, &a_n, in->hid); + for (i = nn = 0; i < a_n; i++) { + if((a[i].u>>1) == avid) continue; + ou = &(ref_sc->a[a[i].u>>1].bb.a[a[i].off]); + p.qn = (uint32_t)-1; p.qs = in->qs; p.qe = in->qe; + p.tn = a[i].u>>1; p.ts = ou->qs; p.te = ou->qe; + p.el = 1; p.rev = ((in->rev == ou->rev)?0:1); + nw = MAX(p.te-p.ts, p.qe-p.qs); nw *= CHAIN_MATCH; + p.sec = ((nw>=0x3fffffff)?(0x3fffffff):(nw)); + kv_push(ul_ov_t, *res, p); + + nn++; + } + return nn; +} + +uint64_t gen_trans_ovlp_scaf(ma_ug_t *gfa, u_trans_t *map, uc_block_t *qin, uc_block_t *rin, ul_ov_t *res) +{ + uint64_t s, e, s0, e0; uc_block_t *z; + + z = qin; s0 = map->qs; e0 = map->qe; + if(s0 > gfa->u.a[z->hid].len || e0 > gfa->u.a[z->hid].len) return 0; + if(!(z->rev)) { + s = s0; e = e0; + } else { + s = gfa->u.a[z->hid].len - e0; + e = gfa->u.a[z->hid].len - s0; + } + s += z->qs; e += z->qs; + if(s >= e) return 0; + res->qs = s; res->qe = e; + + + z = rin; s0 = map->ts; e0 = map->te; + if(s0 > gfa->u.a[z->hid].len || e0 > gfa->u.a[z->hid].len) return 0; + if(!(z->rev)) { + s = s0; e = e0; + } else { + s = gfa->u.a[z->hid].len - e0; + e = gfa->u.a[z->hid].len - s0; + } + s += z->qs; e += z->qs; + if(s >= e) return 0; + res->ts = s; res->te = e; + + res->rev = map->rev^(qin->rev^rin->rev); + + return 1; +} + +void extract_trans_scaf_res_t(uc_block_t *qin, const ul_idx_t *uref, scaf_res_t *ref_sc, ma_ug_t *gfa, kv_u_trans_t *ta, uint32_t avid, uint32_t is_exact, kv_ul_ov_t *res) +{ + utg_rid_dt *a; uint64_t i, a_n; uc_block_t *rin; + u_trans_t *u; uint64_t k, u_n; + ul_ov_t p; memset(&p, 0, sizeof(p)); + + // fprintf(stderr, "\n[M::%s] utg%.6u%c, [%u, %u)\n", __func__, qin->hid+1, "lc"[gfa->u.a[qin->hid].circ], qin->qs, qin->qe); + u = u_trans_a(*ta, qin->hid); + u_n = u_trans_n(*ta, qin->hid); + for (k = 0; k < u_n; k++) { + if(is_exact && u[k].f != RC_0 && u[k].f != RC_1) continue; + // fprintf(stderr, "+[M::%s] utg%.6u%c->utg%.6u%c, q::[%u, %u), %c, t::[%u, %u)\n", __func__, qin->hid+1, "lc"[gfa->u.a[qin->hid].circ], u[k].tn+1, "lc"[gfa->u.a[u[k].tn].circ], u[k].qs, u[k].qe, "+-"[u[k].rev], u[k].ts, u[k].te); + a = get_r_ug_region(uref->r_ug, &a_n, u[k].tn); + for (i = 0; i < a_n; i++) { + if((a[i].u>>1) == avid) continue; + rin = &(ref_sc->a[a[i].u>>1].bb.a[a[i].off]); + if(gen_trans_ovlp_scaf(gfa, &(u[k]), qin, rin, &p)) { + p.tn = a[i].u>>1; p.qn = u[k].f; p.el = 0; p.sec = u[k].nw; + kv_push(ul_ov_t, *res, p); + + // fprintf(stderr, "-[M::%s] q::[%u, %u), %c, t::[%u, %u), qin->qs::%u, rin->qs::%u\n", __func__, p.qs, p.qe, "+-"[p.rev], p.ts, p.te, qin->qs, rin->qs); + } + } + } +} + +void cl_trans_gen(uint32_t qid, uint32_t qlen, ul_vec_t *qstr, kv_ul_ov_t *res, const ul_idx_t *uref, ma_ug_t *ref, scaf_res_t *ref_sc, ma_ug_t *gfa, bubble_type *bub, kv_u_trans_t *ta, uint32_t is_self, uint32_t is_exact) +{ + uint64_t k, l, m = 0, mi, z, zn, a_n, bid, nw; uc_block_t *a; uint32_t avid = ((is_self)?(qid):((uint32_t)-1)); + res->n = 0; + ///identify bubble chain first + for (k = 0, a = qstr->bb.a; k < qstr->bb.n; k++) { + z = qstr->bb.a[k].ts; a_n = qstr->bb.a[k].te; + while (z < a_n) { + zn = 1; + zn = pick_bubble(a + z, a_n - z, bub, &bid); + if((!zn) || (!qry_bub_sc(uref, gfa, ref_sc, bub, bid, z, z + zn, qstr, avid, res))) {///found a bubble; a[z] -> beg; a[z + zn] -> sink + zn = 1; + } + z += zn; + } + } + + if(res->n) {///matched bubbles + for (k = 0; k < res->n; k++) res->a[k].tn = (((uint64_t)res->a[k].tn)<<1)|((uint64_t)res->a[k].rev); + radix_sort_ul_ov_srt_tn(res->a, res->a + res->n); + + for (k = 1, l = m = 0; k <= res->n; k++) { + if(k == res->n || res->a[k].tn != res->a[l].tn) {///qn <- (tn|rev) + for (z = l; z < k; z++) res->a[z].tn>>=1; + a_n = k; + if(k - l > 1) {///if there is only one alignment for a node, then no need for DP + a_n = l + cc_bub_match(res->a+l, k-l); + } + + for (z = l; z < a_n; z++) res->a[m++] = res->a[z]; + // fprintf(stderr, "l::%lu, k::%lu, m::%lu\n", l, k, m); + l = k; + } + } + res->n = m; + radix_sort_ul_ov_srt_qe(res->a, res->a + res->n); + // for (k = 0; k < res->n; k++) { + // fprintf(stderr, "***qsidx::%u(utg%.6u%c), qeidx::%u(utg%.6u%c)\n", res->a[k].qs, (qstr->bb.a[res->a[k].qs].hid)+1, "lc"[gfa->u.a[qstr->bb.a[res->a[k].qs].hid].circ], res->a[k].qe, (qstr->bb.a[res->a[k].qe].hid)+1, "lc"[gfa->u.a[qstr->bb.a[res->a[k].qe].hid].circ]); + // } + + } + + for (k = 0; k < qstr->bb.n; k++) { + z = qstr->bb.a[k].ts; a_n = qstr->bb.a[k].te; + for (; z < a_n; z++) { + ///filter by bubble + for (mi = 0; mi < m && z <= res->a[mi].qe; mi++) { + if((z >= res->a[mi].qs) && (z <= res->a[mi].qe)) break; + } + if((mi < m) && (z >= res->a[mi].qs) && (z <= res->a[mi].qe)) continue; + + ///exact match + if(extract_scaf_res_t(&(qstr->bb.a[z]), uref, ref_sc, avid, res)) continue; + + ///trans match + extract_trans_scaf_res_t(&(qstr->bb.a[z]), uref, ref_sc, gfa, ta, avid, is_exact, res); + } + } + + for(k = 0; k < m; k++) {///reset bubble + res->a[k].el = 1; res->a[k].qn = res->a[k].qs; + + res->a[k].qs = qstr->bb.a[res->a[k].qs].qs; + res->a[k].qe = qstr->bb.a[res->a[k].qe].qe; + + res->a[k].ts = ref_sc->a[res->a[k].tn].bb.a[res->a[k].ts].qs; + res->a[k].te = ref_sc->a[res->a[k].tn].bb.a[res->a[k].te].qe; + + nw = MAX(res->a[k].te-res->a[k].ts, res->a[k].qe-res->a[k].qs); nw *= CHAIN_MATCH; + res->a[k].sec = ((nw>=0x3fffffff)?(0x3fffffff):(nw)); + } + + // for (k = 0; k < res->n; k++) { + // fprintf(stderr, "[M::%s]\tutg%.6ul(len::%u)\tq::[%u, %u)\t%c\tutg%.6ul(len::%u)\tt::[%u, %u)\tel::%u\ttp::%u\n", __func__, qid + 1, qlen, res->a[k].qs, res->a[k].qe, "+-"[res->a[k].rev], res->a[k].tn+1, ref->u.a[res->a[k].tn].len, res->a[k].ts, res->a[k].te, res->a[k].el, res->a[k].qn); + // } +} + +inline int64_t comput_linear_ctg_trans_sc(ul_ov_t *li, ul_ov_t *lj, double diff_ec_ul, double ovlp_max, int64_t bw) +{ ///li is the suffix of lj + int64_t dq, dt, dd, mm, os, oe; + if(lj->rev != li->rev) return INT32_MIN; + int64_t iqs, iqe, its, ite, jqs, jqe, jts, jte; + iqs = li->qs; iqe = li->qe; + jqs = lj->qs; jqe = lj->qe; + its = li->ts; ite = li->te; + jts = lj->ts; jte = lj->te; + // if(li->rev) { + // its = lj->ts; ite = lj->te; + // jts = li->ts; jte = li->te; + // } + if(jte > ite) return INT32_MIN; + + + + + dq = iqs - jqe; + dt = its - jte; + dd = (dq>dt? dq-dt:dt-dq); + + dq = iqe - jqs; + dt = ite - jts; + mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; + if(dd > mm) return INT32_MIN; + + ///too long overlap + dd = iqe - iqs; if(dd > jqe - jqs) dd = jqe - jqs; + dd *= ovlp_max; if(dd < bw) dd = bw; + os = MAX(iqs, jqs), oe = MIN(iqe, jqe); + mm = ((oe > os)? (oe - os):0); + if(mm > 0 && mm > dd) return INT32_MIN; + + dd = ite - its; if(dd > jte - jts) dd = jte - jts; + dd *= ovlp_max; if(dd < bw) dd = bw; + os = MAX(its, jts), oe = MIN(ite, jte); + mm = ((oe > os)? (oe - os):0); + if(mm > dd) return INT32_MIN; + + return li->sec; +} + +uint64_t linear_ctg_trans_chain_dp(uint32_t qid, ul_ov_t *ch, int64_t ch_n, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, double ovlp_max, double unmatch_max, int64_t qlen, int64_t tlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, ul_ov_t *res, asg64_v *ea) +{ + memset(res, 0, sizeof((*res))); + if(ch_n == 0) return 0; + int64_t i, j, k, l, sc, csc, se, cse, mm_sc, mm_se, mm_idx, max, max_e, peak_sc, peak_e, peak_i, rts, rte, rqs, rqe; + ul_ov_t *li = NULL, *lj = NULL; int64_t *f, *e, st, plus, max_ii, n_skip, end_j; int32_t *p, *t; + resize_Chain_Data(dp, ch_n, NULL); + e = dp->tmp; f = dp->pre; p = dp->score; t = dp->indels; + + i = 0; + if(i < ch_n) { + ch[i].tn >>= 1; + if(ch[i].rev) { + adjust_rev_tse(&(ch[i]), tlen, &rts, &rte); + ch[i].ts = rts; ch[i].te = rte; + } + } + + for (i = 1, j = 0; i <= ch_n; i++) { + if(i < ch_n) { + ch[i].tn >>= 1; + if(ch[i].rev) { + adjust_rev_tse(&(ch[i]), tlen, &rts, &rte); + ch[i].ts = rts; ch[i].te = rte; + } + } + if (i == ch_n || ch[i].rev != ch[j].rev) { + if(i - j > 1) { + radix_sort_ul_ov_srt_qe(ch+j, ch+i); + for (k = j + 1, l = j; k <= i; k++) { + if(k == i || ch[k].qe != ch[l].qe) { + if(k - l > 1) radix_sort_ul_ov_srt_qs(ch+l, ch+k); + l = k; + } + } + } + j = i; + } + } + + // fprintf(stderr, "[M::%s::] ch_n:%ld\n", __func__, ch_n); + memset(t, 0, (ch_n*sizeof((*t)))); peak_sc = peak_e = peak_i = INT32_MIN; + for (i = st = plus = 0, max_ii = -1; i < ch_n; ++i) { + li = &(ch[i]); csc = li->sec; cse = 0; + if(li->el || li->qn == RC_0 || li->qn == RC_1) cse = li->qe - li->qs; + + mm_sc = csc; mm_se = cse; mm_idx = -1; n_skip = 0; end_j = -1; + st = (i= st; --j) { + lj = &(ch[j]); + sc = comput_linear_ctg_trans_sc(li, lj, diff_ec_ul, ovlp_max, bw); ///should allow contain + if(sc == INT32_MIN) continue; + sc += f[j]; se = cse + e[j]; + if((sc > mm_sc) || (sc == mm_sc && se > mm_se)) { + mm_sc = sc, mm_se = se, mm_idx = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + + + end_j = j; + if (max_ii < 0 || (ch[i].qe>(ch[max_ii].qe+max_dis))) {//too long + max = INT32_MIN; max_e = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && (ch[i].qe<=(max_dis+ch[j].qe)); --j) { + if ((max < f[j]) || (max == f[j] && max_e < e[j])) { + max = f[j], max_e = e[j], max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + lj = &(ch[max_ii]); + sc = comput_linear_ctg_trans_sc(li, lj, diff_ec_ul, ovlp_max, bw); ///should allow contain + if(sc != INT32_MIN) { + sc += f[max_ii]; + se = cse + e[max_ii]; + if((sc > mm_sc) || (sc == mm_sc && se > mm_se)) { + mm_sc = sc; mm_se = se; mm_idx = max_ii; + } + } + } + + f[i] = mm_sc; e[i] = mm_se; p[i] = mm_idx; + if ((max_ii < 0) || ((ch[i].qe<=max_dis+ch[max_ii].qe) && ((f[max_ii] peak_sc) || (f[i] == peak_sc || e[i] > peak_e)) { + peak_sc = f[i]; peak_e = e[i]; peak_i = i; + } + // li->sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); + // sv[i] = *li; + // fprintf(stderr, "##(%ld) %u\t%u\t%c\tutg%.6d%c(%u)\t%u\t%u\tmm_idx:%ld\tmm_sc:%ld\n", i, li->qs, li->qe, "+-"[li->rev], + // (int32_t)(li->tn)+1, "lc"[uref->ug->u.a[li->tn].circ], uref->ug->u.a[li->tn].len, li->ts, li->te, mm_idx, mm_sc); + // track[i] = push_sc_pre(mm_sc, mm_idx); + // li->sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); sv[i] = *li; + } + + if(peak_i < 0) return 0; + + uint64_t qs, qgap = 0, ts, tgap = 0, eqs = (uint64_t)-1, eqe = (uint64_t)-1, ea_n = ea->n; + i = peak_i; *res = ch[i]; + res->qn = ((peak_sc>UINT32_MAX)?(UINT32_MAX):(peak_sc)); + res->sec = 0; qs = res->qs; ts = res->ts; + + // memset(er, 0, sizeof((*er))); er->qs = er->qe = er->ts = er->te = (uint32_t)-1; + // er->qn = ((peak_e>UINT32_MAX)?(UINT32_MAX):(peak_e)); + + ///has been sorted by qe && te + while (i >= 0) { + if(ch[i].qe >= qs) { + if(ch[i].qs < qs) qs = ch[i].qs; + } else { + qgap += qs - ch[i].qe; + qs = ch[i].qs; + } + + if(ch[i].te >= ts) { + if(ch[i].ts < ts) ts = ch[i].ts; + } else { + tgap += ts - ch[i].te; + ts = ch[i].ts; + } + + if(ch[i].el || ch[i].qn == RC_0 || ch[i].qn == RC_1) {///reliable + if ((ea->n > ea_n) && (ch[i].qe >= (ea->a[ea->n-1]>>32))) { + if(ch[i].qs < (ea->a[ea->n-1]>>32)) { + eqs = ch[i].qs; eqe = (uint32_t)(ea->a[ea->n-1]); + ea->a[ea->n-1] = eqs << 32; ea->a[ea->n-1] |= eqe; + } + } else { + eqs = ch[i].qs; eqe = ch[i].qe; eqs <<= 32; eqs |= eqe; + kv_push(uint64_t, *ea, eqs); + // ea->a[ea->n-1] = eqs << 32; ea->a[ea->n-1] |= eqe; + } + } + + if(ch[i].qs < res->qs) res->qs = ch[i].qs; + if(ch[i].qe > res->qe) res->qe = ch[i].qe; + if(ch[i].ts < res->ts) res->ts = ch[i].ts; + if(ch[i].te > res->te) res->te = ch[i].te; + // if(qid == 2 && qlen == 112183461 && ch[i].tn == 30 && tlen == 24761445) { + // fprintf(stderr, "-(%ld)[M::%s] h2tg%.6u%c\t%ld\t%u\t%u\t%c\th1tg%.6u%c\t%ld\t%u\t%u\tsec(%u)\tel(%u)\tf(%u)\n", i, __func__, + // qid+1, "lc"[0], qlen, ch[i].qs, ch[i].qe, "+-"[ch[i].rev], ch[i].tn+1, "lc"[0], tlen, ch[i].ts, ch[i].te, ch[i].sec, ch[i].el, ch[i].qn); + // } else if(ch[i].tn == 2 && tlen == 112183461 && ch[i].qn == 30 && qlen == 24761445) { + // fprintf(stderr, "-(%ld)[M::%s] h1tg%.6u%c\t%ld\t%u\t%u\t%c\th2tg%.6u%c\t%ld\t%u\t%u\tsec(%u)\tel(%u)\tf(%u)\n", i, __func__, + // qid+1, "lc"[0], qlen, ch[i].qs, ch[i].qe, "+-"[ch[i].rev], ch[i].tn+1, "lc"[0], tlen, ch[i].ts, ch[i].te, ch[i].sec, ch[i].el, ch[i].qn); + // } + i = p[i]; + } + ////0x3fffffff + // if(qgap > 0x3fffffff || tgap > 0x3fffffff) { + // ea->n = ea_n; return 0; + // } + + adjust_rev_tse(res, tlen, &rts, &rte); + res->ts = rts; res->te = rte; + extend_end_coord(NULL, res, qlen, tlen, &rqs, &rqe, &rts, &rte); + qgap += (rqe - rqs) - (res->qe - res->qs); + tgap += (rte - rts) - (res->te - res->ts); + + // if(qid == 2 && qlen == 112183461 && ch[0].tn == 30 && tlen == 24761445) { + // fprintf(stderr, "+(%ld)[M::%s] h2tg%.6u%c\t%ld\t%ld(%u)\t%ld(%u)\t%c\th1tg%.6u%c\t%ld\t%ld(%u)\t%ld(%u)\tqgap(%ld)\ttgap(%ld)\n", i, __func__, + // qid+1, "lc"[0], qlen, rqs, res->qs, rqe, res->qe, "+-"[ch[0].rev], ch[0].tn+1, "lc"[0], tlen, rts, res->ts, rte, res->te, qgap, tgap); + // } else if(ch[i].tn == 2 && tlen == 112183461 && ch[0].qn == 30 && qlen == 24761445) { + // fprintf(stderr, "+(%ld)[M::%s] h2tg%.6u%c\t%ld\t%ld(%u)\t%ld(%u)\t%c\th1tg%.6u%c\t%ld\t%ld(%u)\t%ld(%u)\tqgap(%ld)\ttgap(%ld)\n", i, __func__, + // qid+1, "lc"[0], qlen, rqs, res->qs, rqe, res->qe, "+-"[ch[0].rev], ch[0].tn+1, "lc"[0], tlen, rts, res->ts, rte, res->te, qgap, tgap); + // } + + // if(qgap > 0x3fffffff || tgap > 0x3fffffff) { + // ea->n = ea_n; return 0; + // } + if((qgap > ((rqe-rqs)*unmatch_max)) || (tgap > ((rte-rts)*unmatch_max))) { + ea->n = ea_n; return 0; + } + + double qrate = ((double)((rqe-rqs)-qgap))/((double)(rqe-rqs)); + double trate = ((double)((rte-rts)-tgap))/((double)(rte-rts)); + double mrate = MIN(qrate, trate); if(mrate < 0) mrate = 0; + res->qn *= mrate; + if(res->qn <= 0) { + ea->n = ea_n; return 0; + } + + res->qs = rqs; res->qe = rqe; res->ts = rts; res->te = rte; + res->sec = (0x3fffffff); + if(ea->n > ea_n) { + uint64_t *a = ea->a + ea_n, an = ea->n - ea_n, ai, an1 = an>>1; + for(ai = 0; ai < an1; ai++) { + qs = a[ai]; a[ai] = a[an - ai - 1]; a[an - ai - 1] = qs; + } + res->sec = ea->n; kv_push(uint64_t, *ea, an); + } + + return 1; +} + +void ctg_trans_gp_chain(uint32_t qid, kv_ul_ov_t *res, const ul_idx_t *uref, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, int64_t qlen, Chain_Data* dp, ma_ug_t *ref, uint32_t is_self, asg64_v *b, double unmatch_max) +{ + uint64_t k, l, m = 0, rn = res->n; ul_ov_t rr; uint32_t avid = ((is_self)?(qid):((uint32_t)-1)); + for (k = 0; k < rn; k++) { + res->a[k].tn <<= 1; res->a[k].tn |= res->a[k].rev; + } + radix_sort_ul_ov_srt_tn(res->a, res->a + rn); + + for (k = 1, l = 0, b->n = 0; k <= rn; k++) { + if((k == rn) || ((res->a[l].tn>>1) != (res->a[k].tn>>1))) { + // fprintf(stderr, "+[M::%s]\tutg%.6ul\n", __func__, (res->a[l].tn>>1) + 1); + if(((res->a[l].tn>>1) != avid) && (linear_ctg_trans_chain_dp(qid, res->a+l, k-l, uref, uopt, bw, diff_ec_ul, /**0.333333**/0.4, unmatch_max, qlen, ref->u.a[(res->a[l].tn>>1)].len, UG_SKIP_N, UG_ITER_N, UG_DIS_N, dp, &rr, b))) { + res->a[m++] = rr; + // fprintf(stderr, "-[M::%s]\tutg%.6ul\n", __func__, rr.tn + 1); + } + l = k; + } + } + res->n = m; + + // for (k = 0; k < res->n; k++) { + // fprintf(stderr, "[M::%s]\tutg%.6ul(len::%ld)\tq::[%u, %u)\t%c\tutg%.6ul(len::%u)\tt::[%u, %u)\tel::%u\ttp::%u\n", __func__, qid + 1, qlen, res->a[k].qs, res->a[k].qe, "+-"[res->a[k].rev], res->a[k].tn+1, ref->u.a[res->a[k].tn].len, res->a[k].ts, res->a[k].te, res->a[k].el, res->a[k].qn); + // } +} + + +uint64_t cal_reliable_ovlp(ul_ov_t *z, asg64_v *in, uint64_t s, uint64_t e) +{ + if(z->sec >= in->n) return 0; + uint64_t k, zs, ze, os, oe, ovq, l = 0; + for (k = z->sec - in->a[z->sec]; k < z->sec; k++) { + zs = (in->a[k]>>32); ze = ((uint32_t)in->a[k]); + if(zs >= e) break; + if(ze <= s) continue; + os = MAX(s, zs); oe = MIN(e, ze); + ovq = ((oe > os)? (oe - os):0); + l += ovq; + } + return l; +} + + +uint64_t filter_ctg_trans(uint32_t qid, ma_ug_t *qry, ma_ug_t *ref, kv_ul_ov_t *aln, asg64_v *aln_e, asg64_v *srt, double reliable_rate, uint64_t reliable_len, double sec_rate, uint64_t sec_bd, double sec_sc, uint64_t soff, uint32_t is_self) +{ + if(aln->n <= 0) return 0; + + uint64_t k, an, *ss, *hs, *bu, *wu, clen, m, wm, z, l, wl, le, os, oe, ovq; ul_ov_t *cz, *mz; uint32_t sce[2]; sce[0] = 0; sce[1] = 1; + for (k = 0; k < aln->n; k++) { + aln->a[k].el = 0; clen = 0; + if((!is_self) || (sce[(qida[k].tna[k].sec < aln_e->n) {///has reliable regions + for (z = aln->a[k].sec - aln_e->a[aln->a[k].sec]; z < aln->a[k].sec; z++) { + clen += ((uint32_t)aln_e->a[z]) - (aln_e->a[z]>>32); + } + } + if((clen > reliable_len) && (clen > ((aln->a[k].qe - aln->a[k].qs)*reliable_rate))) { + aln->a[k].el = 1; + } + } + aln->a[k].qn = ((uint32_t)-1) - aln->a[k].qn; + + // if(qid == 2 && qry->u.a[qid].len == 112183461) {///h2tg000003l + // fprintf(stderr, "+[M::%s] h2tg%.6u%c\t%u\t%u\t%u\t%c\th1tg%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, + // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], + // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); + // } else if(qid == 30 && qry->u.a[qid].len == 24761445) {///h1tg000031l + // fprintf(stderr, "+[M::%s] h1tg%.6u%c\t%u\t%u\t%u\t%c\th12g%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, + // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], + // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); + // } else if(aln->a[k].tn == 2 && ref->u.a[aln->a[k].tn].len == 112183461) {///h2tg000003l + // fprintf(stderr, "+[M::%s] h1tg%.6u%c\t%u\t%u\t%u\t%c\th12g%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, + // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], + // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); + // } else if(aln->a[k].tn == 30 && ref->u.a[aln->a[k].tn].len == 24761445) { + // fprintf(stderr, "+[M::%s] h2tg%.6u%c\t%u\t%u\t%u\t%c\th1tg%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, + // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], + // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); + // } + } + if(aln->n > 1) radix_sort_ul_ov_srt_qn(aln->a, aln->a + aln->n);///qn->score + for (k = 0; k < aln->n; k++) aln->a[k].qn = ((uint32_t)-1) - aln->a[k].qn; + + an = aln->n; an <<= 2; + srt->n = 0; kv_resize(uint64_t, *srt, an); + for (k = 0; k < aln->n; k++) { + srt->a[srt->n] = aln->a[k].qs; + srt->a[srt->n] <<= 32; + srt->a[srt->n] |= k; + srt->n++; + } + + ss = srt->a; hs = ss + srt->n; bu = hs + srt->n; wu = bu + srt->n; + radix_sort_gfa64(ss, ss + aln->n); + for (k = 0; k < aln->n; k++) { + ss[k] = (uint32_t)ss[k]; hs[ss[k]] = k; + } + for (k = 0; k < aln->n; k++) { + if(aln->a[k].el) continue; + cz = &(aln->a[k]); clen = (cz->qe-cz->qs) * sec_rate; m = wm = 0; + + for (z = l = wl = le = 0; z < aln->n; z++) { + if(z == hs[k]) { + assert(ss[z] == k); + continue; + } + if(ss[z] > k) continue;///smaller nw than a[k] + mz = &(aln->a[ss[z]]); + if(mz->qs >= cz->qe) break; + if(mz->tn == ((uint32_t)-1)) continue;///has been deleted + if((!(mz->el)) && (cz->qn > (mz->qn*0.9))) continue; + os = MAX(cz->qs, mz->qs); oe = MIN(cz->qe, mz->qe); + ovq = ((oe > os)? (oe - os):0); + if(!ovq) continue; + // if(is_connect_arc(cz, mz, s->ug, 0.04) || is_connect_arc(mz, cz, s->ug, 0.04)) continue; + + if((m > 0) && (((uint32_t)bu[m-1]) >= os)) { + if(oe > ((uint32_t)bu[m-1])) { + le += cal_reliable_ovlp(cz, aln_e, ((uint32_t)bu[m-1]), oe); + l += (oe - ((uint32_t)bu[m-1])); + bu[m-1] += (oe - ((uint32_t)bu[m-1])); + } + } else { + le += cal_reliable_ovlp(cz, aln_e, os, oe); + l += oe - os; + bu[m] = os; bu[m] <<= 32; bu[m] |= oe; m++; + } + + if((wm > 0) && (((uint32_t)wu[wm-1]) >= mz->qs)) { + if(mz->qe > ((uint32_t)wu[wm-1])) { + wl += (mz->qe - ((uint32_t)wu[wm-1])); + wu[wm-1] += (mz->qe - ((uint32_t)wu[wm-1])); + } + } else { + wl += mz->qe - mz->qs; + wu[wm] = mz->qs; wu[wm] <<= 32; wu[wm] |= mz->qe; wm++; + } + + if((l > 0) && (l > sec_bd) && (le <= l*0.5)) { + if((l>=clen) || (l>=(wl*sec_rate))) { + ///sc is small enough + if(cz->qn <= (mz->qn*sec_sc)) { + cz->tn = ((uint32_t)-1); + break; + } + } + } + } + } + + for (k = m = 0; k < aln->n; k++) { + if(aln->a[k].tn == ((uint32_t)-1)) continue; + // if(qid == 2 && qry->u.a[qid].len == 112183461) {///h2tg000003l + // fprintf(stderr, "-[M::%s] h2tg%.6u%c\t%u\t%u\t%u\t%c\th1tg%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, + // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], + // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); + // } else if(qid == 30 && qry->u.a[qid].len == 24761445) {///h1tg000031l + // fprintf(stderr, "-[M::%s] h1tg%.6u%c\t%u\t%u\t%u\t%c\th12g%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, + // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], + // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); + // } else if(aln->a[k].tn == 2 && ref->u.a[aln->a[k].tn].len == 112183461) {///h2tg000003l + // fprintf(stderr, "-[M::%s] h1tg%.6u%c\t%u\t%u\t%u\t%c\th12g%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, + // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], + // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); + // } else if(aln->a[k].tn == 30 && ref->u.a[aln->a[k].tn].len == 24761445) { + // fprintf(stderr, "-[M::%s] h2tg%.6u%c\t%u\t%u\t%u\t%c\th1tg%.6u%c\t%u\t%u\t%u\tsec(%u)\tel(%u)\n", __func__, + // qid+1, "lc"[qry->u.a[qid].circ], qry->u.a[qid].len, aln->a[k].qs, aln->a[k].qe, "+-"[aln->a[k].rev], + // aln->a[k].tn+1, "lc"[ref->u.a[aln->a[k].tn].circ], ref->u.a[aln->a[k].tn].len, aln->a[k].ts, aln->a[k].te, aln->a[k].sec, aln->a[k].el); + // } + aln->a[m++] = aln->a[k]; + } + aln->n = m; + // radix_sort_ul_ov_srt_qs(aln->a, aln->a + aln->n); + return aln->n; +} + +void push_ctg_trans_res(uint32_t id, kv_ul_ov_t *in, kv_ul_ov_t *ou) +{ + uint32_t k; + kv_resize(ul_ov_t, *ou, ou->n + in->n); + for (k = 0; k < in->n; k++) { + in->a[k].sec = ((in->a[k].qn>=(0x3fffffff))?(0x3fffffff):(in->a[k].qn)); + in->a[k].qn = id; kv_push(ul_ov_t, *ou, in->a[k]); + } +} + +uint32_t direct_ctg_trans_chain(mg_tbuf_t *b, uint32_t id, glchain_t *ll, gdpchain_t *gdp, st_mt_t *sps, haplotype_evdience_alloc *hap, const ul_idx_t *uref, const ug_opt_t *uopt, +int64_t bw, double diff_ec_ul, int64_t max_skip, int64_t ulid, Chain_Data* dp, ma_ug_t *qry, scaf_res_t *qry_sc, ma_ug_t *ref, scaf_res_t *ref_sc, ma_ug_t *gfa, bubble_type *bub, kv_u_trans_t *ta, const asg_t *rg, uint64_t soff, uint64_t is_exact) +{ + // res->bb.n = 0; + // if(ulid != 86660) return 0; + kv_ul_ov_t *idx = &(ll->lo), *init = &(ll->tk); ///int64_t max_idx; + asg64_v b0, b1; uint32_t is_self = (qry?0:1); idx->n = 0; + + cl_trans_gen(id, qry?qry->u.a[id].len:ref->u.a[id].len, qry_sc?&(qry_sc->a[id]):&(ref_sc->a[id]), idx, uref, ref, ref_sc, gfa, bub, ta, is_self, is_exact); + if(idx->n == 0) return 0; + + copy_asg_arr(b0, (*sps)); + ctg_trans_gp_chain(id, idx, uref, uopt, bw, diff_ec_ul, qry?qry->u.a[id].len:ref->u.a[id].len, dp, ref, is_self, &b0, ((is_exact)?(0.5):(0.666666))); + copy_asg_arr((*sps), b0); + if(idx->n == 0) return 0; + + copy_asg_arr(b0, (*sps)); copy_asg_arr(b1, ll->srt.a); + filter_ctg_trans(id, qry, ref, idx, &b0, &b1, 0.5, 10000, /**0.333333**/0.85, 10000, 0.3, soff, is_self); + copy_asg_arr((*sps), b0); copy_asg_arr(ll->srt.a, b1); + if(idx->n == 0) return 0; + + push_ctg_trans_res(id, idx, init); + + /** + // gl_rg2ug_gen(rch, idx, uref, 1, 2, ulid); + ctg_rg2ug_gen(rch, idx, uref); + + // uint32_t k; + // fprintf(stderr, "[M::%s] rch->len::%u, rch->n::%u, idx->n::%u\n", __func__, (uint32_t)rch->len, (uint32_t)rch->n, (uint32_t)idx->n); + // for (k = 0; k < idx->n; k++) { + // fprintf(stderr, "[k->%u::utg%.6u%c(len->%u::n->%u)]\tq::[%u, %u)\t%c\tt::[%u, %u)\n", + // k, (idx->a[k].tn>>1) + 1, "lc"[uref->ug->u.a[(idx->a[k].tn>>1)].circ], uref->ug->u.a[(idx->a[k].tn>>1)].len, idx->a[k].sec, + // idx->a[k].qs, idx->a[k].qe, "+-"[idx->a[k].rev], idx->a[k].ts, idx->a[k].te); + // } + + // for (k = 0; k < idx->n; k++) { + // fprintf(stderr, "utg%.6u%c,", (idx->a[k].tn>>1)+1, "lc"[uref->ug->u.a[(idx->a[k].tn>>1)].circ]); + // } + // fprintf(stderr, "\n"); + + if(idx->n == 0) return 0; + ///generate linear chains + gen_linear_chains_ctg(idx, init, uref, uopt, bw, diff_ec_ul, rch->len, dp); + + if(idx->n == 0) return 0; + + dump_linear_chain(uref->ug, idx, &(gdp->l), rch->len, ulid); + if(gdp->l.n == 0) return 0; + + kv_resize(uint64_t, ll->srt.a, gdp->l.n); + max_idx = ctg_chain_graph(b->km, uref, uref->ug, &(gdp->l), &(gdp->swap), &(gdp->dst), &(gdp->out), + &(gdp->path), rch->len, uopt, G_CHAIN_BW, N_GCHAIN_RATE, ll->srt.a.a, sps, dp, UG_SKIP_GRAPH_N, UG_ITER_N, UG_DIS_N*100); + + //sps -> idx; (gdp->l) -> alignments + if(max_idx >= 0) { + max_idx = select_max_ctg_chain(b->km, uref, ulid, sps, &(gdp->l), &(ll->tk), uref->ug->g, &(gdp->dst_done), &(gdp->out), &(gdp->path), &(gdp->swap)); + if(max_idx) { + push_ctg_res(res, &(gdp->swap)); + return 1; + } + } + **/ + + return 0; +} + + +uint32_t refine_rid_chain(const asg_t *rg, mg_tbuf_t *b, ul_vec_t *rch, uint64_t ulid) +{ + if(rch->bb.n == 1 && rch->bb.a[0].base) return 1;///no alignment + if(rch->bb.n == 0) return 1;///no alignment + uint64_t i, m, c[2], nc, cc/**, ni[2]**/; + for (i = c[1] = rch->bb.n-1, m = nc = 0; i != (uint32_t)-1; i = rch->bb.a[i].pidx) { + m++; c[0] = i; if(!(rg->seq[rch->bb.a[i].hid].del)) nc++; + } + if(m == rch->bb.n) {///only one chain + if(nc == m || nc == 0) return 1;///all alignments are non-contained/contained + cc = 0; + for (i = c[1]; i != (uint32_t)-1; i = rch->bb.a[i].pidx) { + if(rg->seq[rch->bb.a[i].hid].del) cc++; + else break; + } + // ni[1] = i; + for (i = c[0]; i != (uint32_t)-1; i = rch->bb.a[i].aidx) { + if(rg->seq[rch->bb.a[i].hid].del) cc++; + else break; + } + // ni[0] = i; + if(nc + cc == m) return 1; + // assert(ni[1] > ni[0] && ni[0] != (uint32_t)-1 && ni[1] != (uint32_t)-1); + return 2; + } + return 0; +} + +static void worker_for_ul_gchains_alignment(void *data, long i, int tid) +{ + ul_vec_t *p = &(UL_INF.a[i]); + utepdat_t *s = (utepdat_t*)data; uint32_t ff; + ff = refine_rid_chain(s->rg, s->buf[tid], p, i); + // fprintf(stderr, "[M::%s::%.*s(id:%ld), len:%u] ff:%u\n", __func__, + // UL_INF.nid.a[i].n, UL_INF.nid.a[i].a, i, p->rlen, ff); + if(ff == 1) return; + // if(p->dd == 1) return; //fully aligned + // if(p->bb.n == 1 && p->bb.a[0].base) return;///no alignment + // if(p->bb.n == 0) return;///no alignment + s->hab[tid]->num_read_base++; + s->hab[tid]->num_correct_base += direct_gchain(s->buf[tid], p, &(s->ll[tid]), &(s->gdp[tid]), &(s->sps[tid]), &(s->hab[tid]->hap), s->uu, s->uopt, G_CHAIN_BW, s->opt->diff_ec_ul, UG_SKIP, i, &(s->hab[tid]->clist.chainDP), s->rg, ((ff==2)?1:0)); + // gl_chain_refine_advance(&b->olist, &b->correct, &b->hap, bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, km); +} + +static void worker_for_ctg_gchains_alignment(void *data, long i, int tid) +{ + utepdat_t *s = (utepdat_t*)data; ma_utg_t *q = &(s->ug->u.a[i]); s->rsc->a[i].bb.n = 0; + + s->hab[tid]->num_read_base++; + s->hab[tid]->num_correct_base += direct_gchain_scaf(s->buf[tid], q, &(s->ll[tid]), &(s->gdp[tid]), &(s->sps[tid]), &(s->hab[tid]->hap), s->uu, s->uopt, G_CHAIN_BW, s->opt->diff_ec_ul, UG_SKIP, i, &(s->hab[tid]->clist.chainDP), s->rg, &(s->rsc->a[i])); +} + +static void worker_for_ctg_trans_alignment(void *data, long i, int tid) +{ + ctdat_t *c = (ctdat_t*)data; + utepdat_t *s = c->s; + // ul_vec_t *q = &(c->qry_sc->a[i]); + + s->hab[tid]->num_read_base++; + s->hab[tid]->num_correct_base += direct_ctg_trans_chain(s->buf[tid], i, &(s->ll[tid]), &(s->gdp[tid]), &(s->sps[tid]), &(s->hab[tid]->hap), s->uu, s->uopt, G_CHAIN_BW, s->opt->diff_ec_ul, UG_SKIP, i, &(s->hab[tid]->clist.chainDP), + c->qry, c->qry_sc, c->ref, c->ref_sc, c->gfa, c->bub, c->ta, s->rg, c->soff, c->is_exact); +} + +void rm_dup_aln(u_trans_t *u, uint64_t u_n, asg64_v *b, double dup_cut) +{ + if(u_n <= 0) return; + uint64_t k, m, s, e, dp, old_dp, z, zs, ze, l, os, oe, ovq, cut; u_trans_t t; + b->n = 0; + for (k = 0; k < u_n; k++) { + s = u[k].qs; e = u[k].qe; u[k].occ = 0; + kv_push(uint64_t, *b, (s<<1)); + kv_push(uint64_t, *b, (e<<1|1)); + } + radix_sort_gfa64(b->a, b->a + b->n); + + for (k = dp = old_dp = m = 0, s = e = (uint64_t)-1; k < b->n; k++) { + old_dp = dp; + //if a[j] is qe + if (b->a[k]&1) --dp; + else ++dp; + + if (old_dp < 2 && dp >= 2) {///old_dp < dp, b.a[k] is qs + s = b->a[k]>>1; + } else if (old_dp >= 2 && dp < 2) {///old_dp > min_dp, b.a[k] is qe + e = b->a[k]>>1; + if(e > s) b->a[m++] = (s<<32)|e;///non-unique region + } + } + + b->n = m; + for (k = m = 0; k < u_n; k++) { + l = 0; s = u[k].qs; e = u[k].qe; + cut = (e - s)*dup_cut; + if(!(u[k].f)) {//unreliable + for (z = 0; z < b->n; z++) { + zs = (b->a[z]>>32); ze = ((uint32_t)b->a[z]); + if(zs >= e) break; + if(ze <= s) continue; + os = MAX(s, zs); oe = MIN(e, ze); + ovq = ((oe > os)? (oe - os):0); + l += ovq; + if(l > cut) break; + } + } + if(((l <= 0) || (l <= cut)) && (l < (e - s))) { + if(m != k) { t = u[m]; u[m] = u[k]; u[k] = t;} + m++; + } + } + + for (k = m; k < u_n; k++) u[k].del = 1;///delete + + for (k = b->n = 0; k < m; k++) { + dp = u[k].nw; dp <<= 32; dp |= k; kv_push(uint64_t, *b, dp); + } + radix_sort_gfa64(b->a, b->a + b->n); old_dp = 0; + for (k = 0; k < b->n; k++) { + assert(!u[((uint32_t)b->a[k])].del); + for (z = 0; z < b->n; z++) { + if(k == z) continue; + if(u[((uint32_t)b->a[z])].del) continue; + if(u[((uint32_t)b->a[k])].qs >= u[((uint32_t)b->a[z])].qs && u[((uint32_t)b->a[k])].qe <= u[((uint32_t)b->a[z])].qe) break; + } + if(z < b->n) { + u[((uint32_t)b->a[k])].del = 1; old_dp++; + } + } + + if(old_dp) { + for (k = m = 0; k < u_n; k++) { + if(u[k].del) continue; + if(m != k) { t = u[m]; u[m] = u[k]; u[k] = t;} + m++; + } + } + + + ///for debug is there is any contained overlaps in u[0, m) + for (k = 0; k < m; k++) { + for (z = 0; z < m; z++) { + if(k == z) continue; + if(u[k].qs >= u[z].qs && u[k].qe <= u[z].qe) break; + } + assert(z >= m); + } +} + +static void worker_for_ctg_trans_order(void *data, long i, int tid) +{ + ctdat_t *c = (ctdat_t*)data; utepdat_t *s = c->s; asg64_v b; + u_trans_t *a = NULL, *r_a = NULL, t; uint64_t n, r_n, k, z, m; + + if(c->mm == 0) { + copy_asg_arr(b, (s->sps[tid])); + rm_dup_aln(u_trans_a(*(c->ta), i), u_trans_n(*(c->ta), i), &b, 0.25); + copy_asg_arr((s->sps[tid]), b); + } else if(c->mm == 1) { + a = u_trans_a(*(c->ta), i); n = u_trans_n(*(c->ta), i); + for (k = 0; k < n; k++) { + if(a[k].tn < a[k].qn) continue; + r_a = u_trans_a(*(c->ta), a[k].tn); r_n = u_trans_n(*(c->ta), a[k].tn); + for(z = 0; (z < r_n) && (r_a[z].tn != a[k].qn); z++); + assert(z < r_n); + // if(a[k].del || r_a[z].del) { + // a[k].del = r_a[z].del = 1; + // } + ///discard too short overlaps + if((!a[k].f) || (!r_a[z].f)) { + if((a[k].qe - a[k].qs <= asm_opt.self_scaf_min) || (a[k].te - a[k].ts <= asm_opt.self_scaf_min)) { + a[k].del = r_a[z].del = 1; + } else if((r_a[z].qe - r_a[z].qs <= asm_opt.self_scaf_min) || (r_a[z].te - r_a[z].ts <= asm_opt.self_scaf_min)) { + a[k].del = r_a[z].del = 1; + } + } + + if(a[k].del != r_a[z].del) { + a[k].del = r_a[z].del = 0; + a[k].occ = r_a[z].occ = (uint32_t)-1; + } + } + } else { + a = u_trans_a(*(c->ta), i); n = u_trans_n(*(c->ta), i); + for (k = m = 0; k < n; k++) { + if((a[k].occ != (uint32_t)-1)) { + if(m != k) {t = a[k]; a[k] = a[m]; a[m] = t;} + m++; + } + } + radix_sort_u_trans_qs0(a, a + m); + radix_sort_u_trans_qs0(a + m, a + n); + a = a + m; n = n - m; + if(n) {//sort and merge unreliable regions + for (k = 0; k < n; k++) a[k].del = 1; + for (k = m = 0; k < n; k++) { + if((m > 0) && (a[m-1].qe >= a[k].qs)) { + if(a[k].qe > a[m-1].qe) a[m-1].qe = a[k].qe; + } else { + a[m++] = a[k]; + } + } + + for(k = m; k < n; k++) {///not useful anymore + a[k].qn = a[k].qs = a[k].qe = (uint32_t)-1; + a[k].tn = a[k].ts = a[k].te = (uint32_t)-1; + } + } + } + +} + +uint32_t inline is_rg_connect(const asg_t *rg, uint32_t v, uint32_t w) +{ + uint32_t nv = asg_arc_n(rg, v), i; + asg_arc_t *av = asg_arc_a(rg, v); + for (i = 0; i < nv; i++) { + if((!(av[i].del)) && (av[i].v == w)) return 1; + } + return 0; +} + +uint32_t refine_contain_consensus_chain(const asg_t *rg, ul_vec_t *rch, R_to_U *ri, asg64_v *bu, uint64_t ulid) +{ + bu->n = 0; + if(rch->bb.n == 1 && rch->bb.a[0].base) return bu->n;///no alignment + if(rch->bb.n == 0) return bu->n;///no alignment + uint64_t i, m, nc, occ, is_end; int64_t k, kn; + kv_resize(uint64_t, *bu, rch->bb.n); + memset(bu->a, -1, (sizeof((*(bu->a)))*rch->bb.n)); + for (k = rch->bb.n-1; k >= 0; k--) { + // if(ulid == 2 || ulid == 46 || ulid == 475 || ulid == 3274 || ulid == 3360) { + // fprintf(stderr, "[M::%s::] ulid::%lu, k::%ld, q::[%u, %u), t::[%u, %u), del::%u, pidx::%u, pconn::%u, aidx::%u, aconn::%u\n", + // __func__, ulid, k, + // rch->bb.a[k].qs, rch->bb.a[k].qe, rch->bb.a[k].ts, rch->bb.a[k].te, rg->seq[rch->bb.a[k].hid].del, + // rch->bb.a[k].pidx, + // ((rch->bb.a[k].pidx!=((uint32_t)-1))&&is_rg_connect(rg, (uint64_t)((rch->bb.a[rch->bb.a[k].pidx].hid<<1)|(rch->bb.a[rch->bb.a[k].pidx].rev)), (uint64_t)((rch->bb.a[k].hid<<1)|(rch->bb.a[k].rev))))?1:0, + // rch->bb.a[k].aidx, + // ((rch->bb.a[k].aidx!=((uint32_t)-1))&&is_rg_connect(rg, (uint64_t)((rch->bb.a[k].hid<<1)|(rch->bb.a[k].rev)),(uint64_t)((rch->bb.a[rch->bb.a[k].aidx].hid<<1)|(rch->bb.a[rch->bb.a[k].aidx].rev))))?1:0); + // } + + + + if(bu->a[k] != ((uint64_t)-1)) continue; + is_end = 0; + if((rch->bb.a[k].aidx == ((uint32_t)-1)) && (rch->bb.a[k].pidx != ((uint32_t)-1))) {///the end of a chain + is_end = 1; + } else if((rch->bb.a[k].aidx != ((uint32_t)-1)) && (rch->bb.a[k].pidx != ((uint32_t)-1))) { + if(!is_rg_connect(rg, (uint64_t)((rch->bb.a[k].hid<<1)|(rch->bb.a[k].rev)), + (uint64_t)((rch->bb.a[rch->bb.a[k].aidx].hid<<1)|(rch->bb.a[rch->bb.a[k].aidx].rev)))) { + is_end = 1; + } + } + if(!is_end) continue; + i = m = k; occ = 0; + while (i != ((uint32_t)-1)) { + //assert(bu->a[i] == ((uint64_t)-1)); + if(rg->seq[rch->bb.a[i].hid].del) { + if(occ > 1) { + bu->a[m] = occ; + // if(debug_out) { + // fprintf(stderr, "+[M::%s::] ulid::%lu, k::%ld, m::%lu, occ::%lu\n", + // __func__, ulid, k, m, occ); + // } + } + // assert(i!=m); + bu->a[i] = 0; m = (uint32_t)-1; occ = 0; + } else { + if(m == (uint32_t)-1) m = i; + bu->a[i] = 0; occ++; + } + i = rch->bb.a[i].pidx; + if(i != ((uint32_t)-1)) { + if(!is_rg_connect(rg, (uint64_t)((rch->bb.a[i].hid<<1)|(rch->bb.a[i].rev)), + (uint64_t)((rch->bb.a[rch->bb.a[i].aidx].hid<<1)|(rch->bb.a[rch->bb.a[i].aidx].rev)))) { + i = ((uint32_t)-1); + } + } + } + + if(occ > 1) { + bu->a[m] = occ; + // if(debug_out) { + // fprintf(stderr, "+[M::%s::] ulid::%lu, k::%ld, m::%lu, occ::%lu\n", + // __func__, ulid, k, m, occ); + // } + } + } + + kn = rch->bb.n; + for (k = bu->n = 0; k < kn; k++) { + if((bu->a[k] == ((uint64_t)-1)) || (bu->a[k] == 0)) continue; + i = k; occ = nc = 0; + while (i != (uint32_t)-1) { + if(rg->seq[rch->bb.a[i].hid].del) break; + + occ++; if(is_contain_r((*ri), rch->bb.a[i].hid)) nc++; + + i = rch->bb.a[i].pidx; + if(i != ((uint32_t)-1)) { + if(!is_rg_connect(rg, (uint64_t)((rch->bb.a[i].hid<<1)|(rch->bb.a[i].rev)), + (uint64_t)((rch->bb.a[rch->bb.a[i].aidx].hid<<1)|(rch->bb.a[rch->bb.a[i].aidx].rev)))) { + i = ((uint32_t)-1); + } + } + } + // for (i = k, occ = nc = 0; (i != (uint32_t)-1) && (!rg->seq[rch->bb.a[i].hid].del); i = rch->bb.a[i].pidx) { + // occ++; if(is_contain_r((*ri), rch->bb.a[i].hid)) nc++; + // } + assert(occ == bu->a[k]); + if(nc) bu->a[bu->n++] = k; + // if(debug_out) { + // if(occ != rch->bb.n) { + // fprintf(stderr, "-[M::%s::] ulid::%lu, nc::%lu, occ::%lu, k::%ld, rch->bb.n::%u\n", + // __func__, ulid, nc, occ, k, (uint32_t)rch->bb.n); + // } + // } + } + return bu->n;///# chains have contained reads +} + +uint32_t extract_ccov(ma_hit_t *in, uc_block_t *rovlp, const asg_t *rg, ul_ov_t *res, uint32_t adjust_rev, int64_t min_ovlp, int64_t max_hang) +{ + uint64_t qn, tn; int32_t r = 1; asg_arc_t e; + qn = Get_qn((*in)); tn = Get_tn((*in)); + if(rg->seq[tn].del) return 0; + + r = ma_hit2arc(in, Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &e); + if(r != MA_HT_QCONT) return 0; ///qn is contained in tn + + uint64_t ori = in->rev, ts = rovlp->ts, te = rovlp->te, tl; + if(ori) { + ts = rg->seq[qn].len - rovlp->te; + te = rg->seq[qn].len - rovlp->ts; + } + + ts += in->ts; te += in->ts; + if(te <= ts) return 0; + tl = te - ts; tl = tl*0.01; if(tl > 8) tl = 8; + if((ts >= (rg->seq[tn].len+tl)) || (te >= (rg->seq[tn].len+tl))) return 0; + if(ts > rg->seq[tn].len) ts = rg->seq[tn].len; + if(te > rg->seq[tn].len) te = rg->seq[tn].len; + if(te <= ts) return 0; + + memset(res, 0, sizeof(*res)); + res->qn = 0; res->qs = rovlp->qs; res->qe = rovlp->qe; + res->tn = tn; res->ts = ts; res->te = te; + res->el = rovlp->el; res->rev = (rovlp->rev == ori?0:1); + if(adjust_rev && res->rev) {///for linear chaining + res->ts = rg->seq[tn].len - te; + res->te = rg->seq[tn].len - ts; + } + return 1; +} + +uint32_t extract_nccov(ma_hit_t *in, uc_block_t *rovlp, const asg_t *rg, ul_ov_t *res, uint32_t adjust_rev, int64_t min_ovlp, int64_t max_hang) +{ + uint64_t tn; int64_t os, oe, s_shift, e_shift, tt, qs, qe, ts, te; + tn = Get_tn((*in)); if(rg->seq[tn].del) return 0; + os = MAX(rovlp->ts, Get_qs((*in))); + oe = MIN(rovlp->te, Get_qe((*in))); + if(oe <= os) return 0; + + ///[os, oe) -> rovlp->t* + s_shift = get_offset_adjust(os-rovlp->ts, rovlp->te-rovlp->ts, rovlp->qe-rovlp->qs); + e_shift = get_offset_adjust(rovlp->te-oe, rovlp->te-rovlp->ts, rovlp->qe-rovlp->qs); + if(rovlp->rev) { + tt = s_shift; s_shift = e_shift; e_shift = tt; + } + qs = rovlp->qs + s_shift; qe = ((int64_t)rovlp->qe)-e_shift; + if(qs >= qe) return 0; + + ///[os, oe) -> in->q* + s_shift = get_offset_adjust(os-Get_qs((*in)), Get_qe((*in))-Get_qs((*in)), Get_te((*in))-Get_ts((*in))); + e_shift = get_offset_adjust(Get_qe((*in))-oe, Get_qe((*in))-Get_qs((*in)), Get_te((*in))-Get_ts((*in))); + if(in->rev) { + tt = s_shift; s_shift = e_shift; e_shift = tt; + } + ts = Get_ts((*in)) + s_shift; te = ((int64_t)Get_te((*in)))-e_shift; + if(ts >= te) return 0; + + memset(res, 0, sizeof(*res)); + res->qn = 0; res->qs = qs; res->qe = qe; + res->tn = tn; res->ts = ts; res->te = te; + res->el = rovlp->el; res->rev = ((rovlp->rev == in->rev)?0:1); + if(adjust_rev && res->rev) {///for linear chaining + res->ts = rg->seq[tn].len - te; + res->te = rg->seq[tn].len - ts; + } + + // fprintf(stderr, "\n[M::%s::id->%u::%c] q::[%u, %u), t::[%u, %u)\n", + // __func__, rovlp->hid, "+-"[rovlp->rev], rovlp->qs, rovlp->qe, rovlp->ts, rovlp->te); + // fprintf(stderr, "+[M::%s::] qn::%u, q::[%u, %u), %c, tn::%u, t::[%u, %u)\n", + // __func__, Get_qn((*in)), Get_qs((*in)), in->qe, "+-"[in->rev], in->tn, in->ts, in->te); + // fprintf(stderr, "-[M::%s::] qn::%u, q::[%u, %u), %c, tn::%u, t::[%u, %u)\n", + // __func__, res->qn, res->qs, res->qe, "+-"[res->rev], res->tn, res->ts, res->te); + return 1; +} + + +void collect_nc_ovlps(ul_vec_t *rch, uint32_t rch_i, kv_ul_ov_t *res, const ug_opt_t *uopt, const asg_t *rg, R_to_U *ri, int64_t ulid, uint64_t *mqs, uint64_t *mqe) +{ + uint64_t i, occ, nc, k; ma_hit_t_alloc* src; + int64_t min_ovlp = uopt->min_ovlp, max_hang = uopt->max_hang; ul_ov_t p; + res->n = occ = nc = 0; (*mqs) = (*mqe) = (uint64_t)-1; + i = rch_i; + // for (i = rch_i; (i != (uint32_t)-1) && (!rg->seq[rch->bb.a[i].hid].del); i = rch->bb.a[i].pidx) { + while(i != (uint32_t)-1) { + if(rg->seq[rch->bb.a[i].hid].del) break; + // if(ulid == 442462) { + // fprintf(stderr, "\n>>>[M::%s::i->%lu::id->%u::%.*s]\n", __func__, i, rch->bb.a[i].hid, + // (int)Get_NAME_LENGTH(R_INF, rch->bb.a[i].hid), Get_NAME(R_INF, rch->bb.a[i].hid)); + // fprintf(stderr, "*[M::%s::id->%u::%.*s]\tq::[%u, %u),\tt::[%u, %u),\tis_rev::%u,\tis_cr::%u\n", + // __func__, rch->bb.a[i].hid, + // (int)Get_NAME_LENGTH(R_INF, rch->bb.a[i].hid), Get_NAME(R_INF, rch->bb.a[i].hid), + // rch->bb.a[i].qs, rch->bb.a[i].qe, rch->bb.a[i].ts, rch->bb.a[i].te, rch->bb.a[i].rev, + // !!(is_contain_r((*(ri)), rch->bb.a[i].hid))); + // } + + if(is_contain_r((*ri), rch->bb.a[i].hid)) { + src = &(uopt->sources[rch->bb.a[i].hid]); + for (k = 0; k < src->length; k++) { + if(rg->seq[Get_tn(src->buffer[k])].del) continue;///tn must exist + // if(!extract_ccov(&(src->buffer[k]), &(rch->bb.a[i]), rg, &p, 1, min_ovlp, max_hang)) continue; + // if(ulid == 442462) { + // fprintf(stderr, "+[M::%s::id->%u::%.*s]\tq::[%u, %u),\tql::%u,\tt::[%u, %u),\ttl::%u,\tis_rev::%u,\tis_cr::%u\n", + // __func__, src->buffer[k].tn, + // (int)Get_NAME_LENGTH(R_INF, src->buffer[k].tn), Get_NAME(R_INF, src->buffer[k].tn), + // Get_qs(src->buffer[k]), Get_qe(src->buffer[k]), rg->seq[Get_qn(src->buffer[k])].len, + // Get_ts(src->buffer[k]), Get_te(src->buffer[k]), rg->seq[Get_tn(src->buffer[k])].len, + // src->buffer[k].rev, !!(is_contain_r((*(ri)), src->buffer[k].tn))); + // } + if(!extract_nccov(&(src->buffer[k]), &(rch->bb.a[i]), rg, &p, 1, min_ovlp, max_hang)) continue; + // if(ulid == 442462) { + // fprintf(stderr, "-[M::%s::id->%u::%.*s]\tq::[%u, %u),\tt::[%u, %u),\tis_rev::%u,\tis_cr::%u\n", + // __func__, p.tn, (int)Get_NAME_LENGTH(R_INF, p.tn), Get_NAME(R_INF, p.tn), + // p.qs, p.qe, p.ts, p.te, p.rev, !!(is_contain_r((*(ri)), p.tn))); + // // fprintf(stderr, "cc[M::%s::id->%u::%.*s] q::[%u, %u), t::[%u, %u), is_cr::%u, del::%u\n", + // // __func__, p.tn, (int)Get_NAME_LENGTH(R_INF, p.tn), Get_NAME(R_INF, p.tn), + // // p.qs, p.qe, p.ts, p.te, !!(is_contain_r((*(ri)), p.tn)), rg->seq[p.tn].del); + // } + p.el = 0; p.tn <<= 1; p.tn |= p.rev; p.qn = i;//for linear chain + kv_push(ul_ov_t, *res, p); + } + nc++; + } + ///push itself into the chain + memset(&p, 0, sizeof(p)); + p.qn = 0; p.qs = rch->bb.a[i].qs; p.qe = rch->bb.a[i].qe; + p.tn = rch->bb.a[i].hid; p.ts = rch->bb.a[i].ts; p.te = rch->bb.a[i].te; + p.el = 1; p.rev = rch->bb.a[i].rev; + if(p.rev) {///for linear chaining + p.ts = rg->seq[p.tn].len - rch->bb.a[i].te; + p.te = rg->seq[p.tn].len - rch->bb.a[i].ts; + } + p.el = 1; p.tn <<= 1; p.tn |= p.rev; p.qn = i;//for linear chain + kv_push(ul_ov_t, *res, p); + if(((*mqs) == ((uint64_t)-1)) || ((*mqs) > rch->bb.a[i].qs)) (*mqs) = rch->bb.a[i].qs; + if(((*mqe) == ((uint64_t)-1)) || ((*mqe) < rch->bb.a[i].qe)) (*mqe) = rch->bb.a[i].qe; + occ++; + + i = rch->bb.a[i].pidx; + if(i != ((uint32_t)-1)) { + if(!is_rg_connect(rg, (uint64_t)((rch->bb.a[i].hid<<1)|(rch->bb.a[i].rev)), + (uint64_t)((rch->bb.a[rch->bb.a[i].aidx].hid<<1)|(rch->bb.a[rch->bb.a[i].aidx].rev)))) { + i = ((uint32_t)-1); + } + } + } + assert(occ > 1 && nc > 0); +} + + +inline int64_t comput_rlinear_sc(ul_ov_t *li, ul_ov_t *lj, int64_t jidx, int32_t *bq, int32_t *bt, double diff_ec_ul, int64_t bw) +{ ///li is the suffix of lj; sorted by qe, so li->qe >= lj->qe, so li->te >= lj->te + if(li->te < lj->te) return INT32_MIN; + int64_t dq, dt, dd, mm, os, oe; + oe = MIN((li->qe), (lj->qe)); os = MAX((li->qs), (lj->qs)); + if(oe <= os) return INT32_MIN; + oe = MIN((li->te), (lj->te)); os = MAX((li->ts), (lj->ts)); + if(oe <= os) return INT32_MIN; + + dq = li->qe - lj->qs; dt = li->te - lj->ts; + dd = (dq>dt? dq-dt:dt-dq); + mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; + if(dd > mm) return INT32_MIN; + dq = (int64_t)li->qe - bq[jidx]; + dt = (int64_t)li->te - bt[jidx]; + if(dq < ((int64_t)(li->qe - li->qs))) dq = li->qe - li->qs; + if(dt < ((int64_t)(li->te - li->ts))) dt = li->te - li->ts; + return MIN(dq, dt); +} + +uint64_t linear_rchain_dp_adv(ul_ov_t *ch, int64_t ch_n, ul_ov_t *sv, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, int64_t max_skip, int64_t max_iter, int64_t max_dis, Chain_Data* dp, const asg_t *rg, int64_t ulid) +{ ///all in[].el must be 1 + if(ch_n == 0) return 0; + int64_t i, j, k, sc, csc, mm_sc, mm_idx, its, ite, max; int32_t *f, *bq, *bt; + ul_ov_t *li = NULL, *lj = NULL; int64_t *p, *t, st, plus, max_ii, n_skip, end_j; + resize_Chain_Data(dp, ch_n, NULL); + t = dp->tmp; f = dp->score; p = dp->pre; bq = dp->indels; bt = dp->self_length; + + radix_sort_ul_ov_srt_qe(ch, ch + ch_n); + for (i = 1, j = 0; i <= ch_n; i++) { + if (i == ch_n || ch[i].qe != ch[j].qe) { + if(i - j > 1) radix_sort_ul_ov_srt_qs(ch+j, ch+i); + j = i; + } + } + + memset(t, 0, (ch_n*sizeof((*t)))); + for (i = st = plus = 0, max_ii = -1; i < ch_n; ++i) { + li = &(ch[i]); csc = MIN((li->qe-li->qs), (li->te-li->ts)); + mm_sc = /**csc**/-1; mm_idx = -1; n_skip = 0; end_j = -1; + st = (i= st; --j) { + lj = &(ch[j]); + if(lj->qe <= li->qs) break; + sc = comput_rlinear_sc(li, lj, j, bq, bt, diff_ec_ul, bw); ///should allow contain + if(sc == INT32_MIN) continue; + if(sc > mm_sc) { + mm_sc = sc, mm_idx = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == i) { + if (++n_skip > max_skip) + break; + } + if (p[j] >= 0) t[p[j]] = i; + } + end_j = j; + if (max_ii < 0 || (ch[i].qe>(ch[max_ii].qe+max_dis))) {//too long + max = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && (ch[i].qe<=(max_dis+ch[j].qe)); --j) { + if (max < f[j]) { + max = f[j], max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + lj = &(ch[max_ii]); + if(lj->qe > li->qs) { + sc = comput_rlinear_sc(li, lj, max_ii, bq, bt, diff_ec_ul, bw); ///should allow contain + if(sc != INT32_MIN) { + if(sc > mm_sc) { + mm_sc = sc; mm_idx = max_ii; + } + } + } + } + + if(mm_idx < 0) mm_sc = csc; + f[i] = mm_sc; p[i] = mm_idx; + bq[i] = li->qs; bt[i] = li->ts; + if(mm_idx >= 0) { + if(bq[i] > bq[mm_idx]) bq[i] = bq[mm_idx]; + if(bt[i] > bt[mm_idx]) bt[i] = bt[mm_idx]; + } + + if ((max_ii < 0) || ((ch[i].qe<=max_dis+ch[max_ii].qe) && (f[max_ii]sec = (mm_idx<0?0x3FFFFFFF:i-mm_idx); sv[i] = *li; + // if(ulid == 442462) { + // fprintf(stderr, "[M::%s::id->%u::%.*s]\tq::[%u, %u),\tt::[%u, %u),\tis_rev::%u\n", + // __func__, li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), + // li->qs, li->qe, li->ts, li->te, li->rev); + // } + + } + // radix_sort_gfa64i + for (i = 0; i < ch_n; ++i) { + t[i] = ((uint64_t)f[i])<<32; t[i] += i; bt[i] = 0; + } + radix_sort_gfa64i(t, t+ch_n); + int64_t n_u, z; + for (z = ch_n-1, n_u = 0; z >= 0; --z) { + k = (uint32_t)t[z]; + if(bt[k]) continue; + i = k; ch[n_u]=sv[i]; sc = f[i]; + for (;i>=0;) { + if(sv[i].qs < ch[n_u].qs) ch[n_u].qs = sv[i].qs; + if(sv[i].ts < ch[n_u].ts) ch[n_u].ts = sv[i].ts; + if(sv[i].qe > ch[n_u].qe) ch[n_u].qe = sv[i].qe; + if(sv[i].te > ch[n_u].te) ch[n_u].te = sv[i].te; + // ch[n_u].qn = i;//start idx of read alignment in chain + bt[i] = 1; i = p[i]; + } + adjust_rev_tse(&(ch[n_u]), rg->seq[ch[n_u].tn].len, &its, &ite); + ch[n_u].ts = its; ch[n_u].te = ite; ch[n_u].sec = (sc>0x3FFFFFFF?0x3FFFFFFF:sc); + ch[n_u].qn = 0; + n_u++; + } + return n_u; +} + + +void gen_linear_rchains(kv_ul_ov_t *res, kv_ul_ov_t *buf, const asg_t *rg, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, Chain_Data* dp, int64_t ulid) +{ + uint64_t k, l, z, an, m, bn = buf->n; + radix_sort_ul_ov_srt_tn(res->a, res->a + res->n); + ///after this function, res keeps unitig alignment, while buf keeps read alignments + for (k = 1, l = m = 0; k <= res->n; k++) { + if(k == res->n || res->a[k].tn != res->a[l].tn) {///qn <- (tn|rev) + for (z = l; z < k; z++) res->a[z].tn>>=1; + kv_resize(ul_ov_t, *buf, bn+k-l); + an = l + linear_rchain_dp_adv(res->a+l, k-l, buf->a+bn, uopt, bw, diff_ec_ul, qlen, + UG_SKIP_N, UG_ITER_N, UG_DIS_N, dp, rg, ulid); + for (z = l; z < an; z++) res->a[m++] = res->a[z]; + l = k; + } + } + res->n = m; + // kv_resize(ul_ov_t, *buf, bn+res->n); + // int64_t iqs, iqe, its, ite; + // for (k = 0, z = bn; k < res->n; k++) { + // buf->a[z] = res->a[k]; res->a[k].qn = z; + // extend_end_coord(NULL, &(res->a[k]), qlen, rg->seq[res->a[k].tn].len, &iqs, &iqe, &its, &ite); + // res->a[k].qs = iqs; res->a[k].qe = iqe; res->a[k].ts = its; res->a[k].te = ite; + // z++; + // } +} + +int64_t gconnect_test(const asg_t *g, uint32_t v, uint32_t w, int64_t bw, double diff_ec_ul, int64_t dq) +{ + int64_t dt = -1, dif, mm; + uint32_t nv, i; asg_arc_t *av = NULL; ///ma_hit_t *x = NULL; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (i = 0; i < nv; i++) { + if(av[i].del || av[i].v != w) continue; + dt = av[i].ol; + break; + } + + if(dt < 0) return 0; + dif = (dq>dt? dq-dt:dt-dq); + mm = MAX(dq, dt); mm *= diff_ec_ul; if(mm < bw) mm = bw; + if(dif <= mm) return 1; + return 0; +} + +uint64_t gen_cns_chain_linear(ul_ov_t *a, int64_t a_n, /**ul_ov_t *ab,**/ const asg_t *rg, R_to_U *ri, int64_t qlen, int64_t bw, double diff_thre, Chain_Data* dp, +int64_t max_skip, int64_t max_iter, int64_t max_dis, uint64_t mqs, uint64_t mqe, uint64_t ulid) +{ + if(a_n == 0) return 0; + uint32_t li_v, lj_v; int32_t *f, *c_n, *len; int64_t *p, *t, st, max_ii, max, qo, cL, sn, ln, csn, mm_sn, cln, mm_ln; + int64_t mm_ovlp, x, i, j, sc, csc, mm_sc, mm_idx, n_skip, end_j, ch_sc, cn_sn, ch_ln, ch_i; ul_ov_t *li, *lj; + resize_Chain_Data(dp, a_n, NULL); + t = dp->tmp; f = dp->score; p = dp->pre; c_n = dp->occ; len = dp->indels; + + radix_sort_ul_ov_srt_qe(a, a + a_n); + for (i = 1, j = 0; i <= a_n; i++) { + if (i == a_n || a[i].qe != a[j].qe) { + if(i - j > 1) radix_sort_ul_ov_srt_qs(a+j, a+i); + j = i; + } + } + + memset(t, 0, (a_n*sizeof((*t)))); + ch_sc = ch_i = cn_sn = INT32_MIN; ch_ln = INT32_MAX; + for (i = st = 0, max_ii = -1; i < a_n; ++i) { + li = &(a[i]); + mm_ovlp = max_ovlp(rg, ((li->tn<<1)|li->rev)^1); + x = (li->qs + mm_ovlp)*diff_thre; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(i, a, x+G_CHAIN_INDEL); + + csc = 0; csn = 1; cln = 0; + if(is_contain_r((*ri), li->tn)) {csc = -1; csn = 0; cln = rg->seq[li->tn].len;} + mm_sc = INT32_MIN+1; mm_sn = INT32_MIN+1; mm_ln = INT32_MAX; + mm_idx = -1; n_skip = 0; end_j = -1; + + li_v = (li->tn<<1)|li->rev; li_v ^= 1; + if ((x-st) > max_iter) st = x-max_iter; + for (j = x; j >= st; --j) { // collect potential destination vertices + lj = &(a[j]); + if(lj->qe+G_CHAIN_INDEL <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore + if(f[j] == INT32_MIN) continue;///could not reach the left end + sc = sn = ln = INT32_MIN; + if(lj->qs <= li->qs && lj->qe <= li->qe) {///not contained + lj_v = (lj->tn<<1)|lj->rev; lj_v ^= 1; + qo = infer_rovlp(li, lj, NULL, NULL, NULL, NULL); + if(gconnect_test(rg, li_v, lj_v, bw, diff_thre, qo)) { + sc = f[j] + csc; sn = c_n[j] + csn; ln = len[j] + cln; + } + } + if(sc == INT32_MIN) continue; + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_sn)) || + ((sc == mm_sc) && (sn == mm_sn) && (ln < mm_ln))) { + mm_sc = sc, mm_idx = j, mm_sn = sn, mm_ln = ln; + if (n_skip > 0) --n_skip; + } else if (t[j] == i) { + if (++n_skip > max_skip) break; + } + if (p[j] >= 0) t[p[j]] = i; + } + + end_j = j; + if (max_ii < 0 || (a[i].qe > (a[max_ii].qe+max_dis))) {//too long + max = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && (a[i].qe<=(max_dis+a[j].qe)); --j) { + if (max < f[j]) { + max = f[j], max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + lj = &(a[max_ii]); + if(((lj->qe+G_CHAIN_INDEL)>li->qs) && (lj->qs<=li->qs) && (lj->qe<=li->qe) && (f[max_ii]!=INT32_MIN)) { + lj_v = (lj->tn<<1)|lj->rev; lj_v ^= 1; sc = sn = ln = INT32_MIN; + qo = infer_rovlp(li, lj, NULL, NULL, NULL, NULL); + if(gconnect_test(rg, li_v, lj_v, bw, diff_thre, qo)) { + sc = f[max_ii] + csc; sn = c_n[max_ii] + csn; ln = len[max_ii] + cln; + } + if(sc != INT32_MIN) { + if((sc > mm_sc) || ((sc == mm_sc) && (sn > mm_sn)) || + ((sc == mm_sc) && (sn == mm_sn) && (ln < mm_ln))) { + mm_sc = sc, mm_idx = max_ii, mm_sn = sn, mm_ln = ln; + } + } + } + } + + if((mm_idx == -1) && (((int64_t)li->qs) > ((int64_t)(mqs+bw)))) { + mm_sc = mm_idx = mm_sn = INT32_MIN; mm_ln = INT32_MAX; + } + if((mm_sc==(INT32_MIN+1))) { + mm_sc = csc; mm_sn = csn; mm_ln = cln; + } + + + f[i] = mm_sc; p[i] = mm_idx; c_n[i] = mm_sn; len[i] = mm_ln; + if ((max_ii < 0) || ((a[i].qe<=max_dis+a[max_ii].qe) && (f[max_ii]=((int64_t)(mqe)))) { + if((mm_sc > ch_sc) || ((mm_sc == ch_sc) && (mm_sn > cn_sn)) || + ((mm_sc == ch_sc) && (mm_sn == cn_sn) && (mm_ln < ch_ln))) { + ch_sc = mm_sc; ch_i = i; cn_sn = mm_sn; ch_ln = mm_ln; + } + } + // if(ulid == 442462) { + // fprintf(stderr, "[M::%s::id->%u::%.*s] i::%ld, q::[%u, %u), t::[%u, %u), is_cr::%u, mm_idx::%ld, end::%u\n", + // __func__, li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), i, + // li->qs, li->qe, li->ts, li->te, !!(is_contain_r((*ri), li->tn)), mm_idx, !!(((int64_t)(a[i].qe+bw))>=((int64_t)(mqe)))); + // } + } + // if(ulid == 442462) { + // fprintf(stderr, "[M::%s::] ch_i::%ld, mqs::%lu, mqe::%lu\n", + // __func__, ch_i, mqs, mqe); + // } + if(ch_i == INT32_MIN) return 0; + + i = ch_i; cL = 0; + while (i >= 0) {t[cL++] = i; i = p[i];} + for (i = 0; i < cL; i++) a[i] = a[t[cL-i-1]]; + return cL; +} + +void gen_contain_consensus_chain(ul_vec_t *rch, uint32_t rch_i, kv_ul_ov_t *idx, kv_ul_ov_t *dump, +const ug_opt_t *uopt, const asg_t *rg, R_to_U *ri, int64_t bw, double diff_ec_ul, int64_t ulid, Chain_Data* dp) +{ + uint64_t dn = dump->n, i, mqs, mqe; int64_t iqs, iqe, its, ite; idx->n = 0; + collect_nc_ovlps(rch, rch_i, idx, uopt, rg, ri, ulid, &mqs, &mqe); + // assert(idx->n > 1); assert((mqs != ((uint64_t)-1)) && (mqe != ((uint64_t)-1)) && (mqe > mqs)); + if((idx->n <= 1) || (mqs == ((uint64_t)-1)) || (mqe == ((uint64_t)-1)) || (mqe <= mqs)) return; + + gen_linear_rchains(idx, dump, rg, uopt, bw, diff_ec_ul, rch->rlen, dp, ulid); + assert(idx->n); + idx->n = gen_cns_chain_linear(idx->a, idx->n, /**dump->a+dn,**/ rg, ri, rch->rlen, bw, diff_ec_ul, dp, UG_SKIP_N, UG_ITER_N, UG_DIS_N, mqs, mqe, ulid); + // fprintf(stderr, "[M::%s::] idx->n::%u, mqs::%lu, mqe::%lu\n", __func__, (uint32_t)idx->n, mqs, mqe); + if(idx->n) { + kv_resize(ul_ov_t, *dump, dn + idx->n); + ///mask existing overlaps + for (i = rch_i; (i != (uint32_t)-1) && (!rg->seq[rch->bb.a[i].hid].del); i = rch->bb.a[i].pidx) { + dump->a[i].tn = dump->a[i].qn = (uint32_t)-1; + } + for (i = 0; i < idx->n; i++) { + dump->a[dn] = idx->a[i]; + extend_end_coord(NULL, &(dump->a[dn]), rch->rlen, rg->seq[dump->a[dn].tn].len, &iqs, &iqe, &its, &ite); + dump->a[dn].qs = iqs; dump->a[dn].qe = iqe; dump->a[dn].ts = its; dump->a[dn].te = ite; + dump->a[dn].qn = ((i>0)?(dn-1):((uint32_t)-1)); dn++; + } + dump->n = dn; + } +} + +uint32_t update_consensus_chain(const ug_opt_t *uopt, const asg_t *rg, kv_ul_ov_t *idx, kv_ul_ov_t *dump, ul_vec_t *rch, asg64_v *b, R_to_U *ri) +{ + uint64_t *idm, k, l, kn, dn, cc = 0; + assert(dump->n >= rch->bb.n); + kv_resize(uint64_t, *b, dump->n); idm = b->a; + + for (k = kn = 0; k < rch->bb.n; k++) { + idm[k] = (uint64_t)-1; + if((dump->a[k].qn == ((uint32_t)-1)) && (dump->a[k].tn == ((uint32_t)-1))) continue; + dump->a[k].qn = rch->bb.a[dump->a[k].qn].pidx; idm[k] = kn; kn++; + } + for (; k < dump->n; k++) { + idm[k] = kn; kn++; + } + // fprintf(stderr, "[M::%s::kn->%lu] dump->n::%u\n", __func__, kn, (uint32_t)dump->n); + + dn = dump->n; dump->n = 0; + kv_resize(ul_ov_t, *idx, kn); idx->n = 0; + for (k = 0; k < dn; k++) { + if(idm[k] == ((uint64_t)-1)) continue; + dump->a[idm[k]] = dump->a[k]; kn--; dump->n++; + if(dump->a[idm[k]].qn != ((uint32_t)-1)) { + dump->a[idm[k]].qn = (uint32_t)idm[dump->a[idm[k]].qn]; + } + kv_push(ul_ov_t, *idx, dump->a[idm[k]]); idx->a[idx->n-1].qn = idm[k]; + } + assert(kn == 0); + + radix_sort_ul_ov_srt_qe(idx->a, idx->a + idx->n); + for (k = 1, l = 0; k <= idx->n; k++) { + if (k == idx->n || idx->a[l].qe != idx->a[k].qe) { + if(k - l > 1) radix_sort_ul_ov_srt_qs(idx->a+l, idx->a+k); + l = k; + } + } + for (k = 0; k < idx->n; k++) dump->a[idx->a[k].qn].tn = k; + + for (k = 0; k < idx->n; k++) { + idx->a[k].qn = ((dump->a[idx->a[k].qn].qn!=((uint32_t)-1))? + (dump->a[dump->a[idx->a[k].qn].qn].tn):((uint32_t)-1)); + idx->a[k].el = 1; + } + + uc_block_t *z, *p; int64_t tt; + kv_resize(uc_block_t, rch->bb, idx->n); rch->bb.n = 0; + for (k = 0; k < idx->n; k++) { + // fprintf(stderr, "+k::%lu[M::%s::id->%u] q::[%u, %u), t::[%u, %u), is_cr::%u\n", + // k, __func__, idx->a[k].tn, idx->a[k].qs, idx->a[k].qe, idx->a[k].ts, idx->a[k].te, + // !!(is_contain_r((*ri), idx->a[k].tn))); + kv_pushp(uc_block_t, rch->bb, &z); memset(z, 0, sizeof((*z))); + z->hid = idx->a[k].tn; z->rev = idx->a[k].rev; + z->pchain = 1; z->base = 0; z->el = 1; + z->qs = idx->a[k].qs; z->qe = idx->a[k].qe; + z->te = idx->a[k].te; z->ts = idx->a[k].ts; + z->pidx = idx->a[k].qn; z->pdis = z->aidx = (uint32_t)-1; + + } + for (k = cc = 0; k < rch->bb.n; k++) { + if(is_contain_r((*ri), rch->bb.a[k].hid)) cc++; + // fprintf(stderr, "-k::%lu[M::%s::id->%u] q::[%u, %u), t::[%u, %u), is_cr::%u\n", + // k, __func__, rch->bb.a[k].hid, rch->bb.a[k].qs, rch->bb.a[k].qe, rch->bb.a[k].ts, rch->bb.a[k].te, + // !!(is_contain_r((*ri), rch->bb.a[k].hid))); + if(rch->bb.a[k].pidx == (uint32_t)-1) continue; + z = &(rch->bb.a[k]); p = &(rch->bb.a[z->pidx]); + assert(p->aidx == (uint32_t)-1); p->aidx = k; + tt = g_adjacent_dis_mul(NULL, uopt->sources, uopt->max_hang, uopt->min_ovlp, ((z->hid<<1)|((uint32_t)z->rev))^1, ((p->hid<<1)|((uint32_t)p->rev))^1); + if(tt >= 0) z->pdis = tt; ///assert(tt >= 0); + } + + ///debug_ssb + // for (k = 0; k < rch->bb.n; k++) { + // if(rch->bb.a[k].pidx != (uint32_t)-1) { + // if((rch->bb.a[k].pidx >= 0) && (rch->bb.a[k].pidx < rch->bb.n) && + // (rch->bb.a[rch->bb.a[k].pidx].aidx == k)) { + // ; + // } else { + // fprintf(stderr, "[M::%s::k->%lu] +rch->bb.n::%u\n", __func__, k, (uint32_t)rch->bb.n); + // for (l = 0; l < rch->bb.n; l++) { + // fprintf(stderr, "[M::%.*s::k->%lu] q::[%u, %u), t::[%u, %u), is_cr::%u, pidx::%u, aidx::%u\n", + // (int)Get_NAME_LENGTH(R_INF, rch->bb.a[l].hid), Get_NAME(R_INF, rch->bb.a[l].hid), l, + // rch->bb.a[l].qs, rch->bb.a[l].qe, rch->bb.a[l].ts, rch->bb.a[l].te, + // !!(is_contain_r((*ri), rch->bb.a[l].hid)), + // rch->bb.a[l].pidx, rch->bb.a[l].aidx); + // } + // exit(1); + // } + // } + + // if(rch->bb.a[k].aidx != (uint32_t)-1) { + // if((rch->bb.a[k].aidx >= 0) && (rch->bb.a[k].aidx < rch->bb.n) && + // (rch->bb.a[rch->bb.a[k].aidx].pidx == k)) { + // ; + // } else { + // fprintf(stderr, "[M::%s::k->%lu] -rch->bb.n::%u\n", __func__, k, (uint32_t)rch->bb.n); + // for (l = 0; l < rch->bb.n; l++) { + // fprintf(stderr, "[M::%.*s::k->%lu] q::[%u, %u), t::[%u, %u), is_cr::%u, pidx::%u, aidx::%u\n", + // (int)Get_NAME_LENGTH(R_INF, rch->bb.a[l].hid), Get_NAME(R_INF, rch->bb.a[l].hid), l, + // rch->bb.a[l].qs, rch->bb.a[l].qe, rch->bb.a[l].ts, rch->bb.a[l].te, + // !!(is_contain_r((*ri), rch->bb.a[l].hid)), + // rch->bb.a[l].pidx, rch->bb.a[l].aidx); + // } + // exit(1); + // } + // } + // } + + return ((cc==0)?1:0); +} + +static void worker_for_contain_consensus(void *data, long i, int tid) +{ + ul_vec_t *p = &(UL_INF.a[i]); asg64_v b0; + utepdat_t *s = (utepdat_t*)data; uint32_t ff, k; + + // if(i != 304) return; + copy_asg_arr(b0, s->ll[tid].srt.a); + ff = refine_contain_consensus_chain(s->rg, p, s->uopt->ruIndex, &b0, i); + copy_asg_arr(s->ll[tid].srt.a, b0); + // fprintf(stderr, "[M::%s::%.*s(id:%ld), len:%u] ff:%u\n", __func__, + // UL_INF.nid.a[i].n, UL_INF.nid.a[i].a, i, p->rlen, ff); + // if(debug_out) { + // for (k = 0; k < p->bb.n; k++) { + // fprintf(stderr, "[M::%.*s] q::[%u, %u), t::[%u, %u), is_cr::%u, pidx::%u, aidx::%u\n", + // (int)Get_NAME_LENGTH(R_INF, p->bb.a[k].hid), Get_NAME(R_INF, p->bb.a[k].hid), + // p->bb.a[k].qs, p->bb.a[k].qe, p->bb.a[k].ts, p->bb.a[k].te, + // !!(is_contain_r((*(s->uopt->ruIndex)), p->bb.a[k].hid)), p->bb.a[k].pidx, p->bb.a[k].aidx); + // } + // fprintf(stderr, "***[M::%s::%.*s(id:%ld), len:%u] ff:%u, sp_chn::%u, p->bb.n::%u\n\n", __func__, + // UL_INF.nid.a[i].n, UL_INF.nid.a[i].a, i, p->rlen, ff, (uint32_t)s->ll[tid].srt.a.n, (uint32_t)p->bb.n); + // } + if(!ff) return; + + // char *as = NULL; + // asprintf(&as, "\n[M::%s]\trid::%ld\tlen::%lu\tname::%.*s\tb0.n::%u\n", + // __func__, s->id+i, s->len[i], (int32_t)UL_INF.nid.a[s->id+i].n, UL_INF.nid.a[s->id+i].a, (uint32_t)b0.n); + // push_vlog(&(overall_zdbg->a[s->id+i]), as); free(as); as = NULL; + + + + kv_ul_ov_t *idx = &(s->ll[tid].lo), *dump = &(s->ll[tid].tk); ul_ov_t *z; + // if(p->dd == 1) return; //fully aligned + // if(p->bb.n == 1 && p->bb.a[0].base) return;///no alignment + // if(p->bb.n == 0) return;///no alignment + s->hab[tid]->num_read_base++; + + // if(i == 442462) { + // fprintf(stderr, "\n[M::%s::%.*s(id:%ld), len:%u] ff:%u, sp_chn::%u, p->bb.n::%u\n", __func__, + // UL_INF.nid.a[i].n, UL_INF.nid.a[i].a, i, p->rlen, ff, (uint32_t)s->ll[tid].srt.a.n, (uint32_t)p->bb.n); + // } + + // fprintf(stderr, "[M::%s]\tp->bb.n::%u\n", __func__, (uint32_t)p->bb.n); + kv_resize(ul_ov_t, *dump, p->bb.n); + for (k = dump->n = 0; k < p->bb.n; k++) { + z = &(dump->a[dump->n++]); ///memset(z, 0, sizeof((*z))); + z->qn = k; z->qs = p->bb.a[k].qs; z->qe = p->bb.a[k].qe; + z->tn = p->bb.a[k].hid; z->ts = p->bb.a[k].ts; z->te = p->bb.a[k].te; + z->el = 1; z->rev = p->bb.a[k].rev; z->sec = 0; + // if(i == 442462) { + // fprintf(stderr, "[M::%s::id->%u::%.*s] q::[%u, %u), t::[%u, %u), is_rev::%u, is_cr::%u\n", + // __func__, z->tn, (int)Get_NAME_LENGTH(R_INF, z->tn), Get_NAME(R_INF, z->tn), + // z->qs, z->qe, z->ts, z->te, z->rev, !!(is_contain_r((*(s->uopt->ruIndex)), z->tn))); + // } + } + + for (k = 0; k < s->ll[tid].srt.a.n; k++) { + gen_contain_consensus_chain(p, s->ll[tid].srt.a.a[k], idx, dump, s->uopt, s->rg, s->uopt->ruIndex, G_CHAIN_BW, s->opt->diff_ec_ul, i, &(s->hab[tid]->clist.chainDP)); + } + + copy_asg_arr(b0, s->ll[tid].srt.a); + ff = update_consensus_chain(s->uopt, s->rg, idx, dump, p, &b0, s->uopt->ruIndex); + copy_asg_arr(s->ll[tid].srt.a, b0); + s->hab[tid]->num_correct_base += ff; + // fprintf(stderr, "[M::%s::%.*s(id:%ld), len:%u] ffa->%u, sp_chn::%u\n", __func__, + // UL_INF.nid.a[i].n, UL_INF.nid.a[i].a, i, p->rlen, ff, (uint32_t)s->ll[tid].srt.a.n); + + // s->hab[tid]->num_correct_base += direct_gchain(s->buf[tid], p, &(s->ll[tid]), &(s->gdp[tid]), &(s->sps[tid]), &(s->hab[tid]->hap), s->uu, s->uopt, G_CHAIN_BW, s->opt->diff_ec_ul, UG_SKIP, i, &(s->hab[tid]->clist.chainDP), s->rg, ((ff==2)?1:0)); + // gl_chain_refine_advance(&b->olist, &b->correct, &b->hap, bl, s->uu, s->opt->diff_ec_ul, winLen, s->len[i], s->uopt, s->id+i, km); +} + +uint32_t extract_contain_tig(asg_t *g, uint64_t v0, R_to_U *ri, uint64_t offset, uint64_t must_tip, kv_ul_ov_t *res) +{ + uint32_t v = v0, w, kv, kw, is_tip = 0, l = offset; + ul_ov_t p; memset(&p, 0, sizeof(p)); + + while (1) { + if(!is_contain_r((*ri), (v>>1))) return 0; + kv = get_arcs(g, v, &w, 1); + if(kv > 1) return 0; + + p.qn = 0; p.qs = l; p.qe = l + g->seq[v>>1].len; + p.tn = v>>1; p.ts = 0; p.te = g->seq[v>>1].len; + p.el = 0; p.rev = v&1; kv_push(ul_ov_t, *res, p); + + if(kv == 0) {is_tip = 1; break;} + + l += asg_arc_len(g->arc[w]); + w = g->arc[w].v; + ///kv must be 1 here + kw = get_arcs(g, w^1, NULL, 0); + assert(kw >= 1); + if(kw > 1) { + p.qn = 0; p.qs = l; p.qe = l + g->seq[w>>1].len; + p.tn = w>>1; p.ts = 0; p.te = g->seq[w>>1].len; + p.el = 1; p.rev = w&1; kv_push(ul_ov_t, *res, p); + break; + } + v = w; + if(v == v0) return 0; + } + if((must_tip) && (!is_tip)) return 0; + return 1; +} + +uint32_t gen_dup_path(const asg_t *g, R_to_U *ri, kv_ul_ov_t *res, uint64_t v) +{ + asg_t *rg = (asg_t *)g; res->n = 0; + if(rg->seq[v>>1].del) return res->n; + uint64_t nv = asg_arc_n(rg, v); asg_arc_t *av = asg_arc_a(rg, v); + uint64_t k, kv, w = (uint64_t)-1, kw, l, rn, z; ul_ov_t p; memset(&p, 0, sizeof(p)); + + // for (k = 0; k < nv; k++) { + // if(av[k].del) continue; + // asg_arc_t *aw = asg_arc_a(rg, av[k].v); + // uint64_t nw = asg_arc_n(rg, av[k].v); + // for (l = 0; l < nw; l++) { + // if(aw[l].del) continue; + // for (rn = 0; rn < nv; rn++) { + // if(av[rn].del) continue; + // if(av[rn].v == aw[l].v) break; + // } + // if(rn < nv) { + // fprintf(stderr, "[M::%s] v0::%lu, w::%u, v1::%u\n", __func__, v, av[k].v, aw[l].v); + // } + // } + // } + + + + + for (k = kv = 0; k < nv && kv < 2; k++) { + if(!(av[k].del)) kv++; + } + // if(v == 7723) { + // fprintf(stderr, "[M::%s] v0::%lu, kv::%lu\n", __func__, v, kv); + // } + if(kv > 1) { + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + w = av[k].v; kw = get_arcs(rg, w^1, NULL, 0); + // if(v == 7723) { + // fprintf(stderr, "*[M::%s] v0::%lu, av[%lu].v::%u, kw::%lu,\n", __func__, v, k, av[k].v, kw); + // } + if(kw > 1) {///kv > 1 && kw > 1 + if((v>>1) != (w>>1)) {///cannot handle if the prefix and suffix nodes are the same + l = 0; + p.qn = 0; p.qs = l; p.qe = l + rg->seq[v>>1].len; + p.tn = v>>1; p.ts = 0; p.te = rg->seq[v>>1].len; + p.el = 1; p.rev = v&1; kv_push(ul_ov_t, *res, p); + // if(v == 7723) { + // fprintf(stderr, "*[M::%s] v0::%lu, p.tn::%u, p.rev::%u\n", __func__, v, p.tn, p.rev); + // } + + l += asg_arc_len(av[k]); + p.qn = 0; p.qs = l; p.qe = l + rg->seq[w>>1].len; + p.tn = w>>1; p.ts = 0; p.te = rg->seq[w>>1].len; + p.el = 1; p.rev = w&1; kv_push(ul_ov_t, *res, p); + + // if(v == 7723) { + // fprintf(stderr, "*[M::%s] v0::%lu, p.tn::%u, p.rev::%u\n", __func__, v, p.tn, p.rev); + // } + + p.tn = (uint32_t)-1; p.qn = ((uint64_t)(av-g->arc+k)); + kv_push(ul_ov_t, *res, p); + } + } else if((kw == 1) && (is_contain_r((*ri), (w>>1)))) {///kv > 1 && kw == 1 && w is contained + rn = res->n; l = 0; + p.qn = 0; p.qs = l; p.qe = l + rg->seq[v>>1].len; + p.tn = v>>1; p.ts = 0; p.te = rg->seq[v>>1].len; + p.el = 1; p.rev = v&1; kv_push(ul_ov_t, *res, p); + l += asg_arc_len(av[k]); + if(!extract_contain_tig(rg, w, ri, l, 0, res)) { + res->n = rn; + } else { + for (z = rn+1; z < res->n; z++) { + if(res->a[z].tn == (v>>1)) break; + } + if(z >= res->n) {///cannot handle circles + p.tn = (uint32_t)-1; p.qn = ((uint64_t)(av-g->arc+k)); + kv_push(ul_ov_t, *res, p); + } else { + res->n = rn; + } + } + } + } + } else if(((kv == 1) || (kv == 0)) && (!get_arcs(rg, v^1, NULL, 0)) && (is_contain_r((*ri), (v>>1)))) { + ///1. kv == 1 && kv^ == 0 && v is contained + ///2. kv == 0 && kv^ == 0 && v is contained; an isolated single contained read + rn = res->n; l = 0; + if(!extract_contain_tig(rg, v, ri, l, 1, res)) { + res->n = rn; + } else { + for (z = rn+1; z < res->n; z++) { + if(res->a[z].tn == (v>>1)) break; + } + if(z >= res->n) {///cannot handle circles + p.tn = (uint32_t)-1; p.qn = (uint32_t)-1; + if(kv > 0) { + for (k = 0; k < nv; k++) { + if(!(av[k].del)) break; + } + assert(k < nv); + p.qn = ((uint64_t)(av-g->arc+k)); + } + + kv_push(ul_ov_t, *res, p); + } else { + res->n = rn; + } + } + } + // if(v == 7723) { + // fprintf(stderr, "[M::%s] v0::%lu, res->n::%lu,\n", __func__, v, (uint64_t)res->n); + // } + return res->n;///# chains have contained reads +} + +void collect_pp_ovlps(ul_ov_t *a, uint64_t a_n, kv_ul_ov_t *res, const ug_opt_t *uopt, const asg_t *rg, uint64_t rlen, int64_t ulid, uint64_t *mqs, uint64_t *mqe) +{ + uint64_t i, k; ma_hit_t_alloc* src; uc_block_t rch; ul_ov_t p, *st, *et; + int64_t min_ovlp = uopt->min_ovlp, max_hang = uopt->max_hang, iqs, iqe; st = et = NULL; + res->n = 0; (*mqs) = (*mqe) = (uint64_t)-1; memset(&rch, 0, sizeof(rch)); + if(a_n && a[0].el) st = &(a[0]); + if(a_n > 1 && a[a_n-1].el) et = &(a[a_n-1]); + // if(ulid == 7723 && a_n == 2 && a[0].tn == (7723>>1) && a[a_n-1].tn == (7829>>1)) { + // fprintf(stderr, "[M::%s] ulid::%ld, st::%ld, st_q::[%ld, %ld), et::%ld, et_q::[%ld, %ld)\n", + // __func__, ulid, st?(int64_t)st->tn:-1, st?(int64_t)st->qs:-1, st?(int64_t)st->qe:-1, + // et?(int64_t)et->tn:-1, et?(int64_t)et->qs:-1, et?(int64_t)et->qe:-1); + // } + for (i = 0; i < a_n; i++) { + src = &(uopt->sources[a[i].tn]); + rch.hid = a[i].tn; rch.rev = a[i].rev; + rch.qs = a[i].qs; rch.qe = a[i].qe; + rch.ts = a[i].ts; rch.te = a[i].te; + for (k = 0; k < src->length; k++) { + if(rg->seq[Get_tn(src->buffer[k])].del) continue;///tn must exist + if(st && st->tn == Get_tn(src->buffer[k])) continue;//not useful + if(et && et->tn == Get_tn(src->buffer[k])) continue;//not useful + if(!extract_nccov(&(src->buffer[k]), &rch, rg, &p, 0, min_ovlp, max_hang)) continue; + + extend_end_coord(NULL, &p, rlen, rg->seq[p.tn].len, &iqs, &iqe, NULL, NULL); + if(st && iqs <= (int64_t)st->qe && iqe <= (int64_t)st->qe) continue;//not useful + if(et && iqs >= (int64_t)et->qs && iqe >= (int64_t)et->qs) continue;//not useful + + if(p.rev) { + iqs = rg->seq[p.tn].len - p.te; + iqe = rg->seq[p.tn].len - p.ts; + p.ts = iqs; p.te = iqe; + } + // if(ulid == 7723 && a_n == 2 && a[0].tn == (7723>>1) && a[a_n-1].tn == (7829>>1)) { + // fprintf(stderr, "[M::%s] ulid::%ld, p.tn::%u, pq::[%u, %u), p.el::%u\n", + // __func__, ulid, p.tn, p.qs, p.qe, p.el); + // } + p.el = 0; p.tn <<= 1; p.tn |= p.rev; p.qn = i;//for linear chain + kv_push(ul_ov_t, *res, p); + } + + ///it is unnecessary to push any non-end reads; + ///since the read graph will remove any old read; each read/node is unique within the read graph + if(a[i].el) { + ///push itself into the chain + p = a[i]; + // if(ulid == 7723 && a_n == 2 && a[0].tn == (7723>>1) && a[a_n-1].tn == (7829>>1)) { + // fprintf(stderr, "[M::%s] ulid::%ld, p.tn::%u, pq::[%u, %u), p.el::%u\n", + // __func__, ulid, p.tn, p.qs, p.qe, p.el); + // } + p.tn <<= 1; p.tn |= p.rev; p.qn = i;//for linear chain + kv_push(ul_ov_t, *res, p); + } + if(((*mqs) == ((uint64_t)-1)) || ((*mqs) > a[i].qs)) (*mqs) = a[i].qs; + if(((*mqe) == ((uint64_t)-1)) || ((*mqe) < a[i].qe)) (*mqe) = a[i].qe; + + } + if(st) {(*mqs) = st->qs;} if(et) {(*mqe) = et->qe;} +} + +uint64_t gen_cns_chain_linear_hard(ul_ov_t *a, int64_t a_n, const asg_t *rg, int64_t qlen, int64_t bw, double diff_thre, Chain_Data* dp, +int64_t max_skip, int64_t max_iter, int64_t max_dis, uint64_t mqs, uint64_t mqe, uint64_t ulid, uint64_t ltn, uint64_t rtn) +{ + if(a_n == 0) return 0; + uint32_t li_v, lj_v; int32_t *f; int64_t *p, *t, st, max_ii, max, qo, cL; ul_ov_t *li, *lj; + int64_t mm_ovlp, x, i, j, sc, csc, mm_sc, mm_idx, n_skip, end_j, ch_sc, ch_i; + resize_Chain_Data(dp, a_n, NULL); t = dp->tmp; f = dp->score; p = dp->pre; + + radix_sort_ul_ov_srt_qe(a, a + a_n); + for (i = 1, j = 0; i <= a_n; i++) { + if (i == a_n || a[i].qe != a[j].qe) { + if(i - j > 1) radix_sort_ul_ov_srt_qs(a+j, a+i); + j = i; + } + } + + memset(t, 0, (a_n*sizeof((*t)))); + ch_sc = ch_i = INT32_MIN; + for (i = st = 0, max_ii = -1; i < a_n; ++i) { + li = &(a[i]); + mm_ovlp = max_ovlp(rg, ((li->tn<<1)|li->rev)^1); + x = (li->qs + mm_ovlp)*diff_thre; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > qlen+1) x = qlen+1; + x = find_ul_ov_max(i, a, x+G_CHAIN_INDEL); + + csc = 1; if(li->el) csc = 0; + mm_sc = INT32_MIN+1; mm_idx = -1; n_skip = 0; end_j = -1; + + li_v = (li->tn<<1)|li->rev; li_v ^= 1; + if ((x-st) > max_iter) st = x-max_iter; + for (j = x; j >= st; --j) { // collect potential destination vertices + lj = &(a[j]); + if(lj->qe+G_CHAIN_INDEL <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore + if(f[j] == INT32_MIN) continue;///could not reach the left end + sc = INT32_MIN; + if(lj->qs <= li->qs && lj->qe <= li->qe) {///not contained + lj_v = (lj->tn<<1)|lj->rev; lj_v ^= 1; + qo = infer_rovlp(li, lj, NULL, NULL, NULL, NULL); + if(gconnect_test(rg, li_v, lj_v, bw, diff_thre, qo)) { + sc = f[j] + csc; + } + } + if(sc == INT32_MIN) continue; + if(sc > mm_sc) { + mm_sc = sc, mm_idx = j; + if (n_skip > 0) --n_skip; + } else if (t[j] == i) { + if (++n_skip > max_skip) break; + } + if (p[j] >= 0) t[p[j]] = i; + } + + end_j = j; + if (max_ii < 0 || (a[i].qe > (a[max_ii].qe+max_dis))) {//too long + max = INT32_MIN; max_ii = -1; + for (j = i - 1; (j >= st) && (a[i].qe<=(max_dis+a[j].qe)); --j) { + if (max < f[j]) { + max = f[j], max_ii = j; + } + } + } + + if (max_ii >= 0 && max_ii < end_j) {///just have a try with a[i]<->a[max_ii] + lj = &(a[max_ii]); + if(((lj->qe+G_CHAIN_INDEL)>li->qs) && (lj->qs<=li->qs) && (lj->qe<=li->qe) && (f[max_ii]!=INT32_MIN)) { + lj_v = (lj->tn<<1)|lj->rev; lj_v ^= 1; sc = INT32_MIN; + qo = infer_rovlp(li, lj, NULL, NULL, NULL, NULL); + if(gconnect_test(rg, li_v, lj_v, bw, diff_thre, qo)) { + sc = f[max_ii] + csc; + } + if(sc != INT32_MIN) { + if(sc > mm_sc) { + mm_sc = sc, mm_idx = max_ii; + } + } + } + } + + if(mm_idx == -1) { + if((ltn) != ((uint64_t)-1)) { + if(ltn != li->tn) mm_sc = mm_idx = INT32_MIN; + } else { + if(((int64_t)li->qs) > ((int64_t)(mqs+bw))) mm_sc = mm_idx = INT32_MIN; + } + } + + if((mm_sc==(INT32_MIN+1))) { + mm_sc = csc; + } + + + f[i] = mm_sc; p[i] = mm_idx; + + // if(ulid == 7723 && ltn == (7723>>1) && rtn == (7829>>1)) { + // fprintf(stderr, "[M::%s::id->%u::%.*s] i::%ld, q::[%u, %u), t::[%u, %u), mm_idx::%ld, mm_sc::%ld\n", + // __func__, li->tn, (int)Get_NAME_LENGTH(R_INF, li->tn), Get_NAME(R_INF, li->tn), i, + // li->qs, li->qe, li->ts, li->te, mm_idx, mm_sc); + // } + + if(mm_sc == INT32_MIN) continue; + if((rtn != ((uint64_t)-1)) && (rtn != li->tn)) continue; + if((rtn == ((uint64_t)-1)) && (((int64_t)(a[i].qe+bw))<((int64_t)(mqe)))) continue; + if(mm_sc >= ch_sc) { + ch_sc = mm_sc; ch_i = i; + } + if ((max_ii < 0) || (f[max_ii]= 0) {t[cL++] = i; i = p[i];} + for (i = 0; i < cL; i++) a[i] = a[t[cL-i-1]]; + return cL; +} + +void gen_linear_rchains_dedup(kv_ul_ov_t *res, kv_ul_ov_t *buf, const asg_t *rg, const ug_opt_t *uopt, int64_t bw, +double diff_ec_ul, int64_t qlen, Chain_Data* dp, int64_t ulid, uint64_t *flt, uint64_t flt_n) +{ + uint64_t k, l, z, an, m, bn = buf->n, fi, tn; + radix_sort_ul_ov_srt_tn(res->a, res->a + res->n); + ///after this function, res keeps unitig alignment, while buf keeps read alignments + for (k = 1, l = m = fi = 0; k <= res->n; k++) { + if(k == res->n || res->a[k].tn != res->a[l].tn) {///qn <- (tn|rev) + tn = res->a[l].tn>>1; + for (z = l; z < k; z++) res->a[z].tn>>=1; + for (; (fi=flt_n) || (flt[fi]!=tn)) { + kv_resize(ul_ov_t, *buf, bn+k-l); + an = l + linear_rchain_dp_adv(res->a+l, k-l, buf->a+bn, uopt, bw, diff_ec_ul, qlen, + UG_SKIP_N, UG_ITER_N, UG_DIS_N, dp, rg, ulid); + for (z = l; z < an; z++) res->a[m++] = res->a[z]; + } + l = k; + } + } + res->n = m; +} + +void renew_consensus_chain(kv_ul_ov_t *in, uint32_t in_s, uint32_t in_e, kv_ul_ov_t *idx, asg64_v *ou, R_to_U *ri, +const ug_opt_t *uopt, const asg_t *rg, int64_t bw, double diff_ec_ul, uint32_t arc_id, Chain_Data* dp, uint64_t rlen, uint32_t ulid) +{ + if(in_e <= in_s) return; + uint64_t mqs, mqe, k, l, ou_n = ou->n, stn, etn; + collect_pp_ovlps(in->a + in_s, in_e - in_s, idx, uopt, rg, rlen, ulid, &mqs, &mqe); + // if(ulid == 7723 && in_e-in_s == 2 && in->a[in_s].tn == (7723>>1) && in->a[in_e-1].tn == (7829>>1)) { + // fprintf(stderr, "-0-[M::%s] ulid::%u, idx->n::%u\n", __func__, ulid, (uint32_t)idx->n); + // } + if(!idx->n) return;///it is possible + kv_resize(uint64_t, *ou, (ou_n+(in_e-in_s))); + for (k = in_s; k < in_e; k++) { + if(in->a[k].el) continue; + ou->a[ou_n++] = in->a[k].tn; + } + assert(ou_n <= ou->m); + radix_sort_gfa64(ou->a+ou->n, ou->a+ou_n); + gen_linear_rchains_dedup(idx, in, rg, uopt, bw, diff_ec_ul, rlen, dp, ulid, ou->a+ou->n, ou_n-ou->n); + // if(ulid == 7723 && in_e-in_s == 2 && in->a[in_s].tn == (7723>>1) && in->a[in_e-1].tn == (7829>>1)) { + // fprintf(stderr, "-1-[M::%s] ulid::%u, idx->n::%u\n", __func__, ulid, (uint32_t)idx->n); + // } + if(!idx->n) return;///it is possible + stn = etn = (uint64_t)-1; + if(in_e > in_s && in->a[in_s].el) stn = in->a[in_s].tn; + if(in_e-in_s>1 && in->a[in_e-1].el) etn = in->a[in_e-1].tn; + idx->n = gen_cns_chain_linear_hard(idx->a, idx->n, rg, rlen, bw, diff_ec_ul, dp, UG_SKIP_N, UG_ITER_N, UG_DIS_N, mqs, mqe, ulid, stn, etn); + // if(ulid == 7723 && in_e-in_s == 2 && in->a[in_s].tn == (7723>>1) && in->a[in_e-1].tn == (7829>>1)) { + // fprintf(stderr, "-2-[M::%s] ulid::%u, idx->n::%u\n", __func__, ulid, (uint32_t)idx->n); + // } + if(!idx->n) return; + assert((stn==((uint64_t)-1))||((idx->a[0].tn == stn) && (idx->a[0].el))); + assert((etn==((uint64_t)-1))||((idx->a[idx->n-1].tn == etn) && (idx->a[idx->n-1].el))); + if((stn != ((uint64_t)-1)) && (etn != ((uint64_t)-1)) && idx->n < 2) return;///could happen for circle + if(((stn != ((uint64_t)-1)) || (etn != ((uint64_t)-1))) && idx->n < 1) return;///not sure if it will happen + ou_n = ou->n; + for (k = in_s; k < in_e; k++) { + if(in->a[k].el) continue; + kv_push(uint64_t, *ou, in->a[k].tn); + } + for (k = 0; k < idx->n; k++) { + if(idx->a[k].el) continue; + kv_push(uint64_t, *ou, idx->a[k].tn); + } + if(ou->n == ou_n) return; + radix_sort_gfa64(ou->a+ou_n, ou->a+ou->n); + for (k = ou_n+1, l = ou_n; k <= ou->n; k++) { + if(k == ou->n || ou->a[l] != ou->a[k]) { + if(k-l > 1) break; + l = k; + } + } + assert(k > ou->n); + ou->n = ou_n; + l = arc_id; + if(arc_id == (uint32_t)-1) {///this is an isloated node + l = idx->a[0].tn; l |= ((uint64_t)0x80000000); + } + l <<= 32; l |= ((uint64_t)((uint32_t)-1)); + kv_push(uint64_t, *ou, l); + for (k = 0; k < idx->n; k++) { + l = ((uint64_t)(idx->a[k].tn<<1))|((uint64_t)idx->a[k].rev); + if(idx->a[k].el) l += ((uint64_t)0x100000000); + kv_push(uint64_t, *ou, l); + } + kv_push(uint64_t, *ou, ((uint64_t)-1)); + for (k = in_s; k < in_e; k++) { + l = ((uint64_t)(in->a[k].tn<<1))|((uint64_t)in->a[k].rev); + if(in->a[k].el) l += ((uint64_t)0x100000000); + kv_push(uint64_t, *ou, l); + } +} + +static void worker_for_contain_dedup(void *data, long i, int tid) +{ + utepdat_t *s = (utepdat_t*)data; asg64_v ou; + kv_ul_ov_t *idx = &(s->ll[tid].lo), *dump = &(s->ll[tid].tk); + uint32_t k, v = i, l, dump_n; + + if(!gen_dup_path(s->rg, s->uopt->ruIndex, dump, v)) return; + // if(v == 7723) { + // fprintf(stderr, "[M::%s] v::%u, dump->n::%u\n", __func__, v, (uint32_t)dump->n); + // } + + + copy_asg_arr(ou, s->ll[tid].srt.a); + for (k = 1, l = 0, dump_n = dump->n; k <= dump_n; k++) { + if(k == dump_n || (dump->a[k].tn == ((uint32_t)-1))) { + assert(k > l || k == dump_n); + if(k > l) { + assert(dump->a[k].tn == ((uint32_t)-1)); + renew_consensus_chain(dump, l, k, idx, &ou, s->uopt->ruIndex, s->uopt, s->rg, G_CHAIN_BW, + 0.02/**s->opt->diff_ec_ul**/, dump->a[k].qn, &(s->hab[tid]->clist.chainDP), dump->a[k-1].qe, v); + } + l = k + 1; + } + } + copy_asg_arr(s->ll[tid].srt.a, ou); +} + +void detect_outlier_len(const char* cmd) +{ + uint64_t k; + for (k = 0; k < UL_INF.n; k++) { + if(UL_INF.a[k].rlen == 0) { + fprintf(stderr, "[%s] rid->%lu, rlen->%u, %.*s\n", + cmd, k, UL_INF.a[k].rlen, (int32_t)UL_INF.nid.a[k].n, UL_INF.nid.a[k].a); + } + } +} + +uint64_t work_ul_gchains(uldat_t *sl) +{ + utepdat_t s; uint64_t i; memset(&s, 0, sizeof(s)); + s.id = 0; s.opt = sl->opt; s.ug = sl->ug; s.uopt = sl->uopt; s.rg = sl->rg; s.uu = sl->uu; + CALLOC(s.hab, sl->n_thread); CALLOC(s.buf, sl->n_thread); CALLOC(s.ll, sl->n_thread); + CALLOC(s.gdp, sl->n_thread); CALLOC(s.mzs, sl->n_thread); CALLOC(s.sps, sl->n_thread); + + for (i = 0; i < sl->n_thread; ++i) { + s.hab[i] = ha_ovec_init(0, 0, 1); s.buf[i] = mg_tbuf_init(); + } + + // detect_outlier_len("+++work_ul_gchains"); + + kt_for(sl->n_thread, worker_for_ul_gchains_alignment, &s, UL_INF.n); + + // detect_outlier_len("---work_ul_gchains"); + + for (i = 0; i < sl->n_thread; ++i) { + s.sum_len += s.hab[i]->num_read_base; s.n += s.hab[i]->num_correct_base; + ha_ovec_destroy(s.hab[i]); mg_tbuf_destroy(s.buf[i]); hc_glchain_destroy(&(s.ll[i])); + hc_gdpchain_destroy(&(s.gdp[i])); kv_destroy(s.mzs[i]); kv_destroy(s.sps[i]); + } + + free(s.hab); free(s.buf); free(s.ll); free(s.gdp); free(s.mzs); free(s.sps); + fprintf(stderr, "[M::%s::] # try:%d, # done:%d\n", __func__, s.sum_len, s.n); + return s.n; +} + +scaf_res_t *work_ctg_path_gchains(uldat_t *sl) +{ + utepdat_t s; uint64_t i; memset(&s, 0, sizeof(s)); scaf_res_t *res = init_scaf_res_t(sl->ug->u.n); + s.id = 0; s.opt = sl->opt; s.ug = sl->ug; s.uopt = sl->uopt; s.rg = sl->rg; s.uu = sl->uu; s.rsc = res; + CALLOC(s.hab, sl->n_thread); CALLOC(s.buf, sl->n_thread); CALLOC(s.ll, sl->n_thread); + CALLOC(s.gdp, sl->n_thread); CALLOC(s.mzs, sl->n_thread); CALLOC(s.sps, sl->n_thread); + + for (i = 0; i < sl->n_thread; ++i) { + s.hab[i] = ha_ovec_init(0, 0, 1); s.buf[i] = mg_tbuf_init(); + } + + // detect_outlier_len("+++work_ul_gchains"); + + kt_for(sl->n_thread, worker_for_ctg_gchains_alignment, &s, s.ug->u.n); + + // detect_outlier_len("---work_ul_gchains"); + + for (i = 0; i < sl->n_thread; ++i) { + s.sum_len += s.hab[i]->num_read_base; s.n += s.hab[i]->num_correct_base; + ha_ovec_destroy(s.hab[i]); mg_tbuf_destroy(s.buf[i]); hc_glchain_destroy(&(s.ll[i])); + hc_gdpchain_destroy(&(s.gdp[i])); kv_destroy(s.mzs[i]); kv_destroy(s.sps[i]); + } + + free(s.hab); free(s.buf); free(s.ll); free(s.gdp); free(s.mzs); free(s.sps); + fprintf(stderr, "[M::%s::] # try:%d, # done:%d\n", __func__, s.sum_len, s.n); + return res; +} + + +void fill_ctg_path_trans_idx(glchain_t *a, uint64_t n, uint64_t qn, uint32_t qoff, uint32_t toff, kv_u_trans_t *ou) +{ + kv_resize(uint64_t, ou->idx, qn); + memset(ou->idx.a, -1, sizeof((*(ou->idx.a)))*qn); + + uint64_t i, k, l, pn; kv_ul_ov_t *s = NULL; u_trans_t *z = NULL; + for(i = pn = 0; i < n; i++) { + s = &(a[i].tk); pn += s->n; + for (k = 1, l = 0; k <= s->n; k++) { + if(k == s->n || s->a[l].qn != s->a[k].qn) { + assert(ou->idx.a[s->a[l].qn] == (uint64_t)-1); + ou->idx.a[s->a[l].qn] = (i<<32)|l; + l = k; + } + } + } + kv_resize(u_trans_t, *ou, ou->n+(pn<<1)); l = ou->n; + + for (i = 0; i < qn; i++) { + if(ou->idx.a[i] == (uint64_t)-1) { + ou->idx.a[i] = 0; continue; + } + s = &(a[ou->idx.a[i]>>32].tk); + for(k = l = (uint32_t)ou->idx.a[i]; k < s->n && s->a[l].qn == s->a[k].qn; k++) { + kv_pushp(u_trans_t, *ou, &z); + z->qn = s->a[k].qn+qoff; z->qs = s->a[k].qs; z->qe = s->a[k].qe; + z->tn = s->a[k].tn+toff; z->ts = s->a[k].ts; z->te = s->a[k].te; + z->rev = s->a[k].rev; z->f = s->a[k].el; z->nw = s->a[k].sec; + z->occ = s->a[k].sec; z->del = 0; + + + kv_pushp(u_trans_t, *ou, &z); + z->tn = s->a[k].qn+qoff; z->ts = s->a[k].qs; z->te = s->a[k].qe; + z->qn = s->a[k].tn+toff; z->qs = s->a[k].ts; z->qe = s->a[k].te; + z->rev = s->a[k].rev; z->f = s->a[k].el; z->nw = s->a[k].sec; + z->occ = s->a[k].sec; z->del = 0; + + } + // p->idx.a[i] = pn - (k - l); p->idx.a[i] <<= 32; p->idx.a[i] |= k - l; ///pn += k - l; + } + // assert(l + (pn<<1) == ou->n); +} + +void work_ctg_path_trans(uldat_t *sl, asg_t *sg, ma_ug_t *qry, scaf_res_t *qry_sc, ma_ug_t *ref, scaf_res_t *ref_sc, ma_ug_t *gfa, kv_u_trans_t *ta, uint32_t qoff, uint32_t toff, bubble_type *bu, kv_u_trans_t *res) +{ + utepdat_t s; uint64_t i; memset(&s, 0, sizeof(s)); + s.id = 0; s.opt = sl->opt; s.ug = sl->ug; s.uopt = sl->uopt; s.rg = sl->rg; s.uu = sl->uu; + CALLOC(s.hab, sl->n_thread); CALLOC(s.buf, sl->n_thread); CALLOC(s.ll, sl->n_thread); + CALLOC(s.gdp, sl->n_thread); CALLOC(s.mzs, sl->n_thread); CALLOC(s.sps, sl->n_thread); + + for (i = 0; i < sl->n_thread; ++i) { + s.hab[i] = ha_ovec_init(0, 0, 1); s.buf[i] = mg_tbuf_init(); + } + + ctdat_t c; memset(&c, 0, sizeof(c)); c.soff = (uint64_t)-1; /**uint8_t *bf = NULL; c.bub = gen_bubble_chain(sg, gfa, (ug_opt_t *)(sl->uopt), &bf, 0); free(bf);**/c.bub = bu; + c.s = &(s); c.qry = qry; c.qry_sc = qry_sc; c.ref = ref; c.ref_sc = ref_sc; c.gfa = gfa; c.ta = ta; + + // detect_outlier_len("+++work_ul_gchains"); + + kt_for(sl->n_thread, worker_for_ctg_trans_alignment, &c, c.qry_sc->n); + + // detect_outlier_len("---work_ul_gchains"); + /**destory_bubbles(c.bub); free(c.bub);**/ + fill_ctg_path_trans_idx(s.ll, sl->n_thread, qry->u.n, qoff, toff, res); + for (i = 0; i < sl->n_thread; ++i) { + s.sum_len += s.hab[i]->num_read_base; s.n += s.hab[i]->num_correct_base; + ha_ovec_destroy(s.hab[i]); mg_tbuf_destroy(s.buf[i]); hc_glchain_destroy(&(s.ll[i])); + hc_gdpchain_destroy(&(s.gdp[i])); kv_destroy(s.mzs[i]); kv_destroy(s.sps[i]); + } + + free(s.hab); free(s.buf); free(s.ll); free(s.gdp); free(s.mzs); free(s.sps); + fprintf(stderr, "[M::%s::] # try:%d, # done:%d\n", __func__, s.sum_len, s.n); +} + +void work_ctg_path_trans_self(uldat_t *sl, asg_t *sg, ma_ug_t *db, scaf_res_t *db_sc, ma_ug_t *gfa, kv_u_trans_t *ta, uint64_t soff, uint64_t is_exact, bubble_type *bu, kv_u_trans_t *res) +{ + utepdat_t s; uint64_t i; memset(&s, 0, sizeof(s)); + s.id = 0; s.opt = sl->opt; s.ug = sl->ug; s.uopt = sl->uopt; s.rg = sl->rg; s.uu = sl->uu; + CALLOC(s.hab, sl->n_thread); CALLOC(s.buf, sl->n_thread); CALLOC(s.ll, sl->n_thread); + CALLOC(s.gdp, sl->n_thread); CALLOC(s.mzs, sl->n_thread); CALLOC(s.sps, sl->n_thread); + + for (i = 0; i < sl->n_thread; ++i) { + s.hab[i] = ha_ovec_init(0, 0, 1); s.buf[i] = mg_tbuf_init(); + } + + ctdat_t c; memset(&c, 0, sizeof(c)); c.soff = soff; c.bub = bu; c.is_exact = is_exact; + c.s = &(s); c.qry = NULL; c.qry_sc = NULL; c.ref = db; c.ref_sc = db_sc; c.gfa = gfa; c.ta = ta; + + // detect_outlier_len("+++work_ul_gchains"); + + kt_for(sl->n_thread, worker_for_ctg_trans_alignment, &c, db_sc->n); + + // detect_outlier_len("---work_ul_gchains"); + fill_ctg_path_trans_idx(s.ll, sl->n_thread, db->u.n, 0, 0, res); + for (i = 0; i < sl->n_thread; ++i) { + s.sum_len += s.hab[i]->num_read_base; s.n += s.hab[i]->num_correct_base; + ha_ovec_destroy(s.hab[i]); mg_tbuf_destroy(s.buf[i]); hc_glchain_destroy(&(s.ll[i])); + hc_gdpchain_destroy(&(s.gdp[i])); kv_destroy(s.mzs[i]); kv_destroy(s.sps[i]); + } + + free(s.hab); free(s.buf); free(s.ll); free(s.gdp); free(s.mzs); free(s.sps); + fprintf(stderr, "[M::%s::] # try:%d, # done:%d\n", __func__, s.sum_len, s.n); +} + +uint64_t work_ul_gchains_consensus(uldat_t *sl) +{ + utepdat_t s; uint64_t i; memset(&s, 0, sizeof(s)); + s.id = 0; s.uopt = sl->uopt; s.rg = sl->rg; s.opt = sl->opt; ///s.ug = sl->ug; s.uu = sl->uu; + // CALLOC(s.buf, sl->n_thread); CALLOC(s.gdp, sl->n_thread); CALLOC(s.mzs, sl->n_thread); + CALLOC(s.hab, sl->n_thread); CALLOC(s.ll, sl->n_thread); ///CALLOC(s.sps, sl->n_thread); + + for (i = 0; i < sl->n_thread; ++i) { + s.hab[i] = ha_ovec_init(0, 0, 1); ///s.buf[i] = mg_tbuf_init(); + } + + // detect_outlier_len("+++work_ul_gchains"); + + //debug + // overall_zdbg = init_mul_debug_prt_t(UL_INF.n); + + kt_for(sl->n_thread, worker_for_contain_consensus, &s, UL_INF.n); + + // detect_outlier_len("---work_ul_gchains"); + + for (i = 0; i < sl->n_thread; ++i) { + s.sum_len += s.hab[i]->num_read_base; s.n += s.hab[i]->num_correct_base; + // hc_gdpchain_destroy(&(s.gdp[i])); kv_destroy(s.mzs[i]); mg_tbuf_destroy(s.buf[i]); + ha_ovec_destroy(s.hab[i]); hc_glchain_destroy(&(s.ll[i])); ///kv_destroy(s.sps[i]); + } + + // free(s.buf); free(s.gdp); free(s.mzs); + free(s.hab); free(s.ll); ///free(s.sps); + fprintf(stderr, "[M::%s::] # try:%d, # done:%d\n", __func__, s.sum_len, s.n); + return s.sum_len; +} + + +void update_contain_dedup_arr(asg64_v *in, uint64_t prefix, asg64_v *res) +{ + if(in->n == 0) return; + uint64_t i, m; + for (i = 0; i < in->n; i++) { + if(in->a[i] == ((uint64_t)-1)) continue; + if(((uint32_t)in->a[i]) == ((uint32_t)-1)) { + m = prefix; m <<= 32; m += i; + kv_push(uint64_t, *res, m); + } + } +} + +uint64_t path_del_topo(asg_t *g, uint64_t v) +{ + uint64_t nv, nw, kw, k, z, w; asg_arc_t *av, *aw; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (k = 0; k < nv; k++){ + if(av[k].del) continue; + w = av[k].v^1; + nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); + for (z = kw = 0; z < nw; z++) { + if(aw[z].del) continue; + if((aw[z].v>>1) != (v>>1)) continue; + kw++; + } + if(kw <= 0) return 0; + } + return 1; +} + +uint64_t tes_path_connec(asg_t *g, uint64_t sn, uint64_t en, uint64_t *pa, uint64_t pn, uint64_t is_single_path, uint64_t *min_ou) +{ + // fprintf(stderr, "-0-[M::%s::]\n", __func__); + if(min_ou) (*min_ou) = 0; + if((sn != (uint64_t)-1) && ((g->seq[sn>>1].del)||(get_arcs(g, sn, NULL, 0)<2))) return 0; + if((en != (uint64_t)-1) && ((g->seq[en>>1].del)||((get_arcs(g, en^1, NULL, 0)<2)))) return 0; + uint64_t nv, k, v, w, i, ou = (uint64_t)-1; asg_arc_t *av; + if((sn != (uint64_t)-1) && (en != (uint64_t)-1) && (!pn)) { + v = sn; w = en; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == w) { + if(((uint64_t)av[k].ou) < ou) ou = av[k].ou; + break; + } + } + if(k >= nv) return 0; + + v = en^1; w = sn^1; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == w) { + if(((uint64_t)av[k].ou) < ou) ou = av[k].ou; + break; + } + } + if(k >= nv) return 0; + + // if(get_arcs(g, sn, NULL, 0) < 2) return 0; + // if(get_arcs(g, en^1, NULL, 0) < 2) return 0; + if(min_ou) (*min_ou) = ou; + return 1; + } + + // fprintf(stderr, "-1-[M::%s::]\n", __func__); + if(sn != (uint64_t)-1) { + v = sn; i = 0; + } else { + v = pa[0]; i = 1; assert(!(pa[0]>>32)); + } + // fprintf(stderr, "-2-[M::%s::]\n", __func__); + for (; i < pn; i++) { + w = pa[i]; assert(!(pa[i]>>32)); + if(g->seq[v>>1].del || g->seq[w>>1].del) return 0; + + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == w) { + if(((uint64_t)av[k].ou) < ou) ou = av[k].ou; + break; + } + } + if(k >= nv) return 0; + + nv = asg_arc_n(g, w^1); av = asg_arc_a(g, w^1); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == (v^1)) { + if(((uint64_t)av[k].ou) < ou) ou = av[k].ou; + break; + } + } + if(k >= nv) return 0; + + if(is_single_path) { + if(v != sn && v != en && get_arcs(g, v, NULL, 0) != 1) return 0; + if(w != sn && w != en && get_arcs(g, w^1, NULL, 0) != 1) return 0; + } + + v = w; + } + // fprintf(stderr, "-3-[M::%s::]\n", __func__); + if(en != (uint64_t)-1) { + w = en; + if(g->seq[v>>1].del || g->seq[w>>1].del) return 0; + // fprintf(stderr, "-3a-[M::%s::]\n", __func__); + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == w) { + if(((uint64_t)av[k].ou) < ou) ou = av[k].ou; + break; + } + } + if(k >= nv) return 0; + // fprintf(stderr, "-3b-[M::%s::]\n", __func__); + nv = asg_arc_n(g, w^1); av = asg_arc_a(g, w^1); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == (v^1)) { + if(((uint64_t)av[k].ou) < ou) ou = av[k].ou; + break; + } + } + if(k >= nv) return 0; + + if(is_single_path) { + if(v != sn && v != en && get_arcs(g, v, NULL, 0) != 1) return 0; + if(w != sn && w != en && get_arcs(g, w^1, NULL, 0) != 1) return 0; + } + } + + + + // fprintf(stderr, "-4-[M::%s::]\n", __func__); + if(!path_del_topo(g, pa[0]^1)) return 0; + // if(sn != ((uint64_t)-1)) { + // v = sn; w = pa[0]; + // nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + // for (k = 0; k < nv; k++) { + // if(av[k].del) continue; + // if(av[k].v == w) break; + // } + // if(k >= nv) return 0; + + // v = pa[0]^1; w = sn^1; + // nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + // for (k = 0; k < nv; k++) { + // if(av[k].del) continue; + // if(av[k].v == w) break; + // } + // if(k >= nv) return 0; + // } + + + + if(!path_del_topo(g, pa[pn-1])) return 0; + // if(en != ((uint64_t)-1)) { + // v = pa[pn-1]; w = en; + // nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + // for (k = 0; k < nv; k++) { + // if(av[k].del) continue; + // if(av[k].v == w) break; + // } + // if(k >= nv) return 0; + + // v = en^1; w = pa[pn-1]^1; + // nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + // for (k = 0; k < nv; k++) { + // if(av[k].del) continue; + // if(av[k].v == w) break; + // } + // if(k >= nv) return 0; + // } + + if(min_ou) (*min_ou) = ou; + return 1; +} + +void append_path_connec(asg_t *g, uint64_t sn, uint64_t en, uint64_t *pa, uint64_t pn, uint64_t min_ou) +{ + uint64_t nv, k, v, w, i, ou; asg_arc_t *av; + if(sn != (uint64_t)-1) { + v = sn; i = 0; + } else { + v = pa[0]; i = 1; + } + + for (; i < pn; i++) { + w = pa[i]; + + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == w) { + ou = av[k].ou; ou += min_ou; + if(ou > OU_MASK) ou = OU_MASK; + av[k].ou = ou; + break; + } + } + assert(k < nv); + + nv = asg_arc_n(g, w^1); av = asg_arc_a(g, w^1); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == (v^1)) { + ou = av[k].ou; ou += min_ou; + if(ou > OU_MASK) ou = OU_MASK; + av[k].ou = ou; + break; + } + } + assert(k < nv); + + v = w; + } + // fprintf(stderr, "-3-[M::%s::]\n", __func__); + if(en != (uint64_t)-1) { + w = en; + // fprintf(stderr, "-3a-[M::%s::]\n", __func__); + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == w) { + ou = av[k].ou; ou += min_ou; + if(ou > OU_MASK) ou = OU_MASK; + av[k].ou = ou; + break; + } + } + assert(k < nv); + + // fprintf(stderr, "-3b-[M::%s::]\n", __func__); + nv = asg_arc_n(g, w^1); av = asg_arc_a(g, w^1); + for (k = 0; k < nv; k++) { + if(av[k].del) continue; + if(av[k].v == (v^1)) { + ou = av[k].ou; ou += min_ou; + if(ou > OU_MASK) ou = OU_MASK; + av[k].ou = ou; + break; + } + } + assert(k < nv); + } +} + + +uint64_t asg_clean_idx_tig(asg_t *g, uint64_t *idx, uint64_t idx_n, uint64_t *srt, uint64_t srt_n, utepdat_t *s) +{ + uint64_t i, k, *a, an, sp, *del_a, del_n, *ref_a, ref_n, *ka, kk, cnt = 0, min_ou; + uint64_t ref_s, ref_e, del_s, del_e; + for (i = 0; i < srt_n; i++) { + a = s->ll[idx[(uint32_t)srt[i]]>>32].srt.a.a; + an = s->ll[idx[(uint32_t)srt[i]]>>32].srt.a.n; + sp = (uint32_t)idx[(uint32_t)srt[i]]; + assert((((uint32_t)a[sp])==((uint32_t)-1)) && ((a[sp]>>32)!=((uint32_t)-1))); + + // fprintf(stderr, "\n+[M::%s::] ((uint32_t)(a[sp]>>32))::%u, ((uint32_t)a[sp])::%u, sp::%lu, an::%lu\n", __func__, + // ((uint32_t)(a[sp]>>32)), ((uint32_t)a[sp]), sp, an); + + k = sp + 1; ref_a = a + k; + for (sp = k; k < an; k++) { + if(a[k] == (uint64_t)-1) break; + } + assert(k < an); + ref_n = k - sp; + // fprintf(stderr, "+[M::%s::] k::%lu\n", __func__, k); + // fprintf(stderr, "+[M::%s::] k::%lu, an::%lu\n", __func__, k, an); + + k++; del_a = a + k; + for (sp = k; k < an; k++) { + if((a[k] != (uint64_t)-1) && (((uint32_t)a[k]) == ((uint32_t)-1))) break; + } + + // assert(k < an);//for the last batch of reads, there is no end marker, so k == an + del_n = k - sp; + + ref_s = ref_e = del_s = del_e = (uint64_t)-1; + if(ref_n > 0 && (ref_a[0]>>32)) ref_s = (uint32_t)ref_a[0]; + if(ref_n > 1 && (ref_a[ref_n-1]>>32)) ref_e = (uint32_t)ref_a[ref_n-1]; + + if(del_n > 0 && (del_a[0]>>32)) del_s = (uint32_t)del_a[0]; + if(del_n > 1 && (del_a[del_n-1]>>32)) del_e = (uint32_t)del_a[del_n-1]; + + // if((ref_e != del_e) || (ref_s != del_s)) { + // fprintf(stderr, "-[M::%s::] idx_n::%lu, idx_n::%lu, ref_n::%lu, del_n::%lu, ref_s::%lu, ref_e::%lu, del_s::%lu, del_e::%lu\n", + // __func__, idx_n, idx_n, ref_n, del_n, ref_s, ref_e, del_s, del_e); + // for (k = 0; k < ref_n; k++) { + // fprintf(stderr, "-[M::ref::] ref_a[k]>>1::%lu\n", ref_a[k]>>1); + // } + // for (k = 0; k < del_n; k++) { + // fprintf(stderr, "-[M::del::] del_a[k]>>1::%lu\n", del_a[k]>>1); + // } + // } + assert(ref_s == del_s); assert(ref_e == del_e); + + if(ref_s != (uint64_t)-1) { + ref_a = ref_a + 1; ref_n--; + } + if(ref_e != (uint64_t)-1) ref_n--; + + if(del_s != (uint64_t)-1) { + del_a = del_a + 1; del_n--; + } + if(del_e != (uint64_t)-1) del_n--; + + if(ref_n == 0 && del_n > 0) { + ka = ref_a; ref_a = del_a; del_a = ka; + kk = ref_n; ref_n = del_n; del_n = kk; + kk = ref_s; ref_s = del_s; del_s = kk; + kk = ref_e; ref_e = del_e; del_e = kk; + } + + // fprintf(stderr, "-[M::%s::] idx_n::%lu, idx_n::%lu, ref_n::%lu, del_n::%lu, ref_s::%lu, ref_e::%lu\n", + // __func__, idx_n, idx_n, ref_n, del_n, ref_s, ref_e); + // for (k = 0; k < ref_n; k++) { + // fprintf(stderr, "-[M::ref::] ref_a[k]>>1::%lu\n", ref_a[k]>>1); + // } + // for (k = 0; k < del_n; k++) { + // fprintf(stderr, "-[M::del::] del_a[k]>>1::%lu\n", del_a[k]>>1); + // } + + + + ///just for debug + // if(ref_s != (uint64_t)-1) { + // assert(get_arcs(g, ref_s, NULL, 0) > 1); + // } + // if(ref_e != (uint64_t)-1) { + // assert(get_arcs(g, ref_e^1, NULL, 0) > 1); + // } + // assert(tes_path_connec(g, ref_s, ref_e, ref_a, ref_n, 0, NULL)); + // assert(tes_path_connec(g, del_s, del_e, del_a, del_n, 1, NULL)); + + min_ou = 0; + if((ref_s!=(uint64_t)-1) && (get_arcs(g, ref_s, NULL, 0)<=1)) continue; + if((ref_e!=(uint64_t)-1) && (get_arcs(g, ref_e^1, NULL, 0)<=1)) continue; + if(!tes_path_connec(g, ref_s, ref_e, ref_a, ref_n, 0, NULL)) continue; + if(!tes_path_connec(g, del_s, del_e, del_a, del_n, 1, &min_ou)) continue; + + if(del_n > 0) { + for (k = 0; k < del_n; k++) asg_seq_del(g, del_a[k]>>1); + cnt += del_n; + } else { + asg_arc_del(g, del_s, del_e, 1); + asg_arc_del(g, del_e^1, del_s^1, 1); + cnt++; + } + if(min_ou > 0) append_path_connec(g, ref_s, ref_e, ref_a, ref_n, min_ou); + } + if(cnt) { + asg_cleanup(g); + } + return cnt; +} + +uint64_t work_rg_contain_dedup(uldat_t *sl) +{ + utepdat_t s; uint64_t i, occ, ou_n, m, *srt, srt_n, *idx, idx_n, tot; + asg64_v ou, bu; kv_init(ou); memset(&s, 0, sizeof(s)); + s.id = 0; s.uopt = sl->uopt; s.rg = sl->rg; s.opt = sl->opt; ///s.ug = sl->ug; s.uu = sl->uu; + // CALLOC(s.buf, sl->n_thread); CALLOC(s.gdp, sl->n_thread); CALLOC(s.mzs, sl->n_thread); + CALLOC(s.hab, sl->n_thread); CALLOC(s.ll, sl->n_thread); ///CALLOC(s.sps, sl->n_thread); + + for (i = 0; i < sl->n_thread; ++i) { + s.hab[i] = ha_ovec_init(0, 0, 1); ///s.buf[i] = mg_tbuf_init(); + } + + // detect_outlier_len("+++work_ul_gchains"); + + //debug + // overall_zdbg = init_mul_debug_prt_t(UL_INF.n); + occ = 1; tot = 0; + while (occ) { + kt_for(sl->n_thread, worker_for_contain_dedup, &s, (s.rg->n_seq<<1)); + for (i = ou.n = 0; i < sl->n_thread; ++i) { + copy_asg_arr(bu, s.ll[i].srt.a); + update_contain_dedup_arr(&bu, i, &ou); + copy_asg_arr(s.ll[i].srt.a, bu); + } + ou_n = ou.n; + for (i = 0; i < ou_n; i++) { + assert(((uint32_t)s.ll[ou.a[i]>>32].srt.a.a[(uint32_t)ou.a[i]]) == ((uint32_t)-1)); + m = s.ll[ou.a[i]>>32].srt.a.a[(uint32_t)ou.a[i]]>>32; m <<= 32; m += i; + kv_push(uint64_t, ou, m); + } + // fprintf(stderr, "[M::%s::] ou_n::%lu, ou.n::%u\n", __func__, ou_n, (uint32_t)ou.n); + idx = ou.a; idx_n = ou_n; srt = ou.a + ou_n; srt_n = ou.n - ou_n; + radix_sort_gfa64(srt, srt + srt_n); + // print_debug_gfa((asg_t *)s.rg, NULL, s.uopt->coverage_cut, "UL.dirty.debug", s.uopt->sources, s.uopt->ruIndex, s.uopt->max_hang, s.uopt->min_ovlp, 0, 0, 0); + occ = asg_clean_idx_tig((asg_t *)s.rg, idx, idx_n, srt, srt_n, &s); + for (i = 0; i < sl->n_thread; ++i) s.ll[i].srt.a.n = 0; + tot += occ; + // fprintf(stderr, "[M::%s::] idx_n::%lu, srt_n::%lu, occ::%lu\n", __func__, idx_n, srt_n, occ); + } + + + + + // detect_outlier_len("---work_ul_gchains"); + + for (i = 0; i < sl->n_thread; ++i) { + s.sum_len += s.hab[i]->num_read_base; s.n += s.hab[i]->num_correct_base; + // hc_gdpchain_destroy(&(s.gdp[i])); kv_destroy(s.mzs[i]); mg_tbuf_destroy(s.buf[i]); + ha_ovec_destroy(s.hab[i]); hc_glchain_destroy(&(s.ll[i])); ///kv_destroy(s.sps[i]); + } + + // free(s.buf); free(s.gdp); free(s.mzs); + free(s.hab); free(s.ll); kv_destroy(ou); ///free(s.sps); + fprintf(stderr, "[M::%s::] # duplicated reads::%lu\n", __func__, tot); + // exit(1); + return tot; +} + +void print_ul_ovlps(all_ul_t *x, int32_t prt_ovlp) +{ + uint64_t k, i, ucov_occ = 0, cov_occ = 0, ucov_len = 0, cov_len = 0, unaligned_len = 0, unaligned_occ = 0, aligned_occ = 0; + ul_vec_t *p = NULL; nid_t *z = NULL; uc_block_t *m = NULL; + for (k = 0; k < x->n; k++) { + z = &(x->nid.a[k]); + p = &(x->a[k]); + fprintf(stderr, "S\t%.*s\tq:id:%lu\tl:%u\tdd:%d\n", (int32_t)z->n, z->a, k, p->rlen, + ((p->bb.n == 1&&p->bb.a[0].base)||(p->bb.n==0))?-1:(int32_t)p->dd); + if(prt_ovlp) { + for (i = 0; i < p->bb.n; i++) { + m = &(p->bb.a[i]); + if(m->base) { + ucov_occ++; + ucov_len += (m->qe-(m->hid&FLANK_M)) - (m->qs+((m->hid>>15)&FLANK_M)); + fprintf(stderr, "B\t%.*s\t%u\t%u\t%u\n", + (int32_t)z->n, z->a, p->rlen, (m->qs+((m->hid>>15)&FLANK_M)), (m->qe-(m->hid&FLANK_M))); + } else { + fprintf(stderr, "A\t%.*s(%lu)\t%u\t%u\t%u\t%c\t%.*s(%u)\t%u\t%u\t%u\n", + (int32_t)z->n, z->a, k, p->rlen, m->qs, m->qe, "+-"[m->rev], + (int32_t)Get_NAME_LENGTH(R_INF, m->hid), Get_NAME(R_INF, m->hid), m->hid, + (uint32_t)Get_READ_LENGTH(R_INF, m->hid), m->ts, m->te); + if(m->el) cov_occ++; + } + } + } + if((p->bb.n == 1 && p->bb.a[0].base)||(p->bb.n == 0)) { + unaligned_len += p->rlen; unaligned_occ++; + } else { + aligned_occ++; + } + cov_len += p->rlen; + } + cov_len -= ucov_len; + fprintf(stderr, "[M::%s::] ==>aligned_occ:%lu, unaligned_occ:%lu\n", __func__, aligned_occ, unaligned_occ); + fprintf(stderr, "[M::%s::] ==>cov_len:%lu, ucov_len:%lu, unaligned_len:%lu\n", + __func__, cov_len, ucov_len-unaligned_len, unaligned_len); +} + +void print_all_ul_t_stat(all_ul_t *x) +{ + uint64_t k, i, ucov_occ = 0, cov_occ = 0, ucov_len = 0, cov_len = 0; + ul_vec_t *p = NULL; + for (k = 0; k < x->n; k++) { + p = &(x->a[k]); + for (i = 0; i < p->bb.n; i++) { + if(p->bb.a[i].base/**.hid&x->mm**/) { + ucov_occ++; + ucov_len += (p->bb.a[i].qe-(p->bb.a[i].hid&FLANK_M)) - + (p->bb.a[i].qs+((p->bb.a[i].hid>>15)&FLANK_M)); + } else { + cov_occ++; + } + } + cov_len += p->rlen; + } + cov_len -= ucov_len; + fprintf(stderr, "[M::%s::] ==>cov_occ:%lu, ucov_occ:%lu\n", __func__, cov_occ, ucov_occ); + fprintf(stderr, "[M::%s::] ==>cov_len:%lu, ucov_len:%lu\n", __func__, cov_len, ucov_len); +} + +void print_ovlp_src_bl_stat(all_ul_t *x, const ug_opt_t *uopt) +{ + uint64_t k, z, tc, ta; + ma_hit_t_alloc* src = uopt->sources; + for (k = tc = ta = 0; k < R_INF.total_reads; k++) { + if(x->ridx.idx.a[k+1] - x->ridx.idx.a[k] == 0) continue; + tc++; + for (z = 0; z < src[k].length; z++) { + if(src[k].buffer[z].bl) { + ta++; + break; + } + } + } + + fprintf(stderr, "[M::%s::] ==> # HiFi reads:%lu, # covered HiFi reads:%lu, # chained HiFi reads:%lu\n", + __func__, R_INF.total_reads, tc, ta); + + uint64_t tt[4] = {0}; + for (k = 0; k < x->n; k++) { + tt[x->a[k].dd]++; + // if(x->a[k].dd == 1) { + // fprintf(stderr, "(%lu) %.*s\n", k, (int32_t)x->nid.a[k].n, x->nid.a[k].a); + // } + } + + fprintf(stderr, "[M::%s::] ==> # passed UL reads:%lu, # fully corrected UL reads:%lu, # almost fully corrected UL reads:%lu, # UL reads have primary chains:%lu\n", + __func__, tt[0]+tt[1]+tt[2]+tt[3], tt[1], tt[2], tt[3]); +} + +void gen_ul_vec_rid_t(all_ul_t *x, All_reads *rdb, ma_ug_t *ug) +{ + ul_vec_rid_t *ridx = &(x->ridx); + uint64_t k, i, l, m, *a, a_n, idx_n; ul_vec_t *p = NULL; + idx_n = (rdb?rdb->total_reads:ug->u.n); + ridx->idx.n = ridx->idx.m = idx_n + 1; CALLOC(ridx->idx.a, ridx->idx.n); + + for (k = 0; k < x->n; k++) {///each UL read + p = &(x->a[k]); + for (i = 0; i < p->bb.n; i++) { + if(p->bb.a[i].base) continue; + ridx->idx.a[p->bb.a[i].hid]++; + } + } + + for (k = l = 0; k < ridx->idx.n; k++) { + m = ridx->idx.a[k]; + ridx->idx.a[k] = l; + l += m; + } + + ridx->occ.n = ridx->occ.m = l; MALLOC(ridx->occ.a, ridx->occ.n); + for (k = 0; k < idx_n; k++) { + a = ridx->occ.a + ridx->idx.a[k]; + a_n = ridx->idx.a[k+1] - ridx->idx.a[k]; + if(a_n) a[a_n-1] = 0; + } + + for (k = 0; k < x->n; k++) { + p = &(x->a[k]); + for (i = 0; i < p->bb.n; i++) { + if(p->bb.a[i].base) continue; + a = ridx->occ.a + ridx->idx.a[p->bb.a[i].hid]; + a_n = ridx->idx.a[p->bb.a[i].hid+1] - ridx->idx.a[p->bb.a[i].hid]; + if(a_n) { + if(a[a_n-1] == a_n-1) a[a_n-1] = (k<<32)|i; + else a[a[a_n-1]++] = (k<<32)|i; + } + } + } +} + + +uint32_t ugl_cover_check(uint64_t is, uint64_t ie, ma_utg_t *u) +{ + if(is == 0 && ie == u->len) return 1; + uint64_t l, i, us, ue; + for (i = l = 0; i < u->n; i++) { + us = l; ue = l + Get_READ_LENGTH(R_INF, (u->a[i]>>33)); + if(is <= us && ie >= ue) return 1; + if(us >= ie) break; + l += (uint32_t)u->a[i]; + } + return 0; +} + +static void update_ug_arch_ul(void *data, long i, int tid) // callback for kt_for() +{ + const ma_ug_t *ug = (ma_ug_t *)data; + asg_arc_t *e = &(ug->g->arc[i]); e->ou = 0; + uint32_t v = e->ul>>32, w = e->v, k, uv, uw; + uint64_t *a, a_n; uc_block_t *p, *n; + a = UL_INF.ridx.occ.a + UL_INF.ridx.idx.a[v>>1]; + a_n = UL_INF.ridx.idx.a[(v>>1)+1] - UL_INF.ridx.idx.a[v>>1]; + for (k = 0; k < a_n; k++) { + p = &(UL_INF.a[a[k]>>32].bb.a[(uint32_t)(a[k])]); + if(p->base || (!p->el) || (!p->pchain)) continue; + uv = (((uint32_t)(p->hid))<<1)|((uint32_t)(p->rev)); + if((uv == v) && (p->aidx != (uint32_t)-1)) { + n = &(UL_INF.a[a[k]>>32].bb.a[p->aidx]); + assert((!n->base)&&(n->el)&&(n->pchain)&&(n->pidx==((uint32_t)(a[k])))); + uw = (((uint32_t)(n->hid))<<1)|((uint32_t)(n->rev)); + if(uw == w) e->ou++; + } + + if(((uv^1) == v) && (p->pidx != (uint32_t)-1)) { + n = &(UL_INF.a[a[k]>>32].bb.a[p->pidx]); + // if(!((!n->base)&&(n->el)&&(n->pchain)&&(n->aidx==((uint32_t)(a[k]))))) { + // fprintf(stderr, "ulid->%ld, n->base::%u, n->el::%u, n->pchain::%u, n->aidx::%u, ((uint32_t)(a[k]))::%u\n", + // i, n->base, n->el, n->pchain, n->aidx, ((uint32_t)(a[k]))); + // } + assert((!n->base)&&(n->el)&&(n->pchain)&&(n->aidx==((uint32_t)(a[k])))); + uw = (((uint32_t)(n->hid))<<1)|((uint32_t)(n->rev)); uw ^= 1; + if(uw == w) e->ou++; + } + } +} + +void update_ug_arch_ul_mul(ma_ug_t *ug) +{ + kt_for(asm_opt.thread_num, update_ug_arch_ul, ug, ug->g->n_arc); +} + +static void filter_short_ulalignments(void *data, long i, int tid) // callback for kt_for() +{ + const ma_ug_t *ug = (ma_ug_t *)data; + uc_block_t *a = NULL; uc_block_t *p; int64_t k, a_n; uint32_t z, fz, lz, l, bz; + a = UL_INF.a[i].bb.a; a_n = UL_INF.a[i].bb.n; + + for (k = a_n - 1; k >= 0; k--) { + p = &(a[k]); + // if(i == 338344) { + // fprintf(stderr, "+[M::%s::id->%ld::rlen->%u::glen->%u] (%ld) utg%.6dl, q::[%u, %u), t::[%u, %u), pidx::%u, aidx::%u, pdis::%u, a[k].base::%u, a[k].el::%u, a[k].pchain::%u\n", + // __func__, i, UL_INF.a[i].rlen, ug->u.a[p->hid].len, k, (int32_t)a[k].hid+1, a[k].qs, a[k].qe, a[k].ts, a[k].te, a[k].pidx, a[k].aidx, a[k].pdis, + // a[k].base, a[k].el, a[k].pchain); + // } + if(p->base || (!p->el) || (!p->pchain)) continue; + if(p->pidx == (uint32_t)-1) { + if(!ugl_cover_check(p->ts, p->te, &(ug->u.a[p->hid]))) { + p->pchain = 0; + if(p->aidx != (uint32_t)-1) { + a[p->aidx].pidx = a[p->aidx].pdis = (uint32_t)-1; p->aidx = (uint32_t)-1; + } + } + continue; + } + if(ugl_cover_check(p->ts, p->te, &(ug->u.a[p->hid]))) continue; + for (z = p->pidx; z != (uint32_t)-1; z = a[z].pidx) { + if(ugl_cover_check(a[z].ts, a[z].te, &(ug->u.a[a[z].hid]))) break; + } + lz = z; fz = p->aidx; l = 0; if(fz != (uint32_t)-1) l = a[fz].pdis; + for (z = k; z != lz; z = bz) { + bz = a[z].pidx; l += a[z].pdis; + a[z].pidx = a[z].pdis = a[z].aidx = (uint32_t)-1; a[z].pchain = 0; + } + + if(fz != (uint32_t)-1 && lz != (uint32_t)-1) { + a[fz].pdis = l; a[fz].pidx = lz; a[lz].aidx = fz; + } else if(fz != (uint32_t)-1) { + a[fz].pdis = a[fz].pidx = (uint32_t)-1; + } else if(lz != (uint32_t)-1) { + a[lz].aidx = (uint32_t)-1; + } + } + + for (k = a_n - 1; k >= 0; k--) { + p = &(a[k]); + if(p->base || (!p->el) || (!p->pchain)) continue; + if(p->pidx != (uint32_t)-1) { + if((a[p->pidx].aidx != ((uint32_t)k)) && (a[p->pidx].aidx == ((uint32_t)-1))) { + p->pidx = (uint32_t)-1; + } else { + assert(a[p->pidx].aidx == (uint32_t)k); + assert(a[p->pidx].pchain); + } + } + if(p->aidx != (uint32_t)-1) { + if((a[p->aidx].pidx != (uint32_t)k) && (a[p->aidx].pidx == ((uint32_t)-1))) { + p->aidx = (uint32_t)-1; + } else { + assert(a[p->aidx].pidx == (uint32_t)k); + assert(a[p->aidx].pchain); + } + + } + } + + for (k = a_n - 1; k >= 0; k--) { + p = &(a[k]); + if(p->base || (!p->el) || (!p->pchain)) continue; + // if(i == 338344) { + // fprintf(stderr, "-[M::%s::id->%ld::rlen->%u::glen->%u] (%ld) utg%.6dl, q::[%u, %u), t::[%u, %u), pidx::%u, aidx::%u, pdis::%u, a[k].base::%u, a[k].el::%u, a[k].pchain::%u\n", + // __func__, i, UL_INF.a[i].rlen, ug->u.a[p->hid].len, k, (int32_t)a[k].hid+1, a[k].qs, a[k].qe, a[k].ts, a[k].te, a[k].pidx, a[k].aidx, a[k].pdis, + // a[k].base, a[k].el, a[k].pchain); + // } + if(p->pidx != (uint32_t)-1) { + // if(!(a[p->pidx].aidx == (uint32_t)k)) { + // fprintf(stderr, "[M::%s::id->%ld] name::%.*s, a_n::%ld\n", __func__, + // i, (int32_t)UL_INF.nid.a[i].n, UL_INF.nid.a[i].a, a_n); + // } + assert(a[p->pidx].aidx == (uint32_t)k); + assert(a[p->pidx].pchain); + } + if(p->aidx != (uint32_t)-1) { + // if(a[p->aidx].pidx != (uint32_t)k) { + // fprintf(stderr, "[M::%s::id->%ld] name::%.*s, a_n::%ld, p->aidx::%u, p->pidx::%u, a[p->aidx].pidx::%u\n", __func__, i, (int32_t)UL_INF.nid.a[i].n, UL_INF.nid.a[i].a, a_n, + // p->aidx, p->pidx, a[p->aidx].pidx); + // } + assert(a[p->aidx].pidx == (uint32_t)k); + assert(a[p->aidx].pchain); + } + } +} + + +static void dcheck_ulalignments_mul(void *data, long i, int tid) // callback for kt_for() +{ + if(!ck_ul_alignment(&(UL_INF.a[i]))) UL_INF.a[i].rlen |= (uint32_t)(0x80000000); +} + + + +void print_ul_alignment(ma_ug_t *ug, all_ul_t *aln, uint32_t id, const char* cmd) +{ + uc_block_t *a = NULL; int64_t k, a_n; + a = aln->a[id].bb.a; a_n = aln->a[id].bb.n; + fprintf(stderr, "\n%s::[M::%s::ul_id->%u::a_n->%ld]\n", cmd, __func__, id, a_n); + for (k = 0; k < a_n; k++) { + fprintf(stderr, "[k->%ld::utg%.6d%c(len->%u)]\tts::%u\tte::%u\t%c\tqs::%u\tqe::%u\tpchain::%u\tpidx::%u\taidx::%u\tpdis::%u\n", + k, a[k].hid + 1, "lc"[ug->u.a[a[k].hid].circ], ug->u.a[a[k].hid].len, + a[k].ts, a[k].te, "+-"[a[k].rev], a[k].qs, a[k].qe, a[k].pchain, a[k].pidx, a[k].aidx, a[k].pdis); + + } + +} + + +void filter_ul_ug(ma_ug_t *ug) +{ + kt_for(asm_opt.thread_num, filter_short_ulalignments, ug, UL_INF.n); +} + + +int32_t find_ul_block_max_reverse(int32_t n, const uc_block_t *a, uint32_t x) +{ + int32_t s = 0, e = n; + if (n == 0) return n; + if (a[0].qe < x) return 0;///max qe + if (a[n-1].qe >= x) return n;///min qe + + while (e > s) { // TODO: finish this block + int32_t m = s + (e - s) / 2; + // if (a[m].qe >= x) e = m; + // else s = m + 1; + if (a[m].qe > x) s = m + 1; + else e = m; + } + assert(s == e); + return s; +} + +int32_t find_ul_block_max(int32_t n, const uc_block_t *a, uint32_t x) +{ + int32_t s = 0, e = n; + if (n == 0) return -1; + if (a[n-1].qe < x) return n - 1; + if (a[0].qe >= x) return -1; + while (e > s) { // TODO: finish this block + int32_t m = s + (e - s) / 2; + if (a[m].qe >= x) e = m; + else s = m + 1; + } + assert(s == e); + return s; +} +/** +void determine_connective(all_ul_t *m, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, ul_vec_t *p, uint32_t ii, uint64_t rid) +{ + if((p->bb.a[ii].base) || p->bb.a[ii].hid != rid) fprintf(stderr, "ERROR\n"); + if(p->bb.n <= ii + 1) return; + uint32_t li_v, lk_v, k, ol; int64_t mm_ovlp, x; + uc_block_t *li = NULL, *lk = NULL; + ma_hit_t *t = NULL; + li = &(p->bb.a[ii]); li_v = (((uint32_t)(li->hid))<<1)|((uint32_t)(li->rev)); + mm_ovlp = max_ovlp_src(uopt, li_v^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > p->rlen+1) x = p->rlen+1; + x = find_ul_block_max_rev(p->bb.n - ii - 1, p->bb.a + ii + 1, x) + ii + 1; + for (k = x; k < p->bb.n; ++k) { // collect potential destination vertices + lk = &(p->bb.a[k]); lk_v = (((uint32_t)(lk->hid))<<1)|((uint32_t)(lk->rev)); + if(lk->qe <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore + if((li_v == lk_v) || (lk->base)) continue; + // if(li->qs <= 0) continue;///means the UL read does not longer than the overlap between li and lk + // if(lk->qs <= 0) continue;//the UL read should be cover the whole HiFi reads li and lk + if(((li->te - li->ts)*1.05) < Get_READ_LENGTH(R_INF, li->hid)) continue; + if(((lk->te - lk->ts)*1.05) < Get_READ_LENGTH(R_INF, lk->hid)) continue; + x = infer_rovlp(NULL, NULL, li, lk, &R_INF, NULL); + t = query_ovlp_src(uopt, li_v^1, lk_v^1, x, diff_ec_ul, &ol); + if(t) { + // sum = t->bl + ol; + // t->bl = (sum & 0x7fffffffU); + t->bl++; + } + } +} +**/ + +///note: we only label reliable chains +void determine_connective_adv(all_ul_t *m, const ug_opt_t *uopt, int64_t bw, double diff_ec_ul, ul_vec_t *p, uint32_t ii, uint64_t rid) +{ + assert((!p->bb.a[ii].base)&&(p->bb.a[ii].hid == rid)); + if(ii <= 0) return; + if(!(p->bb.a[ii].pchain)) return; ///not a primary chain + if(!(p->bb.a[ii].el)) return; ///not a cis alignment + uint32_t li_v, lk_v, ol; int64_t mm_ovlp, k, x; + uc_block_t *li = NULL, *lk = NULL; + ma_hit_t *t = NULL; + li = &(p->bb.a[ii]); li_v = (((uint32_t)(li->hid))<<1)|((uint32_t)(li->rev)); + mm_ovlp = max_ovlp_src(uopt, li_v^1); + x = (li->qs + mm_ovlp)*diff_ec_ul; + if(x < bw) x = bw; + x += li->qs + mm_ovlp; + if (x > p->rlen+1) x = p->rlen+1; + x = find_ul_block_max(ii, p->bb.a, x+G_CHAIN_INDEL); + for (k = x; k >= 0; --k) { // collect potential destination vertices + lk = &(p->bb.a[k]); lk_v = (((uint32_t)(lk->hid))<<1)|((uint32_t)(lk->rev)); + if(lk->qe+G_CHAIN_INDEL <= li->qs) break;//even this pair has a overlap, its length will be very small; just ignore + if(lk->base || (!(lk->pchain)) || (!(lk->el))) continue; + if(li_v == lk_v) continue; + // if(li->qs <= 0) continue;///means the UL read does not longer than the overlap between li and lk + // if(lk->qs <= 0) continue;//the UL read should be cover the whole HiFi reads li and lk + // if(((li->te - li->ts)*1.05) < Get_READ_LENGTH(R_INF, li->hid)) continue; + // if(((lk->te - lk->ts)*1.05) < Get_READ_LENGTH(R_INF, lk->hid)) continue; + if((li->te - li->ts) < Get_READ_LENGTH(R_INF, li->hid)) continue; + if((lk->te - lk->ts) < Get_READ_LENGTH(R_INF, lk->hid)) continue; + x = /**((int64_t)(lk->qe))-((int64_t)(li->qs))**/infer_rovlp(NULL, NULL, li, lk, &R_INF, NULL); + t = query_ovlp_src(uopt, li_v^1, lk_v^1, x, diff_ec_ul, &ol); + if(t) { + // sum = t->bl + ol; + // t->bl = (sum & 0x7fffffffU); + t->bl++; + } + } +} + +void determine_connective_backtrack(all_ul_t *m, const ug_opt_t *uopt, ul_vec_t *p, uint32_t ii, uint64_t rid, uint64_t ulid) +{ + assert((!p->bb.a[ii].base)&&(p->bb.a[ii].hid == rid)&&(p->bb.a[ii].el)); + if(ii <= 0) return; + if(!(p->bb.a[ii].pchain)) return; ///not a primary chain + if(p->bb.a[ii].pidx == (uint32_t)-1) return; ///not connected + uint32_t li_v, lk_v, z, qn, tn; int32_t r; uc_block_t *li = NULL, *lk = NULL; asg_arc_t t; + li = &(p->bb.a[ii]); li_v = (((uint32_t)(li->hid))<<1)|((uint32_t)(li->rev)); li_v^=1; + if((li->te - li->ts) < Get_READ_LENGTH(R_INF, li->hid)) return; + ma_hit_t_alloc *x = &(uopt->sources[li_v>>1]); + int64_t min_ovlp = uopt->min_ovlp; + int64_t max_hang = uopt->max_hang; + // if(rid == 4217) fprintf(stderr, "rid: %lu, p->bb.n: %u\n", rid, p->bb.n); + + for (lk = &(p->bb.a[li->pidx]); lk; ) { + lk_v = (((uint32_t)(lk->hid))<<1)|((uint32_t)(lk->rev)); lk_v^=1; + assert((!(lk->base)) && (lk->pchain) && (lk->el)); + if((lk->te - lk->ts) >= Get_READ_LENGTH(R_INF, lk->hid)) { + for (z = 0; z < x->length; z++) { + qn = Get_qn(x->buffer[z]); + tn = Get_tn(x->buffer[z]); + if(qn == (li_v>>1) && tn == (lk_v>>1)) { + r = ma_hit2arc(&(x->buffer[z]), Get_READ_LENGTH(R_INF, li_v>>1), Get_READ_LENGTH(R_INF, lk_v>>1), + max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + if(r < 0) continue; + if((t.ul>>32) != li_v || t.v != lk_v) continue; + break; + } + } + if(z < x->length) { + x->buffer[z].bl++; + // if(((li_v>>1) == 1656459) || ((li_v>>1) == 4179430)|| + // ((lk_v>>1) == 1656459) || ((lk_v>>1) == 4179430)) { + // fprintf(stderr, "[M::%s::]\tulid::%lu\n", __func__, ulid); + // } + } + } + + lk = ((lk->pidx==(uint32_t)-1)?NULL:&(p->bb.a[lk->pidx])); + } +} + +static void update_ovlp_src(void *data, long i, int tid) // callback for kt_for() +{ + uldat_t *sl = (uldat_t *)data; + ma_hit_t_alloc* src = sl->uopt->sources; + uint64_t z, k, *a, a_n; + for (z = 0; z < src[i].length; z++) src[i].buffer[z].bl = 0; + a = UL_INF.ridx.occ.a + UL_INF.ridx.idx.a[i]; + a_n = UL_INF.ridx.idx.a[i+1] - UL_INF.ridx.idx.a[i]; + // fprintf(stderr, "++i->%d, a_n->%lu++\n", i, a_n); + for (k = 0; k < a_n; k++) { + ///note: we only label reliable chains + // if(i == 4217) fprintf(stderr, "\nul_id: %lu\n", a[k]>>32); + determine_connective_backtrack(&UL_INF, sl->uopt, &(UL_INF.a[a[k]>>32]), (uint32_t)(a[k]), i, a[k]>>32); + // determine_connective_adv(&UL_INF, sl->uopt, G_CHAIN_BW, sl->opt->diff_ec_ul, &(UL_INF.a[a[k]>>32]), (uint32_t)(a[k]), i); + // determine_connective(&UL_INF, sl->uopt, G_CHAIN_BW, sl->opt->diff_ec_ul, + // &(UL_INF.a[a[k]>>32]), (uint32_t)(a[k]), i); + } + // fprintf(stderr, "--i->%d, a_n->%lu--\n", i, a_n); +} + + +static void clean_contained_chg(void *data, long i, int tid) // callback for kt_for() +{ + uldat_t *sl = (uldat_t *)data; + sl->rg->seq_vis[i] = 0; + if(sl->rg->seq[i].del) return; + if(!(is_contain_r((*(sl->uopt->ruIndex)), ((uint64_t)i)))) return; + ma_hit_t_alloc* src = sl->uopt->sources; + uint64_t z; + for (z = 0; z < src[i].length; z++) { + if(src[i].buffer[z].bl) break; + } + if(z >= src[i].length) sl->rg->seq_vis[i] = 1; +} + +static void label_contained_chg(void *data, long i, int tid) // callback for kt_for() +{ + uldat_t *sl = (uldat_t *)data; uint32_t v = i; + sl->rg->seq_vis[v] = 0; + if(sl->rg->seq[v>>1].del) return; + if(is_contain_r((*(sl->uopt->ruIndex)), (v>>1))) { + sl->rg->seq_vis[v] = 1; return; + } + asg_arc_t *av = asg_arc_a(sl->rg, v); + uint32_t nv = asg_arc_n(sl->rg, v), k; + for (k = 0; k < nv; ++k) { + if(av[k].del) continue; + if(is_contain_r((*(sl->uopt->ruIndex)), (av[k].v>>1))) break; + } + if(k < nv) sl->rg->seq_vis[v] = 1; +} + + +uint64_t* get_hifi2ul_list(all_ul_t *x, uint64_t hid, uint64_t* a_n) +{ + (*a_n) = x->ridx.idx.a[hid+1] - x->ridx.idx.a[hid]; + return x->ridx.occ.a + x->ridx.idx.a[hid]; +} + + +static void update_ovlp_src_bl(void *data, long i, int tid) +{ + uldat_t *sl = (uldat_t *)data; + ma_hit_t_alloc* src = sl->uopt->sources; + uint64_t z, sum; uint32_t qn, tn; int32_t idx; + for (z = 0; z < src[i].length; z++) { + qn = Get_qn(src[i].buffer[z]); + tn = Get_tn(src[i].buffer[z]); + if(qn > tn) continue; + idx = get_specific_overlap(&(src[tn]), tn, qn); + assert(idx != -1); + sum = src[i].buffer[z].bl + src[tn].buffer[idx].bl; + src[i].buffer[z].bl = src[tn].buffer[idx].bl = sum/**(sum&0x7fffffffU)**/; + } +} + +int scall_ul_pipeline(uldat_t* sl, const enzyme *fn) +{ + double index_time = yak_realtime(); + int i; + + init_all_ul_t(&UL_INF, &R_INF); + for (i = 0; i < fn->n; i++){ + gzFile fp; + if ((fp = gzopen(fn->a[i], "r")) == 0) return 0; + sl->ks = kseq_init(fp); + kt_pipeline(3, worker_ul_scall_pipeline, sl, 3); + kseq_destroy(sl->ks); + gzclose(fp); + } + sl->hits.total_base = sl->total_base; + sl->hits.total_pair = sl->total_pair; + fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); + fprintf(stderr, "[M::%s::] ==> # reads: %lu, # bases: %lu\n", __func__, UL_INF.n, sl->total_base); + // fprintf(stderr, "[M::%s::] ==> # bases: %lu; # corrected bases: %lu; # recorrected bases: %lu\n", + // __func__, sl->num_bases, sl->num_corrected_bases, sl->num_recorrected_bases); + fprintf(stderr, "[M::%s::] ==> # fully covered reads: %lu\n", __func__, sl->num_bases); + gen_ul_vec_rid_t(&UL_INF, &R_INF, NULL); + return 1; +} + + +int rescall_ul_pipeline(uldat_t* sl, const enzyme *fn) +{ + double index_time = yak_realtime(); + int32_t i; + ///debug + // overall_zdbg = init_mul_debug_prt_t(UL_INF.n); + + for (i = 0; i < fn->n; i++){ + gzFile fp; + if ((fp = gzopen(fn->a[i], "r")) == 0) return 0; + sl->ks = kseq_init(fp); + kt_pipeline(3, worker_ul_rescall_pipeline, sl, 3); + kseq_destroy(sl->ks); + gzclose(fp); + } + sl->hits.total_base = sl->total_base; + sl->hits.total_pair = sl->total_pair; + fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); + fprintf(stderr, "[M::%s::] ==> # reads: %lu, # bases: %lu, # fully corrected reads: %lu\n", + __func__, UL_INF.n, sl->total_base, sl->num_corrected_bases); + // fprintf(stderr, "[M::%s::] ==> # bases: %lu; # corrected bases: %lu; # recorrected bases: %lu\n", + // __func__, sl->num_bases, sl->num_corrected_bases, sl->num_recorrected_bases); + // gen_ul_vec_rid_t(&UL_INF); + // for (i = 0; i < UL_INF.n; i++) { + // fprintf(stderr, "[M::%s] rid::%d, dd::%u\n", __func__, i, UL_INF.a[i].dd); + // } + // print_mul_debug_prt_t(asm_opt.output_file_name, overall_zdbg); + // print_raw_uls_seq_direct(sl->uu->ug, &UL_INF, asm_opt.output_file_name); + + return 1; +} + + +int recorrect_ul_pipeline(uldat_t* sl, const enzyme *fn) +{ + double index_time = yak_realtime(); + int32_t i; + + for (i = 0; i < fn->n; i++){ + gzFile fp; + if ((fp = gzopen(fn->a[i], "r")) == 0) return 0; + sl->ks = kseq_init(fp); + kt_pipeline(2, worker_ul_recorrect_pipeline, sl, 2); + kseq_destroy(sl->ks); + gzclose(fp); + } + sl->hits.total_base = sl->total_base; + sl->hits.total_pair = sl->total_pair; + fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); + fprintf(stderr, "[M::%s::] ==> # reads: %lu, # processed reads: %lu, # fixed reads: %lu\n", + __func__, UL_INF.n, sl->num_bases, sl->num_corrected_bases); + // fprintf(stderr, "[M::%s::] ==> # bases: %lu; # corrected bases: %lu; # recorrected bases: %lu\n", + // __func__, sl->num_bases, sl->num_corrected_bases, sl->num_recorrected_bases); + // gen_ul_vec_rid_t(&UL_INF); + return 1; +} + +int print_ul_rs(all_ul_t *U_INF) +{ + uint32_t i; + UC_Read ur; + init_UC_Read(&ur); + for (i = 0; i < U_INF->n; i++) { + retrieve_ul_t(&ur, NULL, U_INF, i, 0, 0, -1); + fprintf(stderr, ">%s\n", U_INF->nid.a[i].a); + fprintf(stderr, "%.*s\n", (int)ur.length, ur.seq); + } + + destory_UC_Read(&ur); + return 1; +} + +inline void get_ulname(mg_dbn_t *name, int32_t rid, char **rn, int32_t *rl) +{ + (*rn) = name->cc.a + (rid>0?name->a[rid-1]:0); + (*rl) = name->a[rid] - (rid>0?name->a[rid-1]:0); +} + +void print_gaf(const ma_ug_t *ug, mg_gres_a *hits, mg_dbn_t *name) +{ + uint64_t i, q; + int32_t k, nl, m; + char *nn; mg_gchain_t *gc; mg_lres_t *lc; + for (i = 0; i < hits->n; i++) { + q = hits->a[i].qid; + nn = name->cc.a + (q>0?name->a[q-1]:0); + nl = name->a[q] - (q>0?name->a[q-1]:0); + for (k = 0; k < hits->a[i].n_gc; k++) { + gc = &(hits->a[i].gc[k]); + fprintf(stderr, "S\t%.*s\tq:id:%lu\tl:n:%d\n", nl, nn, q, gc->cnt); + for (m = 0; m < gc->cnt; m++) { + lc = &(hits->a[i].lc[gc->off + m]); + fprintf(stderr, "*\tA\tutg%.6d%c\t%c\tqs:%u\tqe:%u\tql:%lu\tts:%u\tte:%u\ttl:%u\tcnt:%d\n", + (lc->v>>1)+1, "lc"[ug->u.a[lc->v>>1].circ], "+-"[lc->v&1], lc->qs, lc->qe, hits->a[i].qlen, lc->ts, lc->te, ug->u.a[lc->v>>1].len, lc->cnt); + } + } + } +} + +void write_ul_hits(mg_gres_a *hits, mg_dbn_t *nn, const char *fn) +{ + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.ul.aln.bin", fn); + FILE* fp = fopen(buf, "w"); + uint32_t i; + + fwrite(&hits->n, sizeof(hits->n), 1, fp); + for (i = 0; i < hits->n; i++) { + fwrite(&hits->a[i].qid, sizeof(hits->a[i].qid), 1, fp); + fwrite(&hits->a[i].qlen, sizeof(hits->a[i].qlen), 1, fp); + fwrite(&hits->a[i].n_gc, sizeof(hits->a[i].n_gc), 1, fp); + fwrite(&hits->a[i].n_lc, sizeof(hits->a[i].n_lc), 1, fp); + fwrite(hits->a[i].gc, sizeof(mg_gchain_t), hits->a[i].n_gc, fp); + fwrite(hits->a[i].lc, sizeof(mg_lres_t), hits->a[i].n_lc, fp); + } + // fwrite(hits->a, sizeof(mg_gres_t), hits->n, fp); + fwrite(&hits->total_pair, sizeof(hits->total_pair), 1, fp); + fwrite(&hits->total_base, sizeof(hits->total_base), 1, fp); + + fwrite(&(nn->n), sizeof(nn->n), 1, fp); + fwrite(nn->a, sizeof(uint64_t), nn->n, fp); + fwrite(&(nn->tl), sizeof(nn->tl), 1, fp); + fwrite(&(nn->cc.n), sizeof(nn->cc.n), 1, fp); + fwrite(nn->cc.a, sizeof(char), nn->cc.n, fp); + // write_dbug(ug, fp); + + fclose(fp); + fprintf(stderr, "[M::%s::] ==> UL alignments have been written\n", __func__); + free(buf); +} + +int load_ul_hits(mg_gres_a *hits, mg_dbn_t *nn, const char *fn) +{ + uint64_t flag = 0; + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.ul.aln.bin", fn); + + FILE* fp = NULL; + fp = fopen(buf, "r"); + if(!fp) { + free(buf); + return 0; + } + uint32_t i; + + kv_init(*hits); + flag += fread(&hits->n, sizeof(hits->n), 1, fp); + hits->m = hits->n; MALLOC(hits->a, hits->n); + for (i = 0; i < hits->n; i++) { + flag += fread(&hits->a[i].qid, sizeof(hits->a[i].qid), 1, fp); + flag += fread(&hits->a[i].qlen, sizeof(hits->a[i].qlen), 1, fp); + flag += fread(&hits->a[i].n_gc, sizeof(hits->a[i].n_gc), 1, fp); + flag += fread(&hits->a[i].n_lc, sizeof(hits->a[i].n_lc), 1, fp); + MALLOC(hits->a[i].gc, hits->a[i].n_gc); MALLOC(hits->a[i].lc, hits->a[i].n_lc); + flag += fread(hits->a[i].gc, sizeof(mg_gchain_t), hits->a[i].n_gc, fp); + flag += fread(hits->a[i].lc, sizeof(mg_lres_t), hits->a[i].n_lc, fp); + } + // flag += fread(hits->a, sizeof(mg_gres_t), hits->n, fp); + flag += fread(&hits->total_pair, sizeof(hits->total_pair), 1, fp); + flag += fread(&hits->total_base, sizeof(hits->total_base), 1, fp); + + memset(nn, 0, sizeof(*nn)); + flag += fread(&(nn->n), sizeof(nn->n), 1, fp); + nn->m = nn->n; MALLOC(nn->a, nn->n); + flag += fread(nn->a, sizeof(uint64_t), nn->n, fp); + flag += fread(&(nn->tl), sizeof(nn->tl), 1, fp); + flag += fread(&(nn->cc.n), sizeof(nn->cc.n), 1, fp); + nn->cc.m = nn->cc.n; MALLOC(nn->cc.a, nn->cc.n); + flag += fread(nn->cc.a, sizeof(char), nn->cc.n, fp); + + free(buf); + + // if(!test_dbug(ug, fp)) + // { + // free(hits->a.a); + // kv_init(hits->a); + // fclose(fp); + // fprintf(stderr, "[M::%s::] ==> Renew Hi-C linkages\n", __func__); + // return 0; + // } + + fclose(fp); + fprintf(stderr, "[M::%s::] ==> UL alignments have been loaded\n", __func__); + return 1; +} + +void get_asm_cov(ma_ug_t *ug, uint64_t ul_base, mul_ov_t *aov) +{ + int64_t ss = asm_opt.hg_size; + if(ss < 0) { + uint64_t i, k, an; + int64_t sp; + asg_t *g = ug->g; + asg_arc_t *av = NULL; + for (i = 0, ss = 0; i < g->n_seq; i++) { + sp = g->seq[i].len; av = asg_arc_a(g, i); an = asg_arc_n(g, i); + for (k = 0; k < an; k++) { + if(av[k].del) continue; + if((av[k].v) < i) { + sp -= ((int64_t)av[k].ol); + } + } + if(sp > 0) ss += sp; + } + } else { + ss *= asm_opt.polyploidy; + } + + if(ss <= 0) ss = 1; + + aov->asm_cov = ul_base/ss; aov->asm_size = ss; + fprintf(stderr, "[M::%s::] ==> asm_cov: %lu, asm_size: %lu\n", __func__, aov->asm_cov, aov->asm_size); +} + +int32_t spec_ovlp_occ(eg_srt_t *a, int32_t a_n, int32_t st, int32_t vv, int32_t c_thres) +{ + int32_t i, dst = a[st].d, occ = 1; + if(occ >= c_thres) return 1; + for (i = st + 1; i < a_n; i++) { + if(a[i].id == a[st].id) continue; + if(a[i].d - dst <= vv) { + occ++; + if(occ >= c_thres) return 1; + } + } + + for (i = st - 1; i >= 0; i--) { + if(a[i].id == a[st].id) continue; + if(dst - a[i].d <= vv) { + occ++; + if(occ >= c_thres) return 1; + } + } + return 0; +} + + +int32_t get_spec_ovlp_occ(eg_srt_t *a, int32_t a_n, int32_t st, int32_t vv, int32_t c_thres, int32_t *s, int32_t *e, kvec_t_u64_warp *res) +{ + int32_t i, dst = a[st].d, occ = 1, pp; + (*s) = (*e) = st; res->a.n = 0; + for (i = st + 1; i < a_n; i++) { + if(a[i].d - dst <= vv) { + (*e) = i; + if(a[i].id == a[st].id) continue; + occ++; kv_push(uint64_t, res->a, (((uint64_t)(a[i].id))<<32)|i); + } else { + break; + } + } + + for (i = st - 1; i >= 0; i--) { + if(dst - a[i].d <= vv) { + (*s) = i; + if(a[i].id == a[st].id) continue; + occ++; kv_push(uint64_t, res->a, (((uint64_t)(a[i].id))<<32)|i); + } else { + break; + } + } + if(occ >= c_thres) { + radix_sort_gfa64(res->a.a, res->a.a + res->a.n); + for (i = 0, pp = -1, occ = 0; i < (int32_t)res->a.n; i++) { + if((int32_t)(res->a.a[i]>>32) != pp) { + pp = (res->a.a[i]>>32); + res->a.a[occ] = res->a.a[i]; + occ++; + } + } + res->a.n = occ; + if(occ >= c_thres) return occ; + return 0; + } + else { + return 0; + } +} + +void clean_ul_g(asg_t *xg) +{ + uint32_t n_vtx = xg->n_seq * 2, v, i, nv, ie = 0, ike = 0; + asg_arc_t *av = NULL; + uint8_t* bs_flag = NULL; CALLOC(bs_flag, n_vtx); + buf_t b; memset(&b, 0, sizeof(buf_t)); b.a = (binfo_t*)calloc(n_vtx, sizeof(binfo_t)); + uint64_t max_dist = get_bub_pop_max_dist_advance(xg, &b); + for (v = 0; v < xg->n_seq; v++) xg->seq[v].c = 0; + for (v = 0; v < n_vtx; ++v) { + if(bs_flag[v] != 0) continue; + if (asg_arc_n(xg, v) < 2 || xg->seq[v>>1].del) continue; + if(asg_bub_pop1_primary_trio(xg, NULL, v, max_dist, &b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (i = 0; i < b.b.n; i++) { + if(b.b.a[i]==v || b.b.a[i]==b.S.a[0]) continue; + bs_flag[b.b.a[i]] = bs_flag[b.b.a[i]^1] = 1; + } + bs_flag[v] = 2; bs_flag[b.S.a[0]^1] = 3; + } + } + + for (v = 0; v < n_vtx; ++v) { + if(bs_flag[v] != 0) continue; + nv = asg_arc_n(xg, v); + if (nv >= 2) { + av = asg_arc_a(xg, v); + for (i = 0; i < nv; ++i){ + if (av[i].ol == 0) { + av[i].del = 1; + asg_arc_del(xg, av[i].v^1, (av[i].ul>>32)^1, 1); + // fprintf(stderr, "---q0-utg%.6d%c, q1-utg%.6d%c\n", + // (int32_t)((av[i].ul>>33)+1), "lc"[ug->u.a[av[i].ul>>33].circ], + // (int32_t)((av[i].v)>>1)+1, "lc"[ug->u.a[av[i].v].circ]); + } + + // fprintf(stderr, "xxxx-nv: %u, q0-utg%.6d%c, q1-utg%.6d%c\n", nv, + // (int32_t)((av[i].ul>>33)+1), "lc"[ug->u.a[av[i].ul>>33].circ], + // (int32_t)((av[i].v)>>1)+1, "lc"[ug->u.a[av[i].v].circ]); + } + } + } + + for (i = 0; i < xg->n_arc; i++) { + if(xg->arc[i].ol == 0) { + ie++; + if(!xg->arc[i].del) ike++; + } + } + + fprintf(stderr, "[M::%s::] ==> # fill gaps: %u, # keep gaps: %u\n", __func__, ie, ike); + free(bs_flag); free(b.a); free(b.S.a); free(b.T.a); free(b.b.a); free(b.e.a); +} + +// int32_t max_cluster(int32_t mmi, double vv, int32_t min_off, eg_srt_t *a, int32_t a_n, int32_t st, int32_t st_occ, int32_t *s, int32_t *e, kvec_t_u64_warp *res) +// { +// int32_t i, k, iocc, ovlp; +// for (i = st, iocc = 0; i < k; i++) { +// ovlp = (a[i].d > mmi? a[i].d - mmi: mmi - a[i].d) * vv; +// if(ovlp < min_off) ovlp = min_off; +// // fprintf(stderr, "i-%lu, ovlp: %d, td.a[i].d: %d, qid: %u\n", i, ovlp, td.a[i].d, td.a[i].id); +// // if(spec_ovlp_occ(td.a + l, k-l, i - l, ovlp, c_thres)) break; +// iocc = get_spec_ovlp_occ(td.a + l, k-l, i - l, ovlp, c_thres, &is, &ie, &tidx); +// if(iocc >= c_thres) break; +// } +// } + +void get_ul_g(mul_ov_t *aov, mg_gres_a *hits, ma_ug_t *ug, const asg_t *rg, +double cov_thres, double vv, int32_t min_off, int32_t min_read_ovlp) +{ + int64_t c_thres = (aov->asm_cov*cov_thres)>2?(aov->asm_cov*cov_thres):2; + uint64_t i, k, l, m, v0, v1, r0, r1; + int32_t qs, qe, rs, re, qs0, qe0, qs1, qe1, ovlp, mmi, nngc2 = 0, is, ie, iocc, m_iocc, max_i; + mg_gres_t *p = NULL; + mg_gchain_t *gc = NULL, *gc0, *gc1; + mg_lres_t *lf = NULL, *ll = NULL; + asg_t *xg = copy_read_graph(ug->g); + asg_arc_t *pe = NULL; + kvec_t(lc_srt_t) tt; kv_init(tt); lc_srt_t *pt = NULL; + kvec_t(eg_srt_t) td; kv_init(td); eg_srt_t *pd = NULL; + kvec_t_u64_warp tidx; kv_init(tidx.a); + ///for debug + kvec_t(eg_srt_t) dbg_vw_srt; kv_init(dbg_vw_srt); + for (i = 0; i < hits->n; i++) { + // fprintf(stderr, "+i+: %lu\n",i); + p = &(hits->a[i]); tt.n = 0; + // fprintf(stderr, "-i-: %lu\n",i); + if(p->n_gc < 2) continue; + nngc2++; + // fprintf(stderr, "\nsis: %lu, p->n_gc: %d\n",i,p->n_gc); + for (k = 0; k < (uint64_t)p->n_gc; k++) { + gc = &(p->gc[k]); + assert(gc->cnt > 0); + lf = &(p->lc[gc->off]); ll = gc->cnt>1?&(p->lc[gc->off+gc->cnt-1]):NULL; + assert(lf->qs != (uint32_t)-1); + if(ll) assert(ll->qs != (uint32_t)-1); + + transfor_icoord(lf->qs, lf->qe, lf->ts, lf->te, lf->v&1, p->qlen, ug->g->seq[lf->v>>1].len, + &qs, ll?NULL:&qe, &rs, ll?NULL:&re); + if(ll) { + transfor_icoord(ll->qs, ll->qe, ll->ts, ll->te, ll->v&1, p->qlen, ug->g->seq[ll->v>>1].len, + NULL, &qe, NULL, &re); + } else { + ll = lf; + } + if(qe - qs < min_read_ovlp || re - rs < min_read_ovlp) continue; + kv_pushp(lc_srt_t, tt, &pt); + pt->qse = qs; pt->qse <<= 32; pt->qse |= qe; + pt->rse = rs; pt->rse <<= 32; pt->rse |= re; + pt->gld = i; pt->gld <<= 32; pt->gld |= k; + // fprintf(stderr, ">>>>k: %lu, qs: %d, qe: %d, qs-utg%.6d%c, qe-utg%.6d%c\n", k, qs, qe, + // (int32_t)((lf->v>>1)+1), "lc"[ug->u.a[lf->v>>1].circ], + // (int32_t)((ll->v>>1)+1), "lc"[ug->u.a[ll->v>>1].circ]); + // fprintf(stderr, "lf_qs: %u, lf_qe: %u, lf_ts: %u, lf_te: %u\n", lf->qs, lf->qe, lf->ts, lf->te); + // fprintf(stderr, "ll_qs: %u, ll_qe: %u, ll_ts: %u, ll_te: %u\n", ll->qs, ll->qe, ll->ts, ll->te); + } + // fprintf(stderr, "eie: %lu\n",i); + radix_sort_lc_srt(tt.a, tt.a + tt.n); + for (k = 0; k < tt.n; k++) { + for (m = k + 1; m < tt.n; m++) { + gc0 = &(p->gc[(uint32_t)(tt.a[k].gld)]); + v0 = p->lc[gc0->off+gc0->cnt-1].v; + gc1 = &(p->gc[(uint32_t)(tt.a[m].gld)]); + v1 = p->lc[gc1->off].v; + if((v0>>1) == (v1>>1)) continue; + + qs0 = tt.a[k].qse>>32; qe0 = (uint32_t)(tt.a[k].qse); + qs1 = tt.a[m].qse>>32; qe1 = (uint32_t)(tt.a[m].qse); + // fprintf(stderr, "++++k: %lu, qs0: %d, qe0: %d, qs1: %d, qe1: %d, q0-utg%.6d%c, q1-utg%.6d%c\n", + // k, qs0, qe0, qs1, qe1, (int32_t)((v0>>1)+1), "lc"[ug->u.a[v0>>1].circ], (int32_t)((v1>>1)+1), "lc"[ug->u.a[v1>>1].circ]); + if(qs1 <= qs0 && qe1 >= qe0) continue;///contain + if(qs0 <= qs1 && qe0 >= qe1) continue;///contain + if(ug->u.a[v0>>1].circ || ug->u.a[v1>>1].circ) continue; + ovlp = ((MIN((qe0), (qe1)) > MAX((qs0), (qs1)))? MIN((qe0), (qe1)) - MAX((qs0), (qs1)):0); + r0 = v0&1?(ug->u.a[v0>>1].start>>1):(ug->u.a[v0>>1].end>>1); + r1 = v1&1?(ug->u.a[v1>>1].end>>1):(ug->u.a[v1>>1].start>>1); + // fprintf(stderr, "----k: %lu, ovlp: %d\n", k, ovlp); + // if((ovlp == 0) || (ovlp <= ((qe0 - qs0)*vv) && ovlp <= ((qe1 - qs1)*vv)) || + // (asg_arc_n(ug->g, v0) == 0 && asg_arc_n(ug->g, v1^1) == 0)) { + if(/**(asg_arc_n(ug->g, v0) == 0 && asg_arc_n(ug->g, v1^1) == 0) + && **/(ovlp < (int32_t)(MIN(rg->seq[r0].len, rg->seq[r1].len)))) { + kv_pushp(eg_srt_t, td, &pd); + pd->d = MAX((qs0), (qs1)) - MIN((qe0), (qe1)); + pd->x = v0id = p->qid; + pd->e = (uint32_t)(tt.a[k].gld); + pd->e <<= 32; pd->e |= (uint32_t)(tt.a[m].gld); + } + } + } + } + fprintf(stderr, "td.n: %d\n", (int)td.n); + radix_sort_eg_srt_x(td.a, td.a + td.n); + for (k = 1, l = 0; k <= td.n; ++k) + { + if (k == td.n || td.a[k].x != td.a[l].x) + { + if(k - l >= (uint64_t)c_thres) { + for (i = l+1, mmi = l; i < k; i++) { + if(td.a[mmi].d > td.a[i].d) mmi = i; + } + mmi = td.a[mmi].d < 0? -td.a[mmi].d:0; + if(mmi != 0) { + for (i = l; i < k; i++) td.a[i].d += mmi; + } + + + radix_sort_eg_srt_d(td.a + l, td.a + k); + for (i = l, iocc = 0, tidx.a.n = 0; i < k; i++) { + ovlp = (td.a[i].d > mmi? td.a[i].d - mmi: mmi - td.a[i].d) * vv; + if(ovlp < min_off) ovlp = min_off; + // fprintf(stderr, "i-%lu, ovlp: %d, td.a[i].d: %d, qid: %u\n", i, ovlp, td.a[i].d, td.a[i].id); + // if(spec_ovlp_occ(td.a + l, k-l, i - l, ovlp, c_thres)) break; + iocc = get_spec_ovlp_occ(td.a + l, k-l, i - l, ovlp, c_thres, &is, &ie, &tidx); + // fprintf(stderr, "c_thres-%ld, iocc-%d\n", c_thres, iocc); + if(iocc >= c_thres) break; + } + + + + if(i < k) { + m_iocc = iocc; max_i = i; + for (i = ie + 1; i < k; i++) { + iocc = get_spec_ovlp_occ(td.a + l, k-l, i - l, ovlp, m_iocc, &is, &ie, &tidx); + if(iocc > m_iocc) m_iocc = iocc, max_i = i; + i = ie + l; + } + ///for debug + kv_pushp(eg_srt_t, dbg_vw_srt, &pd); + pd->x = m_iocc; pd->e = td.a[l].x; + + v0 = (uint32_t)td.a[l].x; v1 = td.a[l].x>>32; + pe = asg_arc_pushp(xg); + pe->del = 0; pe->strong = 0; pe->el = 0; pe->no_l_indel = 0; pe->ol = 0; + pe->v = v0; pe->ul = v1<<32; pe->ul += xg->seq[v1>>1].len; + + v0 = (td.a[l].x>>32)^1; v1 = ((uint32_t)td.a[l].x)^1; + pe = asg_arc_pushp(xg); + pe->del = 0; pe->strong = 0; pe->el = 0; pe->no_l_indel = 0; pe->ol = 0; + pe->v = v0; pe->ul = v1<<32; pe->ul += xg->seq[v1>>1].len; + + // fprintf(stderr, "++++q0-utg%.6d%c, q1-utg%.6d%c, k-l: %lu, c_thres: %ld, flag: %u\n", + // (int32_t)((td.a[l].x>>33)+1), "lc"[ug->u.a[td.a[l].x>>33].circ], + // (int32_t)(((uint32_t)td.a[l].x)>>1)+1, "lc"[ug->u.a[(((uint32_t)td.a[l].x)>>1)].circ], k-l, c_thres, + // (asg_arc_n(ug->g, ((uint32_t)td.a[l].x)^1) == 0 && asg_arc_n(ug->g, (td.a[l].x>>32)) == 0)); + } + } + l = k; + } + } + + xg->is_srt = 0; xg->idx = 0; free(xg->idx); + asg_cleanup(xg); + clean_ul_g(xg); + + ///for debug + fprintf(stderr, "[M::%s::] ==> nngc2: %d\n", __func__, nngc2); + radix_sort_eg_srt_x(dbg_vw_srt.a, dbg_vw_srt.a + dbg_vw_srt.n); + for (max_i = (int32_t)dbg_vw_srt.n - 1; max_i >= 0; --max_i) { + pd = &(dbg_vw_srt.a[max_i]); + fprintf(stderr, "++++q0-utg%.6d%c, q1-utg%.6d%c, occ: %lu, c_thres: %ld, flag: %u\n", + (int32_t)((pd->e>>33)+1), "lc"[ug->u.a[pd->e>>33].circ], + (int32_t)(((uint32_t)pd->e)>>1)+1, "lc"[ug->u.a[(((uint32_t)pd->e)>>1)].circ], pd->x, c_thres, + (asg_arc_n(ug->g, ((uint32_t)pd->e)^1) == 0 && asg_arc_n(ug->g, (pd->e>>32)) == 0)); + } + + + kv_destroy(tt); kv_destroy(td); kv_destroy(tidx.a); kv_destroy(dbg_vw_srt); + asg_destroy(xg); +} + +int ul_align(mg_idxopt_t *opt, const ug_opt_t *uopt, const asg_t *rg, const enzyme *fn, void *ha_flt_tab, ha_pt_t *ha_idx, ma_ug_t *ug) +{ + uldat_t sl; memset(&sl, 0, sizeof(sl)); + sl.ha_flt_tab = ha_flt_tab; + sl.ha_idx = ha_idx; + sl.opt = opt; + sl.chunk_size = 200000000; + sl.n_thread = asm_opt.thread_num; + sl.ug = ug; + sl.rg = rg; + sl.uopt = uopt; + if(!load_ul_hits(&sl.hits, &sl.nn, asm_opt.output_file_name)) { + alignment_ul_pipeline(&sl, fn); + write_ul_hits(&sl.hits, &sl.nn, asm_opt.output_file_name); + } + + mul_ov_t aov; memset(&aov, 0, sizeof(aov)); + get_asm_cov(ug, sl.hits.total_base, &aov); + fprintf(stderr, "[M::%s::] ==> total_pair: %lu, total_base: %lu, n: %d\n", + __func__, sl.hits.total_pair, sl.hits.total_base, (int32_t)sl.hits.n); + + + + get_ul_g(&aov, &sl.hits, ug, rg, 0.51, 0.1, 500, 1000); + + + + // print_gaf(ug, &(sl.hits), &(sl.nn)); + mg_gres_a_des(&(sl.hits)); free(sl.nn.a); free(sl.nn.cc.a); + return 1; +} + +void ul_resolve(ma_ug_t *ug, const asg_t *rg, const ug_opt_t *uopt, int hap_n) +{ + fprintf(stderr, "[M::%s::] ==> UL\n", __func__); + mg_idxopt_t opt; + init_mg_opt(&opt, 0, 19, 10, hap_n, 0, 0, 0.05, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); + int exist = (asm_opt.load_index_from_disk? uidx_load(&ha_flt_tab, &ha_idx, asm_opt.output_file_name, NULL) : 0); + if(exist == 0) uidx_build(ug, &opt); + if(exist == 0) uidx_write(ha_flt_tab, ha_idx, asm_opt.output_file_name, NULL); + ul_align(&opt, uopt, rg, asm_opt.ar, ha_flt_tab, ha_idx, ug); + uidx_destory(); +} + +void ul_v_call(uldat_t *sl, const enzyme *fn) +{ + scall_ul_pipeline(sl, fn); + // UL_INF; + // print_ul_rs(&UL_INF); + // debug_retrieve_rc_sub(uopt, &UL_INF, &R_INF, (ul_idx_t *)sl.uu, 100); + // if(!load_ul_hits(&sl.hits, &sl.nn, asm_opt.output_file_name)) { + // scall_ul_pipeline(&sl, fn); + // write_ul_hits(&sl.hits, &sl.nn, asm_opt.output_file_name); + // } +} + +void ul_v_recall(uldat_t *sl, const enzyme *fn) +{ + rescall_ul_pipeline(sl, fn); + // UL_INF; + // print_ul_rs(&UL_INF); + // debug_retrieve_rc_sub(uopt, &UL_INF, &R_INF, (ul_idx_t *)sl.uu, 100); + // if(!load_ul_hits(&sl.hits, &sl.nn, asm_opt.output_file_name)) { + // scall_ul_pipeline(&sl, fn); + // write_ul_hits(&sl.hits, &sl.nn, asm_opt.output_file_name); + // } +} + +void print_dedup_HiFis_seq(ma_ug_t *ug) +{ + uint64_t i; + ma_utg_t *p = NULL; + for (i = 0; i < ug->u.n; i++) { + p = &(ug->u.a[i]); + CALLOC(p->s, p->len+1); + retrieve_u_seq(NULL, p->s, p, 0, 0, -1, NULL); + p->s[p->len] = '\0'; + } + + FILE* output_file = fopen("dedup_HiFis_seq.gfa", "w"); + ma_ug_print(ug, NULL, NULL, NULL, NULL, "utg", output_file); + fclose(output_file); + + output_file = fopen("dedup_HiFis_seq.noseq.gfa", "w"); + ma_ug_print_simple(ug, NULL, NULL, NULL, NULL, "utg", output_file); + fclose(output_file); + exit(1); +} + +void push_coverage_track(ucov_t *cc, ul_contain *ct, uint64_t uid, ma_utg_t *u, asg_t *rg, ma_hit_t_alloc* src, int64_t min_ovlp, int64_t max_hang, uint64_t is_el, uint64_t is_del) +{ + uint64_t k, l, z, dp, ct_n; utg_ct_t *ct_a = NULL; + cc->idx[uid] = cc->interval.n; + ct_n = ((uint32_t)(ct->idx.a[uid])); ct_a = ct->rids.a + ((ct->idx.a[uid])>>32); + for (z = 0; z < ct_n; z++) { + kv_push(uint64_t, cc->interval, ct_a[z].s<<1); + kv_push(uint64_t, cc->interval, (ct_a[z].e<<1)|1); + } + for (k = l = 0; k < u->n; k++) { + kv_push(uint64_t, cc->interval, l<<1); + kv_push(uint64_t, cc->interval, ((l + Get_READ_LENGTH(R_INF, u->a[k]>>33))<<1)|1); + /** + i = u->a[k]>>33;///rid + for (z = 0; z < src[i].length; z++) { + if(is_el && (!src[i].buffer[z].el)) continue; + if(is_del && (!src[i].buffer[z].del)) continue; + qn = Get_qn(src[i].buffer[z]); tn = Get_tn(src[i].buffer[z]); + if(!rg->seq[tn].del) continue; + if((Get_qe(src[i].buffer[z]) - Get_qs(src[i].buffer[z])) < min_ovlp) continue; + if((Get_te(src[i].buffer[z]) - Get_ts(src[i].buffer[z])) < min_ovlp) continue; + r = ma_hit2arc(&(src[i].buffer[z]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + if(r != MA_HT_TCONT) continue;///tn is contained + ori = (u->a[k]>>32)&1; + if(ori == 0) { + qs = Get_qs(src[i].buffer[z]); qe = Get_qe(src[i].buffer[z]); + } else { + qs = (Get_READ_LENGTH(R_INF, i)) - Get_qe(src[i].buffer[z]); + qe = (Get_READ_LENGTH(R_INF, i)) - Get_qs(src[i].buffer[z]); + } + kv_push(uint64_t, cc->interval, (l+qs)<<1); + kv_push(uint64_t, cc->interval, ((l+qe)<<1)|1); + } + **/ + l += (uint32_t)u->a[k]; + } + cc->idx[uid+1] = cc->interval.n; + + + radix_sort_gfa64(cc->interval.a+cc->idx[uid], cc->interval.a+cc->interval.n); + for (k = cc->idx[uid], dp = 0; k < cc->interval.n; ++k) { + ///if a[j] is qe + if (cc->interval.a[k]&1) --dp; + else ++dp; + l = cc->interval.a[k]>>1; l <<= 32; l += dp; + cc->interval.a[k] = l; + } +} + + +uint32_t check_if_fully_contain(uint32_t sid, uint32_t lid, uint32_t ori, uint8_t *rset, asg_t *rg, +ma_hit_t_alloc* src, int64_t min_ovlp, int64_t max_hang, int64_t gap_fuzz) +{ + uint32_t rid, k, qn, tn, ff = 1; int32_t r; asg_arc_t t; + return 1; + + rid = lid; + for (k = 0; k < src[rid].length; k++) { + if(!src[rid].buffer[k].el) continue; + qn = Get_qn(src[rid].buffer[k]); tn = Get_tn(src[rid].buffer[k]); + if(rg->seq[qn].del || rg->seq[tn].del) continue; + if((Get_qe(src[rid].buffer[k]) - Get_qs(src[rid].buffer[k])) < min_ovlp) continue; + if((Get_te(src[rid].buffer[k]) - Get_ts(src[rid].buffer[k])) < min_ovlp) continue; + r = ma_hit2arc(&(src[rid].buffer[k]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + if(r < 0) continue; + rset[t.v] = ((t.ul>>32)&1)+1; + } + + + + rid = sid; + for (k = 0; k < src[rid].length; k++) { + if(!src[rid].buffer[k].el) continue; + qn = Get_qn(src[rid].buffer[k]); tn = Get_tn(src[rid].buffer[k]); + if(rg->seq[qn].del || rg->seq[tn].del) continue; + if((Get_qe(src[rid].buffer[k]) - Get_qs(src[rid].buffer[k])) < min_ovlp) continue; + if((Get_te(src[rid].buffer[k]) - Get_ts(src[rid].buffer[k])) < min_ovlp) continue; + r = ma_hit2arc(&(src[rid].buffer[k]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + if(r < 0) continue; + if(rset[t.v] != ((((t.ul>>32)&1)^ori)+1)) { + ff = 0; + break; + } + } + + + rid = lid; + for (k = 0; k < src[rid].length; k++) { + if(!src[rid].buffer[k].el) continue; + qn = Get_qn(src[rid].buffer[k]); tn = Get_tn(src[rid].buffer[k]); + if(rg->seq[qn].del || rg->seq[tn].del) continue; + if((Get_qe(src[rid].buffer[k]) - Get_qs(src[rid].buffer[k])) < min_ovlp) continue; + if((Get_te(src[rid].buffer[k]) - Get_ts(src[rid].buffer[k])) < min_ovlp) continue; + r = ma_hit2arc(&(src[rid].buffer[k]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + if(r < 0) continue; + rset[t.v] = 0; + } + + return ff; +} + +ul_contain *ul_contain_gen(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc* src, int64_t min_ovlp, int64_t max_hang, uint64_t is_el, uint64_t is_del) +{ + uint64_t k, l, i, z, t, qn, tn, ori, qs, qe, ovlp, o_z, o_r, o_o; + ul_contain *p = NULL; ma_utg_t *u = NULL; + utg_ct_t *m = NULL; + int32_t r; asg_arc_t e; + CALLOC(p, 1); + p->idx.n = p->idx.m = ug->u.n; CALLOC(p->idx.a, p->idx.n); + p->is_c.n = rg->n_seq; CALLOC(p->is_c.a, p->is_c.n); + for (t = 0; t < ug->u.n; t++) { + u = &(ug->u.a[t]); + p->idx.a[t] = p->rids.n; p->idx.a[t] <<= 32; + + for (k = l = 0; k < u->n; k++) { + i = u->a[k]>>33;///rid + + for (z = 0; z < src[i].length; z++) { + if(is_el && (!src[i].buffer[z].el)) continue; + if(is_del && (!src[i].buffer[z].del)) continue; + qn = Get_qn(src[i].buffer[z]); tn = Get_tn(src[i].buffer[z]); + if(!rg->seq[tn].del) continue; + if((Get_qe(src[i].buffer[z]) - Get_qs(src[i].buffer[z])) < min_ovlp) continue; + if((Get_te(src[i].buffer[z]) - Get_ts(src[i].buffer[z])) < min_ovlp) continue; + r = ma_hit2arc(&(src[i].buffer[z]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &e); + if(r != MA_HT_TCONT) continue;///tn is contained + p->is_c.a[qn] = 1; + ori = (u->a[k]>>32)&1; + if(ori == 0) { + qs = Get_qs(src[i].buffer[z]); qe = Get_qe(src[i].buffer[z]); + } else { + qs = (Get_READ_LENGTH(R_INF, i)) - Get_qe(src[i].buffer[z]); + qe = (Get_READ_LENGTH(R_INF, i)) - Get_qs(src[i].buffer[z]); + } + qs += l; qe += l; + kv_pushp(utg_ct_t, p->rids, &m); + m->x = tn; m->x <<= 1; m->x |= (src[i].buffer[z].rev == ori?0:1); + m->s = qs; m->e = qe/** + 1**/; + } + + l += (uint32_t)u->a[k]; + } + + radix_sort_utg_ct_t_x_srt(p->rids.a + (p->idx.a[t]>>32), p->rids.a + p->rids.n); + /** + for (k = (p->idx.a[t]>>32) + 1, l = i = (p->idx.a[t]>>32); k <= p->rids.n; ++k) { + if (k == p->rids.n || (p->rids.a[k].x>>1) != (p->rids.a[l].x>>1)) { + p->rids.a[i] = p->rids.a[l]; i++; + l = k; + } + } + **/ + for (k = (p->idx.a[t]>>32) + 1, l = i = (p->idx.a[t]>>32); k <= p->rids.n; ++k) { + if (k == p->rids.n || p->rids.a[k].x != p->rids.a[l].x) { + for (z = l; z < k; z++) { + for (r = (int64_t)i-1; r >= 0 && p->rids.a[r].x == p->rids.a[z].x; r--) { + ovlp = ((MIN(p->rids.a[z].e, p->rids.a[r].e) > MAX(p->rids.a[z].s, p->rids.a[r].s))? + (MIN(p->rids.a[z].e, p->rids.a[r].e) - MAX(p->rids.a[z].s, p->rids.a[r].s)):0); + if(ovlp) { + o_z = p->rids.a[z].e - p->rids.a[z].s; + o_r = p->rids.a[r].e - p->rids.a[r].s; + o_o = MIN(o_z, o_r); + if((ovlp <= o_o*1.05) && (ovlp >= o_o*0.95)) break; + } + // if(p->rids.a[z].s == p->rids.a[r].s && p->rids.a[z].e == p->rids.a[r].e) break; + } + if(r >= 0 && p->rids.a[r].x == p->rids.a[z].x) continue; + p->rids.a[i++] = p->rids.a[z]; + } + l = k; + } + } + p->rids.n = i; + + radix_sort_utg_ct_t_s_srt(p->rids.a + (p->idx.a[t]>>32), p->rids.a + p->rids.n); + p->idx.a[t] |= (p->rids.n - (p->idx.a[t]>>32)); + } + + // fprintf(stderr, "p->rids.n:%u, p->idx.n:%u\n", (uint32_t)p->rids.n, (uint32_t)p->idx.n); + + return p; +} + +void gen_hpc_seq(const char *in, uint32_t in_len, ma_utg_t *ou, hmap_t *mm, uint32_t hpc_id) +{ + uint32_t k, l, m; int64_t n; memset(ou, 0, sizeof((*ou))); + for (l = 0, k = 1; k <= in_len; k++) { + if((k == in_len) || (in[k] != in[l]) || (seq_nt4_table[(uint8_t)in[l]] >= 4)) { + ou->len++; l = k; + } + } + kv_resize(uint8_t, *mm, mm->n+ou->len); + mm->idx[hpc_id] = ((uint64_t)mm->n)<<32; + + ou->len <<= 1; + MALLOC(ou->s, ou->len); m = 0; + for (l = 0, k = 1; k <= in_len; k++) { + if((k == in_len) || (in[k] != in[l]) || (seq_nt4_table[(uint8_t)in[l]] >= 4)) { + ou->s[m++] = in[l]; + n = k-l; + while(n >= 0) {///even if n == 0, need to keep it + if(n < 255) { + kv_push(uint8_t, *mm, n); break; + } else { + kv_push(uint8_t, *mm, 255); n -= 255; + } + } + l = k; + } + } + l = m; mm->idx[hpc_id] += (mm->n - (mm->idx[hpc_id]>>32)); + for (k = 0; k < l; k++) ou->s[m++] = RC_CHAR(ou->s[l-k-1]); + + + +} + +void gen_microsatellite(const char *in, uint32_t in_len, ma_utg_t *idx, hpc_t *res, uint32_t mcs_len) +{ + uint32_t k, i, l, c, o; char sk[256]; + idx->start = idx->end = res->n; + if(mcs_len > 256) mcs_len = 256; + for (k = 1; k <= mcs_len; k++) { + memset(sk, 'N', k); ///k->length of k-mer + o = k + (k>>1) + 1; + for (i = l = 0; i < in_len; i++) { + c = seq_nt4_table[(uint8_t)in[i]]; + if((c < 4) && (((l >= k) && (sk[l%k] == in[i])) || (l < k))) { + if(l < k) sk[l] = in[i]; + l++; + } else { + if(l >= o) { + kv_push(uint64_t, *res, (((uint64_t)(i-l))<<1)); + kv_push(uint64_t, *res, ((((uint64_t)i)<<1)|1)); + } + l = 0; + } + } + } + + radix_sort_gfa64(res->a+idx->start, res->a+res->n); + int64_t dp, old_dp; uint64_t st, en; + for (k = st = idx->start, dp = 0; k < res->n; k++) { + old_dp = dp; + if (res->a[k]&1) --dp;//qe + else ++dp; + if (old_dp < 1 && dp >= 1) {///qs + st = res->a[k]>>1; + } else if (old_dp >= 1 && dp < 1) {///qe + en = res->a[k]>>1; + res->a[idx->end++] = ((st<<32)|(en)); + } + } + res->n = idx->end; +} + +uint32_t hpc_l(char *s, int64_t hof, int64_t sof, int64_t scut) +{ + if(scut == sof) return hof; + if(scut < sof) sof = hof = 0; + int64_t l, k; + for (k=sof; (k>0)&&(k= 4)) { + hof++; l = k; + } + } + return hof; +} + +hpc_t *hpc_g_gen(ma_ug_t *ug) +{ + uint32_t k, i, ho, so, len; int32_t z; hpc_t *p; kvec_t(char) cc; asg_t *ng = asg_init(); + CALLOC(p, 1); CALLOC(p->hg, 1); kv_init(cc); CALLOC(p->mm, 1); + CALLOC(p->hg->u.a, ug->u.n); p->hg->u.n = p->hg->u.m = ug->u.n; + CALLOC(p->mm->idx, ug->u.n); + + for (k = 0; k < ug->u.n; k++) { + kv_resize(char, cc, ug->u.a[k].len); + retrieve_u_seq(NULL, cc.a, &(ug->u.a[k]), 0, 0, ug->u.a[k].len, NULL); + gen_hpc_seq(cc.a, ug->u.a[k].len, &(p->hg->u.a[k]), p->mm, k); + gen_microsatellite(cc.a, ug->u.a[k].len, &(p->hg->u.a[k]), p, 6); + } + + ng->m_arc = ng->n_arc = ug->g->n_arc; CALLOC(ng->arc, ng->n_arc); + ng->m_seq = ng->n_seq = ug->g->n_seq; CALLOC(ng->seq, ng->n_seq); + for (k = 0; k < ng->n_seq; k++) { + ng->seq[k].del = ng->seq[k].c = 0; ng->seq[k].len = p->hg->u.a[k].len>>1;///hpc len + } + memcpy(ng->arc, ug->g->arc, ng->n_arc*(sizeof((*(ng->arc))))); + for (k = 1, i = 0; k <= ng->n_arc; k++) { + if(k == ng->n_arc || (ng->arc[i].ul>>32) != (ng->arc[k].ul>>32)) { + //sorted by ol + len = ng->arc[i].ol; kv_resize(char, cc, len); + retrieve_u_seq(NULL, cc.a, &(ug->u.a[ng->arc[i].ul>>33]), ((ng->arc[i].ul>>32)&1)^1, 0, len, NULL); + // min_o = ng->arc[k-1].ol; max_o = ng->arc[i].ol; + len = ng->seq[ng->arc[i].ul>>33].len;///hpc len + for (z = k-1, ho = so = 0; z >= (int32_t)i; z--) { + ho = hpc_l(cc.a, ho, so, ng->arc[z].ol); + so = ng->arc[z].ol; + ng->arc[z].ol = ho; + ng->arc[z].ul>>=32; + ng->arc[z].ul<<=32; + ng->arc[z].ul += len - ng->arc[z].ol; + assert(z == (int32_t)k-1 || ng->arc[z].ol>=ng->arc[z+1].ol); + } + i = k; + } + } + asg_cleanup(ng); + p->hg->g = ng; + kv_destroy(cc); + return p; +} + +void debug_append_inexact_edges(ma_ug_t *ug, const ug_opt_t *uopt) { + uint32_t n_asymm = 0, n_disconnect = 0, z, v, w, k, nv; asg_arc_t *av = NULL; + for (z = 0; z < ug->g->n_arc; ++z) { + if(ug->g->arc[z].del) continue; + if(!get_ug_edge_src(ug, uopt->sources, uopt->max_hang, uopt->min_ovlp, + ug->g->arc[z].ul>>32, ug->g->arc[z].v)) { + n_disconnect++; + } + v = ug->g->arc[z].v^1; w = (ug->g->arc[z].ul>>32)^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; + // fprintf(stderr, "found <%lu> -> <%u>\n", av[k].ul>>32, av[k].v); + if (av[k].v == w) break; + } + + if (k == nv) { + ug->g->arc[z].del = 1, ++n_asymm; + // fprintf(stderr, "# lack of <%u> -> <%u>, should be <%u> -> <%u>\n\n", w^1, v^1, v, w); + } + } + + if(n_asymm || n_disconnect) { + asg_cleanup(ug->g); + fprintf(stderr, "[M::%s] # asymm edges: %u, # disconnect edges: %u\n", + __func__, n_asymm, n_disconnect); + // exit(1); + } +} + +void append_inexact_edges(ma_ug_t *ug, const ug_opt_t *uopt, asg_t *rg) +{ + uint32_t *idx = NULL, n_read = R_INF.total_reads, z, v, k, qn, tn, tu, ut_v, ut_w; + ma_utg_t *u = NULL; ma_hit_t_alloc *src = uopt->sources, *s = NULL; + int32_t r; asg_arc_t t, *p = NULL; + int64_t min_ovlp = uopt->min_ovlp, max_hang = uopt->max_hang, occ = 0; + + MALLOC(idx, n_read); memset(idx, -1, n_read*sizeof(*(idx))); + for (z = 0; z < ug->u.n; z++) { + u = &(ug->u.a[z]); + if(u->circ) continue; + idx[u->start>>1] = idx[u->end>>1] = z; + } + + for (z = 0; z < ug->u.n; z++) { + u = &(ug->u.a[z]); + if(u->circ) continue; + + v = u->end^1; s = &(src[v>>1]); ut_v = (z<<1); + for (k = 0; k < s->length; k++) { + if(s->buffer[k].el) continue;///we just need inexact edges + qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); tu = idx[tn]; ut_w = (uint32_t)-1; + if(tu == (uint32_t)-1 || ug->g->seq[tu].del) continue; + if((Get_qe(s->buffer[k]) - Get_qs(s->buffer[k])) < min_ovlp) continue; + if((Get_te(s->buffer[k]) - Get_ts(s->buffer[k])) < min_ovlp) continue; + r = ma_hit2arc(&(s->buffer[k]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + if(r < 0 || (t.ul>>32) != v) continue; + if(t.v == ug->u.a[tu].start) ut_w = tu<<1; + if(t.v == ug->u.a[tu].end) ut_w = (tu<<1)+1; + if(ut_w==(uint32_t)-1) continue; + p = asg_arc_pushp(ug->g); memset(p, 0, sizeof(*p)); + *p = t; p->ul = ut_v; p->ul <<= 32; p->ul += ((uint32_t)(t.ul)); p->v = ut_w; + occ++; + // if((p->v>>1)>=ug->g->n_seq || (p->ul>>33)>=ug->g->n_seq) { + // fprintf(stderr, "+ug->g->n_seq:%u, (p->ul>>33):%u, (p->v>>1):%u\n", + // (uint32_t)ug->g->n_seq, (uint32_t)(p->ul>>33), (uint32_t)(p->v>>1)); + // } + // assert((p->v>>1)g->n_seq && (p->ul>>33)g->n_seq); + } + + v = u->start^1; s = &(src[v>>1]); ut_v = (z<<1) + 1; + for (k = 0; k < s->length; k++) { + if(s->buffer[k].el) continue;///we just need inexact edges + qn = Get_qn(s->buffer[k]); tn = Get_tn(s->buffer[k]); tu = idx[tn]; ut_w = (uint32_t)-1; + if(tu == (uint32_t)-1 || ug->g->seq[tu].del) continue; + if((Get_qe(s->buffer[k]) - Get_qs(s->buffer[k])) < min_ovlp) continue; + if((Get_te(s->buffer[k]) - Get_ts(s->buffer[k])) < min_ovlp) continue; + r = ma_hit2arc(&(s->buffer[k]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + if(r < 0 || (t.ul>>32) != v) continue; + if(t.v == ug->u.a[tu].start) ut_w = tu<<1; + if(t.v == ug->u.a[tu].end) ut_w = (tu<<1)+1; + if(ut_w==(uint32_t)-1) continue; + p = asg_arc_pushp(ug->g); memset(p, 0, sizeof(*p)); + *p = t; p->ul = ut_v; p->ul <<= 32; p->ul += ((uint32_t)(t.ul)); p->v = ut_w; + occ++; + // if((p->v>>1)>=ug->g->n_seq || (p->ul>>33)>=ug->g->n_seq) { + // fprintf(stderr, "+ug->g->n_seq:%u, (p->ul>>33):%u, (p->v>>1):%u\n", + // (uint32_t)ug->g->n_seq, (uint32_t)(p->ul>>33), (uint32_t)(p->v>>1)); + // } + // assert((p->v>>1)g->n_seq && (p->ul>>33)g->n_seq); + } + } + if(occ) { + free(ug->g->idx); + ug->g->idx = 0; + ug->g->is_srt = 0; + asg_cleanup(ug->g); + } + + free(idx); + ///for debug + debug_append_inexact_edges(ug, uopt); + fprintf(stderr, "[M::%s] # inserted inexact edges: %ld\n", __func__, occ); +} + +typedef struct { + ucov_t *cr; + ma_hit_t_alloc* src; + int64_t min_ovlp; + int64_t max_hang; + uint64_t is_el; + uint64_t is_del; + uint64_t is_src_cc; + asg_t *rg; + ma_ug_t *ug; +} r_contain_aux; + +static void update_gen_r_contain(void *data, long i, int tid) // callback for kt_for() +{ + r_contain_aux *s = (r_contain_aux *)data; + ma_hit_t_alloc *src = s->src; ma_hit_t *t; int32_t r; asg_arc_t x; + uint64_t *a = s->cr->interval.a + s->cr->idx[i], a_n = s->cr->idx[i+1] - s->cr->idx[i], k, dp, l, z, qn, tn; + uint64_t is_el = s->is_el, is_del = s->is_del, min_ovlp = s->min_ovlp, max_hang = s->max_hang, qs, qe, cs, ce, sum; + int64_t ii; asg_t *rg = s->rg; uint64_t *b, b_n, ti; + // if(a_n == 0 || rg->seq[i].del) return; + if(s->is_src_cc) { + for (z = 0; z < src[i].length; z++) { + t = &(src[i].buffer[z]); t->cc = 0; + if(a_n == 0 || rg->seq[i].del) continue; + qn = Get_qn((*t)); tn = Get_tn((*t)); + if(qn > tn) continue; + if(is_el && (!(t->el))) continue; + if(is_del && (!(t->del))) continue; + if((Get_qe((*t)) - Get_qs((*t))) < min_ovlp) continue; + if((Get_te((*t)) - Get_ts((*t))) < min_ovlp) continue; + if(rg->seq[tn].del) continue; + b = s->cr->interval.a + s->cr->idx[tn]; b_n = s->cr->idx[tn+1] - s->cr->idx[tn]; + if(b_n == 0) continue; + r = ma_hit2arc(t, Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &x); + if(r < 0) continue; + qs = Get_qs((*t)); qe = Get_qe((*t)); + for (k = 0; k < a_n; k += 2) { + cs = a[k]>>33; ce = a[k+1]>>33; assert(rg->seq[(uint32_t)(a[k])].del); + if(qs<=cs+128 && qe+128>=ce) { ///128 is the offset for indel + for (ti = 0; ti < b_n; ti+=2) { + if((uint32_t)(b[ti]) == (uint32_t)(a[k])) { + sum = t->cc; sum += (ce - cs); + if(sum > 0x3fffffffU) sum = 0x3fffffffU; + t->cc = sum; + break; + } + } + } + } + } + } else { + radix_sort_gfa64(a, a + a_n); + for (k = 0, dp = 0; k < a_n; ++k) { + ///if a[j] is qe + if ((a[k]>>32)&1) --dp; + else ++dp; + l = a[k]>>33; l <<= 32; l += dp; + a[k] = l; + } + for (z = 0; z < src[i].length; z++) { + t = &(src[i].buffer[z]); + qn = Get_qn((*t)); tn = Get_tn((*t)); + if(qn > tn) continue; + if(t->cc == 0) continue; + ii = get_specific_overlap(&(src[tn]), tn, qn); + src[tn].buffer[ii].cc = t->cc; + } + } +} + +static void update_ug_uo_t(void *data, long i, int tid) +{ + r_contain_aux *sl = (r_contain_aux *)data; int32_t r; + ma_hit_t_alloc *src = sl->src, *x; uint32_t k, qn, tn, uv, uw, v, w; + asg_arc_t *e = &(sl->ug->g->arc[i]), t; + uv = e->ul>>32; uw = e->v; e->ou = 0; + if(sl->ug->u.a[uv>>1].circ || sl->ug->u.a[uw>>1].circ) return; + v = ((uv&1)?(sl->ug->u.a[uv>>1].start^1):(sl->ug->u.a[uv>>1].end^1)); + w = ((uw&1)?(sl->ug->u.a[uw>>1].end):(sl->ug->u.a[uw>>1].start)); + x = &(src[v>>1]); + + for (k = 0; k < x->length; k++) { + qn = Get_qn(x->buffer[k]); + tn = Get_tn(x->buffer[k]); + if(qn == (v>>1) && tn == (w>>1)) { + r = ma_hit2arc(&(x->buffer[k]), sl->rg->seq[v>>1].len, sl->rg->seq[w>>1].len, + sl->max_hang, asm_opt.max_hang_rate, sl->min_ovlp, &t); + if(r < 0) continue; + if((t.ul>>32)!=v || t.v!=w) continue; + e->ou = (x->buffer[k].cc>OU_MASK?OU_MASK:x->buffer[k].cc); + break; + } + } + assert(k < x->length); +} + +ucov_t *gen_r_contain(ma_ug_t *ug, asg_t *rg, ma_hit_t_alloc* src, uint64_t n_read, int64_t min_ovlp, int64_t max_hang, uint64_t n_thread, uint64_t is_el, uint64_t is_del) +{ + ucov_t *cr = NULL; uint64_t i, z, qn, tn, qs, qe; + ma_hit_t *t = NULL; int32_t r; asg_arc_t x; + CALLOC(cr, 1); MALLOC(cr->idx, n_read+1); kv_init(cr->interval); + for (i = 0; i < n_read; i++) { + cr->idx[i] = cr->interval.n; + if(rg->seq[i].del) continue; + for (z = 0; z < src[i].length; z++) { + t = &(src[i].buffer[z]); t->cc = 0; + if(is_el && (!(t->el))) continue; + if(is_del && (!(t->del))) continue; + if((Get_qe((*t)) - Get_qs((*t))) < min_ovlp) continue; + if((Get_te((*t)) - Get_ts((*t))) < min_ovlp) continue; + qn = Get_qn((*t)); tn = Get_tn((*t)); + if(!rg->seq[tn].del) continue; + r = ma_hit2arc(t, Get_READ_LENGTH(R_INF, qn), Get_READ_LENGTH(R_INF, tn), max_hang, asm_opt.max_hang_rate, min_ovlp, &x); + if(r == MA_HT_TCONT) { ///tn is contained + qs = Get_qs((*t)); qe = Get_qe((*t)); + kv_push(uint64_t, cr->interval, ((qs<<1)<<32)|tn); + kv_push(uint64_t, cr->interval, (((qe<<1)|1)<<32)|tn); + } + } + } + cr->idx[i] = cr->interval.n; + // fprintf(stderr, "+++[M::%s]n_read:%lu\n", __func__, n_read); + r_contain_aux aux; + aux.cr = cr; aux.src = src; aux.min_ovlp = min_ovlp; aux.rg = rg; aux.ug = ug; + aux.max_hang = max_hang; aux.is_el = 0/**is_el**/; aux.is_del = 0/**is_del**/; + aux.is_src_cc = 1; + kt_for(n_thread, update_gen_r_contain, &aux, n_read);///note: here we should set is_el = is_del = 0 + + aux.is_src_cc = 0; + kt_for(n_thread, update_gen_r_contain, &aux, n_read); + + if(ug) kt_for(n_thread, update_ug_uo_t, &aux, ug->g->n_arc); + + return cr; +} + +ucov_t *gen_cov_track(ma_ug_t *ug, asg_t *rg, ul_contain *ct, ma_hit_t_alloc* src, int64_t min_ovlp, int64_t max_hang, uint64_t is_el, uint64_t is_del) +{ + uint64_t i, k; + ucov_t *cc = NULL; CALLOC(cc, 1); MALLOC(cc->idx, ug->u.n+1); kv_init(cc->interval); + for (i = k = 0; i < ug->u.n; i++) { + k += ug->u.a[i].len; + push_coverage_track(cc, ct, i, &(ug->u.a[i]), rg, src, min_ovlp, max_hang, is_el, is_del); + } + fprintf(stderr, "[M::%s::] # bases: %lu\n", __func__, k); + return cc; +} + +ul_idx_t *dedup_HiFis(const ug_opt_t *uopt, uint64_t is_el, uint64_t is_del) +{ + uint64_t i, k, qn, tn, n_read = R_INF.total_reads, cc_num = 0; + int32_t r; asg_arc_t t, *p = NULL; + uint8_t *rset = NULL; CALLOC(rset, n_read<<1); + asg_t *rg = asg_init(); + ma_hit_t_alloc* src = uopt->sources; + int64_t min_ovlp = uopt->min_ovlp; + int64_t max_hang = uopt->max_hang; + int64_t gap_fuzz = uopt->gap_fuzz; + + rg->m_seq = rg->n_seq = n_read; MALLOC(rg->seq, rg->m_seq); + for (i = 0; i < n_read; ++i) { + rg->seq[i].len = Get_READ_LENGTH(R_INF, i); + rg->seq[i].del = rg->seq[i].c = 0; + } + + for (i = 0; i < n_read; i++) { + if(rg->seq[i].del) continue; + for (k = 0; k < src[i].length; k++) { + if(is_el && (!src[i].buffer[k].el)) continue; + if(is_del && (!src[i].buffer[k].del)) continue; + qn = Get_qn(src[i].buffer[k]); tn = Get_tn(src[i].buffer[k]); + if(rg->seq[qn].del || rg->seq[tn].del) continue; + if((Get_qe(src[i].buffer[k]) - Get_qs(src[i].buffer[k])) < min_ovlp) continue; + if((Get_te(src[i].buffer[k]) - Get_ts(src[i].buffer[k])) < min_ovlp) continue; + r = ma_hit2arc(&(src[i].buffer[k]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + if (r == MA_HT_QCONT/** && check_if_fully_contain(qn, tn, src[i].buffer[k].rev, rset, rg, src, min_ovlp, max_hang, gap_fuzz)**/) { + rg->seq[qn].del = 1; + } else if(r == MA_HT_TCONT/** && check_if_fully_contain(tn, qn, src[i].buffer[k].rev, rset, rg, src, min_ovlp, max_hang, gap_fuzz)**/) { + rg->seq[tn].del = 1; + } + if(rg->seq[i].del) break; + } + } + + + for (i = 0; i < n_read; i++) { + if(rg->seq[i].del) {cc_num++; continue;} + for (k = 0; k < src[i].length; k++) { + if(is_el && (!src[i].buffer[k].el)) continue; + if(is_del && (!src[i].buffer[k].del)) continue; + qn = Get_qn(src[i].buffer[k]); tn = Get_tn(src[i].buffer[k]); + if(rg->seq[qn].del || rg->seq[tn].del) continue; + if((Get_qe(src[i].buffer[k]) - Get_qs(src[i].buffer[k])) < min_ovlp) continue; + if((Get_te(src[i].buffer[k]) - Get_ts(src[i].buffer[k])) < min_ovlp) continue; + r = ma_hit2arc(&(src[i].buffer[k]), rg->seq[qn].len, rg->seq[tn].len, max_hang, asm_opt.max_hang_rate, min_ovlp, &t); + if (r >= 0) { + p = asg_arc_pushp(rg); + *p = t; + } + } + } + + asg_cleanup(rg); asg_symm(rg); + asg_arc_del_trans(rg, gap_fuzz); + ma_ug_t *ug = NULL; + ug = ma_ug_gen(rg); + append_inexact_edges(ug, uopt, rg); + + ul_idx_t *uu = NULL; CALLOC(uu, 1); + uu->ug = ug; + + uu->ct = ul_contain_gen(ug, rg, src, min_ovlp, max_hang, is_el, is_del); + uu->cc = gen_cov_track(ug, rg, uu->ct, src, min_ovlp, max_hang, is_el, is_del); + uu->cr = gen_r_contain(ug, rg, src, n_read, min_ovlp, max_hang, asm_opt.thread_num, is_el, is_del); + + // uu->ov = compress_dedup_HiFis(ug, src); + asg_destroy(rg); free(rset); + // uu->nug = cvert_t_gen(uopt); + + fprintf(stderr, "[M::%s::] # unitigs: %lu, # edges: %lu, # cc_num: %lu\n", __func__, (uint64_t)ug->u.n, (uint64_t)ug->g->n_arc, cc_num); + // print_dedup_HiFis_seq(ug); + return uu; +} + +ul_idx_t *gen_ul_idx(const ug_opt_t *uopt, ma_ug_t *ug, asg_t *sg) +{ + ma_hit_t_alloc* src = uopt->sources; + int64_t min_ovlp = uopt->min_ovlp; + int64_t max_hang = uopt->max_hang; + + ul_idx_t *uu = NULL; CALLOC(uu, 1); uu->ug = ug; + uu->ct = ul_contain_gen(ug, sg, src, min_ovlp, max_hang, 0, 1); + uu->cc = gen_cov_track(ug, sg, uu->ct, src, min_ovlp, max_hang, 0, 1); + uu->cr = gen_r_contain(ug, sg, src, R_INF.total_reads, min_ovlp, max_hang, asm_opt.thread_num, 0, 1); + // uu->hpc_g = hpc_g_gen(ug); + + return uu; +} + + + +utg_rid_t *gen_r_ug_idx(ma_ug_t *ug, ul_contain *ct, asg_t *rg, uint32_t keep_offset) +{ + uint64_t i, k, l, m, rid, a_n, cn, rn = R_INF.total_reads; ///R_INF.total_reads might be larger than rg->n_seq due scaffold reads + utg_rid_dt *a; ma_utg_t *u = NULL; utg_ct_t *ca; + + utg_rid_t *cc = NULL; CALLOC(cc, 1); CALLOC(cc->idx, rn+1); kv_init(cc->p); cc->rg = rg; + for (i = 0; i < ug->u.n; i++) { + u = &(ug->u.a[i]); + for (k = 0; k < u->n; k++) cc->idx[u->a[k]>>33]++; + + if(ct) { + cn = ((uint32_t)(ct->idx.a[i])); + ca = ct->rids.a + ((ct->idx.a[i])>>32); + for (k = 0; k < cn; k++) cc->idx[ca[k].x>>1]++; + } + } + + for (k = l = 0; k <= rn; k++) { + m = cc->idx[k]; + cc->idx[k] = l; + l += m; + } + cc->p.n = cc->p.m = l; CALLOC(cc->p.a, cc->p.n); + for (i = 0; i < ug->u.n; i++) { + u = &(ug->u.a[i]); + for (k = l = 0; k < u->n; k++) { + rid = u->a[k]>>33; + a = cc->p.a + cc->idx[rid]; + a_n = cc->idx[rid+1] - cc->idx[rid]; + if(a_n) { + if(a[a_n-1].off == a_n-1) { + a[a_n-1].u = (i<<1)|((u->a[k]>>32)&1); + a[a_n-1].pos = l; a[a_n-1].off = (keep_offset?k:l); + } else { + a[a[a_n-1].off].u = (i<<1)|((u->a[k]>>32)&1); + a[a[a_n-1].off].pos = l; a[a[a_n-1].off].off = (keep_offset?k:l); + a[a_n-1].off++; + } + } + l += (uint32_t)u->a[k]; + } + + if(ct) { + cn = ((uint32_t)(ct->idx.a[i])); + ca = ct->rids.a + ((ct->idx.a[i])>>32); + for (k = 0; k < cn; k++) { + rid = ca[k].x>>1; + a = cc->p.a + cc->idx[rid]; + a_n = cc->idx[rid+1] - cc->idx[rid]; + if(a_n) { + if(a[a_n-1].off == a_n-1) { + a[a_n-1].u = (i<<1)|(ca[k].x&1); + a[a_n-1].pos = ca[k].s; a[a_n-1].off = (keep_offset?k:ca[k].s); + } else { + a[a[a_n-1].off].u = (i<<1)|(ca[k].x&1); + a[a[a_n-1].off].pos = ca[k].s; a[a[a_n-1].off].off = (keep_offset?k:ca[k].s); + a[a_n-1].off++; + } + } + } + } + } + return cc; +} + +utg_rid_t *gen_r_ug_sc_idx(scaf_res_t *ug_sc, uint64_t ug_sc_num) +{ + uint64_t i, z, k, l, m, rid, a_n, s, e, rn = ug_sc_num; ///ug_sc_num is the number of nodes within the inital graph + utg_rid_dt *a; ul_vec_t *idx; + + utg_rid_t *cc = NULL; CALLOC(cc, 1); CALLOC(cc->idx, rn+1); kv_init(cc->p); ///cc->rg = rg; + for (i = 0; i < ug_sc->n; i++) { + idx = &(ug_sc->a[i]); + for (z = 0; z < idx->bb.n; z++) { + s = idx->bb.a[z].ts; e = idx->bb.a[z].te; + for (k = s; k < e; k++) cc->idx[idx->bb.a[k].hid]++; + } + } + + for (k = l = 0; k <= rn; k++) { + m = cc->idx[k]; + cc->idx[k] = l; + l += m; + } + cc->p.n = cc->p.m = l; CALLOC(cc->p.a, cc->p.n); + for (i = 0; i < ug_sc->n; i++) { + idx = &(ug_sc->a[i]); + for (z = 0; z < idx->bb.n; z++) { + s = idx->bb.a[z].ts; e = idx->bb.a[z].te; + for (k = s; k < e; k++) { + rid = idx->bb.a[k].hid; + a = cc->p.a + cc->idx[rid]; + a_n = cc->idx[rid+1] - cc->idx[rid]; + if(a_n) { + if(a[a_n-1].off == a_n-1) { + a[a_n-1].u = (i<<1)|(idx->bb.a[k].rev); + a[a_n-1].pos = idx->bb.a[k].qs; a[a_n-1].off = k; + } else { + a[a[a_n-1].off].u = (i<<1)|(idx->bb.a[k].rev); + a[a[a_n-1].off].pos = idx->bb.a[k].qs; a[a[a_n-1].off].off = k; + a[a_n-1].off++; + } + } + } + } + } + return cc; +} + +ul_idx_t *gen_ul_idx_t(const ug_opt_t *uopt, ma_ug_t *ug, asg_t *sg, uint64_t is_el, uint64_t is_del, uint64_t is_scaf) +{ + uint64_t n_read = R_INF.total_reads; + ma_hit_t_alloc* src = uopt->sources; + int64_t min_ovlp = uopt->min_ovlp; + int64_t max_hang = uopt->max_hang; + // int64_t gap_fuzz = uopt->gap_fuzz; + ul_idx_t *uu = NULL; CALLOC(uu, 1); uu->ug = (ug?(ug):(ma_ug_gen(sg))); + if(!is_scaf) { + uu->ct = ul_contain_gen(uu->ug, sg, src, min_ovlp, max_hang, is_el, is_del); + uu->cc = gen_cov_track(uu->ug, sg, uu->ct, src, min_ovlp, max_hang, is_el, is_del); + uu->cr = gen_r_contain(uu->ug, sg, src, n_read, min_ovlp, max_hang, asm_opt.thread_num, is_el, is_del); + } + uu->r_ug = gen_r_ug_idx(uu->ug, (!is_scaf)?(uu->ct):(NULL), sg, is_scaf); + return uu; +} + +ul_idx_t *gen_ul_idx_t_sc(ma_ug_t *ug, asg_t *sg, scaf_res_t *ug_sc, uint64_t ug_sc_num) +{ + // int64_t gap_fuzz = uopt->gap_fuzz; + ul_idx_t *uu = NULL; CALLOC(uu, 1); uu->ug = (ug?(ug):(ma_ug_gen(sg))); + uu->r_ug = gen_r_ug_sc_idx(ug_sc, ug_sc_num); + return uu; +} + + +void destroy_ul_idx_t(ul_idx_t *uu) +{ + if(!uu) return; + if(uu->cc) { + free(uu->cc->idx); + free(uu->cc->interval.a); + free(uu->cc); + } + + if(uu->cr) { + free(uu->cr->idx); + free(uu->cr->interval.a); + free(uu->cr); + } + + if(uu->ct) { + free(uu->ct->idx.a); + free(uu->ct->rids.a); + free(uu->ct->is_c.a); + free(uu->ct); + } + + if(uu->r_ug) { + free(uu->r_ug->idx); + free(uu->r_ug->p.a); + free(uu->r_ug); + } + + if(uu->hpc_g) { + free(uu->hpc_g->a); + ma_ug_destroy(uu->hpc_g->hg); + free(uu->hpc_g->mm->a); + free(uu->hpc_g->mm->idx); + free(uu->hpc_g->mm); + free(uu->hpc_g); + } + // if(uu->ov) { + // free(uu->ov->a); + // free(uu->ov); + // } + ma_ug_destroy(uu->ug); + // if(uu->nug) { + // free(uu->nug->idx); + // ma_ug_destroy(uu->nug->ug); + // free(uu->nug); + // } + free(uu); +} + +void destroy_idx_emask_t(idx_emask_t *mm) +{ + if(mm) { + uint64_t k; + for (k = 0; k < mm->n; k++) { + free(mm->a[k].a); memset(&(mm->a[k]), 0, sizeof(mm->a[k])); + } + free(mm->a); + } +} + +void gen_UL_ovlps(uldat_t *sl, int32_t cutoff) +{ + ul_idx_t *uu = dedup_HiFis(sl->uopt, 1, 0); + ///for unitig index + int exist = (asm_opt.load_index_from_disk? uidx_load(&ha_flt_tab, &ha_idx, asm_opt.output_file_name, NULL) : 0); + if(exist == 0) uidx_l_build(uu->ug, (mg_idxopt_t *)sl->opt, cutoff); + if(exist == 0) uidx_write(ha_flt_tab, ha_idx, asm_opt.output_file_name, NULL); + // print_debug_gfa(sl->uopt, ug, coverage_cut, "debug_dups", sources, ruIndex, asm_opt.max_hang_Len, asm_opt.min_overlap_Len); + sl->ha_flt_tab = ha_flt_tab; sl->ha_idx = (ha_pt_t *)ha_idx; sl->uu = uu; + ul_v_call(sl, asm_opt.ar); + // print_raw_u2rgfa_seq(&UL_INF, uu, 1); + destroy_ul_idx_t(uu); ha_ft_destroy(ha_flt_tab); ha_pt_destroy(ha_idx); + sl->ha_flt_tab = NULL; sl->ha_idx = NULL; sl->uu = NULL; +} + +int32_t load_emask_t(idx_emask_t **z, char* file_name, ma_ug_t *ug) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(file_name)+50); + sprintf(gfa_name, "%s.ul.msk.bin", file_name); + FILE* fp = fopen(gfa_name, "r"); free(gfa_name); + if (!fp) return 0; + if(ug && (!test_dbug(ug, fp))) { + fprintf(stderr, "[M::%s] Renew UL Index\n", __func__); + fclose(fp); + return 0; + } + uint64_t k; kv_emask_t *p; idx_emask_t *x; CALLOC(x, 1); + + + fread(&x->n, sizeof(x->n), 1, fp); MALLOC(x->a, x->n); + for (k = 0; k < x->n; k++) { + p = &(x->a[k]); + fread(&p->n, sizeof(p->n), 1, fp); MALLOC(p->a, p->n); p->m = p->n; + fread(p->a, sizeof((*(p->a))), p->n, fp); + } + + fprintf(stderr, "[M::%s] Index has been loaded.\n", __func__); + fclose(fp); + *z = x; + return 1; +} + +int32_t write_emask_t(idx_emask_t *x, char* file_name, ma_ug_t *ug) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(file_name)+50); + sprintf(gfa_name, "%s.ul.msk.bin", file_name); + FILE* fp = fopen(gfa_name, "w"); free(gfa_name); + if (!fp) return 0; + uint64_t k; kv_emask_t *p = NULL; + + if(ug) write_dbug(ug, fp); + + fwrite(&x->n, sizeof(x->n), 1, fp); + for (k = 0; k < x->n; k++) { + p = &(x->a[k]); + fwrite(&p->n, sizeof(p->n), 1, fp); + fwrite(p->a, sizeof((*(p->a))), p->n, fp); + } + + fprintf(stderr, "[M::%s] Index has been written.\n", __func__); + fclose(fp); + return 1; +} + +void gen_UL_reovlps(uldat_t *sl, ma_ug_t *ug, asg_t *sg, char* gfa_name, int32_t cutoff, int32_t is_emask) +{ + ul_idx_t *uu = gen_ul_idx(sl->uopt, ug, sg); + int exist = (asm_opt.load_index_from_disk? uidx_load(&ha_flt_tab, &ha_idx, gfa_name, ug) : 0); + if(exist == 0) uidx_l_build(uu->ug, (mg_idxopt_t *)sl->opt, cutoff); + if(exist == 0) uidx_write(ha_flt_tab, ha_idx, gfa_name, ug); + sl->ha_flt_tab = ha_flt_tab; sl->ha_idx = (ha_pt_t *)ha_idx; sl->uu = uu; + if(is_emask) { + if((!(asm_opt.load_index_from_disk)) || (!load_emask_t(&(sl->mm), gfa_name, ug))) { + sl->mm = graph_ovlp_binning(ug, sg, sl->uopt); + write_emask_t(sl->mm, gfa_name, ug); + } + } + + init_ucr_file_t(sl, gfa_name, 1); + ul_v_recall(sl, asm_opt.ar); + destory_ucr_file_t(sl); + ///do not free ug + uu->ug = NULL; destroy_ul_idx_t(uu); ha_ft_destroy(ha_flt_tab); ha_pt_destroy(ha_idx); + sl->ha_flt_tab = NULL; sl->ha_idx = NULL; sl->uu = NULL; + destroy_idx_emask_t(sl->mm); free(sl->mm); sl->mm = NULL; + // exit(1); +} + +uint32_t drenew_UL_reovlps(uldat_t *sl, ma_ug_t *ug, asg_t *sg, char* gfa_name, int32_t cutoff) +{ + uint32_t k, f_occ; + kt_for(asm_opt.thread_num, dcheck_ulalignments_mul, ug, UL_INF.n); + for (k = f_occ = 0; k < UL_INF.n; k++) { + if(UL_INF.a[k].rlen&((uint32_t)(0x80000000))) f_occ++; + } + fprintf(stderr, "[M::%s::] # wrong UL alignments::%u\n", __func__, f_occ); + if(f_occ == 0) return 0;//all set + + ul_idx_t *uu = gen_ul_idx(sl->uopt, ug, sg); + int exist = (asm_opt.load_index_from_disk? uidx_load(&ha_flt_tab, &ha_idx, gfa_name, ug) : 0); + if(exist == 0) uidx_l_build(uu->ug, (mg_idxopt_t *)sl->opt, cutoff); + if(exist == 0) uidx_write(ha_flt_tab, ha_idx, gfa_name, ug); + sl->ha_flt_tab = ha_flt_tab; sl->ha_idx = (ha_pt_t *)ha_idx; sl->uu = uu; + + // init_ucr_file_t(sl, gfa_name, 1); + recorrect_ul_pipeline(sl, asm_opt.ar); + // destory_ucr_file_t(sl); + ///do not free ug + uu->ug = NULL; destroy_ul_idx_t(uu); ha_ft_destroy(ha_flt_tab); ha_pt_destroy(ha_idx); + sl->ha_flt_tab = NULL; sl->ha_idx = NULL; sl->uu = NULL; + return 1; + // exit(1); +} + +void init_uldat_t(uldat_t *sl, void *ha_flt_tab, void *ha_idx, mg_idxopt_t *opt, uint64_t chunk_size, uint64_t n_thread, const ug_opt_t *uopt, ul_idx_t *uu) +{ + memset(sl, 0, sizeof(uldat_t)); + sl->ha_flt_tab = ha_flt_tab; + sl->ha_idx = (ha_pt_t *)ha_idx; + sl->opt = opt; + sl->chunk_size = chunk_size; + sl->n_thread = n_thread; + sl->uu = uu; + sl->uopt = uopt; +} + +int32_t write_all_ul_t(all_ul_t *x, char* file_name, ma_ug_t *ug) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(file_name)+50); + sprintf(gfa_name, "%s.ul.ovlp.bin", file_name); + FILE* fp = fopen(gfa_name, "w"); free(gfa_name); + if (!fp) return 0; + uint64_t k; ul_vec_t *p = NULL; + + if(ug) write_dbug(ug, fp); + + fwrite(&x->nid.n, sizeof(x->nid.n), 1, fp); + for (k = 0; k < x->nid.n; k++) { + fwrite(&x->nid.a[k].n, sizeof(x->nid.a[k].n), 1, fp); + fwrite(x->nid.a[k].a, sizeof((*(x->nid.a[k].a))), x->nid.a[k].n, fp); + } + + fwrite(&x->ridx.idx.n, sizeof(x->ridx.idx.n), 1, fp); + fwrite(x->ridx.idx.a, sizeof((*(x->ridx.idx.a))), x->ridx.idx.n, fp); + + fwrite(&x->ridx.occ.n, sizeof(x->ridx.occ.n), 1, fp); + fwrite(x->ridx.occ.a, sizeof((*(x->ridx.occ.a))), x->ridx.occ.n, fp); + + fwrite(&x->n, sizeof(x->n), 1, fp); + for (k = 0; k < x->n; k++) { + p = &(x->a[k]); + fwrite(&p->dd, sizeof(p->dd), 1, fp); + fwrite(&p->rlen, sizeof(p->rlen), 1, fp); + + fwrite(&p->r_base.n, sizeof(p->r_base.n), 1, fp); + fwrite(p->r_base.a, sizeof((*(p->r_base.a))), p->r_base.n, fp); + + fwrite(&p->bb.n, sizeof(p->bb.n), 1, fp); + fwrite(p->bb.a, sizeof((*(p->bb.a))), p->bb.n, fp); + + fwrite(&p->N_site.n, sizeof(p->N_site.n), 1, fp); + fwrite(p->N_site.a, sizeof((*(p->N_site.a))), p->N_site.n, fp); + } + + fprintf(stderr, "[M::%s] Index has been written.\n", __func__); + fclose(fp); + if(asm_opt.bin_only) exit(0); + return 1; +} + + +int32_t load_all_ul_t(all_ul_t *x, char* file_name, All_reads *hR, ma_ug_t *ug) +{ + char* gfa_name = NULL; MALLOC(gfa_name, strlen(file_name)+50); + sprintf(gfa_name, "%s.ul.ovlp.bin", file_name); + FILE* fp = fopen(gfa_name, "r"); free(gfa_name); + if (!fp) return 0; + if(ug && (!test_dbug(ug, fp))) { + fprintf(stderr, "[M::%s] Renew UL Index\n", __func__); + fclose(fp); + return 0; + } + + destory_all_ul_t(x); + memset(x, 0, sizeof(*x)); x->hR = hR; init_aux_table(); + uint64_t k; ul_vec_t *p = NULL; + + fread(&x->nid.n, sizeof(x->nid.n), 1, fp); x->nid.m = x->nid.n; MALLOC(x->nid.a, x->nid.n); + for (k = 0; k < x->nid.n; k++) { + fread(&x->nid.a[k].n, sizeof(x->nid.a[k].n), 1, fp); MALLOC(x->nid.a[k].a, x->nid.a[k].n); + fread(x->nid.a[k].a, sizeof((*(x->nid.a[k].a))), x->nid.a[k].n, fp); + } + + fread(&x->ridx.idx.n, sizeof(x->ridx.idx.n), 1, fp); x->ridx.idx.m = x->ridx.idx.n; MALLOC(x->ridx.idx.a, x->ridx.idx.n); + fread(x->ridx.idx.a, sizeof((*(x->ridx.idx.a))), x->ridx.idx.n, fp); + + fread(&x->ridx.occ.n, sizeof(x->ridx.occ.n), 1, fp); x->ridx.occ.m = x->ridx.occ.n; MALLOC(x->ridx.occ.a, x->ridx.occ.n); + fread(x->ridx.occ.a, sizeof((*(x->ridx.occ.a))), x->ridx.occ.n, fp); + + fread(&x->n, sizeof(x->n), 1, fp); x->m = x->n; MALLOC(x->a, x->n); + for (k = 0; k < x->n; k++) { + p = &(x->a[k]); + fread(&p->dd, sizeof(p->dd), 1, fp); + fread(&p->rlen, sizeof(p->rlen), 1, fp); + + fread(&p->r_base.n, sizeof(p->r_base.n), 1, fp); p->r_base.m = p->r_base.n; MALLOC(p->r_base.a, p->r_base.n); + fread(p->r_base.a, sizeof((*(p->r_base.a))), p->r_base.n, fp); + + fread(&p->bb.n, sizeof(p->bb.n), 1, fp); p->bb.m = p->bb.n; MALLOC(p->bb.a, p->bb.n); + fread(p->bb.a, sizeof((*(p->bb.a))), p->bb.n, fp); + + fread(&p->N_site.n, sizeof(p->N_site.n), 1, fp); p->N_site.m = p->N_site.n; MALLOC(p->N_site.a, p->N_site.n); + fread(p->N_site.a, sizeof((*(p->N_site.a))), p->N_site.n, fp); + } + + fprintf(stderr, "[M::%s] Index has been loaded.\n", __func__); + fclose(fp); + return 1; +} + +void ul_load(const ug_opt_t *uopt) +{ + fprintf(stderr, "[M::%s::] ==> UL\n", __func__); + mg_idxopt_t opt; uldat_t sl; + int32_t cutoff; + init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); + cutoff = asm_opt.max_n_chain; + init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); + init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, NULL); + + if(!load_all_ul_t(&UL_INF, asm_opt.output_file_name, &R_INF, NULL)) { + gen_UL_ovlps(&sl, cutoff); + write_all_ul_t(&UL_INF, asm_opt.output_file_name, NULL); + // exit(1); + } + // detect_outlier_len("ul_load"); + // print_all_ul_t_stat(&UL_INF); + // fprintf(stderr, "**1**\n"); + kt_for(sl.n_thread, update_ovlp_src, &sl, R_INF.total_reads); + // fprintf(stderr, "**2**\n"); + kt_for(sl.n_thread, update_ovlp_src_bl, &sl, R_INF.total_reads); + // fprintf(stderr, "**3**\n"); + + print_ovlp_src_bl_stat(&UL_INF, sl.uopt); + // exit(1); + // print_ul_ovlps(&UL_INF, 0); + // print_ul_ovlps(&UL_INF, 1); + + // destory_all_ul_t(&UL_INF); +} + +void clean_contain_g0(uldat_t *sl) +{ + kt_for(sl->n_thread, clean_contained_chg, sl, R_INF.total_reads); + asg_t *sg = (asg_t *)sl->rg; uint32_t k, cnt; + for (k = cnt = 0; k < sg->n_seq; k++) { + // if(is_contain_r((*(sl->uopt->ruIndex)), k)) { + // fprintf(stderr, "[M::%s::]\t%.*s\n", __func__, (int)Get_NAME_LENGTH(R_INF, k), Get_NAME(R_INF, k)); + // } + if(sg->seq_vis[k]) { + asg_seq_del(sg, k); cnt++; + } + sg->seq_vis[k] = 0; + } + if(cnt) asg_cleanup(sg); + fprintf(stderr, "[M::%s::] # discard cread::%u\n", __func__, cnt); + // exit(1); +} + +void asg_arc_push_contain_trans(asg_t *g, ma_hit_t_alloc* ov, int64_t min_ovlp, int64_t max_hang, double max_hang_rate, int64_t fuzz, R_to_U *ri, uint8_t *mark) +{ + uint32_t n_vtx = g->n_seq<<1, cnt = 0, nc, cc, qn, tn, avi, awi; + uint32_t v, w, i, k, nv, nw; asg_arc_t *av, *aw; int32_t r = 1; + ma_hit_t_alloc *z; asg_arc_t p, *t; + uint32_t *dis, *idx; CALLOC(dis, n_vtx); MALLOC(idx, n_vtx); + for (v = 0; v < n_vtx; ++v) { + if(g->seq[v>>1].del || (!mark[v])) continue; + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); + if (nv == 0) continue; // no hits + for (i = 0; i < nv; ++i) { + if((!(av[i].del)) && (is_contain_r((*ri), (av[i].v>>1)))) break; + } + if(i >= nv) continue; + z = &(ov[v>>1]); + for (i = 0; i < z->length; i++) { + qn = Get_qn(z->buffer[i]); tn = Get_tn(z->buffer[i]); + if(z->buffer[i].del) continue; + r = ma_hit2arc(&(z->buffer[i]), g->seq[qn].len, g->seq[tn].len, max_hang, max_hang_rate, min_ovlp, &p); + if((r < 0) || ((p.ul>>32) != v)) continue; + if(g->seq[p.v>>1].del) continue; + if(mark[p.v^1]) { + dis[p.v] = asg_arc_len(p) + fuzz; idx[p.v] = i; + } + } + + nv = asg_arc_n(g, v); av = asg_arc_a(g, v); avi = g->idx[v]>>32; + while(nv) { + for (i = nc = cc = 0; i < nv; ++i) { + if(av[i].del) {continue;} w = av[i].v; + if(!(is_contain_r((*ri), (w>>1)))) continue;///new arcs must be bridged by contained reads + assert(!(g->seq[w>>1].del)); + nw = asg_arc_n(g, w); aw = asg_arc_a(g, w); awi = g->idx[w]>>32; + for (k = 0; k < nw; k++) { + if(aw[k].del) continue; + if((dis[aw[k].v] == ((uint32_t)-1)) || (dis[aw[k].v] == 0)) continue; + assert(!(g->seq[aw[k].v>>1].del)); + if((asg_arc_len(av[i]) + asg_arc_len(aw[k])) <= dis[aw[k].v]) { + dis[aw[k].v] = ((uint32_t)-1); assert(!(z->buffer[idx[aw[k].v]].del)); + qn = Get_qn(z->buffer[idx[aw[k].v]]); tn = Get_tn(z->buffer[idx[aw[k].v]]); + r = ma_hit2arc(&(z->buffer[idx[aw[k].v]]), g->seq[qn].len, g->seq[tn].len, max_hang, max_hang_rate, min_ovlp, &p); + assert(r>=0); assert((p.ul>>32)==v); assert(p.v==aw[k].v); + cnt++; p.ou = 0; t = asg_arc_pushp(g); *t = p; + + // fprintf(stderr, "[M::%s::]\t%.*s(id::%lu::%c)(is_c::%u)\t%.*s(id::%u::%c)(is_c::%u)\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, (g->arc[g->n_arc-1].ul>>33)), + // Get_NAME(R_INF, (g->arc[g->n_arc-1].ul>>33)), + // g->arc[g->n_arc-1].ul>>33, "+-"[(g->arc[g->n_arc-1].ul>>32)&1], + // (is_contain_r((*ri), (g->arc[g->n_arc-1].ul>>33))), + // (int)Get_NAME_LENGTH(R_INF, (g->arc[g->n_arc-1].v>>1)), + // Get_NAME(R_INF, (g->arc[g->n_arc-1].v>>1)), + // g->arc[g->n_arc-1].v>>1, "+-"[(g->arc[g->n_arc-1].v)&1], + // (is_contain_r((*ri), (g->arc[g->n_arc-1].v>>1))) + // ); + // fprintf(stderr, "[M::%s::]\tmiddle::%.*s(id::%u::%c)(is_c::%u)\n", __func__, + // (int)Get_NAME_LENGTH(R_INF, (w>>1)), Get_NAME(R_INF, (w>>1)), + // w>>1, "+-"[w&1], (is_contain_r((*ri), (w>>1)))); + + + + av = g->arc + avi; aw = g->arc + awi;///renew av and aw since asg_arc_pushp + if((is_contain_r((*ri), (g->arc[g->n_arc-1].v>>1)))) { + cc++; + } else { + if(g->n_arc!=(nc+1)) { + p = g->arc[g->n_arc-1]; + g->arc[g->n_arc-1] = g->arc[nc]; + g->arc[nc] = p; + } + nc++; + } + } + } + } + + if(cc) {///new arcs must be bridged by contained reads + nv = cc; av = g->arc + g->n_arc - cc; avi = g->n_arc - cc; + } else { + nv = 0; av = NULL; avi = ((uint32_t)-1); + } + } + + z = &(ov[v>>1]); + for (i = 0; i < z->length; i++) { + qn = Get_qn(z->buffer[i]); tn = Get_tn(z->buffer[i]); + if(z->buffer[i].del) continue; + r = ma_hit2arc(&(z->buffer[i]), g->seq[qn].len, g->seq[tn].len, max_hang, max_hang_rate, min_ovlp, &p); + if((r < 0) || ((p.ul>>32) != v)) continue; + dis[p.v] = 0; + } + } + + free(dis); free(idx); + if(cnt) { + free(g->idx); + g->idx = 0; + g->is_srt = 0; + asg_cleanup(g); + asg_symm(g); + } +} + +void repush_contain_trans_archs(uldat_t *sl) +{ + asg_t *sg = (asg_t *)sl->rg; + kt_for(sl->n_thread, label_contained_chg, sl, (sg->n_seq<<1)); + + // print_debug_gfa(sg, NULL, sl->uopt->coverage_cut, "UL.dirty.debug0", sl->uopt->sources, sl->uopt->ruIndex, sl->uopt->max_hang, sl->uopt->min_ovlp, 0, 0, 0); + + asg_arc_push_contain_trans(sg, sl->uopt->sources, sl->uopt->min_ovlp, sl->uopt->max_hang, asm_opt.max_hang_rate, sl->uopt->gap_fuzz, sl->uopt->ruIndex, sg->seq_vis); + + // print_debug_gfa(sg, NULL, sl->uopt->coverage_cut, "UL.dirty.debug1", sl->uopt->sources, sl->uopt->ruIndex, sl->uopt->max_hang, sl->uopt->min_ovlp, 0, 0, 0); + // exit(1); +} + +uint32_t clean_contain_g(const ug_opt_t *uopt, asg_t *sg, uint32_t push_trans) +{ + mg_idxopt_t opt; uldat_t sl; int32_t cutoff, f = 0; + init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); + cutoff = asm_opt.max_n_chain; + init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); + init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, NULL); sl.rg = sg; + + if(push_trans) repush_contain_trans_archs(&sl); + if(work_ul_gchains_consensus(&sl)) { + free(UL_INF.ridx.idx.a); free(UL_INF.ridx.occ.a); memset(&(UL_INF.ridx), 0, sizeof(UL_INF.ridx)); + gen_ul_vec_rid_t(&UL_INF, &R_INF, NULL); + // fprintf(stderr, "+[M::%s::]\n", __func__); + kt_for(sl.n_thread, update_ovlp_src, &sl, R_INF.total_reads); + // fprintf(stderr, "-[M::%s::]\n", __func__); + kt_for(sl.n_thread, update_ovlp_src_bl, &sl, R_INF.total_reads); + clean_contain_g0(&sl); + f = 1; + } + if(push_trans) asg_arc_del_trans_ul(sg, sl.uopt->gap_fuzz); + return f; +} + + +void dedup_contain_g(const ug_opt_t *uopt, asg_t *sg) +{ + mg_idxopt_t opt; uldat_t sl; int32_t cutoff; + init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); + cutoff = asm_opt.max_n_chain; + init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); + init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, NULL); sl.rg = sg; + work_rg_contain_dedup(&sl); +} + + +uint64_t ul_refine_alignment(const ug_opt_t *uopt, asg_t *sg) +{ + fprintf(stderr, "[M::%s::] ==> UL refinement...\n", __func__); + mg_idxopt_t opt; uldat_t sl; int32_t cutoff; + init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); + cutoff = asm_opt.max_n_chain; + init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); + ul_idx_t *uu = gen_ul_idx_t(uopt, NULL, sg, 0, 0, 0);///record contained reads; is_el = is_del = 0 + init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, uu); sl.rg = sg; + if(work_ul_gchains(&sl)) { + free(UL_INF.ridx.idx.a); free(UL_INF.ridx.occ.a); memset(&(UL_INF.ridx), 0, sizeof(UL_INF.ridx)); + gen_ul_vec_rid_t(&UL_INF, &R_INF, NULL); + kt_for(sl.n_thread, update_ovlp_src, &sl, R_INF.total_reads); + kt_for(sl.n_thread, update_ovlp_src_bl, &sl, R_INF.total_reads); + destroy_ul_idx_t(uu); + return 1; + } else { + destroy_ul_idx_t(uu); + return 0; + } +} + +scaf_res_t *gen_contig_path(const ug_opt_t *uopt, asg_t *sg, ma_ug_t *ctg, ma_ug_t *ref) +{ + mg_idxopt_t opt; uldat_t sl; int32_t cutoff; + init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); + cutoff = asm_opt.max_n_chain; + init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); + ul_idx_t *uu = gen_ul_idx_t(uopt, ref, sg, 0, 0, 1); + init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, uu); sl.rg = sg; sl.ug = ctg; + + scaf_res_t *res = work_ctg_path_gchains(&sl); uu->ug = NULL; + destroy_ul_idx_t(uu); + return res; +} + +void gen_contig_trans(const ug_opt_t *uopt, asg_t *sg, ma_ug_t *qry, scaf_res_t *qry_sc, ma_ug_t *ref, scaf_res_t *ref_sc, ma_ug_t *gfa, kv_u_trans_t *ta, uint32_t qoff, uint32_t toff, bubble_type *bu, kv_u_trans_t *res) +{ + mg_idxopt_t opt; uldat_t sl; int32_t cutoff; + init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); + cutoff = asm_opt.max_n_chain; + init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); + ul_idx_t *uu = gen_ul_idx_t_sc(ref, sg, ref_sc, gfa->u.n); + init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, uu); sl.rg = sg; sl.ug = qry; + + work_ctg_path_trans(&sl, sg, qry, qry_sc, ref, ref_sc, gfa, ta, qoff, toff, bu, res); uu->ug = NULL; + destroy_ul_idx_t(uu); +} + +void gen_contig_self(const ug_opt_t *uopt, asg_t *sg, ma_ug_t *db, scaf_res_t *db_sc, ma_ug_t *gfa, kv_u_trans_t *ta, uint64_t soff, bubble_type *bu, kv_u_trans_t *res, uint32_t is_exact) +{ + mg_idxopt_t opt; uldat_t sl; int32_t cutoff; + init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); + cutoff = asm_opt.max_n_chain; + init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, ((is_exact)?(0.333333):(asm_opt.ul_error_rate)), asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); + ul_idx_t *uu = gen_ul_idx_t_sc(db, sg, db_sc, gfa->u.n); + init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, uu); sl.rg = sg; sl.ug = db; + + work_ctg_path_trans_self(&sl, sg, db, db_sc, gfa, ta, soff, is_exact, bu, res); + + uu->ug = NULL; destroy_ul_idx_t(uu); +} + +void order_contig_trans(kv_u_trans_t *in) +{ + utepdat_t s; uint64_t i, n_th = asm_opt.thread_num; memset(&s, 0, sizeof(s)); + CALLOC(s.hab, n_th); CALLOC(s.buf, n_th); CALLOC(s.ll, n_th); + CALLOC(s.gdp, n_th); CALLOC(s.mzs, n_th); CALLOC(s.sps, n_th); + + for (i = 0; i < n_th; ++i) { + s.hab[i] = ha_ovec_init(0, 0, 1); s.buf[i] = mg_tbuf_init(); + } + + ctdat_t c; memset(&c, 0, sizeof(c)); c.s = &(s); c.ta = in; + + c.mm = 0; kt_for(n_th, worker_for_ctg_trans_order, &c, in->idx.n); + c.mm = 1; kt_for(n_th, worker_for_ctg_trans_order, &c, in->idx.n); + + for (i = 0; i < n_th; ++i) { + s.sum_len += s.hab[i]->num_read_base; s.n += s.hab[i]->num_correct_base; + ha_ovec_destroy(s.hab[i]); mg_tbuf_destroy(s.buf[i]); hc_glchain_destroy(&(s.ll[i])); + hc_gdpchain_destroy(&(s.gdp[i])); kv_destroy(s.mzs[i]); kv_destroy(s.sps[i]); + } + + free(s.hab); free(s.buf); free(s.ll); free(s.gdp); free(s.mzs); free(s.sps); + fprintf(stderr, "[M::%s::] # try:%d, # done:%d\n", __func__, s.sum_len, s.n); + + uint64_t m; + for (i = m = 0; i < in->n; i++) { + if(in->a[i].del) continue; + in->a[m++] = in->a[i]; + } + in->n = m; + kt_u_trans_t_idx(in, in->idx.n); + c.mm = 2; kt_for(n_th, worker_for_ctg_trans_order, &c, in->idx.n); +} + + +uint32_t dd_ug(asg_t *sg, ma_ug_t *ug, ma_sub_t* coverage_cut, ma_hit_t_alloc* sources, R_to_U* ruIndex, const char* output_file_name) +{ + fprintf(stderr, "Writing raw unitig GFA to disk... \n"); + char* gfa_name = (char*)malloc(strlen(output_file_name)+25); + sprintf(gfa_name, "%s.r_utg.noseq.gfa", output_file_name); + FILE* output_file = fopen(gfa_name, "w"); + ma_ug_print_simple(ug, sg, coverage_cut, sources, ruIndex, "utg", output_file); + fclose(output_file); + + free(gfa_name); + exit(1); +} + + +void clear_all_ul_t(all_ul_t *x) +{ + uint64_t k, rlen; + for (k = 0; k < x->n; k++) { + rlen = x->a[k].rlen; + free(x->a[k].bb.a); free(x->a[k].N_site.a); free(x->a[k].r_base.a); + memset(&(x->a[k]), 0, sizeof(x->a[k])); x->a[k].rlen = rlen; + } + free(x->ridx.idx.a); free(x->ridx.occ.a); memset(&(x->ridx), 0, sizeof((x->ridx))); + + // if(x->mm) { + // for (k = 0; k < x->mm->n; k++) { + // free(x->mm->a[k].a); memset(&(x->mm->a[k]), 0, sizeof(x->mm->a[k])); + // } + // free(x->mm->a); free(x->mm); x->mm = NULL; + // } +} + +void init_ug_trans_t(ug_trans_t *opt, ug_opt_t *uopt, int32_t is_HPC, int32_t k, int32_t w, int32_t max_n_chain, +double bw_thres, double diff_ec_ul, double bw_thres_double, double diff_ec_ul_double, double sec_cutoff, int32_t n_thread, +int32_t mini_cut, int32_t chain_cut, int32_t keep_unsymm_arc, ma_ug_t *ug, asg_t *sg, bubble_type *bub, uint8_t gen_bub) +{ + int64_t i; uint8_t *bf = NULL; + memset(opt, 0, sizeof((*opt))); + opt->uopt = uopt; + opt->k = k; + opt->w = w; + opt->is_HPC = is_HPC; + opt->max_n_chain = max_n_chain; + opt->bw_thres = bw_thres; + opt->bw_thres_double = bw_thres_double; + opt->diff_ec_ul = diff_ec_ul; + opt->diff_ec_ul_double = diff_ec_ul_double; + opt->sec_cutoff = sec_cutoff; + opt->mini_cut = mini_cut; + opt->chain_cut = chain_cut; + opt->keep_unsymm_arc = keep_unsymm_arc; + + opt->bw = 10000;///2000 in minigraph + opt->max_gap = 500000;///5000 in minigraph + opt->ug = ug; + opt->rg = sg; + opt->n_thread = ((n_thread>=1)?n_thread:1); + + CALLOC(opt->free_cnt, opt->n_thread); + CALLOC(opt->hab, opt->n_thread); + CALLOC(opt->ll, opt->n_thread); + for (i = 0; i < opt->n_thread; ++i) { + opt->hab[i] = ha_ovec_init(0, 0, 1); + } + + opt->idx_n.n = opt->idx_n.m = ug->u.n+1; + MALLOC(opt->idx_n.a, opt->idx_n.n); + + opt->udb.ug = ug; + if(bub) { + opt->bub = bub; + } else if(gen_bub) { + opt->bub = gen_bubble_chain(sg, ug, uopt, &bf, 0); free(bf); + } +} + +void gen_trans_base_count(ug_trans_t *p, kv_u_trans_t *res) +{ + double index_time = yak_realtime(); + // ha_flt_tab = NULL; + uint64_t i, k, l, occ, m, cc; kv_ul_ov_t *bl = NULL; + u_trans_t *z; ha_mzl_t *tz; + clean_u_trans_t_idx_adv(res, p->ug, p->rg); p->filter = res; + fprintf(stderr, "[M::%s::] ==> 0\n", __func__); + p->is_cnt = 1; p->is_ovlp = 0; + kt_for(p->n_thread, worker_for_trans_ovlp, p, p->ug->u.n); + for (i = l = 0; i < p->ug->u.n; i++) { + occ = p->idx_n.a[i]; p->idx_n.a[i] = l; l += occ; + } + fprintf(stderr, "[M::%s::] i::%lu, l::%lu\n", __func__, i, l); + p->idx_n.a[i] = l; + p->idx_a.n = p->idx_a.m = l; MALLOC(p->idx_a.a, p->idx_a.n); + fprintf(stderr, "[M::%s::] ==> 1\n", __func__); + p->is_cnt = 0; p->is_ovlp = 0; + kt_for(p->n_thread, worker_for_trans_ovlp, p, p->ug->u.n); + p->srt_a.n = p->srt_a.m = p->idx_a.n; MALLOC(p->srt_a.a, p->srt_a.n); + fprintf(stderr, "[M::%s::] p->idx_a.n::%lu \n", __func__, (uint64_t)p->idx_a.n); + // memcpy(p->srt_a.a, p->idx_a.a, p->srt_a.n*sizeof((*(p->srt_a.a)))); + for (i = 0; i < p->srt_a.n; i++) { + p->srt_a.a[i] = p->idx_a.a[i]; + p->srt_a.a[i].pos = (uint32_t)i; + p->srt_a.a[i].rid = i>>32; + } + radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); + kvec_t(uint64_t) cut; kv_init(cut); + for (k = 1, l = 0; k <= p->srt_a.n; k++) { + if(k == p->srt_a.n || p->srt_a.a[l].x != p->srt_a.a[k].x) { + for (i = l; i < k; i++) { + m = p->srt_a.a[i].rid; m <<= 32; m |= p->srt_a.a[i].pos; + assert(p->srt_a.a[i].x == p->idx_a.a[m].x); + p->srt_a.a[i] = p->idx_a.a[m]; p->idx_a.a[m].x = i; + } + kv_push(uint64_t, cut, (k - l)); + l = k; + } + } + + if(cut.n > 0) { + radix_sort_gfa64(cut.a, cut.a + cut.n); + m = cut.n * 0.0002; cc = cut.a[cut.n-1] + 1; + if(m > 0 && m <= cut.n) cc = cut.a[cut.n-m] + 1; + if(cc < (uint64_t)p->mini_cut) p->mini_cut = cc; + } + kv_destroy(cut); + fprintf(stderr, "[M::%s::] p->mini_cut::%d \n", __func__, p->mini_cut); + + fprintf(stderr, "[M::%s::] ==> 2\n", __func__); + p->is_cnt = 0; p->is_ovlp = 1; + kt_for(p->n_thread, worker_for_trans_ovlp, p, p->ug->u.n); + fprintf(stderr, "[M::%s::] ==> 3\n", __func__); + for (i = 0; (int64_t)i < p->n_thread; i++) { + ha_ovec_destroy(p->hab[i]); + free(p->ll[i].lo.a); free(p->ll[i].srt.a.a); free(p->ll[i].tc.a); + } + free(p->idx_a.a); free(p->idx_n.a); free(p->hab); + // destory_bubbles(p->bub); free(p->bub); + + fprintf(stderr, "[M::%s::] ==> 4\n", __func__); + ///make results consistent + kv_resize(ha_mzl_t, p->srt_a, p->ug->u.n); p->srt_a.n = p->ug->u.n; + for (i = 0; i < p->srt_a.n; i++) { + tz = &(p->srt_a.a[i]); + tz->x = (uint64_t)-1; tz->rev = 0; + tz->pos = tz->rid = tz->span = 0; + } + // memset(p->srt_a.a, 0, sizeof((*(p->srt_a.a)))*p->srt_a.n); + for (i = 0, occ = res->n; (int64_t)i < p->n_thread; i++) { + bl = &(p->ll[i].tk); + if(!(bl->n)) continue; + for (k = 1, l = 0; k <= bl->n; k++) { + if(k == bl->n || bl->a[k].qn != bl->a[l].qn) { + if(k > l) { + tz = &(p->srt_a.a[bl->a[l].qn]); + tz->x = bl->a[l].qn; tz->x <<= 32; tz->x |= i; + tz->rid = l>>32; tz->pos = (uint32_t)l; tz->rev = 1; + occ += (k - l); + } + l = k; + } + } + } + fprintf(stderr, "[M::%s::] ==> 5\n", __func__); + kt_for(p->n_thread, worker_for_sysm_trans_ovlp, p, p->ug->u.n); + // assert(p->srt_a.n <= p->ug->u.n); + // radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); + kv_resize(u_trans_t, *res, occ); + for (i = 0; i < p->srt_a.n; i++) { + tz = &(p->srt_a.a[i]); + if(!(tz->rev)) continue; + bl = &(p->ll[(uint32_t)(tz->x)].tk); + k = tz->rid; k <<= 32; k += tz->pos; + assert(bl->a[k].qn == (tz->x>>32)); + for (; (k < bl->n) && (bl->a[k].qn == (tz->x>>32)); k++) { + if(bl->a[k].qn == bl->a[k].tn) continue; + if(bl->a[k].qs == (uint32_t)-1 && bl->a[k].qe == (uint32_t)-1) continue; + + kv_pushp(u_trans_t, *res, &z); + z->f = RC_3; z->rev = bl->a[k].rev; z->del = 0; + z->qn = bl->a[k].qn; z->qs = bl->a[k].qs; z->qe = bl->a[k].qe; + z->tn = bl->a[k].tn; z->ts = bl->a[k].ts; z->te = bl->a[k].te; + z->nw = cal_trans_ov_w(&(bl->a[k])); assert(z->nw > 0); + // if(z->nw <= 0) res->n--; + } + } + fprintf(stderr, "[M::%s::] ==> 6\n", __func__); + for (i = 0; (int64_t)i < p->n_thread; i++) free(p->ll[i].tk.a); + free(p->srt_a.a); free(p->ll); + fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); +} + + +void gen_trans_base_count_comp(ug_trans_t *p, kv_u_trans_t *res) +{ + double index_time = yak_realtime(); + // ha_flt_tab = NULL; + uint64_t i, k, l, occ, m, cc; kv_ul_ov_t *bl = NULL; + u_trans_t *z; ha_mzl_t *tz; double ww; + clean_u_trans_t_idx_adv(res, p->ug, p->rg); p->filter = res; + // fprintf(stderr, "[M::%s::] ==> 0\n", __func__); + p->is_cnt = 1; p->is_ovlp = 0; + memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); + kt_for(p->n_thread, worker_for_trans_ovlp_adv, p, p->ug->u.n); + for (i = l = 0; i < p->ug->u.n; i++) { + occ = p->idx_n.a[i]; p->idx_n.a[i] = l; l += occ; + } + // fprintf(stderr, "[M::%s::] i::%lu, l::%lu\n", __func__, i, l); + p->idx_n.a[i] = l; + p->idx_a.n = p->idx_a.m = l; MALLOC(p->idx_a.a, p->idx_a.n); + // fprintf(stderr, "[M::%s::] ==> 1\n", __func__); + p->is_cnt = 0; p->is_ovlp = 0; + memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); + kt_for(p->n_thread, worker_for_trans_ovlp_adv, p, p->ug->u.n); + p->srt_a.n = p->srt_a.m = p->idx_a.n; MALLOC(p->srt_a.a, p->srt_a.n); + // fprintf(stderr, "[M::%s::] p->idx_a.n::%lu \n", __func__, (uint64_t)p->idx_a.n); + // memcpy(p->srt_a.a, p->idx_a.a, p->srt_a.n*sizeof((*(p->srt_a.a)))); + for (i = 0; i < p->srt_a.n; i++) { + p->srt_a.a[i] = p->idx_a.a[i]; + p->srt_a.a[i].pos = (uint32_t)i; + p->srt_a.a[i].rid = i>>32; + } + radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); + kvec_t(uint64_t) cut; kv_init(cut); + for (k = 1, l = 0; k <= p->srt_a.n; k++) { + if(k == p->srt_a.n || p->srt_a.a[l].x != p->srt_a.a[k].x) { + for (i = l; i < k; i++) { + m = p->srt_a.a[i].rid; m <<= 32; m |= p->srt_a.a[i].pos; + assert(p->srt_a.a[i].x == p->idx_a.a[m].x); + p->srt_a.a[i] = p->idx_a.a[m]; p->idx_a.a[m].x = i; + } + kv_push(uint64_t, cut, (k - l)); + l = k; + } + } + + if(cut.n > 0) { + radix_sort_gfa64(cut.a, cut.a + cut.n); + m = cut.n * 0.0002; cc = cut.a[cut.n-1] + 1; + if(m > 0 && m <= cut.n) cc = cut.a[cut.n-m] + 1; + if(cc < (uint64_t)p->mini_cut) p->mini_cut = cc; + } + kv_destroy(cut); + // fprintf(stderr, "[M::%s::] p->mini_cut::%d \n", __func__, p->mini_cut); + + // fprintf(stderr, "[M::%s::] ==> 2\n", __func__); + p->is_cnt = 0; p->is_ovlp = 1; + memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); + kt_for(p->n_thread, worker_for_trans_ovlp_adv, p, p->ug->u.n); + // fprintf(stderr, "[M::%s::] ==> 3\n", __func__); + for (i = 0; (int64_t)i < p->n_thread; i++) { + ha_ovec_destroy(p->hab[i]); + free(p->ll[i].lo.a); free(p->ll[i].srt.a.a); free(p->ll[i].tc.a); + } + free(p->idx_a.a); free(p->idx_n.a); free(p->hab); free(p->free_cnt); + // destory_bubbles(p->bub); free(p->bub); + + // fprintf(stderr, "[M::%s::] ==> 4\n", __func__); + ///make results consistent + kv_resize(ha_mzl_t, p->srt_a, p->ug->u.n); p->srt_a.n = p->ug->u.n; + for (i = 0; i < p->srt_a.n; i++) { + tz = &(p->srt_a.a[i]); + tz->x = (uint64_t)-1; tz->rev = 0; + tz->pos = tz->rid = tz->span = 0; + } + // memset(p->srt_a.a, 0, sizeof((*(p->srt_a.a)))*p->srt_a.n); + for (i = 0, occ = res->n; (int64_t)i < p->n_thread; i++) { + bl = &(p->ll[i].tk); + if(!(bl->n)) continue; + for (k = 1, l = 0; k <= bl->n; k++) { + if(k == bl->n || bl->a[k].qn != bl->a[l].qn) { + if(k > l) { + tz = &(p->srt_a.a[bl->a[l].qn]); + tz->x = bl->a[l].qn; tz->x <<= 32; tz->x |= i; + tz->rid = l>>32; tz->pos = (uint32_t)l; tz->rev = 1; + occ += (k - l); + } + l = k; + } + } + } + // fprintf(stderr, "[M::%s::] ==> 5\n", __func__); + // kt_for(p->n_thread, worker_for_sysm_trans_ovlp, p, p->ug->u.n);///not correct + // assert(p->srt_a.n <= p->ug->u.n); + // radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); + kv_resize(u_trans_t, *res, occ); + for (i = 0; i < p->srt_a.n; i++) { + tz = &(p->srt_a.a[i]); + if(!(tz->rev)) continue; + bl = &(p->ll[(uint32_t)(tz->x)].tk); + k = tz->rid; k <<= 32; k += tz->pos; + assert(bl->a[k].qn == (tz->x>>32)); + for (; (k < bl->n) && (bl->a[k].qn == (tz->x>>32)); k++) { + if(bl->a[k].qn == bl->a[k].tn) continue; + ww = cal_trans_ov_w(&(bl->a[k])); + if(ww <= 0) continue; + + kv_pushp(u_trans_t, *res, &z); + z->f = RC_3; z->rev = bl->a[k].rev; z->del = 0; + z->qn = bl->a[k].qn; z->qs = bl->a[k].qs; z->qe = bl->a[k].qe; + z->tn = bl->a[k].tn; z->ts = bl->a[k].ts; z->te = bl->a[k].te; + z->nw = ww; + // if(z->qn == 56 || z->qn == 160 || z->tn == 56 || z->tn == 160) { + // fprintf(stderr, ">>>utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\n", + // z->qn+1, "lc"[p->ug->u.a[z->qn].circ], p->ug->u.a[z->qn].len, z->qs, z->qe, "+-"[z->rev], + // z->tn+1, "lc"[p->ug->u.a[z->tn].circ], p->ug->u.a[z->tn].len, z->ts, z->te, z->nw); + // } + // if(z->nw <= 0) res->n--; + } + } + // fprintf(stderr, "[M::%s::] ==> 6\n", __func__); + for (i = 0; (int64_t)i < p->n_thread; i++) free(p->ll[i].tk.a); + free(p->srt_a.a); free(p->ll); + fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); +} + +void clean_trans_base_count_mmhap_comp_rmap(ug_trans_t *p, kv_u_trans_t *res) +{ + uint64_t i, k, l, occ, idx_n; ha_mzl_t *tz; u_trans_t *z; + kv_ul_ov_t *bl; double ww; ha_mzl_t *idx; + ///make results consistent + kv_resize(ha_mzl_t, p->srt_a, p->srt_a.n+p->ug->u.n); + idx = p->srt_a.a + p->srt_a.n; idx_n = p->ug->u.n; + for (i = 0; i < idx_n; i++) { + tz = &(idx[i]); + tz->x = (uint64_t)-1; tz->rev = 0; + tz->pos = tz->rid = tz->span = 0; + } + + for (i = 0, occ = res->n; (int64_t)i < p->n_thread; i++) { + bl = &(p->ll[i].tk); + if(!(bl->n)) continue; + for (k = 1, l = 0; k <= bl->n; k++) { + if(k == bl->n || bl->a[k].qn != bl->a[l].qn) { + if(k > l) { + tz = &(idx[bl->a[l].qn]); + tz->x = bl->a[l].qn; tz->x <<= 32; tz->x |= i; + tz->rid = l>>32; tz->pos = (uint32_t)l; tz->rev = 1; + occ += (k - l); + } + l = k; + } + } + } + + kv_resize(u_trans_t, *res, occ); + for (i = 0; i < idx_n; i++) { + tz = &(idx[i]); + if(!(tz->rev)) continue; + bl = &(p->ll[(uint32_t)(tz->x)].tk); + k = tz->rid; k <<= 32; k += tz->pos; + assert(bl->a[k].qn == (tz->x>>32)); + for (; (k < bl->n) && (bl->a[k].qn == (tz->x>>32)); k++) { + if(bl->a[k].qn == bl->a[k].tn) continue; + ww = cal_trans_ov_w(&(bl->a[k])); + if(ww <= 0) continue; + + kv_pushp(u_trans_t, *res, &z); + z->f = RC_3; z->rev = bl->a[k].rev; z->del = 0; + z->qn = bl->a[k].qn; z->qs = bl->a[k].qs; z->qe = bl->a[k].qe; + z->tn = bl->a[k].tn; z->ts = bl->a[k].ts; z->te = bl->a[k].te; + z->nw = ww; + } + } + destory_ug_rid_cov_t(p->ccov); free(p->ccov); + p->ccov = gen_ug_rid_cov_t(p->ug, p->rg, p->uopt->sources); + + clean_u_trans_t_idx_filter_mmhap_adv(res, p->ug, p->rg, p->uopt->sources, p->ccov); + gen_ug_rid_cov_t_by_ovlp(res, p->ccov); +} + +void gen_trans_base_count_mmhap_comp_rmap(ug_trans_t *p, kv_u_trans_t *res) +{ + double index_time = yak_realtime(); + uint64_t i, k, l, occ, m, cc; + p->ccov = gen_ug_rid_cov_t(p->ug, p->rg, p->uopt->sources); + clean_u_trans_t_idx_adv(res, p->ug, p->rg); p->filter = res; + + p->is_cnt = 1; p->is_ovlp = 0; + memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); + kt_for(p->n_thread, worker_for_trans_ovlp_mmhap_adv, p, p->ug->u.n); + for (i = l = 0; i < p->ug->u.n; i++) { + occ = p->idx_n.a[i]; p->idx_n.a[i] = l; l += occ; + } + + p->idx_n.a[i] = l; + p->idx_a.n = p->idx_a.m = l; MALLOC(p->idx_a.a, p->idx_a.n); + p->is_cnt = 0; p->is_ovlp = 0; + memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); + kt_for(p->n_thread, worker_for_trans_ovlp_mmhap_adv, p, p->ug->u.n); + p->srt_a.n = p->srt_a.m = p->idx_a.n; MALLOC(p->srt_a.a, p->srt_a.n); + + for (i = 0; i < p->srt_a.n; i++) { + p->srt_a.a[i] = p->idx_a.a[i]; + p->srt_a.a[i].pos = (uint32_t)i; + p->srt_a.a[i].rid = i>>32; + } + radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); + kvec_t(uint64_t) cut; kv_init(cut); + for (k = 1, l = 0; k <= p->srt_a.n; k++) { + if(k == p->srt_a.n || p->srt_a.a[l].x != p->srt_a.a[k].x) { + for (i = l; i < k; i++) { + m = p->srt_a.a[i].rid; m <<= 32; m |= p->srt_a.a[i].pos; + assert(p->srt_a.a[i].x == p->idx_a.a[m].x); + p->srt_a.a[i] = p->idx_a.a[m]; p->idx_a.a[m].x = i; + } + kv_push(uint64_t, cut, (k - l)); + l = k; + } + } + + if(cut.n > 0) { + radix_sort_gfa64(cut.a, cut.a + cut.n); + m = cut.n * 0.0002; cc = cut.a[cut.n-1] + 1; + if(m > 0 && m <= cut.n) cc = cut.a[cut.n-m] + 1; + if(cc < (uint64_t)p->mini_cut) p->mini_cut = cc; + } + kv_destroy(cut); + + p->is_cnt = 0; p->is_ovlp = 1; + memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); + kt_for(p->n_thread, worker_for_trans_ovlp_mmhap_adv, p, p->ug->u.n); + + clean_trans_base_count_mmhap_comp_rmap(p, res); + + for (i = 0; (int64_t)i < p->n_thread; i++) p->ll[i].tk.n = 0; + + p->is_cnt = 0; p->is_ovlp = 1; + memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); + kt_for(p->n_thread, worker_for_trans_chain_mmhap_adv, p, p->ug->u.n); + + + + + + for (i = 0; (int64_t)i < p->n_thread; i++) { + ha_ovec_destroy(p->hab[i]); + free(p->ll[i].lo.a); free(p->ll[i].srt.a.a); free(p->ll[i].tc.a); + } + free(p->idx_a.a); free(p->idx_n.a); free(p->hab); free(p->free_cnt); + destory_ug_rid_cov_t(p->ccov); free(p->ccov); + + + + + + + + + + + for (i = 0; (int64_t)i < p->n_thread; i++) free(p->ll[i].tk.a); + free(p->srt_a.a); free(p->ll); + fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); +} + +void gen_trans_base_count_mmhap_comp(ug_trans_t *p, kv_u_trans_t *res) +{ + double index_time = yak_realtime(); + // ha_flt_tab = NULL; + uint64_t i, k, l, occ, m, cc; kv_ul_ov_t *bl = NULL; + u_trans_t *z; ha_mzl_t *tz; double ww; + p->ccov = gen_ug_rid_cov_t(p->ug, p->rg, p->uopt->sources); + clean_u_trans_t_idx_adv(res, p->ug, p->rg); p->filter = res; + // fprintf(stderr, "[M::%s::] ==> 0\n", __func__); + p->is_cnt = 1; p->is_ovlp = 0; + memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); + kt_for(p->n_thread, worker_for_trans_ovlp_mmhap_adv, p, p->ug->u.n); + for (i = l = 0; i < p->ug->u.n; i++) { + occ = p->idx_n.a[i]; p->idx_n.a[i] = l; l += occ; + } + // fprintf(stderr, "[M::%s::] i::%lu, l::%lu\n", __func__, i, l); + p->idx_n.a[i] = l; + p->idx_a.n = p->idx_a.m = l; MALLOC(p->idx_a.a, p->idx_a.n); + // fprintf(stderr, "[M::%s::] ==> 1\n", __func__); + p->is_cnt = 0; p->is_ovlp = 0; + memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); + kt_for(p->n_thread, worker_for_trans_ovlp_mmhap_adv, p, p->ug->u.n); + p->srt_a.n = p->srt_a.m = p->idx_a.n; MALLOC(p->srt_a.a, p->srt_a.n); + // fprintf(stderr, "[M::%s::] p->idx_a.n::%lu \n", __func__, (uint64_t)p->idx_a.n); + // memcpy(p->srt_a.a, p->idx_a.a, p->srt_a.n*sizeof((*(p->srt_a.a)))); + for (i = 0; i < p->srt_a.n; i++) { + p->srt_a.a[i] = p->idx_a.a[i]; + p->srt_a.a[i].pos = (uint32_t)i; + p->srt_a.a[i].rid = i>>32; + } + radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); + kvec_t(uint64_t) cut; kv_init(cut); + for (k = 1, l = 0; k <= p->srt_a.n; k++) { + if(k == p->srt_a.n || p->srt_a.a[l].x != p->srt_a.a[k].x) { + for (i = l; i < k; i++) { + m = p->srt_a.a[i].rid; m <<= 32; m |= p->srt_a.a[i].pos; + assert(p->srt_a.a[i].x == p->idx_a.a[m].x); + p->srt_a.a[i] = p->idx_a.a[m]; p->idx_a.a[m].x = i; + } + kv_push(uint64_t, cut, (k - l)); + l = k; + } + } + + if(cut.n > 0) { + radix_sort_gfa64(cut.a, cut.a + cut.n); + m = cut.n * 0.0002; cc = cut.a[cut.n-1] + 1; + if(m > 0 && m <= cut.n) cc = cut.a[cut.n-m] + 1; + if(cc < (uint64_t)p->mini_cut) p->mini_cut = cc; + } + kv_destroy(cut); + // fprintf(stderr, "[M::%s::] p->mini_cut::%d \n", __func__, p->mini_cut); + + // fprintf(stderr, "[M::%s::] ==> 2\n", __func__); + p->is_cnt = 0; p->is_ovlp = 1; + memset(p->free_cnt, 0, sizeof((*(p->free_cnt)))*p->n_thread); + kt_for(p->n_thread, worker_for_trans_ovlp_mmhap_adv, p, p->ug->u.n); + // fprintf(stderr, "[M::%s::] ==> 3\n", __func__); + for (i = 0; (int64_t)i < p->n_thread; i++) { + ha_ovec_destroy(p->hab[i]); + free(p->ll[i].lo.a); free(p->ll[i].srt.a.a); free(p->ll[i].tc.a); + } + free(p->idx_a.a); free(p->idx_n.a); free(p->hab); free(p->free_cnt); + destory_ug_rid_cov_t(p->ccov); free(p->ccov); + // destory_bubbles(p->bub); free(p->bub); + + // fprintf(stderr, "[M::%s::] ==> 4\n", __func__); + ///make results consistent + kv_resize(ha_mzl_t, p->srt_a, p->ug->u.n); p->srt_a.n = p->ug->u.n; + for (i = 0; i < p->srt_a.n; i++) { + tz = &(p->srt_a.a[i]); + tz->x = (uint64_t)-1; tz->rev = 0; + tz->pos = tz->rid = tz->span = 0; + } + // memset(p->srt_a.a, 0, sizeof((*(p->srt_a.a)))*p->srt_a.n); + for (i = 0, occ = res->n; (int64_t)i < p->n_thread; i++) { + bl = &(p->ll[i].tk); + if(!(bl->n)) continue; + for (k = 1, l = 0; k <= bl->n; k++) { + if(k == bl->n || bl->a[k].qn != bl->a[l].qn) { + if(k > l) { + tz = &(p->srt_a.a[bl->a[l].qn]); + tz->x = bl->a[l].qn; tz->x <<= 32; tz->x |= i; + tz->rid = l>>32; tz->pos = (uint32_t)l; tz->rev = 1; + occ += (k - l); + } + l = k; + } + } + } + // fprintf(stderr, "[M::%s::] ==> 5\n", __func__); + // kt_for(p->n_thread, worker_for_sysm_trans_ovlp, p, p->ug->u.n);///not correct + // assert(p->srt_a.n <= p->ug->u.n); + // radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); + kv_resize(u_trans_t, *res, occ); + for (i = 0; i < p->srt_a.n; i++) { + tz = &(p->srt_a.a[i]); + if(!(tz->rev)) continue; + bl = &(p->ll[(uint32_t)(tz->x)].tk); + k = tz->rid; k <<= 32; k += tz->pos; + assert(bl->a[k].qn == (tz->x>>32)); + for (; (k < bl->n) && (bl->a[k].qn == (tz->x>>32)); k++) { + if(bl->a[k].qn == bl->a[k].tn) continue; + ww = cal_trans_ov_w(&(bl->a[k])); + if(ww <= 0) continue; + + kv_pushp(u_trans_t, *res, &z); + z->f = RC_3; z->rev = bl->a[k].rev; z->del = 0; + z->qn = bl->a[k].qn; z->qs = bl->a[k].qs; z->qe = bl->a[k].qe; + z->tn = bl->a[k].tn; z->ts = bl->a[k].ts; z->te = bl->a[k].te; + z->nw = ww; + // if(z->ts >= z->te || z->qs >= z->qe) { + // fprintf(stderr, "[M::%s]\tutg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\n", __func__, + // z->qn+1, "lc"[p->ug->u.a[z->qn].circ], p->ug->u.a[z->qn].len, z->qs, z->qe, "+-"[z->rev], + // z->tn+1, "lc"[p->ug->u.a[z->tn].circ], p->ug->u.a[z->tn].len, z->ts, z->te); + // } + // if(z->qn == 56 || z->qn == 160 || z->tn == 56 || z->tn == 160) { + // fprintf(stderr, ">>>utg%.6u%c\t%u\t%u\t%u\t%c\tutg%.6u%c\t%u\t%u\t%u\tnw::%f\n", + // z->qn+1, "lc"[p->ug->u.a[z->qn].circ], p->ug->u.a[z->qn].len, z->qs, z->qe, "+-"[z->rev], + // z->tn+1, "lc"[p->ug->u.a[z->tn].circ], p->ug->u.a[z->tn].len, z->ts, z->te, z->nw); + // } + // if(z->nw <= 0) res->n--; + } + } + // fprintf(stderr, "[M::%s::] ==> 6\n", __func__); + for (i = 0; (int64_t)i < p->n_thread; i++) free(p->ll[i].tk.a); + free(p->srt_a.a); free(p->ll); + fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); +} + +void trans_base_infer(ma_ug_t *ug, asg_t *sg, ug_opt_t *uopt, kv_u_trans_t *res, bubble_type *bub) +{ + ug_trans_t sl; + init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); + init_ug_trans_t(&sl, uopt, 0, asm_opt.trans_mer_length, asm_opt.trans_win, asm_opt.max_n_chain, + 1.0-asm_opt.trans_base_rate, 1.0-asm_opt.trans_base_rate, 1.0-asm_opt.trans_base_rate_sec, 1.0-asm_opt.trans_base_rate_sec, + 0.85, asm_opt.thread_num, 512, 3, 1, ug, sg, bub, 1); + // gen_trans_base_count(&sl, res); + gen_trans_base_count_comp(&sl, res); + if(!bub) { + destory_bubbles(sl.bub); free(sl.bub); + } +} + +void trans_base_mmhap_infer(ma_ug_t *ug, asg_t *sg, ug_opt_t *uopt, kv_u_trans_t *res) +{ + ug_trans_t sl; + init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); + init_ug_trans_t(&sl, uopt, 0, asm_opt.trans_mer_length, asm_opt.trans_win, asm_opt.max_n_chain, + 1.0-asm_opt.trans_base_rate, 1.0-asm_opt.trans_base_rate, 1.0-asm_opt.trans_base_rate_sec, 1.0-asm_opt.trans_base_rate_sec, + 0.85, asm_opt.thread_num, 512, 3, 1, ug, sg, NULL, 0); + // gen_trans_base_count(&sl, res); + gen_trans_base_count_mmhap_comp(&sl, res); +} + +void init_ug_bin_t(ug_bin_t *sl, const ug_opt_t *uopt, int32_t is_HPC, int32_t k, int32_t w, int32_t max_n_chain, +double bw_thres, double diff_ov, double diff_bin, uint64_t max_diff, uint64_t min_bin_len, int32_t n_thread, +int32_t mini_cut, int32_t chain_cut, int32_t keep_unsymm_arc, ma_ug_t *ug, asg_t *sg) +{ + int64_t i; + memset(sl, 0, sizeof((*sl))); + sl->uopt = uopt; + sl->k = k; + sl->w = w; + sl->is_HPC = is_HPC; + sl->max_n_chain = max_n_chain; + sl->bw_thres = bw_thres; + sl->diff_ov = diff_ov; + sl->diff_bin = diff_bin; + sl->max_diff = max_diff; + sl->min_bin_len = min_bin_len; + sl->mini_cut = mini_cut; + sl->chain_cut = chain_cut; + sl->keep_unsymm_arc = keep_unsymm_arc; + + sl->bw = 10000;///2000 in minigraph + sl->max_gap = 500000;///5000 in minigraph + sl->ug = ug; + sl->rg = sg; + sl->n_thread = ((n_thread>=1)?n_thread:1); + + CALLOC(sl->mk, sl->n_thread); + CALLOC(sl->hab, sl->n_thread); + CALLOC(sl->ll, sl->n_thread); + for (i = 0; i < sl->n_thread; ++i) sl->hab[i] = ha_ovec_init(0, 0, 1); + + sl->idx_n.n = sl->idx_n.m = ug->u.n+1; + MALLOC(sl->idx_n.a, sl->idx_n.n); + + sl->udb.ug = ug; + // CALLOC(sl->bm, sl->n_thread); + // for (i = 0; i < sl->n_thread; ++i) { + // sl->bm[i].n = ((sl->udb.ug->g->n_seq<<1)>>3) + (!!((sl->udb.ug->g->n_seq<<1)&((uint32_t)7))); + // CALLOC(sl->bm[i].a, sl->bm[i].n); + // } +} + +void extract_microsatellite(const char *in, uint32_t in_len, hpc_re_t *res, asg64_v *buf, uint32_t mcs_len, +uint32_t min_klen_simple, uint32_t min_klen_complex, uint32_t ksimple_cut, hpc_idx_t *idx) +{ + uint32_t k, i, l, c, o, ls; char sk[256]; hpc_ss_t z, *za; + uint32_t m, cutoff, zn, bn, ovlp, os, oe, oks, oke; + idx->s = idx->e = res->n; + if(mcs_len > 255) mcs_len = 255; + for (k = 1; k <= mcs_len; k++) { + memset(sk, 'N', k); ///k->length of k-mer + o = ((k<=ksimple_cut)?(k*min_klen_simple):(k*min_klen_complex)); + for (i = l = ls = 0; i < in_len; i++) { + c = seq_nt4_table[(uint8_t)in[i]]; + if((c < 4) && (((l >= k) && (sk[(l+ls)%k] == in[i])) || (l < k))) { + if(l < k) sk[(l+ls)%k] = in[i]; + l++; + } else { + if(l >= o) { + z.s = i-l; z.e = i; z.k = k; + kv_push(hpc_ss_t, *res, z); + } + + if(c >= 4) { + l = ls = 0; + } else if(l >= 0) { + sk[(l+ls)%k] = in[i]; l++; + m = ((l<=k)?(l-1):(k)); + ls = (ls+(l-m))%k; l = m; + } + } + } + } + + uint32_t ks, ke, fs, fe; + radix_sort_hpc_ss_t_s(res->a+idx->s, res->a+res->n); + for (k = ks = ke = idx->e = idx->s; k < res->n; k++) { + fs = fe = (uint32_t)-1; + if(ke > idx->s) { + fs = res->a[ks].s; fe = res->a[ke-1].e; + } + ///new interval is not overlapped with existing one + if((fs == ((uint32_t)-1)) || (fe <= res->a[k].s)) { + res->a[idx->e++] = res->a[k]; ks = idx->e - 1; ke = idx->e; + } else { + assert(res->a[k].s >= fs); + ///new interval might be contained in an exist one + if(res->a[k].s >= fs && res->a[k].e <= fe) { + for (i = ks; i < ke; i++) { + if(res->a[k].s >= res->a[i].s && res->a[k].e <= res->a[i].e) {///new interval is contained in an exist one + if((res->a[k].s == res->a[i].s) && (res->a[k].e == res->a[i].e) + && (res->a[k].k < res->a[i].k)) { + res->a[i] = res->a[k]; + } + break; + } + } + if(i < ke) continue; + } + + for (i = m = ks; i < ke; i++) { + ///exist interval is contained in new interval + if(res->a[k].s <= res->a[i].s && res->a[k].e >= res->a[i].e) continue; + res->a[m++] = res->a[i]; + } + ke = idx->e = m; + res->a[idx->e++] = res->a[k]; ke = idx->e; + } + } + res->n = idx->e; + cutoff = (in_len/sizeof((*(res->a))))/4; if(cutoff < 10) cutoff = 10; + if(idx->e-idx->s > cutoff) {///compress if there are too many intervals + kv_resize(uint64_t, *buf, res->n-idx->s); + za = res->a + idx->s; zn = idx->e - idx->s; + for (k = buf->n = 0; k < zn; k++) { + kv_push(uint64_t, *buf, ((((uint64_t)za[k].k)<<32)|((uint64_t)(k)))); + } + radix_sort_gfa64(buf->a, buf->a+buf->n);///sorted by the k-mer length + for (i = 0, bn = buf->n; i < bn; i++) { + k = (uint32_t)buf->a[i]; oks = za[k].s; oke = za[k].e; + for (m = 0; m < zn && za[m].s < za[k].e; m++) { + if(!(buf->a[m]&((uint64_t)0x8000000000000000))) continue; + if(m == k) continue; + ///now has overlap + os = MAX(za[m].s, oks); oe = MIN(za[m].e, oke); + ovlp = ((oe > os)?(oe - os):(0)); + if(!ovlp) continue; + assert(os == oks || oe == oke); + if(os == oks) oks = oe; + if(oe == oke) oke = os; + if(oke < oks + za[k].k) break; + } + if(oke >= oks + za[k].k) { + buf->a[k] |= ((uint64_t)0x8000000000000000); + } + } + for (i = 0, idx->e = idx->s; i < bn; i++) { + if(!(buf->a[i]&((uint64_t)0x8000000000000000))) continue; + res->a[idx->e++] = za[i]; + } + res->n = idx->e; + } + // for (i = idx->s; i < idx->e; i++) { + // fprintf(stderr, "k::%u\tin::[%u,\t%u)\n", res->a[i].k, res->a[i].s, res->a[i].e); + // } +} + +hpc_re_t *gen_hpc_re_t(ma_ug_t *ug) +{ + uint64_t k; asg64_v buf; kv_init(buf); + hpc_re_t *p = NULL; CALLOC(p, 1); + kvec_t(char) cc; kv_init(cc); + p->idx_n = ug->u.n; CALLOC(p->idx, p->idx_n); + + for (k = 0; k < ug->u.n; k++) { + kv_resize(char, cc, ug->u.a[k].len); + retrieve_u_seq(NULL, cc.a, &(ug->u.a[k]), 0, 0, ug->u.a[k].len, NULL); + // fprintf(stderr, "\nutg%.6lu%c\tlen::%u\n", k + 1, "lc"[ug->u.a[k].circ], ug->u.a[k].len); + extract_microsatellite(cc.a, ug->u.a[k].len, p, &buf, 8, 8, 5, 1, &(p->idx[k])); + // fprintf(stderr, "utg%.6lu%c\t#::%u\tlen::%u\n", k + 1, "lc"[ug->u.a[k].circ], p->idx[k].e-p->idx[k].s, ug->u.a[k].len); + } + + kv_destroy(cc); kv_destroy(buf); + return p; +} + +void sysm_graph_bin(ug_bin_t *s) +{ + uint64_t k, i; kv_emask_t *r; + s->is_cnt = 1; s->is_ovlp = 0; + kt_for(s->n_thread, worker_for_graph_bin_sysm, s, s->ug->u.n); + for (i = 0; i < s->mm->n; i++) { + r = &(s->mm->a[i]); + for (k = 0; k < r->n; k++) { + if(r->a[k].rn == (uint32_t)-1) s->mm->a[r->a[k].tn].m++; + } + } + for (i = 0; i < s->mm->n; i++) { + r = &(s->mm->a[i]); + if(r->m > r->n) REALLOC(r->a, r->m); + } + + + s->is_cnt = 0; s->is_ovlp = 1; + kt_for(s->n_thread, worker_for_graph_bin_sysm, s, s->ug->u.n); + + s->is_cnt = 1; s->is_ovlp = 1; + kt_for(s->n_thread, worker_for_graph_bin_sysm, s, s->ug->u.n); +} + +void cal_graph_ovlp_binning(ug_bin_t *p) +{ + double index_time = yak_realtime(); + // ha_flt_tab = NULL; + uint64_t i, k, l, occ, m, cc; + // p->hre = gen_hpc_re_t(p->ug); + CALLOC(p->mm, 1); p->mm->n = p->udb.ug->g->n_seq; CALLOC(p->mm->a, p->mm->n); + + // fprintf(stderr, "[M::%s::] ==> 0\n", __func__); + p->is_cnt = 1; p->is_ovlp = 0; + kt_for(p->n_thread, worker_for_graph_bin, p, p->ug->u.n); + for (i = l = 0; i < p->ug->u.n; i++) { + occ = p->idx_n.a[i]; p->idx_n.a[i] = l; l += occ; + } + // fprintf(stderr, "[M::%s::] i::%lu, l::%lu\n", __func__, i, l); + p->idx_n.a[i] = l; + p->idx_a.n = p->idx_a.m = l; MALLOC(p->idx_a.a, p->idx_a.n); + // fprintf(stderr, "[M::%s::] ==> 1\n", __func__); + p->is_cnt = 0; p->is_ovlp = 0; + kt_for(p->n_thread, worker_for_graph_bin, p, p->ug->u.n); + p->srt_a.n = p->srt_a.m = p->idx_a.n; MALLOC(p->srt_a.a, p->srt_a.n); + // fprintf(stderr, "[M::%s::] p->idx_a.n::%lu \n", __func__, (uint64_t)p->idx_a.n); + // memcpy(p->srt_a.a, p->idx_a.a, p->srt_a.n*sizeof((*(p->srt_a.a)))); + for (i = 0; i < p->srt_a.n; i++) { + p->srt_a.a[i] = p->idx_a.a[i]; + p->srt_a.a[i].pos = (uint32_t)i; + p->srt_a.a[i].rid = i>>32; + } + radix_sort_ha_mzl_t_srt(p->srt_a.a, p->srt_a.a + p->srt_a.n); + kvec_t(uint64_t) cut; kv_init(cut); + for (k = 1, l = 0; k <= p->srt_a.n; k++) { + if(k == p->srt_a.n || p->srt_a.a[l].x != p->srt_a.a[k].x) { + for (i = l; i < k; i++) { + m = p->srt_a.a[i].rid; m <<= 32; m |= p->srt_a.a[i].pos; + assert(p->srt_a.a[i].x == p->idx_a.a[m].x); + p->srt_a.a[i] = p->idx_a.a[m]; p->idx_a.a[m].x = i; + } + kv_push(uint64_t, cut, (k - l)); + l = k; + } + } + + if(cut.n > 0) { + radix_sort_gfa64(cut.a, cut.a + cut.n); + m = cut.n * 0.0002; cc = cut.a[cut.n-1] + 1; + if(m > 0 && m <= cut.n) cc = cut.a[cut.n-m] + 1; + if(cc < (uint64_t)p->mini_cut) p->mini_cut = cc; + } + kv_destroy(cut); + // fprintf(stderr, "[M::%s::] p->mini_cut::%d \n", __func__, p->mini_cut); + + // fprintf(stderr, "[M::%s::] ==> 2\n", __func__); + p->is_cnt = 0; p->is_ovlp = 1; + kt_for(p->n_thread, worker_for_graph_bin, p, p->ug->u.n); + // fprintf(stderr, "[M::%s::] ==> 3\n", __func__); + // exit(1); + for (i = 0; (int64_t)i < p->n_thread; i++) { + ha_ovec_destroy(p->hab[i]); + free(p->ll[i].lo.a); free(p->ll[i].srt.a.a); free(p->ll[i].tc.a); free(p->ll[i].tk.a); + } + free(p->idx_a.a); free(p->idx_n.a); free(p->hab); free(p->srt_a.a); free(p->ll); + // fprintf(stderr, "[M::%s::] ==> 4\n", __func__); + + // sysm_graph_bin(p); + for (i = 0; (int64_t)i < p->n_thread; i++) { + free(p->mk[i].idx.a); free(p->mk[i].srt.a); + } + free(p->mk); + fprintf(stderr, "[M::%s::%.3f] ==> Qualification\n", __func__, yak_realtime()-index_time); +} + +idx_emask_t* graph_ovlp_binning(ma_ug_t *ug, asg_t *sg, const ug_opt_t *uopt) +{ + ug_bin_t sl; + init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); + init_ug_bin_t(&sl, uopt, 0, GBIN_K, GBIN_W, asm_opt.max_n_chain, GBIN_E, GBIN_E, GBIN_BE, GBIN_ME, GBIN_L, + asm_opt.thread_num, 512, 3, 1, ug, sg); + cal_graph_ovlp_binning(&sl); + return sl.mm; +} + + +ma_ug_t *ul_realignment(const ug_opt_t *uopt, asg_t *sg, uint32_t double_check_cache, const char *bin_file) +{ + fprintf(stderr, "[M::%s::] ==> starting UL\n", __func__); + mg_idxopt_t opt; uldat_t sl; + int32_t cutoff; + char* gfa_name = NULL; MALLOC(gfa_name, strlen(asm_opt.output_file_name)+50); + sprintf(gfa_name, "%s.%s", asm_opt.output_file_name, bin_file); + + init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); + cutoff = REA_ALIGN_CUTOFF; + init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); + init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, NULL); + ma_ug_t *ug = gen_polished_ug(uopt, sg); + // dd_ug(sg, ug, uopt->coverage_cut, uopt->sources, uopt->ruIndex, "UL.sa"); + // debug_sl_compress_base_disk_0(&sl, asm_opt.ar); + // detect_outlier_len("ul_realignment"); + clear_all_ul_t(&UL_INF); + + ///for debug interval + if(!load_all_ul_t(&UL_INF, gfa_name, &R_INF, ug)) { + gen_UL_reovlps(&sl, ug, sg, gfa_name, cutoff, 1); + // exit(1); + write_all_ul_t(&UL_INF, gfa_name, ug); + } else{ + free(UL_INF.ridx.idx.a); free(UL_INF.ridx.occ.a); + memset(&(UL_INF.ridx), 0, sizeof((UL_INF.ridx))); + if(double_check_cache){ + if(drenew_UL_reovlps(&sl, ug, sg, gfa_name, cutoff)) { + write_all_ul_t(&UL_INF, gfa_name, ug); + } + } + } + + // print_ul_alignment(ug, &UL_INF, 147, "init-0"); + filter_ul_ug(ug); + // print_ul_alignment(ug, &UL_INF, 147, "init-1"); + gen_ul_vec_rid_t(&UL_INF, NULL, ug); + // print_ul_alignment(ug, &UL_INF, 147, "init-2"); + update_ug_arch_ul_mul(ug); + + // exit(1); + // print_ul_alignment(ug, &UL_INF, 41927, "init-3"); + // kt_for(asm_opt.thread_num, update_ug_arch_ul, ug, ug->g->n_arc); + // print_all_ul_t_stat(&UL_INF); + // kt_for(sl.n_thread, update_ovlp_src, &sl, R_INF.total_reads); + // kt_for(sl.n_thread, update_ovlp_src_bl, &sl, R_INF.total_reads); + + // print_ovlp_src_bl_stat(&UL_INF, sl.uopt); + // print_ul_ovlps(&UL_INF, 0); print_ul_ovlps(&UL_INF, 1); + + // destory_all_ul_t(&UL_INF); + free(gfa_name); + return ug; +} + + +ma_ug_t *ul_realignment_back(const ug_opt_t *uopt, asg_t *sg, uint32_t double_check_cache, const char *bin_file) +{ + fprintf(stderr, "[M::%s::] ==> starting UL\n", __func__); + mg_idxopt_t opt; uldat_t sl; + int32_t cutoff; + char* gfa_name = NULL; MALLOC(gfa_name, strlen(asm_opt.output_file_name)+50); + sprintf(gfa_name, "%s.%s", asm_opt.output_file_name, bin_file); + + init_aux_table(); ha_opt_update_cov(&asm_opt, asm_opt.hom_cov); + cutoff = REA_ALIGN_CUTOFF; + init_mg_opt(&opt, !(asm_opt.flag&HA_F_NO_HPC), 19, 10, cutoff, asm_opt.max_n_chain, asm_opt.ul_error_rate, asm_opt.ul_error_rate, asm_opt.ul_error_rate_low, asm_opt.ul_error_rate_hpc, asm_opt.ul_ec_round); + init_uldat_t(&sl, NULL, NULL, &opt, CHUNK_SIZE, asm_opt.thread_num, uopt, NULL); + ma_ug_t *ug = gen_polished_ug(uopt, sg); + // dd_ug(sg, ug, uopt->coverage_cut, uopt->sources, uopt->ruIndex, "UL.sa"); + // debug_sl_compress_base_disk_0(&sl, asm_opt.ar); + // detect_outlier_len("ul_realignment"); + clear_all_ul_t(&UL_INF); + + ///for debug interval + if(!load_all_ul_t(&UL_INF, gfa_name, &R_INF, ug)) { + gen_UL_reovlps(&sl, ug, sg, gfa_name, cutoff, 0); + // exit(1); + write_all_ul_t(&UL_INF, gfa_name, ug); + } else{ + free(UL_INF.ridx.idx.a); free(UL_INF.ridx.occ.a); + memset(&(UL_INF.ridx), 0, sizeof((UL_INF.ridx))); + if(double_check_cache){ + if(drenew_UL_reovlps(&sl, ug, sg, gfa_name, cutoff)) { + write_all_ul_t(&UL_INF, gfa_name, ug); + } + } + } + + // print_ul_alignment(ug, &UL_INF, 41927, "init-0"); + filter_ul_ug(ug); + // print_ul_alignment(ug, &UL_INF, 41927, "init-1"); + gen_ul_vec_rid_t(&UL_INF, NULL, ug); + // print_ul_alignment(ug, &UL_INF, 41927, "init-2"); + update_ug_arch_ul_mul(ug); + // print_ul_alignment(ug, &UL_INF, 41927, "init-3"); + // kt_for(asm_opt.thread_num, update_ug_arch_ul, ug, ug->g->n_arc); + // print_all_ul_t_stat(&UL_INF); + // kt_for(sl.n_thread, update_ovlp_src, &sl, R_INF.total_reads); + // kt_for(sl.n_thread, update_ovlp_src_bl, &sl, R_INF.total_reads); + + // print_ovlp_src_bl_stat(&UL_INF, sl.uopt); + // print_ul_ovlps(&UL_INF, 0); print_ul_ovlps(&UL_INF, 1); + + // destory_all_ul_t(&UL_INF); + free(gfa_name); + return ug; } \ No newline at end of file diff --git a/inter.h b/inter.h index 7813f33..5daaa1f 100644 --- a/inter.h +++ b/inter.h @@ -1,136 +1,136 @@ -#ifndef __INTER__ -#define __INTER__ -#include "Overlaps.h" -#include "Process_Read.h" -#include "hic.h" - -#define G_CHAIN_BW 16//128 -#define FLANK_M (0x7fffU) -#define P_CHAIN_COV 0.985 -#define P_FRAGEMENT_CHAIN_COV 0.20 -#define P_FRAGEMENT_PRIMARY_CHAIN_COV 0.70 -#define P_FRAGEMENT_PRIMARY_SECOND_COV 0.25 -#define P_CHAIN_SCORE 0.6 -#define G_CHAIN_GAP 0.1 -#define UG_SKIP 5 -#define RG_SKIP 25 -#define UG_SKIP_GRAPH_N 72 -#define UG_SKIP_N 100 -#define UG_ITER_N 5000 -#define UG_DIS_N 50000 -// #define UG_TRANS_W 2 -#define UG_TRANS_W 2 -// #define UG_TRANS_ERR_W 512 -#define UG_TRANS_ERR_W 64 -#define G_CHAIN_TRANS_RATE 0.25 -#define G_CHAIN_TRANS_WEIGHT -1 -#define G_CHAIN_INDEL 128 -#define W_CHN_PEN_GAP 0.1 -#define N_GCHAIN_RATE 0.04 -#define PRIMARY_UL_CHAIN_MIN 75000 - -typedef struct { - int w, k, bw, max_gap, is_HPC, hap_n, occ_weight, max_gap_pre, max_gc_seq_ext, seed; - int max_lc_skip, max_lc_iter, min_lc_cnt, min_lc_score, max_gc_skip, ref_bonus; - int min_gc_cnt, min_gc_score, sub_diff, best_n; - float chn_pen_gap, mask_level, pri_ratio; - ///base-alignment - double bw_thres, diff_ec_ul, diff_ec_ul_low, diff_ec_ul_hpc; int max_n_chain, ec_ul_round; -} mg_idxopt_t; - -struct mg_tbuf_s { - void *km; - int frag_gap; -}; -typedef struct mg_tbuf_s mg_tbuf_t; - - -mg_tbuf_t *mg_tbuf_init(void); - -void mg_tbuf_destroy(mg_tbuf_t *b); - -void *mg_tbuf_get_km(mg_tbuf_t *b); - -typedef struct { - FILE *fp; - ul_vec_t u; - uint64_t flag; -} ucr_file_t; - -typedef struct { - int32_t off, cnt; - uint32_t v; - int32_t score; -} mg_llchain_t; - -typedef struct { - int32_t id, parent; - int32_t off, cnt; - int32_t n_anchor, score; - int32_t qs, qe; - int32_t plen, ps, pe; - int32_t blen, mlen; - float div; - uint32_t hash; - int32_t subsc, n_sub; - uint32_t mapq:8, flt:1, dummy:23; -} mg_gchain_t; - -typedef struct { - size_t n,m; - uint64_t *a, tl; - kvec_t(char) cc; -} mg_dbn_t; - -typedef struct { - int32_t cnt; - uint32_t v; - int32_t score; - uint32_t qs, qe, ts, te; -} mg_lres_t; - -typedef struct { - int32_t n_gc, n_lc; - mg_gchain_t *gc;///g_chain; idx in l_chains - mg_lres_t *lc;///l_chain - uint64_t qid, qlen; -} mg_gres_t; - -typedef struct { - size_t n,m; - mg_gres_t *a; - uint64_t total_base; - uint64_t total_pair; -} mg_gres_a; - -void push_uc_block_t(const ug_opt_t *uopt, kv_ul_ov_t *z, char **seq, uint64_t *len, uint64_t b_id); -void ul_resolve(ma_ug_t *ug, const asg_t *rg, const ug_opt_t *uopt, int hap_n); -void ul_load(const ug_opt_t *uopt); -uint64_t* get_hifi2ul_list(all_ul_t *x, uint64_t hid, uint64_t* a_n); -uint64_t ul_refine_alignment(const ug_opt_t *uopt, asg_t *sg); -ma_ug_t *ul_realignment(const ug_opt_t *uopt, asg_t *sg, uint32_t double_check_cache, const char *bin_file); -int32_t write_all_ul_t(all_ul_t *x, char* file_name, ma_ug_t *ug); -int32_t load_all_ul_t(all_ul_t *x, char* file_name, All_reads *hR, ma_ug_t *ug); -uint32_t ugl_cover_check(uint64_t is, uint64_t ie, ma_utg_t *u); -void filter_ul_ug(ma_ug_t *ug); -void gen_ul_vec_rid_t(all_ul_t *x, All_reads *rdb, ma_ug_t *ug); -void update_ug_arch_ul_mul(ma_ug_t *ug); -void print_ul_alignment(ma_ug_t *ug, all_ul_t *aln, uint32_t id, const char* cmd); -void clear_all_ul_t(all_ul_t *x); -void trans_base_infer(ma_ug_t *ug, asg_t *sg, ug_opt_t *uopt, kv_u_trans_t *res, bubble_type *bub); -hpc_re_t *gen_hpc_re_t(ma_ug_t *ug); -idx_emask_t* graph_ovlp_binning(ma_ug_t *ug, asg_t *sg, const ug_opt_t *uopt); -uint32_t gen_src_shared_interval_simple(uint32_t src, ma_ug_t *ug, uint64_t *flt, uint64_t flt_n, kv_ul_ov_t *res); -uint64_t check_ul_ov_t_consist(ul_ov_t *x, ul_ov_t *y, int64_t ql, int64_t tl, double diff); -uint32_t infer_se(uint32_t qs, uint32_t qe, uint32_t ts, uint32_t te, uint32_t rev, -uint32_t rqs, uint32_t rqe, uint32_t *rts, uint32_t *rte); -uint32_t clean_contain_g(const ug_opt_t *uopt, asg_t *sg, uint32_t push_trans); -void dedup_contain_g(const ug_opt_t *uopt, asg_t *sg); -void trans_base_mmhap_infer(ma_ug_t *ug, asg_t *sg, ug_opt_t *uopt, kv_u_trans_t *res); -scaf_res_t *gen_contig_path(const ug_opt_t *uopt, asg_t *sg, ma_ug_t *ctg, ma_ug_t *ref); -void gen_contig_trans(const ug_opt_t *uopt, asg_t *sg, ma_ug_t *qry, scaf_res_t *qry_sc, ma_ug_t *ref, scaf_res_t *ref_sc, ma_ug_t *gfa, kv_u_trans_t *ta, uint32_t qoff, uint32_t toff, bubble_type *bu, kv_u_trans_t *res); -void gen_contig_self(const ug_opt_t *uopt, asg_t *sg, ma_ug_t *db, scaf_res_t *db_sc, ma_ug_t *gfa, kv_u_trans_t *ta, uint64_t soff, bubble_type *bu, kv_u_trans_t *res, uint32_t is_exact); -void order_contig_trans(kv_u_trans_t *in); -void sort_uc_block_qe(uc_block_t* a, uint64_t a_n); - -#endif +#ifndef __INTER__ +#define __INTER__ +#include "Overlaps.h" +#include "Process_Read.h" +#include "hic.h" + +#define G_CHAIN_BW 16//128 +#define FLANK_M (0x7fffU) +#define P_CHAIN_COV 0.985 +#define P_FRAGEMENT_CHAIN_COV 0.20 +#define P_FRAGEMENT_PRIMARY_CHAIN_COV 0.70 +#define P_FRAGEMENT_PRIMARY_SECOND_COV 0.25 +#define P_CHAIN_SCORE 0.6 +#define G_CHAIN_GAP 0.1 +#define UG_SKIP 5 +#define RG_SKIP 25 +#define UG_SKIP_GRAPH_N 72 +#define UG_SKIP_N 100 +#define UG_ITER_N 5000 +#define UG_DIS_N 50000 +// #define UG_TRANS_W 2 +#define UG_TRANS_W 2 +// #define UG_TRANS_ERR_W 512 +#define UG_TRANS_ERR_W 64 +#define G_CHAIN_TRANS_RATE 0.25 +#define G_CHAIN_TRANS_WEIGHT -1 +#define G_CHAIN_INDEL 128 +#define W_CHN_PEN_GAP 0.1 +#define N_GCHAIN_RATE 0.04 +#define PRIMARY_UL_CHAIN_MIN 75000 + +typedef struct { + int w, k, bw, max_gap, is_HPC, hap_n, occ_weight, max_gap_pre, max_gc_seq_ext, seed; + int max_lc_skip, max_lc_iter, min_lc_cnt, min_lc_score, max_gc_skip, ref_bonus; + int min_gc_cnt, min_gc_score, sub_diff, best_n; + float chn_pen_gap, mask_level, pri_ratio; + ///base-alignment + double bw_thres, diff_ec_ul, diff_ec_ul_low, diff_ec_ul_hpc; int max_n_chain, ec_ul_round; +} mg_idxopt_t; + +struct mg_tbuf_s { + void *km; + int frag_gap; +}; +typedef struct mg_tbuf_s mg_tbuf_t; + + +mg_tbuf_t *mg_tbuf_init(void); + +void mg_tbuf_destroy(mg_tbuf_t *b); + +void *mg_tbuf_get_km(mg_tbuf_t *b); + +typedef struct { + FILE *fp; + ul_vec_t u; + uint64_t flag; +} ucr_file_t; + +typedef struct { + int32_t off, cnt; + uint32_t v; + int32_t score; +} mg_llchain_t; + +typedef struct { + int32_t id, parent; + int32_t off, cnt; + int32_t n_anchor, score; + int32_t qs, qe; + int32_t plen, ps, pe; + int32_t blen, mlen; + float div; + uint32_t hash; + int32_t subsc, n_sub; + uint32_t mapq:8, flt:1, dummy:23; +} mg_gchain_t; + +typedef struct { + size_t n,m; + uint64_t *a, tl; + kvec_t(char) cc; +} mg_dbn_t; + +typedef struct { + int32_t cnt; + uint32_t v; + int32_t score; + uint32_t qs, qe, ts, te; +} mg_lres_t; + +typedef struct { + int32_t n_gc, n_lc; + mg_gchain_t *gc;///g_chain; idx in l_chains + mg_lres_t *lc;///l_chain + uint64_t qid, qlen; +} mg_gres_t; + +typedef struct { + size_t n,m; + mg_gres_t *a; + uint64_t total_base; + uint64_t total_pair; +} mg_gres_a; + +void push_uc_block_t(const ug_opt_t *uopt, kv_ul_ov_t *z, char **seq, uint64_t *len, uint64_t b_id); +void ul_resolve(ma_ug_t *ug, const asg_t *rg, const ug_opt_t *uopt, int hap_n); +void ul_load(const ug_opt_t *uopt); +uint64_t* get_hifi2ul_list(all_ul_t *x, uint64_t hid, uint64_t* a_n); +uint64_t ul_refine_alignment(const ug_opt_t *uopt, asg_t *sg); +ma_ug_t *ul_realignment(const ug_opt_t *uopt, asg_t *sg, uint32_t double_check_cache, const char *bin_file); +int32_t write_all_ul_t(all_ul_t *x, char* file_name, ma_ug_t *ug); +int32_t load_all_ul_t(all_ul_t *x, char* file_name, All_reads *hR, ma_ug_t *ug); +uint32_t ugl_cover_check(uint64_t is, uint64_t ie, ma_utg_t *u); +void filter_ul_ug(ma_ug_t *ug); +void gen_ul_vec_rid_t(all_ul_t *x, All_reads *rdb, ma_ug_t *ug); +void update_ug_arch_ul_mul(ma_ug_t *ug); +void print_ul_alignment(ma_ug_t *ug, all_ul_t *aln, uint32_t id, const char* cmd); +void clear_all_ul_t(all_ul_t *x); +void trans_base_infer(ma_ug_t *ug, asg_t *sg, ug_opt_t *uopt, kv_u_trans_t *res, bubble_type *bub); +hpc_re_t *gen_hpc_re_t(ma_ug_t *ug); +idx_emask_t* graph_ovlp_binning(ma_ug_t *ug, asg_t *sg, const ug_opt_t *uopt); +uint32_t gen_src_shared_interval_simple(uint32_t src, ma_ug_t *ug, uint64_t *flt, uint64_t flt_n, kv_ul_ov_t *res); +uint64_t check_ul_ov_t_consist(ul_ov_t *x, ul_ov_t *y, int64_t ql, int64_t tl, double diff); +uint32_t infer_se(uint32_t qs, uint32_t qe, uint32_t ts, uint32_t te, uint32_t rev, +uint32_t rqs, uint32_t rqe, uint32_t *rts, uint32_t *rte); +uint32_t clean_contain_g(const ug_opt_t *uopt, asg_t *sg, uint32_t push_trans); +void dedup_contain_g(const ug_opt_t *uopt, asg_t *sg); +void trans_base_mmhap_infer(ma_ug_t *ug, asg_t *sg, ug_opt_t *uopt, kv_u_trans_t *res); +scaf_res_t *gen_contig_path(const ug_opt_t *uopt, asg_t *sg, ma_ug_t *ctg, ma_ug_t *ref); +void gen_contig_trans(const ug_opt_t *uopt, asg_t *sg, ma_ug_t *qry, scaf_res_t *qry_sc, ma_ug_t *ref, scaf_res_t *ref_sc, ma_ug_t *gfa, kv_u_trans_t *ta, uint32_t qoff, uint32_t toff, bubble_type *bu, kv_u_trans_t *res); +void gen_contig_self(const ug_opt_t *uopt, asg_t *sg, ma_ug_t *db, scaf_res_t *db_sc, ma_ug_t *gfa, kv_u_trans_t *ta, uint64_t soff, bubble_type *bu, kv_u_trans_t *res, uint32_t is_exact); +void order_contig_trans(kv_u_trans_t *in); +void sort_uc_block_qe(uc_block_t* a, uint64_t a_n); + +#endif diff --git a/kalloc.cpp b/kalloc.cpp index 8499552..641b193 100644 --- a/kalloc.cpp +++ b/kalloc.cpp @@ -1,205 +1,205 @@ -#include -#include -#include -#include "kalloc.h" - -/* In kalloc, a *core* is a large chunk of contiguous memory. Each core is - * associated with a master header, which keeps the size of the current core - * and the pointer to next core. Kalloc allocates small *blocks* of memory from - * the cores and organizes free memory blocks in a circular single-linked list. - * - * In the following diagram, "@" stands for the header of a free block (of type - * header_t), "#" for the header of an allocated block (of type size_t), "-" - * for free memory, and "+" for allocated memory. - * - * master This region is core 1. master This region is core 2. - * | | - * *@-------#++++++#++++++++++++@-------- *@----------#++++++++++++#+++++++@------------ - * | | | | - * p=p->ptr->ptr->ptr->ptr p->ptr p->ptr->ptr p->ptr->ptr->ptr - */ -typedef struct header_t { - size_t size; - struct header_t *ptr; -} header_t; - -typedef struct { - void *par; - size_t min_core_size; - header_t base, *loop_head, *core_head; /* base is a zero-sized block always kept in the loop */ -} kmem_t; - -static void panic(const char *s) -{ - fprintf(stderr, "%s\n", s); - abort(); -} - -void *km_init2(void *km_par, size_t min_core_size) -{ - kmem_t *km; - km = (kmem_t*)kcalloc(km_par, 1, sizeof(kmem_t)); - km->par = km_par; - km->min_core_size = min_core_size > 0? min_core_size : 0x80000; - return (void*)km; -} - -void *km_init(void) { return km_init2(0, 0); } - -void km_destroy(void *_km) -{ - kmem_t *km = (kmem_t*)_km; - void *km_par; - header_t *p, *q; - if (km == NULL) return; - km_par = km->par; - for (p = km->core_head; p != NULL;) { - q = p->ptr; - kfree(km_par, p); - p = q; - } - kfree(km_par, km); -} - -static header_t *morecore(kmem_t *km, size_t nu) -{ - header_t *q; - size_t bytes, *p; - nu = (nu + 1 + (km->min_core_size - 1)) / km->min_core_size * km->min_core_size; /* the first +1 for core header */ - bytes = nu * sizeof(header_t); - q = (header_t*)kmalloc(km->par, bytes); - if (!q) panic("[morecore] insufficient memory"); - q->ptr = km->core_head, q->size = nu, km->core_head = q; - p = (size_t*)(q + 1); - *p = nu - 1; /* the size of the free block; -1 because the first unit is used for the core header */ - kfree(km, p + 1); /* initialize the new "core"; NB: the core header is not looped. */ - return km->loop_head; -} - -void kfree(void *_km, void *ap) /* kfree() also adds a new core to the circular list */ -{ - header_t *p, *q; - kmem_t *km = (kmem_t*)_km; - - if (!ap) return; - if (km == NULL) { - free(ap); - return; - } - p = (header_t*)((size_t*)ap - 1); - p->size = *((size_t*)ap - 1); - /* Find the pointer that points to the block to be freed. The following loop can stop on two conditions: - * - * a) "p>q && pptr": @------#++++++++#+++++++@------- @---------------#+++++++@------- - * (can also be in | | | -> | | - * two cores) q p q->ptr q q->ptr - * - * @-------- #+++++++++@-------- @-------- @------------------ - * | | | -> | | - * q p q->ptr q q->ptr - * - * b) "q>=q->ptr && (p>q || pptr)": @-------#+++++ @--------#+++++++ @-------#+++++ @---------------- - * | | | -> | | - * q->ptr q p q->ptr q - * - * #+++++++@----- #++++++++@------- @------------- #++++++++@------- - * | | | -> | | - * p q->ptr q q->ptr q - */ - for (q = km->loop_head; !(p > q && p < q->ptr); q = q->ptr) - if (q >= q->ptr && (p > q || p < q->ptr)) break; - if (p + p->size == q->ptr) { /* two adjacent blocks, merge p and q->ptr (the 2nd and 4th cases) */ - p->size += q->ptr->size; - p->ptr = q->ptr->ptr; - } else if (p + p->size > q->ptr && q->ptr >= p) { - panic("[kfree] The end of the allocated block enters a free block."); - } else p->ptr = q->ptr; /* backup q->ptr */ - - if (q + q->size == p) { /* two adjacent blocks, merge q and p (the other two cases) */ - q->size += p->size; - q->ptr = p->ptr; - km->loop_head = q; - } else if (q + q->size > p && p >= q) { - panic("[kfree] The end of a free block enters the allocated block."); - } else km->loop_head = p, q->ptr = p; /* in two cores, cannot be merged; create a new block in the list */ -} - -void *kmalloc(void *_km, size_t n_bytes) -{ - kmem_t *km = (kmem_t*)_km; - size_t n_units; - header_t *p, *q; - - if (n_bytes == 0) return 0; - if (km == NULL) return malloc(n_bytes); - n_units = (n_bytes + sizeof(size_t) + sizeof(header_t) - 1) / sizeof(header_t); /* header+n_bytes requires at least this number of units */ - - if (!(q = km->loop_head)) /* the first time when kmalloc() is called, intialize it */ - q = km->loop_head = km->base.ptr = &km->base; - for (p = q->ptr;; q = p, p = p->ptr) { /* search for a suitable block */ - if (p->size >= n_units) { /* p->size if the size of current block. This line means the current block is large enough. */ - if (p->size == n_units) q->ptr = p->ptr; /* no need to split the block */ - else { /* split the block. NB: memory is allocated at the end of the block! */ - p->size -= n_units; /* reduce the size of the free block */ - p += p->size; /* p points to the allocated block */ - *(size_t*)p = n_units; /* set the size */ - } - km->loop_head = q; /* set the end of chain */ - return (size_t*)p + 1; - } - if (p == km->loop_head) { /* then ask for more "cores" */ - if ((p = morecore(km, n_units)) == 0) return 0; - } - } -} - -void *kcalloc(void *_km, size_t count, size_t size) -{ - kmem_t *km = (kmem_t*)_km; - void *p; - if (size == 0 || count == 0) return 0; - if (km == NULL) return calloc(count, size); - p = kmalloc(km, count * size); - memset(p, 0, count * size); - return p; -} - -void *krealloc(void *_km, void *ap, size_t n_bytes) // TODO: this can be made more efficient in principle -{ - kmem_t *km = (kmem_t*)_km; - size_t cap, *p, *q; - - if (n_bytes == 0) { - kfree(km, ap); return 0; - } - if (km == NULL) return realloc(ap, n_bytes); - if (ap == NULL) return kmalloc(km, n_bytes); - p = (size_t*)ap - 1; - cap = (*p) * sizeof(header_t) - sizeof(size_t); - if (cap >= n_bytes) return ap; /* TODO: this prevents shrinking */ - q = (size_t*)kmalloc(km, n_bytes); - memcpy(q, ap, cap); - kfree(km, ap); - return q; -} - -void km_stat(const void *_km, km_stat_t *s) -{ - kmem_t *km = (kmem_t*)_km; - header_t *p; - memset(s, 0, sizeof(km_stat_t)); - if (km == NULL || km->loop_head == NULL) return; - for (p = km->loop_head;; p = p->ptr) { - s->available += p->size * sizeof(header_t); - if (p->size != 0) ++s->n_blocks; /* &kmem_t::base is always one of the cores. It is zero-sized. */ - if (p->ptr > p && p + p->size > p->ptr) - panic("[km_stat] The end of a free block enters another free block."); - if (p->ptr == km->loop_head) break; - } - for (p = km->core_head; p != NULL; p = p->ptr) { - size_t size = p->size * sizeof(header_t); - ++s->n_cores; - s->capacity += size; - s->largest = s->largest > size? s->largest : size; - } -} +#include +#include +#include +#include "kalloc.h" + +/* In kalloc, a *core* is a large chunk of contiguous memory. Each core is + * associated with a master header, which keeps the size of the current core + * and the pointer to next core. Kalloc allocates small *blocks* of memory from + * the cores and organizes free memory blocks in a circular single-linked list. + * + * In the following diagram, "@" stands for the header of a free block (of type + * header_t), "#" for the header of an allocated block (of type size_t), "-" + * for free memory, and "+" for allocated memory. + * + * master This region is core 1. master This region is core 2. + * | | + * *@-------#++++++#++++++++++++@-------- *@----------#++++++++++++#+++++++@------------ + * | | | | + * p=p->ptr->ptr->ptr->ptr p->ptr p->ptr->ptr p->ptr->ptr->ptr + */ +typedef struct header_t { + size_t size; + struct header_t *ptr; +} header_t; + +typedef struct { + void *par; + size_t min_core_size; + header_t base, *loop_head, *core_head; /* base is a zero-sized block always kept in the loop */ +} kmem_t; + +static void panic(const char *s) +{ + fprintf(stderr, "%s\n", s); + abort(); +} + +void *km_init2(void *km_par, size_t min_core_size) +{ + kmem_t *km; + km = (kmem_t*)kcalloc(km_par, 1, sizeof(kmem_t)); + km->par = km_par; + km->min_core_size = min_core_size > 0? min_core_size : 0x80000; + return (void*)km; +} + +void *km_init(void) { return km_init2(0, 0); } + +void km_destroy(void *_km) +{ + kmem_t *km = (kmem_t*)_km; + void *km_par; + header_t *p, *q; + if (km == NULL) return; + km_par = km->par; + for (p = km->core_head; p != NULL;) { + q = p->ptr; + kfree(km_par, p); + p = q; + } + kfree(km_par, km); +} + +static header_t *morecore(kmem_t *km, size_t nu) +{ + header_t *q; + size_t bytes, *p; + nu = (nu + 1 + (km->min_core_size - 1)) / km->min_core_size * km->min_core_size; /* the first +1 for core header */ + bytes = nu * sizeof(header_t); + q = (header_t*)kmalloc(km->par, bytes); + if (!q) panic("[morecore] insufficient memory"); + q->ptr = km->core_head, q->size = nu, km->core_head = q; + p = (size_t*)(q + 1); + *p = nu - 1; /* the size of the free block; -1 because the first unit is used for the core header */ + kfree(km, p + 1); /* initialize the new "core"; NB: the core header is not looped. */ + return km->loop_head; +} + +void kfree(void *_km, void *ap) /* kfree() also adds a new core to the circular list */ +{ + header_t *p, *q; + kmem_t *km = (kmem_t*)_km; + + if (!ap) return; + if (km == NULL) { + free(ap); + return; + } + p = (header_t*)((size_t*)ap - 1); + p->size = *((size_t*)ap - 1); + /* Find the pointer that points to the block to be freed. The following loop can stop on two conditions: + * + * a) "p>q && pptr": @------#++++++++#+++++++@------- @---------------#+++++++@------- + * (can also be in | | | -> | | + * two cores) q p q->ptr q q->ptr + * + * @-------- #+++++++++@-------- @-------- @------------------ + * | | | -> | | + * q p q->ptr q q->ptr + * + * b) "q>=q->ptr && (p>q || pptr)": @-------#+++++ @--------#+++++++ @-------#+++++ @---------------- + * | | | -> | | + * q->ptr q p q->ptr q + * + * #+++++++@----- #++++++++@------- @------------- #++++++++@------- + * | | | -> | | + * p q->ptr q q->ptr q + */ + for (q = km->loop_head; !(p > q && p < q->ptr); q = q->ptr) + if (q >= q->ptr && (p > q || p < q->ptr)) break; + if (p + p->size == q->ptr) { /* two adjacent blocks, merge p and q->ptr (the 2nd and 4th cases) */ + p->size += q->ptr->size; + p->ptr = q->ptr->ptr; + } else if (p + p->size > q->ptr && q->ptr >= p) { + panic("[kfree] The end of the allocated block enters a free block."); + } else p->ptr = q->ptr; /* backup q->ptr */ + + if (q + q->size == p) { /* two adjacent blocks, merge q and p (the other two cases) */ + q->size += p->size; + q->ptr = p->ptr; + km->loop_head = q; + } else if (q + q->size > p && p >= q) { + panic("[kfree] The end of a free block enters the allocated block."); + } else km->loop_head = p, q->ptr = p; /* in two cores, cannot be merged; create a new block in the list */ +} + +void *kmalloc(void *_km, size_t n_bytes) +{ + kmem_t *km = (kmem_t*)_km; + size_t n_units; + header_t *p, *q; + + if (n_bytes == 0) return 0; + if (km == NULL) return malloc(n_bytes); + n_units = (n_bytes + sizeof(size_t) + sizeof(header_t) - 1) / sizeof(header_t); /* header+n_bytes requires at least this number of units */ + + if (!(q = km->loop_head)) /* the first time when kmalloc() is called, intialize it */ + q = km->loop_head = km->base.ptr = &km->base; + for (p = q->ptr;; q = p, p = p->ptr) { /* search for a suitable block */ + if (p->size >= n_units) { /* p->size if the size of current block. This line means the current block is large enough. */ + if (p->size == n_units) q->ptr = p->ptr; /* no need to split the block */ + else { /* split the block. NB: memory is allocated at the end of the block! */ + p->size -= n_units; /* reduce the size of the free block */ + p += p->size; /* p points to the allocated block */ + *(size_t*)p = n_units; /* set the size */ + } + km->loop_head = q; /* set the end of chain */ + return (size_t*)p + 1; + } + if (p == km->loop_head) { /* then ask for more "cores" */ + if ((p = morecore(km, n_units)) == 0) return 0; + } + } +} + +void *kcalloc(void *_km, size_t count, size_t size) +{ + kmem_t *km = (kmem_t*)_km; + void *p; + if (size == 0 || count == 0) return 0; + if (km == NULL) return calloc(count, size); + p = kmalloc(km, count * size); + memset(p, 0, count * size); + return p; +} + +void *krealloc(void *_km, void *ap, size_t n_bytes) // TODO: this can be made more efficient in principle +{ + kmem_t *km = (kmem_t*)_km; + size_t cap, *p, *q; + + if (n_bytes == 0) { + kfree(km, ap); return 0; + } + if (km == NULL) return realloc(ap, n_bytes); + if (ap == NULL) return kmalloc(km, n_bytes); + p = (size_t*)ap - 1; + cap = (*p) * sizeof(header_t) - sizeof(size_t); + if (cap >= n_bytes) return ap; /* TODO: this prevents shrinking */ + q = (size_t*)kmalloc(km, n_bytes); + memcpy(q, ap, cap); + kfree(km, ap); + return q; +} + +void km_stat(const void *_km, km_stat_t *s) +{ + kmem_t *km = (kmem_t*)_km; + header_t *p; + memset(s, 0, sizeof(km_stat_t)); + if (km == NULL || km->loop_head == NULL) return; + for (p = km->loop_head;; p = p->ptr) { + s->available += p->size * sizeof(header_t); + if (p->size != 0) ++s->n_blocks; /* &kmem_t::base is always one of the cores. It is zero-sized. */ + if (p->ptr > p && p + p->size > p->ptr) + panic("[km_stat] The end of a free block enters another free block."); + if (p->ptr == km->loop_head) break; + } + for (p = km->core_head; p != NULL; p = p->ptr) { + size_t size = p->size * sizeof(header_t); + ++s->n_cores; + s->capacity += size; + s->largest = s->largest > size? s->largest : size; + } +} diff --git a/kalloc.h b/kalloc.h index b52fda2..d510aa7 100644 --- a/kalloc.h +++ b/kalloc.h @@ -1,107 +1,107 @@ -#ifndef _KALLOC_H_ -#define _KALLOC_H_ - -#include /* for size_t */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - size_t capacity, available, n_blocks, n_cores, largest; -} km_stat_t; - -void *kmalloc(void *km, size_t size); -void *krealloc(void *km, void *ptr, size_t size); -void *kcalloc(void *km, size_t count, size_t size); -void kfree(void *km, void *ptr); - -void *km_init(void); -void *km_init2(void *km_par, size_t min_core_size); -void km_destroy(void *km); -void km_stat(const void *_km, km_stat_t *s); - -#ifdef __cplusplus -} -#endif - -#define KMALLOC(km, ptr, len) ((ptr) = (__typeof__(ptr))kmalloc((km), (len) * sizeof(*(ptr)))) -#define KCALLOC(km, ptr, len) ((ptr) = (__typeof__(ptr))kcalloc((km), (len), sizeof(*(ptr)))) -#define KREALLOC(km, ptr, len) ((ptr) = (__typeof__(ptr))krealloc((km), (ptr), (len) * sizeof(*(ptr)))) - -#define KEXPAND(km, a, m) do { \ - (m) = (m) >= 4? (m) + ((m)>>1) : 16; \ - KREALLOC((km), (a), (m)); \ - } while (0) - -#define kv_resize_km(km, type, v, s) do { \ - if ((v).m < (s)) { \ - (v).m = (s); \ - kv_roundup32((v).m); \ - KREALLOC((km), (v).a, (v).m); \ - } \ - } while (0) - -#define kv_copy_km(km, type, v1, v0) do { \ - if ((v1).m < (v0).n) kv_resize_km((km), type, v1, (v0).n); \ - (v1).n = (v0).n; \ - memcpy((v1).a, (v0).a, sizeof(type) * (v0).n); \ - } while (0) \ - -#define kv_push_km(km, type, v, x) do { \ - if ((v).n == (v).m) { \ - (v).m = (v).m? (v).m<<1 : 2; \ - KREALLOC((km), (v).a, (v).m); \ - } \ - (v).a[(v).n++] = (x); \ - } while (0) - -#define kv_pushp_km(km, type, v, p) do { \ - if ((v).n == (v).m) { \ - (v).m = (v).m? (v).m<<1 : 2; \ - KREALLOC((km), (v).a, (v).m); \ - } \ - *(p) = &(v).a[(v).n++]; \ - } while (0) - -#ifndef klib_unused -#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) -#define klib_unused __attribute__ ((__unused__)) -#else -#define klib_unused -#endif -#endif /* klib_unused */ - -// adapted from klist.h -#define KALLOC_POOL_INIT2(SCOPE, name, kmptype_t) \ - typedef struct { \ - size_t cnt, n, max; \ - kmptype_t **buf; \ - void *km; \ - } kmp_##name##_t; \ - SCOPE kmp_##name##_t *kmp_init_##name(void *km) { \ - kmp_##name##_t *mp; \ - KCALLOC(km, mp, 1); \ - mp->km = km; \ - return mp; \ - } \ - SCOPE void kmp_destroy_##name(kmp_##name##_t *mp) { \ - size_t k; \ - for (k = 0; k < mp->n; ++k) kfree(mp->km, mp->buf[k]); \ - kfree(mp->km, mp->buf); kfree(mp->km, mp); \ - } \ - SCOPE kmptype_t *kmp_alloc_##name(kmp_##name##_t *mp) { \ - ++mp->cnt; \ - if (mp->n == 0) return (kmptype_t*)kcalloc(mp->km, 1, sizeof(kmptype_t)); \ - return mp->buf[--mp->n]; \ - } \ - SCOPE void kmp_free_##name(kmp_##name##_t *mp, kmptype_t *p) { \ - --mp->cnt; \ - if (mp->n == mp->max) KEXPAND(mp->km, mp->buf, mp->max); \ - mp->buf[mp->n++] = p; \ - } - -#define KALLOC_POOL_INIT(name, kmptype_t) \ - KALLOC_POOL_INIT2(static inline klib_unused, name, kmptype_t) - -#endif +#ifndef _KALLOC_H_ +#define _KALLOC_H_ + +#include /* for size_t */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + size_t capacity, available, n_blocks, n_cores, largest; +} km_stat_t; + +void *kmalloc(void *km, size_t size); +void *krealloc(void *km, void *ptr, size_t size); +void *kcalloc(void *km, size_t count, size_t size); +void kfree(void *km, void *ptr); + +void *km_init(void); +void *km_init2(void *km_par, size_t min_core_size); +void km_destroy(void *km); +void km_stat(const void *_km, km_stat_t *s); + +#ifdef __cplusplus +} +#endif + +#define KMALLOC(km, ptr, len) ((ptr) = (__typeof__(ptr))kmalloc((km), (len) * sizeof(*(ptr)))) +#define KCALLOC(km, ptr, len) ((ptr) = (__typeof__(ptr))kcalloc((km), (len), sizeof(*(ptr)))) +#define KREALLOC(km, ptr, len) ((ptr) = (__typeof__(ptr))krealloc((km), (ptr), (len) * sizeof(*(ptr)))) + +#define KEXPAND(km, a, m) do { \ + (m) = (m) >= 4? (m) + ((m)>>1) : 16; \ + KREALLOC((km), (a), (m)); \ + } while (0) + +#define kv_resize_km(km, type, v, s) do { \ + if ((v).m < (s)) { \ + (v).m = (s); \ + kv_roundup32((v).m); \ + KREALLOC((km), (v).a, (v).m); \ + } \ + } while (0) + +#define kv_copy_km(km, type, v1, v0) do { \ + if ((v1).m < (v0).n) kv_resize_km((km), type, v1, (v0).n); \ + (v1).n = (v0).n; \ + memcpy((v1).a, (v0).a, sizeof(type) * (v0).n); \ + } while (0) \ + +#define kv_push_km(km, type, v, x) do { \ + if ((v).n == (v).m) { \ + (v).m = (v).m? (v).m<<1 : 2; \ + KREALLOC((km), (v).a, (v).m); \ + } \ + (v).a[(v).n++] = (x); \ + } while (0) + +#define kv_pushp_km(km, type, v, p) do { \ + if ((v).n == (v).m) { \ + (v).m = (v).m? (v).m<<1 : 2; \ + KREALLOC((km), (v).a, (v).m); \ + } \ + *(p) = &(v).a[(v).n++]; \ + } while (0) + +#ifndef klib_unused +#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) +#define klib_unused __attribute__ ((__unused__)) +#else +#define klib_unused +#endif +#endif /* klib_unused */ + +// adapted from klist.h +#define KALLOC_POOL_INIT2(SCOPE, name, kmptype_t) \ + typedef struct { \ + size_t cnt, n, max; \ + kmptype_t **buf; \ + void *km; \ + } kmp_##name##_t; \ + SCOPE kmp_##name##_t *kmp_init_##name(void *km) { \ + kmp_##name##_t *mp; \ + KCALLOC(km, mp, 1); \ + mp->km = km; \ + return mp; \ + } \ + SCOPE void kmp_destroy_##name(kmp_##name##_t *mp) { \ + size_t k; \ + for (k = 0; k < mp->n; ++k) kfree(mp->km, mp->buf[k]); \ + kfree(mp->km, mp->buf); kfree(mp->km, mp); \ + } \ + SCOPE kmptype_t *kmp_alloc_##name(kmp_##name##_t *mp) { \ + ++mp->cnt; \ + if (mp->n == 0) return (kmptype_t*)kcalloc(mp->km, 1, sizeof(kmptype_t)); \ + return mp->buf[--mp->n]; \ + } \ + SCOPE void kmp_free_##name(kmp_##name##_t *mp, kmptype_t *p) { \ + --mp->cnt; \ + if (mp->n == mp->max) KEXPAND(mp->km, mp->buf, mp->max); \ + mp->buf[mp->n++] = p; \ + } + +#define KALLOC_POOL_INIT(name, kmptype_t) \ + KALLOC_POOL_INIT2(static inline klib_unused, name, kmptype_t) + +#endif diff --git a/kavl.h b/kavl.h index e0a8e1b..bd14d5a 100644 --- a/kavl.h +++ b/kavl.h @@ -1,414 +1,414 @@ -/* The MIT License - - Copyright (c) 2018 by Attractive Chaos - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - -/* An example: - -#include -#include -#include -#include "kavl.h" - -struct my_node { - char key; - KAVL_HEAD(struct my_node) head; -}; -#define my_cmp(p, q) (((q)->key < (p)->key) - ((p)->key < (q)->key)) -KAVL_INIT(my, struct my_node, head, my_cmp) - -int main(void) { - const char *str = "MNOLKQOPHIA"; // from wiki, except a duplicate - struct my_node *root = 0; - int i, l = strlen(str); - for (i = 0; i < l; ++i) { // insert in the input order - struct my_node *q, *p = malloc(sizeof(*p)); - p->key = str[i]; - q = kavl_insert(my, &root, p, 0); - if (p != q) free(p); // if already present, free - } - kavl_itr_t(my) itr; - kavl_itr_first(my, root, &itr); // place at first - do { // traverse - const struct my_node *p = kavl_at(&itr); - putchar(p->key); - free((void*)p); // free node - } while (kavl_itr_next(my, &itr)); - putchar('\n'); - return 0; -} -*/ - -#ifndef KAVL_H -#define KAVL_H - -#ifdef __STRICT_ANSI__ -#define inline __inline__ -#endif - -#define KAVL_MAX_DEPTH 64 - -#define kavl_size(head, p) ((p)? (p)->head.size : 0) -#define kavl_size_child(head, q, i) ((q)->head.p[(i)]? (q)->head.p[(i)]->head.size : 0) - -#define KAVL_HEAD(__type) \ - struct { \ - __type *p[2]; \ - signed char balance; /* balance factor */ \ - unsigned size; /* #elements in subtree */ \ - } - -#define __KAVL_FIND(suf, __scope, __type, __head, __cmp) \ - __scope __type *kavl_find_##suf(const __type *root, const __type *x, unsigned *cnt_) { \ - const __type *p = root; \ - unsigned cnt = 0; \ - while (p != 0) { \ - int cmp; \ - cmp = __cmp(x, p); \ - if (cmp >= 0) cnt += kavl_size_child(__head, p, 0) + 1; \ - if (cmp < 0) p = p->__head.p[0]; \ - else if (cmp > 0) p = p->__head.p[1]; \ - else break; \ - } \ - if (cnt_) *cnt_ = cnt; \ - return (__type*)p; \ - } \ - __scope __type *kavl_interval_##suf(const __type *root, const __type *x, __type **lower, __type **upper) { \ - const __type *p = root, *l = 0, *u = 0; \ - while (p != 0) { \ - int cmp; \ - cmp = __cmp(x, p); \ - if (cmp < 0) u = p, p = p->__head.p[0]; \ - else if (cmp > 0) l = p, p = p->__head.p[1]; \ - else { l = u = p; break; } \ - } \ - if (lower) *lower = (__type*)l; \ - if (upper) *upper = (__type*)u; \ - return (__type*)p; \ - } - -#define __KAVL_ROTATE(suf, __type, __head) \ - /* one rotation: (a,(b,c)q)p => ((a,b)p,c)q */ \ - static inline __type *kavl_rotate1_##suf(__type *p, int dir) { /* dir=0 to left; dir=1 to right */ \ - int opp = 1 - dir; /* opposite direction */ \ - __type *q = p->__head.p[opp]; \ - unsigned size_p = p->__head.size; \ - p->__head.size -= q->__head.size - kavl_size_child(__head, q, dir); \ - q->__head.size = size_p; \ - p->__head.p[opp] = q->__head.p[dir]; \ - q->__head.p[dir] = p; \ - return q; \ - } \ - /* two consecutive rotations: (a,((b,c)r,d)q)p => ((a,b)p,(c,d)q)r */ \ - static inline __type *kavl_rotate2_##suf(__type *p, int dir) { \ - int b1, opp = 1 - dir; \ - __type *q = p->__head.p[opp], *r = q->__head.p[dir]; \ - unsigned size_x_dir = kavl_size_child(__head, r, dir); \ - r->__head.size = p->__head.size; \ - p->__head.size -= q->__head.size - size_x_dir; \ - q->__head.size -= size_x_dir + 1; \ - p->__head.p[opp] = r->__head.p[dir]; \ - r->__head.p[dir] = p; \ - q->__head.p[dir] = r->__head.p[opp]; \ - r->__head.p[opp] = q; \ - b1 = dir == 0? +1 : -1; \ - if (r->__head.balance == b1) q->__head.balance = 0, p->__head.balance = -b1; \ - else if (r->__head.balance == 0) q->__head.balance = p->__head.balance = 0; \ - else q->__head.balance = b1, p->__head.balance = 0; \ - r->__head.balance = 0; \ - return r; \ - } - -#define __KAVL_INSERT(suf, __scope, __type, __head, __cmp) \ - __scope __type *kavl_insert_##suf(__type **root_, __type *x, unsigned *cnt_) { \ - unsigned char stack[KAVL_MAX_DEPTH]; \ - __type *path[KAVL_MAX_DEPTH]; \ - __type *bp, *bq; \ - __type *p, *q, *r = 0; /* _r_ is potentially the new root */ \ - int i, which = 0, top, b1, path_len; \ - unsigned cnt = 0; \ - bp = *root_, bq = 0; \ - /* find the insertion location */ \ - for (p = bp, q = bq, top = path_len = 0; p; q = p, p = p->__head.p[which]) { \ - int cmp; \ - cmp = __cmp(x, p); \ - if (cmp >= 0) cnt += kavl_size_child(__head, p, 0) + 1; \ - if (cmp == 0) { \ - if (cnt_) *cnt_ = cnt; \ - return p; \ - } \ - if (p->__head.balance != 0) \ - bq = q, bp = p, top = 0; \ - stack[top++] = which = (cmp > 0); \ - path[path_len++] = p; \ - } \ - if (cnt_) *cnt_ = cnt; \ - x->__head.balance = 0, x->__head.size = 1, x->__head.p[0] = x->__head.p[1] = 0; \ - if (q == 0) *root_ = x; \ - else q->__head.p[which] = x; \ - if (bp == 0) return x; \ - for (i = 0; i < path_len; ++i) ++path[i]->__head.size; \ - for (p = bp, top = 0; p != x; p = p->__head.p[stack[top]], ++top) /* update balance factors */ \ - if (stack[top] == 0) --p->__head.balance; \ - else ++p->__head.balance; \ - if (bp->__head.balance > -2 && bp->__head.balance < 2) return x; /* no re-balance needed */ \ - /* re-balance */ \ - which = (bp->__head.balance < 0); \ - b1 = which == 0? +1 : -1; \ - q = bp->__head.p[1 - which]; \ - if (q->__head.balance == b1) { \ - r = kavl_rotate1_##suf(bp, which); \ - q->__head.balance = bp->__head.balance = 0; \ - } else r = kavl_rotate2_##suf(bp, which); \ - if (bq == 0) *root_ = r; \ - else bq->__head.p[bp != bq->__head.p[0]] = r; \ - return x; \ - } - -#define __KAVL_ERASE(suf, __scope, __type, __head, __cmp) \ - __scope __type *kavl_erase_##suf(__type **root_, const __type *x, unsigned *cnt_) { \ - __type *p, *path[KAVL_MAX_DEPTH], fake; \ - unsigned char dir[KAVL_MAX_DEPTH]; \ - int i, d = 0, cmp; \ - unsigned cnt = 0; \ - fake.__head.p[0] = *root_, fake.__head.p[1] = 0; \ - if (cnt_) *cnt_ = 0; \ - if (x) { \ - for (cmp = -1, p = &fake; cmp; cmp = __cmp(x, p)) { \ - int which = (cmp > 0); \ - if (cmp > 0) cnt += kavl_size_child(__head, p, 0) + 1; \ - dir[d] = which; \ - path[d++] = p; \ - p = p->__head.p[which]; \ - if (p == 0) { \ - if (cnt_) *cnt_ = 0; \ - return 0; \ - } \ - } \ - cnt += kavl_size_child(__head, p, 0) + 1; /* because p==x is not counted */ \ - } else { \ - for (p = &fake, cnt = 1; p; p = p->__head.p[0]) \ - dir[d] = 0, path[d++] = p; \ - p = path[--d]; \ - } \ - if (cnt_) *cnt_ = cnt; \ - for (i = 1; i < d; ++i) --path[i]->__head.size; \ - if (p->__head.p[1] == 0) { /* ((1,.)2,3)4 => (1,3)4; p=2 */ \ - path[d-1]->__head.p[dir[d-1]] = p->__head.p[0]; \ - } else { \ - __type *q = p->__head.p[1]; \ - if (q->__head.p[0] == 0) { /* ((1,2)3,4)5 => ((1)2,4)5; p=3 */ \ - q->__head.p[0] = p->__head.p[0]; \ - q->__head.balance = p->__head.balance; \ - path[d-1]->__head.p[dir[d-1]] = q; \ - path[d] = q, dir[d++] = 1; \ - q->__head.size = p->__head.size - 1; \ - } else { /* ((1,((.,2)3,4)5)6,7)8 => ((1,(2,4)5)3,7)8; p=6 */ \ - __type *r; \ - int e = d++; /* backup _d_ */\ - for (;;) { \ - dir[d] = 0; \ - path[d++] = q; \ - r = q->__head.p[0]; \ - if (r->__head.p[0] == 0) break; \ - q = r; \ - } \ - r->__head.p[0] = p->__head.p[0]; \ - q->__head.p[0] = r->__head.p[1]; \ - r->__head.p[1] = p->__head.p[1]; \ - r->__head.balance = p->__head.balance; \ - path[e-1]->__head.p[dir[e-1]] = r; \ - path[e] = r, dir[e] = 1; \ - for (i = e + 1; i < d; ++i) --path[i]->__head.size; \ - r->__head.size = p->__head.size - 1; \ - } \ - } \ - while (--d > 0) { \ - __type *q = path[d]; \ - int which, other, b1 = 1, b2 = 2; \ - which = dir[d], other = 1 - which; \ - if (which) b1 = -b1, b2 = -b2; \ - q->__head.balance += b1; \ - if (q->__head.balance == b1) break; \ - else if (q->__head.balance == b2) { \ - __type *r = q->__head.p[other]; \ - if (r->__head.balance == -b1) { \ - path[d-1]->__head.p[dir[d-1]] = kavl_rotate2_##suf(q, which); \ - } else { \ - path[d-1]->__head.p[dir[d-1]] = kavl_rotate1_##suf(q, which); \ - if (r->__head.balance == 0) { \ - r->__head.balance = -b1; \ - q->__head.balance = b1; \ - break; \ - } else r->__head.balance = q->__head.balance = 0; \ - } \ - } \ - } \ - *root_ = fake.__head.p[0]; \ - return p; \ - } - -#define kavl_free(__type, __head, __root, __free) do { \ - __type *_p, *_q; \ - for (_p = __root; _p; _p = _q) { \ - if (_p->__head.p[0] == 0) { \ - _q = _p->__head.p[1]; \ - __free(_p); \ - } else { \ - _q = _p->__head.p[0]; \ - _p->__head.p[0] = _q->__head.p[1]; \ - _q->__head.p[1] = _p; \ - } \ - } \ - } while (0) - -#define __KAVL_ITR(suf, __scope, __type, __head, __cmp) \ - struct kavl_itr_##suf { \ - const __type *stack[KAVL_MAX_DEPTH], **top; \ - }; \ - __scope void kavl_itr_first_##suf(const __type *root, struct kavl_itr_##suf *itr) { \ - const __type *p; \ - for (itr->top = itr->stack - 1, p = root; p; p = p->__head.p[0]) \ - *++itr->top = p; \ - } \ - __scope int kavl_itr_find_##suf(const __type *root, const __type *x, struct kavl_itr_##suf *itr) { \ - const __type *p = root; \ - itr->top = itr->stack - 1; \ - while (p != 0) { \ - int cmp; \ - *++itr->top = p; \ - cmp = __cmp(x, p); \ - if (cmp < 0) p = p->__head.p[0]; \ - else if (cmp > 0) p = p->__head.p[1]; \ - else break; \ - } \ - return p? 1 : 0; \ - } \ - __scope int kavl_itr_next_bidir_##suf(struct kavl_itr_##suf *itr, int dir) { \ - const __type *p; \ - if (itr->top < itr->stack) return 0; \ - dir = !!dir; \ - p = (*itr->top)->__head.p[dir]; \ - if (p) { /* go down */ \ - for (; p; p = p->__head.p[!dir]) \ - *++itr->top = p; \ - return 1; \ - } else { /* go up */ \ - do { \ - p = *itr->top--; \ - } while (itr->top >= itr->stack && p == (*itr->top)->__head.p[dir]); \ - return itr->top < itr->stack? 0 : 1; \ - } \ - } \ - -/** - * Insert a node to the tree - * - * @param suf name suffix used in KAVL_INIT() - * @param proot pointer to the root of the tree (in/out: root may change) - * @param x node to insert (in) - * @param cnt number of nodes smaller than or equal to _x_; can be NULL (out) - * - * @return _x_ if not present in the tree, or the node equal to x. - */ -#define kavl_insert(suf, proot, x, cnt) kavl_insert_##suf(proot, x, cnt) - -/** - * Find a node in the tree - * - * @param suf name suffix used in KAVL_INIT() - * @param root root of the tree - * @param x node value to find (in) - * @param cnt number of nodes smaller than or equal to _x_; can be NULL (out) - * - * @return node equal to _x_ if present, or NULL if absent - */ -#define kavl_find(suf, root, x, cnt) kavl_find_##suf(root, x, cnt) -#define kavl_interval(suf, root, x, lower, upper) kavl_interval_##suf(root, x, lower, upper) - -/** - * Delete a node from the tree - * - * @param suf name suffix used in KAVL_INIT() - * @param proot pointer to the root of the tree (in/out: root may change) - * @param x node value to delete; if NULL, delete the first node (in) - * - * @return node removed from the tree if present, or NULL if absent - */ -#define kavl_erase(suf, proot, x, cnt) kavl_erase_##suf(proot, x, cnt) -#define kavl_erase_first(suf, proot) kavl_erase_##suf(proot, 0, 0) - -#define kavl_itr_t(suf) struct kavl_itr_##suf - -/** - * Place the iterator at the smallest object - * - * @param suf name suffix used in KAVL_INIT() - * @param root root of the tree - * @param itr iterator - */ -#define kavl_itr_first(suf, root, itr) kavl_itr_first_##suf(root, itr) - -/** - * Place the iterator at the object equal to or greater than the query - * - * @param suf name suffix used in KAVL_INIT() - * @param root root of the tree - * @param x query (in) - * @param itr iterator (out) - * - * @return 1 if find; 0 otherwise. kavl_at(itr) is NULL if and only if query is - * larger than all objects in the tree - */ -#define kavl_itr_find(suf, root, x, itr) kavl_itr_find_##suf(root, x, itr) - -/** - * Move to the next object in order - * - * @param itr iterator (modified) - * - * @return 1 if there is a next object; 0 otherwise - */ -#define kavl_itr_next(suf, itr) kavl_itr_next_bidir_##suf(itr, 1) -#define kavl_itr_prev(suf, itr) kavl_itr_next_bidir_##suf(itr, 0) - -/** - * Return the pointer at the iterator - * - * @param itr iterator - * - * @return pointer if present; NULL otherwise - */ -#define kavl_at(itr) ((itr)->top < (itr)->stack? 0 : *(itr)->top) - -#define KAVL_INIT2(suf, __scope, __type, __head, __cmp) \ - __KAVL_FIND(suf, __scope, __type, __head, __cmp) \ - __KAVL_ROTATE(suf, __type, __head) \ - __KAVL_INSERT(suf, __scope, __type, __head, __cmp) \ - __KAVL_ERASE(suf, __scope, __type, __head, __cmp) \ - __KAVL_ITR(suf, __scope, __type, __head, __cmp) - -#define KAVL_INIT(suf, __type, __head, __cmp) \ - KAVL_INIT2(suf,, __type, __head, __cmp) - -#endif +/* The MIT License + + Copyright (c) 2018 by Attractive Chaos + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +/* An example: + +#include +#include +#include +#include "kavl.h" + +struct my_node { + char key; + KAVL_HEAD(struct my_node) head; +}; +#define my_cmp(p, q) (((q)->key < (p)->key) - ((p)->key < (q)->key)) +KAVL_INIT(my, struct my_node, head, my_cmp) + +int main(void) { + const char *str = "MNOLKQOPHIA"; // from wiki, except a duplicate + struct my_node *root = 0; + int i, l = strlen(str); + for (i = 0; i < l; ++i) { // insert in the input order + struct my_node *q, *p = malloc(sizeof(*p)); + p->key = str[i]; + q = kavl_insert(my, &root, p, 0); + if (p != q) free(p); // if already present, free + } + kavl_itr_t(my) itr; + kavl_itr_first(my, root, &itr); // place at first + do { // traverse + const struct my_node *p = kavl_at(&itr); + putchar(p->key); + free((void*)p); // free node + } while (kavl_itr_next(my, &itr)); + putchar('\n'); + return 0; +} +*/ + +#ifndef KAVL_H +#define KAVL_H + +#ifdef __STRICT_ANSI__ +#define inline __inline__ +#endif + +#define KAVL_MAX_DEPTH 64 + +#define kavl_size(head, p) ((p)? (p)->head.size : 0) +#define kavl_size_child(head, q, i) ((q)->head.p[(i)]? (q)->head.p[(i)]->head.size : 0) + +#define KAVL_HEAD(__type) \ + struct { \ + __type *p[2]; \ + signed char balance; /* balance factor */ \ + unsigned size; /* #elements in subtree */ \ + } + +#define __KAVL_FIND(suf, __scope, __type, __head, __cmp) \ + __scope __type *kavl_find_##suf(const __type *root, const __type *x, unsigned *cnt_) { \ + const __type *p = root; \ + unsigned cnt = 0; \ + while (p != 0) { \ + int cmp; \ + cmp = __cmp(x, p); \ + if (cmp >= 0) cnt += kavl_size_child(__head, p, 0) + 1; \ + if (cmp < 0) p = p->__head.p[0]; \ + else if (cmp > 0) p = p->__head.p[1]; \ + else break; \ + } \ + if (cnt_) *cnt_ = cnt; \ + return (__type*)p; \ + } \ + __scope __type *kavl_interval_##suf(const __type *root, const __type *x, __type **lower, __type **upper) { \ + const __type *p = root, *l = 0, *u = 0; \ + while (p != 0) { \ + int cmp; \ + cmp = __cmp(x, p); \ + if (cmp < 0) u = p, p = p->__head.p[0]; \ + else if (cmp > 0) l = p, p = p->__head.p[1]; \ + else { l = u = p; break; } \ + } \ + if (lower) *lower = (__type*)l; \ + if (upper) *upper = (__type*)u; \ + return (__type*)p; \ + } + +#define __KAVL_ROTATE(suf, __type, __head) \ + /* one rotation: (a,(b,c)q)p => ((a,b)p,c)q */ \ + static inline __type *kavl_rotate1_##suf(__type *p, int dir) { /* dir=0 to left; dir=1 to right */ \ + int opp = 1 - dir; /* opposite direction */ \ + __type *q = p->__head.p[opp]; \ + unsigned size_p = p->__head.size; \ + p->__head.size -= q->__head.size - kavl_size_child(__head, q, dir); \ + q->__head.size = size_p; \ + p->__head.p[opp] = q->__head.p[dir]; \ + q->__head.p[dir] = p; \ + return q; \ + } \ + /* two consecutive rotations: (a,((b,c)r,d)q)p => ((a,b)p,(c,d)q)r */ \ + static inline __type *kavl_rotate2_##suf(__type *p, int dir) { \ + int b1, opp = 1 - dir; \ + __type *q = p->__head.p[opp], *r = q->__head.p[dir]; \ + unsigned size_x_dir = kavl_size_child(__head, r, dir); \ + r->__head.size = p->__head.size; \ + p->__head.size -= q->__head.size - size_x_dir; \ + q->__head.size -= size_x_dir + 1; \ + p->__head.p[opp] = r->__head.p[dir]; \ + r->__head.p[dir] = p; \ + q->__head.p[dir] = r->__head.p[opp]; \ + r->__head.p[opp] = q; \ + b1 = dir == 0? +1 : -1; \ + if (r->__head.balance == b1) q->__head.balance = 0, p->__head.balance = -b1; \ + else if (r->__head.balance == 0) q->__head.balance = p->__head.balance = 0; \ + else q->__head.balance = b1, p->__head.balance = 0; \ + r->__head.balance = 0; \ + return r; \ + } + +#define __KAVL_INSERT(suf, __scope, __type, __head, __cmp) \ + __scope __type *kavl_insert_##suf(__type **root_, __type *x, unsigned *cnt_) { \ + unsigned char stack[KAVL_MAX_DEPTH]; \ + __type *path[KAVL_MAX_DEPTH]; \ + __type *bp, *bq; \ + __type *p, *q, *r = 0; /* _r_ is potentially the new root */ \ + int i, which = 0, top, b1, path_len; \ + unsigned cnt = 0; \ + bp = *root_, bq = 0; \ + /* find the insertion location */ \ + for (p = bp, q = bq, top = path_len = 0; p; q = p, p = p->__head.p[which]) { \ + int cmp; \ + cmp = __cmp(x, p); \ + if (cmp >= 0) cnt += kavl_size_child(__head, p, 0) + 1; \ + if (cmp == 0) { \ + if (cnt_) *cnt_ = cnt; \ + return p; \ + } \ + if (p->__head.balance != 0) \ + bq = q, bp = p, top = 0; \ + stack[top++] = which = (cmp > 0); \ + path[path_len++] = p; \ + } \ + if (cnt_) *cnt_ = cnt; \ + x->__head.balance = 0, x->__head.size = 1, x->__head.p[0] = x->__head.p[1] = 0; \ + if (q == 0) *root_ = x; \ + else q->__head.p[which] = x; \ + if (bp == 0) return x; \ + for (i = 0; i < path_len; ++i) ++path[i]->__head.size; \ + for (p = bp, top = 0; p != x; p = p->__head.p[stack[top]], ++top) /* update balance factors */ \ + if (stack[top] == 0) --p->__head.balance; \ + else ++p->__head.balance; \ + if (bp->__head.balance > -2 && bp->__head.balance < 2) return x; /* no re-balance needed */ \ + /* re-balance */ \ + which = (bp->__head.balance < 0); \ + b1 = which == 0? +1 : -1; \ + q = bp->__head.p[1 - which]; \ + if (q->__head.balance == b1) { \ + r = kavl_rotate1_##suf(bp, which); \ + q->__head.balance = bp->__head.balance = 0; \ + } else r = kavl_rotate2_##suf(bp, which); \ + if (bq == 0) *root_ = r; \ + else bq->__head.p[bp != bq->__head.p[0]] = r; \ + return x; \ + } + +#define __KAVL_ERASE(suf, __scope, __type, __head, __cmp) \ + __scope __type *kavl_erase_##suf(__type **root_, const __type *x, unsigned *cnt_) { \ + __type *p, *path[KAVL_MAX_DEPTH], fake; \ + unsigned char dir[KAVL_MAX_DEPTH]; \ + int i, d = 0, cmp; \ + unsigned cnt = 0; \ + fake.__head.p[0] = *root_, fake.__head.p[1] = 0; \ + if (cnt_) *cnt_ = 0; \ + if (x) { \ + for (cmp = -1, p = &fake; cmp; cmp = __cmp(x, p)) { \ + int which = (cmp > 0); \ + if (cmp > 0) cnt += kavl_size_child(__head, p, 0) + 1; \ + dir[d] = which; \ + path[d++] = p; \ + p = p->__head.p[which]; \ + if (p == 0) { \ + if (cnt_) *cnt_ = 0; \ + return 0; \ + } \ + } \ + cnt += kavl_size_child(__head, p, 0) + 1; /* because p==x is not counted */ \ + } else { \ + for (p = &fake, cnt = 1; p; p = p->__head.p[0]) \ + dir[d] = 0, path[d++] = p; \ + p = path[--d]; \ + } \ + if (cnt_) *cnt_ = cnt; \ + for (i = 1; i < d; ++i) --path[i]->__head.size; \ + if (p->__head.p[1] == 0) { /* ((1,.)2,3)4 => (1,3)4; p=2 */ \ + path[d-1]->__head.p[dir[d-1]] = p->__head.p[0]; \ + } else { \ + __type *q = p->__head.p[1]; \ + if (q->__head.p[0] == 0) { /* ((1,2)3,4)5 => ((1)2,4)5; p=3 */ \ + q->__head.p[0] = p->__head.p[0]; \ + q->__head.balance = p->__head.balance; \ + path[d-1]->__head.p[dir[d-1]] = q; \ + path[d] = q, dir[d++] = 1; \ + q->__head.size = p->__head.size - 1; \ + } else { /* ((1,((.,2)3,4)5)6,7)8 => ((1,(2,4)5)3,7)8; p=6 */ \ + __type *r; \ + int e = d++; /* backup _d_ */\ + for (;;) { \ + dir[d] = 0; \ + path[d++] = q; \ + r = q->__head.p[0]; \ + if (r->__head.p[0] == 0) break; \ + q = r; \ + } \ + r->__head.p[0] = p->__head.p[0]; \ + q->__head.p[0] = r->__head.p[1]; \ + r->__head.p[1] = p->__head.p[1]; \ + r->__head.balance = p->__head.balance; \ + path[e-1]->__head.p[dir[e-1]] = r; \ + path[e] = r, dir[e] = 1; \ + for (i = e + 1; i < d; ++i) --path[i]->__head.size; \ + r->__head.size = p->__head.size - 1; \ + } \ + } \ + while (--d > 0) { \ + __type *q = path[d]; \ + int which, other, b1 = 1, b2 = 2; \ + which = dir[d], other = 1 - which; \ + if (which) b1 = -b1, b2 = -b2; \ + q->__head.balance += b1; \ + if (q->__head.balance == b1) break; \ + else if (q->__head.balance == b2) { \ + __type *r = q->__head.p[other]; \ + if (r->__head.balance == -b1) { \ + path[d-1]->__head.p[dir[d-1]] = kavl_rotate2_##suf(q, which); \ + } else { \ + path[d-1]->__head.p[dir[d-1]] = kavl_rotate1_##suf(q, which); \ + if (r->__head.balance == 0) { \ + r->__head.balance = -b1; \ + q->__head.balance = b1; \ + break; \ + } else r->__head.balance = q->__head.balance = 0; \ + } \ + } \ + } \ + *root_ = fake.__head.p[0]; \ + return p; \ + } + +#define kavl_free(__type, __head, __root, __free) do { \ + __type *_p, *_q; \ + for (_p = __root; _p; _p = _q) { \ + if (_p->__head.p[0] == 0) { \ + _q = _p->__head.p[1]; \ + __free(_p); \ + } else { \ + _q = _p->__head.p[0]; \ + _p->__head.p[0] = _q->__head.p[1]; \ + _q->__head.p[1] = _p; \ + } \ + } \ + } while (0) + +#define __KAVL_ITR(suf, __scope, __type, __head, __cmp) \ + struct kavl_itr_##suf { \ + const __type *stack[KAVL_MAX_DEPTH], **top; \ + }; \ + __scope void kavl_itr_first_##suf(const __type *root, struct kavl_itr_##suf *itr) { \ + const __type *p; \ + for (itr->top = itr->stack - 1, p = root; p; p = p->__head.p[0]) \ + *++itr->top = p; \ + } \ + __scope int kavl_itr_find_##suf(const __type *root, const __type *x, struct kavl_itr_##suf *itr) { \ + const __type *p = root; \ + itr->top = itr->stack - 1; \ + while (p != 0) { \ + int cmp; \ + *++itr->top = p; \ + cmp = __cmp(x, p); \ + if (cmp < 0) p = p->__head.p[0]; \ + else if (cmp > 0) p = p->__head.p[1]; \ + else break; \ + } \ + return p? 1 : 0; \ + } \ + __scope int kavl_itr_next_bidir_##suf(struct kavl_itr_##suf *itr, int dir) { \ + const __type *p; \ + if (itr->top < itr->stack) return 0; \ + dir = !!dir; \ + p = (*itr->top)->__head.p[dir]; \ + if (p) { /* go down */ \ + for (; p; p = p->__head.p[!dir]) \ + *++itr->top = p; \ + return 1; \ + } else { /* go up */ \ + do { \ + p = *itr->top--; \ + } while (itr->top >= itr->stack && p == (*itr->top)->__head.p[dir]); \ + return itr->top < itr->stack? 0 : 1; \ + } \ + } \ + +/** + * Insert a node to the tree + * + * @param suf name suffix used in KAVL_INIT() + * @param proot pointer to the root of the tree (in/out: root may change) + * @param x node to insert (in) + * @param cnt number of nodes smaller than or equal to _x_; can be NULL (out) + * + * @return _x_ if not present in the tree, or the node equal to x. + */ +#define kavl_insert(suf, proot, x, cnt) kavl_insert_##suf(proot, x, cnt) + +/** + * Find a node in the tree + * + * @param suf name suffix used in KAVL_INIT() + * @param root root of the tree + * @param x node value to find (in) + * @param cnt number of nodes smaller than or equal to _x_; can be NULL (out) + * + * @return node equal to _x_ if present, or NULL if absent + */ +#define kavl_find(suf, root, x, cnt) kavl_find_##suf(root, x, cnt) +#define kavl_interval(suf, root, x, lower, upper) kavl_interval_##suf(root, x, lower, upper) + +/** + * Delete a node from the tree + * + * @param suf name suffix used in KAVL_INIT() + * @param proot pointer to the root of the tree (in/out: root may change) + * @param x node value to delete; if NULL, delete the first node (in) + * + * @return node removed from the tree if present, or NULL if absent + */ +#define kavl_erase(suf, proot, x, cnt) kavl_erase_##suf(proot, x, cnt) +#define kavl_erase_first(suf, proot) kavl_erase_##suf(proot, 0, 0) + +#define kavl_itr_t(suf) struct kavl_itr_##suf + +/** + * Place the iterator at the smallest object + * + * @param suf name suffix used in KAVL_INIT() + * @param root root of the tree + * @param itr iterator + */ +#define kavl_itr_first(suf, root, itr) kavl_itr_first_##suf(root, itr) + +/** + * Place the iterator at the object equal to or greater than the query + * + * @param suf name suffix used in KAVL_INIT() + * @param root root of the tree + * @param x query (in) + * @param itr iterator (out) + * + * @return 1 if find; 0 otherwise. kavl_at(itr) is NULL if and only if query is + * larger than all objects in the tree + */ +#define kavl_itr_find(suf, root, x, itr) kavl_itr_find_##suf(root, x, itr) + +/** + * Move to the next object in order + * + * @param itr iterator (modified) + * + * @return 1 if there is a next object; 0 otherwise + */ +#define kavl_itr_next(suf, itr) kavl_itr_next_bidir_##suf(itr, 1) +#define kavl_itr_prev(suf, itr) kavl_itr_next_bidir_##suf(itr, 0) + +/** + * Return the pointer at the iterator + * + * @param itr iterator + * + * @return pointer if present; NULL otherwise + */ +#define kavl_at(itr) ((itr)->top < (itr)->stack? 0 : *(itr)->top) + +#define KAVL_INIT2(suf, __scope, __type, __head, __cmp) \ + __KAVL_FIND(suf, __scope, __type, __head, __cmp) \ + __KAVL_ROTATE(suf, __type, __head) \ + __KAVL_INSERT(suf, __scope, __type, __head, __cmp) \ + __KAVL_ERASE(suf, __scope, __type, __head, __cmp) \ + __KAVL_ITR(suf, __scope, __type, __head, __cmp) + +#define KAVL_INIT(suf, __type, __head, __cmp) \ + KAVL_INIT2(suf,, __type, __head, __cmp) + +#endif diff --git a/kdq.h b/kdq.h index edd55b5..3836048 100644 --- a/kdq.h +++ b/kdq.h @@ -1,128 +1,128 @@ -#ifndef __AC_KDQ_H -#define __AC_KDQ_H - -#include -#include - -#define __KDQ_TYPE(type) \ - typedef struct { \ - size_t front:58, bits:6, count, mask; \ - type *a; \ - } kdq_##type##_t; - -#define kdq_t(type) kdq_##type##_t -#define kdq_size(q) ((q)->count) -#define kdq_first(q) ((q)->a[(q)->front]) -#define kdq_last(q) ((q)->a[((q)->front + (q)->count - 1) & (q)->mask]) -#define kdq_at(q, i) ((q)->a[((q)->front + (i)) & (q)->mask]) - -#define __KDQ_IMPL(type, SCOPE) \ - SCOPE kdq_##type##_t *kdq_init_##type() \ - { \ - kdq_##type##_t *q; \ - q = (kdq_##type##_t*)calloc(1, sizeof(kdq_##type##_t)); \ - q->bits = 2, q->mask = (1ULL<bits) - 1; \ - q->a = (type*)malloc((1<bits) * sizeof(type)); \ - return q; \ - } \ - SCOPE void kdq_destroy_##type(kdq_##type##_t *q) \ - { \ - if (q == 0) return; \ - free(q->a); free(q); \ - } \ - SCOPE int kdq_resize_##type(kdq_##type##_t *q, int new_bits) \ - { \ - size_t new_size = 1ULL<bits; \ - if (new_size < q->count) { /* not big enough */ \ - int i; \ - for (i = 0; i < 64; ++i) \ - if (1ULL< q->count) break; \ - new_bits = i, new_size = 1ULL<bits) return q->bits; /* unchanged */ \ - if (new_bits > q->bits) q->a = (type*)realloc(q->a, (1ULL<front + q->count <= old_size) { /* unwrapped */ \ - if (q->front + q->count > new_size) /* only happens for shrinking */ \ - memmove(q->a, q->a + new_size, (q->front + q->count - new_size) * sizeof(type)); \ - } else { /* wrapped */ \ - memmove(q->a + (new_size - (old_size - q->front)), q->a + q->front, (old_size - q->front) * sizeof(type)); \ - q->front = new_size - (old_size - q->front); \ - } \ - q->bits = new_bits, q->mask = (1ULL<bits) - 1; \ - if (new_bits < q->bits) q->a = (type*)realloc(q->a, (1ULL<bits; \ - } \ - SCOPE type *kdq_pushp_##type(kdq_##type##_t *q) \ - { \ - if (q->count == 1ULL<bits) kdq_resize_##type(q, q->bits + 1); \ - return &q->a[((q->count++) + q->front) & (q)->mask]; \ - } \ - SCOPE void kdq_push_##type(kdq_##type##_t *q, type v) \ - { \ - if (q->count == 1ULL<bits) kdq_resize_##type(q, q->bits + 1); \ - q->a[((q->count++) + q->front) & (q)->mask] = v; \ - } \ - SCOPE type *kdq_unshiftp_##type(kdq_##type##_t *q) \ - { \ - if (q->count == 1ULL<bits) kdq_resize_##type(q, q->bits + 1); \ - ++q->count; \ - q->front = q->front? q->front - 1 : (1ULL<bits) - 1; \ - return &q->a[q->front]; \ - } \ - SCOPE void kdq_unshift_##type(kdq_##type##_t *q, type v) \ - { \ - type *p; \ - p = kdq_unshiftp_##type(q); \ - *p = v; \ - } \ - SCOPE type *kdq_pop_##type(kdq_##type##_t *q) \ - { \ - return q->count? &q->a[((--q->count) + q->front) & q->mask] : 0; \ - } \ - SCOPE type *kdq_shift_##type(kdq_##type##_t *q) \ - { \ - type *d = 0; \ - if (q->count == 0) return 0; \ - d = &q->a[q->front++]; \ - q->front &= q->mask; \ - --q->count; \ - return d; \ - } - -#define KDQ_INIT2(type, SCOPE) \ - __KDQ_TYPE(type) \ - __KDQ_IMPL(type, SCOPE) - -#ifndef klib_unused -#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) -#define klib_unused __attribute__ ((__unused__)) -#else -#define klib_unused -#endif -#endif /* klib_unused */ - -#define KDQ_INIT(type) KDQ_INIT2(type, static inline klib_unused) - -#define KDQ_DECLARE(type) \ - __KDQ_TYPE(type) \ - kdq_##type##_t *kdq_init_##type(); \ - void kdq_destroy_##type(kdq_##type##_t *q); \ - int kdq_resize_##type(kdq_##type##_t *q, int new_bits); \ - type *kdq_pushp_##type(kdq_##type##_t *q); \ - void kdq_push_##type(kdq_##type##_t *q, type v); \ - type *kdq_unshiftp_##type(kdq_##type##_t *q); \ - void kdq_unshift_##type(kdq_##type##_t *q, type v); \ - type *kdq_pop_##type(kdq_##type##_t *q); \ - type *kdq_shift_##type(kdq_##type##_t *q); - -#define kdq_init(type) kdq_init_##type() -#define kdq_destroy(type, q) kdq_destroy_##type(q) -#define kdq_resize(type, q, new_bits) kdq_resize_##type(q, new_bits) -#define kdq_pushp(type, q) kdq_pushp_##type(q) -#define kdq_push(type, q, v) kdq_push_##type(q, v) -#define kdq_pop(type, q) kdq_pop_##type(q) -#define kdq_unshiftp(type, q) kdq_unshiftp_##type(q) -#define kdq_unshift(type, q, v) kdq_unshift_##type(q, v) -#define kdq_shift(type, q) kdq_shift_##type(q) - -#endif +#ifndef __AC_KDQ_H +#define __AC_KDQ_H + +#include +#include + +#define __KDQ_TYPE(type) \ + typedef struct { \ + size_t front:58, bits:6, count, mask; \ + type *a; \ + } kdq_##type##_t; + +#define kdq_t(type) kdq_##type##_t +#define kdq_size(q) ((q)->count) +#define kdq_first(q) ((q)->a[(q)->front]) +#define kdq_last(q) ((q)->a[((q)->front + (q)->count - 1) & (q)->mask]) +#define kdq_at(q, i) ((q)->a[((q)->front + (i)) & (q)->mask]) + +#define __KDQ_IMPL(type, SCOPE) \ + SCOPE kdq_##type##_t *kdq_init_##type() \ + { \ + kdq_##type##_t *q; \ + q = (kdq_##type##_t*)calloc(1, sizeof(kdq_##type##_t)); \ + q->bits = 2, q->mask = (1ULL<bits) - 1; \ + q->a = (type*)malloc((1<bits) * sizeof(type)); \ + return q; \ + } \ + SCOPE void kdq_destroy_##type(kdq_##type##_t *q) \ + { \ + if (q == 0) return; \ + free(q->a); free(q); \ + } \ + SCOPE int kdq_resize_##type(kdq_##type##_t *q, int new_bits) \ + { \ + size_t new_size = 1ULL<bits; \ + if (new_size < q->count) { /* not big enough */ \ + int i; \ + for (i = 0; i < 64; ++i) \ + if (1ULL< q->count) break; \ + new_bits = i, new_size = 1ULL<bits) return q->bits; /* unchanged */ \ + if (new_bits > q->bits) q->a = (type*)realloc(q->a, (1ULL<front + q->count <= old_size) { /* unwrapped */ \ + if (q->front + q->count > new_size) /* only happens for shrinking */ \ + memmove(q->a, q->a + new_size, (q->front + q->count - new_size) * sizeof(type)); \ + } else { /* wrapped */ \ + memmove(q->a + (new_size - (old_size - q->front)), q->a + q->front, (old_size - q->front) * sizeof(type)); \ + q->front = new_size - (old_size - q->front); \ + } \ + q->bits = new_bits, q->mask = (1ULL<bits) - 1; \ + if (new_bits < q->bits) q->a = (type*)realloc(q->a, (1ULL<bits; \ + } \ + SCOPE type *kdq_pushp_##type(kdq_##type##_t *q) \ + { \ + if (q->count == 1ULL<bits) kdq_resize_##type(q, q->bits + 1); \ + return &q->a[((q->count++) + q->front) & (q)->mask]; \ + } \ + SCOPE void kdq_push_##type(kdq_##type##_t *q, type v) \ + { \ + if (q->count == 1ULL<bits) kdq_resize_##type(q, q->bits + 1); \ + q->a[((q->count++) + q->front) & (q)->mask] = v; \ + } \ + SCOPE type *kdq_unshiftp_##type(kdq_##type##_t *q) \ + { \ + if (q->count == 1ULL<bits) kdq_resize_##type(q, q->bits + 1); \ + ++q->count; \ + q->front = q->front? q->front - 1 : (1ULL<bits) - 1; \ + return &q->a[q->front]; \ + } \ + SCOPE void kdq_unshift_##type(kdq_##type##_t *q, type v) \ + { \ + type *p; \ + p = kdq_unshiftp_##type(q); \ + *p = v; \ + } \ + SCOPE type *kdq_pop_##type(kdq_##type##_t *q) \ + { \ + return q->count? &q->a[((--q->count) + q->front) & q->mask] : 0; \ + } \ + SCOPE type *kdq_shift_##type(kdq_##type##_t *q) \ + { \ + type *d = 0; \ + if (q->count == 0) return 0; \ + d = &q->a[q->front++]; \ + q->front &= q->mask; \ + --q->count; \ + return d; \ + } + +#define KDQ_INIT2(type, SCOPE) \ + __KDQ_TYPE(type) \ + __KDQ_IMPL(type, SCOPE) + +#ifndef klib_unused +#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) +#define klib_unused __attribute__ ((__unused__)) +#else +#define klib_unused +#endif +#endif /* klib_unused */ + +#define KDQ_INIT(type) KDQ_INIT2(type, static inline klib_unused) + +#define KDQ_DECLARE(type) \ + __KDQ_TYPE(type) \ + kdq_##type##_t *kdq_init_##type(); \ + void kdq_destroy_##type(kdq_##type##_t *q); \ + int kdq_resize_##type(kdq_##type##_t *q, int new_bits); \ + type *kdq_pushp_##type(kdq_##type##_t *q); \ + void kdq_push_##type(kdq_##type##_t *q, type v); \ + type *kdq_unshiftp_##type(kdq_##type##_t *q); \ + void kdq_unshift_##type(kdq_##type##_t *q, type v); \ + type *kdq_pop_##type(kdq_##type##_t *q); \ + type *kdq_shift_##type(kdq_##type##_t *q); + +#define kdq_init(type) kdq_init_##type() +#define kdq_destroy(type, q) kdq_destroy_##type(q) +#define kdq_resize(type, q, new_bits) kdq_resize_##type(q, new_bits) +#define kdq_pushp(type, q) kdq_pushp_##type(q) +#define kdq_push(type, q, v) kdq_push_##type(q, v) +#define kdq_pop(type, q) kdq_pop_##type(q) +#define kdq_unshiftp(type, q) kdq_unshiftp_##type(q) +#define kdq_unshift(type, q, v) kdq_unshift_##type(q, v) +#define kdq_shift(type, q) kdq_shift_##type(q) + +#endif diff --git a/ketopt.h b/ketopt.h index 827256f..61cf73a 100644 --- a/ketopt.h +++ b/ketopt.h @@ -1,120 +1,120 @@ -#ifndef KETOPT_H -#define KETOPT_H - -#include /* for strchr() and strncmp() */ - -#define ko_no_argument 0 -#define ko_required_argument 1 -#define ko_optional_argument 2 - -typedef struct { - int ind; /* equivalent to optind */ - int opt; /* equivalent to optopt */ - char *arg; /* equivalent to optarg */ - int longidx; /* index of a long option; or -1 if short */ - /* private variables not intended for external uses */ - int i, pos, n_args; -} ketopt_t; - -typedef struct { - const char *name; - int has_arg; - int val; -} ko_longopt_t; - -static ketopt_t KETOPT_INIT = { 1, 0, 0, -1, 1, 0, 0 }; - -static void ketopt_permute(char *argv[], int j, int n) /* move argv[j] over n elements to the left */ -{ - int k; - char *p = argv[j]; - for (k = 0; k < n; ++k) - argv[j - k] = argv[j - k - 1]; - argv[j - k] = p; -} - -/** - * Parse command-line options and arguments - * - * This fuction has a similar interface to GNU's getopt_long(). Each call - * parses one option and returns the option name. s->arg points to the option - * argument if present. The function returns -1 when all command-line arguments - * are parsed. In this case, s->ind is the index of the first non-option - * argument. - * - * @param s status; shall be initialized to KETOPT_INIT on the first call - * @param argc length of argv[] - * @param argv list of command-line arguments; argv[0] is ignored - * @param permute non-zero to move options ahead of non-option arguments - * @param ostr option string - * @param longopts long options - * - * @return ASCII for a short option; ko_longopt_t::val for a long option; -1 if - * argv[] is fully processed; '?' for an unknown option or an ambiguous - * long option; ':' if an option argument is missing - */ -static int ketopt(ketopt_t *s, int argc, char *argv[], int permute, const char *ostr, const ko_longopt_t *longopts) -{ - int opt = -1, i0, j; - if (permute) { - while (s->i < argc && (argv[s->i][0] != '-' || argv[s->i][1] == '\0')) - ++s->i, ++s->n_args; - } - s->arg = 0, s->longidx = -1, i0 = s->i; - if (s->i >= argc || argv[s->i][0] != '-' || argv[s->i][1] == '\0') { - s->ind = s->i - s->n_args; - return -1; - } - if (argv[s->i][0] == '-' && argv[s->i][1] == '-') { /* "--" or a long option */ - if (argv[s->i][2] == '\0') { /* a bare "--" */ - ketopt_permute(argv, s->i, s->n_args); - ++s->i, s->ind = s->i - s->n_args; - return -1; - } - s->opt = 0, opt = '?', s->pos = -1; - if (longopts) { /* parse long options */ - int k, n_exact = 0, n_partial = 0; - const ko_longopt_t *o = 0, *o_exact = 0, *o_partial = 0; - for (j = 2; argv[s->i][j] != '\0' && argv[s->i][j] != '='; ++j) {} /* find the end of the option name */ - for (k = 0; longopts[k].name != 0; ++k) - if (strncmp(&argv[s->i][2], longopts[k].name, j - 2) == 0) { - if (longopts[k].name[j - 2] == 0) ++n_exact, o_exact = &longopts[k]; - else ++n_partial, o_partial = &longopts[k]; - } - if (n_exact > 1 || (n_exact == 0 && n_partial > 1)) return '?'; - o = n_exact == 1? o_exact : n_partial == 1? o_partial : 0; - if (o) { - s->opt = opt = o->val, s->longidx = o - longopts; - if (argv[s->i][j] == '=') s->arg = &argv[s->i][j + 1]; - if (o->has_arg == 1 && argv[s->i][j] == '\0') { - if (s->i < argc - 1) s->arg = argv[++s->i]; - else opt = ':'; /* missing option argument */ - } - } - } - } else { /* a short option */ - const char *p; - if (s->pos == 0) s->pos = 1; - opt = s->opt = argv[s->i][s->pos++]; - p = strchr((char*)ostr, opt); - if (p == 0) { - opt = '?'; /* unknown option */ - } else if (p[1] == ':') { - if (argv[s->i][s->pos] == 0) { - if (s->i < argc - 1) s->arg = argv[++s->i]; - else opt = ':'; /* missing option argument */ - } else s->arg = &argv[s->i][s->pos]; - s->pos = -1; - } - } - if (s->pos < 0 || argv[s->i][s->pos] == 0) { - ++s->i, s->pos = 0; - if (s->n_args > 0) /* permute */ - for (j = i0; j < s->i; ++j) - ketopt_permute(argv, j, s->n_args); - } - s->ind = s->i - s->n_args; - return opt; -} - -#endif +#ifndef KETOPT_H +#define KETOPT_H + +#include /* for strchr() and strncmp() */ + +#define ko_no_argument 0 +#define ko_required_argument 1 +#define ko_optional_argument 2 + +typedef struct { + int ind; /* equivalent to optind */ + int opt; /* equivalent to optopt */ + char *arg; /* equivalent to optarg */ + int longidx; /* index of a long option; or -1 if short */ + /* private variables not intended for external uses */ + int i, pos, n_args; +} ketopt_t; + +typedef struct { + const char *name; + int has_arg; + int val; +} ko_longopt_t; + +static ketopt_t KETOPT_INIT = { 1, 0, 0, -1, 1, 0, 0 }; + +static void ketopt_permute(char *argv[], int j, int n) /* move argv[j] over n elements to the left */ +{ + int k; + char *p = argv[j]; + for (k = 0; k < n; ++k) + argv[j - k] = argv[j - k - 1]; + argv[j - k] = p; +} + +/** + * Parse command-line options and arguments + * + * This fuction has a similar interface to GNU's getopt_long(). Each call + * parses one option and returns the option name. s->arg points to the option + * argument if present. The function returns -1 when all command-line arguments + * are parsed. In this case, s->ind is the index of the first non-option + * argument. + * + * @param s status; shall be initialized to KETOPT_INIT on the first call + * @param argc length of argv[] + * @param argv list of command-line arguments; argv[0] is ignored + * @param permute non-zero to move options ahead of non-option arguments + * @param ostr option string + * @param longopts long options + * + * @return ASCII for a short option; ko_longopt_t::val for a long option; -1 if + * argv[] is fully processed; '?' for an unknown option or an ambiguous + * long option; ':' if an option argument is missing + */ +static int ketopt(ketopt_t *s, int argc, char *argv[], int permute, const char *ostr, const ko_longopt_t *longopts) +{ + int opt = -1, i0, j; + if (permute) { + while (s->i < argc && (argv[s->i][0] != '-' || argv[s->i][1] == '\0')) + ++s->i, ++s->n_args; + } + s->arg = 0, s->longidx = -1, i0 = s->i; + if (s->i >= argc || argv[s->i][0] != '-' || argv[s->i][1] == '\0') { + s->ind = s->i - s->n_args; + return -1; + } + if (argv[s->i][0] == '-' && argv[s->i][1] == '-') { /* "--" or a long option */ + if (argv[s->i][2] == '\0') { /* a bare "--" */ + ketopt_permute(argv, s->i, s->n_args); + ++s->i, s->ind = s->i - s->n_args; + return -1; + } + s->opt = 0, opt = '?', s->pos = -1; + if (longopts) { /* parse long options */ + int k, n_exact = 0, n_partial = 0; + const ko_longopt_t *o = 0, *o_exact = 0, *o_partial = 0; + for (j = 2; argv[s->i][j] != '\0' && argv[s->i][j] != '='; ++j) {} /* find the end of the option name */ + for (k = 0; longopts[k].name != 0; ++k) + if (strncmp(&argv[s->i][2], longopts[k].name, j - 2) == 0) { + if (longopts[k].name[j - 2] == 0) ++n_exact, o_exact = &longopts[k]; + else ++n_partial, o_partial = &longopts[k]; + } + if (n_exact > 1 || (n_exact == 0 && n_partial > 1)) return '?'; + o = n_exact == 1? o_exact : n_partial == 1? o_partial : 0; + if (o) { + s->opt = opt = o->val, s->longidx = o - longopts; + if (argv[s->i][j] == '=') s->arg = &argv[s->i][j + 1]; + if (o->has_arg == 1 && argv[s->i][j] == '\0') { + if (s->i < argc - 1) s->arg = argv[++s->i]; + else opt = ':'; /* missing option argument */ + } + } + } + } else { /* a short option */ + const char *p; + if (s->pos == 0) s->pos = 1; + opt = s->opt = argv[s->i][s->pos++]; + p = strchr((char*)ostr, opt); + if (p == 0) { + opt = '?'; /* unknown option */ + } else if (p[1] == ':') { + if (argv[s->i][s->pos] == 0) { + if (s->i < argc - 1) s->arg = argv[++s->i]; + else opt = ':'; /* missing option argument */ + } else s->arg = &argv[s->i][s->pos]; + s->pos = -1; + } + } + if (s->pos < 0 || argv[s->i][s->pos] == 0) { + ++s->i, s->pos = 0; + if (s->n_args > 0) /* permute */ + for (j = i0; j < s->i; ++j) + ketopt_permute(argv, j, s->n_args); + } + s->ind = s->i - s->n_args; + return opt; +} + +#endif diff --git a/khash.h b/khash.h index 311e88d..8f66469 100644 --- a/khash.h +++ b/khash.h @@ -1,635 +1,635 @@ -/* The MIT License - - Copyright (c) 2008, 2009, 2011 by Attractive Chaos - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - -/* - An example: - -#include "khash.h" -KHASH_MAP_INIT_INT(32, char) -int main() { - int ret, is_missing; - khiter_t k; - khash_t(32) *h = kh_init(32); - k = kh_put(32, h, 5, &ret); - kh_value(h, k) = 10; - k = kh_get(32, h, 10); - is_missing = (k == kh_end(h)); - k = kh_get(32, h, 5); - kh_del(32, h, k); - for (k = kh_begin(h); k != kh_end(h); ++k) - if (kh_exist(h, k)) kh_value(h, k) = 1; - kh_destroy(32, h); - return 0; -} -*/ - -/* - 2013-05-02 (0.2.8): - - * Use quadratic probing. When the capacity is power of 2, stepping function - i*(i+1)/2 guarantees to traverse each bucket. It is better than double - hashing on cache performance and is more robust than linear probing. - - In theory, double hashing should be more robust than quadratic probing. - However, my implementation is probably not for large hash tables, because - the second hash function is closely tied to the first hash function, - which reduce the effectiveness of double hashing. - - Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php - - 2011-12-29 (0.2.7): - - * Minor code clean up; no actual effect. - - 2011-09-16 (0.2.6): - - * The capacity is a power of 2. This seems to dramatically improve the - speed for simple keys. Thank Zilong Tan for the suggestion. Reference: - - - http://code.google.com/p/ulib/ - - http://nothings.org/computer/judy/ - - * Allow to optionally use linear probing which usually has better - performance for random input. Double hashing is still the default as it - is more robust to certain non-random input. - - * Added Wang's integer hash function (not used by default). This hash - function is more robust to certain non-random input. - - 2011-02-14 (0.2.5): - - * Allow to declare global functions. - - 2009-09-26 (0.2.4): - - * Improve portability - - 2008-09-19 (0.2.3): - - * Corrected the example - * Improved interfaces - - 2008-09-11 (0.2.2): - - * Improved speed a little in kh_put() - - 2008-09-10 (0.2.1): - - * Added kh_clear() - * Fixed a compiling error - - 2008-09-02 (0.2.0): - - * Changed to token concatenation which increases flexibility. - - 2008-08-31 (0.1.2): - - * Fixed a bug in kh_get(), which has not been tested previously. - - 2008-08-31 (0.1.1): - - * Added destructor -*/ - - -#ifndef __AC_KHASH_H -#define __AC_KHASH_H - -/*! - @header - - Generic hash table library. - */ - -#define AC_VERSION_KHASH_H "0.2.8" - -#include -#include -#include -#include "kalloc.h" - -/* compiler specific configuration */ - -#if UINT_MAX == 0xffffffffu -typedef unsigned int khint32_t; -#elif ULONG_MAX == 0xffffffffu -typedef unsigned long khint32_t; -#endif - -#if ULONG_MAX == ULLONG_MAX -typedef unsigned long khint64_t; -#else -typedef unsigned long long khint64_t; -#endif - -#ifndef kh_inline -#ifdef _MSC_VER -#define kh_inline __inline -#else -#define kh_inline inline -#endif -#endif /* kh_inline */ - -#ifndef klib_unused -#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) -#define klib_unused __attribute__ ((__unused__)) -#else -#define klib_unused -#endif -#endif /* klib_unused */ - -typedef khint32_t khint_t; -typedef khint_t khiter_t; - -#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2) -#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1) -#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3) -#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1))) -#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1))) -#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1))) -#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1)) - -#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4) - -#ifndef kroundup32 -#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) -#endif - -static const double __ac_HASH_UPPER = 0.77; - -#define __KHASH_TYPE(name, khkey_t, khval_t) \ - typedef struct kh_##name##_s { \ - khint_t n_buckets, size, n_occupied, upper_bound; \ - khint32_t *flags; \ - khkey_t *keys; \ - khval_t *vals; \ - void *km; \ - } kh_##name##_t; - -#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \ - extern kh_##name##_t *kh_init_##name(void); \ - extern void kh_destroy_##name(kh_##name##_t *h); \ - extern void kh_clear_##name(kh_##name##_t *h); \ - extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \ - extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \ - extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \ - extern void kh_del_##name(kh_##name##_t *h, khint_t x); - -#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ - SCOPE kh_##name##_t *kh_init2_##name(void *km) { \ - kh_##name##_t *h; \ - h = (kh_##name##_t*)kcalloc(km, 1, sizeof(kh_##name##_t)); \ - h->km = km; \ - return h; \ - } \ - SCOPE kh_##name##_t *kh_init_##name(void) { return kh_init2_##name(0); } \ - SCOPE void kh_destroy_##name(kh_##name##_t *h) \ - { \ - if (h) { \ - void *km = h->km; \ - kfree(km, (void *)h->keys); kfree(km, h->flags); \ - kfree(km, (void *)h->vals); \ - kfree(km, h); \ - } \ - } \ - SCOPE void kh_clear_##name(kh_##name##_t *h) \ - { \ - if (h && h->flags) { \ - memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \ - h->size = h->n_occupied = 0; \ - } \ - } \ - SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ - { \ - if (h->n_buckets) { \ - khint_t k, i, last, mask, step = 0; \ - mask = h->n_buckets - 1; \ - k = __hash_func(key); i = k & mask; \ - last = i; \ - while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ - i = (i + (++step)) & mask; \ - if (i == last) return h->n_buckets; \ - } \ - return __ac_iseither(h->flags, i)? h->n_buckets : i; \ - } else return 0; \ - } \ - SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \ - { /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \ - khint32_t *new_flags = 0; \ - khint_t j = 1; \ - { \ - kroundup32(new_n_buckets); \ - if (new_n_buckets < 4) new_n_buckets = 4; \ - if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \ - else { /* hash table size to be changed (shrink or expand); rehash */ \ - new_flags = (khint32_t*)kmalloc(h->km, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ - if (!new_flags) return -1; \ - memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ - if (h->n_buckets < new_n_buckets) { /* expand */ \ - khkey_t *new_keys = (khkey_t*)krealloc(h->km, (void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ - if (!new_keys) { kfree(h->km, new_flags); return -1; } \ - h->keys = new_keys; \ - if (kh_is_map) { \ - khval_t *new_vals = (khval_t*)krealloc(h->km, (void *)h->vals, new_n_buckets * sizeof(khval_t)); \ - if (!new_vals) { kfree(h->km, new_flags); return -1; } \ - h->vals = new_vals; \ - } \ - } /* otherwise shrink */ \ - } \ - } \ - if (j) { /* rehashing is needed */ \ - for (j = 0; j != h->n_buckets; ++j) { \ - if (__ac_iseither(h->flags, j) == 0) { \ - khkey_t key = h->keys[j]; \ - khval_t val; \ - khint_t new_mask; \ - new_mask = new_n_buckets - 1; \ - if (kh_is_map) val = h->vals[j]; \ - __ac_set_isdel_true(h->flags, j); \ - while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \ - khint_t k, i, step = 0; \ - k = __hash_func(key); \ - i = k & new_mask; \ - while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \ - __ac_set_isempty_false(new_flags, i); \ - if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \ - { khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \ - if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \ - __ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \ - } else { /* write the element and jump out of the loop */ \ - h->keys[i] = key; \ - if (kh_is_map) h->vals[i] = val; \ - break; \ - } \ - } \ - } \ - } \ - if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \ - h->keys = (khkey_t*)krealloc(h->km, (void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ - if (kh_is_map) h->vals = (khval_t*)krealloc(h->km, (void *)h->vals, new_n_buckets * sizeof(khval_t)); \ - } \ - kfree(h->km, h->flags); /* free the working space */ \ - h->flags = new_flags; \ - h->n_buckets = new_n_buckets; \ - h->n_occupied = h->size; \ - h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \ - } \ - return 0; \ - } \ - SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \ - { \ - khint_t x; \ - if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \ - if (h->n_buckets > (h->size<<1)) { \ - if (kh_resize_##name(h, h->n_buckets - 1) < 0) { /* clear "deleted" elements */ \ - *ret = -1; return h->n_buckets; \ - } \ - } else if (kh_resize_##name(h, h->n_buckets + 1) < 0) { /* expand the hash table */ \ - *ret = -1; return h->n_buckets; \ - } \ - } /* TODO: to implement automatically shrinking; resize() already support shrinking */ \ - { \ - khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \ - x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \ - if (__ac_isempty(h->flags, i)) x = i; /* for speed up */ \ - else { \ - last = i; \ - while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ - if (__ac_isdel(h->flags, i)) site = i; \ - i = (i + (++step)) & mask; \ - if (i == last) { x = site; break; } \ - } \ - if (x == h->n_buckets) { \ - if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \ - else x = i; \ - } \ - } \ - } \ - if (__ac_isempty(h->flags, x)) { /* not present at all */ \ - h->keys[x] = key; \ - __ac_set_isboth_false(h->flags, x); \ - ++h->size; ++h->n_occupied; \ - *ret = 1; \ - } else if (__ac_isdel(h->flags, x)) { /* deleted */ \ - h->keys[x] = key; \ - __ac_set_isboth_false(h->flags, x); \ - ++h->size; \ - *ret = 2; \ - } else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \ - return x; \ - } \ - SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \ - { \ - if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \ - __ac_set_isdel_true(h->flags, x); \ - --h->size; \ - } \ - } - -#define KHASH_DECLARE(name, khkey_t, khval_t) \ - __KHASH_TYPE(name, khkey_t, khval_t) \ - __KHASH_PROTOTYPES(name, khkey_t, khval_t) - -#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ - __KHASH_TYPE(name, khkey_t, khval_t) \ - __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) - -#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ - KHASH_INIT2(name, static kh_inline klib_unused, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) - -/* --- BEGIN OF HASH FUNCTIONS --- */ - -/*! @function - @abstract Integer hash function - @param key The integer [khint32_t] - @return The hash value [khint_t] - */ -#define kh_int_hash_func(key) (khint32_t)(key) -/*! @function - @abstract Integer comparison function - */ -#define kh_int_hash_equal(a, b) ((a) == (b)) -/*! @function - @abstract 64-bit integer hash function - @param key The integer [khint64_t] - @return The hash value [khint_t] - */ -#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11) -/*! @function - @abstract 64-bit integer comparison function - */ -#define kh_int64_hash_equal(a, b) ((a) == (b)) -/*! @function - @abstract const char* hash function - @param s Pointer to a null terminated string - @return The hash value - */ -static kh_inline khint_t __ac_X31_hash_string(const char *s) -{ - khint_t h = (khint_t)*s; - if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s; - return h; -} -/*! @function - @abstract Another interface to const char* hash function - @param key Pointer to a null terminated string [const char*] - @return The hash value [khint_t] - */ -#define kh_str_hash_func(key) __ac_X31_hash_string(key) -/*! @function - @abstract Const char* comparison function - */ -#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0) - -static kh_inline khint_t __ac_Wang_hash(khint_t key) -{ - key += ~(key << 15); - key ^= (key >> 10); - key += (key << 3); - key ^= (key >> 6); - key += ~(key << 11); - key ^= (key >> 16); - return key; -} -#define kh_int_hash_func2(key) __ac_Wang_hash((khint_t)key) - -static kh_inline khint64_t __ac_Wang_hash64(khint64_t key) -{ - key = ~key + (key << 21); - key = key ^ key >> 24; - key = (key + (key << 3)) + (key << 8); - key = key ^ key >> 14; - key = (key + (key << 2)) + (key << 4); - key = key ^ key >> 28; - key = key + (key << 31); - return key; -} -#define kh_int_hash64_func2(key) __ac_Wang_hash64((khint64_t)key) - -/* --- END OF HASH FUNCTIONS --- */ - -/* Other convenient macros... */ - -/*! - @abstract Type of the hash table. - @param name Name of the hash table [symbol] - */ -#define khash_t(name) kh_##name##_t - -/*! @function - @abstract Initiate a hash table. - @param name Name of the hash table [symbol] - @return Pointer to the hash table [khash_t(name)*] - */ -#define kh_init(name) kh_init_##name() -#define kh_init2(name, km) kh_init2_##name(km) - -/*! @function - @abstract Destroy a hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - */ -#define kh_destroy(name, h) kh_destroy_##name(h) - -/*! @function - @abstract Reset a hash table without deallocating memory. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - */ -#define kh_clear(name, h) kh_clear_##name(h) - -/*! @function - @abstract Resize a hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param s New size [khint_t] - */ -#define kh_resize(name, h, s) kh_resize_##name(h, s) - -/*! @function - @abstract Insert a key to the hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param k Key [type of keys] - @param r Extra return code: -1 if the operation failed; - 0 if the key is present in the hash table; - 1 if the bucket is empty (never used); 2 if the element in - the bucket has been deleted [int*] - @return Iterator to the inserted element [khint_t] - */ -#define kh_put(name, h, k, r) kh_put_##name(h, k, r) - -/*! @function - @abstract Retrieve a key from the hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param k Key [type of keys] - @return Iterator to the found element, or kh_end(h) if the element is absent [khint_t] - */ -#define kh_get(name, h, k) kh_get_##name(h, k) - -/*! @function - @abstract Remove a key from the hash table. - @param name Name of the hash table [symbol] - @param h Pointer to the hash table [khash_t(name)*] - @param k Iterator to the element to be deleted [khint_t] - */ -#define kh_del(name, h, k) kh_del_##name(h, k) - -/*! @function - @abstract Test whether a bucket contains data. - @param h Pointer to the hash table [khash_t(name)*] - @param x Iterator to the bucket [khint_t] - @return 1 if containing data; 0 otherwise [int] - */ -#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x))) - -/*! @function - @abstract Get key given an iterator - @param h Pointer to the hash table [khash_t(name)*] - @param x Iterator to the bucket [khint_t] - @return Key [type of keys] - */ -#define kh_key(h, x) ((h)->keys[x]) - -/*! @function - @abstract Get value given an iterator - @param h Pointer to the hash table [khash_t(name)*] - @param x Iterator to the bucket [khint_t] - @return Value [type of values] - @discussion For hash sets, calling this results in segfault. - */ -#define kh_val(h, x) ((h)->vals[x]) - -/*! @function - @abstract Alias of kh_val() - */ -#define kh_value(h, x) ((h)->vals[x]) - -/*! @function - @abstract Get the start iterator - @param h Pointer to the hash table [khash_t(name)*] - @return The start iterator [khint_t] - */ -#define kh_begin(h) (khint_t)(0) - -/*! @function - @abstract Get the end iterator - @param h Pointer to the hash table [khash_t(name)*] - @return The end iterator [khint_t] - */ -#define kh_end(h) ((h)->n_buckets) - -/*! @function - @abstract Get the number of elements in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @return Number of elements in the hash table [khint_t] - */ -#define kh_size(h) ((h)->size) - -/*! @function - @abstract Get the number of buckets in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @return Number of buckets in the hash table [khint_t] - */ -#define kh_n_buckets(h) ((h)->n_buckets) - -/*! @function - @abstract Iterate over the entries in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @param kvar Variable to which key will be assigned - @param vvar Variable to which value will be assigned - @param code Block of code to execute - */ -#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \ - for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ - if (!kh_exist(h,__i)) continue; \ - (kvar) = kh_key(h,__i); \ - (vvar) = kh_val(h,__i); \ - code; \ - } } - -/*! @function - @abstract Iterate over the values in the hash table - @param h Pointer to the hash table [khash_t(name)*] - @param vvar Variable to which value will be assigned - @param code Block of code to execute - */ -#define kh_foreach_value(h, vvar, code) { khint_t __i; \ - for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ - if (!kh_exist(h,__i)) continue; \ - (vvar) = kh_val(h,__i); \ - code; \ - } } - -/* More conenient interfaces */ - -/*! @function - @abstract Instantiate a hash set containing integer keys - @param name Name of the hash table [symbol] - */ -#define KHASH_SET_INIT_INT(name) \ - KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal) - -/*! @function - @abstract Instantiate a hash map containing integer keys - @param name Name of the hash table [symbol] - @param khval_t Type of values [type] - */ -#define KHASH_MAP_INIT_INT(name, khval_t) \ - KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal) - -/*! @function - @abstract Instantiate a hash map containing 64-bit integer keys - @param name Name of the hash table [symbol] - */ -#define KHASH_SET_INIT_INT64(name) \ - KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal) - -/*! @function - @abstract Instantiate a hash map containing 64-bit integer keys - @param name Name of the hash table [symbol] - @param khval_t Type of values [type] - */ -#define KHASH_MAP_INIT_INT64(name, khval_t) \ - KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal) - -typedef const char *kh_cstr_t; -/*! @function - @abstract Instantiate a hash map containing const char* keys - @param name Name of the hash table [symbol] - */ -#define KHASH_SET_INIT_STR(name) \ - KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal) - -/*! @function - @abstract Instantiate a hash map containing const char* keys - @param name Name of the hash table [symbol] - @param khval_t Type of values [type] - */ -#define KHASH_MAP_INIT_STR(name, khval_t) \ - KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal) - -#endif /* __AC_KHASH_H */ +/* The MIT License + + Copyright (c) 2008, 2009, 2011 by Attractive Chaos + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +/* + An example: + +#include "khash.h" +KHASH_MAP_INIT_INT(32, char) +int main() { + int ret, is_missing; + khiter_t k; + khash_t(32) *h = kh_init(32); + k = kh_put(32, h, 5, &ret); + kh_value(h, k) = 10; + k = kh_get(32, h, 10); + is_missing = (k == kh_end(h)); + k = kh_get(32, h, 5); + kh_del(32, h, k); + for (k = kh_begin(h); k != kh_end(h); ++k) + if (kh_exist(h, k)) kh_value(h, k) = 1; + kh_destroy(32, h); + return 0; +} +*/ + +/* + 2013-05-02 (0.2.8): + + * Use quadratic probing. When the capacity is power of 2, stepping function + i*(i+1)/2 guarantees to traverse each bucket. It is better than double + hashing on cache performance and is more robust than linear probing. + + In theory, double hashing should be more robust than quadratic probing. + However, my implementation is probably not for large hash tables, because + the second hash function is closely tied to the first hash function, + which reduce the effectiveness of double hashing. + + Reference: http://research.cs.vt.edu/AVresearch/hashing/quadratic.php + + 2011-12-29 (0.2.7): + + * Minor code clean up; no actual effect. + + 2011-09-16 (0.2.6): + + * The capacity is a power of 2. This seems to dramatically improve the + speed for simple keys. Thank Zilong Tan for the suggestion. Reference: + + - http://code.google.com/p/ulib/ + - http://nothings.org/computer/judy/ + + * Allow to optionally use linear probing which usually has better + performance for random input. Double hashing is still the default as it + is more robust to certain non-random input. + + * Added Wang's integer hash function (not used by default). This hash + function is more robust to certain non-random input. + + 2011-02-14 (0.2.5): + + * Allow to declare global functions. + + 2009-09-26 (0.2.4): + + * Improve portability + + 2008-09-19 (0.2.3): + + * Corrected the example + * Improved interfaces + + 2008-09-11 (0.2.2): + + * Improved speed a little in kh_put() + + 2008-09-10 (0.2.1): + + * Added kh_clear() + * Fixed a compiling error + + 2008-09-02 (0.2.0): + + * Changed to token concatenation which increases flexibility. + + 2008-08-31 (0.1.2): + + * Fixed a bug in kh_get(), which has not been tested previously. + + 2008-08-31 (0.1.1): + + * Added destructor +*/ + + +#ifndef __AC_KHASH_H +#define __AC_KHASH_H + +/*! + @header + + Generic hash table library. + */ + +#define AC_VERSION_KHASH_H "0.2.8" + +#include +#include +#include +#include "kalloc.h" + +/* compiler specific configuration */ + +#if UINT_MAX == 0xffffffffu +typedef unsigned int khint32_t; +#elif ULONG_MAX == 0xffffffffu +typedef unsigned long khint32_t; +#endif + +#if ULONG_MAX == ULLONG_MAX +typedef unsigned long khint64_t; +#else +typedef unsigned long long khint64_t; +#endif + +#ifndef kh_inline +#ifdef _MSC_VER +#define kh_inline __inline +#else +#define kh_inline inline +#endif +#endif /* kh_inline */ + +#ifndef klib_unused +#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) +#define klib_unused __attribute__ ((__unused__)) +#else +#define klib_unused +#endif +#endif /* klib_unused */ + +typedef khint32_t khint_t; +typedef khint_t khiter_t; + +#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2) +#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1) +#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3) +#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1))) +#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1))) +#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1))) +#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1)) + +#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4) + +#ifndef kroundup32 +#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) +#endif + +static const double __ac_HASH_UPPER = 0.77; + +#define __KHASH_TYPE(name, khkey_t, khval_t) \ + typedef struct kh_##name##_s { \ + khint_t n_buckets, size, n_occupied, upper_bound; \ + khint32_t *flags; \ + khkey_t *keys; \ + khval_t *vals; \ + void *km; \ + } kh_##name##_t; + +#define __KHASH_PROTOTYPES(name, khkey_t, khval_t) \ + extern kh_##name##_t *kh_init_##name(void); \ + extern void kh_destroy_##name(kh_##name##_t *h); \ + extern void kh_clear_##name(kh_##name##_t *h); \ + extern khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key); \ + extern int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets); \ + extern khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret); \ + extern void kh_del_##name(kh_##name##_t *h, khint_t x); + +#define __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ + SCOPE kh_##name##_t *kh_init2_##name(void *km) { \ + kh_##name##_t *h; \ + h = (kh_##name##_t*)kcalloc(km, 1, sizeof(kh_##name##_t)); \ + h->km = km; \ + return h; \ + } \ + SCOPE kh_##name##_t *kh_init_##name(void) { return kh_init2_##name(0); } \ + SCOPE void kh_destroy_##name(kh_##name##_t *h) \ + { \ + if (h) { \ + void *km = h->km; \ + kfree(km, (void *)h->keys); kfree(km, h->flags); \ + kfree(km, (void *)h->vals); \ + kfree(km, h); \ + } \ + } \ + SCOPE void kh_clear_##name(kh_##name##_t *h) \ + { \ + if (h && h->flags) { \ + memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \ + h->size = h->n_occupied = 0; \ + } \ + } \ + SCOPE khint_t kh_get_##name(const kh_##name##_t *h, khkey_t key) \ + { \ + if (h->n_buckets) { \ + khint_t k, i, last, mask, step = 0; \ + mask = h->n_buckets - 1; \ + k = __hash_func(key); i = k & mask; \ + last = i; \ + while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ + i = (i + (++step)) & mask; \ + if (i == last) return h->n_buckets; \ + } \ + return __ac_iseither(h->flags, i)? h->n_buckets : i; \ + } else return 0; \ + } \ + SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \ + { /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \ + khint32_t *new_flags = 0; \ + khint_t j = 1; \ + { \ + kroundup32(new_n_buckets); \ + if (new_n_buckets < 4) new_n_buckets = 4; \ + if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \ + else { /* hash table size to be changed (shrink or expand); rehash */ \ + new_flags = (khint32_t*)kmalloc(h->km, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ + if (!new_flags) return -1; \ + memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \ + if (h->n_buckets < new_n_buckets) { /* expand */ \ + khkey_t *new_keys = (khkey_t*)krealloc(h->km, (void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ + if (!new_keys) { kfree(h->km, new_flags); return -1; } \ + h->keys = new_keys; \ + if (kh_is_map) { \ + khval_t *new_vals = (khval_t*)krealloc(h->km, (void *)h->vals, new_n_buckets * sizeof(khval_t)); \ + if (!new_vals) { kfree(h->km, new_flags); return -1; } \ + h->vals = new_vals; \ + } \ + } /* otherwise shrink */ \ + } \ + } \ + if (j) { /* rehashing is needed */ \ + for (j = 0; j != h->n_buckets; ++j) { \ + if (__ac_iseither(h->flags, j) == 0) { \ + khkey_t key = h->keys[j]; \ + khval_t val; \ + khint_t new_mask; \ + new_mask = new_n_buckets - 1; \ + if (kh_is_map) val = h->vals[j]; \ + __ac_set_isdel_true(h->flags, j); \ + while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \ + khint_t k, i, step = 0; \ + k = __hash_func(key); \ + i = k & new_mask; \ + while (!__ac_isempty(new_flags, i)) i = (i + (++step)) & new_mask; \ + __ac_set_isempty_false(new_flags, i); \ + if (i < h->n_buckets && __ac_iseither(h->flags, i) == 0) { /* kick out the existing element */ \ + { khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \ + if (kh_is_map) { khval_t tmp = h->vals[i]; h->vals[i] = val; val = tmp; } \ + __ac_set_isdel_true(h->flags, i); /* mark it as deleted in the old hash table */ \ + } else { /* write the element and jump out of the loop */ \ + h->keys[i] = key; \ + if (kh_is_map) h->vals[i] = val; \ + break; \ + } \ + } \ + } \ + } \ + if (h->n_buckets > new_n_buckets) { /* shrink the hash table */ \ + h->keys = (khkey_t*)krealloc(h->km, (void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ + if (kh_is_map) h->vals = (khval_t*)krealloc(h->km, (void *)h->vals, new_n_buckets * sizeof(khval_t)); \ + } \ + kfree(h->km, h->flags); /* free the working space */ \ + h->flags = new_flags; \ + h->n_buckets = new_n_buckets; \ + h->n_occupied = h->size; \ + h->upper_bound = (khint_t)(h->n_buckets * __ac_HASH_UPPER + 0.5); \ + } \ + return 0; \ + } \ + SCOPE khint_t kh_put_##name(kh_##name##_t *h, khkey_t key, int *ret) \ + { \ + khint_t x; \ + if (h->n_occupied >= h->upper_bound) { /* update the hash table */ \ + if (h->n_buckets > (h->size<<1)) { \ + if (kh_resize_##name(h, h->n_buckets - 1) < 0) { /* clear "deleted" elements */ \ + *ret = -1; return h->n_buckets; \ + } \ + } else if (kh_resize_##name(h, h->n_buckets + 1) < 0) { /* expand the hash table */ \ + *ret = -1; return h->n_buckets; \ + } \ + } /* TODO: to implement automatically shrinking; resize() already support shrinking */ \ + { \ + khint_t k, i, site, last, mask = h->n_buckets - 1, step = 0; \ + x = site = h->n_buckets; k = __hash_func(key); i = k & mask; \ + if (__ac_isempty(h->flags, i)) x = i; /* for speed up */ \ + else { \ + last = i; \ + while (!__ac_isempty(h->flags, i) && (__ac_isdel(h->flags, i) || !__hash_equal(h->keys[i], key))) { \ + if (__ac_isdel(h->flags, i)) site = i; \ + i = (i + (++step)) & mask; \ + if (i == last) { x = site; break; } \ + } \ + if (x == h->n_buckets) { \ + if (__ac_isempty(h->flags, i) && site != h->n_buckets) x = site; \ + else x = i; \ + } \ + } \ + } \ + if (__ac_isempty(h->flags, x)) { /* not present at all */ \ + h->keys[x] = key; \ + __ac_set_isboth_false(h->flags, x); \ + ++h->size; ++h->n_occupied; \ + *ret = 1; \ + } else if (__ac_isdel(h->flags, x)) { /* deleted */ \ + h->keys[x] = key; \ + __ac_set_isboth_false(h->flags, x); \ + ++h->size; \ + *ret = 2; \ + } else *ret = 0; /* Don't touch h->keys[x] if present and not deleted */ \ + return x; \ + } \ + SCOPE void kh_del_##name(kh_##name##_t *h, khint_t x) \ + { \ + if (x != h->n_buckets && !__ac_iseither(h->flags, x)) { \ + __ac_set_isdel_true(h->flags, x); \ + --h->size; \ + } \ + } + +#define KHASH_DECLARE(name, khkey_t, khval_t) \ + __KHASH_TYPE(name, khkey_t, khval_t) \ + __KHASH_PROTOTYPES(name, khkey_t, khval_t) + +#define KHASH_INIT2(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ + __KHASH_TYPE(name, khkey_t, khval_t) \ + __KHASH_IMPL(name, SCOPE, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) + +#define KHASH_INIT(name, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) \ + KHASH_INIT2(name, static kh_inline klib_unused, khkey_t, khval_t, kh_is_map, __hash_func, __hash_equal) + +/* --- BEGIN OF HASH FUNCTIONS --- */ + +/*! @function + @abstract Integer hash function + @param key The integer [khint32_t] + @return The hash value [khint_t] + */ +#define kh_int_hash_func(key) (khint32_t)(key) +/*! @function + @abstract Integer comparison function + */ +#define kh_int_hash_equal(a, b) ((a) == (b)) +/*! @function + @abstract 64-bit integer hash function + @param key The integer [khint64_t] + @return The hash value [khint_t] + */ +#define kh_int64_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11) +/*! @function + @abstract 64-bit integer comparison function + */ +#define kh_int64_hash_equal(a, b) ((a) == (b)) +/*! @function + @abstract const char* hash function + @param s Pointer to a null terminated string + @return The hash value + */ +static kh_inline khint_t __ac_X31_hash_string(const char *s) +{ + khint_t h = (khint_t)*s; + if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s; + return h; +} +/*! @function + @abstract Another interface to const char* hash function + @param key Pointer to a null terminated string [const char*] + @return The hash value [khint_t] + */ +#define kh_str_hash_func(key) __ac_X31_hash_string(key) +/*! @function + @abstract Const char* comparison function + */ +#define kh_str_hash_equal(a, b) (strcmp(a, b) == 0) + +static kh_inline khint_t __ac_Wang_hash(khint_t key) +{ + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; +} +#define kh_int_hash_func2(key) __ac_Wang_hash((khint_t)key) + +static kh_inline khint64_t __ac_Wang_hash64(khint64_t key) +{ + key = ~key + (key << 21); + key = key ^ key >> 24; + key = (key + (key << 3)) + (key << 8); + key = key ^ key >> 14; + key = (key + (key << 2)) + (key << 4); + key = key ^ key >> 28; + key = key + (key << 31); + return key; +} +#define kh_int_hash64_func2(key) __ac_Wang_hash64((khint64_t)key) + +/* --- END OF HASH FUNCTIONS --- */ + +/* Other convenient macros... */ + +/*! + @abstract Type of the hash table. + @param name Name of the hash table [symbol] + */ +#define khash_t(name) kh_##name##_t + +/*! @function + @abstract Initiate a hash table. + @param name Name of the hash table [symbol] + @return Pointer to the hash table [khash_t(name)*] + */ +#define kh_init(name) kh_init_##name() +#define kh_init2(name, km) kh_init2_##name(km) + +/*! @function + @abstract Destroy a hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + */ +#define kh_destroy(name, h) kh_destroy_##name(h) + +/*! @function + @abstract Reset a hash table without deallocating memory. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + */ +#define kh_clear(name, h) kh_clear_##name(h) + +/*! @function + @abstract Resize a hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param s New size [khint_t] + */ +#define kh_resize(name, h, s) kh_resize_##name(h, s) + +/*! @function + @abstract Insert a key to the hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param k Key [type of keys] + @param r Extra return code: -1 if the operation failed; + 0 if the key is present in the hash table; + 1 if the bucket is empty (never used); 2 if the element in + the bucket has been deleted [int*] + @return Iterator to the inserted element [khint_t] + */ +#define kh_put(name, h, k, r) kh_put_##name(h, k, r) + +/*! @function + @abstract Retrieve a key from the hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param k Key [type of keys] + @return Iterator to the found element, or kh_end(h) if the element is absent [khint_t] + */ +#define kh_get(name, h, k) kh_get_##name(h, k) + +/*! @function + @abstract Remove a key from the hash table. + @param name Name of the hash table [symbol] + @param h Pointer to the hash table [khash_t(name)*] + @param k Iterator to the element to be deleted [khint_t] + */ +#define kh_del(name, h, k) kh_del_##name(h, k) + +/*! @function + @abstract Test whether a bucket contains data. + @param h Pointer to the hash table [khash_t(name)*] + @param x Iterator to the bucket [khint_t] + @return 1 if containing data; 0 otherwise [int] + */ +#define kh_exist(h, x) (!__ac_iseither((h)->flags, (x))) + +/*! @function + @abstract Get key given an iterator + @param h Pointer to the hash table [khash_t(name)*] + @param x Iterator to the bucket [khint_t] + @return Key [type of keys] + */ +#define kh_key(h, x) ((h)->keys[x]) + +/*! @function + @abstract Get value given an iterator + @param h Pointer to the hash table [khash_t(name)*] + @param x Iterator to the bucket [khint_t] + @return Value [type of values] + @discussion For hash sets, calling this results in segfault. + */ +#define kh_val(h, x) ((h)->vals[x]) + +/*! @function + @abstract Alias of kh_val() + */ +#define kh_value(h, x) ((h)->vals[x]) + +/*! @function + @abstract Get the start iterator + @param h Pointer to the hash table [khash_t(name)*] + @return The start iterator [khint_t] + */ +#define kh_begin(h) (khint_t)(0) + +/*! @function + @abstract Get the end iterator + @param h Pointer to the hash table [khash_t(name)*] + @return The end iterator [khint_t] + */ +#define kh_end(h) ((h)->n_buckets) + +/*! @function + @abstract Get the number of elements in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @return Number of elements in the hash table [khint_t] + */ +#define kh_size(h) ((h)->size) + +/*! @function + @abstract Get the number of buckets in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @return Number of buckets in the hash table [khint_t] + */ +#define kh_n_buckets(h) ((h)->n_buckets) + +/*! @function + @abstract Iterate over the entries in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @param kvar Variable to which key will be assigned + @param vvar Variable to which value will be assigned + @param code Block of code to execute + */ +#define kh_foreach(h, kvar, vvar, code) { khint_t __i; \ + for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ + if (!kh_exist(h,__i)) continue; \ + (kvar) = kh_key(h,__i); \ + (vvar) = kh_val(h,__i); \ + code; \ + } } + +/*! @function + @abstract Iterate over the values in the hash table + @param h Pointer to the hash table [khash_t(name)*] + @param vvar Variable to which value will be assigned + @param code Block of code to execute + */ +#define kh_foreach_value(h, vvar, code) { khint_t __i; \ + for (__i = kh_begin(h); __i != kh_end(h); ++__i) { \ + if (!kh_exist(h,__i)) continue; \ + (vvar) = kh_val(h,__i); \ + code; \ + } } + +/* More conenient interfaces */ + +/*! @function + @abstract Instantiate a hash set containing integer keys + @param name Name of the hash table [symbol] + */ +#define KHASH_SET_INIT_INT(name) \ + KHASH_INIT(name, khint32_t, char, 0, kh_int_hash_func, kh_int_hash_equal) + +/*! @function + @abstract Instantiate a hash map containing integer keys + @param name Name of the hash table [symbol] + @param khval_t Type of values [type] + */ +#define KHASH_MAP_INIT_INT(name, khval_t) \ + KHASH_INIT(name, khint32_t, khval_t, 1, kh_int_hash_func, kh_int_hash_equal) + +/*! @function + @abstract Instantiate a hash map containing 64-bit integer keys + @param name Name of the hash table [symbol] + */ +#define KHASH_SET_INIT_INT64(name) \ + KHASH_INIT(name, khint64_t, char, 0, kh_int64_hash_func, kh_int64_hash_equal) + +/*! @function + @abstract Instantiate a hash map containing 64-bit integer keys + @param name Name of the hash table [symbol] + @param khval_t Type of values [type] + */ +#define KHASH_MAP_INIT_INT64(name, khval_t) \ + KHASH_INIT(name, khint64_t, khval_t, 1, kh_int64_hash_func, kh_int64_hash_equal) + +typedef const char *kh_cstr_t; +/*! @function + @abstract Instantiate a hash map containing const char* keys + @param name Name of the hash table [symbol] + */ +#define KHASH_SET_INIT_STR(name) \ + KHASH_INIT(name, kh_cstr_t, char, 0, kh_str_hash_func, kh_str_hash_equal) + +/*! @function + @abstract Instantiate a hash map containing const char* keys + @param name Name of the hash table [symbol] + @param khval_t Type of values [type] + */ +#define KHASH_MAP_INIT_STR(name, khval_t) \ + KHASH_INIT(name, kh_cstr_t, khval_t, 1, kh_str_hash_func, kh_str_hash_equal) + +#endif /* __AC_KHASH_H */ diff --git a/khashl.h b/khashl.h index 6fddd39..c9afab3 100644 --- a/khashl.h +++ b/khashl.h @@ -1,393 +1,393 @@ -/* The MIT License - - Copyright (c) 2019 by Attractive Chaos - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - -#ifndef __AC_KHASHL_H -#define __AC_KHASHL_H - -#define AC_VERSION_KHASHL_H "0.1" - -#include -#include -#include - -/************************************ - * Compiler specific configurations * - ************************************/ - -#if UINT_MAX == 0xffffffffu -typedef unsigned int khint32_t; -#elif ULONG_MAX == 0xffffffffu -typedef unsigned long khint32_t; -#endif - -#if ULONG_MAX == ULLONG_MAX -typedef unsigned long khint64_t; -#else -typedef unsigned long long khint64_t; -#endif - -#ifndef kh_inline -#ifdef _MSC_VER -#define kh_inline __inline -#else -#define kh_inline inline -#endif -#endif /* kh_inline */ - -#ifndef klib_unused -#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) -#define klib_unused __attribute__ ((__unused__)) -#else -#define klib_unused -#endif -#endif /* klib_unused */ - -#define KH_LOCAL static kh_inline klib_unused - -typedef khint32_t khint_t; - -/****************** - * malloc aliases * - ******************/ - -#ifndef kcalloc -#define kcalloc(N,Z) calloc(N,Z) -#endif -#ifndef kmalloc -#define kmalloc(Z) malloc(Z) -#endif -#ifndef krealloc -#define krealloc(P,Z) realloc(P,Z) -#endif -#ifndef kfree -#define kfree(P) free(P) -#endif - -/**************************** - * Simple private functions * - ****************************/ - -#define __kh_used(flag, i) (flag[i>>5] >> (i&0x1fU) & 1U) -#define __kh_set_used(flag, i) (flag[i>>5] |= 1U<<(i&0x1fU)) -#define __kh_set_unused(flag, i) (flag[i>>5] &= ~(1U<<(i&0x1fU))) - -#define __kh_fsize(m) ((m) < 32? 1 : (m)>>5) - -static kh_inline khint_t __kh_h2b(khint_t hash, khint_t bits) { return hash * 2654435769U >> (32 - bits); } - -/******************* - * Hash table base * - *******************/ - -#define __KHASHL_TYPE(HType, khkey_t) \ - typedef struct HType { \ - khint_t bits, count; \ - khint32_t *used; \ - khkey_t *keys; \ - } HType; - -#define __KHASHL_PROTOTYPES(HType, prefix, khkey_t) \ - extern HType *prefix##_init(void); \ - extern void prefix##_destroy(HType *h); \ - extern void prefix##_clear(HType *h); \ - extern khint_t prefix##_getp(const HType *h, const khkey_t *key); \ - extern int prefix##_resize(HType *h, khint_t new_n_buckets); \ - extern khint_t prefix##_putp(HType *h, const khkey_t *key, int *absent); \ - extern void prefix##_del(HType *h, khint_t k); - -#define __KHASHL_IMPL_BASIC(SCOPE, HType, prefix) \ - SCOPE HType *prefix##_init(void) { \ - return (HType*)kcalloc(1, sizeof(HType)); \ - } \ - SCOPE void prefix##_destroy(HType *h) { \ - if (!h) return; \ - kfree((void *)h->keys); kfree(h->used); \ - kfree(h); \ - } \ - SCOPE void prefix##_clear(HType *h) { \ - if (h && h->used) { \ - uint32_t n_buckets = 1U << h->bits; \ - memset(h->used, 0, __kh_fsize(n_buckets) * sizeof(khint32_t)); \ - h->count = 0; \ - } \ - } -#define __KHASHL_IMPL_S_L(SCOPE, HType, prefix, khkey_t) \ - SCOPE khint_t prefix##_save(HType *h, FILE* fp) { \ - if (!h) return 0; \ - uint8_t ff; \ - khint_t n_buckets = (h->keys? 1U<bits : 0U); \ - fwrite(&n_buckets, sizeof(n_buckets), 1, fp); \ - fwrite(&h->bits, sizeof(h->bits), 1, fp); \ - fwrite(&h->count, sizeof(h->count), 1, fp); \ - ff = h->used? 1:0; fwrite(&ff, sizeof(ff), 1, fp); \ - if(ff) fwrite(h->used, sizeof(khint32_t), __kh_fsize(n_buckets), fp); \ - ff = h->keys? 1:0; fwrite(&ff, sizeof(ff), 1, fp); \ - if(ff) fwrite(h->keys, sizeof(khkey_t), n_buckets, fp); \ - return 1; \ - } \ - SCOPE khint_t prefix##_load(HType **h, FILE* fp) { \ - (*h) = prefix##_init(); \ - khint_t n_buckets; \ - uint64_t flag = 0;\ - uint8_t ff; \ - flag += fread(&n_buckets, sizeof(n_buckets), 1, fp); \ - flag += fread(&(*h)->bits, sizeof((*h)->bits), 1, fp); \ - flag += fread(&(*h)->count, sizeof((*h)->count), 1, fp); \ - flag += fread(&ff, sizeof(ff), 1, fp); \ - if(ff) {\ - (*h)->used = (khint32_t*)kmalloc(__kh_fsize(n_buckets) * sizeof(khint32_t)); \ - flag += fread((*h)->used, sizeof(khint32_t), __kh_fsize(n_buckets), fp); }\ - flag += fread(&ff, sizeof(ff), 1, fp); \ - if(ff) {\ - (*h)->keys = (khkey_t*)kmalloc(n_buckets * sizeof(khkey_t)); \ - flag += fread((*h)->keys, sizeof(khkey_t), n_buckets, fp); }\ - return 1; \ - } \ - -#define __KHASHL_IMPL_GET(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ - SCOPE khint_t prefix##_getp(const HType *h, const khkey_t *key) { \ - khint_t i, last, n_buckets, mask; \ - if (h->keys == 0) return 0; \ - n_buckets = 1U << h->bits; \ - mask = n_buckets - 1U; \ - i = last = __kh_h2b(__hash_fn(*key), h->bits); \ - while (__kh_used(h->used, i) && !__hash_eq(h->keys[i], *key)) { \ - i = (i + 1U) & mask; \ - if (i == last) return n_buckets; \ - } \ - return !__kh_used(h->used, i)? n_buckets : i; \ - } \ - SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { return prefix##_getp(h, &key); } - -#define __KHASHL_IMPL_RESIZE(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ - SCOPE int prefix##_resize(HType *h, khint_t new_n_buckets) { \ - khint32_t *new_used = 0; \ - khint_t j = 0, x = new_n_buckets, n_buckets, new_bits, new_mask; \ - while ((x >>= 1) != 0) ++j; \ - if (new_n_buckets & (new_n_buckets - 1)) ++j; \ - new_bits = j > 2? j : 2; \ - new_n_buckets = 1U << new_bits; \ - if (h->count > (new_n_buckets>>1) + (new_n_buckets>>2)) return 0; /* requested size is too small */ \ - new_used = (khint32_t*)kmalloc(__kh_fsize(new_n_buckets) * sizeof(khint32_t)); \ - memset(new_used, 0, __kh_fsize(new_n_buckets) * sizeof(khint32_t)); \ - if (!new_used) return -1; /* not enough memory */ \ - n_buckets = h->keys? 1U<bits : 0U; \ - if (n_buckets < new_n_buckets) { /* expand */ \ - khkey_t *new_keys = (khkey_t*)krealloc((void*)h->keys, new_n_buckets * sizeof(khkey_t)); \ - if (!new_keys) { kfree(new_used); return -1; } \ - h->keys = new_keys; \ - } /* otherwise shrink */ \ - new_mask = new_n_buckets - 1; \ - for (j = 0; j != n_buckets; ++j) { \ - khkey_t key; \ - if (!__kh_used(h->used, j)) continue; \ - key = h->keys[j]; \ - __kh_set_unused(h->used, j); \ - while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \ - khint_t i; \ - i = __kh_h2b(__hash_fn(key), new_bits); \ - while (__kh_used(new_used, i)) i = (i + 1) & new_mask; \ - __kh_set_used(new_used, i); \ - if (i < n_buckets && __kh_used(h->used, i)) { /* kick out the existing element */ \ - { khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \ - __kh_set_unused(h->used, i); /* mark it as deleted in the old hash table */ \ - } else { /* write the element and jump out of the loop */ \ - h->keys[i] = key; \ - break; \ - } \ - } \ - } \ - if (n_buckets > new_n_buckets) /* shrink the hash table */ \ - h->keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ - kfree(h->used); /* free the working space */ \ - h->used = new_used, h->bits = new_bits; \ - return 0; \ - } - -#define __KHASHL_IMPL_PUT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ - SCOPE khint_t prefix##_putp(HType *h, const khkey_t *key, int *absent) { \ - khint_t n_buckets, i, last, mask; \ - n_buckets = h->keys? 1U<bits : 0U; \ - *absent = -1; \ - if (h->count >= (n_buckets>>1) + (n_buckets>>2)) { /* rehashing */ \ - if (prefix##_resize(h, n_buckets + 1U) < 0) \ - return n_buckets; \ - n_buckets = 1U<bits; \ - } /* TODO: to implement automatically shrinking; resize() already support shrinking */ \ - mask = n_buckets - 1; \ - i = last = __kh_h2b(__hash_fn(*key), h->bits); \ - while (__kh_used(h->used, i) && !__hash_eq(h->keys[i], *key)) { \ - i = (i + 1U) & mask; \ - if (i == last) break; \ - } \ - if (!__kh_used(h->used, i)) { /* not present at all */ \ - h->keys[i] = *key; \ - __kh_set_used(h->used, i); \ - ++h->count; \ - *absent = 1; \ - } else *absent = 0; /* Don't touch h->keys[i] if present */ \ - return i; \ - } \ - SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { return prefix##_putp(h, &key, absent); } - -#define __KHASHL_IMPL_DEL(SCOPE, HType, prefix, khkey_t, __hash_fn) \ - SCOPE int prefix##_del(HType *h, khint_t i) { \ - khint_t j = i, k, mask, n_buckets; \ - if (h->keys == 0) return 0; \ - n_buckets = 1U<bits; \ - mask = n_buckets - 1U; \ - while (1) { \ - j = (j + 1U) & mask; \ - if (j == i || !__kh_used(h->used, j)) break; /* j==i only when the table is completely full */ \ - k = __kh_h2b(__hash_fn(h->keys[j]), h->bits); \ - if ((j > i && (k <= i || k > j)) || (j < i && (k <= i && k > j))) \ - h->keys[i] = h->keys[j], i = j; \ - } \ - __kh_set_unused(h->used, i); \ - --h->count; \ - return 1; \ - } - -#define KHASHL_DECLARE(HType, prefix, khkey_t) \ - __KHASHL_TYPE(HType, khkey_t) \ - __KHASHL_PROTOTYPES(HType, prefix, khkey_t) - -#define KHASHL_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ - __KHASHL_TYPE(HType, khkey_t) \ - __KHASHL_IMPL_BASIC(SCOPE, HType, prefix) \ - __KHASHL_IMPL_S_L(SCOPE, HType, prefix, khkey_t) \ - __KHASHL_IMPL_GET(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ - __KHASHL_IMPL_RESIZE(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ - __KHASHL_IMPL_PUT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ - __KHASHL_IMPL_DEL(SCOPE, HType, prefix, khkey_t, __hash_fn) - -/***************************** - * More convenient interface * - *****************************/ - -#define __kh_packed __attribute__ ((__packed__)) -#define __kh_cached_hash(x) ((x).hash) - -#define KHASHL_SET_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ - typedef struct { khkey_t key; } __kh_packed HType##_s_bucket_t; \ - static kh_inline khint_t prefix##_s_hash(HType##_s_bucket_t x) { return __hash_fn(x.key); } \ - static kh_inline int prefix##_s_eq(HType##_s_bucket_t x, HType##_s_bucket_t y) { return __hash_eq(x.key, y.key); } \ - KHASHL_INIT(KH_LOCAL, HType, prefix##_s, HType##_s_bucket_t, prefix##_s_hash, prefix##_s_eq) \ - SCOPE HType *prefix##_init(void) { return prefix##_s_init(); } \ - SCOPE void prefix##_destroy(HType *h) { prefix##_s_destroy(h); } \ - SCOPE khint_t prefix##_save(HType *h, FILE* fp) { return prefix##_s_save(h, fp); } \ - SCOPE khint_t prefix##_load(HType **h, FILE* fp) { return prefix##_s_load(h, fp); } \ - SCOPE void prefix##_resize(HType *h, khint_t new_n_buckets) { prefix##_s_resize(h, new_n_buckets); } \ - SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_s_bucket_t t; t.key = key; return prefix##_s_getp(h, &t); } \ - SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_s_del(h, k); } \ - SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_s_bucket_t t; t.key = key; return prefix##_s_putp(h, &t, absent); } - -#define KHASHL_MAP_INIT(SCOPE, HType, prefix, khkey_t, kh_val_t, __hash_fn, __hash_eq) \ - typedef struct { khkey_t key; kh_val_t val; } __kh_packed HType##_m_bucket_t; \ - static kh_inline khint_t prefix##_m_hash(HType##_m_bucket_t x) { return __hash_fn(x.key); } \ - static kh_inline int prefix##_m_eq(HType##_m_bucket_t x, HType##_m_bucket_t y) { return __hash_eq(x.key, y.key); } \ - KHASHL_INIT(KH_LOCAL, HType, prefix##_m, HType##_m_bucket_t, prefix##_m_hash, prefix##_m_eq) \ - SCOPE HType *prefix##_init(void) { return prefix##_m_init(); } \ - SCOPE void prefix##_destroy(HType *h) { prefix##_m_destroy(h); } \ - SCOPE khint_t prefix##_save(HType *h, FILE* fp) { return prefix##_m_save(h, fp); } \ - SCOPE khint_t prefix##_load(HType **h, FILE* fp) { return prefix##_m_load(h, fp); } \ - SCOPE void prefix##_resize(HType *h, khint_t new_n_buckets) { prefix##_m_resize(h, new_n_buckets); } \ - SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_m_bucket_t t; t.key = key; return prefix##_m_getp(h, &t); } \ - SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_m_del(h, k); } \ - SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_m_bucket_t t; t.key = key; return prefix##_m_putp(h, &t, absent); } - -#define KHASHL_CSET_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ - typedef struct { khkey_t key; khint_t hash; } __kh_packed HType##_cs_bucket_t; \ - static kh_inline int prefix##_cs_eq(HType##_cs_bucket_t x, HType##_cs_bucket_t y) { return x.hash == y.hash && __hash_eq(x.key, y.key); } \ - KHASHL_INIT(KH_LOCAL, HType, prefix##_cs, HType##_cs_bucket_t, __kh_cached_hash, prefix##_cs_eq) \ - SCOPE HType *prefix##_init(void) { return prefix##_cs_init(); } \ - SCOPE void prefix##_destroy(HType *h) { prefix##_cs_destroy(h); } \ - SCOPE khint_t prefix##_save(HType *h, FILE* fp) { return prefix##_cs_save(h, fp); } \ - SCOPE khint_t prefix##_load(HType **h, FILE* fp) { return prefix##_cs_load(h, fp); } \ - SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_cs_bucket_t t; t.key = key; t.hash = __hash_fn(key); return prefix##_cs_getp(h, &t); } \ - SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_cs_del(h, k); } \ - SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_cs_bucket_t t; t.key = key, t.hash = __hash_fn(key); return prefix##_cs_putp(h, &t, absent); } - -#define KHASHL_CMAP_INIT(SCOPE, HType, prefix, khkey_t, kh_val_t, __hash_fn, __hash_eq) \ - typedef struct { khkey_t key; kh_val_t val; khint_t hash; } __kh_packed HType##_cm_bucket_t; \ - static kh_inline int prefix##_cm_eq(HType##_cm_bucket_t x, HType##_cm_bucket_t y) { return x.hash == y.hash && __hash_eq(x.key, y.key); } \ - KHASHL_INIT(KH_LOCAL, HType, prefix##_cm, HType##_cm_bucket_t, __kh_cached_hash, prefix##_cm_eq) \ - SCOPE HType *prefix##_init(void) { return prefix##_cm_init(); } \ - SCOPE void prefix##_destroy(HType *h) { prefix##_cm_destroy(h); } \ - SCOPE khint_t prefix##_save(HType *h, FILE* fp) { return prefix##_cm_save(h, fp); } \ - SCOPE khint_t prefix##_load(HType **h, FILE* fp) { return prefix##_cm_load(h, fp); } \ - SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_cm_bucket_t t; t.key = key; t.hash = __hash_fn(key); return prefix##_cm_getp(h, &t); } \ - SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_cm_del(h, k); } \ - SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_cm_bucket_t t; t.key = key, t.hash = __hash_fn(key); return prefix##_cm_putp(h, &t, absent); } - -/************************** - * Public macro functions * - **************************/ - -#define kh_bucket(h, x) ((h)->keys[x]) -#define kh_size(h) ((h)->count) -#define kh_capacity(h) ((h)->keys? 1U<<(h)->bits : 0U) -#define kh_end(h) kh_capacity(h) - -#define kh_key(h, x) ((h)->keys[x].key) -#define kh_val(h, x) ((h)->keys[x].val) -#define kh_exist(h, x) __kh_used((h)->used, (x)) - -/************************************** - * Common hash and equality functions * - **************************************/ - -#define kh_eq_generic(a, b) ((a) == (b)) -#define kh_eq_str(a, b) (strcmp((a), (b)) == 0) -#define kh_hash_dummy(x) ((khint_t)(x)) - -static kh_inline khint_t kh_hash_uint32(khint_t key) { - key += ~(key << 15); - key ^= (key >> 10); - key += (key << 3); - key ^= (key >> 6); - key += ~(key << 11); - key ^= (key >> 16); - return key; -} - -static kh_inline khint_t kh_hash_uint64(khint64_t key) { - key = ~key + (key << 21); - key = key ^ key >> 24; - key = (key + (key << 3)) + (key << 8); - key = key ^ key >> 14; - key = (key + (key << 2)) + (key << 4); - key = key ^ key >> 28; - key = key + (key << 31); - return (khint_t)key; -} - -static kh_inline khint_t kh_hash_str(const char *s) { - khint_t h = (khint_t)*s; - if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s; - return h; -} - -#endif /* __AC_KHASHL_H */ +/* The MIT License + + Copyright (c) 2019 by Attractive Chaos + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#ifndef __AC_KHASHL_H +#define __AC_KHASHL_H + +#define AC_VERSION_KHASHL_H "0.1" + +#include +#include +#include + +/************************************ + * Compiler specific configurations * + ************************************/ + +#if UINT_MAX == 0xffffffffu +typedef unsigned int khint32_t; +#elif ULONG_MAX == 0xffffffffu +typedef unsigned long khint32_t; +#endif + +#if ULONG_MAX == ULLONG_MAX +typedef unsigned long khint64_t; +#else +typedef unsigned long long khint64_t; +#endif + +#ifndef kh_inline +#ifdef _MSC_VER +#define kh_inline __inline +#else +#define kh_inline inline +#endif +#endif /* kh_inline */ + +#ifndef klib_unused +#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) +#define klib_unused __attribute__ ((__unused__)) +#else +#define klib_unused +#endif +#endif /* klib_unused */ + +#define KH_LOCAL static kh_inline klib_unused + +typedef khint32_t khint_t; + +/****************** + * malloc aliases * + ******************/ + +#ifndef kcalloc +#define kcalloc(N,Z) calloc(N,Z) +#endif +#ifndef kmalloc +#define kmalloc(Z) malloc(Z) +#endif +#ifndef krealloc +#define krealloc(P,Z) realloc(P,Z) +#endif +#ifndef kfree +#define kfree(P) free(P) +#endif + +/**************************** + * Simple private functions * + ****************************/ + +#define __kh_used(flag, i) (flag[i>>5] >> (i&0x1fU) & 1U) +#define __kh_set_used(flag, i) (flag[i>>5] |= 1U<<(i&0x1fU)) +#define __kh_set_unused(flag, i) (flag[i>>5] &= ~(1U<<(i&0x1fU))) + +#define __kh_fsize(m) ((m) < 32? 1 : (m)>>5) + +static kh_inline khint_t __kh_h2b(khint_t hash, khint_t bits) { return hash * 2654435769U >> (32 - bits); } + +/******************* + * Hash table base * + *******************/ + +#define __KHASHL_TYPE(HType, khkey_t) \ + typedef struct HType { \ + khint_t bits, count; \ + khint32_t *used; \ + khkey_t *keys; \ + } HType; + +#define __KHASHL_PROTOTYPES(HType, prefix, khkey_t) \ + extern HType *prefix##_init(void); \ + extern void prefix##_destroy(HType *h); \ + extern void prefix##_clear(HType *h); \ + extern khint_t prefix##_getp(const HType *h, const khkey_t *key); \ + extern int prefix##_resize(HType *h, khint_t new_n_buckets); \ + extern khint_t prefix##_putp(HType *h, const khkey_t *key, int *absent); \ + extern void prefix##_del(HType *h, khint_t k); + +#define __KHASHL_IMPL_BASIC(SCOPE, HType, prefix) \ + SCOPE HType *prefix##_init(void) { \ + return (HType*)kcalloc(1, sizeof(HType)); \ + } \ + SCOPE void prefix##_destroy(HType *h) { \ + if (!h) return; \ + kfree((void *)h->keys); kfree(h->used); \ + kfree(h); \ + } \ + SCOPE void prefix##_clear(HType *h) { \ + if (h && h->used) { \ + uint32_t n_buckets = 1U << h->bits; \ + memset(h->used, 0, __kh_fsize(n_buckets) * sizeof(khint32_t)); \ + h->count = 0; \ + } \ + } +#define __KHASHL_IMPL_S_L(SCOPE, HType, prefix, khkey_t) \ + SCOPE khint_t prefix##_save(HType *h, FILE* fp) { \ + if (!h) return 0; \ + uint8_t ff; \ + khint_t n_buckets = (h->keys? 1U<bits : 0U); \ + fwrite(&n_buckets, sizeof(n_buckets), 1, fp); \ + fwrite(&h->bits, sizeof(h->bits), 1, fp); \ + fwrite(&h->count, sizeof(h->count), 1, fp); \ + ff = h->used? 1:0; fwrite(&ff, sizeof(ff), 1, fp); \ + if(ff) fwrite(h->used, sizeof(khint32_t), __kh_fsize(n_buckets), fp); \ + ff = h->keys? 1:0; fwrite(&ff, sizeof(ff), 1, fp); \ + if(ff) fwrite(h->keys, sizeof(khkey_t), n_buckets, fp); \ + return 1; \ + } \ + SCOPE khint_t prefix##_load(HType **h, FILE* fp) { \ + (*h) = prefix##_init(); \ + khint_t n_buckets; \ + uint64_t flag = 0;\ + uint8_t ff; \ + flag += fread(&n_buckets, sizeof(n_buckets), 1, fp); \ + flag += fread(&(*h)->bits, sizeof((*h)->bits), 1, fp); \ + flag += fread(&(*h)->count, sizeof((*h)->count), 1, fp); \ + flag += fread(&ff, sizeof(ff), 1, fp); \ + if(ff) {\ + (*h)->used = (khint32_t*)kmalloc(__kh_fsize(n_buckets) * sizeof(khint32_t)); \ + flag += fread((*h)->used, sizeof(khint32_t), __kh_fsize(n_buckets), fp); }\ + flag += fread(&ff, sizeof(ff), 1, fp); \ + if(ff) {\ + (*h)->keys = (khkey_t*)kmalloc(n_buckets * sizeof(khkey_t)); \ + flag += fread((*h)->keys, sizeof(khkey_t), n_buckets, fp); }\ + return 1; \ + } \ + +#define __KHASHL_IMPL_GET(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ + SCOPE khint_t prefix##_getp(const HType *h, const khkey_t *key) { \ + khint_t i, last, n_buckets, mask; \ + if (h->keys == 0) return 0; \ + n_buckets = 1U << h->bits; \ + mask = n_buckets - 1U; \ + i = last = __kh_h2b(__hash_fn(*key), h->bits); \ + while (__kh_used(h->used, i) && !__hash_eq(h->keys[i], *key)) { \ + i = (i + 1U) & mask; \ + if (i == last) return n_buckets; \ + } \ + return !__kh_used(h->used, i)? n_buckets : i; \ + } \ + SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { return prefix##_getp(h, &key); } + +#define __KHASHL_IMPL_RESIZE(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ + SCOPE int prefix##_resize(HType *h, khint_t new_n_buckets) { \ + khint32_t *new_used = 0; \ + khint_t j = 0, x = new_n_buckets, n_buckets, new_bits, new_mask; \ + while ((x >>= 1) != 0) ++j; \ + if (new_n_buckets & (new_n_buckets - 1)) ++j; \ + new_bits = j > 2? j : 2; \ + new_n_buckets = 1U << new_bits; \ + if (h->count > (new_n_buckets>>1) + (new_n_buckets>>2)) return 0; /* requested size is too small */ \ + new_used = (khint32_t*)kmalloc(__kh_fsize(new_n_buckets) * sizeof(khint32_t)); \ + memset(new_used, 0, __kh_fsize(new_n_buckets) * sizeof(khint32_t)); \ + if (!new_used) return -1; /* not enough memory */ \ + n_buckets = h->keys? 1U<bits : 0U; \ + if (n_buckets < new_n_buckets) { /* expand */ \ + khkey_t *new_keys = (khkey_t*)krealloc((void*)h->keys, new_n_buckets * sizeof(khkey_t)); \ + if (!new_keys) { kfree(new_used); return -1; } \ + h->keys = new_keys; \ + } /* otherwise shrink */ \ + new_mask = new_n_buckets - 1; \ + for (j = 0; j != n_buckets; ++j) { \ + khkey_t key; \ + if (!__kh_used(h->used, j)) continue; \ + key = h->keys[j]; \ + __kh_set_unused(h->used, j); \ + while (1) { /* kick-out process; sort of like in Cuckoo hashing */ \ + khint_t i; \ + i = __kh_h2b(__hash_fn(key), new_bits); \ + while (__kh_used(new_used, i)) i = (i + 1) & new_mask; \ + __kh_set_used(new_used, i); \ + if (i < n_buckets && __kh_used(h->used, i)) { /* kick out the existing element */ \ + { khkey_t tmp = h->keys[i]; h->keys[i] = key; key = tmp; } \ + __kh_set_unused(h->used, i); /* mark it as deleted in the old hash table */ \ + } else { /* write the element and jump out of the loop */ \ + h->keys[i] = key; \ + break; \ + } \ + } \ + } \ + if (n_buckets > new_n_buckets) /* shrink the hash table */ \ + h->keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \ + kfree(h->used); /* free the working space */ \ + h->used = new_used, h->bits = new_bits; \ + return 0; \ + } + +#define __KHASHL_IMPL_PUT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ + SCOPE khint_t prefix##_putp(HType *h, const khkey_t *key, int *absent) { \ + khint_t n_buckets, i, last, mask; \ + n_buckets = h->keys? 1U<bits : 0U; \ + *absent = -1; \ + if (h->count >= (n_buckets>>1) + (n_buckets>>2)) { /* rehashing */ \ + if (prefix##_resize(h, n_buckets + 1U) < 0) \ + return n_buckets; \ + n_buckets = 1U<bits; \ + } /* TODO: to implement automatically shrinking; resize() already support shrinking */ \ + mask = n_buckets - 1; \ + i = last = __kh_h2b(__hash_fn(*key), h->bits); \ + while (__kh_used(h->used, i) && !__hash_eq(h->keys[i], *key)) { \ + i = (i + 1U) & mask; \ + if (i == last) break; \ + } \ + if (!__kh_used(h->used, i)) { /* not present at all */ \ + h->keys[i] = *key; \ + __kh_set_used(h->used, i); \ + ++h->count; \ + *absent = 1; \ + } else *absent = 0; /* Don't touch h->keys[i] if present */ \ + return i; \ + } \ + SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { return prefix##_putp(h, &key, absent); } + +#define __KHASHL_IMPL_DEL(SCOPE, HType, prefix, khkey_t, __hash_fn) \ + SCOPE int prefix##_del(HType *h, khint_t i) { \ + khint_t j = i, k, mask, n_buckets; \ + if (h->keys == 0) return 0; \ + n_buckets = 1U<bits; \ + mask = n_buckets - 1U; \ + while (1) { \ + j = (j + 1U) & mask; \ + if (j == i || !__kh_used(h->used, j)) break; /* j==i only when the table is completely full */ \ + k = __kh_h2b(__hash_fn(h->keys[j]), h->bits); \ + if ((j > i && (k <= i || k > j)) || (j < i && (k <= i && k > j))) \ + h->keys[i] = h->keys[j], i = j; \ + } \ + __kh_set_unused(h->used, i); \ + --h->count; \ + return 1; \ + } + +#define KHASHL_DECLARE(HType, prefix, khkey_t) \ + __KHASHL_TYPE(HType, khkey_t) \ + __KHASHL_PROTOTYPES(HType, prefix, khkey_t) + +#define KHASHL_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ + __KHASHL_TYPE(HType, khkey_t) \ + __KHASHL_IMPL_BASIC(SCOPE, HType, prefix) \ + __KHASHL_IMPL_S_L(SCOPE, HType, prefix, khkey_t) \ + __KHASHL_IMPL_GET(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ + __KHASHL_IMPL_RESIZE(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ + __KHASHL_IMPL_PUT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ + __KHASHL_IMPL_DEL(SCOPE, HType, prefix, khkey_t, __hash_fn) + +/***************************** + * More convenient interface * + *****************************/ + +#define __kh_packed __attribute__ ((__packed__)) +#define __kh_cached_hash(x) ((x).hash) + +#define KHASHL_SET_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ + typedef struct { khkey_t key; } __kh_packed HType##_s_bucket_t; \ + static kh_inline khint_t prefix##_s_hash(HType##_s_bucket_t x) { return __hash_fn(x.key); } \ + static kh_inline int prefix##_s_eq(HType##_s_bucket_t x, HType##_s_bucket_t y) { return __hash_eq(x.key, y.key); } \ + KHASHL_INIT(KH_LOCAL, HType, prefix##_s, HType##_s_bucket_t, prefix##_s_hash, prefix##_s_eq) \ + SCOPE HType *prefix##_init(void) { return prefix##_s_init(); } \ + SCOPE void prefix##_destroy(HType *h) { prefix##_s_destroy(h); } \ + SCOPE khint_t prefix##_save(HType *h, FILE* fp) { return prefix##_s_save(h, fp); } \ + SCOPE khint_t prefix##_load(HType **h, FILE* fp) { return prefix##_s_load(h, fp); } \ + SCOPE void prefix##_resize(HType *h, khint_t new_n_buckets) { prefix##_s_resize(h, new_n_buckets); } \ + SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_s_bucket_t t; t.key = key; return prefix##_s_getp(h, &t); } \ + SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_s_del(h, k); } \ + SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_s_bucket_t t; t.key = key; return prefix##_s_putp(h, &t, absent); } + +#define KHASHL_MAP_INIT(SCOPE, HType, prefix, khkey_t, kh_val_t, __hash_fn, __hash_eq) \ + typedef struct { khkey_t key; kh_val_t val; } __kh_packed HType##_m_bucket_t; \ + static kh_inline khint_t prefix##_m_hash(HType##_m_bucket_t x) { return __hash_fn(x.key); } \ + static kh_inline int prefix##_m_eq(HType##_m_bucket_t x, HType##_m_bucket_t y) { return __hash_eq(x.key, y.key); } \ + KHASHL_INIT(KH_LOCAL, HType, prefix##_m, HType##_m_bucket_t, prefix##_m_hash, prefix##_m_eq) \ + SCOPE HType *prefix##_init(void) { return prefix##_m_init(); } \ + SCOPE void prefix##_destroy(HType *h) { prefix##_m_destroy(h); } \ + SCOPE khint_t prefix##_save(HType *h, FILE* fp) { return prefix##_m_save(h, fp); } \ + SCOPE khint_t prefix##_load(HType **h, FILE* fp) { return prefix##_m_load(h, fp); } \ + SCOPE void prefix##_resize(HType *h, khint_t new_n_buckets) { prefix##_m_resize(h, new_n_buckets); } \ + SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_m_bucket_t t; t.key = key; return prefix##_m_getp(h, &t); } \ + SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_m_del(h, k); } \ + SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_m_bucket_t t; t.key = key; return prefix##_m_putp(h, &t, absent); } + +#define KHASHL_CSET_INIT(SCOPE, HType, prefix, khkey_t, __hash_fn, __hash_eq) \ + typedef struct { khkey_t key; khint_t hash; } __kh_packed HType##_cs_bucket_t; \ + static kh_inline int prefix##_cs_eq(HType##_cs_bucket_t x, HType##_cs_bucket_t y) { return x.hash == y.hash && __hash_eq(x.key, y.key); } \ + KHASHL_INIT(KH_LOCAL, HType, prefix##_cs, HType##_cs_bucket_t, __kh_cached_hash, prefix##_cs_eq) \ + SCOPE HType *prefix##_init(void) { return prefix##_cs_init(); } \ + SCOPE void prefix##_destroy(HType *h) { prefix##_cs_destroy(h); } \ + SCOPE khint_t prefix##_save(HType *h, FILE* fp) { return prefix##_cs_save(h, fp); } \ + SCOPE khint_t prefix##_load(HType **h, FILE* fp) { return prefix##_cs_load(h, fp); } \ + SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_cs_bucket_t t; t.key = key; t.hash = __hash_fn(key); return prefix##_cs_getp(h, &t); } \ + SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_cs_del(h, k); } \ + SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_cs_bucket_t t; t.key = key, t.hash = __hash_fn(key); return prefix##_cs_putp(h, &t, absent); } + +#define KHASHL_CMAP_INIT(SCOPE, HType, prefix, khkey_t, kh_val_t, __hash_fn, __hash_eq) \ + typedef struct { khkey_t key; kh_val_t val; khint_t hash; } __kh_packed HType##_cm_bucket_t; \ + static kh_inline int prefix##_cm_eq(HType##_cm_bucket_t x, HType##_cm_bucket_t y) { return x.hash == y.hash && __hash_eq(x.key, y.key); } \ + KHASHL_INIT(KH_LOCAL, HType, prefix##_cm, HType##_cm_bucket_t, __kh_cached_hash, prefix##_cm_eq) \ + SCOPE HType *prefix##_init(void) { return prefix##_cm_init(); } \ + SCOPE void prefix##_destroy(HType *h) { prefix##_cm_destroy(h); } \ + SCOPE khint_t prefix##_save(HType *h, FILE* fp) { return prefix##_cm_save(h, fp); } \ + SCOPE khint_t prefix##_load(HType **h, FILE* fp) { return prefix##_cm_load(h, fp); } \ + SCOPE khint_t prefix##_get(const HType *h, khkey_t key) { HType##_cm_bucket_t t; t.key = key; t.hash = __hash_fn(key); return prefix##_cm_getp(h, &t); } \ + SCOPE int prefix##_del(HType *h, khint_t k) { return prefix##_cm_del(h, k); } \ + SCOPE khint_t prefix##_put(HType *h, khkey_t key, int *absent) { HType##_cm_bucket_t t; t.key = key, t.hash = __hash_fn(key); return prefix##_cm_putp(h, &t, absent); } + +/************************** + * Public macro functions * + **************************/ + +#define kh_bucket(h, x) ((h)->keys[x]) +#define kh_size(h) ((h)->count) +#define kh_capacity(h) ((h)->keys? 1U<<(h)->bits : 0U) +#define kh_end(h) kh_capacity(h) + +#define kh_key(h, x) ((h)->keys[x].key) +#define kh_val(h, x) ((h)->keys[x].val) +#define kh_exist(h, x) __kh_used((h)->used, (x)) + +/************************************** + * Common hash and equality functions * + **************************************/ + +#define kh_eq_generic(a, b) ((a) == (b)) +#define kh_eq_str(a, b) (strcmp((a), (b)) == 0) +#define kh_hash_dummy(x) ((khint_t)(x)) + +static kh_inline khint_t kh_hash_uint32(khint_t key) { + key += ~(key << 15); + key ^= (key >> 10); + key += (key << 3); + key ^= (key >> 6); + key += ~(key << 11); + key ^= (key >> 16); + return key; +} + +static kh_inline khint_t kh_hash_uint64(khint64_t key) { + key = ~key + (key << 21); + key = key ^ key >> 24; + key = (key + (key << 3)) + (key << 8); + key = key ^ key >> 14; + key = (key + (key << 2)) + (key << 4); + key = key ^ key >> 28; + key = key + (key << 31); + return (khint_t)key; +} + +static kh_inline khint_t kh_hash_str(const char *s) { + khint_t h = (khint_t)*s; + if (h) for (++s ; *s; ++s) h = (h << 5) - h + (khint_t)*s; + return h; +} + +#endif /* __AC_KHASHL_H */ diff --git a/kseq.h b/kseq.h index 4360f82..7c04170 100644 --- a/kseq.h +++ b/kseq.h @@ -1,251 +1,251 @@ -/* The MIT License - - Copyright (c) 2008, 2009, 2011 Attractive Chaos - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - -/* Last Modified: 05MAR2012 */ - -#ifndef AC_KSEQ_H -#define AC_KSEQ_H - -#include -#include -#include - -#define KS_SEP_SPACE 0 // isspace(): \t, \n, \v, \f, \r -#define KS_SEP_TAB 1 // isspace() && !' ' -#define KS_SEP_LINE 2 // line separator: "\n" (Unix) or "\r\n" (Windows) -#define KS_SEP_MAX 2 - -#ifndef klib_unused -#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) -#define klib_unused __attribute__ ((__unused__)) -#else -#define klib_unused -#endif -#endif /* klib_unused */ - -#define __KS_TYPE(type_t) \ - typedef struct __kstream_t { \ - unsigned char *buf; \ - int begin, end, is_eof; \ - type_t f; \ - } kstream_t; - -#define ks_err(ks) ((ks)->end == -1) -#define ks_eof(ks) ((ks)->is_eof && (ks)->begin >= (ks)->end) -#define ks_rewind(ks) ((ks)->is_eof = (ks)->begin = (ks)->end = 0) - -#define __KS_BASIC(type_t, __bufsize) \ - static inline kstream_t *ks_init(type_t f) \ - { \ - kstream_t *ks = (kstream_t*)calloc(1, sizeof(kstream_t)); \ - ks->f = f; \ - ks->buf = (unsigned char*)malloc(__bufsize); \ - return ks; \ - } \ - static inline void ks_destroy(kstream_t *ks) \ - { \ - if (ks) { \ - free(ks->buf); \ - free(ks); \ - } \ - } - -#define __KS_GETC(__read, __bufsize) \ - static inline klib_unused int ks_getc(kstream_t *ks) \ - { \ - if (ks_err(ks)) return -3; \ - if (ks->is_eof && ks->begin >= ks->end) return -1; \ - if (ks->begin >= ks->end) { \ - ks->begin = 0; \ - ks->end = __read(ks->f, ks->buf, __bufsize); \ - if (ks->end == 0) { ks->is_eof = 1; return -1;} \ - if (ks->end == -1) { ks->is_eof = 1; return -3;}\ - } \ - return (int)ks->buf[ks->begin++]; \ - } - -#ifndef KSTRING_T -#define KSTRING_T kstring_t -typedef struct __kstring_t { - size_t l, m; - char *s; -} kstring_t; -#endif - -#ifndef kroundup32 -#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) -#endif - -#define __KS_GETUNTIL(__read, __bufsize) \ - static int ks_getuntil2(kstream_t *ks, int delimiter, kstring_t *str, int *dret, int append) \ - { \ - int gotany = 0; \ - if (dret) *dret = 0; \ - str->l = append? str->l : 0; \ - for (;;) { \ - int i; \ - if (ks_err(ks)) return -3; \ - if (ks->begin >= ks->end) { \ - if (!ks->is_eof) { \ - ks->begin = 0; \ - ks->end = __read(ks->f, ks->buf, __bufsize); \ - if (ks->end == 0) { ks->is_eof = 1; break; } \ - if (ks->end == -1) { ks->is_eof = 1; return -3; } \ - } else break; \ - } \ - if (delimiter == KS_SEP_LINE) { \ - for (i = ks->begin; i < ks->end; ++i) \ - if (ks->buf[i] == '\n') break; \ - } else if (delimiter > KS_SEP_MAX) { \ - for (i = ks->begin; i < ks->end; ++i) \ - if (ks->buf[i] == delimiter) break; \ - } else if (delimiter == KS_SEP_SPACE) { \ - for (i = ks->begin; i < ks->end; ++i) \ - if (isspace(ks->buf[i])) break; \ - } else if (delimiter == KS_SEP_TAB) { \ - for (i = ks->begin; i < ks->end; ++i) \ - if (isspace(ks->buf[i]) && ks->buf[i] != ' ') break; \ - } else i = 0; /* never come to here! */ \ - if (str->m - str->l < (size_t)(i - ks->begin + 1)) { \ - str->m = str->l + (i - ks->begin) + 1; \ - kroundup32(str->m); \ - str->s = (char*)realloc(str->s, str->m); \ - } \ - gotany = 1; \ - memcpy(str->s + str->l, ks->buf + ks->begin, i - ks->begin); \ - str->l = str->l + (i - ks->begin); \ - ks->begin = i + 1; \ - if (i < ks->end) { \ - if (dret) *dret = ks->buf[i]; \ - break; \ - } \ - } \ - if (!gotany && ks_eof(ks)) return -1; \ - if (str->s == 0) { \ - str->m = 1; \ - str->s = (char*)calloc(1, 1); \ - } else if (delimiter == KS_SEP_LINE && str->l > 1 && str->s[str->l-1] == '\r') --str->l; \ - str->s[str->l] = '\0'; \ - return str->l; \ - } \ - static inline int ks_getuntil(kstream_t *ks, int delimiter, kstring_t *str, int *dret) \ - { return ks_getuntil2(ks, delimiter, str, dret, 0); } - -#define KSTREAM_INIT(type_t, __read, __bufsize) \ - __KS_TYPE(type_t) \ - __KS_BASIC(type_t, __bufsize) \ - __KS_GETC(__read, __bufsize) \ - __KS_GETUNTIL(__read, __bufsize) - -#define kseq_rewind(ks) ((ks)->last_char = (ks)->f->is_eof = (ks)->f->begin = (ks)->f->end = 0) - -#define __KSEQ_BASIC(SCOPE, type_t) \ - SCOPE kseq_t *kseq_init(type_t fd) \ - { \ - kseq_t *s = (kseq_t*)calloc(1, sizeof(kseq_t)); \ - s->f = ks_init(fd); \ - return s; \ - } \ - SCOPE void kseq_destroy(kseq_t *ks) \ - { \ - if (!ks) return; \ - free(ks->name.s); free(ks->comment.s); free(ks->seq.s); free(ks->qual.s); \ - ks_destroy(ks->f); \ - free(ks); \ - } - -/* Return value: - >=0 length of the sequence (normal) - -1 end-of-file - -2 truncated quality string - -3 error reading stream - */ -#define __KSEQ_READ(SCOPE) \ - SCOPE int kseq_read(kseq_t *seq) \ - { \ - int c,r; \ - kstream_t *ks = seq->f; \ - if (seq->last_char == 0) { /* then jump to the next header line */ \ - while ((c = ks_getc(ks)) >= 0 && c != '>' && c != '@'); \ - if (c < 0) return c; /* end of file or error*/ \ - seq->last_char = c; \ - } /* else: the first header char has been read in the previous call */ \ - seq->comment.l = seq->seq.l = seq->qual.l = 0; /* reset all members */ \ - if ((r=ks_getuntil(ks, 0, &seq->name, &c)) < 0) return r; /* normal exit: EOF or error */ \ - if (c != '\n') ks_getuntil(ks, KS_SEP_LINE, &seq->comment, 0); /* read FASTA/Q comment */ \ - if (seq->seq.s == 0) { /* we can do this in the loop below, but that is slower */ \ - seq->seq.m = 256; \ - seq->seq.s = (char*)malloc(seq->seq.m); \ - } \ - while ((c = ks_getc(ks)) >= 0 && c != '>' && c != '+' && c != '@') { \ - if (c == '\n') continue; /* skip empty lines */ \ - seq->seq.s[seq->seq.l++] = c; /* this is safe: we always have enough space for 1 char */ \ - ks_getuntil2(ks, KS_SEP_LINE, &seq->seq, 0, 1); /* read the rest of the line */ \ - } \ - if (c == '>' || c == '@') seq->last_char = c; /* the first header char has been read */ \ - if (seq->seq.l + 1 >= seq->seq.m) { /* seq->seq.s[seq->seq.l] below may be out of boundary */ \ - seq->seq.m = seq->seq.l + 2; \ - kroundup32(seq->seq.m); /* rounded to the next closest 2^k */ \ - seq->seq.s = (char*)realloc(seq->seq.s, seq->seq.m); \ - } \ - seq->seq.s[seq->seq.l] = 0; /* null terminated string */ \ - if (c != '+') return seq->seq.l; /* FASTA */ \ - if (seq->qual.m < seq->seq.m) { /* allocate memory for qual in case insufficient */ \ - seq->qual.m = seq->seq.m; \ - seq->qual.s = (char*)realloc(seq->qual.s, seq->qual.m); \ - } \ - while ((c = ks_getc(ks)) >= 0 && c != '\n'); /* skip the rest of '+' line */ \ - if (c == -1) return -2; /* error: no quality string */ \ - while ((c = ks_getuntil2(ks, KS_SEP_LINE, &seq->qual, 0, 1) >= 0 && seq->qual.l < seq->seq.l)); \ - if (c == -3) return -3; /* stream error */ \ - seq->last_char = 0; /* we have not come to the next header line */ \ - if (seq->seq.l != seq->qual.l) return -2; /* error: qual string is of a different length */ \ - return seq->seq.l; \ - } - -#define __KSEQ_TYPE(type_t) \ - typedef struct { \ - kstring_t name, comment, seq, qual; \ - int last_char; \ - kstream_t *f; \ - uint64_t ID; \ - } kseq_t; - -#define KSEQ_INIT2(SCOPE, type_t, __read) \ - KSTREAM_INIT(type_t, __read, 16384) \ - __KSEQ_TYPE(type_t) \ - __KSEQ_BASIC(SCOPE, type_t) \ - __KSEQ_READ(SCOPE) - -#define KSEQ_INIT(type_t, __read) KSEQ_INIT2(static klib_unused, type_t, __read) - -#define KSEQ_DECLARE(type_t) \ - __KS_TYPE(type_t) \ - __KSEQ_TYPE(type_t) \ - extern kseq_t *kseq_init(type_t fd); \ - void kseq_destroy(kseq_t *ks); \ - int kseq_read(kseq_t *seq); - -#endif +/* The MIT License + + Copyright (c) 2008, 2009, 2011 Attractive Chaos + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +/* Last Modified: 05MAR2012 */ + +#ifndef AC_KSEQ_H +#define AC_KSEQ_H + +#include +#include +#include + +#define KS_SEP_SPACE 0 // isspace(): \t, \n, \v, \f, \r +#define KS_SEP_TAB 1 // isspace() && !' ' +#define KS_SEP_LINE 2 // line separator: "\n" (Unix) or "\r\n" (Windows) +#define KS_SEP_MAX 2 + +#ifndef klib_unused +#if (defined __clang__ && __clang_major__ >= 3) || (defined __GNUC__ && __GNUC__ >= 3) +#define klib_unused __attribute__ ((__unused__)) +#else +#define klib_unused +#endif +#endif /* klib_unused */ + +#define __KS_TYPE(type_t) \ + typedef struct __kstream_t { \ + unsigned char *buf; \ + int begin, end, is_eof; \ + type_t f; \ + } kstream_t; + +#define ks_err(ks) ((ks)->end == -1) +#define ks_eof(ks) ((ks)->is_eof && (ks)->begin >= (ks)->end) +#define ks_rewind(ks) ((ks)->is_eof = (ks)->begin = (ks)->end = 0) + +#define __KS_BASIC(type_t, __bufsize) \ + static inline kstream_t *ks_init(type_t f) \ + { \ + kstream_t *ks = (kstream_t*)calloc(1, sizeof(kstream_t)); \ + ks->f = f; \ + ks->buf = (unsigned char*)malloc(__bufsize); \ + return ks; \ + } \ + static inline void ks_destroy(kstream_t *ks) \ + { \ + if (ks) { \ + free(ks->buf); \ + free(ks); \ + } \ + } + +#define __KS_GETC(__read, __bufsize) \ + static inline klib_unused int ks_getc(kstream_t *ks) \ + { \ + if (ks_err(ks)) return -3; \ + if (ks->is_eof && ks->begin >= ks->end) return -1; \ + if (ks->begin >= ks->end) { \ + ks->begin = 0; \ + ks->end = __read(ks->f, ks->buf, __bufsize); \ + if (ks->end == 0) { ks->is_eof = 1; return -1;} \ + if (ks->end == -1) { ks->is_eof = 1; return -3;}\ + } \ + return (int)ks->buf[ks->begin++]; \ + } + +#ifndef KSTRING_T +#define KSTRING_T kstring_t +typedef struct __kstring_t { + size_t l, m; + char *s; +} kstring_t; +#endif + +#ifndef kroundup32 +#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) +#endif + +#define __KS_GETUNTIL(__read, __bufsize) \ + static int ks_getuntil2(kstream_t *ks, int delimiter, kstring_t *str, int *dret, int append) \ + { \ + int gotany = 0; \ + if (dret) *dret = 0; \ + str->l = append? str->l : 0; \ + for (;;) { \ + int i; \ + if (ks_err(ks)) return -3; \ + if (ks->begin >= ks->end) { \ + if (!ks->is_eof) { \ + ks->begin = 0; \ + ks->end = __read(ks->f, ks->buf, __bufsize); \ + if (ks->end == 0) { ks->is_eof = 1; break; } \ + if (ks->end == -1) { ks->is_eof = 1; return -3; } \ + } else break; \ + } \ + if (delimiter == KS_SEP_LINE) { \ + for (i = ks->begin; i < ks->end; ++i) \ + if (ks->buf[i] == '\n') break; \ + } else if (delimiter > KS_SEP_MAX) { \ + for (i = ks->begin; i < ks->end; ++i) \ + if (ks->buf[i] == delimiter) break; \ + } else if (delimiter == KS_SEP_SPACE) { \ + for (i = ks->begin; i < ks->end; ++i) \ + if (isspace(ks->buf[i])) break; \ + } else if (delimiter == KS_SEP_TAB) { \ + for (i = ks->begin; i < ks->end; ++i) \ + if (isspace(ks->buf[i]) && ks->buf[i] != ' ') break; \ + } else i = 0; /* never come to here! */ \ + if (str->m - str->l < (size_t)(i - ks->begin + 1)) { \ + str->m = str->l + (i - ks->begin) + 1; \ + kroundup32(str->m); \ + str->s = (char*)realloc(str->s, str->m); \ + } \ + gotany = 1; \ + memcpy(str->s + str->l, ks->buf + ks->begin, i - ks->begin); \ + str->l = str->l + (i - ks->begin); \ + ks->begin = i + 1; \ + if (i < ks->end) { \ + if (dret) *dret = ks->buf[i]; \ + break; \ + } \ + } \ + if (!gotany && ks_eof(ks)) return -1; \ + if (str->s == 0) { \ + str->m = 1; \ + str->s = (char*)calloc(1, 1); \ + } else if (delimiter == KS_SEP_LINE && str->l > 1 && str->s[str->l-1] == '\r') --str->l; \ + str->s[str->l] = '\0'; \ + return str->l; \ + } \ + static inline int ks_getuntil(kstream_t *ks, int delimiter, kstring_t *str, int *dret) \ + { return ks_getuntil2(ks, delimiter, str, dret, 0); } + +#define KSTREAM_INIT(type_t, __read, __bufsize) \ + __KS_TYPE(type_t) \ + __KS_BASIC(type_t, __bufsize) \ + __KS_GETC(__read, __bufsize) \ + __KS_GETUNTIL(__read, __bufsize) + +#define kseq_rewind(ks) ((ks)->last_char = (ks)->f->is_eof = (ks)->f->begin = (ks)->f->end = 0) + +#define __KSEQ_BASIC(SCOPE, type_t) \ + SCOPE kseq_t *kseq_init(type_t fd) \ + { \ + kseq_t *s = (kseq_t*)calloc(1, sizeof(kseq_t)); \ + s->f = ks_init(fd); \ + return s; \ + } \ + SCOPE void kseq_destroy(kseq_t *ks) \ + { \ + if (!ks) return; \ + free(ks->name.s); free(ks->comment.s); free(ks->seq.s); free(ks->qual.s); \ + ks_destroy(ks->f); \ + free(ks); \ + } + +/* Return value: + >=0 length of the sequence (normal) + -1 end-of-file + -2 truncated quality string + -3 error reading stream + */ +#define __KSEQ_READ(SCOPE) \ + SCOPE int kseq_read(kseq_t *seq) \ + { \ + int c,r; \ + kstream_t *ks = seq->f; \ + if (seq->last_char == 0) { /* then jump to the next header line */ \ + while ((c = ks_getc(ks)) >= 0 && c != '>' && c != '@'); \ + if (c < 0) return c; /* end of file or error*/ \ + seq->last_char = c; \ + } /* else: the first header char has been read in the previous call */ \ + seq->comment.l = seq->seq.l = seq->qual.l = 0; /* reset all members */ \ + if ((r=ks_getuntil(ks, 0, &seq->name, &c)) < 0) return r; /* normal exit: EOF or error */ \ + if (c != '\n') ks_getuntil(ks, KS_SEP_LINE, &seq->comment, 0); /* read FASTA/Q comment */ \ + if (seq->seq.s == 0) { /* we can do this in the loop below, but that is slower */ \ + seq->seq.m = 256; \ + seq->seq.s = (char*)malloc(seq->seq.m); \ + } \ + while ((c = ks_getc(ks)) >= 0 && c != '>' && c != '+' && c != '@') { \ + if (c == '\n') continue; /* skip empty lines */ \ + seq->seq.s[seq->seq.l++] = c; /* this is safe: we always have enough space for 1 char */ \ + ks_getuntil2(ks, KS_SEP_LINE, &seq->seq, 0, 1); /* read the rest of the line */ \ + } \ + if (c == '>' || c == '@') seq->last_char = c; /* the first header char has been read */ \ + if (seq->seq.l + 1 >= seq->seq.m) { /* seq->seq.s[seq->seq.l] below may be out of boundary */ \ + seq->seq.m = seq->seq.l + 2; \ + kroundup32(seq->seq.m); /* rounded to the next closest 2^k */ \ + seq->seq.s = (char*)realloc(seq->seq.s, seq->seq.m); \ + } \ + seq->seq.s[seq->seq.l] = 0; /* null terminated string */ \ + if (c != '+') return seq->seq.l; /* FASTA */ \ + if (seq->qual.m < seq->seq.m) { /* allocate memory for qual in case insufficient */ \ + seq->qual.m = seq->seq.m; \ + seq->qual.s = (char*)realloc(seq->qual.s, seq->qual.m); \ + } \ + while ((c = ks_getc(ks)) >= 0 && c != '\n'); /* skip the rest of '+' line */ \ + if (c == -1) return -2; /* error: no quality string */ \ + while ((c = ks_getuntil2(ks, KS_SEP_LINE, &seq->qual, 0, 1) >= 0 && seq->qual.l < seq->seq.l)); \ + if (c == -3) return -3; /* stream error */ \ + seq->last_char = 0; /* we have not come to the next header line */ \ + if (seq->seq.l != seq->qual.l) return -2; /* error: qual string is of a different length */ \ + return seq->seq.l; \ + } + +#define __KSEQ_TYPE(type_t) \ + typedef struct { \ + kstring_t name, comment, seq, qual; \ + int last_char; \ + kstream_t *f; \ + uint64_t ID; \ + } kseq_t; + +#define KSEQ_INIT2(SCOPE, type_t, __read) \ + KSTREAM_INIT(type_t, __read, 16384) \ + __KSEQ_TYPE(type_t) \ + __KSEQ_BASIC(SCOPE, type_t) \ + __KSEQ_READ(SCOPE) + +#define KSEQ_INIT(type_t, __read) KSEQ_INIT2(static klib_unused, type_t, __read) + +#define KSEQ_DECLARE(type_t) \ + __KS_TYPE(type_t) \ + __KSEQ_TYPE(type_t) \ + extern kseq_t *kseq_init(type_t fd); \ + void kseq_destroy(kseq_t *ks); \ + int kseq_read(kseq_t *seq); + +#endif diff --git a/ksort.h b/ksort.h index 828abc6..475b1fc 100644 --- a/ksort.h +++ b/ksort.h @@ -1,223 +1,223 @@ -/* The MIT License - - Copyright (c) 2008, 2011 Attractive Chaos - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - -// This is a simplified version of ksort.h - -#ifndef AC_KSORT_H -#define AC_KSORT_H - -#include -#include - -typedef struct { - void *left, *right; - int depth; -} ks_isort_stack_t; - -#define member_size(type, member) sizeof(((type *)0)->member) - -#define KSORT_SWAP(type_t, a, b) { register type_t t=(a); (a)=(b); (b)=t; } - -#define KSORT_INIT(name, type_t, __sort_lt) \ - void ks_heapdown_##name(size_t i, size_t n, type_t l[]) \ - { \ - size_t k = i; \ - type_t tmp = l[i]; \ - while ((k = (k << 1) + 1) < n) { \ - if (k != n - 1 && __sort_lt(l[k], l[k+1])) ++k; \ - if (__sort_lt(l[k], tmp)) break; \ - l[i] = l[k]; i = k; \ - } \ - l[i] = tmp; \ - } \ - void ks_heapup_##name(size_t n, type_t l[]) \ - { \ - size_t i, k = n - 1; \ - type_t tmp = l[k]; \ - while (k) { \ - i = (k - 1) >> 1; \ - if (__sort_lt(tmp, l[i])) break; \ - l[k] = l[i]; k = i; \ - } \ - l[k] = tmp; \ - } \ - void ks_heapmake_##name(size_t lsize, type_t l[]) \ - { \ - size_t i; \ - for (i = (lsize >> 1) - 1; i != (size_t)(-1); --i) \ - ks_heapdown_##name(i, lsize, l); \ - } \ - void ks_heapsort_##name(size_t lsize, type_t l[]) \ - { \ - size_t i; \ - for (i = lsize - 1; i > 0; --i) { \ - type_t tmp; \ - tmp = *l; *l = l[i]; l[i] = tmp; ks_heapdown_##name(0, i, l); \ - } \ - } \ - static inline void __ks_insertsort_##name(type_t *s, type_t *t) \ - { \ - type_t *i, *j, swap_tmp; \ - for (i = s + 1; i < t; ++i) \ - for (j = i; j > s && __sort_lt(*j, *(j-1)); --j) { \ - swap_tmp = *j; *j = *(j-1); *(j-1) = swap_tmp; \ - } \ - } \ - void ks_combsort_##name(size_t n, type_t a[]) \ - { \ - const double shrink_factor = 1.2473309501039786540366528676643; \ - int do_swap; \ - size_t gap = n; \ - type_t tmp, *i, *j; \ - do { \ - if (gap > 2) { \ - gap = (size_t)(gap / shrink_factor); \ - if (gap == 9 || gap == 10) gap = 11; \ - } \ - do_swap = 0; \ - for (i = a; i < a + n - gap; ++i) { \ - j = i + gap; \ - if (__sort_lt(*j, *i)) { \ - tmp = *i; *i = *j; *j = tmp; \ - do_swap = 1; \ - } \ - } \ - } while (do_swap || gap > 2); \ - if (gap != 1) __ks_insertsort_##name(a, a + n); \ - } \ - void ks_introsort_##name(size_t n, type_t a[]) \ - { \ - int d; \ - ks_isort_stack_t *top, *stack; \ - type_t rp, swap_tmp; \ - type_t *s, *t, *i, *j, *k; \ - \ - if (n < 1) return; \ - else if (n == 2) { \ - if (__sort_lt(a[1], a[0])) { swap_tmp = a[0]; a[0] = a[1]; a[1] = swap_tmp; } \ - return; \ - } \ - for (d = 2; 1ul<>1) + 1; \ - if (__sort_lt(*k, *i)) { \ - if (__sort_lt(*k, *j)) k = j; \ - } else k = __sort_lt(*j, *i)? i : j; \ - rp = *k; \ - if (k != t) { swap_tmp = *k; *k = *t; *t = swap_tmp; } \ - for (;;) { \ - do ++i; while (__sort_lt(*i, rp)); \ - do --j; while (i <= j && __sort_lt(rp, *j)); \ - if (j <= i) break; \ - swap_tmp = *i; *i = *j; *j = swap_tmp; \ - } \ - swap_tmp = *i; *i = *t; *t = swap_tmp; \ - if (i-s > t-i) { \ - if (i-s > 16) { top->left = s; top->right = i-1; top->depth = d; ++top; } \ - s = t-i > 16? i+1 : t; \ - } else { \ - if (t-i > 16) { top->left = i+1; top->right = t; top->depth = d; ++top; } \ - t = i-s > 16? i-1 : s; \ - } \ - } else { \ - if (top == stack) { \ - free(stack); \ - __ks_insertsort_##name(a, a+n); \ - return; \ - } else { --top; s = (type_t*)top->left; t = (type_t*)top->right; d = top->depth; } \ - } \ - } \ - } - -#define ks_lt_generic(a, b) ((a) < (b)) -#define ks_lt_str(a, b) (strcmp((a), (b)) < 0) - -typedef const char *ksstr_t; - -#define KSORT_INIT_GENERIC(type_t) KSORT_INIT(type_t, type_t, ks_lt_generic) -#define KSORT_INIT_STR KSORT_INIT(str, ksstr_t, ks_lt_str) - -#define RS_MIN_SIZE 64 - -#define KRADIX_SORT_INIT(name, rstype_t, rskey, sizeof_key) \ - typedef struct { \ - rstype_t *b, *e; \ - } rsbucket_##name##_t; \ - void rs_insertsort_##name(rstype_t *beg, rstype_t *end) \ - { \ - rstype_t *i; \ - for (i = beg + 1; i < end; ++i) \ - if (rskey(*i) < rskey(*(i - 1))) { \ - rstype_t *j, tmp = *i; \ - for (j = i; j > beg && rskey(tmp) < rskey(*(j-1)); --j) \ - *j = *(j - 1); \ - *j = tmp; \ - } \ - } \ - void rs_sort_##name(rstype_t *beg, rstype_t *end, int n_bits, int s) \ - { \ - rstype_t *i; \ - int size = 1<b = k->e = beg; \ - for (i = beg; i != end; ++i) ++b[rskey(*i)>>s&m].e; \ - for (k = b + 1; k != be; ++k) \ - k->e += (k-1)->e - beg, k->b = (k-1)->e; \ - for (k = b; k != be;) { \ - if (k->b != k->e) { \ - rsbucket_##name##_t *l; \ - if ((l = b + (rskey(*k->b)>>s&m)) != k) { \ - rstype_t tmp = *k->b, swap; \ - do { \ - swap = tmp; tmp = *l->b; *l->b++ = swap; \ - l = b + (rskey(tmp)>>s&m); \ - } while (l != k); \ - *k->b++ = tmp; \ - } else ++k->b; \ - } else ++k; \ - } \ - for (b->b = beg, k = b + 1; k != be; ++k) k->b = (k-1)->e; \ - if (s) { \ - s = s > n_bits? s - n_bits : 0; \ - for (k = b; k != be; ++k) \ - if (k->e - k->b > RS_MIN_SIZE) rs_sort_##name(k->b, k->e, n_bits, s); \ - else if (k->e - k->b > 1) rs_insertsort_##name(k->b, k->e); \ - } \ - } \ - void radix_sort_##name(rstype_t *beg, rstype_t *end) \ - { \ - if (end - beg <= RS_MIN_SIZE) rs_insertsort_##name(beg, end); \ - else rs_sort_##name(beg, end, 8, sizeof_key * 8 - 8); \ - } - -#endif +/* The MIT License + + Copyright (c) 2008, 2011 Attractive Chaos + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +// This is a simplified version of ksort.h + +#ifndef AC_KSORT_H +#define AC_KSORT_H + +#include +#include + +typedef struct { + void *left, *right; + int depth; +} ks_isort_stack_t; + +#define member_size(type, member) sizeof(((type *)0)->member) + +#define KSORT_SWAP(type_t, a, b) { register type_t t=(a); (a)=(b); (b)=t; } + +#define KSORT_INIT(name, type_t, __sort_lt) \ + void ks_heapdown_##name(size_t i, size_t n, type_t l[]) \ + { \ + size_t k = i; \ + type_t tmp = l[i]; \ + while ((k = (k << 1) + 1) < n) { \ + if (k != n - 1 && __sort_lt(l[k], l[k+1])) ++k; \ + if (__sort_lt(l[k], tmp)) break; \ + l[i] = l[k]; i = k; \ + } \ + l[i] = tmp; \ + } \ + void ks_heapup_##name(size_t n, type_t l[]) \ + { \ + size_t i, k = n - 1; \ + type_t tmp = l[k]; \ + while (k) { \ + i = (k - 1) >> 1; \ + if (__sort_lt(tmp, l[i])) break; \ + l[k] = l[i]; k = i; \ + } \ + l[k] = tmp; \ + } \ + void ks_heapmake_##name(size_t lsize, type_t l[]) \ + { \ + size_t i; \ + for (i = (lsize >> 1) - 1; i != (size_t)(-1); --i) \ + ks_heapdown_##name(i, lsize, l); \ + } \ + void ks_heapsort_##name(size_t lsize, type_t l[]) \ + { \ + size_t i; \ + for (i = lsize - 1; i > 0; --i) { \ + type_t tmp; \ + tmp = *l; *l = l[i]; l[i] = tmp; ks_heapdown_##name(0, i, l); \ + } \ + } \ + static inline void __ks_insertsort_##name(type_t *s, type_t *t) \ + { \ + type_t *i, *j, swap_tmp; \ + for (i = s + 1; i < t; ++i) \ + for (j = i; j > s && __sort_lt(*j, *(j-1)); --j) { \ + swap_tmp = *j; *j = *(j-1); *(j-1) = swap_tmp; \ + } \ + } \ + void ks_combsort_##name(size_t n, type_t a[]) \ + { \ + const double shrink_factor = 1.2473309501039786540366528676643; \ + int do_swap; \ + size_t gap = n; \ + type_t tmp, *i, *j; \ + do { \ + if (gap > 2) { \ + gap = (size_t)(gap / shrink_factor); \ + if (gap == 9 || gap == 10) gap = 11; \ + } \ + do_swap = 0; \ + for (i = a; i < a + n - gap; ++i) { \ + j = i + gap; \ + if (__sort_lt(*j, *i)) { \ + tmp = *i; *i = *j; *j = tmp; \ + do_swap = 1; \ + } \ + } \ + } while (do_swap || gap > 2); \ + if (gap != 1) __ks_insertsort_##name(a, a + n); \ + } \ + void ks_introsort_##name(size_t n, type_t a[]) \ + { \ + int d; \ + ks_isort_stack_t *top, *stack; \ + type_t rp, swap_tmp; \ + type_t *s, *t, *i, *j, *k; \ + \ + if (n < 1) return; \ + else if (n == 2) { \ + if (__sort_lt(a[1], a[0])) { swap_tmp = a[0]; a[0] = a[1]; a[1] = swap_tmp; } \ + return; \ + } \ + for (d = 2; 1ul<>1) + 1; \ + if (__sort_lt(*k, *i)) { \ + if (__sort_lt(*k, *j)) k = j; \ + } else k = __sort_lt(*j, *i)? i : j; \ + rp = *k; \ + if (k != t) { swap_tmp = *k; *k = *t; *t = swap_tmp; } \ + for (;;) { \ + do ++i; while (__sort_lt(*i, rp)); \ + do --j; while (i <= j && __sort_lt(rp, *j)); \ + if (j <= i) break; \ + swap_tmp = *i; *i = *j; *j = swap_tmp; \ + } \ + swap_tmp = *i; *i = *t; *t = swap_tmp; \ + if (i-s > t-i) { \ + if (i-s > 16) { top->left = s; top->right = i-1; top->depth = d; ++top; } \ + s = t-i > 16? i+1 : t; \ + } else { \ + if (t-i > 16) { top->left = i+1; top->right = t; top->depth = d; ++top; } \ + t = i-s > 16? i-1 : s; \ + } \ + } else { \ + if (top == stack) { \ + free(stack); \ + __ks_insertsort_##name(a, a+n); \ + return; \ + } else { --top; s = (type_t*)top->left; t = (type_t*)top->right; d = top->depth; } \ + } \ + } \ + } + +#define ks_lt_generic(a, b) ((a) < (b)) +#define ks_lt_str(a, b) (strcmp((a), (b)) < 0) + +typedef const char *ksstr_t; + +#define KSORT_INIT_GENERIC(type_t) KSORT_INIT(type_t, type_t, ks_lt_generic) +#define KSORT_INIT_STR KSORT_INIT(str, ksstr_t, ks_lt_str) + +#define RS_MIN_SIZE 64 + +#define KRADIX_SORT_INIT(name, rstype_t, rskey, sizeof_key) \ + typedef struct { \ + rstype_t *b, *e; \ + } rsbucket_##name##_t; \ + void rs_insertsort_##name(rstype_t *beg, rstype_t *end) \ + { \ + rstype_t *i; \ + for (i = beg + 1; i < end; ++i) \ + if (rskey(*i) < rskey(*(i - 1))) { \ + rstype_t *j, tmp = *i; \ + for (j = i; j > beg && rskey(tmp) < rskey(*(j-1)); --j) \ + *j = *(j - 1); \ + *j = tmp; \ + } \ + } \ + void rs_sort_##name(rstype_t *beg, rstype_t *end, int n_bits, int s) \ + { \ + rstype_t *i; \ + int size = 1<b = k->e = beg; \ + for (i = beg; i != end; ++i) ++b[rskey(*i)>>s&m].e; \ + for (k = b + 1; k != be; ++k) \ + k->e += (k-1)->e - beg, k->b = (k-1)->e; \ + for (k = b; k != be;) { \ + if (k->b != k->e) { \ + rsbucket_##name##_t *l; \ + if ((l = b + (rskey(*k->b)>>s&m)) != k) { \ + rstype_t tmp = *k->b, swap; \ + do { \ + swap = tmp; tmp = *l->b; *l->b++ = swap; \ + l = b + (rskey(tmp)>>s&m); \ + } while (l != k); \ + *k->b++ = tmp; \ + } else ++k->b; \ + } else ++k; \ + } \ + for (b->b = beg, k = b + 1; k != be; ++k) k->b = (k-1)->e; \ + if (s) { \ + s = s > n_bits? s - n_bits : 0; \ + for (k = b; k != be; ++k) \ + if (k->e - k->b > RS_MIN_SIZE) rs_sort_##name(k->b, k->e, n_bits, s); \ + else if (k->e - k->b > 1) rs_insertsort_##name(k->b, k->e); \ + } \ + } \ + void radix_sort_##name(rstype_t *beg, rstype_t *end) \ + { \ + if (end - beg <= RS_MIN_SIZE) rs_insertsort_##name(beg, end); \ + else rs_sort_##name(beg, end, 8, sizeof_key * 8 - 8); \ + } + +#endif diff --git a/ksw2.h b/ksw2.h index d8465aa..a53ff7d 100644 --- a/ksw2.h +++ b/ksw2.h @@ -1,178 +1,178 @@ -#ifndef KSW2_H_ -#define KSW2_H_ - -#define __STDC_LIMIT_MACROS -#include - -#define KSW_NEG_INF -0x40000000 - -#define KSW_EZ_SCORE_ONLY 0x01 // don't record alignment path/cigar -#define KSW_EZ_RIGHT 0x02 // right-align gaps -#define KSW_EZ_GENERIC_SC 0x04 // without this flag: match/mismatch only; last symbol is a wildcard -#define KSW_EZ_APPROX_MAX 0x08 // approximate max; this is faster with sse -#define KSW_EZ_APPROX_DROP 0x10 // approximate Z-drop; faster with sse -#define KSW_EZ_EXTZ_ONLY 0x40 // only perform extension -#define KSW_EZ_REV_CIGAR 0x80 // reverse CIGAR in the output -#define KSW_EZ_SPLICE_FOR 0x100 -#define KSW_EZ_SPLICE_REV 0x200 -#define KSW_EZ_SPLICE_FLANK 0x400 - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - uint32_t max:31, zdropped:1; - int max_q, max_t; // max extension coordinate - int mqe, mqe_t; // max score when reaching the end of query - int mte, mte_q; // max score when reaching the end of target - int score; // max score reaching both ends; may be KSW_NEG_INF - int m_cigar, n_cigar; - int reach_end; - uint32_t *cigar; -} ksw_extz_t; - -/** - * NW-like extension - * - * @param km memory pool, when used with kalloc - * @param qlen query length - * @param query query sequence with 0 <= query[i] < m - * @param tlen target length - * @param target target sequence with 0 <= target[i] < m - * @param m number of residue types - * @param mat m*m scoring mattrix in one-dimension array - * @param gapo gap open penalty; a gap of length l cost "-(gapo+l*gape)" - * @param gape gap extension penalty - * @param w band width (<0 to disable) - * @param zdrop off-diagonal drop-off to stop extension (positive; <0 to disable) - * @param flag flag (see KSW_EZ_* macros) - * @param ez (out) scores and cigar - */ -void ksw_extz(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, - int8_t q, int8_t e, int w, int zdrop, int flag, ksw_extz_t *ez); - -void ksw_extz2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, - int8_t q, int8_t e, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez); - -void ksw_extd(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, - int8_t gapo, int8_t gape, int8_t gapo2, int8_t gape2, int w, int zdrop, int flag, ksw_extz_t *ez); - -void ksw_extd2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, - int8_t gapo, int8_t gape, int8_t gapo2, int8_t gape2, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez); - -void ksw_exts2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, - int8_t gapo, int8_t gape, int8_t gapo2, int8_t noncan, int zdrop, int flag, ksw_extz_t *ez); - -void ksw_extf2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t mch, int8_t mis, int8_t e, int w, int xdrop, ksw_extz_t *ez); - -/** - * Global alignment - * - * (first 10 parameters identical to ksw_extz_sse()) - * @param m_cigar (modified) max CIGAR length; feed 0 if cigar==0 - * @param n_cigar (out) number of CIGAR elements - * @param cigar (out) BAM-encoded CIGAR; caller need to deallocate with kfree(km, ) - * - * @return score of the alignment - */ -int ksw_gg(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t gapo, int8_t gape, int w, int *m_cigar_, int *n_cigar_, uint32_t **cigar_); -int ksw_gg2(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t gapo, int8_t gape, int w, int *m_cigar_, int *n_cigar_, uint32_t **cigar_); -int ksw_gg2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t gapo, int8_t gape, int w, int *m_cigar_, int *n_cigar_, uint32_t **cigar_); - -void *ksw_ll_qinit(void *km, int size, int qlen, const uint8_t *query, int m, const int8_t *mat); -int ksw_ll_i16(void *q, int tlen, const uint8_t *target, int gapo, int gape, int *qe, int *te); - -#ifdef __cplusplus -} -#endif - -/************************************ - *** Private macros and functions *** - ************************************/ - -#ifdef HAVE_KALLOC -#include "kalloc.h" -#else -#include -#define kmalloc(km, size) malloc((size)) -#define kcalloc(km, count, size) calloc((count), (size)) -#define krealloc(km, ptr, size) realloc((ptr), (size)) -#define kfree(km, ptr) free((ptr)) -#endif - -static inline uint32_t *ksw_push_cigar(void *km, int *n_cigar, int *m_cigar, uint32_t *cigar, uint32_t op, int len) -{ - if (*n_cigar == 0 || op != (cigar[(*n_cigar) - 1]&0xf)) { - if (*n_cigar == *m_cigar) { - *m_cigar = *m_cigar? (*m_cigar)<<1 : 4; - cigar = (uint32_t*)krealloc(km, cigar, (*m_cigar) << 2); - } - cigar[(*n_cigar)++] = len<<4 | op; - } else cigar[(*n_cigar)-1] += len<<4; - return cigar; -} - -// In the backtrack matrix, value p[] has the following structure: -// bit 0-2: which type gets the max - 0 for H, 1 for E, 2 for F, 3 for \tilde{E} and 4 for \tilde{F} -// bit 3/0x08: 1 if a continuation on the E state (bit 5/0x20 for a continuation on \tilde{E}) -// bit 4/0x10: 1 if a continuation on the F state (bit 6/0x40 for a continuation on \tilde{F}) -static inline void ksw_backtrack(void *km, int is_rot, int is_rev, int min_intron_len, const uint8_t *p, const int *off, const int *off_end, int n_col, int i0, int j0, - int *m_cigar_, int *n_cigar_, uint32_t **cigar_) -{ // p[] - lower 3 bits: which type gets the max; bit - int n_cigar = 0, m_cigar = *m_cigar_, i = i0, j = j0, r, state = 0; - uint32_t *cigar = *cigar_, tmp; - while (i >= 0 && j >= 0) { // at the beginning of the loop, _state_ tells us which state to check - int force_state = -1; - if (is_rot) { - r = i + j; - if (i < off[r]) force_state = 2; - if (off_end && i > off_end[r]) force_state = 1; - tmp = force_state < 0? p[(size_t)r * n_col + i - off[r]] : 0; - } else { - if (j < off[i]) force_state = 2; - if (off_end && j > off_end[i]) force_state = 1; - tmp = force_state < 0? p[(size_t)i * n_col + j - off[i]] : 0; - } - if (state == 0) state = tmp & 7; // if requesting the H state, find state one maximizes it. - else if (!(tmp >> (state + 2) & 1)) state = 0; // if requesting other states, _state_ stays the same if it is a continuation; otherwise, set to H - if (state == 0) state = tmp & 7; // TODO: probably this line can be merged into the "else if" line right above; not 100% sure - if (force_state >= 0) state = force_state; - if (state == 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 0, 1), --i, --j; // match - else if (state == 1 || (state == 3 && min_intron_len <= 0)) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 2, 1), --i; // deletion - else if (state == 3 && min_intron_len > 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 3, 1), --i; // intron - else cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 1, 1), --j; // insertion - } - if (i >= 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, min_intron_len > 0 && i >= min_intron_len? 3 : 2, i + 1); // first deletion - if (j >= 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 1, j + 1); // first insertion - if (!is_rev) - for (i = 0; i < n_cigar>>1; ++i) // reverse CIGAR - tmp = cigar[i], cigar[i] = cigar[n_cigar-1-i], cigar[n_cigar-1-i] = tmp; - *m_cigar_ = m_cigar, *n_cigar_ = n_cigar, *cigar_ = cigar; -} - -static inline void ksw_reset_extz(ksw_extz_t *ez) -{ - ez->max_q = ez->max_t = ez->mqe_t = ez->mte_q = -1; - ez->max = 0, ez->score = ez->mqe = ez->mte = KSW_NEG_INF; - ez->n_cigar = 0, ez->zdropped = 0, ez->reach_end = 0; -} - -static inline int ksw_apply_zdrop(ksw_extz_t *ez, int is_rot, int32_t H, int a, int b, int zdrop, int8_t e) -{ - int r, t; - if (is_rot) r = a, t = b; - else r = a + b, t = a; - if (H > (int32_t)ez->max) { - ez->max = H, ez->max_t = t, ez->max_q = r - t; - } else if (t >= ez->max_t && r - t >= ez->max_q) { - int tl = t - ez->max_t, ql = (r - t) - ez->max_q, l; - l = tl > ql? tl - ql : ql - tl; - if (zdrop >= 0 && ez->max - H > zdrop + l * e) { - ez->zdropped = 1; - return 1; - } - } - return 0; -} -#endif +#ifndef KSW2_H_ +#define KSW2_H_ + +#define __STDC_LIMIT_MACROS +#include + +#define KSW_NEG_INF -0x40000000 + +#define KSW_EZ_SCORE_ONLY 0x01 // don't record alignment path/cigar +#define KSW_EZ_RIGHT 0x02 // right-align gaps +#define KSW_EZ_GENERIC_SC 0x04 // without this flag: match/mismatch only; last symbol is a wildcard +#define KSW_EZ_APPROX_MAX 0x08 // approximate max; this is faster with sse +#define KSW_EZ_APPROX_DROP 0x10 // approximate Z-drop; faster with sse +#define KSW_EZ_EXTZ_ONLY 0x40 // only perform extension +#define KSW_EZ_REV_CIGAR 0x80 // reverse CIGAR in the output +#define KSW_EZ_SPLICE_FOR 0x100 +#define KSW_EZ_SPLICE_REV 0x200 +#define KSW_EZ_SPLICE_FLANK 0x400 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t max:31, zdropped:1; + int max_q, max_t; // max extension coordinate + int mqe, mqe_t; // max score when reaching the end of query + int mte, mte_q; // max score when reaching the end of target + int score; // max score reaching both ends; may be KSW_NEG_INF + int m_cigar, n_cigar; + int reach_end; + uint32_t *cigar; +} ksw_extz_t; + +/** + * NW-like extension + * + * @param km memory pool, when used with kalloc + * @param qlen query length + * @param query query sequence with 0 <= query[i] < m + * @param tlen target length + * @param target target sequence with 0 <= target[i] < m + * @param m number of residue types + * @param mat m*m scoring mattrix in one-dimension array + * @param gapo gap open penalty; a gap of length l cost "-(gapo+l*gape)" + * @param gape gap extension penalty + * @param w band width (<0 to disable) + * @param zdrop off-diagonal drop-off to stop extension (positive; <0 to disable) + * @param flag flag (see KSW_EZ_* macros) + * @param ez (out) scores and cigar + */ +void ksw_extz(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, + int8_t q, int8_t e, int w, int zdrop, int flag, ksw_extz_t *ez); + +void ksw_extz2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, + int8_t q, int8_t e, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez); + +void ksw_extd(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, + int8_t gapo, int8_t gape, int8_t gapo2, int8_t gape2, int w, int zdrop, int flag, ksw_extz_t *ez); + +void ksw_extd2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, + int8_t gapo, int8_t gape, int8_t gapo2, int8_t gape2, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez); + +void ksw_exts2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, + int8_t gapo, int8_t gape, int8_t gapo2, int8_t noncan, int zdrop, int flag, ksw_extz_t *ez); + +void ksw_extf2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t mch, int8_t mis, int8_t e, int w, int xdrop, ksw_extz_t *ez); + +/** + * Global alignment + * + * (first 10 parameters identical to ksw_extz_sse()) + * @param m_cigar (modified) max CIGAR length; feed 0 if cigar==0 + * @param n_cigar (out) number of CIGAR elements + * @param cigar (out) BAM-encoded CIGAR; caller need to deallocate with kfree(km, ) + * + * @return score of the alignment + */ +int ksw_gg(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t gapo, int8_t gape, int w, int *m_cigar_, int *n_cigar_, uint32_t **cigar_); +int ksw_gg2(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t gapo, int8_t gape, int w, int *m_cigar_, int *n_cigar_, uint32_t **cigar_); +int ksw_gg2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t gapo, int8_t gape, int w, int *m_cigar_, int *n_cigar_, uint32_t **cigar_); + +void *ksw_ll_qinit(void *km, int size, int qlen, const uint8_t *query, int m, const int8_t *mat); +int ksw_ll_i16(void *q, int tlen, const uint8_t *target, int gapo, int gape, int *qe, int *te); + +#ifdef __cplusplus +} +#endif + +/************************************ + *** Private macros and functions *** + ************************************/ + +#ifdef HAVE_KALLOC +#include "kalloc.h" +#else +#include +#define kmalloc(km, size) malloc((size)) +#define kcalloc(km, count, size) calloc((count), (size)) +#define krealloc(km, ptr, size) realloc((ptr), (size)) +#define kfree(km, ptr) free((ptr)) +#endif + +static inline uint32_t *ksw_push_cigar(void *km, int *n_cigar, int *m_cigar, uint32_t *cigar, uint32_t op, int len) +{ + if (*n_cigar == 0 || op != (cigar[(*n_cigar) - 1]&0xf)) { + if (*n_cigar == *m_cigar) { + *m_cigar = *m_cigar? (*m_cigar)<<1 : 4; + cigar = (uint32_t*)krealloc(km, cigar, (*m_cigar) << 2); + } + cigar[(*n_cigar)++] = len<<4 | op; + } else cigar[(*n_cigar)-1] += len<<4; + return cigar; +} + +// In the backtrack matrix, value p[] has the following structure: +// bit 0-2: which type gets the max - 0 for H, 1 for E, 2 for F, 3 for \tilde{E} and 4 for \tilde{F} +// bit 3/0x08: 1 if a continuation on the E state (bit 5/0x20 for a continuation on \tilde{E}) +// bit 4/0x10: 1 if a continuation on the F state (bit 6/0x40 for a continuation on \tilde{F}) +static inline void ksw_backtrack(void *km, int is_rot, int is_rev, int min_intron_len, const uint8_t *p, const int *off, const int *off_end, int n_col, int i0, int j0, + int *m_cigar_, int *n_cigar_, uint32_t **cigar_) +{ // p[] - lower 3 bits: which type gets the max; bit + int n_cigar = 0, m_cigar = *m_cigar_, i = i0, j = j0, r, state = 0; + uint32_t *cigar = *cigar_, tmp; + while (i >= 0 && j >= 0) { // at the beginning of the loop, _state_ tells us which state to check + int force_state = -1; + if (is_rot) { + r = i + j; + if (i < off[r]) force_state = 2; + if (off_end && i > off_end[r]) force_state = 1; + tmp = force_state < 0? p[(size_t)r * n_col + i - off[r]] : 0; + } else { + if (j < off[i]) force_state = 2; + if (off_end && j > off_end[i]) force_state = 1; + tmp = force_state < 0? p[(size_t)i * n_col + j - off[i]] : 0; + } + if (state == 0) state = tmp & 7; // if requesting the H state, find state one maximizes it. + else if (!(tmp >> (state + 2) & 1)) state = 0; // if requesting other states, _state_ stays the same if it is a continuation; otherwise, set to H + if (state == 0) state = tmp & 7; // TODO: probably this line can be merged into the "else if" line right above; not 100% sure + if (force_state >= 0) state = force_state; + if (state == 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 0, 1), --i, --j; // match + else if (state == 1 || (state == 3 && min_intron_len <= 0)) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 2, 1), --i; // deletion + else if (state == 3 && min_intron_len > 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 3, 1), --i; // intron + else cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 1, 1), --j; // insertion + } + if (i >= 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, min_intron_len > 0 && i >= min_intron_len? 3 : 2, i + 1); // first deletion + if (j >= 0) cigar = ksw_push_cigar(km, &n_cigar, &m_cigar, cigar, 1, j + 1); // first insertion + if (!is_rev) + for (i = 0; i < n_cigar>>1; ++i) // reverse CIGAR + tmp = cigar[i], cigar[i] = cigar[n_cigar-1-i], cigar[n_cigar-1-i] = tmp; + *m_cigar_ = m_cigar, *n_cigar_ = n_cigar, *cigar_ = cigar; +} + +static inline void ksw_reset_extz(ksw_extz_t *ez) +{ + ez->max_q = ez->max_t = ez->mqe_t = ez->mte_q = -1; + ez->max = 0, ez->score = ez->mqe = ez->mte = KSW_NEG_INF; + ez->n_cigar = 0, ez->zdropped = 0, ez->reach_end = 0; +} + +static inline int ksw_apply_zdrop(ksw_extz_t *ez, int is_rot, int32_t H, int a, int b, int zdrop, int8_t e) +{ + int r, t; + if (is_rot) r = a, t = b; + else r = a + b, t = a; + if (H > (int32_t)ez->max) { + ez->max = H, ez->max_t = t, ez->max_q = r - t; + } else if (t >= ez->max_t && r - t >= ez->max_q) { + int tl = t - ez->max_t, ql = (r - t) - ez->max_q, l; + l = tl > ql? tl - ql : ql - tl; + if (zdrop >= 0 && ez->max - H > zdrop + l * e) { + ez->zdropped = 1; + return 1; + } + } + return 0; +} +#endif diff --git a/ksw2_extz2_sse.c b/ksw2_extz2_sse.c index 02bb4c2..dfc6805 100644 --- a/ksw2_extz2_sse.c +++ b/ksw2_extz2_sse.c @@ -1,305 +1,305 @@ -#include -#include -#include "ksw2.h" - -#ifdef __SSE2__ -#include - -#ifdef KSW_SSE2_ONLY -#undef __SSE4_1__ -#endif - -#ifdef __SSE4_1__ -#include -#endif - -#ifdef KSW_CPU_DISPATCH -#ifdef __SSE4_1__ -void ksw_extz2_sse41(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t q, int8_t e, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez) -#else -void ksw_extz2_sse2(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t q, int8_t e, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez) -#endif -#else -void ksw_extz2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t q, int8_t e, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez) -#endif // ~KSW_CPU_DISPATCH -{ -#define __dp_code_block1 \ - z = _mm_add_epi8(_mm_load_si128(&s[t]), qe2_); \ - xt1 = _mm_load_si128(&x[t]); /* xt1 <- x[r-1][t..t+15] */ \ - tmp = _mm_srli_si128(xt1, 15); /* tmp <- x[r-1][t+15] */ \ - xt1 = _mm_or_si128(_mm_slli_si128(xt1, 1), x1_); /* xt1 <- x[r-1][t-1..t+14] */ \ - x1_ = tmp; \ - vt1 = _mm_load_si128(&v[t]); /* vt1 <- v[r-1][t..t+15] */ \ - tmp = _mm_srli_si128(vt1, 15); /* tmp <- v[r-1][t+15] */ \ - vt1 = _mm_or_si128(_mm_slli_si128(vt1, 1), v1_); /* vt1 <- v[r-1][t-1..t+14] */ \ - v1_ = tmp; \ - a = _mm_add_epi8(xt1, vt1); /* a <- x[r-1][t-1..t+14] + v[r-1][t-1..t+14] */ \ - ut = _mm_load_si128(&u[t]); /* ut <- u[t..t+15] */ \ - b = _mm_add_epi8(_mm_load_si128(&y[t]), ut); /* b <- y[r-1][t..t+15] + u[r-1][t..t+15] */ - -#define __dp_code_block2 \ - z = _mm_max_epu8(z, b); /* z = max(z, b); this works because both are non-negative */ \ - z = _mm_min_epu8(z, max_sc_); \ - _mm_store_si128(&u[t], _mm_sub_epi8(z, vt1)); /* u[r][t..t+15] <- z - v[r-1][t-1..t+14] */ \ - _mm_store_si128(&v[t], _mm_sub_epi8(z, ut)); /* v[r][t..t+15] <- z - u[r-1][t..t+15] */ \ - z = _mm_sub_epi8(z, q_); \ - a = _mm_sub_epi8(a, z); \ - b = _mm_sub_epi8(b, z); - - int r, t, qe = q + e, n_col_, *off = 0, *off_end = 0, tlen_, qlen_, last_st, last_en, wl, wr, max_sc, min_sc; - int with_cigar = !(flag&KSW_EZ_SCORE_ONLY), approx_max = !!(flag&KSW_EZ_APPROX_MAX); - int32_t *H = 0, H0 = 0, last_H0_t = 0; - uint8_t *qr, *sf, *mem, *mem2 = 0; - __m128i q_, qe2_, zero_, flag1_, flag2_, flag8_, flag16_, sc_mch_, sc_mis_, sc_N_, m1_, max_sc_; - __m128i *u, *v, *x, *y, *s, *p = 0; - - ksw_reset_extz(ez); - if (m <= 0 || qlen <= 0 || tlen <= 0) return; - - zero_ = _mm_set1_epi8(0); - q_ = _mm_set1_epi8(q); - qe2_ = _mm_set1_epi8((q + e) * 2); - flag1_ = _mm_set1_epi8(1); - flag2_ = _mm_set1_epi8(2); - flag8_ = _mm_set1_epi8(0x08); - flag16_ = _mm_set1_epi8(0x10); - sc_mch_ = _mm_set1_epi8(mat[0]); - sc_mis_ = _mm_set1_epi8(mat[1]); - sc_N_ = mat[m*m-1] == 0? _mm_set1_epi8(-e) : _mm_set1_epi8(mat[m*m-1]); - m1_ = _mm_set1_epi8(m - 1); // wildcard - max_sc_ = _mm_set1_epi8(mat[0] + (q + e) * 2); - - if (w < 0) w = tlen > qlen? tlen : qlen; - wl = wr = w; - tlen_ = (tlen + 15) / 16; - n_col_ = qlen < tlen? qlen : tlen; - n_col_ = ((n_col_ < w + 1? n_col_ : w + 1) + 15) / 16 + 1; - qlen_ = (qlen + 15) / 16; - for (t = 1, max_sc = mat[0], min_sc = mat[1]; t < m * m; ++t) { - max_sc = max_sc > mat[t]? max_sc : mat[t]; - min_sc = min_sc < mat[t]? min_sc : mat[t]; - } - if (-min_sc > 2 * (q + e)) return; // otherwise, we won't see any mismatches - - mem = (uint8_t*)kcalloc(km, tlen_ * 6 + qlen_ + 1, 16); - u = (__m128i*)(((size_t)mem + 15) >> 4 << 4); // 16-byte aligned - v = u + tlen_, x = v + tlen_, y = x + tlen_, s = y + tlen_, sf = (uint8_t*)(s + tlen_), qr = sf + tlen_ * 16; - if (!approx_max) { - H = (int32_t*)kmalloc(km, tlen_ * 16 * 4); - for (t = 0; t < tlen_ * 16; ++t) H[t] = KSW_NEG_INF; - } - if (with_cigar) { - mem2 = (uint8_t*)kmalloc(km, ((size_t)(qlen + tlen - 1) * n_col_ + 1) * 16); - p = (__m128i*)(((size_t)mem2 + 15) >> 4 << 4); - off = (int*)kmalloc(km, (qlen + tlen - 1) * sizeof(int) * 2); - off_end = off + qlen + tlen - 1; - } - - for (t = 0; t < qlen; ++t) qr[t] = query[qlen - 1 - t]; - memcpy(sf, target, tlen); - - for (r = 0, last_st = last_en = -1; r < qlen + tlen - 1; ++r) { - int st = 0, en = tlen - 1, st0, en0, st_, en_; - int8_t x1, v1; - uint8_t *qrr = qr + (qlen - 1 - r), *u8 = (uint8_t*)u, *v8 = (uint8_t*)v; - __m128i x1_, v1_; - // find the boundaries - if (st < r - qlen + 1) st = r - qlen + 1; - if (en > r) en = r; - if (st < (r-wr+1)>>1) st = (r-wr+1)>>1; // take the ceil - if (en > (r+wl)>>1) en = (r+wl)>>1; // take the floor - if (st > en) { - ez->zdropped = 1; - break; - } - st0 = st, en0 = en; - st = st / 16 * 16, en = (en + 16) / 16 * 16 - 1; - // set boundary conditions - if (st > 0) { - if (st - 1 >= last_st && st - 1 <= last_en) - x1 = ((uint8_t*)x)[st - 1], v1 = v8[st - 1]; // (r-1,s-1) calculated in the last round - else x1 = v1 = 0; // not calculated; set to zeros - } else x1 = 0, v1 = r? q : 0; - if (en >= r) ((uint8_t*)y)[r] = 0, u8[r] = r? q : 0; - // loop fission: set scores first - if (!(flag & KSW_EZ_GENERIC_SC)) { - for (t = st0; t <= en0; t += 16) { - __m128i sq, st, tmp, mask; - sq = _mm_loadu_si128((__m128i*)&sf[t]); - st = _mm_loadu_si128((__m128i*)&qrr[t]); - mask = _mm_or_si128(_mm_cmpeq_epi8(sq, m1_), _mm_cmpeq_epi8(st, m1_)); - tmp = _mm_cmpeq_epi8(sq, st); -#ifdef __SSE4_1__ - tmp = _mm_blendv_epi8(sc_mis_, sc_mch_, tmp); - tmp = _mm_blendv_epi8(tmp, sc_N_, mask); -#else - tmp = _mm_or_si128(_mm_andnot_si128(tmp, sc_mis_), _mm_and_si128(tmp, sc_mch_)); - tmp = _mm_or_si128(_mm_andnot_si128(mask, tmp), _mm_and_si128(mask, sc_N_)); -#endif - _mm_storeu_si128((__m128i*)((uint8_t*)s + t), tmp); - } - } else { - for (t = st0; t <= en0; ++t) - ((uint8_t*)s)[t] = mat[sf[t] * m + qrr[t]]; - } - // core loop - x1_ = _mm_cvtsi32_si128(x1); - v1_ = _mm_cvtsi32_si128(v1); - st_ = st / 16, en_ = en / 16; - assert(en_ - st_ + 1 <= n_col_); - if (!with_cigar) { // score only - for (t = st_; t <= en_; ++t) { - __m128i z, a, b, xt1, vt1, ut, tmp; - __dp_code_block1; -#ifdef __SSE4_1__ - z = _mm_max_epi8(z, a); // z = z > a? z : a (signed) -#else // we need to emulate SSE4.1 intrinsics _mm_max_epi8() - z = _mm_and_si128(z, _mm_cmpgt_epi8(z, zero_)); // z = z > 0? z : 0; - z = _mm_max_epu8(z, a); // z = max(z, a); this works because both are non-negative -#endif - __dp_code_block2; -#ifdef __SSE4_1__ - _mm_store_si128(&x[t], _mm_max_epi8(a, zero_)); - _mm_store_si128(&y[t], _mm_max_epi8(b, zero_)); -#else - tmp = _mm_cmpgt_epi8(a, zero_); - _mm_store_si128(&x[t], _mm_and_si128(a, tmp)); - tmp = _mm_cmpgt_epi8(b, zero_); - _mm_store_si128(&y[t], _mm_and_si128(b, tmp)); -#endif - } - } else if (!(flag&KSW_EZ_RIGHT)) { // gap left-alignment - __m128i *pr = p + (size_t)r * n_col_ - st_; - off[r] = st, off_end[r] = en; - for (t = st_; t <= en_; ++t) { - __m128i d, z, a, b, xt1, vt1, ut, tmp; - __dp_code_block1; - d = _mm_and_si128(_mm_cmpgt_epi8(a, z), flag1_); // d = a > z? 1 : 0 -#ifdef __SSE4_1__ - z = _mm_max_epi8(z, a); // z = z > a? z : a (signed) - tmp = _mm_cmpgt_epi8(b, z); - d = _mm_blendv_epi8(d, flag2_, tmp); // d = b > z? 2 : d -#else // we need to emulate SSE4.1 intrinsics _mm_max_epi8() and _mm_blendv_epi8() - z = _mm_and_si128(z, _mm_cmpgt_epi8(z, zero_)); // z = z > 0? z : 0; - z = _mm_max_epu8(z, a); // z = max(z, a); this works because both are non-negative - tmp = _mm_cmpgt_epi8(b, z); - d = _mm_or_si128(_mm_andnot_si128(tmp, d), _mm_and_si128(tmp, flag2_)); // d = b > z? 2 : d; emulating blendv -#endif - __dp_code_block2; - tmp = _mm_cmpgt_epi8(a, zero_); - _mm_store_si128(&x[t], _mm_and_si128(tmp, a)); - d = _mm_or_si128(d, _mm_and_si128(tmp, flag8_)); // d = a > 0? 0x08 : 0 - tmp = _mm_cmpgt_epi8(b, zero_); - _mm_store_si128(&y[t], _mm_and_si128(tmp, b)); - d = _mm_or_si128(d, _mm_and_si128(tmp, flag16_)); // d = b > 0? 0x10 : 0 - _mm_store_si128(&pr[t], d); - } - } else { // gap right-alignment - __m128i *pr = p + (size_t)r * n_col_ - st_; - off[r] = st, off_end[r] = en; - for (t = st_; t <= en_; ++t) { - __m128i d, z, a, b, xt1, vt1, ut, tmp; - __dp_code_block1; - d = _mm_andnot_si128(_mm_cmpgt_epi8(z, a), flag1_); // d = z > a? 0 : 1 -#ifdef __SSE4_1__ - z = _mm_max_epi8(z, a); // z = z > a? z : a (signed) - tmp = _mm_cmpgt_epi8(z, b); - d = _mm_blendv_epi8(flag2_, d, tmp); // d = z > b? d : 2 -#else // we need to emulate SSE4.1 intrinsics _mm_max_epi8() and _mm_blendv_epi8() - z = _mm_and_si128(z, _mm_cmpgt_epi8(z, zero_)); // z = z > 0? z : 0; - z = _mm_max_epu8(z, a); // z = max(z, a); this works because both are non-negative - tmp = _mm_cmpgt_epi8(z, b); - d = _mm_or_si128(_mm_andnot_si128(tmp, flag2_), _mm_and_si128(tmp, d)); // d = z > b? d : 2; emulating blendv -#endif - __dp_code_block2; - tmp = _mm_cmpgt_epi8(zero_, a); - _mm_store_si128(&x[t], _mm_andnot_si128(tmp, a)); - d = _mm_or_si128(d, _mm_andnot_si128(tmp, flag8_)); // d = 0 > a? 0 : 0x08 - tmp = _mm_cmpgt_epi8(zero_, b); - _mm_store_si128(&y[t], _mm_andnot_si128(tmp, b)); - d = _mm_or_si128(d, _mm_andnot_si128(tmp, flag16_)); // d = 0 > b? 0 : 0x10 - _mm_store_si128(&pr[t], d); - } - } - if (!approx_max) { // find the exact max with a 32-bit score array - int32_t max_H, max_t; - // compute H[], max_H and max_t - if (r > 0) { - int32_t HH[4], tt[4], en1 = st0 + (en0 - st0) / 4 * 4, i; - __m128i max_H_, max_t_, qe_; - max_H = H[en0] = en0 > 0? H[en0-1] + u8[en0] - qe : H[en0] + v8[en0] - qe; // special casing the last element - max_t = en0; - max_H_ = _mm_set1_epi32(max_H); - max_t_ = _mm_set1_epi32(max_t); - qe_ = _mm_set1_epi32(q + e); - for (t = st0; t < en1; t += 4) { // this implements: H[t]+=v8[t]-qe; if(H[t]>max_H) max_H=H[t],max_t=t; - __m128i H1, tmp, t_; - H1 = _mm_loadu_si128((__m128i*)&H[t]); - t_ = _mm_setr_epi32(v8[t], v8[t+1], v8[t+2], v8[t+3]); - H1 = _mm_add_epi32(H1, t_); - H1 = _mm_sub_epi32(H1, qe_); - _mm_storeu_si128((__m128i*)&H[t], H1); - t_ = _mm_set1_epi32(t); - tmp = _mm_cmpgt_epi32(H1, max_H_); -#ifdef __SSE4_1__ - max_H_ = _mm_blendv_epi8(max_H_, H1, tmp); - max_t_ = _mm_blendv_epi8(max_t_, t_, tmp); -#else - max_H_ = _mm_or_si128(_mm_and_si128(tmp, H1), _mm_andnot_si128(tmp, max_H_)); - max_t_ = _mm_or_si128(_mm_and_si128(tmp, t_), _mm_andnot_si128(tmp, max_t_)); -#endif - } - _mm_storeu_si128((__m128i*)HH, max_H_); - _mm_storeu_si128((__m128i*)tt, max_t_); - for (i = 0; i < 4; ++i) - if (max_H < HH[i]) max_H = HH[i], max_t = tt[i] + i; - for (; t < en0; ++t) { // for the rest of values that haven't been computed with SSE - H[t] += (int32_t)v8[t] - qe; - if (H[t] > max_H) - max_H = H[t], max_t = t; - } - } else H[0] = v8[0] - qe - qe, max_H = H[0], max_t = 0; // special casing r==0 - // update ez - if (en0 == tlen - 1 && H[en0] > ez->mte) - ez->mte = H[en0], ez->mte_q = r - en; - if (r - st0 == qlen - 1 && H[st0] > ez->mqe) - ez->mqe = H[st0], ez->mqe_t = st0; - if (ksw_apply_zdrop(ez, 1, max_H, r, max_t, zdrop, e)) break; - if (r == qlen + tlen - 2 && en0 == tlen - 1) - ez->score = H[tlen - 1]; - } else { // find approximate max; Z-drop might be inaccurate, too. - if (r > 0) { - if (last_H0_t >= st0 && last_H0_t <= en0 && last_H0_t + 1 >= st0 && last_H0_t + 1 <= en0) { - int32_t d0 = v8[last_H0_t] - qe; - int32_t d1 = u8[last_H0_t + 1] - qe; - if (d0 > d1) H0 += d0; - else H0 += d1, ++last_H0_t; - } else if (last_H0_t >= st0 && last_H0_t <= en0) { - H0 += v8[last_H0_t] - qe; - } else { - ++last_H0_t, H0 += u8[last_H0_t] - qe; - } - if ((flag & KSW_EZ_APPROX_DROP) && ksw_apply_zdrop(ez, 1, H0, r, last_H0_t, zdrop, e)) break; - } else H0 = v8[0] - qe - qe, last_H0_t = 0; - if (r == qlen + tlen - 2 && en0 == tlen - 1) - ez->score = H0; - } - last_st = st, last_en = en; - //for (t = st0; t <= en0; ++t) printf("(%d,%d)\t(%d,%d,%d,%d)\t%d\n", r, t, ((int8_t*)u)[t], ((int8_t*)v)[t], ((int8_t*)x)[t], ((int8_t*)y)[t], H[t]); // for debugging - } - kfree(km, mem); - if (!approx_max) kfree(km, H); - if (with_cigar) { // backtrack - int rev_cigar = !!(flag & KSW_EZ_REV_CIGAR); - if (!ez->zdropped && !(flag&KSW_EZ_EXTZ_ONLY)) { - ksw_backtrack(km, 1, rev_cigar, 0, (uint8_t*)p, off, off_end, n_col_*16, tlen-1, qlen-1, &ez->m_cigar, &ez->n_cigar, &ez->cigar); - } else if (!ez->zdropped && (flag&KSW_EZ_EXTZ_ONLY) && ez->mqe + end_bonus > (int)ez->max) { - ez->reach_end = 1; - ksw_backtrack(km, 1, rev_cigar, 0, (uint8_t*)p, off, off_end, n_col_*16, ez->mqe_t, qlen-1, &ez->m_cigar, &ez->n_cigar, &ez->cigar); - } else if (ez->max_t >= 0 && ez->max_q >= 0) { - ksw_backtrack(km, 1, rev_cigar, 0, (uint8_t*)p, off, off_end, n_col_*16, ez->max_t, ez->max_q, &ez->m_cigar, &ez->n_cigar, &ez->cigar); - } - kfree(km, mem2); kfree(km, off); - } -} -#endif // __SSE2__ +#include +#include +#include "ksw2.h" + +#ifdef __SSE2__ +#include + +#ifdef KSW_SSE2_ONLY +#undef __SSE4_1__ +#endif + +#ifdef __SSE4_1__ +#include +#endif + +#ifdef KSW_CPU_DISPATCH +#ifdef __SSE4_1__ +void ksw_extz2_sse41(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t q, int8_t e, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez) +#else +void ksw_extz2_sse2(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t q, int8_t e, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez) +#endif +#else +void ksw_extz2_sse(void *km, int qlen, const uint8_t *query, int tlen, const uint8_t *target, int8_t m, const int8_t *mat, int8_t q, int8_t e, int w, int zdrop, int end_bonus, int flag, ksw_extz_t *ez) +#endif // ~KSW_CPU_DISPATCH +{ +#define __dp_code_block1 \ + z = _mm_add_epi8(_mm_load_si128(&s[t]), qe2_); \ + xt1 = _mm_load_si128(&x[t]); /* xt1 <- x[r-1][t..t+15] */ \ + tmp = _mm_srli_si128(xt1, 15); /* tmp <- x[r-1][t+15] */ \ + xt1 = _mm_or_si128(_mm_slli_si128(xt1, 1), x1_); /* xt1 <- x[r-1][t-1..t+14] */ \ + x1_ = tmp; \ + vt1 = _mm_load_si128(&v[t]); /* vt1 <- v[r-1][t..t+15] */ \ + tmp = _mm_srli_si128(vt1, 15); /* tmp <- v[r-1][t+15] */ \ + vt1 = _mm_or_si128(_mm_slli_si128(vt1, 1), v1_); /* vt1 <- v[r-1][t-1..t+14] */ \ + v1_ = tmp; \ + a = _mm_add_epi8(xt1, vt1); /* a <- x[r-1][t-1..t+14] + v[r-1][t-1..t+14] */ \ + ut = _mm_load_si128(&u[t]); /* ut <- u[t..t+15] */ \ + b = _mm_add_epi8(_mm_load_si128(&y[t]), ut); /* b <- y[r-1][t..t+15] + u[r-1][t..t+15] */ + +#define __dp_code_block2 \ + z = _mm_max_epu8(z, b); /* z = max(z, b); this works because both are non-negative */ \ + z = _mm_min_epu8(z, max_sc_); \ + _mm_store_si128(&u[t], _mm_sub_epi8(z, vt1)); /* u[r][t..t+15] <- z - v[r-1][t-1..t+14] */ \ + _mm_store_si128(&v[t], _mm_sub_epi8(z, ut)); /* v[r][t..t+15] <- z - u[r-1][t..t+15] */ \ + z = _mm_sub_epi8(z, q_); \ + a = _mm_sub_epi8(a, z); \ + b = _mm_sub_epi8(b, z); + + int r, t, qe = q + e, n_col_, *off = 0, *off_end = 0, tlen_, qlen_, last_st, last_en, wl, wr, max_sc, min_sc; + int with_cigar = !(flag&KSW_EZ_SCORE_ONLY), approx_max = !!(flag&KSW_EZ_APPROX_MAX); + int32_t *H = 0, H0 = 0, last_H0_t = 0; + uint8_t *qr, *sf, *mem, *mem2 = 0; + __m128i q_, qe2_, zero_, flag1_, flag2_, flag8_, flag16_, sc_mch_, sc_mis_, sc_N_, m1_, max_sc_; + __m128i *u, *v, *x, *y, *s, *p = 0; + + ksw_reset_extz(ez); + if (m <= 0 || qlen <= 0 || tlen <= 0) return; + + zero_ = _mm_set1_epi8(0); + q_ = _mm_set1_epi8(q); + qe2_ = _mm_set1_epi8((q + e) * 2); + flag1_ = _mm_set1_epi8(1); + flag2_ = _mm_set1_epi8(2); + flag8_ = _mm_set1_epi8(0x08); + flag16_ = _mm_set1_epi8(0x10); + sc_mch_ = _mm_set1_epi8(mat[0]); + sc_mis_ = _mm_set1_epi8(mat[1]); + sc_N_ = mat[m*m-1] == 0? _mm_set1_epi8(-e) : _mm_set1_epi8(mat[m*m-1]); + m1_ = _mm_set1_epi8(m - 1); // wildcard + max_sc_ = _mm_set1_epi8(mat[0] + (q + e) * 2); + + if (w < 0) w = tlen > qlen? tlen : qlen; + wl = wr = w; + tlen_ = (tlen + 15) / 16; + n_col_ = qlen < tlen? qlen : tlen; + n_col_ = ((n_col_ < w + 1? n_col_ : w + 1) + 15) / 16 + 1; + qlen_ = (qlen + 15) / 16; + for (t = 1, max_sc = mat[0], min_sc = mat[1]; t < m * m; ++t) { + max_sc = max_sc > mat[t]? max_sc : mat[t]; + min_sc = min_sc < mat[t]? min_sc : mat[t]; + } + if (-min_sc > 2 * (q + e)) return; // otherwise, we won't see any mismatches + + mem = (uint8_t*)kcalloc(km, tlen_ * 6 + qlen_ + 1, 16); + u = (__m128i*)(((size_t)mem + 15) >> 4 << 4); // 16-byte aligned + v = u + tlen_, x = v + tlen_, y = x + tlen_, s = y + tlen_, sf = (uint8_t*)(s + tlen_), qr = sf + tlen_ * 16; + if (!approx_max) { + H = (int32_t*)kmalloc(km, tlen_ * 16 * 4); + for (t = 0; t < tlen_ * 16; ++t) H[t] = KSW_NEG_INF; + } + if (with_cigar) { + mem2 = (uint8_t*)kmalloc(km, ((size_t)(qlen + tlen - 1) * n_col_ + 1) * 16); + p = (__m128i*)(((size_t)mem2 + 15) >> 4 << 4); + off = (int*)kmalloc(km, (qlen + tlen - 1) * sizeof(int) * 2); + off_end = off + qlen + tlen - 1; + } + + for (t = 0; t < qlen; ++t) qr[t] = query[qlen - 1 - t]; + memcpy(sf, target, tlen); + + for (r = 0, last_st = last_en = -1; r < qlen + tlen - 1; ++r) { + int st = 0, en = tlen - 1, st0, en0, st_, en_; + int8_t x1, v1; + uint8_t *qrr = qr + (qlen - 1 - r), *u8 = (uint8_t*)u, *v8 = (uint8_t*)v; + __m128i x1_, v1_; + // find the boundaries + if (st < r - qlen + 1) st = r - qlen + 1; + if (en > r) en = r; + if (st < (r-wr+1)>>1) st = (r-wr+1)>>1; // take the ceil + if (en > (r+wl)>>1) en = (r+wl)>>1; // take the floor + if (st > en) { + ez->zdropped = 1; + break; + } + st0 = st, en0 = en; + st = st / 16 * 16, en = (en + 16) / 16 * 16 - 1; + // set boundary conditions + if (st > 0) { + if (st - 1 >= last_st && st - 1 <= last_en) + x1 = ((uint8_t*)x)[st - 1], v1 = v8[st - 1]; // (r-1,s-1) calculated in the last round + else x1 = v1 = 0; // not calculated; set to zeros + } else x1 = 0, v1 = r? q : 0; + if (en >= r) ((uint8_t*)y)[r] = 0, u8[r] = r? q : 0; + // loop fission: set scores first + if (!(flag & KSW_EZ_GENERIC_SC)) { + for (t = st0; t <= en0; t += 16) { + __m128i sq, st, tmp, mask; + sq = _mm_loadu_si128((__m128i*)&sf[t]); + st = _mm_loadu_si128((__m128i*)&qrr[t]); + mask = _mm_or_si128(_mm_cmpeq_epi8(sq, m1_), _mm_cmpeq_epi8(st, m1_)); + tmp = _mm_cmpeq_epi8(sq, st); +#ifdef __SSE4_1__ + tmp = _mm_blendv_epi8(sc_mis_, sc_mch_, tmp); + tmp = _mm_blendv_epi8(tmp, sc_N_, mask); +#else + tmp = _mm_or_si128(_mm_andnot_si128(tmp, sc_mis_), _mm_and_si128(tmp, sc_mch_)); + tmp = _mm_or_si128(_mm_andnot_si128(mask, tmp), _mm_and_si128(mask, sc_N_)); +#endif + _mm_storeu_si128((__m128i*)((uint8_t*)s + t), tmp); + } + } else { + for (t = st0; t <= en0; ++t) + ((uint8_t*)s)[t] = mat[sf[t] * m + qrr[t]]; + } + // core loop + x1_ = _mm_cvtsi32_si128(x1); + v1_ = _mm_cvtsi32_si128(v1); + st_ = st / 16, en_ = en / 16; + assert(en_ - st_ + 1 <= n_col_); + if (!with_cigar) { // score only + for (t = st_; t <= en_; ++t) { + __m128i z, a, b, xt1, vt1, ut, tmp; + __dp_code_block1; +#ifdef __SSE4_1__ + z = _mm_max_epi8(z, a); // z = z > a? z : a (signed) +#else // we need to emulate SSE4.1 intrinsics _mm_max_epi8() + z = _mm_and_si128(z, _mm_cmpgt_epi8(z, zero_)); // z = z > 0? z : 0; + z = _mm_max_epu8(z, a); // z = max(z, a); this works because both are non-negative +#endif + __dp_code_block2; +#ifdef __SSE4_1__ + _mm_store_si128(&x[t], _mm_max_epi8(a, zero_)); + _mm_store_si128(&y[t], _mm_max_epi8(b, zero_)); +#else + tmp = _mm_cmpgt_epi8(a, zero_); + _mm_store_si128(&x[t], _mm_and_si128(a, tmp)); + tmp = _mm_cmpgt_epi8(b, zero_); + _mm_store_si128(&y[t], _mm_and_si128(b, tmp)); +#endif + } + } else if (!(flag&KSW_EZ_RIGHT)) { // gap left-alignment + __m128i *pr = p + (size_t)r * n_col_ - st_; + off[r] = st, off_end[r] = en; + for (t = st_; t <= en_; ++t) { + __m128i d, z, a, b, xt1, vt1, ut, tmp; + __dp_code_block1; + d = _mm_and_si128(_mm_cmpgt_epi8(a, z), flag1_); // d = a > z? 1 : 0 +#ifdef __SSE4_1__ + z = _mm_max_epi8(z, a); // z = z > a? z : a (signed) + tmp = _mm_cmpgt_epi8(b, z); + d = _mm_blendv_epi8(d, flag2_, tmp); // d = b > z? 2 : d +#else // we need to emulate SSE4.1 intrinsics _mm_max_epi8() and _mm_blendv_epi8() + z = _mm_and_si128(z, _mm_cmpgt_epi8(z, zero_)); // z = z > 0? z : 0; + z = _mm_max_epu8(z, a); // z = max(z, a); this works because both are non-negative + tmp = _mm_cmpgt_epi8(b, z); + d = _mm_or_si128(_mm_andnot_si128(tmp, d), _mm_and_si128(tmp, flag2_)); // d = b > z? 2 : d; emulating blendv +#endif + __dp_code_block2; + tmp = _mm_cmpgt_epi8(a, zero_); + _mm_store_si128(&x[t], _mm_and_si128(tmp, a)); + d = _mm_or_si128(d, _mm_and_si128(tmp, flag8_)); // d = a > 0? 0x08 : 0 + tmp = _mm_cmpgt_epi8(b, zero_); + _mm_store_si128(&y[t], _mm_and_si128(tmp, b)); + d = _mm_or_si128(d, _mm_and_si128(tmp, flag16_)); // d = b > 0? 0x10 : 0 + _mm_store_si128(&pr[t], d); + } + } else { // gap right-alignment + __m128i *pr = p + (size_t)r * n_col_ - st_; + off[r] = st, off_end[r] = en; + for (t = st_; t <= en_; ++t) { + __m128i d, z, a, b, xt1, vt1, ut, tmp; + __dp_code_block1; + d = _mm_andnot_si128(_mm_cmpgt_epi8(z, a), flag1_); // d = z > a? 0 : 1 +#ifdef __SSE4_1__ + z = _mm_max_epi8(z, a); // z = z > a? z : a (signed) + tmp = _mm_cmpgt_epi8(z, b); + d = _mm_blendv_epi8(flag2_, d, tmp); // d = z > b? d : 2 +#else // we need to emulate SSE4.1 intrinsics _mm_max_epi8() and _mm_blendv_epi8() + z = _mm_and_si128(z, _mm_cmpgt_epi8(z, zero_)); // z = z > 0? z : 0; + z = _mm_max_epu8(z, a); // z = max(z, a); this works because both are non-negative + tmp = _mm_cmpgt_epi8(z, b); + d = _mm_or_si128(_mm_andnot_si128(tmp, flag2_), _mm_and_si128(tmp, d)); // d = z > b? d : 2; emulating blendv +#endif + __dp_code_block2; + tmp = _mm_cmpgt_epi8(zero_, a); + _mm_store_si128(&x[t], _mm_andnot_si128(tmp, a)); + d = _mm_or_si128(d, _mm_andnot_si128(tmp, flag8_)); // d = 0 > a? 0 : 0x08 + tmp = _mm_cmpgt_epi8(zero_, b); + _mm_store_si128(&y[t], _mm_andnot_si128(tmp, b)); + d = _mm_or_si128(d, _mm_andnot_si128(tmp, flag16_)); // d = 0 > b? 0 : 0x10 + _mm_store_si128(&pr[t], d); + } + } + if (!approx_max) { // find the exact max with a 32-bit score array + int32_t max_H, max_t; + // compute H[], max_H and max_t + if (r > 0) { + int32_t HH[4], tt[4], en1 = st0 + (en0 - st0) / 4 * 4, i; + __m128i max_H_, max_t_, qe_; + max_H = H[en0] = en0 > 0? H[en0-1] + u8[en0] - qe : H[en0] + v8[en0] - qe; // special casing the last element + max_t = en0; + max_H_ = _mm_set1_epi32(max_H); + max_t_ = _mm_set1_epi32(max_t); + qe_ = _mm_set1_epi32(q + e); + for (t = st0; t < en1; t += 4) { // this implements: H[t]+=v8[t]-qe; if(H[t]>max_H) max_H=H[t],max_t=t; + __m128i H1, tmp, t_; + H1 = _mm_loadu_si128((__m128i*)&H[t]); + t_ = _mm_setr_epi32(v8[t], v8[t+1], v8[t+2], v8[t+3]); + H1 = _mm_add_epi32(H1, t_); + H1 = _mm_sub_epi32(H1, qe_); + _mm_storeu_si128((__m128i*)&H[t], H1); + t_ = _mm_set1_epi32(t); + tmp = _mm_cmpgt_epi32(H1, max_H_); +#ifdef __SSE4_1__ + max_H_ = _mm_blendv_epi8(max_H_, H1, tmp); + max_t_ = _mm_blendv_epi8(max_t_, t_, tmp); +#else + max_H_ = _mm_or_si128(_mm_and_si128(tmp, H1), _mm_andnot_si128(tmp, max_H_)); + max_t_ = _mm_or_si128(_mm_and_si128(tmp, t_), _mm_andnot_si128(tmp, max_t_)); +#endif + } + _mm_storeu_si128((__m128i*)HH, max_H_); + _mm_storeu_si128((__m128i*)tt, max_t_); + for (i = 0; i < 4; ++i) + if (max_H < HH[i]) max_H = HH[i], max_t = tt[i] + i; + for (; t < en0; ++t) { // for the rest of values that haven't been computed with SSE + H[t] += (int32_t)v8[t] - qe; + if (H[t] > max_H) + max_H = H[t], max_t = t; + } + } else H[0] = v8[0] - qe - qe, max_H = H[0], max_t = 0; // special casing r==0 + // update ez + if (en0 == tlen - 1 && H[en0] > ez->mte) + ez->mte = H[en0], ez->mte_q = r - en; + if (r - st0 == qlen - 1 && H[st0] > ez->mqe) + ez->mqe = H[st0], ez->mqe_t = st0; + if (ksw_apply_zdrop(ez, 1, max_H, r, max_t, zdrop, e)) break; + if (r == qlen + tlen - 2 && en0 == tlen - 1) + ez->score = H[tlen - 1]; + } else { // find approximate max; Z-drop might be inaccurate, too. + if (r > 0) { + if (last_H0_t >= st0 && last_H0_t <= en0 && last_H0_t + 1 >= st0 && last_H0_t + 1 <= en0) { + int32_t d0 = v8[last_H0_t] - qe; + int32_t d1 = u8[last_H0_t + 1] - qe; + if (d0 > d1) H0 += d0; + else H0 += d1, ++last_H0_t; + } else if (last_H0_t >= st0 && last_H0_t <= en0) { + H0 += v8[last_H0_t] - qe; + } else { + ++last_H0_t, H0 += u8[last_H0_t] - qe; + } + if ((flag & KSW_EZ_APPROX_DROP) && ksw_apply_zdrop(ez, 1, H0, r, last_H0_t, zdrop, e)) break; + } else H0 = v8[0] - qe - qe, last_H0_t = 0; + if (r == qlen + tlen - 2 && en0 == tlen - 1) + ez->score = H0; + } + last_st = st, last_en = en; + //for (t = st0; t <= en0; ++t) printf("(%d,%d)\t(%d,%d,%d,%d)\t%d\n", r, t, ((int8_t*)u)[t], ((int8_t*)v)[t], ((int8_t*)x)[t], ((int8_t*)y)[t], H[t]); // for debugging + } + kfree(km, mem); + if (!approx_max) kfree(km, H); + if (with_cigar) { // backtrack + int rev_cigar = !!(flag & KSW_EZ_REV_CIGAR); + if (!ez->zdropped && !(flag&KSW_EZ_EXTZ_ONLY)) { + ksw_backtrack(km, 1, rev_cigar, 0, (uint8_t*)p, off, off_end, n_col_*16, tlen-1, qlen-1, &ez->m_cigar, &ez->n_cigar, &ez->cigar); + } else if (!ez->zdropped && (flag&KSW_EZ_EXTZ_ONLY) && ez->mqe + end_bonus > (int)ez->max) { + ez->reach_end = 1; + ksw_backtrack(km, 1, rev_cigar, 0, (uint8_t*)p, off, off_end, n_col_*16, ez->mqe_t, qlen-1, &ez->m_cigar, &ez->n_cigar, &ez->cigar); + } else if (ez->max_t >= 0 && ez->max_q >= 0) { + ksw_backtrack(km, 1, rev_cigar, 0, (uint8_t*)p, off, off_end, n_col_*16, ez->max_t, ez->max_q, &ez->m_cigar, &ez->n_cigar, &ez->cigar); + } + kfree(km, mem2); kfree(km, off); + } +} +#endif // __SSE2__ diff --git a/kthread.cpp b/kthread.cpp index d79d72c..5668916 100644 --- a/kthread.cpp +++ b/kthread.cpp @@ -1,160 +1,160 @@ -#define __STDC_LIMIT_MACROS -#include -#include -#include -#include -#include "kthread.h" - -#if (defined(WIN32) || defined(_WIN32)) && defined(_MSC_VER) -#define __sync_fetch_and_add(ptr, addend) _InterlockedExchangeAdd((void*)ptr, addend) -#endif - -/************ - * kt_for() * - ************/ - -struct kt_for_t; - -typedef struct { - struct kt_for_t *t; - long i; -} ktf_worker_t; - -typedef struct kt_for_t { - int n_threads; - long n; - ktf_worker_t *w; - void (*func)(void*,long,int); - void *data; -} kt_for_t; - -static inline long steal_work(kt_for_t *t) -{ - int i, min_i = -1; - long k, min = LONG_MAX; - for (i = 0; i < t->n_threads; ++i) - if (min > t->w[i].i) min = t->w[i].i, min_i = i; - k = __sync_fetch_and_add(&t->w[min_i].i, t->n_threads); - return k >= t->n? -1 : k; -} - -static void *ktf_worker(void *data) -{ - ktf_worker_t *w = (ktf_worker_t*)data; - long i; - for (;;) { - i = __sync_fetch_and_add(&w->i, w->t->n_threads); - if (i >= w->t->n) break; - w->t->func(w->t->data, i, w - w->t->w); - } - while ((i = steal_work(w->t)) >= 0) - w->t->func(w->t->data, i, w - w->t->w); - pthread_exit(0); -} - -void kt_for(int n_threads, void (*func)(void*,long,int), void *data, long n) -{ - if (n_threads > 1) { - int i; - kt_for_t t; - pthread_t *tid; - t.func = func, t.data = data, t.n_threads = n_threads, t.n = n; - t.w = (ktf_worker_t*)calloc(n_threads, sizeof(ktf_worker_t)); - tid = (pthread_t*)calloc(n_threads, sizeof(pthread_t)); - for (i = 0; i < n_threads; ++i) - t.w[i].t = &t, t.w[i].i = i; - for (i = 0; i < n_threads; ++i) pthread_create(&tid[i], 0, ktf_worker, &t.w[i]); - for (i = 0; i < n_threads; ++i) pthread_join(tid[i], 0); - free(tid); free(t.w); - } else { - long j; - for (j = 0; j < n; ++j) func(data, j, 0); - } -} - -/***************** - * kt_pipeline() * - *****************/ - -struct ktp_t; - -typedef struct { - struct ktp_t *pl; - int64_t index; - int step; - void *data; -} ktp_worker_t; - -typedef struct ktp_t { - void *shared; - void *(*func)(void*, int, void*); - int64_t index; - int n_workers, n_steps; - ktp_worker_t *workers; - pthread_mutex_t mutex; - pthread_cond_t cv; -} ktp_t; - -static void *ktp_worker(void *data) -{ - ktp_worker_t *w = (ktp_worker_t*)data; - ktp_t *p = w->pl; - while (w->step < p->n_steps) { - // test whether we can kick off the job with this worker - pthread_mutex_lock(&p->mutex); - for (;;) { - int i; - // test whether another worker is doing the same step - for (i = 0; i < p->n_workers; ++i) { - if (w == &p->workers[i]) continue; // ignore itself - if (p->workers[i].step <= w->step && p->workers[i].index < w->index) - break; - } - if (i == p->n_workers) break; // no workers with smaller indices are doing w->step or the previous steps - pthread_cond_wait(&p->cv, &p->mutex); - } - pthread_mutex_unlock(&p->mutex); - - // working on w->step - w->data = p->func(p->shared, w->step, w->step? w->data : 0); // for the first step, input is NULL - - // update step and let other workers know - pthread_mutex_lock(&p->mutex); - w->step = w->step == p->n_steps - 1 || w->data? (w->step + 1) % p->n_steps : p->n_steps; - if (w->step == 0) w->index = p->index++; - pthread_cond_broadcast(&p->cv); - pthread_mutex_unlock(&p->mutex); - } - pthread_exit(0); -} - -void kt_pipeline(int n_threads, void *(*func)(void*, int, void*), void *shared_data, int n_steps) -{ - ktp_t aux; - pthread_t *tid; - int i; - - if (n_threads < 1) n_threads = 1; - aux.n_workers = n_threads; - aux.n_steps = n_steps; - aux.func = func; - aux.shared = shared_data; - aux.index = 0; - pthread_mutex_init(&aux.mutex, 0); - pthread_cond_init(&aux.cv, 0); - - aux.workers = (ktp_worker_t*)calloc(n_threads, sizeof(ktp_worker_t)); - for (i = 0; i < n_threads; ++i) { - ktp_worker_t *w = &aux.workers[i]; - w->step = 0; w->pl = &aux; w->data = 0; - w->index = aux.index++; - } - - tid = (pthread_t*)calloc(n_threads, sizeof(pthread_t)); - for (i = 0; i < n_threads; ++i) pthread_create(&tid[i], 0, ktp_worker, &aux.workers[i]); - for (i = 0; i < n_threads; ++i) pthread_join(tid[i], 0); - free(tid); free(aux.workers); - - pthread_mutex_destroy(&aux.mutex); - pthread_cond_destroy(&aux.cv); -} +#define __STDC_LIMIT_MACROS +#include +#include +#include +#include +#include "kthread.h" + +#if (defined(WIN32) || defined(_WIN32)) && defined(_MSC_VER) +#define __sync_fetch_and_add(ptr, addend) _InterlockedExchangeAdd((void*)ptr, addend) +#endif + +/************ + * kt_for() * + ************/ + +struct kt_for_t; + +typedef struct { + struct kt_for_t *t; + long i; +} ktf_worker_t; + +typedef struct kt_for_t { + int n_threads; + long n; + ktf_worker_t *w; + void (*func)(void*,long,int); + void *data; +} kt_for_t; + +static inline long steal_work(kt_for_t *t) +{ + int i, min_i = -1; + long k, min = LONG_MAX; + for (i = 0; i < t->n_threads; ++i) + if (min > t->w[i].i) min = t->w[i].i, min_i = i; + k = __sync_fetch_and_add(&t->w[min_i].i, t->n_threads); + return k >= t->n? -1 : k; +} + +static void *ktf_worker(void *data) +{ + ktf_worker_t *w = (ktf_worker_t*)data; + long i; + for (;;) { + i = __sync_fetch_and_add(&w->i, w->t->n_threads); + if (i >= w->t->n) break; + w->t->func(w->t->data, i, w - w->t->w); + } + while ((i = steal_work(w->t)) >= 0) + w->t->func(w->t->data, i, w - w->t->w); + pthread_exit(0); +} + +void kt_for(int n_threads, void (*func)(void*,long,int), void *data, long n) +{ + if (n_threads > 1) { + int i; + kt_for_t t; + pthread_t *tid; + t.func = func, t.data = data, t.n_threads = n_threads, t.n = n; + t.w = (ktf_worker_t*)calloc(n_threads, sizeof(ktf_worker_t)); + tid = (pthread_t*)calloc(n_threads, sizeof(pthread_t)); + for (i = 0; i < n_threads; ++i) + t.w[i].t = &t, t.w[i].i = i; + for (i = 0; i < n_threads; ++i) pthread_create(&tid[i], 0, ktf_worker, &t.w[i]); + for (i = 0; i < n_threads; ++i) pthread_join(tid[i], 0); + free(tid); free(t.w); + } else { + long j; + for (j = 0; j < n; ++j) func(data, j, 0); + } +} + +/***************** + * kt_pipeline() * + *****************/ + +struct ktp_t; + +typedef struct { + struct ktp_t *pl; + int64_t index; + int step; + void *data; +} ktp_worker_t; + +typedef struct ktp_t { + void *shared; + void *(*func)(void*, int, void*); + int64_t index; + int n_workers, n_steps; + ktp_worker_t *workers; + pthread_mutex_t mutex; + pthread_cond_t cv; +} ktp_t; + +static void *ktp_worker(void *data) +{ + ktp_worker_t *w = (ktp_worker_t*)data; + ktp_t *p = w->pl; + while (w->step < p->n_steps) { + // test whether we can kick off the job with this worker + pthread_mutex_lock(&p->mutex); + for (;;) { + int i; + // test whether another worker is doing the same step + for (i = 0; i < p->n_workers; ++i) { + if (w == &p->workers[i]) continue; // ignore itself + if (p->workers[i].step <= w->step && p->workers[i].index < w->index) + break; + } + if (i == p->n_workers) break; // no workers with smaller indices are doing w->step or the previous steps + pthread_cond_wait(&p->cv, &p->mutex); + } + pthread_mutex_unlock(&p->mutex); + + // working on w->step + w->data = p->func(p->shared, w->step, w->step? w->data : 0); // for the first step, input is NULL + + // update step and let other workers know + pthread_mutex_lock(&p->mutex); + w->step = w->step == p->n_steps - 1 || w->data? (w->step + 1) % p->n_steps : p->n_steps; + if (w->step == 0) w->index = p->index++; + pthread_cond_broadcast(&p->cv); + pthread_mutex_unlock(&p->mutex); + } + pthread_exit(0); +} + +void kt_pipeline(int n_threads, void *(*func)(void*, int, void*), void *shared_data, int n_steps) +{ + ktp_t aux; + pthread_t *tid; + int i; + + if (n_threads < 1) n_threads = 1; + aux.n_workers = n_threads; + aux.n_steps = n_steps; + aux.func = func; + aux.shared = shared_data; + aux.index = 0; + pthread_mutex_init(&aux.mutex, 0); + pthread_cond_init(&aux.cv, 0); + + aux.workers = (ktp_worker_t*)calloc(n_threads, sizeof(ktp_worker_t)); + for (i = 0; i < n_threads; ++i) { + ktp_worker_t *w = &aux.workers[i]; + w->step = 0; w->pl = &aux; w->data = 0; + w->index = aux.index++; + } + + tid = (pthread_t*)calloc(n_threads, sizeof(pthread_t)); + for (i = 0; i < n_threads; ++i) pthread_create(&tid[i], 0, ktp_worker, &aux.workers[i]); + for (i = 0; i < n_threads; ++i) pthread_join(tid[i], 0); + free(tid); free(aux.workers); + + pthread_mutex_destroy(&aux.mutex); + pthread_cond_destroy(&aux.cv); +} diff --git a/kthread.h b/kthread.h index c3cd165..4fe0915 100644 --- a/kthread.h +++ b/kthread.h @@ -1,15 +1,15 @@ -#ifndef KTHREAD_H -#define KTHREAD_H - -#ifdef __cplusplus -extern "C" { -#endif - -void kt_for(int n_threads, void (*func)(void*,long,int), void *data, long n); -void kt_pipeline(int n_threads, void *(*func)(void*, int, void*), void *shared_data, int n_steps); - -#ifdef __cplusplus -} -#endif - -#endif +#ifndef KTHREAD_H +#define KTHREAD_H + +#ifdef __cplusplus +extern "C" { +#endif + +void kt_for(int n_threads, void (*func)(void*,long,int), void *data, long n); +void kt_pipeline(int n_threads, void *(*func)(void*, int, void*), void *shared_data, int n_steps); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/kvec.h b/kvec.h index 632fce4..cf92db9 100644 --- a/kvec.h +++ b/kvec.h @@ -1,110 +1,110 @@ -/* The MIT License - - Copyright (c) 2008, by Attractive Chaos - - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be - included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - -/* - An example: - -#include "kvec.h" -int main() { - kvec_t(int) array; - kv_init(array); - kv_push(int, array, 10); // append - kv_a(int, array, 20) = 5; // dynamic - kv_A(array, 20) = 4; // static - kv_destroy(array); - return 0; -} -*/ - -/* - 2008-09-22 (0.1.0): - - * The initial version. - -*/ - -#ifndef AC_KVEC_H -#define AC_KVEC_H - -#include - -#define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) - -#define kvec_t(type) struct { size_t n, m; type *a; } -#define kv_init(v) ((v).n = (v).m = 0, (v).a = 0) -#define kv_destroy(v) free((v).a) -#define kv_A(v, i) ((v).a[(i)]) -#define kv_pop(v) ((v).a[--(v).n]) -#define kv_size(v) ((v).n) -#define kv_max(v) ((v).m) - -#define kv_resize(type, v, s) do { \ - if ((v).m < (s)) { \ - (v).m = (s); \ - kv_roundup32((v).m); \ - (v).a = (type*)realloc((v).a, sizeof(type) * (v).m); \ - } \ - } while (0) - -#define kv_copy(type, v1, v0) do { \ - if ((v1).m < (v0).n) kv_resize(type, v1, (v0).n); \ - (v1).n = (v0).n; \ - memcpy((v1).a, (v0).a, sizeof(type) * (v0).n); \ - } while (0) \ - -#define kv_push(type, v, x) do { \ - if ((v).n == (v).m) { \ - (v).m = (v).m? (v).m<<1 : 2; \ - (v).a = (type*)realloc((v).a, sizeof(type) * (v).m); \ - } \ - (v).a[(v).n++] = (x); \ - } while (0) - -#define kv_pushp(type, v, p) do { \ - if ((v).n == (v).m) { \ - (v).m = (v).m? (v).m<<1 : 2; \ - (v).a = (type*)realloc((v).a, sizeof(type) * (v).m); \ - } \ - *(p) = &(v).a[(v).n++]; \ - } while (0) - -#define kv_a(type, v, i) ((v).m <= (size_t)(i)? \ - ((v).m = (v).n = (i) + 1, kv_roundup32((v).m), \ - (v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0) \ - : (v).n <= (size_t)(i)? (v).n = (i) \ - : 0), (v).a[(i)] - -#define kv_reverse(type, v, start) do { \ - if ((v).m > 0 && (v).n > (start)) { \ - size_t __i, __end = (v).n - (start); \ - type *__a = (v).a + (start); \ - for (__i = 0; __i < __end>>1; ++__i) { \ - type __t = __a[__end - 1 - __i]; \ - __a[__end - 1 - __i] = __a[__i]; __a[__i] = __t; \ - } \ - } \ - } while (0) - -#endif +/* The MIT License + + Copyright (c) 2008, by Attractive Chaos + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +/* + An example: + +#include "kvec.h" +int main() { + kvec_t(int) array; + kv_init(array); + kv_push(int, array, 10); // append + kv_a(int, array, 20) = 5; // dynamic + kv_A(array, 20) = 4; // static + kv_destroy(array); + return 0; +} +*/ + +/* + 2008-09-22 (0.1.0): + + * The initial version. + +*/ + +#ifndef AC_KVEC_H +#define AC_KVEC_H + +#include + +#define kv_roundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) + +#define kvec_t(type) struct { size_t n, m; type *a; } +#define kv_init(v) ((v).n = (v).m = 0, (v).a = 0) +#define kv_destroy(v) free((v).a) +#define kv_A(v, i) ((v).a[(i)]) +#define kv_pop(v) ((v).a[--(v).n]) +#define kv_size(v) ((v).n) +#define kv_max(v) ((v).m) + +#define kv_resize(type, v, s) do { \ + if ((v).m < (s)) { \ + (v).m = (s); \ + kv_roundup32((v).m); \ + (v).a = (type*)realloc((v).a, sizeof(type) * (v).m); \ + } \ + } while (0) + +#define kv_copy(type, v1, v0) do { \ + if ((v1).m < (v0).n) kv_resize(type, v1, (v0).n); \ + (v1).n = (v0).n; \ + memcpy((v1).a, (v0).a, sizeof(type) * (v0).n); \ + } while (0) \ + +#define kv_push(type, v, x) do { \ + if ((v).n == (v).m) { \ + (v).m = (v).m? (v).m<<1 : 2; \ + (v).a = (type*)realloc((v).a, sizeof(type) * (v).m); \ + } \ + (v).a[(v).n++] = (x); \ + } while (0) + +#define kv_pushp(type, v, p) do { \ + if ((v).n == (v).m) { \ + (v).m = (v).m? (v).m<<1 : 2; \ + (v).a = (type*)realloc((v).a, sizeof(type) * (v).m); \ + } \ + *(p) = &(v).a[(v).n++]; \ + } while (0) + +#define kv_a(type, v, i) ((v).m <= (size_t)(i)? \ + ((v).m = (v).n = (i) + 1, kv_roundup32((v).m), \ + (v).a = (type*)realloc((v).a, sizeof(type) * (v).m), 0) \ + : (v).n <= (size_t)(i)? (v).n = (i) \ + : 0), (v).a[(i)] + +#define kv_reverse(type, v, start) do { \ + if ((v).m > 0 && (v).n > (start)) { \ + size_t __i, __end = (v).n - (start); \ + type *__a = (v).a + (start); \ + for (__i = 0; __i < __end>>1; ++__i) { \ + type __t = __a[__end - 1 - __i]; \ + __a[__end - 1 - __i] = __a[__i]; __a[__i] = __t; \ + } \ + } \ + } while (0) + +#endif diff --git a/main.cpp b/main.cpp index 3d1c372..2c8cf9e 100644 --- a/main.cpp +++ b/main.cpp @@ -1,75 +1,75 @@ -#include -#include -#include "CommandLines.h" -#include "Process_Read.h" -#include "Assembly.h" -#include "Levenshtein_distance.h" -#include "htab.h" - -int main(int argc, char *argv[]) -{ - int i, ret; - yak_reset_realtime(); - init_opt(&asm_opt); - if (!CommandLine_process(argc, argv, &asm_opt)) return 0; - - // bit_extz_t exz, exz64; init_bit_extz_t(&exz, 2); init_bit_extz_t(&exz64, 2); - - // char *pstr = "GACCCAG", *tsrt = "GTTGTTAATTCCAT"; int32_t thre = 14; clear_align(exz); clear_align(exz64); - // ed_band_cal_extension_64_0_w_trace((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, &exz); - // // // ed_band_cal_semi_64_w_absent_diag((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, 0, &exz); - // fprintf(stderr, "\n[M::%s::] exz.err::%d, exz.ps::%d, exz.pe::%d, exz.ts::%d, exz.te::%d\n", __func__, - // exz.err, exz.ps, exz.pe, exz.ts, exz.te); - // cigar_check((char*)pstr, (char*)tsrt, &(exz)); - // ed_band_cal_extension_64_0_w((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, &exz); - // fprintf(stderr, "\n[M::%s::] exz.err::%d, exz.ps::%d, exz.pe::%d, exz.ts::%d, exz.te::%d\n", __func__, - // exz.err, exz.ps, exz.pe, exz.ts, exz.te); - // ed_band_cal_semi_infi_w((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, NULL, &exz); - // ed_band_cal_semi_64_w((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, &exz64); - // fprintf(stderr, "\n[M::%s::] exz.err::%d, exz64.err::%d, exz.ps::%d, exz64.ps::%d, exz.pe::%d, exz64.pe::%d, exz.ts::%d, exz64.ts::%d, exz.te::%d, exz64.te::%d\n", __func__, - // exz.err, exz64.err, exz.ps, exz64.ps, exz.pe, exz64.pe, exz.ts, exz64.ts, exz.te, exz64.te); - // ed_band_cal_semi_64_w_trace((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, &exz64); - // cigar_check((char*)pstr, (char*)tsrt, &(exz64)); - - - // char *pstr = "TGT", *tsrt = "CTGT"; int32_t thre = 1; - // ed_band_cal_global_infi_w((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, NULL, &exz); - // ed_band_cal_global_64_w((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, &exz64); - // ed_band_cal_global_64_w_trace((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, &exz64); - // fprintf(stderr, "\n[M::%s::] exz.err::%d, exz64.err::%d, exz.ps::%d, exz64.ps::%d, exz.pe::%d, exz64.pe::%d, exz.ts::%d, exz64.ts::%d, exz.te::%d, exz64.te::%d\n", __func__, - // exz.err, exz64.err, exz.ps, exz64.ps, exz.pe, exz64.pe, exz.ts, exz64.ts, exz.te, exz64.te); - // cigar_check((char*)pstr, (char*)tsrt, &(exz64)); - - // ed_band_cal_extension_infi0_w((char *)"AAT", 3, (char *)"ACTTTTTT", 8, 2, NULL, &exz); - // ed_band_cal_extension_64_w((char *)"AAT", 3, (char *)"ACTTTTTT", 8, 2, &exz64); - // fprintf(stderr, "\n[M::%s::] exz.err::%d, exz64.err::%d, exz.ps::%d, exz64.ps::%d, exz.pe::%d, exz64.pe::%d, exz.ts::%d, exz64.ts::%d, exz.te::%d, exz64.te::%d\n", __func__, - // exz.err, exz64.err, exz.ps, exz64.ps, exz.pe, exz64.pe, exz.ts, exz64.ts, exz.te, exz64.te); - - //bit_extz_t exz; ///ed_band_cal_global_128bit(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz); - // ed_band_cal_extension_128bit((char *)"AAGTTTA", 7, (char *)"CCTTTTTT", 8, 4, &exz); - // ed_band_cal_extension_128bit((char *)"AA", 2, (char *)"ACTTTTTT", 8, 1, &exz); - // fprintf(stderr, "ed_extension::%d, pe::%d, te::%d\n", exz.err, exz.pe, exz.te); - // exit(1); - - - - // fprintf(stderr, "[M::%s::] ed_global::%d, ed_global_128bit::%d\n", __func__, - // ed_band_cal_global((char *)"ACT", 3, (char *)"AAT", 3, 1), - // ed_band_cal_global_128bit((char *)"ACT", 3, (char *)"AAT", 3, 1)); - - // fprintf(stderr, "[M::%s::] ed_global::%d, ed_global_128bit::%d\n", __func__, - // ed_band_cal_global((char*)"ACTTTTTT", 8, (char*)"AATTTT", 6, 3), - // ed_band_cal_global_128bit((char*)"ACTTTTTT", 8, (char*)"AATTTT", 6, 3)); - // exit(1); - if(asm_opt.sec_in) ret = ha_assemble_pair(); - else if(asm_opt.dbg_ovec_cal) ret = ha_ec_dbg(); - else ret = ha_assemble(); - - destory_opt(&asm_opt); - fprintf(stderr, "[M::%s] Version: %s\n", __func__, HA_VERSION); - fprintf(stderr, "[M::%s] CMD:", __func__); - for (i = 0; i < argc; ++i) - fprintf(stderr, " %s", argv[i]); - fprintf(stderr, "\n[M::%s] Real time: %.3f sec; CPU: %.3f sec; Peak RSS: %.3f GB\n", __func__, yak_realtime(), yak_cputime(), yak_peakrss_in_gb()); - return ret; -} +#include +#include +#include "CommandLines.h" +#include "Process_Read.h" +#include "Assembly.h" +#include "Levenshtein_distance.h" +#include "htab.h" + +int main(int argc, char *argv[]) +{ + int i, ret; + yak_reset_realtime(); + init_opt(&asm_opt); + if (!CommandLine_process(argc, argv, &asm_opt)) return 0; + + // bit_extz_t exz, exz64; init_bit_extz_t(&exz, 2); init_bit_extz_t(&exz64, 2); + + // char *pstr = "GACCCAG", *tsrt = "GTTGTTAATTCCAT"; int32_t thre = 14; clear_align(exz); clear_align(exz64); + // ed_band_cal_extension_64_0_w_trace((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, &exz); + // // // ed_band_cal_semi_64_w_absent_diag((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, 0, &exz); + // fprintf(stderr, "\n[M::%s::] exz.err::%d, exz.ps::%d, exz.pe::%d, exz.ts::%d, exz.te::%d\n", __func__, + // exz.err, exz.ps, exz.pe, exz.ts, exz.te); + // cigar_check((char*)pstr, (char*)tsrt, &(exz)); + // ed_band_cal_extension_64_0_w((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, &exz); + // fprintf(stderr, "\n[M::%s::] exz.err::%d, exz.ps::%d, exz.pe::%d, exz.ts::%d, exz.te::%d\n", __func__, + // exz.err, exz.ps, exz.pe, exz.ts, exz.te); + // ed_band_cal_semi_infi_w((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, NULL, &exz); + // ed_band_cal_semi_64_w((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, &exz64); + // fprintf(stderr, "\n[M::%s::] exz.err::%d, exz64.err::%d, exz.ps::%d, exz64.ps::%d, exz.pe::%d, exz64.pe::%d, exz.ts::%d, exz64.ts::%d, exz.te::%d, exz64.te::%d\n", __func__, + // exz.err, exz64.err, exz.ps, exz64.ps, exz.pe, exz64.pe, exz.ts, exz64.ts, exz.te, exz64.te); + // ed_band_cal_semi_64_w_trace((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, &exz64); + // cigar_check((char*)pstr, (char*)tsrt, &(exz64)); + + + // char *pstr = "TGT", *tsrt = "CTGT"; int32_t thre = 1; + // ed_band_cal_global_infi_w((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, NULL, &exz); + // ed_band_cal_global_64_w((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, &exz64); + // ed_band_cal_global_64_w_trace((char*)pstr, strlen(pstr), (char*)tsrt, strlen(tsrt), thre, &exz64); + // fprintf(stderr, "\n[M::%s::] exz.err::%d, exz64.err::%d, exz.ps::%d, exz64.ps::%d, exz.pe::%d, exz64.pe::%d, exz.ts::%d, exz64.ts::%d, exz.te::%d, exz64.te::%d\n", __func__, + // exz.err, exz64.err, exz.ps, exz64.ps, exz.pe, exz64.pe, exz.ts, exz64.ts, exz.te, exz64.te); + // cigar_check((char*)pstr, (char*)tsrt, &(exz64)); + + // ed_band_cal_extension_infi0_w((char *)"AAT", 3, (char *)"ACTTTTTT", 8, 2, NULL, &exz); + // ed_band_cal_extension_64_w((char *)"AAT", 3, (char *)"ACTTTTTT", 8, 2, &exz64); + // fprintf(stderr, "\n[M::%s::] exz.err::%d, exz64.err::%d, exz.ps::%d, exz64.ps::%d, exz.pe::%d, exz64.pe::%d, exz.ts::%d, exz64.ts::%d, exz.te::%d, exz64.te::%d\n", __func__, + // exz.err, exz64.err, exz.ps, exz64.ps, exz.pe, exz64.pe, exz.ts, exz64.ts, exz.te, exz64.te); + + //bit_extz_t exz; ///ed_band_cal_global_128bit(t_string+r_ts, t_end+1-r_ts, q_string, ql, thres, &exz); + // ed_band_cal_extension_128bit((char *)"AAGTTTA", 7, (char *)"CCTTTTTT", 8, 4, &exz); + // ed_band_cal_extension_128bit((char *)"AA", 2, (char *)"ACTTTTTT", 8, 1, &exz); + // fprintf(stderr, "ed_extension::%d, pe::%d, te::%d\n", exz.err, exz.pe, exz.te); + // exit(1); + + + + // fprintf(stderr, "[M::%s::] ed_global::%d, ed_global_128bit::%d\n", __func__, + // ed_band_cal_global((char *)"ACT", 3, (char *)"AAT", 3, 1), + // ed_band_cal_global_128bit((char *)"ACT", 3, (char *)"AAT", 3, 1)); + + // fprintf(stderr, "[M::%s::] ed_global::%d, ed_global_128bit::%d\n", __func__, + // ed_band_cal_global((char*)"ACTTTTTT", 8, (char*)"AATTTT", 6, 3), + // ed_band_cal_global_128bit((char*)"ACTTTTTT", 8, (char*)"AATTTT", 6, 3)); + // exit(1); + if(asm_opt.sec_in) ret = ha_assemble_pair(); + else if(asm_opt.dbg_ovec_cal) ret = ha_ec_dbg(); + else ret = ha_assemble(); + + destory_opt(&asm_opt); + fprintf(stderr, "[M::%s] Version: %s\n", __func__, HA_VERSION); + fprintf(stderr, "[M::%s] CMD:", __func__); + for (i = 0; i < argc; ++i) + fprintf(stderr, " %s", argv[i]); + fprintf(stderr, "\n[M::%s] Real time: %.3f sec; CPU: %.3f sec; Peak RSS: %.3f GB\n", __func__, yak_realtime(), yak_cputime(), yak_peakrss_in_gb()); + return ret; +} diff --git a/rcut.cpp b/rcut.cpp index 50395f6..4059c17 100644 --- a/rcut.cpp +++ b/rcut.cpp @@ -1,4872 +1,4881 @@ -#define __STDC_LIMIT_MACROS -#include -#include -#include -#include "assert.h" -#include "rcut.h" -#include "Purge_Dups.h" -#include "Correct.h" -#include "ksort.h" -#include "kthread.h" -#include "hic.h" -#include "horder.h" - -#define VERBOSE_CUT 0 - -#define mc_edge_key(e) ((e).x) -KRADIX_SORT_INIT(mce, mc_edge_t, mc_edge_key, member_size(mc_edge_t, x)) -#define mb_edge_key(e) ((e).x) -KRADIX_SORT_INIT(mbe, mb_edge_t, mb_edge_key, member_size(mb_edge_t, x)) -#define mc_generic_key(x) (x) -KRADIX_SORT_INIT(mc64, uint64_t, mc_generic_key, 8) -KRADIX_SORT_INIT(mc32, uint32_t, mc_generic_key, 4) - -#define pt_a(x, id) ((x).ma.a + ((x).idx.a[(id)]>>32)) -#define pt_n(x, id) ((uint32_t)((x).idx.a[(id)])) -#define ma_x(z) (((z).x>>32)) -#define ma_y(z) (((uint32_t)((z).x))) - -#define mcb_pat(x, id) (&((x).m.a[(id)-1])) -#define mcp_de(x, id, m) ((x).z[((id)<<(x).hapN)+(m)]) - -uint8_t bit_filed[8] = {1, 2, 4, 8, 16, 32, 64, 128}; -#define is_bit_set(id, a) ((a)[(id)>>3]&bit_filed[(id)&7]) - -typedef struct { - int32_t max_iter; - int32_t n_perturb; - int32_t n_b_perturb; - int32_t n_s_perturb; - double f_perturb; - uint64_t seed; -} mc_opt_t; - - -typedef struct { - t_w_t z[2]; -} mc_pairsc_t; - -typedef struct { - uint64_t x; // RNG - uint32_t cc_off, cc_size; - kvec_t(uint64_t) cc_edge; - uint32_t *cc_node; - uint32_t *bfs, *bfs_mark; - mc_pairsc_t *z, *z_opt;///keep scores to nodes(1) and nodes(-1) - int8_t *s, *s_opt; - uint8_t *f; -} mc_svaux_t; - - -typedef struct { - uint64_t x; // RNG - uint32_t cc_off, cc_size; - kvec_t(uint64_t) cc_edge; - uint32_t *cc_node; - uint32_t *bfs, *bfs_mark; - mb_node_t *u, *u_opt;///keep status - uint8_t *f; -} mb_svaux_t; - -typedef struct{ - uint64_t chain_id, bid, uid; -}mc_bp_iter; - -typedef struct{ - uint32_t chain_id; - uint32_t f_bid; - uint32_t f_uid; - uint32_t l_bid; - uint32_t l_uid; - uint32_t id; - t_w_t w; -}mc_bp_res; - -typedef struct{ - size_t n, m; - uint8_t *a; -}bits_p; - -typedef struct{ - bubble_type* b_b; - uint64_t *idx, idx_n, occ, n_thread; - mc_bp_res *res; - uint8_t *lock; - mc_svaux_t *b_aux; - mc_match_t *ma; - bits_p *vis; -}mc_bp_t; - -typedef struct{ - kvec_t(uint32_t) nn; - kvec_t(uint64_t) ng; -} nn_clus_t; - -typedef struct{ - bits_p vis; - t_w_t w; - uint32_t off, occ; -}clus_flip_aux; - -typedef struct{ - nn_clus_t cc; - bubble_type* bub; - const mc_opt_t *opt; - mc_g_t *mg; - uint8_t *lock, lock_max, dbg; - uint32_t n, n_thread; - clus_flip_aux *aux; - mc_svaux_t *baux; - asg64_v *asn; - scg_t sg; -} mc_clus_t; - -typedef struct { - uint64_t x; // RNG - uint32_t cc_off, cc_size; - kvec_t(uint32_t) cc_node; - kvec_t(uint32_t) bfs; - ///share - uint32_t *bfs_mark; - mc_pairsc_t *z, *z_opt;///keep scores to nodes(1) and nodes(-1) - int8_t *s, *s_opt; -} mc_svaux_t_s; - -typedef struct { - kvec_t(mc_svaux_t_s) bs; - kvec_t(uint64_t) cc_edge; - uint32_t *bfs_mark; - mc_pairsc_t *z, *z_opt;///keep scores to nodes(1) and nodes(-1) - int8_t *s, *s_opt; - uint32_t n_t, n_g; -} mc_svaux_t_mul; - -void mc_opt_init(mc_opt_t *opt, int32_t n_perturb, double f_perturb, uint64_t seed) -{ - memset(opt, 0, sizeof(mc_opt_t)); - opt->n_perturb = n_perturb; - opt->f_perturb = f_perturb; - opt->max_iter = 1000; - opt->seed = seed; - opt->n_s_perturb = n_perturb; - opt->n_b_perturb = n_perturb*0.5; -} - -void mc_merge_dup(mc_g_t *mg) // MUST BE sorted -{ - uint32_t i, j, k, st; - w_t w; - for (st = 0, i = 1, k = 0; i <= mg->e->ma.n; ++i) { - if (i == mg->e->ma.n || mg->e->ma.a[i].x != mg->e->ma.a[st].x) { - if (i - st > 1) { - for (j = st, w = 0; j < i; ++j) { - w += mg->e->ma.a[j].w; - } - mg->e->ma.a[k] = mg->e->ma.a[st]; - mg->e->ma.a[k++].w = w; - } else mg->e->ma.a[k++] = mg->e->ma.a[st]; - st = i; - } - } - mg->e->ma.n = k; -} - -void mb_merge_dup(mb_g_t *mbg) // MUST BE sorted -{ - uint32_t i, j, k, st; - t_w_t w[4]; - for (st = 0, i = 1, k = 0; i <= mbg->e->ma.n; ++i) { - if (i == mbg->e->ma.n || mbg->e->ma.a[i].x != mbg->e->ma.a[st].x) { - if (i - st > 1) { - w[0] = w[1] = w[2] = w[3] = 0; - for (j = st; j < i; ++j) { - w[0] += mbg->e->ma.a[j].w[0]; - w[1] += mbg->e->ma.a[j].w[1]; - w[2] += mbg->e->ma.a[j].w[2]; - w[3] += mbg->e->ma.a[j].w[3]; - } - mbg->e->ma.a[k] = mbg->e->ma.a[st]; - mbg->e->ma.a[k].w[0] = w[0]; - mbg->e->ma.a[k].w[1] = w[1]; - mbg->e->ma.a[k].w[2] = w[2]; - mbg->e->ma.a[k].w[3] = w[3]; - k++; - } else mbg->e->ma.a[k++] = mbg->e->ma.a[st]; - st = i; - } - } - mbg->e->ma.n = k; -} - -static void mc_edges_idx(mc_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].x>>32) != (ma->ma.a[st].x>>32)) - ma->idx.a[ma->ma.a[st].x>>32] = (uint64_t)st << 32 | (i - st), st = i; -} - -static void mb_edges_idx(mb_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].x>>32) != (ma->ma.a[st].x>>32)) - ma->idx.a[ma->ma.a[st].x>>32] = (uint64_t)st << 32 | (i - st), st = i; -} - - -mc_g_t *init_mc_g_t(ma_ug_t *ug, asg_t *read_g, int8_t *s, uint32_t renew_s) -{ - mc_g_t *p = NULL; CALLOC(p, 1); - p->ug = ug; - p->rg = read_g; - kv_init(p->s); - if(s) - { - p->s.a = s; - p->s.n = ug->g->n_seq; - p->s.m = 0; - if(renew_s) memset(p->s.a, 0, p->s.n); - } - else - { - CALLOC(p->s.a, ug->g->n_seq); - p->s.n = p->s.m = ug->g->n_seq; - } - return p; -} - -static mc_edge_t *get_mc_edge(const mc_match_t *ma, uint32_t sid1, uint32_t sid2) -{ - mc_edge_t *o = pt_a(*ma, sid1); - uint32_t n = pt_n(*ma, sid1), k; - for (k = 0; k < n; ++k) - if (((uint32_t)o[k].x) == sid2) - return &(o[k]); - return NULL; -} - -static mb_edge_t *get_mb_edge(const mb_match_t *ma, uint32_t sid1, uint32_t sid2) -{ - mb_edge_t *o = pt_a(*ma, sid1); - uint32_t n = pt_n(*ma, sid1), k; - for (k = 0; k < n; ++k) - if (((uint32_t)o[k].x) == sid2) - return &(o[k]); - return NULL; -} - -uint32_t mb_edges_symm(mb_match_t *ma); - -uint32_t debug_mb_edges_symm(mb_match_t *ma) -{ - uint32_t i, n = 0; - mb_edge_t *t = NULL, *m = NULL; - - for (i = 0; i < ma->ma.n; ++i) { - m = &ma->ma.a[i]; - if (ma_x(*m) == ma_y(*m)) - { - fprintf(stderr, "ERROR-0-::%s\n", __func__); - continue; - } - t = get_mb_edge(ma, ma_y(*m), ma_x(*m)); - if(!t) - { - fprintf(stderr, "ERROR-1-::%s\n", __func__); - continue; - } - - if(m->w[0] != t->w[0]) - { - fprintf(stderr, "\nERROR-2-::%s\n", __func__); - fprintf(stderr, "ma_x(*m): %lu, ma_y(*m): %u\n", ma_x(*m), ma_y(*m)); - // fprintf(stderr, "m->w[0]: %ld, m->w[1]: %ld, m->w[2]: %ld, m->w[3]: %ld\n", - // m->w[0], m->w[1], m->w[2], m->w[3]); - // fprintf(stderr, "t->w[0]: %ld, t->w[1]: %ld, t->w[2]: %ld, t->w[3]: %ld\n", - // t->w[0], t->w[1], t->w[2], t->w[3]); - fprintf(stderr, "m->w[0]: %f, m->w[1]: %f, m->w[2]: %f, m->w[3]: %f\n", - m->w[0], m->w[1], m->w[2], m->w[3]); - fprintf(stderr, "t->w[0]: %f, t->w[1]: %f, t->w[2]: %f, t->w[3]: %f\n", - t->w[0], t->w[1], t->w[2], t->w[3]); - } - - if(m->w[3] != t->w[3]) - { - fprintf(stderr, "\nERROR-3-::%s\n", __func__); - fprintf(stderr, "ma_x(*m): %lu, ma_y(*m): %u\n", ma_x(*m), ma_y(*m)); - // fprintf(stderr, "m->w[0]: %ld, m->w[1]: %ld, m->w[2]: %ld, m->w[3]: %ld\n", - // m->w[0], m->w[1], m->w[2], m->w[3]); - // fprintf(stderr, "t->w[0]: %ld, t->w[1]: %ld, t->w[2]: %ld, t->w[3]: %ld\n", - // t->w[0], t->w[1], t->w[2], t->w[3]); - fprintf(stderr, "m->w[0]: %f, m->w[1]: %f, m->w[2]: %f, m->w[3]: %f\n", - m->w[0], m->w[1], m->w[2], m->w[3]); - fprintf(stderr, "t->w[0]: %f, t->w[1]: %f, t->w[2]: %f, t->w[3]: %f\n", - t->w[0], t->w[1], t->w[2], t->w[3]); - } - - if(m->w[1] != t->w[2]) - { - fprintf(stderr, "\nERROR-4-::%s\n", __func__); - fprintf(stderr, "ma_x(*m): %lu, ma_y(*m): %u\n", ma_x(*m), ma_y(*m)); - // fprintf(stderr, "m->w[0]: %ld, m->w[1]: %ld, m->w[2]: %ld, m->w[3]: %ld\n", - // m->w[0], m->w[1], m->w[2], m->w[3]); - // fprintf(stderr, "t->w[0]: %ld, t->w[1]: %ld, t->w[2]: %ld, t->w[3]: %ld\n", - // t->w[0], t->w[1], t->w[2], t->w[3]); - fprintf(stderr, "m->w[0]: %f, m->w[1]: %f, m->w[2]: %f, m->w[3]: %f\n", - m->w[0], m->w[1], m->w[2], m->w[3]); - fprintf(stderr, "t->w[0]: %f, t->w[1]: %f, t->w[2]: %f, t->w[3]: %f\n", - t->w[0], t->w[1], t->w[2], t->w[3]); - } - - - - if(m->w[2] != t->w[1]) - { - fprintf(stderr, "\nERROR-5-::%s\n", __func__); - fprintf(stderr, "ma_x(*m): %lu, ma_y(*m): %u\n", ma_x(*m), ma_y(*m)); - // fprintf(stderr, "m->w[0]: %ld, m->w[1]: %ld, m->w[2]: %ld, m->w[3]: %ld\n", - // m->w[0], m->w[1], m->w[2], m->w[3]); - // fprintf(stderr, "t->w[0]: %ld, t->w[1]: %ld, t->w[2]: %ld, t->w[3]: %ld\n", - // t->w[0], t->w[1], t->w[2], t->w[3]); - fprintf(stderr, "m->w[0]: %f, m->w[1]: %f, m->w[2]: %f, m->w[3]: %f\n", - m->w[0], m->w[1], m->w[2], m->w[3]); - fprintf(stderr, "t->w[0]: %f, t->w[1]: %f, t->w[2]: %f, t->w[3]: %f\n", - t->w[0], t->w[1], t->w[2], t->w[3]); - } - - } - - return n; -} - -inline void decode_mb_node(mb_g_t *mbg, uint32_t id, uint32_t **a0, uint32_t *n0, mc_node_t *s0, -uint32_t **a1, uint32_t *n1, mc_node_t *s1) -{ - if(a0) (*a0) = mbg->u->bid.a + mbg->u->u.a[id].a[0]; - if(n0) (*n0) = mbg->u->u.a[id].occ[0]; - if(s0) (*s0) = mbg->u->u.a[id].s[0]; - - if(a1) (*a1) = mbg->u->bid.a + mbg->u->u.a[id].a[1]; - if(n1) (*n1) = mbg->u->u.a[id].occ[1]; - if(s1) (*s1) = mbg->u->u.a[id].s[1]; -} - - -uint64_t *mb_nodes_core(kv_u_trans_t *ref, mc_match_t* ma, uint32_t occ, uint32_t *fg, kvec_t_u32_warp *sk) -{ - uint32_t i, x, y; - uint64_t *group; - u_trans_t *o = NULL; - - for (i = 0; i < occ; ++i) - fg[i] = (uint32_t)-1; - - // connected componets - for (i = 0; i < occ; ++i) { - if (fg[i] != (uint32_t)-1) continue; - if (pt_n(*ma, i) == 0) - { - fg[i] = i;///group id - continue; - } - sk->a.n = 0; - kv_push(uint32_t, sk->a, i); - while (sk->a.n > 0) { - uint32_t k, j, st, n, t; - sk->a.n--; - k = sk->a.a[sk->a.n]; - fg[k] = i;///group id - o = u_trans_a(*ref, k); - n = u_trans_n(*ref, k); - for (st = 0, j = 1; j <= n; ++j) - { - if(j == n || o[j].tn != o[st].tn) - { - t = o[st].tn; - if ((pt_n(*ma, t) != 0) && (fg[t] == (uint32_t)-1)) - { - kv_push(uint32_t, sk->a, t); - } - st = j; - } - } - } - } - - // precalculate the size of each group - CALLOC(group, occ); - for (i = 0; i < occ; ++i) - group[i] = (uint64_t)fg[i] << 32 | i; - radix_sort_mc64(group, group + occ); - for (i = 1, x = y = 0; i <= occ; ++i) { - if (i == occ || 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; - } - } - return group; -} - -void assgin_mb_node(mb_nodes_t *x, kv_u_trans_t *ref, mc_match_t* ma, uint32_t *fg, kvec_t_u32_warp *sk, uint64_t *cc, uint32_t cc_off, uint32_t cc_size) -{ - uint32_t i, v, n, st, j, t, pass, uid; - u_trans_t *o = NULL; - mb_node_t *p = NULL; - for (i = 0; i < cc_size; ++i) - { - v = (uint32_t)cc[cc_off + i];///node id - fg[v] = (uint32_t)-1; - } - - sk->a.n = 0; - v = (uint32_t)cc[cc_off]; - kv_push(uint32_t, sk->a, v); - fg[v] = 0; - pass = 1; - while (sk->a.n > 0) - { - sk->a.n--; - v = sk->a.a[sk->a.n]; - if(pt_n(*ma, v) == 0) continue; - o = u_trans_a(*ref, v); - n = u_trans_n(*ref, v); - for (st = 0, j = 1; j <= n; ++j) - { - if(j == n || o[j].tn != o[st].tn) - { - t = o[st].tn; - if (pt_n(*ma, t) == 0) - { - st = j; - continue; - } - - if (fg[t] == (uint32_t)-1)///uncolor - { - fg[t] = 1 - fg[v]; - kv_push(uint32_t, sk->a, t); - } - else if(fg[t] == fg[v]) ///color - { - pass = 0; - break; - } - st = j; - } - } - if(pass == 0) break; - } - - if(pass) - { - uid = x->u.n; - kv_pushp(mb_node_t, x->u, &p); - p->z[0] = p->z[1] = p->z[2] = p->z[3] = 0; - p->s[0] = p->s[1] = 0; - p->occ[0] = p->occ[1] = 0; - - for (i = 0, p->a[0] = x->bid.n; i < cc_size; ++i) - { - v = (uint32_t)cc[cc_off + i];///node id - if(fg[v] == 0) - { - kv_push(uint32_t, x->bid, v); - p->occ[0]++; - x->idx.a[v] = (uid<<1); - } - } - - for (i = 0, p->a[1] = x->bid.n; i < cc_size; ++i) - { - v = (uint32_t)cc[cc_off + i];///node id - if(fg[v] == 1) - { - kv_push(uint32_t, x->bid, v); - p->occ[1]++; - x->idx.a[v] = (uid<<1) + 1; - } - } - } - else - { - for (i = 0; i < cc_size; ++i) - { - v = (uint32_t)cc[cc_off + i];///node id - uid = x->u.n; - kv_pushp(mb_node_t, x->u, &p); - p->z[0] = p->z[1] = p->z[2] = p->z[3] = 0; - p->s[0] = p->s[1] = 0; - p->occ[0] = p->occ[1] = 0; - - p->a[0] = x->bid.n; - kv_push(uint32_t, x->bid, v); - p->occ[0]++; - x->idx.a[v] = (uid<<1); - - p->a[1] = x->bid.n; - } - } -} - -void debug_mb_nodes(mb_nodes_t *x, kv_u_trans_t *ref, mc_match_t* ma) -{ - uint32_t i, k, bid, ori, *a = NULL, a_n, v; - for (i = 0; i < x->idx.n; i++) - { - if(x->idx.a[i] == (uint32_t)-1) - { - fprintf(stderr, "ERROR-0-::%s\n", __func__); - continue; - } - bid = x->idx.a[i]>>1; ori = x->idx.a[i] & 1; - a = x->bid.a + x->u.a[bid].a[ori]; - a_n = x->u.a[bid].occ[ori]; - for (k = 0; k < a_n; k++) - { - if(a[k] == i) break; - } - if(k >= a_n) fprintf(stderr, "ERROR-1-::%s\n", __func__); - } - - uint32_t *tt[2], t_n[2], o_n, m, t, found; - int8_t *vis = NULL; CALLOC(vis, x->idx.n); - u_trans_t *o = NULL; - for (i = 0; i < x->u.n; i++)///each block - { - tt[0] = x->bid.a + x->u.a[i].a[0]; - t_n[0] = x->u.a[i].occ[0]; - tt[1] = x->bid.a + x->u.a[i].a[1]; - t_n[1] = x->u.a[i].occ[1]; - - if(t_n[0] == 1 && t_n[1] == 0) continue; - - for (k = 0; k < t_n[0]; k++) - { - vis[tt[0][k]] = 1; - } - for (k = 0; k < t_n[1]; k++) - { - vis[tt[1][k]] = -1; - } - - - - - - for (k = 0; k < t_n[0]; k++) - { - v = tt[0][k]; - o = u_trans_a(*ref, v); - o_n = u_trans_n(*ref, v); - found = 0; - for (m = 0; m < o_n; m++) - { - t = o[m].tn; - if (pt_n(*ma, t) == 0) continue; - if (vis[t] != -1) fprintf(stderr, "ERROR-2-::%s\n", __func__); - else found = 1; - } - if(found == 0) fprintf(stderr, "ERROR-2-*::%s\n", __func__); - } - - for (k = 0; k < t_n[1]; k++) - { - v = tt[1][k]; - o = u_trans_a(*ref, v); - o_n = u_trans_n(*ref, v); - found = 0; - for (m = 0; m < o_n; m++) - { - t = o[m].tn; - if (pt_n(*ma, t) == 0) continue; - if (vis[t] != 1) fprintf(stderr, "ERROR-3-::%s\n", __func__); - else found = 1; - } - if(found == 0) fprintf(stderr, "ERROR-3-*::%s\n", __func__); - } - - - for (k = 0; k < t_n[0]; k++) - { - vis[tt[0][k]] = 0; - } - for (k = 0; k < t_n[1]; k++) - { - vis[tt[1][k]] = 0; - } - } - - free(vis); -} - -mb_nodes_t *update_mb_nodes_t(kv_u_trans_t *ref, mc_match_t* ma, uint32_t occ) -{ - uint32_t i, st; - uint64_t *cc = NULL; - mb_nodes_t *x = NULL; CALLOC(x, 1); - x->bid.n = x->u.n = x->idx.n = 0; - kv_resize(uint32_t, x->idx, occ); - x->idx.n = occ; - memset(x->idx.a, -1, sizeof(uint32_t)*x->idx.n); - kvec_t_u32_warp stack; kv_init(stack.a); - uint32_t *flag = NULL; MALLOC(flag, occ); - - cc = mb_nodes_core(ref, ma, occ, flag, &stack); - - for (st = 0, i = 1; i <= occ; ++i) { - if (i == occ || cc[st]>>32 != cc[i]>>32) { - assgin_mb_node(x, ref, ma, flag, &stack, cc, st, i - st); - st = i; - } - } - - free(cc); free(flag); - kv_destroy(stack.a); - - /*******************************for debug************************************/ - // debug_mb_nodes(x, ref, ma); - /*******************************for debug************************************/ - return x; -} - -mb_g_t *init_mb_g_t(mc_match_t* e, kv_u_trans_t *ref, uint32_t is_sys) -{ - mc_edge_t *o = NULL; - uint32_t i, k, m, n, a_n[2], *a[2], qn, tn, qb, tb; - mb_edge_t *t = NULL; - mb_g_t *p = NULL; CALLOC(p, 1); - p->u = update_mb_nodes_t(ref, e, e->n_seq); - p->e = NULL; CALLOC(p->e, 1); - p->e->n_seq = p->u->u.n; - kv_init(p->e->ma); kv_init(p->e->idx); - for (i = 0; i < p->u->u.n; i++)///each block - { - qb = i; - p->u->u.a[i].s[0] = p->u->u.a[i].s[1] = 0; - decode_mb_node(p, i, &(a[0]), &(a_n[0]), NULL, &(a[1]), &(a_n[1]), NULL); - for (k = 0; k < a_n[0]; k++) - { - qn = a[0][k]; - o = pt_a(*e, qn); - n = pt_n(*e, qn); - for (m = 0; m < n; m++) - { - tn = ma_y(o[m]); - tb = p->u->idx.a[tn]>>1;///tn is the unitig id; tb is the block id - if(tb == qb) - { - continue; - } - - kv_pushp(mb_edge_t, p->e->ma, &t); - t->x = (uint64_t)qb << 32 | tb; - t->w[0] = t->w[1] = t->w[2] = t->w[3] = 0; - t->w[p->u->idx.a[tn]&1] = o[m].w; - } - } - - for (k = 0; k < a_n[1]; k++) - { - qn = a[1][k]; - o = pt_a(*e, qn); - n = pt_n(*e, qn); - for (m = 0; m < n; m++) - { - tn = ma_y(o[m]); - tb = p->u->idx.a[tn]>>1; - if(tb == qb) - { - continue; - } - - kv_pushp(mb_edge_t, p->e->ma, &t); - t->x = (uint64_t)qb << 32 | tb; - t->w[0] = t->w[1] = t->w[2] = t->w[3] = 0; - t->w[(p->u->idx.a[tn]&1)+2] = o[m].w; - } - } - } - - radix_sort_mbe(p->e->ma.a, p->e->ma.a + p->e->ma.n); - mb_merge_dup(p); // MUST BE sorted - mb_edges_idx(p->e); - /*******************************for debug************************************/ - // debug_mb_edges_symm(p->e); - /*******************************for debug************************************/ - if(is_sys) mb_edges_symm(p->e); - - return p; -} - -void destory_mc_g_t(mc_g_t **p) -{ - if(!p || !(*p)) return; - if((*p)->s.m == 0) (*p)->s.a = NULL; - kv_destroy((*p)->s); - if((*p)->e) - { - kv_destroy((*p)->e->idx); - kv_destroy((*p)->e->ma); - free((*p)->e->cc); - free((*p)->e); - } - free((*p)); -} - -void destory_mb_g_t(mb_g_t **p) -{ - if(!p || !(*p)) return; - kv_destroy((*p)->e->idx); - kv_destroy((*p)->e->ma); - free((*p)->e->cc); - free((*p)->e); - - kv_destroy((*p)->u->bid); - kv_destroy((*p)->u->idx); - kv_destroy((*p)->u->u); - free((*p)->u); - - free((*p)); -} - - -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); - tmp = a[j]; a[j] = a[i-1]; a[i-1] = tmp; - } -} - - - -static void normalize_mc_edge(mc_edge_t *a, mc_edge_t *b) -{ - if(a->w >= b->w) - { - b->x = (uint32_t)a->x; - b->x <<= 32; - b->x |= (a->x>>32); - b->w = a->w; - } - else - { - a->x = (uint32_t)b->x; - a->x <<= 32; - a->x |= (b->x>>32); - a->w = b->w; - } -} - -uint32_t mc_edges_symm(mc_match_t *ma) -{ - uint8_t *del = NULL; - uint32_t i, k, n = 0; - mc_edge_t *t = NULL, *m = NULL; - CALLOC(del, ma->ma.n); - - for (i = 0; i < ma->ma.n; ++i) { - m = &ma->ma.a[i]; - if (ma_x(*m) == ma_y(*m)) - { - del[i] = 1, ++n;///self overlap - continue; - } - t = get_mc_edge(ma, ma_y(*m), ma_x(*m)); - if(!t) - { - del[i] = 1, ++n;///self overlap - continue; - } - normalize_mc_edge(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; - mc_edges_idx(ma); - } - - free(del); - return n; -} - - -static void normalize_mb_edge(mb_edge_t *a, mb_edge_t *b) -{ - if(a->w >= b->w) - { - b->x = (uint32_t)a->x; - b->x <<= 32; - b->x |= (a->x>>32); - b->w[0] = a->w[0]; - b->w[3] = a->w[3]; - b->w[1] = a->w[2]; - b->w[2] = a->w[1]; - } - else - { - a->x = (uint32_t)b->x; - a->x <<= 32; - a->x |= (b->x>>32); - a->w[0] = b->w[0]; - a->w[3] = b->w[3]; - a->w[1] = b->w[2]; - a->w[2] = b->w[1]; - } -} - -uint32_t mb_edges_symm(mb_match_t *ma) -{ - uint8_t *del = NULL; - uint32_t i, k, n = 0; - mb_edge_t *t = NULL, *m = NULL; - CALLOC(del, ma->ma.n); - - for (i = 0; i < ma->ma.n; ++i) { - m = &ma->ma.a[i]; - if (ma_x(*m) == ma_y(*m)) - { - del[i] = 1, ++n;///self overlap - continue; - } - t = get_mb_edge(ma, ma_y(*m), ma_x(*m)); - if(!t) - { - del[i] = 1, ++n;///self overlap - continue; - } - normalize_mb_edge(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; - mb_edges_idx(ma); - } - - free(del); - return n; -} - -void debug_mc_interval_t(mc_interval_t *p, uint32_t p_n, uint32_t *p_idx, ma_ug_t *ug, asg_t *rg, -trans_chain* t_ch) -{ - 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; - mc_interval_t *a = NULL, *t = NULL; - - for (v = 0; v < ug->u.n; v++) - { - a = p + p_idx[v]; - occ = p_idx[v+1] - p_idx[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 < p_n; v++) - { - t = &(p[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 = &(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+rg->seq[u->a[i]>>33].len - 1)) - { - fprintf(stderr, "ERROR-c, real end: %u\n", - (uint32_t)(offset+rg->seq[u->a[i]>>33].len - 1)); - } - } - - offset += (uint32_t)u->a[i]; - if(i >= sid && i <= eid) - { - if(t_ch->ir_het[u->a[i]>>33] != t->hs) - { - fprintf(stderr, "ERROR-d: is_r_het: %u, h_status: %u\n", t_ch->ir_het[u->a[i]>>33], t->hs); - } - } - } - } -} - -double get_w_scale(kv_u_trans_t *ta) -{ - uint32_t i, max_w_i, min_w_i; - double max_w = 0, min_w = 0, w; - max_w_i = min_w_i = (uint32_t)-1; - for (i = 0; i < ta->n; ++i) - { - if(ta->a[i].del) continue; - if(ta->a[i].nw == 0) continue; - w = (ta->a[i].nw >= 0? ta->a[i].nw:-ta->a[i].nw); - if(max_w_i == (uint32_t)-1 || max_w < w) max_w = w, max_w_i = i; - if(min_w_i == (uint32_t)-1 || min_w > w) min_w = w, min_w_i = i; - } - - if(max_w_i == (uint32_t)-1 || min_w_i == (uint32_t)-1) return 1; - if(min_w > 1.1) return 1; - double sc_max = (double)(1<<30), sc_min = 1.1; - - return MIN(sc_max/max_w, sc_min/min_w) + sc_min; -} - -void update_mc_edges(mc_g_t *mg, hap_overlaps_list* ha, kv_u_trans_t *ta, trans_chain* t_ch, double f_rate, uint32_t is_sys) -{ - uint32_t v, i, k, qn, tn, qs, qe, ts, te, occ, as, ae, l, offset, l_pos; - uint64_t hetLen, homLen, oLen; - mc_interval_t *a = NULL; - mc_edge_t *ma = NULL; - asg_t* nsg = mg->ug->g; - ma_utg_t *u = NULL; - mc_interval_t *t = NULL; - - kvec_t(mc_interval_t) p; kv_init(p); - kvec_t(uint32_t) p_idx; kv_init(p_idx); - if(t_ch) - { - kv_push(uint32_t, p_idx, 0); - for (v = 0; v < nsg->n_seq; v++) - { - u = &(mg->ug->u.a[v]); - for (k = 1, l = 0, offset = 0, l_pos = 0; k <= u->n; ++k) - { - if (k == u->n || t_ch->ir_het[u->a[k]>>33] != t_ch->ir_het[u->a[l]>>33]) - { - kv_pushp(mc_interval_t, p, &t); - t->uID = v; - t->hs = t_ch->ir_het[u->a[l]>>33]; - - t->bS = l_pos; - t->bE = offset + mg->rg->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_idx, p.n); - } - - ///debug_mc_interval_t(p.a, p.n, p_idx.a, mg->ug, mg->rg, t_ch); - } - - if(!mg->e) - { - CALLOC(mg->e, 1); - mg->e->n_seq = mg->ug->g->n_seq; - kv_init(mg->e->idx); kv_init(mg->e->ma); - } - - if(ha) - { - 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; - if(p.n > 0 && p_idx.n > 0) - { - /*****************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 = p.a + p_idx.a[qn]; - occ = p_idx.a[qn+1] - 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 = p.a + p_idx.a[tn]; - occ = p_idx.a[tn+1] - 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(mc_edge_t, mg->e->ma, &ma); - ma->x = (uint64_t)ha->x[v].a.a[i].xUid << 32 | ha->x[v].a.a[i].yUid; - ma->w = ha->x[v].a.a[i].score; - } - } - } - - if(ta) - { - // double sc = get_w_scale(ta); - // fprintf(stderr, "sc: %f\n", sc); - for (i = 0; i < ta->n; ++i) - { - if(ta->a[i].del) continue; - if(p.n > 0 && p_idx.n > 0) - { - /*****************qn*****************/ - qn = ta->a[i].qn; - qs = ta->a[i].qs; - qe = ta->a[i].qe - 1; - - a = p.a + p_idx.a[qn]; - occ = p_idx.a[qn+1] - 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 = ta->a[i].tn; - ts = ta->a[i].ts; - te = ta->a[i].te - 1; - - a = p.a + p_idx.a[tn]; - occ = p_idx.a[tn+1] - 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(mc_edge_t, mg->e->ma, &ma); - ma->x = (uint64_t)ta->a[i].qn << 32 | ta->a[i].tn; - // ma->w = w_cast((ta->a[i].nw*sc)); - ma->w = w_cast((ta->a[i].nw)); - } - } - - for (i = k = 0; i < mg->e->ma.n; i++) - { - if(mg->e->ma.a[i].w == 0) continue; - mg->e->ma.a[k] = mg->e->ma.a[i]; - k++; - } - mg->e->ma.n = k; - - radix_sort_mce(mg->e->ma.a, mg->e->ma.a + mg->e->ma.n); - mc_merge_dup(mg); - mc_edges_idx(mg->e); - if(is_sys) mc_edges_symm(mg->e); - kv_destroy(p); kv_destroy(p_idx); -} - -void debug_mc_g_t(mc_g_t *mg) -{ - fprintf(stderr, "0----------[M::%s]----------\n", __func__); - mc_edge_t *o = NULL, *s = NULL; - uint32_t i, k, n, cnt; - for (i = 0; i < mg->e->n_seq; ++i) - { - o = pt_a(*(mg->e), i); n = pt_n(*(mg->e), i); - for (k = 0; k < n; ++k) - { - if(ma_x(o[k]) != i) fprintf(stderr, "ERROR-g\n"); - s = get_mc_edge(mg->e, ma_y(o[k]), ma_x(o[k])); - if(!s) fprintf(stderr, "ERROR-e\n"); - if(s) - { - if(!(ma_x(*s) == ma_y(o[k]) && ma_y(*s) == ma_x(o[k]) && s->w == o[k].w)) - { - fprintf(stderr, "ERROR-f\n"); - } - } - } - - for (k = cnt = 0; k < mg->e->ma.n; ++k) - { - if(ma_x(mg->e->ma.a[k]) == i) cnt++; - } - - if(cnt != n) fprintf(stderr, "ERROR-h\n"); - } -} - -uint64_t *mc_g_cc_core(mc_match_t *ma) -{ - uint32_t i, x, y, *flag; - uint64_t *group; - mc_edge_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 = ma_y(o[j]); - 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_mc64(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 mc_g_cc(mc_match_t *ma) -{ - ma->cc = mc_g_cc_core(ma); -} -mc_bp_t *mc_bp_t_init(mc_match_t *ma, mc_svaux_t *b_aux, bubble_type* bub, uint64_t n_thread) -{ - uint32_t i, k, n; - mc_bp_t *bp = NULL; - ma_utg_t *u = NULL; - CALLOC(bp, 1); - bp->b_aux = b_aux; - bp->ma = ma; - bp->b_b = bub; - bp->n_thread = n_thread; - CALLOC(bp->lock, bub->ug->g->n_seq); - CALLOC(bp->res, n_thread); - CALLOC(bp->vis, n_thread); - for (i = 0; i < n_thread; i++) - { - bp->vis[i].m = bp->vis[i].n = bub->ug->g->n_seq; - CALLOC(bp->vis[i].a, bp->vis[i].n); - } - - - MALLOC(bp->idx, bub->chain_weight.n+1); - bp->idx_n = bp->occ = 0; - for (i = 0; i < bub->chain_weight.n; i++) - { - bp->idx[i] = bp->occ; - bp->idx_n++; - if(bub->chain_weight.a[i].del) continue; - u = &(bub->b_ug->u.a[bub->chain_weight.a[i].id]);///list of bubbles - for (k = 0; k < u->n; k++) - { - get_bubbles(bub, u->a[k]>>33, NULL, NULL, NULL, &n, NULL); - bp->occ += n; - } - } - bp->idx[i] = bp->occ; - fprintf(stderr, "# nodes in chains: %lu, # chains: %lu\n", bp->occ, bp->idx_n); - return bp; -} - -void destroy_mc_bp_t(mc_bp_t **bp) -{ - uint32_t i; - for (i = 0; i < (*bp)->n_thread; i++) - { - free((*bp)->vis[i].a); - } - free((*bp)->idx); - free((*bp)->res); - free((*bp)->lock); - free((*bp)); -} - -mc_svaux_t *mc_svaux_init(const mc_g_t *mg, uint64_t x) -{ - uint32_t st, i, max_cc = 0; - mc_match_t *ma = mg->e; - mc_svaux_t *b; - CALLOC(b, 1); - b->x = x; - for (st = 0, i = 1; i <= ma->n_seq; ++i) - if (i == ma->n_seq || ma->cc[st]>>32 != ma->cc[i]>>32) - max_cc = max_cc > i - st? max_cc : i - st, st = i; - kv_init(b->cc_edge); - MALLOC(b->cc_node, max_cc); - ///CALLOC(b->s, ma->n_seq); - b->s = mg->s.a; - CALLOC(b->s_opt, ma->n_seq); - MALLOC(b->bfs, ma->n_seq); - - MALLOC(b->bfs_mark, ma->n_seq); - memset(b->bfs_mark, -1, ma->n_seq*sizeof(uint32_t)); - - CALLOC(b->z, ma->n_seq); - CALLOC(b->z_opt, ma->n_seq); - CALLOC(b->f, ma->n_seq); - return b; -} -void mc_svaux_destroy(mc_svaux_t *b) -{ - b->s = NULL; - kv_destroy(b->cc_edge); free(b->cc_node); - free(b->s); free(b->s_opt); - free(b->z); free(b->z_opt); - free(b->bfs); free(b->bfs_mark); - free(b->f); - free(b); -} - - -mb_svaux_t *mb_svaux_init(const mb_g_t *mg, uint64_t x) -{ - uint32_t st, i, max_cc = 0; - mb_match_t *ma = mg->e; - mb_svaux_t *b; - CALLOC(b, 1); - b->x = x; - for (st = 0, i = 1; i <= ma->n_seq; ++i) - if (i == ma->n_seq || ma->cc[st]>>32 != ma->cc[i]>>32) - max_cc = max_cc > i - st? max_cc : i - st, st = i; - kv_init(b->cc_edge); - MALLOC(b->cc_node, max_cc); - - b->u = mg->u->u.a; - CALLOC(b->u_opt, ma->n_seq); - - MALLOC(b->bfs, ma->n_seq); - MALLOC(b->bfs_mark, ma->n_seq); - memset(b->bfs_mark, -1, ma->n_seq*sizeof(uint32_t)); - - CALLOC(b->f, ma->n_seq); - return b; -} - -void mb_svaux_destroy(mb_svaux_t *b) -{ - b->u = NULL; - kv_destroy(b->cc_edge); free(b->cc_node); - free(b->u); free(b->u_opt); - free(b->bfs); free(b->bfs_mark); - free(b->f); - free(b); -} - - -mc_svaux_t_mul *init_mc_svaux_t_mul(const mc_g_t *mg, uint64_t n_threads) -{ - uint32_t st, i; - mc_match_t *ma = mg->e; - mc_svaux_t_mul *b; CALLOC(b, 1); - for (st = 0, i = 1, b->n_t = 0; i <= ma->n_seq; ++i) - { - if (i == ma->n_seq || ma->cc[st]>>32 != ma->cc[i]>>32) - { - b->n_t++; - } - } - b->n_g = b->n_t; - if(n_threads < b->n_t) b->n_t = n_threads; - - kv_init(b->cc_edge); - MALLOC(b->bfs_mark, ma->n_seq); - memset(b->bfs_mark, -1, ma->n_seq*sizeof(uint32_t)); - CALLOC(b->s_opt, ma->n_seq); - CALLOC(b->z, ma->n_seq); - CALLOC(b->z_opt, ma->n_seq); - b->s = mg->s.a; - - kv_init(b->bs); CALLOC(b->bs.a, b->n_t); - b->bs.n = b->bs.m = b->n_t; - for (i = 0; i < b->bs.n; i++) - { - kv_init(b->bs.a[i].cc_node); - kv_init(b->bs.a[i].bfs); - b->bs.a[i].bfs_mark = b->bfs_mark; - b->bs.a[i].z = b->z; - b->bs.a[i].z_opt = b->z_opt; - b->bs.a[i].s = b->s; - b->bs.a[i].s_opt = b->s_opt; - } - return b; -} - - -void destroy_mc_svaux_t_mul(mc_svaux_t_mul *b) -{ - uint32_t i; - kv_destroy(b->cc_edge); - free(b->bfs_mark); - free(b->s_opt); - free(b->z); - free(b->z_opt); - b->s = NULL; - for (i = 0; i < b->bs.n; i++) - { - kv_destroy(b->bs.a[i].cc_node); - kv_destroy(b->bs.a[i].bfs); - } - kv_destroy(b->bs); - free(b); -} - -uint32_t mc_best(const mc_match_t *ma, mc_svaux_t *b) -{ - uint32_t i, max_i = (uint32_t)-1; - t_w_t w, max_w; - for (i = 0, max_w = -1; i < b->cc_size; ++i) { - uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///uid - if(b->f[k] || b->s[k] == 0) continue; - ///z += -((t_w_t)(b->s[k])) * (b->z[k].z[0] - b->z[k].z[1]); - ///-((t_w_t)(b->s[k])) * (b->z[k].z[0] - b->z[k].z[1]) current - ///((t_w_t)(b->s[k])) * (b->z[k].z[0] - b->z[k].z[1]) flipped - w = ((t_w_t)(b->s[k])) * (b->z[k].z[0] - b->z[k].z[1]) * 2; - if(w <= 0) continue; - if(w > max_w) - { - w = max_w; max_i = k; - } - } - - return max_i; -} - -t_w_t mb_score(mb_g_t *mbg, mb_svaux_t *b) -{ - uint32_t i; - t_w_t z = 0; - mb_match_t *ma = mbg->e; - for (i = 0; i < b->cc_size; ++i) { - uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///uid - ///a[0] - z += -(t_w_t)(mbg->u->u.a[k].s[0]) * (mbg->u->u.a[k].z[0] - mbg->u->u.a[k].z[1]); - ///a[1] - z += -(t_w_t)(mbg->u->u.a[k].s[1]) * (mbg->u->u.a[k].z[2] - mbg->u->u.a[k].z[3]); - } - return z; -} - -t_w_t mc_score(const mc_match_t *ma, mc_svaux_t *b) -{ - uint32_t i; - t_w_t z = 0; - for (i = 0; i < b->cc_size; ++i) { - uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///uid - z += -((t_w_t)(b->s[k])) * (b->z[k].z[0] - b->z[k].z[1]); - } - return z; -} - -t_w_t mc_score_all(const mc_match_t *ma, mc_svaux_t *b) -{ - uint32_t k; - t_w_t z = 0; - for (k = 0; k < ma->n_seq; ++k) - { - z += -((t_w_t)(b->s[k])) * (b->z[k].z[0] - b->z[k].z[1]); - } - return z; -} - -void mc_reset_z(const mc_match_t *ma, mc_svaux_t *b) -{ - uint32_t i; - for (i = 0; i < b->cc_size; ++i) { - uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///uid - uint32_t o = ma->idx.a[k] >> 32; - uint32_t j, n = (uint32_t)ma->idx.a[k]; - b->z[k].z[0] = b->z[k].z[1] = 0; - for (j = 0; j < n; ++j) { - const mc_edge_t *e = &ma->ma.a[o + j]; - uint32_t t = ma_y(*e); - if (b->s[t] > 0) b->z[k].z[0] += e->w; - else if (b->s[t] < 0) b->z[k].z[1] += e->w; - } - } -} - -void mc_reset_z_debug(const mc_match_t *ma, mc_svaux_t *b) -{ - uint32_t i; - t_w_t z[2]; - for (i = 0; i < b->cc_size; ++i) { - uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///uid - uint32_t o = ma->idx.a[k] >> 32; - uint32_t j, n = (uint32_t)ma->idx.a[k]; - z[0] = b->z[k].z[0]; z[1] = b->z[k].z[1]; - b->z[k].z[0] = b->z[k].z[1] = 0; - for (j = 0; j < n; ++j) { - const mc_edge_t *e = &ma->ma.a[o + j]; - uint32_t t = ma_y(*e); - if (b->s[t] > 0) b->z[k].z[0] += e->w; - else if (b->s[t] < 0) b->z[k].z[1] += e->w; - } - if(z[0] != b->z[k].z[0]) fprintf(stderr, "ERROR1\n"); - if(z[1] != b->z[k].z[1]) fprintf(stderr, "ERROR2\n"); - } -} - - -t_w_t mc_init_spin(const mc_match_t *ma, mc_svaux_t *b) -{ - uint32_t i; - b->cc_edge.n = 0; - if(b->cc_size <= 2)//mannually clear - { - for (i = 0; i < b->cc_size; ++i) {///how many nodes - b->s[(uint32_t)ma->cc[b->cc_off + i]] = 0; - } - } - - for (i = 0; i < b->cc_size; ++i) {///how many nodes - uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///node id - b->cc_node[i] = k; - if(b->s[k] == 0) break; - } - if(i >= b->cc_size) goto passed; - - for (i = 0; i < b->cc_size; ++i) {///how many nodes - uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///node id - uint32_t o = ma->idx.a[k] >> 32;///cc group id - uint32_t n = (uint32_t)ma->idx.a[k], j; - b->cc_node[i] = k; - for (j = 0; j < n; ++j) { - w_t w = ma->ma.a[o + j].w; - w = w > 0? w : -w; - kv_push(uint64_t, b->cc_edge, (uint64_t)((uint32_t)-1 - ((uint32_t)w)) << 32 | (o + j)); - } - } - radix_sort_mc64(b->cc_edge.a, b->cc_edge.a + b->cc_edge.n); - for (i = 0; i < b->cc_edge.n; ++i) { // from the strongest edge to the weakest - const mc_edge_t *e = &ma->ma.a[(uint32_t)b->cc_edge.a[i]]; - uint32_t n1 = ma_x(*e), n2 = ma_y(*e); - if (b->s[n1] == 0 && b->s[n2] == 0) { - b->x = kr_splitmix64(b->x); - b->s[n1] = b->x&1? 1 : -1; - b->s[n2] = e->w > 0? -b->s[n1] : b->s[n1]; - }/****************************may have bugs********************************/ - else if(b->s[n1] == 0) - { - b->s[n1] = e->w > 0? -b->s[n2] : b->s[n2]; - } - else if(b->s[n2] == 0) - { - b->s[n2] = e->w > 0? -b->s[n1] : b->s[n1]; - } - /****************************may have bugs********************************/ - } - - passed: - mc_reset_z(ma, b); - return mc_score(ma, b); -} -///k is uid -static void mc_set_spin(const mc_match_t *ma, mc_svaux_t *b, uint32_t k, int8_t s) -{ - uint32_t o, j, n; - int8_t s0 = b->s[k]; - if (s0 == s) return; - o = ma->idx.a[k] >> 32; - n = (uint32_t)ma->idx.a[k]; - for (j = 0; j < n; ++j) { - const mc_edge_t *e = &ma->ma.a[o + j]; - uint32_t t = ma_y(*e);///1->z[0]; (-1)->z[1]; - if (s0 != 0) b->z[t].z[(s0 < 0)] -= e->w; - if (s != 0) b->z[t].z[(s < 0)] += e->w; - } - b->s[k] = s; -} - -void debug_mb_z(mb_g_t *mbg, uint32_t k) -{ - t_w_t z[4]; - z[0] = z[1] = z[2] = z[3] = 0; - mb_match_t *ma = mbg->e; - uint32_t o = ma->idx.a[k] >> 32; - uint32_t j, n = (uint32_t)ma->idx.a[k]; - - for (j = 0; j < n; ++j) { - const mb_edge_t *e = &ma->ma.a[o + j]; - uint32_t t = ma_y(*e); - - ///a[0]->b[0] - if(mbg->u->u.a[t].s[0] > 0) z[0] += e->w[0]; - else if(mbg->u->u.a[t].s[0] < 0) z[1] += e->w[0]; - - ///a[0]->b[1] - if(mbg->u->u.a[t].s[1] > 0) z[0] += e->w[1]; - else if(mbg->u->u.a[t].s[1] < 0) z[1] += e->w[1]; - - ///a[1]->b[0] - if(mbg->u->u.a[t].s[0] > 0) z[2] += e->w[2]; - else if(mbg->u->u.a[t].s[0] < 0) z[3] += e->w[2]; - - ///a[1]->b[1] - if(mbg->u->u.a[t].s[1] > 0) z[2] += e->w[3]; - else if(mbg->u->u.a[t].s[1] < 0) z[3] += e->w[3]; - } - - if(mbg->u->u.a[k].z[0] != z[0]) fprintf(stderr, "ERROR-0-::%s, z[0]: %f, n-z[0]: %f\n", __func__, z[0], mbg->u->u.a[k].z[0]); - if(mbg->u->u.a[k].z[1] != z[1]) fprintf(stderr, "ERROR-1-::%s, z[1]: %f, n-z[1]: %f\n", __func__, z[1], mbg->u->u.a[k].z[1]); - if(mbg->u->u.a[k].z[2] != z[2]) fprintf(stderr, "ERROR-2-::%s, z[2]: %f, n-z[2]: %f\n", __func__, z[2], mbg->u->u.a[k].z[2]); - if(mbg->u->u.a[k].z[3] != z[3]) fprintf(stderr, "ERROR-3-::%s, z[3]: %f, n-z[3]: %f\n", __func__, z[3], mbg->u->u.a[k].z[3]); -} - -///k is uid -static void mb_flip_spin(mb_g_t *mbg, mb_svaux_t *b, uint32_t k) -{ - if(mbg->u->u.a[k].s[0] == 0 && mbg->u->u.a[k].s[1] == 0) return; - mb_match_t *ma = mbg->e; - uint32_t o, j, n; - o = ma->idx.a[k] >> 32; - n = (uint32_t)ma->idx.a[k]; - mbg->u->u.a[k].s[0] = -mbg->u->u.a[k].s[0]; - mbg->u->u.a[k].s[1] = -mbg->u->u.a[k].s[1]; - for (j = 0; j < n; ++j) { - const mb_edge_t *e = &ma->ma.a[o + j]; - uint32_t t = ma_y(*e);///1->z[0]; (-1)->z[1]; - - if(mbg->u->u.a[k].s[0] != 0) - { - ///note: e is from k to t - ///t[0] ---> k[0], so update z[0 + x] and e[0] - mbg->u->u.a[t].z[mbg->u->u.a[k].s[0] < 0] += e->w[0]; - mbg->u->u.a[t].z[mbg->u->u.a[k].s[0] > 0] -= e->w[0]; - - ///t[1] ---> k[0], so update z[2 + x] and e[1] - mbg->u->u.a[t].z[(mbg->u->u.a[k].s[0] < 0) + 2] += e->w[1]; - mbg->u->u.a[t].z[(mbg->u->u.a[k].s[0] > 0) + 2] -= e->w[1]; - } - - if(mbg->u->u.a[k].s[1] != 0) - { - ///note: e is from k to t - ///t[0] ---> k[1], so update z[0 + x] and e[2] - mbg->u->u.a[t].z[mbg->u->u.a[k].s[1] < 0] += e->w[2]; - mbg->u->u.a[t].z[mbg->u->u.a[k].s[1] > 0] -= e->w[2]; - - ///t[1] ---> k[1], so update z[2 + x] and e[3] - mbg->u->u.a[t].z[(mbg->u->u.a[k].s[1] < 0) + 2] += e->w[3]; - mbg->u->u.a[t].z[(mbg->u->u.a[k].s[1] > 0) + 2] -= e->w[3]; - } - - /*******************************for debug************************************/ - // debug_mb_z(mbg, t); - /*******************************for debug************************************/ - } -} - -void mc_best_flip(const mc_match_t *ma, mc_svaux_t *b) -{ - uint32_t idx; - for (idx = 0; idx < b->cc_size; ++idx) { - b->f[(uint32_t)ma->cc[b->cc_off + idx]] = 0; - ///uint32_t k = (uint32_t)ma->cc[b->cc_off + idx];///uid - } - while (1) - { - idx = mc_best(ma, b); - if(idx == (uint32_t)-1) break; - mc_set_spin(ma, b, idx, -b->s[idx]); - b->f[idx] = 1; - } -} - -static t_w_t mc_optimize_local(const mc_opt_t *opt, const mc_match_t *ma, mc_svaux_t *b, uint32_t *n_iter) -{ - uint32_t i, n_flip = 0; - int32_t n_iter_local = 0; - while (n_iter_local < opt->max_iter) { - ++(*n_iter); - ks_shuffle_uint32_t(b->cc_size, b->cc_node, &b->x); - for (i = n_flip = 0; i < b->cc_size; ++i) { - uint32_t k = b->cc_node[i];///uid - int8_t s; - if (b->z[k].z[0] == b->z[k].z[1]) continue; - s = b->z[k].z[0] > b->z[k].z[1]? -1 : 1; - if (b->s[k] != s) { - // fprintf(stderr, "utg%.6dl, s[k]::%d, s::%d\n", (int32_t)(k)+1, b->s[k], s); - mc_set_spin(ma, b, k, s);///no need to change the score of k itself - ++n_flip; - } - } - ++n_iter_local; - if (n_flip == 0) break; - } - - // if(n_flip != 0) mc_best_flip(ma, b); - return mc_score(ma, b); -} - -static t_w_t mb_optimize_local(const mc_opt_t *opt, mb_g_t *mbg, mb_svaux_t *b, uint32_t *n_iter) -{ - uint32_t i, n_flip = 0; - int32_t n_iter_local = 0; - mb_node_t *u = NULL; - t_w_t z = 0; - while (n_iter_local < opt->max_iter) { - ++(*n_iter); - ks_shuffle_uint32_t(b->cc_size, b->cc_node, &b->x); - for (i = n_flip = 0; i < b->cc_size; ++i) { - uint32_t k = b->cc_node[i];///uid - u = &(mbg->u->u.a[k]); - if(u->z[0] == u->z[1] && u->z[2] == u->z[3]) continue; - z = 0; - ///a[0] - z += -(t_w_t)(u->s[0]) * (u->z[0] - u->z[1]); - ///a[1] - z += -(t_w_t)(u->s[1]) * (u->z[2] - u->z[3]); - if(z >= 0) continue; - - mb_flip_spin(mbg, b, k);///no need to change the score of k itself - ++n_flip; - } - ++n_iter_local; - if (n_flip == 0) break; - } - - // if(n_flip != 0) mc_best_flip(ma, b); - return mb_score(mbg, b); -} - -static void mc_perturb(const mc_opt_t *opt, const mc_match_t *ma, mc_svaux_t *b) -{ - uint32_t i; - for (i = 0; i < b->cc_size; ++i) { - uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///node id - double y; - y = kr_drand_r(&b->x); - if (y < opt->f_perturb) - mc_set_spin(ma, b, k, -b->s[k]); - } -} - -static void mb_perturb(const mc_opt_t *opt, mb_g_t *mbg, mb_svaux_t *b) -{ - uint32_t i; - for (i = 0; i < b->cc_size; ++i) { - uint32_t k = (uint32_t)mbg->e->cc[b->cc_off + i];///node id - double y; - y = kr_drand_r(&b->x); - if (y < opt->f_perturb) - mb_flip_spin(mbg, b, k); - } -} - -static uint32_t mc_bfs(const mc_match_t *ma, mc_svaux_t *b, uint32_t k0, uint32_t bfs_round, uint32_t max_size) -{ - uint32_t i, n_bfs = 0, st, en, r; - b->bfs[n_bfs++] = k0, b->bfs_mark[k0] = k0; - st = 0, en = n_bfs; - for (r = 0; r < bfs_round; ++r) { - for (i = st; i < en; ++i) { - uint32_t k = b->bfs[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) { - uint32_t t = (uint32_t)ma->ma.a[o + j].x; - if (b->bfs_mark[t] != k0) - b->bfs[n_bfs++] = t, b->bfs_mark[t] = k0; - } - } - st = en, en = n_bfs; - if (max_size > 0 && n_bfs > max_size) break; - } - return n_bfs; -} - -///bfs_round is 3 -static void mc_perturb_node(const mc_opt_t *opt, const mc_match_t *ma, mc_svaux_t *b, int32_t bfs_round) -{ - uint32_t i, k, n_bfs = 0; - k = (uint32_t)(kr_drand_r(&b->x) * b->cc_size + .499); - if(k >= b->cc_size) k = b->cc_size - 1; - k = (uint32_t)ma->cc[b->cc_off + k];///node id - n_bfs = mc_bfs(ma, b, k, bfs_round, (int32_t)(b->cc_size * opt->f_perturb)); - for (i = 0; i < n_bfs; ++i) - mc_set_spin(ma, b, b->bfs[i], -b->s[b->bfs[i]]); -} - - -static uint32_t mb_bfs(const mb_match_t *ma, mb_svaux_t *b, uint32_t k0, uint32_t bfs_round, uint32_t max_size) -{ - uint32_t i, n_bfs = 0, st, en, r; - b->bfs[n_bfs++] = k0, b->bfs_mark[k0] = k0; - st = 0, en = n_bfs; - for (r = 0; r < bfs_round; ++r) { - for (i = st; i < en; ++i) { - uint32_t k = b->bfs[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) { - uint32_t t = (uint32_t)ma->ma.a[o + j].x; - if (b->bfs_mark[t] != k0) - b->bfs[n_bfs++] = t, b->bfs_mark[t] = k0; - } - } - st = en, en = n_bfs; - if (max_size > 0 && n_bfs > max_size) break; - } - return n_bfs; -} - -///bfs_round is 3 -static void mb_perturb_node(const mc_opt_t *opt, mb_g_t *mbg, mb_svaux_t *b, int32_t bfs_round) -{ - uint32_t i, k, n_bfs = 0; - k = (uint32_t)(kr_drand_r(&b->x) * b->cc_size + .499); - if(k >= b->cc_size) k = b->cc_size - 1; - k = (uint32_t)mbg->e->cc[b->cc_off + k];///node id - n_bfs = mb_bfs(mbg->e, b, k, bfs_round, (int32_t)(b->cc_size * opt->f_perturb)); - for (i = 0; i < n_bfs; ++i) - mb_flip_spin(mbg, b, b->bfs[i]); -} - -void clean_mc_bp_res(mc_bp_res *res) -{ - res->chain_id = (uint32_t)-1; - res->f_bid = res->f_uid = res->l_bid = res->l_uid = (uint32_t)-1; - res->id = (uint32_t)-1; res->w = -1; -} - -void reset_mc_bp_iter(mc_bp_t* bp, mc_bp_iter *x, uint64_t id) -{ - ma_utg_t *u = NULL; - uint32_t i, n, occ; - for (i = 0; i < bp->idx_n; i++) - { - if(id >= bp->idx[i]) break; - } - - id -= bp->idx[i]; - x->chain_id = bp->b_b->chain_weight.a[i].id; - u = &(bp->b_b->b_ug->u.a[x->chain_id]); - for (i = occ = 0; i < u->n; i++) - { - get_bubbles(bp->b_b, u->a[i]>>33, NULL, NULL, NULL, &n, NULL); - occ += n; - if(id < occ) - { - x->bid = i; - x->uid = id - (occ -n); - break; - } - } -} -inline uint32_t next_uid(mc_bp_iter *iter, bubble_type* bub, uint32_t *c_bid, uint32_t *c_uid) -{ - ma_utg_t *u = &(bub->b_ug->u.a[iter->chain_id]); - uint32_t *a, n, uid; - while (1) - { - if(iter->bid >= u->n) break; - get_bubbles(bub, u->a[iter->bid]>>33, NULL, NULL, &a, &n, NULL); - while (1) - { - if(iter->uid >= n) break; - uid = a[iter->uid]>>1; - if(c_bid) (*c_bid) = iter->bid; - if(c_uid) (*c_uid) = iter->uid; - iter->uid++; - return uid; - } - iter->bid++, iter->uid = 0; - } - return (uint32_t)-1; -} - -t_w_t incre_weight(mc_svaux_t *b_aux, mc_match_t *ma, uint8_t* vis, uint32_t uid) -{ - mc_edge_t *o = NULL; - uint32_t n, i, t; - t_w_t w = ((t_w_t)(b_aux->s[uid])) * (b_aux->z[uid].z[0] - b_aux->z[uid].z[1]) * 2; - t_w_t w_off = 0; - o = pt_a(*ma, uid); - n = pt_n(*ma, uid); - for (i = 0; i < n; ++i) - { - t = ma_y(o[i]); - if(vis[t] == 0) continue; - if(t == uid) continue; - w_off += (b_aux->s[uid]*b_aux->s[t]*o[i].w); - } - return w - (w_off*4);//2 for self; 4 for both directions -} - -void select_min_bp(bubble_type* bub, mc_match_t *ma, mc_svaux_t *b_aux, mc_bp_t* bp, -uint8_t *lock, bits_p *vis, uint64_t id, mc_bp_res* r) -{ - uint32_t uid, val = 0, max_bid, max_uid, c_bid, c_uid, f_bid, f_uid; - t_w_t w = 0, max_w = -1; - mc_bp_iter i; - reset_mc_bp_iter(bp, &i, id); - memset(vis->a, 0, vis->n); - max_bid = max_uid = (uint32_t)-1; - f_bid = i.bid; f_uid = i.uid;///f_bid::bubble id, f_uid::unitig id - - while (1) - { - uid = next_uid(&i, bub, &c_bid, &c_uid); - if(uid == (uint32_t)-1) break; - if(vis->a[uid]) continue; ///already flip uid - ///update w - w += incre_weight(b_aux, ma, vis->a, uid); - vis->a[uid] = 1; - if(lock[uid] == 0) val = 1; - if(val == 0) continue; - ///update max_w - if(max_w < w) - { - max_w = w; - max_bid = c_bid; - max_uid = c_uid; - } - } - - if(max_w <= 0 || max_bid == (uint32_t)-1 || max_uid == (uint32_t)-1) return; - if((max_w > r->w) || (max_w == r->w && id < r->id)) - { - r->w = max_w; - r->id = id; - r->chain_id = i.chain_id; - r->l_bid = max_bid; - r->l_uid = max_uid; - r->f_bid = f_bid; - r->f_uid = f_uid; - } - ///if((res->min_w > i_b->weight) || (res->min_w == i_b->weight && id < res->min_idx)) -} - -static void worker_for_min_bp(void *data, long i, int tid) // callback for kt_for() -{ - mc_bp_t* bp = (mc_bp_t *)data; - select_min_bp(bp->b_b, bp->ma, bp->b_aux, bp, bp->lock, &(bp->vis[tid]), i, &(bp->res[tid])); -} - -uint32_t best_bp(mc_bp_t *bp, mc_bp_res *res) -{ - uint32_t i; - clean_mc_bp_res(res); - for (i = 0; i < bp->n_thread; i++) - { - clean_mc_bp_res(&(bp->res[i])); - } - kt_for(bp->n_thread, worker_for_min_bp, bp, bp->occ); - - for (i = 0; i < bp->n_thread; i++) - { - if(bp->res[i].chain_id == (uint32_t)-1) continue; - if(bp->res[i].w <= 0) continue; - if((bp->res[i].w > res->w) || (bp->res[i].w == res->w && bp->res[i].id < res->id)) - { - (*res) = bp->res[i]; - } - } - if(res->chain_id != (uint32_t)-1) return 1; - return 0; -} - -void mc_set_bp_spin(bubble_type* bub, mc_match_t *ma, mc_svaux_t *b_aux, mc_bp_t* bp, -uint8_t *lock, bits_p *vis, mc_bp_res *res) -{ - uint32_t uid, val = 0, c_bid, c_uid; - mc_bp_iter i; - i.chain_id = res->chain_id; - i.bid = res->f_bid; - i.uid = res->f_uid; - memset(vis->a, 0, vis->n); - while (1) - { - uid = next_uid(&i, bub, &c_bid, &c_uid); - if(uid == (uint32_t)-1) break; - if(lock[uid] == 0) - { - val = 1; - break; - } - if(c_bid == res->l_bid && c_uid == res->l_uid) break; - } - - if(val == 0) - { - fprintf(stderr, "ERROR-1\n"); - return; - } - - i.bid = res->f_bid; - i.uid = res->f_uid; - while (1) - { - uid = next_uid(&i, bub, &c_bid, &c_uid); - if(uid == (uint32_t)-1) break; - if(vis->a[uid] == 1) continue; - lock[uid] = 1; - vis->a[uid] = 1; - mc_set_spin(ma, b_aux, uid, -b_aux->s[uid]); - if(c_bid == res->l_bid && c_uid == res->l_uid) break; - } -} - -t_w_t mc_solve_bp_cc(mc_bp_t *bp) -{ - mc_bp_res res; - memset(bp->lock, 0, bp->b_b->ug->g->n_seq); - while (best_bp(bp, &res)) - { - mc_set_bp_spin(bp->b_b, bp->ma, bp->b_aux, bp, bp->lock, &(bp->vis[0]), &res); - } - - return mc_score_all(bp->ma, bp->b_aux); -} - -void mc_reset_z_all(const mc_match_t *ma, mc_svaux_t *b) -{ - // t_w_t z[2]; - uint32_t k; - for (k = 0; k < ma->n_seq; ++k) - { - uint32_t o = ma->idx.a[k] >> 32; - uint32_t j, n = (uint32_t)ma->idx.a[k]; - // z[0] = b->z[k].z[0]; z[1] = b->z[k].z[1]; - b->z[k].z[0] = b->z[k].z[1] = 0; - for (j = 0; j < n; ++j) { - const mc_edge_t *e = &ma->ma.a[o + j]; - uint32_t t = ma_y(*e); - if (b->s[t] > 0) b->z[k].z[0] += e->w; - else if (b->s[t] < 0) b->z[k].z[1] += e->w; - } - // if(z[0] != b->z[k].z[0]) fprintf(stderr, "ERROR1-all\n"); - // if(z[1] != b->z[k].z[1]) fprintf(stderr, "ERROR2-all\n"); - } -} - -void mc_solve_bp(mc_bp_t *bp) -{ - double index_time = yak_realtime(); - uint32_t r = 1; - t_w_t sc_opt, sc; - mc_reset_z_all(bp->ma, bp->b_aux); - sc_opt = mc_score_all(bp->ma, bp->b_aux); - - while (1) - { - sc = mc_solve_bp_cc(bp); - // fprintf(stderr, "[M::%s::# round: %u] sc_opt: %ld, sc: %ld\n", __func__, r, sc_opt, sc); - fprintf(stderr, "[M::%s::# round: %u] sc_opt: %f, sc: %f\n", __func__, r, sc_opt, sc); - if(sc <= sc_opt) break; - sc_opt = sc; - r++; - } - fprintf(stderr, "[M::%s::%.3f] ==> round %u\n", __func__, yak_realtime()-index_time, r); -} - -t_w_t mc_score_all_advance(const mc_match_t *ma, int8_t *s) -{ - uint32_t k; - t_w_t z[2], zt = 0; - for (k = 0; k < ma->n_seq; ++k) - { - uint32_t o = ma->idx.a[k] >> 32; - uint32_t j, n = (uint32_t)ma->idx.a[k]; - z[0] = z[1] = 0; - for (j = 0; j < n; ++j) { - const mc_edge_t *e = &ma->ma.a[o + j]; - uint32_t t = ma_y(*e); - if (s[t] > 0) z[0] += e->w; - else if (s[t] < 0) z[1] += e->w; - } - zt += -((t_w_t)(s[k])) * (z[0] - z[1]); - } - return zt; -} - -void mc_status_all(const mc_match_t *ma, int8_t *s) -{ - t_w_t tt_w = mc_score_all_advance(ma, s); - uint64_t k, nn = 0, ne = 0; - for (k = 0; k < ma->n_seq; ++k) { - if((uint32_t)ma->idx.a[k]) nn++; - ne += (uint32_t)ma->idx.a[k]; - } - fprintf(stderr, "[M::%s::] ==> # nodes: %lu, # edges: %lu, weight: %f\n", __func__, nn, ne, tt_w); -} - - -t_w_t mb_score_all_advance(const mc_match_t *ma, mb_g_t *mbg) -{ - uint32_t k; - t_w_t z[2], zt = 0; - for (k = 0; k < ma->n_seq; ++k) - { - uint32_t o = ma->idx.a[k] >> 32; - uint32_t j, n = (uint32_t)ma->idx.a[k]; - z[0] = z[1] = 0; - for (j = 0; j < n; ++j) { - const mc_edge_t *e = &ma->ma.a[o + j]; - uint32_t t = ma_y(*e); - if (mbg->u->u.a[mbg->u->idx.a[t]>>1].s[mbg->u->idx.a[t]&1] > 0) z[0] += e->w; - else if (mbg->u->u.a[mbg->u->idx.a[t]>>1].s[mbg->u->idx.a[t]&1] < 0) z[1] += e->w; - } - zt += -((t_w_t)(mbg->u->u.a[mbg->u->idx.a[k]>>1].s[mbg->u->idx.a[k]&1])) * (z[0] - z[1]); - } - return zt; -} - -void print_sc(const mc_opt_t *opt, const mc_g_t *mg, mc_svaux_t *b, t_w_t sc_opt, uint32_t n_iter) -{ - t_w_t w = mc_score(mg->e, b); - // if(w != sc_opt) fprintf(stderr, "ERROR\n"); - fprintf(stderr, "# iter: %u, sc_opt: %f, sc-local: %f, sc-global: %f\n", n_iter, sc_opt, w, mc_score_all_advance(mg->e, mg->s.a)); -} - -void print_mc_node(const mc_match_t *ma, mc_svaux_t *b, uint32_t id) -{ - fprintf(stderr, "[M::%s::utg%.6ul-hap%u]\n", __func__, id, b->s[id]>0?1:b->s[id]<0?2:0); - w_t w[128], z[4]; - uint32_t o, n, i, hn = 4; - int8_t s; - for (i = 0; i < hn; i++) w[i] = 0; - o = ma->idx.a[id] >> 32; - n = (uint32_t)ma->idx.a[id]; - for (i = 0; i < n; ++i) - { - s = b->s[ma_y(ma->ma.a[o + i])]; - w[s>0?1:s<0?2:0] += ma->ma.a[o + i].w; - } - z[0] = z[3] = 0; z[1] = b->z[id].z[0]; z[2] = b->z[id].z[1]; - for (i = 0; i < hn; i++) fprintf(stderr, "w[%u]-%f, z[%u]-%f\n", i, w[i], i, z[i]); -} - -uint32_t mc_solve_cc(const mc_opt_t *opt, const mc_g_t *mg, mc_svaux_t *b, uint32_t cc_off, uint32_t cc_size) -{ - uint32_t j, k, n_iter = 0, flush = opt->max_iter * 50; - t_w_t sc_opt = -(1<<30), sc;///problem-w - b->cc_off = cc_off, b->cc_size = cc_size; - if (b->cc_size < 2) return 0; - sc_opt = mc_init_spin(mg->e, b); - // print_sc(opt, mg, b, sc_opt, n_iter); - if (b->cc_size == 2) return 0; - for (j = 0; j < b->cc_size; ++j) {///backup s and z in s_opt and z_opt - b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; ///hap status of each unitig - b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; ///z[0]: positive weight; z[1]: positive weight - } - // print_sc(opt, mg->e, b, sc_opt, n_iter); - sc = mc_optimize_local(opt, mg->e, b, &n_iter); - if (sc > sc_opt) { - for (j = 0; j < b->cc_size; ++j) { - b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; - b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; - } - sc_opt = sc; - } else { - for (j = 0; j < b->cc_size; ++j) { - b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; - b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; - } - } - - // print_mc_node(mg->e, b, 36880); - // print_sc(opt, mg, b, sc_opt, n_iter); - // mc_reset_z_debug(mg->e, b); - // print_sc(opt, mg->e, b, sc_opt, n_iter); - // fprintf(stderr, "\ncc_size: %u, cc_off: %u\n", b->cc_size, b->cc_off); - for (k = 0; k < (uint32_t)opt->n_perturb; ++k) { - if (k&1) mc_perturb(opt, mg->e, b); - else mc_perturb_node(opt, mg->e, b, 3); - sc = mc_optimize_local(opt, mg->e, b, &n_iter); - // fprintf(stderr, "(%u) sc_opt: %f, sc: %f\n", k, sc_opt, sc); - if (sc > sc_opt) { - for (j = 0; j < b->cc_size; ++j) { - b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; - b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; - } - sc_opt = sc; - // print_sc(opt, mg, b, sc_opt, n_iter); - } else { - for (j = 0; j < b->cc_size; ++j) { - b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; - b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; - } - } - - if((n_iter%flush) == 0) - { - mc_reset_z(mg->e, b); - sc = mc_score(mg->e, b); - - for (j = 0; j < b->cc_size; ++j) { - b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; - } - sc_opt = sc; - } - } - - for (j = 0; j < b->cc_size; ++j) - { - b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; - b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; - } - - return n_iter; -} - -#define clus_a(b, id) (((b)).cc.nn.a+(((b)).cc.ng.a[(id)]>>32)) -#define clus_n(b, id) (((uint32_t)((((b)).cc.ng.a[(id)])))) - - -void reorder_bub(const mc_match_t *ma, uint32_t *a, uint32_t a_n, uint8_t *ff, uint8_t lf, uint8_t rf, uint8_t cf, -uint8_t cuf, double *sc_l, double *sc_r, double *sc_m, uint32_t *res) -{ - uint32_t k, o, j, n, t, z; mc_edge_t *e; - double mm_l, mm_r, m_inner, mm; int64_t mmlk, mmrk, rev, m_inner_k, mmk; - for (k = 0; k < a_n; k++) ff[a[k]] = cf; - m_inner = 0; m_inner_k = -1; mm_l = mm_r = 0; mmlk = mmrk = -1; - for (k = 0, rev = -1; k < a_n; k++) { - sc_l[k] = sc_r[k] = sc_m[k] = 0; - o = ma->idx.a[a[k]] >> 32; n = (uint32_t)ma->idx.a[a[k]]; - for (j = 0; j < n; ++j) { - e = &ma->ma.a[o + j]; - t = ma_y(*e); - if(ff[t] == lf) sc_l[k] += fabs(e->w); - if(ff[t] == rf) sc_r[k] += fabs(e->w); - if(ff[t] == cf) sc_m[k] += fabs(e->w); - } - if(sc_l[k] > 0) { - if(sc_l[k] > mm_l) { - mm_l = sc_l[k]; mmlk = k; - } - } else if(sc_r[k] > 0) { - if(sc_r[k] > mm_r) { - mm_r = sc_r[k]; mmrk = k; - } - } else if(sc_m[k] > 0 && sc_m[k] > m_inner) { - m_inner = sc_m[k]; m_inner_k = k; - } - } - if(mmlk == -1 && mmrk == -1 && m_inner_k == -1) return; - if(mmlk != -1) { - mm = mm_l; mmk = mmlk; rev = 0; - } else if(mmrk != -1) { - mm = mm_r; mmk = mmrk; rev = 1; - } else { - mm = m_inner; mmk = m_inner_k; rev = 0; - } - - double *sc = (!rev)?sc_l:sc_r; - // for (k = 0; k < a_n; k++) { - // // sc_m[k] = 0; - // fprintf(stderr, "+[M::%s] a_n::%u, a[%u]::%u\n", __func__, a_n, k, a[k]); - // } - - z = 0; res[z++] = a[mmk]; ff[a[mmk]] = cuf; - for (; z < a_n; ) { - for (k = 0, mm = 0, mmk = -1; k < a_n; k++) { - if(ff[a[k]] == cuf) continue; - o = ma->idx.a[a[k]] >> 32; n = (uint32_t)ma->idx.a[a[k]]; - for (j = 0; j < n; ++j) { - e = &ma->ma.a[o + j]; - t = ma_y(*e); - if(ff[t] == cuf) sc[k] += fabs(e->w); - // if(ff[t] == cuf) sc_m[k] += fabs(e->w); - } - - if(sc[k] > 0) { - if(sc[k] > mm) { - mm = sc[k]; mmk = k; - } - } - } - if(mmk == -1) break; - // fprintf(stderr, "-[M::%s] mmk::%ld, a[%ld]::%u, z::%u\n", __func__, mmk, mmk, a[mmk], z); - res[z++] = a[mmk]; ff[a[mmk]] = cuf; - } - // fprintf(stderr, "[M::%s] a_n::%u, z::%u\n", __func__, a_n, k, z); - if(z < a_n) { - for (k = 0; k < a_n; k++) { - if(ff[a[k]] == cuf) continue; - res[z++] = a[k]; ff[a[k]] = cuf; - } - } - assert(z == a_n); - if(!rev) { - for (k = 0; k < a_n; k++) { - a[k] = res[k]; - // fprintf(stderr, "[M::%s] a_n::%u, a[k]::%u, res[k]::%u\n", __func__, a_n, a[k], res[k]); - ff[a[k]] = lf; - } - } else { - for (k = 0; k < a_n; k++) { - a[k] = res[a_n-k-1]; ff[a[k]] = lf; - } - } -} - -void prt_bub(uint32_t *a, uint32_t a_n, const char *cmd) -{ - uint32_t k; - fprintf(stderr, "%s\n", cmd); - for (k = 0; k < a_n; k++) { - fprintf(stderr, "utg%.6dl\t", (int32_t)a[k]+1); - } - fprintf(stderr, "\n"); - -} - -void renew_mc_clus_t(mc_clus_t *bc, uint32_t *a, uint32_t a_n) -{ - if(!bc) return; - // fprintf(stderr, "[M::%s] a_n::%u\n", __func__, a_n); - uint32_t k, i, *ba, bn, m, cocc, iin, /**bub_occ = 0,**/ bbn = 0; uint64_t *p; ma_utg_t *u = NULL; - kvec_t(double) sc_l; kvec_t(double) sc_r; kvec_t(double) sc_m; kvec_t(uint32_t) tmp; - kv_init(sc_l); kv_init(sc_r); kv_init(sc_m); kv_init(tmp); - - bc->cc.ng.n = bc->cc.nn.n = 0; - memset(bc->lock, 0, sizeof((*(bc->lock)))*bc->n);///bc->n: number of all nodes - for (k = 0; k < a_n; k++) bc->lock[a[k]] = 1;///a_n: number of nodes within the cluster - - kv_resize(uint32_t, bc->cc.nn, a_n); - // for (i = 0; i < bc->bub->chain_weight.n; i++) { - // if(bc->bub->chain_weight.a[i].del) continue; - // u = &(bc->bub->b_ug->u.a[bc->bub->chain_weight.a[i].id]);///list of bubbles - for (i = 0; i < bc->bub->b_ug->u.n; i++) { - u = &(bc->bub->b_ug->u.a[i]); - if(u->n == 0) continue; - // bub_occ += u->n; - // fprintf(stderr, "[M::%s] i::%u, u->n::%u\n", __func__, i, (uint32_t)u->n); - for (k = cocc = 0, iin = bc->cc.nn.n; k < u->n; k++) { - get_bubbles(bc->bub, u->a[k]>>33, NULL, NULL, &ba, &bn, NULL); - kv_pushp(uint64_t, bc->cc.ng, &p); bbn += bn; - *p = bc->cc.nn.n;///a bubble - for (m = 0; m < bn; m++) { - if(!(bc->lock[ba[m]>>1])) continue;///if the node of bubble is not at this cluster - kv_push(uint32_t, bc->cc.nn, (ba[m]>>1)); - bc->lock[ba[m]>>1] = 2; - } - if(bc->cc.nn.n <= (*p)) {///no node in this bubble - bc->cc.ng.n--; - continue; - } - *p <<= 32; *p |= (bc->cc.nn.n-((*p)>>32)); cocc++; - } - //split the chain if there is multipe bubbles - if(cocc > 0) {//cocc: # of bubbles in this chain - for (k = bc->cc.ng.n - cocc; k < bc->cc.ng.n; k++) { - kv_resize(double, sc_l, clus_n((*bc), k)); - kv_resize(double, sc_r, clus_n((*bc), k)); - kv_resize(double, sc_m, clus_n((*bc), k)); - kv_resize(uint32_t, tmp, clus_n((*bc), k)); - // prt_bub(clus_a((*bc), k), clus_n((*bc), k), "-0-"); - reorder_bub(bc->mg->e, clus_a((*bc), k), clus_n((*bc), k), bc->lock, 3, 2, 4, 5, - sc_l.a, sc_r.a, sc_m.a, tmp.a); - // prt_bub(clus_a((*bc), k), clus_n((*bc), k), "-1-"); - } - for (k = iin; k < bc->cc.nn.n; k++) bc->lock[bc->cc.nn.a[k]] = 1;//reset - kv_pushp(uint64_t, bc->cc.ng, &p); *p = (uint64_t)-1; ///cluster - kv_push(uint32_t, bc->cc.nn, ((uint32_t)-1)); ///split, node id - } - } - - for (k = 0; k < a_n; k++) bc->lock[a[k]] = 0; - kv_destroy(sc_l); kv_destroy(sc_r); kv_destroy(sc_m); kv_destroy(tmp); - // fprintf(stderr, "[M::%s] a_n::%u, bc->cc.nn.n::%u, bc->cc.ng.n::%u, bbn::%u, bub_occ::%u, bc->bub->b_ug->u.n::%u\n", __func__, - // a_n, (uint32_t)bc->cc.nn.n, (uint32_t)bc->cc.ng.n, bbn, bub_occ, (uint32_t)bc->bub->b_ug->u.n); -} - - -void renew_mc_clus_t_adv(mc_clus_t *bc, uint32_t *a, uint32_t a_n) -{ - if(!bc) return; - // fprintf(stderr, "[M::%s] a_n::%u\n", __func__, a_n); - uint32_t k, i, *ba, bn, m, cocc, iin, /**bub_occ = 0,**/ bbn = 0, bid, bk, bl; - uint64_t *p; ma_utg_t *u = NULL; asg64_v *asn = bc->asn; - kvec_t(double) sc_l; kvec_t(double) sc_r; kvec_t(double) sc_m; kvec_t(uint32_t) tmp; - kv_init(sc_l); kv_init(sc_r); kv_init(sc_m); kv_init(tmp); - - bc->cc.ng.n = bc->cc.nn.n = 0; - memset(bc->lock, 0, sizeof((*(bc->lock)))*bc->n);///bc->n: number of all nodes - for (k = 0; k < a_n; k++) bc->lock[a[k]] = 1;///a_n: number of nodes within the cluster - - kv_resize(uint32_t, bc->cc.nn, a_n); - for (i = bid = bk = 0; i < bc->bub->b_ug->u.n; i++) { - u = &(bc->bub->b_ug->u.a[i]); - if(u->n == 0) continue; - // bub_occ += u->n; - // fprintf(stderr, "[M::%s] i::%u, u->n::%u\n", __func__, i, (uint32_t)u->n); - for (k = cocc = 0, iin = bc->cc.nn.n; k < u->n; k++, bid++) { - get_bubbles(bc->bub, u->a[k]>>33, NULL, NULL, &ba, &bn, NULL); - kv_pushp(uint64_t, bc->cc.ng, &p); bbn += bn; - *p = bc->cc.nn.n;///a bubble - for (m = 0; m < bn; m++) { - if(!(bc->lock[ba[m]>>1])) continue;///if the node of bubble is not at this cluster - kv_push(uint32_t, bc->cc.nn, (ba[m]>>1)); - bc->lock[ba[m]>>1] = 2; - } - if(asn) { - for (; bk < asn->n && (asn->a[bk]>>32) < bid; bk++); - for (; bk < asn->n && (asn->a[bk]>>32) == bid; bk++) { - if(!(bc->lock[((uint32_t)asn->a[bk])])) continue;///if the node of bubble is not at this cluster - kv_push(uint32_t, bc->cc.nn, ((uint32_t)asn->a[bk])); - bc->lock[((uint32_t)asn->a[bk])] = 2; - } - } - - if(bc->cc.nn.n <= (*p)) {///no node in this bubble - bc->cc.ng.n--; - continue; - } - *p <<= 32; *p |= (bc->cc.nn.n-((*p)>>32)); cocc++; - } - //split the chain if there is multipe bubbles - if(cocc > 0) {//cocc: # of bubbles in this chain - for (k = bc->cc.ng.n - cocc; k < bc->cc.ng.n; k++) { - kv_resize(double, sc_l, clus_n((*bc), k)); - kv_resize(double, sc_r, clus_n((*bc), k)); - kv_resize(double, sc_m, clus_n((*bc), k)); - kv_resize(uint32_t, tmp, clus_n((*bc), k)); - // prt_bub(clus_a((*bc), k), clus_n((*bc), k), "-0-"); - reorder_bub(bc->mg->e, clus_a((*bc), k), clus_n((*bc), k), bc->lock, 3, 2, 4, 5, - sc_l.a, sc_r.a, sc_m.a, tmp.a); - // prt_bub(clus_a((*bc), k), clus_n((*bc), k), "-1-"); - } - for (k = iin; k < bc->cc.nn.n; k++) bc->lock[bc->cc.nn.a[k]] = 1;//reset - kv_pushp(uint64_t, bc->cc.ng, &p); *p = (uint64_t)-1; ///cluster - kv_push(uint32_t, bc->cc.nn, ((uint32_t)-1)); ///split, node id - } - } - - if(asn) { - for (bl = bk, bk = bk + 1; bk <= asn->n; bk++) { - if(bk == asn->n || (asn->a[bk]>>32) != (asn->a[bl]>>32)) { - cocc = 0; iin = bc->cc.nn.n; - kv_pushp(uint64_t, bc->cc.ng, &p); bbn += bn; - *p = bc->cc.nn.n;///a bubble - for (m = bl; m < bk; m++) { - if(!(bc->lock[((uint32_t)asn->a[m])])) continue;///if the node of bubble is not at this cluster - kv_push(uint32_t, bc->cc.nn, ((uint32_t)asn->a[m])); - bc->lock[((uint32_t)asn->a[m])] = 2; - } - if(bc->cc.nn.n <= (*p)) {///no node in this bubble - bc->cc.ng.n--; - bl = bk; - continue; - } - *p <<= 32; *p |= (bc->cc.nn.n-((*p)>>32)); cocc++; - if(cocc > 0) {//cocc: # of bubbles in this chain - for (k = bc->cc.ng.n - cocc; k < bc->cc.ng.n; k++) { - kv_resize(double, sc_l, clus_n((*bc), k)); - kv_resize(double, sc_r, clus_n((*bc), k)); - kv_resize(double, sc_m, clus_n((*bc), k)); - kv_resize(uint32_t, tmp, clus_n((*bc), k)); - // prt_bub(clus_a((*bc), k), clus_n((*bc), k), "-0-"); - reorder_bub(bc->mg->e, clus_a((*bc), k), clus_n((*bc), k), bc->lock, 3, 2, 4, 5, - sc_l.a, sc_r.a, sc_m.a, tmp.a); - // prt_bub(clus_a((*bc), k), clus_n((*bc), k), "-1-"); - } - for (k = iin; k < bc->cc.nn.n; k++) bc->lock[bc->cc.nn.a[k]] = 1;//reset - kv_pushp(uint64_t, bc->cc.ng, &p); *p = (uint64_t)-1; ///cluster - kv_push(uint32_t, bc->cc.nn, ((uint32_t)-1)); ///split, node id - } - - bl = bk; - } - } - } - ///need enable it later - kv_resize(uint32_t, tmp, bc->cc.nn.n); - kv_resize(uint64_t, bc->cc.ng, bc->cc.ng.n+bc->bub->ug->g->n_seq); - layout_mc_clus_t(bc->mg->e, bc->cc.nn.a, bc->cc.nn.n, &(bc->sg), tmp.a, bc->cc.ng.a+bc->cc.ng.n, bc->bub->ug, 0.199999, 0.800001, 4); - - for (k = 0; k < a_n; k++) bc->lock[a[k]] = 0; - kv_destroy(sc_l); kv_destroy(sc_r); kv_destroy(sc_m); kv_destroy(tmp); - // fprintf(stderr, "[M::%s] a_n::%u, bc->cc.nn.n::%u, bc->cc.ng.n::%u, bbn::%u, bub_occ::%u, bc->bub->b_ug->u.n::%u\n", __func__, - // a_n, (uint32_t)bc->cc.nn.n, (uint32_t)bc->cc.ng.n, bbn, bub_occ, (uint32_t)bc->bub->b_ug->u.n); -} - - -void clean_clus_flip_aux(clus_flip_aux *z) -{ - z->w = -1; z->occ = z->off = (uint32_t)-1; - memset(z->vis.a, 0, sizeof(*(z->vis.a))*z->vis.n); -} - -#define is_set_bits_p(v, i) (((v).a[((i)>>3)]>>(i&7))&1) -#define set_bits_p(v, i) (((v).a[((i)>>3)])|=(((uint8_t)1)<<(i&7))); - -t_w_t clus_weight(mc_svaux_t *b_aux, mc_match_t *ma, bits_p *vis, uint32_t uid) -{ - mc_edge_t *o = NULL; - uint32_t n, i, t; - t_w_t w = ((t_w_t)(b_aux->s[uid])) * (b_aux->z[uid].z[0] - b_aux->z[uid].z[1]) * 2; - t_w_t w_off = 0; - o = pt_a(*ma, uid); - n = pt_n(*ma, uid); - for (i = 0; i < n; ++i) { - t = ma_y(o[i]); - if(!(is_set_bits_p((*vis), t))) continue; - // if(vis[t] == 0) continue; - if(t == uid) continue; - w_off += (b_aux->s[uid]*b_aux->s[t]*o[i].w); - } - return w - (w_off*4);//2 for self; 4 for both directions -} - -void cal_clus_sc0(mc_match_t *ma, mc_svaux_t *b_aux, mc_clus_t* bc, uint8_t *lock, uint8_t lock_max, -uint32_t *a, uint32_t a_n, uint32_t id, clus_flip_aux *r, uint32_t tid) -{ - uint32_t i, max_occ = (uint32_t)-1;//, len, mm0 = (uint32_t)-1, mm1 = 0; - bits_p *vis = &(r->vis); t_w_t w = 0, max_w = -1; - - memset(vis->a, 0, sizeof(*(vis->a))*vis->n); - // if(bc->dbg) { - // if(a[id] == 487 || a[id] == 47) { - // fprintf(stderr, "[M::%s::] id::%u, a[id]::%u, s::%d\n", __func__, id, a[id], b_aux->s[a[id]]); - // } - // } - for (i = id; i < a_n && a[i] != (uint32_t)-1; i++) { - if(lock[a[i]] >= lock_max) continue; - if(is_set_bits_p((*vis), a[i])) continue; - w += clus_weight(b_aux, ma, vis, a[i]); - // if(bc->dbg) { - // if(a[id] == 487 || a[id] == 47) { - // fprintf(stderr, "[M::%s::id->%u] a[%u]::%u, s::%d, lock::%u, lock_max::%u, is_set::%u, w::%f\n", - // __func__, id, i, a[i], b_aux->s[a[i]], lock[a[i]], lock_max, is_set_bits_p((*vis), a[i]), w); - // } - // } - set_bits_p((*vis), a[i]); - // mm1 = a[i]; if(a[i] < mm0) mm0 = a[i]; - ///update max_w - if(max_w < w) { - max_w = w; max_occ = i + 1 - id; - } - } - // if(mm0 != (uint32_t)-1 && mm1 != (uint32_t)-1) { - // len = MIN(((mm1>>3)+1), vis->n) - (mm0>>3); - // memset(vis->a+(mm0>>3), 0, sizeof(*(vis->a))*len); - // } - for (i = id; i < a_n && a[i] != (uint32_t)-1; i++) vis->a[a[i]>>3] = 0;///reset - if(max_w <= 0.000001 || max_occ == (uint32_t)-1) return; - if((max_w > r->w) || (max_w == r->w && id < r->off)) { - r->w = max_w; r->off = id; r->occ = max_occ; - } - // if(bc->dbg) { - // if(a[id] == 487 || a[id] == 47) { - // fprintf(stderr, "[M::%s::] id::%u, a[id]::%u, w::%f, off::%u, occ::%u\n", __func__, id, a[id], r->w, r->off, r->occ); - // } - // } -} - -static void worker_cal_clus_sc(void *data, long i, int tid) // callback for kt_for() -{ - mc_clus_t *bc = (mc_clus_t *)data; - uint32_t *a = bc->cc.nn.a, a_n = bc->cc.nn.n; - if(a[i] == (uint32_t)-1) return; - cal_clus_sc0(bc->mg->e, bc->baux, bc, bc->lock, bc->lock_max, a, a_n, i, &(bc->aux[tid]), tid); -} - - -uint32_t gen_best_clus(mc_clus_t *bc, uint32_t *off, uint32_t *occ, double *rw) -{ - uint32_t i; (*off) = (*occ) = (uint32_t)-1; (*rw) = -1; - for (i = 0; i < bc->n_thread; i++) clean_clus_flip_aux(&(bc->aux[i])); - - kt_for(bc->n_thread, worker_cal_clus_sc, bc, bc->cc.nn.n); - - for (i = 0; i < bc->n_thread; i++) { - if(bc->aux[i].off == (uint32_t)-1) continue; - if(bc->aux[i].w < 0) continue; - - if((bc->aux[i].w > (*rw)) || (bc->aux[i].w == (*rw) && bc->aux[i].off < (*off))) { - (*off) = bc->aux[i].off; (*occ) = bc->aux[i].occ; (*rw) = bc->aux[i].w; - } - } - if((*off) != (uint32_t)-1) return 1; - return 0; -} - -double flip_chain(const mc_match_t *ma, mc_svaux_t *b, uint32_t *a, uint32_t a_n, uint32_t off, uint32_t occ, -bits_p *vis, uint8_t *lock, uint8_t lock_max) -{ - uint32_t k, kn = off + occ; - for (k = off; k < kn; k++) { - vis->a[a[k]>>3] = 0; - // if(occ == 4 && a[off] == 11279) dbg = 1; - } - for (k = off; k < kn; k++) { - if(lock[a[k]] >= lock_max) continue; - if(is_set_bits_p((*vis), a[k])) continue; - set_bits_p((*vis), a[k]); lock[a[k]]++; - // if(dbg) fprintf(stderr, "[M::%s::] a[%u]::%u, s::%d\n", __func__, k, a[k], b->s[a[k]]); - mc_set_spin(ma, b, a[k], -b->s[a[k]]); - } - return mc_score(ma, b); -} - - -void test_flip_sc(const mc_match_t *ma, mc_svaux_t *b, uint32_t *a, uint32_t a_n, bits_p *vis) -{ - mc_edge_t *o = NULL; t_w_t w = 0, w_off = 0; - t_w_t sc_new = mc_score(ma, b), sc; - uint32_t n, i, t, k, uid, z; - for (k = 0; k < a_n; k++) mc_set_spin(ma, b, a[k], -b->s[a[k]]); - for (k = 0; k < a_n; k++) { - uid = a[k]; - fprintf(stderr, "+[M::%s::] uid::%u, z[0]::%f, z[1]::%f\n", __func__, uid, b->z[uid].z[0], b->z[uid].z[1]); - w += ((t_w_t)(b->s[uid])) * (b->z[uid].z[0] - b->z[uid].z[1]) * 2; - o = pt_a(*ma, uid); - n = pt_n(*ma, uid); - for (i = 0; i < n; ++i) { - t = ma_y(o[i]); - for (z = 0; z < k; z++) { - if(a[z] == t) break; - } - if(z >= k) continue; - // if(!(is_set_bits_p((*vis), t))) continue; - // if(vis[t] == 0) continue; - if(t == uid) continue; - fprintf(stderr, "+[M::%s::] uid::%u, t::%u, w::%f\n", __func__, uid, t, o[i].w); - w_off += (b->s[uid]*b->s[t]*o[i].w); - } - } - w -= (w_off*4); - sc = mc_score(ma, b); - fprintf(stderr, "+[M::%s::] sc::%f, sc_new::%f, w::%f\n", __func__, sc, sc_new, w); - - w = w_off = 0; memset(vis->a, 0, sizeof(*(vis->a))*vis->n); - for (k = 0; k < a_n; k++) { - uid = a[k]; - fprintf(stderr, "-[M::%s::] uid::%u, z[0]::%f, z[1]::%f\n", __func__, uid, b->z[uid].z[0], b->z[uid].z[1]); - w += ((t_w_t)(b->s[uid])) * (b->z[uid].z[0] - b->z[uid].z[1]) * 2; - o = pt_a(*ma, uid); - n = pt_n(*ma, uid); - for (i = 0; i < n; ++i) { - t = ma_y(o[i]); - // for (z = 0; z < k; z++) { - // if(a[z] == t) break; - // } - // if(z >= k) continue; - if(!(is_set_bits_p((*vis), t))) continue; - // if(vis[t] == 0) continue; - if(t == uid) continue; - fprintf(stderr, "-[M::%s::] uid::%u, t::%u, w::%f\n", __func__, uid, t, o[i].w); - w_off += (b->s[uid]*b->s[t]*o[i].w); - } - set_bits_p((*vis), uid); - } - w -= (w_off*4); - sc = mc_score(ma, b); - fprintf(stderr, "-[M::%s::] sc::%f, sc_new::%f, w::%f\n", __func__, sc, sc_new, w); -} - -t_w_t mc_solve_clus(mc_clus_t *bc) -{ - uint32_t off, occ/**, r = 0**/; double rw, sc, sc_opt = mc_score(bc->mg->e, bc->baux); - memset(bc->lock, 0, bc->n*sizeof(*(bc->lock))); - while (gen_best_clus(bc, &off, &occ, &rw)) { - sc = flip_chain(bc->mg->e, bc->baux, bc->cc.nn.a, bc->cc.nn.n, off, occ, &(bc->aux[0].vis), bc->lock, bc->lock_max); - // if(r%10000) { - // fprintf(stderr, "[M::%s::] rw::%f, sc_opt::%f, sc::%f, off::%u, occ::%u, r::%u\n", - // __func__, rw, sc_opt, sc, off, occ, r); - // } - if(sc < sc_opt) { - fprintf(stderr, "\nwrong::[M::%s::] rw::%f, sc_opt::%f, sc::%f, off::%u, occ::%u\n", - __func__, rw, sc_opt, sc, off, occ); - // if(occ == 2) { - // uint32_t k; - // for (k = off; k < off + occ; k++) { - // fprintf(stderr, "[M::%s::] a[%u]::%u, s::%d\n", __func__, k, bc->cc.nn.a[k], bc->baux->s[bc->cc.nn.a[k]]); - // } - // test_flip_sc(bc->mg->e, bc->baux, bc->cc.nn.a+off, occ, &(bc->aux[0].vis)); - // } - } - sc_opt = sc; //r++; - } - return sc_opt; -} - -t_w_t mc_clus_cc(mc_clus_t *bc) -{ - // fprintf(stderr, "+[M::%s::]\n", __func__); - // double index_time = yak_realtime(); - // uint32_t r = 1; - t_w_t sc_opt, sc; - // fprintf(stderr, "-[M::%s::]\n", __func__); - mc_reset_z(bc->mg->e, bc->baux); - // fprintf(stderr, "*[M::%s::]\n", __func__); - sc_opt = mc_score(bc->mg->e, bc->baux); - // fprintf(stderr, "[M::%s::] sc_opt: %f\n", __func__, sc_opt); - while (1) { - sc = mc_solve_clus(bc); - // fprintf(stderr, "[M::%s::# round: %u] sc_opt: %f, sc: %f\n", __func__, r, sc_opt, sc); - if(sc <= (sc_opt+0.0000001)) break; - sc_opt = sc; //r++; - } - // fprintf(stderr, "[M::%s::%.3f] ==> round %u\n", __func__, yak_realtime()-index_time, r); - return sc; -} - -uint32_t mc_solve_cc_adv(const mc_opt_t *opt, const mc_g_t *mg, mc_svaux_t *b, uint32_t cc_off, uint32_t cc_size, mc_clus_t *bc) -{ - uint32_t j, k, n_iter = 0, flush = opt->max_iter * 50, n_skip, n_skip_flush = opt->n_perturb/16; - t_w_t sc_opt = -(1<<30), sc;///problem-w - b->cc_off = cc_off, b->cc_size = cc_size; - if (b->cc_size < 2) return 0; - sc_opt = mc_init_spin(mg->e, b); - // print_sc(opt, mg, b, sc_opt, n_iter); - if (b->cc_size == 2) return 0; - for (j = 0; j < b->cc_size; ++j) {///backup s and z in s_opt and z_opt - b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; ///hap status of each unitig - b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; ///z[0]: positive weight; z[1]: positive weight - } - // renew_mc_clus_t(bc, b->cc_node, b->cc_size); - renew_mc_clus_t_adv(bc, b->cc_node, b->cc_size); - // fprintf(stderr, "\ncc_size: %u, cc_off: %u\n", b->cc_size, b->cc_off); - // print_sc(opt, mg->e, b, sc_opt, n_iter); - sc = mc_optimize_local(opt, mg->e, b, &n_iter); - if (sc > sc_opt) { - for (j = 0; j < b->cc_size; ++j) { - b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; - b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; - } - sc_opt = sc; - } else { - for (j = 0; j < b->cc_size; ++j) { - b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; - b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; - } - } - // print_mc_node(mg->e, b, 36880); - // print_sc(opt, mg, b, sc_opt, n_iter); - // mc_reset_z_debug(mg->e, b); - // print_sc(opt, mg->e, b, sc_opt, n_iter); - // fprintf(stderr, "\ncc_size: %u, cc_off: %u\n", b->cc_size, b->cc_off); - - if(bc) { - sc = mc_clus_cc(bc); - if (sc > sc_opt) { - for (j = 0; j < b->cc_size; ++j) { - b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; - b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; - } - sc_opt = sc; - } else { - for (j = 0; j < b->cc_size; ++j) { - b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; - b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; - } - } - } - - for (k = n_skip = 0; k < (uint32_t)opt->n_perturb; ++k) { - if (k&1) mc_perturb(opt, mg->e, b); - else mc_perturb_node(opt, mg->e, b, 3); - sc = mc_optimize_local(opt, mg->e, b, &n_iter); - // if((k%256) == 0) fprintf(stderr, "(%u) sc_opt::%f, sc::%f, flush::%u, n_iter::%u\n", k, sc_opt, sc, flush, n_iter); - if (sc > sc_opt) { - for (j = 0; j < b->cc_size; ++j) { - b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; - b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; - } - sc_opt = sc; n_skip = 0; - // print_sc(opt, mg, b, sc_opt, n_iter); - } else { - for (j = 0; j < b->cc_size; ++j) { - b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; - b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; - } - n_skip++; - } - if(n_skip >= n_skip_flush && bc) { - sc = mc_clus_cc(bc); - if (sc > sc_opt) { - for (j = 0; j < b->cc_size; ++j) { - b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; - b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; - } - sc_opt = sc; - } else { - for (j = 0; j < b->cc_size; ++j) { - b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; - b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; - } - } - n_skip = 0; - } - - if((n_iter%flush) == 0) { - mc_reset_z(mg->e, b); - sc = mc_score(mg->e, b); - - for (j = 0; j < b->cc_size; ++j) { - b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; - } - sc_opt = sc; - } - } - if(bc) { - sc = mc_clus_cc(bc); - if (sc > sc_opt) { - for (j = 0; j < b->cc_size; ++j) { - b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; - b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; - } - sc_opt = sc; - } else { - for (j = 0; j < b->cc_size; ++j) { - b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; - b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; - } - } - } - - // if(bc) { - // bc->dbg = 1; - // mc_clus_cc(bc); - // bc->dbg = 0; - // } - - for (j = 0; j < b->cc_size; ++j) - { - b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; - b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; - } - // exit(1); - return n_iter; -} - - -void reset_mb_g_t_z(mb_g_t *mbg); -uint32_t mb_solve_cc(const mc_opt_t *opt, mb_g_t *mbg, mb_svaux_t *b, uint32_t cc_off, uint32_t cc_size) -{ - uint32_t j, k, n_iter = 0, flush = opt->max_iter * 50; - t_w_t sc_opt = -(1<<30), sc;///problem-w - b->cc_off = cc_off, b->cc_size = cc_size; - if (b->cc_size <= 2) return 0; - - for (j = 0; j < b->cc_size; ++j) {///how many nodes - k = (uint32_t)mbg->e->cc[b->cc_off + j];///node id - b->cc_node[j] = k; - } - - sc_opt = mb_score(mbg, b); - for (j = 0; j < b->cc_size; ++j) {///backup s and z in s_opt and z_opt - memcpy(b->u_opt[b->cc_node[j]].s, b->u[b->cc_node[j]].s, 2*sizeof(mc_node_t)); - memcpy(b->u_opt[b->cc_node[j]].z, b->u[b->cc_node[j]].z, 4*sizeof(t_w_t)); - } - - // print_sc(opt, mg->e, b, sc_opt, n_iter); - sc = mb_optimize_local(opt, mbg, b, &n_iter); - if (sc > sc_opt) { - for (j = 0; j < b->cc_size; ++j) { - memcpy(b->u_opt[b->cc_node[j]].s, b->u[b->cc_node[j]].s, 2*sizeof(mc_node_t)); - memcpy(b->u_opt[b->cc_node[j]].z, b->u[b->cc_node[j]].z, 4*sizeof(t_w_t)); - } - sc_opt = sc; - } else { - for (j = 0; j < b->cc_size; ++j) { - memcpy(b->u[b->cc_node[j]].s, b->u_opt[b->cc_node[j]].s, 2*sizeof(mc_node_t)); - memcpy(b->u[b->cc_node[j]].z, b->u_opt[b->cc_node[j]].z, 4*sizeof(t_w_t)); - } - } - // mc_reset_z_debug(mg->e, b); - // print_sc(opt, mg->e, b, sc_opt, n_iter); - // fprintf(stderr, "\ncc_size: %u, cc_off: %u\n", b->cc_size, b->cc_off); - for (k = 0; k < (uint32_t)opt->n_perturb; ++k) { - if (k&1) mb_perturb(opt, mbg, b); - else mb_perturb_node(opt, mbg, b, 3); - sc = mb_optimize_local(opt, mbg, b, &n_iter); - // fprintf(stderr, "(%u) sc_opt: %f, sc: %f\n", k, sc_opt, sc); - if (sc > sc_opt) { - for (j = 0; j < b->cc_size; ++j) { - memcpy(b->u_opt[b->cc_node[j]].s, b->u[b->cc_node[j]].s, 2*sizeof(mc_node_t)); - memcpy(b->u_opt[b->cc_node[j]].z, b->u[b->cc_node[j]].z, 4*sizeof(t_w_t)); - } - sc_opt = sc; - } else { - for (j = 0; j < b->cc_size; ++j) { - memcpy(b->u[b->cc_node[j]].s, b->u_opt[b->cc_node[j]].s, 2*sizeof(mc_node_t)); - memcpy(b->u[b->cc_node[j]].z, b->u_opt[b->cc_node[j]].z, 4*sizeof(t_w_t)); - } - } - - if((n_iter%flush) == 0) - { - reset_mb_g_t_z(mbg); - sc = mb_score(mbg, b); - - for (j = 0; j < b->cc_size; ++j) { - memcpy(b->u_opt[b->cc_node[j]].z, b->u[b->cc_node[j]].z, 4*sizeof(t_w_t)); - } - sc_opt = sc; - } - - // print_sc(opt, mg->e, b, sc_opt, n_iter); - } - for (j = 0; j < b->cc_size; ++j) - { - memcpy(b->u[b->cc_node[j]].s, b->u_opt[b->cc_node[j]].s, 2*sizeof(mc_node_t)); - memcpy(b->u[b->cc_node[j]].z, b->u_opt[b->cc_node[j]].z, 4*sizeof(t_w_t)); - } - - return n_iter; -} - -void reset_mb_g_t_z(mb_g_t *mbg) -{ - uint32_t k; - mb_match_t *ma = mbg->e; - for (k = 0; k < ma->n_seq; ++k) ///each block - { - uint32_t o = ma->idx.a[k] >> 32; - uint32_t j, n = (uint32_t)ma->idx.a[k]; - mbg->u->u.a[k].z[0] = mbg->u->u.a[k].z[1] = 0; - mbg->u->u.a[k].z[2] = mbg->u->u.a[k].z[3] = 0; - for (j = 0; j < n; ++j) { - const mb_edge_t *e = &ma->ma.a[o + j]; - uint32_t t = ma_y(*e); - - ///a[0]->b[0] - if(mbg->u->u.a[t].s[0] > 0) mbg->u->u.a[k].z[0] += e->w[0]; - else if(mbg->u->u.a[t].s[0] < 0) mbg->u->u.a[k].z[1] += e->w[0]; - - ///a[0]->b[1] - if(mbg->u->u.a[t].s[1] > 0) mbg->u->u.a[k].z[0] += e->w[1]; - else if(mbg->u->u.a[t].s[1] < 0) mbg->u->u.a[k].z[1] += e->w[1]; - - ///a[1]->b[0] - if(mbg->u->u.a[t].s[0] > 0) mbg->u->u.a[k].z[2] += e->w[2]; - else if(mbg->u->u.a[t].s[0] < 0) mbg->u->u.a[k].z[3] += e->w[2]; - - ///a[1]->b[1] - if(mbg->u->u.a[t].s[1] > 0) mbg->u->u.a[k].z[2] += e->w[3]; - else if(mbg->u->u.a[t].s[1] < 0) mbg->u->u.a[k].z[3] += e->w[3]; - } - } -} - -void debug_mbg(mb_g_t *mbg, mc_g_t *mg, mc_svaux_t *b) -{ - uint32_t i, k, a_n[2], *a[2], qn, found; - int8_t s[2]; - for (i = 0; i < mbg->u->u.n; i++)///each block - { - fprintf(stderr, "i: %u, mbg->u->u.n: %u\n", i, (uint32_t)mbg->u->u.n); - decode_mb_node(mbg, i, &(a[0]), &(a_n[0]), &(s[0]), &(a[1]), &(a_n[1]), &(s[1])); - - found = 0; - for (k = 0; k < a_n[0]; k++) - { - qn = a[0][k]; - if(b->s[qn] == s[0]) found = 1; - if(b->s[qn] == 0) continue; - if(b->s[qn] != s[0]) fprintf(stderr, "ERROR-0-::%s\n", __func__); - } - if(found == 0) fprintf(stderr, "ERROR-0-*::%s\n", __func__); - - found = 0; - for (k = 0; k < a_n[1]; k++) - { - qn = a[1][k]; - if(b->s[qn] == s[1]) found = 1; - if(b->s[qn] == 0) continue; - if(b->s[qn] != s[1]) fprintf(stderr, "ERROR-1-::%s\n", __func__); - } - if(found == 0 && a_n[1] > 0) fprintf(stderr, "ERROR-1-*::%s\n", __func__); - } - - // t_w_t mcw = mc_score_all(mg->e, b); - // t_w_t mbw = 0; - // mb_match_t *ma = mbg->e; - // for (k = 0; k < ma->n_seq; ++k) { - // ///a[0] - // mbw += -(t_w_t)(mbg->u->u.a[k].s[0]) * (mbg->u->u.a[k].z[0] - mbg->u->u.a[k].z[1]); - // ///a[1] - // mbw += -(t_w_t)(mbg->u->u.a[k].s[1]) * (mbg->u->u.a[k].z[2] - mbg->u->u.a[k].z[3]); - // } -} - -void mc_init_spin_all(const mc_opt_t *opt, mc_g_t *mg, mb_g_t *mbg, mc_svaux_t *b) -{ - uint32_t st, i, k, m, a_n[2], *a[2], qn; - for (st = 0, i = 1; i <= mg->e->n_seq; ++i) { - if (i == mg->e->n_seq || mg->e->cc[st]>>32 != mg->e->cc[i]>>32) { - b->cc_off = st, b->cc_size = i - st; - if (b->cc_size >= 2) - { - mc_init_spin(mg->e, b); - } - st = i; - } - } - - if(!mbg) return; - // memcpy(b->s_opt, b->s, sizeof(int8_t)*mg->e->n_seq); - - ///adjust by block - kvec_t(uint32_t) s; kv_init(s); - uint32_t ws, we, n_flip; - uint8_t *vis = NULL; CALLOC(vis, mg->e->n_seq); - t_w_t w = 0, max_w = 0; - for (i = 0; i < mbg->u->u.n; i++)///each block - { - decode_mb_node(mbg, i, &(a[0]), &(a_n[0]), NULL, &(a[1]), &(a_n[1]), NULL); - ///if(a_n[0] == 0 || a_n[1] == 0) continue; - if(a_n[0] + a_n[1] <= 1) continue; - s.n = 0; - for (k = 0; k < a_n[0]; k++) - { - qn = a[0][k]; - if(b->s[qn] == 0) continue; - // qn <<= 1; - if(b->s[qn] < 0) qn += ((uint32_t)1<<31); - kv_push(uint32_t, s, qn); - } - - for (k = 0; k < a_n[1]; k++) - { - qn = a[1][k]; - if(b->s[qn] == 0) continue; - // qn <<= 1; qn++; - if(b->s[qn] > 0) qn += ((uint32_t)1<<31); - kv_push(uint32_t, s, qn); - } - - if(s.n == 0) continue; - radix_sort_mc32(s.a, s.a + s.n); - - ws = we = (uint32_t)-1; n_flip = 0; - for (st = 0, k = 1; k <= s.n; k++) - { - if(k == s.n || (s.a[k]>>31) != (s.a[st]>>31)) - { - w = 0; - for (m = st; m < k; m++) vis[(s.a[m]<<1)>>1] = 1; - for (m = st; m < k; m++) w += incre_weight(b, mg->e, vis, (s.a[m]<<1)>>1); - for (m = st; m < k; m++) vis[(s.a[m]<<1)>>1] = 0; - if(ws == (uint32_t)-1 || max_w < w) max_w = w, ws = st, we = k; - st = k; - n_flip++; - } - } - - if(n_flip <= 1) continue; - - /*******************************for debug************************************/ - // t_w_t sc_opt = mc_score_all(mg->e, b); - /*******************************for debug************************************/ - for (m = ws; m < we; m++) mc_set_spin(mg->e, b, (s.a[m]<<1)>>1, -b->s[(s.a[m]<<1)>>1]); - /*******************************for debug************************************/ - // t_w_t sc_cur = mc_score_all(mg->e, b); - // if(sc_cur - sc_opt != max_w*2) - // { - // fprintf(stderr, "ERROR-0-::%s\n", __func__); - // // fprintf(stderr, "sc_opt: %ld, sc_cur: %ld, max_w: %ld\n", sc_opt, sc_cur, max_w); - // fprintf(stderr, "sc_opt: %f, sc_cur: %f, max_w: %f\n", sc_opt, sc_cur, max_w); - // } - /*******************************for debug************************************/ - } - kv_destroy(s); free(vis); - - for (i = 0; i < mbg->u->u.n; i++)///each block - { - decode_mb_node(mbg, i, &(a[0]), &(a_n[0]), NULL, &(a[1]), &(a_n[1]), NULL); - mbg->u->u.a[i].s[0] = mbg->u->u.a[i].s[1] = 0; - mbg->u->u.a[i].z[0] = mbg->u->u.a[i].z[1] = 0; - mbg->u->u.a[i].z[2] = mbg->u->u.a[i].z[3] = 0; - for (k = 0; k < a_n[0]; k++) - { - qn = a[0][k]; - if(b->s[qn] == 0) continue; - mbg->u->u.a[i].s[0] = b->s[qn]; - break; - } - - for (k = 0; k < a_n[1]; k++) - { - qn = a[1][k]; - if(b->s[qn] == 0) continue; - mbg->u->u.a[i].s[1] = b->s[qn]; - break; - } - } - - reset_mb_g_t_z(mbg); - - /*******************************for debug************************************/ - // debug_mbg(mbg, mg, b); - /*******************************for debug************************************/ - // memcpy(b->s, b->s_opt, sizeof(int8_t)*mg->e->n_seq); -} - - -uint64_t *mb_g_cc_core(mb_match_t *ma) -{ - uint32_t i, x, y, *flag; - uint64_t *group; - mb_edge_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 = ma_y(o[j]); - 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_mc64(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 mb_g_cc(mb_g_t *mbg) -{ - mbg->e->cc = mb_g_cc_core(mbg->e); -} - -void mc_set_by_mbg(mc_g_t *mg, mb_g_t *mbg) -{ - // t_w_t z0 = mc_score_all_advance(mg->e, mg->s.a); - // t_w_t z1 = mb_score_all_advance(mg->e, mbg); - // if(z0 >= z1) return; - uint32_t i, k, qn, *a[2], a_n[2]; - int8_t s[2]; - for (i = 0; i < mbg->u->u.n; i++) - { - decode_mb_node(mbg, i, &(a[0]), &(a_n[0]), &(s[0]), &(a[1]), &(a_n[1]), &(s[1])); - for (k = 0; k < a_n[0]; k++) - { - qn = a[0][k]; - if(mg->s.a[qn] == 0) continue; - mg->s.a[qn] = s[0]; - } - - for (k = 0; k < a_n[1]; k++) - { - qn = a[1][k]; - if(mg->s.a[qn] == 0) continue; - mg->s.a[qn] = s[1]; - } - } -} - - -void debug_mb_solve_core(mb_g_t *mbg) -{ - uint32_t i; - for (i = 0; i < mbg->u->u.n; i++) - { - debug_mb_z(mbg, i); - } -} - -void print_mb_g_blcok(mb_g_t *mbg) -{ - uint32_t i, k, a_n[2], *a[2]; - for (i = 0; i < mbg->u->u.n; i++)///each block - { - decode_mb_node(mbg, i, &(a[0]), &(a_n[0]), NULL, &(a[1]), &(a_n[1]), NULL); - { - if(a_n[0] + a_n[1] <= 1) continue; - fprintf(stderr, "\nB0-%s\n", a_n[0]>1?"mul":"single"); - for (k = 0; k < a_n[0]; k++) - { - fprintf(stderr,"s-utg%.6ul\n", a[0][k]+1); - } - - fprintf(stderr, "B1-%s\n", a_n[0]>1?"mul":"single"); - for (k = 0; k < a_n[1]; k++) - { - fprintf(stderr,"d-utg%.6ul\n", a[1][k]+1); - } - } - } -} - - - -void mb_solve_core(mc_opt_t *opt, mc_g_t *mg, kv_u_trans_t *ref, uint32_t is_sys) -{ - if(!ref) return; - double index_time = yak_realtime(); - uint32_t st, i; - mb_g_t *mbg = init_mb_g_t(mg->e, ref, is_sys); - mb_svaux_t *bb; - /**************************init**************************/ - if(VERBOSE_CUT) - { - fprintf(stderr, "\n\n\n\n\n*************beg-[M::%s::score->%f] ==> Partition\n", __func__, mc_score_all_advance(mg->e, mg->s.a)); - } - - mc_svaux_t *b; - mc_g_cc(mg->e); - b = mc_svaux_init(mg, opt->seed); - mc_init_spin_all(opt, mg, mbg, b); - mc_svaux_destroy(b); - free(mg->e->cc); - mg->e->cc = NULL; - /**************************init**************************/ - mb_g_cc(mbg); - bb = mb_svaux_init(mbg, opt->seed); - - if(VERBOSE_CUT) - { - fprintf(stderr, "*********before-[M::%s::mc_score->%f] ==> Partition\n", __func__, mc_score_all_advance(mg->e, mg->s.a)); - fprintf(stderr, "*********before-[M::%s::mb_score->%f] ==> Partition\n", __func__, mb_score_all_advance(mg->e, mbg)); - /*******************************for debug************************************/ - // print_mb_g_blcok(mbg); - /*******************************for debug************************************/ - } - - - opt->n_perturb = opt->n_b_perturb; - for (st = 0, i = 1; i <= mbg->e->n_seq; ++i) { - if (i == mbg->e->n_seq || mbg->e->cc[st]>>32 != mbg->e->cc[i]>>32) { - mb_solve_cc(opt, mbg, bb, st, i - st); - st = i; - } - } - opt->n_perturb = opt->n_s_perturb - opt->n_b_perturb; - - mc_set_by_mbg(mg, mbg); - if(VERBOSE_CUT) - { - /*******************************for debug************************************/ - // debug_mb_solve_core(mbg); - /*******************************for debug************************************/ - fprintf(stderr, "##############end-[M::%s::score->%f] ==> Partition\n", __func__, mc_score_all_advance(mg->e, mg->s.a)); - } - destory_mb_g_t(&mbg); - mb_svaux_destroy(bb); - fprintf(stderr, "[M::%s::%.3f] ==> Partition\n", __func__, yak_realtime()-index_time); -} - - -void mc_solve_core(const mc_opt_t *opt, mc_g_t *mg, bubble_type* bub) -{ - double index_time = yak_realtime(); - uint32_t st, i; - mc_svaux_t *b; - mc_bp_t *bp = NULL; - mc_g_cc(mg->e); - b = mc_svaux_init(mg, opt->seed); - if(bub) bp = mc_bp_t_init(mg->e, b, bub, asm_opt.thread_num); - /*******************************for debug************************************/ - if(bp) mc_init_spin_all(opt, mg, NULL, b); - if(bp) mc_solve_bp(bp); - /*******************************for debug************************************/ - if(VERBOSE_CUT) - { - fprintf(stderr, "\n\n\n\n\n*************beg-[M::%s::score->%f] ==> Partition\n", __func__, mc_score_all_advance(mg->e, mg->s.a)); - } - - for (st = 0, i = 1; i <= mg->e->n_seq; ++i) { - if (i == mg->e->n_seq || mg->e->cc[st]>>32 != mg->e->cc[i]>>32) { - mc_solve_cc(opt, mg, b, st, i - st); - st = i; - } - } - - if(VERBOSE_CUT) - { - fprintf(stderr, "##############end-[---M::%s::score->%f] ==> Partition\n", __func__, mc_score_all(mg->e, b)); - mc_status_all(mg->e, mg->s.a); - } - - - if(bp) mc_solve_bp(bp); - ///mc_write_info(g, b); - mc_svaux_destroy(b); - if(bp) destroy_mc_bp_t(&bp); - fprintf(stderr, "[M::%s::%.3f] ==> Partition\n", __func__, yak_realtime()-index_time); -} - -mc_clus_t *init_mc_clus_t(const mc_opt_t *opt, mc_g_t *mg, bubble_type* bub, uint32_t n_thread, mc_svaux_t *b, uint32_t flp_max) -{ - if((!bub)) return NULL; - mc_clus_t *p; CALLOC(p, 1); - p->bub = bub; p->opt = opt; p->mg = mg; p->n = bub->ug->g->n_seq; - CALLOC(p->lock, p->n); - if(n_thread > 64) n_thread = 64; p->n_thread = n_thread; - CALLOC(p->aux, p->n_thread); - uint32_t k, ss = (p->n>>3)+(!!(p->n&7)); - for (k = 0; k < p->n_thread; k++) { - kv_resize(uint8_t, p->aux[k].vis, ss); p->aux[k].vis.n = ss; - } - p->baux = b; p->lock_max = ((flp_max<=255)?flp_max:255); if(p->lock_max < 1) p->lock_max = 1; - return p; -} - -void des_mc_clus_t(mc_clus_t *p) -{ - if((!p)) return; - uint32_t k; free(p->lock); osg_destroy(p->sg.g); - if(p->asn) { - free(p->asn->a); free(p->asn); - } - for (k = 0; k < p->n_thread; k++) free(p->aux[k].vis.a); - free(p->aux); free(p->cc.ng.a); free(p->cc.nn.a); - free(p); -} - -asg64_v* gen_ref_bub(mc_clus_t *bc, kv_u_trans_t *ref) -{ - if(!ref) return NULL; - asg64_v *aux; CALLOC(aux, 1); aux->n = aux->m = bc->n; double w, mmw; - MALLOC(aux->a, bc->n); memset(aux->a, -1, sizeof((*(aux->a)))*bc->n); - uint32_t k, l, i, *ba, bn, m, on, bid; ma_utg_t *u = NULL; uint64_t p, mm, st, j; - u_trans_t *o = NULL; asg64_v buf; kv_init(buf); - - for (i = bid = 0; i < bc->bub->b_ug->u.n; i++) {///set nodes within bubbles - u = &(bc->bub->b_ug->u.a[i]); - for (k = 0; k < u->n; k++, bid++) { - get_bubbles(bc->bub, u->a[k]>>33, NULL, NULL, &ba, &bn, NULL); - for (m = 0; m < bn; m++) aux->a[ba[m]>>1] = bid; - } - } - // bin = bid; - - for (i = 0; i < bc->bub->ug->g->n_seq; i++) { - if(aux->a[i] != ((uint64_t)-1)) continue; - o = u_trans_a(*ref, i); on = u_trans_n(*ref, i); - if(!on) continue; - buf.n = 0; kv_resize(uint64_t, buf, on); - for (k = 0; k < on; k++) { - p = aux->a[o[k].tn]; p<<= 32; p += k; - kv_push(uint64_t, buf, p); - } - - radix_sort_mc64(buf.a, buf.a + buf.n); - mm = (uint32_t)-1; mmw = -1; - for (l = 0, k = 1; k <= buf.n; k++) { - if((k == buf.n) || ((buf.a[l]>>32) == ((uint32_t)-1)) || ((buf.a[l]>>32) != (buf.a[k]>>32))) { - for (m = l, w = 0; m < k; m++) w += fabs(o[((uint32_t)buf.a[m])].nw); - if(mmw < w) { - mmw = w; mm = buf.a[l]>>32; - } - l = k; - } - } - if(mm != ((uint32_t)-1)) aux->a[i] = mm; - } - - - ///final cluster - for (i = 0; i < bc->bub->ug->g->n_seq; i++) { - if(aux->a[i] != ((uint64_t)-1)) continue; - buf.n = 0; kv_push(uint64_t, buf, i); - while (buf.n > 0) { - k = buf.a[--buf.n]; - if(aux->a[k] != ((uint64_t)-1)) continue; - aux->a[k] = bid;///group id - o = u_trans_a(*ref, k); on = u_trans_n(*ref, k); - for (st = 0, j = 1; j <= on; ++j) { - if(j == on || o[j].tn != o[st].tn) { - if(aux->a[o[st].tn] == ((uint64_t)-1)) { - kv_push(uint64_t, buf, o[st].tn); - } - st = j; - } - } - } - bid++; - } - - assert(aux->n == bc->bub->ug->g->n_seq); - - for (i = 0; i < bc->bub->b_ug->u.n; i++) {///no need nodes in bubbles - u = &(bc->bub->b_ug->u.a[i]); - for (k = 0; k < u->n; k++) { - get_bubbles(bc->bub, u->a[k]>>33, NULL, NULL, &ba, &bn, NULL); - for (m = 0; m < bn; m++) aux->a[ba[m]>>1] = (uint64_t)-1; - } - } - for (i = aux->n = 0; i < bc->bub->ug->g->n_seq; i++) { - if(aux->a[i] == ((uint64_t)-1)) continue; - aux->a[i] <<= 32; aux->a[i] |= i;//bub_id|node_id - aux->a[aux->n++] = aux->a[i]; - } - radix_sort_mc64(aux->a, aux->a + aux->n); - kv_destroy(buf); - return aux; -} - -void mc_solve_core_adv(const mc_opt_t *opt, mc_g_t *mg, bubble_type* bub, kv_u_trans_t *ref) -{ - double index_time = yak_realtime(); - uint32_t st, i; - mc_svaux_t *b; mc_clus_t *bc; - // mc_bp_t *bp = NULL; - mc_g_cc(mg->e); - b = mc_svaux_init(mg, opt->seed); - bc = init_mc_clus_t(opt, mg, bub, asm_opt.thread_num, b, 16); - if(ref && bc) bc->asn = gen_ref_bub(bc, ref); - // bc = gen_mc_clus_t(mg->e, b, bub, ref, asm_opt.thread_num); - // if(bub) bp = mc_bp_t_init(mg->e, b, bub, asm_opt.thread_num); - /*******************************for debug************************************/ - // if(bp) mc_init_spin_all(opt, mg, NULL, b); - // if(bp) mc_solve_bp(bp); - /*******************************for debug************************************/ - if(VERBOSE_CUT) - { - fprintf(stderr, "\n\n\n\n\n*************beg-[M::%s::score->%f] ==> Partition\n", __func__, mc_score_all_advance(mg->e, mg->s.a)); - } - - for (st = 0, i = 1; i <= mg->e->n_seq; ++i) { - if (i == mg->e->n_seq || mg->e->cc[st]>>32 != mg->e->cc[i]>>32) { - mc_solve_cc_adv(opt, mg, b, st, i - st, bc); - st = i; - } - } - - if(VERBOSE_CUT) - { - fprintf(stderr, "##############end-[---M::%s::score->%f] ==> Partition\n", __func__, mc_score_all(mg->e, b)); - mc_status_all(mg->e, mg->s.a); - } - - - // if(bp) mc_solve_bp(bp); - ///mc_write_info(g, b); - mc_svaux_destroy(b); des_mc_clus_t(bc); - // if(bp) destroy_mc_bp_t(&bp); - fprintf(stderr, "[M::%s::%.3f] ==> Partition\n", __func__, yak_realtime()-index_time); -} - -void set_p_flag(mc_g_t *mg, uint32_t uID, uint8_t* trio_flag, trans_chain* t_ch, int8_t s) -{ - uint32_t i; - ma_utg_t *u = &(mg->ug->u.a[uID]); - for (i = 0; i < u->n; i++) - { - trio_flag[u->a[i]>>33] |= SET_TRIO; - if(t_ch->ir_het[u->a[i]>>33] == N_HET) continue; - if(s == 0) - { - if(t_ch->ir_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); - } -} - -void filter_ovlp_by_mc(ma_ug_t *ug, asg_t *read_g, uint32_t uID, hap_overlaps_list* ha, mc_match_t *ma, -int8_t *s) -{ - mc_edge_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 = ma_x(o[k]); tn = ma_y(o[k]); 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_by_mc(mc_g_t *mg, hap_overlaps_list* ha) -{ - 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 < mg->e->n_seq; ++i) - { - filter_ovlp_by_mc(mg->ug, mg->rg, i, ha, mg->e, mg->s.a); - } - - 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) continue; - - ha->x[v].a.a[k] = ha->x[v].a.a[i]; - k++; - } - ha->x[v].a.n = k; - } -} - - -void filter_ta_by_mc(ma_ug_t *ug, asg_t *read_g, uint32_t uID, kv_u_trans_t* ta, mc_match_t *ma, int8_t *s) -{ - mc_edge_t *o = pt_a(*ma, uID); - uint32_t n = pt_n(*ma, uID), k, qn, tn; - u_trans_t *p = NULL; - for (k = 0; k < n; ++k) - { - qn = ma_x(o[k]); tn = ma_y(o[k]); p = NULL; - if((s[qn]*s[tn])!=-1) continue; - get_u_trans_spec(ta, qn, tn, &p, NULL); - if(p && p->nw == o[k].w) { - p->del = 0; - } - else { - get_u_trans_spec(ta, tn, qn, &p, NULL); - if(p && p->nw == o[k].w) p->del = 0; - } - if(!p) fprintf(stderr, "ERROR-ta-p\n"); - } -} - - -void clean_ta_by_mc(mc_g_t *mg, kv_u_trans_t *ta) -{ - uint32_t v, i; - u_trans_t *p = NULL; - for (i = 0; i < ta->n; i++) ta->a[i].del = 1; - for (i = 0; i < mg->e->n_seq; ++i) filter_ta_by_mc(mg->ug, mg->rg, i, ta, mg->e, mg->s.a); - for (i = v = 0; i < ta->n; i++) { - if(ta->a[i].del) continue; - ta->a[v++] = ta->a[i]; - } - ta->n = v; - for (i = 0; i < v; i++) { - kv_pushp(u_trans_t, *ta, &p); - (*p) = ta->a[i]; - p->qn = ta->a[i].tn; p->qs = ta->a[i].ts; p->qe = ta->a[i].te; - p->tn = ta->a[i].qn; p->ts = ta->a[i].qs; p->te = ta->a[i].qe; - } - kt_u_trans_t_idx(ta, mg->ug->g->n_seq); -} - -void p_nodes(mc_g_t *mg, trans_chain* t_ch, uint8_t* trio_flag) -{ - uint32_t i; - for (i = 0; i < mg->e->n_seq; ++i) - { - set_p_flag(mg, i, trio_flag, t_ch, mg->s.a[i]); - } -} - -void write_mc_g_t(mc_opt_t *opt, mc_g_t *mg, const char *name) -{ - FILE* fp = fopen(name, "w"); - - fwrite(opt, sizeof(mc_opt_t), 1, fp); - fwrite(&(mg->s.n), sizeof(mg->s.n), 1, fp); - fwrite(mg->s.a, sizeof(mc_node_t), mg->s.n, fp); - fwrite(&(mg->e->n_seq), sizeof(mg->e->n_seq), 1, fp); - fwrite(&(mg->e->ma.n), sizeof(mg->e->ma.n), 1, fp); - fwrite(mg->e->ma.a, sizeof(mc_edge_t), mg->e->ma.n, fp); - fwrite(&(mg->e->idx.n), sizeof(mg->e->idx.n), 1, fp); - fwrite(mg->e->idx.a, sizeof(uint64_t), mg->e->idx.n, fp); - - fclose(fp); -} - -mc_g_t* load_mc_g_t(mc_opt_t *opt, const char *name) -{ - FILE* fp = NULL; - fp = fopen(name, "r"); - if(!fp) return NULL; - - uint64_t flag = 0; - mc_g_t *mg = NULL; CALLOC(mg, 1); - kv_init(mg->s); CALLOC(mg->e, 1); - - flag += fread(opt, sizeof(mc_opt_t), 1, fp); - - flag += fread(&(mg->s.n), sizeof(mg->s.n), 1, fp); - mg->s.m = mg->s.n; MALLOC(mg->s.a, mg->s.n); - flag += fread(mg->s.a, sizeof(mc_node_t), mg->s.n, fp); - - flag += fread(&(mg->e->n_seq), sizeof(mg->e->n_seq), 1, fp); - - flag += fread(&(mg->e->ma.n), sizeof(mg->e->ma.n), 1, fp); - mg->e->ma.m = mg->e->ma.n; MALLOC(mg->e->ma.a, mg->e->ma.n); - flag += fread(mg->e->ma.a, sizeof(mc_edge_t), mg->e->ma.n, fp); - - flag += fread(&(mg->e->idx.n), sizeof(mg->e->idx.n), 1, fp); - mg->e->idx.m = mg->e->idx.n; MALLOC(mg->e->idx.a, mg->e->idx.n); - flag += fread(mg->e->idx.a, sizeof(uint64_t), mg->e->idx.n, fp); - - fclose(fp); - return mg; -} - -void debug_mc_g_t(const char* name) -{ - mc_opt_t opt; - mc_g_t *mg = load_mc_g_t(&opt, name); - mc_solve_core(&opt, mg, NULL); - destory_mc_g_t(&mg); - exit(1); -} - -void print_hap_s(int8_t *s, uint32_t sn) -{ - fprintf(stderr, "\n[M::%s]\n", __func__); - uint32_t i; - for (i = 0; i < sn; i++) - { - fprintf(stderr,"utg%.6ul\t", i + 1); - if(s[i] > 0) fprintf(stderr, "h%u\n", 1); - else if(s[i] < 0) fprintf(stderr, "h%u\n", 2); - else fprintf(stderr,"\n"); - } -} - -void dump_debug_phasing(const char* fn, kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, double f_rate, -uint32_t renew_s, int8_t *s, uint32_t is_sys, bubble_type* bub, kv_u_trans_t *ref); -void mc_solve(hap_overlaps_list* ovlp, trans_chain* t_ch, kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, double f_rate, uint8_t* trio_flag, uint32_t renew_s, int8_t *s, uint32_t is_sys, bubble_type* bub, kv_u_trans_t *ref, int clean_ov, int is_dump) -{ - if(is_dump) { - dump_debug_phasing(MC_NAME, ta, ug, read_g, f_rate, renew_s, s, is_sys, bub, ref); - // bub = NULL; - } - - mc_opt_t opt; - mc_opt_init(&opt, asm_opt.n_perturb, asm_opt.f_perturb, asm_opt.seed); - mc_g_t *mg = init_mc_g_t(ug, read_g, s, renew_s); - update_mc_edges(mg, ovlp, ta, t_ch, f_rate, is_sys); - - fprintf(stderr, "[M::%s:: # edges: %u]\n", __func__, (uint32_t)mg->e->ma.n); - - mb_solve_core(&opt, mg, ref, is_sys); - ///debug_mc_g_t(mg); - // if(renew_s == 0) write_mc_g_t(&opt, mg, MC_NAME); - // mc_solve_core(&opt, mg, bub); - mc_solve_core_adv(&opt, mg, bub, ref); - - if((asm_opt.flag & HA_F_PARTITION) && t_ch) - { - p_nodes(mg, t_ch, trio_flag); - } - - if(clean_ov){ - if(ovlp) clean_ovlp_by_mc(mg, ovlp); - if(ta) clean_ta_by_mc(mg, ta); - } - // print_hap_s(s, ug->u.n); - - destory_mc_g_t(&mg); -} - - - -void comp(int m, int N, int M, mcb_t *p, int *c) -{ - if (m == M + 1) - { - int i; - mcg_node_t x = 0; - for (i = 0; i < M; i++) x |= ((mcg_node_t)1<<(c[i+1]-1)); - kv_push(mcg_node_t, *p, x); - } - else - { - for (c[m] = c[m - 1] + 1; c[m] <= N - M + m; c[m]++) - { - comp(m + 1, N, M, p, c); - } - } -} - - -void get_mcb(uint32_t n, uint32_t m, mcb_t *p, int *c) -{ - memset(c, 0, sizeof(int)*n+1); - p->n = 0; - comp(1, n, m, p, c); -} - -mc_gg_t *init_mc_gg_t(uint32_t un, kv_gg_status *s, uint16_t hapN) -{ - uint32_t i; - int *c = NULL; CALLOC(c, hapN+1); - mc_gg_t *p = NULL; CALLOC(p, 1); - // p->ug = ug; p->rg = read_g; - p->un = un; p->s = s; p->hN = hapN; - CALLOC(p->m.a, p->hN); p->m.n = p->m.m = hapN; - for (i = 0; i < p->hN; i++) get_mcb(hapN, i+1, &(p->m.a[i]), c); - p->mask = (1<mask--; - free(c); - return p; -} - -void destory_mc_gg_t(mc_gg_t **p) -{ - uint32_t i; - if(!p || !(*p)) return; - for (i = 0; i < (*p)->m.m; i++) - { - free((*p)->m.a[i].a); - } - free((*p)->m.a); - - if((*p)->e) - { - kv_destroy((*p)->e->idx); - kv_destroy((*p)->e->ma); - free((*p)->e->cc); - free((*p)->e); - } - free((*p)); -} - -kv_gg_status *init_mc_gg_status(ma_ug_t *ug, asg_t *read_g, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex, uint64_t t_cov, uint16_t hapN) -{ - fprintf(stderr, "t_cov-%lu\n", t_cov); - uint64_t *covs = NULL, i, k, k_i, c = t_cov/hapN, c_min, c_max; - uint32_t len[2]; - uint8_t *vis = NULL; CALLOC(vis, read_g->n_seq); - kv_gg_status *p = NULL; - CALLOC(covs, hapN); - for (i = 0; i < hapN; i++) - { - c_min = ((i+1)*c) - (0.6*c); - c_max = ((i+1)*c) + (0.6*c); - if(i == 0) c_min = 0; - if(i == hapN) c_max = (uint32_t)-1; - covs[i] = (c_max<<32)|c_min; - } - CALLOC(p, 1); - p->n = p->m = ug->u.n; - CALLOC(p->a, p->n); - for (i = 0; i < p->n; i++) - { - c = get_utg_cov(ug, i, read_g, coverage_cut, sources, ruIndex, vis); - p->a[i].h[0] = p->a[i].h[1] = (uint16_t)-1; p->a[i].s = 0; k_i = 0; - p->a[i].hw[0] = 1; p->a[i].hw[1] = 0; p->a[i].hc = 0; - for (k = 0; k < hapN; k++) - { - c_min = (uint32_t)covs[k]; c_max = covs[k]>>32; - if(c < c_min || c >= c_max) continue; - p->a[i].h[k_i++] = k + 1; - } - if(p->a[i].h[1] == (uint16_t)-1) continue; - - len[0] = (c >= (p->a[i].h[0]*(t_cov/hapN))? - c - (p->a[i].h[0]*(t_cov/hapN)) : (p->a[i].h[0]*(t_cov/hapN)) - c); - len[1] = (c >= (p->a[i].h[1]*(t_cov/hapN))? - c - (p->a[i].h[1]*(t_cov/hapN)) : (p->a[i].h[1]*(t_cov/hapN)) - c); - if(len[0] > len[1]) - { - k_i = p->a[i].h[0]; - p->a[i].h[0] = p->a[i].h[1]; - p->a[i].h[1] = k_i; - - k_i = len[0]; - len[0] = len[1]; - len[1] = k_i; - } - - p->a[i].hw[0] = (double)len[1]/(double)(len[0]+len[1]); - p->a[i].hw[1] = (double)len[0]/(double)(len[0]+len[1]); - } - free(covs); free(vis); - return p; -} - -void update_mc_edges_general(mc_gg_t *mg, kv_u_trans_t *ta, uint16_t hapN) -{ - uint32_t i, k; - mc_edge_t *ma = NULL; - CALLOC(mg->e, 1); - mg->e->n_seq = mg->un; - kv_init(mg->e->idx); kv_init(mg->e->ma); - - for (i = 0; i < ta->n; ++i) - { - if(ta->a[i].del) continue; - if(mg->s->a[ta->a[i].qn].h[0] >= hapN && mg->s->a[ta->a[i].qn].h[1] >= hapN) continue; - if(mg->s->a[ta->a[i].tn].h[0] >= hapN && mg->s->a[ta->a[i].tn].h[1] >= hapN) continue; - kv_pushp(mc_edge_t, mg->e->ma, &ma); - ma->x = (uint64_t)ta->a[i].qn << 32 | ta->a[i].tn; - ma->w = w_cast((ta->a[i].nw)); - } - - for (i = k = 0; i < mg->e->ma.n; i++) - { - if(mg->e->ma.a[i].w == 0) continue; - mg->e->ma.a[k] = mg->e->ma.a[i]; - k++; - } - mg->e->ma.n = k; - - radix_sort_mce(mg->e->ma.a, mg->e->ma.a + mg->e->ma.n); - mc_edges_idx(mg->e); - mc_edges_symm(mg->e); -} - - -typedef struct { - t_w_t *z; - uint32_t hapN; -} mc_poy_t; - -typedef struct { - uint64_t x; // RNG - uint32_t cc_off, cc_size; - kvec_t(uint64_t) cc_edge; - uint32_t *cc_node; - uint32_t *bfs, *bfs_mark; - mc_poy_t *z, *z_opt;///keep scores to nodes(1) and nodes(-1) - mc_gg_status *s, *s_opt; - mcb_t *m; - mcg_node_t mask; - uint32_t hapN; -} mcgg_svaux_t; - -mc_poy_t *init_mc_poy_t(uint32_t un, uint32_t hapN) -{ - uint32_t i; - mc_poy_t *z = NULL; CALLOC(z, 1); - MALLOC(z->z, ((uint32_t)un<z[i] = 0; - z->hapN = hapN; - return z; -} - -void destroy_mc_poy_t(mc_poy_t **p) -{ - if(!p || !(*p)) return; - free((*p)->z); free(*p); -} - -mcgg_svaux_t *mcgg_svaux_init(const mc_gg_t *mg, uint64_t x, uint32_t hapN) -{ - uint32_t st, i, max_cc = 0; - mc_match_t *ma = mg->e; - mcgg_svaux_t *b; - CALLOC(b, 1); - b->x = x; - for (st = 0, i = 1; i <= ma->n_seq; ++i) - if (i == ma->n_seq || ma->cc[st]>>32 != ma->cc[i]>>32) - max_cc = max_cc > i - st? max_cc : i - st, st = i; - kv_init(b->cc_edge); - MALLOC(b->cc_node, max_cc); - b->s = mg->s->a; - CALLOC(b->s_opt, ma->n_seq); - MALLOC(b->bfs, ma->n_seq); - - MALLOC(b->bfs_mark, ma->n_seq); - memset(b->bfs_mark, -1, ma->n_seq*sizeof(uint32_t)); - - b->z = init_mc_poy_t(ma->n_seq, hapN); - b->z_opt = init_mc_poy_t(ma->n_seq, hapN); - - b->m = mg->m.a; - b->mask = ((mcg_node_t)1)<mask--; - b->hapN = hapN; - return b; -} - -void mcgg_svaux_destroy(mcgg_svaux_t *b) -{ - b->s = NULL; - kv_destroy(b->cc_edge); free(b->cc_node); - free(b->s); free(b->s_opt); - destroy_mc_poy_t(&(b->z)); - destroy_mc_poy_t(&(b->z_opt)); - free(b->bfs); free(b->bfs_mark); - free(b); -} - -static inline mcg_node_t kr_drand_node(uint64_t id, mcgg_svaux_t *b, uint16_t *hc) -{ - uint16_t hn = b->s[id].h[0]-1; - if(hc) (*hc) = 0; - b->x = kr_splitmix64(b->x); - if(b->s[id].h[1] != (uint16_t)-1) - { - union { uint64_t i; double d; } u; - u.i = 0x3FFULL << 52 | (b->x) >> 12; - if((u.d - 1.0) > b->s[id].hw[0]) - { - hn = b->s[id].h[1]-1; - if(hc) (*hc) = 1; - } - } - return b->m[hn].a[(b->x)%b->m[hn].n]; -} - -static inline mcg_node_t kr_drand_node_ref(uint64_t id, mcgg_svaux_t *b, uint16_t *hc, mcg_node_t ref, uint64_t rev) -{ - uint64_t i, k, m, mm, mn, mi, cn, hn = b->s[id].h[0]; - mcg_node_t t; - if(hc) (*hc) = 0; - b->x = kr_splitmix64(b->x); - if(b->s[id].h[1] != (uint16_t)-1) - { - union { uint64_t i; double d; } u; - u.i = 0x3FFULL << 52 | (b->x) >> 12; - if((u.d - 1.0) > b->s[id].hw[0]) - { - hn = b->s[id].h[1]; - if(hc) (*hc) = 1; - } - } - if(rev) ref ^= (mcg_node_t)-1; - ref &= b->mask; - - t = ref; cn = 0; - while (t) - { - cn += t&1; - t >>= 1; - } - if(cn == hn) return ref; - - if(cn>=hn) mm=cn, m=1, mn=cn-hn;///1->0 - else mm=b->hapN-cn, m=0, mn=hn-cn;///0->1 - - for (i = 0; i < mn; i++) - { - mi = (b->x%mm); - for (k = 0; k < b->hapN; k++) - { - if(((ref>>k)&1)!=m) continue; - if(mi == 0) - { - ref ^= ((mcg_node_t)1<h[s->hc]; - mcg_node_t ref = s->s; - for (i = cn = 0; i < 32; i++) cn += ((ref>>i)&1); - if (cn != hn) fprintf(stderr, "%s-ERROR-cn, cn-%u, hn-%u\n", cmd, cn, hn); - else fprintf(stderr, "%s-pass-cn, cn-%u, hn-%u\n", cmd, cn, hn); -} - - -void mcgg_reset_z(const mc_match_t *ma, mcgg_svaux_t *b) -{ - uint32_t i; - for (i = 0; i < b->cc_size; ++i) { - uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///uid - uint32_t o = ma->idx.a[k] >> 32; - uint32_t j, n = (1<z->hapN); - for (j = 0; j < n; j++) mcp_de(*(b->z), k, j) = 0; - n = (uint32_t)ma->idx.a[k]; - for (j = 0; j < n; ++j) { - const mc_edge_t *e = &ma->ma.a[o + j]; - uint32_t t = ma_y(*e); - mcp_de(*(b->z), k, b->s[t].s) += e->w; - } - } -} - -t_w_t mcgg_score(const mc_match_t *ma, mcgg_svaux_t *b) -{ - uint32_t i, j, n = (1<z->hapN); - t_w_t z = 0; - for (i = 0; i < b->cc_size; ++i) { - uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///uid - for (j = 0; j < n; j++) - { - z += ((b->s[k].s&((mcg_node_t)j))?-mcp_de(*(b->z), k, j):mcp_de(*(b->z), k, j)); - } - } - return z; -} - -t_w_t mcgg_init_spin(const mc_match_t *ma, mcgg_svaux_t *b) -{ - uint32_t i; - b->cc_edge.n = 0; - for (i = 0; i < b->cc_size; ++i) {///how many nodes - uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///node id - b->cc_node[i] = k; - if(b->s[k].s == 0) break; - } - if(i >= b->cc_size) goto passed; - - for (i = 0; i < b->cc_size; ++i) {///how many nodes - uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///node id - uint32_t o = ma->idx.a[k] >> 32;///cc group id - uint32_t n = (uint32_t)ma->idx.a[k], j; - b->cc_node[i] = k; - for (j = 0; j < n; ++j) { - w_t w = ma->ma.a[o + j].w; - w = w > 0? w : -w; - kv_push(uint64_t, b->cc_edge, (uint64_t)((uint32_t)-1 - ((uint32_t)w)) << 32 | (o + j)); - } - } - radix_sort_mc64(b->cc_edge.a, b->cc_edge.a + b->cc_edge.n); - for (i = 0; i < b->cc_edge.n; ++i) { // from the strongest edge to the weakest - const mc_edge_t *e = &ma->ma.a[(uint32_t)b->cc_edge.a[i]]; - uint32_t n1 = ma_x(*e), n2 = ma_y(*e); - if (b->s[n1].s == 0 && b->s[n2].s == 0) { - b->s[n1].s = kr_drand_node(n1, b, &(b->s[n1].hc)); - // debug_hapM(&(b->s[n1]), "s0"); - b->s[n2].s = kr_drand_node_ref(n2, b, &(b->s[n2].hc), b->s[n1].s, e->w>0?1:0); - // debug_hapM(&(b->s[n2]), "s1"); - } - else if(b->s[n1].s == 0) - { - b->s[n1].s = kr_drand_node_ref(n1, b, &(b->s[n1].hc), b->s[n2].s, e->w>0?1:0); - // debug_hapM(&(b->s[n1]), "s2"); - } - else if(b->s[n2].s == 0) - { - b->s[n2].s = kr_drand_node_ref(n2, b, &(b->s[n2].hc), b->s[n1].s, e->w>0?1:0); - // debug_hapM(&(b->s[n2]), "s3"); - } - } - - passed: - mcgg_reset_z(ma, b); - return mcgg_score(ma, b); -} - -static mcg_node_t get_max_m(uint64_t id, mcgg_svaux_t *b) -{ - uint32_t hn = b->s[id].h[0]-1, k, j, n = (1<z->hapN); - mcg_node_t m, *p = NULL; - t_w_t z, max_z = -(1<<30); - for (k = 0; k < b->m[hn].n; k++) - { - m = b->m[hn].a[k]; z = 0; - for (j = 0; j < n; j++) - { - z += ((m&((mcg_node_t)j))?-mcp_de(*(b->z), id, j):mcp_de(*(b->z), id, j)); - } - if(!p || max_z < z || (max_z == z && m == b->s[id].s)) p = &(b->m[hn].a[k]), max_z = z; - } - - if(b->s[id].h[1] != (uint16_t)-1) - { - hn = b->s[id].h[1]-1; - for (k = 0; k < b->m[hn].n; k++) - { - m = b->m[hn].a[k]; z = 0; - for (j = 0; j < n; j++) - { - z += ((m&((mcg_node_t)j))?-mcp_de(*(b->z), id, j):mcp_de(*(b->z), id, j)); - } - if(!p || max_z < z || (max_z == z && m == b->s[id].s)) p = &(b->m[hn].a[k]), max_z = z; - } - } - return (*p); -} - -///k is uid -static void mcgg_set_spin(const mc_match_t *ma, mcgg_svaux_t *b, uint32_t k, mcg_node_t s, const char* cmd) -{ - uint32_t o, j, n; - mcg_node_t s0 = b->s[k].s; - /*******************************for debug************************************/ - // mcg_node_t t = s; - // o = 0; - // while (t) { - // o += (t&1); t>>=1; - // } - // if(o != b->s[k].h[0] && o != b->s[k].h[1]) fprintf(stderr, "cmd-%s, ERROR-mcgg-1\n", cmd); - // if(s0 == s) fprintf(stderr, "cmd-%s, ERROR-mcgg-2\n", cmd); - /*******************************for debug************************************/ - if (s0 == s) return; - o = ma->idx.a[k] >> 32; - n = (uint32_t)ma->idx.a[k]; - for (j = 0; j < n; ++j) { - const mc_edge_t *e = &ma->ma.a[o + j]; - uint32_t t = ma_y(*e);///1->z[0]; (-1)->z[1]; - mcp_de(*(b->z), t, s0) -= e->w; - mcp_de(*(b->z), t, s) += e->w; - } - b->s[k].s = s; -} - -static t_w_t mcgg_optimize_local(const mc_opt_t *opt, const mc_match_t *ma, mcgg_svaux_t *b, uint32_t *n_iter) -{ - uint32_t i, n_flip = 0; - int32_t n_iter_local = 0; - mcg_node_t ms; - while (n_iter_local < opt->max_iter) { - ++(*n_iter); - ks_shuffle_uint32_t(b->cc_size, b->cc_node, &b->x); - for (i = n_flip = 0; i < b->cc_size; ++i) { - uint32_t k = b->cc_node[i];///uid - ms = get_max_m(k, b); - if(ms != b->s[k].s) - { - mcgg_set_spin(ma, b, k, ms, __func__);///no need to change the score of k itself - // debug_hapM(&(b->s[k]), "s4"); - ++n_flip; - } - } - ++n_iter_local; - if (n_flip == 0) break; - } - - return mcgg_score(ma, b); -} - -void inline back_status(mcgg_svaux_t *b, uint32_t id, uint32_t to_opt) -{ - if(to_opt) - { - b->s_opt[id] = b->s[id]; - memcpy(b->z_opt->z+(id<z->hapN), b->z->z+(id<z->hapN), (1<z->hapN)*sizeof(t_w_t)); - } - else - { - b->s[id] = b->s_opt[id]; - memcpy(b->z->z+(id<z->hapN), b->z_opt->z+(id<z->hapN), (1<z->hapN)*sizeof(t_w_t)); - } - -} -/** -static inline mcg_node_t kr_drand_node_new(uint64_t id, mcgg_svaux_t *b) -{ - if(id == 10070) fprintf(stderr, "id-%lu, h[0]-%u, h[1]-%u\n", id, b->s[id].h[0], b->s[id].h[1]); - uint32_t hn = b->s[id].h[0]-1, is_old = 1, k; - if((b->s[id].h[1] != (uint16_t)-1) && (kr_drand_r(&b->x) > b->s[id].hw[0])) - { - hn = b->s[id].h[1]-1; is_old = 0; - } - if(id == 10070) fprintf(stderr, "id-%lu, hn-%u, b->m[hn].n-%u, is_old-%u\n", id, hn, b->m[hn].n, is_old); - b->x = kr_splitmix64(b->x); - k = b->x%(b->m[hn].n-is_old); - if(id == 10070) fprintf(stderr, "id-%lu, hn-%u, k-%u\n", id, hn, k); - if(b->m[hn].a[k] == b->s[id].s) k = b->m[hn].n-1; - return b->m[hn].a[k]; -} -**/ - -static inline mcg_node_t kr_drand_node_new(uint64_t id, mcgg_svaux_t *b) -{ - uint32_t hn = b->s[id].h[0]-1, k; - if((b->s[id].h[1] != (uint16_t)-1) && (kr_drand_r(&b->x) > b->s[id].hw[0])) - { - hn = b->s[id].h[1]-1; - } - b->x = kr_splitmix64(b->x); - k = b->x%(b->m[hn].n); - if(b->m[hn].a[k] == b->s[id].s && b->m[hn].n > 1) - { - k = b->x%(b->m[hn].n-1); - if(b->m[hn].a[k] == b->s[id].s) k = b->m[hn].n-1; - } - return b->m[hn].a[k]; -} - -static void mcgg_perturb(const mc_opt_t *opt, const mc_match_t *ma, mcgg_svaux_t *b) -{ - uint32_t i; - for (i = 0; i < b->cc_size; ++i) { - uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///node id - double y; - y = kr_drand_r(&b->x); - if (y < opt->f_perturb) - mcgg_set_spin(ma, b, k, kr_drand_node_new(k, b), __func__); - } -} - -static uint32_t mcgg_bfs(const mc_match_t *ma, mcgg_svaux_t *b, uint32_t k0, uint32_t bfs_round, uint32_t max_size) -{ - uint32_t i, n_bfs = 0, st, en, r; - b->bfs[n_bfs++] = k0, b->bfs_mark[k0] = k0; - st = 0, en = n_bfs; - for (r = 0; r < bfs_round; ++r) { - for (i = st; i < en; ++i) { - uint32_t k = b->bfs[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) { - uint32_t t = (uint32_t)ma->ma.a[o + j].x; - if (b->bfs_mark[t] != k0) - b->bfs[n_bfs++] = t, b->bfs_mark[t] = k0; - } - } - st = en, en = n_bfs; - if (max_size > 0 && n_bfs > max_size) break; - } - return n_bfs; -} - -///bfs_round is 3 -static void mcgg_perturb_node(const mc_opt_t *opt, const mc_match_t *ma, mcgg_svaux_t *b, int32_t bfs_round) -{ - uint32_t i, k, n_bfs = 0; - k = (uint32_t)(kr_drand_r(&b->x) * b->cc_size + .499); - if(k >= b->cc_size) k = b->cc_size - 1; - k = (uint32_t)ma->cc[b->cc_off + k];///node id - n_bfs = mcgg_bfs(ma, b, k, bfs_round, (int32_t)(b->cc_size * opt->f_perturb)); - for (i = 0; i < n_bfs; ++i) - mcgg_set_spin(ma, b, b->bfs[i], kr_drand_node_new(b->bfs[i], b), __func__); -} - -void print_mcgg_node(const mc_match_t *ma, mcgg_svaux_t *b, uint32_t id) -{ - fprintf(stderr, "[M::%s::utg%.6ul-hap%u]\n", __func__, id, b->s[id].s); - w_t w[128]; - uint32_t o, n, i, hn = (1<z->hapN); - for (i = 0; i < hn; i++) w[i] = 0; - o = ma->idx.a[id] >> 32; - n = (uint32_t)ma->idx.a[id]; - for (i = 0; i < n; ++i) w[b->s[ma_y(ma->ma.a[o + i])].s] += ma->ma.a[o + i].w; - for (i = 0; i < hn; i++) fprintf(stderr, "w[%u]-%f, z[%u]-%f\n", i, w[i], i, mcp_de(*(b->z), id, i)); -} - -uint32_t mcgg_solve_cc(const mc_opt_t *opt, const mc_gg_t *mg, mcgg_svaux_t *b, uint32_t cc_off, uint32_t cc_size) -{ - // double t0, t1, tt0, tt1; - uint32_t j, k, n_iter = 0, flush = opt->max_iter * 50; - t_w_t sc_opt = -(1<<30), sc;///problem-w - b->cc_off = cc_off, b->cc_size = cc_size; - if (b->cc_size < 2) return 0; - sc_opt = mcgg_init_spin(mg->e, b); - if (b->cc_size == 2) return 0; - for (j = 0; j < b->cc_size; ++j) back_status(b, b->cc_node[j], 1); - - sc = mcgg_optimize_local(opt, mg->e, b, &n_iter); - if (sc > sc_opt) - { - for (j = 0; j < b->cc_size; ++j) back_status(b, b->cc_node[j], 1); - sc_opt = sc; - } - else - { - for (j = 0; j < b->cc_size; ++j) back_status(b, b->cc_node[j], 0); - } - fprintf(stderr, "\nBeg-[M::%s::score->%f]\n", __func__, mcgg_score(mg->e, b)); - // print_mcgg_node(mg->e, b, 3838); - // print_mcgg_node(mg->e, b, 36880); - - // tt0 = tt1 = 0; - for (k = 0; k < (uint32_t)opt->n_perturb; ++k) { - // t0 = yak_realtime(); - if (k&1) mcgg_perturb(opt, mg->e, b); - else mcgg_perturb_node(opt, mg->e, b, 3); - // tt0 += yak_realtime()-t0; - - // t1 = yak_realtime(); - sc = mcgg_optimize_local(opt, mg->e, b, &n_iter); - // tt1 += yak_realtime()-t1; - // fprintf(stderr, "++(%u) sc_after: %f\n", k, mcgg_score(mg->e, b)); - - if (sc > sc_opt) { - for (j = 0; j < b->cc_size; ++j) back_status(b, b->cc_node[j], 1); - sc_opt = sc; - } else { - for (j = 0; j < b->cc_size; ++j) back_status(b, b->cc_node[j], 0); - } - - - if((n_iter%flush) == 0) - { - mcgg_reset_z(mg->e, b); - sc = mcgg_score(mg->e, b); - for (j = 0; j < b->cc_size; ++j) back_status(b, b->cc_node[j], 1); - sc_opt = sc; - } - // fprintf(stderr, "\n"); - // print_mcgg_node(mg->e, b, 3838); - // print_mcgg_node(mg->e, b, 36880); - // if((k&31)==0)fprintf(stderr, "+++(%u) sc: %f, sc_opt: %f, tt0: %.3f, tt1: %.3f\n", k, sc, sc_opt, tt0, tt1); - } - - for (j = 0; j < b->cc_size; ++j) back_status(b, b->cc_node[j], 0); - fprintf(stderr, "End-[M::%s::score->%f]\n", __func__, mcgg_score(mg->e, b)); - return n_iter; -} - -void mc_solve_core_genral(const mc_opt_t *opt, mc_gg_t *mg, uint32_t hapN) -{ - double index_time = yak_realtime(); - uint32_t st, i; - mcgg_svaux_t *b; - mc_g_cc(mg->e); - b = mcgg_svaux_init(mg, opt->seed, hapN); - // if(VERBOSE_CUT) - // { - // fprintf(stderr, "\n\n\n\n\n*************beg-[M::%s::score->%f] ==> Partition\n", __func__, mc_score_all_advance(mg->e, mg->s.a)); - // } - - for (st = 0, i = 1; i <= mg->e->n_seq; ++i) { - if (i == mg->e->n_seq || mg->e->cc[st]>>32 != mg->e->cc[i]>>32) { - mcgg_solve_cc(opt, mg, b, st, i - st); - st = i; - } - } - - // if(VERBOSE_CUT) - // { - // fprintf(stderr, "##############end-[---M::%s::score->%f] ==> Partition\n", __func__, mc_score_all(mg->e, b)); - // } - ///mc_write_info(g, b); - mcgg_svaux_destroy(b); - fprintf(stderr, "[M::%s::%.3f] ==> Partition\n", __func__, yak_realtime()-index_time); -} - -void print_mcb(mc_gg_t *mg) -{ - uint32_t i, k, m; - mcg_node_t t; - mcb_t *p; - for (i = 0; i < mg->m.n; i++) - { - p = mcb_pat(*mg, i + 1); - fprintf(stderr, "# haplotypes: %u, # combination: %u\n", i+1, (uint32_t)p->n); - for (k = 0; k < p->n; k++) - { - t = p->a[k]; - for (m = 0; m < 32; m++) - { - if((t>>m)&1) fprintf(stderr, "%u\t", m); - } - fprintf(stderr, "\n"); - } - } -} - -void print_hap_p(kv_gg_status *s) -{ - fprintf(stderr, "\n[M::%s]\n", __func__); - uint32_t i, h; - mcg_node_t m; - for (i = 0; i < s->n; i++) - { - fprintf(stderr,"utg%.6ul\t", i + 1); - m = s->a[i].s; h = 0; - while (m) { - h++; - if(m&1) fprintf(stderr, "h%u\t", h); - m>>=1; - } - fprintf(stderr,"\n"); - } -} - -void write_mc_gg_dump(kv_u_trans_t *ta, uint32_t un, kv_gg_status *s, uint16_t hapN, const char* fn) -{ - fprintf(stderr, "\n[M::%s]\n", __func__); - char *buf = (char*)calloc(strlen(fn) + 50, 1); - sprintf(buf, "%s.hic.dbg.dump.bin", fn); - FILE* fp = fopen(buf, "w"); - - fwrite(&ta->n, sizeof(ta->n), 1, fp); - fwrite(ta->a, sizeof(u_trans_t), ta->n, fp); - - fwrite(&ta->idx.n, sizeof(ta->idx.n), 1, fp); - fwrite(ta->idx.a, sizeof(uint64_t), ta->idx.n, fp); - - fwrite(&un, sizeof(un), 1, fp); - - fwrite(&(s->n), sizeof(s->n), 1, fp); - fwrite(s->a, sizeof(mc_gg_status), s->n, fp); - - fwrite(&hapN, sizeof(hapN), 1, fp); - - fclose(fp); - free(buf); -} - -uint32_t load_mc_gg_dump(kv_u_trans_t **rta, uint32_t *un, kv_gg_status **rs, uint16_t *hapN, const char* fn) -{ - fprintf(stderr, "\n[M::%s]\n", __func__); - kv_u_trans_t *ta = NULL; - kv_gg_status *s = NULL; - uint64_t flag = 0; - char *buf = (char*)calloc(strlen(fn) + 25, 1); - sprintf(buf, "%s.hic.dbg.dump.bin", fn); - - FILE* fp = NULL; - fp = fopen(buf, "r"); - if(!fp) - { - free(buf); - return 0; - } - CALLOC(ta, 1); - flag += fread(&ta->n, sizeof(ta->n), 1, fp); - ta->m = ta->n; MALLOC(ta->a, ta->n); - flag += fread(ta->a, sizeof(u_trans_t), ta->n, fp); - - flag += fread(&ta->idx.n, sizeof(ta->idx.n), 1, fp); - ta->idx.m = ta->idx.n; MALLOC(ta->idx.a, ta->idx.n); - flag += fread(ta->idx.a, sizeof(uint64_t), ta->idx.n, fp); - - flag += fread(un, sizeof(*un), 1, fp); - - CALLOC(s, 1); - flag += fread(&(s->n), sizeof(s->n), 1, fp); - s->m = s->n; MALLOC(s->a, s->n); - flag += fread(s->a, sizeof(mc_gg_status), s->n, fp); - - flag += fread(hapN, sizeof(*hapN), 1, fp); - *rta = ta; *rs = s; - fclose(fp); - free(buf); - return 1; -} - -mc_g_t* to_mc_g_t(kv_u_trans_t *ta, kv_gg_status *s, uint32_t un) -{ - fprintf(stderr, "[M::%s]\n", __func__); - uint32_t i, k; - mc_edge_t *ma = NULL; - mc_g_t *mg = NULL; CALLOC(mg, 1); - - - CALLOC(mg->e, 1); - mg->e->n_seq = un; - kv_init(mg->e->idx); kv_init(mg->e->ma); - // double sc = get_w_scale(ta); - // fprintf(stderr, "sc: %f\n", sc); - for (i = 0; i < ta->n; ++i) - { - if(ta->a[i].del) continue; - kv_pushp(mc_edge_t, mg->e->ma, &ma); - ma->x = (uint64_t)ta->a[i].qn << 32 | ta->a[i].tn; - // ma->w = w_cast((ta->a[i].nw*sc)); - ma->w = w_cast((ta->a[i].nw)); - } - - - for (i = k = 0; i < mg->e->ma.n; i++) - { - if(mg->e->ma.a[i].w == 0) continue; - mg->e->ma.a[k] = mg->e->ma.a[i]; - k++; - } - mg->e->ma.n = k; - - radix_sort_mce(mg->e->ma.a, mg->e->ma.a + mg->e->ma.n); - mc_merge_dup(mg); - mc_edges_idx(mg->e); - mc_edges_symm(mg->e); - - kv_init(mg->s); - mg->s.m = mg->s.n = s->n; CALLOC(mg->s.a, mg->s.n); - for (i = 0; i < mg->s.n; ++i) - { - if(s->a[i].s != 1 && s->a[i].s != 2) continue; - mg->s.a[i] = (s->a[i].s == 1? 1:-1); - } - return mg; -} - -void debug_mc_gg_t(const char* fn, uint32_t update_ta, uint32_t convert_mc_g_t) -{ - kv_u_trans_t *ta = NULL; - kv_gg_status *s = NULL; - uint32_t un; - uint16_t hapN; - if(load_mc_gg_dump(&ta, &un, &s, &hapN, fn)) - { - if(convert_mc_g_t) - { - mc_opt_t opt; - mc_opt_init(&opt, asm_opt.n_perturb, asm_opt.f_perturb, asm_opt.seed); - mc_g_t *mg = NULL; - mg = to_mc_g_t(ta, s, un); - char *o_file = get_outfile_name(asm_opt.output_file_name); - trans_chain* t_ch = load_hc_trans(o_file); - mb_solve_core(&opt, mg, &(t_ch->k_trans), 1); - mc_solve_core(&opt, mg, NULL); - } - else - { - mc_solve_general(ta, un, s, hapN, update_ta, 0); - } - } - exit(1); -} - -void clean_solve_general_ovlp(kv_u_trans_t *ta, uint32_t un, kv_gg_status *s) -{ - uint32_t i; - for (i = 0; i < ta->n; i++) ta->a[i].del = !!(s->a[ta->a[i].qn].s&s->a[ta->a[i].tn].s); - kt_u_trans_t_simple_symm(ta, un, 0); -} - -void mc_solve_general(kv_u_trans_t *ta, uint32_t un, kv_gg_status *s, uint16_t hapN, uint16_t update_ta, uint16_t write_dump) -{ - print_hap_p(s); - exit(1); - mc_opt_t opt; - mc_opt_init(&opt, asm_opt.n_perturb, asm_opt.f_perturb, asm_opt.seed); - mc_gg_t *mg = init_mc_gg_t(un, s, hapN); - // print_mcb(mg); - - update_mc_edges_general(mg, ta, hapN); - mc_solve_core_genral(&opt, mg, hapN); - if(update_ta) clean_solve_general_ovlp(ta, un, s); - // print_hap_p(s); - - destory_mc_gg_t(&mg); - if(write_dump) write_mc_gg_dump(ta, un, s, hapN, MC_NAME); -} - -void dump_kv_u_trans_t(kv_u_trans_t *z, FILE *fp) -{ - fwrite(&(z->n), sizeof(z->n), 1, fp); - fwrite(z->a, sizeof((*(z->a))), z->n, fp); - fwrite(&z->idx.n, sizeof(z->idx.n), 1, fp); - fwrite(z->idx.a, sizeof((*(z->idx.a))), z->idx.n, fp); -} - -void dump_asg_t(asg_t *g, FILE *fp) -{ - uint32_t tmp, Len; - tmp = g->n_arc; - fwrite(&tmp, sizeof(tmp), 1, fp); - - tmp = g->is_srt; - fwrite(&tmp, sizeof(tmp), 1, fp); - - tmp = g->n_seq; - fwrite(&tmp, sizeof(tmp), 1, fp); - - tmp = g->is_symm; - fwrite(&tmp, sizeof(tmp), 1, fp); - - tmp = g->r_seq; - fwrite(&tmp, sizeof(tmp), 1, fp); - - - // Len = g->n_seq*2; - // fwrite(g->seq_vis, sizeof((*(g->seq_vis))), Len, fp); - - Len = g->n_seq*2; - fwrite(g->idx, sizeof((*(g->idx))), Len, fp); - fwrite(g->arc, sizeof((*(g->arc))), g->n_arc, fp); - fwrite(g->seq, sizeof((*(g->seq))), g->n_seq, fp); -} - -void dump_ma_ug_t(ma_ug_t *ug, FILE *fp) -{ - ma_utg_t *u = NULL; uint32_t t, i; - fwrite(&(ug->u.n), sizeof(ug->u.n), 1, fp); - for (i = 0; i < ug->u.n; i++) { - u = &(ug->u.a[i]); - t = u->len; - fwrite(&t, sizeof(t), 1, fp); - t = u->circ; - fwrite(&t, sizeof(t), 1, fp); - fwrite(&(u->start), sizeof(u->start), 1, fp); - fwrite(&(u->end), sizeof(u->end), 1, fp); - fwrite(&(u->n), sizeof(u->n), 1, fp); - fwrite(u->a, sizeof(uint64_t), u->n, fp); - } - dump_asg_t(ug->g, fp); -} - -void dump_bubble_type(bubble_type* bub, FILE *fp) -{ - fwrite(&(bub->chain_weight.n), sizeof(bub->chain_weight.n), 1, fp); - fwrite(bub->chain_weight.a, sizeof((*(bub->chain_weight.a))), bub->chain_weight.n, fp); - - fwrite(&(bub->list.n), sizeof(bub->list.n), 1, fp); - fwrite(bub->list.a, sizeof((*(bub->list.a))), bub->list.n, fp); - - fwrite(&(bub->num.n), sizeof(bub->num.n), 1, fp); - fwrite(bub->num.a, sizeof((*(bub->num.a))), bub->num.n, fp); - - fwrite(&(bub->pathLen.n), sizeof(bub->pathLen.n), 1, fp); - fwrite(bub->pathLen.a, sizeof((*(bub->pathLen.a))), bub->pathLen.n, fp); - - dump_ma_ug_t(bub->b_ug, fp); - dump_asg_t(bub->b_g, fp); - dump_ma_ug_t(bub->ug, fp); -} - -void dump_rid(All_reads *rdb, FILE *fp) -{ - fwrite(&(rdb->total_reads), sizeof(rdb->total_reads), 1, fp); - fwrite(&(rdb->name_index_size), sizeof(rdb->name_index_size), 1, fp); - fwrite(rdb->name_index, sizeof((*(rdb->name_index))), rdb->name_index_size, fp); - - fwrite(&(rdb->total_name_length), sizeof(rdb->total_name_length), 1, fp); - fwrite(rdb->name, sizeof((*(rdb->name))), rdb->total_name_length, fp); -} - -void load_rid(All_reads *rdb, FILE *fp) -{ - fread(&(rdb->total_reads), sizeof(rdb->total_reads), 1, fp); - fread(&(rdb->name_index_size), sizeof(rdb->name_index_size), 1, fp); - MALLOC(rdb->name_index, rdb->name_index_size); - fread(rdb->name_index, sizeof((*(rdb->name_index))), rdb->name_index_size, fp); - - fread(&(rdb->total_name_length), sizeof(rdb->total_name_length), 1, fp); - MALLOC(rdb->name, rdb->total_name_length); - fread(rdb->name, sizeof((*(rdb->name))), rdb->total_name_length, fp); -} - -void dump_debug_phasing(const char* fn, kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, double f_rate, -uint32_t renew_s, int8_t *s, uint32_t is_sys, bubble_type* bub, kv_u_trans_t *ref) -{ - fprintf(stderr, "\n[M::%s]\n", __func__); - char *buf = (char*)calloc(strlen(fn) + 50, 1); - sprintf(buf, "%s.hic.dbg.dump.bin", fn); - FILE *fp = fopen(buf, "w"); - - dump_kv_u_trans_t(ta, fp);///ta - dump_ma_ug_t(ug, fp);///ug - dump_asg_t(read_g, fp);///read_g - fwrite(&f_rate, sizeof(f_rate), 1, fp);///f_rate - fwrite(&renew_s, sizeof(renew_s), 1, fp);///renew_s - fwrite(s, sizeof((*s)), ug->g->n_seq, fp);///s - fwrite(&is_sys, sizeof(is_sys), 1, fp);///is_sys - dump_bubble_type(bub, fp);///bub - dump_kv_u_trans_t(ref, fp);///ta - dump_rid(&R_INF, fp); - - fclose(fp); - free(buf); -} - -void load_kv_u_trans_t(kv_u_trans_t *z, FILE *fp) -{ - fread(&(z->n), sizeof(z->n), 1, fp); - z->m = z->n; MALLOC(z->a, z->n); - fread(z->a, sizeof((*(z->a))), z->n, fp); - - fread(&z->idx.n, sizeof(z->idx.n), 1, fp); - z->idx.m = z->idx.n; MALLOC(z->idx.a, z->idx.n); - fread(z->idx.a, sizeof((*(z->idx.a))), z->idx.n, fp); -} - -void load_asg_t(asg_t *g, FILE *fp) -{ - uint32_t tmp, Len; - fread(&tmp, sizeof(tmp), 1, fp); - g->n_arc = g->m_arc = tmp; - - fread(&tmp, sizeof(tmp), 1, fp); - g->is_srt = tmp; - - fread(&tmp, sizeof(tmp), 1, fp); - g->n_seq = g->m_seq = tmp; - - fread(&tmp, sizeof(tmp), 1, fp); - g->is_symm = tmp; - - fread(&tmp, sizeof(tmp), 1, fp); - g->r_seq = tmp; - - // Len = g->n_seq*2; - // fwrite(g->seq_vis, sizeof((*(g->seq_vis))), Len, fp); - - Len = g->n_seq*2; - CALLOC(g->idx, Len); fread(g->idx, sizeof((*(g->idx))), Len, fp); - CALLOC(g->arc, g->n_arc); fread(g->arc, sizeof((*(g->arc))), g->n_arc, fp); - CALLOC(g->seq, g->n_seq); fread(g->seq, sizeof((*(g->seq))), g->n_seq, fp); -} - -void load_ma_ug_t(ma_ug_t *ug, FILE *fp) -{ - ma_utg_t *u = NULL; uint32_t t, i; - fread(&(ug->u.n), sizeof(ug->u.n), 1, fp); - ug->u.m = ug->u.n; CALLOC(ug->u.a, ug->u.n); - for (i = 0; i < ug->u.n; i++) { - u = &(ug->u.a[i]); - fread(&t, sizeof(t), 1, fp); u->len = t; - fread(&t, sizeof(t), 1, fp); u->circ = t; - fread(&(u->start), sizeof(u->start), 1, fp); - fread(&(u->end), sizeof(u->end), 1, fp); - fread(&(u->n), sizeof(u->n), 1, fp); - u->m = u->n; MALLOC(u->a, u->n); - fread(u->a, sizeof((*(u->a))), u->n, fp); - } - CALLOC(ug->g, 1); - load_asg_t(ug->g, fp); -} - -void load_bubble_type(bubble_type* bub, FILE *fp) -{ - fread(&(bub->chain_weight.n), sizeof(bub->chain_weight.n), 1, fp); - bub->chain_weight.m = bub->chain_weight.n; CALLOC(bub->chain_weight.a, bub->chain_weight.n); - fread(bub->chain_weight.a, sizeof((*(bub->chain_weight.a))), bub->chain_weight.n, fp); - - fread(&(bub->list.n), sizeof(bub->list.n), 1, fp); - bub->list.m = bub->list.n; CALLOC(bub->list.a, bub->list.n); - fread(bub->list.a, sizeof((*(bub->list.a))), bub->list.n, fp); - - fread(&(bub->num.n), sizeof(bub->num.n), 1, fp); - bub->num.m = bub->num.n; CALLOC(bub->num.a, bub->num.n); - fread(bub->num.a, sizeof((*(bub->num.a))), bub->num.n, fp); - - fread(&(bub->pathLen.n), sizeof(bub->pathLen.n), 1, fp); - bub->pathLen.m = bub->pathLen.n; CALLOC(bub->pathLen.a, bub->pathLen.n); - fread(bub->pathLen.a, sizeof((*(bub->pathLen.a))), bub->pathLen.n, fp); - - CALLOC(bub->b_ug, 1); load_ma_ug_t(bub->b_ug, fp); - CALLOC(bub->b_g, 1); load_asg_t(bub->b_g, fp); - CALLOC(bub->ug, 1); load_ma_ug_t(bub->ug, fp); -} - -void load_debug_phasing(const char* fn, kv_u_trans_t **ta, ma_ug_t **ug, asg_t **read_g, double *f_rate, -uint32_t *renew_s, int8_t **s, uint32_t *is_sys, bubble_type **bub, kv_u_trans_t **ref) -{ - fprintf(stderr, "\n[M::%s]\n", __func__); - char *buf = (char*)calloc(strlen(fn) + 50, 1); - sprintf(buf, "%s.hic.dbg.dump.bin", fn); - FILE *fp = fopen(buf, "r"); - - CALLOC((*ta), 1); load_kv_u_trans_t(*ta, fp);///ta - CALLOC((*ug), 1); load_ma_ug_t(*ug, fp);///ug - CALLOC((*read_g), 1); load_asg_t((*read_g), fp);///read_g - - fread(f_rate, sizeof((*f_rate)), 1, fp);///f_rate - fread(renew_s, sizeof((*renew_s)), 1, fp);///renew_s - CALLOC((*s), (*ug)->g->n_seq); fread(*s, sizeof((*(*s))), (*ug)->g->n_seq, fp);///s - fread(is_sys, sizeof((*is_sys)), 1, fp);///is_sys - - CALLOC((*bub), 1); load_bubble_type(*bub, fp);///bub - CALLOC((*ref), 1); load_kv_u_trans_t(*ref, fp);///ta - - load_rid(&R_INF, fp);///read id - - fclose(fp); - free(buf); -} - - -void prt_rcut_res(const char* fn, int8_t *s, ma_ug_t *ug, asg_t *sg) -{ - uint32_t i, k, flag = AMBIGU; - char *buf = (char*)calloc(strlen(fn) + 50, 1); - sprintf(buf, "%s.rcut.res.log", fn); - FILE *fp = fopen(buf, "w"); - uint8_t *rs = NULL; MALLOC(rs, sg->n_seq); - memset(rs, AMBIGU, sg->n_seq*sizeof((*rs))); - - for (i = 0; i < ug->g->n_seq; i++) { - if(ug->g->seq[i].del) continue; - flag = AMBIGU; - if(s[i] == 0) continue; - flag = (s[i] > 0? FATHER:MOTHER); - for (k = 0; k < ug->u.a[i].n; k++) rs[ug->u.a[i].a[k]>>33] = flag; - } - - for (i = 0; i < sg->n_seq; i++) { - if(rs[i] == AMBIGU) continue; - fprintf(fp, "%.*s\t%u\n", (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i), rs[i]); - } - - fclose(fp); free(rs); - free(buf); -} - -void quick_debug_phasing(const char* fn) -{ - kv_u_trans_t *ta; ma_ug_t *ug; asg_t *read_g; double f_rate; - uint32_t renew_s; int8_t *s; uint32_t is_sys; bubble_type *bub; kv_u_trans_t *ref; - load_debug_phasing(fn, &ta, &ug, &read_g, &f_rate, &renew_s, &s, &is_sys, &bub, &ref); - - - - mc_solve(NULL, NULL, ta, ug, read_g, f_rate, NULL, renew_s, s, is_sys, bub, ref, 0, 0); - // mc_solve_core_adv(const mc_opt_t *opt, mc_g_t *mg, bubble_type* bub, kv_u_trans_t *ref) - - // for (k = 0; k < ug->g->n_seq; k++) { - // fprintf(stderr, "utg%.6dl(len::%u), s[k]::%d\n", (int32_t)(k)+1, ug->g->seq[k].len, s[k]); - // } - prt_rcut_res(fn, s, ug, read_g); - - exit(1); -} +#define __STDC_LIMIT_MACROS +#include +#include +#include +#include "assert.h" +#include "rcut.h" +#include "Purge_Dups.h" +#include "Correct.h" +#include "ksort.h" +#include "kthread.h" +#include "hic.h" +#include "horder.h" + +#define VERBOSE_CUT 0 + +#define mc_edge_key(e) ((e).x) +KRADIX_SORT_INIT(mce, mc_edge_t, mc_edge_key, member_size(mc_edge_t, x)) +#define mb_edge_key(e) ((e).x) +KRADIX_SORT_INIT(mbe, mb_edge_t, mb_edge_key, member_size(mb_edge_t, x)) +#define mc_generic_key(x) (x) +KRADIX_SORT_INIT(mc64, uint64_t, mc_generic_key, 8) +KRADIX_SORT_INIT(mc32, uint32_t, mc_generic_key, 4) + +#define pt_a(x, id) ((x).ma.a + ((x).idx.a[(id)]>>32)) +#define pt_n(x, id) ((uint32_t)((x).idx.a[(id)])) +#define ma_x(z) (((z).x>>32)) +#define ma_y(z) (((uint32_t)((z).x))) + +#define mcb_pat(x, id) (&((x).m.a[(id)-1])) +#define mcp_de(x, id, m) ((x).z[((id)<<(x).hapN)+(m)]) + +uint8_t bit_filed[8] = {1, 2, 4, 8, 16, 32, 64, 128}; +#define is_bit_set(id, a) ((a)[(id)>>3]&bit_filed[(id)&7]) + +typedef struct { + int32_t max_iter; + int32_t n_perturb; + int32_t n_b_perturb; + int32_t n_s_perturb; + double f_perturb; + uint64_t seed; +} mc_opt_t; + + +typedef struct { + t_w_t z[2]; +} mc_pairsc_t; + +typedef struct { + uint64_t x; // RNG + uint32_t cc_off, cc_size; + kvec_t(uint64_t) cc_edge; + uint32_t *cc_node; + uint32_t *bfs, *bfs_mark; + mc_pairsc_t *z, *z_opt;///keep scores to nodes(1) and nodes(-1) + int8_t *s, *s_opt; + uint8_t *f; +} mc_svaux_t; + + +typedef struct { + uint64_t x; // RNG + uint32_t cc_off, cc_size; + kvec_t(uint64_t) cc_edge; + uint32_t *cc_node; + uint32_t *bfs, *bfs_mark; + mb_node_t *u, *u_opt;///keep status + uint8_t *f; +} mb_svaux_t; + +typedef struct{ + uint64_t chain_id, bid, uid; +}mc_bp_iter; + +typedef struct{ + uint32_t chain_id; + uint32_t f_bid; + uint32_t f_uid; + uint32_t l_bid; + uint32_t l_uid; + uint32_t id; + t_w_t w; +}mc_bp_res; + +typedef struct{ + size_t n, m; + uint8_t *a; +}bits_p; + +typedef struct{ + bubble_type* b_b; + uint64_t *idx, idx_n, occ, n_thread; + mc_bp_res *res; + uint8_t *lock; + mc_svaux_t *b_aux; + mc_match_t *ma; + bits_p *vis; +}mc_bp_t; + +typedef struct{ + kvec_t(uint32_t) nn; + kvec_t(uint64_t) ng; +} nn_clus_t; + +typedef struct{ + bits_p vis; + t_w_t w; + uint32_t off, occ; +}clus_flip_aux; + +typedef struct{ + nn_clus_t cc; + bubble_type* bub; + const mc_opt_t *opt; + mc_g_t *mg; + uint8_t *lock, lock_max, dbg; + uint32_t n, n_thread; + clus_flip_aux *aux; + mc_svaux_t *baux; + asg64_v *asn; + scg_t sg; +} mc_clus_t; + +typedef struct { + uint64_t x; // RNG + uint32_t cc_off, cc_size; + kvec_t(uint32_t) cc_node; + kvec_t(uint32_t) bfs; + ///share + uint32_t *bfs_mark; + mc_pairsc_t *z, *z_opt;///keep scores to nodes(1) and nodes(-1) + int8_t *s, *s_opt; +} mc_svaux_t_s; + +typedef struct { + kvec_t(mc_svaux_t_s) bs; + kvec_t(uint64_t) cc_edge; + uint32_t *bfs_mark; + mc_pairsc_t *z, *z_opt;///keep scores to nodes(1) and nodes(-1) + int8_t *s, *s_opt; + uint32_t n_t, n_g; +} mc_svaux_t_mul; + +void mc_opt_init(mc_opt_t *opt, int32_t n_perturb, double f_perturb, uint64_t seed) +{ + memset(opt, 0, sizeof(mc_opt_t)); + opt->n_perturb = n_perturb; + opt->f_perturb = f_perturb; + opt->max_iter = 1000; + opt->seed = seed; + opt->n_s_perturb = n_perturb; + opt->n_b_perturb = n_perturb*0.5; +} + +void mc_merge_dup(mc_g_t *mg) // MUST BE sorted +{ + uint32_t i, j, k, st; + w_t w; + for (st = 0, i = 1, k = 0; i <= mg->e->ma.n; ++i) { + if (i == mg->e->ma.n || mg->e->ma.a[i].x != mg->e->ma.a[st].x) { + if (i - st > 1) { + for (j = st, w = 0; j < i; ++j) { + w += mg->e->ma.a[j].w; + } + mg->e->ma.a[k] = mg->e->ma.a[st]; + mg->e->ma.a[k++].w = w; + } else mg->e->ma.a[k++] = mg->e->ma.a[st]; + st = i; + } + } + mg->e->ma.n = k; +} + +void mb_merge_dup(mb_g_t *mbg) // MUST BE sorted +{ + uint32_t i, j, k, st; + t_w_t w[4]; + for (st = 0, i = 1, k = 0; i <= mbg->e->ma.n; ++i) { + if (i == mbg->e->ma.n || mbg->e->ma.a[i].x != mbg->e->ma.a[st].x) { + if (i - st > 1) { + w[0] = w[1] = w[2] = w[3] = 0; + for (j = st; j < i; ++j) { + w[0] += mbg->e->ma.a[j].w[0]; + w[1] += mbg->e->ma.a[j].w[1]; + w[2] += mbg->e->ma.a[j].w[2]; + w[3] += mbg->e->ma.a[j].w[3]; + } + mbg->e->ma.a[k] = mbg->e->ma.a[st]; + mbg->e->ma.a[k].w[0] = w[0]; + mbg->e->ma.a[k].w[1] = w[1]; + mbg->e->ma.a[k].w[2] = w[2]; + mbg->e->ma.a[k].w[3] = w[3]; + k++; + } else mbg->e->ma.a[k++] = mbg->e->ma.a[st]; + st = i; + } + } + mbg->e->ma.n = k; +} + +static void mc_edges_idx(mc_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].x>>32) != (ma->ma.a[st].x>>32)) + ma->idx.a[ma->ma.a[st].x>>32] = (uint64_t)st << 32 | (i - st), st = i; +} + +static void mb_edges_idx(mb_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].x>>32) != (ma->ma.a[st].x>>32)) + ma->idx.a[ma->ma.a[st].x>>32] = (uint64_t)st << 32 | (i - st), st = i; +} + + +mc_g_t *init_mc_g_t(ma_ug_t *ug, asg_t *read_g, int8_t *s, uint32_t renew_s) +{ + mc_g_t *p = NULL; CALLOC(p, 1); + p->ug = ug; + p->rg = read_g; + kv_init(p->s); + if(s) + { + p->s.a = s; + p->s.n = ug->g->n_seq; + p->s.m = 0; + if(renew_s) memset(p->s.a, 0, p->s.n); + } + else + { + CALLOC(p->s.a, ug->g->n_seq); + p->s.n = p->s.m = ug->g->n_seq; + } + return p; +} + +static mc_edge_t *get_mc_edge(const mc_match_t *ma, uint32_t sid1, uint32_t sid2) +{ + mc_edge_t *o = pt_a(*ma, sid1); + uint32_t n = pt_n(*ma, sid1), k; + for (k = 0; k < n; ++k) + if (((uint32_t)o[k].x) == sid2) + return &(o[k]); + return NULL; +} + +static mb_edge_t *get_mb_edge(const mb_match_t *ma, uint32_t sid1, uint32_t sid2) +{ + mb_edge_t *o = pt_a(*ma, sid1); + uint32_t n = pt_n(*ma, sid1), k; + for (k = 0; k < n; ++k) + if (((uint32_t)o[k].x) == sid2) + return &(o[k]); + return NULL; +} + +uint32_t mb_edges_symm(mb_match_t *ma); + +uint32_t debug_mb_edges_symm(mb_match_t *ma) +{ + uint32_t i, n = 0; + mb_edge_t *t = NULL, *m = NULL; + + for (i = 0; i < ma->ma.n; ++i) { + m = &ma->ma.a[i]; + if (ma_x(*m) == ma_y(*m)) + { + fprintf(stderr, "ERROR-0-::%s\n", __func__); + continue; + } + t = get_mb_edge(ma, ma_y(*m), ma_x(*m)); + if(!t) + { + fprintf(stderr, "ERROR-1-::%s\n", __func__); + continue; + } + + if(m->w[0] != t->w[0]) + { + fprintf(stderr, "\nERROR-2-::%s\n", __func__); + fprintf(stderr, "ma_x(*m): %lu, ma_y(*m): %u\n", ma_x(*m), ma_y(*m)); + // fprintf(stderr, "m->w[0]: %ld, m->w[1]: %ld, m->w[2]: %ld, m->w[3]: %ld\n", + // m->w[0], m->w[1], m->w[2], m->w[3]); + // fprintf(stderr, "t->w[0]: %ld, t->w[1]: %ld, t->w[2]: %ld, t->w[3]: %ld\n", + // t->w[0], t->w[1], t->w[2], t->w[3]); + fprintf(stderr, "m->w[0]: %f, m->w[1]: %f, m->w[2]: %f, m->w[3]: %f\n", + m->w[0], m->w[1], m->w[2], m->w[3]); + fprintf(stderr, "t->w[0]: %f, t->w[1]: %f, t->w[2]: %f, t->w[3]: %f\n", + t->w[0], t->w[1], t->w[2], t->w[3]); + } + + if(m->w[3] != t->w[3]) + { + fprintf(stderr, "\nERROR-3-::%s\n", __func__); + fprintf(stderr, "ma_x(*m): %lu, ma_y(*m): %u\n", ma_x(*m), ma_y(*m)); + // fprintf(stderr, "m->w[0]: %ld, m->w[1]: %ld, m->w[2]: %ld, m->w[3]: %ld\n", + // m->w[0], m->w[1], m->w[2], m->w[3]); + // fprintf(stderr, "t->w[0]: %ld, t->w[1]: %ld, t->w[2]: %ld, t->w[3]: %ld\n", + // t->w[0], t->w[1], t->w[2], t->w[3]); + fprintf(stderr, "m->w[0]: %f, m->w[1]: %f, m->w[2]: %f, m->w[3]: %f\n", + m->w[0], m->w[1], m->w[2], m->w[3]); + fprintf(stderr, "t->w[0]: %f, t->w[1]: %f, t->w[2]: %f, t->w[3]: %f\n", + t->w[0], t->w[1], t->w[2], t->w[3]); + } + + if(m->w[1] != t->w[2]) + { + fprintf(stderr, "\nERROR-4-::%s\n", __func__); + fprintf(stderr, "ma_x(*m): %lu, ma_y(*m): %u\n", ma_x(*m), ma_y(*m)); + // fprintf(stderr, "m->w[0]: %ld, m->w[1]: %ld, m->w[2]: %ld, m->w[3]: %ld\n", + // m->w[0], m->w[1], m->w[2], m->w[3]); + // fprintf(stderr, "t->w[0]: %ld, t->w[1]: %ld, t->w[2]: %ld, t->w[3]: %ld\n", + // t->w[0], t->w[1], t->w[2], t->w[3]); + fprintf(stderr, "m->w[0]: %f, m->w[1]: %f, m->w[2]: %f, m->w[3]: %f\n", + m->w[0], m->w[1], m->w[2], m->w[3]); + fprintf(stderr, "t->w[0]: %f, t->w[1]: %f, t->w[2]: %f, t->w[3]: %f\n", + t->w[0], t->w[1], t->w[2], t->w[3]); + } + + + + if(m->w[2] != t->w[1]) + { + fprintf(stderr, "\nERROR-5-::%s\n", __func__); + fprintf(stderr, "ma_x(*m): %lu, ma_y(*m): %u\n", ma_x(*m), ma_y(*m)); + // fprintf(stderr, "m->w[0]: %ld, m->w[1]: %ld, m->w[2]: %ld, m->w[3]: %ld\n", + // m->w[0], m->w[1], m->w[2], m->w[3]); + // fprintf(stderr, "t->w[0]: %ld, t->w[1]: %ld, t->w[2]: %ld, t->w[3]: %ld\n", + // t->w[0], t->w[1], t->w[2], t->w[3]); + fprintf(stderr, "m->w[0]: %f, m->w[1]: %f, m->w[2]: %f, m->w[3]: %f\n", + m->w[0], m->w[1], m->w[2], m->w[3]); + fprintf(stderr, "t->w[0]: %f, t->w[1]: %f, t->w[2]: %f, t->w[3]: %f\n", + t->w[0], t->w[1], t->w[2], t->w[3]); + } + + } + + return n; +} + +inline void decode_mb_node(mb_g_t *mbg, uint32_t id, uint32_t **a0, uint32_t *n0, mc_node_t *s0, +uint32_t **a1, uint32_t *n1, mc_node_t *s1) +{ + if(a0) (*a0) = mbg->u->bid.a + mbg->u->u.a[id].a[0]; + if(n0) (*n0) = mbg->u->u.a[id].occ[0]; + if(s0) (*s0) = mbg->u->u.a[id].s[0]; + + if(a1) (*a1) = mbg->u->bid.a + mbg->u->u.a[id].a[1]; + if(n1) (*n1) = mbg->u->u.a[id].occ[1]; + if(s1) (*s1) = mbg->u->u.a[id].s[1]; +} + + +uint64_t *mb_nodes_core(kv_u_trans_t *ref, mc_match_t* ma, uint32_t occ, uint32_t *fg, kvec_t_u32_warp *sk) +{ + uint32_t i, x, y; + uint64_t *group; + u_trans_t *o = NULL; + + for (i = 0; i < occ; ++i) + fg[i] = (uint32_t)-1; + + // connected componets + for (i = 0; i < occ; ++i) { + if (fg[i] != (uint32_t)-1) continue; + if (pt_n(*ma, i) == 0) + { + fg[i] = i;///group id + continue; + } + sk->a.n = 0; + kv_push(uint32_t, sk->a, i); + while (sk->a.n > 0) { + uint32_t k, j, st, n, t; + sk->a.n--; + k = sk->a.a[sk->a.n]; + fg[k] = i;///group id + o = u_trans_a(*ref, k); + n = u_trans_n(*ref, k); + for (st = 0, j = 1; j <= n; ++j) + { + if(j == n || o[j].tn != o[st].tn) + { + t = o[st].tn; + if ((pt_n(*ma, t) != 0) && (fg[t] == (uint32_t)-1)) + { + kv_push(uint32_t, sk->a, t); + } + st = j; + } + } + } + } + + // precalculate the size of each group + CALLOC(group, occ); + for (i = 0; i < occ; ++i) + group[i] = (uint64_t)fg[i] << 32 | i; + radix_sort_mc64(group, group + occ); + for (i = 1, x = y = 0; i <= occ; ++i) { + if (i == occ || 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; + } + } + return group; +} + +void assgin_mb_node(mb_nodes_t *x, kv_u_trans_t *ref, mc_match_t* ma, uint32_t *fg, kvec_t_u32_warp *sk, uint64_t *cc, uint32_t cc_off, uint32_t cc_size) +{ + uint32_t i, v, n, st, j, t, pass, uid; + u_trans_t *o = NULL; + mb_node_t *p = NULL; + for (i = 0; i < cc_size; ++i) + { + v = (uint32_t)cc[cc_off + i];///node id + fg[v] = (uint32_t)-1; + } + + sk->a.n = 0; + v = (uint32_t)cc[cc_off]; + kv_push(uint32_t, sk->a, v); + fg[v] = 0; + pass = 1; + while (sk->a.n > 0) + { + sk->a.n--; + v = sk->a.a[sk->a.n]; + if(pt_n(*ma, v) == 0) continue; + o = u_trans_a(*ref, v); + n = u_trans_n(*ref, v); + for (st = 0, j = 1; j <= n; ++j) + { + if(j == n || o[j].tn != o[st].tn) + { + t = o[st].tn; + if (pt_n(*ma, t) == 0) + { + st = j; + continue; + } + + if (fg[t] == (uint32_t)-1)///uncolor + { + fg[t] = 1 - fg[v]; + kv_push(uint32_t, sk->a, t); + } + else if(fg[t] == fg[v]) ///color + { + pass = 0; + break; + } + st = j; + } + } + if(pass == 0) break; + } + + if(pass) + { + uid = x->u.n; + kv_pushp(mb_node_t, x->u, &p); + p->z[0] = p->z[1] = p->z[2] = p->z[3] = 0; + p->s[0] = p->s[1] = 0; + p->occ[0] = p->occ[1] = 0; + + for (i = 0, p->a[0] = x->bid.n; i < cc_size; ++i) + { + v = (uint32_t)cc[cc_off + i];///node id + if(fg[v] == 0) + { + kv_push(uint32_t, x->bid, v); + p->occ[0]++; + x->idx.a[v] = (uid<<1); + } + } + + for (i = 0, p->a[1] = x->bid.n; i < cc_size; ++i) + { + v = (uint32_t)cc[cc_off + i];///node id + if(fg[v] == 1) + { + kv_push(uint32_t, x->bid, v); + p->occ[1]++; + x->idx.a[v] = (uid<<1) + 1; + } + } + } + else + { + for (i = 0; i < cc_size; ++i) + { + v = (uint32_t)cc[cc_off + i];///node id + uid = x->u.n; + kv_pushp(mb_node_t, x->u, &p); + p->z[0] = p->z[1] = p->z[2] = p->z[3] = 0; + p->s[0] = p->s[1] = 0; + p->occ[0] = p->occ[1] = 0; + + p->a[0] = x->bid.n; + kv_push(uint32_t, x->bid, v); + p->occ[0]++; + x->idx.a[v] = (uid<<1); + + p->a[1] = x->bid.n; + } + } +} + +void debug_mb_nodes(mb_nodes_t *x, kv_u_trans_t *ref, mc_match_t* ma) +{ + uint32_t i, k, bid, ori, *a = NULL, a_n, v; + for (i = 0; i < x->idx.n; i++) + { + if(x->idx.a[i] == (uint32_t)-1) + { + fprintf(stderr, "ERROR-0-::%s\n", __func__); + continue; + } + bid = x->idx.a[i]>>1; ori = x->idx.a[i] & 1; + a = x->bid.a + x->u.a[bid].a[ori]; + a_n = x->u.a[bid].occ[ori]; + for (k = 0; k < a_n; k++) + { + if(a[k] == i) break; + } + if(k >= a_n) fprintf(stderr, "ERROR-1-::%s\n", __func__); + } + + uint32_t *tt[2], t_n[2], o_n, m, t, found; + int8_t *vis = NULL; CALLOC(vis, x->idx.n); + u_trans_t *o = NULL; + for (i = 0; i < x->u.n; i++)///each block + { + tt[0] = x->bid.a + x->u.a[i].a[0]; + t_n[0] = x->u.a[i].occ[0]; + tt[1] = x->bid.a + x->u.a[i].a[1]; + t_n[1] = x->u.a[i].occ[1]; + + if(t_n[0] == 1 && t_n[1] == 0) continue; + + for (k = 0; k < t_n[0]; k++) + { + vis[tt[0][k]] = 1; + } + for (k = 0; k < t_n[1]; k++) + { + vis[tt[1][k]] = -1; + } + + + + + + for (k = 0; k < t_n[0]; k++) + { + v = tt[0][k]; + o = u_trans_a(*ref, v); + o_n = u_trans_n(*ref, v); + found = 0; + for (m = 0; m < o_n; m++) + { + t = o[m].tn; + if (pt_n(*ma, t) == 0) continue; + if (vis[t] != -1) fprintf(stderr, "ERROR-2-::%s\n", __func__); + else found = 1; + } + if(found == 0) fprintf(stderr, "ERROR-2-*::%s\n", __func__); + } + + for (k = 0; k < t_n[1]; k++) + { + v = tt[1][k]; + o = u_trans_a(*ref, v); + o_n = u_trans_n(*ref, v); + found = 0; + for (m = 0; m < o_n; m++) + { + t = o[m].tn; + if (pt_n(*ma, t) == 0) continue; + if (vis[t] != 1) fprintf(stderr, "ERROR-3-::%s\n", __func__); + else found = 1; + } + if(found == 0) fprintf(stderr, "ERROR-3-*::%s\n", __func__); + } + + + for (k = 0; k < t_n[0]; k++) + { + vis[tt[0][k]] = 0; + } + for (k = 0; k < t_n[1]; k++) + { + vis[tt[1][k]] = 0; + } + } + + free(vis); +} + +mb_nodes_t *update_mb_nodes_t(kv_u_trans_t *ref, mc_match_t* ma, uint32_t occ) +{ + uint32_t i, st; + uint64_t *cc = NULL; + mb_nodes_t *x = NULL; CALLOC(x, 1); + x->bid.n = x->u.n = x->idx.n = 0; + kv_resize(uint32_t, x->idx, occ); + x->idx.n = occ; + memset(x->idx.a, -1, sizeof(uint32_t)*x->idx.n); + kvec_t_u32_warp stack; kv_init(stack.a); + uint32_t *flag = NULL; MALLOC(flag, occ); + + cc = mb_nodes_core(ref, ma, occ, flag, &stack); + + for (st = 0, i = 1; i <= occ; ++i) { + if (i == occ || cc[st]>>32 != cc[i]>>32) { + assgin_mb_node(x, ref, ma, flag, &stack, cc, st, i - st); + st = i; + } + } + + free(cc); free(flag); + kv_destroy(stack.a); + + /*******************************for debug************************************/ + // debug_mb_nodes(x, ref, ma); + /*******************************for debug************************************/ + return x; +} + +mb_g_t *init_mb_g_t(mc_match_t* e, kv_u_trans_t *ref, uint32_t is_sys) +{ + mc_edge_t *o = NULL; + uint32_t i, k, m, n, a_n[2], *a[2], qn, tn, qb, tb; + mb_edge_t *t = NULL; + mb_g_t *p = NULL; CALLOC(p, 1); + p->u = update_mb_nodes_t(ref, e, e->n_seq); + p->e = NULL; CALLOC(p->e, 1); + p->e->n_seq = p->u->u.n; + kv_init(p->e->ma); kv_init(p->e->idx); + for (i = 0; i < p->u->u.n; i++)///each block + { + qb = i; + p->u->u.a[i].s[0] = p->u->u.a[i].s[1] = 0; + decode_mb_node(p, i, &(a[0]), &(a_n[0]), NULL, &(a[1]), &(a_n[1]), NULL); + for (k = 0; k < a_n[0]; k++) + { + qn = a[0][k]; + o = pt_a(*e, qn); + n = pt_n(*e, qn); + for (m = 0; m < n; m++) + { + tn = ma_y(o[m]); + tb = p->u->idx.a[tn]>>1;///tn is the unitig id; tb is the block id + if(tb == qb) + { + continue; + } + + kv_pushp(mb_edge_t, p->e->ma, &t); + t->x = (uint64_t)qb << 32 | tb; + t->w[0] = t->w[1] = t->w[2] = t->w[3] = 0; + t->w[p->u->idx.a[tn]&1] = o[m].w; + } + } + + for (k = 0; k < a_n[1]; k++) + { + qn = a[1][k]; + o = pt_a(*e, qn); + n = pt_n(*e, qn); + for (m = 0; m < n; m++) + { + tn = ma_y(o[m]); + tb = p->u->idx.a[tn]>>1; + if(tb == qb) + { + continue; + } + + kv_pushp(mb_edge_t, p->e->ma, &t); + t->x = (uint64_t)qb << 32 | tb; + t->w[0] = t->w[1] = t->w[2] = t->w[3] = 0; + t->w[(p->u->idx.a[tn]&1)+2] = o[m].w; + } + } + } + + radix_sort_mbe(p->e->ma.a, p->e->ma.a + p->e->ma.n); + mb_merge_dup(p); // MUST BE sorted + mb_edges_idx(p->e); + /*******************************for debug************************************/ + // debug_mb_edges_symm(p->e); + /*******************************for debug************************************/ + if(is_sys) mb_edges_symm(p->e); + + return p; +} + +void destory_mc_g_t(mc_g_t **p) +{ + if(!p || !(*p)) return; + if((*p)->s.m == 0) (*p)->s.a = NULL; + kv_destroy((*p)->s); + if((*p)->e) + { + kv_destroy((*p)->e->idx); + kv_destroy((*p)->e->ma); + free((*p)->e->cc); + free((*p)->e); + } + free((*p)); +} + +void destory_mb_g_t(mb_g_t **p) +{ + if(!p || !(*p)) return; + kv_destroy((*p)->e->idx); + kv_destroy((*p)->e->ma); + free((*p)->e->cc); + free((*p)->e); + + kv_destroy((*p)->u->bid); + kv_destroy((*p)->u->idx); + kv_destroy((*p)->u->u); + free((*p)->u); + + free((*p)); +} + + +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); + tmp = a[j]; a[j] = a[i-1]; a[i-1] = tmp; + } +} + + + +static void normalize_mc_edge(mc_edge_t *a, mc_edge_t *b) +{ + if(a->w >= b->w) + { + b->x = (uint32_t)a->x; + b->x <<= 32; + b->x |= (a->x>>32); + b->w = a->w; + } + else + { + a->x = (uint32_t)b->x; + a->x <<= 32; + a->x |= (b->x>>32); + a->w = b->w; + } +} + +uint32_t mc_edges_symm(mc_match_t *ma) +{ + uint8_t *del = NULL; + uint32_t i, k, n = 0; + mc_edge_t *t = NULL, *m = NULL; + CALLOC(del, ma->ma.n); + + for (i = 0; i < ma->ma.n; ++i) { + m = &ma->ma.a[i]; + if (ma_x(*m) == ma_y(*m)) + { + del[i] = 1, ++n;///self overlap + continue; + } + t = get_mc_edge(ma, ma_y(*m), ma_x(*m)); + if(!t) + { + del[i] = 1, ++n;///self overlap + continue; + } + normalize_mc_edge(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; + mc_edges_idx(ma); + } + + free(del); + return n; +} + + +static void normalize_mb_edge(mb_edge_t *a, mb_edge_t *b) +{ + uint8_t f = 0; + if(a->w[0] > b->w[0]) { + f = 1; + } else if(a->w[0] == b->w[0] && a->w[1] > b->w[1]) { + f = 1; + } else if(a->w[0] == b->w[0] && a->w[1] == b->w[1] && a->w[2] > b->w[2]) { + f = 1; + } else if(a->w[0] == b->w[0] && a->w[1] == b->w[1] && a->w[2] == b->w[2] && a->w[3] > b->w[3]) { + f = 1; + } + + // if(a->w >= b->w) { + if(f) { + b->x = (uint32_t)a->x; + b->x <<= 32; + b->x |= (a->x>>32); + b->w[0] = a->w[0]; + b->w[3] = a->w[3]; + b->w[1] = a->w[2]; + b->w[2] = a->w[1]; + } else { + a->x = (uint32_t)b->x; + a->x <<= 32; + a->x |= (b->x>>32); + a->w[0] = b->w[0]; + a->w[3] = b->w[3]; + a->w[1] = b->w[2]; + a->w[2] = b->w[1]; + } +} + +uint32_t mb_edges_symm(mb_match_t *ma) +{ + uint8_t *del = NULL; + uint32_t i, k, n = 0; + mb_edge_t *t = NULL, *m = NULL; + CALLOC(del, ma->ma.n); + + for (i = 0; i < ma->ma.n; ++i) { + m = &ma->ma.a[i]; + if (ma_x(*m) == ma_y(*m)) + { + del[i] = 1, ++n;///self overlap + continue; + } + t = get_mb_edge(ma, ma_y(*m), ma_x(*m)); + if(!t) + { + del[i] = 1, ++n;///self overlap + continue; + } + normalize_mb_edge(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; + mb_edges_idx(ma); + } + + free(del); + return n; +} + +void debug_mc_interval_t(mc_interval_t *p, uint32_t p_n, uint32_t *p_idx, ma_ug_t *ug, asg_t *rg, +trans_chain* t_ch) +{ + 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; + mc_interval_t *a = NULL, *t = NULL; + + for (v = 0; v < ug->u.n; v++) + { + a = p + p_idx[v]; + occ = p_idx[v+1] - p_idx[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 < p_n; v++) + { + t = &(p[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 = &(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+rg->seq[u->a[i]>>33].len - 1)) + { + fprintf(stderr, "ERROR-c, real end: %u\n", + (uint32_t)(offset+rg->seq[u->a[i]>>33].len - 1)); + } + } + + offset += (uint32_t)u->a[i]; + if(i >= sid && i <= eid) + { + if(t_ch->ir_het[u->a[i]>>33] != t->hs) + { + fprintf(stderr, "ERROR-d: is_r_het: %u, h_status: %u\n", t_ch->ir_het[u->a[i]>>33], t->hs); + } + } + } + } +} + +double get_w_scale(kv_u_trans_t *ta) +{ + uint32_t i, max_w_i, min_w_i; + double max_w = 0, min_w = 0, w; + max_w_i = min_w_i = (uint32_t)-1; + for (i = 0; i < ta->n; ++i) + { + if(ta->a[i].del) continue; + if(ta->a[i].nw == 0) continue; + w = (ta->a[i].nw >= 0? ta->a[i].nw:-ta->a[i].nw); + if(max_w_i == (uint32_t)-1 || max_w < w) max_w = w, max_w_i = i; + if(min_w_i == (uint32_t)-1 || min_w > w) min_w = w, min_w_i = i; + } + + if(max_w_i == (uint32_t)-1 || min_w_i == (uint32_t)-1) return 1; + if(min_w > 1.1) return 1; + double sc_max = (double)(1<<30), sc_min = 1.1; + + return MIN(sc_max/max_w, sc_min/min_w) + sc_min; +} + +void update_mc_edges(mc_g_t *mg, hap_overlaps_list* ha, kv_u_trans_t *ta, trans_chain* t_ch, double f_rate, uint32_t is_sys) +{ + uint32_t v, i, k, qn, tn, qs, qe, ts, te, occ, as, ae, l, offset, l_pos; + uint64_t hetLen, homLen, oLen; + mc_interval_t *a = NULL; + mc_edge_t *ma = NULL; + asg_t* nsg = mg->ug->g; + ma_utg_t *u = NULL; + mc_interval_t *t = NULL; + + kvec_t(mc_interval_t) p; kv_init(p); + kvec_t(uint32_t) p_idx; kv_init(p_idx); + if(t_ch) + { + kv_push(uint32_t, p_idx, 0); + for (v = 0; v < nsg->n_seq; v++) + { + u = &(mg->ug->u.a[v]); + for (k = 1, l = 0, offset = 0, l_pos = 0; k <= u->n; ++k) + { + if (k == u->n || t_ch->ir_het[u->a[k]>>33] != t_ch->ir_het[u->a[l]>>33]) + { + kv_pushp(mc_interval_t, p, &t); + t->uID = v; + t->hs = t_ch->ir_het[u->a[l]>>33]; + + t->bS = l_pos; + t->bE = offset + mg->rg->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_idx, p.n); + } + + ///debug_mc_interval_t(p.a, p.n, p_idx.a, mg->ug, mg->rg, t_ch); + } + + if(!mg->e) + { + CALLOC(mg->e, 1); + mg->e->n_seq = mg->ug->g->n_seq; + kv_init(mg->e->idx); kv_init(mg->e->ma); + } + + if(ha) + { + 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; + if(p.n > 0 && p_idx.n > 0) + { + /*****************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 = p.a + p_idx.a[qn]; + occ = p_idx.a[qn+1] - 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 = p.a + p_idx.a[tn]; + occ = p_idx.a[tn+1] - 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(mc_edge_t, mg->e->ma, &ma); + ma->x = (uint64_t)ha->x[v].a.a[i].xUid << 32 | ha->x[v].a.a[i].yUid; + ma->w = ha->x[v].a.a[i].score; + } + } + } + + if(ta) + { + // double sc = get_w_scale(ta); + // fprintf(stderr, "sc: %f\n", sc); + for (i = 0; i < ta->n; ++i) + { + if(ta->a[i].del) continue; + if(p.n > 0 && p_idx.n > 0) + { + /*****************qn*****************/ + qn = ta->a[i].qn; + qs = ta->a[i].qs; + qe = ta->a[i].qe - 1; + + a = p.a + p_idx.a[qn]; + occ = p_idx.a[qn+1] - 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 = ta->a[i].tn; + ts = ta->a[i].ts; + te = ta->a[i].te - 1; + + a = p.a + p_idx.a[tn]; + occ = p_idx.a[tn+1] - 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(mc_edge_t, mg->e->ma, &ma); + ma->x = (uint64_t)ta->a[i].qn << 32 | ta->a[i].tn; + // ma->w = w_cast((ta->a[i].nw*sc)); + ma->w = w_cast((ta->a[i].nw)); + } + } + + for (i = k = 0; i < mg->e->ma.n; i++) + { + if(mg->e->ma.a[i].w == 0) continue; + mg->e->ma.a[k] = mg->e->ma.a[i]; + k++; + } + mg->e->ma.n = k; + + radix_sort_mce(mg->e->ma.a, mg->e->ma.a + mg->e->ma.n); + mc_merge_dup(mg); + mc_edges_idx(mg->e); + if(is_sys) mc_edges_symm(mg->e); + kv_destroy(p); kv_destroy(p_idx); +} + +void debug_mc_g_t(mc_g_t *mg) +{ + fprintf(stderr, "0----------[M::%s]----------\n", __func__); + mc_edge_t *o = NULL, *s = NULL; + uint32_t i, k, n, cnt; + for (i = 0; i < mg->e->n_seq; ++i) + { + o = pt_a(*(mg->e), i); n = pt_n(*(mg->e), i); + for (k = 0; k < n; ++k) + { + if(ma_x(o[k]) != i) fprintf(stderr, "ERROR-g\n"); + s = get_mc_edge(mg->e, ma_y(o[k]), ma_x(o[k])); + if(!s) fprintf(stderr, "ERROR-e\n"); + if(s) + { + if(!(ma_x(*s) == ma_y(o[k]) && ma_y(*s) == ma_x(o[k]) && s->w == o[k].w)) + { + fprintf(stderr, "ERROR-f\n"); + } + } + } + + for (k = cnt = 0; k < mg->e->ma.n; ++k) + { + if(ma_x(mg->e->ma.a[k]) == i) cnt++; + } + + if(cnt != n) fprintf(stderr, "ERROR-h\n"); + } +} + +uint64_t *mc_g_cc_core(mc_match_t *ma) +{ + uint32_t i, x, y, *flag; + uint64_t *group; + mc_edge_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 = ma_y(o[j]); + 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_mc64(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 mc_g_cc(mc_match_t *ma) +{ + ma->cc = mc_g_cc_core(ma); +} +mc_bp_t *mc_bp_t_init(mc_match_t *ma, mc_svaux_t *b_aux, bubble_type* bub, uint64_t n_thread) +{ + uint32_t i, k, n; + mc_bp_t *bp = NULL; + ma_utg_t *u = NULL; + CALLOC(bp, 1); + bp->b_aux = b_aux; + bp->ma = ma; + bp->b_b = bub; + bp->n_thread = n_thread; + CALLOC(bp->lock, bub->ug->g->n_seq); + CALLOC(bp->res, n_thread); + CALLOC(bp->vis, n_thread); + for (i = 0; i < n_thread; i++) + { + bp->vis[i].m = bp->vis[i].n = bub->ug->g->n_seq; + CALLOC(bp->vis[i].a, bp->vis[i].n); + } + + + MALLOC(bp->idx, bub->chain_weight.n+1); + bp->idx_n = bp->occ = 0; + for (i = 0; i < bub->chain_weight.n; i++) + { + bp->idx[i] = bp->occ; + bp->idx_n++; + if(bub->chain_weight.a[i].del) continue; + u = &(bub->b_ug->u.a[bub->chain_weight.a[i].id]);///list of bubbles + for (k = 0; k < u->n; k++) + { + get_bubbles(bub, u->a[k]>>33, NULL, NULL, NULL, &n, NULL); + bp->occ += n; + } + } + bp->idx[i] = bp->occ; + fprintf(stderr, "# nodes in chains: %lu, # chains: %lu\n", bp->occ, bp->idx_n); + return bp; +} + +void destroy_mc_bp_t(mc_bp_t **bp) +{ + uint32_t i; + for (i = 0; i < (*bp)->n_thread; i++) + { + free((*bp)->vis[i].a); + } + free((*bp)->idx); + free((*bp)->res); + free((*bp)->lock); + free((*bp)); +} + +mc_svaux_t *mc_svaux_init(const mc_g_t *mg, uint64_t x) +{ + uint32_t st, i, max_cc = 0; + mc_match_t *ma = mg->e; + mc_svaux_t *b; + CALLOC(b, 1); + b->x = x; + for (st = 0, i = 1; i <= ma->n_seq; ++i) + if (i == ma->n_seq || ma->cc[st]>>32 != ma->cc[i]>>32) + max_cc = max_cc > i - st? max_cc : i - st, st = i; + kv_init(b->cc_edge); + MALLOC(b->cc_node, max_cc); + ///CALLOC(b->s, ma->n_seq); + b->s = mg->s.a; + CALLOC(b->s_opt, ma->n_seq); + MALLOC(b->bfs, ma->n_seq); + + MALLOC(b->bfs_mark, ma->n_seq); + memset(b->bfs_mark, -1, ma->n_seq*sizeof(uint32_t)); + + CALLOC(b->z, ma->n_seq); + CALLOC(b->z_opt, ma->n_seq); + CALLOC(b->f, ma->n_seq); + return b; +} +void mc_svaux_destroy(mc_svaux_t *b) +{ + b->s = NULL; + kv_destroy(b->cc_edge); free(b->cc_node); + free(b->s); free(b->s_opt); + free(b->z); free(b->z_opt); + free(b->bfs); free(b->bfs_mark); + free(b->f); + free(b); +} + + +mb_svaux_t *mb_svaux_init(const mb_g_t *mg, uint64_t x) +{ + uint32_t st, i, max_cc = 0; + mb_match_t *ma = mg->e; + mb_svaux_t *b; + CALLOC(b, 1); + b->x = x; + for (st = 0, i = 1; i <= ma->n_seq; ++i) + if (i == ma->n_seq || ma->cc[st]>>32 != ma->cc[i]>>32) + max_cc = max_cc > i - st? max_cc : i - st, st = i; + kv_init(b->cc_edge); + MALLOC(b->cc_node, max_cc); + + b->u = mg->u->u.a; + CALLOC(b->u_opt, ma->n_seq); + + MALLOC(b->bfs, ma->n_seq); + MALLOC(b->bfs_mark, ma->n_seq); + memset(b->bfs_mark, -1, ma->n_seq*sizeof(uint32_t)); + + CALLOC(b->f, ma->n_seq); + return b; +} + +void mb_svaux_destroy(mb_svaux_t *b) +{ + b->u = NULL; + kv_destroy(b->cc_edge); free(b->cc_node); + free(b->u); free(b->u_opt); + free(b->bfs); free(b->bfs_mark); + free(b->f); + free(b); +} + + +mc_svaux_t_mul *init_mc_svaux_t_mul(const mc_g_t *mg, uint64_t n_threads) +{ + uint32_t st, i; + mc_match_t *ma = mg->e; + mc_svaux_t_mul *b; CALLOC(b, 1); + for (st = 0, i = 1, b->n_t = 0; i <= ma->n_seq; ++i) + { + if (i == ma->n_seq || ma->cc[st]>>32 != ma->cc[i]>>32) + { + b->n_t++; + } + } + b->n_g = b->n_t; + if(n_threads < b->n_t) b->n_t = n_threads; + + kv_init(b->cc_edge); + MALLOC(b->bfs_mark, ma->n_seq); + memset(b->bfs_mark, -1, ma->n_seq*sizeof(uint32_t)); + CALLOC(b->s_opt, ma->n_seq); + CALLOC(b->z, ma->n_seq); + CALLOC(b->z_opt, ma->n_seq); + b->s = mg->s.a; + + kv_init(b->bs); CALLOC(b->bs.a, b->n_t); + b->bs.n = b->bs.m = b->n_t; + for (i = 0; i < b->bs.n; i++) + { + kv_init(b->bs.a[i].cc_node); + kv_init(b->bs.a[i].bfs); + b->bs.a[i].bfs_mark = b->bfs_mark; + b->bs.a[i].z = b->z; + b->bs.a[i].z_opt = b->z_opt; + b->bs.a[i].s = b->s; + b->bs.a[i].s_opt = b->s_opt; + } + return b; +} + + +void destroy_mc_svaux_t_mul(mc_svaux_t_mul *b) +{ + uint32_t i; + kv_destroy(b->cc_edge); + free(b->bfs_mark); + free(b->s_opt); + free(b->z); + free(b->z_opt); + b->s = NULL; + for (i = 0; i < b->bs.n; i++) + { + kv_destroy(b->bs.a[i].cc_node); + kv_destroy(b->bs.a[i].bfs); + } + kv_destroy(b->bs); + free(b); +} + +uint32_t mc_best(const mc_match_t *ma, mc_svaux_t *b) +{ + uint32_t i, max_i = (uint32_t)-1; + t_w_t w, max_w; + for (i = 0, max_w = -1; i < b->cc_size; ++i) { + uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///uid + if(b->f[k] || b->s[k] == 0) continue; + ///z += -((t_w_t)(b->s[k])) * (b->z[k].z[0] - b->z[k].z[1]); + ///-((t_w_t)(b->s[k])) * (b->z[k].z[0] - b->z[k].z[1]) current + ///((t_w_t)(b->s[k])) * (b->z[k].z[0] - b->z[k].z[1]) flipped + w = ((t_w_t)(b->s[k])) * (b->z[k].z[0] - b->z[k].z[1]) * 2; + if(w <= 0) continue; + if(w > max_w) + { + w = max_w; max_i = k; + } + } + + return max_i; +} + +t_w_t mb_score(mb_g_t *mbg, mb_svaux_t *b) +{ + uint32_t i; + t_w_t z = 0; + mb_match_t *ma = mbg->e; + for (i = 0; i < b->cc_size; ++i) { + uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///uid + ///a[0] + z += -(t_w_t)(mbg->u->u.a[k].s[0]) * (mbg->u->u.a[k].z[0] - mbg->u->u.a[k].z[1]); + ///a[1] + z += -(t_w_t)(mbg->u->u.a[k].s[1]) * (mbg->u->u.a[k].z[2] - mbg->u->u.a[k].z[3]); + } + return z; +} + +t_w_t mc_score(const mc_match_t *ma, mc_svaux_t *b) +{ + uint32_t i; + t_w_t z = 0; + for (i = 0; i < b->cc_size; ++i) { + uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///uid + z += -((t_w_t)(b->s[k])) * (b->z[k].z[0] - b->z[k].z[1]); + } + return z; +} + +t_w_t mc_score_all(const mc_match_t *ma, mc_svaux_t *b) +{ + uint32_t k; + t_w_t z = 0; + for (k = 0; k < ma->n_seq; ++k) + { + z += -((t_w_t)(b->s[k])) * (b->z[k].z[0] - b->z[k].z[1]); + } + return z; +} + +void mc_reset_z(const mc_match_t *ma, mc_svaux_t *b) +{ + uint32_t i; + for (i = 0; i < b->cc_size; ++i) { + uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///uid + uint32_t o = ma->idx.a[k] >> 32; + uint32_t j, n = (uint32_t)ma->idx.a[k]; + b->z[k].z[0] = b->z[k].z[1] = 0; + for (j = 0; j < n; ++j) { + const mc_edge_t *e = &ma->ma.a[o + j]; + uint32_t t = ma_y(*e); + if (b->s[t] > 0) b->z[k].z[0] += e->w; + else if (b->s[t] < 0) b->z[k].z[1] += e->w; + } + } +} + +void mc_reset_z_debug(const mc_match_t *ma, mc_svaux_t *b) +{ + uint32_t i; + t_w_t z[2]; + for (i = 0; i < b->cc_size; ++i) { + uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///uid + uint32_t o = ma->idx.a[k] >> 32; + uint32_t j, n = (uint32_t)ma->idx.a[k]; + z[0] = b->z[k].z[0]; z[1] = b->z[k].z[1]; + b->z[k].z[0] = b->z[k].z[1] = 0; + for (j = 0; j < n; ++j) { + const mc_edge_t *e = &ma->ma.a[o + j]; + uint32_t t = ma_y(*e); + if (b->s[t] > 0) b->z[k].z[0] += e->w; + else if (b->s[t] < 0) b->z[k].z[1] += e->w; + } + if(z[0] != b->z[k].z[0]) fprintf(stderr, "ERROR1\n"); + if(z[1] != b->z[k].z[1]) fprintf(stderr, "ERROR2\n"); + } +} + + +t_w_t mc_init_spin(const mc_match_t *ma, mc_svaux_t *b) +{ + uint32_t i; + b->cc_edge.n = 0; + if(b->cc_size <= 2)//mannually clear + { + for (i = 0; i < b->cc_size; ++i) {///how many nodes + b->s[(uint32_t)ma->cc[b->cc_off + i]] = 0; + } + } + + for (i = 0; i < b->cc_size; ++i) {///how many nodes + uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///node id + b->cc_node[i] = k; + if(b->s[k] == 0) break; + } + if(i >= b->cc_size) goto passed; + + for (i = 0; i < b->cc_size; ++i) {///how many nodes + uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///node id + uint32_t o = ma->idx.a[k] >> 32;///cc group id + uint32_t n = (uint32_t)ma->idx.a[k], j; + b->cc_node[i] = k; + for (j = 0; j < n; ++j) { + w_t w = ma->ma.a[o + j].w; + w = w > 0? w : -w; + kv_push(uint64_t, b->cc_edge, (uint64_t)((uint32_t)-1 - ((uint32_t)w)) << 32 | (o + j)); + } + } + radix_sort_mc64(b->cc_edge.a, b->cc_edge.a + b->cc_edge.n); + for (i = 0; i < b->cc_edge.n; ++i) { // from the strongest edge to the weakest + const mc_edge_t *e = &ma->ma.a[(uint32_t)b->cc_edge.a[i]]; + uint32_t n1 = ma_x(*e), n2 = ma_y(*e); + if (b->s[n1] == 0 && b->s[n2] == 0) { + b->x = kr_splitmix64(b->x); + b->s[n1] = b->x&1? 1 : -1; + b->s[n2] = e->w > 0? -b->s[n1] : b->s[n1]; + }/****************************may have bugs********************************/ + else if(b->s[n1] == 0) + { + b->s[n1] = e->w > 0? -b->s[n2] : b->s[n2]; + } + else if(b->s[n2] == 0) + { + b->s[n2] = e->w > 0? -b->s[n1] : b->s[n1]; + } + /****************************may have bugs********************************/ + } + + passed: + mc_reset_z(ma, b); + return mc_score(ma, b); +} +///k is uid +static void mc_set_spin(const mc_match_t *ma, mc_svaux_t *b, uint32_t k, int8_t s) +{ + uint32_t o, j, n; + int8_t s0 = b->s[k]; + if (s0 == s) return; + o = ma->idx.a[k] >> 32; + n = (uint32_t)ma->idx.a[k]; + for (j = 0; j < n; ++j) { + const mc_edge_t *e = &ma->ma.a[o + j]; + uint32_t t = ma_y(*e);///1->z[0]; (-1)->z[1]; + if (s0 != 0) b->z[t].z[(s0 < 0)] -= e->w; + if (s != 0) b->z[t].z[(s < 0)] += e->w; + } + b->s[k] = s; +} + +void debug_mb_z(mb_g_t *mbg, uint32_t k) +{ + t_w_t z[4]; + z[0] = z[1] = z[2] = z[3] = 0; + mb_match_t *ma = mbg->e; + uint32_t o = ma->idx.a[k] >> 32; + uint32_t j, n = (uint32_t)ma->idx.a[k]; + + for (j = 0; j < n; ++j) { + const mb_edge_t *e = &ma->ma.a[o + j]; + uint32_t t = ma_y(*e); + + ///a[0]->b[0] + if(mbg->u->u.a[t].s[0] > 0) z[0] += e->w[0]; + else if(mbg->u->u.a[t].s[0] < 0) z[1] += e->w[0]; + + ///a[0]->b[1] + if(mbg->u->u.a[t].s[1] > 0) z[0] += e->w[1]; + else if(mbg->u->u.a[t].s[1] < 0) z[1] += e->w[1]; + + ///a[1]->b[0] + if(mbg->u->u.a[t].s[0] > 0) z[2] += e->w[2]; + else if(mbg->u->u.a[t].s[0] < 0) z[3] += e->w[2]; + + ///a[1]->b[1] + if(mbg->u->u.a[t].s[1] > 0) z[2] += e->w[3]; + else if(mbg->u->u.a[t].s[1] < 0) z[3] += e->w[3]; + } + + if(mbg->u->u.a[k].z[0] != z[0]) fprintf(stderr, "ERROR-0-::%s, z[0]: %f, n-z[0]: %f\n", __func__, z[0], mbg->u->u.a[k].z[0]); + if(mbg->u->u.a[k].z[1] != z[1]) fprintf(stderr, "ERROR-1-::%s, z[1]: %f, n-z[1]: %f\n", __func__, z[1], mbg->u->u.a[k].z[1]); + if(mbg->u->u.a[k].z[2] != z[2]) fprintf(stderr, "ERROR-2-::%s, z[2]: %f, n-z[2]: %f\n", __func__, z[2], mbg->u->u.a[k].z[2]); + if(mbg->u->u.a[k].z[3] != z[3]) fprintf(stderr, "ERROR-3-::%s, z[3]: %f, n-z[3]: %f\n", __func__, z[3], mbg->u->u.a[k].z[3]); +} + +///k is uid +static void mb_flip_spin(mb_g_t *mbg, mb_svaux_t *b, uint32_t k) +{ + if(mbg->u->u.a[k].s[0] == 0 && mbg->u->u.a[k].s[1] == 0) return; + mb_match_t *ma = mbg->e; + uint32_t o, j, n; + o = ma->idx.a[k] >> 32; + n = (uint32_t)ma->idx.a[k]; + mbg->u->u.a[k].s[0] = -mbg->u->u.a[k].s[0]; + mbg->u->u.a[k].s[1] = -mbg->u->u.a[k].s[1]; + for (j = 0; j < n; ++j) { + const mb_edge_t *e = &ma->ma.a[o + j]; + uint32_t t = ma_y(*e);///1->z[0]; (-1)->z[1]; + + if(mbg->u->u.a[k].s[0] != 0) + { + ///note: e is from k to t + ///t[0] ---> k[0], so update z[0 + x] and e[0] + mbg->u->u.a[t].z[mbg->u->u.a[k].s[0] < 0] += e->w[0]; + mbg->u->u.a[t].z[mbg->u->u.a[k].s[0] > 0] -= e->w[0]; + + ///t[1] ---> k[0], so update z[2 + x] and e[1] + mbg->u->u.a[t].z[(mbg->u->u.a[k].s[0] < 0) + 2] += e->w[1]; + mbg->u->u.a[t].z[(mbg->u->u.a[k].s[0] > 0) + 2] -= e->w[1]; + } + + if(mbg->u->u.a[k].s[1] != 0) + { + ///note: e is from k to t + ///t[0] ---> k[1], so update z[0 + x] and e[2] + mbg->u->u.a[t].z[mbg->u->u.a[k].s[1] < 0] += e->w[2]; + mbg->u->u.a[t].z[mbg->u->u.a[k].s[1] > 0] -= e->w[2]; + + ///t[1] ---> k[1], so update z[2 + x] and e[3] + mbg->u->u.a[t].z[(mbg->u->u.a[k].s[1] < 0) + 2] += e->w[3]; + mbg->u->u.a[t].z[(mbg->u->u.a[k].s[1] > 0) + 2] -= e->w[3]; + } + + /*******************************for debug************************************/ + // debug_mb_z(mbg, t); + /*******************************for debug************************************/ + } +} + +void mc_best_flip(const mc_match_t *ma, mc_svaux_t *b) +{ + uint32_t idx; + for (idx = 0; idx < b->cc_size; ++idx) { + b->f[(uint32_t)ma->cc[b->cc_off + idx]] = 0; + ///uint32_t k = (uint32_t)ma->cc[b->cc_off + idx];///uid + } + while (1) + { + idx = mc_best(ma, b); + if(idx == (uint32_t)-1) break; + mc_set_spin(ma, b, idx, -b->s[idx]); + b->f[idx] = 1; + } +} + +static t_w_t mc_optimize_local(const mc_opt_t *opt, const mc_match_t *ma, mc_svaux_t *b, uint32_t *n_iter) +{ + uint32_t i, n_flip = 0; + int32_t n_iter_local = 0; + while (n_iter_local < opt->max_iter) { + ++(*n_iter); + ks_shuffle_uint32_t(b->cc_size, b->cc_node, &b->x); + for (i = n_flip = 0; i < b->cc_size; ++i) { + uint32_t k = b->cc_node[i];///uid + int8_t s; + if (b->z[k].z[0] == b->z[k].z[1]) continue; + s = b->z[k].z[0] > b->z[k].z[1]? -1 : 1; + if (b->s[k] != s) { + // fprintf(stderr, "utg%.6dl, s[k]::%d, s::%d\n", (int32_t)(k)+1, b->s[k], s); + mc_set_spin(ma, b, k, s);///no need to change the score of k itself + ++n_flip; + } + } + ++n_iter_local; + if (n_flip == 0) break; + } + + // if(n_flip != 0) mc_best_flip(ma, b); + return mc_score(ma, b); +} + +static t_w_t mb_optimize_local(const mc_opt_t *opt, mb_g_t *mbg, mb_svaux_t *b, uint32_t *n_iter) +{ + uint32_t i, n_flip = 0; + int32_t n_iter_local = 0; + mb_node_t *u = NULL; + t_w_t z = 0; + while (n_iter_local < opt->max_iter) { + ++(*n_iter); + ks_shuffle_uint32_t(b->cc_size, b->cc_node, &b->x); + for (i = n_flip = 0; i < b->cc_size; ++i) { + uint32_t k = b->cc_node[i];///uid + u = &(mbg->u->u.a[k]); + if(u->z[0] == u->z[1] && u->z[2] == u->z[3]) continue; + z = 0; + ///a[0] + z += -(t_w_t)(u->s[0]) * (u->z[0] - u->z[1]); + ///a[1] + z += -(t_w_t)(u->s[1]) * (u->z[2] - u->z[3]); + if(z >= 0) continue; + + mb_flip_spin(mbg, b, k);///no need to change the score of k itself + ++n_flip; + } + ++n_iter_local; + if (n_flip == 0) break; + } + + // if(n_flip != 0) mc_best_flip(ma, b); + return mb_score(mbg, b); +} + +static void mc_perturb(const mc_opt_t *opt, const mc_match_t *ma, mc_svaux_t *b) +{ + uint32_t i; + for (i = 0; i < b->cc_size; ++i) { + uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///node id + double y; + y = kr_drand_r(&b->x); + if (y < opt->f_perturb) + mc_set_spin(ma, b, k, -b->s[k]); + } +} + +static void mb_perturb(const mc_opt_t *opt, mb_g_t *mbg, mb_svaux_t *b) +{ + uint32_t i; + for (i = 0; i < b->cc_size; ++i) { + uint32_t k = (uint32_t)mbg->e->cc[b->cc_off + i];///node id + double y; + y = kr_drand_r(&b->x); + if (y < opt->f_perturb) + mb_flip_spin(mbg, b, k); + } +} + +static uint32_t mc_bfs(const mc_match_t *ma, mc_svaux_t *b, uint32_t k0, uint32_t bfs_round, uint32_t max_size) +{ + uint32_t i, n_bfs = 0, st, en, r; + b->bfs[n_bfs++] = k0, b->bfs_mark[k0] = k0; + st = 0, en = n_bfs; + for (r = 0; r < bfs_round; ++r) { + for (i = st; i < en; ++i) { + uint32_t k = b->bfs[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) { + uint32_t t = (uint32_t)ma->ma.a[o + j].x; + if (b->bfs_mark[t] != k0) + b->bfs[n_bfs++] = t, b->bfs_mark[t] = k0; + } + } + st = en, en = n_bfs; + if (max_size > 0 && n_bfs > max_size) break; + } + return n_bfs; +} + +///bfs_round is 3 +static void mc_perturb_node(const mc_opt_t *opt, const mc_match_t *ma, mc_svaux_t *b, int32_t bfs_round) +{ + uint32_t i, k, n_bfs = 0; + k = (uint32_t)(kr_drand_r(&b->x) * b->cc_size + .499); + if(k >= b->cc_size) k = b->cc_size - 1; + k = (uint32_t)ma->cc[b->cc_off + k];///node id + n_bfs = mc_bfs(ma, b, k, bfs_round, (int32_t)(b->cc_size * opt->f_perturb)); + for (i = 0; i < n_bfs; ++i) + mc_set_spin(ma, b, b->bfs[i], -b->s[b->bfs[i]]); +} + + +static uint32_t mb_bfs(const mb_match_t *ma, mb_svaux_t *b, uint32_t k0, uint32_t bfs_round, uint32_t max_size) +{ + uint32_t i, n_bfs = 0, st, en, r; + b->bfs[n_bfs++] = k0, b->bfs_mark[k0] = k0; + st = 0, en = n_bfs; + for (r = 0; r < bfs_round; ++r) { + for (i = st; i < en; ++i) { + uint32_t k = b->bfs[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) { + uint32_t t = (uint32_t)ma->ma.a[o + j].x; + if (b->bfs_mark[t] != k0) + b->bfs[n_bfs++] = t, b->bfs_mark[t] = k0; + } + } + st = en, en = n_bfs; + if (max_size > 0 && n_bfs > max_size) break; + } + return n_bfs; +} + +///bfs_round is 3 +static void mb_perturb_node(const mc_opt_t *opt, mb_g_t *mbg, mb_svaux_t *b, int32_t bfs_round) +{ + uint32_t i, k, n_bfs = 0; + k = (uint32_t)(kr_drand_r(&b->x) * b->cc_size + .499); + if(k >= b->cc_size) k = b->cc_size - 1; + k = (uint32_t)mbg->e->cc[b->cc_off + k];///node id + n_bfs = mb_bfs(mbg->e, b, k, bfs_round, (int32_t)(b->cc_size * opt->f_perturb)); + for (i = 0; i < n_bfs; ++i) + mb_flip_spin(mbg, b, b->bfs[i]); +} + +void clean_mc_bp_res(mc_bp_res *res) +{ + res->chain_id = (uint32_t)-1; + res->f_bid = res->f_uid = res->l_bid = res->l_uid = (uint32_t)-1; + res->id = (uint32_t)-1; res->w = -1; +} + +void reset_mc_bp_iter(mc_bp_t* bp, mc_bp_iter *x, uint64_t id) +{ + ma_utg_t *u = NULL; + uint32_t i, n, occ; + for (i = 0; i < bp->idx_n; i++) + { + if(id >= bp->idx[i]) break; + } + + id -= bp->idx[i]; + x->chain_id = bp->b_b->chain_weight.a[i].id; + u = &(bp->b_b->b_ug->u.a[x->chain_id]); + for (i = occ = 0; i < u->n; i++) + { + get_bubbles(bp->b_b, u->a[i]>>33, NULL, NULL, NULL, &n, NULL); + occ += n; + if(id < occ) + { + x->bid = i; + x->uid = id - (occ -n); + break; + } + } +} +inline uint32_t next_uid(mc_bp_iter *iter, bubble_type* bub, uint32_t *c_bid, uint32_t *c_uid) +{ + ma_utg_t *u = &(bub->b_ug->u.a[iter->chain_id]); + uint32_t *a, n, uid; + while (1) + { + if(iter->bid >= u->n) break; + get_bubbles(bub, u->a[iter->bid]>>33, NULL, NULL, &a, &n, NULL); + while (1) + { + if(iter->uid >= n) break; + uid = a[iter->uid]>>1; + if(c_bid) (*c_bid) = iter->bid; + if(c_uid) (*c_uid) = iter->uid; + iter->uid++; + return uid; + } + iter->bid++, iter->uid = 0; + } + return (uint32_t)-1; +} + +t_w_t incre_weight(mc_svaux_t *b_aux, mc_match_t *ma, uint8_t* vis, uint32_t uid) +{ + mc_edge_t *o = NULL; + uint32_t n, i, t; + t_w_t w = ((t_w_t)(b_aux->s[uid])) * (b_aux->z[uid].z[0] - b_aux->z[uid].z[1]) * 2; + t_w_t w_off = 0; + o = pt_a(*ma, uid); + n = pt_n(*ma, uid); + for (i = 0; i < n; ++i) + { + t = ma_y(o[i]); + if(vis[t] == 0) continue; + if(t == uid) continue; + w_off += (b_aux->s[uid]*b_aux->s[t]*o[i].w); + } + return w - (w_off*4);//2 for self; 4 for both directions +} + +void select_min_bp(bubble_type* bub, mc_match_t *ma, mc_svaux_t *b_aux, mc_bp_t* bp, +uint8_t *lock, bits_p *vis, uint64_t id, mc_bp_res* r) +{ + uint32_t uid, val = 0, max_bid, max_uid, c_bid, c_uid, f_bid, f_uid; + t_w_t w = 0, max_w = -1; + mc_bp_iter i; + reset_mc_bp_iter(bp, &i, id); + memset(vis->a, 0, vis->n); + max_bid = max_uid = (uint32_t)-1; + f_bid = i.bid; f_uid = i.uid;///f_bid::bubble id, f_uid::unitig id + + while (1) + { + uid = next_uid(&i, bub, &c_bid, &c_uid); + if(uid == (uint32_t)-1) break; + if(vis->a[uid]) continue; ///already flip uid + ///update w + w += incre_weight(b_aux, ma, vis->a, uid); + vis->a[uid] = 1; + if(lock[uid] == 0) val = 1; + if(val == 0) continue; + ///update max_w + if(max_w < w) + { + max_w = w; + max_bid = c_bid; + max_uid = c_uid; + } + } + + if(max_w <= 0 || max_bid == (uint32_t)-1 || max_uid == (uint32_t)-1) return; + if((max_w > r->w) || (max_w == r->w && id < r->id)) + { + r->w = max_w; + r->id = id; + r->chain_id = i.chain_id; + r->l_bid = max_bid; + r->l_uid = max_uid; + r->f_bid = f_bid; + r->f_uid = f_uid; + } + ///if((res->min_w > i_b->weight) || (res->min_w == i_b->weight && id < res->min_idx)) +} + +static void worker_for_min_bp(void *data, long i, int tid) // callback for kt_for() +{ + mc_bp_t* bp = (mc_bp_t *)data; + select_min_bp(bp->b_b, bp->ma, bp->b_aux, bp, bp->lock, &(bp->vis[tid]), i, &(bp->res[tid])); +} + +uint32_t best_bp(mc_bp_t *bp, mc_bp_res *res) +{ + uint32_t i; + clean_mc_bp_res(res); + for (i = 0; i < bp->n_thread; i++) + { + clean_mc_bp_res(&(bp->res[i])); + } + kt_for(bp->n_thread, worker_for_min_bp, bp, bp->occ); + + for (i = 0; i < bp->n_thread; i++) + { + if(bp->res[i].chain_id == (uint32_t)-1) continue; + if(bp->res[i].w <= 0) continue; + if((bp->res[i].w > res->w) || (bp->res[i].w == res->w && bp->res[i].id < res->id)) + { + (*res) = bp->res[i]; + } + } + if(res->chain_id != (uint32_t)-1) return 1; + return 0; +} + +void mc_set_bp_spin(bubble_type* bub, mc_match_t *ma, mc_svaux_t *b_aux, mc_bp_t* bp, +uint8_t *lock, bits_p *vis, mc_bp_res *res) +{ + uint32_t uid, val = 0, c_bid, c_uid; + mc_bp_iter i; + i.chain_id = res->chain_id; + i.bid = res->f_bid; + i.uid = res->f_uid; + memset(vis->a, 0, vis->n); + while (1) + { + uid = next_uid(&i, bub, &c_bid, &c_uid); + if(uid == (uint32_t)-1) break; + if(lock[uid] == 0) + { + val = 1; + break; + } + if(c_bid == res->l_bid && c_uid == res->l_uid) break; + } + + if(val == 0) + { + fprintf(stderr, "ERROR-1\n"); + return; + } + + i.bid = res->f_bid; + i.uid = res->f_uid; + while (1) + { + uid = next_uid(&i, bub, &c_bid, &c_uid); + if(uid == (uint32_t)-1) break; + if(vis->a[uid] == 1) continue; + lock[uid] = 1; + vis->a[uid] = 1; + mc_set_spin(ma, b_aux, uid, -b_aux->s[uid]); + if(c_bid == res->l_bid && c_uid == res->l_uid) break; + } +} + +t_w_t mc_solve_bp_cc(mc_bp_t *bp) +{ + mc_bp_res res; + memset(bp->lock, 0, bp->b_b->ug->g->n_seq); + while (best_bp(bp, &res)) + { + mc_set_bp_spin(bp->b_b, bp->ma, bp->b_aux, bp, bp->lock, &(bp->vis[0]), &res); + } + + return mc_score_all(bp->ma, bp->b_aux); +} + +void mc_reset_z_all(const mc_match_t *ma, mc_svaux_t *b) +{ + // t_w_t z[2]; + uint32_t k; + for (k = 0; k < ma->n_seq; ++k) + { + uint32_t o = ma->idx.a[k] >> 32; + uint32_t j, n = (uint32_t)ma->idx.a[k]; + // z[0] = b->z[k].z[0]; z[1] = b->z[k].z[1]; + b->z[k].z[0] = b->z[k].z[1] = 0; + for (j = 0; j < n; ++j) { + const mc_edge_t *e = &ma->ma.a[o + j]; + uint32_t t = ma_y(*e); + if (b->s[t] > 0) b->z[k].z[0] += e->w; + else if (b->s[t] < 0) b->z[k].z[1] += e->w; + } + // if(z[0] != b->z[k].z[0]) fprintf(stderr, "ERROR1-all\n"); + // if(z[1] != b->z[k].z[1]) fprintf(stderr, "ERROR2-all\n"); + } +} + +void mc_solve_bp(mc_bp_t *bp) +{ + double index_time = yak_realtime(); + uint32_t r = 1; + t_w_t sc_opt, sc; + mc_reset_z_all(bp->ma, bp->b_aux); + sc_opt = mc_score_all(bp->ma, bp->b_aux); + + while (1) + { + sc = mc_solve_bp_cc(bp); + // fprintf(stderr, "[M::%s::# round: %u] sc_opt: %ld, sc: %ld\n", __func__, r, sc_opt, sc); + fprintf(stderr, "[M::%s::# round: %u] sc_opt: %f, sc: %f\n", __func__, r, sc_opt, sc); + if(sc <= sc_opt) break; + sc_opt = sc; + r++; + } + fprintf(stderr, "[M::%s::%.3f] ==> round %u\n", __func__, yak_realtime()-index_time, r); +} + +t_w_t mc_score_all_advance(const mc_match_t *ma, int8_t *s) +{ + uint32_t k; + t_w_t z[2], zt = 0; + for (k = 0; k < ma->n_seq; ++k) + { + uint32_t o = ma->idx.a[k] >> 32; + uint32_t j, n = (uint32_t)ma->idx.a[k]; + z[0] = z[1] = 0; + for (j = 0; j < n; ++j) { + const mc_edge_t *e = &ma->ma.a[o + j]; + uint32_t t = ma_y(*e); + if (s[t] > 0) z[0] += e->w; + else if (s[t] < 0) z[1] += e->w; + } + zt += -((t_w_t)(s[k])) * (z[0] - z[1]); + } + return zt; +} + +void mc_status_all(const mc_match_t *ma, int8_t *s) +{ + t_w_t tt_w = mc_score_all_advance(ma, s); + uint64_t k, nn = 0, ne = 0; + for (k = 0; k < ma->n_seq; ++k) { + if((uint32_t)ma->idx.a[k]) nn++; + ne += (uint32_t)ma->idx.a[k]; + } + fprintf(stderr, "[M::%s::] ==> # nodes: %lu, # edges: %lu, weight: %f\n", __func__, nn, ne, tt_w); +} + + +t_w_t mb_score_all_advance(const mc_match_t *ma, mb_g_t *mbg) +{ + uint32_t k; + t_w_t z[2], zt = 0; + for (k = 0; k < ma->n_seq; ++k) + { + uint32_t o = ma->idx.a[k] >> 32; + uint32_t j, n = (uint32_t)ma->idx.a[k]; + z[0] = z[1] = 0; + for (j = 0; j < n; ++j) { + const mc_edge_t *e = &ma->ma.a[o + j]; + uint32_t t = ma_y(*e); + if (mbg->u->u.a[mbg->u->idx.a[t]>>1].s[mbg->u->idx.a[t]&1] > 0) z[0] += e->w; + else if (mbg->u->u.a[mbg->u->idx.a[t]>>1].s[mbg->u->idx.a[t]&1] < 0) z[1] += e->w; + } + zt += -((t_w_t)(mbg->u->u.a[mbg->u->idx.a[k]>>1].s[mbg->u->idx.a[k]&1])) * (z[0] - z[1]); + } + return zt; +} + +void print_sc(const mc_opt_t *opt, const mc_g_t *mg, mc_svaux_t *b, t_w_t sc_opt, uint32_t n_iter) +{ + t_w_t w = mc_score(mg->e, b); + // if(w != sc_opt) fprintf(stderr, "ERROR\n"); + fprintf(stderr, "# iter: %u, sc_opt: %f, sc-local: %f, sc-global: %f\n", n_iter, sc_opt, w, mc_score_all_advance(mg->e, mg->s.a)); +} + +void print_mc_node(const mc_match_t *ma, mc_svaux_t *b, uint32_t id) +{ + fprintf(stderr, "[M::%s::utg%.6ul-hap%u]\n", __func__, id, b->s[id]>0?1:b->s[id]<0?2:0); + w_t w[128], z[4]; + uint32_t o, n, i, hn = 4; + int8_t s; + for (i = 0; i < hn; i++) w[i] = 0; + o = ma->idx.a[id] >> 32; + n = (uint32_t)ma->idx.a[id]; + for (i = 0; i < n; ++i) + { + s = b->s[ma_y(ma->ma.a[o + i])]; + w[s>0?1:s<0?2:0] += ma->ma.a[o + i].w; + } + z[0] = z[3] = 0; z[1] = b->z[id].z[0]; z[2] = b->z[id].z[1]; + for (i = 0; i < hn; i++) fprintf(stderr, "w[%u]-%f, z[%u]-%f\n", i, w[i], i, z[i]); +} + +uint32_t mc_solve_cc(const mc_opt_t *opt, const mc_g_t *mg, mc_svaux_t *b, uint32_t cc_off, uint32_t cc_size) +{ + uint32_t j, k, n_iter = 0, flush = opt->max_iter * 50; + t_w_t sc_opt = -(1<<30), sc;///problem-w + b->cc_off = cc_off, b->cc_size = cc_size; + if (b->cc_size < 2) return 0; + sc_opt = mc_init_spin(mg->e, b); + // print_sc(opt, mg, b, sc_opt, n_iter); + if (b->cc_size == 2) return 0; + for (j = 0; j < b->cc_size; ++j) {///backup s and z in s_opt and z_opt + b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; ///hap status of each unitig + b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; ///z[0]: positive weight; z[1]: positive weight + } + // print_sc(opt, mg->e, b, sc_opt, n_iter); + sc = mc_optimize_local(opt, mg->e, b, &n_iter); + if (sc > sc_opt) { + for (j = 0; j < b->cc_size; ++j) { + b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; + b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; + } + sc_opt = sc; + } else { + for (j = 0; j < b->cc_size; ++j) { + b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; + b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; + } + } + + // print_mc_node(mg->e, b, 36880); + // print_sc(opt, mg, b, sc_opt, n_iter); + // mc_reset_z_debug(mg->e, b); + // print_sc(opt, mg->e, b, sc_opt, n_iter); + // fprintf(stderr, "\ncc_size: %u, cc_off: %u\n", b->cc_size, b->cc_off); + for (k = 0; k < (uint32_t)opt->n_perturb; ++k) { + if (k&1) mc_perturb(opt, mg->e, b); + else mc_perturb_node(opt, mg->e, b, 3); + sc = mc_optimize_local(opt, mg->e, b, &n_iter); + // fprintf(stderr, "(%u) sc_opt: %f, sc: %f\n", k, sc_opt, sc); + if (sc > sc_opt) { + for (j = 0; j < b->cc_size; ++j) { + b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; + b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; + } + sc_opt = sc; + // print_sc(opt, mg, b, sc_opt, n_iter); + } else { + for (j = 0; j < b->cc_size; ++j) { + b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; + b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; + } + } + + if((n_iter%flush) == 0) + { + mc_reset_z(mg->e, b); + sc = mc_score(mg->e, b); + + for (j = 0; j < b->cc_size; ++j) { + b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; + } + sc_opt = sc; + } + } + + for (j = 0; j < b->cc_size; ++j) + { + b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; + b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; + } + + return n_iter; +} + +#define clus_a(b, id) (((b)).cc.nn.a+(((b)).cc.ng.a[(id)]>>32)) +#define clus_n(b, id) (((uint32_t)((((b)).cc.ng.a[(id)])))) + + +void reorder_bub(const mc_match_t *ma, uint32_t *a, uint32_t a_n, uint8_t *ff, uint8_t lf, uint8_t rf, uint8_t cf, +uint8_t cuf, double *sc_l, double *sc_r, double *sc_m, uint32_t *res) +{ + uint32_t k, o, j, n, t, z; mc_edge_t *e; + double mm_l, mm_r, m_inner, mm; int64_t mmlk, mmrk, rev, m_inner_k, mmk; + for (k = 0; k < a_n; k++) ff[a[k]] = cf; + m_inner = 0; m_inner_k = -1; mm_l = mm_r = 0; mmlk = mmrk = -1; + for (k = 0, rev = -1; k < a_n; k++) { + sc_l[k] = sc_r[k] = sc_m[k] = 0; + o = ma->idx.a[a[k]] >> 32; n = (uint32_t)ma->idx.a[a[k]]; + for (j = 0; j < n; ++j) { + e = &ma->ma.a[o + j]; + t = ma_y(*e); + if(ff[t] == lf) sc_l[k] += fabs(e->w); + if(ff[t] == rf) sc_r[k] += fabs(e->w); + if(ff[t] == cf) sc_m[k] += fabs(e->w); + } + if(sc_l[k] > 0) { + if(sc_l[k] > mm_l) { + mm_l = sc_l[k]; mmlk = k; + } + } else if(sc_r[k] > 0) { + if(sc_r[k] > mm_r) { + mm_r = sc_r[k]; mmrk = k; + } + } else if(sc_m[k] > 0 && sc_m[k] > m_inner) { + m_inner = sc_m[k]; m_inner_k = k; + } + } + if(mmlk == -1 && mmrk == -1 && m_inner_k == -1) return; + if(mmlk != -1) { + mm = mm_l; mmk = mmlk; rev = 0; + } else if(mmrk != -1) { + mm = mm_r; mmk = mmrk; rev = 1; + } else { + mm = m_inner; mmk = m_inner_k; rev = 0; + } + + double *sc = (!rev)?sc_l:sc_r; + // for (k = 0; k < a_n; k++) { + // // sc_m[k] = 0; + // fprintf(stderr, "+[M::%s] a_n::%u, a[%u]::%u\n", __func__, a_n, k, a[k]); + // } + + z = 0; res[z++] = a[mmk]; ff[a[mmk]] = cuf; + for (; z < a_n; ) { + for (k = 0, mm = 0, mmk = -1; k < a_n; k++) { + if(ff[a[k]] == cuf) continue; + o = ma->idx.a[a[k]] >> 32; n = (uint32_t)ma->idx.a[a[k]]; + for (j = 0; j < n; ++j) { + e = &ma->ma.a[o + j]; + t = ma_y(*e); + if(ff[t] == cuf) sc[k] += fabs(e->w); + // if(ff[t] == cuf) sc_m[k] += fabs(e->w); + } + + if(sc[k] > 0) { + if(sc[k] > mm) { + mm = sc[k]; mmk = k; + } + } + } + if(mmk == -1) break; + // fprintf(stderr, "-[M::%s] mmk::%ld, a[%ld]::%u, z::%u\n", __func__, mmk, mmk, a[mmk], z); + res[z++] = a[mmk]; ff[a[mmk]] = cuf; + } + // fprintf(stderr, "[M::%s] a_n::%u, z::%u\n", __func__, a_n, k, z); + if(z < a_n) { + for (k = 0; k < a_n; k++) { + if(ff[a[k]] == cuf) continue; + res[z++] = a[k]; ff[a[k]] = cuf; + } + } + assert(z == a_n); + if(!rev) { + for (k = 0; k < a_n; k++) { + a[k] = res[k]; + // fprintf(stderr, "[M::%s] a_n::%u, a[k]::%u, res[k]::%u\n", __func__, a_n, a[k], res[k]); + ff[a[k]] = lf; + } + } else { + for (k = 0; k < a_n; k++) { + a[k] = res[a_n-k-1]; ff[a[k]] = lf; + } + } +} + +void prt_bub(uint32_t *a, uint32_t a_n, const char *cmd) +{ + uint32_t k; + fprintf(stderr, "%s\n", cmd); + for (k = 0; k < a_n; k++) { + fprintf(stderr, "utg%.6dl\t", (int32_t)a[k]+1); + } + fprintf(stderr, "\n"); + +} + +void renew_mc_clus_t(mc_clus_t *bc, uint32_t *a, uint32_t a_n) +{ + if(!bc) return; + // fprintf(stderr, "[M::%s] a_n::%u\n", __func__, a_n); + uint32_t k, i, *ba, bn, m, cocc, iin, /**bub_occ = 0,**/ bbn = 0; uint64_t *p; ma_utg_t *u = NULL; + kvec_t(double) sc_l; kvec_t(double) sc_r; kvec_t(double) sc_m; kvec_t(uint32_t) tmp; + kv_init(sc_l); kv_init(sc_r); kv_init(sc_m); kv_init(tmp); + + bc->cc.ng.n = bc->cc.nn.n = 0; + memset(bc->lock, 0, sizeof((*(bc->lock)))*bc->n);///bc->n: number of all nodes + for (k = 0; k < a_n; k++) bc->lock[a[k]] = 1;///a_n: number of nodes within the cluster + + kv_resize(uint32_t, bc->cc.nn, a_n); + // for (i = 0; i < bc->bub->chain_weight.n; i++) { + // if(bc->bub->chain_weight.a[i].del) continue; + // u = &(bc->bub->b_ug->u.a[bc->bub->chain_weight.a[i].id]);///list of bubbles + for (i = 0; i < bc->bub->b_ug->u.n; i++) { + u = &(bc->bub->b_ug->u.a[i]); + if(u->n == 0) continue; + // bub_occ += u->n; + // fprintf(stderr, "[M::%s] i::%u, u->n::%u\n", __func__, i, (uint32_t)u->n); + for (k = cocc = 0, iin = bc->cc.nn.n; k < u->n; k++) { + get_bubbles(bc->bub, u->a[k]>>33, NULL, NULL, &ba, &bn, NULL); + kv_pushp(uint64_t, bc->cc.ng, &p); bbn += bn; + *p = bc->cc.nn.n;///a bubble + for (m = 0; m < bn; m++) { + if(!(bc->lock[ba[m]>>1])) continue;///if the node of bubble is not at this cluster + kv_push(uint32_t, bc->cc.nn, (ba[m]>>1)); + bc->lock[ba[m]>>1] = 2; + } + if(bc->cc.nn.n <= (*p)) {///no node in this bubble + bc->cc.ng.n--; + continue; + } + *p <<= 32; *p |= (bc->cc.nn.n-((*p)>>32)); cocc++; + } + //split the chain if there is multipe bubbles + if(cocc > 0) {//cocc: # of bubbles in this chain + for (k = bc->cc.ng.n - cocc; k < bc->cc.ng.n; k++) { + kv_resize(double, sc_l, clus_n((*bc), k)); + kv_resize(double, sc_r, clus_n((*bc), k)); + kv_resize(double, sc_m, clus_n((*bc), k)); + kv_resize(uint32_t, tmp, clus_n((*bc), k)); + // prt_bub(clus_a((*bc), k), clus_n((*bc), k), "-0-"); + reorder_bub(bc->mg->e, clus_a((*bc), k), clus_n((*bc), k), bc->lock, 3, 2, 4, 5, + sc_l.a, sc_r.a, sc_m.a, tmp.a); + // prt_bub(clus_a((*bc), k), clus_n((*bc), k), "-1-"); + } + for (k = iin; k < bc->cc.nn.n; k++) bc->lock[bc->cc.nn.a[k]] = 1;//reset + kv_pushp(uint64_t, bc->cc.ng, &p); *p = (uint64_t)-1; ///cluster + kv_push(uint32_t, bc->cc.nn, ((uint32_t)-1)); ///split, node id + } + } + + for (k = 0; k < a_n; k++) bc->lock[a[k]] = 0; + kv_destroy(sc_l); kv_destroy(sc_r); kv_destroy(sc_m); kv_destroy(tmp); + // fprintf(stderr, "[M::%s] a_n::%u, bc->cc.nn.n::%u, bc->cc.ng.n::%u, bbn::%u, bub_occ::%u, bc->bub->b_ug->u.n::%u\n", __func__, + // a_n, (uint32_t)bc->cc.nn.n, (uint32_t)bc->cc.ng.n, bbn, bub_occ, (uint32_t)bc->bub->b_ug->u.n); +} + + +void renew_mc_clus_t_adv(mc_clus_t *bc, uint32_t *a, uint32_t a_n) +{ + if(!bc) return; + // fprintf(stderr, "[M::%s] a_n::%u\n", __func__, a_n); + uint32_t k, i, *ba, bn, m, cocc, iin, /**bub_occ = 0,**/ bbn = 0, bid, bk, bl; + uint64_t *p; ma_utg_t *u = NULL; asg64_v *asn = bc->asn; + kvec_t(double) sc_l; kvec_t(double) sc_r; kvec_t(double) sc_m; kvec_t(uint32_t) tmp; + kv_init(sc_l); kv_init(sc_r); kv_init(sc_m); kv_init(tmp); + + bc->cc.ng.n = bc->cc.nn.n = 0; + memset(bc->lock, 0, sizeof((*(bc->lock)))*bc->n);///bc->n: number of all nodes + for (k = 0; k < a_n; k++) bc->lock[a[k]] = 1;///a_n: number of nodes within the cluster + + kv_resize(uint32_t, bc->cc.nn, a_n); + for (i = bid = bk = 0; i < bc->bub->b_ug->u.n; i++) { + u = &(bc->bub->b_ug->u.a[i]); + if(u->n == 0) continue; + // bub_occ += u->n; + // fprintf(stderr, "[M::%s] i::%u, u->n::%u\n", __func__, i, (uint32_t)u->n); + for (k = cocc = 0, iin = bc->cc.nn.n; k < u->n; k++, bid++) { + get_bubbles(bc->bub, u->a[k]>>33, NULL, NULL, &ba, &bn, NULL); + kv_pushp(uint64_t, bc->cc.ng, &p); bbn += bn; + *p = bc->cc.nn.n;///a bubble + for (m = 0; m < bn; m++) { + if(!(bc->lock[ba[m]>>1])) continue;///if the node of bubble is not at this cluster + kv_push(uint32_t, bc->cc.nn, (ba[m]>>1)); + bc->lock[ba[m]>>1] = 2; + } + if(asn) { + for (; bk < asn->n && (asn->a[bk]>>32) < bid; bk++); + for (; bk < asn->n && (asn->a[bk]>>32) == bid; bk++) { + if(!(bc->lock[((uint32_t)asn->a[bk])])) continue;///if the node of bubble is not at this cluster + kv_push(uint32_t, bc->cc.nn, ((uint32_t)asn->a[bk])); + bc->lock[((uint32_t)asn->a[bk])] = 2; + } + } + + if(bc->cc.nn.n <= (*p)) {///no node in this bubble + bc->cc.ng.n--; + continue; + } + *p <<= 32; *p |= (bc->cc.nn.n-((*p)>>32)); cocc++; + } + //split the chain if there is multipe bubbles + if(cocc > 0) {//cocc: # of bubbles in this chain + for (k = bc->cc.ng.n - cocc; k < bc->cc.ng.n; k++) { + kv_resize(double, sc_l, clus_n((*bc), k)); + kv_resize(double, sc_r, clus_n((*bc), k)); + kv_resize(double, sc_m, clus_n((*bc), k)); + kv_resize(uint32_t, tmp, clus_n((*bc), k)); + // prt_bub(clus_a((*bc), k), clus_n((*bc), k), "-0-"); + reorder_bub(bc->mg->e, clus_a((*bc), k), clus_n((*bc), k), bc->lock, 3, 2, 4, 5, + sc_l.a, sc_r.a, sc_m.a, tmp.a); + // prt_bub(clus_a((*bc), k), clus_n((*bc), k), "-1-"); + } + for (k = iin; k < bc->cc.nn.n; k++) bc->lock[bc->cc.nn.a[k]] = 1;//reset + kv_pushp(uint64_t, bc->cc.ng, &p); *p = (uint64_t)-1; ///cluster + kv_push(uint32_t, bc->cc.nn, ((uint32_t)-1)); ///split, node id + } + } + + if(asn) { + for (bl = bk, bk = bk + 1; bk <= asn->n; bk++) { + if(bk == asn->n || (asn->a[bk]>>32) != (asn->a[bl]>>32)) { + cocc = 0; iin = bc->cc.nn.n; + kv_pushp(uint64_t, bc->cc.ng, &p); bbn += bn; + *p = bc->cc.nn.n;///a bubble + for (m = bl; m < bk; m++) { + if(!(bc->lock[((uint32_t)asn->a[m])])) continue;///if the node of bubble is not at this cluster + kv_push(uint32_t, bc->cc.nn, ((uint32_t)asn->a[m])); + bc->lock[((uint32_t)asn->a[m])] = 2; + } + if(bc->cc.nn.n <= (*p)) {///no node in this bubble + bc->cc.ng.n--; + bl = bk; + continue; + } + *p <<= 32; *p |= (bc->cc.nn.n-((*p)>>32)); cocc++; + if(cocc > 0) {//cocc: # of bubbles in this chain + for (k = bc->cc.ng.n - cocc; k < bc->cc.ng.n; k++) { + kv_resize(double, sc_l, clus_n((*bc), k)); + kv_resize(double, sc_r, clus_n((*bc), k)); + kv_resize(double, sc_m, clus_n((*bc), k)); + kv_resize(uint32_t, tmp, clus_n((*bc), k)); + // prt_bub(clus_a((*bc), k), clus_n((*bc), k), "-0-"); + reorder_bub(bc->mg->e, clus_a((*bc), k), clus_n((*bc), k), bc->lock, 3, 2, 4, 5, + sc_l.a, sc_r.a, sc_m.a, tmp.a); + // prt_bub(clus_a((*bc), k), clus_n((*bc), k), "-1-"); + } + for (k = iin; k < bc->cc.nn.n; k++) bc->lock[bc->cc.nn.a[k]] = 1;//reset + kv_pushp(uint64_t, bc->cc.ng, &p); *p = (uint64_t)-1; ///cluster + kv_push(uint32_t, bc->cc.nn, ((uint32_t)-1)); ///split, node id + } + + bl = bk; + } + } + } + ///need enable it later + kv_resize(uint32_t, tmp, bc->cc.nn.n); + kv_resize(uint64_t, bc->cc.ng, bc->cc.ng.n+bc->bub->ug->g->n_seq); + layout_mc_clus_t(bc->mg->e, bc->cc.nn.a, bc->cc.nn.n, &(bc->sg), tmp.a, bc->cc.ng.a+bc->cc.ng.n, bc->bub->ug, 0.199999, 0.800001, 4); + + for (k = 0; k < a_n; k++) bc->lock[a[k]] = 0; + kv_destroy(sc_l); kv_destroy(sc_r); kv_destroy(sc_m); kv_destroy(tmp); + // fprintf(stderr, "[M::%s] a_n::%u, bc->cc.nn.n::%u, bc->cc.ng.n::%u, bbn::%u, bub_occ::%u, bc->bub->b_ug->u.n::%u\n", __func__, + // a_n, (uint32_t)bc->cc.nn.n, (uint32_t)bc->cc.ng.n, bbn, bub_occ, (uint32_t)bc->bub->b_ug->u.n); +} + + +void clean_clus_flip_aux(clus_flip_aux *z) +{ + z->w = -1; z->occ = z->off = (uint32_t)-1; + memset(z->vis.a, 0, sizeof(*(z->vis.a))*z->vis.n); +} + +#define is_set_bits_p(v, i) (((v).a[((i)>>3)]>>(i&7))&1) +#define set_bits_p(v, i) (((v).a[((i)>>3)])|=(((uint8_t)1)<<(i&7))); + +t_w_t clus_weight(mc_svaux_t *b_aux, mc_match_t *ma, bits_p *vis, uint32_t uid) +{ + mc_edge_t *o = NULL; + uint32_t n, i, t; + t_w_t w = ((t_w_t)(b_aux->s[uid])) * (b_aux->z[uid].z[0] - b_aux->z[uid].z[1]) * 2; + t_w_t w_off = 0; + o = pt_a(*ma, uid); + n = pt_n(*ma, uid); + for (i = 0; i < n; ++i) { + t = ma_y(o[i]); + if(!(is_set_bits_p((*vis), t))) continue; + // if(vis[t] == 0) continue; + if(t == uid) continue; + w_off += (b_aux->s[uid]*b_aux->s[t]*o[i].w); + } + return w - (w_off*4);//2 for self; 4 for both directions +} + +void cal_clus_sc0(mc_match_t *ma, mc_svaux_t *b_aux, mc_clus_t* bc, uint8_t *lock, uint8_t lock_max, +uint32_t *a, uint32_t a_n, uint32_t id, clus_flip_aux *r, uint32_t tid) +{ + uint32_t i, max_occ = (uint32_t)-1;//, len, mm0 = (uint32_t)-1, mm1 = 0; + bits_p *vis = &(r->vis); t_w_t w = 0, max_w = -1; + + memset(vis->a, 0, sizeof(*(vis->a))*vis->n); + // if(bc->dbg) { + // if(a[id] == 487 || a[id] == 47) { + // fprintf(stderr, "[M::%s::] id::%u, a[id]::%u, s::%d\n", __func__, id, a[id], b_aux->s[a[id]]); + // } + // } + for (i = id; i < a_n && a[i] != (uint32_t)-1; i++) { + if(lock[a[i]] >= lock_max) continue; + if(is_set_bits_p((*vis), a[i])) continue; + w += clus_weight(b_aux, ma, vis, a[i]); + // if(bc->dbg) { + // if(a[id] == 487 || a[id] == 47) { + // fprintf(stderr, "[M::%s::id->%u] a[%u]::%u, s::%d, lock::%u, lock_max::%u, is_set::%u, w::%f\n", + // __func__, id, i, a[i], b_aux->s[a[i]], lock[a[i]], lock_max, is_set_bits_p((*vis), a[i]), w); + // } + // } + set_bits_p((*vis), a[i]); + // mm1 = a[i]; if(a[i] < mm0) mm0 = a[i]; + ///update max_w + if(max_w < w) { + max_w = w; max_occ = i + 1 - id; + } + } + // if(mm0 != (uint32_t)-1 && mm1 != (uint32_t)-1) { + // len = MIN(((mm1>>3)+1), vis->n) - (mm0>>3); + // memset(vis->a+(mm0>>3), 0, sizeof(*(vis->a))*len); + // } + for (i = id; i < a_n && a[i] != (uint32_t)-1; i++) vis->a[a[i]>>3] = 0;///reset + if(max_w <= 0.000001 || max_occ == (uint32_t)-1) return; + if((max_w > r->w) || (max_w == r->w && id < r->off)) { + r->w = max_w; r->off = id; r->occ = max_occ; + } + // if(bc->dbg) { + // if(a[id] == 487 || a[id] == 47) { + // fprintf(stderr, "[M::%s::] id::%u, a[id]::%u, w::%f, off::%u, occ::%u\n", __func__, id, a[id], r->w, r->off, r->occ); + // } + // } +} + +static void worker_cal_clus_sc(void *data, long i, int tid) // callback for kt_for() +{ + mc_clus_t *bc = (mc_clus_t *)data; + uint32_t *a = bc->cc.nn.a, a_n = bc->cc.nn.n; + if(a[i] == (uint32_t)-1) return; + cal_clus_sc0(bc->mg->e, bc->baux, bc, bc->lock, bc->lock_max, a, a_n, i, &(bc->aux[tid]), tid); +} + + +uint32_t gen_best_clus(mc_clus_t *bc, uint32_t *off, uint32_t *occ, double *rw) +{ + uint32_t i; (*off) = (*occ) = (uint32_t)-1; (*rw) = -1; + for (i = 0; i < bc->n_thread; i++) clean_clus_flip_aux(&(bc->aux[i])); + + kt_for(bc->n_thread, worker_cal_clus_sc, bc, bc->cc.nn.n); + + for (i = 0; i < bc->n_thread; i++) { + if(bc->aux[i].off == (uint32_t)-1) continue; + if(bc->aux[i].w < 0) continue; + + if((bc->aux[i].w > (*rw)) || (bc->aux[i].w == (*rw) && bc->aux[i].off < (*off))) { + (*off) = bc->aux[i].off; (*occ) = bc->aux[i].occ; (*rw) = bc->aux[i].w; + } + } + if((*off) != (uint32_t)-1) return 1; + return 0; +} + +double flip_chain(const mc_match_t *ma, mc_svaux_t *b, uint32_t *a, uint32_t a_n, uint32_t off, uint32_t occ, +bits_p *vis, uint8_t *lock, uint8_t lock_max) +{ + uint32_t k, kn = off + occ; + for (k = off; k < kn; k++) { + vis->a[a[k]>>3] = 0; + // if(occ == 4 && a[off] == 11279) dbg = 1; + } + for (k = off; k < kn; k++) { + if(lock[a[k]] >= lock_max) continue; + if(is_set_bits_p((*vis), a[k])) continue; + set_bits_p((*vis), a[k]); lock[a[k]]++; + // if(dbg) fprintf(stderr, "[M::%s::] a[%u]::%u, s::%d\n", __func__, k, a[k], b->s[a[k]]); + mc_set_spin(ma, b, a[k], -b->s[a[k]]); + } + return mc_score(ma, b); +} + + +void test_flip_sc(const mc_match_t *ma, mc_svaux_t *b, uint32_t *a, uint32_t a_n, bits_p *vis) +{ + mc_edge_t *o = NULL; t_w_t w = 0, w_off = 0; + t_w_t sc_new = mc_score(ma, b), sc; + uint32_t n, i, t, k, uid, z; + for (k = 0; k < a_n; k++) mc_set_spin(ma, b, a[k], -b->s[a[k]]); + for (k = 0; k < a_n; k++) { + uid = a[k]; + fprintf(stderr, "+[M::%s::] uid::%u, z[0]::%f, z[1]::%f\n", __func__, uid, b->z[uid].z[0], b->z[uid].z[1]); + w += ((t_w_t)(b->s[uid])) * (b->z[uid].z[0] - b->z[uid].z[1]) * 2; + o = pt_a(*ma, uid); + n = pt_n(*ma, uid); + for (i = 0; i < n; ++i) { + t = ma_y(o[i]); + for (z = 0; z < k; z++) { + if(a[z] == t) break; + } + if(z >= k) continue; + // if(!(is_set_bits_p((*vis), t))) continue; + // if(vis[t] == 0) continue; + if(t == uid) continue; + fprintf(stderr, "+[M::%s::] uid::%u, t::%u, w::%f\n", __func__, uid, t, o[i].w); + w_off += (b->s[uid]*b->s[t]*o[i].w); + } + } + w -= (w_off*4); + sc = mc_score(ma, b); + fprintf(stderr, "+[M::%s::] sc::%f, sc_new::%f, w::%f\n", __func__, sc, sc_new, w); + + w = w_off = 0; memset(vis->a, 0, sizeof(*(vis->a))*vis->n); + for (k = 0; k < a_n; k++) { + uid = a[k]; + fprintf(stderr, "-[M::%s::] uid::%u, z[0]::%f, z[1]::%f\n", __func__, uid, b->z[uid].z[0], b->z[uid].z[1]); + w += ((t_w_t)(b->s[uid])) * (b->z[uid].z[0] - b->z[uid].z[1]) * 2; + o = pt_a(*ma, uid); + n = pt_n(*ma, uid); + for (i = 0; i < n; ++i) { + t = ma_y(o[i]); + // for (z = 0; z < k; z++) { + // if(a[z] == t) break; + // } + // if(z >= k) continue; + if(!(is_set_bits_p((*vis), t))) continue; + // if(vis[t] == 0) continue; + if(t == uid) continue; + fprintf(stderr, "-[M::%s::] uid::%u, t::%u, w::%f\n", __func__, uid, t, o[i].w); + w_off += (b->s[uid]*b->s[t]*o[i].w); + } + set_bits_p((*vis), uid); + } + w -= (w_off*4); + sc = mc_score(ma, b); + fprintf(stderr, "-[M::%s::] sc::%f, sc_new::%f, w::%f\n", __func__, sc, sc_new, w); +} + +t_w_t mc_solve_clus(mc_clus_t *bc) +{ + uint32_t off, occ/**, r = 0**/; double rw, sc, sc_opt = mc_score(bc->mg->e, bc->baux); + memset(bc->lock, 0, bc->n*sizeof(*(bc->lock))); + while (gen_best_clus(bc, &off, &occ, &rw)) { + sc = flip_chain(bc->mg->e, bc->baux, bc->cc.nn.a, bc->cc.nn.n, off, occ, &(bc->aux[0].vis), bc->lock, bc->lock_max); + // if(r%10000) { + // fprintf(stderr, "[M::%s::] rw::%f, sc_opt::%f, sc::%f, off::%u, occ::%u, r::%u\n", + // __func__, rw, sc_opt, sc, off, occ, r); + // } + if(sc < sc_opt) { + fprintf(stderr, "\nwrong::[M::%s::] rw::%f, sc_opt::%f, sc::%f, off::%u, occ::%u\n", + __func__, rw, sc_opt, sc, off, occ); + // if(occ == 2) { + // uint32_t k; + // for (k = off; k < off + occ; k++) { + // fprintf(stderr, "[M::%s::] a[%u]::%u, s::%d\n", __func__, k, bc->cc.nn.a[k], bc->baux->s[bc->cc.nn.a[k]]); + // } + // test_flip_sc(bc->mg->e, bc->baux, bc->cc.nn.a+off, occ, &(bc->aux[0].vis)); + // } + } + sc_opt = sc; //r++; + } + return sc_opt; +} + +t_w_t mc_clus_cc(mc_clus_t *bc) +{ + // fprintf(stderr, "+[M::%s::]\n", __func__); + // double index_time = yak_realtime(); + // uint32_t r = 1; + t_w_t sc_opt, sc; + // fprintf(stderr, "-[M::%s::]\n", __func__); + mc_reset_z(bc->mg->e, bc->baux); + // fprintf(stderr, "*[M::%s::]\n", __func__); + sc_opt = mc_score(bc->mg->e, bc->baux); + // fprintf(stderr, "[M::%s::] sc_opt: %f\n", __func__, sc_opt); + while (1) { + sc = mc_solve_clus(bc); + // fprintf(stderr, "[M::%s::# round: %u] sc_opt: %f, sc: %f\n", __func__, r, sc_opt, sc); + if(sc <= (sc_opt+0.0000001)) break; + sc_opt = sc; //r++; + } + // fprintf(stderr, "[M::%s::%.3f] ==> round %u\n", __func__, yak_realtime()-index_time, r); + return sc; +} + +uint32_t mc_solve_cc_adv(const mc_opt_t *opt, const mc_g_t *mg, mc_svaux_t *b, uint32_t cc_off, uint32_t cc_size, mc_clus_t *bc) +{ + uint32_t j, k, n_iter = 0, flush = opt->max_iter * 50, n_skip, n_skip_flush = opt->n_perturb/16; + t_w_t sc_opt = -(1<<30), sc;///problem-w + b->cc_off = cc_off, b->cc_size = cc_size; + if (b->cc_size < 2) return 0; + sc_opt = mc_init_spin(mg->e, b); + // print_sc(opt, mg, b, sc_opt, n_iter); + if (b->cc_size == 2) return 0; + for (j = 0; j < b->cc_size; ++j) {///backup s and z in s_opt and z_opt + b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; ///hap status of each unitig + b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; ///z[0]: positive weight; z[1]: positive weight + } + // renew_mc_clus_t(bc, b->cc_node, b->cc_size); + renew_mc_clus_t_adv(bc, b->cc_node, b->cc_size); + // fprintf(stderr, "\ncc_size: %u, cc_off: %u\n", b->cc_size, b->cc_off); + // print_sc(opt, mg->e, b, sc_opt, n_iter); + sc = mc_optimize_local(opt, mg->e, b, &n_iter); + if (sc > sc_opt) { + for (j = 0; j < b->cc_size; ++j) { + b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; + b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; + } + sc_opt = sc; + } else { + for (j = 0; j < b->cc_size; ++j) { + b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; + b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; + } + } + // print_mc_node(mg->e, b, 36880); + // print_sc(opt, mg, b, sc_opt, n_iter); + // mc_reset_z_debug(mg->e, b); + // print_sc(opt, mg->e, b, sc_opt, n_iter); + // fprintf(stderr, "\ncc_size: %u, cc_off: %u\n", b->cc_size, b->cc_off); + + if(bc) { + sc = mc_clus_cc(bc); + if (sc > sc_opt) { + for (j = 0; j < b->cc_size; ++j) { + b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; + b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; + } + sc_opt = sc; + } else { + for (j = 0; j < b->cc_size; ++j) { + b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; + b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; + } + } + } + + for (k = n_skip = 0; k < (uint32_t)opt->n_perturb; ++k) { + if (k&1) mc_perturb(opt, mg->e, b); + else mc_perturb_node(opt, mg->e, b, 3); + sc = mc_optimize_local(opt, mg->e, b, &n_iter); + // if((k%256) == 0) fprintf(stderr, "(%u) sc_opt::%f, sc::%f, flush::%u, n_iter::%u\n", k, sc_opt, sc, flush, n_iter); + if (sc > sc_opt) { + for (j = 0; j < b->cc_size; ++j) { + b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; + b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; + } + sc_opt = sc; n_skip = 0; + // print_sc(opt, mg, b, sc_opt, n_iter); + } else { + for (j = 0; j < b->cc_size; ++j) { + b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; + b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; + } + n_skip++; + } + if(n_skip >= n_skip_flush && bc) { + sc = mc_clus_cc(bc); + if (sc > sc_opt) { + for (j = 0; j < b->cc_size; ++j) { + b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; + b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; + } + sc_opt = sc; + } else { + for (j = 0; j < b->cc_size; ++j) { + b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; + b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; + } + } + n_skip = 0; + } + + if((n_iter%flush) == 0) { + mc_reset_z(mg->e, b); + sc = mc_score(mg->e, b); + + for (j = 0; j < b->cc_size; ++j) { + b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; + } + sc_opt = sc; + } + } + if(bc) { + sc = mc_clus_cc(bc); + if (sc > sc_opt) { + for (j = 0; j < b->cc_size; ++j) { + b->s_opt[b->cc_node[j]] = b->s[b->cc_node[j]]; + b->z_opt[b->cc_node[j]] = b->z[b->cc_node[j]]; + } + sc_opt = sc; + } else { + for (j = 0; j < b->cc_size; ++j) { + b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; + b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; + } + } + } + + // if(bc) { + // bc->dbg = 1; + // mc_clus_cc(bc); + // bc->dbg = 0; + // } + + for (j = 0; j < b->cc_size; ++j) + { + b->s[b->cc_node[j]] = b->s_opt[b->cc_node[j]]; + b->z[b->cc_node[j]] = b->z_opt[b->cc_node[j]]; + } + // exit(1); + return n_iter; +} + + +void reset_mb_g_t_z(mb_g_t *mbg); +uint32_t mb_solve_cc(const mc_opt_t *opt, mb_g_t *mbg, mb_svaux_t *b, uint32_t cc_off, uint32_t cc_size) +{ + uint32_t j, k, n_iter = 0, flush = opt->max_iter * 50; + t_w_t sc_opt = -(1<<30), sc;///problem-w + b->cc_off = cc_off, b->cc_size = cc_size; + if (b->cc_size <= 2) return 0; + + for (j = 0; j < b->cc_size; ++j) {///how many nodes + k = (uint32_t)mbg->e->cc[b->cc_off + j];///node id + b->cc_node[j] = k; + } + + sc_opt = mb_score(mbg, b); + for (j = 0; j < b->cc_size; ++j) {///backup s and z in s_opt and z_opt + memcpy(b->u_opt[b->cc_node[j]].s, b->u[b->cc_node[j]].s, 2*sizeof(mc_node_t)); + memcpy(b->u_opt[b->cc_node[j]].z, b->u[b->cc_node[j]].z, 4*sizeof(t_w_t)); + } + + // print_sc(opt, mg->e, b, sc_opt, n_iter); + sc = mb_optimize_local(opt, mbg, b, &n_iter); + if (sc > sc_opt) { + for (j = 0; j < b->cc_size; ++j) { + memcpy(b->u_opt[b->cc_node[j]].s, b->u[b->cc_node[j]].s, 2*sizeof(mc_node_t)); + memcpy(b->u_opt[b->cc_node[j]].z, b->u[b->cc_node[j]].z, 4*sizeof(t_w_t)); + } + sc_opt = sc; + } else { + for (j = 0; j < b->cc_size; ++j) { + memcpy(b->u[b->cc_node[j]].s, b->u_opt[b->cc_node[j]].s, 2*sizeof(mc_node_t)); + memcpy(b->u[b->cc_node[j]].z, b->u_opt[b->cc_node[j]].z, 4*sizeof(t_w_t)); + } + } + // mc_reset_z_debug(mg->e, b); + // print_sc(opt, mg->e, b, sc_opt, n_iter); + // fprintf(stderr, "\ncc_size: %u, cc_off: %u\n", b->cc_size, b->cc_off); + for (k = 0; k < (uint32_t)opt->n_perturb; ++k) { + if (k&1) mb_perturb(opt, mbg, b); + else mb_perturb_node(opt, mbg, b, 3); + sc = mb_optimize_local(opt, mbg, b, &n_iter); + // fprintf(stderr, "(%u) sc_opt: %f, sc: %f\n", k, sc_opt, sc); + if (sc > sc_opt) { + for (j = 0; j < b->cc_size; ++j) { + memcpy(b->u_opt[b->cc_node[j]].s, b->u[b->cc_node[j]].s, 2*sizeof(mc_node_t)); + memcpy(b->u_opt[b->cc_node[j]].z, b->u[b->cc_node[j]].z, 4*sizeof(t_w_t)); + } + sc_opt = sc; + } else { + for (j = 0; j < b->cc_size; ++j) { + memcpy(b->u[b->cc_node[j]].s, b->u_opt[b->cc_node[j]].s, 2*sizeof(mc_node_t)); + memcpy(b->u[b->cc_node[j]].z, b->u_opt[b->cc_node[j]].z, 4*sizeof(t_w_t)); + } + } + + if((n_iter%flush) == 0) + { + reset_mb_g_t_z(mbg); + sc = mb_score(mbg, b); + + for (j = 0; j < b->cc_size; ++j) { + memcpy(b->u_opt[b->cc_node[j]].z, b->u[b->cc_node[j]].z, 4*sizeof(t_w_t)); + } + sc_opt = sc; + } + + // print_sc(opt, mg->e, b, sc_opt, n_iter); + } + for (j = 0; j < b->cc_size; ++j) + { + memcpy(b->u[b->cc_node[j]].s, b->u_opt[b->cc_node[j]].s, 2*sizeof(mc_node_t)); + memcpy(b->u[b->cc_node[j]].z, b->u_opt[b->cc_node[j]].z, 4*sizeof(t_w_t)); + } + + return n_iter; +} + +void reset_mb_g_t_z(mb_g_t *mbg) +{ + uint32_t k; + mb_match_t *ma = mbg->e; + for (k = 0; k < ma->n_seq; ++k) ///each block + { + uint32_t o = ma->idx.a[k] >> 32; + uint32_t j, n = (uint32_t)ma->idx.a[k]; + mbg->u->u.a[k].z[0] = mbg->u->u.a[k].z[1] = 0; + mbg->u->u.a[k].z[2] = mbg->u->u.a[k].z[3] = 0; + for (j = 0; j < n; ++j) { + const mb_edge_t *e = &ma->ma.a[o + j]; + uint32_t t = ma_y(*e); + + ///a[0]->b[0] + if(mbg->u->u.a[t].s[0] > 0) mbg->u->u.a[k].z[0] += e->w[0]; + else if(mbg->u->u.a[t].s[0] < 0) mbg->u->u.a[k].z[1] += e->w[0]; + + ///a[0]->b[1] + if(mbg->u->u.a[t].s[1] > 0) mbg->u->u.a[k].z[0] += e->w[1]; + else if(mbg->u->u.a[t].s[1] < 0) mbg->u->u.a[k].z[1] += e->w[1]; + + ///a[1]->b[0] + if(mbg->u->u.a[t].s[0] > 0) mbg->u->u.a[k].z[2] += e->w[2]; + else if(mbg->u->u.a[t].s[0] < 0) mbg->u->u.a[k].z[3] += e->w[2]; + + ///a[1]->b[1] + if(mbg->u->u.a[t].s[1] > 0) mbg->u->u.a[k].z[2] += e->w[3]; + else if(mbg->u->u.a[t].s[1] < 0) mbg->u->u.a[k].z[3] += e->w[3]; + } + } +} + +void debug_mbg(mb_g_t *mbg, mc_g_t *mg, mc_svaux_t *b) +{ + uint32_t i, k, a_n[2], *a[2], qn, found; + int8_t s[2]; + for (i = 0; i < mbg->u->u.n; i++)///each block + { + fprintf(stderr, "i: %u, mbg->u->u.n: %u\n", i, (uint32_t)mbg->u->u.n); + decode_mb_node(mbg, i, &(a[0]), &(a_n[0]), &(s[0]), &(a[1]), &(a_n[1]), &(s[1])); + + found = 0; + for (k = 0; k < a_n[0]; k++) + { + qn = a[0][k]; + if(b->s[qn] == s[0]) found = 1; + if(b->s[qn] == 0) continue; + if(b->s[qn] != s[0]) fprintf(stderr, "ERROR-0-::%s\n", __func__); + } + if(found == 0) fprintf(stderr, "ERROR-0-*::%s\n", __func__); + + found = 0; + for (k = 0; k < a_n[1]; k++) + { + qn = a[1][k]; + if(b->s[qn] == s[1]) found = 1; + if(b->s[qn] == 0) continue; + if(b->s[qn] != s[1]) fprintf(stderr, "ERROR-1-::%s\n", __func__); + } + if(found == 0 && a_n[1] > 0) fprintf(stderr, "ERROR-1-*::%s\n", __func__); + } + + // t_w_t mcw = mc_score_all(mg->e, b); + // t_w_t mbw = 0; + // mb_match_t *ma = mbg->e; + // for (k = 0; k < ma->n_seq; ++k) { + // ///a[0] + // mbw += -(t_w_t)(mbg->u->u.a[k].s[0]) * (mbg->u->u.a[k].z[0] - mbg->u->u.a[k].z[1]); + // ///a[1] + // mbw += -(t_w_t)(mbg->u->u.a[k].s[1]) * (mbg->u->u.a[k].z[2] - mbg->u->u.a[k].z[3]); + // } +} + +void mc_init_spin_all(const mc_opt_t *opt, mc_g_t *mg, mb_g_t *mbg, mc_svaux_t *b) +{ + uint32_t st, i, k, m, a_n[2], *a[2], qn; + for (st = 0, i = 1; i <= mg->e->n_seq; ++i) { + if (i == mg->e->n_seq || mg->e->cc[st]>>32 != mg->e->cc[i]>>32) { + b->cc_off = st, b->cc_size = i - st; + if (b->cc_size >= 2) + { + mc_init_spin(mg->e, b); + } + st = i; + } + } + + if(!mbg) return; + // memcpy(b->s_opt, b->s, sizeof(int8_t)*mg->e->n_seq); + + ///adjust by block + kvec_t(uint32_t) s; kv_init(s); + uint32_t ws, we, n_flip; + uint8_t *vis = NULL; CALLOC(vis, mg->e->n_seq); + t_w_t w = 0, max_w = 0; + for (i = 0; i < mbg->u->u.n; i++)///each block + { + decode_mb_node(mbg, i, &(a[0]), &(a_n[0]), NULL, &(a[1]), &(a_n[1]), NULL); + ///if(a_n[0] == 0 || a_n[1] == 0) continue; + if(a_n[0] + a_n[1] <= 1) continue; + s.n = 0; + for (k = 0; k < a_n[0]; k++) + { + qn = a[0][k]; + if(b->s[qn] == 0) continue; + // qn <<= 1; + if(b->s[qn] < 0) qn += ((uint32_t)1<<31); + kv_push(uint32_t, s, qn); + } + + for (k = 0; k < a_n[1]; k++) + { + qn = a[1][k]; + if(b->s[qn] == 0) continue; + // qn <<= 1; qn++; + if(b->s[qn] > 0) qn += ((uint32_t)1<<31); + kv_push(uint32_t, s, qn); + } + + if(s.n == 0) continue; + radix_sort_mc32(s.a, s.a + s.n); + + ws = we = (uint32_t)-1; n_flip = 0; + for (st = 0, k = 1; k <= s.n; k++) + { + if(k == s.n || (s.a[k]>>31) != (s.a[st]>>31)) + { + w = 0; + for (m = st; m < k; m++) vis[(s.a[m]<<1)>>1] = 1; + for (m = st; m < k; m++) w += incre_weight(b, mg->e, vis, (s.a[m]<<1)>>1); + for (m = st; m < k; m++) vis[(s.a[m]<<1)>>1] = 0; + if(ws == (uint32_t)-1 || max_w < w) max_w = w, ws = st, we = k; + st = k; + n_flip++; + } + } + + if(n_flip <= 1) continue; + + /*******************************for debug************************************/ + // t_w_t sc_opt = mc_score_all(mg->e, b); + /*******************************for debug************************************/ + for (m = ws; m < we; m++) mc_set_spin(mg->e, b, (s.a[m]<<1)>>1, -b->s[(s.a[m]<<1)>>1]); + /*******************************for debug************************************/ + // t_w_t sc_cur = mc_score_all(mg->e, b); + // if(sc_cur - sc_opt != max_w*2) + // { + // fprintf(stderr, "ERROR-0-::%s\n", __func__); + // // fprintf(stderr, "sc_opt: %ld, sc_cur: %ld, max_w: %ld\n", sc_opt, sc_cur, max_w); + // fprintf(stderr, "sc_opt: %f, sc_cur: %f, max_w: %f\n", sc_opt, sc_cur, max_w); + // } + /*******************************for debug************************************/ + } + kv_destroy(s); free(vis); + + for (i = 0; i < mbg->u->u.n; i++)///each block + { + decode_mb_node(mbg, i, &(a[0]), &(a_n[0]), NULL, &(a[1]), &(a_n[1]), NULL); + mbg->u->u.a[i].s[0] = mbg->u->u.a[i].s[1] = 0; + mbg->u->u.a[i].z[0] = mbg->u->u.a[i].z[1] = 0; + mbg->u->u.a[i].z[2] = mbg->u->u.a[i].z[3] = 0; + for (k = 0; k < a_n[0]; k++) + { + qn = a[0][k]; + if(b->s[qn] == 0) continue; + mbg->u->u.a[i].s[0] = b->s[qn]; + break; + } + + for (k = 0; k < a_n[1]; k++) + { + qn = a[1][k]; + if(b->s[qn] == 0) continue; + mbg->u->u.a[i].s[1] = b->s[qn]; + break; + } + } + + reset_mb_g_t_z(mbg); + + /*******************************for debug************************************/ + // debug_mbg(mbg, mg, b); + /*******************************for debug************************************/ + // memcpy(b->s, b->s_opt, sizeof(int8_t)*mg->e->n_seq); +} + + +uint64_t *mb_g_cc_core(mb_match_t *ma) +{ + uint32_t i, x, y, *flag; + uint64_t *group; + mb_edge_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 = ma_y(o[j]); + 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_mc64(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 mb_g_cc(mb_g_t *mbg) +{ + mbg->e->cc = mb_g_cc_core(mbg->e); +} + +void mc_set_by_mbg(mc_g_t *mg, mb_g_t *mbg) +{ + // t_w_t z0 = mc_score_all_advance(mg->e, mg->s.a); + // t_w_t z1 = mb_score_all_advance(mg->e, mbg); + // if(z0 >= z1) return; + uint32_t i, k, qn, *a[2], a_n[2]; + int8_t s[2]; + for (i = 0; i < mbg->u->u.n; i++) + { + decode_mb_node(mbg, i, &(a[0]), &(a_n[0]), &(s[0]), &(a[1]), &(a_n[1]), &(s[1])); + for (k = 0; k < a_n[0]; k++) + { + qn = a[0][k]; + if(mg->s.a[qn] == 0) continue; + mg->s.a[qn] = s[0]; + } + + for (k = 0; k < a_n[1]; k++) + { + qn = a[1][k]; + if(mg->s.a[qn] == 0) continue; + mg->s.a[qn] = s[1]; + } + } +} + + +void debug_mb_solve_core(mb_g_t *mbg) +{ + uint32_t i; + for (i = 0; i < mbg->u->u.n; i++) + { + debug_mb_z(mbg, i); + } +} + +void print_mb_g_blcok(mb_g_t *mbg) +{ + uint32_t i, k, a_n[2], *a[2]; + for (i = 0; i < mbg->u->u.n; i++)///each block + { + decode_mb_node(mbg, i, &(a[0]), &(a_n[0]), NULL, &(a[1]), &(a_n[1]), NULL); + { + if(a_n[0] + a_n[1] <= 1) continue; + fprintf(stderr, "\nB0-%s\n", a_n[0]>1?"mul":"single"); + for (k = 0; k < a_n[0]; k++) + { + fprintf(stderr,"s-utg%.6ul\n", a[0][k]+1); + } + + fprintf(stderr, "B1-%s\n", a_n[0]>1?"mul":"single"); + for (k = 0; k < a_n[1]; k++) + { + fprintf(stderr,"d-utg%.6ul\n", a[1][k]+1); + } + } + } +} + + + +void mb_solve_core(mc_opt_t *opt, mc_g_t *mg, kv_u_trans_t *ref, uint32_t is_sys) +{ + if(!ref) return; + double index_time = yak_realtime(); + uint32_t st, i; + mb_g_t *mbg = init_mb_g_t(mg->e, ref, is_sys); + mb_svaux_t *bb; + /**************************init**************************/ + if(VERBOSE_CUT) + { + fprintf(stderr, "\n\n\n\n\n*************beg-[M::%s::score->%f] ==> Partition\n", __func__, mc_score_all_advance(mg->e, mg->s.a)); + } + + mc_svaux_t *b; + mc_g_cc(mg->e); + b = mc_svaux_init(mg, opt->seed); + mc_init_spin_all(opt, mg, mbg, b); + mc_svaux_destroy(b); + free(mg->e->cc); + mg->e->cc = NULL; + /**************************init**************************/ + mb_g_cc(mbg); + bb = mb_svaux_init(mbg, opt->seed); + + if(VERBOSE_CUT) + { + fprintf(stderr, "*********before-[M::%s::mc_score->%f] ==> Partition\n", __func__, mc_score_all_advance(mg->e, mg->s.a)); + fprintf(stderr, "*********before-[M::%s::mb_score->%f] ==> Partition\n", __func__, mb_score_all_advance(mg->e, mbg)); + /*******************************for debug************************************/ + // print_mb_g_blcok(mbg); + /*******************************for debug************************************/ + } + + + opt->n_perturb = opt->n_b_perturb; + for (st = 0, i = 1; i <= mbg->e->n_seq; ++i) { + if (i == mbg->e->n_seq || mbg->e->cc[st]>>32 != mbg->e->cc[i]>>32) { + mb_solve_cc(opt, mbg, bb, st, i - st); + st = i; + } + } + opt->n_perturb = opt->n_s_perturb - opt->n_b_perturb; + + mc_set_by_mbg(mg, mbg); + if(VERBOSE_CUT) + { + /*******************************for debug************************************/ + // debug_mb_solve_core(mbg); + /*******************************for debug************************************/ + fprintf(stderr, "##############end-[M::%s::score->%f] ==> Partition\n", __func__, mc_score_all_advance(mg->e, mg->s.a)); + } + destory_mb_g_t(&mbg); + mb_svaux_destroy(bb); + fprintf(stderr, "[M::%s::%.3f] ==> Partition\n", __func__, yak_realtime()-index_time); +} + + +void mc_solve_core(const mc_opt_t *opt, mc_g_t *mg, bubble_type* bub) +{ + double index_time = yak_realtime(); + uint32_t st, i; + mc_svaux_t *b; + mc_bp_t *bp = NULL; + mc_g_cc(mg->e); + b = mc_svaux_init(mg, opt->seed); + if(bub) bp = mc_bp_t_init(mg->e, b, bub, asm_opt.thread_num); + /*******************************for debug************************************/ + if(bp) mc_init_spin_all(opt, mg, NULL, b); + if(bp) mc_solve_bp(bp); + /*******************************for debug************************************/ + if(VERBOSE_CUT) + { + fprintf(stderr, "\n\n\n\n\n*************beg-[M::%s::score->%f] ==> Partition\n", __func__, mc_score_all_advance(mg->e, mg->s.a)); + } + + for (st = 0, i = 1; i <= mg->e->n_seq; ++i) { + if (i == mg->e->n_seq || mg->e->cc[st]>>32 != mg->e->cc[i]>>32) { + mc_solve_cc(opt, mg, b, st, i - st); + st = i; + } + } + + if(VERBOSE_CUT) + { + fprintf(stderr, "##############end-[---M::%s::score->%f] ==> Partition\n", __func__, mc_score_all(mg->e, b)); + mc_status_all(mg->e, mg->s.a); + } + + + if(bp) mc_solve_bp(bp); + ///mc_write_info(g, b); + mc_svaux_destroy(b); + if(bp) destroy_mc_bp_t(&bp); + fprintf(stderr, "[M::%s::%.3f] ==> Partition\n", __func__, yak_realtime()-index_time); +} + +mc_clus_t *init_mc_clus_t(const mc_opt_t *opt, mc_g_t *mg, bubble_type* bub, uint32_t n_thread, mc_svaux_t *b, uint32_t flp_max) +{ + if((!bub)) return NULL; + mc_clus_t *p; CALLOC(p, 1); + p->bub = bub; p->opt = opt; p->mg = mg; p->n = bub->ug->g->n_seq; + CALLOC(p->lock, p->n); + if(n_thread > 64) {n_thread = 64;} p->n_thread = n_thread; + CALLOC(p->aux, p->n_thread); + uint32_t k, ss = (p->n>>3)+(!!(p->n&7)); + for (k = 0; k < p->n_thread; k++) { + kv_resize(uint8_t, p->aux[k].vis, ss); p->aux[k].vis.n = ss; + } + p->baux = b; p->lock_max = ((flp_max<=255)?flp_max:255); if(p->lock_max < 1) p->lock_max = 1; + return p; +} + +void des_mc_clus_t(mc_clus_t *p) +{ + if((!p)) return; + uint32_t k; free(p->lock); osg_destroy(p->sg.g); + if(p->asn) { + free(p->asn->a); free(p->asn); + } + for (k = 0; k < p->n_thread; k++) free(p->aux[k].vis.a); + free(p->aux); free(p->cc.ng.a); free(p->cc.nn.a); + free(p); +} + +asg64_v* gen_ref_bub(mc_clus_t *bc, kv_u_trans_t *ref) +{ + if(!ref) return NULL; + asg64_v *aux; CALLOC(aux, 1); aux->n = aux->m = bc->n; double w, mmw; + MALLOC(aux->a, bc->n); memset(aux->a, -1, sizeof((*(aux->a)))*bc->n); + uint32_t k, l, i, *ba, bn, m, on, bid; ma_utg_t *u = NULL; uint64_t p, mm, st, j; + u_trans_t *o = NULL; asg64_v buf; kv_init(buf); + + for (i = bid = 0; i < bc->bub->b_ug->u.n; i++) {///set nodes within bubbles + u = &(bc->bub->b_ug->u.a[i]); + for (k = 0; k < u->n; k++, bid++) { + get_bubbles(bc->bub, u->a[k]>>33, NULL, NULL, &ba, &bn, NULL); + for (m = 0; m < bn; m++) aux->a[ba[m]>>1] = bid; + } + } + // bin = bid; + + for (i = 0; i < bc->bub->ug->g->n_seq; i++) { + if(aux->a[i] != ((uint64_t)-1)) continue; + o = u_trans_a(*ref, i); on = u_trans_n(*ref, i); + if(!on) continue; + buf.n = 0; kv_resize(uint64_t, buf, on); + for (k = 0; k < on; k++) { + p = aux->a[o[k].tn]; p<<= 32; p += k; + kv_push(uint64_t, buf, p); + } + + radix_sort_mc64(buf.a, buf.a + buf.n); + mm = (uint32_t)-1; mmw = -1; + for (l = 0, k = 1; k <= buf.n; k++) { + if((k == buf.n) || ((buf.a[l]>>32) == ((uint32_t)-1)) || ((buf.a[l]>>32) != (buf.a[k]>>32))) { + for (m = l, w = 0; m < k; m++) w += fabs(o[((uint32_t)buf.a[m])].nw); + if(mmw < w) { + mmw = w; mm = buf.a[l]>>32; + } + l = k; + } + } + if(mm != ((uint32_t)-1)) aux->a[i] = mm; + } + + + ///final cluster + for (i = 0; i < bc->bub->ug->g->n_seq; i++) { + if(aux->a[i] != ((uint64_t)-1)) continue; + buf.n = 0; kv_push(uint64_t, buf, i); + while (buf.n > 0) { + k = buf.a[--buf.n]; + if(aux->a[k] != ((uint64_t)-1)) continue; + aux->a[k] = bid;///group id + o = u_trans_a(*ref, k); on = u_trans_n(*ref, k); + for (st = 0, j = 1; j <= on; ++j) { + if(j == on || o[j].tn != o[st].tn) { + if(aux->a[o[st].tn] == ((uint64_t)-1)) { + kv_push(uint64_t, buf, o[st].tn); + } + st = j; + } + } + } + bid++; + } + + assert(aux->n == bc->bub->ug->g->n_seq); + + for (i = 0; i < bc->bub->b_ug->u.n; i++) {///no need nodes in bubbles + u = &(bc->bub->b_ug->u.a[i]); + for (k = 0; k < u->n; k++) { + get_bubbles(bc->bub, u->a[k]>>33, NULL, NULL, &ba, &bn, NULL); + for (m = 0; m < bn; m++) aux->a[ba[m]>>1] = (uint64_t)-1; + } + } + for (i = aux->n = 0; i < bc->bub->ug->g->n_seq; i++) { + if(aux->a[i] == ((uint64_t)-1)) continue; + aux->a[i] <<= 32; aux->a[i] |= i;//bub_id|node_id + aux->a[aux->n++] = aux->a[i]; + } + radix_sort_mc64(aux->a, aux->a + aux->n); + kv_destroy(buf); + return aux; +} + +void mc_solve_core_adv(const mc_opt_t *opt, mc_g_t *mg, bubble_type* bub, kv_u_trans_t *ref) +{ + double index_time = yak_realtime(); + uint32_t st, i; + mc_svaux_t *b; mc_clus_t *bc; + // mc_bp_t *bp = NULL; + mc_g_cc(mg->e); + b = mc_svaux_init(mg, opt->seed); + bc = init_mc_clus_t(opt, mg, bub, asm_opt.thread_num, b, 16); + if(ref && bc) bc->asn = gen_ref_bub(bc, ref); + // bc = gen_mc_clus_t(mg->e, b, bub, ref, asm_opt.thread_num); + // if(bub) bp = mc_bp_t_init(mg->e, b, bub, asm_opt.thread_num); + /*******************************for debug************************************/ + // if(bp) mc_init_spin_all(opt, mg, NULL, b); + // if(bp) mc_solve_bp(bp); + /*******************************for debug************************************/ + if(VERBOSE_CUT) + { + fprintf(stderr, "\n\n\n\n\n*************beg-[M::%s::score->%f] ==> Partition\n", __func__, mc_score_all_advance(mg->e, mg->s.a)); + } + + for (st = 0, i = 1; i <= mg->e->n_seq; ++i) { + if (i == mg->e->n_seq || mg->e->cc[st]>>32 != mg->e->cc[i]>>32) { + mc_solve_cc_adv(opt, mg, b, st, i - st, bc); + st = i; + } + } + + if(VERBOSE_CUT) + { + fprintf(stderr, "##############end-[---M::%s::score->%f] ==> Partition\n", __func__, mc_score_all(mg->e, b)); + mc_status_all(mg->e, mg->s.a); + } + + + // if(bp) mc_solve_bp(bp); + ///mc_write_info(g, b); + mc_svaux_destroy(b); des_mc_clus_t(bc); + // if(bp) destroy_mc_bp_t(&bp); + fprintf(stderr, "[M::%s::%.3f] ==> Partition\n", __func__, yak_realtime()-index_time); +} + +void set_p_flag(mc_g_t *mg, uint32_t uID, uint8_t* trio_flag, trans_chain* t_ch, int8_t s) +{ + uint32_t i; + ma_utg_t *u = &(mg->ug->u.a[uID]); + for (i = 0; i < u->n; i++) + { + trio_flag[u->a[i]>>33] |= SET_TRIO; + if(t_ch->ir_het[u->a[i]>>33] == N_HET) continue; + if(s == 0) + { + if(t_ch->ir_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); + } +} + +void filter_ovlp_by_mc(ma_ug_t *ug, asg_t *read_g, uint32_t uID, hap_overlaps_list* ha, mc_match_t *ma, +int8_t *s) +{ + mc_edge_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 = ma_x(o[k]); tn = ma_y(o[k]); 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_by_mc(mc_g_t *mg, hap_overlaps_list* ha) +{ + 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 < mg->e->n_seq; ++i) + { + filter_ovlp_by_mc(mg->ug, mg->rg, i, ha, mg->e, mg->s.a); + } + + 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) continue; + + ha->x[v].a.a[k] = ha->x[v].a.a[i]; + k++; + } + ha->x[v].a.n = k; + } +} + + +void filter_ta_by_mc(ma_ug_t *ug, asg_t *read_g, uint32_t uID, kv_u_trans_t* ta, mc_match_t *ma, int8_t *s) +{ + mc_edge_t *o = pt_a(*ma, uID); + uint32_t n = pt_n(*ma, uID), k, qn, tn; + u_trans_t *p = NULL; + for (k = 0; k < n; ++k) + { + qn = ma_x(o[k]); tn = ma_y(o[k]); p = NULL; + if((s[qn]*s[tn])!=-1) continue; + get_u_trans_spec(ta, qn, tn, &p, NULL); + if(p && p->nw == o[k].w) { + p->del = 0; + } + else { + get_u_trans_spec(ta, tn, qn, &p, NULL); + if(p && p->nw == o[k].w) p->del = 0; + } + if(!p) fprintf(stderr, "ERROR-ta-p\n"); + } +} + + +void clean_ta_by_mc(mc_g_t *mg, kv_u_trans_t *ta) +{ + uint32_t v, i; + u_trans_t *p = NULL; + for (i = 0; i < ta->n; i++) ta->a[i].del = 1; + for (i = 0; i < mg->e->n_seq; ++i) filter_ta_by_mc(mg->ug, mg->rg, i, ta, mg->e, mg->s.a); + for (i = v = 0; i < ta->n; i++) { + if(ta->a[i].del) continue; + ta->a[v++] = ta->a[i]; + } + ta->n = v; + for (i = 0; i < v; i++) { + kv_pushp(u_trans_t, *ta, &p); + (*p) = ta->a[i]; + p->qn = ta->a[i].tn; p->qs = ta->a[i].ts; p->qe = ta->a[i].te; + p->tn = ta->a[i].qn; p->ts = ta->a[i].qs; p->te = ta->a[i].qe; + } + kt_u_trans_t_idx(ta, mg->ug->g->n_seq); +} + +void p_nodes(mc_g_t *mg, trans_chain* t_ch, uint8_t* trio_flag) +{ + uint32_t i; + for (i = 0; i < mg->e->n_seq; ++i) + { + set_p_flag(mg, i, trio_flag, t_ch, mg->s.a[i]); + } +} + +void write_mc_g_t(mc_opt_t *opt, mc_g_t *mg, const char *name) +{ + FILE* fp = fopen(name, "w"); + + fwrite(opt, sizeof(mc_opt_t), 1, fp); + fwrite(&(mg->s.n), sizeof(mg->s.n), 1, fp); + fwrite(mg->s.a, sizeof(mc_node_t), mg->s.n, fp); + fwrite(&(mg->e->n_seq), sizeof(mg->e->n_seq), 1, fp); + fwrite(&(mg->e->ma.n), sizeof(mg->e->ma.n), 1, fp); + fwrite(mg->e->ma.a, sizeof(mc_edge_t), mg->e->ma.n, fp); + fwrite(&(mg->e->idx.n), sizeof(mg->e->idx.n), 1, fp); + fwrite(mg->e->idx.a, sizeof(uint64_t), mg->e->idx.n, fp); + + fclose(fp); +} + +mc_g_t* load_mc_g_t(mc_opt_t *opt, const char *name) +{ + FILE* fp = NULL; + fp = fopen(name, "r"); + if(!fp) return NULL; + + uint64_t flag = 0; + mc_g_t *mg = NULL; CALLOC(mg, 1); + kv_init(mg->s); CALLOC(mg->e, 1); + + flag += fread(opt, sizeof(mc_opt_t), 1, fp); + + flag += fread(&(mg->s.n), sizeof(mg->s.n), 1, fp); + mg->s.m = mg->s.n; MALLOC(mg->s.a, mg->s.n); + flag += fread(mg->s.a, sizeof(mc_node_t), mg->s.n, fp); + + flag += fread(&(mg->e->n_seq), sizeof(mg->e->n_seq), 1, fp); + + flag += fread(&(mg->e->ma.n), sizeof(mg->e->ma.n), 1, fp); + mg->e->ma.m = mg->e->ma.n; MALLOC(mg->e->ma.a, mg->e->ma.n); + flag += fread(mg->e->ma.a, sizeof(mc_edge_t), mg->e->ma.n, fp); + + flag += fread(&(mg->e->idx.n), sizeof(mg->e->idx.n), 1, fp); + mg->e->idx.m = mg->e->idx.n; MALLOC(mg->e->idx.a, mg->e->idx.n); + flag += fread(mg->e->idx.a, sizeof(uint64_t), mg->e->idx.n, fp); + + fclose(fp); + return mg; +} + +void debug_mc_g_t(const char* name) +{ + mc_opt_t opt; + mc_g_t *mg = load_mc_g_t(&opt, name); + mc_solve_core(&opt, mg, NULL); + destory_mc_g_t(&mg); + exit(1); +} + +void print_hap_s(int8_t *s, uint32_t sn) +{ + fprintf(stderr, "\n[M::%s]\n", __func__); + uint32_t i; + for (i = 0; i < sn; i++) + { + fprintf(stderr,"utg%.6ul\t", i + 1); + if(s[i] > 0) fprintf(stderr, "h%u\n", 1); + else if(s[i] < 0) fprintf(stderr, "h%u\n", 2); + else fprintf(stderr,"\n"); + } +} + +void dump_debug_phasing(const char* fn, kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, double f_rate, +uint32_t renew_s, int8_t *s, uint32_t is_sys, bubble_type* bub, kv_u_trans_t *ref); +void mc_solve(hap_overlaps_list* ovlp, trans_chain* t_ch, kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, double f_rate, uint8_t* trio_flag, uint32_t renew_s, int8_t *s, uint32_t is_sys, bubble_type* bub, kv_u_trans_t *ref, int clean_ov, int is_dump) +{ + if(is_dump) { + dump_debug_phasing(MC_NAME, ta, ug, read_g, f_rate, renew_s, s, is_sys, bub, ref); + // bub = NULL; + } + + mc_opt_t opt; + mc_opt_init(&opt, asm_opt.n_perturb, asm_opt.f_perturb, asm_opt.seed); + mc_g_t *mg = init_mc_g_t(ug, read_g, s, renew_s); + update_mc_edges(mg, ovlp, ta, t_ch, f_rate, is_sys); + + fprintf(stderr, "[M::%s:: # edges: %u]\n", __func__, (uint32_t)mg->e->ma.n); + + mb_solve_core(&opt, mg, ref, is_sys); + ///debug_mc_g_t(mg); + // if(renew_s == 0) write_mc_g_t(&opt, mg, MC_NAME); + // mc_solve_core(&opt, mg, bub); + mc_solve_core_adv(&opt, mg, bub, ref); + + if((asm_opt.flag & HA_F_PARTITION) && t_ch) + { + p_nodes(mg, t_ch, trio_flag); + } + + if(clean_ov){ + if(ovlp) clean_ovlp_by_mc(mg, ovlp); + if(ta) clean_ta_by_mc(mg, ta); + } + // print_hap_s(s, ug->u.n); + + destory_mc_g_t(&mg); +} + + + +void comp(int m, int N, int M, mcb_t *p, int *c) +{ + if (m == M + 1) + { + int i; + mcg_node_t x = 0; + for (i = 0; i < M; i++) x |= ((mcg_node_t)1<<(c[i+1]-1)); + kv_push(mcg_node_t, *p, x); + } + else + { + for (c[m] = c[m - 1] + 1; c[m] <= N - M + m; c[m]++) + { + comp(m + 1, N, M, p, c); + } + } +} + + +void get_mcb(uint32_t n, uint32_t m, mcb_t *p, int *c) +{ + memset(c, 0, sizeof(int)*n+1); + p->n = 0; + comp(1, n, m, p, c); +} + +mc_gg_t *init_mc_gg_t(uint32_t un, kv_gg_status *s, uint16_t hapN) +{ + uint32_t i; + int *c = NULL; CALLOC(c, hapN+1); + mc_gg_t *p = NULL; CALLOC(p, 1); + // p->ug = ug; p->rg = read_g; + p->un = un; p->s = s; p->hN = hapN; + CALLOC(p->m.a, p->hN); p->m.n = p->m.m = hapN; + for (i = 0; i < p->hN; i++) get_mcb(hapN, i+1, &(p->m.a[i]), c); + p->mask = (1<mask--; + free(c); + return p; +} + +void destory_mc_gg_t(mc_gg_t **p) +{ + uint32_t i; + if(!p || !(*p)) return; + for (i = 0; i < (*p)->m.m; i++) + { + free((*p)->m.a[i].a); + } + free((*p)->m.a); + + if((*p)->e) + { + kv_destroy((*p)->e->idx); + kv_destroy((*p)->e->ma); + free((*p)->e->cc); + free((*p)->e); + } + free((*p)); +} + +kv_gg_status *init_mc_gg_status(ma_ug_t *ug, asg_t *read_g, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex, uint64_t t_cov, uint16_t hapN) +{ + fprintf(stderr, "t_cov-%lu\n", t_cov); + uint64_t *covs = NULL, i, k, k_i, c = t_cov/hapN, c_min, c_max; + uint32_t len[2]; + uint8_t *vis = NULL; CALLOC(vis, read_g->n_seq); + kv_gg_status *p = NULL; + CALLOC(covs, hapN); + for (i = 0; i < hapN; i++) + { + c_min = ((i+1)*c) - (0.6*c); + c_max = ((i+1)*c) + (0.6*c); + if(i == 0) c_min = 0; + if(i == hapN) c_max = (uint32_t)-1; + covs[i] = (c_max<<32)|c_min; + } + CALLOC(p, 1); + p->n = p->m = ug->u.n; + CALLOC(p->a, p->n); + for (i = 0; i < p->n; i++) + { + c = get_utg_cov(ug, i, read_g, coverage_cut, sources, ruIndex, vis); + p->a[i].h[0] = p->a[i].h[1] = (uint16_t)-1; p->a[i].s = 0; k_i = 0; + p->a[i].hw[0] = 1; p->a[i].hw[1] = 0; p->a[i].hc = 0; + for (k = 0; k < hapN; k++) + { + c_min = (uint32_t)covs[k]; c_max = covs[k]>>32; + if(c < c_min || c >= c_max) continue; + p->a[i].h[k_i++] = k + 1; + } + if(p->a[i].h[1] == (uint16_t)-1) continue; + + len[0] = (c >= (p->a[i].h[0]*(t_cov/hapN))? + c - (p->a[i].h[0]*(t_cov/hapN)) : (p->a[i].h[0]*(t_cov/hapN)) - c); + len[1] = (c >= (p->a[i].h[1]*(t_cov/hapN))? + c - (p->a[i].h[1]*(t_cov/hapN)) : (p->a[i].h[1]*(t_cov/hapN)) - c); + if(len[0] > len[1]) + { + k_i = p->a[i].h[0]; + p->a[i].h[0] = p->a[i].h[1]; + p->a[i].h[1] = k_i; + + k_i = len[0]; + len[0] = len[1]; + len[1] = k_i; + } + + p->a[i].hw[0] = (double)len[1]/(double)(len[0]+len[1]); + p->a[i].hw[1] = (double)len[0]/(double)(len[0]+len[1]); + } + free(covs); free(vis); + return p; +} + +void update_mc_edges_general(mc_gg_t *mg, kv_u_trans_t *ta, uint16_t hapN) +{ + uint32_t i, k; + mc_edge_t *ma = NULL; + CALLOC(mg->e, 1); + mg->e->n_seq = mg->un; + kv_init(mg->e->idx); kv_init(mg->e->ma); + + for (i = 0; i < ta->n; ++i) + { + if(ta->a[i].del) continue; + if(mg->s->a[ta->a[i].qn].h[0] >= hapN && mg->s->a[ta->a[i].qn].h[1] >= hapN) continue; + if(mg->s->a[ta->a[i].tn].h[0] >= hapN && mg->s->a[ta->a[i].tn].h[1] >= hapN) continue; + kv_pushp(mc_edge_t, mg->e->ma, &ma); + ma->x = (uint64_t)ta->a[i].qn << 32 | ta->a[i].tn; + ma->w = w_cast((ta->a[i].nw)); + } + + for (i = k = 0; i < mg->e->ma.n; i++) + { + if(mg->e->ma.a[i].w == 0) continue; + mg->e->ma.a[k] = mg->e->ma.a[i]; + k++; + } + mg->e->ma.n = k; + + radix_sort_mce(mg->e->ma.a, mg->e->ma.a + mg->e->ma.n); + mc_edges_idx(mg->e); + mc_edges_symm(mg->e); +} + + +typedef struct { + t_w_t *z; + uint32_t hapN; +} mc_poy_t; + +typedef struct { + uint64_t x; // RNG + uint32_t cc_off, cc_size; + kvec_t(uint64_t) cc_edge; + uint32_t *cc_node; + uint32_t *bfs, *bfs_mark; + mc_poy_t *z, *z_opt;///keep scores to nodes(1) and nodes(-1) + mc_gg_status *s, *s_opt; + mcb_t *m; + mcg_node_t mask; + uint32_t hapN; +} mcgg_svaux_t; + +mc_poy_t *init_mc_poy_t(uint32_t un, uint32_t hapN) +{ + uint32_t i; + mc_poy_t *z = NULL; CALLOC(z, 1); + MALLOC(z->z, ((uint32_t)un<z[i] = 0; + z->hapN = hapN; + return z; +} + +void destroy_mc_poy_t(mc_poy_t **p) +{ + if(!p || !(*p)) return; + free((*p)->z); free(*p); +} + +mcgg_svaux_t *mcgg_svaux_init(const mc_gg_t *mg, uint64_t x, uint32_t hapN) +{ + uint32_t st, i, max_cc = 0; + mc_match_t *ma = mg->e; + mcgg_svaux_t *b; + CALLOC(b, 1); + b->x = x; + for (st = 0, i = 1; i <= ma->n_seq; ++i) + if (i == ma->n_seq || ma->cc[st]>>32 != ma->cc[i]>>32) + max_cc = max_cc > i - st? max_cc : i - st, st = i; + kv_init(b->cc_edge); + MALLOC(b->cc_node, max_cc); + b->s = mg->s->a; + CALLOC(b->s_opt, ma->n_seq); + MALLOC(b->bfs, ma->n_seq); + + MALLOC(b->bfs_mark, ma->n_seq); + memset(b->bfs_mark, -1, ma->n_seq*sizeof(uint32_t)); + + b->z = init_mc_poy_t(ma->n_seq, hapN); + b->z_opt = init_mc_poy_t(ma->n_seq, hapN); + + b->m = mg->m.a; + b->mask = ((mcg_node_t)1)<mask--; + b->hapN = hapN; + return b; +} + +void mcgg_svaux_destroy(mcgg_svaux_t *b) +{ + b->s = NULL; + kv_destroy(b->cc_edge); free(b->cc_node); + free(b->s); free(b->s_opt); + destroy_mc_poy_t(&(b->z)); + destroy_mc_poy_t(&(b->z_opt)); + free(b->bfs); free(b->bfs_mark); + free(b); +} + +static inline mcg_node_t kr_drand_node(uint64_t id, mcgg_svaux_t *b, uint16_t *hc) +{ + uint16_t hn = b->s[id].h[0]-1; + if(hc) (*hc) = 0; + b->x = kr_splitmix64(b->x); + if(b->s[id].h[1] != (uint16_t)-1) + { + union { uint64_t i; double d; } u; + u.i = 0x3FFULL << 52 | (b->x) >> 12; + if((u.d - 1.0) > b->s[id].hw[0]) + { + hn = b->s[id].h[1]-1; + if(hc) (*hc) = 1; + } + } + return b->m[hn].a[(b->x)%b->m[hn].n]; +} + +static inline mcg_node_t kr_drand_node_ref(uint64_t id, mcgg_svaux_t *b, uint16_t *hc, mcg_node_t ref, uint64_t rev) +{ + uint64_t i, k, m, mm, mn, mi, cn, hn = b->s[id].h[0]; + mcg_node_t t; + if(hc) (*hc) = 0; + b->x = kr_splitmix64(b->x); + if(b->s[id].h[1] != (uint16_t)-1) + { + union { uint64_t i; double d; } u; + u.i = 0x3FFULL << 52 | (b->x) >> 12; + if((u.d - 1.0) > b->s[id].hw[0]) + { + hn = b->s[id].h[1]; + if(hc) (*hc) = 1; + } + } + if(rev) ref ^= (mcg_node_t)-1; + ref &= b->mask; + + t = ref; cn = 0; + while (t) + { + cn += t&1; + t >>= 1; + } + if(cn == hn) return ref; + + if(cn>=hn) mm=cn, m=1, mn=cn-hn;///1->0 + else mm=b->hapN-cn, m=0, mn=hn-cn;///0->1 + + for (i = 0; i < mn; i++) + { + mi = (b->x%mm); + for (k = 0; k < b->hapN; k++) + { + if(((ref>>k)&1)!=m) continue; + if(mi == 0) + { + ref ^= ((mcg_node_t)1<h[s->hc]; + mcg_node_t ref = s->s; + for (i = cn = 0; i < 32; i++) cn += ((ref>>i)&1); + if (cn != hn) fprintf(stderr, "%s-ERROR-cn, cn-%u, hn-%u\n", cmd, cn, hn); + else fprintf(stderr, "%s-pass-cn, cn-%u, hn-%u\n", cmd, cn, hn); +} + + +void mcgg_reset_z(const mc_match_t *ma, mcgg_svaux_t *b) +{ + uint32_t i; + for (i = 0; i < b->cc_size; ++i) { + uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///uid + uint32_t o = ma->idx.a[k] >> 32; + uint32_t j, n = (1<z->hapN); + for (j = 0; j < n; j++) mcp_de(*(b->z), k, j) = 0; + n = (uint32_t)ma->idx.a[k]; + for (j = 0; j < n; ++j) { + const mc_edge_t *e = &ma->ma.a[o + j]; + uint32_t t = ma_y(*e); + mcp_de(*(b->z), k, b->s[t].s) += e->w; + } + } +} + +t_w_t mcgg_score(const mc_match_t *ma, mcgg_svaux_t *b) +{ + uint32_t i, j, n = (1<z->hapN); + t_w_t z = 0; + for (i = 0; i < b->cc_size; ++i) { + uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///uid + for (j = 0; j < n; j++) + { + z += ((b->s[k].s&((mcg_node_t)j))?-mcp_de(*(b->z), k, j):mcp_de(*(b->z), k, j)); + } + } + return z; +} + +t_w_t mcgg_init_spin(const mc_match_t *ma, mcgg_svaux_t *b) +{ + uint32_t i; + b->cc_edge.n = 0; + for (i = 0; i < b->cc_size; ++i) {///how many nodes + uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///node id + b->cc_node[i] = k; + if(b->s[k].s == 0) break; + } + if(i >= b->cc_size) goto passed; + + for (i = 0; i < b->cc_size; ++i) {///how many nodes + uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///node id + uint32_t o = ma->idx.a[k] >> 32;///cc group id + uint32_t n = (uint32_t)ma->idx.a[k], j; + b->cc_node[i] = k; + for (j = 0; j < n; ++j) { + w_t w = ma->ma.a[o + j].w; + w = w > 0? w : -w; + kv_push(uint64_t, b->cc_edge, (uint64_t)((uint32_t)-1 - ((uint32_t)w)) << 32 | (o + j)); + } + } + radix_sort_mc64(b->cc_edge.a, b->cc_edge.a + b->cc_edge.n); + for (i = 0; i < b->cc_edge.n; ++i) { // from the strongest edge to the weakest + const mc_edge_t *e = &ma->ma.a[(uint32_t)b->cc_edge.a[i]]; + uint32_t n1 = ma_x(*e), n2 = ma_y(*e); + if (b->s[n1].s == 0 && b->s[n2].s == 0) { + b->s[n1].s = kr_drand_node(n1, b, &(b->s[n1].hc)); + // debug_hapM(&(b->s[n1]), "s0"); + b->s[n2].s = kr_drand_node_ref(n2, b, &(b->s[n2].hc), b->s[n1].s, e->w>0?1:0); + // debug_hapM(&(b->s[n2]), "s1"); + } + else if(b->s[n1].s == 0) + { + b->s[n1].s = kr_drand_node_ref(n1, b, &(b->s[n1].hc), b->s[n2].s, e->w>0?1:0); + // debug_hapM(&(b->s[n1]), "s2"); + } + else if(b->s[n2].s == 0) + { + b->s[n2].s = kr_drand_node_ref(n2, b, &(b->s[n2].hc), b->s[n1].s, e->w>0?1:0); + // debug_hapM(&(b->s[n2]), "s3"); + } + } + + passed: + mcgg_reset_z(ma, b); + return mcgg_score(ma, b); +} + +static mcg_node_t get_max_m(uint64_t id, mcgg_svaux_t *b) +{ + uint32_t hn = b->s[id].h[0]-1, k, j, n = (1<z->hapN); + mcg_node_t m, *p = NULL; + t_w_t z, max_z = -(1<<30); + for (k = 0; k < b->m[hn].n; k++) + { + m = b->m[hn].a[k]; z = 0; + for (j = 0; j < n; j++) + { + z += ((m&((mcg_node_t)j))?-mcp_de(*(b->z), id, j):mcp_de(*(b->z), id, j)); + } + if(!p || max_z < z || (max_z == z && m == b->s[id].s)) p = &(b->m[hn].a[k]), max_z = z; + } + + if(b->s[id].h[1] != (uint16_t)-1) + { + hn = b->s[id].h[1]-1; + for (k = 0; k < b->m[hn].n; k++) + { + m = b->m[hn].a[k]; z = 0; + for (j = 0; j < n; j++) + { + z += ((m&((mcg_node_t)j))?-mcp_de(*(b->z), id, j):mcp_de(*(b->z), id, j)); + } + if(!p || max_z < z || (max_z == z && m == b->s[id].s)) p = &(b->m[hn].a[k]), max_z = z; + } + } + return (*p); +} + +///k is uid +static void mcgg_set_spin(const mc_match_t *ma, mcgg_svaux_t *b, uint32_t k, mcg_node_t s, const char* cmd) +{ + uint32_t o, j, n; + mcg_node_t s0 = b->s[k].s; + /*******************************for debug************************************/ + // mcg_node_t t = s; + // o = 0; + // while (t) { + // o += (t&1); t>>=1; + // } + // if(o != b->s[k].h[0] && o != b->s[k].h[1]) fprintf(stderr, "cmd-%s, ERROR-mcgg-1\n", cmd); + // if(s0 == s) fprintf(stderr, "cmd-%s, ERROR-mcgg-2\n", cmd); + /*******************************for debug************************************/ + if (s0 == s) return; + o = ma->idx.a[k] >> 32; + n = (uint32_t)ma->idx.a[k]; + for (j = 0; j < n; ++j) { + const mc_edge_t *e = &ma->ma.a[o + j]; + uint32_t t = ma_y(*e);///1->z[0]; (-1)->z[1]; + mcp_de(*(b->z), t, s0) -= e->w; + mcp_de(*(b->z), t, s) += e->w; + } + b->s[k].s = s; +} + +static t_w_t mcgg_optimize_local(const mc_opt_t *opt, const mc_match_t *ma, mcgg_svaux_t *b, uint32_t *n_iter) +{ + uint32_t i, n_flip = 0; + int32_t n_iter_local = 0; + mcg_node_t ms; + while (n_iter_local < opt->max_iter) { + ++(*n_iter); + ks_shuffle_uint32_t(b->cc_size, b->cc_node, &b->x); + for (i = n_flip = 0; i < b->cc_size; ++i) { + uint32_t k = b->cc_node[i];///uid + ms = get_max_m(k, b); + if(ms != b->s[k].s) + { + mcgg_set_spin(ma, b, k, ms, __func__);///no need to change the score of k itself + // debug_hapM(&(b->s[k]), "s4"); + ++n_flip; + } + } + ++n_iter_local; + if (n_flip == 0) break; + } + + return mcgg_score(ma, b); +} + +void inline back_status(mcgg_svaux_t *b, uint32_t id, uint32_t to_opt) +{ + if(to_opt) + { + b->s_opt[id] = b->s[id]; + memcpy(b->z_opt->z+(id<z->hapN), b->z->z+(id<z->hapN), (1<z->hapN)*sizeof(t_w_t)); + } + else + { + b->s[id] = b->s_opt[id]; + memcpy(b->z->z+(id<z->hapN), b->z_opt->z+(id<z->hapN), (1<z->hapN)*sizeof(t_w_t)); + } + +} +/** +static inline mcg_node_t kr_drand_node_new(uint64_t id, mcgg_svaux_t *b) +{ + if(id == 10070) fprintf(stderr, "id-%lu, h[0]-%u, h[1]-%u\n", id, b->s[id].h[0], b->s[id].h[1]); + uint32_t hn = b->s[id].h[0]-1, is_old = 1, k; + if((b->s[id].h[1] != (uint16_t)-1) && (kr_drand_r(&b->x) > b->s[id].hw[0])) + { + hn = b->s[id].h[1]-1; is_old = 0; + } + if(id == 10070) fprintf(stderr, "id-%lu, hn-%u, b->m[hn].n-%u, is_old-%u\n", id, hn, b->m[hn].n, is_old); + b->x = kr_splitmix64(b->x); + k = b->x%(b->m[hn].n-is_old); + if(id == 10070) fprintf(stderr, "id-%lu, hn-%u, k-%u\n", id, hn, k); + if(b->m[hn].a[k] == b->s[id].s) k = b->m[hn].n-1; + return b->m[hn].a[k]; +} +**/ + +static inline mcg_node_t kr_drand_node_new(uint64_t id, mcgg_svaux_t *b) +{ + uint32_t hn = b->s[id].h[0]-1, k; + if((b->s[id].h[1] != (uint16_t)-1) && (kr_drand_r(&b->x) > b->s[id].hw[0])) + { + hn = b->s[id].h[1]-1; + } + b->x = kr_splitmix64(b->x); + k = b->x%(b->m[hn].n); + if(b->m[hn].a[k] == b->s[id].s && b->m[hn].n > 1) + { + k = b->x%(b->m[hn].n-1); + if(b->m[hn].a[k] == b->s[id].s) k = b->m[hn].n-1; + } + return b->m[hn].a[k]; +} + +static void mcgg_perturb(const mc_opt_t *opt, const mc_match_t *ma, mcgg_svaux_t *b) +{ + uint32_t i; + for (i = 0; i < b->cc_size; ++i) { + uint32_t k = (uint32_t)ma->cc[b->cc_off + i];///node id + double y; + y = kr_drand_r(&b->x); + if (y < opt->f_perturb) + mcgg_set_spin(ma, b, k, kr_drand_node_new(k, b), __func__); + } +} + +static uint32_t mcgg_bfs(const mc_match_t *ma, mcgg_svaux_t *b, uint32_t k0, uint32_t bfs_round, uint32_t max_size) +{ + uint32_t i, n_bfs = 0, st, en, r; + b->bfs[n_bfs++] = k0, b->bfs_mark[k0] = k0; + st = 0, en = n_bfs; + for (r = 0; r < bfs_round; ++r) { + for (i = st; i < en; ++i) { + uint32_t k = b->bfs[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) { + uint32_t t = (uint32_t)ma->ma.a[o + j].x; + if (b->bfs_mark[t] != k0) + b->bfs[n_bfs++] = t, b->bfs_mark[t] = k0; + } + } + st = en, en = n_bfs; + if (max_size > 0 && n_bfs > max_size) break; + } + return n_bfs; +} + +///bfs_round is 3 +static void mcgg_perturb_node(const mc_opt_t *opt, const mc_match_t *ma, mcgg_svaux_t *b, int32_t bfs_round) +{ + uint32_t i, k, n_bfs = 0; + k = (uint32_t)(kr_drand_r(&b->x) * b->cc_size + .499); + if(k >= b->cc_size) k = b->cc_size - 1; + k = (uint32_t)ma->cc[b->cc_off + k];///node id + n_bfs = mcgg_bfs(ma, b, k, bfs_round, (int32_t)(b->cc_size * opt->f_perturb)); + for (i = 0; i < n_bfs; ++i) + mcgg_set_spin(ma, b, b->bfs[i], kr_drand_node_new(b->bfs[i], b), __func__); +} + +void print_mcgg_node(const mc_match_t *ma, mcgg_svaux_t *b, uint32_t id) +{ + fprintf(stderr, "[M::%s::utg%.6ul-hap%u]\n", __func__, id, b->s[id].s); + w_t w[128]; + uint32_t o, n, i, hn = (1<z->hapN); + for (i = 0; i < hn; i++) w[i] = 0; + o = ma->idx.a[id] >> 32; + n = (uint32_t)ma->idx.a[id]; + for (i = 0; i < n; ++i) w[b->s[ma_y(ma->ma.a[o + i])].s] += ma->ma.a[o + i].w; + for (i = 0; i < hn; i++) fprintf(stderr, "w[%u]-%f, z[%u]-%f\n", i, w[i], i, mcp_de(*(b->z), id, i)); +} + +uint32_t mcgg_solve_cc(const mc_opt_t *opt, const mc_gg_t *mg, mcgg_svaux_t *b, uint32_t cc_off, uint32_t cc_size) +{ + // double t0, t1, tt0, tt1; + uint32_t j, k, n_iter = 0, flush = opt->max_iter * 50; + t_w_t sc_opt = -(1<<30), sc;///problem-w + b->cc_off = cc_off, b->cc_size = cc_size; + if (b->cc_size < 2) return 0; + sc_opt = mcgg_init_spin(mg->e, b); + if (b->cc_size == 2) return 0; + for (j = 0; j < b->cc_size; ++j) back_status(b, b->cc_node[j], 1); + + sc = mcgg_optimize_local(opt, mg->e, b, &n_iter); + if (sc > sc_opt) + { + for (j = 0; j < b->cc_size; ++j) back_status(b, b->cc_node[j], 1); + sc_opt = sc; + } + else + { + for (j = 0; j < b->cc_size; ++j) back_status(b, b->cc_node[j], 0); + } + fprintf(stderr, "\nBeg-[M::%s::score->%f]\n", __func__, mcgg_score(mg->e, b)); + // print_mcgg_node(mg->e, b, 3838); + // print_mcgg_node(mg->e, b, 36880); + + // tt0 = tt1 = 0; + for (k = 0; k < (uint32_t)opt->n_perturb; ++k) { + // t0 = yak_realtime(); + if (k&1) mcgg_perturb(opt, mg->e, b); + else mcgg_perturb_node(opt, mg->e, b, 3); + // tt0 += yak_realtime()-t0; + + // t1 = yak_realtime(); + sc = mcgg_optimize_local(opt, mg->e, b, &n_iter); + // tt1 += yak_realtime()-t1; + // fprintf(stderr, "++(%u) sc_after: %f\n", k, mcgg_score(mg->e, b)); + + if (sc > sc_opt) { + for (j = 0; j < b->cc_size; ++j) back_status(b, b->cc_node[j], 1); + sc_opt = sc; + } else { + for (j = 0; j < b->cc_size; ++j) back_status(b, b->cc_node[j], 0); + } + + + if((n_iter%flush) == 0) + { + mcgg_reset_z(mg->e, b); + sc = mcgg_score(mg->e, b); + for (j = 0; j < b->cc_size; ++j) back_status(b, b->cc_node[j], 1); + sc_opt = sc; + } + // fprintf(stderr, "\n"); + // print_mcgg_node(mg->e, b, 3838); + // print_mcgg_node(mg->e, b, 36880); + // if((k&31)==0)fprintf(stderr, "+++(%u) sc: %f, sc_opt: %f, tt0: %.3f, tt1: %.3f\n", k, sc, sc_opt, tt0, tt1); + } + + for (j = 0; j < b->cc_size; ++j) back_status(b, b->cc_node[j], 0); + fprintf(stderr, "End-[M::%s::score->%f]\n", __func__, mcgg_score(mg->e, b)); + return n_iter; +} + +void mc_solve_core_genral(const mc_opt_t *opt, mc_gg_t *mg, uint32_t hapN) +{ + double index_time = yak_realtime(); + uint32_t st, i; + mcgg_svaux_t *b; + mc_g_cc(mg->e); + b = mcgg_svaux_init(mg, opt->seed, hapN); + // if(VERBOSE_CUT) + // { + // fprintf(stderr, "\n\n\n\n\n*************beg-[M::%s::score->%f] ==> Partition\n", __func__, mc_score_all_advance(mg->e, mg->s.a)); + // } + + for (st = 0, i = 1; i <= mg->e->n_seq; ++i) { + if (i == mg->e->n_seq || mg->e->cc[st]>>32 != mg->e->cc[i]>>32) { + mcgg_solve_cc(opt, mg, b, st, i - st); + st = i; + } + } + + // if(VERBOSE_CUT) + // { + // fprintf(stderr, "##############end-[---M::%s::score->%f] ==> Partition\n", __func__, mc_score_all(mg->e, b)); + // } + ///mc_write_info(g, b); + mcgg_svaux_destroy(b); + fprintf(stderr, "[M::%s::%.3f] ==> Partition\n", __func__, yak_realtime()-index_time); +} + +void print_mcb(mc_gg_t *mg) +{ + uint32_t i, k, m; + mcg_node_t t; + mcb_t *p; + for (i = 0; i < mg->m.n; i++) + { + p = mcb_pat(*mg, i + 1); + fprintf(stderr, "# haplotypes: %u, # combination: %u\n", i+1, (uint32_t)p->n); + for (k = 0; k < p->n; k++) + { + t = p->a[k]; + for (m = 0; m < 32; m++) + { + if((t>>m)&1) fprintf(stderr, "%u\t", m); + } + fprintf(stderr, "\n"); + } + } +} + +void print_hap_p(kv_gg_status *s) +{ + fprintf(stderr, "\n[M::%s]\n", __func__); + uint32_t i, h; + mcg_node_t m; + for (i = 0; i < s->n; i++) + { + fprintf(stderr,"utg%.6ul\t", i + 1); + m = s->a[i].s; h = 0; + while (m) { + h++; + if(m&1) fprintf(stderr, "h%u\t", h); + m>>=1; + } + fprintf(stderr,"\n"); + } +} + +void write_mc_gg_dump(kv_u_trans_t *ta, uint32_t un, kv_gg_status *s, uint16_t hapN, const char* fn) +{ + fprintf(stderr, "\n[M::%s]\n", __func__); + char *buf = (char*)calloc(strlen(fn) + 50, 1); + sprintf(buf, "%s.hic.dbg.dump.bin", fn); + FILE* fp = fopen(buf, "w"); + + fwrite(&ta->n, sizeof(ta->n), 1, fp); + fwrite(ta->a, sizeof(u_trans_t), ta->n, fp); + + fwrite(&ta->idx.n, sizeof(ta->idx.n), 1, fp); + fwrite(ta->idx.a, sizeof(uint64_t), ta->idx.n, fp); + + fwrite(&un, sizeof(un), 1, fp); + + fwrite(&(s->n), sizeof(s->n), 1, fp); + fwrite(s->a, sizeof(mc_gg_status), s->n, fp); + + fwrite(&hapN, sizeof(hapN), 1, fp); + + fclose(fp); + free(buf); +} + +uint32_t load_mc_gg_dump(kv_u_trans_t **rta, uint32_t *un, kv_gg_status **rs, uint16_t *hapN, const char* fn) +{ + fprintf(stderr, "\n[M::%s]\n", __func__); + kv_u_trans_t *ta = NULL; + kv_gg_status *s = NULL; + uint64_t flag = 0; + char *buf = (char*)calloc(strlen(fn) + 25, 1); + sprintf(buf, "%s.hic.dbg.dump.bin", fn); + + FILE* fp = NULL; + fp = fopen(buf, "r"); + if(!fp) + { + free(buf); + return 0; + } + CALLOC(ta, 1); + flag += fread(&ta->n, sizeof(ta->n), 1, fp); + ta->m = ta->n; MALLOC(ta->a, ta->n); + flag += fread(ta->a, sizeof(u_trans_t), ta->n, fp); + + flag += fread(&ta->idx.n, sizeof(ta->idx.n), 1, fp); + ta->idx.m = ta->idx.n; MALLOC(ta->idx.a, ta->idx.n); + flag += fread(ta->idx.a, sizeof(uint64_t), ta->idx.n, fp); + + flag += fread(un, sizeof(*un), 1, fp); + + CALLOC(s, 1); + flag += fread(&(s->n), sizeof(s->n), 1, fp); + s->m = s->n; MALLOC(s->a, s->n); + flag += fread(s->a, sizeof(mc_gg_status), s->n, fp); + + flag += fread(hapN, sizeof(*hapN), 1, fp); + *rta = ta; *rs = s; + fclose(fp); + free(buf); + return 1; +} + +mc_g_t* to_mc_g_t(kv_u_trans_t *ta, kv_gg_status *s, uint32_t un) +{ + fprintf(stderr, "[M::%s]\n", __func__); + uint32_t i, k; + mc_edge_t *ma = NULL; + mc_g_t *mg = NULL; CALLOC(mg, 1); + + + CALLOC(mg->e, 1); + mg->e->n_seq = un; + kv_init(mg->e->idx); kv_init(mg->e->ma); + // double sc = get_w_scale(ta); + // fprintf(stderr, "sc: %f\n", sc); + for (i = 0; i < ta->n; ++i) + { + if(ta->a[i].del) continue; + kv_pushp(mc_edge_t, mg->e->ma, &ma); + ma->x = (uint64_t)ta->a[i].qn << 32 | ta->a[i].tn; + // ma->w = w_cast((ta->a[i].nw*sc)); + ma->w = w_cast((ta->a[i].nw)); + } + + + for (i = k = 0; i < mg->e->ma.n; i++) + { + if(mg->e->ma.a[i].w == 0) continue; + mg->e->ma.a[k] = mg->e->ma.a[i]; + k++; + } + mg->e->ma.n = k; + + radix_sort_mce(mg->e->ma.a, mg->e->ma.a + mg->e->ma.n); + mc_merge_dup(mg); + mc_edges_idx(mg->e); + mc_edges_symm(mg->e); + + kv_init(mg->s); + mg->s.m = mg->s.n = s->n; CALLOC(mg->s.a, mg->s.n); + for (i = 0; i < mg->s.n; ++i) + { + if(s->a[i].s != 1 && s->a[i].s != 2) continue; + mg->s.a[i] = (s->a[i].s == 1? 1:-1); + } + return mg; +} + +void debug_mc_gg_t(const char* fn, uint32_t update_ta, uint32_t convert_mc_g_t) +{ + kv_u_trans_t *ta = NULL; + kv_gg_status *s = NULL; + uint32_t un; + uint16_t hapN; + if(load_mc_gg_dump(&ta, &un, &s, &hapN, fn)) + { + if(convert_mc_g_t) + { + mc_opt_t opt; + mc_opt_init(&opt, asm_opt.n_perturb, asm_opt.f_perturb, asm_opt.seed); + mc_g_t *mg = NULL; + mg = to_mc_g_t(ta, s, un); + char *o_file = get_outfile_name(asm_opt.output_file_name); + trans_chain* t_ch = load_hc_trans(o_file); + mb_solve_core(&opt, mg, &(t_ch->k_trans), 1); + mc_solve_core(&opt, mg, NULL); + } + else + { + mc_solve_general(ta, un, s, hapN, update_ta, 0); + } + } + exit(1); +} + +void clean_solve_general_ovlp(kv_u_trans_t *ta, uint32_t un, kv_gg_status *s) +{ + uint32_t i; + for (i = 0; i < ta->n; i++) ta->a[i].del = !!(s->a[ta->a[i].qn].s&s->a[ta->a[i].tn].s); + kt_u_trans_t_simple_symm(ta, un, 0); +} + +void mc_solve_general(kv_u_trans_t *ta, uint32_t un, kv_gg_status *s, uint16_t hapN, uint16_t update_ta, uint16_t write_dump) +{ + print_hap_p(s); + exit(1); + mc_opt_t opt; + mc_opt_init(&opt, asm_opt.n_perturb, asm_opt.f_perturb, asm_opt.seed); + mc_gg_t *mg = init_mc_gg_t(un, s, hapN); + // print_mcb(mg); + + update_mc_edges_general(mg, ta, hapN); + mc_solve_core_genral(&opt, mg, hapN); + if(update_ta) clean_solve_general_ovlp(ta, un, s); + // print_hap_p(s); + + destory_mc_gg_t(&mg); + if(write_dump) write_mc_gg_dump(ta, un, s, hapN, MC_NAME); +} + +void dump_kv_u_trans_t(kv_u_trans_t *z, FILE *fp) +{ + fwrite(&(z->n), sizeof(z->n), 1, fp); + fwrite(z->a, sizeof((*(z->a))), z->n, fp); + fwrite(&z->idx.n, sizeof(z->idx.n), 1, fp); + fwrite(z->idx.a, sizeof((*(z->idx.a))), z->idx.n, fp); +} + +void dump_asg_t(asg_t *g, FILE *fp) +{ + uint32_t tmp, Len; + tmp = g->n_arc; + fwrite(&tmp, sizeof(tmp), 1, fp); + + tmp = g->is_srt; + fwrite(&tmp, sizeof(tmp), 1, fp); + + tmp = g->n_seq; + fwrite(&tmp, sizeof(tmp), 1, fp); + + tmp = g->is_symm; + fwrite(&tmp, sizeof(tmp), 1, fp); + + tmp = g->r_seq; + fwrite(&tmp, sizeof(tmp), 1, fp); + + + // Len = g->n_seq*2; + // fwrite(g->seq_vis, sizeof((*(g->seq_vis))), Len, fp); + + Len = g->n_seq*2; + fwrite(g->idx, sizeof((*(g->idx))), Len, fp); + fwrite(g->arc, sizeof((*(g->arc))), g->n_arc, fp); + fwrite(g->seq, sizeof((*(g->seq))), g->n_seq, fp); +} + +void dump_ma_ug_t(ma_ug_t *ug, FILE *fp) +{ + ma_utg_t *u = NULL; uint32_t t, i; + fwrite(&(ug->u.n), sizeof(ug->u.n), 1, fp); + for (i = 0; i < ug->u.n; i++) { + u = &(ug->u.a[i]); + t = u->len; + fwrite(&t, sizeof(t), 1, fp); + t = u->circ; + fwrite(&t, sizeof(t), 1, fp); + fwrite(&(u->start), sizeof(u->start), 1, fp); + fwrite(&(u->end), sizeof(u->end), 1, fp); + fwrite(&(u->n), sizeof(u->n), 1, fp); + fwrite(u->a, sizeof(uint64_t), u->n, fp); + } + dump_asg_t(ug->g, fp); +} + +void dump_bubble_type(bubble_type* bub, FILE *fp) +{ + fwrite(&(bub->chain_weight.n), sizeof(bub->chain_weight.n), 1, fp); + fwrite(bub->chain_weight.a, sizeof((*(bub->chain_weight.a))), bub->chain_weight.n, fp); + + fwrite(&(bub->list.n), sizeof(bub->list.n), 1, fp); + fwrite(bub->list.a, sizeof((*(bub->list.a))), bub->list.n, fp); + + fwrite(&(bub->num.n), sizeof(bub->num.n), 1, fp); + fwrite(bub->num.a, sizeof((*(bub->num.a))), bub->num.n, fp); + + fwrite(&(bub->pathLen.n), sizeof(bub->pathLen.n), 1, fp); + fwrite(bub->pathLen.a, sizeof((*(bub->pathLen.a))), bub->pathLen.n, fp); + + dump_ma_ug_t(bub->b_ug, fp); + dump_asg_t(bub->b_g, fp); + dump_ma_ug_t(bub->ug, fp); +} + +void dump_rid(All_reads *rdb, FILE *fp) +{ + fwrite(&(rdb->total_reads), sizeof(rdb->total_reads), 1, fp); + fwrite(&(rdb->name_index_size), sizeof(rdb->name_index_size), 1, fp); + fwrite(rdb->name_index, sizeof((*(rdb->name_index))), rdb->name_index_size, fp); + + fwrite(&(rdb->total_name_length), sizeof(rdb->total_name_length), 1, fp); + fwrite(rdb->name, sizeof((*(rdb->name))), rdb->total_name_length, fp); +} + +void load_rid(All_reads *rdb, FILE *fp) +{ + fread(&(rdb->total_reads), sizeof(rdb->total_reads), 1, fp); + fread(&(rdb->name_index_size), sizeof(rdb->name_index_size), 1, fp); + MALLOC(rdb->name_index, rdb->name_index_size); + fread(rdb->name_index, sizeof((*(rdb->name_index))), rdb->name_index_size, fp); + + fread(&(rdb->total_name_length), sizeof(rdb->total_name_length), 1, fp); + MALLOC(rdb->name, rdb->total_name_length); + fread(rdb->name, sizeof((*(rdb->name))), rdb->total_name_length, fp); +} + +void dump_debug_phasing(const char* fn, kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, double f_rate, +uint32_t renew_s, int8_t *s, uint32_t is_sys, bubble_type* bub, kv_u_trans_t *ref) +{ + fprintf(stderr, "\n[M::%s]\n", __func__); + char *buf = (char*)calloc(strlen(fn) + 50, 1); + sprintf(buf, "%s.hic.dbg.dump.bin", fn); + FILE *fp = fopen(buf, "w"); + + dump_kv_u_trans_t(ta, fp);///ta + dump_ma_ug_t(ug, fp);///ug + dump_asg_t(read_g, fp);///read_g + fwrite(&f_rate, sizeof(f_rate), 1, fp);///f_rate + fwrite(&renew_s, sizeof(renew_s), 1, fp);///renew_s + fwrite(s, sizeof((*s)), ug->g->n_seq, fp);///s + fwrite(&is_sys, sizeof(is_sys), 1, fp);///is_sys + dump_bubble_type(bub, fp);///bub + dump_kv_u_trans_t(ref, fp);///ta + dump_rid(&R_INF, fp); + + fclose(fp); + free(buf); +} + +void load_kv_u_trans_t(kv_u_trans_t *z, FILE *fp) +{ + fread(&(z->n), sizeof(z->n), 1, fp); + z->m = z->n; MALLOC(z->a, z->n); + fread(z->a, sizeof((*(z->a))), z->n, fp); + + fread(&z->idx.n, sizeof(z->idx.n), 1, fp); + z->idx.m = z->idx.n; MALLOC(z->idx.a, z->idx.n); + fread(z->idx.a, sizeof((*(z->idx.a))), z->idx.n, fp); +} + +void load_asg_t(asg_t *g, FILE *fp) +{ + uint32_t tmp, Len; + fread(&tmp, sizeof(tmp), 1, fp); + g->n_arc = g->m_arc = tmp; + + fread(&tmp, sizeof(tmp), 1, fp); + g->is_srt = tmp; + + fread(&tmp, sizeof(tmp), 1, fp); + g->n_seq = g->m_seq = tmp; + + fread(&tmp, sizeof(tmp), 1, fp); + g->is_symm = tmp; + + fread(&tmp, sizeof(tmp), 1, fp); + g->r_seq = tmp; + + // Len = g->n_seq*2; + // fwrite(g->seq_vis, sizeof((*(g->seq_vis))), Len, fp); + + Len = g->n_seq*2; + CALLOC(g->idx, Len); fread(g->idx, sizeof((*(g->idx))), Len, fp); + CALLOC(g->arc, g->n_arc); fread(g->arc, sizeof((*(g->arc))), g->n_arc, fp); + CALLOC(g->seq, g->n_seq); fread(g->seq, sizeof((*(g->seq))), g->n_seq, fp); +} + +void load_ma_ug_t(ma_ug_t *ug, FILE *fp) +{ + ma_utg_t *u = NULL; uint32_t t, i; + fread(&(ug->u.n), sizeof(ug->u.n), 1, fp); + ug->u.m = ug->u.n; CALLOC(ug->u.a, ug->u.n); + for (i = 0; i < ug->u.n; i++) { + u = &(ug->u.a[i]); + fread(&t, sizeof(t), 1, fp); u->len = t; + fread(&t, sizeof(t), 1, fp); u->circ = t; + fread(&(u->start), sizeof(u->start), 1, fp); + fread(&(u->end), sizeof(u->end), 1, fp); + fread(&(u->n), sizeof(u->n), 1, fp); + u->m = u->n; MALLOC(u->a, u->n); + fread(u->a, sizeof((*(u->a))), u->n, fp); + } + CALLOC(ug->g, 1); + load_asg_t(ug->g, fp); +} + +void load_bubble_type(bubble_type* bub, FILE *fp) +{ + fread(&(bub->chain_weight.n), sizeof(bub->chain_weight.n), 1, fp); + bub->chain_weight.m = bub->chain_weight.n; CALLOC(bub->chain_weight.a, bub->chain_weight.n); + fread(bub->chain_weight.a, sizeof((*(bub->chain_weight.a))), bub->chain_weight.n, fp); + + fread(&(bub->list.n), sizeof(bub->list.n), 1, fp); + bub->list.m = bub->list.n; CALLOC(bub->list.a, bub->list.n); + fread(bub->list.a, sizeof((*(bub->list.a))), bub->list.n, fp); + + fread(&(bub->num.n), sizeof(bub->num.n), 1, fp); + bub->num.m = bub->num.n; CALLOC(bub->num.a, bub->num.n); + fread(bub->num.a, sizeof((*(bub->num.a))), bub->num.n, fp); + + fread(&(bub->pathLen.n), sizeof(bub->pathLen.n), 1, fp); + bub->pathLen.m = bub->pathLen.n; CALLOC(bub->pathLen.a, bub->pathLen.n); + fread(bub->pathLen.a, sizeof((*(bub->pathLen.a))), bub->pathLen.n, fp); + + CALLOC(bub->b_ug, 1); load_ma_ug_t(bub->b_ug, fp); + CALLOC(bub->b_g, 1); load_asg_t(bub->b_g, fp); + CALLOC(bub->ug, 1); load_ma_ug_t(bub->ug, fp); +} + +void load_debug_phasing(const char* fn, kv_u_trans_t **ta, ma_ug_t **ug, asg_t **read_g, double *f_rate, +uint32_t *renew_s, int8_t **s, uint32_t *is_sys, bubble_type **bub, kv_u_trans_t **ref) +{ + fprintf(stderr, "\n[M::%s]\n", __func__); + char *buf = (char*)calloc(strlen(fn) + 50, 1); + sprintf(buf, "%s.hic.dbg.dump.bin", fn); + FILE *fp = fopen(buf, "r"); + + CALLOC((*ta), 1); load_kv_u_trans_t(*ta, fp);///ta + CALLOC((*ug), 1); load_ma_ug_t(*ug, fp);///ug + CALLOC((*read_g), 1); load_asg_t((*read_g), fp);///read_g + + fread(f_rate, sizeof((*f_rate)), 1, fp);///f_rate + fread(renew_s, sizeof((*renew_s)), 1, fp);///renew_s + CALLOC((*s), (*ug)->g->n_seq); fread(*s, sizeof((*(*s))), (*ug)->g->n_seq, fp);///s + fread(is_sys, sizeof((*is_sys)), 1, fp);///is_sys + + CALLOC((*bub), 1); load_bubble_type(*bub, fp);///bub + CALLOC((*ref), 1); load_kv_u_trans_t(*ref, fp);///ta + + load_rid(&R_INF, fp);///read id + + fclose(fp); + free(buf); +} + + +void prt_rcut_res(const char* fn, int8_t *s, ma_ug_t *ug, asg_t *sg) +{ + uint32_t i, k, flag = AMBIGU; + char *buf = (char*)calloc(strlen(fn) + 50, 1); + sprintf(buf, "%s.rcut.res.log", fn); + FILE *fp = fopen(buf, "w"); + uint8_t *rs = NULL; MALLOC(rs, sg->n_seq); + memset(rs, AMBIGU, sg->n_seq*sizeof((*rs))); + + for (i = 0; i < ug->g->n_seq; i++) { + if(ug->g->seq[i].del) continue; + flag = AMBIGU; + if(s[i] == 0) continue; + flag = (s[i] > 0? FATHER:MOTHER); + for (k = 0; k < ug->u.a[i].n; k++) rs[ug->u.a[i].a[k]>>33] = flag; + } + + for (i = 0; i < sg->n_seq; i++) { + if(rs[i] == AMBIGU) continue; + fprintf(fp, "%.*s\t%u\n", (int)Get_NAME_LENGTH(R_INF, i), Get_NAME(R_INF, i), rs[i]); + } + + fclose(fp); free(rs); + free(buf); +} + +void quick_debug_phasing(const char* fn) +{ + kv_u_trans_t *ta; ma_ug_t *ug; asg_t *read_g; double f_rate; + uint32_t renew_s; int8_t *s; uint32_t is_sys; bubble_type *bub; kv_u_trans_t *ref; + load_debug_phasing(fn, &ta, &ug, &read_g, &f_rate, &renew_s, &s, &is_sys, &bub, &ref); + + + + mc_solve(NULL, NULL, ta, ug, read_g, f_rate, NULL, renew_s, s, is_sys, bub, ref, 0, 0); + // mc_solve_core_adv(const mc_opt_t *opt, mc_g_t *mg, bubble_type* bub, kv_u_trans_t *ref) + + // for (k = 0; k < ug->g->n_seq; k++) { + // fprintf(stderr, "utg%.6dl(len::%u), s[k]::%d\n", (int32_t)(k)+1, ug->g->seq[k].len, s[k]); + // } + prt_rcut_res(fn, s, ug, read_g); + + exit(1); +} diff --git a/rcut.h b/rcut.h index 2679e3c..23532b3 100644 --- a/rcut.h +++ b/rcut.h @@ -1,131 +1,131 @@ -#ifndef __RCUT__ -#define __RCUT__ - -#define __STDC_LIMIT_MACROS -#include -#include -#include "kvec.h" -#include "Overlaps.h" -#include "Purge_Dups.h" -#include "hic.h" - -typedef struct { - uint32_t bS, bE; - uint32_t nS, nE; - uint32_t uID; - uint8_t hs; -}mc_interval_t; - -#define mc_node_t int8_t -#define mcg_node_t uint32_t -// #define w_t int64_t -// #define t_w_t int64_t -// #define w_cast(x) ((t_w_t)((x) < 0 ? (x) - 0.5 : (x) + 0.5)) - -#define w_t double -#define t_w_t double -#define w_cast(x) ((t_w_t)((x))) -#define MC_NAME "debug_mc.bin" - -typedef struct { - uint64_t x; ///(uint64_t)nid1 << 32 | nid2; - w_t w; ///might be negative or positive -} mc_edge_t; - -typedef struct { - kvec_t(uint64_t) idx; - kvec_t(mc_edge_t) ma; - uint64_t* cc; - uint32_t n_seq; -} mc_match_t; - -typedef struct { - kvec_t(mc_node_t) s; - ma_ug_t *ug; - asg_t *rg; - mc_match_t* e; -}mc_g_t; - -typedef struct { - uint32_t a[2], occ[2]; - mc_node_t s[2]; - t_w_t z[4]; -}mb_node_t; - -typedef struct { - kvec_t(uint32_t) bid; - kvec_t(uint32_t) idx; - kvec_t(mb_node_t) u; -}mb_nodes_t; - -typedef struct { - uint64_t x; ///(uint64_t)nid1 << 32 | nid2; - t_w_t w[4]; ///might be negative or positive -} mb_edge_t; - -typedef struct { - kvec_t(uint64_t) idx; - kvec_t(mb_edge_t) ma; - uint64_t* cc; - uint32_t n_seq; -} mb_match_t; - -typedef struct { - mb_nodes_t* u; - mb_match_t* e; -}mb_g_t; - -typedef struct { - mcg_node_t s; - uint16_t h[2], hc; - double hw[2]; -}mc_gg_status; - -typedef struct { - mc_gg_status *a; - size_t n, m; -}kv_gg_status; - -typedef struct { - mcg_node_t *a; - size_t n, m; -}mcb_t; - - -typedef struct { - kv_gg_status *s; - // ma_ug_t *ug; - // asg_t *rg; - uint32_t un; - mc_match_t* e; - kvec_t(mcb_t) m; - mcg_node_t mask; - uint16_t hN; -}mc_gg_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 mc_solve(hap_overlaps_list* ovlp, trans_chain* t_ch, kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, double f_rate, uint8_t* trio_flag, uint32_t renew_s, int8_t *s, uint32_t is_sys, bubble_type* bub, kv_u_trans_t *ref, int clean_ov, int is_dump); -void debug_mc_g_t(const char* name); -void mc_solve_general(kv_u_trans_t *ta, uint32_t un, kv_gg_status *s, uint16_t hapN, uint16_t update_ta, uint16_t write_dump); -kv_gg_status *init_mc_gg_status(ma_ug_t *ug, asg_t *read_g, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex, uint64_t t_cov, uint16_t hapN); -void destory_mc_gg_t(mc_gg_t **p); -void debug_mc_gg_t(const char* fn, uint32_t update_ta, uint32_t convert_mc_g_t); -void quick_debug_phasing(const char* fn); +#ifndef __RCUT__ +#define __RCUT__ + +#define __STDC_LIMIT_MACROS +#include +#include +#include "kvec.h" +#include "Overlaps.h" +#include "Purge_Dups.h" +#include "hic.h" + +typedef struct { + uint32_t bS, bE; + uint32_t nS, nE; + uint32_t uID; + uint8_t hs; +}mc_interval_t; + +#define mc_node_t int8_t +#define mcg_node_t uint32_t +// #define w_t int64_t +// #define t_w_t int64_t +// #define w_cast(x) ((t_w_t)((x) < 0 ? (x) - 0.5 : (x) + 0.5)) + +#define w_t double +#define t_w_t double +#define w_cast(x) ((t_w_t)((x))) +#define MC_NAME "debug_mc.bin" + +typedef struct { + uint64_t x; ///(uint64_t)nid1 << 32 | nid2; + w_t w; ///might be negative or positive +} mc_edge_t; + +typedef struct { + kvec_t(uint64_t) idx; + kvec_t(mc_edge_t) ma; + uint64_t* cc; + uint32_t n_seq; +} mc_match_t; + +typedef struct { + kvec_t(mc_node_t) s; + ma_ug_t *ug; + asg_t *rg; + mc_match_t* e; +}mc_g_t; + +typedef struct { + uint32_t a[2], occ[2]; + mc_node_t s[2]; + t_w_t z[4]; +}mb_node_t; + +typedef struct { + kvec_t(uint32_t) bid; + kvec_t(uint32_t) idx; + kvec_t(mb_node_t) u; +}mb_nodes_t; + +typedef struct { + uint64_t x; ///(uint64_t)nid1 << 32 | nid2; + t_w_t w[4]; ///might be negative or positive +} mb_edge_t; + +typedef struct { + kvec_t(uint64_t) idx; + kvec_t(mb_edge_t) ma; + uint64_t* cc; + uint32_t n_seq; +} mb_match_t; + +typedef struct { + mb_nodes_t* u; + mb_match_t* e; +}mb_g_t; + +typedef struct { + mcg_node_t s; + uint16_t h[2], hc; + double hw[2]; +}mc_gg_status; + +typedef struct { + mc_gg_status *a; + size_t n, m; +}kv_gg_status; + +typedef struct { + mcg_node_t *a; + size_t n, m; +}mcb_t; + + +typedef struct { + kv_gg_status *s; + // ma_ug_t *ug; + // asg_t *rg; + uint32_t un; + mc_match_t* e; + kvec_t(mcb_t) m; + mcg_node_t mask; + uint16_t hN; +}mc_gg_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 mc_solve(hap_overlaps_list* ovlp, trans_chain* t_ch, kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, double f_rate, uint8_t* trio_flag, uint32_t renew_s, int8_t *s, uint32_t is_sys, bubble_type* bub, kv_u_trans_t *ref, int clean_ov, int is_dump); +void debug_mc_g_t(const char* name); +void mc_solve_general(kv_u_trans_t *ta, uint32_t un, kv_gg_status *s, uint16_t hapN, uint16_t update_ta, uint16_t write_dump); +kv_gg_status *init_mc_gg_status(ma_ug_t *ug, asg_t *read_g, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex, uint64_t t_cov, uint16_t hapN); +void destory_mc_gg_t(mc_gg_t **p); +void debug_mc_gg_t(const char* fn, uint32_t update_ta, uint32_t convert_mc_g_t); +void quick_debug_phasing(const char* fn); #endif \ No newline at end of file diff --git a/sketch.cpp b/sketch.cpp index 3f21111..54dd5f7 100644 --- a/sketch.cpp +++ b/sketch.cpp @@ -1,582 +1,582 @@ -#include -#include -#include -#include -#include "kvec.h" -#include "htab.h" -#include "ksort.h" -#include "Correct.h" -#include "kalloc.h" - -#define MAX_HIGH_OCC 8 // TODO: don't hard code if we need to tune this parameter -#define MAX_MAX_HIGH_OCC 16 -#define GMC(a, x,y,xn) ((a)[(x)*(xn)+(y)]) -#define GL(x, i) ((int64_t)((uint32_t)((x).a[(i)]))) -#define A_M(p, i) ((i) >= 0 && (p).a[(i)].rid > 0) - -void debug_refine(ha_mz1_t *ma, uint64_t *mmt, int32_t sn, int32_t n, int32_t m, int32_t end) -{ - uint64_t ks = end; - int64_t t = 0, i, k, sp = -1, ep = -1, ovlp, tot = mmt[end]&0xffffffff, nt = 0;; - while (ks != 0xffffffff) - { - i = ks/m; k = ks%m; - ks = mmt[ks]>>32; - if(ks == 0xffffffff || (int32_t)(ks/m) == (i-1)) - { - t++; - ovlp = ((MIN(ep, (int64_t)ma[k].pos) >= MAX(sp, (int64_t)(ma[k].pos+1-ma[k].span)))? - MIN(ep, (int64_t)ma[k].pos) - MAX(sp, (int64_t)(ma[k].pos+1-ma[k].span)) + 1:0); - if(ovlp != 0) fprintf(stderr, "ERROR-OVLP\n"); - if(sp == -1 || sp > (ma[k].pos+1-ma[k].span)) sp = ma[k].pos+1-ma[k].span; - if(ep == -1 || ep < ma[k].pos) ep = ma[k].pos; - nt += (ma[k].rid); - } - } - if(t != sn) fprintf(stderr, "ERROR-TN, t: %ld, sn: %d\n", t, sn); - if(nt != tot) fprintf(stderr, "ERROR-TOT, nt: %ld, tot: %ld\n", nt, tot); -} - -void dbg_boundary(ha_mz1_v *p, st_mt_t *mt, int32_t w, int32_t k, int32_t tot_l) -{ - if(tot_l < w + k -1) return; - int32_t i, m, n = p->n, s, a; - for (i = 0; i < n; i++){ - if(GL(*mt, i) >= w+k-1){ - for (m = s = a = 0; m <= i; m++){ - if(!A_M(*p, m)) continue; - if(GL(*mt, m) <= w+k-1){ - a++; - if(mt->a[m]&0x100000000) s++; - } - } - if(a > 0 && s == 0){ - fprintf(stderr, "\nERROR1, s: %d, n: %d, tot_l: %d, end_l: %ld\n", s, n, tot_l, GL(*mt, i)); - for (m = s = a = 0; m <= i; m++){ - if(!A_M(*p, m)) continue; - if(GL(*mt, m) <= w+k-1){ - fprintf(stderr, "lp: %ld\n", GL(*mt, m)); - a++; - if(mt->a[m]&0x100000000) s++; - } - } - - } - - break; - } - } - if(i == n){ - for (m = s = a = 0; m < n; m++){ - if(!A_M(*p, m)) continue; - if(GL(*mt, m) <= w+k-1){ - a++; - if(mt->a[m]&0x100000000) s++; - } - } - if(a > 0 && s == 0) fprintf(stderr, "ERROR2\n"); - } - - for (i = n-1; i >= 0; i--) - { - if (GL(*mt, i) + w <= tot_l + 1) { - for (m = i, s = a = 0; m < n; m++){ - if(!A_M(*p, m)) continue; - if(GL(*mt, m) + w >= tot_l + 1){ - a++; - if(mt->a[m]&0x100000000) s++; - } - } - if(a > 0 && s == 0) { - fprintf(stderr, "\nERROR3, s: %d, n: %d, tot_l: %d, end_l: %ld\n", s, n, tot_l, GL(*mt, i)); - for (m = i, s = a = 0; m < n; m++){ - if(!A_M(*p, m)) continue; - if(GL(*mt, m) + w >= tot_l + 1){ - fprintf(stderr, "lp: %ld\n", GL(*mt, m)); - a++; - if(mt->a[m]&0x100000000) s++; - } - } - } - - break; - } - } - - if(i < 0){ - for (m = s = a = 0; m < n; m++){ - if(!A_M(*p, m)) continue; - if(GL(*mt, m) + w >= tot_l + 1){ - a++; - if(mt->a[m]&0x100000000) s++; - } - } - if(a > 0 && s == 0) fprintf(stderr, "ERROR4\n"); - } -} - -void debug_pl(const char *str, int len, int w, int k, int is_hpc, ha_mz1_v *p, const void *hf, st_mt_t *mt) -{ - int i, l, dbi, dbcnt = 0, kmer_span = 0; - tiny_queue_t tq; - memset(&tq, 0, sizeof(tiny_queue_t)); - uint64_t shift1 = k - 1, mask = (1ULL< k) kmer_span -= tq_shift(&tq); - } else kmer_span = l + 1 < k? l + 1 : k; - ///kmer_span should be used for HPC k-mer - ///non-HPC k-mer, kmer_span should be k - ///kmer_span is used to calculate anchor pos on reverse complementary strand - - kmer[0] = (kmer[0] << 1 | (c&1)) & mask; // forward k-mer - kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; - kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; // reverse k-mer - kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; - if (kmer[1] == kmer[3]) continue; // skip "symmetric k-mers" as we don't know it strand - z = kmer[1] < kmer[3]? 0 : 1; // strand - ++l; - - if (l >= k && kmer_span < 256) { - uint64_t y; - int32_t cnt; - y = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); - cnt = hf? ha_ft_cnt(hf, y) : 0; - - for (dbi = 0; dbi < (int32_t)mt->n; dbi++) - { - if(p->a[dbi].x == y && p->a[dbi].rid == cnt && p->a[dbi].pos == i && p->a[dbi].rev == z && p->a[dbi].span == kmer_span) - { - if(l != (int)mt->a[dbi]) fprintf(stderr, "ERROR\n"); - dbcnt++; - } - } - } - } else l = 0, tq.count = tq.front = 0, kmer_span = 0; - } - - if(dbcnt != (int32_t)mt->n) fprintf(stderr, "ERROR\n"); - if(mt->n != p->n) fprintf(stderr, "ERROR\n"); - for (dbi = 1; dbi < (int32_t)mt->n; dbi++) - { - if(p->a[dbi].pos <= p->a[dbi-1].pos || (int)mt->a[dbi] <= (int)mt->a[dbi-1]) - { - fprintf(stderr, "ERROR\n"); - } - } -} - -static inline int mz1_mzcmp(const ha_mz1_t *a, const ha_mz1_t *b){return a->rid < b->rid? -1 : a->rid > b->rid? 1 : ((a->x > b->x) - (a->x < b->x));} -#define mz1_mz_lt(a, b) (mz1_mzcmp(&(a), &(b)) < 0) -KSORT_INIT(mz1_mz, ha_mz1_t, mz1_mz_lt) - -static inline int mz2_mzcmp(const ha_mzl_t *a, const ha_mzl_t *b){return a->rid < b->rid? -1 : a->rid > b->rid? 1 : ((a->x > b->x) - (a->x < b->x));} -#define mz2_mz_lt(a, b) (mz2_mzcmp(&(a), &(b)) < 0) -KSORT_INIT(mz2_mz, ha_mzl_t, mz2_mz_lt) - - -#define HA_SC_INIT(sf, HType, VType, RidBits, PosBits)\ -inline void sf##_hf_select(VType *p, int32_t si, int32_t ei, int32_t n, int32_t len, int32_t sample_dist, HType *b, int32_t force)\ -{\ - if(ei - si <= 1) return;\ - int32_t ps = si < 0? 0 : p->a[si].pos;\ - int32_t pe = ei == n? len : p->a[ei].pos;\ - int32_t j, k, st = si + 1, en = ei;\ - int32_t max_high_occ = (int32_t)((double)(pe - ps) / sample_dist + .499);\ - if (max_high_occ > MAX_MAX_HIGH_OCC)\ - max_high_occ = MAX_MAX_HIGH_OCC;\ - for (j = st, k = 0; j < en && k < max_high_occ; ++j, ++k)\ - b[k] = p->a[j], b[k].pos = j; /** b[].pos keeps the index in p->a[]**/\ - ks_heapmake_##sf##_mz(k, b); /** initialize the binomial heap**/\ - for (; j < en; ++j) { /** if there are more, choose top max_high_occ**/\ - if (sf##_mz_lt(p->a[j], b[0])) { /** then update the heap**/\ - b[0] = p->a[j], b[0].pos = j;\ - ks_heapdown_##sf##_mz(0, k, b);\ - }\ - }\ - /**ks_heapsort_mz(k, b); // sorting is not needed for now**/\ - for (j = 0; j < k; ++j)\ - if (b[j].rid < pe - ps || force)\ - p->a[b[j].pos].rid = 0;\ -}\ -static inline int sf##_mzcmp_l(const VType *p, int32_t ai, int32_t bi)\ -{\ - if(ai >= 0 && bi >= 0){\ - HType *a = &(p->a[ai]), *b = &(p->a[bi]);\ - if(a->rid > 0 && b->rid > 0) return sf##_mzcmp(a, b);\ - return (a->rid == 0) - (b->rid == 0);\ - }\ - return (ai < 0) - (bi < 0);\ -}\ -int32_t sf##_qfw(VType *p, st_mt_t *mt, int32_t n, int32_t tot_l, int32_t ws, int32_t i, int32_t *mi)\ -{\ - int32_t m, si;\ - for (si = i, (*mi) = -1; i < n; i++){\ - if(GL(*mt, i) >= ws || (i+1 < n && GL(*mt, i) < ws && GL(*mt, i+1) > ws) || \ - (i+1 == n && tot_l >= ws && GL(*mt, i) < ws)){\ - for (m = si; m <= i; m++){\ - if(!A_M(*p, m)) continue;\ - if(sf##_mzcmp_l(p, *mi, m) >= 0) (*mi) = m;\ - }\ - if((*mi) >= 0 && A_M(*p, *mi)){\ - for (m = si; m <= i; m++){\ - if(!A_M(*p, m)) continue;\ - if(sf##_mzcmp_l(p, *mi, m) == 0) mt->a[m] |= 0x100000000;\ - }\ - }\ - break;\ - }\ - }\ - return i;\ -}\ -static void sf##_select_mz_h(VType *p, st_mt_t *mt, int len, int sample_dist, int32_t w, int32_t k, int32_t tot_l)\ -{ /**for high-occ minimizers, choose up to max_high_occ in each high-occ streak**/\ - int32_t i, mi = -1, si, last0 = -1, n = (int32_t)p->n, m = 0, ws = w + k - 1;\ - if (n == 0) return;\ - assert((int64_t)(n) < (int64_t)((((uint64_t)1)<a[i].rid == 0) {\ - if (i - last0 > 1) {\ - int32_t ps = last0 < 0? 0 : p->a[last0].pos;\ - int32_t pe = i == n? len : p->a[i].pos;\ - if(((int32_t)((double)(pe - ps) / sample_dist + .499)) > 0){\ - last0 = -2;\ - m++;\ - break;\ - }\ - }\ - last0 = i;\ - }\ - }\ - if (m == 0) return; /**no high-frequency k-mers; do nothing**/\ - if(last0 >= -1) goto sf##_ff;\ - i = 0;\ - i = sf##_qfw(p, mt, n, tot_l, ws, i, &mi);\ - if(i == n) goto sf##_ff;\ - for (si = 0, i++; i < n; i++){\ - for (; si < i; si++){\ - if(GL(*mt, si) + w > GL(*mt, i)) break;\ - }\ - /**a new minimum; then write the old min**/\ - if(sf##_mzcmp_l(p, i, mi) <= 0) {\ - if(A_M(*p, mi)) mt->a[mi] |= 0x100000000;\ - mi = i;\ - }/**old min has moved outside the window**/\ - else if(si > mi){\ - if(A_M(*p, mi)) mt->a[mi] |= 0x100000000;\ - for (m = si, mi = -1; m <= i; m++){\ - if(sf##_mzcmp_l(p, mi, m) >= 0) mi = m;\ - }\ - if(A_M(*p, mi)){\ - for (m = si; m <= i; m++){\ - if(!A_M(*p, m)) continue;\ - if(sf##_mzcmp_l(p, mi, m) == 0) mt->a[m] |= 0x100000000;\ - }\ - }\ - }\ - }\ - if(A_M(*p, mi)) mt->a[mi] |= 0x100000000;\ - for (i = n - 1; si < n && GL(*mt, si) + w <= tot_l + 1; si++){\ - if(si > mi){\ - if(A_M(*p, mi)) mt->a[mi] |= 0x100000000;\ - for (m = si, mi = -1; m <= i; m++){\ - if(sf##_mzcmp_l(p, mi, m) >= 0) mi = m;\ - }\ - if(A_M(*p, mi)){\ - for (m = si; m <= i; m++){\ - if(!A_M(*p, m)) continue;\ - if(sf##_mzcmp_l(p, mi, m) == 0) mt->a[m] |= 0x100000000;\ - }\ - }\ - }\ - }\ - /**dbg_boundary(p, mt, w, k, tot_l);**/\ - HType b[MAX_MAX_HIGH_OCC];\ - for (i = 0, last0 = -1; i <= n; ++i) {\ - if (i == n || p->a[i].rid == 0) {\ - if (i - last0 > 1) {\ - int32_t ps = last0 < 0? 0 : p->a[last0].pos;\ - int32_t pe = i == n? len : p->a[i].pos;\ - if(((int32_t)((double)(pe - ps) / sample_dist + .499)) > 0){\ - for (m = last0 + 1, mi = 0; m < i; ++m){\ - if(mt->a[m]&0x100000000) p->a[m].rid = 0, mi++;\ - }\ - if(mi == 0) sf##_hf_select(p, last0, i, n, len, sample_dist, b, 0);\ - }\ - }\ - last0 = i;\ - }\ - }\ - sf##_ff:\ - for (i = n = 0; i < (int32_t)p->n; ++i) /**squeeze out filtered minimizers**/\ - if (p->a[i].rid == 0)\ - p->a[n++] = p->a[i];\ - p->n = n;\ -}\ -void sf##_refine_select(VType *mz, int32_t sidx, int32_t eidx, int32_t sn, int32_t min_freq, st_mt_t *mm, int32_t *rsi, int32_t *rei, void *km)\ -{\ - int32_t n = sn, m = eidx + 1 - sidx, i, k, t, mk=-1;\ - uint64_t ix, kx, ks;\ - kv_resize_km(km, uint64_t, *mm, mm->n+n*m);\ - HType *ma = mz->a + sidx;\ - uint64_t *mmt = mm->a + mm->n;\ - /**fprintf(stderr, "[M::%s::] ==> +n: %d, m: %d, sn: %d, sidx: %d, eidx: %d\n", __func__, n, m, sn, sidx, eidx);**/\ - for (i = 0; i < n; i++) /**how many selected minimizers**/\ - {\ - for (k = 0, mk = -1; k < m; k++) /**how many minimizers in total**/\ - {\ - if((int32_t)(ma[k].rid) 0){\ - for (t = k-1; t >= 0 && (ma[t].pos >= ks||(int32_t)(ma[t].rid)0?(i-1)*m+t:0xffffffff)<<32;\ - else if(ks == kx) ks |= (uint64_t)(mk>=0?i*m+mk:0xffffffff)<<32;\ - GMC(mmt, i,k,m) = ks;\ - mk = k;\ - }\ - }\ - /**fprintf(stderr, "[M::%s::] ==> ++n: %d, m: %d, sn: %d, sidx: %d, eidx: %d\n", __func__, n, m, sn, sidx, eidx);**/\ - ks = (n-1)*m + mk; ix = (uint64_t)-1; kx = 0;\ - while (ks != 0xffffffff)\ - {\ - i = ks/m; k = ks%m;\ - ks = mmt[ks]>>32;\ - /**fprintf(stderr, "i: %d, k: %d, ks: %lu\n", i, k, ks);**/\ - if(ks == 0xffffffff || (int32_t)(ks/m) == (i-1)){\ - mm->a[sidx+k] = 1;\ - ix = MIN((uint64_t)k, ix); kx = MAX((uint64_t)k, kx);\ - }\ - }\ - /**debug_refine(ma, mmt, sn, n, m, (n-1)*m + mk);**/\ - if(rsi) (*rsi) = ix + sidx;\ - if(rei) (*rei) = kx + sidx;\ -}\ -void sf##_refine_sketch(VType *p, ha_pt_t *pt, int32_t rlen, int32_t dp_min_len, float er, int32_t min_freq, st_mt_t *mt, void *km)\ -{\ - /**fprintf(stderr, "[M::%s::] ==> #########10#########, rlen: %d\n", __func__, rlen);**/\ - int32_t i, n = p->n, bd, len = MIN(rlen, dp_min_len), sublen, cnt, ei, li, ri;\ - int32_t sn = len*er + 1;\ - kv_resize_km(km, uint64_t, *mt, (int64_t)p->n);\ - mt->n = p->n; memset(mt->a, 0, sizeof(uint64_t)*p->n);\ - for (i = 0; i < n; i++) p->a[i].rid = ha_pt_cnt(pt, p->a[i].x);\ - for (i = cnt = 0, bd = -1, ei = -1; i < n; i++){\ - if((int32_t)(p->a[i].rid)a[i].pos + 1;\ - if(sublen > len) break;\ - else ei = i;\ - if((int32_t)(p->a[i].pos + 1 - p->a[i].span) > bd){\ - bd = p->a[i].pos;\ - cnt++;\ - }\ - }\ - /**fprintf(stderr, "[M::%s::] ==> +cnt: %d, sn: %d, ei: %d, n: %d\n", __func__, cnt, sn, ei, n);**/\ - if(cnt >= sn) sf##_refine_select(p, 0, ei, sn, min_freq, mt, NULL, &li, km);\ - else{\ - li = i-1;\ - for (i = 0; i <= li; i++) mt->a[i] = 1;\ - }\ - if(len < rlen){\ - for (i = n-1, cnt = 0, bd = rlen+1, ei = -1; i >= 0; i--){\ - if((int32_t)(p->a[i].rid)a[i].pos + 1 - p->a[i].span);\ - if(sublen > len) break;\ - else ei = i;\ - if((int32_t)(p->a[i].pos) < bd){\ - bd = p->a[i].pos + 1 - p->a[i].span;\ - cnt++;\ - }\ - }\ - /**fprintf(stderr, "[M::%s::] ==> -cnt: %d, sn: %d, ei: %d, n: %d\n", __func__, cnt, sn, ei, n);**/\ - if(cnt >= sn) sf##_refine_select(p, ei, n-1, sn, min_freq, mt, &ri, NULL, km);\ - else {\ - ri = i+1;\ - for (i = ri; i <= n-1; i++) mt->a[i] = 1;\ - }\ - /**fprintf(stderr, "[M::%s::] ==> --cnt: %d, sn: %d, ei: %d, n: %d\n", __func__, cnt, sn, ei, n);**/\ - if(ri - li >= 2){\ - li++; ri--;\ - sn = (p->a[ri].pos - p->a[li].pos + p->a[li].span)*er + 1;\ - for (i = li, cnt = 0, bd = -1; i <= ri; i++){\ - if((int32_t)(p->a[i].rid)a[i].pos + 1 - p->a[i].span) > bd){\ - bd = p->a[i].pos;\ - cnt++;\ - if(cnt >= sn) break;\ - }\ - }\ - if(cnt >= sn) sf##_refine_select(p, li, ri, sn, min_freq, mt, NULL, NULL, km);\ - else for (i = li; i <= ri; i++) mt->a[i] = 1;\ - }\ - }\ - /**fprintf(stderr, "[M::%s::] ==> #########20#########, p->n: %u, n: %d\n", __func__, p->n, n);**/\ - for (i = sn = 0; i < n; i++){\ - if(mt->a[i]){\ - p->a[sn] = p->a[i];\ - sn++;\ - }\ - }\ - /**if(p->n != sn) fprintf(stderr, "[M::%s::] ==> #########21#########, p->n: %u, sn: %d\n", __func__, p->n, sn);**/\ - p->n = sn;\ -}\ -/**\ - * Find symmetric (w,k)-minimizers on a DNA sequence\ - *\ - * @param str DNA sequence\ - * @param len length of $str\ - * @param w find a minimizer for every $w consecutive k-mers\ - * @param k k-mer size\ - * @param rid reference ID; will be copied to the output $p array\ - * @param is_hpc homopolymer-compressed or not\ - * @param p minimizers\ - */\ -void sf##_ha_sketch(const char *str, int len, int w, int k, uint32_t rid, int is_hpc, VType *p, const void *hf, int sample_dist, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, ha_pt_t *pt, int min_freq, int32_t dp_min_len, float dp_e, st_mt_t *mt, int32_t ws, int32_t is_unique, void *km)\ -{ /**in default, w = 51, k = 51, is_hpc = 1**/\ - extern void *ha_ct_table;\ - static const HType dummy = { UINT64_MAX, (((uint64_t)1)< 0 && (int64_t)(len) < (int64_t)((((uint64_t)1)< 0 && w < 256) && (k > 0 && k <= 63));\ - if (dbg_ct != NULL) dbg_ct->a.n = 0;\ - if (k_flag != NULL) {\ - kv_resize_km(km, uint8_t, k_flag->a, (uint64_t)len);\ - k_flag->a.n = len;\ - memset(k_flag->a.a, 0, k_flag->a.n);\ - }\ - memset(buf, 0xff, w * sizeof(HType));\ - memset(&tq, 0, sizeof(tiny_queue_t));\ - /**len/w is the evaluated minimizer numbers**/\ - kv_resize_km(km, HType, *p, p->n + len/w);\ - kv_resize_km(km, uint64_t, *mt, (int64_t)p->m); mt->n = p->n;\ - for (i = l = tl = buf_pos = min_pos = 0; i < len; ++i) {\ - int c = seq_nt4_table[(uint8_t)str[i]];\ - HType info = dummy;\ - if (c < 4) { /**not an ambiguous base**/\ - int z;\ - if (is_hpc) {\ - int skip_len = 1;\ - if (i + 1 < len && seq_nt4_table[(uint8_t)str[i + 1]] == c) {\ - for (skip_len = 2; i + skip_len < len; ++skip_len)\ - if (seq_nt4_table[(uint8_t)str[i + skip_len]] != c)\ - break;\ - i += skip_len - 1; /**put $i at the end of the current homopolymer run**/\ - }\ - tq_push(&tq, skip_len);\ - kmer_span += skip_len;\ - /**how many bases that are covered by this HPC k-mer\ - kmer_span includes at most k HPC elements**/\ - if (tq.count > k) kmer_span -= tq_shift(&tq);\ - } else kmer_span = l + 1 < k? l + 1 : k;\ - /**kmer_span should be used for HPC k-mer\ - non-HPC k-mer, kmer_span should be k\ - kmer_span is used to calculate anchor pos on reverse complementary strand**/\ - if (k_flag != NULL) k_flag->a.a[i] = 1;/**lable all useful base, which are not ignored by HPC**/\ - kmer[0] = (kmer[0] << 1 | (c&1)) & mask;/**forward k-mer**/\ - kmer[1] = (kmer[1] << 1 | (c>>1)) & mask;\ - kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; /**reverse k-mer**/\ - kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1;\ - if (kmer[1] == kmer[3]) continue; /** skip "symmetric k-mers" as we don't know it strand**/\ - z = kmer[1] < kmer[3]? 0 : 1; /** strand**/\ - ++l; tl++;\ - if (l >= k && kmer_span < 256) {\ - uint64_t y;\ - int32_t cnt, filtered;\ - y = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]);\ - cnt = hf? ha_ft_cnt(hf, y) : 0;\ - filtered = (cnt >= 1<<28);\ - if(is_unique && (!filtered)) {\ - filtered = (cnt == 0);\ - cnt = (cnt == 1? 0:cnt);\ - }\ - if (dbg_ct != NULL) kv_push_km(km, uint64_t, dbg_ct->a, ((((uint64_t)(query_ct_index(ha_ct_table, y))<<1)|filtered)<<32)|(uint64_t)(i));\ - if (!filtered) info.x = y, info.rid = cnt, info.pos = i, info.rev = z, info.span = kmer_span; /** initially ha_mz1_t::rid keeps the k-mer count**/\ - if (k_flag != NULL) k_flag->a.a[i]++;\ - if (k_flag != NULL && filtered > 0) k_flag->a.a[i]++;\ - }\ - } else l = 0, tq.count = tq.front = 0, kmer_span = 0;\ - buf[buf_pos] = info; /**need to do this here as appropriate buf_pos and buf[buf_pos] are needed below**/\ - buf_p[buf_pos] = l;\ - if (l == w + k - 1 && min.x != UINT64_MAX) { /**special case for the first window - because identical k-mers are not stored yet**/\ - for (j = buf_pos + 1; j < w; ++j){\ - if (sf##_mzcmp(&min, &buf[j]) == 0 && buf[j].pos != min.pos){\ - kv_push_km(km, HType, *p, buf[j]); kv_push_km(km, uint64_t, *mt, buf_p[j]);\ - }\ - }\ - for (j = 0; j < buf_pos; ++j){\ - if (sf##_mzcmp(&min, &buf[j]) == 0 && buf[j].pos != min.pos){\ - kv_push_km(km, HType, *p, buf[j]); kv_push_km(km, uint64_t, *mt, buf_p[j]);\ - }\ - }\ - }\ - /**\ - * There are three cases:\ - * 1. info.x <= min.x, means info is a new minimizer\ - * 2. info.x > min.x, info is not a new minimizer\ - * (1) buf_pos != min_pos, do nothing\ - * (2) buf_pos == min_pos, means current minimizer has moved outside the window\ - * **/\ - /**three cases: 1.**/\ - if (sf##_mzcmp(&min, &info) >= 0) { /**a new minimum; then write the old min**/\ - if (l >= w + k && min.x != UINT64_MAX){\ - kv_push_km(km, HType, *p, min); kv_push_km(km, uint64_t, *mt, min_s);\ - }\ - min = info, min_pos = buf_pos, min_s = buf_p[buf_pos];\ - } else if (buf_pos == min_pos) { /**old min has moved outside the window**/\ - if (l >= w + k - 1 && min.x != UINT64_MAX){\ - kv_push_km(km, HType, *p, min); kv_push_km(km, uint64_t, *mt, min_s);\ - }\ - /**buf_pos == min_pos, means current minimizer has moved outside the window\ - so for now we need to find a new minimizer at the current window (w k-mers)**/\ - for (j = buf_pos + 1, min = dummy; j < w; ++j) /**the two loops are necessary when there are identical k-mers**/\ - if (sf##_mzcmp(&min, &buf[j]) >= 0) min = buf[j], min_pos = j, min_s = buf_p[j]; /** >= is important s.t. min is always the closest k-mer**/\ - for (j = 0; j <= buf_pos; ++j)\ - if (sf##_mzcmp(&min, &buf[j]) >= 0) min = buf[j], min_pos = j, min_s = buf_p[j];\ - if (l >= w + k - 1 && min.x != UINT64_MAX) { /**write identical k-mers**/\ - for (j = buf_pos + 1; j < w; ++j) /**these two loops make sure the output is sorted**/\ - if (sf##_mzcmp(&min, &buf[j]) == 0 && min.pos != buf[j].pos){\ - kv_push_km(km, HType, *p, buf[j]); kv_push_km(km, uint64_t, *mt, buf_p[j]);\ - }\ - for (j = 0; j <= buf_pos; ++j)\ - if (sf##_mzcmp(&min, &buf[j]) == 0 && min.pos != buf[j].pos){\ - kv_push_km(km, HType, *p, buf[j]); kv_push_km(km, uint64_t, *mt, buf_p[j]);\ - }\ - }\ - }\ - if (++buf_pos == w) buf_pos = 0;\ - }\ - if (min.x != UINT64_MAX){\ - kv_push_km(km, HType, *p, min); kv_push_km(km, uint64_t, *mt, min_s);\ - }\ - /**debug_pl(str, len, w, k, is_hpc, p, hf, mt);**/\ - if (sample_dist > w) sf##_select_mz_h(p, mt, len, sample_dist, ws, k, tl);\ - if (dp_min_len > 0 && pt && mt) sf##_refine_sketch(p, pt, len, dp_min_len, dp_e, min_freq, mt, km);\ - for (i = 0; i < (int)p->n; ++i) /**populate .rid as this was keeping counts**/\ - p->a[i].rid = rid;\ -} - -HA_SC_INIT(mz1, ha_mz1_t, ha_mz1_v, 28, 27) +#include +#include +#include +#include +#include "kvec.h" +#include "htab.h" +#include "ksort.h" +#include "Correct.h" +#include "kalloc.h" + +#define MAX_HIGH_OCC 8 // TODO: don't hard code if we need to tune this parameter +#define MAX_MAX_HIGH_OCC 16 +#define GMC(a, x,y,xn) ((a)[(x)*(xn)+(y)]) +#define GL(x, i) ((int64_t)((uint32_t)((x).a[(i)]))) +#define A_M(p, i) ((i) >= 0 && (p).a[(i)].rid > 0) + +void debug_refine(ha_mz1_t *ma, uint64_t *mmt, int32_t sn, int32_t n, int32_t m, int32_t end) +{ + uint64_t ks = end; + int64_t t = 0, i, k, sp = -1, ep = -1, ovlp, tot = mmt[end]&0xffffffff, nt = 0;; + while (ks != 0xffffffff) + { + i = ks/m; k = ks%m; + ks = mmt[ks]>>32; + if(ks == 0xffffffff || (int32_t)(ks/m) == (i-1)) + { + t++; + ovlp = ((MIN(ep, (int64_t)ma[k].pos) >= MAX(sp, (int64_t)(ma[k].pos+1-ma[k].span)))? + MIN(ep, (int64_t)ma[k].pos) - MAX(sp, (int64_t)(ma[k].pos+1-ma[k].span)) + 1:0); + if(ovlp != 0) fprintf(stderr, "ERROR-OVLP\n"); + if(sp == -1 || sp > (ma[k].pos+1-ma[k].span)) sp = ma[k].pos+1-ma[k].span; + if(ep == -1 || ep < ma[k].pos) ep = ma[k].pos; + nt += (ma[k].rid); + } + } + if(t != sn) fprintf(stderr, "ERROR-TN, t: %ld, sn: %d\n", t, sn); + if(nt != tot) fprintf(stderr, "ERROR-TOT, nt: %ld, tot: %ld\n", nt, tot); +} + +void dbg_boundary(ha_mz1_v *p, st_mt_t *mt, int32_t w, int32_t k, int32_t tot_l) +{ + if(tot_l < w + k -1) return; + int32_t i, m, n = p->n, s, a; + for (i = 0; i < n; i++){ + if(GL(*mt, i) >= w+k-1){ + for (m = s = a = 0; m <= i; m++){ + if(!A_M(*p, m)) continue; + if(GL(*mt, m) <= w+k-1){ + a++; + if(mt->a[m]&0x100000000) s++; + } + } + if(a > 0 && s == 0){ + fprintf(stderr, "\nERROR1, s: %d, n: %d, tot_l: %d, end_l: %ld\n", s, n, tot_l, GL(*mt, i)); + for (m = s = a = 0; m <= i; m++){ + if(!A_M(*p, m)) continue; + if(GL(*mt, m) <= w+k-1){ + fprintf(stderr, "lp: %ld\n", GL(*mt, m)); + a++; + if(mt->a[m]&0x100000000) s++; + } + } + + } + + break; + } + } + if(i == n){ + for (m = s = a = 0; m < n; m++){ + if(!A_M(*p, m)) continue; + if(GL(*mt, m) <= w+k-1){ + a++; + if(mt->a[m]&0x100000000) s++; + } + } + if(a > 0 && s == 0) fprintf(stderr, "ERROR2\n"); + } + + for (i = n-1; i >= 0; i--) + { + if (GL(*mt, i) + w <= tot_l + 1) { + for (m = i, s = a = 0; m < n; m++){ + if(!A_M(*p, m)) continue; + if(GL(*mt, m) + w >= tot_l + 1){ + a++; + if(mt->a[m]&0x100000000) s++; + } + } + if(a > 0 && s == 0) { + fprintf(stderr, "\nERROR3, s: %d, n: %d, tot_l: %d, end_l: %ld\n", s, n, tot_l, GL(*mt, i)); + for (m = i, s = a = 0; m < n; m++){ + if(!A_M(*p, m)) continue; + if(GL(*mt, m) + w >= tot_l + 1){ + fprintf(stderr, "lp: %ld\n", GL(*mt, m)); + a++; + if(mt->a[m]&0x100000000) s++; + } + } + } + + break; + } + } + + if(i < 0){ + for (m = s = a = 0; m < n; m++){ + if(!A_M(*p, m)) continue; + if(GL(*mt, m) + w >= tot_l + 1){ + a++; + if(mt->a[m]&0x100000000) s++; + } + } + if(a > 0 && s == 0) fprintf(stderr, "ERROR4\n"); + } +} + +void debug_pl(const char *str, int len, int w, int k, int is_hpc, ha_mz1_v *p, const void *hf, st_mt_t *mt) +{ + int i, l, dbi, dbcnt = 0, kmer_span = 0; + tiny_queue_t tq; + memset(&tq, 0, sizeof(tiny_queue_t)); + uint64_t shift1 = k - 1, mask = (1ULL< k) kmer_span -= tq_shift(&tq); + } else kmer_span = l + 1 < k? l + 1 : k; + ///kmer_span should be used for HPC k-mer + ///non-HPC k-mer, kmer_span should be k + ///kmer_span is used to calculate anchor pos on reverse complementary strand + + kmer[0] = (kmer[0] << 1 | (c&1)) & mask; // forward k-mer + kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; + kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; // reverse k-mer + kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; + if (kmer[1] == kmer[3]) continue; // skip "symmetric k-mers" as we don't know it strand + z = kmer[1] < kmer[3]? 0 : 1; // strand + ++l; + + if (l >= k && kmer_span < 256) { + uint64_t y; + int32_t cnt; + y = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); + cnt = hf? ha_ft_cnt(hf, y) : 0; + + for (dbi = 0; dbi < (int32_t)mt->n; dbi++) + { + if(p->a[dbi].x == y && p->a[dbi].rid == cnt && p->a[dbi].pos == i && p->a[dbi].rev == z && p->a[dbi].span == kmer_span) + { + if(l != (int)mt->a[dbi]) fprintf(stderr, "ERROR\n"); + dbcnt++; + } + } + } + } else l = 0, tq.count = tq.front = 0, kmer_span = 0; + } + + if(dbcnt != (int32_t)mt->n) fprintf(stderr, "ERROR\n"); + if(mt->n != p->n) fprintf(stderr, "ERROR\n"); + for (dbi = 1; dbi < (int32_t)mt->n; dbi++) + { + if(p->a[dbi].pos <= p->a[dbi-1].pos || (int)mt->a[dbi] <= (int)mt->a[dbi-1]) + { + fprintf(stderr, "ERROR\n"); + } + } +} + +static inline int mz1_mzcmp(const ha_mz1_t *a, const ha_mz1_t *b){return a->rid < b->rid? -1 : a->rid > b->rid? 1 : ((a->x > b->x) - (a->x < b->x));} +#define mz1_mz_lt(a, b) (mz1_mzcmp(&(a), &(b)) < 0) +KSORT_INIT(mz1_mz, ha_mz1_t, mz1_mz_lt) + +static inline int mz2_mzcmp(const ha_mzl_t *a, const ha_mzl_t *b){return a->rid < b->rid? -1 : a->rid > b->rid? 1 : ((a->x > b->x) - (a->x < b->x));} +#define mz2_mz_lt(a, b) (mz2_mzcmp(&(a), &(b)) < 0) +KSORT_INIT(mz2_mz, ha_mzl_t, mz2_mz_lt) + + +#define HA_SC_INIT(sf, HType, VType, RidBits, PosBits)\ +inline void sf##_hf_select(VType *p, int32_t si, int32_t ei, int32_t n, int32_t len, int32_t sample_dist, HType *b, int32_t force)\ +{\ + if(ei - si <= 1) return;\ + int32_t ps = si < 0? 0 : p->a[si].pos;\ + int32_t pe = ei == n? len : p->a[ei].pos;\ + int32_t j, k, st = si + 1, en = ei;\ + int32_t max_high_occ = (int32_t)((double)(pe - ps) / sample_dist + .499);\ + if (max_high_occ > MAX_MAX_HIGH_OCC)\ + max_high_occ = MAX_MAX_HIGH_OCC;\ + for (j = st, k = 0; j < en && k < max_high_occ; ++j, ++k)\ + b[k] = p->a[j], b[k].pos = j; /** b[].pos keeps the index in p->a[]**/\ + ks_heapmake_##sf##_mz(k, b); /** initialize the binomial heap**/\ + for (; j < en; ++j) { /** if there are more, choose top max_high_occ**/\ + if (sf##_mz_lt(p->a[j], b[0])) { /** then update the heap**/\ + b[0] = p->a[j], b[0].pos = j;\ + ks_heapdown_##sf##_mz(0, k, b);\ + }\ + }\ + /**ks_heapsort_mz(k, b); // sorting is not needed for now**/\ + for (j = 0; j < k; ++j)\ + if (b[j].rid < pe - ps || force)\ + p->a[b[j].pos].rid = 0;\ +}\ +static inline int sf##_mzcmp_l(const VType *p, int32_t ai, int32_t bi)\ +{\ + if(ai >= 0 && bi >= 0){\ + HType *a = &(p->a[ai]), *b = &(p->a[bi]);\ + if(a->rid > 0 && b->rid > 0) return sf##_mzcmp(a, b);\ + return (a->rid == 0) - (b->rid == 0);\ + }\ + return (ai < 0) - (bi < 0);\ +}\ +int32_t sf##_qfw(VType *p, st_mt_t *mt, int32_t n, int32_t tot_l, int32_t ws, int32_t i, int32_t *mi)\ +{\ + int32_t m, si;\ + for (si = i, (*mi) = -1; i < n; i++){\ + if(GL(*mt, i) >= ws || (i+1 < n && GL(*mt, i) < ws && GL(*mt, i+1) > ws) || \ + (i+1 == n && tot_l >= ws && GL(*mt, i) < ws)){\ + for (m = si; m <= i; m++){\ + if(!A_M(*p, m)) continue;\ + if(sf##_mzcmp_l(p, *mi, m) >= 0) (*mi) = m;\ + }\ + if((*mi) >= 0 && A_M(*p, *mi)){\ + for (m = si; m <= i; m++){\ + if(!A_M(*p, m)) continue;\ + if(sf##_mzcmp_l(p, *mi, m) == 0) mt->a[m] |= 0x100000000;\ + }\ + }\ + break;\ + }\ + }\ + return i;\ +}\ +static void sf##_select_mz_h(VType *p, st_mt_t *mt, int len, int sample_dist, int32_t w, int32_t k, int32_t tot_l)\ +{ /**for high-occ minimizers, choose up to max_high_occ in each high-occ streak**/\ + int32_t i, mi = -1, si, last0 = -1, n = (int32_t)p->n, m = 0, ws = w + k - 1;\ + if (n == 0) return;\ + assert((int64_t)(n) < (int64_t)((((uint64_t)1)<a[i].rid == 0) {\ + if (i - last0 > 1) {\ + int32_t ps = last0 < 0? 0 : p->a[last0].pos;\ + int32_t pe = i == n? len : p->a[i].pos;\ + if(((int32_t)((double)(pe - ps) / sample_dist + .499)) > 0){\ + last0 = -2;\ + m++;\ + break;\ + }\ + }\ + last0 = i;\ + }\ + }\ + if (m == 0) return; /**no high-frequency k-mers; do nothing**/\ + if(last0 >= -1) goto sf##_ff;\ + i = 0;\ + i = sf##_qfw(p, mt, n, tot_l, ws, i, &mi);\ + if(i == n) goto sf##_ff;\ + for (si = 0, i++; i < n; i++){\ + for (; si < i; si++){\ + if(GL(*mt, si) + w > GL(*mt, i)) break;\ + }\ + /**a new minimum; then write the old min**/\ + if(sf##_mzcmp_l(p, i, mi) <= 0) {\ + if(A_M(*p, mi)) mt->a[mi] |= 0x100000000;\ + mi = i;\ + }/**old min has moved outside the window**/\ + else if(si > mi){\ + if(A_M(*p, mi)) mt->a[mi] |= 0x100000000;\ + for (m = si, mi = -1; m <= i; m++){\ + if(sf##_mzcmp_l(p, mi, m) >= 0) mi = m;\ + }\ + if(A_M(*p, mi)){\ + for (m = si; m <= i; m++){\ + if(!A_M(*p, m)) continue;\ + if(sf##_mzcmp_l(p, mi, m) == 0) mt->a[m] |= 0x100000000;\ + }\ + }\ + }\ + }\ + if(A_M(*p, mi)) mt->a[mi] |= 0x100000000;\ + for (i = n - 1; si < n && GL(*mt, si) + w <= tot_l + 1; si++){\ + if(si > mi){\ + if(A_M(*p, mi)) mt->a[mi] |= 0x100000000;\ + for (m = si, mi = -1; m <= i; m++){\ + if(sf##_mzcmp_l(p, mi, m) >= 0) mi = m;\ + }\ + if(A_M(*p, mi)){\ + for (m = si; m <= i; m++){\ + if(!A_M(*p, m)) continue;\ + if(sf##_mzcmp_l(p, mi, m) == 0) mt->a[m] |= 0x100000000;\ + }\ + }\ + }\ + }\ + /**dbg_boundary(p, mt, w, k, tot_l);**/\ + HType b[MAX_MAX_HIGH_OCC];\ + for (i = 0, last0 = -1; i <= n; ++i) {\ + if (i == n || p->a[i].rid == 0) {\ + if (i - last0 > 1) {\ + int32_t ps = last0 < 0? 0 : p->a[last0].pos;\ + int32_t pe = i == n? len : p->a[i].pos;\ + if(((int32_t)((double)(pe - ps) / sample_dist + .499)) > 0){\ + for (m = last0 + 1, mi = 0; m < i; ++m){\ + if(mt->a[m]&0x100000000) p->a[m].rid = 0, mi++;\ + }\ + if(mi == 0) sf##_hf_select(p, last0, i, n, len, sample_dist, b, 0);\ + }\ + }\ + last0 = i;\ + }\ + }\ + sf##_ff:\ + for (i = n = 0; i < (int32_t)p->n; ++i) /**squeeze out filtered minimizers**/\ + if (p->a[i].rid == 0)\ + p->a[n++] = p->a[i];\ + p->n = n;\ +}\ +void sf##_refine_select(VType *mz, int32_t sidx, int32_t eidx, int32_t sn, int32_t min_freq, st_mt_t *mm, int32_t *rsi, int32_t *rei, void *km)\ +{\ + int32_t n = sn, m = eidx + 1 - sidx, i, k, t, mk=-1;\ + uint64_t ix, kx, ks;\ + kv_resize_km(km, uint64_t, *mm, mm->n+n*m);\ + HType *ma = mz->a + sidx;\ + uint64_t *mmt = mm->a + mm->n;\ + /**fprintf(stderr, "[M::%s::] ==> +n: %d, m: %d, sn: %d, sidx: %d, eidx: %d\n", __func__, n, m, sn, sidx, eidx);**/\ + for (i = 0; i < n; i++) /**how many selected minimizers**/\ + {\ + for (k = 0, mk = -1; k < m; k++) /**how many minimizers in total**/\ + {\ + if((int32_t)(ma[k].rid) 0){\ + for (t = k-1; t >= 0 && (ma[t].pos >= ks||(int32_t)(ma[t].rid)0?(i-1)*m+t:0xffffffff)<<32;\ + else if(ks == kx) ks |= (uint64_t)(mk>=0?i*m+mk:0xffffffff)<<32;\ + GMC(mmt, i,k,m) = ks;\ + mk = k;\ + }\ + }\ + /**fprintf(stderr, "[M::%s::] ==> ++n: %d, m: %d, sn: %d, sidx: %d, eidx: %d\n", __func__, n, m, sn, sidx, eidx);**/\ + ks = (n-1)*m + mk; ix = (uint64_t)-1; kx = 0;\ + while (ks != 0xffffffff)\ + {\ + i = ks/m; k = ks%m;\ + ks = mmt[ks]>>32;\ + /**fprintf(stderr, "i: %d, k: %d, ks: %lu\n", i, k, ks);**/\ + if(ks == 0xffffffff || (int32_t)(ks/m) == (i-1)){\ + mm->a[sidx+k] = 1;\ + ix = MIN((uint64_t)k, ix); kx = MAX((uint64_t)k, kx);\ + }\ + }\ + /**debug_refine(ma, mmt, sn, n, m, (n-1)*m + mk);**/\ + if(rsi) (*rsi) = ix + sidx;\ + if(rei) (*rei) = kx + sidx;\ +}\ +void sf##_refine_sketch(VType *p, ha_pt_t *pt, int32_t rlen, int32_t dp_min_len, float er, int32_t min_freq, st_mt_t *mt, void *km)\ +{\ + /**fprintf(stderr, "[M::%s::] ==> #########10#########, rlen: %d\n", __func__, rlen);**/\ + int32_t i, n = p->n, bd, len = MIN(rlen, dp_min_len), sublen, cnt, ei, li, ri;\ + int32_t sn = len*er + 1;\ + kv_resize_km(km, uint64_t, *mt, (int64_t)p->n);\ + mt->n = p->n; memset(mt->a, 0, sizeof(uint64_t)*p->n);\ + for (i = 0; i < n; i++) p->a[i].rid = ha_pt_cnt(pt, p->a[i].x);\ + for (i = cnt = 0, bd = -1, ei = -1; i < n; i++){\ + if((int32_t)(p->a[i].rid)a[i].pos + 1;\ + if(sublen > len) break;\ + else ei = i;\ + if((int32_t)(p->a[i].pos + 1 - p->a[i].span) > bd){\ + bd = p->a[i].pos;\ + cnt++;\ + }\ + }\ + /**fprintf(stderr, "[M::%s::] ==> +cnt: %d, sn: %d, ei: %d, n: %d\n", __func__, cnt, sn, ei, n);**/\ + if(cnt >= sn) sf##_refine_select(p, 0, ei, sn, min_freq, mt, NULL, &li, km);\ + else{\ + li = i-1;\ + for (i = 0; i <= li; i++) mt->a[i] = 1;\ + }\ + if(len < rlen){\ + for (i = n-1, cnt = 0, bd = rlen+1, ei = -1; i >= 0; i--){\ + if((int32_t)(p->a[i].rid)a[i].pos + 1 - p->a[i].span);\ + if(sublen > len) break;\ + else ei = i;\ + if((int32_t)(p->a[i].pos) < bd){\ + bd = p->a[i].pos + 1 - p->a[i].span;\ + cnt++;\ + }\ + }\ + /**fprintf(stderr, "[M::%s::] ==> -cnt: %d, sn: %d, ei: %d, n: %d\n", __func__, cnt, sn, ei, n);**/\ + if(cnt >= sn) sf##_refine_select(p, ei, n-1, sn, min_freq, mt, &ri, NULL, km);\ + else {\ + ri = i+1;\ + for (i = ri; i <= n-1; i++) mt->a[i] = 1;\ + }\ + /**fprintf(stderr, "[M::%s::] ==> --cnt: %d, sn: %d, ei: %d, n: %d\n", __func__, cnt, sn, ei, n);**/\ + if(ri - li >= 2){\ + li++; ri--;\ + sn = (p->a[ri].pos - p->a[li].pos + p->a[li].span)*er + 1;\ + for (i = li, cnt = 0, bd = -1; i <= ri; i++){\ + if((int32_t)(p->a[i].rid)a[i].pos + 1 - p->a[i].span) > bd){\ + bd = p->a[i].pos;\ + cnt++;\ + if(cnt >= sn) break;\ + }\ + }\ + if(cnt >= sn) sf##_refine_select(p, li, ri, sn, min_freq, mt, NULL, NULL, km);\ + else for (i = li; i <= ri; i++) mt->a[i] = 1;\ + }\ + }\ + /**fprintf(stderr, "[M::%s::] ==> #########20#########, p->n: %u, n: %d\n", __func__, p->n, n);**/\ + for (i = sn = 0; i < n; i++){\ + if(mt->a[i]){\ + p->a[sn] = p->a[i];\ + sn++;\ + }\ + }\ + /**if(p->n != sn) fprintf(stderr, "[M::%s::] ==> #########21#########, p->n: %u, sn: %d\n", __func__, p->n, sn);**/\ + p->n = sn;\ +}\ +/**\ + * Find symmetric (w,k)-minimizers on a DNA sequence\ + *\ + * @param str DNA sequence\ + * @param len length of $str\ + * @param w find a minimizer for every $w consecutive k-mers\ + * @param k k-mer size\ + * @param rid reference ID; will be copied to the output $p array\ + * @param is_hpc homopolymer-compressed or not\ + * @param p minimizers\ + */\ +void sf##_ha_sketch(const char *str, int len, int w, int k, uint32_t rid, int is_hpc, VType *p, const void *hf, int sample_dist, kvec_t_u8_warp* k_flag, kvec_t_u64_warp* dbg_ct, ha_pt_t *pt, int min_freq, int32_t dp_min_len, float dp_e, st_mt_t *mt, int32_t ws, int32_t is_unique, void *km)\ +{ /**in default, w = 51, k = 51, is_hpc = 1**/\ + extern void *ha_ct_table;\ + static const HType dummy = { UINT64_MAX, (((uint64_t)1)< 0 && (int64_t)(len) < (int64_t)((((uint64_t)1)< 0 && w < 256) && (k > 0 && k <= 63));\ + if (dbg_ct != NULL) dbg_ct->a.n = 0;\ + if (k_flag != NULL) {\ + kv_resize_km(km, uint8_t, k_flag->a, (uint64_t)len);\ + k_flag->a.n = len;\ + memset(k_flag->a.a, 0, k_flag->a.n);\ + }\ + memset(buf, 0xff, w * sizeof(HType));\ + memset(&tq, 0, sizeof(tiny_queue_t));\ + /**len/w is the evaluated minimizer numbers**/\ + kv_resize_km(km, HType, *p, p->n + len/w);\ + kv_resize_km(km, uint64_t, *mt, (int64_t)p->m); mt->n = p->n;\ + for (i = l = tl = buf_pos = min_pos = 0; i < len; ++i) {\ + int c = seq_nt4_table[(uint8_t)str[i]];\ + HType info = dummy;\ + if (c < 4) { /**not an ambiguous base**/\ + int z;\ + if (is_hpc) {\ + int skip_len = 1;\ + if (i + 1 < len && seq_nt4_table[(uint8_t)str[i + 1]] == c) {\ + for (skip_len = 2; i + skip_len < len; ++skip_len)\ + if (seq_nt4_table[(uint8_t)str[i + skip_len]] != c)\ + break;\ + i += skip_len - 1; /**put $i at the end of the current homopolymer run**/\ + }\ + tq_push(&tq, skip_len);\ + kmer_span += skip_len;\ + /**how many bases that are covered by this HPC k-mer\ + kmer_span includes at most k HPC elements**/\ + if (tq.count > k) kmer_span -= tq_shift(&tq);\ + } else kmer_span = l + 1 < k? l + 1 : k;\ + /**kmer_span should be used for HPC k-mer\ + non-HPC k-mer, kmer_span should be k\ + kmer_span is used to calculate anchor pos on reverse complementary strand**/\ + if (k_flag != NULL) k_flag->a.a[i] = 1;/**lable all useful base, which are not ignored by HPC**/\ + kmer[0] = (kmer[0] << 1 | (c&1)) & mask;/**forward k-mer**/\ + kmer[1] = (kmer[1] << 1 | (c>>1)) & mask;\ + kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; /**reverse k-mer**/\ + kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1;\ + if (kmer[1] == kmer[3]) continue; /** skip "symmetric k-mers" as we don't know it strand**/\ + z = kmer[1] < kmer[3]? 0 : 1; /** strand**/\ + ++l; tl++;\ + if (l >= k && kmer_span < 256) {\ + uint64_t y;\ + int32_t cnt, filtered;\ + y = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]);\ + cnt = hf? ha_ft_cnt(hf, y) : 0;\ + filtered = (cnt >= 1<<28);\ + if(is_unique && (!filtered)) {\ + filtered = (cnt == 0);\ + cnt = (cnt == 1? 0:cnt);\ + }\ + if (dbg_ct != NULL) kv_push_km(km, uint64_t, dbg_ct->a, ((((uint64_t)(query_ct_index(ha_ct_table, y))<<1)|filtered)<<32)|(uint64_t)(i));\ + if (!filtered) info.x = y, info.rid = cnt, info.pos = i, info.rev = z, info.span = kmer_span; /** initially ha_mz1_t::rid keeps the k-mer count**/\ + if (k_flag != NULL) k_flag->a.a[i]++;\ + if (k_flag != NULL && filtered > 0) k_flag->a.a[i]++;\ + }\ + } else l = 0, tq.count = tq.front = 0, kmer_span = 0;\ + buf[buf_pos] = info; /**need to do this here as appropriate buf_pos and buf[buf_pos] are needed below**/\ + buf_p[buf_pos] = l;\ + if (l == w + k - 1 && min.x != UINT64_MAX) { /**special case for the first window - because identical k-mers are not stored yet**/\ + for (j = buf_pos + 1; j < w; ++j){\ + if (sf##_mzcmp(&min, &buf[j]) == 0 && buf[j].pos != min.pos){\ + kv_push_km(km, HType, *p, buf[j]); kv_push_km(km, uint64_t, *mt, buf_p[j]);\ + }\ + }\ + for (j = 0; j < buf_pos; ++j){\ + if (sf##_mzcmp(&min, &buf[j]) == 0 && buf[j].pos != min.pos){\ + kv_push_km(km, HType, *p, buf[j]); kv_push_km(km, uint64_t, *mt, buf_p[j]);\ + }\ + }\ + }\ + /**\ + * There are three cases:\ + * 1. info.x <= min.x, means info is a new minimizer\ + * 2. info.x > min.x, info is not a new minimizer\ + * (1) buf_pos != min_pos, do nothing\ + * (2) buf_pos == min_pos, means current minimizer has moved outside the window\ + * **/\ + /**three cases: 1.**/\ + if (sf##_mzcmp(&min, &info) >= 0) { /**a new minimum; then write the old min**/\ + if (l >= w + k && min.x != UINT64_MAX){\ + kv_push_km(km, HType, *p, min); kv_push_km(km, uint64_t, *mt, min_s);\ + }\ + min = info, min_pos = buf_pos, min_s = buf_p[buf_pos];\ + } else if (buf_pos == min_pos) { /**old min has moved outside the window**/\ + if (l >= w + k - 1 && min.x != UINT64_MAX){\ + kv_push_km(km, HType, *p, min); kv_push_km(km, uint64_t, *mt, min_s);\ + }\ + /**buf_pos == min_pos, means current minimizer has moved outside the window\ + so for now we need to find a new minimizer at the current window (w k-mers)**/\ + for (j = buf_pos + 1, min = dummy; j < w; ++j) /**the two loops are necessary when there are identical k-mers**/\ + if (sf##_mzcmp(&min, &buf[j]) >= 0) min = buf[j], min_pos = j, min_s = buf_p[j]; /** >= is important s.t. min is always the closest k-mer**/\ + for (j = 0; j <= buf_pos; ++j)\ + if (sf##_mzcmp(&min, &buf[j]) >= 0) min = buf[j], min_pos = j, min_s = buf_p[j];\ + if (l >= w + k - 1 && min.x != UINT64_MAX) { /**write identical k-mers**/\ + for (j = buf_pos + 1; j < w; ++j) /**these two loops make sure the output is sorted**/\ + if (sf##_mzcmp(&min, &buf[j]) == 0 && min.pos != buf[j].pos){\ + kv_push_km(km, HType, *p, buf[j]); kv_push_km(km, uint64_t, *mt, buf_p[j]);\ + }\ + for (j = 0; j <= buf_pos; ++j)\ + if (sf##_mzcmp(&min, &buf[j]) == 0 && min.pos != buf[j].pos){\ + kv_push_km(km, HType, *p, buf[j]); kv_push_km(km, uint64_t, *mt, buf_p[j]);\ + }\ + }\ + }\ + if (++buf_pos == w) buf_pos = 0;\ + }\ + if (min.x != UINT64_MAX){\ + kv_push_km(km, HType, *p, min); kv_push_km(km, uint64_t, *mt, min_s);\ + }\ + /**debug_pl(str, len, w, k, is_hpc, p, hf, mt);**/\ + if (sample_dist > w) sf##_select_mz_h(p, mt, len, sample_dist, ws, k, tl);\ + if (dp_min_len > 0 && pt && mt) sf##_refine_sketch(p, pt, len, dp_min_len, dp_e, min_freq, mt, km);\ + for (i = 0; i < (int)p->n; ++i) /**populate .rid as this was keeping counts**/\ + p->a[i].rid = rid;\ +} + +HA_SC_INIT(mz1, ha_mz1_t, ha_mz1_v, 28, 27) HA_SC_INIT(mz2, ha_mzl_t, ha_mzl_v, 31, 32) \ No newline at end of file diff --git a/sys.cpp b/sys.cpp index 8dbe050..fc15a15 100644 --- a/sys.cpp +++ b/sys.cpp @@ -1,59 +1,59 @@ -#include -#include -#include "htab.h" - -int yak_verbose = 3; - -static double yak_realtime0; - -double yak_cputime(void) -{ - struct rusage r; - getrusage(RUSAGE_SELF, &r); - return r.ru_utime.tv_sec + r.ru_stime.tv_sec + 1e-6 * (r.ru_utime.tv_usec + r.ru_stime.tv_usec); -} - -static inline double yak_realtime_core(void) -{ - struct timeval tp; - struct timezone tzp; - gettimeofday(&tp, &tzp); - return tp.tv_sec + tp.tv_usec * 1e-6; -} - -void yak_reset_realtime(void) -{ - yak_realtime0 = yak_realtime_core(); -} - -double yak_realtime(void) -{ - return yak_realtime_core() - yak_realtime0; -} - -double yak_realtime_0(void) -{ - return yak_realtime_core(); -} - - -long yak_peakrss(void) -{ - struct rusage r; - getrusage(RUSAGE_SELF, &r); -#ifdef __linux__ - return r.ru_maxrss * 1024; -#else - return r.ru_maxrss; -#endif -} - -double yak_peakrss_in_gb(void) -{ - return yak_peakrss() / 1073741824.0; -} - -double yak_cpu_usage(void) -{ - return (yak_cputime() + 1e-9) / (yak_realtime() + 1e-9); -} +#include +#include +#include "htab.h" + +int yak_verbose = 3; + +static double yak_realtime0; + +double yak_cputime(void) +{ + struct rusage r; + getrusage(RUSAGE_SELF, &r); + return r.ru_utime.tv_sec + r.ru_stime.tv_sec + 1e-6 * (r.ru_utime.tv_usec + r.ru_stime.tv_usec); +} + +static inline double yak_realtime_core(void) +{ + struct timeval tp; + struct timezone tzp; + gettimeofday(&tp, &tzp); + return tp.tv_sec + tp.tv_usec * 1e-6; +} + +void yak_reset_realtime(void) +{ + yak_realtime0 = yak_realtime_core(); +} + +double yak_realtime(void) +{ + return yak_realtime_core() - yak_realtime0; +} + +double yak_realtime_0(void) +{ + return yak_realtime_core(); +} + + +long yak_peakrss(void) +{ + struct rusage r; + getrusage(RUSAGE_SELF, &r); +#ifdef __linux__ + return r.ru_maxrss * 1024; +#else + return r.ru_maxrss; +#endif +} + +double yak_peakrss_in_gb(void) +{ + return yak_peakrss() / 1073741824.0; +} + +double yak_cpu_usage(void) +{ + return (yak_cputime() + 1e-9) / (yak_realtime() + 1e-9); +} diff --git a/tovlp.cpp b/tovlp.cpp index 55923cc..e7bc85a 100644 --- a/tovlp.cpp +++ b/tovlp.cpp @@ -1,1943 +1,1943 @@ -#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" -#include "tovlp.h" -#include "hic.h" -KSEQ_INIT(gzFile, gzread) -KDQ_INIT(uint64_t) - - -typedef struct { - kvec_t_u32_warp tt; - kvec_t_u32_warp stack; - uint8_t *vis; - pdq pq_p; - pdq pq_a; - buf_t b; - uint32_t min_v, offset1, offset2; - long long min_d; - int is_b; -} clean_t; - -typedef struct { - clean_t *a; - size_t n, m; - uint64_t max_dist; - uint8_t *bs_flag, fp, fa; - asg_t *g; - ma_ug_t *ug; -} clean_mul_t; - -clean_mul_t *init_clean_mul_t(asg_t *g, ma_ug_t *ug, uint64_t n_threads, uint8_t fp, uint8_t fa) -{ - uint32_t i; - clean_t *kt = NULL; - clean_mul_t *p = NULL; CALLOC(p, 1); - p->g = g; p->ug = ug; - CALLOC(p->bs_flag, p->g->n_seq<<1); - p->n = p->m = n_threads; - CALLOC(p->a, p->n); - for (i = 0, kt = NULL; i < p->n; i++) - { - kt = &(p->a[i]); - kv_init(kt->tt.a); kv_init(kt->stack.a); - CALLOC(kt->vis, p->g->n_seq<<1); - init_pdq(&kt->pq_p, p->g->n_seq<<1); - init_pdq(&kt->pq_a, p->g->n_seq<<1); - memset(&kt->b, 0, sizeof(kt->b)); - kt->b.a = (binfo_t*)calloc(p->g->n_seq<<1, sizeof(binfo_t)); - } - p->max_dist = get_bub_pop_max_dist_advance(g, &kt->b); - p->fp = fp; p->fa = fa; - return p; -} - -void destroy_clean_mul_t(clean_mul_t **p) -{ - uint32_t i; - clean_t *kt = NULL; - free((*p)->bs_flag); - for (i = 0; i < (*p)->n; i++) - { - kt = &((*p)->a[i]); - kv_destroy(kt->tt.a); - kv_destroy(kt->stack.a); - free(kt->vis); - destory_pdq(&kt->pq_p); - destory_pdq(&kt->pq_a); - free(kt->b.a); free(kt->b.S.a); free(kt->b.T.a); free(kt->b.b.a); free(kt->b.e.a); - } - free((*p)->a); - free((*p)); -} - -utg_trans_t *init_utg_trans_t(ma_ug_t *ug, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, asg_t *read_g, int max_hang, int min_ovlp) -{ - utg_trans_t *o = NULL; - CALLOC(o, 1); - o->reverse_sources = reverse_sources; - o->coverage_cut = coverage_cut; - o->ruIndex = ruIndex; - o->read_g = read_g; - o->rn = read_g->n_seq; - memset(&(o->b0), 0, sizeof(o->b0)); - memset(&(o->b1), 0, sizeof(o->b1)); - MALLOC(o->pos_idx, o->rn); memset(o->pos_idx, -1, o->rn*sizeof(uint64_t)); - o->cug = copy_untig_graph(ug); - o->max_hang = max_hang; - o->min_ovlp = min_ovlp; - return o; -} - -void destroy_utg_trans_t(utg_trans_t **o) -{ - ; -} - -uint64_t get_utg_chain_length(ma_ug_t *ug, uint32_t *a, uint32_t a_n) -{ - uint64_t i, k, l, qn, v, w, nv, offset; - asg_arc_t *av = NULL; - for (i = 0, offset = 0; i < a_n; i++) - { - qn = a[i]>>1; - l = ug->g->seq[qn].len; - if(i + 1 < a_n) - { - v = a[i]; w = a[i+1]; - av = asg_arc_a(ug->g, v); - nv = asg_arc_n(ug->g, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - l = asg_arc_len(av[k]); - break; - } - } - if(k >= nv) fprintf(stderr, "ERROR-mc\n"); - } - offset += l; - } - return offset; -} - -void refine_utg_thit_t(utg_thit_t *q, kv_ca_buf_t* cb) -{ - ///already know [qScur, qEcur), [qSpre, qEpre) - uint32_t s, e, i, si, ei; - s = q->qs; e = q->qe;///[s, e) - for (i = 0, si = ei = cb->n; i < cb->n; i++) - { - if(cb->a[i].c_x_p > s && si == cb->n) - { - si = i; - } - - if(cb->a[i].c_x_p > (e-1) && ei == cb->n) - { - ei = i; - } - - if(si != cb->n && ei != cb->n) break; - } - - if(si == 0 || ei == 0) fprintf(stderr, "ERROR-si-ei-0\n"); - if(si >= cb->n || ei >= cb->n) fprintf(stderr, "ERROR-si-ei-1\n"); - si--; ei--; - - if(s < cb->a[si].c_x_p || ((si + 1) < cb->n && s >= cb->a[si + 1].c_x_p)) - { - fprintf(stderr, "ERROR3\n"); - } - if(e < cb->a[ei].c_x_p || ((ei + 1) < cb->n && e > cb->a[ei + 1].c_x_p)) - { - fprintf(stderr, "ERROR4\n"); - } - ///si and ei must be less than (cb->n-1) - q->ts = cb->a[si].c_y_p + - get_offset_adjust(s-cb->a[si].c_x_p, cb->a[si+1].c_x_p-cb->a[si].c_x_p, cb->a[si+1].c_y_p-cb->a[si].c_y_p); - - q->te = cb->a[ei].c_y_p + - get_offset_adjust(e-cb->a[ei].c_x_p, cb->a[ei+1].c_x_p-cb->a[ei].c_x_p, cb->a[ei+1].c_y_p-cb->a[ei].c_y_p); - - ///might be equal - if(q->ts > q->te) fprintf(stderr, "ERROR5\n"); - // if(q->tScur >= q->tEcur) - // { - // fprintf(stderr, "\n###q->tScur: %u, s: %u, si: %u, q->tEcur: %u, e: %u, ei: %u\n", - // q->tScur, s, si, q->tEcur, e, ei); - - // fprintf(stderr, "###cb->a[si].c_x_p: %u, cb->a[si].c_y_p: %u, cb->a[si+1].c_x_p: %u, cb->a[si+1].c_y_p: %u\n", - // cb->a[si].c_x_p, cb->a[si].c_y_p, cb->a[si+1].c_x_p, cb->a[si+1].c_y_p); - - // fprintf(stderr, "###cb->a[ei].c_x_p: %u, cb->a[ei].c_y_p: %u, cb->a[ei+1].c_x_p: %u, cb->a[ei+1].c_y_p: %u\n", - // cb->a[ei].c_x_p, cb->a[ei].c_y_p, cb->a[ei+1].c_x_p, cb->a[ei+1].c_y_p); - - // fprintf(stderr, "ERROR5\n"); - // } -} - -///[ts, te) -void extract_sub_overlaps_utg_thit(uint32_t i_ts, uint32_t i_te, uint32_t i_tus, uint32_t i_tue, -uint32_t tn, kv_utg_thit_t_t* ktb, uint32_t bn) -{ - uint32_t i, ovlp, found, beg, end, offS, offE; - utg_thit_t *q = NULL, x; - for (i = found = 0; i < bn; i++) - { - q = &(ktb->a[i]);///for q, already know [qs, qe), [qus, que), [ts, te) - - ovlp = ((MIN(i_te, q->te) > MAX(i_ts, q->ts))? - MIN(i_te, q->te) - MAX(i_ts, q->ts):0); - if(found == 1 && ovlp == 0) break; - if(ovlp > 0) found = 1; - if(ovlp == 0) continue; - - - beg = MAX(i_ts, q->ts); end = MIN(i_te, q->te); - offS = beg - q->ts; offE = q->te - end; - x.ts = q->ts + offS; - x.te = q->te - offE; - //x.qs = q->qs + offS; - x.qs = q->qs + get_offset_adjust(offS, q->te-q->ts, q->qe-q->qs); - ///x.qe = q->qe - offE; - x.qe = q->qe - get_offset_adjust(offE, q->te-q->ts, q->qe-q->qs); - - x.qn = q->qn; - offS = beg - q->ts; offE = q->te - end; - if((x.qn&1) == 0) - { - // x.qus = q->qus + offS; - x.qus = q->qus + get_offset_adjust(offS, q->te-q->ts, q->que-q->qus); - // x.que = q->que - offE; - x.que = q->que - get_offset_adjust(offE, q->te-q->ts, q->que-q->qus); - } - else - { - // x.qus = q->qus + offE; - x.qus = q->qus + get_offset_adjust(offE, q->te-q->ts, q->que-q->qus); - // x.que = q->que - offS; - x.que = q->que - get_offset_adjust(offS, q->te-q->ts, q->que-q->qus); - } - - x.tn = tn; - offS = beg - i_ts; offE = i_te - end; - if((x.tn&1) == 0) - { - // x.tus = i_tus + offS; - x.tus = i_tus + get_offset_adjust(offS, i_te-i_ts, i_tue-i_tus); - // x.tue = i_tue - offE; - x.tue = i_tue - get_offset_adjust(offE, i_te-i_ts, i_tue-i_tus); - } - else - { - // x.tus = i_tus + offE; - x.tus = i_tus + get_offset_adjust(offE, i_te-i_ts, i_tue-i_tus); - // x.tue = i_tue - offS; - x.tue = i_tue - get_offset_adjust(offS, i_te-i_ts, i_tue-i_tus); - } - - kv_push(utg_thit_t, *ktb, x); - - // if(x.tus >= x.tue || x.qus >= x.que) - // { - // fprintf(stderr, "\n*********x.qn: %u, x.tn: %u\n", x.qn, x.tn); - // fprintf(stderr, "x.qus: %u, x.que: %u, x.tus: %u, x.tue: %u\n", - // x.qus, x.que, x.tus, x.tue); - // fprintf(stderr, "q->qs: %u, q->qe: %u, q->qus: %u, q->que: %u\n", - // q->qs, q->qe, q->qus, q->que); - // fprintf(stderr, "q->ts: %u, q->te: %u, q->tus: %u, q->tue: %u\n", - // q->ts, q->te, q->tus, q->tue); - // fprintf(stderr, "i_ts: %u, i_te: %u, i_tus: %u, i_tue: %u\n", - // i_ts, i_te, i_tus, i_tue); - // } - } -} - -uint32_t get_utg_trans_hit(utg_trans_hit_idx *t, utg_thit_t *hit) -{ - uint32_t r_beg, r_end, ovlp; - uint32_t k, l, qn, v, w, nv; - uint32_t *a = t->a, a_n = t->an; - asg_arc_t *av = NULL; - hit->qs = hit->qe = hit->qn = hit->qus = hit->que = (uint32_t)-1; - hit->ts = hit->te = hit->tn = hit->tus = hit->tue = (uint32_t)-1; - - while (t->ui < a_n) - { - qn = a[t->ui]; - l = t->ug->g->seq[qn>>1].len; - if(t->ui + 1 < a_n) - { - v = a[t->ui]; w = a[t->ui+1]; - av = asg_arc_a(t->ug->g, v); - nv = asg_arc_n(t->ug->g, v); - for (k = 0; k < nv; k++) - { - if(av[k].del) continue; - if(av[k].v == w) - { - l = asg_arc_len(av[k]); - break; - } - } - if(k >= nv) fprintf(stderr, "ERROR-mc-1\n"); - } - - r_beg = t->len; r_end = t->len + t->ug->g->seq[qn>>1].len; - t->len += l; t->ui++; - - ovlp = ((MIN(t->cEnd, r_end) > MAX(t->cBeg, r_beg))? (MIN(t->cEnd, r_end) - MAX(t->cBeg, r_beg)) : 0); - if(ovlp == 0 && r_beg >= t->cEnd) return 0; - if(ovlp == 0) continue; - - hit->qn = qn; hit->qs = r_beg; hit->qe = r_end; hit->qus = 0; hit->que = t->ug->g->seq[qn>>1].len; - if(hit->qs < t->cBeg) - { - hit->qus += (t->cBeg - hit->qs); - hit->qs = t->cBeg; - } - - if(hit->qe > t->cEnd) - { - hit->que -= (hit->qe - t->cEnd); - hit->qe = t->cEnd; - } - - return 1; - } - return 0; -} - -void reset_utg_trans_hit_idx(utg_trans_hit_idx *t, uint32_t* i_x_a, uint32_t i_x_n, ma_ug_t *i_ug, -utg_trans_t *i_o, uint32_t i_cBeg, uint32_t i_cEnd) -{ - t->a = i_x_a; - t->an = i_x_n; - t->ug = i_ug; - t->o = i_o; - t->cBeg = i_cBeg; - t->cEnd = i_cEnd; - t->ui = t->len = 0; -} - -void chain_trans_d(utg_trans_t *o, -uint32_t *pri_a, uint32_t pri_n, uint32_t pri_beg, uint64_t *i_pri_len, -uint32_t *aux_a, uint32_t aux_n, uint32_t aux_beg, uint64_t *i_aux_len, -ma_ug_t *ug, uint32_t flag, double score, const char* cmd) -{ - uint32_t i, len, bn; - uint64_t pri_len, aux_len; - kvec_asg_arc_t_offset* u_buffer = &(o->u_buffer); - kvec_t_i32_warp* tailIndex = &(o->tailIndex); - asg_arc_t_offset *tt = NULL; - ca_buf_t *tx = NULL; - - if(i_pri_len) pri_len = (*i_pri_len); - else pri_len = get_utg_chain_length(ug, pri_a, pri_n); - - if(i_aux_len) aux_len = (*i_aux_len); - else aux_len = get_utg_chain_length(ug, aux_a, aux_n); - - tt = NULL; o->c_buf.n = 0; o->k_t_b.n = 0; - if(tailIndex->a.n > 0) tt = &(u_buffer->a.a[tailIndex->a.a[0]]); - if(!tt || (pri_beg < (tt->Off>>32) && aux_beg < ((uint32_t)tt->Off))) - { - kv_pushp(ca_buf_t, o->c_buf, &tx); - tx->c_x_p = pri_beg; - tx->c_y_p = aux_beg; - - for (i = 0; i < tailIndex->a.n; i++) - { - tt = &(u_buffer->a.a[tailIndex->a.a[i]]); - kv_pushp(ca_buf_t, o->c_buf, &tx); - - tx->c_x_p = tt->Off>>32; - tx->c_y_p = (uint32_t)tt->Off; - } - } - else if(tailIndex->a.n == 1)//1 ele in chain - { - kv_pushp(ca_buf_t, o->c_buf, &tx); - tx->c_x_p = pri_beg; tx->c_y_p = aux_beg; - } - else if(tailIndex->a.n > 0) - { - uint32_t cx, cy, ax, ay, found = 0; - for (i = 0; i < tailIndex->a.n; i++) - { - cx = cy = ax = ay = (uint32_t)-1; - - cx = u_buffer->a.a[tailIndex->a.a[i]].Off>>32; - cy = (uint32_t)u_buffer->a.a[tailIndex->a.a[i]].Off; - if((i + 1) < tailIndex->a.n) - { - ax = u_buffer->a.a[tailIndex->a.a[i+1]].Off>>32; - ay = (uint32_t)u_buffer->a.a[tailIndex->a.a[i+1]].Off; - } - - kv_pushp(ca_buf_t, o->c_buf, &tx); - tx->c_x_p = cx; tx->c_y_p = cy; - - if(found) continue; - if(pri_beg > cx && pri_beg < ax && aux_beg > cy && aux_beg < ay) - { - kv_pushp(ca_buf_t, o->c_buf, &tx); - tx->c_x_p = pri_beg; tx->c_y_p = aux_beg; - found = 1; - } - } - } - - - // fprintf(stderr, "\ncmd-%s\n", cmd); - // fprintf(stderr, "pri_beg=%u, pri_len=%lu\n", pri_beg, pri_len); - // fprintf(stderr, "aux_beg=%u, aux_len=%lu\n", aux_beg, aux_len); - - // print_buf_t(ug, pri, "pri"); - // print_buf_t(ug, aux, "aux"); - - - tx = &(o->c_buf.a[o->c_buf.n-1]); - len = MIN(pri_len - tx->c_x_p, aux_len - tx->c_y_p); - if(len > 0)///insert boundary - { - kv_pushp(ca_buf_t, o->c_buf, &tx); - tx->c_x_p = o->c_buf.a[o->c_buf.n-2].c_x_p + len; - tx->c_y_p = o->c_buf.a[o->c_buf.n-2].c_y_p + len; - } - - tx = &(o->c_buf.a[0]);///insert boundary - if(tx->c_x_p != 0 && tx->c_y_p != 0)///already at boundary - { - len = MIN(tx->c_x_p, tx->c_y_p);///offset - kv_pushp(ca_buf_t, o->c_buf, &tx); - for (i = 0; (i + 1)< o->c_buf.n; i++) - { - o->c_buf.a[o->c_buf.n - i - 1] = o->c_buf.a[o->c_buf.n - i - 2]; - } - o->c_buf.a[0].c_x_p = o->c_buf.a[1].c_x_p - len; - o->c_buf.a[0].c_y_p = o->c_buf.a[1].c_y_p - len; - } - - ///chain is [s, e) - if(o->c_buf.a[0].c_x_p != 0 && o->c_buf.a[0].c_y_p != 0) fprintf(stderr, "ERROR1\n"); - if(o->c_buf.a[o->c_buf.n-1].c_x_p!= pri_len && - o->c_buf.a[o->c_buf.n-1].c_y_p!= aux_len) - { - fprintf(stderr, "ERROR2\n"); - } - - utg_trans_hit_idx iter; - utg_thit_t hit, *kh = NULL; - ////////prx - reset_utg_trans_hit_idx(&iter, pri_a, pri_n, ug, o, o->c_buf.a[0].c_x_p, o->c_buf.a[o->c_buf.n-1].c_x_p); - while(get_utg_trans_hit(&iter, &hit))//get [qs, qe), [qus, que) - { - refine_utg_thit_t(&hit, &(o->c_buf)); ///get [ts, te) - kv_push(utg_thit_t, o->k_t_b, hit); - } - bn = o->k_t_b.n; - - ////////aux - reset_utg_trans_hit_idx(&iter, aux_a, aux_n, ug, o, o->c_buf.a[0].c_y_p, o->c_buf.a[o->c_buf.n-1].c_y_p); - while(get_utg_trans_hit(&iter, &hit)) - { - extract_sub_overlaps_utg_thit(hit.qs, hit.qe, hit.qus, hit.que, hit.qn, &(o->k_t_b), bn); - } - - if(o->k_t_b.n - bn == 0) fprintf(stderr, "ERROR7\n"); - - // fprintf(stderr, "\n******o->k_t_b.n: %u, bn: %u\n", (uint32_t)o->k_t_b.n, bn); - // for (i = 0; i < pri_n; i++) - // { - // fprintf(stderr, "p-utg%.6ul\n", (pri_a[i]>>1) + 1); - // } - // for (i = 0; i < aux_n; i++) - // { - // fprintf(stderr, "a-utg%.6ul\n", (aux_a[i]>>1) + 1); - // } - - u_trans_t *kt = NULL; - double x_score, y_score; - for (i = bn; i < o->k_t_b.n; i++) - { - kh = &(o->k_t_b.a[i]); - if(kh->que <= kh->qus) continue; - if(kh->tue <= kh->tus) continue; - kv_pushp(u_trans_t, o->k_trans, &kt); - kt->f = flag; kt->rev = ((kh->qn ^ kh->tn) & 1); kt->del = 0; - kt->qn = kh->qn>>1; kt->qs = kh->qus; kt->qe = kh->que; ///kt->qo = kh->qn&1; - kt->tn = kh->tn>>1; kt->ts = kh->tus; kt->te = kh->tue; ///kt->to = kh->tn&1; - if(score < 0) - { - kt->nw = (MIN((kt->qe - kt->qs), (kt->te - kt->ts)))*CHAIN_MATCH; - } - else - { - x_score = ((double)(kt->qe-kt->qs)/(double)(o->c_buf.a[o->c_buf.n-1].c_x_p-o->c_buf.a[0].c_x_p))*score; - y_score = ((double)(kt->te-kt->ts)/(double)(o->c_buf.a[o->c_buf.n-1].c_y_p-o->c_buf.a[0].c_y_p))*score; - kt->nw = MIN(x_score, y_score); - } - } -} - - -void chain_bubble(buf_t *pri, uint64_t pri_len, buf_t* aux, uint64_t aux_len, -uint32_t beg, uint32_t sink, ma_ug_t *ug, utg_trans_t *o) -{ - if(pri->b.n == 0 || aux->b.n == 0) return; - asg_arc_t *av = NULL; - uint32_t pri_v, aux_v, nv, i, priBeg, priEnd, auxBeg, auxEnd; - - priBeg = priEnd = auxBeg = auxEnd = (uint32_t)-1; - pri_v = pri->b.a[0]; aux_v = aux->b.a[0]; - av = asg_arc_a(ug->g, beg); - nv = asg_arc_n(ug->g, beg); - for (i = 0; i < nv; ++i) - { - if(av[i].del) continue; - if(av[i].v == pri_v) priBeg = av[i].ol; - if(av[i].v == aux_v) auxBeg = av[i].ol; - } - - pri_v = pri->b.a[pri->b.n-1]^1; aux_v = aux->b.a[aux->b.n-1]^1; - av = asg_arc_a(ug->g, sink); - nv = asg_arc_n(ug->g, sink); - for (i = 0; i < nv; ++i) - { - if(av[i].del) continue; - if(av[i].v == pri_v) priEnd = ((pri_len > av[i].ol)? (pri_len - av[i].ol - 1) : 0); - if(av[i].v == aux_v) auxEnd = ((aux_len > av[i].ol)? (aux_len - av[i].ol - 1) : 0); - } - - if(priBeg == (uint32_t)-1 || priEnd == (uint32_t)-1 || auxBeg == (uint32_t)-1 || auxEnd == (uint32_t)-1) - { - fprintf(stderr, "ERROR-s_bubble\n"); - } - - o->u_buffer.a.n = o->tailIndex.a.n = 0; - - kv_resize(asg_arc_t_offset, o->u_buffer.a, 1); - o->u_buffer.a.n = 1; - o->u_buffer.a.a[0].Off = priEnd; - o->u_buffer.a.a[0].Off <<= 32; - o->u_buffer.a.a[0].Off |= auxEnd; - - kv_resize(int32_t, o->tailIndex.a, 1); - o->tailIndex.a.n = 1; - o->tailIndex.a.a[0] = 0; - - chain_trans_d(o, pri->b.a, pri->b.n, priBeg, &pri_len, aux->b.a, aux->b.n, auxBeg, &aux_len, ug, RC_0, -1024, __func__); -} - -void chain_c_bubble(uint32_t query, buf_t *target, buf_t *idx, ma_ug_t *ug, utg_trans_t *o) -{ - if(target->b.n == 0) return; - uint32_t qs, qe, ts, te, i, v, ovlp; - qs = idx->a[query].d; qe = qs + ug->g->seq[query>>1].len; - uint64_t qlen = ug->g->seq[query>>1].len, tlen; - o->u_buffer.a.n = o->tailIndex.a.n = 0; - - for (i = 0; i < target->b.n; ++i) - { - v = target->b.a[i]; - if(v < query) continue; //avoid dup - ts = idx->a[v].d; te = ts + ug->g->seq[v>>1].len; tlen = ug->g->seq[v>>1].len; - ovlp = ((MIN(qe, te) > MAX(qs, ts))? (MIN(qe, te) - MAX(qs, ts)) : 0); - if(ovlp == 0) continue; - chain_trans_d(o, &query, 1, MAX(qs, ts) - qs, &qlen, - &v, 1, MAX(qs, ts) - ts, &tlen, ug, RC_0, -1024, __func__); - } - // fprintf(stderr, "\nocc: %u\n", (uint32_t)(cov->t_ch->k_trans.n - i_n)); - // for (i = i_n; i < cov->t_ch->k_trans.n; i++) - // { - // fprintf(stderr, "s-utg%.6ul\t%u\t%u\td-utg%.6ul\t%u\t%u\trev(%u)\n", - // cov->t_ch->k_trans.a[i].qn+1, cov->t_ch->k_trans.a[i].qs, cov->t_ch->k_trans.a[i].qe, - // cov->t_ch->k_trans.a[i].tn+1, cov->t_ch->k_trans.a[i].ts, cov->t_ch->k_trans.a[i].te, - // cov->t_ch->k_trans.a[i].rev); - // } -} - -void tpSort(asg_t *g, utg_trans_t *o, uint32_t beg, uint32_t sink) -{ - buf_t *b = &(o->b0); - uint64_t *visited = o->pos_idx; - uint32_t v = beg, nv, kv, i; - asg_arc_t *av = NULL; - - b->b.n = 0; o->topo_res.n = 0; - kv_push(uint32_t, b->b, v); - while (b->b.n > 0) - { - ///b->b.n--; - v = b->b.a[b->b.n-1]; - if(visited[v>>1] == (uint64_t)-1) - { - visited[v>>1] = 0; - } - - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - for (i = kv = 0; i < nv; i++) - { - if(av[i].del) continue; - if((av[i].v>>1) == (beg>>1) || (av[i].v>>1) == (sink>>1)) continue; - if(visited[av[i].v>>1] != (uint64_t)-1) continue; - kv_push(uint32_t, b->b, av[i].v); - kv++; - } - - if(kv != 0) continue; - b->b.n--; - if(visited[v>>1] != 1) - { - kv_push(uint32_t, o->topo_res, v); - visited[v>>1] = 1; - } - } - for (i = 0; i < o->topo_res.n; ++i) - { - visited[o->topo_res.a[i]>>1] = (uint64_t)-1; - } - - o->topo_res.n--;//remove beg - for (i = 0; i < (o->topo_res.n>>1); ++i) - { - v = o->topo_res.a[i]; - o->topo_res.a[i] = o->topo_res.a[o->topo_res.n - i - 1]; - o->topo_res.a[o->topo_res.n - i - 1] = v; - } - - /*******************************for debug************************************/ - // for (i = 0; i < cov->n; ++i) - // { - // if(visited[i] != (uint64_t)-1) fprintf(stderr, "ERROR-2\n"); - // } - // debug_topo_sorting(g, cov, beg, sink); - /*******************************for debug************************************/ -} - -void dfs_trans_chain(asg_t *g, utg_trans_t *o, uint32_t v, uint32_t beg, uint32_t sink) -{ - buf_t *b = &(o->b0); - b->b.n = 0; - if(v == beg || v == sink) return; - uint64_t *flag = o->pos_idx; - asg_arc_t *acur = NULL; - uint32_t cur, ncur, i; - v = v << 1; - kv_push(uint32_t, b->b, v); - while (b->b.n > 0) - { - b->b.n--; - cur = b->b.a[b->b.n]; - if(flag[cur>>1] == 0 && (cur>>1) != (v>>1)) continue; - flag[cur>>1] = 0; - - ncur = asg_arc_n(g, cur); - acur = asg_arc_a(g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if((acur[i].v>>1) == beg || (acur[i].v>>1) == sink) continue; - if(flag[acur[i].v>>1] == 0) continue; - kv_push(uint32_t, b->b, acur[i].v); - } - } - - v = v + 1; - kv_push(uint32_t, b->b, v); - while (b->b.n > 0) - { - b->b.n--; - cur = b->b.a[b->b.n]; - if(flag[cur>>1] == 0 && (cur>>1) != (v>>1)) continue; - flag[cur>>1] = 0; - - ncur = asg_arc_n(g, cur); - acur = asg_arc_a(g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if((acur[i].v>>1) == beg || (acur[i].v>>1) == sink) continue; - if(flag[acur[i].v>>1] == 0) continue; - kv_push(uint32_t, b->b, acur[i].v); - } - } - - b->b.n = 0; - for (i = 0; i < o->topo_res.n; ++i) //has been sorted - { - if(flag[o->topo_res.a[i]>>1] == 0) - { - flag[o->topo_res.a[i]>>1] = (uint64_t)-1; - } - else - { - kv_push(uint32_t, b->b, o->topo_res.a[i]); - } - } - - - /*******************************for debug************************************/ - // for (i = 0; i < cov->n; ++i) - // { - // if(flag[i] != (uint64_t)-1) fprintf(stderr, "ERROR-0\n"); - // } - /*******************************for debug************************************/ -} - -void asg_bub_collect_ovlp(ma_ug_t *ug, uint32_t v0, buf_t *b, utg_trans_t *o) -{ - uint32_t i, uId; - ///b->S.a[0] is the sink of this bubble - if(get_real_length(ug->g, v0, NULL) == 2 && get_real_length(ug->g, b->S.a[0]^1, NULL) == 2) - { - long long tmp, max_stop_nodeLen, max_stop_baseLen, bch_occ[2], len[2]; - uint32_t bch[2], convex[2]; - get_real_length(ug->g, v0, bch); - - ///in rare cases, one side of a bubble might be empty - if((bch[0]>>1)!=(b->S.a[0]>>1) && (bch[1]>>1)!=(b->S.a[0]>>1)) - { - get_unitig(ug->g, NULL, bch[0], &convex[0], &bch_occ[0], &tmp, - &max_stop_nodeLen, &max_stop_baseLen, 1, NULL); - get_unitig(ug->g, NULL, bch[1], &convex[1], &bch_occ[1], &tmp, - &max_stop_nodeLen, &max_stop_baseLen, 1, NULL); - if(((bch_occ[0] + bch_occ[1] + 1) == (uint32_t)b->b.n) && - get_real_length(ug->g, convex[0], NULL) == 1 && get_real_length(ug->g, convex[1], NULL) == 1) - { - get_real_length(ug->g, convex[0], &convex[0]); - get_real_length(ug->g, convex[1], &convex[1]); - if(convex[0] == b->S.a[0] && convex[1] == b->S.a[0]) - { - o->b0.b.n = 0; - get_unitig(ug->g, NULL, bch[0], &convex[0], &bch_occ[0], &len[0], &max_stop_nodeLen, &max_stop_baseLen, 1, &(o->b0)); - o->b1.b.n = 0; - get_unitig(ug->g, NULL, bch[1], &convex[1], &bch_occ[1], &len[1], &max_stop_nodeLen, &max_stop_baseLen, 1, &(o->b1)); - - chain_bubble(&(o->b0), len[0], &(o->b1), len[1], v0, b->S.a[0]^1, ug, o); - return; - } - } - } - } - - tpSort(ug->g, o, v0, b->S.a[0]); - ///if(o->topo_res.n != b->b.n - 1) fprintf(stderr, "ERROR-4\n"); - if(o->topo_res.n == 0) return; - for (i = 0; i < o->topo_res.n; ++i) - { - uId = o->topo_res.a[i]>>1; - if(uId == (b->S.a[0]>>1)) continue; - - dfs_trans_chain(ug->g, o, uId, v0>>1, b->S.a[0]>>1); - - if(o->b0.b.n == 0) continue; - chain_c_bubble(o->topo_res.a[i], &(o->b0), b, ug, o); - } -} - - -void collect_trans_ovlp(const char* cmd, buf_t* pri, uint64_t pri_offset, buf_t* aux, uint64_t aux_offset, -ma_ug_t *ug, utg_trans_t *o) -{ - uint32_t thre_pri; - uint64_t len_aux; - if(pri->b.n == 0 || aux->b.n == 0) return; - - len_aux = set_utg_offset(aux->b.a, aux->b.n, ug, o->read_g, o->pos_idx, 0, 0); - chain_trans_ovlp(NULL, o, ug, o->read_g, pri, len_aux, &thre_pri); - - - if(thre_pri > 0) - { - chain_trans_d(o, pri->b.a, pri->b.n, pri_offset, NULL, aux->b.a, aux->b.n, aux_offset, &len_aux, - ug, RC_1, -1024, __func__); - // fprintf(stderr, "\n%s, thre_pri: %u, len_aux: %lu\n", cmd, thre_pri, len_aux); - // print_buf_t(ug, pri, "pri"); - // print_buf_t(ug, aux, "aux"); - } - set_utg_offset(aux->b.a, aux->b.n, ug, o->read_g, o->pos_idx, 1, 0); -} - - -uint32_t dfs_set(asg_t *g, uint32_t v0, uint32_t fbv, kvec_t_u32_warp *stack, kvec_t_u32_warp *tmp, uint8_t *vis, uint8_t flag) -{ - uint32_t cur, ncur, i, occ = 0;; - asg_arc_t *acur = NULL; - stack->a.n = 0; - kv_push(uint32_t, stack->a, v0); - // vis[v0] = 0; - - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - if(vis[cur] && (!(vis[cur]&flag))) - { - vis[cur] |= flag; - kv_push(uint32_t, tmp->a, cur); - occ++; - } - if(vis[cur]) continue; - else kv_push(uint32_t, tmp->a, cur); - - vis[cur] |= flag; - ncur = asg_arc_n(g, cur); - acur = asg_arc_a(g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if((acur[i].v>>1) == fbv) continue; - if(vis[acur[i].v] && (!(vis[acur[i].v]&flag))) - { - vis[acur[i].v] |= flag; - kv_push(uint32_t, tmp->a, acur[i].v); - occ++; - continue; - } - - kv_push(uint32_t, stack->a, acur[i].v); - } - } - - return occ; -} - - -uint32_t dfs_reach(asg_t *g, uint32_t src, uint32_t dest, kvec_t_u32_warp *stack, kvec_t_u32_warp *tmp, uint8_t *vis) -{ - uint32_t cur, ncur, i, occ = 0;; - asg_arc_t *acur = NULL; - stack->a.n = 0; tmp->a.n = 0; - kv_push(uint32_t, stack->a, src); - - while (stack->a.n > 0) - { - stack->a.n--; - cur = stack->a.a[stack->a.n]; - if(vis[cur]) continue; - else kv_push(uint32_t, tmp->a, cur); - vis[cur] = 1; - if(cur == dest) - { - occ = 1; - break; - } - - - ncur = asg_arc_n(g, cur); - acur = asg_arc_a(g, cur); - for (i = 0; i < ncur; i++) - { - if(acur[i].del) continue; - if(vis[acur[i].v]) continue; - kv_push(uint32_t, stack->a, acur[i].v); - if(acur[i].v == dest) - { - occ = 1; - break; - } - } - if(occ) break; - } - - for (i = 0; i < tmp->a.n; i++) - { - vis[tmp->a.a[i]] = 0; - } - - stack->a.n = 0; tmp->a.n = 0; - return occ; -} - -int is_hap_ovlp(ma_ug_t *ug, asg_t *read_sg, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, - uint32_t *a, uint32_t a_n, uint32_t *b, uint32_t b_n) -{ - uint32_t i, k, j, qn, tn, is_Unitig, uId, found = 0; - ma_utg_t *u = NULL; - for (i = 0; i < b_n; i++) - { - u = &(ug->u.a[b[i]]); - for (k = 0; k < u->n; k++) - { - qn = (u->a[k]>>33); - set_R_to_U(ruIndex, qn, b[i], 1, NULL); - } - } - - - for (i = 0; i < a_n; i++) - { - u = &(ug->u.a[a[i]]); - for (k = 0; k < u->n; k++) - { - qn = (u->a[k]>>33); - for (j = 0; j < reverse_sources[qn].length; j++) - { - tn = Get_tn(reverse_sources[qn].buffer[j]); - if(read_sg->seq[tn].del == 1) - { - get_R_to_U(ruIndex, tn, &tn, &is_Unitig); - if(tn == (uint32_t)-1 || is_Unitig == 1 || read_sg->seq[tn].del == 1) continue; - } - - get_R_to_U(ruIndex, tn, &uId, &is_Unitig); - if(uId!=(uint32_t)-1 && is_Unitig == 1) - { - found = 1; - break; - } - } - if(found) break; - } - if(found) break; - } - - - - - for (i = 0; i < b_n; i++) - { - u = &(ug->u.a[b[i]]); - for (k = 0; k < u->n; k++) - { - qn = (u->a[k]>>33); - ruIndex->index[qn] = (uint32_t)-1; - } - } - - return found; -} - -uint32_t get_dir_v(uint32_t x, buf_t *b) -{ - uint32_t i; - for (i = 0; i < b->b.n; i++) - { - if((b->b.a[i]>>1) == x) return b->b.a[i]; - } - - return (uint32_t)-1; -} - -int is_pop_unitig(uint32_t v, asg_t *g, ma_ug_t *ug, kvec_t_u32_warp *tt, kvec_t_u32_warp *stack, uint8_t *vis, -pdq *pq_p, pdq *pq_a, uint8_t fp, uint8_t fa, long long *d) -{ - asg_arc_t *as = NULL; - uint32_t s, sv, return_flag, convex, ns, i, k, nc, p_n, found, *a_a = NULL, a_n; - long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; - if(g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) return 0; - if(asg_arc_n(g, v) == 0 || get_real_length(g, v, NULL) != 1) return 0; - get_real_length(g, v, &s); - if(get_real_length(g, s^1, NULL) < 2) return 0; - return_flag = get_unitig(g, ug, v^1, &convex, &ll, &tmp, &max_stop_nodeLen,&max_stop_baseLen, 1, NULL); - if(return_flag == LOOP) return 0; - - as = asg_arc_a(g, convex); ns = asg_arc_n(g, convex); - for (i = nc = 0; i < ns; i++) - { - if(as[i].del) continue; - if(get_real_length(g, as[i].v^1, NULL) < 2) break; - nc++; - } - if(nc == 0 || i < ns) return 0; - - tt->a.n = 0; s^=1; sv = v^1; - dfs_set(g, sv, s>>1, stack, tt, vis, fp); - p_n = tt->a.n; - as = asg_arc_a(g, s); ns = asg_arc_n(g, s); found = 0; - for (i = 0; i < ns; i++) - { - if(as[i].del || as[i].v == sv) continue; - nc = dfs_set(g, as[i].v, s>>1, stack, tt, vis, fa);///nc > 0 means as[i].v and sv have common suffix - if(nc && check_trans_relation_by_path(sv, as[i].v, pq_p, NULL, NULL, pq_a, NULL, NULL, g, - vis, fp+fa, nc, 0.45, d)) - { - found = 1; - } - a_a = tt->a.a + p_n; a_n = tt->a.n - p_n; - for (k = 0; k < a_n; k++) - { - if(vis[a_a[k]]&fa) vis[a_a[k]] -= fa; - } - tt->a.n = p_n; - if(found) break; - } - a_a = tt->a.a; a_n = p_n; - for (k = 0; k < a_n; k++) vis[a_a[k]] = 0; - return found; -} - -static void unitig_iden_worker(void *_data, long eid, int tid) -{ - long long d; - clean_mul_t *buf = (clean_mul_t*)_data; - clean_t *b = &(buf->a[tid]); - if(is_pop_unitig(eid, buf->g, buf->ug, &(b->tt), &(b->stack), b->vis, &(b->pq_p), &(b->pq_a), buf->fp, buf->fa, &d)) - { - if(b->min_v == (uint32_t)-1 || (b->min_d > d) || - (b->min_d == d && buf->g->seq[b->min_v>>1].len > buf->g->seq[eid>>1].len) || - (b->min_d == d && buf->g->seq[b->min_v>>1].len == buf->g->seq[eid>>1].len && b->min_v > eid)) - { - b->min_v = eid; b->min_d = d; - } - } -} - -int is_pop_bub(uint32_t v, asg_t *g, ma_ug_t *ug, buf_t *b, uint64_t max_dist, uint8_t *bs_flag) -{ - bs_flag[v] = 4; - asg_arc_t *av = NULL; - uint32_t nv, i, n_arc; - int occ = 0; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) return occ; - ///some edges could be deleted - for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs - if (!av[i].del) ++n_arc; - if (n_arc < 2) return occ; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, max_dist, b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) - { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - bs_flag[v] = 0; - occ = 1; - } - return occ; -} - -static void bub_iden_worker(void *_data, long eid, int tid) -{ - clean_mul_t *buf = (clean_mul_t*)_data; - clean_t *b = &(buf->a[tid]); - if(is_pop_bub(eid, buf->g, buf->ug, &(b->b), buf->max_dist, buf->bs_flag)) - { - b->is_b = 1; - } -} - -int asg_pop_bubble_primary_trio(asg_t *g, ma_ug_t *ug, uint8_t *bs_flag, buf_t *b, -uint64_t max_dist, uint32_t positive_flag, uint32_t negative_flag, utg_trans_t *o) -{ - uint32_t v, n_vtx = g->n_seq * 2, n_arc, nv, i; - uint64_t n_pop = 0; - asg_arc_t *av = NULL; - - if(max_dist > 0) - { - for (v = 0; v < n_vtx; ++v) - { - if(bs_flag[v] != 0) continue; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - ///some edges could be deleted - for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs - if (!av[i].del) ++n_arc; - if (n_arc < 2) continue; - if(asg_bub_pop1_primary_trio(ug->g, NULL, v, max_dist, b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) - { - //beg is v, end is b.S.a[0] - //note b.b include end, does not include beg - for (i = 0; i < b->b.n; i++) - { - if(b->b.a[i]==v || b->b.a[i]==b->S.a[0]) continue; - bs_flag[b->b.a[i]] = bs_flag[b->b.a[i]^1] = 1; - } - bs_flag[v] = 2; bs_flag[b->S.a[0]^1] = 3; - } - } - - //traverse all node with two directions - for (v = 0; v < n_vtx; ++v) { - if(bs_flag[v] !=2) continue; - nv = asg_arc_n(g, v); - av = asg_arc_a(g, v); - ///some node could be deleted - if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - ///some edges could be deleted - for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs - if (!av[i].del) ++n_arc; - if (n_arc > 1) - n_pop += asg_bub_pop1_primary_trio(ug->g, ug, v, max_dist, b, positive_flag, negative_flag, 1, NULL, NULL, NULL, 0, 0, o); - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] popped %lu bubbles\n", __func__, (unsigned long)n_pop); - } - } - - if (n_pop) asg_cleanup(g); - return n_pop; -} - -int get_min_dec(clean_mul_t *cl, uint32_t positive_flag, uint32_t negative_flag, utg_trans_t *o, uint32_t *v) -{ - uint32_t i, n_pop; - clean_t *p = NULL; - (*v) = (uint32_t)-1; - for (i = 0; i < cl->n; i++) cl->a[i].is_b = 0, cl->a[i].min_v = (uint32_t)-1; - kt_for(cl->n, bub_iden_worker, cl, cl->g->n_seq<<1);///fast check if there are bubbles in graph - for (i = 0; i < cl->n; i++) - { - if(cl->a[i].is_b) ///pop bubble - { - ///pop all bubbles - n_pop = asg_pop_bubble_primary_trio(cl->g, cl->ug, cl->bs_flag, &(cl->a[i].b), - cl->max_dist, positive_flag, negative_flag, o); - if(n_pop ==0) fprintf(stderr, "ERROR-n_pop\n"); - break; - } - } - kt_for(cl->n, unitig_iden_worker, cl, cl->g->n_seq<<1); - for (i = 0; i < cl->n; i++) - { - if(cl->a[i].min_v == (uint32_t)-1) continue; - // if(b->min_v == (uint32_t)-1 || (b->min_d > d) || (b->min_d == d && b->min_v < eid)) - ///looks like select the minum node, and back - if(!p || p->min_d > cl->a[i].min_d || - (p->min_d == cl->a[i].min_d && cl->g->seq[p->min_v>>1].len > cl->g->seq[cl->a[i].min_v>>1].len) || - (p->min_d == cl->a[i].min_d && cl->g->seq[p->min_v>>1].len == cl->g->seq[cl->a[i].min_v>>1].len && p->min_v > cl->a[i].min_v)) - { - p = &(cl->a[i]); - } - } - if(p) (*v) = p->min_v; - return p?1:0; -} - -int asg_arc_decompress_mul(asg_t *g, ma_ug_t *ug, asg_t *read_sg, uint32_t positive_flag, uint32_t negative_flag, -ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, utg_trans_t *o) -{ - double startTime = Get_T(); - asg_arc_t *as = NULL, *pm = NULL; - u_trans_t *kt = NULL; - uint32_t v, s, sv, nc, ns, n_vtx = g->n_seq * 2, n_reduced = 0, convex, pi, qn, tn; - uint32_t return_flag, k, m, i, p_n, a_n, *a_a = NULL; - uint8_t fp = 1, fa = 2, found; - long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; - kvec_t_u32_warp tt; kv_init(tt.a); - kvec_t_u32_warp stack; kv_init(stack.a); - uint8_t *vis = NULL; CALLOC(vis, n_vtx); - buf_t b; - memset(&b, 0, sizeof(buf_t)); - pdq pq_p, pq_a; - init_pdq(&pq_p, g->n_seq<<1); - init_pdq(&pq_a, g->n_seq<<1); - uint32_t *path_p = NULL, *path_q = NULL; - CALLOC(path_p, g->n_seq<<1); - CALLOC(path_q, g->n_seq<<1); - clean_mul_t *cl = init_clean_mul_t(g, ug, asm_opt.thread_num, fp, fa); - - while (get_min_dec(cl, positive_flag, negative_flag, o, &v)) - { - if(g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - if(asg_arc_n(g, v) == 0 || get_real_length(g, v, NULL) != 1) continue; - get_real_length(g, v, &s); - if(get_real_length(g, s^1, NULL) < 2) continue; - return_flag = get_unitig(g, ug, v^1, &convex, &ll, &tmp, &max_stop_nodeLen,&max_stop_baseLen, 1, NULL); - if(return_flag == LOOP) continue; - - as = asg_arc_a(g, convex); ns = asg_arc_n(g, convex); - for (i = nc = 0; i < ns; i++) - { - if(as[i].del) continue; - if(get_real_length(g, as[i].v^1, NULL) < 2) break; - nc++; - } - if(nc == 0 || i < ns) continue; - - tt.a.n = 0; s^=1; sv = v^1; - dfs_set(g, sv, s>>1, &stack, &tt, vis, fp); - p_n = tt.a.n; - as = asg_arc_a(g, s); ns = asg_arc_n(g, s); found = 0; - for (i = 0, pm = NULL; i < ns; i++) - { - if(as[i].del || as[i].v != sv) continue; - pm = &(as[i]); - break; - } - - for (i = 0; i < ns; i++) - { - if(as[i].del || as[i].v == sv) continue; - nc = dfs_set(g, as[i].v, s>>1, &stack, &tt, vis, fa); - if(nc && check_trans_relation_by_path(sv, as[i].v, &pq_p, path_p, &(o->b0), &pq_a, path_q, &(o->b1), g, - vis, fp+fa, nc, 0.45, NULL)) - { - found = 1; - } - a_a = tt.a.a + p_n; a_n = tt.a.n - p_n; - for (k = 0; k < a_n; k++) - { - if(vis[a_a[k]]&fa) vis[a_a[k]] -= fa; - } - tt.a.n = p_n; - if(found) break; - } - a_a = tt.a.a; a_n = p_n; - for (k = 0; k < a_n; k++) vis[a_a[k]] = 0; - - if(found == 0) fprintf(stderr, "ERROR-found\n"); - if(found) - { - b.b.n = 0; - get_unitig(g, ug, sv, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, &b); - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]>>1].c = ALTER_LABLE; - } - - for (k = 0; k < b.b.n; k++) - { - asg_seq_drop(g, b.b.a[k]>>1); - } - - // uint32_t ui; - // fprintf(stderr, "\n"); - // for (ui = 0; ui < o->b0.b.n; ui++) - // { - // fprintf(stderr, "p-utg%.6ul\n", (o->b0.b.a[ui]>>1)+1); - // } - // for (ui = 0; ui < o->b1.b.n; ui++) - // { - // fprintf(stderr, "a-utg%.6ul\n", (o->b1.b.a[ui]>>1)+1); - // } - - - if(o->b0.b.n < b.b.n) fprintf(stderr, "ERROR-ll\n"); - o->b0.b.n = b.b.n; pi = o->k_trans.n; - collect_trans_ovlp(__func__, &(o->b0), pm->ol, &(o->b1), as[i].ol, ug, o); - - for (k = m = pi; k < o->k_trans.n; k++) - { - kt = &(o->k_trans.a[k]); - if(is_hap_ovlp(ug, read_sg, reverse_sources, ruIndex, &(kt->qn), 1, &(kt->tn), 1) || - is_hap_ovlp(ug, read_sg, reverse_sources, ruIndex, &(kt->tn), 1, &(kt->qn), 1)) - { - qn = get_dir_v(kt->qn, &(o->b0)); - tn = get_dir_v(kt->tn, &(o->b1)); - - if(dfs_reach(o->cug->g, qn, tn, &stack, &tt, vis) || dfs_reach(o->cug->g, tn, qn, &stack, &tt, vis)) - { - // fprintf(stderr, "<<<<<qn + 1, kt->qs, kt->qe, kt->tn + 1, kt->ts, kt->te); - continue; - } - - // fprintf(stderr, "q-utg%.6ul (qs: %u, qe: %u), t-utg%.6ul (ts: %u, te: %u)\n", - // kt->qn + 1, kt->qs, kt->qe, kt->tn + 1, kt->ts, kt->te); - o->k_trans.a[m] = *kt; - m++; - } - // else - // { - // fprintf(stderr, "******delete: q-utg%.6ul (qs: %u, qe: %u), t-utg%.6ul (ts: %u, te: %u)\n", - // kt->qn + 1, kt->qs, kt->qe, kt->tn + 1, kt->ts, kt->te); - // } - } - o->k_trans.n = m; - } - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d long tips\n", - __func__, n_reduced); - } - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - asg_cleanup(g); - asg_symm(g); - free(b.b.a); - kv_destroy(tt.a); - kv_destroy(stack.a); - free(vis); - destory_pdq(&pq_p); - destory_pdq(&pq_a); - free(path_p); - free(path_q); - destroy_clean_mul_t(&cl); - return n_reduced; -} - - -int asg_arc_decompress(asg_t *g, ma_ug_t *ug, asg_t *read_sg, ma_hit_t_alloc* reverse_sources, -R_to_U* ruIndex, utg_trans_t *o) -{ - double startTime = Get_T(); - asg_arc_t *as = NULL, *pm = NULL; - u_trans_t *kt = NULL; - uint32_t v, s, sv, nc, ns, n_vtx = g->n_seq * 2, n_reduced = 0, convex, pi, qn, tn; - uint32_t return_flag, k, m, i, p_n, a_n, *a_a = NULL; - uint8_t fp = 1, fa = 2, found; - long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; - kvec_t_u32_warp tt; kv_init(tt.a); - kvec_t_u32_warp stack; kv_init(stack.a); - uint8_t *vis = NULL; CALLOC(vis, n_vtx); - buf_t b; - memset(&b, 0, sizeof(buf_t)); - pdq pq_p, pq_a; - init_pdq(&pq_p, g->n_seq<<1); - init_pdq(&pq_a, g->n_seq<<1); - uint32_t *path_p = NULL, *path_q = NULL; - CALLOC(path_p, g->n_seq<<1); - CALLOC(path_q, g->n_seq<<1); - - for (v = 0; v < n_vtx; v++) - { - if(g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; - if(asg_arc_n(g, v) == 0 || get_real_length(g, v, NULL) != 1) continue; - get_real_length(g, v, &s); - if(get_real_length(g, s^1, NULL) < 2) continue; - return_flag = get_unitig(g, ug, v^1, &convex, &ll, &tmp, &max_stop_nodeLen,&max_stop_baseLen, 1, NULL); - if(return_flag == LOOP) continue; - - as = asg_arc_a(g, convex); ns = asg_arc_n(g, convex); - for (i = nc = 0; i < ns; i++) - { - if(as[i].del) continue; - if(get_real_length(g, as[i].v^1, NULL) < 2) break; - nc++; - } - if(nc == 0 || i < ns) continue; - - tt.a.n = 0; s^=1; sv = v^1; - dfs_set(g, sv, s>>1, &stack, &tt, vis, fp); - p_n = tt.a.n; - as = asg_arc_a(g, s); ns = asg_arc_n(g, s); found = 0; - for (i = 0, pm = NULL; i < ns; i++) - { - if(as[i].del || as[i].v != sv) continue; - pm = &(as[i]); - break; - } - - for (i = 0; i < ns; i++) - { - if(as[i].del || as[i].v == sv) continue; - nc = dfs_set(g, as[i].v, s>>1, &stack, &tt, vis, fa); - if(nc && check_trans_relation_by_path(sv, as[i].v, &pq_p, path_p, &(o->b0), &pq_a, path_q, &(o->b1), g, - vis, fp+fa, nc, 0.45, NULL)) - { - found = 1; - } - a_a = tt.a.a + p_n; a_n = tt.a.n - p_n; - for (k = 0; k < a_n; k++) - { - if(vis[a_a[k]]&fa) vis[a_a[k]] -= fa; - } - tt.a.n = p_n; - if(found) break; - } - a_a = tt.a.a; a_n = p_n; - for (k = 0; k < a_n; k++) vis[a_a[k]] = 0; - - if(found) - { - b.b.n = 0; - get_unitig(g, ug, sv, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, &b); - for (k = 0; k < b.b.n; k++) - { - g->seq[b.b.a[k]>>1].c = ALTER_LABLE; - } - - for (k = 0; k < b.b.n; k++) - { - asg_seq_drop(g, b.b.a[k]>>1); - } - - // uint32_t ui; - // fprintf(stderr, "\n"); - // for (ui = 0; ui < o->b0.b.n; ui++) - // { - // fprintf(stderr, "p-utg%.6ul\n", (o->b0.b.a[ui]>>1)+1); - // } - // for (ui = 0; ui < o->b1.b.n; ui++) - // { - // fprintf(stderr, "a-utg%.6ul\n", (o->b1.b.a[ui]>>1)+1); - // } - - - if(o->b0.b.n < b.b.n) fprintf(stderr, "ERROR-ll\n"); - o->b0.b.n = b.b.n; pi = o->k_trans.n; - collect_trans_ovlp(__func__, &(o->b0), pm->ol, &(o->b1), as[i].ol, ug, o); - - for (k = m = pi; k < o->k_trans.n; k++) - { - kt = &(o->k_trans.a[k]); - if(is_hap_ovlp(ug, read_sg, reverse_sources, ruIndex, &(kt->qn), 1, &(kt->tn), 1) || - is_hap_ovlp(ug, read_sg, reverse_sources, ruIndex, &(kt->tn), 1, &(kt->qn), 1)) - { - qn = get_dir_v(kt->qn, &(o->b0)); - tn = get_dir_v(kt->tn, &(o->b1)); - - if(dfs_reach(o->cug->g, qn, tn, &stack, &tt, vis) || dfs_reach(o->cug->g, tn, qn, &stack, &tt, vis)) - { - // fprintf(stderr, "<<<<<qn + 1, kt->qs, kt->qe, kt->tn + 1, kt->ts, kt->te); - continue; - } - - // fprintf(stderr, "q-utg%.6ul (qs: %u, qe: %u), t-utg%.6ul (ts: %u, te: %u)\n", - // kt->qn + 1, kt->qs, kt->qe, kt->tn + 1, kt->ts, kt->te); - o->k_trans.a[m] = *kt; - m++; - } - // else - // { - // fprintf(stderr, "******delete: q-utg%.6ul (qs: %u, qe: %u), t-utg%.6ul (ts: %u, te: %u)\n", - // kt->qn + 1, kt->qs, kt->qe, kt->tn + 1, kt->ts, kt->te); - // } - } - o->k_trans.n = m; - } - } - - if(VERBOSE >= 1) - { - fprintf(stderr, "[M::%s] removed %d long tips\n", - __func__, n_reduced); - fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); - } - - asg_cleanup(g); - asg_symm(g); - free(b.b.a); - kv_destroy(tt.a); - kv_destroy(stack.a); - free(vis); - destory_pdq(&pq_p); - destory_pdq(&pq_a); - free(path_p); - free(path_q); - return n_reduced; -} - -typedef struct { - uint64_t *idx; - kvec_t(uint64_t) pos; -} mz_ds_t; - -typedef struct { - uint64_t x, y; -} pt128_t; - -typedef struct { - uint64_t x; - uint64_t rid:32, span:32; - uint64_t pos:63, rev:1; -} pt_mz1_t; - -typedef struct { - ///cnt1: how many unique minimizers - ///cnt2: how many non-unique minimizers - uint32_t cnt2, cnt1; - uint32_t m[2]; - int8_t s; -} pt_uinfo_t; - -typedef struct { - uint32_t n_seq; // number of segments; same as gfa_t::n_seg - pt_uinfo_t *info; // of size n_seg - kv_u_trans_t *ma; -} pt_match_t; - -#define mz_key(z) ((z).x) -KRADIX_SORT_INIT(mz, pt_mz1_t, mz_key, 8) - -#define pt128x_key(z) ((z).x) -KRADIX_SORT_INIT(pt128x, pt128_t, pt128x_key, 8) - -#define generic_key(x) (x) -KRADIX_SORT_INIT(tb64, uint64_t, generic_key, 8) - -typedef struct { uint32_t n, m; pt128_t *a; } pt128_v; -typedef struct { uint32_t n, m; pt_mz1_t *a; } pt_mz1_v; - -static inline int mzcmp(const pt_mz1_t *a, const pt_mz1_t *b) -{ - return (a->x > b->x) - (a->x < b->x); -} - -void pt_sketch(const char *str, int len, int w, int k, uint32_t rid, int is_hpc, pt_mz1_v *p) -{ - static const pt_mz1_t dummy = { UINT64_MAX, (1<<28) - 1, 0, 0 }; - uint64_t shift1 = k - 1, mask = (1ULL< 0 && rid < (uint64_t)1<<32 && (w > 0 && w < 256) && (k > 0 && k <= 63)); - - memset(buf, 0xff, w * sizeof(pt_mz1_t)); - memset(&tq, 0, sizeof(tiny_queue_t)); - kv_resize(pt_mz1_t, *p, p->n + len/w); - - for (i = l = buf_pos = min_pos = 0; i < len; ++i) { - int c = seq_nt4_table[(uint8_t)str[i]]; - pt_mz1_t info = dummy; - if (c < 4) { // not an ambiguous base - int z; - if (is_hpc) { - int skip_len = 1; - if (i + 1 < len && seq_nt4_table[(uint8_t)str[i + 1]] == c) { - for (skip_len = 2; i + skip_len < len; ++skip_len) - if (seq_nt4_table[(uint8_t)str[i + skip_len]] != c) - break; - i += skip_len - 1; // put $i at the end of the current homopolymer run - } - tq_push(&tq, skip_len); - kmer_span += skip_len; - if (tq.count > k) kmer_span -= tq_shift(&tq); - } else kmer_span = l + 1 < k? l + 1 : k; - - kmer[0] = (kmer[0] << 1 | (c&1)) & mask; // forward k-mer - kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; - kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; // reverse k-mer - kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; - if (kmer[1] == kmer[3]) continue; // skip "symmetric k-mers" as we don't know its strand - z = kmer[1] < kmer[3]? 0 : 1; // strand - ++l; - if (l >= k && kmer_span < 256) { - uint64_t y; - y = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); - info.x = y, info.rid = rid, info.pos = i, info.rev = z, info.span = kmer_span; // initially pt_mz1_t::rid keeps the k-mer count - } - } else l = 0, tq.count = tq.front = 0, kmer_span = 0; - - buf[buf_pos] = info; // need to do this here as appropriate buf_pos and buf[buf_pos] are needed below - if (l == w + k - 1 && min.x != UINT64_MAX) { // special case for the first window - because identical k-mers are not stored yet - for (j = buf_pos + 1; j < w; ++j) - if (mzcmp(&min, &buf[j]) == 0 && buf[j].pos != min.pos) kv_push(pt_mz1_t, *p, buf[j]); - for (j = 0; j < buf_pos; ++j) - if (mzcmp(&min, &buf[j]) == 0 && buf[j].pos != min.pos) kv_push(pt_mz1_t, *p, buf[j]); - } - ///three cases: 1. - if (info.x <= min.x) { // a new minimum; then write the old min - if (l >= w + k && min.x != UINT64_MAX) kv_push(pt_mz1_t, *p, min); - min = info, min_pos = buf_pos; - } else if (buf_pos == min_pos) { // old min has moved outside the window - if (l >= w + k - 1 && min.x != UINT64_MAX) kv_push(pt_mz1_t, *p, min); - for (j = buf_pos + 1, min.x = UINT64_MAX; j < w; ++j) // the two loops are necessary when there are identical k-mers - if (mzcmp(&min, &buf[j]) >= 0) min = buf[j], min_pos = j; // >= is important s.t. min is always the closest k-mer - for (j = 0; j <= buf_pos; ++j) - if (mzcmp(&min, &buf[j]) >= 0) min = buf[j], min_pos = j; - - if (l >= w + k - 1 && min.x != UINT64_MAX) { // write identical k-mers - for (j = buf_pos + 1; j < w; ++j) // these two loops make sure the output is sorted - if (mzcmp(&min, &buf[j]) == 0 && min.pos != buf[j].pos) kv_push(pt_mz1_t, *p, buf[j]); - for (j = 0; j <= buf_pos; ++j) - if (mzcmp(&min, &buf[j]) == 0 && min.pos != buf[j].pos) kv_push(pt_mz1_t, *p, buf[j]); - } - } - if (++buf_pos == w) buf_pos = 0; - } - if (min.x != UINT64_MAX) - kv_push(pt_mz1_t, *p, min); -} - -pt_mz1_v *pt_collect_minimizers(ma_ug_t *ug, asg_t *read_g, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, -kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp) -{ - uint32_t i; - pt_mz1_v *mz = NULL; CALLOC(mz, 1); - - for (i = 0; i < ug->u.n; i++) - { - if(!ug->u.a[i].len) continue; - pt_sketch(ug->u.a[i].s, ug->u.a[i].len, asm_opt.mz_win, asm_opt.k_mer_length, i, 0, mz); - } - - radix_sort_mz(mz->a, mz->a + mz->n); - return mz; -} - -pt128_v *pt_collect_anchors(ma_ug_t *ug, pt_mz1_v *mz, mz_ds_t *mz_idx, uint32_t max_occ) -{ - uint32_t st, j; - pt128_v *pa = NULL; CALLOC(pa, 1); - pt128_t *p = NULL; - mz_idx->pos.n = 0; - ///all minimizers - for (j = 1, st = 0; j <= mz->n; ++j) { - if (j == mz->n || mz->a[j].x != mz->a[st].x) { - uint32_t k, l; - // if (j - st == 1) ++info[mz->a[st].rid].cnt1; ///of size n_seg - ///max_occ is the frquency threshold of minimizer - ///if (j - st) == 1, means minimizer only occurs in one read, it is not useful - if (j - st == 1 || j - st > max_occ) goto end_anchor; - for (k = st; k < j; ++k) { - // ++info[mz->a[k].rid].cnt2; - kv_push(uint64_t, mz_idx->pos, (uint64_t)(mz->a[k].rid)<<32|(uint64_t)(mz->a[k].pos)); - for (l = k + 1; l < j; ++l) { - ///k is current minimizer - uint32_t span, rev = (mz->a[k].rev != mz->a[l].rev); - int32_t lk = ug->u.a[mz->a[k].rid].len, ll = ug->u.a[mz->a[l].rid].len; - kv_pushp(pt128_t, *pa, &p); - span = mz->a[l].span; - p->x = (uint64_t)mz->a[k].rid << 33 | mz->a[l].rid << 1 | rev; - p->y = (uint64_t)mz->a[k].pos << 32 | (rev? ll - (mz->a[l].pos + 1 - span) - 1 : mz->a[l].pos); - kv_pushp(pt128_t, *pa, &p); - span = mz->a[k].span; - p->x = (uint64_t)mz->a[l].rid << 33 | mz->a[k].rid << 1 | rev; - p->y = (uint64_t)mz->a[l].pos << 32 | (rev? lk - (mz->a[k].pos + 1 - span) - 1 : mz->a[k].pos); - } - } - end_anchor: st = j; - } - } - - radix_sort_pt128x(pa->a, pa->a + pa->n); - - radix_sort_tb64(mz_idx->pos.a, mz_idx->pos.a + mz_idx->pos.n); - CALLOC(mz_idx->idx, ug->u.n); - for (st = 0, j = 1; j <= mz_idx->pos.n; ++j) - { - if (j == mz_idx->pos.n || (mz_idx->pos.a[j]>>32) != (mz_idx->pos.a[st]>>32)) - { - mz_idx->idx[mz_idx->pos.a[st]>>32] = (uint64_t)st << 32 | (j - st), st = j; - } - } - - return pa; -} - -int32_t pt_lis_64(int32_t n, const uint64_t *a_idx, int32_t *b, int32_t *M) -{ - int32_t i, k, L = 0, *P = b; - // MALLOC(M, n+1); - for (i = 0; i < n; ++i) { - int32_t lo = 1, hi = L, newL; - while (lo <= hi) { - int32_t mid = (lo + hi + 1) >> 1; - if ((uint32_t)a_idx[M[mid]] < (uint32_t)a_idx[i]) lo = mid + 1; - else hi = mid - 1; - } - newL = lo, P[i] = M[newL - 1], M[newL] = i; - if (newL > L) L = newL; - } - k = M[L]; - memcpy(M, P, n * sizeof(int32_t)); - for (i = L - 1; i >= 0; --i) b[i] = k, k = M[k]; - // free(M); - return L; -} - -uint32_t debug_lis_64(const uint64_t *a, int32_t *b, uint64_t n) -{ - uint32_t i; - if(n <= 1) return 1; - for (i = 0; i+1 < n; i++) - { - if(((a[b[i]]>>32) > (a[b[i+1]]>>32)) || (((uint32_t)a[b[i]]) > ((uint32_t)a[b[i+1]]))) - { - i = (uint32_t)-1; - break; - } - } - if(i == (uint32_t)-1) - { - fprintf(stderr, "\nERROR-chain\n"); - for (i = 0; i < n; i++) - { - fprintf(stderr, "x-%lu, y-%lu\n", (a[b[i]]>>32), (uint64_t)((uint32_t)a[b[i]])); - } - } - return 1; -} - -void update_mz_ovlp(uint32_t* n_x_beg, uint32_t* n_x_end, int64_t xLen, -uint32_t* n_y_beg, uint32_t* n_y_end, int64_t yLen, uint32_t rev) -{ - int64_t x_beg = (*n_x_beg), x_end = (*n_x_end); - int64_t y_beg = (*n_y_beg), y_end = (*n_y_end); - if(x_beg <= y_beg) - { - y_beg = y_beg - x_beg; - x_beg = 0; - } - else - { - x_beg = x_beg - y_beg; - y_beg = 0; - } - - long long x_right_length = xLen - x_end - 1; - long long y_right_length = yLen - y_end - 1; - - - if(x_right_length <= y_right_length) - { - x_end = xLen - 1; - y_end = y_end + x_right_length; - } - else - { - x_end = x_end + y_right_length; - y_end = yLen - 1; - } - - if(rev == 0) - { - (*n_y_beg) = y_beg; - (*n_y_end) = y_end + 1; - } - else - { - (*n_y_beg) = yLen - y_end - 1; - (*n_y_end) = yLen - y_beg - 1 + 1; - } - - (*n_x_beg) = x_beg; - (*n_x_end) = x_end + 1; -} - -int64_t get_insert_pos(uint64_t *a, int64_t n, int64_t target) -{ - int64_t left, right, ans, mid; - left = 0; right = n - 1; ans = n; - while (left <= right) { - mid = ((right - left) >> 1) + left; - if (target <= (uint32_t)a[mid]) { - ans = mid; - right = mid - 1; - } else { - left = mid + 1; - } - } - return ans; -} - -uint32_t get_mz_occ(mz_ds_t *mz_idx, uint64_t uid, uint64_t s, uint64_t e) -{ - uint64_t *a = mz_idx->pos.a + (mz_idx->idx[uid]>>32), n = (uint32_t)(mz_idx->idx[uid]); - if(n == 0) return 0; - int64_t sid, eid; - sid = get_insert_pos(a, n, s); - eid = get_insert_pos(a, n, e); - return eid + 1 - sid; -} - -kv_u_trans_t *pt_cal_sim(pt128_v *pa, mz_ds_t *mz_idx, ma_ug_t *ug, uint32_t min_cnt, double min_sim) -{ - int64_t st, i, j; - kvec_t(uint64_t) a; kv_init(a); - kvec_t(int32_t) b; kv_init(b); - kvec_t(int32_t) M; kv_init(M); - kv_u_trans_t *ma = NULL; CALLOC(ma, 1); - u_trans_t m; - ///x = (uint64_t)mz[l].rid << 33 | mz[k].rid << 1 | rev; - for (st = 0, i = 1; i <= pa->n; ++i) { - if (i == pa->n || pa->a[i].x != pa->a[st].x) {///minimizers between a pair of unitigs - if((pa->a[st].x>>33) == (((uint32_t)pa->a[st].x)>>1)) goto end_chain; - uint32_t nn[2], nn_min; - a.n = 0; memset(&m, 0, sizeof(m)); - if (i - st < min_cnt) goto end_chain; - //(uint64_t)mz[l].pos << 32 | (rev? lk - (mz[k].pos + 1 - span) - 1 : mz[k].pos); - for (j = st; j < i; ++j) kv_push(uint64_t, a, pa->a[j].y); - radix_sort_tb64(a.a, a.a + a.n);///sort by query pos + target pos - // for (l = 0; l < a.n; ++l) a.a[l] = (uint32_t)a.a[l];///only need target pos to do LIS - kv_resize(int32_t, b, a.n); kv_resize(int32_t, M, a.n+1); - m.occ = pt_lis_64(a.n, a.a, b.a, M.a); - /*******************************for debug************************************/ - // debug_lis_64(a.a, b.a, m.occ); - /*******************************for debug************************************/ - if (m.occ == 0 || m.occ < min_cnt) goto end_chain;//chain occ - m.qn = pa->a[st].x >> 33;///query id - m.tn = ((uint32_t)pa->a[st].x) >> 1;///target id - if (m.qn == m.tn) goto end_chain; - m.qs = a.a[b.a[0]]>>32; m.qe = a.a[b.a[m.occ-1]]>>32; - m.ts = (uint32_t)(a.a[b.a[0]]); m.te = (uint32_t)(a.a[b.a[m.occ-1]]); - m.rev = (pa->a[st].x>>32&1) ^ (pa->a[st].x&1); - update_mz_ovlp(&(m.qs), &(m.qe), ug->u.a[m.qn].len, &(m.ts), &(m.te), ug->u.a[m.tn].len, m.rev); - - nn[0] = get_mz_occ(mz_idx, m.qn, m.qs, m.qe-1); - nn[1] = get_mz_occ(mz_idx, m.tn, m.ts, m.te-1); - nn_min = MIN(nn[0], nn[1]); - nn_min = MAX(nn_min, m.occ); - // m.sim = pow(2.0 * m.m / (nn[0] + nn[1]), 1.0 / k); - if(m.occ >= nn_min*min_sim){ - m.nw = (double)(m.occ) - (double)(nn_min-m.occ)*0.2; - if(m.nw > 0) kv_push(u_trans_t, *ma, m); - } - end_chain: st = i; - } - } - kv_destroy(b); kv_destroy(a); kv_destroy(M); - return ma; -} - -void clean_mz_ovlp(kv_u_trans_t *ta, ma_ug_t *ug) -{ - u_trans_t *a = NULL; - asg_arc_t *as = NULL; - uint32_t k, i, n, v, ns; - pdq pq; init_pdq(&pq, ug->g->n_seq<<1); - uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq); - kvec_t_u32_warp p; kv_init(p.a); - for (k = 0; k < ta->idx.n; k++) - { - p.a.n = 0; - a = u_trans_a(*ta, k); - n = u_trans_n(*ta, k); - if(n == 0) continue; - - v = k<<1; - as = asg_arc_a(ug->g, v); ns = asg_arc_n(ug->g, v); - if(ns > 0) - { - for (i = 0; i < ns; i++) - { - if(as[i].del) continue; - kv_push(uint32_t, p.a, as[i].v); - } - set_utg_by_dis(v, &pq, ug->g, &p, ug->g->seq[v>>1].len); - } - - - v = (k<<1) + 1; - as = asg_arc_a(ug->g, v); ns = asg_arc_n(ug->g, v); - if(ns > 0) - { - for (i = 0; i < ns; i++) - { - if(as[i].del) continue; - kv_push(uint32_t, p.a, as[i].v); - } - set_utg_by_dis(v, &pq, ug->g, &p, ug->g->seq[v>>1].len); - } - - for (i = 0; i < p.a.n; i++) vis[p.a.a[i]>>1] = 1; - - for (i = 0; i < n; i++) - { - if(vis[a[i].tn]) a[i].del = 1; - } - - for (i = 0; i < p.a.n; i++) vis[p.a.a[i]>>1] = 0; - } - destory_pdq(&pq); - kv_destroy(p.a); - free(vis); - - for (k = n = 0; k < ta->n; ++k) - { - if(ta->a[k].del) continue; - ta->a[n] = ta->a[k]; - n++; - } - ta->n = n; - kt_u_trans_t_idx(ta, ug->g->n_seq); - kt_u_trans_t_simple_symm(ta, ug->g->n_seq, 0); -} - -int cmp_u_trans_nw(const void * a, const void * b) -{ - if((*(u_trans_t*)a).nw == (*(u_trans_t*)b).nw) return 0; - return (*(u_trans_t*)a).nw < (*(u_trans_t*)b).nw ? 1 : -1; -} - -/** -void flat_mz_ovlp(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, ma_sub_t* coverage_cut, -ma_hit_t_alloc* sources, R_to_U* ruIndex, uint32_t min_cnt, uint32_t cov_thres, -double cov_pass_rate, double nw_pass_rate) -{ - u_trans_t *a = NULL, *p = NULL; - uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq); - uint32_t *cov = NULL; CALLOC(cov, ug->g->n_seq); - kvec_t(uint32_t) tc; kv_init(tc); - uint32_t k, i, j, n, v, ns, qs, qe, occ, hapN, pass; - double w; - for (i = 0; i < ug->u.n; i++) - { - cov[i] = get_utg_cov(ug, i, read_g, coverage_cut, sources, ruIndex, vis); - } - - for (k = 0; k < ta->idx.n; k++) - { - a = u_trans_a(*ta, k); - n = u_trans_n(*ta, k); - if(n == 0) continue; - qsort(a, n, sizeof(u_trans_t), cmp_u_trans_nw); - kv_resize(uint32_t, tc, ug->u.a[k].len); - tc.n = ug->u.a[k].len; - memset(tc.a, 0, tc.n*sizeof(uint32_t)); - for (i = 0, p = NULL; i < n; i++) - { - qs = a[i].qs; qe = a[i].qe; w = a[i].nw; occ = a[i].occ; pass = 0; - for (j = qs; j < qe; j++) - { - if(tc.a[j] + cov[k] >= cov_thres) pass++; - } - if(pass > cov_pass_rate*(qe - qs)) - { - if(p && nw_pass_rate*) a[i].del = 1; - } - else - { - for (j = qs; j < qe; j++) tc.a[j] += cov[k]; - } - } - } - free(vis); free(cov); kv_destroy(tc); -} -**/ - - -void print_u_trans(kv_u_trans_t *ta) -{ - uint32_t i; - u_trans_t *p = NULL; - for (i = 0; i < ta->n; i++) - { - p = &(ta->a[i]); - fprintf(stderr, "q-utg%.6ul\tqs(%u)\tqe(%u)\tt-utg%.6ul\tts(%u)\tte(%u)\trev(%u)\tw(%f)\tf(%u)\n", - p->qn+1, p->qs, p->qe, p->tn+1, p->ts, p->te, p->rev, p->nw, p->f); - } - fprintf(stderr, "[M::%s::] \n", __func__); -} - -kv_u_trans_t *pt_pdist(ma_ug_t *ug, asg_t *read_g, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, -kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, uint32_t min_chain_cnt) -{ - pt_mz1_v *mz = NULL; - mz_ds_t mz_idx; memset(&mz_idx, 0, sizeof(mz_idx)); - pt128_v *an = NULL; - kv_u_trans_t *ma = NULL; CALLOC(ma, 1); - mz = pt_collect_minimizers(ug, read_g, coverage_cut, sources, edge, max_hang, min_ovlp); - an = pt_collect_anchors(ug, mz, &mz_idx, asm_opt.polyploidy*10); - kv_destroy(*mz); free(mz); - - ma = pt_cal_sim(an, &mz_idx, ug, min_chain_cnt, asm_opt.purge_simi_thres); - kv_destroy(*an); free(an); - kv_destroy(mz_idx.pos); free(mz_idx.idx); - - kt_u_trans_t_idx(ma, ug->g->n_seq); - kt_u_trans_t_simple_symm(ma, ug->g->n_seq, 1); - clean_mz_ovlp(ma, ug); - // print_u_trans(ma); - // exit(1); - return ma; +#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" +#include "tovlp.h" +#include "hic.h" +KSEQ_INIT(gzFile, gzread) +KDQ_INIT(uint64_t) + + +typedef struct { + kvec_t_u32_warp tt; + kvec_t_u32_warp stack; + uint8_t *vis; + pdq pq_p; + pdq pq_a; + buf_t b; + uint32_t min_v, offset1, offset2; + long long min_d; + int is_b; +} clean_t; + +typedef struct { + clean_t *a; + size_t n, m; + uint64_t max_dist; + uint8_t *bs_flag, fp, fa; + asg_t *g; + ma_ug_t *ug; +} clean_mul_t; + +clean_mul_t *init_clean_mul_t(asg_t *g, ma_ug_t *ug, uint64_t n_threads, uint8_t fp, uint8_t fa) +{ + uint32_t i; + clean_t *kt = NULL; + clean_mul_t *p = NULL; CALLOC(p, 1); + p->g = g; p->ug = ug; + CALLOC(p->bs_flag, p->g->n_seq<<1); + p->n = p->m = n_threads; + CALLOC(p->a, p->n); + for (i = 0, kt = NULL; i < p->n; i++) + { + kt = &(p->a[i]); + kv_init(kt->tt.a); kv_init(kt->stack.a); + CALLOC(kt->vis, p->g->n_seq<<1); + init_pdq(&kt->pq_p, p->g->n_seq<<1); + init_pdq(&kt->pq_a, p->g->n_seq<<1); + memset(&kt->b, 0, sizeof(kt->b)); + kt->b.a = (binfo_t*)calloc(p->g->n_seq<<1, sizeof(binfo_t)); + } + p->max_dist = get_bub_pop_max_dist_advance(g, &kt->b); + p->fp = fp; p->fa = fa; + return p; +} + +void destroy_clean_mul_t(clean_mul_t **p) +{ + uint32_t i; + clean_t *kt = NULL; + free((*p)->bs_flag); + for (i = 0; i < (*p)->n; i++) + { + kt = &((*p)->a[i]); + kv_destroy(kt->tt.a); + kv_destroy(kt->stack.a); + free(kt->vis); + destory_pdq(&kt->pq_p); + destory_pdq(&kt->pq_a); + free(kt->b.a); free(kt->b.S.a); free(kt->b.T.a); free(kt->b.b.a); free(kt->b.e.a); + } + free((*p)->a); + free((*p)); +} + +utg_trans_t *init_utg_trans_t(ma_ug_t *ug, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, asg_t *read_g, int max_hang, int min_ovlp) +{ + utg_trans_t *o = NULL; + CALLOC(o, 1); + o->reverse_sources = reverse_sources; + o->coverage_cut = coverage_cut; + o->ruIndex = ruIndex; + o->read_g = read_g; + o->rn = read_g->n_seq; + memset(&(o->b0), 0, sizeof(o->b0)); + memset(&(o->b1), 0, sizeof(o->b1)); + MALLOC(o->pos_idx, o->rn); memset(o->pos_idx, -1, o->rn*sizeof(uint64_t)); + o->cug = copy_untig_graph(ug); + o->max_hang = max_hang; + o->min_ovlp = min_ovlp; + return o; +} + +void destroy_utg_trans_t(utg_trans_t **o) +{ + ; +} + +uint64_t get_utg_chain_length(ma_ug_t *ug, uint32_t *a, uint32_t a_n) +{ + uint64_t i, k, l, qn, v, w, nv, offset; + asg_arc_t *av = NULL; + for (i = 0, offset = 0; i < a_n; i++) + { + qn = a[i]>>1; + l = ug->g->seq[qn].len; + if(i + 1 < a_n) + { + v = a[i]; w = a[i+1]; + av = asg_arc_a(ug->g, v); + nv = asg_arc_n(ug->g, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + l = asg_arc_len(av[k]); + break; + } + } + if(k >= nv) fprintf(stderr, "ERROR-mc\n"); + } + offset += l; + } + return offset; +} + +void refine_utg_thit_t(utg_thit_t *q, kv_ca_buf_t* cb) +{ + ///already know [qScur, qEcur), [qSpre, qEpre) + uint32_t s, e, i, si, ei; + s = q->qs; e = q->qe;///[s, e) + for (i = 0, si = ei = cb->n; i < cb->n; i++) + { + if(cb->a[i].c_x_p > s && si == cb->n) + { + si = i; + } + + if(cb->a[i].c_x_p > (e-1) && ei == cb->n) + { + ei = i; + } + + if(si != cb->n && ei != cb->n) break; + } + + if(si == 0 || ei == 0) fprintf(stderr, "ERROR-si-ei-0\n"); + if(si >= cb->n || ei >= cb->n) fprintf(stderr, "ERROR-si-ei-1\n"); + si--; ei--; + + if(s < cb->a[si].c_x_p || ((si + 1) < cb->n && s >= cb->a[si + 1].c_x_p)) + { + fprintf(stderr, "ERROR3\n"); + } + if(e < cb->a[ei].c_x_p || ((ei + 1) < cb->n && e > cb->a[ei + 1].c_x_p)) + { + fprintf(stderr, "ERROR4\n"); + } + ///si and ei must be less than (cb->n-1) + q->ts = cb->a[si].c_y_p + + get_offset_adjust(s-cb->a[si].c_x_p, cb->a[si+1].c_x_p-cb->a[si].c_x_p, cb->a[si+1].c_y_p-cb->a[si].c_y_p); + + q->te = cb->a[ei].c_y_p + + get_offset_adjust(e-cb->a[ei].c_x_p, cb->a[ei+1].c_x_p-cb->a[ei].c_x_p, cb->a[ei+1].c_y_p-cb->a[ei].c_y_p); + + ///might be equal + if(q->ts > q->te) fprintf(stderr, "ERROR5\n"); + // if(q->tScur >= q->tEcur) + // { + // fprintf(stderr, "\n###q->tScur: %u, s: %u, si: %u, q->tEcur: %u, e: %u, ei: %u\n", + // q->tScur, s, si, q->tEcur, e, ei); + + // fprintf(stderr, "###cb->a[si].c_x_p: %u, cb->a[si].c_y_p: %u, cb->a[si+1].c_x_p: %u, cb->a[si+1].c_y_p: %u\n", + // cb->a[si].c_x_p, cb->a[si].c_y_p, cb->a[si+1].c_x_p, cb->a[si+1].c_y_p); + + // fprintf(stderr, "###cb->a[ei].c_x_p: %u, cb->a[ei].c_y_p: %u, cb->a[ei+1].c_x_p: %u, cb->a[ei+1].c_y_p: %u\n", + // cb->a[ei].c_x_p, cb->a[ei].c_y_p, cb->a[ei+1].c_x_p, cb->a[ei+1].c_y_p); + + // fprintf(stderr, "ERROR5\n"); + // } +} + +///[ts, te) +void extract_sub_overlaps_utg_thit(uint32_t i_ts, uint32_t i_te, uint32_t i_tus, uint32_t i_tue, +uint32_t tn, kv_utg_thit_t_t* ktb, uint32_t bn) +{ + uint32_t i, ovlp, found, beg, end, offS, offE; + utg_thit_t *q = NULL, x; + for (i = found = 0; i < bn; i++) + { + q = &(ktb->a[i]);///for q, already know [qs, qe), [qus, que), [ts, te) + + ovlp = ((MIN(i_te, q->te) > MAX(i_ts, q->ts))? + MIN(i_te, q->te) - MAX(i_ts, q->ts):0); + if(found == 1 && ovlp == 0) break; + if(ovlp > 0) found = 1; + if(ovlp == 0) continue; + + + beg = MAX(i_ts, q->ts); end = MIN(i_te, q->te); + offS = beg - q->ts; offE = q->te - end; + x.ts = q->ts + offS; + x.te = q->te - offE; + //x.qs = q->qs + offS; + x.qs = q->qs + get_offset_adjust(offS, q->te-q->ts, q->qe-q->qs); + ///x.qe = q->qe - offE; + x.qe = q->qe - get_offset_adjust(offE, q->te-q->ts, q->qe-q->qs); + + x.qn = q->qn; + offS = beg - q->ts; offE = q->te - end; + if((x.qn&1) == 0) + { + // x.qus = q->qus + offS; + x.qus = q->qus + get_offset_adjust(offS, q->te-q->ts, q->que-q->qus); + // x.que = q->que - offE; + x.que = q->que - get_offset_adjust(offE, q->te-q->ts, q->que-q->qus); + } + else + { + // x.qus = q->qus + offE; + x.qus = q->qus + get_offset_adjust(offE, q->te-q->ts, q->que-q->qus); + // x.que = q->que - offS; + x.que = q->que - get_offset_adjust(offS, q->te-q->ts, q->que-q->qus); + } + + x.tn = tn; + offS = beg - i_ts; offE = i_te - end; + if((x.tn&1) == 0) + { + // x.tus = i_tus + offS; + x.tus = i_tus + get_offset_adjust(offS, i_te-i_ts, i_tue-i_tus); + // x.tue = i_tue - offE; + x.tue = i_tue - get_offset_adjust(offE, i_te-i_ts, i_tue-i_tus); + } + else + { + // x.tus = i_tus + offE; + x.tus = i_tus + get_offset_adjust(offE, i_te-i_ts, i_tue-i_tus); + // x.tue = i_tue - offS; + x.tue = i_tue - get_offset_adjust(offS, i_te-i_ts, i_tue-i_tus); + } + + kv_push(utg_thit_t, *ktb, x); + + // if(x.tus >= x.tue || x.qus >= x.que) + // { + // fprintf(stderr, "\n*********x.qn: %u, x.tn: %u\n", x.qn, x.tn); + // fprintf(stderr, "x.qus: %u, x.que: %u, x.tus: %u, x.tue: %u\n", + // x.qus, x.que, x.tus, x.tue); + // fprintf(stderr, "q->qs: %u, q->qe: %u, q->qus: %u, q->que: %u\n", + // q->qs, q->qe, q->qus, q->que); + // fprintf(stderr, "q->ts: %u, q->te: %u, q->tus: %u, q->tue: %u\n", + // q->ts, q->te, q->tus, q->tue); + // fprintf(stderr, "i_ts: %u, i_te: %u, i_tus: %u, i_tue: %u\n", + // i_ts, i_te, i_tus, i_tue); + // } + } +} + +uint32_t get_utg_trans_hit(utg_trans_hit_idx *t, utg_thit_t *hit) +{ + uint32_t r_beg, r_end, ovlp; + uint32_t k, l, qn, v, w, nv; + uint32_t *a = t->a, a_n = t->an; + asg_arc_t *av = NULL; + hit->qs = hit->qe = hit->qn = hit->qus = hit->que = (uint32_t)-1; + hit->ts = hit->te = hit->tn = hit->tus = hit->tue = (uint32_t)-1; + + while (t->ui < a_n) + { + qn = a[t->ui]; + l = t->ug->g->seq[qn>>1].len; + if(t->ui + 1 < a_n) + { + v = a[t->ui]; w = a[t->ui+1]; + av = asg_arc_a(t->ug->g, v); + nv = asg_arc_n(t->ug->g, v); + for (k = 0; k < nv; k++) + { + if(av[k].del) continue; + if(av[k].v == w) + { + l = asg_arc_len(av[k]); + break; + } + } + if(k >= nv) fprintf(stderr, "ERROR-mc-1\n"); + } + + r_beg = t->len; r_end = t->len + t->ug->g->seq[qn>>1].len; + t->len += l; t->ui++; + + ovlp = ((MIN(t->cEnd, r_end) > MAX(t->cBeg, r_beg))? (MIN(t->cEnd, r_end) - MAX(t->cBeg, r_beg)) : 0); + if(ovlp == 0 && r_beg >= t->cEnd) return 0; + if(ovlp == 0) continue; + + hit->qn = qn; hit->qs = r_beg; hit->qe = r_end; hit->qus = 0; hit->que = t->ug->g->seq[qn>>1].len; + if(hit->qs < t->cBeg) + { + hit->qus += (t->cBeg - hit->qs); + hit->qs = t->cBeg; + } + + if(hit->qe > t->cEnd) + { + hit->que -= (hit->qe - t->cEnd); + hit->qe = t->cEnd; + } + + return 1; + } + return 0; +} + +void reset_utg_trans_hit_idx(utg_trans_hit_idx *t, uint32_t* i_x_a, uint32_t i_x_n, ma_ug_t *i_ug, +utg_trans_t *i_o, uint32_t i_cBeg, uint32_t i_cEnd) +{ + t->a = i_x_a; + t->an = i_x_n; + t->ug = i_ug; + t->o = i_o; + t->cBeg = i_cBeg; + t->cEnd = i_cEnd; + t->ui = t->len = 0; +} + +void chain_trans_d(utg_trans_t *o, +uint32_t *pri_a, uint32_t pri_n, uint32_t pri_beg, uint64_t *i_pri_len, +uint32_t *aux_a, uint32_t aux_n, uint32_t aux_beg, uint64_t *i_aux_len, +ma_ug_t *ug, uint32_t flag, double score, const char* cmd) +{ + uint32_t i, len, bn; + uint64_t pri_len, aux_len; + kvec_asg_arc_t_offset* u_buffer = &(o->u_buffer); + kvec_t_i32_warp* tailIndex = &(o->tailIndex); + asg_arc_t_offset *tt = NULL; + ca_buf_t *tx = NULL; + + if(i_pri_len) pri_len = (*i_pri_len); + else pri_len = get_utg_chain_length(ug, pri_a, pri_n); + + if(i_aux_len) aux_len = (*i_aux_len); + else aux_len = get_utg_chain_length(ug, aux_a, aux_n); + + tt = NULL; o->c_buf.n = 0; o->k_t_b.n = 0; + if(tailIndex->a.n > 0) tt = &(u_buffer->a.a[tailIndex->a.a[0]]); + if(!tt || (pri_beg < (tt->Off>>32) && aux_beg < ((uint32_t)tt->Off))) + { + kv_pushp(ca_buf_t, o->c_buf, &tx); + tx->c_x_p = pri_beg; + tx->c_y_p = aux_beg; + + for (i = 0; i < tailIndex->a.n; i++) + { + tt = &(u_buffer->a.a[tailIndex->a.a[i]]); + kv_pushp(ca_buf_t, o->c_buf, &tx); + + tx->c_x_p = tt->Off>>32; + tx->c_y_p = (uint32_t)tt->Off; + } + } + else if(tailIndex->a.n == 1)//1 ele in chain + { + kv_pushp(ca_buf_t, o->c_buf, &tx); + tx->c_x_p = pri_beg; tx->c_y_p = aux_beg; + } + else if(tailIndex->a.n > 0) + { + uint32_t cx, cy, ax, ay, found = 0; + for (i = 0; i < tailIndex->a.n; i++) + { + cx = cy = ax = ay = (uint32_t)-1; + + cx = u_buffer->a.a[tailIndex->a.a[i]].Off>>32; + cy = (uint32_t)u_buffer->a.a[tailIndex->a.a[i]].Off; + if((i + 1) < tailIndex->a.n) + { + ax = u_buffer->a.a[tailIndex->a.a[i+1]].Off>>32; + ay = (uint32_t)u_buffer->a.a[tailIndex->a.a[i+1]].Off; + } + + kv_pushp(ca_buf_t, o->c_buf, &tx); + tx->c_x_p = cx; tx->c_y_p = cy; + + if(found) continue; + if(pri_beg > cx && pri_beg < ax && aux_beg > cy && aux_beg < ay) + { + kv_pushp(ca_buf_t, o->c_buf, &tx); + tx->c_x_p = pri_beg; tx->c_y_p = aux_beg; + found = 1; + } + } + } + + + // fprintf(stderr, "\ncmd-%s\n", cmd); + // fprintf(stderr, "pri_beg=%u, pri_len=%lu\n", pri_beg, pri_len); + // fprintf(stderr, "aux_beg=%u, aux_len=%lu\n", aux_beg, aux_len); + + // print_buf_t(ug, pri, "pri"); + // print_buf_t(ug, aux, "aux"); + + + tx = &(o->c_buf.a[o->c_buf.n-1]); + len = MIN(pri_len - tx->c_x_p, aux_len - tx->c_y_p); + if(len > 0)///insert boundary + { + kv_pushp(ca_buf_t, o->c_buf, &tx); + tx->c_x_p = o->c_buf.a[o->c_buf.n-2].c_x_p + len; + tx->c_y_p = o->c_buf.a[o->c_buf.n-2].c_y_p + len; + } + + tx = &(o->c_buf.a[0]);///insert boundary + if(tx->c_x_p != 0 && tx->c_y_p != 0)///already at boundary + { + len = MIN(tx->c_x_p, tx->c_y_p);///offset + kv_pushp(ca_buf_t, o->c_buf, &tx); + for (i = 0; (i + 1)< o->c_buf.n; i++) + { + o->c_buf.a[o->c_buf.n - i - 1] = o->c_buf.a[o->c_buf.n - i - 2]; + } + o->c_buf.a[0].c_x_p = o->c_buf.a[1].c_x_p - len; + o->c_buf.a[0].c_y_p = o->c_buf.a[1].c_y_p - len; + } + + ///chain is [s, e) + if(o->c_buf.a[0].c_x_p != 0 && o->c_buf.a[0].c_y_p != 0) fprintf(stderr, "ERROR1\n"); + if(o->c_buf.a[o->c_buf.n-1].c_x_p!= pri_len && + o->c_buf.a[o->c_buf.n-1].c_y_p!= aux_len) + { + fprintf(stderr, "ERROR2\n"); + } + + utg_trans_hit_idx iter; + utg_thit_t hit, *kh = NULL; + ////////prx + reset_utg_trans_hit_idx(&iter, pri_a, pri_n, ug, o, o->c_buf.a[0].c_x_p, o->c_buf.a[o->c_buf.n-1].c_x_p); + while(get_utg_trans_hit(&iter, &hit))//get [qs, qe), [qus, que) + { + refine_utg_thit_t(&hit, &(o->c_buf)); ///get [ts, te) + kv_push(utg_thit_t, o->k_t_b, hit); + } + bn = o->k_t_b.n; + + ////////aux + reset_utg_trans_hit_idx(&iter, aux_a, aux_n, ug, o, o->c_buf.a[0].c_y_p, o->c_buf.a[o->c_buf.n-1].c_y_p); + while(get_utg_trans_hit(&iter, &hit)) + { + extract_sub_overlaps_utg_thit(hit.qs, hit.qe, hit.qus, hit.que, hit.qn, &(o->k_t_b), bn); + } + + if(o->k_t_b.n - bn == 0) fprintf(stderr, "ERROR7\n"); + + // fprintf(stderr, "\n******o->k_t_b.n: %u, bn: %u\n", (uint32_t)o->k_t_b.n, bn); + // for (i = 0; i < pri_n; i++) + // { + // fprintf(stderr, "p-utg%.6ul\n", (pri_a[i]>>1) + 1); + // } + // for (i = 0; i < aux_n; i++) + // { + // fprintf(stderr, "a-utg%.6ul\n", (aux_a[i]>>1) + 1); + // } + + u_trans_t *kt = NULL; + double x_score, y_score; + for (i = bn; i < o->k_t_b.n; i++) + { + kh = &(o->k_t_b.a[i]); + if(kh->que <= kh->qus) continue; + if(kh->tue <= kh->tus) continue; + kv_pushp(u_trans_t, o->k_trans, &kt); + kt->f = flag; kt->rev = ((kh->qn ^ kh->tn) & 1); kt->del = 0; + kt->qn = kh->qn>>1; kt->qs = kh->qus; kt->qe = kh->que; ///kt->qo = kh->qn&1; + kt->tn = kh->tn>>1; kt->ts = kh->tus; kt->te = kh->tue; ///kt->to = kh->tn&1; + if(score < 0) + { + kt->nw = (MIN((kt->qe - kt->qs), (kt->te - kt->ts)))*CHAIN_MATCH; + } + else + { + x_score = ((double)(kt->qe-kt->qs)/(double)(o->c_buf.a[o->c_buf.n-1].c_x_p-o->c_buf.a[0].c_x_p))*score; + y_score = ((double)(kt->te-kt->ts)/(double)(o->c_buf.a[o->c_buf.n-1].c_y_p-o->c_buf.a[0].c_y_p))*score; + kt->nw = MIN(x_score, y_score); + } + } +} + + +void chain_bubble(buf_t *pri, uint64_t pri_len, buf_t* aux, uint64_t aux_len, +uint32_t beg, uint32_t sink, ma_ug_t *ug, utg_trans_t *o) +{ + if(pri->b.n == 0 || aux->b.n == 0) return; + asg_arc_t *av = NULL; + uint32_t pri_v, aux_v, nv, i, priBeg, priEnd, auxBeg, auxEnd; + + priBeg = priEnd = auxBeg = auxEnd = (uint32_t)-1; + pri_v = pri->b.a[0]; aux_v = aux->b.a[0]; + av = asg_arc_a(ug->g, beg); + nv = asg_arc_n(ug->g, beg); + for (i = 0; i < nv; ++i) + { + if(av[i].del) continue; + if(av[i].v == pri_v) priBeg = av[i].ol; + if(av[i].v == aux_v) auxBeg = av[i].ol; + } + + pri_v = pri->b.a[pri->b.n-1]^1; aux_v = aux->b.a[aux->b.n-1]^1; + av = asg_arc_a(ug->g, sink); + nv = asg_arc_n(ug->g, sink); + for (i = 0; i < nv; ++i) + { + if(av[i].del) continue; + if(av[i].v == pri_v) priEnd = ((pri_len > av[i].ol)? (pri_len - av[i].ol - 1) : 0); + if(av[i].v == aux_v) auxEnd = ((aux_len > av[i].ol)? (aux_len - av[i].ol - 1) : 0); + } + + if(priBeg == (uint32_t)-1 || priEnd == (uint32_t)-1 || auxBeg == (uint32_t)-1 || auxEnd == (uint32_t)-1) + { + fprintf(stderr, "ERROR-s_bubble\n"); + } + + o->u_buffer.a.n = o->tailIndex.a.n = 0; + + kv_resize(asg_arc_t_offset, o->u_buffer.a, 1); + o->u_buffer.a.n = 1; + o->u_buffer.a.a[0].Off = priEnd; + o->u_buffer.a.a[0].Off <<= 32; + o->u_buffer.a.a[0].Off |= auxEnd; + + kv_resize(int32_t, o->tailIndex.a, 1); + o->tailIndex.a.n = 1; + o->tailIndex.a.a[0] = 0; + + chain_trans_d(o, pri->b.a, pri->b.n, priBeg, &pri_len, aux->b.a, aux->b.n, auxBeg, &aux_len, ug, RC_0, -1024, __func__); +} + +void chain_c_bubble(uint32_t query, buf_t *target, buf_t *idx, ma_ug_t *ug, utg_trans_t *o) +{ + if(target->b.n == 0) return; + uint32_t qs, qe, ts, te, i, v, ovlp; + qs = idx->a[query].d; qe = qs + ug->g->seq[query>>1].len; + uint64_t qlen = ug->g->seq[query>>1].len, tlen; + o->u_buffer.a.n = o->tailIndex.a.n = 0; + + for (i = 0; i < target->b.n; ++i) + { + v = target->b.a[i]; + if(v < query) continue; //avoid dup + ts = idx->a[v].d; te = ts + ug->g->seq[v>>1].len; tlen = ug->g->seq[v>>1].len; + ovlp = ((MIN(qe, te) > MAX(qs, ts))? (MIN(qe, te) - MAX(qs, ts)) : 0); + if(ovlp == 0) continue; + chain_trans_d(o, &query, 1, MAX(qs, ts) - qs, &qlen, + &v, 1, MAX(qs, ts) - ts, &tlen, ug, RC_0, -1024, __func__); + } + // fprintf(stderr, "\nocc: %u\n", (uint32_t)(cov->t_ch->k_trans.n - i_n)); + // for (i = i_n; i < cov->t_ch->k_trans.n; i++) + // { + // fprintf(stderr, "s-utg%.6ul\t%u\t%u\td-utg%.6ul\t%u\t%u\trev(%u)\n", + // cov->t_ch->k_trans.a[i].qn+1, cov->t_ch->k_trans.a[i].qs, cov->t_ch->k_trans.a[i].qe, + // cov->t_ch->k_trans.a[i].tn+1, cov->t_ch->k_trans.a[i].ts, cov->t_ch->k_trans.a[i].te, + // cov->t_ch->k_trans.a[i].rev); + // } +} + +void tpSort(asg_t *g, utg_trans_t *o, uint32_t beg, uint32_t sink) +{ + buf_t *b = &(o->b0); + uint64_t *visited = o->pos_idx; + uint32_t v = beg, nv, kv, i; + asg_arc_t *av = NULL; + + b->b.n = 0; o->topo_res.n = 0; + kv_push(uint32_t, b->b, v); + while (b->b.n > 0) + { + ///b->b.n--; + v = b->b.a[b->b.n-1]; + if(visited[v>>1] == (uint64_t)-1) + { + visited[v>>1] = 0; + } + + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + for (i = kv = 0; i < nv; i++) + { + if(av[i].del) continue; + if((av[i].v>>1) == (beg>>1) || (av[i].v>>1) == (sink>>1)) continue; + if(visited[av[i].v>>1] != (uint64_t)-1) continue; + kv_push(uint32_t, b->b, av[i].v); + kv++; + } + + if(kv != 0) continue; + b->b.n--; + if(visited[v>>1] != 1) + { + kv_push(uint32_t, o->topo_res, v); + visited[v>>1] = 1; + } + } + for (i = 0; i < o->topo_res.n; ++i) + { + visited[o->topo_res.a[i]>>1] = (uint64_t)-1; + } + + o->topo_res.n--;//remove beg + for (i = 0; i < (o->topo_res.n>>1); ++i) + { + v = o->topo_res.a[i]; + o->topo_res.a[i] = o->topo_res.a[o->topo_res.n - i - 1]; + o->topo_res.a[o->topo_res.n - i - 1] = v; + } + + /*******************************for debug************************************/ + // for (i = 0; i < cov->n; ++i) + // { + // if(visited[i] != (uint64_t)-1) fprintf(stderr, "ERROR-2\n"); + // } + // debug_topo_sorting(g, cov, beg, sink); + /*******************************for debug************************************/ +} + +void dfs_trans_chain(asg_t *g, utg_trans_t *o, uint32_t v, uint32_t beg, uint32_t sink) +{ + buf_t *b = &(o->b0); + b->b.n = 0; + if(v == beg || v == sink) return; + uint64_t *flag = o->pos_idx; + asg_arc_t *acur = NULL; + uint32_t cur, ncur, i; + v = v << 1; + kv_push(uint32_t, b->b, v); + while (b->b.n > 0) + { + b->b.n--; + cur = b->b.a[b->b.n]; + if(flag[cur>>1] == 0 && (cur>>1) != (v>>1)) continue; + flag[cur>>1] = 0; + + ncur = asg_arc_n(g, cur); + acur = asg_arc_a(g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if((acur[i].v>>1) == beg || (acur[i].v>>1) == sink) continue; + if(flag[acur[i].v>>1] == 0) continue; + kv_push(uint32_t, b->b, acur[i].v); + } + } + + v = v + 1; + kv_push(uint32_t, b->b, v); + while (b->b.n > 0) + { + b->b.n--; + cur = b->b.a[b->b.n]; + if(flag[cur>>1] == 0 && (cur>>1) != (v>>1)) continue; + flag[cur>>1] = 0; + + ncur = asg_arc_n(g, cur); + acur = asg_arc_a(g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if((acur[i].v>>1) == beg || (acur[i].v>>1) == sink) continue; + if(flag[acur[i].v>>1] == 0) continue; + kv_push(uint32_t, b->b, acur[i].v); + } + } + + b->b.n = 0; + for (i = 0; i < o->topo_res.n; ++i) //has been sorted + { + if(flag[o->topo_res.a[i]>>1] == 0) + { + flag[o->topo_res.a[i]>>1] = (uint64_t)-1; + } + else + { + kv_push(uint32_t, b->b, o->topo_res.a[i]); + } + } + + + /*******************************for debug************************************/ + // for (i = 0; i < cov->n; ++i) + // { + // if(flag[i] != (uint64_t)-1) fprintf(stderr, "ERROR-0\n"); + // } + /*******************************for debug************************************/ +} + +void asg_bub_collect_ovlp(ma_ug_t *ug, uint32_t v0, buf_t *b, utg_trans_t *o) +{ + uint32_t i, uId; + ///b->S.a[0] is the sink of this bubble + if(get_real_length(ug->g, v0, NULL) == 2 && get_real_length(ug->g, b->S.a[0]^1, NULL) == 2) + { + long long tmp, max_stop_nodeLen, max_stop_baseLen, bch_occ[2], len[2]; + uint32_t bch[2], convex[2]; + get_real_length(ug->g, v0, bch); + + ///in rare cases, one side of a bubble might be empty + if((bch[0]>>1)!=(b->S.a[0]>>1) && (bch[1]>>1)!=(b->S.a[0]>>1)) + { + get_unitig(ug->g, NULL, bch[0], &convex[0], &bch_occ[0], &tmp, + &max_stop_nodeLen, &max_stop_baseLen, 1, NULL); + get_unitig(ug->g, NULL, bch[1], &convex[1], &bch_occ[1], &tmp, + &max_stop_nodeLen, &max_stop_baseLen, 1, NULL); + if(((bch_occ[0] + bch_occ[1] + 1) == (uint32_t)b->b.n) && + get_real_length(ug->g, convex[0], NULL) == 1 && get_real_length(ug->g, convex[1], NULL) == 1) + { + get_real_length(ug->g, convex[0], &convex[0]); + get_real_length(ug->g, convex[1], &convex[1]); + if(convex[0] == b->S.a[0] && convex[1] == b->S.a[0]) + { + o->b0.b.n = 0; + get_unitig(ug->g, NULL, bch[0], &convex[0], &bch_occ[0], &len[0], &max_stop_nodeLen, &max_stop_baseLen, 1, &(o->b0)); + o->b1.b.n = 0; + get_unitig(ug->g, NULL, bch[1], &convex[1], &bch_occ[1], &len[1], &max_stop_nodeLen, &max_stop_baseLen, 1, &(o->b1)); + + chain_bubble(&(o->b0), len[0], &(o->b1), len[1], v0, b->S.a[0]^1, ug, o); + return; + } + } + } + } + + tpSort(ug->g, o, v0, b->S.a[0]); + ///if(o->topo_res.n != b->b.n - 1) fprintf(stderr, "ERROR-4\n"); + if(o->topo_res.n == 0) return; + for (i = 0; i < o->topo_res.n; ++i) + { + uId = o->topo_res.a[i]>>1; + if(uId == (b->S.a[0]>>1)) continue; + + dfs_trans_chain(ug->g, o, uId, v0>>1, b->S.a[0]>>1); + + if(o->b0.b.n == 0) continue; + chain_c_bubble(o->topo_res.a[i], &(o->b0), b, ug, o); + } +} + + +void collect_trans_ovlp(const char* cmd, buf_t* pri, uint64_t pri_offset, buf_t* aux, uint64_t aux_offset, +ma_ug_t *ug, utg_trans_t *o) +{ + uint32_t thre_pri; + uint64_t len_aux; + if(pri->b.n == 0 || aux->b.n == 0) return; + + len_aux = set_utg_offset(aux->b.a, aux->b.n, ug, o->read_g, o->pos_idx, 0, 0); + chain_trans_ovlp(NULL, o, ug, o->read_g, pri, len_aux, &thre_pri); + + + if(thre_pri > 0) + { + chain_trans_d(o, pri->b.a, pri->b.n, pri_offset, NULL, aux->b.a, aux->b.n, aux_offset, &len_aux, + ug, RC_1, -1024, __func__); + // fprintf(stderr, "\n%s, thre_pri: %u, len_aux: %lu\n", cmd, thre_pri, len_aux); + // print_buf_t(ug, pri, "pri"); + // print_buf_t(ug, aux, "aux"); + } + set_utg_offset(aux->b.a, aux->b.n, ug, o->read_g, o->pos_idx, 1, 0); +} + + +uint32_t dfs_set(asg_t *g, uint32_t v0, uint32_t fbv, kvec_t_u32_warp *stack, kvec_t_u32_warp *tmp, uint8_t *vis, uint8_t flag) +{ + uint32_t cur, ncur, i, occ = 0;; + asg_arc_t *acur = NULL; + stack->a.n = 0; + kv_push(uint32_t, stack->a, v0); + // vis[v0] = 0; + + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + if(vis[cur] && (!(vis[cur]&flag))) + { + vis[cur] |= flag; + kv_push(uint32_t, tmp->a, cur); + occ++; + } + if(vis[cur]) continue; + else kv_push(uint32_t, tmp->a, cur); + + vis[cur] |= flag; + ncur = asg_arc_n(g, cur); + acur = asg_arc_a(g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if((acur[i].v>>1) == fbv) continue; + if(vis[acur[i].v] && (!(vis[acur[i].v]&flag))) + { + vis[acur[i].v] |= flag; + kv_push(uint32_t, tmp->a, acur[i].v); + occ++; + continue; + } + + kv_push(uint32_t, stack->a, acur[i].v); + } + } + + return occ; +} + + +uint32_t dfs_reach(asg_t *g, uint32_t src, uint32_t dest, kvec_t_u32_warp *stack, kvec_t_u32_warp *tmp, uint8_t *vis) +{ + uint32_t cur, ncur, i, occ = 0;; + asg_arc_t *acur = NULL; + stack->a.n = 0; tmp->a.n = 0; + kv_push(uint32_t, stack->a, src); + + while (stack->a.n > 0) + { + stack->a.n--; + cur = stack->a.a[stack->a.n]; + if(vis[cur]) continue; + else kv_push(uint32_t, tmp->a, cur); + vis[cur] = 1; + if(cur == dest) + { + occ = 1; + break; + } + + + ncur = asg_arc_n(g, cur); + acur = asg_arc_a(g, cur); + for (i = 0; i < ncur; i++) + { + if(acur[i].del) continue; + if(vis[acur[i].v]) continue; + kv_push(uint32_t, stack->a, acur[i].v); + if(acur[i].v == dest) + { + occ = 1; + break; + } + } + if(occ) break; + } + + for (i = 0; i < tmp->a.n; i++) + { + vis[tmp->a.a[i]] = 0; + } + + stack->a.n = 0; tmp->a.n = 0; + return occ; +} + +int is_hap_ovlp(ma_ug_t *ug, asg_t *read_sg, ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, + uint32_t *a, uint32_t a_n, uint32_t *b, uint32_t b_n) +{ + uint32_t i, k, j, qn, tn, is_Unitig, uId, found = 0; + ma_utg_t *u = NULL; + for (i = 0; i < b_n; i++) + { + u = &(ug->u.a[b[i]]); + for (k = 0; k < u->n; k++) + { + qn = (u->a[k]>>33); + set_R_to_U(ruIndex, qn, b[i], 1, NULL); + } + } + + + for (i = 0; i < a_n; i++) + { + u = &(ug->u.a[a[i]]); + for (k = 0; k < u->n; k++) + { + qn = (u->a[k]>>33); + for (j = 0; j < reverse_sources[qn].length; j++) + { + tn = Get_tn(reverse_sources[qn].buffer[j]); + if(read_sg->seq[tn].del == 1) + { + get_R_to_U(ruIndex, tn, &tn, &is_Unitig); + if(tn == (uint32_t)-1 || is_Unitig == 1 || read_sg->seq[tn].del == 1) continue; + } + + get_R_to_U(ruIndex, tn, &uId, &is_Unitig); + if(uId!=(uint32_t)-1 && is_Unitig == 1) + { + found = 1; + break; + } + } + if(found) break; + } + if(found) break; + } + + + + + for (i = 0; i < b_n; i++) + { + u = &(ug->u.a[b[i]]); + for (k = 0; k < u->n; k++) + { + qn = (u->a[k]>>33); + ruIndex->index[qn] = (uint32_t)-1; + } + } + + return found; +} + +uint32_t get_dir_v(uint32_t x, buf_t *b) +{ + uint32_t i; + for (i = 0; i < b->b.n; i++) + { + if((b->b.a[i]>>1) == x) return b->b.a[i]; + } + + return (uint32_t)-1; +} + +int is_pop_unitig(uint32_t v, asg_t *g, ma_ug_t *ug, kvec_t_u32_warp *tt, kvec_t_u32_warp *stack, uint8_t *vis, +pdq *pq_p, pdq *pq_a, uint8_t fp, uint8_t fa, long long *d) +{ + asg_arc_t *as = NULL; + uint32_t s, sv, return_flag, convex, ns, i, k, nc, p_n, found, *a_a = NULL, a_n; + long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; + if(g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) return 0; + if(asg_arc_n(g, v) == 0 || get_real_length(g, v, NULL) != 1) return 0; + get_real_length(g, v, &s); + if(get_real_length(g, s^1, NULL) < 2) return 0; + return_flag = get_unitig(g, ug, v^1, &convex, &ll, &tmp, &max_stop_nodeLen,&max_stop_baseLen, 1, NULL); + if(return_flag == LOOP) return 0; + + as = asg_arc_a(g, convex); ns = asg_arc_n(g, convex); + for (i = nc = 0; i < ns; i++) + { + if(as[i].del) continue; + if(get_real_length(g, as[i].v^1, NULL) < 2) break; + nc++; + } + if(nc == 0 || i < ns) return 0; + + tt->a.n = 0; s^=1; sv = v^1; + dfs_set(g, sv, s>>1, stack, tt, vis, fp); + p_n = tt->a.n; + as = asg_arc_a(g, s); ns = asg_arc_n(g, s); found = 0; + for (i = 0; i < ns; i++) + { + if(as[i].del || as[i].v == sv) continue; + nc = dfs_set(g, as[i].v, s>>1, stack, tt, vis, fa);///nc > 0 means as[i].v and sv have common suffix + if(nc && check_trans_relation_by_path(sv, as[i].v, pq_p, NULL, NULL, pq_a, NULL, NULL, g, + vis, fp+fa, nc, 0.45, d)) + { + found = 1; + } + a_a = tt->a.a + p_n; a_n = tt->a.n - p_n; + for (k = 0; k < a_n; k++) + { + if(vis[a_a[k]]&fa) vis[a_a[k]] -= fa; + } + tt->a.n = p_n; + if(found) break; + } + a_a = tt->a.a; a_n = p_n; + for (k = 0; k < a_n; k++) vis[a_a[k]] = 0; + return found; +} + +static void unitig_iden_worker(void *_data, long eid, int tid) +{ + long long d; + clean_mul_t *buf = (clean_mul_t*)_data; + clean_t *b = &(buf->a[tid]); + if(is_pop_unitig(eid, buf->g, buf->ug, &(b->tt), &(b->stack), b->vis, &(b->pq_p), &(b->pq_a), buf->fp, buf->fa, &d)) + { + if(b->min_v == (uint32_t)-1 || (b->min_d > d) || + (b->min_d == d && buf->g->seq[b->min_v>>1].len > buf->g->seq[eid>>1].len) || + (b->min_d == d && buf->g->seq[b->min_v>>1].len == buf->g->seq[eid>>1].len && b->min_v > eid)) + { + b->min_v = eid; b->min_d = d; + } + } +} + +int is_pop_bub(uint32_t v, asg_t *g, ma_ug_t *ug, buf_t *b, uint64_t max_dist, uint8_t *bs_flag) +{ + bs_flag[v] = 4; + asg_arc_t *av = NULL; + uint32_t nv, i, n_arc; + int occ = 0; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) return occ; + ///some edges could be deleted + for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs + if (!av[i].del) ++n_arc; + if (n_arc < 2) return occ; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, max_dist, b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) + { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + bs_flag[v] = 0; + occ = 1; + } + return occ; +} + +static void bub_iden_worker(void *_data, long eid, int tid) +{ + clean_mul_t *buf = (clean_mul_t*)_data; + clean_t *b = &(buf->a[tid]); + if(is_pop_bub(eid, buf->g, buf->ug, &(b->b), buf->max_dist, buf->bs_flag)) + { + b->is_b = 1; + } +} + +int asg_pop_bubble_primary_trio(asg_t *g, ma_ug_t *ug, uint8_t *bs_flag, buf_t *b, +uint64_t max_dist, uint32_t positive_flag, uint32_t negative_flag, utg_trans_t *o) +{ + uint32_t v, n_vtx = g->n_seq * 2, n_arc, nv, i; + uint64_t n_pop = 0; + asg_arc_t *av = NULL; + + if(max_dist > 0) + { + for (v = 0; v < n_vtx; ++v) + { + if(bs_flag[v] != 0) continue; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + ///some edges could be deleted + for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs + if (!av[i].del) ++n_arc; + if (n_arc < 2) continue; + if(asg_bub_pop1_primary_trio(ug->g, NULL, v, max_dist, b, (uint32_t)-1, (uint32_t)-1, 0, NULL, NULL, NULL, 0, 0, NULL)) + { + //beg is v, end is b.S.a[0] + //note b.b include end, does not include beg + for (i = 0; i < b->b.n; i++) + { + if(b->b.a[i]==v || b->b.a[i]==b->S.a[0]) continue; + bs_flag[b->b.a[i]] = bs_flag[b->b.a[i]^1] = 1; + } + bs_flag[v] = 2; bs_flag[b->S.a[0]^1] = 3; + } + } + + //traverse all node with two directions + for (v = 0; v < n_vtx; ++v) { + if(bs_flag[v] !=2) continue; + nv = asg_arc_n(g, v); + av = asg_arc_a(g, v); + ///some node could be deleted + if (nv < 2 || g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + ///some edges could be deleted + for (i = n_arc = 0; i < nv; ++i) // asg_bub_pop1() may delete some edges/arcs + if (!av[i].del) ++n_arc; + if (n_arc > 1) + n_pop += asg_bub_pop1_primary_trio(ug->g, ug, v, max_dist, b, positive_flag, negative_flag, 1, NULL, NULL, NULL, 0, 0, o); + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] popped %lu bubbles\n", __func__, (unsigned long)n_pop); + } + } + + if (n_pop) asg_cleanup(g); + return n_pop; +} + +int get_min_dec(clean_mul_t *cl, uint32_t positive_flag, uint32_t negative_flag, utg_trans_t *o, uint32_t *v) +{ + uint32_t i, n_pop; + clean_t *p = NULL; + (*v) = (uint32_t)-1; + for (i = 0; i < cl->n; i++) cl->a[i].is_b = 0, cl->a[i].min_v = (uint32_t)-1; + kt_for(cl->n, bub_iden_worker, cl, cl->g->n_seq<<1);///fast check if there are bubbles in graph + for (i = 0; i < cl->n; i++) + { + if(cl->a[i].is_b) ///pop bubble + { + ///pop all bubbles + n_pop = asg_pop_bubble_primary_trio(cl->g, cl->ug, cl->bs_flag, &(cl->a[i].b), + cl->max_dist, positive_flag, negative_flag, o); + if(n_pop ==0) fprintf(stderr, "ERROR-n_pop\n"); + break; + } + } + kt_for(cl->n, unitig_iden_worker, cl, cl->g->n_seq<<1); + for (i = 0; i < cl->n; i++) + { + if(cl->a[i].min_v == (uint32_t)-1) continue; + // if(b->min_v == (uint32_t)-1 || (b->min_d > d) || (b->min_d == d && b->min_v < eid)) + ///looks like select the minum node, and back + if(!p || p->min_d > cl->a[i].min_d || + (p->min_d == cl->a[i].min_d && cl->g->seq[p->min_v>>1].len > cl->g->seq[cl->a[i].min_v>>1].len) || + (p->min_d == cl->a[i].min_d && cl->g->seq[p->min_v>>1].len == cl->g->seq[cl->a[i].min_v>>1].len && p->min_v > cl->a[i].min_v)) + { + p = &(cl->a[i]); + } + } + if(p) (*v) = p->min_v; + return p?1:0; +} + +int asg_arc_decompress_mul(asg_t *g, ma_ug_t *ug, asg_t *read_sg, uint32_t positive_flag, uint32_t negative_flag, +ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, utg_trans_t *o) +{ + double startTime = Get_T(); + asg_arc_t *as = NULL, *pm = NULL; + u_trans_t *kt = NULL; + uint32_t v, s, sv, nc, ns, n_vtx = g->n_seq * 2, n_reduced = 0, convex, pi, qn, tn; + uint32_t return_flag, k, m, i, p_n, a_n, *a_a = NULL; + uint8_t fp = 1, fa = 2, found; + long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; + kvec_t_u32_warp tt; kv_init(tt.a); + kvec_t_u32_warp stack; kv_init(stack.a); + uint8_t *vis = NULL; CALLOC(vis, n_vtx); + buf_t b; + memset(&b, 0, sizeof(buf_t)); + pdq pq_p, pq_a; + init_pdq(&pq_p, g->n_seq<<1); + init_pdq(&pq_a, g->n_seq<<1); + uint32_t *path_p = NULL, *path_q = NULL; + CALLOC(path_p, g->n_seq<<1); + CALLOC(path_q, g->n_seq<<1); + clean_mul_t *cl = init_clean_mul_t(g, ug, asm_opt.thread_num, fp, fa); + + while (get_min_dec(cl, positive_flag, negative_flag, o, &v)) + { + if(g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + if(asg_arc_n(g, v) == 0 || get_real_length(g, v, NULL) != 1) continue; + get_real_length(g, v, &s); + if(get_real_length(g, s^1, NULL) < 2) continue; + return_flag = get_unitig(g, ug, v^1, &convex, &ll, &tmp, &max_stop_nodeLen,&max_stop_baseLen, 1, NULL); + if(return_flag == LOOP) continue; + + as = asg_arc_a(g, convex); ns = asg_arc_n(g, convex); + for (i = nc = 0; i < ns; i++) + { + if(as[i].del) continue; + if(get_real_length(g, as[i].v^1, NULL) < 2) break; + nc++; + } + if(nc == 0 || i < ns) continue; + + tt.a.n = 0; s^=1; sv = v^1; + dfs_set(g, sv, s>>1, &stack, &tt, vis, fp); + p_n = tt.a.n; + as = asg_arc_a(g, s); ns = asg_arc_n(g, s); found = 0; + for (i = 0, pm = NULL; i < ns; i++) + { + if(as[i].del || as[i].v != sv) continue; + pm = &(as[i]); + break; + } + + for (i = 0; i < ns; i++) + { + if(as[i].del || as[i].v == sv) continue; + nc = dfs_set(g, as[i].v, s>>1, &stack, &tt, vis, fa); + if(nc && check_trans_relation_by_path(sv, as[i].v, &pq_p, path_p, &(o->b0), &pq_a, path_q, &(o->b1), g, + vis, fp+fa, nc, 0.45, NULL)) + { + found = 1; + } + a_a = tt.a.a + p_n; a_n = tt.a.n - p_n; + for (k = 0; k < a_n; k++) + { + if(vis[a_a[k]]&fa) vis[a_a[k]] -= fa; + } + tt.a.n = p_n; + if(found) break; + } + a_a = tt.a.a; a_n = p_n; + for (k = 0; k < a_n; k++) vis[a_a[k]] = 0; + + if(found == 0) fprintf(stderr, "ERROR-found\n"); + if(found) + { + b.b.n = 0; + get_unitig(g, ug, sv, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, &b); + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]>>1].c = ALTER_LABLE; + } + + for (k = 0; k < b.b.n; k++) + { + asg_seq_drop(g, b.b.a[k]>>1); + } + + // uint32_t ui; + // fprintf(stderr, "\n"); + // for (ui = 0; ui < o->b0.b.n; ui++) + // { + // fprintf(stderr, "p-utg%.6ul\n", (o->b0.b.a[ui]>>1)+1); + // } + // for (ui = 0; ui < o->b1.b.n; ui++) + // { + // fprintf(stderr, "a-utg%.6ul\n", (o->b1.b.a[ui]>>1)+1); + // } + + + if(o->b0.b.n < b.b.n) fprintf(stderr, "ERROR-ll\n"); + o->b0.b.n = b.b.n; pi = o->k_trans.n; + collect_trans_ovlp(__func__, &(o->b0), pm->ol, &(o->b1), as[i].ol, ug, o); + + for (k = m = pi; k < o->k_trans.n; k++) + { + kt = &(o->k_trans.a[k]); + if(is_hap_ovlp(ug, read_sg, reverse_sources, ruIndex, &(kt->qn), 1, &(kt->tn), 1) || + is_hap_ovlp(ug, read_sg, reverse_sources, ruIndex, &(kt->tn), 1, &(kt->qn), 1)) + { + qn = get_dir_v(kt->qn, &(o->b0)); + tn = get_dir_v(kt->tn, &(o->b1)); + + if(dfs_reach(o->cug->g, qn, tn, &stack, &tt, vis) || dfs_reach(o->cug->g, tn, qn, &stack, &tt, vis)) + { + // fprintf(stderr, "<<<<<qn + 1, kt->qs, kt->qe, kt->tn + 1, kt->ts, kt->te); + continue; + } + + // fprintf(stderr, "q-utg%.6ul (qs: %u, qe: %u), t-utg%.6ul (ts: %u, te: %u)\n", + // kt->qn + 1, kt->qs, kt->qe, kt->tn + 1, kt->ts, kt->te); + o->k_trans.a[m] = *kt; + m++; + } + // else + // { + // fprintf(stderr, "******delete: q-utg%.6ul (qs: %u, qe: %u), t-utg%.6ul (ts: %u, te: %u)\n", + // kt->qn + 1, kt->qs, kt->qe, kt->tn + 1, kt->ts, kt->te); + // } + } + o->k_trans.n = m; + } + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d long tips\n", + __func__, n_reduced); + } + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + asg_cleanup(g); + asg_symm(g); + free(b.b.a); + kv_destroy(tt.a); + kv_destroy(stack.a); + free(vis); + destory_pdq(&pq_p); + destory_pdq(&pq_a); + free(path_p); + free(path_q); + destroy_clean_mul_t(&cl); + return n_reduced; +} + + +int asg_arc_decompress(asg_t *g, ma_ug_t *ug, asg_t *read_sg, ma_hit_t_alloc* reverse_sources, +R_to_U* ruIndex, utg_trans_t *o) +{ + double startTime = Get_T(); + asg_arc_t *as = NULL, *pm = NULL; + u_trans_t *kt = NULL; + uint32_t v, s, sv, nc, ns, n_vtx = g->n_seq * 2, n_reduced = 0, convex, pi, qn, tn; + uint32_t return_flag, k, m, i, p_n, a_n, *a_a = NULL; + uint8_t fp = 1, fa = 2, found; + long long ll, tmp, max_stop_nodeLen, max_stop_baseLen; + kvec_t_u32_warp tt; kv_init(tt.a); + kvec_t_u32_warp stack; kv_init(stack.a); + uint8_t *vis = NULL; CALLOC(vis, n_vtx); + buf_t b; + memset(&b, 0, sizeof(buf_t)); + pdq pq_p, pq_a; + init_pdq(&pq_p, g->n_seq<<1); + init_pdq(&pq_a, g->n_seq<<1); + uint32_t *path_p = NULL, *path_q = NULL; + CALLOC(path_p, g->n_seq<<1); + CALLOC(path_q, g->n_seq<<1); + + for (v = 0; v < n_vtx; v++) + { + if(g->seq[v>>1].del || g->seq[v>>1].c == ALTER_LABLE) continue; + if(asg_arc_n(g, v) == 0 || get_real_length(g, v, NULL) != 1) continue; + get_real_length(g, v, &s); + if(get_real_length(g, s^1, NULL) < 2) continue; + return_flag = get_unitig(g, ug, v^1, &convex, &ll, &tmp, &max_stop_nodeLen,&max_stop_baseLen, 1, NULL); + if(return_flag == LOOP) continue; + + as = asg_arc_a(g, convex); ns = asg_arc_n(g, convex); + for (i = nc = 0; i < ns; i++) + { + if(as[i].del) continue; + if(get_real_length(g, as[i].v^1, NULL) < 2) break; + nc++; + } + if(nc == 0 || i < ns) continue; + + tt.a.n = 0; s^=1; sv = v^1; + dfs_set(g, sv, s>>1, &stack, &tt, vis, fp); + p_n = tt.a.n; + as = asg_arc_a(g, s); ns = asg_arc_n(g, s); found = 0; + for (i = 0, pm = NULL; i < ns; i++) + { + if(as[i].del || as[i].v != sv) continue; + pm = &(as[i]); + break; + } + + for (i = 0; i < ns; i++) + { + if(as[i].del || as[i].v == sv) continue; + nc = dfs_set(g, as[i].v, s>>1, &stack, &tt, vis, fa); + if(nc && check_trans_relation_by_path(sv, as[i].v, &pq_p, path_p, &(o->b0), &pq_a, path_q, &(o->b1), g, + vis, fp+fa, nc, 0.45, NULL)) + { + found = 1; + } + a_a = tt.a.a + p_n; a_n = tt.a.n - p_n; + for (k = 0; k < a_n; k++) + { + if(vis[a_a[k]]&fa) vis[a_a[k]] -= fa; + } + tt.a.n = p_n; + if(found) break; + } + a_a = tt.a.a; a_n = p_n; + for (k = 0; k < a_n; k++) vis[a_a[k]] = 0; + + if(found) + { + b.b.n = 0; + get_unitig(g, ug, sv, &convex, &ll, &tmp, &max_stop_nodeLen, &max_stop_baseLen, 1, &b); + for (k = 0; k < b.b.n; k++) + { + g->seq[b.b.a[k]>>1].c = ALTER_LABLE; + } + + for (k = 0; k < b.b.n; k++) + { + asg_seq_drop(g, b.b.a[k]>>1); + } + + // uint32_t ui; + // fprintf(stderr, "\n"); + // for (ui = 0; ui < o->b0.b.n; ui++) + // { + // fprintf(stderr, "p-utg%.6ul\n", (o->b0.b.a[ui]>>1)+1); + // } + // for (ui = 0; ui < o->b1.b.n; ui++) + // { + // fprintf(stderr, "a-utg%.6ul\n", (o->b1.b.a[ui]>>1)+1); + // } + + + if(o->b0.b.n < b.b.n) fprintf(stderr, "ERROR-ll\n"); + o->b0.b.n = b.b.n; pi = o->k_trans.n; + collect_trans_ovlp(__func__, &(o->b0), pm->ol, &(o->b1), as[i].ol, ug, o); + + for (k = m = pi; k < o->k_trans.n; k++) + { + kt = &(o->k_trans.a[k]); + if(is_hap_ovlp(ug, read_sg, reverse_sources, ruIndex, &(kt->qn), 1, &(kt->tn), 1) || + is_hap_ovlp(ug, read_sg, reverse_sources, ruIndex, &(kt->tn), 1, &(kt->qn), 1)) + { + qn = get_dir_v(kt->qn, &(o->b0)); + tn = get_dir_v(kt->tn, &(o->b1)); + + if(dfs_reach(o->cug->g, qn, tn, &stack, &tt, vis) || dfs_reach(o->cug->g, tn, qn, &stack, &tt, vis)) + { + // fprintf(stderr, "<<<<<qn + 1, kt->qs, kt->qe, kt->tn + 1, kt->ts, kt->te); + continue; + } + + // fprintf(stderr, "q-utg%.6ul (qs: %u, qe: %u), t-utg%.6ul (ts: %u, te: %u)\n", + // kt->qn + 1, kt->qs, kt->qe, kt->tn + 1, kt->ts, kt->te); + o->k_trans.a[m] = *kt; + m++; + } + // else + // { + // fprintf(stderr, "******delete: q-utg%.6ul (qs: %u, qe: %u), t-utg%.6ul (ts: %u, te: %u)\n", + // kt->qn + 1, kt->qs, kt->qe, kt->tn + 1, kt->ts, kt->te); + // } + } + o->k_trans.n = m; + } + } + + if(VERBOSE >= 1) + { + fprintf(stderr, "[M::%s] removed %d long tips\n", + __func__, n_reduced); + fprintf(stderr, "[M::%s] takes %0.2f s\n\n", __func__, Get_T()-startTime); + } + + asg_cleanup(g); + asg_symm(g); + free(b.b.a); + kv_destroy(tt.a); + kv_destroy(stack.a); + free(vis); + destory_pdq(&pq_p); + destory_pdq(&pq_a); + free(path_p); + free(path_q); + return n_reduced; +} + +typedef struct { + uint64_t *idx; + kvec_t(uint64_t) pos; +} mz_ds_t; + +typedef struct { + uint64_t x, y; +} pt128_t; + +typedef struct { + uint64_t x; + uint64_t rid:32, span:32; + uint64_t pos:63, rev:1; +} pt_mz1_t; + +typedef struct { + ///cnt1: how many unique minimizers + ///cnt2: how many non-unique minimizers + uint32_t cnt2, cnt1; + uint32_t m[2]; + int8_t s; +} pt_uinfo_t; + +typedef struct { + uint32_t n_seq; // number of segments; same as gfa_t::n_seg + pt_uinfo_t *info; // of size n_seg + kv_u_trans_t *ma; +} pt_match_t; + +#define mz_key(z) ((z).x) +KRADIX_SORT_INIT(mz, pt_mz1_t, mz_key, 8) + +#define pt128x_key(z) ((z).x) +KRADIX_SORT_INIT(pt128x, pt128_t, pt128x_key, 8) + +#define generic_key(x) (x) +KRADIX_SORT_INIT(tb64, uint64_t, generic_key, 8) + +typedef struct { uint32_t n, m; pt128_t *a; } pt128_v; +typedef struct { uint32_t n, m; pt_mz1_t *a; } pt_mz1_v; + +static inline int mzcmp(const pt_mz1_t *a, const pt_mz1_t *b) +{ + return (a->x > b->x) - (a->x < b->x); +} + +void pt_sketch(const char *str, int len, int w, int k, uint32_t rid, int is_hpc, pt_mz1_v *p) +{ + static const pt_mz1_t dummy = { UINT64_MAX, (1<<28) - 1, 0, 0 }; + uint64_t shift1 = k - 1, mask = (1ULL< 0 && rid < (uint64_t)1<<32 && (w > 0 && w < 256) && (k > 0 && k <= 63)); + + memset(buf, 0xff, w * sizeof(pt_mz1_t)); + memset(&tq, 0, sizeof(tiny_queue_t)); + kv_resize(pt_mz1_t, *p, p->n + len/w); + + for (i = l = buf_pos = min_pos = 0; i < len; ++i) { + int c = seq_nt4_table[(uint8_t)str[i]]; + pt_mz1_t info = dummy; + if (c < 4) { // not an ambiguous base + int z; + if (is_hpc) { + int skip_len = 1; + if (i + 1 < len && seq_nt4_table[(uint8_t)str[i + 1]] == c) { + for (skip_len = 2; i + skip_len < len; ++skip_len) + if (seq_nt4_table[(uint8_t)str[i + skip_len]] != c) + break; + i += skip_len - 1; // put $i at the end of the current homopolymer run + } + tq_push(&tq, skip_len); + kmer_span += skip_len; + if (tq.count > k) kmer_span -= tq_shift(&tq); + } else kmer_span = l + 1 < k? l + 1 : k; + + kmer[0] = (kmer[0] << 1 | (c&1)) & mask; // forward k-mer + kmer[1] = (kmer[1] << 1 | (c>>1)) & mask; + kmer[2] = kmer[2] >> 1 | (uint64_t)(1 - (c&1)) << shift1; // reverse k-mer + kmer[3] = kmer[3] >> 1 | (uint64_t)(1 - (c>>1)) << shift1; + if (kmer[1] == kmer[3]) continue; // skip "symmetric k-mers" as we don't know its strand + z = kmer[1] < kmer[3]? 0 : 1; // strand + ++l; + if (l >= k && kmer_span < 256) { + uint64_t y; + y = yak_hash64_64(kmer[z<<1|0]) + yak_hash64_64(kmer[z<<1|1]); + info.x = y, info.rid = rid, info.pos = i, info.rev = z, info.span = kmer_span; // initially pt_mz1_t::rid keeps the k-mer count + } + } else l = 0, tq.count = tq.front = 0, kmer_span = 0; + + buf[buf_pos] = info; // need to do this here as appropriate buf_pos and buf[buf_pos] are needed below + if (l == w + k - 1 && min.x != UINT64_MAX) { // special case for the first window - because identical k-mers are not stored yet + for (j = buf_pos + 1; j < w; ++j) + if (mzcmp(&min, &buf[j]) == 0 && buf[j].pos != min.pos) kv_push(pt_mz1_t, *p, buf[j]); + for (j = 0; j < buf_pos; ++j) + if (mzcmp(&min, &buf[j]) == 0 && buf[j].pos != min.pos) kv_push(pt_mz1_t, *p, buf[j]); + } + ///three cases: 1. + if (info.x <= min.x) { // a new minimum; then write the old min + if (l >= w + k && min.x != UINT64_MAX) kv_push(pt_mz1_t, *p, min); + min = info, min_pos = buf_pos; + } else if (buf_pos == min_pos) { // old min has moved outside the window + if (l >= w + k - 1 && min.x != UINT64_MAX) kv_push(pt_mz1_t, *p, min); + for (j = buf_pos + 1, min.x = UINT64_MAX; j < w; ++j) // the two loops are necessary when there are identical k-mers + if (mzcmp(&min, &buf[j]) >= 0) min = buf[j], min_pos = j; // >= is important s.t. min is always the closest k-mer + for (j = 0; j <= buf_pos; ++j) + if (mzcmp(&min, &buf[j]) >= 0) min = buf[j], min_pos = j; + + if (l >= w + k - 1 && min.x != UINT64_MAX) { // write identical k-mers + for (j = buf_pos + 1; j < w; ++j) // these two loops make sure the output is sorted + if (mzcmp(&min, &buf[j]) == 0 && min.pos != buf[j].pos) kv_push(pt_mz1_t, *p, buf[j]); + for (j = 0; j <= buf_pos; ++j) + if (mzcmp(&min, &buf[j]) == 0 && min.pos != buf[j].pos) kv_push(pt_mz1_t, *p, buf[j]); + } + } + if (++buf_pos == w) buf_pos = 0; + } + if (min.x != UINT64_MAX) + kv_push(pt_mz1_t, *p, min); +} + +pt_mz1_v *pt_collect_minimizers(ma_ug_t *ug, asg_t *read_g, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, +kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp) +{ + uint32_t i; + pt_mz1_v *mz = NULL; CALLOC(mz, 1); + + for (i = 0; i < ug->u.n; i++) + { + if(!ug->u.a[i].len) continue; + pt_sketch(ug->u.a[i].s, ug->u.a[i].len, asm_opt.mz_win, asm_opt.k_mer_length, i, 0, mz); + } + + radix_sort_mz(mz->a, mz->a + mz->n); + return mz; +} + +pt128_v *pt_collect_anchors(ma_ug_t *ug, pt_mz1_v *mz, mz_ds_t *mz_idx, uint32_t max_occ) +{ + uint32_t st, j; + pt128_v *pa = NULL; CALLOC(pa, 1); + pt128_t *p = NULL; + mz_idx->pos.n = 0; + ///all minimizers + for (j = 1, st = 0; j <= mz->n; ++j) { + if (j == mz->n || mz->a[j].x != mz->a[st].x) { + uint32_t k, l; + // if (j - st == 1) ++info[mz->a[st].rid].cnt1; ///of size n_seg + ///max_occ is the frquency threshold of minimizer + ///if (j - st) == 1, means minimizer only occurs in one read, it is not useful + if (j - st == 1 || j - st > max_occ) goto end_anchor; + for (k = st; k < j; ++k) { + // ++info[mz->a[k].rid].cnt2; + kv_push(uint64_t, mz_idx->pos, (uint64_t)(mz->a[k].rid)<<32|(uint64_t)(mz->a[k].pos)); + for (l = k + 1; l < j; ++l) { + ///k is current minimizer + uint32_t span, rev = (mz->a[k].rev != mz->a[l].rev); + int32_t lk = ug->u.a[mz->a[k].rid].len, ll = ug->u.a[mz->a[l].rid].len; + kv_pushp(pt128_t, *pa, &p); + span = mz->a[l].span; + p->x = (uint64_t)mz->a[k].rid << 33 | mz->a[l].rid << 1 | rev; + p->y = (uint64_t)mz->a[k].pos << 32 | (rev? ll - (mz->a[l].pos + 1 - span) - 1 : mz->a[l].pos); + kv_pushp(pt128_t, *pa, &p); + span = mz->a[k].span; + p->x = (uint64_t)mz->a[l].rid << 33 | mz->a[k].rid << 1 | rev; + p->y = (uint64_t)mz->a[l].pos << 32 | (rev? lk - (mz->a[k].pos + 1 - span) - 1 : mz->a[k].pos); + } + } + end_anchor: st = j; + } + } + + radix_sort_pt128x(pa->a, pa->a + pa->n); + + radix_sort_tb64(mz_idx->pos.a, mz_idx->pos.a + mz_idx->pos.n); + CALLOC(mz_idx->idx, ug->u.n); + for (st = 0, j = 1; j <= mz_idx->pos.n; ++j) + { + if (j == mz_idx->pos.n || (mz_idx->pos.a[j]>>32) != (mz_idx->pos.a[st]>>32)) + { + mz_idx->idx[mz_idx->pos.a[st]>>32] = (uint64_t)st << 32 | (j - st), st = j; + } + } + + return pa; +} + +int32_t pt_lis_64(int32_t n, const uint64_t *a_idx, int32_t *b, int32_t *M) +{ + int32_t i, k, L = 0, *P = b; + // MALLOC(M, n+1); + for (i = 0; i < n; ++i) { + int32_t lo = 1, hi = L, newL; + while (lo <= hi) { + int32_t mid = (lo + hi + 1) >> 1; + if ((uint32_t)a_idx[M[mid]] < (uint32_t)a_idx[i]) lo = mid + 1; + else hi = mid - 1; + } + newL = lo, P[i] = M[newL - 1], M[newL] = i; + if (newL > L) L = newL; + } + k = M[L]; + memcpy(M, P, n * sizeof(int32_t)); + for (i = L - 1; i >= 0; --i) b[i] = k, k = M[k]; + // free(M); + return L; +} + +uint32_t debug_lis_64(const uint64_t *a, int32_t *b, uint64_t n) +{ + uint32_t i; + if(n <= 1) return 1; + for (i = 0; i+1 < n; i++) + { + if(((a[b[i]]>>32) > (a[b[i+1]]>>32)) || (((uint32_t)a[b[i]]) > ((uint32_t)a[b[i+1]]))) + { + i = (uint32_t)-1; + break; + } + } + if(i == (uint32_t)-1) + { + fprintf(stderr, "\nERROR-chain\n"); + for (i = 0; i < n; i++) + { + fprintf(stderr, "x-%lu, y-%lu\n", (a[b[i]]>>32), (uint64_t)((uint32_t)a[b[i]])); + } + } + return 1; +} + +void update_mz_ovlp(uint32_t* n_x_beg, uint32_t* n_x_end, int64_t xLen, +uint32_t* n_y_beg, uint32_t* n_y_end, int64_t yLen, uint32_t rev) +{ + int64_t x_beg = (*n_x_beg), x_end = (*n_x_end); + int64_t y_beg = (*n_y_beg), y_end = (*n_y_end); + if(x_beg <= y_beg) + { + y_beg = y_beg - x_beg; + x_beg = 0; + } + else + { + x_beg = x_beg - y_beg; + y_beg = 0; + } + + long long x_right_length = xLen - x_end - 1; + long long y_right_length = yLen - y_end - 1; + + + if(x_right_length <= y_right_length) + { + x_end = xLen - 1; + y_end = y_end + x_right_length; + } + else + { + x_end = x_end + y_right_length; + y_end = yLen - 1; + } + + if(rev == 0) + { + (*n_y_beg) = y_beg; + (*n_y_end) = y_end + 1; + } + else + { + (*n_y_beg) = yLen - y_end - 1; + (*n_y_end) = yLen - y_beg - 1 + 1; + } + + (*n_x_beg) = x_beg; + (*n_x_end) = x_end + 1; +} + +int64_t get_insert_pos(uint64_t *a, int64_t n, int64_t target) +{ + int64_t left, right, ans, mid; + left = 0; right = n - 1; ans = n; + while (left <= right) { + mid = ((right - left) >> 1) + left; + if (target <= (uint32_t)a[mid]) { + ans = mid; + right = mid - 1; + } else { + left = mid + 1; + } + } + return ans; +} + +uint32_t get_mz_occ(mz_ds_t *mz_idx, uint64_t uid, uint64_t s, uint64_t e) +{ + uint64_t *a = mz_idx->pos.a + (mz_idx->idx[uid]>>32), n = (uint32_t)(mz_idx->idx[uid]); + if(n == 0) return 0; + int64_t sid, eid; + sid = get_insert_pos(a, n, s); + eid = get_insert_pos(a, n, e); + return eid + 1 - sid; +} + +kv_u_trans_t *pt_cal_sim(pt128_v *pa, mz_ds_t *mz_idx, ma_ug_t *ug, uint32_t min_cnt, double min_sim) +{ + int64_t st, i, j; + kvec_t(uint64_t) a; kv_init(a); + kvec_t(int32_t) b; kv_init(b); + kvec_t(int32_t) M; kv_init(M); + kv_u_trans_t *ma = NULL; CALLOC(ma, 1); + u_trans_t m; + ///x = (uint64_t)mz[l].rid << 33 | mz[k].rid << 1 | rev; + for (st = 0, i = 1; i <= pa->n; ++i) { + if (i == pa->n || pa->a[i].x != pa->a[st].x) {///minimizers between a pair of unitigs + if((pa->a[st].x>>33) == (((uint32_t)pa->a[st].x)>>1)) goto end_chain; + uint32_t nn[2], nn_min; + a.n = 0; memset(&m, 0, sizeof(m)); + if (i - st < min_cnt) goto end_chain; + //(uint64_t)mz[l].pos << 32 | (rev? lk - (mz[k].pos + 1 - span) - 1 : mz[k].pos); + for (j = st; j < i; ++j) kv_push(uint64_t, a, pa->a[j].y); + radix_sort_tb64(a.a, a.a + a.n);///sort by query pos + target pos + // for (l = 0; l < a.n; ++l) a.a[l] = (uint32_t)a.a[l];///only need target pos to do LIS + kv_resize(int32_t, b, a.n); kv_resize(int32_t, M, a.n+1); + m.occ = pt_lis_64(a.n, a.a, b.a, M.a); + /*******************************for debug************************************/ + // debug_lis_64(a.a, b.a, m.occ); + /*******************************for debug************************************/ + if (m.occ == 0 || m.occ < min_cnt) goto end_chain;//chain occ + m.qn = pa->a[st].x >> 33;///query id + m.tn = ((uint32_t)pa->a[st].x) >> 1;///target id + if (m.qn == m.tn) goto end_chain; + m.qs = a.a[b.a[0]]>>32; m.qe = a.a[b.a[m.occ-1]]>>32; + m.ts = (uint32_t)(a.a[b.a[0]]); m.te = (uint32_t)(a.a[b.a[m.occ-1]]); + m.rev = (pa->a[st].x>>32&1) ^ (pa->a[st].x&1); + update_mz_ovlp(&(m.qs), &(m.qe), ug->u.a[m.qn].len, &(m.ts), &(m.te), ug->u.a[m.tn].len, m.rev); + + nn[0] = get_mz_occ(mz_idx, m.qn, m.qs, m.qe-1); + nn[1] = get_mz_occ(mz_idx, m.tn, m.ts, m.te-1); + nn_min = MIN(nn[0], nn[1]); + nn_min = MAX(nn_min, m.occ); + // m.sim = pow(2.0 * m.m / (nn[0] + nn[1]), 1.0 / k); + if(m.occ >= nn_min*min_sim){ + m.nw = (double)(m.occ) - (double)(nn_min-m.occ)*0.2; + if(m.nw > 0) kv_push(u_trans_t, *ma, m); + } + end_chain: st = i; + } + } + kv_destroy(b); kv_destroy(a); kv_destroy(M); + return ma; +} + +void clean_mz_ovlp(kv_u_trans_t *ta, ma_ug_t *ug) +{ + u_trans_t *a = NULL; + asg_arc_t *as = NULL; + uint32_t k, i, n, v, ns; + pdq pq; init_pdq(&pq, ug->g->n_seq<<1); + uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq); + kvec_t_u32_warp p; kv_init(p.a); + for (k = 0; k < ta->idx.n; k++) + { + p.a.n = 0; + a = u_trans_a(*ta, k); + n = u_trans_n(*ta, k); + if(n == 0) continue; + + v = k<<1; + as = asg_arc_a(ug->g, v); ns = asg_arc_n(ug->g, v); + if(ns > 0) + { + for (i = 0; i < ns; i++) + { + if(as[i].del) continue; + kv_push(uint32_t, p.a, as[i].v); + } + set_utg_by_dis(v, &pq, ug->g, &p, ug->g->seq[v>>1].len); + } + + + v = (k<<1) + 1; + as = asg_arc_a(ug->g, v); ns = asg_arc_n(ug->g, v); + if(ns > 0) + { + for (i = 0; i < ns; i++) + { + if(as[i].del) continue; + kv_push(uint32_t, p.a, as[i].v); + } + set_utg_by_dis(v, &pq, ug->g, &p, ug->g->seq[v>>1].len); + } + + for (i = 0; i < p.a.n; i++) vis[p.a.a[i]>>1] = 1; + + for (i = 0; i < n; i++) + { + if(vis[a[i].tn]) a[i].del = 1; + } + + for (i = 0; i < p.a.n; i++) vis[p.a.a[i]>>1] = 0; + } + destory_pdq(&pq); + kv_destroy(p.a); + free(vis); + + for (k = n = 0; k < ta->n; ++k) + { + if(ta->a[k].del) continue; + ta->a[n] = ta->a[k]; + n++; + } + ta->n = n; + kt_u_trans_t_idx(ta, ug->g->n_seq); + kt_u_trans_t_simple_symm(ta, ug->g->n_seq, 0); +} + +int cmp_u_trans_nw(const void * a, const void * b) +{ + if((*(u_trans_t*)a).nw == (*(u_trans_t*)b).nw) return 0; + return (*(u_trans_t*)a).nw < (*(u_trans_t*)b).nw ? 1 : -1; +} + +/** +void flat_mz_ovlp(kv_u_trans_t *ta, ma_ug_t *ug, asg_t *read_g, ma_sub_t* coverage_cut, +ma_hit_t_alloc* sources, R_to_U* ruIndex, uint32_t min_cnt, uint32_t cov_thres, +double cov_pass_rate, double nw_pass_rate) +{ + u_trans_t *a = NULL, *p = NULL; + uint8_t *vis = NULL; CALLOC(vis, ug->g->n_seq); + uint32_t *cov = NULL; CALLOC(cov, ug->g->n_seq); + kvec_t(uint32_t) tc; kv_init(tc); + uint32_t k, i, j, n, v, ns, qs, qe, occ, hapN, pass; + double w; + for (i = 0; i < ug->u.n; i++) + { + cov[i] = get_utg_cov(ug, i, read_g, coverage_cut, sources, ruIndex, vis); + } + + for (k = 0; k < ta->idx.n; k++) + { + a = u_trans_a(*ta, k); + n = u_trans_n(*ta, k); + if(n == 0) continue; + qsort(a, n, sizeof(u_trans_t), cmp_u_trans_nw); + kv_resize(uint32_t, tc, ug->u.a[k].len); + tc.n = ug->u.a[k].len; + memset(tc.a, 0, tc.n*sizeof(uint32_t)); + for (i = 0, p = NULL; i < n; i++) + { + qs = a[i].qs; qe = a[i].qe; w = a[i].nw; occ = a[i].occ; pass = 0; + for (j = qs; j < qe; j++) + { + if(tc.a[j] + cov[k] >= cov_thres) pass++; + } + if(pass > cov_pass_rate*(qe - qs)) + { + if(p && nw_pass_rate*) a[i].del = 1; + } + else + { + for (j = qs; j < qe; j++) tc.a[j] += cov[k]; + } + } + } + free(vis); free(cov); kv_destroy(tc); +} +**/ + + +void print_u_trans(kv_u_trans_t *ta) +{ + uint32_t i; + u_trans_t *p = NULL; + for (i = 0; i < ta->n; i++) + { + p = &(ta->a[i]); + fprintf(stderr, "q-utg%.6ul\tqs(%u)\tqe(%u)\tt-utg%.6ul\tts(%u)\tte(%u)\trev(%u)\tw(%f)\tf(%u)\n", + p->qn+1, p->qs, p->qe, p->tn+1, p->ts, p->te, p->rev, p->nw, p->f); + } + fprintf(stderr, "[M::%s::] \n", __func__); +} + +kv_u_trans_t *pt_pdist(ma_ug_t *ug, asg_t *read_g, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, +kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, uint32_t min_chain_cnt) +{ + pt_mz1_v *mz = NULL; + mz_ds_t mz_idx; memset(&mz_idx, 0, sizeof(mz_idx)); + pt128_v *an = NULL; + kv_u_trans_t *ma = NULL; CALLOC(ma, 1); + mz = pt_collect_minimizers(ug, read_g, coverage_cut, sources, edge, max_hang, min_ovlp); + an = pt_collect_anchors(ug, mz, &mz_idx, asm_opt.polyploidy*10); + kv_destroy(*mz); free(mz); + + ma = pt_cal_sim(an, &mz_idx, ug, min_chain_cnt, asm_opt.purge_simi_thres); + kv_destroy(*an); free(an); + kv_destroy(mz_idx.pos); free(mz_idx.idx); + + kt_u_trans_t_idx(ma, ug->g->n_seq); + kt_u_trans_t_simple_symm(ma, ug->g->n_seq, 1); + clean_mz_ovlp(ma, ug); + // print_u_trans(ma); + // exit(1); + return ma; } \ No newline at end of file diff --git a/tovlp.h b/tovlp.h index f009fe4..bc1e63f 100644 --- a/tovlp.h +++ b/tovlp.h @@ -1,28 +1,28 @@ -#ifndef __TOVLP__ -#define __TOVLP__ - -#define __STDC_LIMIT_MACROS -#include -#include "Overlaps.h" - -typedef struct {///[cBeg, cEnd) - uint32_t ui, len, cBeg, cEnd; - uint32_t *a, an; - ma_ug_t *ug; - utg_trans_t *o; -} utg_trans_hit_idx; - -utg_trans_t *init_utg_trans_t(ma_ug_t *ug, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, asg_t *read_g, int max_hang, int min_ovlp); -void destroy_utg_trans_t(utg_trans_t **o); -void asg_bub_collect_ovlp(ma_ug_t *ug, uint32_t v0, buf_t *b, utg_trans_t *o); -void collect_trans_ovlp(const char* cmd, buf_t* pri, uint64_t pri_offset, buf_t* aux, uint64_t aux_offset, -ma_ug_t *ug, utg_trans_t *o); -int asg_arc_decompress(asg_t *g, ma_ug_t *ug, asg_t *read_sg, ma_hit_t_alloc* reverse_sources, -R_to_U* ruIndex, utg_trans_t *o); -int asg_arc_decompress_mul(asg_t *g, ma_ug_t *ug, asg_t *read_sg, uint32_t positive_flag, uint32_t negative_flag, -ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, utg_trans_t *o); -kv_u_trans_t *pt_pdist(ma_ug_t *ug, asg_t *read_g, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, -kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, uint32_t min_chain_cnt); -void reset_utg_trans_hit_idx(utg_trans_hit_idx *t, uint32_t* i_x_a, uint32_t i_x_n, ma_ug_t *i_ug, -utg_trans_t *i_o, uint32_t i_cBeg, uint32_t i_cEnd); -#endif +#ifndef __TOVLP__ +#define __TOVLP__ + +#define __STDC_LIMIT_MACROS +#include +#include "Overlaps.h" + +typedef struct {///[cBeg, cEnd) + uint32_t ui, len, cBeg, cEnd; + uint32_t *a, an; + ma_ug_t *ug; + utg_trans_t *o; +} utg_trans_hit_idx; + +utg_trans_t *init_utg_trans_t(ma_ug_t *ug, ma_hit_t_alloc* reverse_sources, ma_sub_t *coverage_cut, R_to_U* ruIndex, asg_t *read_g, int max_hang, int min_ovlp); +void destroy_utg_trans_t(utg_trans_t **o); +void asg_bub_collect_ovlp(ma_ug_t *ug, uint32_t v0, buf_t *b, utg_trans_t *o); +void collect_trans_ovlp(const char* cmd, buf_t* pri, uint64_t pri_offset, buf_t* aux, uint64_t aux_offset, +ma_ug_t *ug, utg_trans_t *o); +int asg_arc_decompress(asg_t *g, ma_ug_t *ug, asg_t *read_sg, ma_hit_t_alloc* reverse_sources, +R_to_U* ruIndex, utg_trans_t *o); +int asg_arc_decompress_mul(asg_t *g, ma_ug_t *ug, asg_t *read_sg, uint32_t positive_flag, uint32_t negative_flag, +ma_hit_t_alloc* reverse_sources, R_to_U* ruIndex, utg_trans_t *o); +kv_u_trans_t *pt_pdist(ma_ug_t *ug, asg_t *read_g, ma_sub_t *coverage_cut, ma_hit_t_alloc* sources, +kvec_asg_arc_t_warp* edge, int max_hang, int min_ovlp, uint32_t min_chain_cnt); +void reset_utg_trans_hit_idx(utg_trans_hit_idx *t, uint32_t* i_x_a, uint32_t i_x_n, ma_ug_t *i_ug, +utg_trans_t *i_o, uint32_t i_cBeg, uint32_t i_cEnd); +#endif